commit bea333e6cc0878da6e04aa33cfde1dbda6592ce4 Author: 8402134 <8402134@qq.com> Date: Tue Sep 20 11:10:29 2022 +0800 1 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e90a366 --- /dev/null +++ b/.gitignore @@ -0,0 +1,374 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd +/packages +加密处理 +加密处理 +jiami +WXRobot2.8Demo +Coco.Framework +Help +Members +Coco.Framework +/ProductTool +ProductTool diff --git a/Chat.Packet/PackCMD.cs b/Chat.Packet/PackCMD.cs new file mode 100644 index 0000000..177f290 --- /dev/null +++ b/Chat.Packet/PackCMD.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Packet +{ + ///// + ///// 客户端 - CMD命令 + ///// + //public enum : int + //{ + // 登陆成功Wechat = 1000, + // 收到消息Wechat = 1001, + // 收到通讯录Wechat = 1002, + // 收到客户端Wechat = 1003 + //} + + /// + /// 服务器 - CMD命令 + /// + public enum PackCMD : int + { + Wechat发送消息 = 100001, + + + Wechat刷新客户端 = 200001, + Wechat刷新通讯录 = 200002 , + Wechat收到消息 = 200003 + } +} diff --git a/Chat.Packet/PacketData.cs b/Chat.Packet/PacketData.cs new file mode 100644 index 0000000..6e701c8 --- /dev/null +++ b/Chat.Packet/PacketData.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Threading.Tasks; +using CsharpHttpHelper; +namespace Chat.Packet +{ + public class PacketData + { + public PacketData() { } + + public PackCMD Cmd { get; set; } + public string FromUser { get; set; } + + public object Data { get; set; } + public PacketData(PackCMD cmd) + { + this.Cmd = cmd; + } + + public PacketData(PackCMD cmd, object data) : this(cmd) + { + this.Data = data; + } + + private byte[] _body; + public byte[] EncData(string key) + { + if (_body != null) return _body; + try + { + string aes_data = string.Empty; + var _json = HttpHelper.ObjectToJson(Data); + if (_json != null) + { + var aes = new AESCryption(); + aes_data = aes.AesEncrypt(_json, key); + } + string need = (int)Cmd + " " + aes_data + "\r\n"; + _body = Encoding.UTF8.GetBytes(need); + + } + catch (Exception) + { + } + return _body; + } + + + + + } +} diff --git a/Chat.Packet/Packts/MessagePack.cs b/Chat.Packet/Packts/MessagePack.cs new file mode 100644 index 0000000..389eddc --- /dev/null +++ b/Chat.Packet/Packts/MessagePack.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Packet.Packts +{ + public class MessagePack :PacketData + { + + /// + /// 是群消息 + /// + public string ToUsername { get; set; } + + /// + ///发送给谁 + /// + public string ToUsernick { get; set; } + + /// + /// 群号 + /// + public string ToGroupid { get; set; } + + /// + /// 群名称 + /// + public string ToGroupname { get; set; } + + /// + /// 消息正文 + /// + public string Message { get; set; } + + /// + /// At某成员 + /// + public string AtUsername { get; set; } + } +} diff --git a/Chat.Packet/Properties/AssemblyInfo.cs b/Chat.Packet/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..dbb69b6 --- /dev/null +++ b/Chat.Packet/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Chat.Packet")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Chat.Packet")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("1bddba09-c420-4897-8e8c-3625f2eec154")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Chat.Packet/RobotType.cs b/Chat.Packet/RobotType.cs new file mode 100644 index 0000000..3c03818 --- /dev/null +++ b/Chat.Packet/RobotType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Packet +{ + public enum RobotType:int + { + 微信 = 1 + } +} diff --git a/DLL/AdvancedStringBuilder.dll b/DLL/AdvancedStringBuilder.dll new file mode 100644 index 0000000..2449326 Binary files /dev/null and b/DLL/AdvancedStringBuilder.dll differ diff --git a/DLL/CefSharp.BrowserSubprocess.Core.dll b/DLL/CefSharp.BrowserSubprocess.Core.dll new file mode 100644 index 0000000..eb7736f Binary files /dev/null and b/DLL/CefSharp.BrowserSubprocess.Core.dll differ diff --git a/DLL/CefSharp.BrowserSubprocess.exe b/DLL/CefSharp.BrowserSubprocess.exe new file mode 100644 index 0000000..bd51166 Binary files /dev/null and b/DLL/CefSharp.BrowserSubprocess.exe differ diff --git a/DLL/CefSharp.Core.Runtime.dll b/DLL/CefSharp.Core.Runtime.dll new file mode 100644 index 0000000..f8dc180 Binary files /dev/null and b/DLL/CefSharp.Core.Runtime.dll differ diff --git a/DLL/CefSharp.Core.Runtime.xml b/DLL/CefSharp.Core.Runtime.xml new file mode 100644 index 0000000..069e089 --- /dev/null +++ b/DLL/CefSharp.Core.Runtime.xml @@ -0,0 +1,1584 @@ + + + + "CefSharp.Core.Runtime" + + + + +Returns true if the underlying POST data includes elements that are not +represented by this IPostData object (for example, multi-part file upload +data). Modifying IPostData objects with excluded elements may result in +the request failing. + + + + +Create a new instance + + PostDataElement + + + +Remove all existing post data elements. + + + + +Remove the specified . + + element to be removed. + Returns true if the add succeeds. + + + +Add the specified . + + element to be added. + Returns true if the add succeeds. + + + +Retrieve the post data elements. + + + + +Returns true if this object is read-only. + + + + +Default constructor. + + + + +Throw exception if Readonly + + Thrown when an exception error condition occurs. + + + +Destructor. + + + + +Finalizer. + + + + +Form Post Data + + + + + +Constructor. + + The popup features. + + + +Class representing popup window features. + + + + + + + + +Helper method to ensure all ChromiumWebBrowser instances have been +closed/disposed, should be called before Cef.Shutdown. +Disposes all remaning ChromiumWebBrowser instances +then waits for CEF to release it's remaning CefBrowser instances. +Finally a small delay of 50ms to allow for CEF to finish it's cleanup. +Should only be called when MultiThreadedMessageLoop = true; +(Hasn't been tested when when CEF integrates into main message loop). + + + + +WaitForBrowsersToClose is not enabled by default, call this method +before Cef.Initialize to enable. If you aren't calling Cef.Initialize +explicitly then this should be called before creating your first +ChromiumWebBrowser instance. + + + + +Returns the mime type for the specified file extension or an empty string if unknown. + + file extension + Returns the mime type for the specified file extension or an empty string if unknown. + + + +Register the Widevine CDM plugin. + +See for more details. + + is a directory that contains the Widevine CDM files + Returns a Task that can be awaited to receive the response. + + + +Register the Widevine CDM plugin. + +The client application is responsible for downloading an appropriate +platform-specific CDM binary distribution from Google, extracting the +contents, and building the required directory structure on the local machine. +The method class can be used +to implement this functionality in CefSharp. Contact Google via +https://www.widevine.com/contact.html for details on CDM download. + + +path is a directory that must contain the following files: + 1. manifest.json file from the CDM binary distribution (see below). + 2. widevinecdm file from the CDM binary distribution (e.g. + widevinecdm.dll on Windows). + 3. widevidecdmadapter file from the CEF binary distribution (e.g. + widevinecdmadapter.dll on Windows). + +If any of these files are missing or if the manifest file has incorrect +contents the registration will fail and callback will receive an ErrorCode +value of . + +The manifest.json file must contain the following keys: + A. "os": Supported OS (e.g. "mac", "win" or "linux"). + B. "arch": Supported architecture (e.g. "ia32" or "x64"). + C. "x-cdm-module-versions": Module API version (e.g. "4"). + D. "x-cdm-interface-versions": Interface API version (e.g. "8"). + E. "x-cdm-host-versions": Host API version (e.g. "8"). + F. "version": CDM version (e.g. "1.4.8.903"). + G. "x-cdm-codecs": List of supported codecs (e.g. "vp8,vp9.0,avc1"). + +A through E are used to verify compatibility with the current Chromium +version. If the CDM is not compatible the registration will fail and +callback will receive an ErrorCode value of . + +If registration is not supported at the time that Cef.RegisterWidevineCdm() is called then callback +will receive an ErrorCode value of . + + is a directory that contains the Widevine CDM files + optional callback - +will be executed asynchronously once registration is complete + + + +Sets or clears a specific key-value pair from the crash metadata. + + + + +Crash reporting is configured using an INI-style config file named +crash_reporter.cfg. This file must be placed next to +the main application executable. File contents are as follows: + + # Comments start with a hash character and must be on their own line. + + [Config] + ProductName=<Value of the "prod" crash key; defaults to "cef"> + ProductVersion=<Value of the "ver" crash key; defaults to the CEF version> + AppName=<Windows only; App-specific folder name component for storing crash + information; default to "CEF"> + ExternalHandler=<Windows only; Name of the external handler exe to use + instead of re-launching the main exe; default to empty> + ServerURL=<crash server URL; default to empty> + RateLimitEnabled=<True if uploads should be rate limited; default to true> + MaxUploadsPerDay=<Max uploads per 24 hours, used if rate limit is enabled; + default to 5> + MaxDatabaseSizeInMb=<Total crash report disk usage greater than this value + will cause older reports to be deleted; default to 20> + MaxDatabaseAgeInDays=<Crash reports older than this value will be deleted; + default to 5> + + [CrashKeys] + my_key1=<small|medium|large> + my_key2=<small|medium|large> + +Config section: + +If "ProductName" and/or "ProductVersion" are set then the specified values +will be included in the crash dump metadata. + +If "AppName" is set on Windows then crash report information (metrics, +database and dumps) will be stored locally on disk under the +"C:\Users\[CurrentUser]\AppData\Local\[AppName]\User Data" folder. + +If "ExternalHandler" is set on Windows then the specified exe will be +launched as the crashpad-handler instead of re-launching the main process +exe. The value can be an absolute path or a path relative to the main exe +directory. + +If "ServerURL" is set then crashes will be uploaded as a multi-part POST +request to the specified URL. Otherwise, reports will only be stored locally +on disk. + +If "RateLimitEnabled" is set to true then crash report uploads will be rate +limited as follows: + 1. If "MaxUploadsPerDay" is set to a positive value then at most the + specified number of crashes will be uploaded in each 24 hour period. + 2. If crash upload fails due to a network or server error then an + incremental backoff delay up to a maximum of 24 hours will be applied for + retries. + 3. If a backoff delay is applied and "MaxUploadsPerDay" is > 1 then the + "MaxUploadsPerDay" value will be reduced to 1 until the client is + restarted. This helps to avoid an upload flood when the network or + server error is resolved. + +If "MaxDatabaseSizeInMb" is set to a positive value then crash report storage +on disk will be limited to that size in megabytes. For example, on Windows +each dump is about 600KB so a "MaxDatabaseSizeInMb" value of 20 equates to +about 34 crash reports stored on disk. + +If "MaxDatabaseAgeInDays" is set to a positive value then crash reports older +than the specified age in days will be deleted. + +CrashKeys section: + +Any number of crash keys can be specified for use by the application. Crash +key values will be truncated based on the specified size (small = 63 bytes, +medium = 252 bytes, large = 1008 bytes). The value of crash keys can be set +from any thread or process using the Cef.SetCrashKeyValue function. These +key/value pairs will be sent to the crash server along with the crash dump +file. Medium and large values will be chunked for submission. For example, +if your key is named "mykey" then the value will be broken into ordered +chunks and submitted using keys named "mykey-1", "mykey-2", etc. + + Returns true if crash reporting is enabled. + + + +Helper function (wrapper around the CefColorSetARGB macro) which combines +the 4 color components into an uint32 for use with BackgroundColor property + + Alpha + Red + Green + Blue + Returns the color. + + + +Gets the Global Request Context. Make sure to Dispose of this object when finished. +The earlier possible place to access the IRequestContext is in IBrowserProcessHandler.OnContextInitialized. +Alternative use the ChromiumWebBrowser BrowserInitialized (OffScreen) or IsBrowserInitializedChanged (WinForms/WPF) events. + + Returns the global request context or null if the RequestContext has not been initialized yet. + + + +Returns true if called on the specified CEF thread. + + Returns true if called on the specified thread. + + + +Call during process startup to enable High-DPI support on Windows 7 or newer. +Older versions of Windows should be left DPI-unaware because they do not +support DirectWrite and GDI fonts are kerned very badly. + + + + +Unregister an internal plugin. This may be undone the next time RefreshWebPlugins() is called. + + Path (directory + file). + + + +Cause the plugin list to refresh the next time it is accessed regardless of whether it has already been loaded. + + + + +Async returns a list containing Plugin Information +(Wrapper around CefVisitWebPluginInfo) + + Returns List of structs. + + + +Visit web plugin information. Can be called on any thread in the browser process. + + + + +Clear all scheme handler factories registered with the global request context. +Returns false on error. This function may be called on any thread in the browser process. +Using this function is equivalent to calling Cef.GetGlobalRequestContext().ClearSchemeHandlerFactories(). + + Returns false on error. + + + +This method should only be used by advanced users, if you're unsure then use Cef.Shutdown(). +This function should be called on the main application thread to shut down +the CEF browser process before the application exits. This method simply obtains a lock +and calls the native CefShutdown method, only IsInitialized is checked. All ChromiumWebBrowser +instances MUST be Disposed of before calling this method. If calling this method results in a crash +or hangs then you're likely hanging on to some unmanaged resources or haven't closed all of your browser +instances + + + + +Shuts down CefSharp and the underlying CEF infrastructure. This method is safe to call multiple times; it will only +shut down CEF on the first call (all subsequent calls will be ignored). +This method should be called on the main application thread to shut down the CEF browser process before the application exits. +If you are Using CefSharp.OffScreen then you must call this explicitly before your application exits or it will hang. +This method must be called on the same thread as Initialize. If you don't call Shutdown explicitly then CefSharp.Wpf and CefSharp.WinForms +versions will do their best to call Shutdown for you, if your application is having trouble closing then call thus explicitly. + + + + +Called prior to calling Cef.Shutdown, this diposes of any remaning +ChromiumWebBrowser instances. In WPF this is used from Dispatcher.ShutdownStarted +to release the unmanaged resources held by the ChromiumWebBrowser instances. +Generally speaking you don't need to call this yourself. + + + + +Returns the global cookie manager. By default data will be stored at CefSettings.CachePath if specified or in memory otherwise. +Using this method is equivalent to calling Cef.GetGlobalRequestContext().GetCookieManager() +The cookie managers storage is created in an async fashion, whilst this method may return a cookie manager instance, +there may be a short delay before you can Get/Write cookies. +To be sure the cookie manager has been initialized use one of the following +- Access the ICookieManager after ICompletionCallback.OnComplete has been called +- Access the ICookieManager instance in IBrowserProcessHandler.OnContextInitialized. +- Use the ChromiumWebBrowser BrowserInitialized (OffScreen) or IsBrowserInitializedChanged (WinForms/WPF) events. + + If non-NULL it will be executed asnychronously on the CEF UI thread after the manager's storage has been initialized. + A the global cookie manager or null if the RequestContext has not yet been initialized. + + + +Returns the global cookie manager. By default data will be stored at CefSettings.CachePath if specified or in memory otherwise. +Using this method is equivalent to calling Cef.GetGlobalRequestContext().GetCookieManager() +The cookie managers storage is created in an async fashion, whilst this method may return a cookie manager instance, +there may be a short delay before you can Get/Write cookies. +To be sure the cookie manager has been initialized use one of the following +- Use the GetGlobalCookieManager(ICompletionCallback) overload and access the ICookieManager after + ICompletionCallback.OnComplete has been called. +- Access the ICookieManager instance in IBrowserProcessHandler.OnContextInitialized. +- Use the ChromiumWebBrowser BrowserInitialized (OffScreen) or IsBrowserInitializedChanged (WinForms/WPF) events. + + A the global cookie manager or null if the RequestContext has not yet been initialized. + + + Remove all entries from the cross-origin access whitelist. + +Remove all entries from the cross-origin access whitelist. Returns false if +the whitelist cannot be accessed. + + + + Remove entry from cross-origin whitelist + The origin allowed to be accessed by the target protocol/domain. + The target protocol allowed to access the source origin. + The optional target domain allowed to access the source origin. + If set to true would allow a blah.example.com if the + was set to example.com + + +Remove an entry from the cross-origin access whitelist. Returns false if + is invalid or the whitelist cannot be accessed. + + + + Add an entry to the cross-origin whitelist. + The origin allowed to be accessed by the target protocol/domain. + The target protocol allowed to access the source origin. + The optional target domain allowed to access the source origin. + If set to true would allow a blah.example.com if the + was set to example.com + + Returns false if is invalid or the whitelist cannot be accessed. + +The same-origin policy restricts how scripts hosted from different origins +(scheme + domain + port) can communicate. By default, scripts can only access +resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes +(but no other schemes) can use the "Access-Control-Allow-Origin" header to +allow cross-origin requests. For example, https://source.example.com can make +XMLHttpRequest requests on http://target.example.com if the +http://target.example.com request returns an "Access-Control-Allow-Origin: +https://source.example.com" response header. +Scripts in separate frames or iframes and hosted from the same protocol and +domain suffix can execute cross-origin JavaScript if both pages set the +document.domain value to the same domain suffix. For example, +scheme://foo.example.com and scheme://bar.example.com can communicate using +JavaScript if both domains set document.domain="example.com". +This method is used to allow access to origins that would otherwise violate +the same-origin policy. Scripts hosted underneath the fully qualified + URL (like http://www.example.com) will be allowed access to +all resources hosted on the specified and . +If is non-empty and if false only +exact domain matches will be allowed. If contains a top- +level domain component (like "example.com") and is +true sub-domain matches will be allowed. If is empty and + if true all domains and IP addresses will be +allowed. +This method cannot be used to bypass the restrictions on local or display +isolated schemes. See the comments on for more +information. + +This function may be called on any thread. Returns false if +is invalid or the whitelist cannot be accessed. + + + + +This function should be called from the application entry point function to execute a secondary process. +It can be used to run secondary processes from the browser client executable (default behavior) or +from a separate executable specified by the CefSettings.browser_subprocess_path value. +If called for the browser process (identified by no "type" command-line value) it will return immediately with a value of -1. +If called for a recognized secondary process it will block until the process should exit and then return the process exit code. +The |application| parameter may be empty. The |windows_sandbox_info| parameter is only used on Windows and may be NULL (see cef_sandbox_win.h for details). + + + + +Perform a single iteration of CEF message loop processing.This function is +provided for cases where the CEF message loop must be integrated into an +existing application message loop. Use of this function is not recommended +for most users; use CefSettings.MultiThreadedMessageLoop if possible (the default). +When using this function care must be taken to balance performance +against excessive CPU usage. It is recommended to enable the +CefSettings.ExternalMessagePump option when using +this function so that IBrowserProcessHandler.OnScheduleMessagePumpWork() +callbacks can facilitate the scheduling process. This function should only be +called on the main application thread and only if Cef.Initialize() is called +with a CefSettings.MultiThreadedMessageLoop value of false. This function +will not block. + + + + +Quit the CEF message loop that was started by calling Cef.RunMessageLoop(). +This function should only be called on the main application thread and only +if Cef.RunMessageLoop() was used. + + + + +Run the CEF message loop. Use this function instead of an application- +provided message loop to get the best balance between performance and CPU +usage. This function should only be called on the main application thread and +only if Cef.Initialize() is called with a +CefSettings.MultiThreadedMessageLoop value of false. This function will +block until a quit message is received by the system. + + + + +Initializes CefSharp with user-provided settings. +It's important to note that Initialize/Shutdown MUST be called on your main +application thread (typically the UI thread). If you call them on different +threads, your application will hang. See the documentation for Cef.Shutdown() for more details. + + CefSharp configuration settings. + Check that all relevant dependencies avaliable, throws exception if any are missing + Implement this interface to provide handler implementations. Null if you don't wish to handle these events + true if successful; otherwise, false. + + + +Initializes CefSharp with user-provided settings. +It's important to note that Initialize/Shutdown MUST be called on your main +applicaiton thread (Typically the UI thead). If you call them on different +threads, your application will hang. See the documentation for Cef.Shutdown() for more details. + + CefSharp configuration settings. + Check that all relevant dependencies avaliable, throws exception if any are missing + The handler for functionality specific to the browser process. Null if you don't wish to handle these events + true if successful; otherwise, false. + + + +Initializes CefSharp with user-provided settings. +It's important to note that Initialize/Shutdown MUST be called on your main +application thread (typically the UI thread). If you call them on different +threads, your application will hang. See the documentation for Cef.Shutdown() for more details. + + CefSharp configuration settings. + Check that all relevant dependencies avaliable, throws exception if any are missing + true if successful; otherwise, false. + + + +Initializes CefSharp with user-provided settings. +It's important to note that Initialize and Shutdown MUST be called on your main +application thread (typically the UI thread). If you call them on different +threads, your application will hang. See the documentation for Cef.Shutdown() for more details. + + CefSharp configuration settings. + true if successful; otherwise, false. + + + +Gets a value that indicates the Git Hash for CEF version currently being used. + + The Git Commit Hash + + + Gets a value that indicates the Chromium version currently being used. + The Chromium version. + + + Gets a value that indicates the CEF version currently being used. + The CEF Version + + + Gets a value that indicates the version of CefSharp currently being used. + The CefSharp version. + + + Gets a value that indicates whether CefSharp is initialized. + true if CefSharp is initialized; otherwise, false. + + + +Global CEF methods are exposed through this class. e.g. CefInitalize maps to Cef.Initialize +CEF API Doc https://magpcss.org/ceforum/apidocs3/projects/(default)/(_globals).html +This class cannot be inherited. + + + + +Method that will be called when CDM registration is complete. |result| +will be CEF_CDM_REGISTRATION_ERROR_NONE if registration completed +successfully. Otherwise, |result| and |error_message| will contain +additional information about why registration failed. + + + + +Registers a custom scheme using the provided settings. + + The CefCustomScheme which provides the details about the scheme. + + + +GUID string used for identifying the application. This is passed to the system AV function for scanning downloaded files. By +default, the GUID will be an empty string and the file will be treated as an untrusted file when the GUID is empty. + + + + +If CookieableSchemesExcludeDefaults is false the +default schemes ("http", "https", "ws" and "wss") will also be supported. +Specifying a CookieableSchemesList value and setting +CookieableSchemesExcludeDefaults to true will disable all loading +and saving of cookies for this manager. Can be overridden +for individual RequestContext instances via the +RequestContextSettings.CookieableSchemesList and +RequestContextSettings.CookieableSchemesExcludeDefaults values. + + + + +Comma delimited list of schemes supported by the associated +ICookieManager. If CookieableSchemesExcludeDefaults is false the +default schemes ("http", "https", "ws" and "wss") will also be supported. +Specifying a CookieableSchemesList value and setting +CookieableSchemesExcludeDefaults to true will disable all loading +and saving of cookies for this manager. Can be overridden +for individual RequestContext instances via the +RequestContextSettings.CookieableSchemesList and +RequestContextSettings.CookieableSchemesExcludeDefaults values. + + + + +Background color used for the browser before a document is loaded and when no document color is specified. The alpha +component must be either fully opaque (0xFF) or fully transparent (0x00). If the alpha component is fully opaque then the RGB +components will be used as the background color. If the alpha component is fully transparent for a WinForms browser then the +default value of opaque white be used. If the alpha component is fully transparent for a windowless (WPF/OffScreen) browser +then transparent painting will be enabled. + + + + +Comma delimited ordered list of language codes without any whitespace that will be used in the "Accept-Language" HTTP header. +May be set globally using the CefSettings.AcceptLanguageList value. If both values are empty then "en-US,en" will be used. + + + + + +To persist user preferences as a JSON file in the cache path directory set this value to true. A CachePath value must also be +specified to enable this feature. Also configurable using the "persist-user-preferences" command-line switch. Can be +overridden for individual RequestContext instances via the RequestContextSettings.PersistUserPreferences value. + + + + +To persist session cookies (cookies without an expiry date or validity interval) by default when using the global cookie +manager set this value to true. Session cookies are generally intended to be transient and most Web browsers do not persist +them. A CachePath value must also be specified to enable this feature. Also configurable using the "persist-session-cookies" +command-line switch. Can be overridden for individual RequestContext instances via the +RequestContextSettings.PersistSessionCookies value. + + + + +Set to true (1) to enable windowless (off-screen) rendering support. Do not enable this value if the application does not use +windowless rendering as it may reduce rendering performance on some systems. + + + + +Value that will be returned as the User-Agent HTTP header. If empty the default User-Agent string will be used. Also +configurable using the "user-agent" command-line switch. + + + + +The number of stack trace frames to capture for uncaught exceptions. Specify a positive value to enable the +CefRenderProcessHandler:: OnUncaughtException() callback. Specify 0 (default value) and OnUncaughtException() will not be +called. Also configurable using the "uncaught-exception-stack-size" command-line switch. + + + + +Set to a value between 1024 and 65535 to enable remote debugging on the specified port. For example, if 8080 is specified the +remote debugging URL will be http://localhost:8080. CEF can be remotely debugged from any CEF or Chrome browser window. Also +configurable using the "remote-debugging-port" command-line switch. + + + + +Value that will be inserted as the product portion of the default User-Agent string. If empty the Chromium product version +will be used. If UserAgent is specified this value will be ignored. Also configurable using the "user-agent-product" command- +line switch. + + + + +Set to true to disable loading of pack files for resources and locales. A resource bundle handler must be provided for the +browser and render processes via CefApp::GetResourceBundleHandler() if loading of pack files is disabled. Also configurable +using the "disable-pack-loading" command- line switch. + + + + +Custom flags that will be used when initializing the V8 JavaScript engine. The consequences of using custom flags may not be +well tested. Also configurable using the "js-flags" command-line switch. + + + + +The log severity. Only messages of this severity level or higher will be logged. When set to + no messages will be written to the log file, but Fatal messages will still be +output to stderr. Also configurable using the "log-severity" command-line switch with a value of "verbose", "info", "warning", +"error", "fatal", "error-report" or "disable". + + + + +The directory and file name to use for the debug log. If empty a default log file name and location will be used. On Windows +a "debug.log" file will be written in the main executable directory. Also configurable using the"log-file" command- line +switch. + + + + +The fully qualified path for the resources directory. If this value is empty the cef.pak and/or devtools_resources.pak files +must be located in the module directory. Also configurable using the "resources-dir-path" command-line switch. + + + + +The fully qualified path for the locales directory. If this value is empty the locales directory must be located in the +module directory. If this value is non-empty then it must be an absolute path. Also configurable using the "locales-dir-path" +command-line switch. + + + + +The locale string that will be passed to WebKit. If empty the default locale of "en-US" will be used. Also configurable using +the "lang" command-line switch. + + + + +Set to true in order to completely ignore SSL certificate errors. This is NOT recommended. + + + + +The location where user data such as spell checking dictionary files will be stored on disk. If this value is empty then the +default user data directory will be used ("Local Settings\Application Data\CEF\User Data" directory under the user +profile directory on Windows). If this value is non-empty then it must be an absolute path. + + + + +The root directory that all CefSettings.CachePath and RequestContextSettings.CachePath values must have in common. If this +value is empty and CefSettings.CachePath is non-empty then it will default to the CefSettings.CachePath value. +If this value is non-empty then it must be an absolute path. Failure to set this value correctly may result in the sandbox +blocking read/write access to the CachePath directory. NOTE: CefSharp does not implement the CHROMIUM SANDBOX. A non-empty +RootCachePath can be used in conjuncation with an empty CefSettings.CachePath in instances where you would like browsers +attached to the Global RequestContext (the default) created in "incognito mode" and instances created with a custom +RequestContext using a disk based cache. + + + + +The location where data for the global browser cache will be stored on disk. In this value is non-empty then it must be +an absolute path that is must be either equal to or a child directory of CefSettings.RootCachePath (if RootCachePath is +empty it will default to this value). If the value is empty then browsers will be created in "incognito mode" where +in-memory caches are used for storage and no data is persisted to disk. HTML5 databases such as localStorage will only +persist across sessions if a cache path is specified. Can be overridden for individual RequestContext instances via the +RequestContextSettings.CachePath value. + + + + +The path to a separate executable that will be launched for sub-processes. By default the browser process executable is used. +See the comments on Cef.ExecuteProcess() for details. If this value is non-empty then it must be an absolute path. +Also configurable using the "browser-subprocess-path" command-line switch. +Defaults to using the provided CefSharp.BrowserSubprocess.exe instance + + + + +Set to true to have the browser process message loop run in a separate thread. If false than the CefDoMessageLoopWork() +function must be called from your application message loop. This option is only supported on Windows. The default value is +true. + + + + +Set to true to control browser process main (UI) thread message pump scheduling via the +IBrowserProcessHandler.OnScheduleMessagePumpWork callback. This option is recommended for use in combination with the +Cef.DoMessageLoopWork() function in cases where the CEF message loop must be integrated into an existing application message +loop (see additional comments and warnings on Cef.DoMessageLoopWork). Enabling this option is not recommended for most users; +leave this option disabled and use either MultiThreadedMessageLoop (the default) if possible. + + + + +Set to true to disable configuration of browser process features using standard CEF and Chromium command-line arguments. +Configuration can still be specified using CEF data structures or by adding to CefCommandLineArgs. + + + + +**Experimental** +Set to true to enable use of the Chrome runtime in CEF. This feature is +considered experimental and is not recommended for most users at this time. +See issue https://bitbucket.org/chromiumembedded/cef/issues/2969/support-chrome-windows-with-cef-callbacks for details. + + + + +Add custom command line argumens to this collection, they will be added in OnBeforeCommandLineProcessing. The +CefSettings.CommandLineArgsDisabled value can be used to start with an empty command-line object. Any values specified in +CefSettings that equate to command-line arguments will be set before this method is called. + + + + +Add Customs schemes to this collection. + + + + +Destructor. + + + + +Finalizer. + + + + +Default Constructor. + + + + +CefCustomScheme collection + + + + +CefSettings unmanaged pointer + + + + +Command Line Arguments Dictionary. + + + + +Initialization settings. Many of these and other settings can also configured using command-line switches. +WPF/WinForms/OffScreen each have their own CefSettings implementation that sets +relevant settings e.g. OffScreen starts with audio muted. + + + +ref + + + +Interface that should be implemented by the CefUrlRequest client. +The methods of this class will be called on the same thread that created +the request unless otherwise documented. + + + +Load the request represented by the |request| object. + + + + + + + +Get the image hotspot (drag start location relative to image dimensions). + + + + +Get the image representation of drag data. +May return NULL if no image representation is available. + + + + +Returns the image width in density independent pixel(DIP) units. + + + + +Removes the representation for scaleFactor. + + + true for success + + + +Returns true if this Image and that Image share the same underlying storage. + + image to compare + returns true if share same underlying storage + + + +Returns true if this Image is empty. + + + + + +Returns true if this image contains a representation for scaleFactor. + + + + + + +Returns the image height in density independent pixel(DIP) units. + + + + +Returns information for the representation that most closely matches scaleFactor. + + scale factor + actual scale factor + pixel width + pixel height + return if information found for scale factor + + + +Returns the PNG representation that most closely matches scaleFactor. + + scale factor + is the PNG transparent + pixel width + pixel height + A stream represending the PNG or null. + + + +Returns the JPEG representation that most closely matches scaleFactor. + + scale factor + image quality + pixel width + pixel height + A stream representing the JPEG or null. + + + +Returns the bitmap representation that most closely matches scaleFactor. + + scale factor + color type + alpha type + pixel width + pixel height + A stream represending the bitmap or null. + + + +Gets the inner most instance + + current instance + + + +Load an extension. If extension resources will be read from disk using the default load implementation then rootDirectoy +should be the absolute path to the extension resources directory and manifestJson should be null. +If extension resources will be provided by the client (e.g. via IRequestHandler and/or IExtensionHandler) then rootDirectory +should be a path component unique to the extension (if not absolute this will be internally prefixed with the PK_DIR_RESOURCES path) +and manifestJson should contain the contents that would otherwise be read from the "manifest.json" file on disk. +The loaded extension will be accessible in all contexts sharing the same storage (HasExtension returns true). +However, only the context on which this method was called is considered the loader (DidLoadExtension returns true) and only the +loader will receive IRequestContextHandler callbacks for the extension. will be +called on load success or will be called on load failure. +If the extension specifies a background script via the "background" manifest key then +will be called to create the background browser. See that method for additional information about background scripts. +For visible extension views the client application should evaluate the manifest to determine the correct extension URL to load and then pass +that URL to the IBrowserHost.CreateBrowser* function after the extension has loaded. For example, the client can look for the "browser_action" +manifest key as documented at https://developer.chrome.com/extensions/browserAction. Extension URLs take the form "chrome-extension:///". +Browsers that host extensions differ from normal browsers as follows: - Can access chrome.* JavaScript APIs if allowed by the manifest. +Visit chrome://extensions-support for the list of extension APIs currently supported by CEF. - Main frame navigation to non-extension +content is blocked. +- Pinch-zooming is disabled. +- returns the hosted extension. +- CefBrowserHost::IsBackgroundHost returns true for background hosts. See https://developer.chrome.com/extensions for extension implementation and usage documentation. + + If extension resources will be read from disk using the default load implementation then rootDirectoy +should be the absolute path to the extension resources directory and manifestJson should be null + If extension resources will be provided by the client then rootDirectory should be a path component unique to the extension +and manifestJson should contain the contents that would otherwise be read from the manifest.json file on disk + handle events related to browser extensions + + + +Returns true if this context has access to the extension identified by extensionId. +This may not be the context that was used to load the extension (see DidLoadExtension). +This method must be called on the CEF UI thread. + + extension id + Returns true if this context has access to the extension identified by extensionId + Use Cef.UIThreadTaskFactory to execute this method if required, + and ChromiumWebBrowser.IsBrowserInitializedChanged are both +executed on the CEF UI thread, so can be called directly. +When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main +application thread will be the CEF UI thread. + + + +Retrieve the list of all extensions that this context has access to (see HasExtension). + will be populated with the list of extension ID values. +This method must be called on the CEF UI thread. + + output a list of extensions Ids + returns true on success otherwise false + Use Cef.UIThreadTaskFactory to execute this method if required, + and ChromiumWebBrowser.IsBrowserInitializedChanged are both +executed on the CEF UI thread, so can be called directly. +When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main +application thread will be the CEF UI thread. + + + +Returns the extension matching extensionId or null if no matching extension is accessible in this context (see HasExtension). +This method must be called on the CEF UI thread. + + extension Id + Returns the extension matching extensionId or null if no matching extension is accessible in this context + Use Cef.UIThreadTaskFactory to execute this method if required, + and ChromiumWebBrowser.IsBrowserInitializedChanged are both +executed on the CEF UI thread, so can be called directly. +When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main +application thread will be the CEF UI thread. + + + +Returns true if this context was used to load the extension identified by extensionId. Other contexts sharing the same storage will also have access to the extension (see HasExtension). +This method must be called on the CEF UI thread. + + Returns true if this context was used to load the extension identified by extensionId + Use Cef.UIThreadTaskFactory to execute this method if required, + and ChromiumWebBrowser.IsBrowserInitializedChanged are both +executed on the CEF UI thread, so can be called directly. +When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main +application thread will be the CEF UI thread. + + + +Attempts to resolve origin to a list of associated IP addresses. + + host name to resolve + A task that represents the Resoolve Host operation. The value of the TResult parameter contains ResolveCallbackResult. + + + +Clears all active and idle connections that Chromium currently has. +This is only recommended if you have released all other CEF objects but +don't yet want to call Cef.Shutdown(). + + If is non-NULL it will be executed on the CEF UI thread after +completion. This param is optional + + + +Clears all HTTP authentication credentials that were added as part of handling +. + + If is non-NULL it will be executed on the CEF UI thread after +completion. This param is optional + + + +Clears all certificate exceptions that were added as part of handling +. If you call this it is +recommended that you also call or you risk not +being prompted again for server certificates if you reconnect quickly. + + If is non-NULL it will be executed on the CEF UI thread after +completion. This param is optional + + + +Set the value associated with preference name. If value is null the +preference will be restored to its default value. If setting the preference +fails then error will be populated with a detailed description of the +problem. This method must be called on the CEF UI thread. +Preferences set via the command-line usually cannot be modified. + + preference key + preference value + out error + Returns true if the value is set successfully and false otherwise. + Use Cef.UIThreadTaskFactory to execute this method if required, + and ChromiumWebBrowser.IsBrowserInitializedChanged are both +executed on the CEF UI thread, so can be called directly. +When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main +application thread will be the CEF UI thread. + + + +Returns true if the preference with the specified name can be modified +using SetPreference. As one example preferences set via the command-line +usually cannot be modified. This method must be called on the CEF UI thread. + + preference key + Returns true if the preference with the specified name can be modified +using SetPreference + Use Cef.UIThreadTaskFactory to execute this method if required, + and ChromiumWebBrowser.IsBrowserInitializedChanged are both +executed on the CEF UI thread, so can be called directly. +When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main +application thread will be the CEF UI thread. + + + +Returns all preferences as a dictionary. The returned +object contains a copy of the underlying preference values and +modifications to the returned object will not modify the underlying +preference values. This method must be called on the browser process UI +thread. + + If true then +preferences currently at their default value will be included. + Preferences (dictionary can have sub dictionaries) + + + +Returns the value for the preference with the specified name. Returns +NULL if the preference does not exist. The returned object contains a copy +of the underlying preference value and modifications to the returned object +will not modify the underlying preference value. This method must be called +on the CEF UI thread. + + preference name + Returns the value for the preference with the specified name + Use Cef.UIThreadTaskFactory to execute this method if required, + and ChromiumWebBrowser.IsBrowserInitializedChanged are both +executed on the CEF UI thread, so can be called directly. +When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main +application thread will be the CEF UI thread. + + + +Returns true if a preference with the specified name exists. This method +must be called on the CEF UI thread. + + name of preference + bool if the preference exists + Use Cef.UIThreadTaskFactory to execute this method if required, + and ChromiumWebBrowser.IsBrowserInitializedChanged are both +executed on the CEF UI thread, so can be called directly. +When CefSettings.MultiThreadedMessageLoop == false (the default is true) then the main +application thread will be the CEF UI thread. + + + +Tells all renderer processes associated with this context to throw away +their plugin list cache. If reloadPages is true they will also reload +all pages with plugins. RequestContextHandler.OnBeforePluginLoad may +be called to rebuild the plugin list cache. + + reload any pages with pluginst + + + +Returns the cache path for this object. If empty an "incognito mode" +in-memory cache is being used. + + + + +Clear all registered scheme handler factories. + + Returns false on error. + + + +Register a scheme handler factory for the specified schemeName and optional domainName. +An empty domainName value for a standard scheme will cause the factory to match all domain +names. The domainName value will be ignored for non-standard schemes. If schemeName is +a built-in scheme and no handler is returned by factory then the built-in scheme handler +factory will be called. If schemeName is a custom scheme then you must also implement the +IApp.OnRegisterCustomSchemes() method in all processes. This function may be called multiple +times to change or remove the factory that matches the specified schemeName and optional +domainName. + + Scheme Name + Optional domain name + Scheme handler factory + Returns false if an error occurs. + + + +Returns true if this object is the global context. The global context is +used by default when creating a browser or URL request with a NULL context +argument. + + + + +Returns the default cookie manager for this object. This will be the global +cookie manager if this object is the global request context. + + If callback is non-NULL it will be executed asnychronously on the CEF IO thread +after the manager's storage has been initialized. + Returns the default cookie manager for this object + + + +Returns true if this object is sharing the same storage as the specified context. + + context to compare + Returns true if same storage + + + +Returns true if this object is pointing to the same context object. + + context to compare + Returns true if the same + + + +Creates a new context object that shares storage with other and uses an +optional handler. + + shares storage with this RequestContext + optional requestContext handler + Returns a new RequestContext + + +Creates a new context object that shares storage with | other | and uses an optional | handler | . + + + +A request context provides request handling for a set of related browser objects. +A request context is specified when creating a new browser object via the CefBrowserHost +static factory methods. Browser objects with different request contexts will never be +hosted in the same render process. Browser objects with the same request context may or +may not be hosted in the same render process depending on the process model. +Browser objects created indirectly via the JavaScript window.open function or targeted +links will share the same render process and the same request context as the source browser. +When running in single-process mode there is only a single render process (the main process) +and so all browsers created in single-process mode will share the same request context. +This will be the first request context passed into a CefBrowserHost static factory method +and all other request context objects will be ignored. + + + + +If CookieableSchemesExcludeDefaults is false the +default schemes ("http", "https", "ws" and "wss") will also be supported. +Specifying a CookieableSchemesList value and setting +CookieableSchemesExcludeDefaults to true will disable all loading +and saving of cookies for this manager. This value will be ignored if + matches the value. + + + + +Comma delimited list of schemes supported by the associated +ICookieManager. If CookieableSchemesExcludeDefaults is false the +default schemes ("http", "https", "ws" and "wss") will also be supported. +Specifying a CookieableSchemesList value and setting +CookieableSchemesExcludeDefaults to true will disable all loading +and saving of cookies for this manager. This value will be ignored if + matches the value. + + + + +Set to true to ignore errors related to invalid SSL certificates. +Enabling this setting can lead to potential security vulnerabilities like +"man in the middle" attacks. Applications that load content from the +internet should not enable this setting. Can be set globally using the +CefSettings.IgnoreCertificateErrors value. This value will be ignored if +CachePath matches the CefSettings.cache_path value. + + + + +Comma delimited ordered list of language codes without any whitespace that +will be used in the "Accept-Language" HTTP header. Can be set globally +using the CefSettings.accept_language_list value or overridden on a per- +browser basis using the BrowserSettings.AcceptLanguageList value. If +all values are empty then "en-US,en" will be used. This value will be +ignored if CachePath matches the CefSettings.CachePath value. + + + + +The location where cache data for this request context will be stored on +disk. If this value is non-empty then it must be an absolute path that is +either equal to or a child directory of CefSettings.RootCachePath. +If the value is empty then browsers will be created in "incognito mode" +where in-memory caches are used for storage and no data is persisted to disk. +HTML5 databases such as localStorage will only persist across sessions if a +cache path is specified. To share the global browser cache and related +configuration set this value to match the CefSettings.CachePath value. + + + + +To persist user preferences as a JSON file in the cache path directory set +this value to true. Can be set globally using the +CefSettings.PersistUserPreferences value. This value will be ignored if +CachePath is empty or if it matches the CefSettings.CachePath value. + + + + +To persist session cookies (cookies without an expiry date or validity +interval) by default when using the global cookie manager set this value to +true. Session cookies are generally intended to be transient and most +Web browsers do not persist them. Can be set globally using the +CefSettings.PersistSessionCookies value. This value will be ignored if +CachePath is empty or if it matches the CefSettings.CachePath value. + + + + +Default constructor + + + + +RequestContextSettings + + + + +True if dispose should be called after this object is used + + + + +Gets a value indicating if the browser settings has been disposed. + + + + +The maximum rate in frames per second (fps) that CefRenderHandler::OnPaint +will be called for a windowless browser. The actual fps may be lower if +the browser cannot generate frames at the requested rate. The minimum +value is 1 and the maximum value is 60 (default 30). This value can also be +changed dynamically via IBrowserHost.SetWindowlessFrameRate. + + + + +Comma delimited ordered list of language codes without any whitespace that +will be used in the "Accept-Language" HTTP header. May be overridden on a +per-browser basis using the CefBrowserSettings.AcceptLanguageList value. +If both values are empty then "en-US,en" will be used. Can be overridden +for individual RequestContext instances via the +RequestContextSettings.AcceptLanguageList value. + + + + +Background color used for the browser before a document is loaded and when no document color +is specified. The alpha component must be either fully opaque (0xFF) or fully transparent (0x00). +If the alpha component is fully opaque then the RGB components will be used as the background +color. If the alpha component is fully transparent for a WinForms browser then the +CefSettings.BackgroundColor value will be used. If the alpha component is fully transparent +for a windowless (WPF/OffScreen) browser then transparent painting will be enabled. + + + + +Controls whether WebGL can be used. Note that WebGL requires hardware +support and may not work on all systems even when enabled. Also +configurable using the "disable-webgl" command-line switch. + + + + +Controls whether the application cache can be used. Also configurable using +the "disable-application-cache" command-line switch. + + + + +Controls whether databases can be used. Also configurable using the +"disable-databases" command-line switch. + + + + +Controls whether local storage can be used. Also configurable using the +"disable-local-storage" command-line switch. + + + + +Controls whether the tab key can advance focus to links. Also configurable +using the "disable-tab-to-links" command-line switch. + + + + +Controls whether text areas can be resized. Also configurable using the +"disable-text-area-resize" command-line switch. + + + + +Controls whether standalone images will be shrunk to fit the page. Also +configurable using the "image-shrink-standalone-to-fit" command-line +switch. + + + + +Controls whether image URLs will be loaded from the network. A cached image +will still be rendered if requested. Also configurable using the +"disable-image-loading" command-line switch. + + + + +Controls whether file URLs will have access to other file URLs. Also +configurable using the "allow-access-from-files" command-line switch. + + + + +Controls whether file URLs will have access to all URLs. Also configurable +using the "allow-universal-access-from-files" command-line switch. + + + + +Controls whether any plugins will be loaded. Also configurable using the +"disable-plugins" command-line switch. + + + + +Controls whether DOM pasting is supported in the editor via +execCommand("paste"). The |javascript_access_clipboard| setting must also +be enabled. Also configurable using the "disable-javascript-dom-paste" +command-line switch. + + + + +Controls whether JavaScript can access the clipboard. Also configurable +using the "disable-javascript-access-clipboard" command-line switch. + + + + +Controls whether JavaScript can be used to close windows that were not +opened via JavaScript. JavaScript can still be used to close windows that +were opened via JavaScript. Also configurable using the +"disable-javascript-close-windows" command-line switch. + + + + +Controls whether JavaScript can be executed. (Used to Enable/Disable javascript) +Also configurable using the "disable-javascript" command-line switch. + + + + +Controls the loading of fonts from remote sources. Also configurable using +the "disable-remote-fonts" command-line switch. + + + + +Default encoding for Web content. If empty "ISO-8859-1" will be used. Also +configurable using the "default-encoding" command-line switch. + + + + +MinimumLogicalFontSize + + + + +MinimumFontSize + + + + +DefaultFixedFontSize + + + + +DefaultFontSize + + + + +FantasyFontFamily + + + + +CursiveFontFamily + + + + +SansSerifFontFamily + + + + +SerifFontFamily + + + + +FixedFontFamily + + + + +StandardFontFamily + + + + +Destructor. + + + + +Finalizer. + + + + +Default Constructor + + + + +Internal Constructor + + + + +Browser initialization settings. Specify NULL or 0 to get the recommended +default values. The consequences of using custom values may not be well +tested. Many of these and other settings can also configured using command- +line switches. + + + + +Creates a detailed expection string from a provided Cef V8 exception. + + The exception which will be used as base for the message + + + +Assigns the provided cef_string_t object from the given .NET string. + + The cef_string_t that should be updated. + The .NET string whose value should be used to update cefStr. + + + +Converts a .NET List of strings to native (unmanaged) format. + + The List of strings that should be converted. + An unmanaged representation of the provided List of strings, or an empty List if the input is a nullptr. + + + +Converts a .NET string to native (unmanaged) format. Note that this method does not allocate a new copy of the + + The string that should be converted. + An unmanaged representation of the provided string, or an empty string if the input string is a nullptr. + + + +Converts an unmanaged vector of strings to a (managed) .NET List of strings. + + The vector of strings that should be converted. + A .NET List of strings. + + + +Converts an unmanaged string to a (managed) .NET string. + + The string that should be converted. + A .NET string. + + + +Converts an unmanaged string to a (managed) .NET string. + + The string that should be converted. + A .NET string. + + + + + + \ No newline at end of file diff --git a/DLL/CefSharp.Core.dll b/DLL/CefSharp.Core.dll new file mode 100644 index 0000000..1f9a2db Binary files /dev/null and b/DLL/CefSharp.Core.dll differ diff --git a/DLL/CefSharp.WinForms.dll b/DLL/CefSharp.WinForms.dll new file mode 100644 index 0000000..ad2ee80 Binary files /dev/null and b/DLL/CefSharp.WinForms.dll differ diff --git a/DLL/CefSharp.dll b/DLL/CefSharp.dll new file mode 100644 index 0000000..3cbb96d Binary files /dev/null and b/DLL/CefSharp.dll differ diff --git a/DLL/ClearScript.Core.dll b/DLL/ClearScript.Core.dll new file mode 100644 index 0000000..d1db0d0 Binary files /dev/null and b/DLL/ClearScript.Core.dll differ diff --git a/DLL/ClearScript.V8.dll b/DLL/ClearScript.V8.dll new file mode 100644 index 0000000..c567c09 Binary files /dev/null and b/DLL/ClearScript.V8.dll differ diff --git a/DLL/ClearScriptV8.win-x86.dll b/DLL/ClearScriptV8.win-x86.dll new file mode 100644 index 0000000..ec59a00 Binary files /dev/null and b/DLL/ClearScriptV8.win-x86.dll differ diff --git a/DLL/Easy4net.XML b/DLL/Easy4net.XML new file mode 100644 index 0000000..6bf7b1b --- /dev/null +++ b/DLL/Easy4net.XML @@ -0,0 +1,2881 @@ + + + + Easy4net + + + + + 数据库字段名跟值键值对试题类 + + + + + 通用实用工具 + + + + + 用于字符串和枚举类型的转换 + + + + + + + + 根据传入的Key获取配置文件中的Value值 + + + + + + + 检测输入值是否为空 + + + + + + + 数据库条件语句生成器 + + + + + 参数字符前缀 + + + + + SQL语句创建对象 + + + + + 查询SQL语句 + + + + + 字段信息 + + + + + 根据配置文件创建一个默认的条件语句生成器 + + + + + 根据配置文件创建一个默认的条件语句生成器 + + 查询语句 + + + + 传入查询语句 + + 查询语句 + + + + + 增加Where关键字 + + + + + + 增加Where等于语句 + + 字段名 + 字段值 + + + + + 增加等于语句 + + 字段名 + 字段值 + + + + + 增加And等于语句 + + 字段名 + 字段值 + + + + + 增加Or等于语句 + + 字段名 + 字段值 + + + + + 增加大于语句 + + 字段名 + 字段值 + + + + + 增加大于等于语句 + + 字段名 + 字段值 + + + + + 增加And大于语句 + + 字段名 + 字段值 + + + + + 增加And大于等于语句 + + 字段名 + 字段值 + + + + + 增加Or大于语句 + + 字段名 + 字段值 + + + + + 增加Or大于等于语句 + + 字段名 + 字段值 + + + + + 增加小于语句 + + 字段名 + 字段值 + + + + + 增加小于等于语句 + + 字段名 + 字段值 + + + + + 增加And小于语句 + + 字段名 + 字段值 + + + + + 增加And小于等于语句 + + 字段名 + 字段值 + + + + + 增加Or小于语句 + + 字段名 + 字段值 + + + + + 增加Or小于等于语句 + + 字段名 + 字段值 + + + + + 增加And等于语句,相当于AndEqual方法 + + 字段名 + 字段值 + + + + + 增加Or等于语句,相当于OrEqual方法 + + 字段名 + 字段值 + + + + + 增加Order By Asc递增排序语句 + + 排序的字段名 + + + + + 增加Order By Desc递减排序语句 + + 排序的字段名 + + + + + 增加Like %XX%语句 + + 字段名 + 字段值 + + + + + 增加And Like %XX%语句 + + 字段名 + 字段值 + + + + + 增加Or Like %XX%语句 + + 字段名 + 字段值 + + + + + 增加Like %XX语句 + + 字段名 + 字段值 + + + + + 增加And Like %XX语句 + + 字段名 + 字段值 + + + + + 增加Or Like %XX语句 + + 字段名 + 字段值 + + + + + 增加Like XX%语句 + + 字段名 + 字段值 + + + + + 增加And Like XX%语句 + + 字段名 + 字段值 + + + + + 增加Or Like XX%语句 + + 字段名 + 字段值 + + + + + 输出本条件对象的字符串描述 + + + + + + 对关键字进行格式化输出 + + 要格式化的关键字 + + + + + 数据库关键字检查帮助类 + + + + + MySQL中关键字集合 + + + + + MSSQL中关键字集合 + + + + + 初始化MySQL中关键字集合 + + + + + 初始化MSSQL中关键字集合 + + + + + 格式化列名,对列名与数据库关键字相同的进行格式化处理 + + + + + + + + 实体帮助类 + + + + + 根据实体类类型和数据操作类型获取数据库表特性 + + 数据库表实例类型 + 数据操作类型 + 数据库表特性 + + + + 根据主键特性跟数据操作类型获取主键名 + + IdAttribute主键特性 + 数据操作类型 + 主键名 + + + + 根据字段特性或主键特性获取对应字段名 + + 字段特性或主键特性 + 字段名 + + + + 根据数据库表对象及数据操作类型获取表信息 + + 数据库表对象 + 操作类型 + 数据库表对象属性集合 + 数据库表信息 + + + + 根据数据库表对象获取该对象中主键成员的属性 + + 数据库表对象 + 该对象的属性集合 + 主键成员属性 + + + + 根据数据库表信息从DataReader中读取对应实体类的数据集合 + + 数据库表实体类 + DataReader + 数据库表信息 + 实体类属性集合 + + + + + 从DataReader中读取指定数据库表类型的数据集合 + + 数据库表实体类 + DataReader + + + + + 根据数据库表信息及条件生成器获取Select语句 + + 数据库表信息 + 条件生成器 + + + + + 根据数据库表信息获取Selet All语句 + + 数据库表信息 + + + + + 根据数据库表信息获取根据主键值进行查询的SQL语句 + + 数据库表信息 + + + + + 根据数据库表信息获取查询记录条数的SQL语句 + + 数据库表信息 + + + + + 根据数据库表信息及条件生成器获取查询记录条数的SQL语句 + + 数据库表信息 + 条件生成器 + + + + + 根据数据库表信息获取根据主键值进行查询的SQL语句 + 同方法GetFindByIdSql + + + + + + + 根据数据库类型获取对应的获取在插入操作后自增长型主键字段的SQL语句 + + 数据库类型 + + + + + 根据数据库表信息获取Insert插入操作语句 + + + + + + + 根据数据库表信息获取Update更新操作语句 + + + + + + + 根据数据库表信息获取根据主键进行Delete删除操作语句 + + + + + + + 将字段信息集合设置到参数数组中 + + 字段信息集合 + [输出] 参数值集合 + + + + 根据操作类型判断输入的字段特性中指定的字段是否进行忽略 + + 字段特性ColumnAttribute,如果不为此特性则不进行忽略检测 + 操作类型 + true忽略此字段 + + + + 根据操作类型判断输入的成员属性中指定的成员是否进行忽略 + + 成员属性 + 数据操作 + true忽略此属性中的成员 + + + Delegate for calling a method that is not known at runtime. + the object to be called or null if the call is to a static method. + the parameters to the method. + the return value for the method or null if it doesn't return anything. + + + Delegate for creating and object at runtime using the default constructor. + the newly created object. + + + Delegate to get an arbitraty property at runtime. + the object instance whose property will be obtained. + the property value. + + + Delegate to set an arbitrary property at runtime. + the object instance whose property will be modified. + + + + Class with helper methods for dynamic invocation generating IL on the fly. + + + + 用于存放GetMethodInvoker的Dictionary + + + + + 快速执行指定方法 + + + + + + + 用于存放GetInstanceCreator的Dictionary + + + + Gets the instance creator delegate that can be use to create instances of the specified type. + The type of the objects we want to create. + A delegate that can be used to create the objects. + + + + 用于存放GetPropertyGetter的Dictionary + + + + + 快速获取成员属性 + + + + + + + 用于存放SetPropertySetter的Dictionary + + + + + 快速设置成员属性 + + + + + + Emits the cast to a reference, unboxing if needed. + The MSIL generator. + The type to cast. + + + Boxes a type if needed. + The MSIL generator. + The type. + + + Emits code to save an integer to the evaluation stack. + The MSIL generator. + The value to push. + + + + 主键字段信息 + + + + + 主键字段名 + + + + + 主键字段值 + + + + + 主键字段名 + + + + + 主键字段值 + + + + + 键值对映射类 + + + + + 设置/添加键值对 + + + + + + + 设置/添加参数 + + + + + + + 分页查询结果 + + 数据库表实体类 + + + + 分页查询中总记录数 + + + + + 分页查询中结果集合 + + + + + 参数映射集合类 + + + + + 是否分页 + + + + + 页面偏移量 + + + + + 每页限制记录数 + + + + + 排序字段 + + + + + 是否递减排序 + + + + + 数据库参数集合 + + + + + 创建一个参数映射集合 + + + + + 排序的字段 + + + + + 是否递减排序 + + + + + 创建一个参数映射集合 + + + + + + 是否进行分页 + + + + + 每页的偏移量 + + + + + 每页的记录条数限制 + + + + + 根据键值获取整型数据 + + + + + + + 根据键值获取字符串数据 + + + + + + + 根据键值获取Double型数据 + + + + + + + 根据键值获取Long型数据 + + + + + + + 根据键值获取Decimal型数据 + + + + + + + 根据键值获取DateTime型数据 + + + + + + + 设置排序字段及排序方式 + + 排序字段 + 是否为递减排序 + + + + 此方法已过时,请使用 setPageParamters方法分页 + + + + + + 此方法已过时,请使用 setPageParamters方法分页 + + + + + + 分页参数设置 + + 第几页,从0开始 + 每页最多显示几条数据 + + + + 设置分页参数 + + + + + 添加键值对映射 + + + + + + + 添加键值对映射 + + + + + + + 添加键值对映射 + + + + + + + 输出参数集合 + + + + + + 实体类反射帮助类 + + + + + 根据输入类型获取对应的成员属性集合 + + + + + + + 根据输入类型获取对应的字段属性集合 + + + + + + + 快速执行Method + + + + + + + + + 快速实例化一个T + + + + + + + 快速实例化一个FastCreateInstanceHandler + + + + + + + 设置属性值 + + + + + + + + 设置属性值 + + + + + + + + 设置属性值 + + + + + + + + + 获取属性值 + + + + + + + + + 获取属性值 + + + + + + + + + 获取属性类型 + + + + + + + + SQL语句创建帮助类 + + + + + MSSQL分页语句模版 + + + + + MySQL排序分页语句模版 + + + + + MySQL分页语句模板 + + + + + SQLite排序分页语句模板 + + + + + SQLite分页语句模板 + + + + + ACCESS分页语句模板 + + + + + 从SQL语句中获取查询的列名集合 + Select 与 From中间的部分 + + + + + + + 从SQL语句中获取分页语句 + + + + + + + 从SQL语句中获取查询语句 + + + + + + + 根据SQL语句判断是否为分页语句 + + + + + + + 根据SQL语句及排序条件创建分页语句 + + SQL语句 + 排序字段 + 是否为递减排序 + + + + + 根据SQL语句创建一个获取记录数的SQL语句 + + + + + + + 创建ACCESS数据库的分页SQL语句 + + + 参数集合 + + + + + 创建ACCESS的分页SQL语句 + + + 参数集合 + 每页记录数 + + + + + 创建ACCESS的SQL语句 + + 数据库表实体对象类型 + 表信息 + SQL语句 + 参数集合 + + + + + 创建ACCESS SQL语句 + + + 参数集合 + + + + + 数据库表信息实体类 + + + + + 数据库表名 + + + + + 主键生成方式 + + + + + 主键信息 + + + + + 普通字段信息集合 + + + + + 属性到字段信息的映射集合 + + + + + 字段信息到属性的映射集合 + + + + + 是否不具备自增长键 + + + + + 数据库表名 + + + + + 主键生成方式,参考GenerationType定义 + + + + + 主键字段信息 + + + + + 普通字段信息集合 + + + + + 实体类属性对应字段信息映射集合 + + + + + 字段信息对应实体类属性映射集合 + + + + + 获取本数据库表信息中的参数键值集合 + + + + + + 将参数集合转为参数数组 + + 参数集合 + + + + + 获取本数据库表信息中的参数键值数组 + + + + + + 类型单元帮助类 + + + + + 根据数据类型将指定数据进行相应转换 + + + + + + + + 获取类型名 + + + + + + + 检查输入值是否为空 + + + + + + + 数据库连接信息 + + + + + 数据库类型 + + + + + 创建表 + + + + + + 执行更新语句 + 注意:支持完整SQL、或非完整SQL 会自动识别 + + + + 例如:nick=@nick,wxid=@wxid + 例如:id=@id + + + + + 创建表 + + + + + + 获得Table + + + SQL + + + + + + 根据ID查数据、必须有为ID的字段 + + + + + + + + + 添加唯一约束 + + + + + 添加唯一约束 + + + + + 添加索引 + + + + + 判断表是否存在 + + + + + + + 判断表是否存在 + + + + + 持久层实体类 + + + + + 数据库连接字符串 + + + + + 数据库事物对象 + + + + + 数据库类型 + + + + + 数据库工厂对象,生成相应的数据库操作对象 + + + + + /数据库工厂对象,生成相应的数据库操作对象 + + + + + 根据数据库类型名创建一个持久层对象 + + + + + + + 获取当前的持久层对象 + + + + + + 根据连接类型名进行连接配置 + + + + + + 开启事物处理功能 + + + + + 根据事物锁定行为开启事物 + + + + + + 提交事物 + + + + + 事物回滚 + + + + + 获取当前的事物 + + + + + + Insert插入操作 + + + 数据库表实体对象 + + + + + 批量进行Insert插入操作 + + + 数据库表实体对象集合 + + + + + Update更新操作 + + + 数据库表实体对象 + + + + + 批量进行Update更新操作 + + + 数据库表实体对象集合 + + + + + 执行一条带有参数集合的SQL语句 + + SQL语句 + 参数集合 + + + + + 执行一条SQL语句 + + + + + + + 进行Delete删除操作 + + + 数据库表实体对象 + + + + + 批量进行Delete删除操作 + + + 数据库表实体对象集合 + + + + + 根据主键值删除实体类对应数据库中的数据 + + + 主键值 + + + + + 根据主键ID集合进行删除操作 + + + + + + + + 根据SQL语句获取记录数 + + + + + + + 通过自定义SQL语句查询记录数 + + + 参数集合 + + + + + 通过自定义SQL语句查询数据 + + + + + + + + 通过自定义SQL语句查询数据 + + + + + + + + + 分页查询返回分页结果 + + + + + + + + + 通过主键ID查询数据 + + + + + + + + 获取数据库连接 + + + + + + 获取当前事物是否为空 + + + + + + 持久层对象获取帮助 + + + + + 根据数据库类型名获取对应的持久层对象 + + + + + + + 获取MSSQL持久层对象 + + + + + + 持久层线程池 + + + + + 设置持久层到线程池 + + + + + + 从线程池获取持久层 + + + + + + 清空线程池 + + + + + 数据库表字段特性 + + + + + 字段信息 例如:varchar(255) default '' + + + + + 是否为主键 + + + + + 字段名 + + + + + 是否唯一 + + + + + 是否允许为空 + + + + + 是否插入到表中 + + + + + 是否修改到表中 + + + + + 在所有操作中是否忽略此字段 + + + + + 表字段名 + + + + + 是否是唯一的,默认为否 + + + + + 此字段是否允许为空,默认允许为空 + + + + + 在执行插入操作时此是否插入此字段值,默认为插入 + + + + + 在执行更新操作时是否更新此字段值,默认为更新 + + + + + 在执行所有操作时是否忽略此字段,默认不忽略 + + + + + 创建一个空的字段特性 + + + + + 创建一个指定字段名的字段特性 + + 字段名 + + + + 创建一个制定字段名的字段特性 + + 字段名 + 在执行数据操作时是否忽略此字段 + + + + 创建一个制定字段名的字段特性 + + 字段名 + 此字段是否参与插入操作 + 此字段是否参与更新操作 + + + + 数据库表主键生成类型定义 + + + + + 自动增长型 + + + + + GUID型 + + + + + 提前生成并填充 + + + + + 数据库主键字段特性 + + + + + 主键字段名 + + + + + 主键字段名 + + + + + 主键字段生成方式,参考GenerationType定义 + + + + + 创建一个默认的主键特性,字段生成方式为自动增长型 + + + + + 创建一个制定字段名的主键特性,字段生成方式为自动增长型 + + 主键字段名 + + + + 数据库表特性 + + + + + 数据库名 + + + + + 创建一个空的数据库表特性,默认具备自增长键 + + + + + 创建一个制定表明的数据库表特性,默认具备自增长键 + + 数据库表名 + + + + 数据库名 + + + + + 不具备自增长键的表 + + + + + 数据库操作帮助类 + + + + + 通过提供的参数,执行无结果集的数据库操作命令 + 并返回执行数据库操作所影响的行数。 + + 数据库配置对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回通过执行命令所影响的行数 + + + + 通过提供的参数,执行无结果集的数据库操作命令 + 并返回执行数据库操作所影响的行数。 + + 数据库配置对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回通过执行命令所影响的行数 + + + + 通过提供的参数,执行无结果集返回的数据库操作命令 + 并返回执行数据库操作所影响的行数。 + + + e.g.: + int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库连接对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回通过执行命令所影响的行数 + + + + 通过提供的参数,执行无结果集返回的数据库操作命令 + 并返回执行数据库操作所影响的行数。 + + + e.g.: + int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库连接对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回通过执行命令所影响的行数 + + + + 通过提供的参数,执行无结果集返回的数据库操作命令 + 并返回执行数据库操作所影响的行数。 + + + e.g.: + int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库连接对象 + + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回通过执行命令所影响的行数 + + + + 通过提供的参数,执行无结果集返回的数据库操作命令 + 并返回执行数据库操作所影响的行数。 + + + e.g.: + int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库连接对象 + + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + + 返回通过执行命令所影响的行数 + + + + 通过提供的参数,执行无结果集返回的数据库操作命令 + 并返回执行数据库操作所影响的行数。 + + + e.g.: + int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + sql事务对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回通过执行命令所影响的行数 + + + + 通过提供的参数,执行无结果集返回的数据库操作命令 + 并返回执行数据库操作所影响的行数。 + + + e.g.: + int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + sql事务对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回通过执行命令所影响的行数 + + + + 使用提供的参数,执行有结果集返回的数据库操作命令 + 并返回SqlDataReader对象 + + + e.g.: + SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回SqlDataReader对象 + + + + 使用提供的参数,执行有结果集返回的数据库操作命令 + 并返回SqlDataReader对象 + + + e.g.: + SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回SqlDataReader对象 + + + + 使用提供的参数,执行有结果集返回的数据库操作命令 + 并返回SqlDataReader对象 + + + e.g.: + SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 读取完关闭Reader是否同时也关闭数据库连接 + 数据库链接 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回SqlDataReader对象 + + + + 使用提供的参数,执行有结果集返回的数据库操作命令 + 并返回SqlDataReader对象 + + 数据库配置对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回SqlDataReader对象 + + + + 使用提供的参数,执行有结果集返回的数据库操作命令 + 并返回SqlDataReader对象 + + 数据库配置对象 + + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回SqlDataReader对象 + + + + 使用提供的参数,执行有结果集返回的数据库操作命令 + 并返回SqlDataReader对象 + + 数据库配置对象 + 读取完关闭Reader是否同时也关闭数据库连接 + 数据库链接 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回SqlDataReader对象 + + + + 查询数据填充到数据集DataSet中 + + 数据库配置对象 + 执行命令的类型(存储过程或T-SQL,等等) + 命令文本 + 参数数组 + 数据集DataSet对象 + + + + 查询数据填充到数据集DataSet中 + + 数据库配置对象 + 执行命令的类型(存储过程或T-SQL,等等) + 命令文本 + 数据集DataSet对象 + + + + 依靠数据库连接字符串connectionString, + 使用所提供参数,执行返回首行首列命令 + + + e.g.: + Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + + + + 依靠数据库连接字符串connectionString, + 使用所提供参数,执行返回首行首列命令 + + + e.g.: + Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + + + + 依靠数据库连接字符串connectionString, + 使用所提供参数,执行返回首行首列命令 + + + e.g.: + Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库连接对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + + + + 依靠数据库连接字符串connectionString, + 使用所提供参数,执行返回首行首列命令 + + + e.g.: + Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库连接对象 + + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + + + + 依靠数据库连接字符串connectionString, + 使用所提供参数,执行返回首行首列命令 + + + e.g.: + Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库连接对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + + + + 依靠数据库连接字符串connectionString, + 使用所提供参数,执行返回首行首列命令 + + + e.g.: + Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库连接对象 + + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + + + + 依靠数据库连接字符串connectionString, + 使用所提供参数,执行返回首行首列命令 + + + e.g.: + Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + + 数据库配置对象 + 数据库事物对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行 + 执行命令所需的参数数组 + 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + + + + add parameter array to the cache + + Key to the parameter cache + an array of SqlParamters to be cached + + + + 查询缓存参数 + + 使用缓存名称查找值 + 缓存参数数组 + + + + 为即将执行准备一个命令 + + 数据库配置对象 + SqlCommand对象 + SqlConnection对象 + IDbTransaction对象 + 执行命令的类型(存储过程或T-SQL,等等) + 存储过程名称或者T-SQL命令行, e.g. Select * from Products + SqlParameters to use in the command + + + + 根据传入的Key获取配置文件中 + 相应Key的数据库连接字符串 + + + + + + + 用于数据库类型的字符串枚举转换 + + + + + + + + 数据库类型枚举,需要扩展类型可在此添加 + + + + + MSSQL数据库 + + + + + ORACLE数据库 + + + + + ACCESS数据库 + + + + + MYSQL数据库 + + + + + SQLITE数据库 + + + + + 数据生成工厂类 + + + + + 根据数据库连接字符串以及数据库类型创建一个数据库工厂对象 + + 数据库连接字符串 + 数据库类型 + + + + + 数据库类型 + + + + + 连接字符串 + + + + + 参数的前缀字符 + + + + + 根据配置文件中所配置的数据库类型 + 来获取命令参数中的参数符号oracle为":",sqlserver为"@" + + + + + + 根据配置文件中所配置的数据库类型和传入的 + 数据库链接字符串来创建相应数据库连接对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库命令对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库适配器对象 + + + + + + 根据配置文件中所配置的数据库类型 + 和传入的命令对象来创建相应数据库适配器对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库的参数对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库的参数对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库的参数对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库的参数对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库的参数对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库的参数对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库的参数对象 + + + + + + 根据配置文件中所配置的数据库类型 + 和传入的参数来创建相应数据库的参数数组对象 + + + + + + 根据配置文件中所配置的数据库类型 + 来创建相应数据库的事物对象 + + + + + + 创建数据库的事物对象 + + + + + + + 数据库帮助类 + + + + + 根据数据库连接类型名创建一个数据库帮助类 + + + + + + 根据数据库连接类型名创建一个数据库帮助类 + + + + + + + 根据主键ID获取对象 + + 对象类型 + 主键ID + + + + + 插入对象数据 + + 需要插入的数据对象 + + + + + 批量插入对象数据 + + 数据对象类型 + 需要插入的数据对象集合 + + + + + 更新对象数据 + + 数据对象类型 + 需要更新的数据对象集合 + + + + + 批量更新对象数据 + + 数据对象类型 + 需要更新的数据对象集合 + + + + + 删除对象数据 + + 数据对象类型 + 需要删除的数据对象 + + + + + 批量删除对象数据 + + 数据对象类型 + 需要删除的数据对象集合 + + + + + 根据主键ID删除数据 + + 数据对象类型 + 主键ID + + + + + 执行SQL语句 + + SQL命令 + 参数 + + + + + 执行SQL语句 + + SQL命令 + + + + + 根据SQL查询数量 + + SQL命令 + + + + + 根据SQL查询记录数 + + SQL命令 + 参数 + + + + + 根据SQL查询数据 + + 对象类型 + SQL命令 + + + + + 根据SQL查询数据 + + 对象类型 + SQL命令 + 参数 + + + + + 分页查询返回分页对象 + + 对象类型 + SQL命令 + 参数 + + + + + 查询一条数据 + + 对象类型 + SQL命令 + + + + + 查询一条数据 + + 对象类型 + SQL命令 + 参数 + + + + + 开启事务 + + + + + 根据锁定行为开启事物 + + + + + + 提交事务 + + + + + 回滚事务 + + + + + 数据库表操作类型定义 + + + + + 插入操作 + + + + + 更新操作 + + + + + 删除操作 + + + + + 查询操作 + + + + + 获取记录数操作 + + + + + 数据类型转换帮助类 + + + + + 转为Decimal类型 + + + + + + + MSSQL数据库配置类 + + + + + MSSQL关键字集合 + + + + + 获取当前支持的数据库类型 + + + + + 获取对应的数据库参数字符前缀 + + + + + 创建一个数据库参数对象 + + + + + + 根据MSSQL数据库参数获取一个MSSQL的数据库参数对象 + + + + + + 根据当前的全局配置获取一个MSSQL的数据库参数对象 + + + + + 创建一个数据库链接对象 + + + + + + 创建一个数据库命令对象 + + + + + + 创建数据库适配器对象 + + + + + + 根据传入的命令对象创建适配器对象 + + + + + + + 创建数据库参数对象 + + + + + + 检查MSSQL列名是否为数据库的关键字,是则进行格式化,否则返回原列名 + + + + + + + 生成获取自增长列的新添加值的SQL语句 + + + + + + SQL数据库连接参数配置类 + + + + + 数据库连接字符串 + + + + + 数据库主机地址 + + + + + 数据库端口 + + + + + 数据库名 + + + + + 数据库用户名 + + + + + 数据库密码 + + + + + 最小缓存池大小,空则未配置 + + + + + 最大缓存池大小,空则未配置 + + + + + 字符集设置,空则未配置 + + + + + 新建一个MSSQL链接参数对象 + + 数据库主机地址 + 端口号 + 数据库名 + 用户名 + 密码 + + + + 新建一个MSSQL链接参数对象 + + 数据库主机地址 + 端口号 + 数据库名 + 用户名 + 密码 + 字符集 + + + + 新建一个MSSQL链接参数对象 + + 数据库主机地址 + 端口号 + 数据库名 + 用户名 + 密码 + 最小缓存池大小 + 最大缓存池大小 + + + + 新建一个MSSQL链接参数对象 + + 数据库主机地址 + 端口号 + 数据库名 + 用户名 + 密码 + 最小缓存池大小 + 最大缓存池大小 + 字符集 + + + + 将当前参数设置为全局连接参数 + + + + + 输出当前连接参数字符串 + + + + + + 根据当前的变量生成链接字符串 + + 数据库连接参数 + 连接字符串 + + + + ORM配置基类 + + + + + 获取当前支持的数据库类型 + + + + + 获取对应的数据库参数字符前缀 + + + + + 获取数据库连接字符串 + + + + + 创建一个数据库链接对象 + + + + + + 创建一个数据库命令对象 + + + + + + 创建数据库适配器对象 + + + + + + 根据传入的命令对象创建适配器对象 + + + + + + + 打开数据库连接并创建事物对象 + + + + + + 打开数据库连接并创建指定连接行为的事物对象 + + + + + + + 创建数据库参数对象 + + + + + + 根据参数名与值创建数据库参数对象 + + + + + + + + 根据参数名与值及参数值类型创建一个数据库参数对象 + + + + 参数值的数据类型 + + + + + 根据参数名与值及参数输入输出类型创建一个数据库参数对象 + + + + + + + + + 根据参数名,值,参数大小,参数方向类型创建一个参数对象 + + + + + + + + + + + 格式化字段名 + + + + + + + 生成获取自增长列的新添加值的SQL语句 + + + + + + SQLite数据库配置类 + + + + + SQLite关键字集合 + + + + + 获取当前支持的数据库类型 + + + + + 获取对应的数据库参数字符前缀 + + + + + 创建一个数据库参数对象 + + + + + + 根据SQLite数据库参数获取一个MSSQL的数据库参数对象 + + + + + + 根据当前的全局配置获取一个SQLite的数据库参数对象 + + + + + 创建一个数据库链接对象 + + + + + + 创建一个数据库命令对象 + + + + + + 创建数据库适配器对象 + + + + + + 根据传入的命令对象创建适配器对象 + + + + + + + 创建数据库参数对象 + + + + + + 根据参数名与值创建数据库参数对象 + + + + + + + + 检查SQLite列名是否为数据库的关键字,是则进行格式化,否则返回原列名 + + + + + + + 生成获取自增长列的新添加值的SQL语句 + + + + + + SQLite数据库连接参数 + + + + + 数据库连接字符串 + + + + + SQLite数据库路径 + + + + + SQLite数据库密码 + + + + + 创建一个无密码的SQLite数据库参数 + + 数据库文件路径 + + + + 创建一个带密码的SQLite数据库参数 + + + + + + + 将当前参数设置为全局连接参数 + + + + + 输出当前连接参数字符串 + + + + + + 根据当前的变量生成链接字符串 + + 数据库连接参数 + 连接字符串 + + + diff --git a/DLL/Easy4net.dll b/DLL/Easy4net.dll new file mode 100644 index 0000000..a5ac624 Binary files /dev/null and b/DLL/Easy4net.dll differ diff --git a/DLL/Easy4net.dll.config b/DLL/Easy4net.dll.config new file mode 100644 index 0000000..469eec3 --- /dev/null +++ b/DLL/Easy4net.dll.config @@ -0,0 +1,24 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + diff --git a/DLL/FastSocket.Client.dll b/DLL/FastSocket.Client.dll new file mode 100644 index 0000000..41a93b3 Binary files /dev/null and b/DLL/FastSocket.Client.dll differ diff --git a/DLL/FastSocket.SocketBase.dll b/DLL/FastSocket.SocketBase.dll new file mode 100644 index 0000000..75b2888 Binary files /dev/null and b/DLL/FastSocket.SocketBase.dll differ diff --git a/DLL/Framework.Core.dll b/DLL/Framework.Core.dll new file mode 100644 index 0000000..3c75125 Binary files /dev/null and b/DLL/Framework.Core.dll differ diff --git a/DLL/Framework.Protobuf.dll b/DLL/Framework.Protobuf.dll new file mode 100644 index 0000000..8a9dcc3 Binary files /dev/null and b/DLL/Framework.Protobuf.dll differ diff --git a/DLL/Google.Protobuf.dll b/DLL/Google.Protobuf.dll new file mode 100644 index 0000000..53c3b64 Binary files /dev/null and b/DLL/Google.Protobuf.dll differ diff --git a/DLL/Grpc.Core.Api.dll b/DLL/Grpc.Core.Api.dll new file mode 100644 index 0000000..c3ebca6 Binary files /dev/null and b/DLL/Grpc.Core.Api.dll differ diff --git a/DLL/Grpc.Core.dll b/DLL/Grpc.Core.dll new file mode 100644 index 0000000..7edc565 Binary files /dev/null and b/DLL/Grpc.Core.dll differ diff --git a/DLL/HttpHelper.dll b/DLL/HttpHelper.dll new file mode 100644 index 0000000..72b4b3f Binary files /dev/null and b/DLL/HttpHelper.dll differ diff --git a/DLL/ICSharpCode.SharpZipLib.dll b/DLL/ICSharpCode.SharpZipLib.dll new file mode 100644 index 0000000..fe643eb Binary files /dev/null and b/DLL/ICSharpCode.SharpZipLib.dll differ diff --git a/DLL/Interop.MSScriptControl.dll b/DLL/Interop.MSScriptControl.dll new file mode 100644 index 0000000..f3caeae Binary files /dev/null and b/DLL/Interop.MSScriptControl.dll differ diff --git a/DLL/Ionic.Zip.dll b/DLL/Ionic.Zip.dll new file mode 100644 index 0000000..95fa928 Binary files /dev/null and b/DLL/Ionic.Zip.dll differ diff --git a/DLL/JavaScriptEngineSwitcher.Core.dll b/DLL/JavaScriptEngineSwitcher.Core.dll new file mode 100644 index 0000000..9652891 Binary files /dev/null and b/DLL/JavaScriptEngineSwitcher.Core.dll differ diff --git a/DLL/LevelUpdate.exe b/DLL/LevelUpdate.exe new file mode 100644 index 0000000..06e2571 Binary files /dev/null and b/DLL/LevelUpdate.exe differ diff --git a/DLL/LevelUpdate.xml b/DLL/LevelUpdate.xml new file mode 100644 index 0000000..ce4ddb3 --- /dev/null +++ b/DLL/LevelUpdate.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DLL/Microsoft.Owin.Cors.dll b/DLL/Microsoft.Owin.Cors.dll new file mode 100644 index 0000000..a854c4c Binary files /dev/null and b/DLL/Microsoft.Owin.Cors.dll differ diff --git a/DLL/Microsoft.Owin.Cors.xml b/DLL/Microsoft.Owin.Cors.xml new file mode 100644 index 0000000..3a1239c --- /dev/null +++ b/DLL/Microsoft.Owin.Cors.xml @@ -0,0 +1,96 @@ + + + + Microsoft.Owin.Cors + + + + + Extension methods for adding CorsMiddleware to an application pipeline. + + + + + Adds a CORS middleware to your web application pipeline to allow cross domain requests. + + The IAppBuilder passed to your configuration method + An options class that controls the middleware behavior + The original app parameter + + + + Processes requests according to the provided cross domain policy. + + + + + Creates a new instance of CorsMiddleware. + + + + + + + Evaluates and applies the CORS policy. Responses will be generated for preflight requests. + Requests that are permitted by the CORS policy will be passed onto the next middleware. + + + + + + + Contains the options used by the CorsMiddleware + + + + + A policy that allows all headers, all methods, any origin and supports credentials + + + + + The cors policy to apply + + + + + The cors engine + + + + + A pluggable CORS policy provider that always returns null by default. + + + + + Defines how to select a CORS policy for a given request. + + + + + Selects a CORS policy to apply for the given request. + + + The CORS policy to apply to the request, or null if no policy applies and + the request should be passed through to the next middleware. + + + + Creates a new CorsPolicyProvider instance. + + + + + Executes the PolicyResolver unless overridden by a subclass. + + + + + + + A pluggable callback that will be used to select the CORS policy for the given requests. + + + + diff --git a/DLL/Microsoft.Owin.FileSystems.dll b/DLL/Microsoft.Owin.FileSystems.dll new file mode 100644 index 0000000..85616f3 Binary files /dev/null and b/DLL/Microsoft.Owin.FileSystems.dll differ diff --git a/DLL/Microsoft.Owin.FileSystems.xml b/DLL/Microsoft.Owin.FileSystems.xml new file mode 100644 index 0000000..ff4f6b7 --- /dev/null +++ b/DLL/Microsoft.Owin.FileSystems.xml @@ -0,0 +1,148 @@ + + + + Microsoft.Owin.FileSystems + + + + + Looks up files using embedded resources in the specified assembly. + This file system is case sensitive. + + + + + A file system abstraction + + + + + Locate a file at the given path + + The path that identifies the file + The discovered file if any + True if a file was located at the given path + + + + Enumerate a directory at the given path, if any + + The path that identifies the directory + The contents if any + True if a directory was located at the given path + + + + Initializes a new instance of the class using the calling + assembly and empty base namespace. + + + + + Initializes a new instance of the class using the specified + assembly and empty base namespace. + + + + + + Initializes a new instance of the class using the calling + assembly and specified base namespace. + + The base namespace that contains the embedded resources. + + + + Initializes a new instance of the class using the specified + assembly and base namespace. + + The assembly that contains the embedded resources. + The base namespace that contains the embedded resources. + + + + Locate a file at the given path + + The path that identifies the file + The discovered file if any + True if a file was located at the given path + + + + Enumerate a directory at the given path, if any. + This file system uses a flat directory structure. Everything under the base namespace is considered to be one directory. + + The path that identifies the directory + The contents if any + True if a directory was located at the given path + + + + Represents a file in the given file system. + + + + + Return file contents as readonly stream. Caller should dispose stream when complete. + + The file stream + + + + The length of the file in bytes, or -1 for a directory info + + + + + The path to the file, including the file name. Return null if the file is not directly accessible. + + + + + The name of the file + + + + + When the file was last modified + + + + + True for the case TryGetDirectoryContents has enumerated a sub-directory + + + + + Looks up files using the on-disk file system + + + + + Creates a new instance of a PhysicalFileSystem at the given root directory. + + The root directory + + + + Locate a file at the given path by directly mapping path segments to physical directories. + + A path under the root directory + The discovered file, if any + True if a file was discovered at the given path + + + + Enumerate a directory at the given path, if any. + + A path under the root directory + The discovered directories, if any + True if a directory was discovered at the given path + + + + The root directory for this instance. + + + + diff --git a/DLL/Microsoft.Owin.Host.HttpListener.dll b/DLL/Microsoft.Owin.Host.HttpListener.dll new file mode 100644 index 0000000..be5c05a Binary files /dev/null and b/DLL/Microsoft.Owin.Host.HttpListener.dll differ diff --git a/DLL/Microsoft.Owin.Host.HttpListener.xml b/DLL/Microsoft.Owin.Host.HttpListener.xml new file mode 100644 index 0000000..fe00947 --- /dev/null +++ b/DLL/Microsoft.Owin.Host.HttpListener.xml @@ -0,0 +1,140 @@ + + + + Microsoft.Owin.Host.HttpListener + + + + + This class is used to wrap other streams and convert some exception types. + + + + + This wraps HttpListenerRequest's WebHeaderCollection (NameValueCollection) and adapts it to + the OWIN required IDictionary surface area. It remains fully mutable, but you will be subject + to the header validations performed by the underlying collection. + + + + + This wraps HttpListener and exposes it as an OWIN compatible server. + + + + + Creates a listener wrapper that can be configured by the user before starting. + + + + + These are merged as one call because they should be swapped out atomically. + This controls how many requests the server attempts to process concurrently. + + The maximum number of pending request receives. + The maximum number of active requests being processed. + + + + + + + + + + + Sets the maximum number of requests that will be queued up in Http.Sys. + + + + + + Starts the listener and request processing threads. + + + + + Shuts down the listener and disposes it. + + + + + The HttpListener instance wrapped by this wrapper. + + + + + This wraps an HttpListenerRequest and exposes it as an OWIN environment IDictionary. + + + + + Initializes a new instance of the class. + Uses the given request object to populate the OWIN standard keys in the environment IDictionary. + Most values are copied so that they can be mutable, but the headers collection is only wrapped. + + + + + This wraps an HttpListenerResponse, populates it with the given response fields, and relays + the response body to the underlying stream. + + + + + Initializes a new instance of the class. + Sets up the Environment with the necessary request state items. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to The key '{0}' is already present in the dictionary.. + + + + + Looks up a localized string similar to The response headers have already been sent.. + + + + + Implements the Katana setup pattern for the OwinHttpListener server. + + + + + Advertise the capabilities of the server. + + + + + + Creates an OwinHttpListener and starts listening on the given URL. + + The application entry point. + The addresses to listen on. + The OwinHttpListener. Invoke Dispose to shut down. + + + + Standard keys and values for use within the OWIN interfaces + + + + diff --git a/DLL/Microsoft.Owin.Host.SystemWeb.dll b/DLL/Microsoft.Owin.Host.SystemWeb.dll new file mode 100644 index 0000000..4a593d8 Binary files /dev/null and b/DLL/Microsoft.Owin.Host.SystemWeb.dll differ diff --git a/DLL/Microsoft.Owin.Host.SystemWeb.xml b/DLL/Microsoft.Owin.Host.SystemWeb.xml new file mode 100644 index 0000000..f2c4c49 --- /dev/null +++ b/DLL/Microsoft.Owin.Host.SystemWeb.xml @@ -0,0 +1,639 @@ + + + + Microsoft.Owin.Host.SystemWeb + + + + + Locates the startup class based on the following convention: + AssemblyName.Startup, with a method named Configuration + + + + + + + + + + Allows for a fallback loader to be specified. + + + + + + Allows for a fallback loader and a Dependency Injection activator to be specified. + + + + + + + + + + + + + + + Executes the loader, searching for the entry point by name. + + The name of the assembly and type entry point + + + + + + + + + + + + + A default fallback loader that does nothing. + + + + + A placeholder method that always returns null. + + + + null. + + + + A singleton instance of the NullLoader type. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to For the app startup parameter value '{0}', the assembly '{1}' was not found.. + + + + + Looks up a localized string similar to For the app startup parameter value '{0}', the class '{1}' was not found in assembly '{2}'.. + + + + + Looks up a localized string similar to The OwinStartup attribute discovered in assembly '{0}' referencing startup type '{1}' conflicts with the attribute in assembly '{2}' referencing startup type '{3}' because they have the same FriendlyName '{4}'. Remove or rename one of the attributes, or reference the desired type directly.. + + + + + Looks up a localized string similar to The discovered startup type '{0}' conflicts with the type '{1}'. Remove or rename one of the types, or reference the desired type directly.. + + + + + Looks up a localized string similar to The OwinStartupAttribute.FriendlyName value '{0}' does not match the given value '{1}' in Assembly '{2}'.. + + + + + Looks up a localized string similar to No '{0}' method was found in class '{1}'.. + + + + + Looks up a localized string similar to No assembly found containing a Startup or [AssemblyName].Startup class.. + + + + + Looks up a localized string similar to No assembly found containing an OwinStartupAttribute.. + + + + + Looks up a localized string similar to The OwinStartupAttribute.StartupType value is empty in Assembly '{0}'.. + + + + + Looks up a localized string similar to The type '{0}' referenced from assembly '{1}' does not define a property 'StartupType' of type 'Type'.. + + + + + Looks up a localized string similar to The given type or method '{0}' was not found. Try specifying the Assembly.. + + + + + Looks up a localized string similar to The '{0}' method on class '{1}' does not have the expected signature 'void {0}(IAppBuilder)'.. + + + + + This handles cookies that are limited by per cookie length. It breaks down long cookies for responses, and reassembles them + from requests. The cookies are stored in the System.Web object model rather than directly in the headers. + + + + + This handles cookies that are limited by per cookie length. It breaks down long cookies for responses, and reassembles them + from requests. The cookies are stored in the System.Web object model rather than directly in the headers. + + + + + Get the reassembled cookie. Non chunked cookies are returned normally. + Cookies with missing chunks just have their "chunks:XX" header returned. + + + + The reassembled cookie, if any, or null. + + + + Appends a new response cookie to the Set-Cookie header. If the cookie is larger than the given size limit + then it will be broken down into multiple cookies as follows: + Set-Cookie: CookieName=chunks:3; path=/ + Set-Cookie: CookieNameC1=Segment1; path=/ + Set-Cookie: CookieNameC2=Segment2; path=/ + Set-Cookie: CookieNameC3=Segment3; path=/ + + + + + + + + + Deletes the cookie with the given key by setting an expired state. If a matching chunked cookie exists on + the request, delete each chunk. + + + + + + + + A fallback manager used if HttpContextBase can't be located. + + + + + The maximum size of cookie to send back to the client. If a cookie exceeds this size it will be broken down into multiple + cookies. Set this value to null to disable this behavior. The default is 4090 characters, which is supported by all + common browsers. + + Note that browsers may also have limits on the total size of all cookies per domain, and on the number of cookies per domain. + + + + + Throw if not all chunks of a cookie are available on a request for re-assembly. + + + + + Used to provide the data protection services that are derived from the MachineKey API. It is the best choice of + data protection when you application is hosted by ASP.NET and all servers in the farm are running with the same Machine Key values. + + + + + Returns a new instance of IDataProtection for the provider. + + Additional entropy used to ensure protected data may only be unprotected for the correct purposes. + An instance of a data protection service + + + + Provides extension methods for . + + + + + Gets the for the current request. + + + + + + + Gets the for the current request. + + + + + + + Provides extension methods for . + + + + + Gets the for the current request. + + + + + + + Gets the for the current request. + + + + + + + Processes requests from System.Web as OWIN requests. + + + + + Processes requests using the default OWIN application. + + + + + Initiates an asynchronous call to the HTTP handler. + + + An System.Web.HttpContextBase object that provides references to intrinsic server + objects (for example, Request, Response, Session, and Server) used to service + HTTP requests. + + + The System.AsyncCallback to call when the asynchronous method call is complete. + If callback is null, the delegate is not called. + + + Any extra data needed to process the request. + + + An System.IAsyncResult that contains information about the status of the process. + + + + + Provides an asynchronous process End method when the process ends. + + + An System.IAsyncResult that contains information about the status of the process. + + + + + Gets a value indicating whether another request can use the System.Web.IHttpHandler instance. + + + true. + + + + + Processes a route through an OWIN pipeline. + + + + + Initialize an OwinRouteHandler + + The method to initialize the pipeline that processes requests for the route. + + + + Provides the object that processes the request. + + + An object that processes the request. + + An object that encapsulates information about the request. + + + + Registers the OWIN request processing module at application startup. + + + + + Registers the OWIN request processing module. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to The following errors occurred while attempting to load the app.. + + + + + Looks up a localized string similar to Cannot register for 'OnSendingHeaders' event after response headers have been sent.. + + + + + Looks up a localized string similar to The cookie key and options are larger than ChunksSize, leaving no room for data.. + + + + + Looks up a localized string similar to The key '{0}' is already present in the dictionary.. + + + + + Looks up a localized string similar to To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of "false" in your web.config.. + + + + + Looks up a localized string similar to To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.. + + + + + Looks up a localized string similar to The chunked cookie is incomplete. Only {0} of the expected {1} chunks were found, totaling {2} characters. A client size limit may have been exceeded.. + + + + + Looks up a localized string similar to The given stage '{0}' is not supported.. + + + + + Looks up a localized string similar to No owin.Environment item was found in the context.. + + + + + Looks up a localized string similar to An exception was thrown while trying to load the client certificate:. + + + + + Looks up a localized string similar to The OWIN entry point threw an exception:. + + + + + Looks up a localized string similar to The IAsyncResult callback for OwinCallHandler threw an exception:. + + + + + Looks up a localized string similar to Failed to register the OWIN module:. + + + + + Looks up a localized string similar to The application threw one or more exceptions when notified of a client disconnect:. + + + + + Looks up a localized string similar to Shutdown detection setup failed:. + + + + + Looks up a localized string similar to One or more exceptions were thrown during app pool shutdown:. + + + + + Looks up a localized string similar to An exception was thrown from a timer callback:. + + + + + Looks up a localized string similar to An exception was thrown while processing the WebSocket:. + + + + + Looks up a localized string similar to Support for WebSockets has been detected.. + + + + + Looks up a localized string similar to No support for WebSockets has been detected.. + + + + + Provides extension methods for registering OWIN applications as System.Web routes. + + + + + Registers a route for the default OWIN application. + + The route collection. + The route path to map to the default OWIN application. + The created route. + + + + Registers a route for a specific OWIN application entry point. + + The OWIN application entry point type. + The route collection. + The route path to map to the given OWIN application. + The OWIN application entry point. + The created route. + + + + Invokes the System.Action startup delegate to build the OWIN application + and then registers a route for it on the given path. + + The route collection. + The route path to map to the given OWIN application. + A System.Action delegate invoked to build the OWIN application. + The created route. + + + + Registers a route for the default OWIN application. + + The route collection. + The given name of the route. + The route path to map to the default OWIN application. + The created route. + + + + Registers a route for a specific OWIN application entry point. + + The OWIN application entry point type. + The route collection. + The given name of the route. + The route path to map to the given OWIN application. + The OWIN application entry point. + The created route. + + + + Invokes the System.Action startup delegate to build the OWIN application + and then registers a route for it on the given path. + + The route collection. + The given name of the route. + The route path to map to the given OWIN application. + A System.Action delegate invoked to build the OWIN application. + The created route. + + + + Provides a way to define routes for an OWIN pipeline. + + The route collection. + The URL pattern for the route. + The method to initialize the pipeline that processes requests for the route. + + + + Provides a way to define routes for an OWIN pipeline. + + The route collection. + The URL pattern for the route. + The values to use if the URL does not contain all the parameters. + The method to initialize the pipeline that processes requests for the route. + + + + Provides a way to define routes for an OWIN pipeline. + + The route collection. + The URL pattern for the route. + The values to use if the URL does not contain all the parameters. + A regular expression that specifies valid values for a URL parameter. + The method to initialize the pipeline that processes requests for the route. + + + + Provides a way to define routes for an OWIN pipeline. + + The route collection. + The URL pattern for the route. + The values to use if the URL does not contain all the parameters. + A regular expression that specifies valid values for a URL parameter. + Custom values that are passed to the route handler, but which are not used to determine whether the route matches a specific URL pattern. These values are passed to the route handler, where they can be used for processing the request. + The method to initialize the pipeline that processes requests for the route. + + + + Provides a way to define routes for an OWIN pipeline. + + The route collection. + The name of the route. + The URL pattern for the route. + The method to initialize the pipeline that processes requests for the route. + + + + Provides a way to define routes for an OWIN pipeline. + + The route collection. + The name of the route. + The URL pattern for the route. + The values to use if the URL does not contain all the parameters. + The method to initialize the pipeline that processes requests for the route. + + + + Provides a way to define routes for an OWIN pipeline. + + The route collection. + The name of the route. + The URL pattern for the route. + The values to use if the URL does not contain all the parameters. + A regular expression that specifies valid values for a URL parameter. + The method to initialize the pipeline that processes requests for the route. + + + + Provides a way to define routes for an OWIN pipeline. + + The route collection. + The name of the route. + The URL pattern for the route. + The values to use if the URL does not contain all the parameters. + A regular expression that specifies valid values for a URL parameter. + Custom values that are passed to the route handler, but which are not used to determine whether the route matches a specific URL pattern. These values are passed to the route handler, where they can be used for processing the request. + The method to initialize the pipeline that processes requests for the route. + + + + An implementation of ICookieManager that uses the System.Web.HttpContextBase object model. + + + + + Creates a new instance of SystemWebCookieManager. + + + + + Reads the requested cookie from System.Web.HttpContextBase.Request.Cookies. + + + + + + + + Appends the requested cookie to System.Web.HttpContextBase.Response.Cookies. + + + + + + + + + Deletes the requested cookie by appending an expired cookie to System.Web.HttpContextBase.Response.Cookies. + + + + + + + + A fallback manager used if HttpContextBase can't be located. + + + + diff --git a/DLL/Microsoft.Owin.Hosting.dll b/DLL/Microsoft.Owin.Hosting.dll new file mode 100644 index 0000000..204763b Binary files /dev/null and b/DLL/Microsoft.Owin.Hosting.dll differ diff --git a/DLL/Microsoft.Owin.Hosting.xml b/DLL/Microsoft.Owin.Hosting.xml new file mode 100644 index 0000000..748b05f --- /dev/null +++ b/DLL/Microsoft.Owin.Hosting.xml @@ -0,0 +1,1023 @@ + + + + Microsoft.Owin.Hosting + + + + + Locates the startup class based on the following convention: + AssemblyName.Startup, with a method named Configuration + + + + + + + + + + Allows for a fallback loader to be specified. + + + + + + Allows for a fallback loader and a Dependency Injection activator to be specified. + + + + + + + + + + + + + + + Executes the loader, searching for the entry point by name. + + The name of the assembly and type entry point + + + + + + + + + + + + + A default fallback loader that does nothing. + + + + + A placeholder method that always returns null. + + + + null. + + + + A singleton instance of the NullLoader type. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to For the app startup parameter value '{0}', the assembly '{1}' was not found.. + + + + + Looks up a localized string similar to For the app startup parameter value '{0}', the class '{1}' was not found in assembly '{2}'.. + + + + + Looks up a localized string similar to The OwinStartup attribute discovered in assembly '{0}' referencing startup type '{1}' conflicts with the attribute in assembly '{2}' referencing startup type '{3}' because they have the same FriendlyName '{4}'. Remove or rename one of the attributes, or reference the desired type directly.. + + + + + Looks up a localized string similar to The discovered startup type '{0}' conflicts with the type '{1}'. Remove or rename one of the types, or reference the desired type directly.. + + + + + Looks up a localized string similar to The OwinStartupAttribute.FriendlyName value '{0}' does not match the given value '{1}' in Assembly '{2}'.. + + + + + Looks up a localized string similar to No '{0}' method was found in class '{1}'.. + + + + + Looks up a localized string similar to No assembly found containing a Startup or [AssemblyName].Startup class.. + + + + + Looks up a localized string similar to No assembly found containing an OwinStartupAttribute.. + + + + + Looks up a localized string similar to The OwinStartupAttribute.StartupType value is empty in Assembly '{0}'.. + + + + + Looks up a localized string similar to The type '{0}' referenced from assembly '{1}' does not define a property 'StartupType' of type 'Type'.. + + + + + Looks up a localized string similar to The given type or method '{0}' was not found. Try specifying the Assembly.. + + + + + Looks up a localized string similar to The '{0}' method on class '{1}' does not have the expected signature 'void {0}(IAppBuilder)'.. + + + + + Used to instantiate the server factory. + + + + + Used to instantiate the server factory. + + + + + Instantiate an instance of the given type. + + + + + + + + + + + + + Instantiate an instance of the given type. + + + + + + + Located and loads the server factory. + + + + + Used to locate and load the named server factory. + + + + + Used to locate and load the named server factory. + + + + + + + Allows for a Dependency Injection activator to be specified. + + + + + + Executes the loader, searching for the server factory by name. + Acceptable inputs: + - Assembly.Name. Look for type Assembly.Name.ServerFactory in the assembly Assembly.Name. + - Assembly.Name.FactoryName. Look for type Assembly.Name.FactoryName in the assembly Assembly.Name. + + The name of the assembly and type of the server factory + + + + + The basic ServerFactory contract. + + + + + An optional method that allows the server factory to specify its capabilities. + + + + + + Starts a server with the given app instance. + + + + + + + Attempts to find the entry point for an app. + + + + + Attempts to find the entry point for an app. + + + + + Attempts to find the entry point for a given configuration string. + + + + + + + + + + + + + + Attempts to find the entry point for a given configuration string. + + + + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to The following errors occurred while attempting to load the app.. + + + + + Looks up a localized string similar to Failed to resolve an instance of {0} from the IServiceProvider.. + + + + + Looks up a localized string similar to The settings file is improperly formatted. It should consist of one name=value pair per line. Empty lines or lines beginning with '#' are ignored.. + + + + + Looks up a localized string similar to The '{0}' Create method must take two parameters.. + + + + + Looks up a localized string similar to The '{0}' Create method must have a second parameter of type IDictionary<string,object>.. + + + + + Looks up a localized string similar to The server factory could not be located for the given input: {0}. + + + + + The basic ServerFactory contract. + + + + + Creates a wrapper around the given server factory instance. + + + + + + Creates a wrapper around the given server factory type. + + + + + + + Calls the optional Initialize method on the server factory. + The method may be static or instance, and may accept either + an IAppBuilder or the IAppBuilder.Properties IDictionary<string, object>. + + + + + + Calls the Create method on the server factory. + The method may be static or instance, and may accept the AppFunc and the + IAppBuilder.Properties IDictionary<string, object>. + + + + + + + Helper code for the various activator services. + + + + + Retrieve an instance of the given type from the service provider. If one is not found then instantiate it directly. + + + + + + + + Instantiate an object of the given type, using constructor service injection if possible. + + + + + + + + Creates a factory to instantiate a type using constructor service injection if possible. + + + + + + + Used to instantiate the application entry point. e.g. the Startup class. + + + + + Used to instantiate the application entry point. e.g. the Startup class. + + + + + Instantiate an instance of the given type. + + + + + + + Creates a new AppActivator. + + + + + + Instantiate an instance of the given type, injecting any available services. + + + + + + + Provides an IAppBuilder instance based on Microsoft.Owin.Builder.AppBuilder. + + + + + Provides an IAppBuilder instance. + + + + + Create a new IAppBuilder instance. + + + + + + Create a new IAppBuilder instance based on Microsoft.Owin.Builder.AppBuilder. + + + + + + Initializes a new app loader. + + + + + Initializes a new app loader. + + + + + Create a new chained app loader. + + + + + + + Not currently used. + + + + + + + + + + + Create a new chained app loader. + + + + + + + Not currently used. + + + + + Create a default ServiceProvider with input from a variety or sources. + + + + + Create a default ServiceProvider with the given settings. + + + + + + + + Create a default ServiceProvider with the given settings file. + + + + + + + + Create a default ServiceProvider. + + + + + + + Create a default ServiceProvider with the given settings. + + + + + + + Create a default ServiceProvider with the given settings file. + + + + + + + Create a default ServiceProvider. + + + + + + Enumerate the default service types with the given settings overrides. + + + + + + + Enumerate the default service types with the given settings file overrides. + + + + + + + Enumerate the default service types. + + + + + + Loads settings from various locations. + + + + + Load settings from the AppSettings section of the config file. + + + + + + Load settings from the AppSettings section of the config file. + + + + + + Load settings from a flat text file. + + + + + + + Load settings from a flat text file. + + + + + + + Extension methods for IServiceProvider. + + + + + Retrieve a service of type T from the IServiceProvider. + + + + + + + + The default IServiceProvider. + + + + + + + + + + Gets the service object of the specified type. + + + + + + + Remove all occurrences of the given type from the provider. + + + + + + + Remove all occurrences of the given type from the provider. + + + + + + + Add an instance of type TService to the list of providers. + + + + + + + + Add an instance of the given type to the list of providers. + + + + + + + + Specify that services of the type TService should be fulfilled by the type TImplementation. + + + + + + + + Specify that services of the type serviceType should be fulfilled by the type implementationType. + + + + + + + + Specify that services of the given type should be created with the given serviceFactory. + + + + + + + + Opens a stream writer for the given file. + + + + + Used to create the trace output. + + + + + Used to create the trace output. + + + + + + + Opens a stream writer for the given file. + + + + + + + Instantiates instances of the IHostingStarter. + + + + + Instantiates instances of the IHostingStarter. + + + + + Instantiates instances of the IHostingStarter. + + + + + + + + + + + + + Instantiates instances of the IHostingStarter. + + + + + + + Executes the IHostingEngine without making any changes to the current execution environment. + + + + + Performs any necessary environment setup prior to executing the IHostingEngine. + + + + + Performs any necessary environment setup prior to executing the IHostingEngine. + + + + + + + + + + + + + Executes the IHostingEngine without making any changes to the current execution environment. + + + + + + + Used for executing the IHostingEngine in a new AppDomain. + + + + + Registers a fallback assembly resolver that looks in the given directory. + + + + + + Executes the IHostingEngine in a new AppDomain. + + + + + + + + + + + + + + + + + Renews the given lease for 5 minutes. + + + + + + + Creates a new AppDomain to run the IHostingEngine in. + + + + + Creates a new AppDomain to run the IHostingEngine in. + + + + + + + This attribute is used to identify custom hosting starters that may be loaded at runtime. + + + + + + + + + + + + + + + + Creates a IHostingStarter for the given identifier. + + + + + Creates a IHostingStarter for the given identifier. + + + + + + + Selects from known hosting starters, or detects additional providers via convention. + + + + + + + + + + + Selects from known hosting starters, or detects additional providers via convention. + + + + + + + These methods are used to load, assemble, and start a web app. + + + + + Start a web app using default settings and the given url and entry point. + e.g. Discover the ServerFactory and run at the given url. + + An IDisposible instance that can be called to shut down the web app. + + + + Start a web app using the given settings and entry point, using defaults for items not specified. + + An IDisposible instance that can be called to shut down the web app. + + + + Start a web app using default settings and the given url and entry point type. + e.g. Discover the ServerFactory and run at the given url. + + An IDisposible instance that can be called to shut down the web app. + + + + Start a web app using the given settings and entry point type, using defaults for items not specified. + + An IDisposible instance that can be called to shut down the web app. + + + + Start a web app using the given settings and entry point type, using defaults for items not specified. + + An IDisposible instance that can be called to shut down the web app. + + + + Start a web app using the given settings and entry point type, using defaults for items not specified. + + An IDisposible instance that can be called to shut down the web app. + + + + Settings to control the startup behavior of an OWIN application + + + + + Initializes a new instance of the class + + + + + Initializes a new instance of the class + + + + + A list of url prefixes to listen on. Overrides port. + + + + + A port to listen on. + + + + + Parameter to locate and load web application startup routine + + + + + Name of the assembly containing the http server implementation + + + + + Optional settings used to override service types and other defaults + + + + + Initializes and starts a web application. + + + + + Initializes and starts a web application. + + + + + + + Determines the which IHostingStarter instance to use via the IHostingSterterFactory. + + + + + + + + + + + Determines the which IHostingStarter instance to use via the IHostingSterterFactory. + + + + + + + Used to initialize and start a web application. + + + + + + + + + + + + + + + Initialize and start a web application. + Major Steps: + - Find and initialize the ServerFactory + - Find and initialize the application + - Start the server + + + + + + + Tries to determine a custom port setting from the startup options or the port environment variable. + + The OWIN application startup options. + The port number. + True if a valid custom port was set, false if not. + + + + Gets the default port number. + + The default port number. + + + + This class contains the relevant application and server state during startup. + + + + + Create a new StartContext with the given options. + If the given options do not define any settings, then settings will be loaded from the config. + + + + + + The initial options provided to the constructor. + + + + + The factory used to instantiate the server. + + + + + The IAppBuilder used to construct the OWIN application pipeline. + + + + + The constructed OWIN application pipeline. + + + + + The application entry point where the pipeline is defined. + + + + + A TextWriter for writing diagnostic data to. + + + + + A list of keys and their associated values that will be injected by the host into each OWIN request environment. + + + + diff --git a/DLL/Microsoft.Owin.StaticFiles.dll b/DLL/Microsoft.Owin.StaticFiles.dll new file mode 100644 index 0000000..39c31ae Binary files /dev/null and b/DLL/Microsoft.Owin.StaticFiles.dll differ diff --git a/DLL/Microsoft.Owin.StaticFiles.xml b/DLL/Microsoft.Owin.StaticFiles.xml new file mode 100644 index 0000000..c880c3e --- /dev/null +++ b/DLL/Microsoft.Owin.StaticFiles.xml @@ -0,0 +1,559 @@ + + + + Microsoft.Owin.StaticFiles + + + + + Provides a mapping between file extensions and MIME types. + + + + + Used to look up MIME types given a file path + + + + + Given a file path, determine the MIME type + + A file path + The resulting MIME type + True if MIME type could be determined + + + + Creates a new provider with a set of default mappings. + + + + + Creates a lookup engine using the provided mapping. + It is recommended that the IDictionary instance use StringComparer.OrdinalIgnoreCase. + + + + + + Given a file path, determine the MIME type + + A file path + The resulting MIME type + True if MIME type could be determined + + + + The cross reference table of file extensions and content-types. + + + + + Generates an HTML view for a directory. + + + + + Generates the view for a directory + + + + + Generates the view for a directory. + Implementers should properly handle HEAD requests. + Implementers should set all necessary response headers (e.g. Content-Type, Content-Length, etc.). + + + + + Generates an HTML view for a directory. + + + + + Options for selecting default file names. + + + + + Options common to several middleware components + + The type of the subclass + + + + Creates an new instance of the SharedOptionsBase. + + + + + + Options common to several middleware components + + + + + The relative request path that maps to static resources. + + + + + The file system used to locate resources + + + + + Configuration for the DefaultFilesMiddleware. + + + + + Configuration for the DefaultFilesMiddleware. + + + + + + An ordered list of file names to select by default. List length and ordering may affect performance. + + + + + Directory browsing options + + + + + Enabled directory browsing in the current physical directory for all request paths + + + + + Enabled directory browsing in the current physical directory for all request paths + + + + + + The component that generates the view. + + + + + Options common to several middleware components + + + + + Defaults to all request paths and the current physical directory. + + + + + The request path that maps to static resources + + + + + The file system used to locate resources + + + + + Options for all of the static file middleware components + + + + + Creates a combined options class for all of the static file middleware components. + + + + + Options for configuring the StaticFileMiddleware. + + + + + Options for configuring the DirectoryBrowserMiddleware. + + + + + Options for configuring the DefaultFilesMiddleware. + + + + + Directory browsing is disabled by default. + + + + + Default files are enabled by default. + + + + + Extension methods that combine all of the static file middleware components: + Default files, directory browsing, send file, and static files + + + + + Enable all static file middleware (except directory browsing) for the current request path in the current directory. + + + + + + + Enable all static file middleware on for the current request path in the current directory. + + + Should directory browsing be enabled? + + + + + Enables all static file middleware (except directory browsing) for the given request path from the directory of the same name + + + The relative request path and physical path. + + + + + Enable all static file middleware with the given options + + + + + + + + Extension methods for the DefaultFilesMiddleware + + + + + Enables default file mapping on the current path from the current directory + + + + + + + Enables default file mapping for the given request path from the directory of the same name + + + The relative request path and physical path. + + + + + Enables default file mapping with the given options + + + + + + + + This examines a directory path and determines if there is a default file present. + If so the file name is appended to the path and execution continues. + Note we don't just serve the file because it may require interpretation. + + + + + Creates a new instance of the DefaultFilesMiddleware. + + The next middleware in the pipeline. + The configuration options for this middleware. + + + + This examines the request to see if it matches a configured directory, and if there are any files with the + configured default names in that directory. If so this will append the corresponding file name to the request + path for a later middleware to handle. + + The request environment. + + + + + Enables directory browsing + + + + + Creates a new instance of the SendFileMiddleware. + + The next middleware in the pipeline. + The configuration for this middleware. + + + + Examines the request to see if it matches a configured directory. If so, a view of the directory contents is returned. + + The request environment. + + + + + Extension methods for the DirectoryBrowserMiddleware + + + + + Enable directory browsing on the current path for the current directory + + + + + + + Enables directory browsing for the given request path from the directory of the same name + + + The relative request path and physical path. + + + + + Enable directory browsing with the given options + + + + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to No IContentTypeProvider was specified.. + + + + + Looks up a localized string similar to No formatter provided.. + + + + + Looks up a localized string similar to This server does not support the sendfile.SendAsync extension.. + + + + + Looks up a localized string similar to Index of. + + + + + Looks up a localized string similar to Last Modified. + + + + + Looks up a localized string similar to Modified. + + + + + Looks up a localized string similar to Name. + + + + + Looks up a localized string similar to Size. + + + + + Looks up a localized string similar to The list of files in the given directory. Column headers are listed in the first row.. + + + + + This middleware provides an efficient fallback mechanism for sending static files + when the server does not natively support such a feature. + The caller is responsible for setting all headers in advance. + The caller is responsible for performing the correct impersonation to give access to the file. + + + + + Creates a new instance of the SendFileMiddleware. + + The next middleware in the pipeline. + + + + Adds the sendfile.SendAsync Func to the request environment, if not already present. + + OWIN environment dictionary which stores state information about the request, response and relevant server state. + + + + + Extension methods for the SendFileMiddleware + + + + + Provide a SendFileFunc if another component does not. + + + + + + + Provides extensions for IOwinResponse exposing the SendFile extension. + + + + + Checks if the SendFile extension is supported. + + + True if sendfile.SendAsync is defined in the environment. + + + + Sends the given file using the SendFile extension. + + + + + + + + Sends the given file using the SendFile extension. + + + The full or relative path to the file. + The offset in the file. + The number of types to send, or null to send the remainder of the file. + + + + + + Extension methods for the StaticFileMiddleware + + + + + Enables static file serving for the current request path from the current directory + + + + + + + Enables static file serving for the given request path from the directory of the same name + + + The relative request path and physical path. + + + + + Enables static file serving with the given options + + + + + + + + Enables serving static files for a given request path + + + + + Creates a new instance of the StaticFileMiddleware. + + The next middleware in the pipeline. + The configuration options. + + + + Processes a request to determine if it matches a known file, and if so, serves it. + + OWIN environment dictionary which stores state information about the request, response and relevant server state. + + + + + Options for serving static files + + + + + Defaults to all request paths in the current physical directory + + + + + Defaults to all request paths in the current physical directory + + + + + + Used to map files to content-types. + + + + + The default content type for a request if the ContentTypeProvider cannot determine one. + None is provided by default, so the client must determine the format themselves. + http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7 + + + + + If the file is not a recognized content-type should it be served? + Default: false. + + + + + Called after the status code and headers have been set, but before the body has been written. + This can be used to add or change the response headers. + + + + + Contains information about the request and the file that will be served in response. + + + + + The request and response information. + + + + + The file to be served. + + + + diff --git a/DLL/Microsoft.Owin.dll b/DLL/Microsoft.Owin.dll new file mode 100644 index 0000000..f9cd1a4 Binary files /dev/null and b/DLL/Microsoft.Owin.dll differ diff --git a/DLL/Microsoft.Owin.xml b/DLL/Microsoft.Owin.xml new file mode 100644 index 0000000..15c340b --- /dev/null +++ b/DLL/Microsoft.Owin.xml @@ -0,0 +1,3289 @@ + + + + Microsoft.Owin + + + + + Extension methods for . + + + + + Inserts a middleware into the OWIN pipeline. + + The middleware type + + Any additional arguments for the middleware constructor + + + + + Inserts into the OWIN pipeline a middleware which does not have a next middleware reference. + + + An app that handles all requests + + + + Inserts a middleware into the OWIN pipeline. + + + An app that handles the request or calls the given next Func + + + + + Represents a middleware for executing in-line function middleware. + + + + + Initializes a new instance of the class. + + The pointer to next middleware. + A function that handles all requests. + + + + Initializes a new instance of the class. + + The pointer to next middleware. + A function that handles the request or calls the given next function. + + + + Invokes the handler for processing the request. + + The OWIN context. + The object that represents the request operation. + + + + Contains the parsed form values. + + + + + Accessors for query, forms, etc. + + + + + Accessors for headers, query, forms, etc. + + + + + Get the associated value from the collection. Multiple values will be merged. + Returns null if the key is not present. + + + + + + + Get the associated values from the collection in their original format. + Returns null if the key is not present. + + + + + + + Get the associated value from the collection. Multiple values will be merged. + Returns null if the key is not present. + + + + + + + Create a new wrapper + + + + + + Get the associated value from the collection. Multiple values will be merged. + Returns null if the key is not present. + + + + + + + Get the associated values from the collection in their original format. + Returns null if the key is not present. + + + + + + + + + + + + + + + + + + + Get the associated value from the collection. Multiple values will be merged. + Returns null if the key is not present. + + + + + + + Contains the parsed form values. + + + + + Initializes a new instance of the class. + + The store for the form. + + + + Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders. + + + + + Represents a wrapper for owin.RequestHeaders and owin.ResponseHeaders. + + + + + Get the associated values from the collection separated into individual values. + Quoted values will not be split, and the quotes will be removed. + + The header name. + the associated values from the collection separated into individual values, or null if the key is not present. + + + + Add a new value. Appends to the header if already present + + The header name. + The header value. + + + + Add new values. Each item remains a separate array entry. + + The header name. + The header values. + + + + Quotes any values containing comas, and then coma joins all of the values with any existing values. + + The header name. + The header values. + + + + Sets a specific header value. + + The header name. + The header value. + + + + Sets the specified header values without modification. + + The header name. + The header values. + + + + Quotes any values containing comas, and then coma joins all of the values. + + The header name. + The header values. + + + + Get or sets the associated value from the collection as a single string. + + The header name. + the associated value from the collection as a single string or null if the key is not present. + + + + Initializes a new instance of the class. + + The underlying data store. + + + + Returns an enumerator that iterates through a collection. + + An object that can be used to iterate through the collection. + + + + Returns an enumerator that iterates through a collection. + + An object that can be used to iterate through the collection. + + + + Get the associated value from the collection as a single string. + + The header name. + the associated value from the collection as a single string or null if the key is not present. + + + + Get the associated values from the collection without modification. + + The header name. + the associated value from the collection without modification, or null if the key is not present. + + + + Get the associated values from the collection separated into individual values. + Quoted values will not be split, and the quotes will be removed. + + The header name. + the associated values from the collection separated into individual values, or null if the key is not present. + + + + Add a new value. Appends to the header if already present + + The header name. + The header value. + + + + Add new values. Each item remains a separate array entry. + + The header name. + The header values. + + + + Quotes any values containing comas, and then coma joins all of the values with any existing values. + + The header name. + The header values. + + + + Sets a specific header value. + + The header name. + The header value. + + + + Sets the specified header values without modification. + + The header name. + The header values. + + + + Quotes any values containing comas, and then coma joins all of the values. + + The header name. + The header values. + + + + Adds the given header and values to the collection. + + The header name. + The header values. + + + + Determines whether the contains a specific key. + + The key. + true if the contains a specific key; otherwise, false. + + + + Removes the given header from the collection. + + The header name. + true if the specified object was removed from the collection; otherwise, false. + + + + Retrieves a value from the dictionary. + + The header name. + The value. + true if the contains the key; otherwise, false. + + + + Adds a new list of items to the collection. + + The item to add. + + + + Clears the entire list of objects. + + + + + Returns a value indicating whether the specified object occurs within this collection. + + The item. + true if the specified object occurs within this collection; otherwise, false. + + + + Copies the elements to a one-dimensional Array instance at the specified index. + + The one-dimensional Array that is the destination of the specified objects copied from the . + The zero-based index in at which copying begins. + + + + Removes the given item from the the collection. + + The item. + true if the specified object was removed from the collection; otherwise, false. + + + + Gets an that contains the keys in the ;. + + An that contains the keys in the . + + + + + + + + + Gets the number of elements contained in the ;. + + The number of elements contained in the . + + + + Gets a value that indicates whether the is in read-only mode. + + true if the is in read-only mode; otherwise, false. + + + + Get or sets the associated value from the collection as a single string. + + The header name. + the associated value from the collection as a single string or null if the key is not present. + + + + Throws KeyNotFoundException if the key is not present. + + The header name. + + + + + Represents the host portion of a Uri can be used to construct Uri's properly formatted and encoded for use in + HTTP headers. + + + + + Creates a new HostString without modification. The value should be Unicode rather than punycode, and may have a port. + IPv4 and IPv6 addresses are also allowed, and also may have ports. + + + + + + Returns the value as normalized by ToUriComponent(). + + + + + + Returns the value properly formatted and encoded for use in a URI in a HTTP header. + Any Unicode is converted to punycode. IPv6 addresses will have brackets added if they are missing. + + + + + + Creates a new HostString from the given uri component. + Any punycode will be converted to Unicode. + + + + + + + Creates a new HostString from the host and port of the give Uri instance. + Punycode will be converted to Unicode. + + + + + + + Compares the equality of the Value property, ignoring case. + + + + + + + Compares against the given object only if it is a HostString. + + + + + + + Gets a hash code for the value. + + + + + + Compares the two instances for equality. + + + + + + + + Compares the two instances for inequality. + + + + + + + + Returns the original value from the constructor. + + + + + An implementation of ICookieManager that writes directly to IOwinContext.Response.Cookies. + + + + + An abstraction for reading request cookies and writing response cookies. + + + + + Read a cookie with the given name from the request. + + + + + + + + Append a cookie to the response. + + + + + + + + + Append a delete cookie to the response. + + + + + + + + Read a cookie with the given name from the request. + + + + + + + + Appends a new response cookie to the Set-Cookie header. + + + + + + + + + Deletes the cookie with the given key by appending an expired cookie. + + + + + + + + This handles cookies that are limited by per cookie length. It breaks down long cookies for responses, and reassembles them + from requests. + + + + + Creates a new instance of ChunkingCookieManager. + + + + + Get the reassembled cookie. Non chunked cookies are returned normally. + Cookies with missing chunks just have their "chunks:XX" header returned. + + + + The reassembled cookie, if any, or null. + + + + Appends a new response cookie to the Set-Cookie header. If the cookie is larger than the given size limit + then it will be broken down into multiple cookies as follows: + Set-Cookie: CookieName=chunks:3; path=/ + Set-Cookie: CookieNameC1=Segment1; path=/ + Set-Cookie: CookieNameC2=Segment2; path=/ + Set-Cookie: CookieNameC3=Segment3; path=/ + + + + + + + + + Deletes the cookie with the given key by setting an expired state. If a matching chunked cookie exists on + the request, delete each chunk. + + + + + + + + The maximum size of cookie to send back to the client. If a cookie exceeds this size it will be broken down into multiple + cookies. Set this value to null to disable this behavior. The default is 4090 characters, which is supported by all + common browsers. + + Note that browsers may also have limits on the total size of all cookies per domain, and on the number of cookies per domain. + + + + + Throw if not all chunks of a cookie are available on a request for re-assembly. + + + + + This wraps OWIN environment dictionary and provides strongly typed accessors. + + + + + Gets a value from the OWIN environment, or returns default(T) if not present. + + The type of the value. + The key of the value to get. + The value with the specified key or the default(T) if not present. + + + + Sets the given key and value in the OWIN environment. + + The type of the value. + The key of the value to set. + The value to set. + This instance. + + + + Gets a wrapper exposing request specific properties. + + A wrapper exposing request specific properties. + + + + Gets a wrapper exposing response specific properties. + + A wrapper exposing response specific properties. + + + + Gets the Authentication middleware functionality available on the current request. + + The authentication middleware functionality available on the current request. + + + + Gets the OWIN environment. + + The OWIN environment. + + + + Gets or sets the host.TraceOutput environment value. + + The host.TraceOutput TextWriter. + + + + This wraps OWIN environment dictionary and provides strongly typed accessors. + + + + + Asynchronously reads and parses the request body as a form. + + The parsed form data. + + + + Gets a value from the OWIN environment, or returns default(T) if not present. + + The type of the value. + The key of the value to get. + The value with the specified key or the default(T) if not present. + + + + Sets the given key and value in the OWIN environment. + + The type of the value. + The key of the value to set. + The value to set. + This instance. + + + + Gets the OWIN environment. + + The OWIN environment. + + + + Gets the request context. + + The request context. + + + + Gets or set the HTTP method. + + The HTTP method. + + + + Gets or set the HTTP request scheme from owin.RequestScheme. + + The HTTP request scheme from owin.RequestScheme. + + + + Returns true if the owin.RequestScheme is https. + + true if this request is using https; otherwise, false. + + + + Gets or set the Host header. May include the port. + + The Host header. + + + + Gets or set the owin.RequestPathBase. + + The owin.RequestPathBase. + + + + Gets or set the request path from owin.RequestPath. + + The request path from owin.RequestPath. + + + + Gets or set the query string from owin.RequestQueryString. + + The query string from owin.RequestQueryString. + + + + Gets the query value collection parsed from owin.RequestQueryString. + + The query value collection parsed from owin.RequestQueryString. + + + + Gets the uniform resource identifier (URI) associated with the request. + + The uniform resource identifier (URI) associated with the request. + + + + Gets or set the owin.RequestProtocol. + + The owin.RequestProtocol. + + + + Gets the request headers. + + The request headers. + + + + Gets the collection of Cookies for this request. + + The collection of Cookies for this request. + + + + Gets or sets the Content-Type header. + + The Content-Type header. + + + + Gets or sets the Cache-Control header. + + The Cache-Control header. + + + + Gets or sets the Media-Type header. + + The Media-Type header. + + + + Gets or set the Accept header. + + The Accept header. + + + + Gets or set the owin.RequestBody Stream. + + The owin.RequestBody Stream. + + + + Gets or sets the cancellation token for the request. + + The cancellation token for the request. + + + + Gets or set the server.LocalIpAddress. + + The server.LocalIpAddress. + + + + Gets or set the server.LocalPort. + + The server.LocalPort. + + + + Gets or set the server.RemoteIpAddress. + + The server.RemoteIpAddress. + + + + Gets or set the server.RemotePort. + + The server.RemotePort. + + + + Gets or set the server.User. + + The server.User. + + + + This wraps OWIN environment dictionary and provides strongly typed accessors. + + + + + Registers for an event that fires when the response headers are sent. + + The callback method. + The callback state. + + + + Sets a 302 response status code and the Location header. + + The location where to redirect the client. + + + + Writes the given text to the response body stream using UTF-8. + + The response data. + + + + Writes the given bytes to the response body stream. + + The response data. + + + + Writes the given bytes to the response body stream. + + The response data. + The zero-based byte offset in the parameter at which to begin copying bytes. + The number of bytes to write. + + + + Asynchronously writes the given text to the response body stream using UTF-8. + + The response data. + A Task tracking the state of the write operation. + + + + Asynchronously writes the given text to the response body stream using UTF-8. + + The response data. + A token used to indicate cancellation. + A Task tracking the state of the write operation. + + + + Asynchronously writes the given bytes to the response body stream. + + The response data. + A Task tracking the state of the write operation. + + + + Asynchronously writes the given bytes to the response body stream. + + The response data. + A token used to indicate cancellation. + A Task tracking the state of the write operation. + + + + Asynchronously writes the given bytes to the response body stream. + + The response data. + The zero-based byte offset in the parameter at which to begin copying bytes. + The number of bytes to write. + A token used to indicate cancellation. + A Task tracking the state of the write operation. + + + + Gets a value from the OWIN environment, or returns default(T) if not present. + + The type of the value. + The key of the value to get. + The value with the specified key or the default(T) if not present. + + + + Sets the given key and value in the OWIN environment. + + The type of the value. + The key of the value to set. + The value to set. + This instance. + + + + Gets the OWIN environment. + + The OWIN environment. + + + + Gets the request context. + + The request context. + + + + Gets or sets the optional owin.ResponseStatusCode. + + The optional owin.ResponseStatusCode, or 200 if not set. + + + + Gets or sets the the optional owin.ResponseReasonPhrase. + + The the optional owin.ResponseReasonPhrase. + + + + Gets or sets the owin.ResponseProtocol. + + The owin.ResponseProtocol. + + + + Gets the response header collection. + + The response header collection. + + + + Gets a collection used to manipulate the Set-Cookie header. + + A collection used to manipulate the Set-Cookie header. + + + + Gets or sets the Content-Length header. + + The Content-Length header. + + + + Gets or sets the Content-Type header. + + The Content-Type header. + + + + Gets or sets the Expires header. + + The Expires header. + + + + Gets or sets the E-Tag header. + + The E-Tag header. + + + + Gets or sets the owin.ResponseBody Stream. + + The owin.ResponseBody Stream. + + + + Used to mark which class in an assembly should be used for automatic startup. + + + + + Initializes a new instance of the class + + The startup class + + + + Initializes a new instance of the class + + A non-default configuration, e.g. staging. + The startup class + + + + Initializes a new instance of the class + + The startup class + Specifies which method to call + + + + Initializes a new instance of the class + + A non-default configuration, e.g. staging. + The startup class + Specifies which method to call + + + + A non-default configuration if any. e.g. Staging. + + + + + The startup class + + + + + The name of the configuration method + + + + + An ordered list of known Asp.Net integrated pipeline stages. More details on the ASP.NET integrated pipeline can be found at http://msdn.microsoft.com/en-us/library/system.web.httpapplication.aspx + + + + + Corresponds to the AuthenticateRequest stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the PostAuthenticateRequest stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the AuthorizeRequest stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the PostAuthorizeRequest stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the ResolveRequestCache stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the PostResolveRequestCache stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the MapRequestHandler stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the PostMapRequestHandler stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the AcquireRequestState stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the PostAcquireRequestState stage of the ASP.NET integrated pipeline. + + + + + Corresponds to the PreRequestHandlerExecute stage of the ASP.NET integrated pipeline. + + + + + Extension methods for the MapMiddleware + + + + + If the request path starts with the given pathMatch, execute the app configured via configuration parameter instead of + continuing to the next component in the pipeline. + + + The path to match + The branch to take for positive path matches + + + + + If the request path starts with the given pathMatch, execute the app configured via configuration parameter instead of + continuing to the next component in the pipeline. + + + The path to match + The branch to take for positive path matches + + + + + Used to create path based branches in your application pipeline. + The owin.RequestPathBase is not included in the evaluation, only owin.RequestPath. + Matching paths have the matching piece removed from owin.RequestPath and added to the owin.RequestPathBase. + + + + + Initializes a new instance of the class + + The normal pipeline taken for a negative match + + + + + Process an individual request. + + + + + + + Options for the Map middleware + + + + + The path to match + + + + + The branch taken for a positive match + + + + + Extension methods for the MapWhenMiddleware + + + + + Branches the request pipeline based on the result of the given predicate. + + + Invoked with the request environment to determine if the branch should be taken + Configures a branch to take + + + + + Branches the request pipeline based on the async result of the given predicate. + + + Invoked asynchronously with the request environment to determine if the branch should be taken + Configures a branch to take + + + + + Determines if the request should take a specific branch of the pipeline by passing the environment + to a user defined callback. + + + + + Initializes a new instance of the class + + The normal application pipeline + + + + + Process an individual request. + + + + + + + Options for the MapWhen middleware + + + + + The user callback that determines if the branch should be taken + + + + + The async user callback that determines if the branch should be taken + + + + + The branch taken for a positive match + + + + + This wraps OWIN environment dictionary and provides strongly typed accessors. + + + + + Create a new context with only request and response header collections. + + + + + Create a new wrapper. + + OWIN environment dictionary which stores state information about the request, response and relevant server state. + + + + Gets a value from the OWIN environment, or returns default(T) if not present. + + The type of the value. + The key of the value to get. + The value with the specified key or the default(T) if not present. + + + + Sets the given key and value in the OWIN environment. + + The type of the value. + The key of the value to set. + The value to set. + This instance. + + + + Gets a wrapper exposing request specific properties. + + A wrapper exposing request specific properties. + + + + Gets a wrapper exposing response specific properties. + + A wrapper exposing response specific properties. + + + + Gets the Authentication middleware functionality available on the current request. + + The authentication middleware functionality available on the current request. + + + + Gets the OWIN environment. + + The OWIN environment. + + + + Gets or sets the host.TraceOutput environment value. + + The host.TraceOutput TextWriter. + + + + Provides correct escaping for Path and PathBase values when needed to reconstruct a request or redirect URI string + + + + + Represents the empty path. This field is read-only. + + + + + Initialize the path string with a given value. This value must be in un-escaped format. Use + PathString.FromUriComponent(value) if you have a path value which is in an escaped format. + + The unescaped path to be assigned to the Value property. + + + + Provides the path string escaped in a way which is correct for combining into the URI representation. + + The escaped path value + + + + Provides the path string escaped in a way which is correct for combining into the URI representation. + + The escaped path value + + + + Returns an PathString given the path as it is escaped in the URI format. The string MUST NOT contain any + value that is not a path. + + The escaped path as it appears in the URI format. + The resulting PathString + + + + Returns an PathString given the path as from a Uri object. Relative Uri objects are not supported. + + The Uri object + The resulting PathString + + + + Checks if this instance starts with or exactly matches the other instance. Only full segments are matched. + + + + + + + Checks if this instance starts with or exactly matches the other instance. Only full segments are matched. + + + Any remaining segments from this instance not included in the other instance. + + + + + Adds two PathString instances into a combined PathString value. + + The combined PathString value + + + + Combines a PathString and QueryString into the joined URI formatted string value. + + The joined URI formatted string value + + + + Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase. + + The second PathString for comparison. + True if both PathString values are equal + + + + Compares this PathString value to another value using a specific StringComparison type + + The second PathString for comparison + The StringComparison type to use + True if both PathString values are equal + + + + Compares this PathString value to another value. The default comparison is StringComparison.OrdinalIgnoreCase. + + The second PathString for comparison. + True if both PathString values are equal + + + + Returns the hash code for the PathString value. The hash code is provided by the OrdinalIgnoreCase implementation. + + The hash code + + + + Operator call through to Equals + + The left parameter + The right parameter + True if both PathString values are equal + + + + Operator call through to Equals + + The left parameter + The right parameter + True if both PathString values are not equal + + + + Operator call through to Add + + The left parameter + The right parameter + The PathString combination of both values + + + + Operator call through to Add + + The left parameter + The right parameter + The PathString combination of both values + + + + The unescaped path value + + + + + True if the path is not empty + + + + + Provides correct handling for QueryString value when needed to reconstruct a request or redirect URI string + + + + + Represents the empty query string. This field is read-only. + + + + + Initialize the query string with a given value. This value must be in escaped and delimited format without + a leading '?' character. + + The query string to be assigned to the Value property. + + + + Initialize a query string with a single given parameter name and value. The value is + + The unencoded parameter name + The unencoded parameter value + + + + Provides the query string escaped in a way which is correct for combining into the URI representation. + A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially + dangerous are escaped. + + The query string value + + + + Provides the query string escaped in a way which is correct for combining into the URI representation. + A leading '?' character will be prepended unless the Value is null or empty. Characters which are potentially + dangerous are escaped. + + The query string value + + + + Returns an QueryString given the query as it is escaped in the URI format. The string MUST NOT contain any + value that is not a query. + + The escaped query as it appears in the URI format. + The resulting QueryString + + + + Returns an QueryString given the query as from a Uri object. Relative Uri objects are not supported. + + The Uri object + The resulting QueryString + + + + Indicates whether the current instance is equal to the other instance. + + + + + + + Indicates whether the current instance is equal to the other instance. + + + + + + + Returns the hash code for this instance. + + + + + + Compares the two instances for equality. + + + + + + + + Compares the two instances for inequality. + + + + + + + + The escaped query string without the leading '?' character + + + + + True if the query string is not empty + + + + + A wrapper for the request Cookie header + + + + + Create a new wrapper + + + + + + + + + + + + + + + + + + Returns null rather than throwing KeyNotFoundException + + + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to Conversion delegate must take one parameter.. + + + + + Looks up a localized string similar to The cookie key and options are larger than ChunksSize, leaving no room for data.. + + + + + Looks up a localized string similar to The chunked cookie is incomplete. Only {0} of the expected {1} chunks were found, totaling {2} characters. A client size limit may have been exceeded.. + + + + + Looks up a localized string similar to The type '{0}' does not match any known middleware pattern.. + + + + + Looks up a localized string similar to The OWIN key 'server.OnSendingHeaders' is not available for this request.. + + + + + Looks up a localized string similar to The class '{0}' does not have a constructor taking {1} arguments.. + + + + + Looks up a localized string similar to No conversion available between {0} and {1}.. + + + + + Looks up a localized string similar to The path must not end with a '/'. + + + + + Looks up a localized string similar to The path must start with a '/' followed by one or more characters.. + + + + + Looks up a localized string similar to The path is required. + + + + + Looks up a localized string similar to The query string must start with a '?' unless null or empty.. + + + + + A standard implementation of IAppBuilder + + + + + Initializes a new instance of the the type. + + + + + + + + + + + + Adds a middleware node to the OWIN function pipeline. The middleware are + invoked in the order they are added: the first middleware passed to Use will + be the outermost function, and the last middleware passed to Use will be the + innermost. + + + The middleware parameter determines which behavior is being chained into the + pipeline. + + If the middleware given to Use is a Delegate, then it will be invoked with the "next app" in + the chain as the first parameter. If the delegate takes more than the single argument, + then the additional values must be provided to Use in the args array. + + If the middleware given to Use is a Type, then the public constructor will be + invoked with the "next app" in the chain as the first parameter. The resulting object + must have a public Invoke method. If the object has constructors which take more than + the single "next app" argument, then additional values may be provided in the args array. + + + Any additional args passed to Use will be passed as additional values, following the "next app" + parameter, when the OWIN call pipeline is build. + + They are passed as additional parameters if the middleware parameter is a Delegate, or as additional + constructor arguments if the middle parameter is a Type. + + + The IAppBuilder itself is returned. This enables you to chain your use statements together. + + + + + The New method creates a new instance of an IAppBuilder. This is needed to create + a tree structure in your processing, rather than a linear pipeline. The new instance share the + same Properties, but will be created with a new, empty middleware list. + + To create a tangent pipeline you would first call New, followed by several calls to Use on + the new builder, ending with a call to Build on the new builder. The return value from Build + will be the entry-point to your tangent pipeline. This entry-point may now be added to the + main pipeline as an argument to a switching middleware, which will either call the tangent + pipeline or the "next app", based on something in the request. + + That said - all of that work is typically hidden by a middleware like Map, which will do that + for you. + + The new instance of the IAppBuilder implementation + + + + The Build is called at the point when all of the middleware should be chained + together. This is typically done by the hosting component which created the app builder, + and does not need to be called by the startup method if the IAppBuilder is passed in. + + + The Type argument indicates which calling convention should be returned, and + is typically typeof() for the OWIN + calling convention. + + + Returns an instance of the pipeline's entry point. This object may be safely cast to the + type which was provided + + + + + Contains arbitrary properties which may added, examined, and modified by + components during the startup sequence. + + Returns . + + + + Simple object used by AppBuilder as seed OWIN callable if the + builder.Properties["builder.DefaultApp"] is not set + + + + + Abstracts the system clock to facilitate testing. + + + + + Retrieves the current system time in UTC. + + + + + Provides access to the normal system clock. + + + + + Retrieves the current system time in UTC. + + + + + Response generation utilities. + + + + + Append the given query to the uri. + + The base uri. + The query string to append, if any. + The combine result. + + + + Append the given query key and value to the uri. + + The base uri. + The name of the query key. + The query value. + The combine result. + + + + Append the given query keys and values to the uri. + + The base uri. + A collection of name value query pairs to append. + The combine result. + + + + A wrapper for the response Set-Cookie header + + + + + Create a new wrapper + + + + + + Add a new cookie and value + + + + + + + Add a new cookie + + + + + + + + Sets an expired cookie + + + + + + Sets an expired cookie + + + + + + + Acts as the return value from calls to the IAuthenticationManager's AuthenticeAsync methods. + + + + + Create an instance of the result object + + Assigned to Identity. May be null. + Assigned to Properties. Contains extra information carried along with the identity. + Assigned to Description. Contains information describing the authentication provider. + + + + Contains the claims that were authenticated by the given AuthenticationType. If the authentication + type was not successful the Identity property will be null. + + + + + Contains extra values that were provided with the original SignIn call. + + + + + Contains description properties for the middleware authentication type in general. Does not + vary per request. + + + + + Contains information describing an authentication provider. + + + + + Initializes a new instance of the class + + + + + Initializes a new instance of the class + + + + + + Contains metadata about the authentication provider. + + + + + Gets or sets the name used to reference the authentication middleware instance. + + + + + Gets or sets the display name for the authentication provider. + + + + + Extension methods used to indicate at which stage in the integrated pipeline prior middleware should run. + + + + + Call after other middleware to specify when they should run in the integrated pipeline. + + The IAppBuilder. + The name of the integrated pipeline in which to run. + The original IAppBuilder for chaining. + + + + Call after other middleware to specify when they should run in the integrated pipeline. + + The IAppBuilder. + The stage of the integrated pipeline in which to run. + The original IAppBuilder for chaining. + + + + Logging extension methods for IAppBuilder. + + + + + Sets the server.LoggerFactory in the Properties collection. + + + + + + + Retrieves the server.LoggerFactory from the Properties collection. + + + + + + + Creates a new ILogger instance from the server.LoggerFactory in the Properties collection. + + + + + + + + Creates a new ILogger instance from the server.LoggerFactory in the Properties collection. + + + + + + + + Creates a new ILogger instance from the server.LoggerFactory in the Properties collection. + + + + + + + + Used to create logger instances of the given name. + + + + + Creates a new ILogger instance of the given name. + + + + + + + A generic interface for logging. + + + + + Aggregates most logging patterns to a single method. This must be compatible with the Func representation in the OWIN environment. + + To check IsEnabled call WriteCore with only TraceEventType and check the return value, no event will be written. + + + + + + + + + + + Contains the parts of an address. + + + + + Initializes a new instance. + + + + + + Initializes a new with the given parts. + + The scheme. + The host. + The port. + The path. + + + + Creates a new + + A new + + + + Determines whether the specified object is equal to the current object. + + The other object. + true if the specified object is equal to the current object; otherwise, false. + + + + Determines whether the specified object is equal to the current object. + + The other object. + true if the specified object is equal to the current object; otherwise, false. + + + + Returns the hash code for this instance. + + The hash code for this instance. + + + + Determines whether two specified instances of are equal. + + The first object to compare. + The second object to compare. + true if left and right represent the same address; otherwise, false. + + + + Determines whether two specified instances of are not equal. + + The first object to compare. + The second object to compare. + true if left and right do not represent the same address; otherwise, false. + + + + Gets a specified key and value from the underlying dictionary. + + + The key. + + + + + Sets a specified key and value in the underlying dictionary. + + The key. + The value. + + + + + Gets the internal dictionary for this collection. + + The internal dictionary for this collection. + + + + The uri scheme. + + + + + The uri host. + + + + + The uri port. + + + + + The uri path. + + + + + Wraps the host.Addresses list. + + + + + Initializes a new instance of the class. + + The address list to set to the collection. + + + + Adds the specified address to the collection. + + The address to add to the collection. + + + + Gets the enumerator that iterates through the collection. + + The enumerator that can be used to iterate through the collection. + + + + Gets the enumerator that iterates through the collection. + + The enumerator that can be used to iterate through the collection. + + + + Creates a new empty instance of . + + A new empty instance of . + + + + Determines whether the current collection is equal to the specified collection. + + The other collection to compare to the current collection. + true if current collection is equal to the specified collection; otherwise, false. + + + + Determines whether the current collection is equal to the specified object. + + The object to compare to the current collection. + true if current collection is equal to the specified object; otherwise, false. + + + + Gets the hash code for this instance. + + The hash code for this instance. + + + + Determines whether the first collection is equal to the second collection. + + The first collection to compare. + The second collection to compare. + true if both collections are equal; otherwise, false. + + + + Determines whether the first collection is not equal to the second collection. + + The first collection to compare. + The second collection to compare. + true if both collections are not equal; otherwise, false. + + + + Gets the underlying address list. + + The underlying address list. + + + + Gets the number of elements in the collection. + + The number of elements in the collection. + + + + Gets the item with the specified index from the collection. + + The index. + The item with the specified index. + + + + A wrapper for the IDictionary. + + + + + Initializes a new instance of the class. + + + + + + Determines whether the current AppProperties is equal to the specified AppProperties. + + The other AppProperties to compare with the current instance. + true if the current AppProperties is equal to the specified AppProperties; otherwise, false. + + + + Determines whether the current AppProperties is equal to the specified object. + + The object to compare with the current instance. + true if the current AppProperties is equal to the specified object; otherwise, false. + + + + Returns the hash code for this instance. + + The hash code for this instance. + + + + Determines whether the first AppPProperties is equal to the second AppProperties. + + The first AppPropeties to compare. + The second AppPropeties to compare. + true if both AppProperties are equal; otherwise, false. + + + + Determines whether the first AppPProperties is not equal to the second AppProperties. + + The first AppPropeties to compare. + The second AppPropeties to compare. + true if both AppProperties are not equal; otherwise, false. + + + + Gets the value from the dictionary with the specified key. + + The type of the value. + The key of the value to get. + The value with the specified key. + + + + Sets the value with the specified key. + + The key of the value to set. + The value to set. + This instance. + + + + Gets or sets the string value for “owin.Version”. + + The string value for “owin.Version”. + + + + Gets or sets the function delegate for “builder.DefaultApp”. + + The function delegate for “builder.DefaultApp”. + + + + Gets or sets the action delegate for “builder.AddSignatureConversion”. + + The action delegate for “builder.AddSignatureConversion”. + + + + Gets or sets the string value for “host.AppName”. + + The string value for “host.AppName”. + + + + Gets or sets the text writer for “host.TraceOutput”. + + The text writer for “host.TraceOutput”. + + + + Gets or sets the cancellation token for “host.OnAppDisposing”. + + The cancellation token for “host.OnAppDisposing”. + + + + Gets or sets the address collection for “host.Addresses”. + + The address collection for “host.Addresses”. + + + + Gets or sets the list of “server.Capabilities”. + + The list of “server.Capabilities”. + + + + Gets the underlying dictionary for this instance. + + The underlying dictionary for this instance. + + + + Represents the capabilities for the builder properties. + + + + + Initializes a new instance of the class. + + + + + + Initializes a new instance of the class. + + A new instance of the class. + + + + Determines whether the current Capabilities instance is equal to the specified Capabilities. + + The other Capabilities to compare with the current instance. + true if the specified object is equal to the current object; otherwise, false. + + + + Determines whether the current Capabilities is equal to the specified object. + + The object to compare with the current instance. + true if the current Capabilities is equal to the specified object; otherwise, false. + + + + Returns the hash code for this instance. + + The hash code for this instance. + + + + Determines whether two specified instances of are equal. + + The first object to compare. + The second object to compare. + true if the two specified instances of are equal; otherwise, false. + + + + Determines whether two specified instances of are not equal. + + The first object to compare. + The second object to compare. + true if the two specified instances of are not equal; otherwise, false. + + + + Gets the value from the dictionary with the specified key. + + The type of the value. + The key of the value to get. + The value with the specified key. + + + + Sets the given key and value in the underlying dictionary. + + The key of the value to set. + The value to set. + This instance. + + + + The underling IDictionary + + + + + Gets or sets the string value for "sendfile.Version" + + the string value for "sendfile.Version" + + + + Gets or sets the websocket version. + + The websocket version. + + + + Options used to create a new cookie. + + + + + Creates a default cookie with a path of '/'. + + + + + Gets or sets the domain to associate the cookie with. + + The domain to associate the cookie with. + + + + Gets or sets the cookie path. + + The cookie path. + + + + Gets or sets the expiration date and time for the cookie. + + The expiration date and time for the cookie. + + + + Gets or sets a value that indicates whether to transmit the cookie using Secure Sockets Layer (SSL)—that is, over HTTPS only. + + true to transmit the cookie only over an SSL connection (HTTPS); otherwise, false. + + + + Gets or sets a value that indicates whether a cookie is accessible by client-side script. + + true if a cookie is accessible by client-side script; otherwise, false. + + + + Provides a default ILoggerFactory. + + + + + Provides a default ILoggerFactory based on System.Diagnostics.TraceSorce. + + + + + Extension methods for IAppBuilder. + + + + + The Build is called at the point when all of the middleware should be chained + together. May be called to build pipeline branches. + + + The request processing entry point for this section of the pipeline. + + + + The Build is called at the point when all of the middleware should be chained + together. May be called to build pipeline branches. + + The application signature. + + The request processing entry point for this section of the pipeline. + + + + Adds converters for adapting between disparate application signatures. + + + + + + + Adds converters for adapting between disparate application signatures. + + + + + + + + + Provides helper methods for processing requests. + + + + + Parses an HTTP form body. + + The HTTP form body to parse. + The object containing the parsed HTTP form body. + + + + Converts between an OwinMiddlware and an . + + + + + An abstract base class for a standard middleware pattern. + + + + + Instantiates the middleware with an optional pointer to the next component. + + + + + + Process an individual request. + + + + + + + The optional next component. + + + + + + + + + + + + + + + + + + Transitions between and OwinMiddleware. + + + + + + + + + + + + + OWIN environment dictionary which stores state information about the request, response and relevant server state. + + + + + Adds adapters between and OwinMiddleware. + + + + + Adds adapters between and OwinMiddleware. + + + + + + This wraps OWIN environment dictionary and provides strongly typed accessors. + + + + + Create a new context with only request and response header collections. + + + + + Create a new environment wrapper exposing request properties. + + OWIN environment dictionary which stores state information about the request, response and relevant server state. + + + + Asynchronously reads and parses the request body as a form. + + The parsed form data. + + + + Gets a value from the OWIN environment, or returns default(T) if not present. + + The type of the value. + The key of the value to get. + The value with the specified key or the default(T) if not present. + + + + Sets the given key and value in the OWIN environment. + + The type of the value. + The key of the value to set. + The value to set. + This instance. + + + + Gets the OWIN environment. + + The OWIN environment. + + + + Gets the request context. + + The request context. + + + + Gets or set the HTTP method. + + The HTTP method. + + + + Gets or set the HTTP request scheme from owin.RequestScheme. + + The HTTP request scheme from owin.RequestScheme. + + + + Returns true if the owin.RequestScheme is https. + + true if this request is using https; otherwise, false. + + + + Gets or set the Host header. May include the port. + + The Host header. + + + + Gets or set the owin.RequestPathBase. + + The owin.RequestPathBase. + + + + Gets or set the request path from owin.RequestPath. + + The request path from owin.RequestPath. + + + + Gets or set the query string from owin.RequestQueryString. + + The query string from owin.RequestQueryString. + + + + Gets the query value collection parsed from owin.RequestQueryString. + + The query value collection parsed from owin.RequestQueryString. + + + + Gets the uniform resource identifier (URI) associated with the request. + + The uniform resource identifier (URI) associated with the request. + + + + Gets or set the owin.RequestProtocol. + + The owin.RequestProtocol. + + + + Gets the request headers. + + The request headers. + + + + Gets the collection of Cookies for this request. + + The collection of Cookies for this request. + + + + Gets or sets the Content-Type header. + + The Content-Type header. + + + + Gets or sets the Cache-Control header. + + The Cache-Control header. + + + + Gets or sets the Media-Type header. + + The Media-Type header. + + + + Gets or set the Accept header. + + The Accept header. + + + + Gets or set the owin.RequestBody Stream. + + The owin.RequestBody Stream. + + + + Gets or sets the cancellation token for the request. + + The cancellation token for the request. + + + + Gets or set the server.LocalIpAddress. + + The server.LocalIpAddress. + + + + Gets or set the server.LocalPort. + + The server.LocalPort. + + + + Gets or set the server.RemoteIpAddress. + + The server.RemoteIpAddress. + + + + Gets or set the server.RemotePort. + + The server.RemotePort. + + + + Gets or set the server.User. + + The server.User. + + + + This wraps OWIN environment dictionary and provides strongly typed accessors. + + + + + Create a new context with only request and response header collections. + + + + + Creates a new environment wrapper exposing response properties. + + OWIN environment dictionary which stores state information about the request, response and relevant server state. + + + + Registers for an event that fires when the response headers are sent. + + The callback method. + The callback state. + + + + Sets a 302 response status code and the Location header. + + The location where to redirect the client. + + + + Writes the given text to the response body stream using UTF-8. + + The response data. + + + + Writes the given bytes to the response body stream. + + The response data. + + + + Writes the given bytes to the response body stream. + + The response data. + The zero-based byte offset in the parameter at which to begin copying bytes. + The number of bytes to write. + + + + Asynchronously writes the given text to the response body stream using UTF-8. + + The response data. + A Task tracking the state of the write operation. + + + + Asynchronously writes the given text to the response body stream using UTF-8. + + The response data. + A token used to indicate cancellation. + A Task tracking the state of the write operation. + + + + Asynchronously writes the given bytes to the response body stream. + + The response data. + A Task tracking the state of the write operation. + + + + Asynchronously writes the given bytes to the response body stream. + + The response data. + A token used to indicate cancellation. + A Task tracking the state of the write operation. + + + + Asynchronously writes the given bytes to the response body stream. + + The response data. + The zero-based byte offset in the parameter at which to begin copying bytes. + The number of bytes to write. + A token used to indicate cancellation. + A Task tracking the state of the write operation. + + + + Gets a value from the OWIN environment, or returns default(T) if not present. + + The type of the value. + The key of the value to get. + The value with the specified key or the default(T) if not present. + + + + Sets the given key and value in the OWIN environment. + + The type of the value. + The key of the value to set. + The value to set. + This instance. + + + + Gets the OWIN environment. + + The OWIN environment. + + + + Gets the request context. + + The request context. + + + + Gets or sets the optional owin.ResponseStatusCode. + + The optional owin.ResponseStatusCode, or 200 if not set. + + + + Gets or sets the the optional owin.ResponseReasonPhrase. + + The the optional owin.ResponseReasonPhrase. + + + + Gets or sets the owin.ResponseProtocol. + + The owin.ResponseProtocol. + + + + Gets the response header collection. + + The response header collection. + + + + Gets a collection used to manipulate the Set-Cookie header. + + A collection used to manipulate the Set-Cookie header. + + + + Gets or sets the Content-Length header. + + The Content-Length header. + + + + Gets or sets the Content-Type header. + + The Content-Type header. + + + + Gets or sets the Expires header. + + The Expires header. + + + + Gets or sets the E-Tag header. + + The E-Tag header. + + + + Gets or sets the owin.ResponseBody Stream. + + The owin.ResponseBody Stream. + + + + Used to interact with authentication middleware that have been chained in the pipeline + + + + + Lists all of the description data provided by authentication middleware that have been chained + + The authentication descriptions + + + + Lists the description data of all of the authentication middleware which are true for a given predicate + + A function provided by the caller which returns true for descriptions that should be in the returned list + The authentication descriptions + + + + Call back through the middleware to ask for a specific form of authentication to be performed + on the current request + + Identifies which middleware should respond to the request + for authentication. This value is compared to the middleware's Options.AuthenticationType property. + Returns an object with the results of the authentication. The AuthenticationResult.Identity + may be null if authentication failed. Even if the Identity property is null, there may still be + AuthenticationResult.properties and AuthenticationResult.Description information returned. + + + + Called to perform any number of authentication mechanisms on the current request. + + Identifies one or more middleware which should attempt to respond + Returns the AuthenticationResult information from the middleware which responded. The + order is determined by the order the middleware are in the pipeline. Latest added is first in the list. + + + + Add information into the response environment that will cause the authentication middleware to challenge + the caller to authenticate. This also changes the status code of the response to 401. The nature of that + challenge varies greatly, and ranges from adding a response header or changing the 401 status code to + a 302 redirect. + + Additional arbitrary values which may be used by particular authentication types. + Identify which middleware should perform their alterations on the + response. If the authenticationTypes is null or empty, that means the + AuthenticationMode.Active middleware should perform their alterations on the response. + + + + Add information into the response environment that will cause the authentication middleware to challenge + the caller to authenticate. This also changes the status code of the response to 401. The nature of that + challenge varies greatly, and ranges from adding a response header or changing the 401 status code to + a 302 redirect. + + Identify which middleware should perform their alterations on the + response. If the authenticationTypes is null or empty, that means the + AuthenticationMode.Active middleware should perform their alterations on the response. + + + + Add information to the response environment that will cause the appropriate authentication middleware + to grant a claims-based identity to the recipient of the response. The exact mechanism of this may vary. + Examples include setting a cookie, to adding a fragment on the redirect url, or producing an OAuth2 + access code or token response. + + Contains additional properties the middleware are expected to persist along with + the claims. These values will be returned as the AuthenticateResult.properties collection when AuthenticateAsync + is called on subsequent requests. + Determines which claims are granted to the signed in user. The + ClaimsIdentity.AuthenticationType property is compared to the middleware's Options.AuthenticationType + value to determine which claims are granted by which middleware. The recommended use is to have a single + ClaimsIdentity which has the AuthenticationType matching a specific middleware. + + + + Add information to the response environment that will cause the appropriate authentication middleware + to grant a claims-based identity to the recipient of the response. The exact mechanism of this may vary. + Examples include setting a cookie, to adding a fragment on the redirect url, or producing an OAuth2 + access code or token response. + + Determines which claims are granted to the signed in user. The + ClaimsIdentity.AuthenticationType property is compared to the middleware's Options.AuthenticationType + value to determine which claims are granted by which middleware. The recommended use is to have a single + ClaimsIdentity which has the AuthenticationType matching a specific middleware. + + + + Add information to the response environment that will cause the appropriate authentication middleware + to revoke any claims identity associated the the caller. The exact method varies. + + Additional arbitrary values which may be used by particular authentication types. + Identifies which middleware should perform the work to sign out. + Multiple authentication types may be provided to clear out more than one cookie at a time, or to clear + cookies and redirect to an external single-sign out url. + + + + Add information to the response environment that will cause the appropriate authentication middleware + to revoke any claims identity associated the the caller. The exact method varies. + + Identifies which middleware should perform the work to sign out. + Multiple authentication types may be provided to clear out more than one cookie at a time, or to clear + cookies and redirect to an external single-sign out url. + + + + Returns the current user for the request + + + + + Exposes the security.Challenge environment value as a strong type. + + + + + Exposes the security.SignIn environment value as a strong type. + + + + + Exposes the security.SignOut environment value as a strong type. + + + + + + + + + + + + + + Exposes the security.Challenge environment value as a strong type. + + + + + Exposes the security.SignIn environment value as a strong type. + + + + + Exposes the security.SignOut environment value as a strong type. + + + + + Dictionary used to store state values about the authentication session. + + + + + Initializes a new instance of the class + + + + + Initializes a new instance of the class + + + + + + State values about the authentication session. + + + + + Gets or sets whether the authentication session is persisted across multiple requests. + + + + + Gets or sets the full path or absolute URI to be used as an http redirect response value. + + + + + Gets or sets the time at which the authentication ticket was issued. + + + + + Gets or sets the time at which the authentication ticket expires. + + + + + Gets or sets if refreshing the authentication session should be allowed. + + + + + Exposes the security.Challenge environment value as a strong type. + + + + + Initializes a new instance of the class + + + + + + + List of the authentication types that should send a challenge in the response. + + + + + Dictionary used to store state values about the authentication session. + + + + + Exposes the security.SignIn environment value as a strong type. + + + + + Initializes a new instance of the class. + + + + + + + Initializes a new instance of the class. + + + + + + + The identity associated with the user sign in. + + + + + The security principal associated with the user sign in. + + + + + Dictionary used to store state values about the authentication session. + + + + + Exposes the security.SignOut and security.SignOutProperties environment values as a strong type. + + + + + Initializes a new instance of the class + + + + + + Initializes a new instance of the class + + + + + + + List of the authentication types that should be revoked on sign out. + + + + + Dictionary used to store state values about the authentication session. + + + + + Provides an ILoggerFactory based on System.Diagnostics.TraceSource. + + + + + Initializes a new instance of the class. + + + Creates a factory named "Microsoft.Owin". + + + + + Initializes a new instance of the class. + + + + + + + Creates a new DiagnosticsLogger for the given component name. + + + + + + + ILogger extension methods for common scenarios. + + + + + Checks if the given TraceEventType is enabled. + + + + + + + + Writes a verbose log message. + + + + + + + Writes an informational log message. + + + + + + + Writes a warning log message. + + + + + + + + Writes a warning log message. + + + + + + + + Writes an error log message. + + + + + + + Writes an error log message. + + + + + + + + Writes a critical log message. + + + + + + + Writes a critical log message. + + + + + + + diff --git a/DLL/Miniblink.dll b/DLL/Miniblink.dll new file mode 100644 index 0000000..5d45da5 Binary files /dev/null and b/DLL/Miniblink.dll differ diff --git a/DLL/NPOI.DDF.dll b/DLL/NPOI.DDF.dll new file mode 100644 index 0000000..e966ee3 Binary files /dev/null and b/DLL/NPOI.DDF.dll differ diff --git a/DLL/NPOI.HPSF.dll b/DLL/NPOI.HPSF.dll new file mode 100644 index 0000000..e482076 Binary files /dev/null and b/DLL/NPOI.HPSF.dll differ diff --git a/DLL/NPOI.HSSF.dll b/DLL/NPOI.HSSF.dll new file mode 100644 index 0000000..e2e1707 Binary files /dev/null and b/DLL/NPOI.HSSF.dll differ diff --git a/DLL/NPOI.OOXML.dll b/DLL/NPOI.OOXML.dll new file mode 100644 index 0000000..e31fdd9 Binary files /dev/null and b/DLL/NPOI.OOXML.dll differ diff --git a/DLL/NPOI.OpenXml4Net.dll b/DLL/NPOI.OpenXml4Net.dll new file mode 100644 index 0000000..70d1e2d Binary files /dev/null and b/DLL/NPOI.OpenXml4Net.dll differ diff --git a/DLL/NPOI.OpenXmlFormats.dll b/DLL/NPOI.OpenXmlFormats.dll new file mode 100644 index 0000000..859bc4a Binary files /dev/null and b/DLL/NPOI.OpenXmlFormats.dll differ diff --git a/DLL/NPOI.POIFS.dll b/DLL/NPOI.POIFS.dll new file mode 100644 index 0000000..a67905c Binary files /dev/null and b/DLL/NPOI.POIFS.dll differ diff --git a/DLL/NPOI.Util.dll b/DLL/NPOI.Util.dll new file mode 100644 index 0000000..730489e Binary files /dev/null and b/DLL/NPOI.Util.dll differ diff --git a/DLL/NPOI.dll b/DLL/NPOI.dll new file mode 100644 index 0000000..60202b8 Binary files /dev/null and b/DLL/NPOI.dll differ diff --git a/DLL/Newtonsoft.Json.dll b/DLL/Newtonsoft.Json.dll new file mode 100644 index 0000000..55d537f Binary files /dev/null and b/DLL/Newtonsoft.Json.dll differ diff --git a/DLL/Owin.Compression.dll b/DLL/Owin.Compression.dll new file mode 100644 index 0000000..a715f9c Binary files /dev/null and b/DLL/Owin.Compression.dll differ diff --git a/DLL/Owin.dll b/DLL/Owin.dll new file mode 100644 index 0000000..ba6e21e Binary files /dev/null and b/DLL/Owin.dll differ diff --git a/DLL/Protect/WeiQ.Framework.dll b/DLL/Protect/WeiQ.Framework.dll new file mode 100644 index 0000000..411cbf6 Binary files /dev/null and b/DLL/Protect/WeiQ.Framework.dll differ diff --git a/DLL/Protect/s.exe b/DLL/Protect/s.exe new file mode 100644 index 0000000..45e205e Binary files /dev/null and b/DLL/Protect/s.exe differ diff --git a/DLL/Protect/test.snk b/DLL/Protect/test.snk new file mode 100644 index 0000000..e11876d Binary files /dev/null and b/DLL/Protect/test.snk differ diff --git a/DLL/PsyQrDcd.dll b/DLL/PsyQrDcd.dll new file mode 100644 index 0000000..e2fa1a2 Binary files /dev/null and b/DLL/PsyQrDcd.dll differ diff --git a/DLL/Robot.Framework.dll b/DLL/Robot.Framework.dll new file mode 100644 index 0000000..ea0cdf9 Binary files /dev/null and b/DLL/Robot.Framework.dll differ diff --git a/DLL/Robot.Framework.hvmprj b/DLL/Robot.Framework.hvmprj new file mode 100644 index 0000000..50e5176 --- /dev/null +++ b/DLL/Robot.Framework.hvmprj @@ -0,0 +1,70 @@ + + + + + .\Robot.Framework.dll + true + + + + ..\加密处理\FLSystem\Assembly\apifile + Runtime.dll + HVMRun64.dll + 0 + 0 + true + +
+ 1 + 0 + 0 + + + 600 + 400 + 0 + + Loading... + Starting... + + + +
+
+ + true + true + true + true + true + true + true + true + true + true + true + true + true + true + 5 + 1 + 2 + true + true + true + true + 2 + + + true + true + 1 + + + + + true + true + + +
diff --git a/DLL/Robot.Framework1.dll b/DLL/Robot.Framework1.dll new file mode 100644 index 0000000..5b5a412 Binary files /dev/null and b/DLL/Robot.Framework1.dll differ diff --git a/DLL/SQLite.Interop.dll b/DLL/SQLite.Interop.dll new file mode 100644 index 0000000..1838fba Binary files /dev/null and b/DLL/SQLite.Interop.dll differ diff --git a/DLL/Socket.Framework.Ext.x64.dll b/DLL/Socket.Framework.Ext.x64.dll new file mode 100644 index 0000000..ec45804 Binary files /dev/null and b/DLL/Socket.Framework.Ext.x64.dll differ diff --git a/DLL/Socket.Framework.Ext.x86.dll b/DLL/Socket.Framework.Ext.x86.dll new file mode 100644 index 0000000..06157e5 Binary files /dev/null and b/DLL/Socket.Framework.Ext.x86.dll differ diff --git a/DLL/Socket.Framework.dll b/DLL/Socket.Framework.dll new file mode 100644 index 0000000..fcbb783 Binary files /dev/null and b/DLL/Socket.Framework.dll differ diff --git a/DLL/SqlSugar.dll b/DLL/SqlSugar.dll new file mode 100644 index 0000000..36ac9f7 Binary files /dev/null and b/DLL/SqlSugar.dll differ diff --git a/DLL/SuperSocket.Common.dll b/DLL/SuperSocket.Common.dll new file mode 100644 index 0000000..df54cc7 Binary files /dev/null and b/DLL/SuperSocket.Common.dll differ diff --git a/DLL/SuperSocket.SocketBase.dll b/DLL/SuperSocket.SocketBase.dll new file mode 100644 index 0000000..9bcda3a Binary files /dev/null and b/DLL/SuperSocket.SocketBase.dll differ diff --git a/DLL/SuperSocket.SocketEngine.dll b/DLL/SuperSocket.SocketEngine.dll new file mode 100644 index 0000000..894ac1a Binary files /dev/null and b/DLL/SuperSocket.SocketEngine.dll differ diff --git a/DLL/System.Data.OracleClient.dll b/DLL/System.Data.OracleClient.dll new file mode 100644 index 0000000..e481a98 Binary files /dev/null and b/DLL/System.Data.OracleClient.dll differ diff --git a/DLL/System.Data.SQLite.EF6.dll b/DLL/System.Data.SQLite.EF6.dll new file mode 100644 index 0000000..f1da71b Binary files /dev/null and b/DLL/System.Data.SQLite.EF6.dll differ diff --git a/DLL/System.Data.SQLite.Linq.dll b/DLL/System.Data.SQLite.Linq.dll new file mode 100644 index 0000000..3cba50a Binary files /dev/null and b/DLL/System.Data.SQLite.Linq.dll differ diff --git a/DLL/System.Data.SQLite.dll b/DLL/System.Data.SQLite.dll new file mode 100644 index 0000000..1ee930f Binary files /dev/null and b/DLL/System.Data.SQLite.dll differ diff --git a/DLL/System.Data.SQLite.dll.config b/DLL/System.Data.SQLite.dll.config new file mode 100644 index 0000000..b14f7b5 --- /dev/null +++ b/DLL/System.Data.SQLite.dll.config @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/DLL/System.Data.SQLite.xml b/DLL/System.Data.SQLite.xml new file mode 100644 index 0000000..9b723a5 --- /dev/null +++ b/DLL/System.Data.SQLite.xml @@ -0,0 +1,21112 @@ + + + + System.Data.SQLite + + + + + Defines a source code identifier custom attribute for an assembly + manifest. + + + + + Constructs an instance of this attribute class using the specified + source code identifier value. + + + The source code identifier value to use. + + + + + Gets the source code identifier value. + + + + + Defines a source code time-stamp custom attribute for an assembly + manifest. + + + + + Constructs an instance of this attribute class using the specified + source code time-stamp value. + + + The source code time-stamp value to use. + + + + + Gets the source code time-stamp value. + + + + + This is the method signature for the SQLite core library logging callback + function for use with sqlite3_log() and the SQLITE_CONFIG_LOG. + + WARNING: This delegate is used more-or-less directly by native code, do + not modify its type signature. + + + The extra data associated with this message, if any. + + + The error code associated with this message. + + + The message string to be logged. + + + + + This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET + + + + + This field is used to refer to memory allocated for the + SQLITE_DBCONFIG_MAINDBNAME value used with the native + "sqlite3_db_config" API. If allocated, the associated + memeory will be freed when the underlying connection is + closed. + + + + + The opaque pointer returned to us by the sqlite provider + + + + + The user-defined functions registered on this connection + + + + + This is the name of the native library file that contains the + "vtshim" extension [wrapper]. + + + + + This is the flag indicate whether the native library file that + contains the "vtshim" extension must be dynamically loaded by + this class prior to use. + + + + + This is the name of the native entry point for the "vtshim" + extension [wrapper]. + + + + + The modules created using this connection. + + + + + Constructs the object used to interact with the SQLite core library + using the UTF-8 text encoding. + + + The DateTime format to be used when converting string values to a + DateTime and binding DateTime parameters. + + + The to be used when creating DateTime + values. + + + The format string to be used when parsing and formatting DateTime + values. + + + The native handle to be associated with the database connection. + + + The fully qualified file name associated with . + + + Non-zero if the newly created object instance will need to dispose + of when it is no longer needed. + + + + + This method attempts to dispose of all the derived + object instances currently associated with the native database connection. + + + + + Returns the number of times the method has been + called. + + + + + This method determines whether or not a + with a return code of should + be thrown after making a call into the SQLite core library. + + + Non-zero if a to be thrown. This method + will only return non-zero if the method was called + one or more times during a call into the SQLite core library (e.g. when + the sqlite3_prepare*() or sqlite3_step() APIs are used). + + + + + Resets the value of the field. + + + + + Attempts to interrupt the query currently executing on the associated + native database connection. + + + + + This function binds a user-defined function to the connection. + + + The object instance containing + the metadata for the function to be bound. + + + The object instance that implements the + function to be bound. + + + The flags associated with the parent connection object. + + + + + This function binds a user-defined function to the connection. + + + The object instance containing + the metadata for the function to be unbound. + + + The flags associated with the parent connection object. + + Non-zero if the function was unbound and removed. + + + + Returns non-zero if the underlying native connection handle is owned + by this instance. + + + + + Returns the logical list of functions associated with this connection. + + + + + Attempts to free as much heap memory as possible for the database connection. + + A standard SQLite return code (i.e. zero for success and non-zero for failure). + + + + Attempts to free N bytes of heap memory by deallocating non-essential memory + allocations held by the database library. Memory used to cache database pages + to improve performance is an example of non-essential memory. This is a no-op + returning zero if the SQLite core library was not compiled with the compile-time + option SQLITE_ENABLE_MEMORY_MANAGEMENT. Optionally, attempts to reset and/or + compact the Win32 native heap, if applicable. + + + The requested number of bytes to free. + + + Non-zero to attempt a heap reset. + + + Non-zero to attempt heap compaction. + + + The number of bytes actually freed. This value may be zero. + + + This value will be non-zero if the heap reset was successful. + + + The size of the largest committed free block in the heap, in bytes. + This value will be zero unless heap compaction is enabled. + + + A standard SQLite return code (i.e. zero for success and non-zero + for failure). + + + + + Shutdown the SQLite engine so that it can be restarted with different + configuration options. We depend on auto initialization to recover. + + Returns a standard SQLite result code. + + + + Shutdown the SQLite engine so that it can be restarted with different + configuration options. We depend on auto initialization to recover. + + + Non-zero to reset the database and temporary directories to their + default values, which should be null for both. This parameter has no + effect on non-Windows operating systems. + + Returns a standard SQLite result code. + + + + Determines if the associated native connection handle is open. + + + Non-zero if the associated native connection handle is open. + + + + + Returns the fully qualified path and file name for the currently open + database, if any. + + + The name of the attached database to query. + + + The fully qualified path and file name for the currently open database, + if any. + + + + + This method attempts to determine if a database connection opened + with the specified should be + allowed into the connection pool. + + + The that were specified when the + connection was opened. + + + Non-zero if the connection should (eventually) be allowed into the + connection pool; otherwise, zero. + + + + + Has the sqlite3_errstr() core library API been checked for yet? + If so, is it present? + + + + + Returns the error message for the specified SQLite return code using + the sqlite3_errstr() function, falling back to the internal lookup + table if necessary. + + WARNING: Do not remove this method, it is used via reflection. + + The SQLite return code. + The error message or null if it cannot be found. + + + + Has the sqlite3_stmt_readonly() core library API been checked for yet? + If so, is it present? + + + + + Returns non-zero if the specified statement is read-only in nature. + + The statement to check. + True if the outer query is read-only. + + + + This field is used to keep track of whether or not the + "SQLite_ForceLogPrepare" environment variable has been queried. If so, + it will only be non-zero if the environment variable was present. + + + + + Determines if all calls to prepare a SQL query will be logged, + regardless of the flags for the associated connection. + + + Non-zero to log all calls to prepare a SQL query. + + + + + Determines the file name of the native library containing the native + "vtshim" extension -AND- whether it should be dynamically loaded by + this class. + + + This output parameter will be set to non-zero if the returned native + library file name should be dynamically loaded prior to attempting + the creation of native disposable extension modules. + + + The file name of the native library containing the native "vtshim" + extension -OR- null if it cannot be determined. + + + + + Calls the native SQLite core library in order to create a disposable + module containing the implementation of a virtual table. + + + The module object to be used when creating the native disposable module. + + + The flags for the associated object instance. + + + + + Calls the native SQLite core library in order to cleanup the resources + associated with a module containing the implementation of a virtual table. + + + The module object previously passed to the + method. + + + The flags for the associated object instance. + + + + + Calls the native SQLite core library in order to declare a virtual table + in response to a call into the + or virtual table methods. + + + The virtual table module that is to be responsible for the virtual table + being declared. + + + The string containing the SQL statement describing the virtual table to + be declared. + + + Upon success, the contents of this parameter are undefined. Upon failure, + it should contain an appropriate error message. + + + A standard SQLite return code. + + + + + Calls the native SQLite core library in order to declare a virtual table + function in response to a call into the + or virtual table methods. + + + The virtual table module that is to be responsible for the virtual table + function being declared. + + + The number of arguments to the function being declared. + + + The name of the function being declared. + + + Upon success, the contents of this parameter are undefined. Upon failure, + it should contain an appropriate error message. + + + A standard SQLite return code. + + + + + Builds an error message string fragment containing the + defined values of the + enumeration. + + + The built string fragment. + + + + + Builds an error message string fragment containing the + defined values of the + enumeration. + + + The built string fragment. + + + + + Returns the current and/or highwater values for the specified + database status parameter. + + + The database status parameter to query. + + + Non-zero to reset the highwater value to the current value. + + + If applicable, receives the current value. + + + If applicable, receives the highwater value. + + + A standard SQLite return code. + + + + + Change a configuration option value for the database. + connection. + + + The database configuration option to change. + + + The new value for the specified configuration option. + + + A standard SQLite return code. + + + + + Enables or disables extension loading by SQLite. + + + True to enable loading of extensions, false to disable. + + + + + Loads a SQLite extension library from the named file. + + + The name of the dynamic link library file containing the extension. + + + The name of the exported function used to initialize the extension. + If null, the default "sqlite3_extension_init" will be used. + + + + Enables or disabled extended result codes returned by SQLite + + + Gets the last SQLite error code + + + Gets the last SQLite extended error code + + + Add a log message via the SQLite sqlite3_log interface. + + + Add a log message via the SQLite sqlite3_log interface. + + + + Allows the setting of a logging callback invoked by SQLite when a + log event occurs. Only one callback may be set. If NULL is passed, + the logging callback is unregistered. + + The callback function to invoke. + Returns a result code + + + + Appends an error message and an appropriate line-ending to a + instance. This is useful because the .NET Compact Framework has a slightly different set + of supported methods for the class. + + + The instance to append to. + + + The message to append. It will be followed by an appropriate line-ending. + + + + + This method attempts to cause the SQLite native library to invalidate + its function pointers that refer to this instance. This is necessary + to prevent calls from native code into delegates that may have been + garbage collected. Normally, these types of issues can only arise for + connections that are added to the pool; howver, it is good practice to + unconditionally invalidate function pointers that may refer to objects + being disposed. + + + Non-zero to also invalidate global function pointers (i.e. those that + are not directly associated with this connection on the native side). + + + Non-zero if this method is being executed within a context where it can + throw an exception in the event of failure; otherwise, zero. + + + Non-zero if this method was successful; otherwise, zero. + + + + + This method attempts to free the cached database name used with the + method. + + + Non-zero if this method is being executed within a context where it can + throw an exception in the event of failure; otherwise, zero. + + + Non-zero if this method was successful; otherwise, zero. + + + + + Creates a new SQLite backup object based on the provided destination + database connection. The source database connection is the one + associated with this object. The source and destination database + connections cannot be the same. + + The destination database connection. + The destination database name. + The source database name. + The newly created backup object. + + + + Copies up to N pages from the source database to the destination + database associated with the specified backup object. + + The backup object to use. + + The number of pages to copy, negative to copy all remaining pages. + + + Set to true if the operation needs to be retried due to database + locking issues; otherwise, set to false. + + + True if there are more pages to be copied, false otherwise. + + + + + Returns the number of pages remaining to be copied from the source + database to the destination database associated with the specified + backup object. + + The backup object to check. + The number of pages remaining to be copied. + + + + Returns the total number of pages in the source database associated + with the specified backup object. + + The backup object to check. + The total number of pages in the source database. + + + + Destroys the backup object, rolling back any backup that may be in + progess. + + The backup object to destroy. + + + + Determines if the SQLite core library has been initialized for the + current process. + + + A boolean indicating whether or not the SQLite core library has been + initialized for the current process. + + + + + Determines if the SQLite core library has been initialized for the + current process. + + + A boolean indicating whether or not the SQLite core library has been + initialized for the current process. + + + + + Helper function to retrieve a column of data from an active statement. + + The statement being step()'d through + The flags associated with the connection. + The column index to retrieve + The type of data contained in the column. If Uninitialized, this function will retrieve the datatype information. + Returns the data in the column + + + + Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode) + + + + + Constructs the object used to interact with the SQLite core library + using the UTF-8 text encoding. + + + The DateTime format to be used when converting string values to a + DateTime and binding DateTime parameters. + + + The to be used when creating DateTime + values. + + + The format string to be used when parsing and formatting DateTime + values. + + + The native handle to be associated with the database connection. + + + The fully qualified file name associated with . + + + Non-zero if the newly created object instance will need to dispose + of when it is no longer needed. + + + + + Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8 + + A pointer to a UTF-16 string + The length (IN BYTES) of the string + A .NET string + + + + Represents a single SQL backup in SQLite. + + + + + The underlying SQLite object this backup is bound to. + + + + + The actual backup handle. + + + + + The destination database for the backup. + + + + + The destination database name for the backup. + + + + + The source database for the backup. + + + + + The source database name for the backup. + + + + + The last result from the StepBackup method of the SQLite3 class. + This is used to determine if the call to the FinishBackup method of + the SQLite3 class should throw an exception when it receives a non-Ok + return code from the core SQLite library. + + + + + Initializes the backup. + + The base SQLite object. + The backup handle. + The destination database for the backup. + The destination database name for the backup. + The source database for the backup. + The source database name for the backup. + + + + Disposes and finalizes the backup. + + + + + This internal class provides the foundation of SQLite support. It defines all the abstract members needed to implement + a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite. + + + + + The error code used for logging exceptions caught in user-provided + code. + + + + + Returns a string representing the active version of SQLite + + + + + Returns an integer representing the active version of SQLite + + + + + Returns non-zero if this connection to the database is read-only. + + + + + Returns the rowid of the most recent successful INSERT into the database from this connection. + + + + + Returns the number of changes the last executing insert/update caused. + + + + + Returns the amount of memory (in bytes) currently in use by the SQLite core library. This is not really a per-connection + value, it is global to the process. + + + + + Returns the maximum amount of memory (in bytes) used by the SQLite core library since the high-water mark was last reset. + This is not really a per-connection value, it is global to the process. + + + + + Returns non-zero if the underlying native connection handle is owned by this instance. + + + + + Returns the logical list of functions associated with this connection. + + + + + Sets the status of the memory usage tracking subsystem in the SQLite core library. By default, this is enabled. + If this is disabled, memory usage tracking will not be performed. This is not really a per-connection value, it is + global to the process. + + Non-zero to enable memory usage tracking, zero otherwise. + A standard SQLite return code (i.e. zero for success and non-zero for failure). + + + + Attempts to free as much heap memory as possible for the database connection. + + A standard SQLite return code (i.e. zero for success and non-zero for failure). + + + + Shutdown the SQLite engine so that it can be restarted with different config options. + We depend on auto initialization to recover. + + + + + Determines if the associated native connection handle is open. + + + Non-zero if a database connection is open. + + + + + Returns the fully qualified path and file name for the currently open + database, if any. + + + The name of the attached database to query. + + + The fully qualified path and file name for the currently open database, + if any. + + + + + Opens a database. + + + Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection + to bind all attributed user-defined functions and collating sequences to the new connection. + + The filename of the database to open. SQLite automatically creates it if it doesn't exist. + The name of the VFS to use -OR- null to use the default VFS. + The flags associated with the parent connection object + The open flags to use when creating the connection + The maximum size of the pool for the given filename + If true, the connection can be pulled from the connection pool + + + + Closes the currently-open database. + + + After the database has been closed implemeters should call SQLiteFunction.UnbindFunctions() to deallocate all interop allocated + memory associated with the user-defined functions and collating sequences tied to the closed connection. + + Non-zero if connection is being disposed, zero otherwise. + + + + Sets the busy timeout on the connection. SQLiteCommand will call this before executing any command. + + The number of milliseconds to wait before returning SQLITE_BUSY + + + + Returns the text of the last error issued by SQLite + + + + + + Returns the text of the last error issued by SQLite -OR- the specified default error text if + none is available from the SQLite core library. + + + The error text to return in the event that one is not available from the SQLite core library. + + + The error text. + + + + + When pooling is enabled, force this connection to be disposed rather than returned to the pool + + + + + When pooling is enabled, returns the number of pool entries matching the current file name. + + The number of pool entries matching the current file name. + + + + Prepares a SQL statement for execution. + + The source connection preparing the command. Can be null for any caller except LINQ + The SQL command text to prepare + The previous statement in a multi-statement command, or null if no previous statement exists + The timeout to wait before aborting the prepare + The remainder of the statement that was not processed. Each call to prepare parses the + SQL up to to either the end of the text or to the first semi-colon delimiter. The remaining text is returned + here for a subsequent call to Prepare() until all the text has been processed. + Returns an initialized SQLiteStatement. + + + + Steps through a prepared statement. + + The SQLiteStatement to step through + True if a row was returned, False if not. + + + + Returns non-zero if the specified statement is read-only in nature. + + The statement to check. + True if the outer query is read-only. + + + + Resets a prepared statement so it can be executed again. If the error returned is SQLITE_SCHEMA, + transparently attempt to rebuild the SQL statement and throw an error if that was not possible. + + The statement to reset + Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock + + + + Attempts to interrupt the query currently executing on the associated + native database connection. + + + + + This function binds a user-defined function to the connection. + + + The object instance containing + the metadata for the function to be bound. + + + The object instance that implements the + function to be bound. + + + The flags associated with the parent connection object. + + + + + This function unbinds a user-defined function from the connection. + + + The object instance containing + the metadata for the function to be unbound. + + + The flags associated with the parent connection object. + + Non-zero if the function was unbound. + + + + Calls the native SQLite core library in order to create a disposable + module containing the implementation of a virtual table. + + + The module object to be used when creating the native disposable module. + + + The flags for the associated object instance. + + + + + Calls the native SQLite core library in order to cleanup the resources + associated with a module containing the implementation of a virtual table. + + + The module object previously passed to the + method. + + + The flags for the associated object instance. + + + + + Calls the native SQLite core library in order to declare a virtual table + in response to a call into the + or virtual table methods. + + + The virtual table module that is to be responsible for the virtual table + being declared. + + + The string containing the SQL statement describing the virtual table to + be declared. + + + Upon success, the contents of this parameter are undefined. Upon failure, + it should contain an appropriate error message. + + + A standard SQLite return code. + + + + + Calls the native SQLite core library in order to declare a virtual table + function in response to a call into the + or virtual table methods. + + + The virtual table module that is to be responsible for the virtual table + function being declared. + + + The number of arguments to the function being declared. + + + The name of the function being declared. + + + Upon success, the contents of this parameter are undefined. Upon failure, + it should contain an appropriate error message. + + + A standard SQLite return code. + + + + + Returns the current and/or highwater values for the specified database status parameter. + + + The database status parameter to query. + + + Non-zero to reset the highwater value to the current value. + + + If applicable, receives the current value. + + + If applicable, receives the highwater value. + + + A standard SQLite return code. + + + + + Change a configuration option value for the database. + + + The database configuration option to change. + + + The new value for the specified configuration option. + + + A standard SQLite return code. + + + + + Enables or disables extension loading by SQLite. + + + True to enable loading of extensions, false to disable. + + + + + Loads a SQLite extension library from the named file. + + + The name of the dynamic link library file containing the extension. + + + The name of the exported function used to initialize the extension. + If null, the default "sqlite3_extension_init" will be used. + + + + + Enables or disabled extened result codes returned by SQLite + + true to enable extended result codes, false to disable. + + + + + Returns the numeric result code for the most recent failed SQLite API call + associated with the database connection. + + Result code + + + + Returns the extended numeric result code for the most recent failed SQLite API call + associated with the database connection. + + Extended result code + + + + Add a log message via the SQLite sqlite3_log interface. + + Error code to be logged with the message. + String to be logged. Unlike the SQLite sqlite3_log() + interface, this should be pre-formatted. Consider using the + String.Format() function. + + + + + Checks if the SQLite core library has been initialized in the current process. + + + Non-zero if the SQLite core library has been initialized in the current process, + zero otherwise. + + + + + Returns non-zero if the given database connection is in autocommit mode. + Autocommit mode is on by default. Autocommit mode is disabled by a BEGIN + statement. Autocommit mode is re-enabled by a COMMIT or ROLLBACK. + + + + + Creates a new SQLite backup object based on the provided destination + database connection. The source database connection is the one + associated with this object. The source and destination database + connections cannot be the same. + + The destination database connection. + The destination database name. + The source database name. + The newly created backup object. + + + + Copies up to N pages from the source database to the destination + database associated with the specified backup object. + + The backup object to use. + + The number of pages to copy or negative to copy all remaining pages. + + + Set to true if the operation needs to be retried due to database + locking issues. + + + True if there are more pages to be copied, false otherwise. + + + + + Returns the number of pages remaining to be copied from the source + database to the destination database associated with the specified + backup object. + + The backup object to check. + The number of pages remaining to be copied. + + + + Returns the total number of pages in the source database associated + with the specified backup object. + + The backup object to check. + The total number of pages in the source database. + + + + Destroys the backup object, rolling back any backup that may be in + progess. + + The backup object to destroy. + + + + Returns the error message for the specified SQLite return code using + the internal static lookup table. + + The SQLite return code. + The error message or null if it cannot be found. + + + + + + + + + Creates temporary tables on the connection so schema information can be queried. + + + The connection upon which to build the schema tables. + + + + + The extra behavioral flags that can be applied to a connection. + + + + + No extra flags. + + + + + Enable logging of all SQL statements to be prepared. + + + + + Enable logging of all bound parameter types and raw values. + + + + + Enable logging of all bound parameter strongly typed values. + + + + + Enable logging of all exceptions caught from user-provided + managed code called from native code via delegates. + + + + + Enable logging of backup API errors. + + + + + Skip adding the extension functions provided by the native + interop assembly. + + + + + When binding parameter values with the + type, use the interop method that accepts an + value. + + + + + When binding parameter values, always bind them as though they were + plain text (i.e. no numeric, date/time, or other conversions should + be attempted). + + + + + When returning column values, always return them as though they were + plain text (i.e. no numeric, date/time, or other conversions should + be attempted). + + + + + Prevent this object instance from + loading extensions. + + + + + Prevent this object instance from + creating virtual table modules. + + + + + Skip binding any functions provided by other managed assemblies when + opening the connection. + + + + + Skip setting the logging related properties of the + object instance that was passed to + the method. + + + + + Enable logging of all virtual table module errors seen by the + method. + + + + + Enable logging of certain virtual table module exceptions that cannot + be easily discovered via other means. + + + + + Enable tracing of potentially important [non-fatal] error conditions + that cannot be easily reported through other means. + + + + + When binding parameter values, always use the invariant culture when + converting their values from strings. + + + + + When binding parameter values, always use the invariant culture when + converting their values to strings. + + + + + Disable using the connection pool by default. If the "Pooling" + connection string property is specified, its value will override + this flag. The precise outcome of combining this flag with the + flag is unspecified; however, + one of the flags will be in effect. + + + + + Enable using the connection pool by default. If the "Pooling" + connection string property is specified, its value will override + this flag. The precise outcome of combining this flag with the + flag is unspecified; however, + one of the flags will be in effect. + + + + + Enable using per-connection mappings between type names and + values. Also see the + , + , and + methods. These + per-connection mappings, when present, override the corresponding + global mappings. + + + + + Disable using global mappings between type names and + values. This may be useful in some very narrow + cases; however, if there are no per-connection type mappings, the + fallback defaults will be used for both type names and their + associated values. Therefore, use of this flag + is not recommended. + + + + + When the property is used, it + should return non-zero if there were ever any rows in the associated + result sets. + + + + + Enable "strict" transaction enlistment semantics. Setting this flag + will cause an exception to be thrown if an attempt is made to enlist + in a transaction with an unavailable or unsupported isolation level. + In the future, more extensive checks may be enabled by this flag as + well. + + + + + Enable mapping of unsupported transaction isolation levels to the + closest supported transaction isolation level. + + + + + When returning column values, attempt to detect the affinity of + textual values by checking if they fully conform to those of the + , + , + , + or types. + + + + + When returning column values, attempt to detect the type of + string values by checking if they fully conform to those of + the , + , + , + or types. + + + + + Skip querying runtime configuration settings for use by the + class, including the default + value and default database type name. + NOTE: If the + and/or + properties are not set explicitly nor set via their connection + string properties and repeated calls to determine these runtime + configuration settings are seen to be a problem, this flag + should be set. + + + + + When binding parameter values with the + type, take their into account as + well as that of the associated . + + + + + If an exception is caught when raising the + event, the transaction + should be rolled back. If this is not specified, the transaction + will continue the commit process instead. + + + + + If an exception is caught when raising the + event, the action should + should be denied. If this is not specified, the action will be + allowed instead. + + + + + If an exception is caught when raising the + event, the operation + should be interrupted. If this is not specified, the operation + will simply continue. + + + + + Attempt to unbind all functions provided by other managed assemblies + when closing the connection. + + + + + When returning column values as a , skip + verifying their affinity. + + + + + Enable using per-connection mappings between type names and + values. Also see the + , + , and + methods. + + + + + Enable using per-connection mappings between type names and + values. Also see the + , + , and + methods. + + + + + If the database type name has not been explicitly set for the + parameter specified, fallback to using the parameter name. + + + + + If the database type name has not been explicitly set for the + parameter specified, fallback to using the database type name + associated with the value. + + + + + When returning column values, skip verifying their affinity. + + + + + Allow transactions to be nested. The outermost transaction still + controls whether or not any changes are ultimately committed or + rolled back. All non-outermost transactions are implemented using + the SAVEPOINT construct. + + + + + When binding parameter values, always bind + values as though they were plain text (i.e. not , + which is the legacy behavior). + + + + + When returning column values, always return + values as though they were plain text (i.e. not , + which is the legacy behavior). + + + + + When binding parameter values, always use + the invariant culture when converting their values to strings. + + + + + When returning column values, always use + the invariant culture when converting their values from strings. + + + + + EXPERIMENTAL -- + Enable waiting for the enlistment to be reset prior to attempting + to create a new enlistment. This may be necessary due to the + semantics used by distributed transactions, which complete + asynchronously. + + + + + When returning column values, always use + the invariant culture when converting their values from strings. + + + + + When returning column values, always use + the invariant culture when converting their values from strings. + + + + + EXPERIMENTAL -- + Enable strict conformance to the ADO.NET standard, e.g. use of + thrown exceptions to indicate common error conditions. + + + + + EXPERIMENTAL -- + When opening a connection, attempt to hide the password from the + connection string, etc. Given the memory architecture of the CLR, + (and P/Invoke) this is not 100% reliable and should not be relied + upon for security critical uses or applications. + + + + + When binding parameter values or returning column values, always + treat them as though they were plain text (i.e. no numeric, + date/time, or other conversions should be attempted). + + + + + When binding parameter values, always use the invariant culture when + converting their values to strings or from strings. + + + + + When binding parameter values or returning column values, always + treat them as though they were plain text (i.e. no numeric, + date/time, or other conversions should be attempted) and always + use the invariant culture when converting their values to strings. + + + + + When binding parameter values or returning column values, always + treat them as though they were plain text (i.e. no numeric, + date/time, or other conversions should be attempted) and always + use the invariant culture when converting their values to strings + or from strings. + + + + + Enables use of all per-connection value handling callbacks. + + + + + Enables use of all applicable + properties as fallbacks for the database type name. + + + + + Enable all logging. + + + + + The default logging related flags for new connections. + + + + + The default extra flags for new connections. + + + + + The default extra flags for new connections with all logging enabled. + + + + + These are the supported status parameters for use with the native + SQLite library. + + + + + This parameter returns the number of lookaside memory slots + currently checked out. + + + + + This parameter returns the approximate number of bytes of + heap memory used by all pager caches associated with the + database connection. The highwater mark associated with + SQLITE_DBSTATUS_CACHE_USED is always 0. + + + + + This parameter returns the approximate number of bytes of + heap memory used to store the schema for all databases + associated with the connection - main, temp, and any ATTACH-ed + databases. The full amount of memory used by the schemas is + reported, even if the schema memory is shared with other + database connections due to shared cache mode being enabled. + The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED + is always 0. + + + + + This parameter returns the number malloc attempts that might + have been satisfied using lookaside memory but failed due to + all lookaside memory already being in use. Only the high-water + value is meaningful; the current value is always zero. + + + + + This parameter returns the number malloc attempts that were + satisfied using lookaside memory. Only the high-water value + is meaningful; the current value is always zero. + + + + + This parameter returns the number malloc attempts that might + have been satisfied using lookaside memory but failed due to + the amount of memory requested being larger than the lookaside + slot size. Only the high-water value is meaningful; the current + value is always zero. + + + + + This parameter returns the number malloc attempts that might + have been satisfied using lookaside memory but failed due to + the amount of memory requested being larger than the lookaside + slot size. Only the high-water value is meaningful; the current + value is always zero. + + + + + This parameter returns the number of pager cache hits that + have occurred. The highwater mark associated with + SQLITE_DBSTATUS_CACHE_HIT is always 0. + + + + + This parameter returns the number of pager cache misses that + have occurred. The highwater mark associated with + SQLITE_DBSTATUS_CACHE_MISS is always 0. + + + + + This parameter returns the number of dirty cache entries that + have been written to disk. Specifically, the number of pages + written to the wal file in wal mode databases, or the number + of pages written to the database file in rollback mode + databases. Any pages written as part of transaction rollback + or database recovery operations are not included. If an IO or + other error occurs while writing a page to disk, the effect + on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is + undefined. The highwater mark associated with + SQLITE_DBSTATUS_CACHE_WRITE is always 0. + + + + + This parameter returns zero for the current value if and only + if all foreign key constraints (deferred or immediate) have + been resolved. The highwater mark is always 0. + + + + + This parameter is similar to DBSTATUS_CACHE_USED, except that + if a pager cache is shared between two or more connections the + bytes of heap memory used by that pager cache is divided evenly + between the attached connections. In other words, if none of + the pager caches associated with the database connection are + shared, this request returns the same value as DBSTATUS_CACHE_USED. + Or, if one or more or the pager caches are shared, the value + returned by this call will be smaller than that returned by + DBSTATUS_CACHE_USED. The highwater mark associated with + SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0. + + + + + These are the supported configuration verbs for use with the native + SQLite library. They are used with the + method. + + + + + This value represents an unknown (or invalid) option, do not use it. + + + + + This option is used to change the name of the "main" database + schema. The sole argument is a pointer to a constant UTF8 string + which will become the new schema name in place of "main". + + + + + This option is used to configure the lookaside memory allocator. + The value must be an array with three elements. The second element + must be an containing the size of each buffer + slot. The third element must be an containing + the number of slots. The first element must be an + that points to a native memory buffer of bytes equal to or greater + than the product of the second and third element values. + + + + + This option is used to enable or disable the enforcement of + foreign key constraints. + + + + + This option is used to enable or disable triggers. + + + + + This option is used to enable or disable the two-argument version + of the fts3_tokenizer() function which is part of the FTS3 full-text + search engine extension. + + + + + This option is used to enable or disable the loading of extensions. + + + + + This option is used to enable or disable the automatic checkpointing + when a WAL database is closed. + + + + + This option is used to enable or disable the query planner stability + guarantee (QPSG). + + + + + This option is used to enable or disable the extra EXPLAIN QUERY PLAN + output for trigger programs. + + + + + This option is used as part of the process to reset a database back + to an empty state. Because resetting a database is destructive and + irreversible, the process requires the use of this obscure flag and + multiple steps to help ensure that it does not happen by accident. + + + + + These constants are used with the sqlite3_trace_v2() API and the + callbacks registered by it. + + + + + Represents a single SQL blob in SQLite. + + + + + The underlying SQLite object this blob is bound to. + + + + + The actual blob handle. + + + + + Initializes the blob. + + The base SQLite object. + The blob handle. + + + + Creates a object. This will not work + for tables that were created WITHOUT ROWID -OR- if the query + does not include the "rowid" column or one of its aliases -OR- + if the was not created with the + flag. + + + The instance with a result set + containing the desired blob column. + + + The index of the blob column. + + + Non-zero to open the blob object for read-only access. + + + The newly created instance -OR- null + if an error occurs. + + + + + Creates a object. This will not work + for tables that were created WITHOUT ROWID. + + + The connection to use when opening the blob object. + + + The name of the database containing the blob object. + + + The name of the table containing the blob object. + + + The name of the column containing the blob object. + + + The integer identifier for the row associated with the desired + blob object. + + + Non-zero to open the blob object for read-only access. + + + The newly created instance -OR- null + if an error occurs. + + + + + Throws an exception if the blob object does not appear to be open. + + + + + Throws an exception if an invalid read/write parameter is detected. + + + When reading, this array will be populated with the bytes read from + the underlying database blob. When writing, this array contains new + values for the specified portion of the underlying database blob. + + + The number of bytes to read or write. + + + The byte offset, relative to the start of the underlying database + blob, where the read or write operation will begin. + + + + + Retargets this object to an underlying database blob for a + different row; the database, table, and column remain exactly + the same. If this operation fails for any reason, this blob + object is automatically disposed. + + + The integer identifier for the new row. + + + + + Queries the total number of bytes for the underlying database blob. + + + The total number of bytes for the underlying database blob. + + + + + Reads data from the underlying database blob. + + + This array will be populated with the bytes read from the + underlying database blob. + + + The number of bytes to read. + + + The byte offset, relative to the start of the underlying + database blob, where the read operation will begin. + + + + + Writes data into the underlying database blob. + + + This array contains the new values for the specified portion of + the underlying database blob. + + + The number of bytes to write. + + + The byte offset, relative to the start of the underlying + database blob, where the write operation will begin. + + + + + Closes the blob, freeing the associated resources. + + + + + Disposes and finalizes the blob. + + + + + The destructor. + + + + + SQLite implementation of DbCommand. + + + + + The default connection string to be used when creating a temporary + connection to execute a command via the static + or + + methods. + + + + + The command text this command is based on + + + + + The connection the command is associated with + + + + + The version of the connection the command is associated with + + + + + Indicates whether or not a DataReader is active on the command. + + + + + The timeout for the command, kludged because SQLite doesn't support per-command timeout values + + + + + Designer support + + + + + Used by DbDataAdapter to determine updating behavior + + + + + The collection of parameters for the command + + + + + The SQL command text, broken into individual SQL statements as they are executed + + + + + Unprocessed SQL text that has not been executed + + + + + Transaction associated with this command + + + + + Constructs a new SQLiteCommand + + + Default constructor + + + + + Initializes the command with the given command text + + The SQL command text + + + + Initializes the command with the given SQL command text and attach the command to the specified + connection. + + The SQL command text + The connection to associate with the command + + + + Initializes the command and associates it with the specified connection. + + The connection to associate with the command + + + + Initializes a command with the given SQL, connection and transaction + + The SQL command text + The connection to associate with the command + The transaction the command should be associated with + + + + Disposes of the command and clears all member variables + + Whether or not the class is being explicitly or implicitly disposed + + + + This method attempts to query the flags associated with the database + connection in use. If the database connection is disposed, the default + flags will be returned. + + + The command containing the databse connection to query the flags from. + + + The connection flags value. + + + + + Clears and destroys all statements currently prepared + + + + + Builds an array of prepared statements for each complete SQL statement in the command text + + + + + Not implemented + + + + + The SQL command text associated with the command + + + + + The amount of time to wait for the connection to become available before erroring out + + + + + The type of the command. SQLite only supports CommandType.Text + + + + + Forwards to the local CreateParameter() function + + + + + + Create a new parameter + + + + + + The connection associated with this command + + + + + Forwards to the local Connection property + + + + + Returns the SQLiteParameterCollection for the given command + + + + + Forwards to the local Parameters property + + + + + The transaction associated with this command. SQLite only supports one transaction per connection, so this property forwards to the + command's underlying connection. + + + + + Forwards to the local Transaction property + + + + + Verifies that all SQL queries associated with the current command text + can be successfully compiled. A will be + raised if any errors occur. + + + + + This function ensures there are no active readers, that we have a valid connection, + that the connection is open, that all statements are prepared and all parameters are assigned + in preparation for allocating a data reader. + + + + + Creates a new SQLiteDataReader to execute/iterate the array of SQLite prepared statements + + The behavior the data reader should adopt + Returns a SQLiteDataReader object + + + + This method creates a new connection, executes the query using the given + execution type, closes the connection, and returns the results. If the + connection string is null, a temporary in-memory database connection will + be used. + + + The text of the command to be executed. + + + The execution type for the command. This is used to determine which method + of the command object to call, which then determines the type of results + returned, if any. + + + The connection string to the database to be opened, used, and closed. If + this parameter is null, a temporary in-memory databse will be used. + + + The SQL parameter values to be used when building the command object to be + executed, if any. + + + The results of the query -OR- null if no results were produced from the + given execution type. + + + + + This method creates a new connection, executes the query using the given + execution type and command behavior, closes the connection unless a data + reader is created, and returns the results. If the connection string is + null, a temporary in-memory database connection will be used. + + + The text of the command to be executed. + + + The execution type for the command. This is used to determine which method + of the command object to call, which then determines the type of results + returned, if any. + + + The command behavior flags for the command. + + + The connection string to the database to be opened, used, and closed. If + this parameter is null, a temporary in-memory databse will be used. + + + The SQL parameter values to be used when building the command object to be + executed, if any. + + + The results of the query -OR- null if no results were produced from the + given execution type. + + + + + Overrides the default behavior to return a SQLiteDataReader specialization class + + The flags to be associated with the reader. + A SQLiteDataReader + + + + Overrides the default behavior of DbDataReader to return a specialized SQLiteDataReader class + + A SQLiteDataReader + + + + Called by the SQLiteDataReader when the data reader is closed. + + + + + Execute the command and return the number of rows inserted/updated affected by it. + + The number of rows inserted/updated affected by it. + + + + Execute the command and return the number of rows inserted/updated affected by it. + + The flags to be associated with the reader. + The number of rows inserted/updated affected by it. + + + + Execute the command and return the first column of the first row of the resultset + (if present), or null if no resultset was returned. + + The first column of the first row of the first resultset from the query. + + + + Execute the command and return the first column of the first row of the resultset + (if present), or null if no resultset was returned. + + The flags to be associated with the reader. + The first column of the first row of the first resultset from the query. + + + + This method resets all the prepared statements held by this instance + back to their initial states, ready to be re-executed. + + + + + This method resets all the prepared statements held by this instance + back to their initial states, ready to be re-executed. + + + Non-zero if the parameter bindings should be cleared as well. + + + If this is zero, a may be thrown for + any unsuccessful return codes from the native library; otherwise, a + will only be thrown if the connection + or its state is invalid. + + + + + Does nothing. Commands are prepared as they are executed the first time, and kept in prepared state afterwards. + + + + + Sets the method the SQLiteCommandBuilder uses to determine how to update inserted or updated rows in a DataTable. + + + + + Determines if the command is visible at design time. Defaults to True. + + + + + Clones a command, including all its parameters + + A new SQLiteCommand with the same commandtext, connection and parameters + + + + SQLite implementation of DbCommandBuilder. + + + + + Default constructor + + + + + Initializes the command builder and associates it with the specified data adapter. + + + + + + Cleans up resources (native and managed) associated with the current instance. + + + Zero when being disposed via garbage collection; otherwise, non-zero. + + + + + Minimal amount of parameter processing. Primarily sets the DbType for the parameter equal to the provider type in the schema + + The parameter to use in applying custom behaviors to a row + The row to apply the parameter to + The type of statement + Whether the application of the parameter is part of a WHERE clause + + + + Returns a valid named parameter + + The name of the parameter + Error + + + + Returns a named parameter for the given ordinal + + The i of the parameter + Error + + + + Returns a placeholder character for the specified parameter i. + + The index of the parameter to provide a placeholder for + Returns a named parameter + + + + Sets the handler for receiving row updating events. Used by the DbCommandBuilder to autogenerate SQL + statements that may not have previously been generated. + + A data adapter to receive events on. + + + + Gets/sets the DataAdapter for this CommandBuilder + + + + + Returns the automatically-generated SQLite command to delete rows from the database + + + + + + Returns the automatically-generated SQLite command to delete rows from the database + + + + + + + Returns the automatically-generated SQLite command to update rows in the database + + + + + + Returns the automatically-generated SQLite command to update rows in the database + + + + + + + Returns the automatically-generated SQLite command to insert rows into the database + + + + + + Returns the automatically-generated SQLite command to insert rows into the database + + + + + + + Overridden to hide its property from the designer + + + + + Overridden to hide its property from the designer + + + + + Overridden to hide its property from the designer + + + + + Overridden to hide its property from the designer + + + + + Places brackets around an identifier + + The identifier to quote + The bracketed identifier + + + + Removes brackets around an identifier + + The quoted (bracketed) identifier + The undecorated identifier + + + + Overridden to hide its property from the designer + + + + + Override helper, which can help the base command builder choose the right keys for the given query + + + + + + + This class represents a single value to be returned + from the class via + its , + , + , + , + , + , + , + , + , + , + , + , + , + , + , or + method. If the value of the + associated public field of this class is null upon returning from the + callback, the null value will only be used if the return type for the + method called is not a value type. + If the value to be returned from the + method is unsuitable (e.g. null with a value type), an exception will + be thrown. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method -OR- null to + indicate an error. + + + + + The value to be returned from the + method. + + + + + The value to be returned from the + method. + + + + + This class represents the parameters that are provided + to the methods, with + the exception of the column index (provided separately). + + + + + This class represents the parameters that are provided to + the method, with + the exception of the column index (provided separately). + + + + + Provides the underlying storage for the + property. + + + + + Constructs an instance of this class to pass into a user-defined + callback associated with the + method. + + + The value that was originally specified for the "readOnly" + parameter to the method. + + + + + The value that was originally specified for the "readOnly" + parameter to the method. + + + + + This class represents the parameters that are provided + to the and + methods, with + the exception of the column index (provided separately). + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Constructs an instance of this class to pass into a user-defined + callback associated with the + method. + + + The value that was originally specified for the "dataOffset" + parameter to the or + methods. + + + The value that was originally specified for the "buffer" + parameter to the + method. + + + The value that was originally specified for the "bufferOffset" + parameter to the or + methods. + + + The value that was originally specified for the "length" + parameter to the or + methods. + + + + + Constructs an instance of this class to pass into a user-defined + callback associated with the + method. + + + The value that was originally specified for the "dataOffset" + parameter to the or + methods. + + + The value that was originally specified for the "buffer" + parameter to the + method. + + + The value that was originally specified for the "bufferOffset" + parameter to the or + methods. + + + The value that was originally specified for the "length" + parameter to the or + methods. + + + + + The value that was originally specified for the "dataOffset" + parameter to the or + methods. + + + + + The value that was originally specified for the "buffer" + parameter to the + method. + + + + + The value that was originally specified for the "buffer" + parameter to the + method. + + + + + The value that was originally specified for the "bufferOffset" + parameter to the or + methods. + + + + + The value that was originally specified for the "length" + parameter to the or + methods. + + + + + This class represents the parameters and return values for the + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , and + methods. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Constructs a new instance of this class. Depending on the method + being called, the and/or + parameters may be null. + + + The name of the method that was + responsible for invoking this callback. + + + If the or + method is being called, + this object will contain the array related parameters for that + method. If the method is + being called, this object will contain the blob related parameters + for that method. + + + This may be used by the callback to set the return value for the + called method. + + + + + The name of the method that was + responsible for invoking this callback. + + + + + If the or + method is being called, + this object will contain the array related parameters for that + method. If the method is + being called, this object will contain the blob related parameters + for that method. + + + + + This may be used by the callback to set the return value for the + called method. + + + + + This represents a method that will be called in response to a request to + bind a parameter to a command. If an exception is thrown, it will cause + the parameter binding operation to fail -AND- it will continue to unwind + the call stack. + + + The instance in use. + + + The instance in use. + + + The flags associated with the instance + in use. + + + The instance being bound to the command. + + + The database type name associated with this callback. + + + The ordinal of the parameter being bound to the command. + + + The data originally used when registering this callback. + + + Non-zero if the default handling for the parameter binding call should + be skipped (i.e. the parameter should not be bound at all). Great care + should be used when setting this to non-zero. + + + + + This represents a method that will be called in response to a request + to read a value from a data reader. If an exception is thrown, it will + cause the data reader operation to fail -AND- it will continue to unwind + the call stack. + + + The instance in use. + + + The instance in use. + + + The flags associated with the instance + in use. + + + The parameter and return type data for the column being read from the + data reader. + + + The database type name associated with this callback. + + + The zero based index of the column being read from the data reader. + + + The data originally used when registering this callback. + + + Non-zero if the default handling for the data reader call should be + skipped. If this is set to non-zero and the necessary return value + is unavailable or unsuitable, an exception will be thrown. + + + + + This class represents the custom data type handling callbacks + for a single type name. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Provides the underlying storage for the + property. + + + + + Constructs an instance of this class. + + + The custom paramater binding callback. This parameter may be null. + + + The custom data reader value callback. This parameter may be null. + + + The extra data to pass into the parameter binding callback. This + parameter may be null. + + + The extra data to pass into the data reader value callback. This + parameter may be null. + + + + + Creates an instance of the class. + + + The custom paramater binding callback. This parameter may be null. + + + The custom data reader value callback. This parameter may be null. + + + The extra data to pass into the parameter binding callback. This + parameter may be null. + + + The extra data to pass into the data reader value callback. This + parameter may be null. + + + + + The database type name that the callbacks contained in this class + will apply to. This value may not be null. + + + + + The custom paramater binding callback. This value may be null. + + + + + The custom data reader value callback. This value may be null. + + + + + The extra data to pass into the parameter binding callback. This + value may be null. + + + + + The extra data to pass into the data reader value callback. This + value may be null. + + + + + This class represents the mappings between database type names + and their associated custom data type handling callbacks. + + + + + Constructs an (empty) instance of this class. + + + + + Event data for connection event handlers. + + + + + The type of event being raised. + + + + + The associated with this event, if any. + + + + + The transaction associated with this event, if any. + + + + + The command associated with this event, if any. + + + + + The data reader associated with this event, if any. + + + + + The critical handle associated with this event, if any. + + + + + Command or message text associated with this event, if any. + + + + + Extra data associated with this event, if any. + + + + + Constructs the object. + + The type of event being raised. + The base associated + with this event, if any. + The transaction associated with this event, if any. + The command associated with this event, if any. + The data reader associated with this event, if any. + The critical handle associated with this event, if any. + The command or message text, if any. + The extra data, if any. + + + + Raised when an event pertaining to a connection occurs. + + The connection involved. + Extra information about the event. + + + + SQLite implentation of DbConnection. + + + The property can contain the following parameter(s), delimited with a semi-colon: + + + Parameter + Values + Required + Default + + + Data Source + + This may be a file name, the string ":memory:", or any supported URI (starting with SQLite 3.7.7). + Starting with release 1.0.86.0, in order to use more than one consecutive backslash (e.g. for a + UNC path), each of the adjoining backslash characters must be doubled (e.g. "\\Network\Share\test.db" + would become "\\\\Network\Share\test.db"). + + Y + + + + Uri + + If specified, this must be a file name that starts with "file://", "file:", or "/". Any leading + "file://" or "file:" prefix will be stripped off and the resulting file name will be used to open + the database. + + N + null + + + FullUri + + If specified, this must be a URI in a format recognized by the SQLite core library (starting with + SQLite 3.7.7). It will be passed verbatim to the SQLite core library. + + N + null + + + Version + 3 + N + 3 + + + UseUTF16Encoding + + True - The UTF-16 encoding should be used. +
+ False - The UTF-8 encoding should be used. +
+ N + False +
+ + DefaultDbType + + This is the default to use when one cannot be determined based on the + column metadata and the configured type mappings. + + N + null + + + DefaultTypeName + + This is the default type name to use when one cannot be determined based on the column metadata + and the configured type mappings. + + N + null + + + NoDefaultFlags + + True - Do not combine the specified (or existing) connection flags with the value of the + property. +
+ False - Combine the specified (or existing) connection flags with the value of the + property. +
+ N + False +
+ + NoSharedFlags + + True - Do not combine the specified (or existing) connection flags with the value of the + property. +
+ False - Combine the specified (or existing) connection flags with the value of the + property. +
+ N + False +
+ + VfsName + + The name of the VFS to use when opening the database connection. + If this is not specified, the default VFS will be used. + + N + null + + + ZipVfsVersion + + If non-null, this is the "version" of ZipVFS to use. This requires + the System.Data.SQLite interop assembly -AND- primary managed assembly + to be compiled with the INTEROP_INCLUDE_ZIPVFS option; otherwise, this + property does nothing. The valid values are "v2" and "v3". Using + anyother value will cause an exception to be thrown. Please see the + ZipVFS documentation for more information on how to use this parameter. + + N + null + + + DateTimeFormat + + Ticks - Use the value of DateTime.Ticks.
+ ISO8601 - Use the ISO-8601 format. Uses the "yyyy-MM-dd HH:mm:ss.FFFFFFFK" format for UTC + DateTime values and "yyyy-MM-dd HH:mm:ss.FFFFFFF" format for local DateTime values).
+ JulianDay - The interval of time in days and fractions of a day since January 1, 4713 BC.
+ UnixEpoch - The whole number of seconds since the Unix epoch (January 1, 1970).
+ InvariantCulture - Any culture-independent string value that the .NET Framework can interpret as a valid DateTime.
+ CurrentCulture - Any string value that the .NET Framework can interpret as a valid DateTime using the current culture.
+ N + ISO8601 +
+ + DateTimeKind + + Unspecified - Not specified as either UTC or local time. +
+ Utc - The time represented is UTC. +
+ Local - The time represented is local time. +
+ N + Unspecified +
+ + DateTimeFormatString + + The exact DateTime format string to use for all formatting and parsing of all DateTime + values for this connection. + + N + null + + + BaseSchemaName + + Some base data classes in the framework (e.g. those that build SQL queries dynamically) + assume that an ADO.NET provider cannot support an alternate catalog (i.e. database) without supporting + alternate schemas as well; however, SQLite does not fit into this model. Therefore, this value is used + as a placeholder and removed prior to preparing any SQL statements that may contain it. + + N + sqlite_default_schema + + + BinaryGUID + + True - Store GUID columns in binary form +
+ False - Store GUID columns as text +
+ N + True +
+ + Cache Size + + If the argument N is positive then the suggested cache size is set to N. + If the argument N is negative, then the number of cache pages is adjusted + to use approximately abs(N*4096) bytes of memory. Backwards compatibility + note: The behavior of cache_size with a negative N was different in SQLite + versions prior to 3.7.10. In version 3.7.9 and earlier, the number of + pages in the cache was set to the absolute value of N. + + N + -2000 + + + Synchronous + + Normal - Normal file flushing behavior +
+ Full - Full flushing after all writes +
+ Off - Underlying OS flushes I/O's +
+ N + Full +
+ + Page Size + {size in bytes} + N + 4096 + + + Password + + {password} - Using this parameter requires that the legacy CryptoAPI based + codec (or the SQLite Encryption Extension) be enabled at compile-time for + both the native interop assembly and the core managed assemblies; otherwise, + using this parameter may result in an exception being thrown when attempting + to open the connection. + + N + + + + HexPassword + + {hexPassword} - Must contain a sequence of zero or more hexadecimal encoded + byte values without a leading "0x" prefix. Using this parameter requires + that the legacy CryptoAPI based codec (or the SQLite Encryption Extension) + be enabled at compile-time for both the native interop assembly and the + core managed assemblies; otherwise, using this parameter may result in an + exception being thrown when attempting to open the connection. + + N + + + + Enlist + + Y - Automatically enlist in distributed transactions +
+ N - No automatic enlistment +
+ N + Y +
+ + Pooling + + True - Use connection pooling.
+ False - Do not use connection pooling.

+ WARNING: When using the default connection pool implementation, + setting this property to True should be avoided by applications that make + use of COM (either directly or indirectly) due to possible deadlocks that + can occur during the finalization of some COM objects. +
+ N + False +
+ + FailIfMissing + + True - Don't create the database if it does not exist, throw an error instead +
+ False - Automatically create the database if it does not exist +
+ N + False +
+ + Max Page Count + {size in pages} - Limits the maximum number of pages (limits the size) of the database + N + 0 + + + Legacy Format + + True - Use the more compatible legacy 3.x database format +
+ False - Use the newer 3.3x database format which compresses numbers more effectively +
+ N + False +
+ + Default Timeout + {time in seconds}
The default command timeout
+ N + 30 +
+ + BusyTimeout + {time in milliseconds}
Sets the busy timeout for the core library.
+ N + 0 +
+ + WaitTimeout + {time in milliseconds}
+ EXPERIMENTAL -- The wait timeout to use with + method. This is only used when + waiting for the enlistment to be reset prior to enlisting in a transaction, + and then only when the appropriate connection flag is set.
+ N + 30000 +
+ + Journal Mode + + Delete - Delete the journal file after a commit. +
+ Persist - Zero out and leave the journal file on disk after a + commit. +
+ Off - Disable the rollback journal entirely. This saves disk I/O + but at the expense of database safety and integrity. If the application + using SQLite crashes in the middle of a transaction when this journaling + mode is set, then the database file will very likely go corrupt. +
+ Truncate - Truncate the journal file to zero-length instead of + deleting it. +
+ Memory - Store the journal in volatile RAM. This saves disk I/O + but at the expense of database safety and integrity. If the application + using SQLite crashes in the middle of a transaction when this journaling + mode is set, then the database file will very likely go corrupt. +
+ Wal - Use a write-ahead log instead of a rollback journal. +
+ N + Delete +
+ + Read Only + + True - Open the database for read only access +
+ False - Open the database for normal read/write access +
+ N + False +
+ + Max Pool Size + The maximum number of connections for the given connection string that can be in the connection pool + N + 100 + + + Default IsolationLevel + The default transaciton isolation level + N + Serializable + + + Foreign Keys + Enable foreign key constraints + N + False + + + Flags + Extra behavioral flags for the connection. See the enumeration for possible values. + N + Default + + + SetDefaults + + True - Apply the default connection settings to the opened database.
+ False - Skip applying the default connection settings to the opened database. +
+ N + True +
+ + ToFullPath + + True - Attempt to expand the data source file name to a fully qualified path before opening. +
+ False - Skip attempting to expand the data source file name to a fully qualified path before opening. +
+ N + True +
+ + PrepareRetries + + The maximum number of retries when preparing SQL to be executed. This + normally only applies to preparation errors resulting from the database + schema being changed. + + N + 3 + + + ProgressOps + + The approximate number of virtual machine instructions between progress + events. In order for progress events to actually fire, the event handler + must be added to the event as well. + + N + 0 + + + Recursive Triggers + + True - Enable the recursive trigger capability. + False - Disable the recursive trigger capability. + + N + False + +
+
+
+ + + The "invalid value" for the enumeration used + by the property. This constant is shared + by this class and the SQLiteConnectionStringBuilder class. + + + + + The default "stub" (i.e. placeholder) base schema name to use when + returning column schema information. Used as the initial value of + the BaseSchemaName property. This should start with "sqlite_*" + because those names are reserved for use by SQLite (i.e. they cannot + be confused with the names of user objects). + + + + + The managed assembly containing this type. + + + + + Object used to synchronize access to the static instance data + for this class. + + + + + Static variable to store the connection event handlers to call. + + + + + The extra connection flags to be used for all opened connections. + + + + + The instance (for this thread) that + had the most recent call to . + + + + + State of the current connection + + + + + The connection string + + + + + Nesting level of the transactions open on the connection + + + + + Transaction counter for the connection. Currently, this is only used + to build SAVEPOINT names. + + + + + If this flag is non-zero, the method will have + no effect; however, the method will continue to + behave as normal. + + + + + If set, then the connection is currently being disposed. + + + + + The default isolation level for new transactions + + + + + This object is used with lock statements to synchronize access to the + field, below. + + + + + Whether or not the connection is enlisted in a distrubuted transaction + + + + + The per-connection mappings between type names and + values. These mappings override the corresponding global mappings. + + + + + The per-connection mappings between type names and optional callbacks + for parameter binding and value reading. + + + + + The base SQLite object to interop with + + + + + The database filename minus path and extension + + + + + Temporary password storage, emptied after the database has been opened + + + + + The "stub" (i.e. placeholder) base schema name to use when returning + column schema information. + + + + + The extra behavioral flags for this connection, if any. See the + enumeration for a list of + possible values. + + + + + The cached values for all settings that have been fetched on behalf + of this connection. This cache may be cleared by calling the + method. + + + + + The default databse type for this connection. This value will only + be used if the + flag is set. + + + + + The default databse type name for this connection. This value will only + be used if the + flag is set. + + + + + The name of the VFS to be used when opening the database connection. + + + + + Default command timeout + + + + + The default busy timeout to use with the SQLite core library. This is + only used when opening a connection. + + + + + The default wait timeout to use with + method. This is only used when waiting for the enlistment to be reset + prior to enlisting in a transaction, and then only when the appropriate + connection flag is set. + + + + + The maximum number of retries when preparing SQL to be executed. This + normally only applies to preparation errors resulting from the database + schema being changed. + + + + + The approximate number of virtual machine instructions between progress + events. In order for progress events to actually fire, the event handler + must be added to the event as + well. This value will only be used when opening the database. + + + + + Non-zero if the built-in (i.e. framework provided) connection string + parser should be used when opening the connection. + + + + + This event is raised whenever the database is opened or closed. + + + + + Constructs a new SQLiteConnection object + + + Default constructor + + + + + Initializes the connection with the specified connection string. + + The connection string to use. + + + + Initializes the connection with a pre-existing native connection handle. + This constructor overload is intended to be used only by the private + method. + + + The native connection handle to use. + + + The file name corresponding to the native connection handle. + + + Non-zero if this instance owns the native connection handle and + should dispose of it when it is no longer needed. + + + + + Initializes the connection with the specified connection string. + + + The connection string to use. + + + Non-zero to parse the connection string using the built-in (i.e. + framework provided) parser when opening the connection. + + + + + Clones the settings and connection string from an existing connection. If the existing connection is already open, this + function will open its own connection, enumerate any attached databases of the original connection, and automatically + attach to them. + + The connection to copy the settings from. + + + + Attempts to lookup the native handle associated with the connection. An exception will + be thrown if this cannot be accomplished. + + + The connection associated with the desired native handle. + + + The native handle associated with the connection or if it + cannot be determined. + + + + + Raises the event. + + + The connection associated with this event. If this parameter is not + null and the specified connection cannot raise events, then the + registered event handlers will not be invoked. + + + A that contains the event data. + + + + + This event is raised when events related to the lifecycle of a + SQLiteConnection object occur. + + + + + This property is used to obtain or set the custom connection pool + implementation to use, if any. Setting this property to null will + cause the default connection pool implementation to be used. + + + + + Creates and returns a new managed database connection handle. This + method is intended to be used by implementations of the + interface only. In theory, it + could be used by other classes; however, that usage is not supported. + + + This must be a native database connection handle returned by the + SQLite core library and it must remain valid and open during the + entire duration of the calling method. + + + The new managed database connection handle or null if it cannot be + created. + + + + + Backs up the database, using the specified database connection as the + destination. + + The destination database connection. + The destination database name. + The source database name. + + The number of pages to copy at a time -OR- a negative value to copy all + pages. When a negative value is used, the + may never be invoked. + + + The method to invoke between each step of the backup process. This + parameter may be null (i.e. no callbacks will be performed). If the + callback returns false -OR- throws an exception, the backup is canceled. + + + The number of milliseconds to sleep after encountering a locking error + during the backup process. A value less than zero means that no sleep + should be performed. + + + + + Clears the per-connection cached settings. + + + The total number of per-connection settings cleared. + + + + + Queries and returns the value of the specified setting, using the + cached setting names and values for this connection, when available. + + + The name of the setting. + + + The value to be returned if the setting has not been set explicitly + or cannot be determined. + + + The value of the cached setting is stored here if found; otherwise, + the value of is stored here. + + + Non-zero if the cached setting was found; otherwise, zero. + + + + + Adds or sets the cached setting specified by + to the value specified by . + + + The name of the cached setting to add or replace. + + + The new value of the cached setting. + + + + + Clears the per-connection type mappings. + + + The total number of per-connection type mappings cleared. + + + + + Returns the per-connection type mappings. + + + The per-connection type mappings -OR- null if they are unavailable. + + + + + Adds a per-connection type mapping, possibly replacing one or more + that already exist. + + + The case-insensitive database type name (e.g. "MYDATE"). The value + of this parameter cannot be null. Using an empty string value (or + a string value consisting entirely of whitespace) for this parameter + is not recommended. + + + The value that should be associated with the + specified type name. + + + Non-zero if this mapping should be considered to be the primary one + for the specified . + + + A negative value if nothing was done. Zero if no per-connection type + mappings were replaced (i.e. it was a pure add operation). More than + zero if some per-connection type mappings were replaced. + + + + + Clears the per-connection type callbacks. + + + The total number of per-connection type callbacks cleared. + + + + + Attempts to get the per-connection type callbacks for the specified + database type name. + + + The database type name. + + + Upon success, this parameter will contain the object holding the + callbacks for the database type name. Upon failure, this parameter + will be null. + + + Non-zero upon success; otherwise, zero. + + + + + Sets, resets, or clears the per-connection type callbacks for the + specified database type name. + + + The database type name. + + + The object holding the callbacks for the database type name. If + this parameter is null, any callbacks for the database type name + will be removed if they are present. + + + Non-zero if callbacks were set or removed; otherwise, zero. + + + + + Attempts to bind the specified object + instance to this connection. + + + The object instance containing + the metadata for the function to be bound. + + + The object instance that implements the + function to be bound. + + + + + Attempts to bind the specified object + instance to this connection. + + + The object instance containing + the metadata for the function to be bound. + + + A object instance that helps implement the + function to be bound. For scalar functions, this corresponds to the + type. For aggregate functions, + this corresponds to the type. For + collation functions, this corresponds to the + type. + + + A object instance that helps implement the + function to be bound. For aggregate functions, this corresponds to the + type. For other callback types, it + is not used and must be null. + + + + + Attempts to unbind the specified object + instance to this connection. + + + The object instance containing + the metadata for the function to be unbound. + + Non-zero if the function was unbound. + + + + This method unbinds all registered (known) functions -OR- all previously + bound user-defined functions from this connection. + + + Non-zero to unbind all registered (known) functions -OR- zero to unbind + all functions currently bound to the connection. + + + Non-zero if all the specified user-defined functions were unbound. + + + + + Parses a connection string into component parts using the custom + connection string parser. An exception may be thrown if the syntax + of the connection string is incorrect. + + + The connection string to parse. + + + Non-zero to parse the connection string using the algorithm provided + by the framework itself. This is not applicable when running on the + .NET Compact Framework. + + + Non-zero if names are allowed without values. + + + The list of key/value pairs corresponding to the parameters specified + within the connection string. + + + + + Parses a connection string into component parts using the custom + connection string parser. An exception may be thrown if the syntax + of the connection string is incorrect. + + + The connection that will be using the parsed connection string. + + + The connection string to parse. + + + Non-zero to parse the connection string using the algorithm provided + by the framework itself. This is not applicable when running on the + .NET Compact Framework. + + + Non-zero if names are allowed without values. + + + The list of key/value pairs corresponding to the parameters specified + within the connection string. + + + + + Attempts to escape the specified connection string property name or + value in a way that is compatible with the connection string parser. + + + The connection string property name or value to escape. + + + Non-zero if the equals sign is permitted in the string. If this is + zero and the string contains an equals sign, an exception will be + thrown. + + + The original string, with all special characters escaped. If the + original string contains equals signs, they will not be escaped. + Instead, they will be preserved verbatim. + + + + + Builds a connection string from a list of key/value pairs. + + + The list of key/value pairs corresponding to the parameters to be + specified within the connection string. + + + The connection string. Depending on how the connection string was + originally parsed, the returned connection string value may not be + usable in a subsequent call to the method. + + + + + Disposes and finalizes the connection, if applicable. + + + + + Cleans up resources (native and managed) associated with the current instance. + + + Zero when being disposed via garbage collection; otherwise, non-zero. + + + + + Creates a clone of the connection. All attached databases and user-defined functions are cloned. If the existing connection is open, the cloned connection + will also be opened. + + + + + + Creates a database file. This just creates a zero-byte file which SQLite + will turn into a database when the file is opened properly. + + The file to create + + + + Raises the state change event when the state of the connection changes + + The new connection state. If this is different + from the previous state, the event is + raised. + The event data created for the raised event, if + it was actually raised. + + + + Determines and returns the fallback default isolation level when one cannot be + obtained from an existing connection instance. + + + The fallback default isolation level for this connection instance -OR- + if it cannot be determined. + + + + + Determines and returns the default isolation level for this connection instance. + + + The default isolation level for this connection instance -OR- + if it cannot be determined. + + + + + OBSOLETE. Creates a new SQLiteTransaction if one isn't already active on the connection. + + This parameter is ignored. + When TRUE, SQLite defers obtaining a write lock until a write operation is requested. + When FALSE, a writelock is obtained immediately. The default is TRUE, but in a multi-threaded multi-writer + environment, one may instead choose to lock the database immediately to avoid any possible writer deadlock. + Returns a SQLiteTransaction object. + + + + OBSOLETE. Creates a new SQLiteTransaction if one isn't already active on the connection. + + When TRUE, SQLite defers obtaining a write lock until a write operation is requested. + When FALSE, a writelock is obtained immediately. The default is false, but in a multi-threaded multi-writer + environment, one may instead choose to lock the database immediately to avoid any possible writer deadlock. + Returns a SQLiteTransaction object. + + + + Creates a new if one isn't already active on the connection. + + Supported isolation levels are Serializable, ReadCommitted and Unspecified. + + Unspecified will use the default isolation level specified in the connection string. If no isolation level is specified in the + connection string, Serializable is used. + Serializable transactions are the default. In this mode, the engine gets an immediate lock on the database, and no other threads + may begin a transaction. Other threads may read from the database, but not write. + With a ReadCommitted isolation level, locks are deferred and elevated as needed. It is possible for multiple threads to start + a transaction in ReadCommitted mode, but if a thread attempts to commit a transaction while another thread + has a ReadCommitted lock, it may timeout or cause a deadlock on both threads until both threads' CommandTimeout's are reached. + + Returns a SQLiteTransaction object. + + + + Creates a new if one isn't already + active on the connection. + + Returns the new transaction object. + + + + Forwards to the local function + + Supported isolation levels are Unspecified, Serializable, and ReadCommitted + + + + + This method is not implemented; however, the + event will still be raised. + + + + + + When the database connection is closed, all commands linked to this connection are automatically reset. + + + + + Returns the number of pool entries for the file name associated with this connection. + + + + + Clears the connection pool associated with the connection. Any other active connections using the same database file + will be discarded instead of returned to the pool when they are closed. + + + + + + Clears all connection pools. Any active connections will be discarded instead of sent to the pool when they are closed. + + + + + The connection string containing the parameters for the connection + + + For the complete list of supported connection string properties, + please see . + + + + + Create a new and associate it with this connection. + + Returns a new command object already assigned to this connection. + + + + Forwards to the local function. + + + + + + Attempts to create a new object instance + using this connection and the specified database name. + + + The name of the database for the newly created session. + + + The newly created session -OR- null if it cannot be created. + + + + + Attempts to create a new object instance + using this connection and the specified raw data. + + + The raw data that contains a change set (or patch set). + + + The newly created change set -OR- null if it cannot be created. + + + + + Attempts to create a new object instance + using this connection and the specified raw data. + + + The raw data that contains a change set (or patch set). + + + The flags used to create the change set iterator. + + + The newly created change set -OR- null if it cannot be created. + + + + + Attempts to create a new object instance + using this connection and the specified stream. + + + The stream where the raw data that contains a change set (or patch set) + may be read. + + + The stream where the raw data that contains a change set (or patch set) + may be written. + + + The newly created change set -OR- null if it cannot be created. + + + + + Attempts to create a new object instance + using this connection and the specified stream. + + + The stream where the raw data that contains a change set (or patch set) + may be read. + + + The stream where the raw data that contains a change set (or patch set) + may be written. + + + The flags used to create the change set iterator. + + + The newly created change set -OR- null if it cannot be created. + + + + + Attempts to create a new object + instance using this connection. + + + The newly created change group -OR- null if it cannot be created. + + + + + Returns the data source file name without extension or path. + + + + + Returns the fully qualified path and file name for the currently open + database, if any. + + + + + Returns the string "main". + + + + + Determines if the legacy connection string parser should be used. + + + The connection that will be using the parsed connection string. + + + Non-zero if the legacy connection string parser should be used. + + + + + Parses a connection string into component parts using the custom + connection string parser. An exception may be thrown if the syntax + of the connection string is incorrect. + + + The connection string to parse. + + + Non-zero if names are allowed without values. + + + The list of key/value pairs corresponding to the parameters specified + within the connection string. + + + + + Parses a connection string into component parts using the custom + connection string parser. An exception may be thrown if the syntax + of the connection string is incorrect. + + + The connection that will be using the parsed connection string. + + + The connection string to parse. + + + Non-zero if names are allowed without values. + + + The list of key/value pairs corresponding to the parameters specified + within the connection string. + + + + + Parses a connection string using the built-in (i.e. framework provided) + connection string parser class and returns the key/value pairs. An + exception may be thrown if the connection string is invalid or cannot be + parsed. When compiled for the .NET Compact Framework, the custom + connection string parser is always used instead because the framework + provided one is unavailable there. + + + The connection that will be using the parsed connection string. + + + The connection string to parse. + + + Non-zero to throw an exception if any connection string values are not of + the type. This is not applicable when running on + the .NET Compact Framework. + + The list of key/value pairs. + + + + Manual distributed transaction enlistment support + + The distributed transaction to enlist in + + + + EXPERIMENTAL -- + Waits for the enlistment associated with this connection to be reset. + This method always throws when + running on the .NET Compact Framework. + + + The approximate maximum number of milliseconds to wait before timing + out the wait operation. + + + The return value to use if the connection has been disposed; if this + value is null, will be raised + if the connection has been disposed. + + + Non-zero if the enlistment assciated with this connection was reset; + otherwise, zero. It should be noted that this method returning a + non-zero value does not necessarily guarantee that the connection + can enlist in a new transaction (i.e. due to potentical race with + other threads); therefore, callers should generally use try/catch + when calling the method. + + + + + Looks for a key in the array of key/values of the parameter string. If not found, return the specified default value + + The list to look in + The key to find + The default value to return if the key is not found + The value corresponding to the specified key, or the default value if not found. + + + + Attempts to convert the string value to an enumerated value of the specified type. + + The enumerated type to convert the string value to. + The string value to be converted. + Non-zero to make the conversion case-insensitive. + The enumerated value upon success or null upon error. + + + + Attempts to convert an input string into a byte value. + + + The string value to be converted. + + + The number styles to use for the conversion. + + + Upon sucess, this will contain the parsed byte value. + Upon failure, the value of this parameter is undefined. + + + Non-zero upon success; zero on failure. + + + + + Change a configuration option value for the database. + + + The database configuration option to change. + + + The new value for the specified configuration option. + + + + + Enables or disabled extension loading. + + + True to enable loading of extensions, false to disable. + + + + + Loads a SQLite extension library from the named dynamic link library file. + + + The name of the dynamic link library file containing the extension. + + + + + Loads a SQLite extension library from the named dynamic link library file. + + + The name of the dynamic link library file containing the extension. + + + The name of the exported function used to initialize the extension. + If null, the default "sqlite3_extension_init" will be used. + + + + + Creates a disposable module containing the implementation of a virtual + table. + + + The module object to be used when creating the disposable module. + + + + + Parses a string containing a sequence of zero or more hexadecimal + encoded byte values and returns the resulting byte array. The + "0x" prefix is not allowed on the input string. + + + The input string containing zero or more hexadecimal encoded byte + values. + + + A byte array containing the parsed byte values or null if an error + was encountered. + + + + + Creates and returns a string containing the hexadecimal encoded byte + values from the input array. + + + The input array of bytes. + + + The resulting string or null upon failure. + + + + + Parses a string containing a sequence of zero or more hexadecimal + encoded byte values and returns the resulting byte array. The + "0x" prefix is not allowed on the input string. + + + The input string containing zero or more hexadecimal encoded byte + values. + + + Upon failure, this will contain an appropriate error message. + + + A byte array containing the parsed byte values or null if an error + was encountered. + + + + + This method figures out what the default connection pool setting should + be based on the connection flags. When present, the "Pooling" connection + string property value always overrides the value returned by this method. + + + Non-zero if the connection pool should be enabled by default; otherwise, + zero. + + + + + Determines the transaction isolation level that should be used by + the caller, primarily based upon the one specified by the caller. + If mapping of transaction isolation levels is enabled, the returned + transaction isolation level may be significantly different than the + originally specified one. + + + The originally specified transaction isolation level. + + + The transaction isolation level that should be used. + + + + + Opens the connection using the parameters found in the . + + + + + Opens the connection using the parameters found in the and then returns it. + + The current connection object. + + + + Gets/sets the default command timeout for newly-created commands. This is especially useful for + commands used internally such as inside a SQLiteTransaction, where setting the timeout is not possible. + This can also be set in the ConnectionString with "Default Timeout" + + + + + Gets/sets the default busy timeout to use with the SQLite core library. This is only used when + opening a connection. + + + + + EXPERIMENTAL -- + The wait timeout to use with method. + This is only used when waiting for the enlistment to be reset prior to + enlisting in a transaction, and then only when the appropriate connection + flag is set. + + + + + The maximum number of retries when preparing SQL to be executed. This + normally only applies to preparation errors resulting from the database + schema being changed. + + + + + The approximate number of virtual machine instructions between progress + events. In order for progress events to actually fire, the event handler + must be added to the event as + well. This value will only be used when the underlying native progress + callback needs to be changed. + + + + + Non-zero if the built-in (i.e. framework provided) connection string + parser should be used when opening the connection. + + + + + Gets/sets the extra behavioral flags for this connection. See the + enumeration for a list of + possible values. + + + + + Gets/sets the default database type for this connection. This value + will only be used when not null. + + + + + Gets/sets the default database type name for this connection. This + value will only be used when not null. + + + + + Gets/sets the VFS name for this connection. This value will only be + used when opening the database. + + + + + Returns non-zero if the underlying native connection handle is + owned by this instance. + + + + + Returns the version of the underlying SQLite database engine + + + + + Returns the rowid of the most recent successful INSERT into the database from this connection. + + + + + This method causes any pending database operation to abort and return at + its earliest opportunity. This routine is typically called in response + to a user action such as pressing "Cancel" or Ctrl-C where the user wants + a long query operation to halt immediately. It is safe to call this + routine from any thread. However, it is not safe to call this routine + with a database connection that is closed or might close before this method + returns. + + + + + Returns the number of rows changed by the last INSERT, UPDATE, or DELETE statement executed on + this connection. + + + + + Checks if this connection to the specified database should be considered + read-only. An exception will be thrown if the database name specified + via cannot be found. + + + The name of a database associated with this connection -OR- null for the + main database. + + + Non-zero if this connection to the specified database should be considered + read-only. + + + + + Returns non-zero if the given database connection is in autocommit mode. + Autocommit mode is on by default. Autocommit mode is disabled by a BEGIN + statement. Autocommit mode is re-enabled by a COMMIT or ROLLBACK. + + + + + Returns the amount of memory (in bytes) currently in use by the SQLite core library. + + + + + Returns the maximum amount of memory (in bytes) used by the SQLite core library since the high-water mark was last reset. + + + + + Returns various global memory statistics for the SQLite core library via + a dictionary of key/value pairs. Currently, only the "MemoryUsed" and + "MemoryHighwater" keys are returned and they have values that correspond + to the values that could be obtained via the + and connection properties. + + + This dictionary will be populated with the global memory statistics. It + will be created if necessary. + + + + + Attempts to free as much heap memory as possible for this database connection. + + + + + Attempts to free N bytes of heap memory by deallocating non-essential memory + allocations held by the database library. Memory used to cache database pages + to improve performance is an example of non-essential memory. This is a no-op + returning zero if the SQLite core library was not compiled with the compile-time + option SQLITE_ENABLE_MEMORY_MANAGEMENT. Optionally, attempts to reset and/or + compact the Win32 native heap, if applicable. + + + The requested number of bytes to free. + + + Non-zero to attempt a heap reset. + + + Non-zero to attempt heap compaction. + + + The number of bytes actually freed. This value may be zero. + + + This value will be non-zero if the heap reset was successful. + + + The size of the largest committed free block in the heap, in bytes. + This value will be zero unless heap compaction is enabled. + + + A standard SQLite return code (i.e. zero for success and non-zero + for failure). + + + + + Sets the status of the memory usage tracking subsystem in the SQLite core library. By default, this is enabled. + If this is disabled, memory usage tracking will not be performed. This is not really a per-connection value, it is + global to the process. + + Non-zero to enable memory usage tracking, zero otherwise. + A standard SQLite return code (i.e. zero for success and non-zero for failure). + + + + Returns a string containing the define constants (i.e. compile-time + options) used to compile the core managed assembly, delimited with + spaces. + + + + + Returns the version of the underlying SQLite core library. + + + + + This method returns the string whose value is the same as the + SQLITE_SOURCE_ID C preprocessor macro used when compiling the + SQLite core library. + + + + + Returns a string containing the compile-time options used to + compile the SQLite core native library, delimited with spaces. + + + + + This method returns the version of the interop SQLite assembly + used. If the SQLite interop assembly is not in use or the + necessary information cannot be obtained for any reason, a null + value may be returned. + + + + + This method returns the string whose value contains the unique + identifier for the source checkout used to build the interop + assembly. If the SQLite interop assembly is not in use or the + necessary information cannot be obtained for any reason, a null + value may be returned. + + + + + Returns a string containing the compile-time options used to + compile the SQLite interop assembly, delimited with spaces. + + + + + This method returns the version of the managed components used + to interact with the SQLite core library. If the necessary + information cannot be obtained for any reason, a null value may + be returned. + + + + + This method returns the string whose value contains the unique + identifier for the source checkout used to build the managed + components currently executing. If the necessary information + cannot be obtained for any reason, a null value may be returned. + + + + + Queries and returns the value of the specified setting, using the + cached setting names and values for the last connection that used + the method, when available. + + + The name of the setting. + + + The value to be returned if the setting has not been set explicitly + or cannot be determined. + + + The value of the cached setting is stored here if found; otherwise, + the value of is stored here. + + + Non-zero if the cached setting was found; otherwise, zero. + + + + + Adds or sets the cached setting specified by + to the value specified by using the cached + setting names and values for the last connection that used the + method, when available. + + + The name of the cached setting to add or replace. + + + The new value of the cached setting. + + + + + The default connection flags to be used for all opened connections + when they are not present in the connection string. + + + + + The extra connection flags to be used for all opened connections. + + + + + Returns the state of the connection. + + + + + Passes a shutdown request to the SQLite core library. Does not throw + an exception if the shutdown request fails. + + + A standard SQLite return code (i.e. zero for success and non-zero for + failure). + + + + + Passes a shutdown request to the SQLite core library. Throws an + exception if the shutdown request fails and the no-throw parameter + is non-zero. + + + Non-zero to reset the database and temporary directories to their + default values, which should be null for both. + + + When non-zero, throw an exception if the shutdown request fails. + + + + Enables or disabled extended result codes returned by SQLite + + + Enables or disabled extended result codes returned by SQLite + + + Enables or disabled extended result codes returned by SQLite + + + Add a log message via the SQLite sqlite3_log interface. + + + Add a log message via the SQLite sqlite3_log interface. + + + + Change the password (or assign a password) to an open database. + + + No readers or writers may be active for this process. The database must already be open + and if it already was password protected, the existing password must already have been supplied. + + The new password to assign to the database + + + + Change the password (or assign a password) to an open database. + + + No readers or writers may be active for this process. The database must already be open + and if it already was password protected, the existing password must already have been supplied. + + The new password to assign to the database + + + + Sets the password for a password-protected database. A password-protected database is + unusable for any operation until the password has been set. + + The password for the database + + + + Sets the password for a password-protected database. A password-protected database is + unusable for any operation until the password has been set. + + The password for the database + + + + Queries or modifies the number of retries or the retry interval (in milliseconds) for + certain I/O operations that may fail due to anti-virus software. + + The number of times to retry the I/O operation. A negative value + will cause the current count to be queried and replace that negative value. + The number of milliseconds to wait before retrying the I/O + operation. This number is multiplied by the number of retry attempts so far to come + up with the final number of milliseconds to wait. A negative value will cause the + current interval to be queried and replace that negative value. + Zero for success, non-zero for error. + + + + Sets the chunk size for the primary file associated with this database + connection. + + + The new chunk size for the main database, in bytes. + + + Zero for success, non-zero for error. + + + + + Removes one set of surrounding single -OR- double quotes from the string + value and returns the resulting string value. If the string is null, empty, + or contains quotes that are not balanced, nothing is done and the original + string value will be returned. + + The string value to process. + + The string value, modified to remove one set of surrounding single -OR- + double quotes, if applicable. + + + + + Determines the directory to be used when dealing with the "|DataDirectory|" + macro in a database file name. + + + The directory to use in place of the "|DataDirectory|" macro -OR- null if it + cannot be determined. + + + + + Expand the filename of the data source, resolving the |DataDirectory| + macro as appropriate. + + The database filename to expand + + Non-zero if the returned file name should be converted to a full path + (except when using the .NET Compact Framework). + + The expanded path and filename of the filename + + + + The following commands are used to extract schema information out of the database. Valid schema types are: + + + MetaDataCollections + + + DataSourceInformation + + + Catalogs + + + Columns + + + ForeignKeys + + + Indexes + + + IndexColumns + + + Tables + + + Views + + + ViewColumns + + + + + Returns the MetaDataCollections schema + + A DataTable of the MetaDataCollections schema + + + + Returns schema information of the specified collection + + The schema collection to retrieve + A DataTable of the specified collection + + + + Retrieves schema information using the specified constraint(s) for the specified collection + + The collection to retrieve. + + The restrictions to impose. Typically, this may include: + + + restrictionValues element index + usage + + + 0 + The database (or catalog) name, if applicable. + + + 1 + The schema name. This is not used by this provider. + + + 2 + The table name, if applicable. + + + 3 + + Depends on . + When "IndexColumns", it is the index name; otherwise, it is the column name. + + + + 4 + + Depends on . + When "IndexColumns", it is the column name; otherwise, it is not used. + + + + + A DataTable of the specified collection + + + + Builds a MetaDataCollections schema datatable + + DataTable + + + + Builds a DataSourceInformation datatable + + DataTable + + + + Build a Columns schema + + The catalog (attached database) to query, can be null + The table to retrieve schema information for, can be null + The column to retrieve schema information for, can be null + DataTable + + + + Returns index information for the given database and catalog + + The catalog (attached database) to query, can be null + The name of the index to retrieve information for, can be null + The table to retrieve index information for, can be null + DataTable + + + + Retrieves table schema information for the database and catalog + + The catalog (attached database) to retrieve tables on + The table to retrieve, can be null + The table type, can be null + DataTable + + + + Retrieves view schema information for the database + + The catalog (attached database) to retrieve views on + The view name, can be null + DataTable + + + + Retrieves catalog (attached databases) schema information for the database + + The catalog to retrieve, can be null + DataTable + + + + Returns the base column information for indexes in a database + + The catalog to retrieve indexes for (can be null) + The table to restrict index information by (can be null) + The index to restrict index information by (can be null) + The source column to restrict index information by (can be null) + A DataTable containing the results + + + + Returns detailed column information for a specified view + + The catalog to retrieve columns for (can be null) + The view to restrict column information by (can be null) + The source column to restrict column information by (can be null) + A DataTable containing the results + + + + Retrieves foreign key information from the specified set of filters + + An optional catalog to restrict results on + An optional table to restrict results on + An optional foreign key name to restrict results on + A DataTable with the results of the query + + + + This event is raised periodically during long running queries. Changing + the value of the property will + determine if the operation in progress will continue or be interrupted. + For the entire duration of the event, the associated connection and + statement objects must not be modified, either directly or indirectly, by + the called code. + + + + + This event is raised whenever SQLite encounters an action covered by the + authorizer during query preparation. Changing the value of the + property will determine if + the specific action will be allowed, ignored, or denied. For the entire + duration of the event, the associated connection and statement objects + must not be modified, either directly or indirectly, by the called code. + + + + + This event is raised whenever SQLite makes an update/delete/insert into the database on + this connection. It only applies to the given connection. + + + + + This event is raised whenever SQLite is committing a transaction. + Return non-zero to trigger a rollback. + + + + + This event is raised whenever SQLite statement first begins executing on + this connection. It only applies to the given connection. + + + + + This event is raised whenever SQLite is rolling back a transaction. + + + + + Returns the instance. + + + + + The I/O file cache flushing behavior for the connection + + + + + Normal file flushing at critical sections of the code + + + + + Full file flushing after every write operation + + + + + Use the default operating system's file flushing, SQLite does not explicitly flush the file buffers after writing + + + + + Raised each time the number of virtual machine instructions is + approximately equal to the value of the + property. + + The connection performing the operation. + A that contains the + event data. + + + + Raised when authorization is required to perform an action contained + within a SQL query. + + The connection performing the action. + A that contains the + event data. + + + + Raised when a transaction is about to be committed. To roll back a transaction, set the + rollbackTrans boolean value to true. + + The connection committing the transaction + Event arguments on the transaction + + + + Raised when data is inserted, updated and deleted on a given connection + + The connection committing the transaction + The event parameters which triggered the event + + + + Raised when a statement first begins executing on a given connection + + The connection executing the statement + Event arguments of the trace + + + + Raised between each backup step. + + + The source database connection. + + + The source database name. + + + The destination database connection. + + + The destination database name. + + + The number of pages copied with each step. + + + The number of pages remaining to be copied. + + + The total number of pages in the source database. + + + Set to true if the operation needs to be retried due to database + locking issues; otherwise, set to false. + + + True to continue with the backup process or false to halt the backup + process, rolling back any changes that have been made so far. + + + + + The event data associated with progress reporting events. + + + + + The user-defined native data associated with this event. Currently, + this will always contain the value of . + + + + + The return code for the current call into the progress callback. + + + + + Constructs an instance of this class with default property values. + + + + + Constructs an instance of this class with specific property values. + + + The user-defined native data associated with this event. + + + The progress return code. + + + + + The data associated with a call into the authorizer. + + + + + The user-defined native data associated with this event. Currently, + this will always contain the value of . + + + + + The action code responsible for the current call into the authorizer. + + + + + The first string argument for the current call into the authorizer. + The exact value will vary based on the action code, see the + enumeration for possible + values. + + + + + The second string argument for the current call into the authorizer. + The exact value will vary based on the action code, see the + enumeration for possible + values. + + + + + The database name for the current call into the authorizer, if + applicable. + + + + + The name of the inner-most trigger or view that is responsible for + the access attempt or a null value if this access attempt is directly + from top-level SQL code. + + + + + The return code for the current call into the authorizer. + + + + + Constructs an instance of this class with default property values. + + + + + Constructs an instance of this class with specific property values. + + + The user-defined native data associated with this event. + + + The authorizer action code. + + + The first authorizer argument. + + + The second authorizer argument. + + + The database name, if applicable. + + + The name of the inner-most trigger or view that is responsible for + the access attempt or a null value if this access attempt is directly + from top-level SQL code. + + + The authorizer return code. + + + + + Whenever an update event is triggered on a connection, this enum will indicate + exactly what type of operation is being performed. + + + + + A row is being deleted from the given database and table + + + + + A row is being inserted into the table. + + + + + A row is being updated in the table. + + + + + Passed during an Update callback, these event arguments detail the type of update operation being performed + on the given connection. + + + + + The name of the database being updated (usually "main" but can be any attached or temporary database) + + + + + The name of the table being updated + + + + + The type of update being performed (insert/update/delete) + + + + + The RowId affected by this update. + + + + + Event arguments raised when a transaction is being committed + + + + + Set to true to abort the transaction and trigger a rollback + + + + + Passed during an Trace callback, these event arguments contain the UTF-8 rendering of the SQL statement text + + + + + SQL statement text as the statement first begins executing + + + + + This interface represents a custom connection pool implementation + usable by System.Data.SQLite. + + + + + Counts the number of pool entries matching the specified file name. + + + The file name to match or null to match all files. + + + The pool entry counts for each matching file. + + + The total number of connections successfully opened from any pool. + + + The total number of connections successfully closed from any pool. + + + The total number of pool entries for all matching files. + + + + + Disposes of all pooled connections associated with the specified + database file name. + + + The database file name. + + + + + Disposes of all pooled connections. + + + + + Adds a connection to the pool of those associated with the + specified database file name. + + + The database file name. + + + The database connection handle. + + + The connection pool version at the point the database connection + handle was received from the connection pool. This is also the + connection pool version that the database connection handle was + created under. + + + + + Removes a connection from the pool of those associated with the + specified database file name with the intent of using it to + interact with the database. + + + The database file name. + + + The new maximum size of the connection pool for the specified + database file name. + + + The connection pool version associated with the returned database + connection handle, if any. + + + The database connection handle associated with the specified + database file name or null if it cannot be obtained. + + + + + This default method implementations in this class should not be used by + applications that make use of COM (either directly or indirectly) due + to possible deadlocks that can occur during finalization of some COM + objects. + + + + + Keeps track of connections made on a specified file. The PoolVersion + dictates whether old objects get returned to the pool or discarded + when no longer in use. + + + + + The queue of weak references to the actual database connection + handles. + + + + + This pool version associated with the database connection + handles in this pool queue. + + + + + The maximum size of this pool queue. + + + + + Constructs a connection pool queue using the specified version + and maximum size. Normally, all the database connection + handles in this pool are associated with a single database file + name. + + + The initial pool version for this connection pool queue. + + + The initial maximum size for this connection pool queue. + + + + + This field is used to synchronize access to the private static data + in this class. + + + + + When this field is non-null, it will be used to provide the + implementation of all the connection pool methods; otherwise, + the default method implementations will be used. + + + + + The dictionary of connection pools, based on the normalized file + name of the SQLite database. + + + + + The default version number new pools will get. + + + + + The number of connections successfully opened from any pool. + This value is incremented by the Remove method. + + + + + The number of connections successfully closed from any pool. + This value is incremented by the Add method. + + + + + Counts the number of pool entries matching the specified file name. + + + The file name to match or null to match all files. + + + The pool entry counts for each matching file. + + + The total number of connections successfully opened from any pool. + + + The total number of connections successfully closed from any pool. + + + The total number of pool entries for all matching files. + + + + + Disposes of all pooled connections associated with the specified + database file name. + + + The database file name. + + + + + Disposes of all pooled connections. + + + + + Adds a connection to the pool of those associated with the + specified database file name. + + + The database file name. + + + The database connection handle. + + + The connection pool version at the point the database connection + handle was received from the connection pool. This is also the + connection pool version that the database connection handle was + created under. + + + + + Removes a connection from the pool of those associated with the + specified database file name with the intent of using it to + interact with the database. + + + The database file name. + + + The new maximum size of the connection pool for the specified + database file name. + + + The connection pool version associated with the returned database + connection handle, if any. + + + The database connection handle associated with the specified + database file name or null if it cannot be obtained. + + + + + This method is used to obtain a reference to the custom connection + pool implementation currently in use, if any. + + + The custom connection pool implementation or null if the default + connection pool implementation should be used. + + + + + This method is used to set the reference to the custom connection + pool implementation to use, if any. + + + The custom connection pool implementation to use or null if the + default connection pool implementation should be used. + + + + + We do not have to thread-lock anything in this function, because it + is only called by other functions above which already take the lock. + + + The pool queue to resize. + + + If a function intends to add to the pool, this is true, which + forces the resize to take one more than it needs from the pool. + + + + + SQLite implementation of DbConnectionStringBuilder. + + + + + Properties of this class + + + + + Constructs a new instance of the class + + + Default constructor + + + + + Constructs a new instance of the class using the specified connection string. + + The connection string to parse + + + + Private initializer, which assigns the connection string and resets the builder + + The connection string to assign + + + + Gets/Sets the default version of the SQLite engine to instantiate. Currently the only valid value is 3, indicating version 3 of the sqlite library. + + + + + Gets/Sets the synchronization mode (file flushing) of the connection string. Default is "Normal". + + + + + Gets/Sets the encoding for the connection string. The default is "False" which indicates UTF-8 encoding. + + + + + Gets/Sets whether or not to use connection pooling. The default is "False" + + + + + Gets/Sets whethor not to store GUID's in binary format. The default is True + which saves space in the database. + + + + + Gets/Sets the filename to open on the connection string. + + + + + An alternate to the data source property + + + + + An alternate to the data source property that uses the SQLite URI syntax. + + + + + Gets/sets the default command timeout for newly-created commands. This is especially useful for + commands used internally such as inside a SQLiteTransaction, where setting the timeout is not possible. + + + + + Gets/sets the busy timeout to use with the SQLite core library. + + + + + EXPERIMENTAL -- + The wait timeout to use with + method. + This is only used when waiting for the enlistment to be reset + prior to enlisting in a transaction, and then only when the + appropriate connection flag is set. + + + + + Gets/sets the maximum number of retries when preparing SQL to be executed. + This normally only applies to preparation errors resulting from the database + schema being changed. + + + + + Gets/sets the approximate number of virtual machine instructions between + progress events. In order for progress events to actually fire, the event + handler must be added to the event + as well. + + + + + Determines whether or not the connection will automatically participate + in the current distributed transaction (if one exists) + + + + + If set to true, will throw an exception if the database specified in the connection + string does not exist. If false, the database will be created automatically. + + + + + If enabled, uses the legacy 3.xx format for maximum compatibility, but results in larger + database sizes. + + + + + When enabled, the database will be opened for read-only access and writing will be disabled. + + + + + Gets/sets the database encryption password + + + + + Gets/sets the database encryption hexadecimal password + + + + + Gets/Sets the page size for the connection. + + + + + Gets/Sets the maximum number of pages the database may hold + + + + + Gets/Sets the cache size for the connection. + + + + + Gets/Sets the DateTime format for the connection. + + + + + Gets/Sets the DateTime kind for the connection. + + + + + Gets/sets the DateTime format string used for formatting + and parsing purposes. + + + + + Gets/Sets the placeholder base schema name used for + .NET Framework compatibility purposes. + + + + + Determines how SQLite handles the transaction journal file. + + + + + Sets the default isolation level for transactions on the connection. + + + + + Gets/sets the default database type for the connection. + + + + + Gets/sets the default type name for the connection. + + + + + Gets/sets the VFS name for the connection. + + + + + If enabled, use foreign key constraints + + + + + Enable or disable the recursive trigger capability. + + + + + If non-null, this is the version of ZipVFS to use. This requires the + System.Data.SQLite interop assembly -AND- primary managed assembly to + be compiled with the INTEROP_INCLUDE_ZIPVFS option; otherwise, this + property does nothing. + + + + + Gets/Sets the extra behavioral flags. + + + + + If enabled, apply the default connection settings to opened databases. + + + + + If enabled, attempt to resolve the provided data source file name to a + full path before opening. + + + + + If enabled, skip using the configured default connection flags. + + + + + If enabled, skip using the configured shared connection flags. + + + + + Helper function for retrieving values from the connectionstring + + The keyword to retrieve settings for + The resulting parameter value + Returns true if the value was found and returned + + + + Fallback method for MONO, which doesn't implement DbConnectionStringBuilder.GetProperties() + + The hashtable to fill with property descriptors + + + + This base class provides datatype conversion services for the SQLite provider. + + + + + This character is used to escape other characters, including itself, in + connection string property names and values. + + + + + This character can be used to wrap connection string property names and + values. Normally, it is optional; however, when used, it must be the + first -AND- last character of that connection string property name -OR- + value. + + + + + This character can be used to wrap connection string property names and + values. Normally, it is optional; however, when used, it must be the + first -AND- last character of that connection string property name -OR- + value. + + + + + The character is used to separate the name and value for a connection + string property. This character cannot be present in any connection + string property name. This character can be present in a connection + string property value; however, this should be avoided unless deemed + absolutely necessary. + + + + + This character is used to separate connection string properties. When + the "No_SQLiteConnectionNewParser" setting is enabled, this character + may not appear in connection string property names -OR- values. + + + + + These are the characters that are special to the connection string + parser. + + + + + The fallback default database type when one cannot be obtained from an + existing connection instance. + + + + + The fallback default database type name when one cannot be obtained from + an existing connection instance. + + + + + The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC). + + + + + The value of the OLE Automation epoch represented as a Julian day. This + field cannot be removed as the test suite relies upon it. + + + + + The format string for DateTime values when using the InvariantCulture or CurrentCulture formats. + + + + + This is the minimum Julian Day value supported by this library + (148731163200000). + + + + + This is the maximum Julian Day value supported by this library + (464269060799000). + + + + + An array of ISO-8601 DateTime formats that we support parsing. + + + + + The internal default format for UTC DateTime values when converting + to a string. + + + + + The internal default format for local DateTime values when converting + to a string. + + + + + An UTF-8 Encoding instance, so we can convert strings to and from UTF-8 + + + + + The default DateTime format for this instance. + + + + + The default DateTimeKind for this instance. + + + + + The default DateTime format string for this instance. + + + + + Initializes the conversion class + + The default date/time format to use for this instance + The DateTimeKind to use. + The DateTime format string to use. + + + + Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character. + + The string to convert to UTF-8 + A byte array containing the converted string plus an extra 0 terminating byte at the end of the array. + + + + Convert a DateTime to a UTF-8 encoded, zero-terminated byte array. + + + This function is a convenience function, which first calls ToString() on the DateTime, and then calls ToUTF8() with the + string result. + + The DateTime to convert. + The UTF-8 encoded string, including a 0 terminating byte at the end of the array. + + + + Converts a UTF-8 encoded IntPtr of the specified length into a .NET string + + The pointer to the memory where the UTF-8 string is encoded + The number of bytes to decode + A string containing the translated character(s) + + + + Converts a UTF-8 encoded IntPtr of the specified length into a .NET string + + The pointer to the memory where the UTF-8 string is encoded + The number of bytes to decode + A string containing the translated character(s) + + + + Checks if the specified is within the + supported range for a Julian Day value. + + + The Julian Day value to check. + + + Non-zero if the specified Julian Day value is in the supported + range; otherwise, zero. + + + + + Converts a Julian Day value from a to an + . + + + The Julian Day value to convert. + + + The resulting Julian Day value. + + + + + Converts a Julian Day value from an to a + . + + + The Julian Day value to convert. + + + The resulting Julian Day value. + + + + + Converts a Julian Day value to a . + This method was translated from the "computeYMD" function in the + "date.c" file belonging to the SQLite core library. + + + The Julian Day value to convert. + + + The value to return in the event that the + Julian Day is out of the supported range. If this value is null, + an exception will be thrown instead. + + + A value that contains the year, month, and + day values that are closest to the specified Julian Day value. + + + + + Converts a Julian Day value to a . + This method was translated from the "computeHMS" function in the + "date.c" file belonging to the SQLite core library. + + + The Julian Day value to convert. + + + The value to return in the event that the + Julian Day value is out of the supported range. If this value is + null, an exception will be thrown instead. + + + A value that contains the hour, minute, and + second, and millisecond values that are closest to the specified + Julian Day value. + + + + + Converts a to a Julian Day value. + This method was translated from the "computeJD" function in + the "date.c" file belonging to the SQLite core library. + Since the range of Julian Day values supported by this method + includes all possible (valid) values of a + value, it should be extremely difficult for this method to + raise an exception or return an undefined result. + + + The value to convert. This value + will be within the range of + (00:00:00.0000000, January 1, 0001) to + (23:59:59.9999999, December + 31, 9999). + + + The nearest Julian Day value corresponding to the specified + value. + + + + + Converts a string into a DateTime, using the DateTimeFormat, DateTimeKind, + and DateTimeFormatString specified for the connection when it was opened. + + + Acceptable ISO8601 DateTime formats are: + + THHmmssK + THHmmK + HH:mm:ss.FFFFFFFK + HH:mm:ssK + HH:mmK + yyyy-MM-dd HH:mm:ss.FFFFFFFK + yyyy-MM-dd HH:mm:ssK + yyyy-MM-dd HH:mmK + yyyy-MM-ddTHH:mm:ss.FFFFFFFK + yyyy-MM-ddTHH:mmK + yyyy-MM-ddTHH:mm:ssK + yyyyMMddHHmmssK + yyyyMMddHHmmK + yyyyMMddTHHmmssFFFFFFFK + THHmmss + THHmm + HH:mm:ss.FFFFFFF + HH:mm:ss + HH:mm + yyyy-MM-dd HH:mm:ss.FFFFFFF + yyyy-MM-dd HH:mm:ss + yyyy-MM-dd HH:mm + yyyy-MM-ddTHH:mm:ss.FFFFFFF + yyyy-MM-ddTHH:mm + yyyy-MM-ddTHH:mm:ss + yyyyMMddHHmmss + yyyyMMddHHmm + yyyyMMddTHHmmssFFFFFFF + yyyy-MM-dd + yyyyMMdd + yy-MM-dd + + If the string cannot be matched to one of the above formats -OR- + the DateTimeFormatString if one was provided, an exception will + be thrown. + + The string containing either a long integer number of 100-nanosecond units since + System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a + culture-independent formatted date and time string, a formatted date and time string in the current + culture, or an ISO8601-format string. + A DateTime value + + + + Converts a string into a DateTime, using the specified DateTimeFormat, + DateTimeKind and DateTimeFormatString. + + + Acceptable ISO8601 DateTime formats are: + + THHmmssK + THHmmK + HH:mm:ss.FFFFFFFK + HH:mm:ssK + HH:mmK + yyyy-MM-dd HH:mm:ss.FFFFFFFK + yyyy-MM-dd HH:mm:ssK + yyyy-MM-dd HH:mmK + yyyy-MM-ddTHH:mm:ss.FFFFFFFK + yyyy-MM-ddTHH:mmK + yyyy-MM-ddTHH:mm:ssK + yyyyMMddHHmmssK + yyyyMMddHHmmK + yyyyMMddTHHmmssFFFFFFFK + THHmmss + THHmm + HH:mm:ss.FFFFFFF + HH:mm:ss + HH:mm + yyyy-MM-dd HH:mm:ss.FFFFFFF + yyyy-MM-dd HH:mm:ss + yyyy-MM-dd HH:mm + yyyy-MM-ddTHH:mm:ss.FFFFFFF + yyyy-MM-ddTHH:mm + yyyy-MM-ddTHH:mm:ss + yyyyMMddHHmmss + yyyyMMddHHmm + yyyyMMddTHHmmssFFFFFFF + yyyy-MM-dd + yyyyMMdd + yy-MM-dd + + If the string cannot be matched to one of the above formats -OR- + the DateTimeFormatString if one was provided, an exception will + be thrown. + + The string containing either a long integer number of 100-nanosecond units since + System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a + culture-independent formatted date and time string, a formatted date and time string in the current + culture, or an ISO8601-format string. + The SQLiteDateFormats to use. + The DateTimeKind to use. + The DateTime format string to use. + A DateTime value + + + + Converts a julianday value into a DateTime + + The value to convert + A .NET DateTime + + + + Converts a julianday value into a DateTime + + The value to convert + The DateTimeKind to use. + A .NET DateTime + + + + Converts the specified number of seconds from the Unix epoch into a + value. + + + The number of whole seconds since the Unix epoch. + + + Either Utc or Local time. + + + The new value. + + + + + Converts the specified number of ticks since the epoch into a + value. + + + The number of whole ticks since the epoch. + + + Either Utc or Local time. + + + The new value. + + + + + Converts a DateTime struct to a JulianDay double + + The DateTime to convert + The JulianDay value the Datetime represents + + + + Converts a DateTime struct to the whole number of seconds since the + Unix epoch. + + The DateTime to convert + The whole number of seconds since the Unix epoch + + + + Returns the DateTime format string to use for the specified DateTimeKind. + If is not null, it will be returned verbatim. + + The DateTimeKind to use. + The DateTime format string to use. + + The DateTime format string to use for the specified DateTimeKind. + + + + + Converts a string into a DateTime, using the DateTimeFormat, DateTimeKind, + and DateTimeFormatString specified for the connection when it was opened. + + The DateTime value to convert + Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a + Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time + string, a formatted date and time string in the current culture, or an ISO8601-format date/time string. + + + + Converts a string into a DateTime, using the DateTimeFormat, DateTimeKind, + and DateTimeFormatString specified for the connection when it was opened. + + The DateTime value to convert + The SQLiteDateFormats to use. + The DateTimeKind to use. + The DateTime format string to use. + Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a + Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time + string, a formatted date and time string in the current culture, or an ISO8601-format date/time string. + + + + Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime. + + + This is a convenience function, which first calls ToString() on the IntPtr to convert it to a string, then calls + ToDateTime() on the string to return a DateTime. + + A pointer to the UTF-8 encoded string + The length in bytes of the string + The parsed DateTime value + + + + Smart method of splitting a string. Skips quoted elements, removes the quotes. + + + This split function works somewhat like the String.Split() function in that it breaks apart a string into + pieces and returns the pieces as an array. The primary differences are: + + Only one character can be provided as a separator character + Quoted text inside the string is skipped over when searching for the separator, and the quotes are removed. + + Thus, if splitting the following string looking for a comma:
+ One,Two, "Three, Four", Five
+
+ The resulting array would contain
+ [0] One
+ [1] Two
+ [2] Three, Four
+ [3] Five
+
+ Note that the leading and trailing spaces were removed from each item during the split. +
+ Source string to split apart + Separator character + A string array of the split up elements +
+ + + Splits the specified string into multiple strings based on a separator + and returns the result as an array of strings. + + + The string to split into pieces based on the separator character. If + this string is null, null will always be returned. If this string is + empty, an array of zero strings will always be returned. + + + The character used to divide the original string into sub-strings. + This character cannot be a backslash or a double-quote; otherwise, no + work will be performed and null will be returned. + + + If this parameter is non-zero, all double-quote characters will be + retained in the returned list of strings; otherwise, they will be + dropped. + + + Upon failure, this parameter will be modified to contain an appropriate + error message. + + + The new array of strings or null if the input string is null -OR- the + separator character is a backslash or a double-quote -OR- the string + contains an unbalanced backslash or double-quote character. + + + + + Queries and returns the string representation for an object, using the + specified (or current) format provider. + + + The object instance to return the string representation for. + + + The format provider to use -OR- null if the current format provider for + the thread should be used instead. + + + The string representation for the object instance -OR- null if the + object instance is also null. + + + + + Attempts to convert an arbitrary object to the Boolean data type. + Null object values are converted to false. Throws an exception + upon failure. + + + The object value to convert. + + + The format provider to use. + + + If non-zero, a string value will be converted using the + + method; otherwise, the + method will be used. + + + The converted boolean value. + + + + + Convert a value to true or false. + + A string or number representing true or false + + + + + Converts an integer to a string that can be round-tripped using the + invariant culture. + + + The integer value to return the string representation for. + + + The string representation of the specified integer value, using the + invariant culture. + + + + + Attempts to convert a into a . + + + The to convert, cannot be null. + + + The converted value. + + + The supported strings are "yes", "no", "y", "n", "on", "off", "0", "1", + as well as any prefix of the strings + and . All strings are treated in a + case-insensitive manner. + + + + + Converts a SQLiteType to a .NET Type object + + The SQLiteType to convert + Returns a .NET Type object + + + + For a given intrinsic type, return a DbType + + The native type to convert + The corresponding (closest match) DbType + + + + Returns the ColumnSize for the given DbType + + The DbType to get the size of + + + + + Determines the default database type name to be used when a + per-connection value is not available. + + + The connection context for type mappings, if any. + + + The default database type name to use. + + + + + If applicable, issues a trace log message warning about falling back to + the default database type name. + + + The database value type. + + + The flags associated with the parent connection object. + + + The textual name of the database type. + + + + + If applicable, issues a trace log message warning about falling back to + the default database value type. + + + The textual name of the database type. + + + The flags associated with the parent connection object. + + + The database value type. + + + + + For a given database value type, return the "closest-match" textual database type name. + + The connection context for custom type mappings, if any. + The database value type. + The flags associated with the parent connection object. + The type name or an empty string if it cannot be determined. + + + + Convert a DbType to a Type + + The DbType to convert from + The closest-match .NET type + + + + For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types. + + The type to evaluate + The flags associated with the connection. + The SQLite type affinity for that type. + + + + Builds and returns a map containing the database column types + recognized by this provider. + + + A map containing the database column types recognized by this + provider. + + + + + Determines if a database type is considered to be a string. + + + The database type to check. + + + Non-zero if the database type is considered to be a string, zero + otherwise. + + + + + Determines and returns the runtime configuration setting string that + should be used in place of the specified object value. + + + The object value to convert to a string. + + + Either the string to use in place of the object value -OR- null if it + cannot be determined. + + + + + Determines the default value to be used when a + per-connection value is not available. + + + The connection context for type mappings, if any. + + + The default value to use. + + + + + Converts the object value, which is assumed to have originated + from a , to a string value. + + + The value to be converted to a string. + + + A null value will be returned if the original value is null -OR- + the original value is . Otherwise, + the original value will be converted to a string, using its + (possibly overridden) method and + then returned. + + + + + Determines if the specified textual value appears to be a + value. + + + The textual value to inspect. + + + Non-zero if the text looks like a value, + zero otherwise. + + + + + Determines if the specified textual value appears to be an + value. + + + The textual value to inspect. + + + Non-zero if the text looks like an value, + zero otherwise. + + + + + Determines if the specified textual value appears to be a + value. + + + The textual value to inspect. + + + Non-zero if the text looks like a value, + zero otherwise. + + + + + Determines if the specified textual value appears to be a + value. + + + The object instance configured with + the chosen format. + + + The textual value to inspect. + + + Non-zero if the text looks like a in the + configured format, zero otherwise. + + + + + For a given textual database type name, return the "closest-match" database type. + This method is called during query result processing; therefore, its performance + is critical. + + The connection context for custom type mappings, if any. + The textual name of the database type to match. + The flags associated with the parent connection object. + The .NET DBType the text evaluates to. + + + + SQLite has very limited types, and is inherently text-based. The first 5 types below represent the sum of all types SQLite + understands. The DateTime extension to the spec is for internal use only. + + + + + Not used + + + + + All integers in SQLite default to Int64 + + + + + All floating point numbers in SQLite default to double + + + + + The default data type of SQLite is text + + + + + Typically blob types are only seen when returned from a function + + + + + Null types can be returned from functions + + + + + Used internally by this provider + + + + + Used internally by this provider + + + + + These are the event types associated with the + + delegate (and its corresponding event) and the + class. + + + + + Not used. + + + + + Not used. + + + + + The connection is being opened. + + + + + The connection string has been parsed. + + + + + The connection was opened. + + + + + The method was called on the + connection. + + + + + A transaction was created using the connection. + + + + + The connection was enlisted into a transaction. + + + + + A command was created using the connection. + + + + + A data reader was created using the connection. + + + + + An instance of a derived class has + been created to wrap a native resource. + + + + + The connection is being closed. + + + + + The connection was closed. + + + + + A command is being disposed. + + + + + A data reader is being disposed. + + + + + A data reader is being closed. + + + + + A native resource was opened (i.e. obtained) from the pool. + + + + + A native resource was closed (i.e. released) to the pool. + + + + + This implementation of SQLite for ADO.NET can process date/time fields in + databases in one of six formats. + + + ISO8601 format is more compatible, readable, fully-processable, but less + accurate as it does not provide time down to fractions of a second. + JulianDay is the numeric format the SQLite uses internally and is arguably + the most compatible with 3rd party tools. It is not readable as text + without post-processing. Ticks less compatible with 3rd party tools that + query the database, and renders the DateTime field unreadable as text + without post-processing. UnixEpoch is more compatible with Unix systems. + InvariantCulture allows the configured format for the invariant culture + format to be used and is human readable. CurrentCulture allows the + configured format for the current culture to be used and is also human + readable. + + The preferred order of choosing a DateTime format is JulianDay, ISO8601, + and then Ticks. Ticks is mainly present for legacy code support. + + + + + Use the value of DateTime.Ticks. This value is not recommended and is not well supported with LINQ. + + + + + Use the ISO-8601 format. Uses the "yyyy-MM-dd HH:mm:ss.FFFFFFFK" format for UTC DateTime values and + "yyyy-MM-dd HH:mm:ss.FFFFFFF" format for local DateTime values). + + + + + The interval of time in days and fractions of a day since January 1, 4713 BC. + + + + + The whole number of seconds since the Unix epoch (January 1, 1970). + + + + + Any culture-independent string value that the .NET Framework can interpret as a valid DateTime. + + + + + Any string value that the .NET Framework can interpret as a valid DateTime using the current culture. + + + + + The default format for this provider. + + + + + This enum determines how SQLite treats its journal file. + + + By default SQLite will create and delete the journal file when needed during a transaction. + However, for some computers running certain filesystem monitoring tools, the rapid + creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite. + + If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file" + when starting a transaction. If this is happening, you may want to change the default journal mode to Persist. + + + + + The default mode, this causes SQLite to use the existing journaling mode for the database. + + + + + SQLite will create and destroy the journal file as-needed. + + + + + When this is set, SQLite will keep the journal file even after a transaction has completed. It's contents will be erased, + and the journal re-used as often as needed. If it is deleted, it will be recreated the next time it is needed. + + + + + This option disables the rollback journal entirely. Interrupted transactions or a program crash can cause database + corruption in this mode! + + + + + SQLite will truncate the journal file to zero-length instead of deleting it. + + + + + SQLite will store the journal in volatile RAM. This saves disk I/O but at the expense of database safety and integrity. + If the application using SQLite crashes in the middle of a transaction when the MEMORY journaling mode is set, then the + database file will very likely go corrupt. + + + + + SQLite uses a write-ahead log instead of a rollback journal to implement transactions. The WAL journaling mode is persistent; + after being set it stays in effect across multiple database connections and after closing and reopening the database. A database + in WAL journaling mode can only be accessed by SQLite version 3.7.0 or later. + + + + + Possible values for the "synchronous" database setting. This setting determines + how often the database engine calls the xSync method of the VFS. + + + + + Use the default "synchronous" database setting. Currently, this should be + the same as using the FULL mode. + + + + + The database engine continues without syncing as soon as it has handed + data off to the operating system. If the application running SQLite + crashes, the data will be safe, but the database might become corrupted + if the operating system crashes or the computer loses power before that + data has been written to the disk surface. + + + + + The database engine will still sync at the most critical moments, but + less often than in FULL mode. There is a very small (though non-zero) + chance that a power failure at just the wrong time could corrupt the + database in NORMAL mode. + + + + + The database engine will use the xSync method of the VFS to ensure that + all content is safely written to the disk surface prior to continuing. + This ensures that an operating system crash or power failure will not + corrupt the database. FULL synchronous is very safe, but it is also + slower. + + + + + The requested command execution type. This controls which method of the + object will be called. + + + + + Do nothing. No method will be called. + + + + + The command is not expected to return a result -OR- the result is not + needed. The or + method + will be called. + + + + + The command is expected to return a scalar result -OR- the result should + be limited to a scalar result. The + or method will + be called. + + + + + The command is expected to return result. + The or + method will + be called. + + + + + Use the default command execution type. Using this value is the same + as using the value. + + + + + The action code responsible for the current call into the authorizer. + + + + + No action is being performed. This value should not be used from + external code. + + + + + No longer used. + + + + + An index will be created. The action-specific arguments are the + index name and the table name. + + + + + + A table will be created. The action-specific arguments are the + table name and a null value. + + + + + A temporary index will be created. The action-specific arguments + are the index name and the table name. + + + + + A temporary table will be created. The action-specific arguments + are the table name and a null value. + + + + + A temporary trigger will be created. The action-specific arguments + are the trigger name and the table name. + + + + + A temporary view will be created. The action-specific arguments are + the view name and a null value. + + + + + A trigger will be created. The action-specific arguments are the + trigger name and the table name. + + + + + A view will be created. The action-specific arguments are the view + name and a null value. + + + + + A DELETE statement will be executed. The action-specific arguments + are the table name and a null value. + + + + + An index will be dropped. The action-specific arguments are the + index name and the table name. + + + + + A table will be dropped. The action-specific arguments are the tables + name and a null value. + + + + + A temporary index will be dropped. The action-specific arguments are + the index name and the table name. + + + + + A temporary table will be dropped. The action-specific arguments are + the table name and a null value. + + + + + A temporary trigger will be dropped. The action-specific arguments + are the trigger name and the table name. + + + + + A temporary view will be dropped. The action-specific arguments are + the view name and a null value. + + + + + A trigger will be dropped. The action-specific arguments are the + trigger name and the table name. + + + + + A view will be dropped. The action-specific arguments are the view + name and a null value. + + + + + An INSERT statement will be executed. The action-specific arguments + are the table name and a null value. + + + + + A PRAGMA statement will be executed. The action-specific arguments + are the name of the PRAGMA and the new value or a null value. + + + + + A table column will be read. The action-specific arguments are the + table name and the column name. + + + + + A SELECT statement will be executed. The action-specific arguments + are both null values. + + + + + A transaction will be started, committed, or rolled back. The + action-specific arguments are the name of the operation (BEGIN, + COMMIT, or ROLLBACK) and a null value. + + + + + An UPDATE statement will be executed. The action-specific arguments + are the table name and the column name. + + + + + A database will be attached to the connection. The action-specific + arguments are the database file name and a null value. + + + + + A database will be detached from the connection. The action-specific + arguments are the database name and a null value. + + + + + The schema of a table will be altered. The action-specific arguments + are the database name and the table name. + + + + + An index will be deleted and then recreated. The action-specific + arguments are the index name and a null value. + + + + + A table will be analyzed to gathers statistics about it. The + action-specific arguments are the table name and a null value. + + + + + A virtual table will be created. The action-specific arguments are + the table name and the module name. + + + + + A virtual table will be dropped. The action-specific arguments are + the table name and the module name. + + + + + A SQL function will be called. The action-specific arguments are a + null value and the function name. + + + + + A savepoint will be created, released, or rolled back. The + action-specific arguments are the name of the operation (BEGIN, + RELEASE, or ROLLBACK) and the savepoint name. + + + + + A recursive query will be executed. The action-specific arguments + are two null values. + + + + + The possible return codes for the progress callback. + + + + + The operation should continue. + + + + + The operation should be interrupted. + + + + + The return code for the current call into the authorizer. + + + + + The action will be allowed. + + + + + The overall action will be disallowed and an error message will be + returned from the query preparation method. + + + + + The specific action will be disallowed; however, the overall action + will continue. The exact effects of this return code vary depending + on the specific action, please refer to the SQLite core library + documentation for futher details. + + + + + Class used internally to determine the datatype of a column in a resultset + + + + + The DbType of the column, or DbType.Object if it cannot be determined + + + + + The affinity of a column, used for expressions or when Type is DbType.Object + + + + + Constructs a default instance of this type. + + + + + Constructs an instance of this type with the specified field values. + + + The type affinity to use for the new instance. + + + The database type to use for the new instance. + + + + + SQLite implementation of DbDataAdapter. + + + + + This class is just a shell around the DbDataAdapter. Nothing from + DbDataAdapter is overridden here, just a few constructors are defined. + + + Default constructor. + + + + + Constructs a data adapter using the specified select command. + + + The select command to associate with the adapter. + + + + + Constructs a data adapter with the supplied select command text and + associated with the specified connection. + + + The select command text to associate with the data adapter. + + + The connection to associate with the select command. + + + + + Constructs a data adapter with the specified select command text, + and using the specified database connection string. + + + The select command text to use to construct a select command. + + + A connection string suitable for passing to a new SQLiteConnection, + which is associated with the select command. + + + + + Constructs a data adapter with the specified select command text, + and using the specified database connection string. + + + The select command text to use to construct a select command. + + + A connection string suitable for passing to a new SQLiteConnection, + which is associated with the select command. + + + Non-zero to parse the connection string using the built-in (i.e. + framework provided) parser when opening the connection. + + + + + Cleans up resources (native and managed) associated with the current instance. + + + Zero when being disposed via garbage collection; otherwise, non-zero. + + + + + Row updating event handler + + + + + Row updated event handler + + + + + Raised by the underlying DbDataAdapter when a row is being updated + + The event's specifics + + + + Raised by DbDataAdapter after a row is updated + + The event's specifics + + + + Gets/sets the select command for this DataAdapter + + + + + Gets/sets the insert command for this DataAdapter + + + + + Gets/sets the update command for this DataAdapter + + + + + Gets/sets the delete command for this DataAdapter + + + + + SQLite implementation of DbDataReader. + + + + + Underlying command this reader is attached to + + + + + The flags pertaining to the associated connection (via the command). + + + + + Index of the current statement in the command being processed + + + + + Current statement being Read() + + + + + State of the current statement being processed. + -1 = First Step() executed, so the first Read() will be ignored + 0 = Actively reading + 1 = Finished reading + 2 = Non-row-returning statement, no records + + + + + Number of records affected by the insert/update statements executed on the command + + + + + Count of fields (columns) in the row-returning statement currently being processed + + + + + The number of calls to Step() that have returned true (i.e. the number of rows that + have been read in the current result set). + + + + + Maps the field (column) names to their corresponding indexes within the results. + + + + + Datatypes of active fields (columns) in the current statement, used for type-restricting data + + + + + The behavior of the datareader + + + + + If set, then dispose of the command object when the reader is finished + + + + + If set, then raise an exception when the object is accessed after being disposed. + + + + + An array of rowid's for the active statement if CommandBehavior.KeyInfo is specified + + + + + Matches the version of the connection. + + + + + The "stub" (i.e. placeholder) base schema name to use when returning + column schema information. Matches the base schema name used by the + associated connection. + + + + + Internal constructor, initializes the datareader and sets up to begin executing statements + + The SQLiteCommand this data reader is for + The expected behavior of the data reader + + + + Dispose of all resources used by this datareader. + + + + + + Closes the datareader, potentially closing the connection as well if CommandBehavior.CloseConnection was specified. + + + + + Throw an error if the datareader is closed + + + + + Throw an error if a row is not loaded + + + + + Enumerator support + + Returns a DbEnumerator object. + + + + Not implemented. Returns 0 + + + + + Returns the number of columns in the current resultset + + + + + Forces the connection flags cached by this data reader to be refreshed + from the underlying connection. + + + + + Returns the number of rows seen so far in the current result set. + + + + + Returns the number of visible fields in the current resultset + + + + + This method is used to make sure the result set is open and a row is currently available. + + + + + SQLite is inherently un-typed. All datatypes in SQLite are natively strings. The definition of the columns of a table + and the affinity of returned types are all we have to go on to type-restrict data in the reader. + + This function attempts to verify that the type of data being requested of a column matches the datatype of the column. In + the case of columns that are not backed into a table definition, we attempt to match up the affinity of a column (int, double, string or blob) + to a set of known types that closely match that affinity. It's not an exact science, but its the best we can do. + + + This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity. + + The index of the column to type-check + The type we want to get out of the column + + + + Invokes the data reader value callback configured for the database + type name associated with the specified column. If no data reader + value callback is available for the database type name, do nothing. + + + The index of the column being read. + + + The extra event data to pass into the callback. + + + Non-zero if the default handling for the data reader call should be + skipped. If this is set to non-zero and the necessary return value + is unavailable or unsuitable, an exception will be thrown. + + + + + Attempts to query the integer identifier for the current row. This + will not work for tables that were created WITHOUT ROWID -OR- if the + query does not include the "rowid" column or one of its aliases -OR- + if the was not created with the + flag. + + + The index of the BLOB column. + + + The integer identifier for the current row -OR- null if it could not + be determined. + + + + + Retrieves the column as a object. + This will not work for tables that were created WITHOUT ROWID + -OR- if the query does not include the "rowid" column or one + of its aliases -OR- if the was + not created with the + flag. + + The index of the column. + + Non-zero to open the blob object for read-only access. + + A new object. + + + + Retrieves the column as a boolean value + + The index of the column. + bool + + + + Retrieves the column as a single byte value + + The index of the column. + byte + + + + Retrieves a column as an array of bytes (blob) + + The index of the column. + The zero-based index of where to begin reading the data + The buffer to write the bytes into + The zero-based index of where to begin writing into the array + The number of bytes to retrieve + The actual number of bytes written into the array + + To determine the number of bytes in the column, pass a null value for the buffer. The total length will be returned. + + + + + Returns the column as a single character + + The index of the column. + char + + + + Retrieves a column as an array of chars (blob) + + The index of the column. + The zero-based index of where to begin reading the data + The buffer to write the characters into + The zero-based index of where to begin writing into the array + The number of bytes to retrieve + The actual number of characters written into the array + + To determine the number of characters in the column, pass a null value for the buffer. The total length will be returned. + + + + + Retrieves the name of the back-end datatype of the column + + The index of the column. + string + + + + Retrieve the column as a date/time value + + The index of the column. + DateTime + + + + Retrieve the column as a decimal value + + The index of the column. + decimal + + + + Returns the column as a double + + The index of the column. + double + + + + Determines and returns the of the + specified column. + + + The index of the column. + + + The associated with the specified + column, if any. + + + + + Returns the .NET type of a given column + + The index of the column. + Type + + + + Returns a column as a float value + + The index of the column. + float + + + + Returns the column as a Guid + + The index of the column. + Guid + + + + Returns the column as a short + + The index of the column. + Int16 + + + + Retrieves the column as an int + + The index of the column. + Int32 + + + + Retrieves the column as a long + + The index of the column. + Int64 + + + + Retrieves the name of the column + + The index of the column. + string + + + + Returns the name of the database associated with the specified column. + + The index of the column. + string + + + + Returns the name of the table associated with the specified column. + + The index of the column. + string + + + + Returns the original name of the specified column. + + The index of the column. + string + + + + Retrieves the i of a column, given its name + + The name of the column to retrieve + The int i of the column + + + + Schema information in SQLite is difficult to map into .NET conventions, so a lot of work must be done + to gather the necessary information so it can be represented in an ADO.NET manner. + + Returns a DataTable containing the schema information for the active SELECT statement being processed. + + + + Retrieves the column as a string + + The index of the column. + string + + + + Retrieves the column as an object corresponding to the underlying datatype of the column + + The index of the column. + object + + + + Retreives the values of multiple columns, up to the size of the supplied array + + The array to fill with values from the columns in the current resultset + The number of columns retrieved + + + + Returns a collection containing all the column names and values for the + current row of data in the current resultset, if any. If there is no + current row or no current resultset, an exception may be thrown. + + + The collection containing the column name and value information for the + current row of data in the current resultset or null if this information + cannot be obtained. + + + + + Returns True if the resultset has rows that can be fetched + + + + + Returns True if the data reader is closed + + + + + Returns True if the specified column is null + + The index of the column. + True or False + + + + Moves to the next resultset in multiple row-returning SQL command. + + True if the command was successful and a new resultset is available, False otherwise. + + + + This method attempts to query the database connection associated with + the data reader in use. If the underlying command or connection is + unavailable, a null value will be returned. + + + The connection object -OR- null if it is unavailable. + + + + + Retrieves the SQLiteType for a given column and row value. + + + The original SQLiteType structure, based only on the column. + + + The textual value of the column for a given row. + + + The SQLiteType structure. + + + + + Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls. + + The flags associated with the parent connection object. + The index of the column. + A SQLiteType structure + + + + Reads the next row from the resultset + + True if a new row was successfully loaded and is ready for processing + + + + Returns the number of rows affected by the statement being executed. + The value returned may not be accurate for DDL statements. Also, it + will be -1 for any statement that does not modify the database (e.g. + SELECT). If an otherwise read-only statement modifies the database + indirectly (e.g. via a virtual table or user-defined function), the + value returned is undefined. + + + + + Indexer to retrieve data from a column given its name + + The name of the column to retrieve data for + The value contained in the column + + + + Indexer to retrieve data from a column given its i + + The index of the column. + The value contained in the column + + + + SQLite exception class. + + + + + This value was copied from the "WinError.h" file included with the + Platform SDK for Windows 10. + + + + + Private constructor for use with serialization. + + + Holds the serialized object data about the exception being thrown. + + + Contains contextual information about the source or destination. + + + + + Public constructor for generating a SQLite exception given the error + code and message. + + + The SQLite return code to report. + + + Message text to go along with the return code message text. + + + + + Public constructor that uses the base class constructor for the error + message. + + Error message text. + + + + Public constructor that uses the default base class constructor. + + + + + Public constructor that uses the base class constructor for the error + message and inner exception. + + Error message text. + The original (inner) exception. + + + + Adds extra information to the serialized object data specific to this + class type. This is only used for serialization. + + + Holds the serialized object data about the exception being thrown. + + + Contains contextual information about the source or destination. + + + + + Gets the associated SQLite result code for this exception as a + . This property returns the same + underlying value as the property. + + + + + Gets the associated SQLite return code for this exception as an + . For desktop versions of the .NET Framework, + this property overrides the property of the same name within the + + class. This property returns the same underlying value as the + property. + + + + + This method performs extra initialization tasks. It may be called by + any of the constructors of this class. It must not throw exceptions. + + + + + Maps a Win32 error code to an HRESULT. + + + The specified Win32 error code. It must be within the range of zero + (0) to 0xFFFF (65535). + + + Non-zero if the HRESULT should indicate success; otherwise, zero. + + + The integer value of the HRESULT. + + + + + Attempts to map the specified onto an + existing HRESULT -OR- a Win32 error code wrapped in an HRESULT. The + mappings may not have perfectly matching semantics; however, they do + have the benefit of being unique within the context of this exception + type. + + + The to map. + + + The integer HRESULT value -OR- null if there is no known mapping. + + + + + Returns the error message for the specified SQLite return code. + + The SQLite return code. + The error message or null if it cannot be found. + + + + Returns the composite error message based on the SQLite return code + and the optional detailed error message. + + The SQLite return code. + Optional detailed error message. + Error message text for the return code. + + + + SQLite error codes. Actually, this enumeration represents a return code, + which may also indicate success in one of several ways (e.g. SQLITE_OK, + SQLITE_ROW, and SQLITE_DONE). Therefore, the name of this enumeration is + something of a misnomer. + + + + + The error code is unknown. This error code + is only used by the managed wrapper itself. + + + + + Successful result + + + + + SQL error or missing database + + + + + Internal logic error in SQLite + + + + + Access permission denied + + + + + Callback routine requested an abort + + + + + The database file is locked + + + + + A table in the database is locked + + + + + A malloc() failed + + + + + Attempt to write a readonly database + + + + + Operation terminated by sqlite3_interrupt() + + + + + Some kind of disk I/O error occurred + + + + + The database disk image is malformed + + + + + Unknown opcode in sqlite3_file_control() + + + + + Insertion failed because database is full + + + + + Unable to open the database file + + + + + Database lock protocol error + + + + + Database is empty + + + + + The database schema changed + + + + + String or BLOB exceeds size limit + + + + + Abort due to constraint violation + + + + + Data type mismatch + + + + + Library used incorrectly + + + + + Uses OS features not supported on host + + + + + Authorization denied + + + + + Auxiliary database format error + + + + + 2nd parameter to sqlite3_bind out of range + + + + + File opened that is not a database file + + + + + Notifications from sqlite3_log() + + + + + Warnings from sqlite3_log() + + + + + sqlite3_step() has another row ready + + + + + sqlite3_step() has finished executing + + + + + Used to mask off extended result codes + + + + + A collation sequence was referenced by a schema and it cannot be + found. + + + + + An internal operation failed and it may succeed if retried. + + + + + A file read operation failed. + + + + + A file read operation returned less data than requested. + + + + + A file write operation failed. + + + + + A file synchronization operation failed. + + + + + A directory synchronization operation failed. + + + + + A file truncate operation failed. + + + + + A file metadata operation failed. + + + + + A file unlock operation failed. + + + + + A file lock operation failed. + + + + + A file delete operation failed. + + + + + Not currently used. + + + + + Out-of-memory during a file operation. + + + + + A file existence/status operation failed. + + + + + A check for a reserved lock failed. + + + + + A file lock operation failed. + + + + + A file close operation failed. + + + + + A directory close operation failed. + + + + + A shared memory open operation failed. + + + + + A shared memory size operation failed. + + + + + A shared memory lock operation failed. + + + + + A shared memory map operation failed. + + + + + A file seek operation failed. + + + + + A file delete operation failed because it does not exist. + + + + + A file memory mapping operation failed. + + + + + The temporary directory path could not be obtained. + + + + + A path string conversion operation failed. + + + + + Reserved. + + + + + An attempt to authenticate failed. + + + + + An attempt to begin a file system transaction failed. + + + + + An attempt to commit a file system transaction failed. + + + + + An attempt to rollback a file system transaction failed. + + + + + A database table is locked in shared-cache mode. + + + + + A virtual table in the database is locked. + + + + + A database file is locked due to a recovery operation. + + + + + A database file is locked due to snapshot semantics. + + + + + A database file cannot be opened because no temporary directory is available. + + + + + A database file cannot be opened because its path represents a directory. + + + + + A database file cannot be opened because its full path could not be obtained. + + + + + A database file cannot be opened because a path string conversion operation failed. + + + + + A virtual table is malformed. + + + + + A required sequence table is missing or corrupt. + + + + + A database file is read-only due to a recovery operation. + + + + + A database file is read-only because a lock could not be obtained. + + + + + A database file is read-only because it needs rollback processing. + + + + + A database file is read-only because it was moved while open. + + + + + The shared-memory file is read-only and it should be read-write. + + + + + Unable to create journal file because the directory is read-only. + + + + + An operation is being aborted due to rollback processing. + + + + + A CHECK constraint failed. + + + + + A commit hook produced a unsuccessful return code. + + + + + A FOREIGN KEY constraint failed. + + + + + Not currently used. + + + + + A NOT NULL constraint failed. + + + + + A PRIMARY KEY constraint failed. + + + + + The RAISE function was used by a trigger-program. + + + + + A UNIQUE constraint failed. + + + + + Not currently used. + + + + + A ROWID constraint failed. + + + + + Frames were recovered from the WAL log file. + + + + + Pages were recovered from the journal file. + + + + + An automatic index was created to process a query. + + + + + User authentication failed. + + + + + Success. Prevents the extension from unloading until the process + terminates. + + + + + SQLite implementation of . + + + SQLite implementation of . + + + + + Constructs a new instance. + + + + + Cleans up resources (native and managed) associated with the current instance. + + + + + Cleans up resources associated with the current instance. + + + + + This event is raised whenever SQLite raises a logging event. + Note that this should be set as one of the first things in the + application. This event is provided for backward compatibility only. + New code should use the class instead. + + + + + Static instance member which returns an instanced class. + + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Creates and returns a new object. + + The new object. + + + + Will provide a object in .NET 3.5. + + The class or interface type to query for. + + + + + This abstract class is designed to handle user-defined functions easily. An instance of the derived class is made for each + connection to the database. + + + Although there is one instance of a class derived from SQLiteFunction per database connection, the derived class has no access + to the underlying connection. This is necessary to deter implementers from thinking it would be a good idea to make database + calls during processing. + + It is important to distinguish between a per-connection instance, and a per-SQL statement context. One instance of this class + services all SQL statements being stepped through on that connection, and there can be many. One should never store per-statement + information in member variables of user-defined function classes. + + For aggregate functions, always create and store your per-statement data in the contextData object on the 1st step. This data will + be automatically freed for you (and Dispose() called if the item supports IDisposable) when the statement completes. + + + + + The base connection this function is attached to + + + + + Internal array used to keep track of aggregate function context data + + + + + The connection flags associated with this object (this should be the + same value as the flags associated with the parent connection object). + + + + + Holds a reference to the callback function for user functions + + + + + Holds a reference to the callbakc function for stepping in an aggregate function + + + + + Holds a reference to the callback function for finalizing an aggregate function + + + + + Holds a reference to the callback function for collating sequences + + + + + Current context of the current callback. Only valid during a callback + + + + + This static dictionary contains all the registered (known) user-defined + functions declared using the proper attributes. The contained dictionary + values are always null and are not currently used. + + + + + Internal constructor, initializes the function's internal variables. + + + + + Constructs an instance of this class using the specified data-type + conversion parameters. + + + The DateTime format to be used when converting string values to a + DateTime and binding DateTime parameters. + + + The to be used when creating DateTime + values. + + + The format string to be used when parsing and formatting DateTime + values. + + + Non-zero to create a UTF-16 data-type conversion context; otherwise, + a UTF-8 data-type conversion context will be created. + + + + + Disposes of any active contextData variables that were not automatically cleaned up. Sometimes this can happen if + someone closes the connection while a DataReader is open. + + + + + Placeholder for a user-defined disposal routine + + True if the object is being disposed explicitly + + + + Cleans up resources associated with the current instance. + + + + + Returns a reference to the underlying connection's SQLiteConvert class, which can be used to convert + strings and DateTime's into the current connection's encoding schema. + + + + + Scalar functions override this method to do their magic. + + + Parameters passed to functions have only an affinity for a certain data type, there is no underlying schema available + to force them into a certain type. Therefore the only types you will ever see as parameters are + DBNull.Value, Int64, Double, String or byte[] array. + + The arguments for the command to process + You may return most simple types as a return value, null or DBNull.Value to return null, DateTime, or + you may return an Exception-derived class if you wish to return an error to SQLite. Do not actually throw the error, + just return it! + + + + Aggregate functions override this method to do their magic. + + + Typically you'll be updating whatever you've placed in the contextData field and returning as quickly as possible. + + The arguments for the command to process + The 1-based step number. This is incrememted each time the step method is called. + A placeholder for implementers to store contextual data pertaining to the current context. + + + + Aggregate functions override this method to finish their aggregate processing. + + + If you implemented your aggregate function properly, + you've been recording and keeping track of your data in the contextData object provided, and now at this stage you should have + all the information you need in there to figure out what to return. + NOTE: It is possible to arrive here without receiving a previous call to Step(), in which case the contextData will + be null. This can happen when no rows were returned. You can either return null, or 0 or some other custom return value + if that is the case. + + Your own assigned contextData, provided for you so you can return your final results. + You may return most simple types as a return value, null or DBNull.Value to return null, DateTime, or + you may return an Exception-derived class if you wish to return an error to SQLite. Do not actually throw the error, + just return it! + + + + + User-defined collating sequences override this method to provide a custom string sorting algorithm. + + The first string to compare. + The second strnig to compare. + 1 if param1 is greater than param2, 0 if they are equal, or -1 if param1 is less than param2. + + + + Converts an IntPtr array of context arguments to an object array containing the resolved parameters the pointers point to. + + + Parameters passed to functions have only an affinity for a certain data type, there is no underlying schema available + to force them into a certain type. Therefore the only types you will ever see as parameters are + DBNull.Value, Int64, Double, String or byte[] array. + + The number of arguments + A pointer to the array of arguments + An object array of the arguments once they've been converted to .NET values + + + + Takes the return value from Invoke() and Final() and figures out how to return it to SQLite's context. + + The context the return value applies to + The parameter to return to SQLite + + + + Internal scalar callback function, which wraps the raw context pointer and calls the virtual Invoke() method. + WARNING: Must not throw exceptions. + + A raw context pointer + Number of arguments passed in + A pointer to the array of arguments + + + + Internal collating sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. + WARNING: Must not throw exceptions. + + Not used + Length of the string pv1 + Pointer to the first string to compare + Length of the string pv2 + Pointer to the second string to compare + Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater + than the second. Returns 0 if an exception is caught. + + + + Internal collating sequence function, which wraps up the raw string pointers and executes the Compare() virtual function. + WARNING: Must not throw exceptions. + + Not used + Length of the string pv1 + Pointer to the first string to compare + Length of the string pv2 + Pointer to the second string to compare + Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater + than the second. Returns 0 if an exception is caught. + + + + The internal aggregate Step function callback, which wraps the raw context pointer and calls the virtual Step() method. + WARNING: Must not throw exceptions. + + + This function takes care of doing the lookups and getting the important information put together to call the Step() function. + That includes pulling out the user's contextData and updating it after the call is made. We use a sorted list for this so + binary searches can be done to find the data. + + A raw context pointer + Number of arguments passed in + A pointer to the array of arguments + + + + An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method. + WARNING: Must not throw exceptions. + + A raw context pointer + + + + Using reflection, enumerate all assemblies in the current appdomain looking for classes that + have a SQLiteFunctionAttribute attribute, and registering them accordingly. + + + + + Manual method of registering a function. The type must still have the SQLiteFunctionAttributes in order to work + properly, but this is a workaround for the Compact Framework where enumerating assemblies is not currently supported. + + The type of the function to register + + + + Alternative method of registering a function. This method + does not require the specified type to be annotated with + . + + + The name of the function to register. + + + The number of arguments accepted by the function. + + + The type of SQLite function being resitered (e.g. scalar, + aggregate, or collating sequence). + + + The that actually implements the function. + This will only be used if the + and parameters are null. + + + The to be used for all calls into the + , + , + and virtual methods. + + + The to be used for all calls into the + virtual method. This + parameter is only necessary for aggregate functions. + + + + + Replaces a registered function, disposing of the associated (old) + value if necessary. + + + The attribute that describes the function to replace. + + + The new value to use. + + + Non-zero if an existing registered function was replaced; otherwise, + zero. + + + + + Creates a instance based on the specified + . + + + The containing the metadata about + the function to create. + + + The created function -OR- null if the function could not be created. + + + Non-zero if the function was created; otherwise, zero. + + + + + Called by the SQLiteBase derived classes, this method binds all registered (known) user-defined functions to a connection. + It is done this way so that all user-defined functions will access the database using the same encoding scheme + as the connection (UTF-8 or UTF-16). + + + The wrapper functions that interop with SQLite will create a unique cookie value, which internally is a pointer to + all the wrapped callback functions. The interop function uses it to map CDecl callbacks to StdCall callbacks. + + The base object on which the functions are to bind. + The flags associated with the parent connection object. + Returns a logical list of functions which the connection should retain until it is closed. + + + + Called by the SQLiteBase derived classes, this method unbinds all registered (known) + functions -OR- all previously bound user-defined functions from a connection. + + The base object from which the functions are to be unbound. + The flags associated with the parent connection object. + + Non-zero to unbind all registered (known) functions -OR- zero to unbind all functions + currently bound to the connection. + + Non-zero if all the specified user-defined functions were unbound. + + + + This function binds a user-defined function to a connection. + + + The object instance associated with the + that the function should be bound to. + + + The object instance containing + the metadata for the function to be bound. + + + The object instance that implements the + function to be bound. + + + The flags associated with the parent connection object. + + + + + This function unbinds a user-defined functions from a connection. + + + The object instance associated with the + that the function should be bound to. + + + The object instance containing + the metadata for the function to be bound. + + + The object instance that implements the + function to be bound. + + + The flags associated with the parent connection object. + + Non-zero if the function was unbound. + + + + This type is used with the + method. + + + This is always the string literal "Invoke". + + + The arguments for the scalar function. + + + The result of the scalar function. + + + + + This type is used with the + method. + + + This is always the string literal "Step". + + + The arguments for the aggregate function. + + + The step number (one based). This is incrememted each time the + method is called. + + + A placeholder for implementers to store contextual data pertaining + to the current context. + + + + + This type is used with the + method. + + + This is always the string literal "Final". + + + A placeholder for implementers to store contextual data pertaining + to the current context. + + + The result of the aggregate function. + + + + + This type is used with the + method. + + + This is always the string literal "Compare". + + + The first string to compare. + + + The second strnig to compare. + + + A positive integer if the parameter is + greater than the parameter, a negative + integer if the parameter is less than + the parameter, or zero if they are + equal. + + + + + This class implements a SQLite function using a . + All the virtual methods of the class are + implemented using calls to the , + , , + and strongly typed delegate types + or via the method. + The arguments are presented in the same order they appear in + the associated methods with one exception: + the first argument is the name of the virtual method being implemented. + + + + + This error message is used by the overridden virtual methods when + a required property (e.g. + or ) has not been + set. + + + + + This error message is used by the overridden + method when the result does not have a type of . + + + + + Constructs an empty instance of this class. + + + + + Constructs an instance of this class using the specified + as the + implementation. + + + The to be used for all calls into the + , , and + virtual methods needed by the + base class. + + + The to be used for all calls into the + virtual methods needed by the + base class. + + + + + Returns the list of arguments for the method, + as an of . The first + argument is always the literal string "Invoke". + + + The original arguments received by the method. + + + Non-zero if the returned arguments are going to be used with the + type; otherwise, zero. + + + The arguments to pass to the configured . + + + + + Returns the list of arguments for the method, + as an of . The first + argument is always the literal string "Step". + + + The original arguments received by the method. + + + The step number (one based). This is incrememted each time the + method is called. + + + A placeholder for implementers to store contextual data pertaining + to the current context. + + + Non-zero if the returned arguments are going to be used with the + type; otherwise, zero. + + + The arguments to pass to the configured . + + + + + Updates the output arguments for the method, + using an of . The first + argument is always the literal string "Step". Currently, only the + parameter is updated. + + + The original arguments received by the method. + + + A placeholder for implementers to store contextual data pertaining + to the current context. + + + Non-zero if the returned arguments are going to be used with the + type; otherwise, zero. + + + The arguments to pass to the configured . + + + + + Returns the list of arguments for the method, + as an of . The first + argument is always the literal string "Final". + + + A placeholder for implementers to store contextual data pertaining + to the current context. + + + Non-zero if the returned arguments are going to be used with the + type; otherwise, zero. + + + The arguments to pass to the configured . + + + + + Returns the list of arguments for the method, + as an of . The first + argument is always the literal string "Compare". + + + The first string to compare. + + + The second strnig to compare. + + + Non-zero if the returned arguments are going to be used with the + type; otherwise, zero. + + + The arguments to pass to the configured . + + + + + The to be used for all calls into the + , , and + virtual methods needed by the + base class. + + + + + The to be used for all calls into the + virtual methods needed by the + base class. + + + + + This virtual method is the implementation for scalar functions. + See the method for more + details. + + + The arguments for the scalar function. + + + The result of the scalar function. + + + + + This virtual method is part of the implementation for aggregate + functions. See the method + for more details. + + + The arguments for the aggregate function. + + + The step number (one based). This is incrememted each time the + method is called. + + + A placeholder for implementers to store contextual data pertaining + to the current context. + + + + + This virtual method is part of the implementation for aggregate + functions. See the method + for more details. + + + A placeholder for implementers to store contextual data pertaining + to the current context. + + + The result of the aggregate function. + + + + + This virtual method is part of the implementation for collating + sequences. See the method + for more details. + + + The first string to compare. + + + The second strnig to compare. + + + A positive integer if the parameter is + greater than the parameter, a negative + integer if the parameter is less than + the parameter, or zero if they are + equal. + + + + + Extends SQLiteFunction and allows an inherited class to obtain the collating sequence associated with a function call. + + + User-defined functions can call the GetCollationSequence() method in this class and use it to compare strings and char arrays. + + + + + Obtains the collating sequence in effect for the given function. + + + + + + Cleans up resources (native and managed) associated with the current instance. + + + Zero when being disposed via garbage collection; otherwise, non-zero. + + + + + The type of user-defined function to declare + + + + + Scalar functions are designed to be called and return a result immediately. Examples include ABS(), Upper(), Lower(), etc. + + + + + Aggregate functions are designed to accumulate data until the end of a call and then return a result gleaned from the accumulated data. + Examples include SUM(), COUNT(), AVG(), etc. + + + + + Collating sequences are used to sort textual data in a custom manner, and appear in an ORDER BY clause. Typically text in an ORDER BY is + sorted using a straight case-insensitive comparison function. Custom collating sequences can be used to alter the behavior of text sorting + in a user-defined manner. + + + + + An internal callback delegate declaration. + + Raw native context pointer for the user function. + Total number of arguments to the user function. + Raw native pointer to the array of raw native argument pointers. + + + + An internal final callback delegate declaration. + + Raw context pointer for the user function + + + + Internal callback delegate for implementing collating sequences + + Not used + Length of the string pv1 + Pointer to the first string to compare + Length of the string pv2 + Pointer to the second string to compare + Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater + than the second. + + + + The type of collating sequence + + + + + The built-in BINARY collating sequence + + + + + The built-in NOCASE collating sequence + + + + + The built-in REVERSE collating sequence + + + + + A custom user-defined collating sequence + + + + + The encoding type the collation sequence uses + + + + + The collation sequence is UTF8 + + + + + The collation sequence is UTF16 little-endian + + + + + The collation sequence is UTF16 big-endian + + + + + A struct describing the collating sequence a function is executing in + + + + + The name of the collating sequence + + + + + The type of collating sequence + + + + + The text encoding of the collation sequence + + + + + Context of the function that requested the collating sequence + + + + + Calls the base collating sequence to compare two strings + + The first string to compare + The second string to compare + -1 if s1 is less than s2, 0 if s1 is equal to s2, and 1 if s1 is greater than s2 + + + + Calls the base collating sequence to compare two character arrays + + The first array to compare + The second array to compare + -1 if c1 is less than c2, 0 if c1 is equal to c2, and 1 if c1 is greater than c2 + + + + A simple custom attribute to enable us to easily find user-defined functions in + the loaded assemblies and initialize them in SQLite as connections are made. + + + + + Default constructor, initializes the internal variables for the function. + + + + + Constructs an instance of this class. This sets the initial + , , and + properties to null. + + + The name of the function, as seen by the SQLite core library. + + + The number of arguments that the function will accept. + + + The type of function being declared. This will either be Scalar, + Aggregate, or Collation. + + + + + The function's name as it will be used in SQLite command text. + + + + + The number of arguments this function expects. -1 if the number of arguments is variable. + + + + + The type of function this implementation will be. + + + + + The object instance that describes the class + containing the implementation for the associated function. The value of + this property will not be used if either the or + property values are set to non-null. + + + + + The that refers to the implementation for the + associated function. If this property value is set to non-null, it will + be used instead of the property value. + + + + + The that refers to the implementation for the + associated function. If this property value is set to non-null, it will + be used instead of the property value. + + + + + This class provides key info for a given SQLite statement. + + Providing key information for a given statement is non-trivial :( + + + + + + Used to support CommandBehavior.KeyInfo + + + + + Used to keep track of the per-table RowId column metadata. + + + + + A single sub-query for a given table/database. + + + + + This function does all the nasty work at determining what keys need to be returned for + a given statement. + + + + + + + + How many additional columns of keyinfo we're holding + + + + + Make sure all the subqueries are open and ready and sync'd with the current rowid + of the table they're supporting + + + + + Release any readers on any subqueries + + + + + Append all the columns we've added to the original query to the schema + + + + + + Event data for logging event handlers. + + + + + The error code. The type of this object value should be + or . + + + + + SQL statement text as the statement first begins executing + + + + + Extra data associated with this event, if any. + + + + + Constructs the object. + + Should be null. + + The error code. The type of this object value should be + or . + + The error message, if any. + The extra data, if any. + + + + Raised when a log event occurs. + + The current connection + Event arguments of the trace + + + + Manages the SQLite custom logging functionality and the associated + callback for the whole process. + + + + + Object used to synchronize access to the static instance data + for this class. + + + + + Member variable to store the AppDomain.DomainUnload event handler. + + + + + Member variable to store the application log handler to call. + + + + + The default log event handler. + + + + + The log callback passed to native SQLite engine. This must live + as long as the SQLite library has a pointer to it. + + + + + The base SQLite object to interop with. + + + + + This will be non-zero if an attempt was already made to initialize + the (managed) logging subsystem. + + + + + This will be non-zero if logging is currently enabled. + + + + + Initializes the SQLite logging facilities. + + + + + Initializes the SQLite logging facilities. + + + The name of the managed class that called this method. This + parameter may be null. + + + + + Handles the AppDomain being unloaded. + + Should be null. + The data associated with this event. + + + + This event is raised whenever SQLite raises a logging event. + Note that this should be set as one of the first things in the + application. + + + + + If this property is true, logging is enabled; otherwise, logging is + disabled. When logging is disabled, no logging events will fire. + + + + + Log a message to all the registered log event handlers without going + through the SQLite library. + + The message to be logged. + + + + Log a message to all the registered log event handlers without going + through the SQLite library. + + The SQLite error code. + The message to be logged. + + + + Log a message to all the registered log event handlers without going + through the SQLite library. + + The integer error code. + The message to be logged. + + + + Log a message to all the registered log event handlers without going + through the SQLite library. + + + The error code. The type of this object value should be + System.Int32 or SQLiteErrorCode. + + The message to be logged. + + + + Creates and initializes the default log event handler. + + + + + Adds the default log event handler to the list of handlers. + + + + + Removes the default log event handler from the list of handlers. + + + + + Internal proxy function that calls any registered application log + event handlers. + + WARNING: This method is used more-or-less directly by native code, + do not modify its type signature. + + + The extra data associated with this message, if any. + + + The error code associated with this message. + + + The message string to be logged. + + + + + Default logger. Currently, uses the Trace class (i.e. sends events + to the current trace listeners, if any). + + Should be null. + The data associated with this event. + + + + MetaDataCollections specific to SQLite + + + + + Returns a list of databases attached to the connection + + + + + Returns column information for the specified table + + + + + Returns index information for the optionally-specified table + + + + + Returns base columns for the given index + + + + + Returns the tables in the given catalog + + + + + Returns user-defined views in the given catalog + + + + + Returns underlying column information on the given view + + + + + Returns foreign key information for the given catalog + + + + + Returns the triggers on the database + + + + + SQLite implementation of DbParameter. + + + + + This value represents an "unknown" . + + + + + The command associated with this parameter. + + + + + The data type of the parameter + + + + + The version information for mapping the parameter + + + + + The value of the data in the parameter + + + + + The source column for the parameter + + + + + The column name + + + + + The data size, unused by SQLite + + + + + The database type name associated with this parameter, if any. + + + + + Constructor used when creating for use with a specific command. + + + The command associated with this parameter. + + + + + Default constructor + + + + + Constructs a named parameter given the specified parameter name + + The parameter name + + + + Constructs a named parameter given the specified parameter name and initial value + + The parameter name + The initial value of the parameter + + + + Constructs a named parameter of the specified type + + The parameter name + The datatype of the parameter + + + + Constructs a named parameter of the specified type and source column reference + + The parameter name + The data type + The source column + + + + Constructs a named parameter of the specified type, source column and row version + + The parameter name + The data type + The source column + The row version information + + + + Constructs an unnamed parameter of the specified data type + + The datatype of the parameter + + + + Constructs an unnamed parameter of the specified data type and sets the initial value + + The datatype of the parameter + The initial value of the parameter + + + + Constructs an unnamed parameter of the specified data type and source column + + The datatype of the parameter + The source column + + + + Constructs an unnamed parameter of the specified data type, source column and row version + + The data type + The source column + The row version information + + + + Constructs a named parameter of the specified type and size + + The parameter name + The data type + The size of the parameter + + + + Constructs a named parameter of the specified type, size and source column + + The name of the parameter + The data type + The size of the parameter + The source column + + + + Constructs a named parameter of the specified type, size, source column and row version + + The name of the parameter + The data type + The size of the parameter + The source column + The row version information + + + + Constructs a named parameter of the specified type, size, source column and row version + + The name of the parameter + The data type + The size of the parameter + Only input parameters are supported in SQLite + Ignored + Ignored + Ignored + The source column + The row version information + The initial value to assign the parameter + + + + Constructs a named parameter, yet another flavor + + The name of the parameter + The data type + The size of the parameter + Only input parameters are supported in SQLite + Ignored + Ignored + The source column + The row version information + Whether or not this parameter is for comparing NULL's + The intial value to assign the parameter + + + + Constructs an unnamed parameter of the specified type and size + + The data type + The size of the parameter + + + + Constructs an unnamed parameter of the specified type, size, and source column + + The data type + The size of the parameter + The source column + + + + Constructs an unnamed parameter of the specified type, size, source column and row version + + The data type + The size of the parameter + The source column + The row version information + + + + The command associated with this parameter. + + + + + Whether or not the parameter can contain a null value + + + + + Returns the datatype of the parameter + + + + + Supports only input parameters + + + + + Returns the parameter name + + + + + Resets the DbType of the parameter so it can be inferred from the value + + + + + Returns the size of the parameter + + + + + Gets/sets the source column + + + + + Used by DbCommandBuilder to determine the mapping for nullable fields + + + + + Gets and sets the row version + + + + + Gets and sets the parameter value. If no datatype was specified, the datatype will assume the type from the value given. + + + + + The database type name associated with this parameter, if any. + + + + + Clones a parameter + + A new, unassociated SQLiteParameter + + + + SQLite implementation of DbParameterCollection. + + + + + The underlying command to which this collection belongs + + + + + The internal array of parameters in this collection + + + + + Determines whether or not all parameters have been bound to their statement(s) + + + + + Initializes the collection + + The command to which the collection belongs + + + + Returns false + + + + + Returns false + + + + + Returns false + + + + + Returns null + + + + + Retrieves an enumerator for the collection + + An enumerator for the underlying array + + + + Adds a parameter to the collection + + The parameter name + The data type + The size of the value + The source column + A SQLiteParameter object + + + + Adds a parameter to the collection + + The parameter name + The data type + The size of the value + A SQLiteParameter object + + + + Adds a parameter to the collection + + The parameter name + The data type + A SQLiteParameter object + + + + Adds a parameter to the collection + + The parameter to add + A zero-based index of where the parameter is located in the array + + + + Adds a parameter to the collection + + The parameter to add + A zero-based index of where the parameter is located in the array + + + + Adds a named/unnamed parameter and its value to the parameter collection. + + Name of the parameter, or null to indicate an unnamed parameter + The initial value of the parameter + Returns the SQLiteParameter object created during the call. + + + + Adds an array of parameters to the collection + + The array of parameters to add + + + + Adds an array of parameters to the collection + + The array of parameters to add + + + + Clears the array and resets the collection + + + + + Determines if the named parameter exists in the collection + + The name of the parameter to check + True if the parameter is in the collection + + + + Determines if the parameter exists in the collection + + The SQLiteParameter to check + True if the parameter is in the collection + + + + Not implemented + + + + + + + Returns a count of parameters in the collection + + + + + Overloaded to specialize the return value of the default indexer + + Name of the parameter to get/set + The specified named SQLite parameter + + + + Overloaded to specialize the return value of the default indexer + + The index of the parameter to get/set + The specified SQLite parameter + + + + Retrieve a parameter by name from the collection + + The name of the parameter to fetch + A DbParameter object + + + + Retrieves a parameter by its index in the collection + + The index of the parameter to retrieve + A DbParameter object + + + + Returns the index of a parameter given its name + + The name of the parameter to find + -1 if not found, otherwise a zero-based index of the parameter + + + + Returns the index of a parameter + + The parameter to find + -1 if not found, otherwise a zero-based index of the parameter + + + + Inserts a parameter into the array at the specified location + + The zero-based index to insert the parameter at + The parameter to insert + + + + Removes a parameter from the collection + + The parameter to remove + + + + Removes a parameter from the collection given its name + + The name of the parameter to remove + + + + Removes a parameter from the collection given its index + + The zero-based parameter index to remove + + + + Re-assign the named parameter to a new parameter object + + The name of the parameter to replace + The new parameter + + + + Re-assign a parameter at the specified index + + The zero-based index of the parameter to replace + The new parameter + + + + Un-binds all parameters from their statements + + + + + This function attempts to map all parameters in the collection to all statements in a Command. + Since named parameters may span multiple statements, this function makes sure all statements are bound + to the same named parameter. Unnamed parameters are bound in sequence. + + + + + Represents a single SQL statement in SQLite. + + + + + The underlying SQLite object this statement is bound to + + + + + The command text of this SQL statement + + + + + The actual statement pointer + + + + + An index from which unnamed parameters begin + + + + + Names of the parameters as SQLite understands them to be + + + + + Parameters for this statement + + + + + Command this statement belongs to (if any) + + + + + The flags associated with the parent connection object. + + + + + Initializes the statement and attempts to get all information about parameters in the statement + + The base SQLite object + The flags associated with the parent connection object + The statement + The command text for this statement + The previous command in a multi-statement command + + + + Disposes and finalizes the statement + + + + + If the underlying database connection is open, fetches the number of changed rows + resulting from the most recent query; otherwise, does nothing. + + + The number of changes when true is returned. + Undefined if false is returned. + + + The read-only flag when true is returned. + Undefined if false is returned. + + Non-zero if the number of changed rows was fetched. + + + + Called by SQLiteParameterCollection, this function determines if the specified parameter name belongs to + this statement, and if so, keeps a reference to the parameter so it can be bound later. + + The parameter name to map + The parameter to assign it + + + + Bind all parameters, making sure the caller didn't miss any + + + + + This method attempts to query the database connection associated with + the statement in use. If the underlying command or connection is + unavailable, a null value will be returned. + + + The connection object -OR- null if it is unavailable. + + + + + Invokes the parameter binding callback configured for the database + type name associated with the specified column. If no parameter + binding callback is available for the database type name, do + nothing. + + + The index of the column being read. + + + The instance being bound to the + command. + + + Non-zero if the default handling for the parameter binding call + should be skipped (i.e. the parameter should not be bound at all). + Great care should be used when setting this to non-zero. + + + + + Perform the bind operation for an individual parameter + + The index of the parameter to bind + The parameter we're binding + + + + SQLite implementation of DbTransaction that does not support nested transactions. + + + + + Constructs the transaction object, binding it to the supplied connection + + The connection to open a transaction on + TRUE to defer the writelock, or FALSE to lock immediately + + + + Disposes the transaction. If it is currently active, any changes are rolled back. + + + + + Commits the current transaction. + + + + + Attempts to start a transaction. An exception will be thrown if the transaction cannot + be started for any reason. + + TRUE to defer the writelock, or FALSE to lock immediately + + + + Issue a ROLLBACK command against the database connection, + optionally re-throwing any caught exception. + + + Non-zero to re-throw caught exceptions. + + + + + SQLite implementation of DbTransaction that does support nested transactions. + + + + + The original transaction level for the associated connection + when this transaction was created (i.e. begun). + + + + + The SAVEPOINT name for this transaction, if any. This will + only be non-null if this transaction is a nested one. + + + + + Constructs the transaction object, binding it to the supplied connection + + The connection to open a transaction on + TRUE to defer the writelock, or FALSE to lock immediately + + + + Disposes the transaction. If it is currently active, any changes are rolled back. + + + + + Commits the current transaction. + + + + + Attempts to start a transaction. An exception will be thrown if the transaction cannot + be started for any reason. + + TRUE to defer the writelock, or FALSE to lock immediately + + + + Issue a ROLLBACK command against the database connection, + optionally re-throwing any caught exception. + + + Non-zero to re-throw caught exceptions. + + + + + Constructs the name of a new savepoint for this transaction. It + should only be called from the constructor of this class. + + + The name of the new savepoint -OR- null if it cannot be constructed. + + + + + Base class used by to implement DbTransaction for SQLite. + + + + + The connection to which this transaction is bound. + + + + + Matches the version of the connection. + + + + + The isolation level for this transaction. + + + + + Constructs the transaction object, binding it to the supplied connection + + The connection to open a transaction on + TRUE to defer the writelock, or FALSE to lock immediately + + + + Gets the isolation level of the transaction. SQLite only supports Serializable transactions. + + + + + Disposes the transaction. If it is currently active, any changes are rolled back. + + + + + Returns the underlying connection to which this transaction applies. + + + + + Forwards to the local Connection property + + + + + Rolls back the active transaction. + + + + + Attempts to start a transaction. An exception will be thrown if the transaction cannot + be started for any reason. + + TRUE to defer the writelock, or FALSE to lock immediately + + + + Issue a ROLLBACK command against the database connection, + optionally re-throwing any caught exception. + + + Non-zero to re-throw caught exceptions. + + + + + Checks the state of this transaction, optionally throwing an exception if a state + inconsistency is found. + + + Non-zero to throw an exception if a state inconsistency is found. + + + Non-zero if this transaction is valid; otherwise, false. + + + + + This static class provides some methods that are shared between the + native library pre-loader and other classes. + + + + + This lock is used to protect the static and + fields. + + + + + This type is only present when running on Mono. + + + + + This type is only present when running on .NET Core. + + + + + Keeps track of whether we are running on Mono. Initially null, it is + set by the method on its first call. Later, it + is returned verbatim by the method. + + + + + Keeps track of whether we are running on .NET Core. Initially null, + it is set by the method on its first + call. Later, it is returned verbatim by the + method. + + + + + Keeps track of whether we successfully invoked the + method. Initially null, it is set by + the method on its first call. + + + + + Determines the ID of the current process. Only used for debugging. + + + The ID of the current process -OR- zero if it cannot be determined. + + + + + Determines whether or not this assembly is running on Mono. + + + Non-zero if this assembly is running on Mono. + + + + + Determines whether or not this assembly is running on .NET Core. + + + Non-zero if this assembly is running on .NET Core. + + + + + Resets the cached value for the "PreLoadSQLite_BreakIntoDebugger" + configuration setting. + + + + + If the "PreLoadSQLite_BreakIntoDebugger" configuration setting is + present (e.g. via the environment), give the interactive user an + opportunity to attach a debugger to the current process; otherwise, + do nothing. + + + + + Determines the ID of the current thread. Only used for debugging. + + + The ID of the current thread -OR- zero if it cannot be determined. + + + + + Determines if the specified flags are present within the flags + associated with the parent connection object. + + + The flags associated with the parent connection object. + + + The flags to check for. + + + Non-zero if the specified flag or flags were present; otherwise, + zero. + + + + + Determines if preparing a query should be logged. + + + The flags associated with the parent connection object. + + + Non-zero if the query preparation should be logged; otherwise, zero. + + + + + Determines if pre-parameter binding should be logged. + + + The flags associated with the parent connection object. + + + Non-zero if the pre-parameter binding should be logged; otherwise, + zero. + + + + + Determines if parameter binding should be logged. + + + The flags associated with the parent connection object. + + + Non-zero if the parameter binding should be logged; otherwise, zero. + + + + + Determines if an exception in a native callback should be logged. + + + The flags associated with the parent connection object. + + + Non-zero if the exception should be logged; otherwise, zero. + + + + + Determines if backup API errors should be logged. + + + The flags associated with the parent connection object. + + + Non-zero if the backup API error should be logged; otherwise, zero. + + + + + Determines if logging for the class is + disabled. + + + The flags associated with the parent connection object. + + + Non-zero if logging for the class is + disabled; otherwise, zero. + + + + + Determines if errors should be logged. + + + The flags associated with the parent connection object. + + + Non-zero if the error should be logged; + otherwise, zero. + + + + + Determines if exceptions should be + logged. + + + The flags associated with the parent connection object. + + + Non-zero if the exception should be + logged; otherwise, zero. + + + + + Determines if the current process is running on one of the Windows + [sub-]platforms. + + + Non-zero when running on Windows; otherwise, zero. + + + + + This is a wrapper around the + method. + On Mono, it has to call the method overload without the + parameter, due to a bug in Mono. + + + This is used for culture-specific formatting. + + + The format string. + + + An array the objects to format. + + + The resulting string. + + + + + This static class provides a thin wrapper around the native library + loading features of the underlying platform. + + + + + This delegate is used to wrap the concept of loading a native + library, based on a file name, and returning the loaded module + handle. + + + The file name of the native library to load. + + + The native module handle upon success -OR- IntPtr.Zero on failure. + + + + + This delegate is used to wrap the concept of querying the machine + name of the current process. + + + The machine name for the current process -OR- null on failure. + + + + + Attempts to load the specified native library file using the Win32 + API. + + + The file name of the native library to load. + + + The native module handle upon success -OR- IntPtr.Zero on failure. + + + + + Attempts to determine the machine name of the current process using + the Win32 API. + + + The machine name for the current process -OR- null on failure. + + + + + Attempts to load the specified native library file using the POSIX + API. + + + The file name of the native library to load. + + + The native module handle upon success -OR- IntPtr.Zero on failure. + + + + + Attempts to determine the machine name of the current process using + the POSIX API. + + + The machine name for the current process -OR- null on failure. + + + + + Attempts to load the specified native library file. + + + The file name of the native library to load. + + + The native module handle upon success -OR- IntPtr.Zero on failure. + + + + + Attempts to determine the machine name of the current process. + + + The machine name for the current process -OR- null on failure. + + + + + This class declares P/Invoke methods to call native POSIX APIs. + + + + + This structure is used when running on POSIX operating systems + to store information about the current machine, including the + human readable name of the operating system as well as that of + the underlying hardware. + + + + + This structure is passed directly to the P/Invoke method to + obtain the information about the current machine, including + the human readable name of the operating system as well as + that of the underlying hardware. + + + + + This is the P/Invoke method that wraps the native Unix uname + function. See the POSIX documentation for full details on what it + does. + + + Structure containing a preallocated byte buffer to fill with the + requested information. + + + Zero for success and less than zero upon failure. + + + + + This is the P/Invoke method that wraps the native Unix dlopen + function. See the POSIX documentation for full details on what it + does. + + + The name of the executable library. + + + This must be a combination of the individual bit flags RTLD_LAZY, + RTLD_NOW, RTLD_GLOBAL, and/or RTLD_LOCAL. + + + The native module handle upon success -OR- IntPtr.Zero on failure. + + + + + This is the P/Invoke method that wraps the native Unix dlclose + function. See the POSIX documentation for full details on what it + does. + + + The handle to the loaded native library. + + + Zero upon success -OR- non-zero on failure. + + + + + For use with dlopen(), bind function calls lazily. + + + + + For use with dlopen(), bind function calls immediately. + + + + + For use with dlopen(), make symbols globally available. + + + + + For use with dlopen(), opposite of RTLD_GLOBAL, and the default. + + + + + For use with dlopen(), the defaults used by this class. + + + + + These are the characters used to separate the string fields within + the raw buffer returned by the P/Invoke method. + + + + + This method is a wrapper around the P/Invoke + method that extracts and returns the human readable strings from + the raw buffer. + + + This structure, which contains strings, will be filled based on the + data placed in the raw buffer returned by the + P/Invoke method. + + + Non-zero upon success; otherwise, zero. + + + + + This class declares P/Invoke methods to call native Win32 APIs. + + + + + This is the P/Invoke method that wraps the native Win32 LoadLibrary + function. See the MSDN documentation for full details on what it + does. + + + The name of the executable library. + + + The native module handle upon success -OR- IntPtr.Zero on failure. + + + + + This is the P/Invoke method that wraps the native Win32 GetSystemInfo + function. See the MSDN documentation for full details on what it + does. + + + The system information structure to be filled in by the function. + + + + + This enumeration contains the possible values for the processor + architecture field of the system information structure. + + + + + This structure contains information about the current computer. This + includes the processor type, page size, memory addresses, etc. + + + + + This class declares P/Invoke methods to call native SQLite APIs. + + + + + The file extension used for dynamic link libraries. + + + + + The file extension used for the XML configuration file. + + + + + This is the name of the XML configuration file specific to the + System.Data.SQLite assembly. + + + + + This is the XML configuratrion file token that will be replaced with + the qualified path to the directory containing the XML configuration + file. + + + + + This is the environment variable token that will be replaced with + the qualified path to the directory containing this assembly. + + + + + This is the environment variable token that will be replaced with an + abbreviation of the target framework attribute value associated with + this assembly. + + + + + This lock is used to protect the static _SQLiteNativeModuleFileName, + _SQLiteNativeModuleHandle, and processorArchitecturePlatforms fields. + + + + + This dictionary stores the mappings between processor architecture + names and platform names. These mappings are now used for two + purposes. First, they are used to determine if the assembly code + base should be used instead of the location, based upon whether one + or more of the named sub-directories exist within the assembly code + base. Second, they are used to assist in loading the appropriate + SQLite interop assembly into the current process. + + + + + This is the cached return value from the + method -OR- null if that method + has never returned a valid value. + + + + + When this field is non-zero, it indicates the + method was not able to locate a + suitable assembly directory. The + method will check this + field and skips calls into the + method whenever it is non-zero. + + + + + This is the cached return value from the + method -OR- null if that method + has never returned a valid value. + + + + + When this field is non-zero, it indicates the + method was not able to locate a + suitable XML configuration file name. The + method will check this + field and skips calls into the + method whenever it is non-zero. + + + + + For now, this method simply calls the Initialize method. + + + + + Attempts to initialize this class by pre-loading the native SQLite + library for the processor architecture of the current process. + + + + + Combines two path strings. + + + The first path -OR- null. + + + The second path -OR- null. + + + The combined path string -OR- null if both of the original path + strings are null. + + + + + Resets the cached XML configuration file name value, thus forcing the + next call to method to rely + upon the method to fetch the + XML configuration file name. + + + + + Queries and returns the cached XML configuration file name for the + assembly containing the managed System.Data.SQLite components, if + available. If the cached XML configuration file name value is not + available, the method will + be used to obtain the XML configuration file name. + + + The XML configuration file name -OR- null if it cannot be determined + or does not exist. + + + + + Queries and returns the XML configuration file name for the assembly + containing the managed System.Data.SQLite components. + + + The XML configuration file name -OR- null if it cannot be determined + or does not exist. + + + + + If necessary, replaces all supported XML configuration file tokens + with their associated values. + + + The name of the XML configuration file being read. + + + A setting value read from the XML configuration file. + + + The value of the will all supported XML + configuration file tokens replaced. No return value is reserved + to indicate an error. This method cannot fail. + + + + + Queries and returns the value of the specified setting, using the + specified XML configuration file. + + + The name of the XML configuration file to read. + + + The name of the setting. + + + The value to be returned if the setting has not been set explicitly + or cannot be determined. + + + Non-zero to expand any environment variable references contained in + the setting value to be returned. This has no effect on the .NET + Compact Framework. + + + The value of the setting -OR- the default value specified by + if it has not been set explicitly or + cannot be determined. + + + + + Attempts to determine the target framework attribute value that is + associated with the specified managed assembly, if applicable. + + + The managed assembly to read the target framework attribute value + from. + + + The value of the target framework attribute value for the specified + managed assembly -OR- null if it cannot be determined. If this + assembly was compiled with a version of the .NET Framework prior to + version 4.0, the value returned MAY reflect that version of the .NET + Framework instead of the one associated with the specified managed + assembly. + + + + + Accepts a long target framework attribute value and makes it into a + much shorter version, suitable for use with NuGet packages. + + + The long target framework attribute value to convert. + + + The short target framework attribute value -OR- null if it cannot + be determined or converted. + + + + + If necessary, replaces all supported environment variable tokens + with their associated values. + + + A setting value read from an environment variable. + + + The value of the will all supported + environment variable tokens replaced. No return value is reserved + to indicate an error. This method cannot fail. + + + + + Queries and returns the value of the specified setting, using the XML + configuration file and/or the environment variables for the current + process and/or the current system, when available. + + + The name of the setting. + + + The value to be returned if the setting has not been set explicitly + or cannot be determined. + + + The value of the setting -OR- the default value specified by + if it has not been set explicitly or + cannot be determined. By default, all references to existing + environment variables will be expanded to their corresponding values + within the value to be returned unless either the "No_Expand" or + "No_Expand_" environment variable is set [to + anything]. + + + + + Resets the cached assembly directory value, thus forcing the next + call to method to rely + upon the method to fetch the + assembly directory. + + + + + Queries and returns the cached directory for the assembly currently + being executed, if available. If the cached assembly directory value + is not available, the method will + be used to obtain the assembly directory. + + + The directory for the assembly currently being executed -OR- null if + it cannot be determined. + + + + + Queries and returns the directory for the assembly currently being + executed. + + + The directory for the assembly currently being executed -OR- null if + it cannot be determined. + + + + + The name of the environment variable containing the processor + architecture of the current process. + + + + + The native module file name for the native SQLite library or null. + + + + + The native module handle for the native SQLite library or the value + IntPtr.Zero. + + + + + Determines the base file name (without any directory information) + for the native SQLite library to be pre-loaded by this class. + + + The base file name for the native SQLite library to be pre-loaded by + this class -OR- null if its value cannot be determined. + + + + + Searches for the native SQLite library in the directory containing + the assembly currently being executed as well as the base directory + for the current application domain. + + + Upon success, this parameter will be modified to refer to the base + directory containing the native SQLite library. + + + Upon success, this parameter will be modified to refer to the name + of the immediate directory (i.e. the offset from the base directory) + containing the native SQLite library. + + + Upon success, this parameter will be modified to non-zero only if + the base directory itself should be allowed for loading the native + library. + + + Non-zero (success) if the native SQLite library was found; otherwise, + zero (failure). + + + + + Queries and returns the base directory of the current application + domain. + + + The base directory for the current application domain -OR- null if it + cannot be determined. + + + + + Determines if the dynamic link library file name requires a suffix + and adds it if necessary. + + + The original dynamic link library file name to inspect. + + + The dynamic link library file name, possibly modified to include an + extension. + + + + + Queries and returns the processor architecture of the current + process. + + + The processor architecture of the current process -OR- null if it + cannot be determined. + + + + + Given the processor architecture, returns the name of the platform. + + + The processor architecture to be translated to a platform name. + + + The platform name for the specified processor architecture -OR- null + if it cannot be determined. + + + + + Attempts to load the native SQLite library based on the specified + directory and processor architecture. + + + The base directory to use, null for default (the base directory of + the current application domain). This directory should contain the + processor architecture specific sub-directories. + + + The requested processor architecture, null for default (the + processor architecture of the current process). This caller should + almost always specify null for this parameter. + + + Non-zero indicates that the native SQLite library can be loaded + from the base directory itself. + + + The candidate native module file name to load will be stored here, + if necessary. + + + The native module handle as returned by LoadLibrary will be stored + here, if necessary. This value will be IntPtr.Zero if the call to + LoadLibrary fails. + + + Non-zero if the native module was loaded successfully; otherwise, + zero. + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to <?xml version="1.0" standalone="yes"?> + <DocumentElement> + <DataTypes> + <TypeName>smallint</TypeName> + <ProviderDbType>10</ProviderDbType> + <ColumnSize>5</ColumnSize> + <DataType>System.Int16</DataType> + <CreateFormat>smallint</CreateFormat> + <IsAutoIncrementable>false</IsAutoIncrementable> + <IsCaseSensitive>false</IsCaseSensitive> + <IsFixedLength>true</IsFixedLength> + <IsFixedPrecisionScale>true</IsFixedPrecisionScale> + <IsLong>false</IsLong> + <IsNullable>true</ [rest of string was truncated]";. + + + + + Looks up a localized string similar to ALL,ALTER,AND,AS,AUTOINCREMENT,BETWEEN,BY,CASE,CHECK,COLLATE,COMMIT,CONSTRAINT,CREATE,CROSS,DEFAULT,DEFERRABLE,DELETE,DISTINCT,DROP,ELSE,ESCAPE,EXCEPT,FOREIGN,FROM,FULL,GROUP,HAVING,IN,INDEX,INNER,INSERT,INTERSECT,INTO,IS,ISNULL,JOIN,LEFT,LIMIT,NATURAL,NOT,NOTNULL,NULL,ON,OR,ORDER,OUTER,PRIMARY,REFERENCES,RIGHT,ROLLBACK,SELECT,SET,TABLE,THEN,TO,TRANSACTION,UNION,UNIQUE,UPDATE,USING,VALUES,WHEN,WHERE. + + + + + Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> + <DocumentElement> + <MetaDataCollections> + <CollectionName>MetaDataCollections</CollectionName> + <NumberOfRestrictions>0</NumberOfRestrictions> + <NumberOfIdentifierParts>0</NumberOfIdentifierParts> + </MetaDataCollections> + <MetaDataCollections> + <CollectionName>DataSourceInformation</CollectionName> + <NumberOfRestrictions>0</NumberOfRestrictions> + <NumberOfIdentifierParts>0</NumberOfIdentifierParts> + </MetaDataCollections> + <MetaDataC [rest of string was truncated]";. + + + + + This interface represents a virtual table implementation written in + native code. + + + + + + int (*xCreate)(sqlite3 *db, void *pAux, + int argc, char *const*argv, + sqlite3_vtab **ppVTab, + char **pzErr); + + + The xCreate method is called to create a new instance of a virtual table + in response to a CREATE VIRTUAL TABLE statement. + If the xCreate method is the same pointer as the xConnect method, then the + virtual table is an eponymous virtual table. + If the xCreate method is omitted (if it is a NULL pointer) then the virtual + table is an eponymous-only virtual table. + + + The db parameter is a pointer to the SQLite database connection that + is executing the CREATE VIRTUAL TABLE statement. + The pAux argument is the copy of the client data pointer that was the + fourth argument to the sqlite3_create_module() or + sqlite3_create_module_v2() call that registered the + virtual table module. + The argv parameter is an array of argc pointers to null terminated strings. + The first string, argv[0], is the name of the module being invoked. The + module name is the name provided as the second argument to + sqlite3_create_module() and as the argument to the USING clause of the + CREATE VIRTUAL TABLE statement that is running. + The second, argv[1], is the name of the database in which the new virtual table is being created. The database name is "main" for the primary database, or + "temp" for TEMP database, or the name given at the end of the ATTACH + statement for attached databases. The third element of the array, argv[2], + is the name of the new virtual table, as specified following the TABLE + keyword in the CREATE VIRTUAL TABLE statement. + If present, the fourth and subsequent strings in the argv[] array report + the arguments to the module name in the CREATE VIRTUAL TABLE statement. + + + The job of this method is to construct the new virtual table object + (an sqlite3_vtab object) and return a pointer to it in *ppVTab. + + + As part of the task of creating a new sqlite3_vtab structure, this + method must invoke sqlite3_declare_vtab() to tell the SQLite + core about the columns and datatypes in the virtual table. + The sqlite3_declare_vtab() API has the following prototype: + + + int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable) + + + The first argument to sqlite3_declare_vtab() must be the same + database connection pointer as the first parameter to this method. + The second argument to sqlite3_declare_vtab() must a zero-terminated + UTF-8 string that contains a well-formed CREATE TABLE statement that + defines the columns in the virtual table and their data types. + The name of the table in this CREATE TABLE statement is ignored, + as are all constraints. Only the column names and datatypes matter. + The CREATE TABLE statement string need not to be + held in persistent memory. The string can be + deallocated and/or reused as soon as the sqlite3_declare_vtab() + routine returns. + + + The xCreate method need not initialize the pModule, nRef, and zErrMsg + fields of the sqlite3_vtab object. The SQLite core will take care of + that chore. + + + The xCreate should return SQLITE_OK if it is successful in + creating the new virtual table, or SQLITE_ERROR if it is not successful. + If not successful, the sqlite3_vtab structure must not be allocated. + An error message may optionally be returned in *pzErr if unsuccessful. + Space to hold the error message string must be allocated using + an SQLite memory allocation function like + sqlite3_malloc() or sqlite3_mprintf() as the SQLite core will + attempt to free the space using sqlite3_free() after the error has + been reported up to the application. + + + If the xCreate method is omitted (left as a NULL pointer) then the + virtual table is an eponymous-only virtual table. New instances of + the virtual table cannot be created using CREATE VIRTUAL TABLE and the + virtual table can only be used via its module name. + Note that SQLite versions prior to 3.9.0 (2015-10-14) do not understand + eponymous-only virtual tables and will segfault if an attempt is made + to CREATE VIRTUAL TABLE on an eponymous-only virtual table because + the xCreate method was not checked for null. + + + If the xCreate method is the exact same pointer as the xConnect method, + that indicates that the virtual table does not need to initialize backing + store. Such a virtual table can be used as an eponymous virtual table + or as a named virtual table using CREATE VIRTUAL TABLE or both. + + + If a column datatype contains the special keyword "HIDDEN" + (in any combination of upper and lower case letters) then that keyword + it is omitted from the column datatype name and the column is marked + as a hidden column internally. + A hidden column differs from a normal column in three respects: + + + ]]> + ]]> Hidden columns are not listed in the dataset returned by + "PRAGMA table_info", + ]]>]]> Hidden columns are not included in the expansion of a "*" + expression in the result set of a SELECT, and + ]]>]]> Hidden columns are not included in the implicit column-list + used by an INSERT statement that lacks an explicit column-list. + ]]>]]> + + + For example, if the following SQL is passed to sqlite3_declare_vtab(): + + + CREATE TABLE x(a HIDDEN VARCHAR(12), b INTEGER, c INTEGER Hidden); + + + Then the virtual table would be created with two hidden columns, + and with datatypes of "VARCHAR(12)" and "INTEGER". + + + An example use of hidden columns can be seen in the FTS3 virtual + table implementation, where every FTS virtual table + contains an FTS hidden column that is used to pass information from the + virtual table into FTS auxiliary functions and to the FTS MATCH operator. + + + A virtual table that contains hidden columns can be used like + a table-valued function in the FROM clause of a SELECT statement. + The arguments to the table-valued function become constraints on + the HIDDEN columns of the virtual table. + + + For example, the "generate_series" extension (located in the + ext/misc/series.c + file in the source tree) + implements an eponymous virtual table with the following schema: + + + CREATE TABLE generate_series( + value, + start HIDDEN, + stop HIDDEN, + step HIDDEN + ); + + + The sqlite3_module.xBestIndex method in the implementation of this + table checks for equality constraints against the HIDDEN columns, and uses + those as input parameters to determine the range of integer "value" outputs + to generate. Reasonable defaults are used for any unconstrained columns. + For example, to list all integers between 5 and 50: + + + SELECT value FROM generate_series(5,50); + + + The previous query is equivalent to the following: + + + SELECT value FROM generate_series WHERE start=5 AND stop=50; + + + Arguments on the virtual table name are matched to hidden columns + in order. The number of arguments can be less than the + number of hidden columns, in which case the latter hidden columns are + unconstrained. However, an error results if there are more arguments + than there are hidden columns in the virtual table. + + + Beginning with SQLite version 3.14.0 (2016-08-08), + the CREATE TABLE statement that + is passed into sqlite3_declare_vtab() may contain a WITHOUT ROWID clause. + This is useful for cases where the virtual table rows + cannot easily be mapped into unique integers. A CREATE TABLE + statement that includes WITHOUT ROWID must define one or more columns as + the PRIMARY KEY. Every column of the PRIMARY KEY must individually be + NOT NULL and all columns for each row must be collectively unique. + + + Note that SQLite does not enforce the PRIMARY KEY for a WITHOUT ROWID + virtual table. Enforcement is the responsibility of the underlying + virtual table implementation. But SQLite does assume that the PRIMARY KEY + constraint is valid - that the identified columns really are UNIQUE and + NOT NULL - and it uses that assumption to optimize queries against the + virtual table. + + + The rowid column is not accessible on a + WITHOUT ROWID virtual table (of course). + + + The xUpdate method was originally designed around having a + ROWID as a single value. The xUpdate method has been expanded to + accommodate an arbitrary PRIMARY KEY in place of the ROWID, but the + PRIMARY KEY must still be only one column. For this reason, SQLite + will reject any WITHOUT ROWID virtual table that has more than one + PRIMARY KEY column and a non-NULL xUpdate method. + + + + The native database connection handle. + + + The original native pointer value that was provided to the + sqlite3_create_module(), sqlite3_create_module_v2() or + sqlite3_create_disposable_module() functions. + + + The number of arguments from the CREATE VIRTUAL TABLE statement. + + + The array of string arguments from the CREATE VIRTUAL TABLE + statement. + + + Upon success, this parameter must be modified to point to the newly + created native sqlite3_vtab derived structure. + + + Upon failure, this parameter must be modified to point to the error + message, with the underlying memory having been obtained from the + sqlite3_malloc() function. + + + A standard SQLite return code. + + + + + + int (*xConnect)(sqlite3*, void *pAux, + int argc, char *const*argv, + sqlite3_vtab **ppVTab, + char **pzErr); + + + The xConnect method is very similar to xCreate. + It has the same parameters and constructs a new sqlite3_vtab structure + just like xCreate. + And it must also call sqlite3_declare_vtab() like xCreate. + + + The difference is that xConnect is called to establish a new + connection to an existing virtual table whereas xCreate is called + to create a new virtual table from scratch. + + + The xCreate and xConnect methods are only different when the + virtual table has some kind of backing store that must be initialized + the first time the virtual table is created. The xCreate method creates + and initializes the backing store. The xConnect method just connects + to an existing backing store. When xCreate and xConnect are the same, + the table is an eponymous virtual table. + + + As an example, consider a virtual table implementation that + provides read-only access to existing comma-separated-value (CSV) + files on disk. There is no backing store that needs to be created + or initialized for such a virtual table (since the CSV files already + exist on disk) so the xCreate and xConnect methods will be identical + for that module. + + + Another example is a virtual table that implements a full-text index. + The xCreate method must create and initialize data structures to hold + the dictionary and posting lists for that index. The xConnect method, + on the other hand, only has to locate and use an existing dictionary + and posting lists that were created by a prior xCreate call. + + + The xConnect method must return SQLITE_OK if it is successful + in creating the new virtual table, or SQLITE_ERROR if it is not + successful. If not successful, the sqlite3_vtab structure must not be + allocated. An error message may optionally be returned in *pzErr if + unsuccessful. + Space to hold the error message string must be allocated using + an SQLite memory allocation function like + sqlite3_malloc() or sqlite3_mprintf() as the SQLite core will + attempt to free the space using sqlite3_free() after the error has + been reported up to the application. + + + The xConnect method is required for every virtual table implementation, + though the xCreate and xConnect pointers of the sqlite3_module object + may point to the same function if the virtual table does not need to + initialize backing store. + + + + The native database connection handle. + + + The original native pointer value that was provided to the + sqlite3_create_module(), sqlite3_create_module_v2() or + sqlite3_create_disposable_module() functions. + + + The number of arguments from the CREATE VIRTUAL TABLE statement. + + + The array of string arguments from the CREATE VIRTUAL TABLE + statement. + + + Upon success, this parameter must be modified to point to the newly + created native sqlite3_vtab derived structure. + + + Upon failure, this parameter must be modified to point to the error + message, with the underlying memory having been obtained from the + sqlite3_malloc() function. + + + A standard SQLite return code. + + + + + + SQLite uses the xBestIndex method of a virtual table module to determine + the best way to access the virtual table. + The xBestIndex method has a prototype like this: + + + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + + + The SQLite core communicates with the xBestIndex method by filling + in certain fields of the sqlite3_index_info structure and passing a + pointer to that structure into xBestIndex as the second parameter. + The xBestIndex method fills out other fields of this structure which + forms the reply. The sqlite3_index_info structure looks like this: + + + struct sqlite3_index_info { + /* Inputs */ + const int nConstraint; /* Number of entries in aConstraint */ + const struct sqlite3_index_constraint { + int iColumn; /* Column constrained. -1 for ROWID */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *const aConstraint; /* Table of WHERE clause constraints */ + const int nOrderBy; /* Number of terms in the ORDER BY clause */ + const struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *const aOrderBy; /* The ORDER BY clause */ + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *const aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ + ]]>/* Fields below are only available in SQLite 3.8.2 and later */]]> + sqlite3_int64 estimatedRows; /* Estimated number of rows returned */ + ]]>/* Fields below are only available in SQLite 3.9.0 and later */]]> + int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */ + ]]>/* Fields below are only available in SQLite 3.10.0 and later */]]> + sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */ + }; + + + Note the warnings on the "estimatedRows", "idxFlags", and colUsed fields. + These fields were added with SQLite versions 3.8.2, 3.9.0, and 3.10.0, respectively. + Any extension that reads or writes these fields must first check that the + version of the SQLite library in use is greater than or equal to appropriate + version - perhaps comparing the value returned from sqlite3_libversion_number() + against constants 3008002, 3009000, and/or 3010000. The result of attempting + to access these fields in an sqlite3_index_info structure created by an + older version of SQLite are undefined. + + + In addition, there are some defined constants: + + + #define SQLITE_INDEX_CONSTRAINT_EQ 2 + #define SQLITE_INDEX_CONSTRAINT_GT 4 + #define SQLITE_INDEX_CONSTRAINT_LE 8 + #define SQLITE_INDEX_CONSTRAINT_LT 16 + #define SQLITE_INDEX_CONSTRAINT_GE 32 + #define SQLITE_INDEX_CONSTRAINT_MATCH 64 + #define SQLITE_INDEX_CONSTRAINT_LIKE 65 /* 3.10.0 and later */ + #define SQLITE_INDEX_CONSTRAINT_GLOB 66 /* 3.10.0 and later */ + #define SQLITE_INDEX_CONSTRAINT_REGEXP 67 /* 3.10.0 and later */ + #define SQLITE_INDEX_CONSTRAINT_NE 68 /* 3.21.0 and later */ + #define SQLITE_INDEX_CONSTRAINT_ISNOT 69 /* 3.21.0 and later */ + #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 /* 3.21.0 and later */ + #define SQLITE_INDEX_CONSTRAINT_ISNULL 71 /* 3.21.0 and later */ + #define SQLITE_INDEX_CONSTRAINT_IS 72 /* 3.21.0 and later */ + #define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 /* 3.25.0 and later */ + #define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */ + + + The SQLite core calls the xBestIndex method when it is compiling a query + that involves a virtual table. In other words, SQLite calls this method + when it is running sqlite3_prepare() or the equivalent. + By calling this method, the + SQLite core is saying to the virtual table that it needs to access + some subset of the rows in the virtual table and it wants to know the + most efficient way to do that access. The xBestIndex method replies + with information that the SQLite core can then use to conduct an + efficient search of the virtual table. + + + While compiling a single SQL query, the SQLite core might call + xBestIndex multiple times with different settings in sqlite3_index_info. + The SQLite core will then select the combination that appears to + give the best performance. + + + Before calling this method, the SQLite core initializes an instance + of the sqlite3_index_info structure with information about the + query that it is currently trying to process. This information + derives mainly from the WHERE clause and ORDER BY or GROUP BY clauses + of the query, but also from any ON or USING clauses if the query is a + join. The information that the SQLite core provides to the xBestIndex + method is held in the part of the structure that is marked as "Inputs". + The "Outputs" section is initialized to zero. + + + The information in the sqlite3_index_info structure is ephemeral + and may be overwritten or deallocated as soon as the xBestIndex method + returns. If the xBestIndex method needs to remember any part of the + sqlite3_index_info structure, it should make a copy. Care must be + take to store the copy in a place where it will be deallocated, such + as in the idxStr field with needToFreeIdxStr set to 1. + + + Note that xBestIndex will always be called before xFilter, since + the idxNum and idxStr outputs from xBestIndex are required inputs to + xFilter. However, there is no guarantee that xFilter will be called + following a successful xBestIndex. + + + The xBestIndex method is required for every virtual table implementation. + + + The main thing that the SQLite core is trying to communicate to + the virtual table is the constraints that are available to limit + the number of rows that need to be searched. The aConstraint[] array + contains one entry for each constraint. There will be exactly + nConstraint entries in that array. + + + Each constraint will usually correspond to a term in the WHERE clause + or in a USING or ON clause that is of the form + + + column OP EXPR + + + Where "column" is a column in the virtual table, OP is an operator + like "=" or "<", and EXPR is an arbitrary expression. So, for example, + if the WHERE clause contained a term like this: + + + a = 5 + + + Then one of the constraints would be on the "a" column with + operator "=" and an expression of "5". Constraints need not have a + literal representation of the WHERE clause. The query optimizer might + make transformations to the + WHERE clause in order to extract as many constraints + as it can. So, for example, if the WHERE clause contained something + like this: + + + x BETWEEN 10 AND 100 AND 999>y + + + The query optimizer might translate this into three separate constraints: + + + x >= 10 + x <= 100 + y < 999 + + + For each such constraint, the aConstraint[].iColumn field indicates which + column appears on the left-hand side of the constraint. + The first column of the virtual table is column 0. + The rowid of the virtual table is column -1. + The aConstraint[].op field indicates which operator is used. + The SQLITE_INDEX_CONSTRAINT_* constants map integer constants + into operator values. + Columns occur in the order they were defined by the call to + sqlite3_declare_vtab() in the xCreate or xConnect method. + Hidden columns are counted when determining the column index. + + + If the xFindFunction() method for the virtual table is defined, and + if xFindFunction() sometimes returns SQLITE_INDEX_CONSTRAINT_FUNCTION or + larger, then the constraints might also be of the form: + + + FUNCTION( column, EXPR) + + + In this case the aConstraint[].op value is the same as the value + returned by xFindFunction() for FUNCTION. + + + The aConstraint[] array contains information about all constraints + that apply to the virtual table. But some of the constraints might + not be usable because of the way tables are ordered in a join. + The xBestIndex method must therefore only consider constraints + that have an aConstraint[].usable flag which is true. + + + In addition to WHERE clause constraints, the SQLite core also + tells the xBestIndex method about the ORDER BY clause. + (In an aggregate query, the SQLite core might put in GROUP BY clause + information in place of the ORDER BY clause information, but this fact + should not make any difference to the xBestIndex method.) + If all terms of the ORDER BY clause are columns in the virtual table, + then nOrderBy will be the number of terms in the ORDER BY clause + and the aOrderBy[] array will identify the column for each term + in the order by clause and whether or not that column is ASC or DESC. + + + In SQLite version 3.10.0 (2016-01-06) and later, + the colUsed field is available + to indicate which fields of the virtual table are actually used by the + statement being prepared. If the lowest bit of colUsed is set, that + means that the first column is used. The second lowest bit corresponds + to the second column. And so forth. If the most significant bit of + colUsed is set, that means that one or more columns other than the + first 63 columns are used. If column usage information is needed by the + xFilter method, then the required bits must be encoded into either + the idxNum or idxStr output fields. + + + Given all of the information above, the job of the xBestIndex + method it to figure out the best way to search the virtual table. + + + The xBestIndex method fills the idxNum and idxStr fields with + information that communicates an indexing strategy to the xFilter + method. The information in idxNum and idxStr is arbitrary as far + as the SQLite core is concerned. The SQLite core just copies the + information through to the xFilter method. Any desired meaning can + be assigned to idxNum and idxStr as long as xBestIndex and xFilter + agree on what that meaning is. + + + The idxStr value may be a string obtained from an SQLite + memory allocation function such as sqlite3_mprintf(). + If this is the case, then the needToFreeIdxStr flag must be set to + true so that the SQLite core will know to call sqlite3_free() on + that string when it has finished with it, and thus avoid a memory leak. + The idxStr value may also be a static constant string, in which case + the needToFreeIdxStr boolean should remain false. + + + If the virtual table will output rows in the order specified by + the ORDER BY clause, then the orderByConsumed flag may be set to + true. If the output is not automatically in the correct order + then orderByConsumed must be left in its default false setting. + This will indicate to the SQLite core that it will need to do a + separate sorting pass over the data after it comes out of the virtual table. + + + The estimatedCost field should be set to the estimated number + of disk access operations required to execute this query against + the virtual table. The SQLite core will often call xBestIndex + multiple times with different constraints, obtain multiple cost + estimates, then choose the query plan that gives the lowest estimate. + The SQLite core initializes estimatedCost to a very large value + prior to invoking xBestIndex, so if xBestIndex determines that the + current combination of parameters is undesirable, it can leave the + estimatedCost field unchanged to discourage its use. + + + If the current version of SQLite is 3.8.2 or greater, the estimatedRows + field may be set to an estimate of the number of rows returned by the + proposed query plan. If this value is not explicitly set, the default + estimate of 25 rows is used. + + + If the current version of SQLite is 3.9.0 or greater, the idxFlags field + may be set to SQLITE_INDEX_SCAN_UNIQUE to indicate that the virtual table + will return only zero or one rows given the input constraints. Additional + bits of the idxFlags field might be understood in later versions of SQLite. + + + The aConstraintUsage[] array contains one element for each of + the nConstraint constraints in the inputs section of the + sqlite3_index_info structure. + The aConstraintUsage[] array is used by xBestIndex to tell the + core how it is using the constraints. + + + The xBestIndex method may set aConstraintUsage[].argvIndex + entries to values greater than zero. + Exactly one entry should be set to 1, another to 2, another to 3, + and so forth up to as many or as few as the xBestIndex method wants. + The EXPR of the corresponding constraints will then be passed + in as the argv[] parameters to xFilter. + + + For example, if the aConstraint[3].argvIndex is set to 1, then + when xFilter is called, the argv[0] passed to xFilter will have + the EXPR value of the aConstraint[3] constraint. + + + By default, the SQLite core double checks all constraints on + each row of the virtual table that it receives. If such a check + is redundant, the xBestFilter method can suppress that double-check by + setting aConstraintUsage[].omit. + + + The xBestIndex method should return SQLITE_OK on success. If any + kind of fatal error occurs, an appropriate error code (ex: SQLITE_NOMEM) + should be returned instead. + + + If xBestIndex returns SQLITE_CONSTRAINT, that does not indicate an + error. Rather, SQLITE_CONSTRAINT indicates that the particular combination + of input parameters specified should not be used in the query plan. + The SQLITE_CONSTRAINT return is useful for table-valued functions that + have required parameters. If the aConstraint[].usable field is false + for one of the required parameter, then the xBestIndex method should + return SQLITE_CONSTRAINT. + + + The following example will better illustrate the use of SQLITE_CONSTRAINT + as a return value from xBestIndex: + + + SELECT * FROM realtab, tablevaluedfunc(realtab.x); + + + Assuming that the first hidden column of "tablevaluedfunc" is "param1", + the query above is semantically equivalent to this: + + + SELECT * FROM realtab, tablevaluedfunc + WHERE tablevaluedfunc.param1 = realtab.x; + + + The query planner must decide between many possible implementations + of this query, but two plans in particular are of note: + + ]]> + ]]>Scan all + rows of realtab and for each row, find rows in tablevaluedfunc where + param1 is equal to realtab.x + ]]>]]>Scan all rows of tablevalued func and for each row find rows + in realtab where x is equal to tablevaluedfunc.param1. + ]]>]]> + + The xBestIndex method will be invoked once for each of the potential + plans above. For plan 1, the aConstraint[].usable flag for for the + SQLITE_CONSTRAINT_EQ constraint on the param1 column will be true because + the right-hand side value for the "param1 = ?" constraint will be known, + since it is determined by the outer realtab loop. + But for plan 2, the aConstraint[].usable flag for "param1 = ?" will be false + because the right-hand side value is determined by an inner loop and is thus + an unknown quantity. Because param1 is a required input to the table-valued + functions, the xBestIndex method should return SQLITE_CONSTRAINT when presented + with plan 2, indicating that a required input is missing. This forces the + query planner to select plan 1. + + + + The native pointer to the sqlite3_vtab derived structure. + + + The native pointer to the sqlite3_index_info structure. + + + A standard SQLite return code. + + + + + + int (*xDisconnect)(sqlite3_vtab *pVTab); + + + This method releases a connection to a virtual table. + Only the sqlite3_vtab object is destroyed. + The virtual table is not destroyed and any backing store + associated with the virtual table persists. + + This method undoes the work of xConnect. + + This method is a destructor for a connection to the virtual table. + Contrast this method with xDestroy. The xDestroy is a destructor + for the entire virtual table. + + + The xDisconnect method is required for every virtual table implementation, + though it is acceptable for the xDisconnect and xDestroy methods to be + the same function if that makes sense for the particular virtual table. + + + + The native pointer to the sqlite3_vtab derived structure. + + + A standard SQLite return code. + + + + + + int (*xDestroy)(sqlite3_vtab *pVTab); + + + This method releases a connection to a virtual table, just like + the xDisconnect method, and it also destroys the underlying + table implementation. This method undoes the work of xCreate. + + + The xDisconnect method is called whenever a database connection + that uses a virtual table is closed. The xDestroy method is only + called when a DROP TABLE statement is executed against the virtual table. + + + The xDestroy method is required for every virtual table implementation, + though it is acceptable for the xDisconnect and xDestroy methods to be + the same function if that makes sense for the particular virtual table. + + + + The native pointer to the sqlite3_vtab derived structure. + + + A standard SQLite return code. + + + + + + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + + + The xOpen method creates a new cursor used for accessing (read and/or + writing) a virtual table. A successful invocation of this method + will allocate the memory for the sqlite3_vtab_cursor (or a subclass), + initialize the new object, and make *ppCursor point to the new object. + The successful call then returns SQLITE_OK. + + + For every successful call to this method, the SQLite core will + later invoke the xClose method to destroy + the allocated cursor. + + + The xOpen method need not initialize the pVtab field of the + sqlite3_vtab_cursor structure. The SQLite core will take care + of that chore automatically. + + + A virtual table implementation must be able to support an arbitrary + number of simultaneously open cursors. + + + When initially opened, the cursor is in an undefined state. + The SQLite core will invoke the xFilter method + on the cursor prior to any attempt to position or read from the cursor. + + + The xOpen method is required for every virtual table implementation. + + + + The native pointer to the sqlite3_vtab derived structure. + + + Upon success, this parameter must be modified to point to the newly + created native sqlite3_vtab_cursor derived structure. + + + A standard SQLite return code. + + + + + + int (*xClose)(sqlite3_vtab_cursor*); + + + The xClose method closes a cursor previously opened by + xOpen. + The SQLite core will always call xClose once for each cursor opened + using xOpen. + + + This method must release all resources allocated by the + corresponding xOpen call. The routine will not be called again even if it + returns an error. The SQLite core will not use the + sqlite3_vtab_cursor again after it has been closed. + + + The xClose method is required for every virtual table implementation. + + + + The native pointer to the sqlite3_vtab_cursor derived structure. + + + A standard SQLite return code. + + + + + + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + + + This method begins a search of a virtual table. + The first argument is a cursor opened by xOpen. + The next two arguments define a particular search index previously + chosen by xBestIndex. The specific meanings of idxNum and idxStr + are unimportant as long as xFilter and xBestIndex agree on what + that meaning is. + + + The xBestIndex function may have requested the values of + certain expressions using the aConstraintUsage[].argvIndex values + of the sqlite3_index_info structure. + Those values are passed to xFilter using the argc and argv parameters. + + + If the virtual table contains one or more rows that match the + search criteria, then the cursor must be left point at the first row. + Subsequent calls to xEof must return false (zero). + If there are no rows match, then the cursor must be left in a state + that will cause the xEof to return true (non-zero). + The SQLite engine will use + the xColumn and xRowid methods to access that row content. + The xNext method will be used to advance to the next row. + + + This method must return SQLITE_OK if successful, or an sqlite + error code if an error occurs. + + + The xFilter method is required for every virtual table implementation. + + + + The native pointer to the sqlite3_vtab_cursor derived structure. + + + Number used to help identify the selected index. + + + The native pointer to the UTF-8 encoded string containing the + string used to help identify the selected index. + + + The number of native pointers to sqlite3_value structures specified + in . + + + An array of native pointers to sqlite3_value structures containing + filtering criteria for the selected index. + + + A standard SQLite return code. + + + + + + int (*xNext)(sqlite3_vtab_cursor*); + + + The xNext method advances a virtual table cursor + to the next row of a result set initiated by xFilter. + If the cursor is already pointing at the last row when this + routine is called, then the cursor no longer points to valid + data and a subsequent call to the xEof method must return true (non-zero). + If the cursor is successfully advanced to another row of content, then + subsequent calls to xEof must return false (zero). + + + This method must return SQLITE_OK if successful, or an sqlite + error code if an error occurs. + + + The xNext method is required for every virtual table implementation. + + + + The native pointer to the sqlite3_vtab_cursor derived structure. + + + A standard SQLite return code. + + + + + + int (*xEof)(sqlite3_vtab_cursor*); + + + The xEof method must return false (zero) if the specified cursor + currently points to a valid row of data, or true (non-zero) otherwise. + This method is called by the SQL engine immediately after each + xFilter and xNext invocation. + + + The xEof method is required for every virtual table implementation. + + + + The native pointer to the sqlite3_vtab_cursor derived structure. + + + Non-zero if no more rows are available; zero otherwise. + + + + + + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int N); + + + The SQLite core invokes this method in order to find the value for + the N-th column of the current row. N is zero-based so the first column + is numbered 0. + The xColumn method may return its result back to SQLite using one of the + following interface: + + + ]]> + ]]> sqlite3_result_blob() + ]]>]]> sqlite3_result_double() + ]]>]]> sqlite3_result_int() + ]]>]]> sqlite3_result_int64() + ]]>]]> sqlite3_result_null() + ]]>]]> sqlite3_result_text() + ]]>]]> sqlite3_result_text16() + ]]>]]> sqlite3_result_text16le() + ]]>]]> sqlite3_result_text16be() + ]]>]]> sqlite3_result_zeroblob() + ]]>]]> + + + If the xColumn method implementation calls none of the functions above, + then the value of the column defaults to an SQL NULL. + + + To raise an error, the xColumn method should use one of the result_text() + methods to set the error message text, then return an appropriate + error code. The xColumn method must return SQLITE_OK on success. + + + The xColumn method is required for every virtual table implementation. + + + + The native pointer to the sqlite3_vtab_cursor derived structure. + + + The native pointer to the sqlite3_context structure to be used + for returning the specified column value to the SQLite core + library. + + + The zero-based index corresponding to the column containing the + value to be returned. + + + A standard SQLite return code. + + + + + + int (*xRowid)(sqlite3_vtab_cursor *pCur, sqlite_int64 *pRowid); + + + A successful invocation of this method will cause *pRowid to be + filled with the rowid of row that the + virtual table cursor pCur is currently pointing at. + This method returns SQLITE_OK on success. + It returns an appropriate error code on failure. + + + The xRowid method is required for every virtual table implementation. + + + + The native pointer to the sqlite3_vtab_cursor derived structure. + + + Upon success, this parameter must be modified to contain the unique + integer row identifier for the current row for the specified cursor. + + + A standard SQLite return code. + + + + + + int (*xUpdate)( + sqlite3_vtab *pVTab, + int argc, + sqlite3_value **argv, + sqlite_int64 *pRowid + ); + + + All changes to a virtual table are made using the xUpdate method. + This one method can be used to insert, delete, or update. + + + The argc parameter specifies the number of entries in the argv array. + The value of argc will be 1 for a pure delete operation or N+2 for an insert + or replace or update where N is the number of columns in the table. + In the previous sentence, N includes any hidden columns. + + + Every argv entry will have a non-NULL value in C but may contain the + SQL value NULL. In other words, it is always true that + ]]>argv[i]!=0]]> for ]]>i]]> between 0 and ]]>argc-1]]>. + However, it might be the case that + ]]>sqlite3_value_type(argv[i])==SQLITE_NULL]]>. + + + The argv[0] parameter is the rowid of a row in the virtual table + to be deleted. If argv[0] is an SQL NULL, then no deletion occurs. + + + The argv[1] parameter is the rowid of a new row to be inserted + into the virtual table. If argv[1] is an SQL NULL, then the implementation + must choose a rowid for the newly inserted row. Subsequent argv[] + entries contain values of the columns of the virtual table, in the + order that the columns were declared. The number of columns will + match the table declaration that the xConnect or xCreate method made + using the sqlite3_declare_vtab() call. All hidden columns are included. + + + When doing an insert without a rowid (argc>1, argv[1] is an SQL NULL), + on a virtual table that uses ROWID (but not on a WITHOUT ROWID virtual table), + the implementation must set *pRowid to the rowid of the newly inserted row; + this will become the value returned by the sqlite3_last_insert_rowid() + function. Setting this value in all the other cases is a harmless no-op; + the SQLite engine ignores the *pRowid return value if argc==1 or + argv[1] is not an SQL NULL. + + + Each call to xUpdate will fall into one of cases shown below. + Not that references to ]]>argv[i]]]> mean the SQL value + held within the argv[i] object, not the argv[i] + object itself. + + + ]]> + ]]>]]>argc = 1 ]]> argv[0] ≠ NULL]]> + ]]>]]> + DELETE: The single row with rowid or PRIMARY KEY equal to argv[0] is deleted. + No insert occurs. + ]]>]]>]]>argc > 1 ]]> argv[0] = NULL]]> + ]]>]]> + INSERT: A new row is inserted with column values taken from + argv[2] and following. In a rowid virtual table, if argv[1] is an SQL NULL, + then a new unique rowid is generated automatically. The argv[1] will be NULL + for a WITHOUT ROWID virtual table, in which case the implementation should + take the PRIMARY KEY value from the appropriate column in argv[2] and following. + ]]>]]>]]>argc > 1 ]]> argv[0] ≠ NULL ]]> argv[0] = argv[1]]]> + ]]>]]> + UPDATE: + The row with rowid or PRIMARY KEY argv[0] is updated with new values + in argv[2] and following parameters. + ]]>]]>]]>argc > 1 ]]> argv[0] ≠ NULL ]]> argv[0] ≠ argv[1]]]> + ]]>]]> + UPDATE with rowid or PRIMARY KEY change: + The row with rowid or PRIMARY KEY argv[0] is updated with + the rowid or PRIMARY KEY in argv[1] + and new values in argv[2] and following parameters. This will occur + when an SQL statement updates a rowid, as in the statement: + + UPDATE table SET rowid=rowid+1 WHERE ...; + + ]]>]]> + + + The xUpdate method must return SQLITE_OK if and only if it is + successful. If a failure occurs, the xUpdate must return an appropriate + error code. On a failure, the pVTab->zErrMsg element may optionally + be replaced with error message text stored in memory allocated from SQLite + using functions such as sqlite3_mprintf() or sqlite3_malloc(). + + + If the xUpdate method violates some constraint of the virtual table + (including, but not limited to, attempting to store a value of the wrong + datatype, attempting to store a value that is too + large or too small, or attempting to change a read-only value) then the + xUpdate must fail with an appropriate error code. + + + If the xUpdate method is performing an UPDATE, then + sqlite3_value_nochange(X) can be used to discover which columns + of the virtual table were actually modified by the UPDATE + statement. The sqlite3_value_nochange(X) interface returns + true for columns that do not change. + On every UPDATE, SQLite will first invoke + xColumn separately for each unchanging column in the table to + obtain the value for that column. The xColumn method can + check to see if the column is unchanged at the SQL level + by invoking sqlite3_vtab_nochange(). If xColumn sees that + the column is not being modified, it should return without setting + a result using one of the sqlite3_result_xxxxx() + interfaces. Only in that case sqlite3_value_nochange() will be + true within the xUpdate method. If xColumn does + invoke one or more sqlite3_result_xxxxx() + interfaces, then SQLite understands that as a change in the value + of the column and the sqlite3_value_nochange() call for that + column within xUpdate will return false. + + + There might be one or more sqlite3_vtab_cursor objects open and in use + on the virtual table instance and perhaps even on the row of the virtual + table when the xUpdate method is invoked. The implementation of + xUpdate must be prepared for attempts to delete or modify rows of the table + out from other existing cursors. If the virtual table cannot accommodate + such changes, the xUpdate method must return an error code. + + + The xUpdate method is optional. + If the xUpdate pointer in the sqlite3_module for a virtual table + is a NULL pointer, then the virtual table is read-only. + + + + The native pointer to the sqlite3_vtab derived structure. + + + The number of new or modified column values contained in + . + + + The array of native pointers to sqlite3_value structures containing + the new or modified column values, if any. + + + Upon success, this parameter must be modified to contain the unique + integer row identifier for the row that was inserted, if any. + + + A standard SQLite return code. + + + + + + int (*xBegin)(sqlite3_vtab *pVTab); + + + This method begins a transaction on a virtual table. + This is method is optional. The xBegin pointer of sqlite3_module + may be NULL. + + + This method is always followed by one call to either the + xCommit or xRollback method. Virtual table transactions do + not nest, so the xBegin method will not be invoked more than once + on a single virtual table + without an intervening call to either xCommit or xRollback. + Multiple calls to other methods can and likely will occur in between + the xBegin and the corresponding xCommit or xRollback. + + + + The native pointer to the sqlite3_vtab derived structure. + + + A standard SQLite return code. + + + + + + int (*xSync)(sqlite3_vtab *pVTab); + + + This method signals the start of a two-phase commit on a virtual + table. + This is method is optional. The xSync pointer of sqlite3_module + may be NULL. + + + This method is only invoked after call to the xBegin method and + prior to an xCommit or xRollback. In order to implement two-phase + commit, the xSync method on all virtual tables is invoked prior to + invoking the xCommit method on any virtual table. If any of the + xSync methods fail, the entire transaction is rolled back. + + + + The native pointer to the sqlite3_vtab derived structure. + + + A standard SQLite return code. + + + + + + int (*xCommit)(sqlite3_vtab *pVTab); + + + This method causes a virtual table transaction to commit. + This is method is optional. The xCommit pointer of sqlite3_module + may be NULL. + + + A call to this method always follows a prior call to xBegin and + xSync. + + + + The native pointer to the sqlite3_vtab derived structure. + + + A standard SQLite return code. + + + + + + int (*xRollback)(sqlite3_vtab *pVTab); + + + This method causes a virtual table transaction to rollback. + This is method is optional. The xRollback pointer of sqlite3_module + may be NULL. + + + A call to this method always follows a prior call to xBegin. + + + + The native pointer to the sqlite3_vtab derived structure. + + + A standard SQLite return code. + + + + + + int (*xFindFunction)( + sqlite3_vtab *pVtab, + int nArg, + const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg + ); + + + This method is called during sqlite3_prepare() to give the virtual + table implementation an opportunity to overload functions. + This method may be set to NULL in which case no overloading occurs. + + + When a function uses a column from a virtual table as its first + argument, this method is called to see if the virtual table would + like to overload the function. The first three parameters are inputs: + the virtual table, the number of arguments to the function, and the + name of the function. If no overloading is desired, this method + returns 0. To overload the function, this method writes the new + function implementation into *pxFunc and writes user data into *ppArg + and returns either 1 or a number between + SQLITE_INDEX_CONSTRAINT_FUNCTION and 255. + + + Historically, the return value from xFindFunction() was either zero + or one. Zero means that the function is not overloaded and one means that + it is overload. The ability to return values of + SQLITE_INDEX_CONSTRAINT_FUNCTION or greater was added in + version 3.25.0 (2018-09-15). If xFindFunction returns + SQLITE_INDEX_CONSTRAINT_FUNCTION or greater, than means that the function + takes two arguments and the function + can be used as a boolean in the WHERE clause of a query and that + the virtual table is able to exploit that function to speed up the query + result. When xFindFunction returns SQLITE_INDEX_CONSTRAINT_FUNCTION or + larger, the value returned becomes the sqlite3_index_info.aConstraint.op + value for one of the constraints passed into xBestIndex() and the second + argument becomes the value corresponding to that constraint that is passed + to xFilter(). This enables the + xBestIndex()/xFilter implementations to use the function to speed + its search. + + + The technique of having xFindFunction() return values of + SQLITE_INDEX_CONSTRAINT_FUNCTION was initially used in the implementation + of the Geopoly module. The xFindFunction() method of that module returns + SQLITE_INDEX_CONSTRAINT_FUNCTION for the geopoly_overlap() SQL function + and it returns + SQLITE_INDEX_CONSTRAINT_FUNCTION+1 for the geopoly_within() SQL function. + This permits search optimizations for queries such as: + + + SELECT * FROM geopolytab WHERE geopoly_overlap(_shape, $query_polygon); + + + Note that infix functions (LIKE, GLOB, REGEXP, and MATCH) reverse + the order of their arguments. So "like(A,B)" is equivalent to "B like A". + For the form "B like A" the B term is considered the first argument + to the function. But for "like(A,B)" the A term is considered the + first argument. + + + The function pointer returned by this routine must be valid for + the lifetime of the sqlite3_vtab object given in the first parameter. + + + + The native pointer to the sqlite3_vtab derived structure. + + + The number of arguments to the function being sought. + + + The name of the function being sought. + + + Upon success, this parameter must be modified to contain the + delegate responsible for implementing the specified function. + + + Upon success, this parameter must be modified to contain the + native user-data pointer associated with + . + + + Non-zero if the specified function was found; zero otherwise. + + + + + + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); + + + This method provides notification that the virtual table implementation + that the virtual table will be given a new name. + If this method returns SQLITE_OK then SQLite renames the table. + If this method returns an error code then the renaming is prevented. + + + The xRename method is optional. If omitted, then the virtual + table may not be renamed using the ALTER TABLE RENAME command. + + + The PRAGMA legacy_alter_table setting is enabled prior to invoking this + method, and the value for legacy_alter_table is restored after this + method finishes. This is necessary for the correct operation of virtual + tables that make use of shadow tables where the shadow tables must be + renamed to match the new virtual table name. If the legacy_alter_format is + off, then the xConnect method will be invoked for the virtual table every + time the xRename method tries to change the name of the shadow table. + + + + The native pointer to the sqlite3_vtab derived structure. + + + The native pointer to the UTF-8 encoded string containing the new + name for the virtual table. + + + A standard SQLite return code. + + + + + + int (*xSavepoint)(sqlite3_vtab *pVtab, int); + int (*xRelease)(sqlite3_vtab *pVtab, int); + int (*xRollbackTo)(sqlite3_vtab *pVtab, int); + + + These methods provide the virtual table implementation an opportunity to + implement nested transactions. They are always optional and will only be + called in SQLite version 3.7.7 (2011-06-23) and later. + + + When xSavepoint(X,N) is invoked, that is a signal to the virtual table X + that it should save its current state as savepoint N. + A subsequent call + to xRollbackTo(X,R) means that the state of the virtual table should return + to what it was when xSavepoint(X,R) was last called. + The call + to xRollbackTo(X,R) will invalidate all savepoints with N>R; none of the + invalided savepoints will be rolled back or released without first + being reinitialized by a call to xSavepoint(). + A call to xRelease(X,M) invalidates all savepoints where N>=M. + + + None of the xSavepoint(), xRelease(), or xRollbackTo() methods will ever + be called except in between calls to xBegin() and + either xCommit() or xRollback(). + + + + The native pointer to the sqlite3_vtab derived structure. + + + This is an integer identifier under which the the current state of + the virtual table should be saved. + + + A standard SQLite return code. + + + + + + int (*xSavepoint)(sqlite3_vtab *pVtab, int); + int (*xRelease)(sqlite3_vtab *pVtab, int); + int (*xRollbackTo)(sqlite3_vtab *pVtab, int); + + + These methods provide the virtual table implementation an opportunity to + implement nested transactions. They are always optional and will only be + called in SQLite version 3.7.7 (2011-06-23) and later. + + + When xSavepoint(X,N) is invoked, that is a signal to the virtual table X + that it should save its current state as savepoint N. + A subsequent call + to xRollbackTo(X,R) means that the state of the virtual table should return + to what it was when xSavepoint(X,R) was last called. + The call + to xRollbackTo(X,R) will invalidate all savepoints with N>R; none of the + invalided savepoints will be rolled back or released without first + being reinitialized by a call to xSavepoint(). + A call to xRelease(X,M) invalidates all savepoints where N>=M. + + + None of the xSavepoint(), xRelease(), or xRollbackTo() methods will ever + be called except in between calls to xBegin() and + either xCommit() or xRollback(). + + + + The native pointer to the sqlite3_vtab derived structure. + + + This is an integer used to indicate that any saved states with an + identifier greater than or equal to this should be deleted by the + virtual table. + + + A standard SQLite return code. + + + + + + int (*xSavepoint)(sqlite3_vtab *pVtab, int); + int (*xRelease)(sqlite3_vtab *pVtab, int); + int (*xRollbackTo)(sqlite3_vtab *pVtab, int); + + + These methods provide the virtual table implementation an opportunity to + implement nested transactions. They are always optional and will only be + called in SQLite version 3.7.7 (2011-06-23) and later. + + + When xSavepoint(X,N) is invoked, that is a signal to the virtual table X + that it should save its current state as savepoint N. + A subsequent call + to xRollbackTo(X,R) means that the state of the virtual table should return + to what it was when xSavepoint(X,R) was last called. + The call + to xRollbackTo(X,R) will invalidate all savepoints with N>R; none of the + invalided savepoints will be rolled back or released without first + being reinitialized by a call to xSavepoint(). + A call to xRelease(X,M) invalidates all savepoints where N>=M. + + + None of the xSavepoint(), xRelease(), or xRollbackTo() methods will ever + be called except in between calls to xBegin() and + either xCommit() or xRollback(). + + + + The native pointer to the sqlite3_vtab derived structure. + + + This is an integer identifier used to specify a specific saved + state for the virtual table for it to restore itself back to, which + should also have the effect of deleting all saved states with an + integer identifier greater than this one. + + + A standard SQLite return code. + + + + + This class represents a context from the SQLite core library that can + be passed to the sqlite3_result_*() and associated functions. + + + + + The native context handle. + + + + + Constructs an instance of this class using the specified native + context handle. + + + The native context handle to use. + + + + + Returns the underlying SQLite native handle associated with this + object instance. + + + + + Sets the context result to NULL. + + + + + Sets the context result to the specified + value. + + + The value to use. + + + + + Sets the context result to the specified + value. + + + The value to use. + + + + + Sets the context result to the specified + value. + + + The value to use. + + + + + Sets the context result to the specified + value. + + + The value to use. This value will be + converted to the UTF-8 encoding prior to being used. + + + + + Sets the context result to the specified + value containing an error message. + + + The value containing the error message text. + This value will be converted to the UTF-8 encoding prior to being + used. + + + + + Sets the context result to the specified + value. + + + The value to use. + + + + + Sets the context result to contain the error code SQLITE_TOOBIG. + + + + + Sets the context result to contain the error code SQLITE_NOMEM. + + + + + Sets the context result to the specified array + value. + + + The array value to use. + + + + + Sets the context result to a BLOB of zeros of the specified size. + + + The number of zero bytes to use for the BLOB context result. + + + + + Sets the context result to the specified . + + + The to use. + + + + + This class represents a value from the SQLite core library that can be + passed to the sqlite3_value_*() and associated functions. + + + + + The native value handle. + + + + + Constructs an instance of this class using the specified native + value handle. + + + The native value handle to use. + + + + + Invalidates the native value handle, thereby preventing further + access to it from this object instance. + + + + + Converts a native pointer to a native sqlite3_value structure into + a managed object instance. + + + The native pointer to a native sqlite3_value structure to convert. + + + The managed object instance or null upon + failure. + + + + + Converts a logical array of native pointers to native sqlite3_value + structures into a managed array of + object instances. + + + The number of elements in the logical array of native sqlite3_value + structures. + + + The native pointer to the logical array of native sqlite3_value + structures to convert. + + + The managed array of object instances or + null upon failure. + + + + + Returns the underlying SQLite native handle associated with this + object instance. + + + + + Returns non-zero if the native SQLite value has been successfully + persisted as a managed value within this object instance (i.e. the + property may then be read successfully). + + + + + If the managed value for this object instance is available (i.e. it + has been previously persisted via the ) method, + that value is returned; otherwise, an exception is thrown. The + returned value may be null. + + + + + Gets and returns the type affinity associated with this value. + + + The type affinity associated with this value. + + + + + Gets and returns the number of bytes associated with this value, if + it refers to a UTF-8 encoded string. + + + The number of bytes associated with this value. The returned value + may be zero. + + + + + Gets and returns the associated with this + value. + + + The associated with this value. + + + + + Gets and returns the associated with + this value. + + + The associated with this value. + + + + + Gets and returns the associated with this + value. + + + The associated with this value. + + + + + Gets and returns the associated with this + value. + + + The associated with this value. The value is + converted from the UTF-8 encoding prior to being returned. + + + + + Gets and returns the array associated with this + value. + + + The array associated with this value. + + + + + Gets and returns an instance associated with + this value. + + + The associated with this value. If the type + affinity of the object is unknown or cannot be determined, a null + value will be returned. + + + + + Uses the native value handle to obtain and store the managed value + for this object instance, thus saving it for later use. The type + of the managed value is determined by the type affinity of the + native value. If the type affinity is not recognized by this + method, no work is done and false is returned. + + + Non-zero if the native value was persisted successfully. + + + + + These are the allowed values for the operators that are part of a + constraint term in the WHERE clause of a query that uses a virtual + table. + + + + + This value represents the equality operator. + + + + + This value represents the greater than operator. + + + + + This value represents the less than or equal to operator. + + + + + This value represents the less than operator. + + + + + This value represents the greater than or equal to operator. + + + + + This value represents the MATCH operator. + + + + + This value represents the LIKE operator. + + + + + This value represents the GLOB operator. + + + + + This value represents the REGEXP operator. + + + + + This value represents the inequality operator. + + + + + This value represents the IS NOT operator. + + + + + This value represents the IS NOT NULL operator. + + + + + This value represents the IS NULL operator. + + + + + This value represents the IS operator. + + + + + These are the allowed values for the index flags from the + method. + + + + + No special handling. This is the default. + + + + + This value indicates that the scan of the index will visit at + most one row. + + + + + This class represents the native sqlite3_index_constraint structure + from the SQLite core library. + + + + + Constructs an instance of this class using the specified native + sqlite3_index_constraint structure. + + + The native sqlite3_index_constraint structure to use. + + + + + Constructs an instance of this class using the specified field + values. + + + Column on left-hand side of constraint. + + + Constraint operator (). + + + True if this constraint is usable. + + + Used internally - + should ignore. + + + + + Column on left-hand side of constraint. + + + + + Constraint operator (). + + + + + True if this constraint is usable. + + + + + Used internally - + should ignore. + + + + + This class represents the native sqlite3_index_orderby structure from + the SQLite core library. + + + + + Constructs an instance of this class using the specified native + sqlite3_index_orderby structure. + + + The native sqlite3_index_orderby structure to use. + + + + + Constructs an instance of this class using the specified field + values. + + + Column number. + + + True for DESC. False for ASC. + + + + + Column number. + + + + + True for DESC. False for ASC. + + + + + This class represents the native sqlite3_index_constraint_usage + structure from the SQLite core library. + + + + + Constructs a default instance of this class. + + + + + Constructs an instance of this class using the specified native + sqlite3_index_constraint_usage structure. + + + The native sqlite3_index_constraint_usage structure to use. + + + + + Constructs an instance of this class using the specified field + values. + + + If greater than 0, constraint is part of argv to xFilter. + + + Do not code a test for this constraint. + + + + + If greater than 0, constraint is part of argv to xFilter. + + + + + Do not code a test for this constraint. + + + + + This class represents the various inputs provided by the SQLite core + library to the method. + + + + + Constructs an instance of this class. + + + The number of instances to + pre-allocate space for. + + + The number of instances to + pre-allocate space for. + + + + + An array of object instances, + each containing information supplied by the SQLite core library. + + + + + An array of object instances, + each containing information supplied by the SQLite core library. + + + + + This class represents the various outputs provided to the SQLite core + library by the method. + + + + + Constructs an instance of this class. + + + The number of instances + to pre-allocate space for. + + + + + Determines if the native estimatedRows field can be used, based on + the available version of the SQLite core library. + + + Non-zero if the property is supported + by the SQLite core library. + + + + + Determines if the native flags field can be used, based on the + available version of the SQLite core library. + + + Non-zero if the property is supported by + the SQLite core library. + + + + + Determines if the native flags field can be used, based on the + available version of the SQLite core library. + + + Non-zero if the property is supported by + the SQLite core library. + + + + + An array of object + instances, each containing information to be supplied to the SQLite + core library. + + + + + Number used to help identify the selected index. This value will + later be provided to the + method. + + + + + String used to help identify the selected index. This value will + later be provided to the + method. + + + + + Non-zero if the index string must be freed by the SQLite core + library. + + + + + True if output is already ordered. + + + + + Estimated cost of using this index. Using a null value here + indicates that a default estimated cost value should be used. + + + + + Estimated number of rows returned. Using a null value here + indicates that a default estimated rows value should be used. + This property has no effect if the SQLite core library is not at + least version 3.8.2. + + + + + The flags that should be used with this index. Using a null value + here indicates that a default flags value should be used. This + property has no effect if the SQLite core library is not at least + version 3.9.0. + + + + + + Indicates which columns of the virtual table may be required by the + current scan. Virtual table columns are numbered from zero in the + order in which they appear within the CREATE TABLE statement passed + to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62), + the corresponding bit is set within the bit mask if the column may + be required by SQLite. If the table has at least 64 columns and + any column to the right of the first 63 is required, then bit 63 of + colUsed is also set. In other words, column iCol may be required + if the expression + + + (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) + + + evaluates to non-zero. Using a null value here indicates that a + default flags value should be used. This property has no effect if + the SQLite core library is not at least version 3.10.0. + + + + + + This class represents the various inputs and outputs used with the + method. + + + + + Constructs an instance of this class. + + + The number of (and + ) instances to + pre-allocate space for. + + + The number of instances to + pre-allocate space for. + + + + + Attempts to determine the structure sizes needed to create and + populate a native + + structure. + + + The size of the native + + structure is stored here. + + + The size of the native + + structure is stored here. + + + The size of the native + + structure is stored here. + + + The size of the native + + structure is stored here. + + + + + Attempts to allocate and initialize a native + + structure. + + + The number of instances to + pre-allocate space for. + + + The number of instances to + pre-allocate space for. + + + The newly allocated native + structure + -OR- if it could not be fully allocated. + + + + + Frees all the memory associated with a native + + structure. + + + The native pointer to the native sqlite3_index_info structure to + free. + + + + + Converts a native pointer to a native sqlite3_index_info structure + into a new object instance. + + + The native pointer to the native sqlite3_index_info structure to + convert. + + + Non-zero to include fields from the outputs portion of the native + structure; otherwise, the "output" fields will not be read. + + + Upon success, this parameter will be modified to contain the newly + created object instance. + + + + + Populates the outputs of a pre-allocated native sqlite3_index_info + structure using an existing object + instance. + + + The existing object instance containing + the output data to use. + + + The native pointer to the pre-allocated native sqlite3_index_info + structure. + + + Non-zero to include fields from the inputs portion of the native + structure; otherwise, the "input" fields will not be written. + + + + + The object instance containing + the inputs to the + method. + + + + + The object instance containing + the outputs from the + method. + + + + + This class represents a managed virtual table implementation. It is + not sealed and should be used as the base class for any user-defined + virtual table classes implemented in managed code. + + + + + The index within the array of strings provided to the + and + methods containing the + name of the module implementing this virtual table. + + + + + The index within the array of strings provided to the + and + methods containing the + name of the database containing this virtual table. + + + + + The index within the array of strings provided to the + and + methods containing the + name of the virtual table. + + + + + Constructs an instance of this class. + + + The original array of strings provided to the + and + methods. + + + + + The original array of strings provided to the + and + methods. + + + + + The name of the module implementing this virtual table. + + + + + The name of the database containing this virtual table. + + + + + The name of the virtual table. + + + + + The object instance containing all the + data for the inputs and outputs relating to the most recent index + selection. + + + + + This method should normally be used by the + method in order to + perform index selection based on the constraints provided by the + SQLite core library. + + + The object instance containing all the + data for the inputs and outputs relating to index selection. + + + Non-zero upon success. + + + + + Attempts to record the renaming of the virtual table associated + with this object instance. + + + The new name for the virtual table. + + + Non-zero upon success. + + + + + Returns the underlying SQLite native handle associated with this + object instance. + + + + + Disposes of this object instance. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is being called + from the finalizer. + + + + + Finalizes this object instance. + + + + + This class represents a managed virtual table cursor implementation. + It is not sealed and should be used as the base class for any + user-defined virtual table cursor classes implemented in managed code. + + + + + This value represents an invalid integer row sequence number. + + + + + The field holds the integer row sequence number for the current row + pointed to by this cursor object instance. + + + + + Constructs an instance of this class. + + + The object instance associated + with this object instance. + + + + + Constructs an instance of this class. + + + + + The object instance associated + with this object instance. + + + + + Number used to help identify the selected index. This value will + be set via the method. + + + + + String used to help identify the selected index. This value will + be set via the method. + + + + + The values used to filter the rows returned via this cursor object + instance. This value will be set via the + method. + + + + + Attempts to persist the specified object + instances in order to make them available after the + method returns. + + + The array of object instances to be + persisted. + + + The number of object instances that were + successfully persisted. + + + + + This method should normally be used by the + method in order to + perform filtering of the result rows and/or to record the filtering + criteria provided by the SQLite core library. + + + Number used to help identify the selected index. + + + String used to help identify the selected index. + + + The values corresponding to each column in the selected index. + + + + + Determines the integer row sequence number for the current row. + + + The integer row sequence number for the current row -OR- zero if + it cannot be determined. + + + + + Adjusts the integer row sequence number so that it refers to the + next row. + + + + + Returns the underlying SQLite native handle associated with this + object instance. + + + + + Disposes of this object instance. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is being called + from the finalizer. + + + + + Finalizes this object instance. + + + + + This interface represents a native handle provided by the SQLite core + library. + + + + + The native handle value. + + + + + This interface represents a virtual table implementation written in + managed code. + + + + + Returns non-zero if the schema for the virtual table has been + declared. + + + + + Returns the name of the module as it was registered with the SQLite + core library. + + + + + This method is called in response to the + method. + + + The object instance associated with + the virtual table. + + + The native user-data pointer associated with this module, as it was + provided to the SQLite core library when the native module instance + was created. + + + The module name, database name, virtual table name, and all other + arguments passed to the CREATE VIRTUAL TABLE statement. + + + Upon success, this parameter must be modified to contain the + object instance associated with + the virtual table. + + + Upon failure, this parameter must be modified to contain an error + message. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated with + the virtual table. + + + The native user-data pointer associated with this module, as it was + provided to the SQLite core library when the native module instance + was created. + + + The module name, database name, virtual table name, and all other + arguments passed to the CREATE VIRTUAL TABLE statement. + + + Upon success, this parameter must be modified to contain the + object instance associated with + the virtual table. + + + Upon failure, this parameter must be modified to contain an error + message. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + The object instance containing all the + data for the inputs and outputs relating to index selection. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + Upon success, this parameter must be modified to contain the + object instance associated + with the newly opened virtual table cursor. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + Number used to help identify the selected index. + + + String used to help identify the selected index. + + + The values corresponding to each column in the selected index. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + Non-zero if no more rows are available; zero otherwise. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + The object instance to be used for + returning the specified column value to the SQLite core library. + + + The zero-based index corresponding to the column containing the + value to be returned. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + Upon success, this parameter must be modified to contain the unique + integer row identifier for the current row for the specified cursor. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + The array of object instances containing + the new or modified column values, if any. + + + Upon success, this parameter must be modified to contain the unique + integer row identifier for the row that was inserted, if any. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + The number of arguments to the function being sought. + + + The name of the function being sought. + + + Upon success, this parameter must be modified to contain the + object instance responsible for + implementing the specified function. + + + Upon success, this parameter must be modified to contain the + native user-data pointer associated with + . + + + Non-zero if the specified function was found; zero otherwise. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + The new name for the virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + This is an integer identifier under which the the current state of + the virtual table should be saved. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + This is an integer used to indicate that any saved states with an + identifier greater than or equal to this should be deleted by the + virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + This is an integer identifier used to specify a specific saved + state for the virtual table for it to restore itself back to, which + should also have the effect of deleting all saved states with an + integer identifier greater than this one. + + + A standard SQLite return code. + + + + + This class contains static methods that are used to allocate, + manipulate, and free native memory provided by the SQLite core library. + + + + + Determines if the native sqlite3_msize() API can be used, based on + the available version of the SQLite core library. + + + Non-zero if the native sqlite3_msize() API is supported by the + SQLite core library. + + + + + Allocates at least the specified number of bytes of native memory + via the SQLite core library sqlite3_malloc() function and returns + the resulting native pointer. If the TRACK_MEMORY_BYTES option + was enabled at compile-time, adjusts the number of bytes currently + allocated by this class. + + + The number of bytes to allocate. + + + The native pointer that points to a block of memory of at least the + specified size -OR- if the memory could + not be allocated. + + + + + Allocates at least the specified number of bytes of native memory + via the SQLite core library sqlite3_malloc64() function and returns + the resulting native pointer. If the TRACK_MEMORY_BYTES option + was enabled at compile-time, adjusts the number of bytes currently + allocated by this class. + + + The number of bytes to allocate. + + + The native pointer that points to a block of memory of at least the + specified size -OR- if the memory could + not be allocated. + + + + + Allocates at least the specified number of bytes of native memory + via the SQLite core library sqlite3_malloc() function and returns + the resulting native pointer without adjusting the number of + allocated bytes currently tracked by this class. This is useful + when dealing with blocks of memory that will be freed directly by + the SQLite core library. + + + The number of bytes to allocate. + + + The native pointer that points to a block of memory of at least the + specified size -OR- if the memory could + not be allocated. + + + + + Allocates at least the specified number of bytes of native memory + via the SQLite core library sqlite3_malloc64() function and returns + the resulting native pointer without adjusting the number of + allocated bytes currently tracked by this class. This is useful + when dealing with blocks of memory that will be freed directly by + the SQLite core library. + + + The number of bytes to allocate. + + + The native pointer that points to a block of memory of at least the + specified size -OR- if the memory could + not be allocated. + + + + + Gets and returns the actual size of the specified memory block + that was previously obtained from the , + , , or + methods or directly from the + SQLite core library. + + + The native pointer to the memory block previously obtained from + the , , + , or + methods or directly from the + SQLite core library. + + + The actual size, in bytes, of the memory block specified via the + native pointer. + + + + + Gets and returns the actual size of the specified memory block + that was previously obtained from the , + , , or + methods or directly from the + SQLite core library. + + + The native pointer to the memory block previously obtained from + the , , + , or + methods or directly from the + SQLite core library. + + + The actual size, in bytes, of the memory block specified via the + native pointer. + + + + + Frees a memory block previously obtained from the + or methods. If + the TRACK_MEMORY_BYTES option was enabled at compile-time, adjusts + the number of bytes currently allocated by this class. + + + The native pointer to the memory block previously obtained from the + or methods. + + + + + Frees a memory block previously obtained from the SQLite core + library without adjusting the number of allocated bytes currently + tracked by this class. This is useful when dealing with blocks of + memory that were not allocated using this class. + + + The native pointer to the memory block previously obtained from the + SQLite core library. + + + + + This class contains static methods that are used to deal with native + UTF-8 string pointers to be used with the SQLite core library. + + + + + This is the maximum possible length for the native UTF-8 encoded + strings used with the SQLite core library. + + + + + This is the object instance used to handle + conversions from/to UTF-8. + + + + + Converts the specified managed string into the UTF-8 encoding and + returns the array of bytes containing its representation in that + encoding. + + + The managed string to convert. + + + The array of bytes containing the representation of the managed + string in the UTF-8 encoding or null upon failure. + + + + + Converts the specified array of bytes representing a string in the + UTF-8 encoding and returns a managed string. + + + The array of bytes to convert. + + + The managed string or null upon failure. + + + + + Probes a native pointer to a string in the UTF-8 encoding for its + terminating NUL character, within the specified length limit. + + + The native NUL-terminated string pointer. + + + The maximum length of the native string, in bytes. + + + The length of the native string, in bytes -OR- zero if the length + could not be determined. + + + + + Converts the specified native NUL-terminated UTF-8 string pointer + into a managed string. + + + The native NUL-terminated UTF-8 string pointer. + + + The managed string or null upon failure. + + + + + Converts the specified native UTF-8 string pointer of the specified + length into a managed string. + + + The native UTF-8 string pointer. + + + The length of the native string, in bytes. + + + The managed string or null upon failure. + + + + + Converts the specified managed string into a native NUL-terminated + UTF-8 string pointer using memory obtained from the SQLite core + library. + + + The managed string to convert. + + + The native NUL-terminated UTF-8 string pointer or + upon failure. + + + + + Converts the specified managed string into a native NUL-terminated + UTF-8 string pointer using memory obtained from the SQLite core + library. + + + The managed string to convert. + + + Non-zero to obtain memory from the SQLite core library without + adjusting the number of allocated bytes currently being tracked + by the class. + + + The native NUL-terminated UTF-8 string pointer or + upon failure. + + + + + Converts the specified managed string into a native NUL-terminated + UTF-8 string pointer using memory obtained from the SQLite core + library. + + + The managed string to convert. + + + The length of the native string, in bytes. + + + The native NUL-terminated UTF-8 string pointer or + upon failure. + + + + + Converts the specified managed string into a native NUL-terminated + UTF-8 string pointer using memory obtained from the SQLite core + library. + + + The managed string to convert. + + + Non-zero to obtain memory from the SQLite core library without + adjusting the number of allocated bytes currently being tracked + by the class. + + + The length of the native string, in bytes. + + + The native NUL-terminated UTF-8 string pointer or + upon failure. + + + + + Converts a logical array of native NUL-terminated UTF-8 string + pointers into an array of managed strings. + + + The number of elements in the logical array of native + NUL-terminated UTF-8 string pointers. + + + The native pointer to the logical array of native NUL-terminated + UTF-8 string pointers to convert. + + + The array of managed strings or null upon failure. + + + + + Converts an array of managed strings into an array of native + NUL-terminated UTF-8 string pointers. + + + The array of managed strings to convert. + + + Non-zero to obtain memory from the SQLite core library without + adjusting the number of allocated bytes currently being tracked + by the class. + + + The array of native NUL-terminated UTF-8 string pointers or null + upon failure. + + + + + This class contains static methods that are used to deal with native + pointers to memory blocks that logically contain arrays of bytes to be + used with the SQLite core library. + + + + + Converts a native pointer to a logical array of bytes of the + specified length into a managed byte array. + + + The native pointer to the logical array of bytes to convert. + + + The length, in bytes, of the logical array of bytes to convert. + + + The managed byte array or null upon failure. + + + + + Converts a managed byte array into a native pointer to a logical + array of bytes. + + + The managed byte array to convert. + + + The native pointer to a logical byte array or null upon failure. + + + + + Converts a managed byte array into a native pointer to a logical + array of bytes. + + + The managed byte array to convert. + + + The length, in bytes, of the converted logical array of bytes. + + + The native pointer to a logical byte array or null upon failure. + + + + + This class contains static methods that are used to perform several + low-level data marshalling tasks between native and managed code. + + + + + Returns a new object instance based on the + specified object instance and an integer + offset. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location that the new + object instance should point to. + + + The new object instance. + + + + + Rounds up an integer size to the next multiple of the alignment. + + + The size, in bytes, to be rounded up. + + + The required alignment for the return value. + + + The size, in bytes, rounded up to the next multiple of the + alignment. This value may end up being the same as the original + size. + + + + + Determines the offset, in bytes, of the next structure member. + + + The offset, in bytes, of the current structure member. + + + The size, in bytes, of the current structure member. + + + The alignment, in bytes, of the next structure member. + + + The offset, in bytes, of the next structure member. + + + + + Reads a value from the specified memory + location. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location where the + value to be read is located. + + + The value at the specified memory location. + + + + + Reads a value from the specified memory + location. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location where the + value to be read is located. + + + The value at the specified memory location. + + + + + Reads a value from the specified memory + location. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location where the + to be read is located. + + + The value at the specified memory location. + + + + + Reads an value from the specified memory + location. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location where the + value to be read is located. + + + The value at the specified memory location. + + + + + Writes an value to the specified memory + location. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location where the + value to be written is located. + + + The value to write. + + + + + Writes an value to the specified memory + location. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location where the + value to be written is located. + + + The value to write. + + + + + Writes a value to the specified memory + location. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location where the + value to be written is located. + + + The value to write. + + + + + Writes a value to the specified memory + location. + + + The object instance representing the base + memory location. + + + The integer offset from the base memory location where the + value to be written is located. + + + The value to write. + + + + + Generates a hash code value for the object. + + + The object instance used to calculate the hash code. + + + Non-zero if different object instances with the same value should + generate different hash codes, where applicable. This parameter + has no effect on the .NET Compact Framework. + + + The hash code value -OR- zero if the object is null. + + + + + This class represents a managed virtual table module implementation. + It is not sealed and must be used as the base class for any + user-defined virtual table module classes implemented in managed code. + + + + + This class implements the + interface by forwarding those method calls to the + object instance it contains. If the + contained object instance is null, all + the methods simply generate an + error. + + + + + This is the value that is always used for the "logErrors" + parameter to the various static error handling methods provided + by the class. + + + + + This is the value that is always used for the "logExceptions" + parameter to the various static error handling methods provided + by the class. + + + + + This is the error message text used when the contained + object instance is not available + for any reason. + + + + + The object instance used to provide + an implementation of the + interface. + + + + + Constructs an instance of this class. + + + The object instance used to provide + an implementation of the + interface. + + + + + Sets the table error message to one that indicates the native + module implementation is not available. + + + The native pointer to the sqlite3_vtab derived structure. + + + The value of . + + + + + Sets the table error message to one that indicates the native + module implementation is not available. + + + The native pointer to the sqlite3_vtab_cursor derived + structure. + + + The value of . + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + Disposes of this object instance. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is being + called from the finalizer. + + + + + Finalizes this object instance. + + + + + The default version of the native sqlite3_module structure in use. + + + + + This field is used to store the native sqlite3_module structure + associated with this object instance. + + + + + This field is used to store the destructor delegate to be passed to + the SQLite core library via the sqlite3_create_disposable_module() + function. + + + + + This field is used to store a pointer to the native sqlite3_module + structure returned by the sqlite3_create_disposable_module + function. + + + + + This field is used to store the virtual table instances associated + with this module. The native pointer to the sqlite3_vtab derived + structure is used to key into this collection. + + + + + This field is used to store the virtual table cursor instances + associated with this module. The native pointer to the + sqlite3_vtab_cursor derived structure is used to key into this + collection. + + + + + This field is used to store the virtual table function instances + associated with this module. The case-insensitive function name + and the number of arguments (with -1 meaning "any") are used to + construct the string that is used to key into this collection. + + + + + Constructs an instance of this class. + + + The name of the module. This parameter cannot be null. + + + + + Calls the native SQLite core library in order to create a new + disposable module containing the implementation of a virtual table. + + + The native database connection pointer to use. + + + Non-zero upon success. + + + + + This method is called by the SQLite core library when the native + module associated with this object instance is being destroyed due + to its parent connection being closed. It may also be called by + the "vtshim" module if/when the sqlite3_dispose_module() function + is called. + + + The native user-data pointer associated with this module, as it was + provided to the SQLite core library when the native module instance + was created. + + + + + Creates and returns the native sqlite_module structure using the + configured (or default) + interface implementation. + + + The native sqlite_module structure using the configured (or + default) interface + implementation. + + + + + Creates and returns the native sqlite_module structure using the + specified interface + implementation. + + + The interface implementation to + use. + + + The native sqlite_module structure using the specified + interface implementation. + + + + + Creates a copy of the specified + object instance, + using default implementations for the contained delegates when + necessary. + + + The object + instance to copy. + + + The new object + instance. + + + + + Calls one of the virtual table initialization methods. + + + Non-zero to call the + method; otherwise, the + method will be called. + + + The native database connection handle. + + + The original native pointer value that was provided to the + sqlite3_create_module(), sqlite3_create_module_v2() or + sqlite3_create_disposable_module() functions. + + + The number of arguments from the CREATE VIRTUAL TABLE statement. + + + The array of string arguments from the CREATE VIRTUAL TABLE + statement. + + + Upon success, this parameter must be modified to point to the newly + created native sqlite3_vtab derived structure. + + + Upon failure, this parameter must be modified to point to the error + message, with the underlying memory having been obtained from the + sqlite3_malloc() function. + + + A standard SQLite return code. + + + + + Calls one of the virtual table finalization methods. + + + Non-zero to call the + method; otherwise, the + method will be + called. + + + The native pointer to the sqlite3_vtab derived structure. + + + A standard SQLite return code. + + + + + Arranges for the specified error message to be placed into the + zErrMsg field of a sqlite3_vtab derived structure, freeing the + existing error message, if any. + + + The object instance to be used. + + + The native pointer to the sqlite3_vtab derived structure. + + + Non-zero if this error message should also be logged using the + class. + + + Non-zero if caught exceptions should be logged using the + class. + + + The error message. + + + Non-zero upon success. + + + + + Arranges for the specified error message to be placed into the + zErrMsg field of a sqlite3_vtab derived structure, freeing the + existing error message, if any. + + + The object instance to be used. + + + The object instance used to + lookup the native pointer to the sqlite3_vtab derived structure. + + + Non-zero if this error message should also be logged using the + class. + + + Non-zero if caught exceptions should be logged using the + class. + + + The error message. + + + Non-zero upon success. + + + + + Arranges for the specified error message to be placed into the + zErrMsg field of a sqlite3_vtab derived structure, freeing the + existing error message, if any. + + + The object instance to be used. + + + The native pointer to the sqlite3_vtab_cursor derived structure + used to get the native pointer to the sqlite3_vtab derived + structure. + + + Non-zero if this error message should also be logged using the + class. + + + Non-zero if caught exceptions should be logged using the + class. + + + The error message. + + + Non-zero upon success. + + + + + Arranges for the specified error message to be placed into the + zErrMsg field of a sqlite3_vtab derived structure, freeing the + existing error message, if any. + + + The object instance to be used. + + + The object instance used to + lookup the native pointer to the sqlite3_vtab derived structure. + + + Non-zero if this error message should also be logged using the + class. + + + Non-zero if caught exceptions should be logged using the + class. + + + The error message. + + + Non-zero upon success. + + + + + Gets and returns the interface + implementation to be used when creating the native sqlite3_module + structure. Derived classes may override this method to supply an + alternate implementation for the + interface. + + + The interface implementation to + be used when populating the native sqlite3_module structure. If + the returned value is null, the private methods provided by the + class and relating to the + interface will be used to + create the necessary delegates. + + + + + Creates and returns the + interface implementation corresponding to the current + object instance. + + + The interface implementation + corresponding to the current object + instance. + + + + + Allocates a native sqlite3_vtab derived structure and returns a + native pointer to it. + + + A native pointer to a native sqlite3_vtab derived structure. + + + + + Zeros out the fields of a native sqlite3_vtab derived structure. + + + The native pointer to the native sqlite3_vtab derived structure to + zero. + + + + + Frees a native sqlite3_vtab structure using the provided native + pointer to it. + + + A native pointer to a native sqlite3_vtab derived structure. + + + + + Allocates a native sqlite3_vtab_cursor derived structure and + returns a native pointer to it. + + + A native pointer to a native sqlite3_vtab_cursor derived structure. + + + + + Frees a native sqlite3_vtab_cursor structure using the provided + native pointer to it. + + + A native pointer to a native sqlite3_vtab_cursor derived structure. + + + + + Reads and returns the native pointer to the sqlite3_vtab derived + structure based on the native pointer to the sqlite3_vtab_cursor + derived structure. + + + The object instance to be used. + + + The native pointer to the sqlite3_vtab_cursor derived structure + from which to read the native pointer to the sqlite3_vtab derived + structure. + + + The native pointer to the sqlite3_vtab derived structure -OR- + if it cannot be determined. + + + + + Reads and returns the native pointer to the sqlite3_vtab derived + structure based on the native pointer to the sqlite3_vtab_cursor + derived structure. + + + The native pointer to the sqlite3_vtab_cursor derived structure + from which to read the native pointer to the sqlite3_vtab derived + structure. + + + The native pointer to the sqlite3_vtab derived structure -OR- + if it cannot be determined. + + + + + Looks up and returns the object + instance based on the native pointer to the sqlite3_vtab derived + structure. + + + The native pointer to the sqlite3_vtab derived structure. + + + The object instance or null if + the corresponding one cannot be found. + + + + + Allocates and returns a native pointer to a sqlite3_vtab derived + structure and creates an association between it and the specified + object instance. + + + The object instance to be used + when creating the association. + + + The native pointer to a sqlite3_vtab derived structure or + if the method fails for any reason. + + + + + Looks up and returns the + object instance based on the native pointer to the + sqlite3_vtab_cursor derived structure. + + + The native pointer to the sqlite3_vtab derived structure. + + + The native pointer to the sqlite3_vtab_cursor derived structure. + + + The object instance or null + if the corresponding one cannot be found. + + + + + Allocates and returns a native pointer to a sqlite3_vtab_cursor + derived structure and creates an association between it and the + specified object instance. + + + The object instance to be + used when creating the association. + + + The native pointer to a sqlite3_vtab_cursor derived structure or + if the method fails for any reason. + + + + + Deterimines the key that should be used to identify and store the + object instance for the virtual table + (i.e. to be returned via the + method). + + + The number of arguments to the virtual table function. + + + The name of the virtual table function. + + + The object instance associated with + this virtual table function. + + + The string that should be used to identify and store the virtual + table function instance. This method cannot return null. If null + is returned from this method, the behavior is undefined. + + + + + Attempts to declare the schema for the virtual table using the + specified database connection. + + + The object instance to use when + declaring the schema of the virtual table. This parameter may not + be null. + + + The string containing the CREATE TABLE statement that completely + describes the schema for the virtual table. This parameter may not + be null. + + + Upon failure, this parameter must be modified to contain an error + message. + + + A standard SQLite return code. + + + + + Calls the native SQLite core library in order to declare a virtual + table function in response to a call into the + + or virtual table + methods. + + + The object instance to use when + declaring the schema of the virtual table. + + + The number of arguments to the function being declared. + + + The name of the function being declared. + + + Upon success, the contents of this parameter are undefined. Upon + failure, it should contain an appropriate error message. + + + A standard SQLite return code. + + + + + Returns or sets a boolean value indicating whether virtual table + errors should be logged using the class. + + + + + Returns or sets a boolean value indicating whether exceptions + caught in the + method, + the method, + the method, + the method, + and the method should be logged using the + class. + + + + + Arranges for the specified error message to be placed into the + zErrMsg field of a sqlite3_vtab derived structure, freeing the + existing error message, if any. + + + The native pointer to the sqlite3_vtab derived structure. + + + The error message. + + + Non-zero upon success. + + + + + Arranges for the specified error message to be placed into the + zErrMsg field of a sqlite3_vtab derived structure, freeing the + existing error message, if any. + + + The object instance used to + lookup the native pointer to the sqlite3_vtab derived structure. + + + The error message. + + + Non-zero upon success. + + + + + Arranges for the specified error message to be placed into the + zErrMsg field of a sqlite3_vtab derived structure, freeing the + existing error message, if any. + + + The object instance used to + lookup the native pointer to the sqlite3_vtab derived structure. + + + The error message. + + + Non-zero upon success. + + + + + Modifies the specified object instance + to contain the specified estimated cost. + + + The object instance to modify. + + + The estimated cost value to use. Using a null value means that the + default value provided by the SQLite core library should be used. + + + Non-zero upon success. + + + + + Modifies the specified object instance + to contain the default estimated cost. + + + The object instance to modify. + + + Non-zero upon success. + + + + + Modifies the specified object instance + to contain the specified estimated rows. + + + The object instance to modify. + + + The estimated rows value to use. Using a null value means that the + default value provided by the SQLite core library should be used. + + + Non-zero upon success. + + + + + Modifies the specified object instance + to contain the default estimated rows. + + + The object instance to modify. + + + Non-zero upon success. + + + + + Modifies the specified object instance + to contain the specified flags. + + + The object instance to modify. + + + The index flags value to use. Using a null value means that the + default value provided by the SQLite core library should be used. + + + Non-zero upon success. + + + + + Modifies the specified object instance + to contain the default index flags. + + + The object instance to modify. + + + Non-zero upon success. + + + + + Returns or sets a boolean value indicating whether virtual table + errors should be logged using the class. + + + + + Returns or sets a boolean value indicating whether exceptions + caught in the + method, + method, and the + method should be logged using the + class. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + Returns non-zero if the schema for the virtual table has been + declared. + + + + + Returns the name of the module as it was registered with the SQLite + core library. + + + + + This method is called in response to the + method. + + + The object instance associated with + the virtual table. + + + The native user-data pointer associated with this module, as it was + provided to the SQLite core library when the native module instance + was created. + + + The module name, database name, virtual table name, and all other + arguments passed to the CREATE VIRTUAL TABLE statement. + + + Upon success, this parameter must be modified to contain the + object instance associated with + the virtual table. + + + Upon failure, this parameter must be modified to contain an error + message. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated with + the virtual table. + + + The native user-data pointer associated with this module, as it was + provided to the SQLite core library when the native module instance + was created. + + + The module name, database name, virtual table name, and all other + arguments passed to the CREATE VIRTUAL TABLE statement. + + + Upon success, this parameter must be modified to contain the + object instance associated with + the virtual table. + + + Upon failure, this parameter must be modified to contain an error + message. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + The object instance containing all the + data for the inputs and outputs relating to index selection. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + Upon success, this parameter must be modified to contain the + object instance associated + with the newly opened virtual table cursor. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + Number used to help identify the selected index. + + + String used to help identify the selected index. + + + The values corresponding to each column in the selected index. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + Non-zero if no more rows are available; zero otherwise. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + The object instance to be used for + returning the specified column value to the SQLite core library. + + + The zero-based index corresponding to the column containing the + value to be returned. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + Upon success, this parameter must be modified to contain the unique + integer row identifier for the current row for the specified cursor. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + The array of object instances containing + the new or modified column values, if any. + + + Upon success, this parameter must be modified to contain the unique + integer row identifier for the row that was inserted, if any. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + The number of arguments to the function being sought. + + + The name of the function being sought. + + + Upon success, this parameter must be modified to contain the + object instance responsible for + implementing the specified function. + + + Upon success, this parameter must be modified to contain the + native user-data pointer associated with + . + + + Non-zero if the specified function was found; zero otherwise. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + The new name for the virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + This is an integer identifier under which the the current state of + the virtual table should be saved. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + This is an integer used to indicate that any saved states with an + identifier greater than or equal to this should be deleted by the + virtual table. + + + A standard SQLite return code. + + + + + This method is called in response to the + method. + + + The object instance associated + with this virtual table. + + + This is an integer identifier used to specify a specific saved + state for the virtual table for it to restore itself back to, which + should also have the effect of deleting all saved states with an + integer identifier greater than this one. + + + A standard SQLite return code. + + + + + Disposes of this object instance. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is being + called from the finalizer. + + + + + Finalizes this object instance. + + + + + This class contains some virtual methods that may be useful for other + virtual table classes. It specifically does NOT implement any of the + interface methods. + + + + + The CREATE TABLE statement used to declare the schema for the + virtual table. + + + + + Non-zero if different object instances with the same value should + generate different row identifiers, where applicable. This has no + effect on the .NET Compact Framework. + + + + + Constructs an instance of this class. + + + The name of the module. This parameter cannot be null. + + + + + Constructs an instance of this class. + + + The name of the module. This parameter cannot be null. + + + Non-zero if different object instances with the same value should + generate different row identifiers, where applicable. This + parameter has no effect on the .NET Compact Framework. + + + + + Determines the SQL statement used to declare the virtual table. + This method should be overridden in derived classes if they require + a custom virtual table schema. + + + The SQL statement used to declare the virtual table -OR- null if it + cannot be determined. + + + + + Sets the table error message to one that indicates the virtual + table cursor is of the wrong type. + + + The object instance. + + + The that the virtual table cursor should be. + + + The value of . + + + + + Determines the string to return as the column value for the object + instance value. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + The object instance to return a string representation for. + + + The string representation of the specified object instance or null + upon failure. + + + + + Constructs an unique row identifier from two + values. The first value + must contain the row sequence number for the current row and the + second value must contain the hash code of the key column value + for the current row. + + + The integer row sequence number for the current row. + + + The hash code of the key column value for the current row. + + + The unique row identifier or zero upon failure. + + + + + Determines the unique row identifier for the current row. + + + The object instance + associated with the previously opened virtual table cursor to be + used. + + + The object instance to return a unique row identifier for. + + + The unique row identifier or zero upon failure. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is + being called from the finalizer. + + + + + This class represents a virtual table cursor to be used with the + class. It is not sealed and may + be used as the base class for any user-defined virtual table cursor + class that wraps an object instance. + + + + + The instance provided when this cursor + was created. + + + + + This value will be non-zero if false has been returned from the + method. + + + + + Constructs an instance of this class. + + + The object instance associated + with this object instance. + + + The instance to expose as a virtual + table cursor. + + + + + Advances to the next row of the virtual table cursor using the + method of the + object instance. + + + Non-zero if the current row is valid; zero otherwise. If zero is + returned, no further rows are available. + + + + + Returns the value for the current row of the virtual table cursor + using the property of the + object instance. + + + + + Resets the virtual table cursor position, also invalidating the + current row, using the method of + the object instance. + + + + + Returns non-zero if the end of the virtual table cursor has been + seen (i.e. no more rows are available, including the current one). + + + + + Returns non-zero if the virtual table cursor is open. + + + + + Closes the virtual table cursor. This method must not throw any + exceptions. + + + + + Throws an if the virtual + table cursor has been closed. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is + being called from the finalizer. + + + + + This class implements a virtual table module that exposes an + object instance as a read-only virtual + table. It is not sealed and may be used as the base class for any + user-defined virtual table class that wraps an + object instance. The following short + example shows it being used to treat an array of strings as a table + data source: + + public static class Sample + { + public static void Main() + { + using (SQLiteConnection connection = new SQLiteConnection( + "Data Source=:memory:;")) + { + connection.Open(); + + connection.CreateModule(new SQLiteModuleEnumerable( + "sampleModule", new string[] { "one", "two", "three" })); + + using (SQLiteCommand command = connection.CreateCommand()) + { + command.CommandText = + "CREATE VIRTUAL TABLE t1 USING sampleModule;"; + + command.ExecuteNonQuery(); + } + + using (SQLiteCommand command = connection.CreateCommand()) + { + command.CommandText = "SELECT * FROM t1;"; + + using (SQLiteDataReader dataReader = command.ExecuteReader()) + { + while (dataReader.Read()) + Console.WriteLine(dataReader[0].ToString()); + } + } + + connection.Close(); + } + } + } + + + + + + The instance containing the backing data + for the virtual table. + + + + + Non-zero if different object instances with the same value should + generate different row identifiers, where applicable. This has no + effect on the .NET Compact Framework. + + + + + Constructs an instance of this class. + + + The name of the module. This parameter cannot be null. + + + The instance to expose as a virtual + table. This parameter cannot be null. + + + + + Constructs an instance of this class. + + + The name of the module. This parameter cannot be null. + + + The instance to expose as a virtual + table. This parameter cannot be null. + + + Non-zero if different object instances with the same value should + generate different row identifiers, where applicable. This + parameter has no effect on the .NET Compact Framework. + + + + + Sets the table error message to one that indicates the virtual + table cursor has no current row. + + + The object instance. + + + The value of . + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is + being called from the finalizer. + + + + + This class represents a virtual table cursor to be used with the + class. It is not sealed and may + be used as the base class for any user-defined virtual table cursor + class that wraps an object instance. + + + + + The instance provided when this + cursor was created. + + + + + Constructs an instance of this class. + + + The object instance associated + with this object instance. + + + The instance to expose as a virtual + table cursor. + + + + + Returns the value for the current row of the virtual table cursor + using the property of the + object instance. + + + + + Closes the virtual table cursor. This method must not throw any + exceptions. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is + being called from the finalizer. + + + + + This class implements a virtual table module that exposes an + object instance as a read-only virtual + table. It is not sealed and may be used as the base class for any + user-defined virtual table class that wraps an + object instance. + + + + + The instance containing the backing + data for the virtual table. + + + + + Constructs an instance of this class. + + + The name of the module. This parameter cannot be null. + + + The instance to expose as a virtual + table. This parameter cannot be null. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is + being called from the finalizer. + + + + + This class implements a virtual table module that does nothing by + providing "empty" implementations for all of the + interface methods. The result + codes returned by these "empty" method implementations may be + controlled on a per-method basis by using and/or overriding the + , + , + , + , and + methods from within derived classes. + + + + + This field is used to store the + values to return, on a per-method basis, for all methods that are + part of the interface. + + + + + Constructs an instance of this class. + + + The name of the module. This parameter cannot be null. + + + + + Determines the default value to be + returned by methods of the + interface that lack an overridden implementation in all classes + derived from the class. + + + The value that should be returned + by all interface methods unless + a more specific result code has been set for that interface method. + + + + + Converts a value into a boolean + return value for use with the + method. + + + The value to convert. + + + The value. + + + + + Converts a value into a boolean + return value for use with the + method. + + + The value to convert. + + + The value. + + + + + Determines the value that should be + returned by the specified + interface method if it lack an overridden implementation. If no + specific value is available (or set) + for the specified method, the value + returned by the method will be + returned instead. + + + The name of the method. Currently, this method must be part of + the interface. + + + The value that should be returned + by the interface method. + + + + + Sets the value that should be + returned by the specified + interface method if it lack an overridden implementation. + + + The name of the method. Currently, this method must be part of + the interface. + + + The value that should be returned + by the interface method. + + + Non-zero upon success. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + See the method. + + + See the method. + + + See the method. + + + See the method. + + + + + Throws an if this object + instance has been disposed. + + + + + Disposes of this object instance. + + + Non-zero if this method is being called from the + method. Zero if this method is + being called from the finalizer. + + + + + This enumerated type represents a type of conflict seen when apply + changes from a change set or patch set. + + + + + This value is seen when processing a DELETE or UPDATE change if a + row with the required PRIMARY KEY fields is present in the + database, but one or more other (non primary-key) fields modified + by the update do not contain the expected "before" values. + + + + + This value is seen when processing a DELETE or UPDATE change if a + row with the required PRIMARY KEY fields is not present in the + database. There is no conflicting row in this case. + + The results of invoking the + + method are undefined. + + + + + This value is seen when processing an INSERT change if the + operation would result in duplicate primary key values. + The conflicting row in this case is the database row with the + matching primary key. + + + + + If a non-foreign key constraint violation occurs while applying a + change (i.e. a UNIQUE, CHECK or NOT NULL constraint), the conflict + callback will see this value. + + There is no conflicting row in this case. The results of invoking + the + method are undefined. + + + + + If foreign key handling is enabled, and applying a changes leaves + the database in a state containing foreign key violations, this + value will be seen exactly once before the changes are committed. + If the conflict handler + , the changes, + including those that caused the foreign key constraint violation, + are committed. Or, if it returns + , the changes are + rolled back. + + No current or conflicting row information is provided. The only + method it is possible to call on the supplied + object is + . + + + + + This enumerated type represents the result of a user-defined conflict + resolution callback. + + + + + If a conflict callback returns this value no special action is + taken. The change that caused the conflict is not applied. The + application of changes continues with the next change. + + + + + This value may only be returned from a conflict callback if the + type of conflict was + or . If this is + not the case, any changes applied so far are rolled back and the + call to + + will raise a with an error code of + . + + If this value is returned for a + conflict, then the + conflicting row is either updated or deleted, depending on the type + of change. + + If this value is returned for a + conflict, then + the conflicting row is removed from the database and a second + attempt to apply the change is made. If this second attempt fails, + the original row is restored to the database before continuing. + + + + + If this value is returned, any changes applied so far are rolled + back and the call to + + will raise a with an error code of + . + + + + + This enumerated type represents possible flags that may be passed + to the appropriate overloads of various change set creation methods. + + + + + No special handling. + + + + + Invert the change set while iterating through it. + This is equivalent to inverting a change set using + before + applying it. It is an error to specify this flag + with a patch set. + + + + + This callback is invoked when a determination must be made about + whether changes to a specific table should be tracked -OR- applied. + It will not be called for tables that are already attached to a + . + + + The optional application-defined context data that was originally + passed to the or + + methods. This value may be null. + + + The name of the table. + + + Non-zero if changes to the table should be considered; otherwise, + zero. Throwing an exception from this callback will result in + undefined behavior. + + + + + This callback is invoked when there is a conflict while apply changes + to a database. + + + The optional application-defined context data that was originally + passed to the + + method. This value may be null. + + + The type of this conflict. + + + The object associated with + this conflict. This value may not be null; however, only properties + that are applicable to the conflict type will be available. Further + information on this is available within the descriptions of the + available values. + + + A value that indicates the + action to be taken in order to resolve the conflict. Throwing an + exception from this callback will result in undefined behavior. + + + + + This interface contains methods used to manipulate a set of changes for + a database. + + + + + This method "inverts" the set of changes within this instance. + Applying an inverted set of changes to a database reverses the + effects of applying the uninverted changes. Specifically: + ]]>]]> + Each DELETE change is changed to an INSERT, and + ]]>]]> + Each INSERT change is changed to a DELETE, and + ]]>]]> + For each UPDATE change, the old.* and new.* values are exchanged. + ]]>]]> + This method does not change the order in which changes appear + within the set of changes. It merely reverses the sense of each + individual change. + + + The new instance that represents + the resulting set of changes -OR- null if it is not available. + + + + + This method combines the specified set of changes with the ones + contained in this instance. + + + The changes to be combined with those in this instance. + + + The new instance that represents + the resulting set of changes -OR- null if it is not available. + + + + + Attempts to apply the set of changes in this instance to the + associated database. + + + The delegate that will need + to handle any conflicting changes that may arise. + + + The optional application-defined context data. This value may be + null. + + + + + Attempts to apply the set of changes in this instance to the + associated database. + + + The delegate that will need + to handle any conflicting changes that may arise. + + + The optional delegate + that can be used to filter the list of tables impacted by the set + of changes. + + + The optional application-defined context data. This value may be + null. + + + + + This interface contains methods used to manipulate multiple sets of + changes for a database. + + + + + Attempts to add a change set (or patch set) to this change group + instance. The underlying data must be contained entirely within + the byte array. + + + The raw byte data for the specified change set (or patch set). + + + + + Attempts to add a change set (or patch set) to this change group + instance. The underlying data will be read from the specified + . + + + The instance containing the raw change set + (or patch set) data to read. + + + + + Attempts to create and return, via , the + combined set of changes represented by this change group instance. + + + Upon success, this will contain the raw byte data for all the + changes in this change group instance. + + + + + Attempts to create and write, via , the + combined set of changes represented by this change group instance. + + + Upon success, the raw byte data for all the changes in this change + group instance will be written to this . + + + + + This interface contains properties and methods used to fetch metadata + about one change within a set of changes for a database. + + + + + The name of the table the change was made to. + + + + + The number of columns impacted by this change. This value can be + used to determine the highest valid column index that may be used + with the , , + and methods of this interface. It + will be this value minus one. + + + + + This will contain the value + , + , or + , corresponding to + the overall type of change this item represents. + + + + + Non-zero if this change is considered to be indirect (i.e. as + though they were made via a trigger or foreign key action). + + + + + This array contains a for each column in + the table associated with this change. The element will be zero + if the column is not part of the primary key; otherwise, it will + be non-zero. + + + + + This method may only be called from within a + delegate when the conflict + type is . It + returns the total number of known foreign key violations in the + destination database. + + + + + Queries and returns the original value of a given column for this + change. This method may only be called when the + has a value of + or + . + + + The index for the column. This value must be between zero and one + less than the total number of columns for this table. + + + The original value of a given column for this change. + + + + + Queries and returns the updated value of a given column for this + change. This method may only be called when the + has a value of + or + . + + + The index for the column. This value must be between zero and one + less than the total number of columns for this table. + + + The updated value of a given column for this change. + + + + + Queries and returns the conflicting value of a given column for + this change. This method may only be called from within a + delegate when the conflict + type is or + . + + + The index for the column. This value must be between zero and one + less than the total number of columns for this table. + + + The conflicting value of a given column for this change. + + + + + This interface contains methods to query and manipulate the state of a + change tracking session for a database. + + + + + Determines if this session is currently tracking changes to its + associated database. + + + Non-zero if changes to the associated database are being trakced; + otherwise, zero. + + + + + Enables tracking of changes to the associated database. + + + + + Disables tracking of changes to the associated database. + + + + + Determines if this session is currently set to mark changes as + indirect (i.e. as though they were made via a trigger or foreign + key action). + + + Non-zero if changes to the associated database are being marked as + indirect; otherwise, zero. + + + + + Sets the indirect flag for this session. Subsequent changes will + be marked as indirect until this flag is changed again. + + + + + Clears the indirect flag for this session. Subsequent changes will + be marked as direct until this flag is changed again. + + + + + Determines if there are any tracked changes currently within the + data for this session. + + + Non-zero if there are no changes within the data for this session; + otherwise, zero. + + + + + Upon success, causes changes to the specified table(s) to start + being tracked. Any tables impacted by calls to this method will + not cause the callback + to be invoked. + + + The name of the table to be tracked -OR- null to track all + applicable tables within this database. + + + + + This method is used to set the table filter for this instance. + + + The table filter callback -OR- null to clear any existing table + filter callback. + + + The optional application-defined context data. This value may be + null. + + + + + Attempts to create and return, via , the + combined set of changes represented by this session instance. + + + Upon success, this will contain the raw byte data for all the + changes in this session instance. + + + + + Attempts to create and write, via , the + combined set of changes represented by this session instance. + + + Upon success, the raw byte data for all the changes in this session + instance will be written to this . + + + + + Attempts to create and return, via , the + combined set of changes represented by this session instance as a + patch set. + + + Upon success, this will contain the raw byte data for all the + changes in this session instance. + + + + + Attempts to create and write, via , the + combined set of changes represented by this session instance as a + patch set. + + + Upon success, the raw byte data for all the changes in this session + instance will be written to this . + + + + + This method loads the differences between two tables [with the same + name, set of columns, and primary key definition] into this session + instance. + + + The name of the database containing the table with the original + data (i.e. it will need updating in order to be identical to the + one within the database associated with this session instance). + + + The name of the table. + + + + + This class contains some static helper methods for use within this + subsystem. + + + + + This method checks the byte array specified by the caller to make + sure it will be usable. + + + A byte array provided by the caller into one of the public methods + for the classes that belong to this subsystem. This value cannot + be null or represent an empty array; otherwise, an appropriate + exception will be thrown. + + + + + This class is used to hold the native connection handle associated with + a open until this subsystem is totally + done with it. This class is for internal use by this subsystem only. + + + + + The SQL statement used when creating the native statement handle. + There are no special requirements for this other than counting as + an "open statement handle". + + + + + The format of the error message used when reporting, during object + disposal, that the statement handle is still open (i.e. because + this situation is considered a fairly serious programming error). + + + + + The wrapped native connection handle associated with this lock. + + + + + The flags associated with the connection represented by the + value. + + + + + The native statement handle for this lock. The garbage collector + cannot cause this statement to be finalized; therefore, it will + serve to hold the associated native connection open until it is + freed manually using the method. + + + + + Constructs a new instance of this class using the specified wrapped + native connection handle and associated flags. + + + The wrapped native connection handle to be associated with this + lock. + + + The flags associated with the connection represented by the + value. + + + Non-zero if the method should be called prior + to returning from this constructor. + + + + + Queries and returns the wrapped native connection handle for this + instance. + + + The wrapped native connection handle for this instance -OR- null + if it is unavailable. + + + + + Queries and returns the flags associated with the connection for + this instance. + + + The value. There is no return + value reserved to indicate an error. + + + + + Queries and returns the native connection handle for this instance. + + + The native connection handle for this instance. If this value is + unavailable or invalid an exception will be thrown. + + + + + This method attempts to "lock" the associated native connection + handle by preparing a SQL statement that will not be finalized + until the method is called (i.e. and which + cannot be done by the garbage collector). If the statement is + already prepared, nothing is done. If the statement cannot be + prepared for any reason, an exception will be thrown. + + + + + This method attempts to "unlock" the associated native connection + handle by finalizing the previously prepared statement. If the + statement is already finalized, nothing is done. If the statement + cannot be finalized for any reason, an exception will be thrown. + + + + + Disposes of this object instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + Finalizes this object instance. + + + + + This class manages the native change set iterator. It is used as the + base class for the and + classes. It knows how to + advance the native iterator handle as well as finalize it. + + + + + The native change set (a.k.a. iterator) handle. + + + + + Non-zero if this instance owns the native iterator handle in the + field. In that case, this instance will + finalize the native iterator handle upon being disposed or + finalized. + + + + + Constructs a new instance of this class using the specified native + iterator handle. + + + The native iterator handle to use. + + + Non-zero if this instance is to take ownership of the native + iterator handle specified by . + + + + + Throws an exception if the native iterator handle is invalid. + + + + + Used to query the native iterator handle. This method is only used + by the class. + + + The native iterator handle -OR- if it + is not available. + + + + + Attempts to advance the native iterator handle to its next item. + + + Non-zero if the native iterator handle was advanced and contains + more data; otherwise, zero. If the underlying native API returns + an unexpected value then an exception will be thrown. + + + + + Attempts to create an instance of this class that is associated + with the specified native iterator handle. Ownership of the + native iterator handle is NOT transferred to the new instance of + this class. + + + The native iterator handle to use. + + + The new instance of this class. No return value is reserved to + indicate an error; however, if the native iterator handle is not + valid, any subsequent attempt to make use of it via the returned + instance of this class may throw exceptions. + + + + + Disposes of this object instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + Finalizes this object instance. + + + + + This class manages the native change set iterator for a set of changes + contained entirely in memory. + + + + + The native memory buffer allocated to contain the set of changes + associated with this instance. This will always be freed when this + instance is disposed or finalized. + + + + + Constructs an instance of this class using the specified native + memory buffer and native iterator handle. + + + The native memory buffer to use. + + + The native iterator handle to use. + + + Non-zero if this instance is to take ownership of the native + iterator handle specified by . + + + + + Attempts to create an instance of this class using the specified + raw byte data. + + + The raw byte data containing the set of changes for this native + iterator. + + + The new instance of this class -OR- null if it cannot be created. + + + + + Attempts to create an instance of this class using the specified + raw byte data. + + + The raw byte data containing the set of changes for this native + iterator. + + + The flags used to create the change set iterator. + + + The new instance of this class -OR- null if it cannot be created. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + This class manages the native change set iterator for a set of changes + backed by a instance. + + + + + The instance that is managing + the underlying used as the backing store for + the set of changes associated with this native change set iterator. + + + + + Constructs an instance of this class using the specified native + iterator handle and . + + + The instance to use. + + + The native iterator handle to use. + + + Non-zero if this instance is to take ownership of the native + iterator handle specified by . + + + + + Attempts to create an instance of this class using the specified + . + + + The where the raw byte data for the set of + changes may be read. + + + The flags associated with the parent connection. + + + The new instance of this class -OR- null if it cannot be created. + + + + + Attempts to create an instance of this class using the specified + . + + + The where the raw byte data for the set of + changes may be read. + + + The flags associated with the parent connection. + + + The flags used to create the change set iterator. + + + The new instance of this class -OR- null if it cannot be created. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + This class is used to act as a bridge between a + instance and the delegates used with the native streaming API. + + + + + The managed stream instance used to in order to service the native + delegates for both input and output. + + + + + The flags associated with the connection. + + + + + The delegate used to provide input to the native streaming API. + It will be null -OR- point to the method. + + + + + The delegate used to provide output to the native streaming API. + It will be null -OR- point to the method. + + + + + Constructs a new instance of this class using the specified managed + stream and connection flags. + + + The managed stream instance to be used in order to service the + native delegates for both input and output. + + + The flags associated with the parent connection. + + + + + Queries and returns the flags associated with the connection for + this instance. + + + The value. There is no return + value reserved to indicate an error. + + + + + Returns a delegate that wraps the method, + creating it first if necessary. + + + A delegate that refers to the method. + + + + + Returns a delegate that wraps the method, + creating it first if necessary. + + + A delegate that refers to the method. + + + + + This method attempts to read bytes from + the managed stream, writing them to the + buffer. + + + Optional extra context information. Currently, this will always + have a value of . + + + A preallocated native buffer to receive the requested input bytes. + It must be at least bytes in size. + + + Upon entry, the number of bytes to read. Upon exit, the number of + bytes actually read. This value may be zero upon exit. + + + The value upon success -OR- an + appropriate error code upon failure. + + + + + This method attempts to write bytes to + the managed stream, reading them from the + buffer. + + + Optional extra context information. Currently, this will always + have a value of . + + + A preallocated native buffer containing the requested output + bytes. It must be at least bytes in + size. + + + The number of bytes to write. + + + The value upon success -OR- an + appropriate error code upon failure. + + + + + Disposes of this object instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + Finalizes this object instance. + + + + + This class manages a collection of + instances. When used, it takes responsibility for creating, returning, + and disposing of its instances. + + + + + The managed collection of + instances, keyed by their associated + instance. + + + + + The flags associated with the connection. + + + + + Constructs a new instance of this class using the specified + connection flags. + + + The flags associated with the parent connection. + + + + + Makes sure the collection of + is created. + + + + + Makes sure the collection of + is disposed. + + + + + Attempts to return a instance + suitable for the specified . + + + The instance. If this value is null, a null + value will be returned. + + + A instance. Typically, these + are always freshly created; however, this method is designed to + return the existing instance + associated with the specified stream, should one exist. + + + + + Disposes of this object instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + Finalizes this object instance. + + + + + This class represents a group of change sets (or patch sets). + + + + + The instance associated + with this change group. + + + + + The flags associated with the connection. + + + + + The native handle for this change group. This will be deleted when + this instance is disposed or finalized. + + + + + Constructs a new instance of this class using the specified + connection flags. + + + The flags associated with the parent connection. + + + + + Throws an exception if the native change group handle is invalid. + + + + + Makes sure the native change group handle is valid, creating it if + necessary. + + + + + Makes sure the instance + is available, creating it if necessary. + + + + + Attempts to return a instance + suitable for the specified . + + + The instance. If this value is null, a null + value will be returned. + + + A instance. Typically, these + are always freshly created; however, this method is designed to + return the existing instance + associated with the specified stream, should one exist. + + + + + Attempts to add a change set (or patch set) to this change group + instance. The underlying data must be contained entirely within + the byte array. + + + The raw byte data for the specified change set (or patch set). + + + + + Attempts to add a change set (or patch set) to this change group + instance. The underlying data will be read from the specified + . + + + The instance containing the raw change set + (or patch set) data to read. + + + + + Attempts to create and return, via , the + combined set of changes represented by this change group instance. + + + Upon success, this will contain the raw byte data for all the + changes in this change group instance. + + + + + Attempts to create and write, via , the + combined set of changes represented by this change group instance. + + + Upon success, the raw byte data for all the changes in this change + group instance will be written to this . + + + + + Disposes of this object instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + Finalizes this object instance. + + + + + This class represents the change tracking session associated with a + database. + + + + + The instance associated + with this session. + + + + + The name of the database (e.g. "main") for this session. + + + + + The native handle for this session. This will be deleted when + this instance is disposed or finalized. + + + + + The delegate used to provide table filtering to the native API. + It will be null -OR- point to the method. + + + + + The managed callback used to filter tables for this session. Set + via the method. + + + + + The optional application-defined context data that was passed to + the method. This value may be null. + + + + + Constructs a new instance of this class using the specified wrapped + native connection handle and associated flags. + + + The wrapped native connection handle to be associated with this + session. + + + The flags associated with the connection represented by the + value. + + + The name of the database (e.g. "main") for this session. + + + + + Throws an exception if the native session handle is invalid. + + + + + Makes sure the native session handle is valid, creating it if + necessary. + + + + + This method sets up the internal table filtering associated state + of this instance. + + + The table filter callback -OR- null to clear any existing table + filter callback. + + + The optional application-defined context data. This value may be + null. + + + The native + delegate -OR- null to clear any existing table filter. + + + + + Makes sure the instance + is available, creating it if necessary. + + + + + Attempts to return a instance + suitable for the specified . + + + The instance. If this value is null, a null + value will be returned. + + + A instance. Typically, these + are always freshly created; however, this method is designed to + return the existing instance + associated with the specified stream, should one exist. + + + + + This method is called when determining if a table needs to be + included in the tracked changes for the associated database. + + + Optional extra context information. Currently, this will always + have a value of . + + + The native pointer to the name of the table. + + + Non-zero if changes to the specified table should be considered; + otherwise, zero. + + + + + Determines if this session is currently tracking changes to its + associated database. + + + Non-zero if changes to the associated database are being trakced; + otherwise, zero. + + + + + Enables tracking of changes to the associated database. + + + + + Disables tracking of changes to the associated database. + + + + + Determines if this session is currently set to mark changes as + indirect (i.e. as though they were made via a trigger or foreign + key action). + + + Non-zero if changes to the associated database are being marked as + indirect; otherwise, zero. + + + + + Sets the indirect flag for this session. Subsequent changes will + be marked as indirect until this flag is changed again. + + + + + Clears the indirect flag for this session. Subsequent changes will + be marked as direct until this flag is changed again. + + + + + Determines if there are any tracked changes currently within the + data for this session. + + + Non-zero if there are no changes within the data for this session; + otherwise, zero. + + + + + Upon success, causes changes to the specified table(s) to start + being tracked. Any tables impacted by calls to this method will + not cause the callback + to be invoked. + + + The name of the table to be tracked -OR- null to track all + applicable tables within this database. + + + + + This method is used to set the table filter for this instance. + + + The table filter callback -OR- null to clear any existing table + filter callback. + + + The optional application-defined context data. This value may be + null. + + + + + Attempts to create and return, via , the + set of changes represented by this session instance. + + + Upon success, this will contain the raw byte data for all the + changes in this session instance. + + + + + Attempts to create and write, via , the + set of changes represented by this session instance. + + + Upon success, the raw byte data for all the changes in this session + instance will be written to this . + + + + + Attempts to create and return, via , the + set of changes represented by this session instance as a patch set. + + + Upon success, this will contain the raw byte data for all the + changes in this session instance. + + + + + Attempts to create and write, via , the + set of changes represented by this session instance as a patch set. + + + Upon success, the raw byte data for all the changes in this session + instance will be written to this . + + + + + This method loads the differences between two tables [with the same + name, set of columns, and primary key definition] into this session + instance. + + + The name of the database containing the table with the original + data (i.e. it will need updating in order to be identical to the + one within the database associated with this session instance). + + + The name of the table. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + This class represents the abstract concept of a set of changes. It + acts as the base class for the + and classes. It derives from + the class, which is used to hold + the underlying native connection handle open until the instances of + this class are disposed or finalized. It also provides the ability + to construct wrapped native delegates of the + and + types. + + + + + Constructs an instance of this class using the specified wrapped + native connection handle. + + + The wrapped native connection handle to be associated with this + change set. + + + The flags associated with the connection represented by the + value. + + + + + Creates and returns a concrete implementation of the + interface. + + + The native iterator handle to use. + + + An instance of the + interface, which can be used to fetch metadata associated with + the current item in this set of changes. + + + + + Attempts to create a + native delegate + that invokes the specified + delegate. + + + The to invoke when the + native delegate + is called. If this value is null then null is returned. + + + The optional application-defined context data. This value may be + null. + + + The created + native delegate -OR- null if it cannot be created. + + + + + Attempts to create a + native delegate + that invokes the specified + delegate. + + + The to invoke when the + native delegate + is called. If this value is null then null is returned. + + + The optional application-defined context data. This value may be + null. + + + The created + native delegate -OR- null if it cannot be created. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + This class represents a set of changes contained entirely in memory. + + + + + The raw byte data for this set of changes. Since this data must + be marshalled to a native memory buffer before being used, there + must be enough memory available to store at least two times the + amount of data contained within it. + + + + + The flags used to create the change set iterator. + + + + + Constructs an instance of this class using the specified raw byte + data and wrapped native connection handle. + + + The raw byte data for the specified change set (or patch set). + + + The wrapped native connection handle to be associated with this + set of changes. + + + The flags associated with the connection represented by the + value. + + + + + Constructs an instance of this class using the specified raw byte + data and wrapped native connection handle. + + + The raw byte data for the specified change set (or patch set). + + + The wrapped native connection handle to be associated with this + set of changes. + + + The flags associated with the connection represented by the + value. + + + The flags used to create the change set iterator. + + + + + This method "inverts" the set of changes within this instance. + Applying an inverted set of changes to a database reverses the + effects of applying the uninverted changes. Specifically: + ]]>]]> + Each DELETE change is changed to an INSERT, and + ]]>]]> + Each INSERT change is changed to a DELETE, and + ]]>]]> + For each UPDATE change, the old.* and new.* values are exchanged. + ]]>]]> + This method does not change the order in which changes appear + within the set of changes. It merely reverses the sense of each + individual change. + + + The new instance that represents + the resulting set of changes. + + + + + This method combines the specified set of changes with the ones + contained in this instance. + + + The changes to be combined with those in this instance. + + + The new instance that represents + the resulting set of changes. + + + + + Attempts to apply the set of changes in this instance to the + associated database. + + + The delegate that will need + to handle any conflicting changes that may arise. + + + The optional application-defined context data. This value may be + null. + + + + + Attempts to apply the set of changes in this instance to the + associated database. + + + The delegate that will need + to handle any conflicting changes that may arise. + + + The optional delegate + that can be used to filter the list of tables impacted by the set + of changes. + + + The optional application-defined context data. This value may be + null. + + + + + Creates an capable of iterating over the + items within this set of changes. + + + The new + instance. + + + + + Creates an capable of iterating over the + items within this set of changes. + + + The new instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + This class represents a set of changes that are backed by a + instance. + + + + + The instance that is managing + the underlying input used as the backing + store for the set of changes associated with this instance. + + + + + The instance that is managing + the underlying output used as the backing + store for the set of changes generated by the + or methods. + + + + + The instance used as the backing store for + the set of changes associated with this instance. + + + + + The instance used as the backing store for + the set of changes generated by the or + methods. + + + + + The flags used to create the change set iterator. + + + + + Constructs an instance of this class using the specified streams + and wrapped native connection handle. + + + The where the raw byte data for the set of + changes may be read. + + + The where the raw byte data for resulting + sets of changes may be written. + + + The wrapped native connection handle to be associated with this + set of changes. + + + The flags associated with the connection represented by the + value. + + + + + Constructs an instance of this class using the specified streams + and wrapped native connection handle. + + + The where the raw byte data for the set of + changes may be read. + + + The where the raw byte data for resulting + sets of changes may be written. + + + The wrapped native connection handle to be associated with this + set of changes. + + + The flags associated with the connection represented by the + value. + + + The flags used to create the change set iterator. + + + + + Throws an exception if the input stream or its associated stream + adapter are invalid. + + + + + Throws an exception if the output stream or its associated stream + adapter are invalid. + + + + + This method "inverts" the set of changes within this instance. + Applying an inverted set of changes to a database reverses the + effects of applying the uninverted changes. Specifically: + ]]>]]> + Each DELETE change is changed to an INSERT, and + ]]>]]> + Each INSERT change is changed to a DELETE, and + ]]>]]> + For each UPDATE change, the old.* and new.* values are exchanged. + ]]>]]> + This method does not change the order in which changes appear + within the set of changes. It merely reverses the sense of each + individual change. + + + Since the resulting set of changes is written to the output stream, + this method always returns null. + + + + + This method combines the specified set of changes with the ones + contained in this instance. + + + The changes to be combined with those in this instance. + + + Since the resulting set of changes is written to the output stream, + this method always returns null. + + + + + Attempts to apply the set of changes in this instance to the + associated database. + + + The delegate that will need + to handle any conflicting changes that may arise. + + + The optional application-defined context data. This value may be + null. + + + + + Attempts to apply the set of changes in this instance to the + associated database. + + + The delegate that will need + to handle any conflicting changes that may arise. + + + The optional delegate + that can be used to filter the list of tables impacted by the set + of changes. + + + The optional application-defined context data. This value may be + null. + + + + + Creates an capable of iterating over the + items within this set of changes. + + + The new + instance. + + + + + Creates an capable of iterating over the + items within this set of changes. + + + The new instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + This class represents an that is capable of + enumerating over a set of changes. It serves as the base class for the + and + classes. It manages and + owns an instance of the class. + + + + + This managed change set iterator is managed and owned by this + class. It will be disposed when this class is disposed. + + + + + Constructs an instance of this class using the specified managed + change set iterator. + + + The managed iterator instance to use. + + + + + Throws an exception if the managed iterator instance is invalid. + + + + + Sets the managed iterator instance to a new value. + + + The new managed iterator instance to use. + + + + + Disposes of the managed iterator instance and sets its value to + null. + + + + + Disposes of the existing managed iterator instance and then sets it + to a new value. + + + The new managed iterator instance to use. + + + + + Returns the current change within the set of changes, represented + by a instance. + + + + + Returns the current change within the set of changes, represented + by a instance. + + + + + Attempts to advance to the next item in the set of changes. + + + Non-zero if more items are available; otherwise, zero. + + + + + Throws because not all the + derived classes are able to support reset functionality. + + + + + Disposes of this object instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + Finalizes this object instance. + + + + + This class represents an that is capable of + enumerating over a set of changes contained entirely in memory. + + + + + The raw byte data for this set of changes. Since this data must + be marshalled to a native memory buffer before being used, there + must be enough memory available to store at least two times the + amount of data contained within it. + + + + + The flags used to create the change set iterator. + + + + + Constructs an instance of this class using the specified raw byte + data. + + + The raw byte data containing the set of changes for this + enumerator. + + + + + Constructs an instance of this class using the specified raw byte + data. + + + The raw byte data containing the set of changes for this + enumerator. + + + The flags used to create the change set iterator. + + + + + Resets the enumerator to its initial position. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + This class represents an that is capable of + enumerating over a set of changes backed by a + instance. + + + + + Constructs an instance of this class using the specified stream. + + + The where the raw byte data for the set of + changes may be read. + + + The flags associated with the parent connection. + + + + + Constructs an instance of this class using the specified stream. + + + The where the raw byte data for the set of + changes may be read. + + + The flags associated with the parent connection. + + + The flags used to create the change set iterator. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + This interface implements properties and methods used to fetch metadata + about one change within a set of changes for a database. + + + + + The instance to use. This + will NOT be owned by this class and will not be disposed upon this + class being disposed or finalized. + + + + + Constructs an instance of this class using the specified iterator + instance. + + + The managed iterator instance to use. + + + + + Throws an exception if the managed iterator instance is invalid. + + + + + Populates the underlying data for the , + , , and + properties, using the appropriate native + API. + + + + + Populates the underlying data for the + property using the appropriate + native API. + + + + + Populates the underlying data for the + property using the + appropriate native API. + + + + + Backing field for the property. This value + will be null if this field has not yet been populated via the + underlying native API. + + + + + The name of the table the change was made to. + + + + + Backing field for the property. This + value will be null if this field has not yet been populated via the + underlying native API. + + + + + The number of columns impacted by this change. This value can be + used to determine the highest valid column index that may be used + with the , , + and methods of this interface. It + will be this value minus one. + + + + + Backing field for the property. This + value will be null if this field has not yet been populated via the + underlying native API. + + + + + This will contain the value + , + , or + , corresponding to + the overall type of change this item represents. + + + + + Backing field for the property. This value + will be null if this field has not yet been populated via the + underlying native API. + + + + + Non-zero if this change is considered to be indirect (i.e. as + though they were made via a trigger or foreign key action). + + + + + Backing field for the property. + This value will be null if this field has not yet been populated + via the underlying native API. + + + + + This array contains a for each column in + the table associated with this change. The element will be zero + if the column is not part of the primary key; otherwise, it will + be non-zero. + + + + + Backing field for the + property. This value will be null if this field has not yet been + populated via the underlying native API. + + + + + This method may only be called from within a + delegate when the conflict + type is . It + returns the total number of known foreign key violations in the + destination database. + + + + + Queries and returns the original value of a given column for this + change. This method may only be called when the + has a value of + or + . + + + The index for the column. This value must be between zero and one + less than the total number of columns for this table. + + + The original value of a given column for this change. + + + + + Queries and returns the updated value of a given column for this + change. This method may only be called when the + has a value of + or + . + + + The index for the column. This value must be between zero and one + less than the total number of columns for this table. + + + The updated value of a given column for this change. + + + + + Queries and returns the conflicting value of a given column for + this change. This method may only be called from within a + delegate when the conflict + type is or + . + + + The index for the column. This value must be between zero and one + less than the total number of columns for this table. + + + The conflicting value of a given column for this change. + + + + + Disposes of this object instance. + + + + + Non-zero if this object instance has been disposed. + + + + + Throws an exception if this object instance has been disposed. + + + + + Disposes or finalizes this object instance. + + + Non-zero if this object is being disposed; otherwise, this object + is being finalized. + + + + + Finalizes this object instance. + + +
+
diff --git a/DLL/System.Interactive.Async.dll b/DLL/System.Interactive.Async.dll new file mode 100644 index 0000000..48efea4 Binary files /dev/null and b/DLL/System.Interactive.Async.dll differ diff --git a/DLL/System.Runtime.InteropServices.RuntimeInformation.dll b/DLL/System.Runtime.InteropServices.RuntimeInformation.dll new file mode 100644 index 0000000..360e92a Binary files /dev/null and b/DLL/System.Runtime.InteropServices.RuntimeInformation.dll differ diff --git a/DLL/System.ValueTuple.dll b/DLL/System.ValueTuple.dll new file mode 100644 index 0000000..1cadbf3 Binary files /dev/null and b/DLL/System.ValueTuple.dll differ diff --git a/DLL/System.Web.Http.Owin.dll b/DLL/System.Web.Http.Owin.dll new file mode 100644 index 0000000..2db6f2d Binary files /dev/null and b/DLL/System.Web.Http.Owin.dll differ diff --git a/DLL/System.Web.Http.dll b/DLL/System.Web.Http.dll new file mode 100644 index 0000000..136113c Binary files /dev/null and b/DLL/System.Web.Http.dll differ diff --git a/DLL/ThoughtWorks.QRCode.dll b/DLL/ThoughtWorks.QRCode.dll new file mode 100644 index 0000000..522c7ed Binary files /dev/null and b/DLL/ThoughtWorks.QRCode.dll differ diff --git a/DLL/UI.Framework.dll b/DLL/UI.Framework.dll new file mode 100644 index 0000000..10d03be Binary files /dev/null and b/DLL/UI.Framework.dll differ diff --git a/DLL/UICorePlus.dll b/DLL/UICorePlus.dll new file mode 100644 index 0000000..e3785f1 Binary files /dev/null and b/DLL/UICorePlus.dll differ diff --git a/DLL/WeiQ.Framework.dll b/DLL/WeiQ.Framework.dll new file mode 100644 index 0000000..411cbf6 Binary files /dev/null and b/DLL/WeiQ.Framework.dll differ diff --git a/DLL/WeiQ.Framework.hvmprj b/DLL/WeiQ.Framework.hvmprj new file mode 100644 index 0000000..060db9a --- /dev/null +++ b/DLL/WeiQ.Framework.hvmprj @@ -0,0 +1,67 @@ + + + + + .\WeiQ.Framework.dll + + + + ..\DLL_Protected + Runtime.dll + HVMRun64.dll + 0 + 0 + true + true + true + +
+ 1 + + + 600 + 400 + 0 + + Loading... + Starting... + + + +
+
+ + true + true + true + true + true + true + true + true + true + true + true + true + true + true + 5 + 0 + true + true + true + true + + + true + true + 1 + + + + + true + true + + +
diff --git a/DLL/WeiQ.Framework.snk b/DLL/WeiQ.Framework.snk new file mode 100644 index 0000000..ddb1d27 --- /dev/null +++ b/DLL/WeiQ.Framework.snk @@ -0,0 +1 @@ +0024000004800000940000000602000000240000525341310004000001000100d5a0c7e494766fed85a57d1797641738ef18a7476257c4d2ff2c1fdda845dd5f7f0a9fcc52ba537b66ed6ff450595a520d2357eaa1ead76bf7852f8038f4a3d36e5daedde75674c48247bdb95670179305c96d037bb9c8b37665c42a43b744645996c025969a215abbf1d86b2c2c6a57a34cb968c801442b04e2bb765d82d4bf \ No newline at end of file diff --git a/DLL/ZipExtract.exe b/DLL/ZipExtract.exe new file mode 100644 index 0000000..026aa32 Binary files /dev/null and b/DLL/ZipExtract.exe differ diff --git a/DLL/grpc_csharp_ext.x64.dll b/DLL/grpc_csharp_ext.x64.dll new file mode 100644 index 0000000..6ed5407 Binary files /dev/null and b/DLL/grpc_csharp_ext.x64.dll differ diff --git a/DLL/grpc_csharp_ext.x86.dll b/DLL/grpc_csharp_ext.x86.dll new file mode 100644 index 0000000..5a7fb96 Binary files /dev/null and b/DLL/grpc_csharp_ext.x86.dll differ diff --git a/DLL/log4net.dll b/DLL/log4net.dll new file mode 100644 index 0000000..e74861d Binary files /dev/null and b/DLL/log4net.dll differ diff --git a/DLL/mysql.data.dll b/DLL/mysql.data.dll new file mode 100644 index 0000000..ac84b5e Binary files /dev/null and b/DLL/mysql.data.dll differ diff --git a/DLL/node.dll b/DLL/node.dll new file mode 100644 index 0000000..a148004 Binary files /dev/null and b/DLL/node.dll differ diff --git a/DLL/protobuf-net.dll b/DLL/protobuf-net.dll new file mode 100644 index 0000000..de4701c Binary files /dev/null and b/DLL/protobuf-net.dll differ diff --git a/DLL/zxing.dll b/DLL/zxing.dll new file mode 100644 index 0000000..b7cf916 Binary files /dev/null and b/DLL/zxing.dll differ diff --git a/Document.shfbproj b/Document.shfbproj new file mode 100644 index 0000000..69ce246 --- /dev/null +++ b/Document.shfbproj @@ -0,0 +1,96 @@ + + + + + + v4.7.2 + + Debug + AnyCPU + 2.0 + {741bdc80-9707-44aa-9aff-061a61a353ae} + 2017.9.26.0 + + Documentation + Documentation + Documentation + + .NET Framework 4.6.2 + .\Help\ + flcc + zh-CN + A Sandcastle Documented Class Library + 1.0.0.0 + Guid + AboveNamespaces + False + False + 2 + False + Blank + HtmlHelp1 + C# + VS2013 + True + True + False + False + OnlyWarningsAndErrors + 100 + + + + + + + + + + + + + + + + Summary, Parameter, AutoDocumentCtors, Namespace, AutoDocumentDispose + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OnBuildSuccess + + \ No newline at end of file diff --git a/Document/apidoc.json b/Document/apidoc.json new file mode 100644 index 0000000..4ffbed0 --- /dev/null +++ b/Document/apidoc.json @@ -0,0 +1,14 @@ +{ + "name": "返利开发文档", + "version": "0.0.1", + "description": "接口文档描述", + "title": "返利接口文档", + "url" : "http://127.0.0.1:9998", + "sampleUrl" : "http://127.0.0.1:9998", + "order": [ + "系统" + ], + "template": { + "forceLanguage": "zh_cn" + } +} \ No newline at end of file diff --git a/FLSystem.sln b/FLSystem.sln new file mode 100644 index 0000000..46abd6b --- /dev/null +++ b/FLSystem.sln @@ -0,0 +1,1579 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.960 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FLSystem", "FLSystem\FLSystem.csproj", "{2E04051F-0E96-409A-9F93-4418603E69D0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "类库", "类库", "{927E9767-FEA0-4FE7-A441-69E4CFEC0B48}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api.Framework", "类库\Api.Framework\Api.Framework.csproj", "{DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}" + ProjectSection(ProjectDependencies) = postProject + {08421940-859B-4E93-B8D5-C4BEF64B0A95} = {08421940-859B-4E93-B8D5-C4BEF64B0A95} + {2916C951-8BF2-4941-BF8D-EBC1E1A73758} = {2916C951-8BF2-4941-BF8D-EBC1E1A73758} + {F865D881-B9D2-4C90-9AD0-0667103827F6} = {F865D881-B9D2-4C90-9AD0-0667103827F6} + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5} = {489BB790-226C-4FAD-8D1E-51D72A7FF8E5} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chat.Framework", "类库\Chat.Framework\Chat.Framework.csproj", "{08421940-859B-4E93-B8D5-C4BEF64B0A95}" + ProjectSection(ProjectDependencies) = postProject + {2916C951-8BF2-4941-BF8D-EBC1E1A73758} = {2916C951-8BF2-4941-BF8D-EBC1E1A73758} + {F865D881-B9D2-4C90-9AD0-0667103827F6} = {F865D881-B9D2-4C90-9AD0-0667103827F6} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grant.Framework", "类库\Grant.Framework\Grant.Framework.csproj", "{2916C951-8BF2-4941-BF8D-EBC1E1A73758}" + ProjectSection(ProjectDependencies) = postProject + {F865D881-B9D2-4C90-9AD0-0667103827F6} = {F865D881-B9D2-4C90-9AD0-0667103827F6} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "应用", "应用", "{7731056B-09B5-4494-907E-CDCD561F36FA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoAnswer", "应用\AutoAnswer\AutoAnswer.csproj", "{E5A7E5DB-EB35-4542-BD69-22E263691CAA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackupAndImport", "应用\BackupAndImport\BackupAndImport.csproj", "{35A30202-1D63-413A-AD12-8FFB24165B43}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleaningTools", "应用\CleaningTools\CleaningTools.csproj", "{91A026DE-527F-4897-A1DC-01775E1CDD03}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PDDRebate", "应用\PDDRebate\PDDRebate.csproj", "{6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MessageSupervises", "应用\MessageSupervises\MessageSupervises.csproj", "{659742CF-6EAD-42C6-B2EF-93F1FF2465F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PointManage", "应用\PointManage\PointManage.csproj", "{8ED1828E-52D2-448A-B586-537C9D45501B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TBRebate", "应用\TBRebate\TBRebate.csproj", "{32FB3BAC-447A-471F-9A2F-698CE9700002}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserFission", "应用\UserFission\UserFission.csproj", "{BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VideoFission", "应用\VideoFission\VideoFission.csproj", "{BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weixin.CircleTools", "应用\Weixin.CircleTools\Weixin.CircleTools.csproj", "{00191980-D031-4C7D-99AA-69B26C43D2C6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weixin.PDDCirclePromotion", "应用\Weixin.PDDCirclePromotion\Weixin.PDDCirclePromotion.csproj", "{E10D2202-D6D2-429B-8AA5-7586DF9605C1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weixin.TBCirclePromotion", "应用\Weixin.TBCirclePromotion\Weixin.TBCirclePromotion.csproj", "{5F4FC620-9101-4630-ADB5-77B7DC057CF9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FreeActivity", "应用\FreeActivity\FreeActivity.csproj", "{8BA5CF87-767F-4D7A-996D-76D0CC790610}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JDRebate", "应用\JDRebate\JDRebate.csproj", "{7BB4FC1F-DFB0-43B1-85B0-A343DB109843}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Messaging", "Messaging\Messaging.csproj", "{189BF68E-7359-4884-AD95-EE00BE836C47}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WeChatCollectMoney", "应用\WeChatCollectMoney\WeChatCollectMoney.csproj", "{1E721FBD-B9A3-4D52-92AA-428A8ACD726A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Miniblink", "..\DLL库\Miniblink\Miniblink.csproj", "{B20B797D-67FA-4A46-945E-59390D6C0A36}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FLSystemMonitor", "FLSystemMonitor\FLSystemMonitor.csproj", "{95406794-F388-41A2-9ABD-F056894A7D43}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Easy4net", "..\DLL库\Easy4net\Easy4net\Easy4net.csproj", "{C54A1140-3F51-450A-A813-B556679934A8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EncDebug", "EncDebug\EncDebug.csproj", "{10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReadWechat", "ReadWechat\ReadWechat.csproj", "{D946300F-CC08-4FBD-A18E-766F66FD7F1F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UI.Framework", "类库\UI.Framework\UI.Framework.csproj", "{F865D881-B9D2-4C90-9AD0-0667103827F6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartUP", "StartUP\StartUP.csproj", "{1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SignContacts", "应用\SignContacts\SignContacts.csproj", "{5407B027-5203-48B2-8191-A3FF43D57B16}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weixin.JDCirclePromotion", "应用\Weixin.JDCirclePromotion\Weixin.JDCirclePromotion.csproj", "{89E7BCC7-CDF2-433C-9848-327DA30FB281}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "socket.core", "C:\Users\秒单客\Desktop\软件图标\socket.core-master\socket.core\socket.core.csproj", "{CDBA3100-3794-4DFA-AE04-A1B84B9736FD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weixin.AccurateCircle", "应用\Weixin.AccurateCircle\Weixin.AccurateCircle.csproj", "{A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WechatPC", "WechatPC\WechatPC.csproj", "{6D7A46AF-67DA-4919-99DD-A933EA14ED27}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlSugar", "类库\SqlSugar\SqlSugar.csproj", "{489BB790-226C-4FAD-8D1E-51D72A7FF8E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CouponsSend", "应用\CouponsSend\CouponsSend.csproj", "{3D53BFC6-1C75-483A-BF7C-6B20F0152C66}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Delivery.Plugin", "应用\Delivery.Plugin\Delivery.Plugin.csproj", "{4311A2FD-1032-47CE-B627-FE527A962288}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductTool", "ProductTool\ProductTool.csproj", "{8CC5E981-FAAF-47C6-93C8-45986A077B9B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProductClient", "应用\ProductClient\ProductClient.csproj", "{B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Transmitter", "应用\Transmitter\Transmitter.csproj", "{ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}" +EndProject +Project("{911E67C6-3D85-4FCE-B560-20A9C3E3FF48}") = "WxRobot", "PCRobot\WxRobot.exe", "{31D3929C-175A-47E8-AD56-D6CB2B4CDF51}" + ProjectSection(DebuggerProjectSystem) = preProject + PortSupplier = 00000000-0000-0000-0000-000000000000 + Executable = D:\代码同步\fl_system\PCRobot\WxRobot.exe + RemoteMachine = PC-20131209OMEZ + StartingDirectory = D:\代码同步\fl_system\PCRobot + Environment = 默认值 + LaunchingEngine = 00000000-0000-0000-0000-000000000000 + UseLegacyDebugEngines = No + LaunchSQLEngine = No + AttachLaunchAction = No + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCRobot", "PCRobot\PCRobot.csproj", "{676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}" + ProjectSection(ProjectDependencies) = postProject + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC} = {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebTools", "应用\WebTools\WebTools.csproj", "{823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PCRobotFile", "PCRobotFile", "{116B0EB5-AF61-4B16-8942-667CF8989044}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCRobot.Pack", "PCRobot.Pack\PCRobot.Pack.csproj", "{C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebAPi", "应用\WebAPi\WebAPi.csproj", "{EDC2AC83-D4E3-4AFF-9690-9F631F224D21}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "循环的发消息", "应用\循环的发消息\循环的发消息.csproj", "{5BD19CCB-7D4E-4207-852D-3B630C57DF49}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EncourageUser", "应用\EncourageUser\EncourageUser.csproj", "{44593BAC-0617-483E-9AD7-BEF4336E14D7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "群成员监控", "应用\群成员监控\群成员监控.csproj", "{3EB20A81-87C6-4BFA-A66C-DDDB57806E09}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NewFans", "应用\NewFans\NewFans.csproj", "{1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WacheCheckUrl", "应用\WacheCheckUrl\WacheCheckUrl.csproj", "{CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Members", "Members\Members.csproj", "{649F9CBC-670C-4843-B835-5FF38D1F6B66}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FissionData", "应用\FissionData\FissionData.csproj", "{2DAF9579-77B2-44E2-B359-887D8FA01EE5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FissionSend", "应用\FissionSend\FissionSend.csproj", "{09AFCD48-2450-42A2-851C-A83F28474D80}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "监听违规", "应用\监听违规\监听违规.csproj", "{242E7FA6-3518-4E73-9899-0A309BF8410C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoomMembers", "应用\RoomMembers\RoomMembers.csproj", "{3CAA5D74-7533-49B5-A91F-169561CEEDAC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "同步老妖联盟上下级关系", "应用\同步老妖联盟上下级关系\同步老妖联盟上下级关系.csproj", "{534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GroupManager", "应用\GroupManager\GroupManager.csproj", "{DF4B1E13-144C-4419-B289-FCA08A68BC23}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPHRebate", "应用\WPHRebate\WPHRebate.csproj", "{2CB069FC-D25A-417E-837F-FAFDCEE639B2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weixin.WPHCirclePromotion", "应用\Weixin.WPHCirclePromotion\Weixin.WPHCirclePromotion.csproj", "{1E56F851-0341-4F86-8401-A8B3452F94EB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AllRebatesActivity", "应用\AllRebatesActivity\AllRebatesActivity.csproj", "{5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpHelper", "类库\HttpHelper2.1\HttpHelper.csproj", "{B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnlineRepair", "类库\OnlineRepair\OnlineRepair.csproj", "{0576158B-ACD4-4467-85A7-6055B278111E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DYRebate", "应用\DYRebate\DYRebate.csproj", "{6D011140-0E5F-4627-A010-529EFF6C9EFE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SelfFix", "SelfFix\SelfFix.csproj", "{B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SNRebate", "应用\SNRebate\SNRebate.csproj", "{6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "易转发自修复", "易转发自修复\易转发自修复.csproj", "{58FF110B-FDBC-4B53-B714-C3B171915616}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", "应用\QQ采集项目\QQ采集项目\Demo.csproj", "{955877A4-0126-4014-A7A8-40BCA9DD0B7E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Weixin.SNCirclePromotion", "应用\Weixin.SNCirclePromotion\Weixin.SNCirclePromotion.csproj", "{7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robot.Framework", "Coco.Framework\Robot.Framework.csproj", "{483D41CE-0A17-40C6-AF90-554794B2214E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KSRebate", "应用\KSRebate\KSRebate.csproj", "{BD719746-8782-4DA2-9469-75A03E02FAB9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSIMTurnMoney", "应用\CSIMTurnMoney\CSIMTurnMoney.csproj", "{91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|ARM.ActiveCfg = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|ARM.Build.0 = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|ARM64.Build.0 = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|x64.ActiveCfg = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|x64.Build.0 = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|x86.ActiveCfg = Debug|x86 + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|x86.Build.0 = Debug|x86 + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|Any CPU.Build.0 = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|ARM.ActiveCfg = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|ARM.Build.0 = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|ARM64.ActiveCfg = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|ARM64.Build.0 = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|x64.ActiveCfg = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|x64.Build.0 = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|x86.ActiveCfg = Release|x86 + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|x86.Build.0 = Release|x86 + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|ARM.ActiveCfg = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|ARM.Build.0 = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|ARM64.Build.0 = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|x64.ActiveCfg = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|x64.Build.0 = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|x86.ActiveCfg = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Debug|x86.Build.0 = Debug|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|Any CPU.Build.0 = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|ARM.ActiveCfg = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|ARM.Build.0 = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|ARM64.ActiveCfg = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|ARM64.Build.0 = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|x64.ActiveCfg = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|x64.Build.0 = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|x86.ActiveCfg = Release|Any CPU + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}.Release|x86.Build.0 = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|ARM.ActiveCfg = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|ARM.Build.0 = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|ARM64.Build.0 = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|x64.ActiveCfg = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|x64.Build.0 = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|x86.ActiveCfg = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Debug|x86.Build.0 = Debug|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|Any CPU.Build.0 = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|ARM.ActiveCfg = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|ARM.Build.0 = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|ARM64.ActiveCfg = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|ARM64.Build.0 = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|x64.ActiveCfg = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|x64.Build.0 = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|x86.ActiveCfg = Release|Any CPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95}.Release|x86.Build.0 = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|ARM.ActiveCfg = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|ARM.Build.0 = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|ARM64.Build.0 = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|x64.ActiveCfg = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|x64.Build.0 = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|x86.ActiveCfg = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Debug|x86.Build.0 = Debug|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|Any CPU.Build.0 = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|ARM.ActiveCfg = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|ARM.Build.0 = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|ARM64.ActiveCfg = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|ARM64.Build.0 = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|x64.ActiveCfg = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|x64.Build.0 = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|x86.ActiveCfg = Release|Any CPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758}.Release|x86.Build.0 = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|ARM.ActiveCfg = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|ARM.Build.0 = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|ARM64.Build.0 = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|x64.ActiveCfg = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|x64.Build.0 = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|x86.ActiveCfg = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Debug|x86.Build.0 = Debug|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|Any CPU.Build.0 = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|ARM.ActiveCfg = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|ARM.Build.0 = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|ARM64.ActiveCfg = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|ARM64.Build.0 = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|x64.ActiveCfg = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|x64.Build.0 = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|x86.ActiveCfg = Release|Any CPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA}.Release|x86.Build.0 = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|ARM.ActiveCfg = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|ARM.Build.0 = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|ARM64.Build.0 = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|x64.ActiveCfg = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|x64.Build.0 = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|x86.ActiveCfg = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Debug|x86.Build.0 = Debug|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|Any CPU.Build.0 = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|ARM.ActiveCfg = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|ARM.Build.0 = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|ARM64.ActiveCfg = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|ARM64.Build.0 = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|x64.ActiveCfg = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|x64.Build.0 = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|x86.ActiveCfg = Release|Any CPU + {35A30202-1D63-413A-AD12-8FFB24165B43}.Release|x86.Build.0 = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|ARM.ActiveCfg = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|ARM.Build.0 = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|ARM64.Build.0 = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|x64.ActiveCfg = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|x64.Build.0 = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|x86.ActiveCfg = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Debug|x86.Build.0 = Debug|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|Any CPU.Build.0 = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|ARM.ActiveCfg = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|ARM.Build.0 = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|ARM64.ActiveCfg = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|ARM64.Build.0 = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|x64.ActiveCfg = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|x64.Build.0 = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|x86.ActiveCfg = Release|Any CPU + {91A026DE-527F-4897-A1DC-01775E1CDD03}.Release|x86.Build.0 = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|ARM.Build.0 = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|ARM64.Build.0 = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|x64.ActiveCfg = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|x64.Build.0 = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|x86.ActiveCfg = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Debug|x86.Build.0 = Debug|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|Any CPU.Build.0 = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|ARM.ActiveCfg = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|ARM.Build.0 = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|ARM64.ActiveCfg = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|ARM64.Build.0 = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|x64.ActiveCfg = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|x64.Build.0 = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|x86.ActiveCfg = Release|Any CPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33}.Release|x86.Build.0 = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|ARM.ActiveCfg = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|ARM.Build.0 = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|ARM64.Build.0 = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|x64.ActiveCfg = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|x64.Build.0 = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|x86.ActiveCfg = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Debug|x86.Build.0 = Debug|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|Any CPU.Build.0 = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|ARM.ActiveCfg = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|ARM.Build.0 = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|ARM64.ActiveCfg = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|ARM64.Build.0 = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|x64.ActiveCfg = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|x64.Build.0 = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|x86.ActiveCfg = Release|Any CPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1}.Release|x86.Build.0 = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|ARM.ActiveCfg = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|ARM.Build.0 = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|ARM64.Build.0 = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|x64.ActiveCfg = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|x64.Build.0 = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|x86.ActiveCfg = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Debug|x86.Build.0 = Debug|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|Any CPU.Build.0 = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|ARM.ActiveCfg = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|ARM.Build.0 = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|ARM64.ActiveCfg = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|ARM64.Build.0 = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|x64.ActiveCfg = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|x64.Build.0 = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|x86.ActiveCfg = Release|Any CPU + {8ED1828E-52D2-448A-B586-537C9D45501B}.Release|x86.Build.0 = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|ARM.ActiveCfg = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|ARM.Build.0 = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|ARM64.Build.0 = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|x64.ActiveCfg = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|x64.Build.0 = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|x86.ActiveCfg = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Debug|x86.Build.0 = Debug|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|Any CPU.Build.0 = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|ARM.ActiveCfg = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|ARM.Build.0 = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|ARM64.ActiveCfg = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|ARM64.Build.0 = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|x64.ActiveCfg = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|x64.Build.0 = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|x86.ActiveCfg = Release|Any CPU + {32FB3BAC-447A-471F-9A2F-698CE9700002}.Release|x86.Build.0 = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|ARM.ActiveCfg = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|ARM.Build.0 = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|ARM64.Build.0 = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|x64.ActiveCfg = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|x64.Build.0 = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|x86.ActiveCfg = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Debug|x86.Build.0 = Debug|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|Any CPU.Build.0 = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|ARM.ActiveCfg = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|ARM.Build.0 = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|ARM64.ActiveCfg = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|ARM64.Build.0 = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|x64.ActiveCfg = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|x64.Build.0 = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|x86.ActiveCfg = Release|Any CPU + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}.Release|x86.Build.0 = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|ARM.ActiveCfg = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|ARM.Build.0 = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|ARM64.Build.0 = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|x64.ActiveCfg = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|x64.Build.0 = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|x86.ActiveCfg = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Debug|x86.Build.0 = Debug|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|Any CPU.Build.0 = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|ARM.ActiveCfg = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|ARM.Build.0 = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|ARM64.ActiveCfg = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|ARM64.Build.0 = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|x64.ActiveCfg = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|x64.Build.0 = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|x86.ActiveCfg = Release|Any CPU + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}.Release|x86.Build.0 = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|ARM.Build.0 = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|ARM64.Build.0 = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|x64.ActiveCfg = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|x64.Build.0 = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|x86.ActiveCfg = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Debug|x86.Build.0 = Debug|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|Any CPU.Build.0 = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|ARM.ActiveCfg = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|ARM.Build.0 = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|ARM64.ActiveCfg = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|ARM64.Build.0 = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|x64.ActiveCfg = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|x64.Build.0 = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|x86.ActiveCfg = Release|Any CPU + {00191980-D031-4C7D-99AA-69B26C43D2C6}.Release|x86.Build.0 = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|ARM.ActiveCfg = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|ARM.Build.0 = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|ARM64.Build.0 = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|x64.ActiveCfg = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|x64.Build.0 = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|x86.ActiveCfg = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Debug|x86.Build.0 = Debug|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|Any CPU.Build.0 = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|ARM.ActiveCfg = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|ARM.Build.0 = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|ARM64.ActiveCfg = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|ARM64.Build.0 = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|x64.ActiveCfg = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|x64.Build.0 = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|x86.ActiveCfg = Release|Any CPU + {E10D2202-D6D2-429B-8AA5-7586DF9605C1}.Release|x86.Build.0 = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|ARM.ActiveCfg = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|ARM.Build.0 = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|ARM64.Build.0 = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|x64.ActiveCfg = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|x64.Build.0 = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|x86.ActiveCfg = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Debug|x86.Build.0 = Debug|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|Any CPU.Build.0 = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|ARM.ActiveCfg = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|ARM.Build.0 = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|ARM64.ActiveCfg = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|ARM64.Build.0 = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|x64.ActiveCfg = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|x64.Build.0 = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|x86.ActiveCfg = Release|Any CPU + {5F4FC620-9101-4630-ADB5-77B7DC057CF9}.Release|x86.Build.0 = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|ARM.ActiveCfg = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|ARM.Build.0 = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|ARM64.Build.0 = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|x64.ActiveCfg = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|x64.Build.0 = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|x86.ActiveCfg = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Debug|x86.Build.0 = Debug|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|Any CPU.Build.0 = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|ARM.ActiveCfg = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|ARM.Build.0 = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|ARM64.ActiveCfg = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|ARM64.Build.0 = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|x64.ActiveCfg = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|x64.Build.0 = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|x86.ActiveCfg = Release|Any CPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610}.Release|x86.Build.0 = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|ARM.ActiveCfg = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|ARM.Build.0 = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|ARM64.Build.0 = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|x64.ActiveCfg = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|x64.Build.0 = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|x86.ActiveCfg = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Debug|x86.Build.0 = Debug|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|Any CPU.Build.0 = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|ARM.ActiveCfg = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|ARM.Build.0 = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|ARM64.ActiveCfg = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|ARM64.Build.0 = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|x64.ActiveCfg = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|x64.Build.0 = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|x86.ActiveCfg = Release|Any CPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843}.Release|x86.Build.0 = Release|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Debug|Any CPU.Build.0 = Debug|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Debug|ARM.ActiveCfg = Debug|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Debug|x64.ActiveCfg = Debug|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Debug|x86.ActiveCfg = Debug|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Debug|x86.Build.0 = Debug|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Release|Any CPU.ActiveCfg = Release|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Release|Any CPU.Build.0 = Release|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Release|ARM.ActiveCfg = Release|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Release|ARM64.ActiveCfg = Release|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Release|x64.ActiveCfg = Release|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Release|x86.ActiveCfg = Release|Any CPU + {189BF68E-7359-4884-AD95-EE00BE836C47}.Release|x86.Build.0 = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|ARM.Build.0 = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|ARM64.Build.0 = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|x64.ActiveCfg = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|x64.Build.0 = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|x86.ActiveCfg = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Debug|x86.Build.0 = Debug|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|Any CPU.Build.0 = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|ARM.ActiveCfg = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|ARM.Build.0 = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|ARM64.ActiveCfg = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|ARM64.Build.0 = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|x64.ActiveCfg = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|x64.Build.0 = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|x86.ActiveCfg = Release|Any CPU + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A}.Release|x86.Build.0 = Release|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Debug|ARM.ActiveCfg = Debug|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Debug|x64.ActiveCfg = Debug|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Debug|x86.ActiveCfg = Debug|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Debug|x86.Build.0 = Debug|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Release|Any CPU.Build.0 = Release|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Release|ARM.ActiveCfg = Release|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Release|ARM64.ActiveCfg = Release|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Release|x64.ActiveCfg = Release|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Release|x86.ActiveCfg = Release|Any CPU + {B20B797D-67FA-4A46-945E-59390D6C0A36}.Release|x86.Build.0 = Release|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Debug|ARM.ActiveCfg = Debug|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Debug|x64.ActiveCfg = Debug|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Debug|x86.ActiveCfg = Debug|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Debug|x86.Build.0 = Debug|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Release|Any CPU.Build.0 = Release|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Release|ARM.ActiveCfg = Release|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Release|ARM64.ActiveCfg = Release|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Release|x64.ActiveCfg = Release|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Release|x86.ActiveCfg = Release|Any CPU + {95406794-F388-41A2-9ABD-F056894A7D43}.Release|x86.Build.0 = Release|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Debug|x64.ActiveCfg = Debug|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Debug|x86.ActiveCfg = Debug|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Debug|x86.Build.0 = Debug|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Release|Any CPU.Build.0 = Release|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Release|ARM.ActiveCfg = Release|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Release|ARM64.ActiveCfg = Release|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Release|x64.ActiveCfg = Release|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Release|x86.ActiveCfg = Release|Any CPU + {C54A1140-3F51-450A-A813-B556679934A8}.Release|x86.Build.0 = Release|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Debug|x64.ActiveCfg = Debug|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Debug|x86.ActiveCfg = Debug|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Debug|x86.Build.0 = Debug|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Release|Any CPU.Build.0 = Release|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Release|ARM.ActiveCfg = Release|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Release|ARM64.ActiveCfg = Release|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Release|x64.ActiveCfg = Release|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Release|x86.ActiveCfg = Release|Any CPU + {10BD6B4C-1C99-4266-8B3F-5B3EDE218D3A}.Release|x86.Build.0 = Release|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Debug|ARM.ActiveCfg = Debug|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Debug|x64.ActiveCfg = Debug|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Debug|x86.ActiveCfg = Debug|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Debug|x86.Build.0 = Debug|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Release|Any CPU.Build.0 = Release|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Release|ARM.ActiveCfg = Release|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Release|ARM64.ActiveCfg = Release|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Release|x64.ActiveCfg = Release|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Release|x86.ActiveCfg = Release|Any CPU + {D946300F-CC08-4FBD-A18E-766F66FD7F1F}.Release|x86.Build.0 = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|ARM.Build.0 = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|ARM64.Build.0 = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|x64.ActiveCfg = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|x64.Build.0 = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|x86.ActiveCfg = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Debug|x86.Build.0 = Debug|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|Any CPU.Build.0 = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|ARM.ActiveCfg = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|ARM.Build.0 = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|ARM64.ActiveCfg = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|ARM64.Build.0 = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|x64.ActiveCfg = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|x64.Build.0 = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|x86.ActiveCfg = Release|Any CPU + {F865D881-B9D2-4C90-9AD0-0667103827F6}.Release|x86.Build.0 = Release|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Debug|ARM.ActiveCfg = Debug|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Debug|x64.ActiveCfg = Debug|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Debug|x86.ActiveCfg = Debug|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Debug|x86.Build.0 = Debug|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Release|Any CPU.Build.0 = Release|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Release|ARM.ActiveCfg = Release|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Release|ARM64.ActiveCfg = Release|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Release|x64.ActiveCfg = Release|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Release|x86.ActiveCfg = Release|Any CPU + {1C8DA3FE-0A59-4D9B-A32B-AA2CD16586F2}.Release|x86.Build.0 = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|ARM.ActiveCfg = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|ARM.Build.0 = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|ARM64.Build.0 = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|x64.ActiveCfg = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|x64.Build.0 = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|x86.ActiveCfg = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Debug|x86.Build.0 = Debug|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|Any CPU.Build.0 = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|ARM.ActiveCfg = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|ARM.Build.0 = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|ARM64.ActiveCfg = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|ARM64.Build.0 = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|x64.ActiveCfg = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|x64.Build.0 = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|x86.ActiveCfg = Release|Any CPU + {5407B027-5203-48B2-8191-A3FF43D57B16}.Release|x86.Build.0 = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|ARM.ActiveCfg = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|ARM.Build.0 = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|ARM64.Build.0 = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|x64.ActiveCfg = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|x64.Build.0 = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|x86.ActiveCfg = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Debug|x86.Build.0 = Debug|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|Any CPU.Build.0 = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|ARM.ActiveCfg = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|ARM.Build.0 = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|ARM64.ActiveCfg = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|ARM64.Build.0 = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|x64.ActiveCfg = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|x64.Build.0 = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|x86.ActiveCfg = Release|Any CPU + {89E7BCC7-CDF2-433C-9848-327DA30FB281}.Release|x86.Build.0 = Release|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Debug|ARM.ActiveCfg = Debug|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Debug|x64.ActiveCfg = Debug|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Debug|x86.ActiveCfg = Debug|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Debug|x86.Build.0 = Debug|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Release|Any CPU.Build.0 = Release|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Release|ARM.ActiveCfg = Release|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Release|ARM64.ActiveCfg = Release|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Release|x64.ActiveCfg = Release|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Release|x86.ActiveCfg = Release|Any CPU + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD}.Release|x86.Build.0 = Release|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Debug|ARM.ActiveCfg = Debug|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Debug|x64.ActiveCfg = Debug|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Debug|x86.ActiveCfg = Debug|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Debug|x86.Build.0 = Debug|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Release|Any CPU.Build.0 = Release|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Release|ARM.ActiveCfg = Release|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Release|ARM64.ActiveCfg = Release|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Release|x64.ActiveCfg = Release|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Release|x86.ActiveCfg = Release|Any CPU + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4}.Release|x86.Build.0 = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|ARM.ActiveCfg = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|ARM.Build.0 = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|ARM64.Build.0 = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|x64.ActiveCfg = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|x64.Build.0 = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|x86.ActiveCfg = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Debug|x86.Build.0 = Debug|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|Any CPU.Build.0 = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|ARM.ActiveCfg = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|ARM.Build.0 = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|ARM64.ActiveCfg = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|ARM64.Build.0 = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|x64.ActiveCfg = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|x64.Build.0 = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|x86.ActiveCfg = Release|Any CPU + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}.Release|x86.Build.0 = Release|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Debug|x64.ActiveCfg = Debug|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Debug|x86.ActiveCfg = Debug|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Debug|x86.Build.0 = Debug|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Release|Any CPU.Build.0 = Release|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Release|ARM.ActiveCfg = Release|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Release|ARM64.ActiveCfg = Release|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Release|x64.ActiveCfg = Release|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Release|x86.ActiveCfg = Release|Any CPU + {6D7A46AF-67DA-4919-99DD-A933EA14ED27}.Release|x86.Build.0 = Release|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Debug|ARM.ActiveCfg = Debug|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Debug|x64.ActiveCfg = Debug|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Debug|x86.ActiveCfg = Debug|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Debug|x86.Build.0 = Debug|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Release|Any CPU.Build.0 = Release|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Release|ARM.ActiveCfg = Release|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Release|ARM64.ActiveCfg = Release|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Release|x64.ActiveCfg = Release|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Release|x86.ActiveCfg = Release|Any CPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5}.Release|x86.Build.0 = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|ARM.Build.0 = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|ARM64.Build.0 = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|x64.ActiveCfg = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|x64.Build.0 = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|x86.ActiveCfg = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Debug|x86.Build.0 = Debug|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|Any CPU.Build.0 = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|ARM.ActiveCfg = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|ARM.Build.0 = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|ARM64.ActiveCfg = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|ARM64.Build.0 = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|x64.ActiveCfg = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|x64.Build.0 = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|x86.ActiveCfg = Release|Any CPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66}.Release|x86.Build.0 = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|ARM.ActiveCfg = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|ARM.Build.0 = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|ARM64.Build.0 = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|x64.ActiveCfg = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|x64.Build.0 = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|x86.ActiveCfg = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Debug|x86.Build.0 = Debug|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|Any CPU.Build.0 = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|ARM.ActiveCfg = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|ARM.Build.0 = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|ARM64.ActiveCfg = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|ARM64.Build.0 = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|x64.ActiveCfg = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|x64.Build.0 = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|x86.ActiveCfg = Release|Any CPU + {4311A2FD-1032-47CE-B627-FE527A962288}.Release|x86.Build.0 = Release|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Debug|ARM.ActiveCfg = Debug|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Debug|x64.ActiveCfg = Debug|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Debug|x86.ActiveCfg = Debug|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Debug|x86.Build.0 = Debug|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Release|Any CPU.Build.0 = Release|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Release|ARM.ActiveCfg = Release|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Release|ARM64.ActiveCfg = Release|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Release|x64.ActiveCfg = Release|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Release|x86.ActiveCfg = Release|Any CPU + {8CC5E981-FAAF-47C6-93C8-45986A077B9B}.Release|x86.Build.0 = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|ARM.ActiveCfg = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|ARM.Build.0 = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|ARM64.Build.0 = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|x64.ActiveCfg = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|x64.Build.0 = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|x86.ActiveCfg = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Debug|x86.Build.0 = Debug|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|Any CPU.Build.0 = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|ARM.ActiveCfg = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|ARM.Build.0 = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|ARM64.ActiveCfg = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|ARM64.Build.0 = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|x64.ActiveCfg = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|x64.Build.0 = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|x86.ActiveCfg = Release|Any CPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C}.Release|x86.Build.0 = Release|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Debug|ARM.ActiveCfg = Debug|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Debug|x64.ActiveCfg = Debug|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Debug|x86.ActiveCfg = Debug|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Debug|x86.Build.0 = Debug|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Release|Any CPU.Build.0 = Release|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Release|ARM.ActiveCfg = Release|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Release|ARM64.ActiveCfg = Release|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Release|x64.ActiveCfg = Release|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Release|x86.ActiveCfg = Release|Any CPU + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC}.Release|x86.Build.0 = Release|Any CPU + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Debug|Any CPU.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Debug|ARM.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Debug|ARM64.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Debug|x64.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Debug|x86.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Release|Any CPU.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Release|ARM.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Release|ARM64.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Release|x64.ActiveCfg = Release + {31D3929C-175A-47E8-AD56-D6CB2B4CDF51}.Release|x86.ActiveCfg = Release + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|ARM.ActiveCfg = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|ARM.Build.0 = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|ARM64.Build.0 = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|x64.ActiveCfg = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|x64.Build.0 = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|x86.ActiveCfg = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|x86.Build.0 = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|Any CPU.Build.0 = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|ARM.ActiveCfg = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|ARM.Build.0 = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|ARM64.ActiveCfg = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|ARM64.Build.0 = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|x64.ActiveCfg = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|x64.Build.0 = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|x86.ActiveCfg = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|x86.Build.0 = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|ARM.ActiveCfg = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|ARM.Build.0 = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|ARM64.Build.0 = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|x64.ActiveCfg = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|x64.Build.0 = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|x86.ActiveCfg = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Debug|x86.Build.0 = Debug|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|Any CPU.Build.0 = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|ARM.ActiveCfg = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|ARM.Build.0 = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|ARM64.ActiveCfg = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|ARM64.Build.0 = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|x64.ActiveCfg = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|x64.Build.0 = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|x86.ActiveCfg = Release|Any CPU + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}.Release|x86.Build.0 = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|ARM.Build.0 = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|ARM64.Build.0 = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|x64.ActiveCfg = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|x64.Build.0 = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|x86.ActiveCfg = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|x86.Build.0 = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|Any CPU.Build.0 = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|ARM.ActiveCfg = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|ARM.Build.0 = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|ARM64.ActiveCfg = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|ARM64.Build.0 = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|x64.ActiveCfg = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|x64.Build.0 = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|x86.ActiveCfg = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|x86.Build.0 = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|ARM.ActiveCfg = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|ARM.Build.0 = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|ARM64.Build.0 = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|x64.ActiveCfg = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|x64.Build.0 = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|x86.ActiveCfg = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Debug|x86.Build.0 = Debug|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|Any CPU.Build.0 = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|ARM.ActiveCfg = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|ARM.Build.0 = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|ARM64.ActiveCfg = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|ARM64.Build.0 = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|x64.ActiveCfg = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|x64.Build.0 = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|x86.ActiveCfg = Release|Any CPU + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21}.Release|x86.Build.0 = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|ARM.ActiveCfg = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|ARM.Build.0 = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|ARM64.Build.0 = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|x64.ActiveCfg = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|x64.Build.0 = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|x86.ActiveCfg = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Debug|x86.Build.0 = Debug|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|Any CPU.Build.0 = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|ARM.ActiveCfg = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|ARM.Build.0 = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|ARM64.ActiveCfg = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|ARM64.Build.0 = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|x64.ActiveCfg = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|x64.Build.0 = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|x86.ActiveCfg = Release|Any CPU + {5BD19CCB-7D4E-4207-852D-3B630C57DF49}.Release|x86.Build.0 = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|ARM.ActiveCfg = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|ARM.Build.0 = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|ARM64.Build.0 = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|x64.ActiveCfg = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|x64.Build.0 = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|x86.ActiveCfg = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Debug|x86.Build.0 = Debug|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|Any CPU.Build.0 = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|ARM.ActiveCfg = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|ARM.Build.0 = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|ARM64.ActiveCfg = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|ARM64.Build.0 = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|x64.ActiveCfg = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|x64.Build.0 = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|x86.ActiveCfg = Release|Any CPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7}.Release|x86.Build.0 = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|ARM.Build.0 = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|ARM64.Build.0 = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|x64.ActiveCfg = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|x64.Build.0 = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|x86.ActiveCfg = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Debug|x86.Build.0 = Debug|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|Any CPU.Build.0 = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|ARM.ActiveCfg = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|ARM.Build.0 = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|ARM64.ActiveCfg = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|ARM64.Build.0 = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|x64.ActiveCfg = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|x64.Build.0 = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|x86.ActiveCfg = Release|Any CPU + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09}.Release|x86.Build.0 = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|ARM.ActiveCfg = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|ARM.Build.0 = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|ARM64.Build.0 = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|x64.ActiveCfg = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|x64.Build.0 = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|x86.ActiveCfg = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Debug|x86.Build.0 = Debug|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|Any CPU.Build.0 = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|ARM.ActiveCfg = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|ARM.Build.0 = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|ARM64.ActiveCfg = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|ARM64.Build.0 = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|x64.ActiveCfg = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|x64.Build.0 = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|x86.ActiveCfg = Release|Any CPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B}.Release|x86.Build.0 = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|ARM.ActiveCfg = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|ARM.Build.0 = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|ARM64.Build.0 = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|x64.ActiveCfg = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|x64.Build.0 = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|x86.ActiveCfg = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Debug|x86.Build.0 = Debug|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|Any CPU.Build.0 = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|ARM.ActiveCfg = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|ARM.Build.0 = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|ARM64.ActiveCfg = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|ARM64.Build.0 = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|x64.ActiveCfg = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|x64.Build.0 = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|x86.ActiveCfg = Release|Any CPU + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}.Release|x86.Build.0 = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|ARM.ActiveCfg = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|ARM.Build.0 = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|ARM64.Build.0 = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|x64.ActiveCfg = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|x64.Build.0 = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|x86.ActiveCfg = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Debug|x86.Build.0 = Debug|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|Any CPU.Build.0 = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|ARM.ActiveCfg = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|ARM.Build.0 = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|ARM64.ActiveCfg = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|ARM64.Build.0 = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|x64.ActiveCfg = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|x64.Build.0 = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|x86.ActiveCfg = Release|Any CPU + {649F9CBC-670C-4843-B835-5FF38D1F6B66}.Release|x86.Build.0 = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|ARM.ActiveCfg = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|ARM.Build.0 = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|ARM64.Build.0 = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|x64.ActiveCfg = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|x64.Build.0 = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|x86.ActiveCfg = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Debug|x86.Build.0 = Debug|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|Any CPU.Build.0 = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|ARM.ActiveCfg = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|ARM.Build.0 = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|ARM64.ActiveCfg = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|ARM64.Build.0 = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|x64.ActiveCfg = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|x64.Build.0 = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|x86.ActiveCfg = Release|Any CPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5}.Release|x86.Build.0 = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|ARM.ActiveCfg = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|ARM.Build.0 = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|ARM64.Build.0 = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|x64.ActiveCfg = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|x64.Build.0 = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|x86.ActiveCfg = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Debug|x86.Build.0 = Debug|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|Any CPU.Build.0 = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|ARM.ActiveCfg = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|ARM.Build.0 = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|ARM64.ActiveCfg = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|ARM64.Build.0 = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|x64.ActiveCfg = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|x64.Build.0 = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|x86.ActiveCfg = Release|Any CPU + {09AFCD48-2450-42A2-851C-A83F28474D80}.Release|x86.Build.0 = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|ARM.ActiveCfg = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|ARM.Build.0 = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|ARM64.Build.0 = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|x64.ActiveCfg = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|x64.Build.0 = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|x86.ActiveCfg = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Debug|x86.Build.0 = Debug|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|Any CPU.Build.0 = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|ARM.ActiveCfg = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|ARM.Build.0 = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|ARM64.ActiveCfg = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|ARM64.Build.0 = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|x64.ActiveCfg = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|x64.Build.0 = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|x86.ActiveCfg = Release|Any CPU + {242E7FA6-3518-4E73-9899-0A309BF8410C}.Release|x86.Build.0 = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|ARM.ActiveCfg = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|ARM.Build.0 = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|ARM64.Build.0 = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|x64.ActiveCfg = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|x64.Build.0 = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|x86.ActiveCfg = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Debug|x86.Build.0 = Debug|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|Any CPU.Build.0 = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|ARM.ActiveCfg = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|ARM.Build.0 = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|ARM64.ActiveCfg = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|ARM64.Build.0 = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|x64.ActiveCfg = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|x64.Build.0 = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|x86.ActiveCfg = Release|Any CPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC}.Release|x86.Build.0 = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|ARM.ActiveCfg = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|ARM.Build.0 = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|ARM64.Build.0 = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|x64.ActiveCfg = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|x64.Build.0 = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|x86.ActiveCfg = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Debug|x86.Build.0 = Debug|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|Any CPU.Build.0 = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|ARM.ActiveCfg = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|ARM.Build.0 = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|ARM64.ActiveCfg = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|ARM64.Build.0 = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|x64.ActiveCfg = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|x64.Build.0 = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|x86.ActiveCfg = Release|Any CPU + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}.Release|x86.Build.0 = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|ARM.ActiveCfg = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|ARM.Build.0 = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|ARM64.Build.0 = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|x64.ActiveCfg = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|x64.Build.0 = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|x86.ActiveCfg = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Debug|x86.Build.0 = Debug|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|Any CPU.Build.0 = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|ARM.ActiveCfg = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|ARM.Build.0 = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|ARM64.ActiveCfg = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|ARM64.Build.0 = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|x64.ActiveCfg = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|x64.Build.0 = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|x86.ActiveCfg = Release|Any CPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23}.Release|x86.Build.0 = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|ARM.ActiveCfg = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|ARM.Build.0 = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|ARM64.Build.0 = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|x64.ActiveCfg = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|x64.Build.0 = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|x86.ActiveCfg = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Debug|x86.Build.0 = Debug|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|Any CPU.Build.0 = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|ARM.ActiveCfg = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|ARM.Build.0 = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|ARM64.ActiveCfg = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|ARM64.Build.0 = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|x64.ActiveCfg = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|x64.Build.0 = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|x86.ActiveCfg = Release|Any CPU + {2CB069FC-D25A-417E-837F-FAFDCEE639B2}.Release|x86.Build.0 = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|ARM.ActiveCfg = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|ARM.Build.0 = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|ARM64.Build.0 = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|x64.ActiveCfg = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|x64.Build.0 = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|x86.ActiveCfg = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Debug|x86.Build.0 = Debug|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|Any CPU.Build.0 = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|ARM.ActiveCfg = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|ARM.Build.0 = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|ARM64.ActiveCfg = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|ARM64.Build.0 = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|x64.ActiveCfg = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|x64.Build.0 = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|x86.ActiveCfg = Release|Any CPU + {1E56F851-0341-4F86-8401-A8B3452F94EB}.Release|x86.Build.0 = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|ARM.ActiveCfg = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|ARM.Build.0 = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|ARM64.Build.0 = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|x64.ActiveCfg = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|x64.Build.0 = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|x86.ActiveCfg = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Debug|x86.Build.0 = Debug|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|Any CPU.Build.0 = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|ARM.ActiveCfg = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|ARM.Build.0 = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|ARM64.ActiveCfg = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|ARM64.Build.0 = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|x64.ActiveCfg = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|x64.Build.0 = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|x86.ActiveCfg = Release|Any CPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5}.Release|x86.Build.0 = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|ARM.ActiveCfg = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|ARM.Build.0 = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|ARM64.Build.0 = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|x64.ActiveCfg = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|x64.Build.0 = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|x86.ActiveCfg = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|x86.Build.0 = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|Any CPU.Build.0 = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|ARM.ActiveCfg = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|ARM.Build.0 = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|ARM64.ActiveCfg = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|ARM64.Build.0 = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|x64.ActiveCfg = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|x64.Build.0 = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|x86.ActiveCfg = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|x86.Build.0 = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|ARM.Build.0 = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|ARM64.Build.0 = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|x64.ActiveCfg = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|x64.Build.0 = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|x86.ActiveCfg = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Debug|x86.Build.0 = Debug|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|Any CPU.Build.0 = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|ARM.ActiveCfg = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|ARM.Build.0 = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|ARM64.ActiveCfg = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|ARM64.Build.0 = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|x64.ActiveCfg = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|x64.Build.0 = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|x86.ActiveCfg = Release|Any CPU + {0576158B-ACD4-4467-85A7-6055B278111E}.Release|x86.Build.0 = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|ARM.Build.0 = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|ARM64.Build.0 = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|x64.ActiveCfg = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|x64.Build.0 = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|x86.ActiveCfg = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Debug|x86.Build.0 = Debug|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|Any CPU.Build.0 = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|ARM.ActiveCfg = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|ARM.Build.0 = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|ARM64.ActiveCfg = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|ARM64.Build.0 = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|x64.ActiveCfg = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|x64.Build.0 = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|x86.ActiveCfg = Release|Any CPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE}.Release|x86.Build.0 = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|ARM.ActiveCfg = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|ARM.Build.0 = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|ARM64.Build.0 = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|x64.ActiveCfg = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|x64.Build.0 = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|x86.ActiveCfg = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Debug|x86.Build.0 = Debug|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|Any CPU.Build.0 = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|ARM.ActiveCfg = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|ARM.Build.0 = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|ARM64.ActiveCfg = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|ARM64.Build.0 = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|x64.ActiveCfg = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|x64.Build.0 = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|x86.ActiveCfg = Release|Any CPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5}.Release|x86.Build.0 = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|ARM.Build.0 = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|ARM64.Build.0 = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|x64.ActiveCfg = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|x64.Build.0 = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|x86.ActiveCfg = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Debug|x86.Build.0 = Debug|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|Any CPU.Build.0 = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|ARM.ActiveCfg = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|ARM.Build.0 = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|ARM64.ActiveCfg = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|ARM64.Build.0 = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|x64.ActiveCfg = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|x64.Build.0 = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|x86.ActiveCfg = Release|Any CPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B}.Release|x86.Build.0 = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|ARM.ActiveCfg = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|ARM.Build.0 = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|ARM64.Build.0 = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|x64.ActiveCfg = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|x64.Build.0 = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|x86.ActiveCfg = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Debug|x86.Build.0 = Debug|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|Any CPU.Build.0 = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|ARM.ActiveCfg = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|ARM.Build.0 = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|ARM64.ActiveCfg = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|ARM64.Build.0 = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|x64.ActiveCfg = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|x64.Build.0 = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|x86.ActiveCfg = Release|Any CPU + {58FF110B-FDBC-4B53-B714-C3B171915616}.Release|x86.Build.0 = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|ARM.Build.0 = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|ARM64.Build.0 = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|x64.ActiveCfg = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|x64.Build.0 = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|x86.ActiveCfg = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|x86.Build.0 = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|Any CPU.Build.0 = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|ARM.ActiveCfg = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|ARM.Build.0 = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|ARM64.ActiveCfg = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|ARM64.Build.0 = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|x64.ActiveCfg = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|x64.Build.0 = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|x86.ActiveCfg = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|x86.Build.0 = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|ARM.ActiveCfg = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|ARM.Build.0 = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|ARM64.Build.0 = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|x64.ActiveCfg = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|x64.Build.0 = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|x86.ActiveCfg = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Debug|x86.Build.0 = Debug|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|Any CPU.Build.0 = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|ARM.ActiveCfg = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|ARM.Build.0 = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|ARM64.ActiveCfg = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|ARM64.Build.0 = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|x64.ActiveCfg = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|x64.Build.0 = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|x86.ActiveCfg = Release|Any CPU + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}.Release|x86.Build.0 = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|ARM.ActiveCfg = Debug|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|ARM.Build.0 = Debug|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|ARM64.Build.0 = Debug|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|x64.ActiveCfg = Debug|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|x64.Build.0 = Debug|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|x86.ActiveCfg = Debug|x86 + {483D41CE-0A17-40C6-AF90-554794B2214E}.Debug|x86.Build.0 = Debug|x86 + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|Any CPU.Build.0 = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|ARM.ActiveCfg = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|ARM.Build.0 = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|ARM64.ActiveCfg = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|ARM64.Build.0 = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|x64.ActiveCfg = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|x64.Build.0 = Release|Any CPU + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|x86.ActiveCfg = Release|x86 + {483D41CE-0A17-40C6-AF90-554794B2214E}.Release|x86.Build.0 = Release|x86 + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|ARM.ActiveCfg = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|ARM.Build.0 = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|ARM64.Build.0 = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|x64.ActiveCfg = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|x64.Build.0 = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|x86.ActiveCfg = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Debug|x86.Build.0 = Debug|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|Any CPU.Build.0 = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|ARM.ActiveCfg = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|ARM.Build.0 = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|ARM64.ActiveCfg = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|ARM64.Build.0 = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|x64.ActiveCfg = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|x64.Build.0 = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|x86.ActiveCfg = Release|Any CPU + {BD719746-8782-4DA2-9469-75A03E02FAB9}.Release|x86.Build.0 = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|ARM.ActiveCfg = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|ARM.Build.0 = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|ARM64.Build.0 = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|x64.ActiveCfg = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|x64.Build.0 = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|x86.ActiveCfg = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Debug|x86.Build.0 = Debug|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|Any CPU.Build.0 = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|ARM.ActiveCfg = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|ARM.Build.0 = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|ARM64.ActiveCfg = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|ARM64.Build.0 = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|x64.ActiveCfg = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|x64.Build.0 = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|x86.ActiveCfg = Release|Any CPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {08421940-859B-4E93-B8D5-C4BEF64B0A95} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {2916C951-8BF2-4941-BF8D-EBC1E1A73758} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {E5A7E5DB-EB35-4542-BD69-22E263691CAA} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {35A30202-1D63-413A-AD12-8FFB24165B43} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {91A026DE-527F-4897-A1DC-01775E1CDD03} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {8ED1828E-52D2-448A-B586-537C9D45501B} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {32FB3BAC-447A-471F-9A2F-698CE9700002} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {00191980-D031-4C7D-99AA-69B26C43D2C6} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {E10D2202-D6D2-429B-8AA5-7586DF9605C1} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {5F4FC620-9101-4630-ADB5-77B7DC057CF9} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {8BA5CF87-767F-4D7A-996D-76D0CC790610} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {189BF68E-7359-4884-AD95-EE00BE836C47} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {1E721FBD-B9A3-4D52-92AA-428A8ACD726A} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {B20B797D-67FA-4A46-945E-59390D6C0A36} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {C54A1140-3F51-450A-A813-B556679934A8} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {D946300F-CC08-4FBD-A18E-766F66FD7F1F} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {F865D881-B9D2-4C90-9AD0-0667103827F6} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {5407B027-5203-48B2-8191-A3FF43D57B16} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {89E7BCC7-CDF2-433C-9848-327DA30FB281} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {CDBA3100-3794-4DFA-AE04-A1B84B9736FD} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {25E0D8EA-56B7-4DF1-A07C-1831D699F9B4} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {A9B42891-505B-4BAE-9EE8-AF62C92BC4DA} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {4311A2FD-1032-47CE-B627-FE527A962288} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {8CC5E981-FAAF-47C6-93C8-45986A077B9B} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {ADB455D6-B2F9-4C61-90EE-60D2C04D16BC} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D} = {116B0EB5-AF61-4B16-8942-667CF8989044} + {823E5AFA-4A55-4338-8CE5-7FBAFAC103D0} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {116B0EB5-AF61-4B16-8942-667CF8989044} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC} = {116B0EB5-AF61-4B16-8942-667CF8989044} + {EDC2AC83-D4E3-4AFF-9690-9F631F224D21} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {5BD19CCB-7D4E-4207-852D-3B630C57DF49} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {44593BAC-0617-483E-9AD7-BEF4336E14D7} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {3EB20A81-87C6-4BFA-A66C-DDDB57806E09} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {CDD49C07-90A3-4244-B3D7-D6A590D0E5C1} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {649F9CBC-670C-4843-B835-5FF38D1F6B66} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {2DAF9579-77B2-44E2-B359-887D8FA01EE5} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {09AFCD48-2450-42A2-851C-A83F28474D80} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {242E7FA6-3518-4E73-9899-0A309BF8410C} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {3CAA5D74-7533-49B5-A91F-169561CEEDAC} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {534131C2-BA76-43F6-BE09-1DDEAFE4AC5C} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {DF4B1E13-144C-4419-B289-FCA08A68BC23} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {2CB069FC-D25A-417E-837F-FAFDCEE639B2} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {1E56F851-0341-4F86-8401-A8B3452F94EB} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {0576158B-ACD4-4467-85A7-6055B278111E} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {6D011140-0E5F-4627-A010-529EFF6C9EFE} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {58FF110B-FDBC-4B53-B714-C3B171915616} = {116B0EB5-AF61-4B16-8942-667CF8989044} + {955877A4-0126-4014-A7A8-40BCA9DD0B7E} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {7D4F373B-0FDA-4736-BCA4-629F00F6A8FB} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {483D41CE-0A17-40C6-AF90-554794B2214E} = {927E9767-FEA0-4FE7-A441-69E4CFEC0B48} + {BD719746-8782-4DA2-9469-75A03E02FAB9} = {7731056B-09B5-4494-907E-CDCD561F36FA} + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC} = {7731056B-09B5-4494-907E-CDCD561F36FA} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FC35004E-A0B3-48A7-9799-844D5A99B33F} + EndGlobalSection +EndGlobal diff --git a/FLSystem/About/FLSystem.html b/FLSystem/About/FLSystem.html new file mode 100644 index 0000000..064c1d7 --- /dev/null +++ b/FLSystem/About/FLSystem.html @@ -0,0 +1 @@ +20d075e371acddc48a48892fd58481c75675d9fd7e74b7ae16e63feb7\u0026scene=0#rd]]\u003e\u003c/url\u003e\n \u003clowurl\u003e\u003c![CDATA[]]\u003e\u003c/lowurl\u003e\n \u003cappattach\u003e\n \u003ctotallen\u003e0\u003c/totallen\u003e\n \u003cattachid\u003e\u003c/attachid\u003e\n \u003cfileext\u003e\u003c/fileext\u003e\n \u003c/appattach\u003e\n \u003cextinfo\u003e\u003c/extinfo\u003e\n \u003cmmreader\u003e\n \u003ccategory type=\"20\" count=\"1\"\u003e\n \u003cname\u003e\u003c![CDATA[大华日记]]\u003e\u003c/name\u003e\n \u003ctopnew\u003e\n \u003ccover\u003e\u003c![CDATA[http://mmbiz.qpic.cn/mmbiz_jpg/GTpLGfYrTNxebKolOn4HzHWyEkqZibvueOB2z1cp5vxwAyHzyANR3vWiapE353zzXtFFSUBLWc0pR2KLa5hRGB0A/640?wxtype=jpeg\u0026wxfrom=0]]\u003e\u003c/cover\u003e\n \u003cwidth\u003e0\u003c/width\u003e\n \u003cheight\u003e0\u003c/height\u003e\n \u003cdigest\u003e\u003c![CDATA[]]\u003e\u003c/digest\u003e\n \u003c/topnew\u003e\n \n \u003citem\u003e\n \u003citemshowtype\u003e0\u003c/itemshowtype\u003e\n \u003ctitle\u003e\u003c![CDATA[值多少钱]]\u003e\u003c/title\u003e\n \u003curl\u003e\u003c![CDATA[http://mp.weixin.qq.com/s?__biz=MzI4MjAyOTE3Mw==\u0026mid=2457155782\u0026idx=1\u0026sn=3460cceaa05b65fb9c26b4db94dce229\u0026chksm=fc21a5dccb562cca37320d075e371acddc48a48892fd58481c75675d9fd7e74b7ae16e63feb7\u0026scene=0#rd]]\u003e\u003c/url\u003e\n \u003cshorturl\u003e\u003c![CDATA[]]\u003e\u003c/shorturl\u003e\n \u003clongurl\u003e\u003c![CDATA[]]\u003e\u003c/longurl\u003e\n \u003cpub_time\u003e1513609845\u003c/pub_time\u003e\n \u003ccover\u003e\u003c![CDATA[http://mmbiz.qpic.cn/mmbiz_jpg/GTpLGfYrTNxebKolOn4HzHWyEkqZibvueOB2z1cp5vxwAyHzyANR3vWiapE353zzXtFFSUBLWc0pR2KLa5hRGB0A/640?wxtype=jpeg\u0026wxfrom=0]]\u003e\u003c/cover\u003e\n \u003ctweetid\u003e\u003c/tweetid\u003e\n \u003cdigest\u003e\u003c![CDATA[]]\u003e\u003c/digest\u003e\n \u003cfileid\u003e309672130\u003c/fileid\u003e\n \u003csources\u003e\n \u003csource\u003e\n \u003cname\u003e\u003c![CDATA[大华日记]]\u003e\u003c/name\u003e\n \u003c/source\u003e\n \u003c/sources\u003e\n \u003cstyles\u003e\u003c/styles\u003e\n \u003cnative_url\u003e\u003c/native_url\u003e\n \u003cdel_flag\u003e0\u003c/del_flag\u003e\n \u003ccontentattr\u003e1\u003c/contentattr\u003e\n \u003cplay_length\u003e0\u003c/play_length\u003e\n \u003cplay_url\u003e\u003c![CDATA[]]\u003e\u003c/play_url\u003e\n \u003cplayer\u003e\u003c/player\u003e\n \u003cmusic_source\u003e\u003c/music_source\u003e\n \u003cpic_num\u003e\u003c/pic_num\u003e\n \u003c/item\u003e\n \n \u003c/category\u003e\n \u003cpublisher\u003e\n \u003cusername\u003e\u003c![CDATA[gh_ab371b6d18e7]]\u003e\u003c/username\u003e\n \u003cnickname\u003e\u003c![CDATA[大华日记]]\u003e\u003c/nickname\u003e\n \u003c/publisher\u003e\n \u003ctemplate_header\u003e\u003c/template_header\u003e\n \u003ctemplate_detail\u003e\u003c/template_detail\u003e\n \u003cforbid_forward\u003e0\u003c/forbid_forward\u003e\n \u003c/mmreader\u003e\n \u003cthumburl\u003e\u003c![CDATA[http://mmbiz.qpic.cn/mmbiz_jpg/GTpLGfYrTNxebKolOn4HzHWyEkqZibvueOB2z1cp5vxwAyHzyANR3vWiapE353zzXtFFSUBLWc0pR2KLa5hRGB0A/640?wxtype=jpeg\u0026wxfrom=0]]\u003e\u003c/thumburl\u003e\n \u003c/appmsg\u003e\n \u003cfromusername\u003e\u003c![CDATA[gh_ab371b6d18e7]]\u003e\u003c/fromuse7@chatroom","ToUserName":"wxid_8s44kddouuaj21","MsgType":3,"Content":"XIEHAIFENG823171:\n\u003c?xml version=\"1.0\"?\u003e\n\u003cmsg\u003e\n\t\u003cimg aeskey=\"f90b5a075995467bba3ae916bc11cd29\" encryver=\"0\" cdnthumbaeskey=\"f90b5a075995467bba3ae916bc11cd29\" cdnthumburl=\"3050020100044930470201000204a4e1c7cb02033d11ff02046bc9c0b702045a18ee140422373738313739363238374063686174726f6f6d333630395f313531313538333232370204010400020201000400\" cdnthumblength=\"3990\" cdnthumbheight=\"67\" cdnthumbwidth=\"120\" cdnmidheight=\"0\" cdnmidwidth=\"0\" cdnhdheight=\"0\" cdnhdwidth=\"0\" cdnmidimgurl=\"3050020100044930470201000204a4e1c7cb02033d11ff02046bc9c0b702045a18ee140422373738313739363238374063686174726f6f6d333630395f313531313538333232370204010400020201000400\" length=\"59485\" md5=\"4e9a631bafdf5b38c3a6c086f71cfe5a\" /\u003e\n\u003c/msg\u003e\n","Status":3,"ImgStatus":2,"ImgBuf":"/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAABA \ No newline at end of file diff --git a/FLSystem/About/css/bootstrap.css b/FLSystem/About/css/bootstrap.css new file mode 100644 index 0000000..fb15e3d --- /dev/null +++ b/FLSystem/About/css/bootstrap.css @@ -0,0 +1,6584 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} +textarea.form-group-sm .form-control, +select[multiple].form-group-sm .form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.form-group-lg .form-control { + height: 46px; + line-height: 46px; +} +textarea.form-group-lg .form-control, +select[multiple].form-group-lg .form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.333333px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default.focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary.focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success.focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info.focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning.focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger.focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px solid; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +a.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/FLSystem/About/css/font-awesome.min.css b/FLSystem/About/css/font-awesome.min.css new file mode 100644 index 0000000..eb8bf6f --- /dev/null +++ b/FLSystem/About/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.6.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.6.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.6.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.6.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.6.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.6.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/FLSystem/About/css/timeline.css b/FLSystem/About/css/timeline.css new file mode 100644 index 0000000..0610d87 --- /dev/null +++ b/FLSystem/About/css/timeline.css @@ -0,0 +1,847 @@ +.timeline { + width: 100%; + position: relative; + padding: 1px 0; + list-style: none; + font-weight: 300; +} +.timeline .timeline-item { + padding-left: 0; + padding-right: 30px; +} +.timeline .timeline-item.timeline-item-right, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) { + padding-left: 30px; + padding-right: 0; +} +.timeline .timeline-item .timeline-event { + width: 100%; +} +.timeline:before { + border-right-style: solid; +} +.timeline:before, +.timeline:after { + content: " "; + display: block; +} +.timeline:after { + clear: both; +} +.timeline:before { + content: ""; + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 50%; + height: 100% !important; + margin-left: 1px; + border-right-width: 2px; + border-right-style: solid; + border-right-color: #888888; +} +.timeline.timeline-single-column.timeline { + width: 100%; + max-width: 768px; +} +.timeline.timeline-single-column.timeline .timeline-item { + padding-left: 72px; + padding-right: 0; +} +.timeline.timeline-single-column.timeline .timeline-item.timeline-item-right, +.timeline.timeline-single-column.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) { + padding-left: 72px; + padding-right: 0; +} +.timeline.timeline-single-column.timeline .timeline-item .timeline-event { + width: 100%; +} +.timeline.timeline-single-column.timeline:before { + left: 42px; + width: 0; + margin-left: -1px; +} +.timeline.timeline-single-column.timeline .timeline-item { + width: 100%; + margin-bottom: 20px; +} +.timeline.timeline-single-column.timeline .timeline-item:nth-of-type(even) { + margin-top: 0; +} +.timeline.timeline-single-column.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), +.timeline.timeline-single-column.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; +} +.timeline.timeline-single-column.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), +.timeline.timeline-single-column.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; +} +.timeline.timeline-single-column.timeline .timeline-item > .timeline-event { + float: right !important; +} +.timeline.timeline-single-column.timeline .timeline-item > .timeline-event:before, +.timeline.timeline-single-column.timeline .timeline-item > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline.timeline-single-column.timeline .timeline-item > .timeline-event:before { + left: -15px !important; + border-right-width: 15px !important; +} +.timeline.timeline-single-column.timeline .timeline-item > .timeline-event:after { + left: -14px !important; + border-right-width: 14px !important; +} +.timeline.timeline-single-column.timeline .timeline-item > .timeline-point { + transform: translateX(-50%); + left: 42px !important; + margin-left: 0; +} +.timeline.timeline-single-column.timeline .timeline-label { + transform: translateX(-50%); + margin: 0 0 20px 42px; +} +.timeline.timeline-single-column.timeline .timeline-label + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; +} +.timeline.timeline-single-column.timeline .timeline-label + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; +} +.timeline.timeline-line-solid:before { + border-right-style: solid; +} +.timeline.timeline-line-dotted:before { + border-right-style: dotted; +} +.timeline.timeline-line-dashed:before { + border-right-style: dashed; +} +.timeline.timeline-line-hidden:before { + border-right-style: none; +} +.timeline .timeline-item { + position: relative; + float: left; + clear: left; + width: 50%; + margin-bottom: 20px; +} +.timeline .timeline-item:before, +.timeline .timeline-item:after { + content: ""; + display: table; +} +.timeline .timeline-item:after { + clear: both; +} +.timeline .timeline-item:last-child { + margin-bottom: 0 !important; +} +.timeline .timeline-item.timeline-item-right > .timeline-event, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) > .timeline-event { + float: right !important; +} +.timeline .timeline-item.timeline-item-right > .timeline-event:before, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) > .timeline-event:before, +.timeline .timeline-item.timeline-item-right > .timeline-event:after, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline .timeline-item.timeline-item-right > .timeline-event:before, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) > .timeline-event:before { + left: -15px !important; + border-right-width: 15px !important; +} +.timeline .timeline-item.timeline-item-right > .timeline-event:after, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) > .timeline-event:after { + left: -14px !important; + border-right-width: 14px !important; +} +.timeline .timeline-item > .timeline-event:before { + top: 10px; + right: -15px; + border-top: 15px solid transparent; + border-left-width: 15px; + border-left-style: solid; + border-right-width: 0; + border-right-style: solid; + border-bottom: 15px solid transparent; +} +.timeline .timeline-item > .timeline-event:after { + top: 11px; + right: -14px; + border-top: 14px solid transparent; + border-left-width: 14px; + border-left-style: solid; + border-right-width: 0; + border-right-style: solid; + border-bottom: 14px solid transparent; +} +.timeline .timeline-item > .timeline-point { + top: 25px; +} +.timeline-single-column.timeline .timeline-item > .timeline-event { + float: right !important; +} +.timeline-single-column.timeline .timeline-item > .timeline-event:before, +.timeline-single-column.timeline .timeline-item > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline-single-column.timeline .timeline-item > .timeline-event:before { + left: -15px !important; + border-right-width: 15px !important; +} +.timeline-single-column.timeline .timeline-item > .timeline-event:after { + left: -14px !important; + border-right-width: 14px !important; +} +.timeline .timeline-item:nth-of-type(2) { + margin-top: 40px; +} +.timeline .timeline-item.timeline-item-left, +.timeline .timeline-item.timeline-item-right { + clear: both !important; +} +.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), +.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; +} +.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), +.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 40px; +} +.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), +.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + clear: both; +} +.timeline .timeline-item.timeline-item-right, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) { + float: right; + clear: right; +} +.timeline .timeline-item.timeline-item-right > .timeline-point, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) > .timeline-point { + left: -24px; +} +.timeline .timeline-item.timeline-item-right > .timeline-point.timeline-point-blank, +.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) > .timeline-point.timeline-point-blank { + left: -12px; +} +.timeline .timeline-item.timeline-item-arrow-sm.timeline-item-right > .timeline-event, +.timeline .timeline-item.timeline-item-arrow-sm:nth-of-type(even):not(.timeline-item-left) > .timeline-event { + float: right !important; +} +.timeline .timeline-item.timeline-item-arrow-sm.timeline-item-right > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-sm:nth-of-type(even):not(.timeline-item-left) > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-sm.timeline-item-right > .timeline-event:after, +.timeline .timeline-item.timeline-item-arrow-sm:nth-of-type(even):not(.timeline-item-left) > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline .timeline-item.timeline-item-arrow-sm.timeline-item-right > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-sm:nth-of-type(even):not(.timeline-item-left) > .timeline-event:before { + left: -10px !important; + border-right-width: 10px !important; +} +.timeline .timeline-item.timeline-item-arrow-sm.timeline-item-right > .timeline-event:after, +.timeline .timeline-item.timeline-item-arrow-sm:nth-of-type(even):not(.timeline-item-left) > .timeline-event:after { + left: -9px !important; + border-right-width: 9px !important; +} +.timeline .timeline-item.timeline-item-arrow-sm > .timeline-event:before { + top: 4px; + right: -10px; + border-top: 10px solid transparent; + border-left-width: 10px; + border-left-style: solid; + border-right-width: 0; + border-right-style: solid; + border-bottom: 10px solid transparent; +} +.timeline .timeline-item.timeline-item-arrow-sm > .timeline-event:after { + top: 5px; + right: -9px; + border-top: 9px solid transparent; + border-left-width: 9px; + border-left-style: solid; + border-right-width: 0; + border-right-style: solid; + border-bottom: 9px solid transparent; +} +.timeline .timeline-item.timeline-item-arrow-sm > .timeline-point { + top: 14px; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-sm > .timeline-event { + float: right !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-sm > .timeline-event:before, +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-sm > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-sm > .timeline-event:before { + left: -10px !important; + border-right-width: 10px !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-sm > .timeline-event:after { + left: -9px !important; + border-right-width: 9px !important; +} +.timeline .timeline-item.timeline-item-arrow-md.timeline-item-right > .timeline-event, +.timeline .timeline-item.timeline-item-arrow-md:nth-of-type(even):not(.timeline-item-left) > .timeline-event { + float: right !important; +} +.timeline .timeline-item.timeline-item-arrow-md.timeline-item-right > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-md:nth-of-type(even):not(.timeline-item-left) > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-md.timeline-item-right > .timeline-event:after, +.timeline .timeline-item.timeline-item-arrow-md:nth-of-type(even):not(.timeline-item-left) > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline .timeline-item.timeline-item-arrow-md.timeline-item-right > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-md:nth-of-type(even):not(.timeline-item-left) > .timeline-event:before { + left: -15px !important; + border-right-width: 15px !important; +} +.timeline .timeline-item.timeline-item-arrow-md.timeline-item-right > .timeline-event:after, +.timeline .timeline-item.timeline-item-arrow-md:nth-of-type(even):not(.timeline-item-left) > .timeline-event:after { + left: -14px !important; + border-right-width: 14px !important; +} +.timeline .timeline-item.timeline-item-arrow-md > .timeline-event:before { + top: 10px; + right: -15px; + border-top: 15px solid transparent; + border-left-width: 15px; + border-left-style: solid; + border-right-width: 0; + border-right-style: solid; + border-bottom: 15px solid transparent; +} +.timeline .timeline-item.timeline-item-arrow-md > .timeline-event:after { + top: 11px; + right: -14px; + border-top: 14px solid transparent; + border-left-width: 14px; + border-left-style: solid; + border-right-width: 0; + border-right-style: solid; + border-bottom: 14px solid transparent; +} +.timeline .timeline-item.timeline-item-arrow-md > .timeline-point { + top: 25px; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-md > .timeline-event { + float: right !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-md > .timeline-event:before, +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-md > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-md > .timeline-event:before { + left: -15px !important; + border-right-width: 15px !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-md > .timeline-event:after { + left: -14px !important; + border-right-width: 14px !important; +} +.timeline .timeline-item.timeline-item-arrow-lg.timeline-item-right > .timeline-event, +.timeline .timeline-item.timeline-item-arrow-lg:nth-of-type(even):not(.timeline-item-left) > .timeline-event { + float: right !important; +} +.timeline .timeline-item.timeline-item-arrow-lg.timeline-item-right > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-lg:nth-of-type(even):not(.timeline-item-left) > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-lg.timeline-item-right > .timeline-event:after, +.timeline .timeline-item.timeline-item-arrow-lg:nth-of-type(even):not(.timeline-item-left) > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline .timeline-item.timeline-item-arrow-lg.timeline-item-right > .timeline-event:before, +.timeline .timeline-item.timeline-item-arrow-lg:nth-of-type(even):not(.timeline-item-left) > .timeline-event:before { + left: -18px !important; + border-right-width: 18px !important; +} +.timeline .timeline-item.timeline-item-arrow-lg.timeline-item-right > .timeline-event:after, +.timeline .timeline-item.timeline-item-arrow-lg:nth-of-type(even):not(.timeline-item-left) > .timeline-event:after { + left: -17px !important; + border-right-width: 17px !important; +} +.timeline .timeline-item.timeline-item-arrow-lg > .timeline-event:before { + top: 10px; + right: -18px; + border-top: 18px solid transparent; + border-left-width: 18px; + border-left-style: solid; + border-right-width: 0; + border-right-style: solid; + border-bottom: 18px solid transparent; +} +.timeline .timeline-item.timeline-item-arrow-lg > .timeline-event:after { + top: 11px; + right: -17px; + border-top: 17px solid transparent; + border-left-width: 17px; + border-left-style: solid; + border-right-width: 0; + border-right-style: solid; + border-bottom: 17px solid transparent; +} +.timeline .timeline-item.timeline-item-arrow-lg > .timeline-point { + top: 28px; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-lg > .timeline-event { + float: right !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-lg > .timeline-event:before, +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-lg > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-lg > .timeline-event:before { + left: -18px !important; + border-right-width: 18px !important; +} +.timeline-single-column.timeline .timeline-item.timeline-item-arrow-lg > .timeline-event:after { + left: -17px !important; + border-right-width: 17px !important; +} +.timeline .timeline-item > .timeline-event { + background: #fff; + border: 1px solid #888888; + color: #555; + position: relative; + float: left; + border-radius: 3px; +} +.timeline .timeline-item > .timeline-event:before { + border-left-color: #888888; + border-right-color: #888888; +} +.timeline .timeline-item > .timeline-event:after { + border-left-color: #fff; + border-right-color: #fff; +} +.timeline .timeline-item > .timeline-event h1, +.timeline .timeline-item > .timeline-event h2, +.timeline .timeline-item > .timeline-event h3, +.timeline .timeline-item > .timeline-event h4, +.timeline .timeline-item > .timeline-event h5, +.timeline .timeline-item > .timeline-event h6, +.timeline .timeline-item > .timeline-event p, +.timeline .timeline-item > .timeline-event .timeline-inherit-color { + color: inherit; +} +.timeline .timeline-item > .timeline-event.timeline-event-default { + background: #fff; + border: 1px solid #888888; + color: #555; +} +.timeline .timeline-item > .timeline-event.timeline-event-default:before { + border-left-color: #888888; + border-right-color: #888888; +} +.timeline .timeline-item > .timeline-event.timeline-event-default:after { + border-left-color: #fff; + border-right-color: #fff; +} +.timeline .timeline-item > .timeline-event.timeline-event-default h1, +.timeline .timeline-item > .timeline-event.timeline-event-default h2, +.timeline .timeline-item > .timeline-event.timeline-event-default h3, +.timeline .timeline-item > .timeline-event.timeline-event-default h4, +.timeline .timeline-item > .timeline-event.timeline-event-default h5, +.timeline .timeline-item > .timeline-event.timeline-event-default h6, +.timeline .timeline-item > .timeline-event.timeline-event-default p, +.timeline .timeline-item > .timeline-event.timeline-event-default .timeline-inherit-color { + color: inherit; +} +.timeline .timeline-item > .timeline-event.timeline-event-primary { + background: #f5f5f5; + border: 1px solid #888888; + color: #555; +} +.timeline .timeline-item > .timeline-event.timeline-event-primary:before { + border-left-color: #888888; + border-right-color: #888888; +} +.timeline .timeline-item > .timeline-event.timeline-event-primary:after { + border-left-color: #f5f5f5; + border-right-color: #f5f5f5; +} +.timeline .timeline-item > .timeline-event.timeline-event-primary h1, +.timeline .timeline-item > .timeline-event.timeline-event-primary h2, +.timeline .timeline-item > .timeline-event.timeline-event-primary h3, +.timeline .timeline-item > .timeline-event.timeline-event-primary h4, +.timeline .timeline-item > .timeline-event.timeline-event-primary h5, +.timeline .timeline-item > .timeline-event.timeline-event-primary h6, +.timeline .timeline-item > .timeline-event.timeline-event-primary p, +.timeline .timeline-item > .timeline-event.timeline-event-primary .timeline-inherit-color { + color: inherit; +} +.timeline .timeline-item > .timeline-event.timeline-event-success { + background: #F3F8ED; + border: 1px solid #72b92e; + color: #3F8100; +} +.timeline .timeline-item > .timeline-event.timeline-event-success:before { + border-left-color: #72b92e; + border-right-color: #72b92e; +} +.timeline .timeline-item > .timeline-event.timeline-event-success:after { + border-left-color: #F3F8ED; + border-right-color: #F3F8ED; +} +.timeline .timeline-item > .timeline-event.timeline-event-success h1, +.timeline .timeline-item > .timeline-event.timeline-event-success h2, +.timeline .timeline-item > .timeline-event.timeline-event-success h3, +.timeline .timeline-item > .timeline-event.timeline-event-success h4, +.timeline .timeline-item > .timeline-event.timeline-event-success h5, +.timeline .timeline-item > .timeline-event.timeline-event-success h6, +.timeline .timeline-item > .timeline-event.timeline-event-success p, +.timeline .timeline-item > .timeline-event.timeline-event-success .timeline-inherit-color { + color: inherit; +} +.timeline .timeline-item > .timeline-event.timeline-event-info { + background: #F0F8FD; + border: 1px solid #3e93cf; + color: #0062A7; +} +.timeline .timeline-item > .timeline-event.timeline-event-info:before { + border-left-color: #3e93cf; + border-right-color: #3e93cf; +} +.timeline .timeline-item > .timeline-event.timeline-event-info:after { + border-left-color: #F0F8FD; + border-right-color: #F0F8FD; +} +.timeline .timeline-item > .timeline-event.timeline-event-info h1, +.timeline .timeline-item > .timeline-event.timeline-event-info h2, +.timeline .timeline-item > .timeline-event.timeline-event-info h3, +.timeline .timeline-item > .timeline-event.timeline-event-info h4, +.timeline .timeline-item > .timeline-event.timeline-event-info h5, +.timeline .timeline-item > .timeline-event.timeline-event-info h6, +.timeline .timeline-item > .timeline-event.timeline-event-info p, +.timeline .timeline-item > .timeline-event.timeline-event-info .timeline-inherit-color { + color: inherit; +} +.timeline .timeline-item > .timeline-event.timeline-event-warning { + background: #FFF9E9; + border: 1px solid #d0aa42; + color: #ac7e00; +} +.timeline .timeline-item > .timeline-event.timeline-event-warning:before { + border-left-color: #d0aa42; + border-right-color: #d0aa42; +} +.timeline .timeline-item > .timeline-event.timeline-event-warning:after { + border-left-color: #FFF9E9; + border-right-color: #FFF9E9; +} +.timeline .timeline-item > .timeline-event.timeline-event-warning h1, +.timeline .timeline-item > .timeline-event.timeline-event-warning h2, +.timeline .timeline-item > .timeline-event.timeline-event-warning h3, +.timeline .timeline-item > .timeline-event.timeline-event-warning h4, +.timeline .timeline-item > .timeline-event.timeline-event-warning h5, +.timeline .timeline-item > .timeline-event.timeline-event-warning h6, +.timeline .timeline-item > .timeline-event.timeline-event-warning p, +.timeline .timeline-item > .timeline-event.timeline-event-warning .timeline-inherit-color { + color: inherit; +} +.timeline .timeline-item > .timeline-event.timeline-event-danger { + background: #FFC4BC; + border: 1px solid #d25a4b; + color: #B71500; +} +.timeline .timeline-item > .timeline-event.timeline-event-danger:before { + border-left-color: #d25a4b; + border-right-color: #d25a4b; +} +.timeline .timeline-item > .timeline-event.timeline-event-danger:after { + border-left-color: #FFC4BC; + border-right-color: #FFC4BC; +} +.timeline .timeline-item > .timeline-event.timeline-event-danger h1, +.timeline .timeline-item > .timeline-event.timeline-event-danger h2, +.timeline .timeline-item > .timeline-event.timeline-event-danger h3, +.timeline .timeline-item > .timeline-event.timeline-event-danger h4, +.timeline .timeline-item > .timeline-event.timeline-event-danger h5, +.timeline .timeline-item > .timeline-event.timeline-event-danger h6, +.timeline .timeline-item > .timeline-event.timeline-event-danger p, +.timeline .timeline-item > .timeline-event.timeline-event-danger .timeline-inherit-color { + color: inherit; +} +.timeline .timeline-item > .timeline-event:before, +.timeline .timeline-item > .timeline-event:after { + content: ""; + display: inline-block; + position: absolute; +} +.timeline .timeline-item > .timeline-event .timeline-heading, +.timeline .timeline-item > .timeline-event .timeline-body, +.timeline .timeline-item > .timeline-event .timeline-footer { + padding: 4px 10px; +} +.timeline .timeline-item > .timeline-event .timeline-heading p, +.timeline .timeline-item > .timeline-event .timeline-body p, +.timeline .timeline-item > .timeline-event .timeline-footer p, +.timeline .timeline-item > .timeline-event .timeline-heading ul, +.timeline .timeline-item > .timeline-event .timeline-body ul, +.timeline .timeline-item > .timeline-event .timeline-footer ul { + margin-bottom: 0; +} +.timeline .timeline-item > .timeline-event .timeline-heading h4 { + font-weight: 400; +} +.timeline .timeline-item > .timeline-event .timeline-footer a { + cursor: pointer; + text-decoration: none; +} +.timeline .timeline-item > .timeline-event .panel, +.timeline .timeline-item > .timeline-event .table, +.timeline .timeline-item > .timeline-event .blankslate { + margin: 0; + border: none; + border-radius: inherit; + overflow: hidden; +} +.timeline .timeline-item > .timeline-event .table th { + border-top: 0; +} +.timeline .timeline-item > .timeline-point { + color: #888888; + background: #fff; + right: -24px; + width: 24px; + height: 24px; + margin-top: -12px; + margin-left: 12px; + margin-right: 12px; + position: absolute; + z-index: 100; + border-width: 2px; + border-style: solid; + border-radius: 100%; + line-height: 20px; + text-align: center; +} +.timeline .timeline-item > .timeline-point.timeline-point-blank { + right: -12px; + width: 12px; + height: 12px; + margin-top: -6px; + margin-left: 6px; + margin-right: 6px; + color: #888888; + background: #888888; +} +.timeline .timeline-item > .timeline-point.timeline-point-default { + color: #888888; + background: #fff; +} +.timeline .timeline-item > .timeline-point.timeline-point-primary { + color: #888888; + background: #fff; +} +.timeline .timeline-item > .timeline-point.timeline-point-success { + color: #72b92e; + background: #fff; +} +.timeline .timeline-item > .timeline-point.timeline-point-info { + color: #3e93cf; + background: #fff; +} +.timeline .timeline-item > .timeline-point.timeline-point-warning { + color: #d0aa42; + background: #fff; +} +.timeline .timeline-item > .timeline-point.timeline-point-danger { + color: #d25a4b; + background: #fff; +} +.timeline .timeline-label { + position: relative; + float: left; + clear: left; + width: 50%; + margin-bottom: 20px; + top: 1px; + width: 100%; + margin-left: auto; + margin-right: auto; + padding: 0; + text-align: center; +} +.timeline .timeline-label:before, +.timeline .timeline-label:after { + content: ""; + display: table; +} +.timeline .timeline-label:after { + clear: both; +} +.timeline .timeline-label:last-child { + margin-bottom: 0 !important; +} +.timeline .timeline-label + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; +} +.timeline .timeline-label + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 40px; +} +.timeline .timeline-label .label-default { + background-color: #888888; +} +.timeline .timeline-label .label-primary { + background-color: #888888; +} +.timeline .timeline-label .label-info { + background-color: #3e93cf; +} +.timeline .timeline-label .label-warning { + background-color: #d0aa42; +} +.timeline .timeline-label .label-danger { + background-color: #d25a4b; +} +@media all and (orientation: portrait) { + .timeline.timeline { + width: 100%; + max-width: 100%; + } + .timeline.timeline .timeline-item { + padding-left: 72px; + padding-right: 0; + } + .timeline.timeline .timeline-item.timeline-item-right, + .timeline.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) { + padding-left: 72px; + padding-right: 0; + } + .timeline.timeline .timeline-item .timeline-event { + width: 100%; + } + .timeline.timeline:before { + left: 42px; + width: 0; + margin-left: -1px; + } + .timeline.timeline .timeline-item { + width: 100%; + margin-bottom: 20px; + } + .timeline.timeline .timeline-item:nth-of-type(even) { + margin-top: 0; + } + .timeline.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), + .timeline.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; + } + .timeline.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), + .timeline.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; + } + .timeline.timeline .timeline-item > .timeline-event { + float: right !important; + } + .timeline.timeline .timeline-item > .timeline-event:before, + .timeline.timeline .timeline-item > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; + } + .timeline.timeline .timeline-item > .timeline-event:before { + left: -15px !important; + border-right-width: 15px !important; + } + .timeline.timeline .timeline-item > .timeline-event:after { + left: -14px !important; + border-right-width: 14px !important; + } + .timeline.timeline .timeline-item > .timeline-point { + transform: translateX(-50%); + left: 42px !important; + margin-left: 0; + } + .timeline.timeline .timeline-label { + transform: translateX(-50%); + margin: 0 0 20px 42px; + } + .timeline.timeline .timeline-label + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; + } + .timeline.timeline .timeline-label + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; + } +} +@media (max-width: 768px) { + .timeline.timeline { + width: 100%; + max-width: 100%; + } + .timeline.timeline .timeline-item { + padding-left: 72px; + padding-right: 0; + } + .timeline.timeline .timeline-item.timeline-item-right, + .timeline.timeline .timeline-item:nth-of-type(even):not(.timeline-item-left) { + padding-left: 72px; + padding-right: 0; + } + .timeline.timeline .timeline-item .timeline-event { + width: 100%; + } + .timeline.timeline:before { + left: 42px; + width: 0; + margin-left: -1px; + } + .timeline.timeline .timeline-item { + width: 100%; + margin-bottom: 20px; + } + .timeline.timeline .timeline-item:nth-of-type(even) { + margin-top: 0; + } + .timeline.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), + .timeline.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; + } + .timeline.timeline .timeline-item.timeline-item-left + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right), + .timeline.timeline .timeline-item.timeline-item-right + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; + } + .timeline.timeline .timeline-item > .timeline-event { + float: right !important; + } + .timeline.timeline .timeline-item > .timeline-event:before, + .timeline.timeline .timeline-item > .timeline-event:after { + right: auto !important; + border-left-width: 0 !important; + } + .timeline.timeline .timeline-item > .timeline-event:before { + left: -15px !important; + border-right-width: 15px !important; + } + .timeline.timeline .timeline-item > .timeline-event:after { + left: -14px !important; + border-right-width: 14px !important; + } + .timeline.timeline .timeline-item > .timeline-point { + transform: translateX(-50%); + left: 42px !important; + margin-left: 0; + } + .timeline.timeline .timeline-label { + transform: translateX(-50%); + margin: 0 0 20px 42px; + } + .timeline.timeline .timeline-label + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; + } + .timeline.timeline .timeline-label + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) + .timeline-item:not(.timeline-item-left):not(.timeline-item-right) { + margin-top: 0; + } +} diff --git a/FLSystem/About/fonts/fontawesome-webfont.ttf b/FLSystem/About/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..cec09e0 Binary files /dev/null and b/FLSystem/About/fonts/fontawesome-webfont.ttf differ diff --git a/FLSystem/App.config b/FLSystem/App.config new file mode 100644 index 0000000..ef694b0 --- /dev/null +++ b/FLSystem/App.config @@ -0,0 +1,77 @@ + + + + +
+ +
+ + + + + Skin/Office 2019 White + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FLSystem/ControlExtension.cs b/FLSystem/ControlExtension.cs new file mode 100644 index 0000000..10516ee --- /dev/null +++ b/FLSystem/ControlExtension.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace System.Windows.Forms +{ + /// + /// + /// + public static class ControlExtension + { + /// + /// 控件跨线程访问 + /// + /// + /// + /// + /// + public static void SafeInvoke(this Control uiElement, Action updater, bool forceSynchronous = true,bool isOutputLog=true) + { + try + { + if (uiElement == null) + { + throw new ArgumentNullException("uiElement"); + } + + if (uiElement.InvokeRequired) + { + if (forceSynchronous) + { + uiElement.Invoke((Action)delegate { SafeInvoke(uiElement, updater, true); }); + } + else + { + uiElement.BeginInvoke((Action)delegate { SafeInvoke(uiElement, updater, false); }); + } + } + else + { + if (uiElement.IsDisposed) + { + return; + throw new ObjectDisposedException("Control is already disposed."); + } + + updater(); + } + } + catch (Exception ex) + { + if (isOutputLog) + { + } + } + } + /// + /// 控件跨线程访问 + /// + /// + /// + /// + /// + /// + /// + public static void SafeInvoke(this Control uiElement, Action updater, T data, bool forceSynchronous = true, bool isOutputLog = true) + { + try + { + if (uiElement == null) + { + throw new ArgumentNullException("uiElement"); + } + + if (uiElement.InvokeRequired) + { + if (forceSynchronous) + { + uiElement.Invoke(updater, data); + } + else + { + uiElement.BeginInvoke(updater, data); + } + } + else + { + if (uiElement.IsDisposed) + { + return; + throw new ObjectDisposedException("Control is already disposed."); + } + updater(data); + } + } + catch (Exception ex) + { + if (isOutputLog) + { + } + } + } + + /// + /// 自动禁止启动执行 + /// + /// + /// + /// + public static void SafeEnabledInvoke(this ToolStripItem uiElement, Action updater, string hintText = "正在执行.") + { + string value = uiElement.Text; + uiElement.Enabled = false; + uiElement.Text = hintText; + try + { + updater(); + } + catch (Exception ex) + { + } + uiElement.Text = value; + uiElement.Enabled = true; + } + + /// + /// 自动禁止启动控件执行 + /// + /// + /// + /// + public static void SafeEnabledInvoke(this Control uiElement, Action updater,string hintText= "正在执行.") + { + uiElement.Enabled = false; + string value = uiElement.Text; + uiElement.Text = hintText; + try + { + updater(); + } + catch (Exception ex) + { + } + uiElement.Text = value; + uiElement.Enabled = true; + } + } +} \ No newline at end of file diff --git a/FLSystem/Events/CommonEvents.cs b/FLSystem/Events/CommonEvents.cs new file mode 100644 index 0000000..ae557b5 --- /dev/null +++ b/FLSystem/Events/CommonEvents.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FLSystem.Events +{ + public class CommonEvents:EventArgs + { + public Dictionary Commons { get; private set; } + + public CommonEvents(Dictionary Commons) + { + this.Commons = Commons; + } + + public CommonEvents() + { + } + } +} diff --git a/FLSystem/FLSystem.csproj b/FLSystem/FLSystem.csproj new file mode 100644 index 0000000..e7813dd --- /dev/null +++ b/FLSystem/FLSystem.csproj @@ -0,0 +1,1117 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {2E04051F-0E96-409A-9F93-4418603E69D0} + WinExe + Properties + FLSystem + FLSystem + v4.6.1 + 512 + false + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + x86 + true + full + false + ..\Debug\ + DEBUG;TRACE + prompt + 4 + + + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + true + ..\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + true + + + LocalIntranet + + + false + + + Properties\app.manifest + + + false + + + + False + ..\Debug\Api.Framework.dll + False + + + + + False + ..\Debug\Chat.Framework.dll + False + + + + + + + + + + + + + + + + + + + + False + + + + + + + + + + + + + + + + + + + + + + False + + + C:\Users\先森吳\Desktop\DevExpressCrack.dll + + + ..\packages\EO.WebBrowser.21.3.18\lib\EO.Base.dll + + + ..\packages\EO.WebBrowser.21.3.18\lib\EO.WebBrowser.dll + + + ..\packages\EO.WebBrowser.WinForm.21.3.18\lib\EO.WebBrowser.WinForm.dll + + + ..\packages\EO.WebBrowser.21.3.18\lib\EO.WebEngine.dll + + + False + ..\Debug\Grant.Framework.dll + + + False + ..\DLL\Newtonsoft.Json.dll + + + False + ..\Debug\Robot.Framework.dll + False + + + False + ..\Debug\SqlSugar.dll + + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.dll + + + ..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll + + + + + + + + + + + + + ..\packages\System.Net.NameResolution.4.3.0\lib\net46\System.Net.NameResolution.dll + + + ..\packages\System.Net.Security.4.3.0\lib\net46\System.Net.Security.dll + + + ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll + + + ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + + + ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + + + ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + + + ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + + + + + + + + + + + + + + False + ..\Debug\UI.Framework.dll + + + + + + + + Form + + + AddCloudblack.cs + + + UserControl + + + admin_verify_control.cs + + + UserControl + + + convert_tool_control.cs + + + UserControl + + + cps_order_douyin.cs + + + UserControl + + + cps_order_kuaishou.cs + + + UserControl + + + cps_order_refund_alimama.cs + + + UserControl + + + cps_order_suning.cs + + + UserControl + + + cps_order_weipinhui.cs + + + Form + + + edit_uservariate_form.cs + + + Form + + + group_info_form.cs + + + UserControl + + + home_control.cs + + + Form + + + jd_adzone_group_form.cs + + + Form + + + LockForm.cs + + + Form + + + member_order_lastnum_custom.cs + + + Form + + + OneKeyExchangeForm.cs + + + Form + + + RatioCustomGroupForm.cs + + + Form + + + UpdateForm.cs + + + Form + + + VerifyPassForm.cs + + + Form + + + WPHNavForm.cs + + + UserControl + + + notice_robotapi_control.cs + + + Form + + + notice_robotapi_editform.cs + + + Form + + + ServerClientManage.cs + + + Form + + + tb_adzone_activity_group_form.cs + + + Form + + + tb_adzone_group_form.cs + + + Form + + + setting_endtime_form.cs + + + Form + + + set_wechat_device.cs + + + Form + + + TCPForm.cs + + + Form + + + tlj_form.cs + + + Form + + + update_log_form.cs + + + Form + + + WphRegisterForm.cs + + + + True + True + Resources.resx + + + + + Form + + + add_authorization.cs + + + Form + + + change_point_form.cs + + + UserControl + + + cps_coerce_alimama.cs + + + UserControl + + + cps_manage_control.cs + + + UserControl + + + cps_order_alimama.cs + + + UserControl + + + cps_order_jingdong.cs + + + UserControl + + + cps_order_pinduoduo.cs + + + UserControl + + + data_report_control.cs + + + Form + + + EditGroup.cs + + + Form + + + EncPlugin.cs + + + Form + + + ExchangeStateForm.cs + + + Form + + + GroupForm.cs + + + UserControl + + + group_manage_control.cs + + + UserControl + + + item_query_hist_control.cs + + + Form + + + LeavingMessageForm.cs + + + Form + + + main.cs + + + Form + + + MemberForm.cs + + + Form + + + member_base_info_form.cs + + + Form + + + member_inviter_control.cs + + + UserControl + + + member_manage_control.cs + + + UserControl + + + member_order_lastnum.cs + + + Form + + + member_private_config.cs + + + Form + + + member_reelect_group.cs + + + UserControl + + + plugin_control.cs + + + UserControl + + + plugin_debug.cs + + + UserControl + + + plugin_manage.cs + + + Form + + + plugin_sort_form.cs + + + UserControl + + + point_manage_control.cs + + + UserControl + + + private_pid_manage.cs + + + UserControl + + + robot_manage_control.cs + + + Form + + + select_member_form.cs + + + UserControl + + + setting_system_control.cs + + + Form + + + set_weixin_password.cs + + + UserControl + + + system_log_control.cs + + + Form + + + web_api_form.cs + + + + + Form + + + Test.cs + + + + AddCloudblack.cs + Designer + + + add_authorization.cs + Designer + + + admin_verify_control.cs + + + convert_tool_control.cs + + + cps_order_douyin.cs + + + cps_order_kuaishou.cs + + + cps_order_refund_alimama.cs + Designer + + + cps_order_suning.cs + + + cps_order_weipinhui.cs + + + edit_uservariate_form.cs + + + group_info_form.cs + + + home_control.cs + + + jd_adzone_group_form.cs + Designer + + + LockForm.cs + + + member_order_lastnum_custom.cs + + + OneKeyExchangeForm.cs + + + RatioCustomGroupForm.cs + + + UpdateForm.cs + + + VerifyPassForm.cs + + + WPHNavForm.cs + + + notice_robotapi_control.cs + + + notice_robotapi_editform.cs + + + ServerClientManage.cs + + + tb_adzone_activity_group_form.cs + Designer + + + tb_adzone_group_form.cs + Designer + + + change_point_form.cs + + + cps_coerce_alimama.cs + Designer + + + cps_manage_control.cs + Designer + + + cps_order_alimama.cs + Designer + + + cps_order_jingdong.cs + Designer + + + cps_order_pinduoduo.cs + Designer + + + data_report_control.cs + + + EditGroup.cs + + + EncPlugin.cs + + + ExchangeStateForm.cs + Designer + + + GroupForm.cs + + + group_manage_control.cs + + + item_query_hist_control.cs + + + LeavingMessageForm.cs + + + main.cs + Designer + + + MemberForm.cs + + + member_base_info_form.cs + + + member_inviter_control.cs + + + member_order_lastnum.cs + + + member_private_config.cs + Designer + + + member_reelect_group.cs + + + point_manage_control.cs + + + private_pid_manage.cs + + + select_member_form.cs + + + setting_endtime_form.cs + + + set_wechat_device.cs + Designer + + + TCPForm.cs + + + tlj_form.cs + + + update_log_form.cs + + + web_api_form.cs + + + + + WphRegisterForm.cs + + + Test.cs + + + + Designer + + + member_manage_control.cs + + + plugin_control.cs + + + plugin_debug.cs + + + plugin_manage.cs + + + plugin_sort_form.cs + + + robot_manage_control.cs + + + setting_system_control.cs + + + set_weixin_password.cs + + + system_log_control.cs + + + Designer + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + True + Settings.settings + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4.6.1 %28x86 和 x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC} + PCRobot.Pack + + + {b54ae050-dd6c-4f73-95e8-9d8c1cf38ffe} + HttpHelper + False + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + \ No newline at end of file diff --git a/FLSystem/FLSystem.sln b/FLSystem/FLSystem.sln new file mode 100644 index 0000000..cb4a3ff --- /dev/null +++ b/FLSystem/FLSystem.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.106 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FLSystem", "FLSystem.csproj", "{2E04051F-0E96-409A-9F93-4418603E69D0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|x86.ActiveCfg = Debug|x86 + {2E04051F-0E96-409A-9F93-4418603E69D0}.Debug|x86.Build.0 = Debug|x86 + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|Any CPU.Build.0 = Release|Any CPU + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|x86.ActiveCfg = Release|x86 + {2E04051F-0E96-409A-9F93-4418603E69D0}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FC35004E-A0B3-48A7-9799-844D5A99B33F} + EndGlobalSection +EndGlobal diff --git a/FLSystem/Forms/AddCloudblack.Designer.cs b/FLSystem/Forms/AddCloudblack.Designer.cs new file mode 100644 index 0000000..bc7e9c3 --- /dev/null +++ b/FLSystem/Forms/AddCloudblack.Designer.cs @@ -0,0 +1,177 @@ +namespace FLSystem.Forms +{ + partial class AddCloudblack + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AddCloudblack)); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.label4 = new System.Windows.Forms.Label(); + this.textEdit4 = new DevExpress.XtraEditors.MemoEdit(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(34, 77); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 0; + this.label1.Text = "用户名:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(34, 121); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(51, 14); + this.label2.TabIndex = 1; + this.label2.Text = "昵 称:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(34, 31); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(51, 14); + this.label3.TabIndex = 2; + this.label3.Text = "类 型:"; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(93, 28); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Properties.ReadOnly = true; + this.textEdit1.Size = new System.Drawing.Size(201, 20); + this.textEdit1.TabIndex = 3; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(93, 74); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Properties.ReadOnly = true; + this.textEdit2.Size = new System.Drawing.Size(201, 20); + this.textEdit2.TabIndex = 4; + // + // textEdit3 + // + this.textEdit3.Location = new System.Drawing.Point(93, 118); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Properties.ReadOnly = true; + this.textEdit3.Size = new System.Drawing.Size(201, 20); + this.textEdit3.TabIndex = 5; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(34, 171); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(51, 14); + this.label4.TabIndex = 6; + this.label4.Text = "原 因:"; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(93, 168); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(201, 62); + this.textEdit4.TabIndex = 7; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(37, 250); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(116, 31); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "更新云黑名单"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // simpleButton2 + // + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(193, 250); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(131, 31); + this.simpleButton2.TabIndex = 9; + this.simpleButton2.Text = "删除云黑名单"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // AddCloudblack + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(349, 303); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.label4); + this.Controls.Add(this.textEdit3); + this.Controls.Add(this.textEdit2); + this.Controls.Add(this.textEdit1); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.textEdit4); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AddCloudblack"; + this.Text = "更新云黑名"; + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.TextEdit textEdit3; + private System.Windows.Forms.Label label4; + private DevExpress.XtraEditors.MemoEdit textEdit4; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/AddCloudblack.cs b/FLSystem/Forms/AddCloudblack.cs new file mode 100644 index 0000000..c39d258 --- /dev/null +++ b/FLSystem/Forms/AddCloudblack.cs @@ -0,0 +1,103 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using Newtonsoft.Json; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class AddCloudblack : BaseForm + { + public AddCloudblack(fl_member_info info) + { + InitializeComponent(); + this.info = info; + this.textEdit1.Text = this.info.robot_type.ToString(); + this.textEdit2.Text = this.info.username; + this.textEdit3.Text = this.info.usernick; + } + fl_member_info info; + private void simpleButton1_Click(object sender, EventArgs e) + { + ServiceResult rst = null; + try + { + CloudBlack black = new CloudBlack(); + rst = black.InsertBlack(info, this.textEdit4.Text); + if (rst.Ok) + { + info.status = Api.Framework.Enums.MemberType.黑名单; + var session = ApiClient.GetSession(); + session.Updateable(new { status = info.status }).Where(f => f.id == info.id).ExecuteCommand(); + + var _black = session.Queryable().First(f => f.username == info.username && f.usertype == info.robot_type); + if (_black != null) + { + _black.nickname = info.usernick; + _black.remark = textEdit4.Text; + _black.iscloud = true; + _black.isdel = false;//标记没有被删除 + session.Updateable(_black).ExecuteCommand(); + } + else + { + _black = new fl_blackuser(); + _black.usertype = info.robot_type; + _black.username = info.username; + _black.nickname = info.usernick; + _black.remark = textEdit4.Text; + _black.isdel = false; + _black.iscloud = true; + _black.updatetime = DateTime.Now; + session.Insertable(_black).ExecuteCommand(); + } + + BaseForm.ShowSuccess(rst.Message); + this.Close(); + } + else + throw new Exception(rst.Message ?? rst.Data?.ToString()); + } + catch (Exception ex) + { + EventClient.OnEvent("添加云黑名单异常:", "添加云黑名单:" + (rst == null ? string.Empty : JsonConvert.SerializeObject(rst))); + BaseForm.ShowError(ex); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + ServiceResult rst = null; + try + { + CloudBlack black = new CloudBlack(); + rst = black.RemoveBlack(info); + if (rst != null && rst.Ok) + { + info.status = Api.Framework.Enums.MemberType.正常; + var session = ApiClient.GetSession(); + session.Updateable(new { status = info.status }).Where(f => f.id == info.id).ExecuteCommand(); + var blackuser = session.Queryable().First(f => f.username == info.username && f.usertype == info.robot_type); + if (blackuser != null) + { + blackuser.isdel = true; + blackuser.iscloud = false; + blackuser.updatetime = DateTime.Now; + session.Updateable(blackuser).ExecuteCommand(); + } + + BaseForm.ShowSuccess(rst.Message); + this.Close(); + } + else + throw new Exception(rst.Message ?? rst.Data?.ToString()); + } + catch (Exception ex) + { + EventClient.OnEvent("删除云黑名单异常:", "删除云黑名单:" + (rst == null ? string.Empty : CsharpHttpHelper.HttpHelper.ObjectToJson(rst))); + BaseForm.ShowError(ex); + } + } + } +} diff --git a/FLSystem/Forms/AddCloudblack.resx b/FLSystem/Forms/AddCloudblack.resx new file mode 100644 index 0000000..ca4e21e --- /dev/null +++ b/FLSystem/Forms/AddCloudblack.resx @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACN0RVh0VGl0 + bGUAQ2FuY2VsO1N0b3A7RXhpdDtCYXJzO1JpYmJvbjtMlpayAAALFUlEQVRYR5WXB1RVxxaGx/dSfEGM + xq50BUUEC1goAtJBwYZiiRpFDREJNkBApVgQE7FjJMYSg6KiXlBRNNJEqQIXROBSlM6lKqLI1bf+7DkX + iHkr67319lrfmrlzZvb/zz5zDgdWsz+Y2C0n9G+g8Wpqq0M4wYyiz3/jRYA/ex7gxyp2+rLnRIW/Nyv3 + 9WLl271Ymc9WVuq9hUm2bWaSrZ40naJmXxD7d+vzbl6wD38DRY/AP4h/Ep8Qn/4HfIzDr/N5fd7XP2Pv + 6wvZ+zrOU/a+poDJasRMVp3Hijw9aApF1d4A9qGlnKj4K2SIokdYEM302jyleIdvcOku/0dlu/xyKgL8 + PpTv9P0g8ffOlfh6P8732rwnYcN6A5r7GZ9PyI0I4vm94rKqXFa4cQNdoqgM3sk+NJcRZOIjKHp2/Kl4 + +7bFJCip/DEEzbFX0CFOxdtnmaB5RBneFKbjdU4yGq9HomJvIJ5t2yxJc3dbTms/JwQjMm6gSi4uq3zC + 8r9zo2GKil1+7H2jpJtSoaUQdp3g7ja6xH97ek34EXTkpeJ9fRE6i9LQkX4Xr1Nv4uXdi3h55ze0J91A + e0oM3oqTIKvOR3t2IirC9kPs4Z55dsH8cZSLV0SoRteLbNb1PIvlrVtLPynK/Lez9w3FvVBw8U/SPT2s + JTu2t7beE6HrRR5eP75NYpFy4i6g7TZx6zzaYs+iVXQGrddPoyX6FFqunsTL+IvoLE6DNCYK+R7urTFL + lzhQTl4NuYnSNJa9ejV1KSQ+2+jePGWy2kL+UxBP3fCdjWSXf1d7ViLeZP8uF7opp/XmObTFnCVI9MYv + JPwzWq9FkPBPaL58As0Xj6Hpt8NoPB+G9oRotD2MQ66Hu+y688JeE53FqSxzxUqux1jRZk/WVZnHu0LZ + Rd+sGFfos625PfMBXlGCFi5C8FaABFu4YDQXpR1fOUnC4Wi+dBxNkUfQeOEQGs/9iMYzByD9OUSoSmtS + LDJcXVuOWVvrkoZwOx4vXcY1GROvWc26yrN5l5fnszyPjY+lsVFUxig08+RXaGe9cLFuwSjaLRcVdtwj + fBCNZ3+A9HQoGiL2ouHkbtQdDyJjx1AdeRrJLkvTSaMfwQ8m3zBjWS5LeCOUPnntmuUlwbvQnixCY+RR + YWEPNREHEOc8F78aTMX9rxej4exBNP1KolTqehKMd5mP0xP0IHKwRmXYDtSfCEbd0QDUHt6B2oO+aKFz + kvX9Rlyyc+A3vy/BN8xYuvMi3vAfn2evXy9puh0F6YXDkJKA9FyYQE34PojsbXDNaxfuxDzE1fUeuDXX + AXWnQlD30z7EzLHF5bXuiBOl4IqnL6JMjFAR4oXaMD9U/+CD6tBtqD7gjdrIU4h3ml9GWv2J3ioIu79q + a28n3uJJTs9S4n2ojwgRaPh5P+4sdILINwipWWUoe96IotJ6XHPzxE1He9ycY0fiG5GUVoyisnqUPG+C + iIyKrC1QFeqFqpAtqNq9CS8CNwq5UletwrGphk6k2fNUCAY+i7ObfejZzm2o3O2JmqOBqKUScuqIy8ZG + qK9qQEV1C9rau9D2+h1KyhsEE5fXeSDxcTGKyVhz+zs0v+pEq7QFZ3QnomqPJ14EfY/nAe6o8P8W5d6u + yN26ERemmxwnTQWCv2EFF33jbR0eSXZ6osTVCcXfzkflnk2oObQDNYd3InHVMjzasROd72Rk4B1aXpEQ + tcXlUqTnVKC4ohFNLzsF+JwkLx/EzXeUC+9wQ+nWVXi2xglFaxxR6LMBUdNn8sPIb0OvgS/ireyaJd7r + ULjSDoVf26JwhR1K3JxR7u+G2vA9uLdoAdICAwUBQYx2ytvGj+jslOGhnx9i7a3xItQHpZtWoNh1npDr + 6XIbwhbFW1xx2cCkhTQHEvwcCC4UblvYyCQey1HgYo2CpdZ4uowvILiZVQ4o93ND3GwbJPv6Qdr2BlIS + lLa97aW+uQOJPr6IsTRD2Xa+EQdBkOfh+fJdLCFebIlidxdcmmwoI82vCP5XVDDQL3ampaxw9TyInWfR + RAvk02S+qGCJlTwBJbptaYob33rgqUQKaQsZaHmLBqKOqG3qwK0NmxBjaggxzS9YaoX8JfIcPF+eszny + Fpqh4Js5uKA7nRsY9BcDN4zMmnOW2CNvAU1cYEaTzckMsYgMLbLALXNDXKfH7/eUIhSUSlHXTKICHYJ4 + bdNbiIvrcdV1A64b6iOXC3IoV+4CU+TOm0mYIsvZGme19fkt6DXAz4DCJQOTx2lzrZBDE584mdBkDi2a + PxN3LY1xw+173E95hnzavVywA2/edqGDqGnsQHU3ec9qcW3tBsQYG1AuUzyZa4InjsbIdjQS8ibZmSFc + c2ImafaeAW7gX6f1ph29b2WObCdTZDvMQNYcQ2TPMaKFJG5qjDJJNcQl9YJYDYl3vOlCRlAA0gMDhH6V + tEOgsuE1aqukuKg/RVifNXsGMilfpt10ymmEWKPpCFXR/ok0//IUfL5XS9cpepoRMhwIm6nItJmGDLtp + yKKF8faWeHryBF51dFHp3wiCWcFBuGNjjjhrM8HIaxrjVeFz8o4ewc1ZJsL6TMqVYW2AdCt9pNlOx3nt + idg6TN2FNPl7gGvL34TEl2e09cvvG08RJqdb8nYKMqwMkLtsNuJIjJt429CArKBA3LWdhYKVjihY5Yg7 + 1qbICNyFNw31yDt2FCJTI+QstUcarU+zmIy0WZOQRvnipk7AYSVt/q03lOBvwj7s3Dh9auXvgj1q49dF + 6kxGqvkkPDKbiMfmBF9MhriJ+w6WiJ01Ew/mWCFvmYNgNIMQL7PHPXsLRBsbIs6K7jsd5jRLfSHHI1M9 + PJqphxQTPUSoa2PrYFV30uopfx/2i+ZkaoUq8BM54ISGbtYNPR2kGE9AqrEuUmlx6kxdPDKfjNzF9Diu + nIscZyukmZFJUy5AJqmfs5Ae1xWOyF1kTcKT8NBEvv6hkQ6SZ4xHlJYmQoeO4R8ef+6eR4SGHkuw4B+y + 8sO4ZrDSjHA1ndbYiVpImqotLE6ZoYOHhtQakjGj8ULSh0YTPoJf52N03VCb5vM12kiaPg6JBlq4Pk4D + YUNHty3oN8SUNPj3gHz3PMJVddj9GRMEKPhZ6Ld5iOrCcGVt2TXt0fh9iiYSp45FMpE4bRySiSQipbv9 + k7ECiZypWkgg7k3SwGVNVYQN1pC5Kg5fSrkHELzSfX4YqEYNxfFR2uzuZE0WR1D03Ir+7l8pLzo8XOtl + pIYabuuo4f5kDTyYMgYP9DUFEnoZgwQymSBcI6h/T08DN8er4LyKCkK/Un21WmEo//7ir17+OdZHNEGd + hfZXpS7FkRFjWSwNxOqo85/cQI8JxXn9Bk/bP0gjN3yEOqLUlRE7Vgm3KPE9XTVCHQ8mUoWIePodP0EN + cXRNpDUKkaqjcHSwCoL6K4tt+w4wolx854I455qWEtunqEJdirAhY5iIBq5rjWIizVF8qMcEvx38WR3i + 0X+k+76BapWHBqsiYoQSflMZSSIjET16OKI1hiNSZQQuKI/EqeGjcHCgMvYoKle5KQzj/3sNJxQJoeyc + K+oj2BX14WyvgjL9pPhxkAaLVh/Grml0Q32KHhP8sPATyx+bYcu+GOLorTjyRKCisjhYUaUkpL8KQhRp + p/2USgIUlMRbvxgR7tJ30FyaO4Lgu+bffnwjQr7LKkNYD3sVlGiI4sBAdXZggBoL5XypSi3B2/5CiT42 + wkvIK8ITDyH47kZ2w/v88eLvd37KueleYS72d/w/0WOEP6o8MS8pN8SFOLzPx/g1Pqdn/v8Ixv4AVZya + X9ttAMYAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/FLSystem/Forms/EditGroup.Designer.cs b/FLSystem/Forms/EditGroup.Designer.cs new file mode 100644 index 0000000..cb5ac1b --- /dev/null +++ b/FLSystem/Forms/EditGroup.Designer.cs @@ -0,0 +1,182 @@ +namespace FLSystem.Forms +{ + partial class EditGroup + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.linkLabel2); + this.groupBox1.Controls.Add(this.linkLabel1); + this.groupBox1.Controls.Add(this.textBox4); + this.groupBox1.Controls.Add(this.textBox3); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(37, 30); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(431, 244); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 编辑区 "; + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(328, 135); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(55, 14); + this.linkLabel2.TabIndex = 2; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "选择用户"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(328, 51); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(43, 14); + this.linkLabel1.TabIndex = 2; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "选择群"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // textBox4 + // + this.textBox4.Location = new System.Drawing.Point(120, 173); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(189, 22); + this.textBox4.TabIndex = 1; + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(120, 131); + this.textBox3.Name = "textBox3"; + this.textBox3.Size = new System.Drawing.Size(189, 22); + this.textBox3.TabIndex = 1; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(120, 89); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(189, 22); + this.textBox2.TabIndex = 1; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(44, 177); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 14); + this.label4.TabIndex = 0; + this.label4.Text = "群管昵称:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(120, 47); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(189, 22); + this.textBox1.TabIndex = 1; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(44, 135); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(67, 14); + this.label3.TabIndex = 0; + this.label3.Text = "群管账号:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(56, 93); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(55, 14); + this.label2.TabIndex = 0; + this.label2.Text = "群昵称:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(56, 51); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 0; + this.label1.Text = "群账号:"; + // + // EditGroup + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(507, 309); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditGroup"; + this.Text = "{0}群管"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.EditGroup_FormClosing); + this.Load += new System.EventHandler(this.EditGroup_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/EditGroup.cs b/FLSystem/Forms/EditGroup.cs new file mode 100644 index 0000000..a9c2c1b --- /dev/null +++ b/FLSystem/Forms/EditGroup.cs @@ -0,0 +1,124 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using SqlSugar; +using System; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class EditGroup : BaseForm + { + private fl_group_person group = null; + SqlSugarClient session = ApiClient.GetSession(); + public EditGroup(fl_group_person group = null) + { + InitializeComponent(); + this.group = group; + this.Text = Text.Replace("{0}", group == null ? "增加" : "修改"); + } + + private void EditGroup_Load(object sender, EventArgs e) + { + try + { + if (group != null) + { + textBox1.Text = group.groupid; + textBox2.Text = group.groupname; + if (group.mid != 0) + { + var member = session.FindSingle("select * from fl_member_info where username = @username", new { username = textBox3.Text }); + if (member != null) + { + textBox3.Text = member.username; + textBox4.Text = member.usernick; + linkLabel2.Tag = member.id; + } + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + var groupForm = new GroupForm(); + if (groupForm.ShowDialog() == DialogResult.OK) + { + if (groupForm.group != null) + { + textBox1.Text = groupForm.group.groupid; + textBox2.Text = groupForm.group.groupname; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + var memberForm = new MemberForm(); + if (memberForm.ShowDialog() == DialogResult.OK) + { + if (memberForm.member != null) + { + textBox3.Text = memberForm.member.username; + textBox4.Text = memberForm.member.usernick; + linkLabel2.Tag = memberForm.member.id; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void EditGroup_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("请填写群账号"); + if (string.IsNullOrWhiteSpace(textBox3.Text)) throw new Exception("请填写管理账号"); + + if (group == null) + { + var _group = session.Queryable().First(f => f.groupid == textBox1.Text.Trim()); + if (_group != null) throw new Exception("该群账号已经存在请核对后重试"); + group = new fl_group_person() { groupid = textBox1.Text.Trim(), groupname = textBox2.Text.Trim() }; + } + + long mid = 0; + if (linkLabel2.Tag != null) + mid = long.Parse(linkLabel2.Tag.ToString()); + else + { + var member = session.FindSingle("select * from fl_member_info where username = @username",new { username = textBox3.Text }); + if (member == null) throw new Exception("输入的管理员账号不存在"); + mid = member.id; + } + group.mid = mid; + session.SaveOrUpdate(group); + } + catch (Exception ex) + { + if (XtraMessageBox.Show(ex.Message + ",是否关闭?", "操作失败", MessageBoxButtons.YesNo) == DialogResult.No) + e.Cancel = true; + } + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/EditGroup.resx b/FLSystem/Forms/EditGroup.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/EditGroup.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/EncPlugin.Designer.cs b/FLSystem/Forms/EncPlugin.Designer.cs new file mode 100644 index 0000000..2d4fab7 --- /dev/null +++ b/FLSystem/Forms/EncPlugin.Designer.cs @@ -0,0 +1,128 @@ +namespace FLSystem.Forms +{ + partial class EncPlugin + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label1 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.linkLabel1); + this.groupBox1.Controls.Add(this.panel1); + this.groupBox1.Location = new System.Drawing.Point(19, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(348, 130); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "应用封装"; + this.groupBox1.DragDrop += new System.Windows.Forms.DragEventHandler(this.groupBox1_DragDrop); + this.groupBox1.DragEnter += new System.Windows.Forms.DragEventHandler(this.groupBox1_DragEnter); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(270, 0); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(75, 14); + this.linkLabel1.TabIndex = 2; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "选择应用DLL"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // panel1 + // + this.panel1.AllowDrop = true; + this.panel1.Controls.Add(this.label1); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(3, 18); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(342, 109); + this.panel1.TabIndex = 0; + this.panel1.DragDrop += new System.Windows.Forms.DragEventHandler(this.groupBox1_DragDrop); + this.panel1.DragEnter += new System.Windows.Forms.DragEventHandler(this.groupBox1_DragEnter); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ForeColor = System.Drawing.Color.Gray; + this.label1.Location = new System.Drawing.Point(122, 47); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(99, 14); + this.label1.TabIndex = 1; + this.label1.Text = "请拖拽DLL到此处"; + this.label1.DragDrop += new System.Windows.Forms.DragEventHandler(this.groupBox1_DragDrop); + this.label1.DragEnter += new System.Windows.Forms.DragEventHandler(this.groupBox1_DragEnter); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(114, 153); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(156, 40); + this.button1.TabIndex = 1; + this.button1.Text = "申请可调试权限"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // EncPlugin + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(386, 206); + this.Controls.Add(this.button1); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EncPlugin"; + this.Text = "应用封装"; + this.Load += new System.EventHandler(this.EncPlugin_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.LinkLabel linkLabel1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/EncPlugin.cs b/FLSystem/Forms/EncPlugin.cs new file mode 100644 index 0000000..cfd8d17 --- /dev/null +++ b/FLSystem/Forms/EncPlugin.cs @@ -0,0 +1,96 @@ +using Api.Framework; +using CsharpHttpHelper; +using Grant.Framework; +using System; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class EncPlugin :BaseForm + { + public EncPlugin() + { + InitializeComponent(); + } + + private void EncPlugin_Load(object sender, EventArgs e) + { + try + { + var a = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; + var b = System.IO.File.ReadAllBytes(a); + if (b[b.Length - 1] != 83 || b[b.Length - 2] != 84) + { + this.button1.Text = "已获得可调试权限"; + this.button1.Enabled = false; + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message,"Error",MessageBoxButtons.OK,MessageBoxIcon.Error); + } + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + Computer cx = Computer.Instance(); + var md5 = HttpHelper.ToMD5(cx.ComputerName + cx.CpuID + cx.LoginUserName); + MessageBox.Show($@"机器码:{md5} + +如有独立开发能力、可向客服申請权限!","请发送给管理员"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message,"Error",MessageBoxButtons.OK,MessageBoxIcon.Error); + } + } + + private void groupBox1_DragEnter(object sender, DragEventArgs e) + { + e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Link : DragDropEffects.None; + } + + private void groupBox1_DragDrop(object sender, DragEventArgs e) + { + try + { + var text = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString(); + var plugin = PluginClient.FileConvertPlugin(text); + ShowSuccess($"恭喜您,封装成功!\r\n友情提示:\r\n 您的DLL可以先混淆加密再來封裝会更安全哦!\r\n路径:{plugin.FilePath}","操作成功"); + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + + try + { + OpenFileDialog dialog = new OpenFileDialog(); + dialog.Multiselect = true;//该值确定是否可以选择多个文件 + dialog.Title = "请选择插件DLL"; + dialog.Filter = "所有文件(*.dll)|*.dll"; + if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + string file = dialog.FileName; + var plugin = PluginClient.FileConvertPlugin(file); + ShowSuccess($@"恭喜您,封装成功! +友情提示: +您的DLL可以先混淆加密再來封裝会更安全哦! +路径:{plugin.FilePath}", "操作成功"); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + } +} diff --git a/FLSystem/Forms/EncPlugin.resx b/FLSystem/Forms/EncPlugin.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/EncPlugin.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/ExchangeStateForm.Designer.cs b/FLSystem/Forms/ExchangeStateForm.Designer.cs new file mode 100644 index 0000000..600103b --- /dev/null +++ b/FLSystem/Forms/ExchangeStateForm.Designer.cs @@ -0,0 +1,134 @@ +namespace FLSystem.Forms +{ + partial class ExchangeStateForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExchangeStateForm)); + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.simpleButton4 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + this.SuspendLayout(); + // + // panelControl1 + // + this.panelControl1.Controls.Add(this.simpleButton4); + this.panelControl1.Controls.Add(this.simpleButton3); + this.panelControl1.Controls.Add(this.simpleButton2); + this.panelControl1.Controls.Add(this.simpleButton1); + this.panelControl1.Controls.Add(this.settingControl1); + this.panelControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panelControl1.Location = new System.Drawing.Point(0, 0); + this.panelControl1.Name = "panelControl1"; + this.panelControl1.Size = new System.Drawing.Size(483, 511); + this.panelControl1.TabIndex = 0; + // + // simpleButton4 + // + this.simpleButton4.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton4.ImageOptions.Image"))); + this.simpleButton4.Location = new System.Drawing.Point(9, 466); + this.simpleButton4.Name = "simpleButton4"; + this.simpleButton4.Size = new System.Drawing.Size(100, 33); + this.simpleButton4.TabIndex = 8; + this.simpleButton4.Text = "确认修改"; + this.simpleButton4.Click += new System.EventHandler(this.simpleButton4_Click); + // + // simpleButton3 + // + this.simpleButton3.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(376, 466); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(92, 33); + this.simpleButton3.TabIndex = 7; + this.simpleButton3.Text = "取消操作"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(257, 466); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(98, 33); + this.simpleButton2.TabIndex = 6; + this.simpleButton2.Text = "商户支付"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(130, 466); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(106, 33); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "微信支付"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.settingControl1.Location = new System.Drawing.Point(2, 2); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(479, 457); + this.settingControl1.TabIndex = 1; + // + // ExchangeStateForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.simpleButton3; + this.ClientSize = new System.Drawing.Size(483, 511); + this.Controls.Add(this.panelControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ExchangeStateForm"; + this.Text = " 审 核 申 请 "; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ExchangeStateForm_FormClosing); + this.Load += new System.EventHandler(this.ExchangeStateForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.PanelControl panelControl1; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton4; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/ExchangeStateForm.cs b/FLSystem/Forms/ExchangeStateForm.cs new file mode 100644 index 0000000..870b272 --- /dev/null +++ b/FLSystem/Forms/ExchangeStateForm.cs @@ -0,0 +1,297 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.IPAD; +using DevExpress.XtraEditors; +using Newtonsoft.Json; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; +using static FLSystem.Forms.point_manage_control; + +namespace FLSystem.Forms +{ + public partial class ExchangeStateForm : BaseForm + { + public ExchangeStateForm(exchange_list_temp exchange) + { + InitializeComponent(); + this.exchange = exchange; + } + + exchange_list_temp exchange; + bool is_auto_pay = false; + public string mess { get; set; } + public string pay_url { get; private set; } + + private void ExchangeStateForm_Load(object sender, EventArgs e) + { + pay_url = string.Empty; + try + { + this.settingControl1.Bind(exchange); + } + catch (Exception ex) + { + if (!this.IsDisposed) + ShowError(ex); + } + } + + private void simpleButton4_Click(object sender, EventArgs e) + { + try + { + if (exchange.state == ApplyType.退回兑换) + { + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == exchange.robot_name); + if (client == null) + { + if (XtraMessageBox.Show( +$@"{exchange.robot_name}机器人没有登录 +用户将无法收到退回兑换消息 +点击OK执行操作", "温馨提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, DevExpress.Utils.DefaultBoolean.Default) == DialogResult.Cancel) + { + exchange.state = ApplyType.未审核; + } + } + else + { + exchange.state = ApplyType.退回兑换; + //throw new Exception("兑换退回失败,请稍后重试"); + } + } + this.Close(); + + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + exchange.state = ApplyType.未审核; + exchange.remark = string.Empty; + this.Close(); + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private async void simpleButton1_Click(object sender, EventArgs e) + { + ChangeBtn(this.simpleButton1); + try + { + await Task.Run(() => + { + try + { + if (exchange.chattype != Api.Framework.SDK.ChatType.微信) throw new Exception("暂时不支持自动转账!"); + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == exchange.robot_name); + if (client == null) throw new Exception(exchange.robot_name + ",该帐号没有登录!"); + if (client.WeixinType != Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信) throw new Exception("您当前登录的微信版本,暂不支持自动转账!"); + + var session = ApiClient.GetSession(); + var robot = session.FindRobotInfo(exchange.robot_name, exchange.chattype); + if (robot == null) throw new Exception(exchange.robot_name + ",数据库丢失!"); + var passInfo = session.FindWeixinpassword(robot.id);//微信自动转账 + + if (!string.IsNullOrWhiteSpace(exchange.groupid)) + { + var user = client.GetContact(exchange.username); + if (user == null) throw new Exception("兑换用户数据异常"); + if (!string.IsNullOrWhiteSpace(user.Ticket))//非好友 + throw new Exception("该用户为非好友,请使用支付宝转账"); + } + + if (passInfo != null && !string.IsNullOrEmpty(passInfo.password))//是否设置了账号密码 + { + var bank = passInfo.GetBank(); + var pointConfig = ApiClient.GetPointManageConfig(); + if (pointConfig == null) + throw new Exception("获取积分管理配置为*"); + string result = client.SendPay(exchange.username, pointConfig.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", exchange.point.ToString("0.00")), (int)((decimal)exchange.point * 100m), passInfo.password, 1, (PayType)Enum.ToObject(typeof(PayType), (int)pointConfig.Exchange_PayType), bank); + if (!string.IsNullOrEmpty(result)) throw new Exception(robot.name + (bank != null ? "银行" : "余额") + "转账:" + exchange.point.ToString("0.00") + "," + result); + exchange.state = ApplyType.已审核; + exchange.check_time = DateTime.Now; + exchange.remark = "手动审核【微信支付】"; + is_auto_pay = true; + ChangeBtn(this.simpleButton1, "微信支付"); + } + else + throw new Exception($@"{robot.nick}({robot.name}),尚未设置支付密码! +请在机器人管理中,右击机器人设置密码!"); + } + catch (Exception ex) + { + exchange.state = ApplyType.未审核; + //settingControl1.Bind(new exchange_list_temp()); + this.settingControl1.Bind(exchange); + if (!this.IsDisposed) ShowError(ex); + ChangeBtn(this.simpleButton1, "微信支付"); + } + }, tokenSource.Token); + } + catch (Exception) + { } + } + bool is_close = true; + private void ChangeBtn(SimpleButton btn, string text = "") + { + if (!this.IsDisposed) + this.UpdateUI(() => + { + btn.Text = string.IsNullOrEmpty(text) ? "支付中.." : text; + btn.Enabled = string.IsNullOrEmpty(text) ? false : true; + is_close = btn.Enabled; + if (is_auto_pay) this.Close(); + }); + } + + private async void simpleButton2_Click(object sender, EventArgs e) + { + ChangeBtn(this.simpleButton2); + try + { + await Task.Run(() => + { + try + { + //if (exchange.chattype != Api.Framework.SDK.ChatType.微信) + // throw new Exception("暂时不支持自动转账!"); + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == exchange.robot_name); + + //var pcclient = ChatClient.PCRobotPool.GetSession(exchange.robot_name); + + if (client == null) + throw new Exception(exchange.robot_name + ",该账号没有登录!"); + + var session = ApiClient.GetSession(); + var robot = session.FindRobotInfo(exchange.robot_name, exchange.chattype); + if (robot == null) + throw new Exception(exchange.robot_name + ",数据库丢失!"); + + if (client != null && !string.IsNullOrWhiteSpace(exchange.groupid)) + { + var user = client.GetContact(exchange.username); + if (user == null) throw new Exception("兑换用户数据异常"); + if (!string.IsNullOrWhiteSpace(user.Ticket) && user.Ticket != "-1" && user.Ticket != "0")//非好友 + throw new Exception("该用户为非好友或已拉黑,请使用支付宝转账"); + } + + var pointConfig = ApiClient.GetPointManageConfig(); + if (pointConfig == null) + throw new Exception("获取积分管理配置为空_"); + + if (string.IsNullOrWhiteSpace(pointConfig.ExchangeCommercialPayTip)) + throw new Exception("商户付款通知提示语不能为空,请到积分兑换插件中设置"); + else if (!pointConfig.ExchangeCommercialPayTip.Contains("[领取地址]")) + throw new Exception("商户付款通知提示语中不包含 [领取地址] 变量,请到积分兑换插件中设置"); + + EventClient.OnEvent(this, $"{robot.nick}【{robot.uin}】手动审核【商户付款】{exchange.username} begin:{DateTime.Now.ToString("u")}"); + + var ispaid = false; + object appinfo = null; + + var ExchangePacketTitle = @"兑换成功:[兑换金额]"; + if (!string.IsNullOrWhiteSpace(pointConfig.ExchangePacketTitle)) + ExchangePacketTitle = pointConfig.ExchangePacketTitle; + + string url = ApiClient.SendWechatPay(new { robot_nick = robot.nick, robot_name = robot.name, username = exchange.username, usernick = exchange.usernick }, ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", exchange.point.ToString()), exchange.point, out ispaid, out appinfo); + if (string.IsNullOrEmpty(url)) + throw new Exception("服务器繁忙,请稍后重试"); + if (ispaid) + { + var ExchangeCommercialEftTip = @"一一一一商 户 转 账 成 功一一一一 +[兑换金额]兑换成功 +已直接转入您的账户!"; + if (!string.IsNullOrWhiteSpace(pointConfig.ExchangeCommercialEftTip)) + ExchangeCommercialEftTip = pointConfig.ExchangeCommercialEftTip; + + this.mess = ExchangeCommercialEftTip.Replace("[兑换金额]", exchange.point.ToString("0.00")); + } + else + { + this.pay_url = url;//ApiClient.ShortURL(url).Result; + bool isSendMiNi = false; + + if (pointConfig.ExchangeCommercialPayTip_MiniApp == Api.Framework.Enums.SwitchType.开启) + { + var xml = Util.GetMiNiAppXml(appinfo, robot.type); + if (!string.IsNullOrWhiteSpace(xml)) + { + this.mess = xml; + isSendMiNi = true; + } + } + + try + { + EventClient.OnEvent(this, $@"{robot.type.ToString()}->{robot.nick}【{robot.uin}】手动审核【{robot.name} - {exchange.username}({exchange.usernick})】 +手动审核【商户付款】end:{DateTime.Now.ToString("u")} +url:{url} +pay_url:{pay_url} +appinfo is null:{(appinfo == null)} +appinfo = {(appinfo != null ? JsonConvert.SerializeObject(appinfo) : "NULL") } +app开关:{(pointConfig.ExchangeCommercialPayTip_MiniApp == Api.Framework.Enums.SwitchType.开启)} +是否小程序:{isSendMiNi.ToString()} +回复长度:{(mess == null ? "0" : mess.Length + "")}"); + + } + catch (Exception) + { } + + if (!isSendMiNi) + { + var ExchangeCommercialPayTip = @"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"; + if (!string.IsNullOrWhiteSpace(pointConfig.ExchangeCommercialPayTip)) + ExchangeCommercialPayTip = pointConfig.ExchangeCommercialPayTip; + + this.mess = ExchangeCommercialPayTip.Replace("[领取地址]", ApiClient.ShortURL(this.pay_url).Result).Replace("[兑换金额]", exchange.point.ToString("0.00")); + } + } + + exchange.state = ApplyType.已审核; + exchange.check_time = DateTime.Now; + exchange.remark = $"手动审核【商户付款】 商户链接:{url}"; + is_auto_pay = true; + EventClient.OnEvent(this, $"{robot.nick}【{robot.uin}】商户付款信息 = " + mess); + ChangeBtn(this.simpleButton2, "商户支付"); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + ChangeBtn(this.simpleButton2, "商户支付"); + exchange.state = ApplyType.未审核; + //settingControl1.Bind(new exchange_list_temp()); + this.settingControl1.Bind(exchange); + if (!this.IsDisposed) ShowError(ex); + })); + } + }, tokenSource.Token); + } + catch (Exception) + { } + } + + private void ExchangeStateForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (!is_close) + e.Cancel = true; + else + tokenSource.Cancel(); + } + + } +} \ No newline at end of file diff --git a/FLSystem/Forms/ExchangeStateForm.resx b/FLSystem/Forms/ExchangeStateForm.resx new file mode 100644 index 0000000..440de48 --- /dev/null +++ b/FLSystem/Forms/ExchangeStateForm.resx @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACN0RVh0VGl0 + bGUAQ2FuY2VsO1N0b3A7RXhpdDtCYXJzO1JpYmJvbjtMlpayAAALFUlEQVRYR5WXB1RVxxaGx/dSfEGM + xq50BUUEC1goAtJBwYZiiRpFDREJNkBApVgQE7FjJMYSg6KiXlBRNNJEqQIXROBSlM6lKqLI1bf+7DkX + iHkr67319lrfmrlzZvb/zz5zDgdWsz+Y2C0n9G+g8Wpqq0M4wYyiz3/jRYA/ex7gxyp2+rLnRIW/Nyv3 + 9WLl271Ymc9WVuq9hUm2bWaSrZ40naJmXxD7d+vzbl6wD38DRY/AP4h/Ep8Qn/4HfIzDr/N5fd7XP2Pv + 6wvZ+zrOU/a+poDJasRMVp3Hijw9aApF1d4A9qGlnKj4K2SIokdYEM302jyleIdvcOku/0dlu/xyKgL8 + PpTv9P0g8ffOlfh6P8732rwnYcN6A5r7GZ9PyI0I4vm94rKqXFa4cQNdoqgM3sk+NJcRZOIjKHp2/Kl4 + +7bFJCip/DEEzbFX0CFOxdtnmaB5RBneFKbjdU4yGq9HomJvIJ5t2yxJc3dbTms/JwQjMm6gSi4uq3zC + 8r9zo2GKil1+7H2jpJtSoaUQdp3g7ja6xH97ek34EXTkpeJ9fRE6i9LQkX4Xr1Nv4uXdi3h55ze0J91A + e0oM3oqTIKvOR3t2IirC9kPs4Z55dsH8cZSLV0SoRteLbNb1PIvlrVtLPynK/Lez9w3FvVBw8U/SPT2s + JTu2t7beE6HrRR5eP75NYpFy4i6g7TZx6zzaYs+iVXQGrddPoyX6FFqunsTL+IvoLE6DNCYK+R7urTFL + lzhQTl4NuYnSNJa9ejV1KSQ+2+jePGWy2kL+UxBP3fCdjWSXf1d7ViLeZP8uF7opp/XmObTFnCVI9MYv + JPwzWq9FkPBPaL58As0Xj6Hpt8NoPB+G9oRotD2MQ66Hu+y688JeE53FqSxzxUqux1jRZk/WVZnHu0LZ + Rd+sGFfos625PfMBXlGCFi5C8FaABFu4YDQXpR1fOUnC4Wi+dBxNkUfQeOEQGs/9iMYzByD9OUSoSmtS + LDJcXVuOWVvrkoZwOx4vXcY1GROvWc26yrN5l5fnszyPjY+lsVFUxig08+RXaGe9cLFuwSjaLRcVdtwj + fBCNZ3+A9HQoGiL2ouHkbtQdDyJjx1AdeRrJLkvTSaMfwQ8m3zBjWS5LeCOUPnntmuUlwbvQnixCY+RR + YWEPNREHEOc8F78aTMX9rxej4exBNP1KolTqehKMd5mP0xP0IHKwRmXYDtSfCEbd0QDUHt6B2oO+aKFz + kvX9Rlyyc+A3vy/BN8xYuvMi3vAfn2evXy9puh0F6YXDkJKA9FyYQE34PojsbXDNaxfuxDzE1fUeuDXX + AXWnQlD30z7EzLHF5bXuiBOl4IqnL6JMjFAR4oXaMD9U/+CD6tBtqD7gjdrIU4h3ml9GWv2J3ioIu79q + a28n3uJJTs9S4n2ojwgRaPh5P+4sdILINwipWWUoe96IotJ6XHPzxE1He9ycY0fiG5GUVoyisnqUPG+C + iIyKrC1QFeqFqpAtqNq9CS8CNwq5UletwrGphk6k2fNUCAY+i7ObfejZzm2o3O2JmqOBqKUScuqIy8ZG + qK9qQEV1C9rau9D2+h1KyhsEE5fXeSDxcTGKyVhz+zs0v+pEq7QFZ3QnomqPJ14EfY/nAe6o8P8W5d6u + yN26ERemmxwnTQWCv2EFF33jbR0eSXZ6osTVCcXfzkflnk2oObQDNYd3InHVMjzasROd72Rk4B1aXpEQ + tcXlUqTnVKC4ohFNLzsF+JwkLx/EzXeUC+9wQ+nWVXi2xglFaxxR6LMBUdNn8sPIb0OvgS/ireyaJd7r + ULjSDoVf26JwhR1K3JxR7u+G2vA9uLdoAdICAwUBQYx2ytvGj+jslOGhnx9i7a3xItQHpZtWoNh1npDr + 6XIbwhbFW1xx2cCkhTQHEvwcCC4UblvYyCQey1HgYo2CpdZ4uowvILiZVQ4o93ND3GwbJPv6Qdr2BlIS + lLa97aW+uQOJPr6IsTRD2Xa+EQdBkOfh+fJdLCFebIlidxdcmmwoI82vCP5XVDDQL3ampaxw9TyInWfR + RAvk02S+qGCJlTwBJbptaYob33rgqUQKaQsZaHmLBqKOqG3qwK0NmxBjaggxzS9YaoX8JfIcPF+eszny + Fpqh4Js5uKA7nRsY9BcDN4zMmnOW2CNvAU1cYEaTzckMsYgMLbLALXNDXKfH7/eUIhSUSlHXTKICHYJ4 + bdNbiIvrcdV1A64b6iOXC3IoV+4CU+TOm0mYIsvZGme19fkt6DXAz4DCJQOTx2lzrZBDE584mdBkDi2a + PxN3LY1xw+173E95hnzavVywA2/edqGDqGnsQHU3ec9qcW3tBsQYG1AuUzyZa4InjsbIdjQS8ibZmSFc + c2ImafaeAW7gX6f1ph29b2WObCdTZDvMQNYcQ2TPMaKFJG5qjDJJNcQl9YJYDYl3vOlCRlAA0gMDhH6V + tEOgsuE1aqukuKg/RVifNXsGMilfpt10ymmEWKPpCFXR/ok0//IUfL5XS9cpepoRMhwIm6nItJmGDLtp + yKKF8faWeHryBF51dFHp3wiCWcFBuGNjjjhrM8HIaxrjVeFz8o4ewc1ZJsL6TMqVYW2AdCt9pNlOx3nt + idg6TN2FNPl7gGvL34TEl2e09cvvG08RJqdb8nYKMqwMkLtsNuJIjJt429CArKBA3LWdhYKVjihY5Yg7 + 1qbICNyFNw31yDt2FCJTI+QstUcarU+zmIy0WZOQRvnipk7AYSVt/q03lOBvwj7s3Dh9auXvgj1q49dF + 6kxGqvkkPDKbiMfmBF9MhriJ+w6WiJ01Ew/mWCFvmYNgNIMQL7PHPXsLRBsbIs6K7jsd5jRLfSHHI1M9 + PJqphxQTPUSoa2PrYFV30uopfx/2i+ZkaoUq8BM54ISGbtYNPR2kGE9AqrEuUmlx6kxdPDKfjNzF9Diu + nIscZyukmZFJUy5AJqmfs5Ae1xWOyF1kTcKT8NBEvv6hkQ6SZ4xHlJYmQoeO4R8ef+6eR4SGHkuw4B+y + 8sO4ZrDSjHA1ndbYiVpImqotLE6ZoYOHhtQakjGj8ULSh0YTPoJf52N03VCb5vM12kiaPg6JBlq4Pk4D + YUNHty3oN8SUNPj3gHz3PMJVddj9GRMEKPhZ6Ld5iOrCcGVt2TXt0fh9iiYSp45FMpE4bRySiSQipbv9 + k7ECiZypWkgg7k3SwGVNVYQN1pC5Kg5fSrkHELzSfX4YqEYNxfFR2uzuZE0WR1D03Ir+7l8pLzo8XOtl + pIYabuuo4f5kDTyYMgYP9DUFEnoZgwQymSBcI6h/T08DN8er4LyKCkK/Un21WmEo//7ir17+OdZHNEGd + hfZXpS7FkRFjWSwNxOqo85/cQI8JxXn9Bk/bP0gjN3yEOqLUlRE7Vgm3KPE9XTVCHQ8mUoWIePodP0EN + cXRNpDUKkaqjcHSwCoL6K4tt+w4wolx854I455qWEtunqEJdirAhY5iIBq5rjWIizVF8qMcEvx38WR3i + 0X+k+76BapWHBqsiYoQSflMZSSIjET16OKI1hiNSZQQuKI/EqeGjcHCgMvYoKle5KQzj/3sNJxQJoeyc + K+oj2BX14WyvgjL9pPhxkAaLVh/Grml0Q32KHhP8sPATyx+bYcu+GOLorTjyRKCisjhYUaUkpL8KQhRp + p/2USgIUlMRbvxgR7tJ30FyaO4Lgu+bffnwjQr7LKkNYD3sVlGiI4sBAdXZggBoL5XypSi3B2/5CiT42 + wkvIK8ITDyH47kZ2w/v88eLvd37KueleYS72d/w/0WOEP6o8MS8pN8SFOLzPx/g1Pqdn/v8Ixv4AVZya + X9ttAMYAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAidEVYdFRpdGxlAEZpbmFuY2lhbDtEb2xsYXI7TW9u + ZXk7Qm9vazuCQ/4SAAAHWUlEQVRYR7WXe1RU1xXGbZM2adL4ioI8jC9MEQFRIySKPAZBEYFBXsobGQRE + YGAQkNcIAeOT1xgEykOrNZoYoyYxpigPETQKSq0g2CDGlXYtLUn/aFf759e9z8wlo94J7erKXeu39jln + Zs737XPP7HPvJACT+ErYtXxSQslybv7MwM9/AqS5xSW0xw1ol3HgD18gfkm8bOBXE/DKBLxqiDzXLwjJ + yNMG6OLBF8PV9mtjC51644uWIr5YT2bV2+OoOVa6GNoUqc1j6koJ6jMVLsgwIm2/c19cwRJf0mATsgbY + 2UuxhUsfR+Y4ovdeN/7+z3//T3z/j3+ZpG+4G2n7nB+TBq8aa8kaeCW2wAlBqXY4eq4Zt4Yf4tbQI9w2 + xL5BioOj6Bt6KNp91L45oOeGEdz/6s4IvrpLUOSxO8PfIHXPWyz2GsG3+TkDPPhqTL4j1Pu8kPzuKgMr + UdziiiKm2ZhVgsImgqPUFqxEAdMo8Q7ePRqOpLJlLDaZeJEF5Qz8OirPEWev7MeZjt34uL0MJ/9Qggff + n8T9747j/tgxDI/9jjiKobEjBlqIZgz9rQn3njCNGHzyW6IBA0/qiToMPK7DpQEttulXYAph2kBErgM+ + aNWivDkE5S3B2FUXgBvflqDnUeF/zzdSLBin/6+VkoGphEkDr23KtsfxLwpQ2qgkglBYuwHXHhWj62He + 84zKxGfbBnq/3Yfk8uUTGpgcrlmMI5/lQtsQgOL6QOTrfHH1YQE6Rnag40G2Po4Yx2y0GyE3xlx/VIat + +j0wjZA1wINTQjPt0Hheg8LDfoLcqrXofJCLy39W4xIhxWfbpskQdI9qkVi6lMWmE1wL5A0EZyxC/Zl0 + 5B/yFWgq1qDtaw2+HN4uy0UidMd8wcXhVFwcMsBto37nSD627HJisdcJkwamBqXZQvdhMnJqvJFT7Y3M + Awq03lfjwr1kPYMpIp7tV6G42R2qcgdkVa8Q7Kx3RclRBT69m4jPB5OJpHFahzVUVZdMaGBaYOqbKGsK + Q1aFAppKL6TvcaMMtuP8XRXODxAUT9+OQ5zWDvEldkjZswTpB5cj7eAyMRZdZEsmPHHuT1uIBBHPEh/0 + RiC2UBiYQYhyLGdgun/KQtp8SqhKliFjvztSy1fhM8rmzJ1YnPkjQbGo2Y2EHbF9/1LCCV/2l+DGqA4H + TgUjZe8SaHSu4rsfEx/1R6OxZz2OXFciOt+BxWYSsgZ48HW/JBv66/kjrtARW+ggUu1aQVkk0kRR+PB2 + JBGFnFoysNdRkEzwYVPXGoSukTL0/6UOPaPv4dStCPy+NxS1Xd54/4oCTdcCEJVnz2JmBi15A+sTF9Dm + 8xfLFUsmNu+ww/GboTRZCE70hdNShmPfKSUS31uMxN1E+WJE5i/EhlRrbMyah7KTnjh2IxgNV31xqFOB + 9w009vgjIlcYMCf4uJc1MGNdwjzk1awT4jEFDtiUbYeWa4GoveKF+qs+NJEfTvemYBstdXyprSBWuxDR + WhuE5c6FV8JMZNY5QtfpSShwqMNT0HDVT8xFGrIG+HxmAzN94ucip9IHfCjxPRMGegINmXiJrOopu0/6 + MpBZ44LQ3NkIYXKsCSsE77CC33ZL6EhUoqbDA/VdvgjLWsRiswiTBszWxM5BdoWPEI8hwjWL0NQTIIQ5 + E87MNXo60nVOuDCgxunraXTaeQjhjUy2JYKyrKFr90ANIWKbOw5fWYsQtTBgQcga4EFzRdQcZB3wQvRO + B0QR7Lqp2/+HjGjC+NJF8N5qhvRaexxq88VHvSqE5b2BIA2JE2kVb6Gq3R3VJCzF2k5vbMywZTFLg5a8 + AY/I2VDvVYgdG5WnN9DQvYGy0YtzVtqWNSJbz/gZcAmfCpfQKQjMsoSS2LRzHo50xujF29zG0XV4QZn2 + JotZES+xppyBWe6bran4eCBSGLBHaKYtGfBDNWdC8HKeuBmDg6eDkE6ZBmksSNgCW3c7oKjJC+f61ThM + 97uSRCWq2lbTPlCAixxp/KgBi9XhVti22038ZSIJYYB2MGfBWQloNU70RlLJTYMy0wKBxIVBNdUKFe2V + Nai4vFqIVhpRRSsXQEWONKwJkwYsXcMssa3MVRhg2EA9GTDORpqchdq/LkIHIfVNUX3ZHf7JNiw2m5A1 + wINWK0MskFy6EhE5iwUh6t+IJeVJhLBhQjnByks/RGMOXnKl37nBL2nBhAYs3w6ehaSSd0jcHpuJYNq5 + koFnxSQqSECMG8REn+C26LdyfzW4ypIGG+CXFNlbYLYi0HxsUxbVgJ1OwkSI2hZ1XetFBkyVENdHfZtF + 9VS0UiQxqS36bKJ1FfKPrYBP3PzvSMNkIeLTcLKt67Q45wDzMWelOVwIZ6UZLZ0NNtDy+W21ITgSiTZY + T5GzegrVfPiqFgjWCaifsABr4+eNOftabCEN6an4KQN8sQmuhvzczvWad+sbJpgzAXOfgX/DFZDFOXvZ + NyM2wB/wwyl/ifeE9IL6/8JzMTw3a7DWcwakiz/8KRm/AEz6D1HqNoxHF4jMAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAYdEVYdFRpdGxlAFNhbGU7RG9sbGFyO01vbmV5O/mn + uEUAAAfYSURBVFhHxZZ5UFTXEocvGhGRRUVerICACIGIiMCwg8wMzAwawYABFBRZRraHoKMsakSQTRxE + QVSCijFkEFwCTxNXXKJPUeN7Rq0k6rMqLonGBdS8ULFIWZ3uw9yZQdBo/CNd9avb98yd/vr06XPu5QDg + b9Wbmt5zGqAjfoxZf3DSmxgFH4gahNJHDX5ONPYWik/mxQn4pW7l/FH8lfc1StH69BsaBR3klbA+zjd5 + 0z4cB5Jv8mbwTqoDr4SNIJi1dv+EiBUJ+JwBihLtNwlmFDS15sKfCo2CEFzfO6m2ODz/AKSs/wbymn6E + vO23IO+zG5BZdxnmVp6CWSWHQZKxDZzClpfh84YoqkafJJjRzPoD6gqtFzx25UlY0vwTpNffhJjq6xBa + /h3Ilp8FUU4b+KY2gntsFQgztoM4/RNwkGWX4/+GolgSr50AGg8f7J24sSRGDZfX/QChq64y+Ptll9Vw + FbjOWK0aLYh0c4ssbRKlfwqCmavBxi8lGf9Py0FxXj0BNILTGvaFKxG+sgc+peQCSJaexJlXg21AohM+ + bzrKKcTLJbwYAuSbwMY/o43GUFSFV0sAjYcbeCdsKCX44hfAJ684D7KCM+CDFfCIXtVg6R41oXh5yaWw + BQ0wY1kLWAdkEm0kinaNXqsy6+UJoGnhiT1wfuYyhIkWHYbAhQdBurwdJhecheDFx0Ga/28IXnocgjIb + wSWiGNo2FUFFjQqkmSoY7ZNGtFEo2p56u0rTXpwAGg8f4pVQU6YLly47Dd4pzZCiPAyq/Reh8cAliCva + DyHZeyGt5jwE5R0BcfYhiCw6CqlrTkC1sgoSFZVg4ZFENAsUnRF6Tfnx/SeARnBaJ0Ov+HUrqdv5socp + r4Bv2i4o2HIKOjs74M69Trh7/xE8/e0pfPtDB+w5cxvEOYdAtHAfBCr2wqTMFhDPa4JPy3LByT+eaFYo + akS9hiWxfRNAIzitkZHnnHXlujMnOHW719ztcPPOfbh26yFIFf8C2cIW6HzcBc+ePYNFdedBuIjgXyC8 + Ffzn7QbfFBWEJSuhfIEcTAwN7DH2EOLUK6ZrE1CfbjzcxDNuTcWLut0nbQf88uQJ7Dt9HeGtcO7KQ2g7 + fxN+vPcErtx6pJ55D9w/Ywd4JdbDuLAimBsVfbsyLawG4w/dsiCcq8sM1SaAxg4Y1DCP2ZWr+4NPVXe7 + EBvvfzfuw/2O/8O5qw/g2MWfISCrFRoOfo/xAOTKY1q4/BNwn70RrP0zwczav3CzYvoNRbiPG3LeWp8q + 0yTADhjUCMGsijW6cDF2tndys2arhWC3Uw+saWyH33/vhq+vPWQNJ8KyK2rbQdmM2zFnD4N7q+Fjg3LB + 1EZCJbYtiBUlVyXL9qI/pFou1iRAcDP32FVVz888aPFXsGHn19DR0cG2mm/6Llb29su32Zpfvf2YwfuU + HeGCWQgPzgUTa8k2jD8WZUKqkouvZYS4+KA/kE/AVBDTG8433OSi/0CF6jQ8wTWfU3KINdy5Kw/Ymp/B + JMhmlhxh3e6foVN2gotzwNhaqML4DsRA0c4avOxDz5yiKI9G9A35BMzxddsD39T3hItecRS6urpgx5Hv + 4Cyu+dELd0AQtxm27vkvS0CuPN57zQmOZTceHdiUHzqOCO+g+DfhABdrM4vymZ5PnSyHWdI9ihvhPqOs + NnLF4T4Nx8qOa75l7yXo7u6GWz8/BtfYDTB1gQp+evAr/NLVDX7qmdOaC3DN7bDsplZimqGgcJozJUDH + r97a+Elc5WyqPGdS8MHEr1JE9vStQI3P3tVWLtML6qfkfamF43E7SbFPvdUewPc3H7EZ80bw+TUnNXDW + cGzNRU0YbxzKuuRDV5ZAaaQbgytjPfGWM5wvc1QqZA716BvRAB25xijb8WGLt8kWtTA4dbw0/xR8vP86 + HL14l51wyWtPgerIdajd8y1EFRzA0j8HtxLtwDjjUSNQ5mXRgk7JeAtKZoAy1osrjxagyxnIA8b+M1vm + cAz94TTAH73UpfaOIYqG4KwmBg/+6AQE5bYh/CDu/55uD8Bu1y07v9VMrIQ78f/OKILTgTasONrzbIrY + MQZ9fYKXRrqiyxnM8bVJz5bYn0DfjAbI+CSGoRztRGnbhWnb8BzAFwvBaavNR3iWttsZXNNwwl34vwko + Cshet6ihSz5wrc2eOqEafSOCF4e7oMsZJfnZFM0T2raizyrAG58EDTrZ+CU2ByR9rD7be2bO4Fh2/oRj + ZR8duBufn4jSwLFF8MLpxwe+G10Y4foN+v+gcbXM54lsD8Z5Wi5Fnz7Tehk9QEGojM6W7jE7feLWaeGa + sm9gcGMr4ef4HNVV86FBcHUCFGtUYcTEO0HvjRKhT29BY88xwyW5Uvt75kb6dnhP/ac15/BiuvBJ0Ixc + 3nYO3+0RXaED58se2IK/07mugZuMCWNwnSSMU4V2pfMlDvTs+Cg3i4W5Uru7wY5mEXg/VP2M1saFFnBx + RV+SyydBwV1HOkxpmTitUBdO6+eOMlc/pzcj5zOunwQGmg4Z9E5WsN0Xy953hEyRbbvvmOFSHKddxy+V + 1hxClnL2klzOVqSg215JDB8r2TnSaSauuYi6vc/MeekmoAbwMaxRb6PYB4nO7y81PglqTFsUfe3Sle7Z + t50u7K/oVYySYB+nKDo16Ur3bwwnvY5RIryY9Rfw9QTcHxcOclAl7kcyAAAAAElFTkSuQmCC + + + + 51 + + \ No newline at end of file diff --git a/FLSystem/Forms/GroupForm.Designer.cs b/FLSystem/Forms/GroupForm.Designer.cs new file mode 100644 index 0000000..456fe48 --- /dev/null +++ b/FLSystem/Forms/GroupForm.Designer.cs @@ -0,0 +1,215 @@ +namespace FLSystem.Forms +{ + partial class GroupForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GroupForm)); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.label7 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.Location = new System.Drawing.Point(0, 94); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(616, 340); + this.gridControl1.TabIndex = 6; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn6}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView1_RowClick); + this.gridView1.Click += new System.EventHandler(this.gridView1_DoubleClick); + this.gridView1.DoubleClick += new System.EventHandler(this.gridView1_DoubleClick); + // + // gridColumn1 + // + this.gridColumn1.Caption = "群号"; + this.gridColumn1.FieldName = "groupid"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 281; + // + // gridColumn6 + // + this.gridColumn6.Caption = "群名"; + this.gridColumn6.FieldName = "groupname"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 1; + this.gridColumn6.Width = 283; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.label7); + this.groupControl1.Controls.Add(this.hyperlinkLabelControl1); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(617, 88); + this.groupControl1.TabIndex = 8; + this.groupControl1.Text = "搜索条件"; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(388, 38); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl1.TabIndex = 16; + this.hyperlinkLabelControl1.Text = "刷新通讯录"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(62, 38); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(36, 14); + this.labelControl1.TabIndex = 15; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(474, 32); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(79, 27); + this.simpleButton1.TabIndex = 14; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit3 + // + this.comboBoxEdit3.EditValue = "全部平台"; + this.comboBoxEdit3.Location = new System.Drawing.Point(272, 35); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { + "全部平台"}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit3.TabIndex = 11; + this.comboBoxEdit3.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit3_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(101, 35); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(165, 20); + this.textEdit1.TabIndex = 10; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.ForeColor = System.Drawing.Color.Blue; + this.label7.Location = new System.Drawing.Point(87, 65); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(371, 14); + this.label7.TabIndex = 24; + this.label7.Text = "注:列表中没有您要设置的群时,请给群发条信息,即可获取该群信息"; + // + // GroupForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(617, 436); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.gridControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "GroupForm"; + this.Text = "选择群"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.GroupForm_FormClosing); + this.Load += new System.EventHandler(this.GroupForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private System.Windows.Forms.Label label7; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/GroupForm.cs b/FLSystem/Forms/GroupForm.cs new file mode 100644 index 0000000..1393727 --- /dev/null +++ b/FLSystem/Forms/GroupForm.cs @@ -0,0 +1,238 @@ +using Api.Framework.Model; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class GroupForm : BaseForm + { + public class Groups + { + //public WXClientImpl_IPAD Client { get; private set; } + //public Friend Friend { get; private set; } + + //public Groups(WXClientImpl_IPAD Client, Friend Friend) + //{ + // this.Client = Client; + // this.Friend = Friend; + //} + + public WeixinBase Client { get; private set; } + public Friend Friend { get; private set; } + + public Groups(WeixinBase Client, Friend Friend) + { + this.Client = Client; + this.Friend = Friend; + } + public string groupid { get; set; } + public string groupname { get; set; } + } + + public GroupForm() + { + InitializeComponent(); + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + #endregion + + } + + private void GroupForm_Load(object sender, EventArgs e) + { + try + { + if (groups != null && groups.Count != 0) + { + List objs = new List(); + if (comboBoxEdit3.SelectedIndex != 0) + groups = groups.Where(f => f.Client.WeixinHao == comboBoxEdit3.Text).ToList(); + foreach (var item in groups) + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) + objs.Add(new { groupid = item.Friend.UserName, groupname = item.Friend.NickName }); + else if (item.Friend.UserName.Contains(textEdit1.Text) || item.Friend.NickName.Contains(textEdit1.Text)) + objs.Add(new { groupid = item.Friend.UserName, groupname = item.Friend.NickName }); + } + gridControl1.DataSource = objs; + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + ShowError(ex); + } + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private async void comboBoxEdit3_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + List> clients = null; + if (comboBoxEdit3.SelectedIndex == 0) + clients = Chat.Framework.ChatClient.WXClient.Where(f => /*f.Value.WeixinType == WeixinType.Grpc微信 &&*/ f.Value.Status == WxStatus.在线).ToList(); + else + clients = Chat.Framework.ChatClient.WXClient.Where(f => f.Value.Status == WxStatus.在线 /*&& f.Value.WeixinType == WeixinType.Grpc微信*/ && f.Value.WeixinHao == comboBoxEdit3.Text).ToList(); + + try + { + await Task.Run(() => GetGroup(clients), tokenSource.Token); + } + catch (Exception) + { } + + if (clients != null && clients.Count > 0) GroupForm_Load(null, null); + } + catch (Exception ex) + { + if (!this.IsDisposed) + ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + GroupForm_Load(null, null); + } + + + static List groups = new List();//缓存 + + /// + /// 获取群集合 + /// + /// + /// + public static void GetGroup(List> clients) + { + Task.Delay(30000); + groups = new List();//缓存 + foreach (var client in clients) + { + if (client.Value.GetType() == typeof(WXClientImpl_IPAD)) + { + var ipad = client.Value as WXClientImpl_IPAD; + if (ipad == null || ipad.Friends == null) continue; + var friends = ipad.Friends.Values.Where(f => f.UserName.EndsWith("@chatroom")).ToList(); + + foreach (var item in friends) + { + groups.Add(new Groups(ipad, item)); + } + } + else if (client.Value.GetType() == typeof(WXClientImpl_HOOK)) + { + var ipad = client.Value as WXClientImpl_HOOK; + if (ipad == null || ipad.Friends == null) continue; + var friends = ipad.Friends.Values.Where(f => f.UserName.EndsWith("@chatroom")).ToList(); + + foreach (var item in friends) + { + groups.Add(new Groups(ipad, item)); + } + } + } + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + Loding.ShowWaitForm();//开启等待 + + List> clients = null; + if (comboBoxEdit3.SelectedIndex == 0)//全部机器人 + clients = Chat.Framework.ChatClient.WXClient.Where(f => /*f.Value.WeixinType == WeixinType.Grpc微信 &&*/ f.Value.Status == WxStatus.在线).ToList(); + else + clients = Chat.Framework.ChatClient.WXClient.Where(f => f.Value.WeixinHao == comboBoxEdit3.Text /*&& f.Value.WeixinType == WeixinType.Grpc微信*/ && f.Value.Status == WxStatus.在线).ToList(); + + if (clients != null && clients.Count != 0) + { + foreach (var item in clients) + { + var ipad = item.Value as WXClientImpl_IPAD; + if (ipad.Status == WxStatus.在线 && ipad.Friends.Count == 0 && !ipad.IsRefreshContact) + { + ipad.RefreshContact(); + } + } + ShowSuccess("刷新通讯录,请等待"); + } + else + throw new Exception("没有在线的微信号,或者没有符合的微信号"); + } + catch (Exception ex) + { + if (!this.IsDisposed) + ShowError(ex); + } + finally + { + Loding.CloseWaitForm(); + } + } + + public fl_group_person group = null; + + void change_user() + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var groupid = this.gridView1.GetRowCellValue(rows[0], "groupid").ToString();//获取列的数据 + var groupname = this.gridView1.GetRowCellValue(rows[0], "groupname").ToString();//获取列的数据 + + group = new fl_group_person() { groupid = groupid, groupname = groupname }; + this.DialogResult = DialogResult.OK; + } + } + catch (Exception ex) + { } + } + + private void gridView1_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + change_user(); + } + + private void gridView1_DoubleClick(object sender, EventArgs e) + { + change_user(); + } + + private void GroupForm_FormClosing(object sender, FormClosingEventArgs e) + { + tokenSource.Cancel(); + } + } +} diff --git a/FLSystem/Forms/GroupForm.resx b/FLSystem/Forms/GroupForm.resx new file mode 100644 index 0000000..bc5d4fb --- /dev/null +++ b/FLSystem/Forms/GroupForm.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/FLSystem/Forms/LeavingMessageForm.Designer.cs b/FLSystem/Forms/LeavingMessageForm.Designer.cs new file mode 100644 index 0000000..2a87cfe --- /dev/null +++ b/FLSystem/Forms/LeavingMessageForm.Designer.cs @@ -0,0 +1,132 @@ +namespace FLSystem.Forms +{ + partial class LeavingMessageForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LeavingMessageForm)); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.label3 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(12, 12); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox1.Size = new System.Drawing.Size(449, 224); + this.textBox1.TabIndex = 0; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(173, 280); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(111, 29); + this.simpleButton1.TabIndex = 1; + this.simpleButton1.Text = "传朕旨意"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ForeColor = System.Drawing.Color.Gray; + this.label1.Location = new System.Drawing.Point(59, 242); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(367, 14); + this.label1.TabIndex = 2; + this.label1.Text = "此处留言仅供技术团队分析,并不予回复,如有售后问题请联系客服"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.ForeColor = System.Drawing.Color.Gray; + this.label2.Location = new System.Drawing.Point(62, 261); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(151, 14); + this.label2.TabIndex = 2; + this.label2.Text = "如有紧急情况请联系邮箱:"; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline; + this.linkLabel1.Location = new System.Drawing.Point(209, 261); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(117, 14); + this.linkLabel1.TabIndex = 3; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "fl_system@163.com"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.ForeColor = System.Drawing.Color.Gray; + this.label3.Location = new System.Drawing.Point(331, 261); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(89, 14); + this.label3.TabIndex = 2; + this.label3.Text = "(点击即可复制)"; + // + // LeavingMessageForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(471, 321); + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.textBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "LeavingMessageForm"; + this.Text = "建议反馈"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Label label3; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/LeavingMessageForm.cs b/FLSystem/Forms/LeavingMessageForm.cs new file mode 100644 index 0000000..3c923f0 --- /dev/null +++ b/FLSystem/Forms/LeavingMessageForm.cs @@ -0,0 +1,54 @@ +using Api.Framework; +using Api.Framework.Model; +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class LeavingMessageForm : BaseForm + { + public static List MessageMd5 = new List(); + public LeavingMessageForm() + { + InitializeComponent(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(this.textBox1.Text) || this.textBox1.Text.Length < 10) throw new Exception("陛下,您的圣旨内容太短~"); + string msg = $@"用户账号:{Grant.Framework.GrantClient.Get().accounts.username} +⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇ +{this.textBox1.Text}"; + var md5 = CsharpHttpHelper.HttpHelper.ToMD5(msg); + if (!MessageMd5.Contains(md5)) + { + //ApiClient.SendNewDingdingMessage(msg, "https://oapi.dingtalk.com/robot/send?access_token=12c07d749de435a3ee3ba7b9fdfcb1ca3db4dad18a9ab6201510d7d665656401"); + ApiClient.SendNoticeMessage(new fl_noticeapi_info() { api_location = "https://open.feishu.cn/open-apis/bot/hook/e8cb9f6034e947cf9f2d560af1331785", notice_apitype = NoticeApiType.飞书机器人API, name = "飞书_反-馈." }, msg); + MessageMd5.Add(md5); + } + ShowSuccess("已下达旨意!", "友情提示"); + this.Close(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void linkLabel1_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e) + { + try + { + Clipboard.SetDataObject(linkLabel1.Text); + ShowSuccessAutoClose("复制成功"); + } + catch (Exception) + { } + } + + } +} \ No newline at end of file diff --git a/FLSystem/Forms/LeavingMessageForm.resx b/FLSystem/Forms/LeavingMessageForm.resx new file mode 100644 index 0000000..aa716b0 --- /dev/null +++ b/FLSystem/Forms/LeavingMessageForm.resx @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/FLSystem/Forms/LockForm.Designer.cs b/FLSystem/Forms/LockForm.Designer.cs new file mode 100644 index 0000000..72aa881 --- /dev/null +++ b/FLSystem/Forms/LockForm.Designer.cs @@ -0,0 +1,151 @@ +namespace FLSystem.Forms +{ + partial class LockForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.lb_LoginName = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.panel1 = new System.Windows.Forms.Panel(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(76, 181); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(142, 28); + this.simpleButton1.TabIndex = 6; + this.simpleButton1.Text = "立即解锁 >>"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(61, 120); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Properties.Appearance.Font = new System.Drawing.Font("Tahoma", 15F); + this.textEdit1.Properties.Appearance.Options.UseFont = true; + this.textEdit1.Properties.PasswordChar = '*'; + this.textEdit1.Size = new System.Drawing.Size(347, 30); + this.textEdit1.TabIndex = 7; + // + // lb_LoginName + // + this.lb_LoginName.Appearance.Font = new System.Drawing.Font("Tahoma", 20F); + this.lb_LoginName.Appearance.ForeColor = System.Drawing.Color.RoyalBlue; + this.lb_LoginName.Appearance.Options.UseFont = true; + this.lb_LoginName.Appearance.Options.UseForeColor = true; + this.lb_LoginName.Location = new System.Drawing.Point(61, 38); + this.lb_LoginName.Name = "lb_LoginName"; + this.lb_LoginName.Size = new System.Drawing.Size(81, 33); + this.lb_LoginName.TabIndex = 8; + this.lb_LoginName.Text = "先森吳"; + // + // labelControl1 + // + this.labelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 15F, System.Drawing.FontStyle.Bold); + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseFont = true; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(146, 78); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(105, 24); + this.labelControl1.TabIndex = 8; + this.labelControl1.Text = "正在锁定中"; + // + // panel1 + // + this.panel1.Controls.Add(this.pictureBox1); + this.panel1.Controls.Add(this.simpleButton2); + this.panel1.Controls.Add(this.simpleButton1); + this.panel1.Controls.Add(this.textEdit1); + this.panel1.Controls.Add(this.labelControl1); + this.panel1.Controls.Add(this.lb_LoginName); + this.panel1.Location = new System.Drawing.Point(123, 124); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(433, 236); + this.panel1.TabIndex = 10; + // + // pictureBox1 + // + this.pictureBox1.Image = global::FLSystem.Properties.Resources.锁; + this.pictureBox1.Location = new System.Drawing.Point(110, 74); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(28, 28); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureBox1.TabIndex = 9; + this.pictureBox1.TabStop = false; + // + // simpleButton2 + // + this.simpleButton2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton2.Location = new System.Drawing.Point(247, 181); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(142, 28); + this.simpleButton2.TabIndex = 6; + this.simpleButton2.Text = "最小化"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // LockForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.simpleButton2; + this.ClientSize = new System.Drawing.Size(803, 620); + this.Controls.Add(this.panel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.MinimumSize = new System.Drawing.Size(343, 257); + this.Name = "LockForm"; + this.Text = "LockForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LockForm_FormClosing); + this.Load += new System.EventHandler(this.LockForm_Load); + this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Main_MouseDown); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl lb_LoginName; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.PictureBox pictureBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/LockForm.cs b/FLSystem/Forms/LockForm.cs new file mode 100644 index 0000000..b110d50 --- /dev/null +++ b/FLSystem/Forms/LockForm.cs @@ -0,0 +1,101 @@ +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class LockForm : BaseForm + { + public LockForm(Size size) + { + InitializeComponent(); + this.Size = size; + //433, 236 + + this.panel1.Location = new Point(((size.Width - panel1.Width) / 2),((size.Height - panel1.Height) / 2)); + } + + private void LockForm_Load(object sender, EventArgs e) + { + try + { + var account = Grant.Framework.GrantClient.Get().accounts; + lb_LoginName.Text = "账号:" + account.username; + //labelControl1.Text = Grant.Framework.GrantClient.Get().About["title"].ToString() + " 正在锁定中"; + labelControl1.Text = "正在锁定中"; + } + catch (Exception ex) + { } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text.Trim())) + throw new Exception("请输入密码"); + string pass = HttpExtend.DESEncrypt(textEdit1.Text.Trim(), "12345678", "12378946"); + var Config = new Api.Framework.Tools.IniHelper(HttpExtend.MapFile("系统配置.ini", "Config")); + var passData = Config.GetValue("帐号信息", "密码"); + if (pass == passData) + { + isInputRightPwd = true; + this.DialogResult = DialogResult.OK; + } + else + throw new Exception("密码错误"); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "温馨提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + + #region 控制无边框窗体的移动 + //using System.Runtime.InteropServices; + [DllImport("user32.dll")] + public static extern bool ReleaseCapture(); + [DllImport("user32.dll")] + public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam); + + private void Main_MouseDown(object sender, MouseEventArgs e) + { + //常量 + int WM_SYSCOMMAND = 0x0112; + + //窗体移动 + int SC_MOVE = 0xF010; + int HTCAPTION = 0x0002; + + ReleaseCapture(); + SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); + } + #endregion + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.WindowState = FormWindowState.Minimized; + } + + private bool isInputRightPwd = false; + + private void LockForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (!isInputRightPwd) + { + e.Cancel = true; + this.WindowState = FormWindowState.Minimized; + } + } + } +} diff --git a/FLSystem/Forms/LockForm.resx b/FLSystem/Forms/LockForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/LockForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/LoginQQForm.Designer.cs b/FLSystem/Forms/LoginQQForm.Designer.cs new file mode 100644 index 0000000..1709c95 --- /dev/null +++ b/FLSystem/Forms/LoginQQForm.Designer.cs @@ -0,0 +1,142 @@ +namespace FLSystem.Forms +{ + partial class LoginQQForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(51, 43); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(36, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "账号:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(51, 114); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(36, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "密码:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(93, 40); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(161, 22); + this.textBox1.TabIndex = 2; + this.textBox1.Text = "123495534"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(93, 111); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(161, 22); + this.textBox2.TabIndex = 3; + this.textBox2.Text = "qq12345554"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(139, 169); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 23); + this.simpleButton1.TabIndex = 4; + this.simpleButton1.Text = "登陆"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(93, 259); + this.textBox3.Name = "textBox3"; + this.textBox3.Size = new System.Drawing.Size(177, 22); + this.textBox3.TabIndex = 5; + this.textBox3.Text = "1747423426"; + // + // textBox4 + // + this.textBox4.Location = new System.Drawing.Point(93, 299); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(177, 22); + this.textBox4.TabIndex = 6; + this.textBox4.Text = "Test"; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(126, 330); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 7; + this.button1.Text = "发送消息"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // LoginQQForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(315, 364); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox4); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.labelControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "LoginQQForm"; + this.Text = "登陆QQ"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox textBox2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/LoginQQForm.cs b/FLSystem/Forms/LoginQQForm.cs new file mode 100644 index 0000000..d0b5850 --- /dev/null +++ b/FLSystem/Forms/LoginQQForm.cs @@ -0,0 +1,34 @@ +using Chat.Framework.QQSdk; +using Chat.Framework.QQSdk.AndroidQQ; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class LoginQQForm : BaseForm + { + public LoginQQForm() + { + InitializeComponent(); + } + + QQBase test = new AndroidQQ(); + private void simpleButton1_Click(object sender, EventArgs e) + { + test.Login(this.textBox1.Text,this.textBox2.Text); + } + + private void button1_Click(object sender, EventArgs e) + { + test.SendMessage(uint.Parse(this.textBox3.Text),this.textBox4.Text); + } + } +} diff --git a/FLSystem/Forms/LoginQQForm.resx b/FLSystem/Forms/LoginQQForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/LoginQQForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/LoginWechat62Data.Designer.cs b/FLSystem/Forms/LoginWechat62Data.Designer.cs new file mode 100644 index 0000000..759e9d4 --- /dev/null +++ b/FLSystem/Forms/LoginWechat62Data.Designer.cs @@ -0,0 +1,139 @@ +namespace FLSystem.Forms +{ + partial class LoginWechat62Data + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.Location = new System.Drawing.Point(12, 75); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(948, 394); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.AppearancePrint.Row.Options.UseTextOptions = true; + this.gridView1.AppearancePrint.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + // + // gridColumn1 + // + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "账号"; + this.gridColumn1.FieldName = "username"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 164; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Near; + this.gridColumn2.Caption = "登陆结果"; + this.gridColumn2.FieldName = "message"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 763; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(236, 20); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(134, 27); + this.simpleButton1.TabIndex = 1; + this.simpleButton1.Text = "绑定数据源"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(465, 20); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(134, 27); + this.simpleButton2.TabIndex = 2; + this.simpleButton2.Text = "开始批量登陆"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton3 + // + this.simpleButton3.Location = new System.Drawing.Point(678, 20); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(134, 27); + this.simpleButton3.TabIndex = 3; + this.simpleButton3.Text = "复制登陆失败账号"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // LoginWechat62Data + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(972, 481); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.gridControl1); + this.Name = "LoginWechat62Data"; + this.Text = "LoginWechat62Data"; + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/LoginWechat62Data.cs b/FLSystem/Forms/LoginWechat62Data.cs new file mode 100644 index 0000000..4910097 --- /dev/null +++ b/FLSystem/Forms/LoginWechat62Data.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using System.Threading; + +namespace FLSystem.Forms +{ + public partial class LoginWechat62Data:BaseForm + { + public LoginWechat62Data() + { + InitializeComponent(); + } + + class view_62data + { + public string username { get; set; } + public string userpass { get; set; } + public string user62data { get; set; } + public string message { get; set; } + } + List list = new List(); + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog file = new OpenFileDialog(); + file.Filter = "(*.txt)|*.txt"; + file.ShowDialog(); + list.Clear(); + if (!string.IsNullOrEmpty(file.FileName)) + { + var text = System.IO.File.ReadAllText(file.FileName); + var data62 = text.Split(new string[] { "\r\n" }, StringSplitOptions.None); + + foreach (var item in data62) + { + var data = item.Split(new string[] { "----" }, StringSplitOptions.None); + if (data.Length >=3) + list.Add(new view_62data() { username = data[0], userpass = data[1], user62data = data[2], message = string.Empty }); + } + this.gridControl1.DataSource = list; + } + + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + Thread login_thread = null; + bool isrun = false; + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + if (login_thread != null) + { + try + { + isrun = false; + login_thread.Abort(); + } + catch (Exception) + { + + + } + } + if (this.simpleButton2.Text == "开始批量登陆") + { + this.simpleButton2.Text = "停止批量登陆"; + isrun = true; + login_thread = new Thread(new ThreadStart(delegate + { + foreach (var item in list) + { + if (!isrun) return; + try + { + var msg = Chat.Framework.ChatClient.LoginWeixin(item.username, item.username, item.userpass, item.user62data); + if (string.IsNullOrEmpty(msg)) item.message = "登陆成功"; + else item.message = msg; + } + catch (Exception ex) + { + item.message = ex.Message; + } + Thread.Sleep(10); + } + })); + + login_thread.Start(); + } + else this.simpleButton2.Text = "开始批量登陆"; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + try + { + StringBuilder sb = new StringBuilder("登陆失败的账号有:\r\n"); + int number = 0; + foreach (var item in list) + { + if (!string.IsNullOrEmpty(item.message) && item.message != "登陆成功") + { + number++; + if (item.message.Contains("该微信帐号因批量或者使用非法软件注册被限制登录,如需继续使用,请轻触“确定”申请解除限制。")) + { + sb.Append($"{item.username}----{item.userpass}----{item.user62data}----该微信帐号因批量或者使用非法软件注册被限制登录,如需继续使用,请轻触“确定”申请解除限制。"); + } + else + { + sb.Append($"{item.username}----{item.message}"); + } + sb.Append("\r\n"); + + } + } + + Clipboard.SetDataObject(sb.ToString()+"\r\n\r\n共计:"+number+"个"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + + } + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/LoginWechat62Data.resx b/FLSystem/Forms/LoginWechat62Data.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/LoginWechat62Data.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/MemberForm.Designer.cs b/FLSystem/Forms/MemberForm.Designer.cs new file mode 100644 index 0000000..dc2a5f6 --- /dev/null +++ b/FLSystem/Forms/MemberForm.Designer.cs @@ -0,0 +1,216 @@ +namespace FLSystem.Forms +{ + partial class MemberForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MemberForm)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(617, 73); + this.groupControl1.TabIndex = 11; + this.groupControl1.Text = "搜索条件"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(90, 37); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(36, 14); + this.labelControl1.TabIndex = 15; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(440, 31); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(79, 27); + this.simpleButton1.TabIndex = 14; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit3 + // + this.comboBoxEdit3.EditValue = "全部平台"; + this.comboBoxEdit3.Location = new System.Drawing.Point(315, 34); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { + "全部平台"}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(108, 20); + this.comboBoxEdit3.TabIndex = 11; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(129, 34); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(177, 20); + this.textEdit1.TabIndex = 10; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 384); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(617, 35); + this.pageControl1.TabIndex = 10; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(0, 79); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(616, 303); + this.gridControl1.TabIndex = 9; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn2, + this.gridColumn1, + this.gridColumn6}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView1_RowClick); + this.gridView1.Click += new System.EventHandler(this.gridView1_DoubleClick); + this.gridView1.DoubleClick += new System.EventHandler(this.gridView1_DoubleClick); + // + // gridColumn2 + // + this.gridColumn2.Caption = "编号"; + this.gridColumn2.FieldName = "id"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 0; + // + // gridColumn1 + // + this.gridColumn1.Caption = "用户账号"; + this.gridColumn1.FieldName = "username"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 227; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 2; + this.gridColumn6.Width = 258; + // + // MemberForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(617, 419); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MemberForm"; + this.Text = "选择用户"; + this.Load += new System.EventHandler(this.MemberForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/MemberForm.cs b/FLSystem/Forms/MemberForm.cs new file mode 100644 index 0000000..3adf9a4 --- /dev/null +++ b/FLSystem/Forms/MemberForm.cs @@ -0,0 +1,94 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class MemberForm : BaseForm + { + public MemberForm() + { + InitializeComponent(); + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + this.comboBoxEdit3.Properties.Items.AddRange(objList); + #endregion + + } + + private void MemberForm_Load(object sender, EventArgs e) + { + try + { + this.pageControl1.Bind(delegate (int page, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var map = session.NewParamMap(); + map.setPageParamters(page, pagesize); + string where = string.Empty; + if (!string.IsNullOrEmpty(this.textEdit1.Text)) + where = " where (username like '%" + textEdit1.Text.Trim() + "%' or usernick like '%" + textEdit1.Text.Trim() + "%')"; + if (comboBoxEdit3.SelectedIndex != 0) + where += string.IsNullOrWhiteSpace(where) ? "where robot_name = "+ comboBoxEdit3.Text : " and robot_name = "+ comboBoxEdit3.Text; + + var rest = session.FindPage($"select * from fl_member_info {where} ", map); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = rest.DataList, Total = rest.Total }; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = null, Total = 0 }; + + }, this.gridControl1, 40, true, true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + pageControl1.Go(sender, e); + } + + public fl_member_info member = null; + + void change_user() + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + member = this.gridView1.GetRow(rows[0]) as fl_member_info; + this.DialogResult = DialogResult.OK; + } + } + + private void gridView1_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + change_user(); + } + + private void gridView1_DoubleClick(object sender, EventArgs e) + { + change_user(); + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/MemberForm.resx b/FLSystem/Forms/MemberForm.resx new file mode 100644 index 0000000..bc5d4fb --- /dev/null +++ b/FLSystem/Forms/MemberForm.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/FLSystem/Forms/OneKeyExchangeForm.Designer.cs b/FLSystem/Forms/OneKeyExchangeForm.Designer.cs new file mode 100644 index 0000000..2dd10d6 --- /dev/null +++ b/FLSystem/Forms/OneKeyExchangeForm.Designer.cs @@ -0,0 +1,76 @@ +namespace FLSystem.Forms +{ + partial class OneKeyExchangeForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.SuspendLayout(); + // + // progressBar1 + // + this.progressBar1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.progressBar1.Location = new System.Drawing.Point(0, 420); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(544, 33); + this.progressBar1.TabIndex = 22; + // + // richTextBox1 + // + this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.richTextBox1.Location = new System.Drawing.Point(0, 0); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.ForcedVertical; + this.richTextBox1.Size = new System.Drawing.Size(544, 420); + this.richTextBox1.TabIndex = 23; + this.richTextBox1.Text = ""; + // + // OneKeyExchangeForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(544, 453); + this.Controls.Add(this.richTextBox1); + this.Controls.Add(this.progressBar1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "OneKeyExchangeForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "审核进度日志"; + this.Load += new System.EventHandler(this.OneKeyExchangeForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.RichTextBox richTextBox1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/OneKeyExchangeForm.cs b/FLSystem/Forms/OneKeyExchangeForm.cs new file mode 100644 index 0000000..37e331b --- /dev/null +++ b/FLSystem/Forms/OneKeyExchangeForm.cs @@ -0,0 +1,419 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.IPAD; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class OneKeyExchangeForm : BaseForm + { + List exchangeList = null; + string name = string.Empty; + public OneKeyExchangeForm(List exchangeList, string name) + { + InitializeComponent(); + this.exchangeList = exchangeList; + this.name = name; + } + + private void OneKeyExchangeForm_Load(object sender, EventArgs e) + { + Task.Run(new Action(() => + { + Run(); + })); + } + + private object lock_obj4 = new object(); + private void AddJindu(string text = "", int max = 0) + { + base.UpdateUI(() => + { + try + { + lock (lock_obj4) + { + if (!string.IsNullOrEmpty(text) && max == 0) + { + richTextBox1.AppendText(text + "\r\n"); + } + else if (!string.IsNullOrEmpty(text) && max != 0) + { + richTextBox1.AppendText(text + "\r\n"); + this.progressBar1.Value = 0; + this.progressBar1.Maximum = max; + } + else + { + if (this.progressBar1.Value < this.progressBar1.Maximum) this.progressBar1.Value++; + richTextBox1.AppendText($"一共{this.progressBar1.Maximum}个任务,正在执行第:{this.progressBar1.Value}个\r\n"); + } + richTextBox1.Focus(); + } + Application.DoEvents(); + } + catch (Exception) + { } + }); + } + + public void Run() + { + var pointConfig = ApiClient.GetPointManageConfig(); + if (pointConfig == null) + { + AddJindu($@"获取基础配置超时,请稍后重试"); + return; + } + + AddJindu("获取基础配置完成"); + + switch (name) + { + case "商户支付": + Shanghu(); + break; + case "微信支付": + WeixinPay(); + break; + case "没收兑换": + MoShou(); + break; + case "退回兑换": + TuiHui(); + break; + case "已审核": + YiShen(); + break; + default: + break; + } + AddJindu("\r\n所有操作执行完毕~!!!"); + } + + /// + /// 已审核 + /// + private void YiShen() + { + AddJindu("执行已审核", exchangeList.Count); + foreach (var exchange in exchangeList) + { + try + { + exchange.state = ApplyType.已审核; + exchange.remark = "一键审核【已审核】"; + Update(exchange); + } + catch (Exception ex) + { + AddJindu(ex.Message); + } + finally + { + AddJindu(); + Thread.Sleep(200); + } + } + } + + /// + /// 退回 + /// + private void TuiHui() + { + AddJindu("执行退回兑换", exchangeList.Count); + foreach (var exchange in exchangeList) + { + try + { + exchange.state = ApplyType.退回兑换; + exchange.remark = "一键审核【退回兑换】"; + Update(exchange); + } + catch (Exception ex) + { + AddJindu(ex.Message); + } + finally + { + AddJindu(); + Thread.Sleep(200); + } + } + } + + /// + /// 没收 + /// + private void MoShou() + { + AddJindu("执行没收兑换", exchangeList.Count); + foreach (var exchange in exchangeList) + { + try + { + exchange.state = ApplyType.没收兑换; + exchange.remark = "一键审核【没收兑换】"; + Update(exchange); + } + catch (Exception ex) + { + AddJindu(ex.Message); + } + finally + { + AddJindu(); + Thread.Sleep(200); + } + } + } + + /// + /// 微信支付 + /// + private void WeixinPay() + { + var session = ApiClient.GetSession(); + + AddJindu("执行微信支付", exchangeList.Count); + + foreach (var exchange in exchangeList) + { + try + { + if (exchange.chattype != Api.Framework.SDK.ChatType.微信) + throw new Exception($"平台:{exchange.chattype},{exchange.robot_nick}({exchange.robot_name}),暂时不支持自动转账,跳过该兑换"); + + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == exchange.robot_name); + if (client == null) throw new Exception(exchange.robot_name + ",该帐号没有登录!"); + if (client.WeixinType != Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信) + throw new Exception($"平台:{exchange.chattype},{exchange.robot_nick}({exchange.robot_name}),您当前登录的微信版本,暂不支持自动转账,跳过该兑换"); + + var robot = session.FindRobotInfo(exchange.robot_name, exchange.chattype); + if (robot == null) throw new Exception($"{exchange.robot_nick}({exchange.robot_name}),机器人数据获取异常,跳过该兑换"); + var passInfo = session.FindWeixinpassword(robot.id);//微信自动转账 + + if (!string.IsNullOrWhiteSpace(exchange.groupid)) + { + var user = client.GetContact(exchange.username); + if (user == null) throw new Exception($"{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username})兑换用户数据异常,跳过该兑换"); + if (!string.IsNullOrWhiteSpace(user.Ticket))//非好友 + throw new Exception($"{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}),该用户为非好友,请使用支付宝转账,跳过该兑换"); + } + + if (passInfo != null && !string.IsNullOrEmpty(passInfo.password))//是否设置了账号密码 + { + var bank = passInfo.GetBank(); + var pointConfig = ApiClient.GetPointManageConfig(); + if (pointConfig == null) + throw new Exception("获取积分管理配置为空"); + string result = client.SendPay(exchange.username, pointConfig.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", exchange.point.ToString("0.00")), (int)((decimal)exchange.point * 100m), passInfo.password, 1, (PayType)Enum.ToObject(typeof(PayType), (int)pointConfig.Exchange_PayType), bank); + if (!string.IsNullOrEmpty(result)) throw new Exception($"{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}), {(bank != null ? "银行" : "余额")},转账:{exchange.point.ToString("0.00")},{result}"); + exchange.state = ApplyType.已审核; + exchange.check_time = DateTime.Now; + exchange.remark = "一键审核【微信支付】"; + Update(exchange); + } + else + throw new Exception($@"{robot.nick}({robot.name}),尚未设置支付密码! +请在机器人管理中,右击机器人设置密码!"); + } + catch (Exception ex) + { + AddJindu($"{ex.Message}"); + } + finally + { + AddJindu(); + Thread.Sleep(200); + } + } + } + + /// + /// 商户支付 + /// + private void Shanghu() + { + try + { + AddJindu("执行商户支付", exchangeList.Count); + var pointConfig = ApiClient.GetPointManageConfig(); + if (pointConfig == null) + throw new Exception("获取积分管理配置为空."); + foreach (var exchange in exchangeList) + { + try + { + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == exchange.robot_name); + + if (client == null || client.Status != Chat.Framework.WXSdk.WxStatus.在线) + throw new Exception($"{exchange.robot_nick}({exchange.robot_name}),该机器人没有登录,跳过该兑换"); + + var db = ApiClient.GetSession(); + var robot = db.FindRobotInfo(exchange.robot_name, exchange.chattype); + if (robot == null) + throw new Exception($"{exchange.robot_nick}({exchange.robot_name}),机器人数据获取异常,跳过该兑换"); + + if (client != null && !string.IsNullOrWhiteSpace(exchange.groupid)) + { + var user = client.GetContact(exchange.username); + if (user == null) + throw new Exception($"机器人:{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}),未能获取该用户数据,跳过该兑换"); + + if (!string.IsNullOrWhiteSpace(user.Ticket) && user.Ticket != "-1" && user.Ticket != "0")//非好友 + throw new Exception($"机器人:{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}),该用户为非好友或已拉黑,请使用支付宝转账,跳过该兑换"); + } + + if (string.IsNullOrWhiteSpace(pointConfig.ExchangeCommercialPayTip)) + throw new Exception($"机器人:{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}),商户付款通知提示语不能为空,请到积分兑换插件中设置,跳过该兑换"); + + else if (!pointConfig.ExchangeCommercialPayTip.Contains("[领取地址]")) + throw new Exception($@"机器人:{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}), +商户付款通知提示语中不包含 [领取地址] 变量,请到积分兑换插件中设置,请到积分兑换插件中设置,跳过该兑换"); + + + EventClient.OnEvent(this, $"机器人:{robot.nick}【{robot.uin}】一键审核【商户付款】用户:{exchange.usernick}({exchange.username}) begin:{DateTime.Now.ToString("u")}"); + + var mess = string.Empty; + var ispaid = false; + object appinfo = null; + + var ExchangePacketTitle = @"兑换成功:[兑换金额]"; + if (!string.IsNullOrWhiteSpace(pointConfig.ExchangePacketTitle)) + ExchangePacketTitle = pointConfig.ExchangePacketTitle; + + string url = ApiClient.SendWechatPay(new { robot_nick = robot.nick, robot_name = robot.name, username = exchange.username, usernick = exchange.usernick }, ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", exchange.point.ToString()), exchange.point, out ispaid, out appinfo); + if (string.IsNullOrEmpty(url)) + throw new Exception($@"机器人:{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}),服务器繁忙,请稍后重试,跳过该兑换"); + + if (ispaid) + { + var ExchangeCommercialEftTip = @"一一一一商 户 转 账 成 功一一一一 +[兑换金额]兑换成功 +已直接转入您的账户!"; + if (!string.IsNullOrWhiteSpace(pointConfig.ExchangeCommercialEftTip)) + ExchangeCommercialEftTip = pointConfig.ExchangeCommercialEftTip; + + mess = ExchangeCommercialEftTip.Replace("[兑换金额]", exchange.point.ToString("0.00")); + } + else + { + EventClient.OnEvent(this, $@"机器人:{robot.nick}【{robot.uin}】一键审核【商户付款】用户:{exchange.usernick}({exchange.username}) +end:{DateTime.Now.ToString("u")} +url:{url} +appinfo is null:{(appinfo == null)}"); + + bool isSendMiNi = false; + if (pointConfig.ExchangeCommercialPayTip_MiniApp == SwitchType.开启 && appinfo != null) + { + var xml = Util.GetMiNiAppXml(appinfo, robot.type); + if (!string.IsNullOrWhiteSpace(xml)) + { + mess = xml; + isSendMiNi = true; + } + } + + if (!isSendMiNi) + { + var ExchangeCommercialPayTip = @"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"; + if (!string.IsNullOrWhiteSpace(pointConfig.ExchangeCommercialPayTip)) + ExchangeCommercialPayTip = pointConfig.ExchangeCommercialPayTip; + + mess = ExchangeCommercialPayTip.Replace("[领取地址]", ApiClient.ShortURL(url).Result).Replace("[兑换金额]", exchange.point.ToString("0.00")); + } + } + + exchange.state = ApplyType.已审核; + exchange.check_time = DateTime.Now; + exchange.remark = $"一键审核【商户付款】 商户链接:{url}"; + //is_auto_pay = true; + EventClient.OnEvent(this, $"{robot.nick}【{robot.uin}】商户付款信息 = " + mess); + Update(exchange, url, mess); + } + catch (Exception ex) + { + AddJindu(ex.Message); + } + finally + { + AddJindu(); + Thread.Sleep(200); + } + } + } + catch (Exception ex) + { + AddJindu($@"商户一键兑换未知异常:{ex.Message} - {ex.StackTrace}"); + } + } + + private void Update(point_manage_control.exchange_list_temp exchange, string url = "", string mess = "") + { + try + { + var session = ApiClient.GetSession(); + if (exchange.state != ApplyType.未审核) + { + var exchangeResult = session.Find("select * from fl_exchange_info where id = @id", new { id = exchange.id }).FirstOrDefault(); + if (exchangeResult == null) throw new Exception($"{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}),兑换数据异常,请稍后重试!"); + session.ExcuteSQL("update fl_exchange_info set state = @state,remark = @remark,check_time = @check_time where id = @id", new { state = exchange.state, check_time = DateTime.Now, remark = exchange.remark, id = exchange.id }); + var robot_info = session.FindRobotInfo(exchange.robot_name, exchange.chattype); + var member_info = session.Find("select * from fl_member_info where id = @id", new { id = exchangeResult.uid }).FirstOrDefault(); + + var pointConfig = ApiClient.GetPointManageConfig(); + if (pointConfig == null) + throw new Exception("获取积分管理配置为空"); + if (member_info != null && robot_info != null) + { + if (exchange.state == ApplyType.退回兑换) + { + member_info = session.ChangePoint(PointType.退回积分, exchangeResult.point, member_info.id, $"退回兑换{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); + if (robot_info != null) + ApiClient.SendMessage(robot_info, exchange.username, new VariateReplace().CommonReplace(pointConfig.ExchangeReturnTip.Replace("[兑换金额]", exchangeResult.point.ToString()).Replace("[备注]", exchange.remark), member_info), exchange.groupid); + } + else if (exchange.state == ApplyType.已审核) + { + var messTmp = new VariateReplace().CommonReplace(pointConfig.ExchangeAdoptTip.Replace("[兑换金额]", exchangeResult.point.ToString()).Replace("[领取地址]", url), member_info); + var sends = new List(); + if (!string.IsNullOrWhiteSpace(mess)) + sends.Add(new temp_send_data() { Groupid = exchange.groupid, Message = mess, Robot = robot_info, TouserName = exchange.username }); + sends.Add(new temp_send_data() { Groupid = exchange.groupid, Message = messTmp, Robot = robot_info, TouserName = exchange.username }); + + ApiClient.SendMessage(sends.ToArray()); + } + else //没收兑换 + { + ApiClient.SendMessage(robot_info, exchange.username, new VariateReplace().CommonReplace(pointConfig.ExchangeConfiscateTip.Replace("[兑换金额]", exchangeResult.point.ToString()).Replace("[备注]", exchange.remark), member_info), exchange.groupid); + } + } + else + { + if (exchange.state == ApplyType.退回兑换) + throw new Exception($"{exchange.robot_nick}({exchange.robot_name}),用户:{exchange.usernick}({exchange.username}),兑换退回失败,请稍后重试."); + } + } + } + catch (Exception ex) + { + AddJindu($@"一键兑换异常:{ex.Message} - {ex.StackTrace}"); + } + } + + } +} diff --git a/FLSystem/Forms/OneKeyExchangeForm.resx b/FLSystem/Forms/OneKeyExchangeForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/OneKeyExchangeForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/RatioCustomGroupForm.Designer.cs b/FLSystem/Forms/RatioCustomGroupForm.Designer.cs new file mode 100644 index 0000000..5241942 --- /dev/null +++ b/FLSystem/Forms/RatioCustomGroupForm.Designer.cs @@ -0,0 +1,163 @@ +namespace FLSystem.Forms +{ + partial class RatioCustomGroupForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RatioCustomGroupForm)); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.label6 = new System.Windows.Forms.Label(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.SuspendLayout(); + // + // gridControl2 + // + this.gridControl2.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(590, 420); + this.gridControl2.TabIndex = 2; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn8, + this.gridColumn10}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn8.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "分组名称"; + this.gridColumn8.FieldName = "name"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 0; + this.gridColumn8.Width = 300; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn10.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "联盟平台"; + this.gridColumn10.FieldName = "cps_type"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 1; + this.gridColumn10.Width = 265; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(47, 178); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(488, 33); + this.label6.TabIndex = 4; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // simpleButton2 + // + this.simpleButton2.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(125, 438); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(152, 32); + this.simpleButton2.TabIndex = 11; + this.simpleButton2.Text = "确认选中行"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(332, 437); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(137, 35); + this.simpleButton3.TabIndex = 12; + this.simpleButton3.Text = "放弃修改"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // RatioCustomGroupForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(590, 482); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.label6); + this.Controls.Add(this.gridControl2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "RatioCustomGroupForm"; + this.Text = "独立分出比例分组"; + this.Load += new System.EventHandler(this.RatioCustomGroupForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private System.Windows.Forms.Label label6; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/RatioCustomGroupForm.cs b/FLSystem/Forms/RatioCustomGroupForm.cs new file mode 100644 index 0000000..fbe138d --- /dev/null +++ b/FLSystem/Forms/RatioCustomGroupForm.cs @@ -0,0 +1,72 @@ +using Api.Framework.Model; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class RatioCustomGroupForm : BaseForm + { + public fl_ratio_info_custom_group group = null; + private List groups = null; + public RatioCustomGroupForm(List groups) + { + InitializeComponent(); + this.groups = groups; + } + + private void RatioCustomGroupForm_Load(object sender, EventArgs e) + { + try + { + if (groups != null && groups.Count != null) + { + label6.Visible = false; + gridControl2.DataSource = groups; + } + else + { + this.label6.Visible = true; + this.label6.Text = "当前没有分组,请先设置独立分出比例"; + } + } + catch (Exception ex) + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + var select = this.gridView2.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + group = this.gridView2.GetRow(select[0]) as fl_ratio_info_custom_group; + this.Close(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + groups = null; + this.Close(); + } + + } +} diff --git a/FLSystem/Forms/RatioCustomGroupForm.resx b/FLSystem/Forms/RatioCustomGroupForm.resx new file mode 100644 index 0000000..c5cbe53 --- /dev/null +++ b/FLSystem/Forms/RatioCustomGroupForm.resx @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC + + + \ No newline at end of file diff --git a/FLSystem/Forms/ServerClientManage.Designer.cs b/FLSystem/Forms/ServerClientManage.Designer.cs new file mode 100644 index 0000000..2f117a4 --- /dev/null +++ b/FLSystem/Forms/ServerClientManage.Designer.cs @@ -0,0 +1,250 @@ +namespace FLSystem.Forms +{ + partial class ServerClientManage + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.button1 = new System.Windows.Forms.Button(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.linkLabel2); + this.groupControl1.Controls.Add(this.linkLabel1); + this.groupControl1.Controls.Add(this.textBox1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.button1); + this.groupControl1.Controls.Add(this.numericUpDown1); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Location = new System.Drawing.Point(10, 12); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(587, 77); + this.groupControl1.TabIndex = 0; + this.groupControl1.Text = "服务器设置"; + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.gridControl1); + this.groupControl2.Location = new System.Drawing.Point(10, 102); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(587, 329); + this.groupControl2.TabIndex = 1; + this.groupControl2.Text = "客户端列表"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(72, 38); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(48, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "端口号:"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(126, 34); + this.numericUpDown1.Maximum = new decimal(new int[] { + 1410065407, + 2, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(48, 22); + this.numericUpDown1.TabIndex = 1; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(483, 35); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 27); + this.button1.TabIndex = 2; + this.button1.Text = "启动"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(192, 38); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(36, 14); + this.labelControl2.TabIndex = 3; + this.labelControl2.Text = "秘钥:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(234, 34); + this.textBox1.Name = "textBox1"; + this.textBox1.PasswordChar = '*'; + this.textBox1.Size = new System.Drawing.Size(128, 22); + this.textBox1.TabIndex = 4; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(385, 39); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(31, 14); + this.linkLabel1.TabIndex = 5; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "随机"; + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(425, 39); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(31, 14); + this.linkLabel2.TabIndex = 6; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "复制"; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(2, 21); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(583, 306); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.AppearancePrint.Row.Options.UseTextOptions = true; + this.gridView1.AppearancePrint.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "客户端IP"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 155; + // + // gridColumn2 + // + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "端口号"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 109; + // + // gridColumn3 + // + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "版本号"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 149; + // + // gridColumn4 + // + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "连接时间"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + this.gridColumn4.Width = 151; + // + // ServerClientManage + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(606, 442); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.groupControl1); + this.Name = "ServerClientManage"; + this.Text = "客户端管理"; + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/ServerClientManage.cs b/FLSystem/Forms/ServerClientManage.cs new file mode 100644 index 0000000..e5854ed --- /dev/null +++ b/FLSystem/Forms/ServerClientManage.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + internal partial class ServerClientManage : BaseForm + { + public ServerClientManage() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + + } + catch (Exception) + { + + throw; + } + } + } +} diff --git a/FLSystem/Forms/ServerClientManage.resx b/FLSystem/Forms/ServerClientManage.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/ServerClientManage.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/TCPForm.Designer.cs b/FLSystem/Forms/TCPForm.Designer.cs new file mode 100644 index 0000000..85d9dd8 --- /dev/null +++ b/FLSystem/Forms/TCPForm.Designer.cs @@ -0,0 +1,146 @@ +namespace FLSystem.Forms +{ + partial class TCPForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(55, 41); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 14); + this.label1.TabIndex = 0; + this.label1.Text = "端口:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(55, 89); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(43, 14); + this.label2.TabIndex = 1; + this.label2.Text = "秘钥:"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(117, 39); + this.numericUpDown1.Maximum = new decimal(new int[] { + 999999999, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(68, 22); + this.numericUpDown1.TabIndex = 2; + this.numericUpDown1.Value = new decimal(new int[] { + 80, + 0, + 0, + 0}); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(117, 84); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.Size = new System.Drawing.Size(258, 22); + this.textBox1.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.ForeColor = System.Drawing.Color.Gray; + this.label3.Location = new System.Drawing.Point(210, 41); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(149, 14); + this.label3.TabIndex = 4; + this.label3.Text = "(请确认防火墙已放行端口)"; + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(390, 87); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(31, 14); + this.linkLabel2.TabIndex = 6; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "随机"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(172, 128); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(147, 23); + this.simpleButton1.TabIndex = 7; + this.simpleButton1.Text = "启动Socket服务器"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // TCPForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(475, 185); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.linkLabel2); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.numericUpDown1); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "TCPForm"; + this.Text = "Socket 服务器"; + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.LinkLabel linkLabel2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/TCPForm.cs b/FLSystem/Forms/TCPForm.cs new file mode 100644 index 0000000..78f11d9 --- /dev/null +++ b/FLSystem/Forms/TCPForm.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; +using Api.Framework; +namespace FLSystem.Forms +{ + /// + /// Socket服务器设置窗体 + /// + public partial class TCPForm : BaseForm + { + public TCPForm() + { + InitializeComponent(); + this.numericUpDown1.Value = ApiClient.Setting.ServerConfig.SocketPort; + var socketPassword = ApiClient.Setting.ServerConfig.SocketPassword; + if (socketPassword.Length > 16) + socketPassword = socketPassword.Substring(0, 16); + this.textBox1.Text = socketPassword; + if (ApiClient.Server != null && ApiClient.Server.State == SuperSocket.SocketBase.ServerState.Running) + { + numericUpDown1.Enabled = linkLabel2.Enabled = false; + this.simpleButton1.Text = "关闭Socket服务器"; + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (this.simpleButton1.Text == "关闭Socket服务器") + { + numericUpDown1.Enabled = linkLabel2.Enabled = true; + ApiClient.StopSocketServer(); + this.simpleButton1.Text = "启动Socket服务器"; + } + else + { + if (string.IsNullOrEmpty(this.textBox1.Text)) linkLabel2_LinkClicked(null, null); + + if (ApiClient.StartSocketServer((int)this.numericUpDown1.Value, this.textBox1.Text)) + { + numericUpDown1.Enabled = linkLabel2.Enabled = false; + this.simpleButton1.Text = "关闭Socket服务器"; + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + this.textBox1.Text = CsharpHttpHelper.HttpExtend.GetMD5String(Guid.NewGuid().ToString()).ToLower().Substring(0, 16); + } + } +} diff --git a/FLSystem/Forms/TCPForm.resx b/FLSystem/Forms/TCPForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/TCPForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/UpdateForm.Designer.cs b/FLSystem/Forms/UpdateForm.Designer.cs new file mode 100644 index 0000000..6810876 --- /dev/null +++ b/FLSystem/Forms/UpdateForm.Designer.cs @@ -0,0 +1,77 @@ +namespace FLSystem.Forms +{ + partial class UpdateForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.SuspendLayout(); + // + // richTextBox1 + // + this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.richTextBox1.Location = new System.Drawing.Point(0, 0); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.Size = new System.Drawing.Size(417, 383); + this.richTextBox1.TabIndex = 1; + this.richTextBox1.Text = ""; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(160, 395); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(96, 30); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "立即更新"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // UpdateForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(417, 437); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.richTextBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.IconOptions.ShowIcon = false; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UpdateForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "更新内容"; + this.Load += new System.EventHandler(this.UpdateForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.RichTextBox richTextBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/UpdateForm.cs b/FLSystem/Forms/UpdateForm.cs new file mode 100644 index 0000000..f5790e0 --- /dev/null +++ b/FLSystem/Forms/UpdateForm.cs @@ -0,0 +1,43 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; +using static Api.Framework.Tools.UpdateClient; + +namespace FLSystem.Forms +{ + public partial class UpdateForm : BaseForm + { + private string strb = null; + public UpdateForm(string strb) + { + InitializeComponent(); + this.strb = strb; + } + + private void UpdateForm_Load(object sender, EventArgs e) + { + try + { + richTextBox1.Text = strb ?? "作者未填写更新内容"; + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex, 20000); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.OK; + } + + } +} diff --git a/FLSystem/Forms/UpdateForm.resx b/FLSystem/Forms/UpdateForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/UpdateForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/VerifyPassForm.cs b/FLSystem/Forms/VerifyPassForm.cs new file mode 100644 index 0000000..2f5a23a --- /dev/null +++ b/FLSystem/Forms/VerifyPassForm.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class VerifyPassForm : BaseForm + { + private string pass = string.Empty; + public VerifyPassForm(string pass) + { + InitializeComponent(); + this.pass = pass; + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox2.Text)) throw new Exception("密码不能为空"); + if (CsharpHttpHelper.HttpExtend.GetMD5String(this.textBox2.Text.Trim()) != pass) + throw new Exception("抱歉,身份验证失败!"); + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + + this.Close(); + } + + private void VerifyPassForm_Load(object sender, EventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/VerifyPassForm.designer.cs b/FLSystem/Forms/VerifyPassForm.designer.cs new file mode 100644 index 0000000..e369cb1 --- /dev/null +++ b/FLSystem/Forms/VerifyPassForm.designer.cs @@ -0,0 +1,105 @@ +namespace FLSystem.Forms +{ + partial class VerifyPassForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(40, 73); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 14; + this.label2.Text = "登陆密码:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(113, 69); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(196, 22); + this.textBox2.TabIndex = 13; + this.textBox2.UseSystemPasswordChar = true; + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Location = new System.Drawing.Point(114, 111); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(131, 30); + this.button1.TabIndex = 16; + this.button1.Text = " 确 定 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Tahoma", 10F); + this.label1.ForeColor = System.Drawing.Color.Blue; + this.label1.Location = new System.Drawing.Point(20, 27); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(316, 17); + this.label1.TabIndex = 17; + this.label1.Text = "请输入修改金额密码,验证身份通过才能继续操作"; + // + // VerifyPassForm + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(356, 161); + this.Controls.Add(this.label1); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "VerifyPassForm"; + this.Text = " 身 份 验 证 "; + this.Load += new System.EventHandler(this.VerifyPassForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/VerifyPassForm.resx b/FLSystem/Forms/VerifyPassForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/VerifyPassForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/WPHNavForm.Designer.cs b/FLSystem/Forms/WPHNavForm.Designer.cs new file mode 100644 index 0000000..a7ff8c9 --- /dev/null +++ b/FLSystem/Forms/WPHNavForm.Designer.cs @@ -0,0 +1,103 @@ +namespace FLSystem.Forms +{ + partial class WPHNavForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.checkEdit1 = new DevExpress.XtraEditors.CheckEdit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(58, 31); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(420, 154); + this.labelControl1.TabIndex = 2; + this.labelControl1.Text = "温馨提示:亲当前还未使用唯品会返利,唯品会活动力度不比其他平台返利少哦\r\n\r\n使用步骤如下:\r\n\r\n1、注册唯品会联盟账号(点击右侧按钮进行注册)\r\n\r\n2、注册" + + "完成以后在联盟管理中进行登录\r\n\r\n3、设置机器人推广位即可\r\n\r\n就是这么便捷,现在行动起来吧!!!"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(366, 83); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(101, 23); + this.simpleButton1.TabIndex = 3; + this.simpleButton1.Text = "打开唯品会联盟"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(12, 203); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(533, 23); + this.separatorControl1.TabIndex = 4; + // + // checkEdit1 + // + this.checkEdit1.Location = new System.Drawing.Point(34, 225); + this.checkEdit1.Name = "checkEdit1"; + this.checkEdit1.Properties.Caption = "下次不在提示"; + this.checkEdit1.Size = new System.Drawing.Size(341, 18); + this.checkEdit1.TabIndex = 5; + // + // WPHNavForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(557, 255); + this.Controls.Add(this.checkEdit1); + this.Controls.Add(this.separatorControl1); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.labelControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "WPHNavForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "唯品会引导页"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.WPHNavForm_FormClosing); + this.Load += new System.EventHandler(this.WPHNavForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.ComponentModel.BackgroundWorker backgroundWorker1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private DevExpress.XtraEditors.CheckEdit checkEdit1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/WPHNavForm.cs b/FLSystem/Forms/WPHNavForm.cs new file mode 100644 index 0000000..8aa7a94 --- /dev/null +++ b/FLSystem/Forms/WPHNavForm.cs @@ -0,0 +1,60 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class WPHNavForm : BaseForm + { + public bool isIgnore = false; + public WPHNavForm() + { + InitializeComponent(); + } + + private void WPHNavForm_FormClosing(object sender, FormClosingEventArgs e) + { + isIgnore = checkEdit1.Checked; + this.DialogResult = DialogResult.OK; + } + + private string LoginUrl = "https://union.vip.com/index"; + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + //从注册表中读取默认浏览器可执行文件路径 + RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"http\shell\open\command\"); + string s = key.GetValue("").ToString(); + + System.Diagnostics.Process.Start(s.Substring(0, s.Length - 8), LoginUrl); + } + catch (Exception) + { + try + { + System.Diagnostics.Process.Start(LoginUrl); + } + catch (Exception) + { + MessageBox.Show("抱歉,无法启动【默认浏览器】,已经将网址复制到粘贴板,请复制到网页端进行注册!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + } + } + + private void WPHNavForm_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/FLSystem/Forms/WPHNavForm.resx b/FLSystem/Forms/WPHNavForm.resx new file mode 100644 index 0000000..b966dfd --- /dev/null +++ b/FLSystem/Forms/WPHNavForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/Web Api.Designer.cs b/FLSystem/Forms/Web Api.Designer.cs new file mode 100644 index 0000000..7c3144d --- /dev/null +++ b/FLSystem/Forms/Web Api.Designer.cs @@ -0,0 +1,96 @@ +namespace FLSystem.Forms +{ + partial class Web_Api + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(55, 54); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(84, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "新增好友备注:"; + // + // textEdit1 + // + this.textEdit1.EditValue = "【新】-xxxx-[昵称]"; + this.textEdit1.Location = new System.Drawing.Point(150, 52); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(195, 20); + this.textEdit1.TabIndex = 1; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(55, 114); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(84, 14); + this.labelControl2.TabIndex = 2; + this.labelControl2.Text = "绑定订单成功:"; + // + // textEdit2 + // + this.textEdit2.EditValue = "【】"; + this.textEdit2.Location = new System.Drawing.Point(150, 111); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(195, 20); + this.textEdit2.TabIndex = 3; + // + // Web_Api + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(480, 402); + this.Controls.Add(this.textEdit2); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.textEdit1); + this.Controls.Add(this.labelControl1); + this.Name = "Web_Api"; + this.Text = "API接口"; + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.TextEdit textEdit2; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/Web Api.cs b/FLSystem/Forms/Web Api.cs new file mode 100644 index 0000000..a6f30ec --- /dev/null +++ b/FLSystem/Forms/Web Api.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class Web_Api : BaseForm + { + public Web_Api() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/Web Api.resx b/FLSystem/Forms/Web Api.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/Web Api.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/WphRegisterForm.Designer.cs b/FLSystem/Forms/WphRegisterForm.Designer.cs new file mode 100644 index 0000000..c1793ed --- /dev/null +++ b/FLSystem/Forms/WphRegisterForm.Designer.cs @@ -0,0 +1,50 @@ +namespace FLSystem.Forms +{ + partial class WphRegisterForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // WphRegisterForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(567, 451); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "WphRegisterForm"; + this.Text = "唯品会注册"; + this.WindowState = System.Windows.Forms.FormWindowState.Maximized; + this.Load += new System.EventHandler(this.WphRegisterForm_Load); + this.ResumeLayout(false); + + } + + #endregion + } +} \ No newline at end of file diff --git a/FLSystem/Forms/WphRegisterForm.cs b/FLSystem/Forms/WphRegisterForm.cs new file mode 100644 index 0000000..7f072f6 --- /dev/null +++ b/FLSystem/Forms/WphRegisterForm.cs @@ -0,0 +1,46 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace FLSystem.Forms +{ + public partial class WphRegisterForm : Form + { + private WebBrowser webBrowser1; + + private string regUrl = "https://passport.vip.com/register?src=https://union.vip.com/vip_login_redirect?timestamp="; + + public WphRegisterForm() + { + InitializeComponent(); + + this.webBrowser1 = new WebBrowser(); + this.webBrowser1.Parent = this; + this.webBrowser1.Dock = DockStyle.Fill; + webBrowser1.ScriptErrorsSuppressed = true; //禁用错误脚本提示 + webBrowser1.IsWebBrowserContextMenuEnabled = false; //禁用右键菜单 + webBrowser1.WebBrowserShortcutsEnabled = false; //禁用快捷键 + webBrowser1.AllowWebBrowserDrop = false;//禁止拖拽 + + this.webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted; + this.webBrowser1.Navigate($"{regUrl}{Util.GetTimeSpan(DateTime.Now)}"); + } + + private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) + { + //Console.WriteLine($"e.Url = {e.Url} ## webBrowser1.Url = {webBrowser1.Url}"); + } + + private void WphRegisterForm_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/FLSystem/Forms/WphRegisterForm.resx b/FLSystem/Forms/WphRegisterForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Forms/WphRegisterForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/FLSystem/Forms/add_authorization.Designer.cs b/FLSystem/Forms/add_authorization.Designer.cs new file mode 100644 index 0000000..5838b9d --- /dev/null +++ b/FLSystem/Forms/add_authorization.Designer.cs @@ -0,0 +1,163 @@ +namespace FLSystem.Forms +{ + partial class add_authorization + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(add_authorization)); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(35, 31); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(65, 12); + this.label1.TabIndex = 0; + this.label1.Text = "授权账号:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(35, 121); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(65, 12); + this.label2.TabIndex = 1; + this.label2.Text = "授权卡号:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(106, 117); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(242, 21); + this.textBox1.TabIndex = 2; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(106, 31); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(53, 12); + this.label3.TabIndex = 4; + this.label3.Text = "username"; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(126, 154); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(129, 34); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "充值授权"; + this.simpleButton1.Click += new System.EventHandler(this.button1_Click); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(35, 60); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(65, 12); + this.label4.TabIndex = 6; + this.label4.Text = "帐号昵称:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(106, 60); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(53, 12); + this.label5.TabIndex = 7; + this.label5.Text = "usernick"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(106, 89); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(23, 12); + this.label6.TabIndex = 9; + this.label6.Text = "uin"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(35, 89); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(65, 12); + this.label7.TabIndex = 8; + this.label7.Text = "授权编号:"; + // + // add_authorization + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(378, 211); + this.Controls.Add(this.label6); + this.Controls.Add(this.label7); + this.Controls.Add(this.label5); + this.Controls.Add(this.label4); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "add_authorization"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "账号续费"; + this.Load += new System.EventHandler(this.add_authorization_Load_1); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/add_authorization.cs b/FLSystem/Forms/add_authorization.cs new file mode 100644 index 0000000..79afbc8 --- /dev/null +++ b/FLSystem/Forms/add_authorization.cs @@ -0,0 +1,54 @@ +using Api.Framework; +using Api.Framework.Model; +using Grant.Framework; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace FLSystem.Forms +{ + public partial class add_authorization : Form + { + private fl_robot_info fl_robot_info; + public add_authorization(fl_robot_info fl_robot_info) + { + InitializeComponent(); + this.fl_robot_info = fl_robot_info; + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + var webResult = GrantClient.Get().SendPack("addTime", new { cName = fl_robot_info.uin, cardid = this.textBox1.Text }); + MessageBox.Show(webResult.message.ToString(), "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + + var softId = (fl_robot_info.type == Api.Framework.SDK.ChatType.QQ) ? 1002 : 1001; + var custm = GrantClient.Get().Refresh(fl_robot_info.uin.ToString(), softId); + if (custm != null) + { + fl_robot_info.end_time = custm.endTime; + ApiClient.GetSession().SaveOrUpdate(fl_robot_info); + } + this.Close(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void add_authorization_Load_1(object sender, EventArgs e) + { + this.label3.Text = fl_robot_info.name; + this.label5.Text = fl_robot_info.nick; + this.label6.Text = fl_robot_info.uin; + } + } +} diff --git a/FLSystem/Forms/add_authorization.resx b/FLSystem/Forms/add_authorization.resx new file mode 100644 index 0000000..3fc1eb5 --- /dev/null +++ b/FLSystem/Forms/add_authorization.resx @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/FLSystem/Forms/admin_verify_control.Designer.cs b/FLSystem/Forms/admin_verify_control.Designer.cs new file mode 100644 index 0000000..2bef37c --- /dev/null +++ b/FLSystem/Forms/admin_verify_control.Designer.cs @@ -0,0 +1,704 @@ +namespace FLSystem.Forms +{ + partial class admin_verify_control + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.checkBox45 = new System.Windows.Forms.CheckBox(); + this.checkBox11 = new System.Windows.Forms.CheckBox(); + this.checkBox10 = new System.Windows.Forms.CheckBox(); + this.checkBox9 = new System.Windows.Forms.CheckBox(); + this.checkBox8 = new System.Windows.Forms.CheckBox(); + this.checkBox7 = new System.Windows.Forms.CheckBox(); + this.checkBox6 = new System.Windows.Forms.CheckBox(); + this.checkBox5 = new System.Windows.Forms.CheckBox(); + this.checkBox43 = new System.Windows.Forms.CheckBox(); + this.checkBox42 = new System.Windows.Forms.CheckBox(); + this.checkBox41 = new System.Windows.Forms.CheckBox(); + this.checkBox44 = new System.Windows.Forms.CheckBox(); + this.checkBox40 = new System.Windows.Forms.CheckBox(); + this.checkBox39 = new System.Windows.Forms.CheckBox(); + this.checkBox37 = new System.Windows.Forms.CheckBox(); + this.checkBox4 = new System.Windows.Forms.CheckBox(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.checkBox35 = new System.Windows.Forms.CheckBox(); + this.checkBox34 = new System.Windows.Forms.CheckBox(); + this.checkBox33 = new System.Windows.Forms.CheckBox(); + this.checkBox32 = new System.Windows.Forms.CheckBox(); + this.checkBox31 = new System.Windows.Forms.CheckBox(); + this.checkBox30 = new System.Windows.Forms.CheckBox(); + this.checkBox29 = new System.Windows.Forms.CheckBox(); + this.checkBox28 = new System.Windows.Forms.CheckBox(); + this.checkBox27 = new System.Windows.Forms.CheckBox(); + this.checkBox26 = new System.Windows.Forms.CheckBox(); + this.checkBox25 = new System.Windows.Forms.CheckBox(); + this.checkBox24 = new System.Windows.Forms.CheckBox(); + this.checkBox23 = new System.Windows.Forms.CheckBox(); + this.checkBox22 = new System.Windows.Forms.CheckBox(); + this.checkBox21 = new System.Windows.Forms.CheckBox(); + this.checkBox20 = new System.Windows.Forms.CheckBox(); + this.checkBox19 = new System.Windows.Forms.CheckBox(); + this.checkBox18 = new System.Windows.Forms.CheckBox(); + this.checkBox17 = new System.Windows.Forms.CheckBox(); + this.checkBox16 = new System.Windows.Forms.CheckBox(); + this.checkBox15 = new System.Windows.Forms.CheckBox(); + this.checkBox14 = new System.Windows.Forms.CheckBox(); + this.checkBox13 = new System.Windows.Forms.CheckBox(); + this.checkBox12 = new System.Windows.Forms.CheckBox(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.separatorControl3 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + this.SuspendLayout(); + // + // panelControl1 + // + this.panelControl1.Controls.Add(this.checkBox45); + this.panelControl1.Controls.Add(this.checkBox11); + this.panelControl1.Controls.Add(this.checkBox10); + this.panelControl1.Controls.Add(this.checkBox9); + this.panelControl1.Controls.Add(this.checkBox8); + this.panelControl1.Controls.Add(this.checkBox7); + this.panelControl1.Controls.Add(this.checkBox6); + this.panelControl1.Controls.Add(this.checkBox5); + this.panelControl1.Controls.Add(this.checkBox43); + this.panelControl1.Controls.Add(this.checkBox42); + this.panelControl1.Controls.Add(this.checkBox41); + this.panelControl1.Controls.Add(this.checkBox44); + this.panelControl1.Controls.Add(this.checkBox40); + this.panelControl1.Controls.Add(this.checkBox39); + this.panelControl1.Controls.Add(this.checkBox37); + this.panelControl1.Controls.Add(this.checkBox4); + this.panelControl1.Controls.Add(this.checkBox3); + this.panelControl1.Controls.Add(this.checkBox35); + this.panelControl1.Controls.Add(this.checkBox34); + this.panelControl1.Controls.Add(this.checkBox33); + this.panelControl1.Controls.Add(this.checkBox32); + this.panelControl1.Controls.Add(this.checkBox31); + this.panelControl1.Controls.Add(this.checkBox30); + this.panelControl1.Controls.Add(this.checkBox29); + this.panelControl1.Controls.Add(this.checkBox28); + this.panelControl1.Controls.Add(this.checkBox27); + this.panelControl1.Controls.Add(this.checkBox26); + this.panelControl1.Controls.Add(this.checkBox25); + this.panelControl1.Controls.Add(this.checkBox24); + this.panelControl1.Controls.Add(this.checkBox23); + this.panelControl1.Controls.Add(this.checkBox22); + this.panelControl1.Controls.Add(this.checkBox21); + this.panelControl1.Controls.Add(this.checkBox20); + this.panelControl1.Controls.Add(this.checkBox19); + this.panelControl1.Controls.Add(this.checkBox18); + this.panelControl1.Controls.Add(this.checkBox17); + this.panelControl1.Controls.Add(this.checkBox16); + this.panelControl1.Controls.Add(this.checkBox15); + this.panelControl1.Controls.Add(this.checkBox14); + this.panelControl1.Controls.Add(this.checkBox13); + this.panelControl1.Controls.Add(this.checkBox12); + this.panelControl1.Controls.Add(this.checkBox2); + this.panelControl1.Controls.Add(this.checkBox1); + this.panelControl1.Controls.Add(this.labelControl3); + this.panelControl1.Controls.Add(this.labelControl2); + this.panelControl1.Controls.Add(this.labelControl1); + this.panelControl1.Controls.Add(this.separatorControl3); + this.panelControl1.Controls.Add(this.separatorControl2); + this.panelControl1.Controls.Add(this.separatorControl1); + this.panelControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panelControl1.Location = new System.Drawing.Point(0, 0); + this.panelControl1.Name = "panelControl1"; + this.panelControl1.Size = new System.Drawing.Size(905, 603); + this.panelControl1.TabIndex = 0; + // + // checkBox45 + // + this.checkBox45.AutoSize = true; + this.checkBox45.Location = new System.Drawing.Point(134, 164); + this.checkBox45.Name = "checkBox45"; + this.checkBox45.Size = new System.Drawing.Size(74, 18); + this.checkBox45.TabIndex = 2; + this.checkBox45.Text = "数据报表"; + this.checkBox45.UseVisualStyleBackColor = true; + // + // checkBox11 + // + this.checkBox11.AutoSize = true; + this.checkBox11.Location = new System.Drawing.Point(134, 140); + this.checkBox11.Name = "checkBox11"; + this.checkBox11.Size = new System.Drawing.Size(74, 18); + this.checkBox11.TabIndex = 2; + this.checkBox11.Text = "运行日志"; + this.checkBox11.UseVisualStyleBackColor = true; + // + // checkBox10 + // + this.checkBox10.AutoSize = true; + this.checkBox10.Location = new System.Drawing.Point(760, 140); + this.checkBox10.Name = "checkBox10"; + this.checkBox10.Size = new System.Drawing.Size(110, 18); + this.checkBox10.TabIndex = 2; + this.checkBox10.Text = "添加微信公众号"; + this.checkBox10.UseVisualStyleBackColor = true; + // + // checkBox9 + // + this.checkBox9.AutoSize = true; + this.checkBox9.Location = new System.Drawing.Point(760, 118); + this.checkBox9.Name = "checkBox9"; + this.checkBox9.Size = new System.Drawing.Size(68, 18); + this.checkBox9.TabIndex = 2; + this.checkBox9.Text = "登录QQ"; + this.checkBox9.UseVisualStyleBackColor = true; + // + // checkBox8 + // + this.checkBox8.AutoSize = true; + this.checkBox8.Location = new System.Drawing.Point(760, 94); + this.checkBox8.Name = "checkBox8"; + this.checkBox8.Size = new System.Drawing.Size(74, 18); + this.checkBox8.TabIndex = 2; + this.checkBox8.Text = "登录微信"; + this.checkBox8.UseVisualStyleBackColor = true; + // + // checkBox7 + // + this.checkBox7.AutoSize = true; + this.checkBox7.Location = new System.Drawing.Point(512, 94); + this.checkBox7.Name = "checkBox7"; + this.checkBox7.Size = new System.Drawing.Size(86, 18); + this.checkBox7.TabIndex = 2; + this.checkBox7.Text = "机器人管理"; + this.checkBox7.UseVisualStyleBackColor = true; + // + // checkBox6 + // + this.checkBox6.AutoSize = true; + this.checkBox6.Location = new System.Drawing.Point(370, 140); + this.checkBox6.Name = "checkBox6"; + this.checkBox6.Size = new System.Drawing.Size(98, 18); + this.checkBox6.TabIndex = 2; + this.checkBox6.Text = "登录京东联盟"; + this.checkBox6.UseVisualStyleBackColor = true; + // + // checkBox5 + // + this.checkBox5.AutoSize = true; + this.checkBox5.Location = new System.Drawing.Point(370, 118); + this.checkBox5.Name = "checkBox5"; + this.checkBox5.Size = new System.Drawing.Size(98, 18); + this.checkBox5.TabIndex = 2; + this.checkBox5.Text = "登录阿里妈妈"; + this.checkBox5.UseVisualStyleBackColor = true; + // + // checkBox43 + // + this.checkBox43.AutoSize = true; + this.checkBox43.Location = new System.Drawing.Point(642, 164); + this.checkBox43.Name = "checkBox43"; + this.checkBox43.Size = new System.Drawing.Size(86, 18); + this.checkBox43.TabIndex = 2; + this.checkBox43.Text = "删除机器人"; + this.checkBox43.UseVisualStyleBackColor = true; + // + // checkBox42 + // + this.checkBox42.AutoSize = true; + this.checkBox42.Location = new System.Drawing.Point(642, 140); + this.checkBox42.Name = "checkBox42"; + this.checkBox42.Size = new System.Drawing.Size(98, 18); + this.checkBox42.TabIndex = 2; + this.checkBox42.Text = "重置设备信息"; + this.checkBox42.UseVisualStyleBackColor = true; + // + // checkBox41 + // + this.checkBox41.AutoSize = true; + this.checkBox41.Location = new System.Drawing.Point(642, 116); + this.checkBox41.Name = "checkBox41"; + this.checkBox41.Size = new System.Drawing.Size(98, 18); + this.checkBox41.TabIndex = 2; + this.checkBox41.Text = "设置支付密码"; + this.checkBox41.UseVisualStyleBackColor = true; + // + // checkBox44 + // + this.checkBox44.AutoSize = true; + this.checkBox44.Location = new System.Drawing.Point(252, 118); + this.checkBox44.Name = "checkBox44"; + this.checkBox44.Size = new System.Drawing.Size(74, 18); + this.checkBox44.TabIndex = 2; + this.checkBox44.Text = "手动同步"; + this.checkBox44.UseVisualStyleBackColor = true; + // + // checkBox40 + // + this.checkBox40.AutoSize = true; + this.checkBox40.Location = new System.Drawing.Point(642, 94); + this.checkBox40.Name = "checkBox40"; + this.checkBox40.Size = new System.Drawing.Size(74, 18); + this.checkBox40.TabIndex = 2; + this.checkBox40.Text = "卡密授权"; + this.checkBox40.UseVisualStyleBackColor = true; + // + // checkBox39 + // + this.checkBox39.AutoSize = true; + this.checkBox39.Location = new System.Drawing.Point(512, 142); + this.checkBox39.Name = "checkBox39"; + this.checkBox39.Size = new System.Drawing.Size(74, 18); + this.checkBox39.TabIndex = 2; + this.checkBox39.Text = "注销登录"; + this.checkBox39.UseVisualStyleBackColor = true; + // + // checkBox37 + // + this.checkBox37.AutoSize = true; + this.checkBox37.Location = new System.Drawing.Point(512, 118); + this.checkBox37.Name = "checkBox37"; + this.checkBox37.Size = new System.Drawing.Size(74, 18); + this.checkBox37.TabIndex = 2; + this.checkBox37.Text = "重新登录"; + this.checkBox37.UseVisualStyleBackColor = true; + // + // checkBox4 + // + this.checkBox4.AutoSize = true; + this.checkBox4.Location = new System.Drawing.Point(370, 94); + this.checkBox4.Name = "checkBox4"; + this.checkBox4.Size = new System.Drawing.Size(98, 18); + this.checkBox4.TabIndex = 2; + this.checkBox4.Text = "登录多多进宝"; + this.checkBox4.UseVisualStyleBackColor = true; + // + // checkBox3 + // + this.checkBox3.AutoSize = true; + this.checkBox3.Location = new System.Drawing.Point(252, 94); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.Size = new System.Drawing.Size(74, 18); + this.checkBox3.TabIndex = 2; + this.checkBox3.Text = "联盟管理"; + this.checkBox3.UseVisualStyleBackColor = true; + // + // checkBox35 + // + this.checkBox35.AutoSize = true; + this.checkBox35.Location = new System.Drawing.Point(370, 382); + this.checkBox35.Name = "checkBox35"; + this.checkBox35.Size = new System.Drawing.Size(74, 18); + this.checkBox35.TabIndex = 2; + this.checkBox35.Text = "执行顺序"; + this.checkBox35.UseVisualStyleBackColor = true; + // + // checkBox34 + // + this.checkBox34.AutoSize = true; + this.checkBox34.Location = new System.Drawing.Point(371, 406); + this.checkBox34.Name = "checkBox34"; + this.checkBox34.Size = new System.Drawing.Size(74, 18); + this.checkBox34.TabIndex = 2; + this.checkBox34.Text = "全部重启"; + this.checkBox34.UseVisualStyleBackColor = true; + // + // checkBox33 + // + this.checkBox33.AutoSize = true; + this.checkBox33.Location = new System.Drawing.Point(371, 430); + this.checkBox33.Name = "checkBox33"; + this.checkBox33.Size = new System.Drawing.Size(74, 18); + this.checkBox33.TabIndex = 2; + this.checkBox33.Text = "刷新应用"; + this.checkBox33.UseVisualStyleBackColor = true; + // + // checkBox32 + // + this.checkBox32.AutoSize = true; + this.checkBox32.Location = new System.Drawing.Point(252, 430); + this.checkBox32.Name = "checkBox32"; + this.checkBox32.Size = new System.Drawing.Size(74, 18); + this.checkBox32.TabIndex = 2; + this.checkBox32.Text = "应用功能"; + this.checkBox32.UseVisualStyleBackColor = true; + // + // checkBox31 + // + this.checkBox31.AutoSize = true; + this.checkBox31.Location = new System.Drawing.Point(252, 406); + this.checkBox31.Name = "checkBox31"; + this.checkBox31.Size = new System.Drawing.Size(69, 18); + this.checkBox31.TabIndex = 2; + this.checkBox31.Text = "WedApi"; + this.checkBox31.UseVisualStyleBackColor = true; + // + // checkBox30 + // + this.checkBox30.AutoSize = true; + this.checkBox30.Location = new System.Drawing.Point(252, 382); + this.checkBox30.Name = "checkBox30"; + this.checkBox30.Size = new System.Drawing.Size(74, 18); + this.checkBox30.TabIndex = 2; + this.checkBox30.Text = "应用封装"; + this.checkBox30.UseVisualStyleBackColor = true; + // + // checkBox29 + // + this.checkBox29.AutoSize = true; + this.checkBox29.Location = new System.Drawing.Point(134, 430); + this.checkBox29.Name = "checkBox29"; + this.checkBox29.Size = new System.Drawing.Size(74, 18); + this.checkBox29.TabIndex = 2; + this.checkBox29.Text = "开发调试"; + this.checkBox29.UseVisualStyleBackColor = true; + // + // checkBox28 + // + this.checkBox28.AutoSize = true; + this.checkBox28.Location = new System.Drawing.Point(134, 406); + this.checkBox28.Name = "checkBox28"; + this.checkBox28.Size = new System.Drawing.Size(98, 18); + this.checkBox28.TabIndex = 2; + this.checkBox28.Text = "打开应用目录"; + this.checkBox28.UseVisualStyleBackColor = true; + // + // checkBox27 + // + this.checkBox27.AutoSize = true; + this.checkBox27.Location = new System.Drawing.Point(134, 382); + this.checkBox27.Name = "checkBox27"; + this.checkBox27.Size = new System.Drawing.Size(86, 18); + this.checkBox27.TabIndex = 2; + this.checkBox27.Text = "打开根目录"; + this.checkBox27.UseVisualStyleBackColor = true; + // + // checkBox26 + // + this.checkBox26.AutoSize = true; + this.checkBox26.Location = new System.Drawing.Point(642, 291); + this.checkBox26.Name = "checkBox26"; + this.checkBox26.Size = new System.Drawing.Size(98, 18); + this.checkBox26.TabIndex = 2; + this.checkBox26.Text = "强制结算订单"; + this.checkBox26.UseVisualStyleBackColor = true; + // + // checkBox25 + // + this.checkBox25.AutoSize = true; + this.checkBox25.Location = new System.Drawing.Point(370, 267); + this.checkBox25.Name = "checkBox25"; + this.checkBox25.Size = new System.Drawing.Size(98, 18); + this.checkBox25.TabIndex = 2; + this.checkBox25.Text = "阿里妈妈订单"; + this.checkBox25.UseVisualStyleBackColor = true; + // + // checkBox24 + // + this.checkBox24.AutoSize = true; + this.checkBox24.Location = new System.Drawing.Point(370, 291); + this.checkBox24.Name = "checkBox24"; + this.checkBox24.Size = new System.Drawing.Size(98, 18); + this.checkBox24.TabIndex = 2; + this.checkBox24.Text = "京东联盟订单"; + this.checkBox24.UseVisualStyleBackColor = true; + // + // checkBox23 + // + this.checkBox23.AutoSize = true; + this.checkBox23.Location = new System.Drawing.Point(512, 243); + this.checkBox23.Name = "checkBox23"; + this.checkBox23.Size = new System.Drawing.Size(74, 18); + this.checkBox23.TabIndex = 2; + this.checkBox23.Text = "用户管理"; + this.checkBox23.UseVisualStyleBackColor = true; + // + // checkBox22 + // + this.checkBox22.AutoSize = true; + this.checkBox22.Location = new System.Drawing.Point(512, 267); + this.checkBox22.Name = "checkBox22"; + this.checkBox22.Size = new System.Drawing.Size(74, 18); + this.checkBox22.TabIndex = 2; + this.checkBox22.Text = "群负责人"; + this.checkBox22.UseVisualStyleBackColor = true; + // + // checkBox21 + // + this.checkBox21.AutoSize = true; + this.checkBox21.Location = new System.Drawing.Point(512, 291); + this.checkBox21.Name = "checkBox21"; + this.checkBox21.Size = new System.Drawing.Size(74, 18); + this.checkBox21.TabIndex = 2; + this.checkBox21.Text = "积分管理"; + this.checkBox21.UseVisualStyleBackColor = true; + // + // checkBox20 + // + this.checkBox20.AutoSize = true; + this.checkBox20.Location = new System.Drawing.Point(642, 243); + this.checkBox20.Name = "checkBox20"; + this.checkBox20.Size = new System.Drawing.Size(74, 18); + this.checkBox20.TabIndex = 2; + this.checkBox20.Text = "查询记录"; + this.checkBox20.UseVisualStyleBackColor = true; + // + // checkBox19 + // + this.checkBox19.AutoSize = true; + this.checkBox19.Location = new System.Drawing.Point(642, 267); + this.checkBox19.Name = "checkBox19"; + this.checkBox19.Size = new System.Drawing.Size(98, 18); + this.checkBox19.TabIndex = 2; + this.checkBox19.Text = "淘宝订单尾号"; + this.checkBox19.UseVisualStyleBackColor = true; + // + // checkBox18 + // + this.checkBox18.AutoSize = true; + this.checkBox18.Location = new System.Drawing.Point(370, 243); + this.checkBox18.Name = "checkBox18"; + this.checkBox18.Size = new System.Drawing.Size(98, 18); + this.checkBox18.TabIndex = 2; + this.checkBox18.Text = "多多进宝订单"; + this.checkBox18.UseVisualStyleBackColor = true; + // + // checkBox17 + // + this.checkBox17.AutoSize = true; + this.checkBox17.Location = new System.Drawing.Point(252, 291); + this.checkBox17.Name = "checkBox17"; + this.checkBox17.Size = new System.Drawing.Size(98, 18); + this.checkBox17.TabIndex = 2; + this.checkBox17.Text = "授权商户付款"; + this.checkBox17.UseVisualStyleBackColor = true; + // + // checkBox16 + // + this.checkBox16.AutoSize = true; + this.checkBox16.Location = new System.Drawing.Point(252, 267); + this.checkBox16.Name = "checkBox16"; + this.checkBox16.Size = new System.Drawing.Size(98, 18); + this.checkBox16.TabIndex = 2; + this.checkBox16.Text = "测试佣金比例"; + this.checkBox16.UseVisualStyleBackColor = true; + // + // checkBox15 + // + this.checkBox15.AutoSize = true; + this.checkBox15.Location = new System.Drawing.Point(135, 267); + this.checkBox15.Name = "checkBox15"; + this.checkBox15.Size = new System.Drawing.Size(74, 18); + this.checkBox15.TabIndex = 2; + this.checkBox15.Text = "其他设置"; + this.checkBox15.UseVisualStyleBackColor = true; + // + // checkBox14 + // + this.checkBox14.AutoSize = true; + this.checkBox14.Location = new System.Drawing.Point(253, 243); + this.checkBox14.Name = "checkBox14"; + this.checkBox14.Size = new System.Drawing.Size(98, 18); + this.checkBox14.TabIndex = 2; + this.checkBox14.Text = "测试邮件通信"; + this.checkBox14.UseVisualStyleBackColor = true; + // + // checkBox13 + // + this.checkBox13.AutoSize = true; + this.checkBox13.Location = new System.Drawing.Point(135, 291); + this.checkBox13.Name = "checkBox13"; + this.checkBox13.Size = new System.Drawing.Size(74, 18); + this.checkBox13.TabIndex = 2; + this.checkBox13.Text = "保存设置"; + this.checkBox13.UseVisualStyleBackColor = true; + // + // checkBox12 + // + this.checkBox12.AutoSize = true; + this.checkBox12.Location = new System.Drawing.Point(135, 243); + this.checkBox12.Name = "checkBox12"; + this.checkBox12.Size = new System.Drawing.Size(74, 18); + this.checkBox12.TabIndex = 2; + this.checkBox12.Text = "系统设置"; + this.checkBox12.UseVisualStyleBackColor = true; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(134, 116); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(74, 18); + this.checkBox2.TabIndex = 2; + this.checkBox2.Text = "停止接收"; + this.checkBox2.UseVisualStyleBackColor = true; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(134, 94); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(74, 18); + this.checkBox1.TabIndex = 2; + this.checkBox1.Text = "接收消息"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.Common_CheckedChanged); + // + // labelControl3 + // + this.labelControl3.Appearance.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Bold); + this.labelControl3.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl3.Appearance.Options.UseFont = true; + this.labelControl3.Appearance.Options.UseForeColor = true; + this.labelControl3.Location = new System.Drawing.Point(97, 347); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(93, 19); + this.labelControl3.TabIndex = 1; + this.labelControl3.Text = " 应 用 中 心 "; + // + // labelControl2 + // + this.labelControl2.Appearance.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Bold); + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl2.Appearance.Options.UseFont = true; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(97, 218); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(93, 19); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = " 系 统 管 理 "; + // + // labelControl1 + // + this.labelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Bold); + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl1.Appearance.Options.UseFont = true; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(97, 56); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(93, 19); + this.labelControl1.TabIndex = 1; + this.labelControl1.Text = " 账 号 设 置 "; + // + // separatorControl3 + // + this.separatorControl3.Location = new System.Drawing.Point(73, 463); + this.separatorControl3.Name = "separatorControl3"; + this.separatorControl3.Size = new System.Drawing.Size(765, 23); + this.separatorControl3.TabIndex = 0; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(73, 318); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(765, 23); + this.separatorControl2.TabIndex = 0; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(73, 188); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(765, 23); + this.separatorControl1.TabIndex = 0; + // + // admin_verify_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.panelControl1); + this.Name = "admin_verify_control"; + this.Size = new System.Drawing.Size(905, 603); + this.Load += new System.EventHandler(this.admin_verify_control_Load); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + this.panelControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.PanelControl panelControl1; + private DevExpress.XtraEditors.SeparatorControl separatorControl3; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.CheckBox checkBox4; + private System.Windows.Forms.CheckBox checkBox3; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.CheckBox checkBox6; + private System.Windows.Forms.CheckBox checkBox5; + private System.Windows.Forms.CheckBox checkBox7; + private System.Windows.Forms.CheckBox checkBox10; + private System.Windows.Forms.CheckBox checkBox9; + private System.Windows.Forms.CheckBox checkBox8; + private System.Windows.Forms.CheckBox checkBox11; + private System.Windows.Forms.CheckBox checkBox32; + private System.Windows.Forms.CheckBox checkBox31; + private System.Windows.Forms.CheckBox checkBox30; + private System.Windows.Forms.CheckBox checkBox29; + private System.Windows.Forms.CheckBox checkBox28; + private System.Windows.Forms.CheckBox checkBox27; + private System.Windows.Forms.CheckBox checkBox26; + private System.Windows.Forms.CheckBox checkBox25; + private System.Windows.Forms.CheckBox checkBox24; + private System.Windows.Forms.CheckBox checkBox23; + private System.Windows.Forms.CheckBox checkBox22; + private System.Windows.Forms.CheckBox checkBox21; + private System.Windows.Forms.CheckBox checkBox20; + private System.Windows.Forms.CheckBox checkBox19; + private System.Windows.Forms.CheckBox checkBox18; + private System.Windows.Forms.CheckBox checkBox17; + private System.Windows.Forms.CheckBox checkBox16; + private System.Windows.Forms.CheckBox checkBox15; + private System.Windows.Forms.CheckBox checkBox14; + private System.Windows.Forms.CheckBox checkBox13; + private System.Windows.Forms.CheckBox checkBox12; + private System.Windows.Forms.CheckBox checkBox35; + private System.Windows.Forms.CheckBox checkBox34; + private System.Windows.Forms.CheckBox checkBox33; + private System.Windows.Forms.CheckBox checkBox37; + private System.Windows.Forms.CheckBox checkBox41; + private System.Windows.Forms.CheckBox checkBox40; + private System.Windows.Forms.CheckBox checkBox39; + private System.Windows.Forms.CheckBox checkBox42; + private System.Windows.Forms.CheckBox checkBox43; + private System.Windows.Forms.CheckBox checkBox44; + private System.Windows.Forms.CheckBox checkBox45; + } +} diff --git a/FLSystem/Forms/admin_verify_control.cs b/FLSystem/Forms/admin_verify_control.cs new file mode 100644 index 0000000..8206efe --- /dev/null +++ b/FLSystem/Forms/admin_verify_control.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using Api.Framework; +using Api.Framework.Tools; + +namespace FLSystem.Forms +{ + public partial class admin_verify_control : DevExpress.XtraEditors.XtraUserControl + { + public admin_verify_control() + { + InitializeComponent(); + } + + private void admin_verify_control_Load(object sender, EventArgs e) + { + //try + //{ + // foreach (Control item in panelControl1.Controls) + // { + // if (item is CheckBox) + // { + // var control = item as CheckBox; + // if (ApiClient.Setting.SystemConfig.admin_verify_control_name.Contains(control.Text.Trim())) + // control.Checked = true; + // control.CheckedChanged += Common_CheckedChanged; + // } + // } + //} + //catch (Exception ex) + //{ + // XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + //} + } + + private void Common_CheckedChanged(object sender, EventArgs e) + { + //var control = sender as CheckBox; + //if (control.Checked) + //{ + // if (!ApiClient.Setting.SystemConfig.admin_verify_control_name.Contains(control.Text.Trim())) + // ApiClient.Setting.SystemConfig.admin_verify_control_name.Add(control.Text.Trim()); + //} + //else + //{ + // if (ApiClient.Setting.SystemConfig.admin_verify_control_name.Contains(control.Text.Trim())) + // ApiClient.Setting.SystemConfig.admin_verify_control_name.Remove(control.Text.Trim()); + //} + //Util.Save(ApiClient.Setting.SystemConfig); + } + } +} diff --git a/FLSystem/Forms/admin_verify_control.resx b/FLSystem/Forms/admin_verify_control.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Forms/admin_verify_control.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/FLSystem/Forms/change_point_form.Designer.cs b/FLSystem/Forms/change_point_form.Designer.cs new file mode 100644 index 0000000..3c9716b --- /dev/null +++ b/FLSystem/Forms/change_point_form.Designer.cs @@ -0,0 +1,261 @@ +namespace FLSystem.Forms +{ + partial class change_point_form + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.hyperlinkLabelControl4 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.label1 = new System.Windows.Forms.Label(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.hyperlinkLabelControl4); + this.groupBox1.Controls.Add(this.hyperlinkLabelControl3); + this.groupBox1.Controls.Add(this.hyperlinkLabelControl2); + this.groupBox1.Controls.Add(this.memoEdit1); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.button2); + this.groupBox1.Controls.Add(this.button1); + this.groupBox1.Controls.Add(this.hyperlinkLabelControl1); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Location = new System.Drawing.Point(36, 24); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(562, 344); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 修改积分 "; + // + // hyperlinkLabelControl4 + // + this.hyperlinkLabelControl4.Location = new System.Drawing.Point(358, 157); + this.hyperlinkLabelControl4.Name = "hyperlinkLabelControl4"; + this.hyperlinkLabelControl4.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl4.TabIndex = 9; + this.hyperlinkLabelControl4.Text = "[积分名称]"; + this.hyperlinkLabelControl4.Click += new System.EventHandler(this.hyperlinkLabelControl_Click); + // + // hyperlinkLabelControl3 + // + this.hyperlinkLabelControl3.Location = new System.Drawing.Point(283, 157); + this.hyperlinkLabelControl3.Name = "hyperlinkLabelControl3"; + this.hyperlinkLabelControl3.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl3.TabIndex = 9; + this.hyperlinkLabelControl3.Text = "[剩余积分]"; + this.hyperlinkLabelControl3.Click += new System.EventHandler(this.hyperlinkLabelControl_Click); + // + // hyperlinkLabelControl2 + // + this.hyperlinkLabelControl2.Location = new System.Drawing.Point(208, 157); + this.hyperlinkLabelControl2.Name = "hyperlinkLabelControl2"; + this.hyperlinkLabelControl2.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl2.TabIndex = 9; + this.hyperlinkLabelControl2.Text = "[修改金额]"; + this.hyperlinkLabelControl2.Click += new System.EventHandler(this.hyperlinkLabelControl_Click); + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(105, 177); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Properties.NullValuePrompt = "不通知客户为空即可"; + this.memoEdit1.Properties.NullValuePromptShowForEmptyValue = true; + this.memoEdit1.Size = new System.Drawing.Size(359, 95); + this.memoEdit1.TabIndex = 8; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(190, 110); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(231, 22); + this.textBox1.TabIndex = 7; + // + // button2 + // + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Location = new System.Drawing.Point(282, 289); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(90, 26); + this.button2.TabIndex = 6; + this.button2.Text = " 取 消 "; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Location = new System.Drawing.Point(163, 289); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(90, 26); + this.button1.TabIndex = 6; + this.button1.Text = " 确 定 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Bold); + this.hyperlinkLabelControl1.Appearance.Options.UseFont = true; + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(358, 44); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(32, 18); + this.hyperlinkLabelControl1.TabIndex = 5; + this.hyperlinkLabelControl1.Text = "刷新"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ForeColor = System.Drawing.Color.Blue; + this.label1.Location = new System.Drawing.Point(196, 46); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 14); + this.label1.TabIndex = 4; + this.label1.Text = "label1"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(105, 46); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(72, 14); + this.labelControl2.TabIndex = 3; + this.labelControl2.Text = "当前积分值:"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(117, 157); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(60, 14); + this.labelControl5.TabIndex = 3; + this.labelControl5.Text = "通知用户:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(117, 113); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 3; + this.labelControl3.Text = "操作说明:"; + // + // labelControl4 + // + this.labelControl4.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl4.Appearance.Options.UseForeColor = true; + this.labelControl4.Location = new System.Drawing.Point(334, 81); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(87, 14); + this.labelControl4.TabIndex = 3; + this.labelControl4.Text = "(正数加/负数减)"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(105, 81); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(72, 14); + this.labelControl1.TabIndex = 3; + this.labelControl1.Text = "增加减少值:"; + // + // numericUpDown1 + // + this.numericUpDown1.DecimalPlaces = 2; + this.numericUpDown1.Location = new System.Drawing.Point(190, 77); + this.numericUpDown1.Maximum = new decimal(new int[] { + -1530494977, + 232830, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + -1530494977, + 232830, + 0, + -2147483648}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(124, 22); + this.numericUpDown1.TabIndex = 2; + // + // change_point_form + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.ClientSize = new System.Drawing.Size(636, 395); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "change_point_form"; + this.Text = "修改积分"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl4; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/change_point_form.cs b/FLSystem/Forms/change_point_form.cs new file mode 100644 index 0000000..b467304 --- /dev/null +++ b/FLSystem/Forms/change_point_form.cs @@ -0,0 +1,101 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using SqlSugar; +using System; +using System.Linq; +using System.Threading; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class change_point_form : BaseForm + { + private long uid; + private fl_member_info member = null; + private SqlSugarClient session = null; + public change_point_form(long uid) + { + InitializeComponent(); + session = ApiClient.GetSession(); + this.uid = uid; + hyperlinkLabelControl1_Click(null, null); + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (member != null) + { + if (numericUpDown1.Value == 0m) throw new Exception("积分值不能为0"); + + member = session.ChangePoint(PointType.人为修改, (double)numericUpDown1.Value, member.id, string.IsNullOrWhiteSpace(textBox1.Text) ? $"手动修改积分:{numericUpDown1.Value} 积分" : textBox1.Text.Trim()); + + #region 通知用户积分变动 + if (!string.IsNullOrWhiteSpace(memoEdit1.Text)) + { + var robot = session.FindRobots().FirstOrDefault(f => f.type == member.robot_type && f.name == member.robot_name); + if (robot != null) + ApiClient.SendMessage(robot, member.username, new VariateReplace().CommonReplace(memoEdit1.Text.Replace("[修改金额]", numericUpDown1.Value.ToString("0.00")), member)); + } + #endregion + + ShowSuccess("修改成功"); + label1.Text = member.cur_point.ToString(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button2_Click(object sender, EventArgs e) + { + this.Close(); + } + + /// + /// 刷新 + /// + /// + /// + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + hyperlinkLabelControl1.Enabled = false; + if (uid != 0) + { + member = session.FindMemberInfoById(uid); + if (member != null) + { + label1.Text = member.cur_point.ToString(); + Thread.Sleep(1000); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + hyperlinkLabelControl1.Enabled = true; + } + } + + private void hyperlinkLabelControl_Click(object sender, EventArgs e) + { + if (sender is HyperlinkLabelControl) + { + var label = sender as HyperlinkLabelControl; + memoEdit1.Text += label.Text; + } + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/change_point_form.resx b/FLSystem/Forms/change_point_form.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/change_point_form.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/convert_tool_control.Designer.cs b/FLSystem/Forms/convert_tool_control.Designer.cs new file mode 100644 index 0000000..fcbd28d --- /dev/null +++ b/FLSystem/Forms/convert_tool_control.Designer.cs @@ -0,0 +1,1886 @@ +namespace FLSystem.Forms +{ + partial class convert_tool_control + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraScrollableControl1 = new DevExpress.XtraEditors.XtraScrollableControl(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl17 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl52 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.textEdit10 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl16 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit37 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl55 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit11 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl15 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit9 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit8 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit6 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit5 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox8 = new System.Windows.Forms.GroupBox(); + this.textEdit44 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl69 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit42 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl67 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit43 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl68 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox7 = new System.Windows.Forms.GroupBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.simpleButton5 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton4 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl64 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl63 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl62 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl61 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl60 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit41 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl59 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit38 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit47 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit39 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl56 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl66 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit40 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl57 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl65 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl58 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraScrollableControl2 = new DevExpress.XtraEditors.XtraScrollableControl(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.labelControl53 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit2 = new DevExpress.XtraEditors.MemoEdit(); + this.textEdit7 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl18 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit14 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl19 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl21 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit15 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl22 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit16 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl23 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl24 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit17 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit18 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl25 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl26 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit19 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit20 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit21 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.hyperlinkLabelControl2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit24 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl32 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl33 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl34 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraScrollableControl3 = new DevExpress.XtraEditors.XtraScrollableControl(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.comboBox3 = new System.Windows.Forms.ComboBox(); + this.hyperlinkLabelControl3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit36 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl49 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl50 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl51 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.labelControl54 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit3 = new DevExpress.XtraEditors.MemoEdit(); + this.textEdit25 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl35 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit22 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit26 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl36 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl37 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl38 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit35 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit27 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl48 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl39 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit34 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit28 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl47 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl40 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl41 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit29 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit30 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl42 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl43 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit23 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl31 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit31 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl44 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit32 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl45 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit33 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl46 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.xtraScrollableControl1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit10.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit37.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit11.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit9.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit8.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + this.xtraTabPage4.SuspendLayout(); + this.groupBox8.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit44.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit42.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit43.Properties)).BeginInit(); + this.groupBox7.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit41.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit38.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit47.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit39.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit40.Properties)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.xtraScrollableControl2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit7.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit14.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit15.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit16.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit17.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit18.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit19.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit20.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit21.Properties)).BeginInit(); + this.groupBox4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit24.Properties)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.xtraScrollableControl3.SuspendLayout(); + this.groupBox6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit36.Properties)).BeginInit(); + this.groupBox5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit25.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit22.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit26.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit35.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit27.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit34.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit28.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit29.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit30.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit23.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit31.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit32.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit33.Properties)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(885, 519); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage4, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage1 + // + this.xtraTabPage1.AutoScroll = true; + this.xtraTabPage1.Controls.Add(this.xtraScrollableControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(883, 495); + this.xtraTabPage1.Text = " 淘 宝 转 链 "; + // + // xtraScrollableControl1 + // + this.xtraScrollableControl1.Controls.Add(this.groupBox2); + this.xtraScrollableControl1.Controls.Add(this.groupBox1); + this.xtraScrollableControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraScrollableControl1.Location = new System.Drawing.Point(0, 0); + this.xtraScrollableControl1.Name = "xtraScrollableControl1"; + this.xtraScrollableControl1.Size = new System.Drawing.Size(883, 495); + this.xtraScrollableControl1.TabIndex = 2; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.comboBox1); + this.groupBox2.Controls.Add(this.hyperlinkLabelControl1); + this.groupBox2.Controls.Add(this.simpleButton1); + this.groupBox2.Controls.Add(this.textEdit1); + this.groupBox2.Controls.Add(this.labelControl17); + this.groupBox2.Controls.Add(this.labelControl2); + this.groupBox2.Controls.Add(this.labelControl1); + this.groupBox2.Location = new System.Drawing.Point(44, 18); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(799, 165); + this.groupBox2.TabIndex = 3; + this.groupBox2.TabStop = false; + this.groupBox2.Text = " 基本信息 "; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "模板A", + "模板B"}); + this.comboBox1.Location = new System.Drawing.Point(487, 22); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(143, 22); + this.comboBox1.TabIndex = 12; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(265, 26); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl1.TabIndex = 3; + this.hyperlinkLabelControl1.Text = "选择推广位"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(684, 72); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(99, 48); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = " 开 始 生 成 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(148, 86); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(519, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Click += new System.EventHandler(this.textEdit1_Click_1); + // + // labelControl17 + // + this.labelControl17.Location = new System.Drawing.Point(409, 26); + this.labelControl17.Name = "labelControl17"; + this.labelControl17.Size = new System.Drawing.Size(72, 14); + this.labelControl17.TabIndex = 0; + this.labelControl17.Text = "优惠券模板:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(187, 26); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(72, 14); + this.labelControl2.TabIndex = 0; + this.labelControl2.Text = "设置推广位:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(58, 89); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(84, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "链接或淘口令:"; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.labelControl52); + this.groupBox1.Controls.Add(this.memoEdit1); + this.groupBox1.Controls.Add(this.textEdit10); + this.groupBox1.Controls.Add(this.labelControl16); + this.groupBox1.Controls.Add(this.textEdit37); + this.groupBox1.Controls.Add(this.labelControl55); + this.groupBox1.Controls.Add(this.textEdit11); + this.groupBox1.Controls.Add(this.labelControl12); + this.groupBox1.Controls.Add(this.labelControl15); + this.groupBox1.Controls.Add(this.labelControl11); + this.groupBox1.Controls.Add(this.textEdit9); + this.groupBox1.Controls.Add(this.labelControl10); + this.groupBox1.Controls.Add(this.textEdit8); + this.groupBox1.Controls.Add(this.labelControl9); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.textEdit6); + this.groupBox1.Controls.Add(this.textEdit5); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl6); + this.groupBox1.Controls.Add(this.textEdit4); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.textEdit3); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.textEdit2); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Location = new System.Drawing.Point(44, 196); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(799, 264); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 转链信息 "; + // + // labelControl52 + // + this.labelControl52.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl52.Appearance.Options.UseForeColor = true; + this.labelControl52.Location = new System.Drawing.Point(771, 60); + this.labelControl52.Name = "labelControl52"; + this.labelControl52.Size = new System.Drawing.Size(12, 154); + this.labelControl52.TabIndex = 3; + this.labelControl52.Text = "︵\r\n点\r\n击\r\n编\r\n辑\r\n框\r\n自\r\n动\r\n复\r\n制\r\n︶"; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(148, 105); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(604, 71); + this.memoEdit1.TabIndex = 2; + this.memoEdit1.Click += new System.EventHandler(this.textEdit1_Click); + // + // textEdit10 + // + this.textEdit10.Location = new System.Drawing.Point(148, 182); + this.textEdit10.Name = "textEdit10"; + this.textEdit10.Size = new System.Drawing.Size(604, 20); + this.textEdit10.TabIndex = 1; + this.textEdit10.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl16 + // + this.labelControl16.Location = new System.Drawing.Point(58, 185); + this.labelControl16.Name = "labelControl16"; + this.labelControl16.Size = new System.Drawing.Size(84, 14); + this.labelControl16.TabIndex = 0; + this.labelControl16.Text = "合成优惠券图:"; + // + // textEdit37 + // + this.textEdit37.Location = new System.Drawing.Point(148, 230); + this.textEdit37.Name = "textEdit37"; + this.textEdit37.Size = new System.Drawing.Size(604, 20); + this.textEdit37.TabIndex = 1; + this.textEdit37.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl55 + // + this.labelControl55.Location = new System.Drawing.Point(94, 233); + this.labelControl55.Name = "labelControl55"; + this.labelControl55.Size = new System.Drawing.Size(48, 14); + this.labelControl55.TabIndex = 0; + this.labelControl55.Text = "短连接:"; + // + // textEdit11 + // + this.textEdit11.Location = new System.Drawing.Point(148, 206); + this.textEdit11.Name = "textEdit11"; + this.textEdit11.Size = new System.Drawing.Size(604, 20); + this.textEdit11.TabIndex = 1; + this.textEdit11.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl12 + // + this.labelControl12.Location = new System.Drawing.Point(70, 209); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(72, 14); + this.labelControl12.TabIndex = 0; + this.labelControl12.Text = "生成淘口令:"; + // + // labelControl15 + // + this.labelControl15.Appearance.ForeColor = System.Drawing.Color.DarkGray; + this.labelControl15.Appearance.Options.UseForeColor = true; + this.labelControl15.Location = new System.Drawing.Point(36, 127); + this.labelControl15.Name = "labelControl15"; + this.labelControl15.Size = new System.Drawing.Size(106, 14); + this.labelControl15.TabIndex = 0; + this.labelControl15.Text = "(第一个为商品主图)"; + // + // labelControl11 + // + this.labelControl11.Location = new System.Drawing.Point(70, 107); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(72, 14); + this.labelControl11.TabIndex = 0; + this.labelControl11.Text = "商品详情图:"; + // + // textEdit9 + // + this.textEdit9.Location = new System.Drawing.Point(702, 79); + this.textEdit9.Name = "textEdit9"; + this.textEdit9.Size = new System.Drawing.Size(50, 20); + this.textEdit9.TabIndex = 1; + this.textEdit9.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(636, 82); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(60, 14); + this.labelControl10.TabIndex = 0; + this.labelControl10.Text = "弃券返利:"; + // + // textEdit8 + // + this.textEdit8.Location = new System.Drawing.Point(568, 79); + this.textEdit8.Name = "textEdit8"; + this.textEdit8.Size = new System.Drawing.Size(50, 20); + this.textEdit8.TabIndex = 1; + this.textEdit8.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl9 + // + this.labelControl9.Location = new System.Drawing.Point(502, 82); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(60, 14); + this.labelControl9.TabIndex = 0; + this.labelControl9.Text = "券后返利:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(214, 82); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(72, 14); + this.labelControl8.TabIndex = 0; + this.labelControl8.Text = "优惠券金额:"; + // + // textEdit6 + // + this.textEdit6.Location = new System.Drawing.Point(430, 79); + this.textEdit6.Name = "textEdit6"; + this.textEdit6.Size = new System.Drawing.Size(36, 20); + this.textEdit6.TabIndex = 1; + this.textEdit6.Click += new System.EventHandler(this.textEdit1_Click); + // + // textEdit5 + // + this.textEdit5.Location = new System.Drawing.Point(292, 79); + this.textEdit5.Name = "textEdit5"; + this.textEdit5.Size = new System.Drawing.Size(50, 20); + this.textEdit5.TabIndex = 1; + this.textEdit5.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(472, 82); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(12, 14); + this.labelControl7.TabIndex = 0; + this.labelControl7.Text = "%"; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(364, 82); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(60, 14); + this.labelControl6.TabIndex = 0; + this.labelControl6.Text = "返利比例:"; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(148, 79); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(50, 20); + this.textEdit4.TabIndex = 1; + this.textEdit4.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(82, 82); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(60, 14); + this.labelControl5.TabIndex = 0; + this.labelControl5.Text = "商品单价:"; + // + // textEdit3 + // + this.textEdit3.Location = new System.Drawing.Point(148, 53); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Size = new System.Drawing.Size(604, 20); + this.textEdit3.TabIndex = 1; + this.textEdit3.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(82, 56); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(60, 14); + this.labelControl4.TabIndex = 0; + this.labelControl4.Text = "商品标题:"; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(148, 27); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(604, 20); + this.textEdit2.TabIndex = 1; + this.textEdit2.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(82, 30); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 0; + this.labelControl3.Text = "商品链接:"; + // + // xtraTabPage4 + // + this.xtraTabPage4.AutoScroll = true; + this.xtraTabPage4.Controls.Add(this.groupBox8); + this.xtraTabPage4.Controls.Add(this.groupBox7); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(883, 495); + this.xtraTabPage4.Text = " 淘 礼 金 工 具 "; + // + // groupBox8 + // + this.groupBox8.Controls.Add(this.textEdit44); + this.groupBox8.Controls.Add(this.labelControl69); + this.groupBox8.Controls.Add(this.textEdit42); + this.groupBox8.Controls.Add(this.labelControl67); + this.groupBox8.Controls.Add(this.textEdit43); + this.groupBox8.Controls.Add(this.labelControl68); + this.groupBox8.Location = new System.Drawing.Point(37, 360); + this.groupBox8.Name = "groupBox8"; + this.groupBox8.Size = new System.Drawing.Size(813, 119); + this.groupBox8.TabIndex = 1; + this.groupBox8.TabStop = false; + this.groupBox8.Text = " 生 成 信 息 "; + // + // textEdit44 + // + this.textEdit44.Location = new System.Drawing.Point(190, 74); + this.textEdit44.Name = "textEdit44"; + this.textEdit44.Size = new System.Drawing.Size(519, 20); + this.textEdit44.TabIndex = 26; + // + // labelControl69 + // + this.labelControl69.Location = new System.Drawing.Point(136, 77); + this.labelControl69.Name = "labelControl69"; + this.labelControl69.Size = new System.Drawing.Size(48, 14); + this.labelControl69.TabIndex = 25; + this.labelControl69.Text = "短链接:"; + // + // textEdit42 + // + this.textEdit42.Location = new System.Drawing.Point(190, 51); + this.textEdit42.Name = "textEdit42"; + this.textEdit42.Size = new System.Drawing.Size(519, 20); + this.textEdit42.TabIndex = 23; + // + // labelControl67 + // + this.labelControl67.Location = new System.Drawing.Point(112, 54); + this.labelControl67.Name = "labelControl67"; + this.labelControl67.Size = new System.Drawing.Size(72, 14); + this.labelControl67.TabIndex = 21; + this.labelControl67.Text = "中间页链接:"; + // + // textEdit43 + // + this.textEdit43.Location = new System.Drawing.Point(190, 27); + this.textEdit43.Name = "textEdit43"; + this.textEdit43.Size = new System.Drawing.Size(519, 20); + this.textEdit43.TabIndex = 24; + // + // labelControl68 + // + this.labelControl68.Location = new System.Drawing.Point(112, 30); + this.labelControl68.Name = "labelControl68"; + this.labelControl68.Size = new System.Drawing.Size(72, 14); + this.labelControl68.TabIndex = 22; + this.labelControl68.Text = "生成淘口令:"; + // + // groupBox7 + // + this.groupBox7.Controls.Add(this.dateTimePicker2); + this.groupBox7.Controls.Add(this.dateTimePicker1); + this.groupBox7.Controls.Add(this.numericUpDown3); + this.groupBox7.Controls.Add(this.numericUpDown2); + this.groupBox7.Controls.Add(this.numericUpDown1); + this.groupBox7.Controls.Add(this.comboBoxEdit1); + this.groupBox7.Controls.Add(this.simpleButton5); + this.groupBox7.Controls.Add(this.simpleButton4); + this.groupBox7.Controls.Add(this.labelControl64); + this.groupBox7.Controls.Add(this.labelControl63); + this.groupBox7.Controls.Add(this.labelControl62); + this.groupBox7.Controls.Add(this.labelControl61); + this.groupBox7.Controls.Add(this.labelControl60); + this.groupBox7.Controls.Add(this.textEdit41); + this.groupBox7.Controls.Add(this.labelControl59); + this.groupBox7.Controls.Add(this.textEdit38); + this.groupBox7.Controls.Add(this.textEdit47); + this.groupBox7.Controls.Add(this.textEdit39); + this.groupBox7.Controls.Add(this.labelControl56); + this.groupBox7.Controls.Add(this.labelControl66); + this.groupBox7.Controls.Add(this.textEdit40); + this.groupBox7.Controls.Add(this.labelControl57); + this.groupBox7.Controls.Add(this.labelControl65); + this.groupBox7.Controls.Add(this.labelControl58); + this.groupBox7.Location = new System.Drawing.Point(37, 5); + this.groupBox7.Name = "groupBox7"; + this.groupBox7.Size = new System.Drawing.Size(813, 345); + this.groupBox7.TabIndex = 0; + this.groupBox7.TabStop = false; + this.groupBox7.Text = " 基 础 信 息 "; + // + // dateTimePicker2 + // + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(509, 254); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(200, 22); + this.dateTimePicker2.TabIndex = 16; + this.dateTimePicker2.ValueChanged += new System.EventHandler(this.dateTimePicker_ValueChanged); + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(190, 254); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(200, 22); + this.dateTimePicker1.TabIndex = 15; + this.dateTimePicker1.ValueChanged += new System.EventHandler(this.dateTimePicker_ValueChanged); + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(550, 226); + this.numericUpDown3.Maximum = new decimal(new int[] { + 1000000, + 0, + 0, + 0}); + this.numericUpDown3.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(159, 22); + this.numericUpDown3.TabIndex = 14; + this.numericUpDown3.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(190, 226); + this.numericUpDown2.Maximum = new decimal(new int[] { + 1000000, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(159, 22); + this.numericUpDown2.TabIndex = 13; + this.numericUpDown2.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // numericUpDown1 + // + this.numericUpDown1.DecimalPlaces = 2; + this.numericUpDown1.Location = new System.Drawing.Point(190, 282); + this.numericUpDown1.Maximum = new decimal(new int[] { + 1000000, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(159, 22); + this.numericUpDown1.TabIndex = 12; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(250, 42); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Size = new System.Drawing.Size(319, 20); + this.comboBoxEdit1.TabIndex = 11; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // simpleButton5 + // + this.simpleButton5.Location = new System.Drawing.Point(598, 42); + this.simpleButton5.Name = "simpleButton5"; + this.simpleButton5.Size = new System.Drawing.Size(111, 21); + this.simpleButton5.TabIndex = 10; + this.simpleButton5.Text = "淘礼金设置"; + this.simpleButton5.Click += new System.EventHandler(this.simpleButton5_Click); + // + // simpleButton4 + // + this.simpleButton4.Location = new System.Drawing.Point(629, 290); + this.simpleButton4.Name = "simpleButton4"; + this.simpleButton4.Size = new System.Drawing.Size(167, 42); + this.simpleButton4.TabIndex = 10; + this.simpleButton4.Text = "点击生成淘口令和短链接"; + this.simpleButton4.Click += new System.EventHandler(this.simpleButton4_Click); + // + // labelControl64 + // + this.labelControl64.Location = new System.Drawing.Point(88, 286); + this.labelControl64.Name = "labelControl64"; + this.labelControl64.Size = new System.Drawing.Size(96, 14); + this.labelControl64.TabIndex = 8; + this.labelControl64.Text = "每个淘礼金金额:"; + // + // labelControl63 + // + this.labelControl63.Location = new System.Drawing.Point(419, 258); + this.labelControl63.Name = "labelControl63"; + this.labelControl63.Size = new System.Drawing.Size(84, 14); + this.labelControl63.TabIndex = 8; + this.labelControl63.Text = "领取结束时间:"; + // + // labelControl62 + // + this.labelControl62.Location = new System.Drawing.Point(100, 258); + this.labelControl62.Name = "labelControl62"; + this.labelControl62.Size = new System.Drawing.Size(84, 14); + this.labelControl62.TabIndex = 8; + this.labelControl62.Text = "领取开始时间:"; + // + // labelControl61 + // + this.labelControl61.Location = new System.Drawing.Point(460, 230); + this.labelControl61.Name = "labelControl61"; + this.labelControl61.Size = new System.Drawing.Size(84, 14); + this.labelControl61.TabIndex = 8; + this.labelControl61.Text = "每人限领个数:"; + // + // labelControl60 + // + this.labelControl60.Location = new System.Drawing.Point(88, 230); + this.labelControl60.Name = "labelControl60"; + this.labelControl60.Size = new System.Drawing.Size(96, 14); + this.labelControl60.TabIndex = 8; + this.labelControl60.Text = "淘礼金发放个数:"; + // + // textEdit41 + // + this.textEdit41.Location = new System.Drawing.Point(190, 201); + this.textEdit41.Name = "textEdit41"; + this.textEdit41.Properties.MaxLength = 10; + this.textEdit41.Properties.NullValuePrompt = "请填写淘礼金名称,最大10个字符"; + this.textEdit41.Size = new System.Drawing.Size(519, 20); + this.textEdit41.TabIndex = 9; + // + // labelControl59 + // + this.labelControl59.Location = new System.Drawing.Point(88, 204); + this.labelControl59.Name = "labelControl59"; + this.labelControl59.Size = new System.Drawing.Size(96, 14); + this.labelControl59.TabIndex = 8; + this.labelControl59.Text = "淘礼金领取名称:"; + // + // textEdit38 + // + this.textEdit38.Location = new System.Drawing.Point(190, 175); + this.textEdit38.Name = "textEdit38"; + this.textEdit38.Properties.NullValuePrompt = "请填写商品链接"; + this.textEdit38.Size = new System.Drawing.Size(519, 20); + this.textEdit38.TabIndex = 5; + // + // textEdit47 + // + this.textEdit47.Location = new System.Drawing.Point(190, 149); + this.textEdit47.Name = "textEdit47"; + this.textEdit47.Properties.NullValuePrompt = "口令标题可为空"; + this.textEdit47.Size = new System.Drawing.Size(519, 20); + this.textEdit47.TabIndex = 6; + // + // textEdit39 + // + this.textEdit39.Location = new System.Drawing.Point(190, 123); + this.textEdit39.Name = "textEdit39"; + this.textEdit39.Properties.NullValuePrompt = "口令标题可为空"; + this.textEdit39.Size = new System.Drawing.Size(519, 20); + this.textEdit39.TabIndex = 6; + // + // labelControl56 + // + this.labelControl56.Location = new System.Drawing.Point(124, 178); + this.labelControl56.Name = "labelControl56"; + this.labelControl56.Size = new System.Drawing.Size(60, 14); + this.labelControl56.TabIndex = 2; + this.labelControl56.Text = "商品链接:"; + // + // labelControl66 + // + this.labelControl66.Location = new System.Drawing.Point(81, 152); + this.labelControl66.Name = "labelControl66"; + this.labelControl66.Size = new System.Drawing.Size(103, 14); + this.labelControl66.TabIndex = 3; + this.labelControl66.Text = "淘礼金推广位PID:"; + // + // textEdit40 + // + this.textEdit40.Location = new System.Drawing.Point(190, 97); + this.textEdit40.Name = "textEdit40"; + this.textEdit40.Size = new System.Drawing.Size(519, 20); + this.textEdit40.TabIndex = 7; + // + // labelControl57 + // + this.labelControl57.Location = new System.Drawing.Point(78, 126); + this.labelControl57.Name = "labelControl57"; + this.labelControl57.Size = new System.Drawing.Size(106, 14); + this.labelControl57.TabIndex = 3; + this.labelControl57.Text = "淘礼金AppSecret:"; + // + // labelControl65 + // + this.labelControl65.Location = new System.Drawing.Point(88, 45); + this.labelControl65.Name = "labelControl65"; + this.labelControl65.Size = new System.Drawing.Size(156, 14); + this.labelControl65.TabIndex = 4; + this.labelControl65.Text = "选择淘宝账号(快捷操作):"; + // + // labelControl58 + // + this.labelControl58.Location = new System.Drawing.Point(94, 100); + this.labelControl58.Name = "labelControl58"; + this.labelControl58.Size = new System.Drawing.Size(90, 14); + this.labelControl58.TabIndex = 4; + this.labelControl58.Text = "淘礼金AppKey:"; + // + // xtraTabPage2 + // + this.xtraTabPage2.AutoScroll = true; + this.xtraTabPage2.Controls.Add(this.xtraScrollableControl2); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(883, 495); + this.xtraTabPage2.Text = " 京 东 转 链 "; + // + // xtraScrollableControl2 + // + this.xtraScrollableControl2.Controls.Add(this.groupBox3); + this.xtraScrollableControl2.Controls.Add(this.groupBox4); + this.xtraScrollableControl2.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraScrollableControl2.Location = new System.Drawing.Point(0, 0); + this.xtraScrollableControl2.Name = "xtraScrollableControl2"; + this.xtraScrollableControl2.Size = new System.Drawing.Size(883, 495); + this.xtraScrollableControl2.TabIndex = 4; + // + // groupBox3 + // + this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox3.Controls.Add(this.labelControl53); + this.groupBox3.Controls.Add(this.memoEdit2); + this.groupBox3.Controls.Add(this.textEdit7); + this.groupBox3.Controls.Add(this.labelControl18); + this.groupBox3.Controls.Add(this.textEdit14); + this.groupBox3.Controls.Add(this.labelControl19); + this.groupBox3.Controls.Add(this.labelControl20); + this.groupBox3.Controls.Add(this.labelControl21); + this.groupBox3.Controls.Add(this.textEdit15); + this.groupBox3.Controls.Add(this.labelControl22); + this.groupBox3.Controls.Add(this.textEdit16); + this.groupBox3.Controls.Add(this.labelControl23); + this.groupBox3.Controls.Add(this.labelControl24); + this.groupBox3.Controls.Add(this.textEdit17); + this.groupBox3.Controls.Add(this.textEdit18); + this.groupBox3.Controls.Add(this.labelControl25); + this.groupBox3.Controls.Add(this.labelControl26); + this.groupBox3.Controls.Add(this.textEdit19); + this.groupBox3.Controls.Add(this.labelControl27); + this.groupBox3.Controls.Add(this.textEdit20); + this.groupBox3.Controls.Add(this.labelControl28); + this.groupBox3.Controls.Add(this.textEdit21); + this.groupBox3.Controls.Add(this.labelControl29); + this.groupBox3.Location = new System.Drawing.Point(37, 146); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(806, 304); + this.groupBox3.TabIndex = 1; + this.groupBox3.TabStop = false; + this.groupBox3.Text = " 转链信息 "; + // + // labelControl53 + // + this.labelControl53.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl53.Appearance.Options.UseForeColor = true; + this.labelControl53.Location = new System.Drawing.Point(775, 75); + this.labelControl53.Name = "labelControl53"; + this.labelControl53.Size = new System.Drawing.Size(12, 154); + this.labelControl53.TabIndex = 4; + this.labelControl53.Text = "︵\r\n点\r\n击\r\n编\r\n辑\r\n框\r\n自\r\n动\r\n复\r\n制\r\n︶"; + // + // memoEdit2 + // + this.memoEdit2.Location = new System.Drawing.Point(148, 132); + this.memoEdit2.Name = "memoEdit2"; + this.memoEdit2.Size = new System.Drawing.Size(604, 71); + this.memoEdit2.TabIndex = 2; + this.memoEdit2.Click += new System.EventHandler(this.textEdit1_Click); + // + // textEdit7 + // + this.textEdit7.Location = new System.Drawing.Point(148, 216); + this.textEdit7.Name = "textEdit7"; + this.textEdit7.Size = new System.Drawing.Size(604, 20); + this.textEdit7.TabIndex = 1; + this.textEdit7.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl18 + // + this.labelControl18.Location = new System.Drawing.Point(58, 219); + this.labelControl18.Name = "labelControl18"; + this.labelControl18.Size = new System.Drawing.Size(84, 14); + this.labelControl18.TabIndex = 0; + this.labelControl18.Text = "合成优惠券图:"; + // + // textEdit14 + // + this.textEdit14.Location = new System.Drawing.Point(148, 253); + this.textEdit14.Name = "textEdit14"; + this.textEdit14.Size = new System.Drawing.Size(604, 20); + this.textEdit14.TabIndex = 1; + this.textEdit14.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl19 + // + this.labelControl19.Location = new System.Drawing.Point(46, 256); + this.labelControl19.Name = "labelControl19"; + this.labelControl19.Size = new System.Drawing.Size(96, 14); + this.labelControl19.TabIndex = 0; + this.labelControl19.Text = "转链的京东链接:"; + // + // labelControl20 + // + this.labelControl20.Appearance.ForeColor = System.Drawing.Color.DarkGray; + this.labelControl20.Appearance.Options.UseForeColor = true; + this.labelControl20.Location = new System.Drawing.Point(36, 154); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(106, 14); + this.labelControl20.TabIndex = 0; + this.labelControl20.Text = "(第一个为商品主图)"; + // + // labelControl21 + // + this.labelControl21.Location = new System.Drawing.Point(70, 134); + this.labelControl21.Name = "labelControl21"; + this.labelControl21.Size = new System.Drawing.Size(72, 14); + this.labelControl21.TabIndex = 0; + this.labelControl21.Text = "商品详情图:"; + // + // textEdit15 + // + this.textEdit15.Location = new System.Drawing.Point(702, 99); + this.textEdit15.Name = "textEdit15"; + this.textEdit15.Size = new System.Drawing.Size(50, 20); + this.textEdit15.TabIndex = 1; + this.textEdit15.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl22 + // + this.labelControl22.Location = new System.Drawing.Point(636, 102); + this.labelControl22.Name = "labelControl22"; + this.labelControl22.Size = new System.Drawing.Size(60, 14); + this.labelControl22.TabIndex = 0; + this.labelControl22.Text = "弃券返利:"; + // + // textEdit16 + // + this.textEdit16.Location = new System.Drawing.Point(568, 99); + this.textEdit16.Name = "textEdit16"; + this.textEdit16.Size = new System.Drawing.Size(50, 20); + this.textEdit16.TabIndex = 1; + this.textEdit16.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl23 + // + this.labelControl23.Location = new System.Drawing.Point(502, 102); + this.labelControl23.Name = "labelControl23"; + this.labelControl23.Size = new System.Drawing.Size(60, 14); + this.labelControl23.TabIndex = 0; + this.labelControl23.Text = "券后返利:"; + // + // labelControl24 + // + this.labelControl24.Location = new System.Drawing.Point(214, 102); + this.labelControl24.Name = "labelControl24"; + this.labelControl24.Size = new System.Drawing.Size(72, 14); + this.labelControl24.TabIndex = 0; + this.labelControl24.Text = "优惠券金额:"; + // + // textEdit17 + // + this.textEdit17.Location = new System.Drawing.Point(430, 99); + this.textEdit17.Name = "textEdit17"; + this.textEdit17.Size = new System.Drawing.Size(36, 20); + this.textEdit17.TabIndex = 1; + this.textEdit17.Click += new System.EventHandler(this.textEdit1_Click); + // + // textEdit18 + // + this.textEdit18.Location = new System.Drawing.Point(292, 99); + this.textEdit18.Name = "textEdit18"; + this.textEdit18.Size = new System.Drawing.Size(50, 20); + this.textEdit18.TabIndex = 1; + this.textEdit18.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl25 + // + this.labelControl25.Location = new System.Drawing.Point(472, 102); + this.labelControl25.Name = "labelControl25"; + this.labelControl25.Size = new System.Drawing.Size(12, 14); + this.labelControl25.TabIndex = 0; + this.labelControl25.Text = "%"; + // + // labelControl26 + // + this.labelControl26.Location = new System.Drawing.Point(364, 102); + this.labelControl26.Name = "labelControl26"; + this.labelControl26.Size = new System.Drawing.Size(60, 14); + this.labelControl26.TabIndex = 0; + this.labelControl26.Text = "返利比例:"; + // + // textEdit19 + // + this.textEdit19.Location = new System.Drawing.Point(148, 99); + this.textEdit19.Name = "textEdit19"; + this.textEdit19.Size = new System.Drawing.Size(50, 20); + this.textEdit19.TabIndex = 1; + this.textEdit19.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl27 + // + this.labelControl27.Location = new System.Drawing.Point(82, 102); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(60, 14); + this.labelControl27.TabIndex = 0; + this.labelControl27.Text = "商品单价:"; + // + // textEdit20 + // + this.textEdit20.Location = new System.Drawing.Point(148, 66); + this.textEdit20.Name = "textEdit20"; + this.textEdit20.Size = new System.Drawing.Size(604, 20); + this.textEdit20.TabIndex = 1; + this.textEdit20.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl28 + // + this.labelControl28.Location = new System.Drawing.Point(82, 69); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(60, 14); + this.labelControl28.TabIndex = 0; + this.labelControl28.Text = "商品标题:"; + // + // textEdit21 + // + this.textEdit21.Location = new System.Drawing.Point(148, 33); + this.textEdit21.Name = "textEdit21"; + this.textEdit21.Size = new System.Drawing.Size(604, 20); + this.textEdit21.TabIndex = 1; + this.textEdit21.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl29 + // + this.labelControl29.Location = new System.Drawing.Point(82, 36); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(60, 14); + this.labelControl29.TabIndex = 0; + this.labelControl29.Text = "商品链接:"; + // + // groupBox4 + // + this.groupBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox4.Controls.Add(this.comboBox2); + this.groupBox4.Controls.Add(this.hyperlinkLabelControl2); + this.groupBox4.Controls.Add(this.simpleButton2); + this.groupBox4.Controls.Add(this.textEdit24); + this.groupBox4.Controls.Add(this.labelControl32); + this.groupBox4.Controls.Add(this.labelControl33); + this.groupBox4.Controls.Add(this.labelControl34); + this.groupBox4.Location = new System.Drawing.Point(37, 22); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(806, 107); + this.groupBox4.TabIndex = 3; + this.groupBox4.TabStop = false; + this.groupBox4.Text = " 基本信息 "; + // + // comboBox2 + // + this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Items.AddRange(new object[] { + "模板A", + "模板B"}); + this.comboBox2.Location = new System.Drawing.Point(487, 22); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(143, 22); + this.comboBox2.TabIndex = 12; + // + // hyperlinkLabelControl2 + // + this.hyperlinkLabelControl2.Location = new System.Drawing.Point(265, 26); + this.hyperlinkLabelControl2.Name = "hyperlinkLabelControl2"; + this.hyperlinkLabelControl2.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl2.TabIndex = 3; + this.hyperlinkLabelControl2.Text = "选择推广位"; + this.hyperlinkLabelControl2.Click += new System.EventHandler(this.hyperlinkLabelControl2_Click); + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(673, 53); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(99, 35); + this.simpleButton2.TabIndex = 2; + this.simpleButton2.Text = " 开 始 生 成 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // textEdit24 + // + this.textEdit24.Location = new System.Drawing.Point(148, 60); + this.textEdit24.Name = "textEdit24"; + this.textEdit24.Size = new System.Drawing.Size(519, 20); + this.textEdit24.TabIndex = 1; + this.textEdit24.Click += new System.EventHandler(this.textEdit1_Click_1); + // + // labelControl32 + // + this.labelControl32.Location = new System.Drawing.Point(409, 26); + this.labelControl32.Name = "labelControl32"; + this.labelControl32.Size = new System.Drawing.Size(72, 14); + this.labelControl32.TabIndex = 0; + this.labelControl32.Text = "优惠券模板:"; + // + // labelControl33 + // + this.labelControl33.Location = new System.Drawing.Point(187, 26); + this.labelControl33.Name = "labelControl33"; + this.labelControl33.Size = new System.Drawing.Size(72, 14); + this.labelControl33.TabIndex = 0; + this.labelControl33.Text = "设置推广位:"; + // + // labelControl34 + // + this.labelControl34.Location = new System.Drawing.Point(82, 63); + this.labelControl34.Name = "labelControl34"; + this.labelControl34.Size = new System.Drawing.Size(60, 14); + this.labelControl34.TabIndex = 0; + this.labelControl34.Text = "京东链接:"; + // + // xtraTabPage3 + // + this.xtraTabPage3.AutoScroll = true; + this.xtraTabPage3.Controls.Add(this.xtraScrollableControl3); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(883, 495); + this.xtraTabPage3.Text = " 拼 多 多 转 链 "; + // + // xtraScrollableControl3 + // + this.xtraScrollableControl3.Controls.Add(this.groupBox6); + this.xtraScrollableControl3.Controls.Add(this.groupBox5); + this.xtraScrollableControl3.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraScrollableControl3.Location = new System.Drawing.Point(0, 0); + this.xtraScrollableControl3.Name = "xtraScrollableControl3"; + this.xtraScrollableControl3.Size = new System.Drawing.Size(883, 495); + this.xtraScrollableControl3.TabIndex = 3; + // + // groupBox6 + // + this.groupBox6.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox6.Controls.Add(this.comboBox3); + this.groupBox6.Controls.Add(this.hyperlinkLabelControl3); + this.groupBox6.Controls.Add(this.simpleButton3); + this.groupBox6.Controls.Add(this.textEdit36); + this.groupBox6.Controls.Add(this.labelControl49); + this.groupBox6.Controls.Add(this.labelControl50); + this.groupBox6.Controls.Add(this.labelControl51); + this.groupBox6.Location = new System.Drawing.Point(36, 18); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Size = new System.Drawing.Size(810, 100); + this.groupBox6.TabIndex = 2; + this.groupBox6.TabStop = false; + this.groupBox6.Text = " 基本信息 "; + // + // comboBox3 + // + this.comboBox3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox3.FormattingEnabled = true; + this.comboBox3.Items.AddRange(new object[] { + "模板A", + "模板B"}); + this.comboBox3.Location = new System.Drawing.Point(487, 22); + this.comboBox3.Name = "comboBox3"; + this.comboBox3.Size = new System.Drawing.Size(143, 22); + this.comboBox3.TabIndex = 12; + // + // hyperlinkLabelControl3 + // + this.hyperlinkLabelControl3.Location = new System.Drawing.Point(265, 26); + this.hyperlinkLabelControl3.Name = "hyperlinkLabelControl3"; + this.hyperlinkLabelControl3.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl3.TabIndex = 3; + this.hyperlinkLabelControl3.Text = "选择推广位"; + this.hyperlinkLabelControl3.Click += new System.EventHandler(this.hyperlinkLabelControl3_Click); + // + // simpleButton3 + // + this.simpleButton3.Location = new System.Drawing.Point(673, 52); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(99, 31); + this.simpleButton3.TabIndex = 2; + this.simpleButton3.Text = " 开 始 生 成 "; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // textEdit36 + // + this.textEdit36.Location = new System.Drawing.Point(148, 57); + this.textEdit36.Name = "textEdit36"; + this.textEdit36.Size = new System.Drawing.Size(519, 20); + this.textEdit36.TabIndex = 1; + this.textEdit36.Click += new System.EventHandler(this.textEdit1_Click_1); + // + // labelControl49 + // + this.labelControl49.Location = new System.Drawing.Point(409, 26); + this.labelControl49.Name = "labelControl49"; + this.labelControl49.Size = new System.Drawing.Size(72, 14); + this.labelControl49.TabIndex = 0; + this.labelControl49.Text = "优惠券模板:"; + // + // labelControl50 + // + this.labelControl50.Location = new System.Drawing.Point(187, 26); + this.labelControl50.Name = "labelControl50"; + this.labelControl50.Size = new System.Drawing.Size(72, 14); + this.labelControl50.TabIndex = 0; + this.labelControl50.Text = "设置推广位:"; + // + // labelControl51 + // + this.labelControl51.Location = new System.Drawing.Point(70, 60); + this.labelControl51.Name = "labelControl51"; + this.labelControl51.Size = new System.Drawing.Size(72, 14); + this.labelControl51.TabIndex = 0; + this.labelControl51.Text = "拼多多链接:"; + // + // groupBox5 + // + this.groupBox5.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox5.Controls.Add(this.labelControl54); + this.groupBox5.Controls.Add(this.memoEdit3); + this.groupBox5.Controls.Add(this.textEdit25); + this.groupBox5.Controls.Add(this.labelControl35); + this.groupBox5.Controls.Add(this.textEdit22); + this.groupBox5.Controls.Add(this.labelControl30); + this.groupBox5.Controls.Add(this.textEdit26); + this.groupBox5.Controls.Add(this.labelControl36); + this.groupBox5.Controls.Add(this.labelControl37); + this.groupBox5.Controls.Add(this.labelControl38); + this.groupBox5.Controls.Add(this.textEdit35); + this.groupBox5.Controls.Add(this.textEdit27); + this.groupBox5.Controls.Add(this.labelControl48); + this.groupBox5.Controls.Add(this.labelControl39); + this.groupBox5.Controls.Add(this.textEdit34); + this.groupBox5.Controls.Add(this.textEdit28); + this.groupBox5.Controls.Add(this.labelControl47); + this.groupBox5.Controls.Add(this.labelControl40); + this.groupBox5.Controls.Add(this.labelControl41); + this.groupBox5.Controls.Add(this.textEdit29); + this.groupBox5.Controls.Add(this.textEdit30); + this.groupBox5.Controls.Add(this.labelControl42); + this.groupBox5.Controls.Add(this.labelControl43); + this.groupBox5.Controls.Add(this.textEdit23); + this.groupBox5.Controls.Add(this.labelControl31); + this.groupBox5.Controls.Add(this.textEdit31); + this.groupBox5.Controls.Add(this.labelControl44); + this.groupBox5.Controls.Add(this.textEdit32); + this.groupBox5.Controls.Add(this.labelControl45); + this.groupBox5.Controls.Add(this.textEdit33); + this.groupBox5.Controls.Add(this.labelControl46); + this.groupBox5.Location = new System.Drawing.Point(36, 128); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(810, 331); + this.groupBox5.TabIndex = 1; + this.groupBox5.TabStop = false; + this.groupBox5.Text = " 转链信息 "; + // + // labelControl54 + // + this.labelControl54.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl54.Appearance.Options.UseForeColor = true; + this.labelControl54.Location = new System.Drawing.Point(774, 90); + this.labelControl54.Name = "labelControl54"; + this.labelControl54.Size = new System.Drawing.Size(12, 154); + this.labelControl54.TabIndex = 5; + this.labelControl54.Text = "︵\r\n点\r\n击\r\n编\r\n辑\r\n框\r\n自\r\n动\r\n复\r\n制\r\n︶"; + // + // memoEdit3 + // + this.memoEdit3.Location = new System.Drawing.Point(148, 151); + this.memoEdit3.Name = "memoEdit3"; + this.memoEdit3.Size = new System.Drawing.Size(604, 71); + this.memoEdit3.TabIndex = 2; + this.memoEdit3.Click += new System.EventHandler(this.textEdit1_Click); + // + // textEdit25 + // + this.textEdit25.Location = new System.Drawing.Point(148, 229); + this.textEdit25.Name = "textEdit25"; + this.textEdit25.Size = new System.Drawing.Size(604, 20); + this.textEdit25.TabIndex = 1; + this.textEdit25.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl35 + // + this.labelControl35.Location = new System.Drawing.Point(58, 232); + this.labelControl35.Name = "labelControl35"; + this.labelControl35.Size = new System.Drawing.Size(84, 14); + this.labelControl35.TabIndex = 0; + this.labelControl35.Text = "合成优惠券图:"; + // + // textEdit22 + // + this.textEdit22.Location = new System.Drawing.Point(148, 283); + this.textEdit22.Name = "textEdit22"; + this.textEdit22.Size = new System.Drawing.Size(604, 20); + this.textEdit22.TabIndex = 1; + this.textEdit22.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl30 + // + this.labelControl30.Location = new System.Drawing.Point(58, 286); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(84, 14); + this.labelControl30.TabIndex = 0; + this.labelControl30.Text = "生成单买链接:"; + // + // textEdit26 + // + this.textEdit26.Location = new System.Drawing.Point(148, 256); + this.textEdit26.Name = "textEdit26"; + this.textEdit26.Size = new System.Drawing.Size(604, 20); + this.textEdit26.TabIndex = 1; + this.textEdit26.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl36 + // + this.labelControl36.Location = new System.Drawing.Point(58, 259); + this.labelControl36.Name = "labelControl36"; + this.labelControl36.Size = new System.Drawing.Size(84, 14); + this.labelControl36.TabIndex = 0; + this.labelControl36.Text = "生成拼团链接:"; + // + // labelControl37 + // + this.labelControl37.Appearance.ForeColor = System.Drawing.Color.DarkGray; + this.labelControl37.Appearance.Options.UseForeColor = true; + this.labelControl37.Location = new System.Drawing.Point(36, 173); + this.labelControl37.Name = "labelControl37"; + this.labelControl37.Size = new System.Drawing.Size(106, 14); + this.labelControl37.TabIndex = 0; + this.labelControl37.Text = "(第一个为商品主图)"; + // + // labelControl38 + // + this.labelControl38.Location = new System.Drawing.Point(70, 153); + this.labelControl38.Name = "labelControl38"; + this.labelControl38.Size = new System.Drawing.Size(72, 14); + this.labelControl38.TabIndex = 0; + this.labelControl38.Text = "商品详情图:"; + // + // textEdit35 + // + this.textEdit35.Location = new System.Drawing.Point(702, 125); + this.textEdit35.Name = "textEdit35"; + this.textEdit35.Size = new System.Drawing.Size(50, 20); + this.textEdit35.TabIndex = 1; + this.textEdit35.Click += new System.EventHandler(this.textEdit1_Click); + // + // textEdit27 + // + this.textEdit27.Location = new System.Drawing.Point(702, 94); + this.textEdit27.Name = "textEdit27"; + this.textEdit27.Size = new System.Drawing.Size(50, 20); + this.textEdit27.TabIndex = 1; + this.textEdit27.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl48 + // + this.labelControl48.Location = new System.Drawing.Point(616, 128); + this.labelControl48.Name = "labelControl48"; + this.labelControl48.Size = new System.Drawing.Size(84, 14); + this.labelControl48.TabIndex = 0; + this.labelControl48.Text = "拼团弃券返利:"; + // + // labelControl39 + // + this.labelControl39.Location = new System.Drawing.Point(616, 97); + this.labelControl39.Name = "labelControl39"; + this.labelControl39.Size = new System.Drawing.Size(84, 14); + this.labelControl39.TabIndex = 0; + this.labelControl39.Text = "单买弃券返利:"; + // + // textEdit34 + // + this.textEdit34.Location = new System.Drawing.Point(558, 125); + this.textEdit34.Name = "textEdit34"; + this.textEdit34.Size = new System.Drawing.Size(50, 20); + this.textEdit34.TabIndex = 1; + this.textEdit34.Click += new System.EventHandler(this.textEdit1_Click); + // + // textEdit28 + // + this.textEdit28.Location = new System.Drawing.Point(558, 94); + this.textEdit28.Name = "textEdit28"; + this.textEdit28.Size = new System.Drawing.Size(50, 20); + this.textEdit28.TabIndex = 1; + this.textEdit28.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl47 + // + this.labelControl47.Location = new System.Drawing.Point(472, 128); + this.labelControl47.Name = "labelControl47"; + this.labelControl47.Size = new System.Drawing.Size(84, 14); + this.labelControl47.TabIndex = 0; + this.labelControl47.Text = "拼团券后返利:"; + // + // labelControl40 + // + this.labelControl40.Location = new System.Drawing.Point(472, 97); + this.labelControl40.Name = "labelControl40"; + this.labelControl40.Size = new System.Drawing.Size(84, 14); + this.labelControl40.TabIndex = 0; + this.labelControl40.Text = "单买券后返利:"; + // + // labelControl41 + // + this.labelControl41.Location = new System.Drawing.Point(70, 97); + this.labelControl41.Name = "labelControl41"; + this.labelControl41.Size = new System.Drawing.Size(72, 14); + this.labelControl41.TabIndex = 0; + this.labelControl41.Text = "优惠券金额:"; + // + // textEdit29 + // + this.textEdit29.Location = new System.Drawing.Point(272, 94); + this.textEdit29.Name = "textEdit29"; + this.textEdit29.Size = new System.Drawing.Size(36, 20); + this.textEdit29.TabIndex = 1; + this.textEdit29.Click += new System.EventHandler(this.textEdit1_Click); + // + // textEdit30 + // + this.textEdit30.Location = new System.Drawing.Point(148, 94); + this.textEdit30.Name = "textEdit30"; + this.textEdit30.Size = new System.Drawing.Size(50, 20); + this.textEdit30.TabIndex = 1; + this.textEdit30.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl42 + // + this.labelControl42.Location = new System.Drawing.Point(310, 97); + this.labelControl42.Name = "labelControl42"; + this.labelControl42.Size = new System.Drawing.Size(12, 14); + this.labelControl42.TabIndex = 0; + this.labelControl42.Text = "%"; + // + // labelControl43 + // + this.labelControl43.Location = new System.Drawing.Point(210, 97); + this.labelControl43.Name = "labelControl43"; + this.labelControl43.Size = new System.Drawing.Size(60, 14); + this.labelControl43.TabIndex = 0; + this.labelControl43.Text = "返利比例:"; + // + // textEdit23 + // + this.textEdit23.Location = new System.Drawing.Point(408, 125); + this.textEdit23.Name = "textEdit23"; + this.textEdit23.Size = new System.Drawing.Size(50, 20); + this.textEdit23.TabIndex = 1; + this.textEdit23.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl31 + // + this.labelControl31.Location = new System.Drawing.Point(334, 128); + this.labelControl31.Name = "labelControl31"; + this.labelControl31.Size = new System.Drawing.Size(72, 14); + this.labelControl31.TabIndex = 0; + this.labelControl31.Text = "商品拼团价:"; + // + // textEdit31 + // + this.textEdit31.Location = new System.Drawing.Point(408, 94); + this.textEdit31.Name = "textEdit31"; + this.textEdit31.Size = new System.Drawing.Size(50, 20); + this.textEdit31.TabIndex = 1; + this.textEdit31.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl44 + // + this.labelControl44.Location = new System.Drawing.Point(346, 97); + this.labelControl44.Name = "labelControl44"; + this.labelControl44.Size = new System.Drawing.Size(60, 14); + this.labelControl44.TabIndex = 0; + this.labelControl44.Text = "商品单价:"; + // + // textEdit32 + // + this.textEdit32.Location = new System.Drawing.Point(148, 62); + this.textEdit32.Name = "textEdit32"; + this.textEdit32.Size = new System.Drawing.Size(604, 20); + this.textEdit32.TabIndex = 1; + this.textEdit32.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl45 + // + this.labelControl45.Location = new System.Drawing.Point(82, 65); + this.labelControl45.Name = "labelControl45"; + this.labelControl45.Size = new System.Drawing.Size(60, 14); + this.labelControl45.TabIndex = 0; + this.labelControl45.Text = "商品标题:"; + // + // textEdit33 + // + this.textEdit33.Location = new System.Drawing.Point(148, 31); + this.textEdit33.Name = "textEdit33"; + this.textEdit33.Size = new System.Drawing.Size(604, 20); + this.textEdit33.TabIndex = 1; + this.textEdit33.Click += new System.EventHandler(this.textEdit1_Click); + // + // labelControl46 + // + this.labelControl46.Location = new System.Drawing.Point(82, 34); + this.labelControl46.Name = "labelControl46"; + this.labelControl46.Size = new System.Drawing.Size(60, 14); + this.labelControl46.TabIndex = 0; + this.labelControl46.Text = "商品链接:"; + // + // convert_tool_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.xtraTabControl1); + this.Name = "convert_tool_control"; + this.Size = new System.Drawing.Size(885, 519); + this.Load += new System.EventHandler(this.convert_tool_control_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraScrollableControl1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit10.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit37.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit11.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit9.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit8.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + this.xtraTabPage4.ResumeLayout(false); + this.groupBox8.ResumeLayout(false); + this.groupBox8.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit44.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit42.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit43.Properties)).EndInit(); + this.groupBox7.ResumeLayout(false); + this.groupBox7.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit41.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit38.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit47.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit39.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit40.Properties)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraScrollableControl2.ResumeLayout(false); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit7.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit14.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit15.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit16.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit17.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit18.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit19.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit20.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit21.Properties)).EndInit(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit24.Properties)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraScrollableControl3.ResumeLayout(false); + this.groupBox6.ResumeLayout(false); + this.groupBox6.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit36.Properties)).EndInit(); + this.groupBox5.ResumeLayout(false); + this.groupBox5.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit25.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit22.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit26.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit35.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit27.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit34.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit28.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit29.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit30.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit23.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit31.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit32.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit33.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraEditors.XtraScrollableControl xtraScrollableControl1; + private System.Windows.Forms.GroupBox groupBox3; + private DevExpress.XtraEditors.MemoEdit memoEdit2; + private DevExpress.XtraEditors.TextEdit textEdit7; + private DevExpress.XtraEditors.LabelControl labelControl18; + private DevExpress.XtraEditors.TextEdit textEdit14; + private DevExpress.XtraEditors.LabelControl labelControl19; + private DevExpress.XtraEditors.LabelControl labelControl20; + private DevExpress.XtraEditors.LabelControl labelControl21; + private DevExpress.XtraEditors.TextEdit textEdit15; + private DevExpress.XtraEditors.LabelControl labelControl22; + private DevExpress.XtraEditors.TextEdit textEdit16; + private DevExpress.XtraEditors.LabelControl labelControl23; + private DevExpress.XtraEditors.LabelControl labelControl24; + private DevExpress.XtraEditors.TextEdit textEdit17; + private DevExpress.XtraEditors.TextEdit textEdit18; + private DevExpress.XtraEditors.LabelControl labelControl25; + private DevExpress.XtraEditors.LabelControl labelControl26; + private DevExpress.XtraEditors.TextEdit textEdit19; + private DevExpress.XtraEditors.LabelControl labelControl27; + private DevExpress.XtraEditors.TextEdit textEdit20; + private DevExpress.XtraEditors.LabelControl labelControl28; + private DevExpress.XtraEditors.TextEdit textEdit21; + private DevExpress.XtraEditors.LabelControl labelControl29; + private System.Windows.Forms.GroupBox groupBox5; + private DevExpress.XtraEditors.MemoEdit memoEdit3; + private DevExpress.XtraEditors.TextEdit textEdit25; + private DevExpress.XtraEditors.LabelControl labelControl35; + private DevExpress.XtraEditors.TextEdit textEdit26; + private DevExpress.XtraEditors.LabelControl labelControl36; + private DevExpress.XtraEditors.LabelControl labelControl37; + private DevExpress.XtraEditors.LabelControl labelControl38; + private DevExpress.XtraEditors.TextEdit textEdit27; + private DevExpress.XtraEditors.LabelControl labelControl39; + private DevExpress.XtraEditors.TextEdit textEdit28; + private DevExpress.XtraEditors.LabelControl labelControl40; + private DevExpress.XtraEditors.LabelControl labelControl41; + private DevExpress.XtraEditors.TextEdit textEdit29; + private DevExpress.XtraEditors.TextEdit textEdit30; + private DevExpress.XtraEditors.LabelControl labelControl42; + private DevExpress.XtraEditors.LabelControl labelControl43; + private DevExpress.XtraEditors.TextEdit textEdit31; + private DevExpress.XtraEditors.LabelControl labelControl44; + private DevExpress.XtraEditors.TextEdit textEdit32; + private DevExpress.XtraEditors.LabelControl labelControl45; + private DevExpress.XtraEditors.TextEdit textEdit33; + private DevExpress.XtraEditors.LabelControl labelControl46; + private System.Windows.Forms.GroupBox groupBox6; + private System.Windows.Forms.ComboBox comboBox3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.TextEdit textEdit36; + private DevExpress.XtraEditors.LabelControl labelControl49; + private DevExpress.XtraEditors.LabelControl labelControl50; + private DevExpress.XtraEditors.LabelControl labelControl51; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.TextEdit textEdit10; + private DevExpress.XtraEditors.LabelControl labelControl16; + private DevExpress.XtraEditors.TextEdit textEdit11; + private DevExpress.XtraEditors.LabelControl labelControl12; + private DevExpress.XtraEditors.LabelControl labelControl15; + private DevExpress.XtraEditors.LabelControl labelControl11; + private DevExpress.XtraEditors.TextEdit textEdit9; + private DevExpress.XtraEditors.LabelControl labelControl10; + private DevExpress.XtraEditors.TextEdit textEdit8; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.TextEdit textEdit6; + private DevExpress.XtraEditors.TextEdit textEdit5; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.TextEdit textEdit3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl17; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.ComboBox comboBox2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.TextEdit textEdit24; + private DevExpress.XtraEditors.LabelControl labelControl32; + private DevExpress.XtraEditors.LabelControl labelControl33; + private DevExpress.XtraEditors.LabelControl labelControl34; + private DevExpress.XtraEditors.XtraScrollableControl xtraScrollableControl2; + private DevExpress.XtraEditors.XtraScrollableControl xtraScrollableControl3; + private DevExpress.XtraEditors.TextEdit textEdit22; + private DevExpress.XtraEditors.LabelControl labelControl30; + private DevExpress.XtraEditors.TextEdit textEdit23; + private DevExpress.XtraEditors.LabelControl labelControl31; + private DevExpress.XtraEditors.TextEdit textEdit35; + private DevExpress.XtraEditors.LabelControl labelControl48; + private DevExpress.XtraEditors.TextEdit textEdit34; + private DevExpress.XtraEditors.LabelControl labelControl47; + private DevExpress.XtraEditors.LabelControl labelControl52; + private DevExpress.XtraEditors.LabelControl labelControl53; + private DevExpress.XtraEditors.LabelControl labelControl54; + private DevExpress.XtraEditors.TextEdit textEdit37; + private DevExpress.XtraEditors.LabelControl labelControl55; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private System.Windows.Forms.GroupBox groupBox7; + private DevExpress.XtraEditors.TextEdit textEdit38; + private DevExpress.XtraEditors.TextEdit textEdit39; + private DevExpress.XtraEditors.LabelControl labelControl56; + private DevExpress.XtraEditors.TextEdit textEdit40; + private DevExpress.XtraEditors.LabelControl labelControl57; + private DevExpress.XtraEditors.LabelControl labelControl58; + private DevExpress.XtraEditors.LabelControl labelControl64; + private DevExpress.XtraEditors.LabelControl labelControl63; + private DevExpress.XtraEditors.LabelControl labelControl62; + private DevExpress.XtraEditors.LabelControl labelControl61; + private DevExpress.XtraEditors.LabelControl labelControl60; + private DevExpress.XtraEditors.TextEdit textEdit41; + private DevExpress.XtraEditors.LabelControl labelControl59; + private DevExpress.XtraEditors.SimpleButton simpleButton4; + private DevExpress.XtraEditors.LabelControl labelControl65; + private DevExpress.XtraEditors.SimpleButton simpleButton5; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit47; + private DevExpress.XtraEditors.LabelControl labelControl66; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.GroupBox groupBox8; + private DevExpress.XtraEditors.TextEdit textEdit42; + private DevExpress.XtraEditors.LabelControl labelControl67; + private DevExpress.XtraEditors.TextEdit textEdit43; + private DevExpress.XtraEditors.LabelControl labelControl68; + private DevExpress.XtraEditors.TextEdit textEdit44; + private DevExpress.XtraEditors.LabelControl labelControl69; + } +} diff --git a/FLSystem/Forms/convert_tool_control.cs b/FLSystem/Forms/convert_tool_control.cs new file mode 100644 index 0000000..932e2d4 --- /dev/null +++ b/FLSystem/Forms/convert_tool_control.cs @@ -0,0 +1,1022 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using FLSystem.Properties; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class convert_tool_control : XtraUserControl + { + public convert_tool_control() + { + InitializeComponent(); + } + + private void convert_tool_control_Load(object sender, EventArgs e) + { + try + { + this.Disposed += Control_Disposed; + this.comboBox1.SelectedIndex = this.comboBox2.SelectedIndex = this.comboBox3.SelectedIndex = 0; + + var session = ApiClient.GetSession(); + #region 阿里妈妈转链基础数据加载 + var tbadzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.ConvertToolSoftwareType); + if (tbadzone != null)//数据库中存在的情况 + { + hyperlinkLabelControl1.Text = tbadzone.adzone_name; + hyperlinkLabelControl1.Tag = tbadzone; + } + #endregion + + #region 淘礼金 + + var cpsmembers = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈 && f.is_valid).ToList(); + List cpsList = new List(); + cpsList.Add("手动填写数据"); + for (int i = 0; i < cpsmembers.Count; i++) + { + cpsList.Add($"{cpsmembers[i].username}({cpsmembers[i].usernick})"); + } + this.comboBoxEdit1.Properties.Items.AddRange(cpsList); + + comboBoxEdit1.SelectedIndex = 0; + + dateTimePicker2.Value = DateTime.Now; + dateTimePicker2.Value = DateTime.Now.AddDays(1); + + #endregion + + #region 京东 + var jdadzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.ConvertToolSoftwareType); + if (jdadzone != null)//数据库中存在的情况 + { + hyperlinkLabelControl2.Text = jdadzone.adzone_name; + hyperlinkLabelControl2.Tag = jdadzone; + } + #endregion + + #region 拼多多 + var pddadzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.ConvertToolSoftwareType); + if (pddadzone != null)//数据库中存在的情况 + { + hyperlinkLabelControl3.Text = pddadzone.adzone_name; + hyperlinkLabelControl3.Tag = pddadzone; + } + #endregion + + } + catch (Exception ex) + { + XtraMessageBox.Show($"{ex.Message}", "系统异常", MessageBoxButtons.OK); + } + } + private void Control_Disposed(object sender, EventArgs e) + { + + } + + private void textEdit1_Click(object sender, EventArgs e) + { + if (sender is TextEdit) + { + var edit = sender as TextEdit; + edit.SelectAll(); + if (!string.IsNullOrWhiteSpace(edit.Text)) + Clipboard.SetDataObject(edit.Text); + } + } + + private void textEdit1_Click_1(object sender, EventArgs e) + { + if (sender is TextEdit) + { + var edit = sender as TextEdit; + edit.SelectAll(); + } + } + + private async void simpleButton1_Click(object sender, EventArgs e) + { + _ControlEnabled(); + var t1 = Task.Run(() => + { + if (hyperlinkLabelControl1.Tag == null) throw new Exception("请设置推广位"); + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("请填写要解析链接或者淘口令"); + + var twg = hyperlinkLabelControl1.Tag as fl_adzone_info; + + var tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == twg.adzone_pid_cps_name); + if (tb_cps == null) throw new Exception("推广位异常"); + AlimamaApi api = CpsClient.CreateAlimamaRequest(tb_cps); + + var tbAnalysis = new TBHelper.TbAnalysis(); + var pid_split = twg.adzone_pid.Split('_'); + + var item_id = string.Empty; + try + { + item_id = tbAnalysis.FindItemIdByUrlAndTklAndMkl(textEdit1.Text, api, pid_split); + } + catch (Exception) + { + throw new Exception("无法解析宝贝信息!"); + } + if (string.IsNullOrWhiteSpace(item_id)) throw new Exception("无法解析宝贝信息!"); + + var turnItem = api.TurnItemId(item_id, tbAnalysis.activityId, pid_split[3], pid_split[2], "2"); + + //淘口令的前/后符号有没有设置.有设置将替换掉 + var tkl = tbAnalysis.ReplaceTklModifier(turnItem.BuyPass); + + //coupon_click_url = tbAnalysis.FindShortUrlBySrcUrl(coupon_click_url, api); + + //var temp_url = api.ComposeTbClick(item_id, pict_url, tkl, tklInfo.isoUrl, true, twg.adzone_pid, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品);//中间页地址 + + #region 将内容填写到控件中 + this.Invoke(new Action(() => + { + try + { + textEdit2.Text = turnItem.ItemUrl;//商品链接 + textEdit3.Text = turnItem.ItemTitle;//商品标题 + textEdit4.Text = turnItem.Price.ToString("0.00");//商品单价 + textEdit5.Text = turnItem.CouponPrice.ToString("0.00");//优惠券金额 + textEdit6.Text = (turnItem.CommissionRatio * 100m).ToString("0.00");//返利比例 + textEdit8.Text = turnItem.CommissionUseCouponMoney.ToString("0.00");//券后返利 + textEdit9.Text = turnItem.CommissionUnUseCouponMoney.ToString("0.00");//弃券返利 + textEdit11.Text = tkl;//生成淘口令 + textEdit37.Text = turnItem.BuyUrl;//短连接 + textEdit10.Text = ApiClient.GetQRImage(turnItem.ItemTitle, turnItem.Price.ToString("0.00"), turnItem.CouponPrice.ToString(), turnItem.UseCouponPrice.ToString("0.00"), turnItem.ImageUrl, turnItem.ZJYUrl, comboBox1.SelectedIndex == 0 ? ApiClient.QrImageType.模板A : ApiClient.QrImageType.模板B);//合成优惠券图 + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "操作异常", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + })); + + #region 获取预览图 + StringBuilder strb = new StringBuilder(); + int num = 0; + Next: + HttpItem httpItem = new HttpItem() + { + URL = @"https://item.taobao.com/item.htm?id=" + item_id,//宝贝的链接 + Method = "get", + IsToLower = false, + Timeout = 10000, + ReadWriteTimeout = 10000, + Allowautoredirect = true, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + ContentType = "application/x-www-form-urlencoded" + }; + HttpHelper http = new HttpHelper(); + var result = http.GetHtml(httpItem); + + if (result != null && result.Html == "操作超时" && num <= 3) + { + num++; + goto Next; + } + var regs = Regex.Matches(result.Html, @".+?.jpg)_([^""]*?)"""); + + if (regs.Count != 0) + { + strb.Length = 0; + var shopIcon = string.Empty; + var QRCodeUrl = string.Empty;//获取其中一张图片用于合成二维码 + for (int i = 0; i < regs.Count; i++) + { + var previewPic = regs[i].Groups["商品预览图"].Value; + if (!previewPic.StartsWith("http")) + { + previewPic = $"http:{previewPic}"; + if (string.IsNullOrEmpty(shopIcon)) shopIcon = previewPic; + } + strb.AppendLine(previewPic); + } + } + #endregion + + this.Invoke(new Action(() => + { + memoEdit1.Text = strb.ToString();//商品预览图 + })); + #endregion + + }); + + try + { + await t1; + } + catch (global::System.Exception ex) + { + XtraMessageBox.Show($"{ex.Message}", "系统异常", MessageBoxButtons.OK); + } + + _ControlEnabled(true); + } + + private void _ControlEnabled(bool flag = false) + { + simpleButton1.Enabled = hyperlinkLabelControl1.Enabled = comboBox1.Enabled = flag; + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.ConvertToolSoftwareType); + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + else + { + try + { + adzone = new fl_adzone_info() + { + custom_type = Resources.ConvertToolSoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = 0, //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + throw ex; + } + } + hyperlinkLabelControl1.Text = adzone.adzone_name; + hyperlinkLabelControl1.Tag = adzone; + session.FindAdzoneInfos(true); + } + } + catch (Exception ex) + { + XtraMessageBox.Show($"{ex.Message}", "系统异常", MessageBoxButtons.OK); + } + } + + private void hyperlinkLabelControl2_Click(object sender, EventArgs e) + { + try + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.京东联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.ConvertToolSoftwareType); + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + else + { + try + { + adzone = new fl_adzone_info() + { + custom_type = Resources.ConvertToolSoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.京东联盟, //联盟id + robot_id = 0, //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { } + } + hyperlinkLabelControl2.Text = adzone.adzone_name; + hyperlinkLabelControl2.Tag = adzone; + session.FindAdzoneInfos(true); + } + } + catch (Exception ex) + { + XtraMessageBox.Show($"{ex.Message}", "系统异常", MessageBoxButtons.OK); + } + } + + private void hyperlinkLabelControl3_Click(object sender, EventArgs e) + { + try + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.多多进宝); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.ConvertToolSoftwareType); + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + else + { + try + { + adzone = new fl_adzone_info() + { + custom_type = Resources.ConvertToolSoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = 0, //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + throw ex; + } + } + hyperlinkLabelControl3.Text = adzone.adzone_name; + hyperlinkLabelControl3.Tag = adzone; + session.FindAdzoneInfos(true); + } + } + catch (Exception ex) + { + XtraMessageBox.Show($"{ex.Message}", "系统异常", MessageBoxButtons.OK); + } + } + + private async void simpleButton2_Click(object sender, EventArgs e) + { + hyperlinkLabelControl2.Enabled = simpleButton2.Enabled = comboBox2.Enabled = false; + var t1 = Task.Run(() => + { + if (hyperlinkLabelControl2.Tag == null) throw new Exception("请设置推广位"); + if (string.IsNullOrWhiteSpace(textEdit24.Text)) throw new Exception("请填写要解析的京东链接"); + + var itemId = JDHelper.GetJingdongItemId(textEdit24.Text);//匹配京东链接获取京东宝贝ID + if (!string.IsNullOrEmpty(itemId)) + { + var twg = hyperlinkLabelControl2.Tag as fl_adzone_info; + JingdongApi api = null; + var session = ApiClient.GetSession(); + var jd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟 && f.username == twg.adzone_pid_cps_name); + if (jd_cps == null) throw new Exception("京东联盟推广位异常,请检测后重试!"); + + api = new JingdongApi(jd_cps); + + var goodInfoResult = api.SendJingdong("jd.union.open.goods.query", new { goodsReqDTO = new { skuIds = new string[] { itemId } } }); + + var goodData = goodInfoResult.ConvertToObj(); + var goodDatas = goodData.data; + if (goodDatas == null) throw new Exception("京东无返利信息"); + + foreach (Dictionary _goodinfo in goodDatas) + { + var goodinfo = _goodinfo.ConvertToObj(); + goodinfo.skuName = goodinfo.skuName.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); + + if (goodinfo.commissionInfo.Count != 0)//有佣金 + { + var isJdSale = goodinfo.isJdSale == 0 ? false : true;//是否已是京东自营 + + double price = double.Parse(goodinfo.priceInfo["price"].ToString()); //商品价格 + + //var commission = goodinfo.commissionInfo["commission"].ToString(); //佣金 + + var commissionshare = decimal.Parse(goodinfo.commissionInfo["commissionShare"].ToString()) / 100m;//普通用户佣金比例 ,通用接口中的佣金比例 + + #region 这里主要是获取改商品的实际佣金比例,上面的佣金比例是通用的佣金比例,会不准一些 + try + { + var goodResult = api.SendJingdong("jd.union.open.goods.promotiongoodsinfo.query", new { skuIds = itemId }); + if (goodResult != null && goodResult.ContainsKey("data")) + { + var _goodData = goodResult["data"] as ArrayList; + if (_goodData != null && _goodData.Count != 0) + { + foreach (Dictionary data in _goodData) + { + if (data.ContainsKey("commisionRatioWl")) + { + commissionshare = decimal.Parse(data["commisionRatioWl"].ToString()) / 100m; //接口中该商品的实际佣金,比较准一些, + break; + } + } + } + } + } + catch (Exception) + { } + #endregion + + string couponlike = string.Empty; //优惠券链接 + double discount = -1; //优惠券金额 + decimal usecoupon_totalcommfee = 0; + if (goodinfo.couponInfo.Count != 0) + { + var couponList = goodinfo.couponInfo["couponList"] as ArrayList; + if (couponList.Count != 0)//有优惠券 + { + foreach (Dictionary coupon in couponList) + { + var quota = double.Parse(coupon["quota"].ToString()); //券消费限额 + if (quota > price) break;//优惠券面额大于商品单价时终止 + discount = double.Parse(coupon["discount"].ToString()); + #region 普通用户 + usecoupon_totalcommfee = usecoupon_totalcommfee = decimal.Round(((decimal)price - (decimal)discount) * commissionshare, 2);//券后 总佣金(自营) + if (!isJdSale) + usecoupon_totalcommfee = decimal.Round(usecoupon_totalcommfee * 0.9m, 2);//券后 总佣金(非自营) + #endregion + + couponlike = coupon["link"].ToString(); //优惠券链接 + break;//TODO 这里难道有多个优惠券?先不管,直接获取第一个 + } + } + } + #region 普通用户 + //不用券 佣金 + var unusecoupon_totalcommfee = decimal.Round((decimal)price * commissionshare, 2);//券后 总佣金(自营) + if (!isJdSale) + unusecoupon_totalcommfee = decimal.Round(unusecoupon_totalcommfee * 0.9m, 2);//券后 总佣金(非自营) + #endregion + + var buyshorturl = string.Empty; //转连后的地址 + #region 转连(生成自己推广的链接 [有券链接(二合一)或无券链接]) + Dictionary conversionlinkresult = null; //查询到的转换链接对象 + var positionId = twg.adzone_pid.Substring(twg.adzone_pid.LastIndexOf("_") + 1); + if (string.IsNullOrWhiteSpace(couponlike)) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{itemId}.html", positionId = positionId, unionId = jd_cps.usernick } });//宝贝id 和 用户的目标推客的联盟id + } + else + { + try + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{itemId}.html", positionId = positionId, unionId = jd_cps.usernick, couponUrl = couponlike } }); + } + catch (Exception) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{itemId}.html", positionId = positionId, unionId = jd_cps.usernick } });//宝贝id 和 用户的目标推客的联盟id + couponlike = string.Empty; + discount = -1; + } + } + if (conversionlinkresult != null) + { + if (conversionlinkresult["code"].ToString() != "200") throw new Exception($"京东查询接口调用失败:{conversionlinkresult["message"].ToString()}");//抛出错误信息 + if (conversionlinkresult.ContainsKey("data")) + { + var data = conversionlinkresult["data"] as Dictionary; + if (data.ContainsKey("shortURL")) buyshorturl = data["shortURL"].ToString();//购买短连接 + } + if (string.IsNullOrWhiteSpace(buyshorturl)) throw new Exception("京东转链失败,请稍后重试"); + } + #endregion + + var imageList = goodinfo.imageInfo["imageList"] as ArrayList; + string imageUrl = string.Empty; + StringBuilder strb = new StringBuilder(); + for (int i = 0; i < imageList.Count; i++) + { + if (string.IsNullOrWhiteSpace(imageUrl)) + imageUrl = (imageList[i] as Dictionary)["url"].ToString(); + + strb.AppendLine((imageList[i] as Dictionary)["url"].ToString()); + } + + this.Invoke(new Action(() => + { + try + { + textEdit21.Text = $"https://item.jd.com/{itemId}.html";//商品链接 + textEdit20.Text = goodinfo.skuName;//商品标题 + textEdit19.Text = goodinfo.priceInfo["price"].ToString();//商品单价 + textEdit18.Text = discount.ToString("0.00");//优惠券金额 + textEdit17.Text = commissionshare.ToString("0.00");//返利比例 + textEdit16.Text = usecoupon_totalcommfee.ToString("0.00");//券后返利 + textEdit15.Text = unusecoupon_totalcommfee.ToString("0.00");//弃权返利 + textEdit7.Text = ApiClient.GetQRImage(goodinfo.skuName, price.ToString(), discount.ToString(), ((decimal)price - (decimal)discount).ToString(), imageUrl, buyshorturl, comboBox2.SelectedIndex == 0 ? ApiClient.QrImageType.模板A : ApiClient.QrImageType.模板B, CpsType.京东联盟);//合成优惠券图 + textEdit14.Text = buyshorturl;//转换后的链接 + memoEdit2.Text = imageUrl;//商品图片 + } + catch (Exception ex) + { + + MessageBox.Show(ex.Message, "操作异常", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + })); + } + } + } + }); + + try + { + await t1; + } + catch (Exception ex) + { + XtraMessageBox.Show($"{ex.Message}", "系统异常", MessageBoxButtons.OK); + } + + hyperlinkLabelControl2.Enabled = simpleButton2.Enabled = comboBox2.Enabled = true; + } + + private async void simpleButton3_Click(object sender, EventArgs e) + { + hyperlinkLabelControl3.Enabled = simpleButton3.Enabled = comboBox3.Enabled = false; + var t1 = Task.Run(() => + { + if (hyperlinkLabelControl3.Tag == null) throw new Exception("请设置推广位"); + if (string.IsNullOrWhiteSpace(textEdit36.Text)) throw new Exception("请填写要解析的拼多多链接"); + + var goods_id = PDDHelper.GetPddGoodsID(textEdit36.Text); + if (!string.IsNullOrEmpty(goods_id)) + { + var twg = hyperlinkLabelControl3.Tag as fl_adzone_info; + + var session = ApiClient.GetSession(); + + fl_cps_member pdd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == twg.adzone_pid_cps_name); + + if (pdd_cps == null) throw new Exception("拼多多推广位设置异常,请检测后重试!"); + + PinduoduoApi api = CpsClient.CreatePinduoduoRequest(pdd_cps); + var data = new { goods_id_list = $"[{goods_id}]" }; + + ArrayList goods_details = null; + + var isBind = false; + + var result = api.SendPinduoduo("pdd.ddk.oauth.member.authority.query", new { pid = twg.adzone_pid }); + if (result.ContainsKey("authority_query_response")) + { + var authority_query_response = result["authority_query_response"] as Dictionary; + if (authority_query_response != null && authority_query_response.Count != 0) + isBind = int.Parse(authority_query_response["bind"].ToString()) == 1;//1-已绑定;0-未绑定 + } + + goods_details = PDDHelper.FindSendGuideGoodsInfo(api, twg.adzone_pid, goods_id, isBind); + + //没有查到返利提示 + if (goods_details == null || goods_details.Count == 0) + throw new Exception("无法解析该商品"); + + foreach (var item in goods_details) + { + var temp = item as Dictionary; + var goods_name = (temp["goods_name"] ?? string.Empty).ToString().Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); //获取商品标签 + var goods_desc = (temp["goods_desc"] ?? string.Empty).ToString(); //商品描述 + var goods_thumbnail_url = (temp["goods_thumbnail_url"] ?? string.Empty).ToString(); //商品主图 + + var goods_sign = temp["goods_sign"].ToString(); + + StringBuilder strb = new StringBuilder(); + if (temp.ContainsKey("goods_gallery_urls")) + { + var images = temp["goods_gallery_urls"] as ArrayList; + foreach (var image in images) + { + strb.AppendLine(image.ToString()); + } + } + var min_group_price = Math.Round(temp["min_group_price"] == null ? 0 : (double.Parse(temp["min_group_price"].ToString()) / 100.00), 2); //最低价sku的拼团价,单位为分 + var min_normal_price = Math.Round(temp["min_normal_price"] == null ? 0 : (double.Parse(temp["min_normal_price"].ToString()) / 100.00), 2); //最低价sku的单买价,单位为 + var _coupon_discount = double.Parse((temp["coupon_discount"] ?? 0).ToString()); + var coupon_discount = _coupon_discount == 0 ? 0 : Math.Round(_coupon_discount / 100.00, 2); //优惠券面额,单位为分 + double promotion_rate = 0d;//佣金比例,千分比 + if (temp["promotion_rate"] != null) + promotion_rate = double.Parse(temp["promotion_rate"].ToString()) / 1000.00; + promotion_rate = Math.Round(promotion_rate, 3); + + var pdd_api = new PDDHelper(); + var manyShoppingUrl = pdd_api.GetShoppingUrl(api, new { p_id = twg.adzone_pid, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, force_duo_id = true, generate_authority_url = !isBind, generate_schema_url = true }); + + var oneShoppingUrl = pdd_api.GetShoppingUrl(api, new { p_id = twg.adzone_pid, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, force_duo_id = true, generate_authority_url = !isBind, generate_schema_url = true }); + + this.Invoke(new Action(() => + { + try + { + textEdit33.Text = @"https://mobile.yangkeduo.com/goods.html?goods_id=" + goods_id;//商品连接 + textEdit32.Text = goods_name;//商品标题 + textEdit31.Text = min_normal_price.ToString("0.00");//商品单价 + textEdit30.Text = coupon_discount.ToString("0.00");//优惠券金额 + textEdit29.Text = ((decimal)promotion_rate * 100m).ToString("0.00");//返利比例 + textEdit28.Text = ((min_normal_price - coupon_discount) * promotion_rate).ToString("0.00");//单买券后返利 + textEdit27.Text = (min_normal_price * promotion_rate).ToString("0.00");//单买弃券返利 + textEdit23.Text = min_group_price.ToString("0.00");//商品拼团价 + textEdit34.Text = ((min_group_price - coupon_discount) * promotion_rate).ToString("0.00");//拼团券后返利 + textEdit35.Text = (min_group_price * promotion_rate).ToString("0.00");//拼团价弃权返利 + + textEdit25.Text = ApiClient.GetQRImage(goods_name, min_normal_price.ToString(), coupon_discount.ToString(), ((decimal)min_normal_price - (decimal)coupon_discount).ToString(), goods_thumbnail_url, manyShoppingUrl, comboBox3.SelectedIndex == 0 ? ApiClient.QrImageType.模板A : ApiClient.QrImageType.模板B, CpsType.多多进宝);//合成优惠券图 + textEdit26.Text = manyShoppingUrl;//生成拼团链接 + textEdit22.Text = oneShoppingUrl;//生成单买链接 + memoEdit3.Text = strb.ToString();//商品详情图 + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "操作异常", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + })); + } + } + + }); + + try + { + await t1; + } + catch (Exception ex) + { + XtraMessageBox.Show($"{ex.Message}", "系统异常", MessageBoxButtons.OK); + } + + hyperlinkLabelControl3.Enabled = simpleButton3.Enabled = comboBox3.Enabled = true; + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + fl_alimama_tlj_info tlj = null; + if (comboBoxEdit1.SelectedIndex != 0) + { + tlj = GetTlj(comboBoxEdit1.SelectedText); + if (tlj == null) throw new Exception($"淘宝账号:{comboBoxEdit1.SelectedText},还没有设置对应的淘礼金"); + textEdit40.Text = tlj.appkey; + textEdit39.Text = tlj.appsecret; + textEdit47.Text = tlj.adzone_pid; + } + simpleButton5.Enabled = comboBoxEdit1.SelectedIndex != 0; + textEdit40.Text = tlj == null ? string.Empty : tlj.appkey; + textEdit39.Text = tlj == null ? string.Empty : tlj.appsecret; + textEdit47.Text = tlj == null ? string.Empty : tlj.adzone_pid; + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex); + } + } + + /// + /// 获取选中的阿里妈妈账号信息(第一个值为 账号,第二个值为 昵称) + /// + /// + private List GetSelectCpsInfo() + { + var reg = Regex.Match(comboBoxEdit1.SelectedText, "^(?<账号>[^(]+?)((?<昵称>.*?))$"); + if (reg.Success) + { + return new List() { reg.Groups["账号"].Value, reg.Groups["昵称"].Value }; + } + return null; + } + + private fl_alimama_tlj_info GetTlj(string text) + { + var cpsInfo = GetSelectCpsInfo(); + if (cpsInfo != null) + { + var session = ApiClient.GetSession(); + var tljs = session.FindTljInfos(true); + return tljs.FirstOrDefault(f => f.username == cpsInfo[0]); + } + return null; + } + + private void simpleButton5_Click(object sender, EventArgs e) + { + try + { + var cpsInfo = GetSelectCpsInfo(); + if (cpsInfo != null) + { + var tljform = new tlj_form(cpsInfo[1], cpsInfo[0]); + tljform.ShowDialog(); + comboBoxEdit1_SelectedIndexChanged(null, null); + } + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex); + } + } + + /// + /// 生成淘礼金与短链接 + /// + /// + /// + private void simpleButton4_Click(object sender, EventArgs e) + { + try + { + var tljUrl = textEdit38.Text.Trim(); + var tljPid = textEdit47.Text.Trim(); + var appSecret = textEdit39.Text.Trim(); + var appKey = textEdit40.Text.Trim(); + var tljName = textEdit41.Text.Trim(); + var user_total_win_num_limit = (int)numericUpDown3.Value; //每人限领礼金个数 + var per_face = (double)numericUpDown1.Value; //单个淘礼金金额 + var total_num = (int)numericUpDown2.Value; //淘礼金总个数 + var send_start_time = dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss"); + var send_end_time = dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss"); + + if (string.IsNullOrWhiteSpace(appKey)) throw new Exception("淘礼金AppKey不能为空"); + if (string.IsNullOrWhiteSpace(appSecret)) throw new Exception("淘礼金AppSecret不能为空"); + if (string.IsNullOrWhiteSpace(tljPid)) throw new Exception("淘礼金推广位PID不能为空"); + if (string.IsNullOrWhiteSpace(tljUrl)) throw new Exception("商品链接不能为空"); + if (string.IsNullOrWhiteSpace(tljName)) throw new Exception("淘礼金领取名称不能为空"); + + var reg = Regex.Match(tljPid, @"mm_(?\d+)_(?\d+)_(?\d+)"); + if (!reg.Success) throw new Exception($"淘宝推广位格式不正确"); + var cpsname = reg.Groups["cpsname"].Value; + var pid1 = reg.Groups["pid1"].Value; + var pid2 = reg.Groups["pid2"].Value; + + var tb_cps = new fl_cps_member() { username = cpsname, cpstype = CpsType.阿里妈妈, cookies = string.Empty, is_download = SwitchType.关闭, abnormal_tip = SwitchType.关闭, online = true, usernick = string.Empty }; + AlimamaApi api = CpsClient.CreateAlimamaRequest(tb_cps); + if (api == null) throw new Exception("创建淘宝API请求失败"); + + //获取商品的id + var tbAnalysis = new TBHelper.TbAnalysis(); + var item_id = string.Empty; + try + { + item_id = tbAnalysis.FindItemIdByUrlAndTklAndMkl(tljUrl, api, tljPid.Split('_')); + } + catch (Exception) + { + throw new Exception("无法解析商品链接"); + } + if (string.IsNullOrWhiteSpace(item_id)) throw new Exception("无法解析商品链接"); + + var result = api.GetItemInfo(item_id, "2"); + if (result == null) + { + throw new Exception("商品基础信息查询失败"); + } + + if (result.n_tbk_item == null || result.n_tbk_item.Count == 0) + { + throw new Exception("获取商品信息失败,请稍后重试"); + } + + + var queryItemData = result.n_tbk_item[0]; + + if (queryItemData == null) + { + throw new Exception("商品基础信息查询失败"); + } + + //商品主图 + var pict_url = queryItemData.pict_url; + + var session = ApiClient.GetSession(); + if (!session.FindTljCreateNum(cpsname)) + throw new Exception("该淘宝账号ID今日创建淘礼金次数已耗尽"); + + var tljResult = api.SendTaobao("taobao.tbk.dg.vegas.tlj.create", new { adzone_id = pid2, item_id = item_id, security_switch = "true", total_num = total_num, name = tljName, user_total_win_num_limit = user_total_win_num_limit, per_face = per_face, send_start_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), send_end_time = send_end_time }, appKey, appSecret); + + if (tljResult != null && tljResult.ContainsKey("success")) + { + if (tljResult["success"].ToString().ToLower() == "false") + { + if (tljResult.ContainsKey("msg_info")) + { + var msg = tljResult["msg_info"].ToString(); + if (msg == "您创建的淘礼金商品数目已达上限") + session.ExcuteSQL("update fl_alimama_tlj_create_record set number = 30 where cpsname = @cpsname", new { cpsname = cpsname }); + throw new Exception("该淘宝账号ID今日创建淘礼金次数已耗尽"); + } + throw new Exception(tljResult.ContainsKey("msg_info") ? tljResult["msg_info"].ToString() : $"生成淘礼金失败,{HttpHelper.ObjectToJson(tljResult)}"); + } + + if (tljResult.ContainsKey("model")) + { + var model = tljResult["model"] as Dictionary; + if (model.ContainsKey("send_url")) + { + var send_url = model["send_url"].ToString(); + + if (!string.IsNullOrWhiteSpace(tbAnalysis.activityId)) + send_url = send_url + "&activityId=" + tbAnalysis.activityId; + + var tklInfo = tbAnalysis.FindTKL(send_url, api); + + if (tklInfo != null) + { + textEdit43.Text = tklInfo.tkl; + textEdit42.Text = api.ComposeTbClick(item_id, pict_url, tklInfo.tkl, tklInfo.isoUrl, true, tljPid, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品); + textEdit44.Text = tbAnalysis.FindShortUrlBySrcUrl(send_url, api); ; + + #region 统计次数 + session.AddTljCreateNum(cpsname); + #endregion + + } + } + } + } + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex.Message); + } + } + + private void dateTimePicker_ValueChanged(object sender, EventArgs e) + { + if (dateTimePicker1.Value >= dateTimePicker2.Value) + dateTimePicker2.Value = dateTimePicker1.Value.AddDays(1); + } + } + + #region 京东类 + public class goodInfo_temp + { + /// + /// 返回码 + /// + public int code { get; set; } + /// + /// 数据明细 + /// + //public List data { get; set; } + public ArrayList data { get; set; } + /// + /// 返回消息 + /// + public string message { get; set; } + /// + /// + /// + public string requestId { get; set; } + /// + /// 有效商品总数量,上限10w + /// + public long totalCount { get; set; } + } + + /// + /// 数据明细 + /// + public class GoodsResp + { + /// + /// 品牌code + /// + public string brandCode { get; set; } + /// + /// 品牌名 + /// + public string brandName { get; set; } + /// + /// 类目信息 + /// + //public List categoryInfo { get; set; } + public Dictionary categoryInfo { get; set; } + /// + /// 评论数 + /// + public long comments { get; set; } + /// + /// 佣金信息 + /// + //public List commissionInfo { get; set; } + public Dictionary commissionInfo { get; set; } + /// + /// 优惠券信息,返回内容为空说明该SKU无可用优惠券 + /// + //public List couponInfo { get; set; } + public Dictionary couponInfo { get; set; } + /// + /// 商品好评率 + /// + public double goodCommentsShare { get; set; } + /// + /// 图片信息 + /// + //public List imageInfo { get; set; } + public Dictionary imageInfo { get; set; } + /// + /// 30天支出佣金 + /// + public double inOrderComm30Days { get; set; } + /// + /// 30天引单量 + /// + public long inOrderCount30Days { get; set; } + /// + /// 是否爆款,1:是,0:否 + /// + public int isHot { get; set; } + /// + /// 是否自营 (1 : 是, 0 : 否),后续会废弃,请用owner + /// + public int isJdSale { get; set; } + /// + /// 商品落地页 + /// + public string materialUrl { get; set; } + /// + /// g=自营,p=pop + /// + public string owner { get; set; } + /// + /// 拼购信息 + /// + //public List pinGouInfo { get; set; } + public Dictionary pinGouInfo { get; set; } + /// + /// 已废弃,请使用pinGouInfo + /// + //public List pingGouInfo { get; set; } + public Dictionary pingGouInfo { get; set; } + /// + /// 价格信息 + /// + //public List priceInfo { get; set; } + public Dictionary priceInfo { get; set; } + /// + /// 店铺信息 + /// + //public List shopInfo { get; set; } + public Dictionary shopInfo { get; set; } + /// + /// 商品ID + /// + public long skuId { get; set; } + /// + /// 商品名称 + /// + public string skuName { get; set; } + /// + /// spuid,其值为同款商品的主skuid + /// + public long spuid { get; set; } + } + + #endregion +} diff --git a/FLSystem/Forms/convert_tool_control.resx b/FLSystem/Forms/convert_tool_control.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Forms/convert_tool_control.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_coerce_alimama.Designer.cs b/FLSystem/Forms/cps_coerce_alimama.Designer.cs new file mode 100644 index 0000000..8589a3b --- /dev/null +++ b/FLSystem/Forms/cps_coerce_alimama.Designer.cs @@ -0,0 +1,429 @@ +namespace FLSystem.Forms +{ + partial class cps_coerce_alimama + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_coerce_alimama)); + this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.label2 = new System.Windows.Forms.Label(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.simpleButton3); + this.groupControl1.Controls.Add(this.simpleButton2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(847, 76); + this.groupControl1.TabIndex = 3; + this.groupControl1.Text = "搜索条件"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(485, 34); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(82, 27); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "一键结算"; + this.simpleButton1.Visible = false; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // simpleButton3 + // + this.simpleButton3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(372, 34); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(79, 27); + this.simpleButton3.TabIndex = 7; + this.simpleButton3.Text = "搜索"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(717, 34); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(86, 27); + this.simpleButton2.TabIndex = 5; + this.simpleButton2.Text = "一键结算"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(475, 40); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(226, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "( 此功能用于阿里妈妈账号被封,谨慎操作 )"; + // + // labelControl2 + // + this.labelControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl2.Location = new System.Drawing.Point(61, 40); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(84, 14); + this.labelControl2.TabIndex = 6; + this.labelControl2.Text = "淘宝联盟账号:"; + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Location = new System.Drawing.Point(151, 37); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(202, 20); + this.textEdit1.TabIndex = 1; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 491); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(847, 33); + this.pageControl1.TabIndex = 5; + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(308, 245); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(231, 35); + this.label2.TabIndex = 16; + this.label2.Text = "订单列表为空"; + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn9, + this.gridColumn22, + this.gridColumn14, + this.gridColumn6, + this.gridColumn5, + this.gridColumn1, + this.gridColumn3, + this.gridColumn10, + this.gridColumn11, + this.gridColumn18, + this.gridColumn12, + this.gridColumn2, + this.gridColumn16, + this.gridColumn13, + this.gridColumn17}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn15 + // + this.gridColumn15.Caption = "创建时间"; + this.gridColumn15.FieldName = "create_time"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 150; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "trade_parent_id"; + this.gridColumn4.MinWidth = 200; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 200; + // + // gridColumn9 + // + this.gridColumn9.Caption = "付款金额"; + this.gridColumn9.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn9.FieldName = "alipay_total_price"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 2; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "维权金额"; + this.gridColumn22.FieldName = "refundFee"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.OptionsColumn.AllowEdit = false; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 4; + this.gridColumn22.Width = 69; + // + // gridColumn14 + // + this.gridColumn14.Caption = "状态"; + this.gridColumn14.FieldName = "db_status"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 5; + this.gridColumn6.Width = 100; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户名"; + this.gridColumn5.FieldName = "username"; + this.gridColumn5.MinWidth = 120; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 6; + this.gridColumn5.Width = 120; + // + // gridColumn1 + // + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "item_title"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 7; + this.gridColumn1.Width = 350; + // + // gridColumn3 + // + this.gridColumn3.Caption = "商品编号"; + this.gridColumn3.FieldName = "num_iid"; + this.gridColumn3.MinWidth = 120; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 8; + this.gridColumn3.Width = 120; + // + // gridColumn10 + // + this.gridColumn10.Caption = "商品单价"; + this.gridColumn10.FieldName = "price"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 9; + // + // gridColumn11 + // + this.gridColumn11.Caption = "购买数量"; + this.gridColumn11.FieldName = "item_num"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 10; + // + // gridColumn18 + // + this.gridColumn18.Caption = "冻结时间"; + this.gridColumn18.FieldName = "db_endtime"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 11; + // + // gridColumn12 + // + this.gridColumn12.Caption = "宝贝类型"; + this.gridColumn12.FieldName = "order_type"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 12; + // + // gridColumn2 + // + this.gridColumn2.Caption = "联盟账号"; + this.gridColumn2.FieldName = "db_cpsname"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 13; + this.gridColumn2.Width = 100; + // + // gridColumn16 + // + this.gridColumn16.Caption = "联盟昵称"; + this.gridColumn16.FieldName = "db_cpsnick"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 15; + this.gridColumn16.Width = 100; + // + // gridColumn13 + // + this.gridColumn13.Caption = "推广位"; + this.gridColumn13.FieldName = "adzone_id"; + this.gridColumn13.MinWidth = 120; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 14; + this.gridColumn13.Width = 120; + // + // gridColumn17 + // + this.gridColumn17.Caption = "子订单号"; + this.gridColumn17.FieldName = "trade_id"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 16; + this.gridColumn17.Width = 180; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(0, 82); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(847, 403); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // cps_coerce_alimama + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.label2); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.pageControl1); + this.Name = "cps_coerce_alimama"; + this.Size = new System.Drawing.Size(847, 524); + this.Load += new System.EventHandler(this.cps_coerce_alimama_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.ComponentModel.BackgroundWorker backgroundWorker1; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} diff --git a/FLSystem/Forms/cps_coerce_alimama.cs b/FLSystem/Forms/cps_coerce_alimama.cs new file mode 100644 index 0000000..b08a885 --- /dev/null +++ b/FLSystem/Forms/cps_coerce_alimama.cs @@ -0,0 +1,213 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; +using static FLSystem.Forms.cps_order_alimama; + +namespace FLSystem.Forms +{ + public partial class cps_coerce_alimama : DevExpress.XtraEditors.XtraUserControl + { + public cps_coerce_alimama() + { + InitializeComponent(); + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("请输入要一键结算的淘宝联盟账号"); + + if (gridView1.RowCount == 0) throw new Exception("数据列表为空,操作终止!"); + + if (MessageBox.Show("确定结算所有该联盟下所有的订单吗", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + //var orders = session.Q1ueryable().Where(f => f.db_cpsname == textEdit1.Text.Trim() && (f.db_status == SystemOrderStatus.订单付款 || f.db_status == SystemOrderStatus.订单冻结)).ToList(); + var orders = ApiClient.GetSession().Find("select * from fl_order_alimama where db_cpsname = @db_cpsname and (db_status = @db_status1 or db_status = @db_status2)", new { db_cpsname = textEdit1.Text.Trim(), db_status1 = SystemOrderStatus.订单付款, db_status2 = SystemOrderStatus.订单冻结 }); + + if (orders.Count != 0) + { + Task.Run(() => + { + var session = ApiClient.GetSession(); + try + { + var task = TimerTask.GetTimer() as DownAlimamaTimer; + var notices = new List(); + foreach (var order in orders) + { + tokenSource.Token.ThrowIfCancellationRequested(); + order.earning_time = DateTime.Now.AddSeconds(-2); + order.tk_status = 3; + order.db_endtime = DateTime.Now; + order.db_status = SystemOrderStatus.订单冻结; + + task.UpdateOrder(order, notices, session); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + + foreach (var item in notices) + { + tokenSource.Token.ThrowIfCancellationRequested(); + if (item.Member == null) continue; + if (item.Order is fl_order_alimama) + tasks.Add(item); + } + XtraMessageBox.Show($"一键结算成功,一共结算{orders.Count}笔订单!", "温馨提示", MessageBoxButtons.OK); + } + catch (Exception) + { } + }, tokenSource.Token); + } + else + XtraMessageBox.Show($"当前无可结算的订单!", "温馨提示", MessageBoxButtons.OK); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(); + } + + private void cps_coerce_alimama_Load(object sender, EventArgs e) + { + this.Disposed += Control_Disposed; + this.pageControl1.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var map = session.NewParamMap(); + map.setPageParamters(index, pagesize); + map.setOrderFields("create_time", true); + PageResult result = null; + #region 通过联盟名称 一键结算 + + map.setParameter("fk", (int)SystemOrderStatus.订单付款); + map.setParameter("dj", (int)SystemOrderStatus.订单冻结); + map.setParameter("db_cpsname", textEdit1.Text.Trim()); + + result = session.FindPage("select o.db_cpsname,o.trade_id,o.db_cpsnick,o.id,o.item_title,o.num_iid,o.trade_parent_id,o.db_status,u.username,u.usernick,o.pub_share_pre_fee,o.alipay_total_price,o.price,o.item_num,o.order_type,o.adzone_id,o.create_time,o.db_point,o.db_endtime,ra.showReturnFee,ra.refundFee from fl_order_alimama o LEFT JOIN fl_member_info u on o.db_userid=u.id LEFT JOIN fl_order_refund_alimama ra on ra.tbTradeParentId = o.trade_parent_id and ra.tbTradeId = o.trade_id where (o.db_status = @fk or o.db_status = @dj) and o.db_cpsname = @db_cpsname", map); + #endregion + + label2.Visible = result.Total == 0; + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + }, this.gridControl1, 50, true, true); + } + + private void Control_Disposed(object sender, EventArgs e) + { + tokenSource.Cancel(); + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "软件状态": + e.DisplayText = Util.ConvertEnum(int.Parse(e.Value.ToString())).ToString(); + break; + case "一级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString())["AwardOne"].ToString(); + break; + case "二级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString())["AwardTwo"].ToString(); + break; + case "三级提成": + { + var result = HttpExtend.JsonToDictionary(e.Value.ToString()); + e.DisplayText = (result != null && result.ContainsKey("AwardThree")) ? result["AwardThree"].ToString() : "0"; + } + break; + case "群负责人提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString())["AwardCreate"].ToString(); + break; + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + + //if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("请输入要一键结算的淘宝联盟账号"); + + //if (gridView1.RowCount == 0) throw new Exception("数据列表为空,操作终止!"); + + if (MessageBox.Show("确定结算所有联盟的订单吗", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + //var orders = session.Q1ueryable().Where(f => f.db_cpsname == textEdit1.Text.Trim() && (f.db_status == SystemOrderStatus.订单付款 || f.db_status == SystemOrderStatus.订单冻结)).ToList(); + var orders = session.Find("select * from fl_order_alimama where (db_status = @db_status1 or db_status = @db_status2)", new { db_status1 = SystemOrderStatus.订单付款, db_status2 = SystemOrderStatus.订单冻结 }); + + if (orders.Count != 0) + { + Task.Run(() => + { + try + { + var task = TimerTask.GetTimer() as DownAlimamaTimer; + var notices = new List(); + foreach (var order in orders) + { + tokenSource.Token.ThrowIfCancellationRequested(); + order.earning_time = DateTime.Now.AddSeconds(-2); + order.tk_status = 3; + order.db_endtime = DateTime.Now; + order.db_status = SystemOrderStatus.订单冻结; + + task.UpdateOrder(order, notices, session); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + + foreach (var item in notices) + { + tokenSource.Token.ThrowIfCancellationRequested(); + if (item.Member == null) continue; + if (item.Order is fl_order_alimama) + tasks.Add(item); + } + XtraMessageBox.Show($"一键结算成功,一共结算{orders.Count}笔订单!", "温馨提示", MessageBoxButtons.OK); + } + catch (Exception) + { } + }, tokenSource.Token); + } + else + XtraMessageBox.Show($"当前无可结算的订单!", "温馨提示", MessageBoxButtons.OK); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/FLSystem/Forms/cps_coerce_alimama.resx b/FLSystem/Forms/cps_coerce_alimama.resx new file mode 100644 index 0000000..263e412 --- /dev/null +++ b/FLSystem/Forms/cps_coerce_alimama.resx @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 33, 20 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAEFjY291bnRpbmc7Soc56AAAAs9J + REFUOE910u1LU2EYBvBDagpFUJkmUv9BIVFBKEntg1JSKRRRgUWMtMQlS5jQi1amlKGWqWnOab5sai7U + NDLQFCduzqmb0+a0WW56zjbX5svUmVfnnJkpqwd+3B/OfV/PDc8hSsSqdmHtIP4aQEnNZm9q+lFUpWwn + CMILALERwTQsuVY8LC6v4NfqKlsZRdV9dDfh4xFQLFZhiW5IqtODJxlFgngY8ZVa3CjXgisawnXhIIyW + ORRU9DIBWz0CCit74Vxawb0P31ClMqNCacZbJYVyBYUyBQmeWIcf1CzyynqYAF+PgFflPVhYdCG5Xg9+ + 3SiSanRIrB5BQuUwblZoEUdvMkHakVPS9e+AXKEM804XbHOLbrNuMxuMT9mR9bqDCfDzCHhe1InZhWXw + H0qh0lNs7dOR63XsTCQMpAONrUNMwDaa9xov2hYiM78N9vklKL+SUI6QUKyRj0ytI2fm0Fpfg0ZBWGdL + Siiako9Byjv8RcQ9GEM8zv2Mn/SazI09WpO7Drlr91o1WRxoST0FUt1Mb+0+kwopxNwDJHE/qwVWxyJk + GhOri9anm4buuxWGKRvGTTYYjGa8Ob8fdm0BVqwdGBFxMd2ZjqKYfSBSMhphsTvZmzoGJtk6ZrShWVKF + 9rx4NAvC2JUlcSHQSpPgNLVCU3gFxta7yD8bDIKfJgVlW4B63MIapBkpOz6mnQalbgBcNqwuW2GUS/CO + dxT2sfdQZUfD0MTHy6ggENw7ZW3XeCJc5ZUiNlHIqm2QozA6GHZ1LlzkJ2jyLsDY4h6gNFVQZERAXxeP + nIi9zMsQvjTmebZv4J8XFQxrdyqcegn6n3AwIY5lByblxZA9CIcs+xyecgLNm36KP+jjlx0ZRGlKL8Gh + eAGFIATy9HBmwJVxIgDPOAF4dHyP6vaRXZf/F+AtCPW/mHkyQJnFCVwfuHVoZyz9bTdtB43emvD5DRlF + wtjAtpm0AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAEFjY291bnRpbmc7Soc56AAAAs9J + REFUOE910u1LU2EYBvBDagpFUJkmUv9BIVFBKEntg1JSKRRRgUWMtMQlS5jQi1amlKGWqWnOab5sai7U + NDLQFCduzqmb0+a0WW56zjbX5svUmVfnnJkpqwd+3B/OfV/PDc8hSsSqdmHtIP4aQEnNZm9q+lFUpWwn + CMILALERwTQsuVY8LC6v4NfqKlsZRdV9dDfh4xFQLFZhiW5IqtODJxlFgngY8ZVa3CjXgisawnXhIIyW + ORRU9DIBWz0CCit74Vxawb0P31ClMqNCacZbJYVyBYUyBQmeWIcf1CzyynqYAF+PgFflPVhYdCG5Xg9+ + 3SiSanRIrB5BQuUwblZoEUdvMkHakVPS9e+AXKEM804XbHOLbrNuMxuMT9mR9bqDCfDzCHhe1InZhWXw + H0qh0lNs7dOR63XsTCQMpAONrUNMwDaa9xov2hYiM78N9vklKL+SUI6QUKyRj0ytI2fm0Fpfg0ZBWGdL + Siiako9Byjv8RcQ9GEM8zv2Mn/SazI09WpO7Drlr91o1WRxoST0FUt1Mb+0+kwopxNwDJHE/qwVWxyJk + GhOri9anm4buuxWGKRvGTTYYjGa8Ob8fdm0BVqwdGBFxMd2ZjqKYfSBSMhphsTvZmzoGJtk6ZrShWVKF + 9rx4NAvC2JUlcSHQSpPgNLVCU3gFxta7yD8bDIKfJgVlW4B63MIapBkpOz6mnQalbgBcNqwuW2GUS/CO + dxT2sfdQZUfD0MTHy6ggENw7ZW3XeCJc5ZUiNlHIqm2QozA6GHZ1LlzkJ2jyLsDY4h6gNFVQZERAXxeP + nIi9zMsQvjTmebZv4J8XFQxrdyqcegn6n3AwIY5lByblxZA9CIcs+xyecgLNm36KP+jjlx0ZRGlKL8Gh + eAGFIATy9HBmwJVxIgDPOAF4dHyP6vaRXZf/F+AtCPW/mHkyQJnFCVwfuHVoZyz9bTdtB43emvD5DRlF + wtjAtpm0AAAAAElFTkSuQmCC + + + + 69 + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_manage_control.Designer.cs b/FLSystem/Forms/cps_manage_control.Designer.cs new file mode 100644 index 0000000..e6dfeb4 --- /dev/null +++ b/FLSystem/Forms/cps_manage_control.Designer.cs @@ -0,0 +1,1017 @@ +namespace FLSystem.Forms +{ + partial class cps_manage_control + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_manage_control)); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.barManager1 = new DevExpress.XtraBars.BarManager(this.components); + this.barDockControlTop = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlBottom = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlLeft = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlRight = new DevExpress.XtraBars.BarDockControl(); + this.barButtonItem1 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem1 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem2 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem3 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem4 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem5 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem6 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem7 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem2 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem9 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem8 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem10 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem42 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem43 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem44 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem46 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem11 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem12 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem3 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem13 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem14 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem15 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem16 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem17 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem18 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem4 = new DevExpress.XtraBars.BarSubItem(); + this.barSubItem8 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem21 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem22 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem23 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem24 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem9 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem25 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem26 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem31 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem32 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem10 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem27 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem28 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem33 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem34 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem11 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem29 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem30 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem35 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem36 = new DevExpress.XtraBars.BarButtonItem(); + this.barCheckItem1 = new DevExpress.XtraBars.BarCheckItem(); + this.barButtonItem19 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem5 = new DevExpress.XtraBars.BarSubItem(); + this.barSubItem6 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem20 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem7 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem37 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem12 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem38 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem39 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem40 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem41 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem45 = new DevExpress.XtraBars.BarButtonItem(); + this.popupMenu1 = new DevExpress.XtraBars.PopupMenu(this.components); + this.timer1 = new System.Windows.Forms.Timer(this.components); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.barManager1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.popupMenu1)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.MenuManager = this.barManager1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemPictureEdit1}); + this.gridControl1.Size = new System.Drawing.Size(818, 503); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + this.gridControl1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.gridControl1_MouseUp); + // + // gridView1 + // + this.gridView1.AppearancePrint.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.AppearancePrint.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.AppearancePrint.Row.Options.UseTextOptions = true; + this.gridView1.AppearancePrint.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn2, + this.gridColumn7, + this.gridColumn3, + this.gridColumn4, + this.gridColumn5, + this.gridColumn6, + this.gridColumn9, + this.gridColumn8, + this.gridColumn1}); + this.gridView1.FocusRectStyle = DevExpress.XtraGrid.Views.Grid.DrawFocusRectStyle.None; + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.Editable = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomDrawRowIndicator += new DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventHandler(this.gridView1_CustomDrawRowIndicator); + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseImage = true; + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "图标"; + this.gridColumn2.ColumnEdit = this.repositoryItemPictureEdit1; + this.gridColumn2.FieldName = "gridColumn2"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 0; + this.gridColumn2.Width = 50; + // + // repositoryItemPictureEdit1 + // + this.repositoryItemPictureEdit1.Name = "repositoryItemPictureEdit1"; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn7.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "联盟"; + this.gridColumn7.FieldName = "cpstype"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.OptionsColumn.ReadOnly = true; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 1; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号"; + this.gridColumn3.FieldName = "username"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.OptionsColumn.ReadOnly = true; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 133; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "昵称"; + this.gridColumn4.FieldName = "usernick"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.OptionsColumn.ReadOnly = true; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + this.gridColumn4.Width = 133; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn5.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "登录时间"; + this.gridColumn5.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn5.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn5.FieldName = "logintime"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.OptionsColumn.ReadOnly = true; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 133; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn6.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "接口类型"; + this.gridColumn6.FieldName = "cpstype"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.OptionsColumn.ReadOnly = true; + this.gridColumn6.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 5; + this.gridColumn6.Width = 139; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn9.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "同步状态"; + this.gridColumn9.FieldName = "is_download"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 6; + this.gridColumn9.Width = 71; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn8.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "异常通知"; + this.gridColumn8.FieldName = "abnormal_tip"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 7; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "状态"; + this.gridColumn1.FieldName = "gridColumn7"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 8; + // + // barManager1 + // + this.barManager1.DockControls.Add(this.barDockControlTop); + this.barManager1.DockControls.Add(this.barDockControlBottom); + this.barManager1.DockControls.Add(this.barDockControlLeft); + this.barManager1.DockControls.Add(this.barDockControlRight); + this.barManager1.Form = this; + this.barManager1.Items.AddRange(new DevExpress.XtraBars.BarItem[] { + this.barButtonItem1, + this.barSubItem1, + this.barButtonItem2, + this.barButtonItem3, + this.barButtonItem4, + this.barButtonItem5, + this.barButtonItem6, + this.barButtonItem7, + this.barSubItem2, + this.barButtonItem8, + this.barButtonItem9, + this.barButtonItem10, + this.barButtonItem11, + this.barButtonItem12, + this.barSubItem3, + this.barButtonItem13, + this.barButtonItem14, + this.barButtonItem15, + this.barButtonItem16, + this.barButtonItem17, + this.barButtonItem18, + this.barSubItem4, + this.barCheckItem1, + this.barButtonItem19, + this.barSubItem5, + this.barSubItem6, + this.barButtonItem20, + this.barSubItem7, + this.barSubItem8, + this.barSubItem9, + this.barSubItem10, + this.barSubItem11, + this.barButtonItem21, + this.barButtonItem22, + this.barButtonItem23, + this.barButtonItem24, + this.barButtonItem25, + this.barButtonItem26, + this.barButtonItem27, + this.barButtonItem28, + this.barButtonItem29, + this.barButtonItem30, + this.barButtonItem31, + this.barButtonItem32, + this.barButtonItem33, + this.barButtonItem34, + this.barButtonItem35, + this.barButtonItem36, + this.barButtonItem37, + this.barSubItem12, + this.barButtonItem38, + this.barButtonItem39, + this.barButtonItem40, + this.barButtonItem41, + this.barButtonItem42, + this.barButtonItem43, + this.barButtonItem44, + this.barButtonItem45, + this.barButtonItem46}); + this.barManager1.MaxItemId = 60; + // + // barDockControlTop + // + this.barDockControlTop.CausesValidation = false; + this.barDockControlTop.Dock = System.Windows.Forms.DockStyle.Top; + this.barDockControlTop.Location = new System.Drawing.Point(0, 0); + this.barDockControlTop.Manager = this.barManager1; + this.barDockControlTop.Size = new System.Drawing.Size(818, 0); + // + // barDockControlBottom + // + this.barDockControlBottom.CausesValidation = false; + this.barDockControlBottom.Dock = System.Windows.Forms.DockStyle.Bottom; + this.barDockControlBottom.Location = new System.Drawing.Point(0, 503); + this.barDockControlBottom.Manager = this.barManager1; + this.barDockControlBottom.Size = new System.Drawing.Size(818, 0); + // + // barDockControlLeft + // + this.barDockControlLeft.CausesValidation = false; + this.barDockControlLeft.Dock = System.Windows.Forms.DockStyle.Left; + this.barDockControlLeft.Location = new System.Drawing.Point(0, 0); + this.barDockControlLeft.Manager = this.barManager1; + this.barDockControlLeft.Size = new System.Drawing.Size(0, 503); + // + // barDockControlRight + // + this.barDockControlRight.CausesValidation = false; + this.barDockControlRight.Dock = System.Windows.Forms.DockStyle.Right; + this.barDockControlRight.Location = new System.Drawing.Point(818, 0); + this.barDockControlRight.Manager = this.barManager1; + this.barDockControlRight.Size = new System.Drawing.Size(0, 503); + // + // barButtonItem1 + // + this.barButtonItem1.Caption = "刷新数据"; + this.barButtonItem1.Id = 0; + this.barButtonItem1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem1.ImageOptions.Image"))); + this.barButtonItem1.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem1.ImageOptions.LargeImage"))); + this.barButtonItem1.Name = "barButtonItem1"; + this.barButtonItem1.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem1_ItemClick); + // + // barSubItem1 + // + this.barSubItem1.Caption = "同步订单"; + this.barSubItem1.Id = 1; + this.barSubItem1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barSubItem1.ImageOptions.Image"))); + this.barSubItem1.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barSubItem1.ImageOptions.LargeImage"))); + this.barSubItem1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem3), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem4), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem5)}); + this.barSubItem1.Name = "barSubItem1"; + // + // barButtonItem2 + // + this.barButtonItem2.Caption = "最近1天"; + this.barButtonItem2.Id = 2; + this.barButtonItem2.Name = "barButtonItem2"; + this.barButtonItem2.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem2_ItemClick); + // + // barButtonItem3 + // + this.barButtonItem3.Caption = "最近7天"; + this.barButtonItem3.Id = 4; + this.barButtonItem3.Name = "barButtonItem3"; + this.barButtonItem3.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem3_ItemClick); + // + // barButtonItem4 + // + this.barButtonItem4.Caption = "最近30天"; + this.barButtonItem4.Id = 5; + this.barButtonItem4.Name = "barButtonItem4"; + this.barButtonItem4.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem4_ItemClick); + // + // barButtonItem5 + // + this.barButtonItem5.Caption = "最近90天"; + this.barButtonItem5.Id = 6; + this.barButtonItem5.Name = "barButtonItem5"; + this.barButtonItem5.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem5_ItemClick); + // + // barButtonItem6 + // + this.barButtonItem6.Caption = "删除账号"; + this.barButtonItem6.Id = 7; + this.barButtonItem6.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem6.ImageOptions.Image"))); + this.barButtonItem6.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem6.ImageOptions.LargeImage"))); + this.barButtonItem6.Name = "barButtonItem6"; + this.barButtonItem6.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem6_ItemClick); + // + // barButtonItem7 + // + this.barButtonItem7.Caption = "登录联盟"; + this.barButtonItem7.Id = 8; + this.barButtonItem7.Name = "barButtonItem7"; + // + // barSubItem2 + // + this.barSubItem2.Caption = "登录联盟"; + this.barSubItem2.Id = 9; + this.barSubItem2.ImageOptions.Image = global::FLSystem.Properties.Resources.授权__3_; + this.barSubItem2.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem9), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem8), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem10), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem42), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem43), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem44), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem46)}); + this.barSubItem2.Name = "barSubItem2"; + // + // barButtonItem9 + // + this.barButtonItem9.Caption = "登录多多进宝"; + this.barButtonItem9.Id = 11; + this.barButtonItem9.ImageOptions.Image = global::FLSystem.Properties.Resources.拼多多_20; + this.barButtonItem9.Name = "barButtonItem9"; + this.barButtonItem9.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem9_ItemClick); + // + // barButtonItem8 + // + this.barButtonItem8.Caption = "登录阿里妈妈"; + this.barButtonItem8.Id = 10; + this.barButtonItem8.ImageOptions.Image = global::FLSystem.Properties.Resources.淘宝_20; + this.barButtonItem8.Name = "barButtonItem8"; + this.barButtonItem8.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem8_ItemClick); + // + // barButtonItem10 + // + this.barButtonItem10.Caption = "登录京东联盟"; + this.barButtonItem10.Id = 12; + this.barButtonItem10.ImageOptions.Image = global::FLSystem.Properties.Resources.京东_20; + this.barButtonItem10.Name = "barButtonItem10"; + this.barButtonItem10.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem10_ItemClick); + // + // barButtonItem42 + // + this.barButtonItem42.Caption = "登录唯品会联盟"; + this.barButtonItem42.Id = 55; + this.barButtonItem42.ImageOptions.Image = global::FLSystem.Properties.Resources.唯品会12; + this.barButtonItem42.Name = "barButtonItem42"; + this.barButtonItem42.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem42_ItemClick); + // + // barButtonItem43 + // + this.barButtonItem43.Caption = "登录抖音联盟"; + this.barButtonItem43.Enabled = false; + this.barButtonItem43.Id = 56; + this.barButtonItem43.ImageOptions.Image = global::FLSystem.Properties.Resources.抖音; + this.barButtonItem43.Name = "barButtonItem43"; + this.barButtonItem43.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem43_ItemClick); + // + // barButtonItem44 + // + this.barButtonItem44.Caption = "苏宁易购联盟"; + this.barButtonItem44.Id = 57; + this.barButtonItem44.ImageOptions.Image = global::FLSystem.Properties.Resources.苏宁小; + this.barButtonItem44.Name = "barButtonItem44"; + this.barButtonItem44.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem44_ItemClick); + // + // barButtonItem46 + // + this.barButtonItem46.Caption = "登录快手联盟"; + this.barButtonItem46.Id = 59; + this.barButtonItem46.ImageOptions.Image = global::FLSystem.Properties.Resources.快手登录; + this.barButtonItem46.Name = "barButtonItem46"; + this.barButtonItem46.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem46_ItemClick); + // + // barButtonItem11 + // + this.barButtonItem11.Caption = "同步"; + this.barButtonItem11.Id = 13; + this.barButtonItem11.Name = "barButtonItem11"; + // + // barButtonItem12 + // + this.barButtonItem12.Caption = "批量全部同步"; + this.barButtonItem12.Id = 14; + this.barButtonItem12.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem12.ImageOptions.LargeImage"))); + this.barButtonItem12.ImageOptions.SvgImage = ((DevExpress.Utils.Svg.SvgImage)(resources.GetObject("barButtonItem12.ImageOptions.SvgImage"))); + this.barButtonItem12.Name = "barButtonItem12"; + // + // barSubItem3 + // + this.barSubItem3.Caption = "批量同步"; + this.barSubItem3.Id = 15; + this.barSubItem3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barSubItem3.ImageOptions.Image"))); + this.barSubItem3.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barSubItem3.ImageOptions.LargeImage"))); + this.barSubItem3.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem13), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem14), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem15)}); + this.barSubItem3.Name = "barSubItem3"; + // + // barButtonItem13 + // + this.barButtonItem13.Caption = "最近7天"; + this.barButtonItem13.Id = 16; + this.barButtonItem13.Name = "barButtonItem13"; + this.barButtonItem13.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem13_ItemClick); + // + // barButtonItem14 + // + this.barButtonItem14.Caption = "最近30天"; + this.barButtonItem14.Id = 17; + this.barButtonItem14.Name = "barButtonItem14"; + this.barButtonItem14.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem14_ItemClick); + // + // barButtonItem15 + // + this.barButtonItem15.Caption = "最近90天"; + this.barButtonItem15.Id = 18; + this.barButtonItem15.Name = "barButtonItem15"; + this.barButtonItem15.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem15_ItemClick); + // + // barButtonItem16 + // + this.barButtonItem16.Caption = "账号异常通知开启/关闭"; + this.barButtonItem16.Id = 19; + this.barButtonItem16.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem16.ImageOptions.Image"))); + this.barButtonItem16.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem16.ImageOptions.LargeImage"))); + this.barButtonItem16.Name = "barButtonItem16"; + this.barButtonItem16.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem16_ItemClick); + // + // barButtonItem17 + // + this.barButtonItem17.Caption = "订单同步开启/关闭"; + this.barButtonItem17.Id = 20; + this.barButtonItem17.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem17.ImageOptions.Image"))); + this.barButtonItem17.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem17.ImageOptions.LargeImage"))); + this.barButtonItem17.Name = "barButtonItem17"; + this.barButtonItem17.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem17_ItemClick); + // + // barButtonItem18 + // + this.barButtonItem18.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.DropDown; + this.barButtonItem18.Id = 21; + this.barButtonItem18.Name = "barButtonItem18"; + // + // barSubItem4 + // + this.barSubItem4.Caption = "自定义同步订单(阿里妈妈)"; + this.barSubItem4.Id = 22; + this.barSubItem4.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barSubItem4.ImageOptions.Image"))); + this.barSubItem4.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barSubItem4.ImageOptions.LargeImage"))); + this.barSubItem4.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem8), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem9), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem10), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem11)}); + this.barSubItem4.Name = "barSubItem4"; + // + // barSubItem8 + // + this.barSubItem8.Caption = "最近1天"; + this.barSubItem8.Id = 29; + this.barSubItem8.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem21), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem22), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem23), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem24)}); + this.barSubItem8.Name = "barSubItem8"; + // + // barButtonItem21 + // + this.barButtonItem21.Caption = "付款订单"; + this.barButtonItem21.Id = 33; + this.barButtonItem21.Name = "barButtonItem21"; + this.barButtonItem21.Tag = "1"; + this.barButtonItem21.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem22 + // + this.barButtonItem22.Caption = "结算订单"; + this.barButtonItem22.Id = 34; + this.barButtonItem22.Name = "barButtonItem22"; + this.barButtonItem22.Tag = "1"; + this.barButtonItem22.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem23 + // + this.barButtonItem23.Caption = "失效订单"; + this.barButtonItem23.Id = 35; + this.barButtonItem23.Name = "barButtonItem23"; + this.barButtonItem23.Tag = "1"; + this.barButtonItem23.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem24 + // + this.barButtonItem24.Caption = "维权订单"; + this.barButtonItem24.Id = 36; + this.barButtonItem24.Name = "barButtonItem24"; + this.barButtonItem24.Tag = "1"; + this.barButtonItem24.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barSubItem9 + // + this.barSubItem9.Caption = "最近7天"; + this.barSubItem9.Id = 30; + this.barSubItem9.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem25), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem26), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem31), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem32)}); + this.barSubItem9.Name = "barSubItem9"; + // + // barButtonItem25 + // + this.barButtonItem25.Caption = "付款订单"; + this.barButtonItem25.Id = 37; + this.barButtonItem25.Name = "barButtonItem25"; + this.barButtonItem25.Tag = "7"; + this.barButtonItem25.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem26 + // + this.barButtonItem26.Caption = "结算订单"; + this.barButtonItem26.Id = 38; + this.barButtonItem26.Name = "barButtonItem26"; + this.barButtonItem26.Tag = "7"; + this.barButtonItem26.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem31 + // + this.barButtonItem31.Caption = "失效订单"; + this.barButtonItem31.Id = 43; + this.barButtonItem31.Name = "barButtonItem31"; + this.barButtonItem31.Tag = "7"; + this.barButtonItem31.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem32 + // + this.barButtonItem32.Caption = "维权订单"; + this.barButtonItem32.Id = 44; + this.barButtonItem32.Name = "barButtonItem32"; + this.barButtonItem32.Tag = "7"; + this.barButtonItem32.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barSubItem10 + // + this.barSubItem10.Caption = "最近30天"; + this.barSubItem10.Id = 31; + this.barSubItem10.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem27), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem28), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem33), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem34)}); + this.barSubItem10.Name = "barSubItem10"; + // + // barButtonItem27 + // + this.barButtonItem27.Caption = "付款订单"; + this.barButtonItem27.Id = 39; + this.barButtonItem27.Name = "barButtonItem27"; + this.barButtonItem27.Tag = "30"; + this.barButtonItem27.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem28 + // + this.barButtonItem28.Caption = "结算订单"; + this.barButtonItem28.Id = 40; + this.barButtonItem28.Name = "barButtonItem28"; + this.barButtonItem28.Tag = "30"; + this.barButtonItem28.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem33 + // + this.barButtonItem33.Caption = "失效订单"; + this.barButtonItem33.Id = 45; + this.barButtonItem33.Name = "barButtonItem33"; + this.barButtonItem33.Tag = "30"; + this.barButtonItem33.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem34 + // + this.barButtonItem34.Caption = "维权订单"; + this.barButtonItem34.Id = 46; + this.barButtonItem34.Name = "barButtonItem34"; + this.barButtonItem34.Tag = "30"; + this.barButtonItem34.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barSubItem11 + // + this.barSubItem11.Caption = "最近90天"; + this.barSubItem11.Id = 32; + this.barSubItem11.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem29), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem30), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem35), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem36)}); + this.barSubItem11.Name = "barSubItem11"; + // + // barButtonItem29 + // + this.barButtonItem29.Caption = "付款订单"; + this.barButtonItem29.Id = 41; + this.barButtonItem29.Name = "barButtonItem29"; + this.barButtonItem29.Tag = "90"; + this.barButtonItem29.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem30 + // + this.barButtonItem30.Caption = "结算订单"; + this.barButtonItem30.Id = 42; + this.barButtonItem30.Name = "barButtonItem30"; + this.barButtonItem30.Tag = "90"; + this.barButtonItem30.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem35 + // + this.barButtonItem35.Caption = "失效订单"; + this.barButtonItem35.Id = 47; + this.barButtonItem35.Name = "barButtonItem35"; + this.barButtonItem35.Tag = "90"; + this.barButtonItem35.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barButtonItem36 + // + this.barButtonItem36.Caption = "维权订单"; + this.barButtonItem36.Id = 48; + this.barButtonItem36.Name = "barButtonItem36"; + this.barButtonItem36.Tag = "90"; + this.barButtonItem36.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem_ItemClick); + // + // barCheckItem1 + // + this.barCheckItem1.Id = 23; + this.barCheckItem1.Name = "barCheckItem1"; + // + // barButtonItem19 + // + this.barButtonItem19.Id = 24; + this.barButtonItem19.Name = "barButtonItem19"; + // + // barSubItem5 + // + this.barSubItem5.Caption = "维权订单"; + this.barSubItem5.Id = 25; + this.barSubItem5.Name = "barSubItem5"; + // + // barSubItem6 + // + this.barSubItem6.Caption = "付款订单"; + this.barSubItem6.Id = 26; + this.barSubItem6.Name = "barSubItem6"; + // + // barButtonItem20 + // + this.barButtonItem20.Caption = "最近1天"; + this.barButtonItem20.Id = 27; + this.barButtonItem20.Name = "barButtonItem20"; + // + // barSubItem7 + // + this.barSubItem7.Caption = "最近一天"; + this.barSubItem7.Id = 28; + this.barSubItem7.Name = "barSubItem7"; + // + // barButtonItem37 + // + this.barButtonItem37.Caption = "阿里妈妈淘礼金设置"; + this.barButtonItem37.Id = 49; + this.barButtonItem37.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem37.ImageOptions.Image"))); + this.barButtonItem37.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem37.ImageOptions.LargeImage"))); + this.barButtonItem37.Name = "barButtonItem37"; + this.barButtonItem37.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem37_ItemClick); + // + // barSubItem12 + // + this.barSubItem12.Caption = "批量同步订单"; + this.barSubItem12.Id = 50; + this.barSubItem12.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barSubItem12.ImageOptions.Image"))); + this.barSubItem12.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barSubItem12.ImageOptions.LargeImage"))); + this.barSubItem12.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem38), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem39), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem40), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem41)}); + this.barSubItem12.Name = "barSubItem12"; + // + // barButtonItem38 + // + this.barButtonItem38.Caption = "最近1天"; + this.barButtonItem38.Id = 51; + this.barButtonItem38.Name = "barButtonItem38"; + this.barButtonItem38.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem38_ItemClick); + // + // barButtonItem39 + // + this.barButtonItem39.Caption = "最近7天"; + this.barButtonItem39.Id = 52; + this.barButtonItem39.Name = "barButtonItem39"; + this.barButtonItem39.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem39_ItemClick); + // + // barButtonItem40 + // + this.barButtonItem40.Caption = "最近30天"; + this.barButtonItem40.Id = 53; + this.barButtonItem40.Name = "barButtonItem40"; + this.barButtonItem40.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem40_ItemClick); + // + // barButtonItem41 + // + this.barButtonItem41.Caption = "最近90天"; + this.barButtonItem41.Id = 54; + this.barButtonItem41.Name = "barButtonItem41"; + this.barButtonItem41.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem41_ItemClick); + // + // barButtonItem45 + // + this.barButtonItem45.Caption = "复制登陆码"; + this.barButtonItem45.Id = 58; + this.barButtonItem45.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem45.ImageOptions.Image"))); + this.barButtonItem45.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem45.ImageOptions.LargeImage"))); + this.barButtonItem45.Name = "barButtonItem45"; + this.barButtonItem45.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem45_ItemClick); + // + // popupMenu1 + // + this.popupMenu1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem16), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem17), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem12), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem6), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem45), + new DevExpress.XtraBars.LinkPersistInfo(this.barSubItem4), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem37)}); + this.popupMenu1.Manager = this.barManager1; + this.popupMenu1.Name = "popupMenu1"; + this.popupMenu1.Popup += new System.EventHandler(this.popupMenu1_Popup); + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 60000; + // + // cps_manage_control + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.barDockControlLeft); + this.Controls.Add(this.barDockControlRight); + this.Controls.Add(this.barDockControlBottom); + this.Controls.Add(this.barDockControlTop); + this.Name = "cps_manage_control"; + this.Size = new System.Drawing.Size(818, 503); + this.Load += new System.EventHandler(this.cps_manage_control_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.barManager1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.popupMenu1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraBars.PopupMenu popupMenu1; + private DevExpress.XtraBars.BarButtonItem barButtonItem1; + private DevExpress.XtraBars.BarManager barManager1; + private DevExpress.XtraBars.BarDockControl barDockControlTop; + private DevExpress.XtraBars.BarDockControl barDockControlBottom; + private DevExpress.XtraBars.BarDockControl barDockControlLeft; + private DevExpress.XtraBars.BarDockControl barDockControlRight; + private System.Windows.Forms.Timer timer1; + private DevExpress.XtraBars.BarSubItem barSubItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem2; + private DevExpress.XtraBars.BarButtonItem barButtonItem3; + private DevExpress.XtraBars.BarButtonItem barButtonItem4; + private DevExpress.XtraBars.BarButtonItem barButtonItem5; + private DevExpress.XtraBars.BarButtonItem barButtonItem6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraBars.BarButtonItem barButtonItem7; + private DevExpress.XtraBars.BarSubItem barSubItem2; + private DevExpress.XtraBars.BarButtonItem barButtonItem8; + private DevExpress.XtraBars.BarButtonItem barButtonItem9; + private DevExpress.XtraBars.BarButtonItem barButtonItem10; + private DevExpress.XtraBars.BarButtonItem barButtonItem11; + private DevExpress.XtraBars.BarButtonItem barButtonItem12; + private DevExpress.XtraBars.BarSubItem barSubItem3; + private DevExpress.XtraBars.BarButtonItem barButtonItem13; + private DevExpress.XtraBars.BarButtonItem barButtonItem14; + private DevExpress.XtraBars.BarButtonItem barButtonItem15; + private DevExpress.XtraBars.BarButtonItem barButtonItem16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraBars.BarButtonItem barButtonItem17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraBars.BarButtonItem barButtonItem18; + private DevExpress.XtraBars.BarSubItem barSubItem4; + private DevExpress.XtraBars.BarSubItem barSubItem8; + private DevExpress.XtraBars.BarButtonItem barButtonItem21; + private DevExpress.XtraBars.BarButtonItem barButtonItem22; + private DevExpress.XtraBars.BarButtonItem barButtonItem23; + private DevExpress.XtraBars.BarButtonItem barButtonItem24; + private DevExpress.XtraBars.BarSubItem barSubItem9; + private DevExpress.XtraBars.BarButtonItem barButtonItem25; + private DevExpress.XtraBars.BarButtonItem barButtonItem26; + private DevExpress.XtraBars.BarButtonItem barButtonItem31; + private DevExpress.XtraBars.BarButtonItem barButtonItem32; + private DevExpress.XtraBars.BarSubItem barSubItem10; + private DevExpress.XtraBars.BarButtonItem barButtonItem27; + private DevExpress.XtraBars.BarButtonItem barButtonItem28; + private DevExpress.XtraBars.BarButtonItem barButtonItem33; + private DevExpress.XtraBars.BarButtonItem barButtonItem34; + private DevExpress.XtraBars.BarSubItem barSubItem11; + private DevExpress.XtraBars.BarButtonItem barButtonItem29; + private DevExpress.XtraBars.BarButtonItem barButtonItem30; + private DevExpress.XtraBars.BarButtonItem barButtonItem35; + private DevExpress.XtraBars.BarButtonItem barButtonItem36; + private DevExpress.XtraBars.BarCheckItem barCheckItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem19; + private DevExpress.XtraBars.BarSubItem barSubItem5; + private DevExpress.XtraBars.BarSubItem barSubItem6; + private DevExpress.XtraBars.BarButtonItem barButtonItem20; + private DevExpress.XtraBars.BarSubItem barSubItem7; + private DevExpress.XtraBars.BarButtonItem barButtonItem37; + private DevExpress.XtraBars.BarSubItem barSubItem12; + private DevExpress.XtraBars.BarButtonItem barButtonItem38; + private DevExpress.XtraBars.BarButtonItem barButtonItem39; + private DevExpress.XtraBars.BarButtonItem barButtonItem40; + private DevExpress.XtraBars.BarButtonItem barButtonItem41; + private DevExpress.XtraBars.BarButtonItem barButtonItem42; + private DevExpress.XtraBars.BarButtonItem barButtonItem43; + private DevExpress.XtraBars.BarButtonItem barButtonItem44; + private DevExpress.XtraBars.BarButtonItem barButtonItem45; + private DevExpress.XtraBars.BarButtonItem barButtonItem46; + } +} diff --git a/FLSystem/Forms/cps_manage_control.cs b/FLSystem/Forms/cps_manage_control.cs new file mode 100644 index 0000000..ab02aa8 --- /dev/null +++ b/FLSystem/Forms/cps_manage_control.cs @@ -0,0 +1,815 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using DevExpress.XtraBars; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using System.Linq; +using System.Text; +using static Api.Framework.Cps.AlimamaApi; +using FLSystem.Properties; +using Api.Framework.Tools; +using Newtonsoft.Json; + +namespace FLSystem.Forms +{ + public partial class cps_manage_control : DevExpress.XtraEditors.XtraUserControl + { + public cps_manage_control() + { + InitializeComponent(); + + var StartDy = Util.AppConfig_GetValue("StartDy"); + if (StartDy == "1") + barButtonItem43.Enabled = true; + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + var m = e.Row as Api.Framework.Model.fl_cps_member; + // m.online + if (e.Column.Caption == "图标") + { + switch (m.cpstype) + { + case CpsType.京东联盟: + e.Value = Properties.Resources.京东_20; + break; + case CpsType.多多进宝: + e.Value = Properties.Resources.拼多多_20; + break; + case CpsType.唯品联盟: + e.Value = Properties.Resources.唯品会12; + break; + case CpsType.阿里妈妈: + e.Value = Properties.Resources.淘宝_20; + break; + case CpsType.抖音联盟: + e.Value = Properties.Resources.抖音; + break; + case CpsType.苏宁易购: + e.Value = Properties.Resources.苏宁小; + break; + case CpsType.快手联盟: + e.Value = Properties.Resources.快手登录; + break; + default: + e.Value = Properties.Resources.淘宝_20; + break; + } + } + else if (e.Column.Caption == "接口类型") + e.Value = "联盟授权"; + else if (e.Column.Caption == "状态") + { + if (m.cpstype == CpsType.唯品联盟) + e.Value = m.is_valid ? "在线" : "离线"; + else + e.Value = m.online ? "在线" : "离线"; + } + } + + private void cps_manage_control_Load(object sender, EventArgs e) + { + this.gridControl1.DataSource = CpsClient.Members; + EventClient.MethodEvent += EventClient_MethodEvent; + this.Disposed += Cps_manage_control_Disposed; + } + + private void Cps_manage_control_Disposed(object sender, EventArgs e) + { + EventClient.MethodEvent -= EventClient_MethodEvent; + } + + private void EventClient_MethodEvent(object sender, MethodType e) + { + if (e == MethodType.刷新联盟) + { + this.gridControl1.DataSource = null; + CpsClient.RefreshCps(); + this.gridControl1.DataSource = CpsClient.Members; + } + } + + private void barButtonItem1_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + EventClient.OnEvent(this, MethodType.刷新联盟); + } + + private void gridControl1_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) popupMenu1.ShowPopup(Control.MousePosition); + } + + private void popupMenu1_Popup(object sender, EventArgs e) + { + barSubItem4.Enabled = false; + var r = this.gridView1.GetSelectedRows(); + this.barButtonItem17.Enabled = barButtonItem16.Enabled = this.barSubItem1.Enabled = r.Length != 0; + if (r.Length == 0) return; + var row = gridView1.GetRow(r[0]) as fl_cps_member; + if (row == null) return; + barButtonItem37.Enabled = barSubItem4.Enabled = (row.cpstype == CpsType.阿里妈妈); + + barButtonItem45.Enabled = row.cpstype == CpsType.抖音联盟; + } + + /// + /// 同步订单操作 + /// + /// 同步订单开始时间 + private void sync_order(DateTime start_time, bool is_all = false) + { + DialogResult ok = DialogResult.No; + + var r = this.gridView1.GetSelectedRows(); + var row = this.gridView1.GetRow(r[0]) as fl_cps_member; + if (row == null) return; + + if (is_all) + { + ok = XtraMessageBox.Show($"您确定要刷新所有【{row.cpstype}】联盟订单吗?", "请选择", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + } + else + { + if (row.is_download == SwitchType.关闭) + { + BaseForm.ShowError($@"联盟:{row.username}({row.usernick}) +同步状态:禁止 +注:联盟列表选中账号右击开启,即可同步"); + return; + } + ok = XtraMessageBox.Show($"您确定要启动线程同步【{row.username}({row.usernick})】的订单吗?", "请选择", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + } + + if (ok == DialogResult.Yes) + { + Task.Factory.StartNew(delegate + { + string cpsStr = $"【{row.cpstype.ToString()}】账号:{row.username}({row.usernick})"; + if (!is_all) + { + try + { + if (row.cpstype == CpsType.阿里妈妈) + { + var timer = TimerTask.GetTimer() as DownAlimamaTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + row.is_valid = true; + timer.UpdateOrder(new List() { row }, start_time, DateTime.Now); + } + else if (row.cpstype == CpsType.多多进宝) + { + var timer = TimerTask.GetTimer() as DownPinduoduoTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(new List() { row }, start_time, DateTime.Now); + } + else if (row.cpstype == CpsType.京东联盟) + { + var timer = TimerTask.GetTimer() as DownJingdongTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(new List() { row }, start_time); + } + else if (row.cpstype == CpsType.唯品联盟) + { + var timer = TimerTask.GetTimer() as DownWeipinhuiTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(new List() { row }, start_time, DateTime.Now); + } + else if (row.cpstype == CpsType.抖音联盟) + { + var timer = TimerTask.GetTimer() as DownDouyinTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(new List() { row }, start_time, DateTime.Now); + } + else if (row.cpstype == CpsType.苏宁易购) + { + var timer = TimerTask.GetTimer() as DownSuningTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(new List() { row }, start_time, DateTime.Now); + } + else if (row.cpstype == CpsType.快手联盟) + { + var timer = TimerTask.GetTimer() as DownKuaiShouTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(new List() { row }, start_time, DateTime.Now); + } + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowSuccessAutoClose($"{cpsStr},同步完成!", 20000); + })); + EventClient.OnEvent(null, $"{cpsStr},手动同步完成!"); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowError(ex); + })); + } + } + } + else + { + try + { + #region 不下载通知 + var cpss_down = CpsClient.Members.Where(f => f.cpstype == row.cpstype && f.is_download == SwitchType.开启).ToList(); + var cpss_undown = CpsClient.Members.Where(f => f.cpstype == row.cpstype && f.is_download == SwitchType.关闭).ToList(); + if (cpss_undown != null && cpss_undown.Count != 0) + { + StringBuilder strb = new StringBuilder($@"{row.cpstype}联盟: +"); + foreach (var cps in cpss_undown) + { + strb.AppendLine($"{cps.username} ({cps.usernick})"); + } + strb.AppendLine(@" +同步状态:禁止 +注:联盟列表选中账号右击开启, 即可同步"); + EventClient.OnEvent(this, strb.ToString()); + } + #endregion + + if (row.cpstype == CpsType.阿里妈妈) + { + if (cpss_down != null && cpss_down.Count != 0) + { + var timer = TimerTask.GetTimer() as DownAlimamaTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(cpss_down, start_time, DateTime.Now); + } + } + else if (row.cpstype == CpsType.多多进宝) + { + if (cpss_down != null && cpss_down.Count != 0) + { + var timer = TimerTask.GetTimer() as DownPinduoduoTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(cpss_down, start_time, DateTime.Now); + } + } + else if (row.cpstype == CpsType.京东联盟) + { + if (cpss_down != null && cpss_down.Count != 0) + { + var timer = TimerTask.GetTimer() as DownJingdongTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(cpss_down, start_time); + } + } + else if (row.cpstype == CpsType.唯品联盟) + { + if (cpss_down != null && cpss_down.Count != 0) + { + var timer = TimerTask.GetTimer() as DownWeipinhuiTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(cpss_down, start_time, DateTime.Now); + } + } + else if (row.cpstype == CpsType.抖音联盟) + { + if (cpss_down != null && cpss_down.Count != 0) + { + var timer = TimerTask.GetTimer() as DownDouyinTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(cpss_down, start_time, DateTime.Now); + } + } + else if (row.cpstype == CpsType.苏宁易购) + { + if (cpss_down != null && cpss_down.Count != 0) + { + var timer = TimerTask.GetTimer() as DownSuningTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(cpss_down, start_time, DateTime.Now); + } + } + else if (row.cpstype == CpsType.快手联盟) + { + if (cpss_down != null && cpss_down.Count != 0) + { + var timer = TimerTask.GetTimer() as DownKuaiShouTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + timer.UpdateOrder(cpss_down, start_time, DateTime.Now); + } + } + + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowSuccessAutoClose($"{cpsStr},同步完成!", 20000); + })); + EventClient.OnEvent(null, $"{cpsStr},手动同步完成!"); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowError(ex); + })); + } + } + } + }); + } + } + + private void barButtonItem2_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddDays(-1)); + } + + private void barButtonItem3_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddDays(-7)); + } + + private void barButtonItem4_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddMonths(-1)); + } + + private void barButtonItem5_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddDays(-90)); + } + + private void barButtonItem6_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_cps_member; + var result = XtraMessageBox.Show($"您确定要删除【{row.username}({row.usernick})】账号吗?", "请选择", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result == DialogResult.Yes) + { + this.gridView1.DeleteRow(r[0]); + CpsClient.Members.Remove(row); + var session = ApiClient.GetSession(); + session.Delete(row); + EventClient.OnEvent(this, MethodType.刷新联盟); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void barButtonItem8_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + LoginCps(CpsType.阿里妈妈); + } + + private void barButtonItem9_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + LoginCps(CpsType.多多进宝); + } + + private void barButtonItem10_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + LoginCps(CpsType.京东联盟); + } + + private void barButtonItem42_ItemClick(object sender, ItemClickEventArgs e) + { + LoginCps(CpsType.唯品联盟); + } + + private void barButtonItem43_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + LoginCps(CpsType.抖音联盟); + } + catch (Exception ex) + { + BaseForm.ShowError(ex.Message, "抖音异常"); + } + } + + private void barButtonItem44_ItemClick(object sender, ItemClickEventArgs e) + { + LoginCps(CpsType.苏宁易购); + } + + private void barButtonItem46_ItemClick(object sender, ItemClickEventArgs e) + { + //TODO 快手 + return; + LoginCps(CpsType.快手联盟); + } + + private fl_cps_member LoginCps(CpsType type) + { + try + { + var member = CpsClient.Login(type); + if (member != null) + { + CpsClient.RefreshCps(); + EventClient.OnEvent(null, MethodType.刷新联盟); + } + return member; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + } + + private void barButtonItem13_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddDays(-7), true); + } + + private void barButtonItem14_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddMonths(-1), true); + } + + private void barButtonItem15_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddDays(-90), true); + } + + private void barButtonItem16_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + var row = this.gridView1.GetRow(r[0]) as fl_cps_member; + if (row != null) + { + row.abnormal_tip = (row.abnormal_tip == SwitchType.开启) ? SwitchType.关闭 : SwitchType.开启; + var session = ApiClient.GetSession(); + session.SaveOrUpdate(row); + EventClient.OnEvent(this, MethodType.刷新联盟); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void barButtonItem17_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + var row = this.gridView1.GetRow(r[0]) as fl_cps_member; + if (row != null) + { + row.is_download = (row.is_download == SwitchType.开启) ? SwitchType.关闭 : SwitchType.开启; + var session = ApiClient.GetSession(); + session.SaveOrUpdate(row); + EventClient.OnEvent(this, MethodType.刷新联盟); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void barButtonItem_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + try + { + if (sender is BarManager) + { + var tag = e.Item.Tag.ToString(); + //var button = sender as BarManager; + //var tag = button.Tag; + AlimamaOrderStatus status = AlimamaOrderStatus.全部订单; + + if (e.Item.Caption == "付款订单") + status = AlimamaOrderStatus.订单付款; + else if (e.Item.Caption == "结算订单") + status = AlimamaOrderStatus.订单结算; + else if (e.Item.Caption == "失效订单") + status = AlimamaOrderStatus.订单失效; + if (status != AlimamaOrderStatus.全部订单) + { + sync_appoint_alimama_order(status, DateTime.Now.AddDays(-int.Parse(tag))); + } + else if (e.Item.Caption == "维权订单") + { + sync_appoint_alimama_refund_order(DateTime.Now.AddDays(-int.Parse(tag))); + //XtraMessageBox.Show("开发中!", "温馨提示", MessageBoxButtons.OK); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// + /// 同步指定类型阿里妈妈订单 + /// + /// + /// + private void sync_appoint_alimama_order(AlimamaOrderStatus status, DateTime start_time, bool is_all = false) + { + DialogResult ok = DialogResult.No; + + fl_cps_member row = null; + if (is_all) ok = XtraMessageBox.Show($"您确定要刷新所有联盟订单吗?", "请选择", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + else + { + var r = this.gridView1.GetSelectedRows(); + row = this.gridView1.GetRow(r[0]) as fl_cps_member; + + if (row != null && row.is_download == SwitchType.关闭) + { + BaseForm.ShowError($@"联盟:{row.username}({row.usernick}) +同步状态:禁止 +注:联盟列表选中账号右击开启,即可同步"); + return; + } + ok = XtraMessageBox.Show($"您确定要启动线程同步【{row.username}({row.usernick})】的{status.ToString().Replace("订单", "")}订单吗?", "请选择", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + } + + if (ok == DialogResult.Yes) + { + Task.Factory.StartNew(delegate + { + if (!is_all) + { + string cpsStr = $"【{row.cpstype.ToString()}】账号:{row.username}({row.usernick})"; + try + { + if (row.cpstype == CpsType.阿里妈妈) + { + var timer = TimerTask.GetTimer() as DownAlimamaTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + row.is_valid = true; + timer.UpdateOrder(new fl_cps_member[] { row }, start_time, DateTime.Now, status); + } + //else if (row.cpstype == CpsType.多多进宝) + //{ + // var timer = TimerTask.GetTimer() as DownPinduoduoTimer; + // if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + // timer.UpdateOrder(row, start_time, DateTime.Now); + //} + //else if (row.cpstype == CpsType.京东联盟) + //{ + // var timer = TimerTask.GetTimer() as DownJingdongTimer; + // if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + // timer.UpdateOrder(row, start_time); + //} + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowSuccessAutoClose($"{cpsStr},同步完成!", 20000); + })); + EventClient.OnEvent(null, $"{cpsStr},手动同步完成!"); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowError(ex); + })); + } + } + } + //else + //{ + // try + // { + // if (row.cpstype == CpsType.阿里妈妈) + // { + // var timer = TimerTask.GetTimer() as DownAlimamaTimer; + // if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + // timer.UpdateOrder(row, start_time, DateTime.Now); + + // } + // else if (row.cpstype == CpsType.多多进宝) + // { + // var timer = TimerTask.GetTimer() as DownPinduoduoTimer; + // if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + // timer.UpdateOrder(row, start_time, DateTime.Now); + // } + // else if (row.cpstype == CpsType.京东联盟) + // { + // var timer = TimerTask.GetTimer() as DownJingdongTimer; + // if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + // timer.UpdateOrder(row, start_time); + // } + // if (!this.IsDisposed) + // { + // this.Invoke(new Action(delegate + // { + // BaseForm.ShowSuccess("同步完成!"); + // })); + // } + // } + // catch (Exception ex) + // { + // if (!this.IsDisposed) + // { + // this.Invoke(new Action(delegate + // { + // BaseForm.ShowError(ex); + // })); + // } + // } + //} + }); + } + } + + /// + /// 在同步的维权阿里妈妈名称 + /// + private List syncAlimamaRefundNames = new List(); + + /// + /// 手动同步维权订单 + /// + /// + /// + /// + private void sync_appoint_alimama_refund_order(DateTime start_time, bool is_all = false) + { + fl_cps_member row = null; + var r = this.gridView1.GetSelectedRows(); + row = this.gridView1.GetRow(r[0]) as fl_cps_member; + + if (row != null && row.is_download == SwitchType.关闭) + { + BaseForm.ShowErrorAutoClose($@"联盟:{row.username}({row.usernick}) +同步状态:禁止 +注:联盟列表选中账号右击开启,即可同步"); + return; + } + else if (row != null && row.online == false) + { + BaseForm.ShowErrorAutoClose($@"联盟:{row.username}({row.usernick}) +阿里妈妈状态:离线 +注:重新扫码登录阿里妈妈账号即可"); + return; + } + else if (syncAlimamaRefundNames.Contains(row.username)) + { + BaseForm.ShowErrorAutoClose($@"联盟:{row.username}({row.usernick}) +正在同步维权订单~请耐心等待"); + return; + } + + Task.Factory.StartNew(delegate + { + if (!is_all) + { + syncAlimamaRefundNames.Add(row.username); + string cpsStr = $"【{row.cpstype.ToString()}】账号:{row.username}({row.usernick})"; + try + { + if (row.cpstype == CpsType.阿里妈妈) + { + var timer = TimerTask.GetTimer() as DownAlimamaTimer; + if (timer.IsRunning) throw new Exception("系统繁忙,请稍后再同步!"); + var api = timer.GetAlimamaApi(row); + if (api != null) + timer.UpdateOrder(api, start_time); + } + + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowSuccessAutoClose($"{cpsStr},同步完成!", 20000); + })); + EventClient.OnEvent(null, $"{cpsStr},手动同步完成!"); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowError(ex); + })); + } + } + finally + { + if (syncAlimamaRefundNames.Contains(row.username)) + syncAlimamaRefundNames.Remove(row.username); + } + } + }); + } + + private void barButtonItem37_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + var row = this.gridView1.GetRow(r[0]) as fl_cps_member; + if (row.cpstype == CpsType.阿里妈妈) + { + var tljform = new tlj_form(row.usernick, row.username); + tljform.ShowDialog(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowError(ex); + })); + } + } + } + + private void barButtonItem38_ItemClick(object sender, ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddDays(-1), true); + } + + private void barButtonItem39_ItemClick(object sender, ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddDays(-7), true); + } + + private void barButtonItem40_ItemClick(object sender, ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddMonths(-1), true); + } + + private void barButtonItem41_ItemClick(object sender, ItemClickEventArgs e) + { + sync_order(DateTime.Now.AddDays(-90), true); + } + + private void barButtonItem45_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_cps_member; + + var json = JsonConvert.SerializeObject(row); + if (!string.IsNullOrWhiteSpace(json)) + { + var date = Util.EncryptDES(json); + try + { + Clipboard.SetDataObject(date); + } + catch (Exception) + { + throw new Exception("登录码复制失败,请稍后再试"); + } + + BaseForm.ShowSuccessAutoClose("相同登陆码复制成功"); + } + else + throw new Exception("复制登录码异常"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + } +} diff --git a/FLSystem/Forms/cps_manage_control.resx b/FLSystem/Forms/cps_manage_control.resx new file mode 100644 index 0000000..28c3696 --- /dev/null +++ b/FLSystem/Forms/cps_manage_control.resx @@ -0,0 +1,762 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 149, 17 + + + 57 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUAUmVmcmVzaDtSZXBlYXQ7QmFycztSaWJib247UmVsb2FkzU326QAAA4pJREFUOE9tkw1Mk1cUhi9M + UBOlLtsczBaEIquirGiV0iIFKTBLTRapdIV2oo4pbrWyWTeDDRah/FR0EOgqP4vOqfzogkwFOxyORHE/ + oWZAyphM3da4oIzB1FjK9u7exmXJ4kme79zc877nu989+chTwo/i/z/Y3tOj4bKSksGWfoW2BI6tc73Z + 1qW4bncoZj66pJip61x/vbrj1eLdFXELmMZ6JoVUtK4jZS3JxHJaRshRh4KZ/ava5PJPruh+6XVVYnSs + A5Oefh83x86hZ7AMTV9oft1nl8iZ9vHfLjI100f2N0qYl/gfakvNar2Wjx/utuLPv77FhPcr3Pc4cM/T + hd+9X4KKMeQ+BVu7FoYqkZp5JrxXSEGNiBB96erghkuvPxxyn8T4dDduuGthOZEFTeEKH5YTKlweLMXY + 4wv4eqQe++vlD5Vv8kNoE7/tZTGElHyaVOlwmjHmOY/ugWLkV0i9qTu4B6XqYH6CJoSveCfMWFCd6Om7 + VQL3o1Yc6zIgZ5/gEG3wjNYkIOTAcdmA844dPz2oh7VFDaUh3EyLgewNTwjI2hu1t6ZdA9ekFR39u7Bp + T+Qg06j28Am9iITp4XE7hieroD8cj0QVdzEz/uG9SpNvhLOXxD4bYrTJ8PnPKTg3sgEb9GFTdJ/DauS9 + WvHUxVuvofe3LTDWypCu4Ycy4z1PN5GrIzgFR8QPdh+JQ2F9MppvCnHaJcbblauxs1yEHRbRBNlZsWqw + oU+MllEhjl7UIs+8kn3CbAo7fuAWk7CksSsXzvsHcXIkGs0/inBjvBxFTelYmx38PtF+sPzD8jMJtLgC + nznfQFFjuifHuNwoyeAtFiYGv7AoMmjhtuLYO/bvluH48FIccy1DzdUoJOW+eHv+cwEcIlEuinirdOUj + qyMaZ0fX4Wx/Hg63ZWKXVYKtRcJpWWbYmoxtUboC2yv4eEjgI/sAD7EZHC09YQCFBKbpwvO2l8fAckGA + 5hEpOm9r0Os24NS1zVAZlvZQzcKNekGPpfNlmNpDsSZzAdubR/H9I+wxR7qRq1a9u+Su3saH+TwfNd9E + oskZTy8rDinZ4TpR2kvxOlO0NzX/eS9fPDeOemaJNgURkrY1/N8mATxBEFeaya2WaXgDydpQJOWEYm0W + 7/vUXL6J1oPSNkfUxSjn1dH1XOZZpZpP03/BmrC5z6Gw47E5M5iKTWXWk8xgOhqE/AMGBJrrDx94VwAA + AABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUAUmVmcmVzaDtSZXBlYXQ7QmFycztSaWJib247UmVsb2FkzU326QAACkhJREFUWEfFlglMVWcWxy+V + sSqIClRRRMW22iI7PPYnu6BQqaVuFKqAFWgRXJC6IKjsyA6iWEMLBWRxAwFZFUSxWsBKxSIiUNEKKqBO + Jk7U5D/nXMAxk06TzmQyJ/nlLu/7zvadc+4TAPxf+bMi8wf8z2TMwFvEOEL2d+D3/Pt/5kxG5VIh4+xS + 4eAYFcv49ZhR2cgc6/eTTjuEpJY5nk8rd2xNr1j6Kr3c8VVqmUNrSqljfcJJ+z17MqULae1fCHZGdCSt + zFGgPULqGYc3rsSZf74XJb18qTD0vEYY/nstP742HJ1vY51c6nDhWKMXzt8Iw42+TPQNH8fg8yqRu0PF + aLt7GHU/hyG/YT2STi1pCs+2WkJ7xxOiI/1/LRPuPysV7j0tEfqenBJ+HT4u9A4VC8mnHYSkklEHUsij + wefVfCsad/FcKJdwwv7QsQveuNqVgAd/PYn+vxWj71k2eoYPo3MwBbceJ+L2YCq6h8mppzm4++QYmjrj + kNfgiZgC20ypk5oC6eLjkbn/bNT4k5NCLznQPVgkJJxcIsSfsGebgpB0mp0WjY/bGGYwM/64XWNFSzDu + PMoWlXc+TiODybj1KAkdjxLxy6N4tD+Mw42BaLQ9iMBPv+0X6Xx8EDcfZKL0x22IKbS76LFNW5V0ik7c + HT4hGu8ZKhS6BguEuCI7kTERjVPkU2OL7JqrfwqhiHLJYCraB+JxUyQBNx+S4YEDZDgWbf3RuP4gEtfI + cMv9UFzt240fft2B5nth+GXgEMpbvkZkvk2L1HmOMukWnegZKhDuDB4Tbj/KE6ILbIToY7ZsWxQ+8/FR + eTZZpVe2oXswiyIiA0TbgxiRdnKAM9E1eBjdQ9/gzlAmOuj5BjnUcm8fGd+JSz1BaOjegvquzWj7LQnH + LwUgNGtxNumeSIzrGswXbj/OFW49zBEic62FCIKFo5fdlmhqkVXlgbZ7aaQwAs19FNm9cLQS7QOJqL4W + ggP5q+C13xD2fqqw/1IVXuH6iM1zpWiD8GNfGC7c2YLztzeh9taXqOv0x+U7UcgsXwuffQZWZIMLU6aT + jHcMZAn7sq0IS7YvRj9hb7ZVQ+31MFy7H4PLvZzOPbh6N4wyEYsjZZ5YvWvRSxN3paP6n0xzUpwzXpmh + e2czD+Wja3ZrvMwocaMM7EANGa/s8EH5TW9yZivKmoMRckTaSDbkiXEdD7OE9v5vBMqMCIusb7ihecaZ + 1RR9MkXxNRq7d+Biz0609EXgcNk6OPrP6ddbPo1XTyI4krEB9DYhp79c0dIpcG5/eslqMroF5e3eKGlb + h9NtHmjs2oOUE674PFibwxWzcP23g8LuI1LCgh5JSXCaWULxhU243BOKulucxm3kxE6UNm+FR5jOSwMX + JV4pniPBRzaGOC+ISYbLlRev26fzsqhpA8pubMCpn9xRfG0N3W9ETt0GBMQZp/A63tPSlyLsOGQuwjIx + KM208dQVf0pfIKp/2YSajgBc7N6F+MKVsP1iVhat4fSJldz3tJh6uki4+6SQ+rqQ97MjPAEVlvipfRtb + 4IKz7T4oal2NgpaVKG5dixOXv8LmJJNLvIYQ9WxPNxWCCBb5rSnGD47/+AUyG21x+vo6VLT74VJ3CAIS + LSBdq+JMayYQb/UOF1AvM8eEnuF83svGOSucWnmLVTNXBCaZo+KmL/KbXZF79WPkXlmBU80+2Jxs0k9r + uCVZFzssOkIICgHxkhfFrR5IqDVAUp0E3112RkPX13ALWQSl2RNm0hrx7LqHcoXuoe+FOwQ/E6xIjphG + zJisOH7h52GaVAM+yPnBBd82OeFggyW+v/IpAhOMX9AadV5HKBGcDdYrTPGL1n+Re8UVB2r0caBaH/F0 + zb36CT4P04Ly7ImzRhfK3H78ndD5+FsREo58UkC80atNCUagKzYRQalSKj5PpNdLR/Xp4ejFpfCPMyIk + +Irwj6VrrOSVkb2qCiua4rlPu/9IvTMSqiWIrdJFHPHNJQcEpVnBxk3tIzZEvHWj/5BwcyBTaB84zPu4 + AOVWbluYk13jS0MrleZGIpp6o3D0kiPp0UNMpS6hI+pq6g6numL242DpZ3DyU8+l/ZwFQcFtp0ZTYqkD + EmtNEE0bmLTzUsQXrcAngQs4XE4xp1vmh19jhMu90bxPnB8fmigt9AjVfJpRb0+ZM0AcZTCuigYUU6lH + unRFfVFntQkdJFSZ49Pt7z1T11FYRPu5swS5FYHvp4ZmWyO5zmx0oTalzgBZ9asRkGD+0maVOn+22Ft2 + gg2PtSA/T1niNS90a4YEqectybDBa2Iq9Qk90qc7YrzGFH7J2lTYM/fSvrGghAkWrrPtfGMNkVRjIRqP + rNASyWiwRcYZGqURkoeWK+byx5uLh1uSK5mHEEcweYK8rNrHge92xJ2xIiMmZNxwhEpDcsCAMsDZMERU + iRnsfdR635YbN2d0r9gF7IWis//8q7tzjCmFEkSUa45QoYmspo9onrtjc4L05cpAjRw7t/lraP1sYpaD + +7suRg6qOnQ/XeI0Y836cC2k1duSDqMRqiQiMeRMcp0UHvs/gL6Tsg+tn0q8bkOxmAydZyzzDNdGxGkJ + IikL4eWLXpNFbZl30RtJxauxPdUW3nsNCQNsjpdizVbNFtqvxth5qVWE5JqRMUuqBzM6RhNyxJiyYo5d + eRJIPWY00jpua3GuWH/BtyNecBaUbDxVC32TtBFz1gD7yxaJsAMR5VpIofPNa+bRGkCjeo9IVUcwQo84 + w+6z+dtpv9o8XQWLFUELnqfU2dNMkYqG44mUOht8tGXeK3XDyfwPhGtJHOmW3jwSRoSzMFFJbYK6jbfq + z77JGlQLenQEWuSAFl2pLqiQ+Cxj6Cxjq4wpOlMyYo7CK75wC9Z5NGOOnDbpmGu2SiU1IM2QusiOumox + Us5Zwz9dFxJXJe6m6QTXjsxir+mClBDFbiP/cxK9kp/1wSStxetVmj1jFyD0+IjRyAqqYrGl2LiRmFqO + jqPMuLAMiUVr4bDuXTYwb6KCrIbdRrVHiZX2SD1ni/gKW1htUHk8VXW8JusnxC6y8HxHYESx3iCeBR8F + F4a8vKKsuuna6Sddd87HpkOLEFU2EjHDZ8tpTSTjyeeskHbOHoU069136b94X1+RP29qek7KO72idaiL + lsEjQgOajlN20Hv+DvBRy5zrChPM1yuLiGLprSJU39rCt2NO8HyfoWEzxcPU/Z02l+1zsSH+QwR/R9ko + sUByrS1Sa+0RU2qDXd+bwidJB8u3vgfJSsVk2sdhzZW6q1yPOmkLIzfF6/TMbSdOU0LmfNdewWy9kogo + Uk86j1FI2Ak+Dj6rKYSqukTeQf/jaekmbsqtJp8p3SbPwfC98Vqla7ou0w6qG8vxsGKN7PzUDxZPdXb2 + W/DiPQs5/pqyHrHtTNcpCm/y74SdGMsGOzKZYOV8Vtxy80bhyPhjxbnkNfzRGvs8c7WPffXE1BN/WsYc + 4dSxM6yYe/hN2EE2ILbWG/Dzm+//a3lT+e/xr/JHv42KIPwDHxb20BRI/sQAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABt0RVh0VGl0 + bGUAU29ydDtTb3J0QnlPcmRlckRhdGU77hkpEAAAAIxJREFUOE+1ktENgCAMRLsTc7iUYSiHYAP//XcC + bJseCdgGP/CSF89Kz0KgnHP9gmjbD0D8qqwJgEop5nw/DZgpDHD+8GL47k+AhSLPW7OwOOD3LUAIYC0O + iLaA2nndzVud+JnEdxN4QpOEwDPaLHQB3u0bGkeSBkRAQYhMQe0wImSR0cY2r3W36TuVHrv+/NNOlabd + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABt0RVh0VGl0 + bGUAU29ydDtTb3J0QnlPcmRlckRhdGU77hkpEAAAANxJREFUWEftk1EOwiAQRHunnsNLGQ7lIXoD//33 + BMgQFinZNQju1jRM8kyZ2O5rSxfv/aGwpSVsaQlbWhJ/nHNeC+RyvZVMAV6gzrZt6eid3m4KdAn8Mk0C + sCaQ6qSvQYRr8QJ16CJlejusC6bAnwqcahPWSYMJfQF098czrfYCIXFmOF6xVhMAJEHr9N88HKgKAEiU + 60AeDrLAyCZEes8Vn8BImLuWWEUBupsyrR3SIIFXIX8FIwLUfZCIw4GqACJswjgcZAEtKondcBAFjoQt + LWFLS9jSEra0wy8vQf2Q2qu4qKQAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAidEVYdFRpdGxlAERlbGV0ZURhdGFTb3VyY2U7RGF0 + YVNvdXJjZTsGX+lAAAAC40lEQVQ4T43TfSzUcRwHcI9HtjzuWB63RP2nWxm2PM1KTBPRkybdP6jFZqqF + pLtDi3nmNBZ3SYo1HNnxY+chxB+eLyxxdEfE3SF5vHe/n6k/8Eef7f3Pd9/36/vdb7+v2t5odOQGB3Tm + Bmd15QYLOnOuDHdmB6E9M2C4Nf1yXcvzS1lNyb4B5D5NMuoA1P5mt9ydd5UYF7Ag6+FjUVyNFUkjVPJu + LI9XYr43HxKChQF+OJpYPm3U/v2AZlduELA5B2xIgd+TUK2OQrXcB9VSJ3YWmrE9J8CWtBKNSd5UQ2s/ + oNWREYAt8kRs/thDJkhEjG1FL1bHKrHYlYlF0UM0xHtRDe39gHZbmj825oXYUgyRwAI2ZWVQjkRhlriJ + wTQv9HHcIau6jrpHHlSDdgAQpfj9F1AT43ooQCPYFw8BorHU9wJSIg/Twhwo+kpRH+9HNXTJaOxFnYwa + TZh44QDwa7oI8rF3aA+/gVpnJ0gE2eivygbH0sbl7YmTU7zjdoVuR/UpTE3nY5zXQUBaBVH4NYwXF2Nl + TAxhYCCaE6Mh8PaVK0cGIObmo8jatowCdAUP3A8AKzPvUeXsCHlDBdYJEhzqAXGHidWBLqw38bFUX46X + VrYzu0BNzLlDb/ClOg2lri5Y5KVirZaL9f5WrNUU4OerZHAZp+URBibOFEArj3Sq/5TPxKSoGEtfyRNm + eFCOJmBhhIeWZ1Go8/GCspSNZR4HihIWas57quLoFkyyq0MB1JfULQhxuF0SxvjAD2MMljEZm59fp4JI + j9t54+6xM8fLwOzTUEjjQyCjwmWj+IyjItLIbPcG1FAI9VAo8QgZPTJG6aY2U5KCZMgSQvDtvj8qzjqo + Ju764XtsMCZSYpFCt5r690PsDzk0Nt2yXOTvCTHTG4X2pxT3DM0iuHb2yuFbniB8XPDE2Lzi0DIVcjSs + tWj6iSYWfI6J5VSYgakbuaYXqk93TzK2kDw2Mi87pqVt+AeBGmwR1DWrcgAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAidEVYdFRpdGxlAERlbGV0ZURhdGFTb3VyY2U7RGF0 + YVNvdXJjZTsGX+lAAAAIK0lEQVRYR62XCVRU5xmGzSIqmLTBtepJGwIomkRiq9IoiIAoEIJQQhWRRcCl + QlFbt5iwKFGjICIoCGGTIAgGBGQpKi64IA5DYAZQIlTAgQEHkXFgBGbmzf+NDEU6SaEn3znvuffc/5/v + fe73b3fGjCBeG6F+NgD8rNSFKuHrTG8M05vDNLSN+quFUWes0tBQmgZ6LdEs+3a91Q9JbkFVye6p/GSP + 8qpkNy7vjLuQd8YNVUyVia7CigQXLjfehcuJdU67G71mf0nE51bbHD/WYjmGwihDnbFKqngt96iDNjM8 + XpPq/bTx8tdo4ybiWV02egTXmYrR++QW5F0cyDtvo7elEM8fpuF5XTJEnHAIrgXhwfe+4MSsfXor0ik8 + atvyySwnQShDnbFKFET6RnXKhjJRTRb6JQ1Q9DVDIX0IuYQH+fNyyJ/dgqzzBuSiS5C350EuvABZayZk + ggz0Pz6L/qZk9D9KwIu6KLQUf4E7EY73WM6xA7nVGqtEQZ3evB3+FzBnKPqFUHTzmbjMvAyKrjsMoATy + p1ch77gE2ZMCyNpyIGshgHT0N6egvzGJAXyL/obT6K8/hcsHrCizBpOyCuqMVaIggLE3w+zRL66DQi5h + eg70MZAXrAoMRi6+BxkDkXUUsyoUQt6WC5myCkzKKpxTgvTVx6Pr7n4UBVpS5vFMIwbQuBFih2fccDa+ + xZD1CiAnABLd9zAQKRuannooJLVsODjo+Xc2pA3n0VMXh27+CXRd24WWJBs0nf0chf4WowKgThrXjtgO + AFxG34vH6OtrRx8bjl5JJaRtSRDX/R3CguVoSl6I+2FzwQ14D7zQeXicaYeOoo0QZblCkLhKCVDwhRll + njCQW62xShTUaVzxIZtfDeDinuWjB7gcbPWrAeTsNBk9QL6/5e3W4kBImwr/b4CmOEtUHTPDeb8ld1hO + zYHcao1VoqBO4//lb4nHRQGozwnCo+vxEHBz0P7gCp42FEDEC0Fn9dZBgJoQA5TufhecA/rgRxqDF26B + 0n1/xFVfXXAPmyLT7xPKrNoV1RqrREEAE/L3maOrKga9bTfxTFCuBPixMBIV8T64d8IOV3YaIM9zOrJd + puCC82TkuU1FgfcM3PI3BC/CCo/OrIUwwxmC791xfutiyjyRSQnwv0IJkLfHdMgcELAhELEhYMPQXYsX + ovOQPAqA6IYTWi9YoSHeGPxQQ9yPWYLWfBd0FPtBlO05OAfSNy9SB0DLnfRfQZ00c3cuG/Uk5IfNR0dZ + CMQ16RBXpqDzbgweZ21GmvefCOCtgdxkSi+pOj3p/hUQeqCZvcN4dABBemjM3wtRRRIqdv0NVVs3oikz + FB0V3yFr5yoCeJtJeWynLzczKVu/XphnvqLAd47Bb9gzFZgylBVI9/lz6WhWQX26D5qLj4Oz3QtPChPQ + W10AzrZNeHD2G5TEH2hgOX/LNP6MsYnprU0ePdKqXAizY5C7ctUNz/f1qG0Qgm60zvsajXgVVB81QEPu + ftz2cUNbTiz6yrLQezkZfbw8lG71ws2wAKrA1FOLjSxKvN17eitzILkQhZ6iBDSnncC5JSY5rH3wtCSA + iRlbFo14FWSxVcBP8UeRnS2eX0tBT24supmBJDsaL7jZuLnZA6cWGn153dO1R1qeha6zx/As8TA6Ew6j + /btQpBotFTJPOi0HAd5K27RwxKugPs4YgqshqE0LxkX71ei8cBric+HoSglhZqGQ3D6Ha9u3KCSl6ehM + PIiO6ECIogPQEhGIxEVLu/bO0F/KPGl+KAHo5u2zngtGNQkrjxqxOXCUfQkdQaaNNdqTvsHTuGB0nA5E + R8x+SIri8STqK7Qf3422sN1oPLgDCQs/6dr1Oz1j5qf6VvhPBVLcDUe9DKujTfGkIg73s9i4rrBEc9ge + CA75QnhkO1qZWr72RZO/Nx7u8UL8AiOx3zQdU+ZFx/TgBKRQLsP4dR/erYjfBEnDxREDVIXMQ3PeBrRX + pqIsdC+uONujKWgj6jZ+hjpvWzxgqvdbg/xPVyoOzvlwB/OhpUmTjzwHg0g0nD6ePuuU45y4pHUfiQuD + 16M8/Sh+LElFKz8LAg4rL3/IKgiZi5JdOuCwg6fhajRKo4OQ91cHCBOC8WCjLe5vsMZ9D2vUur9UU+g/ + kWG1UrpHZ7YN86JT8pUK0A0REZnWB9O1pgZZ6jget9U9FmmnnxO1Wp9HirWf3R3roI8Yez1E2+l2J7gv + qb1y0l+Qsd2zLsfhM1lb0iHUetmi1nUVatysULfFEdUuVqh2XoEa15VoDNmJVAtz6e7f61kzH7UQJHpI + IDROdJzSdko7F20c7zBpD2gS05R/vDfbPtPWRtoaux817jbgO1uCv24leJ4OSF5spKjxWQveWnZEO5mx + qwUagnyQvMxEumOWDkGMY3r9lWORhQqEKkIiIOV2Okw0iyeenGvY2hj5FWrdrMFbY85kgSr31Tg5d77Y + Z/K7fpEfLBDzNzuhytEMlfYm4LFrzS4vHP6DQSv7/cvvhWEA6kIFNVQENsF/+vt519c7sLf/FDwnc1S6 + 2iLSYL7YQ3umBWt/x1175orIeYZi3gYH/OBgykAscMnGAl9O08ln7a8CjFQDQRBjDcZrTQqcoXflkr0V + yl1XI8LgI7Gn9kxz1kYfI1RiLYKJZBXhuNihwHIZAmboXtUdpzmVtb3cCdWZ/JKGBA2Rht44zSnsjdID + p+s2ek2aZcae0ZvRMFE7XTUJitr3TdPJ0NGYMI09ezn+FOpMfknDgpLQpCVT1VsPnd10JQia1NROGvzH + NGbMmDE/AdatRGZw6SGOAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUAUmVmcmVzaDtSZXBlYXQ7QmFycztSaWJib247UmVsb2FkzU326QAAAwFJREFUOE+lk3sslWEcxx/k + uOcPl1CNoR1JbrOWUB2iCzKEJOTkMsKZ5hJHNffrZiqc6OScwznVUtks5JJbck2RLHZoLmVtNavjcjj0 + 63nkjy7a2vptn73Pvu/3+33f/fa+CAD+i7+NFEb6N4j25zD5fYhZ2UeOxCC1fY+NjFvyfXoir7cd68uE + RG53Rzy7PeYEPUmReIifWdm/nkWxnJ71cFC6YGdsefdYUPpdQ1pE2bHg/Pq1KZEYZkTL0DXxGbhtQrjI + fj7kf4Wjj/3Ss+JvKI5kGTe7SIFsZHF704vJOTidWtOubWCqYk0vLbQNrwAHhgCibjyFwY/z8KB3GiKL + O0bMaF5byUOjf2TRlnM5dQm8tnEYXVoD1uNhcIzmXNXZZaFsYM/QNaBFUs28CzIPRVSudMyI4FrtW/DP + qL5EcmHXnyHkElNqlVDeKxEuSKBftApj8ysQlFUrsfBIoREThixQwfRUXmZAXgPcGZiFM1l1ZGkKAfkt + CNkEc17bnOeBT0YjtMwuQkBeC+ync2Bf4C0hNlE2CpS2GTuZ2YZw4eHEPPikN6xgTQtDlorkMequyXUr + zR8WwDutCTSojuZYU8bIYOSck2reuF6uB8+URuCOfgVydk2uB+fEmglEdSvCHqRoz6h6xeqchjh2Hxy5 + UJ7/UwHF9GSig19Oq6TpvRj478TQMLMEtNCKVU3zQBdkF/WIFMhZ+RenhpT0QMXQJ/BKa5LQwli51IP+ + 5kaHA6lyKhralr4F2aHsASgTLoJPZgNoWEYX4pwKsgqtIgXSylq7tS3plcJw7iDwR75A9O0B8M5sBffU + ZtjrWyTAHn3zAHYf88kUqFnGvZSmqGpjTQaZBt5D1VNiUiKrZeFjZeJXPu6Z2wnJNUJgDc0Ba3AOHOJr + Qc8hga5m5GRtcpY3SdG0O4D9FGXjeISovnyMYP1KRHk1wx26R9PzDN1LhrAOWAdDD9aw3vFspgxFSRV7 + yEckJ2/AQITNhixOCaOGIa+pg1Hf0Mi9X2ezX/TfAfQdAvawuvfdXuIAAAAASUVORK5CYII= + + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFlEZXZFeHByZXNzLkRhdGEudjE5LjIsIFZlcnNpb249MTkuMi4z + LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjg4ZDE3NTRkNzAwZTQ5YQUBAAAAHURl + dkV4cHJlc3MuVXRpbHMuU3ZnLlN2Z0ltYWdlAQAAAAREYXRhBwICAAAACQMAAAAPAwAAAO8BAAAC77u/ + PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4NCjxzdmcgeD0iMHB4IiB5PSIwcHgi + IHZpZXdCb3g9IjAgMCAzMiAzMiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv + MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3Bh + Y2U9InByZXNlcnZlIiBpZD0iTGF5ZXJfMSI+DQogIDxnIGlkPSJMYXllcl8yIj4NCiAgICA8cGF0aCBk + PSJNMzAsMTRWNGwtMy4yLDMuMkMyNC4zLDQsMjAuNCwyLDE2LDJDOC4zLDIsMiw4LjMsMiwxNnM2LjMs + MTQsMTQsMTRjNy4yLDAsMTMuMi01LjUsMTMuOS0xMi41ICAgbC00LTAuNWMtMC41LDUuMS00LjgsOS05 + LjksOWMtNS41LDAtMTAtNC41LTEwLTEwYzAtNS41LDQuNS0xMCwxMC0xMGMzLjMsMCw2LjIsMS42LDgs + NGwtNCw0SDMweiIgZmlsbD0iIzAzOUMyMyIgaWQ9IlJlZnJlc2giIGNsYXNzPSJHcmVlbiIgLz4NCiAg + PC9nPg0KPC9zdmc+Cw== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUAUmVmcmVzaDtSZXBlYXQ7QmFycztSaWJib247UmVsb2FkzU326QAAAwFJREFUOE+lk3sslWEcxx/k + uOcPl1CNoR1JbrOWUB2iCzKEJOTkMsKZ5hJHNffrZiqc6OScwznVUtks5JJbck2RLHZoLmVtNavjcjj0 + 63nkjy7a2vptn73Pvu/3+33f/fa+CAD+i7+NFEb6N4j25zD5fYhZ2UeOxCC1fY+NjFvyfXoir7cd68uE + RG53Rzy7PeYEPUmReIifWdm/nkWxnJ71cFC6YGdsefdYUPpdQ1pE2bHg/Pq1KZEYZkTL0DXxGbhtQrjI + fj7kf4Wjj/3Ss+JvKI5kGTe7SIFsZHF704vJOTidWtOubWCqYk0vLbQNrwAHhgCibjyFwY/z8KB3GiKL + O0bMaF5byUOjf2TRlnM5dQm8tnEYXVoD1uNhcIzmXNXZZaFsYM/QNaBFUs28CzIPRVSudMyI4FrtW/DP + qL5EcmHXnyHkElNqlVDeKxEuSKBftApj8ysQlFUrsfBIoREThixQwfRUXmZAXgPcGZiFM1l1ZGkKAfkt + CNkEc17bnOeBT0YjtMwuQkBeC+ync2Bf4C0hNlE2CpS2GTuZ2YZw4eHEPPikN6xgTQtDlorkMequyXUr + zR8WwDutCTSojuZYU8bIYOSck2reuF6uB8+URuCOfgVydk2uB+fEmglEdSvCHqRoz6h6xeqchjh2Hxy5 + UJ7/UwHF9GSig19Oq6TpvRj478TQMLMEtNCKVU3zQBdkF/WIFMhZ+RenhpT0QMXQJ/BKa5LQwli51IP+ + 5kaHA6lyKhralr4F2aHsASgTLoJPZgNoWEYX4pwKsgqtIgXSylq7tS3plcJw7iDwR75A9O0B8M5sBffU + ZtjrWyTAHn3zAHYf88kUqFnGvZSmqGpjTQaZBt5D1VNiUiKrZeFjZeJXPu6Z2wnJNUJgDc0Ba3AOHOJr + Qc8hga5m5GRtcpY3SdG0O4D9FGXjeISovnyMYP1KRHk1wx26R9PzDN1LhrAOWAdDD9aw3vFspgxFSRV7 + yEckJ2/AQITNhixOCaOGIa+pg1Hf0Mi9X2ezX/TfAfQdAvawuvfdXuIAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUAUmVmcmVzaDtSZXBlYXQ7QmFycztSaWJib247UmVsb2FkzU326QAACWhJREFUWEfFlwlUk1cWgB/W + XUc7LsXWWrfR0arVERV0HKVV66goiy1qkVEEpai4s68iigpHRdwQIeAERKoQNyQgAgISWQISBWUHZZXd + kIQQvL33J3E4Pc6cOZ2ezjvnO2+727vv/i/AAOD/ygcXf0/+l6b1AX6z9u8M07iPmo8+gGavt85/bkei + ctmRnxDsvRBsnBPPyKwIx9DH12msWTt4UfiFa9jjvW78TKEHPzPHPTxL5cbPUrn+84nY5apI6Bicum/X + KcF4lNUEo+Uc9oQ5hRIi5sQTMUdeBnMIQYKpf8yY13Uxk7979x5SdOGlr7uaUgxBwgKwDYg3JIPb/eL2 + HLkuVsU8KYenVc1Q1igFWXc3R1njW1xrgpsZZeAVka2yC0oNtvQOH0d6ZK+j+x3rjVTNwaA0xjyuZTMZ + TghsWt/t8RnkGZFV+qpVDhUtHbD/UkrpX41thpi68qcdCkxWNneqoFqpggqFCgrlXfBM1gVF2NO8TtkN + b3B+O7MCnEMypLtPx65Dm/0oCKkKnf6CfRcfMYYpfO+cBB1D0l3u5VRBPTopV3RBZGoxWPrGuuJef1O3 + m77hKUVQhE7ypV3wVKrs4a0S8tQ8bVdClVwFBTXt4B72BHadEdqhLhdEe9c71hvbcymM0R1ROkjAxi9m + /LEosbQBT/Siowvy0Fjl207Yfz6pw2CX/yQ9I9tRGz2ja15iZsowiAo1JShbiIHktnZCNpLVqgBJeyeU + NsnANTRDZeUTbaoOQkvjvK2rm+30f8iwKETknE7f1y4oLVZc0QwVGEB2CxlTQD4GkVJQCxs9ou+jzMDl + NpeNjewjwcQxEvS2XQa9LYFg7HANjkZkQHZ1GxeEqEkBokY55DQrQFzVgnWU3GayL2Ay6lNNaJHzVsT6 + 1AOc9jj/yNZfaBR4/znUdnaDGB2LmuRqFFCM6fYMTYc1e4JNUHbgfLOztvM2+q4YM/3rYYTO98dW6pqd + Dfza+kpn6MNCyELnaQ0ySK2XwVO0wU8qAsvj93ioOwDp06LsZoTVyXic4sKS9TuHYOWWFWNlP8PUpaMy + xxs5h6hRBnmvW8DQLrJs3KxvhqMOpVPz7RN9kQFzDN0XLdpyqSY0sRAeo35STQck1UpB0tABu/0fqlZb + +05Ty2o1darYVp84HOLCztNCtxvppVCOd0lRp9R2/Iu6HsR4krM3s2Gp1SV31OmPaN4HDTTvP3uds94y + 6yBlGl5l4uu3EF/1FtLrpHDhrgR+cL/hSTIk36hQsb0BSYyZe4R/idUqr8IiEr2RwQNUSnwtxV4KidWI + ek7jgmY5mDpGKuesc56FRriTaNJJY4SyMXDh5jNBJ7Am0jAD98rbMYh2uCV+DZs8BOiRDUL61GMAu89g + EVqfSrif8KwOJFgwORhADqYuB7MQV9mOvIVsnGugvZiMEpi/0Z9yx52EUkk9GUW4AHRMDv99g+N1zt6t + 4laOxNJm2OB+qxb3/4BorrAPM3KIgnVY1QYHI2D1vgiw8o0HEab+Tmkb3Clr48Z4V7B4yyVYaH4BdM3O + wbyN/vQz1vsayBgV2GBk2HDtP322zDoE8vFQN140Q1RhMyThYUzdBErcH41QHQ1FKBtcNO+VDRxiOgvb + OiHmZQvEFLXAI7wCCmCY9pQxuE/RkxzJk1PNyQdsPXofeoiFrcdi4Xs3AeRhANeeNUG4pAliS1rBxCka + LI7FwTa0t83nPlhij7rvjdCdDl6x/0ZNJqbu+vMmuF7QBAnlbVTBsHrnuRW4P1Atx528VtaFXU8ABvv4 + QmHuK6jBh6lajRg/x7C8N8DLfQMCzIIEr7AUD1eIb0xEykuYY+Ibz/R3BLOi1k6NoYFLd0Y8uphUCgFp + NRCcUw/RqOgveArrHa4F4j6dnjs5OmAEjZF+840d/2J2WNB1t6gZeOIGCEHd4OwGuJJdD0FZ9RDwuAaO + CCvB7W45+D2ogiUWl7om6G3TYX+zCGQvW7gAyFD/hZYhnrYX0zhl7/hK8Et+DXckDfAPr7vK5RYnF6EM + ZUGTfg00H7Jka8AJr4hM4Oc1QOCTOrgoqoXTqdWcHbd75eCCzmls5n0Xpi538iUdpmsWwApbFDjmDPX9 + 0sBtpr7tT6rw3AY4LKwAr7gKOJ1cDbyHJWDqEl2rb+69mFPsKUK6DoLGgz/+bLq2vtWViqD0KvBJqOKc + uqodO98pA1fsXW48h+mrjlQOHjFJm9PTMT3DCpoVHNjoGgbNMb8StjdIBL4PX4F7bDl4xFZAIKYwNKkE + zDxvKw0P8i9/a3VmLcp+TCy3Or3KwJa3D8cjvlrjstnc6xacSn4FruiUHDveLgOHW6VwBA+zzPoKjFtg + vZn8IH3YbGNfJmlSsGcINspCvwn6e6bpWPClvsISzrnrHTwJGrqAdZHwognOYE3s8BViRgRg6iyA7Sfi + YPtxIehu8CHDn8w18Uv0upmP993j2F5QAs63S2HH+VQYv9g+EWU0z7kWm2Hgw/IbFYic5TfJca2nGKca + +potsomCo/fLOUPOeAonxBMDCstqgEf4UOU2yEFCv3r4cMW/bIRvbfmvPpmsN/nzOev19Lddlp14UAH2 + MaVgF40BCIrhq7U+spFTDXXJPvkZt9CBsWkrvVneG3kPGAQ2rhaQwVOM/F30fowCu8jn4HGvAhzxNA4C + DSXggMYJe5x7Y3o9rmaCntnZ86g7Zso3zsct/eK4e3dCPYOD12DM3B99cI/eErKv9emCQ4yt2B3BctG5 + GKGeoE210JAJq4+ZzzC72rHhRAq43SoBd7VBR3R6KKYEDuHpKAAK6sKjalh7IKpryhKrhUNHTRw3fZV3 + 5eE7L2E3LwvG6h6o7D907Kdokx4xrcw6GdOei2WzzIbPxA2y9+B7z0FCCAUxSHuB1YxJxhciZprzVZt8 + EmBXSDYcCJeABwbjjlW+ny8Bm6BsMPUWwpLtYSod09NOqPfHsfOtzVftCQXdTf4wYtoP5rhGXw/3CYsw + gNGzbRlbuuMqEsb+vDGUTd2AmPLYFGID/f3ABUEKFPXQ0fMsZo5f4+cywehS8kTjy5KJ3/FgwnoejDcK + lHxheDH585UnXUfOtZiJsuSI7nn4FwvtY0fN3CHE8TCEK7yRs3aykbN2sRHY/zeNgqDCpEC47x2he6RP + cIQaGpMDzftAsgQ5JHmCxmTnVzcKpHcwdD29oTXa08j1ltes/6btl45+XfvQf6y/H8B+Bv87a1kNkH9+ + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABR0RVh0VGl0 + bGUAQW5ub3VuY2U7U3BlYWvh2ENsAAACp0lEQVQ4T32T60vTYRTHH2dqWr3I/gOjd0EvAl9osYpYFL0I + JPAS0bygTmtZYeW11EwtthR1bN6ZMsTpvDQv5WU3XUlIG2IpjJYtpDBtipGGfjvPnJeBdeDD8+N7zvk+ + 53f4/Vj7S8OIrteEtu6hx4wxQbveyDWm7eGMMInK+k88wZt52KccaG7rLyDJf319g22yzmbcq2zay8ct + fq7uGHTojdjYABYWljE+8QGqxvYikgOJAC/8eTdc8yf8CMbHBN0Ep/Mb5ucXoWzSQdnQAUW9FlV1WiRW + mkG3eUhVjiFFYZkTywaenxDFHfKYtHYOYm3tD2yTTtgnHVha/uWDedaNMZeXL27o7HN42PIOMcU9L8gg + gKnb+rGy8htmq93D17l5H6oMDtSMfkKNhaCzwfoZmvFZRBXqf5BBMKtVd2FhcQk9fVboB0ZhsLyHyWKD + ybxJbGk/bsiHiEHPGV8+DKnKjItZHdwghFWoWuGim5q1r6EhjGN2H8SyQSRXmrwYkVhuwOWcTkSkqBRk + EMhK5A2YcbhoaV2orutE+t2nSLvzBKkZRUiWFiIyXQ1hhganpRqcutWCs1I1Toora48cDQ8lAwHLKazC + hM2BZ3INNZfg/KVrfDmHCb5lTmheqQJdrwzQ9Q3jdnbZGmkHCAHBmPR+GSxvpxAveQShKJo386RfdX03 + 41AEVChb4XR9h8lqQ2aurJe0feEpTTzH2PWkB4ZocSYiz0Tx5oOEQHghlglFMSwqLoOXBJXIGzE5PQsF + fRcJqVkS0vy3DSiCCT7qfmJzLN8IziuuxpuJaWQXVODK1aRzpO3U0W/wXyhC7mXLMDxqR4IkF+ERojDS + /Lbzu4v3giIo6Wb+SLK0AIlp+Qg7dpwveCe/u3gvKPi4W6/Jd8R/JG8e7C9oJiC7TxW2FgAAAABJRU5E + rkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABR0RVh0VGl0 + bGUAQW5ub3VuY2U7U3BlYWvh2ENsAAAJFklEQVRYR62XB1CVVxbHP91NcdTElF03O5mdnc2Os7vJZpPV + 2cR1dhWiomhUoqDSVIqFIlL10csLTekgvYvok8ejF6X5IMijPboUBQFRRKUIKiD633M/ulEnZnNmfnO/ + 99373fO/555bHrdD/RiPiropdyEt/0/i9KKcC2mFw+cleTkegYm+HMctUKH6tEsyHjv3SM6eYOUvYswx + 2YKEpOw/5uTL7t2+cx9PnkzgVu895BRVwc0vgYlYyNowATauEZytaziV4ey7/9+mBCxMSi/MZE5FybnY + f9gO58Q56L07gITkApxwCXFkbYgFIbGZXHxSwY8o7hni5H0jXHnv8E9iri1IFOeuKZBW4WpLB9R1raG2 + 3wq7tMzRePUaissb4ROWBEuHACdq+yvW/pcWsPBccl5se+ct+Ieeg46REzQP2mI3iXDzjkD3rbuQ5FyB + 0DseZrZ+LxXxswVYClyWilIKhgYHh2Fy/BQMLTygZ+zCi9DQPYEBek9zj+z8Snj4J+CowMuZPvs1wU/J + 6zItwF1Sx8OFRosUcgtkqG9sg7mdH8xsfGBk6QFdQydo6dugsroBRVfqkVcsRwlNR1h8OoysPF2os7eI + N1+DN4gZ4cILco7BRcSnCirkV5F5sQQ2wmAInIJgTiKOmLlCx8ABiUnZqG1qR1FpHeqabqCh+QZCYtMQ + lpCNcMaZLB7/hHw4nK18GWN28bJiQZTUbM232ktJAD+N9J4iEJtytu16N+JF2XDyjICDezisnU8TAXD3 + iUF2Xik6unqRVyLn84Gnpw83acV03uybR8m1PhR29KPwxgAKqJwmr/0+xPIenL7UjBPRpfVatuGfTEVj + ARccLZb19t1HeJwE7r5x8ApKoOcU0LJEWWUjushh371BpOZeQd/dQfQPPsTg4AgePx7DxMTTefQ8GkPB + vUeoGRqFfPAxMVuyd6W3hyGqvoljwYVNXyh89w4ficDwpBtDD0YQHJUEn+BEBEUmoYNWxNW2bhr5HZ7h + kUcQpRZhdHSUZ3x8nBxO4NmzZ/MYpg0s884Iqslp1cAjYm45+Vx8awguoipou4gtScCbnE9o4tDo2DjC + YlMQEp0Mv9BEjDykhmV1KJe3oLKmFWPjTxCZmIUeigaju+cuOrvvUDSG+VUyXfbeG4L3pRZEl3UiWNo+ + S/Hsc2hxB3yym6DulFJGAhZxpwITxlj4os6kIzohg9Z+FJ4+fYqktAKk55bysNEFRUlIUCvKSVC5vBnS + sgZcv3Eb7Z0E5Uh7Zy+uEw6SOgQWXMPJnGai5bly8tk/rw3f2YjHScBizs03lheQKL6Is4SdMAgTJCAw + Igmhsak8TIB3yHmIM0qIYr6ME+VBVt3CR4kXxtMCs7gKuKc3wU5cD/skQlxHJcFK9o5KW1EtlE3PjpCA + JRxl/tDo6BhSs6RIziiCwNEPd+72w841FI4eERB6xYJNkUfAGQREpvD4R0hAJyWyCyqJqikqIblYAR1/ + Kaziq2AUIYNReNlkOY8y6PgVYe2hSFqDFAFbYfBNtgvm5pchK+8KnD3DkJFTjENm7jhs7kHbrz/N7wM4 + nYqCg0cMHDxjYOcWBToVaVPKRPgcPEPToHxCgj3f52CHQwaRPgf6bZ+BXc7Z2GQhwso9p2xIwNucpb1f + RWfXbfxQVoPCkmpcSM3HoaPO0NSzxh5dAY4JvNB1sxfWLsEwtQniMbLyhcAljBKWJe0sBkIRvjE5D+Xj + Eqw3u/AjlCyTCQlWagQ2v/v7T39DAt7gTKzcRZXVjaiubeXXfWl5PQqklYiKT4GVrReEJ8NQVdMMC/uA + GQFHzL3gGyqhHTBnHtutRNhITjZYSKBgKiaSpkox/mOYiK90o/G5mn/zx19pfsqPnm3L+sb2wrSsy2i7 + 1oXahuuoqWvFD7JapGYWIThChKxcKdJzpDhm7cc7Nz7uB92jwkno0NIxdsZ+Q2eo6Hvgn3tC8AXxj93B + PJ+rBeHvqoH4TDUAf1Pxqlih7Gi/ZPlffjvlnN+OuV2aRltOBcShr68fLbQlN7V2oIIikpEtRViMGPUN + rTgVGA8TwaQAkxPe2LhNx4c+ZiF8n6F8NFK6ySgGigd8Ye54GvqWJ6FnMYmGgRM2qBikUbsPiSUEO5gW + rtjuxa3Y4c1xK/765e+OmAofDA8/pP2c1nJHD+S1zcikRIyKl+D+/UEcMXWFqXUg9h12xIat+5nzZQQb + BTvh3lIyPoOtnlKs04/mNyy30+fhFiSCa+A5qOnaTfz7m91fU7tFBD/qNQbnqJi1peoHLEXFpdXo6r5N + O1wv5PUtyMwthiQ9DyVX5NCjcGsdcoDiZm12P2TO2VE8fR9YuPZgHDRCq7F6XyRqGq8jLb8caXnlCIhK + gbKaaQ61YSPnj2Lm/HkBbytt09ri6BaM+wODvICqmiaa98sUjW7YCwOhqW+LdZs0mPP3CN45JR3HYM// + 0gq/uEojDBv1wzBE50ZVYzsqG9ph6XQait/q7aM2fMJNO39eAAvjsp2aJpfldc10MWlFKS3Jgssy1FIk + VLUt8N8Ne/2ozYxzYsEcASysS7RNvGD9fRj6h0Ygq2lDoawB2zUsBj5c/oflVM988KF/kQDW4aJVq5VW + HT7mPFBNo2fXchYFPWMHKChpxFD9B8SM8/Vbdbj1Ww/QI29MwDvaRz0hEIahr38IJdXNiKBc2LTTMIvV + ESz8LzU2j6zB4pWrlb5W3nnw8jY14/HNKvrSdZPOWaZPrllqq6i8n1PcQlA5ZezbZVpGbiQgFLfoKl9Y + 3kC7ZgQUtuxnl1g2/5NL7kW2bbcxK6ZFsEx9l2AjZiFn16eZkW9WOcQpKO/jFDZPMmXsu/e1DFxwggR0 + 0nF9ka5vhlYnsUZRVYvqFhP898Qrjc9ognU4fYGcVv6qj1nbDzQOOeC4Swiu09GcJZXT/wsBPvty7Wqq + Y4Ni/f4km3Y2l1cZq2dC39urZwMTGz9cbb+JtMJKbN9rgo8+/uTPVMci+PJ+APxsyFjHLEqLFTar79qp + YVqlSn9oVPdZYMM2PRm9Z/nDrwBixub1MffH6zJlrHPmhCUb224/mmJu8s6zeX3M/fG6TBkTMB0JJoSF + nMGeX5h8s32A+x81vuvcCqURhQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAU29ydDtN5wX2AAADNklEQVQ4Tz2TfUyNURzHz9NzX5IxNpsxtFkoXW7c2711u/c+10veSuQmiStC + KhW9KldIisQ0ZUhSrUbNS8zbVu7QZLlmMyEiZGaNP/3h5Y+v8zvht3139vw+3/N9nnOec9jBSwrjJR1o + UzxcIO2/qHioR4A/s5LWYU9xiy0rr86czJiPtPFoCEuqnMMNf2HJRTu+fX8olHPeAd7zIZDb4GBMlqX0 + Gqvt2PWkX4X1MT/i3DqjRiVLiWUhjO27wA3cXNyi4N3XBvS824msMwoFyAR4Sa6S0AlFjVFf+ofa0TvY + guQKy8eFW6eN5waJuZtFgFzYpODNUC0e9mcivcYuAsb4qpkpyl+TUaN4uvvOcl4H7/si3PQWY9UefcfU + 0HFatqvBLgIK6u14+aUa99+kIaVKBKh8eG09bj3c2rUX/UP1eDSQz3kqugfycPJaCpZlB5ez3DoRoMqp + tePZ50p0vNqMTUesYJKkouCl2QaQNlXa0Nm3RWjDYSsWZc0VYpmnbCIgo8YG72Apbr1wwVUeQV+g5qI/ + QUEjXIeseDJYJnhCiYW4n/CknRAB6m1VNnS9L0T783is2R9OBg2BtaURNGhoUvcHt+DO4mEe6w4jJt7g + l1QRgU6+gW3PVsC5JxySJI3k/X9foXG6w+B5m815DFYWhUGWZe3yAjNjrkMWrC+zILE0HDf4+pqfLkLM + LjM4FPobol1RaMad18M8Ot9Efe2yXBNjZpeucm9jLDwDObjyIgHnnzhwuXcNCmqjoYudUcGNKln20Ubn + mtD+ch3qvArf1FAK8F2yw8jY2Mmj/cKTZt07cNWBM49tON1jw+5WM/RxgZ5R40fSMmgJvot3GNHWuxqn + eqyIzDSKgIUZBj7wUzh9nv8UJUU/dOyuA+W3I2B0zfw0yTRxErHITGEiM5qeOlH9yI552w0UMMKRyu9C + 6HodGeTgqIDIqDzDb0ea7mfAAn8r9QjMT59Lgy8345x3JY4/sEPZNkcEKCk8wJAYTAa+6ZJ6tjMwPzA6 + II0//9t9ZknW06DRrw7qCkkIQkh8ELivSy2rNPr4mcT+F02gt5LE5P+lUtHNpHNBh4ek4TeU9xj7A9j/ + Zf1QCUXxAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZ0RVh0VGl0 + bGUAqO7SJwAACZpJREFUWEfFV2lQlckV7bexyahxEqdcMpWYTKKMCggqD3zI5iDi7rghgguCwOAO4oKI + yxgBKUdHBFlF3GZw3HdFVFZBcGMVFBBBdFTQlP+sk3v7PRiZSkzyJ7lVp76v+93uc/re293fEwD+r/iY + KX4NNnr+R6Y2Nyd8Ymj998ZEKoL6V+C+j4ro06unUAqlQqlWKRQqJSlWKLjvo7bnzLhOkEny3ac8rlEb + H4L7+DeDj4g64CIiD7iKiHQXsSbZWYTvc+ZuhYL4A7bZp05fZZOqFKSH+qYsGyamLBkmJoZYi4nB1mJC + kBX76i0yY4xoe1Mg2glkPLl6249uaHuTh9dvcgk38ar9Jjb/MJqTpjH4iDVpjuLt21Lx5u1tCTMzU84R + kWu94o8FIybNH1OWWXtxH//2sj1PvGi7Lp69uiTGdwgguWJ9uisJyCPkyi6CZisJqH2RgZLGrShu3Izq + 1mRsPCQFGBl8xNq00URcQigW7QQVxd53w/AB6xMmtD1uPYPa5iz4b3J7O9Zv8ACVQikj0frqsmh5dbFr + BCLSXAWtUtAqucm1ZrTliBuqn6egqCEKRfWRqGxN7BBgTODJxNoUR4oakb+5JVRqldLSsa9xSNyo/NKq + A6hoTUJ+/UrklO3E1yts8j//8lMTlVqtbHl1gQRc6CpgXaqreNmeI0HGqzPafNgVlc8SUVAfgYLH61H+ + bA8iM7sKCE8ZTVErEmqlhkWrg2McNmVlb0TdiyPIrV+Bq7ULUVi/HvuOLcfEb6w2UUGq1QqN4unLc2J8 + 4AcCwpNciDxb/Nx2lZs8ufHGgy4ob9mDvEdrkFsXjvvN32FduiMLMCEyKSAsUccPFqwK2GbnHH3Y+33j + z6dR2LgBVx4uxKUaX1yo8UZpYwxWxU5+7+E3hKtUFnEXAaupel+0XREv2i9zUwqIyHAh0l24URuK67Wr + cPdpHNamOoLITQw+wpS08PvkwMG/C43/qqnqSRZuN8XgMpFfrPHB+eo5OFc1C6crpuL6g02YHaptGuEx + oDeNUdEZIeuIMy5C9zqJ568vitbXF7iHJzeJSHPBnaY4XHu4nLAMpU+iEZ6sjwD7mPT7vcFXoQmKc8i6 + VrqbBCfgSq0/EfsQ8RycqZyF4w8m4GCZFll3x+Ho5TB4LrbMIk4uZKVx3/58TCjFynhnKoxzEvpJhcma + ZCdJerUmBFeqQ2g3bENoIkdAaco+vK3oqV68XeuffDoED1sPIqduCc5XeeNspRdOV07HD/fGYH/pSOy/ + PULifOUCbE2aC/cFQ4JorMbMzEwvYNkuJ9H08rh4+vIU9UsBpmEJTrT9tuJSZSAuEng3rIjXcQRYAOdR + 5RthO2Rj8uR3D1uyUNKwEzk1q5FdswqXqkKQWeaAjNvDcfwuRYHwE+POTFyrXIeFEa7vnGYNHGqYR4gl + Ox1F3fP94lHrAW7S+akwXRk/mio4CucrFuEcIf9xBJbulgLMNCqlFOCxyLKUAMZYv6HyuWCzVhKml9gi + rXgEjt2ZgRlhw/U+i8jHT/909xtaSnPw8S5EUKxOPHyWKmqepXBTRmD5Lkdcq12O4/dm48Q9L9yoC0PI + Tr0A6UN7mp60+5W8LbkuuL/7vCg7KtqNSC22RUrxcPxYRgJW2vK4HgYfU6GQYzRCRUcXW2C0TlS3JIuq + ln3c5NWZhcTpcKFqITJLXHCAcLbSF0ExDjxRN/aRBUQVqFIaKWkZSrVSxasx89lgR0W7AclFw5FEOFo6 + DdOW28hxBh+i1TCxggpZ7gS5lQxgcj7rzYOiRxHpPGSUOCOj2Blnyn2weLsUwHcs+7BvxziaQ8FtU+/1 + dlS467Cv0BaJhTY4XDIVU5cOM0ROoaptPipqW44KD39L6tIbT8DbgouLQ2RO6BXwNwecJtL0W05IK3LC + qXJv+H1rzxP9ltDd4Mf+HE4VlbOSVJh5hY+gwl2NhAJbJOTb4FDxJNAtCPqVS175sPmwqCFQzdAwvWl8 + NmhL50dpMX+zPRYa4LfFHicfeBP5aKQSTtyfjQWb7OBLOWZf30h6p3DPWTeyjOYwoslJhOg2a/UIXCgP + RXyejcSBogmYHEIRUIhu7FPTfEhUPz3YRYB6jI+FVcAW53dFddtR2hCL2w3RKKnfTqReSCkcTXDET/dm + oqAuCnl1kcir3YCr5eFw87V4N8Cu9zCaQ0OTq1nAjFW2OPtgBfbkWkvsL/TExGApwJwuS1VVU6ZgfCiA + U2DiuWhocNgeFxwpm6wnLXCUxMkFOokkRr4O+/J0VJSemLveGn916rOUxlJV8+qlAPNpK2xx+v4S7L45 + TCIt3wMTgqw5BVJAZVOGYHwogMbJguo2frHVidgTnsi45d5JKJHnQMQOSCSkFrogIk0HC9d+J2kM1wFX + Nn960ZWvMOd8n7wbjO9uWBOskJLvjvGB1hwBOvwVqoonGaLiSXoXAWwswmiQtm//qctsmtNzJyI536mT + VA97ufq9V9xhO+kPzb3/3ONzHkNQckh5dSTgk0nfWON4WSB25lgRrJGUOwbjA6ykAPZhrgeNaYIOJnr9 + xVgAp8J41Nd/GTcv0u59ZvF4JOQ6EOyxV0JL+XTHWP+B7wdoP/Mk345bkcfSga4XQN97yCr1Q9w1K8Rl + WyHxhhtoy7GA7hwB9r3fkNpVwLgAeTd3pMLMeY5FdNheqv5CN+y9qUU8ITXfFYu22VLe+0aTDx9GMvQV + T/bTQy+ASSYEWuFoyXzsuGqFHdmWSLjhIo9hEtcp4F5DclcBfCjkVIfzK4vQmPcy/Y3b/MHFO065ITHX + kaKgw7f0QWrh1r/Y2FzTi3zkdyF/3ZY3pstxsgbofPAMsMThYh/EkoDYq5bYm+Msz3+auUdHCu4+ThIe + H9YAF0R2VSi/dqbCQtfPcmKwVXtCzhgk5LjCbtof/95v8Kcs20ReoSwg0Frcr0+lV2bnPwKiB02MzFtz + EEPkMVcs8X2Okz4C9Bv5yKjdeZTYtQi/WjBEXKpYLi6V8676JRUjJ3+xaF7UcExZaoE/aT/zJ2I++eQq + CIJ2jbjXIC8wvhPoXlJ0Z7KMwtn4PtuxEx0pYB/2LXuU0OUoFm7zBgtXA5x9vuQuJmC15g4zB2Z+4dgn + k98Jnf8J2Fx8yX/uYOHkbcFNirDCzGHmoJs6r0EYNVsPGg+76QNvdointiAfYU/Pf2cdIrjaGTJ8hH9q + hptNwyKEUtmDPip60ndFT1p5DwO5puP2+6jRIMObNKotyrch5/qujxr7qBTGJnTlUlHQVwO/c5/ht/+Z + MdmH+BcmxD8AKMcbpSgGpckAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAATdEVYdFRpdGxlAFNvcnQ7U29ydGluZzvWAzLKAAAC + xklEQVQ4T22Sa0iTYRTH37KmpaLMvHRx06lbKpVdIAkLSkOcr9Iou1BfIon6tK0PRp+MIMnQvC5LcUrZ + zbSk6GLZ3JqGNZkGCrYMRSMtMiSd25z27zzvbEH5wI/znOc557e95325cr3JWFnfAUZFHcOMcoqMMr35 + L7VmlBJXqtuNHMf5AOAYHLt0u+cFZokXnUPe3O3+hdaOIeH8D8XVJurilnsFJTWv4XTNYcY5B4drHlUN + 3XDQnuUMHeWevVs4v1xlZAKRV1B03YSGlj4qtEB3k9G9gAWVNzzoFiKjoNLABL5eQeHVds8vzrhhJ67d + 6sa0w03MYooor3+LaTqfIli8UPqKCfy8gosVBkFgpya7Yw76xl56JPZ3XSR0ou/DGD2ap5mdd1mHmSCA + 8Kw2jQL9+lx05qd4+WJ9BnXBHii16yjuFvLRN40wP9XhQJ4c21WhqdTqk6mN5LjW03GY/XwHTluxgOns + Dti/9YIu8cNpgVIjwc9xK0YGDTh1aSdsY09w6Fzi+Ma9ITIm4R4fl8E1XCs0O4g2dTKmvvYgUyPF4KSe + RFKM2ow4U5QBc38N+ibK8Px9Pni17F1E7MoQ7naOpL35iBTNh6VoOijB/RwJBl7epcYo2CZrSBSFwoJc + JKnEtI+GYeSkcJe0T4yE9OA8NgY/gg0lkAgiVhHRPBX3T5SA18rY0OKJBF4jw6NP+2k2wtlqYoXwKryv + hL6w1BOSPFbIa2OE4kyKvDYOu45Gnuc1sWgZzBbuqDaY18Rx/wqWBoaJwrapwq0PurR4+DELzV1qbFVF + 9ASIRXJeK0eTLYMEclYspvifgK1laxL841OOrf1eZ0kDixHr/RPpPJTXKnBvII0ECkGQpVEsKlhCiGTb + g9I3Z4dPxiQHKyn3JQI2KUM7tqjCsUEZ1slyXkOjWUTAliAh2HBZZLkPwQYtXoiUc9xvGHI82GLBhXIA + AAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAATdEVYdFRpdGxlAFNvcnQ7U29ydGluZzvWAzLKAAAI + c0lEQVRYR8WWCVBUVxaG0SRq3MYYgZgRUascIyARESFj1FBo1BGMhkTjbiJx1KCCO+KCohHihoIgIChE + ZVUEN0QIKs2OokbWsKmobA0CDd2A1j/n3O6GNoXOODVVc6u+Pve+9/r+/z13eU8LwP8VrYN+NwRUumjQ + 9X+A6MvtWDwFZenUwAHfRL7HD79DvEd0I7q/hh5vAffzLsFmROnUABUhvt393JR9XnFZ7t4JcPeOhxtz + TMk+wXWqXxf1n72ud+DJxAn2auDqcTVr467TU6lvNsEabzTQjTqrKH4oRUvrSxUvBAqqB0dmiWuKFmq3 + UFTV5URwRCbkCmW9HUUb8oursOvw1Urqm7MhsvA6A3yzx14aSWsbd64WYXGuv0BQZKZKXFOEYxuCIjJE + vZlEm/8UXQ7HskJPgqf3jQbedz0SqzTwGpFmagtE50qBJiIoPIMiteXKdpNG3HHwCiv0Jt5ogG/23OUR + K9KsFm4mYU4lC50iERYVQnyNOheC8hc4GUYGRF2JrFkF1bf9cokV+qg03mig185DV3A5IU+IvQIJKOvp + VGcySDT93xOaBmf3mP/YQO/tBy6L9CvTR5FHo+IkGRB1MbLW9lE2NrUikMQaRV3ZbmxuRQNHYsvP0azQ + l+Cd8NoiDDhTujj9TSwgRDqEeETKNnfchvqmFhJpwfPGFgSEpFBUoF5GbYLF+R4/s2nPBTbQj+DzRWzF + zgob6OO0L0bMPY+AESNU1QMpncqOW4WQMNlEog1NSMsqxvMGGRpkzWSOTSnICD1H5pz3iQx8SLyv0unU + BN/ou2XvBbHAlELqSFBnAWyAonrUDTI5vKJXYKPfZ+14Rq0Qhmrr5SITtQ0Kyk4S/m49aPQ6H4vH36wZ + OZx0RCbWeVtoOQrMWV/Mz182up7Hpes59Ke0dk6EpHbUz3I9Ff5nkpGa9Qc2+FqgTp6j4gHW+1ggJbMQ + vr8mw+90CkKjbyM69jZW7jeNufUgAKsPmV0mnV4qvS4OnuO01np2GOi3fvc5sfA4xfU0Wk4jj4RHzOIc + 66gtfd6MaulzkHuU1V1A2kMXlFJ0PGaOqpo6VNXK6Bk50YjjZ/3gFWWHEmkUfGJWYLGz8RLSEtNh72Gm + ZX/YjPWVBhx3Rop5ZyFN6gg2wJGpIQMstNbLHKXS80gr20nxHNYcNUdFlRQVNY2Q1snw6MljOB23Qf6T + GKQ/dEXhs0twPDKhwniC7iDS4xdb11UHOwx8sHZ7OC24NtQ1kBCjEqylReVPKeU5ratX0AibUFEpxeoj + 41AsjUBq2Q6K4bA/PA7PnlWTiXpUVtciMGYPolPd8fvTY0gu3Ya7TzwRQ+2lLibBpKfemmJR8sLov9o5 + TGwxFq9l6pULqZZEeU6lFPlapVSGiooakHsUVYchhTovqg6luTZD+dNKYS79ngS7TtqipCYKkpKtgis5 + y5H5yAO7A21fzrAbYU2a7e8INvBhkpMhkneYCSTquI0ZC4nzWCSpuOFkivsXPLDiFzMUVp2hzp0pnsZy + t7EoSLuGwvRYOB21QXZxKFJLd+Nm0SZE3VuM0Du2iLy3ELfyPPHDLrM8ncG9PyZdngphYMCNDSPRVpOA + 1ifhaCkPQ6sglOqheOC/EC2PQ6F4GAJZyRlUlibBbu9Y5FcGI6l4C8UgLNtjirI/7iDkohtOXdkszGWX + HyWDLjibOZuMOONGEWWj1BW+F+1h62DkRrr8ohIGtBMcPkEricgLPSAv0CD/MCRbx6Mp7yAac/ZDmu2G + xzkX8b2rKXIrAsQIcypO0NyOQcH9W5hm9zdYLhmML5boYdEOE/xWtBnBGTZIKNyIhdtMMHGBHiYw8/Va + Bw7vraM2MODayuFQPDoLOQkxzbkH0ZR7ADISTdz0GWTlCagpjkN57kXkpYVi8Y4xtMB8EZdvjzvlR7Bo + uwnuZcQhNztRcDf9GuY7myCuwAEn06bhWv5azNsymk/GkQSnn49oMQViF0QvHVbxJH4nFKW/QlES3I68 + +BQyDsxF3SMJfnAxF6NYQB0z8YXrEZQ+A9fzHTFvqwnmOY0WLNxqisykS5i7+VNcyf0JAalTcDl3FeZs + /JQNDCY49Txw8aXEPz33Tx+44Nx8/eqo+fo4z8wbgvPf6SNy7mCEzxmMjJN74OI0C3tOLERBdQgKqkIQ + m7cagWlf4iqJ5NFCzCVcab3s3vsjJJfC277dYIyYnB/hl2KJ6N+XwdbRmA2ozwHegmIb8g9ngY9JfnHo + Eh+pGKiCU6b/7ntdTSy+/mtRQMJ8BGVY40SKFfyZZCsEpk+Df/y3sJg9qKxbj3c+p+fNZjsY4/z9xfCR + TMQ52gGz1ox6xcBX9kYUOpxwJjgt/Dn9Z/gPfIQOGGrSb9bMVQYvI7IXwFdiSXyB45JJCLk9B1+vNXo5 + dMwHi+k5Fhk+c/UohN/9Dl63xiMsey5sfjJiA3qEMGC90pBCR1EbeR1skP+oM2qybvAm74k4lf4PeCd9 + TtMwFVv8JsHISjeC7nPGeIENIQGcvW2LozctcCZrNmasMGQD+gR/KXeZ/k8y0NlnkiYahU3wydWrr3Z3 + A/Ov9J75xFvDWzIBvr9ZY9zMQdV9BnTnIfEnGE/nkOnLDRGcaQOPRDMxZdOozdcJYWCqncFbGeDCJnia + +g8z7b+SDhMx+m/WGWGoaX8Hus5riKeMp0v/SzsDsTYOJZqK56YsM3jFwOTv/zsD4jOe+HjkRN2rm/3M + 8ckk3ZvU5nnn6+qp0iMB+KdOhl+qlcBqqTDA21AYsFpCR0JnoppoFqPJvDHap6KP9pBepoaWuk91hvUe + x23VdXWWtEdM0JEYWH4ENSPG6yTTdT79+H4Xy0VvaUCjsIh66/KCa//SUcFG+G2nTfCiG6aKLN7+FtTS + 0tL6FxudlmdoalhCAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACt0RVh0VGl0 + bGUARm9ybWF0TnVtYmVyQ3VycmVuY3k7Q3VycmVuY3k7Rm9ybWF0OwM5x+8AAAN4SURBVDhPbZJrTNNX + GMb/4CXxq8aZAlFG1IkBCpoQLCoqQgFXKaXcakEijWPAvAQrRZgyLahQGFuEyk201aYagQoqUYrAtiKC + IEMQasEClRFw0SItBNQ9O//GL6ae5ElOcp73d573nJf6b2GQIsvhyQW+a39xnHygWDA2UByH50Vx432F + sRXtuTxX+nxxWkv1yWIoAF/IVtydH8Pu/zV29h9tESzGRnyc6YRlWANT43n0FkTPPpZyQ2jfsws8e8Bf + ZyNc/5ZFm98b6rEw1YiefB4aBRvQlcvB3IgSb3uryT5ipv5EsFvnuf32gC4pt+R1UxEWp2vQX34QT/J4 + sIxo0H52P8bvpGK2vwDGuiz88XNYKUnhaAfoyOFMWF7dxMJYBRoSvfHv01JYBwsx/0qJ2ecXR80dJ3XT + OqmmRRL0OwEspSF0O5mVLIoW9Wd26ML8aCWUIc5QsJ2gCHbC1SDGnLnzVNeQNrmmXBWq/+XKTgsxQ1LB + Monl26pS87e40SC9WU5Rj07unXjXnUdaaII61gtTnZcxP1bT9ahe0JRV6f/hepsIj4150L+To90ohaL1 + EDLKtll+km3dZ0tz98iOcr3qB7zvzYGuMAENaX6jPZqE2swy1mLbyzN4OpWNFpMI/ExXNI8fQsdkBpqH + MpFe4jsjlGzeQFXFb9l47+h2i+leCsw9BahLC9BliN2HlK1JpPAw7hujECFeC+5nyVv34IExHle0QiRf + ZJaTFJTjVaH393WHfS3dv3Ex0SbViC/5zT00pKJhhIfrz8LAOeaCB8PJaDOl4Y6Bh1tDoagfTCQAj0lq + fuw2DVkiC9+0SXnAq1oR5yn/Md/zU4MhCrUvOagzhOP8rb1gpzJwpNQD6sEgqF4EQv0iBKLczYuUOp5J + qYWeNMSBBhGtSJK6Typ7gslNbGIMgsYQSWInYY9oDbJVTFzr24HLHf5IOLNx8ouhsA0G+WvBqfXVebUs + 3BjYDbmOhYDE1TbtPLgaZbpdqOr1Q85NH/DF3177GsAxMJ7hITy93lrc4gtFXwDuDgvgL1xF+o8hxSzI + tN6IzXKzbud/w7QDREvW0ZBlbJFTZJRkrVVc7Y7CZh9o9HwUNHshveo7RIpdrIEJa6KJb7kdIPKECw2g + 32MZK2IVc18K40b4cZc33HRnhB93fhOWwlD5clb62IopyuF/1GFFjYjGMDUAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACt0RVh0VGl0 + bGUARm9ybWF0TnVtYmVyQ3VycmVuY3k7Q3VycmVuY3k7Rm9ybWF0OwM5x+8AAAoDSURBVFhHnZYHVFRX + GsfHbEhi1iTrYS1YUBQbLmLAiIBYIARUylAGEAFXIoLgDEgXQboS2kAAmVCkSVGkKBqwUGewIHUsVLEB + IlEREsWQPee/9z7B4NlJovs/53fu4/Le9//ud+/73rC68zhvQTSF8AHhb4QPCR8RPp4E/ZvO03umdOVw + WF3Hx8l+DRWAd4IxHesrYf32REifo+bU+KMc/03yLWns4PZsU1Fnjll/dw4HHcfN+tuyTEWtqcZBJwK0 + FpD7pAhMImOPq1ivHhSwOjP/zwSIaKAPLbUWfSE+Zhx3J99q9LEwDCMduRjtO4/fntZhtLccw205GKgN + RVfOjpGriYZ25BlaFZr0lFf38lntx8zI5fskkPum7FKJ+9UXkBU29l3ywau+CxgbqMCvD4sx2pOD0Ttp + GO0m9GTj1YNCvLxbjIfl3hCnmJSmumnKkOeZStxOMaXxJJpJgoqaf2igLju9LdO0cbDuO/xKjEfvF2C0 + KwWPL4dBFGOMsx7qOOW4CqXuahBGsTEgCiXJ5KK/KhRigbHI2UBhGonzwU2BCRNUkpkkqGjmnzQns/l9 + F33xqr+MBM7CL7fi0Zq5CyU8FZz31URloBZqQnVQQcbyA5oo3vclmlNt8aIjGfdK9qM+1jCCxKGHky5I + opkkqKTiuWrLO7O3j73sOYWX3RnEPA71CeY466aKqiBtVBPoWBk4ToA2Kg5tJsmtwWOhP4Zb4tCaYPoi + w3U9PZh0QRLNJEH1ybUEw8jeck+8vJONX27G4H6ZO2NeGbgZFQGb0CCwJlsRiV860jBQF4HrSVa46LcB + 7Se4GGkMw/PrQejKs0NVsK47iUcPpEQzSVD9vSWJfe3pFXLim0Lxc/Nh1EYa4pLfRmKiiYak7aQiCRgh + 88MNga/vuRGHJ/URZC4Cz6/64WmFI3pP20MUoldD4tFteC99Jk4yHnzeeATPhC5IZi9gSnveZz3Oe2vg + NLk+Zr4YxzjjmC3C0GUfPL/ihyGRF55cdMDjs9vRX7oTNYe+7iHx6GvJvBHj/KU+b01gjw03BJOV2GO4 + PgClXCWUua1Dmcc6jLTG4mdxHH4m40grHyMtMXhWsx9PqlwwUGaL/hLzh71FpkV3T5pGlrpv8CbxphL+ + p2N6J69jef+gyvKkCNayPJLWkunX+ryRbzD4THQAP5XbIlZnFgrslqHg2+UodlSEwGA+kgxlCQtw1ECW + rHgPHp/bSYzNBu+eYCdXpev5J6ZtPBeSotHtm6w2dCBVHd4pav1eAlWRa/yaIGsvhbc6Zs/Tk6yWviiW + W+Ia6s1oWt1hvfq+Mh4Gy2wwVOeD2lBtnNy5BCdsl6DSXxPPat0xVOtGVu6G/kJjPCgwutWSvsWbn6JZ + GZixYex4lRNq2qIg7ktHz1AhxL3pqL4dicxLjjiQrDHiFPHlWx2zuS+S5RqvTL0ZTf3RVyu6LcOWJGCL + gdNm6Mq2QL6NPPKt5ZFuIov8XcsgjtdCf4EhGvkbb8btWuoXlKJ+X3DOBjeIaceTDIgfxeD6w2Bcue/L + UE+uW/pj0PQgEfElluDylUvZe+XfdExe7GrGnErqkMm/FGqDdcceldrhURHpciXmEIZsRq7VYuRsX4w0 + tiyiN8/CYXXpwcBNM319YlUe5NVw0flTFpr6InH5njdEdz0g6vGAudcicAjCHncGUY8nGnvDkUm2zjla + SbRWbzbTMZ2iV712J6JlmVrE04hv4LPxqNAI/Sf1MVBqjSvhOsixXIRsczlkc+ToG3L0YNCqCrrytsEU + suIg1Pa44VL7PoRkf4094Upw+34tg3/aJhzO0UVFBxdV3S64cu8QYgqMYX945Vsdk4r5FmjIS0uf5qrV + N8dtQ1+eHnpz9UglLHEn1xLnPVWRs2NJb7iVXID3D2r/abjHR/2DENTc4eFiuxN2Byvi2xBFOEcowzX2 + K7jEqmBX8ErsDFiBI7mkfXc541KnEy7ecqdVeGHktPBNx2T96KpOB5qElIuW3KLCPV81C0n3u5uujYfZ + 2uglyfQXW6Dn1I4zEUfXXxCcMycl90E1WVUlCRyWrQPnyNXgxagQlFF9K5wcwhTEnTLHPjLvc3QjLrQ7 + MBSJzRGerw2bQ0vfdEzWmb2qdJhoGlJbFWbOSN+hyD9lrzwq9F+HGzEa6BRooCVeLdqbr3y3pGEvytr+ + jbO3rMiqHOCXogVu1GrsIzgTPOM1kCO0QlNvFDoGM9Dcx0fZ7W9R2MLB8eu6SK7Qx87Apb93zMLdKqyh + qwH0ciIJmtnHTurz5VI4K4KzLFcKMywUOhLYy/y50UrDF27zUHKDg5PN+igWmyKukAPHCEU4fkcIV4St + /1IY8WRh4bUY/GI9nLm5EyeaDJFd/w2yCBl1W2ETsIR2TNobprBO2iqxTtiuYuXbKLLyrBXJ3FuJ0Jto + R/uUMN0patXYpc59KGg2JEG3Ib9pK0qbdjPGdsHLsDtMAfYEu9DlsD4oDz2H2TiYrozMazrIvPo1Mgjp + l3VgfUh+eDw29flDTSRCoeX63OG7lYNnxfbIa9xG2ILchi2kEkY4f8MDHgnrwPGeDzOK1zzCXJh6zoUB + dy7Sr2jjGIMWBJUbYXlQ7vcKSPpETmZctBrT7EJW1B8n+0sTyCH7SdG0kYaXgBy+bg+UNrgiIE2LMTah + eMyBsfs8pNVtRmrdJobIM+okSdmJM/DOCdBXZqqV75LoI/k6pPxGZE91kXXtG5CkoLNnJrySlZAu0kdp + qwPMfWSJMTWfAxf+GqSINuEH4UbCBrgLVoHtOo++BUxHlGg6mXHRbZDaYCajsDtsxVjeNVOypzrMnoZk + 6TCr3bzrn1C1+AdUOV/AyG0O2ARLXznkCm0hIMaCWk3EXVCDhe+CF1q2M2XHY/71L5dx0ZuZjsnxXBjv + m6pGEvgGaZe1cbplF+KKTOBKVmrsLkOMZeBwRBGBx7RRJnYhh04XR6vXI7FaA3tjlsGQNydsPNZ7JUDF + HMb5yz+VtvBZWB+YrYFUUtq0Oi0UtVqTRsMDe78MjAgX211wWmxHSq6FhCp1xBNck1bA0FWmZrnaZ/Rb + MMXQdTYTVKLpZCa03U+ODsxWrN0mvcjMS7bZNUEJ31doIImUN6l2Pfnw+EF45yASqtXHjdUQVb4W9hGL + oc+b3ahuJk1daYwp+rxZNN67J2BxYCEdmIcJUvIq02boc+fyLXxkR10TFRBSoIyYclXEV6ojsuwrBOSv + htP3S+lBfLFl76zIZeumMSunlN92Y23lziSXRJJMJzMhjrcsq6bLn15OJMF0TJUt0+W27p0dbMCbLdTn + yXSQMmMbGfW5s6p0HWf4qplMn0fue/PTjJqX33JjbXGeQf4kkmQ6mQmZes1jmXjMYxm7zyXMoVOTE5no + mPRXzwR0jv6PMd5KDKnpxPjeCfyJJhL5I/5ELNZ/ARYVvuKnEwoEAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAVdEVYdFRpdGxlAENvbG9yO1doZWVsO3JnYmOOBYgA + AAMoSURBVDhPXZFrU1NXFIbXT8nn/I7k1GqpVcCxKArdDbcY8BI0YOQESoLCOUA4CRdNRRMQMBXKzek4 + nU6nrXNkdDJVJB6r7Xhp7Ih1T2byA17XPhm/+OH9tOd51rvWpr5TI9RzZpzOdKcpFLlCLb1Z7Xh00Tys + L9sH+zfKNQM/lffHb9sHL66Z9SMr2uGxPB2xFujY5Bw1z1wnGjyZcCWRcNJz6uyU0dFztfLN+Xk09P2A + 2tg6WICv4puovbSKQ+atSkNyyWhMz3uap7MUyMwSDYdiFO+Ke1iSOxdOouvcDLgFGi/cRF1srSpIbKJu + +EfwdBxN3UDTdDbHsKd9NkOUDPaQEeozEl2DYAm6wxaCkQyaoguoj626ggOJDdQby2iYWETTVA4Mo2M2 + Y3RmLxPNtJ/W0h1nK2MnohjqHHAlfA+3Bd/BFfD+7nTe24WD167g5NxMpXthSqNsS9C82toJFsEKRsAr + KUmJV9F5DS8LvFxf5+olBYeylxG+MY3I4iSiNydNyn8r7KVAAPOBNlxrPeGKuI2uDsstiAWkLs+wzlNd + sC+fxsCtNOIraZs2xZHyhjiKNdGIFXEcLFQyL4vc31ECholBr4KGVlMYWU9hdCOF8c1UmX4RdWUOPomX + o94o87P1MV4OPkmZbFFj3xM12BJf4L7Yh4L4HI+Epj8VPnoT/ozkndP00hkn++GEfue+hfV7FlbuWsj/ + YWHpd8smBsw/xR4FYUf4wSD+afOVGNbl2CEvC7yyeElnSenRzgRYhF8LFpTs9pZl0mOhaUXhryjweYsP + L4M+MIz3g/shvz8GFkA+/A7vHAMsQbGYRGHbFVV+K1gaqarPAj6Dp+JVyO/C7/Qa8HTIOVEVPIiBW+Ct + Y7qSp0+S4DbGg+0Jor9bffSiw+d53enPKXg3ug/y4gHIqQbIxZaqYOsC5HYC750R/OeMKknurydJz04x + ScSV6XWXXx3Ms3t+r8HVK+50VT/fVhXYUXcNblHhVYw3zqhHHfYZh/6twvS2dy/93/8lyeFaTaa/NuX1 + Zlsut5dZUJZ3e21Z6Dfl4yFNOsO065hUckb5d8bpA63qZcxQqv/zAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAVdEVYdFRpdGxlAENvbG9yO1doZWVsO3JnYmOOBYgA + AAdXSURBVFhHxZfZV1NZGsXvX8ATL/w/WLRaRpA44QR1GUMClDKEQcJMABHJTRgURQkgc2Q0Xau7Kooz + isoUqsqiu7qkusrhPPLI7n3uTSg06a4e1rIf9lpwFuvu37f3d5KLAuD/qqiHn1JRD8OylVxWLKXXlMyy + PuWL8oGY0+eHTSmVY84jjlv+5KrpjcTqua0DNf4tU+3tjcT6WX9S47QzuWnSZG7xxRxpHY/6zI8V9TCs + guIuxWrvic0uvW5NL+8PnKkYwonKURx1+JBcNQUCgAAgAAiAQ43TIAAOX5gIHL04Zj1+aSQ22nN3K+ph + WOeKPAn5Jd0+i/0qmALSKgZx6vwIjjkmYNYBZnWAg3VzSGwggHMK5uZb4PQ41jaKlPYh30n3YEK0Z4cV + 9VCq7NzF1OJCV/BscQdsJVeQXdoLtbwfrAHHK8dxuGoSSbsAkhpmkEyAwy0+cHpwepzQbuK0ZyCY2ulN + jeYhFfWwpqAxtfLLls2yc20oKtTAKpBr79FTSK24yRrGogMY8RvTu4Zwyj0AmuOL7hubGT29USEiDppt + VQmN+bXB2oJGEAKlhCgscoNVICeUgqxB7kFS9cxvAOzfiJ/Ttw+D0eNMh24OmiP72tWg5XpPRB0f/OLK + LY1ts1b4WmwONObVoLagIQRxCdwH2OxX9BTkMso9OBQGqJ/T+5fxy+n16Dv6kfabOXKvX0Fe32VfQX/3 + B4v5AUCnpcjqtpSgPbcMrbbzaMqrRl0Iwl7Yji+LO8FrCV5J8DryJkzrAPIGyPjl8qVw+lOeAaR19e2Y + W29cQb63G2cHulA02Gnd7bnzw7WsvJie7IJAd85ZdFiKoOXawTTASlCfX69DlBBCViFTkDXIm6AD8AbI + +OX0MvrUkHlObw9sfZfBqVE42IWSm52wD3UEyoY7YiIAvJk5phuZuejNsoEgMECKmUYpLtgq0ZBfp0Nw + Kbe5kF4uo5mLGEeAOC6gmcvn5eJty6WT5haaM3J96mLDGOUjHTg/2oHKMY8pAmA4I8N5MyMTAxnZ8GZa + cD3LiqvZ+TqIhyAyDe7FNiEc3Af905F7oBBAYf8Kp1fYu4Pm27JvOXXRLuPKUQ+qxjyoGfegdsLjjACY + UFP94+lpGE1XMZKejqEQTB9TYT06CGvxshKFEAqrUFiDDsD4FUav0Fxh5F4ZtzSuoLEjZFrn86DhlhuN + k240Tbr9EQAz6smNafUUpqhJ9TR86hmMqwYQ09FhmIqZIArT0CFkChJATi/NObVCY7OcVprW01Q3nHKj + ZdqNVurijBtts+6NCIA/qse2KPip2+pxXXNqCmbVEyCcDkaoOAIphFEkiISQANKcxgpNFRrGSTNpdGnW + jfY5N1y33dAoN+Xx69qKAPhaNW9R+B3FUfJvd9TzJ+1jxVH4HUUCzKuJGxTuqQd13aceqCY8VA/gEfVY + /RwL6n7zorpXWVI/U75V45WfCxMU8dVZ5cf1S8rDly7lqwVNmX6kmX33NYze0zA8r2HorobBOxoGpAIa + +invN1pkBTTxP6KJNHqi7pdmeKruAw3xQv0DaIpVdY9XGm9kh8zbjugAYq1Jh1hadUkQb2BRA2Ew91gD + gTD5QIOEGg+BjcxrkUtIM+czmknD5zR8oSbopivUmroHNMarzPjtH3PjHdL8fd1BRVw9bQC8rFXerl+Q + EI61tfbtxWUXCIK7BPn6mQHjf6JhNgz0UIu8hpzS9DJkumxMiyBNpfH3GfHg1PibbQ9ovv3WccDL6c2i + X40jQJx4WmVmCt5f11u3CYFvg+1gGngaApl/7oJM5c9Pd2AiP4hoGrOi7gnIaXcb/5AVj79a4vFTnm6O + NxX7IZxJEJ0pEEOZIADE4/MQyw14v96Cv69fhIT4jhCra+14seLCwpIBco8gdxa1wDfPtMiPYikaW6Xx + d+l63PrUjBw/5YfMy/eB0YPTg/FDjGYbAA8rwBrAFMAq8HMI4nuKlehpyFqeGCDRv4ykaBz7KiPeJ6f+ + Sw7NrfF4HTL/tWwf3lWbIJqTITzHIW6kQUzkGAD3yyAWqyFWGiHWm/FmvRWbIYhX1DrTWFnV0/A9W3b9 + 869jKU6dwMiDsu/XBZ8Z5qX7wN4hGhKN6btPgv1D+CwGwL1ScA8glur1FN6xCu7DDsQPFPciyEr+9QtJ + WDRPpfmmbm7fi7eVnxvRt3B67ZgR/2A6xK1cA2CeAAuVRg2rRgqyil8I8Xq9TUJsEuLfeyULi+apv9j3 + BuXSvath9HLx5PRy+fh6py/gpNUAuGs3FvF5jb6MMgW5kG8IwaUMEuI/eykNi+YJ76oO+N7L6C+Yjekv + M/4+9j+SBTEVBiiBeMRFlHuwVGekEGyWVfi4D//da7kUe5cfOLGi6ZCV0wdEB5dPxi/7lzdg2mYA3CGA + vAlyD2QNKw0BpmBlFf/bPyaMXhGNSQqnV4TraIzoOmESvWec7N8vxrI3xIxtiwBbIlC8IR6U+8WCw8ka + TGK5PkasOqM+82NFPfyUinr46QTlH936vm4cNsTqAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACV0RVh0VGl0 + bGUAQ29weTtCYXJzO1JpYmJvbjtTdGFuZGFyZDtDbG9uZW0O31sAAAJjSURBVDhPhZL7S1NhGMet5ebc + UvsP+qf6JTOiQijKdJWYrDTTaXnBS3mJJEgjwlWWGNmEzamtwtWvUQTZZRe3nbP7zs4u357n3c5MEBp8 + OIO938/zfc+zKgB7MJvNuok5r+ve/Cfcnf9MeDExt4XxOS/GmEdbGCWGHrxz01n9foLqcQoUiyCKFQpM + oUSeGJ79CDprFCH6HCB0xCGDwWBadHyBoiiQoylBRC4hRTOIJVVkcwXcmfGwoFYT6GzTHtfAzHv0T38g + PLBNbaJvyoNeZnITt4j7T7zYkZNQ1AJskxssMGmC6r6pjf/W7hp1wxeKIpPNo3vMzQKzJtD3TLCgiGQ6 + J0ik84J4Mo9YKidqW4ec+BWQkVLysI44WXBYExhujKyJiYmUijgJOBQtI9O9uXbH7VX88EfEgM7B1b2C + jkGnEFSCSQomVEEkkRW123rf4vvvMOL0e/uAgwV1mqDmar9D3JUDEk2U6BmOqQjFsghFs6L2xe7X+La9 + Q3IVl20rLKjXBMbWnhXxoiLxrIBDOwIFQSJBtc9fX8LX7aAY0nrzDQsaNEHtha5l5PLF3ZCsIEAEJQV+ + gq/W3PkKP30hupIq2vzbwHTOukSCgggFpIyAg356+sIZMfVMxyLGZ9eoyTKa25+uk6DyPzCdvfYSKq2K + A/4IBSMUJP6E0wIpruKU5Tn0ev1Rrs5hQlcRnL7yQuyaV8hvOUbrlGkTEm1AoncSJkFTm50P13NGQxPU + NLY8dp20PEOTxS4ONl6y40TrQomWBRwnjjU/XOdh+wkOEkaijqgv01DmSBn+biJ0uwJU/QWlHMOEoK1R + 1QAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACV0RVh0VGl0 + bGUAQ29weTtCYXJzO1JpYmJvbjtTdGFuZGFyZDtDbG9uZW0O31sAAAdbSURBVFhHnZf7U1XXHcV5CZSq + iTFpkzQznf4J/Xf6S5ImTZq2TjQqGlvRBjGhmAjER5OMUQQxNUYIakqIYErAWE1JtNQhoLy5cF9c7vsJ + q2vtc871wuVmOj0zi30Hzt2f9f3u7/7uTRGAdbVx40ZHJW2d3/a1ffodOFLW2Go+axxCa8cQzl4aQgvH + lkv/Mmo+0/8Gv1um71PFx9tuFh1vvVF0jLLnNVoXLtkvFFOlghd6ksk0orEkgqEYPP4wpmYD+HZ4Dl8P + TeHt97+o5fc3UMbE8PeuosYP+/MNFHr0JapM0erJLC8jnVkxSmWWjeIJy8BSOA63P4KJmUX8tf2fWFkB + em88QF1z9yHOUU4ZE3852fc/GyguLy8vqaqqKldKVzhjMp2xlFqmMkjYisWTiEST8AeiNOBHU8uAMRCJ + pdEzMIaaI111hFVQpZSCKmig2FYJVcqnrKKiorL3xigymQziyZSBRSkzMvJILGEZ4OdFLsM4M9Dw3nVj + IJZcNia6r49gb93FwwRWUqtMrDVQ0nRmsK+p5QaaTg+i+bQ1NlLWOIDGDwdw9NQA3uH4zqmvjHq+GkE4 + moA/GMX9SR9qmz83BlLpFZqWiQyu9N7Djpr2PBO5BhR5qeCFHhWcIl0KxuD2hTDJaG/fnUHv4BiuXh+G + LxDG/Qkf/tRwxbwvEywT1oqMZNDV82/8ft9ZmXBqIs9AmaLVk2bBKQIpmeaaU7F4mpEy1cE45r2ETfnR + 8ME/DKjr2j10dt/Bgxkv6k/0oPpQB3ZJtR3Y+YZ0CR38exOzSHAVpSzkGdhwlKnV40CTKRpg0SVsab1D + kSS8/igeTHlx6Pg1YyDMte7oGcb5rtsYHXfj7sgcvhmexu0702ZL9t8ex+A3446BTQUNaE2zBmyoGbmW + cS5Bwl4G31IMY1M+7D/yWbbgZOLi1Ts413ETcwuLmPWEMDMfxNTcEs36MTHtR+OpfhnYTKlJ5RkoP/KB + ZUBAwVVEDlyKSdz7ftbB2IQXu+o6VxVcmAX3URe748VB9oUgvEsReAIRLlkE3sUIi/ZLGXhkPQPaehUN + 73NN+UtNFk9ZUAMm1FEkkUIgFMcoC25bzcfG8NqCa++4hTN/6zeF6ePu8DJjalZH3jMGHi1koLKeL1gp + VbRccwPl/jdgKp6i0jSQwIQrwIq/jJf2nMOLu9vw4q42vLBTasWFy0OoOdqNeU/AZMtPw2pW7IQysKWg + gTdP2k0kJ1oBHbDGECcKUu5F7vvpRXw34sKtu1Mstkn03xpH39dj6L95n/Xxd8wueFkvUQTCCTawFOpP + XpOBxwoZ+NHhE32WAQNMIZyrGOFUmEWoUVnwBtgTuCNcnjCmVWw09P24l0Xnw776q5h2efhOhF0yYZbm + zWNfyMBWSodUnoGqQ+/20sDKOmALKgUlbsUlRqVR0QmgdV7ggTTnDrFRhbG3/jImZ93wsPj8xkAade/2 + yMDjtoHiXAOl1I9rm69hmQYMjPAsNGJDqWDYGpc0UgFHhHhoYp4ZWeS6V9dd5tmwwAypEHlmcElrm7pl + 4IlCBjb+ufFz2wBBghloygLa0IdAnoAc/RoJEERyc1lCkQS7YCeXZJ5ZsQxEaeBg4w8b2HSQlbu8vJKN + 2ESbC5UYqeAalVoH7GOL9i5Z0rLtrL2E0UkXMxKCl3+LsogPcH6Cf0LpPMgzsLnm7c+4n2kgCxbMBtqf + c6OVvI5suCcQZ7oz2HHwExbkLObYEZWVCE2pcxL80/UMlFGPqHJlwIlUEToSzILHLbBgOVBHbkrpfvXA + RYzcn2FLDmKBWzYSTeGPDVdl4MmCBva+dYVXruVV4NyIrUhVbJSANtzNUWC3XzuBTYfp3rb/Au6NTRsD + KswwDezjziD4qUIGHt1z+FNz1/PZEVuyo+RnAxbMkekDkmVgwTHAg+l3+y7gP6PTmHHTgC9iGtjrb2UN + 6IqWZ2DLblauDFjrSrADt8HZNBOyQLiRDXVxdLEPaAwx2lde/wgPJmfNebDEXRHk7xQgwesuwQbqMV0e + UjyKlWZnjbMRC2yATqSWXD6BY5hjlHPeGGZ58qlVv1zdjmOnunkx+YQ9oRPVhzuxveZ8P8HOWZBnYKsq + V3eBbHqVVgN+mF5XNlpBbbBGggWX1DN+s/sceLP+JW/WvyDsGUqpF1z3wrwrmQw8/uqBj809wIrWgmcj + dUSgorYifgh1NOOJmF2kU7GkpOTnNLGJJgTVuity8z9CrgFzG5KBbftpgIeGWeNVUCdaplhaA1wld9ic + Db9+rVWTP00Tlfofw4au+3+BY2DrH1i5OrXUSNS7tZ/VwbStnIPJORVVaM75kG1a9sEkPbe9RZM/SZWL + IdZa5RownfCF105/+du95/Ey9VI1taeda9nOzxp58eClI/fioSif3yGdxfMEPrejBc9yfHb7afzqlRP9 + nHMLpR32gwb0mCsZtZl6gpLzp9bo6TX62Ro9Y0uf9b7glZTmzoMbtvlhPcqCXpRbpSxXMvb/SHNpTs2d + BwdQ9F/AOGC3chKJ6AAAAABJRU5ErkJggg== + + + + 17, 17 + + + 280, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_alimama.Designer.cs b/FLSystem/Forms/cps_order_alimama.Designer.cs new file mode 100644 index 0000000..3bbd2d3 --- /dev/null +++ b/FLSystem/Forms/cps_order_alimama.Designer.cs @@ -0,0 +1,1017 @@ +namespace FLSystem.Forms +{ + partial class cps_order_alimama + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_order_alimama)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.checkBox_isOld = new System.Windows.Forms.CheckBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.解绑ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.维权订单查看ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.所有阿里妈妈订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有多多进宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有京东联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有抖音联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有苏宁易购订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.订单状态操作ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.冻结延期ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.立即结算ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.立即失效ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.一键结算ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键失效ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键延期ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.重新计算未结算订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn30 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn31 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn32 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn28 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn29 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn33 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.所有快手联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.checkBox_isOld); + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(956, 85); + this.groupControl1.TabIndex = 0; + this.groupControl1.Text = "搜索条件"; + this.groupControl1.Paint += new System.Windows.Forms.PaintEventHandler(this.groupControl1_Paint); + // + // checkBox_isOld + // + this.checkBox_isOld.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox_isOld.AutoSize = true; + this.checkBox_isOld.Checked = true; + this.checkBox_isOld.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_isOld.Location = new System.Drawing.Point(808, 33); + this.checkBox_isOld.Name = "checkBox_isOld"; + this.checkBox_isOld.Size = new System.Drawing.Size(134, 32); + this.checkBox_isOld.TabIndex = 10; + this.checkBox_isOld.Text = "搜索一年以内的数据\r\n查询速度慢的请勾选"; + this.checkBox_isOld.UseVisualStyleBackColor = true; + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(449, 40); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(54, 18); + this.checkBox1.TabIndex = 9; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(503, 52); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(161, 22); + this.dateTimePicker2.TabIndex = 8; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(503, 25); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(161, 22); + this.dateTimePicker1.TabIndex = 3; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "不限状态"; + this.comboBoxEdit2.Location = new System.Drawing.Point(329, 28); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "不限状态", + "订单创建", + "订单付款", + "订单失效", + "订单冻结", + "订单结算", + "订单维权中", + "全额退款", + "部分退款", + "订单退款"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(108, 20); + this.comboBoxEdit2.TabIndex = 7; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(33, 41); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(36, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(684, 30); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(97, 39); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜 索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = "全部平台"; + this.comboBoxEdit3.Location = new System.Drawing.Point(329, 54); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { + "全部平台"}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(108, 20); + this.comboBoxEdit3.TabIndex = 2; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(231, 38); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "订单编号", + "商品编号", + "商品标题", + "客户编号", + "客户账号", + "客户昵称", + "店铺编码", + "PID最后1段", + "联盟账号", + "联盟昵称", + "未绑定用户"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(92, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.Tag = "comboboxedit"; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(75, 38); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(147, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Tag = "textedit"; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(3, 91); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(949, 437); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改toolStripMenuItem1, + this.解绑ToolStripMenuItem, + this.维权订单查看ToolStripMenuItem, + this.查看用户信息ToolStripMenuItem, + this.订单状态操作ToolStripMenuItem, + this.刷新ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.重新计算未结算订单ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 202); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 修改toolStripMenuItem1 + // + this.修改toolStripMenuItem1.Name = "修改toolStripMenuItem1"; + this.修改toolStripMenuItem1.Size = new System.Drawing.Size(184, 22); + this.修改toolStripMenuItem1.Text = "绑定"; + this.修改toolStripMenuItem1.Click += new System.EventHandler(this.修改toolStripMenuItem1_Click); + // + // 解绑ToolStripMenuItem + // + this.解绑ToolStripMenuItem.Name = "解绑ToolStripMenuItem"; + this.解绑ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.解绑ToolStripMenuItem.Text = "解绑"; + this.解绑ToolStripMenuItem.Click += new System.EventHandler(this.解绑ToolStripMenuItem_Click); + // + // 维权订单查看ToolStripMenuItem + // + this.维权订单查看ToolStripMenuItem.Name = "维权订单查看ToolStripMenuItem"; + this.维权订单查看ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.维权订单查看ToolStripMenuItem.Text = "查看维权明细"; + this.维权订单查看ToolStripMenuItem.Click += new System.EventHandler(this.维权订单查看ToolStripMenuItem_Click); + // + // 查看用户信息ToolStripMenuItem + // + this.查看用户信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看用户信息ToolStripMenuItem1, + this.toolStripSeparator1, + this.所有阿里妈妈订单ToolStripMenuItem, + this.所有多多进宝订单ToolStripMenuItem, + this.所有京东联盟订单ToolStripMenuItem, + this.所有唯品联盟订单ToolStripMenuItem, + this.所有抖音联盟订单ToolStripMenuItem, + this.所有苏宁易购订单ToolStripMenuItem, + this.所有快手联盟订单ToolStripMenuItem, + this.toolStripSeparator2, + this.积分日志ToolStripMenuItem, + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.查看用户信息ToolStripMenuItem.Name = "查看用户信息ToolStripMenuItem"; + this.查看用户信息ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.查看用户信息ToolStripMenuItem.Text = "用户个人信息"; + // + // 查看用户信息ToolStripMenuItem1 + // + this.查看用户信息ToolStripMenuItem1.Name = "查看用户信息ToolStripMenuItem1"; + this.查看用户信息ToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + this.查看用户信息ToolStripMenuItem1.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem1.Click += new System.EventHandler(this.查看用户信息ToolStripMenuItem1_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6); + // + // 所有阿里妈妈订单ToolStripMenuItem + // + this.所有阿里妈妈订单ToolStripMenuItem.Name = "所有阿里妈妈订单ToolStripMenuItem"; + this.所有阿里妈妈订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有阿里妈妈订单ToolStripMenuItem.Text = "所有阿里妈妈订单"; + this.所有阿里妈妈订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有多多进宝订单ToolStripMenuItem + // + this.所有多多进宝订单ToolStripMenuItem.Name = "所有多多进宝订单ToolStripMenuItem"; + this.所有多多进宝订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有多多进宝订单ToolStripMenuItem.Text = "所有多多进宝订单"; + this.所有多多进宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有京东联盟订单ToolStripMenuItem + // + this.所有京东联盟订单ToolStripMenuItem.Name = "所有京东联盟订单ToolStripMenuItem"; + this.所有京东联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有京东联盟订单ToolStripMenuItem.Text = "所有京东联盟订单"; + this.所有京东联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有唯品联盟订单ToolStripMenuItem + // + this.所有唯品联盟订单ToolStripMenuItem.Name = "所有唯品联盟订单ToolStripMenuItem"; + this.所有唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有唯品联盟订单ToolStripMenuItem.Text = "所有唯品联盟订单"; + this.所有唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有抖音联盟订单ToolStripMenuItem + // + this.所有抖音联盟订单ToolStripMenuItem.Name = "所有抖音联盟订单ToolStripMenuItem"; + this.所有抖音联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有抖音联盟订单ToolStripMenuItem.Text = "所有抖音联盟订单"; + this.所有抖音联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有苏宁易购订单ToolStripMenuItem + // + this.所有苏宁易购订单ToolStripMenuItem.Name = "所有苏宁易购订单ToolStripMenuItem"; + this.所有苏宁易购订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有苏宁易购订单ToolStripMenuItem.Text = "所有苏宁易购订单"; + this.所有苏宁易购订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6); + // + // 积分日志ToolStripMenuItem + // + this.积分日志ToolStripMenuItem.Name = "积分日志ToolStripMenuItem"; + this.积分日志ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.积分日志ToolStripMenuItem.Text = "积分日志"; + this.积分日志ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 订单状态操作ToolStripMenuItem + // + this.订单状态操作ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.冻结延期ToolStripMenuItem, + this.立即结算ToolStripMenuItem1, + this.立即失效ToolStripMenuItem1, + this.一键结算ToolStripMenuItem, + this.一键失效ToolStripMenuItem, + this.一键延期ToolStripMenuItem}); + this.订单状态操作ToolStripMenuItem.Name = "订单状态操作ToolStripMenuItem"; + this.订单状态操作ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.订单状态操作ToolStripMenuItem.Text = "订单状态操作"; + // + // 冻结延期ToolStripMenuItem + // + this.冻结延期ToolStripMenuItem.Name = "冻结延期ToolStripMenuItem"; + this.冻结延期ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.冻结延期ToolStripMenuItem.Text = "冻结延期"; + this.冻结延期ToolStripMenuItem.Click += new System.EventHandler(this.冻结延期ToolStripMenuItem_Click); + // + // 立即结算ToolStripMenuItem1 + // + this.立即结算ToolStripMenuItem1.Name = "立即结算ToolStripMenuItem1"; + this.立即结算ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即结算ToolStripMenuItem1.Text = "立即结算"; + this.立即结算ToolStripMenuItem1.Click += new System.EventHandler(this.立即结算ToolStripMenuItem_Click); + // + // 立即失效ToolStripMenuItem1 + // + this.立即失效ToolStripMenuItem1.Name = "立即失效ToolStripMenuItem1"; + this.立即失效ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即失效ToolStripMenuItem1.Text = "立即失效"; + this.立即失效ToolStripMenuItem1.Click += new System.EventHandler(this.立即失效ToolStripMenuItem_Click); + // + // 一键结算ToolStripMenuItem + // + this.一键结算ToolStripMenuItem.Name = "一键结算ToolStripMenuItem"; + this.一键结算ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.一键结算ToolStripMenuItem.Text = "一键结算"; + this.一键结算ToolStripMenuItem.Click += new System.EventHandler(this.一键结算ToolStripMenuItem_Click); + // + // 一键失效ToolStripMenuItem + // + this.一键失效ToolStripMenuItem.Name = "一键失效ToolStripMenuItem"; + this.一键失效ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.一键失效ToolStripMenuItem.Text = "一键失效"; + this.一键失效ToolStripMenuItem.Click += new System.EventHandler(this.一键失效ToolStripMenuItem_Click); + // + // 一键延期ToolStripMenuItem + // + this.一键延期ToolStripMenuItem.Name = "一键延期ToolStripMenuItem"; + this.一键延期ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.一键延期ToolStripMenuItem.Text = "一键延期"; + this.一键延期ToolStripMenuItem.Click += new System.EventHandler(this.一键延期ToolStripMenuItem_Click); + // + // 刷新ToolStripMenuItem + // + this.刷新ToolStripMenuItem.Name = "刷新ToolStripMenuItem"; + this.刷新ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.刷新ToolStripMenuItem.Text = "刷新"; + this.刷新ToolStripMenuItem.Click += new System.EventHandler(this.刷新ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // 重新计算未结算订单ToolStripMenuItem + // + this.重新计算未结算订单ToolStripMenuItem.Name = "重新计算未结算订单ToolStripMenuItem"; + this.重新计算未结算订单ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.重新计算未结算订单ToolStripMenuItem.Text = "重新计算未结算订单"; + this.重新计算未结算订单ToolStripMenuItem.Visible = false; + this.重新计算未结算订单ToolStripMenuItem.Click += new System.EventHandler(this.重新计算未结算订单ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn9, + this.gridColumn30, + this.gridColumn22, + this.gridColumn14, + this.gridColumn7, + this.gridColumn31, + this.gridColumn8, + this.gridColumn21, + this.gridColumn20, + this.gridColumn25, + this.gridColumn19, + this.gridColumn24, + this.gridColumn6, + this.gridColumn5, + this.gridColumn1, + this.gridColumn3, + this.gridColumn10, + this.gridColumn11, + this.gridColumn18, + this.gridColumn12, + this.gridColumn32, + this.gridColumn26, + this.gridColumn2, + this.gridColumn16, + this.gridColumn13, + this.gridColumn17, + this.gridColumn28, + this.gridColumn29, + this.gridColumn23, + this.gridColumn27, + this.gridColumn33}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn15 + // + this.gridColumn15.Caption = "创建时间"; + this.gridColumn15.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn15.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn15.FieldName = "create_time"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 150; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "trade_parent_id"; + this.gridColumn4.MaxWidth = 180; + this.gridColumn4.MinWidth = 150; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 159; + // + // gridColumn9 + // + this.gridColumn9.Caption = "付款金额"; + this.gridColumn9.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn9.FieldName = "alipay_total_price"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 2; + // + // gridColumn30 + // + this.gridColumn30.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn30.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn30.AppearanceCell.TextOptions.VAlignment = DevExpress.Utils.VertAlignment.Center; + this.gridColumn30.Caption = "结算金额"; + this.gridColumn30.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn30.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn30.FieldName = "pay_price"; + this.gridColumn30.Name = "gridColumn30"; + this.gridColumn30.Visible = true; + this.gridColumn30.VisibleIndex = 3; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "维权金额"; + this.gridColumn22.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn22.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn22.FieldName = "refundFee"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.OptionsColumn.AllowEdit = false; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 5; + this.gridColumn22.Width = 69; + // + // gridColumn14 + // + this.gridColumn14.Caption = "状态"; + this.gridColumn14.FieldName = "db_status"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 4; + // + // gridColumn7 + // + this.gridColumn7.Caption = "预估佣金"; + this.gridColumn7.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn7.FieldName = "pub_share_pre_fee"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 6; + // + // gridColumn31 + // + this.gridColumn31.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn31.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn31.AppearanceCell.TextOptions.VAlignment = DevExpress.Utils.VertAlignment.Center; + this.gridColumn31.Caption = "实际佣金"; + this.gridColumn31.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn31.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn31.FieldName = "commission"; + this.gridColumn31.Name = "gridColumn31"; + this.gridColumn31.Visible = true; + this.gridColumn31.VisibleIndex = 7; + // + // gridColumn8 + // + this.gridColumn8.Caption = "客户所得"; + this.gridColumn8.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn8.FieldName = "endpoint"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 8; + // + // gridColumn21 + // + this.gridColumn21.Caption = "一级提成"; + this.gridColumn21.FieldName = "db_point"; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 9; + // + // gridColumn20 + // + this.gridColumn20.Caption = "二级提成"; + this.gridColumn20.FieldName = "db_point"; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 10; + // + // gridColumn25 + // + this.gridColumn25.Caption = "三级提成"; + this.gridColumn25.FieldName = "db_point"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.OptionsColumn.AllowEdit = false; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 11; + // + // gridColumn19 + // + this.gridColumn19.Caption = "群负责人提成"; + this.gridColumn19.FieldName = "db_point"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 12; + // + // gridColumn24 + // + this.gridColumn24.Caption = "客户维权后佣金"; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 13; + this.gridColumn6.Width = 100; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户名"; + this.gridColumn5.FieldName = "username"; + this.gridColumn5.MinWidth = 120; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 14; + this.gridColumn5.Width = 120; + // + // gridColumn1 + // + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "item_title"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 15; + this.gridColumn1.Width = 350; + // + // gridColumn3 + // + this.gridColumn3.Caption = "商品编号"; + this.gridColumn3.FieldName = "num_iid"; + this.gridColumn3.MinWidth = 120; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 16; + this.gridColumn3.Width = 120; + // + // gridColumn10 + // + this.gridColumn10.Caption = "商品单价"; + this.gridColumn10.FieldName = "price"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 17; + // + // gridColumn11 + // + this.gridColumn11.Caption = "购买数量"; + this.gridColumn11.FieldName = "item_num"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 18; + // + // gridColumn18 + // + this.gridColumn18.Caption = "冻结时间"; + this.gridColumn18.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn18.FieldName = "db_endtime"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 19; + // + // gridColumn12 + // + this.gridColumn12.Caption = "宝贝类型"; + this.gridColumn12.FieldName = "order_type"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 20; + // + // gridColumn32 + // + this.gridColumn32.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn32.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn32.Caption = "机器人昵称"; + this.gridColumn32.FieldName = "robotnick"; + this.gridColumn32.Name = "gridColumn32"; + this.gridColumn32.OptionsColumn.AllowEdit = false; + this.gridColumn32.Visible = true; + this.gridColumn32.VisibleIndex = 21; + // + // gridColumn26 + // + this.gridColumn26.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn26.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn26.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn26.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn26.Caption = "机器人账号"; + this.gridColumn26.FieldName = "robotname"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 22; + // + // gridColumn2 + // + this.gridColumn2.Caption = "联盟账号"; + this.gridColumn2.FieldName = "db_cpsname"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 23; + this.gridColumn2.Width = 100; + // + // gridColumn16 + // + this.gridColumn16.Caption = "联盟昵称"; + this.gridColumn16.FieldName = "db_cpsnick"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 24; + this.gridColumn16.Width = 100; + // + // gridColumn13 + // + this.gridColumn13.Caption = "推广位"; + this.gridColumn13.FieldName = "adzone_id"; + this.gridColumn13.MinWidth = 120; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 25; + this.gridColumn13.Width = 120; + // + // gridColumn17 + // + this.gridColumn17.Caption = "子订单号"; + this.gridColumn17.FieldName = "trade_id"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 26; + this.gridColumn17.Width = 180; + // + // gridColumn28 + // + this.gridColumn28.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn28.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn28.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn28.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn28.Caption = "预付款金额"; + this.gridColumn28.FieldName = "deposit_price"; + this.gridColumn28.Name = "gridColumn28"; + this.gridColumn28.Visible = true; + this.gridColumn28.VisibleIndex = 27; + // + // gridColumn29 + // + this.gridColumn29.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn29.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn29.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.Caption = "预付款时间"; + this.gridColumn29.FieldName = "tb_deposit_time"; + this.gridColumn29.Name = "gridColumn29"; + this.gridColumn29.Visible = true; + this.gridColumn29.VisibleIndex = 28; + // + // gridColumn23 + // + this.gridColumn23.Caption = "退款金额"; + this.gridColumn23.FieldName = "showReturnFee"; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.OptionsColumn.AllowEdit = false; + // + // gridColumn27 + // + this.gridColumn27.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn27.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn27.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.Caption = "店铺编码"; + this.gridColumn27.FieldName = "seller_id"; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 29; + // + // gridColumn33 + // + this.gridColumn33.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn33.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn33.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.Caption = "订单类型"; + this.gridColumn33.DisplayFormat.FormatString = "{0}"; + this.gridColumn33.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn33.FieldName = "ssss"; + this.gridColumn33.Name = "gridColumn33"; + this.gridColumn33.OptionsColumn.AllowEdit = false; + this.gridColumn33.OptionsColumn.AllowFocus = false; + this.gridColumn33.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn33.Visible = true; + this.gridColumn33.VisibleIndex = 30; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 534); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(956, 33); + this.pageControl1.TabIndex = 2; + // + // 所有快手联盟订单ToolStripMenuItem + // + this.所有快手联盟订单ToolStripMenuItem.Name = "所有快手联盟订单ToolStripMenuItem"; + this.所有快手联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有快手联盟订单ToolStripMenuItem.Text = "所有快手联盟订单"; + this.所有快手联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // cps_order_alimama + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.groupControl1); + this.Name = "cps_order_alimama"; + this.Size = new System.Drawing.Size(956, 567); + this.Load += new System.EventHandler(this.cps_order_alimama_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 刷新ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private System.Windows.Forms.ToolStripMenuItem 修改toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 解绑ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 所有阿里妈妈订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有多多进宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有京东联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 订单状态操作ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 立即结算ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 立即失效ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 冻结延期ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn28; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn29; + private System.Windows.Forms.ToolStripMenuItem 维权订单查看ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn30; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn31; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn32; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn33; + private System.Windows.Forms.ToolStripMenuItem 所有唯品联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有抖音联盟订单ToolStripMenuItem; + private System.Windows.Forms.CheckBox checkBox_isOld; + private System.Windows.Forms.ToolStripMenuItem 所有苏宁易购订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 一键结算ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 一键失效ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 一键延期ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 重新计算未结算订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有快手联盟订单ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/cps_order_alimama.cs b/FLSystem/Forms/cps_order_alimama.cs new file mode 100644 index 0000000..1d8e725 --- /dev/null +++ b/FLSystem/Forms/cps_order_alimama.cs @@ -0,0 +1,1309 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using FLSystem.Events; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using UI.Framework.Forms; +using static Api.Framework.Cps.AlimamaApi; + +namespace FLSystem.Forms +{ + public partial class cps_order_alimama : DevExpress.XtraEditors.XtraUserControl + { + public class view_cps_order_alimama + { + /// + /// id + /// + public long id { get; set; } + /// + /// 商品标题 + /// + public string item_title { get; set; } + /// + /// 购买数量 + /// + public string num_iid { get; set; } + /// + /// 实际付款 + /// + public double pay_price { get; set; } + /// + /// 实际总共佣金 + /// + public double commission { get; set; } + /// + /// 订单父id + /// + public string trade_parent_id { get; set; } + /// + /// 订单子id + /// + public string trade_id { get; set; } + /// + /// 订单状态 + /// + public SystemOrderStatus db_status { get; set; } + + + private string _robotname; + /// + /// 机器人微信号 + /// + public string robotname + { + get { return _robotname; } + set { if (string.IsNullOrEmpty(value)) _robotname = string.Empty; else _robotname = value; } + } + + /// + /// 机器人昵称 + /// + public string robotnick { get; set; } + + private string _username; + /// + /// 用户账号 + /// + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + /// + /// 用户昵称 + /// + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + + public long db_userid { get; set; } + + /// + /// 订单类型 + /// + public string order_type { get; set; } + /// + /// 总佣金 + /// + public double pub_share_pre_fee { get; set; } + /// + /// 付款金额 + /// + public double alipay_total_price { get; set; } + /// + /// 商品单价 + /// + public double price { get; set; } + /// + /// 购买数量 + /// + public int item_num { get; set; } + /// + /// 推广位 + /// + public string adzone_id { get; set; } + /// + /// 创建时间 + /// + public DateTime create_time { get; set; } + + public string db_point { get; set; } + /// + /// 联盟账号 + /// + public string db_cpsname { get; set; } + /// + /// 联盟昵称 + /// + public string db_cpsnick { get; set; } + /// + /// 冻结时间 + /// + public DateTime db_endtime { get; set; } + /// + /// 显示返回的费用 + /// + public double showReturnFee { get; set; } + /// + /// 退款手续费 + /// + public double refundFee { get; set; } + /// + /// 卖方编码 + /// + public string seller_id { get; set; } + + /// + /// 预付款金额 + /// + public string deposit_price { get; set; } + + /// + /// 预售时期,用户对预售商品支付定金的付款时间 + /// + public string tb_deposit_time { get; set; } + /// + /// 联盟技术费用比率 + /// + public double alimama_rate { get; set; } + /// + /// 联盟技术费用 + /// + public double alimama_share_fee { get; set; } + /// + /// + /// + public string auction_category { get; set; } + } + + public cps_order_alimama(string textedit = "") + { + try + { + InitializeComponent(); + var session = ApiClient.GetSession(); + this.textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 5; + this.dateTimePicker1.Value = DateTime.Parse(DateTime.Today.AddDays(-30).ToString("yyyy-MM-01")); + this.dateTimePicker2.Value = DateTime.Parse(DateTime.Now.AddDays(30).ToString("yyyy-MM-dd HH:mm:ss")); + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + this.checkBox1.Checked = false; + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + #endregion + + this.pageControl1.Bind(SerchData, this.gridControl1, 50, false, true); + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + private UI.Framework.Controls.PageControl.SerchResult SerchData(int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + + var isOld = true; + + List result = null; + + var sqlwhere = string.Empty; + + if (this.checkBox1.Checked) + { + isOld = false; + + sqlwhere += $" and '{this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss")}' <= create_time and create_time <= '{this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss")}'"; + } + + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword) || comboBoxEdit1.Text == "未绑定用户") + { + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + if (keyword.Length == 6) + sqlwhere += $" and trade_parent_id like '%{keyword}'"; + else + sqlwhere += $" and trade_parent_id = '{keyword}'"; + break; + case "商品编号": + sqlwhere += $" and num_iid = '{keyword}'"; + break; + case "商品标题": + sqlwhere += $" and item_title like '%{keyword}%'"; + break; + case "客户编号": + sqlwhere += $" and db_userid = '{keyword}'"; + break; + case "客户账号": + var ids = FindMemberIdByKey("username", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "客户昵称": + ids = FindMemberIdByKey("usernick", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "店铺编码": + sqlwhere += $" and seller_id = '{keyword}'"; + break; + case "PID最后1段": + sqlwhere += $" and adzone_id = '{keyword}'"; + break; + case "联盟账号": + sqlwhere += $" and db_cpsname = '{keyword}'"; + break; + case "联盟昵称": + sqlwhere += $" and db_cpsnick = '{keyword}'"; + break; + case "未绑定用户": + sqlwhere += $" and db_userid = '0'"; + break; + } + } + + var status = this.comboBoxEdit2.SelectedIndex == 0 ? SystemOrderStatus.订单未知 : Util.ConvertEnum(this.comboBoxEdit2.Text); + if (status != SystemOrderStatus.订单未知) + sqlwhere += $" and db_status = '{((int)status).ToString()}'"; + + if (this.comboBoxEdit3.SelectedIndex != 0) + sqlwhere += $" and db_robotname = '{comboBoxEdit3.Text.Trim()}'"; + + //总记录数 + int totalNumber = 0; + + if (isOld && checkBox_isOld.Checked) + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= create_time"; + + sqlwhere += $" order by id desc"; + + var getCount = session.Find("select count(*) from fl_order_alimama where 1=1 " + sqlwhere); + if (getCount != null && getCount.Count != 0) + totalNumber = getCount[0]; + + sqlwhere += $" limit {(index - 1) * pagesize},{pagesize}"; + + var resultTmp = session.Find("select * from fl_order_alimama where 1=1 " + sqlwhere); + + result = new List(); + foreach (var o in resultTmp) + { + result.Add(new view_cps_order_alimama() + { + id = o.id, + adzone_id = o.adzone_id, + alipay_total_price = o.alipay_total_price, + create_time = o.create_time, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + item_num = o.item_num, + item_title = o.item_title, + num_iid = o.num_iid, + order_type = o.order_type, + price = o.price, + pub_share_pre_fee = o.pub_share_pre_fee, + robotname = o.db_robotname, + trade_id = o.trade_id, + trade_parent_id = o.trade_parent_id, + db_userid = o.db_userid, + seller_id = o.seller_id, + deposit_price = o.deposit_price, + tb_deposit_time = o.tb_deposit_time, + pay_price = o.pay_price, + commission = o.commission, + alimama_rate = o.alimama_rate, + alimama_share_fee = o.alimama_share_fee, + auction_category = o.auction_category, + //refundFee = ra.refundfee, + //showReturnFee = ra.showreturnfee,D:\代码同步\fl_system\类库\Grant.Framework\LoginCard.cs + //username = u.username, + //usernick = u.usernick + }); + } + + if (result.Count != 0) + { + #region 附加用户 + var bindUsersList = result.Where(f => f.db_userid != 0).GroupBy(f => f.db_userid).Select(f => f.Key).ToList(); + var memberData = new List(); + if (bindUsersList != null && bindUsersList.Count != 0) + { + memberData = session.Queryable().Where(new List() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + } + + foreach (var member in memberData) + { + var items = result.Where(f => f.db_userid == member.id).ToList(); + foreach (var item in items) + { + item.usernick = member.usernick; + item.username = member.username; + } + } + #endregion + + #region 附加机器人信息 + var robotList = result.Where(f => !string.IsNullOrWhiteSpace(f.robotname)).GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + var robotData = session.FindRobots().Where(f => robotList.Contains(f.name)).ToList(); + foreach (var robot in robotData) + { + var items = result.Where(f => f.robotname == robot.name).ToList(); + foreach (var item in items) + { + item.robotnick = robot.nick; + } + } + #endregion + + var refundData = result.Where(f => (int)f.db_status == 1003 || (int)f.db_status == 1000 || (int)f.db_status == 999 || (int)f.db_status == 998).ToList(); + + List wherelist = new List(); + foreach (var item in refundData) + { + wherelist.Add($"(tbtradeparentid = {item.trade_parent_id} and tbtradeid = {item.trade_id})"); + } + var _where = string.Join(" or ", wherelist); + _where = string.IsNullOrWhiteSpace(_where) ? string.Empty : $"and { _where}"; + var refundResult = session.Find($"select * from fl_order_refund_alimama where 1 = 1 { _where}"); + foreach (var item in refundResult) + { + var order = result.FirstOrDefault(f => f.trade_parent_id == item.tbtradeparentid && f.trade_id == item.tbtradeid); + if (order != null) + { + if (order.auction_category != "手动处理") + { + order.refundFee = item.refundfee; + order.showReturnFee = item.showreturnfee; + } + } + } + } + //EventClient.OnEvent(this, sb_time.ToString()); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + if (!this.IsDisposed) + this.UpdateUI(() => + { + BaseForm.ShowError(ex); + }); + } + return null; + } + + /// + /// 代理委托更新UI + /// + /// + protected delegate void DelegateUpdateUI(Action act); + + /// + /// 代理委托更新UI + /// + /// + protected void UpdateUI(Action act) + { + try + { + if (!InvokeRequired) + { + act.Invoke(); + } + else + { + DelegateUpdateUI delegateUpdateUI = new DelegateUpdateUI(UpdateUI); + Invoke(delegateUpdateUI, act); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + /// + /// 条件查询(用户账号/用户昵称),模糊查询,获取用户的id + /// + /// 查询的字段 + /// 模糊的关键词 + /// + private List FindMemberIdByKey(string type, string keyword) + { + try + { + var session = ApiClient.GetSession(); + return session.Find($"select id from fl_member_info where {type} like '%{keyword}%'").Select(f => f.ToString()).ToList(); + } + catch (Exception ex) + { + return new List(); + } + } + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("cps_type") && e.Commons.ContainsKey("username")) + { + var cps_type = (CpsType)int.Parse(e.Commons["cps_type"].ToString()); + if (cps_type == CpsType.阿里妈妈) + { + textEdit1.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 5; + comboBoxEdit3.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + checkBox1.Checked = false; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "软件状态": + e.DisplayText = Util.ConvertEnum(int.Parse(e.Value.ToString())).ToString(); + break; + case "一级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardone"].ToString(); + break; + case "二级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardtwo"].ToString(); + break; + case "三级提成": + { + var result = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower()); + e.DisplayText = (result != null && result.ContainsKey("awardthree")) ? result["awardthree"].ToString() : "0"; + } + break; + case "群负责人提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardcreate"].ToString(); + break; + } + } + + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + var row = e.Row as view_cps_order_alimama; + if (e.Column.Caption == "客户所得") + { + //var ss = Newtonsoft.Json.JsonConvert.DeserializeObject(row.db_point); + var point = HttpHelper.JsonToObject(row.db_point) as ItemPoint; + e.Value = point.UserPoint; + } + else if (e.Column.Caption == "订单类型") + { + if (row.create_time > DateTime.Parse("2020-08-04 00:00:00")) + e.Value = row.alimama_rate != 0 ? "正常订单" : "比价订单"; + else + e.Value = "历史订单"; + } + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var info = this.gridView1.GetRow(rows[0]) as view_cps_order_alimama; + if (XtraMessageBox.Show("您确定要删除选中数据嘛?\r\n" + info.item_title, "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_order_alimama where id=" + info.id); + } + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.textEdit1.Enabled = (comboBoxEdit1.SelectedIndex != 0 && comboBoxEdit1.SelectedIndex != 11); + if (!textEdit1.Enabled) + this.textEdit1.Text = string.Empty; + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + this.dateTimePicker1.Enabled = this.dateTimePicker2.Enabled = this.checkBox1.Checked; + } + + /// + /// 订单绑定用户 + /// + /// + /// + private void 修改toolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_alimama; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.订单退款 || db_status == SystemOrderStatus.订单创建) + { + throw new Exception("该订单状态,不允许修改!"); + } + + var session = ApiClient.GetSession(); + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null) + { + if (member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + } + + select_member_form select_form = new select_member_form(); + select_form.ShowDialog(); + if (select_form.fl_member_info != null) + { + var alimama = session.FindSingle("id = @id", new { id = row.id }); + if (alimama != null) + { + if (alimama.db_robottype == 0) alimama.db_robottype = select_form.fl_member_info.robot_type; + if (string.IsNullOrWhiteSpace(alimama.db_robotname)) alimama.db_robotname = select_form.fl_member_info.robot_name; + + #region 判断是否为淘礼金订单,如果是淘礼金订单将不给这个订单返利 + var isTljOrder = session.CheckIsTljOrder(row.adzone_id); + #endregion + + //计算的佣金 - 判断使用设置模式,符合将扣除用户自定义预扣佣金 + var commission = session.GetTbComparisonFeeRate(alimama); + + //var itempoint = session.FindItemPoint(select_form.fl_member_info, isTljOrder ? 0 : alimama.pub_share_pre_fee, alimama.item_num, CpsType.阿里妈妈); + var itempoint = session.FindItemPoint(select_form.fl_member_info, isTljOrder ? 0 : commission, alimama.item_num, CpsType.阿里妈妈); + + if (itempoint != null) + { + alimama.db_point = HttpHelper.ObjectToJson(itempoint); + alimama.db_userpoint = itempoint.UserPoint; + } + + alimama.db_userid = select_form.fl_member_info.id; + session.SaveOrUpdate(alimama); + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id", new { userid = alimama.db_userid, itemid = alimama.num_iid, adzoneid = alimama.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (alimama.id == 0) + session.SaveOrUpdate(alimama); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = alimama.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + simpleButton1_Click(null, null); + + //更新显示值 + row.db_userid = select_form.fl_member_info.id; + row.username = select_form.fl_member_info.username; + row.usernick = select_form.fl_member_info.usernick; + row.db_point = alimama.db_point; + + select_form.fl_member_info.bind_order++; + + #region 首次付款时间 + try + { + var record = session.FindStatisticsRecord(select_form.fl_member_info.id); + if (record == null) + { + record = new fl_statistics_record() { uid = select_form.fl_member_info.id, ex2 = 0, ex4 = HttpExtend.GetTimeStamp(DateTime.Now), ex5 = HttpExtend.GetTimeStamp(alimama.paid_time) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + record.ex5 = CsharpHttpHelper.HttpExtend.GetTimeStamp(alimama.paid_time); + session.Saveable(record).ExecuteCommand(); + } + } + catch (Exception) + { } + #endregion + + session.UpdateMemberGroup(select_form.fl_member_info); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// + /// 订单解绑 + /// + /// + /// + private void 解绑ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_alimama; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.订单退款 || db_status == SystemOrderStatus.订单创建) + { + throw new Exception("该订单状态,不允许解绑!"); + } + var session = ApiClient.GetSession(); + + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null && member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + + session.ExcuteSQL("delete from fl_query_hist where itemid = @num_iid", new { num_iid = row.num_iid }); + session.ExcuteSQL("update fl_order_alimama set db_userid = @userid where id=@id", new { userid = 0, id = row.id }); + session.ExcuteSQL("delete from fl_query_ratio_hist where db_orderid=@id", new { id = row.id }); + + //更新显示值 + row.db_userid = 0; + row.username = string.Empty; + row.usernick = string.Empty; + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要结算选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_alimama; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单创建 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.订单退款) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var alimama = session.FindSingle("select * from fl_order_alimama where trade_id = @trade_id and trade_parent_id = @trade_parent_id", new { trade_id = row.trade_id, trade_parent_id = row.trade_parent_id }); + if (alimama == null) throw new Exception("数据查询失败,请稍后重试"); + alimama.earning_time = DateTime.Now.AddSeconds(-2); + alimama.tk_status = (int)AlimamaOrderStatus.订单结算; + alimama.db_endtime = DateTime.Now; + alimama.db_status = SystemOrderStatus.订单冻结; + alimama.auction_category = "手动处理"; + var task = TimerTask.GetTimer() as DownAlimamaTimer; + var notices = new List(); + + var strb = new StringBuilder(); + try + { + strb.Append($@"手动结算 数据1:{HttpHelper.ObjectToJson(alimama)}"); + } + catch (Exception) + { } + + task.UpdateOrder(alimama, notices, session); + + try + { + strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(alimama)}"); + EventClient.OnEvent("淘宝订单手动结算: ", strb.ToString()); + } + catch (Exception) + { } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_alimama; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单结算; + row.db_endtime = DateTime.Now; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即失效ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要失效选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_alimama; + var db_status = row.db_status; + + var session = ApiClient.GetSession(); + var alimama = session.FindSingle("trade_id = @trade_id and trade_parent_id = @trade_parent_id", new { trade_id = row.trade_id, trade_parent_id = row.trade_parent_id }); + if (alimama == null) throw new Exception("数据查询失败,请稍后重试"); + + var flag = false; + var notices = new List(); + if (db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.部分退款) + flag = true; + else if (db_status != SystemOrderStatus.订单维权中 && alimama.IsFinish()) + throw new Exception($"选中订单:{db_status},不予操作"); + + alimama.earning_time = DateTime.Now.AddSeconds(-2); + alimama.tk_status = (int)AlimamaOrderStatus.订单失效; + alimama.db_endtime = DateTime.Now; + alimama.db_status = SystemOrderStatus.订单失效; + alimama.auction_category = "手动处理"; + var task = TimerTask.GetTimer() as DownAlimamaTimer; + + if (!flag) + { + var strb = new StringBuilder(); + try + { + strb.Append($@"手动失效A 数据1:{HttpHelper.ObjectToJson(alimama)}"); + } + catch (Exception) + { } + + task.UpdateOrder(alimama, notices, session); + + try + { + strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(alimama)}"); + EventClient.OnEvent("淘宝订单手动失效: ", strb.ToString()); + } + catch (Exception) + { } + } + else + { + new OrderHelper().DeductAliOrderPoint(notices, alimama); + session.SaveOrUpdate(alimama); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_alimama; + tasks.Add(item); + } + row.db_status = SystemOrderStatus.订单失效; + row.db_endtime = DateTime.Now; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void cps_order_alimama_Load(object sender, EventArgs e) + { + simpleButton1_Click(this.simpleButton1, null); + } + + private void 查看用户信息ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据; + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary(); + common["control_name"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", "").Replace("所有", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + /// + /// 查询用户对应积分列表 + /// + /// + /// + private void 积分ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + var common = new Dictionary(); + common["control_name"] = "提现管理"; + common["query_type"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void contextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + this.查看用户信息ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "username") != null; + + var status = this.gridView1.GetRowCellValue(rows[0], "db_status").ToString(); + + this.冻结延期ToolStripMenuItem.Enabled = status == "订单冻结"; + + this.维权订单查看ToolStripMenuItem.Enabled = (status == "订单维权中" || status == "全额退款" || status == "部分退款"); + + } + else + e.Cancel = true; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 冻结延期ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要延长冻结选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_alimama; + var db_status = row.db_status; + + if (db_status != SystemOrderStatus.订单冻结) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + setting_endtime_form endtime_form = new setting_endtime_form(row.db_endtime); + endtime_form.ShowDialog(); + if (endtime_form.newtime == DateTime.MinValue) return; + + var alimama = session.FindSingle("id = @id", new { id = row.id }); + if (endtime_form.newtime != row.db_endtime) + { + alimama.db_endtime = endtime_form.newtime; + session.Updateable(alimama).ExecuteCommand(); + } + row.db_endtime = endtime_form.newtime;//更新显示值 + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 维权订单查看ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var trade_parent_id = this.gridView1.GetRowCellValue(rows[0], "trade_parent_id").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary(); + common["type"] = "阿里妈妈维权订单"; + common["trade_parent_id"] = trade_parent_id; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void groupControl1_Paint(object sender, PaintEventArgs e) + { + + } + + private void 一键结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要结算当前页所有的订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.DataSource as List; + + if (rows != null && rows.Count > 0) + { + for (int i = 0; i < rows.Count; i++) + { + //获取选中数据 + var row = rows[i]; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单创建 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.订单退款) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var alimama = session.FindSingle("select * from fl_order_alimama where trade_id = @trade_id and trade_parent_id = @trade_parent_id", new { trade_id = row.trade_id, trade_parent_id = row.trade_parent_id }); + if (alimama == null) throw new Exception("数据查询失败,请稍后重试"); + alimama.earning_time = DateTime.Now.AddSeconds(-2); + alimama.tk_status = (int)AlimamaOrderStatus.订单结算; + alimama.db_endtime = DateTime.Now; + alimama.db_status = SystemOrderStatus.订单冻结; + alimama.auction_category = "手动处理"; + var task = TimerTask.GetTimer() as DownAlimamaTimer; + var notices = new List(); + + var strb = new StringBuilder(); + try + { + strb.Append($@"手动结算 数据1:{HttpHelper.ObjectToJson(alimama)}"); + } + catch (Exception) + { } + + task.UpdateOrder(alimama, notices, session); + + try + { + strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(alimama)}"); + EventClient.OnEvent("淘宝订单手动结算: ", strb.ToString()); + } + catch (Exception) + { } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_alimama; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单结算; + row.db_endtime = DateTime.Now; + } + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 一键失效ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要失效当前页所有的订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.DataSource as List; + + if (rows != null && rows.Count > 0) + { + for (int i = 0; i < rows.Count; i++) + { + //获取选中数据 + var row = rows[i]; + var db_status = row.db_status; + + var session = ApiClient.GetSession(); + var alimama = session.FindSingle("trade_id = @trade_id and trade_parent_id = @trade_parent_id", new { trade_id = row.trade_id, trade_parent_id = row.trade_parent_id }); + if (alimama == null) throw new Exception("数据查询失败,请稍后重试"); + + var flag = false; + var notices = new List(); + if (db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.部分退款) + flag = true; + else if (db_status != SystemOrderStatus.订单维权中 && alimama.IsFinish()) + throw new Exception($"选中订单:{db_status},不予操作"); + + alimama.earning_time = DateTime.Now.AddSeconds(-2); + alimama.tk_status = (int)AlimamaOrderStatus.订单失效; + alimama.db_endtime = DateTime.Now; + alimama.db_status = SystemOrderStatus.订单失效; + alimama.auction_category = "手动处理"; + var task = TimerTask.GetTimer() as DownAlimamaTimer; + + if (!flag) + { + var strb = new StringBuilder(); + try + { + strb.Append($@"手动失效A 数据1:{HttpHelper.ObjectToJson(alimama)}"); + } + catch (Exception) + { } + + task.UpdateOrder(alimama, notices, session); + + try + { + strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(alimama)}"); + EventClient.OnEvent("淘宝订单手动失效: ", strb.ToString()); + } + catch (Exception) + { } + } + else + { + new OrderHelper().DeductAliOrderPoint(notices, alimama); + session.SaveOrUpdate(alimama); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_alimama; + tasks.Add(item); + } + row.db_status = SystemOrderStatus.订单失效; + row.db_endtime = DateTime.Now; + } + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 一键延期ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要延长冻结当前页所有的订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.DataSource as List; + + if (rows != null && rows.Count > 0) + { + for (int i = 0; i < rows.Count; i++) + { + //获取选中数据 + var row = rows[i]; + var db_status = row.db_status; + + if (db_status != SystemOrderStatus.订单冻结) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + setting_endtime_form endtime_form = new setting_endtime_form(row.db_endtime); + endtime_form.ShowDialog(); + if (endtime_form.newtime == DateTime.MinValue) return; + + var alimama = session.FindSingle("id = @id", new { id = row.id }); + if (endtime_form.newtime != row.db_endtime) + { + alimama.db_endtime = endtime_form.newtime; + session.Updateable(alimama).ExecuteCommand(); + } + row.db_endtime = endtime_form.newtime;//更新显示值 + } + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 重新计算未结算订单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var db = ApiClient.GetSession(); + var orders = db.Queryable().Where(f => + f.db_userid != 0 && (f.db_status == SystemOrderStatus.订单付款 || + f.db_status == SystemOrderStatus.订单冻结 || + f.db_status == SystemOrderStatus.订单维权中)).ToList(); + EventClient.OnEvent("", $"淘宝需要重新计算的订单数:{orders.Count}"); + + foreach (var order in orders) + { + var member = db.FindMemberInfoById(order.db_userid); + var commission = db.GetTbComparisonFeeRate(order); + var itempoint = db.FindItemPoint(member, commission, order.item_num, CpsType.阿里妈妈); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + + db.SaveOrUpdate(order); + EventClient.OnEvent("", $"淘宝单号:{order.trade_parent_id}-{order.trade_id},重新计算完成"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"淘宝重新计算异常:{ex.Message}"); + } + } + } +} diff --git a/FLSystem/Forms/cps_order_alimama.resx b/FLSystem/Forms/cps_order_alimama.resx new file mode 100644 index 0000000..58e32d9 --- /dev/null +++ b/FLSystem/Forms/cps_order_alimama.resx @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + + 17, 17 + + + 56 + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_douyin.Designer.cs b/FLSystem/Forms/cps_order_douyin.Designer.cs new file mode 100644 index 0000000..4733310 --- /dev/null +++ b/FLSystem/Forms/cps_order_douyin.Designer.cs @@ -0,0 +1,807 @@ +namespace FLSystem.Forms +{ + partial class cps_order_douyin + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_order_douyin)); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.绑定用户ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.解绑ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.用户个人信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.所有阿里妈妈订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有多多进宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有京东联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有抖音联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有苏宁易购订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.订单状态操作ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.冻结延期ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.立即结算ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.立即失效ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键结算ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.重新计算未结算订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.所有快手联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 705); + this.pageControl1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(1114, 44); + this.pageControl1.TabIndex = 8; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.EmbeddedNavigator.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.gridControl1.Location = new System.Drawing.Point(0, 114); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(1114, 581); + this.gridControl1.TabIndex = 6; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.绑定用户ToolStripMenuItem, + this.解绑ToolStripMenuItem, + this.用户个人信息ToolStripMenuItem, + this.订单状态操作ToolStripMenuItem, + this.刷新ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.一键结算ToolStripMenuItem, + this.重新计算未结算订单ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 202); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 绑定用户ToolStripMenuItem + // + this.绑定用户ToolStripMenuItem.Name = "绑定用户ToolStripMenuItem"; + this.绑定用户ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.绑定用户ToolStripMenuItem.Text = "绑定"; + this.绑定用户ToolStripMenuItem.Click += new System.EventHandler(this.绑定用户ToolStripMenuItem_Click); + // + // 解绑ToolStripMenuItem + // + this.解绑ToolStripMenuItem.Name = "解绑ToolStripMenuItem"; + this.解绑ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.解绑ToolStripMenuItem.Text = "解绑"; + this.解绑ToolStripMenuItem.Click += new System.EventHandler(this.解绑ToolStripMenuItem_Click); + // + // 用户个人信息ToolStripMenuItem + // + this.用户个人信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看用户信息ToolStripMenuItem, + this.toolStripSeparator2, + this.所有阿里妈妈订单ToolStripMenuItem, + this.所有多多进宝订单ToolStripMenuItem, + this.所有京东联盟订单ToolStripMenuItem, + this.所有唯品联盟订单ToolStripMenuItem, + this.所有抖音联盟订单ToolStripMenuItem, + this.所有苏宁易购订单ToolStripMenuItem, + this.所有快手联盟订单ToolStripMenuItem, + this.toolStripSeparator1, + this.积分日志ToolStripMenuItem, + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.用户个人信息ToolStripMenuItem.Name = "用户个人信息ToolStripMenuItem"; + this.用户个人信息ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.用户个人信息ToolStripMenuItem.Text = "用户个人信息"; + // + // 查看用户信息ToolStripMenuItem + // + this.查看用户信息ToolStripMenuItem.Name = "查看用户信息ToolStripMenuItem"; + this.查看用户信息ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.查看用户信息ToolStripMenuItem.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem.Click += new System.EventHandler(this.查看用户信息ToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6); + // + // 所有阿里妈妈订单ToolStripMenuItem + // + this.所有阿里妈妈订单ToolStripMenuItem.Name = "所有阿里妈妈订单ToolStripMenuItem"; + this.所有阿里妈妈订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有阿里妈妈订单ToolStripMenuItem.Text = "所有阿里妈妈订单"; + this.所有阿里妈妈订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有多多进宝订单ToolStripMenuItem + // + this.所有多多进宝订单ToolStripMenuItem.Name = "所有多多进宝订单ToolStripMenuItem"; + this.所有多多进宝订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有多多进宝订单ToolStripMenuItem.Text = "所有多多进宝订单"; + this.所有多多进宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有京东联盟订单ToolStripMenuItem + // + this.所有京东联盟订单ToolStripMenuItem.Name = "所有京东联盟订单ToolStripMenuItem"; + this.所有京东联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有京东联盟订单ToolStripMenuItem.Text = "所有京东联盟订单"; + this.所有京东联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有唯品联盟订单ToolStripMenuItem + // + this.所有唯品联盟订单ToolStripMenuItem.Name = "所有唯品联盟订单ToolStripMenuItem"; + this.所有唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有唯品联盟订单ToolStripMenuItem.Text = "所有唯品联盟订单"; + this.所有唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有抖音联盟订单ToolStripMenuItem + // + this.所有抖音联盟订单ToolStripMenuItem.Name = "所有抖音联盟订单ToolStripMenuItem"; + this.所有抖音联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有抖音联盟订单ToolStripMenuItem.Text = "所有抖音联盟订单"; + this.所有抖音联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有苏宁易购订单ToolStripMenuItem + // + this.所有苏宁易购订单ToolStripMenuItem.Name = "所有苏宁易购订单ToolStripMenuItem"; + this.所有苏宁易购订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有苏宁易购订单ToolStripMenuItem.Text = "所有苏宁易购订单"; + this.所有苏宁易购订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6); + // + // 积分日志ToolStripMenuItem + // + this.积分日志ToolStripMenuItem.Name = "积分日志ToolStripMenuItem"; + this.积分日志ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.积分日志ToolStripMenuItem.Text = "积分日志"; + this.积分日志ToolStripMenuItem.Click += new System.EventHandler(this.积分日志ToolStripMenuItem_Click); + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分日志ToolStripMenuItem_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分日志ToolStripMenuItem_Click); + // + // 订单状态操作ToolStripMenuItem + // + this.订单状态操作ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.冻结延期ToolStripMenuItem, + this.立即结算ToolStripMenuItem1, + this.立即失效ToolStripMenuItem1}); + this.订单状态操作ToolStripMenuItem.Name = "订单状态操作ToolStripMenuItem"; + this.订单状态操作ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.订单状态操作ToolStripMenuItem.Text = "订单状态操作"; + // + // 冻结延期ToolStripMenuItem + // + this.冻结延期ToolStripMenuItem.Name = "冻结延期ToolStripMenuItem"; + this.冻结延期ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.冻结延期ToolStripMenuItem.Text = "冻结延期"; + this.冻结延期ToolStripMenuItem.Click += new System.EventHandler(this.冻结延期ToolStripMenuItem_Click); + // + // 立即结算ToolStripMenuItem1 + // + this.立即结算ToolStripMenuItem1.Name = "立即结算ToolStripMenuItem1"; + this.立即结算ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即结算ToolStripMenuItem1.Text = "立即结算"; + this.立即结算ToolStripMenuItem1.Click += new System.EventHandler(this.立即结算ToolStripMenuItem1_Click); + // + // 立即失效ToolStripMenuItem1 + // + this.立即失效ToolStripMenuItem1.Name = "立即失效ToolStripMenuItem1"; + this.立即失效ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即失效ToolStripMenuItem1.Text = "立即失效"; + this.立即失效ToolStripMenuItem1.Click += new System.EventHandler(this.立即失效ToolStripMenuItem1_Click); + // + // 刷新ToolStripMenuItem + // + this.刷新ToolStripMenuItem.Name = "刷新ToolStripMenuItem"; + this.刷新ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.刷新ToolStripMenuItem.Text = "刷新"; + this.刷新ToolStripMenuItem.Click += new System.EventHandler(this.刷新ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // 一键结算ToolStripMenuItem + // + this.一键结算ToolStripMenuItem.Name = "一键结算ToolStripMenuItem"; + this.一键结算ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.一键结算ToolStripMenuItem.Text = "一键结算(隐藏)"; + this.一键结算ToolStripMenuItem.Visible = false; + // + // 重新计算未结算订单ToolStripMenuItem + // + this.重新计算未结算订单ToolStripMenuItem.Name = "重新计算未结算订单ToolStripMenuItem"; + this.重新计算未结算订单ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.重新计算未结算订单ToolStripMenuItem.Text = "重新计算未结算订单"; + this.重新计算未结算订单ToolStripMenuItem.Visible = false; + this.重新计算未结算订单ToolStripMenuItem.Click += new System.EventHandler(this.重新计算未结算订单ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn14, + this.gridColumn9, + this.gridColumn7, + this.gridColumn8, + this.gridColumn21, + this.gridColumn20, + this.gridColumn25, + this.gridColumn19, + this.gridColumn6, + this.gridColumn5, + this.gridColumn1, + this.gridColumn3, + this.gridColumn18, + this.gridColumn27, + this.gridColumn26, + this.gridColumn2, + this.gridColumn16}); + this.gridView1.DetailHeight = 476; + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 67; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn15 + // + this.gridColumn15.Caption = "创建时间"; + this.gridColumn15.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn15.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn15.FieldName = "pay_time"; + this.gridColumn15.MinWidth = 27; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 165; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "order_id"; + this.gridColumn4.MinWidth = 164; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 164; + // + // gridColumn14 + // + this.gridColumn14.Caption = "状态"; + this.gridColumn14.FieldName = "db_status"; + this.gridColumn14.MinWidth = 27; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 2; + this.gridColumn14.Width = 101; + // + // gridColumn9 + // + this.gridColumn9.Caption = "付款金额"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn9.FieldName = "total_pay_amount"; + this.gridColumn9.MinWidth = 27; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 3; + this.gridColumn9.Width = 101; + // + // gridColumn7 + // + this.gridColumn7.Caption = "实际总佣金"; + this.gridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn7.FieldName = "estimated_comission"; + this.gridColumn7.MinWidth = 27; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + this.gridColumn7.Width = 101; + // + // gridColumn8 + // + this.gridColumn8.Caption = "客户所得"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn8.FieldName = "db_userpoint"; + this.gridColumn8.MinWidth = 27; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 5; + this.gridColumn8.Width = 101; + // + // gridColumn21 + // + this.gridColumn21.Caption = "一级提成"; + this.gridColumn21.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn21.FieldName = "db_point"; + this.gridColumn21.MinWidth = 27; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 6; + this.gridColumn21.Width = 101; + // + // gridColumn20 + // + this.gridColumn20.Caption = "二级提成"; + this.gridColumn20.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn20.FieldName = "db_point"; + this.gridColumn20.MinWidth = 27; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 7; + this.gridColumn20.Width = 101; + // + // gridColumn25 + // + this.gridColumn25.Caption = "三级提成"; + this.gridColumn25.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn25.FieldName = "db_point"; + this.gridColumn25.MinWidth = 24; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.OptionsColumn.AllowEdit = false; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 8; + this.gridColumn25.Width = 87; + // + // gridColumn19 + // + this.gridColumn19.Caption = "群负责人提成"; + this.gridColumn19.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn19.FieldName = "db_point"; + this.gridColumn19.MinWidth = 27; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 9; + this.gridColumn19.Width = 101; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.MinWidth = 27; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 10; + this.gridColumn6.Width = 136; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户名"; + this.gridColumn5.FieldName = "username"; + this.gridColumn5.MinWidth = 164; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 11; + this.gridColumn5.Width = 164; + // + // gridColumn1 + // + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "product_name"; + this.gridColumn1.MinWidth = 27; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 12; + this.gridColumn1.Width = 476; + // + // gridColumn3 + // + this.gridColumn3.Caption = "商品编号"; + this.gridColumn3.FieldName = "product_id"; + this.gridColumn3.MinWidth = 164; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 13; + this.gridColumn3.Width = 164; + // + // gridColumn18 + // + this.gridColumn18.Caption = "冻结时间"; + this.gridColumn18.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn18.FieldName = "db_endtime"; + this.gridColumn18.MinWidth = 27; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 14; + this.gridColumn18.Width = 101; + // + // gridColumn27 + // + this.gridColumn27.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn27.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.Caption = "机器人昵称"; + this.gridColumn27.FieldName = "robotnick"; + this.gridColumn27.MinWidth = 24; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.OptionsColumn.AllowEdit = false; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 15; + this.gridColumn27.Width = 87; + // + // gridColumn26 + // + this.gridColumn26.Caption = "机器人账号"; + this.gridColumn26.FieldName = "robotname"; + this.gridColumn26.MinWidth = 24; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 16; + this.gridColumn26.Width = 87; + // + // gridColumn2 + // + this.gridColumn2.Caption = "联盟账号"; + this.gridColumn2.FieldName = "db_cpsname"; + this.gridColumn2.MinWidth = 27; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 17; + this.gridColumn2.Width = 136; + // + // gridColumn16 + // + this.gridColumn16.Caption = "联盟昵称"; + this.gridColumn16.FieldName = "db_cpsnick"; + this.gridColumn16.MinWidth = 27; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 18; + this.gridColumn16.Width = 136; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(1114, 110); + this.groupControl1.TabIndex = 7; + this.groupControl1.Text = "搜索条件"; + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(682, 54); + this.checkBox1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(62, 18); + this.checkBox1.TabIndex = 9; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(755, 68); + this.dateTimePicker2.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(189, 22); + this.dateTimePicker2.TabIndex = 8; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(755, 36); + this.dateTimePicker1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(189, 22); + this.dateTimePicker1.TabIndex = 3; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = ""; + this.comboBoxEdit3.Location = new System.Drawing.Point(550, 53); + this.comboBoxEdit3.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(108, 20); + this.comboBoxEdit3.TabIndex = 7; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "不限状态"; + this.comboBoxEdit2.Location = new System.Drawing.Point(427, 53); + this.comboBoxEdit2.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "不限状态", + "订单创建", + "订单付款", + "订单失效", + "订单维权中", + "全额退款", + "部分退款", + "订单冻结", + "订单结算"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(99, 20); + this.comboBoxEdit2.TabIndex = 7; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(93, 55); + this.labelControl1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(959, 47); + this.simpleButton1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(104, 36); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(302, 53); + this.comboBoxEdit1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "订单编号", + "商品编号", + "商品标题", + "客户编号", + "客户账号", + "客户昵称", + "推广位ID", + "联盟ID", + "联盟账号", + "未绑定用户"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(104, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.Tag = "comboboxedit"; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(129, 53); + this.textEdit1.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(157, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Tag = "textedit"; + // + // 所有快手联盟订单ToolStripMenuItem + // + this.所有快手联盟订单ToolStripMenuItem.Name = "所有快手联盟订单ToolStripMenuItem"; + this.所有快手联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有快手联盟订单ToolStripMenuItem.Text = "所有快手联盟订单"; + this.所有快手联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // cps_order_douyin + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.groupControl1); + this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); + this.Name = "cps_order_douyin"; + this.Size = new System.Drawing.Size(1114, 749); + this.Load += new System.EventHandler(this.cps_order_douyin_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 绑定用户ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 解绑ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 用户个人信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 所有阿里妈妈订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有多多进宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有京东联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有唯品联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 订单状态操作ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 冻结延期ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 立即结算ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 立即失效ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 刷新ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 一键结算ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有抖音联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有苏宁易购订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 重新计算未结算订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有快手联盟订单ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/cps_order_douyin.cs b/FLSystem/Forms/cps_order_douyin.cs new file mode 100644 index 0000000..673d156 --- /dev/null +++ b/FLSystem/Forms/cps_order_douyin.cs @@ -0,0 +1,889 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraGrid.Views.Grid; +using Api.Framework; +using SqlSugar; +using Api.Framework.Tools; +using Api.Framework.Enums; +using Api.Framework.Model; +using System.Threading; +using FLSystem.Events; +using UI.Framework.Forms; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Events; +using CefSharp.DevTools.IndexedDB; + +namespace FLSystem.Forms +{ + public partial class cps_order_douyin : DevExpress.XtraEditors.XtraUserControl + { + public cps_order_douyin() + { + InitializeComponent(); + } + + public cps_order_douyin(string textedit = "") + { + InitializeComponent(); + this.textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 5; + this.dateTimePicker1.Value = DateTime.Parse(DateTime.Today.AddDays(-30).ToString("yyyy-MM-01")); + this.dateTimePicker2.Value = DateTime.Parse(DateTime.Now.AddDays(30).ToString("yyyy-MM-dd HH:mm:ss")); + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + this.checkBox1.Checked = false; + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + comboBoxEdit3.SelectedIndex = 0; + #endregion + + try + { + this.pageControl1.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + List result = null; + List conModels = new List(); + if (this.checkBox1.Checked) + { + conModels.Add(new ConditionalModel() { FieldName = "orderTime", ConditionalType = ConditionalType.GreaterThanOrEqual, FieldValue = this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + conModels.Add(new ConditionalModel() { FieldName = "orderTime", ConditionalType = ConditionalType.LessThanOrEqual, FieldValue = this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + } + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword) || comboBoxEdit1.Text == "未绑定用户") + { + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + conModels.Add(new ConditionalModel() { FieldName = "order_id", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "商品编号": + conModels.Add(new ConditionalModel() { FieldName = "product_id", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "商品标题": + conModels.Add(new ConditionalModel() { FieldName = "product_name", ConditionalType = ConditionalType.Like, FieldValue = keyword }); + break; + case "客户编号": + conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "客户账号": + var ids = FindMemberIdByKey("username", keyword); + if (ids != null && ids.Count == 0) + ids.Add("-1"); + conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", ids) }); + break; + case "客户昵称": + ids = FindMemberIdByKey("usernick", keyword); + if (ids != null && ids.Count == 0) + ids.Add("-1"); + conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", ids) }); + break; + case "推广位ID": + conModels.Add(new ConditionalModel() { FieldName = "db_cpsname", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "联盟账号": + conModels.Add(new ConditionalModel() { FieldName = "db_cpsname", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "联盟昵称": + conModels.Add(new ConditionalModel() { FieldName = "db_cpsnick", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "未绑定用户": + conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.Equal, FieldValue = "0" }); + break; + } + } + + var status = this.comboBoxEdit2.SelectedIndex == 0 ? SystemOrderStatus.订单未知 : Util.ConvertEnum(this.comboBoxEdit2.Text); + if (status != SystemOrderStatus.订单未知) + conModels.Add(new ConditionalModel() { FieldName = "db_status", ConditionalType = ConditionalType.Equal, FieldValue = ((int)status).ToString() }); + + if (this.comboBoxEdit3.SelectedIndex != 0) + conModels.Add(new ConditionalModel() { FieldName = "db_robotname", ConditionalType = ConditionalType.Equal, FieldValue = this.comboBoxEdit3.Text.Trim() }); + + //总记录数 + int totalNumber = 0; + + result = session.Queryable() + .Where(conModels) + .OrderBy(o => o.pay_time, OrderByType.Desc) + .Select((o) => new view_cps_order_douyin + { + id = o.id, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + db_userpoint = o.db_userpoint, + robotname = o.db_robotname, + db_userid = o.db_userid, + estimated_comission = o.estimated_comission, + order_id = o.order_id, + pay_time = o.pay_time, + product_id = o.product_id, + product_name = o.product_name, + total_pay_amount = o.total_pay_amount + //username = u.username, + //usernick = u.usernick + }).ToPageList(index, pagesize, ref totalNumber); + + if (result.Count != 0) + { + #region 附加用户 + var bindUsersList = result.Where(f => f.db_userid != 0).Select(f => f.db_userid.ToString()).ToList(); + var memberData = new List(); + if (bindUsersList != null && bindUsersList.Count != 0) + memberData = session.Queryable().Where(new List() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + + int count = 1; + foreach (var member in memberData) + { + count++; + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(50); + var items = result.Where(f => f.db_userid == member.id).ToList(); + foreach (var item in items) + { + item.usernick = member.usernick; + item.username = member.username; + } + } + #endregion + + #region 附加机器人信息 + var robotList = result.Where(f => !string.IsNullOrWhiteSpace(f.robotname)).GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + var robotData = session.FindRobots().Where(f => robotList.Contains(f.name)).ToList(); + foreach (var robot in robotData) + { + var items = result.Where(f => f.robotname == robot.name).ToList(); + foreach (var item in items) + { + item.robotnick = robot.nick; + } + } + #endregion + + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + }, this.gridControl1, 50, false, true); + } + catch (Exception ex) + { + if (!this.IsDisposed) + this.UpdateUI(() => + { + BaseForm.ShowError(ex); + }); + } + + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + /// + /// 代理委托更新UI + /// + /// + protected delegate void DelegateUpdateUI(Action act); + + /// + /// 代理委托更新UI + /// + /// + protected void UpdateUI(Action act) + { + if (!InvokeRequired) + { + act.Invoke(); + } + else + { + DelegateUpdateUI delegateUpdateUI = new DelegateUpdateUI(UpdateUI); + Invoke(delegateUpdateUI, act); + } + } + + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("cps_type") && e.Commons.ContainsKey("username")) + { + var cps_type = (CpsType)int.Parse(e.Commons["cps_type"].ToString()); + if (cps_type == CpsType.抖音联盟) + { + textEdit1.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 5; + comboBoxEdit3.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + checkBox1.Checked = false; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + + /// + /// 条件查询(用户账号/用户昵称),模糊查询,获取用户的id + /// + /// 查询的字段 + /// 模糊的关键词 + /// + private List FindMemberIdByKey(string type, string keyword) + { + try + { + var session = ApiClient.GetSession(); + return session.Find($"select id from fl_member_info where {type} like '%{keyword}%'").Select(f => f.ToString()).ToList(); + } + catch (Exception ex) + { + throw ex; + } + } + + private void gridView1_CustomDrawRowIndicator(object sender, RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "软件状态": + e.DisplayText = Util.ConvertEnum(int.Parse(e.Value.ToString())).ToString(); + break; + case "一级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardone"].ToString(); + break; + case "二级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardtwo"].ToString(); + break; + case "三级提成": + { + var result = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower()); + e.DisplayText = (result != null && result.ContainsKey("awardthree")) ? result["awardthree"].ToString() : "0"; + } + break; + case "群负责人提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardcreate"].ToString(); + break; + case "创建时间": + e.DisplayText = HttpExtend.GetDateTime(e.Value.ToString()).ToString("yyyy-MM-dd HH:mm:ss"); + break; + case "付款金额": + case "实际总佣金": + e.DisplayText = (decimal.Parse(e.Value == null ? "0" : e.Value.ToString()) / 100.0m).ToString(); + break; + + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void cps_order_douyin_Load(object sender, EventArgs e) + { + simpleButton1_Click(this.simpleButton1, null); + } + + public class view_cps_order_douyin + { + /// + /// id + /// + public long id { get; set; } + /// + /// 创建时间 + /// + public long pay_time { get; set; } + /// + /// 订单id + /// + public string order_id { get; set; } + /// + /// 订单状态 + /// + public SystemOrderStatus db_status { get; set; } + /// + /// 付款金额 + /// + public double total_pay_amount { get; set; } + /// + /// 预计总佣金 + /// + public double estimated_comission { get; set; } + /// + /// 积分Json + /// + public string db_point { get; set; } + /// + /// 用户所得 + /// + public double db_userpoint { get; set; } + + private string _robotname; + /// + /// 机器人账号 + /// + public string robotname + { + get { return _robotname; } + set { if (string.IsNullOrEmpty(value)) _robotname = string.Empty; else _robotname = value; } + } + + /// + /// 机器人昵称 + /// + public string robotnick { get; set; } + + private string _username; + /// + /// 用户账号 + /// + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + /// + /// 用户昵称 + /// + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + public long db_userid { get; set; } + /// + /// 商品标题 + /// + public string product_name { get; set; } + /// + /// 商品编码 + /// + public string product_id { get; set; } + /// + /// 冻结时间 + /// + public DateTime db_endtime { get; set; } + /// + /// 联盟账号 + /// + public string db_cpsname { get; set; } + /// + /// 联盟昵称 + /// + public string db_cpsnick { get; set; } + + } + + private void 绑定用户ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_douyin; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception("该订单状态为已完结,不允许修改!"); + + var session = ApiClient.GetSession(); + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null) + { + if (member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + } + + select_member_form select_form = new select_member_form(); + select_form.ShowDialog(); + if (select_form.fl_member_info != null) + { + var douyin = session.FindSingle("id = @id", new { id = row.id }); + if (douyin != null) + { + if (douyin.db_robottype == 0) douyin.db_robottype = select_form.fl_member_info.robot_type; + if (string.IsNullOrWhiteSpace(douyin.db_robotname)) douyin.db_robotname = select_form.fl_member_info.robot_name; + + var itempoint = session.FindItemPoint(select_form.fl_member_info, Util.ConvertDouble_FenToYuan(douyin.estimated_comission), 1, CpsType.抖音联盟); + if (itempoint != null) + { + douyin.db_point = HttpHelper.ObjectToJson(itempoint); + douyin.db_userpoint = itempoint.UserPoint; + } + + douyin.db_userid = select_form.fl_member_info.id; + session.SaveOrUpdate(douyin); + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id", new { userid = douyin.db_userid, itemid = douyin.product_id, adzoneid = douyin.db_cpsname, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (douyin.id == 0) + session.SaveOrUpdate(douyin); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = douyin.id, + createtime = DateTime.Now, + cpstype = CpsType.抖音联盟 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + simpleButton1_Click(null, null); + + //更新显示值 + row.db_userid = select_form.fl_member_info.id; + row.username = select_form.fl_member_info.username; + row.usernick = select_form.fl_member_info.usernick; + row.db_point = douyin.db_point; + + select_form.fl_member_info.bind_order++; + + #region 首次付款时间 + try + { + var record = session.FindStatisticsRecord(select_form.fl_member_info.id); + if (record == null) + { + record = new fl_statistics_record() { uid = select_form.fl_member_info.id, ex2 = 0, ex4 = HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + } + catch (Exception) + { } + #endregion + + session.UpdateMemberGroup(select_form.fl_member_info); + } + + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 解绑ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_douyin; + var db_status = row.db_status; + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception("该订单状态为已完结,不允许解绑!"); + + var session = ApiClient.GetSession(); + + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null && member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + + session.ExcuteSQL("delete from fl_query_hist where itemid = @num_iid", new { num_iid = row.product_id }); + session.ExcuteSQL("update fl_order_douyin set db_userid = @userid where id=@id", new { id = row.id, userid = 0 }); + session.ExcuteSQL("delete from fl_query_ratio_hist where db_orderid=@id", new { id = row.id }); + + //更新显示值 + row.db_userid = 0; + row.username = string.Empty; + row.usernick = string.Empty; + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var info = this.gridView1.GetRow(rows[0]) as view_cps_order_douyin; + if (XtraMessageBox.Show("您确定要删除选中数据嘛?\r\n" + info.product_name, "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_order_douyin where id=" + info.id); + } + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 冻结延期ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要延长冻结选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_douyin; + var db_status = row.db_status; + + if (db_status != SystemOrderStatus.订单冻结) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var endtime_form = new setting_endtime_form(row.db_endtime); + endtime_form.ShowDialog(); + if (endtime_form.newtime == DateTime.MinValue) return; + var douyin = session.FindSingle("id = @id", new { id = row.id }); + if (endtime_form.newtime != row.db_endtime) + { + douyin.db_endtime = endtime_form.newtime; + session.Updateable(douyin).ExecuteCommand(); + } + row.db_endtime = endtime_form.newtime;//更新显示值 + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即结算ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要结算选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_douyin; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单创建 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.订单退款) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var douyin = session.FindSingle("order_id = @order_id and product_id = @product_id", new { order_id = row.order_id, product_id = row.product_id }); + if (douyin == null) throw new Exception("数据查询失败,请稍后重试"); + douyin.db_endtime = DateTime.Now; + douyin.db_status = SystemOrderStatus.订单冻结; + douyin.order_status = "SETTLE";//改成结算 + douyin.product_detail = "手动处理"; + var task = TimerTask.GetTimer() as DownDouyinTimer; + var notices = new List(); + task.UpdateOrder(douyin, notices, session); + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_douyin; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单结算; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即失效ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + var result = XtraMessageBox.Show("确定要失效选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_douyin; + var db_status = row.db_status; + + var session = ApiClient.GetSession(); + var douyin = session.FindSingle("order_id = @order_id and product_id = @product_id", new { order_id = row.order_id, product_id = row.product_id }); + if (douyin == null) throw new Exception("数据查询失败,请稍后重试"); + + var flag = false; + var notices = new List(); + if (db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.部分退款) + flag = true; + else if (douyin.IsFinish()) + throw new Exception($"选中订单:{db_status},不予操作"); + + douyin.order_status = "REFUND"; + douyin.product_detail = "手动处理"; + douyin.db_endtime = DateTime.Now; + douyin.db_status = SystemOrderStatus.订单失效; + var task = TimerTask.GetTimer() as DownDouyinTimer; + + if (!flag) + task.UpdateOrder(douyin, notices, session); + else + { + //new OrderHelper().DeductPinDuoOrderPoint(notices, douyin); + //session.SaveOrUpdate(douyin); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_douyin; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单失效; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 查看用户信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据; + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary(); + common["control_name"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", "").Replace("所有", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + private void 积分日志ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + var common = new Dictionary(); + common["control_name"] = "提现管理"; + common["query_type"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit1.SelectedIndex == 0 || comboBoxEdit1.SelectedIndex == 10) + { + this.textEdit1.Enabled = false; + this.textEdit1.Text = ""; + } + else this.textEdit1.Enabled = true; + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + this.用户个人信息ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "username") != null; + this.冻结延期ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "db_status").ToString() == "订单冻结"; + } + else + e.Cancel = true; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 重新计算未结算订单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var db = ApiClient.GetSession(); + var orders = db.Queryable().Where(f => + f.db_userid != 0 && (f.db_status == SystemOrderStatus.订单付款 || + f.db_status == SystemOrderStatus.订单冻结 || + f.db_status == SystemOrderStatus.订单维权中)).ToList(); + EventClient.OnEvent("", $"抖音需要重新计算的订单数:{orders.Count}"); + + foreach (var order in orders) + { + var member = db.FindMemberInfoById(order.db_userid); + var itempoint = db.FindItemPoint(member, + Util.ConvertDouble_FenToYuan(order.estimated_comission), 1, CpsType.抖音联盟); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + + db.SaveOrUpdate(order); + EventClient.OnEvent("", $"抖音单号:{order.order_id},重新计算完成"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"抖音重新计算异常:{ex.Message}"); + } + } + } +} diff --git a/FLSystem/Forms/cps_order_douyin.resx b/FLSystem/Forms/cps_order_douyin.resx new file mode 100644 index 0000000..2396863 --- /dev/null +++ b/FLSystem/Forms/cps_order_douyin.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_jingdong.Designer.cs b/FLSystem/Forms/cps_order_jingdong.Designer.cs new file mode 100644 index 0000000..66dac8a --- /dev/null +++ b/FLSystem/Forms/cps_order_jingdong.Designer.cs @@ -0,0 +1,914 @@ +namespace FLSystem.Forms +{ + partial class cps_order_jingdong + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_order_jingdong)); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.解绑ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.用户个人信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.所有阿里妈妈订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有多多进宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有京东联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有抖音联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有苏宁易购订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.订单状态操作ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.冻结延期ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.立即结算ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.立即失效ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键结算ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.重新计算未结算订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.checkBox_isOld = new System.Windows.Forms.CheckBox(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.所有快手联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.SuspendLayout(); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 604); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(955, 38); + this.pageControl1.TabIndex = 5; + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改toolStripMenuItem1, + this.解绑ToolStripMenuItem, + this.用户个人信息ToolStripMenuItem, + this.订单状态操作ToolStripMenuItem, + this.刷新ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.一键结算ToolStripMenuItem, + this.重新计算未结算订单ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 180); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 修改toolStripMenuItem1 + // + this.修改toolStripMenuItem1.Name = "修改toolStripMenuItem1"; + this.修改toolStripMenuItem1.Size = new System.Drawing.Size(184, 22); + this.修改toolStripMenuItem1.Text = "绑定"; + this.修改toolStripMenuItem1.Click += new System.EventHandler(this.修改toolStripMenuItem1_Click); + // + // 解绑ToolStripMenuItem + // + this.解绑ToolStripMenuItem.Name = "解绑ToolStripMenuItem"; + this.解绑ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.解绑ToolStripMenuItem.Text = "解绑"; + this.解绑ToolStripMenuItem.Click += new System.EventHandler(this.解绑ToolStripMenuItem_Click); + // + // 用户个人信息ToolStripMenuItem + // + this.用户个人信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看用户信息ToolStripMenuItem, + this.toolStripSeparator1, + this.所有阿里妈妈订单ToolStripMenuItem, + this.所有多多进宝订单ToolStripMenuItem, + this.所有京东联盟订单ToolStripMenuItem, + this.所有唯品联盟订单ToolStripMenuItem, + this.所有抖音联盟订单ToolStripMenuItem, + this.所有苏宁易购订单ToolStripMenuItem, + this.所有快手联盟订单ToolStripMenuItem, + this.toolStripSeparator2, + this.积分日志ToolStripMenuItem, + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.用户个人信息ToolStripMenuItem.Name = "用户个人信息ToolStripMenuItem"; + this.用户个人信息ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.用户个人信息ToolStripMenuItem.Text = "用户个人信息"; + // + // 查看用户信息ToolStripMenuItem + // + this.查看用户信息ToolStripMenuItem.Name = "查看用户信息ToolStripMenuItem"; + this.查看用户信息ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.查看用户信息ToolStripMenuItem.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem.Click += new System.EventHandler(this.查看用户信息ToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6); + // + // 所有阿里妈妈订单ToolStripMenuItem + // + this.所有阿里妈妈订单ToolStripMenuItem.Name = "所有阿里妈妈订单ToolStripMenuItem"; + this.所有阿里妈妈订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有阿里妈妈订单ToolStripMenuItem.Text = "所有阿里妈妈订单"; + this.所有阿里妈妈订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有多多进宝订单ToolStripMenuItem + // + this.所有多多进宝订单ToolStripMenuItem.Name = "所有多多进宝订单ToolStripMenuItem"; + this.所有多多进宝订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有多多进宝订单ToolStripMenuItem.Text = "所有多多进宝订单"; + this.所有多多进宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有京东联盟订单ToolStripMenuItem + // + this.所有京东联盟订单ToolStripMenuItem.Name = "所有京东联盟订单ToolStripMenuItem"; + this.所有京东联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有京东联盟订单ToolStripMenuItem.Text = "所有京东联盟订单"; + this.所有京东联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有唯品联盟订单ToolStripMenuItem + // + this.所有唯品联盟订单ToolStripMenuItem.Name = "所有唯品联盟订单ToolStripMenuItem"; + this.所有唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有唯品联盟订单ToolStripMenuItem.Text = "所有唯品联盟订单"; + this.所有唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有抖音联盟订单ToolStripMenuItem + // + this.所有抖音联盟订单ToolStripMenuItem.Name = "所有抖音联盟订单ToolStripMenuItem"; + this.所有抖音联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有抖音联盟订单ToolStripMenuItem.Text = "所有抖音联盟订单"; + this.所有抖音联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有苏宁易购订单ToolStripMenuItem + // + this.所有苏宁易购订单ToolStripMenuItem.Name = "所有苏宁易购订单ToolStripMenuItem"; + this.所有苏宁易购订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有苏宁易购订单ToolStripMenuItem.Text = "所有苏宁易购订单"; + this.所有苏宁易购订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6); + // + // 积分日志ToolStripMenuItem + // + this.积分日志ToolStripMenuItem.Name = "积分日志ToolStripMenuItem"; + this.积分日志ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.积分日志ToolStripMenuItem.Text = "积分日志"; + this.积分日志ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 订单状态操作ToolStripMenuItem + // + this.订单状态操作ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.冻结延期ToolStripMenuItem, + this.立即结算ToolStripMenuItem1, + this.立即失效ToolStripMenuItem1}); + this.订单状态操作ToolStripMenuItem.Name = "订单状态操作ToolStripMenuItem"; + this.订单状态操作ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.订单状态操作ToolStripMenuItem.Text = "订单状态操作"; + // + // 冻结延期ToolStripMenuItem + // + this.冻结延期ToolStripMenuItem.Name = "冻结延期ToolStripMenuItem"; + this.冻结延期ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.冻结延期ToolStripMenuItem.Text = "冻结延期"; + this.冻结延期ToolStripMenuItem.Click += new System.EventHandler(this.冻结延期ToolStripMenuItem_Click); + // + // 立即结算ToolStripMenuItem1 + // + this.立即结算ToolStripMenuItem1.Name = "立即结算ToolStripMenuItem1"; + this.立即结算ToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + this.立即结算ToolStripMenuItem1.Text = "立即结算"; + this.立即结算ToolStripMenuItem1.Click += new System.EventHandler(this.立即结算ToolStripMenuItem_Click); + // + // 立即失效ToolStripMenuItem1 + // + this.立即失效ToolStripMenuItem1.Name = "立即失效ToolStripMenuItem1"; + this.立即失效ToolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + this.立即失效ToolStripMenuItem1.Text = "立即失效"; + this.立即失效ToolStripMenuItem1.Click += new System.EventHandler(this.立即失效ToolStripMenuItem1_Click); + // + // 刷新ToolStripMenuItem + // + this.刷新ToolStripMenuItem.Name = "刷新ToolStripMenuItem"; + this.刷新ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.刷新ToolStripMenuItem.Text = "刷新"; + this.刷新ToolStripMenuItem.Click += new System.EventHandler(this.刷新ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // 一键结算ToolStripMenuItem + // + this.一键结算ToolStripMenuItem.Name = "一键结算ToolStripMenuItem"; + this.一键结算ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.一键结算ToolStripMenuItem.Text = "一键结算(隐藏)"; + this.一键结算ToolStripMenuItem.Visible = false; + this.一键结算ToolStripMenuItem.Click += new System.EventHandler(this.一键结算ToolStripMenuItem_Click); + // + // 重新计算未结算订单ToolStripMenuItem + // + this.重新计算未结算订单ToolStripMenuItem.Name = "重新计算未结算订单ToolStripMenuItem"; + this.重新计算未结算订单ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.重新计算未结算订单ToolStripMenuItem.Text = "重新计算未结算订单"; + this.重新计算未结算订单ToolStripMenuItem.Visible = false; + this.重新计算未结算订单ToolStripMenuItem.Click += new System.EventHandler(this.重新计算未结算订单ToolStripMenuItem_Click); + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(460, 46); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(62, 18); + this.checkBox1.TabIndex = 9; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(522, 53); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(162, 22); + this.dateTimePicker2.TabIndex = 8; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(522, 26); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(162, 22); + this.dateTimePicker1.TabIndex = 3; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "不限状态"; + this.comboBoxEdit2.Location = new System.Drawing.Point(350, 28); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "不限状态", + "订单创建", + "订单付款", + "订单失效", + "订单维权中", + "全额退款", + "部分退款", + "订单冻结", + "订单结算"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(93, 20); + this.comboBoxEdit2.TabIndex = 7; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(31, 48); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(706, 37); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(89, 31); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(242, 45); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "订单编号", + "商品编号", + "商品标题", + "客户编号", + "客户账号", + "客户昵称", + "推广位ID", + "联盟账号", + "联盟昵称", + "未绑定用户"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(89, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.Tag = "comboboxedit"; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(69, 45); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(152, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Tag = "textedit"; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.checkBox_isOld); + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(955, 94); + this.groupControl1.TabIndex = 3; + this.groupControl1.Text = "搜索条件"; + // + // checkBox_isOld + // + this.checkBox_isOld.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox_isOld.AutoSize = true; + this.checkBox_isOld.Checked = true; + this.checkBox_isOld.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_isOld.Location = new System.Drawing.Point(814, 39); + this.checkBox_isOld.Name = "checkBox_isOld"; + this.checkBox_isOld.Size = new System.Drawing.Size(134, 32); + this.checkBox_isOld.TabIndex = 11; + this.checkBox_isOld.Text = "搜索一年以内的数据\r\n查询速度慢的请勾选"; + this.checkBox_isOld.UseVisualStyleBackColor = true; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = ""; + this.comboBoxEdit3.Location = new System.Drawing.Point(350, 55); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(93, 20); + this.comboBoxEdit3.TabIndex = 7; + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn14, + this.gridColumn9, + this.gridColumn7, + this.gridColumn22, + this.gridColumn24, + this.gridColumn12, + this.gridColumn8, + this.gridColumn21, + this.gridColumn20, + this.gridColumn25, + this.gridColumn19, + this.gridColumn17, + this.gridColumn6, + this.gridColumn5, + this.gridColumn1, + this.gridColumn3, + this.gridColumn10, + this.gridColumn11, + this.gridColumn23, + this.gridColumn18, + this.gridColumn27, + this.gridColumn26, + this.gridColumn2, + this.gridColumn16, + this.gridColumn13}); + this.gridView1.DetailHeight = 408; + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 58; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn15 + // + this.gridColumn15.Caption = "创建时间"; + this.gridColumn15.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn15.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn15.FieldName = "orderTime"; + this.gridColumn15.MinWidth = 23; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 142; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "orderId"; + this.gridColumn4.MinWidth = 140; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 140; + // + // gridColumn14 + // + this.gridColumn14.Caption = "状态"; + this.gridColumn14.FieldName = "db_status"; + this.gridColumn14.MinWidth = 23; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 2; + this.gridColumn14.Width = 87; + // + // gridColumn9 + // + this.gridColumn9.Caption = "付款金额"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn9.FieldName = "estimateCosPrice"; + this.gridColumn9.MinWidth = 23; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 3; + this.gridColumn9.Width = 87; + // + // gridColumn7 + // + this.gridColumn7.Caption = "实际总佣金"; + this.gridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn7.FieldName = "actualFee"; + this.gridColumn7.MinWidth = 23; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + this.gridColumn7.Width = 87; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "维权金额"; + this.gridColumn22.MinWidth = 23; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.OptionsColumn.AllowEdit = false; + this.gridColumn22.Width = 80; + // + // gridColumn24 + // + this.gridColumn24.Caption = "客户维权后佣金"; + this.gridColumn24.MinWidth = 23; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + this.gridColumn24.Width = 87; + // + // gridColumn12 + // + this.gridColumn12.Caption = "预计总佣金"; + this.gridColumn12.FieldName = "estimateFee"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 5; + this.gridColumn12.Width = 87; + // + // gridColumn8 + // + this.gridColumn8.Caption = "客户所得"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn8.FieldName = "db_userpoint"; + this.gridColumn8.MinWidth = 23; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 6; + this.gridColumn8.Width = 87; + // + // gridColumn21 + // + this.gridColumn21.Caption = "一级提成"; + this.gridColumn21.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn21.FieldName = "db_point"; + this.gridColumn21.MinWidth = 23; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 7; + this.gridColumn21.Width = 87; + // + // gridColumn20 + // + this.gridColumn20.Caption = "二级提成"; + this.gridColumn20.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn20.FieldName = "db_point"; + this.gridColumn20.MinWidth = 23; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 8; + this.gridColumn20.Width = 87; + // + // gridColumn25 + // + this.gridColumn25.Caption = "三级提成"; + this.gridColumn25.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn25.FieldName = "db_point"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.OptionsColumn.AllowEdit = false; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 9; + // + // gridColumn19 + // + this.gridColumn19.Caption = "群负责人提成"; + this.gridColumn19.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn19.FieldName = "db_point"; + this.gridColumn19.MinWidth = 23; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 10; + this.gridColumn19.Width = 87; + // + // gridColumn17 + // + this.gridColumn17.Caption = "Plus用户"; + this.gridColumn17.FieldName = "plus"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 11; + this.gridColumn17.Width = 87; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.MinWidth = 23; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 12; + this.gridColumn6.Width = 117; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户名"; + this.gridColumn5.FieldName = "username"; + this.gridColumn5.MinWidth = 140; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 13; + this.gridColumn5.Width = 140; + // + // gridColumn1 + // + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "skuName"; + this.gridColumn1.MinWidth = 23; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 14; + this.gridColumn1.Width = 408; + // + // gridColumn3 + // + this.gridColumn3.Caption = "商品编号"; + this.gridColumn3.FieldName = "skuId"; + this.gridColumn3.MinWidth = 140; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 15; + this.gridColumn3.Width = 140; + // + // gridColumn10 + // + this.gridColumn10.Caption = "商品单价"; + this.gridColumn10.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn10.FieldName = "price"; + this.gridColumn10.MinWidth = 23; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 16; + this.gridColumn10.Width = 87; + // + // gridColumn11 + // + this.gridColumn11.Caption = "购买数量"; + this.gridColumn11.FieldName = "skuNum"; + this.gridColumn11.MinWidth = 23; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 17; + this.gridColumn11.Width = 87; + // + // gridColumn23 + // + this.gridColumn23.Caption = "已退货数量"; + this.gridColumn23.FieldName = "skuReturnNum"; + this.gridColumn23.MinWidth = 23; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.OptionsColumn.AllowEdit = false; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 24; + this.gridColumn23.Width = 87; + // + // gridColumn18 + // + this.gridColumn18.Caption = "冻结时间"; + this.gridColumn18.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn18.FieldName = "db_endtime"; + this.gridColumn18.MinWidth = 23; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 18; + this.gridColumn18.Width = 87; + // + // gridColumn27 + // + this.gridColumn27.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn27.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.Caption = "机器人昵称"; + this.gridColumn27.FieldName = "robotnick"; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.OptionsColumn.AllowEdit = false; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 19; + // + // gridColumn26 + // + this.gridColumn26.Caption = "机器人账号"; + this.gridColumn26.FieldName = "robotname"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 20; + // + // gridColumn2 + // + this.gridColumn2.Caption = "联盟账号"; + this.gridColumn2.FieldName = "db_cpsname"; + this.gridColumn2.MinWidth = 23; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 21; + this.gridColumn2.Width = 117; + // + // gridColumn16 + // + this.gridColumn16.Caption = "联盟昵称"; + this.gridColumn16.FieldName = "db_cpsnick"; + this.gridColumn16.MinWidth = 23; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 22; + this.gridColumn16.Width = 117; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "推广位"; + this.gridColumn13.FieldName = "positionId"; + this.gridColumn13.MinWidth = 140; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 23; + this.gridColumn13.Width = 140; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(7, 98); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(948, 498); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // 所有快手联盟订单ToolStripMenuItem + // + this.所有快手联盟订单ToolStripMenuItem.Name = "所有快手联盟订单ToolStripMenuItem"; + this.所有快手联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有快手联盟订单ToolStripMenuItem.Text = "所有快手联盟订单"; + this.所有快手联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // cps_order_jingdong + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.groupControl1); + this.Name = "cps_order_jingdong"; + this.Size = new System.Drawing.Size(955, 642); + this.Load += new System.EventHandler(this.cps_order_jingdong_Load); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private UI.Framework.Controls.PageControl pageControl1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 修改toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 解绑ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 刷新ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private System.Windows.Forms.ToolStripMenuItem 用户个人信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 所有阿里妈妈订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有多多进宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有京东联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 订单状态操作ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 立即失效ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 立即结算ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 冻结延期ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 一键结算ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private System.Windows.Forms.ToolStripMenuItem 所有唯品联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有抖音联盟订单ToolStripMenuItem; + private System.Windows.Forms.CheckBox checkBox_isOld; + private System.Windows.Forms.ToolStripMenuItem 所有苏宁易购订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 重新计算未结算订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有快手联盟订单ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/cps_order_jingdong.cs b/FLSystem/Forms/cps_order_jingdong.cs new file mode 100644 index 0000000..f0fd23c --- /dev/null +++ b/FLSystem/Forms/cps_order_jingdong.cs @@ -0,0 +1,1069 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using FLSystem.Events; +using Newtonsoft.Json; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class cps_order_jingdong : DevExpress.XtraEditors.XtraUserControl + { + public cps_order_jingdong(string textedit = "") + { + InitializeComponent(); + this.textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 5; + this.dateTimePicker1.Value = DateTime.Parse(DateTime.Today.AddDays(-30).ToString("yyyy-MM-01")); + this.dateTimePicker2.Value = DateTime.Parse(DateTime.Now.AddDays(30).ToString("yyyy-MM-dd HH:mm:ss")); + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + this.checkBox1.Checked = false; + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + comboBoxEdit3.SelectedIndex = 0; + #endregion + try + { + this.pageControl1.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var isOld = true; + List result = null; + //List conModels = new List(); + var sqlwhere = string.Empty; + if (this.checkBox1.Checked) + { + isOld = false; + + sqlwhere += $" and '{this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss")}' <= orderTime and orderTime <= '{this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss")}'"; + + //conModels.Add(new ConditionalModel() { FieldName = "orderTime", ConditionalType = ConditionalType.GreaterThanOrEqual, FieldValue = this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + //conModels.Add(new ConditionalModel() { FieldName = "orderTime", ConditionalType = ConditionalType.LessThanOrEqual, FieldValue = this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + } + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword) || comboBoxEdit1.Text == "未绑定用户") + { + + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + //conModels.Add(new ConditionalModel() { FieldName = "orderId", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and orderId = '{keyword}'"; + break; + case "商品编号": + //conModels.Add(new ConditionalModel() { FieldName = "skuId", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and skuId = '{keyword}'"; + break; + case "商品标题": + //conModels.Add(new ConditionalModel() { FieldName = "skuname", ConditionalType = ConditionalType.Like, FieldValue = keyword }); + sqlwhere += $" and skuname like '%{keyword}%'"; + break; + case "客户编号": + //conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and db_userid = '{keyword}'"; + break; + case "客户账号": + var ids = FindMemberIdByKey("username", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + //conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", ids) }); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "客户昵称": + ids = FindMemberIdByKey("usernick", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + //conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", ids) }); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "推广位ID": + //conModels.Add(new ConditionalModel() { FieldName = "positionId", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and positionId = '{keyword}'"; + break; + case "联盟账号": + //conModels.Add(new ConditionalModel() { FieldName = "db_cpsname", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and db_cpsname = '{keyword}'"; + break; + case "联盟昵称": + //conModels.Add(new ConditionalModel() { FieldName = "db_cpsnick", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and db_cpsnick = '{keyword}'"; + break; + case "未绑定用户": + //conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.Equal, FieldValue = "0" }); + sqlwhere += $" and db_userid = '0'"; + break; + } + } + + var status = this.comboBoxEdit2.SelectedIndex == 0 ? SystemOrderStatus.订单未知 : Util.ConvertEnum(this.comboBoxEdit2.Text); + if (status != SystemOrderStatus.订单未知) + //conModels.Add(new ConditionalModel() { FieldName = "db_status", ConditionalType = ConditionalType.Equal, FieldValue = ((int)status).ToString() }); + sqlwhere += $" and db_status = '{((int)status).ToString()}'"; + if (this.comboBoxEdit3.SelectedIndex != 0) + //conModels.Add(new ConditionalModel() { FieldName = "db_robotname", ConditionalType = ConditionalType.Equal, FieldValue = this.comboBoxEdit3.Text.Trim() }); + sqlwhere += $" and db_robotname = '{comboBoxEdit3.Text.Trim()}'"; + + //总记录数 + int totalNumber = 0; + + if (isOld && checkBox_isOld.Checked) + { + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= orderTime"; + } + + + //result = session.Queryable() + //.Where(conModels) + //.OrderBy(o => o.id, OrderByType.Desc); + //.ToPageList(index, pagesize, ref totalNumber); + sqlwhere += $" order by id desc"; + + var getCount = session.Find("select count(*) from fl_order_jingdong where 1=1 " + sqlwhere); + if (getCount != null && getCount.Count != 0) + totalNumber = getCount[0]; + + sqlwhere += $" limit {(index - 1) * pagesize},{pagesize}"; + + var resultTmp = session.Find("select * from fl_order_jingdong where 1=1 " + sqlwhere); + + result = new List(); + foreach (var o in resultTmp) + { + result.Add(new view_cps_order_jingdong + { + id = o.id, + actualFee = o.actualFee, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + db_userpoint = o.db_userpoint, + estimateCosPrice = o.estimateCosPrice, + estimateFee = o.estimateFee, + orderId = o.orderId, + orderTime = o.orderTime, + plus = (plusStatus)o.plus, + positionId = o.positionId, + price = o.price, + robotname = o.db_robotname, + skuId = o.skuId, + skuName = o.skuName, + skuNum = o.skuNum, + skuReturnNum = o.skuReturnNum, + db_userid = o.db_userid + //username = u.username, + //usernick = u.usernick + }); + } + + #region xxx + /* + result = session.Queryable() + .Where(conModels) + .OrderBy(o => o.orderTime, OrderByType.Desc) + .Select((o) => new view_cps_order_jingdong + { + id = o.id, + actualFee = o.actualFee, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + db_userpoint = o.db_userpoint, + estimateCosPrice = o.estimateCosPrice, + estimateFee = o.estimateFee, + orderId = o.orderId, + orderTime = o.orderTime, + plus = (plusStatus)o.plus, + positionId = o.positionId, + price = o.price, + robotname = o.db_robotname, + skuId = o.skuId, + skuName = o.skuName, + skuNum = o.skuNum, + skuReturnNum = o.skuReturnNum, + db_userid = o.db_userid + //username = u.username, + //usernick = u.usernick + }).ToPageList(index, pagesize, ref totalNumber); + */ + #endregion + + if (result.Count != 0) + { + #region 附加用户 + var bindUsersList = result.Where(f => f.db_userid != 0).Select(f => f.db_userid.ToString()).ToList(); + var memberData = new List(); + if (bindUsersList != null && bindUsersList.Count != 0) + memberData = session.Queryable().Where(new List() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + + int count = 1; + foreach (var member in memberData) + { + count++; + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(50); + var items = result.Where(f => f.db_userid == member.id).ToList(); + foreach (var item in items) + { + item.usernick = member.usernick; + item.username = member.username; + } + } + #endregion + + #region 附加机器人信息 + var robotList = result.Where(f => !string.IsNullOrWhiteSpace(f.robotname)).GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + var robotData = session.FindRobots().Where(f => robotList.Contains(f.name)).ToList(); + foreach (var robot in robotData) + { + var items = result.Where(f => f.robotname == robot.name).ToList(); + foreach (var item in items) + { + item.robotnick = robot.nick; + } + } + #endregion + + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + }, this.gridControl1, 50, false, true); + } + catch (Exception ex) + { + if (!this.IsDisposed) + this.UpdateUI(() => + { + BaseForm.ShowError(ex); + }); + } + + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + + private void cps_order_jingdong_Load(object sender, EventArgs e) + { + simpleButton1_Click(this.simpleButton1, null); + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + /// + /// 代理委托更新UI + /// + /// + protected delegate void DelegateUpdateUI(Action act); + + /// + /// 代理委托更新UI + /// + /// + protected void UpdateUI(Action act) + { + if (!InvokeRequired) + { + act.Invoke(); + } + else + { + DelegateUpdateUI delegateUpdateUI = new DelegateUpdateUI(UpdateUI); + Invoke(delegateUpdateUI, act); + } + } + + + /// + /// 条件查询(用户账号/用户昵称),模糊查询,获取用户的id + /// + /// 查询的字段 + /// 模糊的关键词 + /// + private List FindMemberIdByKey(string type, string keyword) + { + try + { + var session = ApiClient.GetSession(); + return session.Find($"select id from fl_member_info where {type} like '%{keyword}%'").Select(f => f.ToString()).ToList(); + } + catch (Exception ex) + { + throw ex; + } + } + + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("cps_type") && e.Commons.ContainsKey("username")) + { + var cps_type = (CpsType)int.Parse(e.Commons["cps_type"].ToString()); + if (cps_type == CpsType.京东联盟) + { + textEdit1.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 5; + comboBoxEdit3.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + checkBox1.Checked = false; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit1.SelectedIndex == 0 || comboBoxEdit1.SelectedIndex == 10) + { + this.textEdit1.Enabled = false; + this.textEdit1.Text = ""; + } + else this.textEdit1.Enabled = true; + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + this.dateTimePicker1.Enabled = this.dateTimePicker2.Enabled = this.checkBox1.Checked; + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "软件状态": + e.DisplayText = Util.ConvertEnum(int.Parse(e.Value.ToString())).ToString(); + break; + case "一级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardone"].ToString(); + break; + case "二级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardtwo"].ToString(); + break; + case "三级提成": + { + var result = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower()); + e.DisplayText = (result != null && result.ContainsKey("awardthree")) ? result["awardthree"].ToString() : "0"; + } + break; + case "群负责人提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardcreate"].ToString(); + break; + } + } + + private void 修改toolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_jingdong; + var db_status = row.db_status; + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) throw new Exception("该订单状态为已完结,不允许修改!"); + + var session = ApiClient.GetSession(); + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null) + { + if (member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + } + + select_member_form select_form = new select_member_form(); + select_form.ShowDialog(); + if (select_form.fl_member_info != null) + { + var jingdong = session.FindSingle("id = @id", new { id = row.id }); + if (jingdong != null) + { + if (jingdong.db_robottype == 0) jingdong.db_robottype = select_form.fl_member_info.robot_type; + if (string.IsNullOrWhiteSpace(jingdong.db_robotname)) jingdong.db_robotname = select_form.fl_member_info.robot_name; + + var itempoint = session.FindItemPoint(select_form.fl_member_info, (jingdong.actualFee == 0) ? jingdong.estimateFee : jingdong.actualFee, (int)jingdong.skuNum, CpsType.京东联盟); + if (itempoint != null) + { + jingdong.db_point = HttpHelper.ObjectToJson(itempoint); + jingdong.db_userpoint = itempoint.UserPoint; + } + + jingdong.db_userid = select_form.fl_member_info.id; + session.SaveOrUpdate(jingdong); + + //更新显示值 + row.db_userid = select_form.fl_member_info.id; + row.username = select_form.fl_member_info.username; + row.usernick = select_form.fl_member_info.usernick; + row.db_point = jingdong.db_point; + + select_form.fl_member_info.bind_order++; + + #region 首次付款时间 + try + { + var record = session.FindStatisticsRecord(select_form.fl_member_info.id); + if (record == null) + { + record = new fl_statistics_record() { uid = select_form.fl_member_info.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now), ex5 = HttpExtend.GetTimeStamp(jingdong.orderTime) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + record.ex5 = CsharpHttpHelper.HttpExtend.GetTimeStamp(jingdong.orderTime); + session.Saveable(record).ExecuteCommand(); + } + } + catch (Exception) + { } + #endregion + + session.UpdateMemberGroup(select_form.fl_member_info); + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id", new { userid = jingdong.db_userid, itemid = jingdong.skuId, adzoneid = jingdong.positionId, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (jingdong.id == 0) + session.SaveOrUpdate(jingdong); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = jingdong.id, + createtime = DateTime.Now, + cpstype = CpsType.京东联盟 + }; + LogHelper.GetSingleObj().Error("历史查询记录4", JsonConvert.SerializeObject(queryRatioHist)); + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + } + + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 解绑ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_jingdong; + var db_status = row.db_status; + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) throw new Exception("该订单状态为已完结,不允许解绑!"); + + var session = ApiClient.GetSession(); + + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null && member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + + session.ExcuteSQL("delete from fl_query_hist where itemid = @num_iid", new { num_iid = row.skuId }); + session.ExcuteSQL("update fl_order_jingdong set db_userid = @userid where id=@id", new { id = row.id, userid = 0 }); + session.ExcuteSQL("delete from fl_query_ratio_hist where db_orderid=@id", new { id = row.id }); + + //更新显示值 + row.db_userid = 0; + row.username = string.Empty; + row.usernick = string.Empty; + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要结算选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_jingdong; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单创建 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var jingdong = session.FindSingle("orderId = @orderId and skuId = @skuId", new { orderId = row.orderId, skuId = row.skuId }); + + if (jingdong == null) throw new Exception("数据查询失败,请稍后重试"); + jingdong.finishTime = DateTime.Now.AddSeconds(-2); + jingdong.validCode = 17; + jingdong.db_endtime = DateTime.Now; + jingdong.db_status = SystemOrderStatus.订单冻结; + var task = TimerTask.GetTimer() as DownJingdongTimer; + var notices = new List(); + task.UpdateOrder(jingdong, session, notices); + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_jingdong; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单结算; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var info = this.gridView1.GetRow(rows[0]) as view_cps_order_jingdong; + if (XtraMessageBox.Show($@"您确定要删除选中数据嘛? +{info.skuName}", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_order_jingdong where id=" + info.id); + } + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 查看用户信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据; + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary(); + common["control_name"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", "").Replace("所有", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + /// + /// 查询用户对应积分列表 + /// + /// + /// + private void 积分ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + var common = new Dictionary(); + common["control_name"] = "提现管理"; + common["query_type"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void contextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + this.用户个人信息ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "username") != null; + this.冻结延期ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "db_status").ToString() == "订单冻结"; + } + else + e.Cancel = true; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 冻结延期ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要延长冻结选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_jingdong; + var db_status = row.db_status; + + if (db_status != SystemOrderStatus.订单冻结) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + + setting_endtime_form endtime_form = new setting_endtime_form(row.db_endtime); + endtime_form.ShowDialog(); + if (endtime_form.newtime == DateTime.MinValue) return; + + var jingdong = session.FindSingle("id = @id", new { id = row.id }); + if (endtime_form.newtime != row.db_endtime) + { + jingdong.db_endtime = endtime_form.newtime; + session.Updateable(jingdong).ExecuteCommand(); + } + row.db_endtime = endtime_form.newtime;//更新显示值 + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即失效ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要失效选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_jingdong; + var db_status = row.db_status; + + var session = ApiClient.GetSession(); + //var jingdong = session.FindSingle("orderId = @orderId", new { orderId = row.orderId }); + var jingdong = session.FindSingle("id = @id", new { id = row.id }); + if (jingdong == null) throw new Exception("数据查询失败,请稍后重试"); + + var flag = false; + var notices = new List(); + if (db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.部分退款) + flag = true; + else if (jingdong.IsFinish()) + throw new Exception($"选中订单:{db_status},不予操作"); + + jingdong.finishTime = DateTime.Now.AddSeconds(-2); + jingdong.validCode = 3; + jingdong.db_endtime = DateTime.Now; + jingdong.db_status = SystemOrderStatus.订单失效; + var task = TimerTask.GetTimer() as DownJingdongTimer; + + if (!flag) + task.UpdateOrder(jingdong, session, notices); + else + { + var itempoint = HttpHelper.JsonToObject(jingdong.db_point) as ItemPoint; + new OrderHelper().DeductJingDongOrderPoint(notices, jingdong, itempoint); + session.SaveOrUpdate(jingdong); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_jingdong; + tasks.Add(item); + } + row.db_status = SystemOrderStatus.订单失效; + row.db_endtime = DateTime.Now; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + /// + /// 要删除的@@@@@ + /// + /// + /// + private void 一键结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (MessageBox.Show("确定结算所有该所有的订单吗", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + var orders = ApiClient.GetSession().Find("select * from fl_order_jingdong where db_userid != 0 and (db_status = @db_status1 or db_status = @db_status2)", new { db_status1 = SystemOrderStatus.订单付款, db_status2 = SystemOrderStatus.订单冻结 }); + + if (orders.Count != 0) + { + Task.Run(() => + { + var session = ApiClient.GetSession(); + try + { + var task = TimerTask.GetTimer() as DownJingdongTimer; + var notices = new List(); + foreach (var order in orders) + { + + tokenSource.Token.ThrowIfCancellationRequested(); + order.finishTime = DateTime.Now.AddSeconds(-2); + order.validCode = 17; + order.db_endtime = DateTime.Now; + order.db_status = SystemOrderStatus.订单冻结; + + //var task = TimerTask.GetTimer() as DownJingdongTimer; + //var notices = new List(); + //task.UpdateOrder(jingdong, session, notices); + + //var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + //foreach (var item in notices) + //{ + // if (item.Member == null) continue; + // var order = item.Order as fl_order_jingdong; + // tasks.Add(item); + //} + + task.UpdateOrder(order, session, notices); + } + + //var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + + //foreach (var item in notices) + //{ + // tokenSource.Token.ThrowIfCancellationRequested(); + // if (item.Member == null) continue; + // if (item.Order is fl_order_jingdong) + // tasks.Add(item); + //} + XtraMessageBox.Show($"一键结算成功,一共结算{orders.Count}笔订单!", "温馨提示", MessageBoxButtons.OK); + } + catch (Exception) + { } + }, tokenSource.Token); + } + else + XtraMessageBox.Show($"当前无可结算的订单!", "温馨提示", MessageBoxButtons.OK); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 重新计算未结算订单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var db = ApiClient.GetSession(); + var orders = db.Queryable().Where(f => + f.db_userid != 0 && (f.db_status == SystemOrderStatus.订单付款 || + f.db_status == SystemOrderStatus.订单冻结 || + f.db_status == SystemOrderStatus.订单维权中)).ToList(); + EventClient.OnEvent("", $"京东需要重新计算的订单数:{orders.Count}"); + + foreach (var order in orders) + { + var member = db.FindMemberInfoById(order.db_userid); + var itempoint = db.FindItemPoint(member, (order.actualFee == 0) ? order.estimateFee : order.actualFee, (int)order.skuNum, CpsType.京东联盟); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + + db.SaveOrUpdate(order); + EventClient.OnEvent("", $"京东单号:{order.orderId},重新计算完成"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"京东重新计算异常:{ex.Message}"); + } + } + } + + public class view_cps_order_jingdong + { + /// + /// id + /// + public long id { get; set; } + /// + /// 创建时间 + /// + public DateTime orderTime { get; set; } + /// + /// 订单父id + /// + public long orderId { get; set; } + /// + /// 订单状态 + /// + public SystemOrderStatus db_status { get; set; } + /// + /// 付款金额 + /// + public double estimateCosPrice { get; set; } + /// + /// 实际总佣金 + /// + public double actualFee { get; set; } + /// + /// 预计总佣金 + /// + public double estimateFee { get; set; } + /// + /// 积分Json + /// + public string db_point { get; set; } + /// + /// 用户所得 + /// + public double db_userpoint { get; set; } + + /// + /// 是否是plus + /// + public plusStatus plus { get; set; } + + private string _robotname; + /// + /// 机器人账号 + /// + public string robotname + { + get { return _robotname; } + set { if (string.IsNullOrEmpty(value)) _robotname = string.Empty; else _robotname = value; } + } + + /// + /// 机器人昵称 + /// + public string robotnick { get; set; } + + private string _username; + /// + /// 用户账号 + /// + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + /// + /// 用户昵称 + /// + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + public long db_userid { get; set; } + /// + /// 商品标题 + /// + public string skuName { get; set; } + /// + /// 商品编码 + /// + public long skuId { get; set; } + /// + /// 商品单价 + /// + public double price { get; set; } + /// + /// 购买数量 + /// + public long skuNum { get; set; } + /// + /// 已退货数量 + /// + public long skuReturnNum { get; set; } + /// + /// 冻结时间 + /// + public DateTime db_endtime { get; set; } + /// + /// 联盟账号 + /// + public string db_cpsname { get; set; } + /// + /// 联盟昵称 + /// + public string db_cpsnick { get; set; } + /// + /// 推广位 + /// + public long positionId { get; set; } + + } + + public enum plusStatus + { + 否 = 0, + 是 = 1 + } + +} diff --git a/FLSystem/Forms/cps_order_jingdong.resx b/FLSystem/Forms/cps_order_jingdong.resx new file mode 100644 index 0000000..2396863 --- /dev/null +++ b/FLSystem/Forms/cps_order_jingdong.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_kuaishou.Designer.cs b/FLSystem/Forms/cps_order_kuaishou.Designer.cs new file mode 100644 index 0000000..2a2717e --- /dev/null +++ b/FLSystem/Forms/cps_order_kuaishou.Designer.cs @@ -0,0 +1,863 @@ +namespace FLSystem.Forms +{ + partial class cps_order_kuaishou + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_order_kuaishou)); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.解绑ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.用户个人信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.所有阿里妈妈订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有多多进宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有京东联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有抖音联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有苏宁易购订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有快手联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.订单状态操作ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.冻结延期ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.立即结算ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.立即失效ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键结算ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.重新计算未结算订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn28 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.checkBox_isOld = new System.Windows.Forms.CheckBox(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + this.SuspendLayout(); + // + // gridColumn8 + // + this.gridColumn8.Caption = "客户所得"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn8.FieldName = "db_userpoint"; + this.gridColumn8.MinWidth = 23; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 5; + this.gridColumn8.Width = 87; + // + // gridColumn7 + // + this.gridColumn7.Caption = "佣金"; + this.gridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn7.FieldName = "estimatedIncome"; + this.gridColumn7.MinWidth = 23; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + this.gridColumn7.Width = 87; + // + // gridColumn9 + // + this.gridColumn9.Caption = "付款金额"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn9.FieldName = "paymentFee"; + this.gridColumn9.MinWidth = 23; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 3; + this.gridColumn9.Width = 87; + // + // gridColumn14 + // + this.gridColumn14.Caption = "状态"; + this.gridColumn14.FieldName = "db_status"; + this.gridColumn14.MinWidth = 23; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 2; + this.gridColumn14.Width = 87; + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(460, 46); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(62, 18); + this.checkBox1.TabIndex = 9; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(522, 53); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(162, 22); + this.dateTimePicker2.TabIndex = 8; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "不限状态"; + this.comboBoxEdit2.Location = new System.Drawing.Point(350, 28); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "不限状态", + "订单创建", + "订单付款", + "订单失效", + "订单维权中", + "全额退款", + "部分退款", + "订单冻结", + "订单结算"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(93, 20); + this.comboBoxEdit2.TabIndex = 7; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(31, 48); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(706, 37); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(89, 31); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(242, 45); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "订单编号", + "商品编号", + "商品标题", + "客户编号", + "客户账号", + "客户昵称", + "推广位ID", + "联盟账号", + "联盟昵称", + "未绑定用户"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(89, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.Tag = "comboboxedit"; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "oid"; + this.gridColumn4.MinWidth = 140; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 140; + // + // gridColumn15 + // + this.gridColumn15.Caption = "创建时间"; + this.gridColumn15.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn15.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn15.FieldName = "createTime"; + this.gridColumn15.MinWidth = 23; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 142; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(522, 26); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(162, 22); + this.dateTimePicker1.TabIndex = 3; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = ""; + this.comboBoxEdit3.Location = new System.Drawing.Point(350, 55); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(93, 20); + this.comboBoxEdit3.TabIndex = 7; + // + // gridColumn21 + // + this.gridColumn21.Caption = "一级提成"; + this.gridColumn21.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn21.FieldName = "db_point"; + this.gridColumn21.MinWidth = 23; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 6; + this.gridColumn21.Width = 87; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(7, 98); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(948, 498); + this.gridControl1.TabIndex = 6; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改toolStripMenuItem1, + this.解绑ToolStripMenuItem, + this.用户个人信息ToolStripMenuItem, + this.订单状态操作ToolStripMenuItem, + this.刷新ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.一键结算ToolStripMenuItem, + this.重新计算未结算订单ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 180); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 修改toolStripMenuItem1 + // + this.修改toolStripMenuItem1.Name = "修改toolStripMenuItem1"; + this.修改toolStripMenuItem1.Size = new System.Drawing.Size(184, 22); + this.修改toolStripMenuItem1.Text = "绑定"; + this.修改toolStripMenuItem1.Click += new System.EventHandler(this.修改toolStripMenuItem1_Click); + // + // 解绑ToolStripMenuItem + // + this.解绑ToolStripMenuItem.Name = "解绑ToolStripMenuItem"; + this.解绑ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.解绑ToolStripMenuItem.Text = "解绑"; + this.解绑ToolStripMenuItem.Click += new System.EventHandler(this.解绑ToolStripMenuItem_Click); + // + // 用户个人信息ToolStripMenuItem + // + this.用户个人信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看用户信息ToolStripMenuItem, + this.toolStripSeparator1, + this.所有阿里妈妈订单ToolStripMenuItem, + this.所有多多进宝订单ToolStripMenuItem, + this.所有京东联盟订单ToolStripMenuItem, + this.所有唯品联盟订单ToolStripMenuItem, + this.所有抖音联盟订单ToolStripMenuItem, + this.所有苏宁易购订单ToolStripMenuItem, + this.所有快手联盟订单ToolStripMenuItem, + this.toolStripSeparator2, + this.积分日志ToolStripMenuItem, + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.用户个人信息ToolStripMenuItem.Name = "用户个人信息ToolStripMenuItem"; + this.用户个人信息ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.用户个人信息ToolStripMenuItem.Text = "用户个人信息"; + // + // 查看用户信息ToolStripMenuItem + // + this.查看用户信息ToolStripMenuItem.Name = "查看用户信息ToolStripMenuItem"; + this.查看用户信息ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.查看用户信息ToolStripMenuItem.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem.Click += new System.EventHandler(this.查看用户信息ToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(169, 6); + // + // 所有阿里妈妈订单ToolStripMenuItem + // + this.所有阿里妈妈订单ToolStripMenuItem.Name = "所有阿里妈妈订单ToolStripMenuItem"; + this.所有阿里妈妈订单ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.所有阿里妈妈订单ToolStripMenuItem.Text = "所有阿里妈妈订单"; + this.所有阿里妈妈订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有多多进宝订单ToolStripMenuItem + // + this.所有多多进宝订单ToolStripMenuItem.Name = "所有多多进宝订单ToolStripMenuItem"; + this.所有多多进宝订单ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.所有多多进宝订单ToolStripMenuItem.Text = "所有多多进宝订单"; + this.所有多多进宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有京东联盟订单ToolStripMenuItem + // + this.所有京东联盟订单ToolStripMenuItem.Name = "所有京东联盟订单ToolStripMenuItem"; + this.所有京东联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.所有京东联盟订单ToolStripMenuItem.Text = "所有京东联盟订单"; + this.所有京东联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有唯品联盟订单ToolStripMenuItem + // + this.所有唯品联盟订单ToolStripMenuItem.Name = "所有唯品联盟订单ToolStripMenuItem"; + this.所有唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.所有唯品联盟订单ToolStripMenuItem.Text = "所有唯品联盟订单"; + this.所有唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有抖音联盟订单ToolStripMenuItem + // + this.所有抖音联盟订单ToolStripMenuItem.Name = "所有抖音联盟订单ToolStripMenuItem"; + this.所有抖音联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.所有抖音联盟订单ToolStripMenuItem.Text = "所有抖音联盟订单"; + this.所有抖音联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有苏宁易购订单ToolStripMenuItem + // + this.所有苏宁易购订单ToolStripMenuItem.Name = "所有苏宁易购订单ToolStripMenuItem"; + this.所有苏宁易购订单ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.所有苏宁易购订单ToolStripMenuItem.Text = "所有苏宁易购订单"; + this.所有苏宁易购订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有快手联盟订单ToolStripMenuItem + // + this.所有快手联盟订单ToolStripMenuItem.Name = "所有快手联盟订单ToolStripMenuItem"; + this.所有快手联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.所有快手联盟订单ToolStripMenuItem.Text = "所有快手联盟订单"; + this.所有快手联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(169, 6); + // + // 积分日志ToolStripMenuItem + // + this.积分日志ToolStripMenuItem.Name = "积分日志ToolStripMenuItem"; + this.积分日志ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.积分日志ToolStripMenuItem.Text = "积分日志"; + this.积分日志ToolStripMenuItem.Click += new System.EventHandler(this.积分日志ToolStripMenuItem_Click); + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分日志ToolStripMenuItem_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(172, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分日志ToolStripMenuItem_Click); + // + // 订单状态操作ToolStripMenuItem + // + this.订单状态操作ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.冻结延期ToolStripMenuItem, + this.立即结算ToolStripMenuItem1, + this.立即失效ToolStripMenuItem1}); + this.订单状态操作ToolStripMenuItem.Name = "订单状态操作ToolStripMenuItem"; + this.订单状态操作ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.订单状态操作ToolStripMenuItem.Text = "订单状态操作"; + // + // 冻结延期ToolStripMenuItem + // + this.冻结延期ToolStripMenuItem.Name = "冻结延期ToolStripMenuItem"; + this.冻结延期ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.冻结延期ToolStripMenuItem.Text = "冻结延期"; + this.冻结延期ToolStripMenuItem.Click += new System.EventHandler(this.冻结延期ToolStripMenuItem_Click); + // + // 立即结算ToolStripMenuItem1 + // + this.立即结算ToolStripMenuItem1.Name = "立即结算ToolStripMenuItem1"; + this.立即结算ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即结算ToolStripMenuItem1.Text = "立即结算"; + this.立即结算ToolStripMenuItem1.Click += new System.EventHandler(this.立即结算ToolStripMenuItem1_Click); + // + // 立即失效ToolStripMenuItem1 + // + this.立即失效ToolStripMenuItem1.Name = "立即失效ToolStripMenuItem1"; + this.立即失效ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即失效ToolStripMenuItem1.Text = "立即失效"; + this.立即失效ToolStripMenuItem1.Click += new System.EventHandler(this.立即失效ToolStripMenuItem1_Click); + // + // 刷新ToolStripMenuItem + // + this.刷新ToolStripMenuItem.Name = "刷新ToolStripMenuItem"; + this.刷新ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.刷新ToolStripMenuItem.Text = "刷新"; + this.刷新ToolStripMenuItem.Click += new System.EventHandler(this.刷新ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // 一键结算ToolStripMenuItem + // + this.一键结算ToolStripMenuItem.Name = "一键结算ToolStripMenuItem"; + this.一键结算ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.一键结算ToolStripMenuItem.Text = "一键结算(隐藏)"; + this.一键结算ToolStripMenuItem.Visible = false; + this.一键结算ToolStripMenuItem.Click += new System.EventHandler(this.一键结算ToolStripMenuItem_Click); + // + // 重新计算未结算订单ToolStripMenuItem + // + this.重新计算未结算订单ToolStripMenuItem.Name = "重新计算未结算订单ToolStripMenuItem"; + this.重新计算未结算订单ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.重新计算未结算订单ToolStripMenuItem.Text = "重新计算未结算订单"; + this.重新计算未结算订单ToolStripMenuItem.Visible = false; + this.重新计算未结算订单ToolStripMenuItem.Click += new System.EventHandler(this.重新计算未结算订单ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn14, + this.gridColumn9, + this.gridColumn7, + this.gridColumn8, + this.gridColumn21, + this.gridColumn20, + this.gridColumn25, + this.gridColumn19, + this.gridColumn6, + this.gridColumn5, + this.gridColumn1, + this.gridColumn3, + this.gridColumn10, + this.gridColumn11, + this.gridColumn18, + this.gridColumn27, + this.gridColumn26, + this.gridColumn2, + this.gridColumn16, + this.gridColumn13, + this.gridColumn28}); + this.gridView1.DetailHeight = 408; + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 58; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText_1); + // + // gridColumn20 + // + this.gridColumn20.Caption = "二级提成"; + this.gridColumn20.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn20.FieldName = "db_point"; + this.gridColumn20.MinWidth = 23; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 7; + this.gridColumn20.Width = 87; + // + // gridColumn25 + // + this.gridColumn25.Caption = "三级提成"; + this.gridColumn25.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn25.FieldName = "db_point"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.OptionsColumn.AllowEdit = false; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 8; + // + // gridColumn19 + // + this.gridColumn19.Caption = "群负责人提成"; + this.gridColumn19.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn19.FieldName = "db_point"; + this.gridColumn19.MinWidth = 23; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 9; + this.gridColumn19.Width = 87; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.MinWidth = 23; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 10; + this.gridColumn6.Width = 117; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户名"; + this.gridColumn5.FieldName = "username"; + this.gridColumn5.MinWidth = 140; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 11; + this.gridColumn5.Width = 140; + // + // gridColumn1 + // + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "itemTitle"; + this.gridColumn1.MinWidth = 23; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 12; + this.gridColumn1.Width = 408; + // + // gridColumn3 + // + this.gridColumn3.Caption = "商品编号"; + this.gridColumn3.FieldName = "itemId"; + this.gridColumn3.MinWidth = 140; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 13; + this.gridColumn3.Width = 140; + // + // gridColumn10 + // + this.gridColumn10.Caption = "商品单价"; + this.gridColumn10.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn10.FieldName = "itemPrice"; + this.gridColumn10.MinWidth = 23; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 14; + this.gridColumn10.Width = 87; + // + // gridColumn11 + // + this.gridColumn11.Caption = "购买数量"; + this.gridColumn11.FieldName = "num"; + this.gridColumn11.MinWidth = 23; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 15; + this.gridColumn11.Width = 87; + // + // gridColumn18 + // + this.gridColumn18.Caption = "冻结时间"; + this.gridColumn18.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn18.FieldName = "db_endtime"; + this.gridColumn18.MinWidth = 23; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 16; + this.gridColumn18.Width = 87; + // + // gridColumn27 + // + this.gridColumn27.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn27.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.Caption = "机器人昵称"; + this.gridColumn27.FieldName = "robotnick"; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.OptionsColumn.AllowEdit = false; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 17; + // + // gridColumn26 + // + this.gridColumn26.Caption = "机器人账号"; + this.gridColumn26.FieldName = "robotname"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 18; + // + // gridColumn2 + // + this.gridColumn2.Caption = "联盟账号"; + this.gridColumn2.FieldName = "db_cpsname"; + this.gridColumn2.MinWidth = 23; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 19; + this.gridColumn2.Width = 117; + // + // gridColumn16 + // + this.gridColumn16.Caption = "联盟昵称"; + this.gridColumn16.FieldName = "db_cpsnick"; + this.gridColumn16.MinWidth = 23; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 20; + this.gridColumn16.Width = 117; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "推广位"; + this.gridColumn13.FieldName = "cpsPid"; + this.gridColumn13.MinWidth = 140; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 21; + this.gridColumn13.Width = 140; + // + // gridColumn28 + // + this.gridColumn28.Caption = "子订单号"; + this.gridColumn28.FieldName = "oid2"; + this.gridColumn28.MinWidth = 140; + this.gridColumn28.Name = "gridColumn28"; + this.gridColumn28.Visible = true; + this.gridColumn28.VisibleIndex = 22; + this.gridColumn28.Width = 140; + // + // checkBox_isOld + // + this.checkBox_isOld.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox_isOld.AutoSize = true; + this.checkBox_isOld.Checked = true; + this.checkBox_isOld.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_isOld.Location = new System.Drawing.Point(814, 39); + this.checkBox_isOld.Name = "checkBox_isOld"; + this.checkBox_isOld.Size = new System.Drawing.Size(134, 32); + this.checkBox_isOld.TabIndex = 11; + this.checkBox_isOld.Text = "搜索一年以内的数据\r\n查询速度慢的请勾选"; + this.checkBox_isOld.UseVisualStyleBackColor = true; + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(69, 45); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(152, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Tag = "textedit"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 604); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(955, 38); + this.pageControl1.TabIndex = 8; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.checkBox_isOld); + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(955, 94); + this.groupControl1.TabIndex = 7; + this.groupControl1.Text = "搜索条件"; + // + // cps_order_kuaishou + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.groupControl1); + this.Name = "cps_order_kuaishou"; + this.Size = new System.Drawing.Size(955, 642); + this.Load += new System.EventHandler(this.cps_order_kuaishou_Load); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.GridControl gridControl1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 修改toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 解绑ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 用户个人信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 所有阿里妈妈订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有多多进宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有京东联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有唯品联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有抖音联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有苏宁易购订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 订单状态操作ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 冻结延期ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 立即结算ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 立即失效ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 刷新ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 一键结算ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 重新计算未结算订单ToolStripMenuItem; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private System.Windows.Forms.CheckBox checkBox_isOld; + private DevExpress.XtraEditors.TextEdit textEdit1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn28; + private System.Windows.Forms.ToolStripMenuItem 所有快手联盟订单ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/cps_order_kuaishou.cs b/FLSystem/Forms/cps_order_kuaishou.cs new file mode 100644 index 0000000..318d6ae --- /dev/null +++ b/FLSystem/Forms/cps_order_kuaishou.cs @@ -0,0 +1,1073 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using FLSystem.Events; +using Newtonsoft.Json; +using SqlSugar; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class cps_order_kuaishou : DevExpress.XtraEditors.XtraUserControl + { + + public cps_order_kuaishou(string textedit = "") + { + InitializeComponent(); + this.textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 5; + this.dateTimePicker1.Value = DateTime.Parse(DateTime.Today.AddDays(-30).ToString("yyyy-MM-01")); + this.dateTimePicker2.Value = DateTime.Parse(DateTime.Now.AddDays(30).ToString("yyyy-MM-dd HH:mm:ss")); + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + this.checkBox1.Checked = false; + + #region 增加所有的机器人账号 + + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + comboBoxEdit3.SelectedIndex = 0; + + #endregion + + try + { + this.pageControl1.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var isOld = true; + List result = null; + //List conModels = new List(); + var sqlwhere = string.Empty; + if (this.checkBox1.Checked) + { + isOld = false; + + sqlwhere += + $" and '{this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss")}' <= payTime and payTime <= '{this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss")}'"; + + //conModels.Add(new ConditionalModel() { FieldName = "payTime", ConditionalType = ConditionalType.GreaterThanOrEqual, FieldValue = this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + //conModels.Add(new ConditionalModel() { FieldName = "payTime", ConditionalType = ConditionalType.LessThanOrEqual, FieldValue = this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + } + + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword) || comboBoxEdit1.Text == "未绑定用户") + { + + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + //conModels.Add(new ConditionalModel() { FieldName = "orderId", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and oid = '{keyword}'"; + break; + case "商品编号": + //conModels.Add(new ConditionalModel() { FieldName = "skuId", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and itemId = '{keyword}'"; + break; + case "商品标题": + //conModels.Add(new ConditionalModel() { FieldName = "skuname", ConditionalType = ConditionalType.Like, FieldValue = keyword }); + sqlwhere += $" and itemTitle like '%{keyword}%'"; + break; + case "客户编号": + //conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and db_userid = '{keyword}'"; + break; + case "客户账号": + var ids = FindMemberIdByKey("username", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + //conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", ids) }); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + + break; + case "客户昵称": + ids = FindMemberIdByKey("usernick", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + //conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", ids) }); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + + break; + case "推广位ID": + //conModels.Add(new ConditionalModel() { FieldName = "positionId", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and cpspid = '{keyword}'"; + break; + case "联盟账号": + //conModels.Add(new ConditionalModel() { FieldName = "db_cpsname", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and db_cpsname = '{keyword}'"; + break; + case "联盟昵称": + //conModels.Add(new ConditionalModel() { FieldName = "db_cpsnick", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + sqlwhere += $" and db_cpsnick = '{keyword}'"; + break; + case "未绑定用户": + //conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.Equal, FieldValue = "0" }); + sqlwhere += $" and db_userid = '0'"; + break; + } + } + + var status = this.comboBoxEdit2.SelectedIndex == 0 + ? SystemOrderStatus.订单未知 + : Util.ConvertEnum(this.comboBoxEdit2.Text); + if (status != SystemOrderStatus.订单未知) + //conModels.Add(new ConditionalModel() { FieldName = "db_status", ConditionalType = ConditionalType.Equal, FieldValue = ((int)status).ToString() }); + sqlwhere += $" and db_status = '{((int)status).ToString()}'"; + if (this.comboBoxEdit3.SelectedIndex != 0) + //conModels.Add(new ConditionalModel() { FieldName = "db_robotname", ConditionalType = ConditionalType.Equal, FieldValue = this.comboBoxEdit3.Text.Trim() }); + sqlwhere += $" and db_robotname = '{comboBoxEdit3.Text.Trim()}'"; + + //总记录数 + int totalNumber = 0; + + if (isOld && checkBox_isOld.Checked) + { + sqlwhere += + $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= payTime"; + } + + + //result = session.Queryable() + //.Where(conModels) + //.OrderBy(o => o.id, OrderByType.Desc); + //.ToPageList(index, pagesize, ref totalNumber); + sqlwhere += $" order by id desc"; + + var getCount = + session.Find("select count(*) from fl_order_kuaishou where 1=1 " + sqlwhere); + if (getCount != null && getCount.Count != 0) + totalNumber = getCount[0]; + + sqlwhere += $" limit {(index - 1) * pagesize},{pagesize}"; + + var resultTmp = + session.Find("select * from fl_order_kuaishou where 1=1 " + sqlwhere); + + result = new List(); + foreach (var o in resultTmp) + { + result.Add(new view_cps_order_kuaishou + { + id = o.id, + oid = o.oid, + cpsPid = o.cpsPid, + createTime = o.createTime, + estimatedIncome = o.estimatedIncome, + itemId = o.itemId, + itemPrice = o.itemPrice, + itemTitle = o.itemTitle, + num = o.num, + oid2 = o.oid2, + paymentFee = o.paymentFee, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + db_userpoint = o.db_userpoint, + robotname = o.db_robotname, + db_userid = o.db_userid + }); + } + + if (result.Count != 0) + { + #region 附加用户 + + var bindUsersList = result.Where(f => f.db_userid != 0).Select(f => f.db_userid.ToString()) + .ToList(); + var memberData = new List(); + if (bindUsersList != null && bindUsersList.Count != 0) + memberData = session.Queryable().Where(new List() + { + new ConditionalModel() + { + FieldName = "id", ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", bindUsersList) + } + }).ToList(); + + int count = 1; + foreach (var member in memberData) + { + count++; + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(50); + var items = result.Where(f => f.db_userid == member.id).ToList(); + foreach (var item in items) + { + item.usernick = member.usernick; + item.username = member.username; + } + } + + #endregion + + #region 附加机器人信息 + + var robotList = result.Where(f => !string.IsNullOrWhiteSpace(f.robotname)) + .GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + var robotData = session.FindRobots().Where(f => robotList.Contains(f.name)).ToList(); + foreach (var robot in robotData) + { + var items = result.Where(f => f.robotname == robot.name).ToList(); + foreach (var item in items) + { + item.robotnick = robot.nick; + } + } + + #endregion + + } + + return new UI.Framework.Controls.PageControl.SerchResult() + { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + + return null; + }, this.gridControl1, 50, false, true); + } + catch (Exception ex) + { + if (!this.IsDisposed) + this.UpdateUI(() => { BaseForm.ShowError(ex); }); + } + + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + + private void cps_order_kuaishou_Load(object sender, EventArgs e) + { + simpleButton1_Click(this.simpleButton1, null); + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + /// + /// 代理委托更新UI + /// + /// + protected delegate void DelegateUpdateUI(Action act); + + /// + /// 代理委托更新UI + /// + /// + protected void UpdateUI(Action act) + { + if (!InvokeRequired) + { + act.Invoke(); + } + else + { + DelegateUpdateUI delegateUpdateUI = new DelegateUpdateUI(UpdateUI); + Invoke(delegateUpdateUI, act); + } + } + + + /// + /// 条件查询(用户账号/用户昵称),模糊查询,获取用户的id + /// + /// 查询的字段 + /// 模糊的关键词 + /// + private List FindMemberIdByKey(string type, string keyword) + { + try + { + var session = ApiClient.GetSession(); + return session.Find($"select id from fl_member_info where {type} like '%{keyword}%'") + .Select(f => f.ToString()).ToList(); + } + catch (Exception ex) + { + throw ex; + } + } + + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("cps_type") && e.Commons.ContainsKey("username")) + { + var cps_type = (CpsType)int.Parse(e.Commons["cps_type"].ToString()); + if (cps_type == CpsType.快手联盟) + { + textEdit1.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 5; + comboBoxEdit3.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + checkBox1.Checked = false; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void gridView1_CustomDrawRowIndicator(object sender, + DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private void gridView1_CustomColumnDisplayText_1(object sender, + DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "软件状态": + e.DisplayText = Util.ConvertEnum(int.Parse(e.Value.ToString())).ToString(); + break; + case "一级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardone"].ToString(); + break; + case "二级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardtwo"].ToString(); + break; + case "三级提成": + { + var result = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower()); + e.DisplayText = (result != null && result.ContainsKey("awardthree")) + ? result["awardthree"].ToString() + : "0"; + } + break; + case "群负责人提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardcreate"].ToString(); + break; + } + } + + private void 修改toolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_kuaishou; + var db_status = row.db_status; + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || + db_status == SystemOrderStatus.全额退款 || + db_status == SystemOrderStatus.部分退款) throw new Exception("该订单状态为已完结,不允许修改!"); + + var session = ApiClient.GetSession(); + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null) + { + if (member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + } + + select_member_form select_form = new select_member_form(); + select_form.ShowDialog(); + if (select_form.fl_member_info != null) + { + var kuaishou = session.FindSingle("id = @id", new { id = row.id }); + if (kuaishou != null) + { + if (kuaishou.db_robottype == 0) + kuaishou.db_robottype = select_form.fl_member_info.robot_type; + if (string.IsNullOrWhiteSpace(kuaishou.db_robotname)) + kuaishou.db_robotname = select_form.fl_member_info.robot_name; + + var itempoint = session.FindItemPoint(select_form.fl_member_info, kuaishou.estimatedIncome, + kuaishou.num, CpsType.快手联盟); + if (itempoint != null) + { + kuaishou.db_point = HttpHelper.ObjectToJson(itempoint); + kuaishou.db_userpoint = itempoint.UserPoint; + } + + kuaishou.db_userid = select_form.fl_member_info.id; + session.SaveOrUpdate(kuaishou); + + //更新显示值 + row.db_userid = select_form.fl_member_info.id; + row.username = select_form.fl_member_info.username; + row.usernick = select_form.fl_member_info.usernick; + row.db_point = kuaishou.db_point; + + select_form.fl_member_info.bind_order++; + + #region 首次付款时间 + + try + { + var record = session.FindStatisticsRecord(select_form.fl_member_info.id); + if (record == null) + { + record = new fl_statistics_record() + { + uid = select_form.fl_member_info.id, + ex2 = 0, + ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now), + ex5 = HttpExtend.GetTimeStamp(kuaishou.createTime) + }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + record.ex5 = CsharpHttpHelper.HttpExtend.GetTimeStamp(kuaishou.createTime); + session.Saveable(record).ExecuteCommand(); + } + } + catch (Exception) + { + } + + #endregion + + session.UpdateMemberGroup(select_form.fl_member_info); + + #region 获取查询时的比例 + + var query_item = session.FindSingle( + "userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id", + new + { + userid = kuaishou.db_userid, + itemid = kuaishou.itemId, + adzoneid = kuaishou.cpsPid, + time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") + }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (kuaishou.id == 0) + session.SaveOrUpdate(kuaishou); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = kuaishou.id, + createtime = DateTime.Now, + cpstype = CpsType.快手联盟 + }; + LogHelper.GetSingleObj().Error("历史查询记录4", JsonConvert.SerializeObject(queryRatioHist)); + session.SaveOrUpdate(queryRatioHist); + } + + #endregion + + } + } + + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 解绑ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_kuaishou; + var db_status = row.db_status; + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || + db_status == SystemOrderStatus.全额退款 || + db_status == SystemOrderStatus.部分退款) throw new Exception("该订单状态为已完结,不允许解绑!"); + + var session = ApiClient.GetSession(); + + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null && member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + + session.ExcuteSQL("delete from fl_query_hist where itemid = @num_iid", + new { num_iid = row.itemId }); + session.ExcuteSQL("update fl_order_kuaishou set db_userid = @userid where id=@id", + new { id = row.id, userid = 0 }); + session.ExcuteSQL("delete from fl_query_ratio_hist where db_orderid=@id", new { id = row.id }); + + //更新显示值 + row.db_userid = 0; + row.username = string.Empty; + row.usernick = string.Empty; + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 查看用户信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = gridView1.GetRowCellValue(rows[0], "username").ToString(); //获取列的数据; + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary(); + common["control_name"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString(); //获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", "").Replace("所有", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + private void 积分日志ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString(); //获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + var common = new Dictionary(); + common["control_name"] = "提现管理"; + common["query_type"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void 冻结延期ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要延长冻结选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == + DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_kuaishou; + var db_status = row.db_status; + + if (db_status != SystemOrderStatus.订单冻结) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + + setting_endtime_form endtime_form = new setting_endtime_form(row.db_endtime); + endtime_form.ShowDialog(); + if (endtime_form.newtime == DateTime.MinValue) return; + + var kuaishou = session.FindSingle("id = @id", new { id = row.id }); + if (endtime_form.newtime != row.db_endtime) + { + kuaishou.db_endtime = endtime_form.newtime; + session.Updateable(kuaishou).ExecuteCommand(); + } + + row.db_endtime = endtime_form.newtime; //更新显示值 + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即结算ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要结算选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == + DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_kuaishou; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单创建 || + db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || + db_status == SystemOrderStatus.部分退款) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var kuaishou = session.FindSingle( + "oid = @oid and oid2 = @oid2 and itemId = @itemId", + new { oid = row.oid, oid2 = row.oid2, itemId = row.itemId }); + + if (kuaishou == null) throw new Exception("数据查询失败,请稍后重试"); + kuaishou.settlementSuccessTime = DateTime.Now.AddSeconds(-2); + kuaishou.cpsOrderStatus = CpsOrderStatus.已结算; + kuaishou.db_endtime = DateTime.Now; + kuaishou.db_status = SystemOrderStatus.订单冻结; + var task = TimerTask.GetTimer() as DownKuaiShouTimer; + var notices = new List(); + task.UpdateOrder(kuaishou, session, notices); + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_kuaishou; + tasks.Add(item); + } + + //更新显示值 + row.db_status = SystemOrderStatus.订单结算; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即失效ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要失效选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_kuaishou; + var db_status = row.db_status; + + var session = ApiClient.GetSession(); + //var kuaishou = session.FindSingle("orderId = @orderId", new { orderId = row.orderId }); + var kuaishou = session.FindSingle("id = @id", new { id = row.id }); + if (kuaishou == null) throw new Exception("数据查询失败,请稍后重试"); + + var flag = false; + var notices = new List(); + if (db_status == SystemOrderStatus.订单结算) + flag = true; + else if (kuaishou.IsFinish()) + throw new Exception($"选中订单:{db_status},不予操作"); + + kuaishou.settlementSuccessTime = DateTime.Now.AddSeconds(-2); + kuaishou.cpsOrderStatus = CpsOrderStatus.已失效; + kuaishou.db_endtime = DateTime.Now; + kuaishou.db_status = SystemOrderStatus.订单失效; + var task = TimerTask.GetTimer() as DownKuaiShouTimer; + + if (!flag) + task.UpdateOrder(kuaishou, session, notices); + else + { + var itempoint = HttpHelper.JsonToObject(kuaishou.db_point) as ItemPoint; + new OrderHelper().DeductKuaiShouOrderPoint(notices, kuaishou, itempoint); + session.SaveOrUpdate(kuaishou); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_kuaishou; + tasks.Add(item); + } + row.db_status = SystemOrderStatus.订单失效; + row.db_endtime = DateTime.Now; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 一键结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (MessageBox.Show("确定结算所有该所有的订单吗", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + var orders = ApiClient.GetSession().Find("select * from fl_order_kuaishou where db_userid != 0 and (db_status = @db_status1 or db_status = @db_status2)", new { db_status1 = SystemOrderStatus.订单付款, db_status2 = SystemOrderStatus.订单冻结 }); + + if (orders.Count != 0) + { + Task.Run(() => + { + var session = ApiClient.GetSession(); + try + { + var task = TimerTask.GetTimer() as DownKuaiShouTimer; + var notices = new List(); + foreach (var order in orders) + { + + tokenSource.Token.ThrowIfCancellationRequested(); + order.settlementSuccessTime = DateTime.Now.AddSeconds(-2); + order.cpsOrderStatus = CpsOrderStatus.已失效; + order.db_endtime = DateTime.Now; + order.db_status = SystemOrderStatus.订单冻结; + + //var task = TimerTask.GetTimer() as DownkuaishouTimer; + //var notices = new List(); + //task.UpdateOrder(kuaishou, session, notices); + + //var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + //foreach (var item in notices) + //{ + // if (item.Member == null) continue; + // var order = item.Order as fl_order_kuaishou; + // tasks.Add(item); + //} + + task.UpdateOrder(order, session, notices); + } + + //var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + + //foreach (var item in notices) + //{ + // tokenSource.Token.ThrowIfCancellationRequested(); + // if (item.Member == null) continue; + // if (item.Order is fl_order_kuaishou) + // tasks.Add(item); + //} + XtraMessageBox.Show($"一键结算成功,一共结算{orders.Count}笔订单!", "温馨提示", MessageBoxButtons.OK); + } + catch (Exception) + { } + }, tokenSource.Token); + } + else + XtraMessageBox.Show($"当前无可结算的订单!", "温馨提示", MessageBoxButtons.OK); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 重新计算未结算订单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var db = ApiClient.GetSession(); + var orders = db.Queryable().Where(f => + f.db_userid != 0 && (f.db_status == SystemOrderStatus.订单付款 || + f.db_status == SystemOrderStatus.订单冻结 || + f.db_status == SystemOrderStatus.订单维权中)).ToList(); + EventClient.OnEvent("", $"快手需要重新计算的订单数:{orders.Count}"); + + foreach (var order in orders) + { + var member = db.FindMemberInfoById(order.db_userid); + var itempoint = db.FindItemPoint(member, order.estimatedIncome, order.num, CpsType.快手联盟); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + + db.SaveOrUpdate(order); + EventClient.OnEvent("", $"快手单号:{order.oid}-{order.oid2},重新计算完成"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"快手重新计算异常:{ex.Message}"); + } + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + this.用户个人信息ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "username") != null; + this.冻结延期ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "db_status").ToString() == "订单冻结"; + } + else + e.Cancel = true; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var info = this.gridView1.GetRow(rows[0]) as view_cps_order_kuaishou; + if (XtraMessageBox.Show($@"您确定要删除选中数据嘛? +{info.itemTitle}", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_order_kuaishou where id=" + info.id); + } + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit1.SelectedIndex == 0 || comboBoxEdit1.SelectedIndex == 10) + { + this.textEdit1.Enabled = false; + this.textEdit1.Text = ""; + } + else this.textEdit1.Enabled = true; + } + } + + public class view_cps_order_kuaishou + { + /// + /// id + /// + public long id { get; set; } + /// + /// 创建时间 + /// + public DateTime createTime { get; set; } + /// + /// 订单父id + /// + public long oid { get; set; } + /// + /// 子订单号 + /// + public long oid2 { get; set; } + /// + /// 订单状态 + /// + public SystemOrderStatus db_status { get; set; } + /// + /// 付款金额 + /// + public double paymentFee { get; set; } + /// + /// 佣金 + /// + public double estimatedIncome { get; set; } + /// + /// 积分Json + /// + public string db_point { get; set; } + /// + /// 用户所得 + /// + public double db_userpoint { get; set; } + + private string _robotname; + /// + /// 机器人账号 + /// + public string robotname + { + get { return _robotname; } + set { if (string.IsNullOrEmpty(value)) _robotname = string.Empty; else _robotname = value; } + } + + /// + /// 机器人昵称 + /// + public string robotnick { get; set; } + + private string _username; + /// + /// 用户账号 + /// + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + /// + /// 用户昵称 + /// + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + public long db_userid { get; set; } + /// + /// 商品标题 + /// + public string itemTitle { get; set; } + /// + /// 商品编码 + /// + public long itemId { get; set; } + /// + /// 商品单价 + /// + public double itemPrice { get; set; } + /// + /// 购买数量 + /// + public int num { get; set; } + /// + /// 冻结时间 + /// + public DateTime db_endtime { get; set; } + /// + /// 联盟账号 + /// + public string db_cpsname { get; set; } + /// + /// 联盟昵称 + /// + public string db_cpsnick { get; set; } + /// + /// 推广位 + /// + public string cpsPid { get; set; } + + } + +} diff --git a/FLSystem/Forms/cps_order_kuaishou.resx b/FLSystem/Forms/cps_order_kuaishou.resx new file mode 100644 index 0000000..8a09e09 --- /dev/null +++ b/FLSystem/Forms/cps_order_kuaishou.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_pinduoduo.Designer.cs b/FLSystem/Forms/cps_order_pinduoduo.Designer.cs new file mode 100644 index 0000000..39ed9ba --- /dev/null +++ b/FLSystem/Forms/cps_order_pinduoduo.Designer.cs @@ -0,0 +1,866 @@ +namespace FLSystem.Forms +{ + partial class cps_order_pinduoduo + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_order_pinduoduo)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.checkBox_isOld = new System.Windows.Forms.CheckBox(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.绑定用户ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.解绑ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.用户个人信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.所有阿里妈妈订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有多多进宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有京东联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有抖音联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有苏宁易购订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.订单状态操作ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.冻结延期ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.立即结算ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.立即失效ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键结算ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.重新计算未结算订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.所有快手联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.checkBox_isOld); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(874, 88); + this.groupControl1.TabIndex = 0; + this.groupControl1.Text = "搜索条件"; + // + // checkBox_isOld + // + this.checkBox_isOld.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox_isOld.AutoSize = true; + this.checkBox_isOld.Checked = true; + this.checkBox_isOld.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_isOld.Location = new System.Drawing.Point(737, 35); + this.checkBox_isOld.Name = "checkBox_isOld"; + this.checkBox_isOld.Size = new System.Drawing.Size(134, 32); + this.checkBox_isOld.TabIndex = 14; + this.checkBox_isOld.Text = "搜索一年以内的数据\r\n查询速度慢的请勾选"; + this.checkBox_isOld.UseVisualStyleBackColor = true; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = ""; + this.comboBoxEdit3.Location = new System.Drawing.Point(319, 57); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(86, 20); + this.comboBoxEdit3.TabIndex = 13; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "不限状态"; + this.comboBoxEdit2.Location = new System.Drawing.Point(319, 29); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "不限状态", + "订单创建", + "订单付款", + "订单失效", + "全额退款", + "部分退款", + "订单冻结", + "订单结算"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(86, 20); + this.comboBoxEdit2.TabIndex = 13; + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(422, 42); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(54, 18); + this.checkBox1.TabIndex = 12; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(477, 55); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(161, 22); + this.dateTimePicker2.TabIndex = 11; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(477, 28); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(161, 22); + this.dateTimePicker1.TabIndex = 10; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(35, 43); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(648, 32); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(78, 39); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(222, 41); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "订单编号", + "商品编号", + "商品标题", + "客户编号", + "客户账号", + "客户昵称", + "店铺编码", + "推广位PID", + "联盟账号", + "联盟昵称", + "未绑定用户"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(86, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.Tag = "comboboxedit"; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(79, 40); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(134, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Tag = "textedit"; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(3, 94); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(871, 392); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.绑定用户ToolStripMenuItem, + this.解绑ToolStripMenuItem, + this.用户个人信息ToolStripMenuItem, + this.订单状态操作ToolStripMenuItem, + this.刷新ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.一键结算ToolStripMenuItem, + this.重新计算未结算订单ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 202); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 绑定用户ToolStripMenuItem + // + this.绑定用户ToolStripMenuItem.Name = "绑定用户ToolStripMenuItem"; + this.绑定用户ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.绑定用户ToolStripMenuItem.Text = "绑定"; + this.绑定用户ToolStripMenuItem.Click += new System.EventHandler(this.绑定用户ToolStripMenuItem_Click); + // + // 解绑ToolStripMenuItem + // + this.解绑ToolStripMenuItem.Name = "解绑ToolStripMenuItem"; + this.解绑ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.解绑ToolStripMenuItem.Text = "解绑"; + this.解绑ToolStripMenuItem.Click += new System.EventHandler(this.解绑ToolStripMenuItem_Click); + // + // 用户个人信息ToolStripMenuItem + // + this.用户个人信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看用户信息ToolStripMenuItem, + this.toolStripSeparator2, + this.所有阿里妈妈订单ToolStripMenuItem, + this.所有多多进宝订单ToolStripMenuItem, + this.所有京东联盟订单ToolStripMenuItem, + this.所有唯品联盟订单ToolStripMenuItem, + this.所有抖音联盟订单ToolStripMenuItem, + this.所有苏宁易购订单ToolStripMenuItem, + this.所有快手联盟订单ToolStripMenuItem, + this.toolStripSeparator1, + this.积分日志ToolStripMenuItem, + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.用户个人信息ToolStripMenuItem.Name = "用户个人信息ToolStripMenuItem"; + this.用户个人信息ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.用户个人信息ToolStripMenuItem.Text = "用户个人信息"; + // + // 查看用户信息ToolStripMenuItem + // + this.查看用户信息ToolStripMenuItem.Name = "查看用户信息ToolStripMenuItem"; + this.查看用户信息ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.查看用户信息ToolStripMenuItem.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem.Click += new System.EventHandler(this.查看用户信息ToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6); + // + // 所有阿里妈妈订单ToolStripMenuItem + // + this.所有阿里妈妈订单ToolStripMenuItem.Name = "所有阿里妈妈订单ToolStripMenuItem"; + this.所有阿里妈妈订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有阿里妈妈订单ToolStripMenuItem.Text = "所有阿里妈妈订单"; + this.所有阿里妈妈订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有多多进宝订单ToolStripMenuItem + // + this.所有多多进宝订单ToolStripMenuItem.Name = "所有多多进宝订单ToolStripMenuItem"; + this.所有多多进宝订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有多多进宝订单ToolStripMenuItem.Text = "所有多多进宝订单"; + this.所有多多进宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有京东联盟订单ToolStripMenuItem + // + this.所有京东联盟订单ToolStripMenuItem.Name = "所有京东联盟订单ToolStripMenuItem"; + this.所有京东联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有京东联盟订单ToolStripMenuItem.Text = "所有京东联盟订单"; + this.所有京东联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有唯品联盟订单ToolStripMenuItem + // + this.所有唯品联盟订单ToolStripMenuItem.Name = "所有唯品联盟订单ToolStripMenuItem"; + this.所有唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有唯品联盟订单ToolStripMenuItem.Text = "所有唯品联盟订单"; + this.所有唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有抖音联盟订单ToolStripMenuItem + // + this.所有抖音联盟订单ToolStripMenuItem.Name = "所有抖音联盟订单ToolStripMenuItem"; + this.所有抖音联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有抖音联盟订单ToolStripMenuItem.Text = "所有抖音联盟订单"; + this.所有抖音联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有苏宁易购订单ToolStripMenuItem + // + this.所有苏宁易购订单ToolStripMenuItem.Name = "所有苏宁易购订单ToolStripMenuItem"; + this.所有苏宁易购订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有苏宁易购订单ToolStripMenuItem.Text = "所有苏宁易购订单"; + this.所有苏宁易购订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6); + // + // 积分日志ToolStripMenuItem + // + this.积分日志ToolStripMenuItem.Name = "积分日志ToolStripMenuItem"; + this.积分日志ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.积分日志ToolStripMenuItem.Text = "积分日志"; + this.积分日志ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 订单状态操作ToolStripMenuItem + // + this.订单状态操作ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.冻结延期ToolStripMenuItem, + this.立即结算ToolStripMenuItem1, + this.立即失效ToolStripMenuItem1}); + this.订单状态操作ToolStripMenuItem.Name = "订单状态操作ToolStripMenuItem"; + this.订单状态操作ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.订单状态操作ToolStripMenuItem.Text = "订单状态操作"; + // + // 冻结延期ToolStripMenuItem + // + this.冻结延期ToolStripMenuItem.Name = "冻结延期ToolStripMenuItem"; + this.冻结延期ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.冻结延期ToolStripMenuItem.Text = "冻结延期"; + this.冻结延期ToolStripMenuItem.Click += new System.EventHandler(this.冻结延期ToolStripMenuItem_Click); + // + // 立即结算ToolStripMenuItem1 + // + this.立即结算ToolStripMenuItem1.Name = "立即结算ToolStripMenuItem1"; + this.立即结算ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即结算ToolStripMenuItem1.Text = "立即结算"; + this.立即结算ToolStripMenuItem1.Click += new System.EventHandler(this.立即结算ToolStripMenuItem_Click); + // + // 立即失效ToolStripMenuItem1 + // + this.立即失效ToolStripMenuItem1.Name = "立即失效ToolStripMenuItem1"; + this.立即失效ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即失效ToolStripMenuItem1.Text = "立即失效"; + this.立即失效ToolStripMenuItem1.Click += new System.EventHandler(this.立即失效ToolStripMenuItem_Click); + // + // 刷新ToolStripMenuItem + // + this.刷新ToolStripMenuItem.Name = "刷新ToolStripMenuItem"; + this.刷新ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.刷新ToolStripMenuItem.Text = "刷新"; + this.刷新ToolStripMenuItem.Click += new System.EventHandler(this.刷新ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // 一键结算ToolStripMenuItem + // + this.一键结算ToolStripMenuItem.Name = "一键结算ToolStripMenuItem"; + this.一键结算ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.一键结算ToolStripMenuItem.Text = "一键结算(隐藏)"; + this.一键结算ToolStripMenuItem.Visible = false; + this.一键结算ToolStripMenuItem.Click += new System.EventHandler(this.一键结算ToolStripMenuItem_Click); + // + // 重新计算未结算订单ToolStripMenuItem + // + this.重新计算未结算订单ToolStripMenuItem.Name = "重新计算未结算订单ToolStripMenuItem"; + this.重新计算未结算订单ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.重新计算未结算订单ToolStripMenuItem.Text = "重新计算未结算订单"; + this.重新计算未结算订单ToolStripMenuItem.Visible = false; + this.重新计算未结算订单ToolStripMenuItem.Click += new System.EventHandler(this.重新计算未结算订单ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn14, + this.gridColumn9, + this.gridColumn7, + this.gridColumn8, + this.gridColumn21, + this.gridColumn20, + this.gridColumn19, + this.gridColumn18, + this.gridColumn6, + this.gridColumn5, + this.gridColumn1, + this.gridColumn3, + this.gridColumn10, + this.gridColumn11, + this.gridColumn12, + this.gridColumn2, + this.gridColumn24, + this.gridColumn22, + this.gridColumn16, + this.gridColumn17, + this.gridColumn13, + this.gridColumn23, + this.gridColumn25}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn15 + // + this.gridColumn15.Caption = "创建时间"; + this.gridColumn15.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn15.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn15.FieldName = "order_create_time"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 150; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "order_sn"; + this.gridColumn4.MinWidth = 200; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 200; + // + // gridColumn14 + // + this.gridColumn14.Caption = "状态"; + this.gridColumn14.FieldName = "db_status"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 2; + // + // gridColumn9 + // + this.gridColumn9.Caption = "付款金额"; + this.gridColumn9.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn9.FieldName = "order_amount"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 3; + // + // gridColumn7 + // + this.gridColumn7.Caption = "总佣金"; + this.gridColumn7.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn7.FieldName = "promotion_amount"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + // + // gridColumn8 + // + this.gridColumn8.Caption = "客户所得"; + this.gridColumn8.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn8.FieldName = "endpoint"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 5; + // + // gridColumn21 + // + this.gridColumn21.Caption = "一级提成"; + this.gridColumn21.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn21.FieldName = "db_point"; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 6; + // + // gridColumn20 + // + this.gridColumn20.Caption = "二级提成"; + this.gridColumn20.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn20.FieldName = "db_point"; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 7; + // + // gridColumn19 + // + this.gridColumn19.Caption = "三级提成"; + this.gridColumn19.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn19.FieldName = "db_point"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 8; + // + // gridColumn18 + // + this.gridColumn18.Caption = "群负责人提成"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn18.FieldName = "db_point"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.OptionsColumn.AllowEdit = false; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 9; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 10; + this.gridColumn6.Width = 120; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户名"; + this.gridColumn5.FieldName = "username"; + this.gridColumn5.MinWidth = 120; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 11; + this.gridColumn5.Width = 120; + // + // gridColumn1 + // + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "goods_name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 12; + this.gridColumn1.Width = 350; + // + // gridColumn3 + // + this.gridColumn3.Caption = "商品编号"; + this.gridColumn3.FieldName = "goods_id"; + this.gridColumn3.MinWidth = 120; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 13; + this.gridColumn3.Width = 120; + // + // gridColumn10 + // + this.gridColumn10.Caption = "商品单价"; + this.gridColumn10.FieldName = "goods_price"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 14; + // + // gridColumn11 + // + this.gridColumn11.Caption = "购买数量"; + this.gridColumn11.FieldName = "goods_quantity"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 15; + // + // gridColumn12 + // + this.gridColumn12.Caption = "状态描述"; + this.gridColumn12.FieldName = "order_status_desc"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 16; + // + // gridColumn2 + // + this.gridColumn2.Caption = "冻结时间"; + this.gridColumn2.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn2.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn2.FieldName = "db_endtime"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 17; + // + // gridColumn24 + // + this.gridColumn24.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn24.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn24.Caption = "机器人昵称"; + this.gridColumn24.FieldName = "robotnick"; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 18; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "机器人账号"; + this.gridColumn22.FieldName = "robotname"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 19; + // + // gridColumn16 + // + this.gridColumn16.Caption = "联盟账号"; + this.gridColumn16.FieldName = "db_cpsname"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 20; + this.gridColumn16.Width = 100; + // + // gridColumn17 + // + this.gridColumn17.Caption = "联盟昵称"; + this.gridColumn17.FieldName = "db_cpsnick"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 21; + this.gridColumn17.Width = 100; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "推广位"; + this.gridColumn13.FieldName = "p_id"; + this.gridColumn13.MinWidth = 120; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 22; + this.gridColumn13.Width = 120; + // + // gridColumn23 + // + this.gridColumn23.Caption = "店铺编码"; + this.gridColumn23.FieldName = "mall_id"; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.OptionsColumn.AllowEdit = false; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 23; + // + // gridColumn25 + // + this.gridColumn25.Caption = "订单类型"; + this.gridColumn25.FieldName = "price_compare_status"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 24; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 492); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(874, 32); + this.pageControl1.TabIndex = 2; + // + // 所有快手联盟订单ToolStripMenuItem + // + this.所有快手联盟订单ToolStripMenuItem.Name = "所有快手联盟订单ToolStripMenuItem"; + this.所有快手联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有快手联盟订单ToolStripMenuItem.Text = "所有快手联盟订单"; + this.所有快手联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // cps_order_pinduoduo + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.groupControl1); + this.Name = "cps_order_pinduoduo"; + this.Size = new System.Drawing.Size(874, 524); + this.Load += new System.EventHandler(this.cps_order_pinduoduo_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 刷新ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private System.Windows.Forms.ToolStripMenuItem 绑定用户ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 解绑ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private System.Windows.Forms.ToolStripMenuItem 用户个人信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 所有阿里妈妈订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有多多进宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有京东联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 订单状态操作ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 立即失效ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 立即结算ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 冻结延期ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private System.Windows.Forms.ToolStripMenuItem 一键结算ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private System.Windows.Forms.ToolStripMenuItem 所有唯品联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有抖音联盟订单ToolStripMenuItem; + private System.Windows.Forms.CheckBox checkBox_isOld; + private System.Windows.Forms.ToolStripMenuItem 所有苏宁易购订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 重新计算未结算订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有快手联盟订单ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/cps_order_pinduoduo.cs b/FLSystem/Forms/cps_order_pinduoduo.cs new file mode 100644 index 0000000..6fa648c --- /dev/null +++ b/FLSystem/Forms/cps_order_pinduoduo.cs @@ -0,0 +1,1075 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using FLSystem.Events; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class cps_order_pinduoduo : DevExpress.XtraEditors.XtraUserControl + { + public class view_cps_order_pinduoduo + { + public PinduoduoBiJiaType price_compare_status { get; set; } + public long id { get; set; } + public string goods_name { get; set; } + public string goods_id { get; set; } + public string order_sn { get; set; } + public SystemOrderStatus db_status { get; set; } + + private string _robotname; + /// + /// 机器人账号 + /// + public string robotname + { + get { return _robotname; } + set { if (string.IsNullOrEmpty(value)) _robotname = string.Empty; else _robotname = value; } + } + + /// + /// 机器人昵称 + /// + public string robotnick { get; set; } + + private string _username; + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + + public long db_userid { get; set; } + + public double promotion_amount { get; set; } + + public double order_amount { get; set; } + + public double goods_price { get; set; } + + public int goods_quantity { get; set; } + + public string order_status_desc { get; set; } + + public string p_id { get; set; } + + public DateTime order_create_time { get; set; } + + public string db_point { get; set; } + + public string db_cpsname { get; set; } + public string db_cpsnick { get; set; } + public DateTime db_endtime { get; set; } + public string mall_id { get; set; } + } + public cps_order_pinduoduo(string textedit = "") + { + InitializeComponent(); + this.textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 5; + this.checkBox1.Checked = false; + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + comboBoxEdit3.SelectedIndex = 0; + #endregion + + try + { + this.pageControl1.Bind(delegate (int index, int pagesize) + { + #region xxx + /* + * try + { + var session = ApiClient.GetSession(); + List result = null; + List conModels = new List(); + if (this.checkBox1.Checked) + { + conModels.Add(new ConditionalModel() { FieldName = "order_create_time", ConditionalType = ConditionalType.GreaterThanOrEqual, FieldValue = this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + conModels.Add(new ConditionalModel() { FieldName = "order_create_time", ConditionalType = ConditionalType.LessThanOrEqual, FieldValue = this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + } + + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(this.comboBoxEdit1.Text) || comboBoxEdit1.Text == "未绑定用户") + { + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + conModels.Add(new ConditionalModel() { FieldName = "order_sn", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "商品编号": + conModels.Add(new ConditionalModel() { FieldName = "goods_id", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "商品标题": + conModels.Add(new ConditionalModel() { FieldName = "goods_name", ConditionalType = ConditionalType.Like, FieldValue = keyword }); + break; + case "客户编号": + conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "客户账号": + var ids = FindMemberIdByKey("username", keyword); + if (ids != null && ids.Count == 0) + ids.Add("-1"); + conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", ids) }); + break; + case "客户昵称": + ids = FindMemberIdByKey("usernick", keyword); + if (ids != null && ids.Count == 0) + ids.Add("-1"); + conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", ids) }); + break; + case "店铺编码": + conModels.Add(new ConditionalModel() { FieldName = "mall_id", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "推广位PID": + conModels.Add(new ConditionalModel() { FieldName = "p_id", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "联盟ID": + conModels.Add(new ConditionalModel() { FieldName = "db_cpsname", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "联盟账号": + conModels.Add(new ConditionalModel() { FieldName = "db_cpsnick", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "未绑定用户": + conModels.Add(new ConditionalModel() { FieldName = "db_userid", ConditionalType = ConditionalType.Equal, FieldValue = "0" }); + break; + } + } + + var status = this.comboBoxEdit2.SelectedIndex == 0 ? SystemOrderStatus.订单未知 : Util.ConvertEnum(this.comboBoxEdit2.Text); + + if (status != SystemOrderStatus.订单未知) + conModels.Add(new ConditionalModel() { FieldName = "db_status", ConditionalType = ConditionalType.Equal, FieldValue = ((int)status).ToString() }); + + if (this.comboBoxEdit3.SelectedIndex != 0) + conModels.Add(new ConditionalModel() { FieldName = "db_robotname", ConditionalType = ConditionalType.Equal, FieldValue = this.comboBoxEdit3.Text.Trim() }); + + //总记录数 + int totalNumber = 0; + + result = session.Queryable() + .OrderBy(o => o.order_create_time, OrderByType.Desc) + .Where(conModels) + .Select((o) => new view_cps_order_pinduoduo() + { + id = o.id, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + goods_id = o.goods_id, + goods_name = o.goods_name, + goods_price = o.goods_price, + goods_quantity = o.goods_quantity, + order_amount = o.order_amount, + order_create_time = o.order_create_time, + order_sn = o.order_sn, + order_status_desc = o.order_status_desc, + promotion_amount = o.promotion_amount, + p_id = o.p_id, + robotname = o.db_robotname, + db_userid = o.db_userid, + mall_id = o.mall_id, + price_compare_status = o.price_compare_status + //username = u.username, + //usernick = u.usernick + }) + .ToPageList(index, pagesize, ref totalNumber); + + if (result.Count != 0) + { + #region 附加用户 + var bindUsersList = result.Where(f => f.db_userid != 0).Select(f => f.db_userid.ToString()).ToList(); + var memberData = new List(); + if (bindUsersList != null && bindUsersList.Count != 0) + memberData = session.Queryable().Where(new List() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + int count = 1; + foreach (var member in memberData) + { + count++; + var items = result.Where(f => f.db_userid == member.id).ToList(); + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(50); + + foreach (var item in items) + { + item.usernick = member.usernick; + item.username = member.username; + } + } + #endregion + + #region 附加机器人信息 + var robotList = result.Where(f => !string.IsNullOrWhiteSpace(f.robotname)).GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + var robotData = session.FindRobots().Where(f => robotList.Contains(f.name)).ToList(); + foreach (var robot in robotData) + { + var items = result.Where(f => f.robotname == robot.name).ToList(); + foreach (var item in items) + { + item.robotnick = robot.nick; + } + } + #endregion + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + */ + #endregion + + try + { + var session = ApiClient.GetSession(); + var isOld = true; + List result = null; + var sqlwhere = string.Empty; + if (this.checkBox1.Checked) + { + isOld = false; + + sqlwhere += $" and '{this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss")}' <= order_create_time and order_create_time <= '{this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss")}'"; + } + + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword) || comboBoxEdit1.Text == "未绑定用户") + { + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + sqlwhere += $" and order_sn = '{keyword}'"; + break; + case "商品编号": + sqlwhere += $" and goods_id = '{keyword}'"; + break; + case "商品标题": + sqlwhere += $" and goods_name like '%{keyword}%'"; + break; + case "客户编号": + sqlwhere += $" and db_userid = '{keyword}'"; + break; + case "客户账号": + var ids = FindMemberIdByKey("username", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "客户昵称": + ids = FindMemberIdByKey("usernick", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "店铺编码": + sqlwhere += $" and mall_id = '{keyword}'"; + break; + case "推广位PID": + sqlwhere += $" and p_id = '{keyword}'"; + break; + case "联盟账号": + sqlwhere += $" and db_cpsname = '{keyword}'"; + break; + case "联盟昵称": + sqlwhere += $" and db_cpsnick = '{keyword}'"; + break; + case "未绑定用户": + sqlwhere += $" and db_userid = '0'"; + break; + } + } + + var status = this.comboBoxEdit2.SelectedIndex == 0 ? SystemOrderStatus.订单未知 : Util.ConvertEnum(this.comboBoxEdit2.Text); + + if (status != SystemOrderStatus.订单未知) + sqlwhere += $" and db_status = '{((int)status).ToString()}'"; + + if (this.comboBoxEdit3.SelectedIndex != 0) + sqlwhere += $" and db_robotname = '{comboBoxEdit3.Text.Trim()}'"; + + //总记录数 + int totalNumber = 0; + + if (isOld && checkBox_isOld.Checked) + { + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= order_create_time"; + } + + sqlwhere += $" order by id desc"; + + var getCount = session.Find("select count(*) from fl_order_pinduoduo where 1=1 " + sqlwhere); + if (getCount != null && getCount.Count != 0) + totalNumber = getCount[0]; + + sqlwhere += $" limit {(index - 1) * pagesize},{pagesize}"; + + var resultTmp = session.Find("select * from fl_order_pinduoduo where 1=1 " + sqlwhere); + + result = new List(); + foreach (var o in resultTmp) + { + result.Add(new view_cps_order_pinduoduo() + { + id = o.id, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + goods_id = o.goods_id, + goods_name = o.goods_name, + goods_price = o.goods_price, + goods_quantity = o.goods_quantity, + order_amount = o.order_amount, + order_create_time = o.order_create_time, + order_sn = o.order_sn, + order_status_desc = o.order_status_desc, + promotion_amount = o.promotion_amount, + p_id = o.p_id, + robotname = o.db_robotname, + db_userid = o.db_userid, + mall_id = o.mall_id, + price_compare_status = o.price_compare_status + //username = u.username, + //usernick = u.usernick + }); + } + + if (result.Count != 0) + { + #region 附加用户 + var bindUsersList = result.Where(f => f.db_userid != 0).Select(f => f.db_userid.ToString()).ToList(); + var memberData = new List(); + if (bindUsersList != null && bindUsersList.Count != 0) + memberData = session.Queryable().Where(new List() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + int count = 1; + foreach (var member in memberData) + { + count++; + var items = result.Where(f => f.db_userid == member.id).ToList(); + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(50); + + foreach (var item in items) + { + item.usernick = member.usernick; + item.username = member.username; + } + } + #endregion + + #region 附加机器人信息 + var robotList = result.Where(f => !string.IsNullOrWhiteSpace(f.robotname)).GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + var robotData = session.FindRobots().Where(f => robotList.Contains(f.name)).ToList(); + foreach (var robot in robotData) + { + var items = result.Where(f => f.robotname == robot.name).ToList(); + foreach (var item in items) + { + item.robotnick = robot.nick; + } + } + #endregion + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + }, this.gridControl1, 50, false, true); + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + + private void cps_order_pinduoduo_Load(object sender, EventArgs e) + { + simpleButton1_Click(this.simpleButton1, null); + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + /// + /// 条件查询(用户账号/用户昵称),模糊查询,获取用户的id + /// + /// 查询的字段 + /// 模糊的关键词 + /// + private List FindMemberIdByKey(string type, string keyword) + { + try + { + var session = ApiClient.GetSession(); + return session.Find($"select id from fl_member_info where {type} like '%{keyword}%'").Select(f => f.ToString()).ToList(); + } + catch (Exception ex) + { } + return new List(); + } + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("cps_type") && e.Commons.ContainsKey("username")) + { + var cps_type = (CpsType)int.Parse(e.Commons["cps_type"].ToString()); + if (cps_type == CpsType.多多进宝) + { + textEdit1.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 5; + comboBoxEdit3.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + checkBox1.Checked = false; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "软件状态": + e.DisplayText = Util.ConvertEnum(int.Parse(e.Value.ToString())).ToString(); + break; + case "一级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardone"].ToString(); + break; + case "二级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardtwo"].ToString(); + break; + case "三级提成": + { + var result = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower()); + if (result != null && result.ContainsKey("awardthree")) + e.DisplayText = result["awardthree"].ToString(); + else + e.DisplayText = "0"; + } + break; + case "群负责人提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardcreate"].ToString(); + break; + case "订单类型": + e.DisplayText = e.Value.ToString(); + break; + } + } + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + var row = e.Row as view_cps_order_pinduoduo; + if (e.Column.Caption == "客户所得") + { + var point = CsharpHttpHelper.HttpHelper.JsonToObject(row.db_point) as ItemPoint; + if (point != null) + e.Value = point.UserPoint; + else + e.Value = 0; + } + else if (e.Column.Caption == "订单类型") + e.Value = row.price_compare_status; + } + + private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var info = this.gridView1.GetRow(rows[0]) as view_cps_order_pinduoduo; + if (XtraMessageBox.Show("您确定要删除选中数据嘛?\r\n" + info.goods_name, "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_order_pinduoduo where id=" + info.id); + } + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.textEdit1.Enabled = comboBoxEdit1.SelectedIndex != 0 && comboBoxEdit1.SelectedIndex != 11; + if (!textEdit1.Enabled) textEdit1.Text = string.Empty; + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + this.dateTimePicker1.Enabled = this.dateTimePicker2.Enabled = this.checkBox1.Checked; + } + + /// + /// 订单绑定 + /// + /// + /// + private void 绑定用户ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_pinduoduo; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception("该订单状态为已完结,不允许修改!"); + + var session = ApiClient.GetSession(); + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null) + { + if (member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + } + + select_member_form select_form = new select_member_form(); + select_form.ShowDialog(); + if (select_form.fl_member_info != null) + { + var pinduoduo = session.FindSingle("id = @id", new { id = row.id }); + if (pinduoduo != null) + { + if (pinduoduo.db_robottype == 0) pinduoduo.db_robottype = select_form.fl_member_info.robot_type; + if (string.IsNullOrWhiteSpace(pinduoduo.db_robotname)) pinduoduo.db_robotname = select_form.fl_member_info.robot_name; + + var itempoint = session.FindItemPoint(select_form.fl_member_info, pinduoduo.promotion_amount, pinduoduo.goods_quantity, CpsType.多多进宝); + if (itempoint != null) + { + pinduoduo.db_point = HttpHelper.ObjectToJson(itempoint); + pinduoduo.db_userpoint = itempoint.UserPoint; + } + + pinduoduo.db_userid = select_form.fl_member_info.id; + session.SaveOrUpdate(pinduoduo); + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id", new { userid = pinduoduo.db_userid, itemid = pinduoduo.goods_id, adzoneid = pinduoduo.p_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (pinduoduo.id == 0) + session.SaveOrUpdate(pinduoduo); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = pinduoduo.id, + createtime = DateTime.Now, + cpstype = CpsType.多多进宝 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + + } + simpleButton1_Click(null, null); + + //更新显示值 + row.db_userid = select_form.fl_member_info.id; + row.username = select_form.fl_member_info.username; + row.usernick = select_form.fl_member_info.usernick; + row.db_point = pinduoduo.db_point; + + select_form.fl_member_info.bind_order++; + + #region 首次付款时间 + try + { + var record = session.FindStatisticsRecord(select_form.fl_member_info.id); + if (record == null) + { + record = new fl_statistics_record() { uid = select_form.fl_member_info.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + } + catch (Exception) + { } + #endregion + + session.UpdateMemberGroup(select_form.fl_member_info); + } + + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// + /// 订单解绑 + /// + /// + /// + private void 解绑ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_pinduoduo; + var db_status = row.db_status; + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception("该订单状态为已完结,不允许解绑!"); + + var session = ApiClient.GetSession(); + + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null && member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + + session.ExcuteSQL("delete from fl_query_hist where itemid = @num_iid", new { num_iid = row.goods_id }); + session.ExcuteSQL("update fl_order_pinduoduo set db_userid = @userid where id=@id", new { id = row.id, userid = 0 }); + session.ExcuteSQL("delete from fl_query_ratio_hist where db_orderid=@id", new { id = row.id }); + + + //更新显示值 + row.db_userid = 0; + row.username = string.Empty; + row.usernick = string.Empty; + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要结算选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_pinduoduo; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单创建 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.订单退款) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var pinduoduo = session.FindSingle("order_sn = @order_sn", new { order_sn = row.order_sn }); + if (pinduoduo == null) throw new Exception("数据查询失败,请稍后重试"); + pinduoduo.db_endtime = DateTime.Now; + pinduoduo.db_status = SystemOrderStatus.订单冻结; + pinduoduo.order_status = 5; + var task = TimerTask.GetTimer() as DownPinduoduoTimer; + var notices = new List(); + task.UpdateOrder(pinduoduo, session, notices); + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_pinduoduo; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单结算; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 查看用户信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据; + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary(); + common["control_name"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", "").Replace("所有", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + /// + /// 查询用户对应积分列表 + /// + /// + /// + private void 积分ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + var common = new Dictionary(); + common["control_name"] = "提现管理"; + common["query_type"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即失效ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var result = XtraMessageBox.Show("确定要失效选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_pinduoduo; + var db_status = row.db_status; + + var session = ApiClient.GetSession(); + var pinduoduo = session.FindSingle("order_sn = @order_sn", new { order_sn = row.order_sn }); + if (pinduoduo == null) throw new Exception("数据查询失败,请稍后重试"); + + var flag = false; + var notices = new List(); + if (db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.部分退款) + flag = true; + else if (pinduoduo.IsFinish()) + throw new Exception($"选中订单:{db_status},不予操作"); + + pinduoduo.order_status = 4; + pinduoduo.db_endtime = DateTime.Now; + pinduoduo.db_status = SystemOrderStatus.订单失效; + var task = TimerTask.GetTimer() as DownPinduoduoTimer; + + if (!flag) + task.UpdateOrder(pinduoduo, session, notices); + else + { + new OrderHelper().DeductPinDuoOrderPoint(notices, pinduoduo); + session.SaveOrUpdate(pinduoduo); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_pinduoduo; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单失效; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void contextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + this.用户个人信息ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "username") != null; + this.冻结延期ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "db_status").ToString() == "订单冻结"; + } + else + e.Cancel = true; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 冻结延期ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要延长冻结选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_pinduoduo; + var db_status = row.db_status; + + if (db_status != SystemOrderStatus.订单冻结) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var endtime_form = new setting_endtime_form(row.db_endtime); + endtime_form.ShowDialog(); + if (endtime_form.newtime == DateTime.MinValue) return; + var pinduoduo = session.FindSingle("id = @id", new { id = row.id }); + if (endtime_form.newtime != row.db_endtime) + { + pinduoduo.db_endtime = endtime_form.newtime; + session.Updateable(pinduoduo).ExecuteCommand(); + } + row.db_endtime = endtime_form.newtime;//更新显示值 + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + /// + /// 要删除的@@@@@ + /// + /// + /// + private void 一键结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (MessageBox.Show("确定结算所有该所有的订单吗", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + var orders = ApiClient.GetSession().Find("select * from fl_order_pinduoduo where db_userid != 0 and (db_status = @db_status1 or db_status = @db_status2)", new { db_status1 = SystemOrderStatus.订单付款, db_status2 = SystemOrderStatus.订单冻结 }); + + if (orders.Count != 0) + { + Task.Run(() => + { + var session = ApiClient.GetSession(); + try + { + var task = TimerTask.GetTimer() as DownPinduoduoTimer; + var notices = new List(); + foreach (var order in orders) + { + tokenSource.Token.ThrowIfCancellationRequested(); + + order.order_status = 5; + order.db_endtime = DateTime.Now; + order.db_status = SystemOrderStatus.订单冻结; + + task.UpdateOrder(order, session, notices); + } + + + XtraMessageBox.Show($"一键结算成功,一共结算{orders.Count}笔订单!", "温馨提示", MessageBoxButtons.OK); + } + catch (Exception) + { } + }, tokenSource.Token); + } + else + XtraMessageBox.Show($"当前无可结算的订单!", "温馨提示", MessageBoxButtons.OK); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 重新计算未结算订单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var db = ApiClient.GetSession(); + var orders = db.Queryable().Where(f => + f.db_userid != 0 && (f.db_status == SystemOrderStatus.订单付款 || + f.db_status == SystemOrderStatus.订单冻结 || + f.db_status == SystemOrderStatus.订单维权中)).ToList(); + EventClient.OnEvent("", $"拼多多需要重新计算的订单数:{orders.Count}"); + + foreach (var order in orders) + { + var member = db.FindMemberInfoById(order.db_userid); + var itempoint = db.FindItemPoint(member, order.promotion_amount, order.goods_quantity, CpsType.多多进宝); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + + db.SaveOrUpdate(order); + EventClient.OnEvent("", $"拼多多单号:{order.order_sn},重新计算完成"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"拼多多重新计算异常:{ex.Message}"); + } + } + } +} diff --git a/FLSystem/Forms/cps_order_pinduoduo.resx b/FLSystem/Forms/cps_order_pinduoduo.resx new file mode 100644 index 0000000..8a09e09 --- /dev/null +++ b/FLSystem/Forms/cps_order_pinduoduo.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_refund_alimama.Designer.cs b/FLSystem/Forms/cps_order_refund_alimama.Designer.cs new file mode 100644 index 0000000..9d924bf --- /dev/null +++ b/FLSystem/Forms/cps_order_refund_alimama.Designer.cs @@ -0,0 +1,350 @@ +namespace FLSystem.Forms +{ + partial class cps_order_refund_alimama + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_order_refund_alimama)); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 534); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(956, 33); + this.pageControl1.TabIndex = 5; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(3, 91); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(949, 437); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn22, + this.gridColumn7, + this.gridColumn1, + this.gridColumn2, + this.gridColumn14, + this.gridColumn17}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn15 + // + this.gridColumn15.Caption = "维权创建时间"; + this.gridColumn15.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn15.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn15.FieldName = "refundcreatetime"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 145; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "tbtradeparentid"; + this.gridColumn4.MinWidth = 200; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 200; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "维权金额"; + this.gridColumn22.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn22.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn22.FieldName = "refundfee"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.OptionsColumn.AllowEdit = false; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 3; + this.gridColumn22.Width = 69; + // + // gridColumn7 + // + this.gridColumn7.Caption = "维权状态"; + this.gridColumn7.FieldName = "showrefundstatus"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + // + // gridColumn1 + // + this.gridColumn1.Caption = "维权完成时间"; + this.gridColumn1.FieldName = "refundfinishtime"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 5; + this.gridColumn1.Width = 117; + // + // gridColumn2 + // + this.gridColumn2.Caption = "被扣减佣金"; + this.gridColumn2.FieldName = "showreturnfee"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 6; + // + // gridColumn14 + // + this.gridColumn14.Caption = "商品标题"; + this.gridColumn14.FieldName = "tbauctiontitle"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 7; + this.gridColumn14.Width = 168; + // + // gridColumn17 + // + this.gridColumn17.Caption = "子订单号"; + this.gridColumn17.FieldName = "tbtradeid"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 2; + this.gridColumn17.Width = 180; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(956, 85); + this.groupControl1.TabIndex = 3; + this.groupControl1.Text = "搜索条件"; + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(576, 39); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(54, 18); + this.checkBox1.TabIndex = 9; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.Visible = false; + this.checkBox1.CheckedChanged += new System.EventHandler(this.CheckBox1_CheckedChanged); + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(630, 37); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(37, 22); + this.dateTimePicker2.TabIndex = 8; + this.dateTimePicker2.Visible = false; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(630, 37); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(37, 22); + this.dateTimePicker1.TabIndex = 3; + this.dateTimePicker1.Visible = false; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(120, 41); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(36, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(687, 29); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(97, 38); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜 索"; + this.simpleButton1.Click += new System.EventHandler(this.SimpleButton1_Click); + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "全部数据"; + this.comboBoxEdit2.Location = new System.Drawing.Point(478, 38); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "全部数据", + "维权创建", + "维权成功", + "维权失败", + "等待处理"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(92, 20); + this.comboBoxEdit2.TabIndex = 2; + this.comboBoxEdit2.Tag = "comboboxedit"; + this.comboBoxEdit2.SelectedIndexChanged += new System.EventHandler(this.ComboBoxEdit1_SelectedIndexChanged); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(369, 38); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "订单编号", + "商品标题"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(92, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.Tag = "comboboxedit"; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.ComboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(162, 38); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(191, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Tag = "textedit"; + // + // cps_order_refund_alimama + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.groupControl1); + this.Name = "cps_order_refund_alimama"; + this.Size = new System.Drawing.Size(956, 567); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + } +} diff --git a/FLSystem/Forms/cps_order_refund_alimama.cs b/FLSystem/Forms/cps_order_refund_alimama.cs new file mode 100644 index 0000000..7d2e60f --- /dev/null +++ b/FLSystem/Forms/cps_order_refund_alimama.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using Api.Framework; +using Api.Framework.Model; +using SqlSugar; +using UI.Framework.Forms; +using FLSystem.Events; +using Api.Framework.Enums; + +namespace FLSystem.Forms +{ + public partial class cps_order_refund_alimama : DevExpress.XtraEditors.XtraUserControl + { + public cps_order_refund_alimama(string textedit = "") + { + try + { + InitializeComponent(); + var session = ApiClient.GetSession(); + this.textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 1; + this.dateTimePicker1.Value = DateTime.Parse(DateTime.Today.AddDays(-30).ToString("yyyy-MM-01")); + this.dateTimePicker2.Value = DateTime.Parse(DateTime.Now.AddDays(30).ToString("yyyy-MM-dd HH:mm:ss")); + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + this.checkBox1.Checked = false; + + this.pageControl1.Bind(SerchData, this.gridControl1, 50, true, true); + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("type") && e.Commons.ContainsKey("trade_parent_id")) + { + if (e.Commons["type"].ToString() == "阿里妈妈维权订单") + { + textEdit1.Text = e.Commons["trade_parent_id"].ToString(); + comboBoxEdit1.SelectedIndex = 1; + comboBoxEdit2.SelectedIndex = 0; + checkBox1.Checked = false; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + private UI.Framework.Controls.PageControl.SerchResult SerchData(int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + + List result = null; + List conModels = new List(); + if (this.checkBox1.Checked) + { + conModels.Add(new ConditionalModel() { FieldName = "refundcreatetime", ConditionalType = ConditionalType.GreaterThanOrEqual, FieldValue = this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + conModels.Add(new ConditionalModel() { FieldName = "refundcreatetime", ConditionalType = ConditionalType.LessThanOrEqual, FieldValue = this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss") }); + } + StringBuilder sb_time = new StringBuilder(); + DateTime startTime = DateTime.Now; + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword)) + { + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + if (keyword.Length == 6) conModels.Add(new ConditionalModel() { FieldName = "tbtradeparentid", ConditionalType = ConditionalType.LikeRight, FieldValue = keyword }); + else conModels.Add(new ConditionalModel() { FieldName = "tbtradeparentid", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + case "商品标题": + conModels.Add(new ConditionalModel() { FieldName = "tbauctiontitle", ConditionalType = ConditionalType.Like, FieldValue = keyword }); + break; + } + } + startTime = DateTime.Now; + if (comboBoxEdit2.Text != "全部数据") + conModels.Add(new ConditionalModel() { FieldName = "showrefundstatus", ConditionalType = ConditionalType.Equal, FieldValue = comboBoxEdit2.Text }); + + startTime = DateTime.Now; + //总记录数 + int totalNumber = 0; + //result = session.Queryable() + // .Where(conModels) + // .OrderBy(o => (string.IsNullOrWhiteSpace(o.refundcreatetime) ? DateTime.MinValue : DateTime.Parse(o.refundcreatetime)), OrderByType.Desc).ToPageList(index, pagesize, ref totalNumber); + result = session.Queryable() + .Where(conModels).OrderBy(f => f.id, OrderByType.Desc) + .ToPageList(index, pagesize, ref totalNumber); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + if (!this.IsDisposed) + this.UpdateUI(() => + { + BaseForm.ShowError(ex); + }); + } + return null; + } + /// + /// 代理委托更新UI + /// + /// + protected delegate void DelegateUpdateUI(Action act); + + /// + /// 代理委托更新UI + /// + /// + protected void UpdateUI(Action act) + { + try + { + if (!InvokeRequired) + { + act.Invoke(); + } + else + { + DelegateUpdateUI delegateUpdateUI = new DelegateUpdateUI(UpdateUI); + Invoke(delegateUpdateUI, act); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void ComboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.textEdit1.Enabled = comboBoxEdit1.SelectedIndex != 0; + if (!textEdit1.Enabled) + this.textEdit1.Text = string.Empty; + } + + private void CheckBox1_CheckedChanged(object sender, EventArgs e) + { + this.dateTimePicker1.Enabled = this.dateTimePicker2.Enabled = this.checkBox1.Checked; + } + + private void SimpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + } +} diff --git a/FLSystem/Forms/cps_order_refund_alimama.resx b/FLSystem/Forms/cps_order_refund_alimama.resx new file mode 100644 index 0000000..029e1d2 --- /dev/null +++ b/FLSystem/Forms/cps_order_refund_alimama.resx @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_suning.Designer.cs b/FLSystem/Forms/cps_order_suning.Designer.cs new file mode 100644 index 0000000..56159c7 --- /dev/null +++ b/FLSystem/Forms/cps_order_suning.Designer.cs @@ -0,0 +1,890 @@ +namespace FLSystem.Forms +{ + partial class cps_order_suning + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_order_suning)); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.刷新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键结算ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.绑定用户ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.解绑ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.用户个人信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.所有阿里妈妈订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有多多进宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有京东联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有抖音联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有苏宁易购订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.订单状态操作ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.冻结延期ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.立即结算ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.立即失效ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.重新计算未结算订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.checkBox_isOld = new System.Windows.Forms.CheckBox(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.所有快手联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // gridColumn23 + // + this.gridColumn23.Caption = "店铺编码"; + this.gridColumn23.FieldName = "mallId"; + this.gridColumn23.MinWidth = 23; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.OptionsColumn.AllowEdit = false; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 23; + this.gridColumn23.Width = 87; + // + // 刷新ToolStripMenuItem + // + this.刷新ToolStripMenuItem.Name = "刷新ToolStripMenuItem"; + this.刷新ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.刷新ToolStripMenuItem.Text = "刷新"; + this.刷新ToolStripMenuItem.Click += new System.EventHandler(this.刷新ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // 一键结算ToolStripMenuItem + // + this.一键结算ToolStripMenuItem.Name = "一键结算ToolStripMenuItem"; + this.一键结算ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.一键结算ToolStripMenuItem.Text = "一键结算(隐藏)"; + this.一键结算ToolStripMenuItem.Visible = false; + this.一键结算ToolStripMenuItem.Click += new System.EventHandler(this.一键结算ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn14, + this.gridColumn9, + this.gridColumn7, + this.gridColumn8, + this.gridColumn21, + this.gridColumn20, + this.gridColumn19, + this.gridColumn18, + this.gridColumn6, + this.gridColumn5, + this.gridColumn1, + this.gridColumn3, + this.gridColumn10, + this.gridColumn11, + this.gridColumn12, + this.gridColumn2, + this.gridColumn24, + this.gridColumn22, + this.gridColumn16, + this.gridColumn17, + this.gridColumn13, + this.gridColumn23}); + this.gridView1.DetailHeight = 408; + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 58; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn15 + // + this.gridColumn15.Caption = "创建时间"; + this.gridColumn15.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn15.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn15.FieldName = "orderSubmitTime"; + this.gridColumn15.MinWidth = 23; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 175; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "orderCode"; + this.gridColumn4.MinWidth = 233; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 233; + // + // gridColumn14 + // + this.gridColumn14.Caption = "状态"; + this.gridColumn14.FieldName = "db_status"; + this.gridColumn14.MinWidth = 23; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 2; + this.gridColumn14.Width = 87; + // + // gridColumn9 + // + this.gridColumn9.Caption = "付款金额"; + this.gridColumn9.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn9.FieldName = "payAmount"; + this.gridColumn9.MinWidth = 23; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 3; + this.gridColumn9.Width = 87; + // + // gridColumn7 + // + this.gridColumn7.Caption = "总佣金"; + this.gridColumn7.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn7.FieldName = "prePayCommission"; + this.gridColumn7.MinWidth = 23; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + this.gridColumn7.Width = 87; + // + // gridColumn8 + // + this.gridColumn8.Caption = "客户所得"; + this.gridColumn8.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn8.FieldName = "endpoint"; + this.gridColumn8.MinWidth = 23; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 5; + this.gridColumn8.Width = 87; + // + // gridColumn21 + // + this.gridColumn21.Caption = "一级提成"; + this.gridColumn21.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn21.FieldName = "db_point"; + this.gridColumn21.MinWidth = 23; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 6; + this.gridColumn21.Width = 87; + // + // gridColumn20 + // + this.gridColumn20.Caption = "二级提成"; + this.gridColumn20.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn20.FieldName = "db_point"; + this.gridColumn20.MinWidth = 23; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 7; + this.gridColumn20.Width = 87; + // + // gridColumn19 + // + this.gridColumn19.Caption = "三级提成"; + this.gridColumn19.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn19.FieldName = "db_point"; + this.gridColumn19.MinWidth = 23; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 8; + this.gridColumn19.Width = 87; + // + // gridColumn18 + // + this.gridColumn18.Caption = "群负责人提成"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn18.FieldName = "db_point"; + this.gridColumn18.MinWidth = 23; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.OptionsColumn.AllowEdit = false; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 9; + this.gridColumn18.Width = 87; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.MinWidth = 23; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 10; + this.gridColumn6.Width = 140; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户名"; + this.gridColumn5.FieldName = "username"; + this.gridColumn5.MinWidth = 140; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 11; + this.gridColumn5.Width = 140; + // + // gridColumn1 + // + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "productName"; + this.gridColumn1.MinWidth = 23; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 12; + this.gridColumn1.Width = 408; + // + // gridColumn3 + // + this.gridColumn3.Caption = "商品编号"; + this.gridColumn3.FieldName = "goodsNum"; + this.gridColumn3.MinWidth = 140; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 13; + this.gridColumn3.Width = 140; + // + // gridColumn10 + // + this.gridColumn10.Caption = "付款金额"; + this.gridColumn10.FieldName = "payAmount"; + this.gridColumn10.MinWidth = 23; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 14; + this.gridColumn10.Width = 87; + // + // gridColumn11 + // + this.gridColumn11.Caption = "购买数量"; + this.gridColumn11.FieldName = "saleNum"; + this.gridColumn11.MinWidth = 23; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 15; + this.gridColumn11.Width = 87; + // + // gridColumn12 + // + this.gridColumn12.Caption = "状态描述"; + this.gridColumn12.FieldName = "orderLineStatusDesc"; + this.gridColumn12.MinWidth = 23; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 16; + this.gridColumn12.Width = 87; + // + // gridColumn2 + // + this.gridColumn2.Caption = "冻结时间"; + this.gridColumn2.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn2.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn2.FieldName = "db_endtime"; + this.gridColumn2.MinWidth = 23; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 17; + this.gridColumn2.Width = 87; + // + // gridColumn24 + // + this.gridColumn24.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn24.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn24.Caption = "机器人昵称"; + this.gridColumn24.FieldName = "robotnick"; + this.gridColumn24.MinWidth = 23; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 18; + this.gridColumn24.Width = 87; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "机器人账号"; + this.gridColumn22.FieldName = "robotname"; + this.gridColumn22.MinWidth = 23; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 19; + this.gridColumn22.Width = 87; + // + // gridColumn16 + // + this.gridColumn16.Caption = "联盟账号"; + this.gridColumn16.FieldName = "db_cpsname"; + this.gridColumn16.MinWidth = 23; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 20; + this.gridColumn16.Width = 117; + // + // gridColumn17 + // + this.gridColumn17.Caption = "联盟昵称"; + this.gridColumn17.FieldName = "db_cpsnick"; + this.gridColumn17.MinWidth = 23; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 21; + this.gridColumn17.Width = 117; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "推广位"; + this.gridColumn13.FieldName = "pid"; + this.gridColumn13.MinWidth = 140; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 22; + this.gridColumn13.Width = 140; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(3, 110); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(1016, 457); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.绑定用户ToolStripMenuItem, + this.解绑ToolStripMenuItem, + this.用户个人信息ToolStripMenuItem, + this.订单状态操作ToolStripMenuItem, + this.刷新ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.一键结算ToolStripMenuItem, + this.重新计算未结算订单ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 202); + // + // 绑定用户ToolStripMenuItem + // + this.绑定用户ToolStripMenuItem.Name = "绑定用户ToolStripMenuItem"; + this.绑定用户ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.绑定用户ToolStripMenuItem.Text = "绑定"; + this.绑定用户ToolStripMenuItem.Click += new System.EventHandler(this.绑定用户ToolStripMenuItem_Click); + // + // 解绑ToolStripMenuItem + // + this.解绑ToolStripMenuItem.Name = "解绑ToolStripMenuItem"; + this.解绑ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.解绑ToolStripMenuItem.Text = "解绑"; + this.解绑ToolStripMenuItem.Click += new System.EventHandler(this.解绑ToolStripMenuItem_Click); + // + // 用户个人信息ToolStripMenuItem + // + this.用户个人信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看用户信息ToolStripMenuItem, + this.toolStripSeparator2, + this.所有阿里妈妈订单ToolStripMenuItem, + this.所有多多进宝订单ToolStripMenuItem, + this.所有京东联盟订单ToolStripMenuItem, + this.所有唯品联盟订单ToolStripMenuItem, + this.所有抖音联盟订单ToolStripMenuItem, + this.所有苏宁易购订单ToolStripMenuItem, + this.所有快手联盟订单ToolStripMenuItem, + this.toolStripSeparator1, + this.积分日志ToolStripMenuItem, + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.用户个人信息ToolStripMenuItem.Name = "用户个人信息ToolStripMenuItem"; + this.用户个人信息ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.用户个人信息ToolStripMenuItem.Text = "用户个人信息"; + // + // 查看用户信息ToolStripMenuItem + // + this.查看用户信息ToolStripMenuItem.Name = "查看用户信息ToolStripMenuItem"; + this.查看用户信息ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.查看用户信息ToolStripMenuItem.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem.Click += new System.EventHandler(this.查看用户信息ToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6); + // + // 所有阿里妈妈订单ToolStripMenuItem + // + this.所有阿里妈妈订单ToolStripMenuItem.Name = "所有阿里妈妈订单ToolStripMenuItem"; + this.所有阿里妈妈订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有阿里妈妈订单ToolStripMenuItem.Text = "所有阿里妈妈订单"; + this.所有阿里妈妈订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有多多进宝订单ToolStripMenuItem + // + this.所有多多进宝订单ToolStripMenuItem.Name = "所有多多进宝订单ToolStripMenuItem"; + this.所有多多进宝订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有多多进宝订单ToolStripMenuItem.Text = "所有多多进宝订单"; + this.所有多多进宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有京东联盟订单ToolStripMenuItem + // + this.所有京东联盟订单ToolStripMenuItem.Name = "所有京东联盟订单ToolStripMenuItem"; + this.所有京东联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有京东联盟订单ToolStripMenuItem.Text = "所有京东联盟订单"; + this.所有京东联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有唯品联盟订单ToolStripMenuItem + // + this.所有唯品联盟订单ToolStripMenuItem.Name = "所有唯品联盟订单ToolStripMenuItem"; + this.所有唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有唯品联盟订单ToolStripMenuItem.Text = "所有唯品联盟订单"; + this.所有唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有抖音联盟订单ToolStripMenuItem + // + this.所有抖音联盟订单ToolStripMenuItem.Name = "所有抖音联盟订单ToolStripMenuItem"; + this.所有抖音联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有抖音联盟订单ToolStripMenuItem.Text = "所有抖音联盟订单"; + this.所有抖音联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有苏宁易购订单ToolStripMenuItem + // + this.所有苏宁易购订单ToolStripMenuItem.Name = "所有苏宁易购订单ToolStripMenuItem"; + this.所有苏宁易购订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有苏宁易购订单ToolStripMenuItem.Text = "所有苏宁易购订单"; + this.所有苏宁易购订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6); + // + // 积分日志ToolStripMenuItem + // + this.积分日志ToolStripMenuItem.Name = "积分日志ToolStripMenuItem"; + this.积分日志ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.积分日志ToolStripMenuItem.Text = "积分日志"; + this.积分日志ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 订单状态操作ToolStripMenuItem + // + this.订单状态操作ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.冻结延期ToolStripMenuItem, + this.立即结算ToolStripMenuItem1, + this.立即失效ToolStripMenuItem1}); + this.订单状态操作ToolStripMenuItem.Name = "订单状态操作ToolStripMenuItem"; + this.订单状态操作ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.订单状态操作ToolStripMenuItem.Text = "订单状态操作"; + // + // 冻结延期ToolStripMenuItem + // + this.冻结延期ToolStripMenuItem.Name = "冻结延期ToolStripMenuItem"; + this.冻结延期ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.冻结延期ToolStripMenuItem.Text = "冻结延期"; + this.冻结延期ToolStripMenuItem.Click += new System.EventHandler(this.冻结延期ToolStripMenuItem_Click); + // + // 立即结算ToolStripMenuItem1 + // + this.立即结算ToolStripMenuItem1.Name = "立即结算ToolStripMenuItem1"; + this.立即结算ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即结算ToolStripMenuItem1.Text = "立即结算"; + this.立即结算ToolStripMenuItem1.Click += new System.EventHandler(this.立即结算ToolStripMenuItem1_Click); + // + // 立即失效ToolStripMenuItem1 + // + this.立即失效ToolStripMenuItem1.Name = "立即失效ToolStripMenuItem1"; + this.立即失效ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即失效ToolStripMenuItem1.Text = "立即失效"; + this.立即失效ToolStripMenuItem1.Click += new System.EventHandler(this.立即失效ToolStripMenuItem1_Click); + // + // 重新计算未结算订单ToolStripMenuItem + // + this.重新计算未结算订单ToolStripMenuItem.Name = "重新计算未结算订单ToolStripMenuItem"; + this.重新计算未结算订单ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.重新计算未结算订单ToolStripMenuItem.Text = "重新计算未结算订单"; + this.重新计算未结算订单ToolStripMenuItem.Visible = false; + this.重新计算未结算订单ToolStripMenuItem.Click += new System.EventHandler(this.重新计算未结算订单ToolStripMenuItem_Click); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 574); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(1020, 37); + this.pageControl1.TabIndex = 5; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.checkBox_isOld); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(1020, 103); + this.groupControl1.TabIndex = 3; + this.groupControl1.Text = "搜索条件"; + // + // checkBox_isOld + // + this.checkBox_isOld.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox_isOld.AutoSize = true; + this.checkBox_isOld.Checked = true; + this.checkBox_isOld.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_isOld.Location = new System.Drawing.Point(860, 41); + this.checkBox_isOld.Name = "checkBox_isOld"; + this.checkBox_isOld.Size = new System.Drawing.Size(134, 32); + this.checkBox_isOld.TabIndex = 14; + this.checkBox_isOld.Text = "搜索一年以内的数据\r\n查询速度慢的请勾选"; + this.checkBox_isOld.UseVisualStyleBackColor = true; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = ""; + this.comboBoxEdit3.Location = new System.Drawing.Point(372, 66); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit3.TabIndex = 13; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "不限状态"; + this.comboBoxEdit2.Location = new System.Drawing.Point(372, 34); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "不限状态", + "订单创建", + "订单付款", + "订单失效", + "全额退款", + "部分退款", + "订单冻结", + "订单结算"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit2.TabIndex = 13; + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(492, 49); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(54, 18); + this.checkBox1.TabIndex = 12; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(556, 64); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(187, 22); + this.dateTimePicker2.TabIndex = 11; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(556, 33); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(187, 22); + this.dateTimePicker1.TabIndex = 10; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(41, 50); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(756, 37); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(91, 45); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(259, 48); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "订单编号", + "商品编号", + "商品标题", + "客户编号", + "客户账号", + "客户昵称", + "店铺编码", + "推广位PID", + "联盟账号", + "联盟昵称", + "未绑定用户"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.Tag = "comboboxedit"; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(92, 47); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(156, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Tag = "textedit"; + // + // 所有快手联盟订单ToolStripMenuItem + // + this.所有快手联盟订单ToolStripMenuItem.Name = "所有快手联盟订单ToolStripMenuItem"; + this.所有快手联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有快手联盟订单ToolStripMenuItem.Text = "所有快手联盟订单"; + this.所有快手联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // cps_order_suning + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.gridControl1); + this.Name = "cps_order_suning"; + this.Size = new System.Drawing.Size(1020, 611); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private System.Windows.Forms.ToolStripMenuItem 刷新ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 一键结算ToolStripMenuItem; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.GridControl gridControl1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 绑定用户ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 解绑ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 用户个人信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 所有阿里妈妈订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有多多进宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有京东联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有唯品联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有抖音联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 订单状态操作ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 冻结延期ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 立即结算ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 立即失效ToolStripMenuItem1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.CheckBox checkBox_isOld; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.ToolStripMenuItem 所有苏宁易购订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 重新计算未结算订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有快手联盟订单ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/cps_order_suning.cs b/FLSystem/Forms/cps_order_suning.cs new file mode 100644 index 0000000..857eb1a --- /dev/null +++ b/FLSystem/Forms/cps_order_suning.cs @@ -0,0 +1,850 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework; +using Api.Framework.Tools; +using Api.Framework.Model; +using Api.Framework.Enums; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using System.Text.RegularExpressions; +using FLSystem.Events; +using Api.Framework.Timers; +using Api.Framework.SDK; +using Api.Framework.Events; +using DevExpress.XtraGrid.Views.Grid; +using SqlSugar; +using System.Threading; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class cps_order_suning : DevExpress.XtraEditors.XtraUserControl + { + public cps_order_suning(string textedit = "") + { + InitializeComponent(); + this.textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 5; + this.checkBox1.Checked = false; + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + comboBoxEdit3.SelectedIndex = 0; + #endregion + + try + { + this.pageControl1.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var isOld = true; + List result = null; + var sqlwhere = string.Empty; + if (this.checkBox1.Checked) + { + isOld = false; + + sqlwhere += $" and '{this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss")}' <= orderSubmitTime and orderSubmitTime <= '{this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss")}'"; + } + + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword) || comboBoxEdit1.Text == "未绑定用户") + { + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + sqlwhere += $" and orderCode = '{keyword}'"; + break; + case "商品编号": + sqlwhere += $" and goodsNum = '{keyword}'"; + break; + case "商品标题": + sqlwhere += $" and productName like '%{keyword}%'"; + break; + case "客户编号": + sqlwhere += $" and db_userid = '{keyword}'"; + break; + case "客户账号": + var ids = FindMemberIdByKey("username", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "客户昵称": + ids = FindMemberIdByKey("usernick", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "店铺编码": + sqlwhere += $" and mallId = '{keyword}'"; + break; + case "推广位PID": + sqlwhere += $" and pid = '{keyword}'"; + break; + case "联盟账号": + sqlwhere += $" and db_cpsname = '{keyword}'"; + break; + case "联盟昵称": + sqlwhere += $" and db_cpsnick = '{keyword}'"; + break; + case "未绑定用户": + sqlwhere += $" and db_userid = '0'"; + break; + } + } + + var status = this.comboBoxEdit2.SelectedIndex == 0 ? SystemOrderStatus.订单未知 : Util.ConvertEnum(this.comboBoxEdit2.Text); + + if (status != SystemOrderStatus.订单未知) + sqlwhere += $" and db_status = '{((int)status).ToString()}'"; + + if (this.comboBoxEdit3.SelectedIndex != 0) + sqlwhere += $" and db_robotname = '{comboBoxEdit3.Text.Trim()}'"; + + //总记录数 + int totalNumber = 0; + + if (isOld && checkBox_isOld.Checked) + { + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= payTime"; + } + + sqlwhere += $" order by id desc"; + + var getCount = session.Find("select count(*) from fl_order_suning where 1=1 " + sqlwhere); + if (getCount != null && getCount.Count != 0) + totalNumber = getCount[0]; + + sqlwhere += $" limit {(index - 1) * pagesize},{pagesize}"; + + var resultTmp = session.Find("select * from fl_order_suning where 1=1 " + sqlwhere); + + result = new List(); + foreach (var o in resultTmp) + { + result.Add(new view_cps_order_suning() + { + id = o.id, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + childAccountId = o.childAccountId, + commissionRatio = o.commissionRatio, + custNo = o.custNo, + db_robotname = o.db_robotname, + db_robottype = o.db_robottype, + db_status_time = o.db_status_time, + db_userpoint = o.db_userpoint, + goodsGroupCatalog = o.goodsGroupCatalog, + goodsNum = o.goodsNum, + mallId = o.mallId, + db_userid = o.db_userid, + msg_groupid = o.msg_groupid, + orderCode = o.orderCode, + orderLineFlag = o.orderLineFlag, + orderLineNumber = o.orderLineNumber, + orderLineOrigin = o.orderLineOrigin, + orderLineStatusChangeTime = o.orderLineStatusChangeTime, + orderLineStatusDesc = o.orderLineStatusDesc, + orderSubmitTime = o.orderSubmitTime, + orderType = o.orderType, + payAmount = o.payAmount, + payTime = o.payTime, + pictureUrl = o.pictureUrl, + positionId = o.positionId, + prePayCommission = o.prePayCommission, + productFirstCatalog = o.productFirstCatalog, + productName = o.productName, + productSecondCatalog = o.productSecondCatalog, + productThirdCatalog = o.productThirdCatalog, + promotion = o.promotion, + returnCommission = o.returnCommission, + saleNum = o.saleNum, + saleType = o.saleType, + sellerCode = o.sellerCode, + sellName = o.sellName, + statParam = o.statParam, + violation = o.violation, + robotname = o.db_robotname + //username = u.username, + //usernick = u.usernick + }); + } + + if (result.Count != 0) + { + #region 附加用户 + var bindUsersList = result.Where(f => f.db_userid != 0).Select(f => f.db_userid.ToString()).ToList(); + var memberData = new List(); + if (bindUsersList != null && bindUsersList.Count != 0) + memberData = session.Queryable().Where(new List() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + int count = 1; + foreach (var member in memberData) + { + count++; + var items = result.Where(f => f.db_userid == member.id).ToList(); + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(50); + + foreach (var item in items) + { + item.usernick = member.usernick; + item.username = member.username; + } + } + #endregion + + #region 附加机器人信息 + var robotList = result.Where(f => !string.IsNullOrWhiteSpace(f.robotname)).GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + var robotData = session.FindRobots().Where(f => robotList.Contains(f.name)).ToList(); + foreach (var robot in robotData) + { + var items = result.Where(f => f.robotname == robot.name).ToList(); + foreach (var item in items) + { + item.robotnick = robot.nick; + } + } + #endregion + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + }, this.gridControl1, 50, false, true); + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("cps_type") && e.Commons.ContainsKey("username")) + { + var cps_type = (CpsType)int.Parse(e.Commons["cps_type"].ToString()); + if (cps_type == CpsType.苏宁易购) + { + textEdit1.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 5; + comboBoxEdit3.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + checkBox1.Checked = false; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + } + + private void gridView1_CustomDrawRowIndicator(object sender, RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + /// + /// 条件查询(用户账号/用户昵称),模糊查询,获取用户的id + /// + /// 查询的字段 + /// 模糊的关键词 + /// + private List FindMemberIdByKey(string type, string keyword) + { + try + { + var session = ApiClient.GetSession(); + return session.Find($"select id from fl_member_info where {type} like '%{keyword}%'").Select(f => f.ToString()).ToList(); + } + catch (Exception ex) + { } + return new List(); + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.textEdit1.Enabled = comboBoxEdit1.SelectedIndex != 0 && comboBoxEdit1.SelectedIndex != 11; + if (!textEdit1.Enabled) textEdit1.Text = string.Empty; + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + this.dateTimePicker1.Enabled = this.dateTimePicker2.Enabled = this.checkBox1.Checked; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + /// + /// 订单绑定 + /// + /// + /// + private void 绑定用户ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_suning; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception("该订单状态为已完结,不允许修改!"); + + var session = ApiClient.GetSession(); + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null) + { + if (member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + } + + select_member_form select_form = new select_member_form(); + select_form.ShowDialog(); + if (select_form.fl_member_info != null) + { + var suning = session.FindSingle("id = @id", new { id = row.id }); + if (suning != null) + { + if (suning.db_robottype == 0) suning.db_robottype = select_form.fl_member_info.robot_type; + if (string.IsNullOrWhiteSpace(suning.db_robotname)) suning.db_robotname = select_form.fl_member_info.robot_name; + + var itempoint = session.FindItemPoint(select_form.fl_member_info, double.Parse(suning.prePayCommission), int.Parse(suning.saleNum), CpsType.苏宁易购); + if (itempoint != null) + { + suning.db_point = HttpHelper.ObjectToJson(itempoint); + suning.db_userpoint = itempoint.UserPoint; + } + + suning.db_userid = select_form.fl_member_info.id; + session.SaveOrUpdate(suning); + + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id", new { userid = suning.db_userid, itemid = suning.goodsNum, adzoneid = suning.pid, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (suning.id == 0) + session.SaveOrUpdate(suning); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = suning.id, + createtime = DateTime.Now, + cpstype = CpsType.苏宁易购 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + } + simpleButton1_Click(null, null); + + //更新显示值 + row.db_userid = select_form.fl_member_info.id; + row.username = select_form.fl_member_info.username; + row.usernick = select_form.fl_member_info.usernick; + row.db_point = suning.db_point; + + select_form.fl_member_info.bind_order++; + + #region 首次付款时间 + try + { + var record = session.FindStatisticsRecord(select_form.fl_member_info.id); + if (record == null) + { + record = new fl_statistics_record() { uid = select_form.fl_member_info.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + } + catch (Exception) + { } + #endregion + + session.UpdateMemberGroup(select_form.fl_member_info); + } + + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// + /// 订单解绑 + /// + /// + /// + private void 解绑ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_suning; + var db_status = row.db_status; + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception("该订单状态为已完结,不允许解绑!"); + + var session = ApiClient.GetSession(); + + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null && member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + + session.ExcuteSQL("delete from fl_query_hist where itemid = @num_iid", new { num_iid = row.goodsNum }); + session.ExcuteSQL("update fl_order_suning set db_userid = @userid where id=@id", new { id = row.id, userid = 0 }); + session.ExcuteSQL("delete from fl_query_ratio_hist where id = @id", new { id = row.id }); + + //更新显示值 + row.db_userid = 0; + row.username = string.Empty; + row.usernick = string.Empty; + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + + public class view_cps_order_suning : fl_order_suning + { + + private string _robotname; + /// + /// 机器人账号 + /// + public string robotname + { + get { return _robotname; } + set { if (string.IsNullOrEmpty(value)) _robotname = string.Empty; else _robotname = value; } + } + + /// + /// 机器人昵称 + /// + public string robotnick { get; set; } + + private string _username; + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + + } + + private void 查看用户信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据; + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary(); + common["control_name"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", "").Replace("所有", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + private void 积分ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + var common = new Dictionary(); + common["control_name"] = "提现管理"; + common["query_type"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 冻结延期ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要延长冻结选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_suning; + var db_status = row.db_status; + + if (db_status != SystemOrderStatus.订单冻结) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var endtime_form = new setting_endtime_form(row.db_endtime); + endtime_form.ShowDialog(); + if (endtime_form.newtime == DateTime.MinValue) return; + var suning = session.FindSingle("id = @id", new { id = row.id }); + if (endtime_form.newtime != row.db_endtime) + { + suning.db_endtime = endtime_form.newtime; + session.Updateable(suning).ExecuteCommand(); + } + row.db_endtime = endtime_form.newtime;//更新显示值 + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即结算ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要结算选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_suning; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单创建 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.订单退款) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var suning = session.FindSingle("orderCode = @orderCode and orderLineNumber = @orderLineNumber", new { orderCode = row.orderCode, orderLineNumber = row.orderLineNumber }); + if (suning == null) throw new Exception("数据查询失败,请稍后重试"); + suning.db_endtime = DateTime.Now; + suning.db_status = SystemOrderStatus.订单冻结; + suning.orderLineStatusDesc = SuNingSubOrderStatus.确认收货.ToString(); + var task = TimerTask.GetTimer() as DownSuningTimer; + var notices = new List(); + task.UpdateOrder(suning, session, notices); + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_suning; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单结算; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即失效ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + var result = XtraMessageBox.Show("确定要失效选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_suning; + var db_status = row.db_status; + + var session = ApiClient.GetSession(); + var suning = session.FindSingle("orderCode = @orderCode and orderLineNumber = @orderLineNumber", new { orderCode = row.orderCode, orderLineNumber = row.orderLineNumber }); + if (suning == null) throw new Exception("数据查询失败,请稍后重试"); + + var flag = false; + var notices = new List(); + if (db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.部分退款) + flag = true; + else if (suning.IsFinish()) + throw new Exception($"选中订单:{db_status},不予操作"); + + suning.orderLineStatusDesc = SuNingSubOrderStatus.订单已取消.ToString(); + suning.db_endtime = DateTime.Now; + suning.db_status = SystemOrderStatus.订单失效; + var task = TimerTask.GetTimer() as DownSuningTimer; + + if (!flag) + task.UpdateOrder(suning, session, notices); + else + { + new OrderHelper().DeductSuningOrderPoint(notices, suning); + session.SaveOrUpdate(suning); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_suning; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单失效; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var info = this.gridView1.GetRow(rows[0]) as view_cps_order_suning; + if (XtraMessageBox.Show("您确定要删除选中数据嘛?\r\n" + info.productName, "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_order_suning where id=" + info.id); + } + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "软件状态": + e.DisplayText = Util.ConvertEnum(int.Parse(e.Value.ToString())).ToString(); + break; + case "一级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString())["AwardOne"].ToString(); + break; + case "二级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString())["AwardTwo"].ToString(); + break; + case "三级提成": + { + var result = HttpExtend.JsonToDictionary(e.Value.ToString()); + if (result != null && result.ContainsKey("AwardThree")) + e.DisplayText = result["AwardThree"].ToString(); + else + e.DisplayText = "0"; + } + break; + case "群负责人提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString())["AwardCreate"].ToString(); + break; + } + } + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + var row = e.Row as view_cps_order_suning; + if (e.Column.Caption == "客户所得") + { + var point = HttpHelper.JsonToObject(row.db_point) as ItemPoint; + if (point != null) + e.Value = point.UserPoint; + else + e.Value = 0; + } + } + + private void 一键结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + + } + + private void 重新计算未结算订单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var db = ApiClient.GetSession(); + var orders = db.Queryable().Where(f => + f.db_userid != 0 && (f.db_status == SystemOrderStatus.订单付款 || + f.db_status == SystemOrderStatus.订单冻结 || + f.db_status == SystemOrderStatus.订单维权中)).ToList(); + EventClient.OnEvent("", $"苏宁需要重新计算的订单数:{orders.Count}"); + + foreach (var order in orders) + { + var member = db.FindMemberInfoById(order.db_userid); + var itempoint = db.FindItemPoint(member, double.Parse(order.prePayCommission), int.Parse(order.saleNum), CpsType.苏宁易购); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + + db.SaveOrUpdate(order); + EventClient.OnEvent("", $"苏宁单号:{order.orderCode},重新计算完成"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"苏宁重新计算异常:{ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_suning.resx b/FLSystem/Forms/cps_order_suning.resx new file mode 100644 index 0000000..5d683ec --- /dev/null +++ b/FLSystem/Forms/cps_order_suning.resx @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + + 55 + + \ No newline at end of file diff --git a/FLSystem/Forms/cps_order_weipinhui.Designer.cs b/FLSystem/Forms/cps_order_weipinhui.Designer.cs new file mode 100644 index 0000000..edb3063 --- /dev/null +++ b/FLSystem/Forms/cps_order_weipinhui.Designer.cs @@ -0,0 +1,921 @@ +namespace FLSystem.Forms +{ + partial class cps_order_weipinhui + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(cps_order_weipinhui)); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.绑定用户ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.解绑ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.用户个人信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.所有阿里妈妈订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有多多进宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有京东联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.所有苏宁易购订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.订单状态操作ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.冻结延期ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.立即结算ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.立即失效ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键结算ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.重新计算未结算订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.checkBox_isOld = new System.Windows.Forms.CheckBox(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.所有快手联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn14, + this.gridColumn9, + this.gridColumn7, + this.gridColumn8, + this.gridColumn21, + this.gridColumn20, + this.gridColumn19, + this.gridColumn18, + this.gridColumn6, + this.gridColumn5, + this.gridColumn1, + this.gridColumn3, + this.gridColumn10, + this.gridColumn11, + this.gridColumn2, + this.gridColumn24, + this.gridColumn22, + this.gridColumn16, + this.gridColumn17, + this.gridColumn13, + this.gridColumn23, + this.gridColumn12, + this.gridColumn25, + this.gridColumn26}); + this.gridView1.DetailHeight = 272; + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 44; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn15 + // + this.gridColumn15.Caption = "下单时间"; + this.gridColumn15.FieldName = "orderTime"; + this.gridColumn15.MinWidth = 17; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 131; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单号"; + this.gridColumn4.FieldName = "orderSn"; + this.gridColumn4.MinWidth = 175; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 175; + // + // gridColumn14 + // + this.gridColumn14.Caption = "状态"; + this.gridColumn14.FieldName = "db_status"; + this.gridColumn14.MinWidth = 17; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 2; + this.gridColumn14.Width = 66; + // + // gridColumn9 + // + this.gridColumn9.Caption = "付款金额"; + this.gridColumn9.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn9.FieldName = "commissionTotalCost"; + this.gridColumn9.MinWidth = 17; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 3; + this.gridColumn9.Width = 66; + // + // gridColumn7 + // + this.gridColumn7.Caption = "总佣金"; + this.gridColumn7.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn7.FieldName = "commission"; + this.gridColumn7.MinWidth = 17; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + this.gridColumn7.Width = 66; + // + // gridColumn8 + // + this.gridColumn8.Caption = "客户所得"; + this.gridColumn8.DisplayFormat.FormatString = "{0:c2}"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn8.FieldName = "endpoint"; + this.gridColumn8.MinWidth = 17; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 5; + this.gridColumn8.Width = 66; + // + // gridColumn21 + // + this.gridColumn21.Caption = "一级提成"; + this.gridColumn21.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn21.FieldName = "db_point"; + this.gridColumn21.MinWidth = 17; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 6; + this.gridColumn21.Width = 66; + // + // gridColumn20 + // + this.gridColumn20.Caption = "二级提成"; + this.gridColumn20.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn20.FieldName = "db_point"; + this.gridColumn20.MinWidth = 17; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 7; + this.gridColumn20.Width = 66; + // + // gridColumn19 + // + this.gridColumn19.Caption = "三级提成"; + this.gridColumn19.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn19.FieldName = "db_point"; + this.gridColumn19.MinWidth = 17; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 8; + this.gridColumn19.Width = 66; + // + // gridColumn18 + // + this.gridColumn18.Caption = "群负责人提成"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn18.FieldName = "db_point"; + this.gridColumn18.MinWidth = 17; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.OptionsColumn.AllowEdit = false; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 9; + this.gridColumn18.Width = 66; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户昵称"; + this.gridColumn6.FieldName = "usernick"; + this.gridColumn6.MinWidth = 17; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 10; + this.gridColumn6.Width = 105; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户名"; + this.gridColumn5.FieldName = "username"; + this.gridColumn5.MinWidth = 105; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 11; + this.gridColumn5.Width = 105; + // + // gridColumn1 + // + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "goodsName"; + this.gridColumn1.MinWidth = 17; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 12; + this.gridColumn1.Width = 306; + // + // gridColumn3 + // + this.gridColumn3.Caption = "商品编号"; + this.gridColumn3.FieldName = "goodsId"; + this.gridColumn3.MinWidth = 105; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 13; + this.gridColumn3.Width = 105; + // + // gridColumn10 + // + this.gridColumn10.Caption = "商品单价"; + this.gridColumn10.FieldName = "goodsFinalPrice"; + this.gridColumn10.MinWidth = 17; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 14; + this.gridColumn10.Width = 66; + // + // gridColumn11 + // + this.gridColumn11.Caption = "购买数量"; + this.gridColumn11.FieldName = "goodsCount"; + this.gridColumn11.MinWidth = 17; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 15; + this.gridColumn11.Width = 66; + // + // gridColumn2 + // + this.gridColumn2.Caption = "冻结时间"; + this.gridColumn2.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn2.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn2.FieldName = "db_endtime"; + this.gridColumn2.MinWidth = 17; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 16; + this.gridColumn2.Width = 90; + // + // gridColumn24 + // + this.gridColumn24.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn24.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn24.Caption = "机器人昵称"; + this.gridColumn24.FieldName = "robotnick"; + this.gridColumn24.MinWidth = 17; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 17; + this.gridColumn24.Width = 66; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "机器人账号"; + this.gridColumn22.FieldName = "robotname"; + this.gridColumn22.MinWidth = 17; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 18; + this.gridColumn22.Width = 66; + // + // gridColumn16 + // + this.gridColumn16.Caption = "联盟账号"; + this.gridColumn16.FieldName = "db_cpsname"; + this.gridColumn16.MinWidth = 17; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 19; + this.gridColumn16.Width = 87; + // + // gridColumn17 + // + this.gridColumn17.Caption = "联盟昵称"; + this.gridColumn17.FieldName = "db_cpsnick"; + this.gridColumn17.MinWidth = 17; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 20; + this.gridColumn17.Width = 87; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "推广位"; + this.gridColumn13.FieldName = "pid"; + this.gridColumn13.MinWidth = 105; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 21; + this.gridColumn13.Width = 105; + // + // gridColumn23 + // + this.gridColumn23.Caption = "店铺编码"; + this.gridColumn23.FieldName = "mallId"; + this.gridColumn23.MinWidth = 17; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.OptionsColumn.AllowEdit = false; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 22; + this.gridColumn23.Width = 66; + // + // gridColumn12 + // + this.gridColumn12.Caption = "预付订单"; + this.gridColumn12.FieldName = "isPrepay"; + this.gridColumn12.MinWidth = 17; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 23; + this.gridColumn12.Width = 66; + // + // gridColumn25 + // + this.gridColumn25.Caption = "自推自买"; + this.gridColumn25.FieldName = "selfBuy"; + this.gridColumn25.MinWidth = 17; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.OptionsColumn.AllowEdit = false; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 24; + this.gridColumn25.Width = 66; + // + // gridColumn26 + // + this.gridColumn26.Caption = "尺码"; + this.gridColumn26.FieldName = "sizeId"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.OptionsColumn.AllowEdit = false; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 25; + this.gridColumn26.Width = 66; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.EmbeddedNavigator.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.gridControl1.Location = new System.Drawing.Point(3, 86); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(947, 322); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.绑定用户ToolStripMenuItem, + this.解绑ToolStripMenuItem, + this.用户个人信息ToolStripMenuItem, + this.订单状态操作ToolStripMenuItem, + this.刷新ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.一键结算ToolStripMenuItem, + this.重新计算未结算订单ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 202); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 绑定用户ToolStripMenuItem + // + this.绑定用户ToolStripMenuItem.Name = "绑定用户ToolStripMenuItem"; + this.绑定用户ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.绑定用户ToolStripMenuItem.Text = "绑定"; + this.绑定用户ToolStripMenuItem.Click += new System.EventHandler(this.绑定用户ToolStripMenuItem_Click); + // + // 解绑ToolStripMenuItem + // + this.解绑ToolStripMenuItem.Name = "解绑ToolStripMenuItem"; + this.解绑ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.解绑ToolStripMenuItem.Text = "解绑"; + this.解绑ToolStripMenuItem.Click += new System.EventHandler(this.解绑ToolStripMenuItem_Click); + // + // 用户个人信息ToolStripMenuItem + // + this.用户个人信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看用户信息ToolStripMenuItem, + this.toolStripSeparator2, + this.所有阿里妈妈订单ToolStripMenuItem, + this.所有多多进宝订单ToolStripMenuItem, + this.所有京东联盟订单ToolStripMenuItem, + this.所有唯品联盟订单ToolStripMenuItem, + this.所有苏宁易购订单ToolStripMenuItem, + this.所有快手联盟订单ToolStripMenuItem, + this.toolStripSeparator1, + this.积分日志ToolStripMenuItem, + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.用户个人信息ToolStripMenuItem.Name = "用户个人信息ToolStripMenuItem"; + this.用户个人信息ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.用户个人信息ToolStripMenuItem.Text = "用户个人信息"; + // + // 查看用户信息ToolStripMenuItem + // + this.查看用户信息ToolStripMenuItem.Name = "查看用户信息ToolStripMenuItem"; + this.查看用户信息ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.查看用户信息ToolStripMenuItem.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem.Click += new System.EventHandler(this.查看用户信息ToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6); + // + // 所有阿里妈妈订单ToolStripMenuItem + // + this.所有阿里妈妈订单ToolStripMenuItem.Name = "所有阿里妈妈订单ToolStripMenuItem"; + this.所有阿里妈妈订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有阿里妈妈订单ToolStripMenuItem.Text = "所有阿里妈妈订单"; + this.所有阿里妈妈订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有多多进宝订单ToolStripMenuItem + // + this.所有多多进宝订单ToolStripMenuItem.Name = "所有多多进宝订单ToolStripMenuItem"; + this.所有多多进宝订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有多多进宝订单ToolStripMenuItem.Text = "所有多多进宝订单"; + this.所有多多进宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有京东联盟订单ToolStripMenuItem + // + this.所有京东联盟订单ToolStripMenuItem.Name = "所有京东联盟订单ToolStripMenuItem"; + this.所有京东联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有京东联盟订单ToolStripMenuItem.Text = "所有京东联盟订单"; + this.所有京东联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有唯品联盟订单ToolStripMenuItem + // + this.所有唯品联盟订单ToolStripMenuItem.Name = "所有唯品联盟订单ToolStripMenuItem"; + this.所有唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有唯品联盟订单ToolStripMenuItem.Text = "所有唯品联盟订单"; + this.所有唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 所有苏宁易购订单ToolStripMenuItem + // + this.所有苏宁易购订单ToolStripMenuItem.Name = "所有苏宁易购订单ToolStripMenuItem"; + this.所有苏宁易购订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有苏宁易购订单ToolStripMenuItem.Text = "所有苏宁易购订单"; + this.所有苏宁易购订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6); + // + // 积分日志ToolStripMenuItem + // + this.积分日志ToolStripMenuItem.Name = "积分日志ToolStripMenuItem"; + this.积分日志ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.积分日志ToolStripMenuItem.Text = "积分日志"; + this.积分日志ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 订单状态操作ToolStripMenuItem + // + this.订单状态操作ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.冻结延期ToolStripMenuItem, + this.立即结算ToolStripMenuItem1, + this.立即失效ToolStripMenuItem1}); + this.订单状态操作ToolStripMenuItem.Name = "订单状态操作ToolStripMenuItem"; + this.订单状态操作ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.订单状态操作ToolStripMenuItem.Text = "订单状态操作"; + // + // 冻结延期ToolStripMenuItem + // + this.冻结延期ToolStripMenuItem.Name = "冻结延期ToolStripMenuItem"; + this.冻结延期ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.冻结延期ToolStripMenuItem.Text = "冻结延期"; + this.冻结延期ToolStripMenuItem.Click += new System.EventHandler(this.冻结延期ToolStripMenuItem_Click); + // + // 立即结算ToolStripMenuItem1 + // + this.立即结算ToolStripMenuItem1.Name = "立即结算ToolStripMenuItem1"; + this.立即结算ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即结算ToolStripMenuItem1.Text = "立即结算"; + this.立即结算ToolStripMenuItem1.Click += new System.EventHandler(this.立即结算ToolStripMenuItem_Click); + // + // 立即失效ToolStripMenuItem1 + // + this.立即失效ToolStripMenuItem1.Name = "立即失效ToolStripMenuItem1"; + this.立即失效ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.立即失效ToolStripMenuItem1.Text = "立即失效"; + this.立即失效ToolStripMenuItem1.Click += new System.EventHandler(this.立即失效ToolStripMenuItem_Click); + // + // 刷新ToolStripMenuItem + // + this.刷新ToolStripMenuItem.Name = "刷新ToolStripMenuItem"; + this.刷新ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.刷新ToolStripMenuItem.Text = "刷新"; + this.刷新ToolStripMenuItem.Click += new System.EventHandler(this.刷新ToolStripMenuItem_Click); + // + // 一键结算ToolStripMenuItem + // + this.一键结算ToolStripMenuItem.Name = "一键结算ToolStripMenuItem"; + this.一键结算ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.一键结算ToolStripMenuItem.Text = "一键结算(隐藏)"; + this.一键结算ToolStripMenuItem.Visible = false; + this.一键结算ToolStripMenuItem.Click += new System.EventHandler(this.一键结算ToolStripMenuItem_Click); + // + // 重新计算未结算订单ToolStripMenuItem + // + this.重新计算未结算订单ToolStripMenuItem.Name = "重新计算未结算订单ToolStripMenuItem"; + this.重新计算未结算订单ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.重新计算未结算订单ToolStripMenuItem.Text = "重新计算未结算订单"; + this.重新计算未结算订单ToolStripMenuItem.Visible = false; + this.重新计算未结算订单ToolStripMenuItem.Click += new System.EventHandler(this.重新计算未结算订单ToolStripMenuItem_Click); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 413); + this.pageControl1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(949, 25); + this.pageControl1.TabIndex = 5; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.checkBox_isOld); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(949, 75); + this.groupControl1.TabIndex = 3; + this.groupControl1.Text = "搜索条件"; + // + // checkBox_isOld + // + this.checkBox_isOld.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox_isOld.AutoSize = true; + this.checkBox_isOld.Checked = true; + this.checkBox_isOld.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBox_isOld.Location = new System.Drawing.Point(795, 30); + this.checkBox_isOld.Name = "checkBox_isOld"; + this.checkBox_isOld.Size = new System.Drawing.Size(134, 32); + this.checkBox_isOld.TabIndex = 14; + this.checkBox_isOld.Text = "搜索一年以内的数据\r\n查询速度慢的请勾选"; + this.checkBox_isOld.UseVisualStyleBackColor = true; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = ""; + this.comboBoxEdit3.Location = new System.Drawing.Point(325, 48); + this.comboBoxEdit3.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(102, 20); + this.comboBoxEdit3.TabIndex = 13; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "不限状态"; + this.comboBoxEdit2.Location = new System.Drawing.Point(325, 25); + this.comboBoxEdit2.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "不限状态", + "订单付款", + "订单失效", + "全额退款", + "部分退款", + "订单冻结", + "订单结算"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(102, 20); + this.comboBoxEdit2.TabIndex = 13; + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(437, 38); + this.checkBox1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(54, 18); + this.checkBox1.TabIndex = 12; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(495, 49); + this.dateTimePicker2.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(141, 22); + this.dateTimePicker2.TabIndex = 11; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(495, 25); + this.dateTimePicker1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(141, 22); + this.dateTimePicker1.TabIndex = 10; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(28, 40); + this.labelControl1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(674, 32); + this.simpleButton1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(88, 31); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(211, 37); + this.comboBoxEdit1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "订单编号", + "商品编号", + "商品标题", + "客户编号", + "客户账号", + "客户昵称", + "店铺编码", + "推广位PID", + "联盟账号", + "联盟昵称", + "未绑定用户"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.Tag = "comboboxedit"; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + this.comboBoxEdit1.Click += new System.EventHandler(this.comboBoxEdit1_Click); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(67, 37); + this.textEdit1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(133, 20); + this.textEdit1.TabIndex = 1; + this.textEdit1.Tag = "textedit"; + // + // 所有快手联盟订单ToolStripMenuItem + // + this.所有快手联盟订单ToolStripMenuItem.Name = "所有快手联盟订单ToolStripMenuItem"; + this.所有快手联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.所有快手联盟订单ToolStripMenuItem.Text = "所有快手联盟订单"; + this.所有快手联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // cps_order_weipinhui + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.groupControl1); + this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.Name = "cps_order_weipinhui"; + this.Size = new System.Drawing.Size(949, 438); + this.Load += new System.EventHandler(this.cps_order_weipinhui_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraGrid.GridControl gridControl1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 绑定用户ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 解绑ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 用户个人信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 所有阿里妈妈订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有多多进宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有京东联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 订单状态操作ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 冻结延期ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 立即结算ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 立即失效ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 刷新ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 一键结算ToolStripMenuItem; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.ToolStripMenuItem 所有唯品联盟订单ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private System.Windows.Forms.CheckBox checkBox_isOld; + private System.Windows.Forms.ToolStripMenuItem 所有苏宁易购订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 重新计算未结算订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 所有快手联盟订单ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/cps_order_weipinhui.cs b/FLSystem/Forms/cps_order_weipinhui.cs new file mode 100644 index 0000000..f2407f7 --- /dev/null +++ b/FLSystem/Forms/cps_order_weipinhui.cs @@ -0,0 +1,1005 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using Api.Framework.Enums; +using Api.Framework.Tools; +using CsharpHttpHelper; +using Api.Framework; +using FLSystem.Events; +using System.Threading; +using Api.Framework.Events; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Model; +using SqlSugar; +using UI.Framework.Forms; +using Chat.Framework; + +namespace FLSystem.Forms +{ + public partial class cps_order_weipinhui : DevExpress.XtraEditors.XtraUserControl + { + public cps_order_weipinhui() + { + InitializeComponent(); + } + + public class view_cps_order_weipinhui + { + public long id { get; set; } + public string orderSn { get; set; } + public SystemOrderStatus db_status { get; set; } + + private string _robotname; + /// + /// 机器人账号 + /// + public string robotname + { + get { return _robotname; } + set { if (string.IsNullOrEmpty(value)) _robotname = string.Empty; else _robotname = value; } + } + + /// + /// 机器人昵称 + /// + public string robotnick { get; set; } + + private string _username; + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + + public long db_userid { get; set; } + + public string db_point { get; set; } + public string db_cpsname { get; set; } + public string db_cpsnick { get; set; } + public DateTime db_endtime { get; set; } + public string mallId { get; set; } + + /// + /// 是否自推自买 0-否,1-是 + /// + public WeipinhuiShiFou selfBuy { get; set; } + + /// + /// 下单时间 时间戳 单位毫秒 + /// + public long orderTime { get; set; } + + /// + /// 商品id + /// + public string goodsId { get; set; } + /// + /// 商品名称 + /// + public string goodsName { get; set; } + + /// + /// 商品数量 + /// + public int goodsCount { get; set; } + + /// + /// 商品成交价(元,保留两位小数,商品成交价上线之后的订单才有该值) + /// + public double goodsFinalPrice { get; set; } + + /// + /// 商品计佣金额(元,保留两位小数) + /// + public double commissionTotalCost { get; set; } + /// + /// 商品佣金比例(%) + /// + public double commissionRate { get; set; } + /// + /// 商品佣金金额(元,保留两位小数) + /// + public double commission { get; set; } + + /// + /// 推广PID:目前等同于channelTag + /// + public string pid { get; set; } + + /// + /// 售后订单佣金变动:仅在订单完结之后发生售后行为时返回 + /// + public string afterSaleChangeCommission { get; set; } + /// + /// 售后订单总商品数量变动:仅在订单完结之后发生售后行为时返回 + /// + public string afterSaleChangeGoodsCount { get; set; } + + /// + /// 是否预付订单:0-否,1-是 + /// + public WeipinhuiShiFou isPrepay { get; set; } + + /// + /// 订单归因方式:0-常规推广,1-惊喜红包,2-锁粉,3-超级红包 + /// + public WeipinhuiGuiYin orderTrackReason { get; set; } + + public string sizeId { get; set; } + } + + private void cps_order_weipinhui_Load(object sender, EventArgs e) + { + simpleButton1_Click(this.simpleButton1, null); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + public cps_order_weipinhui(string textedit = "") + { + InitializeComponent(); + this.textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 5; + this.checkBox1.Checked = false; + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + comboBoxEdit3.SelectedIndex = 0; + #endregion + + try + { + this.pageControl1.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var isOld = true; + List result = null; + //List conModels = new List(); + var sqlwhere = string.Empty; + if (this.checkBox1.Checked) + { + isOld = false; + //sqlwhere += $" and '{this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss")}' <= orderTime and orderTime <= '{this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss")}'"; + sqlwhere += $" and '{HttpExtend.GetTimeStamp(this.dateTimePicker1.Value)}000' <= orderTime and orderTime <= '{HttpExtend.GetTimeStamp(this.dateTimePicker2.Value)}000'"; + } + + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword) || comboBoxEdit1.Text == "未绑定用户") + { + switch (this.comboBoxEdit1.Text) + { + case "订单编号": + sqlwhere += $" and orderSn = '{keyword}'"; + break; + case "商品编号": + sqlwhere += $" and goodsId = '{keyword}'"; + break; + case "商品标题": + sqlwhere += $" and goodsName like '%{keyword}%'"; + break; + case "客户编号": + sqlwhere += $" and db_userid = '{keyword}'"; + break; + case "客户账号": + var ids = FindMemberIdByKey("username", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "客户昵称": + ids = FindMemberIdByKey("usernick", keyword); + if (ids != null) + { + if (ids.Count == 0) + ids.Add("-1"); + sqlwhere += $" and db_userid in ('{string.Join("','", ids)}')"; + } + break; + case "店铺编码": + sqlwhere += $" and mallId = '{keyword}'"; + break; + case "推广位PID": + sqlwhere += $" and pid = '{keyword}'"; + break; + case "联盟账号": + sqlwhere += $" and db_cpsname = '{keyword}'"; + break; + case "联盟昵称": + sqlwhere += $" and db_cpsnick = '{keyword}'"; + break; + case "未绑定用户": + sqlwhere += $" and db_userid = '0'"; + break; + } + } + + var status = this.comboBoxEdit2.SelectedIndex == 0 ? SystemOrderStatus.订单未知 : Util.ConvertEnum(this.comboBoxEdit2.Text); + + if (status != SystemOrderStatus.订单未知) + sqlwhere += $" and db_status = '{((int)status).ToString()}'"; + + if (this.comboBoxEdit3.SelectedIndex != 0) + sqlwhere += $" and db_robotname = '{comboBoxEdit3.Text.Trim()}'"; + + //总记录数 + int totalNumber = 0; + + if (isOld && checkBox_isOld.Checked) + { + //sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= orderTime"; + sqlwhere += $" and '{HttpExtend.GetTimeStamp(DateTime.Now.AddYears(-1))}000' <= orderTime"; + } + + sqlwhere += $" order by id desc"; + + var getCount = session.Find("select count(*) from fl_order_weipinhui where 1=1 " + sqlwhere); + if (getCount != null && getCount.Count != 0) + totalNumber = getCount[0]; + + sqlwhere += $" limit {(index - 1) * pagesize},{pagesize}"; + + var resultTmp = session.Find("select * from fl_order_weipinhui where 1=1 " + sqlwhere); + + result = new List(); + foreach (var o in resultTmp) + { + result.Add(new view_cps_order_weipinhui() + { + id = o.id, + db_cpsname = o.db_cpsname, + db_cpsnick = o.db_cpsnick, + db_endtime = o.db_endtime, + db_point = o.db_point, + db_status = o.db_status, + goodsId = o.goodsId, + goodsName = o.goodsName, + goodsFinalPrice = o.goodsFinalPrice, + goodsCount = o.goodsCount, + commissionRate = o.commissionRate, + commissionTotalCost = o.commissionTotalCost, + orderTime = o.orderTime, + orderSn = o.orderSn, + commission = o.commission, + pid = o.pid, + robotname = o.db_robotname, + db_userid = o.db_userid, + orderTrackReason = o.orderTrackReason, + isPrepay = o.isPrepay, + afterSaleChangeGoodsCount = o.afterSaleChangeGoodsCount, + afterSaleChangeCommission = o.afterSaleChangeCommission, + selfBuy = o.selfBuy, + mallId = o.mallId, + sizeId = o.sizeId + //username = u.username, + //usernick = u.usernick + }); + } + if (result.Count != 0) + { + #region 附加用户 + var bindUsersList = result.Where(f => f.db_userid != 0).Select(f => f.db_userid.ToString()).ToList(); + var memberData = new List(); + if (bindUsersList != null && bindUsersList.Count != 0) + memberData = session.Queryable().Where(new List() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + int count = 1; + foreach (var member in memberData) + { + count++; + var items = result.Where(f => f.db_userid == member.id).ToList(); + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(50); + + foreach (var item in items) + { + item.usernick = member.usernick; + item.username = member.username; + } + } + #endregion + + #region 附加机器人信息 + var robotList = result.Where(f => !string.IsNullOrWhiteSpace(f.robotname)).GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + var robotData = session.FindRobots().Where(f => robotList.Contains(f.name)).ToList(); + foreach (var robot in robotData) + { + var items = result.Where(f => f.robotname == robot.name).ToList(); + foreach (var item in items) + { + item.robotnick = robot.nick; + } + } + #endregion + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + }, this.gridControl1, 50, false, true); + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("cps_type") && e.Commons.ContainsKey("username")) + { + var cps_type = (CpsType)int.Parse(e.Commons["cps_type"].ToString()); + if (cps_type == CpsType.唯品联盟) + { + textEdit1.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 5; + comboBoxEdit3.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + checkBox1.Checked = false; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + } + + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + /// + /// 条件查询(用户账号/用户昵称),模糊查询,获取用户的id + /// + /// 查询的字段 + /// 模糊的关键词 + /// + private List FindMemberIdByKey(string type, string keyword) + { + try + { + var session = ApiClient.GetSession(); + return session.Find($"select id from fl_member_info where {type} like '%{keyword}%'").Select(f => f.ToString()).ToList(); + } + catch (Exception ex) + { } + return new List(); + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "软件状态": + e.DisplayText = Util.ConvertEnum(int.Parse(e.Value.ToString())).ToString(); + break; + case "一级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardone"].ToString(); + break; + case "二级提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardtwo"].ToString(); + break; + case "三级提成": + { + var result = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower()); + if (result != null && result.ContainsKey("awardthree")) + e.DisplayText = result["awardthree"].ToString(); + else + e.DisplayText = "0"; + } + break; + case "群负责人提成": + e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString().ToLower())["awardcreate"].ToString(); + break; + case "订单类型": + e.DisplayText = e.Value.ToString(); + break; + case "下单时间": + e.DisplayText = Util.GetDateTime(long.Parse(e.Value.ToString())).ToString("yyyy-MM-dd HH:mm:ss"); + break; + } + } + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + var row = e.Row as view_cps_order_weipinhui; + if (e.Column.Caption == "客户所得") + { + var point = CsharpHttpHelper.HttpHelper.JsonToObject(row.db_point) as ItemPoint; + if (point != null) + e.Value = point.UserPoint; + else + e.Value = 0; + } + else if (e.Column.Caption == "预付订单") + e.Value = row.isPrepay.ToString(); + else if (e.Column.Caption == "自推自买") + e.Value = row.selfBuy.ToString(); + } + + private void 刷新ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var info = this.gridView1.GetRow(rows[0]) as view_cps_order_weipinhui; + if (XtraMessageBox.Show("您确定要删除选中数据嘛?\r\n" + info.goodsName, "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_order_weipinhui where id=" + info.id); + } + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.textEdit1.Enabled = (comboBoxEdit1.SelectedIndex != 0 && comboBoxEdit1.SelectedIndex != 11); + if (!textEdit1.Enabled) + this.textEdit1.Text = string.Empty; + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + this.dateTimePicker1.Enabled = this.dateTimePicker2.Enabled = this.checkBox1.Checked; + } + + /// + /// 订单绑定 + /// + /// + /// + private void 绑定用户ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_weipinhui; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception("该订单状态为已完结,不允许修改!"); + + var session = ApiClient.GetSession(); + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null) + { + if (member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + } + + select_member_form select_form = new select_member_form(); + select_form.ShowDialog(); + if (select_form.fl_member_info != null) + { + var weipinhui = session.FindSingle("id = @id", new { id = row.id }); + if (weipinhui != null) + { + if (weipinhui.db_robottype == 0) weipinhui.db_robottype = select_form.fl_member_info.robot_type; + if (string.IsNullOrWhiteSpace(weipinhui.db_robotname)) weipinhui.db_robotname = select_form.fl_member_info.robot_name; + + var itempoint = session.FindItemPoint(select_form.fl_member_info, weipinhui.commission, weipinhui.goodsCount, CpsType.唯品联盟); + if (itempoint != null) + { + weipinhui.db_point = HttpHelper.ObjectToJson(itempoint); + weipinhui.db_userpoint = itempoint.UserPoint; + } + + weipinhui.db_userid = select_form.fl_member_info.id; + session.SaveOrUpdate(weipinhui); + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id", new { userid = weipinhui.db_userid, itemid = weipinhui.goodsId, adzoneid = weipinhui.pid, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (weipinhui.id == 0) + session.SaveOrUpdate(weipinhui); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = weipinhui.id, + createtime = DateTime.Now, + cpstype = CpsType.唯品联盟 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + } + simpleButton1_Click(null, null); + + //更新显示值 + row.db_userid = select_form.fl_member_info.id; + row.username = select_form.fl_member_info.username; + row.usernick = select_form.fl_member_info.usernick; + row.db_point = weipinhui.db_point; + + select_form.fl_member_info.bind_order++; + + #region 首次付款时间 + try + { + var record = session.FindStatisticsRecord(select_form.fl_member_info.id); + if (record == null) + { + record = new fl_statistics_record() { uid = select_form.fl_member_info.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + } + catch (Exception) + { } + #endregion + + session.UpdateMemberGroup(select_form.fl_member_info); + } + + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// + /// 订单解绑 + /// + /// + /// + private void 解绑ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_weipinhui; + var db_status = row.db_status; + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款) + throw new Exception("该订单状态为已完结,不允许解绑!"); + + var session = ApiClient.GetSession(); + + if (row.db_userid != 0) + { + var member = session.FindMemberInfoById(row.db_userid); + if (member != null && member.bind_order > 0) + { + member.bind_order--; + member = session.UpdateMemberGroup(member); + } + } + + session.ExcuteSQL("delete from fl_query_hist where itemid = @num_iid", new { num_iid = row.goodsId }); + session.ExcuteSQL("update fl_order_weipinhui set db_userid = @userid where id=@id", new { id = row.id, userid = 0 }); + session.ExcuteSQL("delete from fl_query_ratio_hist where db_orderid=@id", new { id = row.id }); + + //更新显示值 + row.db_userid = 0; + row.username = string.Empty; + row.usernick = string.Empty; + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要结算选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_weipinhui; + var db_status = row.db_status; + + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单创建 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.订单退款) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + //var weipinhui = session.FindSingle("orderSn = @orderSn", new { orderSn = row.orderSn }); + var weipinhui = session.FindSingle("orderSn=@orderSn and goodsId=@goodsId and sizeId = @sizeId", new { orderSn = row.orderSn, goodsId = row.goodsId, sizeId = row.sizeId }); + if (weipinhui == null) throw new Exception("数据查询失败,请稍后重试"); + weipinhui.db_endtime = DateTime.Now; + weipinhui.db_status = SystemOrderStatus.订单冻结; + weipinhui.orderSubStatusName = WeipinhuiOrderSubStatusName.已结算; + var task = TimerTask.GetTimer() as DownWeipinhuiTimer; + var notices = new List(); + task.UpdateOrder(weipinhui, session, notices); + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_weipinhui; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单结算; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 查看用户信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据; + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary(); + common["control_name"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", "").Replace("所有", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + /// + /// 查询用户对应积分列表 + /// + /// + /// + private void 积分ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + var common = new Dictionary(); + common["control_name"] = "提现管理"; + common["query_type"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 立即失效ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var result = XtraMessageBox.Show("确定要失效选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_weipinhui; + var db_status = row.db_status; + + var session = ApiClient.GetSession(); + var weipinhui = session.FindSingle("orderSn=@orderSn and goodsId=@goodsId and sizeId = @sizeId", new { orderSn = row.orderSn, goodsId = row.goodsId, sizeId = row.sizeId }); + if (weipinhui == null) throw new Exception("数据查询失败,请稍后重试"); + + var flag = false; + var notices = new List(); + if (db_status == SystemOrderStatus.订单结算) + flag = true; + else if (weipinhui.IsFinish()) + throw new Exception($"选中订单:{db_status},不予操作"); + + weipinhui.orderSubStatusName = WeipinhuiOrderSubStatusName.手动失效; + weipinhui.db_endtime = DateTime.Now; + weipinhui.db_status = SystemOrderStatus.订单失效; + var task = TimerTask.GetTimer() as DownWeipinhuiTimer; + + if (!flag) + task.UpdateOrder(weipinhui, session, notices); + else + { + new OrderHelper().DeductWeipinhuiOrderPoint(notices, weipinhui); + session.SaveOrUpdate(weipinhui); + } + + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_weipinhui; + tasks.Add(item); + } + //更新显示值 + row.db_status = SystemOrderStatus.订单失效; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void contextMenuStrip1_Opening(object sender, System.ComponentModel.CancelEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + this.用户个人信息ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "username") != null; + this.冻结延期ToolStripMenuItem.Enabled = this.gridView1.GetRowCellValue(rows[0], "db_status").ToString() == "订单冻结"; + } + else + e.Cancel = true; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 冻结延期ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定要延长冻结选中订单?", "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as view_cps_order_weipinhui; + var db_status = row.db_status; + + if (db_status != SystemOrderStatus.订单冻结) + throw new Exception($"选中订单:{db_status},不予操作"); + + var session = ApiClient.GetSession(); + var endtime_form = new setting_endtime_form(row.db_endtime); + endtime_form.ShowDialog(); + if (endtime_form.newtime == DateTime.MinValue) return; + var weipinhui = session.FindSingle("id = @id", new { id = row.id }); + if (endtime_form.newtime != row.db_endtime) + { + weipinhui.db_endtime = endtime_form.newtime; + session.Updateable(weipinhui).ExecuteCommand(); + } + row.db_endtime = endtime_form.newtime;//更新显示值 + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + /// + /// 要删除的@@@@@ + /// + /// + /// + private void 一键结算ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (MessageBox.Show("确定结算所有该所有的订单吗", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + var orders = ApiClient.GetSession().Find("select * from fl_order_weipinhui where db_userid != 0 and (db_status = @db_status1 or db_status = @db_status2)", new { db_status1 = SystemOrderStatus.订单付款, db_status2 = SystemOrderStatus.订单冻结 }); + + if (orders.Count != 0) + { + Task.Run(() => + { + var session = ApiClient.GetSession(); + try + { + var task = TimerTask.GetTimer() as DownWeipinhuiTimer; + var notices = new List(); + foreach (var order in orders) + { + tokenSource.Token.ThrowIfCancellationRequested(); + + order.orderSubStatusName = WeipinhuiOrderSubStatusName.已结算; + order.db_endtime = DateTime.Now; + order.db_status = SystemOrderStatus.订单冻结; + + task.UpdateOrder(order, session, notices); + } + + + XtraMessageBox.Show($"一键结算成功,一共结算{orders.Count}笔订单!", "温馨提示", MessageBoxButtons.OK); + } + catch (Exception) + { } + }, tokenSource.Token); + } + else + XtraMessageBox.Show($"当前无可结算的订单!", "温馨提示", MessageBoxButtons.OK); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void comboBoxEdit1_Click(object sender, EventArgs e) + { + + } + + private void 重新计算未结算订单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var db = ApiClient.GetSession(); + var orders = db.Queryable().Where(f => + f.db_userid != 0 && (f.db_status == SystemOrderStatus.订单付款 || + f.db_status == SystemOrderStatus.订单冻结 || + f.db_status == SystemOrderStatus.订单维权中)).ToList(); + EventClient.OnEvent("", $"唯品会需要重新计算的订单数:{orders.Count}"); + + foreach (var order in orders) + { + var member = db.FindMemberInfoById(order.db_userid); + var itempoint = db.FindItemPoint(member, order.commission, order.goodsCount, CpsType.唯品联盟); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + + db.SaveOrUpdate(order); + EventClient.OnEvent("", $"唯品会单号:{order.orderSn},重新计算完成"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"唯品会重新计算异常:{ex.Message}"); + } + } + } +} diff --git a/FLSystem/Forms/cps_order_weipinhui.resx b/FLSystem/Forms/cps_order_weipinhui.resx new file mode 100644 index 0000000..2396863 --- /dev/null +++ b/FLSystem/Forms/cps_order_weipinhui.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/FLSystem/Forms/data_report_control.Designer.cs b/FLSystem/Forms/data_report_control.Designer.cs new file mode 100644 index 0000000..e969056 --- /dev/null +++ b/FLSystem/Forms/data_report_control.Designer.cs @@ -0,0 +1,856 @@ +namespace FLSystem.Forms +{ + partial class data_report_control + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(data_report_control)); + this.panel1 = new System.Windows.Forms.Panel(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuS_Down = new System.Windows.Forms.ContextMenuStrip(this.components); + this.导出为EceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn36 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn49 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn33 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn34 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn35 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn28 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog(); + this.panel1.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuS_Down.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.labelControl4); + this.panel1.Controls.Add(this.labelControl3); + this.panel1.Controls.Add(this.groupBox1); + this.panel1.Controls.Add(this.gridControl1); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(883, 612); + this.panel1.TabIndex = 0; + // + // labelControl4 + // + this.labelControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl4.Appearance.BackColor = System.Drawing.Color.White; + this.labelControl4.Appearance.Font = new System.Drawing.Font("Tahoma", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelControl4.Appearance.Options.UseBackColor = true; + this.labelControl4.Appearance.Options.UseFont = true; + this.labelControl4.Location = new System.Drawing.Point(357, 207); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(167, 29); + this.labelControl4.TabIndex = 12; + this.labelControl4.Text = " 当 前 无 数 据 "; + // + // labelControl3 + // + this.labelControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl3.Appearance.BackColor = System.Drawing.Color.White; + this.labelControl3.Appearance.Font = new System.Drawing.Font("Tahoma", 18F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelControl3.Appearance.Options.UseBackColor = true; + this.labelControl3.Appearance.Options.UseFont = true; + this.labelControl3.Location = new System.Drawing.Point(357, 207); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(166, 29); + this.labelControl3.TabIndex = 11; + this.labelControl3.Text = "正 在 计 算 . . ."; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.comboBoxEdit3); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.dateTimePicker2); + this.groupBox1.Controls.Add(this.dateTimePicker1); + this.groupBox1.Location = new System.Drawing.Point(14, 13); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(856, 62); + this.groupBox1.TabIndex = 9; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 参 数 选 项 "; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = "今日报表"; + this.comboBoxEdit3.Location = new System.Drawing.Point(530, 27); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { + "今日报表", + "昨日报表", + "7日报表", + "30日报表", + "本月报表", + "上月报表", + "本年报表", + "上年报表"}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(109, 20); + this.comboBoxEdit3.TabIndex = 10; + this.comboBoxEdit3.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit3_SelectedIndexChanged); + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(667, 20); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(93, 35); + this.simpleButton1.TabIndex = 3; + this.simpleButton1.Text = " 查 询 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl2 + // + this.labelControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl2.Location = new System.Drawing.Point(148, 30); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 2; + this.labelControl2.Text = "日期范围:"; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(356, 30); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(4, 14); + this.labelControl1.TabIndex = 2; + this.labelControl1.Text = "-"; + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(370, 26); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(136, 22); + this.dateTimePicker2.TabIndex = 1; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(214, 26); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(136, 22); + this.dateTimePicker1.TabIndex = 0; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuS_Down; + this.gridControl1.Font = new System.Drawing.Font("Tahoma", 9F); + this.gridControl1.Location = new System.Drawing.Point(0, 81); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(883, 531); + this.gridControl1.TabIndex = 6; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuS_Down + // + this.contextMenuS_Down.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuS_Down.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.导出为EceToolStripMenuItem}); + this.contextMenuS_Down.Name = "contextMenuS_Down"; + this.contextMenuS_Down.Size = new System.Drawing.Size(142, 26); + // + // 导出为EceToolStripMenuItem + // + this.导出为EceToolStripMenuItem.Name = "导出为EceToolStripMenuItem"; + this.导出为EceToolStripMenuItem.Size = new System.Drawing.Size(141, 22); + this.导出为EceToolStripMenuItem.Text = "导出为Excel"; + this.导出为EceToolStripMenuItem.Click += new System.EventHandler(this.导出为EceToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Font = new System.Drawing.Font("Tahoma", 12F); + this.gridView1.Appearance.HeaderPanel.Options.UseFont = true; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn8, + this.gridColumn1, + this.gridColumn36, + this.gridColumn19, + this.gridColumn18, + this.gridColumn17, + this.gridColumn20, + this.gridColumn24, + this.gridColumn23, + this.gridColumn49, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4, + this.gridColumn33, + this.gridColumn5, + this.gridColumn34, + this.gridColumn6, + this.gridColumn35, + this.gridColumn22, + this.gridColumn21, + this.gridColumn28, + this.gridColumn27, + this.gridColumn26, + this.gridColumn25, + this.gridColumn7, + this.gridColumn9, + this.gridColumn10, + this.gridColumn11, + this.gridColumn13, + this.gridColumn12, + this.gridColumn14, + this.gridColumn16, + this.gridColumn15}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowFooter = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.OptionsView.ShowIndicator = false; + this.gridView1.OptionsView.ShowVerticalLines = DevExpress.Utils.DefaultBoolean.False; + this.gridView1.CustomSummaryCalculate += new DevExpress.Data.CustomSummaryEventHandler(this.gridView1_CustomSummaryCalculate); + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn8.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "平台"; + this.gridColumn8.FieldName = "chat_type"; + this.gridColumn8.MinWidth = 30; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 0; + this.gridColumn8.Width = 92; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "机器人"; + this.gridColumn1.FieldName = "robot_name"; + this.gridColumn1.MinWidth = 70; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 93; + // + // gridColumn36 + // + this.gridColumn36.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn36.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn36.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn36.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn36.Caption = "机器人昵称"; + this.gridColumn36.FieldName = "robot_nick"; + this.gridColumn36.MinWidth = 100; + this.gridColumn36.Name = "gridColumn36"; + this.gridColumn36.Visible = true; + this.gridColumn36.VisibleIndex = 2; + this.gridColumn36.Width = 132; + // + // gridColumn19 + // + this.gridColumn19.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn19.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn19.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn19.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn19.Caption = "淘宝有效付款"; + this.gridColumn19.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn19.FieldName = "tb_pay"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "tb_pay", "{0:0.##}")}); + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 3; + this.gridColumn19.Width = 120; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn18.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "京东有效付款"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn18.FieldName = "jd_pay"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "jd_pay", "{0:0.##}")}); + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 4; + this.gridColumn18.Width = 120; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn17.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "拼多多有效付款"; + this.gridColumn17.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn17.FieldName = "pdd_pay"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "pdd_pay", "{0:0.##}")}); + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + this.gridColumn17.Width = 120; + // + // gridColumn20 + // + this.gridColumn20.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn20.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn20.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn20.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn20.Caption = "唯品会有效付款"; + this.gridColumn20.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn20.FieldName = "wph_pay"; + this.gridColumn20.MinWidth = 22; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "wph_pay", "{0:0.##}")}); + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 6; + this.gridColumn20.Width = 120; + // + // gridColumn24 + // + this.gridColumn24.Caption = "苏宁有效付款"; + this.gridColumn24.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn24.FieldName = "sn_pay"; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 7; + this.gridColumn24.Width = 66; + // + // gridColumn23 + // + this.gridColumn23.Caption = "抖音有效付款"; + this.gridColumn23.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn23.FieldName = "dy_pay"; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 8; + this.gridColumn23.Width = 66; + // + // gridColumn49 + // + this.gridColumn49.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn49.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn49.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn49.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn49.Caption = "全部收入合计"; + this.gridColumn49.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn49.FieldName = "all_total_income"; + this.gridColumn49.MinWidth = 80; + this.gridColumn49.Name = "gridColumn49"; + this.gridColumn49.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "all_total_income", "{0:0.##}")}); + this.gridColumn49.Visible = true; + this.gridColumn49.VisibleIndex = 9; + this.gridColumn49.Width = 120; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "有效收入合计"; + this.gridColumn2.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn2.FieldName = "total_income"; + this.gridColumn2.MinWidth = 80; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "total_income", "{0:0.##}")}); + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 10; + this.gridColumn2.Width = 110; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "有效毛利合计"; + this.gridColumn3.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn3.FieldName = "total_margin"; + this.gridColumn3.MinWidth = 80; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "total_margin", "{0:0.##}")}); + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 11; + this.gridColumn3.Width = 123; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "淘宝订单量"; + this.gridColumn4.FieldName = "tb_order_count"; + this.gridColumn4.MinWidth = 80; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "tb_order_count", "{0:0.##}")}); + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 12; + this.gridColumn4.Width = 130; + // + // gridColumn33 + // + this.gridColumn33.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn33.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn33.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.Caption = "淘宝收入"; + this.gridColumn33.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn33.FieldName = "tb_income"; + this.gridColumn33.MinWidth = 80; + this.gridColumn33.Name = "gridColumn33"; + this.gridColumn33.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "tb_income", "{0:0.##}")}); + this.gridColumn33.Visible = true; + this.gridColumn33.VisibleIndex = 13; + this.gridColumn33.Width = 116; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn5.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "京东订单量"; + this.gridColumn5.FieldName = "jd_order_count"; + this.gridColumn5.MinWidth = 60; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "jd_order_count", "{0:0.##}")}); + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 14; + this.gridColumn5.Width = 99; + // + // gridColumn34 + // + this.gridColumn34.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn34.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn34.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn34.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn34.Caption = "京东收入"; + this.gridColumn34.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn34.FieldName = "jd_income"; + this.gridColumn34.MinWidth = 60; + this.gridColumn34.Name = "gridColumn34"; + this.gridColumn34.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "jd_income", "{0:0.##}")}); + this.gridColumn34.Visible = true; + this.gridColumn34.VisibleIndex = 15; + this.gridColumn34.Width = 95; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn6.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "拼多多订单量"; + this.gridColumn6.FieldName = "pdd_order_count"; + this.gridColumn6.MinWidth = 60; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "pdd_order_count", "{0:0.##}")}); + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 16; + this.gridColumn6.Width = 111; + // + // gridColumn35 + // + this.gridColumn35.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn35.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn35.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn35.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn35.Caption = "拼多多收入"; + this.gridColumn35.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn35.FieldName = "pdd_income"; + this.gridColumn35.MinWidth = 60; + this.gridColumn35.Name = "gridColumn35"; + this.gridColumn35.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "pdd_income", "{0:0.##}")}); + this.gridColumn35.Visible = true; + this.gridColumn35.VisibleIndex = 17; + this.gridColumn35.Width = 100; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "唯品会订单量"; + this.gridColumn22.FieldName = "wph_order_count"; + this.gridColumn22.MinWidth = 60; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "wph_order_count", "{0:0.##}")}); + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 18; + this.gridColumn22.Width = 111; + // + // gridColumn21 + // + this.gridColumn21.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn21.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn21.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn21.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn21.Caption = "唯品会收入"; + this.gridColumn21.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn21.FieldName = "wph_income"; + this.gridColumn21.MinWidth = 22; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "wph_income", "{0:0.##}")}); + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 19; + this.gridColumn21.Width = 100; + // + // gridColumn28 + // + this.gridColumn28.Caption = "苏宁订单量"; + this.gridColumn28.FieldName = "sn_order_count"; + this.gridColumn28.Name = "gridColumn28"; + this.gridColumn28.Visible = true; + this.gridColumn28.VisibleIndex = 20; + this.gridColumn28.Width = 66; + // + // gridColumn27 + // + this.gridColumn27.Caption = "苏宁收入"; + this.gridColumn27.FieldName = "sn_income"; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 21; + this.gridColumn27.Width = 66; + // + // gridColumn26 + // + this.gridColumn26.Caption = "抖音订单量"; + this.gridColumn26.FieldName = "dy_order_count"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 22; + this.gridColumn26.Width = 66; + // + // gridColumn25 + // + this.gridColumn25.Caption = "抖音收入"; + this.gridColumn25.FieldName = "dy_income"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 23; + this.gridColumn25.Width = 66; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn7.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "毛利率"; + this.gridColumn7.FieldName = "gross_margin"; + this.gridColumn7.MinWidth = 60; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 24; + this.gridColumn7.Width = 116; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn9.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "提现金额"; + this.gridColumn9.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn9.FieldName = "exchange_money"; + this.gridColumn9.MinWidth = 50; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "exchange_money", "{0:0.##}")}); + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 25; + this.gridColumn9.Width = 100; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn10.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "新增粉丝/人"; + this.gridColumn10.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn10.FieldName = "new_member"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "new_member", "{0:0.##}")}); + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 26; + this.gridColumn10.Width = 100; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn11.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "首次下单/人"; + this.gridColumn11.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn11.FieldName = "pay_order_count"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.OptionsColumn.AllowFocus = false; + this.gridColumn11.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "pay_order_count", "{0:0.##}")}); + this.gridColumn11.Width = 140; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "首次下单(所有粉丝)"; + this.gridColumn13.FieldName = "activeMemberCvr"; + this.gridColumn13.MinWidth = 50; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Custom, "activeMemberCvr", "", "activeMemberCvr")}); + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 27; + this.gridColumn13.Width = 190; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn12.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "首次查询/人"; + this.gridColumn12.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn12.FieldName = "query_count"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Sum, "query_count", "{0:0.##}")}); + this.gridColumn12.Width = 140; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn14.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "首次查询(所有粉丝)"; + this.gridColumn14.FieldName = "newQueryMemberCvr"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Custom, "newQueryMemberCvr", "", "newQueryMemberCvr")}); + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 28; + this.gridColumn14.Width = 190; + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn16.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "首次下单(仅今日粉)"; + this.gridColumn16.FieldName = "realPayMembers"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Custom, "realPayMembers", "", "realQueryMembers")}); + this.gridColumn16.Tag = ""; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 29; + this.gridColumn16.Width = 190; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn15.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "首次查询(仅今日粉)"; + this.gridColumn15.FieldName = "realQueryMembers"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Custom, "realQueryMembers", "", "realQueryMembers")}); + this.gridColumn15.Tag = ""; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 30; + this.gridColumn15.Width = 190; + // + // data_report_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScroll = true; + this.Controls.Add(this.panel1); + this.Name = "data_report_control"; + this.Size = new System.Drawing.Size(883, 612); + this.Load += new System.EventHandler(this.data_report_control_Load); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuS_Down.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn36; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn49; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn33; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn34; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn35; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private System.Windows.Forms.ContextMenuStrip contextMenuS_Down; + private System.Windows.Forms.ToolStripMenuItem 导出为EceToolStripMenuItem; + private System.Windows.Forms.SaveFileDialog saveFileDialog1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn28; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + } +} diff --git a/FLSystem/Forms/data_report_control.cs b/FLSystem/Forms/data_report_control.cs new file mode 100644 index 0000000..190c94f --- /dev/null +++ b/FLSystem/Forms/data_report_control.cs @@ -0,0 +1,669 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using CsharpHttpHelper; +using DevExpress.Data; +using DevExpress.XtraEditors; +using DevExpress.XtraGrid; +using DevExpress.XtraGrid.Columns; +using DevExpress.XtraGrid.Views.Grid; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace FLSystem.Forms +{ + public partial class data_report_control : XtraUserControl + { + public data_report_control() + { + InitializeComponent(); + } + + public static List ConvertTo(DataTable table, string name) + { + if (table == null) + { + return null; + } + List list = new List(); + + foreach (DataRow row in table.Rows) + { + list.Add(row[name].ToString()); + } + return list; + } + + private List recordList(List records) + { + var db = ApiClient.GetSession(); + var list = new List(); + foreach (var item in records) + { + var _member = db.FindMemberInfoById(item.uid); + if (_member != null) + list.Add(_member); + } + return list; + } + + private string formatStr = "{0}人 / {1}%"; + + /// + /// 刷新数据报表 + /// + private void RefreshDataReport(GridControl gridControl, GridView gridView, DateTime beginTime, DateTime endTime) + { + GC.Collect(); + IEnumerable pointHists = null; + IEnumerable allOrderAlimamas = null; + IEnumerable orderAlimamas = null; + IEnumerable allOrderJingdongs = null; + IEnumerable orderJingdongs = null; + IEnumerable allOrderPinduoduos = null; + IEnumerable orderPinduoduos = null; + IEnumerable allOrderWeipinhuis = null; + IEnumerable allOrderSunings = null; + IEnumerable allOrderDouyins = null; + IEnumerable orderWeipinhuis = null; + IEnumerable orderSunings = null; + IEnumerable orderDouyins = null; + IEnumerable newMembers = null; + + try + { + var begin_time = beginTime.Date; + var end_time = endTime.Date.AddDays(1); + + var _session = ApiClient.GetSession(); + List resultList = new List(); + object lock_result = new object(); + List actions = new List(); + var robots = new List(_session.FindRobots()); + robots.Add(new fl_robot_info() { name = "", type = ChatType.未知来源 }); + + pointHists = _session.Find("@begin_time <= crt_time and crt_time < @end_time and type = @type ", new { begin_time = begin_time, end_time = end_time, type = "提现扣除" }); + + allOrderAlimamas = _session.Find("select alipay_total_price as pay,pay_price as pay_real,db_status,db_robotname,db_robottype,pub_share_pre_fee as fee,commission as fee_real,db_point,item_num as num from fl_order_alimama where @begin_time <= create_time and create_time < @end_time", new { begin_time = begin_time, end_time = end_time }); + + orderAlimamas = allOrderAlimamas.Where(f => f.db_status == SystemOrderStatus.订单付款 || f.db_status == SystemOrderStatus.订单冻结 || f.db_status == SystemOrderStatus.订单结算 || f.db_status == SystemOrderStatus.部分退款); + + allOrderJingdongs = _session.Find("select estimateCosPrice as pay ,estimateCosPrice as pay_real,db_status,db_robotname,db_robottype,estimateFee as fee,actualFee as fee_real,db_point,skuNum as num from fl_order_jingdong where @begin_time <= orderTime and orderTime < @end_time and db_status in (1005,1002,1001,998)", new { begin_time = begin_time, end_time = end_time }); + + orderJingdongs = allOrderJingdongs.Where(f => f.db_status == SystemOrderStatus.订单付款 || f.db_status == SystemOrderStatus.订单冻结 || f.db_status == SystemOrderStatus.订单结算 || f.db_status == SystemOrderStatus.部分退款); + + allOrderPinduoduos = _session.Find("select order_amount as pay ,order_amount as pay_real,db_status,db_robotname,db_robottype,promotion_amount as fee,db_point,goods_quantity as num from fl_order_pinduoduo where @begin_time <= order_create_time and order_create_time < @end_time and db_status in (1005,1002,1001,998)", new { begin_time = begin_time, end_time = end_time }); + + orderPinduoduos = allOrderPinduoduos.Where(f => f.db_status == SystemOrderStatus.订单付款 || f.db_status == SystemOrderStatus.订单冻结 || f.db_status == SystemOrderStatus.订单结算 || f.db_status == SystemOrderStatus.部分退款); + + allOrderWeipinhuis = _session.Find("select commissionTotalCost as pay ,commissionTotalCost as pay_real,db_status,db_robotname,db_robottype,commission as fee,commission as fee_real,db_point,goodsCount as num from fl_order_weipinhui where @begin_time <= orderTime and orderTime < @end_time and db_status in (1005,1002,1001,998)", new { begin_time = Util.GetTimeSpan(begin_time, true), end_time = Util.GetTimeSpan(end_time, true) }); + + orderWeipinhuis = allOrderWeipinhuis.Where(f => f.db_status == SystemOrderStatus.订单付款 || f.db_status == SystemOrderStatus.订单冻结 || f.db_status == SystemOrderStatus.订单结算 || f.db_status == SystemOrderStatus.部分退款); + + #region 苏宁 + var ddd = _session.Ado.GetDataTable("select payAmount as pay ,payAmount as pay_real,db_status,db_robotname,db_robottype,prePayCommission as fee,prePayCommission as fee_real,db_point,saleNum as num from fl_order_suning where @begin_time <= payTime and payTime < @end_time and db_status in (1005,1002,1001,998)", new { begin_time = begin_time, end_time = end_time }); + + List suningList = new List(); + for (int i = 0; i < ddd.Rows.Count; i++) + { + var pay = double.Parse(ddd.Rows[i]["pay"].ToString()); + var pay_real = double.Parse(ddd.Rows[i]["pay_real"].ToString()); + var db_status = (SystemOrderStatus)int.Parse(ddd.Rows[i]["db_status"].ToString()); + var db_robotname = ddd.Rows[i]["db_robotname"].ToString(); + var db_robottype = (ChatType)int.Parse(ddd.Rows[i]["db_robottype"].ToString()); + var fee = double.Parse(ddd.Rows[i]["fee"].ToString()); + var fee_real = double.Parse(ddd.Rows[i]["fee_real"].ToString()); + var db_point = ddd.Rows[i]["db_point"].ToString(); + var num = int.Parse(ddd.Rows[i]["num"].ToString()); + + suningList.Add(new OrderTemp() { pay = pay, pay_real = pay_real, db_status = db_status, db_robotname = db_robotname, db_robottype = db_robottype, fee = fee, db_point = db_point, num = num }); + } + allOrderSunings = suningList; + #endregion + + //allOrderSunings = _session.Find("select payAmount as pay ,payAmount as pay_real,db_status,db_robotname,db_robottype,prePayCommission as fee,prePayCommission as fee_real,db_point,saleNum as num from fl_order_suning where @begin_time <= payTime and payTime < @end_time and db_status in (1005,1002,1001,998)", new { begin_time = begin_time, end_time = end_time }); + + orderSunings = allOrderSunings.Where(f => f.db_status == SystemOrderStatus.订单付款 || f.db_status == SystemOrderStatus.订单冻结 || f.db_status == SystemOrderStatus.订单结算 || f.db_status == SystemOrderStatus.部分退款); + + allOrderDouyins = _session.Find("select total_pay_amount as pay ,total_pay_amount as pay_real,db_status,db_robotname,db_robottype,estimated_comission as fee,estimated_comission as fee_real,db_point,1 as num from fl_order_douyin where @begin_time <= pay_time and pay_time < @end_time and db_status in (1005,1002,1001,998)", new { begin_time = Util.GetTimeSpan(begin_time, false), end_time = Util.GetTimeSpan(end_time, false) }); + orderDouyins = allOrderDouyins.Where(f => f.db_status == SystemOrderStatus.订单付款 || f.db_status == SystemOrderStatus.订单冻结 || f.db_status == SystemOrderStatus.订单结算 || f.db_status == SystemOrderStatus.部分退款); + + newMembers = _session.Find("@begin_time <= crt_time and crt_time < @end_time", new { begin_time = begin_time, end_time = end_time }); + + //时间段创建的用户集合 + var memberInfos = _session.Find("@begin_time <= crt_time and crt_time < @end_time", new { begin_time = begin_time, end_time = end_time }); + + #region 这个时间段所有首查用户 + var firstQueryStatistics = _session.Find("@begin_time <= ex3 and ex3 < @end_time", new { begin_time = HttpExtend.GetTimeStamp(begin_time), end_time = HttpExtend.GetTimeStamp(end_time) }); + var firstQueryMembers = recordList(firstQueryStatistics); + #endregion + + #region 这个时间段所有首次付款用户 + var firstPaytatistics = _session.Find("@begin_time <= ex4 and ex4 < @end_time", new { begin_time = HttpExtend.GetTimeStamp(begin_time), end_time = HttpExtend.GetTimeStamp(end_time) }); + var firstPayMembers = recordList(firstPaytatistics); + #endregion + + //首次查询 + //var statisticsRecords = _session.Find("select * from fl_statistics_record"); + //var statisticsMembers = recordList(firstPaytatistics); + + foreach (var _item in robots) + { + var item = _item; + actions.Add(new Action(delegate + { + try + { + var session = ApiClient.GetSession(); + #region 全部收入合计 第一个阿里妈妈。第二个京东。第三个拼多多。第四个唯品会。第五个苏宁。第六个抖音 + //decimal all_tb_income = (decimal)allOrderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//淘宝总金额 + var allOrderAlimamasTemp = allOrderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type);//公共的条件的临时集合 + decimal all_tb_income = (decimal)allOrderAlimamasTemp.Where(f => f.fee_real != 0).Sum(f => f.fee_real);//淘宝总金额-真实的佣金 + all_tb_income += (decimal)allOrderAlimamasTemp.Where(f => f.fee_real == 0).Sum(f => f.fee);//淘宝总金额-预估的佣金 + all_tb_income = all_tb_income * 0.9m; + + decimal all_jd_income = (decimal)allOrderJingdongs.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//京东总金额 + decimal all_pdd_income = (decimal)allOrderPinduoduos.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//拼多多总金额 + decimal all_wph_income = (decimal)allOrderWeipinhuis.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//唯品会总金额 + decimal all_sn_income = (decimal)allOrderSunings.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//苏宁总金额 + decimal all_dy_income = (decimal)allOrderDouyins.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => (f.fee / 100));//抖音总金额 + + decimal all_total_income = all_tb_income + all_jd_income + all_pdd_income + all_wph_income + all_sn_income + all_dy_income;//总佣金 + + //decimal all_tb_pay = (decimal)allOrderAlimamasTemp.Where(f => f.pay_real != 0).Sum(f => f.pay_real);//总付款金额 + #endregion + + #region 收入合计 第一个阿里妈妈。第二个京东。第三个拼多多。第四个唯品会。第五个苏宁。第六个抖音 + //var tb_income = (decimal)orderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//淘宝总佣金 + var orderAlimamasTemp = orderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type);//公共的条件的临时集合 + var tb_income = (decimal)orderAlimamasTemp.Where(f => f.fee_real != 0).Sum(f => f.fee_real);//淘宝总佣金-真实的佣金 + tb_income += (decimal)orderAlimamasTemp.Where(f => f.fee_real == 0).Sum(f => f.fee);//淘宝总佣金-预估佣金 + tb_income = tb_income * 0.9m; + + var orderJingdongsTemp = orderJingdongs.Where(f => f.db_robotname == item.name && f.db_robottype == item.type); + var jd_income = (decimal)orderJingdongsTemp.Sum(f => f.fee);//京东总佣金 + var orderPinduoduosTemp = orderPinduoduos.Where(f => f.db_robotname == item.name && f.db_robottype == item.type); + var pdd_income = (decimal)orderPinduoduosTemp.Sum(f => f.fee);//拼多多总佣金 + var orderWeipinhuisTemp = orderWeipinhuis.Where(f => f.db_robotname == item.name && f.db_robottype == item.type); + var wph_income = (decimal)orderWeipinhuisTemp.Sum(f => f.fee);//唯品会总佣金 + var orderSuningsTemp = orderSunings.Where(f => f.db_robotname == item.name && f.db_robottype == item.type); + var sn_income = (decimal)orderSuningsTemp.Sum(f => f.fee);//苏宁总佣金 + var orderDouyinsTemp = orderDouyins.Where(f => f.db_robotname == item.name && f.db_robottype == item.type); + var dy_income = (decimal)orderDouyinsTemp.Sum(f => (f.fee / 100));//抖音总佣金 + + + decimal total_income = tb_income + jd_income + pdd_income + wph_income + sn_income + dy_income;//总佣金 + + decimal tb_pay = (decimal)orderAlimamasTemp.Sum(f => f.pay);//淘宝有效的付款金额 + decimal jd_pay = (decimal)orderJingdongsTemp.Sum(f => f.pay);//京东有效的付款金额 + decimal pdd_pay = (decimal)orderPinduoduosTemp.Sum(f => f.pay);//拼多多有效的付款金额 + decimal wph_pay = (decimal)orderWeipinhuisTemp.Sum(f => f.pay);//唯品会有效的付款金额 + decimal sn_pay = (decimal)orderSuningsTemp.Sum(f => f.pay);//苏宁有效的付款金额 + decimal dy_pay = (decimal)orderDouyinsTemp.Sum(f => (f.pay / 100));//抖音有效的付款金额 + + #endregion + + #region 毛利合计 第一个阿里妈妈。第二个京东。第三个拼多多。第四个唯品会 + var tb_point = orderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//淘宝分出佣金 + var jd_point = orderJingdongs.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//京东分出佣金 + var pdd_point = orderPinduoduos.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//拼多多分出佣金 + var wph_point = orderWeipinhuis.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//唯品会分出佣金 + var sn_point = orderSunings.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//苏宁分出佣金 + var dy_point = orderDouyins.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//抖音分出佣金 + + List temps = new List(); + temps.AddRange(tb_point); + temps.AddRange(jd_point); + temps.AddRange(pdd_point); + temps.AddRange(wph_point); + temps.AddRange(sn_point); + temps.AddRange(dy_point); + + decimal amount_ceded = 0m;//给客户的部分(约等于) + for (int i = 0; i < temps.Count; i++) + { + var point = HttpHelper.JsonToObject(temps[i]) as ItemPoint; + if (point != null) + { + amount_ceded += ((decimal)point.UserPoint + (decimal)point.AwardOne + (decimal)point.AwardTwo + (decimal)point.AwardThree + (decimal)point.AwardCreate); + } + } + decimal total_margin = total_income - amount_ceded;//毛利(约等于) + #endregion + + #region 订单数量合计 第一个阿里妈妈。第二个京东。第三个拼多多。第四个唯品会 + int tb_order_count = orderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//淘宝总订单数 + int jd_order_count = (int)orderJingdongs.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//京东总订单数 + int pdd_order_count = orderPinduoduos.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//拼多多总订单数 + int wph_order_count = orderWeipinhuis.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//唯品会总订单数 + int sn_order_count = orderSunings.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//苏宁总订单数 + int dy_order_count = orderDouyins.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//抖音总订单数 + #endregion + + var gross_margin = (total_income == 0 ? "0%" : Math.Round(total_margin / total_income * 100m, 4).ToString() + "%");//毛利率 + + #region 统计今天新人人数 + //var new_member = newMembers.Count(f => f.robot_name == item.name); + var new_member = 0; + try + { + var applyfriendInfos = session.Ado.GetDataTable("select * from fl_plugin_userfission_applyfriend_info where state = '已接受' and @begin_time <= crt_time and crt_time < @end_time and robot_name = @robot_name", new List(){ + new SugarParameter("@begin_time",begin_time), + new SugarParameter("@end_time",end_time), + new SugarParameter("@robot_name",item.name), +}); + new_member = applyfriendInfos.Rows.Count; + } + catch (Exception ex) + { + EventClient.OnEvent(null, "数据报表统计今天新人人数异常:" + ex.Message + " - " + ex.StackTrace); + } + #endregion + + //#region 统计今天新人绑定人数 + //var bindMembers = memberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order != 0).Count(); + //var verifyMembers = memberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order == 0).ToList(); + //var bindMembers2 = 0; + //for (int i = 0; i < verifyMembers.Count; i++) + //{ + // var temp = statisticsRecords.FirstOrDefault(f => f.uid == verifyMembers[i].id); + // if (null != temp) + // { + // if (temp.querynum != 0) + // bindMembers2++; + // } + //} + //var activeMembers = bindMembers2 + bindMembers; + ////新人转化率 + //var activeMemberCvr = activeMembers == 0 ? 0 : Decimal.Round((bindMembers / activeMembers), 2); + //#endregion + + + #region 统计首次新人绑定人数 + var bindMembers = memberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order != 0).Count(); + + var verifyMembers = memberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order == 0).ToList(); + var queryMembers2 = 0;//所有查询用户数量 + var queryMembers3 = 0;//当天查询用户数量 + for (int i = 0; i < verifyMembers.Count; i++) + { + var temp = firstQueryStatistics.FirstOrDefault(f => f.uid == verifyMembers[i].id); + if (null != temp) + { + if (temp.querynum != 0) + { + queryMembers2++; + if (memberInfos.FirstOrDefault(f => f.id == temp.uid) != null) + queryMembers3++; + } + } + } + + //以前进来的用户首查 + //var dd = firstQueryMembers.Where(f => f.robot_name == item.name && memberInfos.Where(d => d.id != f.id).Any()).ToList(); + //var queyrMembers3 = firstQueryMembers.Where(f => f.robot_name == item.name && memberInfos.Where(d => d.id != f.id).Any()).ToList().Count; + var queyrMembers3 = firstQueryMembers.Where(f => f.robot_name == item.name && memberInfos.FirstOrDefault(d => d.id == f.id) == null).ToList().Count; + var activeMembers = queryMembers2 + bindMembers + queyrMembers3; + + //以前进来的用户首次付款 + //var ss = firstPayMembers.Where(f => f.robot_name == item.name && memberInfos.Where(d => d.id != f.id).Any()).ToList(); + //var bindMembers4 = firstPayMembers.Where(f => f.robot_name == item.name && memberInfos.Where(d => d.id != f.id).Any()).ToList().Count; + var bindMembers4 = firstPayMembers.Where(f => f.robot_name == item.name && memberInfos.FirstOrDefault(d => d.id == f.id) == null).ToList().Count; + var bindMemberNum = bindMembers + bindMembers4; + #endregion + + + + string activeMemberCvr = string.Format(formatStr, 0, 0); + string newQueryMemberCvr = string.Format(formatStr, 0, 0); + string realQueryMembers = string.Format(formatStr, 0, 0); + string realPayMembers = string.Format(formatStr, 0, 0); + if (new_member != 0) + { + //首次付款转化率 + decimal activeMemberCvr_Temp = (decimal)bindMemberNum / (decimal)new_member; + var _activeMemberCvr = (double)decimal.Round(activeMemberCvr_Temp, 4) * 100d; + activeMemberCvr = string.Format(formatStr, bindMemberNum, _activeMemberCvr);//$"{bindMemberNum}人({_activeMemberCvr}%)"; + + //首次查询转换率 + decimal newQueryMemberCvr_Temp = (decimal)activeMembers / (decimal)new_member; + var _newQueryMemberCvr = (double)decimal.Round(newQueryMemberCvr_Temp, 4) * 100d;// 查询的人数 / 新进人数 + newQueryMemberCvr = string.Format(formatStr, activeMembers, _newQueryMemberCvr);//$"{activeMembers}人({_newQueryMemberCvr}%)"; + + //今日下单转换率 + var realPayMembersCvr = (decimal)bindMembers / (decimal)new_member; + realPayMembers = string.Format(formatStr, bindMembers, ((double)decimal.Round(realPayMembersCvr, 4) * 100d));//$"{bindMembers}人({((double)decimal.Round(realPayMembersCvr, 4) * 100d)}%)"; + + //今日查询转换率 + var tempQueryNum = queryMembers3 + bindMembers; + var realQueryMembersCvr = (decimal)tempQueryNum / (decimal)new_member; + realQueryMembers = string.Format(formatStr, tempQueryNum, ((double)decimal.Round(realQueryMembersCvr, 4) * 100d)); //$"{tempQueryNum}人({((double)decimal.Round(realPayMembersCvr, 4) * 100d)}%)"; + } + + #region 提现金额 + var exchange_money = (decimal)(pointHists.Where(f => f.rid == item.id).Sum(f => f.point) * -1); + #endregion + + #region 当天新人查询人数xxx + //statisticsRecords + //已经下单的人,就不验证是否查询过 + //var queryCount1 = memberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order != 0).Count(); + + //var verifyMembers = memberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order == 0).ToList(); + //var queryCount2 = 0; + //for (int i = 0; i < verifyMembers.Count; i++) + //{ + // var temp = statisticsRecords.FirstOrDefault(f => f.uid == verifyMembers[i].id); + // if (null != temp) + // { + // if (temp.querynum != 0) + // queryCount2++; + // } + //} + #endregion + + #region 当天新人首单数量xxx + //var pay_order_count = memberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order != 0).Count(); + #endregion + + lock (lock_result) resultList.Add(new { pdd_pay = pdd_pay, wph_pay = wph_pay, sn_pay = sn_pay, dy_pay = dy_pay, tb_pay = tb_pay, jd_pay = jd_pay, chat_type = item.type, robot_name = item.name, robot_nick = item.nick, all_total_income = Decimal.Round(all_total_income, 2), total_income = Decimal.Round(total_income, 2), tb_income = Decimal.Round(tb_income, 2), jd_income = Decimal.Round(jd_income, 2), pdd_income = Decimal.Round(pdd_income, 2), wph_income = Decimal.Round(wph_income, 2), sn_income = Decimal.Round(sn_income, 2), dy_income = Decimal.Round(dy_income, 2), total_margin = Decimal.Round(total_margin, 2), tb_order_count = tb_order_count, jd_order_count = jd_order_count, pdd_order_count = pdd_order_count, wph_order_count = wph_order_count, sn_order_count = sn_order_count, dy_order_count = dy_order_count, gross_margin = gross_margin, exchange_money = exchange_money, new_member = new_member, newQueryMemberCvr = newQueryMemberCvr, activeMemberCvr = activeMemberCvr,/*pay_order_count = bindMemberNum, query_count = activeMembers,*/ realPayMembers = realPayMembers, realQueryMembers = realQueryMembers }); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"{item.name} - {ex.Message} - {ex.StackTrace}"); + } + })); + } + + Parallel.ForEach(actions, action => + { + action.Invoke(); + }); + + this.Invoke(new Action(() => + { + Convert.ToString(gridView.Columns["all_total_income"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["total_income"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["total_margin"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["tb_order_count"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["jd_order_count"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["pdd_order_count"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["pdd_income"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["wph_order_count"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["wph_income"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["sn_order_count"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["sn_income"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["dy_order_count"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["dy_income"].SummaryItem.SummaryValue); + + Convert.ToString(gridView.Columns["jd_income"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["tb_income"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["exchange_money"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["new_member"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["tb_pay"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["jd_pay"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["pdd_pay"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["wph_pay"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["sn_pay"].SummaryItem.SummaryValue); + Convert.ToString(gridView.Columns["dy_pay"].SummaryItem.SummaryValue); + + try + { + gridControl.DataSource = resultList; + } + catch (Exception ex) + { + EventClient.OnEvent("....", ex.Message + "-" + ex.StackTrace); + } + })); + } + catch (Exception ex) + { + EventClient.OnEvent("...", ex.Message + "-" + ex.StackTrace); + } + finally + { + pointHists = null; + allOrderAlimamas = null; + orderAlimamas = null; + allOrderJingdongs = null; + orderJingdongs = null; + allOrderPinduoduos = null; + orderPinduoduos = null; + allOrderWeipinhuis = null; + orderWeipinhuis = null; + allOrderSunings = null; + orderSunings = null; + allOrderDouyins = null; + orderDouyins = null; + newMembers = null; + } + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private async void simpleButton1_Click(object sender, EventArgs e) + { + try + { + //SumResult = new Dictionary() { { "realPayMember", 0 }, { "realQueryMember", 0 }, { "newQueryMember", 0 }, { "newPayMember", 0 } }; + dateTimePicker1.Enabled = dateTimePicker2.Enabled = comboBoxEdit3.Enabled = simpleButton1.Enabled = false; + labelControl3.Visible = true; + labelControl4.Visible = false; + gridControl1.DataSource = null; + try + { + await Task.Run(() => + { + RefreshDataReport(gridControl1, gridView1, dateTimePicker1.Value, dateTimePicker2.Value); + }, tokenSource.Token); + } + catch (Exception) + { } + dateTimePicker1.Enabled = dateTimePicker2.Enabled = comboBoxEdit3.Enabled = simpleButton1.Enabled = true; + labelControl3.Visible = false; + labelControl4.Visible = gridView1.RowCount == 0; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + private void comboBoxEdit3_SelectedIndexChanged(object sender, EventArgs e) + { + var com = comboBoxEdit3.Text; + var begin_time = DateTime.Now.Date; + var end_time = DateTime.Now.Date; + if (com == "昨日报表") + { + begin_time = begin_time.AddDays(-1); + end_time = end_time.AddDays(-1); + } + else if (com == "7日报表") + { + begin_time = begin_time.AddDays(-7); + end_time = end_time.AddDays(-1); + } + else if (com == "30日报表") + { + begin_time = begin_time.AddDays(-30); + end_time = end_time.AddDays(-1); + } + else if (com == "本月报表") + { + begin_time = begin_time.AddDays(-(begin_time.Day - 1)); + end_time = begin_time.AddMonths(1).AddDays(-1); + } + else if (com == "上月报表") + { + begin_time = begin_time.AddDays(-begin_time.Day).AddMonths(-1).AddDays(1); + end_time = begin_time.AddMonths(1).AddDays(-1); + } + else if (com == "本年报表") + { + begin_time = DateTime.Parse($"{begin_time.Year}-01-01 00:00:00"); + end_time = begin_time.AddYears(1).AddDays(-1); + } + else if (com == "上年报表") + { + begin_time = DateTime.Parse($"{begin_time.Year - 1}-01-01 00:00:00"); + end_time = begin_time.AddYears(1).AddDays(-1); + } + dateTimePicker1.Value = begin_time; + dateTimePicker2.Value = end_time; + simpleButton1_Click(null, null); + } + + private void data_report_control_Load(object sender, EventArgs e) + { + this.Disposed += Control_Disposed; + } + + private void Control_Disposed(object sender, EventArgs e) + { + tokenSource.Cancel(); + } + + private class OrderTemp + { + /// + /// 付款金额 + /// + public double pay { get; set; } + + /// + /// 结算付款金额 + /// + public double pay_real { get; set; } + + /// + /// 订单状态 + /// + public SystemOrderStatus db_status { get; set; } + + /// + /// 机器人名称 + /// + public string db_robotname { get; set; } + + /// + /// 机器人类型 + /// + public ChatType db_robottype { get; set; } + + /// + /// 总佣金 + /// + public double fee { get; set; } + + /// + /// 真实的总佣金 + /// + public double fee_real { get; set; } + + /// + /// 积分json + /// + public string db_point { get; set; } + + /// + /// 购买数量 + /// + public int num { get; set; } + } + + private void 导出为EceToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (this.gridControl1 == null) throw new Exception("没有需要导出的数据!"); + if (XtraMessageBox.Show("确定要将本页面数据导入到Excel内?", "请选择", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) + { + //var table = this.gridControl1.DataSource as DataTable; + //if (table == null || table.Rows.Count == 0) throw new Exception("没有需要导出的数据!"); + + this.saveFileDialog1.Filter = "Excel文件(*.xls)|*.xls"; + if (this.saveFileDialog1.ShowDialog(this) == DialogResult.OK) + { + DevExpress.XtraPrinting.XlsExportOptions options = new DevExpress.XtraPrinting.XlsExportOptions(); + this.gridControl1.ExportToXls(this.saveFileDialog1.FileName); + XtraMessageBox.Show("恭喜您,已完成数据导出!", "导出完成", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + } + catch (Exception vErr) + { + XtraMessageBox.Show(vErr.Message, "导出错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + #region 记录每一列的人数 + Dictionary SumResult = new Dictionary() { { "newPayMember", 0 }, { "newQueryMember", 0 }, { "realPayMember", 0 }, { "realQueryMember", 0 } }; + #endregion + + /// + /// 要获取的列名 + /// + Dictionary SumFields = new Dictionary { { "activeMemberCvr", "newPayMember" }, { "newQueryMemberCvr", "newQueryMember" }, { "realPayMembers", "realPayMember" }, { "realQueryMembers", "realQueryMember" } }; + + /// + /// 自定义公式【使用说明:Start:用作初始化数据,Calculate:用作数据的计算,Finalize:用作统计列数据的显示】 + /// + /// + /// + private void gridView1_CustomSummaryCalculate(object sender, DevExpress.Data.CustomSummaryEventArgs e) + { + string fieldName = (e.Item as GridSummaryItem).FieldName; + + if (!SumFields.ContainsKey(fieldName)) return; + var variate = SumFields[fieldName]; + + switch (e.SummaryProcess) + { + case CustomSummaryProcess.Start: + SumResult = new Dictionary() { { "realPayMember", 0 }, { "realQueryMember", 0 }, { "newQueryMember", 0 }, { "newPayMember", 0 } }; + break; + case CustomSummaryProcess.Calculate: + { + var column = gridView1.Columns[fieldName]; + var value = column.View.GetRowCellValue(e.RowHandle, column).ToString(); + if (!string.IsNullOrWhiteSpace(value)) + { + var reg = Regex.Match(value, @"^(?<数量>\d+)"); + if (reg.Success) + { + var number = decimal.Parse(reg.Groups["数量"].Value); + SumResult[variate] += number; + } + } + } + break; + case CustomSummaryProcess.Finalize: + { + var value = SumResult[variate]; + var new_member = Convert.ToDecimal(gridView1.Columns["new_member"].SummaryItem.SummaryValue); + var cvr = new_member == 0 ? 0 : (decimal.Round(value / new_member, 4) * 100m); + var temp = new_member == 0 ? 0 : decimal.Round(cvr, 2); + e.TotalValue = string.Format(formatStr, value, temp);//$"{value}人({temp}%)"; + } + break; + default: + break; + } + } + + } +} diff --git a/FLSystem/Forms/data_report_control.resx b/FLSystem/Forms/data_report_control.resx new file mode 100644 index 0000000..7ec9427 --- /dev/null +++ b/FLSystem/Forms/data_report_control.resx @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAAJmUlEQVRYR51XB1RUZxZ+lsTNrq51w5ZEjSYmujmWJMcSNEERBFFQUWNfexRF + F0FUIg6IggPSiwyKo6gURVQEUXpHQbGNNOltYGaAoTf12/s/GY4oErPfOd95vP/dud/333v/NwP3B9Dv + d/j/A0CvJKiS9ycOIA4kfkT8uOvKyNbYcz62tzwe5xLoUR/o7UMElnCAueDUMA9xzEof/5TA0wFpmT7+ + aXLRpbSmU37JDz3PJ4SePBWxaY+54z8olpliJt8x4eIbS8t9QBWou8Wf3fI71tRZOcjLL9H47OX06sT0 + ApRU1KK1rYPCXqOltYNfi0t7DtHF5AYHr1sCXYONI+izrCp8RSiMz+soiqbbPqAKJPDih476qnlfTE5M + uJuP5pbXop2dr9BCBhqa26FsbEN9Uzs966T1l7yx6OQcnBRFPtuxz34i5WDV6DYh9LxNf/YBFsRI6G9p + e/5TkX9qXnZBNdNFR8cLPMuXw0Wciu2HQ6Gz+SL0tgdg7/FIiIIeIbe4FnUNbWhvp7jcSjiJomQ7TR2n + UC7eBMtr6xbOcr8fXeL9NLQMB7mLE+Ky8qp48Za2TpwNfgDN9WLom0Vj7fFMbHPLx3biZvsn+M/RVKwz + D0dIVB5qG1r56khyK3DU6UbWIsMd/6ScbED7WTveYPn7BD9wTqJI49jkPF68nnZlJLiB+VsDcS2uAoUl + LcguaEZ4Wi3MxSUwFhVjj08JdnnkYbMgDnY+9yCrbeFbczPqEQ4e83ehnJ+wvJbCEKbRJ/pt32M33EMc + X93Y1Ia29k5Yu8dgodFVVFe3QSFvR0VlKwrIxNPnTUh53ADBpXKY+ZZg/9lSHBCXYrcwFb5XJZApm1Gj + bIGN840Ow7Wm31BuNpRsg+8FP3h2bmGbohKz8OoVkJklxZzVYkRnKLrE23hxCYnfz2pE0uN6XIqRw8Kv + DIcvlPMUXq7ANstoZBfWQKpowrVb92FscVpIuVkV+scLNLjeyMCXnwYlML9YRhPdiRM+SdA3j0Y57bpb + PJ/Es1+LRz9Q4ia1QuBP/Q6ohE1gJYTBUhw58xTnQrNQVdOMJ9nl2HNYfJ9yD2b5yy9rcir2ZmDgMZew + bHa22USvMrmC1Q4PUVDagnxWdiaeQ+JPSDyzDrfS63A1pQbHgythG0LiRIfrUniGleGgWypkdS0orVRS + BcRNI0b9i70bBv6egY+Ou4bVs+GrJvfzt53HJu/nuJVRy4tn5DQgSULiD+sQnlGHa3drII6TQXhDCoeb + UpwMk8LplhR+CTLstI2Dor4VJdIG7LEQ44cf9UczA0ynLwMfWzlcq2f9r5A3QnvnRWwS5eDg5RIkPVMi + UaJEFImHPahFSHotAtIUcLxThZO3q+ASWQXXqCp4xspwida3C2MgV1Lbyuux0/wMflA3GEf5+UHsswIH + bIKK2QkorW7EBjp+GzyfYMeFApgHl+BcsgxXM2oQQDs/k1QN+zu082gSj6uGW3w1PBNlOHdPAd/EChzw + TkEVHUdJvgwbd7t1DB2uNpLyD7R2ucNF+J7gDbgIvd41YHLELzyLXiJlska4Xr6PFfaJ2BFQAOPgIphe + K8Khm6UQRJTDJrICwjgpnMmIOxnzSpVDdE+OEKqS3bVnOBeZg3J5M2JS87B6m8Mzyv1XIm9AZcLKMYxz + czjVw8DAneaivZdD7/IT/KhAAQOLEPwamAfjkEKYhhbBIoIMRJXjeFw5HJIq4ZJWDY97Mng/kCMoi1qT + VYNtLnHIodIXSevheS4SBmsEHpT7L8QBKgOMzICLfU8DA7T1f1UzsTzfLJU3oKSqER7XM7HOOQYmN4tg + FkEViCQDsWU4nlQB+7RKuGZUw/uxHIG5tQgtVOLgpXSIY7JRVdeKzOwqrDdyeTH9p7U/Uu4/Efu/acD+ + mFuPFjDwbdi421VwITiBBkiJKhqkI+eTscE1mnafD0FcGQTxZCClHM73pTj9VI4r+XW4KJHCxC8NtsEZ + qGnuQF6Zkr6QwqGz/FAM5fwbcRDLb+V0+3ULzth3i79tYMC0GXojNuxyexabkoWcUvqWa3mB4JTnWC0M + w77AB7BPKICvRA6/bAU875XCOuwJNrtH43p6ERrbXyK/oh5BYfexbL01tJcdqJ04VW8W5WUvIv4YhvvY + 8UOYckKPS7Yj2urRMoGOP7vwVdBcZDSRprfmTqIE2cV1kDW0o5AG80yUBKa+8Vhx4iZWkqH94mSIY7NR + JG+CsrkTuaVKXLn1gPp+FL5+oUhIlWDVVkf59+qrephgBhKP6XIJNrpcvI0OLRGYgS4T7EfExxp6RlOW + bbTNdfYJR7qkki+rnIywXba+AM/GjpeoaexAobSRjznmEoIFy3+D1hIz+PjFoPPFS9zNLMDKLc7NWvP0 + e5iItVrAxVhpczECbbolvGGAVYE3MWmaltrCXw57/bJV2Cr0CMXV2w/xMFeOR/kKPHrOKEcwrTFh/TXW + mL3AOGK27r7avZYBWL7FGeKAJLBTlZseiiiLnxV7tcerU94hRP6ldMdCk7tzSJP+JKgM1Lf3MMHcfjJ5 + +pIJcxeb2sxfcjB5geFvrVpLLTDP4BA0iRp6ZunqWrtOTvpu8QyKHTX+W111LcOjchOrYOissEFaZADQ + LoPy7glE7FdXGGmMnU1x3SbCzH6mC0Fl4E0S+MEksmB2lNh5Zi+VocRhXWT3bJ09Z9M+eMLkxbPmGlg1 + +7vZodhbEy0Sd95EbZodbvx3pmKr+udzKI6Z4NtB5DjdFUc4neWWnNayw5w2UXOJBUe7pOsh9lhVEdX/ + BW+T/yneRXY/+Psps2cFbZ+sKL6yFkVeGmh56vbaxF1bBO+crtg254uZFPdnIsv7YVB9kbyPZUFzWVi3 + iQ3fqamfXz9RURS0DgUeP3WbKAg1x9kN0xIpZnhX7IehN9G3WRbQw8SQFf8eOdt7+ZeKwsA11A4tvh2v + 2mQQr52ipOejiKy9H4beBMuvvLvWBWaCJR+iP37oHCe9MYoMj2WoCNmCvHB7uC+d9McrcHr519xpwwmc + z9IJnIhxyVect8FX3Cn9LzmvxeM5way/c0dmqnGWM9S4w9PV2Ee6TeiMGTLTZOqoeCet0R22Gp/FGH77 + 6TRa538rEj8MXovGc54k5LFoHOexcBznrvsF50Z01RnLuS4Yy+2fOoozmzqSM51CnDyS20ckqNrBBo7t + mJWdXfmf60T2/MPgqj2Wc9Yaw9Np/mjOSXM05zjvc+7kXKLGZ5zxxGHcbsZvhnG7GL8eyhlNYKeUF1G9 + V1hF2JXd93OcN5b7H1cpDdS8q/oNAAAAAElFTkSuQmCC + + + + 17, 17 + + + 194, 17 + + + 50 + + \ No newline at end of file diff --git a/FLSystem/Forms/edit_uservariate_form.Designer.cs b/FLSystem/Forms/edit_uservariate_form.Designer.cs new file mode 100644 index 0000000..5f5b5a7 --- /dev/null +++ b/FLSystem/Forms/edit_uservariate_form.Designer.cs @@ -0,0 +1,154 @@ +namespace FLSystem.Forms +{ + partial class edit_uservariate_form + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.button2); + this.groupBox1.Controls.Add(this.button1); + this.groupBox1.Controls.Add(this.memoEdit1); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(29, 25); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(543, 289); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // button2 + // + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Location = new System.Drawing.Point(342, 234); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(96, 34); + this.button2.TabIndex = 3; + this.button2.Text = "取 消"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Location = new System.Drawing.Point(169, 234); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(96, 34); + this.button1.TabIndex = 3; + this.button1.Text = "确 定"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(124, 85); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(355, 135); + this.memoEdit1.TabIndex = 2; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(124, 44); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(132, 22); + this.textBox1.TabIndex = 1; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(56, 86); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 0; + this.label2.Text = "替换内容:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.ForeColor = System.Drawing.Color.Gray; + this.label3.Location = new System.Drawing.Point(262, 48); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(237, 14); + this.label3.TabIndex = 0; + this.label3.Text = "(变量名不能与系统内置的一致,一致将无效)"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(68, 48); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 0; + this.label1.Text = "变量名:"; + // + // edit_uservariate_form + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.ClientSize = new System.Drawing.Size(599, 345); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "edit_uservariate_form"; + this.Text = "edit_uservariate_form"; + this.Load += new System.EventHandler(this.edit_uservariate_form_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Label label3; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/edit_uservariate_form.cs b/FLSystem/Forms/edit_uservariate_form.cs new file mode 100644 index 0000000..e21bafd --- /dev/null +++ b/FLSystem/Forms/edit_uservariate_form.cs @@ -0,0 +1,61 @@ +using Api.Framework; +using Api.Framework.Model; +using System; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class edit_uservariate_form : BaseForm + { + private fl_uservariate_info uservariate_Info; + public edit_uservariate_form(fl_uservariate_info uservariate_Info = null) + { + InitializeComponent(); + this.uservariate_Info = uservariate_Info; + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("请填写变量名"); + if (string.IsNullOrEmpty(memoEdit1.Text)) throw new Exception("请填写替换内容"); + if (uservariate_Info == null) + uservariate_Info = new fl_uservariate_info(); + uservariate_Info.variate = textBox1.Text.Trim(); + uservariate_Info.data = memoEdit1.Text; + string mess = uservariate_Info.id == 0 ? "增加成功" : "修改成功"; + var session = ApiClient.GetSession(); + session.Saveable(uservariate_Info).ExecuteCommand(); + session.FindUserVariates(true); + ShowSuccess(mess); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button2_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void edit_uservariate_form_Load(object sender, EventArgs e) + { + try + { + if (uservariate_Info != null) + { + textBox1.Text = uservariate_Info.variate; + memoEdit1.Text = uservariate_Info.data; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} diff --git a/FLSystem/Forms/edit_uservariate_form.resx b/FLSystem/Forms/edit_uservariate_form.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/edit_uservariate_form.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/group_info_form.Designer.cs b/FLSystem/Forms/group_info_form.Designer.cs new file mode 100644 index 0000000..f0bf391 --- /dev/null +++ b/FLSystem/Forms/group_info_form.Designer.cs @@ -0,0 +1,140 @@ +namespace FLSystem.Forms +{ + partial class group_info_form + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.simpleButton3); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.textEdit2); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Location = new System.Drawing.Point(37, 33); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(444, 230); + this.groupBox1.TabIndex = 2; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "群消息"; + // + // simpleButton3 + // + this.simpleButton3.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton3.Location = new System.Drawing.Point(114, 147); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(85, 35); + this.simpleButton3.TabIndex = 14; + this.simpleButton3.Text = " 确 定 "; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton1_Click); + // + // simpleButton2 + // + this.simpleButton2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton2.Location = new System.Drawing.Point(260, 147); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(85, 35); + this.simpleButton2.TabIndex = 14; + this.simpleButton2.Text = " 取 消 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(114, 57); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(250, 20); + this.textEdit1.TabIndex = 11; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(64, 60); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(48, 14); + this.labelControl1.TabIndex = 9; + this.labelControl1.Text = "群昵称:"; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(114, 93); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(250, 20); + this.textEdit2.TabIndex = 11; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(64, 96); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(48, 14); + this.labelControl2.TabIndex = 9; + this.labelControl2.Text = "群账号:"; + // + // group_info_form + // + this.AcceptButton = this.simpleButton3; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.simpleButton2; + this.ClientSize = new System.Drawing.Size(517, 296); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "group_info_form"; + this.Text = "编辑群信息"; + this.Load += new System.EventHandler(this.group_info_form_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/group_info_form.cs b/FLSystem/Forms/group_info_form.cs new file mode 100644 index 0000000..6ff5fd4 --- /dev/null +++ b/FLSystem/Forms/group_info_form.cs @@ -0,0 +1,108 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using FLSystem.Events; +using FLSystem.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class group_info_form : BaseForm + { + string gid = string.Empty; + string gname = string.Empty; + public group_info_form(string gid = "", string gname = "") + { + InitializeComponent(); + this.gid = gid; + this.gname = gname; + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("请填写群昵称"); + if (string.IsNullOrWhiteSpace(textEdit2.Text)) throw new Exception("请填写群账号"); + if (textEdit2.Text.Length > 30) throw new Exception("填写的群账号不合法"); + + var session = ApiClient.GetSession(); + + if (!string.IsNullOrWhiteSpace(gid)) + { + var adzone = session.FindSingle("select * from fl_adzone_info where group_id = @group_id and custom_type = @custom_type", new { group_id = gid, custom_type = Resources.GroupSoftwareType }); + var pidInfos = session.Queryable().Where(f => f.group_id == gid && f.custom_type == Resources.GroupSoftwareType).ToList(); + if (pidInfos != null) + { + foreach (var item in pidInfos) + { + item.group_id = textEdit2.Text.Trim(); + item.extend = textEdit1.Text.Trim(); + session.Updateable(item).ExecuteCommand(); + } + } + ShowSuccess("修改成功"); + } + else + { + var adzone = session.FindSingle("select * from fl_adzone_info where group_id = @group_id and custom_type = @custom_type", new { group_id = textEdit2.Text.Trim(), custom_type = Resources.GroupSoftwareType }); + if (adzone != null) throw new Exception("群号已存在,操作无效"); + //var strs = new string[] { "淘宝推广位名称", "拼多多推广位名称", "京东推广位名称" }; + //var pidSortRemark = Enum.GetNames(typeof(GroupAdzoneType));//pid类别备注,值顺序不能变 + + var pidInfos = session.Queryable().Where(f => f.group_id == textEdit2.Text.Trim() && f.custom_type == Resources.GroupSoftwareType).ToList(); + if (pidInfos != null && pidInfos.Count == 0) + { + for (int i = 1; i <= 3; i++) + { + var _adzone = new fl_adzone_info + { + custom_type = Resources.GroupSoftwareType, + extend = textEdit1.Text.Trim(), + alliance_id = i, + is_download = false, + member_id = 0, + onoff = false, + robot_id = 0, + group_id = textEdit2.Text.Trim(), + adzone_pid_cps_name = string.Empty, + adzone_pid = string.Empty, + adzone_name = string.Empty, + }; + session.Saveable(_adzone).ExecuteReturnEntity(); + } + } + ShowSuccess("增加成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void group_info_form_Load(object sender, EventArgs e) + { + if (!string.IsNullOrWhiteSpace(gid)) + { + textEdit2.Text = gid; + textEdit1.Text = gname; + } + } + } +} diff --git a/FLSystem/Forms/group_info_form.resx b/FLSystem/Forms/group_info_form.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/group_info_form.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/group_manage_control.Designer.cs b/FLSystem/Forms/group_manage_control.Designer.cs new file mode 100644 index 0000000..79d97a6 --- /dev/null +++ b/FLSystem/Forms/group_manage_control.Designer.cs @@ -0,0 +1,298 @@ +namespace FLSystem.Forms +{ + partial class group_manage_control + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(group_manage_control)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton2); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(952, 76); + this.groupControl1.TabIndex = 4; + this.groupControl1.Text = "搜索条件"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(210, 36); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(36, 14); + this.labelControl1.TabIndex = 15; + this.labelControl1.Text = "内容:"; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(801, 30); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(79, 27); + this.simpleButton2.TabIndex = 14; + this.simpleButton2.Text = "增加"; + this.simpleButton2.Click += new System.EventHandler(this.增加ToolStripMenuItem_Click); + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(577, 30); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(79, 27); + this.simpleButton1.TabIndex = 14; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit3 + // + this.comboBoxEdit3.EditValue = "全部平台"; + this.comboBoxEdit3.Location = new System.Drawing.Point(450, 33); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { + "全部平台"}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(108, 20); + this.comboBoxEdit3.TabIndex = 11; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(252, 33); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(192, 20); + this.textEdit1.TabIndex = 10; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(0, 82); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(952, 539); + this.gridControl1.TabIndex = 3; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加ToolStripMenuItem, + this.修改ToolStripMenuItem, + this.删除ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(101, 70); + // + // 增加ToolStripMenuItem + // + this.增加ToolStripMenuItem.Name = "增加ToolStripMenuItem"; + this.增加ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.增加ToolStripMenuItem.Text = "增加"; + this.增加ToolStripMenuItem.Click += new System.EventHandler(this.增加ToolStripMenuItem_Click); + // + // 修改ToolStripMenuItem + // + this.修改ToolStripMenuItem.Name = "修改ToolStripMenuItem"; + this.修改ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.修改ToolStripMenuItem.Text = "修改"; + this.修改ToolStripMenuItem.Click += new System.EventHandler(this.修改ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn3, + this.gridColumn1, + this.gridColumn6, + this.gridColumn11, + this.gridColumn2}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "编号"; + this.gridColumn3.FieldName = "id"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 0; + // + // gridColumn1 + // + this.gridColumn1.Caption = "群号"; + this.gridColumn1.FieldName = "groupid"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 186; + // + // gridColumn6 + // + this.gridColumn6.Caption = "群名"; + this.gridColumn6.FieldName = "groupname"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 2; + this.gridColumn6.Width = 209; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn11.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn11.AppearanceCell.Options.UseFont = true; + this.gridColumn11.AppearanceCell.Options.UseForeColor = true; + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn11.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "绑定用户账号"; + this.gridColumn11.FieldName = "username"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 3; + this.gridColumn11.Width = 219; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "绑定用户昵称"; + this.gridColumn2.FieldName = "usernick"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 4; + this.gridColumn2.Width = 201; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 627); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(952, 33); + this.pageControl1.TabIndex = 5; + // + // group_manage_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.gridControl1); + this.Name = "group_manage_control"; + this.Size = new System.Drawing.Size(952, 660); + this.Load += new System.EventHandler(this.group_manage_control_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 增加ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + } +} diff --git a/FLSystem/Forms/group_manage_control.cs b/FLSystem/Forms/group_manage_control.cs new file mode 100644 index 0000000..79fefa1 --- /dev/null +++ b/FLSystem/Forms/group_manage_control.cs @@ -0,0 +1,195 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace FLSystem.Forms +{ + + public partial class group_manage_control : DevExpress.XtraEditors.XtraUserControl + { + private class fl_group_person_temp + { + public long id { get; set; } + /// + /// 用户ID + /// + public long mid { get; set; } + + /// + /// 用户账号 + /// + public string username { get; set; } + + /// + /// 用户昵称 + /// + public string usernick { get; set; } + + /// + /// 群号 + /// + public string groupid { get; set; } + + /// + /// 群名 + /// + public string groupname { get; set; } + } + + public group_manage_control() + { + InitializeComponent(); + + #region 增加所有的机器人账号 + this.comboBoxEdit3.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit3.Properties.Items.AddRange(objList); + #endregion + + } + + private void group_manage_control_Load(object sender, EventArgs e) + { + this.pageControl1.Bind(delegate (int page, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var map = session.NewParamMap(); + map.setPageParamters(page, pagesize); + string where = string.Empty; + if (!string.IsNullOrEmpty(this.textEdit1.Text)) + where = " where (g.groupid like '%" + textEdit1.Text.Trim() + "%' or g.groupname like '%" + textEdit1.Text.Trim() + "%' or m.username like '%" + textEdit1.Text.Trim() + "%' or m.usernick like '%" + textEdit1.Text.Trim() + "%') "; + + if (comboBoxEdit3.SelectedIndex != 0) + where += string.IsNullOrWhiteSpace(where) ? " where m.robot_name = '" + comboBoxEdit3.Text + "'" : " and m.robot_name = '" + comboBoxEdit3.Text + "'"; + + var rest = session.FindPage($"select g.id,m.id as mid,m.username,m.usernick,g.groupid,g.groupname from fl_group_person g inner join fl_member_info m on g.mid = m.id {where} ", map); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = rest.DataList, Total = rest.Total }; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = null, Total = 0 }; + }, this.gridControl1, 50, true, true); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + pageControl1.Go(sender, e); + } + + EditGroup editForm = null; + private void 增加ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + editForm = new EditGroup(); + editForm.ShowDialog(); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK); + } + finally + { + pageControl1.GotoPage(1); + } + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "id").ToString();//获取列的数据 + var session = ApiClient.GetSession(); + session.Deleteable().Where(f => f.id == int.Parse(id)).ExecuteCommand(); + XtraMessageBox.Show("删除成功", "提示", MessageBoxButtons.OK); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK); + } + finally + { + pageControl1.GotoPage(1); + } + } + + private void 修改ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "id").ToString();//获取列的数据 + var session = ApiClient.GetSession(); + var group = session.Queryable().First(f => f.id == int.Parse(id)); + editForm = new EditGroup(group); + editForm.ShowDialog(); + + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK); + } + finally + { + pageControl1.GotoPage(1); + } + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "id").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "username") + { + var memberForm = new MemberForm(); + if (memberForm.ShowDialog() == DialogResult.OK) + { + if (memberForm.member != null) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("update fl_group_person set mid = @mid where id = @id", new { mid = memberForm.member.id, id = id }); + XtraMessageBox.Show("修改成功", "提示", MessageBoxButtons.OK); + } + } + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK); + } + finally + { + pageControl1.GotoPage(1); + } + } + } +} diff --git a/FLSystem/Forms/group_manage_control.resx b/FLSystem/Forms/group_manage_control.resx new file mode 100644 index 0000000..8a09e09 --- /dev/null +++ b/FLSystem/Forms/group_manage_control.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + + 17, 17 + + \ No newline at end of file diff --git a/FLSystem/Forms/home_control.Designer.cs b/FLSystem/Forms/home_control.Designer.cs new file mode 100644 index 0000000..0d6400d --- /dev/null +++ b/FLSystem/Forms/home_control.Designer.cs @@ -0,0 +1,69 @@ +namespace FLSystem.Forms +{ + partial class home_control + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.webBrowser1 = new System.Windows.Forms.WebBrowser(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.SuspendLayout(); + // + // webBrowser1 + // + this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webBrowser1.Location = new System.Drawing.Point(0, 0); + this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20); + this.webBrowser1.Name = "webBrowser1"; + this.webBrowser1.Size = new System.Drawing.Size(760, 468); + this.webBrowser1.TabIndex = 0; + this.webBrowser1.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser1_DocumentCompleted); + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 3600000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // home_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.webBrowser1); + this.Name = "home_control"; + this.Size = new System.Drawing.Size(760, 468); + this.Load += new System.EventHandler(this.home_control_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.WebBrowser webBrowser1; + private System.Windows.Forms.Timer timer1; + } +} diff --git a/FLSystem/Forms/home_control.cs b/FLSystem/Forms/home_control.cs new file mode 100644 index 0000000..97b1fee --- /dev/null +++ b/FLSystem/Forms/home_control.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraBars; +using DevExpress.XtraTab; +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using System.Threading; + +namespace FLSystem.Forms +{ + public partial class home_control : UserControl + { + //private const string url = "www.baidu.com"; + //private readonly static string url = "https://cps.api.52cmg.cn/view/note.html?rd="; + //private const string url = "https://mo.m.taobao.com/union/hr-team-invite?bizTypeName=raceHorse&timeStamp=1633923247662&id=64315895-70e8-463d-b57e-0dc87564434227247953"; + + //private void GetNoticeUrl() + //{ + //return url + new Random(Guid.NewGuid().GetHashCode()).Next(10000, 50000); + //} + + + public home_control() + { + InitializeComponent(); + + webBrowser1.Dock = DockStyle.Fill; + webBrowser1.ScriptErrorsSuppressed = true; //禁用错误脚本提示 + webBrowser1.IsWebBrowserContextMenuEnabled = false; //禁用右键菜单 + webBrowser1.WebBrowserShortcutsEnabled = true; //禁用快捷键 + webBrowser1.AllowWebBrowserDrop = false;//禁止拖拽 + + Task.Run(() => + { + this.Invoke(new Action(() => + { + var dtEnd = DateTime.Now.AddSeconds(3); + do + { + Thread.Sleep(200); + if (this.Parent != null) + break; + } while (DateTime.Now < dtEnd); + + GetNotice(); + })); + }); + + } + + private void home_control_Load(object sender, EventArgs e) + { + + } + + private void GetNotice() + { + var flag = true; + try + { + + //return url + new Random(Guid.NewGuid().GetHashCode()).Next(10000, 50000); + var ali = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈); + if (ali == null) + ali = new fl_cps_member() { cpstype = CpsType.阿里妈妈, username = "28592081" }; + var cps = CpsClient.CreateAlimamaRequest(ali); + var data = cps.SendServer("find_notice", "webTool.asmx").message.ToString(); + + webBrowser1.Navigate("about:blank"); + while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) + { + Application.DoEvents(); + } + webBrowser1.Document.Write(data); + webBrowser1.Refresh();//不刷新一下,Iframe显示不出来。 + } + catch (Exception) + { + flag = false; + } + + try + { + var tab = this.Parent as XtraTabPage; + if (tab != null) + { + if (!flag) + tab.PageVisible = false; + else + tab.PageVisible = true; + } + else + tab.PageVisible = false; + } + catch (Exception) + { } + } + + + + + + private void timer1_Tick(object sender, EventArgs e) + { + try + { + GetNotice(); + //webBrowser1.Navigate(GetNoticeUrl()); + } + catch (Exception ex) + { } + } + + private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) + { + //try + //{ + // var tab = this.Parent as XtraTabPage; + // if (tab != null) + // { + // string content = webBrowser1.DocumentText; + // if (content.Contains("404")) + // { + // //(ss.Parent as XtraTabControl).TabPages.Remove(ss); + // tab.PageVisible = false; + // } + // else + // { + // tab.PageVisible = true; + // } + // } + //} + //catch (Exception) + //{ } + } + + } +} diff --git a/FLSystem/Forms/home_control.resx b/FLSystem/Forms/home_control.resx new file mode 100644 index 0000000..1f666f2 --- /dev/null +++ b/FLSystem/Forms/home_control.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/item_query_hist_control.Designer.cs b/FLSystem/Forms/item_query_hist_control.Designer.cs new file mode 100644 index 0000000..7abb156 --- /dev/null +++ b/FLSystem/Forms/item_query_hist_control.Designer.cs @@ -0,0 +1,322 @@ +namespace FLSystem.Forms +{ + partial class item_query_hist_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(item_query_hist_control)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.label1 = new System.Windows.Forms.Label(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.dateTimePicker2); + this.groupControl1.Controls.Add(this.label1); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(867, 76); + this.groupControl1.TabIndex = 5; + this.groupControl1.Text = "搜索条件"; + // + // dateTimePicker2 + // + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(577, 32); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(169, 22); + this.dateTimePicker2.TabIndex = 10; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(560, 36); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(11, 14); + this.label1.TabIndex = 9; + this.label1.Text = "-"; + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(389, 32); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(165, 22); + this.dateTimePicker1.TabIndex = 8; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(43, 36); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(766, 30); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(85, 26); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(264, 33); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "商品编号", + "商品标题", + "客户编号", + "客户账号", + "客户昵称", + "推广位ID", + "群号"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit1.TabIndex = 0; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(77, 33); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(165, 20); + this.textEdit1.TabIndex = 1; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 558); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(867, 35); + this.pageControl1.TabIndex = 4; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(0, 82); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(864, 470); + this.gridControl1.TabIndex = 3; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn4, + this.gridColumn6, + this.gridColumn5, + this.gridColumn8, + this.gridColumn3, + this.gridColumn2, + this.gridColumn9, + this.gridColumn7}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "编号"; + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 46; + // + // gridColumn4 + // + this.gridColumn4.Caption = "宝贝类型"; + this.gridColumn4.FieldName = "cps_type"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 70; + // + // gridColumn6 + // + this.gridColumn6.Caption = "宝贝标题"; + this.gridColumn6.FieldName = "title"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 2; + this.gridColumn6.Width = 270; + // + // gridColumn5 + // + this.gridColumn5.Caption = "宝贝ID"; + this.gridColumn5.FieldName = "item_id"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 3; + this.gridColumn5.Width = 120; + // + // gridColumn8 + // + this.gridColumn8.Caption = "推广位ID"; + this.gridColumn8.FieldName = "adzoneid"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 4; + this.gridColumn8.Width = 120; + // + // gridColumn3 + // + this.gridColumn3.Caption = "客户昵称"; + this.gridColumn3.FieldName = "usernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 5; + this.gridColumn3.Width = 150; + // + // gridColumn2 + // + this.gridColumn2.Caption = "客户账号"; + this.gridColumn2.FieldName = "username"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 6; + this.gridColumn2.Width = 150; + // + // gridColumn9 + // + this.gridColumn9.Caption = "群号"; + this.gridColumn9.FieldName = "groupid"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 7; + this.gridColumn9.Width = 140; + // + // gridColumn7 + // + this.gridColumn7.Caption = "查询时间"; + this.gridColumn7.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn7.FieldName = "crt_time"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 8; + this.gridColumn7.Width = 160; + // + // item_query_hist_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Name = "item_query_hist_control"; + this.Size = new System.Drawing.Size(867, 593); + this.Load += new System.EventHandler(this.item_query_hist_control_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + } +} diff --git a/FLSystem/Forms/item_query_hist_control.cs b/FLSystem/Forms/item_query_hist_control.cs new file mode 100644 index 0000000..1e67085 --- /dev/null +++ b/FLSystem/Forms/item_query_hist_control.cs @@ -0,0 +1,112 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using System; +using System.Windows.Forms; + +namespace FLSystem.Forms +{ + public partial class item_query_hist_control : DevExpress.XtraEditors.XtraUserControl + { + class view_item_query_hist + { + public long id { get; set; } + public string username { get; set; } + public string usernick { get; set; } + + public CpsType cps_type { get; set; } + + public string item_id { get; set; } + + public string title { get; set; } + + public string adzoneid { get; set; } + + public DateTime crt_time { get; set; } + + public string groupid { get; set; } + + } + public item_query_hist_control() + { + InitializeComponent(); + this.dateTimePicker1.Text = DateTime.Now.ToString("yyyy-MM-dd 00:00:00"); + this.dateTimePicker2.Text = DateTime.Now.ToString(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void item_query_hist_control_Load(object sender, EventArgs e) + { + try + { + this.pageControl1.Bind(delegate (int page, int pagesize) + { + var session = ApiClient.GetSession(); + var map = session.NewParamMap(); + string where = string.Empty; + if (!string.IsNullOrEmpty(this.textEdit1.Text)) + { + switch (this.comboBoxEdit1.Text) + { + case "商品编号": + where = " and q.itemid = @itemid"; + map.setParameter("itemid", this.textEdit1.Text); + break; + case "商品标题": + where = " and q.title like @title"; + map.setParameter("title", "%" + this.textEdit1.Text + "%"); + break; + case "客户编号": + where = " and u.id=@id"; + map.setParameter("id", this.textEdit1.Text); + break; + case "客户昵称": + where = " and u.usernick like @usernick"; + map.setParameter("usernick", "%" + this.textEdit1.Text + "%"); + break; + case "客户账号": + where = " and u.username like @username"; + map.setParameter("username", "%" + this.textEdit1.Text + "%"); + break; + case "群号": + where = " and q.groupid like @groupid"; + map.setParameter("groupid", "%" + this.textEdit1.Text + "%"); + break; + case "推广位ID": + where = " and q.adzoneid like @adzoneid"; + map.setParameter("adzoneid", "%" + this.textEdit1.Text + "%"); + break; + } + } + map.setOrderFields("q.crt_time", true); + map.setPageParamters(page, pagesize); + map.setParameter("crt_time", this.dateTimePicker1.Text); + map.setParameter("end_time", this.dateTimePicker2.Text); + var result = session.FindPage<view_item_query_hist>("select q.id,u.username,u.usernick,q.type cps_type,q.groupid,q.itemid item_id,q.title,q.crt_time,q.adzoneid from fl_query_hist q left join fl_member_info u on q.userid=u.id where q.crt_time > @crt_time and q.crt_time<@end_time " + where, map); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + + }, this.gridControl1, 40, true, true); + } + catch (Exception ex) + { + XtraMessageBox.Show($"{ex.Message} - {ex.StackTrace}", "温馨提示", MessageBoxButtons.OK); + + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit1.SelectedIndex == 0) + { + this.textEdit1.Enabled = false; + this.textEdit1.Text = ""; + } + else this.textEdit1.Enabled = true; + } + } +} diff --git a/FLSystem/Forms/item_query_hist_control.resx b/FLSystem/Forms/item_query_hist_control.resx new file mode 100644 index 0000000..029e1d2 --- /dev/null +++ b/FLSystem/Forms/item_query_hist_control.resx @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/jd_adzone_group_form.Designer.cs b/FLSystem/Forms/jd_adzone_group_form.Designer.cs new file mode 100644 index 0000000..09c7b0c --- /dev/null +++ b/FLSystem/Forms/jd_adzone_group_form.Designer.cs @@ -0,0 +1,457 @@ +namespace FLSystem.Forms +{ + partial class jd_adzone_group_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(jd_adzone_group_form)); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.label4 = new System.Windows.Forms.Label(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.label2 = new System.Windows.Forms.Label(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除勾选推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除全部推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.SuspendLayout(); + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.textBox1); + this.groupControl3.Controls.Add(this.label1); + this.groupControl3.Location = new System.Drawing.Point(637, 12); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(490, 61); + this.groupControl3.TabIndex = 59; + this.groupControl3.Text = "已选推广位"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(159, 28); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(203, 22); + this.textBox1.TabIndex = 49; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(100, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 50; + this.label1.Text = "组名称:"; + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.simpleButton2); + this.groupControl2.Controls.Add(this.textEdit1); + this.groupControl2.Controls.Add(this.labelControl2); + this.groupControl2.Controls.Add(this.comboBoxEdit1); + this.groupControl2.Controls.Add(this.label4); + this.groupControl2.Location = new System.Drawing.Point(12, 12); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(609, 61); + this.groupControl2.TabIndex = 58; + this.groupControl2.Text = "账号选择"; + // + // simpleButton2 + // + this.simpleButton2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton2.Location = new System.Drawing.Point(505, 24); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(81, 23); + this.simpleButton2.TabIndex = 58; + this.simpleButton2.Text = "创建推广位"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(373, 25); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(126, 20); + this.textEdit1.TabIndex = 57; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(315, 28); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 56; + this.labelControl2.Text = "新建名称:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(126, 25); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(157, 20); + this.comboBoxEdit1.TabIndex = 55; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(53, 28); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 14); + this.label4.TabIndex = 47; + this.label4.Text = "操作账号:"; + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.label6); + this.groupControl1.Controls.Add(this.pageControl1); + this.groupControl1.Controls.Add(this.gridControl1); + this.groupControl1.Location = new System.Drawing.Point(12, 79); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(610, 481); + this.groupControl1.TabIndex = 60; + this.groupControl1.Text = "推广位列表"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(5, 117); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(594, 33); + this.label6.TabIndex = 2; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(2, 442); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(607, 36); + this.pageControl1.TabIndex = 1; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.gridControl1.Location = new System.Drawing.Point(0, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(610, 415); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.OptionsView.ShowIndicator = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 200; + // + // gridColumn2 + // + this.gridColumn2.Caption = "PID"; + this.gridColumn2.FieldName = "p_id"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 271; + // + // groupControl4 + // + this.groupControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl4.Controls.Add(this.label2); + this.groupControl4.Controls.Add(this.gridControl2); + this.groupControl4.Location = new System.Drawing.Point(637, 79); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(490, 481); + this.groupControl4.TabIndex = 61; + this.groupControl4.Text = "推广位列表"; + // + // label2 + // + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.ForeColor = System.Drawing.Color.Red; + this.label2.Location = new System.Drawing.Point(5, 117); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(480, 33); + this.label2.TabIndex = 2; + this.label2.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label2.Visible = false; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.gridControl2.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl2.Location = new System.Drawing.Point(0, 24); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(490, 457); + this.gridControl2.TabIndex = 0; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除勾选推广位ToolStripMenuItem, + this.删除全部推广位ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(161, 48); + // + // 删除勾选推广位ToolStripMenuItem + // + this.删除勾选推广位ToolStripMenuItem.Name = "删除勾选推广位ToolStripMenuItem"; + this.删除勾选推广位ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.删除勾选推广位ToolStripMenuItem.Text = "删除勾选推广位"; + this.删除勾选推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除勾选推广位ToolStripMenuItem_Click); + // + // 删除全部推广位ToolStripMenuItem + // + this.删除全部推广位ToolStripMenuItem.Name = "删除全部推广位ToolStripMenuItem"; + this.删除全部推广位ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.删除全部推广位ToolStripMenuItem.Text = "删除全部推广位"; + this.删除全部推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除全部推广位ToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn4, + this.gridColumn5, + this.gridColumn6}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.IndicatorWidth = 50; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsSelection.MultiSelect = true; + this.gridView2.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.OptionsView.ShowIndicator = false; + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn4 + // + this.gridColumn4.Caption = "京东名称"; + this.gridColumn4.FieldName = "Member"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 200; + // + // gridColumn5 + // + this.gridColumn5.Caption = "推广位名称"; + this.gridColumn5.FieldName = "Name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 271; + // + // gridColumn6 + // + this.gridColumn6.Caption = "PID"; + this.gridColumn6.FieldName = "Pid"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 3; + this.gridColumn6.Width = 218; + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(629, 578); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(126, 32); + this.simpleButton3.TabIndex = 63; + this.simpleButton3.Text = " 取 消 "; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton1 + // + this.simpleButton1.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(433, 578); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(126, 32); + this.simpleButton1.TabIndex = 62; + this.simpleButton1.Text = " 确 认 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // jd_adzone_group_form + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.simpleButton3; + this.ClientSize = new System.Drawing.Size(1139, 622); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.groupControl4); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.groupControl3); + this.Controls.Add(this.groupControl2); + this.Name = "jd_adzone_group_form"; + this.Text = "jd_adzone_group_form"; + this.Load += new System.EventHandler(this.jd_adzone_group_form_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + this.groupControl3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private System.Windows.Forms.Label label4; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.Label label6; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.GroupControl groupControl4; + private System.Windows.Forms.Label label2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除勾选推广位ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除全部推广位ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/jd_adzone_group_form.cs b/FLSystem/Forms/jd_adzone_group_form.cs new file mode 100644 index 0000000..eb7537f --- /dev/null +++ b/FLSystem/Forms/jd_adzone_group_form.cs @@ -0,0 +1,312 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using DevExpress.XtraEditors; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class jd_adzone_group_form : BaseForm + { + public class view_jingdong_form_select_tgw + { + public string name { get; set; } + public string p_id { get; set; } + public DateTime create_time { get; set; } + } + + List<Tuiguangwei> tgws = null; + public fl_adzone_group adzone_group = null; + + public jd_adzone_group_form(int id = 0) + { + InitializeComponent(); + var session = ApiClient.GetSession(); + if (id == 0) + tgws = new List<Tuiguangwei>(); + else + { + adzone_group = session.Queryable<fl_adzone_group>().First(f => f.id == id); + if (adzone_group != null) + { + tgws = CsharpHttpHelper.HttpHelper.JsonToObject<List<Tuiguangwei>>(adzone_group.adzones) as List<Tuiguangwei>; + gridControl2.DataSource = tgws; + textBox1.Text = adzone_group.name; + } + else + tgws = new List<Tuiguangwei>(); + } + } + + private void jd_adzone_group_form_Load(object sender, EventArgs e) + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.京东联盟).ToList(); + if (members == null || members.Count == 0) + { + ShowError("对不起,当前未检测到您登录的京东账号!"); + this.Close(); + return; + } + this.comboBoxEdit1.Properties.Items.AddRange(members); + + this.pageControl1.Bind(delegate (int index, int page) + { + try + { + var member = this.comboBoxEdit1.EditValue as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateJingdongRequest(member); + var list = new List<view_jingdong_form_select_tgw>(); + FindTGW(api, 1, member.usernick, member.username, list); + var _list = list.Skip((index - 1) * page).Take(page).ToList(); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = list.Count }; + } + catch (Exception ex) + { + this.UpdateUI(() => + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + }); + } + return null; + }, this.gridControl1, 100, true, true); + + this.comboBoxEdit1.SelectedIndex = 0; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + /// <summary> + /// 获取所有的推广位 + /// </summary> + /// <param name="api"></param> + /// <param name="page"></param> + /// <param name="usernick"></param> + /// <param name="username"></param> + /// <param name="list"></param> + private void FindTGW(JingdongApi api, int page, string usernick, string username, List<view_jingdong_form_select_tgw> list) + { + try + { + var result = api.SendJingdong("jd.union.open.position.query", new { positionReq = new { unionType = 1, pageSize = 100, pageIndex = page, unionId = usernick, key = username } }); + if (result.ContainsKey("data")) + { + var data = result["data"] as Dictionary<string, object>; + if (data.ContainsKey("result")) + { + var result2 = data["result"] as ArrayList; + this.label6.Visible = false; + foreach (Dictionary<string, object> item in result2) + { + list.Add(new view_jingdong_form_select_tgw { name = item["spaceName"].ToString(), p_id = $"{usernick}_{(item.ContainsKey("siteId") ? item["siteId"].ToString() : "0")}_{item["id"].ToString()}" }); + } + } + if (data.ContainsKey("total")) + { + var total = long.Parse(data["total"].ToString()); + var pageNo = int.Parse(data["pageNo"].ToString()); + var pageSize = int.Parse(data["pageSize"].ToString()); + if (total > (pageNo * pageSize)) + { + page++; + FindTGW(api, page, usernick, username, list); + } + } + } + } + catch (Exception) + { } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(this.textEdit1.Text)) throw new Exception("推广位名称不能留空!"); + string pattern = "[\u4e00-\u9fbb]"; + if (Regex.IsMatch(this.textEdit1.Text, pattern)) throw new Exception("推广位名称不能包含中文!"); + + if (XtraMessageBox.Show($"您确定要创建名为【{this.textEdit1.Text}】的推广位吗?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var member = this.comboBoxEdit1.EditValue as fl_cps_member; + var api = CpsClient.CreateJingdongRequest(member); + api.SendJingdong("jd.union.open.position.create", new + { + positionReq = new + { + spaceNameList = new string[] { this.textEdit1.Text }, + unionType = 1, + type = 4, + unionId = member.usernick, + key = member.username + } + }); + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + ShowError(ex); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + + #region 勾选已经选中的数据 + var _list = gridControl1.DataSource as List<view_jingdong_form_select_tgw>; + if (_list != null && tgws != null && tgws.Count != 0) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + var _tgws = tgws.Where(f => f.Member.username == member.username).ToList(); + for (int i = 0; i < _tgws.Count; i++) + { + gridView1.SelectRow(_list.IndexOf(_list.FirstOrDefault(f => f.p_id == _tgws[i].Pid))); + } + } + #endregion + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + if (e.Column.AbsoluteIndex == -1) + { + var flag = e.CellValue.ToString().ToLower() != "true"; + var pid = gridView1.GetRowCellDisplayText(gridView1.FocusedRowHandle, gridView1.Columns["p_id"]);//获取群号 + if (string.IsNullOrEmpty(pid)) throw new Exception("您当前没有选中任何一行!"); + var _tgw = tgws.FirstOrDefault(f => f.Pid == pid); + if (flag)//增加到集合中 + { + if (_tgw == null) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + _tgw = new Tuiguangwei() + { + Member = new fl_cps_member() { username = member.username, usernick = member.usernick }, + Name = gridView1.GetRowCellDisplayText(gridView1.FocusedRowHandle, gridView1.Columns["name"]), + Pid = pid + }; + tgws.Add(_tgw); + } + } + else + { + if (_tgw != null) + tgws.Remove(_tgw); + } + gridControl2.DataSource = null; + gridControl2.DataSource = tgws; + } + } + catch (Exception ex) + { } + } + + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "Member") + { + var cps = e.Value as fl_cps_member; + e.DisplayText = cps.usernick; + } + } + catch (Exception ex) + { } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("组名称不能为空"); + //if (string.IsNullOrWhiteSpace(memoEdit1.Text)) throw new Exception("请选择推广位"); + if (gridView2.RowCount == 0) throw new Exception("请选择推广位"); + var session = ApiClient.GetSession(); + if (adzone_group == null) + { + adzone_group = new fl_adzone_group() { adzones = CsharpHttpHelper.HttpHelper.ObjectToJson(tgws), cps_type = CpsType.京东联盟, name = textBox1.Text.Trim() }; + } + else + { + adzone_group.adzones = CsharpHttpHelper.HttpHelper.ObjectToJson(tgws); + adzone_group.name = textBox1.Text.Trim(); + } + adzone_group = session.Saveable(adzone_group).ExecuteReturnEntity(); + this.DialogResult = System.Windows.Forms.DialogResult.OK; + } + catch (Exception ex) + { + if (ex.Message.Contains("UNIQUE constraint failed")) + ShowError("推广位组名称已经存在"); + else + ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.No; + this.Close(); + } + + private void 删除勾选推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView2.GetSelectedRows().OrderByDescending(f => f).ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + foreach (var item in rownumber) + { + var _tgw = gridView2.GetRow(item) as Tuiguangwei; + tgws.Remove(_tgw); + } + gridControl2.DataSource = null; + gridControl2.DataSource = tgws; + ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除全部推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + tgws.Clear(); + gridControl2.DataSource = null; + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/jd_adzone_group_form.resx b/FLSystem/Forms/jd_adzone_group_form.resx new file mode 100644 index 0000000..91fb685 --- /dev/null +++ b/FLSystem/Forms/jd_adzone_group_form.resx @@ -0,0 +1,220 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton3.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC +</value> + </data> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== +</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/main.Designer.cs b/FLSystem/Forms/main.Designer.cs new file mode 100644 index 0000000..0b804ca --- /dev/null +++ b/FLSystem/Forms/main.Designer.cs @@ -0,0 +1,2039 @@ +namespace FLSystem.Forms +{ + partial class main + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(main)); + this.ribbonStatusBar1 = new DevExpress.XtraBars.Ribbon.RibbonStatusBar(); + this.barHeaderItem4 = new DevExpress.XtraBars.BarHeaderItem(); + this.barButtonItem53 = new DevExpress.XtraBars.BarButtonItem(); + this.barStaticItem3 = new DevExpress.XtraBars.BarStaticItem(); + this.barStaticItem5 = new DevExpress.XtraBars.BarStaticItem(); + this.barStaticItem7 = new DevExpress.XtraBars.BarStaticItem(); + this.barStaticItem8 = new DevExpress.XtraBars.BarStaticItem(); + this.barStaticItem12 = new DevExpress.XtraBars.BarStaticItem(); + this.ribbonControl1 = new DevExpress.XtraBars.Ribbon.RibbonControl(); + this.barHeaderItem1 = new DevExpress.XtraBars.BarHeaderItem(); + this.barButtonItem9 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem10 = new DevExpress.XtraBars.BarButtonItem(); + this.btn_cps_manage = new DevExpress.XtraBars.BarButtonItem(); + this.btn_robot_manage = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem19 = new DevExpress.XtraBars.BarButtonItem(); + this.menu_login_chat = new DevExpress.XtraBars.PopupMenu(this.components); + this.barButtonItem50 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem51 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem52 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem20 = new DevExpress.XtraBars.BarButtonItem(); + this.menu_login_cps = new DevExpress.XtraBars.PopupMenu(this.components); + this.barButtonItem21 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem25 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem26 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem97 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem100 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem107 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem108 = new DevExpress.XtraBars.BarButtonItem(); + this.btn_log_manage = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem22 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem23 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem24 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem28 = new DevExpress.XtraBars.BarButtonItem(); + this.barSubItem1 = new DevExpress.XtraBars.BarSubItem(); + this.barButtonItem1 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem2 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem3 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem4 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem5 = new DevExpress.XtraBars.BarButtonItem(); + this.barEditItem1 = new DevExpress.XtraBars.BarEditItem(); + this.repositoryItemHypertextLabel1 = new DevExpress.XtraEditors.Repository.RepositoryItemHypertextLabel(); + this.barButtonItem6 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem7 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem8 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem11 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem12 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem13 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem14 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem15 = new DevExpress.XtraBars.BarButtonItem(); + this.skinRibbonGalleryBarItem1 = new DevExpress.XtraBars.SkinRibbonGalleryBarItem(); + this.skinPaletteRibbonGalleryBarItem1 = new DevExpress.XtraBars.SkinPaletteRibbonGalleryBarItem(); + this.skin_manager = new DevExpress.XtraBars.SkinDropDownButtonItem(); + this.barButtonItem16 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem17 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem18 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem27 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem29 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem30 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem31 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem33 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem34 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem35 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem36 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem37 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem38 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem39 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem40 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem41 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem42 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem43 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem44 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem45 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem46 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem47 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem48 = new DevExpress.XtraBars.BarButtonItem(); + this.menu_cps_order = new DevExpress.XtraBars.PopupMenu(this.components); + this.barButtonItem95 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem60 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem98 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem99 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem105 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem109 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem49 = new DevExpress.XtraBars.BarButtonItem(); + this.barEditItem2 = new DevExpress.XtraBars.BarEditItem(); + this.repositoryItemHypertextLabel2 = new DevExpress.XtraEditors.Repository.RepositoryItemHypertextLabel(); + this.barStaticItem1 = new DevExpress.XtraBars.BarStaticItem(); + this.barButtonItem54 = new DevExpress.XtraBars.BarButtonItem(); + this.barStaticItem2 = new DevExpress.XtraBars.BarStaticItem(); + this.barStaticItem4 = new DevExpress.XtraBars.BarStaticItem(); + this.barLinkContainerItem1 = new DevExpress.XtraBars.BarLinkContainerItem(); + this.barButtonItem55 = new DevExpress.XtraBars.BarButtonItem(); + this.barStaticItem6 = new DevExpress.XtraBars.BarStaticItem(); + this.barStaticItem9 = new DevExpress.XtraBars.BarStaticItem(); + this.barStaticItem10 = new DevExpress.XtraBars.BarStaticItem(); + this.barButtonItem56 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem57 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem59 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem61 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem62 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem63 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem64 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem65 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem66 = new DevExpress.XtraBars.BarButtonItem(); + this.btn_data_manage = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem67 = new DevExpress.XtraBars.BarButtonItem(); + this.barEditItem3 = new DevExpress.XtraBars.BarEditItem(); + this.repositoryItemHypertextLabel3 = new DevExpress.XtraEditors.Repository.RepositoryItemHypertextLabel(); + this.barEditItem4 = new DevExpress.XtraBars.BarEditItem(); + this.repositoryItemPictureEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.ribbonGalleryBarItem1 = new DevExpress.XtraBars.RibbonGalleryBarItem(); + this.barButtonItem68 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem69 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem70 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem71 = new DevExpress.XtraBars.BarButtonItem(); + this.PublicNote = new DevExpress.XtraBars.BarStaticItem(); + this.barButtonItem72 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem73 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem74 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem75 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem76 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem77 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem78 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem80 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem81 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem82 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem83 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem84 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem85 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem86 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem87 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem88 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem89 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem90 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem91 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem92 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem93 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem96 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem94 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem101 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem102 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem_douyin = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem103 = new DevExpress.XtraBars.BarButtonItem(); + this.btn_home_manage = new DevExpress.XtraBars.BarButtonItem(); + this.ribbonPageCategory2 = new DevExpress.XtraBars.Ribbon.RibbonPageCategory(); + this.ribbonPage1 = new DevExpress.XtraBars.Ribbon.RibbonPage(); + this.ribbonPageGroup1 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageGroup2 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageGroup7 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageGroup10 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPage2 = new DevExpress.XtraBars.Ribbon.RibbonPage(); + this.ribbonPageGroup9 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageGroup12 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageGroup14 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPage3 = new DevExpress.XtraBars.Ribbon.RibbonPage(); + this.ribbonPageGroup3 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageGroup4 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageGroup13 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageGroup11 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPage4 = new DevExpress.XtraBars.Ribbon.RibbonPage(); + this.ribbonPageGroup5 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.repositoryItemImageEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemImageEdit(); + this.repositoryItemImageEdit2 = new DevExpress.XtraEditors.Repository.RepositoryItemImageEdit(); + this.ribbonPage5 = new DevExpress.XtraBars.Ribbon.RibbonPage(); + this.ribbonPageGroup8 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.ribbonPageCategory1 = new DevExpress.XtraBars.Ribbon.RibbonPageCategory(); + this.barCheckItem3 = new DevExpress.XtraBars.BarCheckItem(); + this.barCheckItem4 = new DevExpress.XtraBars.BarCheckItem(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.notify_pallet = new System.Windows.Forms.NotifyIcon(this.components); + this.menu_tray = new DevExpress.XtraBars.PopupMenu(this.components); + this.barButtonItem32 = new DevExpress.XtraBars.BarButtonItem(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.barButtonItem58 = new DevExpress.XtraBars.BarButtonItem(); + this.menu_coerce_order = new DevExpress.XtraBars.PopupMenu(this.components); + this.barButtonItem79 = new DevExpress.XtraBars.BarButtonItem(); + this.ribbonPageGroup6 = new DevExpress.XtraBars.Ribbon.RibbonPageGroup(); + this.button1 = new System.Windows.Forms.Button(); + this.autologin_timer = new System.Windows.Forms.Timer(this.components); + this.alertControl1 = new DevExpress.XtraBars.Alerter.AlertControl(this.components); + this.barButtonItem104 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem106 = new DevExpress.XtraBars.BarButtonItem(); + ((System.ComponentModel.ISupportInitialize)(this.ribbonControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_login_chat)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_login_cps)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemHypertextLabel1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_cps_order)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemHypertextLabel2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemHypertextLabel3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemImageEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemImageEdit2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_tray)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_coerce_order)).BeginInit(); + this.SuspendLayout(); + // + // ribbonStatusBar1 + // + this.ribbonStatusBar1.ItemLinks.Add(this.barHeaderItem4); + this.ribbonStatusBar1.ItemLinks.Add(this.barButtonItem53); + this.ribbonStatusBar1.ItemLinks.Add(this.barStaticItem3, true); + this.ribbonStatusBar1.ItemLinks.Add(this.barStaticItem5); + this.ribbonStatusBar1.ItemLinks.Add(this.barStaticItem7, true); + this.ribbonStatusBar1.ItemLinks.Add(this.barStaticItem8); + this.ribbonStatusBar1.ItemLinks.Add(this.barStaticItem12, true); + this.ribbonStatusBar1.Location = new System.Drawing.Point(0, 669); + this.ribbonStatusBar1.Name = "ribbonStatusBar1"; + this.ribbonStatusBar1.Ribbon = this.ribbonControl1; + this.ribbonStatusBar1.Size = new System.Drawing.Size(935, 22); + // + // barHeaderItem4 + // + this.barHeaderItem4.Caption = "账号:"; + this.barHeaderItem4.Id = 55; + this.barHeaderItem4.Name = "barHeaderItem4"; + // + // barButtonItem53 + // + this.barButtonItem53.Caption = "administrator"; + this.barButtonItem53.Id = 22; + this.barButtonItem53.Name = "barButtonItem53"; + // + // barStaticItem3 + // + this.barStaticItem3.Caption = "余额:"; + this.barStaticItem3.Id = 25; + this.barStaticItem3.Name = "barStaticItem3"; + // + // barStaticItem5 + // + this.barStaticItem5.Caption = "barStaticItem5"; + this.barStaticItem5.Id = 29; + this.barStaticItem5.Name = "barStaticItem5"; + // + // barStaticItem7 + // + this.barStaticItem7.Caption = "累计充值:"; + this.barStaticItem7.Id = 31; + this.barStaticItem7.Name = "barStaticItem7"; + // + // barStaticItem8 + // + this.barStaticItem8.Caption = "barStaticItem8"; + this.barStaticItem8.Id = 32; + this.barStaticItem8.Name = "barStaticItem8"; + // + // barStaticItem12 + // + this.barStaticItem12.Alignment = DevExpress.XtraBars.BarItemLinkAlignment.Right; + this.barStaticItem12.Caption = "barStaticItem12"; + this.barStaticItem12.Id = 36; + this.barStaticItem12.Name = "barStaticItem12"; + // + // ribbonControl1 + // + this.ribbonControl1.ApplicationButtonText = "菜单"; + this.ribbonControl1.ExpandCollapseItem.Id = 0; + this.ribbonControl1.Font = new System.Drawing.Font("Tahoma", 15F); + this.ribbonControl1.Items.AddRange(new DevExpress.XtraBars.BarItem[] { + this.ribbonControl1.ExpandCollapseItem, + this.ribbonControl1.SearchEditItem, + this.barHeaderItem1, + this.barButtonItem9, + this.barButtonItem10, + this.btn_cps_manage, + this.btn_robot_manage, + this.barButtonItem19, + this.barButtonItem20, + this.btn_log_manage, + this.barButtonItem22, + this.barButtonItem23, + this.barButtonItem24, + this.barHeaderItem4, + this.barButtonItem28, + this.barSubItem1, + this.barButtonItem1, + this.barButtonItem2, + this.barButtonItem3, + this.barButtonItem4, + this.barButtonItem5, + this.barEditItem1, + this.barButtonItem6, + this.barButtonItem7, + this.barButtonItem8, + this.barButtonItem11, + this.barButtonItem12, + this.barButtonItem13, + this.barButtonItem14, + this.barButtonItem15, + this.skinRibbonGalleryBarItem1, + this.skinPaletteRibbonGalleryBarItem1, + this.skin_manager, + this.barButtonItem16, + this.barButtonItem17, + this.barButtonItem18, + this.barButtonItem21, + this.barButtonItem25, + this.barButtonItem26, + this.barButtonItem27, + this.barButtonItem29, + this.barButtonItem30, + this.barButtonItem31, + this.barButtonItem33, + this.barButtonItem34, + this.barButtonItem35, + this.barButtonItem36, + this.barButtonItem37, + this.barButtonItem38, + this.barButtonItem39, + this.barButtonItem40, + this.barButtonItem41, + this.barButtonItem42, + this.barButtonItem43, + this.barButtonItem44, + this.barButtonItem45, + this.barButtonItem46, + this.barButtonItem47, + this.barButtonItem48, + this.barButtonItem49, + this.barEditItem2, + this.barStaticItem1, + this.barButtonItem50, + this.barButtonItem51, + this.barButtonItem52, + this.barButtonItem53, + this.barButtonItem54, + this.barStaticItem2, + this.barStaticItem3, + this.barStaticItem4, + this.barLinkContainerItem1, + this.barButtonItem55, + this.barStaticItem5, + this.barStaticItem6, + this.barStaticItem7, + this.barStaticItem8, + this.barStaticItem9, + this.barStaticItem10, + this.barStaticItem12, + this.barButtonItem56, + this.barButtonItem57, + this.barButtonItem59, + this.barButtonItem60, + this.barButtonItem61, + this.barButtonItem62, + this.barButtonItem63, + this.barButtonItem64, + this.barButtonItem65, + this.barButtonItem66, + this.btn_data_manage, + this.barButtonItem67, + this.barEditItem3, + this.barEditItem4, + this.ribbonGalleryBarItem1, + this.barButtonItem68, + this.barButtonItem69, + this.barButtonItem70, + this.barButtonItem71, + this.PublicNote, + this.barButtonItem72, + this.barButtonItem73, + this.barButtonItem74, + this.barButtonItem75, + this.barButtonItem76, + this.barButtonItem77, + this.barButtonItem78, + this.barButtonItem80, + this.barButtonItem81, + this.barButtonItem82, + this.barButtonItem83, + this.barButtonItem84, + this.barButtonItem85, + this.barButtonItem86, + this.barButtonItem87, + this.barButtonItem88, + this.barButtonItem89, + this.barButtonItem90, + this.barButtonItem91, + this.barButtonItem92, + this.barButtonItem93, + this.barButtonItem95, + this.barButtonItem96, + this.barButtonItem94, + this.barButtonItem97, + this.barButtonItem98, + this.barButtonItem99, + this.barButtonItem100, + this.barButtonItem101, + this.barButtonItem102, + this.barButtonItem_douyin, + this.barButtonItem103, + this.btn_home_manage, + this.barButtonItem105, + this.barButtonItem107, + this.barButtonItem108, + this.barButtonItem109}); + this.ribbonControl1.Location = new System.Drawing.Point(0, 0); + this.ribbonControl1.MaxItemId = 140; + this.ribbonControl1.Name = "ribbonControl1"; + this.ribbonControl1.PageCategories.AddRange(new DevExpress.XtraBars.Ribbon.RibbonPageCategory[] { + this.ribbonPageCategory2}); + this.ribbonControl1.Pages.AddRange(new DevExpress.XtraBars.Ribbon.RibbonPage[] { + this.ribbonPage1, + this.ribbonPage2, + this.ribbonPage3, + this.ribbonPage4}); + this.ribbonControl1.QuickToolbarItemLinks.Add(this.PublicNote); + this.ribbonControl1.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemImageEdit1, + this.repositoryItemImageEdit2, + this.repositoryItemHypertextLabel1, + this.repositoryItemHypertextLabel2, + this.repositoryItemHypertextLabel3, + this.repositoryItemPictureEdit1}); + this.ribbonControl1.ShowPageHeadersMode = DevExpress.XtraBars.Ribbon.ShowPageHeadersMode.Show; + this.ribbonControl1.ShowToolbarCustomizeItem = false; + this.ribbonControl1.Size = new System.Drawing.Size(935, 150); + this.ribbonControl1.StatusBar = this.ribbonStatusBar1; + this.ribbonControl1.Toolbar.ShowCustomizeItem = false; + this.ribbonControl1.ToolbarLocation = DevExpress.XtraBars.Ribbon.RibbonQuickAccessToolbarLocation.Below; + // + // barHeaderItem1 + // + this.barHeaderItem1.Caption = "启动"; + this.barHeaderItem1.Id = 2; + this.barHeaderItem1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barHeaderItem1.ImageOptions.Image"))); + this.barHeaderItem1.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barHeaderItem1.ImageOptions.LargeImage"))); + this.barHeaderItem1.Name = "barHeaderItem1"; + // + // barButtonItem9 + // + this.barButtonItem9.Caption = "接收信息"; + this.barButtonItem9.Id = 23; + this.barButtonItem9.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem9.ImageOptions.Image"))); + this.barButtonItem9.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem9.ImageOptions.LargeImage"))); + this.barButtonItem9.Name = "barButtonItem9"; + this.barButtonItem9.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem9_ItemClick); + // + // barButtonItem10 + // + this.barButtonItem10.Caption = "停止接收"; + this.barButtonItem10.Id = 24; + this.barButtonItem10.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem10.ImageOptions.Image"))); + this.barButtonItem10.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.停止__4_; + this.barButtonItem10.Name = "barButtonItem10"; + this.barButtonItem10.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem10_ItemClick); + // + // btn_cps_manage + // + this.btn_cps_manage.Caption = "联盟管理"; + this.btn_cps_manage.Id = 28; + this.btn_cps_manage.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("btn_cps_manage.ImageOptions.Image"))); + this.btn_cps_manage.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.平台级业务监控; + this.btn_cps_manage.Name = "btn_cps_manage"; + this.btn_cps_manage.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // btn_robot_manage + // + this.btn_robot_manage.Caption = "机器人管理"; + this.btn_robot_manage.Id = 31; + this.btn_robot_manage.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("btn_robot_manage.ImageOptions.Image"))); + this.btn_robot_manage.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("btn_robot_manage.ImageOptions.LargeImage"))); + this.btn_robot_manage.Name = "btn_robot_manage"; + this.btn_robot_manage.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem19 + // + this.barButtonItem19.ActAsDropDown = true; + this.barButtonItem19.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.DropDown; + this.barButtonItem19.Caption = "登录机器人"; + this.barButtonItem19.DropDownControl = this.menu_login_chat; + this.barButtonItem19.Id = 36; + this.barButtonItem19.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem19.ImageOptions.Image"))); + this.barButtonItem19.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.二维码登录; + this.barButtonItem19.Name = "barButtonItem19"; + // + // menu_login_chat + // + this.menu_login_chat.ItemLinks.Add(this.barButtonItem50); + this.menu_login_chat.ItemLinks.Add(this.barButtonItem51); + this.menu_login_chat.ItemLinks.Add(this.barButtonItem52); + this.menu_login_chat.Name = "menu_login_chat"; + this.menu_login_chat.Ribbon = this.ribbonControl1; + // + // barButtonItem50 + // + this.barButtonItem50.Caption = "登录微信"; + this.barButtonItem50.Id = 19; + this.barButtonItem50.ImageOptions.Image = global::FLSystem.Properties.Resources.微信__3_; + this.barButtonItem50.Name = "barButtonItem50"; + this.barButtonItem50.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem50_ItemClick); + // + // barButtonItem51 + // + this.barButtonItem51.Caption = "登录QQ"; + this.barButtonItem51.Id = 20; + this.barButtonItem51.ImageOptions.Image = global::FLSystem.Properties.Resources.QQ; + this.barButtonItem51.Name = "barButtonItem51"; + this.barButtonItem51.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem51_ItemClick); + // + // barButtonItem52 + // + this.barButtonItem52.Caption = "添加微信公众号"; + this.barButtonItem52.Enabled = false; + this.barButtonItem52.Id = 21; + this.barButtonItem52.ImageOptions.Image = global::FLSystem.Properties.Resources.公众号__2_; + this.barButtonItem52.Name = "barButtonItem52"; + // + // barButtonItem20 + // + this.barButtonItem20.ActAsDropDown = true; + this.barButtonItem20.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.DropDown; + this.barButtonItem20.Caption = "登录联盟"; + this.barButtonItem20.DropDownControl = this.menu_login_cps; + this.barButtonItem20.Id = 37; + this.barButtonItem20.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem20.ImageOptions.Image"))); + this.barButtonItem20.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.授权zh_01; + this.barButtonItem20.Name = "barButtonItem20"; + // + // menu_login_cps + // + this.menu_login_cps.ItemLinks.Add(this.barButtonItem21); + this.menu_login_cps.ItemLinks.Add(this.barButtonItem25); + this.menu_login_cps.ItemLinks.Add(this.barButtonItem26); + this.menu_login_cps.ItemLinks.Add(this.barButtonItem97); + this.menu_login_cps.ItemLinks.Add(this.barButtonItem100); + this.menu_login_cps.ItemLinks.Add(this.barButtonItem107); + this.menu_login_cps.ItemLinks.Add(this.barButtonItem108); + this.menu_login_cps.Name = "menu_login_cps"; + this.menu_login_cps.Ribbon = this.ribbonControl1; + // + // barButtonItem21 + // + this.barButtonItem21.Alignment = DevExpress.XtraBars.BarItemLinkAlignment.Left; + this.barButtonItem21.Caption = "登录多多进宝"; + this.barButtonItem21.Id = 82; + this.barButtonItem21.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem21.ImageOptions.Image"))); + this.barButtonItem21.Name = "barButtonItem21"; + this.barButtonItem21.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph; + this.barButtonItem21.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem21_ItemClick); + // + // barButtonItem25 + // + this.barButtonItem25.Caption = "登录阿里妈妈"; + this.barButtonItem25.Id = 83; + this.barButtonItem25.ImageOptions.Image = global::FLSystem.Properties.Resources.淘宝_20; + this.barButtonItem25.Name = "barButtonItem25"; + this.barButtonItem25.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem25_ItemClick); + // + // barButtonItem26 + // + this.barButtonItem26.Caption = "登录京东联盟"; + this.barButtonItem26.Id = 84; + this.barButtonItem26.ImageOptions.Image = global::FLSystem.Properties.Resources.京东_20; + this.barButtonItem26.Name = "barButtonItem26"; + this.barButtonItem26.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem26_ItemClick); + // + // barButtonItem97 + // + this.barButtonItem97.Caption = "登录唯品会联盟"; + this.barButtonItem97.Id = 126; + this.barButtonItem97.ImageOptions.Image = global::FLSystem.Properties.Resources.唯品会12; + this.barButtonItem97.Name = "barButtonItem97"; + this.barButtonItem97.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem97_ItemClick); + // + // barButtonItem100 + // + this.barButtonItem100.Caption = "登录抖音联盟"; + this.barButtonItem100.Id = 129; + this.barButtonItem100.ImageOptions.Image = global::FLSystem.Properties.Resources.抖音; + this.barButtonItem100.Name = "barButtonItem100"; + this.barButtonItem100.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem100_ItemClick); + // + // barButtonItem107 + // + this.barButtonItem107.Caption = "苏宁易购联盟"; + this.barButtonItem107.Id = 137; + this.barButtonItem107.ImageOptions.Image = global::FLSystem.Properties.Resources.苏宁小; + this.barButtonItem107.Name = "barButtonItem107"; + this.barButtonItem107.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem107_ItemClick); + // + // barButtonItem108 + // + this.barButtonItem108.Caption = "登录快手联盟"; + this.barButtonItem108.Id = 138; + this.barButtonItem108.ImageOptions.Image = global::FLSystem.Properties.Resources.快手登录; + this.barButtonItem108.Name = "barButtonItem108"; + this.barButtonItem108.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem108_ItemClick); + // + // btn_log_manage + // + this.btn_log_manage.Caption = "运行日志"; + this.btn_log_manage.Id = 38; + this.btn_log_manage.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("btn_log_manage.ImageOptions.Image"))); + this.btn_log_manage.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("btn_log_manage.ImageOptions.LargeImage"))); + this.btn_log_manage.Name = "btn_log_manage"; + this.btn_log_manage.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem22 + // + this.barButtonItem22.Caption = "开始监听"; + this.barButtonItem22.Id = 43; + this.barButtonItem22.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem22.ImageOptions.Image"))); + this.barButtonItem22.Name = "barButtonItem22"; + // + // barButtonItem23 + // + this.barButtonItem23.Caption = "暂停监听"; + this.barButtonItem23.Enabled = false; + this.barButtonItem23.Id = 44; + this.barButtonItem23.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem23.ImageOptions.Image"))); + this.barButtonItem23.Name = "barButtonItem23"; + // + // barButtonItem24 + // + this.barButtonItem24.Caption = "停止监听"; + this.barButtonItem24.Enabled = false; + this.barButtonItem24.Id = 45; + this.barButtonItem24.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem24.ImageOptions.Image"))); + this.barButtonItem24.Name = "barButtonItem24"; + // + // barButtonItem28 + // + this.barButtonItem28.Caption = "打开工作目录"; + this.barButtonItem28.Id = 58; + this.barButtonItem28.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem28.ImageOptions.Image"))); + this.barButtonItem28.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem28.ImageOptions.LargeImage"))); + this.barButtonItem28.Name = "barButtonItem28"; + // + // barSubItem1 + // + this.barSubItem1.Caption = "barSubItem1"; + this.barSubItem1.Id = 61; + this.barSubItem1.Name = "barSubItem1"; + // + // barButtonItem1 + // + this.barButtonItem1.Caption = "检查更新"; + this.barButtonItem1.Id = 62; + this.barButtonItem1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem1.ImageOptions.Image"))); + this.barButtonItem1.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem1.ImageOptions.LargeImage"))); + this.barButtonItem1.Name = "barButtonItem1"; + this.barButtonItem1.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem1_ItemClick); + // + // barButtonItem2 + // + this.barButtonItem2.Caption = "重启系统"; + this.barButtonItem2.Id = 63; + this.barButtonItem2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem2.ImageOptions.Image"))); + this.barButtonItem2.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem2.ImageOptions.LargeImage"))); + this.barButtonItem2.Name = "barButtonItem2"; + this.barButtonItem2.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem2_ItemClick); + // + // barButtonItem3 + // + this.barButtonItem3.Caption = "退出系统"; + this.barButtonItem3.Id = 64; + this.barButtonItem3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem3.ImageOptions.Image"))); + this.barButtonItem3.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem3.ImageOptions.LargeImage"))); + this.barButtonItem3.Name = "barButtonItem3"; + this.barButtonItem3.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem3_ItemClick); + // + // barButtonItem4 + // + this.barButtonItem4.Caption = "打开工作目录"; + this.barButtonItem4.Id = 65; + this.barButtonItem4.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem4.ImageOptions.Image"))); + this.barButtonItem4.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem4.ImageOptions.LargeImage"))); + this.barButtonItem4.Name = "barButtonItem4"; + this.barButtonItem4.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem4_ItemClick); + // + // barButtonItem5 + // + this.barButtonItem5.Caption = "打开插件目录"; + this.barButtonItem5.Id = 66; + this.barButtonItem5.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem5.ImageOptions.Image"))); + this.barButtonItem5.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem5.ImageOptions.LargeImage"))); + this.barButtonItem5.Name = "barButtonItem5"; + this.barButtonItem5.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem5_ItemClick); + // + // barEditItem1 + // + this.barEditItem1.Caption = "barEditItem1"; + this.barEditItem1.Edit = this.repositoryItemHypertextLabel1; + this.barEditItem1.Id = 67; + this.barEditItem1.Name = "barEditItem1"; + // + // repositoryItemHypertextLabel1 + // + this.repositoryItemHypertextLabel1.Name = "repositoryItemHypertextLabel1"; + // + // barButtonItem6 + // + this.barButtonItem6.Caption = "应用功能"; + this.barButtonItem6.Id = 68; + this.barButtonItem6.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem6.ImageOptions.LargeImage"))); + this.barButtonItem6.Name = "barButtonItem6"; + this.barButtonItem6.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem7 + // + this.barButtonItem7.Caption = "barButtonItem7"; + this.barButtonItem7.Id = 69; + this.barButtonItem7.Name = "barButtonItem7"; + // + // barButtonItem8 + // + this.barButtonItem8.Caption = "开发文档"; + this.barButtonItem8.Enabled = false; + this.barButtonItem8.Id = 70; + this.barButtonItem8.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem8.ImageOptions.Image"))); + this.barButtonItem8.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem8.ImageOptions.LargeImage"))); + this.barButtonItem8.Name = "barButtonItem8"; + this.barButtonItem8.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem8_ItemClick); + // + // barButtonItem11 + // + this.barButtonItem11.Caption = "加密应用"; + this.barButtonItem11.Id = 71; + this.barButtonItem11.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem11.ImageOptions.Image"))); + this.barButtonItem11.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem11.ImageOptions.LargeImage"))); + this.barButtonItem11.Name = "barButtonItem11"; + this.barButtonItem11.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem11_ItemClick); + // + // barButtonItem12 + // + this.barButtonItem12.Caption = "会员相关"; + this.barButtonItem12.Id = 72; + this.barButtonItem12.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem12.ImageOptions.Image"))); + this.barButtonItem12.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem12.ImageOptions.LargeImage"))); + this.barButtonItem12.Name = "barButtonItem12"; + this.barButtonItem12.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem13 + // + this.barButtonItem13.Caption = "系统设置"; + this.barButtonItem13.Id = 73; + this.barButtonItem13.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem13.ImageOptions.Image"))); + this.barButtonItem13.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem13.ImageOptions.LargeImage"))); + this.barButtonItem13.Name = "barButtonItem13"; + this.barButtonItem13.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem14 + // + this.barButtonItem14.Caption = "登录微信"; + this.barButtonItem14.Id = 74; + this.barButtonItem14.Name = "barButtonItem14"; + // + // barButtonItem15 + // + this.barButtonItem15.Caption = "登录QQ"; + this.barButtonItem15.Id = 75; + this.barButtonItem15.Name = "barButtonItem15"; + // + // skinRibbonGalleryBarItem1 + // + this.skinRibbonGalleryBarItem1.Caption = "skinRibbonGalleryBarItem1"; + this.skinRibbonGalleryBarItem1.Id = 76; + this.skinRibbonGalleryBarItem1.Name = "skinRibbonGalleryBarItem1"; + // + // skinPaletteRibbonGalleryBarItem1 + // + this.skinPaletteRibbonGalleryBarItem1.Caption = "skinPaletteRibbonGalleryBarItem1"; + this.skinPaletteRibbonGalleryBarItem1.Id = 77; + this.skinPaletteRibbonGalleryBarItem1.Name = "skinPaletteRibbonGalleryBarItem1"; + // + // skin_manager + // + this.skin_manager.Id = 78; + this.skin_manager.Name = "skin_manager"; + this.skin_manager.RibbonStyle = ((DevExpress.XtraBars.Ribbon.RibbonItemStyles)(((DevExpress.XtraBars.Ribbon.RibbonItemStyles.Large | DevExpress.XtraBars.Ribbon.RibbonItemStyles.SmallWithText) + | DevExpress.XtraBars.Ribbon.RibbonItemStyles.SmallWithoutText))); + // + // barButtonItem16 + // + this.barButtonItem16.Caption = "测试邮件通信"; + this.barButtonItem16.Id = 79; + this.barButtonItem16.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem16.ImageOptions.Image"))); + this.barButtonItem16.Name = "barButtonItem16"; + this.barButtonItem16.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem16_ItemClick); + // + // barButtonItem17 + // + this.barButtonItem17.Caption = "模拟请求消息"; + this.barButtonItem17.Enabled = false; + this.barButtonItem17.Id = 80; + this.barButtonItem17.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem17.ImageOptions.Image"))); + this.barButtonItem17.Name = "barButtonItem17"; + // + // barButtonItem18 + // + this.barButtonItem18.Caption = "添加公众号"; + this.barButtonItem18.Id = 81; + this.barButtonItem18.Name = "barButtonItem18"; + // + // barButtonItem27 + // + this.barButtonItem27.Caption = "开发调试"; + this.barButtonItem27.Id = 85; + this.barButtonItem27.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem27.ImageOptions.Image"))); + this.barButtonItem27.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem27.ImageOptions.LargeImage"))); + this.barButtonItem27.Name = "barButtonItem27"; + this.barButtonItem27.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem29 + // + this.barButtonItem29.Caption = "刷新应用"; + this.barButtonItem29.Id = 86; + this.barButtonItem29.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem29.ImageOptions.Image"))); + this.barButtonItem29.Name = "barButtonItem29"; + this.barButtonItem29.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem29_ItemClick); + // + // barButtonItem30 + // + this.barButtonItem30.Caption = "执行顺序"; + this.barButtonItem30.Id = 87; + this.barButtonItem30.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem30.ImageOptions.Image"))); + this.barButtonItem30.Name = "barButtonItem30"; + this.barButtonItem30.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem30_ItemClick); + // + // barButtonItem31 + // + this.barButtonItem31.Caption = "全部重启"; + this.barButtonItem31.Id = 88; + this.barButtonItem31.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem31.ImageOptions.Image"))); + this.barButtonItem31.Name = "barButtonItem31"; + this.barButtonItem31.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem31_ItemClick); + // + // barButtonItem33 + // + this.barButtonItem33.Caption = "拼多多订单管理"; + this.barButtonItem33.Id = 90; + this.barButtonItem33.ImageOptions.Image = global::FLSystem.Properties.Resources.拼多多_20; + this.barButtonItem33.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.拼多多_1_; + this.barButtonItem33.Name = "barButtonItem33"; + this.barButtonItem33.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem34 + // + this.barButtonItem34.Caption = "建议反馈"; + this.barButtonItem34.Id = 1; + this.barButtonItem34.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem34.ImageOptions.Image"))); + this.barButtonItem34.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem34.ImageOptions.LargeImage"))); + this.barButtonItem34.Name = "barButtonItem34"; + this.barButtonItem34.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem34_ItemClick); + // + // barButtonItem35 + // + this.barButtonItem35.Caption = "barButtonItem35"; + this.barButtonItem35.Id = 2; + this.barButtonItem35.Name = "barButtonItem35"; + // + // barButtonItem36 + // + this.barButtonItem36.Caption = "barButtonItem36"; + this.barButtonItem36.Id = 3; + this.barButtonItem36.Name = "barButtonItem36"; + // + // barButtonItem37 + // + this.barButtonItem37.Caption = "升级专业版"; + this.barButtonItem37.Enabled = false; + this.barButtonItem37.Id = 4; + this.barButtonItem37.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.续费; + this.barButtonItem37.Name = "barButtonItem37"; + // + // barButtonItem38 + // + this.barButtonItem38.Caption = "使用帮助"; + this.barButtonItem38.Enabled = false; + this.barButtonItem38.Id = 5; + this.barButtonItem38.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.帮助__2_; + this.barButtonItem38.Name = "barButtonItem38"; + // + // barButtonItem39 + // + this.barButtonItem39.Caption = "检查更新"; + this.barButtonItem39.Id = 6; + this.barButtonItem39.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem39.ImageOptions.Image"))); + this.barButtonItem39.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem39.ImageOptions.LargeImage"))); + this.barButtonItem39.ImageOptions.SvgImageSize = new System.Drawing.Size(45, 45); + this.barButtonItem39.Name = "barButtonItem39"; + this.barButtonItem39.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem1_ItemClick); + // + // barButtonItem40 + // + this.barButtonItem40.Caption = "应用目录"; + this.barButtonItem40.Id = 7; + this.barButtonItem40.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem40.ImageOptions.Image"))); + this.barButtonItem40.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem40.ImageOptions.LargeImage"))); + this.barButtonItem40.Name = "barButtonItem40"; + this.barButtonItem40.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem40_ItemClick); + // + // barButtonItem41 + // + this.barButtonItem41.Caption = "其他设置"; + this.barButtonItem41.Id = 8; + this.barButtonItem41.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem41.ImageOptions.Image"))); + this.barButtonItem41.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem41.ImageOptions.LargeImage"))); + this.barButtonItem41.Name = "barButtonItem41"; + this.barButtonItem41.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem42 + // + this.barButtonItem42.Caption = "同步服务器缓存"; + this.barButtonItem42.Id = 9; + this.barButtonItem42.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem42.ImageOptions.Image"))); + this.barButtonItem42.Name = "barButtonItem42"; + this.barButtonItem42.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem42_ItemClick); + // + // barButtonItem43 + // + this.barButtonItem43.Caption = "用户管理"; + this.barButtonItem43.Id = 10; + this.barButtonItem43.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem43.ImageOptions.Image"))); + this.barButtonItem43.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem43.ImageOptions.LargeImage"))); + this.barButtonItem43.Name = "barButtonItem43"; + this.barButtonItem43.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem44 + // + this.barButtonItem44.Caption = "黑名单列表"; + this.barButtonItem44.Id = 11; + this.barButtonItem44.ImageOptions.Image = global::FLSystem.Properties.Resources.黑名单__4_; + this.barButtonItem44.Name = "barButtonItem44"; + // + // barButtonItem45 + // + this.barButtonItem45.Caption = "黑名单列表"; + this.barButtonItem45.Id = 12; + this.barButtonItem45.ImageOptions.Image = global::FLSystem.Properties.Resources.黑名单__1_; + this.barButtonItem45.Name = "barButtonItem45"; + // + // barButtonItem46 + // + this.barButtonItem46.Caption = "白名单列表"; + this.barButtonItem46.Id = 13; + this.barButtonItem46.ImageOptions.Image = global::FLSystem.Properties.Resources.白名单__2_; + this.barButtonItem46.Name = "barButtonItem46"; + // + // barButtonItem47 + // + this.barButtonItem47.Caption = "阿里妈妈订单管理"; + this.barButtonItem47.Id = 14; + this.barButtonItem47.ImageOptions.Image = global::FLSystem.Properties.Resources.淘宝_20; + this.barButtonItem47.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.淘宝__2_; + this.barButtonItem47.Name = "barButtonItem47"; + this.barButtonItem47.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem48 + // + this.barButtonItem48.ActAsDropDown = true; + this.barButtonItem48.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.DropDown; + this.barButtonItem48.Caption = "订单管理"; + this.barButtonItem48.DropDownControl = this.menu_cps_order; + this.barButtonItem48.Id = 15; + this.barButtonItem48.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem48.ImageOptions.Image"))); + this.barButtonItem48.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem48.ImageOptions.LargeImage"))); + this.barButtonItem48.Name = "barButtonItem48"; + // + // menu_cps_order + // + this.menu_cps_order.ItemLinks.Add(this.barButtonItem33); + this.menu_cps_order.ItemLinks.Add(this.barButtonItem47); + this.menu_cps_order.ItemLinks.Add(this.barButtonItem95); + this.menu_cps_order.ItemLinks.Add(this.barButtonItem60); + this.menu_cps_order.ItemLinks.Add(this.barButtonItem98); + this.menu_cps_order.ItemLinks.Add(this.barButtonItem99); + this.menu_cps_order.ItemLinks.Add(this.barButtonItem105); + this.menu_cps_order.ItemLinks.Add(this.barButtonItem109); + this.menu_cps_order.Name = "menu_cps_order"; + this.menu_cps_order.Ribbon = this.ribbonControl1; + // + // barButtonItem95 + // + this.barButtonItem95.Caption = "阿里妈妈维权订单管理"; + this.barButtonItem95.Id = 123; + this.barButtonItem95.ImageOptions.Image = global::FLSystem.Properties.Resources.淘宝_20; + this.barButtonItem95.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.淘宝__2_; + this.barButtonItem95.Name = "barButtonItem95"; + this.barButtonItem95.VisibleInSearchMenu = false; + this.barButtonItem95.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem60 + // + this.barButtonItem60.Caption = "京东订单管理"; + this.barButtonItem60.Id = 40; + this.barButtonItem60.ImageOptions.Image = global::FLSystem.Properties.Resources.京东_20; + this.barButtonItem60.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.京东_20; + this.barButtonItem60.Name = "barButtonItem60"; + this.barButtonItem60.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem98 + // + this.barButtonItem98.Caption = "唯品会订单管理"; + this.barButtonItem98.Id = 127; + this.barButtonItem98.ImageOptions.Image = global::FLSystem.Properties.Resources.唯品会12; + this.barButtonItem98.Name = "barButtonItem98"; + this.barButtonItem98.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem99 + // + this.barButtonItem99.Caption = "抖音订单管理"; + this.barButtonItem99.Enabled = false; + this.barButtonItem99.Id = 128; + this.barButtonItem99.ImageOptions.Image = global::FLSystem.Properties.Resources.抖音; + this.barButtonItem99.Name = "barButtonItem99"; + this.barButtonItem99.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem105 + // + this.barButtonItem105.Caption = "苏宁易购订单管理"; + this.barButtonItem105.Id = 136; + this.barButtonItem105.ImageOptions.Image = global::FLSystem.Properties.Resources.苏宁小; + this.barButtonItem105.Name = "barButtonItem105"; + this.barButtonItem105.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem109 + // + this.barButtonItem109.Caption = "快手订单管理"; + this.barButtonItem109.DropDownEnabled = false; + this.barButtonItem109.Id = 139; + this.barButtonItem109.ImageOptions.Image = global::FLSystem.Properties.Resources.快手登录; + this.barButtonItem109.Name = "barButtonItem109"; + this.barButtonItem109.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem49 + // + this.barButtonItem49.Caption = "查询商品记录"; + this.barButtonItem49.Id = 16; + this.barButtonItem49.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem49.ImageOptions.Image"))); + this.barButtonItem49.Name = "barButtonItem49"; + this.barButtonItem49.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barEditItem2 + // + this.barEditItem2.Caption = "barEditItem2"; + this.barEditItem2.Edit = this.repositoryItemHypertextLabel2; + this.barEditItem2.Id = 17; + this.barEditItem2.Name = "barEditItem2"; + // + // repositoryItemHypertextLabel2 + // + this.repositoryItemHypertextLabel2.Name = "repositoryItemHypertextLabel2"; + // + // barStaticItem1 + // + this.barStaticItem1.Caption = "请 不 要 公 开 本 版 本 功 能 及 细节,此版本还处于内测阶段,目前名额有限,正式发布时,会奖励参与内测的成员!"; + this.barStaticItem1.Id = 18; + this.barStaticItem1.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.通知__1_; + this.barStaticItem1.Name = "barStaticItem1"; + // + // barButtonItem54 + // + this.barButtonItem54.Caption = "登录唯品会联盟"; + this.barButtonItem54.Id = 23; + this.barButtonItem54.Name = "barButtonItem54"; + // + // barStaticItem2 + // + this.barStaticItem2.Caption = "|"; + this.barStaticItem2.Id = 24; + this.barStaticItem2.Name = "barStaticItem2"; + // + // barStaticItem4 + // + this.barStaticItem4.Alignment = DevExpress.XtraBars.BarItemLinkAlignment.Right; + this.barStaticItem4.Caption = "barStaticItem4"; + this.barStaticItem4.Id = 26; + this.barStaticItem4.Name = "barStaticItem4"; + // + // barLinkContainerItem1 + // + this.barLinkContainerItem1.Alignment = DevExpress.XtraBars.BarItemLinkAlignment.Right; + this.barLinkContainerItem1.Caption = "barLinkContainerItem1"; + this.barLinkContainerItem1.Id = 27; + this.barLinkContainerItem1.Name = "barLinkContainerItem1"; + // + // barButtonItem55 + // + this.barButtonItem55.Alignment = DevExpress.XtraBars.BarItemLinkAlignment.Right; + this.barButtonItem55.Caption = "barButtonItem55"; + this.barButtonItem55.Id = 28; + this.barButtonItem55.Name = "barButtonItem55"; + // + // barStaticItem6 + // + this.barStaticItem6.Caption = "|"; + this.barStaticItem6.Id = 30; + this.barStaticItem6.Name = "barStaticItem6"; + // + // barStaticItem9 + // + this.barStaticItem9.Caption = "|"; + this.barStaticItem9.Id = 33; + this.barStaticItem9.Name = "barStaticItem9"; + // + // barStaticItem10 + // + this.barStaticItem10.Alignment = DevExpress.XtraBars.BarItemLinkAlignment.Right; + this.barStaticItem10.Caption = "1.0.0.1"; + this.barStaticItem10.Id = 34; + this.barStaticItem10.Name = "barStaticItem10"; + // + // barButtonItem56 + // + this.barButtonItem56.Caption = "保存配置"; + this.barButtonItem56.Id = 37; + this.barButtonItem56.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem56.ImageOptions.Image"))); + this.barButtonItem56.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem56.ImageOptions.LargeImage"))); + this.barButtonItem56.Name = "barButtonItem56"; + this.barButtonItem56.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem57 + // + this.barButtonItem57.Caption = "淘宝订单尾号"; + this.barButtonItem57.Id = 38; + this.barButtonItem57.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem57.ImageOptions.Image"))); + this.barButtonItem57.Name = "barButtonItem57"; + this.barButtonItem57.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem59 + // + this.barButtonItem59.Caption = "上传商户配置"; + this.barButtonItem59.Id = 39; + this.barButtonItem59.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem59.ImageOptions.Image"))); + this.barButtonItem59.Name = "barButtonItem59"; + this.barButtonItem59.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem59_ItemClick); + // + // barButtonItem61 + // + this.barButtonItem61.Caption = "barButtonItem61"; + this.barButtonItem61.Id = 84; + this.barButtonItem61.Name = "barButtonItem61"; + // + // barButtonItem62 + // + this.barButtonItem62.Caption = "申请可调试"; + this.barButtonItem62.Id = 85; + this.barButtonItem62.Name = "barButtonItem62"; + // + // barButtonItem63 + // + this.barButtonItem63.Caption = "强制结算订单"; + this.barButtonItem63.Id = 86; + this.barButtonItem63.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem63.ImageOptions.Image"))); + this.barButtonItem63.Name = "barButtonItem63"; + this.barButtonItem63.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem64 + // + this.barButtonItem64.Caption = "强制结算"; + this.barButtonItem64.Id = 87; + this.barButtonItem64.Name = "barButtonItem64"; + // + // barButtonItem65 + // + this.barButtonItem65.Caption = "重启软件"; + this.barButtonItem65.Id = 88; + this.barButtonItem65.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem65.ImageOptions.Image"))); + this.barButtonItem65.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem65.ImageOptions.LargeImage"))); + this.barButtonItem65.Name = "barButtonItem65"; + this.barButtonItem65.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem65_ItemClick); + // + // barButtonItem66 + // + this.barButtonItem66.Caption = "打开根目录"; + this.barButtonItem66.Id = 90; + this.barButtonItem66.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem66.ImageOptions.Image"))); + this.barButtonItem66.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem66.ImageOptions.LargeImage"))); + this.barButtonItem66.Name = "barButtonItem66"; + this.barButtonItem66.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem66_ItemClick); + // + // btn_data_manage + // + this.btn_data_manage.Caption = "数据报表"; + this.btn_data_manage.Id = 91; + this.btn_data_manage.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("btn_data_manage.ImageOptions.LargeImage"))); + this.btn_data_manage.Name = "btn_data_manage"; + this.btn_data_manage.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem67 + // + this.barButtonItem67.Caption = "群负责人"; + this.barButtonItem67.Id = 92; + this.barButtonItem67.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem67.ImageOptions.Image"))); + this.barButtonItem67.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem67.ImageOptions.LargeImage"))); + this.barButtonItem67.Name = "barButtonItem67"; + this.barButtonItem67.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barEditItem3 + // + this.barEditItem3.Caption = "barEditItem3"; + this.barEditItem3.Edit = this.repositoryItemHypertextLabel3; + this.barEditItem3.Id = 93; + this.barEditItem3.Name = "barEditItem3"; + // + // repositoryItemHypertextLabel3 + // + this.repositoryItemHypertextLabel3.Name = "repositoryItemHypertextLabel3"; + // + // barEditItem4 + // + this.barEditItem4.Edit = this.repositoryItemPictureEdit1; + this.barEditItem4.Id = 94; + this.barEditItem4.ImageOptions.Image = global::FLSystem.Properties.Resources.喇叭; + this.barEditItem4.Name = "barEditItem4"; + // + // repositoryItemPictureEdit1 + // + this.repositoryItemPictureEdit1.Name = "repositoryItemPictureEdit1"; + // + // ribbonGalleryBarItem1 + // + this.ribbonGalleryBarItem1.Caption = "ribbonGalleryBarItem1"; + this.ribbonGalleryBarItem1.Id = 95; + this.ribbonGalleryBarItem1.Name = "ribbonGalleryBarItem1"; + // + // barButtonItem68 + // + this.barButtonItem68.Id = 96; + this.barButtonItem68.ImageOptions.Image = global::FLSystem.Properties.Resources.喇叭__1_; + this.barButtonItem68.Name = "barButtonItem68"; + // + // barButtonItem69 + // + this.barButtonItem69.Caption = "barButtonItem69"; + this.barButtonItem69.Id = 97; + this.barButtonItem69.Name = "barButtonItem69"; + // + // barButtonItem70 + // + this.barButtonItem70.ActAsDropDown = true; + this.barButtonItem70.Alignment = DevExpress.XtraBars.BarItemLinkAlignment.Left; + this.barButtonItem70.AllowAllUp = true; + this.barButtonItem70.AllowDrawArrow = false; + this.barButtonItem70.AllowDrawArrowInMenu = false; + this.barButtonItem70.AllowRightClickInMenu = false; + this.barButtonItem70.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.DropDown; + this.barButtonItem70.Caption = "barButtonItem70"; + this.barButtonItem70.CausesValidation = true; + this.barButtonItem70.CloseRadialMenuOnItemClick = true; + this.barButtonItem70.CloseSubMenuOnClick = false; + this.barButtonItem70.Id = 98; + this.barButtonItem70.MergeType = DevExpress.XtraBars.BarMenuMerge.MergeItems; + this.barButtonItem70.Name = "barButtonItem70"; + this.barButtonItem70.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionInMenu; + this.barButtonItem70.RememberLastCommand = true; + this.barButtonItem70.RibbonStyle = DevExpress.XtraBars.Ribbon.RibbonItemStyles.SmallWithoutText; + this.barButtonItem70.ShortcutKeyDisplayString = "11111"; + this.barButtonItem70.SmallWithoutTextWidth = 100; + this.barButtonItem70.SmallWithTextWidth = 100; + // + // barButtonItem71 + // + this.barButtonItem71.Caption = "barButtonItem71"; + this.barButtonItem71.Id = 99; + this.barButtonItem71.Name = "barButtonItem71"; + // + // PublicNote + // + this.PublicNote.Id = 100; + this.PublicNote.ImageOptions.Image = global::FLSystem.Properties.Resources.喇叭__4_; + this.PublicNote.Name = "PublicNote"; + this.PublicNote.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph; + // + // barButtonItem72 + // + this.barButtonItem72.Caption = "Web通讯"; + this.barButtonItem72.Id = 101; + this.barButtonItem72.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem72.ImageOptions.Image"))); + this.barButtonItem72.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem72.ImageOptions.LargeImage"))); + this.barButtonItem72.Name = "barButtonItem72"; + this.barButtonItem72.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.CreateWebApiEvent); + // + // barButtonItem73 + // + this.barButtonItem73.Caption = "启动服务"; + this.barButtonItem73.Id = 102; + this.barButtonItem73.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem73.ImageOptions.Image"))); + this.barButtonItem73.Name = "barButtonItem73"; + // + // barButtonItem74 + // + this.barButtonItem74.Caption = "关闭服务"; + this.barButtonItem74.Id = 103; + this.barButtonItem74.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem74.ImageOptions.Image"))); + this.barButtonItem74.Name = "barButtonItem74"; + // + // barButtonItem75 + // + this.barButtonItem75.Caption = "测试接口"; + this.barButtonItem75.Id = 104; + this.barButtonItem75.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem75.ImageOptions.Image"))); + this.barButtonItem75.Name = "barButtonItem75"; + // + // barButtonItem76 + // + this.barButtonItem76.Caption = "提现管理"; + this.barButtonItem76.Id = 105; + this.barButtonItem76.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem76.ImageOptions.LargeImage"))); + this.barButtonItem76.Name = "barButtonItem76"; + this.barButtonItem76.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem77 + // + this.barButtonItem77.Caption = "更新摘要"; + this.barButtonItem77.Id = 106; + this.barButtonItem77.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem77.ImageOptions.Image"))); + this.barButtonItem77.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem77.ImageOptions.LargeImage"))); + this.barButtonItem77.Name = "barButtonItem77"; + this.barButtonItem77.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem77_ItemClick); + // + // barButtonItem78 + // + this.barButtonItem78.Caption = "软件目录"; + this.barButtonItem78.Id = 107; + this.barButtonItem78.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem78.ImageOptions.Image"))); + this.barButtonItem78.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem78.ImageOptions.LargeImage"))); + this.barButtonItem78.Name = "barButtonItem78"; + this.barButtonItem78.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem78_ItemClick); + // + // barButtonItem80 + // + this.barButtonItem80.Caption = "的"; + this.barButtonItem80.Id = 108; + this.barButtonItem80.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem80.ImageOptions.Image"))); + this.barButtonItem80.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem80.ImageOptions.LargeImage"))); + this.barButtonItem80.Name = "barButtonItem80"; + // + // barButtonItem81 + // + this.barButtonItem81.Caption = "手动转链"; + this.barButtonItem81.Id = 109; + this.barButtonItem81.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem81.ImageOptions.Image"))); + this.barButtonItem81.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem81.ImageOptions.LargeImage"))); + this.barButtonItem81.Name = "barButtonItem81"; + this.barButtonItem81.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem82 + // + this.barButtonItem82.Caption = "barButtonItem82"; + this.barButtonItem82.Id = 110; + this.barButtonItem82.Name = "barButtonItem82"; + // + // barButtonItem83 + // + this.barButtonItem83.Caption = "barButtonItem83"; + this.barButtonItem83.Id = 111; + this.barButtonItem83.Name = "barButtonItem83"; + // + // barButtonItem84 + // + this.barButtonItem84.Caption = "barButtonItem84"; + this.barButtonItem84.Id = 112; + this.barButtonItem84.Name = "barButtonItem84"; + // + // barButtonItem85 + // + this.barButtonItem85.Caption = "TCP接口"; + this.barButtonItem85.Id = 113; + this.barButtonItem85.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem85.ImageOptions.Image"))); + this.barButtonItem85.Name = "barButtonItem85"; + // + // barButtonItem86 + // + this.barButtonItem86.Caption = "Socket通讯"; + this.barButtonItem86.Id = 114; + this.barButtonItem86.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem86.ImageOptions.Image"))); + this.barButtonItem86.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem86.ImageOptions.LargeImage"))); + this.barButtonItem86.Name = "barButtonItem86"; + this.barButtonItem86.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem86_ItemClick); + // + // barButtonItem87 + // + this.barButtonItem87.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.DropDown; + this.barButtonItem87.Caption = "刷新缓存"; + this.barButtonItem87.Id = 115; + this.barButtonItem87.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem87.ImageOptions.Image"))); + this.barButtonItem87.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem87.ImageOptions.LargeImage"))); + this.barButtonItem87.Name = "barButtonItem87"; + // + // barButtonItem88 + // + this.barButtonItem88.Caption = "barButtonItem88"; + this.barButtonItem88.Id = 116; + this.barButtonItem88.Name = "barButtonItem88"; + // + // barButtonItem89 + // + this.barButtonItem89.Caption = "授权管理"; + this.barButtonItem89.Id = 117; + this.barButtonItem89.Name = "barButtonItem89"; + // + // barButtonItem90 + // + this.barButtonItem90.Id = 118; + this.barButtonItem90.Name = "barButtonItem90"; + this.barButtonItem90.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem90_ItemClick); + // + // barButtonItem91 + // + this.barButtonItem91.Caption = "授权管理"; + this.barButtonItem91.Id = 119; + this.barButtonItem91.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem91.ImageOptions.Image"))); + this.barButtonItem91.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem91.ImageOptions.LargeImage"))); + this.barButtonItem91.Name = "barButtonItem91"; + this.barButtonItem91.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem91_ItemClick); + // + // barButtonItem92 + // + this.barButtonItem92.Caption = "barButtonItem92"; + this.barButtonItem92.Id = 120; + this.barButtonItem92.Name = "barButtonItem92"; + this.barButtonItem92.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem92_ItemClick); + // + // barButtonItem93 + // + this.barButtonItem93.Id = 121; + this.barButtonItem93.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem93.ImageOptions.Image"))); + this.barButtonItem93.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem93.ImageOptions.LargeImage"))); + this.barButtonItem93.Name = "barButtonItem93"; + this.barButtonItem93.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem93_ItemClick); + // + // barButtonItem96 + // + this.barButtonItem96.Caption = "群通知机器人"; + this.barButtonItem96.Id = 124; + this.barButtonItem96.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem96.ImageOptions.Image"))); + this.barButtonItem96.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem96.ImageOptions.LargeImage"))); + this.barButtonItem96.Name = "barButtonItem96"; + this.barButtonItem96.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem94 + // + this.barButtonItem94.Caption = "barButtonItem94"; + this.barButtonItem94.Id = 125; + this.barButtonItem94.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem94.ImageOptions.Image"))); + this.barButtonItem94.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem94.ImageOptions.LargeImage"))); + this.barButtonItem94.Name = "barButtonItem94"; + // + // barButtonItem101 + // + this.barButtonItem101.Caption = "抖音管理"; + this.barButtonItem101.Id = 130; + this.barButtonItem101.Name = "barButtonItem101"; + // + // barButtonItem102 + // + this.barButtonItem102.Caption = "barButtonItem102"; + this.barButtonItem102.Id = 131; + this.barButtonItem102.Name = "barButtonItem102"; + // + // barButtonItem_douyin + // + this.barButtonItem_douyin.Caption = "抖音活跃列表"; + this.barButtonItem_douyin.Enabled = false; + this.barButtonItem_douyin.Id = 132; + this.barButtonItem_douyin.ImageOptions.Image = global::FLSystem.Properties.Resources.抖音; + this.barButtonItem_douyin.Name = "barButtonItem_douyin"; + this.barButtonItem_douyin.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // barButtonItem103 + // + this.barButtonItem103.Caption = "更新易转发"; + this.barButtonItem103.Id = 133; + this.barButtonItem103.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem103.ImageOptions.Image"))); + this.barButtonItem103.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem103.ImageOptions.LargeImage"))); + this.barButtonItem103.Name = "barButtonItem103"; + this.barButtonItem103.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem103_ItemClick); + // + // btn_home_manage + // + this.btn_home_manage.Caption = "首页公告"; + this.btn_home_manage.Id = 135; + this.btn_home_manage.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("btn_home_manage.ImageOptions.Image"))); + this.btn_home_manage.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("btn_home_manage.ImageOptions.LargeImage"))); + this.btn_home_manage.Name = "btn_home_manage"; + this.btn_home_manage.Visibility = DevExpress.XtraBars.BarItemVisibility.Never; + this.btn_home_manage.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.ItemClick); + // + // ribbonPageCategory2 + // + this.ribbonPageCategory2.Name = "ribbonPageCategory2"; + this.ribbonPageCategory2.Text = "ribbonPageCategory2"; + // + // ribbonPage1 + // + this.ribbonPage1.Groups.AddRange(new DevExpress.XtraBars.Ribbon.RibbonPageGroup[] { + this.ribbonPageGroup1, + this.ribbonPageGroup2, + this.ribbonPageGroup7, + this.ribbonPageGroup10}); + this.ribbonPage1.Name = "ribbonPage1"; + this.ribbonPage1.Text = "控制中心"; + // + // ribbonPageGroup1 + // + this.ribbonPageGroup1.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup1.ItemLinks.Add(this.btn_home_manage); + this.ribbonPageGroup1.ItemLinks.Add(this.barButtonItem9); + this.ribbonPageGroup1.ItemLinks.Add(this.barButtonItem93); + this.ribbonPageGroup1.Name = "ribbonPageGroup1"; + this.ribbonPageGroup1.Text = "机器人开关"; + // + // ribbonPageGroup2 + // + this.ribbonPageGroup2.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup2.ItemLinks.Add(this.btn_cps_manage); + this.ribbonPageGroup2.ItemLinks.Add(this.barButtonItem20); + this.ribbonPageGroup2.Name = "ribbonPageGroup2"; + this.ribbonPageGroup2.Text = "联盟平台"; + // + // ribbonPageGroup7 + // + this.ribbonPageGroup7.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup7.ItemLinks.Add(this.barButtonItem91); + this.ribbonPageGroup7.ItemLinks.Add(this.btn_robot_manage); + this.ribbonPageGroup7.ItemLinks.Add(this.barButtonItem19); + this.ribbonPageGroup7.Name = "ribbonPageGroup7"; + this.ribbonPageGroup7.Text = "机器人授权"; + // + // ribbonPageGroup10 + // + this.ribbonPageGroup10.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup10.ItemLinks.Add(this.btn_data_manage); + this.ribbonPageGroup10.ItemLinks.Add(this.btn_log_manage); + this.ribbonPageGroup10.Name = "ribbonPageGroup10"; + this.ribbonPageGroup10.Text = "日志监控"; + // + // ribbonPage2 + // + this.ribbonPage2.Groups.AddRange(new DevExpress.XtraBars.Ribbon.RibbonPageGroup[] { + this.ribbonPageGroup9, + this.ribbonPageGroup12, + this.ribbonPageGroup14}); + this.ribbonPage2.Name = "ribbonPage2"; + this.ribbonPage2.Text = "系统管理"; + // + // ribbonPageGroup9 + // + this.ribbonPageGroup9.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup9.ItemLinks.Add(this.barButtonItem13); + this.ribbonPageGroup9.ItemLinks.Add(this.barButtonItem41); + this.ribbonPageGroup9.ItemLinks.Add(this.barButtonItem56); + this.ribbonPageGroup9.Name = "ribbonPageGroup9"; + this.ribbonPageGroup9.Text = "系统设置"; + // + // ribbonPageGroup12 + // + this.ribbonPageGroup12.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup12.ItemLinks.Add(this.barButtonItem48); + this.ribbonPageGroup12.ItemLinks.Add(this.barButtonItem76); + this.ribbonPageGroup12.ItemLinks.Add(this.barButtonItem43); + this.ribbonPageGroup12.ItemLinks.Add(this.barButtonItem67); + this.ribbonPageGroup12.ItemLinks.Add(this.barButtonItem96); + this.ribbonPageGroup12.Name = "ribbonPageGroup12"; + this.ribbonPageGroup12.Text = "数据管理"; + // + // ribbonPageGroup14 + // + this.ribbonPageGroup14.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup14.ItemLinks.Add(this.barButtonItem16); + this.ribbonPageGroup14.ItemLinks.Add(this.barButtonItem42); + this.ribbonPageGroup14.ItemLinks.Add(this.barButtonItem59); + this.ribbonPageGroup14.ItemLinks.Add(this.barButtonItem49); + this.ribbonPageGroup14.ItemLinks.Add(this.barButtonItem57); + this.ribbonPageGroup14.ItemLinks.Add(this.barButtonItem63); + this.ribbonPageGroup14.ItemLinks.Add(this.skin_manager); + this.ribbonPageGroup14.Name = "ribbonPageGroup14"; + this.ribbonPageGroup14.Text = "其他操作"; + // + // ribbonPage3 + // + this.ribbonPage3.Groups.AddRange(new DevExpress.XtraBars.Ribbon.RibbonPageGroup[] { + this.ribbonPageGroup3, + this.ribbonPageGroup4, + this.ribbonPageGroup13, + this.ribbonPageGroup11}); + this.ribbonPage3.Name = "ribbonPage3"; + this.ribbonPage3.Text = "应用中心"; + // + // ribbonPageGroup3 + // + this.ribbonPageGroup3.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup3.ItemLinks.Add(this.barButtonItem6); + this.ribbonPageGroup3.ItemLinks.Add(this.barButtonItem29); + this.ribbonPageGroup3.ItemLinks.Add(this.barButtonItem31); + this.ribbonPageGroup3.ItemLinks.Add(this.barButtonItem30); + this.ribbonPageGroup3.Name = "ribbonPageGroup3"; + this.ribbonPageGroup3.Text = "应用中心"; + // + // ribbonPageGroup4 + // + this.ribbonPageGroup4.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup4.ItemLinks.Add(this.barButtonItem27); + this.ribbonPageGroup4.ItemLinks.Add(this.barButtonItem11); + this.ribbonPageGroup4.ItemLinks.Add(this.barButtonItem40); + this.ribbonPageGroup4.Name = "ribbonPageGroup4"; + this.ribbonPageGroup4.Text = "开发者调试区"; + // + // ribbonPageGroup13 + // + this.ribbonPageGroup13.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup13.ItemLinks.Add(this.barButtonItem81); + this.ribbonPageGroup13.Name = "ribbonPageGroup13"; + this.ribbonPageGroup13.Text = "实用工具"; + // + // ribbonPageGroup11 + // + this.ribbonPageGroup11.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup11.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("ribbonPageGroup11.ImageOptions.Image"))); + this.ribbonPageGroup11.ItemLinks.Add(this.barButtonItem72); + this.ribbonPageGroup11.ItemLinks.Add(this.barButtonItem86); + this.ribbonPageGroup11.ItemLinks.Add(this.barButtonItem103); + this.ribbonPageGroup11.Name = "ribbonPageGroup11"; + this.ribbonPageGroup11.Text = "服务器API配置"; + // + // ribbonPage4 + // + this.ribbonPage4.Groups.AddRange(new DevExpress.XtraBars.Ribbon.RibbonPageGroup[] { + this.ribbonPageGroup5}); + this.ribbonPage4.Name = "ribbonPage4"; + this.ribbonPage4.Text = "关于"; + // + // ribbonPageGroup5 + // + this.ribbonPageGroup5.AllowTextClipping = false; + this.ribbonPageGroup5.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup5.ItemLinks.Add(this.barButtonItem39); + this.ribbonPageGroup5.ItemLinks.Add(this.barButtonItem77); + this.ribbonPageGroup5.ItemLinks.Add(this.barButtonItem78); + this.ribbonPageGroup5.ItemLinks.Add(this.barButtonItem34); + this.ribbonPageGroup5.ItemLinks.Add(this.barButtonItem65); + this.ribbonPageGroup5.Name = "ribbonPageGroup5"; + this.ribbonPageGroup5.Text = "系统相关"; + // + // repositoryItemImageEdit1 + // + this.repositoryItemImageEdit1.AutoHeight = false; + this.repositoryItemImageEdit1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemImageEdit1.Name = "repositoryItemImageEdit1"; + // + // repositoryItemImageEdit2 + // + this.repositoryItemImageEdit2.AutoHeight = false; + this.repositoryItemImageEdit2.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemImageEdit2.Name = "repositoryItemImageEdit2"; + // + // ribbonPage5 + // + this.ribbonPage5.Name = "ribbonPage5"; + this.ribbonPage5.Text = "ribbonPage5"; + // + // ribbonPageGroup8 + // + this.ribbonPageGroup8.Name = "ribbonPageGroup8"; + this.ribbonPageGroup8.Text = "ribbonPageGroup8"; + // + // ribbonPageCategory1 + // + this.ribbonPageCategory1.Name = "ribbonPageCategory1"; + this.ribbonPageCategory1.Text = "Version:2018.01.1.3"; + // + // barCheckItem3 + // + this.barCheckItem3.Caption = "保存日志"; + this.barCheckItem3.CheckBoxVisibility = DevExpress.XtraBars.CheckBoxVisibility.BeforeText; + this.barCheckItem3.Id = 39; + this.barCheckItem3.Name = "barCheckItem3"; + this.barCheckItem3.RibbonStyle = ((DevExpress.XtraBars.Ribbon.RibbonItemStyles)(((DevExpress.XtraBars.Ribbon.RibbonItemStyles.Large | DevExpress.XtraBars.Ribbon.RibbonItemStyles.SmallWithText) + | DevExpress.XtraBars.Ribbon.RibbonItemStyles.SmallWithoutText))); + // + // barCheckItem4 + // + this.barCheckItem4.Caption = "保存日志"; + this.barCheckItem4.CheckBoxVisibility = DevExpress.XtraBars.CheckBoxVisibility.BeforeText; + this.barCheckItem4.Id = 39; + this.barCheckItem4.Name = "barCheckItem4"; + this.barCheckItem4.RibbonStyle = ((DevExpress.XtraBars.Ribbon.RibbonItemStyles)(((DevExpress.XtraBars.Ribbon.RibbonItemStyles.Large | DevExpress.XtraBars.Ribbon.RibbonItemStyles.SmallWithText) + | DevExpress.XtraBars.Ribbon.RibbonItemStyles.SmallWithoutText))); + // + // xtraTabControl1 + // + this.xtraTabControl1.ClosePageButtonShowMode = DevExpress.XtraTab.ClosePageButtonShowMode.InActiveTabPageHeader; + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 150); + this.xtraTabControl1.MultiLine = DevExpress.Utils.DefaultBoolean.False; + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.ShowHeaderFocus = DevExpress.Utils.DefaultBoolean.False; + this.xtraTabControl1.Size = new System.Drawing.Size(935, 519); + this.xtraTabControl1.TabIndex = 2; + this.xtraTabControl1.SelectedPageChanged += new DevExpress.XtraTab.TabPageChangedEventHandler(this.xtraTabControl1_SelectedPageChanged); + this.xtraTabControl1.CloseButtonClick += new System.EventHandler(this.xtraTabControl1_CloseButtonClick); + // + // notify_pallet + // + this.notify_pallet.Text = "notifyIcon1"; + this.notify_pallet.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.notify_pallet_MouseDoubleClick); + // + // menu_tray + // + this.menu_tray.ItemLinks.Add(this.barButtonItem1); + this.menu_tray.ItemLinks.Add(this.barButtonItem2); + this.menu_tray.ItemLinks.Add(this.barButtonItem3); + this.menu_tray.ItemLinks.Add(this.barButtonItem5); + this.menu_tray.ItemLinks.Add(this.barButtonItem4); + this.menu_tray.Name = "menu_tray"; + this.menu_tray.Ribbon = this.ribbonControl1; + // + // barButtonItem32 + // + this.barButtonItem32.ActAsDropDown = true; + this.barButtonItem32.ButtonStyle = DevExpress.XtraBars.BarButtonStyle.DropDown; + this.barButtonItem32.Caption = "订单管理"; + this.barButtonItem32.DropDownControl = this.menu_cps_order; + this.barButtonItem32.Id = 89; + this.barButtonItem32.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem32.ImageOptions.Image"))); + this.barButtonItem32.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.订单__3_; + this.barButtonItem32.Name = "barButtonItem32"; + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 1800000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // barButtonItem58 + // + this.barButtonItem58.Caption = "测试邮件通信"; + this.barButtonItem58.Id = 79; + this.barButtonItem58.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem58.ImageOptions.Image"))); + this.barButtonItem58.Name = "barButtonItem58"; + // + // menu_coerce_order + // + this.menu_coerce_order.ItemLinks.Add(this.barButtonItem64); + this.menu_coerce_order.Name = "menu_coerce_order"; + this.menu_coerce_order.Ribbon = this.ribbonControl1; + // + // barButtonItem79 + // + this.barButtonItem79.Caption = "测试邮件通信"; + this.barButtonItem79.Id = 79; + this.barButtonItem79.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem79.ImageOptions.Image"))); + this.barButtonItem79.Name = "barButtonItem79"; + // + // ribbonPageGroup6 + // + this.ribbonPageGroup6.CaptionButtonVisible = DevExpress.Utils.DefaultBoolean.False; + this.ribbonPageGroup6.Name = "ribbonPageGroup6"; + this.ribbonPageGroup6.Text = "主题皮肤"; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(807, 63); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 5; + this.button1.Text = "button1"; + this.button1.UseVisualStyleBackColor = false; + this.button1.Visible = false; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // autologin_timer + // + this.autologin_timer.Enabled = true; + this.autologin_timer.Interval = 600000; + this.autologin_timer.Tick += new System.EventHandler(this.autologin_timer_Tick); + // + // barButtonItem104 + // + this.barButtonItem104.Caption = "首页公告"; + this.barButtonItem104.Id = 134; + this.barButtonItem104.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem104.ImageOptions.Image"))); + this.barButtonItem104.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem104.ImageOptions.LargeImage"))); + this.barButtonItem104.Name = "barButtonItem104"; + // + // barButtonItem106 + // + this.barButtonItem106.Caption = "首页公告"; + this.barButtonItem106.Id = 134; + this.barButtonItem106.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem106.ImageOptions.Image"))); + this.barButtonItem106.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem106.ImageOptions.LargeImage"))); + this.barButtonItem106.Name = "barButtonItem106"; + // + // main + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(935, 691); + this.Controls.Add(this.button1); + this.Controls.Add(this.xtraTabControl1); + this.Controls.Add(this.ribbonStatusBar1); + this.Controls.Add(this.ribbonControl1); + this.KeyPreview = true; + this.MinimumSize = new System.Drawing.Size(937, 723); + this.Name = "main"; + this.Text = "main"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.main_FormClosing); + this.Load += new System.EventHandler(this.main_Load); + this.SizeChanged += new System.EventHandler(this.main_SizeChanged); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.main_KeyDown); + ((System.ComponentModel.ISupportInitialize)(this.ribbonControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_login_chat)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_login_cps)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemHypertextLabel1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_cps_order)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemHypertextLabel2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemHypertextLabel3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemImageEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemImageEdit2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_tray)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.menu_coerce_order)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private DevExpress.XtraBars.Ribbon.RibbonStatusBar ribbonStatusBar1; + private DevExpress.XtraBars.Ribbon.RibbonControl ribbonControl1; + private DevExpress.XtraBars.BarHeaderItem barHeaderItem1; + private DevExpress.XtraEditors.Repository.RepositoryItemImageEdit repositoryItemImageEdit1; + private DevExpress.XtraEditors.Repository.RepositoryItemImageEdit repositoryItemImageEdit2; + private DevExpress.XtraBars.BarButtonItem barButtonItem9; + private DevExpress.XtraBars.BarButtonItem barButtonItem10; + + private DevExpress.XtraBars.BarButtonItem btn_cps_manage; + private DevExpress.XtraBars.Ribbon.RibbonPage ribbonPage1; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup1; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup2; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup7; + private DevExpress.XtraBars.Ribbon.RibbonPage ribbonPage2; + private DevExpress.XtraBars.Ribbon.RibbonPage ribbonPage3; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup3; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup4; + private DevExpress.XtraBars.Ribbon.RibbonPage ribbonPage4; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup5; + private DevExpress.XtraBars.Ribbon.RibbonPage ribbonPage5; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup8; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup9; + private DevExpress.XtraBars.Ribbon.RibbonPageCategory ribbonPageCategory1; + private DevExpress.XtraBars.BarButtonItem btn_robot_manage; + private DevExpress.XtraBars.BarButtonItem barButtonItem19; + private DevExpress.XtraBars.BarButtonItem barButtonItem20; + private DevExpress.XtraBars.BarButtonItem btn_log_manage; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup10; + private DevExpress.XtraBars.BarCheckItem barCheckItem3; + private DevExpress.XtraBars.BarCheckItem barCheckItem4; + private DevExpress.XtraBars.BarButtonItem barButtonItem22; + private DevExpress.XtraBars.BarButtonItem barButtonItem23; + private DevExpress.XtraBars.BarButtonItem barButtonItem24; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraBars.BarHeaderItem barHeaderItem4; + private System.Windows.Forms.NotifyIcon notify_pallet; + private DevExpress.XtraBars.BarButtonItem barButtonItem28; + private DevExpress.XtraBars.BarSubItem barSubItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem2; + private DevExpress.XtraBars.BarButtonItem barButtonItem3; + private DevExpress.XtraBars.BarButtonItem barButtonItem4; + private DevExpress.XtraBars.BarButtonItem barButtonItem5; + private DevExpress.XtraBars.BarEditItem barEditItem1; + private DevExpress.XtraEditors.Repository.RepositoryItemHypertextLabel repositoryItemHypertextLabel1; + private DevExpress.XtraBars.PopupMenu menu_tray; + private DevExpress.XtraBars.BarButtonItem barButtonItem6; + private DevExpress.XtraBars.BarButtonItem barButtonItem7; + private DevExpress.XtraBars.BarButtonItem barButtonItem8; + private DevExpress.XtraBars.BarButtonItem barButtonItem11; + private DevExpress.XtraBars.BarButtonItem barButtonItem12; + private DevExpress.XtraBars.BarButtonItem barButtonItem13; + private DevExpress.XtraBars.BarButtonItem barButtonItem14; + private DevExpress.XtraBars.BarButtonItem barButtonItem15; + private DevExpress.XtraBars.SkinRibbonGalleryBarItem skinRibbonGalleryBarItem1; + private DevExpress.XtraBars.SkinPaletteRibbonGalleryBarItem skinPaletteRibbonGalleryBarItem1; + private DevExpress.XtraBars.SkinDropDownButtonItem skin_manager; + private DevExpress.XtraBars.BarButtonItem barButtonItem16; + private DevExpress.XtraBars.BarButtonItem barButtonItem17; + private DevExpress.XtraBars.PopupMenu menu_login_cps; + private DevExpress.XtraBars.BarButtonItem barButtonItem21; + private DevExpress.XtraBars.BarButtonItem barButtonItem25; + private DevExpress.XtraBars.BarButtonItem barButtonItem26; + private DevExpress.XtraBars.BarButtonItem barButtonItem18; + private DevExpress.XtraBars.BarButtonItem barButtonItem27; + private DevExpress.XtraBars.BarButtonItem barButtonItem29; + private DevExpress.XtraBars.BarButtonItem barButtonItem30; + private DevExpress.XtraBars.BarButtonItem barButtonItem31; + private DevExpress.XtraBars.PopupMenu menu_cps_order; + private DevExpress.XtraBars.BarButtonItem barButtonItem33; + private DevExpress.XtraBars.BarButtonItem barButtonItem34; + private DevExpress.XtraBars.BarButtonItem barButtonItem35; + private DevExpress.XtraBars.BarButtonItem barButtonItem36; + private DevExpress.XtraBars.BarButtonItem barButtonItem37; + private DevExpress.XtraBars.BarButtonItem barButtonItem38; + private DevExpress.XtraBars.BarButtonItem barButtonItem39; + private DevExpress.XtraBars.BarButtonItem barButtonItem40; + private DevExpress.XtraBars.BarButtonItem barButtonItem41; + private DevExpress.XtraBars.BarButtonItem barButtonItem42; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup12; + private DevExpress.XtraBars.BarButtonItem barButtonItem43; + private DevExpress.XtraBars.BarButtonItem barButtonItem44; + private DevExpress.XtraBars.BarButtonItem barButtonItem45; + private DevExpress.XtraBars.BarButtonItem barButtonItem46; + private DevExpress.XtraBars.BarButtonItem barButtonItem47; + private DevExpress.XtraBars.BarButtonItem barButtonItem48; + private DevExpress.XtraBars.BarButtonItem barButtonItem32; + private DevExpress.XtraBars.BarButtonItem barButtonItem49; + private DevExpress.XtraBars.BarEditItem barEditItem2; + private DevExpress.XtraEditors.Repository.RepositoryItemHypertextLabel repositoryItemHypertextLabel2; + private DevExpress.XtraBars.BarStaticItem barStaticItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem50; + private DevExpress.XtraBars.BarButtonItem barButtonItem51; + private DevExpress.XtraBars.BarButtonItem barButtonItem52; + private DevExpress.XtraBars.PopupMenu menu_login_chat; + private DevExpress.XtraBars.BarButtonItem barButtonItem53; + private DevExpress.XtraBars.BarButtonItem barButtonItem54; + private DevExpress.XtraBars.BarStaticItem barStaticItem2; + private DevExpress.XtraBars.BarStaticItem barStaticItem3; + private DevExpress.XtraBars.BarStaticItem barStaticItem5; + private DevExpress.XtraBars.BarStaticItem barStaticItem6; + private DevExpress.XtraBars.BarStaticItem barStaticItem4; + private DevExpress.XtraBars.BarLinkContainerItem barLinkContainerItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem55; + private DevExpress.XtraBars.BarStaticItem barStaticItem7; + private DevExpress.XtraBars.BarStaticItem barStaticItem8; + private DevExpress.XtraBars.BarStaticItem barStaticItem9; + private DevExpress.XtraBars.BarStaticItem barStaticItem10; + //private DevExpress.XtraBars.BarStaticItem barStaticItem11; + private DevExpress.XtraBars.BarStaticItem barStaticItem12; + private System.Windows.Forms.Timer timer1; + private DevExpress.XtraBars.BarButtonItem barButtonItem56; + private DevExpress.XtraBars.BarButtonItem barButtonItem57; + private DevExpress.XtraBars.BarButtonItem barButtonItem59; + private DevExpress.XtraBars.BarButtonItem barButtonItem58; + private DevExpress.XtraBars.BarButtonItem barButtonItem61; + private DevExpress.XtraBars.BarButtonItem barButtonItem60; + private DevExpress.XtraBars.BarButtonItem barButtonItem62; + private DevExpress.XtraBars.BarButtonItem barButtonItem63; + private DevExpress.XtraBars.PopupMenu menu_coerce_order; + private DevExpress.XtraBars.BarButtonItem barButtonItem64; + private DevExpress.XtraBars.BarButtonItem barButtonItem65; + private DevExpress.XtraBars.BarButtonItem barButtonItem66; + private DevExpress.XtraBars.BarButtonItem btn_data_manage; + private DevExpress.XtraBars.BarButtonItem barButtonItem67; + private DevExpress.XtraBars.BarEditItem barEditItem3; + private DevExpress.XtraEditors.Repository.RepositoryItemHypertextLabel repositoryItemHypertextLabel3; + private DevExpress.XtraBars.BarEditItem barEditItem4; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit1; + private DevExpress.XtraBars.RibbonGalleryBarItem ribbonGalleryBarItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem68; + private DevExpress.XtraBars.BarButtonItem barButtonItem69; + public DevExpress.XtraBars.BarButtonItem barButtonItem70; + private DevExpress.XtraBars.BarButtonItem barButtonItem71; + private DevExpress.XtraBars.BarStaticItem PublicNote; + private DevExpress.XtraBars.BarButtonItem barButtonItem72; + private DevExpress.XtraBars.BarButtonItem barButtonItem73; + private DevExpress.XtraBars.BarButtonItem barButtonItem74; + private DevExpress.XtraBars.BarButtonItem barButtonItem75; + private DevExpress.XtraBars.BarButtonItem barButtonItem76; + private DevExpress.XtraBars.BarButtonItem barButtonItem77; + private DevExpress.XtraBars.BarButtonItem barButtonItem78; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup14; + private DevExpress.XtraBars.BarButtonItem barButtonItem79; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup6; + private DevExpress.XtraBars.BarButtonItem barButtonItem80; + private DevExpress.XtraBars.BarButtonItem barButtonItem81; + private DevExpress.XtraBars.BarButtonItem barButtonItem82; + private DevExpress.XtraBars.BarButtonItem barButtonItem83; + private DevExpress.XtraBars.BarButtonItem barButtonItem84; + private DevExpress.XtraBars.BarButtonItem barButtonItem85; + private DevExpress.XtraBars.BarButtonItem barButtonItem86; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup13; + private DevExpress.XtraBars.Ribbon.RibbonPageGroup ribbonPageGroup11; + private DevExpress.XtraBars.BarButtonItem barButtonItem87; + private DevExpress.XtraBars.BarButtonItem barButtonItem88; + private DevExpress.XtraBars.BarButtonItem barButtonItem89; + private DevExpress.XtraBars.BarButtonItem barButtonItem90; + private DevExpress.XtraBars.BarButtonItem barButtonItem91; + private DevExpress.XtraBars.BarButtonItem barButtonItem92; + private System.Windows.Forms.Button button1; + private DevExpress.XtraBars.BarButtonItem barButtonItem93; + private DevExpress.XtraBars.Ribbon.RibbonPageCategory ribbonPageCategory2; + private System.Windows.Forms.Timer autologin_timer; + private DevExpress.XtraBars.BarButtonItem barButtonItem95; + private DevExpress.XtraBars.BarButtonItem barButtonItem96; + private DevExpress.XtraBars.BarButtonItem barButtonItem94; + private DevExpress.XtraBars.BarButtonItem barButtonItem97; + private DevExpress.XtraBars.BarButtonItem barButtonItem98; + private DevExpress.XtraBars.BarButtonItem barButtonItem99; + private DevExpress.XtraBars.BarButtonItem barButtonItem100; + private DevExpress.XtraBars.BarButtonItem barButtonItem101; + private DevExpress.XtraBars.BarButtonItem barButtonItem102; + private DevExpress.XtraBars.BarButtonItem barButtonItem_douyin; + private DevExpress.XtraBars.BarButtonItem barButtonItem103; + private DevExpress.XtraBars.Alerter.AlertControl alertControl1; + private DevExpress.XtraBars.BarButtonItem barButtonItem104; + private DevExpress.XtraBars.BarButtonItem barButtonItem106; + private DevExpress.XtraBars.BarButtonItem barButtonItem107; + private DevExpress.XtraBars.BarButtonItem barButtonItem105; + private DevExpress.XtraBars.BarButtonItem btn_home_manage; + private DevExpress.XtraBars.BarButtonItem barButtonItem108; + private DevExpress.XtraBars.BarButtonItem barButtonItem109; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/main.cs b/FLSystem/Forms/main.cs new file mode 100644 index 0000000..9e8ea7a --- /dev/null +++ b/FLSystem/Forms/main.cs @@ -0,0 +1,2581 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using Chat.Framework; +using Chat.Framework.QQSdk; +using Chat.Framework.QQSdk.Events; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using DevExpress.XtraBars; +using DevExpress.XtraEditors; +using DevExpress.XtraTab; +using FLSystem.Events; +using FLSystem.Properties; +using FLSystem.Win32Api; +using GeneralFramework; +using Grant.Framework; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Pack; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Microsoft.Win32; +using UI.Framework.Controls; +using UI.Framework.Forms; +using UI.Framework.Tools; +using static Api.Framework.Tools.TBHelper; + +namespace FLSystem.Forms +{ + public partial class main : BaseForm + { + public main() + { + InitializeComponent(); + + #region 锁屏 + timeClear = new TimerClearEventHandler(Time_Clear);//如果操作了系统,则重新计时 + mouseKeyHook.KeyDown += new KeyEventHandler(mouseKeyHook_KeyDown); + mouseKeyHook.KeyUp += new KeyEventHandler(mouseKeyHook_KeyUp); + mouseKeyHook.KeyPress += new KeyPressEventHandler(mouseKeyHook_KeyPress); + mouseKeyHook.OnMouseActivity += new MouseEventHandler(mouseKeyHook_OnMouseActivity); + mouseKeyHook.Start(true, true); + #endregion + } + + #region 锁主程序 + + public delegate void TimerClearEventHandler(); + public delegate void ShowTimeEventHandler(); + + private MouseKeyHook mouseKeyHook = new MouseKeyHook(true, true); + public bool lockState = false; + private bool timerEnable = false; + private TimerClearEventHandler timeClear; + + private void Time_Clear() + { + if (timerEnable) + { + this.timer1.Stop(); + this.timer1.Start(); + } + } + + void mouseKeyHook_OnMouseActivity(object sender, MouseEventArgs e) { this.Invoke(this.timeClear); } + + void mouseKeyHook_KeyPress(object sender, KeyPressEventArgs e) { this.Invoke(this.timeClear); } + + void mouseKeyHook_KeyUp(object sender, KeyEventArgs e) { this.Invoke(this.timeClear); } + + void mouseKeyHook_KeyDown(object sender, KeyEventArgs e) { this.Invoke(this.timeClear); } + + #endregion + + + KeyboardHook kh; + + /// <summary> + /// 同步黑名单 + /// </summary> + private System.Timers.Timer timerBlackUser = null; + + public void main_Load(object sender, EventArgs e) + { + try + { + DevExpress.UserSkins.BonusSkins.Register(); + + DevExpress.Skins.SkinManager.EnableFormSkins(); + + DevExpress.Utils.WXPaint.WXPPainter.Default.ThemeChanged += Default_ThemeChanged; + + + GrantClient.Get().LodingAbout(1003, Program.ReadICO()); + if (!ApiClient.SelectDbbase()) Program.Exit(); + var skin = Util.AppConfig_GetValue("SkinName"); + //DevExpress.LookAndFeel.UserLookAndFeel.Default.SetSkinStyle(skin == "Basic" ? "The Bezier" : skin); + + if (!Util.AppConfig_ExistItem("ShowTgwz")) + Util.AppConfig_AddItem("ShowTgwz", "0"); + Util.AppConfig_ModifyItem("ShowTgwz", "1"); + + if (!Util.AppConfig_ExistItem("StartDy")) + Util.AppConfig_AddItem("StartDy", "0"); + Util.AppConfig_ModifyItem("StartDy", "1"); + + if (!Util.AppConfig_ExistItem("BlackUserTime")) + Util.AppConfig_AddItem("BlackUserTime", " "); + + #region 菜单导航栏 + if (!Util.AppConfig_ExistItem("Nav")) + Util.AppConfig_AddItem("Nav", ""); + var navConfig = Util.AppConfig_GetValue("Nav"); + if (!string.IsNullOrWhiteSpace(navConfig)) + { + try + { + var jsonData = PackTool.DecompressString(navConfig); + var treeList = JsonConvert.DeserializeObject<List<NavTree>>(jsonData); + var indexList = treeList.GroupBy(f => f.index).Select(f => f.Key).ToList(); + for (int i = 0; i < indexList.Count; i++) + { + var tree = treeList.FirstOrDefault(f => f.ceng == 1 && f.index == i); + if (tree != null) + { + if (i == 0) + { + if (!tree.check) + ribbonPage1.Visible = false; + else + SetShow(treeList, i); + } + else if (i == 1) + { + if (!tree.check) + ribbonPage2.Visible = false; + else + SetShow(treeList, i); + } + else if (i == 2) + { + if (!tree.check) + ribbonPage3.Visible = false; + else + SetShow(treeList, i); + } + else if (i == 3) + { + if (!tree.check) + ribbonPage4.Visible = false; + else + SetShow(treeList, i); + } + else if (i == 4) + { + var t2List = treeList.Where(f => f.ceng == 2 && f.index == i && f.check).Select(f => f.name).ToList(); + ApiClient.ShowPluginList = t2List; + } + } + } + } + catch (Exception) + { } + } + #endregion + + //if (!Util.AppConfig_ExistItem("WphNav")) + // Util.AppConfig_AddItem("WphNav", "0"); + + this.Text = GrantClient.Get().About["title"].ToString(); + + this.notify_pallet.Text = this.Text; + Loding.ShowWaitForm(); + var result = ApiClient.Initialization(); + //ChatMemberHandleEvent.FindChatObject += ChatMemberHandleEvent_FindChatObject; + //ChatMemberHandleEvent.UpdateChatFriends += ChatMemberHandleEvent_UpdateChatFriends; + //ChatMemberHandleEvent.UpdateChatGroupMembers += ChatMemberHandleEvent_UpdateChatGroupMembers; + if (!result) Program.Exit(); + + AlimamaApi.Init(); + + Loding.CloseWaitForm(); + + //btn_home_manage.Visibility = BarItemVisibility.Never; + + ItemClick(btn_home_manage, null);//显示首页 + + ItemClick(btn_log_manage, null);//显示日志 + + try + { + ApiClient.SocketInitialization(); + } + catch (Exception ex) + { + ShowErrorAutoClose(ex, 10000); + } + + //TODO 禁用抖音禁用 + var StartDy = Util.AppConfig_GetValue("StartDy"); + if (StartDy == "1") + { + barButtonItem_douyin.Enabled = barButtonItem99.Enabled = barButtonItem100.Enabled = true; + ItemClick(barButtonItem_douyin, null); + } + var session = ApiClient.GetSession(); + + Thread.Sleep(200); + + this.Icon = Program.ReadICO(); + this.notify_pallet.Icon = this.Icon; + EventClient.MethodEvent += EventClient_MethodEvent; + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + ReadNote(false); + barStaticItem12.Caption = "专业版V" + ApiClient.CurVersion; + this.xtraTabControl1.SelectedTabPageIndex = 0; + RefreshAccount(); + ChatClient.MessFrequentSleepTime = ApiClient.Setting.SystemConfig.mess_frequent_sleep_time; + + //ChatClient.QQPool.LoginChangeEvent += QQPool_LoginChangeEvent; + ChatClient.Events.WXRefreshUserEvent += Events_WXRefreshUserEvent; + ChatClient.Events.WXChangeStatusEvent += Events_WXChangeStatusEvent; + + ChatClient.QQEvents.QQRefreshUserEvent += Events_QQRefreshUserEvent; + ChatClient.QQEvents.LoginChangeEvent += QQEvents_LoginChangeEvent; + + EventClient.SharedEvent += EventClient_SharedEvent; + + UpdTime(); + + //new Utils(); + + EventClient.OnEvent(this, MethodType.刷新配置文件); + + #region 精简消息 + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(main)); + + this.barButtonItem9.ImageOptions.Image = (System.Drawing.Image)(resources.GetObject("barButtonItem10.ImageOptions.Image")); + this.barButtonItem9.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.停止__4_; + + this.barButtonItem9.Caption = "停止接收"; + + if (ApiClient.Setting.SystemConfig.message_warning_switch) + { + this.barButtonItem93.Caption = "关闭【双12】模式"; + this.barButtonItem93.ImageOptions.Image = (System.Drawing.Image)(resources.GetObject("barButtonItem93.ImageOptions.Image")); + this.barButtonItem93.ImageOptions.LargeImage = (System.Drawing.Image)(resources.GetObject("barButtonItem93.ImageOptions.LargeImage")); + } + else + { + this.barButtonItem93.Caption = "开启【双12】模式"; + this.barButtonItem93.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem94.ImageOptions.Image"))); + this.barButtonItem93.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem94.ImageOptions.LargeImage"))); + } + #endregion + + #region ipad协议出现remark为PCWechat Hook的情况,导致无法手动自动登陆(修改为空值) + var _robots = session.FindRobots().Where(f => f.type == ChatType.微信 && f.remark == "PCWechat HOOK" && f.token.StartsWith(@"{""data"":")); + foreach (var item in _robots) + { + item.remark = string.Empty; + session.SaveOrUpdate(item); + } + #endregion + + var WxRobots = session.FindRobots(true).Where(f => f.is_login && f.type == ChatType.微信 && f.remark != "PCWechat HOOK").ToList(); + + TaskTool tasks = new TaskTool(); + if (WxRobots.Count != 0) + { + if (BaseForm.ShowSuccessAutoClose(@"对不起,由于近期个别微信有出现封号! +为了您的账号安全,暂时不提供协议登陆! +请下载【易转发-微信官方客户端】登陆,保障您的账号安全! +------------- +下载地址已复制到剪切板,请粘贴到浏览器下载 +------------- +注意:如果您执意要通过协议登陆,请点击确定!!!", new DialogResult[] { DialogResult.OK, DialogResult.Cancel }, 0) == DialogResult.OK) + { + foreach (var item in WxRobots) + { + var _item = item; + tasks.AddTask(delegate () + { + try + { + EventClient.OnEvent(this, $"正在自动微信->{_item.nick}({item.name})..."); + var flag = ChatClient.LoginWeixin(_item.name, _item.token); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"登录微信->{_item.nick}({item.name})异常:{ex.Message}"); + } + }); + } + } + else + { + try + { + Clipboard.SetDataObject(Resources.易转发下载地址 + "?=" + new Random().Next(100, 2000)); + } + catch (Exception ex) + { } + } + } + + var QQRobots = session.FindRobots(true).Where(f => f.is_login && f.type == ChatType.QQ).ToList(); + if (QQRobots != null && QQRobots.Count != 0) + { + foreach (var item in QQRobots) + { + var QQRobot = item; + tasks.AddTask(delegate () + { + try + { + EventClient.OnEvent(this, $"正在自动QQ->{QQRobot.nick}({QQRobot.name})..."); + if (!string.IsNullOrWhiteSpace(QQRobot.token)) + { + var dic = HttpExtend.JsonToDictionary(Encoding.UTF8.GetString(HttpExtend.HexToByte(QQRobot.token))); + if (dic != null) + { + if (dic.ContainsKey("QQ")) + { + var QQ = dic["QQ"]?.ToString(); + if (!string.IsNullOrWhiteSpace(QQ) && dic.ContainsKey("Password")) + { + var Password = dic["Password"]?.ToString(); + var qq = uint.Parse(QQ); + if (ChatClient.QQClients.ContainsKey(QQ)) + { + var qBase = ChatClient.QQClients[QQ]; + qBase.Login(); + } + else + { + //QQ自动登录 + var IsEQQ = false; + if (!string.IsNullOrWhiteSpace(Password) && dic.ContainsKey("IsEQQ")) + IsEQQ = (dic["IsEQQ"].ToString().ToLower() == "true"); + var qqClient = ChatClient.LoginQQ(QQ, Password); + } + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"登录QQ->{QQRobot.nick}({QQRobot.name})异常:{ex.Message},{ex.StackTrace}"); + } + }); + + Thread.Sleep(500); + } + } + + tasks.Start(30, AsyncCallbackMethod); + + EventClient.OnEvent(this, MethodType.刷新机器人); + ChatClient.WXSdkConfig.IsDebug = false; + ChatClient.WXSdkConfig.MsgConvertToFriend = ApiClient.Setting.SystemConfig.msg_wx_convertswich == SwitchType.开启 ? true : false; + + isLodingOk = true; + + kh = new KeyboardHook(); + kh.SetHook(); + kh.OnKeyDownEvent += kh_OnKeyDownEvent; + + System.Timers.Timer timerLok = new System.Timers.Timer(); + timerLok.Elapsed += timer_lockForm_Tick; + timerLok.Interval = 5 * 60000;//测试1分钟锁屏 + timerLok.Start(); + + + #region 激活抖音xxx + //TODO 禁用抖音禁用 + //if (StartDy == "1") + //{ + // TaskTool tasks_douyin = new TaskTool(); + // var douyinMember = CpsClient.Members.Where(f => f.cpstype == CpsType.抖音联盟 /*&& f.is_download == SwitchType.开启*/).ToList(); + // if (douyinMember != null && douyinMember.Count != 0) + // { + //抖音单登版本EO + //if (douyinMember.Count > 1) + //{ + // for (int i = 1; i < douyinMember.Count; i++) + // { + // session.Delete(douyinMember[i]); + // CpsClient.Members.Remove(douyinMember[i]); + // } + //} + + //抖音多版本EO + //foreach (var item in douyinMember) + //{ + // var _item = item; + // try + // { + // _item.is_valid = true; + // _item.online = false; + // EventClient.OnEvent(this, $"激活抖音->{_item.usernick}({item.username})..."); + // var api = CpsClient.CreateDouyinRequest(_item); + // var form = new douyin_form_login1(); + // DouyinApi.douyinApiAction?.Invoke(api); + // form.Show(); + // //抖音隐藏 + // if (ApiClient.Setting.SystemConfig.hidedy && !string.IsNullOrWhiteSpace(api.Member.username)) + // form.Hide(); + // } + // catch (Exception ex) + // { + // EventClient.OnEvent(this, $"激活抖音->{_item.usernick}({item.username})异常:{ex.Message}"); + // } + // Thread.Sleep(500); + //} + // } + //} + #endregion + + var wphCount = CpsClient.Members.Count(f => f.cpstype == CpsType.唯品联盟); + + var robots = session.FindRobots(); + //if (wphCount == 0 && (WphNav == null || WphNav == "0")) + if (wphCount == 0 && robots != null && robots.Count != 0) + { + if (!Util.AppConfig_ExistItem("ShowWphAd")) + Util.AppConfig_AddItem("ShowWphAd", "1"); + var ShowWphAd = Util.AppConfig_GetValue("ShowWphAd"); + if (ShowWphAd == "1") + { + Thread th = new Thread(delegate () + { + Thread.Sleep(5000); + try + { + var Rst = MessageBox.Show("请尽快设置唯品会联盟,目前唯品会高消费年轻人群剧增,是否立即设置?", "询问", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (Rst != DialogResult.Yes) + { + Rst = MessageBox.Show("唯品会设置只需要1分钟,您确定要放弃吗?(≈1个亿)", "询问", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (Rst == DialogResult.Yes) + { + Util.AppConfig_ModifyItem("ShowWphAd", "0"); + return; + } + } + + Rst = MessageBox.Show("您是否已经有唯品会账号,点击Yes登录唯品会,点击No注册唯品会", "询问", MessageBoxButtons.YesNo); + if (Rst == DialogResult.No) + { + var form = new WphRegisterForm(); + form.ShowDialog(); + } + + //登录唯品会 + var cps_member = LoginCps(CpsType.唯品联盟); + if (cps_member == null) + //throw new Exception("唯品会cps对象为空,可能登录异常"); + return; + + //打开唯品会插件 + if (PluginClient.Plugins != null) + { + var plugin = PluginClient.Plugins.FirstOrDefault(f => f.Name == "唯品会返利"); + if (plugin != null) + { + PluginClient.UnInstall(plugin); + Thread.Sleep(200); + PluginClient.Install(plugin); + } + } + //创建推广位,判断是否有推广位,没有推广位创建一个推广位,有推广位,给没有设置推广位的机器人设置推广位 + #region 获取唯品会推广位 + var api = CpsClient.CreateWeipinhuiRequest(cps_member); + var pidResult = WeipinhuiApi.GetWphTgw(api); + + if (result != null) + { + //推广位为空,创建推广位 + if (pidResult.total == 0) + WeipinhuiApi.CreateWphTgw(api); + + pidResult = WeipinhuiApi.GetWphTgw(api); + + if (pidResult != null && pidResult.pidInfoList != null && pidResult.total != 0) + { + var tmp = pidResult.pidInfoList[0]; + if (tmp != null) + { + var tgw = new Tuiguangwei() + { + Member = cps_member, + Name = tmp.pidName, + Pid = tmp.pid + }; + + // 设置推广位 + var robotList = session.FindRobots(); + foreach (var robot in robotList) + { + setWphTgw((int)robot.id, tgw); + } + } + } + } + #endregion + } + catch (Exception ex) + { + EventClient.OnEvent("引导设置唯品会异常", $"{ex.Message} - {ex.StackTrace}"); + } + finally + { + ////监听刷新 + //PluginClient.LodingPlugin(); + } + + //1.搞个唯品会注册页 + //2.打开联盟登录页,自动登录后关闭窗口即可 + //3.自动启用唯品会插件,并设置好推广位 + + //var form = new WPHNavForm(); + //if (form.ShowDialog() == DialogResult.OK) + //{ + // //下次检测到唯品会未登录是否提示 + // Util.AppConfig_ModifyItem("WphNav", form.isIgnore ? "1" : "0"); + //} + }); + + th.ApartmentState = ApartmentState.STA; //属性设置成单线程 + th.IsBackground = true; + th.Start(); + } + } + else + { + if (!Util.AppConfig_ExistItem("ShowWphAd")) + Util.AppConfig_AddItem("ShowWphAd", "0"); + else + Util.AppConfig_ModifyItem("ShowWphAd", "0"); + } + + //#region MyRegion + //var ss = Util.Read<Dictionary<string, object>>("插件-积分管理-配置"); + //var ssss = Newtonsoft.Json.JsonConvert.SerializeObject(ss); + //var fff = ssss.Contains("ExchangeCommercialPayTip_MiniApp"); + + //#endregion + + System.Timers.Timer timer = new System.Timers.Timer(); + timer.Elapsed += Timer_Elapsed; + timer.Interval = 40 * 60 * 1000; + //timer.Interval = 1000; + timer.Start(); + + //下载黑名单 + timerBlackUser = new System.Timers.Timer(1000); + timerBlackUser.Elapsed += Timer_ElapsedBlackUser; + timer.Interval = 1000; + timerBlackUser.Start(); + } + catch (Exception ex) + { + try { Loding.CloseWaitForm(); } catch (Exception) { } + if (ex.Message.Contains("连接数据库过程中发生错误")) + ShowError(@"连接数据库过程中发生错误 +检查服务器是否正常连接字符串是否正确"); + else + ShowError(ex.Message + "\r\n" + ex.StackTrace); + Program.Exit(); + } + finally + { + ItemClick(barButtonItem6, null); + //监听刷新 + //PluginClient.LodingPlugin(); + this.WindowState = FormWindowState.Normal; + + + Task.Run(() => + { + Thread.Sleep(1000 * 60); + CheckSystemEventsHandlersForFreeze(); + }); + } + } + + + + private static void CheckSystemEventsHandlersForFreeze() + { + try + { + var handlers = typeof(SystemEvents).GetField("_handlers", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); + var handlersValues = handlers.GetType().GetProperty("Values").GetValue(handlers); + foreach (var invokeInfos in (handlersValues as IEnumerable).OfType<object>().ToArray()) + foreach (var invokeInfo in (invokeInfos as IEnumerable).OfType<object>().ToArray()) + { + try + { + var syncContext = invokeInfo.GetType().GetField("_syncContext", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(invokeInfo); + if (syncContext == null) throw new Exception("syncContext missing"); + if (!(syncContext is WindowsFormsSynchronizationContext)) continue; + var threadRef = (WeakReference)syncContext.GetType().GetField("destinationThreadRef", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(syncContext); + if (!threadRef.IsAlive) continue; + var thread = (Thread)threadRef.Target; + if (thread.ManagedThreadId == 1) continue; // Change here if you have more valid UI threads to ignore + var dlg = (Delegate)invokeInfo.GetType().GetField("_delegate", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(invokeInfo); + + SetLog($"SystemEvents handler '{dlg.Method.DeclaringType}.{dlg.Method.Name}' could freeze app due to wrong thread: " + + $"{thread.ManagedThreadId},{thread.IsThreadPoolThread},{thread.IsAlive},{thread.Name}"); + } + catch (Exception e) + { + SetLog(e.ToString() + "线程BB"); + } + } + } + catch (Exception e) + { + SetLog(e.ToString() + "线程AA"); + } + } + + private static void SetLog(string log) + { + var filename = HttpExtend.MapFile($"{DateTime.Now.ToString("yyyy-MM-dd HH")}.log", "Cache\\Ka"); + #region 原始写法 + //创建或打开日志文件,向日志文件末尾追加记录 + //StreamWriter mySw = File.AppendText(filename); + + //向日志文件写入内容 + //string writeContent = time + "|" + typeGrade + ":" + type + "|" + className + ":" + content; + //mySw.WriteLine(writeContent); + + //关闭日志文件 + //mySw.Close(); + #endregion + + //(优化写法)创建或打开日志文件,向日志文件末尾追加记录,关闭日志文件 + using (StreamWriter mySw = File.AppendText(filename)) + { + string writeContent = $@"{DateTime.Now.ToString("HH:mm:ss")} => {log} +"; + mySw.WriteLine(writeContent);//向日志文件写入内容 + mySw.Close(); //关闭日志文件 + } + } + + + private void Default_ThemeChanged(object sender, EventArgs e) + { + //EventClient.OnEvent("", $"{JsonConvert.SerializeObject(sender)} - {JsonConvert.SerializeObject(e)}"); + } + + private void EventClient_SharedEvent(object sender, SharedEvents e) + { + Task.Run(() => + { + try + { + //shared["msg_type"] = "抖音验证码"; + //shared["cps_type"] = CpsType.抖音联盟; + //shared["msg_username"] = api.Member.username; + + if (!e.Shareds.ContainsKey("msg_type") && e.Shareds["msg_type"]?.ToString() == "抖音验证码") + return; + + + + var cps = HttpExtend.ConvertEnum<CpsType>(e.Shareds["cps_type"].ToString()); + var username = e.Shareds["msg_username"].ToString(); + var usernick = e.Shareds["msg_usernick"].ToString(); + + ApiClient.SendNoticeMessage($@"【抖音重要通知】 + +账号:{usernick}({username}) +通知:请滑动验证码,否则部分订单无法同步!"); + + var verify = new douyin_verify(username); + verify.ShowDialog(); + } + catch (Exception ex) + { + EventClient.OnEvent("", $"异常:{ex.Message}"); + } + }); + } + + /// <summary> + /// 设置唯品会推广位 + /// </summary> + /// <param name="robotid"></param> + /// <param name="tgw"></param> + private void setWphTgw(int robotid, Tuiguangwei tgw) + { + try + { + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == robotid).ToList(); + //var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + //var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + for (int i = 0; i < pidNames.Length; i++) + { + #region 有出现两个重复无法修复的情况,删除一个 + var repetAdzone = adzones.Where(f => f.extend == pidNames[i]).ToList(); + if (repetAdzone.Count > 1) + { + for (int z = 1; z <= repetAdzone.Count - 1; z++) + { + session.Deleteable(repetAdzone[z]).ExecuteCommand(); + } + adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == robotid).ToList(); + } + #endregion + + var adzone = adzones.FirstOrDefault(f => f.extend == pidNames[i]); + if (adzone == null) + { + adzones = new List<fl_adzone_info>(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(tgw.Name, tgw.Pid, tgw.Member.username, robotid, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + } + } + #endregion + + session.FindAdzoneInfos(true); + session.FindWeipinhuiAutoBindPid(true);//刷新推广位 + + } + catch (Exception ex) + { } + } + /// <summary> + /// 创建fl_adzone_info对象 + /// </summary> + /// <param name="adzone_name"></param> + /// <param name="adzone_pid"></param> + /// <param name="adzone_pid_cps_name"></param> + /// <param name="rid"></param> + /// <param name="item"></param> + /// <returns></returns> + private fl_adzone_info CreateAdzoneInfo(string adzone_name, string adzone_pid, string adzone_pid_cps_name, int rid, string item, bool onoff = false) + { + return new fl_adzone_info() + { + custom_type = Resources.WPHSoftwareType, //自定义类型 + adzone_name = adzone_name, //推广位名称 + adzone_pid = adzone_pid, //推广位pid + adzone_pid_cps_name = adzone_pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.唯品联盟, //联盟id + robot_id = rid, //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = onoff, //不禁用 + extend = item + }; + } + + void timer_lockForm_Tick(object sender, EventArgs e) + { + if (ApiClient.Setting.SystemConfig.is_lock_main == SwitchType.开启) + { + if (!lockState) + { + lockState = true; + this.Hide(); + LockForm form = new LockForm(this.Size); + form.ShowDialog(); + this.Show(); + lockState = false; + } + } + } + + private void kh_OnKeyDownEvent(object sender, KeyEventArgs e) + { + if (e.KeyData == (Keys.S | Keys.Alt)) { this.Show(); }//Alt+S显示窗口 + if (e.KeyData == (Keys.H | Keys.Alt)) { this.Hide(); }//Alt+H隐藏窗口 + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons == null) return; + if (e.Commons.ContainsKey("cps_type") && e.Commons.ContainsKey("username")) + { + var cps = (CpsType)int.Parse(e.Commons["cps_type"].ToString()); + var username = e.Commons["username"].ToString(); + var buttonItem = new BarButtonItem(); + + switch (cps) + { + case CpsType.阿里妈妈: + buttonItem.Caption = "阿里妈妈订单管理"; + buttonItem.ImageOptions.Image = global::FLSystem.Properties.Resources.淘宝_20; + buttonItem.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.淘宝__2_; + break; + case CpsType.多多进宝: + buttonItem.Caption = "拼多多订单管理"; + buttonItem.ImageOptions.Image = global::FLSystem.Properties.Resources.拼多多_20; + buttonItem.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.拼多多__4_; + break; + case CpsType.京东联盟: + buttonItem.Caption = "京东订单管理"; + buttonItem.ImageOptions.Image = global::FLSystem.Properties.Resources.京东_20; + buttonItem.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.京东_20; + break; + case CpsType.唯品联盟: + buttonItem.Caption = "唯品会订单管理"; + buttonItem.ImageOptions.Image = global::FLSystem.Properties.Resources.唯品会12; + buttonItem.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.唯品会12; + break; + case CpsType.抖音联盟: + buttonItem.Caption = "抖音订单管理"; + buttonItem.ImageOptions.Image = global::FLSystem.Properties.Resources.抖音; + buttonItem.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.抖音; + break; + case CpsType.苏宁易购: + buttonItem.Caption = "苏宁易购订单管理"; + buttonItem.ImageOptions.Image = global::FLSystem.Properties.Resources.苏宁小; + buttonItem.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.苏宁小; + break; + case CpsType.快手联盟: + buttonItem.Caption = "快手订单管理"; + buttonItem.ImageOptions.Image = global::FLSystem.Properties.Resources.小快手; + buttonItem.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.小快手; + break; + default: + break; + } + buttonItem.Tag = new { username = username }; + ItemClick(buttonItem, null); + } + else if (e.Commons.ContainsKey("control_name") && e.Commons.ContainsKey("username")) + { + var control_name = e.Commons["control_name"].ToString(); + var username = e.Commons["username"].ToString(); + if (control_name == "查看用户信息") + { + var buttonItem = new BarButtonItem(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(main)); + buttonItem.Caption = "用户管理"; + buttonItem.ImageOptions.Image = ((Image)(resources.GetObject("barButtonItem43.ImageOptions.Image"))); + buttonItem.ImageOptions.LargeImage = ((Image)(resources.GetObject("barButtonItem43.ImageOptions.LargeImage"))); + buttonItem.Tag = new { username = username }; + ItemClick(buttonItem, null); + } + else if (control_name == "提现管理") + { + var buttonItem = new BarButtonItem(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(main)); + buttonItem.Caption = "提现管理"; + buttonItem.ImageOptions.Image = ((Image)(resources.GetObject("barButtonItem76.ImageOptions.Image"))); + buttonItem.ImageOptions.LargeImage = ((Image)(resources.GetObject("barButtonItem76.ImageOptions.LargeImage"))); + buttonItem.Tag = new { username = username, query_type = e.Commons["query_type"].ToString() }; + ItemClick(buttonItem, null); + } + } + else if (e.Commons.ContainsKey("type") && e.Commons.ContainsKey("trade_parent_id")) + { + var type = e.Commons["type"].ToString(); + if (type == "阿里妈妈维权订单") + { + var trade_parent_id = e.Commons["trade_parent_id"].ToString(); + var buttonItem = new BarButtonItem(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(main)); + buttonItem.Caption = "阿里妈妈维权订单管理"; + buttonItem.ImageOptions.Image = global::FLSystem.Properties.Resources.淘宝_20; + buttonItem.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.淘宝__2_; + buttonItem.Tag = new { username = trade_parent_id }; + ItemClick(buttonItem, null); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 刷新用户信息 + /// </summary> + /// <param name="client"></param> + private void Events_QQRefreshUserEvent(QQBase client) + { + try + { + lock (lock_obj) + { + var robot = client; + var session = ApiClient.GetSession(); + var user = session.FindRobotInfo(client.QQ.ToString(), ChatType.QQ, true); + if (user == null) + { + user = new fl_robot_info() + { + name = client.QQ.ToString(), + type = ChatType.QQ + }; + } + user.uin = client.QQ.ToString(); + user.is_login = client.IsLogin; + user.nick = client.Nickname; + var token = client.ToString(); + if (!string.IsNullOrWhiteSpace(token)) + user.token = token; + if (user.is_login) + { + var custm = Grant.Framework.GrantClient.Get().FindCostomer(client.QQ.ToString(), 1002); + if (custm != null) + user.end_time = custm.endTime; + else + { + if (string.IsNullOrWhiteSpace(user.end_time)) + user.end_time = DateTime.Now.AddMinutes(-1).ToString("yyyy/MM/dd HH:mm:ss"); + } + } + bool isinsert = user.id == 0 ? true : false; + session.SaveOrUpdate(user); + + if (isinsert) EventClient.OnEvent(this, MethodType.刷新机器人); + } + } + catch { } + } + private void Events_QQRefreshUserEvent(object sender, QQRefreshUser e) + { + if (e.QQBase != null && e.QQBase.QQ != 0) { Events_QQRefreshUserEvent(e.QQBase); } + } + + private void QQEvents_LoginChangeEvent(object sender, QQLoginChangeEvents e) + { + try + { + if (e.QQBase != null && e.QQBase.QQ != 0) + { + Events_QQRefreshUserEvent(e.QQBase); + + var client = e.QQBase; + //离线通知 + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.notice_robotname)) + { + if (!e.IsLogin) + { + var session = ApiClient.GetSession(); + var robot = session.FindRobotInfo(client.QQ.ToString(), ChatType.QQ, true); + if (robot == null) + robot = session.FindRobotInfo(client.QQ.ToString(), ChatType.QQ, true); + if (robot != null && robot.off_line_tip == SwitchType.开启) + { + string msg = $"离线通知\n————\nQQ账号:{client.QQ}\nQQ昵称:{client.Nickname}\n当前状态:{(e.IsLogin ? "在线" : "离线")}\n系统时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; + ApiClient.SendNoticeMessage(msg); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "机器人离线通知", msg, true); + } + } + } + } + } + catch { } + } + + private void Events_WXChangeStatusEvent(object sender, Chat.Framework.WXSdk.Events.WXChangeStatus e) + { + try + { + if (e.Client != null && e.Client.User != null && e.Client.User.Uin != 0) + { + Events_WXRefreshUserEvent(e.Client); + + var client = e.Client; + //离线通知 + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.notice_robotname)) + { + if (client.Status == WxStatus.已掉线 || client.Status == WxStatus.已退出) + { + var session = ApiClient.GetSession(); + var robot = session.FindRobotInfo(client.WeixinHao, ChatType.微信, true); + if (robot == null) + robot = session.FindRobotInfo(client.WeixinHao, ChatType.企业微信, true); + if (robot != null && robot.off_line_tip == SwitchType.开启) + { + string msg = $"离线通知\n————\n微信账号:{client.WeixinHao}\n微信昵称:{client.User.Nick}\n当前状态:{client.Status}\n系统时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; + ApiClient.SendNoticeMessage(msg); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "机器人离线通知", msg, true); + } + } + } + } + } + catch { } + } + + private bool isLodingOk = false; + + /// <summary> + /// 账号信息赋值 + /// </summary> + private void RefreshAccount() + { + var account = Grant.Framework.GrantClient.Get().accounts; + barButtonItem53.Caption = account.username; + barStaticItem5.Caption = Math.Round(account.point / 100.00, 2).ToString("0.00") + " 元"; + barStaticItem8.Caption = Math.Round(account.sumPoint / 100.00, 2).ToString("0.00") + " 元"; + } + private void AsyncCallbackMethod(IAsyncResult ar) + { + EventClient.OnEvent(this, $"自动登录线程已完成!"); + } + + private object lock_obj = new object(); + /// <summary> + /// 刷新用户信息 + /// </summary> + /// <param name="client"></param> + private void Events_WXRefreshUserEvent(Chat.Framework.WXSdk.Implement.WeixinBase client) + { + try + { + lock (lock_obj) + { + var robot = client; + var session = ApiClient.GetSession(); + var ctype = robot.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信; + var user = session.FindRobotInfo(robot.WeixinHao, ctype, true); + if (user == null) + { + user = new fl_robot_info() + { + name = client.WeixinHao, + type = ctype + }; + } + user.uin = client.User.Uin.ToString(); + user.is_login = client.Status == Chat.Framework.WXSdk.WxStatus.在线 ? true : false; + user.nick = client.User.Nick; + if (client.WeixinType == WeixinType.Grpc微信) + user.token = client.ToString(); + + if (user.is_login) + { + var custm = Grant.Framework.GrantClient.Get().FindCostomer(client.User.Uin.ToString(), 1001); + if (custm != null) + user.end_time = custm.endTime; + + var ipad = client as Chat.Framework.WXSdk.Implement.WXClientImpl_IPAD; + if (ipad != null) + { + var device = session.Queryable<fl_wechat_device>().Where(f => f.weixinhao == user.name).Single(); + if (device == null) device = new fl_wechat_device() { weixinhao = client.WeixinHao }; + device.device_info = ipad.DeviceId; + session.Saveable<fl_wechat_device>(device).ExecuteCommand(); + } + } + + bool isinsert = user.id == 0 ? true : false; + session.SaveOrUpdate(user); + + if (isinsert) EventClient.OnEvent(this, MethodType.刷新机器人); + } + } + catch { } + } + private void Events_WXRefreshUserEvent(object sender, Chat.Framework.WXSdk.Events.WXRefreshUser e) + { + if (e.Client != null && e.Client.User != null && e.Client.User.Uin != 0) { Events_WXRefreshUserEvent(e.Client); } + } + + private object MethodEventLock = new object(); + + /// <summary> + /// + /// </summary> + private void EventClient_MethodEvent(object sender, MethodType e) + { + this.Invoke(new Action(delegate + { + try + { + lock (MethodEventLock) + { + switch (e) + { + case MethodType.刷新应用: + var page = this.xtraTabControl1.TabPages.FirstOrDefault(f => f.Text == "应用功能"); + + if (page != null) + { + foreach (Control item in page.Controls) + { + item.Dispose(); + } + page.Controls.Clear(); + var list = PluginClient.Plugins.ToArray(); + foreach (Plugin item in list) + { + page.AddContral(new plugin_control(item)); + } + page.AutoScroll = true; + } + break; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + })); + } + + //销毁选项夹 + private void xtraTabControl1_CloseButtonClick(object sender, EventArgs e) + { + try + { + DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs EArg = (DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs)e; + string name = EArg.Page.Text;//得到关闭的选项卡的text + foreach (XtraTabPage page in xtraTabControl1.TabPages)//遍历得到和关闭的选项卡一样的Text + { + if (page.Text == name) + { + xtraTabControl1.TabPages.Remove(page); + + foreach (Control item in page.Controls) + { + item.Dispose(); + } + page.Dispose(); + return; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + //增加选项夹 + private void AddControlPage(string pageName, Control control, Image img = null) + { + try + { + //增加tabpage + XtraTabPage xpage = new XtraTabPage(); + xpage.Name = pageName; + xpage.Text = pageName; + if (img != null) + xpage.ImageOptions.Image = img; + //if (xpage.Text == "运行日志" || xpage.Text == "抖音活跃列表" || xpage.Text == "首页公告") + if (xpage.Text == "运行日志" || xpage.Text == "首页公告") + xpage.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + control.Dock = DockStyle.Fill; + xpage.Controls.Add(control);//添加要增加的控件 + xtraTabControl1.TabPages.Add(xpage); + xtraTabControl1.SelectedTabPage = xpage;//显示该页 + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "AddControlPage Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + //添加Control + private void ItemClick(object sender, ItemClickEventArgs e) + { + BarItem btn = sender as BarItem; + if (btn == null) btn = e.Item; + var cha = ApiClient.Cache; + + var username = string.Empty; + var query_type = string.Empty; + if (btn.Tag != null) + { + var usernameProperty = btn.Tag.GetType().GetProperty("username"); + if (usernameProperty != null) + username = usernameProperty.GetValue(btn.Tag).ToString(); + var query_typeProperty = btn.Tag.GetType().GetProperty("query_type"); + if (query_typeProperty != null) + query_type = query_typeProperty.GetValue(btn.Tag).ToString(); + } + + //判断是否已创建过 + foreach (XtraTabPage page in xtraTabControl1.TabPages) + { + if (page.Text == btn.Caption) + { + xtraTabControl1.SelectedTabPage = page;//显示该页 + return; + } + } + try + { + Loding.ShowWaitForm(); + } + catch (Exception) + { + ShowError("当前有正在加载的数据,请稍后重试!"); + return; + } + Image img = null; + try + { + img = PickBox.ResizeImage(btn.ImageOptions.LargeImage == null ? btn.ImageOptions.Image : btn.ImageOptions.LargeImage, new Size(22, 22)); + Control control = null; + switch (btn.Caption) + { + case "首页公告": + { + control = new home_control(); + break; + } + case "群通知机器人": + { + control = new notice_robotapi_control(); + break; + } + case "强制结算订单": + { + control = new cps_coerce_alimama(); + break; + } + case "机器人管理": + { + control = new robot_manage_control(); + break; + } + case "用户管理": + { + control = new member_manage_control(username); + break; + } + case "群负责人": + { + control = new group_manage_control(); + break; + } + case "开发调试": + { + control = new plugin_debug(); + break; + } + case "查询商品记录": + { + control = new item_query_hist_control(); + break; + } + case "应用功能": + { + _EnabledControl(false); + control = new plugin_manage(); + _EnabledControl(); + break; + } + case "联盟管理": + { + control = new cps_manage_control(); + break; + } + case "系统设置": + { + var temp = new SettingControl(); + temp.Bind(ApiClient.Setting.SystemConfig); + control = temp; + break; + } + case "其他设置": + { + control = new setting_system_control(); + break; + } + case "拼多多订单管理": + { + control = new cps_order_pinduoduo(username); + break; + } + case "唯品会订单管理": + { + control = new cps_order_weipinhui(username); + break; + } + case "阿里妈妈订单管理": + { + control = new cps_order_alimama(username); + break; + } + case "阿里妈妈维权订单管理": + { + control = new cps_order_refund_alimama(username); + break; + } + case "京东订单管理": + { + control = new cps_order_jingdong(username); + break; + } + case "快手订单管理": + { + //TODO 快手 + throw new Exception("该功能尚未开发完成,请等待更新!"); + control = new cps_order_kuaishou(username); + break; + } + case "抖音订单管理": + { + //TODO 禁用抖音禁用 + var StartDy = Util.AppConfig_GetValue("StartDy"); + if (StartDy != "1") + throw new Exception("该功能尚未开发完成,请等待更新!"); + else + { + control = new cps_order_douyin(username); + break; + } + } + case "苏宁易购订单管理": + { + control = new cps_order_suning(username); + break; + } + case "运行日志": + { + control = new system_log_control(); + break; + } + case "抖音活跃列表": + { + //control = new system_douyin_action_control(); + //break; + return; + } + case "保存配置": + { + ChatClient.WXSdkConfig.IsDebug = false; + Util.AppConfig_ModifyItem("SkinName", skin_manager.Caption); + if (ApiClient.Setting != null) ApiClient.Setting.Save(); + + ShowSuccessAutoClose("已保存配置,并应用!"); + return; + } + case "淘宝订单尾号": + { + control = new member_order_lastnum(); + break; + } + case "数据报表": + { + control = new data_report_control(); + break; + } + case "提现管理": + { + control = new point_manage_control(username, query_type); + break; + } + case "手动转链": + { + control = new convert_tool_control(); + break; + } + default: + throw new Exception("该功能尚未开发完成,请等待更新!"); + } + AddControlPage(btn.Caption, control, img); + } + catch (Exception ex) + { + ShowError(ex, "创建异常"); + } + finally + { + Loding.CloseWaitForm(); + } + } + + //窗口即将关闭 + private void main_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + //if (isLodingOk && sender.GetType() != typeof(OnlineUpdate.Client)) + if (isLodingOk && e != null) + { + var result = XtraMessageBox.Show("您确定要退出软件吗?", "谨慎操作", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result != DialogResult.Yes) + { + e.Cancel = true; + return; + } + } + ApiClient.Setting.Save(); + var list = ChatClient.WXClient.Values.ToList(); + foreach (WeixinBase item in list) Events_WXRefreshUserEvent(item); + this.notify_pallet.Visible = false; + Util.AppConfig_ModifyItem("SkinName", skin_manager.Caption); + if (ApiClient.Setting != null) ApiClient.Setting.Save(); + + kh.UnHook(); + } + catch { } + if (sender != null && e == null) + { + Process.Start("检查更新.exe", "FLSystem.exe"); + } + Program.Exit(); + } + + //UpdateSoft update = null; + //LevelUpdate.UpdateForm update = null; + //检查更新 + private void barButtonItem1_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + var LatestData = UpdateClient.GetCloudFileHist(); + if (!string.IsNullOrWhiteSpace(LatestData)) + { + if (new UpdateForm(LatestData).ShowDialog() == DialogResult.OK) + main_FormClosing(LatestData, null); + } + else MessageBox.Show("暂无新版本!", "检查更新", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + catch (Exception ex) + { } + } + + //测试SMTP邮件 + private void barButtonItem16_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.SMTP_User, "测试邮件", "您如果收到此邮件,表示可以正常使用该功能!", false, false); + ShowSuccess("已发送邮件,请注意查收!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + //登录拼多多 + private void barButtonItem21_ItemClick(object sender, ItemClickEventArgs e) + { + if (LoginCps(CpsType.多多进宝) != null) ItemClick(btn_cps_manage, e); + } + + + private fl_cps_member LoginCps(CpsType type) + { + try + { + var member = CpsClient.Login(type); + if (member != null) + { + EventClient.OnEvent(null, MethodType.刷新联盟); + } + return member; + } + catch (Exception ex) + { + // if (ex.Message.Contains(@"“CefSharp.Core.Runtime.dll”或它的某一个依赖项")) + // { + // EventClient.OnEvent("系统缺少服务", $@"请点击链接,下载组件并安装,安装完成后重启软件 + //下载地址:https://wwa.lanzoui.com/iDDvsroqrxc"); + // try + // { + // Clipboard.SetDataObject("https://wwa.lanzoui.com/iDDvsroqrxc" + "?=" + new Random().Next(100, 2000)); + // } + // catch (Exception) + // { } + + // BaseForm.ShowError(@"当前系统缺少组件,请看软件日志,按提示安装相应的组件 + + //下载地址已经复制到粘贴板,在网页中打开即可"); + // } + // else + // ShowError(ex.Message, "抖音创建异常"); + } + return null; + } + + private void barButtonItem30_ItemClick(object sender, ItemClickEventArgs e) + { + new plugin_sort_form().ShowDialog(); + PluginClient.LodingPlugin(); + } + + /// <summary> + /// 修改控件客户交互状态 (Enabled) + /// </summary> + /// <param name="flag"></param> + private void _EnabledControl(bool flag = true) + { + barButtonItem29.Enabled = barButtonItem30.Enabled = barButtonItem31.Enabled = barButtonItem6.Enabled = flag; + } + + private void barButtonItem29_ItemClick(object sender, ItemClickEventArgs e) + { + //监听刷新 + PluginClient.LodingPlugin(); + } + + private void barButtonItem31_ItemClick(object sender, ItemClickEventArgs e) + { + //监听刷新 + PluginClient.LodingPlugin(true); + } + + private void barButtonItem25_ItemClick(object sender, ItemClickEventArgs e) + { + if (LoginCps(CpsType.阿里妈妈) != null) ItemClick(btn_cps_manage, e); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + var client = ChatClient.WXClient.FirstOrDefault().Value; + var label = client.GetLabelList().First(); + //client.AddLabel("Test2"); + client.EditUserLabel(new[] { "wxid_8s44kddouuaj21" }, new System.Collections.Generic.List<Chat.Framework.WXSdk.Implement.Lable>() { label }); + // client.ModifyUserTag(new[] { "wxid_8s44kddouuaj21" }); + //new LoginWechat62Data().ShowDialog(); + //var str = "<msg bigheadimgurl=\"http://wx.qlogo.cn/mmhead/ver_1/5LnxGuicImnmq0IonTk4cQ2rMpDpldkF2EOARwCrhtEH2VmMYrRxC92zTBPRZX1QqZtPd2UOUfZGVF73sKN3cB8mvBibKxkF5SgFjyn0S0sLs/0\" smallheadimgurl=\"http://wx.qlogo.cn/mmhead/ver_1/5LnxGuicImnmq0IonTk4cQ2rMpDpldkF2EOARwCrhtEH2VmMYrRxC92zTBPRZX1QqZtPd2UOUfZGVF73sKN3cB8mvBibKxkF5SgFjyn0S0sLs/132\" username=\"yangshu5188\" nickname=\"杨曙\" fullpy=\"?yangshu?\" shortpy=\"\" alias=\"\" imagestatus=\"3\" scene=\"17\" province=\"昆士兰\" city=\"澳大利亚\" sign=\"\" sex=\"1\" certflag=\"0\" certinfo=\"\" brandIconUrl=\"\" brandHomeUrl=\"\" brandSubscriptConfigUrl=\"\" brandFlags=\"0\" regionCode=\"AU_Queensland_Gold Coast\" />"; + //client.SendMessage("wxid_8s44kddouuaj21", str); + } + + private void barButtonItem40_ItemClick(object sender, ItemClickEventArgs e) + { + Process.Start(Util.MapPath("Plugin")); + } + + private void barButtonItem5_ItemClick(object sender, ItemClickEventArgs e) + { + Process.Start(Util.MapPath("Plugin")); + } + + private void barButtonItem4_ItemClick(object sender, ItemClickEventArgs e) + { + Process.Start(Util.MapPath("")); + } + + private void barButtonItem3_ItemClick(object sender, ItemClickEventArgs e) + { + this.notify_pallet.Visible = false; + Program.Exit(); + } + + private void barButtonItem2_ItemClick(object sender, ItemClickEventArgs e) + { + this.notify_pallet.Visible = false; + Program.Exit(true); + } + + private void barButtonItem10_ItemClick(object sender, ItemClickEventArgs e) + { + } + + private void barButtonItem9_ItemClick(object sender, ItemClickEventArgs e) + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(main)); + + if (!EventClient.StopParsing) + { + this.barButtonItem9.ImageOptions.Image = (System.Drawing.Image)(resources.GetObject("barButtonItem9.ImageOptions.Image")); + this.barButtonItem9.ImageOptions.LargeImage = (System.Drawing.Image)(resources.GetObject("barButtonItem9.ImageOptions.LargeImage")); + + this.barButtonItem9.Caption = "接收信息"; + } + else + { + this.barButtonItem9.ImageOptions.Image = (System.Drawing.Image)(resources.GetObject("barButtonItem10.ImageOptions.Image")); + this.barButtonItem9.ImageOptions.LargeImage = global::FLSystem.Properties.Resources.停止__4_; + + this.barButtonItem9.Caption = "停止接收"; + } + EventClient.StopParsing = !EventClient.StopParsing; + } + + private void barButtonItem50_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + var flag = ChatClient.LoginWeixin(); + if (flag) ItemClick(btn_robot_manage, e); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private DateTime RefPluginControlTime = DateTime.MinValue; + private Thread RefPluginControlTimer = null; + private void main_SizeChanged(object sender, EventArgs e) + { + try + { + //判断是否选择的是最小化按钮 + if (WindowState == FormWindowState.Minimized) + { + //托盘显示图标等于托盘图标对象 + //注意notifyIcon1是控件的名字而不是对象的名字 + this.notify_pallet.Visible = true; + //隐藏任务栏区图标 + this.ShowInTaskbar = false; + } + else + { + this.notify_pallet.Visible = false; + Control page = this.xtraTabControl1.SelectedTabPage; + + if (page != null && page.Text == "应用功能" && page.Controls.Count > 0) + { + if (page.Controls.Count == 1 && page.Controls[0].Name == "plugin_manage") + page = page.Controls[0]; + + lock (lock_obj) + { + RefPluginControlTime = DateTime.Now.AddSeconds(1); + if (RefPluginControlTimer == null || !RefPluginControlTimer.IsAlive) + { + RefPluginControlTimer = new Thread(new ThreadStart(delegate + { + while (DateTime.Now < RefPluginControlTime) + { + Thread.Sleep(200); + } + Invoke(new Action(delegate + { + _EnabledControl(false); + page.RefreshContral(); + _EnabledControl(); + })); + })); + RefPluginControlTimer.IsBackground = true; + RefPluginControlTimer.Start(); + } + } + } + } + } + catch + { } + } + + private void notify_pallet_MouseDoubleClick(object sender, MouseEventArgs e) + { + this.Visible = true; + this.WindowState = FormWindowState.Normal; + this.ShowInTaskbar = true; + } + + /// <summary> + /// 读取公告 + /// </summary> + private void ReadNote(bool f5 = true) + { + try + { + if (f5) Grant.Framework.GrantClient.Get().RefreshAbout(1003); + var notes = GrantClient.Get().About.ContainsKey("notice") ? GrantClient.Get().About["notice"].ToString() : string.Empty; + // var notes = ApiClient.GetServerConfig("FLSystemNotice"); + if (!string.IsNullOrEmpty(notes)) + { + var temp = notes.Split('|'); + this.Invoke(new Action(delegate + { + try + { + this.PublicNote.Caption = temp[new Random().Next(0, temp.Length)]; + } + catch (Exception) + { + } + })); + } + } + catch (Exception) + { } + } + + private static long timeCount = 0; + + private void timer1_Tick(object sender, EventArgs e) + { + new Action(delegate () + { + timeCount++; + try + { + ReadNote(); + + var session = ApiClient.GetSession(); + var robots = session.FindRobots(); + //刷新信息 + foreach (var item in robots) + { + if (item.type == ChatType.微信 || item.type == ChatType.企业微信) + { + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == item.name); + if (client != null) + { + //item.token = (item.token.Contains("Chat.Framework.WXSdk.Implement.WXClientImpl_") || client.WeixinType != WeixinType.Grpc微信) ? string.Empty : client.ToString(); + if (client.WeixinType == WeixinType.Grpc微信) + item.token = client.ToString(); + item.is_login = client.Status == WxStatus.在线 ? true : false; + session.SaveOrUpdate(item); + } + } + } + //重新读取 + robots = session.FindRobots(true); + + StringBuilder sb = new StringBuilder(); + foreach (var item in robots) + { + var isLogin = false; + if (Chat.Framework.ChatClient.WXClient.ContainsKey(item.name)) + { + var wxbase = Chat.Framework.ChatClient.WXClient[item.name]; + isLogin = wxbase.Status != WxStatus.在线; + } + if (isLogin && item.off_line_tip == SwitchType.开启) + sb.Append($"{item.type}账号:{item.nick}({item.name})\n"); + } + string msg = sb.ToString().Trim(); + if (!string.IsNullOrEmpty(msg)) + { + msg = $"离线通知\n————\n{msg.Trim()}"; + ApiClient.SendNoticeMessage(msg); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "机器人离线通知", msg, true); + } + + //账号授权提示 + if (timeCount % 48 == 0)//降低频率一天提醒一次 + { + sb.Length = 0; + foreach (var item in robots) + { + if (string.IsNullOrWhiteSpace(item.end_time)) continue; + DateTime end_time = DateTime.MinValue; + DateTime.TryParse(item.end_time, out end_time); + if (end_time != DateTime.MinValue) //&& end_time >= DateTime.Now) + { + if (end_time.AddDays(1) < DateTime.Now) continue; + if (end_time < DateTime.Now) + { + sb.AppendLine($"{item.type}账号:{item.nick}({item.uin}) 授权已经到期"); + } + else + { + var time = end_time - DateTime.Now; + if (time.TotalDays < 7) + sb.AppendLine($"{item.type}账号:{item.nick}({item.uin}) 授权剩余{time.Days}天{time.Hours}小时{time.Minutes}分"); + } + } + } + msg = sb.ToString().Trim(); + if (!string.IsNullOrEmpty(msg)) + { + msg = $"账号授权即将到期通知\n————\n{msg.Trim()}\n\n温馨提示:为了您的账号能正常使用,请及时给账号续期"; + ApiClient.SendNoticeMessage(msg); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "机器人即将到期通知", msg, true); + } + } + + //系统有更新提示 + if (timeCount % 60 == 0) + { + try + { + var LatestData = UpdateClient.GetCloudFileHist(); + if (!string.IsNullOrWhiteSpace(LatestData)) + { + try + { + StringBuilder sb1 = new StringBuilder(); + sb1.AppendLine("返利系统有更新啦:"); + sb1.AppendLine(""); + + sb1.AppendLine(LatestData); + + //foreach (var item in versions) + //{ + // sb1.Append($"{item.Name} -- {item.Version}\r\n"); + // var index = 10; + // for (int i = 0; i < item.Message.Count; i++) + // { + // if (index > i) + // sb1.AppendLine($"{i + 1}、{item.Message[i]}"); + // else + // { + // sb1.AppendLine($"{i + 1}、。。。"); + // break; + // } + // } + // sb1.AppendLine(""); + //} + var info = sb1.ToString().Trim(); + if (!string.IsNullOrWhiteSpace(info)) + { + ApiClient.SendNoticeMessage(info); + } + } + catch (Exception ex) + { } + } + } + catch (Exception ex) + { + } + } + + } + catch { } + }).BeginInvoke(null, null); + } + + //登录京东联盟 + private void barButtonItem26_ItemClick(object sender, ItemClickEventArgs e) + { + var member = LoginCps(CpsType.京东联盟); + if (member != null) + { + ItemClick(btn_cps_manage, e); + } + } + + private void barButtonItem97_ItemClick(object sender, ItemClickEventArgs e) + { + if (LoginCps(CpsType.唯品联盟) != null) ItemClick(btn_cps_manage, e); + } + + private void barButtonItem100_ItemClick(object sender, ItemClickEventArgs e) + { + if (LoginCps(CpsType.抖音联盟) != null) ItemClick(btn_cps_manage, e); + } + + private void barButtonItem107_ItemClick(object sender, ItemClickEventArgs e) + { + if (LoginCps(CpsType.苏宁易购) != null) ItemClick(btn_cps_manage, e); + } + + private void barButtonItem8_ItemClick(object sender, ItemClickEventArgs e) + { + string filename = Util.MapFile("C#_Plugin.doc", "File\\Design"); + } + + private void barButtonItem59_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + var config = ApiClient.Setting.SystemConfig; + var cer = config.pay_wechat_sh_cerpath; + if (!System.IO.File.Exists(cer)) throw new Exception("对不起,证书文件不存在!"); + var cerdata = File.ReadAllBytes(cer); + WechatPay pay = new WechatPay(); + var result = pay.Upload(config.pay_wechat_host, config.pay_wechat_gzh_appid, config.pay_wechat_gzh_appsecret, config.pay_wechat_sh_appid, config.pay_wechat_sh_appsecret, cerdata, config.pay_wechat_web_footer); + ShowSuccess(result); + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + private void xtraTabControl1_SelectedPageChanged(object sender, TabPageChangedEventArgs e) + { + try + { + var page = this.xtraTabControl1.SelectedTabPage; + if (page != null && page.Text == "应用功能") + { + //page.Controls.Clear(); + if (page.Name == "") + if (page.Controls.Count > 0) + { + Invoke(new Action(delegate + { + _EnabledControl(false); + page.RefreshContral(); + _EnabledControl(); + })); + } + } + else if (page != null && page.Text == "提现管理") + { + EventClient.OnEvent(this, MethodType.刷新配置文件);//刷新积分管理中的配置文件 + } + } + catch { } + } + + private void barButtonItem11_ItemClick(object sender, ItemClickEventArgs e) + { + new EncPlugin().Show(); + } + + private void barButtonItem65_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + if (MessageBox.Show("是否重启软件?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + ApiClient.Setting.Save(); + #region 是否允许软件重启[创建一个名为 reset 的空文件,在FLSystem的Program中判断这个文件是否存在,存在将允许重启] + var reset_program = Util.MapFile("reset", "File"); + File.Create(reset_program); + #endregion + Application.ExitThread(); + Thread thtmp = new Thread(new ParameterizedThreadStart(run)); + object appName = Application.ExecutablePath; + Thread.Sleep(500); + thtmp.Start(appName); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void run(Object obj) + { + Process ps = new Process(); + ps.StartInfo.FileName = obj.ToString(); + ps.Start(); + } + + private void barButtonItem66_ItemClick(object sender, ItemClickEventArgs e) + { + Process.Start(Util.MapPath()); + } + + private void barButtonItem34_ItemClick(object sender, ItemClickEventArgs e) + { + new LeavingMessageForm().ShowDialog(); + } + + private void CreateWebApiEvent(object sender, ItemClickEventArgs e) + { + var form = new web_api_form(); + form.ShowDialog(); + } + + private void barButtonItem77_ItemClick(object sender, ItemClickEventArgs e) + { + new update_log_form().ShowDialog(); + } + + private void barButtonItem78_ItemClick(object sender, ItemClickEventArgs e) + { + Process.Start(Util.MapPath()); + } + + private void barButtonItem51_ItemClick(object sender, ItemClickEventArgs e) + { + ChatClient.LoginQQ(""); + } + + #region QQ + + + + #endregion + + /// <summary> + /// 同步服务器缓存 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void barButtonItem42_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + //AlimamaApi.FindTransferAddress(AlimamaApi.TargetType.产品库, true); + //var ss = AlimamaApi.FindTransferAddress(AlimamaApi.TargetType.淘口令, true); + + AlimamaApi.RefreshTkUrl(); + + TbAnalysis.TklRegToEmpty(); + //删除云黑名单缓存 + Api.Framework.Tools.Util.RemoveCache("Cloud_Black"); + ShowSuccess("缓存更新成功!"); + } + catch (Exception) + { } + } + + private void barButtonItem90_ItemClick(object sender, ItemClickEventArgs e) + { + new AuthorizationManage().ShowDialog(); + } + + private void barButtonItem91_ItemClick(object sender, ItemClickEventArgs e) + { + new AuthorizationManage().ShowDialog(); + } + + private void barButtonItem92_ItemClick(object sender, ItemClickEventArgs e) + { + var wx = ChatClient.WXClient.FirstOrDefault().Value as WXClientImpl_IPAD; + wx.Socket.TestError(); + } + + private void main_KeyDown(object sender, KeyEventArgs e) + { + try + { + if (e.Alt) + { + if (e.KeyCode == Keys.Oem3) + { + var ShowTgwz = Util.AppConfig_GetValue("ShowTgwz"); + var state = ShowTgwz == "1" ? "0" : "1"; + string mess = string.Empty; + if (Util.AppConfig_ModifyItem("ShowTgwz", state)) + mess = state == "1" ? "成功激活推广位组" : "成功隐藏推广位组"; + else + mess = state == "1" ? "激活推广位组失败" : "隐藏推广位组失败"; + ShowSuccess(mess); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + //if (ApiClient.Server != null && ApiClient.Server.State == SuperSocket.SocketBase.ServerState.Running) + //{ + // ChatClient.PCRobotPool.SendAppUpdate(); + // BaseForm.ShowSuccessAutoClose("请求远程更新成功!!!"); + //} + //else + //{ + // throw new Exception("Socket通讯未开启,此操作无效!!!"); + //} + + //var robot = ApiClient.GetSession().FindRobotInfo("wxid_vebvd7abpq1m22", ChatType.微信); + //var sends = new List<temp_send_data>(); + //sends.Add(new temp_send_data() { Groupid = string.Empty, Message = @"撒法第三款了房间里的撒咖啡[分段][延迟=900]机房的凯撒奖发了多少", Robot = robot, TouserName = "wujiahua0876" }); + + //ApiClient.SendMessage(sends.ToArray()); + + //var msg = ApiClient.SendWechatPay(new { test = "123大爷啊.乱码啊" }, "测试啊", 5); + //Console.WriteLine(); + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex); + } + } + + private void barButtonItem93_ItemClick(object sender, ItemClickEventArgs e) + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(main)); + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + { + if (XtraMessageBox.Show(@"确定要开启吗? + +开启后: +①、订单绑定等相关提示语(不通知) +②、返利正在查询中提示语(不通知) +③、上下级订单提成提示语(不通知) + +作用:(有效防止微信消息频繁) +一般在双11、双12、618等 重要节假日开启!", "温馨提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.Cancel) return; + + this.barButtonItem93.Caption = "关闭【双12】模式"; + this.barButtonItem93.ImageOptions.Image = (System.Drawing.Image)(resources.GetObject("barButtonItem93.ImageOptions.Image")); + this.barButtonItem93.ImageOptions.LargeImage = (System.Drawing.Image)(resources.GetObject("barButtonItem93.ImageOptions.LargeImage")); + } + else + { + this.barButtonItem93.Caption = "开启【双12】模式"; + this.barButtonItem93.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem94.ImageOptions.Image"))); + this.barButtonItem93.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem94.ImageOptions.LargeImage"))); + } + ApiClient.Setting.SystemConfig.message_warning_switch = !ApiClient.Setting.SystemConfig.message_warning_switch; + Util.Save(ApiClient.Setting.SystemConfig); + ApiClient.Setting.Save(); + + } + + /// <summary> + /// 机器人离线自动登录记录 + /// 离线后尝试自动登录成功的不记录 + /// 离线后自动尝试登录不成功的记录 + /// 有记录但是已经人工登录成功的清除 + /// 有记录但是没有自动登录不成功的记录增加 + /// </summary> + public Dictionary<string, int> robotOffLineAutoLoginList = new Dictionary<string, int>(); + + private void autologin_timer_Tick(object sender, EventArgs e) + { + new Action(delegate () + { + try + { + var session = ApiClient.GetSession(); + //重新读取 + var robots = session.FindRobots(true).Where(f => f.type == ChatType.微信 && f.remark != "PCWechat HOOK"); + + var wxClients = ChatClient.WXClient.Values; + + foreach (var robot in robots) + { + var isLogin = wxClients.FirstOrDefault(f => robot.name == f.WeixinHao && (f.Status == WxStatus.已掉线 || f.Status == WxStatus.已退出 || f.Status == WxStatus.未登录 || f.Status == WxStatus.登录中)) == null; + if (robotOffLineAutoLoginList.ContainsKey(robot.name)) + { + if (isLogin || robot.off_line_auto_login == SwitchType.关闭) + robotOffLineAutoLoginList.Remove(robot.name); + else if (!isLogin && robot.off_line_auto_login == SwitchType.开启) + robotOffLineAutoLoginList[robot.name] = robotOffLineAutoLoginList[robot.name] + 1; + } + else + { + if (!isLogin) + { + robotOffLineAutoLoginList.Add(robot.name, 1); + } + } + } + if (robotOffLineAutoLoginList.Count == 0) return; + + TaskTool tasks = new TaskTool(); + foreach (var item in robots) + { + if (!robotOffLineAutoLoginList.ContainsKey(item.name)) + continue; + else if (robotOffLineAutoLoginList[item.name] > 2) + continue; + + var _item = item; + tasks.AddTask(delegate () + { + try + { + EventClient.OnEvent(this, $"正在尝试自动微信->{_item.name}({_item.nick})..."); + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == _item.name).Value; + if (wx != null) wx.ResetConnection(); + else ChatClient.LoginWeixin(_item.name, _item.token); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"自动登录微信->{_item.name}({_item.nick})异常:{ex.Message}"); + } + }); + } + if (tasks.Tasks.Count != 0) + tasks.Start(30, AsyncCallbackMethod2); + } + catch { } + }).BeginInvoke(null, null); + + UpdTime(); + } + + /// <summary> + /// 更新win时间 + /// </summary> + public void UpdTime() + { + try + { + new Action(delegate () + { + try + { + HttpHelper http = new HttpHelper(); + var item = new HttpItem(); + item.URL = "http://quan.suning.com/getSysTime.do"; + var html = http.GetHtml(item).Html; + var temp = JObject.Parse(html); + if (temp["sysTime2"] != null) + { + var time = DateTime.Parse(temp["sysTime2"].ToString().Trim()); + Daytime.SetWindowsClock(time); + } + } + catch (Exception ex) + { } + }).BeginInvoke(null, null); + } + catch (Exception ex) + { } + } + + private void AsyncCallbackMethod2(IAsyncResult ar) + { + EventClient.OnEvent(this, MethodType.刷新机器人); + EventClient.OnEvent(this, $"尝试自动登录线程已完成!"); + var session = ApiClient.GetSession(); + var robots = session.FindRobots(true).Where(f => f.type == ChatType.微信 && f.remark != "PCWechat HOOK"); + var wxClients = ChatClient.WXClient.Values; + foreach (var robot in robots) + { + var isLogin = wxClients.FirstOrDefault(f => robot.name == f.WeixinHao && (f.Status == WxStatus.已掉线 || f.Status == WxStatus.已退出 || f.Status == WxStatus.未登录)) == null; + if (isLogin || robot.off_line_auto_login == SwitchType.关闭) + robotOffLineAutoLoginList.Remove(robot.name); + } + } + + private void barButtonItem86_ItemClick(object sender, ItemClickEventArgs e) + { + new TCPForm().ShowDialog(); + } + + private void barButtonItem103_ItemClick(object sender, ItemClickEventArgs e) + { + try + { + if (ApiClient.Server != null && ApiClient.Server.State == SuperSocket.SocketBase.ServerState.Running) + { + ChatClient.PCRobotPool.SendAppUpdate(); + BaseForm.ShowSuccessAutoClose("请求远程更新成功!!!"); + } + else + throw new Exception("Socket通讯未开启,此操作无效!!!"); + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex); + } + } + + private void SetShow(List<NavTree> treeList, int index) + { + var t2List = treeList.Where(f => f.ceng == 2 && f.index == index).ToList(); + foreach (var t2 in t2List) + { + if (t2.name == "首页公告") + btn_home_manage.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "接收信息") + barButtonItem9.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "双十二") + barButtonItem93.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "联盟管理") + btn_cps_manage.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "登录联盟") + barButtonItem20.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "授权管理") + barButtonItem91.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "机器人管理") + btn_robot_manage.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "登录机器人") + barButtonItem19.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "数据报表") + btn_data_manage.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "运行日志") + btn_log_manage.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + + if (t2.name == "系统设置") + barButtonItem13.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "其他设置") + barButtonItem41.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "保存配置") + barButtonItem56.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "订单管理") + barButtonItem48.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "提现管理") + barButtonItem76.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "用户管理") + barButtonItem43.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "群负责人") + barButtonItem67.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "群通知机器人") + barButtonItem96.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "测试邮件通信") + barButtonItem16.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "同步服务器缓存") + barButtonItem42.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "上传商户配置") + barButtonItem59.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "查询商品记录") + barButtonItem49.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "淘宝订单尾号") + barButtonItem57.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "强制结算订单") + barButtonItem63.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + + if (t2.name == "应用功能") + barButtonItem6.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "刷新应用") + barButtonItem29.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "全部重启") + barButtonItem31.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "执行顺序") + barButtonItem30.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "开发调试") + barButtonItem27.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "加密应用") + barButtonItem11.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "应用目录") + barButtonItem40.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "手动转链") + barButtonItem81.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "Web通讯") + barButtonItem72.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "Socket通讯") + barButtonItem86.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "更新易转发") + barButtonItem103.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + + if (t2.name == "检查更新") + barButtonItem39.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "更新摘要") + barButtonItem77.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "软件目录") + barButtonItem78.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "建议反馈") + barButtonItem34.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + if (t2.name == "重启软件") + barButtonItem65.Visibility = t2.check ? BarItemVisibility.Always : BarItemVisibility.Never; + } + } + + private bool isrun = false; + + private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + if (isrun) + return; + isrun = true; + try + { + var h = DateTime.Now.Hour; if (!(1 <= h && h < 3)) + return; + try + { + var robots = ChatClient.WXClient.Values.Where(f => f.Status == WxStatus.在线).ToList(); + foreach (var robot in robots) + { + try + { + var db = ApiClient.GetSession(); + var members = db.Find<fl_member_info>("select * from fl_member_info where robot_name = @robotname and headurl = @headurl", new { robotname = robot.WeixinHao, headurl = "" }); + + var friends = robot.Friends; + foreach (var member in members) + { + if (friends != null && friends.ContainsKey(member.username)) + { + var headurl = friends[member.username].BigHeadImgUrl; + if (!string.IsNullOrWhiteSpace(headurl)) + { + member.headurl = friends[member.username].BigHeadImgUrl; + db.SaveOrUpdate(member); + } + } + else + { + var f = robot.GetContact(member.username); + if (f != null) + { + if (!string.IsNullOrWhiteSpace(f.BigHeadImgUrl)) + { + member.headurl = f.BigHeadImgUrl; + db.SaveOrUpdate(member); + } + } + } + + } + } + catch (Exception ex) + { } + } + } + catch (Exception exception) + { } + } + catch (Exception ex) + { } + finally + { + isrun = false; + } + } + + private ChatType SetUserType(int itemType) + { + + switch (itemType) + { + case 0: + return ChatType.微信; + case 1: + return ChatType.QQ; + case 2: + return ChatType.企业微信; + } + + return ChatType.微信; + } + + /// <summary> + /// 读取黑名单 + /// </summary> + /// <param name="isAsc"></param> + /// <param name="callback"></param> + public static void ReadBlacklist(DateTime updateDateTime, bool isAsc, Func<List<CloudBlacklistResult>, int, int, bool> callback) + { + var size = 1000; + var index = 1; + while (true) + { + var res = YZCloudApiHelper.GetBlacklist(new BlacklistSearchPagingInput() + { + PageIndex = index, + PageSize = size, + UserToken = "", + IsAsc = isAsc, + UpdateDateTime = updateDateTime, + AuditState = AuditStateEmun.Succee + }); + if (res == null || res.Datas.Count <= 0) + { + break; + } + if (callback?.Invoke(res.Datas, index, res.PageNumber) == true) + { + break; + } + if (index <= 0) + { + break; + } + index++; + } + } + + private static bool isrunblackuser = false; + public void Timer_ElapsedBlackUser(object sender, System.Timers.ElapsedEventArgs e) + { + if (isrunblackuser) return; + isrunblackuser = true; + var db = ApiClient.GetSession(); + try + { + if (timerBlackUser.Interval == 1000) + timerBlackUser.Interval = 5 * 60 * 1000; + + #region 同步云黑名单 + + var BlackUserTime = Util.AppConfig_GetValue("BlackUserTime"); + //Util.AppConfig_ModifyItem("BlackUserTime", ""); + ReadBlacklist( + string.IsNullOrWhiteSpace(BlackUserTime) ? DateTime.MinValue : DateTime.Parse(BlackUserTime), false, + (items, index, total) => + { + //Console.WriteLine("输出:" + index + "|" + total + "|" + items.Count); + + BlackUserTime = Util.AppConfig_GetValue("BlackUserTime"); + var syncTime = string.IsNullOrWhiteSpace(BlackUserTime) + ? DateTime.MinValue + : DateTime.Parse(BlackUserTime); + if (syncTime != DateTime.MinValue) + { + syncTime = syncTime.AddMinutes(-1); + } + + bool issyncAdd = false; + db.Ado.BeginTran(); + foreach (var item in items) + { + if (item.UpdateDateTime >= syncTime) + { + issyncAdd = true; + var type = SetUserType(item.Type); + var info = db.Queryable<fl_blackuser>() + .Where(w => w.username == item.UserName && w.usertype == type).First(); + if (info == null) + { + info = new fl_blackuser(); + info.usertype = type; + info.username = item.UserName; + info.nickname = item.UserNick; + info.remark = item.Remark; + info.avatar = item.Avatar; + info.updatetime = item.UpdateDateTime; //DateTime.Now; + info.isdel = item.IsRemove; + info.iscloud = true; + db.Insertable(info).ExecuteCommand(); + } + else + { + //if (info.isdel) + //{ + // //如果本地已经删除,则忽略。 + // continue; + //} + + info.avatar = item.Avatar; + info.isdel = item.IsRemove; + info.updatetime = item.UpdateDateTime; + info.remark = item.Remark; + info.iscloud = true; + db.Updateable(info).ExecuteCommand(); + } + } + } + + if (issyncAdd) + { + //保存最后同步的时间 + Util.AppConfig_ModifyItem("BlackUserTime", + items.LastOrDefault().UpdateDateTime.ToString("yyyy-MM-dd HH:mm:ss")); + + //items.LastOrDefault().UpdateDateTime); + } + + db.Ado.CommitTran(); + return false; + }); + #endregion + } + catch (Exception ex) + { + db.Ado.RollbackTran(); + } + finally + { + isrunblackuser = false; + } + } + + private void barButtonItem108_ItemClick(object sender, ItemClickEventArgs e) + { + //TODO 快手 + return; + if (LoginCps(CpsType.快手联盟) != null) + ItemClick(btn_cps_manage, e); + } + } + +} + + + diff --git a/FLSystem/Forms/main.resx b/FLSystem/Forms/main.resx new file mode 100644 index 0000000..2f0ce04 --- /dev/null +++ b/FLSystem/Forms/main.resx @@ -0,0 +1,3251 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="barHeaderItem1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAAA6ZJREFUOE9Nk31Q03Ucx3+iqwzOhE6t + MxsDOcbDhgPtziPoCGXkJIq6FQsn0WSOjRKIpzTmgRMfuKwpA2zLjFUzIPAIXCDIIiYPTWyDxThQntp4 + iAeBjP569/3Nuut397r73X0/79fn87n7fqnJlQZq7qGJIt86wvqMC+yYXG2o7ng1p19pCFtQfsvtP6Hn + NGSVBwvJ+WMEj/m/zJTrzxvU1Eo9RblWje5wUhZrW6Y6yFhasw+tVhXsTgPmVrswNFMD09BZqJsFKPgy + tE9U6BdIN5p9eOuRgA4L0pnPZHwaPGwwHcPkchOGlyoxMK/Cnblc2BfPYHRZC9dqCxotBcjXcWeT8/24 + JOcxsVznFmx47zS7qc5cAMfCZXT8fgSdLgnMLhm6p+XomVGgZ1aOZrsYv81XoNV2GorPQqzbd3p60c2p + pGw//nFtLOx/lKPlvghtE2LcmnoXJqcEXU4pbk9LUXR1Lw5kMiE5z4ZjsRJltQk4VBSQSTen3v4ooKah + Ox83x9JwY1RIJMloG09BOxGZpg5DWsZG3icyjIw7wZdvww9Dh9E2WII0VaCZCDZSwkL/kXZHAa4PJ0Hd + EoUY2UbkacNgvPcWcqo4KNLkwDW7BMWZRFxuFeHHe+/g9oQSaaXsNSLwot7M8182OtJhsMUhRuqJPqsV + +RcyECv3docnpx/g/FfZUH0TR6YTo95xED9NyJF6KhAhkd7PUq9l+97X9wpgsO6DujERGcWvwjmzhKbO + DoxOLmJg9A4Sc7fDOJKK2qF4fGfno3bgdYg+DqAn2EQlKFjNZY1RuGLZi2uDAhRXx6K4QoaFB2tYWPkb + h5R7cPVnIQyDsdDboqH/9UWU34zBGzksCxF4Ui+Ld4jTz3HxhSUSFb27cM0mQFb5bujqS2Hqv47Uc/5k + vf240v8CPrdEoPpuNI5d4oEveV5JBI8TqCcFct+7J77moqo3AppuLlnnIFJKfBEppaBp34+qPh4qCdpf + dqOkjofED1g2Lx/G0yTrQQvWR8Rv5SVk+s1/qAsigjBoerhkTyGaho9CRybT9Owi8nAU6kOQlOO/Fh63 + JYrkGJ0T71OUaVxGSxjh8Vv3HJD5jqSc3Imi2iCou0JxqZuDi2YOTn4fjFRVAF45yhzgPQrTo69zZzvG + JLSAfokbyFg+0cnPFcZJmGaBnAU3Chb4R5jWl0Q7Tnk+xdhC6hh0PZ1zZ//7+VdE70Tb6Xu+meBD8CZs + IjxB8Ph/fceYhPoHAkQRj5PgdPMAAAAASUVORK5CYII= +</value> + </data> + <data name="barHeaderItem1.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem9.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAFBsYXk7U3RhcnQ7XWFAegAAAfdJ + REFUOE9joBqYsdOPfepWHyMol3TQvNBZcOo2n39Ttnovn7DBSx4qTDzIbTUXmbTZ9//2C13/J27y+j5h + o2dvxwo3Qag0YZBQZiDWs87j/6P3B/5ffLbo/9qTNf971ri/7V7lVlo51ZYdqgw3iC3WE2tf6fr/yvNl + /08+7P9/+tHE/0fuTPm/9FDJ//blLnfbljlHuYQoMUGVY4LIfB2x5iVO/089nPJ/y5W0/0futf8/8aAP + jLdfavs/a0fa/6aFjica5zs4QrWggrAsbbG6eQ7/j9zt/L/6fMT/Necj/2+7mvf/4J1WoFgXGK88XvV/ + wtro/9Uz7KKh2hAgKF1TrGKm7f89N2r+Lz8TjILXnI/5P/dAyv+2FUH/SydbHUlvMtEGamGE6IQCv2R1 + seLJVkDnF/xfdNIPjqfvD/3ftNz3f36P+Z2IfJ14oFIBIGYFYlQDvONVxfL7LP6vOZf8f94xz/+zDwX+ + b1jm/T+n0/RVdIluuZAYpyRQGTcQY2oGAY9oZbGsTtP/i06E/a9d6vY/o9X4a0ypbr+qvpASUJoHiEEa + cceCa4SiWFqL0f/UBoM/MaU6y0ydJQ2AwnxAzAbEII2YtiID10hF0dgKnZ32gXKgaOIHYlDiYQZi/BqR + AAsQcwExJ5RNtEYYAGkg7FQUwMAAAKo13SoioekfAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem9.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAFBsYXk7U3RhcnQ7XWFAegAAA/pJ + REFUWEfFln1QVFUchjXjmkw26R+W6X81fcwYojaxaoEps/KxJo3rR9mYaBI4mlqOTSjJsLK4JAiIuK4f + 6+KCkQKrQhgzrZmCsHy51oiRIK5m6DhZNs40zdjb755uTOecS4Mwa8/MO8N97jnnvfdcdu8OAfC/Rl8G + EalLFEwGEalLFEwGEalLFEwGEalLFEzyDLV/+XrFjuPxY7XjQSF1iYJJnmH2E3NA+XlnVfy7prefe0jz + A0LqEgWTPCE7vzChvssNx9crUFht8uYfjXtaO3ffSF2iYJJH2XE8Djd/8+PK7SYc9m0CHd/N98Suf98a + 8bA2pt9IXaJgkkfJ88Si504L/Nf3ofNWNZqulMPhTcb2ytjm7M+M4dq4fiF1iYJJHiWnfDau/9qI5kAB + y4WeUgRun4Wn2QI698e2I8YtG3dFPqKN/0+kLlEwyaNkf27E1V/OwBfI59J+4wj8P1Zh91crYSszXrSW + REdqc/pE6hIFkzxKVmk0um7VorF7u5TWqw5cvFGBYy020Lh7me5ZRWmOqMe0uRJSlyiY5FG2HJyJc9dc + qOuyof5yjm7U8xd6arDfuxqW4pmBDNdr8dp8DqlLFEzyKOnOGfB1F+Lo+WU43ZmFus5s3Zy9nAv/tWJU + t+Xg04qF2Lw/qjTV/uoYbR2G1CUKJnmUtD2RVLANZS0LUN62BN7vN+P0JVufaewuQvtPlSiqWQaae5PW + 6P3ykrpEwSSP8rH9FZzssKC0eZ4WMzzn34O3IwOnfsjqzTeXttJHdDc9Djdcp9aC5t1bXzDNSWsM+3up + AV7AhsJpqG1PhduXwKXE9wYOty5B1bdr6AK2oiXgRLXfStu/COtyDd+ZU14w0fxHKYO7gA/yDFSyDq6G + OVJKfGZ6LMvhOZeC9DIjFUfcSdwY/knoyBD12Y+gqN+WQ9WFVKQuUTDJo6zJeRmVbclw1sdxOdT0Jipa + k2A7ZgKN+TMpY3Ll1JjxL9Ic9a5DKNKLS+oSBZM8yirbS/QPuBR762JYXA0J7Nh+ch42HIhCSubkjoQV + z5pp7OOU4RR1y3vv+t9IXaJgkkdJsU6Bu3Eh9pyZjQP1c1HcYEbqwRlIzpxy960PJ1hHPzHiSRoXSuG2 + Ww+pSxRM8ihJlklw1iVQ5sJSPgurCgx4JzWsxhAzbhKdH0nR3W49pC5RMMmjLE8PR15tNNY6pmPppond + 8YnPLCY/iqK+gPrcbj2kLlEwyaMkpoVRcdjv81c/nztmfOg4cv3abj2kLlEwyROy+KMJJyJinjLQ3+pL + RqEM+GeZ1CUKJnnULVY/z/e93XpIXaJgkkctVO94UMX/IHWJgskgInWJgskgInWJ4kFHVz64YMhfkU05 + On2zdlYAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem10.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACN0RVh0VGl0 + bGUAQ2FuY2VsO1N0b3A7RXhpdDtCYXJzO1JpYmJvbjtMlpayAAADmklEQVQ4TyWTf1CTdRzHvwim2KS6 + 0k5iXWAbIg6GbG2gHmPGhMEs+CMsT70yE1BGx3F5kCReFE7uNAMu7og6MBFk/LCEOZ15WUkXw8aAcgsE + +SHC9mzABtuR3rvv8/C9ez33vs/n834/3+9zz5d4TK3Ec7uDeO9cJXQF/pZ7RGQrKqh6cKLQMl5c9ISF + 1X8XamsMHxwU05kgSoDHpCcLxhZCA/SsMYCy2qrNKx799BP/7Ldfw93eAM/tTngp7vZGzNRXYezkCb/5 + 2NFSOruWsooLoCtAK5fxho7nmcYryuC51Y757ouY66iHq6UGruYauNvqMPdTI+jLMHH2cwwcz/1FEyl8 + gQ1hA4LMHx7+ZrS8lBovwVKUj7pwEYyZmXA2noOz4RxuZmVxNUvhMS5o7Msy/HH4/cvUu5Z0ZmVKrbk5 + Txj9d7hXkIMG1TswdZvRnFOCbnUGDOkaTpu6ermeOf8juK7UwZqf97Q+NTWJmDI0tSNfnMTj2grU8aPw + wD4Fh2sJ9lEGLdrTHPepnnZ6MWyb4mamq8sxcroEhrR0Pbm5Rz1sP/ouRrT7cUPzFv7UnYd36T84532w + PWRgG2MwO+fDwuIy1zNq9mI4Lxu2I9m4oUp7SK4rVMv/ZKdg6O0dsB+iW969Gz26C5hx+zBDd/LYTWF8 + +L3iKxiUStw/kIbBjAQMZiXBoEhZJlflScuW1DcwoJZhaG8irkm2w3jqLN3yEh45FzHl8FKWcL1Uh2vx + 2zGQLod1jxT9KglYL2kSy8d6lSuFrthtaPu4DAP/OjA56wWz4AMz78f4jBf99lnoC06hKyYaljfj0KsQ + oylWNkVqheLvTTtksCjFuBQuhHPaiUnHIlwLfvRfqOZYCfHA8cjJzfyVFIOfEyWoFsR2kqLQiF0Xo+Ke + mnduw12lHLcOHIKfYXBPVwmjLJ4i4TRbY3t3k2XoS4zGD1vEyH/5NTX7IwVXviK8fCVyKyzJsehJlqJV + GAmTLI5+Fzl3ZlaztR6FFBZFDPSRUTizScBenvVswKqta9ZtqNy4ua8pQgDzLhE1JaA/RYK+hCjKFnrm + eAyqE9C3U4TmzQKc2RhhFa15lk+9gWSi4D02JDD+Gd6msuf4LVUbwtEuiMAd8evoldJAyq9Ud9BaNe19 + 9jz/x+jVwa9ST9C4dh8h7IMTKxeDd3DdS6oSXmhreUjYhC6ED11IGMrXh00W80Lb9ge/qKEzIZTAFd8+ + 8j91kUbX3K/WKgAAAABJRU5ErkJggg== +</value> + </data> + <data name="btn_cps_manage.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAidEVYdFRpdGxlAEZpbmFuY2lhbDtEb2xsYXI7TW9u + ZXk7Qm9vazuCQ/4SAAACxklEQVQ4T3WTa0hTYRyHvV/SPgdhulmmZUSZN4JKNGt4n865Uryt6TTnbeqc + eBkqE9LMW6mRmU5zqZW1JahlBvkhM/OGpk4riCLyhpWZmL/es/ZhKh14OHDe8zzn/N/D0QGgozl0CXrb + 0P8P1Jqu2tUEdMuVrOeVncGgqHjCJlBngjIY5RrKlCyUKVgo7Qjqo0LaAb1rikD0jz3E5uYmNjb+4Pf6 + BlbX1vH95xqWV35hfnkVXxd+4Mv8CvIaz1OSgXZAX9rOQEatK8EF6TUuSKt2gfCGs5rU605IqXJEcuUJ + JFU6IOPmKUoy1A4YFMo9Mbd8V83s0j9US82EJg0yqBZlmFlsRGr1SUoy2hKQyNwwtdCAZ+/jCHw8nePD + N8mSsA89szHoUfHQPcvDq08SJFY4U5KxdsBQXOeKiW816FJxcX84DPElx8EWWyOy0A7hkkMoanVH53QE + +j+KwS8+ujOQXuOIwc/FUE6Fk3mdwBRa4WKuDTqHs1DaxkJmrRu6pmPRMyMAV3qYkky0A0YpVQ6kLkHr + KAs59WfAybJGaN4Bgh2K7jHQOyOC8h1PTVSBHSWZageMBeXH0DcngnyEiY7xSBTJfRAmsUUICTHTrBBd + YI/mt77omAgnIx3cGYi/egTdM4nkJj+EkNmlcg80v+SCLaIhOJOGCzk2eDQRhfYxDkJz91PSLu2AScwV + eygmeZANeSG7/jQiyRM9Y/fAW7AXCSWOaOmPg5Kst4wEgZNtTUlm2gHTaKktHoyHoeENA22jHLJZyfBP + tUCA0AIvPmST2WPQNOQDGXlDtphGSeZbAhH5NpAPB6H+tSfhLG4TFJOXyMbm4/EkF3UDHrg14I47gwyw + RJY7AkaBQnovM4WGgGQa/JNo8BPQ4ZtAg89lOrzjCXF0ePEJsXSci7KifqYtn5H6PY0JZgTzbezeBnXN + hKAHQOcvA3wSczZOvyEAAAAASUVORK5CYII= +</value> + </data> + <data name="btn_robot_manage.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACx0RVh0VGl0 + bGUARG9jdW1lbnQ7TWFwO1NjaGVtZTtEaWFncmFtO0hpZXJhcjtOZXRODypEAAAB80lEQVQ4T5WS3UtT + cRzGj261pakb+Er+IRa0i2ApEUvFWiFtShgrCodvF63RTsjEMYKCyhpE1C6ki1IQfLnaqmkZrBcw6GWW + V2GCVBj0Ij59Hz3I+d2dDnw4v+e75/c55+wcDcA259MfNTmKBJuwQ9hp4DBykblPlBC68046mj36sJCN + jS1hk/EtIg8+PKXI3CdK6Bh5S4FzYLSAzz838MlgcW0DA6OL0tbKzH2iBP/VNxSUBm8u4PXqOmaX/yL3 + dR2ZL38QvL5AgdvcJ0o4kshTUO4bzuPR+zWkXv7A7VffcUvOvkSegkpznyjBqz+nwOWNzWPkxSrij1cQ + z65gSPDq8xRUm/tECZ6LcxTs3tc7nfNcmINkeCI57I/MYm944hnl5j5RQkP/Ewr4CsuFmkPH+tJNbT1p + WdcJbsHefFJX9miXp+u3aT+TxIlQEv7TCfi7hnH01BDaOuNo7RhES1CHbIav/RLY1af2aLHJenFufTjF + go2bjPUmrQE91RyIpcyzw8ej7PAumblXs4Xv1WXC92tw7m4tQqnarMwcFmd2ChxdN6qx9PsaCr+SCFyp + 4hUqLM6cFJT4ByuR/xbGzHIjWqJu/lBlcVZKgbOx25Vp6nXhYE8FDpwt4625Lc52UcA/o0RwGXDNZ7My + K1be6f8D7R8bleevx1tLIwAAAABJRU5ErkJggg== +</value> + </data> + <data name="btn_robot_manage.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACx0RVh0VGl0 + bGUARG9jdW1lbnQ7TWFwO1NjaGVtZTtEaWFncmFtO0hpZXJhcjtOZXRODypEAAAFXUlEQVRYR62XC1AW + VRTHVystHTHNZ9o4ptlkhlChKAgf+PGB8hDEV6mBgWCkKA8FeZgPCCM1Hw3RBJll5AN5SjgKAj5KE8Ix + CUQ/IEwUkmAUmxqb+XfOuvvNSpeapj0zP+7ec//n3LN3v717kQD0iMB69UDvbn2LifJqETpVNMZJHyEe + I/oQfTU8rsDXPPYoYSlClFeL0KmimDx5RHq5KT7rUmXiwRqoJDzUXkZ81sWq8LRSd9JzoXIRorxahE4V + xXh5+6774mLrqYZOmO/+KdNw9z4auu7D3EV9bql/qrETrCN9PyVOmFeL0KmiGCfqvzqzCpfaf0fFjXso + vd6Fkz/fQxlDfeZMy2/4of0PhGdUcaAVwY9MmFeL0KmiGCcasOi90yhrvIOc2l+RW9eB/PoOFFztREE9 + QW0+tRVNd7AwpYIDBxH8WxDm1SJ0qijGiZ7021KGzG9uYHvpT/iY2r0XbmF/dRv2VbYi4/xN7K64js/O + tWDOppMcOITg34EwrxahU0UxLmCwz8ZSpFU0Y0NBPTYVXsOWIjOSis1ILm4gzHI//VQzvDeUcOAwgt8I + YV4tQqeKYnwnQ7wo8bYTTYjLuYKEvHpsyL+KjVQI807hVbm/o6QJsxOOc+AIQrcCONGwWfHHkVR0DesO + 1yE2uw7rqZC4XA3UT6ZVcF9/jAOfJnhfEObVInSqKMYrMNw99hgS864g4kANog79iOhDtVh7uJYKegD3 + eWWMMcUcOIrQ9REMdY0uaA39pOrBhLQCsdlXEHukFjF0HZPNbS143BCR10Z69RH0EuXVInSqKMavoZXt + gq2Bhsj824aoIjAuUUepJSKVNqoQTmvy2q39NweRfqASp0sBvKXyKnDSkcQYYizxLDFOA/t46XkPkO+e + EObVInT6BsRLc5bGcTwbJ2L4dVQ/Pk8wRt+3uUr5WvHzuPoxkgtw8lguzfAIEs7DCJ3ei9cTMRyvNTWp + hZm+K7mAv/kJizmYlkkOxkDhPIzQ6blobfWshVHwWBAJj3lrYPJfDdPccLj5rQJP6uoTBlfvt+DitQLO + nqFwnh0CulPQncLR9CYc3ZZhujEQ04wBsHd9A/YuS6pF8zBC85gX0cPIAzN4hko0qeQ0K5gmDZYc3YMk + mlSiSaXpMwMkmlSyd1kqTTUslqYQds6v0Vz/oQA331Xape3RHOhOqflX3SsOC3vWpZUYueEB/uzyq8M/ + ou5oj1x66mTrnXJwhnHnUcOFXcWu2PU1wW2xi9zuLDRUbtnvYCJdn+QsRzcddVyIXESf1FynW9XNH+Jm + Vz6Rp5CDFuL75p1IzXHmU46VXrr3c2Udv7a8ElK/pIOOaOz8HDW3U3GpbbOFy79shbkjE0lfOfIzHK6X + LvmArLOcmqwS99nTaSYMJeZAlDetwNnm1ShvDMUJ6p9oCEbC3qkcMEYvHY+TbjAhH1oGRafbobBuPjIr + p8hkXLCj1k5uj9R4IzLtVQ6YoJeOx0lnObQMDf/AFtmXfZB+7mWZj5hvbWW+rHZH2DYbDpikhy7rojtW + 0jjp+LsinxmGh6S8RAlM2HPWBnvOTMZuGWvsPm2NzPMGBCdZc4CNHrpPvzMgJGUy60YTcgHDliZObE0t + moYdFZNktpervIh38+3wetwL/I23Jl3b/9WlFNhhScJE1vGpSX4EA53mjw7yixzf7h89Af5Rz4GuMTdi + HPzWjIPPyrHtU7xGrCDdmBn+o5brobP3GRlCOsvRnavgzjPEeGIC8bwCX/P3n4/ZA4inCD10PM7LL+8D + /Icr4Y2B/6Xqr4H77OciWcOvjR46Hn9oO1b373+CTeTvDpvI3x0ySfoLXBkamf6BV/AAAAAASUVORK5C + YII= +</value> + </data> + <metadata name="menu_login_chat.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>641, 17</value> + </metadata> + <data name="barButtonItem19.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAFBlcm1pc3Npb247rGnpegAAAthJ + REFUOE9tkntMzWEch5HItbnkMsxfzCWNlW6ok+yUc3TXKY5Vi2qlVi7lGkIqjklzNtnoQhOLmogSx1Qr + FZVEhmEu2Wz+wBg65/G+OTisd3u23/t9v5/nvew3AOjDPAYKrBM27VDFp6ZXRyam9ahXrXvnszKixl0Z + 4C/WbMw9f3P/CaxTtu/dp9OfouLqDTq6HnP3/kMKS8uJT92FuzIwR/QMFwzsT2C1JjbJLzvvhPHazTpy + 84vQxm0kLCaZ3Tl5nCwpIyoxzTR3oUeI6LXuT2ATHpPcUlZZzZHjhSzyDalxcPXS2Lt4hjt7+9emZx0l + Q6fHycvvnugd3Z9glCp87ae2zm400UnYuyg0UioYNs9FsVqepORiFY5L/T+Lmt0/AjHkw4z1UGtoam3H + Xxsri1MEQwVSMj0yYSPnyquY76mWa1MFgywFVg1Zy+tbdSuQNB9U05ilon6/L7cylNSmL6N621Iupyqo + SPGgONa1SWSGWgqGyCA/euD7a/j2HL52w+cO+NgEHwzw/jL0lGJ8kU9JrJsMjbQU2LQcEoJvL+CtDl5n + wstd6HWR6HO00B0P96OhbTXGxgAKopxlqO8hfwuGN2Wr4MsDeJUBz3fC081s2RBMWnIAPBHzlpXQuAKj + wZsTWkcZsrUUjGgQ9+VjAzzbKnZMga54DKfDMBQEw2NRq/cBgyfGmoUcC50vQ2MsBaNu7VH+uuej9fBg + rTiulvQUX3YmeUNzKNS6Q/UCei/NIjfQQYbGWQpGX98hGt8UQXsEtIbReV5NWIgCTdBiOi8IQdU8TBUz + 6T03jYNqexkabymwvZLmhenZYUx3gjHVqzDeVGC8vQxTWxSm1lB6K+fSWzqZH2fGcsBntgz1/Ux/3qAk + wb2ubP1izsa5URztwqkIJ/JXOaIPXUBukAM6P3uyVXPIVM5hy5IZjXJTS4GVYKRgnMDOzAQzE81MMiO/ + bQWDgQE/AS2rGykb7R4YAAAAAElFTkSuQmCC +</value> + </data> + <metadata name="menu_login_cps.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>347, 17</value> + </metadata> + <data name="barButtonItem21.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABGdBTUEAALGPC/xhBQAAAyRJREFUOE+1 + k9lPE1EUxvlbDJkS2youiBiURHnQGNG4xC3ghkaiuESMy4OJElwTjWsgCCgi4gIuuAfEBxdEENEYFmM7 + rbSlpWU6My2UttPPew9SJJSYEJ3kyyT3nvO7Z40zGXRvzEYd/oVMBqGWAQU51uWEZNA5/i9QTJ4O5e5t + pirY160a6/BbztwceMtKIF25CHPi5JG7P4GOTZkIO+zg38D7t4CmQS4vgzjDGHWwpCbD9+wJ2Sg19+g/ + 2NGO7mWLR4Bi8jRZqaqkS8/p40AoRFHaVi6F53g+QhYRttXLKSqtrw/qw/uwZ64lYND0g2z5ed/5swya + 4Iizb1iv+p4/JaBt9QqEe10UoXNvLvwN9QTk6ffkZJMjfzDwpY2A/hfPYFuRgZDVAqm4ED/T05xxzt07 + /NxIvV89TspTbGaj8Iml1GFJTyuPlbJ0+QI0RYFjc5abgMGuTviePqZL7hBtikHQGCzBOjl+qUUvpJr0 + Qjav1XBT5Ipy9vg7hGzdBI8CeQ1d+/fSoXKnCmJKEhWZN8yqmzTTrBe2mfTxS1jRc6j4vEFzk6E+eoC+ + C+fg2JJFWUWBHKRJEjwn8hE0m+B7UkuG5ikJMOt1C1mkh0xGYadoEA6zrofl66VQWcqBts/wnDmBiKpS + MFGg/3UDvNdKEenvpwL7X74gg8FvX3m3mxmwnUXba89a4xn8+gUh0Qz1QQ3Z8NpJl85joLlpCPhz4Xwl + +L0LEb8PcuUN6qBUXATWffQeOQwEg3AdzGORnBxq1K2bcO7bRcCBD41wHz0CTZYRaGmGNS2lhwabZswr + 0YuRQABS4WU48/bAzeaQR8md/a/qMNDUSLXylhTTWdjppG3h53wxRm2KZd5s5lRPUJ6y5nGj/90bijDQ + /BEIh2lGvaVXEfH5oimr1Xchzkoc2ZRh4LBcB/bRXA12dlCDXCxS/hAfau/VoiEI2xZ3wTE4tm6M+pFi + AbmsC+ZSkTXZi0BrC81aoK2Vtod/yu1KiElTR/mQxgMOy3OqYEzKPduzY9qS/gbk6s5YBKWyAnzfLXNm + xrSJioBGoS7m5QRkMgp1vwAH7FLK0nZhvQAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem20.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAYdEVYdFRpdGxlAFNhbGU7RG9sbGFyO01vbmV5O/mn + uEUAAAMRSURBVDhPdZILSJNRGIb/StE0L+Cl1NLS3K1M09ScbN5wOecIRxlJ2aYjnZdNyazpTFOzErJk + utUSNSK8S5ZUBN0kyqLIyDIRoyIxIrMiiGzj7fy/WVb2wQvnnO+8z/edCwVgXs0TC+bo9765Jlr83Y2/ + tDHDJA9XGMyhaXoEp9YicGuNmSfV7SZ+Kxr0X4Cm+QUVoTTJk7S9FnXTGMgc6qZRZJueIVbVDL8YdQ4B + WNOd/GGmY6byScWsOd04iuiCCwjaVotIVRtEun6wNmnh7B3mQbYv+AcQnm5Ml+zvteSeHkFa3RAklQ+w + ftsxsIXKzIgtZZBV3IJfbCEcPNb5MYDZlunJrDnL+BQq/QAONN1HQf1tJBd1YoPsIMqzdiG9+jJWCjWw + d+OwfwEYs6I+g247xzSCrLoBPB59i1cTUzCbLSg29ENW0oe84gYUKeXw5mfDzpU1A2DMcr1Ssv+8JdM4 + hJTDd3H03EO8nviIkJ0mfPryFS19gxCoz0OQ1w1F8mZIhYKrxOfMAMLk9cok7QWL6uQzHGkdxPDLScTn + 9+DbtBmqmkvouTEMflYrBLld4CZVgB0Qd0aXxBkP9nZ2YgDhcsNYpuEJdhwfxNkrT5nKofJmPHo+Dn3H + PfCz20nlLqyTlGJ7BJu+rBXaBHZLochfTcZWFE9SFMBXnnqXWHYHutN3Mf3dzJx97M0k0iouIjK3E1xp + JZbz4hoLYn0/E9OSnBhfUXEiZ4CMbYkoK1+BIiQktfZ9atU1aE5ch9ZwE/GaDvLu7YzZhZXY4O5g40cq + T3s62zqKeEu9dIlcGuZABaXU0BBrz0BZZKCs8kN0fi+EGnJhud3EXAEXtthA8suI7IrF7CE53ycqiuW2 + ulTCmSJrjlRA8iEaQD+HjSsrJoaboP0oIOfmSqvg4i82knX6xy0ist4Tz6rOj1utVwlX7Svc5N9G1uwo + nrScYotLyJiBLHbyDkvwCs2YdGGJG8icMbuu2U7nF4rXLvXRJnAG94r8+wK8HGfAf31lBkLkTkS/s9Xc + b06C7sT+p0gO1A++AraRs0uR4gAAAABJRU5ErkJggg== +</value> + </data> + <data name="btn_log_manage.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABt0RVh0VGl0 + bGUARm9yY2UgVGVzdDtUZXN0O0NoZWNrZDNApAAAApFJREFUOE9tkvtLU2EYxyXJ8pqX/pSVQSSRkJAS + JYFBSkkmhrCydKkpYjFNXXPlnGXaBZ1lELSFONO8Yk3MG0VlrVoXU7xsc25zO7t8e95Xozp64HPOL8/3 + 87zP854gAEH0BGu0E/0Nj6bAeTgFTdskp56hZUxA3ToB1T3jINWHsBzPrgu2suI/T4BBrwC9/n4D8BM3 + HoyxQCiV/CcIqWsZ58Vuwc9Z9RBuH8yzn5CvToS2qxo+XwDXm0dZIFws2Ka6/5oLWLDFIIdMnYQvMybI + 6g+g740CF1XJEHx+VN8xbi5Q3B3lR3Su+iBVJKLvbQ3OKRPQ1HMM6bJ4mH6Y4fH6UdHwkgUixILtVbeN + 8PsDcLi8VPwZZyv3Qak/iLTzEnz8bobNKfDRrtQNsUCkWBAq1wzDRwI7CZadXnz4ZsLRnHhMm7/C4hBg + XRH4eKXKARaIEgvCym8OwUtLslHY5vDyAGNpxYMluwcLyx44aLyiml4W2CEWhJfU9kOgGVm3yVtN6Ek/ + BdOAEd0nTmJM3Yh5mxsrdLqCqu7NBYXVvXxJrNvj1DT8amtCx/E0zLQ2Qns4FXNWN40mIE/+nAWixYKI + gspuPiPrND0wgq6UFMxX5MFwKBnv+kYwu+SGlU4nLe9kgRixIDLvqgEu+nHmLKtoTzoC04VMNEt24X1u + BmolezGz6ILFLiC3tIMFYsWCKGlZJy3Jyzvpyq5BuWc/xl+8gmJ3Ap6UVODngguLtMic4mcsELdBkFvS + wa/QTrfAZrXSTVjoBiy0k0XqvECjzds8yC7UscCGE4Rm5rcPZl/WI7tYj6xCPc4U6da4pMNpIkv2lJMh + bRmm+g1/4hYijIgmYojYdeL+Yef6N5IIXhMg6Ddf4aVsX+byDwAAAABJRU5ErkJggg== +</value> + </data> + <data name="btn_log_manage.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABt0RVh0VGl0 + bGUARm9yY2UgVGVzdDtUZXN0O0NoZWNrZDNApAAAB8FJREFUWEedl3tQlNcZxjH3pI25aDRtk7bTS6ZN + pum002niP506k056mUynfzQxTZqMjprGgAWteEVQriJEQ/AWBYxJFBHQREVEkaBoUNBCzMRxJBG5yrI3 + WPbC9enznG8XVt2ddvrNPHO+/XY5z+99z3ve7xADICbsmlRUev7EzvIL2Fl2AUWhUSo9j52l1lhIWWMj + Cvc1oqCkETs47ihpMMrdXrOWc91B3aY5NxadjtlYeCpmAxV+Ge8wgEnUbTL8X6/BwWEM+Abh7vOhx96P + 1nYnLnzRibrGVmRuqkzlfHdqTs3N72Kyt9XwduLiFLcA3K5odY2MjGFkNKiRUY6jGOYzaYifJX/AAnD1 + +3Hd7sFXbQ68u+sMxsaAqlNXkJx7KI1z3kUZiLS8YxwmrkgAdyi1FkDI1FLIdGiYAMOjGAzKHxiCxzsI + u9NLADtydtQaAI9vGEdqL2NZRnk6572buj3oMX5FArizgGupy4p0jCaMWmY0l2EgaBwYpPngCMcRZmEI + drcPLcxAev5xA+Dj94I4dPxLJCQXZ3Due6gbICIDsIh0KUpJhibioaCxRiowRHPKLxHC0efHlVY7knIr + DIAy5TcQIzhQ9QUWLNt1C0QkgLu27w0DkBEnHzRmgrFMjTGfh+RjMbr6A2hpdSAx42Pz94Jg0kwW9Zvy + I82Yu7hAEKGauAVAD+/eVmwBmIipCRNpFL4ARxaf188ClJh+r38E7v5BXOt2Iy2vEv9MLkXc6n2IS9qH + 2FVSCfZXNiO34KTM7qOUhYgA92zdfTYIEIw2CDABMoweRy9Wb5uFJZufwWdNtaYIPQSxuXz4ut2Fzy93 + o+FiG+r/fY1b8ipq6ltw8mwLct6rldn9VHSALR/VG4DQ+ipiReqlgaJt7W7F4rzncLBpDhpd8zEn9UlG + 7zUF5/YETDHauCO6egfQ3uXG1Q6XqY2vrtmRvbVGZpMpNamIAPdu+tACUMq93GJHzxZjTcEslJ8owsUr + zVi66XnUtcWh2v57zEqZjpKKD+AeCJgM9Acz0cfRPcCtyQZlcxHG5oHN4UHW1mqZPUBFBbgvX42ED7XG + xxpKkVP2Aj5tWYbVhTPx4vIfovbqAlT2zETs5seQuXU5Ix5AP836DYClvqCUEQeblJZGzSoj3wA8SEUE + 0Lp8I+/9OgOgdJ9uqsE/sn+Js/2v4dJgAi75l+Jo70wkl/8A81f+Bdd7XcZE0a7bcgKZm6uRSZPMTcdN + P0h/V6piJvzw8DfshDJ7iIoK8M2NRQQggTLQx9RW1x/Fa6k/QqX9tzhifxY7mp7C83N/jC9bWuBkVCZa + Tt43YI2CcXksKXont6fk9Q8hNe+ozB6mogLcv4FbRQChLeZgiitqP8FLSY+j5NrT+NPCqSg7XGLWVGuv + DKgHOMJkD4mRy9zRFzA7aM2GSplNofSSiggwOTesl2tdZdLr9GB/VRlmzJqCpeveRMd1OyOkMaN0m2it + e2NGhUx73X4z2g3AMJLfPiKzqZQAJt0MoLRMXr/tUwKMTRSTSWmAW8uDti4bunqccDKyUJqdxljppmhk + siBTjjYC2Kled8A0r6ScwzJ7hIoK8ID2qgBC5p0nT6P5jXm4Wlwybtqy60Ocnz0HbafqLWOahaddpnaa + CkBZEICXACuy/zvAg1lbjmOUACa1BDj3yqvwN9Si9Z31uFz4Pi5teQ9f52bBf+YYTv91lhW1IqZJL82N + gqbXuf1sakz8rJpavu6QzKZReh9EBHgoPf+YBRCs5jNZuah/8Y/wFa5DQ9w8nHtrHrzb0lH359/h1Lq3 + TcQys0wt2VwUx26HFz1OHlacPtOglmZ8IrPpVFSAh9PesQCcXHcVkyI6kZyGuheegyc/Bf15yaj9w29Q + nZYdNFSqA1iWddBIJlIitSRd+tgC4JLqnh6PUhEBtC5T1nKrjPIYNl7JBGjM3ICLs1+BPf5vsMe9jOZX + X0IDnylKI6WaUfdw7KGZDKUuu9eM3Q6fKerFqftl9i0qKsDUFG4VAZh1pc5lbETTG3PhSo3Hnmeexp5f + /wyOlFicf/3v+Izf9dD4uhRmLEOps9dr3RNEBb1orQH4NqUj2g0A5jREPbI6p8IcRM3aUvuemoHOJfNR + 9IufYueKZGxflIiCnz+BtoWvY/cTv5ow1Rg07gqadtgGTBYkNztlfEqZzL5DRQWYtmr9YQNg1paRfV5a + gT1PzsAu1oGiVYq3J67ERz95FhcPVIVFbEXbZbdS30m1E0BZ6OC9+oUOKvR4jIoIoHWZrq2iA6nZPkqt + mVhR3Di5kSbne79Do826l2l7T0ge6ztKvSIuyQA8TkUFeHRp5kEDYIpJEbOwTJqD6b0xWoIZuDAoI0FN + gLVTalixSSUy+y4VHSCRW0X/B4TWdiLFNAyaWWKRyYwmGscNQ6YmG9YySCroBSv3hgB0Oo4IMO1fqQfM + PyDm4Bl++OTrVC+o0Etq4l1htexQ49L2VQ8Zb8+mS1oNasHyYplFLULTCWNX7a5N4HZZtKYcCVR8ilSG + +OQyU0QLV1saP/WGxJPvWyupVXuxYMWE3qRpSLMTCk7RI+rb0BxKKZ1Y1K1EqopV0dwspTFc34ug74dJ + nzWXzO+l5GV5hwEoC/pCmdByKE03S4D/r/T3ilznDnnRGzH/AWd/Ug8fTNo6AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem22.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAFBsYXk7U3RhcnQ7XWFAegAAAfdJ + REFUOE9joBqYsdOPfepWHyMol3TQvNBZcOo2n39Ttnovn7DBSx4qTDzIbTUXmbTZ9//2C13/J27y+j5h + o2dvxwo3Qag0YZBQZiDWs87j/6P3B/5ffLbo/9qTNf971ri/7V7lVlo51ZYdqgw3iC3WE2tf6fr/yvNl + /08+7P9/+tHE/0fuTPm/9FDJ//blLnfbljlHuYQoMUGVY4LIfB2x5iVO/089nPJ/y5W0/0futf8/8aAP + jLdfavs/a0fa/6aFjica5zs4QrWggrAsbbG6eQ7/j9zt/L/6fMT/Necj/2+7mvf/4J1WoFgXGK88XvV/ + wtro/9Uz7KKh2hAgKF1TrGKm7f89N2r+Lz8TjILXnI/5P/dAyv+2FUH/SydbHUlvMtEGamGE6IQCv2R1 + seLJVkDnF/xfdNIPjqfvD/3ftNz3f36P+Z2IfJ14oFIBIGYFYlQDvONVxfL7LP6vOZf8f94xz/+zDwX+ + b1jm/T+n0/RVdIluuZAYpyRQGTcQY2oGAY9oZbGsTtP/i06E/a9d6vY/o9X4a0ypbr+qvpASUJoHiEEa + cceCa4SiWFqL0f/UBoM/MaU6y0ydJQ2AwnxAzAbEII2YtiID10hF0dgKnZ32gXKgaOIHYlDiYQZi/BqR + AAsQcwExJ5RNtEYYAGkg7FQUwMAAAKo13SoioekfAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem23.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAFBhdXNlO1N0b3A7O4p6PAAAAWNJ + REFUOE+t08Erg3Ecx/Gh/Q6c/RHUSkpKqZVWS7ZysRuSg4PD5kBsYmVkikgytaSozeSgNtthRas1YQ7S + mqgpIiMrNRJ9PB+2evSr5+Rd3/r0en7XR/efVaxGLQFfzHqvXH41ag3Rft0aovEb35Rcqmol0oF8MYPn + tyy4aWWn8ZvKpfRLe+0ofF7i6GYG3DQNlxLzu2bkP9JI5qbATdNwKeENmnD3fojEtRvcNA2XEp7NNuSK + YRxcjYObpuFSYnLdiOxrEPHsGLhpGi4lnGutOH/xI5YZATdN7ZELu9qlxPByC9JPiwic2sBNU/vWcafa + pYRjoRmph2lspCzgpmm4lBj0NiFx64I/aQY3TcOlxICnEfHcEHwJE7hpGi4l+t0NX9snvZjbN4KbVvad + sz7Mhv+4lL7LXjfa7TQ89rgMBZujfoLG46bxG9+UXKpSuWrlaktXo9zPz1TaZecbvlXS6b4BZWorSpXd + XfEAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem24.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAALdEVYdFRpdGxlAFN0b3A7um0gTwAAAVJJREFUOE/N + k89HBGEchyfZ99Y9+huSiIiISKmlH9eKLlGiRCpL2dh0KCKjJNoObYeikl27pcNsNsMeKv2yypASkaRb + 0/Lp/fQ9Rd659uFhvPM8Yw4z1r9ZyXI6nFzJhH0NAvDpspFUVmonWz+9txM8f7hG6GjXZyOpLLS434LH + dwfuQ8wIHbpsJJWp+e0meK8Z5LwZI3TospFUpmYTjSi87MG5nzZChy4bSWUqGm/A+dMGjgsRI3TospFU + piKr9XDuYkhdDePwduJPeI8OXTaSytTYUh3SN+PYzHdg56wXB5dDSF2P/sBrnvEeHbpsJJWpkYVa7F4M + IO62GaFDl42kMjU4V4OtfDfWcs1G6NBlI6lM9UerfTvbifXTdiN2tgva/WIjqSzUM1l51DdVVdQggCJd + NpLK+FmWaco1FQHQofvrU+aPwQM+la9mgg5d3VjWN+pcl7HZeVrQAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem28.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACt0RVh0VGl0 + bGUAT3BlbjtGb2xkZXI7QmFycztSaWJib247U3RhbmRhcmQ7TG9hZPHDxGMAAALOSURBVDhPpZN7LJVh + HMff6N5qtfqjrTURf+hGrWQunY5JLkklImm1mjFk6b5aizWSormEQ8nlHKl2ElEicjnIOTg4pFq5nON6 + HA4yjuO835637GyZ9Uc922fPs+f9Pp/n9zzvHgrAf8E0HYLuDPNnembur00rqE+yKRVzbCBO+k1Dgg0q + oq09SUanLp5NieL3UqI4FiWKZVHCGBZV+2DPLEECG/R01wydmBqToJ7jNBh+2ngdyS2cA6bKeVoBsYJW + NYMeK4BmJA/0SA6mFG8hjLdH1T1LVN21hCDCAoI7FqgIt0BJ6O5yIligFdREWYOeFINW8kEPPQOt4EEj + 50IzWkTEEkIL+U42mGyEZqIepbfMmJtbrBUwZnqiDvQgWdiXArUsFurOKKjbIzD1PQxTX0KgarsJ1afr + ULVeQ47/JkawhrCUsIgqCzUHPV6N6e4EdL87i+ZUZzQ9ckZjshMakhzRkOiA+of2EMXZQRizD28umKIg + 2BT5502Qd27bAFV8YxfGpS+hqLkESbonKfMbKbedVEX6ia9E3gbNDwk5khjTwyKoFdVQy8vQL+Qg28dY + SBVe3oGe6mhIUg+hoziMhAQYrb2KkZqLUAqCoawMwnB5IIY++GHovQ8URWcgLzyFj5G2SPIwDKFeB5mg + KSsAleEsKD/zMd7G+SMoL/DGQL4XBnKPoT/HDb38w+h97oJXflsRYLXWhOL7bkbJbQcIIp0wKc3FYJEv + +kiwj38EvS8Ooif7ALqfOkDG2w9Zpi2k6Wy0xlgg1d2ghVzicorrbQS+/3a08AKhrA0jQTvIMkgwjY2u + Jyx0PbZCZ4olOpLN0cExQ3viTpRd2YL7jusjmd9JcVz1arnHDZF1wghZXkbgkTHP0xBcj43IZHBnMECG + G+GoPtJc9ZHsskF60nS1MRH8ejNLCCsIK+dg1SyYuWUE3VQXPYpB+yj+DVA/AVjcWk79JZvUAAAAAElF + TkSuQmCC +</value> + </data> + <data name="barButtonItem28.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACt0RVh0VGl0 + bGUAT3BlbjtGb2xkZXI7QmFycztSaWJib247U3RhbmRhcmQ7TG9hZPHDxGMAAAfgSURBVFhHxZYJVFV1 + HsefVpNlqS1OqTkFaaNzmkZNxkwFFagQ3FHTSVIzxhgdTc0VMLdxRVBjExCRRUVBSK1EETQW2TdZ3Nhl + Xx/vPd5j+/b93/eePhs6x5lT9j/nc+7lncv9/L6///3/75UB+F3p9sfHSbc/Pk70o8cj8qsNwwLEjZ8g + T3XDH3SIc3HNr1aEYQFPxLqZWmb6mqdk+1lAT5YeXy3xh8zm89onSY/MI+YyLZNlGd7mRByJ1wPSPXn0 + nCRL9yDuWgyHYQFPZfqYV7WUfYsuTS65YUCORFtTPLKPTatxc3hnIK8XRfT8P3hoGg0LeJrVAx13gdYL + 5DygOkciAWUEoDhLzqEu+wASDpqd5PW9yTOPwLMGiL/FVN6fRsMCerFdQPttnfjbB+KWMEB+BmgORZc8 + nEUcQsphM6Qc0nHQDMl63EzJBCS5mhIeD0zAdRctcXvHp4VuGD2FrqeJ6MbDBaS5TwTabnUrRtNJoDEE + aAhCV+NpdKli0aVOJ2kGpOpIMSBZRxKaC08gbve4arpEN0QXHirgmZSDpiwgr3txfRA5jq7aY+iqOYqu + al90VRwhnugsd0dn6WF0FLuho+gAZ3EfG7kb7Td3oi1/O9pyt0KT44T2O+6I2zlW2J4jUgGG41nRMvCh + +3liIYZeXEVx5RF03qO4TIgPUepK6X6039pD6Q6052+l1BltOY7QZG2EJn0d1GlroMlzwRUnE1FAXyKW + 9EMPZe/E/eP58GU9ENfpElfrxd4PxCUUFwvxXkqZ8oYTZeuhyaAodRXUSSugSnSAKn4ZlNeWQhG7BKpU + R0Quf1sU8Ap5nvQi+odS1jt+zzg+fJxLIa7xfyCt8GCbDzOtvsX70XFHm7Yt1wnK5JW4dWIWkr/5AMmH + LIkFktwm47rrJCS6mCFxnykS9k6AuH/kv4wR6WCMCAcjhH9hpAj9/I0gukU3ZM/9yPnp4FpvL/NEW8lh + tN1xgebmLmg4j+rcLVBnO0LNlqrS1zPNGiiT/o3K8//gRjUHdXlnuFcUkyJSyIeOtN7VcZsP7S2JTmUB + yUOnIhfy0micWWpUTLdYFbLnr24bA3XlJSgLXKDI3oHKaAfkBMxEqrcNUr2skeJhhWR3Ky5BJj1oietu + FiiI+Aqapkx0KDKhKfSBOt8FrXn70XpjL1pzd6M1ZxeU2TuhzNoOZcbXaElzRkvqZrSkb0Vu0CcIsnvd + j24xDbI+Mc4mUBSFozHZGXXX1iDN0wattWIJ6RKpmUZ9R4uU6iY6lPlor4tGa74rZXugyt4FVY4Q7oAy + cxuU6V9DIaQpjpAnb4T8+jo0J6xBc7IjYpzfh4ftoDl0S1PQN3rzaDTkBKDi0ircPrkA2cH26FTlQ8Pl + oy5wI65SQnUuE+buo2i3lqz/QJG1EwoKFRlboRDSVCdKN6M5aQOaE7+idDWa41eh8eoKshz1V9fg1CLj + VuvhfV6mW3oI+0WtG4nKhMO4e3oxUtwsURzrgo76a5KsNXcvZbqEFCopVGZu1wrTtmhbm+IEedImplyP + poS1aIpfjaYfV6GJwoYYBzRE26P+0lLUX7ZHwbHZCJg7OIpesT1Lu2K/778cgaKLO5DjPRtX2J7mO2HQ + lARLQlXmTqgyOI/p2yijkDJtW4VwIxOug5ytbYqj8Jo2ZUP0MklWd/Ez1P2wCLXf2aHm/HzUnFuAq44m + cJ82cC2997flFy4s/yvyQ9ciYddkxG6fiPaqC2hJ+BLyuJVo4dwphIy0XN8AeeJ67VzGMeU1tjZ2hS7l + MjREfU7pEtR+/ymlCyldgOoIW1SemYaKU1aoCpuBUDtjrBz70tv0Sq92UcCLkf/8C9J9luKH1aOQ4bcY + 6kJ/NEV9isYoOzRctEN91EI0XFqCxphlaLxCWSznMvoLtpWtFSkvLkIdU9ZyaVZHzkV12ExUnbJBRciH + uBdsiXtB5igPssBNr0nwmz6wgE6xGd1/M750dvFbfGPZItx+GEouOqIlYxvqv5uP+gvzUHeenLNFTeRs + 1ETwxuEkbDqqTk9FFZNVhdqgMtQa9yirCLGQZPcCJ6H8+ESUBZih1N+UjEeZP9+Km/6Ggx8O8KRTvJR6 + Hp06SPhlL5/6ZAiiNlngzJJhkGftR8PlpaiNmIWaszNRHT6DwqmUUHRqCipPfoSKE5QxWYUkm4zyAAop + K6ekTMiOjkOp3/so8R2LkiNjUOz9d56/h8jP3sSWCf0X0im24h5+1uL7Rib7Y6CtEcLsR+Ly5vGQpziz + hUzIVFWhVlpZCNsYzDYGUshk5QHkmJmUqsxPKysVMp8xKKWwxNsEJV7voshrFIo8R6LIYwQK3UfB12aQ + esQrvQbTKdZ/Dx8rbQH9/WcMRvD8ochwny4tl0op4QdMyJaKhJJUCE2ZbjyF45iICX3eY0KBCYq9iOdo + FHq+i2KPURSOJEI8Arfc3kGy03C4mr8aQ98L5EmfjwbIBGL085oyOC1o3lAWMQwhH/8ZwfPIx0MROPct + BEkMQdCcIQgkx23fxPHZZJYxj8YImGmk4w0cm0Gmvw5/wTQy9U84OnUwfK1fwzcWAxrmDO87gT7xSdfT + z3qQTCCG2I/7kP5EvC5f/RmizF9C9PCXEHcXiHNx335EWvt+1q9Jcn0BYjMQa1IU8qiIG/0viP/Rf03/ + 10epGPqvk9+a++N+AfqT34tuf3x8QPYTe6ndyZod4FAAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUAUmVmcmVzaFBpdm90VGFibGU7UmVmcmVzaDtVcGRhdGU7zi+BuQAAAt1JREFUOE+Nk3lIlEEYxj+v + zCyCIBDCXRQKsqCw1TzKXC1TBCPEozQVd8t0M91M88htdSWPzCvxTEoUj1SMtsUMBEvxIjW1tFzNDvNI + TTDXSq2nmc+jzP5o4Mc7M987z7wzz3yMLL02Oy7jMf4HmsswjBrhd4tJfYTFHz8xO7ewji+q+VXmFxYh + TakBWaJBUDtox1FnBaJvKNjk9CfDLOOfv2Jsao6lb2gQlXX5SCg8i0upfIhvuCIg3kLqJzPbH5R8GP7X + zfcx4fEP1gjQhaOTKjR1NSE01RGltfHoGHiI0ZkuNtJxaJojaprz4Cvh5TChcfdZAbrzyu49yn6cj7GB + vDETyska9IyW4PnIXTb2TyjQpizDu+kGuATvARMSW72mArp7VmnidGb5OTx7n4aSpyJcuWXHJoeTKO8M + Qd3rKLQMJcHJfxcYsbRqVSCt/gNGJmbhFmz2pqpBCHm3AOLkQ7B25wbYCwyRUnYCFe2eKGpxgaJHiOO+ + hmCCJJXrBDyCrUP4HtwWG08urE9x8sldb+E56JkfcefcpnMr8E9zcpnA6Ip1R7gqidMli7QJOstsXI6b + CPQbhY43MKKoe2vewczsd4RlOBRfJKWvcCHRMlcgMTUmC7Rpn84FJlm2iBIsfBi/sOL8gMhyLFEG/4hS + CKQmmJp7hU+zPZhQvYSiKQdCqSm8IoyFOZWXManqQ+eAAoJrJs1ElJSxVNJWwjbCdnrjveNVaB/OQ/NA + LhLvCOAVboKbhSLUdxfgxVg5siqD4BxoJCH5DH2SmgQtAj2rLrWnXilFUaMvavvC0Po2Gb1jBej6mI2G + QRmy5T7wjuDhqIfBTgbAKqSxYse8DfKSS52I90aIzLZGbo0zqjt82BiVw4ebeC+II7YkV+tvAfqnaVic + 3HHA9gwX1DorV30ZsauN2PaNWNtq5aYfy7PX203yqEua/xJgq9DZrEkT6JH+tI726Ry9N3JsRv0XgYIz + aUwte3MAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem1.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUAUmVmcmVzaFBpdm90VGFibGU7UmVmcmVzaDtVcGRhdGU7zi+BuQAABd1JREFUWEe9lg1UjXccxx/z + Nsa2Y8NGicx729FJmJcyDRnWJEkSsZS63VuK9UYkTIq8nHTrLDQraREdVskyrQydhQqbQvKWXjgpHbZz + vvv//vc+z+593Ks5nD3nfPrf/+//e77f7/P2PwlRO/JcGYUMvCZIyxWA8F8QIuNyfm1+8gwtrX+h+cmr + odF4BtI0ZGYIYd22HH7ig8ZW1L4ipEFapCk3MoYQEfsTT08Cfurzz2GsbgjqJS3SlBsZQwjfckwvwPZf + bkuIovK6IXQDkKbcyBhC6Obs1x6ANOVGxhC+2Xj0tQcgTbmRMYRVG7L0AsgxVjeEGIA05UbGEFZG/Rvg + dUBapCk3MoYQuP5wm3fgZSAt0lTGTBDaggdYEXlIL0BcwS2JtgLcb3gica++hdPU/BQr1mUyZaEdoWso + n/MAAaxZN8DWkzckjAUQDcsqryDr1D7sTA9C+G5HqGJtsCbBEcpv3aGIHh+0LHLsCGb6BuG3ZcJuZgoa + xSA8gP9a/QAxedckDAUg87t1zcg+fQBrk+YiNS8KReUHUHm/ELXNl/hIc6rTulfUWIXPpk8TfDePw8PW + KtCoDdWOB1BF/KgXYPPxqxLyAGReWXMHSYc2IDk7DKXXj6D6YQGu1WfjyoMMVNSm8ZHmVKd16vOKGoN7 + TSWofnSK/2bmHaQAyjUZegE2ZpdJ6AYQr1ydsR6puVG40fgzLtemI7N4NWLT3BG4bQq+XjeajzSnOq1f + bziBmw9PoZyFI5ZEjKIAHeku8AB+q/UDRGVdkBADiOaZJ1IQnxGEa3XHUVS5C3EHPbAw1BJOKgvFtIWD + RvUx796DRielhR/Vab3kdjzO1+xCcXU0Su98B7eQkRSgkxRAEX5QL0BkZomEboDSK+VQbpqG0xXJKKlR + IybVHY6KYZuGj+nZm4l1ZXTR0tVJNSJpXqAFLt5NQeH1jSiojOCU1CSA6qynM0MbIEw/gByq0xu/P1vN + 3nYFfq9JxPf5KjgHWGD42J69mNCbDLoieq5EJyf/4bjRkIuz1Ttw8s9wnPgjhHO2ejtoTduvCeAblt7m + /wMU4ObdesTuCcNsv2GI2OmN2T4jv2IidCVkyt9qLe0dfIeqqc8QDj5DE7XnaF5C7+DUM49bnr7wPyLa + XB41taLxUQvqGx+jrqEJSlVAdyZCL1N7EnPwGcIGHoDCkAGFo0dDfW9rR5rT1fNzeAAPVeISz6B9JT4h + B2CYNCwPToOL0hUzvQcbZIbXYL656CCFmOJuPmPGskFZvG/ZILW1fR8K8u8+wA5q7MbowXjPAO8zen3h + +RGqG5NRVZeoB9VojfVwUfabDZpHYTXlw3dneg3G0cIQ3he3fyGmLx0YRL3UxwPQnxehFetgv3QgiqpC + kVOhkMi/GgCqT/MwV5OhtpffAevpfd6Zuth8few+Z5y7uYbtC95YFGwFO7cBfHtm52n05YZyqJnRaeri + AThW5omU35w4P5xzRvCuSbBfYo7JrmbLbeaafjzEukeXz+abjbBz6+9F9Zi9jsgvVyH70lKs2m4LuwVm + fkyLb0JMT6MvN5SjDdD5c/f+OHJxEZKLHDgpZ+Ygt8KT7fnuiIy3h/tKS7oTfKT5wXwPFFf548iFRQiN + t8XkBWZ0l+iT5V8A09Poyw3lsIPfgcluZjhcOh97i78E/VZEWyMhZxbyLnvgTJUvLtQEoOxOEB9pTnV1 + 7iyotoyBrUu/xE9se5qSDoM/Kqah0ZcbymEHBeg4aUE/HL3oAhonOpskj3PsG+ioHAL/raMRnW6HPQWz + kFEyh480pzqtj59r4s/O1/v8mIZAcH25oRw6gdHBZp6J2na+KZknsTl9Nd0sp/a2Gj+nb+jEeSbHbF1M + b7H1v2mkOdWtpn9gyfpoe5bMWY8gwvXlhnLoJAbdBXp2JCRCGw3B93/GWzrQnJ63uFNycxsXE0EXri83 + lKM9xBBySJgM6M3WDUdz0Zj6njN/2QDiQUF0D5qL6AaT6oaMRbi+3PD/BcI/rFGhuJ5JxAAAAAAASUVO + RK5CYII= +</value> + </data> + <data name="barButtonItem2.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAANdEVYdFRpdGxlAFJlc3VtZTsw1a9vAAACgklEQVQ4 + T3WSW08TQRiG+0u88A944YXeiIoKGomSqLHGgIByEAsJoCByCETEAAJCCS2nWjlUUQzRaIRgAUHwgBdo + YjQxHggHASktbFv21L5+M0sZbtzk2W92Z99nZmfGBMBk7f+Iu0+mUPfoPWp636HKNYnK7je42TmOcudr + lDpGUdQ2jMIWN/JtQ8hrGkRO4wBFYeKC+r4PCIXBCUegDsb/LkvdC1YMQc3Dt9AoPf/rG7pLzSiN24Hn + 1lwShoVwm5SRXvWU7puCyp4JqHoIblcDrFdiUJO0F2XxO6GTdDuhCGRLudUvBOXOMchqCKOP7ahP3o3R + BjOGbHmQFZWLGZoeFpAkoaxPCEo6Rkigc2am3RhsyMTXyZdQNAoTkRqRMczFvUJQYH+FoKJheGwajh43 + pj7PUx3GyPgnPjOZwrKmc1GE09ddQpBrHYS0oSHNUouo2DxUNI7xmpZVi4Cik9xgQwkZkDT+apcQZNOW + rAVVpFruYNeelC2Y0C9rnICsb8FkJ3I6hSCj+hm8fpXjCxisMUi6vokU1PgsI8RlO4WAbYlHUjhev4JV + oto1gdtd46igk1hGi1xMp/BG8xDymwbgpe+OWe4JQSJtycq6bCDJJGKoXMRgUh9vq/CsK1j2yYi93CEE + 5qJe/pKzZpBQ8gDni1w4V9iDswVdOHPtPpao/89qEHMrQRxOaxeCU/ku6tgw8BosEiyw5KNK7QVidiWA + mb8SfixKiL7UKgQnaUXnPEHMM2iEBYKNxELsec4TwO/lAH4u+vF9QcKXWR/2J9mF4HiWkxbFgaOZDv5v + MRntOJLeTtNsw6HUVkRfbMHBlBYcSLZT0IaoCzbsS2ymKEz/AM6IRwuC4ZWaAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem2.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAANdEVYdFRpdGxlAFJlc3VtZTsw1a9vAAAHDElEQVRY + R62WB1BUVxSGbYklmphojGUyMUaT2EsmAYkaUGMU+ygiIE2kKYqIBaSpiNLWYEOwNxARREFiiSiIDdHY + FaSJSO+96p9z3r7Fpe1OZnJnPnZ58/Z+/zn37t3XDkAj/9NorwBhNHH+B3nzyTo0o2MrdJKD/+f7hKEw + wN5zD7A77D52hsbDJ+QedpyJgyT4LrxO34XnqTtwD7yN7QG34HbyJraeiMWWYzew+WgMXA7HwOlQNBwP + XsPG/VGw84/CBr+rWOd7BbZ7L7OEgwidUBSg/a6z8XRJ+Xgvg/405x39kWf1rkss6UwIXaCPtRmgA1ct + P2i+NkVMc9m7d1Ia5Fjl8xdLuvD8LKHpWg3A7ekoCY5rVXQl+ABs5o2F1eyRsJg+DOHHd7cQNaeeaXiP + FZILLOlKKA/gFXRHEMpXdZnkvus1ER+0HHdOmCLMeyHcLdVhr6uGhEdxTWQy6hreNWLpFcGST3h+FikK + 0Ik3WfPKVs8fK8hvnzDDOS8tLFUfhLVavyBUYgDJOsMmMoF6KbUiZh7nWdKdUBrg4220u2VioSpi5ayR + iPDRgemUIdi8dCpCPY0R7LYETvqq2LZSu1EkTw1TJ8VkWxhLehAKA/D6dHY9HtuihZ5r9GCnNRGFybfw + Puk0am+74M0ZC1hMG4GHcbFNZDV1DQLVMmobYOx6liWfEfxVVBigy6YjMS1ayDjoTEZ+Ygxq73mgIsoW + KQEGWDVL5YNIlFW1gv7mEJb0JJQG6Op86HqLFjL+m20QHeCNymhHlFwwRbjjFPjYWbaQVdbIqEeFiJ5L + MEu+ID5iUVsBeH26Oey/1qKFPPHNS+HwsJiLOwdXInr7DDjPH4XrEWdbyBqprke5yGLH0yzpRXCA9ooC + dLej45MnlVUU9zABy9dJMEx1MTRUNeBoOBsOBjOhNmY8Bg6fCSMLF8TefdIoY8qYKqZOYJH9KZZ8SSgN + 0GPd3ivCh7mClIxcmNt6YaqWE1SmrYS9uS4e01eRsTPXwaiJZhirYYXFxg5ITM0UZKUyKutQIrJgfQBL + viI+JtoMwBvk0zV0bhdV1AoT+B8Px++LnDHH2BuzDD3x/ThtvExMExg0eiEmzHHG+JkOGDnBAj6+gY1C + prhCRi3mrT3Jkr6E0gA9renczi+rQUFZLVQmG0FthjXU59lj8kInjJlkhh17AokADFU1xk9TbTBigjm+ + G6ODwcOnCzIOL1AupZCYa3uCJf0J/kFSGOBzKzq3s4qqkFtcjYDQKDi4+mHJMidoaJrix3Hz0H+IJvoP + nk5CTaip62GBjg1s7SQ4FhgpyGQUMFREARUzx+Y4SwYQCgPwBunF53ZGfiXeFlYhu6gauSXVyC/ljtSg + kCaUr6yJUJQx3EEB+lweMcv6GEu+JpQG6G3mfh6pueVIz6tARoEYhLqRQ0FyS3jSD6ICmlwmksny6B5+ + 5Xs5PDNz1VGWfEPwT3KrAfh3gAP0MXELQ2JmKVJyyilIBdLzPwRx8Psbdr6XsX7PRazZGYnVOyJg5XUe + y93DYO4WimWuZ2C86TQMnIOQw6EJDq9pdYQlAwmFAXiH9jVyDcWT18V48bYUSVllSKYgaUKQSlqaKiEI + 75HsYtonVB13Rl7GZNHS8T0ypq84zJJBBD8TKAzQT98lBPGvCvAwtRBP04upG2VIyi5DSnY51u+myn0i + YS2RVm5JlZtR5SZylS9xDITuxpPIpKAclvnD8hBLBhMKA/AGGaDrFIzY5zm4m5iHB8mF0m5klCCRupGU + VS4sjdAR2iNvaGl4eTIKRJn4Kr0mhe+ZZnGQJUMI5QG07YNw9VEmbjzLwq2XuYhPysfDtCI8fVPSrPIQ + mGzhyoNh6HyKKg8QZG9oqWTwsjFTzQ6w5AeiG7vaCiDsARufi7D2jsQKzwhYbA+H6dZz1I18oRuPXhdR + N0qRQPtD1pFkWpqUnAqhK69zK/E6j6H3Inx9yrL9LBlKtBmAh3AS6m/YZ7o16EkNXReGEe2JG8+zcTsh + D/eSaG9wN2hvcJCXHIT2yCsOQ0E4TKr47WExv6ZSOA0Tf5YMJ/i5sGUA4R/xiYjoo2Pz53IKUU/XoecQ + jCv/vMX1J1m4+YL3Rj7uczfSivGMluW5GCSBgnwII/32cCBG3diPBSMIhQF4CA8lRD9ta4kVh9DecAqR + 99Jx+UEGoh5n0d7IkXbjFS1LinSTPk2XBpF2pUwahoJIl6kMvxntYwF3oPUlaLwgHU1CLLANwLgF2/Cz + lgdUtL0xXncHfl2yExP1d2OS4V6oG/kKFaov9YPGUn96Txj5kZTZh0kG+zCRoPm+JVo/iOQRh/B8SPQm + +ATjHcybaBjBlTDcUmakyCiR0SJjxFe+hw8h2UOp4gAM30RwCD6eOQi3jtevOfysrwy+jzvaRA6g3b8K + pIlQ0/k9uwAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem3.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABF0RVh0VGl0 + bGUAQ2xvc2U7RXhpdDsFGf+FAAAArElEQVQ4T7XSOwoCQRCE4c0E8XEDQTMRA+/gTTykGBuYGm6olxBE + tP1LHGl1WoZVg2+DYrqYZrYys6/cPvVibk38teBUkkUFNcbYuGyFCXYuyxYcMYSyPlSi4fY9m+KMsECW + aEF5D2m4gzUeZ6MC8SXZYflU4K8taZ2nc1GBH+4i3eStJFdwwABpWNf268xwQVggW4zgd1aJnnbvsrBA + 9JyvWfGPVOx3Bc1ZdQWpA3U147gCvgAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem3.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABF0RVh0VGl0 + bGUAQ2xvc2U7RXhpdDsFGf+FAAABIUlEQVRYR+2VwQ7BQBRFrfwPIUQs/Ynvk2DhW3wE4QcY90pGbseb + dp4wNl2cRV/HnFO0HYQQ/oo5rIk5rEnj4LhehRqosw/oA34RcDNmDdTpCbiCJTjILGUPFuAiszfUWRpA + +RRwzRBYEZTzHNdMQDZCnSUB/Ep5VTwfSSNUHuFn7kD3eqLOkgCyAakgRlhyHm+BtRdU/gCSi3DJiTo9 + AcSKUDrlRJ3eAJKLKJITdX4SYP3mMaDtFn2hTm9ATh4pilCnJyD3b7dmrRHqLA1ou9XablFrL6h8AXyY + zEEq2IG4xoqYga89iM5gDCx5RCNG4ATSNU/UWRpAGMGrsuQRRnBNVk7U6Qkgna9a8LPX8ddQZx/QBzQC + /oE5rIk5rEcYPADSsjauYx6lKgAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem4.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAddEVYdFRpdGxlAEFydGljbGU7TG9hZDtPcGVuO0lz + c3VlwgbP1QAAAIJJREFUOE+lkQEOgCAIRb0gl+kIzUN1gM7TDRiBG8wlitrf3jKCp7NERL+wRc6ZFvAF + oyBieTYCfgEpqADOq4vEE5SCCqKEAm9nRRIKooQCb2dFUvVPn0AvuYG/uQJgrOm5D2CoA3wF0jwaaKgF + y8OMnWBrmCl3sD0s2P/cxS3OQ+kF2uLi3IrZfvEAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem4.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAddEVYdFRpdGxlAEFydGljbGU7TG9hZDtPcGVuO0lz + c3VlwgbP1QAAARFJREFUWEfdkkEOwkAIRb3gXMaNe9MLufMArj2KVxj5BpKh+dh2xtJEkpcCKZ9P01Ot + 9VBoMxPazIQ2M6FNME1T/RFU36BNgOHR+C8D5XpfRRubDcjLxYbwHA3TkjTEFTpADbBrGW2YlqQhrtAB + aqAnTEvSEFfoADXArmW0YVqShrhCB6iBnjAtSUNcoQPUALuW0YZpSRriCh2gBnrCtCQNcYUOUAPsWkYb + piVpiCt0gBpYiCI4LbC0HLii0wCWg/p6nLdS1hqgFyq9yz84scBAkRcBFRhk8Qvsulz4+g/svhxEBsrz + dtl9OWAGUi435gZSlwNnQBqpy8HcABseJVwOnIEjoM1MaDMT2syENvOopzdUfCMZg5IrCQAAAABJRU5E + rkJggg== +</value> + </data> + <data name="barButtonItem5.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAADh0RVh0VGl0 + bGUASGlnaDtMb3c7Q2xvc2U7Q2hhcnQ7U3RvY2s7U2hhcmU7T3BlbjtDYW5kbGU7U3RpY2vfps9tAAAC + u0lEQVQ4T2WS2U9TQRTG71/gg4ka17CIAQQJFGKRUpWQGDEa0ZAYVgFFRaAUShSBIkgIMSCr8UkUQSMi + iBsFFYqIPgjiqwSJ0aggSymFbrfL55mprTE+/O45d+Y735zMGaGl4+MggeZ2xgSn6Y6bD2hsc9FwmzGO + +lvjuNY6xqm7+X5QqL7xDk7ABX088T+cfwAcHCcqmt5AqLr+li+aLXaYLDbsP5QBI0WWs2ikdcZoTCxW + zTYPDnIpbxiBcKVllBu4xXsPpsJIAgYXm1y8lsdgxSR6sJOBun4YAmuDteNyFhEVm+jJmXAiRwFtlBza + SDmGIqMxdi4XBpMVdrsDJXVaCOr6Ed5OVp4aEfJ4hMuOQkKcyimBwShiUCrDQmeLi/vNeCGRQr8qQiSD + 4qtDEMrqhnk7oXsO8w39qpUTsjsOyxQHwqSYaa7CdF4yfjZWom9XOPQrVog2By7UvIJwqVYLm92J4IgD + /xjslMTy+DxYgh+1pficfQLfay7iiX8IdAYrrKIdRdUv/xoEhMXwjUVCZ7DAP2QfN3hMBd8qlJg6fRxf + y3LR7Rv4rwFrw0rtpGYVwi9YBr+gaGwPkiE5M5/MLOjxCcQXVSYm049gOj8NnVt3YEFv5mNWVg5AUJGL + RXRgcdnCC5jBAuUcEj6ggqkzCfiUEofJzHjc2+iDOVo30pQUlzUQCqoGYLbaScyKzPAOkGKe8nkSsdif + kIK7G7zRsd4L7eu8oDmWhLklEx9xbnkfBGVFP39EvGDJjG1+4fyEOcp/MXQmTtvaLZilQgb7N9CFny99 + BkFRruEPxy3e7BvqKZrVmQkWTWhds4nHmUWGkV9wdgkZ5Kj7qB0bfzRulhl0AsM9Vg7Nf2nFQrgmdbb4 + KYSMol5NhqoX6apHOEmkFfYgraAHqcpuTnL+Qw9JCjddSMxjdGl+A9CPKMzp+HFyAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem5.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAADh0RVh0VGl0 + bGUASGlnaDtMb3c7Q2xvc2U7Q2hhcnQ7U3RvY2s7U2hhcmU7T3BlbjtDYW5kbGU7U3RpY2vfps9tAAAH + AUlEQVRYR71XZ1BVRxgl9t6ixti7oiIi9oINg8bYYmIPRkYMqKCgxgKKDctYYsNeQTEiYi9j7y0x+Zeo + CJbM2AUr71G/fOfb3feudcb8CDNnzrftnLP3XnbBRf/kYuT+BOT5j8irgRo6nzFcckUnXD25Zfef9DHE + ALvegwTwHxQNJHwYm3caXBVsiLtySodwyb1hx+/0f/+sjr1E7I2n4ZJnfZwKkJGRTekZWRqmBluhxu2W + OajtXNvT9Rjzx5CTk0Mrt1xEgHwSYO323yiHA1gN3gcxEVaQ/rfEbe9hW3qmboMzKZsDrLAGWLPtCqci + LYqdqN0AV7p2VTVMtYgZ+6pXgDZg2JWJmNmz6GJnH92HtuozYwgQFX0BAfIjQN7VsZdVAIu4SpxFl31Y + SPcbAWPq3WO4qtkgjfvTuE7Thhc7dlZ9MubEawTIzqFlm887A6zaekkCYKGdYQxgdskbAZSQ2okOwej4 + jZ8yfY/RufadhF8DNsVpYAYCLNl01hkA7wMBkF4JKiPw+Q7ezG8aBP88h7y6+JKXzw/UlhE0PtJhojiD + zni1V7Ugw8Gv0jIoiwMs3nAGAQogQL6omAvyZRoDEdI4266jSo4xZoy36TxIiWnh1t4DdDuTrgYG0YmW + behE81Z0vFkruhIwSvoxF3hpAqw/7QywPPq8fBgQExMGdoH2qTbthA0g1qpTf94J1ywGtOjQ19E+1rQl + 3V81jx6snEv3V8ymI57NxdTMRZ2ZlUOL1p5CgIIIkH8pvw+8F7MLtTNVYycqfSa9xBgLNG//vQgJXmdQ + s3Z9HO0jjVvQPzND6dY4P7o7I5QON2pGL3iOmfuCOTMrmxassQRYskEFkJQwA2scbdKCF8NcizCaen0r + ohADe7bpKeIYO+TelO5GBFNyyI/CB9w81VwLEGD+qhPOAIvXn5H3YgwEWhA7MMmxGLVn6x704pUWZPZo + 2d0hfrBBE7oTNoKSgwfT7cmBtL9eI3rOc57zmEFGZjbNW3kcAQohQIFF6047Ahghq6CpsRjs0bKb1M8g + zHBv3lWJc73P1YNuTRxOSSMH0u1x/rSnjrv0Y65BOgeYG3XMGWAhv48s/jCsJueGDJP0+10biehZ32GO + nTRs1kXVr9JF0K2JDz17qcT31Haj5NChdDOgHyWFDKVdNetTqozxXD0Hp+2c5UcRoDACFFyw+qR8mUpU + YU8dN7oXFUn3ls2ie0tn0u5aDWQxTOt7erNousKLdKrXuJOMpfJYQo0GlDxmCCX696Gk0b4UX62eBFDz + wSpA5NIjzgBzoo7Ke3FOhFA9ujsliJKCBtGd8JEUX52F2Axw9ejAbKcUroG67u2ZVTu+Sl26GTSYrvv1 + oqRRgyiuYm09j8efK8bJOu2XwwhQRAJELjsiqZQBh2DeUdWVbk8MoMTAfnRrwnCKq6SEMDbEfyzVaehF + tRu2pVpubcnXP1SZsMF2NkwMHEDXfbsz96dt5Wtwv52eaqDGyRqx8KAjQKFZ/DhUADul8gSYbK9Qk5LH + +tEN/+8oKdSPhWqqHTBEiOciAARN31NmGCYG9KVrg76mxJ/60tYvqtETGXMCB9qUBRKgqASYsfgwX7fZ + ahfyqOy0tVx1uhnsS9eH9qSbowbTlrJV3wgAs5oNWr0hDMTyPIT+u78P3RjWh2LKVKYnz+waNmEECF9w + wBGg8HQE4L8BrI8qpkwV3kl/uja4G++kH8V8XoWe8mIZhxhzddcWIihtgY22lK7M7783/dXXm8P3ouhS + lekx9z/m8cepYBsfcJkUNm+fM0DEokPyYRgDiB/qPZCiS1aizYIKdKDnQG3CQpqr1m6q+iCcqgJgHdZs + 5DWbSlSUdRgDHul5OFnD5kqAYghQZCp/EPgwzC4Mw2hj8QqS2hjLLjQq1/J8p8+YIYAxBFuBA2/SnL3O + AOHzD8g1KyZYBEMwY32RcqpPoMQfCduoYg0P4bcNgI3Fyus6Tfih7gfjoJs4WwIUR4CiYfP3y4dhxJyG + NlpbqKwWehcVqrnrOk0bGFbBUT+UPtVv2jhNJ0TutgSYt1+uWyNsRMCr85d+p9/gy6puImiErTWCP0ix + 0QOuH3Af+CHaKSrA+FkSoIQEmDx3r1zDVgNTO0U/VIPZhIUd0G1jaO0DUvnYHjdzlyNAMbwPfJlOcS2s + RYSNKFiPKUGLiaXvvq7vP2VYxlDjzhg3I8H5BCbM3uO47x3gtlyxFjwT5luNgUtJ3YYKEJV7xNTWPgGf + sIwUrlOYQ6c7AxQMDo89PXbGLhrLqRR28oSdFMKTQqbHU8g0RkQ8jYnYQaOBqYwpcRQ8NY6CmIFR4dsV + wn6lkZOBbTSS6xHMgknbKBCYGCvwG7PuLHvLbYh/zfGnEX4n8VUCSPYpKPkJKMXAGjZ3yf0v5lEIxo9w + NgwAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem6.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAetJREFUWEft + VltuglAQvUtwCS6hS3AJBPovS+gOdAf6XTCIpt/6rSa4A9Sm37oD+YeGztBBXoPci5qmiSc5QeHOnDMz + l4f4t4gdrfs91wfhTB/hbzr9eERzQ4tmxgIYl+hFrtGnZfdFWm3k6kdGuEhXP0cz3Yk/tBcKb48r1Uox + dA0fuwIFdChlM5SqlaVMV1AYFreuVpbYlXD+2iPZIhITrjGFhUE58E5c1orngTODlpnAE5NElUHo6kMs + jtJXsVqtxpvNhr2F0DF1hUteS3g+bLEISlPEYWKKvT2mf4mB7Xq9joFn4MDzvIpb7ApW0tCVAM2ym813 + umI/GYidfQbxWOytLV0pGLgQzjlwZOdFt+cyE0ZTuokmaUmGT6sHootf0TwbDKSEa37deHCu7KbynQ6I + 9EH4WBVOKWkgx9rxXJC02Rplbb5GdQMXVsZzsDUQ9XihOt5gICWFC16giU8DTwNPAzkDkGxYTi5DCm9p + IPcywqcbJ9BECm9nAJ+aeUBC5S5QaAsD1htFFgFJlUxQmKIBa0hRPGgcaCTIi3GkEFkDU/H1rvapDneH + CUKnsnBKWlZvYGefknbj6/kWgFiPu1XpMmPAWiYfIvcGjgeMTFkDOyuA47iyux8BMNIBA9lmwo/MW9v8 + NxDiB0ll6Er6pf7AAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem8.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACV0RVh0VGl0 + bGUAQyM7Q1NoYXJwO0NvZGU7TGFuZ3VhZ2U7UHJvZ3JhbdjhSgYAAAJeSURBVDhPnZLtS1NhGIdvKHrR + XuxTQX9E9CGCCqwkI6OCjDATBGORNItlkkvFbMZCw2rVMjX8kBhtiiSDMHwLE1TKt75Ef4I63dycO+ds + +3XfzzM0KvrQgYvfeZ7nvi8O93Oo1Tcz1Ob/hjb/LFp9s2h5p2l+O8NM42XnNLydU/B2TOF5x6TC8+Yr + nrRPDBPRRmpoGcf/PPXeUbBgE7mbx9TGqpH4BxZiv7ynUinUeT6LYDPVvxjVgvh6gxTHZM1IFrQRp4WL + r3QmkynUNH0SwRaq84wowQofrHDxGquy1uR7CVFen3+mM8ECZ+OQCLZSNZvkkYM/iFk495Rw9jHhTBPh + 9CNCXgPBSqRQ4R4QQQY5GweRYkGEi8d/DOD66wPIdRFO1JHaM8wETj0kziROPpBMsCAJh+ujFlS4+3ko + wPKKiQuNezD2vR9xLhLCURO59wk59wjHawnHagjZVQTTSqKs9oMIMsnh6lNTDXHx0bvEIguhiJnGUEPN + dpLKI3d0iry0OiCCbWRnU5IFi1x8uJw441jid1kvLsdVHkrvH3QQgstaerWyVwTb6VpVQE1VDvKq96Lv + Sy8WuDHISApyE8HwqsqFdJZU9IhgB9kq3yvBPB8MTgaQU74b+22EfVdI7c0x8yFORmcMEb6h4lvdIthJ + Jbd7YPJUpSAYjvPkzbVrlOK5JYEbFXotAy+62SWCLCp2dMOwEtzAjdwsAgUXSaHGUISFqMEDN1Bo9+sv + KCjtGC660YXLCr+isEzwKS7ZBX8618m3tY+wIIPh31GGITZN1m/s+guyn0lEG34CawLqBpMPrkgAAAAA + SUVORK5CYII= +</value> + </data> + <data name="barButtonItem8.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACV0RVh0VGl0 + bGUAQyM7Q1NoYXJwO0NvZGU7TGFuZ3VhZ2U7UHJvZ3JhbdjhSgYAAAZ7SURBVFhHvZf5b1RVFMdRYTp0 + QdQfJDGiiYnxDzBGI4SwVIEo2kArixVZStkLXSxdmO4rZWlLgbZAy7RQClrWUkGgVJaKRUFUQiQQKcXS + Ykv3ma5fz7n3vtf3OmhiDL7kO+fc+96c7+e85b6ZYYbtqf9Zpo0nniYNVxrxD7L8R3GNZ0g6hDDfWlg5 + Oa/kcs3O0u/ByifRGLn7LmMHay+puBrbSduKLyGn6BK22i8h234R2YUXkEXKLDiPLaxd57F517fYvLMK + m/KrkJF/Dhl5pNxKpG47fcWWXuZNnjoEfwxP21H54G5dM570dqe2CbaMigfkyWdCBxhBAOKA3t5+dPcM + UXefVI+KhrGTolE8b57rFdHBcvZhYABYn3EC5OlG4ssuACyp288KAN1ERWOxvysuRMV5rBlpkffpc85e + AhhA9AYBYDUBpGw7IwCcbDzE3JhzMT2ngg7dlKIwVnMq79LmRexFPwFEpZebAPjDLTlHAWjFDSZyjqOS + 6ozjYHEVhWmfMqbcIaOWM0BE2nEGGGkCSMo+bQYQxZQJFWUDaShzY1GjYX1zHT7a4I4/mupQfbMCn2W/ + qo7pkQD9BJB6zBUgIesbAaBfLxW7tLHBuMshDYW4uBp3ki7eOI4F215HJ80XnUtETKmPyKV6BEB48lEG + cDcCWOMzT0kA0c2ggRjTlzscTlTdsiOzygerD43B8oOjkXhyPAqqVxoMyLQyAfEH/IRZ3H4/FJyJE/Md + NO7s6kEfAyQdcQWI23JSABg70jpsbKlH6ilvBOzzwqK9nli81wuLiyknxZ2YIAqzpsdbMY0VZ8XUWKn3 + Y6x4j9RB+1kMEJZ42BUgdvMgANOLU0p5O3WeUD4JC4u8sMDuhYDiF7CjKgDl1zNhrw5FxfXtEoC+00Nr + xifpr+DCr8cJugHe66140HxfPFXtBoDQhEMM4GEEGBmz6WsBYDydrLM3izG/wBP+uz0QaB+DWw0/iidB + vwlJWnd1D+9hSpQbxTpU/VyOWcljxXx7pxID9A0gOL5MA+DlWALYNlZIgC5ZkLvqoDytwgdzct2FDv+w + UXTaoYppxTlOjnTDpAgSxYnrKJImhku1dXUriG709vVjbexjANbT6sQbF2NjqR4EFo6FX7Y7fLPccaOu + Ru2XAEKqO17Adp1MQFShr8gjC2Yh70SsyNvIuJWOaSPxUr8m9isG8DQCuPPqpAFo3bV2OuC71QqfzaRN + VvzeeEeYcSGj5Fw3wvJmIL8iXszNSngNldeOSeMOAlDqIYCgmC9dASJpdeLNaMAgflmjMCPdig9Trfjl + 7hXa300Fuag8hg1auUMqPsP2MiqvHkVtw32MW2tB7YN7ujGrRQGsth10AfCISDtmAJDXjA2CCt/CtEQ3 + TCXtOZMkzdhULzwIwGuGgKKcV1Nh2k772p0itlDkJ2JV9AEG8DIBrEs5KgDYXJ4BGQvPxmLKejd429zw + QfzzuHa7RhkPkTCQXUozsx4pCYAoMwB/eIQnHxEAoiND4YZHjfBJfInubAsmhFvobveEzf4pth6JQlJJ + IEoqc5SJ1qU04vGjNiUxx9EpzsyKyFIGGGUE8AxL1ADoy0pafvX2d5ge/SLGBVswnsTX9901pCALQrZ/ + LItrZqRmZdqsTDnyHIvfMSsi9rsChCYcFgDSnLshcU6FGKTx0UNkl0XAP+VNvLPSgrdXWDAz5g2k7Fs1 + aMrRYNbc5hCxSY058pt12boSV4CQ+EMCQDtV8lTKXI6d8vEUy7T2VqS1gu6TQcNBNbVKQ1Mk8cq5LFwA + PGsE8AqOK5MAbcqYo6GgJjEnijpUUerSNJZzQ/Unq8UhlvfAL/a5AvDyyJtuRhBGY01GY9nZ4JhNdDM9 + d+rmHIcA8H8QCbCGVicNwHjNTIaioCyqjZtUYc3AlHMU6sJDFTsIYEnYXleA1TYJIIoqU0FPEFzMaK4b + 6WM5J03M8aEyZzUyAN1HAaGuAB6rokvrb/xWL3+K8euWYhf/wOSoXrtDZXxts7g7k/iFRjdtO4uMWTU/ + 1WJRsL2ePE0rodvsgE0zA0LsDQGhRURYhMUhRXTgHixkrSUFFeLzoAKl3Zi/ahf8hXbDf+VO+C/fiXkr + 8jFvudTcZXmYuzQXc5bmYXbgDsxeIuUXkNM4zdfmR56m/wVMwv9U+AXBzyefHqNG/0s99xhp+7hzNmdP + 8deMN06Yhie1f8hPSuzBXuQ5bNhf26SvAjgfskIAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem11.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAA50RVh0VGl0 + bGUARW5jcnlwdDvJzO8VAAACI0lEQVQ4T32SX0hTYRjGLeScq7oJb7pIp0QUQRSWEHQh0V03koX9szaC + SKUFEQqGZy1YiJpYXewukKSLQHdTrW2N/XUzC9cKnYhokUk2c6612TSe3vecnXWmsxd+HPZ9z+/5vh1O + iXbqzhr3nG68NUgs5xjktdx2fgDkyU/dOePeBn1bon/Ii+inBCKzP/D4mRu8xnu5mDzFCrbWX7xp6x/y + 4Ln/AwwtZhiazbC5x2B9YgfvcUaJFi8opesm+WSWT5y8dIrRN99BeGIetJfijBLdWLAl1nskONVXg//B + Gc6ysL6gNNZTjcxcAGupSfxJTRTAaytfQ+AMZ7WyWiB8tBxANu5BduGV8oz7cniR/e7E6mIQsb7jnBaK + FYhj0j5kZp/i1+RDZGYGcPjoGRleS09Z8XvegeR0CJGaXb3vqkSMVolSQcFI626kxq1YGr6BxEgrDh46 + JrMy58LP6H36G18QPb8fLL8hwpUigpVKiVzgv16O5PtHiLsMiDv1MulpG93AjuziOD5LDYpMYojEgE6U + vDoB7gpBkgvcV3fim+8BEqPdWApbClhLL+DtPxkBncCyRDKcBBcILxrLQo7LZSjG8kwEvtrtGCbZT6d6 + iNckOgh7uWDiAv5AthE7NqOp/V7nQG21Xyu/JFl9B/xxcIlAiOu5drvzboupB00dXWZXhWDSymrBpnOl + zSIRIOSrqqPKcoH2h5YLxg6JAJE/bSMo+QtDPgGILqbtFAAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem11.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAZ0RVh0VGl0 + bGUAqO7SJwAABd1JREFUWEellnlMVFcUxp02xNaAMsMAarRqVEyIFdyb9g+1S1I1xKXRulBcsNgiUVux + rbKMdBQUZcQFBEVcKCqoUIUWbYoFS8VBUBDiXnCpRgQEZEQRzddz3sww78Lw1Pglv9z73XPuOXcelzfT + BUAbnUi1zrB/1votB/I2bD1oYnjOaxwzp3SUvK4Sommn1RHxfXVRu9cfyshF5cNWAV7jGOdY0gXJ6yoh + GlFvrQiJjT51uhg3aluQkn4CuvVJEjznNY5xDueat9gkr6uEaGxS+S/R+e7YfRTXqp8gOGwLps8O3Naz + 13vjGZ7zGscSko+Cc3mPeatZ8rpKiMYmB7+A0IJLd03YnpgGny8WxdBaf0JroT+vcYxzOJf3EG2S11VC + NDa9O2fhKlP5rUYsCopA335DhtJaN+JtC9169xno6R+4BpzDubyHaJO8rhKisclxht9KlFbWg0fyGkL+ + d+a5pl2OoxSxSF5XCdHY5DR11jIUX6sFj+zNy4IUc+R1lRANXaTS6FE+V2PH3r++ZSxeB97De7nGmxzA + 4bJh9P07hxegpfoUXjy+jhfNVS/hJp6bbuLRlRxUpcyt4RpvcoBulzeOxJPbmXjeWEKUEaUvgXKaKogq + 1Br3cRG+rEJdJURDF6kiyhstd9PRWleI1obzbfydexSTpgRI8Fwea224gBemf1FTmMxFpMsor6uEaOgi + lenfx5NbqXh6Ox3PHuTjWV0RWh8WY9LUAIwdN1eC57xmRcppKMedLB0XkS6jvK4SoqHN58M90XxjL5rK + 16H5+m48/S8bLffzMJmafjDOV4KfwrOas2h5cEaKSTnkm26WYP8nH8clDfHA1p7uP1M9u19WQk/B0AHO + rfKA6eouNBi/R2PxT3hUFgnTlUT89es2TPTxx+Qpi5CXvYvuyXE0V6ZJscfXkvH88T3kBk3G78OG4VZI + CHJojHV301PNDocQegqGDlAYPBCmijjUn/7WQiAaCpaioTAYGTuW48gOOtg5HRqNIdJaU2k0WuuvoMTw + A7K9hqGKmpePGSON7O0dQugpGDpAwbJ+eFQai7rchR0I/24ewpbPo7m/RGNRBP39L6EocgGyqFllaCjO + eXoiQ+2MgyNHoFynk9Y3u7kKhxB6CoYOkB/YB40lMag54YuanLkC06f7SfC8/p8QtNRWwKifh2NeXrgR + FgYjNT+iVmOdqzbZx9Hxo6QJE9Iv0iGOeXvDIDuE0FMwdIBTAb3w0LiVDuCP6qyZqD4+owM1fyymS3cR + ZyN8kenthavh4SgYOhR/du+OBFctZjs5jaRa6llOTqNSRwyX4pnD6RCuWukQQk/B0P/wifluD4ojP0Nd + oQH1hZGoP6O3S2vTPSQOGoTL9Anz6MLlODtLHNBosFGrjf9RrfbgkT3HOS9x8GBu4iD0FAy9xWI+77Hg + N19t7Uk/LZRoqCxF0mgXpA4YgEx67MctHCNSXDSIoyfBI3uOc95aF80m6tFV6CkY83ucv3r5x4fHS/Ak + RkeN//RCklaLwy4uyLADr3M8QqPZTPlcW/EJ8CXhQ/D7nF+p/FbrjB5r4/ZuSsvJR9LXgdhJTQ66uiJN + Bntej1CrubkL0ZVQvAOvKlVkQqo+NSuXtgFR8b9gp/83SKBmKW5uSCV4ZL+mXXPebO3HCMYedqQK25ys + 35NxksJAdOIB5BeVgf3aD8cZ46npHnd38Khzdu7QnGWtzQjGHu2kCo6K0+88lE0hW3P2S0I3xFK8b7iz + c6yBbn5nzVnW2oxg7CGTakl4jH57SiYt25qzXxis52b8a5nvBl+0npaxQ3OWtTYjGHtYpJq/MlJvSD5M + S7bm/quiMTsoRP5J+ccqX2Ke89ihOctamxGMPUiqL4PC9BsSUsnams9ZHsHBPkSnn7QzWWszgrEHyWHa + 4tU0NTfPM5ZBv20fJn611ECx7hwnXrk5y1qbEYw9SO9MnL8CcibMXMyPXXqpcMLrSqgvN/Yg8eN1Jfhx + M72J137sctnqo8v/mUD6911oPZsAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem12.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAEd0RVh0VGl0 + bGUAQ3VzdG9tZXI7RW1wbG95ZWU7Rml4O1B1YmxpYztTZXR0aW5ncztPcHRpb25zO0N1c3RvbWl6O0dy + b3VwO1RlYW1pCxOIAAADPklEQVQ4T22Te0hTURzHr5tlmoUVRjRLhwtr5nxMy7BZkq42nTlNyscS85Wv + fI0tc2ptbaYOLWxoRPbSICtdkX9kD3Q9DCmichWZoIFSWH9UZKnot3OsLMEffOAezvl+zrm/cy8DYE7E + YjHrfLIguTXT95U52/fHpTSvNyfjPIukUinb0dFxZt2s0P/IwmV2pxP432+ow6aemZLwUB+B2mgecqTC + lQaDYWbdv4ffZUNgEdjBQcFO1XKP8cfNWlw9JMGZ9EBowlwm5DtCl895Aho2Z3tKOtW+lvuHhMN3lD7j + F/d5fes4nomv3dV4UBMPjZRvkclkS6ig+JSIUZk2zRKwr6SuG37emDPVZUzEy2YV7uljoBO7YqRdiTbl + Nigj/A8QgQMV5NcGMNlVfrME800x3NHrmp1o08hxLGo9GhR+UIs4OB4fgPIUv9HNogCBu7u7HRHYpB1e + zyRp1jKM7kLINKTmlYWu7jQfTsTohx58fHQSJsVGlKcF4tp9NZru5SK9XPA6OpOXQQSLCKyYPFeGKT4X + wBwkkGLxVi51NWtix74P3MWIpRr1CiEqm2SobZeg5no4alrkyND7IDyD00UEC2loRnBLn0SHy4z7RX1P + m0rRVb0HJfFrUVS3EcVnApFvjEWp0YwsfTRC9zpP2tvbLyfrbf7uTq+PLd3nxs3S+b6tLAzCkUwh4gp4 + Y4kFcWOpKhWU+kt4P/QZRbrmqeSC8kHxLtVRFou1YDqcavB0O2ASnFWf9v953pIA481tqGgLRkVLGLI0 + FVPdT/rQP/CR9Broed6Pru5X2CJTviDZRVRgm1vnZW24HYuWpymo7QiBrlWIkss+UJ31Rm5lFAwn2vDh + 0xds362F9d0Q4tMrwRNszyFZRyqYn1LlAW1LENQXvVHU6InCRj6yGtYgQbsKirwSdD6yovfNezyzDqD3 + 9SBq6lshCFRYSdaJCmyjC13KIvM5N6U5K16EZTj3haQuhUjhBH/54v7gKMmnrZGJn+P2GydvdPSAv0Ex + wfOOtHD5kjqSnX4F2kBbgh3BgUCvh05Q6A6029w1XhFa/6254HCDjpAx58+87cyXOBf/Ff3BaGAFYTGB + TSDFML8ACaHK5m87ahMAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem12.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAEd0RVh0VGl0 + bGUAQ3VzdG9tZXI7RW1wbG95ZWU7Rml4O1B1YmxpYztTZXR0aW5ncztPcHRpb25zO0N1c3RvbWl6O0dy + b3VwO1RlYW1pCxOIAAAKp0lEQVRYR5WWB1iUVxaGfzebxJhEQRPURI2VBXUYBKSPdFABRVBBEASVNtSh + Ix1GGBgQh44SAoQiUpRmA6mighiJBg3YKJYEbHGNJq767b0TSCBhH7PneV7u3Dv/f77vnlsGBsD/zUWh + EWVGV7yRVWecQcq5OP22MzF691ujdNEcrnO9PkQr+0QgZ3mNn+ak749n0sExDtksZMrtlzFVu6WZGmcZ + ptZFlqlxkmE6BAafdgpN+3oKfXCjOhbD3XV4cuM8Ht84g/6mL3Ehm4uqAN2nhS5KipPlHc+kg2OU7Vgi + Fq9zlWVOuK9kTnqwxG1TuE5QT2kont5oQU9pCB73NmL4m6O4dSwZZ0W7cCzEGOXeOsiwXlk2Wd7xTOjo + 6+i/lQZvOabaR62ytyYZ35XzcdhTG00JdujIcMKZJDuUeevhoJ0i0i1XQmAi3TY+/2RM6FCByp3SpNQy + zElPFtPEYzNNvvLsU54r/Rt92Mdb/FfdavSRA6nCL8d4qih0YKGzKALleyyQaiWPhI3SSDCTxb4tqxBr + Io1QnYVV4/NPxoQONVDhsIypJetNROaQ2V5qC9HA7RJv9FdHY7izCI+vHcdgYwYuZu3CEQ8l5G2Xwa3W + HNy7UIjech/0HdmDEh8TBGjMB09tXtz4/JMxoUMNjK17lZNMdpdoK27VhOC00AqPu77Gg65iDJ3ej55C + HtqFFjgWoIm8bQtR4qWHX4ZO42HLXjxs348i77UI4Cx84aYprTQ+/2RM6FADJdaLmGLbxUyRzeLhnnwX + tMQYIX+HLC7tt8SNUj9c/doD5xI3o5anjALLBcjeMBuJxl/geW8ZHjTzMdIsxMFdnDcCa80Ec3PzaePz + T8aEDjWQZzGfyTGfz2SazUN3hi2yLBYh20kLBbYyqHZTQLUrC0U2S5BuMhcpRjMhMpoFgdEXeNgcSwzE + 4lqJH5K2KfeamZkt0NHReScwTYPxE6kxPvtUGO8kpQl6lAkdA20dJtNkLiNaN5cRGswergvQQrzxElyq + S0ZtkjNi1i1FkOos+CjPBE9lNiI5M7B3jQSyt7MxXB+F4cY4VO3ZgEAzFaGpqel0SUlJhpekzHgJlRj3 + eAXGTbBqgh5lQsdQS4tJNpRi4nQ/YSI0Z9VlbJFGur06Rq6U4un1SgydzUZPWRA6M+xxIs4GXgqSCFWd + gVwnDs6n70ZdhBn4DiqvDNZzlNls9nvUQOkZF6a4dTfjwmcxjtErJuhRJoTRmjVMvM4sJlpzJhOoMnND + gMosVEVa4cWtSrwarMLLm6X46awQQxU+pNT+iDJcCH91KeSFbUeKkwH2ORoh2tsArjEKXab20ixiYCrh + ndwGW2ZXuCxjHyb9NgMcZu8aSSZcXYLR1tZ+J9fTpOdYtBVe3jiEl31FeH45GyOnwjBY5omhmgikkcsm + 0noVmo5GoCk/BNnkWXdvFiJydOEuUHhtFyxTaeKwmENMTCP8Y3vQkskN8Av1mJivdcUV4GtKMKSsdHiK + p6WRbJGX0bNH5/bj54upeNQchTsV3hgs98P10gDwTRcjMXcLIg7oghsrD494RQRlKUNQpo/UajNE5erA + KXoFLHmLGpQN5syn1RAL/jliCnSYqHxtJjJPiwnP5TChORrMYV8TxnCNoUTKTq2GC2k7cL/aD0NlHrhd + 7Io7NWE4Gb0JEbvIlXvEGtknLJFeuwkxxdoIK1BFSN5qBOcoITxfQzzmk6IIM+68EmLgg1HJiRGZp81E + 5K5hrt+rZ/runSJtA1PoYcCoqqpO9dqoaV7A1XozWOGPwUp/Ih6Om2UBSNgkjahEIySWG2PvIV3syVNG + IBH1z1aAT6Y8vNPk4Jm2El7pLARkKmKT+2d3JSQkxKX9S9BZh+VoisX77p6iQ1NG+afF7lXywe7Kr9Kt + 2ajwM0AZTxcC44VwtJeBR5ICfDPk4ZvOHhVcAfeU5fAVbQE/pQQxohJ4J1nAK3UlNnDnPJ8+ffqnJCdd + hikeQSLSjEboQXUmOFuNfhwTpg+96xLL2uGXrDx07XwOKsk9wN+siMiNLMRaqSDJUQ0OoUuwi78Uzoks + hIpiEZwcBGeBCgITwnC1b5AwAB9+IKz9WeCGef3H1S+xQ1lj7czR/FTntwjOUqWNWFjfcsEMroDt5p4o + 1y8s3IzMip0QZBqinmy+NvIbUM7fiswAbXj7LUdYqj4845XgFxeJG/330P3dLaTkVCJCmI8Xv7zEyMOn + CBHkvknIKHvVcakX3T03sZsnaCE67xP+QUXHQlxu93h5T99kpQdpFTvQ/G0m2q8dRO25GKSW2yEoVQsO + 4Uthu2cRuHw5hGXqIaXcGqLDlgjdF07Eb+LJ05/x+KdnGLw7gpcvX+H+j0/QfbUfz1/8iqfPXuBIXQvW + mnOPEC26GX83IBbnxrG8RIet0HYlC81XUlHbEYWK9iCUtwYQApF/ious6h0EO6RUWiKuaD0CM9TgIlgO + 571qEGaW4dGTZ7g//AR3fngkbgfuPsDtoRHSjqDv1n1sdwp9zV6tr0n0Pqaao9piJ++7JbD6y4hQXoMT + Ck+7oajRE/n1LmJB4aENiMrTRWgOh5xzVfimKsJznxwRl4VLtAncIn3hF30Ad+49wNC9h2ho+QbuvkJ4 + +Cai+ey36CXiLee/g7Vj2OvNtn4nTTa77pSas+CjUW3xnw9c42RRcz4cadVbIao0R1LZRsSXrMfeAkNE + fqWNkAOaZMYq5EwrwCOZBed4WThELwEvMhtd317HT/9+jp+f/yqerc3OcCiqGruo62y2d/FOwCAx1dbZ + h/q2y2QZ2mBh60+vQHokaRXEBqY58qVR2R6M/RXmEJaaQlC8DjEF+ojI1cKeAxrwT1cGT7QK7vtWEnEZ + 7Ny7BDZhC+AenI5OssEG7oyQjXgfvTfvw5kXD47uZi9DYzvnwIgsXO//ASdbL6O2+RIy8+uwcRuPGpAY + b2CqXejiVie+DDyFbPCSFeGXspqIkhmLFOG1n1wsBLekFeSYSWMnfzGsQz/HlgApbHBUgbGNBXaTmZ69 + +D26rw2gvvUSgqOyES74Co3tl3Hp6gCKq9qgZ7IL6rpbW+VVjH2IJl0C8dUs3oSEaWqmM6U3uM7hbuTO + Fpl5SNWZeXxy2dRd8oqpq2S/KXcGjF0/xnqnj7DW8UMY2E8b0LX9oGeN1ftXOebzzvNCUl/fHPgRLR3X + 0Hiuh+z+AVy9eQ8XrtxGXXM3Kk9cgPEW7ut5C5cbEa1PCPQoijchDfqBunmPQI/Ih4TpBLpOkgR6edCX + 6E02ntmEBWs3OVcVVzTg8veDON7SjYLKJlSf/gZVp7rwZUk9Dh/rQGldJ8IEB8FSNKgi79B87xJ+NzAW + dIAuCTVDoZWhD45BDY5B+1MJEussXM8fPd6OhJRCGJntJji/KT/egZKas9DQ3fZm7SanN3v4WYhNKYYs + W6+DvkP4/Rj+Oejg32HM6FSpuYvm6xs7nJVbvbbms/kyxhwDmzNZedWITysBW3ld++zPl22UYWsf/Zec + dtfHMz5dSt6ZNvr+lL/8g/B3GBfUiNgEYWy5pBTVTbw5RrbgGG7HsuXqPDI2h0CXkH5Pxf+Y/WQCb+NP + Mb4aY8tC94/UKNQYHaPfUeHfZj4Wkwm8jf8RNOkYVGhsr4wX/UNYHAzzX2JQy7PWC0aGAAAAAElFTkSu + QmCC +</value> + </data> + <data name="barButtonItem13.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACB0RVh0VGl0 + bGUASURFO1Rvb2xzO0N1c3RvbWl6O0Rlc2lnbjuqXSmSAAADAklEQVQ4T4WSaUhUYRSGr1ZuaVq0QFBE + pWRRaZD+MGnDICeiyHC0HMQWRxo1l0ar0TvWOJONuGTjNurYpoFpGYTaNmb+SNM2U0gLS7TMIjVTMYi3 + cwYa7E+98HA573fO+ZZ7hH/IhrCdBsf/FSdZKLneiD8YK81QaorPkD8jWVsqJKWXCEqNUUg8W8w1Vtnm + m25N5ZXUPMk0VOyieFZgcIy2sqYBrHtNzxAn5mvIn0nYkCXEqwu5zirbPQeOi4rEDBSW10KbUy4lb5ZE + GqMzlFVjZGwCDY1tiD6Vq2WfsIlNzec6YQZhuaevf+D8MHkKnr58C6X64mvyONExu/QO3vUN4evwD9SZ + WyFXZup4TaG6KAi63CtTal2RyIkRClGtzbmEVz2DiFflTJHnRLhkFNbiTe8gOnsG8PnrKFKyKiE9rPSh + NTshPiW3S2+oQJzqAnKNN9D7cRhtXf2ISjj3pTrCK6NR4TPc3vEBIXIRIZFMKk6kGXC+6CYik7P1wiGF + KFVpi9HU2ol3/d/Q0tGPpra3qEqLwfinB5h4b4IpYNlPd1f7xXyaTQH7t8aezsbE5BSi1UaQJ9gdPJIU + dvR4eps8Tgtvv6ChgphwKn6Iye50PNZsg+i1MI/yHBI0Js53kEgVOUERJ7F9d7iMDf7v/GsciQX5kjXG + HwMPMN6hglncBLmfNwL3ympobTbxZ6gcCGfCTrgqWUdfS5PZeds9C8b672PseSLqlD4IXrcamXlluH7L + jPAoVRnnENzgL1mKM/1XFXzvu4uxlmOojV2P0EXOpkVLvW6fSCtG88s+VNw048CRJL4D7/xXE/u0jR76 + kd56jDYfRlXUGgTNczKSP5dwW+Kx+VJ8aiEetX9AWWU9gmVxPH58Batcsnw9R4fqw1Auc4fExbGEPDeC + d+Ehc1283O+KqL+MF92DkB1V/SJvDmGVk2rtymv6DZ5Qrl5hoNhSTLHAkLiJ25YdoUU798qxLzS6mmJ+ + C6s4gQ0+suWRdOtXCdNhj+Cp5Ob8BlxDEoTfXwJkh5usadkAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem13.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACB0RVh0VGl0 + bGUASURFO1Rvb2xzO0N1c3RvbWl6O0Rlc2lnbjuqXSmSAAAJeklEQVRYR8VWC1SO6Rb+hwhFNUpuaZrI + oTFuYRx3IqTCcif3UkYuKaFybVKKFEUqc4quI0pK97+/0kW6IcWp5JLSBcUYTDyz9zf91s+4zDnrrHX2 + Ws/6vu9997v3s/f77v1+IgD/V/zHcvx0wnsg+aoVbWQgjL3TC0oQeQfFEy7R8N8TqdEPIfIOZEPx/Mrf + bQlyBHlCRxm0J/C4QMbr1EXRkQCC/wX6/LLIGm7XCn7nMVkychP0jboc9A7f6ekfnU1O4BUQ03LY91yO + k0eQ41TD+T1IpwPrsb7b8bMiN5+z9Pp5EZy7+kREHvSOqHbziYDLsfBqZ8/g83Z7vPRojskI5Jw8Tk/2 + CrhQnph1HWX36/DkVQsev/wdpfceIT6jCO6+kbWbd7gtJV3F1nVfkY5Iik+JQGCKkUXMGqv9qGl+jvuN + TbhcdBue/ude2zuf3Dd2kmFn0mm/zNzhiL2zLyxtDsJm91FcSMjGvdqnqG5oRl3TC1rXjKDIlDebtrs7 + kL4ygbep7acIyKa2Td8BoxSnzV4fa7nVFTfLH+BmxUPcrX0M/9B42O0/4Us6wl7rG60aoztkbJ/RE02G + z1thE3wuNgN3qhtRThmpeFCPWiISQWOW1s4epP81gUkImZAVIepWSE9xWy2doV0M529KdvcJxa3KGmQV + lqO0/CGcPM5g9YY9BqTDxqRnpBNBbc4S6+wEST4RrkFx2T3kFpejouYxzsVnYqWF/RHSUSLIfUhAbsm6 + 3WH73IMujps8i9MrPXDtRoydpbXUfE9L/fPfkHH1Ngpu3sX5+Cz8uO0QnyY+YFLCTEJ50szl+928g5Fd + VAFJ3i2k5pQiOasEpXcfwXzjT1z0PQkKBOFgtkLUfvHaXdU+gTHY6eQXN2zkRGbJZSSv3X+o+jrrgy3N + LW+RTgYz8m+juLQKFjZuNTTPhqSVwQRUppqY5UVeyoT4yp+OEzKvI05SjPj0YpiaOTKBQQQNAm8HbyOv + F8kvWGX/qu7Xlzjifx6b7L0Sxk2Z07vfQD31xWaOEaEX0vD0dQskV8qQduUmbt2pwdrNrq9pnWy2Ougb + Llm0cKVtSwpFnZR1gxwXISa1EFFJV3H2Ug42bDuIXS6n4HjAH+utnY7RGi5TJiHqMNfU7uH9x02C8eAo + MWz3noD1bm+EX0xHU8sb3KYDJc4tFUjkl9zB8vX7amkdn2zeho7j9BfMs7J1eiXOvoaIuFxEJ+cjVlyI + 6JQCspGFQ37RqHjYiBdkq4mCOU9nYtlaOx9aq0oQyRst2vJLVFIWSsprhBP/qPkFmn5/gyekfPtBA0Ve + hpTsm0inc5BCNb7V/kjdt9r9tdhA/0HjF5hbOb7KyCtFJEUaEi2Bwey1MDBZh2lGZli8egcCI8XII+IR + cdnwD09FQdl9mJo78JZwFkTtJs1cZbDayglVNY3IKihHJjlKv3JLcMyRs3Pe00Tay2uldxAeGYso9yW1 + BR4jGtJdf3gr+cWDyi0HoRcvY6bJErRp234f2e1HGG5qbo+r5DwsNgsnw5IRRhlZtHobVNR1TtJ8NybA + e9jRYI5loN1eb6r7auTfqBJISNOeWXALiRnFyLhSgtSMHBT8vAINOe54VZ+Dl48yUXFpH6L8nDDdeBE7 + dyR7vD0qBO2FK2wRTs59Q5MQEnMZC1fZQklN+2ea4wzyQRZOsVwPDR2VKbPMDi8z39USFJ6AwpJKlN+r + w9XrFYhNzhYiT0nLRq6fKZrLwtHSkICXVZ54Ue6CplunEGEzmp3vJltCpyRwn+imP9P05JotLkJ2Fqy0 + gVJX7X/RuDaBq42rRxCBBKHTyHFzx0+eZRajb2RZp29siSmzLOotNu5rDAgMR57/cjSVhuP1wzA8L7TC + 8wKGJRpz7eE2VfMZrec656bEWWVwhBrf6c30GzPVFEqq2gH0Letc6ANS4Q9exOzZSBcCp7G7bt9eQ+Oc + pzez81d3g9Gca4bmnLVoylmDZ1c347LbDGydOOh5754auqTPlw/b4QbFQTEJ3muuf3XCu8tJpfsAerSK + XmfWFUhIuxsTURzUR6F31oER4qc3w/DbnUA8STdFU9oyPElbiqasH1F83ACOE/phtdEsLJq9rKSrag92 + JM2CbKfkkmWb0rH3hQkUHdITvX1ZyZ+s0GGolmKPDCe91CclYXjx7wA0Ji5EY8ICNCTOxxPJOhR4TsH2 + 0ZpYNWManHc6YKv1HhjOsZCoqPboTeulJGSD+qtjqTCBfFe+8v90PlhToadkr17q4xth+LXsJOpjjFF/ + wRh1UUZ4nLwa+W5jsU1PA8smj4fd+o044OyFs9Gp2E2dbsbcDalKKup9yM67dq3WSybdnxDpGeg4SEOh + V4rjcHHDtVA8LzmOusjpqI0wQG34NDTEmyL3p1GwGa752mT4YDhssILTfg8c8z8Hv5Bk6oBFcD0aAn2T + 9eIuyt00yZ7snfFJeef8u94KvRJ2DBPXF4fgWdEx1ARPRM2ZCag5PQH1F5cge/cwOAzpLtHo2nWs4fip + lSuXrqPGlET/CokIoC7nR+A7wMUzmCrITNxZSe0bsvtFEpx2ed1enXpd3Dokra4oBM35nrh/aixhDOGf + eHRuATJ3fA/7wd3T1DvIcRNR69xZ5duRo40zrWxdEZdWSCRScTI0GSeCk3GB7oPtdKdMnL4mrYuyGm8H + XzwfPQPS6LuEmOmcqIynxpJ3GPdOjMC943q466OH2rNzkWEzADsGdZN07yDHaeVSEqpEQVFFU2/MPLGV + nRtiU4vgG5wEn9OJOBqUiCgisXmHJ8ZMWepHulzS0v+A94QHeEI1xFTnUUP2UVR5DSUMQZXnENp3Y6Rv + 0cF23W4Silw2nRwNPxU6Kap8M3T0nLT1W12EyL2JgFdgvPCMFRdg4kzzOtLjHvCX5sPCAzyhGriw752q + MDNUHtJFpbsuHgYbQrxBG7YDVSXd5IW0c+RCFK3lKs2eYkcFZa3Bo0zSrB0O0zVcCO8ziQKik/Iw+Ic5 + VaTzWQJsRMlSW8U50mIC8rf3RYXvVEQu6gObf3zcuRT83ToukPh+hLHE0voAOc7F2bgszF++DQOGTHOl + +U9uAQsP8uWhZq6l4rJNp2uVbb+vqy20lH3V5d/tubB4e7+uog/B463zip0UlDUHDpvuS1FXc+Stzjl6 + 6T/kR4UNCA2IwFcpL2DI/rt9lLmM8DzrsT6v694Kjlzq/LM2pCQ4Ej7hDH7/4kIZ+V/YEBRl8d/I37Qh + Ev0BUQ6AahuAd3MAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem16.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAB50RVh0VGl0 + bGUATGV0dGVyO2UtbWFpbDtlbWFpbDttYWlsGpGT2gAABuJJREFUWEfFlolzU9Uex6vPBcXt4b6893e4 + 8Hxuo6ODyzijgm+eUmGwgMrSRRCZUrUOKAglCFhaEYmFAgVsQwu2tLRI17RJ070ppE3SJmmbpWnTdOXr + 73tuU+Oz8hhH8c58cs4995zv73tOfufcGwPgL2XGxivJjI1XkphjP7TE7DlQGZN/xhoj11V/AldHMd2e + cbBKCrloQK5Ix78J10xx7f/huktw/SXgWMZhzGkDVx8y1D6Zd7qlxlDSDpJXPMXptmlySVGr4nvheCFp + UYiO4ugp0qzIISebFEcKSCMOGuqN6fqSpyUmJ6lM8Oea/cdMbnffICYmJxUXL16Uv+iPuSZFa3x8AqNj + E+jqCWBrRqlHYnI1uOrKwHUffG7AmHQYn5hEeHQM4ZExGTCuzPzea1LGUoN6IwK1Q8OjSPo0V7Iv5saI + Af5cvynjRxQUNaKxza06joyOIyQmyHDEjLRfamX4jH04EU6A4zh+RMaOj0+irtEJfXYFUnYU0cBsgbmg + DMzauysP7txcnCprhf5oLQLBsFq20MgohsR1KKwxPI2YEpOEwcJyz/ZIP4WM5WT8AyF8pf8RxwossG5L + w5dbDtPATdEGbjiTkAhn+m75j/yosdixeXcxKmptGBMTnMmgmIhAQ5GSS8oyuo3lsBjj2LLKDmzYYkBZ + lVVpt8SvRsGyd2ng5mgDNxavjkeg0w6HO4Cubh9azruxPbMEOsHrG1Jig6ERBKOI3GtlWKtLcPbt8w5i + o+4EUrfnw2jpUppO0e5taIbh7eU0cIvAnaBczN61NQeuvqB09AsBdDp8aLP1Yv+RKiR9nIPCsy0qiznD + gcGwxtCIlES75zPmSv5pC95b9x227y2GpaUbNqcPdsl+u+hau/qxOVVPA7dFG7hpfVohTlXaVGdCAzZ7 + P6y2PhQUN+CD1CNI3pwLj5ikEQYPSFDmCutsc3kCSNhwAO9/lI192eVobneLhlfTckgpursP1yLh07xf + Gbh5wbrjyD93AR1dfTgvLjvsfVKXUu7bZSUMRc2IT8lB7IpMfH/KrHZJ5L9nPcdQg/lLdEhIOYKMAxLc + 6hENbTx1qHle7ndmG/Hy6oM0MCfawC2vrclRS98uM1Z0/lwaG2QZZRbdbj9OFJqRsukw4pMPqhk7XT7E + JWRifWoWck/WwdRgh7XTq8ZMawjWqXpTRy9eXJFFA7cLPJaVi1sTN56Ap9mK1g7PLzDWO1Bd71SJFZKt + 5vOHUFbRhgx9ERatTMeCJduQub8IP5Q2or7ZKQnJPJiQQGLc4viVnsPYgOXJR2ngjmgDt21K+RbWjz5B + U7tLcCtqRKCkQrbiVPKR0LBsSfnPzU0OFJZaUFTagHPGDpldL4YkOA0EhzQT1SanmkBTGzUFKeuXvoPk + pHQauDPawN+zX49Fe/IGydoeWFq7ZdZ2nCxtV0IUDEpQijPIkJigGSZVvWQ5S95rwbWdweQMS26UVtlQ + bbaLJnV7YI57B3tfmk8Ddwl8cyoDc7JeewNOcwtMclzW1HfhkMGignllySkW5HYT8YgR7vdIGWQ59Yzb + 0S/9fQPD6PeFlEaeJHCNuQumJidslWZkznuFBu6OGOAy3L5hzR6VIJXmTmTlmtQW63YPwCn7t8czAE// + ILyBYREf1vb+VEANngMjcuSGVR+Pdwg9vUE1jtBUTn4Dqkyd8j7oxtqVO2ngnmgDd8StO4Svj5mxL8cI + n4jw1OLp5ZDj0+kKoJtivQPqsHKLGQbpkxkS1gnb+Urv8QQ1864BNZ73flkR/XETNspLLzbhOxq4N9rA + nU+9lYEt+yrgEucOlx8X5OCwOb1TJrjdxISIUoyzc/UOwsWAU0E5jvCZFjyggnM8DyJOyC3m124rwqP/ + UStwn8BvAs3AEwv3qGPSIQOtnb3q8KAJJhiPZ2WCiFCPm8sbjbbUDBwJblfB/Wr8BTkNO+QccMq50Wh1 + Y+6CHREDPyfh0g8P9TeUVKN28duoXRSH1lIjqmQLbf6mHJ9/UwGjJOf5CjloFsehTmAymZpd+OzrcuEc + 6pp6cKHCpJ6bRKOjvA7VFidS95xFanoZyuu60HymGlVvLsbCBL1XYnIXqG3It+HsxJeWrN31+LyxnU++ + gDUrv8SipCy1VI++vhOxiVlIek8H3WPPQ/fveUh8V4fYeD3mzt+BR4SFUo9fvh1p/3oOaXOfRfyyNLy5 + aj8eelWHh17R4Y1V32LV0m344uFnsPXBp8aWPf3f9RKTb0P1OlbfhAI/EHg6MTm4PPf/Dw/8Bv+YgX/+ + BnzG7Gdwzl59lPJihW7YyP8l+jP6cpl1GbAf9RmLMacNXO4VGfRHoF3yLfmXMmPjlWTGxisHYn4CcBhN + g3QOmyIAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem17.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABF0RVh0VGl0 + bGUAQnVnO1JlcG9ydDuxsBc9AAADEUlEQVQ4T22OaUiTcRzHHzWPDhvZLC3zWIFoolGa0zy2yR7d3OnT + HHPTtcqjpaZk2tSclk7zCOnSUGZZaQdhzg5Ms4iQIgqkF12kdEFZ0rvKV9/+j0Sw1Q++b/6/z/fz/1EA + qL0tW6mYeAGVpS+n0lW75jOzzQ6RLC+EoijvhFRFWCqtcSQJFfO0PJeKiNlCFdm2LPTY/BUkS1MJT7lF + bkrm0FnFgzJd5Q+Jphxp8vyfCSLmyrrQ8ACy9+Cn/UdgbolbKG+IiOMKpKa7Sn0l8vbaYCqxIdtkgVi+ + E7GJmVMBa8LYqzwKm1wFzQsCT4E84yatyIehyIr9DT2o7biEMms3GH0ZkkQM4gX8UcL5sp85Cci4q3PV + KGjcBKlGBo2xEpaj52HtvApLSz9UulIkCJNhqtuIDIZmC16uAi9D5ebnTQMpGJoyoL69FkrdbqSk50Ce + bYKlqRyDj7SoP7cNqqLwV4T3dRUsNjWsf3fitgRDz/WY/ubAzNwNtPTl4v33O3j55TIuP8tG5wgNbUXQ + R8JzXQXLTId5v06NZuIKAV98HsDbb8NothswPXcLU5/suPiEwclRKXRVQfOED3QSSJW5MNbx0HGdRv9j + Ne6/tuL17DXY7Dl4MzuM8Ze1sD+Uo2MoDZr9a5GSpiI15wuW66tDPtT2JaJ7QoKzk0o8eNOMI71aTL7t + RB8pnx6nUWPnQ1US8PmfC8gsZcqCHObWKHQ4RDhzLwM9DyQoORaL/snt6Jqg0TosRIEtEnSe/xjhV7oK + vMQM/6qhJgSWXj7aHEIcHxPD3L4ZPfeVaL0uQFUPH1pyfoI4aoTwS1wFbrRUC0VB2AfjoQ2o6I5D/UAi + 8pui0XqNRkVXLAzVPIj1az6liJRswd1JYLRGsRLPQJ53hKxg1dOcqlDsaoxCzsFIFLfFQXsgGJKdK2dW + BXvGE857B+GdBOwDGTdW4rPUPUSg8euVF3Jn1SX+yMznfk1ScS5w/BdFk70Py/0j2F4eQDH7VlNM6WpW + tIiEQxJEwiMJJvEj8ZTvWUHJikgKV/wRgPoNi0bk6eM2pOcAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem27.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABF0RVh0VGl0 + bGUAQnVnO1JlcG9ydDuxsBc9AAADEUlEQVQ4T22OaUiTcRzHHzWPDhvZLC3zWIFoolGa0zy2yR7d3OnT + HHPTtcqjpaZk2tSclk7zCOnSUGZZaQdhzg5Ms4iQIgqkF12kdEFZ0rvKV9/+j0Sw1Q++b/6/z/fz/1EA + qL0tW6mYeAGVpS+n0lW75jOzzQ6RLC+EoijvhFRFWCqtcSQJFfO0PJeKiNlCFdm2LPTY/BUkS1MJT7lF + bkrm0FnFgzJd5Q+Jphxp8vyfCSLmyrrQ8ACy9+Cn/UdgbolbKG+IiOMKpKa7Sn0l8vbaYCqxIdtkgVi+ + E7GJmVMBa8LYqzwKm1wFzQsCT4E84yatyIehyIr9DT2o7biEMms3GH0ZkkQM4gX8UcL5sp85Cci4q3PV + KGjcBKlGBo2xEpaj52HtvApLSz9UulIkCJNhqtuIDIZmC16uAi9D5ebnTQMpGJoyoL69FkrdbqSk50Ce + bYKlqRyDj7SoP7cNqqLwV4T3dRUsNjWsf3fitgRDz/WY/ubAzNwNtPTl4v33O3j55TIuP8tG5wgNbUXQ + R8JzXQXLTId5v06NZuIKAV98HsDbb8NothswPXcLU5/suPiEwclRKXRVQfOED3QSSJW5MNbx0HGdRv9j + Ne6/tuL17DXY7Dl4MzuM8Ze1sD+Uo2MoDZr9a5GSpiI15wuW66tDPtT2JaJ7QoKzk0o8eNOMI71aTL7t + RB8pnx6nUWPnQ1US8PmfC8gsZcqCHObWKHQ4RDhzLwM9DyQoORaL/snt6Jqg0TosRIEtEnSe/xjhV7oK + vMQM/6qhJgSWXj7aHEIcHxPD3L4ZPfeVaL0uQFUPH1pyfoI4aoTwS1wFbrRUC0VB2AfjoQ2o6I5D/UAi + 8pui0XqNRkVXLAzVPIj1az6liJRswd1JYLRGsRLPQJ53hKxg1dOcqlDsaoxCzsFIFLfFQXsgGJKdK2dW + BXvGE857B+GdBOwDGTdW4rPUPUSg8euVF3Jn1SX+yMznfk1ScS5w/BdFk70Py/0j2F4eQDH7VlNM6WpW + tIiEQxJEwiMJJvEj8ZTvWUHJikgKV/wRgPoNi0bk6eM2pOcAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem27.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABF0RVh0VGl0 + bGUAQnVnO1JlcG9ydDuxsBc9AAAJs0lEQVRYR8VXaVBUVxZ+IKJIlBiQNamZjAr0Ct10N003DXSDzRYQ + UdlEQKFlky2AKAIiIGGXlkVFkSUYkxijxEJHTFwwmsRYcZxMHBONiXE0k8VkZn5M1aSS+ubcR3S6MxXG + f3OqPh7nvnPP993T957bzQH4v8LamcGUQREg1AcEGrzItSHYWkLsr/US+2nqhRL1zInIrDgtnawOTy6+ + SMgJ5bH/BYXaIFKow5mABsphT5hDmPsz5oik6gaBOHC7jyBATL7NL+dHmXxoeNosOa2czDZ3rvtgLucj + UXEa41ouJGY9p4/fwOawVdpJZLpAqSLivkAWc0Yoi7lJicGeAln0WYFUd/93S/00FMfEzSLYhMau57TG + DD7fqs1uNDRtlpxWTkaLO7f79QIuLjWSkwfHs9iHpbb3lkSsJMJvlKHJWJaYj9i057EyuxrPpZXxvjI0 + BUJ5zLdLRPpkip9HsGPz5cHLuZgkA7e6ZiG502bJaeWkN7tx/UcKuO19mSzuEbmvf1SnNHA5wlfkIS69 + HNkVnahoHsK27sP0HOb9uDXliKD3LM5HauyieU8QZrM8WzqTuFVbHkPAmiZXrv+1AqpCPoubJveL3OGn + XoFlKwsQnVKCvC29qGweQ2njKDbWD6G0aYREjKGobgCxqaWIoDgW7y1d1kbzmQi+EolVjyEgrcGVMxqN + NlKlZvZTrq72IpU2XqyMgz7eRAIKsa6sHYV1+5FbvRd5Wwcegfn5Nfv490xoGMWzeT4yVZKLu/sCob/S + kfKyfcGbJaeVk1q/iJNI1Hba0Nh/aQz64hXlXrflmjDoojMQnVyC7Ko+rK/oQfamPpg29cNUtRs5Vf3I + IX9dRS/934eY5FLoojIg04QiOs/9jjI4uFqlNf6gVIY7BGqMMwtI2ubC+fipZql1UTnGVPmPG7sk6D6U + BY0hFEb6fNcWdyKzdCeyyrqRVW5+hMznu5FR2kXvu/i4IH0IOg+mwbTDB/qVkh/p6JYsEQfMVWmWzSxg + dY0zez9robP7/MRNLt80jkbCPL4cR96uQG3LZn5lbIWrTPVIztuB9KJ2pOQ1Y3XOdtof0yuvbdmEw2+X + oPd4ArYN6hFb4PRgoYuHh6OjIzuebGNbcVo70wF2UblOkZkNv8H2UT26x2Mxcj4dV+8M48rHr8E80Ias + /CIkpOVAbViNFfTMJN880IorNw/j2hfDGLuQgd6JODSOGZCyxQPqRIcEyutAYBvbmtPKmRZgH1v8ZMPG + TinqRoKw83g0hs6n4N3bZly7N4SbXx/Dne9P497fL2JznwF//cclfPG3Sdz69ij+dJ9EftaLgxfT0f97 + EnBQh5wmb4StdWilvPMJfIOy4rRyphU6xJU6TZaYZagdVZMAIwlYhalPmnHlTi/+eH8Q178aw81vX0fT + mBG3vxvHx98cxEdfDuHq3X5c+rQFYxeT0XcyhgRoUdghRvg6hynKy84hfyStOK2caQGOcaXzb5V0S1A7 + rETncT0Gzy3H5EdVeOezNnxw14w/3N+D61+PYNcbCbhB5B9+uZfGenD5TjveulGN0bdXoPdEBAlQo2gn + CVg/5y+U14XANyYrTkvH09Nztou7p3Ns8RMPCjsFqB7xQ/t4MPacicLRqzk490kNLn3WiPfukJB7PRg6 + l0oV2YP377bjvc+bceFWLY5f24ADU7EwT4Sh/sUAFHULSYD9PynvYsrPWvSvC6Dj8mygNhKxG+ejoEuA + qkExmo+o0DOpx8il5Th1vRRnPt6EqU+34p3Pm7B7Mh6Xv2jDhdt1OHezCm/eKMOh9xKx98wydIxrsJUW + ULxLBMM6e8hVeoj9Nb7/uwIeXouiC+Y9yG31QcU+EepfkaHrRBD2njXg8JUUTHyUi1N/LsS5WxXY+UYE + ianG5I0inLyejyMfpGLwghG9kyFoek2BLQektBAhwjLsqAJeS93c3BxnFEDGdukC4waHTze0CFC6W4ja + Q3544VgAdp3WYGAqDC9fScSxaxkkxITmV7VEXojxDzNx+GoSDlyMQP8ZHTomlGh4RY7KAQnyWoTQrZl1 + j/Ky+5jvBVacVs60gCfC1889a9ohQlGPL6pHJWg84o+OE0rsepMqMaXD8LuRePVqMmpHZDh6LR0vXo7G + /guh6D+rRfepQLSMK1B70A+lfQJkb/eFNsn2IuVdRJh5E5KxUzAvJM2+dW3NYuR1eqNyUEgfgx9a3ghA + 1ynaD2fU6D+vxuBFAwrMv+XF7J7SoO9cEMxvBtLqVVR+GTYPS1DQ7Yu0qmehfM7WTHkf+xjOVTw3O355 + kQty2wQo7vdB9YtiNFAVWieYCCXMb6mwZyoUpo5nSEgEdpEo82kVOk4qsOOoHHUvSVFGH19+hxAxpich + 0tmkUF52NfM3ohWnlUPqWM92fdrt6dD0uQ9ym6VUhaUo3y+gvSBB0+sytEzI0XEqAD1vaZHV7IU95w0k + SoG2EwFoPibHtlekqDwgotV7I69ZgqBVs7938XAVzJkzh7Xime8CQ5Ydx24tf2VomTra+6eVZZ7Y0CZE + wa6lqBwiES9LqBJ+aD5OJ+OkGmvqPdBzOhQvHJej6ag/T141IsLGHh9avQgJRe5QhD/7Ex2/GrplWQVm + FhCWMYuTyXSOASr9D37KwPqQNNsvNzRJkd3qjcJeb1QcEKDmJRHqSMgO2mirq13RPqHhiWsOiXmRRX0+ + MLV5w9QohXol95VIJm+XyoJ/UCj0ThJ/LeO34rRyQtJtOYVCYScJUM938XjG2X+ZbUbEunnY2K5AdstS + 5JuXomyA+sOwAHWH/JFQ7oLGw0pUDgtp3JevVA6JLaJ4Q8ZcCENs8p3dvDxFMpWzRqNhR5A3S04rR5fG + 35asTPytSHhKFWfTH5mzAMWdauS0+CKnYwkJWYLnB8SILlyIzQdkvDATjZtafVFCccb18yGP5vbRfHcC + +93AEvPlZ2bJaeUEp9py5R0xLIYF8yeCsEgVbzNiyHBAbpMcxTtVtEraF53sknFCMd2aplYRP87eh1Nc + QCw3SvM8Caz38+SaJPr7s1lyWjnqRI4ra43mStuiWJylCBexgSsIWs19F5vrjHXbxLTSYBizXVHZHcb7 + bFyzivteFMoVUzxbOSPn739TfTD3WAIEOo4rbYniSl6I5Epa+C+QTARLwn6GPenkyi2WRnBbAldwl2mD + 3dUmcQiiZ2AC9740nNu6wIXzprinCEz0NPm2YC6nVvt4AtwXcxwlfYSfJzERDKyLsbPsRGBtlZX4aQL7 + scr6POt0bNWs3fJlf5jjYb6HZslp7cxslkIYCavKQ7ANy8atNtuv2X84wf0bGXQmFUwPzCsAAAAASUVO + RK5CYII= +</value> + </data> + <data name="barButtonItem29.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAARFJREFUOE+1 + U9sNwjAQ6wiMwAiMwCcCKrEBbAAb0BHYANSC+CwblO8LUtkANoAN4Jy4pNBGfCAsRansyz2sa/QXjDPT + j1NZ613w5KPtaUo5jMm67CA4zsxD7+s4k5XeCb4dJ+VgX3YZ7jFKzUKDlghAYJyaA5JRtogz2ThNLp+a + TWBFf+6asE/5BSR2umxIeah45MOkUYFA+1WRUMxXeD9qHTrzZD7cSY9UEOwUXsxI1TxQkVQQGAPV30YA + wawXUkEgQev8muDemK0GPMJyuRgpSXvow4QJClIvwBvlrXnVQTxlBxp5tgFaqd6mm5tLhoVSA+EbZQ/X + ZuWyuWmVHB0Fq4bAlhObTLcP1Vr/gd8RRU9yHvV4DTCmdwAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem30.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAAABGdBTUEAALGPC/xhBQAAAOFJREFUOE+d + k8ENgzAMRTNCRzAbMEJHYYSO0A3aS8K1G3SFbgAjdIOiJFKP1AYHXCAB5UsR8bfzFGFHbQm0L0HbD2h3 + Z0uB8Rcw7gn1F9hKiwoJUhjX05dtBLnX4CGQrbjg1p/wFg0dCItTM0i7K1txYXErIVkgMPYRDss9p4+B + 6KdOEO0rqN05DzQV+WqIs0HUKdHWbNBSR0HLC6x0BCSGthkKtrQHChCOp+lfKQmiZxIgOCac3lYKFBbG + Lafi2gMRhJ4Tp+KaQbZjS4Bsl+yUFBUW2r7/Wo370fMlW0JK/QDS1DX1sWRYxAAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem31.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAQxJREFUOE+d + U7sNwkAMtRQuNQUFn1xEQ0HHCPQ0jMAIjMAGsAGMwAYwAl0+EmIE2AD8LOcg4S5IPOmk+Nl+9r1TqA3l + KFrkafwsBzRV6jcKGy3180ugHJlZlnTmkvQhs+YgDVyIuClQ5bM03iCuASSSeWrWSnmv4ESsWSnFZJ/G + 0pyYnVKCkAfcfOZBdw2JMFVUWUgpQVCAfahtAUUcCT4QEgB46MNt/I9ArSckcE1oAnOLIfWUcqj1YBWf + ByFUprvnxLurKQchfgB1XwNzGx9V5P2+HiCPuuaT061L3dyaC5KFNfvmdTS/lWauQ6ypN0BW62nhyR3H + xUdv8yfEJF6RxcRpHInbfqT/QPQC7BurhCKjegEAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem34.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACR0RVh0VGl0 + bGUAQ29tbWVudDtUb29sdGlwO0hpbnQ7VGlwO0Nsb3Vk08HbyQAAAm9JREFUOE91k0lMU1EUhm8QJ6xY + QIWlW4kL3GAoGIIaF7rRDQsFBUUKBLFaQIK0FlocVpo40DQyU1rKIIQhYNR0oVgtpWUSlCJpcGhNQMRo + dPV77nsPUkBv8uX/z7nn/vct3mW0QohQYqPEJmKzxBZiKxEmsY2QSfC9EFbR4rEb2kZhaB2TGCGoto1A + T17PtWUEFTYPaBblLW6UW90orXs5SAFhTGN2w7P0B57vIm6JYc6iiCuIIcL57TdKGpyggB2sqNYJFzXa + ZxZFvBLB9Zq+/ctPqEyDPCCC5T14AUfgF5omFiTmBTWPB9fzUk2etN+3hAt37TwgiqXdfornvh8wDQeQ + VeNC3JVOQVf7oRVvcgVge7uAVH0fD9jJUvUD6KTkW8/moCjpwdxnPw5d7/+vNzzxwTjox4mybh6wi53U + 9sLi/opr3bM4/dCBg5o+nDU5kW58LfgM7qtEn258g9LuD7hj/4RjxY95wG52vKQL1a/8KOzwQtszi8oB + n6CcG3Sbtpc8UUleQ8rnKvt9OHK5lQdEs6PqDtyzf0SB9Z2IbWrFX1zRKcEv12VdM0jOt/KAGJZSYMNN + urWYkovbvLjaMY0iUj6Y2zQpoGwUtcAyhcLWaaht76HIMYtfkJBVa0/KtSAppxmJHGUzEpRmpKgsUNZN + 4lzdBDGG7PpxJKusiD/fKLD/1H0HBcgJ4V8Pl4oIIpKICd+XaTysbkdm9SgyCEVOA7bHptfQ3h6+T/D5 + UKbT6dZBiz8wefSBS6bE/GbEZ9dDtjftEfWiiA2rZoOLYKSQSHmcskoWe8b4r8PC3NpGMPwAsfyU1x3W + 6XTsLy5SM69xQkG9AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem34.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACR0RVh0VGl0 + bGUAQ29tbWVudDtUb29sdGlwO0hpbnQ7VGlwO0Nsb3Vk08HbyQAABe5JREFUWEfFl3tQ1FUUx3+aqfki + H1maNT2mMh9lOibq2pCOZeMrs7GxGcrEB/lCEHTluYiPwkfWkKaFArvIY+UhgqIEIogmoeaUsAu7oKsI + CqaQhaN/fDvnt/cuC26GTdbOfOace+79nfO99/5+v70/BcD/isvgf4mi0+kc0K+dC9rfg4dc0OEveNjJ + 52vbqTVFYZlMDuwo6CToLHiE6CLoSnQjugt6EG7Eo4KeRC+it6CPsNzH13MtnqDSPjSmYMK6xFNl65NO + Q0JtB2uZhBIHEcyeH7FGEs8UqzbcwBS3QEeE6QmygdEFZz8J3jmT6vIEeNJKB0pSe6LqOqp+u4NKgdXB + bVgIttKvcKbRTrkTZidMDbdRRrBljliuYXX0sTqqyyvCq610DDOchKXxDk5cvYXC2iaVAmH/Ca6ulbGS + ulvQfldEd5/yJMHbq3QKjvkBphu3kVf9O/GHgP1/nxNXmhDwTSELeJrg+0rprI0+jnPXbuHQhZsPnEIS + 4ft1Pgt4Rgro4r+jEGevNiHT2vjAybPdxJIv81jAcwQ/VUrXZVH5KKlpQqr5BtEgrCta97lqS5z7m2PZ + lY1YuCmHBTwvBXTzijyEwxUNSPj5VyT+wlx3QsZc0dZxdhKI2FP1mK3LZAEvEPw+UHrM2ZCNlLPXsOFw + NaKKahFzuh5xZ+qxragaszbmwn1ZMmZFfq+24366zzjl4Xycd33OJWw9WoNZoRks4CUpwM0zIgvJlCD8 + gA3hB22IyLZh05FqvLvuMCINR2E2m/G5Ph9Tww/g2+I6zFjvKn71rvhkXZaaJyL7oj03sSWvGu8HprOA + l6WAnrPDM5FIKsOyLqiECjt6uRHWKhvq6+tgKrdihHc8viqswRjftsWHU9w5H7MxtxoztCksYDDBb0Ol + 1wch+2AouYKQ/edVgoWdHpGNqNRi1NTU4IukIrwTkqH23RUPvndcErK/Cp/lXMS0gL0sYIgU0GdmUDpi + T15BYEYVAvdJKrE204ppaw5i2AI9poRlIiLLqvatJdsybrHH7xpvjzvnXUfbO9kvmQW8QvCfmfLYDG0q + dh2vhTa9Eto0gi0RRBduzr2IqKOXyV5CcIa9P5jEbeJ4wWVs4TjNbFWaVY3zOB6/hfrVOOVZJXOSXXPg + Aib5JLKAYVLA41MDjNh57DICUqwISLViZYqFfIuwHJNt6qN+bqu+bItxK9VxMma3PEbNoWKBLvM83lq6 + hwUMJ/hvXOk32S8J2wuq4b/XIqhQ7QonZJ/aNlYI29wvcVzPfWq/yCXGhtKqTFgUzwJGSAH9eUmi8i/B + N7mcqBC09iUt+/0cMWfrPE6MIdHsB9E2eSzUs4CRUsCAibQkW3Nt8Ek0wyep3G4TybIv4baMq31OvtoW + OPuC5U6+lrbljfmxLOB1gk9RyoAJiwzYnGPD0gRzM3sYU8tYArdlzIRlcpwrS6j9EjWfGStpGzRzY+QK + qAKe8Ji/+4Z/7BkEpfNjRo9OOkF3dRCxWkI3mJZYnWa3vjSbxfEmokxYSRmWCH85rYa/sRwBe9nSfUO+ + 1/aTGOW54ybVdbwH3IZO8p+n8drVOG5eLMbNi8E4L4J8Dfka8jVzd2MsqR7rxXY3xhDT6TXrQzP71FBm + Ry8QbR9aofF+cXCfE41RH9txJ0Z+uK3hWfePtFR3AKGeiPj0yydYDvBf5IvEQAG/rwcR/NpkxUMJfn7H + PuWxJHlKWAYtqwnecWVEKRYKeAXG+8ah28Ap+2js24SGGE2MIjgH1+LZ82lcPRrzEZnVtD52t4ZfHLxv + fYkh/TXeSZMC07CYZrwgtpQ4h0WGUiquR/dB01NpDD9q/QmeIB/Z+VrOw5NWvw3+7qPEFXwhn2Y56ZC+ + 7nONE1cZ4a0vVfFoLv4awSdfWUyi5nHUlc79IJKwCP7wGNp7hKfxzRUJVNyA7oPfS6GYLM5jHMVc4TLY + FjixKMAiBvcc7ql3e3W2nnze4zYVZ1wG2woXEIV4f/sRvN/st6k44zJ4P3Ahgj+xuCjDfpuK63Q65U9R + WAqL0Ha31gAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem39.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACp0RVh0VGl0 + bGUAUmVmcmVzaEFsbFBpdm90VGFibGU7UmVmcmVzaDtVcGRhdGU7gLmk/QAAApJJREFUOE9lk21Ik1EU + x9ec0yW9qLlk6VypLUuTILZeiNJJuHTNNDZfculagr3Ym2kvYG1GRlZu9LIyStDQsmJYklh9yyD7oEJB + ZFEGUX2NvtXgdP7X5xlhF37Pueece89z7v0/j2LGmCWhZKIYlWThyzmZ/waCUbUtqx0er6lrd6v5fd0Z + 829Y+IhzPppReXwmr7Q+UkhZ5DamlB/J8Vc154YHR4L0dmqYvv0cExY+4s7DOQFpDfEedCYK4BFdsjfL + f3vgBL37HqKep810tMNK5Y0rhYUv4k9OMS1UdmA5CqgZHE2hLKxNr9havzQ8+ukSnb5pI6s7o39Dqb5K + mxqXAQv/SqiaRqcu0KupduK1KBDLoAuFanPNku5gqJLO37NRgWtxf0KyJpXjCRJJ+ZWGwMnOPHowXiOw + etJRQMOIAtEWV9pkwU4DAbNN5+TYXGmBJq9Sf1bO/QvnIh3gLPHMQgm8dTaDOG4dc+STmRRGxyxgYhhx + B2qWi2bC0vk4h+8AheKch3LLIjmfaVKKiwIxkOXHr3FBz5CXHAez2zmON6MDdeaqxHiWsHfw5VUaeBEg + nvcgzggZYyHL6JeA4NbQfrLvWdZndWduy16nTSyuM9pK9mXd8ffW0+vPQUgYLqzNdPE+FBcFNJCltbtI + 8GiigW489lDTxS20vSGbjnfY6e6zYzTyoY18XcXEkl/jPfMYHG+6A8hiqTJcZ7k6eR7uuF9Kw2ON9Obr + OXo+0USXHzogXdiywxBcsT7JyHtwPPn/UKg3Vejb2CYxyWvsul0bK/R9+dVpH1muP7Dw19oXuTkPheKY + SPsY0BKaIzGHmc9AJi0DWWHho235YsXtywOVcB4gbp2RC8rARzzyA00PheIvOpAOIaUhiVUAAAAASUVO + RK5CYII= +</value> + </data> + <data name="barButtonItem39.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACp0RVh0VGl0 + bGUAUmVmcmVzaEFsbFBpdm90VGFibGU7UmVmcmVzaDtVcGRhdGU7gLmk/QAABwBJREFUWEe9VmdQVVcQ + NoItdk0IUYGItCAYO0gUMCooYKH33uSBIGKNZSgKKqKYGDWiQwRFI0oLIIpKVYoOoGIDFDVjSZlJ/ogz + +bPZ78y7zwcPLDOZ7Mw3HHa//Xbvuefcff0+wD6Soz9DjaHeA/AhJvH+MxNFnWQmY0ITZzuFbzfbszLZ + vFyWMqdTtnNOlwCv4UMMHHCRI8/tzXr3E5ECbKKwyypTzcAtM2OD42fVpOfIKK9yH127k0ttzyrp73/u + CmANH2LggIsc5EIDWkqaahxPkPxwKqxHcTWPuK8cfDZO+yUj/1su8DM9/auaOv4spXu/n6PWlzl060WW + ANbwIQYOuMhBLjSgxUDBAd4bpib5bZ6OIgPkvjemVFzdOXpyqFuc6YMLjRksfIELnaDGX3+ga4/3UE1n + ClU/SqKqhwkCWMOHGDjgIge50HBaZRzGmoOdYybv+P50LLmvNUWhIQw01s1E8eUrjcKco41fVN06Qi3P + MulqZypVtMdT2Z0NdLjEj7YdsaOV2+eQ17opAljDhxg44CIHudCAllPUl8X7T0bSy1cN5BJjjAaGohaK + Sia23T5Ef+kKmWFbeXMq1fETXWrbTOfvxVHGBV9yjDLqcgjVL7bx1d1kbj9h8QSDEUYA1vAhBg64yEEu + NBraD1HR1R30x+t6qupIhA4aGMbo1kD/uY5a4xzC9ItzK9YzMZ6KW1dT4a1ISs5ZSnYhejXWbjrYSg0G + Tvkoxgg5sIZPAxxwkYNcaFxp20LVXLj8/kYquh1FyyIM0MBwhqIBsfU2AbpxycdcqKJtExXcDKezTcGU + mLWYbAN0C2Ys0rRkzmgGOh/MGMjAQQKwhg+x0eCyVuGuMw5C41xzCOW1hNFZ/pvbFET2YXoqDfSfYqWh + YRuoW3viciDlNQfRqevelJZvT4v8J1ZPX6g5jzkjGSiCJOkKKUOccsbHjDELfCZmxv+0kHKue6lgcfCk + bg2Ip7dy13aLTplL+c3+lFXvQsdqHGlRwMQuC8cJIRxH8UEMnFpxp3sDG5oYNN9LJ2VduiWdbPCg43XO + KmBdlQYGWntp70s4toAJK+horQNty5pH1p5aRRzDtuPJ31UcOgNYZ0f8wYV0rtGHsuRaPbHAT6dbA6Jr + LnZpvrc2KcPCafxajknXpc/iAJualYdWUk+NvqCkKxrAIUJHnzDw+QSwxgnH1vfvragENjw9dgg7hdf1 + KQMan/eCzxjKu6pIRiEcIJxkAGs09tatl8AmHUJ84fB00MBD9QRi0mFGbWFSMppAEMBaumogA2gGXJWG + 4JPHwJH40hXtqQs/uMKQqM5jld4HPHYTmf/WVwLIddXCksyiempEJJtfREzOEYvBPMfpFbX3iYzC9RSw + eUYKuPKcdx1KPOGgoG2z8q40ZSp0zlbsJh7VezmGnRG7gK0aihF583lmr0g75U/usVNSmaf8PXibiV3l + HG/W7Wp5lq3QSjzqSk5RJp4ch46igeEYkZUP41VwoJCHUKTxcebgVuAA4f2JrevDxNbbhxhOc401qShq + SKHazp1CK6cmklxWT64zNtfQYg52QOiIBjAiyx9sUsHhEn9aEWGUb+36hRnzFF33YaL4kkD9qTx+c7NK + N/I03EuXeRhBK/6oA9kHG2xiDm4I6r5pACOy9G6sCi7yBDtUEErLIwwreFR7M1c6wUhWBnzqS8MMPJfL + DK9kl66nxifpojB0DpZ40bJwg/OmczX0mIdzpHgQ0QBGZMEtmcB3ha6UUxcs1hintY92UHFdAsZol0O4 + /jket6tsAyaZWSydMBbAGj7EwCmtT6KGx6lUdm8dFd6OpIxLPsSxjvnuOm5cq9vTw0QDGJHZV30pbr8l + xm+5Xcik3w6VuYpRWswzvLp9KzU9TqM8/q2QmulFskQrcok2EcAaPsTAARc5yIWGXajey/keOjFcRzrE + 3V4jGhiGERmz14IHkM4+/n/8PGftNTaBuh27ziyhUze8ea4HUEmrjMXX040nCdT6fCfdf5kmgDV8iIED + LnKQCw1LV+3VrIkfLYorzFAYGhiKEWntoY2rhu84vtVjzZeN9/jGW6csas9s2p1nS9n1rvw7wZML+FJB + SwAV3QwSwBo+xMABFznIhQZroTg+0d22XjJ0NISnIT4y2CK8I3SKWTBSd+ooQ56KW3jM1vttNaU1B8wo + 6bQVpZ+3oR8r7QSwhg8xcMBFDnLlmtDrtTgM7wMnGyTl7zQaw/9oaPQ4vWGTZi7RDPzaafxBS3etKm74 + KY/V1wDW8CEGDrjIkedCQ2XblQ0BqaAyUfKjczQHMWzlWAZeE8aqNLqxhg8xcKRdRC40+iyubH2RlBvB + 10t6PdLIBbCGDzFwPqjw+xrEpGawUyiiDPikou9fuLdJ9v+B+v0LVZMvjm9OYQEAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem40.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACt0RVh0VGl0 + bGUAT3BlbjtGb2xkZXI7QmFycztSaWJib247U3RhbmRhcmQ7TG9hZPHDxGMAAALOSURBVDhPpZN7LJVh + HMff6N5qtfqjrTURf+hGrWQunY5JLkklImm1mjFk6b5aizWSormEQ8nlHKl2ElEicjnIOTg4pFq5nON6 + HA4yjuO835637GyZ9Uc922fPs+f9Pp/n9zzvHgrAf8E0HYLuDPNnembur00rqE+yKRVzbCBO+k1Dgg0q + oq09SUanLp5NieL3UqI4FiWKZVHCGBZV+2DPLEECG/R01wydmBqToJ7jNBh+2ngdyS2cA6bKeVoBsYJW + NYMeK4BmJA/0SA6mFG8hjLdH1T1LVN21hCDCAoI7FqgIt0BJ6O5yIligFdREWYOeFINW8kEPPQOt4EEj + 50IzWkTEEkIL+U42mGyEZqIepbfMmJtbrBUwZnqiDvQgWdiXArUsFurOKKjbIzD1PQxTX0KgarsJ1afr + ULVeQ47/JkawhrCUsIgqCzUHPV6N6e4EdL87i+ZUZzQ9ckZjshMakhzRkOiA+of2EMXZQRizD28umKIg + 2BT5502Qd27bAFV8YxfGpS+hqLkESbonKfMbKbedVEX6ia9E3gbNDwk5khjTwyKoFdVQy8vQL+Qg28dY + SBVe3oGe6mhIUg+hoziMhAQYrb2KkZqLUAqCoawMwnB5IIY++GHovQ8URWcgLzyFj5G2SPIwDKFeB5mg + KSsAleEsKD/zMd7G+SMoL/DGQL4XBnKPoT/HDb38w+h97oJXflsRYLXWhOL7bkbJbQcIIp0wKc3FYJEv + +kiwj38EvS8Ooif7ALqfOkDG2w9Zpi2k6Wy0xlgg1d2ghVzicorrbQS+/3a08AKhrA0jQTvIMkgwjY2u + Jyx0PbZCZ4olOpLN0cExQ3viTpRd2YL7jusjmd9JcVz1arnHDZF1wghZXkbgkTHP0xBcj43IZHBnMECG + G+GoPtJc9ZHsskF60nS1MRH8ejNLCCsIK+dg1SyYuWUE3VQXPYpB+yj+DVA/AVjcWk79JZvUAAAAAElF + TkSuQmCC +</value> + </data> + <data name="barButtonItem40.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACt0RVh0VGl0 + bGUAT3BlbjtGb2xkZXI7QmFycztSaWJib247U3RhbmRhcmQ7TG9hZPHDxGMAAAfgSURBVFhHxZYJVFV1 + HsefVpNlqS1OqTkFaaNzmkZNxkwFFagQ3FHTSVIzxhgdTc0VMLdxRVBjExCRRUVBSK1EETQW2TdZ3Nhl + Xx/vPd5j+/b93/eePhs6x5lT9j/nc+7lncv9/L6///3/75UB+F3p9sfHSbc/Pk70o8cj8qsNwwLEjZ8g + T3XDH3SIc3HNr1aEYQFPxLqZWmb6mqdk+1lAT5YeXy3xh8zm89onSY/MI+YyLZNlGd7mRByJ1wPSPXn0 + nCRL9yDuWgyHYQFPZfqYV7WUfYsuTS65YUCORFtTPLKPTatxc3hnIK8XRfT8P3hoGg0LeJrVAx13gdYL + 5DygOkciAWUEoDhLzqEu+wASDpqd5PW9yTOPwLMGiL/FVN6fRsMCerFdQPttnfjbB+KWMEB+BmgORZc8 + nEUcQsphM6Qc0nHQDMl63EzJBCS5mhIeD0zAdRctcXvHp4VuGD2FrqeJ6MbDBaS5TwTabnUrRtNJoDEE + aAhCV+NpdKli0aVOJ2kGpOpIMSBZRxKaC08gbve4arpEN0QXHirgmZSDpiwgr3txfRA5jq7aY+iqOYqu + al90VRwhnugsd0dn6WF0FLuho+gAZ3EfG7kb7Td3oi1/O9pyt0KT44T2O+6I2zlW2J4jUgGG41nRMvCh + +3liIYZeXEVx5RF03qO4TIgPUepK6X6039pD6Q6052+l1BltOY7QZG2EJn0d1GlroMlzwRUnE1FAXyKW + 9EMPZe/E/eP58GU9ENfpElfrxd4PxCUUFwvxXkqZ8oYTZeuhyaAodRXUSSugSnSAKn4ZlNeWQhG7BKpU + R0Quf1sU8Ap5nvQi+odS1jt+zzg+fJxLIa7xfyCt8GCbDzOtvsX70XFHm7Yt1wnK5JW4dWIWkr/5AMmH + LIkFktwm47rrJCS6mCFxnykS9k6AuH/kv4wR6WCMCAcjhH9hpAj9/I0gukU3ZM/9yPnp4FpvL/NEW8lh + tN1xgebmLmg4j+rcLVBnO0LNlqrS1zPNGiiT/o3K8//gRjUHdXlnuFcUkyJSyIeOtN7VcZsP7S2JTmUB + yUOnIhfy0micWWpUTLdYFbLnr24bA3XlJSgLXKDI3oHKaAfkBMxEqrcNUr2skeJhhWR3Ky5BJj1oietu + FiiI+Aqapkx0KDKhKfSBOt8FrXn70XpjL1pzd6M1ZxeU2TuhzNoOZcbXaElzRkvqZrSkb0Vu0CcIsnvd + j24xDbI+Mc4mUBSFozHZGXXX1iDN0wattWIJ6RKpmUZ9R4uU6iY6lPlor4tGa74rZXugyt4FVY4Q7oAy + cxuU6V9DIaQpjpAnb4T8+jo0J6xBc7IjYpzfh4ftoDl0S1PQN3rzaDTkBKDi0ircPrkA2cH26FTlQ8Pl + oy5wI65SQnUuE+buo2i3lqz/QJG1EwoKFRlboRDSVCdKN6M5aQOaE7+idDWa41eh8eoKshz1V9fg1CLj + VuvhfV6mW3oI+0WtG4nKhMO4e3oxUtwsURzrgo76a5KsNXcvZbqEFCopVGZu1wrTtmhbm+IEedImplyP + poS1aIpfjaYfV6GJwoYYBzRE26P+0lLUX7ZHwbHZCJg7OIpesT1Lu2K/778cgaKLO5DjPRtX2J7mO2HQ + lARLQlXmTqgyOI/p2yijkDJtW4VwIxOug5ytbYqj8Jo2ZUP0MklWd/Ez1P2wCLXf2aHm/HzUnFuAq44m + cJ82cC2997flFy4s/yvyQ9ciYddkxG6fiPaqC2hJ+BLyuJVo4dwphIy0XN8AeeJ67VzGMeU1tjZ2hS7l + MjREfU7pEtR+/ymlCyldgOoIW1SemYaKU1aoCpuBUDtjrBz70tv0Sq92UcCLkf/8C9J9luKH1aOQ4bcY + 6kJ/NEV9isYoOzRctEN91EI0XFqCxphlaLxCWSznMvoLtpWtFSkvLkIdU9ZyaVZHzkV12ExUnbJBRciH + uBdsiXtB5igPssBNr0nwmz6wgE6xGd1/M750dvFbfGPZItx+GEouOqIlYxvqv5uP+gvzUHeenLNFTeRs + 1ETwxuEkbDqqTk9FFZNVhdqgMtQa9yirCLGQZPcCJ6H8+ESUBZih1N+UjEeZP9+Km/6Ggx8O8KRTvJR6 + Hp06SPhlL5/6ZAiiNlngzJJhkGftR8PlpaiNmIWaszNRHT6DwqmUUHRqCipPfoSKE5QxWYUkm4zyAAop + K6ekTMiOjkOp3/so8R2LkiNjUOz9d56/h8jP3sSWCf0X0im24h5+1uL7Rib7Y6CtEcLsR+Ly5vGQpziz + hUzIVFWhVlpZCNsYzDYGUshk5QHkmJmUqsxPKysVMp8xKKWwxNsEJV7voshrFIo8R6LIYwQK3UfB12aQ + esQrvQbTKdZ/Dx8rbQH9/WcMRvD8ochwny4tl0op4QdMyJaKhJJUCE2ZbjyF45iICX3eY0KBCYq9iOdo + FHq+i2KPURSOJEI8Arfc3kGy03C4mr8aQ98L5EmfjwbIBGL085oyOC1o3lAWMQwhH/8ZwfPIx0MROPct + BEkMQdCcIQgkx23fxPHZZJYxj8YImGmk4w0cm0Gmvw5/wTQy9U84OnUwfK1fwzcWAxrmDO87gT7xSdfT + z3qQTCCG2I/7kP5EvC5f/RmizF9C9PCXEHcXiHNx335EWvt+1q9Jcn0BYjMQa1IU8qiIG/0viP/Rf03/ + 10epGPqvk9+a++N+AfqT34tuf3x8QPYTe6ndyZod4FAAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem41.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAADZ0RVh0VGl0 + bGUAUGFnZSBTZXR1cDtTZXR1cDtDdXN0b21pejtEZXNpZ247U2V0dGluZztQcm9wZXJ07jthbQAAA0NJ + REFUOE9Nk3tMjWEcx1/m0o3cyW3G/MU/jc3K5o+mMbk1tqYtZjLkciSKKI5JK6eLczqFYjmFEitFuqCI + zkGXZS1Ro5Jy6nTOqc717Zy+fs9ztHm2z/vueZ/n93l+v+d9HoHa5Iz8xtrMh81gKB82QfnARUZ+M9EI + RV4TFKoGyFWNxGek5NS/o7hpAFi8MEWZ34Rx6nHo4WKc45zA6cJBpN77yCLdJwRTb+Y18CCrzQELYbY6 + MGoWMTxqc2ESMWJxYNgyBvuYEzfuqFmkB4+mNi313icuMFnHYKJJIyY7kpRPIIm7hYTUBygur8eAwQID + fbeJTiRmvmcCz5CDcS6BjIws3VGLyFc20kRFdhHOxKahtOoTslTlkMry8Edn4hleldcxgdee/Re4YHpi + 1geqzQk9pWsYtdNKInRGK25mFeDMJQXau/SQ55Qgt6CSyrEjPq2WCWYEh0Zzgdu1jDrYRREXr99FSYUa + A0YLdMM2dHYPYEdIJOpb+1FR+wXHomQYMpoRm/KKC3aGRHGB+2UyWqw2HI6U4bbqJR4V16C7T4/7j6sh + zy5GXUsf1F/6sC88HtqhEcQkVzPBzG17T7sEsbLXXHA0KhVPyzW4lfscEdFpUFDaNZp21DT9RlFlC8KO + XMVvrQHJt/kmem8NPskFHueTqugXipDfeYIrybn41q1H/5AZHb1GaNq0eN3QQ5IePlb07A3KqtuYYHbg + zuNc4HnuegVE0YEOqvlghBSSWAVyCmtQpfkBVYkaFZouvFT/RPN3LS4mZCMxrYAJFhGTmMAr8hoJ6ID0 + DprxvXsQSekqBO2JwJp1QfALCEG4JAGlbztR8q4TDV8HECPNwjr/XRKKdeMCifQFP2Ej5jF+BgYNZvQP + DuNXvx5dvTrcVT1FaPgFPK5uRwGhbu3DieiUcV+/3WFM4HY0pqj2RHwZIuLKwN7H40px7FIp9Z9Bmv6G + NrYFMfEZ2LXvJO6XtxGtqFR3YGPgAR0TTCbciZmENzHrH7P/Yy6xeN6C5Wc3bw8bVxZqkFn4kcoL0wrs + Rk3cqmWrNwlLVvkLPis2CAuXrxfmL/UVtgafEhb4rGTDbMM8vOcsOuS/+YDOL2C/bq3vltC/pJl/VsY4 + 5MMAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem41.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAADZ0RVh0VGl0 + bGUAUGFnZSBTZXR1cDtTZXR1cDtDdXN0b21pejtEZXNpZ247U2V0dGluZztQcm9wZXJ07jthbQAACGdJ + REFUWEellnlQ1OcZx0mioiYxl0mbXjPtpLf9o+avHjMdp+201XQ60yMzaZpEES8sEQQMEBAFAYlyeaES + QIIgcisB5Fyu5RDkWJD7hoU92AOW3QUW+PZ53t1lECn0eGe+84Nd+H0/z/O8z/O+DgAcVqxnbHrWpufW + 0aY1xJ/z/6+72NOu1QDPRt+SlkV/UYNLiTWIZiVIcSnB+owiWZ/ViIqvRmRcNSLoGRFXJXQmPD+Q3sEg + DP9MYHSJQ2BUkcNZ0sr17wCY/Dk23WjNzVkwY5qDfsoE5eQ0hka1aJCNoVTaC+/Q7CB6z2aSgOjoUawO + cl2ATVGJUvoIsCwuwWJZpOci5i1LQnP0O8tktsBgnIN2yowJtQF9wxpciK3A0hJwv6QDbmfSz9G7tpAE + xAoPsfh3u54GoJTymicjlt10bp4A5hcxa5PJPIfpmTmoNUb0D6tx7mqJADCYLMguasdRn9vB9D5H0lP7 + gj3tWg2wOZJqyYsN58nIam41Fc+5RZipBLO2MkzqTegdnoT/xXwBYKLvGSIjrxVO7vEh9M6tpCcg2NOu + 1QBbwm0AKw35ZzM/beYsE2vWAg3tg95BNTyDcwQAl4r/1mBaQOr9JrzvEvMUBHvatRKA6+V4kWrJiyNk + 8cvM81ZTYUymds3MzkM3bUbP4CRcT6eL/2OIhUUCWWCQBaRkP8S7ztEMYd8T6wNcuGkFeCJSgrCaztuM + SeZ5koUAZjE4roPfhVwc/iQZzl634ex5Gwc9WElUimYqTwGbbCdxFpbXWgBbw26UWwFsUa6M1mBi0eaj + Dpg2zkJvMENHUmhm0DeiRUvXOB7KhlHbNITKhwMoq+1FZV2fHeBF0oYA20JjJALAHqlJRErGpCky1U4b + odJMUf/rSTqotNNiFigmDaQZjKsMGJHr0U9A3QNq6pBJ+IblsckOEg+p5bUWwPbga6WgMi6nmY1Z0xS5 + dsqIO9lliIrNQkj0HURcz0Di3UK0tPdiQqklGANtSjPU1BmcFbmS4QzwDstlk5dI6wJwep4/d9nWz8LY + QsZkLqLnlpuBh28knI4HYmJqBiOUiaqmLkTcyEBmbgWGxpRQagxiQKkIYoJmhJa65FSwAHiZtDFAYHSx + baBYU87SG2bFbueeZxOPTyNx1D0UrV0jaO0eQ//4JK4nfYn45Dz6XiWiV+vNUOpMNKxm4RmUwyavkDYE + eOFMZKEA0Bso5bTB1NoZqvk0Jump4dRSvfuG5HDzjsBnV5Ih65FDUt+J1p5RBIQloKTyEcYUWii1RgHB + gXgEZbHJq6QNAV4MiCgggCURsZKMw6JvIy45nyJTQKGeIhiurQaNzR34u7M/lNMmFNe0o66lD+m5lQSV + QmeDAhNUe5XOTJt5Ae5nMtnkNRIfUstrLYAd3DIMwBNOrtDA+eMQXI7PwZW4LBo4YxilzwYpzU2ybvou + FFM0cAqr2wVEg6wfrt6R6OwdhVxFnaE1wUib+URABpvsJDHAEyN5JQCn5yUfaplFApjUGTEkV+HdA75Q + Gc0Iv56OsEvJaGjpQmNrFwLOxyI5pxS6+QU8qGwjydDeM4aPjgdD1jWIsQk9ZcEkhpWrfxqbvE7aEOBl + 7/NfYpGOYq7hAG24Dw4HiN3e1itHYkYx3Pwu42OfKCTfk1D0i+gYUiK/ohWFBFDf3IsDrsFoftyH4XGt + FYAOJhff/xzglVMh9wSAigCGxtXwDYqh41WK5q5RimwUE3oj9HRCamlEdwwrReR55c0olrajoPwRPjh6 + lqZfM7oGxzFCc2CKjuxjPqls8gaJz4N1AV71OpdtzQC10KhCh/sPqrH/eBD65GqU0W4vrnmMQjJ7UCUT + kedJWpBb1ox7pU2QPurBhaup8Dl7DdKGdnQOTNBeMuLIqWQ2+QppXQBOz2snz2bRaWYFkKun0T00gU+D + rsIr4DJaumnOU5qLpY+FeQFFX0JAbJ5d3IjMokZUPOzEtVv34HX6MqrqWzEyrsIhryQ2eZO0IcBOt4BM + AaCiHuZJNkJZkHUOIvCzWLx/yB/xKXmob+lFZ/846pp6kF0ghbSpF1mFDcgoqEcaSVLXiejPs+DuE4n6 + R22IvCkOo2+R+Ia0JgB/yACvn/DPsGWATzkzHS4zYkO106DJyiuHy8lQvPO3E9iz7wj2/tUVe//iCr+Q + G6ii9LN5an4dUu7XoJQyE0md4/bJRVyJFZPwh6QXSOJOwGtNgH/6pcFCu5vNBQDt5DEqBUP0DCkg6x5B + Y1sPRd+BmsY2FErqsP+YP06H3oSkthMpubXUIVIkZVehqFqG8Ji7+PBIABy3Pv8bev9XSctlWA3AX7zh + 4mMFYGO75AzBx6xiijpDhwG5Bv1jk+gZVqGNgCTSJnx4yBd+wTEore1AUk41ErMrcSuzgvZJK85fSsGe + vQebtm3fsZs8+FTkobdmBnYe9b5D1ynrDYinGA8Sq/gywscyHVLUWno6ZPR8K9ZRieRK1Da04B/Op+AT + eEW0ZAKZx6WXIzZVIjZsQFg8fvHr91LJ4xskkYXVAGISOrnFVxymtjnkRfKkKxbpoGeSuGI50RXL6STJ + /QscIO13SyTdwkcnEhB+LQ/RdD/Y92cXeJ6OEh0Sl1aGm6ml+DxNgiLKxG//eExDHt8jbWPPlQC8xJ2Q + xCniocFt8zWbvr6GOBK7vkn6NuknmzY7/m7X7j80e/hFoKCCIO5KBEgBzYs9+w7L6W++S1oTgLPAEJwJ + ThHD/Dfiqzff+97cvGXbz360+/cNx9xDaDo2Ibe4QRxcu3/+p+v0PcM/VYKVi0H+V9mzuHOL4/afvrXr + V3d2vf2O6sdv7xv/zg9+yeac/uXL6TLAav2fi0F4Q3MpuTTft4lLxeacYf4b8oLDvwCnrN07yt5H9wAA + AABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem42.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAcdEVYdFRpdGxlAEFuYWx5c2lzO0RhdGFBbmFseXNp + czvmB6eEAAAGoUlEQVRYR71XaVMVVxAl7nuWL4lbVYwmlcq/it/cBcUVWR7gEwEFBRW3KCpGVEAFRRAX + XGIwZlHAkJItGhGUHR6PtXNO37kzgzFWmQ+h6lQvM9PndN87dx4Rzt8EYOJ7YNJ/xGQH9FnnAyBiQm7B + wxsni36Rd+EEUfgGChwU/iy5RMG/4/h5i4eKo/lVNx0REROPnv1J/u+/nLz7Am5OI2LSkXwjYGhoVAaH + RhxYn9aPEQmPu27iMOLwoBPDvgtjY2Oy/+QPFDBFBRw680DGIMBf9G1QErVODsUIf/GBt9i2jj7JOXUP + 8TDiYRmFgH1+AQdPV0GVOIXZielGQUK/dcDC4xBmcfqwYScG2tr7ZN+JO3IhuMq9RgHZufcoYCoFTM7J + +9EIwA1+As83eS3gXAs5VgGiEAozF1ISxsPS+rpPso5VyqWMKKnbuFBz/RQwOiZ7j9/1BBw4dV8F8MGw + whR2BTHnkNvYEDvQaySGAFwz5L2y52illN/5Q5p3fi11GxZIaAACAArIPHbbE8D1oACqN52ZYuM6VzKP + yHbuAoU5BRK0vO6RjMM3payyTuMmFbAQ/pD0hYZkBAIyIA7c0yhgSvaJe7ozrXqX7I1Yx6yAP0Ay65vO + 6Le86pX0g9el9NYTzZGwOeUreRK9QPogoNcKOHLLE5CVe1c3hhYBMnGxFYVI5hF7RBbMWb8vNCwv2nok + 7UCFXLnxRMlI3ot8U8qXRoDGQzI8Mia7Dt2kgOkUMHUP1oProiNCsbOB5ZKeU6Hd+AnHAYVJSqJ+FCV5 + yr5yKbleK739hqiHFmiEgNr189XvUQGjknbQJyDzqBFAhSzI9cpPWCYp+8tRuNd0QyKFQ8x7HRF/tXZL + MKtMiitqXFJai8agEWBjCkg9cN0TkHGkUteFqonmnVgz7NrL6Ca4t0wJSMRx8rodJfH8Zbck7y2VS+XV + WrzbIfH7jcElUhs5T2NiaHgUzVVQwAwKmLbr8C1XAB9o0k2DkSEuvlYtSZmlSqSFQ4OwxJA8a+mWxMwr + crHssZMbNCR9HrqAxu1LpCZyrvrEIATsyL7mCUjHeoxgY1jVTTu4aeabIohJkLC7RP580e120Qw/gFzR + 1ceGqNcUf5ttSFostavnuTmetsGscgqYSQHT03Ju6M60qimgNsoI6CIhbNHVRxKXXqzEFBKfXiIFpY8M + iYPOvkEDEvUa2wnbkLhYalbPdWIjIHlPmScgmF2u62If0E0ThTVDMQMSDErhld9kW+pFiU0rlgL4JGGe + zxiEXXT0AMzBqoBVc6Wje1DzPMTid5dSwCwVkIyNRlWdPXzArJluGhTqIkiiCMux6KXyXfS348isgA76 + JLZA3A5bH/hCqiGgvRs5gOdKXPplV8CMJIzDCEAB3NBAAWs4MnTodmZIuJ7VHKdDYMlI5AI12nsGYAkI + SFgkj1Z8ZvIAX+VtaSpgtgoIZJTiczuKQmZEDYnYtdg0nIgdo+2oPmDGaYnYkRKRELnXSuqB8dN4I+B1 + F+IuIyAmrcQVMDOBAvAbwBRz1gxd2g5tcdr6wCKpXjnXECGm/SfC8gr2FQgJFbD8U3nVaWKeKVtTLnkC + 4nZd0Y3RDnU6MrtmOkanK/iXbz6RuOSTsiG5SDYkFUo0kUhboHZ9YoGsDwCw6wLnZV1CgUTBRiUA8eel + jQI6wzhfIGCHCphDAbNisSG4MTgejsnt0unweWuPHMCvmjR8H54+69CcdtcdMp1qDN/puE0RMhakxgfo + AzzgNgcvegJiUkv0y0YBHFM9RlbNNUPhX39vwSF0WU4VPZCXHf0OAYrhGq2NKcAQMTZErZ0haWUO1pK3 + AjzwNm1XAR9SwOytqcW6MUjOm57Gf66b5tK1GozqolRWNbgF3g4QjbOeryJc38Q8STdiGT0BKcX6GbYF + q+O/kbRNcRLMvip1Te1u3ituY3/x8f5LomPAWORoWxl3GAHRSSrgIxWwBV3yc2sJtsTkSO75Kvy06vcV + tSRv+rQk88GJLaE/R3TiZF2PTWsFzOF6cGd6xZ3CThG1tiitc80U9JH4ci2O39IO+K7R56nKt8UKmL1x + +wX9paKfWwvE9stn0aUWpyM/uyhC8Jh2j2oeWtb35xTm2ObBxvMlCq+oFTB9dUzerXWBQry7fH/NO8x3 + NxI3RSack8h4IO6crI07K2uIWGBbvqyOzZdVsMTKmDMGW7+XFVuI07IC/nJYxebTsozYlKdYuvbwbXDr + 15D/mvOnEd9J7kqCyt4HH78HPgH4DMgjJv4N+qeFtt1UKpcAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem43.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABx0RVh0VGl0 + bGUAVGVhbTtQZW9wbGU7R3JvdXA7VXNlcpN7YEkAAANjSURBVDhPfZJ/TNJpHMe/VPNXiuZWa3a76iyd + GVomUVqRpUKCQIHlpmiOnJlopMmgA6KbRiemaYKcR5b2g5bljyXJMjIzbeUy7fdhbXX3z533T22F/bB7 + 3wNtra3NZ3s/fzzv9/u1Z599KAAUj8ejJFwJJRQKaenp6TQ+n08TCAS06Tw2m00FBwdTXgCXy53RKluZ + 11EU/6SrOH7SVrDimTkrpoyEZ07nfQUI04W+Vinj3WUV57/RxjwMGQQ4JolECX912HSewWD4AhDwBEE1 + kqiPd22VsB+RwlFXiguVRVN//flq78TERGFPvXrqaZ8NPcY8NBckQMdZ+Emcxpnn/YHWmkSJRKJA067N + d545GjDp6sZIqxp9B5PdgwcT3zjL46baFBveD7RWwu26gsHabOj4jJtkJnO+AsRisZ+5NFMx0KjA2wc2 + tBfFYaxZjv7qbDw8q8T1SjEqOIvxeuQsOpWpUApYJQQQ4AWQixYeHu6zhZMYfWx/qtth1sK8fSm6NEJ0 + aLbiiGg5LNI4qNk/wm7S4FA+072BzYqJiIjw9XSpkJAQ/7La9TK9NflJ76gBoy/aUV+YhE59Ntx/38U/ + Qw0wSVkwytNwz3URHbdV2FvFfJpVFl1AukHUz7+xrzfZc+B8VIG24XzY7+txqe8wOnXb8e6lE//eNKIx + Jx6Xrlaga1iN369lwOqQoqxuLSSKxf2U8njC57ahEph6tuFoZyqqOzhosatRV87FvTNa9BszcSh3Jc5d + 1Xk9XUsCyi1MqCwsCOVhn6mcA9ENuZplYzJN7B96U+bb+tP7YDxR+GFfVeJUjXIjDCVrkK9d9am6ec9k + 3WkFVDWiSXHx0nGObP7DTVnzLN4ZENHJQOZwc35aUVjLsKmszPddI7vRPbYHzYM8mJybsPOXJR95RWEX + GBtD19Dp9Lmk4zkBlF6v94qcWcXHGY9P3tiBa+Ny9LjycWo4BY1Da2G6xYJ5gCzQmdVg54a6SNaflUn/ + 0vsG4COrioSll6xq7zoctsfiaF8sjE4GtO2RUJ1fAnnTIjAzgkCygbF8/+8As7aV/qATKBZ0p8nnP0gp + mDuetCsU66UhYGUEP1+1NfBRzBZ/R1Sy368k6xeV4vMdgOaBEPkSBRDNJgr6RoFEnnePPyNqswegp/4H + 6rXSVw04ZQQAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem43.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABx0RVh0VGl0 + bGUAVGVhbTtQZW9wbGU7R3JvdXA7VXNlcpN7YEkAAAnYSURBVFhHxZV3VJRXGsbHklA0q4IJMatGLEgb + UCBUKUoRRJFikIBIk5E2dBgJbRgcUHpXqtLLwEgVGAEpQY1IJKBwbNGFZE00q4nZxBzXzbP3Etlk0D/M + /pG95zyH816+9/0933fv+w4DwP9Vr9z8M/XKzT9TDC6X+5I+TdRfdomn73SBq5szFKcz1B+tfb/viBbO + RWjeOhu6tbCNra487/nXyhH6qYlxqF7aGI7XfftCosnN8TIf3GiKxdejzXh88xM8utGPL0QFuJjjBkGA + 1pMyVwXNdh8lRhtL8Q/lzOeJBVSiCM0j45Vh+P5mL8YrQ/FoshtfjzTgdksyBo87oSXUCDUsTWTarBF0 + s5mMrgDVP5QznycWUDX6qAgnhcn4vCYaVYc0IOI5YDjDBf18ezQE7UAV2xy1EXZoiD90jZyhPdVnNbxL + 0xcacKe3FG1x+9DDd/pvTjVLG3kOG5FuvQZcY7mh+TyxgKrEeWP7+WxfFDor4XJNPGpCdiLTXhGV4fso + FM0JbmiOtIKIY/zdJ9EG3/SFqkEUovGsm2NC9i0xKSrFQHEcsh2Z4O2QA8/0PSRZrUessRzCNJe3zOeJ + BVSp1mvyir0MUOKhiwfXmsk5tuGb8RbcPZeJT7imGIo2wN3aYNxr5eHB5Wo8nurEdF8BRk964QxbC6cP + KGH6UwHJ7cBkjQ+m6kNQ7mOMAOZbOKyyNHk+TyygijJaZRlrtAp1odb45z0R/nV/AM8ejGIk2xlXsh3x + RVs0elOd8PhKJb69UoOZ3ixcrwrBcKoDzkZuw+mP1qEueOdszre9Mfh24BhOsQwQoL78qbvaO1rzeWIB + lZWVlUSyvUalMMrul5/uduLnGRHRIATeTFwv98FA4k6UuynhatZ+3K4Px2QlGxfT9qE9RBsV+9ei0EYO + adbr8PN0Px6ei8aDnkTkOan/wrVRS7GwsJCezxMLqDQ1NReam5u/W8a2nJzuy8WPU3V4Ml6LE7arMVbg + ipMO8ihkGaPCVRGt/hpo9WWi2mUD8nevQs5OGWTvlMUxS3k8GasiBmJxrdwP/D2KN0xNTdeS2os4JzQY + YblbGCFZTEZQpvLLBqhMTEyWJjgb87t49njQxcF3o5XItd2AjkhjHLfegKsdmWhPP4xEq404oiuLUG0Z + hOjIgWu4DHyj5Sj20MPjkdP4pjsOgpDtYJsppZKaf2GQFZypyghMV2b4p25m+B5XeLUBBQWFN7ab62xN + 9dn2/GycDa6fSUGesyYKPlRAvrs+Hk7U48ktIWYuFOK64AguF7ijK9kFQRorEKO7DPVRThivjSddYYYY + J+XnekZbtNetW/cmNdB/g8PonQplsPjyDK/E98UNkLWQ6M3ARGNmWvXe0Y6mCJRyHFDN9UZp+EeI1JFF + C9cJT78Q4vl0C57dqcf3F1Ix0xSKqdoIJFisQ6T+O+g6lYyTQbZIctbHxz568E7cfMXCZRWT1JYkWtQx + 4c9wj1/DcI1b9auBF2CJyDQzvbQaG0FRm8vz1ktRKKp1RG8TB/1V8WirSERppB3O8pzw7HYdnt2sxk/j + hXgoisW0IBAzbfHI268Kvps+Rs6fhKgoDDlRu+HJWouk6h0ITFP6t/OR1ULzg28bEpY0ZTodeZuyGQvt + WJtWH6/a3V5y1g29Y3xMfFWC4TsJqBn0REyRAdxi5RGWoYPK1mDUhO3Co4tZ+HE0F4/6E/BlUzCmG8Nx + qz4SSTab0NjFA7fUdDbHN1kJSXW6qBjei4bLLshoMgUrWR4OwbI9TEOpNYS9iBp4MyhNvbFx2B9jM4UE + zIfoegg6JwLR/rkPzlw9BMGIK0oGdkF4KRIl8bYYyXPD/dZwzAjYuFvjiy/bYtHNs0Mq2ww9V1N/l2OF + /F4T5J0zRHbXNuT1mKLovBViT2tg1+G3aglbihqQZqcrf91xNRhVF8m8J06bRj3QNOKG6ouOKB3cgxyR + MTK6DHC63w3FVV6o8DfGNLkf08IIAo/DHUEkUuw2o7w2BM2XQwj4t5z0s7pIbf8Ax1u1kNSigeSWrUgW + 6mK335KvCHu2M5b4JCv80PLZYRT0mCD3nPGs28wuPZKsgzSSfKxFE7ndlqgc9EFh+yFEBeog31kdTeHm + pM124BgZPN7uSjjV6Yc68iULRFazOUktW3D0jDp4QjXwmlQQL1BGbIMS+Gc0YO0n9RNhr6AGpD0T3v+K + U7AVkUXKiK5QAbdODXE1qiRJHdmdVigfYKF6MAAZjR8iKm8bpi6VQEjmwNF9muDuZSLJSQfp3nrwTVBB + So09qgbYKO31RFrbdkRVb0Zo8XqEFMvDL+ev8DouhwNxK6mBHwh79gssWq0guXKXl6zrXj/ZLLtAmU77 + oBWT/okf3Dpa6Pj0aKETonN3IihDExl1DihudcexExY4Ry7fEPkNaDzqiBORJggOVwa/zBKcHD04R8oj + KMkQ3PwPEZNt89QzhnnbkiU1Ze4h2b3dRfKEvr2Ep8x7C0kPMhbPteECojeIaJ8uIaLOZA7Fq3JCszT/ + cbLVBSN3MnDtfh4Gb8SirOsA4gqN4cXdCLeY9aRDtiJLsAtto4chmgzAqT47BGeowNpn+d+NHJdGk1oU + JvOiLm1BOpQW7PYnd3DeIKKLmlnsl8wMym+2x8i9VFyZ4WPwTjj6brHRfysQA7fDIJryRduEB9onvNA8 + dhD1I+TCDlkir3cbCsg9orc9r9MCLP56GDlJ+ZCa9OXovFkgxhQLfl2zQ8k/hXmvfYwF4dg+tIy7EJA7 + Wj93hWDUEeUXLVE0YIwT5w1Jaxkgu1sPGeTCprZrk8unBb5QAzzBFiQKtBBfqQ0zN8kxUpO+Pe371zIg + RYdI96QvyoZ3oHjIBIUEWNBniNwefWSLCLBTBymzHfIC2LgF8fXqiKllIqpKBZxyJYSXKSKuUgtm7pIP + SU16BPSYX8uAtPdRBbRc9ZgFZhFgeqc2Uju0fgWe2YpECmxQQ2ytKj6mwAplRJxSRGipAoKLN4F9ciP8 + C9aDU7oFZh6ST0hNamAx0WsZkDwYs36Qxd+EgAxSMG8zwouVwDlFICWKCC9VBKdSCRGnXwBLNsE3h8yC + tLXwTFmDA7x34fjxStiGLofV4SXY7irZRWrSI3gtA7OXkEhab4+Mgo3vu357/eSybdnvdNiyV47vCVgx + scd3xb09fstg7fsWdrGWwtJ7Cczdpf9m6iZ1bcdByWsmLhJdhvsl8vXsJELk1RerklrLiSSI6MuJM8WC + 3xY1QS8MbRc6r+dacxkRnV70c64koj9nvxfdkyWi/6fPLiWit5+ePYXTuuJMseDlRRNoIjVDRb8MLTYn + anBOczH9S5+jojlz4Fk4XWJMseDVay75f9VL6zcml/EfqE3Re78jPXMAAAAASUVORK5CYII= +</value> + </data> + <metadata name="menu_cps_order.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>493, 17</value> + </metadata> + <data name="barButtonItem48.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAMdEVYdFRpdGxlAE9yZGVyO5LTEh4AAANKSURBVDhP + bZN9TMxxHMe/+MMMm5WSCx13uk51V11nygnJQ0xaLrYeJpRQt+kWx91JeeqMq5asPDbEEnowOtqulbue + r5/UkrI8nJo4D4lbi93evp2N2vrj9dfn+3m9P3+8v8SUu9ROC6UpS0wazoqIIdOPVGcIJVVqQc0jhWdT + uZy/+24yb0bRHi4p3MEhAP5hX7ZZW4htuIvYRszEmOknqT7uU8MUrIYp2xftNwJh0HijJGmxtXDHoouX + otiiCQQMTfaXGDJ9azqLwzHYqcD3F0q0UkFnsQQdN8XouOaD1ovrcV66gO6NETTniCUN50Q13fciMdSt + hLU3DUMvlRjsOGy/YFTQUyHFR6YA3bfjkLVl3nhBg1YEC3MMQ+ZamGuz8Sw/GKbcZWjN8QeTF4CBtnx8 + arsJRitBvZIDzUbWeEGdxg9DXYdpogI/zfcx/O0V3ps0eN+YAevH53j9IBVN6e6oV3NhVCzEiRCX8YLa + Uz4YbJPjS4sMlrpEWBoVsP36gcGeKrTnBaH5OA+NaVzUHVkEw0E2jq1yRkjMySmBEaphwboDIPp0Ib42 + J8NiTMRA9U70P46Btc8A5swStJzy+Juu4tB0Np7K3aCUOCFwq0oipMvcwAQ1eaLyhsWwBx/0cejXRcNc + sQ3feypgOs1HYwYPRhUXtYcWQn/ADbqk+UgRO0KwRqbhBMRrWMJoQh4e8oS5Mhp9lVEwl0vx5m44vjBX + 0XTCA7EyLUISr2Nl3BUERF2AKEIL79DT4CzfP+LiuTXU0SOSkPIU/vYyuddnJn8t3pRsQe/tTRh4qkFD + Og8qWTySsgzIrey3k/3gHWJUpWAJY35Pc3CfbReUJPFIUQLHibastEwuQOflEPTpUlGfthgX9q1AeMod + pN15i70FXdiZ8wz8dWo4eEjbCSFTHUYFtxK45HVxGOktCiW0ZdI8qdtnY9ZmlO1jQ7HK1SyKODviRc92 + Dz4KdkAqWL4y23QXf38qmGwXjH4O2m+SJ11AtGGuRLOB5ZQRPKdUHeRcHCec5UAfzqQ4UpwpLhQnylTK + JHsPxpZiIpZLVXrRplS95+pkwlkWr3f1jdWPnY97PBE+61N0vKD9OrZ4F5kriNbN5m/T/Z+D/AHhxUsZ + 09tltQAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem48.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAMdEVYdFRpdGxlAE9yZGVyO5LTEh4AAAovSURBVFhH + xZZ7OFX5GsdXc8ZzZmpqE7btkltRUwkdpXTRSaFJpaQk26XcIreUZhAil5o0mGiaJo1mmopEGRQSud8p + 94RyJ02h63TO97xrbzWcPOf8cZ5nznqe77L3svf+fL/v713vbzEA/q+a8OKfKcGp8jtDpuKUPlMevYYp + O7maKY1axZRE6DJF4cuZgq91mLywJUxusDaTHbiI2TOfMynWSkXskvNc14S9n1ckus5to7/fXnJU3fjz + bhXOOauZzBkLJSZmmwITtUWeObFRljm2Xpo5os/7AM5KcKo4ZcAMd2b8RxH4o6v71LSvesz/MSNU99Xd + JGe05HyD1qQtGMyzRMtVY/zqrYlYvlLOaTMlv29N5Zf/83X/eBgdY98LrrGn8hj9CaFDj9KY614anHSf + hU7XD6pXVf2yE23ZB9BVegStuYGoTA5FUeRKPEj4Ap2pxujL3Iq+rG1oTd6MvBMrcdJMaThwDS/DV5f7 + pfsScRXiT5rYAJV+LJgt860Aba2MAK0f7oSveX4/3Rndxf7orwpFW+4hFF9wRM4ZB2TEuOK6/yqUxG5H + 2TlT1Fw0Q32COerjt6EleQdar5mhPYWPrlQT+K/isSUQ+cAAe5Sd1BOA0/0Wc3JCljpmBS6urLlogbbb + nuivCMJAdQj6KkPQURRKcA+86E3FSEcChh/8gKcNx/GkKgADRW7oy7VHT5Ylum9sR1e6CbpSNqAjZTuK + DinDe5kkS/tkQgPFkas0C8JXni6NXjf8MNcXfdUxeNaejCHScEcanrano78hCffzzyLrzD6CX8FvtUEY + rNiP/kJ79OYQNHMbQTej69cN6ExZj+50c9SFz0GlNxfZeyVxcIk4S5s8oQHqePTVxeHx/TR0FZ/Aw1te + aL3hhvvXrdGUZIW75zegJGoFbh7SRPqxrRhqO4fBSi8MlOwhuBXB2cRCeE+WDZpOaaL6MA9VPlKoOCCJ + W45kYPF0lvbZhAaKycDz7jA8e3QWIwM1GOmvx0hjDEZKrDBUaIbBLBN0JH6BsigdFMXa4mljBMGdqOTW + 7+F9OY54cF4HtUflUBMkjaoAHiq+4qJ0vwSyyICnlihL40xs4JuVeNN/FG96g0lH6HUM/vHiHvD7U7zt + TsRwsR160zai6tQK1F3zxJPqwwS3QQ/B+/Pd8ChpPeoi5FEbNgP3QmQE6Su9pVBG6Us8yICDONwXCgyI + TWiABg7e9IUJ4K+7D+NVVwBePvLBy45g/D6UB7wdwuuuTDQn8NF+J5Aazh19+fvRlWmOxu9nouFbBdSd + mEEGRtP7UXpvSUH6YndxZNqJw1WTw9LEJzRQeFwHb3qO4FV30Hv4i/av8PzBfloKDww37cervmT81tuE + /urTBKf+iJuN5jOz0HBKkeDC9DUhsmPSS6DUnQy4TMdNm+nYqy4wwJ3QQMExHUpO8G4W7jcKP4CRJoI3 + uuFZvTOe1Tjg9WAhHlyZh5Zf5qD5R1U0fjcT9SfZ9GQgVHZc+jJKX+IqjiInoQGnBQIDvAkN5IctJQME + 72Dh3kL4fXdK7oahUfjTsl143Z9N8LmC9E3/lv4eGRCk9+EK0rNrz6YvcBDDDavp2KMmMCBLmkQSIX1G + mkJiJuWFagvhD73xotWL4Psw3OAuhN8jeDl1fqk1Xnano+U8pT+rIkwfOcHaH6TOp9KXuEoI0gsMWIqB + pitrYAZJRGGZ3S6VNQeh/HdPQQk+yg1ehJcEf942Cqfkz2r3CpNXErzcCoOFFmQwEc1j0492fk0odb4/ + wem+/2PtqfyOYsi3FUU6Xwz28wQGFEhTlHVd7yiv8nguv8QhhzUgcjtQCy/aDmKkmW06NjnB7zoK4WXW + eFK8E4/zdmCk5Sc0x45Z++N/pK/0o6HzPr1w7dn0d3aTAQtR2M0VGFAmiSmtdBuW0eJH0+vprIFPsgP+ + Rj9OI7bZnRrORVj2qlF4kQUe5+9A/+1tZOy0MH2MknDtaehUB8mgzFcKRQe4uOMmjhxncWQTOGOXGFL5 + orhiKoqfjTngq05lDWhwZizSlV++962o0oqV9P5j1sCULD9N6vjR5Cy80o7KbkPJLQXJBwjel2FCSxIx + ml5emD5EDhU08VbzD0Nz+3Gomx6F2pYQzNsUhLlG/pizzhcq+l9ilt4BKK3ygOIKV8gvc4bsot19xJUk + sQ3JcDJ8NTBUxyZ3wrMqewH8tyKC55vjcc52gm9Fzw1jPCkLQUP0mM4/IoPSQ1JwtNoJx/DbiEztEigi + tRMnUjpwPLkdRxNbEHy5CYcv1MEvrgYmnj+Bq2aaRNxp725D0Zs+6uiguf60ipJXCOGDBeYYyKVRm2mC + 3nRjdNPWOlhwCPVs44ULb7uaAGmUU/mj7BZhnWscfC+1w+VsC5zPNMEhpg67ImtgGV6OHWFF2BqYi01+ + tzDb0BdiynrOxBVszezxaYiZkmuyl9pgxVl9DBRY0CPWDmFy2oRYeM+1DehOWoeBnP3j0gs6nzacNCcp + aBr7Iyi+FU6nG2EfXYtdEdXgHy+DWWghTA7nYKNvJgy8UiCz0Oa1yBTubOL+5Z2Bj0hTdFSmLYjiK6ek + eWugOX49+rO2ovfmFnRf20jw9eiKN6D3zoL7/t3QqTjEQ76HJFJtJaBnsBMukbmwj6mFTUQVLL4uxfaQ + AmwJuI0NPhlY55UKbavTEP98cznxJCXm7RBOwlEX76YTd9cKrsP3fOW+W0cW4+EVerBINELnZUN0XFxL + Zmzfpy8jeK4HF+m01YbpiUFHQ6fXyDUWzqdqYH6sBNuC87DZPxtG3jdhcCAVazySMdvAF6JKeuHEmTrO + wDX3z5n717awRthqfMadKjLfay0vIW63ytuyiGV49JM+2uP00JloSdutLIq9ebizTwqXLSTguVj05Wq5 + TyOn8uZtUlzuAnkdJ8hqO0BmkS2kF9pASsMS3AV8SM43B0Exmau2mhgi4wxcdZ3DNCdtYpoSjJiGi+tY + I2w1eKtVp1r560s/jHeeg/roFfTAYYpCbxlkefAQaSQBy3nTahWmfWxEn5UgfUISJXFJUiRpkgxJjsSO + YPnRa5NJ75+OBacE59lMU7wR03jxC6b+ZwOm7sc19Blhb5DmWGiKnj9mJP172pdLkWgnBe/l01+tVZx8 + kv6nSvqUNIl2PEZV/yvdWWu8SmjGlyjquusqLNvLyC3dw8gutteV0dpdwtO0LuGq83Xfwd8biN+jylyw + ncnEWSszZy0Ume/M5JloEzkmwpjdvATTSmou96+mTlpid201OPcUOSIb6Ro7SD52VecwTmocxnE+h5m1 + 1qsnKvEuIhJqIL/cpSc+r5u5mNvByGjZ9gTH5iHoTA4k1Sx6PjDw30QH26Rs6VhHrMaV8Z2UV3t2nrv5 + AC4xlZih49R5ieAXstsZ3kLrzsjLlTD1+ZXthc6x3xn3A/+rlHQ9DBUoOTVij5y2gyE1IkONyEipWxlK + LuD3SM7f2UPNZzj2O+N+4M8XmH8Bjy5oxLkr+soAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem49.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem56.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAU2F2ZTv56PkJAAAC9ElEQVQ4T4WTXUiTURjHV6YhYh9WmpSSGQPBNG1tuvk65+a+nHPT6WxOt+HM + r/zI75WmBkURdBME3QYFIYUYRVFBdJkfF2GpEV2oTec0K5crb/6d520XEkEHfrwv7zn/33nOeXgFobGd + EcbY8Rfh/yAiBM1vYwjCOE3FK05XAZt7AL1Dt9E1cAvt52+iufcGGtqvw91yBY6GS6h090NvaYGsoBxZ + ytLXLEtCQQSntcIzeA1WVx8CwU0ENv6wHuL7j034vvyAdyUAtakBrT2XkK0qBctGkmCntKAM3f1XYan2 + 8EFavLhKBPiQWKqBmNNiYtYHpcGNElsdJAozCaJIEEm2jvOXYbJ18TtS2BsKf5hbQxang7rIhgV/AHKt + kwlqIZIXkyCaBFHifDPaWFlF5W2s3F9YWA7gk/cb3n70Y5ztyimMMJQ6Mb+8jpyCKphP1yKTM5BgNwmi + T8mNaO4chLakid918oMPEzM+jDPGGG+mlzDHwnO+dWQrbDBVuJEu1ZJgLwl2ka2xrQ8qYx3yC2uh0NdA + rnEhV+NAjsoOqbKSBU8jK68CErkVxdYaHBerSbCPBHvSpTqcafGAKzDBWO5iOFFU5oTB4mBUo7C0GvqS + KuhK7NCZK9mcCykiJQkOkCAmVaJGTVMPL/jfkCnZfVhcEGbkkSCOBPtTRCo46jpYucX8otXvP7H6jQhi + 9WsQfvbuZ88VhiRPzypyIDmNI0E8CWLJZne3sjMaeIGfBSnAsxbE8toGj48hkqnZUaqQlColwSESHDyW + ngur8yy7ID36R2dxYWQGPQ+n0Tk8jbb779F87x0a706h/s4UTso00BRXIjFFQoIEEsQnpcpgsddDlKPF + 9ddLuPpqEZdfejH0/DP6ni7A83ge3aNz6GBkZKtYV8xIEIpIkEiCmMPCzDEyZkjVMA29RNHFF9B5nkHd + /QSKc4/ANY8gu/4BTtUOI02cD+EJDnFHjk+yLN8F+i2pn2Q7soWkLRzdQnLoW6xAIAj/DQXi/m5m2Bwf + AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem56.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAU2F2ZTv56PkJAAAJQElEQVRYR8WWd1TUVxbH3ZItycYkpm39d/+Ku1FRikjvvQ0ww9AZGJgBBhh6 + GRh6R6RIQEWxIGKkKKLYgsEaY8EuKEWRCCrShKjnu/f9hiEhuMecPSdn3zkfHo+Zw/d77yv3LgHwf+Wn + 41fEr/9HfvMzUH+X6Swa7IO3iN8Tf/wJb7+Bd34m7Lvs/zMzC0ywxVth6Vsy5Hk7X0YX1COmcDfiiuvB + F6fD1iMGtoIYeIhSkV+2G7ml9cgu2YHMou1QFmxDal4tUrI3IzGjBnHKKsQoNiIqqQwWjsFw8pbD0UsO + B49I2PFlL614kh2kxUywgOcHW/whInfHbNPxK2g50Y3mzm60dV2Hpp4HjCw8YeMcDM8gJZ5NzWKMeDqp + 4snEDB6Pz2B0/DlGnql4NDaN755Mw8w+EFV1+1FZ24ryTc3YUNMEW7fwl6TFssGyMD/Y4u3w7Do0HbuM + 3E3tyN7cjpK6o3MGhLBxCoYwMJUTvNr/BN19j3Hl3mNcvjuKS70jWKllTlhipTZB8/2RCRjbiiCNKYE4 + qhCBEXlIpixZu4ayk/funOb8YIt3wtK3ofHIRWRVtxEHULytA2v0BDA0F8LaSQx+QAoX3cWeEXzb8wgX + 7jzCN7e/w/lbw1ilY40Vmk4k7gx72q67Q89gaOWHkLgiBEXlQRSRi/jMarWBpcRvmbB6MAN/kio3o+Hw + BaRXtSKjaj8Kt3Zg9To+DOYMuPkm48HoJM7dHMbZG8M4c/0hTl8bwqmrQ9DQtYPGWh4ZdoetezRuDTyB + noUPQmKKERhJBsJzEZteBSsXKTPwHrHYgERRg11t55BW0QJlZQsKtrRjtS4ZMPOAlWMgeN6J6BseR1f3 + A3zdfR+dlwfx1aVBnLg4QMJO0DH0wFpjL4oyCldpW3TNvBAsL6LocxAQloXo1ApYOEuYgfeJRQbeDUmu + Rt3+M1CUfYnUsn3I33yQInOHPhmwdBDB2TMed+4/xYlv+3H8Qj+OEh3n+9Bx7h60DHjQN/eFkbUIFrwI + XLj5EDrGHhDLC+AXng2f0GxEppTDnG4Gab3WwNKghErUNnUhqaQRyaV7kVPTSml1g56pABb2IrpKsbh2 + bwQdZ+/iENF+phcHT/ei7VQPtA3dYeEig7mzDGZO4ThNGdIy5NMBzIdfaCa8JZmQJW6AmaOYGfiAWGCA + LZYGxJZj095OJNIbkFjcgKyqFjpcrlhnwoe5XQDd42hcuj2MA109OPD1HbQyTt5GC9HceQunrgyi6/IA + Tl4aQOfFfmjqu3H77yXNhFdIOsLii2FCV5O0ls1pzg+2eM9PXoKN9ccRm7cT8fm7kFnZBEuXMKzQdsEK + LRfomfnAyCoABlb+0Lfwha65N3RNvbDWRAhtSre2oQCaFPUafXc6E67cNQyg/fckcaFYSQeyEEY2IrUB + 9urOD2bgfS9ZIcq2d0CevR3ynO1QlDZAWd6I9LK9UDI2NNLM1o1I27AHSvo8taQBEakbIYkpQkh0IcQM + 2vcgunYiWQ586fAJg9LApzckKDKfM09aHxKLDXhI87B+y0FEZNSqyKxF1BxyNmcxts7/Ls/cgghlDXwo + Qh9JOrxpZtF6BjOU8BCnQcDERQrw/RV0E3JgYOnHDHxELDLwgXtwFgqqWxGetglhCoJm9ruMzUqa1aTV + ENX0txoE0CsnnBNkaWbRenARkygJuwcQ/slw80uGb2gWvQ2+PzYwX5CYgWUugenIrmiCJLEKkuQvIEn5 + AlI2J1dBmkJ/I9gcmrJRtU6sIDElBEyMUsxEBSzaOWEmyvNLAs83CS4+CXQQldzbQFofEwsMsMUyJ98U + KNfvQVBsBYISyiGOL4cX3V8PikxAEQrYzKWVxIIU9I8T4OgZTdeTVbsoeoIjYc9nVS8CNm4ymiPB80nk + xJ284rnM6Bh7MgOfzGkuMPChnWciFIU7ESDfwCGSr+eimn3xEjOzKp4T07MvMDXzEhPTsxinysgq5DOq + jGOTM3hKVfExg6qihZOUhOPIZCwcBLHcOdA2EqoN/I5YaMCaH4O4nG3wlRURxfCjmaWPCU8+f0F8/4Mo + K8VUhpnQ6BhjGiPEo6dTXCkefjJJ5TiYe7zs+bHcG+JK2dA04DMDnxKLDHxkSW94NBUkoSSfUp8HT2k+ + nH3iuagnSLz52C18eeQm9hy+hk2NF1C56zxK686guPYU8qtPIrvyBNJLj5L4FIYfT8LYJpATtnWX05bI + 4SyMp+Lmxgz8mZg3wH4wAx+bOYcjnA6cICibOiEVDsJoTM+8wPj095RqBjUiE7PzaVZFrY6cCROjUxgi + AwaW/rChoGx4UbB2ofNB26CxzvW/GzCyl1L9LodrQAbcROk0UzvmHokpin6cxHe3X8PO/VdQVf8NSref + RQmLvEYd+TEoig8jsaCdEx+isr2OXk4mbE31wcJJRt1QNFbquDADfyEWGfhEz1qMwKj1cPZN43DxVcCK + F8alf4y1YCxy6ojYnrPIR7jIWfulivwhg4SHRibxgNCm0syEGeaO4bDmRWKFjtNrDbDFp7oWgfAPK6BT + mwwHhjAJ5nSSWfRjJP50fBajXNp/6Ps4ceIhRc2Jj05w4qwl09IXwMwhnAiDqX0Y9QIR+FyLM/BXgjWm + Cw1om/rRi5ZNBycedgIVJnZiVHT2I+dQDzLa7iCx+Qbi991AzN7riG68jsiG65DVX0PYzquQ7LiK4Lpu + BG3rRuDWbjpw7lT9QmFqFwoTWynMyci/1zgyA38jFhvQNPamlyydTmwsrN1iOAypwdh45hEKTgwh88gD + pB0aRMrBASQdGED8/n7EtvQhuqkPkfvuQdZ4F+GEtKEXkt091KDy6CZIYETiRjSbkpnlaxxea4C7hmsM + PF+5+adSCZbDyjkKloQedTllXcPIPaYSV7QPIrltEAlkIK6lH9HNfYgi8Yi9KvHQPb2cgZD6Xq5JZcJq + jG0l+Gy1/QvSWvAOsB9cR7Rc06FolR7/lQY1oiupFWNo0j56FnbBNesrOKYdhW1yB6wTDsEi9iBM5Adg + GNGKdaFN0JHsg6a4EatFe7DKfzc+99mF5RoO+EzDnmO5ilf//JdJPmmpWzLOABvsF+aItcvsmWSHhKXp + Tfz9DfzjR7A1u/9MfD796sEW6kyw7WBf+CVgQaojX2BAPdQf/NLMjSVL/gMGC1sK0EICNQAAAABJRU5E + rkJggg== +</value> + </data> + <data name="barButtonItem57.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABt0RVh0VGl0 + bGUARmluZDtJZDtMb2NhdGU7U2VhcmNoyM3XXwAAAypJREFUOE9tkn1MzHEcx688NDLRH9iM2TQzbC0T + kh5wTh7qolPjuo6lx7vq7uzS80Wdq67aragRF5Ws4qLi1DAqtkxPltUllSUlRA/qHsrb9/erNrbe22vf + z/fh/d73ifGPzAgLCYsJiwjmBErU+Bz/CQCDEZ3xiKrNfQVpGyUKjVaaWmEMTy6t9vCN2hyecGtDgqqm + Mi6rxhCd+bhSGFewnqw1kygeUJ6ZAEkK3bEQXip9Xf/2Izq6vkBdUgtBYokhLuuJvqG1F509X5Fb9BQi + uaaWrF0glJVRnpkAInPOWfm+pOwnGPw2htoGHVKzS3DuQiEilVXoG/gFXfcQ8u8+gzC+GDzxVQfioY8z + F2DBjcgpuq9tQU/fMLQv30MYmQ3n4zJ4BmRB1/sdHd3fcOdBPYKj8sAV5d0kHuquZgI22R5Yd0ZaqG/7 + MIim9i8o1TbCT6CEw5EYHOUr0dTxFW1dQ7hX3Yyw2GvwCcubtHXkrCJ+MzrAna8sKCx/g+HRSZimptHZ + O4SYZDXceXJkXK9C/9Aoxn7rYTCa8HngO0oe1iHtalk1i8WyJCHmDLb/Ff3nwRGyxXfwEpbi7uM21Lxo + RHqOBrzQZBz2FhNENEdITTEzJobbyYgXDDeuyjQ+oQdXokFg+QD8ZBXkMn8hN/8RDp4QQpZWgIRUQspt + xCtuIU6Rj1i5mt4li8wzXDjJ3a3tfVBrmuATXQ51ZQvqGtqhzCoe3u8eBGniNXK0PwgQp8NgmobeOI3L + mUWIiMnGfo8gMLbt5YeJEgvx7FUbPvX/gPZ5M/zFKkREym84u/kjVJpJTFPgBSdh0mCCb+BFjE+aEBCu + ADVPvYaVjR1HstUpuGOLUwhsdpzWrbFxkTKZTBtHph/OhCTht34KJ/kxGJ8wwYt3ASPjRpw6Fw9HJp8O + oP78UgL1NGsJqwmW1tbWy3e7ngaHH4WxCSPcfSS08eeYAeJYFdinzmOXKxf0Z5gPomX2Tt44Rm7/0HEB + DnkKwPIMxUF2CJjsYHrMfq/3/GYKoiW2O9kvtztwsN3Bi8aO1HZ7ZvukpebnNVMQzR3NirDiH1bOQmrG + 0r9Edh2sF3LuhQAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem59.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAA90RVh0VGl0 + bGUAVXA7QXJyb3c7yF4oFAAABsxJREFUWEfFlnlQVVUcxy+YSzVqaWrTTH9Y/zRNNfWHU6YVOmmrOuVW + tuiIOFqYwgNUkE0EXNLRAQxBDUFkeayyyL7IDspm7Pv62LfHA2Tp1+/3u/fRvUaO9od9Z75z7u++c36f + c37n3DNPAID/1TO+fJJWBo8nA5kfWXIeMxWBJNeQUsFFTS4RnPUORgcVCyeCSqiLgb1f/ganwGJQXcrY + gLGh1eVcwdI7W7DwyhZU2KqovZQlmHuK1kvOY6YikESw4ck/ZzTKYJ/LjYUuQcXtGu0YWP+e275d5f4c + vR+amBLIg5IHxkUf9MigcSw5j5mKQJITrlQO1UpGUbln2frmn08t64Aa3QTEFbXBQY90N3pPv+uh/exJ + of/+pGDqdpvGsuQ8ZioCSY43ihCIq5EZRXBDc/f4FW5RZVOakQnI7xuDJt04uAQWTu1xjViBv/MkCNqH + 7h0Tvf9CGo1nyXnMVASS7K8XimCppGSU4VsffDnP5lpBUYVGC8X99yGjexRyesagpG0QTN3SSl992+hp + 6qcH945OCj3ovedSaDxLzmOmIpB0zPeOuI9YRjKKVv+UxW/pZuqsBqjRjkNG1wikdYxAqkYHJX2jcC2p + Cna7xlhSP+rfjeCu0Qmha2RCMD6VTDlYch4zFYGkoz75uI+TbBTv+25H/+XH/Qt1zQjP6hyB5PZhSGob + hsRWLSS0aKGiZwRUHhm6TQcuvkL9aVyHbkLo0I0Lu1wSKA9LzmOmIpBkdTmP95CMMkTPOeRx+2Z2VTfc + RVAiAuObtRDXNASxjUMQ0zAIyRgnlWrgR6fYGOw/l8ZphseFdu248L1THOVhyXnMVASSVF65vH8oLr3J + yZubPaLKoLp/jMEEjEZH1Q9AZG0/RNT0Q3h1H+RjVVz878BmS//tOG42jW8Zui/scIilXCw5j5mKQJLZ + xWxquPQfbT20ROWZpanoHIZkXLEcGFbVB6GVvaCu6IGgsh4ILu+F3MZ+2OUcp3lnnfFSHM/nYZttNOVj + yXnMVASSDrhlUkOln2tyOsE9IrcZcnB1BAyp7ENgL8JEaMAf3eB/rwuul3SBX1EnRFb2gG9iNXxlpfbE + 8fRV8HlAs+Q8ZiqCv0UDZm+xuLLKzid/qrQD4ZiYYAH3EFiKQLRfSSf4ItSnsAOu3tXA5QINeOe1Q3Jt + H+w/mzJltPPcaswzB02LYcl5zFQEorj0y5a/MX/PmaSSlPIu8Mlrg7OpjeCR1QreBe0MunpHNAEvZreC + W2YL/JrSCM5xdXA6oR7CClpho0pdtmDpcrqmeSsouZzHTEUgimY7b4dtmJU7Hryosm44k9wAJxPr4VRS + A5zClp7Jrghyia8H5/g6OHGrFpxia8ExphYcomvACyfr6JsPa028bDCffisUPGYqAqn0a76zf830fLru + NpbyfGoTQurYrlJLQIbiap0k8PGYGoTXgH1UNdjdrAZbtBq3Zqt1pO7N9Qdex7y0FQZyHjMVgbT6bx2i + o0Px4MXgQQvEJOQAyU6xIvQ4QXnFNeBARvDV3Da4ktMG3rgll3BLvDKxjasGo73X6CJ4hvLLecxUBNMT + iINv0Nvt42Cb3S3YZhsLW47Fgh/uPwEZimW2R9tF44oRbnuzCryx7J+Zh8OnZuHwycEwWI9e90sofIyW + JjBLzmOmIhC3gA4MdZ6PXohehH7pa+toCMVTry+v3sciq8Emogqs0Z4ZLQzE/i+jX0A/j6ZD+CyaLyY5 + j5mKQBR/BWiaCHkeevFGqygILupAYBXYSCaodXglHCWHVYJ7ejOs+VlNiZag6eARlHJM3wVyHjMVgaRN + h6OEojYtPfKhRC/63CISAu52iDD0kfAqOILQw6EV6EqwCqmEC/gZfrgviBItlsYZZDcOCqtNAvFRlJzH + TEUg6QuLCOFuyxAbRStYRPvql6+ZBlJrhbYMKQcLNbkCzuJnunpvICWi8vMEMhsGhPf3BOCjKDmPmYpA + EsKEguYhNooSLaa9vYaXjh7GbXA5qCSbB5XzBYQwSkRbwBPIqBsQVhrfwEdRch4zFYGkdQdDhbymITaK + J7DWVM2fmHlQGZgHo6lFm5EDy+AQ+iTeCyuNlRNIq+0X3tv9mBNYaxoi5ODeoabPgNFPavDGb5tWeQpv + PzJdTCdv4eVExjvhBBphlGh6C9Jq/sMEVuGhIaP0X8SCd3f6pNLqsJy8SrG9wUC5V/xwlf6B0udLZ8eA + 4GS95DxmKoKZRZcTXaML0LSyZZJffMD0jkpPcP5HhP6H5DxmKoKZRVWgZLQiKitN5mGmftSfv/sHJecx + UxE8XJTwUf2vkvOY+eCLJ2sQ/gJv1yXMMTZttwAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem63.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAAA6ZJREFUOE9Nk31Q03Ucx3+iqwzOhE6t + MxsDOcbDhgPtziPoCGXkJIq6FQsn0WSOjRKIpzTmgRMfuKwpA2zLjFUzIPAIXCDIIiYPTWyDxThQntp4 + iAeBjP569/3Nuut397r73X0/79fn87n7fqnJlQZq7qGJIt86wvqMC+yYXG2o7ng1p19pCFtQfsvtP6Hn + NGSVBwvJ+WMEj/m/zJTrzxvU1Eo9RblWje5wUhZrW6Y6yFhasw+tVhXsTgPmVrswNFMD09BZqJsFKPgy + tE9U6BdIN5p9eOuRgA4L0pnPZHwaPGwwHcPkchOGlyoxMK/Cnblc2BfPYHRZC9dqCxotBcjXcWeT8/24 + JOcxsVznFmx47zS7qc5cAMfCZXT8fgSdLgnMLhm6p+XomVGgZ1aOZrsYv81XoNV2GorPQqzbd3p60c2p + pGw//nFtLOx/lKPlvghtE2LcmnoXJqcEXU4pbk9LUXR1Lw5kMiE5z4ZjsRJltQk4VBSQSTen3v4ooKah + Ox83x9JwY1RIJMloG09BOxGZpg5DWsZG3icyjIw7wZdvww9Dh9E2WII0VaCZCDZSwkL/kXZHAa4PJ0Hd + EoUY2UbkacNgvPcWcqo4KNLkwDW7BMWZRFxuFeHHe+/g9oQSaaXsNSLwot7M8182OtJhsMUhRuqJPqsV + +RcyECv3docnpx/g/FfZUH0TR6YTo95xED9NyJF6KhAhkd7PUq9l+97X9wpgsO6DujERGcWvwjmzhKbO + DoxOLmJg9A4Sc7fDOJKK2qF4fGfno3bgdYg+DqAn2EQlKFjNZY1RuGLZi2uDAhRXx6K4QoaFB2tYWPkb + h5R7cPVnIQyDsdDboqH/9UWU34zBGzksCxF4Ui+Ld4jTz3HxhSUSFb27cM0mQFb5bujqS2Hqv47Uc/5k + vf240v8CPrdEoPpuNI5d4oEveV5JBI8TqCcFct+7J77moqo3AppuLlnnIFJKfBEppaBp34+qPh4qCdpf + dqOkjofED1g2Lx/G0yTrQQvWR8Rv5SVk+s1/qAsigjBoerhkTyGaho9CRybT9Owi8nAU6kOQlOO/Fh63 + JYrkGJ0T71OUaVxGSxjh8Vv3HJD5jqSc3Imi2iCou0JxqZuDi2YOTn4fjFRVAF45yhzgPQrTo69zZzvG + JLSAfokbyFg+0cnPFcZJmGaBnAU3Chb4R5jWl0Q7Tnk+xdhC6hh0PZ1zZ//7+VdE70Tb6Xu+meBD8CZs + IjxB8Ph/fceYhPoHAkQRj5PgdPMAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem65.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAbdEVYdFRpdGxlAFdhcm5pbmc7Tm90aWZpY2F0aW9u + O7bneYYAAAJFSURBVDhPpZFdSJNRHMZPhVAXSUT3FZRgWeEqP1AbZd10WU2CGWZBVKDpBEuTwUxLyl2Y + WTmdiyY5vUhR0o1szvWhtM21lGBO60Jhy7n2kVG64Ol/DijKdiMd+PE+nP/zO+95eZlLe/K/YE5Nblxo + bXA8PVFAyHmO1+Ewx5PjMXBhSJ2TRTlKLJnrs9NXz1fDPj6UxtB+8/C20QbpN9/Yc3jtOlB2t5WlJsbr + shF1zhpobbTez9Z7jLX4+/MropFJeAZqQHtaPovpv6vLWoFf3aTKyLdp5IiSXHSjHMVENOSGrfk8Xldn + yHhnjWOpzlyhUyHZPaTKDHrteiwFJyG/cEWw6Hdi9kMzaBboKJXsXO2wwao0QenpXQmmyqNW14syIfye + saC0RCHg+dd0N5z6YlBnSJq8fdOyx4zlR8TVexWSKqtaRm+eQnhChwVPN9oa70BH8Bwe19IhfbDWnwV1 + K7gj3Fclqcxw9UA6PRcDkxZEvrQjZG9A2NEE30ijgGex52rBjLUJvEtOGnfZg3N7E3uuH/K4DEqEP7XA + P6jAvKUCkc/PoK5VCniet1TC/6YMP97XYvRxIchx153Zs5V1XU5pM9+VITTegTlTEXx9hYLIuB7HpKcE + PC/vfx+4hjnrPRhv56LzUkor6yrY55/ur0HIoUHQ9giRiQ76VhP+eMcQ9roRmnVhYapfzAJva+A338L8 + sAqeXiW4y7R5ST2G/GTEo+viQUG8Gac1L+kl/wM7iCRi/zrhDndZArGZ2LJOyGEJ/wBorfED3Cv3jgAA + AABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem65.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAb1JREFUWEft + ld1NwzAUhSOB89xHJJqIERiBEdgANmhHYAMYgQ1gA9gA3pL2pd2g2QDuSY7Nza+dVAQJ9ZMsRcf3z9ex + HZ04MZXsIrrK03iHgW/K85Gl8YMk/8LAN+X5mLWALDH3eWoOeWLeKPUWILbvsIUPpePIl+bJJiqTLc9v + oHcVgDltKwU/Qp9MM7kE/ORUbwdgo3303Ciaq5GWPu8W0YLTvQXABrY1X3ZtFLKPhQuSxK+UHX0FWODj + /OWoUg6j+ulc8L1eucVXAHz0IjbJ2S2n/FR/sq3erCnX8BUAtI0+QV6cE4L33HJBBVS3pYtFeZiqddbJ + FJRbhBQA9DZ0bWUL/fdjKyi3CC1Ab2fQafjzAoB1wKDUAvsrifflGHgNQ2K1QFDrNOkSITh6Lo7EpOyn + dgUn8Qvl0dSOs8Sk7Kd5fKZ0Qa++jDGwTZ1I9eo+N4ftpbnmlBfYwscll1icCqd8VNS/gICb1Nxxuhex + W9eSS4yg898FV/LzKGHIlSraSneEdisZHzVb8R3TuU7K4I03PmiIz9HJLdwOuXga3egcpoDt5LYPURaC + pxpvve4KvkXD3K8kPvGPiaJvKJfK+IKVISAAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem66.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAZdEVYdFRpdGxlAE9wZW5IeXBlcmxpbms7T3Blbjsh + S+aWAAADVElEQVQ4T32TW0yTSRiGJyKCLBq91otdL1SQeMAI6WbXE0UU13IyGKpNQcV2UdTgYUXUqFkV + FxVNicqxAoJYCiJCEEFQPNJiQOiBajSWghSsLRTq1r/0f51/4WI1xkmezOSb93uSmcwQAD9k45FaQoeH + QMqLEB45rNqe0cjEn65TR+0vjqZ1z+82/R86Jgkkv8ckHA1H0f10GOwu5D40QnjqHviS3Hji6+s7ieIx + weSJmatxe5xgSsTeFF1+41moTQpoh1x4aWVwtOo1QneWdpOu/LBmrTwM2oJxNHlhaM0KieMknTlrOIF3 + SFIZk/GgHxV6O1oHnP/N51rMWL6jhCFdeWvAjpkm6AEzqkWXPNKSKV0yi0qmeHp6TvfjhxiEx3dBLGuA + SPYcZ2ukSMkWY6Eg2UA6rvDBftaCHa2H214H1l4DxtqAjhwB2i6thE6xBwWyVAQK+Nh6ZicuPB7EXwVS + BMeswxzerxLyQrYarLMT7HA1WFslWKsCbstNuEeaqFgHt1OPTyNvobhdgsjtCQiMK4B/uLRzTnBQIj2e + D1FfWAH233awH2njQCFcfVfh6pHBZcwE8+4cmNdn4Oz+G6NvcmB7U472yovw8vL6mTLDx8fHmzxLpwKH + CmPv82Bu+hPd12OgL4qB7loUNPJIaPIj0JUrwMvsP9BxZT3uHw5GY2owGg4Fof7AskHScvI3OHrvwKpO + g+GGCG6HBuwnHZVq4B5tp/eixpjtCVyWZjDmu/jcextO4030P0pHVfJiNWlO46FflQV98SaYmk/R8FOM + tB2DXZWG4eepGH52EENP9sP2aC9sD5JhbUqCpVGCtovrcE0ccILcOxgETfk+tJ4PxZDuOhz67K+ClvpE + fKjbhg+1YgzeEcFcHQfzrU24u3spDvB/WURq9wSi5Z8oqDI3wPGqkDYlYYAGB6qFMFfFol+5Ee+V0ehT + RKKvbAN6S8JhuLwapSJ/LX0n04gyMQA1KTxo5WJ8fHiIBiPQd2M8aCpeSwlFTyEfRvkqygoY85fjcVog + sqLnZlCBNykSzlcpExagclsAKrcGoIKuK+IXQCn2RzmHaBzFFspmP5QJ/VAcO98k4c32454792GmUqZT + ZnyHmd/A1X6ieJTGziOlsfPIFzqPbRnSm7JxAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem66.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAZdEVYdFRpdGxlAE9wZW5IeXBlcmxpbms7T3Blbjsh + S+aWAAAJ60lEQVRYR8WXB1RUZxqGBxBbYqLZmE3ZbDRGRU00ZxNbLFGKCDYQULGLGBF7NBIlRIqUCCiK + FJEuDEQUEERjRFBA2tAhI2Chw1BmgIFhYATefP8dJnGz7p7kHM/Ze85zpv33Pt/7/f8twwPwf+WFX/4V + 2BZW1M67Iux8/js1Qp3QeA72WY39HnTXhReeX85ziyt5OQX43S/gBT7IVX1Wdw3T+Zf/jVVxzlE7G0gC + 19iiRueY/DjLUw6f0e8a/DRXXhCNfykFqFFWl+gzTKy20uLI6M3f73XwiDFS5FSdRmF1OiSKAdR0KcB/ + cAv2ISYKj2hdx6mfvTuSjT8VU/gSOkAVnAw7yQoYts5m30XbiAT8mOkOSW8ZHjWVolneDxFR3lCEZKE3 + wlLNYO26JIDGa353OecldEB9GJOrGx+YpLfVTh+eycnIqCxA/pMHKGuowFOpguORpAc5VSUIvrcPtpeW + QXuziT7bjzdixAiG2p9ENf431DSGswI0jQ9NuuZ6ZQVsQm2RL5KjqEWO0tZelLYpSXuYRVOShLS6gwhM + NsWSjUtjab/hKrkGofkChg/B3rMx/1GE+rBRrICRepYzmtxj1+DrQAfcfiJFep0MD+qJuh6kVbfiWsYV + RKSEIlqwG8H310NvxzwR7TeaHUQjzVtHrzhkuaA01AAqSlSEKMny0TWnscMIteKg5Twl+jz14a+yAkYv + 2mSh2OK4G7bxGfDNaUNihRRJlVJEZSYj6JY/orIy4JMjwn5fO7jHmWDx5tkK2u9VVoBmcfByUVf9DQz2 + CYlfnqOMQ9GRhdJwkxbvA5+/O1SE+vOoqamNMTwQ1rwnQADrsFLY32nEmYwWBOeL4RnjhZ+EJ+CVuBfb + 3Syw0ekItjh9h4Wb9jSrChhRFKgP9D8F5LeIm0BPEpEIyBKA7utEEsSl55B9QTeahr9CjHoeDQ2NNz5a + tDhp1b6tMDvli20+uTj4YyVO3KzHHt8z2OWxFf6p+jhzcyl2expine1ZzN/ockM1BSMLA6iAZ4+HxDd+ + F3fFAdJYoPMqBqXxVIQP8nx1keczxAVdCIiSSEtEBx7DnA0TYOVuhlWHt2ONrQvMfkiD2ek0mDgnwOSY + Eb4J/hR2oYvxqaEeputYGVMBmlwBBX56gOLRC8XouAK0RwMSPgbbr2GwJw2DvYVEwW8MyPMgbRdi/8lt + WLJjMg6eM4DpCTsYn0rBKse7MHZKwdqj23A8cD60d07BhC9mxpB8DKHGChiVd0GHCnj4YrGYT0RisO0y + BlvDMNgSgsGmICIAAw3+GKjzRX+NN/qq/NBUfh3fOm3HNB0DGJ2Ih8XZdFj55nCvhnttMU1Pe+D92dMD + R40b/TbJNT4xcuexAkbnntcGaNH9MTETQyVuJrEoCAONJK5nYh/0V5+npXMWzyo98KzCFX3lbuioiMTt + eB9sOuiBOaau0FrhitmmbjC1dML4acvWqaurv0Frhp3W3LWFFfBKztmltPhK/k3MJW5RiQN/F9eSuIaJ + PUnsAsUvDugrsUVfkQ368o9CnnMY0gIntBb6obEgBPUFEWgsiUH6xSPQ1NT8B/leI0YS7PqiwRWQ5bGE + Fh/NJxO3hv8ubbpIbfYlqTelPcel7X+sTKsQOkAmOIJH0esh8F0BgY8hYYBcb33knl+GHC9d5JzRQban + NtjxEw9qIXG/FhIOTEX8/qndV/dMiSA3twhffeC2GP10rj+rD4Ci1heKJ17oqzxNLXVBr9AJvSX2hB16 + Cm3Rk28DWe7XEN3cTheqjRA/jKVrRQ1RTVTRoiTkT4d4TIv2EceArIJ4iIFuIaR1qYi1mlpNbu5yOibd + eSF6RXchq/BCd6krRKkHUBaxDvmBxsi/ZIS8i6sh8F9NpyAlvWBIKQ1QkXAcfR3F6O8upgUYjN5yL8gf + noX8F0/Ihe6Ql52GrNQNshIXyIqc0FXgiK68k+gqPAUhfzv4FpODyM3dC16777gA3dXxaBc4Qpxhg4IA + Y8jbBMo0HJSm94kSLlUl+mXleCZOhbz8PMk80FN6Gj1lTOgKWbEzZIVO6Oak9pAK7CDNPYHObBt0Cuxx + 3/FLXDSfaEZubgpeTz35BSRlEWi6exSPr2xDaZQ1BnrK0ffEH70V3sR5LmGvkBIKz5DIXUnJD+gucUM3 + CbuLTqGbSfMduKSdud+hM+c4SY+hM+so2tMPE4cgTrdBjKWW3GjW+DfJzS3CscnH50KU7Yun13Yhz9sQ + NWle6BdncDK50JNkQwlJKCOhrNhFKaTVrmytAyX8nrBFR/a36Mg6ho4HR9GRdgiSewcgSbWG+K4VxCnW + qLi8ARGbJv1MXnYZ554Hxt7+Zg6q77iiLHAD7lF7Op/Eoa82ihP2FLvR4qN5LHAmGQlJpmwrE9pRwhOQ + Ums7MkmYoUwpSd3HycR3dkP8syXafrJA682taE3ahnT7BfA3mXCUvGzjChh369BnKL/6LbJP6yPNRQ/P + mm+hK/sbSDOPoIvmrpvJiC5qqzTHVjmXmZQyg1qbdngo5T5IkveQ9Cu03d5J0h2csCXBHKJYEzTFrEZz + nBmuWmjhyOJ3PiYvd2tnBbyRuPdTFAZb4edj81AUugu9VeHoSN6J9mQLSO5YQJy8A5K7X6GdHqfamYxa + K07ZT20dSnnHEmJK2UanZkviJrTErkNzjDGaolaiMcoQjfzlaOAboDJgGUJNJ5STcwzBPeCwAv52fdfH + yPQ0R7z1TNTesUdXkTPEt7YSmyFOYpijNXEDWq/TgeOJOFM0X1uLZkrWfNUYohgjEq0koQEna+QvQ0Ok + HuojdFEXpoO68KWoD9dGpt1sXFj5gR85RxPqYWsncveCN2O2T0fy9waI/WompCVnIUmxQlvCek7YEm9G + wrUQMdGVNcQqNP3IZIZoYrJIfTREkJBkDSSpZ7KwJagL/RK1IYtRG7QQNZcWojZ4ERJ3T4OT9ntbyMku + xWqhRhO4At7im09FnPVcpJxcSnPtiBaWkFI1X12tlEWr2siEemi4TITrcqnqQ5SyOiYLXog6EtYGLkDt + pfmoDpiH6otziTmo8p+HEOOJvXPef/19cnI3o+DVygLGh5tNQtTWGSjyN+VOFxGT8lcQ1FKWkEkpYT21 + sz5sKQmXUDpKSKlqA4mgBagJYHyBqoD5qCFZld9ckjLxHDzy/hwCh1k4v/yfqeQbRwwLXvUBj8EKGHtp + zaR8/uYZVMRMRG/5BFGbiS0zwN/08RDTwd+oJNJ8GiI3EOu16FULEeumDjEFl80I08kIZ5gQaz9C2NpJ + CDH6EH4GH0g2znprEfnYI516qNFEHoMVwG6L7BY5nvg78fYfeOd/wB5S/xvvDcHes+OOJdhG8g85uaoA + 9mTLzknVf4A/w1/d2D6qp2nuv4XynxV4vwI3hnYBipdf0AAAAABJRU5ErkJggg== +</value> + </data> + <data name="btn_data_manage.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAT5JREFUWEft + lt2xgjAQhSkhUIEl2IGWYAl2oB14O/CJ8GoHlqAl+EycsQTt4JoTd3VVgiIkPsiZ2ZFsFr9DyA9JrxhS + eTm0MUu1WStt5pQOJ1UcBllhFgCmuTlm2vxzqMKMqSyc1PKgUl3uJJiDSsLrYsKcJNy2t9QdXpkuVxLu + Ijd/1B1WEo5R4NcR5f0/wt0KoDlBJe3le5IqOHW5OUGX7cQQ++dTSjnVwTuThEgTX4EL4EZcx4I/m6mC + ow2DHDxijeQbdvzWwSFMVnlv433AB2eh7YNDrQy8grOwvPjw4eBl+rGBd+EsH+gjA03hUGcGUCBveIRj + qO0HxegatLt1ZoD3bBRXPfmTQQtAvjMDkJtUej+h5p2iGKhTNAM+UG+gN/A7BrAJ2VNuy2Hb7rSryePc + l3m3ifnyvW5KkjOxB1NJ7TVfCQAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem67.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAASdEVYdFRpdGxlAFVzZXI7UGVyc29uO0y2ImUAAAJ+ + SURBVDhPdZJrSFNxGMb/c7nUTDMvNc2onG4aJBKSq22OYUtXCoolZFAiXanIpc7NSYMKI3W6WmalEnZF + zCK7QpiyfVgSJMQktDAMCi8l1KfKfDrv8TCs1gPP//zP+/6e58s5DAAzq0J5WzIXs+PrRMy6KXLPNePW + /m7bjvH2vRk9pWuDVjI/oix/2DeH8a5VS5hZGZb/8oYF4302jHXvg6veAKMyfDQtWlIgFomE6Jx8BeoV + Et4bopj4ekXe27EeIy5kM5QnM5zMXYXmknQ0bAyEPDwgW8jy8hXMU/BtS+6vrqPrYcqMRd1uNd71OvDJ + fQ7VGRGQBbEmgePlr4BZ1Etfd9lK8O2DG/h4Hz+GO/BzqBkdR7SIYcwhYLz8FigCWNFzZxU3HsZnjx2T + rjOY7jOjoTh1JoixdAHj5beAdFif2vt95AFmvE58ddVg8GIhDLLQu8Lap/8WxASLda1l+XBdOoCeE1mo + 0sURlBvIHQvmfQm/BYnS2KJyc/XQZaMeD205qC+Ix660aBSX7vfqZbJCAeP1T8GhNas7b27RY/DNCF64 + HqGxcjusO1VoddTimduDW3nbcJBjBPzPArVGU+512OHRqNFmtcIzMQ3raTtO1TkxMDmNFlMlPJkaEEPs + 3wWSO4+fTAxcaUF/igL2pCRolUq8n5rCKGedSoUmhYLfEUMsZXwFUqk05wt3eXW1HZ2xy/E0IQFOsRgm + rZY33WlGO2KIpYyvIMdgcHJP7r8/i3sRS+BOSUa/XI62kEW86U4z2hFDEjJzBXHx8drG887JmiwdKkIW + zlqWRc+WRUXimGC604x2xBBLGV+BIO5PZXLOifNM7/5mxHJZsN86BZo6ADxq2AAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem67.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAASdEVYdFRpdGxlAFVzZXI7UGVyc29uO0y2ImUAAAdm + SURBVFhHxZcLUJTnGYUxjYLIhpsIBAx3kauCXAMKFTWNQowsoCKgiFwkIoqCi9cgCFirUUgwiiBRCUqC + plzUiuUipWhEQZTEZkJCaAhGiWWsYaZ1mNPv7CJjwmKhnUzemXf45vve85zz//vv/oMKgF+1hxap3hoj + 9nZ3iUqqu4bKttmaZtvcJUkyd43iZFeNZvYmt0nHRc9NdNZQiZ8xUWW09b8EWJu9yAyl25eg9vB6tJal + o+XjNFzKicO+pTMgAuT+kgHeOBYze6DnWgG+qTuIu2e3oO1UDG7kL0dLfihuFMVgf7gbRIBYwX5B9Di5 + y3NqLAH0dvsZPu6szcMXlbvwl73zUZvujcs7PHBpqxvKU5xRFGuLdyOmIc5h0pNou4m3V05XjxEeLyqs + lNewAFs9JCN18unUxfiq+g+oy5qLKmF4bp0dSmOsUBRhipygl5EVYIiUeRZIW2CA90KmYp2zBFILtRDh + 8xuF3fAaFmCkkrlptN0o2Yabx2NRlmCHwlAT5L5pgOzf6SJjnhaSPTWxO8gZzad3IsldC7kBekiYOQlB + FmqVQj7iQzHaAOOS3ST9n1dmozzVC4eWvIwdvlrY4CpBnKM6wm3UkRM3D99fPYze6++jaLM/1jtpINZG + FUHmaveFXkuBGV6jDfDCJjeN7qsfyJAXaoYdv9VBdpgPPpCFoGJ/ND6rysLDm8eE+WHcv3oI39ZkI2Op + C8IsVSE1n/hE6KcoMMNr1AGSXCZdKc+ORHaAEQ7G+qP/2yb03SnBP24Vyc1/EFd+v+kQ7jXsQ/ef01Gd + uxrLbbX+vdh04r+E3lCBGV6jDpA4S31b3po5SPaajM8bz+Px15fR13YSD1t+av5dTQa+rpKh/r0wRLkZ + DCx6Ra1b6A0UmOE12gDjvC019Da6a3cnumiiq70J/+y4iIetx4duu/zKa9Lx9z9tR/uZt1CxZzHCnfT7 + fA0nFAq9pgIzvEYbgPViqI16+EY3bXxadRKPOi7hhxv5iiu/8vsh887KZDQXRKBogy+CbbRvCZ05tXKC + khpLAP6qaa6d9VJn0a61eNxZL67+iLhymmfIzb+p3IzPSmJR904gMpc6YJ65ximh0ZGrR6ixBGCpLrHX + i9wR4nW/9WIRepsL8F3tnkHzZPztTBz+mheMkxu9Eemq3zdTTy1CaJ77YhhrAN4FrUBH/fdzEpeipfwd + dFXvwZd/TMKtE1FozA1GqcwHKfPN4GUwoUTMjvjwPa0xBZBIJCqWlpaqc9zdE2WvT0NG+FwU71qBiwdW + oCI9AO+ucUGijzHCHSbDSF9PJiTyq/eTqPOP0hptAL7ZVEUA3YCAgLPSIOnj/RGuOJsZih2L7bHKSRdh + 9pqI89BH8nxTxHmZw9HR8UdjY+NyqafH/x1gvOgpArJSwL4oKytDcXExMiK80VWzF7c/TkFNzkqc3roQ + +etm49AqF0R6WSMzMxOcpYZaMgZZP6n/FmCC/vjxdqt0XqrfO80cm3x95OYDAwNIio9E6b5YNOS/hU/F + C+rygWUo2rQAu1Z4Yfmbi9DW1iafpYZaMsgiU4FW1PMC8BVqGj1Z8/aFqEi0ro7EuUULER4eLsaAvr4+ + SAOliA0Pw4b165G0Zg3i/P2xcMF8NDY2oqGhQT5LDbVkkEXmIFteQ75DC0XxaddJSEgoPBAsRdvBg2gR + kIY5s+Hv7Iz29nb09/ejo6MDfn5+SNudJm+uucczznCWGmrJIItMsgc9Rgww3sTExCMvL+/HT97eiaPL + Q9AaHYUr3l7Y7WCPlJQU3Lt3D83NzXLTO3fuyJtr7vGMM5ylhloyyCKTbHrQaKQAOtHR0YV1dXW4fqYE + O2fNwM2o1aj3ehXnHRzgbGmJ+vp6eHp6yo2fFtfc4xlnOEsNtWSQRSbZ9KCRkA0LwFtjlZaW1t3V1YUv + r19DqqkxroeFokbAL9jbId3SAo7C4HUdHYg5IVMU19zjGWc4Sw21ZJBFJtn0oJeQDQug6uTkFFhQUCD/ + LHs6O5FqNAVNgUtw2dUVVXa2qLCZjiJLK3wkjKTa2nJjNtfc4xlnOEsNtWSQRSbZ9KCXsgBay5Yty6uo + qMCjR4/wvfg8txjo4sprr+GisxMqbWzxibU1PrKyQomFOU6YmuINTU15c809nnGGs9RQSwZZZJJND3op + C2AcHx9/rampCb29vfjq7l1s0ddBjY8vzs9wRPl0a5wVBqXm5vhQGB43NcPRqVPlzTX3eMYZzlJDLRlk + kUk2PeilLIBVVlbWkwcPHqCnpwet9bXYrD8Z1R7uqLC3xTlrcestLPChmRlOmJigQBg/29zjGWc4Sw21 + ZJBFJtn0oJeyAHpSqfTEkaPHUHGhGuW5OYibootTttNRKG7vEZNXkCeMco2McMDQEFmG4v+BZ5p7POMM + Z6mhlgyyyCSbHvRSFoDfz2nBwcHVMpkMUTMdEaUjwWq2tgSrRK8c7DAtCUJ/1tx7es5ZaqglgywyyaYH + vZQFYPH32kj0TNFuStr9mX71Z/3smTItmWTL3wkKX6j8B54pnZmRU85dAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem72.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABR0RVh0VGl0 + bGUASHlwZXJsaW5rO1dlYjsG/qDOAAADdklEQVQ4T12TbUxTVxjHr29bZpSEzWXGSdAZQ9mqLOBtDYgg + 0IrIS6lYpS32ggWRpnVYMttKaa0WRKQgFHARMHM2QuPQiS1Cu9Y3BF3wJYoiItnmZvTLEvSTSvl7ri+d + 8SS/L+ee/++553lyqFh1P0XWNMKsGEWXjJfvcvCVvWMrCz2vaMb9MFrqdHKzWpTk+xzCDFp+lgIQhF3T + ojYdXUgXuOypet+kpesybN1unPD/jm1HDiDDZsP68vNTcczJznBeSQQr+VgwawUJp+89C21PM/Rde1B1 + 2o4GVwfyWn/BF5ZVWGKSQWwaRFLBbz3kfChhelDA/nai1jOZ3KrByp+TIXFtgaZXhx+cnag4Pw7ZYTfm + GZPA09sg3nVjihYdNhPBZ0EBr8DlSLQ2YP7+SCxs4eC76mSonKdgHfgXlksTUDlGkNdkBlNngkh7DmlF + nhEi+Dwo4G/tHfu2fCvCtKvwZcVyMMcdqLz6FPuuPIehbwLKn4YhqCpG5aACTI0RYvXACyJY8L9A2fcq + orQAooNtkLV1weB9hAr/M+jcE9jR8R8211xHhDkFsjNpkNdvg0QzyHZuUVBAK1wPhaYTCNueA3njBUgP + +SCr74fCfheKhr+RZbyOUFUiOHVRSDFLIFL2BYggOA0qOrfTmbH7FhJK2xEjV4OXq4BAXoa4zRokMS1I + KfZjmUSN6A0M4sVqxGVqJzm8tTYimMdKKG5ms1KgGphaW+SA1X4cvstD+OfxE3gv/gGzrR38jDIYa1rh + 9vZjbPxPdPdehM7aHODwU6uIIIRAzaFzjp0U5u2Hr38IlsYOSEtrIVFXI6ekEqLCPUjPNyJ1ix4puWXY + rq/F6R4/otZsGibZr1nBjPkcUbRA+mOArSzRVKPtWAeyiyzkisDwyChu3b6DdQoD6puOIDazGHdHHoBe + l/+SZJdQtOwMKwlZnV1yzXPhGgwHjr6rqIOAVFyzcQe5u+pNkJ9eCKXWil+7veDGb7hPcuFvR0FRn9JC + qc5U2z55zn8F4389gst7CYaqlgA3PvuqzmoPnHL7MHxvlIQ92GmuC3wTldBAcqHvBdMJId8n5pTz05ih + 2KziFzFC+c1Iflol2Y9cukJYsyxh472YVOYlN148unh5QiPZDyPMfCP4QDKbwI6Hbc5XhLmETwhst9nA + UkI4gX1QMwFQrwGjWAB+ikgulAAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem72.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABR0RVh0VGl0 + bGUASHlwZXJsaW5rO1dlYjsG/qDOAAALeklEQVRYR31XCVhOaRtuZv4Z5re0kCWGLDNz/X8MYjRtX6WU + 0iLtX7svlfbSRotoU0m0aUNIQr6kRNYWTUOhVJaxREOiVUQp3f/zfilyuf73u+5zznfOe977fu/neZcj + BECAr5RvCN8S/kUYQxhHmESQJEgRlhIWf/wvThAm/JvwA+E7AnufYVQZ5hvhZQcpzxbBQ/kCJSG9czrs + kr3IGmHEwlM4YWrT1JNiZqgnllgH5LaGJJ3vy8y7ivTj5f2ytllPp+sXnpmifShSWHajNkmYTu9MIDAh + rAP/V8SQAI+WTzeGXvieMG6mziGtn9YcO6LuntV94nw52rs68IF+J85cxMnzJegf7EXtvQboB+VDKSQF + Cz2S34jr7DshIrfJjN6fSmCOCNwY6G8RYmBlmEvAxw7/JQc+kjPFTPlESbMLwTJuxc8DD6TjTnstXvW3 + oW/gLT4MDmCQfhknCnGLyN/1t6PwajmM4opgftABOkn2+IWX0CmmFp0gNFZoDrXF3GBh/Kb//T90+oqA + /7gLlLGe/yC6aN1MSfPSFN3Q4sHgvHAUP+Wj8kkJ9pw4gh05x3Ds7FlU1NYgLPc89p8txY0HdbCML4dN + xmPoRFyAQYIbLA9zsdw3YHCS+nb+mBlLFlG7IyIIowV8LMO2C1PP04yi+XAvcEfi7WjwnxxCUT0fO7Kz + kFGYh9qHtUg9mY/ISzXYVtYE/zOP4VXUAfvsNlhn7IVluhccj9vAPtcCnABfiKqG8SmT5lHbLIkFOfGl + AEbO4jRe0vT8Fs2QvEGrUzbYXOWD2LpwZD9Iw4VnJ3H0chYevr6FlreP0PbuCfZXVNHzV4i48R6bLvXC + +fgrcJMbsXprOTSDY+CWy4P7SWtwfEIHxThb46l9CcJYwrdfCmCqxlKyafzhVdaslWEJXhkPPlc9EFET + jLS7u8B/fAilzYWo6ShH8fUCZF4oQEpVA+IbehBJAgJKeuGa1wObva9gEN2CFV6VsEzwhUGkP3RDojBX + /9gL4d82cIlHjCAIxecC2A1hSfOyTK2IDKw+qwfLEiu4Vbog+Lo/4uojcPD+HhQ0HUHJ81M4WJ6H1NqH + 2NvYg4R7fQIBmy+TgFwm4DWMoluhG1yK0LOukOUdhgy3GAtNCjCZE36SeFhS/kgYJWDMdI00xSXu19tW + JKzHyqLVMLpoBvvy9fC95oVwcmF39XbsLEhF+pVyZN1vRnZLL/Y9HcDuO/0Iq+qD//m3cD7aA+u0bhhu + b4eG3z24pEdAzTMazqne0AsMwCKrkDfjf9Vkw1OE8N3nAsbPNisNVA+rhkyaFpQKNaB7zgBWJdYCFwKr + /bCVH4djdxtxuqMXJzo+IOvFB6Q+HkBsfT9C/uyF95m3cDzyBhbJ3WR7F1b5NUPJ6Qz2XQpEQU0QCm4G + IXC/H0SX2aURH5uoWMILXGBFZI5NDd848ToWpapgOV8ZKzN1YVBkKsgF12J3xF8pQX7bO+R1DiL75Qfs + axpA/N3+ofiX9sIjvwd2B96AG9+NNaGd0PB+BoX1p5BZ6YODhAOV3thZ5IFJ8m4VxDeXwJJxRIC4pN3f + 9esy6yCVpIpFhxXhe/g0AvJOw4LvjM15R7D/UStyWgeQ9fwDMog88X4/dtS+R3BFL3zOvYMT2W+T3g3j + mC6KfydUXR9A028Hoi84I/aSM3ZcdELUhQ2Yqe7ZTNPcAuJkM+SIgGmS9o87HY8+wJJEU8gnWmHrxduI + q3mO4MuXsaWiGGkPe7CXiFMfUdyp5zFEzqz3J3KW/bzM14Lerw3rgpZvOzgODdCN8IBXvg02ErzyreFx + 0gpz9J3fEfUy4mRzwogAiTn2Tz848V9AJ2UPpEkENzUDDoV8RFW3Iq6uG7vu9CKOEi6GYs7GPeu57/l3 + cCNy+0OvYbGnm7Kfeh/UAQ3PNijwaqAc7AijrLUwzTKAMZ0ND+ljjglvUGiikCxxjv9cwIxZvMYu2+xX + 4B36G0t22mLWkQUwTEpGUFkrwq/3Ed4j9FovgqnXbMh5nxnq+XoityRy4x1d0AvphKZPG1SdW6FgXYPf + XFwhn6wOueSVkCXIJKlhxlrzPpqUmYDRDsy0un1HP6ELtgc6wU24CemY9ZBJdIDL8Ua4Fz6Ha34TnV/C + 6/RrAfGGnCHbWdYPkzPr1VxbscLuGRStbkHKZgvmxshjTowcZkfLYnaIMsTXmLZSCNg+YlQOTJEwqSxY + sa0V3JRuWKZ1UDzvYkVCCll7C0tCHfFLuDY4UVEw3F0J04TbNOW+gNkuNuuR7Vs6PpE7NkPFthEc83os + M+RDPEARoqFLMYtnAyn9PZgs41RO68IvxDlqFIhN1eaHS3s8xdqoLlpWu2ES3wHT+BfQjqyAqO9PEI6S + gEjcDIiFz8W0oN8h73MAmgF10NzUjFU+rVB1IXL7IXIlizvgcGshb1iGxYYZ+NkqCHKmBZDSO4jJC60T + iG8GgS35IwLGiywP1Jxve6ddfXMbdLZ2QC+sE7rhLZB1P4AJ7lMxIWIqxscSoqdiXPgUTAiQwDTnlZB2 + yIHyhidY4fAUyp+RKxpVQdH4CqEUiqYlULQowVy12K4JszgmxMfWg1EzIdt2SUzVLcxZ6tQEDUokdf82 + WlDu4ydzbUx0FsO4IDH8GDUZYyMJYZMwdsskjNkkikk8ZfzOLYKcRRUUuERqVg1Fk2skoAIc4woomVVC + xeoqlhrmYoq0fQHx/EoYXpZHBLClWERUNtR4vvmN5wpOT6Hi8hJKjo/ws5k3RHgTMcFTBGKBklAPcYF5 + UDR4m5Nh7ZsAc684GLhGQGndRvxs4IaFeongmJ2BmcdR2PrvG6lnsXEXTNxj3us7bDunoGs3n/hGNies + sAvmwnRxtb07Flg3DKo4NEF5/WMsNy+BuIkUpq+fB7eoDFy+1oDGZ63o6O4ZQUv7K5wtuw5D52BI2C7C + xqhsXLv1AB2v3lAHP5W+9/24WnsPtt6x3Qpr7KWJb0QEOzBLmDVzxDUOHl5kWQMV3t9QtKzDYpOj0PTY + iNKq23jZ+RoNjc9RfbcJfzU8HsGfdY0ISzwCI/doVNc/RF//AO7/04ob9/4ZVa+yvhGxe/OgbORZSFxs + Wf52OA5MhGBfMEZ8yeIpqmnZUuaVg3JWN8GxrIbNplQ0t3YKyB2DkqC1Lhi69tvI5kSyOJ4sjoMpkRs4 + RULPPhSr6bm65Waocv0E9dY6RSB2f4FARGTKcSgYuL8hrqF9IhMww7SargUiBPtCwvxJClG75q7Jf7HE + tJSIkgR2X7vzBPoOYRChfBDeMhvG3uG4cbtxVEgY2sn+kqt14Bh6vFbQ4bmp6nI51n7xqLj1CNHpfPyh + 68R6LUoYEiBh/JeQllsN/R9xgqn7SXihnbW4YnQe1yt+8NnLTkEPtqflwcA5EsZuMTB2jUb9/SYUlF5H + dlHFKKTnXoCioSfWOIaD67kTOacrUFheg4g9x7FM066H2mfD8fshAYblhBIhCYOLdE8ggo0MFiP2yTVP + h7etqrjsJq7UPhgV06zCK1i7IQwaVpuxgusLJeONUDTwhPxad6w09yO7c5FztpJy5BGKrtRi98FCuG9N + xkIVbjG1y5wecuBLUBlOTObGODktKwVLz6juiOSjCE06KrBxGNsScmDnuxN/aNu/+13TJs7UbXvPpphM + eIWlwT86E2HJxwT1IlNz4RGaAlkdxzezpBRUqN2hr6avCRgGlWEhY5aqGP2qYuxximPg/lJ+jQtktB2w + bBUPi9WseqU4xhenz5NmHyCiv8lrL1Q19S5UMfF+STkAOT1nyKx2gPSqdb0LlE1Lps1dzBajiQTBtuyr + xJ/jYxlOULaIMOVsPWd5whpiZzaE2bPhOuweSzIWQvaNOI0whcDizup+2hN+Sfg1fCzDbrD8YGDhGQb7 + z559XoeRsEWHgU107MzuCeoNtQ2h/wFeihugPSgzYAAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem73.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAFBsYXk7U3RhcnQ7XWFAegAAA/pJ + REFUWEfFln1QVFUchjXjmkw26R+W6X81fcwYojaxaoEps/KxJo3rR9mYaBI4mlqOTSjJsLK4JAiIuK4f + 6+KCkQKrQhgzrZmCsHy51oiRIK5m6DhZNs40zdjb755uTOecS4Mwa8/MO8N97jnnvfdcdu8OAfC/Rl8G + EalLFEwGEalLFEwGEalLFEwGEalLFEzyDLV/+XrFjuPxY7XjQSF1iYJJnmH2E3NA+XlnVfy7prefe0jz + A0LqEgWTPCE7vzChvssNx9crUFht8uYfjXtaO3ffSF2iYJJH2XE8Djd/8+PK7SYc9m0CHd/N98Suf98a + 8bA2pt9IXaJgkkfJ88Si504L/Nf3ofNWNZqulMPhTcb2ytjm7M+M4dq4fiF1iYJJHiWnfDau/9qI5kAB + y4WeUgRun4Wn2QI698e2I8YtG3dFPqKN/0+kLlEwyaNkf27E1V/OwBfI59J+4wj8P1Zh91crYSszXrSW + REdqc/pE6hIFkzxKVmk0um7VorF7u5TWqw5cvFGBYy020Lh7me5ZRWmOqMe0uRJSlyiY5FG2HJyJc9dc + qOuyof5yjm7U8xd6arDfuxqW4pmBDNdr8dp8DqlLFEzyKOnOGfB1F+Lo+WU43ZmFus5s3Zy9nAv/tWJU + t+Xg04qF2Lw/qjTV/uoYbR2G1CUKJnmUtD2RVLANZS0LUN62BN7vN+P0JVufaewuQvtPlSiqWQaae5PW + 6P3ykrpEwSSP8rH9FZzssKC0eZ4WMzzn34O3IwOnfsjqzTeXttJHdDc9Djdcp9aC5t1bXzDNSWsM+3up + AV7AhsJpqG1PhduXwKXE9wYOty5B1bdr6AK2oiXgRLXfStu/COtyDd+ZU14w0fxHKYO7gA/yDFSyDq6G + OVJKfGZ6LMvhOZeC9DIjFUfcSdwY/knoyBD12Y+gqN+WQ9WFVKQuUTDJo6zJeRmVbclw1sdxOdT0Jipa + k2A7ZgKN+TMpY3Ll1JjxL9Ic9a5DKNKLS+oSBZM8yirbS/QPuBR762JYXA0J7Nh+ch42HIhCSubkjoQV + z5pp7OOU4RR1y3vv+t9IXaJgkkdJsU6Bu3Eh9pyZjQP1c1HcYEbqwRlIzpxy960PJ1hHPzHiSRoXSuG2 + Ww+pSxRM8ihJlklw1iVQ5sJSPgurCgx4JzWsxhAzbhKdH0nR3W49pC5RMMmjLE8PR15tNNY6pmPppond + 8YnPLCY/iqK+gPrcbj2kLlEwyaMkpoVRcdjv81c/nztmfOg4cv3abj2kLlEwyROy+KMJJyJinjLQ3+pL + RqEM+GeZ1CUKJnnULVY/z/e93XpIXaJgkkctVO94UMX/IHWJgskgInWJgskgInWJ4kFHVz64YMhfkU05 + On2zdlYAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem74.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAALdEVYdFRpdGxlAFN0b3A7um0gTwAAAixJREFUWEfF + lt9LU2Ecxiehd94H/QuihBCBBBJKimIQ0ZWYIAgWeDGjQZpGFip5MQozRZQxEAVxQbamsIk/xpxroFTa + jxUuKhJDxC7Wrp7Oc1666JyD7H3nOb7w3Hz3fj7f5+zmHBeAE43l0MlYDp2M5dDJmAc2HuMufZ9pYOMx + 7tL3mQY2HuMufZ9pYOMx7tL3mQb/n4Jn8w0zIwsNGS2QTIYsHUKlVuDU01f1mdSvl/h5mMDu72RO4V0y + ZOkQKrUChU/m6vDjIIb1rwOIp/tyCu+SIUuHUKkVKPI+r8W3g1XEdh5KhQxZOoRKscDgzCWk9yOIfrkv + FTJk6RAqxQL9U1VI7QWx/PmeVMiQpUOoFAs88F/E5ncfIh87sfjpbk7hXTJk6RAqxQI945WI7zxGYLMJ + 89sdCH+4c2R4h3fJkKVDqBQLdI5ewEpqANPJa3pmN67jxZubCG11YGHbo+U2Qu/c+oy//btHhiwdQqVY + wDNUgfD7bkwmrkiFDFk6hEqxgNt7HsG3t+CPX5YKGbJ0CJVigfZH5xDYaMNErE4qZMjSIVSKBW70lWPq + dRPGojVSIUOWDqFSLNDaexa+tasYWamWChmydAiVYoGWnrI/w0vaU63WS4UMWTqESq1AYaOnZK65qzSr + BZLJkqVDqNQK8FVarOW0ljOSIUM2r9cxPyYo4FPwr5QJGbJ5fZAc6zHu0veZBjYe4y59n9XQyVgOnYzl + 0MlYDp0LXH8BV1JZwKf+N70AAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem75.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABt0RVh0VGl0 + bGUARm9yY2UgVGVzdDtUZXN0O0NoZWNrZDNApAAAB8FJREFUWEedl3tQlNcZxjH3pI25aDRtk7bTS6ZN + pum002niP506k056mUynfzQxTZqMjprGgAWteEVQriJEQ/AWBYxJFBHQREVEkaBoUNBCzMRxJBG5yrI3 + WPbC9enznG8XVt2ddvrNPHO+/XY5z+99z3ve7xADICbsmlRUev7EzvIL2Fl2AUWhUSo9j52l1lhIWWMj + Cvc1oqCkETs47ihpMMrdXrOWc91B3aY5NxadjtlYeCpmAxV+Ge8wgEnUbTL8X6/BwWEM+Abh7vOhx96P + 1nYnLnzRibrGVmRuqkzlfHdqTs3N72Kyt9XwduLiFLcA3K5odY2MjGFkNKiRUY6jGOYzaYifJX/AAnD1 + +3Hd7sFXbQ68u+sMxsaAqlNXkJx7KI1z3kUZiLS8YxwmrkgAdyi1FkDI1FLIdGiYAMOjGAzKHxiCxzsI + u9NLADtydtQaAI9vGEdqL2NZRnk6572buj3oMX5FArizgGupy4p0jCaMWmY0l2EgaBwYpPngCMcRZmEI + drcPLcxAev5xA+Dj94I4dPxLJCQXZ3Due6gbICIDsIh0KUpJhibioaCxRiowRHPKLxHC0efHlVY7knIr + DIAy5TcQIzhQ9QUWLNt1C0QkgLu27w0DkBEnHzRmgrFMjTGfh+RjMbr6A2hpdSAx42Pz94Jg0kwW9Zvy + I82Yu7hAEKGauAVAD+/eVmwBmIipCRNpFL4ARxaf188ClJh+r38E7v5BXOt2Iy2vEv9MLkXc6n2IS9qH + 2FVSCfZXNiO34KTM7qOUhYgA92zdfTYIEIw2CDABMoweRy9Wb5uFJZufwWdNtaYIPQSxuXz4ut2Fzy93 + o+FiG+r/fY1b8ipq6ltw8mwLct6rldn9VHSALR/VG4DQ+ipiReqlgaJt7W7F4rzncLBpDhpd8zEn9UlG + 7zUF5/YETDHauCO6egfQ3uXG1Q6XqY2vrtmRvbVGZpMpNamIAPdu+tACUMq93GJHzxZjTcEslJ8owsUr + zVi66XnUtcWh2v57zEqZjpKKD+AeCJgM9Acz0cfRPcCtyQZlcxHG5oHN4UHW1mqZPUBFBbgvX42ED7XG + xxpKkVP2Aj5tWYbVhTPx4vIfovbqAlT2zETs5seQuXU5Ix5AP836DYClvqCUEQeblJZGzSoj3wA8SEUE + 0Lp8I+/9OgOgdJ9uqsE/sn+Js/2v4dJgAi75l+Jo70wkl/8A81f+Bdd7XcZE0a7bcgKZm6uRSZPMTcdN + P0h/V6piJvzw8DfshDJ7iIoK8M2NRQQggTLQx9RW1x/Fa6k/QqX9tzhifxY7mp7C83N/jC9bWuBkVCZa + Tt43YI2CcXksKXont6fk9Q8hNe+ozB6mogLcv4FbRQChLeZgiitqP8FLSY+j5NrT+NPCqSg7XGLWVGuv + DKgHOMJkD4mRy9zRFzA7aM2GSplNofSSiggwOTesl2tdZdLr9GB/VRlmzJqCpeveRMd1OyOkMaN0m2it + e2NGhUx73X4z2g3AMJLfPiKzqZQAJt0MoLRMXr/tUwKMTRSTSWmAW8uDti4bunqccDKyUJqdxljppmhk + siBTjjYC2Kled8A0r6ScwzJ7hIoK8ID2qgBC5p0nT6P5jXm4Wlwybtqy60Ocnz0HbafqLWOahaddpnaa + CkBZEICXACuy/zvAg1lbjmOUACa1BDj3yqvwN9Si9Z31uFz4Pi5teQ9f52bBf+YYTv91lhW1IqZJL82N + gqbXuf1sakz8rJpavu6QzKZReh9EBHgoPf+YBRCs5jNZuah/8Y/wFa5DQ9w8nHtrHrzb0lH359/h1Lq3 + TcQys0wt2VwUx26HFz1OHlacPtOglmZ8IrPpVFSAh9PesQCcXHcVkyI6kZyGuheegyc/Bf15yaj9w29Q + nZYdNFSqA1iWddBIJlIitSRd+tgC4JLqnh6PUhEBtC5T1nKrjPIYNl7JBGjM3ICLs1+BPf5vsMe9jOZX + X0IDnylKI6WaUfdw7KGZDKUuu9eM3Q6fKerFqftl9i0qKsDUFG4VAZh1pc5lbETTG3PhSo3Hnmeexp5f + /wyOlFicf/3v+Izf9dD4uhRmLEOps9dr3RNEBb1orQH4NqUj2g0A5jREPbI6p8IcRM3aUvuemoHOJfNR + 9IufYueKZGxflIiCnz+BtoWvY/cTv5ow1Rg07gqadtgGTBYkNztlfEqZzL5DRQWYtmr9YQNg1paRfV5a + gT1PzsAu1oGiVYq3J67ERz95FhcPVIVFbEXbZbdS30m1E0BZ6OC9+oUOKvR4jIoIoHWZrq2iA6nZPkqt + mVhR3Di5kSbne79Do826l2l7T0ge6ztKvSIuyQA8TkUFeHRp5kEDYIpJEbOwTJqD6b0xWoIZuDAoI0FN + gLVTalixSSUy+y4VHSCRW0X/B4TWdiLFNAyaWWKRyYwmGscNQ6YmG9YySCroBSv3hgB0Oo4IMO1fqQfM + PyDm4Bl++OTrVC+o0Etq4l1htexQ49L2VQ8Zb8+mS1oNasHyYplFLULTCWNX7a5N4HZZtKYcCVR8ilSG + +OQyU0QLV1saP/WGxJPvWyupVXuxYMWE3qRpSLMTCk7RI+rb0BxKKZ1Y1K1EqopV0dwspTFc34ug74dJ + nzWXzO+l5GV5hwEoC/pCmdByKE03S4D/r/T3ilznDnnRGzH/AWd/Ug8fTNo6AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem76.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAABGdBTUEAALGPC/xhBQAANddJREFUeF7t + nQl4VdW1x18YRMWnVVutxT5FhgCCCA4ooAIyQ3Jz7808kZCEEELCPBMmGWSS0VmUaltfKzyl9VXbWlus + r3VoHSiOyBQSyEimOyQhnP3+a+8z33OnEJya833/b6HI4P2v315r7X3Ouf/RfrVf7Vf71X61X+1X+/Xv + ci2fao/Qa0mmPWJhhj1C/un267t8PZTjiNg83R6xY4a9w658e8fHZ9o7bZ9h77w8y9F5RZb9EqjLyiz7 + pdBlioogJMKlSzPtXRZl2C9BMnTenGvrtDbH1nFVVkyHpRkxEbPT2hPkW3ltmu6I2D3T3mHPLHvHh3Md + nTfkOroUpjkum5XuvCIu1nlVbGzsNU6n80eI1yPegNgN8aeINyHejHgz4k2IP0XshvhjxOsQr0W8Oj3B + eWVeiqNrfgoSJCPmkiUZMZ2KMm0d5qbFtCfEN3Vtn+GI2DXT0XFXvqPzokznpXmpziuS4p0/gGnX5aY4 + e89Od96/Oc+R8Mt59qX7F9h3v7PStv/I+ug/n3w46r3Tm6K+PLMp6uiZjZNlTTp6asOkw8fXT3rv0OpJ + rx1YEPXzX82N2rqnIHouSoNzZqr9vqQ4ZyR+b0qSG5BU1ybEOa/MTHRcvniKrcuiKbZOC9JtHfJT2hPi + ol6PwPTHCxwd14Ny0H1ZaoLzqsQ45/XTU5z9kQxpry+1bz+8Nuatyq22k64dNrd3RzTzbI+WvNspRiFG + Mc+2yZJ322TESYiTmOeRiRLE3I9MQJzA3FsRt45HHI84jrm3jGup3TSu+quHxn/+7vIJB/YURK3FKmBL + jXfeHhvr7I4V4ob4WOfVGQmOKwpSY7ogITrNTrV1mJbUXi7a7Hq0wNFh6wxHpyVTnZdNTXJeSZQXZTlH + vLLIse7zDfa3XTtiGrw7Y5h3p415dyiKFoLpQpOFYDo3fttEIZhPxnPBeKFxzLOFNFbT5jGyRnOVrx9d + fHDx+N9sy42an5NkH4q/Uy/oJ9A1GYmOrjNTYi5ZkB7dMS+5fVVo1YXlG0u8swPiJdNTnV1p2V2Y6bxn + 30LHmtIt9o/dO+1Nnp0xEomM9+ywSWS8ZweI5+TriIfxGvGTJDLezcm3JF4iw91bxoq4eYxExrs3jUYc + jfig5Nn0IHNvHCV5No6ieP7s+lG1by8e+7vNOVGFUxIcQ5AEPbA6/Dgl3nFVblLMpXNSbZ3y2xMhtGvr + DGfEE4XOjmumOS9BLb8iJd7ZDf/O+eFax2/qd9hrvLvsjIsTr6deId5EPZZ7QbxMvSXxECdeT71CvEz9 + JtKDskYxMt+zcaTQwyO43BtGnD+5euSxl2aNfywv2T4RSdAPydAtIdb5g+xE+2UoDZ3aV4QA15OFzg7b + 852dZ6ChQ1297vFCZ+bRjY73PbscLZ6ddomMF8THWBBPtR7Ec/KJeKr13HhOvKj1MvE8EvEgnxNP5JuI + 55GIB/lEPCefEw/yRzL3wyMlz8MURyCS+Q8gPoB4v+TZcD+rXXt/3R/mjdk3J83mQBL0o+kC/09XZSXa + Ly1IsXXMSWxPBPV6vICod3RC5345Grsf7y5wZp3c7PgIxp/3T3yIdZ4Tb0V98DrvS7wv9WQ6F0xXtf4+ + WcNZ/drh3j/Nf/DlWak2J1aEW2lFQKTS0CU/2dZR/gj+fa8nCx0dV+c4L01JcF6zdppz/JGNjrdg/DnP + LhPxOxXiKfojXtR6vtz7dPdm4uVavxnk+xBvVetBPCdfR/wGjXj3ekSY7l5/H+Jw5l43XPKsG4Y4THKv + HSpVrR5Ws69wzNNTE+1jkQSRWBGuT4pzXJGXbOv8b7kaPAbqt81wds5McnbFDN/r4ArnM+5dDo93l0Mm + PkCdD4l6izrvQ72pzltSbyZeph7ma9QrxAvquWC+0FCGBIDu5TpeNPz4xqyJi7AK3IVEoE2oa6YmxFw6 + PenfaDV4epajQ1E2p/5aJEJKzQ5HiUY8Iide393LxPPY6nleI55HXXcfCvE8EvFEvkw8jBfEI3Liifxh + gnxQLxuPeC9zPXSP5H7oHsQhiEPYwXkj/oAy4MBK0B9JcAOtBtMSbZ2QDN/f1WBnvtjIyUl2dkWH3/PN + IudT7p2Oxgur84Gob8M6byDeWOcDEc8F44WGMPca0t1cxcvvLXl46oSlGHHvptUA8QdZCTGXZCfGdJA/ + su/P9ViBI+KRGY7OWUnO/1yR7RxWvNnxIVFvJN6qu5eJN3f3Ic3zVt29Ms/L3f1GkM+J13f3ZuL1tV4m + fj2I57XeTDxFIh7kc+KJ/CHMtQbkw3TXmrtFXH2X5F59F6tfdVfTvpmjfoYVYBSSoDdWhGszEuyXYjX4 + /iQBGr2ITdMdlyTGOa/GaJdRv8NR7Z/6wHU+MPEh1PkQ5nlr6s3EB6JeR7yJejJd6E5Nq+5g784f9s60 + pJg4JMEA6PrUOMflOYnfg77gKWF+l5R45w9fXeJY49ppR6N3ofM8yOfEt9U8rxBv1d0rxPt297LxGvEw + Xq31nHgi30i8iHcy16o7JTLeteoOxMHMtXKwdHTx3cfmpETlIAEG075BYpyjK5KgU2rcd/RcgZq9ldmO + LmmY7Q+ucDyG5b7FQLyZeh/idbWeE++nznPqdXVepV6p8zrqA9V5Tr2fOm9JvI56fZ3n1MvEr1GI11EP + 44UGM/dK0iBVpUvvKF+aNmkupgTqC25EElxBSZDyXUuCpwrtHVbB/PQE543vrnb8tzbPW3T3KvGhdPc6 + 4tVar3T3rZznea0PPs/zKNd6Qbxvdx8a8Yggnsx3rRyEOIi5VtwuuVfczlxFA6XKZYPqVk+ZsAwJMAQr + wU8pCbITbJ3kj/bbf8H8CCI/PdF543ur7fsV80Ot82LJvzh13vuLQnbukzd8deg15tntDIF6f8RbUW+s + 85bUw3ShgUJFt3FVLr29HkmwHCvBPUiEnybEOq7IQhIkfdtXgicK7LzmY9m//p1V9l/C/PMa8RbdvV/i + A3X3IN7qtC4g8aLWN726QWK4JFyG2NwoeZ9Ol4kPZZ636u4V4hE58UR+EOJ5HMjJJ+NdRbchDmCu5QOk + iiUD61amT1gqrwQ3Igm6ZsZ/ixvD3TPtERun2y+hhu9gkf2xcOp80HneXOf1xHPqFeJ9qdfX+aZX15Pf + hoty4Hyzl3mfSjcQ7wm5zkOB6nyI1HMtHyCrP9eZxQOrF6ZOmkdJAHWjJJgSH/PtS4IdM+wRW/PsnWnU + e3WxfQ2Ib7Ek3s88L8i/wHneb3ev7eA1/Xa9Sj4Zr8TzTV7J+1QajOZ792S8THxo87xrNYiH8Qbi5e5e + EA/y/RKPCOLJeNfy/oj9mWvZrZJ72a3MtbSfdHLhwNP5SVG5SIA7sBLcgKngsrS4b9lm0WMz7R1pk+fx + AnuGa4fNoxFvol7f2avE+6G+tfP8RoV4ubunf0d/5uOJrPlvP2eUAWS6Xuebm1jjK6soYalsyNQrxMvU + W87zMvVY7g3UG7p7M/F66o3Eu5eRbpXVj7mX9kMS9GWH5gz+HMYnIgluh67DVNDlWzMZPFkQ04G2d1dk + O4bVb7OdFcQHmueJ/ADdfcjzvK7WE/GcfLm7R/Q+m8Wa39ojtRz/B5NcZ+Gzjvjz563juWappeI4az70 + uuR9eSX+3LEgPbx5nhNv0d2T8b7EUyTiQT4Rz8kn0/tJbhjvWtJXci3twxqW9JF+n3/PnxJindFIgL5x + sc6r0+NjOqMkfLNJsDvfHlGU5biU9vaLN9o+ClTnxZIfgPigdV5HPSfeos5vHsuaDqxhLSWfMLhKqNOK + b6A9kJAHlAxCLS2sxVPPmj84wDxPJOvIt6jzBuID1XmFeD31RuK58Vx9kACKIln94sjzT2SNeBYJMAbq + gSS4Mj3uG+4HqO6j6bv2zWUxTxHtVt19QOLN3T3N8yrxoXT3OuL35rKWU/+SJJgHM2GnVuv9Eo+IH4mI + X9fSosQWNbZQ9DZIjX9/UawIIXX3IJ7XeoV4xKDE8+UexPflxJPxDYsjESMRe0uuxb1ZxYI+DXOTJy5G + L0A3otJkcHlynP2b6QcenxnTMSPR2RX1P8W9ParRSL2uzgfq7g113op6c523oB5qemM3k5o8nHa6rOq8 + lYT5PAEsxc2nlUBWc9lXzPNkaoA6L1MfqM5bUC+I11MfKQTTNfVirkW92OHZA44kxjqSkADUD/wICXBJ + /NddCnblx0TQ41V5KY5eNVujSjjxvNYr8zzI58QHmeeJeB51xPNaH3ieV7p7JIZ07qNXYSZcFKbTRcaK + aEG8EmWDfYhXIhl+TonnzqnxnLueeV6Y6Yd4ubsn4uV5npNPxHPyte7ekvglCvGIMF2Q34s1LOoluRb1 + ZA0Le/L4i5xh+2D+RKwEvakUpMbFfL07hY/mx3TC0n/NX5bZntHXeb7c+yUe4sTrqPch3op6M/Hyvj3+ + m+Z/7CfXyfswqQ9EPE8AHyEZkAA8CVhzfRXzPJfjh3goUJ3n1CvEQ7o6b6ReEC/UU2hhD66K+b1cc5In + 0ibRfVA3rAiXQV9PKdidb+tQmOa4fG2Ofbx722SPbLzFPN/a7t48z+tqve60rumPO5l0vgV26sgPRLwS + uclWxCvRRLwSyXglNjdLzZXF/P+LEx9sntfVemE6yOfEE/n+iKcoiG9Y2EMi4xsW3oJ4C2tY0F36W/7A + D+NjnTQaDoiNdV6DsbCzbNHFuzZMi4nYOj2mc2q888dH1kW9pdZ5TrwV9W1V52Xq5ZM67/N5vOaTucEU + iHiSuc7rpadeLyQCkuAca/z0LzL9ZuJ967xvd++/zpuJF7qFuRaQunPVze/esjF91KNIgNFQd5SCrhd9 + Fdg5w9YRdf+K3fkxWajz5wTxoczz+u7eH/EW87zPad19/N+3lByGt0bCzTEo8UrkJmvEK1E2WiVeiWS8 + iM2sqalJQj8QpLuXiZfneU4+J17r7n2JR+TEE/lEPMiH6Q3zu8vxZgk/Zl8W9jkF09PRC9yBVeBHybH2 + S2Sr2v5al8MbP3SczutOrJ/0kTXxVtQrxMvUhzLPm4gXEid1jS8thrEtlrQrgu9kviaY2lJ9ijUf+Tv/ + Z3OdP9fcxJrPHEFslqk3Es/NJwnzDWo89g8xEfgQr+vuA9V5v9QbiefGK4L5pHpoe8aIZ7ACjIduoVUA + o+HFWQW2Trd1mJbsuOKxmbZMEH9eEC9391tC6O5DmedV4sXevfHu2+GUHNK5Y++TifDZSLwSZYM10psb + WdNbeySsIsz78kqZcBP5XpfkeTSeefcXSc11VWSsRrwSYXZTk0Z+kxwbGxuZ+6n0wN29aZ7nxKu13h/x + otbria9X4rybJTK/bl536bPCfsWo/9lIgDuxEvwoKdbeOdbpbPuxcENODJ30dTu6dtL7F17nZeLN1Fve + hyefz0O0n3/+XJMf4nkCGNSCPsF7YI26i+f9nxUG8rn5ULPXxTy7Y/lM73kmgzXXlgvqOfFG6oXxipq4 + vO/8ykh8OHV+kf86r1IPsxXi9UICsNp5t0hbpox8GgkwQVkF4tt6FXgE9OcmO7pumR7jRJ1vMc7zVt29 + eZ5H5MTru3ttnleJD3L3bdNrW+C3mXglCuL1sekgyOd7+OK0Dgmg1XglktGeBsm92ynP9QOZ51cLpWYy + V1frFeLJ8EYlNjZK+DHzlh+XXLRDGFJ3D+LN3b0P8d0lYbyR+HoQLxsv1c27hdXOFfGf+QOOYOnPwAow + GL3AD/Hjtp0IHp5m64TMuvbDlZN+E3ad9zvPB6JeEK+dz4sz+nP/el2jXiSAX51DzUdiGfbtvf9TJKg3 + dfZIAObZ5ZRneszxKwaxxi/+z4J6QbycBEgAIa/bxVxYQVpV5zn1GvFyAlhST8ST4YpAP1fV3B7NS1LG + bcUKQOcEN8Gry5EIbVMG1ufYIhZOsV+2MMN+T93mcTXWxIcyzyvEG+d5a+J19+Ip5/P455YzX4Y8zzf+ + cZfPaR0SwLq7pxVgl8Mwz1N339ToBelo9EzE80jG89jIvF6v5N633A/xFvO8Srx1d0+1XhCv1XphukY+ + GV9DcS7inO7Sq9PufAcrAG0R077A1SgDbbM7uG16dMeMRMeV++ZOXqMRb6rzlsRbUQ/aOfUK8ZC+zge6 + Dw9/TkvNGR/S9SK6SdTVe57JlMnX9u29+5cbyedJcI41uRuYe6fdOM+jdDTWlAvaYXKju541okH0Vp5i + 3iPvMc97/8M8f9jF3L9axNxPptJNI0bqDcSbqDfXeZisl0o9J16jXiGeTOfG61Q6u6c7LS5mLhKAdgd/ + glWgS5usAquybJ2RWdeVrB/3sejuzcSH092biRfdvfX99qa7b7dPZi0NVb7EK1Es7SI2uiX0Jz6ndZ79 + y7TuXj/Pu+slSgDzPO95eZXkeWUN8+ydLn4ef1/M+IG7ewPxoc3zVt29FfE8csO7S9x4kE/x7JxbpOo5 + PaRN6aOeh/nR8Ks3zL8C08CFNYPrsqMjZqbaLyuaGjPCtXlsU/h1XiHeqs4r1BvrvIF6/R0523gCmIjX + qNcLCUBlilPPJZ/Uefcts5znkQDMvSNG3sXTzfPyTK9297zGX3id13f2IgGMUogPRv1Z0hxSD64/5Q4+ + BPIzkAR3QNfixxdWBjbmRHfE6HfVy/MmrSPqQybesrtXiEdszd232yaxlnptBeBGq+Qb9+6bm5skKgHm + 0zrPvqXW8zytADts2t590NM6mfjFgeZ5q+5ekG7u7ol0JYZKvDCeYg9WPZuvAKy4sHdDRnwM3S8wEgnQ + DSvAhZWBzdOi6UbP6z9fNe5tQb1CfCjU+6nzZur1xJup5/fiyffh4c+kHsAv9SRdd+9983GZfHT2cnfv + eWmpkXyeBGjyXLQC2HS7eOZ53g/1nHg/1AeY583U6+t8uNST8YqqZvdga1JH056ADeoJ87tCrSsDRZnR + EfPSYy6dnmzv37BxdIMgPlB3H2CeJ+J5rTcTH8bdt/j55rKjlsTzKJZ2rcZXlfC/l/60zvPSEut53lWH + HiNaJT7keV4+nw9IvBLJ7CDzvEK+vrsXxHeXZOMNxCuxCpHMr5x1i/RS1pC3sQKkIwEGYgW4GgnQujLw + cE5Uh9xk+xW78qLSAhMvUx9wntdTb6rzYTxN2/TZQSP1Fid1PAFIqPPed38tegC5u/f8ejEnnkzXCwnA + 3NujBPUXRLyJeph8ocSLBPBPvF6V0Acz+pei9s9EAtwLXY8EaN0B0fbcyR2T4pw/eG3+hO1qrbc6rbOc + 5wN19zLxrXiatvHNJzTyhdEq8UrkY53S3Xs9kveNR0UPgAYPCaDO80rk83xDneTaFmUiPlB3LxMfQncv + iA9xnkdUiJeNF8SLLt+H+CoQz41HJPMrZ/WQThb0ducmRD0E88dgJfgvJMCliOH3AaumRnfGb3Ld4RVj + 3vKlPkidNxDPl3wd8QHqvAX1yi4ezfPU2MlLvo8E9Vp95wlAgtHef71BR9XMg5mdG8/NV9SIBKhlLkwZ + QakPNs+LJAhKvUo8SaZcL7HcC+IN1JPpJsnGc1XM6snKC3tKRSlj98C7GEiMg7Gx4fUBc9NsEQvSbV2m + Jdt7V6wbVWwgntd6hXhEv8Rrtd7l5105GvGIFsQb77cfzH/f5vJjnHRuuky8iKK2K1Fe6mXSm6TG2grm + PfZP0w6eHBtqsQJMsiDeqrvXER/CaZ0w3kh8sO7eL/G6Wq8QL4zvIZH5FYUiPp0x/HWYngzy6YUTP0AM + 7/bxpRnRETNS7JfPTou537VhhDtwndfXepl60eAFIF5PvUK8NfXGu28Hsca/PCPO7XkC+KOem6+KEy8S + QaWeGy+SgHnqsQI8MtFEfYh1nieAL/EiASzqPImbbyKeBLMNxJO48UaZqVcE+rl+k33XRzCejojpbWTX + QuE1gqunRnWYmRLzn5tyohIE8eF29wHmeYV489O0nPxg99sjbhnHmjG3C9I18g3dPYgXEYQrUU+81ytx + 43n0Mk9DveT65TzWgGlBJZ7H8Lp7Il2JCvEq+dxsC+KVyM3WiBfGa8Qr0Yr4ckRhvogf5PUvgekFIH84 + In1PQning2uzojqik7zql4UTlmrEm+q8nng0eG37NK1GvLKLJ2Z5Mc97//wUo+NalXpOPE8AVVbEc/NF + Isjycnk8kNvF3FWnmfvd/cy1dzolpyC/lXXeQD1MtqRe7u4NxPMEMIoTTwpAPalM1lf5kQ0wfgH0IHQj + 1EW2NrRrU/bkTvhF1+ybNX63gXjzad1akC+Ml4kPYZ6nD9b8NK2h1hPxgZ+mpT+/qeQzMprXephtQbzx + tE4YLxPvUaJHIvPdPHqY2+2R8GPmcrslV9kJ5vrrC5Jrp533AgbiEbnpZuJNtT7oPO+n1huIRyTiufF+ + iC8r6CFx8ykW9GTFM3s1Z8bb1oD8CfCRvhHlMsTQJ4F1UyfTBPCjvy8evd9AfUjzvEx9q+u8jngd9UK6 + 07onklljfY0f6oMQr4jIh+HcfJEAstxcSATmcjUw1ycHWcNzuSgJvQzEC/NDI14kgCDeTL2edkX+iPdH + vUiAnuwMVDKzV8vsxIk74KG8IxjbNawEmJ/GR8DrjxSN+LOB+Daa532I57VeIR7R79O0yv32dFqHuf6X + cyR+TOtDfKOOeNT6IMTDbImMd7kokukuCT9mDTy6WEODS2qor2f1n/5Vqn80kdXNvwWkG2u9gXi51hvn + +QDdvYl4mG6o9Zx0JXKjdcQjwnSJjD8zk2IvVjqz1/mlyeP2gHzYGNsHMbxRcGF69CX4BTecXPnAexrx + vMmTdSF1HuLE66jX13lOvY54n3vujXff0mzvrTvrh3or4nkiCOJV6nXE8wRQBPNFAshqYPU11azuj0+w + uqW3BSeeZEU9mW6SkXgj9XriDdTDdIV6Mv60LCSAtCplzIvwkG4QobeU0zethJUAXfALupWuuu9L2Xg/ + 3b3FPK929wrxIXT3RDyv9QrxFP09Tet7Wud6Kl3ylp/QiNfVemG8TD6IF+TLxPPIzZaE8TL5RDw3vkEi + 4+sRIVZfL2Jdfb1U98lfWe2a4UHneW68mXhdrbci3lzry0zkn5FrvSAfpoN8bj7FmZQAPaWHUkbvB/lp + 8PE2RPr2tND2AnKTYiIWpUdfil/w09Orhh81EB9o3/5i1Hk/1HPTzfv2D+Hv9+5LzIOarVKvIz4g9Wbi + zdQrqhdCAnDVHv8Xq109zC/1KvE8CYzE8wQgqdTriOfmWxBP0hGviExXBPq5kAAvw0O6N4CeIr46zASI + oq7xptKVlABEfKDuXiEeMeg8H6i7D/1pWphuOp+XT+voFO+pdOb+4u+SBybC7NCIRzQTz43XEV9PpteB + fDK+rk7Cj3msOfwWO7t04EWZ562J72lJPDc+X8QSRCTAAZA/FT7Sm0evaU0C3Fy6chgSIECdV6m3qPNm + 6v3WeQvq9cS35q4c+vk92cx96A3mxoogiBfUc+ODUG8mnpuvCMbL5gvV1rGzv9vFiTdTr6edG6/oAqlX + ar2ZemG+0BokADzkCQCFngDTkAAL0+QVYMXQo77EB5jnifgw5nnf7l5HPIynKEwP5Xze4rSOdvA2PMBc + v31Ycn35LnPV1fh294iCeESZeBgO4uVaz03XiJdNl8j4mtpaCWI1FWVS9RabT603EI9oOc8rkRstiPfX + 3QciHqMfGS+R+adm9JLWpIxp3QqQnRgTsSAtinqA/zpZNPSwoc6rNT6cOi9TH6jOB3qa1ky8mXrDvn2A + 0zo63t23nFNvJt6qzpupV4mXqZcTQKimlp39v31hES8SIBjxgvpAxIsE0Ks3EqA3JcAr8JASYBAUegLQ + NTeVN4E3Hls29F0j8YHmeT/dveU8b9XdC+Jl40G+QjxiG9192/DCLGOt1xFfV1/HiTfXepV4RCKeG18j + yD9bUyNx88/WSGcry1nVinsDdvdEuhKF6X6I99fd64iXjVeJF8b3kk4hnpzR+/yy5HEvgvwp8PF2RPpa + 3dATYHYKHwN/cmjR8Ne+ljrPiQ+zzqvU+yGejBdJoKr+hVkq9SrxUN3ZKlb7/GxW+/puVlfylWWdNxPP + jeeqoQTgqnqxyEB9+PO8rrPnxodIvKIZQifyep+fnzjhOXiYCtGRMI2Boe8DFCTzjaAfv1I46uca8SHM + 81Zvx1K7++DzvN+7b1t5Pm8+rUMC+MzznPjqSql241gxzy8fzGpe2SjVVpT6Jx6RjK8m8mF89dmzEsSq + 3jkA8sls6+7eap4PSLxVrSfideST8cWIxTBeicfyIs/lJUzeBfIT4GNfxP8MKwFmJNv43UD/nf/gVp86 + z6lXiDdRb1nnA1Hvj/gAdT4M6n327bECyAnApdT42uoKVvswJYBunn/EzmpOfmGgXiVeRz2SgBKAq+rY + J6xywW0a8SbqVeJJwniVeJEA1tQbiacEMBIvzNd0JC+yOSnWsR4e0hdX9oZoKzj0s4Al6fw08No908fM + VYlXa72e+CDdvdU8z2u9eZ4P1N23/ny+3nRaV/c8VgAyXq7xandfVSHVIAH4HK+b589usUlny06pxMNw + HfGI1TL51dVSVTViZaVUsXyoSry5u7ea51XyudnWxEMG4nnkZgviT+Zp8WReb/bBtFvPwr8VIH8y4i2I + l4eVAHNTojriF1yNRHDC9JZvbJ4PgXiRANbUm8/nkQAq9fo6X1NVzuQE8J3nX9lkoF5PPBIA5vMEEKqq + ZhUbo62JJ5mo19f5wNTLxMvU62kXxhv1h6zBx+HfYoi+qPK/IGrqQ08A9AAdUuIcV85Mjr6vpmhwtXGe + V7p7C+Iv6O1YVt29TDxFTrx1d+/vfN58WleLFUA23TjPV5ZLZzeMheFijjfM80VDWHVZqYn4s4L4KiK/ + mlVWVUmVML+yskoq35GiEh/KPM9jmMQXm4hH0yfi9N7SibxItnfK0H/A8DkgfwTiTxDDuyFkWqItIish + pmtSnCPyyOK7PzdQb6jzUKh1PqSnbBTiQ6/zKvXLB7L6jaNZ/dZJKvHqaR0JS3vtz2Zpnb2+u8cIJxJA + ph5dvDrPz+nFqj94QyXeQD1MJ3Hzq6ooARhPgEDE66jXE2+kvjeXP+ox5gnJxCMBoEih6ZFsU8qo12B8 + HkTfOHIdFN4tYRnxMRFZiTF0P/lN78y998CFzfNB3pVjIN6qu0dcc4/k2jKeNTyRKjX8Yg5reHWz1HBw + L6v/8HWp/qt/svryEqn+bCWrrz0r1Z36gtUuG2h5Pl/zs1nW83xlmVSNBFB28PQ7eTTSVb3xrCSMV4iv + FsRz8qtYBcgn8ysqKqWy7Ska8a2Y51XiEf0TL0dOvEb+ccQjuX3OFSRM2gvTp8A/2gS6GjH0PQDlKkiO + 4vcE7Ml9cK2BeL91HuLEt1WdV6hHfP8Ac9XXWe7b++ziwdDaHU7rM3paAch4XWfPu/uKMla9nhJARz4l + AIl28f73UUG8TL0wH4Lp3HhFFZWsbFuygXqRAMGIJxmJt6QeZmvEkwT1x0G9og9y+tenxtm3wDv6HsK+ + UHgjoHLNSIrmr4VZkjbJZvnu22Wm7l4YH3iet+ruVeIDdPd/2B3CaZ3W3de+8bTv+TzFvbPE3j2Rr5/n + K8qkKiSAtoNnPK2rfPN5SRgvar1KPHX9iOUgn8wvr6iQzqwe7Us8IjfdstYbidfXek68ElXSjcQL40U8 + lttb+t/MO4+C+CKYTu8S7o54OWLoDaBy5SdFdYinFxHHO24vX3J7caA6rxIfTp23pN5Pnd+bx0n32cUz + zfNKd19bVsJqiu7k1Bvuytk7S6Ne39mXn2FV65AAeurlWb5iTh9WeegtmXoQL5Z8WZWceiQAV1lJMTuz + 6E6/dV4+sAmJeJEARqnU64jnxivKjWTbUkf8BabPgR6AfgKF1wAq19QEW0RqvJ1eNtT9YOG9B0Sttyb+ + or8d66FhEt2K5UM838Mn082ndSD8tV0wv4fhfL76uULreb78jFSJBBDEg3zdDl7FqhGsorxMJr6KE0+1 + XiGem1+OWF7Byv71d+n0nFuDEB/6PA/DgxIvjEeE+V9NizyfFz/5WRBPD4XQdwyF/1CI/sIqQGcCN2yb + Ono+zD9vSb1f4i2o1xMfhHpuvF5H0Oyp1OuIV6g3d/fU2W+1a529SACVev1MX1V+mlWuG6fu4HHzeQLg + x6/uMtZ5E/VIAkoAVgad+f2zoVMvk28gnpuvSV/nA1F/VNZfswZWJsY6NsKzeIjqf3j3ApqvvETeB1yd + k2gbWr2kf23AeX5JiPO82t0L4kU0z/MiGub5Axt0xCNazfPK+bzS3R//RKpeNVzt6queLbSe58tOSxVr + x4mdO5l8vpmzNV6qKD0liIfxMFwjHsbDdImMLysrl8rKytjpXVka8cL4gMQH7u4F6cJ4a+KPIpLxIF/6 + KreP9Eza8PdhOL0hZBziTYjhPQ9gvqYlRHdAR0n7yL3eLrz7d8GpNxMfRp3nCaBJv4vH5/iN41hdVblK + vIF6It6qu6cG7/DbrGrFUNHZP1toOc9Xlp1mFWvHcuJVrR7FKo4cUok3UA/TFerLysspAdiZE0dY6Zzb + BPUq8aRWEs8TwCiFeD31Qn3YkWl9zhcmTPo5vJoO0bsBaP6/sJdHp8XHRGQn2Logk36yOWPMLBB/npPf + qnmeG+5DPI8G4jXy1R08ivN7stoPXhfkh3I+T+Yrtf6rQ1LVVgerfG6WzzzPu/szpVI5EkCc1vVi5TvS + pPKvDnPitVoviBfGg3gYfwbkQ+zMmTKp9MAumC1qvTitk4lH9Ed8sO6eSFeinvijIF4lf1ofHt+aOrAS + Pm2A6QmI/RGvQgx//jdfMxKj+GNiU+JjhpyYP+BY0DqvvvvWt85z4nkCCOmJFwkgiFepJ6GLV+f5nQms + Fsb6EC9Tbz6tEzWeBOLpho3P3lOp18/zFWdKWfmWWFa+cwor/9tv0PSV+63zCvXceFmnj3/JSopGWhIf + DvV62rnximC2kfo+XMJ80J/TR9qaMvIgfKLnAfnbQqELW/6VKyvBRmWgK36zHr/OHfYYJ76187wF8Ur0 + IZ6bbrrffn5vqea936jE8yhMtzyf57XeinjzPE+kl5yEyeWG7t4v8WVlPJ4G+RAr+dXDPsTraz0nXYnC + 9JC6eyKeG68nnhsvyD+SEylh6WcfZPd3ZcbZngTxWfCJvzUcsW3eF0zfUIkk4DeI5CVGTTy7MLLOSHzg + Oi8SwJp6sdwHoV6WOs+vH8NqKs74Ug/jNephvlzrVeJFAsgS87zW3aPGiyZPI14s+SrxvM4rgukkMr/0 + g4OsZO4gv8SLBDBKpZ6bHgrxJI14lXxZe9OHfgx/VkHyW0Faufvn78pNjOqYFOe4KjbW2e/3M+7aZznP + 81qvzfMiGomvNxFvJl/du1d38Py8HevF5dJZGArDA5/PW5zWyRs52jzPjRfEg3aZeH1370v86TNneCw9 + flQ6tWqcIJ+b7a+7N57W+SNeq/Ua8cJ4mXgT+V8iHs7u2zQ9Pup5GJ4P8ul9ADcg0vh+4cu/cqXFxURk + xMfQmXK3OcmTHLULe3pV4i2o19d5A/VhEC8SgGRxv/283qz6j8/IpBuJl5d8IZiu1XrTvr3c3euJ91/n + NeLlBGClJ75ip7ZN4eTraefGc/MtiPdHPcy2JN5EvUI8aj7Xl9ALafd+AjDXwhva++8H0f1/bfOiaP2V + kxDdKT6W313a740Zd7zcsPAW1PVw5nmNfB/i5Vof8tO0FBfcyqr+/IJc483n876ndUbiA8zz+loP4mXj + BfGnz0gQKz12RDq1IysA8fruXpAeyjxv1d2biSfTlfhpdt9zOfHRe0F8AXwZgUgvg2jdW8GCXZgCItLj + Y6iz7DYraZKzcl7PmqDEQ8L4MOs8zPahnhuvie/Zz41kVVgJqmCunnphPoR/b6Aephuoh+ka9aY6Txs7 + ZurJ/E8/ZKc2OEOgXiaeJ4BR+lrvQz033kQ8SSZer+fThh6GH2sgop9GPwK07elXLloF6NUxWHJufSln + yNMK8eZa7494v929jnh9rfd3Pl+pv99+dm9W8dwcqfLklwbihfFEvPG0zkC8xTwvG68SLxsvlRafZCWv + 75VOLbyHDLfu7jnxRvIV4pXol3h9rZeJ55GbLYj/IruPGt/PGuCaGmejL5POA/H3I3ZDbJvRz99FvUB6 + nOgFpibYxh6dHXncTLxIAI14lXoYbaaeE0+SqdcTH/bTtCvvZxV//gVm+hKNeEOd16gX5vtSbyQeIuJP + FbOSv7/GTm1MYMX5ffwSr6deTzs3XhHMNlJvnOfN1Otp58Zz9WWfZ/eVtiaPfBs+rITsENX+i0u/ck2N + j+6IFYAajciN6aMWcdNBujBeI16JSq33IV6J3Gxdredma8Qrkcz3d7+94e7b9RNZ+WtPSuXFx2TiYTzV + epX4Ck58wO6eiP/qU1by6pPSqfUOMl4lXiWfG25NvN9aryPe3N2rxHPj5VqfrZEvjEfM7sv+mDG4LCnW + sRPE58CHexBvQLw4td980b5ARryNxgx6D+1df84b9Aex3IdW5+UE4MSHVOdJ+vN5Wfp77tV78GTxO3Lm + 9mdndmWyst/uZmX/fJOVHf0MS/xpTr1CvFrnifTD77HSv7zESn6xBjXewU4V9FNpV+RLvEw9TA6ru4fJ + ltTLpJuJJ9NJIJ8dzup3riB+0q/x+c+HJkI94APN/Re+7RvqhQTomBDruAIZd3NuQpTj2KzIEjPxwniF + +K/h7VjCeOu7bwsjpdML72KnXyiyJr74pFTy0ORvdJ4XpuuJlyM3vo9E5n+W1VfalXL/+zCc3gWciM9/ + EH78Q0TaqLv49OsvJAE9PURPnfbfkP7gUhjc5I96Yb4v8eHUeZEAfqgXN2Cq9+Bx863uynmqwDTP8yRA + ApxgYkPHRDw334J4WT7Ec/OF9MQHqvOhUK/od1PuKE2MdezCZ54L0XcD/RQJQDfttN2uX6hXChrCVNEQ + 3oDJ4O5fZd/zs0DdvRXxAbt7mXglBiQ+xLtvS58sUGs8X/blub7k5Anp1Mpxoc3zOvJ9idd39xrxKvk6 + 4s3dvRXxn2cp5PeR3skcUJ8dF007fvNAPH1VbC9EuuHj61v6zVd6nCgF+EvcnBTnePD/8ga+A9qV5d6X + ephspt5IvJF6PfEG6mF6oKdsVOJlqWfzTxZw6sl0TaeRAMdZMSWAiXpBvEa9nngz9RrxJJiuoz4Q8Sr1 + MNqKeiz77NDUfucWJYx7FZ/zCoiu26AfQl//0m++MBbS3gCNIL1zEqLjPivoe0yt9Trizd29MB5RR3zw + p2l7Bn07FjddR77+fL7kiQKxk1d6GhHGI0Ls1InjEiVAa+Z5HjnxrZvnFeJ51BFPxlP8ZGrf81uTR/wN + y/w6EE9v/RqCiK7feRni17/0m6+kWDuVAspEugFxwOykiTnHCyPL9dTriVepJ5mIF+ZbEE8yER8y9XRK + p+iJAk49ma7XqRPH2MkVlABG4kM/rWu7Oq9QT/p0al/pmdThh/C5boboqJfq/k0wn47nv7ml33ylxNo7 + YDykORSjYezgxcnj556a1asuUHfPl3sT8eZa39ZP0yIBBPElpWqEWPHxYxIlQLDuXiU+QHevEo+odvd+ + 5nk98UoUxveRyPxfpN37BZq+HfhcZ+BzHYWIkS/2SsSLv+ET7oVVoAP+svQYcjdk6N0rU8YsO1XYq95M + vJn6QM/QC+I16jnxfqgPdM+92tk/ls9Kik+yU6STJ1gxxONXX7ATRZQAfqiH2UbiSUbiDdTLpOsVCvF6 + 8vel3308KdbxGD7PQoiavkh8rvS+P5q+vtm67+9CEnSMx/KEDKVTqSErUsYsP1nYqw6m+87zSiSz/XX3 + euIRLZ+mFcZbEu8zz88ZJJ0sGsMg6eRyxOVjpBOIJ5aPlk7M7O9DvLm7NxNvrvUq8bpaH6y754ar5Pel + mi/tT7/7RHKs/XF8jvSABz3hQ1u91yB+801fsAtJQMfGNBnQjHpPUcrYpcdmRlYbqIfJVsRrdV5QH4h4 + kQB6+aGejCehthu7e7nO8yXfmnoj8ST/xIdT5/W0iwQQ+mRqP77sy+ST+VEQnfLRLV60+/rNN33BrrhY + R0RqrEgCZCySIHbIvKQJ8z7P73sahqvdvSXx/rp7f8RfyN233OzAxIdyPm/u7kMhXqv1fSVhfF/p8NR+ + 559OGf6xXPNp2SfyufmItN/y7TdfuSgJUrSVgJeDGQmTc9+dPuBz/9T7dvZm6gMRH5z6IMSTYLaRfJju + j3pIT7ygXiM+VOo/ndqPfZx567mtySMx6vFunxo+qvm07BP53y3z9RfqGCUB9QRoDGPvwKSQeCD7rj+d + LujZ0vp5Xqv1RLy+1nPSlWgmnhuvEa9EMj6seZ4brxGvRH/dvTDcSDyPMJ7I/1vGbfWLEsa/inJJcz6N + etTto+HjNf+7sez7u+JinRFJsXb6/iGaW+nI8nYkRPSu9AeePZYf2aBSD5OtiBfmawpEvEgAo9RaD5ND + I55kJN5AvY52QbyRej3xZupV4rPI+H4MS770avqdpfL2Lu3w0SYPzfk06lG3Tw3fd9d8/ZUQ66AtY9q5 + oseV6L11Y2YnTlz8Xu5tRxTieTQRDxmIN3f3RLoSZcN15GvEh9vd+z2tM83zwWo9n+d51Go9mf8Rlvwd + yQ+8Jx/s0N4+At/howc6aM7/9o56rb3iYx0dkARY0vgsS1k+FB9A0rMZw/YfnRHpUonnCaBIJl6mXk87 + N54k024g3h/1MLstiTdTryfeQD1f7kF9Zj/p9fQ7ymby83x+pEunelTvaW+fVkhaKelJrO+X+cpFzSFM + R3bzU6wbken0ZQYTCxMnLflj9uAPi/N7nQtE/Dd1960gXo7cbD/Em2q9QjzFdzJuc21OGvm2fCcP3cxB + 5/m05NOpHh3s0Ar57dnevVgXzI+gkoC+gHYNqculJ1nuQ2+QuDZl9KP/zO1fEh71Qbp7GG2kXt6315Gv + Ek/ixhvVmjqvUP9xZr+W51KGHc4UN3DS0zt0GxfdyUMvcKIxmWD4/tT7UC8kQAeUBfyPO6nm0ZQwAHE0 + kiN9U+qop9+fNqC4GDVdJV6JKvFG8hXileiXeH2t1xHfVvO80t1/mHlr097UoZ+gyfsZ/r9ouZ+BSDdw + 0j18VALpTh6CoCPi93PJD3bRaoAkoOPky/BjuruIXmp0BzQ+Oc6esyHlwaffyr79yLG8yGaNeI16Pe3c + eEUw25J6mG1FvS/x/qnXE8/NVySI50v9npRhH+fyx7X4Ezu0qUNv7KB39tBsT7We7uH796Pe3xXrdHZA + f9AZEU2Qk3a+bsGHQ0+5TkBpyFyYNH7rvswh73ye29cNo0G5dXdvNc8L443E88jNVrr74PP859xw3+6e + TKddvD9NGVS5KWnUwQzxlC4t9fSsHj2wQU/s0Cvbqeeh+ybo1JRexfvvSX2gC+YjEejAg+8bUH9AiUDf + eUPPvCelxsXMXZcy+vnfZt516JNp/RpU6mF2MOIN1HPzQyPeH/Vk+psZgyqfSLnvfXT19GYOejkDPZ9P + mzn0lC49qEnE004oTT700Mb3t8Nvy0usCJiFxYpAtZLmY+oRqGuOxr/LmBIXs3hF0pinX5hy79t/zRpY + +klOPzdMNhJvUeuF6YFrPSdejsLwPtK/pvY797fM2+peTr/76ObkkX+ZHh/1LCYaeiETvZOHxjl6Mwcl + Kq1c1NjSU7r0/AQR3258uBd9YLQiQDQ2UrNEFNF77+jDpT5hJETfjZuOZJmZEx/90NKkcXseTbv/97+e + MuSjv04dWPJx9q0Nn+b0bf48p08LjD4P0+UEkKmHyTLxZDQt6+fpvvtDWf2aYfbZ36bfefzp1OH/XJ/0 + 4Gsz4yfvTYnlb+CklzDSSR29io1qO83x9E4eOrihRKWVi2o8beO2G98WFwiiZOiESBtJdMpIt5/Rs3D0 + xcgDEcmAMYi09CYjkjn0/fkLUJPXFCZM2rEocfye5UljX1yZNGY/9PLKpLEHEKGxB1YkjX1lceK4F+ck + THwOzdsukE1ftkDv26dXrtNbt+nFy/TuXarpdEpHDR29h49exUZv46IdTnonDy3znRGRuO3Gt/lFHypE + Hy6RRYRRr0ArA92KRu/Fp9WBGq67IKrB9P35NHPTSkEXfZcu7bnTN2rSN2rpRV+wRN+xQ1+zQt+0QV+2 + QO/bp1eu01u3aW4nw2lSoZWINm9ohifTqaNvb+y+zos+bJk0Whlo75xqLR0//wCRVojrEakBo+/Pp5WC + vkWbvkj5NkTagaTv06MGkyKZS9+uRclDZxWUSPRNG5RU9L59Ipzeuk1LO717ly/viO2kf1suMgIiQ4hE + WiGISjKKCKWVgpKDiKXGjFYN2nfQi0Y0+jkymf5b6jvoLJ5+D0ow+n3bDf+uXWQYSOXJIRNLO29kplWk + n6f/jv57/uvk36b9ar/ar/ar/Wq/2q/2q/1qv74v13/8x/8DlXnGhhWArqwAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem77.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACJ0RVh0VGl0 + bGUAVXBkYXRlVGFibGVPZkNvbnRlbnRzO1RhYmxlO++l4NgAAAK4SURBVDhPhZE7TFNhGIbb0ir3tiAg + A5FBE2SRRMVBJ8OijDAYE+Mgm1ArWLm0eKAFwUhQEkNUQkRBKloQF6KLKCDGRYsXyqWAUgQCLQV6gxby + +n1HG2NC4ps8Jycn//Nd/iPh1PVOva57MY3rz6dQ22OHqXsSRsskqp9NQOgaR+WTMRg6bShtsw7QcQUA + SRiOtK53mt7/n9L2b2xE0es/BWS11JkTCG4TW/BvbsFLeDaIwBbW/CEsujege/iFjZiwzHAiarrt7JO4 + jSrLDATLNCqJtUAI+i473FTgpzuAkgef2YgNywxHzvtyvNRxYTWAebcfcy4/Vkl0+4JY8YbgcAWgbR1h + Iz4sMxxFFV0Wh0fWP51CBXUtM09ghWTd4zE4PUF8d/pQdP8TG8qwzHB2XaNb5qzTyNzZ4fJh1umHyxvE + MrHk2cTMkg/mIQcb6rDMcCINZhv74shXO8fFrsXtNljnJmF6VYOcO8eRaojFkfpsxJ+PyFXrZEp1iSw7 + XCCqomNULLDiC8FFYzu9m6Jc2F2ArJtpyLqRhgJLLhrfa3GsYT9IbiK4q1gguvTRV7GAODLtu0Q09t+G + 0CdgyG7FAKHrMeCcOQemd/moHyyA8rKUFbFADP9fzizd9I9lv7jvrf67sC96MU6MLRDzHpxuOouqN2cg + DJ6CUvu3QGRh8/BbbasVmhYriu59pMuaRbJ+N5L0u5BUrkCG6QAutjdgX3lqQEWdWVZq+Q5/F5AR0YSK + SCASiT0sv3Q0o3XEgAStooO+7f1zRm4eNUqo0AWxAD92IqlCgRarHjUf8pDfcXhdfUUmqEpkmepiWSbt + L9AUGj63o8wklitsiWXypkMNqdD0nURe21EcNKYgozoZmcaU3rhL0nQ+t6PMkJydoJMrqfMJ+mXDqmLp + Bo09TJ31tH96nIZdSH4By/+MUJlLXfMAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem77.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACJ0RVh0VGl0 + bGUAVXBkYXRlVGFibGVPZkNvbnRlbnRzO1RhYmxlO++l4NgAAAezSURBVFhHpZZ5VJTnFcZJNI3WgMCJ + aYwJiydNEzVNbbXHdInVHJsTPUqaNJUDklaFiKICoqYuLAJKGGSXXRAQEOsOiqYGBEFAdhiGfdEoCLiw + DswI+PTed2Zw9Ms/pO85v3OHd77vPs997/2+wQDAM4RntWWHZbUi9BJxsRUhF1sQktmC4MxmBGU0IzCj + CYEXmnCYCDjfCNm5BsjONsD3dAPc0xsM9qXVG+xJURjsSpIbuCXUGDjHVRlsja6Q6OiQbLDwT1kkjpgr + LbCVFRg8z6aIMomODslGCFXNa+zJE4LiODA6/mSCx4SavlDTF4JRDXtT65Bf241dCRU5zxvYGFoi0dEh + 2Qim4+b1vAG1Fn0DKq0BFfFNci36lY+RJ++Ga1z5Myb+GVQs0dEh2QiiXvP68ar1xEl0hHmswS1RLu57 + OKhGTk0XtseUTZiwO1wo0dEh2eAh48WiLB6SUY9g5kIdgojACwphIDWvVQin5LZAqR6Hy9EqcV979yCq + b/fiu8p7cIosucYGbPwLJDo6JBs82bzYAHP7/iBuMT0EJWdE5drqh0mcDThFV4r7WroG0dg5QNcP41Jp + J4LO1cHaL1+io0OyITunNaA97sDzCsHh87UIOKthmISP5zRTHEMyRTYQTI+lfVgJUYyNIUWwDbgBa/8C + rPXLx9ehRZxSosVINvzP1FOAOGZGVzUfbZsWXdVD6jENKvpM/NDZjfzKRuSW1qGsWoHi8mpkF5TAzjOF + U0q0GMmG32mtATpiRnamll40xBk5/E/L8e3pGiGelN1E4uNI/L4Rg2Ti2H8pjozBN70KPumV6BsZRd/w + KDoejsA15ianlGgxko2DpxQUABUds5qYqJ5620q00GelrnIyMKgaw4BqVAMZaOoYEDMgDChHcffBCJyj + izmlRIuRbPicfGqA8TtVQ1Tj0H+YKhwkWPzY1UYSHUP8dw0kPIqjFPvIgFdqBVEuqu8lAz88GMa2yEnM + gHe65nkWE05w1aJyHfcGNVWTmEB81hw3G2jgEyBY/CFxiwxsjSjklBItRrLhdaKGAqAkccb3JPe0Ct7U + V+8TFfBOqxAGjl6pFwbiLtcJ4dgsimTC/Xgp9ieX4tHQYzwk2nuU2BJewCklWoxkwyOlmgIZEFM+/rRy + opmhE+Cq+6nqfq5aD666/u4A6u724wGJM23dSjiGTsLAfq0B3SN2gPrplUZQ9Ewpg+fxMhLnihVCNPpS + rRi26EsKUfXexBLiJu6zgUEy0KWEQ8h1TinRYiQb+5I1b7QhqpLhnjd3DqKJ4Mj97RseE6K99OPDoo+G + RgV85HV3+qAgegZV6B4YofsGcL6wnZQMXiAkepKNfydWUNAY4F57UE/dqWp36uv+pBLsSyoVlUdR5Swe + mSkn4VE67lEoOm9BlhUKm7i/4w9+8/HhoXmwjv4crknesHQ0nUv6L2qNiMh6EgO7E8opQPt803MtqtZU + zvCU6yrninW9zmsqwraTG7A+7RN8m+eIU02HkNkWgCM3XWB/4lMs8Xk7x3yTyXIS/rnFdpODFF9iPYmB + XfFlFCAmnHvNPd1DPRUcY4o1lWfIteJqKDrasS19A2yTlmGJ/9tYfMgSK6M+gHPWCoTKbRBb5wCXjNVY + 7Dk3z3yLcaylmwm3ZAbrSQy4xZVQgDhm/SnnCX9EPK1aLWLPgBqRORFwTLVGbG4cytvrUdpWh/CrUbCL + X4OdV1ZCVvk5fIpX48uE38MmYSnMXY3ZgCHrSQy4xIr39oSwZth0Q8a91hqgfzx4ytmAd4YnchuK0dU7 + jHt9KnQSdx4ocbkiF+tirLDn6mr4lX6Gb7L/Co+r1jBzmckGZrKexID2va2pmhBVEzxkGjQG7usZSCpM + RVf/CO71q4SBjt4RQoXbPQPwORUA22NLEVb5FXwK18D+5J9h5iwMGLOexMDWCPHexh36FeP3+O37w/QP + iVK80Zg2orV7iF5MGt4/8AYWeM3GAs/ZmE/M83gd77n/Ah5nfVDR3I2vYxxhl/gxvLNtYZuyCDbJi/DW + diM2YMJ6EgNOR25c3nzkBjaHFWATE0r/UATnwyHoOjYG5WFDIJOL9QHXkHatRYjndkchtysKZ1r8xMSv + i9iM+Cw57MJcYLHDBBbUc3MXYxKeCbNtRnjTyZANGP2ogclA6wWu+vuOcATXWNOgfYaPw3+FX7q+6kzf + /Yx4mTAkZhImxGtz/mW0g+KrxFSR4/mkk4HWi/M8X8dZqtyL+htY8w84XfwLlsrerTa3N/mIvn+Jr9Hy + 8mwbw+VvbTGOoM/TJ3LoJ5wstKZwzx3SV8Iq/gOEy79CQMUX2JH1KZbJ5svNHU12v7bqlYWzVs5Y+OZ6 + o71/9HlXMWe9kQ/dN20ih37CyUJrKg/cO7tmRS72tsh1zbSCx/VV8C2yws7Lq7D26J/w2wPm+I2HGawi + luDXu82KTJdPX8j3TeTQTzhZaE15Z/csX4rTLRxMVyz2mnv9k7AFWBOzAGuTfkcnswz2aSvwt6gP8f7O + OSWzVs/4gq6dRojfAZFDP+Fk4UTEFIJ7PPWNL43eo2P3snQ2zbd0M+2lJ6CXel40e52hzOSjaYvomul8 + 7TM59P/4f9AuMWzEKwRPvSlhTMwgphITlWuAwf8AUWC5pDfTAAgAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem78.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACt0RVh0VGl0 + bGUAT3BlbjtGb2xkZXI7QmFycztSaWJib247U3RhbmRhcmQ7TG9hZPHDxGMAAALOSURBVDhPpZN7LJVh + HMff6N5qtfqjrTURf+hGrWQunY5JLkklImm1mjFk6b5aizWSormEQ8nlHKl2ElEicjnIOTg4pFq5nON6 + HA4yjuO835637GyZ9Uc922fPs+f9Pp/n9zzvHgrAf8E0HYLuDPNnembur00rqE+yKRVzbCBO+k1Dgg0q + oq09SUanLp5NieL3UqI4FiWKZVHCGBZV+2DPLEECG/R01wydmBqToJ7jNBh+2ngdyS2cA6bKeVoBsYJW + NYMeK4BmJA/0SA6mFG8hjLdH1T1LVN21hCDCAoI7FqgIt0BJ6O5yIligFdREWYOeFINW8kEPPQOt4EEj + 50IzWkTEEkIL+U42mGyEZqIepbfMmJtbrBUwZnqiDvQgWdiXArUsFurOKKjbIzD1PQxTX0KgarsJ1afr + ULVeQ47/JkawhrCUsIgqCzUHPV6N6e4EdL87i+ZUZzQ9ckZjshMakhzRkOiA+of2EMXZQRizD28umKIg + 2BT5502Qd27bAFV8YxfGpS+hqLkESbonKfMbKbedVEX6ia9E3gbNDwk5khjTwyKoFdVQy8vQL+Qg28dY + SBVe3oGe6mhIUg+hoziMhAQYrb2KkZqLUAqCoawMwnB5IIY++GHovQ8URWcgLzyFj5G2SPIwDKFeB5mg + KSsAleEsKD/zMd7G+SMoL/DGQL4XBnKPoT/HDb38w+h97oJXflsRYLXWhOL7bkbJbQcIIp0wKc3FYJEv + +kiwj38EvS8Ooif7ALqfOkDG2w9Zpi2k6Wy0xlgg1d2ghVzicorrbQS+/3a08AKhrA0jQTvIMkgwjY2u + Jyx0PbZCZ4olOpLN0cExQ3viTpRd2YL7jusjmd9JcVz1arnHDZF1wghZXkbgkTHP0xBcj43IZHBnMECG + G+GoPtJc9ZHsskF60nS1MRH8ejNLCCsIK+dg1SyYuWUE3VQXPYpB+yj+DVA/AVjcWk79JZvUAAAAAElF + TkSuQmCC +</value> + </data> + <data name="barButtonItem78.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACt0RVh0VGl0 + bGUAT3BlbjtGb2xkZXI7QmFycztSaWJib247U3RhbmRhcmQ7TG9hZPHDxGMAAAfgSURBVFhHxZYJVFV1 + HsefVpNlqS1OqTkFaaNzmkZNxkwFFagQ3FHTSVIzxhgdTc0VMLdxRVBjExCRRUVBSK1EETQW2TdZ3Nhl + Xx/vPd5j+/b93/eePhs6x5lT9j/nc+7lncv9/L6///3/75UB+F3p9sfHSbc/Pk70o8cj8qsNwwLEjZ8g + T3XDH3SIc3HNr1aEYQFPxLqZWmb6mqdk+1lAT5YeXy3xh8zm89onSY/MI+YyLZNlGd7mRByJ1wPSPXn0 + nCRL9yDuWgyHYQFPZfqYV7WUfYsuTS65YUCORFtTPLKPTatxc3hnIK8XRfT8P3hoGg0LeJrVAx13gdYL + 5DygOkciAWUEoDhLzqEu+wASDpqd5PW9yTOPwLMGiL/FVN6fRsMCerFdQPttnfjbB+KWMEB+BmgORZc8 + nEUcQsphM6Qc0nHQDMl63EzJBCS5mhIeD0zAdRctcXvHp4VuGD2FrqeJ6MbDBaS5TwTabnUrRtNJoDEE + aAhCV+NpdKli0aVOJ2kGpOpIMSBZRxKaC08gbve4arpEN0QXHirgmZSDpiwgr3txfRA5jq7aY+iqOYqu + al90VRwhnugsd0dn6WF0FLuho+gAZ3EfG7kb7Td3oi1/O9pyt0KT44T2O+6I2zlW2J4jUgGG41nRMvCh + +3liIYZeXEVx5RF03qO4TIgPUepK6X6039pD6Q6052+l1BltOY7QZG2EJn0d1GlroMlzwRUnE1FAXyKW + 9EMPZe/E/eP58GU9ENfpElfrxd4PxCUUFwvxXkqZ8oYTZeuhyaAodRXUSSugSnSAKn4ZlNeWQhG7BKpU + R0Quf1sU8Ap5nvQi+odS1jt+zzg+fJxLIa7xfyCt8GCbDzOtvsX70XFHm7Yt1wnK5JW4dWIWkr/5AMmH + LIkFktwm47rrJCS6mCFxnykS9k6AuH/kv4wR6WCMCAcjhH9hpAj9/I0gukU3ZM/9yPnp4FpvL/NEW8lh + tN1xgebmLmg4j+rcLVBnO0LNlqrS1zPNGiiT/o3K8//gRjUHdXlnuFcUkyJSyIeOtN7VcZsP7S2JTmUB + yUOnIhfy0micWWpUTLdYFbLnr24bA3XlJSgLXKDI3oHKaAfkBMxEqrcNUr2skeJhhWR3Ky5BJj1oietu + FiiI+Aqapkx0KDKhKfSBOt8FrXn70XpjL1pzd6M1ZxeU2TuhzNoOZcbXaElzRkvqZrSkb0Vu0CcIsnvd + j24xDbI+Mc4mUBSFozHZGXXX1iDN0wattWIJ6RKpmUZ9R4uU6iY6lPlor4tGa74rZXugyt4FVY4Q7oAy + cxuU6V9DIaQpjpAnb4T8+jo0J6xBc7IjYpzfh4ftoDl0S1PQN3rzaDTkBKDi0ircPrkA2cH26FTlQ8Pl + oy5wI65SQnUuE+buo2i3lqz/QJG1EwoKFRlboRDSVCdKN6M5aQOaE7+idDWa41eh8eoKshz1V9fg1CLj + VuvhfV6mW3oI+0WtG4nKhMO4e3oxUtwsURzrgo76a5KsNXcvZbqEFCopVGZu1wrTtmhbm+IEedImplyP + poS1aIpfjaYfV6GJwoYYBzRE26P+0lLUX7ZHwbHZCJg7OIpesT1Lu2K/778cgaKLO5DjPRtX2J7mO2HQ + lARLQlXmTqgyOI/p2yijkDJtW4VwIxOug5ytbYqj8Jo2ZUP0MklWd/Ez1P2wCLXf2aHm/HzUnFuAq44m + cJ82cC2997flFy4s/yvyQ9ciYddkxG6fiPaqC2hJ+BLyuJVo4dwphIy0XN8AeeJ67VzGMeU1tjZ2hS7l + MjREfU7pEtR+/ymlCyldgOoIW1SemYaKU1aoCpuBUDtjrBz70tv0Sq92UcCLkf/8C9J9luKH1aOQ4bcY + 6kJ/NEV9isYoOzRctEN91EI0XFqCxphlaLxCWSznMvoLtpWtFSkvLkIdU9ZyaVZHzkV12ExUnbJBRciH + uBdsiXtB5igPssBNr0nwmz6wgE6xGd1/M750dvFbfGPZItx+GEouOqIlYxvqv5uP+gvzUHeenLNFTeRs + 1ETwxuEkbDqqTk9FFZNVhdqgMtQa9yirCLGQZPcCJ6H8+ESUBZih1N+UjEeZP9+Km/6Ggx8O8KRTvJR6 + Hp06SPhlL5/6ZAiiNlngzJJhkGftR8PlpaiNmIWaszNRHT6DwqmUUHRqCipPfoSKE5QxWYUkm4zyAAop + K6ekTMiOjkOp3/so8R2LkiNjUOz9d56/h8jP3sSWCf0X0im24h5+1uL7Rib7Y6CtEcLsR+Ly5vGQpziz + hUzIVFWhVlpZCNsYzDYGUshk5QHkmJmUqsxPKysVMp8xKKWwxNsEJV7voshrFIo8R6LIYwQK3UfB12aQ + esQrvQbTKdZ/Dx8rbQH9/WcMRvD8ochwny4tl0op4QdMyJaKhJJUCE2ZbjyF45iICX3eY0KBCYq9iOdo + FHq+i2KPURSOJEI8Arfc3kGy03C4mr8aQ98L5EmfjwbIBGL085oyOC1o3lAWMQwhH/8ZwfPIx0MROPct + BEkMQdCcIQgkx23fxPHZZJYxj8YImGmk4w0cm0Gmvw5/wTQy9U84OnUwfK1fwzcWAxrmDO87gT7xSdfT + z3qQTCCG2I/7kP5EvC5f/RmizF9C9PCXEHcXiHNx335EWvt+1q9Jcn0BYjMQa1IU8qiIG/0viP/Rf03/ + 10epGPqvk9+a++N+AfqT34tuf3x8QPYTe6ndyZod4FAAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem80.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAkdEVYdFRpdGxlAFNlcnZlck1vZGU7U2VydmVyO1BD + O0NvbXB1dGVyO3LY4GcAAAGZSURBVDhPfZPZSkJRFEBzKqfsk3z0U4qgR41SynBIc8Sk1LKCCOqliKBM + b5qlRj5EjwZ9gGMGXg0l2O19LjbQ0QuLs7lnnXXug04AAOPwvMLAR44oERUHBSIjb3juZ8ANRLlz8uRE + AXjQHjoUkvECCs921nkmvMDza5PLqVABdzTjIpcXUIWSJRzHP75EgeRJHP8FpgK7RWi+9xitNq7IcGXv + 213wxu5IVnMDvniByVa/AKG9MgSJZBkCiD/5yALrW3mSNbyA2hu7hwbe1P0Y/KUnrY23LriiuZEBDdVJ + srjT4E08ICWGJ04UcU8ERyRLspYbcG3mWIBuE3t96WaGNNdxzx4WSNbxAlpH5IZJ9ZbIB79gNZgZGdDZ + QwKKXaihTISLRlhLGdlcb3XYavOnSdbzAvoVrP+WLRcmmD8ysbnWxHdNEZY3UiRPcwM2/zXKdFiiP/hk + VPEgRarIkueKZAM3YPWlvm+qYqDKZmllc6MDi+5LkrlfoJ4zH9wuWI9hHLPm/Ty63N8B/Y01iAGZGQHt + kSOXzsHEF0eqmAZmOcO3AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem80.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAkdEVYdFRpdGxlAFNlcnZlck1vZGU7U2VydmVyO1BD + O0NvbXB1dGVyO3LY4GcAAAVXSURBVFhHrZdZUxRnGIUlccVdzPIPkov8mvyD3OTWm1R5FzVgjAkIBmWR + nRFkSzSWFYSYoIFBWUwKk1Qq5QgMy7DMDLPP9MyAb855uxsHRJqxmKqn3p6m5zvnO+/3dTd7RESxP3cH + PCwFFu+CfRb784S/2QveAQUtd56hmB9bU3U3G8CHwvzRvp6+f76CIXlb6jpHizEOzagJoB8nAype3fKo + 2P10WnyBhLzwRV/DM78VkXXm8bv+wf+kpPxuCcbbYGI7A7xgb6745BbibzZgY5qY22iCLdmRgf2N3aM4 + tXuf+o4RChwETGFbA7zgQFPXmCRTWQmGUxLIJbQRP6t1nsf+UFKWV5JmtY6jibTcaH9MgUPW+I4GDjZ0 + jUp29aUkjTVJplclboD0mtYEzsUVnEuSrMRY8Z2VRHEuqnVVUvhdbZsaKATcVY4GDjGyTNYUau0Zk9bu + cWnpHnuNZrSq2a4wTZq6R6SpC3SOSCSRkRTGqHYNU+Aw2JmBOhgw1MCqtP/0p84ilXmp1UgjGQXpMCEj + q6kwqYQmRLJy8/a4ROIZ/VuVy52XgcK6W0/EyKxpnO13/pBYyooXNaowYmDVCMFsKWjj+mFcwvG0mqlq + GaLAEeBogBccZs8MzDCaWJW2208tMQysvUVNoFLQIhzPAlM4FDNp7RmXlVgaayQj15oH8zNQg54x7ggG + diFK148AM2JtJTi2aYGQVq4TrJdmwnWBnRSMptV8ZePvFDhqje9o4EhVq1t7ygg5eAJRkxjBgMSOX49z + YDqkqXMUW9TQpK42PMrPwHX0jDsgHMvqjFY02jQizWisKxEemzWwCb9FIxaynwbw24r6hxQ4BvhwcjRw + tBI9i2PxMMImxLkuhu+vRHkTMquf4NiPm5JNQ8cT3IxSujbK6wYocBzs0AB6FjMyEowZ2NOj0og9rWBW + uccUaQSsDR2Ppf7WRhZXUkjOkLLa3/IycIw9i6F37CGF2FOu9BBqCCmEsDYUJmLB42DUQEokLXVtw7IQ + SEoIaZXW/EqBE8DRAC84zp5xezFCzmwJkRLOaMliAff5BdYgKvBBTPGzJqT2plu/ByKGfFv1gAInrfGd + DVxBz7inl2Cgvn04R9BkXQzwuW8Slzk/sGqNawg1oQ+ry9d/ycvAibLaAb2ZcMY32twmmBHhzEyGIOKW + GtRqiFGwunXwFS2DaoQL8vI1NXAK8J3A0cBJ9kwNYIbcx7rHWbfAvBumlbCCOyMr1sjsUhwpJuVSZT8F + isDODHxX/UAXFHvpQ4zzgLOZZ8TWsV1nCYRmNuFdiol3MSaLWB9ff9+Xl4FT7FkQi8fury1IsRkKLqO3 + 2PucJevsUkJmIOa1hHk8jTq9GBcfDFy8ep8Cp4GjAV5Q9A16xpvLLEU3zYxwZff/XSYl9z6S3olSXGvI + FMQoOkVxgvfGqYWoplZS0ZtroMDRwKXKPt2CpiBmhMo47Zlx33/Z9YmcnSuUs66P9WZDsSlLlHXSF9Fj + pldc/jMF3rPGdzRwmj3jFmSEFJxBtWfGQZfDSWnuPy+fniuSht5zalbFwQsIE75Ne1C9y3G5cEUNvG+N + /0YDfCNWAxcr7mvvpjkbG3t2wAvCeD7wbYhp8Dp9FYegB9c9t17Pn+Mck7tQtm6A/x84G2DPfMHEhkjN + /wc4O3NmKqQ1YgmizvEYzOI8YGVq50vv5WWgiD2b9MXkr8kQCOQQkgkPeBGQZ2DC48y/3hXbgOMaoAF9 + GH12pu7h51+4ZLfgeBjXfhpuuwj5UsqY+PLAbfPBJj58Cxg9xQ8Ajr+uuZUBpsCL6JRx0cxuwPE4LsfP + MSB7/gewyEBZy6qOBQAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem81.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACN0RVh0VGl0 + bGUAQ29udmVydDtSZXBlYXQ7QXJyb3c7RXhjaGFuZ2V2I2jSAAADLklEQVQ4T3WTeyzVYRjHf665JpVL + p1rE0FSHCnXIyZG5JJNWyy2lo8vhhCjqCCmXgxhCTijXSclIiYNIpGz9QWJZQ2NM/qD+6ay2b+/bnJO1 + 9W6fvZfneb7vb8/39zJ03HzmxqS0uDE3mg8yyc2uTBKlyZWG1K43uiD+Ibc1JNXWmu4JSlfruTTGAPgz + M4mNLsw32Ru6VCIoE1QJNFkn7qEz3k5KkNbk8yO8xEFs684yWI4rKQTi653ppBx4g80Slu4VRD3gNFyq + 5ExEVzn+jK7kYHKxHDNLLajquwhhmeOUf8rOAJKvphAgQzmswM4l/J5Dc5H0DNqHM/Fxtg6z39sxNF2N + kXkx+qfi0Pn5MjpGk3Ek1ZJWaskFlILS2ewICae7fuAaXo5mIa3uOILTd8MtxgSCYg6knwS4P3AIgiIb + 2IcYzmw7rB9C6tTlAions9kZec8DUdsrRFDq7nmn85vy7AI3uK8z0dx0OMkC8TV74BRmLLPw1stbY6Ju + TIsJih6oBWTseF/+OhChOTbYx9+YSM40CCoELS+ROcw8dV8a2WruI3vaQH2CLo3LBdQPJZjLvERm8Lpm + ju0eBlvJmeYy9CYtgjbH96xlZEkfLt59Df+kZhk505ULUNvojdoEPe9zt3ZFFHRIoyRvaFSHQC3T8U+o + SktvGEJZ5xhMD8SM0FxFEwmqNrxjBnxxU/bVigFZw/tZCAp6YGRqbe4dnuNzQlQjiZX0LuS9GMXxxEfY + 6BBWTGoULqgGJFb7C/K7vhRLx9E58R21HxYRW9qP0Cwposgni58M496rSZzKbIUZL3ZwrZU3/XFU5QIa + /NudePphAY/HllD47ity++dRPTiLtvFvKO+dQmxZH9wjK7DZUdi13vqoH60h/HWBF5ob4nvl0YywdBDi + 7jmIe+bgEVkHtl/mr22eSdMm3EttLLvTotVbnCxJ/ipaTAtX9kCdZbV/A/dU/h2f+EZZVO0IeBdqaJQ6 + Irftj7WNo0uMkV0EWa54TG4RtXSibmhZcfmOnODC3v38ChpdY8oTMZu5cQyLE8MY741kDO2FjOG/AisG + /Rr6CumNesvr/w4AzG/fQnRfIXokewAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem81.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACN0RVh0VGl0 + bGUAQ29udmVydDtSZXBlYXQ7QXJyb3c7RXhjaGFuZ2V2I2jSAAAJ7UlEQVRYR7WXCzSW2RrH3840U5pU + Z7qdmcY0XWa6jGoqlRpEcsmtRJmoTDVDKmk6w1Qql+TyEUVKjXvo4k4IiT4JkSIhQiRGZFSmy5xZ63+e + 5+Vz0jnrnDVrzXnW+nn3fvd+9/+57L0h/Ek26C3+uPlf1BUCCP9UXeFYio5wlPBLJpK0Bd9ELUJbOBKv + JfgQ3nFagiR2eS8XNPnzv3ic08ThmGUp+4NUp3KfGOQWpSEcOqMhuEaqCy4R6oIzE64mOIWp8TcDjUVf + /NbwB6gXIeOI33GPWYY7D+IRkLj2pXPYUhejTZ8Po/eiIzzv137uC/uD/4MDHOnz19VCz291/xWyt9PN + IoMPRamj+1UpHvdcRWapBK4RmvV7T6oY8FjfnEE9r+8JzL5TKtR9y3wTtIW251lC98tycqSmj2rxSfam + 2Dt98MLMu8QQl4ilJJ6Hmg4/ND29gIb2dISmb8Xe0yrJ2w4rTembKzry48mv6PGWecctFx49SyPShY5f + C/nVAFF7/yWTXcKX7qY6niOxMqKW2nAOXwqqae3BMDW0Pc9EeZubSGW7D5q7E1BYEwKPKKOXu48pO6vo + KwzntfrWHWhe55cLLc8uCi1PL3JXJjz4QLDqepdI9VyfWEPESu1RUBWEmkfJaHicia4XN0Ua2jNR1ZKE + h92puPFwXz/FREWbDxqeJCFO6giHQJU6G/f5XBbOmpgNotc8zmoKzd2p3OSXgynihbRzS4IuWlAUJ9H+ + XIqWp+mo7YigCI+gtMUVhU0/Ir/xe3ruQ+nDQ7j+YA+kDbsgre8lt24HUu9uwLmbhkivsUJ+rSd8z5th + 55GFCazRp9VrbtEa/BCjpk1iIzmr+3tOhQfqOqJQ1OSEpDtrEFduhOTKtUirWo+Mmm9wudYal+9ZI/ue + lUh6lSVSKs0Rf9sEMaX6CC1SR2hhL1E3ViBCagy7I0tguG1iMusQA0rB4u+SuL1v7EqUNwfjZosXkkgw + qlQTZ0qW4+zNFYi9vQoJ5aZIKjdDUsU6JFZ8TX0zkfjytaJYyPWlIsFEWJEWooqNsD90CfS3TWxUt/jQ + mHSGEAP2giztazxi9HCnNYxS64CzZXqILFmGGBJOuL0GQdl62PeTMqzcFbFu71Ss/n4STP8+BRsPTBc3 + 44VbpvipQA0/XVNDSAFHrQfPOHWsspv0Ss18vMcCzU8+Ih05QrYH+u0vS1YoyDsGq7bmVx9BfoMDokq0 + EFGsgXNlhjiepgNLp2kwtFVo1bdR8NT9VsFYZ5OCyoxFfx392fxRY7U3TtTY5bsIV+rscZrEwwq1cSJb + B+sdP8fitWMyZqiNnEMaIwKiM7WtvC+dV1Q1HkH9/gyI0X/vq7z51MVvaDN5iaJhRRpiHfeHKMPAVqFd + a/OENTSPbzdOH0fANeRF3iOG2/osRH79AYQW6GHn0S+x2Gxs42ydUWY0NnKdzaZPv/VMkTiFX3/lff4m + LF3jtvR9JzrAqRhiH7g4N6vcFRlVVgguXErR60ASrwGD7RNrvjIeP4PnEP2XyRuwE8O2ey3AiVQLaFj+ + 7dUsXXnJLFWjcfRefqNTjPnOgNzm6Kt1qGrvQcbtR/jOOyOPxrgUYhn4h5x94JLOa/fdKGojSqMqokuM + sMVVEZobPuZzO5RgIZ4rQ+YAt4fauCtBUWd45uSFcl9SnxcfarL75CK743koa+7CrbbnSKvpRHxFGzZ7 + ZXbSuOxSEhcY9kPAYjrHbrSJNBCUr4LoG0Ywc5gGGvuQ4HTxZE49OyPLhswJbvM7HpOV5715y80m2Pjl + oLD5GaLKfkZYSSsuVLTDwvUirytPiA7wj/d3+Sl3Zlc54KRUBcHXNBGYpYUNe7/giQsJXniYvrXnbEpf + hrVvDr+XpfDNTMjgNeVW7z5haHc8F9LGboQUP0IwU/AQpo4JnIF+B/gDuR2SBXlhWZsRWWQEx+BFWLlj + 8iNz+1mWNDby42lK4zY4x7nbn5K+ulLZii1embII3syCTJgzIDdLfe2kje5pdy8UNODSvScIut6C00Ut + 8EqphMGuM1Ka018C/njIloNzv9t6eAE2OM74h85mhYCJXyxRoPdjVtoFrtvimf4gPLsG9U9eoobY6JbO + DnxAyFLOJeL2+8Qo/e3+JuYuKfVBaXdx7UE3Iij1x/ObRCe+lWRC3dLPhub1b0J2YPDMBWNH6dtMjFuo + P06Z+mOVV+2ct+5gQsahM8W41fwL7j15AWlzN3IaurHOORUrrD1WyI/+cPyIMRPG6m3z1TTYHmBisifa + x+xgUvOOY1eQWNyEgsaniCxtw9G8JhwjXOLvQHNr+M8ffPzFeNJgx1lbNE4FRzBy5nzVT4x/CPfY7nv5 + VfrNh7jf9RJFLc9wsbYLidWdSK97gt2BebDxz4OlZxbWH87AJs9M/HBSCt/420i60Ywymp9BOz6I6n3k + ygOiEd6ZdVhhFw2l1S5cVr5PxPSziRkg5LWt/NZaOCc3hFy6i5rOHpTR0UmvfYK4ux2IZe50IJmcKGh+ + iurOF6jueIHKn3twq7UHxbTTL9d1IfZWOwLzm+F9uRFe2Q3wyWnEoaRq6O6MgtIaTxfS4VtwQPRch6HG + DudS9pyS4npdB2639eDS/S5cuPMYZyseI6a8HZF8jCidpwsfkcBD+OVyZETOA1FEQoKSyw3wJFGPrHp4 + ZVHU2Y2wPV0AtS2hv88xcLYnnZEE7xfWHOCAnNa2sDRbv2ycv/FQPDL+Uqrb1d7aHSUxmaAPCXJKWZQj + 9Mxi0fo+0d62F7V3BRdBd1cM5pr6VU5RsdYiDY7838TZuMMpGaG02tl8mXVIk22gFP55JEriLMTp5OhY + 8GhuI5wTKuGWWtM31gDnxLvYG1OGrcelMHFMxGLLU5i9SnJjuvYeW1p3NMGngzVEccWVPvQYaDIn3h8x + bupHSqaevjo7zrx2iCwRU+xJEbln1uPwpfuioNp3EfhqU0jbvDX+mEvMWe3bOnulpFJR3z1tus4B9wlz + TPkk8THlsy67RVlj0NX73cJ0PQk1B5o4SPBEvlJHfrpg3aK5q71zVjnE4mBcJQ5n1MMlrQ4el+pJPJTv + Af4HhK9p/qUzhuBIRxF8QfEZ54D6hfPquoVc4grxmbY7vXrL5psF8IMnc5r4VPBRGT11qd2meSZ+zRZ0 + +Tgl34Nreh0WbQxhB/iPC04tR8hiDH/HorI6D5KJitT+IjJ5uRsNvWVzjP2Eoqan3JRlgxfhxeWHj5v2 + 6WfL9hxbbHHitdXxfMw3P80OcOQ8Lpvfz78Ee0VzarsGMGmZK017yxQNfYSZBoxEmEGQyRbkqPiS+mDc + zJWqUzSdcr/8Oogd4HSLvwumUESTNZlDhKso8L/4I8ZOcDbETUqwMJ9ndkqW6v+7ybLB9eWomT9BXBD+ + CXfa6kejLEGJAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem85.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAkdEVYdFRpdGxlAFNlcnZlck1vZGU7U2VydmVyO1BD + O0NvbXB1dGVyO3LY4GcAAAGZSURBVDhPfZPZSkJRFEBzKqfsk3z0U4qgR41SynBIc8Sk1LKCCOqliKBM + b5qlRj5EjwZ9gGMGXg0l2O19LjbQ0QuLs7lnnXXug04AAOPwvMLAR44oERUHBSIjb3juZ8ANRLlz8uRE + AXjQHjoUkvECCs921nkmvMDza5PLqVABdzTjIpcXUIWSJRzHP75EgeRJHP8FpgK7RWi+9xitNq7IcGXv + 213wxu5IVnMDvniByVa/AKG9MgSJZBkCiD/5yALrW3mSNbyA2hu7hwbe1P0Y/KUnrY23LriiuZEBDdVJ + srjT4E08ICWGJ04UcU8ERyRLspYbcG3mWIBuE3t96WaGNNdxzx4WSNbxAlpH5IZJ9ZbIB79gNZgZGdDZ + QwKKXaihTISLRlhLGdlcb3XYavOnSdbzAvoVrP+WLRcmmD8ysbnWxHdNEZY3UiRPcwM2/zXKdFiiP/hk + VPEgRarIkueKZAM3YPWlvm+qYqDKZmllc6MDi+5LkrlfoJ4zH9wuWI9hHLPm/Ty63N8B/Y01iAGZGQHt + kSOXzsHEF0eqmAZmOcO3AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem86.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAkdEVYdFRpdGxlAFNlcnZlck1vZGU7U2VydmVyO1BD + O0NvbXB1dGVyO3LY4GcAAAGZSURBVDhPfZPZSkJRFEBzKqfsk3z0U4qgR41SynBIc8Sk1LKCCOqliKBM + b5qlRj5EjwZ9gGMGXg0l2O19LjbQ0QuLs7lnnXXug04AAOPwvMLAR44oERUHBSIjb3juZ8ANRLlz8uRE + AXjQHjoUkvECCs921nkmvMDza5PLqVABdzTjIpcXUIWSJRzHP75EgeRJHP8FpgK7RWi+9xitNq7IcGXv + 213wxu5IVnMDvniByVa/AKG9MgSJZBkCiD/5yALrW3mSNbyA2hu7hwbe1P0Y/KUnrY23LriiuZEBDdVJ + srjT4E08ICWGJ04UcU8ERyRLspYbcG3mWIBuE3t96WaGNNdxzx4WSNbxAlpH5IZJ9ZbIB79gNZgZGdDZ + QwKKXaihTISLRlhLGdlcb3XYavOnSdbzAvoVrP+WLRcmmD8ysbnWxHdNEZY3UiRPcwM2/zXKdFiiP/hk + VPEgRarIkueKZAM3YPWlvm+qYqDKZmllc6MDi+5LkrlfoJ4zH9wuWI9hHLPm/Ty63N8B/Y01iAGZGQHt + kSOXzsHEF0eqmAZmOcO3AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem86.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAkdEVYdFRpdGxlAFNlcnZlck1vZGU7U2VydmVyO1BD + O0NvbXB1dGVyO3LY4GcAAAVXSURBVFhHrZdZUxRnGIUlccVdzPIPkov8mvyD3OTWm1R5FzVgjAkIBmWR + nRFkSzSWFYSYoIFBWUwKk1Qq5QgMy7DMDLPP9MyAb855uxsHRJqxmKqn3p6m5zvnO+/3dTd7RESxP3cH + PCwFFu+CfRb784S/2QveAQUtd56hmB9bU3U3G8CHwvzRvp6+f76CIXlb6jpHizEOzagJoB8nAype3fKo + 2P10WnyBhLzwRV/DM78VkXXm8bv+wf+kpPxuCcbbYGI7A7xgb6745BbibzZgY5qY22iCLdmRgf2N3aM4 + tXuf+o4RChwETGFbA7zgQFPXmCRTWQmGUxLIJbQRP6t1nsf+UFKWV5JmtY6jibTcaH9MgUPW+I4GDjZ0 + jUp29aUkjTVJplclboD0mtYEzsUVnEuSrMRY8Z2VRHEuqnVVUvhdbZsaKATcVY4GDjGyTNYUau0Zk9bu + cWnpHnuNZrSq2a4wTZq6R6SpC3SOSCSRkRTGqHYNU+Aw2JmBOhgw1MCqtP/0p84ilXmp1UgjGQXpMCEj + q6kwqYQmRLJy8/a4ROIZ/VuVy52XgcK6W0/EyKxpnO13/pBYyooXNaowYmDVCMFsKWjj+mFcwvG0mqlq + GaLAEeBogBccZs8MzDCaWJW2208tMQysvUVNoFLQIhzPAlM4FDNp7RmXlVgaayQj15oH8zNQg54x7ggG + diFK148AM2JtJTi2aYGQVq4TrJdmwnWBnRSMptV8ZePvFDhqje9o4EhVq1t7ygg5eAJRkxjBgMSOX49z + YDqkqXMUW9TQpK42PMrPwHX0jDsgHMvqjFY02jQizWisKxEemzWwCb9FIxaynwbw24r6hxQ4BvhwcjRw + tBI9i2PxMMImxLkuhu+vRHkTMquf4NiPm5JNQ8cT3IxSujbK6wYocBzs0AB6FjMyEowZ2NOj0og9rWBW + uccUaQSsDR2Ppf7WRhZXUkjOkLLa3/IycIw9i6F37CGF2FOu9BBqCCmEsDYUJmLB42DUQEokLXVtw7IQ + SEoIaZXW/EqBE8DRAC84zp5xezFCzmwJkRLOaMliAff5BdYgKvBBTPGzJqT2plu/ByKGfFv1gAInrfGd + DVxBz7inl2Cgvn04R9BkXQzwuW8Slzk/sGqNawg1oQ+ry9d/ycvAibLaAb2ZcMY32twmmBHhzEyGIOKW + GtRqiFGwunXwFS2DaoQL8vI1NXAK8J3A0cBJ9kwNYIbcx7rHWbfAvBumlbCCOyMr1sjsUhwpJuVSZT8F + isDODHxX/UAXFHvpQ4zzgLOZZ8TWsV1nCYRmNuFdiol3MSaLWB9ff9+Xl4FT7FkQi8fury1IsRkKLqO3 + 2PucJevsUkJmIOa1hHk8jTq9GBcfDFy8ep8Cp4GjAV5Q9A16xpvLLEU3zYxwZff/XSYl9z6S3olSXGvI + FMQoOkVxgvfGqYWoplZS0ZtroMDRwKXKPt2CpiBmhMo47Zlx33/Z9YmcnSuUs66P9WZDsSlLlHXSF9Fj + pldc/jMF3rPGdzRwmj3jFmSEFJxBtWfGQZfDSWnuPy+fniuSht5zalbFwQsIE75Ne1C9y3G5cEUNvG+N + /0YDfCNWAxcr7mvvpjkbG3t2wAvCeD7wbYhp8Dp9FYegB9c9t17Pn+Mck7tQtm6A/x84G2DPfMHEhkjN + /wc4O3NmKqQ1YgmizvEYzOI8YGVq50vv5WWgiD2b9MXkr8kQCOQQkgkPeBGQZ2DC48y/3hXbgOMaoAF9 + GH12pu7h51+4ZLfgeBjXfhpuuwj5UsqY+PLAbfPBJj58Cxg9xQ8Ajr+uuZUBpsCL6JRx0cxuwPE4LsfP + MSB7/gewyEBZy6qOBQAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem87.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAUdEVYdFRpdGxlAFdvcmRXcmFwO0dyaWQ73v25igAA + AuRJREFUOE9tk1lME1EUhocuUBGK2JZFyyJlaRFahEKJELRYKEsVFSRsgViLC9SyRjCEQguKhEUI4AJt + KUHQBDUooBCNJiYk6oNLiWh8MSxG4dWFx+M92Mf5ky/n3nPP/09yZ4YK0rRtQ8SQ6+1dipp7EF89CeGF + vcPYC8hspYQZLRQA0EIFZplJQDsGsOIqxz7FVoxB3MU7EFlyY4302EK1kRKmG2nNCBVA0olcwk+aQqU6 + C4iL+palutvrUdphCFDVyfFsr6qJ1oxQwrRmDGBElw1US0oGICiz5XpEfo9NqrNCsMaE6UwMcVaWszII + /yVMa8LCjtFZFg6cs0NErilLUtBZGqOzQUhOxyKeEVjpjc9/qC49+3mkbm76kOGhlusbhn0Mplz4Mo23 + rNy6hU+VEaRnCNoRCMvr3uKKDnuTGbfU2gV4tfoXbr1cBV3fa0g6/6DDfXeQKwYwQo+3nYosGYLAjFbw + Ta4l1QTi4kEIz+8HvyR9PpnhJJyehGMNc2CccMD4200o61oEedlYOQawxYV9o6F5veCfUj9D9h4ET1FO + 5xtx4RAIUxtHMUCWN6iOOtGTFVtke3x53AE9T75BbOkEzlNsn0TDmo/CAPy48lqyx4ti8eJ0ZoFCD4L4 + ynWyd3P2XSWaTo26fhamvvyBqOLxDdLbvlEc4BBwCC8GwTX2dhDclTrrTawR2deOqmtnYXTpN0hybRu0 + 7xZxiuG1T8UPVnXPZlbfhxCVMVecOzxXY/8I9Xc/Q0hm/xytGUEzb39BYFhW//urM18h3TAFSsM0VNk+ + QPv8CiirpmFPiukCrRkhYntJ9C+uPFqGyRWAme8AVscvqBpzQHLFFPgdNPYy3bjutGaEiMnxU4p40VVL + FfZ3IMqxgH9yx6ZPovmpQN5QyWB77CQzLrRmxCkmmyvx9QzTzgdlj2BTQMBL3f4K+QryE9KZEZSH6CwW + BsOVt4svb7aQNYevaKN4CYiZYKb+AV23obl84AYMAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem87.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAUdEVYdFRpdGxlAFdvcmRXcmFwO0dyaWQ73v25igAA + CBFJREFUWEelVglQVFcWbRTZFYPQAgYNEKSRLQiigOIMjBIdwCWgKIsChtVWlrhMEAMk7EsrmzDIIkai + DiUiIlFUUOIwGBOGOI4iElOlCIMYEEVGZerOva/7Q6e1rVieqtO/6y33nHvf8j+PMGtpzCtEKCAnI5WQ + KhLSf0Wkgv6SaN4Eo7BJDAB4KzL8Rtx5QtzSN8PVaXc1OO2qBsed1WATUgIGLtFrsU9iIoqnvziKp4fk + 8DqRN5GBRMWMZkSQASXbiIM5jjuOg0PsMXD87BjYbz8ChivjSrFPGTmJhDlyeJ3Im8jACesTsaQIKr3q + ophv/m0XWQHWwUVj8yPKxxbFHAXTT9LuY5+6ZIyCntN2HpHD60TeRAZOWCJO2SsaLheakaDlpgIw8Uy6 + au6/76r99iow98uDmQs2OeCYKTRWF8V1Hd/VwG830ySkslVgXpJ9VBWYemfCLGdhlrH7HpGd8AjugzLc + B7Ff4hjalJNIXNdxG817a4wbkFlLKq26bWRFm53wazByT4QZVus89R2CPOdHVALRyD3hJo7RQLLNqOsw + boCqJ8034hUDCJo0hW+z6gO7rV+PWQcVw5zlcaOTVTT5iqrv8S02FY7ahFZgVbJBa567FY6lY6kw00FI + c6lyZJ5MEek/tck1M2FgYiPRBBWBV3KYLWZq5pOD5Y+6gG1aRJO1qResPy2HeX4FoO8UuQvbVCVzSEBR + WHB5TJjXfD8y98K50Oxvk4JSTzpjO+0VNiZ8fxMvbN9F/CvGuAGpjUSuNayDi8/bhB2Cj0Iq0ER6Mrbp + E029U1KsgkrBIvAgGLjuImPTJHPIgNLWvGboGHgGjZ39UNbUBfGVbQNbMhqyN8ZVmmE/W67QHJomxoQB + 8SZi5Z8620bvo5DyUeuQcrDeUsZoFVwKlkEHkSVgGVgCFptLwMgjeVRFe+4snEPLQCaUw3OboHt0bJyt + 94eg6OxNCM5oOL1xT9ViHMNMIBlkDVCZVA0/3unHiVqRKGZriYIkar4JGVAM8/yLwcRLBDp2gcE4Rw1J + gVXCRBeh69kY3B4Zg86Rl+zZhc+K5i7YnHrm9JroInPJWGZi3MBM8S6mLKbiuh+mLD9cmwn6zp8Bf5EQ + +Au3Muov3YHtWWDmWwQCH9wHzjG1OEcTyd4XbsLDEJhSB6lHr0L9vx7AzScv4cbwC7j19AXk198Av8Qa + EY5jtyhSYdwAgq3hFDUtvkVA8SMLzPQDty9A2yYgHdtp/XWQfKSBgcuObwQbCtFAIZ6QvUOTlafpYjsF + VTSy89BcEpDl6hr61+zNX9X2Vl7uguuPX8BPQ8/h0t1fIba45dHqmFJXHMsuMWkDrPzvLwlfbY7lFfjk + w/t/3A0acxbbYzuddxIgTuPP9w+c650HpuvywdA9FbQsvNZgOy0DVZBIwdVctxR8itXore3ogfZfn0PH + 4HPIP3MD1scdT8F+VgXOAGVPEzWMVycXmPkeAONVGYAnoxPbZiCpvGSQqKyiZTzbyCNtyMQrF4zX5ODS + hB/A9qlIisFKi6R1Vl8hLMtJ+9s1uDbwX/j+4SjU/NgDPntr6BiQ4VcMqOssCL/Jt8f1to+EGTZB+dhG + 2VMfjeECa2rP33JSZ0Ek6CyIAB3bMLoV6ThS36TbT17iQ2zWJTDLLVLUCG39o3Cl9xk03x1EA7UPsI/F + lTZAEyhTCkRZEykrtlYoxiMipMdpSzgdSRcSdxw5s0q6xjZ6Pl/Uwd9J/N5TaH0wAuv31o1hH7s/ZDch + BacsSJQoHYyD7Dh6IZG4xrq46mx8cjucqLIsOGvFNrycLqF44y9PoOb6Q/CKq6EKsIpJGyBwYtKUB+oj + g8qa/NlaXruPVW5IOE3RqLRcAtM8ow/lZp3ogHN3n8C3Pw+DqKETPGKrmrCP7RlmgH5+Dzn4JtXTgzJU + xhLzvT8/Xld5qZtKS4No6ciE5vKwgsiw7HN91dd64NTtIajqeAQ7D7bCn0KKMrGffdCwuLJC8igBZc7K + O9vcWX99fHXL0dZf4Luep+AdXwvTZxqaLNmY6PnnbWV5oZln+8qb70B912M43D4AaWfugM+eE4MLvRJW + 4HxaKvE9ICskjxJQ2VXMl2740GfvifYazO5s9zATiRBdgHXxpyA85zykV7cDZV5/+zEUt/VD7uUeCN/X + BE6+okKcz52YtzZA2SvZuQtN/RJPdZ36Zy/UdQ7BkY4BOHlrEFp7RuBa3zO4cm8EzqGpoz89gn0tvbD/ + Ug+E7W+GhRtyGgV/CLXDGOxLiuKxuLJC8iiZpKrjmNpS2HALDv84ACVX+6H0+34o/+Eh+1/8j/9A/pU+ + 2H+5F0TNPZBUcwv8k8+A7SeZjQKXbW44f/xjFimOKyskjwi28aYarzEzXC6685eq65B+sQeSG+9BAYoW + fCdmWkM37Dz0AwSkNIBLaOmgxcqEA3Ps/elKJ3FWeiQDiysrJI8I7uipqc1aKjBwyeyIPdQO6efvQz4K + m61IBqtVGf+z9EjrM1+Z2CJY9nmOoWOIB45/D0l3xSv3CosrKySPEnAm1FW0rY31nFPaIg+0QS6uNRnA + 9rlIejvSJxxtNhKmO4GtefPPwzzBx/SBJQaLKyskj1IgE1RK9SkaBgZ8xy/PB+a0cAbo1U2l5m5SJkxs + 6h7mXUQK3N7RAH8x3SPjlVCbrDxdX3thwnGJAe7tyUSJlLHA7StGUwk5sLiyQvLIgQzImkBqmS6LpzM+ + /vakTDlRafF3NiADzgRlTeebSk9tvwsAwPs/f7/Fl2xBAR0AAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem91.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAEFjY291bnRpbmc7Soc56AAAAs9J + REFUOE910u1LU2EYBvBDagpFUJkmUv9BIVFBKEntg1JSKRRRgUWMtMQlS5jQi1amlKGWqWnOab5sai7U + NDLQFCduzqmb0+a0WW56zjbX5svUmVfnnJkpqwd+3B/OfV/PDc8hSsSqdmHtIP4aQEnNZm9q+lFUpWwn + CMILALERwTQsuVY8LC6v4NfqKlsZRdV9dDfh4xFQLFZhiW5IqtODJxlFgngY8ZVa3CjXgisawnXhIIyW + ORRU9DIBWz0CCit74Vxawb0P31ClMqNCacZbJYVyBYUyBQmeWIcf1CzyynqYAF+PgFflPVhYdCG5Xg9+ + 3SiSanRIrB5BQuUwblZoEUdvMkHakVPS9e+AXKEM804XbHOLbrNuMxuMT9mR9bqDCfDzCHhe1InZhWXw + H0qh0lNs7dOR63XsTCQMpAONrUNMwDaa9xov2hYiM78N9vklKL+SUI6QUKyRj0ytI2fm0Fpfg0ZBWGdL + Siiako9Byjv8RcQ9GEM8zv2Mn/SazI09WpO7Drlr91o1WRxoST0FUt1Mb+0+kwopxNwDJHE/qwVWxyJk + GhOri9anm4buuxWGKRvGTTYYjGa8Ob8fdm0BVqwdGBFxMd2ZjqKYfSBSMhphsTvZmzoGJtk6ZrShWVKF + 9rx4NAvC2JUlcSHQSpPgNLVCU3gFxta7yD8bDIKfJgVlW4B63MIapBkpOz6mnQalbgBcNqwuW2GUS/CO + dxT2sfdQZUfD0MTHy6ggENw7ZW3XeCJc5ZUiNlHIqm2QozA6GHZ1LlzkJ2jyLsDY4h6gNFVQZERAXxeP + nIi9zMsQvjTmebZv4J8XFQxrdyqcegn6n3AwIY5lByblxZA9CIcs+xyecgLNm36KP+jjlx0ZRGlKL8Gh + eAGFIATy9HBmwJVxIgDPOAF4dHyP6vaRXZf/F+AtCPW/mHkyQJnFCVwfuHVoZyz9bTdtB43emvD5DRlF + wtjAtpm0AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem91.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAEFjY291bnRpbmc7Soc56AAACUVJ + REFUWEeVl3lQlPcZx02baLwSNbWZ9I9e0XZqahKjSewRJ2Zap00y6YztxEkbz5p6sgiKFyIoIuKNGA/k + lEPAheW+iSAi53Ltsiywy7ku7L2wnGry7fP8WJAEY5LfzGfefZ/d932+v+d6353iXE8RTyfnKm+l5jci + NW8MFVKYXBWSx8hpgMxJUjajRFKWEomENEsBaSaRocDNjHokMOn1iE+rQxwRLZMXkp9nnP6mAOCDWGyY + Gk8/Hrr/EEMjowwywxOO4zzAgOChkwfoH2Po/jiOb3A1tow9TiN+xE4nCmDDtBupdcKZfWBklP4R2PqH + idGj1TEygWFYmD5myHkchplsZjo39w7BROcmPhKOwfu4HFXKHp91+pssICa5lgQ8EM72xyiwP7Yee6OJ + qDp4EHuuM7VwjxzFLaIGbuE12BVejV1h1XANrYYkpBo7iR3XiGA5tgdXCQG9tKGLkSXscbrT3yQBz0Yl + VYtw8u52R9ZBYR5GPWNihlDnpNboxDCEGqK6ZwhywSCqmO5BVDr53+flMNgHhYDA8OInC4hIlFMe74tQ + Smg3Gc12XK/oRqzcAJnCDFm9CdlNNmSprYJMIqPRivRGC9JUFsTXGBBXbUBYqR5Xi3VIVFmxIbAMPbZB + 2GlT50Jus8cZTn+TBYQlVIpiYQHbrlYhTmHB8Swt/DJbCS2OZWjhSxxN14ySpsERQQt8UlvgzaQwzThM + RNaY8J/Td9FtHYCNBJy6WvhEAdND4iqEAC4eCeVXQDmWhNXAhQmtwU5iBxNCcJ6Jbdfk2Eb53joR2gCz + 5UoV9JZ+kdaAywVPFnA1thx9VK1GyhmnYrSduLXG2utRm01sLwFdx/D13+QeCbD0DuP4xTz2ONPpb7IA + bhMuFhZQUKpFRmGTIL9EK/LItvQvmgR5d7QitPl3yVagRhqRW6yh3Q5AHxaIthOeaPP3RHvQSejM/aIt + fQNzxwT8mJ1+U8AMbhPufXYWIZXT96Pr8g05tN29CL/5yHYpuhIasoUmVDktwIXrFWjR2VC3eQ3sSRGw + JYbj1gd/RXOXDSb7EI6cy36ygMCwYioWFjCAcBJgH6B6IOWXY8iZ3o4wcmbjCJEtKKoCzTo7QuLJRvk1 + kIPAyHKouqyQr/8nDIE+6Ni9Efmr3kNDuwUG2pTXqUz2OIsQAiYuIYDbhIuFQ+t/MRd7/VLgcSxZKG/S + WXE8KBd7fJOx+6gM3mezoCZnfhdy4E7n7j5J8DqdCVWnBZUunyFv1Urk/uVd5Kz5GIpWE3ronp4n0ljA + bOKxAmaeDi4ULchVq9H1orLZiHKVHpXqbtqtTYS3QtWN0gY9KhrJRqFVd9rEeUm9DqVKPRpJQOs9O1Rt + JjR1GKHuMKCz2wqzzYHrUvEseJ54mp1OXEIAtwnP8XtUNHl3NUilwmKyqbh0JrKVaJCSrxZkFbWg0+RA + 7p0WJOep6UmpRsatZhht/ejuMUBTHAFVsifqwz9BbegaKJMOoCDmDD5866Vfkq+phHgiji0OyUx/ahOu + Vh3dOCSucrSyaAVGlIlwX7vxyHYurAyqdis94R7ZTl8rgc5ohyJmM/SlobC35OC+RYH7ZjmsqpvoLDyD + 2wEr1ORrfBaMLRYwi9vESMXURQKukQBORze1FTvjQgomAWaRogGcDSmFss2CKzEVNLg4agM4FXwHHXoL + iv3/iAf9HcCXg05p9HHEgRErta/XsrE6+FoahAAfKjaeAZ1GB46ey4KrtxSuh6XwPJkunB05mwmJl1Rw + ICANdVozfM5kwOXQTew8lEBFmwytzoTCY8vR23AJGNJioDUW7cmuUFxajXt5B5Bz8I3H1oEQcJiquMfK + AvpEeLmwbld34bZCLwQwRXU6fEG2olqdOOf2VLWZRTE2tpuh6epBgffbsNWdx1eDzejXRKNVuhX1Qf+A + LscDWR5LWMAcYrIAz4B06KldOgx9NNVa6LVLJeDiauvpQw7bslVIJNJoGnK9WKw2tJXEQCn1Qun51Sjy + /xC3Dr0NVcwmjJir0NcYipa4Tag9+z46M9yQ7vbatwqYvd8/BXrqgHZydiW63Jk9Kq7guxRuC02/R7YA + yrfe7IA6QYKu2yEwK1MxbCjHkL4QxqpwNMt8UHTk77AqrkAduRbyk6vQkeqCFJfFLGAuwe+G40sI4KHD + 7dZGI5ad8fTiejgZXIJqmgmfR5WRjSJEthNXbqPLYEf2wZV42KcFHg44pXHB9WHE0ojkjQthkF9AQ/DH + qDr+HlqTtkG2/RUWMI8YF8D9KAS4H00SHdDa3QcvKrwdB+OxnfCgicgCPANSsf1AnGCPr4wq3ioE2GpP + AwNKOFqi0Jq4BbWBH6Aryw2yDQuhLzuFuosfoeLIn6G9uRnSz37HAn5CTBbg6p0ohotW34tajQkF8nbk + lLchv7ITNS1G1GiMyJN3IpNs2eWtaKeWYwGWaj985aiBvTEEmhsbUH2awp0mQRIJ6CjypfO/ocxrOZpj + NyB+429ZwHxikoBZEmqlToNDFGEHH6kWuPjaehxUFw7n51G0NG67aeiwAFO5D760l8JaG4RGmnqVx99F + u2wbktYvRGv+IVT6rcTdfUvRdP1T3Fj7mzEBPA3HF0+l6etdw/I3uV/HJrdIbNzFRGCDKxOO9ZJR1rmE + CdbuDEWcrFQIMJZ44YGxAMaKACgvfYRynz9Bm/BfJK5bgOb0vSg7/AcU734VqrA1iP73y5MiwIujwG3B + b6w8pZ5zwgPj2+BC+hkL0Bd6YLhLhp5ib9RQ+O8eXIaW2HVCQKNMgjv7l6LIdRGUwasRuebXLOAF4mtt + yItFcCQ4Hfzld8H/cOawgHt5u6gAI6DL34dK33dQvOc1qCM+gXTtAigStqLQbTHSN74M6Y6l8Hxrnpyu + 483xPdjnpMXG7wPfYDYL6MzcTp1wDu3pEpTS7oski9AQ8i9IP10A3xUvwu+dn+Lw8heU7kvmBr0xf9rP + 6bqxf0dPideiH4pz8Q1mhK59VZWxfwWUNPm0iRtR7PYKUtb/CvFblmDv68/X0G9+QbxIcMo4vRw5jjJv + YvS97IfiXHyDZ95fNP+l/Uvnnvd6c16995vz4LVsLva9Pkch+f1zFxbPm8rPfn4F44rnomPHozsfW49z + 8F1MWHwzvjk/3zmvPGIZLlJ2zLvlVI05feRYrClT/g9qpJo0nePWGwAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem93.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABV0RVh0VGl0 + bGUAR2F1Z2U7Q2lyY3VsYXI72dS81AAAAqFJREFUOE+lk1tIk2Ecxj+1c1FddVFBXXQTZDdWN91FoRWZ + RERCHtqspZI6tXS63NQCY2lzmIFUkqBh6pZlW80N23JlTAuNWGpaasudDzp1U+zp/3165y6KXvjxvIf/ + 8/w/eN+PAfBfhBsRROQyUcuwc3Z/5SivNTHl97rZKVsQVVypPV1yt6tOojCYpYq3oRL5m15xlb6uoEKd + QOer2LobciMjlhtYD8OU1SyZBQWPtpfIu9prG/vwedABrz+IxcXfnA7QWtFgRqGs83nq1ZodVB8pknWx + Pm5EZEme7pUqjHZt9yhcUwvQWKZxz+RFhd5N6oFuMAB/YB6vDN8guq2zJ2VU72J9nHv/wbh1Ipnuk+nj + BIYcQc50U+tEuc7FoTB6YP4eQLvRgtgEAQwfxpBT2tFB1jVcSLZEybvf2AtXYAG3Op2QqB2o7/Hg6+Qs + fNMh2L1BaEwWHD3Bh7q+CdO+AKofvgc/t4FHAVGMsOyl1jxghbLfB9ELGx68c9PnhuAnM6u9/UM4cpIH + 9RMV7AYj7MpWmPrGcaWoVUcBaxlhqcbl9MyiVGNDvuoXhm3UmYyy6seIPhCP6Jg4vNb3wOPwYKw4Bz8y + UzAxOYX0omcOCljPZEnVmJmbR57SiuwWK1z+ELzUPebwGcTGC7B7zyF4p4LweGcwcu44Ri6cgss3i8sF + qnkK2MhkiNvdNlcAhSor0psmYLEG4CGDWFqJbTv3kd6Bm9aOL4MYPnsMo5fOY/SnDxfzWpxcAD+3WW8y + j1OXObjpzt3+lepi1RekzjQnOrtHkJjZwD6EDUxiel1G2nUV+NeUSMtvA5/g5bUhlSW3FSlEMqtCUmEz + knOakUTEJ1UJKGA1wd3nJmJzGLaEYSvBni29g3B/2L8QdvPvAfMHJRxcLgixX+gAAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem93.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABV0RVh0VGl0 + bGUAR2F1Z2U7Q2lyY3VsYXI72dS81AAABzdJREFUWEfFlmlQVFcahlscY5zUlGabqZqaH1Pl1FT5JzVL + 1VSlrDGOJhPjxOgkYiJolMimIKgobgEUVJCtQZZuaBahFUUhRPbFlrA1NPuOrd00dAPdzb7v5J3v3O7b + YBWz/SG36uH0Pfdynvd859zbLQDwk7Jq51qyaudasmrnWrJq51ry/xzriPXEz4jXiI0rYOcbCHad3fc/ + HZYA0idNAun3jYJkRkajICmjwcR3jeyyFbHB/XLYr4VxhfYx9+U5koeKprhHtfqEx3WIS63Wxz6obIqW + lucERec62J/2+w3dzwJZSVJrBLEPqjliCPEDhUCcohCI7lexcZcDMOnKspgvsJls8ApIfi/mfkWa9PsG + yORqqLuHMDA8hYmpOboNXMvOVdRfVP4SiWm1CE/84TsPL9Ef6P9ZkHX8mDyie5VsfN4jENxNb3jlBjqs + DhxyeisquSRGmtEw36I0YHFxCT/SxQVqp2cXMTG9QPIFjE3OYXySPk/PY2pmATOzC2js0CM+tXo+OKZI + 8uFem3dovPUrx49KljMH7xIIEtPrX5G7XgjZGpNS1SqrVGN2bgE/knlmbhGN3WN4XK2HsLALN7M64Zmq + xI1MNULzu5Ba1YcGzShGJuYwaia/REnVKG076uj9exrXEiIiqYJ5lgPQWlrkTu63fktyTV1rL3UB8wtL + aCZxcK4GftmdCJVpEVvRh8QqA+7VGJFArai8DyFFWnhnqOGfpUZd5yiGx+e4MJUNWoTFl3R9ddxzK43P + hQhPLGeu5QC0oVizbvvOfVuipWWVtS09nHx6bgmpCj28MlSIKu1FUrURdxUEtYnUJlaZSOAwIKHSiPDi + HmTWGzE0OkshZjE0NoeyGg2CxEWK9/60423yWAnjy5hvOYDkYTVrNgolTyWFZS8tctGzbtzK60JcJQ3O + BEQ8g87j5QbEyfWQMCpMxBKV6lHaF/OQSLPx0T/dMDjGQsziSVE7fIVPEsizKSSulPmWA9Cx3vOaZEdi + Wt0iW/N52mgp8j7cytEgxjwwQ0ylv1Oso3LrEFighT+FC6D1DyqkMst0KH9plidnYfdnLjh/6SYGqRIs + RG//JCKSypcczwTvYj4mXRngdWGcLL++rZfbcHXqEUvZRWV9iCbCSXy7oBuiH3pQS2usG5ji1lnXP41q + 1QjKnw9jlOSxdzPxwV4nOLtehlKthTY3G7raegoyg+KqTlwLzSwi38+ZlA9gdcLVb5s4pWqJPWJst/uk + v6DNpkNkaR8iS/oQ+lQH/9wu5DYOYIAGYms7bC7tSkQJGfjrHns4u1yEUqWFsaIMmiAfNHt7YmBkFobB + KQTHFC99+Omx3zEvH2CDrzD9UkGpknvOqzoG4ZTQiqCnWgifsXJr4UuPmqxtkJOYNpYJfn1ZGxWfju0f + 2cHxlCcnN5QWoyvkOjQBXqizs0anXIF+CvEopwluVyRu5H2ND7ApUFxQoFT3c4+cKE8FV2kHLqap4Jvd + RY+eBpFF3RY5P/NB2t28PFKShvd3fw2HkxfQruxCT4UcKt8LUPmcQ4eHA5qdbNAcGQHjyAzk9Vpc9k8r + JO8bfIA3gmNlqqGRKUzSm+zs3Sa43+/A+ccv4PHoBZwTWyFr7udkPC86DXC/GEwzPo7Pbc7hLzttYe98 + Hm0kH6BN1/WsGE1Oh9HufgLtbnZodraF4uQ36B+egVIzCO/grE7ybuYD/CJEUjLBdj/bwY6xDXB/8Bzn + Hipx9uFzHBM3QNU7zj3XbLYMBzc/HDp2BS4eYfj04Bn8bc8xk5xmyOhV61Bz5DO0uXyN1lNH0UIVqLQ9 + ACMF0BrH4ROaO0neN/kAmykAfQb35joSUcsFcE/p4LChc+PQjOlxMrN991EcP3kLH3xyEvsOeWDbHz/m + xP1mjAPjUFjvQYuzDVodD6PF4StU7N/NBWD4CPOY+W1LgNviZxMswBCt8ZE7tXBNbsPpe+04LW2HbUQd + DPRtx3Y/H8D6yBns+ocz/r7fDX/ebo29B04sywlD/ziqDn6MJvsv0XTiEBrtvqAAu0g+DcPQNK4GZbEK + WAJsCRQXMz8X4HBoNRzjW+CS1IZTxNGoeuiHWIBZU4mpzSsqx/6DTti6bSf2f+GInIJSbn0ZnIQCKKwp + AIkb7T5Hne0+lHyyg5Pr6bpXUA4zv8MHeDNAJOMCjFCAlaU2SVlLgxN8mXuMY6hpaIesRIGa+nb0GMYs + 5WXLxVomMxIGOjeYZ64fJKi9EsgFeJcPsPlGRCG3BONT88tyNltuxibpK/AyCyQg+JZJ9UzMpKtw8WbG + BHnf4gNsdPGMPnvjTiH8eMIL4UtcDy/A9bACXAvLxzVhPu3ePMLUeoeYCc7Ft8E5Jqi03wZl4yrN8Gpg + Nq7czsZlRkCWmUxcImyd/M+QdxMfgP30ep3YQrCvS/YL5t/x7n/hl/+BX5lhjk2E6VXM/vyUrNq5lqza + uZas2rmWrNq5dkDwL1wF0nbCz3SVAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem96.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAA90RVh0VGl0 + bGUATm90ZTtUZXh00fiaTQAAArRJREFUOE+lk/lLFHEYxhWP0jW1svobgqgkf5HI1S7v1dxVO+hgIyIt + S1fJK20jTU3NLDUFS8rA1MwI8th1XXU81iuzBCmMwHLJ1JVSd3UHnt7vuiPWrw18eN53Zp4PwzBjA+C/ + YIctYUfYEw6M3UExotCM5uzgTNVMyO2eZf9M7Y8DCa+C6JqjFXavrSCw6y+TagcrZBgql2GwXIrc/Dyc + LepCdNEInvZNoZKbhFjRAF1JOPpLI8DdD+uknoMgcGQlXl8PfqqWqEGU8jUq+mYhzR/Ec90U0hrG4XXp + BSbUN7AyUYq+B2Gs6SQINgyQlZ+qw1JrIBaJwMRqlHRP43TlBPzS1PBOeIOdsixwuV4wDV9Db7GENZ0F + wUbdw3CYv5OgLQyLagnyC9MRcbMRZ6omIHs0jr3yMpw4Hgn1LS8s9MejuzCENUWCwKm3OAxm9gRamQWD + JgqxV6/AMzIDuyRJkEZG41ncHnAF+zHfE4euu0GsuUkQOPfcCyVBPYzcKSwRLOfU0egqEKMuaR9qFZ5o + UnrjY1UADL3x0OYEsqarIBBxBcGrAt15Qr7Gr65z0DefxKfaYxirluBLgwwz3QnQZPmzppsgcOnMC4JZ + 3wDj0GWYCCFNQ7FY7I/BPHcRMx0XMK2RY06XSu/iMGu6CwJXbU4ACRphGk3E8qgCpg+JNFPSzjC+V8D4 + LgELw/EwjmVBrbQINgsCt/aso+B/tmDl8x0Ly5bMtu4ss+nc6m7+WgpVxkHW3CII3DXKI+ANHMzfnlh5 + vC6t8yQlwetr0ZLux5oeawJV5iHwv0dI0gF+njBowc+1U2qINprVhIpoBT+rwkCF/C+B6GWSD9eS7msx + N6cRqb6EGM0plCliNCWL8TbZB03XV6mJ8+6h3tp3wP5EF2Ir4UFsW8f2f9hhTVfCHoDNH86SXiJtqJBq + AAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem96.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAA90RVh0VGl0 + bGUATm90ZTtUZXh00fiaTQAAB55JREFUWEetlnlUVdcVxh8mMUkztatT2rT/tGu1WbVtVqpxAAfUCE7I + rKEuY0RIYgGNRIZKrShFLIIIAg5IwoqYBURRHqKgTDLI5EOCs0BUZHqAY0B4Dx5f9z73XrgXIckffWv9 + 3j77O+fc+51zzzn36uo+W/4UF5lkxl3LITeCo7uuNslNZ2jvGYZ+VsQEGav5/mm6mn0uMs66mkRnXXWi + k646wUlXxcQ76gDoxA0t94p/EBu/aNBlfN2lS6/r4hs+Q7z0xh+nvr466lz8quiyFvfws22Lg48m/G6G + 28tsYqxrKFTFyQZ4pCzQCOfQyKoI1CokSRiS3IapOeCGygRnnIjyQHBkMrxiShGcWo9jtW1Iq7qLNVF5 + CAgOwvk4R9BoUR3vBBqtxF5HVO5dVlUZ5zinMnYZD4IM0HQKA4fc2x9dTwWVvxOTsQD1Bj189lci9Og1 + rN1biTPXu3HyWjcSSpuxI+cmrL3i8ejOadG+vyVX0//BlS9QEevQXrHHQTJQS8/Vcv8cPVN3UERflRee + nHND3zh05TohLOFzhGZeQ8zZb7AiogAnLxsRU3QbYacbEZBej8nvbUNrlgOeFLuh7bCdpv/AN3E4H7OU + 5l6sGTJAi4kTw0E3mNrOoOMr+3FpJ659Ng+eUQVIKLmLtfEVcAwvwod78rFdfwOBGZcwe30KnF3oUe2x + QWuaHW7G2miu8e3XESiLXsIGeLHqdIaDrhysLhxwpRkoQ1/pezIeqrKSe+ButjNW7sxDXNEdLI8oxLKo + GthuysTbq2IxySMav1/yL+z2+gtNsy0eFyxH+5FFcl/pOgO39qEsarFiwEpn2C8b2O8Cy4Ny9JWtFPSX + UySUqNCR5w6/sDj4p1zA8pgy0HbDdO8kzN+cCZsNh/GWnSfivSfhPBkw5rig7cslmv4Dt/ejNHIRG+Bd + ZCX2KRdqEl1g6ihER+YygVGO6pxpyViK9J3OsPdPhQc9imVRpXCILMGsgKP4g+M2eNv9CQfWvIm8rdNw + PXkBbsSREdV1ei5Fo+S/C9nAs5KBRGFgQjVtLcvDSvRXrEEfUynFfoqscVQ049mVSIt0gv2qTfibx05M + ctmGyQvXwtfhr0hc+2ekfToFhZG2uH3cFU0pNAMVHwxfZ6A5GcUR9iMG5L8JVbRfLY+q0U+7QMJbxL5q + KqvhXVLhBWPBKpyLX4jDgdNw0G8KEj9+C5/7vo20Te/gxBZrlMYuQEOGK24kL0VPuSeZl/oONKegKNyO + DTynNvAMHQ60x0tg1LvDmE2IuFyKeo6qMukdWe64e9QV9UmLULhjNvL/Mwu5oTbIDplO0Rrl0XNRt98e + ddHz0J7lNty358peFIUtYAMTCbEThIGKWEdYHhtgMvig3+ArxVofmAiO/ZSbSNeUL/jgSfU6PDr/Ec2I + J1pzV+O2fiUajnmg6fjf0XLqfdw64iraS318MND6JQq3v8sGnlcbePZ8jAMZuAjTxQ1a6qTYP1ofg94a + P9wv/RhdRd7oLv4QD8rWoe0o7aRaqq9bL9oMtqUhP3Q+G3hBY6B8twNMXRUwnl6thUb1lKagrpPLHTTq + tpOr0J7zvtAakhw17XquH8LZrfPYwItqA8+VRS2F5dt6mC4FCcyCQFVZ0k2XA2Wdo0ofrgtCf73SLxAd + ek+5Tmoz2JGJM1vmsoGXCD4LhIGJpbuWwNJzGearITBfCYHpymaCyxw3C03oVyknpDYKsiZ0qZ+JrsNa + R7b3iE5xsDMLeSG2bIBf2cIAT8PE0sjFMN27gM6CdRL5chzNePo4NKas0PTpaUxF7uY5bOAVtYHnz0Us + gqX3BswN4TDfJDgSA0pZpT2Vj65T6R25fhptsDsXp4KFgVcJPoyEgReKdyyE5UkDBpoiBeZRUavvElHd + Ro26rfGMv6Zu8F4+TgXNYgM/Vht4sSjcHub79egqDRR0ynE0Y+mKNlZd45E1mrz31jHkBMxkAz9RG/hR + YZgdhvpu01GZgIE7iRLNoxAa1as0s6Jr2o+0MRaGyLmE5WEZTm6yYQM/Jfg4lj4uC7YtwFD/HTqpkiRa + 5KhiUCmPqhvWx8BYvFWTWx5XINvfmg38TG3g5fzQd2F+eB3dVWH/V5oyfDV5b/Np6DfOYAM/Vxt45ey/ + 52PI1IpB4xHaq6lSHIZzolOdy5E10V5dr5CKzrIIqSzq6KO3xwD9J8LALwl+IQkDr+ZtmYchcxsGu9Jl + MlTl0XDdd9WP0Fm+ayTvTKetXocT66ezgdcVA7wSX8sLmQvz40Z0G2KI3YJ7clQzljYWSrumYwEavbe1 + EMf9prGBX2sM5P7TlmbAiMH7evo41YuoJWvMONKW89F1WeisjFVpWXTWXMZxX60BsQZygma3d149A0vf + 1XEZGkP7PnqaSzR5+8V0ZKx7x0j3/IViQJyE+zwnrzgZMLMzJ2AW7VNmpiD7U/rKIfT+FAn9RmtkfSKz + YYbE+hniuQr8posRKmT6TkWmj8w/puKrj6Z0b3d88wO65/C7QHwREfx+fo3gA4K3CMMuGV6xDC8chV/J + 8FQqvCHzGxW/VcE5X4fvw1uQBy9+bIITXg9cwfD0fB/8WfVD4K8fhsvcjwdM99NZ/Q9CWBXlOw2tOgAA + AABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem94.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAZdEVYdFRpdGxlAEdhdWdlO0NoYXJ0T3B0aW9uczub + BMPqAAADIklEQVQ4T22Ta0iTURjHj1ba9WsUFPQh6Et9KiLw8kVCSTIwSiNSU8s0Wk5NUTRWQlAZXrpD + lmVLp7a5zeZd966NqXNaXuimszRLa27z0nSW/nvOm0JEB37vwzmc//88zznvwwYUkfqPlZEYqoiETcGJ + gK08EoPlERgsi8DAsyXkR/Hh6R/elx5F38PDBsbYKmbNPwCM3gUsx4COCKDtCGA+DBjDAeEQoD8ItIQC + jSFEMFC/H9AFQZ+zH2Swhikl/s1aaSC0yYHQJAdAc56QBEDNOReAas5ZfxFVEpHoD2WiH57F72slA1+C + +YhOjK1dYh2xfokN/7C8zllNeLPcOyaWe9tImGjOvHPym8JkhYZ7spuGDlnRS8/FAsGSk99yP/Na3SFR + wJhXToGBZRcIfD9jl28ZefBKvlS56WKBvvqO3Ired9/gnJzDwsKiGHtoXvTEgsy8JnVCeslmvj/zOq/g + z/BKvaLdISsyjDcYbXBNzqKzbwgv9K9QVdeOmtZudPV/wtSMB3XCALKuNo3FSR9s5TpRHRgc45OV19Jl + 6hrB6LgTqgYLKmrbUaFrg4LQtnTjjW0Mb4fGMTHphtD+CdLLOg1JV4oGqbk10XflnZicmRXF5SQSOt7A + 7pgSS3DPzkMwv0ZQaLxo4pr2oLDYjDMZiiiSe7OU3No6S88oOnoGUaY1Q0/in78WMOOeJ1MPunrfkzgW + at1L9A98hZXKMVmHkZStqhezSLlU+/27ww0lnf5UY4LdOQ0XCa8XPsauPWHYtTsE9c1tmHZ7oG62imWN + fJ1CYpZ6nAx8mESmww9KU07i0mqjmKKT2O0XjuCwBGzbvhfOqTlam8OjKgElKgF2lxunM1TzZODLkrI1 + 9jH7DF1cG0qUBnz84oCDBNmyG9i4ZSfFPEzQfGjUgeJKPcpqzLB9diE2reqbaHAqrbLBZBnGwuIi+HDR + SRP09hP0nMvRTpFnxge/2EbjII5L5I1iCSckj0/Fp6sQd0GJ+LTniCNiU58jhpNShWgiikcpRakCUckK + nCDCT96OJYMVhPjhTcH74X8s98jf8D6g/4B5/QYaYFKPSY8fuQAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem94.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAZdEVYdFRpdGxlAEdhdWdlO0NoYXJ0T3B0aW9uczub + BMPqAAAI5UlEQVRYR8WXeVCTdxrHo9aqdWzttd3p7NEdd3am+0d3x9bO7DpWx9put9Wta9UiqGC1oNWi + u+5ab1CsBwQDXhzhEgQVAoGEAAlHEu77EBAQOatyJJzhRvvd53mTN1CX7p/bd+bDkzfvm9/n+7uSFwmA + n5QZ3/x/Inmo2SqhYzYxx8YzMzB3Bp6dgXlPMf8pFtgq3ztbCEDHnGalo6Fd5YR2lSPakxgntHFNdBRq + G1cbrYxyipaE/6Y5fssUii1oUjgQthrngJobm/LIO18MMK/U7y8YbboyA5cx0nQJI/cvYbTRHyPE8D0/ + GxcxXO9r5a7USq0UQ7XexAUMVRN3zmOo6hwsld/CUnGG8IKl/DQMnqvZ/LwY4LmCC2swUk83lu2DpXQv + LCVfwVK8h9iNwSKi0A2D+a4YyP8SA3m7MJC7E/05X6A/ewf6jC7o0zsT29CXtRW9GU7oSXdEr24LetI+ + hzl1M0wpm2DSbIRJvQFmnQu0h1ex+SUxwCL9qdWU3otEuzFQ6EoyEuVbRQM2UT+LDCzaTqJtJGKZI3p0 + hNbBKrOJzOrPYFJtgClpPboTP0VXwjp0xa9Fl+ITmJK3QO2+gs2vigGe1x1eSUPlgcHiA9Tj/RgocCe+ + phD70J+3l3r7FYXYg77s3RTClUK4ojdrJ3oyvrCidYFZ6wxz2nbq8VaYNU6CyKR2QLfqc5gSN1GQjehO + +AydCRugcP0zm18TAywMdlyae8PlXdxwWYYbzlRtRDkvs7J9GSJFtlm5zmxl3hGIcJqG4zsIZ7ZMEcbV + garD25Ct/0MxeV8UA/DWW0S8SvyMeM3Gz5/ideIXxC+JXxNv2PiNrfJ7vyL4Ot8n3ivC18TrLxPPiAEk + UUlVkqjESkkko6yUXFdWWEmo5Mv8HTF3/xG/12Uhul1B0fka+a2iqpDY0o6wuDKE3C7uCL5ZUHUtKlfj + cy3ly11fe7FY2Ofy2yWS4JvFAkFE4M0iSWBMkSQgupDbtX4R8cFSPpkOHbOIuSfOR74VFJ2niEqsQGZ+ + E5raemDqHYZleJxug1D5/D69n57biHBFKfzDDQkHTwT8kT7PQWaJbYoE3Cjg9kWPRBIRX/GDG+iYvX6z + 20tXI41BUcqKieqGTjx+/ATf08VJqiNjj2EZmST5JAaGxjE4RK9HJjA8OonRsUlU1nUg9HbxhDQoXb7m + Y8dXqL0509u/GpnPDtElkYTHl/9Avu/fvkuCYgprMguaMDY+ie/JPDr+GE3fmZBf3giNvhJKXRFiVDmI + p6rRlyO3/B4a27rRZxlHv400YwONRnbtNteTv6N27SEuX+cvwmkBaC7tcrf9Z98geUtZzUN6C5iYfILm + 78xIyixDvLYY2uwqGIrrBGFRVRNyqOqL6pFqrEKcthCJ6cW419qN3sFxIUxBRTv8Qo2tDi6HllD7Qgj/ + 8Fx2TQWgBcVl1vJV6xZfi8opKK1+IMi51zklDYhNzUdmQQ3yKxqRRyPAo8AB8qbB54w2rwZFd5rQ0z9G + IcbQMzBObbTAJzC96K2l7/Hqny0LzWHfVAD5Ld6WknkyeYZcl9Nol6dkV1KPSmAorUNOWYOd7LJ6qvXI + LmUaYKRqLCGo3mvtpHUxAXlUMj74uzvMAxxiDEnpd3FalhRGngW+IdnsmwpAx5xDnvL3whVlj3nOJ2ih + 6QvvQpleSsN7F4aSOhiK6pBFr3W5d5BirIQ6qwxJGaVQUdUYKqDNuYO65g6rPFKN9/+2Fx5e/jDTSHCI + h91DuHw994nrAelq9rF0eoD5spDMtPLah8KCa2jpRIw6D7r8Ghr6WmQQLFDROkij2tDSjQ6zRZjnDtMQ + 6lu6UN34CP0kD45QYeXHbiT3E84Lq+7TtYcUZJQ61QzPi6p08j3HUjHA7J37vN4MjCl8wluMhz46MQfJ + 1CtdXrWAxliBBF0JSqpbhYZ4bnttQzudgDAlVny0CydPXxR2AYdKzCxFeHwWTH1j6DQPQxqkf7JmrfNv + 2SsGmHtaFn9Ym90g7PPq+ge4Gp0Gtb4CqbQGkmm449IKUVHXLkisC8uKOL9cr4bGY/kHO3Dc01dY/VUN + D4Q2EmmaZGHJKKttQzeFiNVUwf2o3J28z4oBFngHarUNTd3CllPqihESm4VoVR4UtO3i04ppjsvtcrHn + ZlrdovyKXIE/vb8dxzykwghVUSdupxQSBYhIMCIgRgdFaiG6+kZpB7XjyDmFjrwLxQALpcGZ93v6hjFE + 32QB0TqExhsQRdPABMako6ymVZCJ3GvuxP5vpNRjF2xw/CfeXeWEox4+MJHcRIuu5E4rrkRpaegNCCOC + b2XAn0ahu3eU1o8ZJ6XqZvK+IAZY5Cs3Wnj18wq+FJFCHzTiujKHyIYsQoO2R33CvubeMm77z2Cz81Hs + PeiHtRsP4MN1u2iOSW6j+UEvpCFqhCkMCCXksZnwCUpCFwVo7xqEx8WUIfLaf45foAD0GsLcSeVqGrZs + hNPQcRDfUBW6e0as28nGijXOcNlzFiv/ugfrNh/E75d+JIi7bXTQYrsQlEhTqUdIHEFTevZaghCA8ZCl + svlle4ALgVkWDtBDc+xLyUNiaegoOQ8fn3fRrx0PrxjAZfdxrP5kNz781B1vL9+EjU7udjnP8yPTMLyD + VdRzPYJv6xF0MwNnA5TUzgg6qTPHfNQ8AvYAi70D9ewXAnDywJgMhFJyRhauoQ9xgDHrEFOtrm+H045/ + Ycmbq+DkchDVdbTCqWcMSziAb2gyybMErtJ6OHMlTpB30PUTPho2vyIGePF8QKYQoI8CTB9qq5QrNc4L + zNZLe2/t0mn0WCvLuohOOu+09bzDTFA96i0EsD+UvnDmsk6YgsHhiSk595Zh+TSpwNNSFhBiZWkHi1k6 + A998q7SQ1/5YPm/voWv/OHNJBy8Rfx1OE6f8tTjlp4WnXxo8ZWm0elMJaz3pa0OaguNSjRUa2uM+yThG + PTzmnYyjF5JxhDmvtqHCYcLJ7dwB8i4QA/CjF/+/tpjgn0t+gvkx+MH1f8EPtT+G+LDLDv4f0fpVzH9+ + OiD5D4reaFGiEQGTAAAAAElFTkSuQmCC +</value> + </data> + <data name="barButtonItem103.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABV0RVh0VGl0 + bGUAUHVibGlzaDtVcGxvYWQ7vRo+wQAAA0xJREFUOE+NkmtQjFEYx18ll0Qm3VzGbZkdY3zRjDGmsmVT + WkmjMCRUk7JNFzWYXZrKZlW6GEO1KqUmtLpIpNow276xy9q0UdtFJSlUHzKUpfk777Y0fPLM/OacOef5 + /+Y97zlULq2iAFCkTMSF2zZmV3tVJN0MGrhQ0QJxefOHJKm6IliU4ED2TUvkYiqP9JM9Q8aYo2bsDIwx + 94/jJ1yU7tYre1Kg6W3EqH4SfV/0KKFrEH99j/7iLW4i22HJHKZfJNX8JZi591R4jrC4CrebUjE60YrO + QS0+jv/EEKF9oBmyN5dR+NgPx8UcCek3O1OknBb4RLDcAs66I00mg6LjJdTdNFoHdHg7pjfQOfoNyp4W + 5D8Jh/Dadrj673EnEpNpQRSrTFzKw6kCIdRD42j+NA7t5wloh6eQtz0lR7oPeX8kcmW+4BxwKSeCWX8E + bsHrB1PLvXEiNwG13WNo7P8K+j2h/xvkvZ9RpiiFTFOLx7pMPGwRITaZP0oE5oSpcjoYqD+UeAzCSgWu + KodxTzeG+x1juNkkQ15NNqqb1egcHkexLA0FNfFoaKqbJDELjyjrKYFnROFQmOQ5jhdqEV//AemKT8hX + jyBNmokG3Tlo+2hUKYoQf8MNEelOkEgl30lsAZdvNSVY67y1yis8AH6iqzh8RYXI2x0QPHgPfnYmapT3 + oO6qQkzWFvQNy9H1sR77BBt+sB3nrSNRE4Ng5WZb7037VyI01Q9e0UfgLTwPv2Q5rtV1QP6qC9GXXPGi + qwTtI/l4NhAH2as0uATZqO3Zsy1JfAbjsGBxlpZyjq5F5KUd8BWchY/oEejXg4iThJL7DwH9Lg513Xzc + bQtAsWYnku/wsGmfZRHJzmIEpuZWc+1WOS7LYbt6TO4WVCIwoxGq9kHwou3hGW2HXScXQ/SIRf7RavBO + 2IMXZQfPSDvmGc6lDp45zUiY81hYrV7vyeIKGtg7RCN1dBtKH6i+p2SV9fBOL0K2aguED5fDPdyWCS5h + +gmm1BoPEbXCOYjMDecxIywgMHdkaxyXusdYIYN2QGz1YnBDbRjBQpdjNmQg9ftF/QtT3DBDk7lz2MJG + lxBbMDgGWCvImgUn+D8ExjIlMJ+7yMh84xopivoFgGMSVvyHHV4AAAAASUVORK5CYII= +</value> + </data> + <data name="barButtonItem103.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABV0RVh0VGl0 + bGUAUHVibGlzaDtVcGxvYWQ7vRo+wQAACu5JREFUWEeNlwtcjmcfxy9z2Jxm48WY2MjezdjLHLaclrN1 + UHSiUtFhJfVEOnlS6emg0tOBklRWKpRU6qmQHNuSDjrTSkjUekSlIey3639T45137/6fz/dz3c91Xd2/ + 3/W/TndMS5zK1rqdYIYSGTPxSWLr3W2YkasaM3FfxUw9NZmFz2q2OVDEnKNTGY8+/wvXQ4XM5ccCZhPs + x6wCdjKbsHPMKjiPme8+zTbsyhHeTzo9AUCAaYvTmIpLMjP08mLiGHN2qiyA1bfFs5sPk1hjRwr17RF5 + h9OX0+8tUD21E31yK0KY4wExW+d9nGm6pTN1rqHqcpytdX+LgdWOIcwq0JxFn3JkxY3B7GKDEzt7YzP1 + 6RHua7Zl3qCkHAeNQxlOUa4RhiX2e+2bPA/L4H3sapMkqbjELb4gepP/dk0VnW+G8P5kSDDietCO6UkO + Mw3XdKa2nWfaI4NXv4xeA2qblrLcSi92ptaBZVRtYCdrLahdGPHcZePf25emaR17Wrc5o8gMBQ1uuNF2 + COVNcYjO24oLd9qRU9eKA2dz4bTPEO6R+s1Rmdqb53ynMJD/PWWlz87YzWytZxRTJwNvy4Cq5VJ2tHgt + Sy5Zy05UGlGbMOqdEcqT9mdqlCX/tB6FTU6obpfg7uPjaH1Uha6nD/Hi9xd4+uJ3yJ88Q1VbF07dbEbM + +Sz4xOvj4Emd8h2hiz/j7+nPeWdXojVb5xnwdgMqlkvYoUJNllSiS/Uk3s9j/3dKYWkqzZlXzVHyqxjV + DwLw6Fk9up934enzJ+h+8RzPuDjR/Qr5426cbmhDSKYrMko2ISZnTYtnxOL5/H2CCb2dUqbH10NP9Br4 + 3nwJiy1YRXXCyK29Zk6UJi1tzSwzRUGTA0p/dcej7gYu8hBdTx6gq/sJHj9/8SbPXuA3jvy3bhwtLUNY + lg3yam3gFqkiV9ZbNJm/l0z00eFroSd6Daw0W0y/hTmfpzJ2qCRuQXlivi7ONdjgp0Z73GpP5wLNXKiF + l3Lc72xFZ/fzP3n6HB0Cz9DOp+PyrduIyLZHarEd7MIkMJKkVkyasewD/n5hTZAYRa8Bva1L6Tc19Hfa + N0ssTVuGnOtmOFO/CRdv2UHeVYaW9no0ttbhjryOP7ei7fGzN7jPR06jb+16iprGcuTXB8HrqASBp6/B + TJoLbedEN/7+dzm0O4ToNSAKWkS/+85V/Wi4y4HZLQmXtSGr2YBTtRZIvmKFursVuClvQVPHE9zl3Ovk + PHqC5s6n/Jl4WU/tt9seov5eOUIzrOGXcRhOkSawCQ8Bn3u54mzVkVyHtqiQhV4Dryr6m3t/sd4zQQnJ + pXpIr1iPuEsbITnqj7ImOerkXai/34WGtt9w88FfofobfCdQv9LbdyA9eQZu8R7IKvXC/qyt0LRdgQV6 + c024DmXhLwYoLe9a+H+e6J+6EIlXtJBydR22RRgj6GwdZNXNqLjbgarmDlS3EJ2o+ZV49KrsFOqoveJe + u9B/V6YMIWm2yCi3RFqxFd8RZrDfvegI1xn0Su+NoIqBZr6Tqx0iVsLCXw+bgwxgt2c9/E9fR+j5Opyv + k6Pw9gMUEY0PUHznYS9FjQ9xhdcV3moT+lF/54NiJF+251nURthJFbgdUsIq23G1XGcohxbjG0EVgzVF + M9p1d3rDOOQcbGMLIT5eBomsGrtOcRPn6pBVdU8QuFAvx8VX0DNB9VlVzUI/31PXcCAzFHnVwZCV7ERK + /nY4RX2NZRajOrjOMA6tgzeCDAzRsP0W7rEmMPR2h3nEJWyJL4Jrajk8uQnvnGvw40Yi8xuQVHIHssp7 + yOapzuTl0ZJGoZ6MSrJrsOfsdaRfPIbgdF3sTlmD7MIweMarYoHRhzThtB376Xt8ynTFn5C2EGRg6Hem + 4g5RiDrMfLVhGHgCP0Tmwy6hGM7HrsItvRKemdWCgFdWNXxOXoMPN0V48zpJVo3Q7i2r4qfgLYSneSIy + eyPHDHtTrZCQ441FxuM6uc5wTr/O7l+YlvME0hbipQGLg7VajiawDV4NXa8IGAafhcX+fNjw6dh2pBTO + KWVwTavAjvQKuGdUweNEJS8r+e9KuPI6F240Ib8e8WcvYsePi/mdUYyWzp+wPVoZ+5L84OBn1Mx1BAMd + T6uZpoMCaQtBi3CwknHEMZUtvjwDatDa4QJt35MwCEiAsY8IG/22YFNkKrYkFsP+SAkckq/CIekqtnHs + uTm7hCJIsyqRdLEaDhGaKGtIQXOXDHXt4Siqj4J14HKI/V2LuM4ITr8HT8qZ+tZxpC0EGXjvay1f0yXW + CVB1joCGswt0XHRgGbAGQSf0ECrThyhUFxsCA2ER9TMsowtgFVMglBYH8rEt7jKOnK+Bx0FnHD23Ay1d + uai5L0WF3Bu1DyIQn2sPfZflBVxnFGcAaaqIPubFyxAOohGfzhmrZBJ9X12cjqWOKVjtaAC/49/DN20+ + AjIWYt8ZDYhjtKC/czP0A+Khz6dIPygPhkFnEJVTjqCkRLjHqPFT8iyqWoNQfE+MIoHtuN4WDYewpS/m + 6oxcw7Xoo6Xvis1jSZuxr9ftp0LYCTO0/L0Wb0qApjgcJpIVcPzxK2w7OBWOsdPgFPcVJMnz4JGgAlOf + VdB298Zqnxz4Hi1E5Il8WPgtQM3dVC4eikuNdgL5VN4W8ectKLq5B1qOivcUpg6m2/E9DmW+D5uuF8FL + IQsDhoyaPGaW/r7rqxyjYOShBouQSfghVBGWexRhtZeYDNuIKdgeO4dPz2KIpB6IyrgAKz89ZBR440qT + H2S1G5D9iwlO3zDjmPMvJhNkXDPAiRpjJJ4XQdl0dDbXorUgTAX7Sjecl4IBysKg8bMNZs4y2H9f18UT + G3wXwtB3nMB6XwVeKrwsfRQg2jsTh09J4RZuCe9YHRQ1SZFUro24khU4VLIS8aV/Qr/jSpYjs8YMLvtX + YLb2CAeuRYdSfzZNO5yZSPP4s2CCTqkhisq2qjP1w1u17C1gLZ0PfcnHfGeM4ozGGtdRAiHJIoQk2sPM + 6xtcuR2GzGq+30tWIbFUA4evaiKqcBGiLisLz4mlmrxNHfHFapBV2ULHecrjz5Xfp6+lgYIB0+BzAq+Z + GPrxdJ0507UDaxYZ68PMZy4spRNhQEbEo6DuMBwB8fZYL56FVXYToC7i2I2Hmmg8DNwUEVP4PfZcmisQ + U7gShu6ToSoaJ7SrUX/qazO+jOsMFgxY7Dkv8MpAj4nBAwYNH/PvpeZu01Z+Jl9gNAxaDqOxwVsBVgFK + /HRLxbHcbBySXUJkSj6C4nIh3n3ksa6LIo5VGGF33nQE5M1A+KWFWLtdkY7hLznjOWM4tB1pCgYIBizD + LvbCo8cErQm6v4cNHDZIYcKcdzdOVn4/6Ysl46qnLp8u/492MKZphcqnakprPleVHJugZG79wYgxSmu2 + TeKp1oFXzpfwOvklpHnfcOOCATp76Takd9ICpEG+Ixh4GzzIBG0V6kjbhvYvHaXk/iMObWQazWgOrep/ + cT7REE1E1M+qcMv4DG6Zk/m9MR2adhPJAB199J6eAfbwf6OnI2WEzNAXLo2gZyQE1dE/Ix+pWn+KPReU + 4S77gjMF7llToGotGCCzwhdRVu0mtuKHP2/Dfxqvu/5vKFNk4sO5hiN/nm8yCvNMRmKeMYeX3+qPpLml + LAmf58obx7JFpq+O4p5vs3/K34Rwp3Bommh66LqjRUdKJE4Zoj5vxttE/o6/idczQakmMwQ9Ux21UZ/X + grE/AKH/djUsnEiBAAAAAElFTkSuQmCC +</value> + </data> + <data name="btn_home_manage.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUASG9tZTsedGQ4AAADTElEQVQ4T22Tf0zMYRzHH2U2y6/Mj0jJUFMMU+bXJvNPE5IsM2pS8qPzI45K + SUsqtX5wqlFZQpcpXel0aqHGHw0TM9EVd3Xuru5Xdd/73g/l7fl++SPju72+n2ff53m/nuezZ19yrWUL + KWwO/M3TQFIgCyT0mXD5wUb/gqZA5FOiC+cF0G/OFKc/TDhe7k7iytwJGXDUE61dQjS2OqK21tI54pRY + 7r+2pDUESstddJmvIqV6JdJvlr3Nu/0GOaWvkS569ZxbFyOaT4jKKiZK6z2iZCv58Kkbq9cWSIMgNxfj + cK4/oq4uR4f+PIQVvpC2ScAwLM5nPwNdOzEyZx4hPUwJ6WaKuLBzTJbfuqyaLXhvysT2s54orryDtOvp + CDrthmeaKAhKvNHQWofT6U85waS9l90IeWfK4MP7kpduuHh/Azp057BT6Imy6vvoVQzgc68at6ruYVv8 + XNQrghFdsAjRF0ScwGVXMhVw4Z0nvDYJS9fghfYwdiV4oqLmAVQaI0Ysdgwzdnzt0+NWtRjBZ+aiSr4e + EdkeCNjjupVmJ5Kg2AWbBKIVeNIfhtCkBbgreYh+tQlDjAMm8w8YKYZhKlHqUSquppLZKP/si/A0NwTs + nrGZRGZ6QVDsg4grCyFrk0KpHoJhyAH98G90lAGTHRqDDXKFEY+aJQhP8cTBXA/sueDBtUImU+YIUutg + YVlojXYacOBRmPtfqHQ2KAes0BnNOCQUc0F6BcSFlHUt4yQuqYUvMTb2E9/1dqj0NtTt9QDTWQTmnYgf + qw20DY2VtuRAfEYLJ5gG0FLycSEnmJKc18YLuF2+aa1oOLAYIx3ZMDTGoGH/Yl7wpZ/FIG3vZBp/jdN5 + Af+itoSc53CM/kSPmoX8OwtplA+G2pKhq4+kY2/0DdrwUWHhRXGpTVzIdbxgujCzFVb7GLr6LPiktEAW + 6wejTIDBmnDIjvrxp+r8ykBB67GUJ1xo5njBjPiMZoywo/hAd3n/jUFL3EroJZHQikPoeBV66cneyM3o + VrGITZL+I3A5klD78kSaDIJLMsRdbML1MB8UhnojP8QbuTuW4EhSI2ITHyMmsRERp6pe0czU8QLuV53S + 3t6+mdZZf5j9H+ZQuLlpFGcA5Bf/aUmHDJTX8gAAAABJRU5ErkJggg== +</value> + </data> + <data name="btn_home_manage.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUASG9tZTsedGQ4AAAKMElEQVRYR52WCVRWZRrHb2Y1Z+ZMTYtKatNUGrTZOKYt5lFzK3dz0kYzK8kV + CfcFxIxN2SXQVGSRXTZFMdGEIDMVFWSR5WP7WD7g49t3wPrP87wfMDjhmXPmPefPfb/Lvff3f5/lvVfi + 4Z708n21K/5lySt1ghR8doYUenaWFHxmJt/ygN/Jqf8IPDUdbkcdsf7g6HF0bhCf3xzpKG0+7ihtiXKS + tkU7SdtjnaQdJ16Sdia8JO1OvPfZfcNsqxcy2mpJMslorZYM1ipShaS33iGVSTprCV/6AGlQ5s8eiw6d + W4J2489oNeRjz4mJcPZ//g3+H18j60iXKttSpPLWeOl2S7R0q+mIdF0eIV2tD5Yu1x6QfpT53GvAZKsj + MEtGUBbDKyWd5fdw98h33wjLWoxWYz7Sy+cjtXQu5Npz2B31DlZ6Pz+erhnM1/Vcf49+rguQ8mW+0qWq + ffca4JULsIVVJektFQQvJ3ippO0H3374rfEhmYsIXkDweZj++RBM/2wIkm9/gFpVJrYffRv/8njuTbr2 + 4R491E/CWG61l3Shco+0i9LRN+xwCns/uI7gOksf/MEt4RPGB6YvpJAXIK1sHmZ+MQSuHoFCM2gef2sm + KpXJ2BLxJua7jJwUmXQlP+FUEZKybiMhqxjxmUWITb+Zy8/LubNT2kE10Tf0BNdbKiW9uULSmgluoZX3 + g7uGjptwIGW+yDeHfOaXQ7HT91vEplwW4vkM5yGIvTEdpYpouIWNh+93MWhoVKKzsxu//fYbeIQeLwA9 + b1B2+TZpOxVm39CZKd/mOwQvkzQE11hu82kBdwkeO8EveQ4U+nwK9WzMWj0MHvsjkJp1DZcKyoR47u4X + LoxFXZuKm42HsTF0HFKzT6G0ohFKjRFqvQVBx34UBs6UuklbY5yYYR8M1/TAteY++OB1/mPe9En8QMAT + i2bh/bUED4hAxrlC/FJYA3mTGo3NKlwplCEju5CM2U0cuTIJVxuCsCF4LI6npuBGcQMaWjQ4cChXGDhV + 7EJt6sgc+9CYyghcQsc++EOr/V59yzvxfQGPuzkDs9c5wNOf4N8X4lapHDqDFVZbF6mT5hbcpHMZZ6/D + 40AEZq4eiojLE5Ff44P1wX/H4fgE/ESGfcIusoHB6UVrpE20X/QNFcHVxmKeCrizz8tveyfOQLMuDzGF + 72GOiwP2BkXg9PmbqK5tg8ViQ2dXN7rv/oru7l9hozybzFbckSkoOjfIRDhmrRmGsPy38EOlO5l4HQdj + TsDd/zQb4I54wO1IPwNqUx/84VW+Tm97JU5DE8Ejr03GPNfh+DrkMM7n3UZLmwZmgi9d/S0mL/Du05QF + Pvh4TTiMJivkzWqcu1iEPQHhImWheeORXbYZG0LGYL17ABv4I+nBHl7fsMN9HN/xTpqKJm0ejlIeF24a + Di+CF1ytRIfGAIu1U6z2s80JKKoxob69S4jnq7YmwkYpMRitUCi1ojg9A8Mxe4MDAi+NQ3rRWriEjcHc + dSOnEOsPpN7NSkwe/txn1ESflKlo1OTh0E8T8eG2EfD79igKS2qhoiq2w++ii0L+5Y5kRGQ04Px1DUmL + I6flWLc7VfzPZKaa0JvRSiZ+ul6FfbSAua4OOHBhLBILV8A1/FUs2HiPCWmw8/7R7/imEVydK/K2ZPcz + CDwaJVpIrTXBbO0SK+/q+lXk3mVPOvZFVSAwWYbQVBkCkqqxad8pMnAXJksX9CYbNAYzWtq1uF5cC19a + yILNw+GX8zpiri7Bpu9ewYdbnpnMC2cDj/hlTKGV5yIkdzyWef4VESfiUFbZCI3WTAVnD3snwwlg67qL + rd5nBDwyuwHxPzTSUY5d+8+JojRSBPRGe2eoyHxTqxbXimoRHBmFxdtHwPf8GBy7PA8bD73YWw/SI4u3 + jJy8LmwUnAOex24qHlldCzQ6s2gzm+0urBR6Dr+VjFht3Qg5Rm/AoBzSBXgG52BvyEWERV8WHaEzEdxI + EdDboNZZ0UEm5AotissbsMLNB0vcn8XyfX/DtJXDpvca4Dzw5HGSQ2zaL6KlOOyWntAzlGUmQ2arfd5J + keCIcN555XdJFjqvNdig1VvJgIUMWNCmpnroMFFN6LHZK51XPYr0NOlRErekMMBt8QjpsZTsIsp1t4Dz + A80sgpos3OtdFGKqdAqzgfLMudbSarW0KfUCWUotSWNBu9puQNFhpN8m7NyfzQYcSH8iMXyQRO8IOop2 + YBN/TswqEitiiJmhVFQCSGA9HdOcJyF65hBEzRqK6PeHIYY1m+WA9LWT0U5gsWqVXQpavVxhIDNmqpOz + DHuSJDYjweY/PSaEgbiMW6KaOZQ6KiYD5VRPq9RRf/P2G/PBMHQ2XYBNnkP6Hrb6c6SzsNZlIW7+CBEB + hdIkwC1KI+QtetQ0a8XvHXYDT5Hua+DR6LRCkV9+kIq6QEXh1PTkVEXnTsx9Grba0zDePAjjjVBSEIyF + QbBWJiN+4TPi+qZ2A5raDKhr1qGmUQMZqUVpwDbfMwwaQhrQAH+xPHY06aqo9naNWYSyjUNJ7nneQefi + FoyEpSIRhl98YbjiTfKC/vI+mEuOIfGfz1LVm1HfYgdXN6pRJdegqkEtDG31zvqfBv5yKO6KKD6GKiiE + rKZ2IxrpAfyQhA+fhelWBLS526H9cRe0eTugvbAJhqt+SFr6Appp9dU9UFZlvQoV9WqqAz22eJ1i0FAS + b0ADGnic+9lMhddMUBHKVj3kbSQ6Nih0SProOegKPKDK/AQdGcvRkf4xlGlLoL34FU4uGy2MVhKQVVGn + wp1aFcpJ9ZQO3i2JMYx0XwNPBEfmw0C7X6OA6giqRz2B6yisdVRMJz9+AZpLW9Ge+hHaTy5Ge/IitCUv + hDp7NdI+daLrDQIqwDUdKOtRXZMObnszGcRtOKABzssT/ofzqL876QtGJ3IpColurmnUUjGRgeWO0Hy/ + AW1JC9CWMA+tcXPQGj8bHZkrkPHFK+KeXmiZTIlSWQdKqpXiXte9GQziTei+Bp70jfhBtFutANuh1SzO + q1yN9M+coMr6HIpY+lo6MYuOM6CIniaikfnla8JwKYFLWARm3a5SoprqgV9ixBhO4k1vQANPfROaQ28y + K2QErOZKFgWlQSU9gIspY9VrUKYvRUvUe6SpaDk+Bc3HJ6E1YTay1o0l41o7VIDbhYpJXBMuHmkDG+Af + JBEBd/+zbTdKmvugopioku+QyqmoTq9+He1JC9GWOFdAFXEUiZ4onNkwTkSNgayiyv8op6AKa3YmKYnx + +xrgHySxEX20yvfTjZ6pHa6eGdjomUauU+HinkqfUyexdlcKApZNQdhiRxxc5IiQhS8iaP5oBMwdDf85 + o/D1onex8qtYrHSNwQrXKHziEo3lG45j2fpILF1zRDVljpszMZ4gccH/LgXiy4jEbyneLrld2G2vuHh6 + xWHsrxH/pZEDiO/jN674Eurj9jPAUWAT7I7TwWYGEufv/xU/mxli9QCkfwP2I15ncmdDHAAAAABJRU5E + rkJggg== +</value> + </data> + <data name="ribbonPageGroup11.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABV0RVh0VGl0 + bGUAUHVibGlzaDtVcGxvYWQ7vRo+wQAACu5JREFUWEeNlwtcjmcfxy9z2Jxm48WY2MjezdjLHLaclrN1 + UHSiUtFhJfVEOnlS6emg0tOBklRWKpRU6qmQHNuSDjrTSkjUekSlIey3639T45137/6fz/dz3c91Xd2/ + 3/W/TndMS5zK1rqdYIYSGTPxSWLr3W2YkasaM3FfxUw9NZmFz2q2OVDEnKNTGY8+/wvXQ4XM5ccCZhPs + x6wCdjKbsHPMKjiPme8+zTbsyhHeTzo9AUCAaYvTmIpLMjP08mLiGHN2qiyA1bfFs5sPk1hjRwr17RF5 + h9OX0+8tUD21E31yK0KY4wExW+d9nGm6pTN1rqHqcpytdX+LgdWOIcwq0JxFn3JkxY3B7GKDEzt7YzP1 + 6RHua7Zl3qCkHAeNQxlOUa4RhiX2e+2bPA/L4H3sapMkqbjELb4gepP/dk0VnW+G8P5kSDDietCO6UkO + Mw3XdKa2nWfaI4NXv4xeA2qblrLcSi92ptaBZVRtYCdrLahdGPHcZePf25emaR17Wrc5o8gMBQ1uuNF2 + COVNcYjO24oLd9qRU9eKA2dz4bTPEO6R+s1Rmdqb53ynMJD/PWWlz87YzWytZxRTJwNvy4Cq5VJ2tHgt + Sy5Zy05UGlGbMOqdEcqT9mdqlCX/tB6FTU6obpfg7uPjaH1Uha6nD/Hi9xd4+uJ3yJ88Q1VbF07dbEbM + +Sz4xOvj4Emd8h2hiz/j7+nPeWdXojVb5xnwdgMqlkvYoUJNllSiS/Uk3s9j/3dKYWkqzZlXzVHyqxjV + DwLw6Fk9up934enzJ+h+8RzPuDjR/Qr5426cbmhDSKYrMko2ISZnTYtnxOL5/H2CCb2dUqbH10NP9Br4 + 3nwJiy1YRXXCyK29Zk6UJi1tzSwzRUGTA0p/dcej7gYu8hBdTx6gq/sJHj9/8SbPXuA3jvy3bhwtLUNY + lg3yam3gFqkiV9ZbNJm/l0z00eFroSd6Daw0W0y/hTmfpzJ2qCRuQXlivi7ONdjgp0Z73GpP5wLNXKiF + l3Lc72xFZ/fzP3n6HB0Cz9DOp+PyrduIyLZHarEd7MIkMJKkVkyasewD/n5hTZAYRa8Bva1L6Tc19Hfa + N0ssTVuGnOtmOFO/CRdv2UHeVYaW9no0ttbhjryOP7ei7fGzN7jPR06jb+16iprGcuTXB8HrqASBp6/B + TJoLbedEN/7+dzm0O4ToNSAKWkS/+85V/Wi4y4HZLQmXtSGr2YBTtRZIvmKFursVuClvQVPHE9zl3Ovk + PHqC5s6n/Jl4WU/tt9seov5eOUIzrOGXcRhOkSawCQ8Bn3u54mzVkVyHtqiQhV4Dryr6m3t/sd4zQQnJ + pXpIr1iPuEsbITnqj7ImOerkXai/34WGtt9w88FfofobfCdQv9LbdyA9eQZu8R7IKvXC/qyt0LRdgQV6 + c024DmXhLwYoLe9a+H+e6J+6EIlXtJBydR22RRgj6GwdZNXNqLjbgarmDlS3EJ2o+ZV49KrsFOqoveJe + u9B/V6YMIWm2yCi3RFqxFd8RZrDfvegI1xn0Su+NoIqBZr6Tqx0iVsLCXw+bgwxgt2c9/E9fR+j5Opyv + k6Pw9gMUEY0PUHznYS9FjQ9xhdcV3moT+lF/54NiJF+251nURthJFbgdUsIq23G1XGcohxbjG0EVgzVF + M9p1d3rDOOQcbGMLIT5eBomsGrtOcRPn6pBVdU8QuFAvx8VX0DNB9VlVzUI/31PXcCAzFHnVwZCV7ERK + /nY4RX2NZRajOrjOMA6tgzeCDAzRsP0W7rEmMPR2h3nEJWyJL4Jrajk8uQnvnGvw40Yi8xuQVHIHssp7 + yOapzuTl0ZJGoZ6MSrJrsOfsdaRfPIbgdF3sTlmD7MIweMarYoHRhzThtB376Xt8ynTFn5C2EGRg6Hem + 4g5RiDrMfLVhGHgCP0Tmwy6hGM7HrsItvRKemdWCgFdWNXxOXoMPN0V48zpJVo3Q7i2r4qfgLYSneSIy + eyPHDHtTrZCQ441FxuM6uc5wTr/O7l+YlvME0hbipQGLg7VajiawDV4NXa8IGAafhcX+fNjw6dh2pBTO + KWVwTavAjvQKuGdUweNEJS8r+e9KuPI6F240Ib8e8WcvYsePi/mdUYyWzp+wPVoZ+5L84OBn1Mx1BAMd + T6uZpoMCaQtBi3CwknHEMZUtvjwDatDa4QJt35MwCEiAsY8IG/22YFNkKrYkFsP+SAkckq/CIekqtnHs + uTm7hCJIsyqRdLEaDhGaKGtIQXOXDHXt4Siqj4J14HKI/V2LuM4ITr8HT8qZ+tZxpC0EGXjvay1f0yXW + CVB1joCGswt0XHRgGbAGQSf0ECrThyhUFxsCA2ER9TMsowtgFVMglBYH8rEt7jKOnK+Bx0FnHD23Ay1d + uai5L0WF3Bu1DyIQn2sPfZflBVxnFGcAaaqIPubFyxAOohGfzhmrZBJ9X12cjqWOKVjtaAC/49/DN20+ + AjIWYt8ZDYhjtKC/czP0A+Khz6dIPygPhkFnEJVTjqCkRLjHqPFT8iyqWoNQfE+MIoHtuN4WDYewpS/m + 6oxcw7Xoo6Xvis1jSZuxr9ftp0LYCTO0/L0Wb0qApjgcJpIVcPzxK2w7OBWOsdPgFPcVJMnz4JGgAlOf + VdB298Zqnxz4Hi1E5Il8WPgtQM3dVC4eikuNdgL5VN4W8ectKLq5B1qOivcUpg6m2/E9DmW+D5uuF8FL + IQsDhoyaPGaW/r7rqxyjYOShBouQSfghVBGWexRhtZeYDNuIKdgeO4dPz2KIpB6IyrgAKz89ZBR440qT + H2S1G5D9iwlO3zDjmPMvJhNkXDPAiRpjJJ4XQdl0dDbXorUgTAX7Sjecl4IBysKg8bMNZs4y2H9f18UT + G3wXwtB3nMB6XwVeKrwsfRQg2jsTh09J4RZuCe9YHRQ1SZFUro24khU4VLIS8aV/Qr/jSpYjs8YMLvtX + YLb2CAeuRYdSfzZNO5yZSPP4s2CCTqkhisq2qjP1w1u17C1gLZ0PfcnHfGeM4ozGGtdRAiHJIoQk2sPM + 6xtcuR2GzGq+30tWIbFUA4evaiKqcBGiLisLz4mlmrxNHfHFapBV2ULHecrjz5Xfp6+lgYIB0+BzAq+Z + GPrxdJ0507UDaxYZ68PMZy4spRNhQEbEo6DuMBwB8fZYL56FVXYToC7i2I2Hmmg8DNwUEVP4PfZcmisQ + U7gShu6ToSoaJ7SrUX/qazO+jOsMFgxY7Dkv8MpAj4nBAwYNH/PvpeZu01Z+Jl9gNAxaDqOxwVsBVgFK + /HRLxbHcbBySXUJkSj6C4nIh3n3ksa6LIo5VGGF33nQE5M1A+KWFWLtdkY7hLznjOWM4tB1pCgYIBizD + LvbCo8cErQm6v4cNHDZIYcKcdzdOVn4/6Ysl46qnLp8u/492MKZphcqnakprPleVHJugZG79wYgxSmu2 + TeKp1oFXzpfwOvklpHnfcOOCATp76Takd9ICpEG+Ixh4GzzIBG0V6kjbhvYvHaXk/iMObWQazWgOrep/ + cT7REE1E1M+qcMv4DG6Zk/m9MR2adhPJAB199J6eAfbwf6OnI2WEzNAXLo2gZyQE1dE/Ix+pWn+KPReU + 4S77gjMF7llToGotGCCzwhdRVu0mtuKHP2/Dfxqvu/5vKFNk4sO5hiN/nm8yCvNMRmKeMYeX3+qPpLml + LAmf58obx7JFpq+O4p5vs3/K34Rwp3Bommh66LqjRUdKJE4Zoj5vxttE/o6/idczQakmMwQ9Ux21UZ/X + grE/AKH/djUsnEiBAAAAAElFTkSuQmCC +</value> + </data> + <metadata name="notify_pallet.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <metadata name="menu_tray.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>233, 17</value> + </metadata> + <data name="barButtonItem32.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAA90RVh0VGl0 + bGUAQnV5O0NhcnQ70AxJmAAAALNJREFUOE+l0j8OQUEQx/FH7xZ6raidQaXTKdV6raBzBgdxAKHUuQFB + sb7zYjeza2T8KT6TzC+zs5u8Vx1G/W8NEJ7O1oBng58XtHBBL2blgGeIIxoxk7JHfNInZkhLpUhgDb7T + QbagC2vQskM6LKQ0cYJ1oDTFywKxhnWg1Ia5wDPGtshqurFu1CbQ87UySN/XyRLdLHHHyskyurlCnnpD + vNXKMrqZQ/7zhZNlqhDCH0L1AC2p72TNLDwrAAAAAElFTkSuQmCC +</value> + </data> + <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>793, 17</value> + </metadata> + <data name="barButtonItem58.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAALdEVYdFRpdGxlAFNlbmQ7faSt1wAAAKNJREFUOE+l + ksENgzAQBN1g2uGJBE1QAiUkH2q7eC9ey2zOsoDHyBy6GRAimdkjwptXSK/1c2TsBgcDGHAu5XoE9txr + A3O5OYpQxv4pAEaRkww0AHqRPxlEAaCRUAZRoF1mpJ2JxzWgT6JU52nfUsbPPC84Gei9pkeKSCzDWA1E + MqGkeATiWwSlFwBz+H8rgQh+3yASFCw2VBmEgsLlQpWnfUtfL1JsVF9I3IwAAAAASUVORK5CYII= +</value> + </data> + <metadata name="menu_coerce_order.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>883, 17</value> + </metadata> + <data name="barButtonItem79.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAMkSURBVEhLtVVZSJVBGP1peYiglaCifSGKinaiooWo + IOqlogWKnqKHoOcgKuo5wijb0zQrzRYtFYuyIs02S6I0zdxSsyRzSVFz5vSdGX+Z5HKvXenhcO/88813 + vvmWMx6ATrRrIOKNxpwrCvOuKswXLLgWHL7NskSF20XiwPFH/LUoawCWXlfoHaEw7IzCyHMKI0KANkNP + K/SSM5tSQhCUC8HCeIVR5xUelmuQsPBncNAmoUBj4CmFLakhCGqagcUJCpOjFYrr5YuzFwwvq4Ehcosd + 6SEIsr/COCc+1soXZy8YHlcAg4VgxQ0NBunudf6J/qAxV4rLXM6KU8gPg4Bn1yZpZEh6/T2vpR04lK3N + Jos7SHI547JCUZ3N79EcjbffgebfQGSuRmKhPcyO4bq+Fciqsinyiz1cCk+72hYxjJcC9Tku15M2Sy/V + WCRFnhiljPMnEhkPnH1nr87OWnXLEmy4q82ajfFKasAbsItIzM4iCQP31ifb6Hfes12zRhyMu6hMhzC6 + tBKNql9AmwKYCjojQc43u2YGnlZagt0PtDk3W1JMn0y5xyHhot8JmxpelQafxJCOugN2EdMzVgIbL2Cq + 6XOm+PM4ibzqdmkxknCDV8yUqFwnwRD1XqP/SXuWvram2awwYI+yMEFyXt1k0zEtRpma8FtMnjYpcJ25 + YF2OPNfm1n3lzGpJb94PmzoSTBVfHvM05oJCScdgNUjeDz7Tppt41ZU3NV5LvpWprXXcKqTJn7UJgsGM + lvNx+RrUMu6nFtsbBCTwcb9MGwFj2gZEKtOSbF3Ox95H1gELu1E6p6DLzKR0h8DHMZkDFo8HGC1/CTbC + HblFV3uC32kzSRQhJAHxQiRkT4Y2srxEtOqApPBLo+wEsCVYSxJMudRNAh+NbXYe3G+BUCrzxDrGSpP8 + E0E4+P8EVE5KQ6XIgbvRE1AFNsvjc1hmxEgFJ5cD4hr1BEkieCwyu8/bl2kXFLs6kVfXMBxwTvgqcrLX + iZB6FdJuy2WgfHmgQE2PDQ/UHso0A94lyppb08HK93ebCBTfAV8RwwFrSaL9WRpN8kAB8P4AuhDeLWkB + /08AAAAASUVORK5CYII= +</value> + </data> + <metadata name="autologin_timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>1051, 17</value> + </metadata> + <metadata name="alertControl1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>1196, 17</value> + </metadata> + <data name="barButtonItem104.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUASG9tZTsedGQ4AAADTElEQVQ4T22Tf0zMYRzHH2U2y6/Mj0jJUFMMU+bXJvNPE5IsM2pS8qPzI45K + SUsqtX5wqlFZQpcpXel0aqHGHw0TM9EVd3Xuru5Xdd/73g/l7fl++SPju72+n2ff53m/nuezZ19yrWUL + KWwO/M3TQFIgCyT0mXD5wUb/gqZA5FOiC+cF0G/OFKc/TDhe7k7iytwJGXDUE61dQjS2OqK21tI54pRY + 7r+2pDUESstddJmvIqV6JdJvlr3Nu/0GOaWvkS569ZxbFyOaT4jKKiZK6z2iZCv58Kkbq9cWSIMgNxfj + cK4/oq4uR4f+PIQVvpC2ScAwLM5nPwNdOzEyZx4hPUwJ6WaKuLBzTJbfuqyaLXhvysT2s54orryDtOvp + CDrthmeaKAhKvNHQWofT6U85waS9l90IeWfK4MP7kpduuHh/Azp057BT6Imy6vvoVQzgc68at6ruYVv8 + XNQrghFdsAjRF0ScwGVXMhVw4Z0nvDYJS9fghfYwdiV4oqLmAVQaI0Ysdgwzdnzt0+NWtRjBZ+aiSr4e + EdkeCNjjupVmJ5Kg2AWbBKIVeNIfhtCkBbgreYh+tQlDjAMm8w8YKYZhKlHqUSquppLZKP/si/A0NwTs + nrGZRGZ6QVDsg4grCyFrk0KpHoJhyAH98G90lAGTHRqDDXKFEY+aJQhP8cTBXA/sueDBtUImU+YIUutg + YVlojXYacOBRmPtfqHQ2KAes0BnNOCQUc0F6BcSFlHUt4yQuqYUvMTb2E9/1dqj0NtTt9QDTWQTmnYgf + qw20DY2VtuRAfEYLJ5gG0FLycSEnmJKc18YLuF2+aa1oOLAYIx3ZMDTGoGH/Yl7wpZ/FIG3vZBp/jdN5 + Af+itoSc53CM/kSPmoX8OwtplA+G2pKhq4+kY2/0DdrwUWHhRXGpTVzIdbxgujCzFVb7GLr6LPiktEAW + 6wejTIDBmnDIjvrxp+r8ykBB67GUJ1xo5njBjPiMZoywo/hAd3n/jUFL3EroJZHQikPoeBV66cneyM3o + VrGITZL+I3A5klD78kSaDIJLMsRdbML1MB8UhnojP8QbuTuW4EhSI2ITHyMmsRERp6pe0czU8QLuV53S + 3t6+mdZZf5j9H+ZQuLlpFGcA5Bf/aUmHDJTX8gAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem104.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUASG9tZTsedGQ4AAAKMElEQVRYR52WCVRWZRrHb2Y1Z+ZMTYtKatNUGrTZOKYt5lFzK3dz0kYzK8kV + CfcFxIxN2SXQVGSRXTZFMdGEIDMVFWSR5WP7WD7g49t3wPrP87wfMDjhmXPmPefPfb/Lvff3f5/lvVfi + 4Z708n21K/5lySt1ghR8doYUenaWFHxmJt/ygN/Jqf8IPDUdbkcdsf7g6HF0bhCf3xzpKG0+7ihtiXKS + tkU7SdtjnaQdJ16Sdia8JO1OvPfZfcNsqxcy2mpJMslorZYM1ipShaS33iGVSTprCV/6AGlQ5s8eiw6d + W4J2489oNeRjz4mJcPZ//g3+H18j60iXKttSpPLWeOl2S7R0q+mIdF0eIV2tD5Yu1x6QfpT53GvAZKsj + MEtGUBbDKyWd5fdw98h33wjLWoxWYz7Sy+cjtXQu5Npz2B31DlZ6Pz+erhnM1/Vcf49+rguQ8mW+0qWq + ffca4JULsIVVJektFQQvJ3ippO0H3374rfEhmYsIXkDweZj++RBM/2wIkm9/gFpVJrYffRv/8njuTbr2 + 4R491E/CWG61l3Shco+0i9LRN+xwCns/uI7gOksf/MEt4RPGB6YvpJAXIK1sHmZ+MQSuHoFCM2gef2sm + KpXJ2BLxJua7jJwUmXQlP+FUEZKybiMhqxjxmUWITb+Zy8/LubNT2kE10Tf0BNdbKiW9uULSmgluoZX3 + g7uGjptwIGW+yDeHfOaXQ7HT91vEplwW4vkM5yGIvTEdpYpouIWNh+93MWhoVKKzsxu//fYbeIQeLwA9 + b1B2+TZpOxVm39CZKd/mOwQvkzQE11hu82kBdwkeO8EveQ4U+nwK9WzMWj0MHvsjkJp1DZcKyoR47u4X + LoxFXZuKm42HsTF0HFKzT6G0ohFKjRFqvQVBx34UBs6UuklbY5yYYR8M1/TAteY++OB1/mPe9En8QMAT + i2bh/bUED4hAxrlC/FJYA3mTGo3NKlwplCEju5CM2U0cuTIJVxuCsCF4LI6npuBGcQMaWjQ4cChXGDhV + 7EJt6sgc+9CYyghcQsc++EOr/V59yzvxfQGPuzkDs9c5wNOf4N8X4lapHDqDFVZbF6mT5hbcpHMZZ6/D + 40AEZq4eiojLE5Ff44P1wX/H4fgE/ESGfcIusoHB6UVrpE20X/QNFcHVxmKeCrizz8tveyfOQLMuDzGF + 72GOiwP2BkXg9PmbqK5tg8ViQ2dXN7rv/oru7l9hozybzFbckSkoOjfIRDhmrRmGsPy38EOlO5l4HQdj + TsDd/zQb4I54wO1IPwNqUx/84VW+Tm97JU5DE8Ejr03GPNfh+DrkMM7n3UZLmwZmgi9d/S0mL/Du05QF + Pvh4TTiMJivkzWqcu1iEPQHhImWheeORXbYZG0LGYL17ABv4I+nBHl7fsMN9HN/xTpqKJm0ejlIeF24a + Di+CF1ytRIfGAIu1U6z2s80JKKoxob69S4jnq7YmwkYpMRitUCi1ojg9A8Mxe4MDAi+NQ3rRWriEjcHc + dSOnEOsPpN7NSkwe/txn1ESflKlo1OTh0E8T8eG2EfD79igKS2qhoiq2w++ii0L+5Y5kRGQ04Px1DUmL + I6flWLc7VfzPZKaa0JvRSiZ+ul6FfbSAua4OOHBhLBILV8A1/FUs2HiPCWmw8/7R7/imEVydK/K2ZPcz + CDwaJVpIrTXBbO0SK+/q+lXk3mVPOvZFVSAwWYbQVBkCkqqxad8pMnAXJksX9CYbNAYzWtq1uF5cC19a + yILNw+GX8zpiri7Bpu9ewYdbnpnMC2cDj/hlTKGV5yIkdzyWef4VESfiUFbZCI3WTAVnD3snwwlg67qL + rd5nBDwyuwHxPzTSUY5d+8+JojRSBPRGe2eoyHxTqxbXimoRHBmFxdtHwPf8GBy7PA8bD73YWw/SI4u3 + jJy8LmwUnAOex24qHlldCzQ6s2gzm+0urBR6Dr+VjFht3Qg5Rm/AoBzSBXgG52BvyEWERV8WHaEzEdxI + EdDboNZZ0UEm5AotissbsMLNB0vcn8XyfX/DtJXDpvca4Dzw5HGSQ2zaL6KlOOyWntAzlGUmQ2arfd5J + keCIcN555XdJFjqvNdig1VvJgIUMWNCmpnroMFFN6LHZK51XPYr0NOlRErekMMBt8QjpsZTsIsp1t4Dz + A80sgpos3OtdFGKqdAqzgfLMudbSarW0KfUCWUotSWNBu9puQNFhpN8m7NyfzQYcSH8iMXyQRO8IOop2 + YBN/TswqEitiiJmhVFQCSGA9HdOcJyF65hBEzRqK6PeHIYY1m+WA9LWT0U5gsWqVXQpavVxhIDNmqpOz + DHuSJDYjweY/PSaEgbiMW6KaOZQ6KiYD5VRPq9RRf/P2G/PBMHQ2XYBNnkP6Hrb6c6SzsNZlIW7+CBEB + hdIkwC1KI+QtetQ0a8XvHXYDT5Hua+DR6LRCkV9+kIq6QEXh1PTkVEXnTsx9Grba0zDePAjjjVBSEIyF + QbBWJiN+4TPi+qZ2A5raDKhr1qGmUQMZqUVpwDbfMwwaQhrQAH+xPHY06aqo9naNWYSyjUNJ7nneQefi + FoyEpSIRhl98YbjiTfKC/vI+mEuOIfGfz1LVm1HfYgdXN6pRJdegqkEtDG31zvqfBv5yKO6KKD6GKiiE + rKZ2IxrpAfyQhA+fhelWBLS526H9cRe0eTugvbAJhqt+SFr6Appp9dU9UFZlvQoV9WqqAz22eJ1i0FAS + b0ADGnic+9lMhddMUBHKVj3kbSQ6Nih0SProOegKPKDK/AQdGcvRkf4xlGlLoL34FU4uGy2MVhKQVVGn + wp1aFcpJ9ZQO3i2JMYx0XwNPBEfmw0C7X6OA6giqRz2B6yisdVRMJz9+AZpLW9Ge+hHaTy5Ge/IitCUv + hDp7NdI+daLrDQIqwDUdKOtRXZMObnszGcRtOKABzssT/ofzqL876QtGJ3IpColurmnUUjGRgeWO0Hy/ + AW1JC9CWMA+tcXPQGj8bHZkrkPHFK+KeXmiZTIlSWQdKqpXiXte9GQziTei+Bp70jfhBtFutANuh1SzO + q1yN9M+coMr6HIpY+lo6MYuOM6CIniaikfnla8JwKYFLWARm3a5SoprqgV9ixBhO4k1vQANPfROaQ28y + K2QErOZKFgWlQSU9gIspY9VrUKYvRUvUe6SpaDk+Bc3HJ6E1YTay1o0l41o7VIDbhYpJXBMuHmkDG+Af + JBEBd/+zbTdKmvugopioku+QyqmoTq9+He1JC9GWOFdAFXEUiZ4onNkwTkSNgayiyv8op6AKa3YmKYnx + +xrgHySxEX20yvfTjZ6pHa6eGdjomUauU+HinkqfUyexdlcKApZNQdhiRxxc5IiQhS8iaP5oBMwdDf85 + o/D1onex8qtYrHSNwQrXKHziEo3lG45j2fpILF1zRDVljpszMZ4gccH/LgXiy4jEbyneLrld2G2vuHh6 + xWHsrxH/pZEDiO/jN674Eurj9jPAUWAT7I7TwWYGEufv/xU/mxli9QCkfwP2I15ncmdDHAAAAABJRU5E + rkJggg== +</value> + </data> + <data name="barButtonItem106.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUASG9tZTsedGQ4AAADTElEQVQ4T22Tf0zMYRzHH2U2y6/Mj0jJUFMMU+bXJvNPE5IsM2pS8qPzI45K + SUsqtX5wqlFZQpcpXel0aqHGHw0TM9EVd3Xuru5Xdd/73g/l7fl++SPju72+n2ff53m/nuezZ19yrWUL + KWwO/M3TQFIgCyT0mXD5wUb/gqZA5FOiC+cF0G/OFKc/TDhe7k7iytwJGXDUE61dQjS2OqK21tI54pRY + 7r+2pDUESstddJmvIqV6JdJvlr3Nu/0GOaWvkS569ZxbFyOaT4jKKiZK6z2iZCv58Kkbq9cWSIMgNxfj + cK4/oq4uR4f+PIQVvpC2ScAwLM5nPwNdOzEyZx4hPUwJ6WaKuLBzTJbfuqyaLXhvysT2s54orryDtOvp + CDrthmeaKAhKvNHQWofT6U85waS9l90IeWfK4MP7kpduuHh/Azp057BT6Imy6vvoVQzgc68at6ruYVv8 + XNQrghFdsAjRF0ScwGVXMhVw4Z0nvDYJS9fghfYwdiV4oqLmAVQaI0Ysdgwzdnzt0+NWtRjBZ+aiSr4e + EdkeCNjjupVmJ5Kg2AWbBKIVeNIfhtCkBbgreYh+tQlDjAMm8w8YKYZhKlHqUSquppLZKP/si/A0NwTs + nrGZRGZ6QVDsg4grCyFrk0KpHoJhyAH98G90lAGTHRqDDXKFEY+aJQhP8cTBXA/sueDBtUImU+YIUutg + YVlojXYacOBRmPtfqHQ2KAes0BnNOCQUc0F6BcSFlHUt4yQuqYUvMTb2E9/1dqj0NtTt9QDTWQTmnYgf + qw20DY2VtuRAfEYLJ5gG0FLycSEnmJKc18YLuF2+aa1oOLAYIx3ZMDTGoGH/Yl7wpZ/FIG3vZBp/jdN5 + Af+itoSc53CM/kSPmoX8OwtplA+G2pKhq4+kY2/0DdrwUWHhRXGpTVzIdbxgujCzFVb7GLr6LPiktEAW + 6wejTIDBmnDIjvrxp+r8ykBB67GUJ1xo5njBjPiMZoywo/hAd3n/jUFL3EroJZHQikPoeBV66cneyM3o + VrGITZL+I3A5klD78kSaDIJLMsRdbML1MB8UhnojP8QbuTuW4EhSI2ITHyMmsRERp6pe0czU8QLuV53S + 3t6+mdZZf5j9H+ZQuLlpFGcA5Bf/aUmHDJTX8gAAAABJRU5ErkJggg== +</value> + </data> + <data name="barButtonItem106.ImageOptions.LargeImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUASG9tZTsedGQ4AAAKMElEQVRYR52WCVRWZRrHb2Y1Z+ZMTYtKatNUGrTZOKYt5lFzK3dz0kYzK8kV + CfcFxIxN2SXQVGSRXTZFMdGEIDMVFWSR5WP7WD7g49t3wPrP87wfMDjhmXPmPefPfb/Lvff3f5/lvVfi + 4Z708n21K/5lySt1ghR8doYUenaWFHxmJt/ygN/Jqf8IPDUdbkcdsf7g6HF0bhCf3xzpKG0+7ihtiXKS + tkU7SdtjnaQdJ16Sdia8JO1OvPfZfcNsqxcy2mpJMslorZYM1ipShaS33iGVSTprCV/6AGlQ5s8eiw6d + W4J2489oNeRjz4mJcPZ//g3+H18j60iXKttSpPLWeOl2S7R0q+mIdF0eIV2tD5Yu1x6QfpT53GvAZKsj + MEtGUBbDKyWd5fdw98h33wjLWoxWYz7Sy+cjtXQu5Npz2B31DlZ6Pz+erhnM1/Vcf49+rguQ8mW+0qWq + ffca4JULsIVVJektFQQvJ3ippO0H3374rfEhmYsIXkDweZj++RBM/2wIkm9/gFpVJrYffRv/8njuTbr2 + 4R491E/CWG61l3Shco+0i9LRN+xwCns/uI7gOksf/MEt4RPGB6YvpJAXIK1sHmZ+MQSuHoFCM2gef2sm + KpXJ2BLxJua7jJwUmXQlP+FUEZKybiMhqxjxmUWITb+Zy8/LubNT2kE10Tf0BNdbKiW9uULSmgluoZX3 + g7uGjptwIGW+yDeHfOaXQ7HT91vEplwW4vkM5yGIvTEdpYpouIWNh+93MWhoVKKzsxu//fYbeIQeLwA9 + b1B2+TZpOxVm39CZKd/mOwQvkzQE11hu82kBdwkeO8EveQ4U+nwK9WzMWj0MHvsjkJp1DZcKyoR47u4X + LoxFXZuKm42HsTF0HFKzT6G0ohFKjRFqvQVBx34UBs6UuklbY5yYYR8M1/TAteY++OB1/mPe9En8QMAT + i2bh/bUED4hAxrlC/FJYA3mTGo3NKlwplCEju5CM2U0cuTIJVxuCsCF4LI6npuBGcQMaWjQ4cChXGDhV + 7EJt6sgc+9CYyghcQsc++EOr/V59yzvxfQGPuzkDs9c5wNOf4N8X4lapHDqDFVZbF6mT5hbcpHMZZ6/D + 40AEZq4eiojLE5Ff44P1wX/H4fgE/ESGfcIusoHB6UVrpE20X/QNFcHVxmKeCrizz8tveyfOQLMuDzGF + 72GOiwP2BkXg9PmbqK5tg8ViQ2dXN7rv/oru7l9hozybzFbckSkoOjfIRDhmrRmGsPy38EOlO5l4HQdj + TsDd/zQb4I54wO1IPwNqUx/84VW+Tm97JU5DE8Ejr03GPNfh+DrkMM7n3UZLmwZmgi9d/S0mL/Du05QF + Pvh4TTiMJivkzWqcu1iEPQHhImWheeORXbYZG0LGYL17ABv4I+nBHl7fsMN9HN/xTpqKJm0ejlIeF24a + Di+CF1ytRIfGAIu1U6z2s80JKKoxob69S4jnq7YmwkYpMRitUCi1ojg9A8Mxe4MDAi+NQ3rRWriEjcHc + dSOnEOsPpN7NSkwe/txn1ESflKlo1OTh0E8T8eG2EfD79igKS2qhoiq2w++ii0L+5Y5kRGQ04Px1DUmL + I6flWLc7VfzPZKaa0JvRSiZ+ul6FfbSAua4OOHBhLBILV8A1/FUs2HiPCWmw8/7R7/imEVydK/K2ZPcz + CDwaJVpIrTXBbO0SK+/q+lXk3mVPOvZFVSAwWYbQVBkCkqqxad8pMnAXJksX9CYbNAYzWtq1uF5cC19a + yILNw+GX8zpiri7Bpu9ewYdbnpnMC2cDj/hlTKGV5yIkdzyWef4VESfiUFbZCI3WTAVnD3snwwlg67qL + rd5nBDwyuwHxPzTSUY5d+8+JojRSBPRGe2eoyHxTqxbXimoRHBmFxdtHwPf8GBy7PA8bD73YWw/SI4u3 + jJy8LmwUnAOex24qHlldCzQ6s2gzm+0urBR6Dr+VjFht3Qg5Rm/AoBzSBXgG52BvyEWERV8WHaEzEdxI + EdDboNZZ0UEm5AotissbsMLNB0vcn8XyfX/DtJXDpvca4Dzw5HGSQ2zaL6KlOOyWntAzlGUmQ2arfd5J + keCIcN555XdJFjqvNdig1VvJgIUMWNCmpnroMFFN6LHZK51XPYr0NOlRErekMMBt8QjpsZTsIsp1t4Dz + A80sgpos3OtdFGKqdAqzgfLMudbSarW0KfUCWUotSWNBu9puQNFhpN8m7NyfzQYcSH8iMXyQRO8IOop2 + YBN/TswqEitiiJmhVFQCSGA9HdOcJyF65hBEzRqK6PeHIYY1m+WA9LWT0U5gsWqVXQpavVxhIDNmqpOz + DHuSJDYjweY/PSaEgbiMW6KaOZQ6KiYD5VRPq9RRf/P2G/PBMHQ2XYBNnkP6Hrb6c6SzsNZlIW7+CBEB + hdIkwC1KI+QtetQ0a8XvHXYDT5Hua+DR6LRCkV9+kIq6QEXh1PTkVEXnTsx9Grba0zDePAjjjVBSEIyF + QbBWJiN+4TPi+qZ2A5raDKhr1qGmUQMZqUVpwDbfMwwaQhrQAH+xPHY06aqo9naNWYSyjUNJ7nneQefi + FoyEpSIRhl98YbjiTfKC/vI+mEuOIfGfz1LVm1HfYgdXN6pRJdegqkEtDG31zvqfBv5yKO6KKD6GKiiE + rKZ2IxrpAfyQhA+fhelWBLS526H9cRe0eTugvbAJhqt+SFr6Appp9dU9UFZlvQoV9WqqAz22eJ1i0FAS + b0ADGnic+9lMhddMUBHKVj3kbSQ6Nih0SProOegKPKDK/AQdGcvRkf4xlGlLoL34FU4uGy2MVhKQVVGn + wp1aFcpJ9ZQO3i2JMYx0XwNPBEfmw0C7X6OA6giqRz2B6yisdVRMJz9+AZpLW9Ge+hHaTy5Ge/IitCUv + hDp7NdI+daLrDQIqwDUdKOtRXZMObnszGcRtOKABzssT/ofzqL876QtGJ3IpColurmnUUjGRgeWO0Hy/ + AW1JC9CWMA+tcXPQGj8bHZkrkPHFK+KeXmiZTIlSWQdKqpXiXte9GQziTei+Bp70jfhBtFutANuh1SzO + q1yN9M+coMr6HIpY+lo6MYuOM6CIniaikfnla8JwKYFLWARm3a5SoprqgV9ixBhO4k1vQANPfROaQ28y + K2QErOZKFgWlQSU9gIspY9VrUKYvRUvUe6SpaDk+Bc3HJ6E1YTay1o0l41o7VIDbhYpJXBMuHmkDG+Af + JBEBd/+zbTdKmvugopioku+QyqmoTq9+He1JC9GWOFdAFXEUiZ4onNkwTkSNgayiyv8op6AKa3YmKYnx + +xrgHySxEX20yvfTjZ6pHa6eGdjomUauU+HinkqfUyexdlcKApZNQdhiRxxc5IiQhS8iaP5oBMwdDf85 + o/D1onex8qtYrHSNwQrXKHziEo3lG45j2fpILF1zRDVljpszMZ4gccH/LgXiy4jEbyneLrld2G2vuHh6 + xWHsrxH/pZEDiO/jN674Eurj9jPAUWAT7I7TwWYGEufv/xU/mxli9QCkfwP2I15ncmdDHAAAAABJRU5E + rkJggg== +</value> + </data> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>129</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/member_base_info_form.Designer.cs b/FLSystem/Forms/member_base_info_form.Designer.cs new file mode 100644 index 0000000..bbb0372 --- /dev/null +++ b/FLSystem/Forms/member_base_info_form.Designer.cs @@ -0,0 +1,944 @@ +namespace FLSystem.Forms +{ + partial class member_base_info_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.label32 = new System.Windows.Forms.Label(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.dateTimePicker7 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker6 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker5 = new System.Windows.Forms.DateTimePicker(); + this.label27 = new System.Windows.Forms.Label(); + this.label23 = new System.Windows.Forms.Label(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.label26 = new System.Windows.Forms.Label(); + this.label22 = new System.Windows.Forms.Label(); + this.memoEdit10 = new DevExpress.XtraEditors.MemoEdit(); + this.label31 = new System.Windows.Forms.Label(); + this.label29 = new System.Windows.Forms.Label(); + this.label25 = new System.Windows.Forms.Label(); + this.label21 = new System.Windows.Forms.Label(); + this.memoEdit21 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit22 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit20 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit19 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit4 = new DevExpress.XtraEditors.MemoEdit(); + this.label11 = new System.Windows.Forms.Label(); + this.memoEdit9 = new DevExpress.XtraEditors.MemoEdit(); + this.label24 = new System.Windows.Forms.Label(); + this.label20 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.memoEdit8 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit7 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit6 = new DevExpress.XtraEditors.MemoEdit(); + this.label8 = new System.Windows.Forms.Label(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl3 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl4 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl5 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.memoEdit18 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit14 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit11 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit3 = new DevExpress.XtraEditors.MemoEdit(); + this.label18 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.label17 = new System.Windows.Forms.Label(); + this.label19 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label16 = new System.Windows.Forms.Label(); + this.label30 = new System.Windows.Forms.Label(); + this.label28 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.memoEdit17 = new DevExpress.XtraEditors.MemoEdit(); + this.label15 = new System.Windows.Forms.Label(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit16 = new DevExpress.XtraEditors.MemoEdit(); + this.label4 = new System.Windows.Forms.Label(); + this.memoEdit15 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit2 = new DevExpress.XtraEditors.MemoEdit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit10.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit21.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit22.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit20.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit19.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit9.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit8.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit7.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl5)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit18.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit14.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit11.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit17.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit16.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit15.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.comboBoxEdit3); + this.groupBox1.Controls.Add(this.label32); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.linkLabel1); + this.groupBox1.Controls.Add(this.dateTimePicker7); + this.groupBox1.Controls.Add(this.dateTimePicker6); + this.groupBox1.Controls.Add(this.dateTimePicker1); + this.groupBox1.Controls.Add(this.dateTimePicker5); + this.groupBox1.Controls.Add(this.label27); + this.groupBox1.Controls.Add(this.label23); + this.groupBox1.Controls.Add(this.comboBoxEdit2); + this.groupBox1.Controls.Add(this.comboBoxEdit1); + this.groupBox1.Controls.Add(this.label26); + this.groupBox1.Controls.Add(this.label22); + this.groupBox1.Controls.Add(this.memoEdit10); + this.groupBox1.Controls.Add(this.label31); + this.groupBox1.Controls.Add(this.label29); + this.groupBox1.Controls.Add(this.label25); + this.groupBox1.Controls.Add(this.label21); + this.groupBox1.Controls.Add(this.memoEdit21); + this.groupBox1.Controls.Add(this.memoEdit22); + this.groupBox1.Controls.Add(this.memoEdit20); + this.groupBox1.Controls.Add(this.memoEdit19); + this.groupBox1.Controls.Add(this.memoEdit4); + this.groupBox1.Controls.Add(this.label11); + this.groupBox1.Controls.Add(this.memoEdit9); + this.groupBox1.Controls.Add(this.label24); + this.groupBox1.Controls.Add(this.label20); + this.groupBox1.Controls.Add(this.label10); + this.groupBox1.Controls.Add(this.label9); + this.groupBox1.Controls.Add(this.memoEdit8); + this.groupBox1.Controls.Add(this.memoEdit7); + this.groupBox1.Controls.Add(this.memoEdit6); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.memoEdit5); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.separatorControl2); + this.groupBox1.Controls.Add(this.separatorControl3); + this.groupBox1.Controls.Add(this.separatorControl4); + this.groupBox1.Controls.Add(this.separatorControl5); + this.groupBox1.Controls.Add(this.separatorControl1); + this.groupBox1.Controls.Add(this.memoEdit18); + this.groupBox1.Controls.Add(this.memoEdit14); + this.groupBox1.Controls.Add(this.memoEdit11); + this.groupBox1.Controls.Add(this.memoEdit3); + this.groupBox1.Controls.Add(this.label18); + this.groupBox1.Controls.Add(this.label14); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.label17); + this.groupBox1.Controls.Add(this.label19); + this.groupBox1.Controls.Add(this.label13); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label16); + this.groupBox1.Controls.Add(this.label30); + this.groupBox1.Controls.Add(this.label28); + this.groupBox1.Controls.Add(this.label12); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.memoEdit17); + this.groupBox1.Controls.Add(this.label15); + this.groupBox1.Controls.Add(this.memoEdit1); + this.groupBox1.Controls.Add(this.memoEdit16); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.memoEdit15); + this.groupBox1.Controls.Add(this.memoEdit2); + this.groupBox1.Location = new System.Drawing.Point(30, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(701, 638); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基 础 信 息 "; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Location = new System.Drawing.Point(152, 143); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(183, 20); + this.comboBoxEdit3.TabIndex = 50; + this.comboBoxEdit3.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // label32 + // + this.label32.AutoSize = true; + this.label32.Location = new System.Drawing.Point(79, 146); + this.label32.Name = "label32"; + this.label32.Size = new System.Drawing.Size(67, 14); + this.label32.TabIndex = 49; + this.label32.Text = "兑换类型:"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(153, 113); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(113, 22); + this.numericUpDown1.TabIndex = 48; + this.numericUpDown1.ValueChanged += new System.EventHandler(this.ChangeInput); + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(156, 222); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(183, 22); + this.comboBox1.TabIndex = 47; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(156, 197); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Properties.Mask.EditMask = "\\d+"; + this.textEdit1.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx; + this.textEdit1.Size = new System.Drawing.Size(183, 20); + this.textEdit1.TabIndex = 22; + this.textEdit1.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(280, 354); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(55, 14); + this.linkLabel1.TabIndex = 31; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "点击修改"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // dateTimePicker7 + // + this.dateTimePicker7.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker7.Enabled = false; + this.dateTimePicker7.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker7.Location = new System.Drawing.Point(156, 589); + this.dateTimePicker7.Name = "dateTimePicker7"; + this.dateTimePicker7.Size = new System.Drawing.Size(183, 22); + this.dateTimePicker7.TabIndex = 46; + // + // dateTimePicker6 + // + this.dateTimePicker6.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker6.Enabled = false; + this.dateTimePicker6.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker6.Location = new System.Drawing.Point(445, 561); + this.dateTimePicker6.Name = "dateTimePicker6"; + this.dateTimePicker6.Size = new System.Drawing.Size(183, 22); + this.dateTimePicker6.TabIndex = 46; + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(156, 530); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(183, 22); + this.dateTimePicker1.TabIndex = 46; + this.dateTimePicker1.ValueChanged += new System.EventHandler(this.ChangeInput); + // + // dateTimePicker5 + // + this.dateTimePicker5.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker5.Enabled = false; + this.dateTimePicker5.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker5.Location = new System.Drawing.Point(156, 561); + this.dateTimePicker5.Name = "dateTimePicker5"; + this.dateTimePicker5.Size = new System.Drawing.Size(183, 22); + this.dateTimePicker5.TabIndex = 46; + // + // label27 + // + this.label27.AutoSize = true; + this.label27.Location = new System.Drawing.Point(348, 593); + this.label27.Name = "label27"; + this.label27.Size = new System.Drawing.Size(91, 14); + this.label27.TabIndex = 42; + this.label27.Text = "自己发消息数:"; + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(372, 482); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(67, 14); + this.label23.TabIndex = 42; + this.label23.Text = "冻结金额:"; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Location = new System.Drawing.Point(442, 58); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(183, 20); + this.comboBoxEdit2.TabIndex = 20; + this.comboBoxEdit2.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(445, 224); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(183, 20); + this.comboBoxEdit1.TabIndex = 26; + this.comboBoxEdit1.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // label26 + // + this.label26.AutoSize = true; + this.label26.Location = new System.Drawing.Point(80, 593); + this.label26.Name = "label26"; + this.label26.Size = new System.Drawing.Size(67, 14); + this.label26.TabIndex = 42; + this.label26.Text = "最后拉黑:"; + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(80, 482); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(67, 14); + this.label22.TabIndex = 42; + this.label22.Text = "冻结数量:"; + // + // memoEdit10 + // + this.memoEdit10.Enabled = false; + this.memoEdit10.Location = new System.Drawing.Point(445, 401); + this.memoEdit10.Name = "memoEdit10"; + this.memoEdit10.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit10.Size = new System.Drawing.Size(183, 22); + this.memoEdit10.TabIndex = 43; + // + // label31 + // + this.label31.AutoSize = true; + this.label31.ForeColor = System.Drawing.Color.Gray; + this.label31.Location = new System.Drawing.Point(276, 117); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(176, 14); + this.label31.TabIndex = 42; + this.label31.Text = "% (值为0时,使用系统默认比例)"; + // + // label29 + // + this.label29.AutoSize = true; + this.label29.ForeColor = System.Drawing.Color.Gray; + this.label29.Location = new System.Drawing.Point(360, 536); + this.label29.Name = "label29"; + this.label29.Size = new System.Drawing.Size(257, 14); + this.label29.TabIndex = 42; + this.label29.Text = "(时间大于当前时间该用户将不能进行兑换操作)"; + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(348, 565); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(91, 14); + this.label25.TabIndex = 42; + this.label25.Text = "最后交谈时间:"; + // + // label21 + // + this.label21.AutoSize = true; + this.label21.Location = new System.Drawing.Point(360, 454); + this.label21.Name = "label21"; + this.label21.Size = new System.Drawing.Size(79, 14); + this.label21.TabIndex = 42; + this.label21.Text = "未收货金额:"; + // + // memoEdit21 + // + this.memoEdit21.Enabled = false; + this.memoEdit21.Location = new System.Drawing.Point(156, 478); + this.memoEdit21.Name = "memoEdit21"; + this.memoEdit21.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit21.Size = new System.Drawing.Size(183, 22); + this.memoEdit21.TabIndex = 44; + // + // memoEdit22 + // + this.memoEdit22.Enabled = false; + this.memoEdit22.Location = new System.Drawing.Point(445, 589); + this.memoEdit22.Name = "memoEdit22"; + this.memoEdit22.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit22.Size = new System.Drawing.Size(183, 22); + this.memoEdit22.TabIndex = 44; + // + // memoEdit20 + // + this.memoEdit20.Enabled = false; + this.memoEdit20.Location = new System.Drawing.Point(445, 478); + this.memoEdit20.Name = "memoEdit20"; + this.memoEdit20.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit20.Size = new System.Drawing.Size(183, 22); + this.memoEdit20.TabIndex = 44; + // + // memoEdit19 + // + this.memoEdit19.Enabled = false; + this.memoEdit19.Location = new System.Drawing.Point(445, 450); + this.memoEdit19.Name = "memoEdit19"; + this.memoEdit19.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit19.Size = new System.Drawing.Size(183, 22); + this.memoEdit19.TabIndex = 44; + // + // memoEdit4 + // + this.memoEdit4.Enabled = false; + this.memoEdit4.Location = new System.Drawing.Point(156, 450); + this.memoEdit4.Name = "memoEdit4"; + this.memoEdit4.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit4.Size = new System.Drawing.Size(183, 22); + this.memoEdit4.TabIndex = 44; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(56, 536); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(91, 14); + this.label11.TabIndex = 42; + this.label11.Text = "限制兑换时间:"; + // + // memoEdit9 + // + this.memoEdit9.Enabled = false; + this.memoEdit9.Location = new System.Drawing.Point(156, 401); + this.memoEdit9.Name = "memoEdit9"; + this.memoEdit9.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit9.Size = new System.Drawing.Size(183, 22); + this.memoEdit9.TabIndex = 44; + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(80, 565); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(67, 14); + this.label24.TabIndex = 42; + this.label24.Text = "注册时间:"; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(80, 454); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(67, 14); + this.label20.TabIndex = 42; + this.label20.Text = "待收货数:"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(372, 405); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(67, 14); + this.label10.TabIndex = 41; + this.label10.Text = "完成订单:"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(80, 405); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(67, 14); + this.label9.TabIndex = 42; + this.label9.Text = "其他奖励:"; + // + // memoEdit8 + // + this.memoEdit8.Enabled = false; + this.memoEdit8.Location = new System.Drawing.Point(445, 375); + this.memoEdit8.Name = "memoEdit8"; + this.memoEdit8.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit8.Size = new System.Drawing.Size(183, 22); + this.memoEdit8.TabIndex = 37; + // + // memoEdit7 + // + this.memoEdit7.Enabled = false; + this.memoEdit7.Location = new System.Drawing.Point(445, 350); + this.memoEdit7.Name = "memoEdit7"; + this.memoEdit7.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit7.Size = new System.Drawing.Size(183, 22); + this.memoEdit7.TabIndex = 38; + // + // memoEdit6 + // + this.memoEdit6.Enabled = false; + this.memoEdit6.Location = new System.Drawing.Point(156, 375); + this.memoEdit6.Name = "memoEdit6"; + this.memoEdit6.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit6.Size = new System.Drawing.Size(183, 22); + this.memoEdit6.TabIndex = 39; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(372, 379); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(67, 14); + this.label8.TabIndex = 33; + this.label8.Text = "提成奖励:"; + // + // memoEdit5 + // + this.memoEdit5.Enabled = false; + this.memoEdit5.Location = new System.Drawing.Point(156, 350); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit5.Size = new System.Drawing.Size(114, 22); + this.memoEdit5.TabIndex = 40; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(372, 354); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(67, 14); + this.label7.TabIndex = 34; + this.label7.Text = "购物积分:"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(80, 379); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(67, 14); + this.label6.TabIndex = 35; + this.label6.Text = "累计积分:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(80, 354); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(67, 14); + this.label5.TabIndex = 36; + this.label5.Text = "剩余积分:"; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(56, 171); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(595, 23); + this.separatorControl2.TabIndex = 32; + // + // separatorControl3 + // + this.separatorControl3.Location = new System.Drawing.Point(56, 325); + this.separatorControl3.Name = "separatorControl3"; + this.separatorControl3.Size = new System.Drawing.Size(595, 23); + this.separatorControl3.TabIndex = 31; + // + // separatorControl4 + // + this.separatorControl4.Location = new System.Drawing.Point(56, 501); + this.separatorControl4.Name = "separatorControl4"; + this.separatorControl4.Size = new System.Drawing.Size(595, 23); + this.separatorControl4.TabIndex = 31; + // + // separatorControl5 + // + this.separatorControl5.Location = new System.Drawing.Point(56, 425); + this.separatorControl5.Name = "separatorControl5"; + this.separatorControl5.Size = new System.Drawing.Size(595, 23); + this.separatorControl5.TabIndex = 31; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(56, 250); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(595, 23); + this.separatorControl1.TabIndex = 31; + // + // memoEdit18 + // + this.memoEdit18.Location = new System.Drawing.Point(445, 275); + this.memoEdit18.Name = "memoEdit18"; + this.memoEdit18.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit18.Size = new System.Drawing.Size(183, 22); + this.memoEdit18.TabIndex = 28; + this.memoEdit18.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // memoEdit14 + // + this.memoEdit14.Enabled = false; + this.memoEdit14.Location = new System.Drawing.Point(445, 196); + this.memoEdit14.Name = "memoEdit14"; + this.memoEdit14.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit14.Size = new System.Drawing.Size(183, 22); + this.memoEdit14.TabIndex = 23; + // + // memoEdit11 + // + this.memoEdit11.Location = new System.Drawing.Point(153, 85); + this.memoEdit11.Name = "memoEdit11"; + this.memoEdit11.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit11.Size = new System.Drawing.Size(475, 22); + this.memoEdit11.TabIndex = 27; + this.memoEdit11.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // memoEdit3 + // + this.memoEdit3.Enabled = false; + this.memoEdit3.Location = new System.Drawing.Point(153, 57); + this.memoEdit3.Name = "memoEdit3"; + this.memoEdit3.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit3.Size = new System.Drawing.Size(183, 22); + this.memoEdit3.TabIndex = 27; + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(68, 279); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(79, 14); + this.label18.TabIndex = 7; + this.label18.Text = "身份证名称:"; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(80, 200); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(67, 14); + this.label14.TabIndex = 8; + this.label14.Text = "推荐人ID:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(77, 34); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(67, 14); + this.label1.TabIndex = 0; + this.label1.Text = "用户账号:"; + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(68, 305); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(79, 14); + this.label17.TabIndex = 10; + this.label17.Text = "支付宝姓名:"; + // + // label19 + // + this.label19.AutoSize = true; + this.label19.Location = new System.Drawing.Point(348, 227); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(91, 14); + this.label19.TabIndex = 12; + this.label19.Text = "锁定会员分组:"; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(92, 225); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(55, 14); + this.label13.TabIndex = 12; + this.label13.Text = "分组ID:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(369, 34); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 11; + this.label2.Text = "用户昵称:"; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(360, 279); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(79, 14); + this.label16.TabIndex = 15; + this.label16.Text = "身份证号码:"; + // + // label30 + // + this.label30.AutoSize = true; + this.label30.Location = new System.Drawing.Point(77, 117); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(67, 14); + this.label30.TabIndex = 14; + this.label30.Text = "私人比例:"; + // + // label28 + // + this.label28.AutoSize = true; + this.label28.Location = new System.Drawing.Point(77, 89); + this.label28.Name = "label28"; + this.label28.Size = new System.Drawing.Size(67, 14); + this.label28.TabIndex = 14; + this.label28.Text = "账户备注:"; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(360, 200); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(79, 14); + this.label12.TabIndex = 16; + this.label12.Text = "推荐人昵称:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(77, 61); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(67, 14); + this.label3.TabIndex = 14; + this.label3.Text = "账号类型:"; + // + // memoEdit17 + // + this.memoEdit17.Location = new System.Drawing.Point(156, 275); + this.memoEdit17.Name = "memoEdit17"; + this.memoEdit17.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit17.Size = new System.Drawing.Size(183, 22); + this.memoEdit17.TabIndex = 27; + this.memoEdit17.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(360, 305); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(79, 14); + this.label15.TabIndex = 18; + this.label15.Text = "支付宝账号:"; + // + // memoEdit1 + // + this.memoEdit1.Enabled = false; + this.memoEdit1.Location = new System.Drawing.Point(153, 30); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit1.Size = new System.Drawing.Size(183, 22); + this.memoEdit1.TabIndex = 5; + // + // memoEdit16 + // + this.memoEdit16.Location = new System.Drawing.Point(445, 301); + this.memoEdit16.Name = "memoEdit16"; + this.memoEdit16.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit16.Size = new System.Drawing.Size(183, 22); + this.memoEdit16.TabIndex = 30; + this.memoEdit16.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(369, 61); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 14); + this.label4.TabIndex = 17; + this.label4.Text = "账号状态:"; + // + // memoEdit15 + // + this.memoEdit15.Location = new System.Drawing.Point(156, 301); + this.memoEdit15.Name = "memoEdit15"; + this.memoEdit15.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit15.Size = new System.Drawing.Size(183, 22); + this.memoEdit15.TabIndex = 29; + this.memoEdit15.EditValueChanged += new System.EventHandler(this.ChangeInput); + // + // memoEdit2 + // + this.memoEdit2.Enabled = false; + this.memoEdit2.Location = new System.Drawing.Point(442, 30); + this.memoEdit2.Name = "memoEdit2"; + this.memoEdit2.Properties.ScrollBars = System.Windows.Forms.ScrollBars.None; + this.memoEdit2.Size = new System.Drawing.Size(183, 22); + this.memoEdit2.TabIndex = 6; + // + // member_base_info_form + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(757, 662); + this.Controls.Add(this.groupBox1); + this.Name = "member_base_info_form"; + this.Text = "用户基础信息"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.member_base_info_form_FormClosing); + this.Load += new System.EventHandler(this.member_base_info_form_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit10.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit21.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit22.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit20.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit19.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit9.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit8.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit7.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl5)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit18.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit14.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit11.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit17.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit16.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit15.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.MemoEdit memoEdit10; + private DevExpress.XtraEditors.MemoEdit memoEdit9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Label label9; + private DevExpress.XtraEditors.MemoEdit memoEdit8; + private DevExpress.XtraEditors.MemoEdit memoEdit7; + private DevExpress.XtraEditors.MemoEdit memoEdit6; + private System.Windows.Forms.Label label8; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label5; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private DevExpress.XtraEditors.SeparatorControl separatorControl3; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private DevExpress.XtraEditors.MemoEdit memoEdit18; + private DevExpress.XtraEditors.MemoEdit memoEdit14; + private DevExpress.XtraEditors.MemoEdit memoEdit3; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.MemoEdit memoEdit17; + private System.Windows.Forms.Label label15; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.MemoEdit memoEdit16; + private System.Windows.Forms.Label label4; + private DevExpress.XtraEditors.MemoEdit memoEdit15; + private DevExpress.XtraEditors.MemoEdit memoEdit2; + private System.Windows.Forms.Label label19; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.SeparatorControl separatorControl5; + private System.Windows.Forms.Label label20; + private System.Windows.Forms.Label label23; + private System.Windows.Forms.Label label22; + private System.Windows.Forms.Label label21; + private System.Windows.Forms.LinkLabel linkLabel1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private System.Windows.Forms.DateTimePicker dateTimePicker7; + private System.Windows.Forms.DateTimePicker dateTimePicker6; + private System.Windows.Forms.DateTimePicker dateTimePicker5; + private System.Windows.Forms.Label label27; + private System.Windows.Forms.Label label26; + private System.Windows.Forms.Label label25; + private System.Windows.Forms.Label label24; + private DevExpress.XtraEditors.SeparatorControl separatorControl4; + private DevExpress.XtraEditors.MemoEdit memoEdit21; + private DevExpress.XtraEditors.MemoEdit memoEdit20; + private DevExpress.XtraEditors.MemoEdit memoEdit19; + private DevExpress.XtraEditors.MemoEdit memoEdit4; + private DevExpress.XtraEditors.MemoEdit memoEdit22; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.MemoEdit memoEdit11; + private System.Windows.Forms.Label label28; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label29; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.Label label30; + private System.Windows.Forms.Label label31; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private System.Windows.Forms.Label label32; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/member_base_info_form.cs b/FLSystem/Forms/member_base_info_form.cs new file mode 100644 index 0000000..3455122 --- /dev/null +++ b/FLSystem/Forms/member_base_info_form.cs @@ -0,0 +1,314 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using SqlSugar; +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Enums; +using Api.Framework.Tools; +using Grant.Framework; +using System.Threading; +using CsharpHttpHelper; + +namespace FLSystem.Forms +{ + public partial class member_base_info_form : BaseForm + { + private SqlSugarClient session = null; + long uid = 0; + fl_member_info member = null; + + public member_base_info_form(long uid) + { + InitializeComponent(); + this.uid = uid; + session = ApiClient.GetSession(); + } + private MemberType old_status; + private void member_base_info_form_Load(object sender, EventArgs e) + { + try + { + comboBoxEdit2.Properties.Items.Clear(); + foreach (int v in Enum.GetValues(typeof(MemberType))) + { + string strName = Enum.GetName(typeof(MemberType), v); + comboBoxEdit2.Properties.Items.AddRange(new object[] { strName }); + } + + comboBoxEdit3.Properties.Items.Clear(); + foreach (int v in Enum.GetValues(typeof(ExchangeType))) + { + string strName = Enum.GetName(typeof(ExchangeType), v); + comboBoxEdit3.Properties.Items.AddRange(new object[] { strName }); + } + + comboBoxEdit1.Properties.Items.Clear(); + foreach (int v in Enum.GetValues(typeof(SwitchType))) + { + string strName = Enum.GetName(typeof(SwitchType), v); + comboBoxEdit1.Properties.Items.AddRange(new object[] { strName }); + } + + var groups = session.FindGroups(); + if (groups != null && groups.Count != 0) + { + comboBox1.DataSource = groups; + comboBox1.DisplayMember = "name"; + comboBox1.Tag = groups; + } + loadMemberInfo(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + /// <summary> + /// 加载数据 + /// </summary> + /// <param name="noAssignment">是否重新赋值可修改的控件数据</param> + private void loadMemberInfo(bool noAssignment = true) + { + try + { + if (uid != 0) + { + member = session.FindMemberInfoById(uid); + if (member == null) throw new Exception("用户数据存在异常"); + old_status = member.status; + memoEdit1.Text = member.username; + memoEdit2.Text = member.usernick; + memoEdit3.Text = member.robot_type.ToString(); + textEdit1.Text = member.inviter_id.ToString(); + if (comboBox1.Tag != null) + { + var groups = comboBox1.Tag as List<fl_member_group>; + var group = groups.FirstOrDefault(f => f.id == member.group_id); + comboBox1.Text = group != null ? group.name : groups.FirstOrDefault().name; + } + + memoEdit11.Text = member.remark; + + memoEdit5.Text = member.cur_point.ToString("0.00"); + memoEdit7.Text = member.buy_point.ToString("0.00"); + memoEdit6.Text = member.sum_point.ToString("0.00"); + memoEdit8.Text = member.ext_point.ToString("0.00"); + memoEdit9.Text = member.rew_point.ToString("0.00"); + memoEdit10.Text = member.finish_order.ToString(); + dateTimePicker5.Value = member.crt_time; + dateTimePicker6.Value = member.upd_time; + dateTimePicker7.Value = (member.blackout_time == DateTime.MinValue ? DateTime.Parse("1900-01-01 00:00:00") : member.blackout_time); + memoEdit22.Text = member.chat_count.ToString(); + + var dic_t = FindOrderTotalInfo(uid, tokenSource.Token); + dic_t.ContinueWith(f => + { + var dic = f.Result; + + this.Invoke(new Action(() => + { + try + { + memoEdit4.Text = (dic == null ? "异常" : dic["count_pay"].ToString("0.00"));//待收货数 + memoEdit19.Text = (dic == null ? "异常" : dic["point_pay"].ToString("0.00"));//未收货金额 + memoEdit21.Text = (dic == null ? "异常" : dic["count_sleep"].ToString("0.00"));//冻结数量 + memoEdit20.Text = (dic == null ? "异常" : dic["point_sleep"].ToString("0.00"));//冻结金额 + } + catch (Exception) + { + } + })); + }, tokenSource.Token); + + if (noAssignment) + { + comboBoxEdit2.SelectedIndex = (int)member.status; + comboBoxEdit3.SelectedIndex = (int)member.exchange_type; + comboBoxEdit1.SelectedIndex = (int)member.ignore_group_update; + memoEdit17.Text = member.identity_name; + memoEdit18.Text = member.identity_card; + + memoEdit15.Text = member.alipay_name; + memoEdit16.Text = member.alipay_num; + dateTimePicker1.Value = member.ban_exchange_time; + numericUpDown1.Value = (decimal)member.private_ratio; + } + + is_loding = true; + } + } + catch (Exception ex) + { + if (!this.IsDisposed) + ShowError(ex); + } + } + + /// <summary> + /// 统计阿里妈妈,京东,拼多多,(付款状态订单合计/冻结状态订单合计/付款和冻结状态订单合计) + /// </summary> + /// <param name="tableName">表名</param> + /// <param name="uid">用户id</param> + /// <returns></returns> + private Task<Dictionary<string, decimal>> FindOrderTotalInfo(long uid, CancellationToken Token) + { + return Task.Run(() => + { + try + { + var session = ApiClient.GetSession(); + var result = session.FindTable($"select round(COALESCE(sum(db_userpoint),0) ,2) as sum ,count(id) as count from fl_order_alimama where db_userid = @id and db_status = 1001 UNION ALL select round(COALESCE(sum(db_userpoint), 0), 2) as sum, count(id) as count from fl_order_alimama where db_userid = @id and db_status = 1005 union all select round(COALESCE(sum(db_userpoint),0) ,2) as sum ,count(id) as count from fl_order_jingdong where db_userid = @id and db_status = 1001 UNION ALL select round(COALESCE(sum(db_userpoint), 0), 2) as sum, count(id) as count from fl_order_jingdong where db_userid = @id and db_status = 1005 union all select round(COALESCE(sum(db_userpoint),0) ,2) as sum ,count(id) as count from fl_order_pinduoduo where db_userid = @id and db_status = 1001 UNION ALL select round(COALESCE(sum(db_userpoint), 0), 2) as sum, count(id) as count from fl_order_pinduoduo where db_userid = @id and db_status = 1005", new { id = uid }); + if (result.Rows.Count != 0 && result.Rows.Count == 6) + { + var dic = new Dictionary<string, decimal>(); + + var ali_point_sleep = decimal.Parse(result.Rows[0]["sum"].ToString()); + var ali_count_sleep = int.Parse(result.Rows[0]["count"].ToString()); + var ali_point_pay = decimal.Parse(result.Rows[1]["sum"].ToString()); + var ali_count_pay = int.Parse(result.Rows[1]["count"].ToString()); + + var jd_point_sleep = decimal.Parse(result.Rows[2]["sum"].ToString()); + var jd_count_sleep = int.Parse(result.Rows[2]["count"].ToString()); + var jd_point_pay = decimal.Parse(result.Rows[3]["sum"].ToString()); + var jd_count_pay = int.Parse(result.Rows[3]["count"].ToString()); + + var pdd_point_sleep = decimal.Parse(result.Rows[4]["sum"].ToString()); + var pdd_count_sleep = int.Parse(result.Rows[4]["count"].ToString()); + var pdd_point_pay = decimal.Parse(result.Rows[5]["sum"].ToString()); + var pdd_count_pay = int.Parse(result.Rows[5]["count"].ToString()); + + dic.Add("point_sleep", ali_point_sleep + jd_point_sleep + pdd_point_sleep); + dic.Add("count_sleep", ali_count_sleep + jd_count_sleep + pdd_count_sleep); + dic.Add("point_pay", ali_point_pay + jd_point_pay + pdd_point_pay); + dic.Add("count_pay", ali_count_pay + jd_count_pay + pdd_count_pay); + + return dic; + } + } + catch (Exception ex) + { } + return null; + }, Token); + } + + + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + DialogResult dialogResult = DialogResult.No; + + CsharpHttpHelper.IniHelper Config = new CsharpHttpHelper.IniHelper(HttpExtend.MapFile("系统配置.ini", "Config")); + var pass = Config.GetValue("帐号信息", "密码2"); + if (!string.IsNullOrWhiteSpace(pass)) + { + var v = new VerifyPassForm(pass); + dialogResult = v.ShowDialog(); + } + else + { + var verify = new Grant.Framework.VerifyPassForm(); + dialogResult = verify.ShowDialog(); + } + + if (dialogResult == DialogResult.OK) + { + if (uid == 0) throw new Exception("当前窗体数据异常"); + var changepoint = new change_point_form(uid); + changepoint.ShowDialog(); + loadMemberInfo(false); + } + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void member_base_info_form_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + memoEdit17.Focus(); + if (is_change && XtraMessageBox.Show("您当前做了修改操作,是否保存?", "系统提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + member.status = (MemberType)comboBoxEdit2.SelectedIndex; + member.exchange_type = (ExchangeType)comboBoxEdit3.SelectedIndex; + + member.ignore_group_update = (SwitchType)comboBoxEdit1.SelectedIndex; + member.identity_name = memoEdit17.Text.Trim(); + member.ban_exchange_time = dateTimePicker1.Value; + member.private_ratio = (double)numericUpDown1.Value; + member.identity_card = memoEdit18.Text.Trim(); + member.alipay_name = memoEdit15.Text.Trim(); + member.alipay_num = memoEdit16.Text.Trim(); + member.inviter_id = int.Parse(textEdit1.Text); + if (comboBox1.SelectedValue != null) + member.group_id = (comboBox1.SelectedValue as fl_member_group).id; + member.remark = memoEdit11.Text; + + session.SaveOrUpdate(member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + } + tokenSource.Cancel(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + private bool is_change = false; + private bool is_loding = false; + + /// <summary> + /// 现在有8个控件可以赋值,如果8个值都没有被修改那么关闭的时候将不提示是否保存提示 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void ChangeInput(object sender, EventArgs e) + { + if (is_loding) + is_change = true; + + try + { + if (sender is TextEdit) + { + var edit = sender as TextEdit; + if (edit.Name == "textEdit1") + { + try + { + if (edit.Text.Trim() == "0") throw new Exception("无"); + var session = ApiClient.GetSession(); + var member = session.FindMemberInfoById(int.Parse(edit.Text.Trim())); + if (member == null) throw new Exception("数据异常"); + memoEdit14.Text = member.usernick; + } + catch (Exception ex) + { + memoEdit14.Text = ex.Message; + } + } + } + } + catch (Exception) + { } + } + + } +} \ No newline at end of file diff --git a/FLSystem/Forms/member_base_info_form.resx b/FLSystem/Forms/member_base_info_form.resx new file mode 100644 index 0000000..d3addf3 --- /dev/null +++ b/FLSystem/Forms/member_base_info_form.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>25</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/member_inviter_control.Designer.cs b/FLSystem/Forms/member_inviter_control.Designer.cs new file mode 100644 index 0000000..7d93ced --- /dev/null +++ b/FLSystem/Forms/member_inviter_control.Designer.cs @@ -0,0 +1,473 @@ +namespace FLSystem.Forms +{ + partial class member_inviter_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(member_inviter_control)); + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // panelControl1 + // + this.panelControl1.Controls.Add(this.groupControl1); + this.panelControl1.Controls.Add(this.pageControl1); + this.panelControl1.Controls.Add(this.gridControl1); + this.panelControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panelControl1.Location = new System.Drawing.Point(0, 0); + this.panelControl1.Name = "panelControl1"; + this.panelControl1.Size = new System.Drawing.Size(821, 501); + this.panelControl1.TabIndex = 0; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(2, 2); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(817, 76); + this.groupControl1.TabIndex = 4; + this.groupControl1.Text = "搜索条件"; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.EditValue = "最近新增"; + this.comboBoxEdit2.Location = new System.Drawing.Point(520, 35); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "最近新增", + "最近聊天", + "最早聊天", + "消费最多"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(85, 20); + this.comboBoxEdit2.TabIndex = 8; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(457, 38); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 7; + this.labelControl2.Text = "排序方式:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(55, 38); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(621, 32); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(99, 26); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(275, 35); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "客户账号", + "客户昵称", + "客户编号", + "上级账号", + "上级昵称", + "上级编号", + "支付宝账号", + "支付宝姓名"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(109, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(99, 35); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(166, 20); + this.textEdit1.TabIndex = 1; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(2, 466); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(817, 33); + this.pageControl1.TabIndex = 3; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(0, 84); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(821, 380); + this.gridControl1.TabIndex = 2; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn6, + this.gridColumn2, + this.gridColumn3, + this.gridColumn18, + this.gridColumn17, + this.gridColumn16, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn4, + this.gridColumn5, + this.gridColumn19, + this.gridColumn20, + this.gridColumn7, + this.gridColumn8, + this.gridColumn9, + this.gridColumn10, + this.gridColumn11}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn1 + // + this.gridColumn1.Caption = "编号"; + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 46; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户类型"; + this.gridColumn6.FieldName = "robot_type"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 1; + this.gridColumn6.Width = 80; + // + // gridColumn2 + // + this.gridColumn2.Caption = "用户名"; + this.gridColumn2.FieldName = "username"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 150; + // + // gridColumn3 + // + this.gridColumn3.Caption = "昵称"; + this.gridColumn3.FieldName = "usernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 150; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn18.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "备注"; + this.gridColumn18.FieldName = "remark"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 4; + this.gridColumn18.Width = 120; + // + // gridColumn17 + // + this.gridColumn17.Caption = "状态"; + this.gridColumn17.FieldName = "status"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + // + // gridColumn16 + // + this.gridColumn16.Caption = "剩余积分"; + this.gridColumn16.FieldName = "cur_point"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 6; + this.gridColumn16.Width = 80; + // + // gridColumn12 + // + this.gridColumn12.Caption = "消费奖励(共)"; + this.gridColumn12.FieldName = "buy_point"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 7; + this.gridColumn12.Width = 90; + // + // gridColumn13 + // + this.gridColumn13.Caption = "推荐提成(共)"; + this.gridColumn13.FieldName = "ext_point"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 8; + this.gridColumn13.Width = 90; + // + // gridColumn14 + // + this.gridColumn14.Caption = "其他奖励(共)"; + this.gridColumn14.FieldName = "rew_point"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 9; + this.gridColumn14.Width = 90; + // + // gridColumn15 + // + this.gridColumn15.Caption = "累计积分(共)"; + this.gridColumn15.FieldName = "sum_point"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 10; + this.gridColumn15.Width = 90; + // + // gridColumn4 + // + this.gridColumn4.Caption = "支付宝账号"; + this.gridColumn4.FieldName = "alipay_num"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 11; + this.gridColumn4.Width = 150; + // + // gridColumn5 + // + this.gridColumn5.Caption = "支付宝姓名"; + this.gridColumn5.FieldName = "alipay_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 12; + this.gridColumn5.Width = 80; + // + // gridColumn19 + // + this.gridColumn19.Caption = "身份证名称"; + this.gridColumn19.FieldName = "identity_name"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 13; + // + // gridColumn20 + // + this.gridColumn20.Caption = "身份证号码"; + this.gridColumn20.FieldName = "identity_card"; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 14; + // + // gridColumn7 + // + this.gridColumn7.Caption = "邀请人编号"; + this.gridColumn7.FieldName = "inviter_id"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 15; + this.gridColumn7.Width = 80; + // + // gridColumn8 + // + this.gridColumn8.Caption = "分组等级"; + this.gridColumn8.FieldName = "gridColumn8"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 16; + this.gridColumn8.Width = 120; + // + // gridColumn9 + // + this.gridColumn9.Caption = "机器人账号"; + this.gridColumn9.FieldName = "robot_name"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 17; + this.gridColumn9.Width = 150; + // + // gridColumn10 + // + this.gridColumn10.Caption = "最后沟通时间"; + this.gridColumn10.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn10.FieldName = "upd_time"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 18; + this.gridColumn10.Width = 150; + // + // gridColumn11 + // + this.gridColumn11.Caption = "注册时间"; + this.gridColumn11.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn11.FieldName = "crt_time"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 19; + this.gridColumn11.Width = 150; + // + // member_inviter_control + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(821, 501); + this.Controls.Add(this.panelControl1); + this.Name = "member_inviter_control"; + this.Text = "下级列表"; + this.Load += new System.EventHandler(this.member_inviter_control_Load); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.PanelControl panelControl1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/member_inviter_control.cs b/FLSystem/Forms/member_inviter_control.cs new file mode 100644 index 0000000..072a4cb --- /dev/null +++ b/FLSystem/Forms/member_inviter_control.cs @@ -0,0 +1,175 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class member_inviter_control : BaseForm + { + private int id = 0; + public member_inviter_control(int id) + { + InitializeComponent(); + this.id = id; + } + + List<fl_member_group> groups = null; + + private void member_inviter_control_Load(object sender, EventArgs e) + { + try + { + if (id != 0) + { + var session = ApiClient.GetSession(); + var member = session.FindMemberInfoById(id); + if (member == null) return; + + this.pageControl1.Bind(delegate (int page, int pagesize) + { + try + { + session = ApiClient.GetSession(); + this.groups = session.FindGroups(); + var map = session.NewParamMap(); + map.setPageParamters(page, pagesize); + string where = string.Empty; + where = " where inviter_id = @inviter_id"; + map.setParameter("inviter_id", member.id); + if (!string.IsNullOrEmpty(this.textEdit1.Text)) + { + switch (this.comboBoxEdit1.Text) + { + case "客户账号": + { + where += " and username = @username "; + map.setParameter("username", this.textEdit1.Text); + break; + } + case "客户昵称": + { + where += " and usernick like @usernick or remark like @remark"; + map.setParameter("usernick", "%" + this.textEdit1.Text + "%"); + map.setParameter("remark", "%" + this.textEdit1.Text + "%"); + break; + } + case "客户编号": + { + where += " and id = @id "; + map.setParameter("id", this.textEdit1.Text); + break; + } + case "支付宝账号": + { + where += " and alipay_num = @alipay_num"; + map.setParameter("alipay_num", this.textEdit1.Text); + break; + } + case "支付宝姓名": + { + where += " and alipay_name = @alipay_name"; + map.setParameter("alipay_name", this.textEdit1.Text); + break; + } + case "上级编号": + { + where += " and inviter_id = @inviter_id"; + map.setParameter("inviter_id", this.textEdit1.Text); + break; + } + case "上级账号": + { + var friend = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = this.textEdit1.Text }); + where += " and inviter_id = @inviter_id"; + map.setParameter(" inviter_id", friend != null ? friend.id : 0); + break; + } + case "上级昵称": + { + var friend = session.FindSingle<fl_member_info>("usernick like @usernick", new { usernick = "%" + this.textEdit1.Text + "%" }); + where += " and inviter_id = @inviter_id"; + map.setParameter("inviter_id", friend != null ? friend.id : 0); + break; + } + } + } + + switch (this.comboBoxEdit2.Text) + { + case "最近新增": + { + map.setOrderFields("crt_time", true); + break; + } + case "最早聊天": + { + map.setOrderFields("upd_time", true); + break; + } + case "最近聊天": + { + map.setOrderFields("upd_time", false); + break; + } + + case "消费最多": + { + map.setOrderFields("buy_point", true); + break; + } + } + var rest = session.FindPage<fl_member_info>($"select * from fl_member_info {where} ", map); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = rest.DataList, Total = rest.Total }; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "搜索标题", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = null, Total = 0 }; + + }, this.gridControl1, 50, true, true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + if (e.Column.Caption == "邀请人编号" && e.Value.ToString() == "0") e.DisplayText = "无"; + } + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + if (e.Column.Caption == "分组等级") + { + var row = e.Row as fl_member_info; + if (row != null) + { + var group = groups.FirstOrDefault(f => f.id == row.group_id); + e.Value = group == null ? "未分组" : group.name; + } + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.textEdit1.Enabled = comboBoxEdit1.SelectedIndex != 0; + if (!textEdit1.Enabled) textEdit1.Text = string.Empty; + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/member_inviter_control.resx b/FLSystem/Forms/member_inviter_control.resx new file mode 100644 index 0000000..bc5d4fb --- /dev/null +++ b/FLSystem/Forms/member_inviter_control.resx @@ -0,0 +1,145 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/member_manage_control.Designer.cs b/FLSystem/Forms/member_manage_control.Designer.cs new file mode 100644 index 0000000..cae50fe --- /dev/null +++ b/FLSystem/Forms/member_manage_control.Designer.cs @@ -0,0 +1,771 @@ +namespace FLSystem.Forms +{ + partial class member_manage_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(member_manage_control)); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改资料ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.设置私人信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.推荐列表ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看平台订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.淘宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.拼多多订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.京东订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.抖音联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.苏宁易购订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.快手联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看积分信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.检测是否为云黑名单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.添加到云黑名单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.系统人工兑换类型ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(0, 82); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(868, 355); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改资料ToolStripMenuItem, + this.设置私人信息ToolStripMenuItem, + this.推荐列表ToolStripMenuItem, + this.查看平台订单ToolStripMenuItem, + this.查看积分信息ToolStripMenuItem, + this.toolStripSeparator1, + this.检测是否为云黑名单ToolStripMenuItem, + this.添加到云黑名单ToolStripMenuItem, + this.系统人工兑换类型ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(191, 208); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 修改资料ToolStripMenuItem + // + this.修改资料ToolStripMenuItem.Checked = true; + this.修改资料ToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.修改资料ToolStripMenuItem.Name = "修改资料ToolStripMenuItem"; + this.修改资料ToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this.修改资料ToolStripMenuItem.Text = "修改资料"; + this.修改资料ToolStripMenuItem.Click += new System.EventHandler(this.修改资料ToolStripMenuItem_Click); + // + // 设置私人信息ToolStripMenuItem + // + this.设置私人信息ToolStripMenuItem.Name = "设置私人信息ToolStripMenuItem"; + this.设置私人信息ToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this.设置私人信息ToolStripMenuItem.Text = "设置私人信息"; + this.设置私人信息ToolStripMenuItem.Click += new System.EventHandler(this.设置私人信息ToolStripMenuItem_Click); + // + // 推荐列表ToolStripMenuItem + // + this.推荐列表ToolStripMenuItem.Name = "推荐列表ToolStripMenuItem"; + this.推荐列表ToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this.推荐列表ToolStripMenuItem.Text = "查看下级列表"; + this.推荐列表ToolStripMenuItem.Click += new System.EventHandler(this.推荐列表ToolStripMenuItem_Click); + // + // 查看平台订单ToolStripMenuItem + // + this.查看平台订单ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.淘宝订单ToolStripMenuItem, + this.拼多多订单ToolStripMenuItem, + this.京东订单ToolStripMenuItem, + this.唯品联盟订单ToolStripMenuItem, + this.抖音联盟订单ToolStripMenuItem, + this.苏宁易购订单ToolStripMenuItem, + this.快手联盟订单ToolStripMenuItem}); + this.查看平台订单ToolStripMenuItem.Name = "查看平台订单ToolStripMenuItem"; + this.查看平台订单ToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this.查看平台订单ToolStripMenuItem.Text = "查看平台订单"; + // + // 淘宝订单ToolStripMenuItem + // + this.淘宝订单ToolStripMenuItem.Name = "淘宝订单ToolStripMenuItem"; + this.淘宝订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.淘宝订单ToolStripMenuItem.Text = "阿里妈妈订单"; + this.淘宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 拼多多订单ToolStripMenuItem + // + this.拼多多订单ToolStripMenuItem.Name = "拼多多订单ToolStripMenuItem"; + this.拼多多订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.拼多多订单ToolStripMenuItem.Text = "多多进宝订单"; + this.拼多多订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 京东订单ToolStripMenuItem + // + this.京东订单ToolStripMenuItem.Name = "京东订单ToolStripMenuItem"; + this.京东订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.京东订单ToolStripMenuItem.Text = "京东联盟订单"; + this.京东订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 唯品联盟订单ToolStripMenuItem + // + this.唯品联盟订单ToolStripMenuItem.Name = "唯品联盟订单ToolStripMenuItem"; + this.唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.唯品联盟订单ToolStripMenuItem.Text = "唯品联盟订单"; + this.唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 抖音联盟订单ToolStripMenuItem + // + this.抖音联盟订单ToolStripMenuItem.Name = "抖音联盟订单ToolStripMenuItem"; + this.抖音联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.抖音联盟订单ToolStripMenuItem.Text = "抖音联盟订单"; + this.抖音联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 苏宁易购订单ToolStripMenuItem + // + this.苏宁易购订单ToolStripMenuItem.Name = "苏宁易购订单ToolStripMenuItem"; + this.苏宁易购订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.苏宁易购订单ToolStripMenuItem.Text = "苏宁易购订单"; + this.苏宁易购订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 快手联盟订单ToolStripMenuItem + // + this.快手联盟订单ToolStripMenuItem.Name = "快手联盟订单ToolStripMenuItem"; + this.快手联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.快手联盟订单ToolStripMenuItem.Text = "快手联盟订单"; + this.快手联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 查看积分信息ToolStripMenuItem + // + this.查看积分信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.积分日志ToolStripMenuItem, + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.查看积分信息ToolStripMenuItem.Name = "查看积分信息ToolStripMenuItem"; + this.查看积分信息ToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this.查看积分信息ToolStripMenuItem.Text = "查看积分信息"; + // + // 积分日志ToolStripMenuItem + // + this.积分日志ToolStripMenuItem.Name = "积分日志ToolStripMenuItem"; + this.积分日志ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.积分日志ToolStripMenuItem.Text = "积分日志"; + this.积分日志ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.积分ToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(187, 6); + // + // 检测是否为云黑名单ToolStripMenuItem + // + this.检测是否为云黑名单ToolStripMenuItem.Name = "检测是否为云黑名单ToolStripMenuItem"; + this.检测是否为云黑名单ToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this.检测是否为云黑名单ToolStripMenuItem.Text = "检测是否为云黑名单"; + this.检测是否为云黑名单ToolStripMenuItem.Click += new System.EventHandler(this.检测是否为云黑名单ToolStripMenuItem_Click); + // + // 添加到云黑名单ToolStripMenuItem + // + this.添加到云黑名单ToolStripMenuItem.Name = "添加到云黑名单ToolStripMenuItem"; + this.添加到云黑名单ToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this.添加到云黑名单ToolStripMenuItem.Text = "添加/删除 - 云黑名"; + this.添加到云黑名单ToolStripMenuItem.Click += new System.EventHandler(this.添加到云黑名单ToolStripMenuItem_Click); + // + // 系统人工兑换类型ToolStripMenuItem + // + this.系统人工兑换类型ToolStripMenuItem.Name = "系统人工兑换类型ToolStripMenuItem"; + this.系统人工兑换类型ToolStripMenuItem.Size = new System.Drawing.Size(190, 22); + this.系统人工兑换类型ToolStripMenuItem.Text = "系统/人工 - 兑换类型"; + this.系统人工兑换类型ToolStripMenuItem.Click += new System.EventHandler(this.系统人工兑换类型ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn6, + this.gridColumn2, + this.gridColumn23, + this.gridColumn3, + this.gridColumn18, + this.gridColumn17, + this.gridColumn16, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn21, + this.gridColumn24, + this.gridColumn25, + this.gridColumn4, + this.gridColumn5, + this.gridColumn19, + this.gridColumn20, + this.gridColumn7, + this.gridColumn8, + this.gridColumn9, + this.gridColumn22, + this.gridColumn10, + this.gridColumn11}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn1 + // + this.gridColumn1.Caption = "编号"; + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 46; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户类型"; + this.gridColumn6.FieldName = "robot_type"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 1; + this.gridColumn6.Width = 80; + // + // gridColumn2 + // + this.gridColumn2.Caption = "用户名"; + this.gridColumn2.FieldName = "username"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 130; + // + // gridColumn23 + // + this.gridColumn23.Caption = "微信号"; + this.gridColumn23.FieldName = "wechatid"; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 3; + this.gridColumn23.Width = 102; + // + // gridColumn3 + // + this.gridColumn3.Caption = "昵称"; + this.gridColumn3.FieldName = "usernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 4; + this.gridColumn3.Width = 150; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn18.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "备注"; + this.gridColumn18.FieldName = "remark"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 5; + this.gridColumn18.Width = 120; + // + // gridColumn17 + // + this.gridColumn17.Caption = "状态"; + this.gridColumn17.FieldName = "status"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 6; + // + // gridColumn16 + // + this.gridColumn16.Caption = "剩余积分"; + this.gridColumn16.FieldName = "cur_point"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 7; + this.gridColumn16.Width = 80; + // + // gridColumn12 + // + this.gridColumn12.Caption = "消费奖励(共)"; + this.gridColumn12.FieldName = "buy_point"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 8; + this.gridColumn12.Width = 90; + // + // gridColumn13 + // + this.gridColumn13.Caption = "推荐提成(共)"; + this.gridColumn13.FieldName = "ext_point"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 9; + this.gridColumn13.Width = 90; + // + // gridColumn14 + // + this.gridColumn14.Caption = "其他奖励(共)"; + this.gridColumn14.FieldName = "rew_point"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 10; + this.gridColumn14.Width = 90; + // + // gridColumn15 + // + this.gridColumn15.Caption = "累计积分(共)"; + this.gridColumn15.FieldName = "sum_point"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 11; + this.gridColumn15.Width = 90; + // + // gridColumn21 + // + this.gridColumn21.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn21.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn21.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn21.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn21.Caption = "完成订单数"; + this.gridColumn21.FieldName = "finish_order"; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 12; + // + // gridColumn24 + // + this.gridColumn24.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn24.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn24.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn24.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn24.Caption = "私人比例"; + this.gridColumn24.DisplayFormat.FormatString = "{0}%"; + this.gridColumn24.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn24.FieldName = "private_ratio"; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + this.gridColumn24.OptionsColumn.AllowFocus = false; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 13; + // + // gridColumn25 + // + this.gridColumn25.Caption = "兑换类型"; + this.gridColumn25.FieldName = "exchange_type"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 14; + // + // gridColumn4 + // + this.gridColumn4.Caption = "支付宝账号"; + this.gridColumn4.FieldName = "alipay_num"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 15; + this.gridColumn4.Width = 150; + // + // gridColumn5 + // + this.gridColumn5.Caption = "支付宝姓名"; + this.gridColumn5.FieldName = "alipay_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 16; + this.gridColumn5.Width = 80; + // + // gridColumn19 + // + this.gridColumn19.Caption = "身份证名称"; + this.gridColumn19.FieldName = "identity_name"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 17; + // + // gridColumn20 + // + this.gridColumn20.Caption = "身份证号码"; + this.gridColumn20.FieldName = "identity_card"; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 18; + // + // gridColumn7 + // + this.gridColumn7.Caption = "邀请人编号"; + this.gridColumn7.FieldName = "inviter_id"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 19; + this.gridColumn7.Width = 80; + // + // gridColumn8 + // + this.gridColumn8.Caption = "分组等级"; + this.gridColumn8.FieldName = "gridColumn8"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 20; + this.gridColumn8.Width = 120; + // + // gridColumn9 + // + this.gridColumn9.Caption = "机器人账号"; + this.gridColumn9.FieldName = "robot_name"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 21; + this.gridColumn9.Width = 150; + // + // gridColumn22 + // + this.gridColumn22.Caption = "限制兑换时间"; + this.gridColumn22.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn22.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn22.FieldName = "ban_exchange_time"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 22; + this.gridColumn22.Width = 150; + // + // gridColumn10 + // + this.gridColumn10.Caption = "最后沟通时间"; + this.gridColumn10.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn10.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn10.FieldName = "upd_time"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 23; + this.gridColumn10.Width = 150; + // + // gridColumn11 + // + this.gridColumn11.Caption = "注册时间"; + this.gridColumn11.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn11.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn11.FieldName = "crt_time"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 24; + this.gridColumn11.Width = 150; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 443); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(868, 33); + this.pageControl1.TabIndex = 1; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.comboBoxEdit3); + this.groupControl1.Controls.Add(this.comboBoxEdit2); + this.groupControl1.Controls.Add(this.labelControl3); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(868, 76); + this.groupControl1.TabIndex = 2; + this.groupControl1.Text = "搜索条件"; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = "全部状态"; + this.comboBoxEdit3.Location = new System.Drawing.Point(430, 35); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { + "全部状态"}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(85, 20); + this.comboBoxEdit3.TabIndex = 8; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = "最近新增"; + this.comboBoxEdit2.Location = new System.Drawing.Point(591, 35); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "最近新增", + "最近聊天", + "最早聊天", + "消费最多"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(85, 20); + this.comboBoxEdit2.TabIndex = 8; + // + // labelControl3 + // + this.labelControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl3.Location = new System.Drawing.Point(373, 38); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(52, 14); + this.labelControl3.TabIndex = 7; + this.labelControl3.Text = "用户状态:"; + // + // labelControl2 + // + this.labelControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl2.Location = new System.Drawing.Point(533, 38); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 7; + this.labelControl2.Text = "排序方式:"; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(22, 38); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(695, 32); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(99, 26); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(242, 35); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "客户账号", + "客户昵称", + "客户编号", + "上级账号", + "上级昵称", + "上级编号", + "支付宝账号", + "支付宝姓名", + "积分为负数", + "私人推广位", + "私人比例"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(109, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(66, 35); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(166, 20); + this.textEdit1.TabIndex = 1; + // + // member_manage_control + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Name = "member_manage_control"; + this.Size = new System.Drawing.Size(868, 476); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 修改资料ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private System.Windows.Forms.ToolStripMenuItem 设置私人信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 推荐列表ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraEditors.LabelControl labelControl3; + private System.Windows.Forms.ToolStripMenuItem 查看平台订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 淘宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 拼多多订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 京东订单ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private System.Windows.Forms.ToolStripMenuItem 查看积分信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 添加到云黑名单ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private System.Windows.Forms.ToolStripMenuItem 检测是否为云黑名单ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private System.Windows.Forms.ToolStripMenuItem 唯品联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 抖音联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 苏宁易购订单ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private System.Windows.Forms.ToolStripMenuItem 系统人工兑换类型ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 快手联盟订单ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/member_manage_control.cs b/FLSystem/Forms/member_manage_control.cs new file mode 100644 index 0000000..9ad8630 --- /dev/null +++ b/FLSystem/Forms/member_manage_control.cs @@ -0,0 +1,437 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using FLSystem.Events; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class member_manage_control : XtraUserControl + { + List<fl_member_group> groups = null; + public member_manage_control(string textedit = "") + { + try + { + InitializeComponent(); + textEdit1.Text = textedit; + this.comboBoxEdit1.SelectedIndex = string.IsNullOrEmpty(textedit) ? 0 : 1; + + this.comboBoxEdit3.Properties.Items.Clear(); + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { "全部状态" }); ; + foreach (int v in Enum.GetValues(typeof(MemberType))) + { + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { Enum.GetName(typeof(MemberType), v) }); + } + this.comboBoxEdit3.SelectedIndex = 0; + + this.gridView1.CustomDrawRowIndicator += GridView1_CustomDrawRowIndicator; + this.pageControl1.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + this.groups = session.FindGroups(); + List<fl_member_info> result = null; + List<IConditionalModel> conModels = new List<IConditionalModel>(); + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword) || this.comboBoxEdit1.Text == "积分为负数" || this.comboBoxEdit1.Text == "私人推广位" || this.comboBoxEdit1.Text == "私人比例") + { + //where = " where "; + switch (this.comboBoxEdit1.Text) + { + case "客户账号": + { + conModels.Add(new ConditionalModel() { FieldName = "username", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + } + case "客户昵称": + { + conModels.Add(new ConditionalModel() { FieldName = "usernick", ConditionalType = ConditionalType.Like, FieldValue = keyword }); + + conModels.Add(new ConditionalCollections() + { + ConditionalList = new List<KeyValuePair<WhereType, SqlSugar.ConditionalModel>>() { new KeyValuePair<WhereType, ConditionalModel>(WhereType.Or, new ConditionalModel() { FieldName = "usernick", ConditionalType = ConditionalType.Like, FieldValue = keyword }), new KeyValuePair<WhereType, ConditionalModel>(WhereType.Or, new ConditionalModel() { FieldName = "remark", ConditionalType = ConditionalType.Like, FieldValue = keyword }) } + }); + break; + } + case "客户编号": + { + conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + } + case "支付宝账号": + { + conModels.Add(new ConditionalModel() { FieldName = "alipay_num", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + } + case "支付宝姓名": + { + conModels.Add(new ConditionalModel() { FieldName = "alipay_name", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + } + case "上级编号": + { + conModels.Add(new ConditionalModel() { FieldName = "inviter_id", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + break; + } + case "上级账号": + { + var friend = session.Find<fl_member_info>("username = @username", new { username = keyword }).FirstOrDefault(); + conModels.Add(new ConditionalModel() { FieldName = "inviter_id", ConditionalType = ConditionalType.Equal, FieldValue = (friend != null ? friend.id.ToString() : "0") }); + break; + } + case "上级昵称": + { + var friend = session.Find<fl_member_info>("usernick like @usernick", new { usernick = "%" + keyword + "%" }).FirstOrDefault(); + conModels.Add(new ConditionalModel() { FieldName = "inviter_id", ConditionalType = ConditionalType.Equal, FieldValue = (friend != null ? friend.id.ToString() : "0") }); + break; + } + case "积分为负数": + { + conModels.Add(new ConditionalModel() { FieldName = "cur_point", ConditionalType = ConditionalType.LessThan, FieldValue = "0" }); + break; + } + case "私人推广位": + { + var members = session.FindAdzoneInfos().Where(f => f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id > 0).GroupBy(f => f.member_id).Select(f => f.Key); + conModels.Add(new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", members) }); + break; + } + case "私人比例": + { + conModels.Add(new ConditionalModel() { FieldName = "private_ratio", ConditionalType = ConditionalType.GreaterThan, FieldValue = "0" }); + break; + } + } + } + + if (!string.IsNullOrWhiteSpace(comboBoxEdit3.Text) && comboBoxEdit3.Text != "全部状态") + { + conModels.Add(new ConditionalModel() { FieldName = "status", ConditionalType = ConditionalType.Equal, FieldValue = ((int)(MemberType)Enum.Parse(typeof(MemberType), comboBoxEdit3.Text)).ToString() }); + } + + int totalNumber = 0; + + switch (this.comboBoxEdit2.Text) + { + case "最近新增": + { + result = session.Queryable<fl_member_info>() + .Where(conModels) + .OrderBy(m => m.crt_time, OrderByType.Desc) + .ToPageList(index, pagesize, ref totalNumber); + break; + } + case "最早聊天": + { + result = session.Queryable<fl_member_info>() + .Where(conModels) + .OrderBy(m => m.upd_time, OrderByType.Asc) + .ToPageList(index, pagesize, ref totalNumber); + break; + } + case "最近聊天": + { + result = session.Queryable<fl_member_info>() + .Where(conModels) + .OrderBy(m => m.upd_time, OrderByType.Desc) + .ToPageList(index, pagesize, ref totalNumber); + break; + } + case "消费最多": + { + result = session.Queryable<fl_member_info>() + .Where(conModels) + .OrderBy(m => m.buy_point, OrderByType.Desc) + .ToPageList(index, pagesize, ref totalNumber); + break; + } + } + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "搜索标题", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = null, Total = 0 }; + + }, this.gridControl1, 30, true, true); + MainEvent.CommonEvents += Main_CommonEvents; + this.Disposed += Control_Disposed; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= Main_CommonEvents; + } + + private void Main_CommonEvents(object sender, CommonEvents e) + { + try + { + if (e.Commons != null && e.Commons.Count != 0) + { + if (e.Commons.ContainsKey("control_name") && e.Commons.ContainsKey("username")) + { + var control_name = e.Commons["control_name"].ToString(); + if (control_name == "查看用户信息") + { + textEdit1.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 1; + comboBoxEdit3.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + pageControl1.GotoPage(1); + } + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + private void GridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + if (e.Column.Caption == "分组等级") + { + var row = e.Row as fl_member_info; + if (row != null) + { + var group = groups.FirstOrDefault(f => f.id == row.group_id); + e.Value = group == null ? "未分组" : group.name; + } + } + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + if (e.Column.Caption == "邀请人编号") + { + if (e.Value.ToString() == "0") e.DisplayText = "无"; + } + } + + private void 修改资料ToolStripMenuItem_Click(object sender, EventArgs e) + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var old_row = this.gridView1.GetRow(rows[0]) as base_model; + var from = new member_base_info_form(old_row.id); + from.ShowDialog(); + this.pageControl1.GotoPage(1); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit1.SelectedIndex == 0 || comboBoxEdit1.SelectedIndex == 9 || comboBoxEdit1.SelectedIndex == 10 || comboBoxEdit1.SelectedIndex == 11) + { + this.textEdit1.Enabled = false; + this.textEdit1.Text = ""; + } + else this.textEdit1.Enabled = true; + } + + private void 设置私人信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var old_row = this.gridView1.GetRow(rows[0]) as base_model; + member_private_config member_private = new member_private_config(old_row.id); + member_private.ShowDialog(); + } + } + + private void 推荐列表ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var selectRows = gridView1.GetSelectedRows(); + + if (selectRows.Length > 0) + { + var id = int.Parse(gridView1.GetRowCellValue(selectRows[0], "id").ToString()); + member_inviter_control inviter_Control = new member_inviter_control(id); + inviter_Control.ShowDialog(); + } + } + catch (Exception ex) + { + XtraMessageBoxArgs args = new XtraMessageBoxArgs(); + args.AutoCloseOptions.Delay = 6000; + args.Caption = "系统错误"; + args.Text = ex.Message; + args.Buttons = new DialogResult[] { DialogResult.OK, DialogResult.Cancel }; + XtraMessageBox.Show(args); + } + } + + /// <summary> + /// 查询用户对应订单列表 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary<string, object>(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message); + } + } + + /// <summary> + /// 查询用户对应积分列表 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void 积分ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var username = this.gridView1.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + var common = new Dictionary<string, object>(); + common["control_name"] = "提现管理"; + common["query_type"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (!(rows != null && rows.Length > 0)) e.Cancel = true; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 添加到云黑名单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var member = this.gridView1.GetRow(rows[0]) as fl_member_info; + new AddCloudblack(member).ShowDialog(); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 检测是否为云黑名单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var member = this.gridView1.GetRow(rows[0]) as fl_member_info; + CloudBlack cloud = new CloudBlack(); + var black = cloud.QueryBlack(member); + var msg = $@"{member.username}({member.usernick})【非云名单用户】"; + if (black != null) + msg = $@"{member.username}({member.usernick})【是云黑名单用户】 "; + + XtraMessageBoxArgs args = new XtraMessageBoxArgs(); + args.AutoCloseOptions.Delay = 5000; + args.Caption = $"云黑名单 - {(5000 / 1000)}秒后自动关闭"; + args.Text = msg; + args.Buttons = new DialogResult[] { DialogResult.OK }; + XtraMessageBox.Show(args).ToString(); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 系统人工兑换类型ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var member = this.gridView1.GetRow(rows[0]) as fl_member_info; + if (XtraMessageBox.Show($"确定修改用户:{member.usernick}({member.username})的兑换类型?", "系统提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + member.exchange_type = member.exchange_type == ExchangeType.人工审核 ? ExchangeType.随系统设置 : ExchangeType.人工审核; + ApiClient.GetSession().SaveOrUpdate(member); + this.pageControl1.GotoPage(1); + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/FLSystem/Forms/member_manage_control.resx b/FLSystem/Forms/member_manage_control.resx new file mode 100644 index 0000000..0d001a7 --- /dev/null +++ b/FLSystem/Forms/member_manage_control.resx @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>58</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/member_order_lastnum.Designer.cs b/FLSystem/Forms/member_order_lastnum.Designer.cs new file mode 100644 index 0000000..b97f02a --- /dev/null +++ b/FLSystem/Forms/member_order_lastnum.Designer.cs @@ -0,0 +1,267 @@ +namespace FLSystem.Forms +{ + partial class member_order_lastnum + { + /// <summary> + /// 必需的设计器变量。 + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// 清理所有正在使用的资源。 + /// </summary> + /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// <summary> + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(member_order_lastnum)); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.手动添加尾号ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 462); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(740, 33); + this.pageControl1.TabIndex = 3; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(0, 76); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(740, 380); + this.gridControl1.TabIndex = 2; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.手动添加尾号ToolStripMenuItem, + this.删除选中项ToolStripMenuItem, + this.删除所有数据ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(181, 92); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有数据ToolStripMenuItem + // + this.删除所有数据ToolStripMenuItem.Name = "删除所有数据ToolStripMenuItem"; + this.删除所有数据ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除所有数据ToolStripMenuItem.Text = "删除所有项"; + this.删除所有数据ToolStripMenuItem.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // 手动添加尾号ToolStripMenuItem + // + this.手动添加尾号ToolStripMenuItem.Name = "手动添加尾号ToolStripMenuItem"; + this.手动添加尾号ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.手动添加尾号ToolStripMenuItem.Text = "手动添加尾号"; + this.手动添加尾号ToolStripMenuItem.Click += new System.EventHandler(this.手动添加尾号ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "编号"; + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 46; + // + // gridColumn2 + // + this.gridColumn2.Caption = "客户账号"; + this.gridColumn2.FieldName = "username"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 195; + // + // gridColumn3 + // + this.gridColumn3.Caption = "客户昵称"; + this.gridColumn3.FieldName = "usernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 238; + // + // gridColumn4 + // + this.gridColumn4.Caption = "订单尾号"; + this.gridColumn4.FieldName = "lastnumber"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + this.gridColumn4.Width = 207; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(740, 74); + this.groupControl1.TabIndex = 4; + this.groupControl1.Text = "搜索条件"; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(121, 41); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(522, 35); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(99, 26); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(395, 38); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "客户账号", + "客户昵称", + "订单尾号"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(109, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(165, 38); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(205, 20); + this.textEdit1.TabIndex = 1; + // + // member_order_lastnum + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.Name = "member_order_lastnum"; + this.Size = new System.Drawing.Size(740, 495); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有数据ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 手动添加尾号ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/member_order_lastnum.cs b/FLSystem/Forms/member_order_lastnum.cs new file mode 100644 index 0000000..1a983ee --- /dev/null +++ b/FLSystem/Forms/member_order_lastnum.cs @@ -0,0 +1,168 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using System; +using System.Windows.Forms; + +namespace FLSystem.Forms +{ + public partial class member_order_lastnum : UserControl + { + public class view_member_order_lastnum + { + /// <summary> + /// id + /// </summary> + public long id { get; set; } + + private string _username; + /// <summary> + /// 用户账号 + /// </summary> + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + /// <summary> + /// 用户昵称 + /// </summary> + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + + /// <summary> + /// 商品单价 + /// </summary> + public string lastnumber { get; set; } + + } + + public member_order_lastnum() + { + InitializeComponent(); + + try + { + this.pageControl1.Bind(delegate (int page, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var map = session.NewParamMap(); + map.setPageParamters(page, pagesize); + string where = string.Empty; + if (!string.IsNullOrEmpty(this.textEdit1.Text.Trim())) + { + where = " where "; + switch (this.comboBoxEdit1.Text) + { + case "客户账号": + { + where += " username like @username"; + map.setParameter("username", "%" + this.textEdit1.Text.Trim() + "%"); + break; + } + case "客户昵称": + { + where += " usernick like @usernick"; + map.setParameter("usernick", "%" + this.textEdit1.Text.Trim() + "%"); + break; + } + case "订单尾号": + { + where += " lastnumber = @lastnumber"; + map.setParameter("lastnumber", this.textEdit1.Text.Trim()); + break; + } + } + } + + var rest = session.FindPage<view_member_order_lastnum>($"select aol.id,mi.username,mi.usernick,aol.lastnumber from fl_alimama_order_lastnum aol LEFT JOIN fl_member_info mi on aol.userid = mi.id {where} ", map); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = rest.DataList, Total = rest.Total }; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "搜索标题", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = null, Total = 0 }; + + }, this.gridControl1, 30, true, true); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "删除选中项", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit1.SelectedIndex == 0) + { + this.textEdit1.Enabled = false; + this.textEdit1.Text = ""; + } + else this.textEdit1.Enabled = true; + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("是否删除选中项", "温馨提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) return; + var session = ApiClient.GetSession(); + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "id").ToString();//获取列的数据 + session.Deleteable<fl_alimama_order_lastnum>().Where(f => f.id == int.Parse(id)).ExecuteCommand(); + pageControl1.GotoPage(1); + XtraMessageBox.Show("删除成功", "温馨实体", MessageBoxButtons.OK); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "删除选中项", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 删除所有数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (XtraMessageBox.Show("确定删除所有项", "温馨提示", MessageBoxButtons.OKCancel) == DialogResult.OK) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_alimama_order_lastnum"); + pageControl1.GotoPage(1); + XtraMessageBox.Show("删除成功", "温馨提示", MessageBoxButtons.OK); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "删除选中项", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 手动添加尾号ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var from = new member_order_lastnum_custom(); + from.ShowDialog(); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "手动添加尾号", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/FLSystem/Forms/member_order_lastnum.resx b/FLSystem/Forms/member_order_lastnum.resx new file mode 100644 index 0000000..2396863 --- /dev/null +++ b/FLSystem/Forms/member_order_lastnum.resx @@ -0,0 +1,145 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/member_order_lastnum_custom.Designer.cs b/FLSystem/Forms/member_order_lastnum_custom.Designer.cs new file mode 100644 index 0000000..66978ef --- /dev/null +++ b/FLSystem/Forms/member_order_lastnum_custom.Designer.cs @@ -0,0 +1,165 @@ +namespace FLSystem.Forms +{ + partial class member_order_lastnum_custom + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.label3 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.button2); + this.groupBox1.Controls.Add(this.button1); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.textEdit3); + this.groupBox1.Controls.Add(this.textEdit2); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Location = new System.Drawing.Point(28, 29); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(304, 191); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // textEdit1 + // + this.textEdit1.EditValue = 0; + this.textEdit1.Location = new System.Drawing.Point(90, 30); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(185, 20); + this.textEdit1.TabIndex = 0; + this.textEdit1.EditValueChanged += new System.EventHandler(this.textEdit1_EditValueChanged); + // + // textEdit2 + // + this.textEdit2.EditValue = 0; + this.textEdit2.Location = new System.Drawing.Point(90, 92); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(185, 20); + this.textEdit2.TabIndex = 0; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(17, 33); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(67, 14); + this.label1.TabIndex = 1; + this.label1.Text = "用户编号:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(17, 95); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 1; + this.label2.Text = "订单尾号:"; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(73, 136); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 2; + this.button1.Text = "添加"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(181, 136); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 23); + this.button2.TabIndex = 2; + this.button2.Text = "取消"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // textEdit3 + // + this.textEdit3.Enabled = false; + this.textEdit3.Location = new System.Drawing.Point(90, 61); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Size = new System.Drawing.Size(185, 20); + this.textEdit3.TabIndex = 0; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(17, 64); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(67, 14); + this.label3.TabIndex = 1; + this.label3.Text = "用户昵称:"; + // + // member_order_lastnum_custom + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(362, 246); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "member_order_lastnum_custom"; + this.Text = "手动添加订单尾号"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.TextEdit textEdit3; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/member_order_lastnum_custom.cs b/FLSystem/Forms/member_order_lastnum_custom.cs new file mode 100644 index 0000000..7335a91 --- /dev/null +++ b/FLSystem/Forms/member_order_lastnum_custom.cs @@ -0,0 +1,71 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class member_order_lastnum_custom : BaseForm + { + public member_order_lastnum_custom() + { + InitializeComponent(); + } + + private void button2_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("用户编号不能为空"); + if (string.IsNullOrWhiteSpace(textEdit2.Text)) throw new Exception("用户订单尾号不能为空"); + if (textEdit2.Text.Length != 6) throw new Exception("用户订单尾号只能为6位"); + if (textEdit1.Tag == null) throw new Exception("用户编码对应的用户不存在,请核对"); + + var db = ApiClient.GetSession(); + var last = db.FindAlimamaOrderLastnums().FirstOrDefault(f => textEdit2.Text.Trim() == f.lastnumber && f.userid == long.Parse(textEdit1.Text.Trim())); + if (last != null) + throw new Exception("用户已存在,无需重复添加"); + last = new fl_alimama_order_lastnum() { lastnumber = textEdit2.Text.Trim(), userid = long.Parse(textEdit1.Text.Trim()) }; + db.Saveable(last).ExecuteCommand(); + XtraMessageBox.Show("添加成功", "温馨提示", MessageBoxButtons.OK); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "异常提示", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void textEdit1_EditValueChanged(object sender, EventArgs e) + { + try + { + if (textEdit1.Text.Trim() == "0") throw new Exception("无"); + var session = ApiClient.GetSession(); + var member = session.FindMemberInfoById(int.Parse(textEdit1.Text.Trim())); + if (member == null) throw new Exception("数据异常"); + textEdit3.Text = member.usernick; + textEdit1.Tag = member; + } + catch (Exception ex) + { + textEdit3.Text = ex.Message; + textEdit1.Tag = null; + } + } + } +} diff --git a/FLSystem/Forms/member_order_lastnum_custom.resx b/FLSystem/Forms/member_order_lastnum_custom.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/member_order_lastnum_custom.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/member_private_config.Designer.cs b/FLSystem/Forms/member_private_config.Designer.cs new file mode 100644 index 0000000..49b1b62 --- /dev/null +++ b/FLSystem/Forms/member_private_config.Designer.cs @@ -0,0 +1,388 @@ +namespace FLSystem.Forms +{ + partial class member_private_config + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(member_private_config)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.tbox_member_KeyWord = new DevExpress.XtraEditors.TextEdit(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除选中淘宝推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中拼多多推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中京东推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除唯品会推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中抖音推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbox_member_KeyWord.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.tbox_member_KeyWord); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(966, 76); + this.groupControl1.TabIndex = 5; + this.groupControl1.Text = "搜索条件"; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(224, 39); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "搜索条件:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(615, 33); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(99, 26); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // tbox_member_KeyWord + // + this.tbox_member_KeyWord.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.tbox_member_KeyWord.Location = new System.Drawing.Point(283, 36); + this.tbox_member_KeyWord.Name = "tbox_member_KeyWord"; + this.tbox_member_KeyWord.Size = new System.Drawing.Size(297, 20); + this.tbox_member_KeyWord.TabIndex = 1; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 498); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(966, 33); + this.pageControl1.TabIndex = 4; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(0, 82); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(966, 410); + this.gridControl1.TabIndex = 3; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中淘宝推广位ToolStripMenuItem, + this.删除选中拼多多推广位ToolStripMenuItem, + this.删除选中京东推广位ToolStripMenuItem, + this.删除唯品会推广位ToolStripMenuItem, + this.删除选中抖音推广位ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(197, 114); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 删除选中淘宝推广位ToolStripMenuItem + // + this.删除选中淘宝推广位ToolStripMenuItem.Name = "删除选中淘宝推广位ToolStripMenuItem"; + this.删除选中淘宝推广位ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.删除选中淘宝推广位ToolStripMenuItem.Text = "删除选中淘宝推广位"; + this.删除选中淘宝推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除选中淘宝推广位ToolStripMenuItem_Click); + // + // 删除选中拼多多推广位ToolStripMenuItem + // + this.删除选中拼多多推广位ToolStripMenuItem.Name = "删除选中拼多多推广位ToolStripMenuItem"; + this.删除选中拼多多推广位ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.删除选中拼多多推广位ToolStripMenuItem.Text = "删除选中拼多多推广位"; + this.删除选中拼多多推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除选中拼多多推广位ToolStripMenuItem_Click); + // + // 删除选中京东推广位ToolStripMenuItem + // + this.删除选中京东推广位ToolStripMenuItem.Name = "删除选中京东推广位ToolStripMenuItem"; + this.删除选中京东推广位ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.删除选中京东推广位ToolStripMenuItem.Text = "删除选中京东推广位"; + this.删除选中京东推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除选中京东推广位ToolStripMenuItem_Click); + // + // 删除唯品会推广位ToolStripMenuItem + // + this.删除唯品会推广位ToolStripMenuItem.Name = "删除唯品会推广位ToolStripMenuItem"; + this.删除唯品会推广位ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.删除唯品会推广位ToolStripMenuItem.Text = "删除选中唯品会推广位"; + this.删除唯品会推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除唯品会推广位ToolStripMenuItem_Click); + // + // 删除选中抖音推广位ToolStripMenuItem + // + this.删除选中抖音推广位ToolStripMenuItem.Name = "删除选中抖音推广位ToolStripMenuItem"; + this.删除选中抖音推广位ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.删除选中抖音推广位ToolStripMenuItem.Text = "删除选中抖音推广位"; + this.删除选中抖音推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除选中抖音推广位ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn6, + this.gridColumn2, + this.gridColumn3, + this.gridColumn18, + this.gridColumn17, + this.gridColumn16, + this.gridColumn5, + this.gridColumn7, + this.gridColumn4}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn1 + // + this.gridColumn1.Caption = "编号"; + this.gridColumn1.FieldName = "uid"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 44; + // + // gridColumn6 + // + this.gridColumn6.Caption = "用户类型"; + this.gridColumn6.FieldName = "robot_type"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 1; + this.gridColumn6.Width = 100; + // + // gridColumn2 + // + this.gridColumn2.Caption = "用户名"; + this.gridColumn2.FieldName = "username"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 150; + // + // gridColumn3 + // + this.gridColumn3.Caption = "昵称"; + this.gridColumn3.FieldName = "usernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 150; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn18.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn18.AppearanceCell.Options.UseFont = true; + this.gridColumn18.AppearanceCell.Options.UseForeColor = true; + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn18.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "淘宝推广位名称"; + this.gridColumn18.FieldName = "tb_pid_name"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.OptionsColumn.AllowEdit = false; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 4; + this.gridColumn18.Width = 91; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn17.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn17.AppearanceCell.Options.UseFont = true; + this.gridColumn17.AppearanceCell.Options.UseForeColor = true; + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn17.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "拼多多推广位名称"; + this.gridColumn17.FieldName = "pdd_pid_name"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + this.gridColumn17.Width = 85; + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn16.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn16.AppearanceCell.Options.UseFont = true; + this.gridColumn16.AppearanceCell.Options.UseForeColor = true; + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn16.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "京东推广位名称"; + this.gridColumn16.FieldName = "jd_pid_name"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.OptionsColumn.AllowEdit = false; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 6; + this.gridColumn16.Width = 90; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn5.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "唯品会推广位名称"; + this.gridColumn5.FieldName = "wph_pid_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 7; + this.gridColumn5.Width = 128; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn7.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "抖音推广位名称"; + this.gridColumn7.FieldName = "dy_pid_name"; + this.gridColumn7.MinWidth = 25; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Width = 128; + // + // gridColumn4 + // + this.gridColumn4.Caption = "无条件绑定"; + this.gridColumn4.FieldName = "is_auto_bind"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 8; + this.gridColumn4.Width = 80; + // + // member_private_config + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(966, 531); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "member_private_config"; + this.Text = "客户私人配置"; + this.Load += new System.EventHandler(this.member_private_config_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbox_member_KeyWord.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit tbox_member_KeyWord; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中淘宝推广位ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中拼多多推广位ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中京东推广位ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private System.Windows.Forms.ToolStripMenuItem 删除唯品会推广位ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中抖音推广位ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/member_private_config.cs b/FLSystem/Forms/member_private_config.cs new file mode 100644 index 0000000..ef55581 --- /dev/null +++ b/FLSystem/Forms/member_private_config.cs @@ -0,0 +1,432 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using FLSystem.Properties; +using System; +using System.ComponentModel; +using System.Data; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class member_private_config : BaseForm + { + private long uid; + public member_private_config(long uid) + { + InitializeComponent(); + this.uid = uid; + var session = ApiClient.GetSession(); + var member = session.FindMemberInfoById(uid); + if (member != null) + tbox_member_KeyWord.Text = member.username; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + pageControl1.Go(sender, e); + } + + private void member_private_config_Load(object sender, EventArgs e) + { + try + { + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var keyword = tbox_member_KeyWord.Text.Replace("'", "''").Trim(); + var where = string.IsNullOrWhiteSpace(keyword) ? string.Empty : $" and (mi.username like '%{keyword}%' or mi.usernick like '%{keyword}%' )"; + //var result1 = session.FindPage<member_private_config_temp>($"select mi.id as uid,mi.robot_type as robot_type,mi.username as username,mi.usernick as usernick,flag.* from fl_member_info mi left join (select ai1_temp.member_id as member_id,ai1_temp.is_auto_bind,ai1_temp.adzone_name as tb_pid_name,ai2_temp.adzone_name as pdd_pid_name,ai3_temp.adzone_name as jd_pid_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.阿里妈妈}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = '淘宝私人pid') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.多多进宝}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='拼多多私人pid') ai2_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.京东联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='京东私人pid') ai3_temp on ai1_temp.member_id = ai2_temp.member_id and ai3_temp.member_id = ai2_temp.member_id) flag on mi.id = flag.member_id where 1=1 {where}", parm); + + /* + var result = session.FindPage<member_private_config_temp>($@"select mi.id as uid,mi.robot_type as robot_type,mi.username as username,mi.usernick as usernick,flag.* from fl_member_info mi left join (select ai1_temp.member_id as member_id,ai1_temp.is_auto_bind,ai1_temp.adzone_name as tb_pid_name,ai2_temp.adzone_name as pdd_pid_name,ai3_temp.adzone_name as jd_pid_name,ai4_temp.adzone_name as wph_pid_name,ai5_temp.adzone_name as dy_pid_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.阿里妈妈}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = '淘宝私人pid') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.多多进宝}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='拼多多私人pid') ai2_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.京东联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='京东私人pid') ai3_temp +INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.唯品联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='唯品会私人pid') ai4_temp +INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.抖音联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='抖音私人pid') ai5_temp +on ai1_temp.member_id = ai2_temp.member_id and ai3_temp.member_id = ai2_temp.member_id and ai4_temp.member_id = ai2_temp.member_id and ai5_temp.member_id = ai2_temp.member_id) flag on mi.id = flag.member_id where 1=1 {where}", parm); + */ + + var result = session.FindPage<member_private_config_temp>($@"select mi.id as uid,mi.robot_type as robot_type,mi.username as username,mi.usernick as usernick,flag.* from fl_member_info mi left join (select ai1_temp.member_id as member_id,ai1_temp.is_auto_bind,ai1_temp.adzone_name as tb_pid_name,ai2_temp.adzone_name as pdd_pid_name,ai3_temp.adzone_name as jd_pid_name,ai4_temp.adzone_name as wph_pid_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.阿里妈妈}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = '淘宝私人pid') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.多多进宝}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='拼多多私人pid') ai2_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.京东联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='京东私人pid') ai3_temp +INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.唯品联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='唯品会私人pid') ai4_temp +on ai1_temp.member_id = ai2_temp.member_id and ai3_temp.member_id = ai2_temp.member_id and ai4_temp.member_id = ai2_temp.member_id) flag on mi.id = flag.member_id where 1=1 {where}", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 修改显示内容的事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + //if ((e.Column.FieldName == "pdd_pid_name" || e.Column.FieldName == "tb_pid_name" || e.Column.FieldName == "jd_pid_name" || e.Column.FieldName == "wph_pid_name" || e.Column.FieldName == "dy_pid_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + if ((e.Column.FieldName == "pdd_pid_name" || e.Column.FieldName == "tb_pid_name" || e.Column.FieldName == "jd_pid_name" || e.Column.FieldName == "wph_pid_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "uid").ToString();//获取列的数据 + + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + var session = ApiClient.GetSession(); + var strs = new string[] { "淘宝推广位名称", "拼多多推广位名称", "京东推广位名称", "唯品会推广位名称", "抖音推广位名称" }; + //var pidSortRemark = new string[] { "淘宝私人pid", "拼多多私人pid", "京东私人pid" };//pid类别备注,值顺序不能变 + var pidSortRemark = Enum.GetNames(typeof(PrivateAdzoneType));//pid类别备注,值顺序不能变 + if (!strs.Contains(e.Column.Caption)) return; + else + { + var pidInfos = session.Queryable<fl_adzone_info>().Where(f => f.member_id == int.Parse(id) && f.custom_type == Resources.SoftwareType).ToList(); + if (pidInfos != null && pidInfos.Count == 0) + { + for (int i = 1; i <= pidSortRemark.Length; i++) + { + var adzone = new fl_adzone_info + { + custom_type = Resources.SoftwareType, + extend = pidSortRemark[i - 1], + alliance_id = i, + is_download = false, + member_id = int.Parse(id), + onoff = false, + robot_id = 0, + group_id = string.Empty, + adzone_pid_cps_name = string.Empty, + adzone_pid = string.Empty, + adzone_name = string.Empty + }; + session.Saveable(adzone).ExecuteReturnEntity(); + pidInfos.Add(adzone); + } + } + fl_adzone_info esbAdzone = null; + object setAdzoneObj = null; + Tuiguangwei setAdzone = null; + if (e.Column.Caption == strs[0]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.extend == pidSortRemark[0]).FirstOrDefault(); + } + else if (e.Column.Caption == strs[1]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.多多进宝); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.extend == pidSortRemark[1]).FirstOrDefault(); + } + else if (e.Column.Caption == strs[2]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.京东联盟); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.extend == pidSortRemark[2]).FirstOrDefault(); + } + else if (e.Column.Caption == strs[3]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.唯品联盟); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.extend == pidSortRemark[3]).FirstOrDefault(); + } + else if (e.Column.Caption == strs[4]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.抖音联盟); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.extend == pidSortRemark[4]).FirstOrDefault(); + } + + if (esbAdzone != null && setAdzoneObj != null) + { + setAdzone = setAdzoneObj as Tuiguangwei; + //var adzone = session.FindAdzoneInfos(true).FirstOrDefault(f => f.member_id != int.Parse(id) && f.adzone_pid == setAdzone.Pid && f.adzone_pid_cps_name == setAdzone.Member.username && f.adzone_name == setAdzone.Name); + //if (adzone != null) + // throw new Exception("该推广位已经被其插件或用户绑定"); + + esbAdzone.adzone_name = setAdzone.Name; + esbAdzone.adzone_pid = setAdzone.Pid; + esbAdzone.adzone_pid_cps_name = setAdzone.Member.username; + session.SaveOrUpdate(esbAdzone); + } + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + } + #endregion + + #region 开关单元格单击修改状态 + if (e.Column.FieldName == "is_auto_bind" && e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该私人推广位是否无条件绑定?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) return; + + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos().Where(f => f.member_id == int.Parse(id) && f.custom_type == Resources.SoftwareType).ToList(); + if (adzones == null || adzones.Count == 0) throw new Exception("请先设置私人推广位"); + session.ExcuteSQL("update fl_adzone_info set is_auto_bind = @is_auto_bind where member_id = @member_id", new { is_auto_bind = !adzones[0].is_auto_bind, member_id = int.Parse(id) }); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中淘宝推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + + try + { + var session = ApiClient.GetSession(); + var selectRow = gridView1.GetSelectedRows()[0]; + var uid = this.gridView1.GetRowCellValue(selectRow, "uid").ToString();//获取列的数据 + var pidSortRemark = Enum.GetNames(typeof(PrivateAdzoneType));//pid类别备注,值顺序不能变 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.member_id == int.Parse(uid) && f.custom_type == Resources.SoftwareType && f.extend == pidSortRemark[0]); + if (adzone != null) + { + adzone.adzone_name = string.Empty; + adzone.adzone_pid = string.Empty; + adzone.adzone_pid_cps_name = string.Empty; + + session.SaveOrUpdate(adzone); + } + ShowSuccess("执行成功"); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中拼多多推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var selectRow = gridView1.GetSelectedRows()[0]; + var uid = this.gridView1.GetRowCellValue(selectRow, "uid").ToString();//获取列的数据 + var pidSortRemark = Enum.GetNames(typeof(PrivateAdzoneType));//pid类别备注,值顺序不能变 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.member_id == int.Parse(uid) && f.custom_type == Resources.SoftwareType && f.extend == pidSortRemark[1]); + if (adzone != null) + { + adzone.adzone_name = string.Empty; + adzone.adzone_pid = string.Empty; + adzone.adzone_pid_cps_name = string.Empty; + + session.SaveOrUpdate(adzone); + } + ShowSuccess("执行成功"); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中京东推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var selectRow = gridView1.GetSelectedRows()[0]; + var uid = this.gridView1.GetRowCellValue(selectRow, "uid").ToString();//获取列的数据 + var pidSortRemark = Enum.GetNames(typeof(PrivateAdzoneType));//pid类别备注,值顺序不能变 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.member_id == int.Parse(uid) && f.custom_type == Resources.SoftwareType && f.extend == pidSortRemark[2]); + if (adzone != null) + { + adzone.adzone_name = string.Empty; + adzone.adzone_pid = string.Empty; + adzone.adzone_pid_cps_name = string.Empty; + + session.SaveOrUpdate(adzone); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + ShowSuccess("执行成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (!(rows != null && rows.Length > 0)) e.Cancel = true; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除唯品会推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var selectRow = gridView1.GetSelectedRows()[0]; + var uid = this.gridView1.GetRowCellValue(selectRow, "uid").ToString();//获取列的数据 + var pidSortRemark = Enum.GetNames(typeof(PrivateAdzoneType));//pid类别备注,值顺序不能变 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.唯品联盟 && f.member_id == int.Parse(uid) && f.custom_type == Resources.SoftwareType && f.extend == pidSortRemark[3]); + if (adzone != null) + { + adzone.adzone_name = string.Empty; + adzone.adzone_pid = string.Empty; + adzone.adzone_pid_cps_name = string.Empty; + + session.SaveOrUpdate(adzone); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + ShowSuccess("执行成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中抖音推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var selectRow = gridView1.GetSelectedRows()[0]; + var uid = this.gridView1.GetRowCellValue(selectRow, "uid").ToString();//获取列的数据 + var pidSortRemark = Enum.GetNames(typeof(PrivateAdzoneType));//pid类别备注,值顺序不能变 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.抖音联盟 && f.member_id == int.Parse(uid) && f.custom_type == Resources.SoftwareType && f.extend == pidSortRemark[4]); + if (adzone != null) + { + adzone.adzone_name = string.Empty; + adzone.adzone_pid = string.Empty; + adzone.adzone_pid_cps_name = string.Empty; + + session.SaveOrUpdate(adzone); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + ShowSuccess("执行成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + } + + class member_private_config_temp + { + /// <summary> + /// 用户id (fl_membe_info 表id) + /// </summary> + public long uid { get; set; } + /// <summary> + /// 机器人类型 + /// </summary> + public ChatType robot_type { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string username { get; set; } + /// <summary> + /// 用户昵称 + /// </summary> + public string usernick { get; set; } + /// <summary> + /// 淘宝推广位名称 + /// </summary> + public string tb_pid_name { get; set; } + /// <summary> + /// 京东推广位名称 + /// </summary> + public string jd_pid_name { get; set; } + /// <summary> + /// 拼多多推广位名称 + /// </summary> + public string pdd_pid_name { get; set; } + /// <summary> + /// 唯品会推广位名称 + /// </summary> + public string wph_pid_name { get; set; } + /// <summary> + /// 抖音推广位名称 + /// </summary> + public string dy_pid_name { get; set; } + /// <summary> + /// 个人的积分比例 + /// </summary> + public long member_id { get; set; } + /// <summary> + /// 私人推广位是否强制绑定 + /// </summary> + public bool is_auto_bind { get; set; } + + } + + class group_pid_temp + { + /// <summary> + /// 群账号 + /// </summary> + public string groupid { get; set; } + /// <summary> + /// 群昵称 + /// </summary> + public string extend { get; set; } + /// <summary> + /// 淘宝推广位名称 + /// </summary> + public string tb_pid_name { get; set; } + /// <summary> + /// 京东推广位名称 + /// </summary> + public string jd_pid_name { get; set; } + /// <summary> + /// 拼多多推广位名称 + /// </summary> + public string pdd_pid_name { get; set; } + ///// <summary> + ///// 个人的积分比例 + ///// </summary> + //public long member_id { get; set; } + ///// <summary> + ///// 私人推广位是否强制绑定 + ///// </summary> + //public bool is_auto_bind { get; set; } + + } + +} diff --git a/FLSystem/Forms/member_private_config.resx b/FLSystem/Forms/member_private_config.resx new file mode 100644 index 0000000..cce7e14 --- /dev/null +++ b/FLSystem/Forms/member_private_config.resx @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/member_reelect_group.Designer.cs b/FLSystem/Forms/member_reelect_group.Designer.cs new file mode 100644 index 0000000..ef70612 --- /dev/null +++ b/FLSystem/Forms/member_reelect_group.Designer.cs @@ -0,0 +1,103 @@ +namespace FLSystem.Forms +{ + partial class member_reelect_group + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.label2 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.SuspendLayout(); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.ForeColor = System.Drawing.Color.Red; + this.label2.Location = new System.Drawing.Point(88, 90); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(283, 14); + this.label2.TabIndex = 7; + this.label2.Text = "注:删除分组,将分组对应的用户转移至选择分组中"; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(330, 41); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 6; + this.button1.Text = "确定"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(68, 45); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(67, 14); + this.label1.TabIndex = 5; + this.label1.Text = "选择分组:"; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(141, 41); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(170, 22); + this.comboBox1.TabIndex = 4; + // + // member_reelect_group + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(472, 144); + this.Controls.Add(this.label2); + this.Controls.Add(this.button1); + this.Controls.Add(this.label1); + this.Controls.Add(this.comboBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "member_reelect_group"; + this.Text = "选择移入分组"; + this.Load += new System.EventHandler(this.member_reelect_group_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox comboBox1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/member_reelect_group.cs b/FLSystem/Forms/member_reelect_group.cs new file mode 100644 index 0000000..1670911 --- /dev/null +++ b/FLSystem/Forms/member_reelect_group.cs @@ -0,0 +1,41 @@ +using Api.Framework.Model; +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class member_reelect_group : BaseForm + { + List<fl_member_group> memberGroup = null; + public member_reelect_group(List<fl_member_group> memberGroup) + { + InitializeComponent(); + this.memberGroup = memberGroup; + } + + private void member_reelect_group_Load(object sender, EventArgs e) + { + if (memberGroup != null && memberGroup.Count != 0) + { + var infoList = new List<object>(); + foreach (var item in memberGroup) + { + infoList.Add(new { Id = item.id.ToString(), Name = item.name }); + } + comboBox1.DataSource = infoList; + comboBox1.ValueMember = "Id"; + comboBox1.DisplayMember = "Name"; + } + } + + public string id = string.Empty; + + private void button1_Click(object sender, EventArgs e) + { + id = comboBox1.SelectedValue.ToString(); + this.DialogResult = DialogResult.OK; + } + } +} diff --git a/FLSystem/Forms/member_reelect_group.resx b/FLSystem/Forms/member_reelect_group.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/member_reelect_group.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/notice_robotapi_control.Designer.cs b/FLSystem/Forms/notice_robotapi_control.Designer.cs new file mode 100644 index 0000000..890b5a5 --- /dev/null +++ b/FLSystem/Forms/notice_robotapi_control.Designer.cs @@ -0,0 +1,167 @@ +using DevExpress.XtraEditors; +using DevExpress.XtraGrid; +using DevExpress.XtraGrid.Columns; +using DevExpress.XtraGrid.Views.Grid; + +namespace FLSystem.Forms +{ + partial class notice_robotapi_control + { + /// <summary> + /// 必需的设计器变量。 + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// 清理所有正在使用的资源。 + /// </summary> + /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// <summary> + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.编辑配置ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(-3, 37); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(760, 431); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.编辑配置ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 26); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 编辑配置ToolStripMenuItem + // + this.编辑配置ToolStripMenuItem.Name = "编辑配置ToolStripMenuItem"; + this.编辑配置ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.编辑配置ToolStripMenuItem.Text = "编辑配置"; + this.编辑配置ToolStripMenuItem.Click += new System.EventHandler(this.编辑配置ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 145; + // + // gridColumn2 + // + this.gridColumn2.Caption = "机器人API类型"; + this.gridColumn2.FieldName = "notice_apitype"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 111; + // + // gridColumn3 + // + this.gridColumn3.Caption = "备注"; + this.gridColumn3.FieldName = "remark"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.ReadOnly = true; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 479; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(6, 7); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 23); + this.simpleButton1.TabIndex = 1; + this.simpleButton1.Text = "新增"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(97, 8); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(75, 23); + this.simpleButton2.TabIndex = 2; + this.simpleButton2.Text = "刷新"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // notice_robotapi_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.gridControl1); + this.Name = "notice_robotapi_control"; + this.Size = new System.Drawing.Size(760, 468); + this.Load += new System.EventHandler(this.notice_robotapi_control_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private GridControl gridControl1; + private GridView gridView1; + private GridColumn gridColumn1; + private GridColumn gridColumn2; + private GridColumn gridColumn3; + private SimpleButton simpleButton1; + private SimpleButton simpleButton2; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 编辑配置ToolStripMenuItem; + } +} diff --git a/FLSystem/Forms/notice_robotapi_control.cs b/FLSystem/Forms/notice_robotapi_control.cs new file mode 100644 index 0000000..b0018e1 --- /dev/null +++ b/FLSystem/Forms/notice_robotapi_control.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework; +using UI.Framework.Forms; +using Api.Framework.Model; + +namespace FLSystem.Forms +{ + public partial class notice_robotapi_control : UserControl + { + public notice_robotapi_control() + { + InitializeComponent(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + var f = new notice_robotapi_editform(); + f.ShowDialog(); + if (f.IsUpdate) simpleButton2_Click(null, null); + } + private void Loading(bool f=false) + { + try + { + this.gridControl1.DataSource = null; + var session = ApiClient.GetSession(); + var list = session.FindNoticeapiRobots(f); + this.gridControl1.DataSource = list; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + private void simpleButton2_Click(object sender, EventArgs e) + { + Loading(true); + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) e.Cancel = true; + + + } + + private void 编辑配置ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_noticeapi_info; + var f = new notice_robotapi_editform(row); + f.ShowDialog(); + if (f.IsUpdate) simpleButton2_Click(null, null); + } + catch (Exception) + { + } + } + + private void notice_robotapi_control_Load(object sender, EventArgs e) + { + Loading(true); + } + } +} diff --git a/FLSystem/Forms/notice_robotapi_control.resx b/FLSystem/Forms/notice_robotapi_control.resx new file mode 100644 index 0000000..ad53752 --- /dev/null +++ b/FLSystem/Forms/notice_robotapi_control.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/notice_robotapi_editform.Designer.cs b/FLSystem/Forms/notice_robotapi_editform.Designer.cs new file mode 100644 index 0000000..d12d5da --- /dev/null +++ b/FLSystem/Forms/notice_robotapi_editform.Designer.cs @@ -0,0 +1,219 @@ +using DevExpress.XtraEditors; + +namespace FLSystem.Forms +{ + partial class notice_robotapi_editform + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(44, 23); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(50, 14); + this.label1.TabIndex = 0; + this.label1.Text = "名称:*"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(44, 89); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(105, 14); + this.label2.TabIndex = 1; + this.label2.Text = "机器人API类型:*"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(44, 153); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(117, 14); + this.label3.TabIndex = 2; + this.label3.Text = "机器人群API接口:*"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(47, 45); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(275, 22); + this.textBox1.TabIndex = 3; + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(47, 174); + this.textBox3.Multiline = true; + this.textBox3.Name = "textBox3"; + this.textBox3.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox3.Size = new System.Drawing.Size(275, 51); + this.textBox3.TabIndex = 5; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(140, 423); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(84, 24); + this.simpleButton1.TabIndex = 6; + this.simpleButton1.Text = "保存"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.ForeColor = System.Drawing.Color.Red; + this.label4.Location = new System.Drawing.Point(100, 23); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(163, 14); + this.label4.TabIndex = 7; + this.label4.Text = "(唯一区分标识、不可重复)"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(44, 246); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(150, 14); + this.label5.TabIndex = 8; + this.label5.Text = "Secret key:(可以不写)"; + // + // textBox4 + // + this.textBox4.Location = new System.Drawing.Point(47, 267); + this.textBox4.Multiline = true; + this.textBox4.Name = "textBox4"; + this.textBox4.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox4.Size = new System.Drawing.Size(275, 51); + this.textBox4.TabIndex = 9; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(47, 110); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(275, 22); + this.comboBox1.TabIndex = 10; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(54, 423); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(80, 24); + this.simpleButton2.TabIndex = 11; + this.simpleButton2.Text = "测试"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(47, 357); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox2.Size = new System.Drawing.Size(275, 51); + this.textBox2.TabIndex = 13; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(44, 336); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(115, 14); + this.label6.TabIndex = 12; + this.label6.Text = "备注:(可以不写)"; + // + // simpleButton3 + // + this.simpleButton3.Location = new System.Drawing.Point(230, 423); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(84, 24); + this.simpleButton3.TabIndex = 14; + this.simpleButton3.Text = "删除"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // notice_robotapi_editform + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(367, 471); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label6); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.textBox4); + this.Controls.Add(this.label5); + this.Controls.Add(this.label4); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "notice_robotapi_editform"; + this.Text = "编辑通知API机器人"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox textBox3; + private SimpleButton simpleButton1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.ComboBox comboBox1; + private SimpleButton simpleButton2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label6; + private SimpleButton simpleButton3; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/notice_robotapi_editform.cs b/FLSystem/Forms/notice_robotapi_editform.cs new file mode 100644 index 0000000..d76f3a1 --- /dev/null +++ b/FLSystem/Forms/notice_robotapi_editform.cs @@ -0,0 +1,117 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class notice_robotapi_editform : BaseForm + { + public notice_robotapi_editform(fl_noticeapi_info model = null) + { + InitializeComponent(); + this.model = model; + + comboBox1.DataSource = null; + comboBox1.DataSource = Enum.GetNames(typeof(NoticeApiType)); + this.comboBox1.SelectedIndex = 0; + + this.simpleButton3.Enabled = false; + if (model != null) + { + this.textBox1.Text = this.model.name; + this.textBox1.ReadOnly = true; + for (int i = 0; i < this.comboBox1.Items.Count; i++) + { + var text = this.comboBox1.Items[i].ToString(); + if (model.notice_apitype.ToString() == text) + { + this.comboBox1.SelectedIndex = i; + break; + } + } + + this.textBox2.Text = this.model.remark; + this.textBox3.Text = this.model.api_location; + this.textBox4.Text = this.model.token; + this.simpleButton3.Enabled = true; + + + } + } + public bool IsUpdate { get; private set; } + fl_noticeapi_info model; + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + //fl_noticeapi_info temp = null; + if (model == null) model = new fl_noticeapi_info() { name = this.textBox1.Text }; + + model.notice_apitype = Util.ConvertEnum<NoticeApiType>(this.comboBox1.Text); + model.api_location = this.textBox3.Text; + model.token = this.textBox4.Text; + model.remark = this.textBox2.Text; + var session = ApiClient.GetSession(); + if (model.id == 0) session.Insertable<fl_noticeapi_info>(model).ExecuteCommand(); + else session.Updateable<fl_noticeapi_info>(model).ExecuteCommand(); + + IsUpdate = true; + + this.Close(); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + fl_noticeapi_info temp = new fl_noticeapi_info() + { + name = "测试", + notice_apitype = Util.ConvertEnum<NoticeApiType>(this.comboBox1.Text), + remark = string.Empty, + api_location = this.textBox3.Text, + token = this.textBox4.Text + }; + + ApiClient.SendNoticeMessage(temp, "这是一条FLsystem的测试消息!", false); + BaseForm.ShowSuccess("已发送测试消息,请注意查收!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_noticeapi_info where id=" + model.id); + IsUpdate = true; + this.Close(); + } + catch (Exception ex) + { + + BaseForm.ShowError(ex); + } + } + } +} diff --git a/FLSystem/Forms/notice_robotapi_editform.resx b/FLSystem/Forms/notice_robotapi_editform.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/notice_robotapi_editform.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/plugin_control.Designer.cs b/FLSystem/Forms/plugin_control.Designer.cs new file mode 100644 index 0000000..0522b7f --- /dev/null +++ b/FLSystem/Forms/plugin_control.Designer.cs @@ -0,0 +1,99 @@ +namespace FLSystem.Forms +{ + partial class plugin_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.pictureEdit1 = new DevExpress.XtraEditors.PictureEdit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.buttonCheck2); + this.groupBox1.Controls.Add(this.pictureEdit1); + this.groupBox1.Location = new System.Drawing.Point(3, 2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(98, 137); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "groupBox1"; + // + // buttonCheck2 + // + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = false; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style4; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(11, 103); + this.buttonCheck2.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(75, 26); + this.buttonCheck2.TabIndex = 3; + this.buttonCheck2.Click += new System.EventHandler(this.buttonCheck1_Click); + // + // pictureEdit1 + // + this.pictureEdit1.Location = new System.Drawing.Point(15, 25); + this.pictureEdit1.Name = "pictureEdit1"; + this.pictureEdit1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.pictureEdit1.Properties.Appearance.Options.UseBackColor = true; + this.pictureEdit1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.pictureEdit1.Properties.ShowCameraMenuItem = DevExpress.XtraEditors.Controls.CameraMenuItemVisibility.Auto; + this.pictureEdit1.Properties.ShowMenu = false; + this.pictureEdit1.Properties.SizeMode = DevExpress.XtraEditors.Controls.PictureSizeMode.Zoom; + this.pictureEdit1.Properties.Click += new System.EventHandler(this.pictureEdit1_Properties_Click); + this.pictureEdit1.Size = new System.Drawing.Size(70, 70); + this.pictureEdit1.TabIndex = 1; + // + // plugin_control + // + this.Appearance.BackColor = System.Drawing.Color.Transparent; + this.Appearance.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(31)))), ((int)(((byte)(53))))); + this.Appearance.Options.UseBackColor = true; + this.Appearance.Options.UseForeColor = true; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.groupBox1); + this.Name = "plugin_control"; + this.Size = new System.Drawing.Size(106, 143); + this.Load += new System.EventHandler(this.plugin_control_Load); + this.Paint += new System.Windows.Forms.PaintEventHandler(this.plugin_control_Paint); + this.groupBox1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.pictureEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.PictureEdit pictureEdit1; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + } +} diff --git a/FLSystem/Forms/plugin_control.cs b/FLSystem/Forms/plugin_control.cs new file mode 100644 index 0000000..e84a149 --- /dev/null +++ b/FLSystem/Forms/plugin_control.cs @@ -0,0 +1,135 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class plugin_control : DevExpress.XtraEditors.XtraUserControl + { + private Plugin Plugin; + public plugin_control(Plugin plugin) + { + try + { + InitializeComponent(); + this.Plugin = plugin; + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + } + + public new void Refresh() + { + try + { + this.groupBox1.Text = this.Plugin.Name; + this.buttonCheck2.Checked = Plugin.IsRun; + this.pictureEdit1.Image = Plugin.IsRun ? Plugin.Logo : Util.ToGrey(Plugin.Logo); + this.ForeColor = Plugin.IsRun ? Color.Black : Color.Gray; + } + catch (Exception) + { } + } + + private void pictureEdit1_Properties_Click(object sender, EventArgs e) + { + try + { + if (Plugin.IsRun) Plugin.ShowForm(); + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + } + + private void buttonCheck1_Click(object sender, EventArgs e) + { + this.buttonCheck2.Enabled = false; + try + { + if (this.buttonCheck2.Checked) + PluginClient.Install(Plugin); + else + PluginClient.UnInstall(Plugin); + } + catch (Exception ex) + { + if (!this.IsDisposed) + BaseForm.ShowError(ex); + } + finally + { + this.buttonCheck2.Enabled = true; + } + this.Refresh(); + } + + private void plugin_control_Load(object sender, EventArgs e) + { + this.Refresh(); + } + + //重绘边框 + private void Draw(Rectangle rectangle, Graphics g, int _radius) + { + //GraphicsPath gp = null; + //try + //{ + + // Pen shadowPen = new Pen(Color.Gray); + // gp = DrawRoundRect(rectangle.X, rectangle.Y, rectangle.Width - 2, rectangle.Height - 1, _radius); + // g.DrawPath(shadowPen, gp); + //} + //catch (Exception) + //{ } + //finally + //{ + // if (gp != null) + // gp.Dispose(); + //} + } + public GraphicsPath DrawRoundRect(int x, int y, int width, int height, int radius) + { + GraphicsPath gp = new GraphicsPath(); + try + { + gp.AddArc(x, y, radius, radius, 180, 90); + gp.AddArc(width - radius, y, radius, radius, 270, 90); + gp.AddArc(width - radius, height - radius, radius, radius, 0, 90); + gp.AddArc(x, height - radius, radius, radius, 90, 90); + gp.CloseAllFigures(); + } + catch (Exception) + { } + return gp; + } + + private void plugin_control_Paint(object sender, PaintEventArgs e) + { + Graphics g = null; + try + { + g = this.CreateGraphics(); + Draw(this.ClientRectangle, g, 20); + } + catch (Exception) + { } + finally + { + if (g != null) + g.Dispose(); + } + } + } +} + diff --git a/FLSystem/Forms/plugin_control.resx b/FLSystem/Forms/plugin_control.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Forms/plugin_control.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/plugin_debug.Designer.cs b/FLSystem/Forms/plugin_debug.Designer.cs new file mode 100644 index 0000000..fc0a82c --- /dev/null +++ b/FLSystem/Forms/plugin_debug.Designer.cs @@ -0,0 +1,242 @@ +namespace FLSystem.Forms +{ + partial class plugin_debug + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(plugin_debug)); + this.maskedTextBox1 = new System.Windows.Forms.MaskedTextBox(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.richEditControl1 = new DevExpress.XtraRichEdit.RichEditControl(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.richEditControl2 = new DevExpress.XtraRichEdit.RichEditControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.maskedTextBox2 = new System.Windows.Forms.MaskedTextBox(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // maskedTextBox1 + // + this.maskedTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.maskedTextBox1.Location = new System.Drawing.Point(123, 31); + this.maskedTextBox1.Name = "maskedTextBox1"; + this.maskedTextBox1.Size = new System.Drawing.Size(449, 22); + this.maskedTextBox1.TabIndex = 7; + this.maskedTextBox1.Text = "id_test"; + // + // labelControl2 + // + this.labelControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.labelControl2.Location = new System.Drawing.Point(68, 71); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(36, 14); + this.labelControl2.TabIndex = 5; + this.labelControl2.Text = "昵 称:"; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.labelControl1.Location = new System.Drawing.Point(64, 34); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(40, 14); + this.labelControl1.TabIndex = 4; + this.labelControl1.Text = "用户名:"; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.maskedTextBox2); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.comboBoxEdit1); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.richEditControl1); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.maskedTextBox1); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Location = new System.Drawing.Point(19, 19); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(596, 233); + this.groupBox1.TabIndex = 8; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "模拟用户请求"; + // + // labelControl3 + // + this.labelControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.labelControl3.Location = new System.Drawing.Point(64, 113); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(40, 14); + this.labelControl3.TabIndex = 8; + this.labelControl3.Text = "待发送:"; + // + // richEditControl1 + // + this.richEditControl1.ActiveViewType = DevExpress.XtraRichEdit.RichEditViewType.Simple; + this.richEditControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richEditControl1.LayoutUnit = DevExpress.XtraRichEdit.DocumentLayoutUnit.Pixel; + this.richEditControl1.Location = new System.Drawing.Point(123, 106); + this.richEditControl1.Name = "richEditControl1"; + this.richEditControl1.Size = new System.Drawing.Size(449, 60); + this.richEditControl1.TabIndex = 9; + this.richEditControl1.Text = "这是一条测试消息!"; + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.richEditControl2); + this.groupControl1.Location = new System.Drawing.Point(17, 258); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(598, 260); + this.groupControl1.TabIndex = 9; + this.groupControl1.Text = "请求响应结果"; + // + // richEditControl2 + // + this.richEditControl2.ActiveViewType = DevExpress.XtraRichEdit.RichEditViewType.Simple; + this.richEditControl2.Dock = System.Windows.Forms.DockStyle.Fill; + this.richEditControl2.LayoutUnit = DevExpress.XtraRichEdit.DocumentLayoutUnit.Pixel; + this.richEditControl2.Location = new System.Drawing.Point(2, 21); + this.richEditControl2.Name = "richEditControl2"; + this.richEditControl2.ReadOnly = true; + this.richEditControl2.Size = new System.Drawing.Size(594, 237); + this.richEditControl2.TabIndex = 10; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(257, 181); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(141, 35); + this.simpleButton1.TabIndex = 10; + this.simpleButton1.Text = "发送数据"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl4 + // + this.labelControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.labelControl4.Location = new System.Drawing.Point(72, 190); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(28, 14); + this.labelControl4.TabIndex = 11; + this.labelControl4.Text = "类型:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.comboBoxEdit1.Location = new System.Drawing.Point(123, 188); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(101, 20); + this.comboBoxEdit1.TabIndex = 12; + // + // simpleButton2 + // + this.simpleButton2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(429, 180); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(143, 35); + this.simpleButton2.TabIndex = 13; + this.simpleButton2.Text = "清空响应"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // maskedTextBox2 + // + this.maskedTextBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.maskedTextBox2.Location = new System.Drawing.Point(123, 68); + this.maskedTextBox2.Name = "maskedTextBox2"; + this.maskedTextBox2.Size = new System.Drawing.Size(449, 22); + this.maskedTextBox2.TabIndex = 14; + this.maskedTextBox2.Text = "张三"; + // + // plugin_debug + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.groupBox1); + this.Name = "plugin_debug"; + this.Size = new System.Drawing.Size(636, 533); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.MaskedTextBox maskedTextBox1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraRichEdit.RichEditControl richEditControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraRichEdit.RichEditControl richEditControl2; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private System.Windows.Forms.MaskedTextBox maskedTextBox2; + } +} diff --git a/FLSystem/Forms/plugin_debug.cs b/FLSystem/Forms/plugin_debug.cs new file mode 100644 index 0000000..22f52f7 --- /dev/null +++ b/FLSystem/Forms/plugin_debug.cs @@ -0,0 +1,54 @@ +using Api.Framework; +using Api.Framework.Events; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; + +namespace FLSystem.Forms +{ + public partial class plugin_debug : DevExpress.XtraEditors.XtraUserControl + { + public plugin_debug() + { + InitializeComponent(); + foreach (ChatType t in Enum.GetValues(typeof(ChatType))) + { + this.comboBoxEdit1.Properties.Items.Add(t); + } + this.comboBoxEdit1.SelectedIndex = 0; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + DebugEvent debug = new DebugEvent(sendmsg, this.maskedTextBox1.Text, this.maskedTextBox2.Text, this.richEditControl1.Text, Util.ConvertEnum<ChatType>(this.comboBoxEdit1.Text)); + EventClient.OnEvent(this, debug); + } + catch (Exception ex) + { + UI.Framework.Forms.BaseForm.ShowError(ex); + } + } + + private void sendmsg(string username, string message) + { + this.Invoke(new Action(delegate + { + try + { + this.richEditControl2.Text += message + "\r\n"; + } + catch (Exception) + { + } + })); + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.richEditControl2.ResetText(); + } + + } +} diff --git a/FLSystem/Forms/plugin_debug.resx b/FLSystem/Forms/plugin_debug.resx new file mode 100644 index 0000000..dbf57f5 --- /dev/null +++ b/FLSystem/Forms/plugin_debug.resx @@ -0,0 +1,199 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton2.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAcdEVYdFRpdGxlAENsZWFyRm9ybWF0dGluZztDbGVhcjuAYheoAAAJV0lEQVRYR52XeVyO6RrH + Hwpt0iKlMkwM5nNm/jkznzPbYTSFV7yO0mjTYg2DIqUoW4WkQjsSEVPIpEn2TKGkbCnStCi0jEKrFn7n + up56X83MO2dmzv35fLvu9+15rt/vue7rue8SZGPUqFGCzpgxgrHxP/oZGo79W/A9dG8/ztF3APhTxDF0 + 6Lh+w0aMoWTj+xsYj1UyHDGO4DhW+c8Zp0z3KNO9SpSjP+fqyfoXDbBrvnHfiYJvDqbdzzuUVoQE4tCP + PYjztGKi9zsFka+JTy28Gf19rjnlUqKcoglFgr9FMDEx6Wf43ljl/Sl3G5/WteAtffuWfvxd+N79J+81 + Uq4BnFMswV8ZRkbj+xkYfTAwNvmWmKiz+w06uhQzZ8EGMb7u7Pn8urO7F5p3dSM2+TYo1yAdHSMlSs0m + RAodZwn35v5HuMs4zBTu2EuF23ZSocB2hiBQE/WndRwUkXgTb8hBByfrm1j++Q2snX3RRQbbO7pF2uSx + S4zhh/OgZzBKXVV18EASHtCLMtGfjRTYzRAKbKYL+cy3FkKetURmYKxKSHwOut+8FZOKvJbFLpFWwspx + HTrpyXkup70LLRSb2zvw/ZlCaOkYaOXYWASW+qxAqfdyXLOWBJA4GxKrkmc9TbgxWyLkWE0VrltOlhtQ + 84+4TE/3VkzaQkkt5/pglsNakfy7j9DS1oWZ9l6Q2ntCardG5OadR2hq7cSr1g40E5nXS3F59tQdj3cF + ojUvE603MlEZ6o/MWeaBJK4iM9Fy7byQPdNcyJaaiQb4dVP3CUqnde2mZJ1iUka2FNNtPEigE9PneKCd + v6PKcMmnfbsKr1o6iHa8bGpFZlAoKkK34EVqIur3BqM+dgdenEpAWdAGnLWYtJXEVWUmMi1MhcuSSXID + GmsCT4tJG5peIyf/IYmthsWcVbAgERZqpyWRWLuJy9HwqkO8bqrVSrS20fxlMx7G70P5jk1oPHkItZHb + UBuxFbXhgajdE4DGpDiUBKzHafMJ20hcjeC+6HfO/N9yA4PdN6eI6/n8ZTsJuaORBFrbO0WmWq0Q42TL + 78TlqX/RhrrGNqxaF4JXTS0oiotF6TY/NHx/ADVhW/AsdDOehTCb8GznRjzd4YdfDsegaKMXjn/9+XYS + V5eZYAO8ow1Z7psslr2Okk+2XEFrTvPGVlHIbOZSNNNnM2lPrHneivqGZuw9eBLF+2PwyH89CcTiCZWa + qd7uh+ptvqjeuh7VgetQFeCDKn9vPE86gKKdgTjyxSdBchM9BsZpuXofw8uW16hpaMWVnPv4RroEpswM + VxHugUnTXYnFWO65A7HxJ5ATFoIHG71RFxdJAiSyxVvk8ea1eLzJC483ehJrULnBA092bkZDRjJKPJbh + qusCREXGswlVPnyUafPQXuh5RCz70+ctRCtqyUgTdXYP3JQdqK5rxsvmNjS+eIW70REo9l2D2phdqPTz + QKUvsxoV65lVqFjnjgofN1R4r0TVVj88TzuGfEsJsmdMQ/7NEqS5r+aTSJO3YuXhtATOqw7VXM2vwJNf + mvH0lxaKPYjz+mZU1zdR6ZtRU9eAm+G7Uejtjmd7glHutZJYgXJPZjnK1jDfoYyetGz1UlRu9kb9ycO4 + OXMKsiwkyM0uRPb8hTg7azobGMKHUX8949Gqls7b7RxXxtc7uR2EkzvBkXB2i6cYD/9daTiacg0xQQdw + d80KPA0OxM9uSwhXkdKVzGKUriCWLyIWopyqUkuNmTfdHFckU3A96y6yXOYjYfRIrDXUD+vtA4HPcmVj + YxM1qoQ2LYce9cQwakwRA6PRBnoGI420dPTH2PolRR28UoHrV+/j0ZL5IiWMKzOvh8UuKFnkgjJPNzxL + iEWuxBSXJ09GduZtXHGah/hRI+A+TG836WoTvEP2HBhcCW0TkwHUEwOoMQcyurrGKpqaeuoqKupDbTel + hMVdLkdeTRsulDfhh5RsPJzviIfzmLk9uDAOKHVbiidx4bg+eSIumZsh69JtZM51xr73jLBMV3cP6ekQ + gwg+I+RDfnr1wjsWX6RluzElZO+Fn3Gtuhk/PnohJykpE8UONnKK7OegZOlCVEWHItt0As6bmiHzfAEu + 2jsh2sgQi3S0WVyX4G1ZPKB+/ccBjcUR1znwL7k8Wta+x0OjzpUis/wVTtx/jpOFDTh5n+iNRxIuoNDa + UuTBQhdU7tqGrAlf4NxEU1w6m4/zNo6IMNCHi6ZmOOUbSsjFg4yMfv1XS+/gp+djVMvKJyl0z5kSnC15 + gSO36nCkoA6JFBNl8Va9SNy+DBQ7z6WteAuufPUZMiZMwoX0PJz91gG79IfBQUMjgvLpEXwWiOLzNDSE + AH2D3xmQlV5jlk9ySOjph0gtasC+3BrEiTwT2d87l8UEMpS9OwqXP/sUZ76aiHNpuciYbY8QvaGwVVeP + pHwycfEgemApFRzU1ITNQ4cpNMB7tI7Hvjwk36lH+E/ViCDCf6pCeFYVzTlWI5LnREzOE0RlVcAu4DyC + HNcjIzUH6ZZ2CNbVxWxVNRYnlXfixVKpwNioqAp+2tQOCgxw+XXdonIRfKHyHRcrsfNCBUIYcV6J3Veq + EHaxFFYb0mHjm4bkjPsIWx6E7do6kKqoRlEefYJPvx5xCwtBhuXAQYLPEHoTFRjgCmiaLo0LXxyZC//0 + MvifKUNAHwKJYDKyLZ2Obc9UWHr9gGPp97BgSwbGzwjDh3ofRVMOWuB34kUSidAX6YCBgpfGEIVNyE3C + r5/el86RUU6hV+F76hFRKo9byNTGlHswd0vGDPfjSDx9B05+aRgzNRhDxs2LoXuHE38ozkxTGiB4qA1W + aEDWiLxu+p/Y7oq2DcqE5/Fi4gHWpT6Ez9Fb+HpJIiTLjuFw6h3Ye5/C+2bbofmBs0yct9g/FGemKCkL + q1Q0fm9g0nfHOchM8FMYfGwVHGPlf1E04H7wBj53OQizRQlISCnAHM8TGDHRH4NHO8bStYaEXPyYV7RC + ccasv5LgNogu/a2BLxcnCV8sOsrTviaGj5duj/7YLh4f2RzABJd4bAo+ColrPMZZ7oX6+w785CwuL/sY + rQ9JRFnkGxElEdM+KDTwr/mJwqfOh4V/OiXwx77Lwfs3bV3CSIL/C2V4zt/x9ip/1Uy0xotik3qFOCpC + oQEFg01wY/Lrydszb6V94Ybl34nixN8bf8GAbHDy/8X/MQThv4TMqWeYOnwhAAAAAElFTkSuQmCC +</value> + </data> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAALdEVYdFRpdGxlAFNlbmQ7faSt1wAABfBJREFUWEftl+lPVGcUxq+1VHG3/Q+aptPNtKlR00ai + NcaNqFiT9oPRToxGkG1UNoFhk30AcQHZdBQEBxAQUKQC4gKCpS5NoyW4oCig7MMOok/Pee+dARUbbBP6 + ob3Jj+ecd4b3Oefwzp2LBOBfZdTF8WTUxfFk1MXxZDh4/ZowDoxagOnFiQrvvgUWY4Tf+w4xQdIllqp0 + CRfU4fGl+rD40mp+Ic5Qae2lr+xKy7uJtNzfkJp7E8eJlJwbSM5mruNY1nUcPclcw5HMazicWYXDGVVI + Sq9CouEXJBiuIj7tKuJSK3GIiD1egdiUCsSkXEFY0sXfQ2MLlpLXRIlMpfC4UimMEBXRokdC2aAmrgwv + aDQC+vF2vMBzgnU06h48wXHvCCN5WZDxeVXooRJ1yKESfUhsCU/AwiHmMjz1legfGEJ//xD6SPtYid7+ + ZwTrCPpojRHxEHooZgafPUdDpC/qdVrUh3nhcYgnBgafo8bTCTfWf8d/90lSSGyxFBwjQxdPwMLpwEU0 + tvYqBs8UYzlmA1nJRDEUMdOroMRs9ih4Nx4FuqPO3xUPfVxobQi/2izGlR+suYDJUvDBYlXQwSJ10IEi + feCBczyB93RJlzDURwUo3ZgNTN0pJt2KISvTJXRQyQdFAQ+1O1HrpUGthzPuuzmKtesbVyM63MAFWEpk + KgXu/1kKIOjikzlpX3wxHoR4oJsMu9lImNHGiqkpZ0Nh2iNrVw+vEZxTzN3ec3HAvZ12uKvZhjtOW9FP + a521tQjcf44LmCIF7CtUBUQXqv2iC/V+0Wd5ApPKHGxx+6fVsqnoxmTAqpgQnZR3sinBasLYTUqwWY3D + FtTYbUb1NjX+2LpJnKvOngHYB+bJBZCx5Bd1VvKNKqBcTGDyrY3WqLbfYO5m5OavQUZGsw6QOTOIDlJx + iPkAv4Im6hyWOaZxAVMln8gCFaHWRhbovSPO8AQsqzatR+/jOrMBK5vwxsOYzAaEmZmul2lnOhXt6hfx + UrtUrJALmCZpI05L3joi/DTlYgKWUSEnxMhNZvuSK4kKRB+rUPSKiPeS7j0qE6XQ3skmshFrm5kBtCpq + 45IB54AcuQCv8HyVZ1i+mtDvDs3jCUzxiSyEV2K5uYv65m40EPVNBKsJzonHgi6BMDIqhqwKHDMtRM3D + NrgF5XIB0yUylTxCcgV08b1/6gbffKzzyjOPTHSp507LEUUaSUTpy4VGHilHBHNYVmFEnbJRi7EPLR0E + xx0M5/3obO+Ebos3FzBDcg/OVbkFn1K7BeboXQNzeAJT17jnYtOes6ILHp/o8GkXHr2BOuaJjGxsMutD + Mxk2m2OivR+XNv6I/DkfcQEzJdegHMl1D5NNuZjAtLXup3C/wWgem7nLI2XUaRl03K1QhaQyhBO6xDIy + kI2aTIYc05pMr+DU5x8iY+6XcgEue7JVuwKy1bv8s/Q7/bN4AtOd/E+h10jd0C/zyDqUwyifdEX5fIw4 + 9e1KPGw2bPqU9GmbAuX5C+fBXRPDBcySyFTa4X9S2uF3knIxgRluPgbcdNwyPDalC7MqjDQSJiazkTGZ + PhHmvaQyDbeqYe+VzgXMljR+mSqNb6Za45Opd/LJ4AnMyFmzFpcXfa1sLo/NFPNGTYSpG85Hbi6gL7KX + 4tYeoY2U85dcI32CvrfTywU4+2RITlomnXL5DFxc+BUur1qC1pq7YgrbdcVYZHcCNnQ2qh+0wdhqRBXd + Vs9/M4fetxhN1XeoqB7YhhbBalsa1rhk49b9FrQ3t6Ny8wYUz/sMF5ZbofF2NRpbemDjkIxPrCO4gBmS + ozZd5eiVrnb0NugdPA08gUmpq1YnB3gktLrQZ9XaOR1WtiewZLsBjn7Z2O2fgayV1ihZ8AXOWC2Ar3si + NHRTWelowMKtqVhsm4bt2iy4ag3IWLYCRXM/Rf6386F1SYCTbxaW26fh45XhmL9Ol0Jelq8+E5qeBScT + 04lZxOxXeP8v+GCMzCQsiYlveijlW/LfedgcK8MPpaMU8E8vbmCs/P+f0X++AEh/AqKkSSOGWHRQAAAA + AElFTkSuQmCC +</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/plugin_manage.Designer.cs b/FLSystem/Forms/plugin_manage.Designer.cs new file mode 100644 index 0000000..b4b5cdb --- /dev/null +++ b/FLSystem/Forms/plugin_manage.Designer.cs @@ -0,0 +1,54 @@ +using System; + +namespace FLSystem.Forms +{ + partial class plugin_manage + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + try + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + catch (Exception ex) + {} + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.SuspendLayout(); + // + // plugin_manage + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.AutoScroll = true; + this.Name = "plugin_manage"; + this.Size = new System.Drawing.Size(751, 527); + this.Load += new System.EventHandler(this.plugin_manage_Load); + //this.SizeChanged += new System.EventHandler(this.plugin_manage_SizeChanged); + this.ResumeLayout(false); + + } + + #endregion + } +} diff --git a/FLSystem/Forms/plugin_manage.cs b/FLSystem/Forms/plugin_manage.cs new file mode 100644 index 0000000..2efedb0 --- /dev/null +++ b/FLSystem/Forms/plugin_manage.cs @@ -0,0 +1,54 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class plugin_manage : DevExpress.XtraEditors.XtraUserControl + { + public plugin_manage() + { + InitializeComponent(); + } + + private void plugin_manage_Load(object sender, EventArgs e) + { + List<Control> list = new List<Control>(); + var _list = PluginClient.Plugins.ToArray(); + foreach (Plugin item in _list) + { + #region 显示的插件,不显示的continue了 + if (ApiClient.ShowPluginList != null) + { + if (!item.FilePath.ToLower().Contains("\\main.dll")) + { + var flag = ApiClient.ShowPluginList.FirstOrDefault(f => item.FilePath.Contains(f)); + if (string.IsNullOrWhiteSpace(flag)) + { + item.Stop(); + continue; + } + } + } + #endregion + + list.Add(new plugin_control(item)); + } + this.Invoke(new Action(() => + { + try + { + this.AddContrals(list.ToArray()); + } + catch (Exception) + { + } + })); + } + } +} diff --git a/FLSystem/Forms/plugin_manage.resx b/FLSystem/Forms/plugin_manage.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Forms/plugin_manage.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/plugin_sort_form.Designer.cs b/FLSystem/Forms/plugin_sort_form.Designer.cs new file mode 100644 index 0000000..d3fa276 --- /dev/null +++ b/FLSystem/Forms/plugin_sort_form.Designer.cs @@ -0,0 +1,100 @@ +namespace FLSystem.Forms +{ + partial class plugin_sort_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SuspendLayout(); + // + // listView1 + // + this.listView1.AllowDrop = true; + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader4, + this.columnHeader3}); + this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.Location = new System.Drawing.Point(0, 0); + this.listView1.MultiSelect = false; + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(603, 451); + this.listView1.TabIndex = 1; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "序号"; + // + // columnHeader2 + // + this.columnHeader2.Text = "插件名"; + this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader2.Width = 120; + // + // columnHeader3 + // + this.columnHeader3.Text = "简介"; + this.columnHeader3.Width = 350; + // + // columnHeader4 + // + this.columnHeader4.Text = "状态"; + this.columnHeader4.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // plugin_sort_form + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(603, 451); + this.Controls.Add(this.listView1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "plugin_sort_form"; + this.Text = "调整执行顺序(靠前优先执行)"; + this.Load += new System.EventHandler(this.plugin_sort_control_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/plugin_sort_form.cs b/FLSystem/Forms/plugin_sort_form.cs new file mode 100644 index 0000000..3d334f2 --- /dev/null +++ b/FLSystem/Forms/plugin_sort_form.cs @@ -0,0 +1,98 @@ +using Api.Framework; +using System; +using System.Drawing; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class plugin_sort_form : BaseForm + { + public plugin_sort_form() + { + InitializeComponent(); + this.listView1.DragDrop += ListView1_DragDrop; + this.listView1.DragEnter += ListView1_DragEnter; + this.listView1.ItemDrag += listView1_ItemDrag; + this.listView1.DragOver += ListView1_DragOver; + } + + private void ListView1_DragOver(object sender, DragEventArgs e) + { + try + { + Point p = new Point(e.X, e.Y); + Point point2 = this.listView1.PointToClient(p); + ListViewItem itemAt = this.listView1.GetItemAt(point2.X, point2.Y); + if (itemAt != null) itemAt.Selected = true; + } + catch (Exception exception) + { + ShowError(exception); + } + } + + private void ListView1_DragEnter(object sender, DragEventArgs e) + { + try + { + e.Effect = DragDropEffects.Move; + } + catch (Exception exception) + { + ShowError(exception); + } + } + + private void ListView1_DragDrop(object sender, DragEventArgs e) + { + try + { + ListViewItem data = (ListViewItem)e.Data.GetData(typeof(ListViewItem)); + Point p = new Point(e.X, e.Y); + Point point2 = this.listView1.PointToClient(p); + + + ListViewItem itemAt = this.listView1.GetItemAt(point2.X, point2.Y); + PluginClient.MovePlugin(data.Index, (itemAt == null ? int.MaxValue : itemAt.Index)); + + if (itemAt == null) + this.listView1.Items.Insert(this.listView1.Items.Count, (ListViewItem)data.Clone()); + else + { + int index = itemAt.Index; + if (data.Index < index) + index++; + this.listView1.Items.Insert(index, (ListViewItem)data.Clone()); + } + this.listView1.Items.Remove(data); + } + catch (Exception exception) + { + ShowError(exception); + } + } + + private void listView1_ItemDrag(object sender, ItemDragEventArgs e) + { + try + { + this.listView1.DoDragDrop(e.Item, DragDropEffects.Move); + } + catch (Exception) + { } + } + + private void plugin_sort_control_Load(object sender, EventArgs e) + { + int number = 1; + foreach (var item in PluginClient.Plugins) + { + var view = new ListViewItem(new string[] { number++.ToString(), item.Name, item.IsRun ? "运行中" : "未启用", item.Note }); + if (!item.IsRun) view.ForeColor = Color.Gray; + else view.ForeColor = Color.Green; + this.listView1.Items.Add(view); + } + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/plugin_sort_form.resx b/FLSystem/Forms/plugin_sort_form.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/plugin_sort_form.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/point_manage_control.Designer.cs b/FLSystem/Forms/point_manage_control.Designer.cs new file mode 100644 index 0000000..e4a40bb --- /dev/null +++ b/FLSystem/Forms/point_manage_control.Designer.cs @@ -0,0 +1,2444 @@ +namespace FLSystem.Forms +{ + partial class point_manage_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(point_manage_control)); + DevExpress.XtraGrid.GridLevelNode gridLevelNode1 = new DevExpress.XtraGrid.GridLevelNode(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.label3 = new System.Windows.Forms.Label(); + this.pageControl3 = new UI.Framework.Controls.PageControl(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.查看积分日志ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查询平台订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.拼多多订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.阿里妈妈订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.京东联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.唯品联盟订单ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.抖音联盟订单ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.一键审核勾选项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.商户付款ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.微信支付ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.没收金额ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.退回ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已审核ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn36 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.comboBoxEdit4 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker5 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker6 = new System.Windows.Forms.DateTimePicker(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label2 = new System.Windows.Forms.Label(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn35 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn41 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.comboBoxEdit5 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker3 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker4 = new System.Windows.Forms.DateTimePicker(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.label4 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.comboBoxEdit3 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.pageControl4 = new UI.Framework.Controls.PageControl(); + this.gridControl4 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip3 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.查询平台订单ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.多多进宝订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.阿里妈妈订单ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.京东联盟订单ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.唯品联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.抖音联盟订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.兑换信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.未兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.已兑换提现ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.查看用户信息ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView4 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn28 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn40 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn39 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn29 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn30 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn31 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn38 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn37 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn32 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn33 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn34 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.splitContainerControl1 = new DevExpress.XtraEditors.SplitContainerControl(); + this.label1 = new System.Windows.Forms.Label(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn42 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn43 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn44 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn45 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn46 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn47 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn49 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn51 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn52 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn50 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn53 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn48 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.panel1 = new System.Windows.Forms.Panel(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.checkEdit2 = new DevExpress.XtraEditors.CheckEdit(); + this.checkEdit1 = new DevExpress.XtraEditors.CheckEdit(); + this.button1 = new System.Windows.Forms.Button(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.linkLabel6 = new System.Windows.Forms.LinkLabel(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.linkLabel5 = new System.Windows.Forms.LinkLabel(); + this.linkLabel3 = new System.Windows.Forms.LinkLabel(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.linkLabel4 = new System.Windows.Forms.LinkLabel(); + this.linkLabel7 = new System.Windows.Forms.LinkLabel(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.comboBoxEdit8 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit6 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.simpleButton4 = new DevExpress.XtraEditors.SimpleButton(); + this.dateTimePicker7 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker8 = new System.Windows.Forms.DateTimePicker(); + this.comboBoxEdit7 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.textBox4 = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.groupBox3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).BeginInit(); + this.contextMenuStrip3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).BeginInit(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1)).BeginInit(); + this.splitContainerControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.groupBox4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit8.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit7.Properties)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage2; + this.xtraTabControl1.Size = new System.Drawing.Size(965, 667); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3, + this.xtraTabPage4}); + this.xtraTabControl1.SelectedPageChanged += new DevExpress.XtraTab.TabPageChangedEventHandler(this.xtraTabControl1_SelectedPageChanged); + this.xtraTabControl1.Click += new System.EventHandler(this.xtraTabControl1_Click); + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.label3); + this.xtraTabPage2.Controls.Add(this.pageControl3); + this.xtraTabPage2.Controls.Add(this.gridControl3); + this.xtraTabPage2.Controls.Add(this.groupBox2); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(963, 643); + this.xtraTabPage2.Text = " 未 兑 换 列 表 "; + // + // label3 + // + this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label3.AutoSize = true; + this.label3.BackColor = System.Drawing.Color.White; + this.label3.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.Location = new System.Drawing.Point(330, 198); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(303, 35); + this.label3.TabIndex = 77; + this.label3.Text = "尚未有人申请兑换"; + // + // pageControl3 + // + this.pageControl3.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl3.Location = new System.Drawing.Point(0, 606); + this.pageControl3.Name = "pageControl3"; + this.pageControl3.Size = new System.Drawing.Size(963, 37); + this.pageControl3.TabIndex = 76; + // + // gridControl3 + // + this.gridControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl3.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl3.Location = new System.Drawing.Point(-1, 86); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.Size = new System.Drawing.Size(965, 509); + this.gridControl3.TabIndex = 75; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看积分日志ToolStripMenuItem, + this.查询平台订单ToolStripMenuItem, + this.查看用户信息ToolStripMenuItem, + this.一键审核勾选项ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(161, 92); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 查看积分日志ToolStripMenuItem + // + this.查看积分日志ToolStripMenuItem.Name = "查看积分日志ToolStripMenuItem"; + this.查看积分日志ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.查看积分日志ToolStripMenuItem.Text = "查看积分日志"; + this.查看积分日志ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem2_Click); + // + // 查询平台订单ToolStripMenuItem + // + this.查询平台订单ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.拼多多订单ToolStripMenuItem, + this.阿里妈妈订单ToolStripMenuItem, + this.京东联盟订单ToolStripMenuItem, + this.唯品联盟订单ToolStripMenuItem1, + this.抖音联盟订单ToolStripMenuItem1}); + this.查询平台订单ToolStripMenuItem.Name = "查询平台订单ToolStripMenuItem"; + this.查询平台订单ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.查询平台订单ToolStripMenuItem.Text = "查询平台订单"; + // + // 拼多多订单ToolStripMenuItem + // + this.拼多多订单ToolStripMenuItem.Name = "拼多多订单ToolStripMenuItem"; + this.拼多多订单ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.拼多多订单ToolStripMenuItem.Text = "多多进宝订单"; + this.拼多多订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 阿里妈妈订单ToolStripMenuItem + // + this.阿里妈妈订单ToolStripMenuItem.Name = "阿里妈妈订单ToolStripMenuItem"; + this.阿里妈妈订单ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.阿里妈妈订单ToolStripMenuItem.Text = "阿里妈妈订单"; + this.阿里妈妈订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 京东联盟订单ToolStripMenuItem + // + this.京东联盟订单ToolStripMenuItem.Name = "京东联盟订单ToolStripMenuItem"; + this.京东联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.京东联盟订单ToolStripMenuItem.Text = "京东联盟订单"; + this.京东联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 唯品联盟订单ToolStripMenuItem1 + // + this.唯品联盟订单ToolStripMenuItem1.Name = "唯品联盟订单ToolStripMenuItem1"; + this.唯品联盟订单ToolStripMenuItem1.Size = new System.Drawing.Size(148, 22); + this.唯品联盟订单ToolStripMenuItem1.Text = "唯品联盟订单"; + this.唯品联盟订单ToolStripMenuItem1.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 抖音联盟订单ToolStripMenuItem1 + // + this.抖音联盟订单ToolStripMenuItem1.Name = "抖音联盟订单ToolStripMenuItem1"; + this.抖音联盟订单ToolStripMenuItem1.Size = new System.Drawing.Size(148, 22); + this.抖音联盟订单ToolStripMenuItem1.Text = "抖音联盟订单"; + this.抖音联盟订单ToolStripMenuItem1.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 查看用户信息ToolStripMenuItem + // + this.查看用户信息ToolStripMenuItem.Name = "查看用户信息ToolStripMenuItem"; + this.查看用户信息ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.查看用户信息ToolStripMenuItem.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem.Click += new System.EventHandler(this.查看用户信息1ToolStripMenuItem_Click); + // + // 一键审核勾选项ToolStripMenuItem + // + this.一键审核勾选项ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.商户付款ToolStripMenuItem, + this.微信支付ToolStripMenuItem, + this.没收金额ToolStripMenuItem, + this.退回ToolStripMenuItem, + this.已审核ToolStripMenuItem}); + this.一键审核勾选项ToolStripMenuItem.Name = "一键审核勾选项ToolStripMenuItem"; + this.一键审核勾选项ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.一键审核勾选项ToolStripMenuItem.Text = "一键审核勾选项"; + // + // 商户付款ToolStripMenuItem + // + this.商户付款ToolStripMenuItem.Name = "商户付款ToolStripMenuItem"; + this.商户付款ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.商户付款ToolStripMenuItem.Text = "商户支付"; + this.商户付款ToolStripMenuItem.Click += new System.EventHandler(this.OneKeyToolStripMenuItem_Click); + // + // 微信支付ToolStripMenuItem + // + this.微信支付ToolStripMenuItem.Name = "微信支付ToolStripMenuItem"; + this.微信支付ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.微信支付ToolStripMenuItem.Text = "微信支付"; + this.微信支付ToolStripMenuItem.Click += new System.EventHandler(this.OneKeyToolStripMenuItem_Click); + // + // 没收金额ToolStripMenuItem + // + this.没收金额ToolStripMenuItem.Name = "没收金额ToolStripMenuItem"; + this.没收金额ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.没收金额ToolStripMenuItem.Text = "没收兑换"; + this.没收金额ToolStripMenuItem.Click += new System.EventHandler(this.OneKeyToolStripMenuItem_Click); + // + // 退回ToolStripMenuItem + // + this.退回ToolStripMenuItem.Name = "退回ToolStripMenuItem"; + this.退回ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.退回ToolStripMenuItem.Text = "退回兑换"; + this.退回ToolStripMenuItem.Click += new System.EventHandler(this.OneKeyToolStripMenuItem_Click); + // + // 已审核ToolStripMenuItem + // + this.已审核ToolStripMenuItem.Name = "已审核ToolStripMenuItem"; + this.已审核ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.已审核ToolStripMenuItem.Text = "已审核"; + this.已审核ToolStripMenuItem.Click += new System.EventHandler(this.OneKeyToolStripMenuItem_Click); + // + // gridView3 + // + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn6, + this.gridColumn20, + this.gridColumn36, + this.gridColumn13, + this.gridColumn14, + this.gridColumn1, + this.gridColumn15, + this.gridColumn16, + this.gridColumn17, + this.gridColumn19, + this.gridColumn18, + this.gridColumn9, + this.gridColumn7, + this.gridColumn26}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsBehavior.Editable = false; + this.gridView3.OptionsSelection.MultiSelect = true; + this.gridView3.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView3.OptionsView.ColumnAutoWidth = false; + this.gridView3.OptionsView.ShowFooter = true; + this.gridView3.OptionsView.ShowGroupPanel = false; + this.gridView3.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView3_RowClick); + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn6.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "平台类型"; + this.gridColumn6.FieldName = "chattype"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 1; + this.gridColumn6.Width = 69; + // + // gridColumn20 + // + this.gridColumn20.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn20.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn20.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn20.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn20.Caption = "机器人帐号"; + this.gridColumn20.FieldName = "robot_name"; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 2; + this.gridColumn20.Width = 88; + // + // gridColumn36 + // + this.gridColumn36.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn36.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn36.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn36.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn36.Caption = "机器人昵称"; + this.gridColumn36.FieldName = "robot_nick"; + this.gridColumn36.Name = "gridColumn36"; + this.gridColumn36.OptionsColumn.AllowEdit = false; + this.gridColumn36.Visible = true; + this.gridColumn36.VisibleIndex = 3; + this.gridColumn36.Width = 137; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn13.AppearanceCell.Options.UseForeColor = true; + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "用户账号"; + this.gridColumn13.FieldName = "username"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.ReadOnly = true; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 4; + this.gridColumn13.Width = 116; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn14.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "昵称"; + this.gridColumn14.FieldName = "usernick"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 5; + this.gridColumn14.Width = 99; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "用户备注"; + this.gridColumn1.FieldName = "member_remark"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 6; + this.gridColumn1.Width = 74; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn15.AppearanceCell.Options.UseForeColor = true; + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn15.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "支付宝账号"; + this.gridColumn15.FieldName = "alipay_num"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.ReadOnly = true; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 7; + this.gridColumn15.Width = 89; + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn16.AppearanceCell.Options.UseForeColor = true; + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn16.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "支付宝名称"; + this.gridColumn16.FieldName = "alipay_name"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.OptionsColumn.ReadOnly = true; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 8; + this.gridColumn16.Width = 95; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn17.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "用户积分"; + this.gridColumn17.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.gridColumn17.FieldName = "point"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Custom, "point", "{0}")}); + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 9; + this.gridColumn17.Width = 69; + // + // gridColumn19 + // + this.gridColumn19.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, ((System.Drawing.FontStyle)((System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Underline)))); + this.gridColumn19.AppearanceCell.ForeColor = System.Drawing.Color.Red; + this.gridColumn19.AppearanceCell.Options.UseFont = true; + this.gridColumn19.AppearanceCell.Options.UseForeColor = true; + this.gridColumn19.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn19.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn19.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn19.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn19.Caption = "状态"; + this.gridColumn19.FieldName = "state"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 10; + this.gridColumn19.Width = 68; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn18.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "兑换时间"; + this.gridColumn18.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn18.FieldName = "time"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.UnboundType = DevExpress.Data.UnboundColumnType.DateTime; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 11; + this.gridColumn18.Width = 130; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn9.AppearanceCell.Options.UseForeColor = true; + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn9.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "身份证姓名"; + this.gridColumn9.FieldName = "identity_name"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 12; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn7.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "身份证号码"; + this.gridColumn7.FieldName = "identity_card"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 13; + // + // gridColumn26 + // + this.gridColumn26.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn26.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn26.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn26.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn26.Caption = "备注"; + this.gridColumn26.FieldName = "remark"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.OptionsColumn.AllowEdit = false; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 14; + this.gridColumn26.Width = 191; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.comboBoxEdit4); + this.groupBox2.Controls.Add(this.hyperlinkLabelControl1); + this.groupBox2.Controls.Add(this.simpleButton2); + this.groupBox2.Controls.Add(this.checkBox2); + this.groupBox2.Controls.Add(this.dateTimePicker5); + this.groupBox2.Controls.Add(this.dateTimePicker6); + this.groupBox2.Controls.Add(this.comboBoxEdit1); + this.groupBox2.Controls.Add(this.labelControl1); + this.groupBox2.Controls.Add(this.textBox3); + this.groupBox2.Location = new System.Drawing.Point(11, 11); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(940, 69); + this.groupBox2.TabIndex = 74; + this.groupBox2.TabStop = false; + this.groupBox2.Text = " 条 件 选 项 "; + // + // comboBoxEdit4 + // + this.comboBoxEdit4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit4.EditValue = "全部数据"; + this.comboBoxEdit4.Location = new System.Drawing.Point(252, 26); + this.comboBoxEdit4.Name = "comboBoxEdit4"; + this.comboBoxEdit4.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit4.Properties.Items.AddRange(new object[] { + "全部数据", + "客户账号", + "客户昵称", + "客户备注", + "客户编号", + "支付宝账号", + "支付宝姓名"}); + this.comboBoxEdit4.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit4.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit4.TabIndex = 80; + this.comboBoxEdit4.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit4_SelectedIndexChanged); + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(838, 28); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(84, 14); + this.hyperlinkLabelControl1.TabIndex = 79; + this.hyperlinkLabelControl1.Text = "校准机器人信息"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // simpleButton2 + // + this.simpleButton2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton2.Appearance.Font = new System.Drawing.Font("Tahoma", 10F); + this.simpleButton2.Appearance.Options.UseFont = true; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(726, 21); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(77, 29); + this.simpleButton2.TabIndex = 78; + this.simpleButton2.Text = " 搜 索 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // checkBox2 + // + this.checkBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(495, 27); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(86, 18); + this.checkBox2.TabIndex = 77; + this.checkBox2.Text = "日期范围:"; + this.checkBox2.UseVisualStyleBackColor = true; + this.checkBox2.CheckedChanged += new System.EventHandler(this.checkBox2_CheckedChanged); + // + // dateTimePicker5 + // + this.dateTimePicker5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker5.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker5.Enabled = false; + this.dateTimePicker5.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker5.Location = new System.Drawing.Point(586, 39); + this.dateTimePicker5.Name = "dateTimePicker5"; + this.dateTimePicker5.Size = new System.Drawing.Size(110, 22); + this.dateTimePicker5.TabIndex = 75; + // + // dateTimePicker6 + // + this.dateTimePicker6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker6.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker6.Enabled = false; + this.dateTimePicker6.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker6.Location = new System.Drawing.Point(586, 11); + this.dateTimePicker6.Name = "dateTimePicker6"; + this.dateTimePicker6.Size = new System.Drawing.Size(110, 22); + this.dateTimePicker6.TabIndex = 74; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit1.EditValue = ""; + this.comboBoxEdit1.Location = new System.Drawing.Point(385, 26); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(104, 20); + this.comboBoxEdit1.TabIndex = 73; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(57, 29); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(36, 14); + this.labelControl1.TabIndex = 71; + this.labelControl1.Text = "搜索:"; + // + // textBox3 + // + this.textBox3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textBox3.Enabled = false; + this.textBox3.Location = new System.Drawing.Point(95, 25); + this.textBox3.Name = "textBox3"; + this.textBox3.Size = new System.Drawing.Size(151, 22); + this.textBox3.TabIndex = 70; + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label2); + this.xtraTabPage1.Controls.Add(this.gridControl2); + this.xtraTabPage1.Controls.Add(this.pageControl2); + this.xtraTabPage1.Controls.Add(this.groupBox3); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(963, 643); + this.xtraTabPage1.Text = " 已 兑 换 列 表 "; + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(330, 198); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(303, 35); + this.label2.TabIndex = 79; + this.label2.Text = "尚未有人兑换成功"; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl2.Location = new System.Drawing.Point(-1, 87); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(964, 508); + this.gridControl2.TabIndex = 77; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn5, + this.gridColumn8, + this.gridColumn27, + this.gridColumn35, + this.gridColumn10, + this.gridColumn11, + this.gridColumn2, + this.gridColumn12, + this.gridColumn21, + this.gridColumn22, + this.gridColumn24, + this.gridColumn23, + this.gridColumn41, + this.gridColumn25, + this.gridColumn4, + this.gridColumn3}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ColumnAutoWidth = false; + this.gridView2.OptionsView.ShowFooter = true; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn5.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "ID"; + this.gridColumn5.FieldName = "id"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 0; + this.gridColumn5.Width = 45; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn8.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "平台类型"; + this.gridColumn8.FieldName = "chattype"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 1; + this.gridColumn8.Width = 74; + // + // gridColumn27 + // + this.gridColumn27.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn27.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn27.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.Caption = "机器人账号"; + this.gridColumn27.FieldName = "robot_name"; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 2; + this.gridColumn27.Width = 97; + // + // gridColumn35 + // + this.gridColumn35.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn35.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn35.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn35.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn35.Caption = "机器人昵称"; + this.gridColumn35.FieldName = "robot_nick"; + this.gridColumn35.Name = "gridColumn35"; + this.gridColumn35.Visible = true; + this.gridColumn35.VisibleIndex = 3; + this.gridColumn35.Width = 101; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn10.AppearanceCell.Options.UseForeColor = true; + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn10.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "用户账号"; + this.gridColumn10.FieldName = "username"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.ReadOnly = true; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 4; + this.gridColumn10.Width = 105; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn11.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "昵称"; + this.gridColumn11.FieldName = "usernick"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.OptionsColumn.AllowFocus = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 5; + this.gridColumn11.Width = 100; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "用户备注"; + this.gridColumn2.FieldName = "member_remark"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 6; + this.gridColumn2.Width = 76; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn12.AppearanceCell.Options.UseForeColor = true; + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn12.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "支付宝账号"; + this.gridColumn12.FieldName = "alipay_num"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.ReadOnly = true; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 7; + this.gridColumn12.Width = 98; + // + // gridColumn21 + // + this.gridColumn21.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn21.AppearanceCell.Options.UseForeColor = true; + this.gridColumn21.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn21.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn21.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn21.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn21.Caption = "支付宝名称"; + this.gridColumn21.FieldName = "alipay_name"; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.ReadOnly = true; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 8; + this.gridColumn21.Width = 94; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "用户积分"; + this.gridColumn22.FieldName = "point"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.OptionsColumn.AllowEdit = false; + this.gridColumn22.OptionsColumn.AllowFocus = false; + this.gridColumn22.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Custom, "point", "{0}")}); + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 9; + this.gridColumn22.Width = 81; + // + // gridColumn24 + // + this.gridColumn24.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn24.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn24.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn24.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn24.Caption = "状态"; + this.gridColumn24.FieldName = "state"; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 10; + this.gridColumn24.Width = 68; + // + // gridColumn23 + // + this.gridColumn23.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn23.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn23.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn23.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn23.Caption = "兑换时间"; + this.gridColumn23.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn23.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn23.FieldName = "time"; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.OptionsColumn.AllowEdit = false; + this.gridColumn23.OptionsColumn.AllowFocus = false; + this.gridColumn23.UnboundType = DevExpress.Data.UnboundColumnType.DateTime; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 11; + this.gridColumn23.Width = 133; + // + // gridColumn41 + // + this.gridColumn41.Caption = "审核时间"; + this.gridColumn41.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn41.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn41.FieldName = "check_time"; + this.gridColumn41.Name = "gridColumn41"; + this.gridColumn41.Visible = true; + this.gridColumn41.VisibleIndex = 12; + // + // gridColumn25 + // + this.gridColumn25.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn25.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn25.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn25.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn25.Caption = "备注"; + this.gridColumn25.FieldName = "remark"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 13; + this.gridColumn25.Width = 150; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn4.AppearanceCell.Options.UseForeColor = true; + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "身份证姓名"; + this.gridColumn4.FieldName = "identity_name"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.ReadOnly = true; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 14; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn3.AppearanceCell.Options.UseForeColor = true; + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "身份证号码"; + this.gridColumn3.FieldName = "identity_card"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.ReadOnly = true; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 15; + this.gridColumn3.Width = 117; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 606); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(963, 37); + this.pageControl2.TabIndex = 76; + // + // groupBox3 + // + this.groupBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox3.Controls.Add(this.comboBoxEdit5); + this.groupBox3.Controls.Add(this.simpleButton3); + this.groupBox3.Controls.Add(this.checkBox1); + this.groupBox3.Controls.Add(this.dateTimePicker3); + this.groupBox3.Controls.Add(this.dateTimePicker4); + this.groupBox3.Controls.Add(this.comboBoxEdit2); + this.groupBox3.Controls.Add(this.labelControl4); + this.groupBox3.Controls.Add(this.textBox2); + this.groupBox3.Location = new System.Drawing.Point(11, 11); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(940, 70); + this.groupBox3.TabIndex = 75; + this.groupBox3.TabStop = false; + this.groupBox3.Text = " 条 件 选 项 "; + // + // comboBoxEdit5 + // + this.comboBoxEdit5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit5.EditValue = "全部数据"; + this.comboBoxEdit5.Location = new System.Drawing.Point(259, 28); + this.comboBoxEdit5.Name = "comboBoxEdit5"; + this.comboBoxEdit5.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit5.Properties.Items.AddRange(new object[] { + "全部数据", + "客户账号", + "客户昵称", + "客户备注", + "客户编号", + "支付宝账号", + "支付宝姓名"}); + this.comboBoxEdit5.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit5.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit5.TabIndex = 81; + this.comboBoxEdit5.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit5_SelectedIndexChanged); + // + // simpleButton3 + // + this.simpleButton3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton3.Appearance.Font = new System.Drawing.Font("Tahoma", 10F); + this.simpleButton3.Appearance.Options.UseFont = true; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(780, 20); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(77, 29); + this.simpleButton3.TabIndex = 78; + this.simpleButton3.Text = " 搜 索 "; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(549, 29); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(86, 18); + this.checkBox1.TabIndex = 77; + this.checkBox1.Text = "日期范围:"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // dateTimePicker3 + // + this.dateTimePicker3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker3.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker3.Enabled = false; + this.dateTimePicker3.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker3.Location = new System.Drawing.Point(640, 39); + this.dateTimePicker3.Name = "dateTimePicker3"; + this.dateTimePicker3.Size = new System.Drawing.Size(110, 22); + this.dateTimePicker3.TabIndex = 75; + // + // dateTimePicker4 + // + this.dateTimePicker4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker4.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker4.Enabled = false; + this.dateTimePicker4.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker4.Location = new System.Drawing.Point(640, 11); + this.dateTimePicker4.Name = "dateTimePicker4"; + this.dateTimePicker4.Size = new System.Drawing.Size(110, 22); + this.dateTimePicker4.TabIndex = 74; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit2.EditValue = ""; + this.comboBoxEdit2.Location = new System.Drawing.Point(398, 28); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(122, 20); + this.comboBoxEdit2.TabIndex = 73; + // + // labelControl4 + // + this.labelControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl4.Location = new System.Drawing.Point(63, 31); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(36, 14); + this.labelControl4.TabIndex = 71; + this.labelControl4.Text = "搜索:"; + // + // textBox2 + // + this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textBox2.Enabled = false; + this.textBox2.Location = new System.Drawing.Point(101, 27); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(152, 22); + this.textBox2.TabIndex = 70; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.label4); + this.xtraTabPage3.Controls.Add(this.groupBox1); + this.xtraTabPage3.Controls.Add(this.pageControl4); + this.xtraTabPage3.Controls.Add(this.gridControl4); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(963, 643); + this.xtraTabPage3.Text = " 积 分 日 志 明 细 "; + // + // label4 + // + this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label4.AutoSize = true; + this.label4.BackColor = System.Drawing.Color.White; + this.label4.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label4.Location = new System.Drawing.Point(366, 196); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(231, 35); + this.label4.TabIndex = 74; + this.label4.Text = "尚未查到数据"; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.comboBoxEdit3); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.dateTimePicker2); + this.groupBox1.Controls.Add(this.dateTimePicker1); + this.groupBox1.Location = new System.Drawing.Point(11, 11); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(940, 67); + this.groupBox1.TabIndex = 73; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 条 件 选 项 "; + // + // comboBoxEdit3 + // + this.comboBoxEdit3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit3.EditValue = "全部数据"; + this.comboBoxEdit3.Location = new System.Drawing.Point(285, 26); + this.comboBoxEdit3.Name = "comboBoxEdit3"; + this.comboBoxEdit3.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit3.Properties.Items.AddRange(new object[] { + "全部数据", + "客户账号", + "客户昵称", + "客户备注", + "客户编号", + "支付宝账号", + "支付宝姓名"}); + this.comboBoxEdit3.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit3.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit3.TabIndex = 72; + this.comboBoxEdit3.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit3_SelectedIndexChanged); + // + // textBox1 + // + this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textBox1.Enabled = false; + this.textBox1.Location = new System.Drawing.Point(105, 25); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(174, 22); + this.textBox1.TabIndex = 63; + // + // labelControl2 + // + this.labelControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl2.Location = new System.Drawing.Point(51, 29); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(48, 14); + this.labelControl2.TabIndex = 65; + this.labelControl2.Text = "关键词:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.Appearance.Font = new System.Drawing.Font("Tahoma", 10F); + this.simpleButton1.Appearance.Options.UseFont = true; + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(795, 16); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(80, 40); + this.simpleButton1.TabIndex = 64; + this.simpleButton1.Text = " 搜 索 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl5 + // + this.labelControl5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl5.Location = new System.Drawing.Point(598, 29); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(60, 14); + this.labelControl5.TabIndex = 71; + this.labelControl5.Text = "日期范围:"; + // + // comboBox1 + // + this.comboBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(473, 25); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(119, 22); + this.comboBox1.TabIndex = 67; + // + // labelControl3 + // + this.labelControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl3.Location = new System.Drawing.Point(407, 29); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 66; + this.labelControl3.Text = "操作类型:"; + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(666, 40); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(110, 22); + this.dateTimePicker2.TabIndex = 69; + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(666, 12); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(110, 22); + this.dateTimePicker1.TabIndex = 68; + // + // pageControl4 + // + this.pageControl4.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl4.Location = new System.Drawing.Point(0, 606); + this.pageControl4.Name = "pageControl4"; + this.pageControl4.Size = new System.Drawing.Size(963, 37); + this.pageControl4.TabIndex = 62; + // + // gridControl4 + // + this.gridControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl4.ContextMenuStrip = this.contextMenuStrip3; + this.gridControl4.Location = new System.Drawing.Point(-1, 84); + this.gridControl4.MainView = this.gridView4; + this.gridControl4.Name = "gridControl4"; + this.gridControl4.Size = new System.Drawing.Size(965, 511); + this.gridControl4.TabIndex = 61; + this.gridControl4.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView4}); + // + // contextMenuStrip3 + // + this.contextMenuStrip3.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip3.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查询平台订单ToolStripMenuItem1, + this.兑换信息ToolStripMenuItem, + this.查看用户信息ToolStripMenuItem1}); + this.contextMenuStrip3.Name = "contextMenuStrip1"; + this.contextMenuStrip3.Size = new System.Drawing.Size(149, 70); + this.contextMenuStrip3.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip3_Opening); + // + // 查询平台订单ToolStripMenuItem1 + // + this.查询平台订单ToolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.多多进宝订单ToolStripMenuItem, + this.阿里妈妈订单ToolStripMenuItem1, + this.京东联盟订单ToolStripMenuItem1, + this.唯品联盟订单ToolStripMenuItem, + this.抖音联盟订单ToolStripMenuItem}); + this.查询平台订单ToolStripMenuItem1.Name = "查询平台订单ToolStripMenuItem1"; + this.查询平台订单ToolStripMenuItem1.Size = new System.Drawing.Size(148, 22); + this.查询平台订单ToolStripMenuItem1.Text = "查询平台订单"; + // + // 多多进宝订单ToolStripMenuItem + // + this.多多进宝订单ToolStripMenuItem.Name = "多多进宝订单ToolStripMenuItem"; + this.多多进宝订单ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.多多进宝订单ToolStripMenuItem.Text = "多多进宝订单"; + this.多多进宝订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 阿里妈妈订单ToolStripMenuItem1 + // + this.阿里妈妈订单ToolStripMenuItem1.Name = "阿里妈妈订单ToolStripMenuItem1"; + this.阿里妈妈订单ToolStripMenuItem1.Size = new System.Drawing.Size(148, 22); + this.阿里妈妈订单ToolStripMenuItem1.Text = "阿里妈妈订单"; + this.阿里妈妈订单ToolStripMenuItem1.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 京东联盟订单ToolStripMenuItem1 + // + this.京东联盟订单ToolStripMenuItem1.Name = "京东联盟订单ToolStripMenuItem1"; + this.京东联盟订单ToolStripMenuItem1.Size = new System.Drawing.Size(148, 22); + this.京东联盟订单ToolStripMenuItem1.Text = "京东联盟订单"; + this.京东联盟订单ToolStripMenuItem1.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 唯品联盟订单ToolStripMenuItem + // + this.唯品联盟订单ToolStripMenuItem.Name = "唯品联盟订单ToolStripMenuItem"; + this.唯品联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.唯品联盟订单ToolStripMenuItem.Text = "唯品联盟订单"; + this.唯品联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 抖音联盟订单ToolStripMenuItem + // + this.抖音联盟订单ToolStripMenuItem.Name = "抖音联盟订单ToolStripMenuItem"; + this.抖音联盟订单ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.抖音联盟订单ToolStripMenuItem.Text = "抖音联盟订单"; + this.抖音联盟订单ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem_Click); + // + // 兑换信息ToolStripMenuItem + // + this.兑换信息ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.未兑换提现ToolStripMenuItem, + this.已兑换提现ToolStripMenuItem}); + this.兑换信息ToolStripMenuItem.Name = "兑换信息ToolStripMenuItem"; + this.兑换信息ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.兑换信息ToolStripMenuItem.Text = "兑换信息"; + // + // 未兑换提现ToolStripMenuItem + // + this.未兑换提现ToolStripMenuItem.Name = "未兑换提现ToolStripMenuItem"; + this.未兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.未兑换提现ToolStripMenuItem.Text = "未兑换提现"; + this.未兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem2_Click); + // + // 已兑换提现ToolStripMenuItem + // + this.已兑换提现ToolStripMenuItem.Name = "已兑换提现ToolStripMenuItem"; + this.已兑换提现ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.已兑换提现ToolStripMenuItem.Text = "已兑换提现"; + this.已兑换提现ToolStripMenuItem.Click += new System.EventHandler(this.ToolStripMenuItem2_Click); + // + // 查看用户信息ToolStripMenuItem1 + // + this.查看用户信息ToolStripMenuItem1.Name = "查看用户信息ToolStripMenuItem1"; + this.查看用户信息ToolStripMenuItem1.Size = new System.Drawing.Size(148, 22); + this.查看用户信息ToolStripMenuItem1.Text = "查看用户信息"; + this.查看用户信息ToolStripMenuItem1.Click += new System.EventHandler(this.查看用户信息1ToolStripMenuItem_Click); + // + // gridView4 + // + this.gridView4.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn28, + this.gridColumn40, + this.gridColumn39, + this.gridColumn29, + this.gridColumn30, + this.gridColumn31, + this.gridColumn38, + this.gridColumn37, + this.gridColumn32, + this.gridColumn33, + this.gridColumn34}); + this.gridView4.GridControl = this.gridControl4; + this.gridView4.Name = "gridView4"; + this.gridView4.OptionsView.ColumnAutoWidth = false; + this.gridView4.OptionsView.ShowFooter = true; + this.gridView4.OptionsView.ShowGroupPanel = false; + // + // gridColumn28 + // + this.gridColumn28.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn28.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn28.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn28.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn28.Caption = "平台类型"; + this.gridColumn28.FieldName = "chattype"; + this.gridColumn28.Name = "gridColumn28"; + this.gridColumn28.OptionsColumn.AllowEdit = false; + this.gridColumn28.OptionsColumn.AllowFocus = false; + this.gridColumn28.Visible = true; + this.gridColumn28.VisibleIndex = 0; + this.gridColumn28.Width = 69; + // + // gridColumn40 + // + this.gridColumn40.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn40.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn40.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn40.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn40.Caption = "机器人账号"; + this.gridColumn40.FieldName = "robot_name"; + this.gridColumn40.Name = "gridColumn40"; + this.gridColumn40.Visible = true; + this.gridColumn40.VisibleIndex = 1; + // + // gridColumn39 + // + this.gridColumn39.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn39.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn39.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn39.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn39.Caption = "机器人昵称"; + this.gridColumn39.FieldName = "robot_nick"; + this.gridColumn39.Name = "gridColumn39"; + this.gridColumn39.Visible = true; + this.gridColumn39.VisibleIndex = 2; + this.gridColumn39.Width = 87; + // + // gridColumn29 + // + this.gridColumn29.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn29.AppearanceCell.Options.UseForeColor = true; + this.gridColumn29.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn29.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn29.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.Caption = "用户账号"; + this.gridColumn29.FieldName = "username"; + this.gridColumn29.Name = "gridColumn29"; + this.gridColumn29.OptionsColumn.ReadOnly = true; + this.gridColumn29.Visible = true; + this.gridColumn29.VisibleIndex = 3; + this.gridColumn29.Width = 116; + // + // gridColumn30 + // + this.gridColumn30.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn30.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn30.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn30.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn30.Caption = "昵称"; + this.gridColumn30.FieldName = "usernick"; + this.gridColumn30.Name = "gridColumn30"; + this.gridColumn30.Visible = true; + this.gridColumn30.VisibleIndex = 4; + this.gridColumn30.Width = 124; + // + // gridColumn31 + // + this.gridColumn31.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn31.AppearanceCell.Options.UseForeColor = true; + this.gridColumn31.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn31.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn31.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn31.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn31.Caption = "操作积分"; + this.gridColumn31.FieldName = "point"; + this.gridColumn31.Name = "gridColumn31"; + this.gridColumn31.OptionsColumn.ReadOnly = true; + this.gridColumn31.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Custom, "point", "{0}")}); + this.gridColumn31.Visible = true; + this.gridColumn31.VisibleIndex = 5; + this.gridColumn31.Width = 85; + // + // gridColumn38 + // + this.gridColumn38.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn38.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn38.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn38.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn38.Caption = "修改前"; + this.gridColumn38.FieldName = "before_point"; + this.gridColumn38.Name = "gridColumn38"; + this.gridColumn38.Visible = true; + this.gridColumn38.VisibleIndex = 6; + this.gridColumn38.Width = 83; + // + // gridColumn37 + // + this.gridColumn37.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn37.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn37.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn37.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn37.Caption = "修改后"; + this.gridColumn37.FieldName = "after_point"; + this.gridColumn37.Name = "gridColumn37"; + this.gridColumn37.Visible = true; + this.gridColumn37.VisibleIndex = 7; + this.gridColumn37.Width = 76; + // + // gridColumn32 + // + this.gridColumn32.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn32.AppearanceCell.Options.UseForeColor = true; + this.gridColumn32.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn32.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn32.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn32.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn32.Caption = "操作类型"; + this.gridColumn32.FieldName = "pointtype"; + this.gridColumn32.Name = "gridColumn32"; + this.gridColumn32.OptionsColumn.AllowEdit = false; + this.gridColumn32.OptionsColumn.AllowFocus = false; + this.gridColumn32.OptionsColumn.ReadOnly = true; + this.gridColumn32.Visible = true; + this.gridColumn32.VisibleIndex = 8; + this.gridColumn32.Width = 99; + // + // gridColumn33 + // + this.gridColumn33.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn33.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn33.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.Caption = "操作备注"; + this.gridColumn33.FieldName = "message"; + this.gridColumn33.Name = "gridColumn33"; + this.gridColumn33.Visible = true; + this.gridColumn33.VisibleIndex = 9; + this.gridColumn33.Width = 405; + // + // gridColumn34 + // + this.gridColumn34.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn34.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn34.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn34.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn34.Caption = "发生时间"; + this.gridColumn34.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn34.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn34.FieldName = "crt_time"; + this.gridColumn34.Name = "gridColumn34"; + this.gridColumn34.OptionsColumn.AllowEdit = false; + this.gridColumn34.OptionsColumn.AllowFocus = false; + this.gridColumn34.UnboundType = DevExpress.Data.UnboundColumnType.DateTime; + this.gridColumn34.Visible = true; + this.gridColumn34.VisibleIndex = 10; + this.gridColumn34.Width = 168; + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.splitContainerControl1); + this.xtraTabPage4.Controls.Add(this.pageControl1); + this.xtraTabPage4.Controls.Add(this.groupBox4); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(963, 643); + this.xtraTabPage4.Text = " 商 户 链 接 明 细 "; + // + // splitContainerControl1 + // + this.splitContainerControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainerControl1.Location = new System.Drawing.Point(-1, 75); + this.splitContainerControl1.Name = "splitContainerControl1"; + this.splitContainerControl1.Panel1.Controls.Add(this.label1); + this.splitContainerControl1.Panel1.Controls.Add(this.gridControl1); + this.splitContainerControl1.Panel1.Text = "Panel1"; + this.splitContainerControl1.Panel2.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Simple; + this.splitContainerControl1.Panel2.Controls.Add(this.panel1); + this.splitContainerControl1.Panel2.Text = "Panel2"; + this.splitContainerControl1.Size = new System.Drawing.Size(965, 525); + this.splitContainerControl1.SplitterPosition = 707; + this.splitContainerControl1.TabIndex = 82; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(245, 196); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(231, 35); + this.label1.TabIndex = 83; + this.label1.Text = "未查询到数据"; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + gridLevelNode1.RelationName = "Level1"; + this.gridControl1.LevelTree.Nodes.AddRange(new DevExpress.XtraGrid.GridLevelNode[] { + gridLevelNode1}); + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(707, 525); + this.gridControl1.TabIndex = 82; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1}); + this.contextMenuStrip2.Name = "contextMenuStrip1"; + this.contextMenuStrip2.Size = new System.Drawing.Size(137, 26); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(136, 22); + this.toolStripMenuItem1.Text = "发送选中项"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn42, + this.gridColumn43, + this.gridColumn44, + this.gridColumn45, + this.gridColumn46, + this.gridColumn47, + this.gridColumn49, + this.gridColumn51, + this.gridColumn52, + this.gridColumn50, + this.gridColumn53, + this.gridColumn48}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowFooter = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn42 + // + this.gridColumn42.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn42.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn42.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn42.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn42.Caption = "ID"; + this.gridColumn42.FieldName = "id"; + this.gridColumn42.Name = "gridColumn42"; + this.gridColumn42.OptionsColumn.AllowEdit = false; + this.gridColumn42.OptionsColumn.AllowFocus = false; + this.gridColumn42.Visible = true; + this.gridColumn42.VisibleIndex = 1; + this.gridColumn42.Width = 40; + // + // gridColumn43 + // + this.gridColumn43.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn43.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn43.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn43.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn43.Caption = "平台类型"; + this.gridColumn43.FieldName = "chattype"; + this.gridColumn43.Name = "gridColumn43"; + this.gridColumn43.OptionsColumn.AllowEdit = false; + this.gridColumn43.OptionsColumn.AllowFocus = false; + this.gridColumn43.Visible = true; + this.gridColumn43.VisibleIndex = 2; + this.gridColumn43.Width = 64; + // + // gridColumn44 + // + this.gridColumn44.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn44.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn44.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn44.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn44.Caption = "机器人账号"; + this.gridColumn44.FieldName = "robot_name"; + this.gridColumn44.Name = "gridColumn44"; + this.gridColumn44.Visible = true; + this.gridColumn44.VisibleIndex = 3; + this.gridColumn44.Width = 77; + // + // gridColumn45 + // + this.gridColumn45.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn45.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn45.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn45.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn45.Caption = "机器人昵称"; + this.gridColumn45.FieldName = "robot_nick"; + this.gridColumn45.Name = "gridColumn45"; + this.gridColumn45.Visible = true; + this.gridColumn45.VisibleIndex = 4; + this.gridColumn45.Width = 91; + // + // gridColumn46 + // + this.gridColumn46.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn46.AppearanceCell.Options.UseForeColor = true; + this.gridColumn46.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn46.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn46.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn46.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn46.Caption = "用户账号"; + this.gridColumn46.FieldName = "username"; + this.gridColumn46.Name = "gridColumn46"; + this.gridColumn46.OptionsColumn.ReadOnly = true; + this.gridColumn46.Visible = true; + this.gridColumn46.VisibleIndex = 5; + this.gridColumn46.Width = 78; + // + // gridColumn47 + // + this.gridColumn47.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn47.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn47.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn47.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn47.Caption = "昵称"; + this.gridColumn47.FieldName = "usernick"; + this.gridColumn47.Name = "gridColumn47"; + this.gridColumn47.OptionsColumn.AllowEdit = false; + this.gridColumn47.OptionsColumn.AllowFocus = false; + this.gridColumn47.Visible = true; + this.gridColumn47.VisibleIndex = 6; + this.gridColumn47.Width = 95; + // + // gridColumn49 + // + this.gridColumn49.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn49.AppearanceCell.Options.UseForeColor = true; + this.gridColumn49.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn49.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn49.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn49.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn49.Caption = "商户连接"; + this.gridColumn49.FieldName = "payurl"; + this.gridColumn49.Name = "gridColumn49"; + this.gridColumn49.OptionsColumn.ReadOnly = true; + this.gridColumn49.Width = 197; + // + // gridColumn51 + // + this.gridColumn51.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn51.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn51.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn51.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn51.Caption = "提现积分"; + this.gridColumn51.FieldName = "point"; + this.gridColumn51.Name = "gridColumn51"; + this.gridColumn51.OptionsColumn.AllowEdit = false; + this.gridColumn51.OptionsColumn.AllowFocus = false; + this.gridColumn51.Summary.AddRange(new DevExpress.XtraGrid.GridSummaryItem[] { + new DevExpress.XtraGrid.GridColumnSummaryItem(DevExpress.Data.SummaryItemType.Custom, "point", "{0}")}); + this.gridColumn51.Visible = true; + this.gridColumn51.VisibleIndex = 7; + this.gridColumn51.Width = 57; + // + // gridColumn52 + // + this.gridColumn52.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn52.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn52.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn52.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn52.Caption = "领取状态"; + this.gridColumn52.FieldName = "paytype"; + this.gridColumn52.Name = "gridColumn52"; + this.gridColumn52.OptionsColumn.AllowEdit = false; + this.gridColumn52.Visible = true; + this.gridColumn52.VisibleIndex = 8; + this.gridColumn52.Width = 64; + // + // gridColumn50 + // + this.gridColumn50.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn50.AppearanceCell.Options.UseForeColor = true; + this.gridColumn50.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn50.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn50.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn50.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn50.Caption = "生成时间"; + this.gridColumn50.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn50.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn50.FieldName = "ctime"; + this.gridColumn50.Name = "gridColumn50"; + this.gridColumn50.OptionsColumn.ReadOnly = true; + this.gridColumn50.UnboundType = DevExpress.Data.UnboundColumnType.DateTime; + this.gridColumn50.Visible = true; + this.gridColumn50.VisibleIndex = 9; + this.gridColumn50.Width = 79; + // + // gridColumn53 + // + this.gridColumn53.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn53.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn53.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn53.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn53.Caption = "领取时间"; + this.gridColumn53.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn53.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn53.FieldName = "paytime"; + this.gridColumn53.Name = "gridColumn53"; + this.gridColumn53.OptionsColumn.AllowEdit = false; + this.gridColumn53.OptionsColumn.AllowFocus = false; + this.gridColumn53.UnboundType = DevExpress.Data.UnboundColumnType.DateTime; + this.gridColumn53.Visible = true; + this.gridColumn53.VisibleIndex = 10; + this.gridColumn53.Width = 112; + // + // gridColumn48 + // + this.gridColumn48.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn48.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn48.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn48.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn48.Caption = "用户备注"; + this.gridColumn48.FieldName = "remark"; + this.gridColumn48.Name = "gridColumn48"; + this.gridColumn48.OptionsColumn.AllowEdit = false; + this.gridColumn48.Visible = true; + this.gridColumn48.VisibleIndex = 11; + this.gridColumn48.Width = 63; + // + // panel1 + // + this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.panel1.AutoScroll = true; + this.panel1.Controls.Add(this.labelControl12); + this.panel1.Controls.Add(this.checkEdit2); + this.panel1.Controls.Add(this.checkEdit1); + this.panel1.Controls.Add(this.button1); + this.panel1.Controls.Add(this.memoEdit1); + this.panel1.Controls.Add(this.linkLabel6); + this.panel1.Controls.Add(this.linkLabel2); + this.panel1.Controls.Add(this.linkLabel5); + this.panel1.Controls.Add(this.linkLabel3); + this.panel1.Controls.Add(this.labelControl11); + this.panel1.Controls.Add(this.labelControl10); + this.panel1.Controls.Add(this.linkLabel1); + this.panel1.Controls.Add(this.linkLabel4); + this.panel1.Controls.Add(this.linkLabel7); + this.panel1.Location = new System.Drawing.Point(10, 4); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(229, 505); + this.panel1.TabIndex = 5; + // + // labelControl12 + // + this.labelControl12.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl12.Appearance.Options.UseForeColor = true; + this.labelControl12.Location = new System.Drawing.Point(27, 70); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(180, 14); + this.labelControl12.TabIndex = 5; + this.labelControl12.Text = "注:手动勾选发送过的不会再通知"; + this.labelControl12.Visible = false; + // + // checkEdit2 + // + this.checkEdit2.Location = new System.Drawing.Point(29, 90); + this.checkEdit2.Name = "checkEdit2"; + this.checkEdit2.Properties.Caption = "商户支持小程序的发小程序"; + this.checkEdit2.Size = new System.Drawing.Size(161, 18); + this.checkEdit2.TabIndex = 4; + // + // checkEdit1 + // + this.checkEdit1.Location = new System.Drawing.Point(34, 49); + this.checkEdit1.Name = "checkEdit1"; + this.checkEdit1.Properties.Caption = "通知24小时未领取的用户"; + this.checkEdit1.Size = new System.Drawing.Size(161, 18); + this.checkEdit1.TabIndex = 4; + this.checkEdit1.Visible = false; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(56, 11); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(103, 27); + this.button1.TabIndex = 2; + this.button1.Text = " 保 存 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(27, 133); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(161, 156); + this.memoEdit1.TabIndex = 0; + // + // linkLabel6 + // + this.linkLabel6.AutoSize = true; + this.linkLabel6.Location = new System.Drawing.Point(34, 355); + this.linkLabel6.Name = "linkLabel6"; + this.linkLabel6.Size = new System.Drawing.Size(65, 14); + this.linkLabel6.TabIndex = 3; + this.linkLabel6.TabStop = true; + this.linkLabel6.Text = "[兑换金额]"; + this.linkLabel6.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked); + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(113, 315); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(77, 14); + this.linkLabel2.TabIndex = 3; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "[机器人昵称]"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked); + // + // linkLabel5 + // + this.linkLabel5.AutoSize = true; + this.linkLabel5.Location = new System.Drawing.Point(123, 336); + this.linkLabel5.Name = "linkLabel5"; + this.linkLabel5.Size = new System.Drawing.Size(65, 14); + this.linkLabel5.TabIndex = 3; + this.linkLabel5.TabStop = true; + this.linkLabel5.Text = "[领取地址]"; + this.linkLabel5.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked); + // + // linkLabel3 + // + this.linkLabel3.AutoSize = true; + this.linkLabel3.Location = new System.Drawing.Point(34, 336); + this.linkLabel3.Name = "linkLabel3"; + this.linkLabel3.Size = new System.Drawing.Size(41, 14); + this.linkLabel3.TabIndex = 3; + this.linkLabel3.TabStop = true; + this.linkLabel3.Text = "[账号]"; + this.linkLabel3.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked); + // + // labelControl11 + // + this.labelControl11.Location = new System.Drawing.Point(37, 295); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(60, 14); + this.labelControl11.TabIndex = 1; + this.labelControl11.Text = "支持变量:"; + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(33, 116); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(84, 14); + this.labelControl10.TabIndex = 1; + this.labelControl10.Text = "通知内容设置:"; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(34, 315); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(77, 14); + this.linkLabel1.TabIndex = 3; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "[机器人账号]"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked); + // + // linkLabel4 + // + this.linkLabel4.AutoSize = true; + this.linkLabel4.Location = new System.Drawing.Point(79, 336); + this.linkLabel4.Name = "linkLabel4"; + this.linkLabel4.Size = new System.Drawing.Size(41, 14); + this.linkLabel4.TabIndex = 3; + this.linkLabel4.TabStop = true; + this.linkLabel4.Text = "[昵称]"; + this.linkLabel4.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked); + // + // linkLabel7 + // + this.linkLabel7.AutoSize = true; + this.linkLabel7.Location = new System.Drawing.Point(113, 355); + this.linkLabel7.Name = "linkLabel7"; + this.linkLabel7.Size = new System.Drawing.Size(65, 14); + this.linkLabel7.TabIndex = 3; + this.linkLabel7.TabStop = true; + this.linkLabel7.Text = "[积分名称]"; + this.linkLabel7.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 606); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(963, 37); + this.pageControl1.TabIndex = 79; + // + // groupBox4 + // + this.groupBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox4.Controls.Add(this.comboBoxEdit8); + this.groupBox4.Controls.Add(this.labelControl9); + this.groupBox4.Controls.Add(this.comboBoxEdit6); + this.groupBox4.Controls.Add(this.simpleButton4); + this.groupBox4.Controls.Add(this.dateTimePicker7); + this.groupBox4.Controls.Add(this.dateTimePicker8); + this.groupBox4.Controls.Add(this.comboBoxEdit7); + this.groupBox4.Controls.Add(this.labelControl8); + this.groupBox4.Controls.Add(this.labelControl7); + this.groupBox4.Controls.Add(this.labelControl6); + this.groupBox4.Controls.Add(this.textBox4); + this.groupBox4.Location = new System.Drawing.Point(11, 5); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(940, 70); + this.groupBox4.TabIndex = 78; + this.groupBox4.TabStop = false; + this.groupBox4.Text = " 条 件 选 项 "; + // + // comboBoxEdit8 + // + this.comboBoxEdit8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit8.EditValue = ""; + this.comboBoxEdit8.Location = new System.Drawing.Point(499, 29); + this.comboBoxEdit8.Name = "comboBoxEdit8"; + this.comboBoxEdit8.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit8.Properties.Items.AddRange(new object[] { + "全部状态", + "未领取", + "已领取"}); + this.comboBoxEdit8.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit8.Size = new System.Drawing.Size(87, 20); + this.comboBoxEdit8.TabIndex = 83; + // + // labelControl9 + // + this.labelControl9.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl9.Location = new System.Drawing.Point(462, 32); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(36, 14); + this.labelControl9.TabIndex = 82; + this.labelControl9.Text = "状态:"; + // + // comboBoxEdit6 + // + this.comboBoxEdit6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit6.EditValue = "全部数据"; + this.comboBoxEdit6.Location = new System.Drawing.Point(222, 29); + this.comboBoxEdit6.Name = "comboBoxEdit6"; + this.comboBoxEdit6.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit6.Properties.Items.AddRange(new object[] { + "全部数据", + "客户账号", + "客户昵称", + "客户备注", + "客户编号", + "机器人编号", + "机器人账号", + "机器人昵称"}); + this.comboBoxEdit6.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit6.Size = new System.Drawing.Size(79, 20); + this.comboBoxEdit6.TabIndex = 81; + this.comboBoxEdit6.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit6_SelectedIndexChanged); + // + // simpleButton4 + // + this.simpleButton4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton4.Appearance.Font = new System.Drawing.Font("Tahoma", 10F); + this.simpleButton4.Appearance.Options.UseFont = true; + this.simpleButton4.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton4.ImageOptions.Image"))); + this.simpleButton4.Location = new System.Drawing.Point(804, 25); + this.simpleButton4.Name = "simpleButton4"; + this.simpleButton4.Size = new System.Drawing.Size(77, 29); + this.simpleButton4.TabIndex = 78; + this.simpleButton4.Text = " 搜 索 "; + this.simpleButton4.Click += new System.EventHandler(this.simpleButton4_Click); + // + // dateTimePicker7 + // + this.dateTimePicker7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker7.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker7.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker7.Location = new System.Drawing.Point(664, 42); + this.dateTimePicker7.Name = "dateTimePicker7"; + this.dateTimePicker7.Size = new System.Drawing.Size(110, 22); + this.dateTimePicker7.TabIndex = 75; + // + // dateTimePicker8 + // + this.dateTimePicker8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker8.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker8.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker8.Location = new System.Drawing.Point(664, 14); + this.dateTimePicker8.Name = "dateTimePicker8"; + this.dateTimePicker8.Size = new System.Drawing.Size(110, 22); + this.dateTimePicker8.TabIndex = 74; + // + // comboBoxEdit7 + // + this.comboBoxEdit7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.comboBoxEdit7.EditValue = ""; + this.comboBoxEdit7.Location = new System.Drawing.Point(357, 29); + this.comboBoxEdit7.Name = "comboBoxEdit7"; + this.comboBoxEdit7.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit7.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit7.Size = new System.Drawing.Size(87, 20); + this.comboBoxEdit7.TabIndex = 73; + // + // labelControl8 + // + this.labelControl8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl8.Location = new System.Drawing.Point(604, 32); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(60, 14); + this.labelControl8.TabIndex = 71; + this.labelControl8.Text = "生成日期:"; + // + // labelControl7 + // + this.labelControl7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl7.Location = new System.Drawing.Point(320, 32); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(36, 14); + this.labelControl7.TabIndex = 71; + this.labelControl7.Text = "平台:"; + // + // labelControl6 + // + this.labelControl6.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl6.Location = new System.Drawing.Point(50, 32); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(36, 14); + this.labelControl6.TabIndex = 71; + this.labelControl6.Text = "搜索:"; + // + // textBox4 + // + this.textBox4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.textBox4.Enabled = false; + this.textBox4.Location = new System.Drawing.Point(88, 28); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(128, 22); + this.textBox4.TabIndex = 70; + // + // point_manage_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.xtraTabControl1); + this.Name = "point_manage_control"; + this.Size = new System.Drawing.Size(965, 667); + this.Load += new System.EventHandler(this.point_manage_control_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraTabPage3.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).EndInit(); + this.contextMenuStrip3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).EndInit(); + this.xtraTabPage4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainerControl1)).EndInit(); + this.splitContainerControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit8.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit7.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private UI.Framework.Controls.PageControl pageControl4; + private DevExpress.XtraGrid.GridControl gridControl4; + private DevExpress.XtraGrid.Views.Grid.GridView gridView4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn28; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn29; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn30; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn31; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn38; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn37; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn32; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn33; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn34; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.DateTimePicker dateTimePicker5; + private System.Windows.Forms.DateTimePicker dateTimePicker6; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.TextBox textBox3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private System.Windows.Forms.GroupBox groupBox3; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker3; + private System.Windows.Forms.DateTimePicker dateTimePicker4; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.TextBox textBox2; + private UI.Framework.Controls.PageControl pageControl3; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn36; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn35; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private UI.Framework.Controls.PageControl pageControl2; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip3; + private System.Windows.Forms.ToolStripMenuItem 查询平台订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 拼多多订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 阿里妈妈订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 京东联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查看积分日志ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 查询平台订单ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 多多进宝订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 阿里妈妈订单ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 京东联盟订单ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 查看用户信息ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 兑换信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 未兑换提现ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已兑换提现ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn40; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn39; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit3; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit4; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn41; + private System.Windows.Forms.ToolStripMenuItem 唯品联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 抖音联盟订单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 唯品联盟订单ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 抖音联盟订单ToolStripMenuItem1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private UI.Framework.Controls.PageControl pageControl1; + private System.Windows.Forms.GroupBox groupBox4; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit6; + private DevExpress.XtraEditors.SimpleButton simpleButton4; + private System.Windows.Forms.DateTimePicker dateTimePicker7; + private System.Windows.Forms.DateTimePicker dateTimePicker8; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit7; + private DevExpress.XtraEditors.LabelControl labelControl6; + private System.Windows.Forms.TextBox textBox4; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit8; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraEditors.LabelControl labelControl8; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private DevExpress.XtraEditors.SplitContainerControl splitContainerControl1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn42; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn43; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn44; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn45; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn46; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn47; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn48; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn49; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn50; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn51; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn52; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn53; + private DevExpress.XtraEditors.LabelControl labelControl10; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl11; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.LinkLabel linkLabel3; + private System.Windows.Forms.LinkLabel linkLabel4; + private System.Windows.Forms.LinkLabel linkLabel5; + private System.Windows.Forms.LinkLabel linkLabel7; + private System.Windows.Forms.LinkLabel linkLabel6; + private DevExpress.XtraEditors.CheckEdit checkEdit1; + private System.Windows.Forms.ToolStripMenuItem 一键审核勾选项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 商户付款ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 微信支付ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 没收金额ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 退回ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 已审核ToolStripMenuItem; + private System.Windows.Forms.Panel panel1; + private DevExpress.XtraEditors.LabelControl labelControl12; + private DevExpress.XtraEditors.CheckEdit checkEdit2; + } +} diff --git a/FLSystem/Forms/point_manage_control.cs b/FLSystem/Forms/point_manage_control.cs new file mode 100644 index 0000000..5596911 --- /dev/null +++ b/FLSystem/Forms/point_manage_control.cs @@ -0,0 +1,2255 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using DevExpress.XtraEditors; +using FLSystem.Events; +using Newtonsoft.Json; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework.Utils; +using UI.Framework.Controls; +using UI.Framework.Entitys; +using UI.Framework.Forms; +using ApplyType = Chat.Framework.WXSdk.IPAD.ApplyType; + +namespace FLSystem.Forms +{ + public partial class point_manage_control : XtraUserControl + { + private string username = string.Empty; + private string query_type = string.Empty; + public point_manage_control(string username, string query_type) + { + InitializeComponent(); + this.username = username; + this.query_type = query_type; + } + + private void MainEvent_CommonEvents(object sender, CommonEvents e) + { + if (this.IsDisposed) return; + try + { + if (e.Commons != null && e.Commons.Count != 0 && xtraTabControl1.TabPages.Count != 0) + { + if (e.Commons.ContainsKey("control_name") && e.Commons.ContainsKey("username")) + { + if (e.Commons["control_name"].ToString() == "提现管理") + { + var query_type = e.Commons["query_type"].ToString(); + if (query_type == "积分日志") + { + textBox1.Text = e.Commons["username"].ToString(); + comboBox1.SelectedIndex = 0; + comboBoxEdit3.SelectedIndex = 1; + if (xtraTabControl1.SelectedTabPageIndex == 2) + xtraTabControl1.SelectedTabPageIndex = 1; + xtraTabControl1.SelectedTabPageIndex = 2; + } + else if (query_type == "未兑换提现") + { + textBox3.Text = e.Commons["username"].ToString(); + comboBoxEdit1.SelectedIndex = 0; + comboBoxEdit4.SelectedIndex = 1; + checkBox2.Checked = false; + if (this.xtraTabControl1.SelectedTabPageIndex == 1) + xtraTabControl1.SelectedTabPageIndex = 0; + xtraTabControl1.SelectedTabPageIndex = 1; + } + else if (query_type == "已兑换提现") + { + textBox2.Text = e.Commons["username"].ToString(); + comboBoxEdit2.SelectedIndex = 0; + comboBoxEdit5.SelectedIndex = 1; + checkBox1.Checked = false; + if (xtraTabControl1.SelectedTabPageIndex == 0) + xtraTabControl1.SelectedTabPageIndex = 1; + xtraTabControl1.SelectedTabPageIndex = 0; + } + } + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + public class exchange_list_temp + { + [ + Browsable(false) + ] + public long id { get; set; } + + /// <summary> + /// 用户id + /// </summary> + [ + Browsable(false) + ] + public long uid { get; set; } + + /// <summary> + /// 机器人id + /// </summary> + [ + Browsable(false) + ] + public long rid { get; set; } + + /// <summary> + /// 平台类型 + /// </summary> + [ + Category("1)、平台信息"), DisplayName("平台"), ReadOnly(true), Description(@"只读:平台信息"), + ] + public ChatType chattype { get; set; } + /// <summary> + /// 用户fl_robot_info的机器人账号 robot_name + /// </summary> + [ + Category("1)、平台信息"), DisplayName("机器人账号"), ReadOnly(true), Description(@"只读:机器人账号"), + ] + public string robot_name { get; set; } + /// <summary> + /// 用户fl_robot_info的机器人昵称 nick + /// </summary> + [ + Category("1)、平台信息"), DisplayName("机器人昵称"), ReadOnly(true), Description(@"只读:机器人昵称"), + ] + public string robot_nick { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + [ + Category("2)、用户信息"), DisplayName("用户账号"), ReadOnly(true), Description(@"只读:用户账号") + ] + public string username { get; set; } + /// <summary> + /// [昵称] + /// </summary> + [ + Category("2)、用户信息"), DisplayName("昵称"), ReadOnly(true), Description(@"只读:昵称") + ] + public string usernick { get; set; } + + /// <summary> + /// [昵称] + /// </summary> + [ + Category("2)、用户信息"), DisplayName("用户备注"), ReadOnly(true), Description(@"只读:用户备注") + ] + public string member_remark { get; set; } + /// <summary> + /// 支付宝账号 + /// </summary> + [ + Category("2)、用户信息"), DisplayName("支付宝账号"), ReadOnly(true), Description(@"只读:用户支付宝账号") + ] + public string alipay_num { get; set; } + /// <summary> + /// 支付宝名称 + /// </summary> + [ + Category("2)、用户信息"), DisplayName("支付宝名称"), ReadOnly(true), Description(@"只读:用户支付宝名称") + ] + public string alipay_name { get; set; } + /// <summary> + /// 身份证名称 + /// </summary> + [ + Category("2)、用户信息"), DisplayName("身份证名称"), ReadOnly(true), Description(@"只读:用户身份证名称") + ] + public string identity_name { get; set; } + /// <summary> + /// 身份证号码 + /// </summary> + [ + Category("2)、用户信息"), DisplayName("身份证号码"), ReadOnly(true), Description(@"只读:用户身份证号码") + ] + public string identity_card { get; set; } + /// <summary> + /// 兑换群 + /// </summary> + [ + Category("2)、用户信息"), DisplayName("兑换群号"), ReadOnly(true), Description(@"只读:再群内兑换才会有群号") + ] + public string groupid { get; set; } + /// <summary> + /// 兑换时间 + /// </summary> + [ + Category("2)、用户信息"), DisplayName("用户兑换时间"), ReadOnly(true), Description(@"只读:用户的兑换时间") + ] + public DateTime time { get; set; } + /// <summary> + /// 用户积分 + /// </summary> + [ + Category("2)、用户信息"), DisplayName("用户兑换积分"), ReadOnly(true), Description(@"只读:用户兑换积分") + ] + public double point { get; set; } + /// <summary> + /// 状态 + /// </summary> + [ + Category("3)、订单操作"), DisplayName("订单状态"), Description(@"设置订单状态") + ] + public ApplyType state { get; set; } + + /// <summary> + /// 备注 + /// </summary> + [ + Category("3)、订单操作"), DisplayName("订单备注"), Description(@"用户兑换备注"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string remark { get; set; } + + /// <summary> + /// 审核时间 + /// </summary> + [ + Browsable(false) + ] + public DateTime check_time { get; set; } + } + + //积分日志 + public class pointlog_list_temp + { + public long uid { get; set; } + + public long rid { get; set; } + + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string username { get; set; } + /// <summary> + /// 用户昵称 + /// </summary> + public string usernick { get; set; } + /// <summary> + /// 机器人昵称 + /// </summary> + public string robot_nick { get; set; } + /// <summary> + /// 机器人账号 + /// </summary> + public string robot_name { get; set; } + /// <summary> + /// 操作积分 + /// </summary> + public double point { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public string pointtype { get; set; } + /// <summary> + /// + /// </summary> + public string message { get; set; } + /// <summary> + /// + /// </summary> + public DateTime crt_time { get; set; } + + /// <summary> + /// 修改前积分 + /// </summary> + public double before_point { get; set; } + + /// <summary> + /// 修改后积分 + /// </summary> + public double after_point { get; set; } + } + + /// <summary> + /// 商户链接临时类 + /// </summary> + public class shpay_temp + { + public long id { get; set; } + /// <summary> + /// 机器人id + /// </summary> + public long rid { get; set; } + /// <summary> + /// 机器人账号 + /// </summary> + public string robot_name { get; set; } + /// <summary> + /// 机器人昵称 + /// </summary> + public string robot_nick { get; set; } + + /// <summary> + /// 用户id + /// </summary> + public long uid { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string username { get; set; } + /// <summary> + /// 用户昵称 + /// </summary> + public string usernick { get; set; } + /// <summary> + /// 用户备注 + /// </summary> + public string remark { get; set; } + /// <summary> + /// 平台 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 提现金额 + /// </summary> + public double point { get; set; } + /// <summary> + /// 商户连接 + /// </summary> + public string payurl { get; set; } + /// <summary> + /// 生成连接时间 + /// </summary> + public long ctime { get; set; } + /// <summary> + /// 领取状态 + /// </summary> + public PayGetType paytype { get; set; } = PayGetType.未领取; + /// <summary> + /// 用户领取时间 + /// </summary> + public long paytime { get; set; } + /// <summary> + /// 商户orderid + /// </summary> + public string orderid { get; set; } + /// <summary> + /// 生成日期 + /// </summary> + public long ctimedate { get; set; } + /// <summary> + /// 通知发送时间 + /// </summary> + public long sendtime { get; set; } + } + + /// <summary> + /// 商户请求状态返回 + /// </summary> + public class shpayResult + { + /// <summary> + /// 请求状态 + /// </summary> + public bool ok { get; set; } + /// <summary> + /// 7d043f8e8e4be0784a596a25cbc078fb|未支付\r\n144a00f52c271c39513937c252a54ef6|已支付 + /// </summary> + public string res { get; set; } + } + + private void gridView3_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + try + { + //if (e.HitInfo.Column.Caption == "状态") + // gridView3.SelectRow(e.HitInfo.RowHandle); + //if (gridView3.GetSelectedRows().Length == 0) return; + //var selectRow = gridView3.GetSelectedRows()[0]; + var id = this.gridView3.GetRowCellValue(e.RowHandle, "id").ToString();//获取ID列的数据 + var state = this.gridView3.GetRowCellValue(e.RowHandle, "state").ToString().ToLower();//获取state列的数据 + #region 单元格双击修改 用户兑换状态 + if (e.Clicks == 2) + { + if (state == ApplyType.未审核.ToString()) + { + var session = ApiClient.GetSession(); + + var exchange = session.Queryable<fl_exchange_info>() + .Where(f => f.id == int.Parse(id)) + .Select<exchange_list_temp>((o) => + new exchange_list_temp() + { + id = o.id, + groupid = o.groupid, + time = o.time, + point = o.point, + state = o.state, + remark = o.remark, + uid = o.uid, + rid = o.rid + //alipay_name = , + //alipay_num = , + //chattype = , + //identity_card = , + //identity_name = , + //member_remark = , + //rid = , + //robot_name = , + //robot_nick = , + //uid = , + //username = , + //usernick = + }).First(); + + if (exchange != null) + { + #region 附加用户 + if (exchange.uid != 0) + { + var member = session.Queryable<fl_member_info>().First(f => f.id == exchange.uid); + if (member != null) + { + exchange.alipay_name = member.alipay_name; + exchange.alipay_num = member.alipay_num; + exchange.chattype = member.robot_type; + exchange.identity_card = member.identity_card; + exchange.identity_name = member.identity_name; + exchange.member_remark = member.remark; + exchange.username = member.username; + exchange.usernick = member.usernick; + } + } + #endregion + + #region 附加机器人信息 + if (exchange.rid != 0) + { + var robot = session.FindRobots().FirstOrDefault(f => f.id == exchange.rid); + if (robot != null) + { + exchange.chattype = robot.type; + exchange.robot_name = robot.name; + exchange.robot_nick = robot.nick; + } + } + #endregion + } + + try + { + var exchangeStateForm = new ExchangeStateForm(exchange); + exchangeStateForm.ShowDialog(); + if (exchange.state != ApplyType.未审核) + { + var exchangeResult = session.Find<fl_exchange_info>("select * from fl_exchange_info where id = @id", new { id = id }).FirstOrDefault(); + if (exchangeResult == null) throw new Exception("对不起数据异常,请稍后重试!"); + session.ExcuteSQL("update fl_exchange_info set state = @state,remark = @remark,check_time = @check_time where id = @id", new { state = exchange.state, check_time = DateTime.Now, remark = exchange.remark, id = id }); + var robot_info = session.FindRobotInfo(exchange.robot_name, exchange.chattype); + // if (robot_info == null) throw new Exception(@"兑换异常 + //机器人账号:" + exchange.robot_name + " 信息异常"); + var member_info = session.Find<fl_member_info>("select * from fl_member_info where id = @id", new { id = exchangeResult.uid }).FirstOrDefault(); + + var pointConfig = ApiClient.GetPointManageConfig(); + if (pointConfig == null) + throw new Exception("获取积分管理配置为空/"); + if (member_info != null && robot_info != null) + { + if (exchange.state == ApplyType.退回兑换) + { + member_info = session.ChangePoint(PointType.退回积分, exchangeResult.point, member_info.id, $"退回兑换{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); + if (robot_info != null) + ApiClient.SendMessage(robot_info, exchange.username, new VariateReplace().CommonReplace(pointConfig.ExchangeReturnTip.Replace("[兑换金额]", exchangeResult.point.ToString()).Replace("[备注]", exchange.remark), member_info), exchange.groupid); + } + else if (exchange.state == ApplyType.已审核) + { + if (member_info != null && robot_info != null) + { + var mess = new VariateReplace().CommonReplace(pointConfig.ExchangeAdoptTip.Replace("[兑换金额]", exchangeResult.point.ToString()).Replace("[领取地址]", exchangeStateForm.pay_url), member_info); + + var sends = new List<temp_send_data>(); + if (!string.IsNullOrWhiteSpace(exchangeStateForm.mess)) + sends.Add(new temp_send_data() { Groupid = exchange.groupid, Message = exchangeStateForm.mess, Robot = robot_info, TouserName = exchange.username }); + sends.Add(new temp_send_data() { Groupid = exchange.groupid, Message = mess, Robot = robot_info, TouserName = exchange.username }); + + ApiClient.SendMessage(sends.ToArray()); + } + } + else //没收兑换 + { + ApiClient.SendMessage(robot_info, exchange.username, new VariateReplace().CommonReplace(pointConfig.ExchangeConfiscateTip.Replace("[兑换金额]", exchangeResult.point.ToString()).Replace("[备注]", exchange.remark), member_info), exchange.groupid); + } + } + else + { + if (exchange.state == ApplyType.退回兑换) + throw new Exception("兑换退回失败,请稍后重试."); + } + this.gridView3.DeleteRow(e.RowHandle); + } + else + { + session.ExcuteSQL("update fl_exchange_info set remark = @remark where id = @id", new { remark = exchange.remark, id = id }); + } + + label3.Visible = gridView3.RowCount == 0; + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message + "-" + ex.StackTrace, "错误1", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + #endregion + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message + "*" + ex.StackTrace, "错误2", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.pageControl3.GotoPage(); + label3.Visible = gridView3.RowCount == 0; + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + this.pageControl2.GotoPage(); + label2.Visible = gridView2.RowCount == 0; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl4.GotoPage(); + label4.Visible = gridView4.RowCount == 0; + } + + private void xtraTabControl1_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e) + { + try + { + if (xtraTabControl1.SelectedTabPageIndex == 0) + { + Task.Run(() => + { + this.Invoke(new Action(() => + { + if (IsInitYiJingDuiHuan == false) + { + YiJingDuihuan(); + } + + if (IsInitYiJingDuiHuan) + { + pageControl2.GotoPage(1); + label2.Visible = gridView2.RowCount == 0; + } + })); + }); + } + else if (xtraTabControl1.SelectedTabPageIndex == 1) + { + if (IsInitNotDuiHuan == false) + { + NotDuiHuan(); + } + + if (IsInitNotDuiHuan) + { + pageControl3.GotoPage(1); + label3.Visible = gridView3.RowCount == 0; + } + } + else if (xtraTabControl1.SelectedTabPageIndex == 2) + { + if (IsInitJiFenRecord == false) + { + JiFenRecord(); + } + + if (IsInitJiFenRecord) + { + pageControl4.GotoPage(1); + label4.Visible = gridView4.RowCount == 0; + } + } + else if (xtraTabControl1.SelectedTabPageIndex == 3) + { + if (IsInitShangHuView == false) + { + ShangHuView(); + } + + if (IsInitShangHuView) + { + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void checkBox2_CheckedChanged(object sender, EventArgs e) + { + dateTimePicker6.Enabled = dateTimePicker5.Enabled = checkBox2.Checked; + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + dateTimePicker4.Enabled = dateTimePicker3.Enabled = checkBox1.Checked; + } + + private string FindUsernameByGrid() + { + try + { + if (xtraTabControl1.SelectedTabPageIndex == 0) + { + var rows = gridView2.GetSelectedRows(); + if (rows != null && rows.Length > 0) + return gridView2.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + return string.Empty; + } + else if (xtraTabControl1.SelectedTabPageIndex == 1) + { + //var rows = gridView3.GetSelectedRows(); + var rows1 = gridView3.GetFocusedRow(); + if (rows1 != null) + return (rows1 as exchange_list_temp).username; + //var rows = gridView3.GetFocusedDataSourceRowIndex(); + //if (rows >= 0) + // return gridView3.GetRowCellValue(rows, "username").ToString();//获取列的数据 + return string.Empty; + } + else if (xtraTabControl1.SelectedTabPageIndex == 2) + { + var rows = gridView4.GetSelectedRows(); + if (rows != null && rows.Length > 0) + return gridView4.GetRowCellValue(rows[0], "username").ToString();//获取列的数据 + return string.Empty; + } + } + catch (Exception) + { } + return string.Empty; + } + + private void 查看用户信息1ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var username = FindUsernameByGrid(); + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var common = new Dictionary<string, object>(); + common["control_name"] = tsmi.Text; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var username = FindUsernameByGrid(); + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + var text = tsmi.Text.Replace("订单", ""); + var cps = (CpsType)Enum.Parse(typeof(CpsType), text); + + var common = new Dictionary<string, object>(); + common["cps_type"] = (int)cps; + common["username"] = username; + MainEvent.OnEvent(null, new CommonEvents(common)); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ToolStripMenuItem2_Click(object sender, EventArgs e) + { + try + { + var username = FindUsernameByGrid(); + if (!string.IsNullOrWhiteSpace(username)) + { + var tsmi = sender as ToolStripMenuItem; + if (tsmi == null) throw new Exception("数据异常"); + + if (tsmi.Text == "查看积分日志") + { + xtraTabControl1.SelectedTabPageIndex = 2; + textBox1.Text = username; + comboBox1.SelectedIndex = 0; + comboBoxEdit3.SelectedIndex = 1; + dateTimePicker1.Value = DateTime.Today.AddDays(-10); + dateTimePicker2.Value = DateTime.Today; + pageControl4.GotoPage(1); + label4.Visible = gridView4.RowCount == 0; + } + else if (tsmi.Text == "未兑换提现") + { + xtraTabControl1.SelectedTabPageIndex = 1; + textBox3.Text = username; + comboBoxEdit1.SelectedIndex = 0; + comboBoxEdit4.SelectedIndex = 1; + pageControl3.GotoPage(1); + label3.Visible = gridView3.RowCount == 0; + } + else if (tsmi.Text == "已兑换提现") + { + xtraTabControl1.SelectedTabPageIndex = 0; + comboBoxEdit5.SelectedIndex = 1; + textBox2.Text = username; + comboBoxEdit2.SelectedIndex = 0; + pageControl2.GotoPage(1); + label2.Visible = gridView2.RowCount == 0; + } + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private async void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + if (XtraMessageBox.Show(@"是否校准用户对应机器人信息 + +校准情况如下: +①机器人信息删除,导致用户绑定的机器人信息丢失 +②机器人账号异常,用户迁移新机器人无法审核提现 + +注:校验后还没有机器人信息,让客户发条信息后重试! +", "系统提示", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No) return; + try + { + EventClient.StopParsing = true; + groupBox2.Enabled = false; + try + { + await Task.Run(() => + { + var session = ApiClient.GetSession(); + session.BeginTransaction(); + try + { + var exchange_infos = session.Find<fl_exchange_info>("state = 1"); + var robots = session.FindRobots(true); + foreach (var item in exchange_infos) + { + var member = session.FindMemberInfoById(item.uid); + if (member == null) continue; + var robot = robots.FirstOrDefault(f => f.name == member.robot_name && f.type == member.robot_type); + if (robot == null) continue; + if (robot.id == item.rid) continue; + item.rid = robot.id; + session.Updateable(item).ExecuteCommand(); + } + session.Commit(); + XtraMessageBox.Show("校准完成", "温馨提示", MessageBoxButtons.OK); + } + catch (Exception ex) + { + session.Rollback(); + this.Invoke(new Action(delegate + { + XtraMessageBox.Show(ex.Message, "校准失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + })); + } + finally + { + this.Invoke(new Action(delegate + { + groupBox2.Enabled = true; + EventClient.StopParsing = false; + pageControl3.GotoPage(1); + })); + } + }, tokenSource.Token); + } + catch (Exception) + { } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private bool IsInitYiJingDuiHuan = false; + + /// <summary> + /// 初始化已经兑换 + /// </summary> + private void YiJingDuihuan() + { + #region 加载已兑换用户信息列表 + + try + { + pageControl2.Bind((index, size) => + { + var stopWatch = new Stopwatch(); + stopWatch.Start(); + + + var stopWatch4 = new Stopwatch(); + stopWatch4.Start(); + + var keyword = textBox2.Text.Replace("'", "''").Trim(); + List<IConditionalModel> conModels = new List<IConditionalModel>(); + var session = ApiClient.GetSession(); + if (!string.IsNullOrWhiteSpace(keyword)) + { + List<string> member_ids = new List<string>(); + switch (comboBoxEdit5.Text) + { + case "客户账号": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "username", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户昵称": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "usernick", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户备注": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "remark", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户编号": + { + member_ids.Add(keyword); + } + break; + case "支付宝账号": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "alipay_num", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "支付宝姓名": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "alipay_name", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + } + + if (member_ids.Count == 1) + conModels.Add(new ConditionalModel() + { + FieldName = "uid", + ConditionalType = ConditionalType.Equal, + FieldValue = member_ids[0] + }); + else if (member_ids.Count == 0) + conModels.Add(new ConditionalModel() + { FieldName = "uid", ConditionalType = ConditionalType.Equal, FieldValue = "-1" }); + else + conModels.Add(new ConditionalModel() + { + FieldName = "uid", + ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", member_ids) + }); + } + + conModels.Add(new ConditionalModel() + { FieldName = "state", ConditionalType = ConditionalType.IsNot, FieldValue = "1" }); + + if (checkBox1.Checked) + { + conModels.Add(new ConditionalModel() + { + FieldName = "time", + ConditionalType = ConditionalType.GreaterThanOrEqual, + FieldValue = dateTimePicker4.Value.Date.ToString("yyyy-MM-dd HH:mm:ss") + }); + conModels.Add(new ConditionalModel() + { + FieldName = "time", + ConditionalType = ConditionalType.LessThanOrEqual, + FieldValue = dateTimePicker3.Value.Date.AddDays(1).ToString("yyyy-MM-dd HH:mm:ss") + }); + } + + if (comboBoxEdit2.SelectedIndex != 0) + { + var robotIds = session.FindRobots().Where(f => f.name == comboBoxEdit2.Text.Trim()) + .Select(f => f.id).ToList(); + if (robotIds != null) + conModels.Add(new ConditionalModel() + { + FieldName = "rid", + ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", robotIds) + }); + } + + stopWatch4.Stop(); + LogHelper.GetSingleObj().Info("", $"A-3执行时间:{stopWatch4.Elapsed.TotalSeconds.ToString("0.0000")}"); + + #region 统计已提现金额 + + var point = session.Queryable<fl_exchange_info>().Where(conModels).Sum(f => f.point); + this.Invoke(new Action(() => + { + gridView2.Columns["point"].SummaryItem.SetSummary(DevExpress.Data.SummaryItemType.Custom, point.ToString("0.00")); + })); + + #endregion + + var stopWatch3 = new Stopwatch(); + stopWatch3.Start(); + int totalNumber = 0; //总数 + + var result = session.Queryable<fl_exchange_info>() + .Where(conModels) + .OrderBy(f => f.id, OrderByType.Desc) + .Select<exchange_list_temp>(f => new exchange_list_temp() + { + id = f.id, + groupid = f.groupid, + point = f.point, + remark = f.remark, + state = f.state, + time = f.time, + uid = f.uid, + rid = f.rid, + check_time = f.check_time + //alipay_name = m.alipay_name, + //alipay_num = m.alipay_num, + //chattype = m.robot_type, + //identity_card = m.identity_card, + //identity_name = m.identity_name, + //member_remark = m.remark, + //username = m.username, + //usernick = m.usernick, + //robot_name = r.name, + //robot_nick = r.nick + }).ToPageList(index, size, ref totalNumber); + + stopWatch3.Stop(); + LogHelper.GetSingleObj().Info("", $"A-2执行时间:{stopWatch3.Elapsed.TotalSeconds.ToString("0.0000")}"); + + if (result.Count != 0) + { + #region 附加用户 + + var stopWatch2 = new Stopwatch(); + stopWatch2.Start(); + var bindUsersList = result.Where(f => f.uid != 0).Select(f => f.uid.ToString()).ToList(); + var memberData = new List<fl_member_info>(); + if (bindUsersList != null && bindUsersList.Count != 0) + { + memberData = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "id", ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", bindUsersList) + } + }).ToList(); + } + + foreach (var member in memberData) + { + var items = result.Where(f => f.uid == member.id).ToList(); + foreach (var item in items) + { + item.alipay_name = member.alipay_name; + item.alipay_num = member.alipay_num; + item.chattype = member.robot_type; + item.identity_card = member.identity_card; + item.identity_name = member.identity_name; + item.member_remark = member.remark; + item.username = member.username; + item.usernick = member.usernick; + } + } + + stopWatch2.Stop(); + LogHelper.GetSingleObj().Info("", $"A-0执行时间:{stopWatch2.Elapsed.TotalSeconds.ToString("0.0000")}"); + + #endregion + + #region 附加机器人信息 + + var stopWatch1 = new Stopwatch(); + stopWatch1.Start(); + var robotList = result.Where(f => f.rid != 0).Select(f => f.rid.ToString()).ToList(); + var robotData = new List<fl_robot_info>(); + if (robotList != null && robotList.Count != 0) + robotData = session.Queryable<fl_robot_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "id", ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", robotList) + } + }).ToList(); + + foreach (var robot in robotData) + { + var items = result.Where(f => f.rid == robot.id).ToList(); + foreach (var item in items) + { + item.robot_name = robot.name; + item.robot_nick = robot.nick; + } + } + + stopWatch1.Stop(); + LogHelper.GetSingleObj().Info("", $"A-1执行时间:{stopWatch1.Elapsed.TotalSeconds.ToString("0.0000")}"); + + #endregion + } + + stopWatch.Stop(); + LogHelper.GetSingleObj().Info("", $"A执行时间:{stopWatch.Elapsed.TotalSeconds.ToString("0.0000")}"); + + return new PageControl.SerchResult() { Result = result, Total = totalNumber }; + }, gridControl2, 40, true, true); + IsInitYiJingDuiHuan = true; + } + catch (Exception ex) + { + IsInitYiJingDuiHuan = false; + BaseForm.ShowError(ex); + } + + label2.Visible = gridView2.RowCount == 0; + + #endregion + } + + private bool IsInitNotDuiHuan = false; + + private void NotDuiHuan() + { + #region 未兑换列表 + try + { + pageControl3.Bind((page, size) => + { + var stopWatch = new Stopwatch(); + stopWatch.Start(); + + var keyword = textBox3.Text.Replace("'", "''").Trim(); + List<IConditionalModel> conModels = new List<IConditionalModel>(); + var session = ApiClient.GetSession(); + if (!string.IsNullOrWhiteSpace(keyword)) + { + List<string> member_ids = new List<string>(); + switch (comboBoxEdit4.Text) + { + case "客户账号": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "username", ConditionalType = ConditionalType.Like, FieldValue = keyword } }).Select(f => f.id.ToString()).ToList();//模糊查询的用户id集合 + } + break; + case "客户昵称": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "usernick", ConditionalType = ConditionalType.Like, FieldValue = keyword } }).Select(f => f.id.ToString()).ToList();//模糊查询的用户id集合 + } + break; + case "客户备注": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "remark", ConditionalType = ConditionalType.Like, FieldValue = keyword } }).Select(f => f.id.ToString()).ToList();//模糊查询的用户id集合 + } + break; + case "客户编号": + { + member_ids.Add(keyword); + } + break; + case "支付宝账号": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "alipay_num", ConditionalType = ConditionalType.Like, FieldValue = keyword } }).Select(f => f.id.ToString()).ToList();//模糊查询的用户id集合 + } + break; + case "支付宝姓名": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "alipay_name", ConditionalType = ConditionalType.Like, FieldValue = keyword } }).Select(f => f.id.ToString()).ToList();//模糊查询的用户id集合 + } + break; + } + if (member_ids.Count == 1) + conModels.Add(new ConditionalModel() { FieldName = "uid", ConditionalType = ConditionalType.Equal, FieldValue = member_ids[0] }); + else if (member_ids.Count == 0) + conModels.Add(new ConditionalModel() { FieldName = "uid", ConditionalType = ConditionalType.Equal, FieldValue = "-1" }); + else + conModels.Add(new ConditionalModel() { FieldName = "uid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", member_ids) }); + } + + if (checkBox2.Checked) + { + //where += " and '" + dateTimePicker6.Value.Date.ToString("yyyy-MM-dd HH:mm:ss") + "' <= e.time and e.time < '" + dateTimePicker5.Value.Date.AddDays(1).ToString("yyyy-MM-dd HH:mm:ss") + "'"; + + conModels.Add(new ConditionalModel() { FieldName = "time", ConditionalType = ConditionalType.GreaterThanOrEqual, FieldValue = dateTimePicker6.Value.Date.ToString("yyyy-MM-dd HH:mm:ss") }); + conModels.Add(new ConditionalModel() { FieldName = "time", ConditionalType = ConditionalType.LessThan, FieldValue = dateTimePicker5.Value.Date.AddDays(1).ToString("yyyy-MM-dd HH:mm:ss") }); + } + + if (comboBoxEdit1.SelectedIndex != 0) + { + var robotIds = session.FindRobots().Where(f => f.name == comboBoxEdit2.Text.Trim()).Select(f => f.id).ToList(); + if (robotIds != null) + { + conModels.Add(new ConditionalModel() { FieldName = "rid", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", robotIds) }); + } + } + conModels.Add(new ConditionalModel() { FieldName = "state", ConditionalType = ConditionalType.Equal, FieldValue = "1" }); + + #region 统计未提现金额 + var point = session.Queryable<fl_exchange_info>().Where(conModels).Sum(f => f.point); + this.Invoke(new Action(() => + { + gridView3.Columns["point"].SummaryItem.SetSummary(DevExpress.Data.SummaryItemType.Custom, point.ToString("0.00")); + })); + #endregion + + int totalNumber = 0;//总数 + + var result = session.Queryable<fl_exchange_info>() + .Where(conModels) + .OrderBy(f => f.id, OrderByType.Desc) + .Select(f => new exchange_list_temp() + { + id = f.id, + groupid = f.groupid, + point = f.point, + remark = f.remark, + state = f.state, + time = f.time, + uid = f.uid, + rid = f.rid + //alipay_name = m.alipay_name, + //alipay_num = m.alipay_num, + //chattype = m.robot_type, + //identity_card = m.identity_card, + //identity_name = m.identity_name, + //member_remark = m.remark, + //username = m.username, + //usernick = m.usernick, + //robot_name = r.name, + //robot_nick = r.nick + }).ToPageList(page, size, ref totalNumber); + + if (result.Count != 0) + { + #region 附加用户 + var bindUsersList = result.Where(f => f.uid != 0).Select(f => f.uid.ToString()).Distinct().ToList(); + var memberData = new List<fl_member_info>(); + if (bindUsersList.Count != 0) + { + memberData = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + } + foreach (var member in memberData) + { + var items = result.Where(f => f.uid == member.id).ToList(); + foreach (var item in items) + { + item.alipay_name = member.alipay_name; + item.alipay_num = member.alipay_num; + item.chattype = member.robot_type; + item.identity_card = member.identity_card; + item.identity_name = member.identity_name; + item.member_remark = member.remark; + item.username = member.username; + item.usernick = member.usernick; + } + } + #endregion + + #region 附加机器人信息 + var robotList = result.Where(f => f.rid != 0).Select(f => f.rid.ToString()).Distinct().ToList(); + var robotData = new List<fl_robot_info>(); + if (robotList != null && robotList.Count != 0) + { + //robotData = session.Queryable<fl_robot_info>().Where(new List<IConditionalModel>() { session.WhereConditionaOrList("id", robotList) }).ToList(); + robotData = session.Queryable<fl_robot_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", robotList) } }).ToList(); + } + + foreach (var robot in robotData) + { + var items = result.Where(f => f.rid == robot.id).ToList(); + foreach (var item in items) + { + item.robot_name = robot.name; + item.robot_nick = robot.nick; + item.chattype = robot.type; + } + } + #endregion + } + + stopWatch.Stop(); + LogHelper.GetSingleObj().Info("", $"B执行时间:{stopWatch.Elapsed.TotalSeconds.ToString("0.0000")}"); + + return new PageControl.SerchResult() { Result = result, Total = totalNumber }; + }, gridControl3, 40, true, true); + IsInitNotDuiHuan = true; + } + catch (Exception ex) + { + IsInitNotDuiHuan = false; + BaseForm.ShowError(ex); + } + label3.Visible = gridView3.RowCount == 0; + + #endregion + } + + private bool IsInitShangHuView = false; + private void ShangHuView() + { + #region 加载商户链接信息列表 + + try + { + pageControl1.Bind((index, size) => + { + var stopWatch = new Stopwatch(); + stopWatch.Start(); + + var stopWatch2 = new Stopwatch(); + stopWatch2.Start(); + + var keyword = textBox4.Text.Replace("'", "''").Trim(); + List<IConditionalModel> conModels = new List<IConditionalModel>(); + var session = ApiClient.GetSession(); + if (!string.IsNullOrWhiteSpace(keyword)) + { + var isrobot = false; + List<string> member_ids = new List<string>(); + List<string> robot_ids = new List<string>(); + switch (comboBoxEdit6.Text) + { + case "客户账号": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "username", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户昵称": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "usernick", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户备注": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "remark", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户编号": + { + member_ids.Add(keyword); + } + break; + case "机器人编号": + { + isrobot = true; + robot_ids.Add(keyword); + } + break; + case "机器人账号": + { + isrobot = true; + robot_ids = session.Queryable<fl_robot_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "name", ConditionalType = ConditionalType.Like, FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); + } + break; + case "机器人昵称": + { + isrobot = true; + robot_ids = session.Queryable<fl_robot_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "nick", ConditionalType = ConditionalType.Like, FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); + } + break; + } + + if (!isrobot) + { + if (member_ids.Count == 1) + conModels.Add(new ConditionalModel() + { + FieldName = "uid", + ConditionalType = ConditionalType.Equal, + FieldValue = member_ids[0] + }); + else if (member_ids.Count == 0) + conModels.Add(new ConditionalModel() + { FieldName = "uid", ConditionalType = ConditionalType.Equal, FieldValue = "-1" }); + else + conModels.Add(new ConditionalModel() + { + FieldName = "uid", + ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", member_ids) + }); + } + else + { + if (robot_ids.Count == 1) + conModels.Add(new ConditionalModel() + { + FieldName = "rid", + ConditionalType = ConditionalType.Equal, + FieldValue = robot_ids[0] + }); + else if (robot_ids.Count == 0) + conModels.Add(new ConditionalModel() + { FieldName = "rid", ConditionalType = ConditionalType.Equal, FieldValue = "-1" }); + else + conModels.Add(new ConditionalModel() + { + FieldName = "rid", + ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", robot_ids) + }); + } + } + + conModels.Add(new ConditionalModel() + { + FieldName = "ctime", + ConditionalType = ConditionalType.GreaterThanOrEqual, + FieldValue = HttpExtend.GetTimeStamp(dateTimePicker8.Value.Date).ObjToString() + }); + conModels.Add(new ConditionalModel() + { + FieldName = "ctime", + ConditionalType = ConditionalType.LessThanOrEqual, + FieldValue = HttpExtend.GetTimeStamp(dateTimePicker7.Value.Date.AddDays(1)).ToString() + }); + + if (comboBoxEdit7.SelectedIndex != 0) + { + conModels.Add(new ConditionalModel() + { + FieldName = "chattype", + ConditionalType = ConditionalType.Equal, + FieldValue = (comboBoxEdit7.SelectedIndex - 1).ToString() + }); + } + + if (comboBoxEdit8.SelectedIndex != 0) + { + conModels.Add(new ConditionalModel() + { + FieldName = "paytype", + ConditionalType = ConditionalType.Equal, + FieldValue = (comboBoxEdit8.SelectedIndex - 1).ToString() + }); + } + + stopWatch2.Stop(); + LogHelper.GetSingleObj().Info("", $"D-1执行时间:{stopWatch2.Elapsed.TotalSeconds.ToString("0.0000")}"); + + var stopWatch3 = new Stopwatch(); + stopWatch3.Start(); + + int totalNumber = 0; //总数 + + var result = session.Queryable<fl_shpay_hist>() + .Where(conModels) + .OrderBy(f => f.id, OrderByType.Desc) + .Select(f => new shpay_temp() + { + id = f.id, + chattype = f.chattype, + point = f.point, + ctime = f.ctime, + paytime = f.paytime, + uid = f.uid, + rid = f.rid, + paytype = f.paytype, + payurl = f.payurl, + ctimedate = f.ctimedate, + orderid = f.orderid, + sendtime = f.sendtime, + robot_name = f.robotname, + robot_nick = f.robotnick, + username = f.username, + usernick = f.usernick + }).ToPageList(index, size, ref totalNumber); + + stopWatch3.Stop(); + LogHelper.GetSingleObj().Info("", $"D-2执行时间:{stopWatch3.Elapsed.TotalSeconds.ToString("0.0000")}"); + + if (result.Count != 0) + { + #region 这里获取远程获取商户链接领取状态 + + var stopWatch4 = new Stopwatch(); + stopWatch4.Start(); + var resultTmp = result.Where(f => f.paytype == PayGetType.未领取).ToList(); + + if (resultTmp.Count != 0) + { + List<string> yjPayList = new List<string>(); //已经领取的连接 + var timedate = resultTmp.GroupBy(f => f.ctimedate).Select(f => f.Key).ToList(); + foreach (var date in timedate) + { + var html = string.Empty; + try + { + var arr = resultTmp.Where(f => f.ctimedate == date) + .Select(f => "\"" + f.orderid + "\"").ToList(); + if (arr.Count() != 0) + { + string parm = "orders=[" + string.Join(",", arr) + $"]&time={date}"; + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "https://pay.api.52cmg.cn/pay/CheckOrders", + Method = "POST", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = + "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = parm, + ResultType = ResultType.String, + }; + html = http.GetHtml(item).Html; + + //{"ok":true,"res":"7d043f8e8e4be0784a596a25cbc078fb|未支付\r\n144a00f52c271c39513937c252a54ef6|已支付"} + + var shResult = JsonConvert.DeserializeObject<shpayResult>(html); + if (shResult != null && shResult.ok) + { + var regs = Regex.Split(shResult.res, @"[\r\n]") + .Where(f => !string.IsNullOrWhiteSpace(f)).ToList(); + if (regs.Count == 0) continue; + + foreach (var tmp in regs) + { + var split = tmp.Split(new string[] { "|" }, + StringSplitOptions.RemoveEmptyEntries); + var r = result.FirstOrDefault(f => split[0] == f.orderid); + if (r != null) + { + r.paytype = split[1] == "已支付" ? PayGetType.已领取 : PayGetType.未领取; + if (r.paytype == PayGetType.已领取) + yjPayList.Add(split[0]); + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"商户状态查询异常:{ex.Message} - {ex.StackTrace} , {html}"); + } + } + + #region 修改数据库中的状态 + + if (yjPayList.Count != 0) + { + try + { + var shpayList = new List<fl_shpay_hist>(); + foreach (var item in yjPayList) + { + var shpay = session.FindSingle<fl_shpay_hist>("orderid = @orderid", + new { orderid = item }); + if (shpay != null) + { + shpay.paytime = HttpExtend.GetTimeStamp(DateTime.Now); + shpay.paytype = PayGetType.已领取; + shpayList.Add(shpay); + } + } + + if (shpayList.Count != 0) + session.Updateable(shpayList).ExecuteCommand(); + } + catch (Exception ex) + { + EventClient.OnEvent("", $"商户状态修改异常:{ex.Message} - {ex.StackTrace}"); + } + } + + #endregion + + } + + stopWatch4.Stop(); + LogHelper.GetSingleObj().Info("", $"D-4执行时间:{stopWatch4.Elapsed.TotalSeconds.ToString("0.0000")}"); + + #endregion + + if (comboBoxEdit8.SelectedIndex == 1) + result = result.Where(f => f.paytype == PayGetType.未领取).ToList(); + else if (comboBoxEdit8.SelectedIndex == 2) + result = result.Where(f => f.paytype == PayGetType.已领取).ToList(); + + #region 附加用户xxx + + //var bindUsersList = result.Where(f => f.uid != 0).Select(f => f.uid.ToString()).ToList(); + //var memberData = new List<fl_member_info>(); + //if (bindUsersList != null && bindUsersList.Count != 0) + //{ + // memberData = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", bindUsersList) } }).ToList(); + //} + + //foreach (var member in memberData) + //{ + // var items = result.Where(f => f.uid == member.id).ToList(); + // foreach (var item in items) + // { + // item.remark = member.remark; + // item.chattype = member.robot_type; + // item.username = member.username; + // item.usernick = member.usernick; + // } + //} + + #endregion + + #region 附加机器人信息xxx + + //var robotList = result.Where(f => f.rid != 0).Select(f => f.rid.ToString()).ToList(); + //var robotData = new List<fl_robot_info>(); + //if (robotList != null && robotList.Count != 0) + // robotData = session.Queryable<fl_robot_info>().Where(new List<IConditionalModel>() { new ConditionalModel() { FieldName = "id", ConditionalType = ConditionalType.In, FieldValue = string.Join(",", robotList) } }).ToList(); + + //foreach (var robot in robotData) + //{ + // var items = result.Where(f => f.rid == robot.id).ToList(); + // foreach (var item in items) + // { + // item.robot_name = robot.name; + // item.robot_nick = robot.nick; + // } + //} + + #endregion + } + + stopWatch.Stop(); + LogHelper.GetSingleObj().Info("", $"D执行时间:{stopWatch.Elapsed.TotalSeconds.ToString("0.0000")}"); + + return new PageControl.SerchResult() { Result = result, Total = totalNumber }; + }, gridControl1, 40, true, true); + IsInitShangHuView = true; + } + catch (Exception ex) + { + IsInitShangHuView = false; + BaseForm.ShowError(ex); + } + label1.Visible = gridView1.RowCount == 0; + + #endregion + } + + private bool IsInitJiFenRecord = false; + + private void JiFenRecord() + { + #region 用户积分兑换日志 + + try + { + pageControl4.Bind((page, size) => + { + var stopWatch = new Stopwatch(); + stopWatch.Start(); + + var keyword = textBox1.Text.Replace("'", "''").Trim(); + List<IConditionalModel> conModels = new List<IConditionalModel>(); + this.Invoke(new Action(() => + { + if (comboBox1.SelectedIndex != 0) + conModels.Add(new ConditionalModel() + { + FieldName = "type", + ConditionalType = ConditionalType.Equal, + FieldValue = comboBox1.Text + }); + })); + + conModels.Add(new ConditionalModel() + { + FieldName = "crt_time", + ConditionalType = ConditionalType.GreaterThan, + FieldValue = dateTimePicker1.Value.AddSeconds(-1).ToString("yyyy-MM-dd HH:mm:ss") + }); + conModels.Add(new ConditionalModel() + { + FieldName = "crt_time", + ConditionalType = ConditionalType.LessThanOrEqual, + FieldValue = dateTimePicker2.Value.AddDays(1).AddSeconds(-1).ToString("yyyy-MM-dd HH:mm:ss") + }); + + var session = ApiClient.GetSession(); + + if (!string.IsNullOrWhiteSpace(keyword)) + { + List<string> member_ids = new List<string>(); + switch (comboBoxEdit3.Text) + { + case "客户账号": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "username", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户昵称": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "usernick", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户备注": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "remark", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "客户编号": + { + member_ids.Add(keyword); + } + break; + case "支付宝账号": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "alipay_num", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + case "支付宝姓名": + { + member_ids = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "alipay_name", ConditionalType = ConditionalType.Like, + FieldValue = keyword + } + }).Select(f => f.id.ToString()).ToList(); //模糊查询的用户id集合 + } + break; + } + + if (member_ids.Count == 1) + conModels.Add(new ConditionalModel() + { + FieldName = "uid", + ConditionalType = ConditionalType.Equal, + FieldValue = member_ids[0] + }); + else if (member_ids.Count == 0) + conModels.Add(new ConditionalModel() + { FieldName = "uid", ConditionalType = ConditionalType.Equal, FieldValue = "-1" }); + else + conModels.Add(new ConditionalModel() + { + FieldName = "uid", + ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", member_ids) + }); + } + + #region 统计积分日志金额 + + var point = session.Queryable<fl_point_hist>().Where(conModels).Sum(f => f.point); + this.Invoke(new Action(() => + { + gridView4.Columns["point"].SummaryItem.SetSummary(DevExpress.Data.SummaryItemType.Custom, point.ToString("0.00")); + })); + + #endregion + + int totalNumber = 0; //总记录数 + + var result = session.Queryable<fl_point_hist>() + .Where(conModels) + .OrderBy(p => p.id, OrderByType.Desc) + .Select<pointlog_list_temp>(p => new pointlog_list_temp() + { + after_point = p.after_point, + before_point = p.before_point, + crt_time = p.crt_time, + message = p.message, + point = p.point, + pointtype = p.type, + uid = p.uid, + rid = p.rid + //robot_name = r.name, + //robot_nick = r.nick, + //chattype = m.robot_type, + //username = m.username, + //usernick = m.usernick + }).ToPageList(page, size, ref totalNumber); + + if (result.Count != 0) + { + #region 附加用户 + + var bindUsersList = result.Where(f => f.uid != 0).Select(f => f.uid.ToString()).Distinct() + .ToList(); + var memberData = new List<fl_member_info>(); + if (bindUsersList != null && bindUsersList.Count != 0) + { + memberData = session.Queryable<fl_member_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "id", ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", bindUsersList) + } + }).ToList(); + } + + foreach (var member in memberData) + { + var items = result.Where(f => f.uid == member.id).ToList(); + foreach (var item in items) + { + item.chattype = member.robot_type; + item.username = member.username; + item.usernick = member.usernick; + } + } + + #endregion + + #region 附加机器人信息 + + var robotList = result.Where(f => f.rid != 0).Select(f => f.rid.ToString()).Distinct().ToList(); + var robotData = new List<fl_robot_info>(); + if (robotList.Count != 0) + { + //robotData = session.Queryable<fl_robot_info>().Where(new List<IConditionalModel>() { session.WhereConditionaOrList("id", robotList) }).ToList(); + robotData = session.Queryable<fl_robot_info>().Where(new List<IConditionalModel>() + { + new ConditionalModel() + { + FieldName = "id", ConditionalType = ConditionalType.In, + FieldValue = string.Join(",", robotList) + } + }).ToList(); + } + + foreach (var robot in robotData) + { + var items = result.Where(f => f.rid == robot.id).ToList(); + foreach (var item in items) + { + item.robot_name = robot.name; + item.robot_nick = robot.nick; + } + } + + #endregion + } + + stopWatch.Stop(); + LogHelper.GetSingleObj().Info("", $"C执行时间:{stopWatch.Elapsed.TotalSeconds.ToString("0.0000")}"); + + return new PageControl.SerchResult() { Result = result, Total = totalNumber }; + }, gridControl4, 40, true, true); + + IsInitJiFenRecord = true; + } + catch (Exception ex) + { + IsInitJiFenRecord = false; + BaseForm.ShowError(ex); + } + label4.Visible = gridView4.RowCount == 0; + + #endregion + } + + private void point_manage_control_Load(object sender, EventArgs e) + { + try + { + memoEdit1.Text = ApiClient.Setting.SystemConfig.send_shpay_msg; + checkEdit1.Checked = ApiClient.Setting.SystemConfig.send_shpay_switch; + checkEdit2.Checked = ApiClient.Setting.SystemConfig.send_shpay_minixml; + comboBoxEdit8.SelectedIndex = 0; + + #region 增加平台类型 + this.comboBoxEdit7.Properties.Items.Clear(); + + var objList1 = new List<object>() { "全部平台" }; + + foreach (ChatType chat in Enum.GetValues(typeof(ChatType))) + { + objList1.Add(chat.ToString()); + } + this.comboBoxEdit7.Properties.Items.AddRange(objList1); + comboBoxEdit7.SelectedIndex = 0; + #endregion + + #region 增加所有的机器人账号 + this.comboBoxEdit2.Properties.Items.Clear(); + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + var objList = new List<object>() { "全部平台" }; + foreach (var item in weixinBases) + { + objList.Add(item.WeixinHao); + } + + var qqBases = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqBases) + { + objList.Add(item.QQ.ToString()); + } + + this.comboBoxEdit2.Properties.Items.AddRange(objList); + this.comboBoxEdit1.Properties.Items.AddRange(objList); + comboBoxEdit1.SelectedIndex = comboBoxEdit2.SelectedIndex = 0; + #endregion + + #region 用户积分使用类型 + comboBox1.Items.Clear(); + comboBox1.Items.Add("选择全部"); + comboBox1.SelectedIndex = 0; + foreach (PointType item in Enum.GetValues(typeof(PointType))) + { + comboBox1.Items.Add(item); + } + #endregion + + NotDuiHuan(); + + dateTimePicker4.Value = DateTime.Today.AddDays(-10); + dateTimePicker3.Value = DateTime.Today; + checkBox1.Checked = true; + + #region + if (query_type == "积分日志") + { + textBox1.Text = username; + comboBox1.SelectedIndex = 0; + comboBoxEdit3.SelectedIndex = 1; + } + else if (query_type == "未兑换提现") + { + textBox3.Text = username; + comboBoxEdit1.SelectedIndex = 0; + comboBoxEdit4.SelectedIndex = 1; + } + else if (query_type == "已兑换提现") + { + textBox2.Text = username; + comboBoxEdit2.SelectedIndex = 0; + comboBoxEdit5.SelectedIndex = 1; + } + #endregion + + dateTimePicker1.Value = DateTime.Today.AddDays(-10); + dateTimePicker2.Value = DateTime.Today; + + #region + if (query_type == "积分日志") + xtraTabControl1.SelectedTabPageIndex = 2; + else if (query_type == "未兑换提现") + xtraTabControl1.SelectedTabPageIndex = 1; + else if (query_type == "已兑换提现") + xtraTabControl1.SelectedTabPageIndex = 0; + #endregion + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + MainEvent.CommonEvents += MainEvent_CommonEvents; + this.Disposed += Control_Disposed; + } + + + + private void Control_Disposed(object sender, EventArgs e) + { + MainEvent.CommonEvents -= MainEvent_CommonEvents; + tokenSource.Cancel(); + } + + private void comboBoxEdit3_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit3.SelectedIndex == 0) + { + this.textBox1.Enabled = false; + this.textBox1.Text = ""; + } + else this.textBox1.Enabled = true; + } + + private void comboBoxEdit5_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit5.SelectedIndex == 0) + { + this.textBox2.Enabled = false; + this.textBox2.Text = ""; + } + else this.textBox2.Enabled = true; + } + + private void comboBoxEdit4_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit4.SelectedIndex == 0) + { + this.textBox3.Enabled = false; + this.textBox3.Text = ""; + } + else this.textBox3.Enabled = true; + } + + private void contextMenuStrip3_Opening(object sender, CancelEventArgs e) + { + try + { + var rows = this.gridView4.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { } + else + e.Cancel = true; + } + catch (Exception) + { } + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + try + { + int rows = 0; + if (xtraTabControl1.SelectedTabPageIndex == 0) + { + rows = this.gridView2.GetSelectedRows().Length; + 一键审核勾选项ToolStripMenuItem.Visible = false; + } + else + { + rows = this.gridView3.GetFocusedDataSourceRowIndex() + 1; + 一键审核勾选项ToolStripMenuItem.Visible = true; + } + if (rows > 0) + { } + else + e.Cancel = true; + } + catch (Exception) + { } + } + + #region 商户连接列表 + private void simpleButton4_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(); + label1.Visible = gridView1.RowCount == 0; + } + + #endregion + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + switch (e.Column.Caption) + { + case "生成时间": + case "领取时间": + e.DisplayText = HttpExtend.GetDateTime(e.Value.ToString()).ToString("yyyy-MM-dd HH:mm:ss"); + break; + //case "二级提成": + // e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString())["AwardTwo"].ToString(); + // break; + //case "三级提成": + // { + // var result = HttpExtend.JsonToDictionary(e.Value.ToString()); + // e.DisplayText = (result != null && result.ContainsKey("AwardThree")) ? result["AwardThree"].ToString() : "0"; + // } + // break; + //case "群负责人提成": + // e.DisplayText = HttpExtend.JsonToDictionary(e.Value.ToString())["AwardCreate"].ToString(); + // break; + default: + { + + } + break; + } + } + + private void comboBoxEdit6_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit6.SelectedIndex == 0) + { + this.textBox4.Enabled = false; + this.textBox4.Text = ""; + } + else this.textBox4.Enabled = true; + } + + private static bool IsRunSend = false; + + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + var rownumber = gridView1.GetSelectedRows().ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + if (IsRunSend) + { + BaseForm.ShowErrorAutoClose("已经有在运行的任务,请稍后重试~!"); + return; + } + IsRunSend = true; + try + { + var shpayList = new List<fl_shpay_hist>(); + foreach (var item in rownumber) + { + var row = gridView1.GetRow(item) as shpay_temp; + if (row == null || row.paytype == PayGetType.已领取) continue; + shpayList.Add(new fl_shpay_hist() + { + id = row.id, + chattype = row.chattype, + point = row.point, + ctime = row.ctime, + paytime = row.paytime, + uid = row.uid, + rid = row.rid, + paytype = row.paytype, + payurl = row.payurl, + ctimedate = row.ctimedate, + orderid = row.orderid, + sendtime = row.sendtime, + robotname = row.robot_name, + robotnick = row.robot_nick, + username = row.username, + usernick = row.usernick + }); + } + + if (shpayList.Count != 0) + { + if (XtraMessageBox.Show($"勾选项中未领取的用户有:{shpayList.Count}位,是否立即给客户发送领取消息?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.No) return; + + Utils.SendShPayMes(shpayList); + + EventClient.OnEvent("", $"商户未领取的用户通知完毕~!"); + } + else + { + BaseForm.ShowSuccessAutoClose("勾选项中没有存在未领取的用户,操作无效~!"); + } + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex, 10000); + } + finally + { + IsRunSend = false; + } + } + else + BaseForm.ShowErrorAutoClose("请勾选后操作~!"); + } + + private void button1_Click(object sender, EventArgs e) + { + ApiClient.Setting.SystemConfig.send_shpay_msg = memoEdit1.Text; + ApiClient.Setting.SystemConfig.send_shpay_switch = checkEdit1.Checked; + ApiClient.Setting.SystemConfig.send_shpay_minixml = checkEdit2.Checked; + ApiClient.Setting.Save(); + MessageBox.Show("保存成功~!"); + } + + private void linkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + var ll = sender as LinkLabel; + memoEdit1.Text += (ll != null ? ll.Text.Trim() : string.Empty); + } + + private static bool IsRunExchange = false; + + private void OneKeyToolStripMenuItem_Click(object sender, EventArgs e) + { + if (IsRunExchange) + { + BaseForm.ShowErrorAutoClose("已经有在运行的任务,请稍后重试~!"); + return; + } + IsRunExchange = true; + + try + { + var item = sender as ToolStripMenuItem; + if (item == null) throw new Exception("未知异常"); + + var rowNum = gridView3.GetSelectedRows().ToList();//获取选中行号; + if (rowNum == null || rowNum.Count == 0) throw new Exception("未勾选执行项~!"); + if (XtraMessageBox.Show($"确定要一键处理:{rowNum.Count}个审核项吗?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.No) return; + + var exchangeList = new List<exchange_list_temp>(); + foreach (var row in rowNum) + { + var temp = gridView3.GetRow(row) as exchange_list_temp; + if (temp != null) + exchangeList.Add(temp); + } + if (exchangeList != null && exchangeList.Count != 0) + new OneKeyExchangeForm(exchangeList, item.Text).ShowDialog(); + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex, 10000); + } + finally + { + IsRunExchange = false; + } + this.pageControl3.GotoPage(); + label3.Visible = gridView3.RowCount == 0; + } + + private void xtraTabControl1_Click(object sender, EventArgs e) + { + + } + } +} diff --git a/FLSystem/Forms/point_manage_control.resx b/FLSystem/Forms/point_manage_control.resx new file mode 100644 index 0000000..733d564 --- /dev/null +++ b/FLSystem/Forms/point_manage_control.resx @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton2.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <data name="simpleButton3.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <metadata name="contextMenuStrip3.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>179, 18</value> + </metadata> + <metadata name="contextMenuStrip2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>344, 18</value> + </metadata> + <data name="simpleButton4.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>42</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/private_pid_manage.Designer.cs b/FLSystem/Forms/private_pid_manage.Designer.cs new file mode 100644 index 0000000..e9bc56a --- /dev/null +++ b/FLSystem/Forms/private_pid_manage.Designer.cs @@ -0,0 +1,179 @@ +namespace FLSystem.Forms +{ + partial class private_pid_manage + { + /// <summary> + /// 必需的设计器变量。 + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// 清理所有正在使用的资源。 + /// </summary> + /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// <summary> + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// </summary> + private void InitializeComponent() + { + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(838, 537); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.FocusedCell.Options.UseTextOptions = true; + this.gridView1.Appearance.FocusedCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.FocusedRow.Options.UseTextOptions = true; + this.gridView1.Appearance.FocusedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.AppearancePrint.Row.Options.UseTextOptions = true; + this.gridView1.AppearancePrint.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4, + this.gridColumn5, + this.gridColumn6, + this.gridColumn7}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 40; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomDrawRowIndicator += new DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventHandler(this.gridView1_CustomDrawRowIndicator); + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "PID"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "推广位"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "用户名"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "昵称"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn5.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "类型"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn6.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "查询时使用"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 5; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn7.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "订单自动绑定"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 6; + // + // private_pid_manage + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.gridControl1); + this.Name = "private_pid_manage"; + this.Size = new System.Drawing.Size(838, 537); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + } +} diff --git a/FLSystem/Forms/private_pid_manage.cs b/FLSystem/Forms/private_pid_manage.cs new file mode 100644 index 0000000..4607297 --- /dev/null +++ b/FLSystem/Forms/private_pid_manage.cs @@ -0,0 +1,51 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System.Windows.Forms; + +namespace FLSystem.Forms +{ + public partial class private_pid_manage : UserControl + { + + public class view_private_pid + { + public long id { get; set; } + + /// <summary> + /// 用户名 + /// </summary> + public string username { get; set; } + + /// <summary> + /// 用户昵称 + /// </summary> + + public string usernick { get; set; } + + /// <summary> + /// 类型 + /// </summary> + + public ChatType robot_type { get; set; } + + /// <summary> + /// ID + /// </summary> + public string pid_id { get; set; } + public string pid_name { get; set; } + public string cps_name { get; set; } + + public CpsType cps_type { get; set; } + } + + public private_pid_manage() + { + InitializeComponent(); + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + } +} diff --git a/FLSystem/Forms/private_pid_manage.resx b/FLSystem/Forms/private_pid_manage.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Forms/private_pid_manage.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/robot_manage_control.Designer.cs b/FLSystem/Forms/robot_manage_control.Designer.cs new file mode 100644 index 0000000..3aae828 --- /dev/null +++ b/FLSystem/Forms/robot_manage_control.Designer.cs @@ -0,0 +1,356 @@ +namespace FLSystem.Forms +{ + partial class robot_manage_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.刷新数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.手动尝试登录ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.重新登录ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.注销登录ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.账号授权ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.设置支付密码ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.重置设备信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.接收状态开启关闭ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.掉线重连开启关闭ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.离线通知开启关闭ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.注销删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemPictureEdit1}); + this.gridControl1.Size = new System.Drawing.Size(806, 480); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.刷新数据ToolStripMenuItem, + this.toolStripSeparator2, + this.手动尝试登录ToolStripMenuItem, + this.重新登录ToolStripMenuItem, + this.注销登录ToolStripMenuItem, + this.账号授权ToolStripMenuItem, + this.设置支付密码ToolStripMenuItem, + this.重置设备信息ToolStripMenuItem, + this.接收状态开启关闭ToolStripMenuItem, + this.掉线重连开启关闭ToolStripMenuItem, + this.离线通知开启关闭ToolStripMenuItem, + this.toolStripSeparator1, + this.注销删除ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(181, 280); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 刷新数据ToolStripMenuItem + // + this.刷新数据ToolStripMenuItem.Name = "刷新数据ToolStripMenuItem"; + this.刷新数据ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.刷新数据ToolStripMenuItem.Text = "刷新数据"; + this.刷新数据ToolStripMenuItem.Click += new System.EventHandler(this.刷新数据ToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6); + // + // 手动尝试登录ToolStripMenuItem + // + this.手动尝试登录ToolStripMenuItem.Name = "手动尝试登录ToolStripMenuItem"; + this.手动尝试登录ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.手动尝试登录ToolStripMenuItem.Text = "尝试自动登录"; + this.手动尝试登录ToolStripMenuItem.Click += new System.EventHandler(this.手动尝试登录ToolStripMenuItem_Click); + // + // 重新登录ToolStripMenuItem + // + this.重新登录ToolStripMenuItem.Name = "重新登录ToolStripMenuItem"; + this.重新登录ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.重新登录ToolStripMenuItem.Text = "人工手动登录"; + this.重新登录ToolStripMenuItem.Click += new System.EventHandler(this.重新登录ToolStripMenuItem_Click); + // + // 注销登录ToolStripMenuItem + // + this.注销登录ToolStripMenuItem.Name = "注销登录ToolStripMenuItem"; + this.注销登录ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.注销登录ToolStripMenuItem.Text = "注销登录"; + this.注销登录ToolStripMenuItem.Click += new System.EventHandler(this.注销登录ToolStripMenuItem_Click); + // + // 账号授权ToolStripMenuItem + // + this.账号授权ToolStripMenuItem.Name = "账号授权ToolStripMenuItem"; + this.账号授权ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.账号授权ToolStripMenuItem.Text = "卡密授权"; + this.账号授权ToolStripMenuItem.Click += new System.EventHandler(this.账号授权ToolStripMenuItem_Click); + // + // 设置支付密码ToolStripMenuItem + // + this.设置支付密码ToolStripMenuItem.Name = "设置支付密码ToolStripMenuItem"; + this.设置支付密码ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.设置支付密码ToolStripMenuItem.Text = "设置支付密码"; + this.设置支付密码ToolStripMenuItem.Click += new System.EventHandler(this.设置支付密码ToolStripMenuItem_Click); + // + // 重置设备信息ToolStripMenuItem + // + this.重置设备信息ToolStripMenuItem.Name = "重置设备信息ToolStripMenuItem"; + this.重置设备信息ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.重置设备信息ToolStripMenuItem.Text = "重置设备信息"; + this.重置设备信息ToolStripMenuItem.Click += new System.EventHandler(this.重置设备信息ToolStripMenuItem_Click); + // + // 接收状态开启关闭ToolStripMenuItem + // + this.接收状态开启关闭ToolStripMenuItem.Name = "接收状态开启关闭ToolStripMenuItem"; + this.接收状态开启关闭ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.接收状态开启关闭ToolStripMenuItem.Text = "接收状态开启/关闭"; + this.接收状态开启关闭ToolStripMenuItem.Click += new System.EventHandler(this.接收状态开启关闭ToolStripMenuItem_Click); + // + // 掉线重连开启关闭ToolStripMenuItem + // + this.掉线重连开启关闭ToolStripMenuItem.Name = "掉线重连开启关闭ToolStripMenuItem"; + this.掉线重连开启关闭ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.掉线重连开启关闭ToolStripMenuItem.Text = "掉线重连开启/关闭"; + this.掉线重连开启关闭ToolStripMenuItem.Click += new System.EventHandler(this.掉线重连开启关闭ToolStripMenuItem_Click); + // + // 离线通知开启关闭ToolStripMenuItem + // + this.离线通知开启关闭ToolStripMenuItem.Name = "离线通知开启关闭ToolStripMenuItem"; + this.离线通知开启关闭ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.离线通知开启关闭ToolStripMenuItem.Text = "离线通知开启/关闭"; + this.离线通知开启关闭ToolStripMenuItem.Click += new System.EventHandler(this.离线通知开启关闭ToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(177, 6); + // + // 注销删除ToolStripMenuItem + // + this.注销删除ToolStripMenuItem.Name = "注销删除ToolStripMenuItem"; + this.注销删除ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.注销删除ToolStripMenuItem.Text = "删除机器人"; + this.注销删除ToolStripMenuItem.Click += new System.EventHandler(this.注销删除ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn6, + this.gridColumn4, + this.gridColumn7, + this.gridColumn8, + this.gridColumn10, + this.gridColumn9, + this.gridColumn5}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + // + // gridColumn1 + // + this.gridColumn1.Caption = "图标"; + this.gridColumn1.ColumnEdit = this.repositoryItemPictureEdit1; + this.gridColumn1.FieldName = "gridColumn1"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.UnboundType = DevExpress.Data.UnboundColumnType.Object; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 40; + // + // repositoryItemPictureEdit1 + // + this.repositoryItemPictureEdit1.Name = "repositoryItemPictureEdit1"; + // + // gridColumn2 + // + this.gridColumn2.Caption = "平台类型"; + this.gridColumn2.FieldName = "gridColumn2"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 86; + // + // gridColumn3 + // + this.gridColumn3.Caption = "机器人账号"; + this.gridColumn3.FieldName = "name"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.ReadOnly = true; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 143; + // + // gridColumn6 + // + this.gridColumn6.Caption = "授权编号"; + this.gridColumn6.FieldName = "uin"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 3; + // + // gridColumn4 + // + this.gridColumn4.Caption = "机器人昵称"; + this.gridColumn4.FieldName = "nick"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.ReadOnly = true; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 4; + this.gridColumn4.Width = 143; + // + // gridColumn7 + // + this.gridColumn7.Caption = "状态"; + this.gridColumn7.FieldName = "gridColumn7"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 56; + // + // gridColumn8 + // + this.gridColumn8.Caption = "接收状态"; + this.gridColumn8.FieldName = "is_receives"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 6; + this.gridColumn8.Width = 80; + // + // gridColumn10 + // + this.gridColumn10.Caption = "离线重登"; + this.gridColumn10.FieldName = "off_line_auto_login"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 7; + // + // gridColumn9 + // + this.gridColumn9.Caption = "离线通知"; + this.gridColumn9.FieldName = "off_line_tip"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 8; + // + // gridColumn5 + // + this.gridColumn5.Caption = "到期时间"; + this.gridColumn5.FieldName = "end_time"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.ReadOnly = true; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 9; + this.gridColumn5.Width = 131; + // + // robot_manage_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.gridControl1); + this.Name = "robot_manage_control"; + this.Size = new System.Drawing.Size(806, 480); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 刷新数据ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private System.Windows.Forms.ToolStripMenuItem 重新登录ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 注销删除ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripMenuItem 注销登录ToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripMenuItem 设置支付密码ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 账号授权ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 重置设备信息ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private System.Windows.Forms.ToolStripMenuItem 接收状态开启关闭ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private System.Windows.Forms.ToolStripMenuItem 离线通知开启关闭ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 手动尝试登录ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 掉线重连开启关闭ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + } +} diff --git a/FLSystem/Forms/robot_manage_control.cs b/FLSystem/Forms/robot_manage_control.cs new file mode 100644 index 0000000..e6cedb0 --- /dev/null +++ b/FLSystem/Forms/robot_manage_control.cs @@ -0,0 +1,594 @@ +using Api.Framework; +using Api.Framework.Model; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using DevExpress.XtraEditors; +using Api.Framework.Tools; +using System; +using System.ComponentModel; +using System.Linq; +using System.Windows.Forms; +using Grant.Framework; +using Chat.Framework.QQSdk; +using System.Threading.Tasks; +using UI.Framework.Forms; +using Api.Framework.Utils; +using System.Collections.Generic; +using Api.Framework.Events; +using CsharpHttpHelper; +using System.Text; +using Robot.Framework.Entities; +using Chat.Framework.QQSdk.QPlus; +using PCRobot.Pack; + +namespace FLSystem.Forms +{ + public partial class robot_manage_control : DevExpress.XtraEditors.XtraUserControl + { + public robot_manage_control() + { + InitializeComponent(); + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + + Refresh(); + EventClient.MethodEvent += EventClient_MethodEvent; + this.Disposed += Robot_manage_control_Disposed; + } + + private void Robot_manage_control_Disposed(object sender, EventArgs e) + { + EventClient.MethodEvent -= EventClient_MethodEvent; + } + + private void EventClient_MethodEvent(object sender, Api.Framework.Events.MethodType e) + { + if (e == Api.Framework.Events.MethodType.刷新机器人) + { + this.Invoke(new Action(delegate + { + Refresh(); + })); + } + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + private new void Refresh() + { + try + { + this.gridControl1.DataSource = null; + var session = ApiClient.GetSession(); + //所有机器人列表 + var robotList = session.FindRobots(true); + + if (robotList != null && robotList.Count != 0) + { + var loginWxs = ChatClient.WXClient.Values.Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线).ToList(); + //在线集合 + var robotTemp_online = robotList.Where(f => loginWxs.FirstOrDefault(z => z.WeixinHao == f.name) != null).OrderBy(f => f.type).ToList(); + //离线集合 + var robotTemp_offline = robotList.Where(f => loginWxs.FirstOrDefault(z => z.WeixinHao == f.name) == null).ToList(); + + robotTemp_online.AddRange(robotTemp_offline); + robotList = robotTemp_online; + } + + this.gridControl1.DataSource = robotList; + } + catch (Exception) + { + + } + } + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + var row = e.Row as fl_robot_info; + + if (e.Column.Caption == "图标") + { + if (row.type == Api.Framework.SDK.ChatType.微信) + e.Value = Properties.Resources.微信__1_; + else if (row.type == Api.Framework.SDK.ChatType.QQ) + e.Value = Properties.Resources.QQ; + if (row.type == Api.Framework.SDK.ChatType.企业微信) + e.Value = Properties.Resources.微信__1_; + } + + else if (e.Column.Caption == "状态") + { + if (row.type == Api.Framework.SDK.ChatType.微信 || row.type == Api.Framework.SDK.ChatType.企业微信) + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == row.name).Value; + //if (wx == null) + //{ + //var temp = Chat.Framework.ChatClient.PCRobotPool.GetSession(row.name); + //if (temp != null) + //{ + // e.Value = "在线"; + // return; + //} + //} + e.Value = wx == null ? "未登陆" : wx.Status.ToString(); + } + else if (row.type == Api.Framework.SDK.ChatType.QQ) + { + if (ChatClient.QQClients.ContainsKey(row.name)) + { + var qBase = ChatClient.QQClients[row.name]; + if (qBase == null || qBase == null) + e.Value = "未登陆"; + else + { + if (qBase is QQClientImpl_QQPlus) + { + var q = qBase as QQClientImpl_QQPlus; + e.Value = q.QQClient.User.LoginStatus == LoginStatus.Login ? "在线" : "未登陆"; + } + } + } + else + e.Value = "未登陆"; + } + } + else if (e.Column.Caption == "平台类型") + { + if (row.type == Api.Framework.SDK.ChatType.微信) + e.Value = row.remark == "PCWechat HOOK" ? "PC微信" : "协议微信"; + else if (row.type == Api.Framework.SDK.ChatType.QQ) + e.Value = "QQ"; + else if (row.type == Api.Framework.SDK.ChatType.企业微信) + e.Value = "企业微信"; + else if (row.type == Api.Framework.SDK.ChatType.微信公众号) + e.Value = "微信公众号"; + else if (row.type == Api.Framework.SDK.ChatType.未知来源) + e.Value = "微信公众号"; + } + } + + private void 刷新数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + Refresh(); + } + + private void 重新登录ToolStripMenuItem_Click(object sender, EventArgs e) + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + + if (row.remark == "PCWechat HOOK") + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == row.name); + if (wx != null && wx.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + BaseForm.ShowErrorAutoClose("PC微信当前在线状态"); + return; + } + if (string.IsNullOrWhiteSpace(row.token)) + { + BaseForm.ShowSuccessAutoClose("PC微信未包含设备信息,请在易转发端登录"); + } + else + { + Task.Run(() => + { + ChatClient.LoginPcWeixin(row.token, row.name, row.type == Api.Framework.SDK.ChatType.微信 ? RobotType.客户端微信 : RobotType.客户端企业微信); + }); + } + return; + } + + if (row.is_login) if (MessageBox.Show("确定要重新登录吗?", "重新登录", MessageBoxButtons.OKCancel) != DialogResult.OK) return; + if (row.type == Api.Framework.SDK.ChatType.微信) + { + if (row.remark != "PCWechat HOOK") + ChatClient.LoginWeixin(row.name); + else + BaseForm.ShowSuccessAutoClose("PC微信请在易转发端登录"); + } + else if (row.type == Api.Framework.SDK.ChatType.QQ) + { + 注销登录ToolStripMenuItem_Click(null, null); + ChatClient.LoginQQ(row.name); + } + Refresh(); + } + + private void 注销删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + if (XtraMessageBox.Show(@"您确定要删除机器人吗? + +重要提醒: +①、删除后会导致提现找不到机器人 +②、删除后订单无法通知到会员信息 +③、数据库中、有连锁关联均会异常 + +除非您不打算用这个微信号,否则请勿删除!", "删除机器人", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK) + + { + var verify = new Grant.Framework.VerifyPassForm(); + + if (verify.ShowDialog() == DialogResult.OK) + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + var session = ApiClient.GetSession(); + if (row.is_login) + { + switch (row.type) + { + case Api.Framework.SDK.ChatType.QQ: + { + if (ChatClient.QQClients.ContainsKey(row.name)) + { + var qClient = ChatClient.QQClients[row.name]; + #region 删除发单中无用的机器人账号,为了防止自动绑定失效 + //不存在表的情况会报错,直接忽略 + try { session.ExcuteSQL("delete from fl_plugin_tbcirclepromotion_tbtgw where robot_id in (select robot_id from fl_plugin_tbcirclepromotion_tbtgw where robot_id not in (select id from fl_robot_info))"); } catch { } + try { session.ExcuteSQL("delete from fl_plugin_pddcirclepromotion_pddtgw where robot_id in (select robot_id from fl_plugin_pddcirclepromotion_pddtgw where robot_id not in (select id from fl_robot_info))"); } catch { } + #endregion + try + { + qClient.Logout(); + } + catch (Exception ex) + { } + ChatClient.QQClients.Remove(row.name); + } + } + break; + case Api.Framework.SDK.ChatType.微信: + case Api.Framework.SDK.ChatType.企业微信: + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == row.name).Value; + if (wx != null) + { + #region 删除发单中无用的机器人账号,为了防止自动绑定失效 + //不存在表的情况会报错,直接忽略 + try { session.ExcuteSQL("delete from fl_plugin_tbcirclepromotion_tbtgw where robot_id in (select robot_id from fl_plugin_tbcirclepromotion_tbtgw where robot_id not in (select id from fl_robot_info))"); } catch { } + try { session.ExcuteSQL("delete from fl_plugin_pddcirclepromotion_pddtgw where robot_id in (select robot_id from fl_plugin_pddcirclepromotion_pddtgw where robot_id not in (select id from fl_robot_info))"); } catch { } + #endregion + + EventClient.OnEvent("", $"删除机器人:{wx.User.Nick}({wx.WeixinHao})"); + wx.LoginOut(); + wx.Dispose(); + } + break; + case Api.Framework.SDK.ChatType.微信公众号: + break; + case Api.Framework.SDK.ChatType.未知来源: + break; + default: + break; + } + } + session.ExcuteSQL("delete from fl_robot_info where id=" + row.id); + session.ExcuteSQL("delete from fl_weixin_password where robot_id=" + row.id); + + Refresh(); + } + } + } + + private void 注销登录ToolStripMenuItem_Click(object sender, EventArgs e) + { + if (sender == null || MessageBox.Show("确定要注销此机器人吗?", "注销机器人", MessageBoxButtons.OKCancel) == DialogResult.OK) + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + if (row != null) + { + if (row.type == Api.Framework.SDK.ChatType.微信 || row.type == Api.Framework.SDK.ChatType.企业微信) + { + row.is_login = false; + ApiClient.GetSession().SaveOrUpdate(row); + EventClient.OnEvent("", $"注销机器人:{row.nick}({row.name})"); + ChatClient.LoginOutWeixin(row.name); + } + else if (row.type == Api.Framework.SDK.ChatType.QQ) + ChatClient.LoginOutQQ(row.name); + } + if (sender != null) + Refresh(); + } + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + var r = this.gridView1.GetSelectedRows(); + + 设置支付密码ToolStripMenuItem.Visible = 设置支付密码ToolStripMenuItem.Enabled = 账号授权ToolStripMenuItem.Enabled = 注销删除ToolStripMenuItem.Enabled = 重新登录ToolStripMenuItem.Enabled = 注销登录ToolStripMenuItem.Enabled = 手动尝试登录ToolStripMenuItem.Enabled = 重置设备信息ToolStripMenuItem.Enabled = false; + + if (r.Length != 0) + { + + 账号授权ToolStripMenuItem.Enabled = 注销删除ToolStripMenuItem.Enabled = true; + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + if (row.type == Api.Framework.SDK.ChatType.微信) + { + 手动尝试登录ToolStripMenuItem.Enabled = 重置设备信息ToolStripMenuItem.Enabled = true; + + 掉线重连开启关闭ToolStripMenuItem.Enabled = 设置支付密码ToolStripMenuItem.Visible = 重新登录ToolStripMenuItem.Enabled = true; + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == row.name).Value; + if (wx != null) + { + var _bool = wx.Status == Chat.Framework.WXSdk.WxStatus.在线; + if (_bool) 设置支付密码ToolStripMenuItem.Enabled = true; + 注销登录ToolStripMenuItem.Enabled = _bool; + } + } + else + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == row.name).Value; + if (wx != null) + { + var _bool = wx.Status == Chat.Framework.WXSdk.WxStatus.在线; + 注销登录ToolStripMenuItem.Enabled = _bool; + } + 重新登录ToolStripMenuItem.Enabled = true; + } + + //if (row.remark == "PCWechat HOOK") + // 账号授权ToolStripMenuItem.Enabled = false; + //else + if (row.type == Api.Framework.SDK.ChatType.QQ) + { + 重置设备信息ToolStripMenuItem.Visible = 设置支付密码ToolStripMenuItem.Visible = 掉线重连开启关闭ToolStripMenuItem.Enabled = false; + 重新登录ToolStripMenuItem.Enabled = true; + 手动尝试登录ToolStripMenuItem.Enabled = true; + if (ChatClient.QQClients.ContainsKey(row.name)) + { + var qBase = ChatClient.QQClients[row.name]; + if (qBase is QQClientImpl_QQPlus) + { + var q = qBase as QQClientImpl_QQPlus; + var _bool = q.QQClient.User.LoginStatus == LoginStatus.Login; + if (_bool) 设置支付密码ToolStripMenuItem.Enabled = true; + 注销登录ToolStripMenuItem.Enabled = _bool; + } + } + } + } + else + e.Cancel = true; + } + + private void 设置支付密码ToolStripMenuItem_Click(object sender, EventArgs e) + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + if (row.type == Api.Framework.SDK.ChatType.微信) + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == row.name).Value; + + if (wx != null && wx.WeixinType == WeixinType.Grpc微信 && wx.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + var temp = wx as WXClientImpl_IPAD; + if (temp != null) + new set_weixin_password(temp).Show(); + } + else if (wx.WeixinType == WeixinType.Hook微信 || wx.WeixinType == WeixinType.QYHook微信) BaseForm.ShowErrorAutoClose("该协议不支持微信支付"); + } + } + + private void 账号授权ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + if ((row.uin == "-1" || row.uin == "0") && row.remark == "PCWechat HOOK" && string.IsNullOrWhiteSpace(row.token)) + throw new Exception("当前为PC微信,目前免费使用,无需授权!"); + + if (row.uin != "-1" && row.uin != "0") + { + var authorization = new add_authorization(row); + authorization.ShowDialog(); + } + else + throw new Exception("账号存在异常,无法进行授权"); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 重置设备信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + var r = this.gridView1.GetSelectedRows(); + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + if (row != null) new set_wechat_device(row.name).ShowDialog(); + else new set_wechat_device("").ShowDialog(); + } + + private void 接收状态开启关闭ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + if (row != null) + { + row.is_receives = (row.is_receives == Api.Framework.Enums.SwitchType.开启) ? Api.Framework.Enums.SwitchType.关闭 : Api.Framework.Enums.SwitchType.开启; + var session = ApiClient.GetSession(); + session.SaveOrUpdate(row); + Refresh(); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 离线通知开启关闭ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + if (row != null) + { + row.off_line_tip = (row.off_line_tip == Api.Framework.Enums.SwitchType.开启) ? Api.Framework.Enums.SwitchType.关闭 : Api.Framework.Enums.SwitchType.开启; + var session = ApiClient.GetSession(); + session.SaveOrUpdate(row); + Refresh(); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 手动尝试登录ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + List<fl_robot_info> weixins = new List<fl_robot_info>(); + List<fl_robot_info> qqs = new List<fl_robot_info>(); + for (int i = 0; i < r.Length; i++) + { + var _row = this.gridView1.GetRow(r[i]) as fl_robot_info; + if (_row != null) + { + if (_row.type == Api.Framework.SDK.ChatType.企业微信) + { + BaseForm.ShowErrorAutoClose(@"企业微信不支持自动登录 +请在易转发程序端扫码登录"); + return; + } + else if (_row.type == Api.Framework.SDK.ChatType.微信) + { + if (_row.remark != "PCWechat HOOK") + weixins.Add(_row); + else + { + BaseForm.ShowErrorAutoClose(@"PC微信不支持自动登录 +请在易转发程序端扫码登录"); + return; + } + } + //else if (_row.type == Api.Framework.SDK.ChatType.微信 && (_row.remark != "PCWechat HOOK")) + else if (_row.type == Api.Framework.SDK.ChatType.QQ) + qqs.Add(_row); + } + } + if (weixins.Count == 0 && qqs.Count == 0) + { + BaseForm.ShowErrorAutoClose("当前没有可以自动登陆的账号"); + return; + } + TaskTool tasks = new TaskTool(); + foreach (var item in weixins) + { + var _item = item; + tasks.AddTask(delegate () + { + try + { + EventClient.OnEvent(this, $"正在自动微信->{_item.name}({_item.nick})..."); + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == _item.name).Value; + if (wx != null) wx.ResetConnection(); + else ChatClient.LoginWeixin(_item.name, _item.token); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"登录微信->{_item.name}({_item.nick})异常:{ex.Message}"); + } + }); + } + + if (qqs.Count != 0) + { + for (int i = 0; i < 1; i++) + { + var _item = qqs[i]; + tasks.AddTask(delegate () + { + try + { + EventClient.OnEvent(this, $"正在自动QQ->{_item.name}({_item.nick})..."); + if (string.IsNullOrWhiteSpace(_item.token)) throw new Exception("该账号请手动登录!"); + + var dic = HttpExtend.JsonToDictionary(Encoding.UTF8.GetString(HttpExtend.HexToByte(_item.token))); + if (dic != null) + { + if (dic.ContainsKey("QQ")) + { + var QQ = dic["QQ"]?.ToString(); + if (!string.IsNullOrWhiteSpace(QQ) && dic.ContainsKey("Password")) + { + var Password = dic["Password"]?.ToString(); + var qq = uint.Parse(QQ); + if (ChatClient.QQClients.ContainsKey(QQ)) + { + var qBase = ChatClient.QQClients[QQ]; + if (!qBase.IsLogin) + qBase.Login(); + } + else + { + var IsEQQ = false; + if (!string.IsNullOrWhiteSpace(Password) && dic.ContainsKey("IsEQQ")) + IsEQQ = (dic["IsEQQ"].ToString().ToLower() == "true"); + var qqClient = ChatClient.LoginQQ(QQ, Password); + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"登录QQ->{_item.name}({_item.nick})异常:{ex.Message}"); + } + }); + } + } + + tasks.Start(30, AsyncCallbackMethod); + EventClient.OnEvent(this, MethodType.刷新机器人); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void AsyncCallbackMethod(IAsyncResult ar) + { + EventClient.OnEvent(this, $"手动尝试登录微信执行完毕!"); + } + + private void 掉线重连开启关闭ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var r = this.gridView1.GetSelectedRows(); + if (r.Length == 0) return; + var row = this.gridView1.GetRow(r[0]) as fl_robot_info; + if (row != null) + { + row.off_line_auto_login = (row.off_line_auto_login == Api.Framework.Enums.SwitchType.开启) ? Api.Framework.Enums.SwitchType.关闭 : Api.Framework.Enums.SwitchType.开启; + var session = ApiClient.GetSession(); + session.SaveOrUpdate(row); + Refresh(); + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/FLSystem/Forms/robot_manage_control.resx b/FLSystem/Forms/robot_manage_control.resx new file mode 100644 index 0000000..ddb8978 --- /dev/null +++ b/FLSystem/Forms/robot_manage_control.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 22</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/select_member_form.Designer.cs b/FLSystem/Forms/select_member_form.Designer.cs new file mode 100644 index 0000000..dac2a4a --- /dev/null +++ b/FLSystem/Forms/select_member_form.Designer.cs @@ -0,0 +1,197 @@ +namespace FLSystem.Forms +{ + partial class select_member_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.Location = new System.Drawing.Point(2, 52); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(743, 321); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + this.gridControl1.DoubleClick += new System.EventHandler(this.gridControl1_DoubleClick); + // + // gridView1 + // + this.gridView1.Appearance.ViewCaption.Options.UseTextOptions = true; + this.gridView1.Appearance.ViewCaption.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.AppearancePrint.Row.Options.UseTextOptions = true; + this.gridView1.AppearancePrint.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "ID"; + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "用户名"; + this.gridColumn2.FieldName = "username"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "昵称"; + this.gridColumn3.FieldName = "usernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "备注"; + this.gridColumn4.FieldName = "remak"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 375); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(745, 33); + this.pageControl1.TabIndex = 3; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(183, 17); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(91, 14); + this.label1.TabIndex = 4; + this.label1.Text = "用户名或昵称:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(280, 13); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(153, 22); + this.textBox1.TabIndex = 5; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(449, 13); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 23); + this.simpleButton1.TabIndex = 6; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // select_member_form + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(745, 408); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.Controls.Add(this.pageControl1); + this.Controls.Add(this.gridControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "select_member_form"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "选择用户 - 双击选中的数据"; + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private UI.Framework.Controls.PageControl pageControl1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/select_member_form.cs b/FLSystem/Forms/select_member_form.cs new file mode 100644 index 0000000..2cf7e90 --- /dev/null +++ b/FLSystem/Forms/select_member_form.cs @@ -0,0 +1,66 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class select_member_form : BaseForm + { + public select_member_form() + { + InitializeComponent(); + + try + { + this.pageControl1.Bind(delegate (int page, int size) + { + try + { + var session = ApiClient.GetSession(); + var map = session.NewParamMap(); + map.setPageParamters(page, size); + PageResult<fl_member_info> members = null; + if (!string.IsNullOrEmpty(this.textBox1.Text)) + { + map.setParameter("username", "%" + this.textBox1.Text + "%"); + map.setParameter("usernick", "%" + this.textBox1.Text + "%"); + members = session.FindPage<fl_member_info>("select * from fl_member_info where username like @username or usernick like @usernick", map); + } + else + members = session.FindPage<fl_member_info>("select * from fl_member_info", map); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = members.DataList, Total = members.Total }; + } + catch (Exception ex) + { + ShowError(ex); + } + return null; + }, this.gridControl1, 50, true, true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl1.Go(sender, e); + } + + private void gridControl1_DoubleClick(object sender, EventArgs e) + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length > 0) + { + var row = this.gridView1.GetRow(rows[0]); + fl_member_info = row as fl_member_info; + this.Close(); + } + } + public fl_member_info fl_member_info { get; private set; } + + } +} diff --git a/FLSystem/Forms/select_member_form.resx b/FLSystem/Forms/select_member_form.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/select_member_form.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/set_private_pid.resx b/FLSystem/Forms/set_private_pid.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/set_private_pid.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/set_wechat_device.Designer.cs b/FLSystem/Forms/set_wechat_device.Designer.cs new file mode 100644 index 0000000..5c92275 --- /dev/null +++ b/FLSystem/Forms/set_wechat_device.Designer.cs @@ -0,0 +1,124 @@ +namespace FLSystem.Forms +{ + partial class set_wechat_device + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(set_wechat_device)); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit2 = new DevExpress.XtraEditors.MemoEdit(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(44, 45); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(48, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "微信号:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(32, 100); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "设备信息:"; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(108, 42); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(243, 20); + this.textEdit1.TabIndex = 2; + this.textEdit1.EditValueChanged += new System.EventHandler(this.textEdit1_EditValueChanged); + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(108, 94); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(243, 147); + this.textEdit2.TabIndex = 3; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(32, 151); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(48, 14); + this.hyperlinkLabelControl1.TabIndex = 4; + this.hyperlinkLabelControl1.Text = "随机生成"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(152, 268); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(133, 34); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "更新设备"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // set_wechat_device + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(386, 331); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.hyperlinkLabelControl1); + this.Controls.Add(this.textEdit1); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.textEdit2); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "set_wechat_device"; + this.Text = "SetWechatDevice"; + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.MemoEdit textEdit2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/set_wechat_device.cs b/FLSystem/Forms/set_wechat_device.cs new file mode 100644 index 0000000..63130de --- /dev/null +++ b/FLSystem/Forms/set_wechat_device.cs @@ -0,0 +1,87 @@ +using Api.Framework; +using Api.Framework.Model; +using System; +using System.Text; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class set_wechat_device : BaseForm + { + + public set_wechat_device(string weixinhao) + { + InitializeComponent(); + this.textEdit1.Text = weixinhao; + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + this.textEdit2.Text = Get62Data(CsharpHttpHelper.HttpExtend.GetMD5String(Guid.NewGuid().ToString())); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (!this.textEdit2.Text.StartsWith("62") || this.textEdit2.Text.EndsWith("07f")) throw new Exception("您的设备信息有误,请点击随机生成!"); + if (string.IsNullOrEmpty(this.textEdit2.Text)) throw new Exception("微信号有误,请重新输入!"); + + if (MessageBox.Show("重置设备信息后,回复消息可能提示操作频繁,确定要重置吗?", "请谨慎操作", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + var device = session.Queryable<fl_wechat_device>().Where(f => f.weixinhao == this.textEdit1.Text).Single(); + if (device == null) + device = new fl_wechat_device() { weixinhao =this.textEdit1.Text}; + device.device_info = this.textEdit2.Text; + if (device.id == 0) session.Insertable<fl_wechat_device>(device).ExecuteCommand(); + else session.Updateable<fl_wechat_device>(device).ExecuteCommand(); + ShowSuccess("重置设备信息成功!\r\n重新登陆微信后生效!"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private string Get62Data(string imei) + { + string hexStr = CsharpHttpHelper.HttpExtend.ByteToHex(Encoding.UTF8.GetBytes(imei)).Replace(" ", ""); + string str = "62706c6973743030d4010203040506090a582476657273696f6e58246f626a65637473592461726368697665725424746f7012000186a0a2070855246e756c6c5f1020" + hexStr + "5f100f4e534b657965644172636869766572d10b0c54726f6f74800108111a232d32373a406375787d0000000000000101000000000000000d0000000000000000000000000000007f"; + return str; + } + + private void textEdit1_EditValueChanged(object sender, EventArgs e) + { + try + { + if (!string.IsNullOrEmpty(this.textEdit1.Text)) + { + var session = ApiClient.GetSession(); + var device = session.Queryable<fl_wechat_device>().Where(f => f.weixinhao == this.textEdit1.Text).Single(); + if (device != null) + { + if (device.device_info.StartsWith("62") && device.device_info.EndsWith("07f")) + this.textEdit2.Text = device.device_info; + else + { + var Ime = CsharpHttpHelper.HttpExtend.GetMD5String(this.textEdit1.Text + device.device_info); + this.textEdit2.Text = Get62Data(device.device_info); + } + } + else + { + var Ime = CsharpHttpHelper.HttpExtend.GetMD5String(this.textEdit1.Text); + this.textEdit2.Text = Get62Data(Ime); + } + } + else this.textEdit2.Text = ""; + } + catch (Exception ) + {} + } + + } +} diff --git a/FLSystem/Forms/set_wechat_device.resx b/FLSystem/Forms/set_wechat_device.resx new file mode 100644 index 0000000..1b9f6ae --- /dev/null +++ b/FLSystem/Forms/set_wechat_device.resx @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUAUmVmcmVzaDtSZXBlYXQ7QmFycztSaWJib247UmVsb2FkzU326QAACWhJREFUWEfFlwlUk1cWgB/W + XUc7LsXWWrfR0arVERV0HKVV66goiy1qkVEEpai4s68iigpHRdwQIeAERKoQNyQgAgISWQISBWUHZZXd + kIQQvL33J3E4Pc6cOZ2ezjvnO2+727vv/i/AAOD/ygcXf0/+l6b1AX6z9u8M07iPmo8+gGavt85/bkei + ctmRnxDsvRBsnBPPyKwIx9DH12msWTt4UfiFa9jjvW78TKEHPzPHPTxL5cbPUrn+84nY5apI6Bicum/X + KcF4lNUEo+Uc9oQ5hRIi5sQTMUdeBnMIQYKpf8yY13Uxk7979x5SdOGlr7uaUgxBwgKwDYg3JIPb/eL2 + HLkuVsU8KYenVc1Q1igFWXc3R1njW1xrgpsZZeAVka2yC0oNtvQOH0d6ZK+j+x3rjVTNwaA0xjyuZTMZ + TghsWt/t8RnkGZFV+qpVDhUtHbD/UkrpX41thpi68qcdCkxWNneqoFqpggqFCgrlXfBM1gVF2NO8TtkN + b3B+O7MCnEMypLtPx65Dm/0oCKkKnf6CfRcfMYYpfO+cBB1D0l3u5VRBPTopV3RBZGoxWPrGuuJef1O3 + m77hKUVQhE7ypV3wVKrs4a0S8tQ8bVdClVwFBTXt4B72BHadEdqhLhdEe9c71hvbcymM0R1ROkjAxi9m + /LEosbQBT/Siowvy0Fjl207Yfz6pw2CX/yQ9I9tRGz2ja15iZsowiAo1JShbiIHktnZCNpLVqgBJeyeU + NsnANTRDZeUTbaoOQkvjvK2rm+30f8iwKETknE7f1y4oLVZc0QwVGEB2CxlTQD4GkVJQCxs9ou+jzMDl + NpeNjewjwcQxEvS2XQa9LYFg7HANjkZkQHZ1GxeEqEkBokY55DQrQFzVgnWU3GayL2Ay6lNNaJHzVsT6 + 1AOc9jj/yNZfaBR4/znUdnaDGB2LmuRqFFCM6fYMTYc1e4JNUHbgfLOztvM2+q4YM/3rYYTO98dW6pqd + Dfza+kpn6MNCyELnaQ0ySK2XwVO0wU8qAsvj93ioOwDp06LsZoTVyXic4sKS9TuHYOWWFWNlP8PUpaMy + xxs5h6hRBnmvW8DQLrJs3KxvhqMOpVPz7RN9kQFzDN0XLdpyqSY0sRAeo35STQck1UpB0tABu/0fqlZb + +05Ty2o1darYVp84HOLCztNCtxvppVCOd0lRp9R2/Iu6HsR4krM3s2Gp1SV31OmPaN4HDTTvP3uds94y + 6yBlGl5l4uu3EF/1FtLrpHDhrgR+cL/hSTIk36hQsb0BSYyZe4R/idUqr8IiEr2RwQNUSnwtxV4KidWI + ek7jgmY5mDpGKuesc56FRriTaNJJY4SyMXDh5jNBJ7Am0jAD98rbMYh2uCV+DZs8BOiRDUL61GMAu89g + EVqfSrif8KwOJFgwORhADqYuB7MQV9mOvIVsnGugvZiMEpi/0Z9yx52EUkk9GUW4AHRMDv99g+N1zt6t + 4laOxNJm2OB+qxb3/4BorrAPM3KIgnVY1QYHI2D1vgiw8o0HEab+Tmkb3Clr48Z4V7B4yyVYaH4BdM3O + wbyN/vQz1vsayBgV2GBk2HDtP322zDoE8vFQN140Q1RhMyThYUzdBErcH41QHQ1FKBtcNO+VDRxiOgvb + OiHmZQvEFLXAI7wCCmCY9pQxuE/RkxzJk1PNyQdsPXofeoiFrcdi4Xs3AeRhANeeNUG4pAliS1rBxCka + LI7FwTa0t83nPlhij7rvjdCdDl6x/0ZNJqbu+vMmuF7QBAnlbVTBsHrnuRW4P1Atx528VtaFXU8ABvv4 + QmHuK6jBh6lajRg/x7C8N8DLfQMCzIIEr7AUD1eIb0xEykuYY+Ibz/R3BLOi1k6NoYFLd0Y8uphUCgFp + NRCcUw/RqOgveArrHa4F4j6dnjs5OmAEjZF+840d/2J2WNB1t6gZeOIGCEHd4OwGuJJdD0FZ9RDwuAaO + CCvB7W45+D2ogiUWl7om6G3TYX+zCGQvW7gAyFD/hZYhnrYX0zhl7/hK8Et+DXckDfAPr7vK5RYnF6EM + ZUGTfg00H7Jka8AJr4hM4Oc1QOCTOrgoqoXTqdWcHbd75eCCzmls5n0Xpi538iUdpmsWwApbFDjmDPX9 + 0sBtpr7tT6rw3AY4LKwAr7gKOJ1cDbyHJWDqEl2rb+69mFPsKUK6DoLGgz/+bLq2vtWViqD0KvBJqOKc + uqodO98pA1fsXW48h+mrjlQOHjFJm9PTMT3DCpoVHNjoGgbNMb8StjdIBL4PX4F7bDl4xFZAIKYwNKkE + zDxvKw0P8i9/a3VmLcp+TCy3Or3KwJa3D8cjvlrjstnc6xacSn4FruiUHDveLgOHW6VwBA+zzPoKjFtg + vZn8IH3YbGNfJmlSsGcINspCvwn6e6bpWPClvsISzrnrHTwJGrqAdZHwognOYE3s8BViRgRg6iyA7Sfi + YPtxIehu8CHDn8w18Uv0upmP993j2F5QAs63S2HH+VQYv9g+EWU0z7kWm2Hgw/IbFYic5TfJca2nGKca + +potsomCo/fLOUPOeAonxBMDCstqgEf4UOU2yEFCv3r4cMW/bIRvbfmvPpmsN/nzOev19Lddlp14UAH2 + MaVgF40BCIrhq7U+spFTDXXJPvkZt9CBsWkrvVneG3kPGAQ2rhaQwVOM/F30fowCu8jn4HGvAhzxNA4C + DSXggMYJe5x7Y3o9rmaCntnZ86g7Zso3zsct/eK4e3dCPYOD12DM3B99cI/eErKv9emCQ4yt2B3BctG5 + GKGeoE210JAJq4+ZzzC72rHhRAq43SoBd7VBR3R6KKYEDuHpKAAK6sKjalh7IKpryhKrhUNHTRw3fZV3 + 5eE7L2E3LwvG6h6o7D907Kdokx4xrcw6GdOei2WzzIbPxA2y9+B7z0FCCAUxSHuB1YxJxhciZprzVZt8 + EmBXSDYcCJeABwbjjlW+ny8Bm6BsMPUWwpLtYSod09NOqPfHsfOtzVftCQXdTf4wYtoP5rhGXw/3CYsw + gNGzbRlbuuMqEsb+vDGUTd2AmPLYFGID/f3ABUEKFPXQ0fMsZo5f4+cywehS8kTjy5KJ3/FgwnoejDcK + lHxheDH585UnXUfOtZiJsuSI7nn4FwvtY0fN3CHE8TCEK7yRs3aykbN2sRHY/zeNgqDCpEC47x2he6RP + cIQaGpMDzftAsgQ5JHmCxmTnVzcKpHcwdD29oTXa08j1ltes/6btl45+XfvQf6y/H8B+Bv87a1kNkH9+ + AAAAAElFTkSuQmCC +</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/set_weixin_password.Designer.cs b/FLSystem/Forms/set_weixin_password.Designer.cs new file mode 100644 index 0000000..2dd0054 --- /dev/null +++ b/FLSystem/Forms/set_weixin_password.Designer.cs @@ -0,0 +1,286 @@ +namespace FLSystem.Forms +{ + partial class set_weixin_password + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit5 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.textEdit3); + this.groupControl1.Controls.Add(this.labelControl4); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.labelControl3); + this.groupControl1.Controls.Add(this.textEdit2); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Location = new System.Drawing.Point(11, 10); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(455, 252); + this.groupControl1.TabIndex = 9; + this.groupControl1.Text = "支付设置"; + // + // textEdit3 + // + this.textEdit3.Location = new System.Drawing.Point(168, 197); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Properties.PasswordChar = '*'; + this.textEdit3.Size = new System.Drawing.Size(211, 20); + this.textEdit3.TabIndex = 15; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(96, 200); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(52, 14); + this.labelControl4.TabIndex = 14; + this.labelControl4.Text = "支付密码:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.EditValue = "微信零钱支付"; + this.comboBoxEdit1.Location = new System.Drawing.Point(168, 145); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "微信零钱支付"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(211, 20); + this.comboBoxEdit1.TabIndex = 13; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(96, 147); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(52, 14); + this.labelControl3.TabIndex = 12; + this.labelControl3.Text = "支付方式:"; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(168, 96); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Properties.ReadOnly = true; + this.textEdit2.Size = new System.Drawing.Size(211, 20); + this.textEdit2.TabIndex = 11; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(168, 48); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Properties.ReadOnly = true; + this.textEdit1.Size = new System.Drawing.Size(211, 20); + this.textEdit1.TabIndex = 10; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(96, 99); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 9; + this.labelControl2.Text = "微信昵称:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(94, 51); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 8; + this.labelControl1.Text = "微信账号:"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(61, 89); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(87, 14); + this.labelControl5.TabIndex = 9; + this.labelControl5.Text = "支付给谁(wxid):"; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(168, 86); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(211, 20); + this.textEdit4.TabIndex = 11; + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.labelControl8); + this.groupControl2.Controls.Add(this.textEdit5); + this.groupControl2.Controls.Add(this.labelControl7); + this.groupControl2.Controls.Add(this.simpleButton1); + this.groupControl2.Controls.Add(this.radioGroup1); + this.groupControl2.Controls.Add(this.labelControl6); + this.groupControl2.Controls.Add(this.textEdit4); + this.groupControl2.Controls.Add(this.labelControl5); + this.groupControl2.Location = new System.Drawing.Point(11, 276); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(455, 210); + this.groupControl2.TabIndex = 10; + this.groupControl2.Text = "测试支付1分钱"; + // + // labelControl8 + // + this.labelControl8.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl8.Appearance.Options.UseForeColor = true; + this.labelControl8.Location = new System.Drawing.Point(307, 128); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(84, 14); + this.labelControl8.TabIndex = 20; + this.labelControl8.Text = "无验证码可忽略"; + // + // textEdit5 + // + this.textEdit5.Location = new System.Drawing.Point(168, 125); + this.textEdit5.Name = "textEdit5"; + this.textEdit5.Size = new System.Drawing.Size(119, 20); + this.textEdit5.TabIndex = 18; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(84, 128); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(64, 14); + this.labelControl7.TabIndex = 17; + this.labelControl7.Text = "收到验证码:"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(168, 163); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(130, 29); + this.simpleButton1.TabIndex = 16; + this.simpleButton1.Text = "测试支付"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // radioGroup1 + // + this.radioGroup1.EditValue = 2; + this.radioGroup1.Location = new System.Drawing.Point(168, 38); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(2, "转账"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(1, "发红包")}); + this.radioGroup1.Size = new System.Drawing.Size(211, 23); + this.radioGroup1.TabIndex = 15; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(94, 42); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(52, 14); + this.labelControl6.TabIndex = 14; + this.labelControl6.Text = "如何支付:"; + // + // set_weixin_password + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(477, 498); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.groupControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "set_weixin_password"; + this.Text = "设置微信支付密码"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.set_weixin_password_FormClosing); + this.Load += new System.EventHandler(this.set_weixin_password_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.TextEdit textEdit3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.TextEdit textEdit5; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl8; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/set_weixin_password.cs b/FLSystem/Forms/set_weixin_password.cs new file mode 100644 index 0000000..e255869 --- /dev/null +++ b/FLSystem/Forms/set_weixin_password.cs @@ -0,0 +1,154 @@ +using Api.Framework; +using Api.Framework.Model; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class set_weixin_password : BaseForm + { + public set_weixin_password(WXClientImpl_IPAD ipad) + { + InitializeComponent(); + this.ipad = ipad; + this.textEdit1.Text = ipad.User.Username; + this.textEdit2.Text = ipad.User.Nick; + } + WXClientImpl_IPAD ipad = null; + + private void set_weixin_password_Load(object sender, EventArgs e) + { + try + { + var list = ipad.FindBankCar(); + + var session = ApiClient.GetSession(); + robot = session.FindRobotInfo(ipad.WeixinHao, Api.Framework.SDK.ChatType.微信); + var entity = session.FindWeixinpassword(robot.id); + if (entity != null) + this.textEdit3.Text = entity.password; + int index = 0; + foreach (var item in list) + { + index++; + this.comboBoxEdit1.Properties.Items.Add(item); + if (entity != null && item.bank_name == entity.bank_name) + this.comboBoxEdit1.SelectedIndex = index; + } + } + catch (Exception ex) + { + ShowError(ex); + this.Close(); + } + } + + Dictionary<string, object> obj = new Dictionary<string, object>(); + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + simpleButton1.Enabled = false; + if (string.IsNullOrEmpty(this.textEdit3.Text)) throw new Exception("您尚未设置,支付密码!"); + if (string.IsNullOrEmpty(this.textEdit4.Text)) throw new Exception("您尚未填写,测试用户wxid!"); + + Task.Run(() => + { + try + { + BankCar bank = null; + if (this.comboBoxEdit1.SelectedIndex != 0) + bank = this.comboBoxEdit1.EditValue as BankCar; + + if (!string.IsNullOrEmpty(this.textEdit5.Text)) + { + if (obj.ContainsKey("reqKey")) + { + this.Invoke(new Action(() => + { + try + { + ipad.SnsVerify(this.textEdit5.Text, false, obj["reqKey"].ToString(), bank, obj["token"].ToString(), obj["pass"].ToString()); + this.textEdit5.Text = ""; + ShowSuccess("已提交,请检查是否支付成功!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex.Message); + } + })); + } + else + { + textEdit5.Text = string.Empty; + ShowSuccessAutoClose("支付异常应该已经解除,请重新再试"); + } + } + else + { + var result = ipad.SendPay(this.textEdit4.Text, "测试", 1, this.textEdit3.Text, 1, this.radioGroup1.EditValue.ToString() == "1" ? Chat.Framework.WXSdk.IPAD.PayType.红包 : Chat.Framework.WXSdk.IPAD.PayType.转账, bank, obj); + if (result == null) + { + ShowSuccessAutoClose("您的支付异常已解除!"); + return; + } + + var r = CsharpHttpHelper.HttpExtend.JsonToDictionary(result); + if (result.Contains("本次交易需要短信验证") || result.Contains("收不到验证码") || (r != null && r.ContainsKey("token") && r.ContainsKey("balance_mobile"))) + { + string token = r["token"].ToString(); + obj["token"] = token; + string phone = r["balance_mobile"].ToString(); + ShowSuccessAutoClose("向您手机“" + phone + "”已发送短信,请注意查收!"); + } + else + ShowSuccessAutoClose(result + "\r\n无法确定异常信息,请检查手机是否收到验证码!"); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + finally + { + this.Invoke(new Action(() => + { + simpleButton1.Enabled = true; + })); + } + }); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + fl_robot_info robot = null; + private void set_weixin_password_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + var session = ApiClient.GetSession(); + + var entity = session.FindWeixinpassword(robot.id); + if (entity == null) entity = new fl_weixin_password() { robot_id = robot.id }; + var bank = this.comboBoxEdit1.EditValue as BankCar; + entity.SetBank(bank); + entity.password = this.textEdit3.Text; + session.SaveOrUpdate(entity); + session.FindWeixinpasswords(true); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + } +} \ No newline at end of file diff --git a/FLSystem/Forms/set_weixin_password.resx b/FLSystem/Forms/set_weixin_password.resx new file mode 100644 index 0000000..61f5ea3 --- /dev/null +++ b/FLSystem/Forms/set_weixin_password.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>52</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/setting_endtime_form.Designer.cs b/FLSystem/Forms/setting_endtime_form.Designer.cs new file mode 100644 index 0000000..f1ae801 --- /dev/null +++ b/FLSystem/Forms/setting_endtime_form.Designer.cs @@ -0,0 +1,129 @@ +namespace FLSystem.Forms +{ + partial class setting_endtime_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Location = new System.Drawing.Point(104, 125); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(95, 29); + this.button1.TabIndex = 0; + this.button1.Text = "确 定"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Location = new System.Drawing.Point(252, 125); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(95, 29); + this.button2.TabIndex = 0; + this.button2.Text = "取 消"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Enabled = false; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(164, 37); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(200, 22); + this.dateTimePicker1.TabIndex = 1; + // + // dateTimePicker2 + // + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(164, 77); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(200, 22); + this.dateTimePicker2.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(67, 41); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(91, 14); + this.label1.TabIndex = 2; + this.label1.Text = "原来冻结日期:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(67, 81); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(91, 14); + this.label2.TabIndex = 2; + this.label2.Text = "设置冻结时间:"; + // + // setting_endtime_form + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.ClientSize = new System.Drawing.Size(440, 184); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.dateTimePicker2); + this.Controls.Add(this.dateTimePicker1); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "setting_endtime_form"; + this.Text = "设 置 冻 结 日 期 "; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/setting_endtime_form.cs b/FLSystem/Forms/setting_endtime_form.cs new file mode 100644 index 0000000..184bf9e --- /dev/null +++ b/FLSystem/Forms/setting_endtime_form.cs @@ -0,0 +1,34 @@ +using System; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class setting_endtime_form : BaseForm + { + public DateTime newtime = DateTime.MinValue; + public setting_endtime_form(DateTime endtime) + { + InitializeComponent(); + dateTimePicker1.Value = endtime; + dateTimePicker2.Value = endtime; + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + newtime = dateTimePicker2.Value; + this.Close(); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void button2_Click(object sender, EventArgs e) + { + this.Close(); + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/setting_endtime_form.resx b/FLSystem/Forms/setting_endtime_form.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/setting_endtime_form.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/setting_system_control.Designer.cs b/FLSystem/Forms/setting_system_control.Designer.cs new file mode 100644 index 0000000..4dce972 --- /dev/null +++ b/FLSystem/Forms/setting_system_control.Designer.cs @@ -0,0 +1,1769 @@ +namespace FLSystem.Forms +{ + partial class setting_system_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(setting_system_control)); + this.tabPane1 = new DevExpress.XtraBars.Navigation.TabPane(); + this.tabNavigationPage1 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contex_1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中独立分出比例ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn35 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn36 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn38 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn39 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn40 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn41 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn42 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.tabNavigationPage2 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.tabNavigationPage3 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.radioGroup2 = new DevExpress.XtraEditors.RadioGroup(); + this.tabNavigationPage4 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.label2 = new System.Windows.Forms.Label(); + this.gridControl4 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView4 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.radioGroup3 = new DevExpress.XtraEditors.RadioGroup(); + this.tabNavigationPage5 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.label1 = new System.Windows.Forms.Label(); + this.gridControl5 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView5 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.radioGroup4 = new DevExpress.XtraEditors.RadioGroup(); + this.tabNavigationPage6 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.label3 = new System.Windows.Forms.Label(); + this.gridControl6 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip3 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView6 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.tabNavigationPage7 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.label4 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl7 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip4 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加群pidToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改群信息ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中群ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.推广位删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中淘宝推广位ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中拼多多推广位ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中京东推广位ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView7 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn29 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn30 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn31 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.tbox_KeyWord = new DevExpress.XtraEditors.TextEdit(); + this.tabNavigationPage8 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.gridControl9 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip5 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem12 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView9 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn34 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn37 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridControl8 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip6 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem13 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView8 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn28 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn32 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn33 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.radioGroup5 = new DevExpress.XtraEditors.RadioGroup(); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).BeginInit(); + this.tabPane1.SuspendLayout(); + this.tabNavigationPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contex_1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.tabNavigationPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + this.tabNavigationPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup2.Properties)).BeginInit(); + this.tabNavigationPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup3.Properties)).BeginInit(); + this.tabNavigationPage5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl5)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView5)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup4.Properties)).BeginInit(); + this.tabNavigationPage6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl6)).BeginInit(); + this.contextMenuStrip3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView6)).BeginInit(); + this.tabNavigationPage7.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl7)).BeginInit(); + this.contextMenuStrip4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView7)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbox_KeyWord.Properties)).BeginInit(); + this.tabNavigationPage8.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl9)).BeginInit(); + this.contextMenuStrip5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView9)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl8)).BeginInit(); + this.contextMenuStrip6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView8)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup5.Properties)).BeginInit(); + this.SuspendLayout(); + // + // tabPane1 + // + this.tabPane1.Controls.Add(this.tabNavigationPage1); + this.tabPane1.Controls.Add(this.tabNavigationPage2); + this.tabPane1.Controls.Add(this.tabNavigationPage3); + this.tabPane1.Controls.Add(this.tabNavigationPage4); + this.tabPane1.Controls.Add(this.tabNavigationPage5); + this.tabPane1.Controls.Add(this.tabNavigationPage6); + this.tabPane1.Controls.Add(this.tabNavigationPage7); + this.tabPane1.Controls.Add(this.tabNavigationPage8); + this.tabPane1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabPane1.Location = new System.Drawing.Point(0, 0); + this.tabPane1.Name = "tabPane1"; + this.tabPane1.Pages.AddRange(new DevExpress.XtraBars.Navigation.NavigationPageBase[] { + this.tabNavigationPage1, + this.tabNavigationPage2, + this.tabNavigationPage8, + this.tabNavigationPage3, + this.tabNavigationPage4, + this.tabNavigationPage5, + this.tabNavigationPage6, + this.tabNavigationPage7}); + this.tabPane1.RegularSize = new System.Drawing.Size(803, 576); + this.tabPane1.SelectedPage = this.tabNavigationPage2; + this.tabPane1.Size = new System.Drawing.Size(803, 576); + this.tabPane1.TabIndex = 0; + this.tabPane1.SelectedPageIndexChanged += new System.EventHandler(this.tabPane1_SelectedPageIndexChanged); + // + // tabNavigationPage1 + // + this.tabNavigationPage1.Caption = "会员组设置"; + this.tabNavigationPage1.Controls.Add(this.gridControl1); + this.tabNavigationPage1.Name = "tabNavigationPage1"; + this.tabNavigationPage1.Size = new System.Drawing.Size(803, 532); + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contex_1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(803, 532); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contex_1 + // + this.contex_1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contex_1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加ToolStripMenuItem, + this.修改ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.删除选中独立分出比例ToolStripMenuItem}); + this.contex_1.Name = "contextMenuStrip1"; + this.contex_1.Size = new System.Drawing.Size(197, 114); + this.contex_1.Opening += new System.ComponentModel.CancelEventHandler(this.contex_1_Opening); + // + // 增加ToolStripMenuItem + // + this.增加ToolStripMenuItem.Name = "增加ToolStripMenuItem"; + this.增加ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.增加ToolStripMenuItem.Text = "增加"; + this.增加ToolStripMenuItem.Click += new System.EventHandler(this.增加ToolStripMenuItem_Click); + // + // 修改ToolStripMenuItem + // + this.修改ToolStripMenuItem.Name = "修改ToolStripMenuItem"; + this.修改ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.修改ToolStripMenuItem.Text = "修改"; + this.修改ToolStripMenuItem.Click += new System.EventHandler(this.修改ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // 删除选中独立分出比例ToolStripMenuItem + // + this.删除选中独立分出比例ToolStripMenuItem.Name = "删除选中独立分出比例ToolStripMenuItem"; + this.删除选中独立分出比例ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.删除选中独立分出比例ToolStripMenuItem.Text = "删除选中独立分出比例"; + this.删除选中独立分出比例ToolStripMenuItem.Click += new System.EventHandler(this.删除选中独立分出比例ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn14, + this.gridColumn1, + this.gridColumn2, + this.gridColumn15, + this.gridColumn3, + this.gridColumn4, + this.gridColumn5, + this.gridColumn35, + this.gridColumn36, + this.gridColumn38, + this.gridColumn39, + this.gridColumn40, + this.gridColumn41, + this.gridColumn42}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn14 + // + this.gridColumn14.Caption = "分组ID"; + this.gridColumn14.FieldName = "id"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 0; + this.gridColumn14.Width = 60; + // + // gridColumn1 + // + this.gridColumn1.Caption = "会员等级"; + this.gridColumn1.FieldName = "gridColumn1"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.UnboundType = DevExpress.Data.UnboundColumnType.Object; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 80; + // + // gridColumn2 + // + this.gridColumn2.Caption = "会员名称"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 120; + // + // gridColumn15 + // + this.gridColumn15.Caption = "升级条件 - 订单数"; + this.gridColumn15.FieldName = "terms_ordersum"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.OptionsColumn.AllowFocus = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 3; + this.gridColumn15.Width = 120; + // + // gridColumn3 + // + this.gridColumn3.Caption = "升级条件 - 积分数"; + this.gridColumn3.FieldName = "terms"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 4; + this.gridColumn3.Width = 120; + // + // gridColumn4 + // + this.gridColumn4.Caption = "补贴类型"; + this.gridColumn4.FieldName = "subsidy_type"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 5; + this.gridColumn4.Width = 100; + // + // gridColumn5 + // + this.gridColumn5.Caption = "增加补贴值"; + this.gridColumn5.FieldName = "subsidy"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.UnboundType = DevExpress.Data.UnboundColumnType.Object; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 6; + this.gridColumn5.Width = 100; + // + // gridColumn35 + // + this.gridColumn35.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn35.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn35.AppearanceCell.Options.UseFont = true; + this.gridColumn35.AppearanceCell.Options.UseForeColor = true; + this.gridColumn35.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn35.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn35.Caption = "淘宝独立分出比例"; + this.gridColumn35.FieldName = "ratio_custom_tb_name"; + this.gridColumn35.Name = "gridColumn35"; + this.gridColumn35.OptionsColumn.AllowEdit = false; + this.gridColumn35.Visible = true; + this.gridColumn35.VisibleIndex = 7; + this.gridColumn35.Width = 120; + // + // gridColumn36 + // + this.gridColumn36.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn36.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn36.AppearanceCell.Options.UseFont = true; + this.gridColumn36.AppearanceCell.Options.UseForeColor = true; + this.gridColumn36.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn36.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn36.Caption = "拼多多独立分出比例"; + this.gridColumn36.FieldName = "ratio_custom_pdd_name"; + this.gridColumn36.Name = "gridColumn36"; + this.gridColumn36.OptionsColumn.AllowEdit = false; + this.gridColumn36.Visible = true; + this.gridColumn36.VisibleIndex = 8; + this.gridColumn36.Width = 120; + // + // gridColumn38 + // + this.gridColumn38.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn38.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn38.AppearanceCell.Options.UseFont = true; + this.gridColumn38.AppearanceCell.Options.UseForeColor = true; + this.gridColumn38.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn38.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn38.Caption = "京东独立分出比例"; + this.gridColumn38.FieldName = "ratio_custom_jd_name"; + this.gridColumn38.Name = "gridColumn38"; + this.gridColumn38.OptionsColumn.AllowEdit = false; + this.gridColumn38.Visible = true; + this.gridColumn38.VisibleIndex = 9; + this.gridColumn38.Width = 120; + // + // gridColumn39 + // + this.gridColumn39.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn39.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn39.AppearanceCell.Options.UseFont = true; + this.gridColumn39.AppearanceCell.Options.UseForeColor = true; + this.gridColumn39.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn39.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn39.Caption = "唯品会独立分出比例"; + this.gridColumn39.FieldName = "ratio_custom_wph_name"; + this.gridColumn39.Name = "gridColumn39"; + this.gridColumn39.OptionsColumn.AllowEdit = false; + this.gridColumn39.Visible = true; + this.gridColumn39.VisibleIndex = 10; + this.gridColumn39.Width = 120; + // + // gridColumn40 + // + this.gridColumn40.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn40.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn40.AppearanceCell.Options.UseFont = true; + this.gridColumn40.AppearanceCell.Options.UseForeColor = true; + this.gridColumn40.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn40.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn40.Caption = "抖音独立分出比例"; + this.gridColumn40.FieldName = "ratio_custom_dy_name"; + this.gridColumn40.Name = "gridColumn40"; + this.gridColumn40.OptionsColumn.AllowEdit = false; + this.gridColumn40.Visible = true; + this.gridColumn40.VisibleIndex = 11; + this.gridColumn40.Width = 120; + // + // gridColumn41 + // + this.gridColumn41.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn41.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn41.AppearanceCell.Options.UseFont = true; + this.gridColumn41.AppearanceCell.Options.UseForeColor = true; + this.gridColumn41.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn41.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn41.Caption = "苏宁独立分出比例"; + this.gridColumn41.FieldName = "ratio_custom_sn_name"; + this.gridColumn41.Name = "gridColumn41"; + this.gridColumn41.OptionsColumn.AllowEdit = false; + this.gridColumn41.Visible = true; + this.gridColumn41.VisibleIndex = 12; + this.gridColumn41.Width = 120; + // + // gridColumn42 + // + this.gridColumn42.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn42.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn42.AppearanceCell.Options.UseFont = true; + this.gridColumn42.AppearanceCell.Options.UseForeColor = true; + this.gridColumn42.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn42.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn42.Caption = "快手独立分出比例"; + this.gridColumn42.FieldName = "ratio_custom_ks_name"; + this.gridColumn42.Name = "gridColumn42"; + this.gridColumn42.OptionsColumn.AllowEdit = false; + this.gridColumn42.Visible = true; + this.gridColumn42.VisibleIndex = 13; + this.gridColumn42.Width = 120; + // + // tabNavigationPage2 + // + this.tabNavigationPage2.Caption = "公共分出比例设置"; + this.tabNavigationPage2.Controls.Add(this.gridControl2); + this.tabNavigationPage2.Controls.Add(this.radioGroup1); + this.tabNavigationPage2.Name = "tabNavigationPage2"; + this.tabNavigationPage2.Size = new System.Drawing.Size(803, 532); + // + // gridControl2 + // + this.gridControl2.ContextMenuStrip = this.contex_1; + this.gridControl2.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl2.Location = new System.Drawing.Point(0, 23); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(803, 509); + this.gridControl2.TabIndex = 1; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn7, + this.gridColumn8, + this.gridColumn9, + this.gridColumn10}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsView.ColumnAutoWidth = false; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn7.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "总佣金低于"; + this.gridColumn7.FieldName = "comm"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 0; + this.gridColumn7.Width = 230; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn8.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "分出数额"; + this.gridColumn8.FieldName = "subsidy_num"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 1; + this.gridColumn8.Width = 276; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn9.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "分出类型"; + this.gridColumn9.FieldName = "subsidy_type"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.OptionsColumn.AllowFocus = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 2; + this.gridColumn9.Width = 225; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn10.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "联盟平台"; + this.gridColumn10.FieldName = "cps_type"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 3; + this.gridColumn10.Width = 200; + // + // radioGroup1 + // + this.radioGroup1.Dock = System.Windows.Forms.DockStyle.Top; + this.radioGroup1.EditValue = 2; + this.radioGroup1.Location = new System.Drawing.Point(0, 0); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(2, "多多进宝"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(1, "阿里妈妈"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(3, "京东联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(4, "唯品联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(5, "抖音联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(6, "苏宁易购"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(7, "快手联盟")}); + this.radioGroup1.Size = new System.Drawing.Size(803, 23); + this.radioGroup1.TabIndex = 0; + this.radioGroup1.SelectedIndexChanged += new System.EventHandler(this.tabPane1_SelectedPageIndexChanged); + // + // tabNavigationPage3 + // + this.tabNavigationPage3.Caption = "延迟结算(防套现)"; + this.tabNavigationPage3.Controls.Add(this.gridControl3); + this.tabNavigationPage3.Controls.Add(this.radioGroup2); + this.tabNavigationPage3.Name = "tabNavigationPage3"; + this.tabNavigationPage3.Size = new System.Drawing.Size(803, 532); + // + // gridControl3 + // + this.gridControl3.ContextMenuStrip = this.contex_1; + this.gridControl3.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl3.Location = new System.Drawing.Point(0, 23); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.Size = new System.Drawing.Size(803, 509); + this.gridControl3.TabIndex = 2; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // gridView3 + // + this.gridView3.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView3.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Appearance.Row.Options.UseTextOptions = true; + this.gridView3.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn6, + this.gridColumn11, + this.gridColumn12, + this.gridColumn13}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsBehavior.ReadOnly = true; + this.gridView3.OptionsView.ShowGroupPanel = false; + // + // gridColumn6 + // + this.gridColumn6.Caption = "佣金低于"; + this.gridColumn6.FieldName = "money"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 0; + // + // gridColumn11 + // + this.gridColumn11.Caption = "结算延迟(小时)"; + this.gridColumn11.FieldName = "sleep"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.OptionsColumn.AllowFocus = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 1; + // + // gridColumn12 + // + this.gridColumn12.Caption = "不受限会员组"; + this.gridColumn12.FieldName = "white_groups"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 2; + // + // gridColumn13 + // + this.gridColumn13.Caption = "联盟类型"; + this.gridColumn13.FieldName = "cps_type"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 3; + // + // radioGroup2 + // + this.radioGroup2.Dock = System.Windows.Forms.DockStyle.Top; + this.radioGroup2.EditValue = 2; + this.radioGroup2.Location = new System.Drawing.Point(0, 0); + this.radioGroup2.Name = "radioGroup2"; + this.radioGroup2.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup2.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup2.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup2.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(2, "多多进宝"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(1, "阿里妈妈"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(3, "京东联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(4, "唯品联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(5, "抖音联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(6, "苏宁易购"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(7, "快手联盟")}); + this.radioGroup2.Size = new System.Drawing.Size(803, 23); + this.radioGroup2.TabIndex = 1; + this.radioGroup2.SelectedIndexChanged += new System.EventHandler(this.tabPane1_SelectedPageIndexChanged); + // + // tabNavigationPage4 + // + this.tabNavigationPage4.Caption = "推广位组设置"; + this.tabNavigationPage4.Controls.Add(this.label2); + this.tabNavigationPage4.Controls.Add(this.gridControl4); + this.tabNavigationPage4.Controls.Add(this.radioGroup3); + this.tabNavigationPage4.Name = "tabNavigationPage4"; + this.tabNavigationPage4.Size = new System.Drawing.Size(803, 547); + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(217, 157); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(393, 35); + this.label2.TabIndex = 15; + this.label2.Text = "推广位组为空,右击添加"; + // + // gridControl4 + // + this.gridControl4.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl4.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl4.Location = new System.Drawing.Point(0, 23); + this.gridControl4.MainView = this.gridView4; + this.gridControl4.Name = "gridControl4"; + this.gridControl4.Size = new System.Drawing.Size(803, 524); + this.gridControl4.TabIndex = 4; + this.gridControl4.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView4}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1, + this.toolStripMenuItem2, + this.toolStripMenuItem3}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(101, 70); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem1.Text = "增加"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click); + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem2.Text = "修改"; + this.toolStripMenuItem2.Click += new System.EventHandler(this.toolStripMenuItem2_Click); + // + // toolStripMenuItem3 + // + this.toolStripMenuItem3.Name = "toolStripMenuItem3"; + this.toolStripMenuItem3.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem3.Text = "删除"; + this.toolStripMenuItem3.Click += new System.EventHandler(this.toolStripMenuItem3_Click); + // + // gridView4 + // + this.gridView4.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView4.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView4.Appearance.Row.Options.UseTextOptions = true; + this.gridView4.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView4.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn16, + this.gridColumn17, + this.gridColumn19}); + this.gridView4.GridControl = this.gridControl4; + this.gridView4.Name = "gridView4"; + this.gridView4.OptionsBehavior.ReadOnly = true; + this.gridView4.OptionsView.ShowGroupPanel = false; + // + // gridColumn16 + // + this.gridColumn16.Caption = "组名称"; + this.gridColumn16.FieldName = "name"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.OptionsColumn.AllowEdit = false; + this.gridColumn16.OptionsColumn.AllowFocus = false; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 0; + this.gridColumn16.Width = 186; + // + // gridColumn17 + // + this.gridColumn17.Caption = "阿里账号集"; + this.gridColumn17.FieldName = "adzones"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.OptionsColumn.AllowFocus = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 1; + this.gridColumn17.Width = 402; + // + // gridColumn19 + // + this.gridColumn19.Caption = "联盟类型"; + this.gridColumn19.FieldName = "cps_type"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.OptionsColumn.AllowFocus = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 2; + this.gridColumn19.Width = 197; + // + // radioGroup3 + // + this.radioGroup3.Dock = System.Windows.Forms.DockStyle.Top; + this.radioGroup3.EditValue = 1; + this.radioGroup3.Location = new System.Drawing.Point(0, 0); + this.radioGroup3.Name = "radioGroup3"; + this.radioGroup3.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup3.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup3.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup3.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(1, "阿里妈妈")}); + this.radioGroup3.Size = new System.Drawing.Size(803, 23); + this.radioGroup3.TabIndex = 3; + this.radioGroup3.SelectedIndexChanged += new System.EventHandler(this.radioGroup3_SelectedIndexChanged); + // + // tabNavigationPage5 + // + this.tabNavigationPage5.Caption = "强制返利推广组设置"; + this.tabNavigationPage5.Controls.Add(this.label1); + this.tabNavigationPage5.Controls.Add(this.gridControl5); + this.tabNavigationPage5.Controls.Add(this.radioGroup4); + this.tabNavigationPage5.Name = "tabNavigationPage5"; + this.tabNavigationPage5.Size = new System.Drawing.Size(803, 547); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(217, 157); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(393, 35); + this.label1.TabIndex = 16; + this.label1.Text = "推广位组为空,右击添加"; + // + // gridControl5 + // + this.gridControl5.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl5.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl5.Location = new System.Drawing.Point(0, 23); + this.gridControl5.MainView = this.gridView5; + this.gridControl5.Name = "gridControl5"; + this.gridControl5.Size = new System.Drawing.Size(803, 524); + this.gridControl5.TabIndex = 6; + this.gridControl5.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView5}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem4, + this.toolStripMenuItem5, + this.toolStripMenuItem6}); + this.contextMenuStrip2.Name = "contextMenuStrip1"; + this.contextMenuStrip2.Size = new System.Drawing.Size(101, 70); + // + // toolStripMenuItem4 + // + this.toolStripMenuItem4.Name = "toolStripMenuItem4"; + this.toolStripMenuItem4.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem4.Text = "增加"; + this.toolStripMenuItem4.Click += new System.EventHandler(this.toolStripMenuItem4_Click); + // + // toolStripMenuItem5 + // + this.toolStripMenuItem5.Name = "toolStripMenuItem5"; + this.toolStripMenuItem5.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem5.Text = "修改"; + this.toolStripMenuItem5.Click += new System.EventHandler(this.toolStripMenuItem5_Click); + // + // toolStripMenuItem6 + // + this.toolStripMenuItem6.Name = "toolStripMenuItem6"; + this.toolStripMenuItem6.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem6.Text = "删除"; + this.toolStripMenuItem6.Click += new System.EventHandler(this.toolStripMenuItem6_Click); + // + // gridView5 + // + this.gridView5.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView5.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView5.Appearance.Row.Options.UseTextOptions = true; + this.gridView5.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView5.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn18, + this.gridColumn20, + this.gridColumn21}); + this.gridView5.GridControl = this.gridControl5; + this.gridView5.Name = "gridView5"; + this.gridView5.OptionsBehavior.ReadOnly = true; + this.gridView5.OptionsView.ShowGroupPanel = false; + // + // gridColumn18 + // + this.gridColumn18.Caption = "组名称"; + this.gridColumn18.FieldName = "name"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.OptionsColumn.AllowEdit = false; + this.gridColumn18.OptionsColumn.AllowFocus = false; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 0; + this.gridColumn18.Width = 186; + // + // gridColumn20 + // + this.gridColumn20.Caption = "阿里账号集"; + this.gridColumn20.FieldName = "adzones"; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.OptionsColumn.AllowFocus = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 1; + this.gridColumn20.Width = 402; + // + // gridColumn21 + // + this.gridColumn21.Caption = "联盟类型"; + this.gridColumn21.FieldName = "cps_type"; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.OptionsColumn.AllowFocus = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 2; + this.gridColumn21.Width = 197; + // + // radioGroup4 + // + this.radioGroup4.Dock = System.Windows.Forms.DockStyle.Top; + this.radioGroup4.EditValue = 1; + this.radioGroup4.Location = new System.Drawing.Point(0, 0); + this.radioGroup4.Name = "radioGroup4"; + this.radioGroup4.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup4.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup4.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup4.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(1, "阿里妈妈")}); + this.radioGroup4.Size = new System.Drawing.Size(803, 23); + this.radioGroup4.TabIndex = 5; + // + // tabNavigationPage6 + // + this.tabNavigationPage6.Caption = "自定义全局变量"; + this.tabNavigationPage6.Controls.Add(this.label3); + this.tabNavigationPage6.Controls.Add(this.gridControl6); + this.tabNavigationPage6.Name = "tabNavigationPage6"; + this.tabNavigationPage6.Size = new System.Drawing.Size(803, 547); + // + // label3 + // + this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label3.AutoSize = true; + this.label3.BackColor = System.Drawing.Color.White; + this.label3.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.Location = new System.Drawing.Point(151, 157); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(501, 35); + this.label3.TabIndex = 17; + this.label3.Text = "自定义全局变量为空,右击添加"; + // + // gridControl6 + // + this.gridControl6.ContextMenuStrip = this.contextMenuStrip3; + this.gridControl6.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl6.Location = new System.Drawing.Point(0, 0); + this.gridControl6.MainView = this.gridView6; + this.gridControl6.Name = "gridControl6"; + this.gridControl6.Size = new System.Drawing.Size(803, 547); + this.gridControl6.TabIndex = 1; + this.gridControl6.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView6}); + // + // contextMenuStrip3 + // + this.contextMenuStrip3.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip3.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem7, + this.toolStripMenuItem8, + this.toolStripMenuItem9}); + this.contextMenuStrip3.Name = "contextMenuStrip1"; + this.contextMenuStrip3.Size = new System.Drawing.Size(101, 70); + // + // toolStripMenuItem7 + // + this.toolStripMenuItem7.Name = "toolStripMenuItem7"; + this.toolStripMenuItem7.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem7.Text = "增加"; + this.toolStripMenuItem7.Click += new System.EventHandler(this.toolStripMenuItem7_Click); + // + // toolStripMenuItem8 + // + this.toolStripMenuItem8.Name = "toolStripMenuItem8"; + this.toolStripMenuItem8.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem8.Text = "修改"; + this.toolStripMenuItem8.Click += new System.EventHandler(this.toolStripMenuItem8_Click); + // + // toolStripMenuItem9 + // + this.toolStripMenuItem9.Name = "toolStripMenuItem9"; + this.toolStripMenuItem9.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem9.Text = "删除"; + this.toolStripMenuItem9.Click += new System.EventHandler(this.toolStripMenuItem9_Click); + // + // gridView6 + // + this.gridView6.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView6.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView6.Appearance.Row.Options.UseTextOptions = true; + this.gridView6.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView6.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn22, + this.gridColumn23, + this.gridColumn24}); + this.gridView6.GridControl = this.gridControl6; + this.gridView6.Name = "gridView6"; + this.gridView6.OptionsBehavior.ReadOnly = true; + this.gridView6.OptionsView.ShowGroupPanel = false; + // + // gridColumn22 + // + this.gridColumn22.Caption = "编码"; + this.gridColumn22.FieldName = "id"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.OptionsColumn.AllowEdit = false; + this.gridColumn22.OptionsColumn.AllowFocus = false; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 0; + this.gridColumn22.Width = 97; + // + // gridColumn23 + // + this.gridColumn23.Caption = "变量"; + this.gridColumn23.FieldName = "variate"; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.OptionsColumn.AllowEdit = false; + this.gridColumn23.OptionsColumn.AllowFocus = false; + this.gridColumn23.UnboundType = DevExpress.Data.UnboundColumnType.Object; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 1; + this.gridColumn23.Width = 129; + // + // gridColumn24 + // + this.gridColumn24.Caption = "内容"; + this.gridColumn24.FieldName = "data"; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + this.gridColumn24.OptionsColumn.AllowFocus = false; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 2; + this.gridColumn24.Width = 556; + // + // tabNavigationPage7 + // + this.tabNavigationPage7.Caption = "群推广位设置"; + this.tabNavigationPage7.Controls.Add(this.label4); + this.tabNavigationPage7.Controls.Add(this.pageControl1); + this.tabNavigationPage7.Controls.Add(this.gridControl7); + this.tabNavigationPage7.Controls.Add(this.groupControl1); + this.tabNavigationPage7.Name = "tabNavigationPage7"; + this.tabNavigationPage7.Size = new System.Drawing.Size(803, 547); + // + // label4 + // + this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label4.AutoSize = true; + this.label4.BackColor = System.Drawing.Color.White; + this.label4.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label4.Location = new System.Drawing.Point(205, 191); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(393, 35); + this.label4.TabIndex = 41; + this.label4.Text = "群推广位为空,右击添加"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 514); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(803, 33); + this.pageControl1.TabIndex = 39; + // + // gridControl7 + // + this.gridControl7.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl7.ContextMenuStrip = this.contextMenuStrip4; + this.gridControl7.Location = new System.Drawing.Point(3, 83); + this.gridControl7.MainView = this.gridView7; + this.gridControl7.Name = "gridControl7"; + this.gridControl7.Size = new System.Drawing.Size(800, 425); + this.gridControl7.TabIndex = 38; + this.gridControl7.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView7}); + // + // contextMenuStrip4 + // + this.contextMenuStrip4.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip4.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加群pidToolStripMenuItem, + this.修改群信息ToolStripMenuItem, + this.删除选中群ToolStripMenuItem, + this.推广位删除ToolStripMenuItem}); + this.contextMenuStrip4.Name = "contextMenuStrip1"; + this.contextMenuStrip4.Size = new System.Drawing.Size(161, 92); + this.contextMenuStrip4.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip4_Opening); + // + // 增加群pidToolStripMenuItem + // + this.增加群pidToolStripMenuItem.Name = "增加群pidToolStripMenuItem"; + this.增加群pidToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.增加群pidToolStripMenuItem.Text = "增加群信息"; + this.增加群pidToolStripMenuItem.Click += new System.EventHandler(this.增加群pidToolStripMenuItem_Click); + // + // 修改群信息ToolStripMenuItem + // + this.修改群信息ToolStripMenuItem.Name = "修改群信息ToolStripMenuItem"; + this.修改群信息ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.修改群信息ToolStripMenuItem.Text = "修改群信息"; + this.修改群信息ToolStripMenuItem.Click += new System.EventHandler(this.修改群信息ToolStripMenuItem_Click); + // + // 删除选中群ToolStripMenuItem + // + this.删除选中群ToolStripMenuItem.Name = "删除选中群ToolStripMenuItem"; + this.删除选中群ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.删除选中群ToolStripMenuItem.Text = "删除选中群信息"; + this.删除选中群ToolStripMenuItem.Click += new System.EventHandler(this.删除选中群ToolStripMenuItem_Click); + // + // 推广位删除ToolStripMenuItem + // + this.推广位删除ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中淘宝推广位ToolStripMenuItem1, + this.删除选中拼多多推广位ToolStripMenuItem1, + this.删除选中京东推广位ToolStripMenuItem1}); + this.推广位删除ToolStripMenuItem.Name = "推广位删除ToolStripMenuItem"; + this.推广位删除ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.推广位删除ToolStripMenuItem.Text = "推广位删除"; + // + // 删除选中淘宝推广位ToolStripMenuItem1 + // + this.删除选中淘宝推广位ToolStripMenuItem1.Name = "删除选中淘宝推广位ToolStripMenuItem1"; + this.删除选中淘宝推广位ToolStripMenuItem1.Size = new System.Drawing.Size(196, 22); + this.删除选中淘宝推广位ToolStripMenuItem1.Text = "删除选中淘宝推广位"; + this.删除选中淘宝推广位ToolStripMenuItem1.Click += new System.EventHandler(this.删除选中推广位ToolStripMenuItem1_Click); + // + // 删除选中拼多多推广位ToolStripMenuItem1 + // + this.删除选中拼多多推广位ToolStripMenuItem1.Name = "删除选中拼多多推广位ToolStripMenuItem1"; + this.删除选中拼多多推广位ToolStripMenuItem1.Size = new System.Drawing.Size(196, 22); + this.删除选中拼多多推广位ToolStripMenuItem1.Text = "删除选中拼多多推广位"; + this.删除选中拼多多推广位ToolStripMenuItem1.Click += new System.EventHandler(this.删除选中推广位ToolStripMenuItem1_Click); + // + // 删除选中京东推广位ToolStripMenuItem1 + // + this.删除选中京东推广位ToolStripMenuItem1.Name = "删除选中京东推广位ToolStripMenuItem1"; + this.删除选中京东推广位ToolStripMenuItem1.Size = new System.Drawing.Size(196, 22); + this.删除选中京东推广位ToolStripMenuItem1.Text = "删除选中京东推广位"; + this.删除选中京东推广位ToolStripMenuItem1.Click += new System.EventHandler(this.删除选中推广位ToolStripMenuItem1_Click); + // + // gridView7 + // + this.gridView7.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView7.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView7.Appearance.Row.Options.UseTextOptions = true; + this.gridView7.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView7.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView7.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView7.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn27, + this.gridColumn25, + this.gridColumn29, + this.gridColumn30, + this.gridColumn31}); + this.gridView7.GridControl = this.gridControl7; + this.gridView7.IndicatorWidth = 50; + this.gridView7.Name = "gridView7"; + this.gridView7.OptionsView.ColumnAutoWidth = false; + this.gridView7.OptionsView.ShowGroupPanel = false; + this.gridView7.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView7_RowCellClick); + this.gridView7.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView7_CustomColumnDisplayText); + // + // gridColumn27 + // + this.gridColumn27.Caption = "群账号"; + this.gridColumn27.FieldName = "groupid"; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.OptionsColumn.AllowEdit = false; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 0; + this.gridColumn27.Width = 159; + // + // gridColumn25 + // + this.gridColumn25.Caption = "群昵称"; + this.gridColumn25.FieldName = "extend"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 1; + this.gridColumn25.Width = 142; + // + // gridColumn29 + // + this.gridColumn29.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn29.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn29.AppearanceCell.Options.UseFont = true; + this.gridColumn29.AppearanceCell.Options.UseForeColor = true; + this.gridColumn29.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn29.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn29.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.Caption = "淘宝推广位名称"; + this.gridColumn29.FieldName = "tb_pid_name"; + this.gridColumn29.Name = "gridColumn29"; + this.gridColumn29.OptionsColumn.AllowEdit = false; + this.gridColumn29.Visible = true; + this.gridColumn29.VisibleIndex = 2; + this.gridColumn29.Width = 147; + // + // gridColumn30 + // + this.gridColumn30.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn30.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn30.AppearanceCell.Options.UseFont = true; + this.gridColumn30.AppearanceCell.Options.UseForeColor = true; + this.gridColumn30.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn30.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn30.Caption = "拼多多推广位名称"; + this.gridColumn30.FieldName = "pdd_pid_name"; + this.gridColumn30.Name = "gridColumn30"; + this.gridColumn30.OptionsColumn.AllowEdit = false; + this.gridColumn30.Visible = true; + this.gridColumn30.VisibleIndex = 3; + this.gridColumn30.Width = 134; + // + // gridColumn31 + // + this.gridColumn31.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn31.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn31.AppearanceCell.Options.UseFont = true; + this.gridColumn31.AppearanceCell.Options.UseForeColor = true; + this.gridColumn31.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn31.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn31.Caption = "京东推广位名称"; + this.gridColumn31.FieldName = "jd_pid_name"; + this.gridColumn31.Name = "gridColumn31"; + this.gridColumn31.OptionsColumn.AllowEdit = false; + this.gridColumn31.Visible = true; + this.gridColumn31.VisibleIndex = 4; + this.gridColumn31.Width = 162; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.simpleButton2); + this.groupControl1.Controls.Add(this.tbox_KeyWord); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl1.Location = new System.Drawing.Point(0, 0); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(803, 77); + this.groupControl1.TabIndex = 37; + this.groupControl1.Text = "搜索条件"; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(156, 43); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 9; + this.labelControl1.Text = "搜索条件:"; + // + // simpleButton2 + // + this.simpleButton2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(547, 37); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(99, 26); + this.simpleButton2.TabIndex = 8; + this.simpleButton2.Text = "搜索"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // tbox_KeyWord + // + this.tbox_KeyWord.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.tbox_KeyWord.Location = new System.Drawing.Point(215, 40); + this.tbox_KeyWord.Name = "tbox_KeyWord"; + this.tbox_KeyWord.Size = new System.Drawing.Size(297, 20); + this.tbox_KeyWord.TabIndex = 7; + // + // tabNavigationPage8 + // + this.tabNavigationPage8.Caption = "独立分出比例设置"; + this.tabNavigationPage8.Controls.Add(this.label5); + this.tabNavigationPage8.Controls.Add(this.label6); + this.tabNavigationPage8.Controls.Add(this.gridControl9); + this.tabNavigationPage8.Controls.Add(this.gridControl8); + this.tabNavigationPage8.Controls.Add(this.radioGroup5); + this.tabNavigationPage8.Name = "tabNavigationPage8"; + this.tabNavigationPage8.Size = new System.Drawing.Size(803, 532); + // + // label5 + // + this.label5.BackColor = System.Drawing.Color.White; + this.label5.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label5.ForeColor = System.Drawing.Color.Red; + this.label5.Location = new System.Drawing.Point(259, 177); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(512, 33); + this.label5.TabIndex = 5; + this.label5.Text = "②右击添加独立分出比例规则"; + this.label5.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label5.Visible = false; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(27, 177); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(179, 33); + this.label6.TabIndex = 5; + this.label6.Text = "①右击添加分组名称"; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // gridControl9 + // + this.gridControl9.ContextMenuStrip = this.contextMenuStrip5; + this.gridControl9.Dock = System.Windows.Forms.DockStyle.Left; + this.gridControl9.Location = new System.Drawing.Point(0, 23); + this.gridControl9.MainView = this.gridView9; + this.gridControl9.Name = "gridControl9"; + this.gridControl9.Size = new System.Drawing.Size(226, 509); + this.gridControl9.TabIndex = 3; + this.gridControl9.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView9}); + this.gridControl9.Click += new System.EventHandler(this.gridControl9_Click); + // + // contextMenuStrip5 + // + this.contextMenuStrip5.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip5.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem10, + this.toolStripMenuItem11, + this.toolStripMenuItem12}); + this.contextMenuStrip5.Name = "contextMenuStrip1"; + this.contextMenuStrip5.Size = new System.Drawing.Size(101, 70); + // + // toolStripMenuItem10 + // + this.toolStripMenuItem10.Name = "toolStripMenuItem10"; + this.toolStripMenuItem10.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem10.Text = "增加"; + this.toolStripMenuItem10.Click += new System.EventHandler(this.toolStripMenuItem10_Click_1); + // + // toolStripMenuItem11 + // + this.toolStripMenuItem11.Name = "toolStripMenuItem11"; + this.toolStripMenuItem11.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem11.Text = "修改"; + this.toolStripMenuItem11.Click += new System.EventHandler(this.toolStripMenuItem11_Click); + // + // toolStripMenuItem12 + // + this.toolStripMenuItem12.Name = "toolStripMenuItem12"; + this.toolStripMenuItem12.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem12.Text = "删除"; + this.toolStripMenuItem12.Click += new System.EventHandler(this.toolStripMenuItem12_Click); + // + // gridView9 + // + this.gridView9.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView9.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView9.Appearance.Row.Options.UseTextOptions = true; + this.gridView9.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView9.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn34, + this.gridColumn37}); + this.gridView9.GridControl = this.gridControl9; + this.gridView9.Name = "gridView9"; + this.gridView9.OptionsBehavior.ReadOnly = true; + this.gridView9.OptionsView.ShowGroupPanel = false; + // + // gridColumn34 + // + this.gridColumn34.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn34.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn34.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn34.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn34.Caption = "分组名称"; + this.gridColumn34.FieldName = "name"; + this.gridColumn34.Name = "gridColumn34"; + this.gridColumn34.OptionsColumn.AllowEdit = false; + this.gridColumn34.OptionsColumn.AllowFocus = false; + this.gridColumn34.Visible = true; + this.gridColumn34.VisibleIndex = 0; + this.gridColumn34.Width = 100; + // + // gridColumn37 + // + this.gridColumn37.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn37.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn37.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn37.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn37.Caption = "联盟平台"; + this.gridColumn37.FieldName = "cps_type"; + this.gridColumn37.Name = "gridColumn37"; + this.gridColumn37.OptionsColumn.AllowEdit = false; + this.gridColumn37.OptionsColumn.AllowFocus = false; + this.gridColumn37.Visible = true; + this.gridColumn37.VisibleIndex = 1; + this.gridColumn37.Width = 100; + // + // gridControl8 + // + this.gridControl8.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl8.ContextMenuStrip = this.contextMenuStrip6; + this.gridControl8.Location = new System.Drawing.Point(232, 23); + this.gridControl8.MainView = this.gridView8; + this.gridControl8.Name = "gridControl8"; + this.gridControl8.Size = new System.Drawing.Size(571, 509); + this.gridControl8.TabIndex = 2; + this.gridControl8.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView8}); + // + // contextMenuStrip6 + // + this.contextMenuStrip6.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip6.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem13, + this.toolStripMenuItem14, + this.toolStripMenuItem15}); + this.contextMenuStrip6.Name = "contextMenuStrip1"; + this.contextMenuStrip6.Size = new System.Drawing.Size(101, 70); + // + // toolStripMenuItem13 + // + this.toolStripMenuItem13.Name = "toolStripMenuItem13"; + this.toolStripMenuItem13.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem13.Text = "增加"; + this.toolStripMenuItem13.Click += new System.EventHandler(this.toolStripMenuItem13_Click); + // + // toolStripMenuItem14 + // + this.toolStripMenuItem14.Name = "toolStripMenuItem14"; + this.toolStripMenuItem14.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem14.Text = "修改"; + this.toolStripMenuItem14.Click += new System.EventHandler(this.toolStripMenuItem14_Click); + // + // toolStripMenuItem15 + // + this.toolStripMenuItem15.Name = "toolStripMenuItem15"; + this.toolStripMenuItem15.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem15.Text = "删除"; + this.toolStripMenuItem15.Click += new System.EventHandler(this.toolStripMenuItem15_Click); + // + // gridView8 + // + this.gridView8.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView8.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView8.Appearance.Row.Options.UseTextOptions = true; + this.gridView8.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView8.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn26, + this.gridColumn28, + this.gridColumn32, + this.gridColumn33}); + this.gridView8.GridControl = this.gridControl8; + this.gridView8.Name = "gridView8"; + this.gridView8.OptionsBehavior.ReadOnly = true; + this.gridView8.OptionsView.ShowGroupPanel = false; + // + // gridColumn26 + // + this.gridColumn26.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn26.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn26.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn26.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn26.Caption = "总佣金低于"; + this.gridColumn26.FieldName = "comm"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.OptionsColumn.AllowEdit = false; + this.gridColumn26.OptionsColumn.AllowFocus = false; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 0; + this.gridColumn26.Width = 120; + // + // gridColumn28 + // + this.gridColumn28.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn28.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn28.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn28.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn28.Caption = "分出数额"; + this.gridColumn28.FieldName = "subsidy_num"; + this.gridColumn28.Name = "gridColumn28"; + this.gridColumn28.OptionsColumn.AllowEdit = false; + this.gridColumn28.OptionsColumn.AllowFocus = false; + this.gridColumn28.Visible = true; + this.gridColumn28.VisibleIndex = 1; + this.gridColumn28.Width = 132; + // + // gridColumn32 + // + this.gridColumn32.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn32.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn32.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn32.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn32.Caption = "分出类型"; + this.gridColumn32.FieldName = "subsidy_type"; + this.gridColumn32.Name = "gridColumn32"; + this.gridColumn32.OptionsColumn.AllowEdit = false; + this.gridColumn32.OptionsColumn.AllowFocus = false; + this.gridColumn32.Visible = true; + this.gridColumn32.VisibleIndex = 2; + this.gridColumn32.Width = 150; + // + // gridColumn33 + // + this.gridColumn33.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn33.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn33.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.Caption = "联盟平台"; + this.gridColumn33.FieldName = "cps_type"; + this.gridColumn33.Name = "gridColumn33"; + this.gridColumn33.OptionsColumn.AllowEdit = false; + this.gridColumn33.OptionsColumn.AllowFocus = false; + this.gridColumn33.Visible = true; + this.gridColumn33.VisibleIndex = 3; + this.gridColumn33.Width = 130; + // + // radioGroup5 + // + this.radioGroup5.Dock = System.Windows.Forms.DockStyle.Top; + this.radioGroup5.EditValue = 2; + this.radioGroup5.Location = new System.Drawing.Point(0, 0); + this.radioGroup5.Name = "radioGroup5"; + this.radioGroup5.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup5.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup5.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup5.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(2, "多多进宝"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(1, "阿里妈妈"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(3, "京东联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(4, "唯品联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(5, "抖音联盟"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(6, "苏宁易购"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(7, "快手联盟")}); + this.radioGroup5.Size = new System.Drawing.Size(803, 23); + this.radioGroup5.TabIndex = 1; + this.radioGroup5.SelectedIndexChanged += new System.EventHandler(this.radioGroup5_SelectedIndexChanged); + // + // setting_system_control + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.tabPane1); + this.Name = "setting_system_control"; + this.Size = new System.Drawing.Size(803, 576); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).EndInit(); + this.tabPane1.ResumeLayout(false); + this.tabNavigationPage1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contex_1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.tabNavigationPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + this.tabNavigationPage3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup2.Properties)).EndInit(); + this.tabNavigationPage4.ResumeLayout(false); + this.tabNavigationPage4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup3.Properties)).EndInit(); + this.tabNavigationPage5.ResumeLayout(false); + this.tabNavigationPage5.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl5)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView5)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup4.Properties)).EndInit(); + this.tabNavigationPage6.ResumeLayout(false); + this.tabNavigationPage6.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl6)).EndInit(); + this.contextMenuStrip3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView6)).EndInit(); + this.tabNavigationPage7.ResumeLayout(false); + this.tabNavigationPage7.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl7)).EndInit(); + this.contextMenuStrip4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView7)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbox_KeyWord.Properties)).EndInit(); + this.tabNavigationPage8.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl9)).EndInit(); + this.contextMenuStrip5.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView9)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl8)).EndInit(); + this.contextMenuStrip6.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView8)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup5.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraBars.Navigation.TabPane tabPane1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage2; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage3; + private System.Windows.Forms.ContextMenuStrip contex_1; + private System.Windows.Forms.ToolStripMenuItem 修改ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + private System.Windows.Forms.ToolStripMenuItem 增加ToolStripMenuItem; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraEditors.RadioGroup radioGroup2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage4; + private DevExpress.XtraGrid.GridControl gridControl4; + private DevExpress.XtraGrid.Views.Grid.GridView gridView4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraEditors.RadioGroup radioGroup3; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem3; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage5; + private DevExpress.XtraGrid.GridControl gridControl5; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem4; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem5; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem6; + private DevExpress.XtraGrid.Views.Grid.GridView gridView5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraEditors.RadioGroup radioGroup4; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage6; + private DevExpress.XtraGrid.GridControl gridControl6; + private DevExpress.XtraGrid.Views.Grid.GridView gridView6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip3; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem7; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem8; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem9; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label3; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage7; + private DevExpress.XtraEditors.GroupControl groupControl1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl7; + private DevExpress.XtraGrid.Views.Grid.GridView gridView7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn29; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn30; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn31; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip4; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.TextEdit tbox_KeyWord; + private System.Windows.Forms.ToolStripMenuItem 增加群pidToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改群信息ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中群ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 推广位删除ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中淘宝推广位ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 删除选中拼多多推广位ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 删除选中京东推广位ToolStripMenuItem1; + private System.Windows.Forms.Label label4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage8; + private DevExpress.XtraGrid.GridControl gridControl8; + private DevExpress.XtraGrid.Views.Grid.GridView gridView8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn28; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn32; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn33; + private DevExpress.XtraEditors.RadioGroup radioGroup5; + private DevExpress.XtraGrid.GridControl gridControl9; + private DevExpress.XtraGrid.Views.Grid.GridView gridView9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn34; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn37; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip5; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem10; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem11; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem12; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip6; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem13; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem14; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn35; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn36; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn38; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn39; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn40; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.ToolStripMenuItem 删除选中独立分出比例ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn41; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn42; + } +} diff --git a/FLSystem/Forms/setting_system_control.cs b/FLSystem/Forms/setting_system_control.cs new file mode 100644 index 0000000..962d7cc --- /dev/null +++ b/FLSystem/Forms/setting_system_control.cs @@ -0,0 +1,1307 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using DevExpress.XtraGrid.Views.Grid; +using FLSystem.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class setting_system_control : DevExpress.XtraEditors.XtraUserControl + { + public setting_system_control() + { + InitializeComponent(); + this.tabPane1.SelectedPageIndex = 0; + //tabNavigationPage4.PageVisible = tabNavigationPage5.PageVisible = Util.ShowTgwz(); + tabNavigationPage4.PageVisible = Util.ShowTgwz(); + } + + #region 临时类 + /// <summary> + /// 临时类,显示用 + /// </summary> + class view_fl_member_group : fl_member_group + { + [Browsable(false)] + public string ratio_custom_tb_name { get; set; } + [Browsable(false)] + public string ratio_custom_pdd_name { get; set; } + [Browsable(false)] + public string ratio_custom_jd_name { get; set; } + [Browsable(false)] + public string ratio_custom_wph_name { get; set; } + [Browsable(false)] + public string ratio_custom_dy_name { get; set; } + [Browsable(false)] + public string ratio_custom_sn_name { get; set; } + [Browsable(false)] + public string ratio_custom_ks_name { get; set; } + } + + private List<view_fl_member_group> GetViewGroups(List<fl_member_group> data) + { + var results = new List<view_fl_member_group>(); + try + { + if (data != null && data.Count != 0) + { + var db = ApiClient.GetSession(); + var custom_groups = db.Find<fl_ratio_info_custom_group>("select * from fl_ratio_info_custom_group"); + foreach (var item in data) + { + var tb = custom_groups.FirstOrDefault(f => f.id == item.ratio_custom_tb); + var pdd = custom_groups.FirstOrDefault(f => f.id == item.ratio_custom_pdd); + var jd = custom_groups.FirstOrDefault(f => f.id == item.ratio_custom_jd); + var wph = custom_groups.FirstOrDefault(f => f.id == item.ratio_custom_wph); + var dy = custom_groups.FirstOrDefault(f => f.id == item.ratio_custom_dy); + var sn = custom_groups.FirstOrDefault(f => f.id == item.ratio_custom_sn); + var ks = custom_groups.FirstOrDefault(f => f.id == item.ratio_custom_ks); + + results.Add(new view_fl_member_group() + { + id = item.id, + name = item.name, + ratio_custom_dy = item.ratio_custom_dy, + ratio_custom_dy_name = (dy == null ? string.Empty : dy.name), + ratio_custom_jd = item.ratio_custom_jd, + ratio_custom_jd_name = (jd == null ? string.Empty : jd.name), + ratio_custom_pdd = item.ratio_custom_pdd, + ratio_custom_pdd_name = (pdd == null ? string.Empty : pdd.name), + ratio_custom_tb = item.ratio_custom_tb, + ratio_custom_tb_name = (tb == null ? string.Empty : tb.name), + ratio_custom_wph = item.ratio_custom_wph, + ratio_custom_wph_name = (wph == null ? string.Empty : wph.name), + ratio_custom_sn = item.ratio_custom_sn, + ratio_custom_sn_name = (sn == null ? string.Empty : sn.name), + ratio_custom_ks = item.ratio_custom_ks, + ratio_custom_ks_name = (ks == null ? string.Empty : ks.name), + subsidy = item.subsidy, + subsidy_type = item.subsidy_type, + terms = item.terms, + terms_ordersum = item.terms_ordersum + }); + } + } + } + catch (Exception ex) + { + BaseForm.ShowError($"加载数据异常:{ex.Message}"); + } + return results; + } + + #endregion + + public void Initialization() + { + try + { + var session = ApiClient.GetSession(); + if (this.tabPane1.SelectedPageIndex == 0) + { + var groups = session.FindGroups(true); + this.gridControl1.DataSource = GetViewGroups(groups); + } + else if (tabPane1.SelectedPageIndex == 1) + { + var groups = session.FindRatios(Util.ConvertEnum<CpsType>(int.Parse(this.radioGroup1.EditValue.ToString())), true); + this.gridControl2.DataSource = groups; + } + else if (tabPane1.SelectedPageIndex == 2) + { + flushCustomGroupView(); + + } + else if (tabPane1.SelectedPageIndex == 3) + { + var groups = session.FindSleeps(Util.ConvertEnum<CpsType>(int.Parse(this.radioGroup2.EditValue.ToString())), true); + this.gridControl3.DataSource = groups; + } + else if (tabPane1.SelectedPageIndex == 4) + { + var groups = session.FindAdzoneGroups(Util.ConvertEnum<CpsType>(int.Parse(this.radioGroup3.EditValue.ToString())), true).Where(f => string.IsNullOrWhiteSpace(f.remark)).ToList(); + foreach (var group in groups) + { + var tgws = (CsharpHttpHelper.HttpHelper.JsonToObject<List<Tuiguangwei>>(group.adzones) as List<Tuiguangwei>); + var temp = string.Join(",", tgws.Select(z => z.Member.usernick).GroupBy(f => f).Select(f => f.Key)); + group.adzones = temp; + } + this.gridControl4.DataSource = groups; + label2.Visible = groups.Count == 0; + } + else if (tabPane1.SelectedPageIndex == 5) + { + var groups = session.FindAdzoneGroups(Util.ConvertEnum<CpsType>(int.Parse(this.radioGroup4.EditValue.ToString())), true).Where(f => f.remark == fl_alimama_activity_type.天猫精选.ToString()).ToList(); + foreach (var group in groups) + { + var tgws = (CsharpHttpHelper.HttpHelper.JsonToObject<List<TuiguangweiActivity>>(group.adzones) as List<TuiguangweiActivity>); + if (tgws == null) continue; + var temp = string.Join(",", tgws.Select(z => z.Member.usernick).GroupBy(f => f).Select(f => f.Key)); + group.adzones = temp; + } + this.gridControl5.DataSource = groups; + label1.Visible = groups.Count == 0; + } + else if (tabPane1.SelectedPageIndex == 6) + { + var list = session.FindUserVariates(); + this.gridControl6.DataSource = list; + label3.Visible = list.Count == 0; + } + else if (tabPane1.SelectedPageIndex == 7) + { + pageControl1.Bind((page, size) => + { + var db = ApiClient.GetSession(); + var parm = db.NewParamMap(); + parm.setPageParamters(page, size); + var total = 0; + List<group_pid_temp> result = null; + if (string.IsNullOrWhiteSpace(tbox_KeyWord.Text)) + { + result = session.Queryable<fl_adzone_info>().Where(f => f.custom_type == Resources.GroupSoftwareType).OrderBy(f => f.id, SqlSugar.OrderByType.Desc).GroupBy(f => f.group_id).Select<group_pid_temp>((f) => new group_pid_temp() + { + groupid = f.group_id, + extend = f.extend, + jd_pid_name = string.Empty, + pdd_pid_name = string.Empty, + tb_pid_name = string.Empty + }).ToPageList(page, size, ref total); + } + else + { + result = session.Queryable<fl_adzone_info>().Where(f => f.custom_type == Resources.GroupSoftwareType && f.group_id.Contains(tbox_KeyWord.Text.Trim())).OrderBy(f => f.id, SqlSugar.OrderByType.Desc).GroupBy(f => f.group_id).Select<group_pid_temp>((f) => new group_pid_temp() + { + groupid = f.group_id, + extend = f.extend, + jd_pid_name = string.Empty, + pdd_pid_name = string.Empty, + tb_pid_name = string.Empty + }).ToPageList(page, size, ref total); + } + + foreach (var item in result) + { + var infos = session.Find<fl_adzone_info>("select * from fl_adzone_info where group_id = @group_id and custom_type = @custom_type", new { group_id = item.groupid, custom_type = Resources.GroupSoftwareType }); + foreach (var info in infos) + { + var type = (CpsType)Enum.ToObject(typeof(CpsType), info.alliance_id); + switch (type) + { + case CpsType.阿里妈妈: + item.tb_pid_name = info.adzone_name; + break; + case CpsType.多多进宝: + item.pdd_pid_name = info.adzone_name; + break; + case CpsType.京东联盟: + item.jd_pid_name = info.adzone_name; + break; + case CpsType.唯品联盟: + item.jd_pid_name = info.adzone_name; + break; + case CpsType.抖音联盟: + item.jd_pid_name = info.adzone_name; + break; + default: + break; + } + } + } + + label4.Visible = result.Count == 0; + + return new PageControl.SerchResult() { Result = result, Total = total }; + }, gridControl7, 40); + + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex.Message + "_" + ex.StackTrace); + } + } + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + if (e.Column.Caption == "会员等级") + { + var row = e.Row as fl_member_group; + e.Value = row.GetLevel(); + } + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + GridView gridview = null; + if (tabPane1.SelectedPageIndex == 0) + { + gridview = gridView1; + var _rows = gridview.GetSelectedRows(); + var temp = gridview.GetRow(_rows[0]) as fl_member_group; + if (temp.terms == 0 && temp.terms_ordersum == 0) + { + XtraMessageBox.Show("升级条件为[0]的项,不能删除!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + } + else if (tabPane1.SelectedPageIndex == 1) gridview = gridView2; + else gridview = gridView3; + + var rows = gridview.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridview.GetRow(rows[0]) as base_model; + var session = ApiClient.GetSession(); + + if (tabPane1.SelectedPageIndex == 0) + { + int rowCount = gridview.RowCount;//获取所有的行数 + var memberModels = new List<fl_member_group>(); + //将没有选中的分组,放置集合中.用于用户分组转移使用 + for (int i = 0; i < rowCount; i++) + { + if (i != rows[0]) + memberModels.Add(gridview.GetRow(i) as fl_member_group); + } + var memberReelectGroupForm = new member_reelect_group(memberModels); + if (memberReelectGroupForm.ShowDialog() == DialogResult.OK) + { + //要删除的分组,分组对应的用户将移至还存在的分组中 + var id = memberReelectGroupForm.id; + session.ExcuteSQL("update fl_member_info set group_id = @newgroupid where group_id = @oldgroupid", new { newgroupid = id, oldgroupid = row.id }); + session.ExcuteSQL("delete from fl_member_group where id = @id", new { id = row.id }); + } + } + else if (tabPane1.SelectedPageIndex == 1) + session.ExcuteSQL("delete from fl_ratio_info where id = @id", new { id = row.id }); + else if (tabPane1.SelectedPageIndex == 3) + session.ExcuteSQL("delete from fl_order_sleep where id = @id", new { id = row.id }); + Initialization(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void 修改ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + GridView grid = null; + bool set_group = false; + double tiaojian_pointsum = 0; + double tiaojian_ordersum = 0; + + if (this.tabPane1.SelectedPageIndex == 0) + { + set_group = true; + grid = this.gridView1; + } + else if (this.tabPane1.SelectedPageIndex == 1) grid = this.gridView2; + else if (this.tabPane1.SelectedPageIndex == 3) grid = this.gridView3; + + var rows = grid.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = grid.GetRow(rows[0]) as base_model; + var temp = set_group ? grid.GetRow(rows[0]) as fl_member_group : null; + tiaojian_pointsum = temp != null ? temp.terms : 0; + tiaojian_ordersum = temp != null ? temp.terms_ordersum : 0; + SettingForm form = new SettingForm(row); + form.ShowDialog(); + if (temp != null && tiaojian_pointsum == 0 && tiaojian_ordersum == 0 && (temp.terms != 0 || temp.terms_ordersum != 0)) + { + temp.terms_ordersum = 0; + temp.terms = 0; + XtraMessageBox.Show("升级条件为[0]的项,不能修改条件,必须有一个升级条件为[0]!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); + } + + var session = ApiClient.GetSession(); + + var type = row.GetType(); + if (type == typeof(fl_member_group) || type == typeof(view_fl_member_group)) session.SaveOrUpdate(row as fl_member_group); + else if (type == typeof(fl_ratio_info)) session.SaveOrUpdate(row as fl_ratio_info); + else if (type == typeof(fl_order_sleep)) session.SaveOrUpdate(row as fl_order_sleep); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + Initialization();//刷新界面 + } + + private void tabPane1_SelectedPageIndexChanged(object sender, EventArgs e) + { + Initialization(); + } + + private void 增加ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var title = string.Empty; + base_model entity = null; + if (this.tabPane1.SelectedPageIndex == 0) + { + entity = new fl_member_group() { subsidy_type = SubsidyType.百分比 }; + title = "增加会员组"; + } + else if (this.tabPane1.SelectedPageIndex == 1)//公共佣金规则 + { + if (radioGroup1.SelectedIndex == 0) + entity = new fl_ratio_info() { cps_type = CpsType.多多进宝, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 1) + entity = new fl_ratio_info() { cps_type = CpsType.阿里妈妈, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 2) + entity = new fl_ratio_info() { cps_type = CpsType.京东联盟, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 3) + entity = new fl_ratio_info() { cps_type = CpsType.唯品联盟, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 4) + entity = new fl_ratio_info() { cps_type = CpsType.抖音联盟, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 5) + entity = new fl_ratio_info() { cps_type = CpsType.苏宁易购, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 6) + entity = new fl_ratio_info() { cps_type = CpsType.快手联盟, subsidy_type = SubsidyType.百分比 }; + title = "增加公共分出比例"; + } + else if (this.tabPane1.SelectedPageIndex == 2) //独立设置佣金规则 + { + if (radioGroup1.SelectedIndex == 0) + entity = new fl_ratio_info_custom() { cps_type = CpsType.多多进宝, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 1) + entity = new fl_ratio_info_custom() { cps_type = CpsType.阿里妈妈, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 2) + entity = new fl_ratio_info_custom() { cps_type = CpsType.京东联盟, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 3) + entity = new fl_ratio_info_custom() { cps_type = CpsType.唯品联盟, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 4) + entity = new fl_ratio_info_custom() { cps_type = CpsType.抖音联盟, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 5) + entity = new fl_ratio_info_custom() { cps_type = CpsType.苏宁易购, subsidy_type = SubsidyType.百分比 }; + else if (radioGroup1.SelectedIndex == 6) + entity = new fl_ratio_info_custom() { cps_type = CpsType.快手联盟, subsidy_type = SubsidyType.百分比 }; + title = "增加独立分出比例"; + } + else if (this.tabPane1.SelectedPageIndex == 3) + { + entity = null; + if (radioGroup2.SelectedIndex == 0) + entity = new fl_order_sleep() { cps_type = CpsType.多多进宝 }; + else if (radioGroup2.SelectedIndex == 1) + entity = new fl_order_sleep() { cps_type = CpsType.阿里妈妈 }; + else if (radioGroup2.SelectedIndex == 2) + entity = new fl_order_sleep() { cps_type = CpsType.京东联盟 }; + else if (radioGroup2.SelectedIndex == 3) + entity = new fl_order_sleep() { cps_type = CpsType.唯品联盟 }; + else if (radioGroup2.SelectedIndex == 4) + entity = new fl_order_sleep() { cps_type = CpsType.抖音联盟 }; + else if (radioGroup2.SelectedIndex == 5) + entity = new fl_order_sleep() { cps_type = CpsType.苏宁易购 }; + else if (radioGroup2.SelectedIndex == 6) + entity = new fl_order_sleep() { cps_type = CpsType.快手联盟 }; + title = "增加延迟结算"; + } + try + { + SettingForm form = new SettingForm(entity); + form.Text = title; + form.ShowDialog(); + + var session = ApiClient.GetSession(); + var type = entity.GetType(); + if (type == typeof(fl_member_group)) session.SaveOrUpdate(entity as fl_member_group); + else if (type == typeof(fl_ratio_info)) session.SaveOrUpdate(entity as fl_ratio_info); + else if (type == typeof(fl_order_sleep)) session.SaveOrUpdate(entity as fl_order_sleep); + } + catch + { + if (!this.IsDisposed) BaseForm.ShowError("数据违反唯一性,请勿重复增加"); + } + Initialization();//刷新界面 + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + /// <summary> + /// 增加 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + if (radioGroup3.SelectedIndex == 0) + { + var adzoneform = new tb_adzone_group_form(); + adzoneform.Text = "增加推广位组"; + adzoneform.ShowDialog(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + Initialization();//刷新界面 + } + + /// <summary> + /// 修改 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void toolStripMenuItem2_Click(object sender, EventArgs e) + { + try + { + var rows = gridView4.GetSelectedRows(); + if (rows.Length != 0) + { + var row = gridView4.GetRow(rows[0]) as base_model; + var adzoneform = new tb_adzone_group_form(row.id); + adzoneform.Text = "修改推广位组"; + adzoneform.ShowDialog(); + Initialization(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + /// <summary> + /// 删除 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void toolStripMenuItem3_Click(object sender, EventArgs e) + { + try + { + var rows = gridView4.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView4.GetRow(rows[0]) as base_model; + var session = ApiClient.GetSession(); + session.Deleteable<fl_adzone_group>().In(row.id).ExecuteCommand(); + Initialization(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void radioGroup3_SelectedIndexChanged(object sender, EventArgs e) + { + Initialization(); + } + + #region 强制返利推广位列表右击 + /// <summary> + /// 增加 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void toolStripMenuItem4_Click(object sender, EventArgs e) + { + try + { + if (radioGroup4.SelectedIndex == 0) + { + var adzoneform = new tb_adzone_activity_group_form(); + adzoneform.Text = "增加强返推广位组"; + adzoneform.ShowDialog(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + Initialization();//刷新界面 + } + + /// <summary> + /// 修改 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void toolStripMenuItem5_Click(object sender, EventArgs e) + { + try + { + var rows = gridView5.GetSelectedRows(); + if (rows.Length != 0) + { + var row = gridView5.GetRow(rows[0]) as base_model; + var adzoneform = new tb_adzone_activity_group_form(row.id); + adzoneform.Text = "修改强返推广位组"; + adzoneform.ShowDialog(); + Initialization(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + /// <summary> + /// 删除 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void toolStripMenuItem6_Click(object sender, EventArgs e) + { + try + { + var rows = gridView5.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView5.GetRow(rows[0]) as base_model; + var session = ApiClient.GetSession(); + session.Deleteable<fl_adzone_group>().In(row.id).ExecuteCommand(); + Initialization(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + #endregion + + private void toolStripMenuItem7_Click(object sender, EventArgs e) + { + try + { + var form = new edit_uservariate_form(); + form.Text = "增加全局变量"; + form.ShowDialog(); + Initialization(); + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void toolStripMenuItem8_Click(object sender, EventArgs e) + { + try + { + var rows = gridView6.GetSelectedRows(); + if (rows.Length == 0) return; + var uservariate_info = gridView6.GetRow(rows[0]) as fl_uservariate_info; + if (uservariate_info == null) return; + var form = new edit_uservariate_form(uservariate_info); + form.Text = "修改全局变量"; + form.ShowDialog(); + Initialization(); + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void toolStripMenuItem9_Click(object sender, EventArgs e) + { + try + { + var rows = gridView6.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView6.GetRow(rows[0]) as base_model; + var session = ApiClient.GetSession(); + session.Deleteable<fl_uservariate_info>().In(row.id).ExecuteCommand(); + session.FindUserVariates(true); + Initialization(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void 增加群pidToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var group_info = new group_info_form(); + group_info.ShowDialog(); + Initialization(); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void 修改群信息ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView7.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var group_id = gridView7.GetRowCellValue(rows[0], "groupid").ToString(); + var extend = gridView7.GetRowCellValue(rows[0], "extend").ToString(); + var group_info = new group_info_form(group_id, extend); + group_info.ShowDialog(); + Initialization(); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + Initialization(); + } + + private void gridView7_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "pdd_pid_name" || e.Column.FieldName == "tb_pid_name" || e.Column.FieldName == "jd_pid_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void gridView7_RowCellClick(object sender, RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView7.GetSelectedRows()[0]; + var groupid = this.gridView7.GetRowCellValue(selectRow, "groupid").ToString();//获取列的数据 + + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + var session = ApiClient.GetSession(); + var strs = new string[] { "淘宝推广位名称", "拼多多推广位名称", "京东推广位名称", "唯品会推广位名称" }; + if (!strs.Contains(e.Column.Caption)) return; + + var pidInfos = session.Queryable<fl_adzone_info>().Where(f => f.group_id == groupid && f.custom_type == Resources.GroupSoftwareType).ToList(); + fl_adzone_info esbAdzone = null; + object setAdzoneObj = null; + Tuiguangwei setAdzone = null; + if (e.Column.Caption == strs[0]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.alliance_id == (int)CpsType.阿里妈妈).FirstOrDefault(); + } + else if (e.Column.Caption == strs[1]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.多多进宝); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.alliance_id == (int)CpsType.多多进宝).FirstOrDefault(); + } + else if (e.Column.Caption == strs[2]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.京东联盟); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.alliance_id == (int)CpsType.京东联盟).FirstOrDefault(); + } + else if (e.Column.Caption == strs[3]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.唯品联盟); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.alliance_id == (int)CpsType.唯品联盟).FirstOrDefault(); + } + else if (e.Column.Caption == strs[4]) + { + setAdzoneObj = CpsClient.SelectTuiguangwei(CpsType.抖音联盟); + if (setAdzoneObj != null) + esbAdzone = pidInfos.Where(f => f.alliance_id == (int)CpsType.抖音联盟).FirstOrDefault(); + } + + if (esbAdzone != null && setAdzoneObj != null) + { + setAdzone = setAdzoneObj as Tuiguangwei; + esbAdzone.adzone_name = setAdzone.Name; + esbAdzone.adzone_pid = setAdzone.Pid; + esbAdzone.adzone_pid_cps_name = setAdzone.Member.username; + session.SaveOrUpdate(esbAdzone); + } + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + #endregion + + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void 删除选中群ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView7.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var group_id = gridView7.GetRowCellValue(rows[0], "groupid").ToString(); + var session = ApiClient.GetSession(); + session.Deleteable<fl_adzone_info>().Where(f => f.custom_type == Resources.GroupSoftwareType && f.group_id == group_id).ExecuteCommand(); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + BaseForm.ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void contextMenuStrip4_Opening(object sender, System.ComponentModel.CancelEventArgs e) + { + var rows = gridView7.GetSelectedRows(); + 修改群信息ToolStripMenuItem.Enabled = 删除选中群ToolStripMenuItem.Enabled = 推广位删除ToolStripMenuItem.Enabled = (rows != null && rows.Length > 0); + } + + private void 删除选中推广位ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + if (sender is ToolStripMenuItem) + { + var item = sender as ToolStripMenuItem; + CpsType cps = CpsType.京东联盟; + if (item.Text == "删除选中淘宝推广位") + cps = CpsType.阿里妈妈; + else if (item.Text == "删除选中拼多多推广位") + cps = CpsType.多多进宝; + else if (item.Text == "删除选中京东推广位") + cps = CpsType.京东联盟; + else if (item.Text == "删除选中唯品会推广位") + cps = CpsType.唯品联盟; + else if (item.Text == "删除选中抖音推广位") + cps = CpsType.抖音联盟; + + var session = ApiClient.GetSession(); + var selectRow = gridView7.GetSelectedRows()[0]; + var groupid = this.gridView7.GetRowCellValue(selectRow, "groupid").ToString();//获取列的数据 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)cps && f.group_id == groupid && f.custom_type == Resources.GroupSoftwareType); + if (adzone != null) + { + adzone.adzone_name = string.Empty; + adzone.adzone_pid = string.Empty; + adzone.adzone_pid_cps_name = string.Empty; + + session.SaveOrUpdate(adzone); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + } + BaseForm.ShowSuccess("执行成功"); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + #region 分组 + + private void toolStripMenuItem10_Click_1(object sender, EventArgs e) + { + try + { + var title = string.Empty; + base_model entity = null; + if (radioGroup5.SelectedIndex == 0) + entity = new fl_ratio_info_custom_group() { cps_type = CpsType.多多进宝 }; + else if (radioGroup5.SelectedIndex == 1) + entity = new fl_ratio_info_custom_group() { cps_type = CpsType.阿里妈妈 }; + else if (radioGroup5.SelectedIndex == 2) + entity = new fl_ratio_info_custom_group() { cps_type = CpsType.京东联盟 }; + else if (radioGroup5.SelectedIndex == 3) + entity = new fl_ratio_info_custom_group() { cps_type = CpsType.唯品联盟 }; + else if (radioGroup5.SelectedIndex == 4) + entity = new fl_ratio_info_custom_group() { cps_type = CpsType.抖音联盟 }; + else if (radioGroup5.SelectedIndex == 5) + entity = new fl_ratio_info_custom_group() { cps_type = CpsType.苏宁易购 }; + else if (radioGroup5.SelectedIndex == 6) + entity = new fl_ratio_info_custom_group() { cps_type = CpsType.快手联盟 }; + title = "增加独立分出比例分组"; + + try + { + SettingForm form = new SettingForm(entity); + form.Text = title; + form.ShowDialog(); + var session = ApiClient.GetSession(); + var type = entity.GetType(); + if (type == typeof(fl_ratio_info_custom_group)) + { + var ricg = entity as fl_ratio_info_custom_group; + if (string.IsNullOrWhiteSpace(ricg.name)) + return; + session.SaveOrUpdate(ricg); + } + } + catch + { + if (!this.IsDisposed) BaseForm.ShowError("数据违反唯一性,请勿重复增加"); + } + Initialization();//刷新界面 + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + /// <summary> + /// 刷新自定义分出比例分组列表 + /// </summary> + private void flushCustomGroupView() + { + try + { + var db = ApiClient.GetSession(); + //var groups = db.Queryable<fl_ratio_info_custom_group>().Where(f => f.cps_type == Util.ConvertEnum<CpsType>(int.Parse(this.radioGroup5.EditValue.ToString()))).ToList(); + var groups = db.Find<fl_ratio_info_custom_group>("select * from fl_ratio_info_custom_group where cps_type = @cps_type", new { cps_type = this.radioGroup5.EditValue.ToString() }).ToList(); + this.gridControl9.DataSource = groups; + if (groups != null && groups.Count != 0) + { + ratioInfoCustomId = groups[0].id; + label6.Visible = false; + } + else + { + ratioInfoCustomId = -1; + label6.Visible = true; + } + } + catch (Exception ex) + { } + flushCustomView(); + } + + private void toolStripMenuItem13_Click(object sender, EventArgs e) + { + try + { + if (ratioInfoCustomId == -1) + { + BaseForm.ShowErrorAutoClose("请先添加分组"); + return; + } + + var title = string.Empty; + base_model entity = null; + if (radioGroup5.SelectedIndex == 0) + entity = new fl_ratio_info_custom() { cps_type = CpsType.多多进宝, subsidy_type = SubsidyType.百分比, cgid = ratioInfoCustomId }; + else if (radioGroup5.SelectedIndex == 1) + entity = new fl_ratio_info_custom() { cps_type = CpsType.阿里妈妈, subsidy_type = SubsidyType.百分比, cgid = ratioInfoCustomId }; + else if (radioGroup5.SelectedIndex == 2) + entity = new fl_ratio_info_custom() { cps_type = CpsType.京东联盟, subsidy_type = SubsidyType.百分比, cgid = ratioInfoCustomId }; + else if (radioGroup5.SelectedIndex == 3) + entity = new fl_ratio_info_custom() { cps_type = CpsType.唯品联盟, subsidy_type = SubsidyType.百分比, cgid = ratioInfoCustomId }; + else if (radioGroup5.SelectedIndex == 4) + entity = new fl_ratio_info_custom() { cps_type = CpsType.抖音联盟, subsidy_type = SubsidyType.百分比, cgid = ratioInfoCustomId }; + else if (radioGroup5.SelectedIndex == 5) + entity = new fl_ratio_info_custom() { cps_type = CpsType.苏宁易购, subsidy_type = SubsidyType.百分比, cgid = ratioInfoCustomId }; + else if (radioGroup5.SelectedIndex == 6) + entity = new fl_ratio_info_custom() { cps_type = CpsType.快手联盟, subsidy_type = SubsidyType.百分比, cgid = ratioInfoCustomId }; + title = "增加独立分出比例"; + + try + { + SettingForm form = new SettingForm(entity); + form.Text = title; + form.ShowDialog(); + + var session = ApiClient.GetSession(); + var type = entity.GetType(); + if (type == typeof(fl_ratio_info_custom)) session.SaveOrUpdate(entity as fl_ratio_info_custom); + } + catch + { + if (!this.IsDisposed) BaseForm.ShowError("数据违反唯一性,请勿重复增加"); + } + //Initialization();//刷新界面 + flushCustomView(); + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + /// <summary> + /// 刷新自定义分出比例分组 + /// </summary> + private void flushCustomView() + { + try + { + if (ratioInfoCustomId == -1) + { + gridControl8.DataSource = null; + label5.Visible = true; + return; + } + var db = ApiClient.GetSession(); + var groups = db.FindCustomRatios(ratioInfoCustomId, true); + this.gridControl8.DataSource = groups; + if (groups != null && groups.Count != 0) + label5.Visible = false; + } + catch (Exception ex) + { } + } + + /// <summary> + /// 独立分组选中id + /// </summary> + private long ratioInfoCustomId = -1; + + #endregion + + private void radioGroup5_SelectedIndexChanged(object sender, EventArgs e) + { + Initialization(); + } + + private void gridControl9_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView9.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView9.GetRow(rows[0]) as fl_ratio_info_custom_group; + if (gridView9.SelectedRowsCount != 0) + { + ratioInfoCustomId = row.id; + flushCustomView(); + } + } + } + catch (Exception ex) + { } + } + + private void toolStripMenuItem11_Click(object sender, EventArgs e) + { + try + { + var rows = gridView9.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView9.GetRow(rows[0]) as fl_ratio_info_custom_group; + SettingForm form = new SettingForm(row); + form.ShowDialog(); + var session = ApiClient.GetSession(); + var type = row.GetType(); + session.SaveOrUpdate(row as fl_ratio_info_custom_group); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + Initialization();//刷新界面 + } + + private void toolStripMenuItem14_Click(object sender, EventArgs e) + { + try + { + var rows = gridView8.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView8.GetRow(rows[0]) as fl_ratio_info_custom; + SettingForm form = new SettingForm(row); + form.ShowDialog(); + var session = ApiClient.GetSession(); + var type = row.GetType(); + session.SaveOrUpdate(row as fl_ratio_info_custom); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + Initialization();//刷新界面 + } + + private void toolStripMenuItem12_Click(object sender, EventArgs e) + { + try + { + var rows = gridView9.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + if (XtraMessageBox.Show("确定要删除选中以及相关的数据吗?", "友情提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.Cancel) + return; + var row = gridView9.GetRow(rows[0]) as fl_ratio_info_custom_group; + + var db = ApiClient.GetSession(); + + db.ExcuteSQL("delete from fl_ratio_info_custom where cgid = @id", new { id = row.id }); + db.ExcuteSQL("delete from fl_ratio_info_custom_group where id = @id", new { id = row.id }); + Initialization(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void toolStripMenuItem15_Click(object sender, EventArgs e) + { + try + { + var rows = gridView8.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView8.GetRow(rows[0]) as fl_ratio_info_custom; + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_ratio_info_custom where id = @id", new { id = row.id }); + flushCustomView(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + /// <summary> + /// 行单元格单击事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView1_RowCellClick(object sender, RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + + if (gridView1.GetSelectedRows().Length != 0) + { + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "id").ToString();//获取列的数据 + + if (e.Column.FieldName == "ratio_custom_tb_name" + || e.Column.FieldName == "ratio_custom_pdd_name" + || e.Column.FieldName == "ratio_custom_jd_name" + || e.Column.FieldName == "ratio_custom_wph_name" + || e.Column.FieldName == "ratio_custom_dy_name" + || e.Column.FieldName == "ratio_custom_sn_name" + || e.Column.FieldName == "ratio_custom_ks_name" + ) + { + /* + 阿里妈妈 = 1, + 多多进宝 = 2, + 京东联盟 = 3, + 唯品联盟 = 4, + 抖音联盟 = 5, + 苏宁易购 = 6, + 快手联盟 = 7, + */ + var selIndex = 0; //选择选 + CpsType cps = CpsType.京东联盟; + if (e.Column.FieldName.Contains("_tb_")) + { + selIndex = 1; + cps = CpsType.阿里妈妈; + } + else if (e.Column.FieldName.Contains("_pdd_")) + { + selIndex = 0; + cps = CpsType.多多进宝; + } + else if (e.Column.FieldName.Contains("_jd_")) + { + selIndex = 2; + cps = CpsType.京东联盟; + } + else if (e.Column.FieldName.Contains("_wph_")) + { + selIndex = 3; + cps = CpsType.唯品联盟; + } + else if (e.Column.FieldName.Contains("_dy_")) + { + selIndex = 4; + cps = CpsType.抖音联盟; + } + else if (e.Column.FieldName.Contains("_sn_")) + { + selIndex = 5; + cps = CpsType.苏宁易购; + } + else if (e.Column.FieldName.Contains("_ks_")) + { + selIndex = 6; + cps = CpsType.快手联盟; + } + var db = ApiClient.GetSession(); + var custom_group = db.Find<fl_ratio_info_custom_group>("select * from fl_ratio_info_custom_group where cps_type = @cps_type", new { cps_type = (int)cps }); + if (custom_group == null || custom_group.Count == 0) + { + if (XtraMessageBox.Show("当前平台联盟没有设置独立的分出比例分组,是否立即去设置?", "友情提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) + { + tabPane1.SelectedPageIndex = 2; + radioGroup5.SelectedIndex = selIndex; + } + return; + } + + var rcgf = new RatioCustomGroupForm(custom_group); + rcgf.ShowDialog(); + if (rcgf.group != null) + { + var custom = db.FindSingle<fl_member_group>("select * from fl_member_group where id = @id", new { id = id }); + if (custom != null) + { + switch (cps) + { + case CpsType.阿里妈妈: + custom.ratio_custom_tb = rcgf.group.id; + break; + case CpsType.多多进宝: + custom.ratio_custom_pdd = rcgf.group.id; + break; + case CpsType.京东联盟: + custom.ratio_custom_jd = rcgf.group.id; + break; + case CpsType.唯品联盟: + custom.ratio_custom_wph = rcgf.group.id; + break; + case CpsType.抖音联盟: + custom.ratio_custom_dy = rcgf.group.id; + break; + case CpsType.苏宁易购: + custom.ratio_custom_sn = rcgf.group.id; + break; + case CpsType.快手联盟: + custom.ratio_custom_ks = rcgf.group.id; + break; + default: + break; + } + db.SaveOrUpdate(custom); + } + Initialization(); + } + } + } + } + #endregion + + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + /// <summary> + /// 修改显示内容的事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "ratio_custom_tb_name" || e.Column.FieldName == "ratio_custom_pdd_name" || e.Column.FieldName == "ratio_custom_jd_name" + || e.Column.FieldName == "ratio_custom_wph_name" || e.Column.FieldName == "ratio_custom_dy_name" || e.Column.FieldName == "ratio_custom_sn_name" || e.Column.FieldName == "ratio_custom_ks_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + return; + } + } + + private void contex_1_Opening(object sender, System.ComponentModel.CancelEventArgs e) + { + try + { + if (this.tabPane1.SelectedPageIndex == 0) + 删除选中独立分出比例ToolStripMenuItem.Visible = true; + else + 删除选中独立分出比例ToolStripMenuItem.Visible = false; + } + catch (Exception) + { } + } + + private void 删除选中独立分出比例ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView1.GetRow(rows[0]) as fl_member_group; + if (gridView1.FocusedColumn.FieldName == "ratio_custom_pdd_name") + row.ratio_custom_pdd = 0; + else if (gridView1.FocusedColumn.FieldName == "ratio_custom_tb_name") + row.ratio_custom_tb = 0; + else if (gridView1.FocusedColumn.FieldName == "ratio_custom_jd_name") + row.ratio_custom_jd = 0; + else if (gridView1.FocusedColumn.FieldName == "ratio_custom_wph_name") + row.ratio_custom_wph = 0; + else if (gridView1.FocusedColumn.FieldName == "ratio_custom_dy_name") + row.ratio_custom_dy = 0; + else if (gridView1.FocusedColumn.FieldName == "ratio_custom_sn_name") + row.ratio_custom_sn = 0; + else if (gridView1.FocusedColumn.FieldName == "ratio_custom_ks_name") + row.ratio_custom_ks = 0; + var db = ApiClient.GetSession(); + db.SaveOrUpdate(row); + Initialization(); + } + } + catch (Exception) + { } + } + } +} diff --git a/FLSystem/Forms/setting_system_control.resx b/FLSystem/Forms/setting_system_control.resx new file mode 100644 index 0000000..4827eeb --- /dev/null +++ b/FLSystem/Forms/setting_system_control.resx @@ -0,0 +1,166 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="contex_1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>130, 21</value> + </metadata> + <metadata name="contextMenuStrip2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>313, 18</value> + </metadata> + <metadata name="contextMenuStrip3.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>478, 18</value> + </metadata> + <metadata name="contextMenuStrip4.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>643, 18</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton2.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <metadata name="contextMenuStrip5.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>808, 18</value> + </metadata> + <metadata name="contextMenuStrip6.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>973, 18</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>50</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/show_word.Designer.cs b/FLSystem/Forms/show_word.Designer.cs new file mode 100644 index 0000000..a80e759 --- /dev/null +++ b/FLSystem/Forms/show_word.Designer.cs @@ -0,0 +1,59 @@ +namespace FLSystem.Forms +{ + partial class show_word + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.richEditControl1 = new DevExpress.XtraRichEdit.RichEditControl(); + this.SuspendLayout(); + // + // richEditControl1 + // + this.richEditControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.richEditControl1.Location = new System.Drawing.Point(0, 0); + this.richEditControl1.Name = "richEditControl1"; + this.richEditControl1.Size = new System.Drawing.Size(708, 469); + this.richEditControl1.TabIndex = 0; + // + // show_word + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(708, 469); + this.Controls.Add(this.richEditControl1); + this.Name = "show_word"; + this.Text = "show_word"; + this.Load += new System.EventHandler(this.show_word_Load); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraRichEdit.RichEditControl richEditControl1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/show_word.cs b/FLSystem/Forms/show_word.cs new file mode 100644 index 0000000..6d6c605 --- /dev/null +++ b/FLSystem/Forms/show_word.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class show_word : BaseForm + { + public show_word(string fileName) + { + InitializeComponent(); + this.filename = fileName; + } + private string filename; + + private void show_word_Load(object sender, EventArgs e) + { + try + { + var result = this.richEditControl1.LoadDocument(filename); + if (!result) throw new Exception("加载文档失败!"); + } + catch (Exception ex) + { + ShowError(ex); + this.Close(); + } + } + } +} diff --git a/FLSystem/Forms/show_word.resx b/FLSystem/Forms/show_word.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/show_word.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/system_douyin_action_control.Designer.cs b/FLSystem/Forms/system_douyin_action_control.Designer.cs new file mode 100644 index 0000000..a937840 --- /dev/null +++ b/FLSystem/Forms/system_douyin_action_control.Designer.cs @@ -0,0 +1,63 @@ +namespace FLSystem.Forms +{ + partial class system_douyin_action_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.ClosePageButtonShowMode = DevExpress.XtraTab.ClosePageButtonShowMode.InActiveTabPageHeader; + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.MultiLine = DevExpress.Utils.DefaultBoolean.False; + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.ShowHeaderFocus = DevExpress.Utils.DefaultBoolean.False; + this.xtraTabControl1.Size = new System.Drawing.Size(893, 701); + this.xtraTabControl1.TabIndex = 3; + this.xtraTabControl1.CloseButtonClick += new System.EventHandler(this.xtraTabControl1_CloseButtonClick); + // + // system_douyin_action_control + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.xtraTabControl1); + this.Name = "system_douyin_action_control"; + this.Size = new System.Drawing.Size(893, 701); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + } +} diff --git a/FLSystem/Forms/system_douyin_action_control.cs b/FLSystem/Forms/system_douyin_action_control.cs new file mode 100644 index 0000000..39ff0f3 --- /dev/null +++ b/FLSystem/Forms/system_douyin_action_control.cs @@ -0,0 +1,747 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using DevExpress.XtraEditors; +using DevExpress.XtraTab; +using System; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + #region xxx + // public partial class system_douyin_action_control : DevExpress.XtraEditors.XtraUserControl + // { + // public system_douyin_action_control() + // { + // InitializeComponent(); + // DouyinApi.douyinApiAction = DouyinApiAction; + // } + + // private static string DefaultTitle = "抖音扫码登录"; + + + // private void DouyinApiAction(DouyinApi api) + // { + // api.IsQualifiedAction = IsQualifiedAction; + + // bool falg = false; + // var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + // //判断是否已创建过 + // this.Invoke(new Action(() => + // { + // foreach (XtraTabPage page in parentXtraTabControl.TabPages) + // { + // if (page.Text == "抖音活跃列表") + // { + // parentXtraTabControl.SelectedTabPage = page;//显示该页 + // break; + // } + // } + + // //判断是否已创建过 + // foreach (XtraTabPage page in xtraTabControl1.TabPages) + // { + // if (!string.IsNullOrWhiteSpace(api.Member.username) && page.Text.StartsWith(api.Member.username)) + // { + // xtraTabControl1.SelectedTabPage = page;//显示该页 + // return; + // } + // else if (string.IsNullOrWhiteSpace(api.Member.username) && page.Text == DefaultTitle) + // { + // falg = true; + // BaseForm.ShowErrorAutoClose("已经存在扫码登录中的页面"); + // return; + // } + // } + // })); + + // if (!falg) + // { + // var pageName = string.Empty; + // if (!string.IsNullOrWhiteSpace(api.Member.username)) + // { + // pageName = $"{api.Member.username}_({api.Member.usernick})"; + // } + // //AddControlPage(pageName, api.chromeBrowser, global::FLSystem.Properties.Resources.抖音); + // AddControlPage(pageName, api.webControl, global::FLSystem.Properties.Resources.抖音); + // } + // } + + // /// <summary> + // /// 是否满足账号权限 + // /// </summary> + // /// <param name="flag"></param> + // private void IsQualifiedAction(DouyinLoginType type, DouyinApi api) + // { + // try + // { + // switch (type) + // { + // case DouyinLoginType.权限不足: + // { + // EventClient.OnEvent("", $"{api.Member.username}({api.Member.usernick}) 权限未开通,请开通后重试!"); + // CpsClient.Members.Remove(api.Member); + // //CpsClient.DelDouyinApi(api.Member.username); + // this.Invoke(new Action(() => + // { + // var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + // foreach (XtraTabPage page in parentXtraTabControl.TabPages) + // { + // if (page.Text == "抖音活跃列表") + // { + // parentXtraTabControl.SelectedTabPage = page;//显示该页 + // break; + // } + // } + + // ////判断是否已创建过 + // //foreach (XtraTabPage page in xtraTabControl1.TabPages) + // //{ + // // if (page.Text == DefaultTitle) + // // { + // // xtraTabControl1.SelectedTabPage = page;//显示该页 + // // api.chromeBrowser.Load("https://www.douyinec.com/"); + // // return; + // // } + // //} + + // XtraTabPage pageTmp = null; + + // //判断是否已创建过 + // foreach (XtraTabPage page in xtraTabControl1.TabPages) + // { + // if (page.Text == DefaultTitle) + // { + // pageTmp = page; + // } + // } + + // if (pageTmp != null) + // { + // xtraTabControl1.TabPages.Remove(pageTmp); + // //AddControlPage($"{api.Member.username}_({api.Member.usernick})", api.chromeBrowser, global::FLSystem.Properties.Resources.抖音); + // } + // })); + // BaseForm.ShowErrorAutoClose($@"该账号未开通商品分享功能,请开通后重试 + + //注:开通电商权限,需要同时满足以下4个条件 + //①、账号实名认证 + //②、个人主页视频数(公开且审核通过)≥ 10 条 + //③、账号粉丝量(绑定第三方粉丝量不计数)≥ 1000 + //④、商品分享保证金 ¥500立即充值", 120); + // } + // break; + // case DouyinLoginType.登录过期: + // { + // EventClient.OnEvent("", $"抖音离线:{api.Member.username}({api.Member.usernick})"); + // CpsClient.Members.Remove(api.Member); + // //CpsClient.DelDouyinApi(api.Member.username); + // this.Invoke(new Action(() => + // { + // var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + // foreach (XtraTabPage page in parentXtraTabControl.TabPages) + // { + // if (page.Text == "抖音活跃列表") + // { + // parentXtraTabControl.SelectedTabPage = page;//显示该页 + // break; + // } + // } + + // ////判断是否已创建过 + // //foreach (XtraTabPage page in xtraTabControl1.TabPages) + // //{ + // // if (page.Text == DefaultTitle) + // // { + // // xtraTabControl1.SelectedTabPage = page;//显示该页 + // // api.chromeBrowser.Load("https://www.douyinec.com/"); + // // return; + // // } + // //} + + // XtraTabPage pageTmp = null; + + // //判断是否已创建过 + // foreach (XtraTabPage page in xtraTabControl1.TabPages) + // { + // if (page.Text == $"{api.Member.username}_({api.Member.usernick})") + // { + // pageTmp = page; + // } + // } + + // if (pageTmp != null) + // { + // xtraTabControl1.TabPages.Remove(pageTmp); + // //AddControlPage($"{api.Member.username}_({api.Member.usernick})", api.chromeBrowser, global::FLSystem.Properties.Resources.抖音); + // } + // })); + // } + // break; + // case DouyinLoginType.登录成功: + // case DouyinLoginType.新号登录成功: + // { + // this.Invoke(new Action(() => + // { + // //api.SkipOther("https://buyin.jinritemai.com/dashboard/dataCenter/export-list"); + + // var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + // foreach (XtraTabPage page in parentXtraTabControl.TabPages) + // { + // if (page.Text == "抖音活跃列表") + // { + // parentXtraTabControl.SelectedTabPage = page;//显示该页 + // break; + // } + // } + + // XtraTabPage pageTmp = null; + + // if (type == DouyinLoginType.新号登录成功) + // { + // //判断是否已创建过 + // foreach (XtraTabPage page in xtraTabControl1.TabPages) + // { + // if (page.Text == DefaultTitle) + // { + // pageTmp = page; + // } + // } + // if (pageTmp != null) + // { + // xtraTabControl1.TabPages.Remove(pageTmp); + // //AddControlPage($"{api.Member.username}_({api.Member.usernick})", api.chromeBrowser, global::FLSystem.Properties.Resources.抖音); + // AddControlPage($"{api.Member.username}_({api.Member.usernick})", api.webControl, global::FLSystem.Properties.Resources.抖音, true); + // } + // } + // else + // { + // if (pageTmp == null) + // { + // var def = xtraTabControl1.TabPages.FirstOrDefault(f => f.Text == DefaultTitle); + // var notDef = xtraTabControl1.TabPages.FirstOrDefault(f => f.Text == $"{api.Member.username}_({api.Member.usernick})"); + + // if (def != null) + // { + // if (notDef != null) + // xtraTabControl1.TabPages.Remove(notDef); + + // def.Text = $"{api.Member.username}_({api.Member.usernick})"; + // //def.Enabled = false; + // def.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + // } + // else if (notDef != null && def == null) + // { + // notDef.Text = $"{api.Member.username}_({api.Member.usernick})"; + // //notDef.Enabled = false; + // notDef.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + // } + // } + // } + // })); + // } + // break; + // case DouyinLoginType.删除登录账号: + // { + // this.Invoke(new Action(() => + // { + // var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + // foreach (XtraTabPage page in parentXtraTabControl.TabPages) + // { + // if (page.Text == "抖音活跃列表") + // { + // parentXtraTabControl.SelectedTabPage = page;//显示该页 + // break; + // } + // } + // XtraTabPage pageTmp = null; + + // //判断是否已创建过 + // foreach (XtraTabPage page in xtraTabControl1.TabPages) + // { + // if (page.Text == $"{api.Member.username}_({api.Member.usernick})") + // { + // pageTmp = page; + // } + // } + + // if (pageTmp != null) + // { + // xtraTabControl1.TabPages.Remove(pageTmp); + // } + // })); + // } + // break; + // default: + // break; + // } + // this.Invoke(new Action(() => + // { + // CpsClient.RefreshCps(); + // EventClient.OnEvent(null, MethodType.刷新联盟); + // })); + // } + // catch (Exception ex) + // { + + // } + // } + + // //增加选项夹 + // private void AddControlPage(string pageName, Control control, Image img = null, bool isLoad = false) + // { + // this.Invoke(new Action(() => + // { + // try + // { + // //增加tabpage + // XtraTabPage xpage = new XtraTabPage(); + + // if (string.IsNullOrWhiteSpace(pageName)) + // { + // pageName = DefaultTitle; + // control.Enabled = true; + // xpage.ShowCloseButton = DevExpress.Utils.DefaultBoolean.True; + // } + // else + // { + // //if (isLoad) + // // control.Enabled = false; + // xpage.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + // } + // xpage.Name = pageName; + // xpage.Text = pageName; + + // if (img != null) + // xpage.ImageOptions.Image = img; + // //if (xpage.Text == "运行日志") + // //xpage.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + // control.Dock = DockStyle.None; + // control.Location = new Point(0, 0); + // control.Size = new Size(1920, 1080); + + // xpage.Controls.Add(control);//添加要增加的控件 + // xtraTabControl1.TabPages.Add(xpage); + // xtraTabControl1.SelectedTabPage = xpage;//显示该页 + // } + // catch (Exception ex) + // { + // if (ex.Message.Contains(@"“CefSharp.Core.Runtime.dll”或它的某一个依赖项")) + // { + // EventClient.OnEvent("系统缺少服务", $@"请点击链接,下载组件并安装,安装完成后重启软件 + //下载地址:https://wwa.lanzoui.com/iDDvsroqrxc"); + // try + // { + // Clipboard.SetDataObject("https://wwa.lanzoui.com/iDDvsroqrxc" + "?=" + new Random().Next(100, 2000)); + // } + // catch (Exception) + // { } + + // BaseForm.ShowError(@"当前系统缺少组件,请看软件日志,按提示安装相应的组件 + + //下载地址已经复制到粘贴板,在网页中打开即可"); + // } + // else + // XtraMessageBox.Show(ex.Message, "AddControlPage Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + // } + // })); + // } + + // private void xtraTabControl1_CloseButtonClick(object sender, EventArgs e) + // { + // try + // { + // DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs EArg = (DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs)e; + // string name = EArg.Page.Text;//得到关闭的选项卡的text + // foreach (XtraTabPage page in xtraTabControl1.TabPages)//遍历得到和关闭的选项卡一样的Text + // { + // if (page.Text == name) + // { + // xtraTabControl1.TabPages.Remove(page); + + // foreach (Control item in page.Controls) + // { + // item.Dispose(); + // } + // page.Dispose(); + // return; + // } + // } + // } + // catch (Exception ex) + // { + // BaseForm.ShowError(ex); + // } + // } + // } + #endregion + public partial class system_douyin_action_control : DevExpress.XtraEditors.XtraUserControl + { + public system_douyin_action_control() + { + InitializeComponent(); + DouyinApi.douyinApiAction = DouyinApiAction; + } + + private static string DefaultTitle = "抖音扫码登录"; + + + private void DouyinApiAction(DouyinApi api) + { + api.IsQualifiedAction = IsQualifiedAction; + + bool falg = false; + var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + //判断是否已创建过 + this.Invoke(new Action(() => + { + foreach (XtraTabPage page in parentXtraTabControl.TabPages) + { + if (page.Text == "抖音活跃列表") + { + parentXtraTabControl.SelectedTabPage = page;//显示该页 + break; + } + } + + //判断是否已创建过 + foreach (XtraTabPage page in xtraTabControl1.TabPages) + { + if (!string.IsNullOrWhiteSpace(api.Member.username) && page.Text.StartsWith(api.Member.username)) + { + xtraTabControl1.SelectedTabPage = page;//显示该页 + return; + } + else if (string.IsNullOrWhiteSpace(api.Member.username) && page.Text == DefaultTitle) + { + falg = true; + BaseForm.ShowErrorAutoClose("已经存在扫码登录中的页面"); + return; + } + } + })); + + if (!falg) + { + var pageName = string.Empty; + if (!string.IsNullOrWhiteSpace(api.Member.username)) + { + pageName = $"{api.Member.username}_({api.Member.usernick})"; + } + //AddControlPage(pageName, api.chromeBrowser, global::FLSystem.Properties.Resources.抖音); + AddControlPage(pageName, api.webControl, global::FLSystem.Properties.Resources.抖音); + } + } + + /// <summary> + /// 是否满足账号权限 + /// </summary> + /// <param name="flag"></param> + private void IsQualifiedAction(DouyinLoginType type, DouyinApi api) + { + try + { + switch (type) + { + case DouyinLoginType.权限不足: + { + EventClient.OnEvent("", $"{api.Member.username}({api.Member.usernick}) 权限未开通,请开通后重试!"); + CpsClient.Members.Remove(api.Member); + //CpsClient.DelDouyinApi(api.Member.username); + this.Invoke(new Action(() => + { + var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + foreach (XtraTabPage page in parentXtraTabControl.TabPages) + { + if (page.Text == "抖音活跃列表") + { + parentXtraTabControl.SelectedTabPage = page;//显示该页 + break; + } + } + + ////判断是否已创建过 + //foreach (XtraTabPage page in xtraTabControl1.TabPages) + //{ + // if (page.Text == DefaultTitle) + // { + // xtraTabControl1.SelectedTabPage = page;//显示该页 + // api.chromeBrowser.Load("https://www.douyinec.com/"); + // return; + // } + //} + + XtraTabPage pageTmp = null; + + //判断是否已创建过 + foreach (XtraTabPage page in xtraTabControl1.TabPages) + { + if (page.Text == DefaultTitle) + { + pageTmp = page; + } + } + + if (pageTmp != null) + { + xtraTabControl1.TabPages.Remove(pageTmp); + //AddControlPage($"{api.Member.username}_({api.Member.usernick})", api.chromeBrowser, global::FLSystem.Properties.Resources.抖音); + } + })); + BaseForm.ShowErrorAutoClose($@"该账号未开通商品分享功能,请开通后重试 + +注:开通电商权限,需要同时满足以下4个条件 +①、账号实名认证 +②、个人主页视频数(公开且审核通过)≥ 10 条 +③、账号粉丝量(绑定第三方粉丝量不计数)≥ 1000 +④、商品分享保证金 ¥500立即充值", 120); + } + break; + case DouyinLoginType.登录过期: + { + EventClient.OnEvent("", $"抖音离线:{api.Member.username}({api.Member.usernick})"); + CpsClient.Members.Remove(api.Member); + //CpsClient.DelDouyinApi(api.Member.username); + this.Invoke(new Action(() => + { + var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + foreach (XtraTabPage page in parentXtraTabControl.TabPages) + { + if (page.Text == "抖音活跃列表") + { + parentXtraTabControl.SelectedTabPage = page;//显示该页 + break; + } + } + + ////判断是否已创建过 + //foreach (XtraTabPage page in xtraTabControl1.TabPages) + //{ + // if (page.Text == DefaultTitle) + // { + // xtraTabControl1.SelectedTabPage = page;//显示该页 + // api.chromeBrowser.Load("https://www.douyinec.com/"); + // return; + // } + //} + + XtraTabPage pageTmp = null; + + //判断是否已创建过 + foreach (XtraTabPage page in xtraTabControl1.TabPages) + { + if (page.Text == $"{api.Member.username}_({api.Member.usernick})") + { + pageTmp = page; + } + } + + if (pageTmp != null) + { + xtraTabControl1.TabPages.Remove(pageTmp); + //AddControlPage($"{api.Member.username}_({api.Member.usernick})", api.chromeBrowser, global::FLSystem.Properties.Resources.抖音); + } + })); + } + break; + case DouyinLoginType.登录成功: + case DouyinLoginType.新号登录成功: + { + this.Invoke(new Action(() => + { + //api.SkipOther("https://buyin.jinritemai.com/dashboard/dataCenter/export-list"); + + var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + foreach (XtraTabPage page in parentXtraTabControl.TabPages) + { + if (page.Text == "抖音活跃列表") + { + parentXtraTabControl.SelectedTabPage = page;//显示该页 + break; + } + } + + XtraTabPage pageTmp = null; + + if (type == DouyinLoginType.新号登录成功) + { + //判断是否已创建过 + foreach (XtraTabPage page in xtraTabControl1.TabPages) + { + if (page.Text == DefaultTitle) + { + pageTmp = page; + } + } + if (pageTmp != null) + { + xtraTabControl1.TabPages.Remove(pageTmp); + //AddControlPage($"{api.Member.username}_({api.Member.usernick})", api.chromeBrowser, global::FLSystem.Properties.Resources.抖音); + AddControlPage($"{api.Member.username}_({api.Member.usernick})", api.webControl, global::FLSystem.Properties.Resources.抖音, true); + } + } + else + { + if (pageTmp == null) + { + var def = xtraTabControl1.TabPages.FirstOrDefault(f => f.Text == DefaultTitle); + var notDef = xtraTabControl1.TabPages.FirstOrDefault(f => f.Text == $"{api.Member.username}_({api.Member.usernick})"); + + if (def != null) + { + if (notDef != null) + xtraTabControl1.TabPages.Remove(notDef); + + def.Text = $"{api.Member.username}_({api.Member.usernick})"; + //def.Enabled = false; + def.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + } + else if (notDef != null && def == null) + { + notDef.Text = $"{api.Member.username}_({api.Member.usernick})"; + //notDef.Enabled = false; + notDef.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + } + } + } + })); + } + break; + case DouyinLoginType.删除登录账号: + { + this.Invoke(new Action(() => + { + var parentXtraTabControl = this.Parent.Parent as XtraTabControl; + foreach (XtraTabPage page in parentXtraTabControl.TabPages) + { + if (page.Text == "抖音活跃列表") + { + parentXtraTabControl.SelectedTabPage = page;//显示该页 + break; + } + } + XtraTabPage pageTmp = null; + + //判断是否已创建过 + foreach (XtraTabPage page in xtraTabControl1.TabPages) + { + if (page.Text == $"{api.Member.username}_({api.Member.usernick})") + { + pageTmp = page; + } + } + + if (pageTmp != null) + { + xtraTabControl1.TabPages.Remove(pageTmp); + } + })); + } + break; + default: + break; + } + this.Invoke(new Action(() => + { + CpsClient.RefreshCps(); + EventClient.OnEvent(null, MethodType.刷新联盟); + })); + } + catch (Exception ex) + { + + } + } + + //增加选项夹 + private void AddControlPage(string pageName, Control control, Image img = null, bool isLoad = false) + { + this.Invoke(new Action(() => + { + try + { + //增加tabpage + XtraTabPage xpage = new XtraTabPage(); + + if (string.IsNullOrWhiteSpace(pageName)) + { + pageName = DefaultTitle; + control.Enabled = true; + xpage.ShowCloseButton = DevExpress.Utils.DefaultBoolean.True; + } + else + { + //if (isLoad) + // control.Enabled = false; + xpage.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + } + xpage.Name = pageName; + xpage.Text = pageName; + + if (img != null) + xpage.ImageOptions.Image = img; + //if (xpage.Text == "运行日志") + //xpage.ShowCloseButton = DevExpress.Utils.DefaultBoolean.False; + control.Dock = DockStyle.None; + control.Location = new Point(0, 0); + control.Size = new Size(1920, 1080); + + xpage.Controls.Add(control);//添加要增加的控件 + xtraTabControl1.TabPages.Add(xpage); + xtraTabControl1.SelectedTabPage = xpage;//显示该页 + } + catch (Exception ex) + { + if (ex.Message.Contains(@"“CefSharp.Core.Runtime.dll”或它的某一个依赖项")) + { + EventClient.OnEvent("系统缺少服务", $@"请点击链接,下载组件并安装,安装完成后重启软件 +下载地址:https://wwa.lanzoui.com/iDDvsroqrxc"); + try + { + Clipboard.SetDataObject("https://wwa.lanzoui.com/iDDvsroqrxc" + "?=" + new Random().Next(100, 2000)); + } + catch (Exception) + { } + + BaseForm.ShowError(@"当前系统缺少组件,请看软件日志,按提示安装相应的组件 + +下载地址已经复制到粘贴板,在网页中打开即可"); + } + else + XtraMessageBox.Show(ex.Message, "AddControlPage Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + })); + } + + private void xtraTabControl1_CloseButtonClick(object sender, EventArgs e) + { + try + { + DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs EArg = (DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs)e; + string name = EArg.Page.Text;//得到关闭的选项卡的text + foreach (XtraTabPage page in xtraTabControl1.TabPages)//遍历得到和关闭的选项卡一样的Text + { + if (page.Text == name) + { + xtraTabControl1.TabPages.Remove(page); + + foreach (Control item in page.Controls) + { + item.Dispose(); + } + page.Dispose(); + return; + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + } +} diff --git a/FLSystem/Forms/system_douyin_action_control.resx b/FLSystem/Forms/system_douyin_action_control.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Forms/system_douyin_action_control.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/system_log_control.Designer.cs b/FLSystem/Forms/system_log_control.Designer.cs new file mode 100644 index 0000000..0faab66 --- /dev/null +++ b/FLSystem/Forms/system_log_control.Designer.cs @@ -0,0 +1,105 @@ +namespace FLSystem.Forms +{ + partial class system_log_control + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.buttonCheck = new UI.Framework.Controls.ButtonCheck(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelControl1.Location = new System.Drawing.Point(580, 8); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 2; + this.labelControl1.Text = "滚动日志:"; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(738, 8); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(24, 14); + this.hyperlinkLabelControl1.TabIndex = 4; + this.hyperlinkLabelControl1.Text = "清空"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // richTextBox1 + // + this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richTextBox1.BackColor = System.Drawing.SystemColors.Control; + this.richTextBox1.Location = new System.Drawing.Point(3, 34); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ReadOnly = true; + this.richTextBox1.Size = new System.Drawing.Size(782, 492); + this.richTextBox1.TabIndex = 5; + this.richTextBox1.Text = ""; + // + // buttonCheck + // + this.buttonCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck.Checked = true; + this.buttonCheck.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck.Location = new System.Drawing.Point(653, 3); + this.buttonCheck.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck.Name = "buttonCheck"; + this.buttonCheck.Size = new System.Drawing.Size(62, 25); + this.buttonCheck.TabIndex = 21; + this.buttonCheck.Click += new System.EventHandler(this.buttonCheck1_Click); + // + // system_log_control + // + this.Appearance.BackColor = System.Drawing.Color.Transparent; + this.Appearance.Options.UseBackColor = true; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.buttonCheck); + this.Controls.Add(this.richTextBox1); + this.Controls.Add(this.hyperlinkLabelControl1); + this.Controls.Add(this.labelControl1); + this.Name = "system_log_control"; + this.Size = new System.Drawing.Size(788, 528); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private System.Windows.Forms.RichTextBox richTextBox1; + private UI.Framework.Controls.ButtonCheck buttonCheck; + } +} diff --git a/FLSystem/Forms/system_log_control.cs b/FLSystem/Forms/system_log_control.cs new file mode 100644 index 0000000..aea4171 --- /dev/null +++ b/FLSystem/Forms/system_log_control.cs @@ -0,0 +1,135 @@ +using Api.Framework; +using Chat.Framework; +using DevExpress.XtraEditors; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework.Events; + +namespace FLSystem.Forms +{ + public partial class system_log_control : DevExpress.XtraEditors.XtraUserControl + { + public system_log_control() + { + InitializeComponent(); + EventClient.LogEvent += EventClient_LogEvent; + ChatClient.Events.WXWriteLogEvent += Events_WXWriteLogEvent; + this.Disposed += System_log_control_Disposed; + this.is_roll = ApiClient.Setting.SystemConfig.show_debug_log; + this.buttonCheck.Checked = this.is_roll; + } + + private void System_log_control_Disposed(object sender, EventArgs e) + { + EventClient.LogEvent -= EventClient_LogEvent; + ChatClient.Events.WXWriteLogEvent -= Events_WXWriteLogEvent; + //tokenSource.Cancel(); + } + + private void Events_WXWriteLogEvent(object sender, Chat.Framework.WXSdk.Events.WXWriteLog e) + { + //if (e.Client.User != null && e.Client.User.Uin != 0) OnLog($"{e.Client.User.Nick}({e.Client.WeixinHao}):{e.Message}"); + //else OnLog(e.Message); + + if (e.Client.User != null && e.Client.User.Uin != 0) showLog($"{e.Client.User.Nick}({e.Client.WeixinHao}):{e.Message}"); + else showLog(e.Message); + + } + + public void showLog(string log) + { + this.SafeInvoke(() => + { + OnLog(log); + }); + } + + + private bool is_roll = true; + private void EventClient_LogEvent(object sender, Api.Framework.Events.LogEvents e) + { + //OnLog(e.Message); + //this.BeginInvoke(updateLog, e.Message); + try + { + showLog(e.Message); + } + catch (Exception ex) + { } + } + + private static object lock_log = new object(); + private void OnLog(string message) + { + try + { + var _msg = message; + try + { + string name = Api.Framework.Tools.Util.MapFile(DateTime.Now.ToString("yyyy-MM-dd") + ".log", "Cache\\系统日志"); + File.AppendAllLines(name, new string[] { DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-->" + _msg }); + } + catch + { } + + if (is_roll) + { + try + { + if (this.richTextBox1.Lines.Length > 1000) + this.richTextBox1.Text = ""; + if (!string.IsNullOrEmpty(this.richTextBox1.Text)) + this.richTextBox1.AppendText("\r\n"); + this.richTextBox1.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-->" + message); + this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length; + this.richTextBox1.ScrollToCaret(); + } + catch (Exception ex) + { } + + #region 老妖以前的 xxx + //this.Invoke(new Action(delegate + //{ + //try + //{ + // if (this.log_text.Lines.Length > 1000) + // this.log_text.Text = ""; + // if (!string.IsNullOrEmpty(this.log_text.Text)) + // this.log_text.Text += "\r\n"; + // this.log_text.Text += DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-->" + message; + // this.log_text.SelectionStart = this.log_text.Text.Length; + // this.log_text.ScrollToCaret(); + //} + //catch (Exception) + //{ } + //})); + #endregion + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void buttonCheck1_Click(object sender, EventArgs e) + { + try + { + this.is_roll = this.buttonCheck.Checked; + ApiClient.Setting.SystemConfig.show_debug_log = this.is_roll; + } + catch (Exception) + { } + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + //this.log_text.Text = ""; + this.richTextBox1.Text = ""; + } + } +} diff --git a/FLSystem/Forms/system_log_control.resx b/FLSystem/Forms/system_log_control.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Forms/system_log_control.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/tb_adzone_activity_group_form.Designer.cs b/FLSystem/Forms/tb_adzone_activity_group_form.Designer.cs new file mode 100644 index 0000000..0050c20 --- /dev/null +++ b/FLSystem/Forms/tb_adzone_activity_group_form.Designer.cs @@ -0,0 +1,495 @@ +namespace FLSystem.Forms +{ + partial class tb_adzone_activity_group_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(tb_adzone_activity_group_form)); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.label2 = new System.Windows.Forms.Label(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除勾选推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除全部推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.label4 = new System.Windows.Forms.Label(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl4 + // + this.groupControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl4.Controls.Add(this.labelControl2); + this.groupControl4.Controls.Add(this.label2); + this.groupControl4.Controls.Add(this.gridControl2); + this.groupControl4.Location = new System.Drawing.Point(627, 79); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(568, 495); + this.groupControl4.TabIndex = 59; + this.groupControl4.Text = "推广位列表"; + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(375, 3); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(184, 14); + this.labelControl2.TabIndex = 3; + this.labelControl2.Text = "点击单元格,即可直接增加或者修改"; + // + // label2 + // + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.ForeColor = System.Drawing.Color.Red; + this.label2.Location = new System.Drawing.Point(1, 117); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(563, 33); + this.label2.TabIndex = 2; + this.label2.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label2.Visible = false; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.gridControl2.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl2.Location = new System.Drawing.Point(0, 24); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(568, 471); + this.gridControl2.TabIndex = 0; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除勾选推广位ToolStripMenuItem, + this.删除全部推广位ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(161, 48); + // + // 删除勾选推广位ToolStripMenuItem + // + this.删除勾选推广位ToolStripMenuItem.Name = "删除勾选推广位ToolStripMenuItem"; + this.删除勾选推广位ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.删除勾选推广位ToolStripMenuItem.Text = "删除勾选推广位"; + this.删除勾选推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除勾选推广位ToolStripMenuItem_Click); + // + // 删除全部推广位ToolStripMenuItem + // + this.删除全部推广位ToolStripMenuItem.Name = "删除全部推广位ToolStripMenuItem"; + this.删除全部推广位ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.删除全部推广位ToolStripMenuItem.Text = "删除全部推广位"; + this.删除全部推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除全部推广位ToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn4, + this.gridColumn5, + this.gridColumn6, + this.gridColumn8, + this.gridColumn7}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsSelection.MultiSelect = true; + this.gridView2.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.CellValueChanging += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(this.gridView2_CellValueChanging); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn4 + // + this.gridColumn4.Caption = "阿里名称"; + this.gridColumn4.FieldName = "Member"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 112; + // + // gridColumn5 + // + this.gridColumn5.Caption = "推广位名称"; + this.gridColumn5.FieldName = "Name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 113; + // + // gridColumn6 + // + this.gridColumn6.Caption = "PID"; + this.gridColumn6.FieldName = "Pid"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 3; + this.gridColumn6.Width = 104; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this.gridColumn8.AppearanceCell.BackColor2 = System.Drawing.Color.LightGray; + this.gridColumn8.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn8.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn8.AppearanceCell.Options.UseBackColor = true; + this.gridColumn8.AppearanceCell.Options.UseFont = true; + this.gridColumn8.AppearanceCell.Options.UseForeColor = true; + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "淘口令"; + this.gridColumn8.FieldName = "Tkl"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.Width = 97; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this.gridColumn7.AppearanceCell.BackColor2 = System.Drawing.Color.LightGray; + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseBackColor = true; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "短连接"; + this.gridColumn7.FieldName = "ShortUrl"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + this.gridColumn7.Width = 143; + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.textBox1); + this.groupControl3.Controls.Add(this.label1); + this.groupControl3.Location = new System.Drawing.Point(627, 12); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(568, 61); + this.groupControl3.TabIndex = 61; + this.groupControl3.Text = "已选推广位"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(159, 28); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(203, 22); + this.textBox1.TabIndex = 49; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(100, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 50; + this.label1.Text = "组名称:"; + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.labelControl1); + this.groupControl2.Controls.Add(this.comboBoxEdit1); + this.groupControl2.Controls.Add(this.label4); + this.groupControl2.Location = new System.Drawing.Point(10, 12); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(606, 61); + this.groupControl2.TabIndex = 60; + this.groupControl2.Text = "账号选择"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(332, 33); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(246, 14); + this.labelControl1.TabIndex = 56; + this.labelControl1.Text = "(注意:推广位信息获取,需要先登录好淘宝账号)"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(126, 30); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(187, 20); + this.comboBoxEdit1.TabIndex = 55; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(53, 33); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 14); + this.label4.TabIndex = 47; + this.label4.Text = "操作账号:"; + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.label6); + this.groupControl1.Controls.Add(this.pageControl1); + this.groupControl1.Controls.Add(this.gridControl1); + this.groupControl1.Location = new System.Drawing.Point(10, 79); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(606, 495); + this.groupControl1.TabIndex = 58; + this.groupControl1.Text = "推广位列表"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(5, 117); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(594, 33); + this.label6.TabIndex = 2; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(2, 456); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(603, 36); + this.pageControl1.TabIndex = 1; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.gridControl1.Location = new System.Drawing.Point(0, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(606, 429); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.OptionsView.ShowIndicator = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.SelectionChanged += new DevExpress.Data.SelectionChangedEventHandler(this.gridView1_SelectionChanged); + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 200; + // + // gridColumn2 + // + this.gridColumn2.Caption = "PID"; + this.gridColumn2.FieldName = "pid"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 271; + // + // gridColumn3 + // + this.gridColumn3.Caption = "联盟昵称"; + this.gridColumn3.FieldName = "membernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 218; + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(645, 594); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(126, 32); + this.simpleButton3.TabIndex = 63; + this.simpleButton3.Text = " 取 消 "; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton1 + // + this.simpleButton1.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(449, 594); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(126, 32); + this.simpleButton1.TabIndex = 62; + this.simpleButton1.Text = " 确 认 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // tb_adzone_activity_group_form + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1207, 638); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.groupControl4); + this.Controls.Add(this.groupControl3); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.groupControl1); + this.Name = "tb_adzone_activity_group_form"; + this.Text = "tb_adzone_activity_group_form"; + this.Load += new System.EventHandler(this.tb_adzone_activity_group_form_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + this.groupControl4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + this.groupControl3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl4; + private System.Windows.Forms.Label label2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private System.Windows.Forms.Label label4; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.Label label6; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除勾选推广位ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除全部推广位ToolStripMenuItem; + private DevExpress.XtraEditors.LabelControl labelControl2; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/tb_adzone_activity_group_form.cs b/FLSystem/Forms/tb_adzone_activity_group_form.cs new file mode 100644 index 0000000..4c30c91 --- /dev/null +++ b/FLSystem/Forms/tb_adzone_activity_group_form.cs @@ -0,0 +1,320 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class tb_adzone_activity_group_form : BaseForm + { + public class view_alimama_form_select_tgw + { + public string name { get; set; } + public string pid { get; set; } + public string membernick { get; set; } + } + + SqlSugarClient session = null; + List<TuiguangweiActivity> tgws = null; + public fl_adzone_group adzone_group = null; + + public tb_adzone_activity_group_form(long id = 0) + { + try + { + InitializeComponent(); + session = ApiClient.GetSession(); + if (id == 0) + tgws = new List<TuiguangweiActivity>(); + else + { + adzone_group = session.Queryable<fl_adzone_group>().First(f => f.id == id); + if (adzone_group != null) + { + tgws = CsharpHttpHelper.HttpHelper.JsonToObject<List<TuiguangweiActivity>>(adzone_group.adzones) as List<TuiguangweiActivity>; + gridControl2.DataSource = tgws; + textBox1.Text = adzone_group.name; + } + else + tgws = new List<TuiguangweiActivity>(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + if (e.Column.AbsoluteIndex == -1) + { + var flag = e.CellValue.ToString().ToLower() != "true"; + var pid = gridView1.GetRowCellDisplayText(gridView1.FocusedRowHandle, gridView1.Columns["pid"]);//获取群号 + if (string.IsNullOrEmpty(pid)) throw new Exception("您当前没有选中任何一行!"); + var _tgw = tgws.FirstOrDefault(f => f.Pid == pid); + if (flag)//增加到集合中 + { + if (_tgw == null) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + _tgw = new TuiguangweiActivity() + { + Member = new fl_cps_member() { username = member.username, usernick = member.usernick }, + Name = gridView1.GetRowCellDisplayText(gridView1.FocusedRowHandle, gridView1.Columns["name"]), + Pid = pid + }; + tgws.Add(_tgw); + } + } + else + { + if (_tgw != null) + tgws.Remove(_tgw); + } + gridControl2.DataSource = null; + gridControl2.DataSource = tgws; + } + } + catch (Exception) + { } + } + + private void gridView1_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e) + { + try + { + if (e.ControllerRow < 0) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + var tgw_temp = tgws.Where(f => f.Member.username == member.username).ToList(); + foreach (var item in tgw_temp) + { + tgws.Remove(item); + } + if (gridView1.SelectedRowsCount != 0) + { + var list = gridControl1.DataSource as List<view_alimama_form_select_tgw>; + foreach (var item in list) + { + var _tgw = new TuiguangweiActivity() + { + Member = new fl_cps_member() { username = member.username, usernick = member.usernick }, + Name = item.name, + Pid = item.pid + }; + tgws.Add(_tgw); + } + } + gridControl2.DataSource = null; + gridControl2.DataSource = tgws; + } + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("组名称不能为空"); + if (gridView2.RowCount == 0) throw new Exception("请选择推广位"); + if (null != tgws.FirstOrDefault(f => string.IsNullOrWhiteSpace(f.ShortUrl))) throw new Exception("请填写短连接"); + + if (adzone_group == null) + adzone_group = new fl_adzone_group() { adzones = CsharpHttpHelper.HttpHelper.ObjectToJson(tgws), cps_type = CpsType.阿里妈妈, name = textBox1.Text.Trim(), remark = fl_alimama_activity_type.天猫精选.ToString() }; + else + { + adzone_group.adzones = CsharpHttpHelper.HttpHelper.ObjectToJson(tgws); + adzone_group.name = textBox1.Text.Trim(); + } + adzone_group = session.Saveable(adzone_group).ExecuteReturnEntity(); + this.DialogResult = System.Windows.Forms.DialogResult.OK; + } + catch (Exception ex) + { + if (ex.Message.Contains("UNIQUE constraint failed") || ex.Message.Contains("Duplicate entry")) + { + if (!this.IsDisposed) ShowError("推广位组名称已经存在"); + } + else + { + if (!this.IsDisposed) ShowError(ex); + } + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.No; + this.Close(); + } + + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "Member") + { + var cps = e.Value as fl_cps_member; + e.DisplayText = cps.usernick; + } + } + catch (Exception) + { } + } + + private void 删除勾选推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView2.GetSelectedRows().OrderByDescending(f => f).ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + foreach (var item in rownumber) + { + var _tgw = gridView2.GetRow(item) as TuiguangweiActivity; + tgws.Remove(_tgw); + } + gridControl2.DataSource = null; + gridControl2.DataSource = tgws; + this.pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + + } + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void 删除全部推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + tgws.Clear(); + gridControl2.DataSource = null; + this.pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void tb_adzone_activity_group_form_Load(object sender, EventArgs e) + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈).ToList(); + if (members == null || members.Count == 0) + { + ShowError("请先登录阿里妈妈后重试!"); + this.Close(); + return; + } + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + + this.pageControl1.Bind(delegate (int page, int pagesize) + { + try + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateAlimamaRequest(member); + var result = api.AdzoneManage(page, pagesize); + this.Invoke(new Action(() => + { + label6.Visible = false; + })); + var list = result["pagelist"] as ArrayList; + var _list = new List<view_alimama_form_select_tgw>(); + foreach (Dictionary<string, object> item in list) + { + _list.Add(new view_alimama_form_select_tgw() { pid = item["adzonePid"].ToString(), membernick = member.usernick, name = item["name"].ToString() }); + } + var paginator = result["paginator"] as Dictionary<string, object>; + + gridControl1.DataSource = _list; + #region 勾选已经选中的数据 + if (_list != null && tgws != null && tgws.Count != 0) + { + var _tgws = tgws.Where(f => f.Member.username == member.username).ToList(); + for (int i = 0; i < _tgws.Count; i++) + { + gridView1.SelectRow(_list.IndexOf(_list.FirstOrDefault(f => f.pid == _tgws[i].Pid))); + } + } + #endregion + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = int.Parse(paginator["items"].ToString()) }; + } + catch (Exception ex) + { + if (!this.IsDisposed) + this.UpdateUI(() => + { + label6.Visible = true; + label6.Text = ex.Message; + }); + } + return null; + + }, this.gridControl1, 40, true, true); + + this.comboBoxEdit1.Properties.Items.Clear(); + this.comboBoxEdit1.Properties.Items.AddRange(members); + this.comboBoxEdit1.SelectedIndex = 0; + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void gridView2_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e) + { + try + { + if (e.Column.Caption == "短连接") + { + if (string.IsNullOrWhiteSpace(e.Value.ToString())) + throw new Exception("短连接不能为空"); + var row = gridView2.GetRow(e.RowHandle) as TuiguangweiActivity; + row.ShortUrl = e.Value.ToString().Trim(); + row.Tkl = string.Empty; + } + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + } +} \ No newline at end of file diff --git a/FLSystem/Forms/tb_adzone_activity_group_form.resx b/FLSystem/Forms/tb_adzone_activity_group_form.resx new file mode 100644 index 0000000..91fb685 --- /dev/null +++ b/FLSystem/Forms/tb_adzone_activity_group_form.resx @@ -0,0 +1,220 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton3.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC +</value> + </data> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== +</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/tb_adzone_group_form.Designer.cs b/FLSystem/Forms/tb_adzone_group_form.Designer.cs new file mode 100644 index 0000000..7a4c62e --- /dev/null +++ b/FLSystem/Forms/tb_adzone_group_form.Designer.cs @@ -0,0 +1,446 @@ +namespace FLSystem.Forms +{ + partial class tb_adzone_group_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(tb_adzone_group_form)); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.label4 = new System.Windows.Forms.Label(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.label2 = new System.Windows.Forms.Label(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除勾选推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除全部推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.SuspendLayout(); + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.labelControl1); + this.groupControl2.Controls.Add(this.comboBoxEdit1); + this.groupControl2.Controls.Add(this.label4); + this.groupControl2.Location = new System.Drawing.Point(12, 12); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(609, 61); + this.groupControl2.TabIndex = 48; + this.groupControl2.Text = "账号选择"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(353, 33); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(246, 14); + this.labelControl1.TabIndex = 56; + this.labelControl1.Text = "(注意:推广位信息获取,需要先登录好淘宝账号)"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(126, 30); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(208, 20); + this.comboBoxEdit1.TabIndex = 55; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(53, 33); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 14); + this.label4.TabIndex = 47; + this.label4.Text = "操作账号:"; + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.label6); + this.groupControl1.Controls.Add(this.pageControl1); + this.groupControl1.Controls.Add(this.gridControl1); + this.groupControl1.Location = new System.Drawing.Point(12, 79); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(610, 481); + this.groupControl1.TabIndex = 47; + this.groupControl1.Text = "推广位列表"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(5, 117); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(594, 33); + this.label6.TabIndex = 2; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(2, 442); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(607, 36); + this.pageControl1.TabIndex = 1; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.gridControl1.Location = new System.Drawing.Point(0, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(610, 415); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.OptionsView.ShowIndicator = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.SelectionChanged += new DevExpress.Data.SelectionChangedEventHandler(this.gridView1_SelectionChanged); + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 200; + // + // gridColumn2 + // + this.gridColumn2.Caption = "PID"; + this.gridColumn2.FieldName = "pid"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 271; + // + // gridColumn3 + // + this.gridColumn3.Caption = "联盟昵称"; + this.gridColumn3.FieldName = "membernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 218; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(159, 28); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(203, 22); + this.textBox1.TabIndex = 49; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(100, 32); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 50; + this.label1.Text = "组名称:"; + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(626, 578); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(126, 32); + this.simpleButton3.TabIndex = 56; + this.simpleButton3.Text = " 取 消 "; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton1 + // + this.simpleButton1.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(430, 578); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(126, 32); + this.simpleButton1.TabIndex = 55; + this.simpleButton1.Text = " 确 认 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.textBox1); + this.groupControl3.Controls.Add(this.label1); + this.groupControl3.Location = new System.Drawing.Point(637, 12); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(490, 61); + this.groupControl3.TabIndex = 57; + this.groupControl3.Text = "已选推广位"; + // + // groupControl4 + // + this.groupControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl4.Controls.Add(this.label2); + this.groupControl4.Controls.Add(this.gridControl2); + this.groupControl4.Location = new System.Drawing.Point(637, 79); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(490, 481); + this.groupControl4.TabIndex = 48; + this.groupControl4.Text = "推广位列表"; + // + // label2 + // + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.ForeColor = System.Drawing.Color.Red; + this.label2.Location = new System.Drawing.Point(5, 117); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(480, 33); + this.label2.TabIndex = 2; + this.label2.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label2.Visible = false; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.gridControl2.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl2.Location = new System.Drawing.Point(0, 24); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(490, 457); + this.gridControl2.TabIndex = 0; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除勾选推广位ToolStripMenuItem, + this.删除全部推广位ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(161, 48); + // + // 删除勾选推广位ToolStripMenuItem + // + this.删除勾选推广位ToolStripMenuItem.Name = "删除勾选推广位ToolStripMenuItem"; + this.删除勾选推广位ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.删除勾选推广位ToolStripMenuItem.Text = "删除勾选推广位"; + this.删除勾选推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除勾选推广位ToolStripMenuItem_Click); + // + // 删除全部推广位ToolStripMenuItem + // + this.删除全部推广位ToolStripMenuItem.Name = "删除全部推广位ToolStripMenuItem"; + this.删除全部推广位ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.删除全部推广位ToolStripMenuItem.Text = "删除全部推广位"; + this.删除全部推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除全部推广位ToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn4, + this.gridColumn5, + this.gridColumn6}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.IndicatorWidth = 50; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsSelection.MultiSelect = true; + this.gridView2.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.OptionsView.ShowIndicator = false; + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn4 + // + this.gridColumn4.Caption = "阿里名称"; + this.gridColumn4.FieldName = "Member"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 200; + // + // gridColumn5 + // + this.gridColumn5.Caption = "推广位名称"; + this.gridColumn5.FieldName = "Name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 271; + // + // gridColumn6 + // + this.gridColumn6.Caption = "PID"; + this.gridColumn6.FieldName = "Pid"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 3; + this.gridColumn6.Width = 218; + // + // tb_adzone_group_form + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1139, 622); + this.Controls.Add(this.groupControl4); + this.Controls.Add(this.groupControl3); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.groupControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "tb_adzone_group_form"; + this.Text = "adzone_group_form"; + this.Load += new System.EventHandler(this.tb_adzone_group_form_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + this.groupControl3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private System.Windows.Forms.Label label4; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.Label label6; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.GroupControl groupControl3; + private DevExpress.XtraEditors.GroupControl groupControl4; + private System.Windows.Forms.Label label2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除勾选推广位ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除全部推广位ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/tb_adzone_group_form.cs b/FLSystem/Forms/tb_adzone_group_form.cs new file mode 100644 index 0000000..65fddd7 --- /dev/null +++ b/FLSystem/Forms/tb_adzone_group_form.cs @@ -0,0 +1,299 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraGrid.Views.Grid; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class tb_adzone_group_form : BaseForm + { + public class view_alimama_form_select_tgw + { + public string name { get; set; } + public string pid { get; set; } + public string membernick { get; set; } + } + + SqlSugarClient session = null; + List<Tuiguangwei> tgws = null; + public fl_adzone_group adzone_group = null; + + public tb_adzone_group_form(long id = 0) + { + try + { + InitializeComponent(); + session = ApiClient.GetSession(); + if (id == 0) + tgws = new List<Tuiguangwei>(); + else + { + adzone_group = session.Queryable<fl_adzone_group>().First(f => f.id == id); + if (adzone_group != null) + { + tgws = CsharpHttpHelper.HttpHelper.JsonToObject<List<Tuiguangwei>>(adzone_group.adzones) as List<Tuiguangwei>; + gridControl2.DataSource = tgws; + textBox1.Text = adzone_group.name; + } + else + tgws = new List<Tuiguangwei>(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + this.DialogResult = System.Windows.Forms.DialogResult.No; + this.Close(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("组名称不能为空"); + if (gridView2.RowCount == 0) throw new Exception("请选择推广位"); + if (adzone_group == null) + { + adzone_group = new fl_adzone_group() { adzones = CsharpHttpHelper.HttpHelper.ObjectToJson(tgws), cps_type = CpsType.阿里妈妈, name = textBox1.Text.Trim() }; + } + else + { + adzone_group.adzones = CsharpHttpHelper.HttpHelper.ObjectToJson(tgws); + adzone_group.name = textBox1.Text.Trim(); + } + adzone_group = session.Saveable(adzone_group).ExecuteReturnEntity(); + this.DialogResult = System.Windows.Forms.DialogResult.OK; + } + catch (Exception ex) + { + if (ex.Message.Contains("UNIQUE constraint failed") || ex.Message.Contains("Duplicate entry")) + ShowError("推广位组名称已经存在"); + else + ShowError(ex); + } + } + + private void tb_adzone_group_form_Load(object sender, EventArgs e) + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈).ToList(); + if (members == null || members.Count == 0) + { + ShowError("请先登录阿里妈妈后重试!"); + this.Close(); + return; + } + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + + this.pageControl1.Bind(delegate (int page, int pagesize) + { + try + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateAlimamaRequest(member); + var result = api.AdzoneManage(page, pagesize); + this.Invoke(new Action(() => + { + label6.Visible = false; + })); + var list = result["pagelist"] as ArrayList; + var _list = new List<view_alimama_form_select_tgw>(); + foreach (Dictionary<string, object> item in list) + { + _list.Add(new view_alimama_form_select_tgw() { pid = item["adzonePid"].ToString(), membernick = member.usernick, name = item["name"].ToString() }); + } + var paginator = result["paginator"] as Dictionary<string, object>; + + gridControl1.DataSource = _list; + #region 勾选已经选中的数据 + if (_list != null && tgws != null && tgws.Count != 0) + { + var _tgws = tgws.Where(f => f.Member.username == member.username).ToList(); + for (int i = 0; i < _tgws.Count; i++) + { + gridView1.SelectRow(_list.IndexOf(_list.FirstOrDefault(f => f.pid == _tgws[i].Pid))); + } + } + #endregion + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = int.Parse(paginator["items"].ToString()) }; + } + catch (Exception ex) + { + if (!this.IsDisposed) + this.UpdateUI(() => + { + label6.Visible = true; + label6.Text = ex.Message; + }); + } + return null; + + }, this.gridControl1, 40, true, true); + + this.comboBoxEdit1.Properties.Items.Clear(); + this.comboBoxEdit1.Properties.Items.AddRange(members); + this.comboBoxEdit1.SelectedIndex = 0; + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + if (e.Column.AbsoluteIndex == -1) + { + var flag = e.CellValue.ToString().ToLower() != "true"; + var pid = gridView1.GetRowCellDisplayText(gridView1.FocusedRowHandle, gridView1.Columns["pid"]);//获取群号 + if (string.IsNullOrEmpty(pid)) throw new Exception("您当前没有选中任何一行!"); + var _tgw = tgws.FirstOrDefault(f => f.Pid == pid); + if (flag)//增加到集合中 + { + if (_tgw == null) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + _tgw = new Tuiguangwei() + { + Member = new fl_cps_member() { username = member.username, usernick = member.usernick }, + Name = gridView1.GetRowCellDisplayText(gridView1.FocusedRowHandle, gridView1.Columns["name"]), + Pid = pid + }; + tgws.Add(_tgw); + } + } + else + { + if (_tgw != null) + tgws.Remove(_tgw); + } + gridControl2.DataSource = null; + gridControl2.DataSource = tgws; + } + } + catch (Exception) + { } + } + + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "Member") + { + var cps = e.Value as fl_cps_member; + e.DisplayText = cps.usernick; + } + } + catch (Exception) + { } + } + + private void 删除勾选推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView2.GetSelectedRows().OrderByDescending(f => f).ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + foreach (var item in rownumber) + { + var _tgw = gridView2.GetRow(item) as Tuiguangwei; + tgws.Remove(_tgw); + } + gridControl2.DataSource = null; + gridControl2.DataSource = tgws; + this.pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除全部推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + tgws.Clear(); + gridControl2.DataSource = null; + this.pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e) + { + try + { + if (e.ControllerRow < 0) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + var tgw_temp = tgws.Where(f => f.Member.username == member.username).ToList(); + foreach (var item in tgw_temp) + { + tgws.Remove(item); + } + if (gridView1.SelectedRowsCount != 0) + { + var list = gridControl1.DataSource as List<view_alimama_form_select_tgw>; + foreach (var item in list) + { + var _tgw = new Tuiguangwei() + { + Member = new fl_cps_member() { username = member.username, usernick = member.usernick }, + Name = item.name, + Pid = item.pid + }; + tgws.Add(_tgw); + } + } + gridControl2.DataSource = null; + gridControl2.DataSource = tgws; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} \ No newline at end of file diff --git a/FLSystem/Forms/tb_adzone_group_form.resx b/FLSystem/Forms/tb_adzone_group_form.resx new file mode 100644 index 0000000..51c44fe --- /dev/null +++ b/FLSystem/Forms/tb_adzone_group_form.resx @@ -0,0 +1,223 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton3.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC +</value> + </data> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== +</value> + </data> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>54</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/tlj_form.Designer.cs b/FLSystem/Forms/tlj_form.Designer.cs new file mode 100644 index 0000000..d2c2b92 --- /dev/null +++ b/FLSystem/Forms/tlj_form.Designer.cs @@ -0,0 +1,265 @@ +namespace FLSystem.Forms +{ + partial class tlj_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(53, 106); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(90, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "淘礼金AppKey:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(37, 137); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(106, 14); + this.labelControl2.TabIndex = 0; + this.labelControl2.Text = "淘礼金AppSecret:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(35, 171); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(108, 14); + this.labelControl3.TabIndex = 0; + this.labelControl3.Text = "淘礼金推广位昵称:"; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(149, 103); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(319, 20); + this.textEdit1.TabIndex = 1; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(149, 134); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(319, 20); + this.textEdit2.TabIndex = 2; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(149, 242); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(102, 30); + this.simpleButton1.TabIndex = 4; + this.simpleButton1.Text = " 确 定 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(297, 242); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(102, 30); + this.simpleButton2.TabIndex = 4; + this.simpleButton2.Text = " 取 消 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.textEdit4); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl11); + this.groupBox1.Controls.Add(this.labelControl10); + this.groupBox1.Controls.Add(this.labelControl9); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.textEdit3); + this.groupBox1.Controls.Add(this.textEdit2); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl6); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Location = new System.Drawing.Point(37, 31); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(499, 301); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 淘礼金基础设置 "; + // + // textEdit3 + // + this.textEdit3.Location = new System.Drawing.Point(149, 165); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Size = new System.Drawing.Size(319, 20); + this.textEdit3.TabIndex = 3; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(83, 75); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(60, 14); + this.labelControl4.TabIndex = 0; + this.labelControl4.Text = "淘宝昵称:"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(161, 75); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(24, 14); + this.labelControl5.TabIndex = 5; + this.labelControl5.Text = "昵称"; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(83, 44); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(60, 14); + this.labelControl6.TabIndex = 0; + this.labelControl6.Text = "淘宝账号:"; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(161, 44); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(24, 14); + this.labelControl7.TabIndex = 5; + this.labelControl7.Text = "账号"; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(149, 196); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(319, 20); + this.textEdit4.TabIndex = 7; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(43, 199); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(100, 14); + this.labelControl8.TabIndex = 6; + this.labelControl8.Text = "淘礼金推广位Pid:"; + // + // labelControl9 + // + this.labelControl9.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl9.Appearance.Options.UseForeColor = true; + this.labelControl9.Location = new System.Drawing.Point(469, 199); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(7, 14); + this.labelControl9.TabIndex = 5; + this.labelControl9.Text = "*"; + // + // labelControl10 + // + this.labelControl10.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl10.Appearance.Options.UseForeColor = true; + this.labelControl10.Location = new System.Drawing.Point(474, 137); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(7, 14); + this.labelControl10.TabIndex = 5; + this.labelControl10.Text = "*"; + // + // labelControl11 + // + this.labelControl11.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl11.Appearance.Options.UseForeColor = true; + this.labelControl11.Location = new System.Drawing.Point(474, 106); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(7, 14); + this.labelControl11.TabIndex = 5; + this.labelControl11.Text = "*"; + // + // tlj_form + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(573, 363); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "tlj_form"; + this.Text = "淘礼金设置"; + this.Load += new System.EventHandler(this.tlj_form_Load); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.TextEdit textEdit3; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraEditors.LabelControl labelControl11; + private DevExpress.XtraEditors.LabelControl labelControl10; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/tlj_form.cs b/FLSystem/Forms/tlj_form.cs new file mode 100644 index 0000000..9ab523e --- /dev/null +++ b/FLSystem/Forms/tlj_form.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Api.Framework; +using Api.Framework.Tools; +using Api.Framework.Model; +using SqlSugar; + +namespace FLSystem.Forms +{ + public partial class tlj_form : BaseForm + { + private string cpsnick; + private string cpsname; + public tlj_form(string cpsnick, string cpsname) + { + InitializeComponent(); + this.labelControl5.Text = this.cpsnick = cpsnick; + this.labelControl7.Text = this.cpsname = cpsname; + } + + private void tlj_form_Load(object sender, EventArgs e) + { + GetTlj(); + if (tlj != null) + { + textEdit1.Text = tlj.appkey; + textEdit2.Text = tlj.appsecret; + textEdit3.Text = tlj.adzone_name; + textEdit4.Text = tlj.adzone_pid; + } + } + + private fl_alimama_tlj_info tlj = null; + private SqlSugarClient session = null; + + private void GetTlj() + { + session = ApiClient.GetSession(); + var tljs = session.FindTljInfos(true); + tlj = tljs.FirstOrDefault(f => f.username == cpsname); + return; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (tlj == null) + tlj = new fl_alimama_tlj_info() { username = cpsname }; + tlj.appkey = textEdit1.Text.Trim(); + tlj.appsecret = textEdit2.Text.Trim(); + tlj.adzone_name = textEdit3.Text.Trim(); + tlj.adzone_pid = textEdit4.Text.Trim(); + session.Saveable(tlj).ExecuteCommand(); + ShowSuccessAutoClose($"操作成功"); + this.Close(); + } + catch (Exception ex) + { + ShowErrorAutoClose($"操作失败:{ex.Message}"); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.Close(); + } + + } +} \ No newline at end of file diff --git a/FLSystem/Forms/tlj_form.resx b/FLSystem/Forms/tlj_form.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/tlj_form.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/update_log_form.Designer.cs b/FLSystem/Forms/update_log_form.Designer.cs new file mode 100644 index 0000000..609574e --- /dev/null +++ b/FLSystem/Forms/update_log_form.Designer.cs @@ -0,0 +1,64 @@ +namespace FLSystem.Forms +{ + partial class update_log_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.SuspendLayout(); + // + // richTextBox1 + // + this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.richTextBox1.Font = new System.Drawing.Font("Tahoma", 12F); + this.richTextBox1.Location = new System.Drawing.Point(0, 0); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ReadOnly = true; + this.richTextBox1.Size = new System.Drawing.Size(526, 545); + this.richTextBox1.TabIndex = 0; + this.richTextBox1.Text = ""; + // + // update_log_form + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(526, 545); + this.Controls.Add(this.richTextBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "update_log_form"; + this.Text = " 更 新 摘 要 "; + this.Load += new System.EventHandler(this.update_log_form_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.RichTextBox richTextBox1; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/update_log_form.cs b/FLSystem/Forms/update_log_form.cs new file mode 100644 index 0000000..3d2925d --- /dev/null +++ b/FLSystem/Forms/update_log_form.cs @@ -0,0 +1,50 @@ +using Api.Framework.Tools; +using System; +using System.Drawing; +using System.IO; +using System.Text.RegularExpressions; +using UI.Framework.Forms; +using UI.Framework.Tools; + +namespace FLSystem.Forms +{ + public partial class update_log_form : BaseForm + { + public update_log_form() + { + InitializeComponent(); + } + + private void update_log_form_Load(object sender, EventArgs e) + { + try + { + //var path = Util.MapFile("Update.log", @"Cache"); + //if (File.Exists(path)) + //{ + // StreamReader sr = new StreamReader(path); + // string content; + // while ((content = sr.ReadLine()) != null) + // { + // if (Regex.IsMatch(content.Trim(), @"^(?<版本>\d{4}\.\d{1,2}\.\d{1,2}\.\d{1,2})$")) + // richTextBox1.AppendTextColorful(content.Trim(), ColorTranslator.FromHtml("#0000FF")); + // else + // richTextBox1.AppendTextColorful(content.Trim(), ColorTranslator.FromHtml("#363636")); + // } + + // this.richTextBox1.SelectionStart =0; + // this.richTextBox1.ScrollToCaret(); + //} + //else richTextBox1.AppendTextColorful("暂无更新内容", Color.Red); + + richTextBox1.AppendTextColorful("暂不支持查看更新内容", Color.Red); + + + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/FLSystem/Forms/update_log_form.resx b/FLSystem/Forms/update_log_form.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/FLSystem/Forms/update_log_form.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/FLSystem/Forms/web_api_form.Designer.cs b/FLSystem/Forms/web_api_form.Designer.cs new file mode 100644 index 0000000..f35881a --- /dev/null +++ b/FLSystem/Forms/web_api_form.Designer.cs @@ -0,0 +1,165 @@ +namespace FLSystem.Forms +{ + partial class web_api_form + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(web_api_form)); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.textBox2 = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(126, 97); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(261, 22); + this.textBox1.TabIndex = 7; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(52, 100); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(59, 14); + this.labelControl4.TabIndex = 6; + this.labelControl4.Text = "服务器IP:"; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(177, 196); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(133, 33); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "启动API服务器"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl3 + // + this.labelControl3.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl3.Appearance.Options.UseForeColor = true; + this.labelControl3.Location = new System.Drawing.Point(203, 40); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(184, 14); + this.labelControl3.TabIndex = 4; + this.labelControl3.Text = "(云服务器,需在安全组放行端口)"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(126, 38); + this.numericUpDown1.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(71, 22); + this.numericUpDown1.TabIndex = 2; + this.numericUpDown1.Value = new decimal(new int[] { + 80, + 0, + 0, + 0}); + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(64, 40); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(48, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "端口号:"; + // + // labelControl1 + // + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(24, 250); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(411, 14); + this.labelControl1.TabIndex = 8; + this.labelControl1.Text = "注意:二次开发时,可以监听事件WebRequestEvent 可获取请求,再作出响应"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(52, 153); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(60, 14); + this.labelControl5.TabIndex = 9; + this.labelControl5.Text = "可读域名:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(126, 150); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(261, 22); + this.textBox2.TabIndex = 10; + // + // web_api_form + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(456, 281); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.labelControl5); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.labelControl4); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.labelControl3); + this.Controls.Add(this.numericUpDown1); + this.Controls.Add(this.labelControl2); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "web_api_form"; + this.Text = "WebApi 服务器"; + this.Load += new System.EventHandler(this.web_api_form_Load); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private System.Windows.Forms.TextBox textBox2; + } +} \ No newline at end of file diff --git a/FLSystem/Forms/web_api_form.cs b/FLSystem/Forms/web_api_form.cs new file mode 100644 index 0000000..4b0f8c4 --- /dev/null +++ b/FLSystem/Forms/web_api_form.cs @@ -0,0 +1,60 @@ +using Api.Framework; +using Api.Framework.Tools; +using System; +using UI.Framework.Forms; + +namespace FLSystem.Forms +{ + public partial class web_api_form : BaseForm + { + public web_api_form() + { + InitializeComponent(); + } + + + /// <summary> + /// 刷新按钮状态 + /// </summary> + private void RefStatus() + { + this.simpleButton1.Text = WebClient.IsStart ? "关闭服务器" : "启动服务器"; + + ApiClient.Setting.ServerConfig.IsOpen = WebClient.IsStart; + this.numericUpDown1.Enabled = this.textBox1.Enabled = !WebClient.IsStart; + } + private void web_api_form_Load(object sender, EventArgs e) + { + try + { + var config = ApiClient.Setting.ServerConfig; + this.textBox1.Text = config.Host; + this.textBox2.Text = config.Domain; + this.numericUpDown1.Value = config.Port; + RefStatus(); + Util.Save(ApiClient.Setting.ServerConfig); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + ApiClient.Setting.ServerConfig.Domain = this.textBox2.Text; + if (WebClient.IsStart) WebClient.Close(); + else WebClient.Start(this.textBox1.Text, (int)this.numericUpDown1.Value); + RefStatus(); + Util.Save(ApiClient.Setting.ServerConfig); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + } +} \ No newline at end of file diff --git a/FLSystem/Forms/web_api_form.resx b/FLSystem/Forms/web_api_form.resx new file mode 100644 index 0000000..1fef426 --- /dev/null +++ b/FLSystem/Forms/web_api_form.resx @@ -0,0 +1,154 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAkdEVYdFRpdGxlAFNlcnZlck1vZGU7U2VydmVyO1BD + O0NvbXB1dGVyO3LY4GcAAAVXSURBVFhHrZdZUxRnGIUlccVdzPIPkov8mvyD3OTWm1R5FzVgjAkIBmWR + nRFkSzSWFYSYoIFBWUwKk1Qq5QgMy7DMDLPP9MyAb855uxsHRJqxmKqn3p6m5zvnO+/3dTd7RESxP3cH + PCwFFu+CfRb784S/2QveAQUtd56hmB9bU3U3G8CHwvzRvp6+f76CIXlb6jpHizEOzagJoB8nAype3fKo + 2P10WnyBhLzwRV/DM78VkXXm8bv+wf+kpPxuCcbbYGI7A7xgb6745BbibzZgY5qY22iCLdmRgf2N3aM4 + tXuf+o4RChwETGFbA7zgQFPXmCRTWQmGUxLIJbQRP6t1nsf+UFKWV5JmtY6jibTcaH9MgUPW+I4GDjZ0 + jUp29aUkjTVJplclboD0mtYEzsUVnEuSrMRY8Z2VRHEuqnVVUvhdbZsaKATcVY4GDjGyTNYUau0Zk9bu + cWnpHnuNZrSq2a4wTZq6R6SpC3SOSCSRkRTGqHYNU+Aw2JmBOhgw1MCqtP/0p84ilXmp1UgjGQXpMCEj + q6kwqYQmRLJy8/a4ROIZ/VuVy52XgcK6W0/EyKxpnO13/pBYyooXNaowYmDVCMFsKWjj+mFcwvG0mqlq + GaLAEeBogBccZs8MzDCaWJW2208tMQysvUVNoFLQIhzPAlM4FDNp7RmXlVgaayQj15oH8zNQg54x7ggG + diFK148AM2JtJTi2aYGQVq4TrJdmwnWBnRSMptV8ZePvFDhqje9o4EhVq1t7ygg5eAJRkxjBgMSOX49z + YDqkqXMUW9TQpK42PMrPwHX0jDsgHMvqjFY02jQizWisKxEemzWwCb9FIxaynwbw24r6hxQ4BvhwcjRw + tBI9i2PxMMImxLkuhu+vRHkTMquf4NiPm5JNQ8cT3IxSujbK6wYocBzs0AB6FjMyEowZ2NOj0og9rWBW + uccUaQSsDR2Ppf7WRhZXUkjOkLLa3/IycIw9i6F37CGF2FOu9BBqCCmEsDYUJmLB42DUQEokLXVtw7IQ + SEoIaZXW/EqBE8DRAC84zp5xezFCzmwJkRLOaMliAff5BdYgKvBBTPGzJqT2plu/ByKGfFv1gAInrfGd + DVxBz7inl2Cgvn04R9BkXQzwuW8Slzk/sGqNawg1oQ+ry9d/ycvAibLaAb2ZcMY32twmmBHhzEyGIOKW + GtRqiFGwunXwFS2DaoQL8vI1NXAK8J3A0cBJ9kwNYIbcx7rHWbfAvBumlbCCOyMr1sjsUhwpJuVSZT8F + isDODHxX/UAXFHvpQ4zzgLOZZ8TWsV1nCYRmNuFdiol3MSaLWB9ff9+Xl4FT7FkQi8fury1IsRkKLqO3 + 2PucJevsUkJmIOa1hHk8jTq9GBcfDFy8ep8Cp4GjAV5Q9A16xpvLLEU3zYxwZff/XSYl9z6S3olSXGvI + FMQoOkVxgvfGqYWoplZS0ZtroMDRwKXKPt2CpiBmhMo47Zlx33/Z9YmcnSuUs66P9WZDsSlLlHXSF9Fj + pldc/jMF3rPGdzRwmj3jFmSEFJxBtWfGQZfDSWnuPy+fniuSht5zalbFwQsIE75Ne1C9y3G5cEUNvG+N + /0YDfCNWAxcr7mvvpjkbG3t2wAvCeD7wbYhp8Dp9FYegB9c9t17Pn+Mck7tQtm6A/x84G2DPfMHEhkjN + /wc4O3NmKqQ1YgmizvEYzOI8YGVq50vv5WWgiD2b9MXkr8kQCOQQkgkPeBGQZ2DC48y/3hXbgOMaoAF9 + GH12pu7h51+4ZLfgeBjXfhpuuwj5UsqY+PLAbfPBJj58Cxg9xQ8Ajr+uuZUBpsCL6JRx0cxuwPE4LsfP + MSB7/gewyEBZy6qOBQAAAABJRU5ErkJggg== +</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/MainEvent.cs b/FLSystem/MainEvent.cs new file mode 100644 index 0000000..c81cea3 --- /dev/null +++ b/FLSystem/MainEvent.cs @@ -0,0 +1,23 @@ +using FLSystem.Events; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FLSystem +{ + public class MainEvent + { + public static event EventHandler<CommonEvents> CommonEvents; + + public static void OnEvent(object sender, CommonEvents e) + { + if (CommonEvents != null) + { + CommonEvents.Invoke(sender, e); + } + } + + } +} diff --git a/FLSystem/MouseKeyHook.cs b/FLSystem/MouseKeyHook.cs new file mode 100644 index 0000000..37d3874 --- /dev/null +++ b/FLSystem/MouseKeyHook.cs @@ -0,0 +1,359 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.Reflection; +using System.ComponentModel; + +namespace GeneralFramework +{ + public class MouseKeyHook + { + [StructLayout(LayoutKind.Sequential)] + private class POINT + { + public int x; + public int y; + } + + [StructLayout(LayoutKind.Sequential)] + private class MouseHookStruct + { + public POINT pt; + public int hwnd; + public int wHitTestCode; + public int dwExtraInfo; + } + [StructLayout(LayoutKind.Sequential)] + private class MouseLLHookStruct + { + public POINT pt; + public int mouseData; + public int flags; + public int time; + public int dwExtraInfo; + } + [StructLayout(LayoutKind.Sequential)] + private class KeyboardHookStruct + { + public int vkCode; + public int scanCode; + public int flags; + public int time; + public int dwExtraInfo; + } + [DllImport("kernel32.dll")] + static extern int GetCurrentThreadId(); //ȡõǰ̱߳ŵAPI + + [DllImport("user32.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall, SetLastError = true)] + private static extern int SetWindowsHookEx( + + int idHook, + + HookProc lpfn, + + IntPtr hMod, + + int dwThreadId); + + [DllImport("user32.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall, SetLastError = true)] + private static extern int UnhookWindowsHookEx(int idHook); + [DllImport("user32.dll", CharSet = CharSet.Auto, + CallingConvention = CallingConvention.StdCall)] + private static extern int CallNextHookEx( + + int idHook, + + int nCode, + + int wParam, + + IntPtr lParam); + private delegate int HookProc(int nCode, int wParam, IntPtr lParam); + [DllImport("user32")] + private static extern int ToAscii( + + int uVirtKey, + + int uScanCode, + + byte[] lpbKeyState, + + byte[] lpwTransKey, + + int fuState); + [DllImport("user32")] + private static extern int GetKeyboardState(byte[] pbKeyState); + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + private static extern short GetKeyState(int vKey); + private const int WH_MOUSE_LL = 14; + private const int WH_KEYBOARD_LL = 13; + private const int WH_MOUSE = 7; + private const int WH_KEYBOARD = 2; + private const int WM_MOUSEMOVE = 0x200; + private const int WM_LBUTTONDOWN = 0x201; + private const int WM_RBUTTONDOWN = 0x204; + private const int WM_MBUTTONDOWN = 0x207; + private const int WM_LBUTTONUP = 0x202; + private const int WM_RBUTTONUP = 0x205; + private const int WM_MBUTTONUP = 0x208; + private const int WM_LBUTTONDBLCLK = 0x203; + private const int WM_RBUTTONDBLCLK = 0x206; + private const int WM_MBUTTONDBLCLK = 0x209; + private const int WM_MOUSEWHEEL = 0x020A; + private const int WM_KEYDOWN = 0x100; + private const int WM_KEYUP = 0x101; + private const int WM_SYSKEYDOWN = 0x104; + private const int WM_SYSKEYUP = 0x105; + private const byte VK_SHIFT = 0x10; + private const byte VK_CAPITAL = 0x14; + private const byte VK_NUMLOCK = 0x90; + + + public MouseKeyHook() + { + + Start(); + + } + public MouseKeyHook(bool InstallMouseHook, bool InstallKeyboardHook) + { + + Start(InstallMouseHook, InstallKeyboardHook); + + } + ~MouseKeyHook() + { + + Stop(true, true, false); + + } + public event MouseEventHandler OnMouseActivity; + public event KeyEventHandler KeyDown; + public event KeyPressEventHandler KeyPress; + public event KeyEventHandler KeyUp; + private int hMouseHook = 0; + private int hKeyboardHook = 0; + private static HookProc MouseHookProcedure; + private static HookProc KeyboardHookProcedure; + public void Start() + { + + this.Start(true, true); + + } + public void Start(bool InstallMouseHook, bool InstallKeyboardHook) + { + + if (hMouseHook == 0 && InstallMouseHook) + { + + MouseHookProcedure = new HookProc(MouseHookProc); + + hMouseHook = SetWindowsHookEx( + + WH_MOUSE, + + MouseHookProcedure, + + IntPtr.Zero, + + GetCurrentThreadId()); + + if (hMouseHook == 0) + { + + int errorCode = Marshal.GetLastWin32Error(); + + Stop(true, false, false); + + //throw new Win32Exception(errorCode); + + } + + } + + + + if (hKeyboardHook == 0 && InstallKeyboardHook) + { + + KeyboardHookProcedure = new HookProc(KeyboardHookProc); + + hKeyboardHook = SetWindowsHookEx( + + WH_KEYBOARD, + + KeyboardHookProcedure, + + IntPtr.Zero, + + GetCurrentThreadId()); + + if (hKeyboardHook == 0) + { + + int errorCode = Marshal.GetLastWin32Error(); + + Stop(false, true, false); + + //throw new Win32Exception(errorCode); + + } + + } + + } + + + + public void Stop() + { + + this.Stop(true, true, true); + + } + + + + public void Stop(bool UninstallMouseHook, bool UninstallKeyboardHook, bool ThrowExceptions) + { + + if (hMouseHook != 0 && UninstallMouseHook) + { + + int retMouse = UnhookWindowsHookEx(hMouseHook); + + hMouseHook = 0; + + if (retMouse == 0 && ThrowExceptions) + { + + int errorCode = Marshal.GetLastWin32Error(); + + throw new Win32Exception(errorCode); + + } + + } + + + + if (hKeyboardHook != 0 && UninstallKeyboardHook) + { + + int retKeyboard = UnhookWindowsHookEx(hKeyboardHook); + + hKeyboardHook = 0; + + if (retKeyboard == 0 && ThrowExceptions) + { + + int errorCode = Marshal.GetLastWin32Error(); + + throw new Win32Exception(errorCode); + + } + + } + + } + + + + + + private int MouseHookProc(int nCode, int wParam, IntPtr lParam) + { + + if ((nCode >= 0) && (OnMouseActivity != null)) + { + + MouseLLHookStruct mouseHookStruct = (MouseLLHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseLLHookStruct)); + + + + MouseButtons button = MouseButtons.None; + + short mouseDelta = 0; + + switch (wParam) + { + + case WM_LBUTTONDOWN: + + button = MouseButtons.Left; + + break; + + case WM_RBUTTONDOWN: + + button = MouseButtons.Right; + + break; + + case WM_MOUSEWHEEL: + + mouseDelta = (short)((mouseHookStruct.mouseData >> 16) & 0xffff); + + break; + + } + + + + int clickCount = 0; + + if (button != MouseButtons.None) + + if (wParam == WM_LBUTTONDBLCLK || wParam == WM_RBUTTONDBLCLK) clickCount = 2; + + else clickCount = 1; + + + + MouseEventArgs e = new MouseEventArgs( + + button, + + clickCount, + + mouseHookStruct.pt.x, + + mouseHookStruct.pt.y, + + mouseDelta); + + OnMouseActivity(this, e); + + } + + return CallNextHookEx(hMouseHook, nCode, wParam, lParam); + + } + + + + private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) + { + try + { + if (nCode < 0) + { + return CallNextHookEx(hMouseHook, nCode, wParam, lParam); + } + + KeyDown(this, null); + + return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); + } + catch (Exception ex) + { + return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); + } + } + } +} diff --git a/FLSystem/Program.cs b/FLSystem/Program.cs new file mode 100644 index 0000000..d035199 --- /dev/null +++ b/FLSystem/Program.cs @@ -0,0 +1,504 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Tools; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using FLSystem.Forms; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows.Threading; +using System.Xml; +using UI.Framework.Forms; + +namespace FLSystem +{ + static class Program + { + [DllImport("User32.dll")] + public static extern int PrivateExtractIcons( + string lpszFile, //文件名可以是exe,dll,ico,cur,ani,bmp + int nIconIndex, //从第几个图标开始获取 + int cxIcon, //获取图标的尺寸x + int cyIcon, //获取图标的尺寸y + IntPtr[] phicon, //获取到的图标指针数组 + int[] piconid, //图标对应的资源编号 + int nIcons, //指定获取的图标数量,仅当文件类型为.exe 和 .dll时候可用 + int flags //标志,默认0就可以,具体可以看LoadImage函数 +); + + [DllImport("User32.dll")] + public static extern bool DestroyIcon( + IntPtr hIcon //A handle to the icon to be destroyed. The icon must not be in use. + ); + + private static System.Drawing.Icon _ico; + public static System.Drawing.Icon ReadICO() + { + if (_ico != null) return _ico; + try + { + bool is_next = false; + NEXT: + DirectoryInfo info = new DirectoryInfo(Util.MapPath()); + var files = info.GetFiles("*.exe"); + foreach (var data in files) + { + var file = data.FullName; + if (file.EndsWith("FLSystem.exe")) continue; + if (file.EndsWith("ZipExtract.exe")) continue; + if (file.EndsWith("FLSystemMonitor.exe")) continue; + if (file.EndsWith("LevelUpdate.exe")) continue; + if (file.EndsWith("OnlineUpdate.exe")) continue; + if (file.EndsWith("VersionUpdate.exe")) continue; + //if (file.EndsWith("软件异常点我修复.exe")) continue; + if (file.EndsWith("检查更新.exe")) continue; + if (data.Name.Replace(".exe", "").ToLower().Contains("net")) continue; + + //选中文件中的图标总数 + var iconTotalCount = PrivateExtractIcons(file, 0, 0, 0, null, null, 0, 0); + + //用于接收获取到的图标指针 + IntPtr[] hIcons = new IntPtr[iconTotalCount]; + //对应的图标id + int[] ids = new int[iconTotalCount]; + //成功获取到的图标个数 + var successCount = PrivateExtractIcons(file, 0, 256, 256, hIcons, ids, iconTotalCount, 0); + + //遍历并保存图标 + for (var i = 0; i < successCount; i++) + { + //指针为空,跳过 + if (hIcons[i] == IntPtr.Zero) continue; + _ico = System.Drawing.Icon.FromHandle(hIcons[i]); + return _ico; + //内存回收 + //DestroyIcon(hIcons[i]); + } + } + + if (!is_next) + { + var exe = Util.MapFile("返利机器人.exe"); + if (!File.Exists(exe)) + { + File.WriteAllBytes(exe, FLSystem.Properties.Resources.返利机器人); + goto NEXT; + } + } + } + catch (Exception) + { + } + _ico = Properties.Resources.exe; + return _ico; + } + + /// <summary> + /// 过滤特殊字符,保留中文,字母,数字,和- + /// </summary> + /// <param name="inputValue">输入字符串</param> + /// <remarks>发件和收件详细地址有这种情况:“仓场路40-73号迎园新村四坊69号202室”,这种带有-的特殊字符不需要过滤掉</remarks> + /// <returns></returns> + public static string FilterChar(string inputValue) + { + // return Regex.Replace(inputValue, "[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()—|{}【】;‘’,。/*-+]+", "", RegexOptions.IgnoreCase); + if (Regex.IsMatch(inputValue, "[A-Za-z0-9\u4e00-\u9fa5-]+")) + { + return Regex.Match(inputValue, "[A-Za-z0-9\u4e00-\u9fa5-]+").Value; + } + return ""; + } + + /// <summary> + /// The main entry point for the application. + /// </summary> + [STAThread] + static void Main() + { + //var sign = HttpExtend.GetMD5String("Cc"+ "_*54R56@%"); + + + //var ss = Util.DecryptDES("lKMvY5Nw0DjddL2gR2Fhu6GFlMehR0ej70MzzGKOi17O/Lp6r5yD288MdztyYPWBkyA4bkKntMpOgsJ3cWZXau/X3U0aHK06"); + + //return; + + //new Form1().ShowDialog(); + //return; + + //string src = string.Format("Data Source={0};Version=3;password={1};Journal Mode=WAL;", Util.MapFile("数据库.db", "Config"), ""); + //var tempConfig = new ConnectionConfig() { ConnectionString = src, DatabaseType = DatabaseType.SQLITE }; + + //var session = ApiClient.GetSession(tempConfig); + //var db_order = session.FindSingle<Api.Framework.Model.fl_order_alimama>("select * from fl_order_alimama where trade_id = @trade_id and trade_parent_id = @trade_parent_id", new { trade_id = "271259596907722923", trade_parent_id = "271259596907722923" }); + + //return; + + // ApiClient.SendDingdingMessageNewApi("TEST", "https://oapi.dingtalk.com/robot/send?access_token=24dbd211f807d4651d22d685c788c9df8548f23c09104646d88372d24b7549ef", "SECbb1f0d66c2ba8f71ff4e1620d99e2dd12191ab884d1567e2f949987b4187e59f"); + + try + { + EO.WebBrowser.Runtime.AddLicense( + "N4SOscufWbPw+g7kp+rp9um7aOPt9BDtrNzpz7iJWZeksefgpePzCOmMQ5ek" + + "scufWZekzQzjnZf4ChvkdpnJ4NnCoenz/hChWe3pAx7oqOXBs92wZ6emsdq9" + + "RoGkscufdabl/RfusLWRm8ufWZfAAB3jnunN/xHuWdvlBRC8W6i2wNywaKm0" + + "w9uhWer58/D3qeD29h7ArbSmwt2uaqizw9uxapmkBxDxrODz/+iha6emsdq9" + + "RoGkscufdert+Bngrez29unLn9D7BR7Wb8T66/nCm6y40hu2b8zFzui7aOrt" + + "+Bngrez29umMQ7Oz/RTinuX39umMQ3Xj7fQQ7azcwp61n1mXpM0X6Jzc8gQQ" + + "yJ21uur5sXGqusrz0XCwtMTis4+zs/0U4p7l9/b043c="); + } + catch (Exception) + { + + } + + try + { + Robot.Framework.Utils.Util.SetWebBrowserFeatures(11); + Robot.Framework.RobotServer.Servers.Add("robotsign.api.52cmg.cn"); + + DevExpressCrack.Crack.Init(); + List<string> files = new List<string>(); + files.Add(Util.MapFile(@"QQPlus.Framework.dll", @"Assembly\apifile")); + files.Add(Util.MapFile(@"FLSystem.dubug", @"Assembly\apifile")); + files.Add(Util.MapFile(@"MaxQQ.db", @"Assembly\apifile")); + files.Add(Util.MapFile(@"Activity.dll", @"Plugin")); + files.Add(Util.MapFile(@"Runtime.dll", @"Plugin")); + files.Add(Util.MapFile(@"FLSystem.exe.se")); + files.Add(Util.MapFile(@"LevelUpdate.exe")); + files.Add(Util.MapFile(@"OnlineUpdate.exe")); + files.Add(Util.MapFile(@"version.txt")); + files.Add(Util.MapFile(@"Update.zip")); + files.Add(Util.MapFile(@"VersionUpdate.exe")); + files.Add(Util.MapFile(@"OnlineUpdate.exe")); + files.Add(Util.MapFile("软件异常点我修复.exe")); + foreach (var item in files) + { + try + { + File.Delete(item); + } + catch (Exception ex) + { } + } + } + catch (Exception ex) + { } + + + if (!Tools.GetDotNetRelease(393297))//.net版本 参数(393297)在这里面看 https://docs.microsoft.com/zh-tw/dotnet/framework/migration-guide/versions-and-dependencies + { + XtraMessageBox.Show(@"检测到系统可能未安装.Net FrameWork 4.6.1", "温馨提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + return; + } + + //获取本机调试码 + //Computer cx = Computer.Instance(); + //var md5 = HttpHelper.ToMD5(cx.ComputerName + cx.CpuID + cx.LoginUserName); + + ////获取开发调试 + //var debug = EncDebugAcc(md5); + + //var tb_data = "{'pageNum' : '0','activityName' : 'orderCommon'}"; + //var tb_api = "mtop.taobao.chatting.group.recommend"; + //var tb_version = "1.0"; + + // GetSign("WGggVwxCetYDAJSz3rev6wHz", "365052383", "21646297", tb_data, tb_api,tb_version, "70047844f777bb980e529af7a40c3ab3", "10000878@tdvideo_android_4.2.2", "AvMoMBLo1CCz-eMOUfuejUazQmEyetOX8RDVE6g", "39.916295", "116.410344","27"); + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + ThreadPool.SetMaxThreads(int.MaxValue, int.MaxValue); + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); + Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); + AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + ReadICO(); + // GetXsign("mtop.taobao.rate.detaillist.get",""); + + CheckMoreopen(); + + //定时输出日志 + Task.Run(() => + { + string log = Util.MapFile("Runtime.log"); + while (true) + { + try + { + File.WriteAllText(log, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + } + catch { } + Thread.Sleep(1000 * 10); + } + }); + + //检查监控是否启动 + try + { + var location = AppDomain.CurrentDomain.BaseDirectory; + var list = Process.GetProcessesByName("FLSystemMonitor").ToList(); + bool is_start = false; + foreach (var item in list) + { + try + { + var fileName = item.MainModule.FileName; + var path = fileName.Substring(0, fileName.Length - 19); + if (location == path) + { + is_start = true; break; + } + } + catch { } + } + if (!is_start) + { + var jk_file = Util.MapFile("FLSystemMonitor.exe"); + if (!File.Exists(jk_file)) + { + var jk_old_file = Util.MapFile("FLSystemMonitor.exe", "Assembly\\apifile"); + if (File.Exists(jk_old_file)) + { + //File.Copy(jk_old_file,jk_file); + ////使用File的静态方法删除路径下的一个文件 + //File.Delete(jk_old_file); + //使用File的静态方法移动路径下的一个文件 + File.Move(jk_old_file, jk_file); + } + } + Process.Start("FLSystemMonitor.exe", "check"); + } + } + catch (Exception) + { } + + DeleteFile(Util.MapFile("Grant.Framework.dll", @"Assembly\library")); + DeleteFile(Util.MapFile("Easy4net.dll", @"Assembly\apifile")); + + SetAllowUnsafeHeaderParsing20(true); + + //CheckUpdate(); + if (CheckUpdate()) + return; + + Application.Run(new main()); + } + + private static string EncDebugAcc(string md5) + { + string rsakey = "<RSAKeyValue><Modulus>nz1sjqJbDn58VvAs+vUZtOZY4fgSQP2DvmagOEXsx/v0ZJ6ykDi71jtnU01ZD40xBt0fooUiC6VEobUJqdLqoAnqUZGqkD9IPZaVDPDYg6aXowhKZJP4Ipxq0eaXBWfROOBAVF/uFkZ27sjcuCfCpzDafOoRLRQCLQ2TKRgfYd0=</Modulus><Exponent>AQAB</Exponent><P>2WfOYWp6o8EZm14a/K0iFGrKq4QQ9q719GKw2CSNZbmSsN0azhLHKG1iYQn0M/qEzRbc1R79vLTJIF3VwbieDw==</P><Q>u4I6+v5RANurQV6YH7kGAmsoAHZhx8hbBUnRFKQyCK3LJbzq8gXeVU7mzzOkSzVMoeGEIVUYXb4zL87txkytUw==</Q><DP>qwh1XkIMdWNmp8oi5QG3u+Q/ySs+xTLjn/08Lu6ippKVirqHafNv5qgXK0xPZ80ASPBhjvCwoZKAYAwyLBL3lQ==</DP><DQ>SQP9U5+Ui3D+zwW21yOFY4u2l/eBO/qY9wY3lIIbuaVzZc6a7oO6gB2pYyYI5ABtRtw6R4CLbHWUGRnLHVzeYQ==</DQ><InverseQ>M1zD3kKgwgQcgWqilmE9/jsAfDTWBaf/2sZDusfS4zhNQtPbZuYtAQOJ5lymvUKkl5BIHrPiQ7LydG47dMiO5w==</InverseQ><D>P6IfGFx+wKsA6wjtIJgDXsvR5vLn8HqeQ97k1bfzp/LiNbdJKeLSBQkWAC7fkRxd5B1G//3tnfO8Glaq9ucnBI1CwJgvoO4h6YtyjmscC8TFpMEu3TfxU1SScokjyciiaXpQsAilFX3RQE1eARuvGaZxwbO3KbAubU6ydZGBK00=</D></RSAKeyValue>"; + RSACryption rsa = new RSACryption(); + var text = rsa.RsaEncrypt(md5, rsakey); + //Console.WriteLine($"请在根目录建立文件debug.txt,并存放值:\r\n{text}"); + return rsa.RsaEncrypt(md5, rsakey); + } + private static void DeleteFile(string fileName) + { + try + { + if (File.Exists(fileName)) File.Delete(fileName); + } + catch { } + } + // <summary> + // 初始化Cef配置,此方法代码不能放于Main方法中,否则Cef无法正常运行,别问为什么,我也不清楚 + // </summary> + + + #region 系统异常捕获 + static bool SetAllowUnsafeHeaderParsing20(bool useUnsafe) + { + try + { + //Get the assembly that contains the internal class + System.Reflection.Assembly aNetAssembly = System.Reflection.Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection)); + if (aNetAssembly != null) + { + //Use the assembly in order to get the internal type for the internal class + Type aSettingsType = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal"); + if (aSettingsType != null) + { + //Use the internal static property to get an instance of the internal settings class. + //If the static instance isn't created allready the property will create it for us. + object anInstance = aSettingsType.InvokeMember("Section", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.NonPublic, null, null, new object[] { }); + + if (anInstance != null) + { + //Locate the private bool field that tells the framework is unsafe header parsing should be allowed or not + System.Reflection.FieldInfo aUseUnsafeHeaderParsing = aSettingsType.GetField("useUnsafeHeaderParsing", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + if (aUseUnsafeHeaderParsing != null) + { + aUseUnsafeHeaderParsing.SetValue(anInstance, useUnsafe); + return true; + } + } + } + } + return false; + } + catch (Exception ex) + { + BaseForm.ShowError(ex, "系统.异常"); + } + return false; + } + static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) + { + try + { + string str = GetExceptionMsg(e.Exception, e.ToString(), "线程"); + //MessageBox.Show(str, "子线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + BaseForm.ShowError(str); + } + catch (Exception ex) + { + + BaseForm.ShowError(ex, "系统线程异常"); + } + } + + static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + try + { + string str = GetExceptionMsg(e.ExceptionObject as Exception, e.ToString(), "未知"); + // MessageBox.Show(str, "主线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + BaseForm.ShowError(str); + } + catch (Exception ex) + { + BaseForm.ShowError(ex, "系统未知异常"); + } + } + static string GetExceptionMsg(Exception ex, string backStr, string r) + { + + + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"****************************异常文本_{r}****************************"); + sb.AppendLine("【出现时间】:" + DateTime.Now.ToString()); + if (ex != null) + { + if (ex.Message == "This version of Windows is not supported.") + { + return "Windows版本不支持"; + } + + sb.AppendLine("【异常类型】:" + ex.GetType().Name); + sb.AppendLine("【异常信息】:" + (ex.Message == "This version of Windows is not supported." ? "Windows版本不支持" : ex.Message)); + sb.AppendLine("【堆栈调用】:" + ex.StackTrace); + } + else + { + sb.AppendLine("【未处理异常】:" + backStr); + } + sb.AppendLine("***************************************************************"); + return sb.ToString(); + } + + #endregion + #region 自定义一些操作 + public static bool CheckUpdate() + { + try + { + var LatestData = UpdateClient.GetCloudFileHist(); + if (!string.IsNullOrWhiteSpace(LatestData)) + { + if (new UpdateForm(LatestData).ShowDialog() == DialogResult.OK) + { + Process.Start("检查更新.exe", "FLSystem.exe"); + //Thread.Sleep(100); + return true; + } + } + //Thread.Sleep(100); + } + catch (Exception ex) + { } + return false; + } + + /// <summary> + /// 防多开限制 + /// </summary> + public static void CheckMoreopen() + { + string strFullPath = Application.ExecutablePath; + string strFileName = System.IO.Path.GetFileName(strFullPath); + string curPath = Util.MapFile(strFileName).ToLower(); + int count = 0; + foreach (Process p in Process.GetProcessesByName(strFileName.Replace(".exe", ""))) + { + string path = p.MainModule.FileName.ToLower(); + if (path == curPath) + count++; + } + + #region 是否允许重启软件 + var reset_program = Util.MapFile("reset", "File");//用于导入导出插件重启用,文件存在允许重启 + + var reset = !File.Exists(reset_program);//保存至变量 + try + { + File.Delete(reset_program);//删除文件 + } + catch (Exception) + { } + #endregion + + if (count > 1) + { + if (reset) + { + BaseForm.ShowError("对不起,您不能在同一个目录重复启动该软件!"); + // BaseForm.ShowError(str); + // MessageBox.Show("对不起,您不能在同一个目录重复启动该软件!", "防多开提醒", MessageBoxButtons.OK, MessageBoxIcon.Error); + Exit(); + } + } + } + + /// <summary> + /// 退出 + /// </summary> + public static void Exit(bool start = false) + { + try + { + if (start) + { + //程序位置 + string strAppFileName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; + System.Diagnostics.Process myNewProcess = new System.Diagnostics.Process(); + //要启动的应用程序 + myNewProcess.StartInfo.FileName = strAppFileName; + // 设置要启动的进程的初始目录 + myNewProcess.StartInfo.WorkingDirectory = Application.ExecutablePath; + //启动程序 + myNewProcess.Start(); + } + //结束该程序 + // Application.Exit(); + //结束该所有线程 + //Environment.Exit(0); + Process.GetCurrentProcess().Kill(); + } + catch (Exception) + { } + } + #endregion + + + } +} diff --git a/FLSystem/Properties/AssemblyInfo.cs b/FLSystem/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e74fd4d --- /dev/null +++ b/FLSystem/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("FLSystem")] +[assembly: AssemblyDescription("FLSystem")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("FLSystem")] +[assembly: AssemblyProduct("FLSystem")] +[assembly: AssemblyCopyright("FLSystem")] +[assembly: AssemblyTrademark("FLSystem")] +[assembly: AssemblyCulture("")] + +//将 ComVisible 设置为 false 将使此程序集中的类型 +//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("1f3449ce-c000-4f8e-afd1-91d5c684a3ad")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/FLSystem/Properties/Resources.Designer.cs b/FLSystem/Properties/Resources.Designer.cs new file mode 100644 index 0000000..eef67bf --- /dev/null +++ b/FLSystem/Properties/Resources.Designer.cs @@ -0,0 +1,1378 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace FLSystem.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FLSystem.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 转链工具 的本地化字符串。 + /// </summary> + internal static string ConvertToolSoftwareType { + get { + return ResourceManager.GetString("ConvertToolSoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap debug_blue { + get { + object obj = ResourceManager.GetObject("debug-blue", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Icon exe { + get { + object obj = ResourceManager.GetObject("exe", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// <summary> + /// 查找类似 群pid 的本地化字符串。 + /// </summary> + internal static string GroupSoftwareType { + get { + return ResourceManager.GetString("GroupSoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap QQ { + get { + object obj = ResourceManager.GetObject("QQ", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap QQ第三方登录 { + get { + object obj = ResourceManager.GetObject("QQ第三方登录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap robot { + get { + object obj = ResourceManager.GetObject("robot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找类似 用户私人pid 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap taobao_32px_1164474_easyicon_net { + get { + object obj = ResourceManager.GetObject("taobao_32px_1164474_easyicon.net", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap wall_e_robot_Awake_32px_501940_easyicon_net { + get { + object obj = ResourceManager.GetObject("wall-e_robot_Awake_32px_501940_easyicon.net", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找类似 唯品会返利 的本地化字符串。 + /// </summary> + internal static string WPHSoftwareType { + get { + return ResourceManager.GetString("WPHSoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 个人中心_登录 { + get { + object obj = ResourceManager.GetObject("个人中心-登录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 二维码登录 { + get { + object obj = ResourceManager.GetObject("二维码登录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 京东 { + get { + object obj = ResourceManager.GetObject("京东", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 京东_1_ { + get { + object obj = ResourceManager.GetObject("京东(1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 京东_2_ { + get { + object obj = ResourceManager.GetObject("京东(2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 京东_20 { + get { + object obj = ResourceManager.GetObject("京东_20", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 京东_32x32 { + get { + object obj = ResourceManager.GetObject("京东_32x32", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 会员管理 { + get { + object obj = ResourceManager.GetObject("会员管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 佣金 { + get { + object obj = ResourceManager.GetObject("佣金", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 佣金查询 { + get { + object obj = ResourceManager.GetObject("佣金查询", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 停止__1_ { + get { + object obj = ResourceManager.GetObject("停止 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 停止__4_ { + get { + object obj = ResourceManager.GetObject("停止 (4)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 公众号 { + get { + object obj = ResourceManager.GetObject("公众号", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 公众号__1_ { + get { + object obj = ResourceManager.GetObject("公众号 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 公众号__2_ { + get { + object obj = ResourceManager.GetObject("公众号 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 分享赚钱 { + get { + object obj = ResourceManager.GetObject("分享赚钱", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 分销 { + get { + object obj = ResourceManager.GetObject("分销", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 升级 { + get { + object obj = ResourceManager.GetObject("升级", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 反馈 { + get { + object obj = ResourceManager.GetObject("反馈", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 反馈__1_ { + get { + object obj = ResourceManager.GetObject("反馈 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 同步 { + get { + object obj = ResourceManager.GetObject("同步", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 唯品会1 { + get { + object obj = ResourceManager.GetObject("唯品会1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 唯品会11 { + get { + object obj = ResourceManager.GetObject("唯品会11", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 唯品会12 { + get { + object obj = ResourceManager.GetObject("唯品会12", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 喇叭 { + get { + object obj = ResourceManager.GetObject("喇叭", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 喇叭__1_ { + get { + object obj = ResourceManager.GetObject("喇叭 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 喇叭__3_ { + get { + object obj = ResourceManager.GetObject("喇叭 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 喇叭__4_ { + get { + object obj = ResourceManager.GetObject("喇叭 (4)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 安装调试_多色 { + get { + object obj = ResourceManager.GetObject("安装调试-多色", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 客服_机器人 { + get { + object obj = ResourceManager.GetObject("客服-机器人", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 客服_机器人改 { + get { + object obj = ResourceManager.GetObject("客服-机器人改", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 客服_机器人改__2_ { + get { + object obj = ResourceManager.GetObject("客服-机器人改 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 小快手 { + get { + object obj = ResourceManager.GetObject("小快手", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 帮助__1_ { + get { + object obj = ResourceManager.GetObject("帮助 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 帮助__2_ { + get { + object obj = ResourceManager.GetObject("帮助 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 平台级业务监控 { + get { + object obj = ResourceManager.GetObject("平台级业务监控", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 平台认证 { + get { + object obj = ResourceManager.GetObject("平台认证", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 应用 { + get { + object obj = ResourceManager.GetObject("应用", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 应用__2_ { + get { + object obj = ResourceManager.GetObject("应用 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 应用__3_ { + get { + object obj = ResourceManager.GetObject("应用 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 应用宝 { + get { + object obj = ResourceManager.GetObject("应用宝", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 微信__1_ { + get { + object obj = ResourceManager.GetObject("微信 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 微信__3_ { + get { + object obj = ResourceManager.GetObject("微信 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 快手登录 { + get { + object obj = ResourceManager.GetObject("快手登录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 抖音 { + get { + object obj = ResourceManager.GetObject("抖音", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多 { + get { + object obj = ResourceManager.GetObject("拼多多", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多__4_ { + get { + object obj = ResourceManager.GetObject("拼多多 (4)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多_1_ { + get { + object obj = ResourceManager.GetObject("拼多多(1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多_2_ { + get { + object obj = ResourceManager.GetObject("拼多多(2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多_20 { + get { + object obj = ResourceManager.GetObject("拼多多_20", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多_3_ { + get { + object obj = ResourceManager.GetObject("拼多多(3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多_4_ { + get { + object obj = ResourceManager.GetObject("拼多多(4)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多0 { + get { + object obj = ResourceManager.GetObject("拼多多0", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 授权 { + get { + object obj = ResourceManager.GetObject("授权", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 授权__1_ { + get { + object obj = ResourceManager.GetObject("授权 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 授权__2_ { + get { + object obj = ResourceManager.GetObject("授权 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 授权__3_ { + get { + object obj = ResourceManager.GetObject("授权 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 授权_2_ { + get { + object obj = ResourceManager.GetObject("授权(2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 授权1 { + get { + object obj = ResourceManager.GetObject("授权1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 授权zh_01 { + get { + object obj = ResourceManager.GetObject("授权zh-01", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 授权成功 { + get { + object obj = ResourceManager.GetObject("授权成功", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 提升成长值 { + get { + object obj = ResourceManager.GetObject("提升成长值", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找类似 http://fr-1303123972.cos.ap-chengdu.myqcloud.com/2652ab08-1134-6471-b994-ca1fe5732a0f.rar 的本地化字符串。 + /// </summary> + internal static string 易转发下载地址 { + get { + return ResourceManager.GetString("易转发下载地址", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 机器人_1_ { + get { + object obj = ResourceManager.GetObject("机器人(1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 机器人_小鲁02 { + get { + object obj = ResourceManager.GetObject("机器人_小鲁02", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 权限 { + get { + object obj = ResourceManager.GetObject("权限", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 权限_1_ { + get { + object obj = ResourceManager.GetObject("权限(1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 权限_2_ { + get { + object obj = ResourceManager.GetObject("权限(2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 淘宝 { + get { + object obj = ResourceManager.GetObject("淘宝", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 淘宝__2_ { + get { + object obj = ResourceManager.GetObject("淘宝 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 淘宝_1_ { + get { + object obj = ResourceManager.GetObject("淘宝(1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 淘宝_2_ { + get { + object obj = ResourceManager.GetObject("淘宝(2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 淘宝_20 { + get { + object obj = ResourceManager.GetObject("淘宝_20", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 淘宝联盟 { + get { + object obj = ResourceManager.GetObject("淘宝联盟", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 淘宝联盟_1_ { + get { + object obj = ResourceManager.GetObject("淘宝联盟(1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 用户管理 { + get { + object obj = ResourceManager.GetObject("用户管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 留言 { + get { + object obj = ResourceManager.GetObject("留言", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 留言__1_ { + get { + object obj = ResourceManager.GetObject("留言 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 留言__2_ { + get { + object obj = ResourceManager.GetObject("留言 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 留言__3_ { + get { + object obj = ResourceManager.GetObject("留言 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 登录 { + get { + object obj = ResourceManager.GetObject("登录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 登录__1_ { + get { + object obj = ResourceManager.GetObject("登录 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 登录密码 { + get { + object obj = ResourceManager.GetObject("登录密码", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 登录验证 { + get { + object obj = ResourceManager.GetObject("登录验证", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 白名单__1_ { + get { + object obj = ResourceManager.GetObject("白名单 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 白名单__1_1 { + get { + object obj = ResourceManager.GetObject("白名单 (1)1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 白名单__2_ { + get { + object obj = ResourceManager.GetObject("白名单 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 第三方登录微信 { + get { + object obj = ResourceManager.GetObject("第三方登录微信", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 管理_从账号管理 { + get { + object obj = ResourceManager.GetObject("管理-从账号管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 续费 { + get { + object obj = ResourceManager.GetObject("续费", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 绿企联盟 { + get { + object obj = ResourceManager.GetObject("绿企联盟", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 联盟 { + get { + object obj = ResourceManager.GetObject("联盟", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 联盟_1_ { + get { + object obj = ResourceManager.GetObject("联盟(1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 联盟1 { + get { + object obj = ResourceManager.GetObject("联盟1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 联盟11 { + get { + object obj = ResourceManager.GetObject("联盟11", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 联盟任务 { + get { + object obj = ResourceManager.GetObject("联盟任务", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 苏宁小 { + get { + object obj = ResourceManager.GetObject("苏宁小", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 订单 { + get { + object obj = ResourceManager.GetObject("订单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 订单__1_ { + get { + object obj = ResourceManager.GetObject("订单 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 订单__2_ { + get { + object obj = ResourceManager.GetObject("订单 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 订单__3_ { + get { + object obj = ResourceManager.GetObject("订单 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 认证 { + get { + object obj = ResourceManager.GetObject("认证", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 认证1 { + get { + object obj = ResourceManager.GetObject("认证1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 调试中 { + get { + object obj = ResourceManager.GetObject("调试中", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 账单 { + get { + object obj = ResourceManager.GetObject("账单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 账单__1_ { + get { + object obj = ResourceManager.GetObject("账单 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Byte[] 类型的本地化资源。 + /// </summary> + internal static byte[] 返利机器人 { + get { + object obj = ResourceManager.GetObject("返利机器人", resourceCulture); + return ((byte[])(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 通知 { + get { + object obj = ResourceManager.GetObject("通知", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 通知__1_ { + get { + object obj = ResourceManager.GetObject("通知 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 通知__2_ { + get { + object obj = ResourceManager.GetObject("通知 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 通知__3_ { + get { + object obj = ResourceManager.GetObject("通知 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 重启__1_ { + get { + object obj = ResourceManager.GetObject("重启 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 重启__2_ { + get { + object obj = ResourceManager.GetObject("重启 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 重启__3_ { + get { + object obj = ResourceManager.GetObject("重启 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 钱 { + get { + object obj = ResourceManager.GetObject("钱", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 锁 { + get { + object obj = ResourceManager.GetObject("锁", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 阿里妈妈 { + get { + object obj = ResourceManager.GetObject("阿里妈妈", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 黑名单__1_ { + get { + object obj = ResourceManager.GetObject("黑名单 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 黑名单__2_ { + get { + object obj = ResourceManager.GetObject("黑名单 (2)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 黑名单__3_ { + get { + object obj = ResourceManager.GetObject("黑名单 (3)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 黑名单__4_ { + get { + object obj = ResourceManager.GetObject("黑名单 (4)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/FLSystem/Properties/Resources.resx b/FLSystem/Properties/Resources.resx new file mode 100644 index 0000000..b121374 --- /dev/null +++ b/FLSystem/Properties/Resources.resx @@ -0,0 +1,520 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="淘宝联盟" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\淘宝联盟.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="拼多多(4)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多(4)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="授权1" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\授权1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="拼多多(1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多(1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="个人中心-登录" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\个人中心-登录1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="拼多多(2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多(2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="安装调试-多色" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\安装调试-多色1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="锁" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\锁.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="授权 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\授权 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="公众号 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\公众号 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="公众号 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\公众号 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="平台认证" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\平台认证.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="淘宝(1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\淘宝(1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="QQ" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\QQ1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="会员管理" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\会员管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="客服-机器人改" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\客服-机器人改1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="绿企联盟" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\绿企联盟.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="联盟(1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\联盟(1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="拼多多(3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多(3)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="二维码登录" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\二维码登录.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="喇叭 (4)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\喇叭 (4).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="留言 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\留言 (2).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="帮助 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\帮助 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="返利机器人" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\返利机器人.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </data> + <data name="帮助 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\帮助 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="应用 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\应用 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="登录" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\登录.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="联盟1" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\联盟2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="wall-e_robot_Awake_32px_501940_easyicon.net" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\wall-e_robot_Awake_32px_501940_easyicon.net1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="debug-blue" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\debug-blue1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="拼多多" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="拼多多 (4)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多 (4)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="重启 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\重启 (3)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="授权zh-01" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\授权zh-011.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="淘宝" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\淘宝.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="抖音" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\抖音.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="账单 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\账单 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="应用 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\应用 (3)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="唯品会11" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\唯品会11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="佣金查询" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\佣金查询.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="黑名单 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\黑名单 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="提升成长值" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\提升成长值.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="QQ第三方登录" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\QQ第三方登录.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="唯品会12" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\唯品会12.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="拼多多0" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多0.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="订单" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\订单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="淘宝 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\淘宝 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="订单 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\订单 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="客服-机器人改 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\客服-机器人改 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="小快手" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\小快手.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="调试中" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\调试中.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="停止 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\停止 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="权限" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\权限.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="公众号" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\公众号.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="分销" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\分销.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="白名单 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\白名单 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="授权 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\授权 (3)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="黑名单 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\黑名单 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="分享赚钱" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\分享赚钱.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="京东(1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\京东(1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="京东(2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\京东(2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="联盟11" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\联盟21.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="通知 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\通知 (3)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="续费" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\续费.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="京东_32x32" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\京东。 (2).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="认证" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\认证.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="苏宁小" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\苏宁小.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="用户管理" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\用户管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="授权 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\授权 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="客服-机器人" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\客服-机器人1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="京东_20" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\京东-20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="淘宝_20" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\淘宝-20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="机器人_小鲁02" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\机器人_小鲁02.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="登录密码" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\登录密码.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="黑名单 (4)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\黑名单 (4)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="账单" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\账单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="通知 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\通知 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="佣金" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\佣金.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="停止 (4)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\停止 (4)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="升级" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\升级.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="淘宝联盟(1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\淘宝联盟(1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="平台级业务监控" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\平台级业务监控.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="留言 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\留言 (1).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="喇叭" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\喇叭.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="应用宝" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\应用宝.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="应用" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\应用.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="微信 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\微信 (3)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="订单 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\订单 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="阿里妈妈" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\阿里妈妈.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="留言 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\留言 (3).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="授权成功" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\授权成功.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="喇叭 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\喇叭 (1).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="通知" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\通知.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="留言" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\留言.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="taobao_32px_1164474_easyicon.net" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\taobao_32px_1164474_easyicon.net1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="重启 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\重启 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="exe" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\exe.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="白名单 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\白名单 (1)2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="认证1" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\认证1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="联盟" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\联盟1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="通知 (2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\通知 (2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="第三方登录微信" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\第三方登录微信.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="机器人(1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\机器人(1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="SoftwareType" xml:space="preserve"> + <value>用户私人pid</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <data name="robot" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\robot.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="喇叭 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\喇叭 (3).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="GroupSoftwareType" xml:space="preserve"> + <value>群pid</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <data name="联盟任务" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\联盟任务.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="重启 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\重启 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="同步" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\同步.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="拼多多_20" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多-20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="反馈" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\反馈.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="登录 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\登录 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="反馈 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\反馈 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="唯品会1" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\唯品会1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="WPHSoftwareType" xml:space="preserve"> + <value>唯品会返利</value> + </data> + <data name="淘宝(2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\淘宝(2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="权限(1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\权限(1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="ConvertToolSoftwareType" xml:space="preserve"> + <value>转链工具</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <data name="授权" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\授权.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="登录验证" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\登录验证.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="订单 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\订单 (3)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="权限(2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\权限(2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="管理-从账号管理" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\管理-从账号管理1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="易转发下载地址" xml:space="preserve"> + <value>http://fr-1303123972.cos.ap-chengdu.myqcloud.com/2652ab08-1134-6471-b994-ca1fe5732a0f.rar</value> + </data> + <data name="钱" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\钱.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="微信 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\微信 (1)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="白名单 (1)1" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\白名单 (1)11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="黑名单 (3)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\黑名单 (3)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="京东" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\京东.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="授权(2)" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\授权(2)1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="快手登录" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\快手登录.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/FLSystem/Properties/Settings.Designer.cs b/FLSystem/Properties/Settings.Designer.cs new file mode 100644 index 0000000..8b87b80 --- /dev/null +++ b/FLSystem/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.18034 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace FLSystem.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/FLSystem/Properties/Settings.settings b/FLSystem/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/FLSystem/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)"> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> + <Settings /> +</SettingsFile> diff --git a/FLSystem/Properties/app.manifest b/FLSystem/Properties/app.manifest new file mode 100644 index 0000000..15b2b8c --- /dev/null +++ b/FLSystem/Properties/app.manifest @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> + <assemblyIdentity version="1.0.0.0" name="MyApplication.app" /> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> + <!-- UAC 清单选项 + 如果想要更改 Windows 用户帐户控制级别,请使用 + 以下节点之一替换 requestedExecutionLevel 节点。n + <requestedExecutionLevel level="asInvoker" uiAccess="false" /> + <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> + <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> + + 指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。 + 如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此 + 元素。 + --> + <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> + </requestedPrivileges> + <applicationRequestMinimum> + <defaultAssemblyRequest permissionSetReference="Custom" /> + <PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" Unrestricted="true" /> + </applicationRequestMinimum> + </security> + </trustInfo> + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的 + Windows 版本的列表。取消评论适当的元素, + Windows 将自动选择最兼容的环境。 --> + <!-- Windows Vista --> + <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />--> + <!-- Windows 7 --> + <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />--> + <!-- Windows 8 --> + <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />--> + <!-- Windows 8.1 --> + <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />--> + <!-- Windows 10 --> + <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />--> + </application> + </compatibility> + <!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行 + 自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需 + 选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应 + 在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。--> + <!-- + <application xmlns="urn:schemas-microsoft-com:asm.v3"> + <windowsSettings> + <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> + </windowsSettings> + </application> + --> + <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) --> + <!-- + <dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="*" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + </dependency> + --> +</assembly> \ No newline at end of file diff --git a/FLSystem/Properties/licenses.licx b/FLSystem/Properties/licenses.licx new file mode 100644 index 0000000..3e0db84 --- /dev/null +++ b/FLSystem/Properties/licenses.licx @@ -0,0 +1,12 @@ +DevExpress.Patch.InMemoryPatch, DevExpress.Patch.Common, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7fc7bfca2443de66 +DevExpress.XtraRichEdit.RichEditControl, DevExpress.XtraRichEdit.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraReports.UserDesigner.XRDesignDockManager, DevExpress.XtraReports.v19.2.Extensions, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraReports.UserDesigner.XRDesignBarManager, DevExpress.XtraReports.v19.2.Extensions, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.PictureEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraBars.BarManager, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraBars.Ribbon.RibbonControl, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/FLSystem/Resources/QQ.png b/FLSystem/Resources/QQ.png new file mode 100644 index 0000000..d7edf22 Binary files /dev/null and b/FLSystem/Resources/QQ.png differ diff --git a/FLSystem/Resources/QQ1.png b/FLSystem/Resources/QQ1.png new file mode 100644 index 0000000..3ca97e1 Binary files /dev/null and b/FLSystem/Resources/QQ1.png differ diff --git a/FLSystem/Resources/QQ第三方登录.png b/FLSystem/Resources/QQ第三方登录.png new file mode 100644 index 0000000..7caca31 Binary files /dev/null and b/FLSystem/Resources/QQ第三方登录.png differ diff --git a/FLSystem/Resources/VersionUpdate.xml b/FLSystem/Resources/VersionUpdate.xml new file mode 100644 index 0000000..1b886fb --- /dev/null +++ b/FLSystem/Resources/VersionUpdate.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<Files> + <File Name="核心组件" Version="2021.8.10.10001" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=MainUpdate" /> + <File Name="Library组件" Version="2020.02.16.1" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=LibraryUpdate" /> + <File Name="Dev界面组件" Version="2019.12.27.1" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=DevUpdate" /> + <File Name="QQ通讯组件" Version="2020.7.27.1" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=QQUpdate" /> + <File Name="插件列表" Version="2021.8.10.10001" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=PluginUpdate" /> + <File Name="CefSharp组件" Version="2021.7.12.2334" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=CefSharpUpdate" /> +</Files> \ No newline at end of file diff --git a/FLSystem/Resources/debug-blue.png b/FLSystem/Resources/debug-blue.png new file mode 100644 index 0000000..a912e09 Binary files /dev/null and b/FLSystem/Resources/debug-blue.png differ diff --git a/FLSystem/Resources/debug-blue1.png b/FLSystem/Resources/debug-blue1.png new file mode 100644 index 0000000..a912e09 Binary files /dev/null and b/FLSystem/Resources/debug-blue1.png differ diff --git a/FLSystem/Resources/exe.ico b/FLSystem/Resources/exe.ico new file mode 100644 index 0000000..f75758e Binary files /dev/null and b/FLSystem/Resources/exe.ico differ diff --git a/FLSystem/Resources/robot.png b/FLSystem/Resources/robot.png new file mode 100644 index 0000000..785f2cf Binary files /dev/null and b/FLSystem/Resources/robot.png differ diff --git a/FLSystem/Resources/taobao_32px_1164474_easyicon.net.png b/FLSystem/Resources/taobao_32px_1164474_easyicon.net.png new file mode 100644 index 0000000..cb009dd Binary files /dev/null and b/FLSystem/Resources/taobao_32px_1164474_easyicon.net.png differ diff --git a/FLSystem/Resources/taobao_32px_1164474_easyicon.net1.png b/FLSystem/Resources/taobao_32px_1164474_easyicon.net1.png new file mode 100644 index 0000000..cb009dd Binary files /dev/null and b/FLSystem/Resources/taobao_32px_1164474_easyicon.net1.png differ diff --git a/FLSystem/Resources/wall-e_robot_Awake_32px_501940_easyicon.net.png b/FLSystem/Resources/wall-e_robot_Awake_32px_501940_easyicon.net.png new file mode 100644 index 0000000..7d34ed2 Binary files /dev/null and b/FLSystem/Resources/wall-e_robot_Awake_32px_501940_easyicon.net.png differ diff --git a/FLSystem/Resources/wall-e_robot_Awake_32px_501940_easyicon.net1.png b/FLSystem/Resources/wall-e_robot_Awake_32px_501940_easyicon.net1.png new file mode 100644 index 0000000..7d34ed2 Binary files /dev/null and b/FLSystem/Resources/wall-e_robot_Awake_32px_501940_easyicon.net1.png differ diff --git a/FLSystem/Resources/个人中心-登录.png b/FLSystem/Resources/个人中心-登录.png new file mode 100644 index 0000000..0348a06 Binary files /dev/null and b/FLSystem/Resources/个人中心-登录.png differ diff --git a/FLSystem/Resources/个人中心-登录1.png b/FLSystem/Resources/个人中心-登录1.png new file mode 100644 index 0000000..0348a06 Binary files /dev/null and b/FLSystem/Resources/个人中心-登录1.png differ diff --git a/FLSystem/Resources/二维码登录.png b/FLSystem/Resources/二维码登录.png new file mode 100644 index 0000000..a720d43 Binary files /dev/null and b/FLSystem/Resources/二维码登录.png differ diff --git a/FLSystem/Resources/京东(1).png b/FLSystem/Resources/京东(1).png new file mode 100644 index 0000000..72a3bb5 Binary files /dev/null and b/FLSystem/Resources/京东(1).png differ diff --git a/FLSystem/Resources/京东(1)1.png b/FLSystem/Resources/京东(1)1.png new file mode 100644 index 0000000..72a3bb5 Binary files /dev/null and b/FLSystem/Resources/京东(1)1.png differ diff --git a/FLSystem/Resources/京东(2).png b/FLSystem/Resources/京东(2).png new file mode 100644 index 0000000..c642c58 Binary files /dev/null and b/FLSystem/Resources/京东(2).png differ diff --git a/FLSystem/Resources/京东(2)1.png b/FLSystem/Resources/京东(2)1.png new file mode 100644 index 0000000..c642c58 Binary files /dev/null and b/FLSystem/Resources/京东(2)1.png differ diff --git a/FLSystem/Resources/京东-20.png b/FLSystem/Resources/京东-20.png new file mode 100644 index 0000000..470b870 Binary files /dev/null and b/FLSystem/Resources/京东-20.png differ diff --git a/FLSystem/Resources/京东.png b/FLSystem/Resources/京东.png new file mode 100644 index 0000000..6b6eb2e Binary files /dev/null and b/FLSystem/Resources/京东.png differ diff --git a/FLSystem/Resources/京东_25x25.png b/FLSystem/Resources/京东_25x25.png new file mode 100644 index 0000000..e78c5b9 Binary files /dev/null and b/FLSystem/Resources/京东_25x25.png differ diff --git a/FLSystem/Resources/京东。 (2).png b/FLSystem/Resources/京东。 (2).png new file mode 100644 index 0000000..bb4a7ba Binary files /dev/null and b/FLSystem/Resources/京东。 (2).png differ diff --git a/FLSystem/Resources/会员管理.png b/FLSystem/Resources/会员管理.png new file mode 100644 index 0000000..e7c2765 Binary files /dev/null and b/FLSystem/Resources/会员管理.png differ diff --git a/FLSystem/Resources/佣金.png b/FLSystem/Resources/佣金.png new file mode 100644 index 0000000..0a5eea6 Binary files /dev/null and b/FLSystem/Resources/佣金.png differ diff --git a/FLSystem/Resources/佣金查询.png b/FLSystem/Resources/佣金查询.png new file mode 100644 index 0000000..59b60de Binary files /dev/null and b/FLSystem/Resources/佣金查询.png differ diff --git a/FLSystem/Resources/停止 (1).png b/FLSystem/Resources/停止 (1).png new file mode 100644 index 0000000..60bb013 Binary files /dev/null and b/FLSystem/Resources/停止 (1).png differ diff --git a/FLSystem/Resources/停止 (1)1.png b/FLSystem/Resources/停止 (1)1.png new file mode 100644 index 0000000..60bb013 Binary files /dev/null and b/FLSystem/Resources/停止 (1)1.png differ diff --git a/FLSystem/Resources/停止 (4).png b/FLSystem/Resources/停止 (4).png new file mode 100644 index 0000000..258455c Binary files /dev/null and b/FLSystem/Resources/停止 (4).png differ diff --git a/FLSystem/Resources/停止 (4)1.png b/FLSystem/Resources/停止 (4)1.png new file mode 100644 index 0000000..258455c Binary files /dev/null and b/FLSystem/Resources/停止 (4)1.png differ diff --git a/FLSystem/Resources/公众号 (1).png b/FLSystem/Resources/公众号 (1).png new file mode 100644 index 0000000..4837dbb Binary files /dev/null and b/FLSystem/Resources/公众号 (1).png differ diff --git a/FLSystem/Resources/公众号 (1)1.png b/FLSystem/Resources/公众号 (1)1.png new file mode 100644 index 0000000..4837dbb Binary files /dev/null and b/FLSystem/Resources/公众号 (1)1.png differ diff --git a/FLSystem/Resources/公众号 (2).png b/FLSystem/Resources/公众号 (2).png new file mode 100644 index 0000000..27cd67a Binary files /dev/null and b/FLSystem/Resources/公众号 (2).png differ diff --git a/FLSystem/Resources/公众号 (2)1.png b/FLSystem/Resources/公众号 (2)1.png new file mode 100644 index 0000000..27cd67a Binary files /dev/null and b/FLSystem/Resources/公众号 (2)1.png differ diff --git a/FLSystem/Resources/公众号.png b/FLSystem/Resources/公众号.png new file mode 100644 index 0000000..d8ec63d Binary files /dev/null and b/FLSystem/Resources/公众号.png differ diff --git a/FLSystem/Resources/分享赚钱.png b/FLSystem/Resources/分享赚钱.png new file mode 100644 index 0000000..e33e071 Binary files /dev/null and b/FLSystem/Resources/分享赚钱.png differ diff --git a/FLSystem/Resources/分销.png b/FLSystem/Resources/分销.png new file mode 100644 index 0000000..5129daa Binary files /dev/null and b/FLSystem/Resources/分销.png differ diff --git a/FLSystem/Resources/升级.png b/FLSystem/Resources/升级.png new file mode 100644 index 0000000..5cfa333 Binary files /dev/null and b/FLSystem/Resources/升级.png differ diff --git a/FLSystem/Resources/反馈 (1).png b/FLSystem/Resources/反馈 (1).png new file mode 100644 index 0000000..d176e50 Binary files /dev/null and b/FLSystem/Resources/反馈 (1).png differ diff --git a/FLSystem/Resources/反馈 (1)1.png b/FLSystem/Resources/反馈 (1)1.png new file mode 100644 index 0000000..d176e50 Binary files /dev/null and b/FLSystem/Resources/反馈 (1)1.png differ diff --git a/FLSystem/Resources/反馈.png b/FLSystem/Resources/反馈.png new file mode 100644 index 0000000..6361ed9 Binary files /dev/null and b/FLSystem/Resources/反馈.png differ diff --git a/FLSystem/Resources/同步.png b/FLSystem/Resources/同步.png new file mode 100644 index 0000000..4ea1c80 Binary files /dev/null and b/FLSystem/Resources/同步.png differ diff --git a/FLSystem/Resources/唯品会1.png b/FLSystem/Resources/唯品会1.png new file mode 100644 index 0000000..787e814 Binary files /dev/null and b/FLSystem/Resources/唯品会1.png differ diff --git a/FLSystem/Resources/唯品会11.png b/FLSystem/Resources/唯品会11.png new file mode 100644 index 0000000..787e814 Binary files /dev/null and b/FLSystem/Resources/唯品会11.png differ diff --git a/FLSystem/Resources/唯品会12.png b/FLSystem/Resources/唯品会12.png new file mode 100644 index 0000000..b14825d Binary files /dev/null and b/FLSystem/Resources/唯品会12.png differ diff --git a/FLSystem/Resources/喇叭 (1).png b/FLSystem/Resources/喇叭 (1).png new file mode 100644 index 0000000..0d0bf8e Binary files /dev/null and b/FLSystem/Resources/喇叭 (1).png differ diff --git a/FLSystem/Resources/喇叭 (3).png b/FLSystem/Resources/喇叭 (3).png new file mode 100644 index 0000000..0c75f1e Binary files /dev/null and b/FLSystem/Resources/喇叭 (3).png differ diff --git a/FLSystem/Resources/喇叭 (4).png b/FLSystem/Resources/喇叭 (4).png new file mode 100644 index 0000000..d42888a Binary files /dev/null and b/FLSystem/Resources/喇叭 (4).png differ diff --git a/FLSystem/Resources/喇叭.png b/FLSystem/Resources/喇叭.png new file mode 100644 index 0000000..785b87c Binary files /dev/null and b/FLSystem/Resources/喇叭.png differ diff --git a/FLSystem/Resources/安装调试-多色.png b/FLSystem/Resources/安装调试-多色.png new file mode 100644 index 0000000..841ba71 Binary files /dev/null and b/FLSystem/Resources/安装调试-多色.png differ diff --git a/FLSystem/Resources/安装调试-多色1.png b/FLSystem/Resources/安装调试-多色1.png new file mode 100644 index 0000000..841ba71 Binary files /dev/null and b/FLSystem/Resources/安装调试-多色1.png differ diff --git a/FLSystem/Resources/客服-机器人.png b/FLSystem/Resources/客服-机器人.png new file mode 100644 index 0000000..71b52a1 Binary files /dev/null and b/FLSystem/Resources/客服-机器人.png differ diff --git a/FLSystem/Resources/客服-机器人1.png b/FLSystem/Resources/客服-机器人1.png new file mode 100644 index 0000000..71b52a1 Binary files /dev/null and b/FLSystem/Resources/客服-机器人1.png differ diff --git a/FLSystem/Resources/客服-机器人改 (2).png b/FLSystem/Resources/客服-机器人改 (2).png new file mode 100644 index 0000000..95eef2e Binary files /dev/null and b/FLSystem/Resources/客服-机器人改 (2).png differ diff --git a/FLSystem/Resources/客服-机器人改 (2)1.png b/FLSystem/Resources/客服-机器人改 (2)1.png new file mode 100644 index 0000000..95eef2e Binary files /dev/null and b/FLSystem/Resources/客服-机器人改 (2)1.png differ diff --git a/FLSystem/Resources/客服-机器人改.png b/FLSystem/Resources/客服-机器人改.png new file mode 100644 index 0000000..2826aea Binary files /dev/null and b/FLSystem/Resources/客服-机器人改.png differ diff --git a/FLSystem/Resources/客服-机器人改1.png b/FLSystem/Resources/客服-机器人改1.png new file mode 100644 index 0000000..2826aea Binary files /dev/null and b/FLSystem/Resources/客服-机器人改1.png differ diff --git a/FLSystem/Resources/导购.png b/FLSystem/Resources/导购.png new file mode 100644 index 0000000..8cc5bf9 Binary files /dev/null and b/FLSystem/Resources/导购.png differ diff --git a/FLSystem/Resources/小快手.jpg b/FLSystem/Resources/小快手.jpg new file mode 100644 index 0000000..0f6d32b Binary files /dev/null and b/FLSystem/Resources/小快手.jpg differ diff --git a/FLSystem/Resources/帮助 (1).png b/FLSystem/Resources/帮助 (1).png new file mode 100644 index 0000000..e56851f Binary files /dev/null and b/FLSystem/Resources/帮助 (1).png differ diff --git a/FLSystem/Resources/帮助 (1)1.png b/FLSystem/Resources/帮助 (1)1.png new file mode 100644 index 0000000..e56851f Binary files /dev/null and b/FLSystem/Resources/帮助 (1)1.png differ diff --git a/FLSystem/Resources/帮助 (2).png b/FLSystem/Resources/帮助 (2).png new file mode 100644 index 0000000..40b6e83 Binary files /dev/null and b/FLSystem/Resources/帮助 (2).png differ diff --git a/FLSystem/Resources/帮助 (2)1.png b/FLSystem/Resources/帮助 (2)1.png new file mode 100644 index 0000000..40b6e83 Binary files /dev/null and b/FLSystem/Resources/帮助 (2)1.png differ diff --git a/FLSystem/Resources/平台级业务监控.png b/FLSystem/Resources/平台级业务监控.png new file mode 100644 index 0000000..625c29d Binary files /dev/null and b/FLSystem/Resources/平台级业务监控.png differ diff --git a/FLSystem/Resources/平台认证.png b/FLSystem/Resources/平台认证.png new file mode 100644 index 0000000..214e00b Binary files /dev/null and b/FLSystem/Resources/平台认证.png differ diff --git a/FLSystem/Resources/应用 (2).png b/FLSystem/Resources/应用 (2).png new file mode 100644 index 0000000..8f6ef45 Binary files /dev/null and b/FLSystem/Resources/应用 (2).png differ diff --git a/FLSystem/Resources/应用 (2)1.png b/FLSystem/Resources/应用 (2)1.png new file mode 100644 index 0000000..8f6ef45 Binary files /dev/null and b/FLSystem/Resources/应用 (2)1.png differ diff --git a/FLSystem/Resources/应用 (3).png b/FLSystem/Resources/应用 (3).png new file mode 100644 index 0000000..17e3aff Binary files /dev/null and b/FLSystem/Resources/应用 (3).png differ diff --git a/FLSystem/Resources/应用 (3)1.png b/FLSystem/Resources/应用 (3)1.png new file mode 100644 index 0000000..17e3aff Binary files /dev/null and b/FLSystem/Resources/应用 (3)1.png differ diff --git a/FLSystem/Resources/应用.png b/FLSystem/Resources/应用.png new file mode 100644 index 0000000..3a98516 Binary files /dev/null and b/FLSystem/Resources/应用.png differ diff --git a/FLSystem/Resources/应用宝.png b/FLSystem/Resources/应用宝.png new file mode 100644 index 0000000..ea9a9fe Binary files /dev/null and b/FLSystem/Resources/应用宝.png differ diff --git a/FLSystem/Resources/微信 (1).png b/FLSystem/Resources/微信 (1).png new file mode 100644 index 0000000..d219d0a Binary files /dev/null and b/FLSystem/Resources/微信 (1).png differ diff --git a/FLSystem/Resources/微信 (1)1.png b/FLSystem/Resources/微信 (1)1.png new file mode 100644 index 0000000..d219d0a Binary files /dev/null and b/FLSystem/Resources/微信 (1)1.png differ diff --git a/FLSystem/Resources/微信 (3).png b/FLSystem/Resources/微信 (3).png new file mode 100644 index 0000000..84ce67f Binary files /dev/null and b/FLSystem/Resources/微信 (3).png differ diff --git a/FLSystem/Resources/微信 (3)1.png b/FLSystem/Resources/微信 (3)1.png new file mode 100644 index 0000000..84ce67f Binary files /dev/null and b/FLSystem/Resources/微信 (3)1.png differ diff --git a/FLSystem/Resources/微信.png b/FLSystem/Resources/微信.png new file mode 100644 index 0000000..ee79ce7 Binary files /dev/null and b/FLSystem/Resources/微信.png differ diff --git a/FLSystem/Resources/快手登录.jpg b/FLSystem/Resources/快手登录.jpg new file mode 100644 index 0000000..723230c Binary files /dev/null and b/FLSystem/Resources/快手登录.jpg differ diff --git a/FLSystem/Resources/抖音.png b/FLSystem/Resources/抖音.png new file mode 100644 index 0000000..c2d86d3 Binary files /dev/null and b/FLSystem/Resources/抖音.png differ diff --git a/FLSystem/Resources/拼多多 (3).png b/FLSystem/Resources/拼多多 (3).png new file mode 100644 index 0000000..8ef281a Binary files /dev/null and b/FLSystem/Resources/拼多多 (3).png differ diff --git a/FLSystem/Resources/拼多多 (4).png b/FLSystem/Resources/拼多多 (4).png new file mode 100644 index 0000000..f7a2280 Binary files /dev/null and b/FLSystem/Resources/拼多多 (4).png differ diff --git a/FLSystem/Resources/拼多多 (4)1.png b/FLSystem/Resources/拼多多 (4)1.png new file mode 100644 index 0000000..f7a2280 Binary files /dev/null and b/FLSystem/Resources/拼多多 (4)1.png differ diff --git a/FLSystem/Resources/拼多多(1).png b/FLSystem/Resources/拼多多(1).png new file mode 100644 index 0000000..bb8a321 Binary files /dev/null and b/FLSystem/Resources/拼多多(1).png differ diff --git a/FLSystem/Resources/拼多多(1)1.png b/FLSystem/Resources/拼多多(1)1.png new file mode 100644 index 0000000..bb8a321 Binary files /dev/null and b/FLSystem/Resources/拼多多(1)1.png differ diff --git a/FLSystem/Resources/拼多多(2).png b/FLSystem/Resources/拼多多(2).png new file mode 100644 index 0000000..2959ff1 Binary files /dev/null and b/FLSystem/Resources/拼多多(2).png differ diff --git a/FLSystem/Resources/拼多多(2)1.png b/FLSystem/Resources/拼多多(2)1.png new file mode 100644 index 0000000..2959ff1 Binary files /dev/null and b/FLSystem/Resources/拼多多(2)1.png differ diff --git a/FLSystem/Resources/拼多多(3).png b/FLSystem/Resources/拼多多(3).png new file mode 100644 index 0000000..00a4c76 Binary files /dev/null and b/FLSystem/Resources/拼多多(3).png differ diff --git a/FLSystem/Resources/拼多多(3)1.png b/FLSystem/Resources/拼多多(3)1.png new file mode 100644 index 0000000..00a4c76 Binary files /dev/null and b/FLSystem/Resources/拼多多(3)1.png differ diff --git a/FLSystem/Resources/拼多多(4).png b/FLSystem/Resources/拼多多(4).png new file mode 100644 index 0000000..33a7e64 Binary files /dev/null and b/FLSystem/Resources/拼多多(4).png differ diff --git a/FLSystem/Resources/拼多多(4)1.png b/FLSystem/Resources/拼多多(4)1.png new file mode 100644 index 0000000..33a7e64 Binary files /dev/null and b/FLSystem/Resources/拼多多(4)1.png differ diff --git a/FLSystem/Resources/拼多多-20.png b/FLSystem/Resources/拼多多-20.png new file mode 100644 index 0000000..8ef281a Binary files /dev/null and b/FLSystem/Resources/拼多多-20.png differ diff --git a/FLSystem/Resources/拼多多.PNG b/FLSystem/Resources/拼多多.PNG new file mode 100644 index 0000000..1ed78b4 Binary files /dev/null and b/FLSystem/Resources/拼多多.PNG differ diff --git a/FLSystem/Resources/拼多多0.png b/FLSystem/Resources/拼多多0.png new file mode 100644 index 0000000..5b92019 Binary files /dev/null and b/FLSystem/Resources/拼多多0.png differ diff --git a/FLSystem/Resources/拼多多1.png b/FLSystem/Resources/拼多多1.png new file mode 100644 index 0000000..9c5b524 Binary files /dev/null and b/FLSystem/Resources/拼多多1.png differ diff --git a/FLSystem/Resources/拼多多2.png b/FLSystem/Resources/拼多多2.png new file mode 100644 index 0000000..367dcc6 Binary files /dev/null and b/FLSystem/Resources/拼多多2.png differ diff --git a/FLSystem/Resources/拼多多_20x20.png b/FLSystem/Resources/拼多多_20x20.png new file mode 100644 index 0000000..8ef281a Binary files /dev/null and b/FLSystem/Resources/拼多多_20x20.png differ diff --git a/FLSystem/Resources/拼多多_22.ico b/FLSystem/Resources/拼多多_22.ico new file mode 100644 index 0000000..22f4b55 Binary files /dev/null and b/FLSystem/Resources/拼多多_22.ico differ diff --git a/FLSystem/Resources/拼多多_25x25.png b/FLSystem/Resources/拼多多_25x25.png new file mode 100644 index 0000000..41b05c7 Binary files /dev/null and b/FLSystem/Resources/拼多多_25x25.png differ diff --git a/FLSystem/Resources/授权 (1).png b/FLSystem/Resources/授权 (1).png new file mode 100644 index 0000000..c8ccf98 Binary files /dev/null and b/FLSystem/Resources/授权 (1).png differ diff --git a/FLSystem/Resources/授权 (1)1.png b/FLSystem/Resources/授权 (1)1.png new file mode 100644 index 0000000..c8ccf98 Binary files /dev/null and b/FLSystem/Resources/授权 (1)1.png differ diff --git a/FLSystem/Resources/授权 (2).png b/FLSystem/Resources/授权 (2).png new file mode 100644 index 0000000..8b8ef72 Binary files /dev/null and b/FLSystem/Resources/授权 (2).png differ diff --git a/FLSystem/Resources/授权 (2)1.png b/FLSystem/Resources/授权 (2)1.png new file mode 100644 index 0000000..8b8ef72 Binary files /dev/null and b/FLSystem/Resources/授权 (2)1.png differ diff --git a/FLSystem/Resources/授权 (3).png b/FLSystem/Resources/授权 (3).png new file mode 100644 index 0000000..6522854 Binary files /dev/null and b/FLSystem/Resources/授权 (3).png differ diff --git a/FLSystem/Resources/授权 (3)1.png b/FLSystem/Resources/授权 (3)1.png new file mode 100644 index 0000000..6522854 Binary files /dev/null and b/FLSystem/Resources/授权 (3)1.png differ diff --git a/FLSystem/Resources/授权(2).png b/FLSystem/Resources/授权(2).png new file mode 100644 index 0000000..6a23256 Binary files /dev/null and b/FLSystem/Resources/授权(2).png differ diff --git a/FLSystem/Resources/授权(2)1.png b/FLSystem/Resources/授权(2)1.png new file mode 100644 index 0000000..6a23256 Binary files /dev/null and b/FLSystem/Resources/授权(2)1.png differ diff --git a/FLSystem/Resources/授权.png b/FLSystem/Resources/授权.png new file mode 100644 index 0000000..4f02489 Binary files /dev/null and b/FLSystem/Resources/授权.png differ diff --git a/FLSystem/Resources/授权1.png b/FLSystem/Resources/授权1.png new file mode 100644 index 0000000..c5db2a3 Binary files /dev/null and b/FLSystem/Resources/授权1.png differ diff --git a/FLSystem/Resources/授权zh-01.png b/FLSystem/Resources/授权zh-01.png new file mode 100644 index 0000000..2366fe0 Binary files /dev/null and b/FLSystem/Resources/授权zh-01.png differ diff --git a/FLSystem/Resources/授权zh-011.png b/FLSystem/Resources/授权zh-011.png new file mode 100644 index 0000000..2366fe0 Binary files /dev/null and b/FLSystem/Resources/授权zh-011.png differ diff --git a/FLSystem/Resources/授权成功.png b/FLSystem/Resources/授权成功.png new file mode 100644 index 0000000..45ddbdc Binary files /dev/null and b/FLSystem/Resources/授权成功.png differ diff --git a/FLSystem/Resources/提升成长值.png b/FLSystem/Resources/提升成长值.png new file mode 100644 index 0000000..c63cf60 Binary files /dev/null and b/FLSystem/Resources/提升成长值.png differ diff --git a/FLSystem/Resources/未标题-2 拷贝.ico b/FLSystem/Resources/未标题-2 拷贝.ico new file mode 100644 index 0000000..b65d15b Binary files /dev/null and b/FLSystem/Resources/未标题-2 拷贝.ico differ diff --git a/FLSystem/Resources/未标题-2 拷贝1.ico b/FLSystem/Resources/未标题-2 拷贝1.ico new file mode 100644 index 0000000..3019ece Binary files /dev/null and b/FLSystem/Resources/未标题-2 拷贝1.ico differ diff --git a/FLSystem/Resources/未标题-2 拷贝2.ico b/FLSystem/Resources/未标题-2 拷贝2.ico new file mode 100644 index 0000000..5027f20 Binary files /dev/null and b/FLSystem/Resources/未标题-2 拷贝2.ico differ diff --git a/FLSystem/Resources/未标题-2.ico b/FLSystem/Resources/未标题-2.ico new file mode 100644 index 0000000..c501850 Binary files /dev/null and b/FLSystem/Resources/未标题-2.ico differ diff --git a/FLSystem/Resources/机器人(1).png b/FLSystem/Resources/机器人(1).png new file mode 100644 index 0000000..0ee4a19 Binary files /dev/null and b/FLSystem/Resources/机器人(1).png differ diff --git a/FLSystem/Resources/机器人(1)1.png b/FLSystem/Resources/机器人(1)1.png new file mode 100644 index 0000000..0ee4a19 Binary files /dev/null and b/FLSystem/Resources/机器人(1)1.png differ diff --git a/FLSystem/Resources/机器人_小鲁02.png b/FLSystem/Resources/机器人_小鲁02.png new file mode 100644 index 0000000..02b5d9e Binary files /dev/null and b/FLSystem/Resources/机器人_小鲁02.png differ diff --git a/FLSystem/Resources/权限(1).png b/FLSystem/Resources/权限(1).png new file mode 100644 index 0000000..a97af64 Binary files /dev/null and b/FLSystem/Resources/权限(1).png differ diff --git a/FLSystem/Resources/权限(1)1.png b/FLSystem/Resources/权限(1)1.png new file mode 100644 index 0000000..a97af64 Binary files /dev/null and b/FLSystem/Resources/权限(1)1.png differ diff --git a/FLSystem/Resources/权限(2).png b/FLSystem/Resources/权限(2).png new file mode 100644 index 0000000..6bd4d36 Binary files /dev/null and b/FLSystem/Resources/权限(2).png differ diff --git a/FLSystem/Resources/权限(2)1.png b/FLSystem/Resources/权限(2)1.png new file mode 100644 index 0000000..6bd4d36 Binary files /dev/null and b/FLSystem/Resources/权限(2)1.png differ diff --git a/FLSystem/Resources/权限.png b/FLSystem/Resources/权限.png new file mode 100644 index 0000000..92caf05 Binary files /dev/null and b/FLSystem/Resources/权限.png differ diff --git a/FLSystem/Resources/淘宝 (2).png b/FLSystem/Resources/淘宝 (2).png new file mode 100644 index 0000000..e0bd8b7 Binary files /dev/null and b/FLSystem/Resources/淘宝 (2).png differ diff --git a/FLSystem/Resources/淘宝 (2)1.png b/FLSystem/Resources/淘宝 (2)1.png new file mode 100644 index 0000000..e0bd8b7 Binary files /dev/null and b/FLSystem/Resources/淘宝 (2)1.png differ diff --git a/FLSystem/Resources/淘宝(1).png b/FLSystem/Resources/淘宝(1).png new file mode 100644 index 0000000..9a7cc0d Binary files /dev/null and b/FLSystem/Resources/淘宝(1).png differ diff --git a/FLSystem/Resources/淘宝(1)1.png b/FLSystem/Resources/淘宝(1)1.png new file mode 100644 index 0000000..9a7cc0d Binary files /dev/null and b/FLSystem/Resources/淘宝(1)1.png differ diff --git a/FLSystem/Resources/淘宝(2).png b/FLSystem/Resources/淘宝(2).png new file mode 100644 index 0000000..8a9b14e Binary files /dev/null and b/FLSystem/Resources/淘宝(2).png differ diff --git a/FLSystem/Resources/淘宝(2)1.png b/FLSystem/Resources/淘宝(2)1.png new file mode 100644 index 0000000..8a9b14e Binary files /dev/null and b/FLSystem/Resources/淘宝(2)1.png differ diff --git a/FLSystem/Resources/淘宝-20.png b/FLSystem/Resources/淘宝-20.png new file mode 100644 index 0000000..75a00a2 Binary files /dev/null and b/FLSystem/Resources/淘宝-20.png differ diff --git a/FLSystem/Resources/淘宝.png b/FLSystem/Resources/淘宝.png new file mode 100644 index 0000000..74a2e2c Binary files /dev/null and b/FLSystem/Resources/淘宝.png differ diff --git a/FLSystem/Resources/淘宝_25x_25.png b/FLSystem/Resources/淘宝_25x_25.png new file mode 100644 index 0000000..80710f9 Binary files /dev/null and b/FLSystem/Resources/淘宝_25x_25.png differ diff --git a/FLSystem/Resources/淘宝联盟(1).png b/FLSystem/Resources/淘宝联盟(1).png new file mode 100644 index 0000000..8da8fec Binary files /dev/null and b/FLSystem/Resources/淘宝联盟(1).png differ diff --git a/FLSystem/Resources/淘宝联盟(1)1.png b/FLSystem/Resources/淘宝联盟(1)1.png new file mode 100644 index 0000000..8da8fec Binary files /dev/null and b/FLSystem/Resources/淘宝联盟(1)1.png differ diff --git a/FLSystem/Resources/淘宝联盟.png b/FLSystem/Resources/淘宝联盟.png new file mode 100644 index 0000000..b31a8f6 Binary files /dev/null and b/FLSystem/Resources/淘宝联盟.png differ diff --git a/FLSystem/Resources/用户管理.png b/FLSystem/Resources/用户管理.png new file mode 100644 index 0000000..5729813 Binary files /dev/null and b/FLSystem/Resources/用户管理.png differ diff --git a/FLSystem/Resources/留言 (1).png b/FLSystem/Resources/留言 (1).png new file mode 100644 index 0000000..e49287e Binary files /dev/null and b/FLSystem/Resources/留言 (1).png differ diff --git a/FLSystem/Resources/留言 (2).png b/FLSystem/Resources/留言 (2).png new file mode 100644 index 0000000..bce50a3 Binary files /dev/null and b/FLSystem/Resources/留言 (2).png differ diff --git a/FLSystem/Resources/留言 (3).png b/FLSystem/Resources/留言 (3).png new file mode 100644 index 0000000..7a02ed6 Binary files /dev/null and b/FLSystem/Resources/留言 (3).png differ diff --git a/FLSystem/Resources/留言.png b/FLSystem/Resources/留言.png new file mode 100644 index 0000000..2e2dbb5 Binary files /dev/null and b/FLSystem/Resources/留言.png differ diff --git a/FLSystem/Resources/登录 (1).png b/FLSystem/Resources/登录 (1).png new file mode 100644 index 0000000..5c8cde8 Binary files /dev/null and b/FLSystem/Resources/登录 (1).png differ diff --git a/FLSystem/Resources/登录 (1)1.png b/FLSystem/Resources/登录 (1)1.png new file mode 100644 index 0000000..5c8cde8 Binary files /dev/null and b/FLSystem/Resources/登录 (1)1.png differ diff --git a/FLSystem/Resources/登录.png b/FLSystem/Resources/登录.png new file mode 100644 index 0000000..93080d6 Binary files /dev/null and b/FLSystem/Resources/登录.png differ diff --git a/FLSystem/Resources/登录密码.png b/FLSystem/Resources/登录密码.png new file mode 100644 index 0000000..e881efb Binary files /dev/null and b/FLSystem/Resources/登录密码.png differ diff --git a/FLSystem/Resources/登录验证.png b/FLSystem/Resources/登录验证.png new file mode 100644 index 0000000..a7977ee Binary files /dev/null and b/FLSystem/Resources/登录验证.png differ diff --git a/FLSystem/Resources/白名单 (1).png b/FLSystem/Resources/白名单 (1).png new file mode 100644 index 0000000..de57b7d Binary files /dev/null and b/FLSystem/Resources/白名单 (1).png differ diff --git a/FLSystem/Resources/白名单 (1)1.png b/FLSystem/Resources/白名单 (1)1.png new file mode 100644 index 0000000..de57b7d Binary files /dev/null and b/FLSystem/Resources/白名单 (1)1.png differ diff --git a/FLSystem/Resources/白名单 (1)11.png b/FLSystem/Resources/白名单 (1)11.png new file mode 100644 index 0000000..de57b7d Binary files /dev/null and b/FLSystem/Resources/白名单 (1)11.png differ diff --git a/FLSystem/Resources/白名单 (1)2.png b/FLSystem/Resources/白名单 (1)2.png new file mode 100644 index 0000000..de57b7d Binary files /dev/null and b/FLSystem/Resources/白名单 (1)2.png differ diff --git a/FLSystem/Resources/白名单 (2).png b/FLSystem/Resources/白名单 (2).png new file mode 100644 index 0000000..606f8cb Binary files /dev/null and b/FLSystem/Resources/白名单 (2).png differ diff --git a/FLSystem/Resources/白名单 (2)1.png b/FLSystem/Resources/白名单 (2)1.png new file mode 100644 index 0000000..606f8cb Binary files /dev/null and b/FLSystem/Resources/白名单 (2)1.png differ diff --git a/FLSystem/Resources/第三方登录微信.png b/FLSystem/Resources/第三方登录微信.png new file mode 100644 index 0000000..cf5dbea Binary files /dev/null and b/FLSystem/Resources/第三方登录微信.png differ diff --git a/FLSystem/Resources/管理-从账号管理.png b/FLSystem/Resources/管理-从账号管理.png new file mode 100644 index 0000000..bf61fbf Binary files /dev/null and b/FLSystem/Resources/管理-从账号管理.png differ diff --git a/FLSystem/Resources/管理-从账号管理1.png b/FLSystem/Resources/管理-从账号管理1.png new file mode 100644 index 0000000..bf61fbf Binary files /dev/null and b/FLSystem/Resources/管理-从账号管理1.png differ diff --git a/FLSystem/Resources/续费.png b/FLSystem/Resources/续费.png new file mode 100644 index 0000000..27bf365 Binary files /dev/null and b/FLSystem/Resources/续费.png differ diff --git a/FLSystem/Resources/绿企联盟.png b/FLSystem/Resources/绿企联盟.png new file mode 100644 index 0000000..4e10e58 Binary files /dev/null and b/FLSystem/Resources/绿企联盟.png differ diff --git a/FLSystem/Resources/联盟(1).png b/FLSystem/Resources/联盟(1).png new file mode 100644 index 0000000..289ec47 Binary files /dev/null and b/FLSystem/Resources/联盟(1).png differ diff --git a/FLSystem/Resources/联盟(1)1.png b/FLSystem/Resources/联盟(1)1.png new file mode 100644 index 0000000..289ec47 Binary files /dev/null and b/FLSystem/Resources/联盟(1)1.png differ diff --git a/FLSystem/Resources/联盟.png b/FLSystem/Resources/联盟.png new file mode 100644 index 0000000..85238bc Binary files /dev/null and b/FLSystem/Resources/联盟.png differ diff --git a/FLSystem/Resources/联盟1.png b/FLSystem/Resources/联盟1.png new file mode 100644 index 0000000..dac61ba Binary files /dev/null and b/FLSystem/Resources/联盟1.png differ diff --git a/FLSystem/Resources/联盟2.png b/FLSystem/Resources/联盟2.png new file mode 100644 index 0000000..39a6f5b Binary files /dev/null and b/FLSystem/Resources/联盟2.png differ diff --git a/FLSystem/Resources/联盟21.png b/FLSystem/Resources/联盟21.png new file mode 100644 index 0000000..39a6f5b Binary files /dev/null and b/FLSystem/Resources/联盟21.png differ diff --git a/FLSystem/Resources/联盟任务.png b/FLSystem/Resources/联盟任务.png new file mode 100644 index 0000000..2511a1f Binary files /dev/null and b/FLSystem/Resources/联盟任务.png differ diff --git a/FLSystem/Resources/苏宁小.jpg b/FLSystem/Resources/苏宁小.jpg new file mode 100644 index 0000000..812589f Binary files /dev/null and b/FLSystem/Resources/苏宁小.jpg differ diff --git a/FLSystem/Resources/订单 (1).png b/FLSystem/Resources/订单 (1).png new file mode 100644 index 0000000..2373a8f Binary files /dev/null and b/FLSystem/Resources/订单 (1).png differ diff --git a/FLSystem/Resources/订单 (1)1.png b/FLSystem/Resources/订单 (1)1.png new file mode 100644 index 0000000..2373a8f Binary files /dev/null and b/FLSystem/Resources/订单 (1)1.png differ diff --git a/FLSystem/Resources/订单 (2).png b/FLSystem/Resources/订单 (2).png new file mode 100644 index 0000000..4991d10 Binary files /dev/null and b/FLSystem/Resources/订单 (2).png differ diff --git a/FLSystem/Resources/订单 (2)1.png b/FLSystem/Resources/订单 (2)1.png new file mode 100644 index 0000000..4991d10 Binary files /dev/null and b/FLSystem/Resources/订单 (2)1.png differ diff --git a/FLSystem/Resources/订单 (3).png b/FLSystem/Resources/订单 (3).png new file mode 100644 index 0000000..619df73 Binary files /dev/null and b/FLSystem/Resources/订单 (3).png differ diff --git a/FLSystem/Resources/订单 (3)1.png b/FLSystem/Resources/订单 (3)1.png new file mode 100644 index 0000000..619df73 Binary files /dev/null and b/FLSystem/Resources/订单 (3)1.png differ diff --git a/FLSystem/Resources/订单.png b/FLSystem/Resources/订单.png new file mode 100644 index 0000000..4c75ca4 Binary files /dev/null and b/FLSystem/Resources/订单.png differ diff --git a/FLSystem/Resources/认证.png b/FLSystem/Resources/认证.png new file mode 100644 index 0000000..263aa58 Binary files /dev/null and b/FLSystem/Resources/认证.png differ diff --git a/FLSystem/Resources/认证1.png b/FLSystem/Resources/认证1.png new file mode 100644 index 0000000..263aa58 Binary files /dev/null and b/FLSystem/Resources/认证1.png differ diff --git a/FLSystem/Resources/调试中.png b/FLSystem/Resources/调试中.png new file mode 100644 index 0000000..8fe5a55 Binary files /dev/null and b/FLSystem/Resources/调试中.png differ diff --git a/FLSystem/Resources/账单 (1).png b/FLSystem/Resources/账单 (1).png new file mode 100644 index 0000000..61e7e5c Binary files /dev/null and b/FLSystem/Resources/账单 (1).png differ diff --git a/FLSystem/Resources/账单 (1)1.png b/FLSystem/Resources/账单 (1)1.png new file mode 100644 index 0000000..61e7e5c Binary files /dev/null and b/FLSystem/Resources/账单 (1)1.png differ diff --git a/FLSystem/Resources/账单.png b/FLSystem/Resources/账单.png new file mode 100644 index 0000000..a09e8ee Binary files /dev/null and b/FLSystem/Resources/账单.png differ diff --git a/FLSystem/Resources/返利机器人.exe b/FLSystem/Resources/返利机器人.exe new file mode 100644 index 0000000..fcd3422 Binary files /dev/null and b/FLSystem/Resources/返利机器人.exe differ diff --git a/FLSystem/Resources/通知 (1).png b/FLSystem/Resources/通知 (1).png new file mode 100644 index 0000000..caf4e76 Binary files /dev/null and b/FLSystem/Resources/通知 (1).png differ diff --git a/FLSystem/Resources/通知 (1)1.png b/FLSystem/Resources/通知 (1)1.png new file mode 100644 index 0000000..caf4e76 Binary files /dev/null and b/FLSystem/Resources/通知 (1)1.png differ diff --git a/FLSystem/Resources/通知 (2).png b/FLSystem/Resources/通知 (2).png new file mode 100644 index 0000000..0599e5a Binary files /dev/null and b/FLSystem/Resources/通知 (2).png differ diff --git a/FLSystem/Resources/通知 (2)1.png b/FLSystem/Resources/通知 (2)1.png new file mode 100644 index 0000000..0599e5a Binary files /dev/null and b/FLSystem/Resources/通知 (2)1.png differ diff --git a/FLSystem/Resources/通知 (3).png b/FLSystem/Resources/通知 (3).png new file mode 100644 index 0000000..c27bdea Binary files /dev/null and b/FLSystem/Resources/通知 (3).png differ diff --git a/FLSystem/Resources/通知 (3)1.png b/FLSystem/Resources/通知 (3)1.png new file mode 100644 index 0000000..c27bdea Binary files /dev/null and b/FLSystem/Resources/通知 (3)1.png differ diff --git a/FLSystem/Resources/通知.png b/FLSystem/Resources/通知.png new file mode 100644 index 0000000..88f4734 Binary files /dev/null and b/FLSystem/Resources/通知.png differ diff --git a/FLSystem/Resources/重启 (1).png b/FLSystem/Resources/重启 (1).png new file mode 100644 index 0000000..42f5ea6 Binary files /dev/null and b/FLSystem/Resources/重启 (1).png differ diff --git a/FLSystem/Resources/重启 (1)1.png b/FLSystem/Resources/重启 (1)1.png new file mode 100644 index 0000000..42f5ea6 Binary files /dev/null and b/FLSystem/Resources/重启 (1)1.png differ diff --git a/FLSystem/Resources/重启 (2).png b/FLSystem/Resources/重启 (2).png new file mode 100644 index 0000000..8ffa8ed Binary files /dev/null and b/FLSystem/Resources/重启 (2).png differ diff --git a/FLSystem/Resources/重启 (2)1.png b/FLSystem/Resources/重启 (2)1.png new file mode 100644 index 0000000..8ffa8ed Binary files /dev/null and b/FLSystem/Resources/重启 (2)1.png differ diff --git a/FLSystem/Resources/重启 (3).png b/FLSystem/Resources/重启 (3).png new file mode 100644 index 0000000..d19317f Binary files /dev/null and b/FLSystem/Resources/重启 (3).png differ diff --git a/FLSystem/Resources/重启 (3)1.png b/FLSystem/Resources/重启 (3)1.png new file mode 100644 index 0000000..d19317f Binary files /dev/null and b/FLSystem/Resources/重启 (3)1.png differ diff --git a/FLSystem/Resources/钱.png b/FLSystem/Resources/钱.png new file mode 100644 index 0000000..223fe18 Binary files /dev/null and b/FLSystem/Resources/钱.png differ diff --git a/FLSystem/Resources/锁.png b/FLSystem/Resources/锁.png new file mode 100644 index 0000000..dab7ad8 Binary files /dev/null and b/FLSystem/Resources/锁.png differ diff --git a/FLSystem/Resources/锁.svg b/FLSystem/Resources/锁.svg new file mode 100644 index 0000000..fdbd6ee --- /dev/null +++ b/FLSystem/Resources/锁.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614762918775" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3485" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M843.9 448.2h-35.4v-84.9c0-164.9-134.2-299.1-299.1-299.1S210.2 198.4 210.2 363.3v84.9h-35.4c-33.6 0-60.9 27.3-60.9 60.9v389.6c0 33.6 27.3 60.9 60.9 60.9h669.1c33.6 0 60.9-27.3 60.9-60.9V509.1c-0.1-33.6-27.4-60.9-60.9-60.9z m-576.8-84.9c0-133.6 108.7-242.3 242.3-242.3s242.3 108.7 242.3 242.3v84.9H267.1v-84.9z m580.8 535.4c0 2.2-1.8 4-4 4H174.8c-2.2 0-4-1.8-4-4V509.1c0-2.2 1.8-4 4-4h669.1c2.2 0 4 1.8 4 4v389.6z" fill="#FC592D" p-id="3486"></path><path d="M537.7 735.2V609.7c0-15.7-12.7-28.4-28.4-28.4s-28.4 12.7-28.4 28.4v125.5c-23.4 12.9-37.5 40.6-28.1 70.7 5.5 17.7 19.9 32.2 37.6 37.8 40.8 12.8 78.5-17.6 78.5-56.5-0.1-22.5-12.7-41.9-31.2-52z" fill="#FFCE00" p-id="3487"></path></svg> \ No newline at end of file diff --git a/FLSystem/Resources/阿里妈妈.png b/FLSystem/Resources/阿里妈妈.png new file mode 100644 index 0000000..5206458 Binary files /dev/null and b/FLSystem/Resources/阿里妈妈.png differ diff --git a/FLSystem/Resources/黑名单 (1).png b/FLSystem/Resources/黑名单 (1).png new file mode 100644 index 0000000..812d302 Binary files /dev/null and b/FLSystem/Resources/黑名单 (1).png differ diff --git a/FLSystem/Resources/黑名单 (1)1.png b/FLSystem/Resources/黑名单 (1)1.png new file mode 100644 index 0000000..812d302 Binary files /dev/null and b/FLSystem/Resources/黑名单 (1)1.png differ diff --git a/FLSystem/Resources/黑名单 (2).png b/FLSystem/Resources/黑名单 (2).png new file mode 100644 index 0000000..42df056 Binary files /dev/null and b/FLSystem/Resources/黑名单 (2).png differ diff --git a/FLSystem/Resources/黑名单 (2)1.png b/FLSystem/Resources/黑名单 (2)1.png new file mode 100644 index 0000000..42df056 Binary files /dev/null and b/FLSystem/Resources/黑名单 (2)1.png differ diff --git a/FLSystem/Resources/黑名单 (3).png b/FLSystem/Resources/黑名单 (3).png new file mode 100644 index 0000000..8cf438b Binary files /dev/null and b/FLSystem/Resources/黑名单 (3).png differ diff --git a/FLSystem/Resources/黑名单 (3)1.png b/FLSystem/Resources/黑名单 (3)1.png new file mode 100644 index 0000000..8cf438b Binary files /dev/null and b/FLSystem/Resources/黑名单 (3)1.png differ diff --git a/FLSystem/Resources/黑名单 (4).png b/FLSystem/Resources/黑名单 (4).png new file mode 100644 index 0000000..5130c17 Binary files /dev/null and b/FLSystem/Resources/黑名单 (4).png differ diff --git a/FLSystem/Resources/黑名单 (4)1.png b/FLSystem/Resources/黑名单 (4)1.png new file mode 100644 index 0000000..5130c17 Binary files /dev/null and b/FLSystem/Resources/黑名单 (4)1.png differ diff --git a/FLSystem/TempEntity.cs b/FLSystem/TempEntity.cs new file mode 100644 index 0000000..b412bb2 --- /dev/null +++ b/FLSystem/TempEntity.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FLSystem +{ + public class TempEntity + { + } + + /// <summary> + /// 界面菜单导航栏 + /// </summary> + public class NavTree + { + public bool check { get; set; } + + public string name { get; set; } + + /// <summary> + /// 下标,用于标识第几个菜单 + /// </summary> + public int index { get; set; } + + /// <summary> + /// 用户标识第几层 + /// </summary> + public int ceng { get; set; } + } +} diff --git a/FLSystem/Test.Designer.cs b/FLSystem/Test.Designer.cs new file mode 100644 index 0000000..66b947e --- /dev/null +++ b/FLSystem/Test.Designer.cs @@ -0,0 +1,73 @@ +namespace FLSystem +{ + partial class Test + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(77, 29); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 0; + this.button1.Text = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(194, 29); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 23); + this.button2.TabIndex = 1; + this.button2.Text = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // Test + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Name = "Test"; + this.Text = "Test"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + } +} \ No newline at end of file diff --git a/FLSystem/Test.cs b/FLSystem/Test.cs new file mode 100644 index 0000000..a024f9b --- /dev/null +++ b/FLSystem/Test.cs @@ -0,0 +1,36 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using static DevExpress.Utils.Drawing.Helpers.NativeMethods; + +namespace FLSystem +{ + public partial class Test : Form + { + public Test() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + //WXClientImpl_HOOK hook = new WXClientImpl_HOOK(); + //hook.ShowLogin(); + + // this.Text = "MyWechat" + hook.Process.Id; + } + + + private void button2_Click(object sender, EventArgs e) + { + } + } +} diff --git a/FLSystem/Test.resx b/FLSystem/Test.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/FLSystem/Test.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/FLSystem/Tools.cs b/FLSystem/Tools.cs new file mode 100644 index 0000000..362d468 --- /dev/null +++ b/FLSystem/Tools.cs @@ -0,0 +1,546 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.Tools; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Microsoft.Win32; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using static FLSystem.Forms.point_manage_control; + +namespace FLSystem +{ + #region 同步Win系统时间 + public class Daytime + { + // Internet Time Server class by Alastair Dallas 01/27/04 + + // Number of seconds + private const int THRESHOLD_SECONDS = 15; + // that Windows clock can deviate from NIST and still be okay + + //Server IP addresses from + //http://www.boulder.nist.gov/timefreq/service/time-servers.html + private static string[] Servers = { + //"129.6.15.28", + //"129.6.15.29", + //"132.163.4.101", + //"132.163.4.102", + //"132.163.4.103", + //"128.138.140.44", + //"192.43.244.18", + //"131.107.1.10", + //"66.243.43.21", + //"216.200.93.8", + //"208.184.49.9", + //"207.126.98.204", + //"205.188.185.33" +"time.windows.com"//微软时间同步服务器 + }; + public static string LastHost = ""; + + public static DateTime LastSysTime; + public static DateTime GetTime() + { + //Returns UTC/GMT using an NIST server if possible, + // degrading to simply returning the system clock + + //If we are successful in getting NIST time, then + // LastHost indicates which server was used and + // LastSysTime contains the system time of the call + // If LastSysTime is not within 15 seconds of NIST time, + // the system clock may need to be reset + // If LastHost is "", time is equal to system clock + + string host = null; + DateTime result = default(DateTime); + + LastHost = ""; + foreach (string host_loopVariable in Servers) + { + host = host_loopVariable; + result = GetNISTTime(host); + if (result > DateTime.MinValue) + { + LastHost = host; + break; // TODO: might not be correct. Was : Exit For + } + } + + if (string.IsNullOrEmpty(LastHost)) + { + //No server in list was successful so use system time + result = DateTime.Now; + } + + return result; + } + + public static int SecondsDifference(DateTime dt1, DateTime dt2) + { + TimeSpan span = dt1.Subtract(dt2); + return span.Seconds + (span.Minutes * 60) + (span.Hours * 360); + } + + public static bool WindowsClockIncorrect() + { + DateTime nist = GetTime(); + if ((Math.Abs(SecondsDifference(nist, LastSysTime)) > THRESHOLD_SECONDS)) + { + return true; + } + return false; + } + + private static DateTime GetNISTTime(string host) + { + //Returns DateTime.MinValue if host unreachable or does not produce time + DateTime result = default(DateTime); + string timeStr = null; + + try + { + StreamReader reader = new StreamReader(new TcpClient(host, 13).GetStream()); + LastSysTime = DateTime.UtcNow; + timeStr = reader.ReadToEnd(); + reader.Close(); + } + catch (SocketException ex) + { + //Couldn't connect to server, transmission error + Debug.WriteLine("Socket Exception [" + host + "]"); + return DateTime.MinValue; + } + catch (Exception ex) + { + //Some other error, such as Stream under/overflow + return DateTime.MinValue; + } + + //Parse timeStr + if ((timeStr.Substring(38, 9) != "UTC(NIST)")) + { + //This signature should be there + return DateTime.MinValue; + } + if ((timeStr.Substring(30, 1) != "0")) + { + //Server reports non-optimum status, time off by as much as 5 seconds + return DateTime.MinValue; + //Try a different server + } + + int jd = int.Parse(timeStr.Substring(1, 5)); + int yr = int.Parse(timeStr.Substring(7, 2)); + int mo = int.Parse(timeStr.Substring(10, 2)); + int dy = int.Parse(timeStr.Substring(13, 2)); + int hr = int.Parse(timeStr.Substring(16, 2)); + int mm = int.Parse(timeStr.Substring(19, 2)); + int sc = int.Parse(timeStr.Substring(22, 2)); + + if ((jd < 15020)) + { + //Date is before 1900 + return DateTime.MinValue; + } + if ((jd > 51544)) + yr += 2000; + else + yr += 1900; + + return new DateTime(yr, mo, dy, hr, mm, sc); + } + + [StructLayout(LayoutKind.Sequential)] + public struct SYSTEMTIME + { + public Int16 wYear; + public Int16 wMonth; + public Int16 wDayOfWeek; + public Int16 wDay; + public Int16 wHour; + public Int16 wMinute; + public Int16 wSecond; + public Int16 wMilliseconds; + } + [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + private static extern Int32 GetSystemTime(ref SYSTEMTIME stru); + [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + private static extern Int32 SetSystemTime(ref SYSTEMTIME stru); + + [DllImport("Kernel32.dll")] + public static extern void GetLocalTime(ref SYSTEMTIME lpSystemTime); + + [DllImport("Kernel32.dll")] + public static extern bool SetLocalTime(ref SYSTEMTIME lpSystemTime); + + + public static void SetWindowsClock(DateTime dt) + { + //Sets system time. Note: Use UTC time; Windows will apply time zone + + SYSTEMTIME timeStru = default(SYSTEMTIME); + Int32 result = default(Int32); + + timeStru.wYear = (Int16)dt.Year; + timeStru.wMonth = (Int16)dt.Month; + timeStru.wDay = (Int16)dt.Day; + timeStru.wDayOfWeek = (Int16)dt.DayOfWeek; + timeStru.wHour = (Int16)dt.Hour; + timeStru.wMinute = (Int16)dt.Minute; + timeStru.wSecond = (Int16)dt.Second; + timeStru.wMilliseconds = (Int16)dt.Millisecond; + SetLocalTime(ref timeStru); + } + } + #endregion + + public class Tools + { + //private static Dictionary<string, object> Config { get; set; } + + static Tools() + { + EventClient.MethodEvent += EventClient_MethodEvent; + } + + private static void EventClient_MethodEvent(object sender, MethodType e) + { + if (e == MethodType.刷新配置文件) + { + ApiClient.GetPointManageConfig(true); + //Config = Util.ReadConfig("插件-积分管理-配置", true);//刷新积分管理中的配置文件 + } + } + + /// <summary> + /// 获取积分插件配置文件 + /// </summary> + /// <param name="flush"></param> + /// <returns></returns> + //public static Dictionary<string, object> GetPointConfig(bool flush = false) + //{ + // if (Config == null || flush) + // Config = Util.ReadConfig("插件-积分管理-配置", true);//刷新积分管理中的配置文件 + // return Config; + //} + + + /// <summary> + /// 判断.Net Framework的Release是否符合需要 + /// (.Net Framework 版本在4.0及以上) + /// </summary> + ///<param name="release">需要的版本 version = 4.5 release = 379893 + /// <returns></returns> + public static bool GetDotNetRelease(int release) + { + const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\"; + using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey)) + { + if (ndpKey != null && ndpKey.GetValue("Release") != null) + { + return (int)ndpKey.GetValue("Release") >= release ? true : false; + } + return false; + } + } + + public static void GetFileFromNetUrl(string url, string file) + { + try + { + System.Net.WebRequest req = System.Net.WebRequest.Create(url); + req.Method = "GET"; + //获得用户名密码的Base64编码 添加Authorization到HTTP头 不需要的账号密码的可以注释下面两行代码 + string code = Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}", "userName", "passWord"))); + req.Headers.Add("Authorization", "Basic " + code); + byte[] fileBytes; + using (WebResponse webRes = req.GetResponse()) + { + int length = (int)webRes.ContentLength; + HttpWebResponse response = webRes as HttpWebResponse; + Stream stream = response.GetResponseStream(); + + //读取到内存 + MemoryStream stmMemory = new MemoryStream(); + byte[] buffer = new byte[length]; + int i; + //将字节逐个放入到Byte中 + while ((i = stream.Read(buffer, 0, buffer.Length)) > 0) + { + stmMemory.Write(buffer, 0, i); + } + fileBytes = stmMemory.ToArray();//文件流Byte,需要文件流可直接return,不需要下面的保存代码 + stmMemory.Close(); + + MemoryStream m = new MemoryStream(fileBytes); + //string file = Util.MapFile("NDP46-KB3045560-Web.exe", @"Cache\_NetFramework");//可根据文件类型自定义后缀 + FileStream fs = new FileStream(file, FileMode.OpenOrCreate); + m.WriteTo(fs); + m.Close(); + fs.Close(); + } + } + catch (System.Exception ex) + { + throw ex; + } + } + + } + + public class Utils + { + //private static Timer timer = new Timer(new TimerCallback(ShpaySync), null, 0, 1000 * 60 * 10); + + //private static bool IsRunSendShPay = false; + //private static void ShpaySync(object state) + //{ + // if (IsRunSendShPay) return; + // IsRunSendShPay = true; + // try + // { + // //EventClient.OnEvent("", "执行状态:" + ApiClient.Setting.SystemConfig.send_shpay_switch); + // if (!ApiClient.Setting.SystemConfig.send_shpay_switch) return; + // var db = ApiClient.GetSession(); + // var time = HttpExtend.GetTimeStamp(DateTime.Now.AddDays(-1)); + // var shpayList = db.Queryable<fl_shpay_hist>().Where(f => f.paytype == PayGetType.未领取 && f.sendtime == 0 && f.ctime <= time).ToList(); + // //EventClient.OnEvent("", "执行的数量:" + shpayList.Count); + // SendShPayMes(shpayList); + // } + // catch (Exception ex) + // { + // EventClient.OnEvent("", $"通知24小时商户未领取异常:{ex.Message} - {ex.StackTrace}"); + // } + // finally + // { + // IsRunSendShPay = false; + // } + //} + + #region 兑换发送消息 + public static void SendShPayMes(List<fl_shpay_hist> shpayList) + { + try + { + if (shpayList == null || shpayList.Count == 0) return; + var session = ApiClient.GetSession(); + + var yjPayList = new List<fl_shpay_hist>();//已经领取的连接 + var sendShpayDic = new Dictionary<string, List<fl_shpay_hist>>();//需要发送的商户 + + var ShPayTmpDic = new Dictionary<string, List<ShPayTmp>>();//需要发送并且能发送商户小程序 + + #region 重新获取商户地址并发送消息 + var timedate = shpayList.GroupBy(f => f.ctimedate).Select(f => f.Key).ToList(); + //EventClient.OnEvent("", "A " + timedate.Count); + foreach (var date in timedate) + { + var strb = new StringBuilder(); + var html = string.Empty; + try + { + strb.Append("手动处理未领取的商户:"); + var arr = shpayList.Where(f => f.ctimedate == date).Select(f => "\"" + f.orderid + "\"").ToList(); + if (arr.Count() != 0) + { + string parm = "orders=[" + string.Join(",", arr) + $"]&time={date}"; + strb.Append($"手动处理未领取的商户:{parm}"); + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "https://pay.api.52cmg.cn/pay/getNewLinks", + Method = "POST", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = parm, + ResultType = ResultType.String, + }; + html = http.GetHtml(item).Html; + strb.AppendLine($"最新的数据:{html}"); + //{"ok":true,"res":"7d043f8e8e4be0784a596a25cbc078fb|{\"code\":1,\"msg\":\"https://txbgl.kuaizhan.com/?orderid=7d043f8e8e4be0784a596a25cbc078fb\u0026appid=wxb8485eacd6e3b832\",\"appinfo\":null}\r\n144a00f52c271c39513937c252a54ef6|已支付"} + + //{"ok":true,"res":"1ec1dada9db612ab972bca104c273909|{\"code\":1,\"msg\":\"https://txbgl.kuaizhan.com/?orderid=1ec1dada9db612ab972bca104c273909\u0026appid=wx6e0df44505ec10f5\",\"appinfo\":{\"ShopId\":15000000,\"appId\":\"wxe5d3b3d276b346c3\",\"appSecret\":\"441c959d0491be8a136db63d5cca6497\",\"appName\":\"gh_ec03868ecfeb\",\"target\":\"\\\"pages/index/index.html?orderId=[订单编号]\\\"\"}}"} + + var shResult = JsonConvert.DeserializeObject<shpayResult>(html); + if (shResult != null && shResult.ok) + { + var regs = Regex.Split(shResult.res, @"[\r\n]").Where(f => !string.IsNullOrWhiteSpace(f)).ToList(); + if (regs.Count == 0) continue; + + foreach (var tmp in regs) + { + var split = tmp.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries); + var shpay = shpayList.FirstOrDefault(f => split[0] == f.orderid); + if (shpay != null) + { + shpay.paytype = split[1] == "已支付" ? PayGetType.已领取 : PayGetType.未领取; + if (shpay.paytype == PayGetType.已领取) + yjPayList.Add(shpay); + else + { + if (!sendShpayDic.ContainsKey(shpay.robotname)) + sendShpayDic.Add(shpay.robotname, new List<fl_shpay_hist>()); + + var jObj = JObject.Parse(split[1]); + if (jObj["msg"] != null) + shpay.payurl = jObj["msg"].ToString(); + + sendShpayDic[shpay.robotname].Add(shpay); + + if (!ShPayTmpDic.ContainsKey(shpay.robotname)) + ShPayTmpDic.Add(shpay.robotname, new List<ShPayTmp>()); + + if (jObj["appinfo"] != null && jObj["appinfo"].ToString().ToLower() != "null") + ShPayTmpDic[shpay.robotname].Add(new ShPayTmp() + { + id = shpay.id, + shpayInfo = jObj["appinfo"].ToObject<Dictionary<string, object>>() + }); + } + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"商户状态查询异常:{ex.Message} - {ex.StackTrace} , {html}"); + } + finally + { + //EventClient.OnEvent("",strb.ToString()); + } + } + + //EventClient.OnEvent("", "B " + sendShpayDic.Count); + + #region 获取到商户数据以后发送消息 + var sendShpayList = new List<fl_shpay_hist>(); + if (sendShpayDic.Count != 0) + { + try + { + foreach (KeyValuePair<string, List<fl_shpay_hist>> item in sendShpayDic) + { + //EventClient.OnEvent("", $"C : {item.Key} - {item.Value.Count} - {(Chat.Framework.ChatClient.WXClient.FirstOrDefault(f => f.Key == item.Key).Value == null)}"); + var wx = Chat.Framework.ChatClient.WXClient.FirstOrDefault(f => f.Key == item.Key && f.Value.Status == Chat.Framework.WXSdk.WxStatus.在线).Value; + if (wx == null) continue; + foreach (var tmp in item.Value) + { + var msg = string.Empty; + var flag = false;//是否为xml + if (ApiClient.Setting.SystemConfig.send_shpay_minixml && ShPayTmpDic.ContainsKey(item.Key)) + { + var shpayTmpList = ShPayTmpDic[item.Key]; + var payInfo = shpayTmpList.FirstOrDefault(f => f.id == tmp.id); + if (payInfo != null) + { + msg = Util.GetMiNiAppXml(payInfo.shpayInfo, tmp.chattype); + if (!string.IsNullOrWhiteSpace(msg)) + { + wx.SendMessage(tmp.username, msg.Replace("[订单编号]", tmp.orderid)); + flag = true; + } + } + } + + if (!flag) + { + msg = ApiClient.Setting.SystemConfig.send_shpay_msg.Replace("[账号]", tmp.username).Replace("[昵称]", tmp.usernick).Replace("[领取地址]", tmp.payurl).Replace("[兑换金额]", tmp.point.ToString("0.00")).Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName); + wx.SendMessage(tmp.username, msg); + } + tmp.sendtime = HttpExtend.GetTimeStamp(DateTime.Now); + EventClient.OnEvent("提示用户商户未领取", $"{wx.User.Nick}[{wx.User.Username}]【{wx.User.Uin}】:发送:{tmp.usernick}({tmp.username}),领取地址:{tmp.payurl} ,未领金额:{tmp.point.ToString("0.00")},{(msg == null ? 0 : msg.Length)},xml ? {(flag ? "是" : "否")}"); + sendShpayList.Add(tmp); + Thread.Sleep(1000); + } + } + if (shpayList.Count != 0) + session.Saveable(shpayList).ExecuteCommand(); + } + catch (Exception ex) + { + EventClient.OnEvent("", $"商户状态修改异常:{ex.Message} - {ex.StackTrace}"); + } + } + #endregion + + #region 修改数据库中的状态 + var shpayList1 = new List<fl_shpay_hist>(); + if (yjPayList.Count != 0) + { + try + { + foreach (var item in yjPayList) + { + item.paytime = HttpExtend.GetTimeStamp(DateTime.Now); + item.paytype = PayGetType.已领取; + shpayList1.Add(item); + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"商户状态修改异常1:{ex.Message} - {ex.StackTrace}"); + } + } + if (sendShpayList.Count != 0) + { + try + { + foreach (var item in sendShpayList) + { + shpayList1.Add(item); + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"商户状态修改异常1:{ex.Message} - {ex.StackTrace}"); + } + } + if (shpayList1.Count != 0) + session.Updateable(shpayList1).ExecuteCommand(); + #endregion + + #endregion + } + catch (Exception ex) + { + EventClient.OnEvent("", $"{ex.Message} - {ex.StackTrace}"); + } + } + + /// <summary> + /// 商户小程序信息临时类 + /// </summary> + class ShPayTmp + { + public long id { get; set; } + + public object shpayInfo { get; set; } + } + #endregion + } +} diff --git a/FLSystem/Win32Api/Win32Api.cs b/FLSystem/Win32Api/Win32Api.cs new file mode 100644 index 0000000..4ecf3e2 --- /dev/null +++ b/FLSystem/Win32Api/Win32Api.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace FLSystem.Win32Api +{ + public class Win32Api + + { + + #region 常数和结构 + + public const int WM_KEYDOWN = 0x100; + + public const int WM_KEYUP = 0x101; + + public const int WM_SYSKEYDOWN = 0x104; + + public const int WM_SYSKEYUP = 0x105; + + public const int WH_KEYBOARD_LL = 13; + + + + [StructLayout(LayoutKind.Sequential)] //声明键盘钩子的封送结构类型 + + public class KeyboardHookStruct + + { + + public int vkCode; //表示一个在1到254间的虚似键盘码 + + public int scanCode; //表示硬件扫描码 + + public int flags; + + public int time; + + public int dwExtraInfo; + + } + + #endregion + + #region Api + + public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); + + //安装钩子的函数 + + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + + public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); + + //卸下钩子的函数 + + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + + public static extern bool UnhookWindowsHookEx(int idHook); + + //下一个钩挂的函数 + + [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + + public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam); + + [DllImport("user32")] + + public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState); + + [DllImport("user32")] + + public static extern int GetKeyboardState(byte[] pbKeyState); + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + + public static extern IntPtr GetModuleHandle(string lpModuleName); + + #endregion + + } + + public class KeyboardHook + { + int hHook; + + Win32Api.HookProc KeyboardHookDelegate; + + public event KeyEventHandler OnKeyDownEvent; + + public event KeyEventHandler OnKeyUpEvent; + + public event KeyPressEventHandler OnKeyPressEvent; + + public KeyboardHook() { } + + public void SetHook() + { + KeyboardHookDelegate = new Win32Api.HookProc(KeyboardHookProc); + Process cProcess = Process.GetCurrentProcess(); + ProcessModule cModule = cProcess.MainModule; + var mh = Win32Api.GetModuleHandle(cModule.ModuleName); + hHook = Win32Api.SetWindowsHookEx(Win32Api.WH_KEYBOARD_LL, KeyboardHookDelegate, mh, 0); + } + + public void UnHook() + { + Win32Api.UnhookWindowsHookEx(hHook); + } + + private List<Keys> preKeysList = new List<Keys>();//存放被按下的控制键,用来生成具体的键 + + private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) + { + //如果该消息被丢弃(nCode<0)或者没有事件绑定处理程序则不会触发事件 + if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null)) + { + Win32Api.KeyboardHookStruct KeyDataFromHook = (Win32Api.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.KeyboardHookStruct)); + Keys keyData = (Keys)KeyDataFromHook.vkCode; + + //按下控制键 + if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN)) + { + if (IsCtrlAltShiftKeys(keyData) && preKeysList.IndexOf(keyData) == -1) + { + preKeysList.Add(keyData); + } + } + //WM_KEYDOWN和WM_SYSKEYDOWN消息,将会引发OnKeyDownEvent事件 + if (OnKeyDownEvent != null && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN)) + { + KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData)); + OnKeyDownEvent(this, e); + } + + //WM_KEYDOWN消息将引发OnKeyPressEvent + + if (OnKeyPressEvent != null && wParam == Win32Api.WM_KEYDOWN) + { + byte[] keyState = new byte[256]; + Win32Api.GetKeyboardState(keyState); + byte[] inBuffer = new byte[2]; + if (Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1) + { + KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]); + OnKeyPressEvent(this, e); + } + } + //松开控制键 + if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP)) + { + if (IsCtrlAltShiftKeys(keyData)) + { + for (int i = preKeysList.Count - 1; i >= 0; i--) + { + if (preKeysList[i] == keyData) { preKeysList.RemoveAt(i); } + } + } + } + //WM_KEYUP和WM_SYSKEYUP消息,将引发OnKeyUpEvent事件 + if (OnKeyUpEvent != null && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP)) + { + KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData)); + OnKeyUpEvent(this, e); + } + } + return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam); + } + + //根据已经按下的控制键生成key + + private Keys GetDownKeys(Keys key) + { + Keys rtnKey = Keys.None; + + foreach (Keys i in preKeysList) + { + if (i == Keys.LControlKey || i == Keys.RControlKey) { rtnKey = rtnKey | Keys.Control; } + + if (i == Keys.LMenu || i == Keys.RMenu) { rtnKey = rtnKey | Keys.Alt; } + + if (i == Keys.LShiftKey || i == Keys.RShiftKey) { rtnKey = rtnKey | Keys.Shift; } + } + return rtnKey | key; + } + + private Boolean IsCtrlAltShiftKeys(Keys key) + { + if (key == Keys.LControlKey || key == Keys.RControlKey || key == Keys.LMenu || key == Keys.RMenu || key == Keys.LShiftKey || key == Keys.RShiftKey) { return true; } + + return false; + + } + + } + +} diff --git a/FLSystem/favicon.ico b/FLSystem/favicon.ico new file mode 100644 index 0000000..f75758e Binary files /dev/null and b/FLSystem/favicon.ico differ diff --git a/FLSystem/packages.config b/FLSystem/packages.config new file mode 100644 index 0000000..7575f8e --- /dev/null +++ b/FLSystem/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="EO.WebBrowser" version="21.3.18" targetFramework="net461" /> + <package id="EO.WebBrowser.WinForm" version="21.3.18" targetFramework="net461" /> +</packages> \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PCRobot.Pack/BaseMsg.cs b/PCRobot.Pack/BaseMsg.cs new file mode 100644 index 0000000..09e776f --- /dev/null +++ b/PCRobot.Pack/BaseMsg.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Pack +{ + public enum RobotType : int + { + 客户端系统 = 1000, + 客户端微信 = 2001, + 客户端企业微信 = 2002, + 客户端扣扣 = 3000 + } + + public enum PCRobotCMD : int + { + /// <summary> + /// 主程序升级 + /// </summary> + updateApp = -100, + + //个人/企业客户端发送 + sendVideo = 1000, + sendTxt = 1001, + sendFile = 1002, + sendImg = 1003, + agreeFriend = 1004, + sendCard = 1005, + getContact = 1006, + getGroupMember = 1007, + getPay = 1008, + deleteFriend = 1009, + sendInviteGroup = 1010,//发送群卡片 + editContacts = 1011,//编辑联系人 + stateOpt = 1012,//置顶 + getWxidInfo = 1013, + getGroupWxidInfo = 1014,//获取群和群内指定用户数据 + getZombie = 1015, + closeWechat = 1016,//关闭微信 + getGroupsNotInMember = 1017,//获取群列表(不包含群成员) + inviteIntoGroup = 1018,//邀请用户进群 + checkUrl = 1019,//检查微信中的有效性(是否被屏蔽) + clearChatHistoryMsg = 1020,//清理历史聊天记录 + deleteGroupMember = 1021,//删除群用户 + setSessionReadedMsg = 1022,//设置会话已读 + setRoomName = 1023,//修改群聊名称 + setRoomNotice = 1024,//修改群公告(可用于@全体) + modRoomMyName = 1025,//设置自己在群中昵称 + setRoomShowMemeberName = 1026,//设置是否显示群成员昵称 + modRoomName = 1027,//修改群聊名称 + setRecvNotify = 1028,//是否消息免打扰 + addPublicUser = 1029,//关注公众号 + setDisableRevoke = 1030,//开启/关闭防撤回功能 + sendProgramMessage = 1031,//发送小程序 + createRoom = 1032,//创建群 + inviteIntoGroup_40Down = 1033,//40人以下,不发送群名片邀请 + openUrl = 1034,//打开链接 + findCircles = 1035,//获取朋友圈 + sendCircle = 1036,//发送朋友圈 + sendCircleComment = 1037,//发送朋友圈评语 + sendCirclePraise = 1038,//朋友圈点赞 + autoAuthMiniAPPLogin = 1039,//小程序自动授权登录 + uploadCiecleImage = 1040,//上传朋友圈图片 + getlogincode = 1041,//获取登录二维码 + + + + //个人微信服务器接收 + rcvTxt = 2001, + rcvFile = 2002, + rcvImg = 2003, + friendRequest = 2004, + offline = 2005, + applyFriend = 2006,//好友申请 + applyGroup = 2007,//申请入群 + receivePay = 2008,//收到转账 + newfriend = 2009,//新好友 + newMember = 2010,//新群用户 + rcvContactList = 2011,//通讯录列表 + rcvGroupMember = 2012,//群信息 + rcvContact = 2013,//返回用户信息(单个用户 或 单个群与用户) + rcvCheckUrl = 2014,//返回url微信中的有效性(是否被屏蔽) + rcvCreateRoom = 2015,//返回新建群的群号 + rcvCircleData = 2016,//返回朋友圈json数据 + rcvMiniAppCode = 2017,//返回小程序自动授权后的code数据 + rcvCircleUploadImageUrl = 2018,//返回朋友圈本地图片上传后返回的地址 + rcvCircleReturnId = 2019,//返回朋友圈本地图片上传后返回的地址 + rcvLoginCode = 2020,//返回登录二维码信息 + rcvFriendList = 2021,//返回好友列表 + + + + + //企业微信服务器接收 + sendVideo_workWeChat = 3000, + rcvTxt_workWeChat = 3001, + rcvFile_workWeChat = 3002, + rcvImg_workWeChat = 3003, + friendRequest_workWeChat = 3004, + offline_workWeChat = 3005, + applyFriend_workWeChat = 3006,//好友申请 + applyGroup_workWeChat = 3007,//申请入群 + receivePay_workWeChat = 3008,//收到转账 + newfriend_workWeChat = 3009,//新好友 + newMember_workWeChat = 3010,//新群用户 + rcvContactList_workWeChat = 3011,//通讯录列表 + rcvGroupMember_workWeChat = 3012,//群信息 + rcvContact_workWeChat = 3013,//返回用户信息(单个用户 或 单个群与用户) + rcvLoginCode_workWeChat = 3014,//返回企业登录二维码信息 + rcvFriendList_workWeChat = 3015,//返回企业好友列表 + rcvCreateRoom_workWeChat = 3016,//返回新建群的群号 + + heartBreak = 9000,//客户端心跳 + } + public enum WechatMsgType + { + 文本 = 1001, + 语音 = 1002, + 视频 = 1003, + 图片 = 1004, + 文件 = 1005, + 表情 = 1006, + 红包 = 1007, + 名片 = 1008, + 小程序 = 1009, + 群邀请 = 1010, + 链接 = 1011, + } + public class BaseMsg + { + public BaseMsg() + { + MsgId = new Random(Guid.NewGuid().GetHashCode()).Next().ToString(); + } + /// <summary> + /// 消息命令 + /// </summary> + public PCRobotCMD Cmd { get; set; } + + /// <summary> + /// 机器人账号 + /// </summary> + public string RobotUsername { get; set; } + + /// <summary> + /// 机器人昵称 + /// </summary> + public string RobotUsernick { get; set; } + + /// <summary> + /// 机器人类型 + /// </summary> + public RobotType RobotType { get; set; } + + /// <summary> + /// 秘钥 + /// </summary> + public string Key { get; set; } + + /// <summary> + /// 消息命 + /// </summary> + public string MsgId { get; set; } + } +} diff --git a/PCRobot.Pack/ClientWechatMsg.cs b/PCRobot.Pack/ClientWechatMsg.cs new file mode 100644 index 0000000..e0796f2 --- /dev/null +++ b/PCRobot.Pack/ClientWechatMsg.cs @@ -0,0 +1,273 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Pack +{ + + /// <summary> + /// 收到微信消息 + /// </summary> + public class WechatReceiveMsg : BaseMsg + { + /// <summary> + /// 是否由客户端发出的消息 + /// </summary> + public bool IsSend { get; set; } + + /// <summary> + /// 用户的微信ID + /// </summary> + public string FromUsername { get; set; } + + /// <summary> + /// 用户昵称 + /// </summary> + public string FromUsernick { get; set; } + + /// <summary> + /// 消息内容 + /// </summary> + public string FromMessage { get; set; } + + /// <summary> + /// 群号 + /// </summary> + public string FromGroupid { get; set; } = string.Empty; + + /// <summary> + /// 群昵称 + /// </summary> + public string FromGroupNick { get; set; } = string.Empty; + + /// <summary> + /// 消息类型 + /// </summary> + public WechatMsgType FromMessageType { get; set; } + + /// <summary> + /// 图片的CND xml信息 + /// </summary> + public string FileCDNXML { get; set; } = string.Empty; + + /// <summary> + /// 原始消息 + /// </summary> + public string OriMessage { get; set; } + + /// <summary> + /// 消息Id + /// </summary> + public string Msgid { get; set; } + + /// <summary> + /// 接收时间 + /// </summary> + + public long Timestamp { get; set; } + } + + /// <summary> + /// 微信群成员信息 + /// </summary> + public class WechatGroupMember : BaseMsg + { + /// <summary> + /// json格式的用户信息 + /// </summary> + public string Message { get; set; } + } + + /// <summary> + /// 申请添加我为好友,需要审核 + /// </summary> + public class WechatApplyFriend : BaseMsg + { + /// <summary> + /// 新朋友Id + /// </summary> + public string NewFriendWxid { get; set; } + /// <summary> + /// 新朋友昵称 + /// </summary> + public string NewFriendNick { get; set; } + /// <summary> + /// 附加消息 + /// </summary> + public string Message { get; set; } + /// <summary> + /// 推荐人wxid 可能为空 + /// </summary> + public string OldFriendWxid { get; set; } + /// <summary> + /// 推荐人昵称 可能为空 + /// </summary> + public string OldFriendNick { get; set; } + /// <summary> + /// token + /// </summary> + public string Token { get; set; } + } + + /// <summary> + /// 新好友 + /// </summary> + public class WechatNewFriend : BaseMsg + { + /// <summary> + /// 账号 + /// </summary> + public string FromUserName { get; set; } + /// <summary> + /// 昵称 + /// </summary> + public string FromUserNick { get; set; } + /// <summary> + /// 头像 + /// </summary> + public string Avatar { get; set; } + /// <summary> + /// 性别 + /// </summary> + public int Sex { get; set; } + } + + /// <summary> + /// 获取到通讯录列表 + /// </summary> + public class WechatContact : BaseMsg + { + /// <summary> + /// json + /// </summary> + public string Message { get; set; } + } + + /// <summary> + /// 新用户入群 + /// </summary> + public class WechatNewMemer : BaseMsg + { + /// <summary> + /// 群id + /// </summary> + public string GroupId { get; set; } + /// <summary> + /// 群昵称 + /// </summary> + public string GroupNick { get; set; } + /// <summary> + /// 邀请人账号 + /// </summary> + public string SourceName { get; set; } + /// <summary> + /// 邀请人昵称 + /// </summary> + public string SourceNick { get; set; } + /// <summary> + /// 账号 + /// </summary> + public string MemberName { get; set; } + /// <summary> + /// 新人昵称 + /// </summary> + public string MemberNick { get; set; } + /// <summary> + /// 成员数量 + /// </summary> + public int TotalMember { get; set; } + } + + /// <summary> + /// 转账收款 + /// </summary> + public class WechatReicevePay : BaseMsg + { + /// <summary> + /// 转账用户账号 + /// </summary> + public string FromUsername { get; set; } + + /// <summary> + /// 转账用户昵称 + /// </summary> + public string FromUsernick { get; set; } + + /// <summary> + /// 失效时间 + /// </summary> + public string Invalidtime { get; set; } + + /// <summary> + /// + /// </summary> + public string Transferid { get; set; } + + /// <summary> + /// 转账金额 + /// </summary> + public double Money { get; set; } + } + + /// <summary> + /// 微信状态 在线/离线 + /// </summary> + public class WechatStatus : BaseMsg + { + /// <summary> + /// uin + /// </summary> + public string Uin { get; set; } + /// <summary> + /// 登录状态 + /// </summary> + public Status Status { get; set; } + /// <summary> + /// 设备信息 + /// </summary> + public string Device { get; set; } + } + + public enum Status + { + 在线 = 0, + 退出 = 1 + } + + /// <summary> + /// 检查域名是否无效 + /// </summary> + public class CheckUrl : BaseMsg + { + /// <summary> + /// 状态 + /// </summary> + public int Status { get; set; } + } + + /// <summary> + /// 创建群 + /// </summary> + public class CreateRoom : BaseMsg + { + /// <summary> + /// 用户数量 + /// </summary> + public int MemberTotal { get; set; } + /// <summary> + /// 新群号 + /// </summary> + public string GroupId { get; set; } + } + + public class CommonResult : BaseMsg + { + /// <summary> + /// json + /// </summary> + public string Data { get; set; } + } + +} diff --git a/PCRobot.Pack/ClientWorkWechatMsg.cs b/PCRobot.Pack/ClientWorkWechatMsg.cs new file mode 100644 index 0000000..7d87dec --- /dev/null +++ b/PCRobot.Pack/ClientWorkWechatMsg.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +/// <summary> +/// 企业客户端事件 +/// </summary> +namespace PCRobot.Pack +{ + + /// <summary> + /// 收到微信消息 + /// </summary> + public class WorkWechatReceiveMsg : BaseMsg + { + /// <summary> + /// 是否由客户端发出的消息 + /// </summary> + public bool IsSend { get; set; } + + /// <summary> + /// 用户的微信ID + /// </summary> + public string FromUsername { get; set; } + + /// <summary> + /// 用户昵称 + /// </summary> + public string FromUsernick { get; set; } + + /// <summary> + /// 发送时间 + /// </summary> + public long Timestamp { get; set; } + + /// <summary> + /// 原始数据内容 + /// </summary> + public string OriMessage { get; set; } + + /// <summary> + /// 消息内容 + /// </summary> + public string FromMessage { get; set; } + + /// <summary> + /// 群号 + /// </summary> + public string FromGroupid { get; set; } = string.Empty; + + /// <summary> + /// 群昵称 + /// </summary> + public string FromGroupNick { get; set; } = string.Empty; + + /// <summary> + /// 消息类型 + /// </summary> + public WechatMsgType FromMessageType { get; set; } + + /// <summary> + /// 图片的CND xml信息 + /// </summary> + public string FileCDNXML { get; set; } = string.Empty; + } + + public class WorkWechatGroupMember : BaseMsg + { + /// <summary> + /// json + /// </summary> + public string Message { get; set; } + } + + /// <summary> + /// 申请添加我为好友,需要审核 + /// </summary> + public class WorkWechatApplyFriend : BaseMsg + { + /// <summary> + /// 新朋友Id + /// </summary> + public string NewFriendWxid { get; set; } + /// <summary> + /// 新朋友昵称 + /// </summary> + public string NewFriendNick { get; set; } + /// <summary> + /// 附加消息 + /// </summary> + public string Message { get; set; } + /// <summary> + /// 推荐人wxid 可能为空 + /// </summary> + public string OldFriendWxid { get; set; } + /// <summary> + /// 推荐人昵称 可能为空 + /// </summary> + public string OldFriendNick { get; set; } + /// <summary> + /// token + /// </summary> + public string Token { get; set; } + } + + public class WorkWechatNewFriend : BaseMsg + { + public string FromUserName { get; set; } + public string FromUserNick { get; set; } + } + + /// <summary> + /// 获取到通讯录列表 + /// </summary> + public class WorkWechatContact : BaseMsg + { + /// <summary> + /// json + /// </summary> + public string Message { get; set; } + } + + /// <summary> + /// 新用户入群 + /// </summary> + public class WorkWechatNewMemer : BaseMsg + { + /// <summary> + /// 群id + /// </summary> + public string GroupId { get; set; } + /// <summary> + /// 群昵称 + /// </summary> + public string GroupNick { get; set; } + /// <summary> + /// 邀请人昵称 + /// </summary> + public string SourceNick { get; set; } + /// <summary> + /// 邀请人账号 + /// </summary> + public string SourceName { get; set; } + /// <summary> + /// 新人昵称 + /// </summary> + public string MemberNick { get; set; } + } + + /// <summary> + /// 转账收款 + /// </summary> + public class WorkWechatReicevePay : BaseMsg + { + /// <summary> + /// 转账用户账号 + /// </summary> + public string FromUsername { get; set; } + + /// <summary> + /// 转账用户昵称 + /// </summary> + public string FromUsernick { get; set; } + + /// <summary> + /// 失效时间 + /// </summary> + public string Invalidtime { get; set; } + + /// <summary> + /// + /// </summary> + public string Transferid { get; set; } + + /// <summary> + /// 转账金额 + /// </summary> + public double Money { get; set; } + } + + /// <summary> + /// 创建群 + /// </summary> + public class WorkCreateRoom : BaseMsg + { + /// <summary> + /// 用户数量 + /// </summary> + public int MemberTotal { get; set; } + /// <summary> + /// 新群号 + /// </summary> + public string GroupId { get; set; } + } + +} diff --git a/PCRobot.Pack/FriendWechatMsg.cs b/PCRobot.Pack/FriendWechatMsg.cs new file mode 100644 index 0000000..f2353fd --- /dev/null +++ b/PCRobot.Pack/FriendWechatMsg.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Pack +{ + public class ServerFriendMsg:ServerWechatMsg + { + public string Ad_V1 { get; set; } + + public string Ad_V2 { get; set; } + + public string Remark { get; set; } + + /// <summary> + /// 消息命令 + /// </summary> + public new PCRobotCMD Cmd { get; set; } = PCRobotCMD.agreeFriend; + } + + public class ClientFriendMsg : WechatReceiveMsg + { + public string Ad_V1 { get; set; } + + public string Ad_V2 { get; set; } + + public string Remark { get; set; } + + /// <summary> + /// 消息命令 + /// </summary> + public new PCRobotCMD Cmd { get; set; } = PCRobotCMD.friendRequest; + } +} diff --git a/PCRobot.Pack/PCRobot.Pack.csproj b/PCRobot.Pack/PCRobot.Pack.csproj new file mode 100644 index 0000000..db264fe --- /dev/null +++ b/PCRobot.Pack/PCRobot.Pack.csproj @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>PCRobot.Pack</RootNamespace> + <AssemblyName>PCRobot.Pack</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="BaseMsg.cs" /> + <Compile Include="ClientWorkWechatMsg.cs" /> + <Compile Include="PackTool.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="ClientWechatMsg.cs" /> + <Compile Include="ServerWechatMsg.cs" /> + </ItemGroup> + <ItemGroup> + <Folder Include="Entitys\" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/PCRobot.Pack/PackTool.cs b/PCRobot.Pack/PackTool.cs new file mode 100644 index 0000000..a19feb3 --- /dev/null +++ b/PCRobot.Pack/PackTool.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Pack +{ + public class PackTool + { + public static string CompressString(string str) + { + var compressBeforeByte = Encoding.GetEncoding("UTF-8").GetBytes(str); + var compressAfterByte = Compress(compressBeforeByte); + string compressString = Convert.ToBase64String(compressAfterByte); + return compressString; + } + + public static string DecompressString(string str) + { + if (str == "$") return str; + var compressBeforeByte = Convert.FromBase64String(str); + var compressAfterByte = Decompress(compressBeforeByte); + string compressString = Encoding.GetEncoding("UTF-8").GetString(compressAfterByte); + return compressString; + } + + /// <summary> + /// Compress + /// </summary> + /// <param name="data"></param> + /// <returns></returns> + private static byte[] Compress(byte[] data) + { + try + { + var ms = new MemoryStream(); + var zip = new GZipStream(ms, CompressionMode.Compress, true); + zip.Write(data, 0, data.Length); + zip.Close(); + var buffer = new byte[ms.Length]; + ms.Position = 0; + ms.Read(buffer, 0, buffer.Length); + ms.Close(); + return buffer; + + } + catch (Exception e) + { + throw new Exception(e.Message); + } + } + + /// <summary> + /// Decompress + /// </summary> + /// <param name="data"></param> + /// <returns></returns> + private static byte[] Decompress(byte[] data) + { + try + { + var ms = new MemoryStream(data); + var zip = new GZipStream(ms, CompressionMode.Decompress, true); + var msreader = new MemoryStream(); + var buffer = new byte[0x1000]; + while (true) + { + var reader = zip.Read(buffer, 0, buffer.Length); + if (reader <= 0) + { + break; + } + msreader.Write(buffer, 0, reader); + } + zip.Close(); + ms.Close(); + msreader.Position = 0; + buffer = msreader.ToArray(); + msreader.Close(); + return buffer; + } + catch (Exception e) + { + throw new Exception(e.Message); + } + } + } +} diff --git a/PCRobot.Pack/Properties/AssemblyInfo.cs b/PCRobot.Pack/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3fc593d --- /dev/null +++ b/PCRobot.Pack/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("PCRobot.Pack")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PCRobot.Pack")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("c1ec66c6-7e57-4780-9ea3-13369bd7c9fc")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PCRobot.Pack/ServerWechatMsg.cs b/PCRobot.Pack/ServerWechatMsg.cs new file mode 100644 index 0000000..559341c --- /dev/null +++ b/PCRobot.Pack/ServerWechatMsg.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Pack +{ + public class ServerWechatMsg : BaseMsg + { + /// <summary> + /// 发送给谁 + /// </summary> + public string ToUsername { get; set; } + + /// <summary> + /// 消息正文内容 + /// </summary> + public string ToMessage { get; set; } + + /// <summary> + /// 要发送的消息类型 + /// </summary> + public WechatMsgType ToMessageType { get; set; } + } + + + public class XmlWechatMsg : ServerWechatMsg + { + public string Title { get; set; } + + public string Text { get; set; } + + public string Pic { get; set; } + + public string URL { get; set; } + } + + /// <summary> + /// 获取二维码消息 + /// </summary> + public class LoginCodeMsg : BaseMsg + { + public string Data { get; set; } + } + +} diff --git a/PCRobot/App.config b/PCRobot/App.config new file mode 100644 index 0000000..429c343 --- /dev/null +++ b/PCRobot/App.config @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/> + </startup> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <probing privatePath="Bin"/> + </assemblyBinding> + </runtime> +</configuration> diff --git a/PCRobot/DLL/HPSocket4C.dll b/PCRobot/DLL/HPSocket4C.dll new file mode 100644 index 0000000..632d86d Binary files /dev/null and b/PCRobot/DLL/HPSocket4C.dll differ diff --git a/PCRobot/DLL/KstAPI.dll b/PCRobot/DLL/KstAPI.dll new file mode 100644 index 0000000..cd8f6ba Binary files /dev/null and b/PCRobot/DLL/KstAPI.dll differ diff --git a/PCRobot/DLL/KstConv.dll b/PCRobot/DLL/KstConv.dll new file mode 100644 index 0000000..2ff3f61 Binary files /dev/null and b/PCRobot/DLL/KstConv.dll differ diff --git a/PCRobot/DLL/KstEx.dll b/PCRobot/DLL/KstEx.dll new file mode 100644 index 0000000..2535fac Binary files /dev/null and b/PCRobot/DLL/KstEx.dll differ diff --git a/PCRobot/DLL/NanMuCore_3.3.5.50.dll b/PCRobot/DLL/NanMuCore_3.3.5.50.dll new file mode 100644 index 0000000..aac7ca3 Binary files /dev/null and b/PCRobot/DLL/NanMuCore_3.3.5.50.dll differ diff --git a/PCRobot/DLL/NanMuHelper.dll b/PCRobot/DLL/NanMuHelper.dll new file mode 100644 index 0000000..dd48321 Binary files /dev/null and b/PCRobot/DLL/NanMuHelper.dll differ diff --git a/PCRobot/DLL/Newtonsoft.Json.dll b/PCRobot/DLL/Newtonsoft.Json.dll new file mode 100644 index 0000000..554e99d Binary files /dev/null and b/PCRobot/DLL/Newtonsoft.Json.dll differ diff --git a/PCRobot/DLL/kst.dll b/PCRobot/DLL/kst.dll new file mode 100644 index 0000000..6909a1c Binary files /dev/null and b/PCRobot/DLL/kst.dll differ diff --git a/PCRobot/EasySoc.cs b/PCRobot/EasySoc.cs new file mode 100644 index 0000000..945d1cc --- /dev/null +++ b/PCRobot/EasySoc.cs @@ -0,0 +1,325 @@ +using CsharpHttpHelper; +using PCRobot.Pack; +using PCRobot.PCWechat; +using SuperSocket.ClientEngine; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace PCRobot +{ + public class EasySoc + { + private static EasySoc _socket; + public static EasySoc GetSocket() + { + if (_socket == null) _socket = new EasySoc(); + return _socket; + } + public EasySoc() + { + timer = new System.Threading.Timer(new TimerCallback(timerCall), null, 0, 1000 * 5); + } + public bool IsConnected + { + get + { + if (client != null && client.IsConnected) return true; + return false; + } + } + public bool Stop { get; set; } + AsyncTcpSession client; + //EasyClient client; + + private readonly static object session_lock = new object(); + + public void Close(bool isQuit = false) + { + try + { + lock (session_lock) + { + if (client != null) + { + if (isQuit) + timer.Dispose(); + + //client.DataReceived -= Client_DataReceived; + client.Connected -= Client_Connected; + client.Closed -= Client_Closed; + client.Error -= Client_Error; + client.Close(); + client = null; + } + } + } + catch (Exception ex) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("Close ERROR:", $"{ex.Message}"); + + LogHelper.GetSingleObj().Error("Close ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + IPEndPoint endPoint; + private Action<string> ReceiveDataAction; + + private Action<string> StateAction; + + private Action<Exception> SocketErrorAction; + + public string key { get; private set; } + private string ip; + private int port; + private System.Threading.Timer timer = null; + private static bool lock_connection = false; + public void Connection(string ip, int port, Action<string> ReceiveDataAction, Action<Exception> SocketErrorAction, string key, Action<string> StateAction) + { + if (Stop) return; + if (lock_connection) return; + if (key.Length != 16) throw new Exception("秘钥必须 == 16位!"); + try + { + lock_connection = true; + if (this.IsConnected) this.Close(); + Console.WriteLine("连接中..."); + this.ip = ip; + this.port = port; + this.ReceiveDataAction = ReceiveDataAction; + this.StateAction = StateAction; + this.SocketErrorAction = SocketErrorAction; + this.key = key.Substring(0, 16); + this.endPoint = new IPEndPoint(IPAddress.Parse(ip), port); + lock (session_lock) + { + client = new AsyncTcpSession(); + client.ReceiveBufferSize = 10 * 1024; + client.DataReceived += Client_DataReceived; + client.Connected += Client_Connected; + client.Closed += Client_Closed; + client.Error += Client_Error; + client.Connect(endPoint); + Thread.Sleep(500); + if (!client.IsConnected) + { + client.Connect(endPoint); + if (!client.IsConnected) + throw new Exception("连接服务器失败,请检查是否填写正确!"); + } + } + } + catch (Exception ex) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("断开", $"连接服务器失败:{ex.Message}"); + StateAction?.Invoke($"连接服务器失败:{ex.Message} - {ex.StackTrace}"); + } + finally + { + lock_connection = false; + } + } + + private void Client_Closed(object sender, EventArgs e) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("断开", $"与服务器{ip}连接断开!!"); + StateAction?.Invoke($"与服务器{ip}连接断开!"); + } + + private void Client_Connected(object sender, EventArgs e) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("连接成功", $"与服务器{ip}连接成功!"); + StateAction?.Invoke($"与服务器{ip}连接成功!"); + } + private long i = 0; + private void timerCall(object state) + { + if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(key) || port == 0) return; + //throw new NotImplementedException(); + try + { + if (Stop) + { + if (IsConnected) Close(); + } + if (!IsConnected) + { + if (Stop) StateAction?.Invoke($"您已断开与服务器{ip}失联!"); + else + { + StateAction?.Invoke($"与服务器{ip}失联,重连中..."); + + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("失联", $"与服务器{ip}失联,重连中..."); + Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction); + } + } + else + { + i++; + //Console.WriteLine($"第{i}次测试,key={this.key}"); + + if (i == 1 || i % 5 == 0) + { + //Send(new BaseMsg() + //{ + // Cmd = PCRobotCMD.heartBreak, + // RobotType = RobotType.客户端微信, + // RobotUsername = "测试", + // RobotUsernick = "测试-可以随时删除" + //}); + //Send(); + //var wxs = WinForm.nms.ToList(); + + var robots = PCWechat.WechatClient.Users.Values.ToList(); + foreach (var item in robots) + { + //var msg = new BaseMsg() + //{ + // Cmd = PCRobotCMD.heartBreak, + // RobotType = RobotType.客户端系统, + // RobotUsername = item.Wxid, + // RobotUsernick = item.Nickname + //}; + if (item.HeartBreakTime.AddMinutes(6) > DateTime.Now) + { + var msg = new WechatStatus() + { + Cmd = item.Type == WechatType.Xiaoxie_QY ? PCRobotCMD.offline_workWeChat : PCRobotCMD.offline, + RobotUsername = item.Wxid, + RobotUsernick = item.Nickname, + RobotType = item.Type == WechatType.Xiaoxie_QY ? RobotType.客户端企业微信 : RobotType.客户端微信, + Status = Status.在线, + Uin = item.Uin + }; + Send(msg); + Thread.Sleep(50); + } + else + { + item.HeartBreakTime = DateTime.Now; + Close(); + if (!IsConnected) Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction); + } + } + } + + StateAction?.Invoke($"与服务器: {ip} 连接成功."); + } + } + catch (Exception ex) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("心跳包异常1", $"{ex.Message}"); + StateAction?.Invoke($"心跳包异常: {ex.Message}"); + } + } + + private void Client_Error(object sender, ErrorEventArgs e) + { + if (SocketErrorAction != null) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("Client_Error", $"{e.Exception.Message}"); + SocketErrorAction(e.Exception); + } + } + + private void Client_DataReceived(object sender, DataEventArgs e) + { + byte[] new_data = new byte[e.Length]; + Buffer.BlockCopy(e.Data, 0, new_data, 0, e.Length); + + var data = Encoding.UTF8.GetString(new_data); + var json = HttpHelper.JsonToObject<WechatStatus>(data) as WechatStatus; + if (json == null) + { + + } + else + { + //var client = WechatClient.Users.Values.ToList().FirstOrDefault(f => f.Wxid == json.RobotUsername && f.Type == (json.RobotType == RobotType.客户端企业微信 ? WechatType.Xiaoxie_QY : WechatType.Xiaoxie)); + var client = WechatClient.Users.Values.ToList().FirstOrDefault(f => f.Wxid == json.RobotUsername); + if (client != null) + client.HeartBreakTime = DateTime.Now; + return; + } + Console.WriteLine(Encoding.UTF8.GetString(new_data)); + //ReceiveDataAction.BeginInvoke(Encoding.UTF8.GetString(new_data), null, null); + ReceiveDataAction.BeginInvoke(data, null, null); + } + + int retry = 0; + private Thread threadConnection; + public void Send(BaseMsg msg) + { + try + { + if (IsConnected) + { + try + { + //秘钥 + //key = string.Empty; + msg.Key = this.key; + //Console.WriteLine("心跳测试:" + i + "," + msg.Key); + var json = HttpHelper.ObjectToJson(msg); + var data = PackTool.CompressString(json); + // + //if (!string.IsNullOrEmpty(key)) + //{ + // AESCryption aes = new AESCryption(); + // data = aes.AesEncrypt(data, key); + //} + + //data =HttpHelper.URLEncode(data); + var send = msg.Cmd + " " + data + "\r\n"; + var data_bytes = Encoding.UTF8.GetBytes(send); + client.Send(data_bytes,0,data_bytes.Length); + + } + catch (Exception ex) + { + StateAction?.Invoke($"发送消息失败: {ex.Message}"); + } + } + else + { + StateAction?.Invoke($"发送消息失败: 没有与服务器建立连接!"); + if (threadConnection == null || !threadConnection.IsAlive) + { + threadConnection = new Thread(new ThreadStart(delegate + { + try + { + Thread.Sleep(5000); + if (!IsConnected) Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction); + } + catch (Exception) + { + } + })); + threadConnection.IsBackground = true; + threadConnection.Start(); + } + } + + + } + catch (Exception ex) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("Send ERROR", $"{ex.Message}"); + LogHelper.GetSingleObj().Error("Send ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + } +} diff --git a/PCRobot/EasySoc_.cs b/PCRobot/EasySoc_.cs new file mode 100644 index 0000000..bd9ae05 --- /dev/null +++ b/PCRobot/EasySoc_.cs @@ -0,0 +1,368 @@ +using CsharpHttpHelper; +using PCRobot.Pack; +using PCRobot.PCWechat; +using PCRobot.Utils; +using SuperSocket.ClientEngine; +using SuperSocket.ProtoBase; +using System; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; + +namespace PCRobot +{ + public class EasySoc + { + #region 字段信息 + static EasySoc _soc; + + public EasyClient client; + + public string key { get; private set; } + + string ip; + + int port; + + public bool Stop { get; set; } + + public bool IsConnected + { + get + { + return client != null && client.IsConnected; + } + } + + readonly static object session_lock = new object(); + + IPEndPoint endPoint; + + Action<string, string> ReceiveDataAction; + + Action<string> StateAction; + + Action<Exception> SocketErrorAction; + + long i = 0; + + //Thread threadConnection; + + static bool lock_connection = false; + #endregion + + public static EasySoc GetSocket() + { + if (_soc == null) _soc = new EasySoc(); + return _soc; + } + private System.Threading.Timer timer = null; + public EasySoc() + { + //timer = new Timer(new TimerCallback(timerCall), null, 0, 1000 * 5); + var thread = new Thread(() => + { + while (true) + { + Thread.Sleep(1000 * 5); + timerCall(null); + } + }); + thread.IsBackground = true; + thread.Start(); + //FluentScheduler.JobManager.AddJob(heartBeat, t => + //{ + // t.WithName("心跳").ToRunNow().AndEvery(5).Seconds(); + //}); + } + + + private void timerCall(object state) + { + if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(key) || port == 0) return; + + //throw new NotImplementedException(); + var sb = new StringBuilder(); + try + { + sb.AppendLine("AAA"); + if (Stop) + { + sb.AppendLine("BBB"); + if (IsConnected) Close(); + sb.AppendLine("ccc"); + StateAction?.Invoke($"您已断开与服务器{ip}失联!"); + return; + } + sb.AppendLine("DDD"); + if (!IsConnected) + { + sb.AppendLine("EEE"); + StateAction?.Invoke($"与服务器{ip}失联,重连中..."); + + if (WechatClient.IsLog) + { + sb.AppendLine("FFF"); + LogHelper.GetSingleObj().Info("失联", $"与服务器{ip}失联,重连中..."); + } + Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction); + sb.AppendLine("GGG"); + } + else + { + sb.AppendLine("HHH"); + i++; + //Console.WriteLine($"第{i}次测试,key={this.key}"); + + if (i == 1 || i % 6 == 0) + { + sb.AppendLine("TTT"); + Send(new CommonResult() + { + Cmd = PCRobotCMD.heartBreak, + RobotType = RobotType.客户端系统, + RobotUsername = string.Empty, + RobotUsernick = "测试-nick", + Data = Common.GetDevice() + }); + Thread.Sleep(50); + sb.AppendLine("LLL"); + var robots = WechatClient.Users.Values.ToList(); + foreach (var item in robots) + { + sb.AppendLine("MMM"); + if (item.HeartBreakTime.AddMinutes(6) > DateTime.Now) + { + var msg = new WechatStatus() + { + Cmd = item.Type == WechatType.Xiaoxie_QY ? PCRobotCMD.offline_workWeChat : PCRobotCMD.offline, + RobotUsername = item.Wxid, + RobotUsernick = item.Nickname,//Regex.Replace(item.Nickname, @"\s", "", RegexOptions.IgnoreCase), + RobotType = item.Type == WechatType.Xiaoxie_QY ? RobotType.客户端企业微信 : RobotType.客户端微信, + Status = Status.在线, + Uin = item.Uin, + Device = Common.GetDevice() + }; + Send(msg); + Thread.Sleep(50); + } + else + { + sb.AppendLine("NNN"); + item.HeartBreakTime = DateTime.Now; + Close(); + if (!IsConnected) Connection(ip, port, ReceiveDataAction, SocketErrorAction, key, StateAction); + } + } + } + sb.AppendLine("ZZZ"); + StateAction?.Invoke($"与服务器: {ip} 连接成功."); + } + } + catch (Exception ex) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("心跳包异常1", $"{ex.Message}"); + StateAction?.Invoke($"心跳包异常: {ex.Message} {ex.StackTrace} +{sb.ToString()}"); + } + } + + public void Send(BaseMsg msg) + { + try + { + if (IsConnected) + { + try + { + msg.Key = this.key; + var json = HttpHelper.ObjectToJson(msg); + var data = PackTool.CompressString(json); + var send = msg.Cmd + " " + data + "\r\n"; + var data_bytes = Encoding.UTF8.GetBytes(send); + if (WechatClient.IsDebug) LogHelper.GetSingleObj().Debug("往服务器发送", $"{msg.Cmd} - {json} - {data.Length}"); + + //var senddata = new byte[_receiveBufferSize]; + //for (int i = 0; i < data_bytes.Length; i++) + //{ + // senddata[i] = data_bytes[i]; + //} + + client.Send(data_bytes); + } + catch (Exception ex) + { + StateAction?.Invoke($"发送消息失败: {ex.Message}"); + } + } + } + catch (Exception ex) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("Send ERROR", $"{ex.Message}"); + LogHelper.GetSingleObj().Error("Send ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + private static int _receiveBufferSize = 1024 * 1024 * 10; + public void Connection(string ip, int port, Action<string, string> receiveDataAction, Action<Exception> socketErrorAction, string key, Action<string> stateAction) + { + if (Stop) return; + if (lock_connection) return; + if (key.Length != 16) throw new Exception("秘钥必须 == 16位!"); + try + { + lock_connection = true; + if (this.IsConnected) this.Close(); + //Console.WriteLine("连接中..."); + this.ip = ip; + this.port = port; + if (receiveDataAction != null) + { + this.ReceiveDataAction = receiveDataAction; + } + if (stateAction != null) + { + this.StateAction = stateAction; + } + if (socketErrorAction != null) + { + this.SocketErrorAction = socketErrorAction; + } + + this.key = key.Substring(0, 16); + this.endPoint = new IPEndPoint(IPAddress.Parse(ip), port); + lock (session_lock) + { + client = new EasyClient(); + client.Initialize(new MyReceiveFilter(), clientRcv); + client.ReceiveBufferSize = _receiveBufferSize; + + + //LogHelper.GetSingleObj().Info("", "client.ReceiveBufferSize = " + client.ReceiveBufferSize); + + //client.DataReceived += Client_DataReceived; + + client.Connected += Client_Connected; + client.Closed += Client_Closed; + client.Error += Client_Error; + var rst = client.ConnectAsync(endPoint).Result; + Thread.Sleep(500); + if (!client.IsConnected) + { + rst = client.ConnectAsync(endPoint).Result; + if (!client.IsConnected) + throw new Exception("连接服务器失败,请检查是否填写正确!"); + } + } + } + catch (Exception ex) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("断开", $"连接服务器失败:{ex.Message}"); + StateAction?.Invoke($"连接服务器失败:{ex.Message} - {ex.StackTrace}"); + } + finally + { + lock_connection = false; + } + } + + private void clientRcv(StringPackageInfo obj) + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("", $"收到服务器消息:{obj.Key} - {obj.Body}"); + + if (obj.Key.ToLower().Trim().StartsWith("offline".ToLower())) + { + try + { + var json = HttpExtend.JsonToDictionary(obj.Body); + if (json != null) + { + var client = WechatClient.Users.Values.ToList().FirstOrDefault(f => f.Wxid == json["RobotUsername"].ToString()); + if (client != null) + client.HeartBreakTime = DateTime.Now; + } + else + { + var text = PackTool.DecompressString(obj.Body); + var json1 = HttpExtend.JsonToDictionary(text); + if (json1 != null) + { + var client = WechatClient.Users.Values.ToList().FirstOrDefault(f => f.Wxid == json1["RobotUsername"].ToString()); + if (client != null) + client.HeartBreakTime = DateTime.Now; + } + } + } + catch (Exception ex) + { } + return; + } + //Console.WriteLine(obj.Body); + //ReceiveDataAction.BeginInvoke(Encoding.UTF8.GetString(new_data), null, null); + ReceiveDataAction.BeginInvoke(obj.Key, obj.Body, null, null); + } + + public void Close(bool isQuit = false) + { + try + { + lock (session_lock) + { + if (client != null) + { + if (isQuit) + { + FluentScheduler.JobManager.RemoveJob("心跳"); + } + + //client.DataReceived -= Client_DataReceived; + client.Connected -= Client_Connected; + client.Closed -= Client_Closed; + client.Error -= Client_Error; + client.Close(); + client = null; + } + } + } + catch (Exception ex) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("Close ERROR:", $"{ex.Message}"); + + LogHelper.GetSingleObj().Error("Close ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + private void Client_Error(object sender, ErrorEventArgs e) + { + if (SocketErrorAction != null) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("Client_Error", $"{e.Exception.Message}"); + SocketErrorAction(e.Exception); + } + } + + private void Client_Closed(object sender, EventArgs e) + { + if (WechatClient.IsLog) + LogHelper.GetSingleObj().Info("断开", $"与服务器{ip},{e} - 连接断开!!"); + StateAction?.Invoke($"与服务器{ip}连接断开!"); + } + + private void Client_Connected(object sender, EventArgs e) + { + if (WechatClient.IsLog) + { + LogHelper.GetSingleObj().Info("连接成功", $"与服务器{ip}连接成功!"); + } + StateAction?.Invoke($"与服务器{ip}连接成功!"); + } + + } +} diff --git a/PCRobot/Entitys/Display_Real.cs b/PCRobot/Entitys/Display_Real.cs new file mode 100644 index 0000000..cf58f6b --- /dev/null +++ b/PCRobot/Entitys/Display_Real.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Entitys +{ + /// <summary> + /// 展示与实际值 + /// </summary> + internal class Display_Real + { + public Display_Real(string Display, string Real) + { + this.Display = Display; + this.Real = Real; + } + + /// <summary> + /// 展示值 + /// </summary> + private string _Display; + + public string Display + { + get { return _Display; } + set { _Display = value; } + } + + /// <summary> + /// 实际值 + /// </summary> + private string _Real; + + public string Real + { + get { return _Real; } + set { _Real = value; } + } + } +} diff --git a/PCRobot/Entitys/Enterprise/CreateGroupInfo.cs b/PCRobot/Entitys/Enterprise/CreateGroupInfo.cs new file mode 100644 index 0000000..16ea936 --- /dev/null +++ b/PCRobot/Entitys/Enterprise/CreateGroupInfo.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Entitys.Enterprise +{ + public class CreateGroupInfo + { + /// <summary> + /// 创建者账号 + /// </summary> + public string CreateUserName { get; set; } + + /// <summary> + /// 群id + /// </summary> + public string GroupId { get; set; } + + /// <summary> + /// 群昵称 + /// </summary> + public string GroupNick { get; set; } + + /// <summary> + /// 创建时间 + /// </summary> + public long CreateTime { get; set; } + } +} diff --git a/PCRobot/Entitys/Enterprise/FileC2cCdnInfo.cs b/PCRobot/Entitys/Enterprise/FileC2cCdnInfo.cs new file mode 100644 index 0000000..b4c23a8 --- /dev/null +++ b/PCRobot/Entitys/Enterprise/FileC2cCdnInfo.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Entitys.Enterprise +{ + /// <summary> + /// 文件Cdn信息 + /// </summary> + public class FileC2cCdnInfo + { + //{"data":{"error_code":0,"file_aes_key":"34336366636637353562383135383465","file_id":"3072020102046b30690201000204f4287e6802030f59b102049317fa710204625050f7042d4e45574944315f6634323837653638393331376661373136323530353133375f3136343934333037373633303002010002030107d0041000fcd55383fba8807e1510efed058c400201010201000400","file_key":"1649430840411","file_md5":"00fcd55383fba8807e1510efed058c40","file_path":"D:\\项目\\秒单客项目\\返利机器人\\3.0\\yz_client\\yz_client\\yz_client\\bin\\Debug\\Cache\\Image\\3c78ef60613e43f1b5a369d528ce50b6.jpg","file_size":67523,"file_type":1,"image_height":960,"image_width":960},"type":11115} + public int error_code { get; set; } + public string file_aes_key { get; set; } + public string file_id { get; set; } + public string file_key { get; set; } + public string file_md5 { get; set; } + public string file_path { get; set; } + public int file_size { get; set; } + public int file_type { get; set; } + public int image_height { get; set; } + public int image_width { get; set; } + + } +} diff --git a/PCRobot/Entitys/Enterprise/FriendInfoHandlerEnterprise.cs b/PCRobot/Entitys/Enterprise/FriendInfoHandlerEnterprise.cs new file mode 100644 index 0000000..dc92a2d --- /dev/null +++ b/PCRobot/Entitys/Enterprise/FriendInfoHandlerEnterprise.cs @@ -0,0 +1,36 @@ +namespace PCRobot.Entitys.Enterprise +{ + /// <summary> + /// 企业微信操作用户信息(搜索|添加微信用户|添加企业用户|添加名片用户|添加删除的联系人) + /// </summary> + public class FriendInfoHandlerEnterprise + { + public string user_id { get; set; } + + /// <summary> + /// openid 个人微信用户 + /// </summary> + public string openid { get; set; } + /// <summary> + /// wx_ticket 个人微信用户 + /// </summary> + public string wx_ticket { get; set; } + + /// <summary> + /// 公司id 企业微信用户 + /// </summary> + public string corp_id { get; set; } + + /// <summary> + /// from_user_id 添加名片为联系人 + /// from_user_id 是接收名片消息中的sender + /// </summary> + public string from_user_id { get; set; } + + /// <summary> + /// 验证信息 + /// </summary> + public string verify { get; set; } + + } +} \ No newline at end of file diff --git a/PCRobot/Entitys/PcCircle.cs b/PCRobot/Entitys/PcCircle.cs new file mode 100644 index 0000000..410f649 --- /dev/null +++ b/PCRobot/Entitys/PcCircle.cs @@ -0,0 +1,332 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Entitys +{ + #region pc原始单条朋友圈对象 + + public class CommentUserListOri + { + /// <summary> + /// + /// </summary> + public int commentFlag { get; set; } + /// <summary> + /// + /// </summary> + public int commentId { get; set; } + /// <summary> + /// + /// </summary> + public int commentId2 { get; set; } + /// <summary> + /// + /// </summary> + public string content { get; set; } + /// <summary> + /// + /// </summary> + public int createTime { get; set; } + /// <summary> + /// + /// </summary> + public int deleteFlag { get; set; } + /// <summary> + /// + /// </summary> + public int isNotRichText { get; set; } + /// <summary> + /// + /// </summary> + public string nickname { get; set; } + /// <summary> + /// + /// </summary> + public int replyCommentId { get; set; } + /// <summary> + /// + /// </summary> + public int replyCommentId2 { get; set; } + /// <summary> + /// + /// </summary> + public string replyUsername { get; set; } + /// <summary> + /// + /// </summary> + public int source { get; set; } + /// <summary> + /// + /// </summary> + public int type { get; set; } + /// <summary> + /// + /// </summary> + public string username { get; set; } + } + + public class LikeUserListOri + { + /// <summary> + /// + /// </summary> + public int commentFlag { get; set; } + /// <summary> + /// + /// </summary> + public int commentId { get; set; } + /// <summary> + /// + /// </summary> + public int commentId2 { get; set; } + /// <summary> + /// + /// </summary> + public string content { get; set; } + /// <summary> + /// + /// </summary> + public int createTime { get; set; } + /// <summary> + /// + /// </summary> + public int deleteFlag { get; set; } + /// <summary> + /// + /// </summary> + public int isNotRichText { get; set; } + /// <summary> + /// + /// </summary> + public string nickname { get; set; } + /// <summary> + /// + /// </summary> + public int replyCommentId { get; set; } + /// <summary> + /// + /// </summary> + public int replyCommentId2 { get; set; } + /// <summary> + /// + /// </summary> + public string replyUsername { get; set; } + /// <summary> + /// + /// </summary> + public int source { get; set; } + /// <summary> + /// + /// </summary> + public int type { get; set; } + /// <summary> + /// + /// </summary> + public string username { get; set; } + } + + public class ObjectDesc + { + /// <summary> + /// + /// </summary> + public string buffer { get; set; } + /// <summary> + /// + /// </summary> + public int iLen { get; set; } + } + + public class ObjectOperations + { + /// <summary> + /// + /// </summary> + public string buffer { get; set; } + /// <summary> + /// + /// </summary> + public int iLen { get; set; } + } + + public class PreDownloadInfo + { + /// <summary> + /// + /// </summary> + public string noPreDownloadRange { get; set; } + /// <summary> + /// + /// </summary> + public int preDownloadNetType { get; set; } + /// <summary> + /// + /// </summary> + public int preDownloadPercent { get; set; } + } + + public class SnsRedEnvelops + { + /// <summary> + /// + /// </summary> + public int reportId { get; set; } + /// <summary> + /// + /// </summary> + public int reportKey { get; set; } + /// <summary> + /// + /// </summary> + public int resourceId { get; set; } + /// <summary> + /// + /// </summary> + public int rewardCount { get; set; } + } + + public class WeAppInfo + { + /// <summary> + /// + /// </summary> + public int appId { get; set; } + /// <summary> + /// + /// </summary> + public string mapPoiId { get; set; } + /// <summary> + /// + /// </summary> + public string redirectUrl { get; set; } + /// <summary> + /// + /// </summary> + public int score { get; set; } + /// <summary> + /// + /// </summary> + public int showType { get; set; } + /// <summary> + /// + /// </summary> + public string userName { get; set; } + } + + public class CirCleInfoOri + { + /// <summary> + /// + /// </summary> + public int blackListCount { get; set; } + /// <summary> + /// + /// </summary> + public int commentCount { get; set; } + /// <summary> + /// + /// </summary> + public List<CommentUserListOri> commentUserList { get; set; } + /// <summary> + /// + /// </summary> + public int commentUserListCount { get; set; } + /// <summary> + /// + /// </summary> + public int createTime { get; set; } + /// <summary> + /// + /// </summary> + public int deleteFlag { get; set; } + /// <summary> + /// + /// </summary> + public int extFlag { get; set; } + /// <summary> + /// + /// </summary> + public int groupCount { get; set; } + /// <summary> + /// + /// </summary> + public int groupUserCount { get; set; } + /// <summary> + /// + /// </summary> + public double id { get; set; } + /// <summary> + /// + /// </summary> + public int isNotRichText { get; set; } + /// <summary> + /// + /// </summary> + public int likeCount { get; set; } + /// <summary> + /// + /// </summary> + public int likeFlag { get; set; } + /// <summary> + /// + /// </summary> + public List<LikeUserListOri> likeUserList { get; set; } + /// <summary> + /// + /// </summary> + public int likeUserListCount { get; set; } + /// <summary> + /// + /// </summary> + public string nickname { get; set; } + /// <summary> + /// + /// </summary> + public int noChange { get; set; } + /// <summary> + /// + /// </summary> + public ObjectDesc objectDesc { get; set; } + /// <summary> + /// + /// </summary> + public ObjectOperations objectOperations { get; set; } + /// <summary> + /// + /// </summary> + public PreDownloadInfo preDownloadInfo { get; set; } + /// <summary> + /// + /// </summary> + public int referId { get; set; } + /// <summary> + /// + /// </summary> + public string referUsername { get; set; } + /// <summary> + /// + /// </summary> + public SnsRedEnvelops snsRedEnvelops { get; set; } + /// <summary> + /// + /// </summary> + public string username { get; set; } + /// <summary> + /// + /// </summary> + public WeAppInfo weAppInfo { get; set; } + /// <summary> + /// + /// </summary> + public int withUserCount { get; set; } + /// <summary> + /// + /// </summary> + public int withUserListCount { get; set; } + } + + #endregion +} diff --git a/PCRobot/Entitys/RemoteLoginCode.cs b/PCRobot/Entitys/RemoteLoginCode.cs new file mode 100644 index 0000000..7ec0832 --- /dev/null +++ b/PCRobot/Entitys/RemoteLoginCode.cs @@ -0,0 +1,41 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Entitys +{ + /// <summary> + /// 远程登录微信二维码类 + /// </summary> + public class RemoteLoginCode + { + /// <summary> + /// 微信pid + /// </summary> + public int pid { get; set; } + + /// <summary> + /// 二维码图片文件md5 + /// </summary> + public string b64Md5 { get; set; } + + /// <summary> + /// 机器人类型 + /// </summary> + public RobotType rType { get; set; } + + /// <summary> + /// 二维码图片Base64 + /// </summary> + public string cImgB64 { get; set; } + + /// <summary> + /// 请求二维码时间 + /// </summary> + public long t { get; set; } + } + +} diff --git a/PCRobot/Entitys/UpLoadImage.cs b/PCRobot/Entitys/UpLoadImage.cs new file mode 100644 index 0000000..9b32a44 --- /dev/null +++ b/PCRobot/Entitys/UpLoadImage.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Entitys +{ + /// <summary> + /// 图片上传返回的数据类 + /// </summary> + public class UpLoadImage + { + /// <summary> + /// + /// </summary> + public Data data { get; set; } + /// <summary> + /// + /// </summary> + public int type { get; set; } + } + + public class BaseResponse + { + /// <summary> + /// + /// </summary> + public int ret { get; set; } + } + + public class BufferUrl + { + /// <summary> + /// + /// </summary> + public int type { get; set; } + /// <summary> + /// + /// </summary> + public string url { get; set; } + } + + public class ThumbUrls + { + /// <summary> + /// + /// </summary> + public int type { get; set; } + /// <summary> + /// + /// </summary> + public string url { get; set; } + } + + public class Data + { + /// <summary> + /// + /// </summary> + public BaseResponse baseResponse { get; set; } + /// <summary> + /// + /// </summary> + public BufferUrl bufferUrl { get; set; } + /// <summary> + /// + /// </summary> + public string clientId { get; set; } + /// <summary> + /// + /// </summary> + public int id { get; set; } + /// <summary> + /// D:\公司项目\fl_system\PCRobot\bin\Debug\Cache\0728114016639.png + /// </summary> + public string path { get; set; } + /// <summary> + /// + /// </summary> + public int startPos { get; set; } + /// <summary> + /// + /// </summary> + public int thumbUrlCount { get; set; } + /// <summary> + /// + /// </summary> + public List<ThumbUrls> thumbUrls { get; set; } + /// <summary> + /// + /// </summary> + public int totalLen { get; set; } + /// <summary> + /// + /// </summary> + public int type { get; set; } + } + +} diff --git a/PCRobot/Enums/RoutineEnum.cs b/PCRobot/Enums/RoutineEnum.cs new file mode 100644 index 0000000..14aabfb --- /dev/null +++ b/PCRobot/Enums/RoutineEnum.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Enums +{ + public enum RequestIsRunType + { + 获取群列表 = 0, + 获取好友列表 = 1, + 获取新创建的群号 = 2, + + //个人微信 + 获取收藏 = 100, + 获取公众号列表 = 101, + 获取朋友圈 = 102, + 上传朋友圈图片 = 103, + } +} diff --git a/PCRobot/HPSocketCS/Extra.cs b/PCRobot/HPSocketCS/Extra.cs new file mode 100644 index 0000000..46b0985 --- /dev/null +++ b/PCRobot/HPSocketCS/Extra.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections.Concurrent; + +namespace HPSocketCS +{ + public class Extra<T> + { + ConcurrentDictionary<IntPtr, T> dict = new ConcurrentDictionary<IntPtr, T>(); + + /// <summary> + /// 获取附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public T Get(IntPtr key) + { + T value; + if (dict.TryGetValue(key, out value)) + { + return value; + } + return default(T); + } + + /// <summary> + /// 设置附加数据 + /// + /// </summary> + /// <param name="key"></param> + /// <param name="newValue"></param> + /// <returns></returns> + public bool Set(IntPtr key, T newValue) + { + try + { + dict.AddOrUpdate(key, newValue, (tKey, existingVal) => { return newValue; }); + return true; + } + catch (OverflowException) + { + // 字典数目超过int.max + return false; + } + catch (ArgumentNullException) + { + // 参数为空 + return false; + } + catch (Exception) + { + return false; + } + } + + /// <summary> + /// 删除附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public bool Remove(IntPtr key) + { + T value; + return dict.TryRemove(key, out value); + } + } + + + public class ConnectionExtra + { + ConcurrentDictionary<IntPtr, object> dict = new ConcurrentDictionary<IntPtr, object>(); + + /// <summary> + /// 获取附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public object GetExtra(IntPtr key) + { + object value; + if (dict.TryGetValue(key, out value)) + { + return value; + } + return null; + } + + /// <summary> + /// 获取附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public T GetExtra<T>(IntPtr key) + { + object value; + if (dict.TryGetValue(key, out value)) + { + return (T)value; + } + return default(T); + } + + /// <summary> + /// 设置附加数据 + /// + /// </summary> + /// <param name="key"></param> + /// <param name="value"></param> + /// <returns></returns> + public bool SetExtra(IntPtr key, object newValue) + { + try + { + dict.AddOrUpdate(key, newValue, (tKey, existingVal) => { return newValue; }); + return true; + } + catch (OverflowException) + { + // 字典数目超过int.max + return false; + } + catch (ArgumentNullException) + { + // 参数为空 + return false; + } + catch (Exception) + { + return false; + } + } + + /// <summary> + /// 删除附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public bool RemoveExtra(IntPtr key) + { + object value; + return dict.TryRemove(key, out value); + } + } +} diff --git a/PCRobot/HPSocketCS/Sdk.cs b/PCRobot/HPSocketCS/Sdk.cs new file mode 100644 index 0000000..3afac80 --- /dev/null +++ b/PCRobot/HPSocketCS/Sdk.cs @@ -0,0 +1,3498 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; +using HPSocketCS; + +namespace HPSocketCS +{ + public interface IServer + { + + } + public class ServerEvent + { + public delegate HandleResult OnSendEventHandler(IServer sender, IntPtr connId, byte[] bytes); + public delegate HandleResult OnReceiveEventHandler(IServer sender, IntPtr connId, byte[] bytes); + public delegate HandleResult OnPointerDataReceiveEventHandler(IServer sender, IntPtr connId, IntPtr pData, int length); + public delegate HandleResult OnCloseEventHandler(IServer sender, IntPtr connId, SocketOperation enOperation, int errorCode); + public delegate HandleResult OnShutdownEventHandler(IServer sender); + public delegate HandleResult OnPrepareListenEventHandler(IServer sender, IntPtr soListen); + /// <summary> + /// 连接进入 + /// </summary> + /// <param name="sender"></param> + /// <param name="connId"></param> + /// <param name="pClient">如果为 TCP 连接,pClient为 SOCKET 句柄;如果为 UDP 连接,pClient为 SOCKADDR 指针;</param> + /// <returns></returns> + public delegate HandleResult OnAcceptEventHandler(IServer sender, IntPtr connId, IntPtr pClient); + public delegate HandleResult OnHandShakeEventHandler(IServer sender, IntPtr connId); + } + + public interface IClient + { + + } + + public class ClientEvent + { + public delegate HandleResult OnPrepareConnectEventHandler(IClient sender, IntPtr socket); + public delegate HandleResult OnConnectEventHandler(IClient sender); + public delegate HandleResult OnSendEventHandler(IClient sender, byte[] bytes); + public delegate HandleResult OnReceiveEventHandler(IClient sender, byte[] bytes); + public delegate HandleResult OnPointerDataReceiveEventHandler(IClient sender, IntPtr pData, int length); + public delegate HandleResult OnCloseEventHandler(IClient sender, SocketOperation enOperation, int errorCode); + public delegate HandleResult OnHandShakeEventHandler(IClient sender); + } + + + + /// <summary> + /// 通信组件服务状态,用程序可以通过通信组件的 GetState() 方法获取组件当前服务状态 + /// </summary> + public enum ServiceState + { + /// <summary> + /// 正在启动 + /// </summary> + Starting = 0, + /// <summary> + /// 已经启动 + /// </summary> + Started = 1, + /// <summary> + /// 正在停止 + /// </summary> + Stopping = 2, + /// <summary> + /// 已经启动 + /// </summary> + Stopped = 3, + } + + /// <summary> + /// Socket 操作类型,应用程序的 OnErrror() 事件中通过该参数标识是哪种操作导致的错误 + /// </summary> + public enum SocketOperation + { + Unknown = 0, // Unknown + Accept = 1, // Accept + Connect = 2, // Connect + Send = 3, // Send + Receive = 4, // Receive + Close = 5, // Receive + }; + + /// <summary> + /// 事件通知处理结果,事件通知的返回值,不同的返回值会影响通信组件的后续行为 + /// </summary> + public enum HandleResult + { + /// <summary> + /// 成功 + /// </summary> + Ok = 0, + /// <summary> + /// 忽略 + /// </summary> + Ignore = 1, + /// <summary> + /// 错误 + /// </summary> + Error = 2, + }; + + + /// <summary> + /// 名称:操作结果代码 + /// 描述:组件 Start() / Stop() 方法执行失败时,可通过 GetLastError() 获取错误代码 + /// </summary> + public enum SocketError + { + /// <summary> + /// 成功 + /// </summary> + Ok = 0, + /// <summary> + /// 当前状态不允许操作 + /// </summary> + IllegalState = 1, + /// <summary> + /// 非法参数 + /// </summary> + InvalidParam = 2, + /// <summary> + /// 创建 SOCKET 失败 + /// </summary> + SocketCreate = 3, + /// <summary> + /// 绑定 SOCKET 失败 + /// </summary> + SocketBind = 4, + /// <summary> + /// 设置 SOCKET 失败 + /// </summary> + SocketPrepare = 5, + /// <summary> + /// 监听 SOCKET 失败 + /// </summary> + SocketListen = 6, + /// <summary> + /// 创建完成端口失败 + /// </summary> + CPCreate = 7, + /// <summary> + /// 创建工作线程失败 + /// </summary> + WorkerThreadCreate = 8, + /// <summary> + /// 创建监测线程失败 + /// </summary> + DetectThreadCreate = 9, + /// <summary> + /// 绑定完成端口失败 + /// </summary> + SocketAttachToCP = 10, + /// <summary> + /// 连接服务器失败 + /// </summary> + ConnectServer = 11, + /// <summary> + /// 网络错误 + /// </summary> + Network = 12, + /// <summary> + /// 数据处理错误 + /// </summary> + DataProc = 13, + /// <summary> + /// 数据发送失败 + /// </summary> + DataSend = 14, + + /***** SSL Socket 扩展操作结果代码 *****/ + /// <summary> + /// SSL 环境未就绪 + /// </summary> + SSLEnvNotReady = 101, + }; + + /// <summary> + /// 数据抓取结果,数据抓取操作的返回值 + /// </summary> + public enum FetchResult + { + /// <summary> + /// 成功 + /// </summary> + Ok = 0, + /// <summary> + /// 抓取长度过大 + /// </summary> + LengthTooLong = 1, + /// <summary> + /// 找不到 ConnID 对应的数据 + /// </summary> + DataNotFound = 2, + }; + + /// <summary> + /// 发送策略 + /// </summary> + public enum SendPolicy + { + /// <summary> + /// 打包模式(默认) + /// </summary> + Pack = 0, + /// <summary> + /// 安全模式 + /// </summary> + Safe = 1, + /// <summary> + /// 直接模式 + /// </summary> + Direct = 2, + }; + + + /// <summary> + /// OnSend 事件同步策略 + /// Server 组件和 Agent 组件的 OnSend 事件同步策略 + /// </summary> + public enum OnSendSyncPolicy + { + /// <summary> + /// 不同步(默认) :不同步 OnSend 事件,此时可能同时触发 OnReceive 和 OnClose 事件 + /// </summary> + OSSP_NONE = 0, + /// <summary> + /// 同步 OnClose :只同步 OnClose 事件,此时可能同时触发 OnReceive 事件 + /// </summary> + OSSP_CLOSE = 1, + /// <summary> + /// 同步 OnReceive :(只用于 TCP 组件)同步 OnReceive 和 OnClose 事件,此处不可能同时触发 OnReceive 或 OnClose 事件 + /// </summary> + OSSP_RECEIVE = 2, + } + + + /// <summary> + /// 播送模式 UDP 组件的播送模式(组播或广播) + /// </summary> + public enum CastMode + { + /// <summary> + /// 组播 + /// </summary> + Multicast = 0, + /// <summary> + /// 广播 + /// </summary> + Broadcast = 1, + + } + + /// <summary> + /// 名称:IP 地址类型 + /// 描述:IP 地址类型枚举值 + /// </summary> + public enum IPAddrType + { + /// <summary> + /// 所有 + /// </summary> + All = 0, + /// <summary> + /// IPv4 + /// </summary> + IPV4 = 1, + /// <summary> + /// IPv6 + /// </summary> + IPV6 = 2, + /// <summary> + /// 其他 + /// </summary> + Other = 100, + } + + /// <summary> + /// 接收状态 + /// </summary> + public enum ReceiveState : int + { + /// <summary> + /// 未知 + /// </summary> + Unknown = -1, + /// <summary> + /// 唤醒状态 + /// </summary> + Resume = 0, + /// <summary> + /// 暂停状态 + /// </summary> + Pause = 1, + } + + /****************************************************/ + /************** sockaddr结构体,udp服务器时OnAccept最后个参数可转化 **************/ + [StructLayout(LayoutKind.Sequential)] + public struct in_addr + { + public ulong S_addr; + } + + //[StructLayout(LayoutKind.Sequential)] + //public struct in_addr + //{ + // public byte s_b1, s_b2, s_b3, s_b4; + //} + + [StructLayout(LayoutKind.Sequential)] + public struct sockaddr_in + { + public short sin_family; + public ushort sin_port; + public in_addr sin_addr; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] sLibNamesin_zero; + } + + /****************************************************/ + + [StructLayout(LayoutKind.Sequential)] + public struct WSABUF + { + public int Length; + public IntPtr Buffer; + } + + /// <summary> + /// 名称:IP 地址条目结构体 + /// 描述:IP 地址的地址簇/地址值结构体 + /// </summary> + public struct IPAddr + { + public IPAddrType Type; + public string Address; + public string TypeString; + } + + + /// <summary> + /// DnsHelper + /// </summary> + public class DnsHelper + { + /// <summary> + /// 获取本机ipv4+ipv6地址 + /// hp-socket可用的ip地址结构 + /// </summary> + /// <returns></returns> + public static List<IPAddr> GetLocalHostAddressesToIPAddrList() + { + return Dns.GetHostAddresses(Dns.GetHostName()).Where(p => p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork || + p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6). + Select(p => new IPAddr + { + Type = p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? IPAddrType.IPV4 : IPAddrType.IPV6, + Address = p.ToString(), + }).ToList(); + } + + /// <summary> + /// 获取本机ipv4+ipv6地址 + /// .net自带的ip地址结构 + /// </summary> + /// <returns></returns> + public static IPAddress[] GetLocalHostAddresses() + { + return Dns.GetHostAddresses(Dns.GetHostName()); + } + } +} + + +/// <summary> +/// ANSI版本 +/// </summary> +public class Sdk +{ + + + /// <summary> + /// HPSocket的文件路径 + /// </summary> + public const string HPSOCKET_DLL_PATH = "bin\\hpsocket4c"; + + /*****************************************************************************************************/ + /******************************************** 公共类、接口 ********************************************/ + /*****************************************************************************************************/ + + + + /****************************************************/ + /************** HPSocket4C.dll 回调函数 **************/ + /* Agent & Server & Client */ + public delegate HandleResult OnSend(IntPtr pSender, IntPtr connId, IntPtr pData, int length); + public delegate HandleResult OnReceive(IntPtr pSender, IntPtr connId, IntPtr pData, int length); + public delegate HandleResult OnPullReceive(IntPtr pSender, IntPtr connId, int length); + public delegate HandleResult OnClose(IntPtr pSender, IntPtr connId, SocketOperation enOperation, int errorCode); + public delegate HandleResult OnHandShake(IntPtr pSender, IntPtr connId); + + + /* Agent & Server */ + public delegate HandleResult OnShutdown(IntPtr pSender); + + /* Agent & Client */ + public delegate HandleResult OnPrepareConnect(IntPtr pSender, IntPtr connId /* IntPtr pClient */, IntPtr socket); + public delegate HandleResult OnConnect(IntPtr pSender, IntPtr connId /* IntPtr pClient */); + + /* Server */ + public delegate HandleResult OnPrepareListen(IntPtr pSender, IntPtr soListen); + public delegate HandleResult OnAccept(IntPtr pSender, IntPtr connId, IntPtr pClient); + + /****************************************************/ + /************** HPSocket4C.dll 导出函数 **************/ + + /// <summary> + /// 创建 TcpServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpServer(IntPtr pListener); + + /// <summary> + /// 创建 TcpClient 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpClient(IntPtr pListener); + + /// <summary> + /// 创建 TcpAgent 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpAgent(IntPtr pListener); + + /// <summary> + /// 创建 TcpPullServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullServer(IntPtr pListener); + + /// <summary> + /// 创建 TcpPullClient 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullClient(IntPtr pListener); + + /// <summary> + /// 创建 TcpPullAgent 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullAgent(IntPtr pListener); + + /// <summary> + /// 创建 HP_TcpPackServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackServer(IntPtr pListener); + + /// <summary> + /// 创建 HP_TcpPackAgent 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackAgent(IntPtr pListener); + + /// <summary> + /// 创建 HP_TcpPackAgent 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackClient(IntPtr pListener); + + /// <summary> + /// 创建 UdpServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpServer(IntPtr pListener); + + /// <summary> + /// 创建 UdpClient 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpClient(IntPtr pListener); + + + /// <summary> + /// 创建 HP_UdpCast 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpCast(IntPtr pListener); + + + /// <summary> + /// 销毁 TcpServer 对象 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpServer(IntPtr pServer); + + /// <summary> + /// 销毁 TcpClient 对象 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpClient(IntPtr pClient); + + /// <summary> + /// 销毁 TcpAgent 对象 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpAgent(IntPtr pAgent); + + /// <summary> + /// 销毁 TcpPullServer 对象 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullServer(IntPtr pServer); + + /// <summary> + /// 销毁 TcpPullClient 对象 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullClient(IntPtr pClient); + + /// <summary> + /// 销毁 TcpPullAgent 对象 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullAgent(IntPtr pAgent); + + /// <summary> + /// 销毁 HP_TcpPackServer 对象 + /// </summary> + /// <param name="pServer"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackServer(IntPtr pServer); + + /// <summary> + /// 销毁 HP_TcpPackAgent 对象 + /// </summary> + /// <param name="pAgent"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackAgent(IntPtr pAgent); + + /// <summary> + /// 销毁 HP_TcpPackClient 对象 + /// </summary> + /// <param name="pClient"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackClient(IntPtr pClient); + + + /// <summary> + /// 销毁 UdpServer 对象 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpServer(IntPtr pServer); + + /// <summary> + /// 销毁 UdpClient 对象 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpClient(IntPtr pClient); + + /// <summary> + /// 销毁 HP_UdpCast 对象 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpCast(IntPtr pCast); + + + /// <summary> + /// 创建 TcpServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpServerListener(); + + /// <summary> + /// 创建 TcpClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpClientListener(); + + /// <summary> + /// 创建 TcpAgentListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpAgentListener(); + + /// <summary> + /// 创建 TcpPullServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullServerListener(); + + /// <summary> + /// 创建 TcpPullClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullClientListener(); + + /// <summary> + /// 创建 TcpPullAgentListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullAgentListener(); + + /// <summary> + /// 创建 TcpPackServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackServerListener(); + + /// <summary> + /// 创建 TcpPackClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackClientListener(); + + /// <summary> + /// 创建 TcpPackAgentListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackAgentListener(); + + /// <summary> + /// 创建 UdpServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpServerListener(); + + /// <summary> + /// 创建 UdpClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpClientListener(); + + /// <summary> + /// 创建 HP_UdpCastListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpCastListener(); + + + + /// <summary> + /// 销毁 TcpServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpClientListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpAgentListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpAgentListener(IntPtr pListener); + + + /// <summary> + /// 销毁 TcpPullServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPullClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullClientListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPullAgentListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullAgentListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPackServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPackClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackClientListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPackAgentListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackAgentListener(IntPtr pListener); + + /// <summary> + /// 销毁 UdpServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 UdpClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpClientListener(IntPtr pListener); + + /// <summary> + /// 销毁 HP_UdpCastListener 对象 + /// </summary> + /// <param name="pListener"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpCastListener(IntPtr pListener); + + + /**********************************************************************************/ + /***************************** Server 回调函数设置方法 *****************************/ + + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnPrepareListen(IntPtr pListener, OnPrepareListen fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnAccept(IntPtr pListener, OnAccept fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnHandShake(IntPtr pListener, OnHandShake fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnSend(IntPtr pListener, OnSend fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnClose(IntPtr pListener, OnClose fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnShutdown(IntPtr pListener, OnShutdown fn); + + /**********************************************************************************/ + /***************************** Client 回调函数设置方法 *****************************/ + + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnPrepareConnect(IntPtr pListener, OnPrepareConnect fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnConnect(IntPtr pListener, OnConnect fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnHandShake(IntPtr pListener, OnHandShake fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnSend(IntPtr pListener, OnSend fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnClose(IntPtr pListener, OnClose fn); + + /**********************************************************************************/ + /****************************** Agent 回调函数设置方法 *****************************/ + + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnPrepareConnect(IntPtr pListener, OnPrepareConnect fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnConnect(IntPtr pListener, OnConnect fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnHandShake(IntPtr pListener, OnHandShake fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnSend(IntPtr pListener, OnSend fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnClose(IntPtr pListener, OnClose fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnShutdown(IntPtr pListener, OnShutdown fn); + + /**************************************************************************/ + /***************************** Server 操作方法 *****************************/ + + /// <summary> + /// 名称:启动通信组件 + /// 描述:启动服务端通信组件,启动完成后可开始接收客户端连接并收发数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="pszBindAddress">监听地址</param> + /// <param name="usPort">监听端口</param> + /// <returns>失败,可通过 GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Start(IntPtr pServer, string pszBindAddress, ushort usPort); + + /// <summary> + /// 关闭服务端通信组件,关闭完成后断开所有客户端连接并释放所有资源 + /// </summary> + /// <param name="pServer"></param> + /// <returns>失败,可通过 GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Stop(IntPtr pServer); + + /// <summary> + /// 用户通过该方法向指定客户端发送数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">发送数据长度</param> + /// <param name="length">发送数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Send(IntPtr pServer, IntPtr connId, byte[] pBuffer, int length); + + /// <summary> + /// 用户通过该方法向指定客户端发送数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">发送数据长度</param> + /// <param name="length">发送数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Send(IntPtr pServer, IntPtr connId, IntPtr pBuffer, int length); + + /// <summary> + /// 用户通过该方法向指定客户端发送数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SendPart(IntPtr pServer, IntPtr connId, byte[] pBuffer, int length, int iOffset); + + /// <summary> + /// 用户通过该方法向指定客户端发送数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SendPart(IntPtr pServer, IntPtr connId, IntPtr pBuffer, int length, int iOffset); + + + /// <summary> + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffers">发送缓冲区数组</param> + /// <param name="iCount">发送缓冲区数目</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SendPackets(IntPtr pServer, IntPtr connId, WSABUF[] pBuffers, int iCount); + + /// <summary> + /// 名称:暂停/恢复接收 + /// 描述:暂停/恢复某个连接的数据接收工作 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwConnID">连接 ID</param> + /// <param name="bPause">TRUE - 暂停, FALSE - 恢复</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_PauseReceive(IntPtr pServer, IntPtr dwConnID, bool bPause); + + + + /// <summary> + /// 断开与某个客户端的连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Disconnect(IntPtr pServer, IntPtr connId, bool bForce); + + /// <summary> + /// 断开超过指定时长的连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwPeriod">时长(毫秒)</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_DisconnectLongConnections(IntPtr pServer, uint dwPeriod, bool bForce); + + /// <summary> + /// 断开超过指定时长的静默连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwPeriod">时长(毫秒)</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_DisconnectSilenceConnections(IntPtr pServer, uint dwPeriod, bool bForce); + + /******************************************************************************/ + /***************************** Server 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据发送策略 + /// </summary> + /// <param name="pServer"></param> + /// <param name="enSendPolicy"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetSendPolicy(IntPtr pServer, SendPolicy enSendPolicy); + + /// <summary> + /// 获取数据发送策略 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SendPolicy HP_Server_GetSendPolicy(IntPtr pServer); + + /// <summary> + /// 设置连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pExtra"></param> + /// <returns>若返回 false 失败则为(无效的连接 ID)</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SetConnectionExtra(IntPtr pServer, IntPtr connId, IntPtr pExtra); + + /// <summary> + /// 获取连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pExtra">数据指针</param> + /// <returns>若返回 false 失败则为(无效的连接 ID)</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetConnectionExtra(IntPtr pServer, IntPtr connId, ref IntPtr pExtra); + + /// <summary> + /// 检测是否为安全连接(SSL/HTTPS) + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_IsSecure(IntPtr pServer); + + + /// <summary> + /// 检查通信组件是否已启动 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_HasStarted(IntPtr pServer); + + /// <summary> + /// 查看通信组件当前状态 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ServiceState HP_Server_GetState(IntPtr pServer); + + /// <summary> + /// 获取最近一次失败操作的错误代码 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SocketError HP_Server_GetLastError(IntPtr pServer); + + /// <summary> + /// 获取最近一次失败操作的错误描述 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Server_GetLastErrorDesc(IntPtr pServer); + + + /// <summary> + /// 获取连接中未发出数据的长度 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="piPending"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetPendingDataLength(IntPtr pServer, IntPtr connId, ref int piPending); + + /// <summary> + /// 获取连接的数据接收状态 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwConnID"></param> + /// <param name="pbPaused"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_IsPauseReceive(IntPtr pServer, IntPtr dwConnID, ref int pbPaused); + + /// <summary> + /// 检测是否有效连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwConnID"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_IsConnected(IntPtr pServer, IntPtr dwConnID); + + + /// <summary> + /// 获取客户端连接数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetConnectionCount(IntPtr pServer); + + /// <summary> + /// 获取所有连接的 CONNID + /// </summary> + /// <param name="pServer"></param> + /// <param name="pIDs"></param> + /// <param name="pdwCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetAllConnectionIDs(IntPtr pServer, IntPtr[] pIDs, ref uint pdwCount); + + /// <summary> + /// 获取某个客户端连接时长(毫秒) + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pdwPeriod"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetConnectPeriod(IntPtr pServer, IntPtr connId, ref uint pdwPeriod); + + /// <summary> + /// 获取某个连接静默时间(毫秒) + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pdwPeriod"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetSilencePeriod(IntPtr pServer, IntPtr connId, ref uint pdwPeriod); + + /// <summary> + /// 获取监听 Socket 的地址信息 + /// </summary> + /// <param name="pServer"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetListenAddress(IntPtr pServer, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取某个连接的本地地址信息 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen">传入传出值,大小最好在222.222.222.222的长度以上</param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetLocalAddress(IntPtr pServer, IntPtr connId, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取某个连接的远程地址信息 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen">传入传出值,大小最好在222.222.222.222的长度以上</param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetRemoteAddress(IntPtr pServer, IntPtr connId, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + + + /// <summary> + /// 设置 OnSend 事件同步策略(默认:OSSP_NONE,不同步) + /// </summary> + /// <param name="pServer"></param> + /// <param name="syncPolicy"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetOnSendSyncPolicy(IntPtr pServer, OnSendSyncPolicy syncPolicy); + + /// <summary> + /// 获取 OnSend 事件同步策略 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern OnSendSyncPolicy HP_Server_GetOnSendSyncPolicy(IntPtr pServer); + + + /// <summary> + /// 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeSocketObjLockTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeSocketObjLockTime(IntPtr pServer, uint dwFreeSocketObjLockTime); + + /// <summary> + /// 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeSocketObjPool"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeSocketObjPool(IntPtr pServer, uint dwFreeSocketObjPool); + + /// <summary> + /// 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeBufferObjPool"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeBufferObjPool(IntPtr pServer, uint dwFreeBufferObjPool); + + /// <summary> + /// 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeSocketObjHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeSocketObjHold(IntPtr pServer, uint dwFreeSocketObjHold); + + /// <summary> + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeBufferObjHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeBufferObjHold(IntPtr pServer, uint dwFreeBufferObjHold); + + /// <summary> + /// 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxConnectionCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetMaxConnectionCount(IntPtr pServer, uint dwWMaxConnectionCount); + + /// <summary> + /// 设置工作线程数量(通常设置为 2 * CPU + 2) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwWorkerThreadCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetWorkerThreadCount(IntPtr pServer, uint dwWorkerThreadCount); + + /// <summary> + /// 设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:FALSE) + /// </summary> + /// <param name="pServer"></param> + /// <param name="bMarkSilence"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetMarkSilence(IntPtr pServer, bool bMarkSilence); + + /// <summary> + /// 获取 Socket 缓存对象锁定时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeSocketObjLockTime(IntPtr pServer); + + /// <summary> + /// 获取 Socket 缓存池大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeSocketObjPool(IntPtr pServer); + + /// <summary> + /// 获取内存块缓存池大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeBufferObjPool(IntPtr pServer); + + /// <summary> + /// 获取 Socket 缓存池回收阀值 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeSocketObjHold(IntPtr pServer); + + /// <summary> + /// 获取内存块缓存池回收阀值 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeBufferObjHold(IntPtr pServer); + + /// <summary> + /// 获取最大连接数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetMaxConnectionCount(IntPtr pServer); + + /// <summary> + /// 获取工作线程数量 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetWorkerThreadCount(IntPtr pServer); + + /// <summary> + /// 检测是否标记静默时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_IsMarkSilence(IntPtr pServer); + + /**********************************************************************************/ + /***************************** TCP Server 操作方法 *****************************/ + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="lpszFileName">文件路径</param> + /// <param name="pHead">头部附加数据</param> + /// <param name="pTail">尾部附加数据</param> + /// <returns>TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_TcpServer_SendSmallFile(IntPtr pServer, IntPtr connId, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /**********************************************************************************/ + /***************************** TCP Server 属性访问方法 *****************************/ + + /// <summary> + /// 设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwAcceptSocketCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetAcceptSocketCount(IntPtr pServer, uint dwAcceptSocketCount); + + /// <summary> + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwSocketBufferSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetSocketBufferSize(IntPtr pServer, uint dwSocketBufferSize); + + /// <summary> + /// 设置监听 Socket 的等候队列大小(根据并发连接数量调整设置) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwSocketListenQueue"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetSocketListenQueue(IntPtr pServer, uint dwSocketListenQueue); + + /// <summary> + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwKeepAliveTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetKeepAliveTime(IntPtr pServer, uint dwKeepAliveTime); + + /// <summary> + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwKeepAliveInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetKeepAliveInterval(IntPtr pServer, uint dwKeepAliveInterval); + + + /// <summary> + /// 获取 Accept 预投递数量 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetAcceptSocketCount(IntPtr pServer); + + /// <summary> + /// 获取通信数据缓冲区大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetSocketBufferSize(IntPtr pServer); + + /// <summary> + /// 获取监听 Socket 的等候队列大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetSocketListenQueue(IntPtr pServer); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetKeepAliveTime(IntPtr pServer); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetKeepAliveInterval(IntPtr pServer); + + + /**********************************************************************************/ + /***************************** UDP Server 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpServer_SetMaxDatagramSize(IntPtr pServer, uint dwMaxDatagramSize); + + /// <summary> + /// 获取数据报文最大长度 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpServer_GetMaxDatagramSize(IntPtr pServer); + + /// <summary> + /// 设置 Receive 预投递数量(根据负载调整设置,Receive 预投递数量越大则丢包概率越小) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwPostReceiveCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpServer_SetPostReceiveCount(IntPtr pServer, uint dwPostReceiveCount); + + /// <summary> + /// 获取 Receive 预投递数量 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpServer_GetPostReceiveCount(IntPtr pServer); + + /// <summary> + /// 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpServer_SetDetectAttempts(IntPtr pServer, uint dwMaxDatagramSize); + + /// <summary> + /// 设置监测包发送间隔(秒,0 不发送监测包) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpServer_SetDetectInterval(IntPtr pServer, uint dwMaxDatagramSize); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpServer_GetDetectAttempts(IntPtr pServer); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpServer_GetDetectInterval(IntPtr pServer); + /******************************************************************************/ + /***************************** Client 组件操作方法 *****************************/ + + /// <summary> + /// 启动客户端通信组件并连接服务端,启动完成后可开始收发数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="bAsyncConnect">是否采用异步 Connect</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Start(IntPtr pClient, string pszRemoteAddress, ushort usPort, bool bAsyncConnect); + + + /// <summary> + /// 启动通信组件(并指定绑定地址), 启动客户端通信组件并连接服务端,启动完成后可开始收发数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="bAsyncConnect">是否采用异步 Connect</param> + /// <param name="lpszBindAddress">绑定地址(默认:nullptr,TcpClient/UdpClient -> 不执行绑定操作,UdpCast 绑定 -> 0.0.0.0)</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_StartWithBindAddress(IntPtr pClient, string lpszRemoteAddress, ushort usPort, bool bAsyncConnect, string lpszBindAddress); + + /// <summary> + /// 名称:启动通信组件(并指定绑定地址) + /// 描述:启动客户端通信组件并连接服务端,启动完成后可开始收发数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="bAsyncConnect">是否采用异步 Connect</param> + /// <param name="lpszBindAddress">绑定地址(默认:nullptr,TcpClient/UdpClient -> 不执行绑定操作,UdpCast 绑定 -> 0.0.0.0)</param> + /// <param name="usLocalPort">本地端口(默认:0)</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_StartWithBindAddressAndLocalPort(IntPtr pClient, string lpszRemoteAddress, ushort usPort, bool bAsyncConnect, string lpszBindAddress, ushort usLocalPort); + + + /// <summary> + /// 关闭客户端通信组件,关闭完成后断开与服务端的连接并释放所有资源 + /// </summary> + /// <param name="pClient"></param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Stop(IntPtr pClient); + + /// <summary> + /// 用户通过该方法向服务端发送数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="connId">连接 ID(保留参数,目前该参数并未使用)</param> + /// <param name="pBuffer">发送数据缓冲区</param> + /// <param name="length">发送数据长度</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Send(IntPtr pClient, byte[] pBuffer, int length); + + /// <summary> + /// 用户通过该方法向服务端发送数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="connId">连接 ID(保留参数,目前该参数并未使用)</param> + /// <param name="pBuffer">发送数据缓冲区</param> + /// <param name="length">发送数据长度</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Send(IntPtr pClient, IntPtr pBuffer, int length); + + /// <summary> + /// 用户通过该方法向服务端发送数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_SendPart(IntPtr pClient, byte[] pBuffer, int length, int iOffset); + + /// <summary> + /// 用户通过该方法向服务端发送数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_SendPart(IntPtr pClient, IntPtr pBuffer, int length, int iOffset); + + + /// <summary> + /// 发送多组数据 + /// 向服务端发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// </summary> + /// <param name="pClient"></param> + /// <param name="pBuffers">发送缓冲区数组</param> + /// <param name="iCount">发送缓冲区数目</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_SendPackets(IntPtr pClient, WSABUF[] pBuffers, int iCount); + + + /// <summary> + /// 名称:暂停/恢复接收 + /// 描述:暂停/恢复某个连接的数据接收工作 + /// </summary> + /// <param name="pClient">TRUE - 暂停, FALSE - 恢复</param> + /// <param name="bPause">TRUE - 暂停, FALSE - 恢复</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_PauseReceive(IntPtr pClient, int bPause); + + /******************************************************************************/ + /***************************** Client 属性访问方法 *****************************/ + + /// <summary> + /// 设置连接的附加数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pExtra"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Client_SetExtra(IntPtr pClient, IntPtr pExtra); + + + /// <summary> + /// 获取连接的附加数据 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Client_GetExtra(IntPtr pClient); + + + /// <summary> + /// 检测是否为安全连接(SSL/HTTPS) + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_IsSecure(IntPtr pClient); + + + /// <summary> + /// 检查通信组件是否已启动 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_HasStarted(IntPtr pClient); + + /// <summary> + /// 查看通信组件当前状态 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ServiceState HP_Client_GetState(IntPtr pClient); + + /// <summary> + /// 获取最近一次失败操作的错误代码 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SocketError HP_Client_GetLastError(IntPtr pClient); + + /// <summary> + /// 获取最近一次失败操作的错误描述 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Client_GetLastErrorDesc(IntPtr pClient); + + /// <summary> + /// 获取该组件对象的连接 ID + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Client_GetConnectionID(IntPtr pClient); + + /// <summary> + /// 获取 Client Socket 的地址信息 + /// </summary> + /// <param name="pClient"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_GetLocalAddress(IntPtr pClient, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取连接的远程主机信息 + /// </summary> + /// <param name="pClient"></param> + /// <param name="lpszHost"></param> + /// <param name="piHostLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_GetRemoteHost(IntPtr pClient, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszHost, ref int piHostLen, ref ushort pusPort); + + + /// <summary> + /// 获取连接中未发出数据的长度 + /// </summary> + /// <param name="pClient"></param> + /// <param name="piPending"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_GetPendingDataLength(IntPtr pClient, ref int piPending); + + /// <summary> + /// 获取连接的数据接收状态 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pbPaused"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_IsPauseReceive(IntPtr pClient, ref int pbPaused); + + /// <summary> + /// 检测是否有效连接 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_IsConnected(IntPtr pClient); + + + /// <summary> + /// 设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 ) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwFreeBufferPoolSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Client_SetFreeBufferPoolSize(IntPtr pClient, uint dwFreeBufferPoolSize); + + /// <summary> + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwFreeBufferPoolHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Client_SetFreeBufferPoolHold(IntPtr pClient, uint dwFreeBufferPoolHold); + + /// <summary> + /// 获取内存块缓存池大小 + /// </summary> + /// <param name="pClient"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Client_GetFreeBufferPoolSize(IntPtr pClient); + + /// <summary> + /// 获取内存块缓存池回收阀值 + /// </summary> + /// <param name="pClient"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Client_GetFreeBufferPoolHold(IntPtr pClient); + /**********************************************************************************/ + /***************************** TCP Client 操作方法 *****************************/ + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="pServer"></param> + /// <param name="lpszFileName">文件路径</param> + /// <param name="pHead">头部附加数据</param> + /// <param name="pTail">尾部附加数据</param> + /// <returns>TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_TcpClient_SendSmallFile(IntPtr pClient, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /**********************************************************************************/ + /***************************** TCP Client 属性访问方法 *****************************/ + + /// <summary> + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj)) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwSocketBufferSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpClient_SetSocketBufferSize(IntPtr pClient, uint dwSocketBufferSize); + + /// <summary> + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwKeepAliveTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpClient_SetKeepAliveTime(IntPtr pClient, uint dwKeepAliveTime); + + /// <summary> + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwKeepAliveInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpClient_SetKeepAliveInterval(IntPtr pClient, uint dwKeepAliveInterval); + + /// <summary> + /// 获取通信数据缓冲区大小 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpClient_GetSocketBufferSize(IntPtr pClient); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpClient_GetKeepAliveTime(IntPtr pClient); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpClient_GetKeepAliveInterval(IntPtr pClient); + + /**********************************************************************************/ + /***************************** UDP Client 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpClient_SetMaxDatagramSize(IntPtr pClient, uint dwMaxDatagramSize); + + /// <summary> + /// 获取数据报文最大长度 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpClient_GetMaxDatagramSize(IntPtr pClient); + + /// <summary> + /// 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线 + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwDetectAttempts"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpClient_SetDetectAttempts(IntPtr pClient, uint dwDetectAttempts); + + /// <summary> + /// 设置监测包发送间隔(秒,0 不发送监测包) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwDetectInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpClient_SetDetectInterval(IntPtr pClient, uint dwDetectInterval); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpClient_GetDetectAttempts(IntPtr pClient); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpClient_GetDetectInterval(IntPtr pClient); + + + /**********************************************************************************/ + /****************************** UDP Cast 属性访问方法 ******************************/ + + /// <summary> + /// 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节 + /// </summary> + /// <param name="pCast"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetMaxDatagramSize(IntPtr pCast, uint dwMaxDatagramSize); + + /// <summary> + /// 获取数据报文最大长度 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpCast_GetMaxDatagramSize(IntPtr pCast); + + /// <summary> + /// 获取当前数据报的远程地址信息(通常在 OnReceive 事件中调用) + /// </summary> + /// <param name="pCast"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpCast_GetRemoteAddress(IntPtr pCast, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 设置是否启用地址重用机制(默认:不启用) + /// </summary> + /// <param name="pCast"></param> + /// <param name="bReuseAddress"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetReuseAddress(IntPtr pCast, bool bReuseAddress); + + /// <summary> + /// 检测是否启用地址重用机制 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpCast_IsReuseAddress(IntPtr pCast); + + /// <summary> + /// 设置传播模式(组播或广播) + /// </summary> + /// <param name="pCast"></param> + /// <param name="enCastMode"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetCastMode(IntPtr pCast, CastMode enCastMode); + + /// <summary> + /// 获取传播模式 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern CastMode HP_UdpCast_GetCastMode(IntPtr pCast); + + /// <summary> + /// 设置组播报文的 TTL(0 - 255) + /// </summary> + /// <param name="pCast"></param> + /// <param name="iMCTtl"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetMultiCastTtl(IntPtr pCast, int iMCTtl); + + /// <summary> + /// 获取组播报文的 TTL + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int HP_UdpCast_GetMultiCastTtl(IntPtr pCast); + + /// <summary> + /// 设置是否启用组播环路(TRUE or FALSE) + /// </summary> + /// <param name="pCast"></param> + /// <param name="bMCLoop"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetMultiCastLoop(IntPtr pCast, bool bMCLoop); + + /// <summary> + /// 检测是否启用组播环路 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpCast_IsMultiCastLoop(IntPtr pCast); + + /**************************************************************************/ + /***************************** Agent 操作方法 *****************************/ + + /// <summary> + /// 启动通信组件 + /// 启动通信代理组件,启动完成后可开始连接远程服务器 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="pszBindAddress">监听地址</param> + /// <param name="bAsyncConnect">是否采用异步 Connect</param> + /// <returns>失败,可通过 GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Start(IntPtr pAgent, string pszBindAddress, bool bAsyncConnect); + + /// <summary> + /// 关闭通信组件 + /// 关闭通信组件,关闭完成后断开所有连接并释放所有资源 + /// </summary> + /// <param name="pAgent"></param> + /// <returns>-- 失败,可通过 GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Stop(IntPtr pAgent); + + /// <summary> + /// 连接服务器 + /// 连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="pszBindAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pconnId">传出连接 ID</param> + /// <returns>失败,可通过 SYS_GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Connect(IntPtr pAgent, string pszBindAddress, ushort usPort, ref IntPtr pconnId); + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">传出连接</param> + /// <param name="pExtra">连接附加数据(默认:nullptr)</param> + /// <returns>失败,可通过函数 SYS_GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithExtra(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, IntPtr pExtra); + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">连接 ID(默认:nullptr,不获取连接 ID)</param> + /// <param name="usLocalPort">本地端口(默认:0)</param> + /// <returns>失败,可通过函数 SYS_GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithLocalPort(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, ushort usLocalPort); + + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">连接 ID(默认:nullptr,不获取连接 ID)</param> + /// <param name="lpszLocalAddress">本地地址(默认:nullptr,使用 Start() 方法中绑定的地址)</param> + /// <returns>失败,可通过函数 SYS_GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithLocalAddress(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, string lpszLocalAddress); + + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">连接 ID(默认:nullptr,不获取连接 ID)</param> + /// <param name="pExtra">连接附加数据(默认:nullptr)</param> + /// <param name="usLocalPort">本地端口(默认:0)</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithExtraAndLocalPort(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, IntPtr pExtra, ushort usLocalPort); + + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">连接 ID(默认:nullptr,不获取连接 ID)</param> + /// <param name="pExtra">连接附加数据(默认:nullptr)</param> + /// <param name="usLocalPort">本地端口(默认:0)</param> + /// <param name="lpszLocalAddress">本地地址(默认:nullptr,使用 Start() 方法中绑定的地址)</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithExtraAndLocalAddressPort(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, IntPtr pExtra, ushort usLocalPort, string lpszLocalAddress); + + + /// <summary> + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">发送数据缓冲区</param> + /// <param name="length">发送数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Send(IntPtr pAgent, IntPtr connId, byte[] pBuffer, int length); + + /// <summary> + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">发送数据缓冲区</param> + /// <param name="length">发送数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Send(IntPtr pAgent, IntPtr connId, IntPtr pBuffer, int length); + + /// <summary> + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_SendPart(IntPtr pAgent, IntPtr connId, byte[] pBuffer, int length, int iOffset); + + /// <summary> + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_SendPart(IntPtr pAgent, IntPtr connId, IntPtr pBuffer, int length, int iOffset); + + + /// <summary> + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffers">发送缓冲区数组</param> + /// <param name="iCount">发送缓冲区数目</param> + /// <returns>TRUE.成功,FALSE .失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_SendPackets(IntPtr pAgent, IntPtr connId, WSABUF[] pBuffers, int iCount); + + /// <summary> + /// 名称:暂停/恢复接收 + /// 描述:暂停/恢复某个连接的数据接收工作 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwConnID"></param> + /// <param name="bPause">TRUE - 暂停, FALSE - 恢复</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_PauseReceive(IntPtr pAgent, IntPtr dwConnID, bool bPause); + + /// <summary> + /// 断开某个连接 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Disconnect(IntPtr pAgent, IntPtr connId, bool bForce); + + /// <summary> + /// 断开超过指定时长的连接 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwPeriod">时长(毫秒)</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_DisconnectLongConnections(IntPtr pAgent, uint dwPeriod, bool bForce); + + /// <summary> + /// 断开超过指定时长的静默连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwPeriod">时长(毫秒)</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_DisconnectSilenceConnections(IntPtr pAgent, uint dwPeriod, bool bForce); + + /******************************************************************************/ + /***************************** Agent 操作方法 *****************************/ + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="lpszFileName">文件路径</param> + /// <param name="pHead">头部附加数据</param> + /// <param name="pTail">尾部附加数据</param> + /// <returns>TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_TcpAgent_SendSmallFile(IntPtr pAgent, IntPtr connId, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /******************************************************************************/ + /***************************** Agent 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据发送策略 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="enSendPolicy"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetSendPolicy(IntPtr pAgent, SendPolicy enSendPolicy); + + /// <summary> + /// 获取数据发送策略 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SendPolicy HP_Agent_GetSendPolicy(IntPtr pAgent); + + + /// <summary> + /// 获取 OnSend 事件同步策略 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern OnSendSyncPolicy HP_Agent_GetOnSendSyncPolicy(IntPtr pAgent); + + /// <summary> + /// 设置 OnSend 事件同步策略(默认:OSSP_NONE,不同步 + /// </summary> + /// <param name="pServer"></param> + /// <param name="syncPolicy"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetOnSendSyncPolicy(IntPtr pAgent, OnSendSyncPolicy syncPolicy); + + + /// <summary> + /// 设置连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pExtra">数据</param> + /// <returns>FALSE -- 失败(无效的连接 ID)</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_SetConnectionExtra(IntPtr pAgent, IntPtr connId, IntPtr pExtra); + + /// <summary> + /// 获取连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="pExtra"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetConnectionExtra(IntPtr pAgent, IntPtr connId, ref IntPtr pExtra); + + /// <summary> + /// 检测是否为安全连接(SSL/HTTPS) + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_IsSecure(IntPtr pAgent); + + /// <summary> + /// 检查通信组件是否已启动 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_HasStarted(IntPtr pAgent); + + /// <summary> + /// 查看通信组件当前状态 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ServiceState HP_Agent_GetState(IntPtr pAgent); + + /// <summary> + /// 获取连接数 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetConnectionCount(IntPtr pAgent); + + /// <summary> + /// 获取所有连接的 CONNID + /// </summary> + /// <param name="pServer"></param> + /// <param name="pIDs"></param> + /// <param name="pdwCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetAllConnectionIDs(IntPtr pAgent, IntPtr[] pIDs, ref uint pdwCount); + + /// <summary> + /// 获取某个连接时长(毫秒) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="pdwPeriod"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetConnectPeriod(IntPtr pAgent, IntPtr connId, ref uint pdwPeriod); + + /// <summary> + /// 获取某个连接静默时间(毫秒) + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pdwPeriod"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetSilencePeriod(IntPtr pAgent, IntPtr connId, ref uint pdwPeriod); + + /// <summary> + /// 获取某个连接的本地地址信息 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetLocalAddress(IntPtr pAgent, IntPtr connId, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取某个连接的远程地址信息 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetRemoteAddress(IntPtr pAgent, IntPtr connId, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取某个连接的远程主机信息 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwConnID"></param> + /// <param name="lpszAddress"></param> + /// <param name="piHostLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetRemoteHost(IntPtr pAgent, IntPtr dwConnID, [MarshalAs(UnmanagedType.LPStr)]StringBuilder lpszAddress, ref int piHostLen, ref ushort pusPort); + + + /// <summary> + /// 获取最近一次失败操作的错误代码 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SocketError HP_Agent_GetLastError(IntPtr pAgent); + + /// <summary> + /// 获取最近一次失败操作的错误描述 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Agent_GetLastErrorDesc(IntPtr pAgent); + + /// <summary> + /// 获取连接中未发出数据的长度 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="piPending"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetPendingDataLength(IntPtr pAgent, IntPtr connId, ref int piPending); + + /// <summary> + /// 获取连接的数据接收状态 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwConnID"></param> + /// <param name="pbPaused"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_IsPauseReceive(IntPtr pAgent, IntPtr dwConnID, ref int pbPaused); + + /// <summary> + /// 检测是否有效连接 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwConnID"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_IsConnected(IntPtr pAgent, IntPtr dwConnID); + + + /// <summary> + /// 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeSocketObjLockTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeSocketObjLockTime(IntPtr pAgent, uint dwFreeSocketObjLockTime); + + /// <summary> + /// 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeSocketObjPool"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeSocketObjPool(IntPtr pAgent, uint dwFreeSocketObjPool); + + /// <summary> + /// 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeBufferObjPool"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeBufferObjPool(IntPtr pAgent, uint dwFreeBufferObjPool); + + /// <summary> + /// 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeSocketObjHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeSocketObjHold(IntPtr pAgent, uint dwFreeSocketObjHold); + + /// <summary> + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeBufferObjHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeBufferObjHold(IntPtr pAgent, uint dwFreeBufferObjHold); + + /// <summary> + /// 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwMaxConnectionCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetMaxConnectionCount(IntPtr pAgent, uint dwMaxConnectionCount); + + /// <summary> + /// 设置工作线程数量(通常设置为 2 * CPU + 2) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwWorkerThreadCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetWorkerThreadCount(IntPtr pAgent, uint dwWorkerThreadCount); + + /// <summary> + /// 设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:FALSE) + /// </summary> + /// <param name="pServer"></param> + /// <param name="bMarkSilence"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetMarkSilence(IntPtr pAgent, bool bMarkSilence); + + /// <summary> + /// 获取 Socket 缓存对象锁定时间 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeSocketObjLockTime(IntPtr pAgent); + + /// <summary> + /// 获取 Socket 缓存池大小 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeSocketObjPool(IntPtr pAgent); + + /// <summary> + /// 获取内存块缓存池大小 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeBufferObjPool(IntPtr pAgent); + + /// <summary> + /// 获取 Socket 缓存池回收阀值 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeSocketObjHold(IntPtr pAgent); + + /// <summary> + /// 获取内存块缓存池回收阀值 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeBufferObjHold(IntPtr pAgent); + + /// <summary> + /// 获取最大连接数 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetMaxConnectionCount(IntPtr pAgent); + + /// <summary> + /// 获取工作线程数量 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetWorkerThreadCount(IntPtr pAgent); + + /// <summary> + /// 检测是否标记静默时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_IsMarkSilence(IntPtr pAgent); + + /**********************************************************************************/ + /***************************** TCP Agent 属性访问方法 *****************************/ + + /// <summary> + /// 置是否启用地址重用机制(默认:不启用) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="bReuseAddress"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpAgent_SetReuseAddress(IntPtr pAgent, bool bReuseAddress); + + /// <summary> + /// 检测是否启用地址重用机制 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_TcpAgent_IsReuseAddress(IntPtr pAgent); + + /// <summary> + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwSocketBufferSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpAgent_SetSocketBufferSize(IntPtr pAgent, uint dwSocketBufferSize); + + /// <summary> + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwKeepAliveTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpAgent_SetKeepAliveTime(IntPtr pAgent, uint dwKeepAliveTime); + + /// <summary> + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwKeepAliveInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpAgent_SetKeepAliveInterval(IntPtr pAgent, uint dwKeepAliveInterval); + + /// <summary> + /// 获取通信数据缓冲区大小 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpAgent_GetSocketBufferSize(IntPtr pAgent); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpAgent_GetKeepAliveTime(IntPtr pAgent); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpAgent_GetKeepAliveInterval(IntPtr pAgent); + + /***************************************************************************************/ + /***************************** TCP Pull Server 组件操作方法 *****************************/ + + /// <summary> + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullServer_Fetch(IntPtr pServer, IntPtr connId, IntPtr pBuffer, int length); + + /// <summary> + /// 窥探数据(不会移除缓冲区数据) + /// 描述:用户通过该方法从 Socket 组件中窥探数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">窥探缓冲区</param> + /// <param name="length">窥探数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullServer_Peek(IntPtr pServer, IntPtr connId, IntPtr pBuffer, int length); + + /***************************************************************************************/ + /***************************** TCP Pull Server 属性访问方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pull Client 组件操作方法 *****************************/ + + /// <summary> + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullClient_Fetch(IntPtr pClient, IntPtr pBuffer, int length); + + /// <summary> + /// 名称:窥探数据(不会移除缓冲区数据) + /// 描述:用户通过该方法从 Socket 组件中窥探数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullClient_Peek(IntPtr pClient, IntPtr pBuffer, int length); + + /***************************************************************************************/ + /***************************** TCP Pull Client 属性访问方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pull Agent 组件操作方法 *****************************/ + + /// <summary> + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullAgent_Fetch(IntPtr pAgent, IntPtr connId, IntPtr pBuffer, int length); + + /// <summary> + /// 名称:窥探数据(不会移除缓冲区数据) + /// 描述:用户通过该方法从 Socket 组件中窥探数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullAgent_Peek(IntPtr pAgent, IntPtr connId, IntPtr pBuffer, int length); + + /***************************************************************************************/ + /***************************** TCP Pull Agent 属性访问方法 *****************************/ + + /***************************************************************************************/ + + /***************************************************************************************/ + /***************************** TCP Pack Server 组件操作方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pack Server 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据包最大长度(有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxPackSize">有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackServer_SetMaxPackSize(IntPtr pServer, uint dwMaxPackSize); + + /// <summary> + /// 设置包头标识(有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0) + /// </summary> + /// <param name="pServer"></param> + /// <param name="usPackHeaderFlag">有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackServer_SetPackHeaderFlag(IntPtr pServer, ushort usPackHeaderFlag); + + /// <summary> + /// 获取数据包最大长度 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpPackServer_GetMaxPackSize(IntPtr pServer); + + /// <summary> + /// 获取包头标识 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ushort HP_TcpPackServer_GetPackHeaderFlag(IntPtr pServer); + /***************************************************************************************/ + /***************************** TCP Pack Agent 组件操作方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pack Agent 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据包最大长度(有效数据包最大长度不能超过 524287/0x7FFFF 字节,默认:262144/0x40000) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxPackSize">有效数据包最大长度不能超过 524287/0x7FFFF 字节,默认:262144/0x40000</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackAgent_SetMaxPackSize(IntPtr pAgent, uint dwMaxPackSize); + + /// <summary> + /// 设置包头标识(有效包头标识取值范围 0 ~ 8191/0x1FFF,当包头标识为 0 时不校验包头,默认:0) + /// </summary> + /// <param name="pServer"></param> + /// <param name="usPackHeaderFlag">有效包头标识取值范围 0 ~ 8191/0x1FFF,当包头标识为 0 时不校验包头,默认:0</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackAgent_SetPackHeaderFlag(IntPtr pAgent, ushort usPackHeaderFlag); + + /// <summary> + /// 获取数据包最大长度 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpPackAgent_GetMaxPackSize(IntPtr pAgent); + + /// <summary> + /// 获取包头标识 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ushort HP_TcpPackAgent_GetPackHeaderFlag(IntPtr pAgent); + /***************************************************************************************/ + /***************************** TCP Pack Client 组件操作方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pack Client 属性访问方法 *****************************/ + /// <summary> + /// 设置数据包最大长度(有效数据包最大长度不能超过 524287/0x7FFFF 字节,默认:262144/0x40000) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxPackSize">有效数据包最大长度不能超过 524287/0x7FFFF 字节,默认:262144/0x40000</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackClient_SetMaxPackSize(IntPtr pClient, uint dwMaxPackSize); + + /// <summary> + /// 设置包头标识(有效包头标识取值范围 0 ~ 8191/0x1FFF,当包头标识为 0 时不校验包头,默认:0) + /// </summary> + /// <param name="pServer"></param> + /// <param name="usPackHeaderFlag">有效包头标识取值范围 0 ~ 8191/0x1FFF,当包头标识为 0 时不校验包头,默认:0</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackClient_SetPackHeaderFlag(IntPtr pClient, ushort usPackHeaderFlag); + + /// <summary> + /// 获取数据包最大长度 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpPackClient_GetMaxPackSize(IntPtr pClient); + + /// <summary> + /// 获取包头标识 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ushort HP_TcpPackClient_GetPackHeaderFlag(IntPtr pClient); + /***************************************************************************************/ + /*************************************** 其它方法 ***************************************/ + + /// <summary> + /// 获取 HPSocket 版本号(4 个字节分别为:主版本号,子版本号,修正版本号,构建编号) + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_GetHPSocketVersion(); + + /// <summary> + /// 获取版本号 + /// </summary> + /// <returns></returns> + public static string GetHPSocketVersion() + { + /* + var ver = BitConverter.GetBytes(HP_GetHPSocketVersion()); + var major = ver[3]; + var minor = ver[2]; + var revision = ver[1]; + var build = ver[0];*/ + + uint ver = HP_GetHPSocketVersion(); + var major = ver >> 24; + var minor = (ver << 8) >> 24; + var revision = (ver << 16) >> 24; + var build = (ver << 24) >> 24; + + return string.Format("{0}.{1}.{2}_{3}", major, minor, revision, build); + } + + /// <summary> + /// 获取错误描述文本 + /// </summary> + /// <param name="enCode"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_GetSocketErrorDesc(SocketError enCode); + + /// <summary> + /// 调用系统的 ::GetLastError() 方法获取系统错误代码 + /// </summary> + /// <returns></returns> + public static int SYS_GetLastError() + { + return Marshal.GetLastWin32Error(); + } + + /// <summary> + /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_WSAGetLastError(); + + /// <summary> + /// 调用系统的 setsockopt() + /// </summary> + /// <param name="sock"></param> + /// <param name="level"></param> + /// <param name="name"></param> + /// <param name="val"></param> + /// <param name="len"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len); + + /// <summary> + /// 调用系统的 getsockopt() + /// </summary> + /// <param name="sock"></param> + /// <param name="level"></param> + /// <param name="name"></param> + /// <param name="val"></param> + /// <param name="len"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_GetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len); + + /// <summary> + /// 调用系统的 ioctlsocket() + /// </summary> + /// <param name="sock"></param> + /// <param name="cmd"></param> + /// <param name="arg"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_IoctlSocket(IntPtr sock, long cmd, IntPtr arg); + + /// <summary> + /// 调用系统的 ::WSAIoctl() + /// </summary> + /// <param name="sock"></param> + /// <param name="dwIoControlCode"></param> + /// <param name="lpvInBuffer"></param> + /// <param name="cbInBuffer"></param> + /// <param name="lpvOutBuffer"></param> + /// <param name="cbOutBuffer"></param> + /// <param name="lpcbBytesReturned"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, + IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned); + + /// <summary> + /// 设置 socket 选项:IPPROTO_TCP -> TCP_NODELAY + /// </summary> + /// <param name="sock"></param> + /// <param name="bNoDelay"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_NoDelay(IntPtr sock, bool bNoDelay); + + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_DONTLINGER + /// </summary> + /// <param name="sock"></param> + /// <param name="bDont"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_DontLinger(IntPtr sock, bool bDont); + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_LINGER + /// </summary> + /// <param name="sock"></param> + /// <param name="l_onoff"></param> + /// <param name="l_linger"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_Linger(IntPtr sock, ushort l_onoff, ushort l_linger); + + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_RCVBUF + /// </summary> + /// <param name="sock"></param> + /// <param name="size"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_RecvBuffSize(IntPtr sock, int size); + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_SNDBUF + /// </summary> + /// <param name="sock"></param> + /// <param name="size"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_SendBuffSize(IntPtr sock, int size); + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_REUSEADDR + /// </summary> + /// <param name="sock"></param> + /// <param name="bReuse"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_ReuseAddress(IntPtr sock, bool bReuse); + + /// <summary> + /// 获取 SOCKET 本地地址信息 + /// </summary> + /// <param name="pSocket"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen">传入传出值,大小最好在222.222.222.222的长度以上</param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_GetSocketLocalAddress(IntPtr pSocket, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取 SOCKET 远程地址信息 + /// </summary> + /// <param name="pSocket"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen">传入传出值,大小最好在222.222.222.222的长度以上</param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_GetSocketRemoteAddress(IntPtr pSocket, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + + /// <summary> + /// 枚举主机 IP 地址 + /// 不要用,未测试 + /// 不要用,未测试 + /// 不要用,未测试 + /// </summary> + /// <param name="lpszHost"></param> + /// <param name="enType"></param> + /// <param name="lpppIPAddr"></param> + /// <param name="piIPAddrCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_EnumHostIPAddresses(string lpszHost, IPAddrType enType, ref IntPtr lpppIPAddr, ref int piIPAddrCount); + + + /// <summary> + /// 释放 HP_LPTIPAddr + /// </summary> + /// <param name="lppIPAddr"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_FreeHostIPAddresses(IntPtr lppIPAddr); + + + /* + * 已删除 + /// <summary> + /// 获取 IPv4 地址 + /// </summary> + /// <param name="lpszAddress"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint SYS_GetIPv4InAddr(string lpszAddress); + */ + /// <summary> + /// 检查字符串是否符合 IP 地址格式 + /// </summary> + /// <param name="lpszAddress"></param> + /// <param name="penType"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_IsIPAddress(string lpszAddress, ref IPAddrType penType); + + /// <summary> + /// 通过主机名获取 IP 地址 + /// </summary> + /// <param name="lpszHost"></param> + /// <param name="lpszIP"></param> + /// <param name="piIPLenth"></param> + /// <param name="penType"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_GetIPAddress(string lpszHost, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszIP, ref int piIPLenth, ref IPAddrType penType); + + /* + * 已删除 + /// <summary> + /// 通过主机名获取最优的 IP 地址 + /// </summary> + /// <param name="lpszHost"></param> + /// <param name="pulAddr"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_GetOptimalIPByHostName(string lpszHost, ref uint pulAddr); + */ + + /// <summary> + /// 64 位网络字节序转主机字节序 + /// </summary> + /// <param name="value"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ulong SYS_NToH64(ulong value); + + /// <summary> + /// 64 位主机字节序转网络字节序 + /// </summary> + /// <param name="value"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ulong SYS_HToN64(ulong value); + + + /// <summary> + /// 分配内存 + /// </summary> + /// <param name="value"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr SYS_Malloc(int value); + + /// <summary> + /// 重新分配内存 + /// </summary> + /// <param name="p"></param> + /// <param name="value"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr SYS_Realloc(IntPtr p, int value); + + /// <summary> + /// 释放内存 + /// </summary> + /// <param name="p"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void SYS_Free(IntPtr p); + + + + + + /// <summary> + /// 创建 HP_UdpArqServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpArqServer(IntPtr pListener); + + /// <summary> + /// 创建 HP_UdpArqClient 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpArqClient(IntPtr pListener); + + /// <summary> + /// 销毁 HP_UdpArqServer 对象 + /// </summary> + /// <param name="pServer"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpArqServer(IntPtr pServer); + + /// <summary> + /// 销毁 HP_UdpArqClient 对象 + /// </summary> + /// <param name="pClient"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpArqClient(IntPtr pClient); + + /// <summary> + /// 创建 HP_UdpArqServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpArqServerListener(); + + /// <summary> + /// 创建 HP_UdpArqClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpArqClientListener(); + + /// <summary> + /// 销毁 HP_UdpArqServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpArqServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 HP_UdpArqClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpArqClientListener(IntPtr pListener); + + /**********************************************************************************/ + /*************************** UDP ARQ Server 属性访问方法 ***************************/ + + + /// <summary> + /// 设置是否开启 nodelay 模式(默认:FALSE,不开启) + /// </summary> + /// <param name="pServer"></param> + /// <param name="bNoDelay"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetNoDelay(IntPtr pServer, bool bNoDelay); + + /// <summary> + /// 设置是否关闭拥塞控制(默认:FALSE,不关闭) + /// </summary> + /// <param name="pServer"></param> + /// <param name="bTurnOff"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetTurnoffCongestCtrl(IntPtr pServer, bool bTurnOff); + + /// <summary> + /// 设置数据刷新间隔(毫秒,默认:20) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFlushInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetFlushInterval(IntPtr pServer, uint dwFlushInterval); + + /// <summary> + /// 设置快速重传 ACK 跨越次数(默认:0,关闭快速重传) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwResendByAcks"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetResendByAcks(IntPtr pServer, uint dwResendByAcks); + + /// <summary> + /// 设置发送窗口大小(数据包数量,默认:128) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwSendWndSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetSendWndSize(IntPtr pServer, uint dwSendWndSize); + + /// <summary> + /// 设置接收窗口大小(数据包数量,默认:512) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwRecvWndSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetRecvWndSize(IntPtr pServer, uint dwRecvWndSize); + + /// <summary> + /// 设置最小重传超时时间(毫秒,默认:30) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMinRto"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetMinRto(IntPtr pServer, uint dwMinRto); + + /// <summary> + /// 设置最大传输单元(默认:0,与 SetMaxDatagramSize() 一致) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxTransUnit"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetMaxTransUnit(IntPtr pServer, uint dwMaxTransUnit); + + /// <summary> + /// 设置最大数据包大小(默认:4096) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxMessageSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetMaxMessageSize(IntPtr pServer, uint dwMaxMessageSize); + + /// <summary> + /// 设置握手超时时间(毫秒,默认:5000) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwHandShakeTimeout"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetHandShakeTimeout(IntPtr pServer, uint dwHandShakeTimeout); + + + /// <summary> + /// 检测是否开启 nodelay 模式 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqServer_IsNoDelay(IntPtr pServer); + + /// <summary> + /// 检测是否关闭拥塞控制 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqServer_IsTurnoffCongestCtrl(IntPtr pServer); + + /// <summary> + /// 获取数据刷新间隔 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetFlushInterval(IntPtr pServer); + + /// <summary> + /// 获取快速重传 ACK 跨越次数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetResendByAcks(IntPtr pServer); + + /// <summary> + /// 获取发送窗口大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetSendWndSize(IntPtr pServer); + + /// <summary> + /// 获取接收窗口大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetRecvWndSize(IntPtr pServer); + + /// <summary> + /// 获取最小重传超时时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetMinRto(IntPtr pServer); + + /// <summary> + /// 获取最大传输单元 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetMaxTransUnit(IntPtr pServer); + + /// <summary> + /// 获取最大数据包大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetMaxMessageSize(IntPtr pServer); + + /// <summary> + /// 获取握手超时时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetHandShakeTimeout(IntPtr pServer); + + + /// <summary> + /// 获取等待发送包数量 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwConnId"></param> + /// <param name="piCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqServer_GetWaitingSendMessageCount(IntPtr pServer, IntPtr dwConnId, ref int piCount); + + /**********************************************************************************/ + /*************************** UDP ARQ Client 属性访问方法 ***************************/ + + + /// <summary> + /// 设置是否开启 nodelay 模式(默认:FALSE,不开启) + /// </summary> + /// <param name="pClient"></param> + /// <param name="bNoDelay"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetNoDelay(IntPtr pClient, bool bNoDelay); + + /// <summary> + /// 设置是否关闭拥塞控制(默认:FALSE,不关闭) + /// </summary> + /// <param name="pClient"></param> + /// <param name="bTurnOff"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetTurnoffCongestCtrl(IntPtr pClient, bool bTurnOff); + + /// <summary> + /// 设置数据刷新间隔(毫秒,默认:20) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwFlushInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetFlushInterval(IntPtr pClient, uint dwFlushInterval); + + /// <summary> + /// 设置快速重传 ACK 跨越次数(默认:0,关闭快速重传) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwResendByAcks"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetResendByAcks(IntPtr pClient, uint dwResendByAcks); + + /// <summary> + /// 设置发送窗口大小(数据包数量,默认:128) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwSendWndSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetSendWndSize(IntPtr pClient, uint dwSendWndSize); + + /// <summary> + /// 设置接收窗口大小(数据包数量,默认:512) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwRecvWndSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetRecvWndSize(IntPtr pClient, uint dwRecvWndSize); + + /// <summary> + /// 设置最小重传超时时间(毫秒,默认:30) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwMinRto"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetMinRto(IntPtr pClient, uint dwMinRto); + + /// <summary> + /// 设置最大传输单元(默认:0,与 SetMaxDatagramSize() 一致) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwMaxTransUnit"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetMaxTransUnit(IntPtr pClient, uint dwMaxTransUnit); + + /// <summary> + /// 设置最大数据包大小(默认:4096) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwMaxMessageSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetMaxMessageSize(IntPtr pClient, uint dwMaxMessageSize); + + /// <summary> + /// 设置握手超时时间(毫秒,默认:5000) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwHandShakeTimeout"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetHandShakeTimeout(IntPtr pClient, uint dwHandShakeTimeout); + + + /// <summary> + /// 检测是否开启 nodelay 模式 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqClient_IsNoDelay(IntPtr pClient); + + /// <summary> + /// 检测是否关闭拥塞控制 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqClient_IsTurnoffCongestCtrl(IntPtr pClient); + + /// <summary> + /// 获取数据刷新间隔 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetFlushInterval(IntPtr pClient); + + /// <summary> + /// 获取快速重传 ACK 跨越次数 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetResendByAcks(IntPtr pClient); + + /// <summary> + /// 获取发送窗口大小 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetSendWndSize(IntPtr pClient); + + /// <summary> + /// 获取接收窗口大小 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetRecvWndSize(IntPtr pClient); + + /// <summary> + /// 获取最小重传超时时间 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetMinRto(IntPtr pClient); + + /// <summary> + /// 获取最大传输单元 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetMaxTransUnit(IntPtr pClient); + + /// <summary> + /// 获取最大数据包大小 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetMaxMessageSize(IntPtr pClient); + + /// <summary> + /// 获取握手超时时间 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetHandShakeTimeout(IntPtr pClient); + + + /// <summary> + /// 获取等待发送包数量 + /// </summary> + /// <param name="pClient"></param> + /// <param name="piCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqClient_GetWaitingSendMessageCount(IntPtr pClient, ref int piCount); + + +} diff --git a/PCRobot/HPSocketCS/TcpPackServer.cs b/PCRobot/HPSocketCS/TcpPackServer.cs new file mode 100644 index 0000000..ed1fe4c --- /dev/null +++ b/PCRobot/HPSocketCS/TcpPackServer.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HPSocketCS +{ + public class TcpPackServer<T> : TcpPackServer + { + public new T GetExtra(IntPtr connId) + { + return base.GetExtra<T>(connId); + } + + public bool SetExtra(IntPtr connId, T obj) + { + return base.SetExtra(connId, obj); + } + } + + public class TcpPackServer : TcpServer + { + + /// <summary> + /// 创建socket监听&服务组件 + /// </summary> + /// <returns></returns> + protected override bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pServer != IntPtr.Zero) + { + return false; + } + + pListener = Sdk.Create_HP_TcpPackServerListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + + pServer = Sdk.Create_HP_TcpPackServer(pListener); + if (pServer == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// <summary> + /// 终止服务并释放资源 + /// </summary> + public override void Destroy() + { + Stop(); + + if (pServer != IntPtr.Zero) + { + Sdk.Destroy_HP_TcpPackServer(pServer); + pServer = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + Sdk.Destroy_HP_TcpPackServerListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + /// <summary> + /// 读取或设置数据包最大长度 + /// 有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000 + /// </summary> + public uint MaxPackSize + { + get + { + return Sdk.HP_TcpPackServer_GetMaxPackSize(pServer); + } + set + { + Sdk.HP_TcpPackServer_SetMaxPackSize(pServer, value ); + } + } + + /// <summary> + /// 读取或设置包头标识 + /// 有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0 + /// </summary> + public ushort PackHeaderFlag + { + get + { + return Sdk.HP_TcpPackServer_GetPackHeaderFlag(pServer); + } + set + { + Sdk.HP_TcpPackServer_SetPackHeaderFlag(pServer, value); + } + } + + + } +} diff --git a/PCRobot/HPSocketCS/TcpServer.cs b/PCRobot/HPSocketCS/TcpServer.cs new file mode 100644 index 0000000..79f2b3f --- /dev/null +++ b/PCRobot/HPSocketCS/TcpServer.cs @@ -0,0 +1,1147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; + +namespace HPSocketCS +{ + + public class TcpServer<T> : TcpServer + { + public new T GetExtra(IntPtr connId) + { + return base.GetExtra<T>(connId); + } + + public bool SetExtra(IntPtr connId, T obj) + { + return base.SetExtra(connId, obj); + } + } + + public class TcpServer : ConnectionExtra, IServer + { + protected IntPtr pServer = IntPtr.Zero; + protected IntPtr pListener = IntPtr.Zero; + + /// <summary> + /// 服务器ip + /// </summary> + public string IpAddress { get; set; } + + /// <summary> + /// 服务器端口 + /// </summary> + public ushort Port { get; set; } + + /// <summary> + /// 连接到达事件 + /// </summary> + public event ServerEvent.OnAcceptEventHandler OnAccept; + /// <summary> + /// 数据包发送事件 + /// </summary> + public event ServerEvent.OnSendEventHandler OnSend; + /// <summary> + /// 准备监听了事件 + /// </summary> + public event ServerEvent.OnPrepareListenEventHandler OnPrepareListen; + /// <summary> + /// 数据到达事件 + /// </summary> + public event ServerEvent.OnReceiveEventHandler OnReceive; + /// <summary> + /// 数据到达事件(指针数据) + /// </summary> + public event ServerEvent.OnPointerDataReceiveEventHandler OnPointerDataReceive; + /// <summary> + /// 连接关闭事件 + /// </summary> + public event ServerEvent.OnCloseEventHandler OnClose; + /// <summary> + /// 服务器关闭事件 + /// </summary> + public event ServerEvent.OnShutdownEventHandler OnShutdown; + /// <summary> + /// 握手成功事件 + /// </summary> + public event ServerEvent.OnHandShakeEventHandler OnHandShake; + + protected bool IsCreate = false; + + + public TcpServer() + { + CreateListener(); + } + + ~TcpServer() + { + Destroy(); + } + + /// <summary> + /// 创建socket监听&服务组件 + /// </summary> + /// <returns></returns> + protected virtual bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pServer != IntPtr.Zero) + { + return false; + } + + pListener = Sdk.Create_HP_TcpServerListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + pServer = Sdk.Create_HP_TcpServer(pListener); + if (pServer == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// <summary> + /// 终止服务并释放资源 + /// </summary> + public virtual void Destroy() + { + Stop(); + + if (pServer != IntPtr.Zero) + { + Sdk.Destroy_HP_TcpServer(pServer); + pServer = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + Sdk.Destroy_HP_TcpServerListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + + /// <summary> + /// 启动服务 + /// </summary> + /// <returns></returns> + public bool Start() + { + if (IsCreate == false) + { + return false; + } + if (pServer == IntPtr.Zero) + { + return false; + } + + SetCallback(); + + return Sdk.HP_Server_Start(pServer, IpAddress, Port); + } + + /// <summary> + /// 停止服务 + /// </summary> + /// <returns></returns> + public bool Stop() + { + if (pServer == IntPtr.Zero) + { + return false; + } + + return Sdk.HP_Server_Stop(pServer); + } + + /// <summary> + /// 发送数据 + /// </summary> + /// <param name="connId"></param> + /// <param name="bytes"></param> + /// <param name="size"></param> + /// <returns></returns> + public bool Send(IntPtr connId, byte[] bytes, int size) + { + return Sdk.HP_Server_Send(pServer, connId, bytes, size); + } + + /// <summary> + /// 发送数据 + /// </summary> + /// <param name="connId"></param> + /// <param name="bufferPtr"></param> + /// <param name="size"></param> + /// <returns></returns> + public bool Send(IntPtr connId, IntPtr bufferPtr, int size) + { + return Sdk.HP_Server_Send(pServer, connId, bufferPtr, size); + } + + + /// <summary> + /// 发送数据 + /// </summary> + /// <param name="connId"></param> + /// <param name="bytes"></param> + /// <param name="offset">针对bytes的偏移</param> + /// <param name="size">发多大</param> + /// <returns></returns> + public bool Send(IntPtr connId, byte[] bytes, int offset, int size) + { + return Sdk.HP_Server_SendPart(pServer, connId, bytes, size, offset); + } + + /// <summary> + /// 发送数据 + /// </summary> + /// <param name="connId"></param> + /// <param name="bufferPtr"></param> + /// <param name="offset">针对bufferPtr的偏移</param> + /// <param name="size">发多大</param> + /// <returns></returns> + public bool Send(IntPtr connId, IntPtr bufferPtr, int offset, int size) + { + return Sdk.HP_Server_SendPart(pServer, connId, bufferPtr, size, offset); + } + + + /// <summary> + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// </summary> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffers">发送缓冲区数组</param> + /// <param name="count">发送缓冲区数目</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendPackets(IntPtr connId, WSABUF[] pBuffers, int count) + { + return Sdk.HP_Server_SendPackets(pServer, connId, pBuffers, count); + } + + /// <summary> + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// </summary> + /// <param name="connId">连接 ID</param> + /// <param name="objects">发送缓冲区数组</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendPackets<T>(IntPtr connId, T[] objects) + { + bool ret = false; + + WSABUF[] buffer = new WSABUF[objects.Length]; + IntPtr[] ptrs = new IntPtr[buffer.Length]; + try + { + + for (int i = 0; i < objects.Length; i++) + { + buffer[i].Length = Marshal.SizeOf(typeof(T)); + + ptrs[i] = Marshal.AllocHGlobal(buffer[i].Length); + Marshal.StructureToPtr(objects[i], ptrs[i], true); + + buffer[i].Buffer = ptrs[i]; + } + ret = SendPackets(connId, buffer, buffer.Length); + } + catch (Exception ex) + { + throw ex; + } + finally + { + foreach (var ptr in ptrs) + { + if (ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + } + } + } + + return ret; + } + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="connId"></param> + /// <param name="filePath">文件路径</param> + /// <param name="head">头部附加数据</param> + /// <param name="tail">尾部附加数据</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendSmallFile(IntPtr connId, string filePath, ref WSABUF head, ref WSABUF tail) + { + return Sdk.HP_TcpServer_SendSmallFile(pServer, connId, filePath, ref head, ref tail); + } + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="connId"></param> + /// <param name="filePath">文件路径</param> + /// <param name="head">头部附加数据,可以为null</param> + /// <param name="tail">尾部附加数据,可以为null</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendSmallFile(IntPtr connId, string filePath, byte[] head, byte[] tail) + { + IntPtr pHead = IntPtr.Zero; + IntPtr pTail = IntPtr.Zero; + WSABUF wsaHead = new WSABUF() { Length = 0, Buffer = pHead }; + WSABUF wsatail = new WSABUF() { Length = 0, Buffer = pTail }; + if (head != null) + { + wsaHead.Length = head.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(head, 0); + } + + if (tail != null) + { + wsaHead.Length = tail.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(tail, 0); + } + + return SendSmallFile(connId, filePath, ref wsaHead, ref wsatail); + } + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="connId"></param> + /// <param name="filePath">文件路径</param> + /// <param name="head">头部附加数据,可以为null</param> + /// <param name="tail">尾部附加数据,可以为null</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendSmallFile<T1, T2>(IntPtr connId, string filePath, T1 head, T2 tail) + { + + byte[] headBuffer = null; + if (head != null) + { + headBuffer = StructureToByte<T1>(head); + } + + byte[] tailBuffer = null; + if (tail != null) + { + tailBuffer = StructureToByte<T2>(tail); + } + return SendSmallFile(connId, filePath, headBuffer, tailBuffer); + } + + /// <summary> + /// 断开与某个客户的连接 + /// </summary> + /// <param name="connId"></param> + /// <param name="force">是否强制断开</param> + /// <returns></returns> + public bool Disconnect(IntPtr connId, bool force = true) + { + return Sdk.HP_Server_Disconnect(pServer, connId, force); + } + + /// <summary> + /// 断开超过指定时间的连接 + /// </summary> + /// <param name="period">毫秒</param> + /// <param name="force">强制</param> + /// <returns></returns> + public bool DisconnectLongConnections(uint period, bool force = true) + { + return Sdk.HP_Server_DisconnectLongConnections(pServer, period, force); + } + + + /// <summary> + /// 暂停接收 + /// </summary> + /// <param name="connId"></param> + /// <returns></returns> + public bool PauseReceive(IntPtr connId) + { + return Sdk.HP_Server_PauseReceive(pServer, connId, true); + } + + /// <summary> + /// 唤醒接收 + /// </summary> + /// <param name="connId"></param> + /// <returns></returns> + public bool ResumeReceive(IntPtr connId) + { + return Sdk.HP_Server_PauseReceive(pServer, connId, false); + } + + /// <summary> + /// 获取连接的接收状态 + /// </summary> + /// <param name="connId"></param> + /// <returns></returns> + public ReceiveState GetReceiveState(IntPtr connId) + { + int state = -1; + + if (Sdk.HP_Server_IsPauseReceive(pServer, connId, ref state)) + { + return (ReceiveState)state; + } + return ReceiveState.Unknown; + } + + /// <summary> + /// 断开超过指定时长的静默连接 + /// </summary> + /// <param name="period">毫秒</param> + /// <param name="force">强制</param> + /// <returns></returns> + public bool DisconnectSilenceConnections(uint period, bool force = true) + { + return Sdk.HP_Server_DisconnectSilenceConnections(pServer, period, force); + } + + /// <summary> + /// 获取某个连接的本地地址信息 + /// </summary> + /// <param name="connId"></param> + /// <param name="ip"></param> + /// <param name="port"></param> + /// <returns></returns> + public bool GetLocalAddress(IntPtr connId, ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = Sdk.HP_Server_GetLocalAddress(pServer, connId, sb, ref ipLength, ref port) && ipLength > 0; + if (ret == true) + { + ip = sb.ToString(); + } + + return ret; + } + + /// <summary> + /// 获取某个连接的远程地址信息 + /// </summary> + /// <param name="connId"></param> + /// <param name="ip"></param> + /// <param name="port"></param> + /// <returns></returns> + public bool GetRemoteAddress(IntPtr connId, ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = Sdk.HP_Server_GetRemoteAddress(pServer, connId, sb, ref ipLength, ref port) && ipLength > 0; + if (ret == true) + { + ip = sb.ToString(); + } + + return ret; + } + + /// <summary> + /// 获取连接中未发出数据的长度 + /// </summary> + /// <param name="connId"></param> + /// <param name="length"></param> + /// <returns></returns> + public bool GetPendingDataLength(IntPtr connId, ref int length) + { + return Sdk.HP_Server_GetPendingDataLength(pServer, connId, ref length); + } + + // 是否启动 + public bool IsStarted + { + get + { + if (pServer == IntPtr.Zero) + { + return false; + } + return Sdk.HP_Server_HasStarted(pServer); + } + } + + /// <summary> + /// 状态 + /// </summary> + public ServiceState State + { + get + { + return Sdk.HP_Server_GetState(pServer); + } + + } + + /// <summary> + /// 连接数 + /// </summary> + public uint ConnectionCount + { + get + { + return Sdk.HP_Server_GetConnectionCount(pServer); + } + + } + + /// <summary> + /// 检测是否为安全连接(SSL/HTTPS) + /// </summary> + public bool IsSecure + { + get + { + return Sdk.HP_Server_IsSecure(pServer); + } + } + + /// <summary> + /// 获取所有连接,未获取到连接返回null + /// </summary> + /// <returns></returns> + public IntPtr[] GetAllConnectionIDs() + { + IntPtr[] arr = null; + do + { + uint count = ConnectionCount; + if (count == 0) + { + break; + } + arr = new IntPtr[count]; + if (Sdk.HP_Server_GetAllConnectionIDs(pServer, arr, ref count)) + { + if (arr.Length > count) + { + IntPtr[] newArr = new IntPtr[count]; + Array.Copy(arr, newArr, count); + arr = newArr; + } + break; + } + } while (true); + + return arr; + } + + /// <summary> + /// 获取监听socket的地址信息 + /// </summary> + /// <param name="ip"></param> + /// <param name="port"></param> + /// <returns></returns> + public bool GetListenAddress(ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = Sdk.HP_Server_GetListenAddress(pServer, sb, ref ipLength, ref port); + if (ret == true) + { + ip = sb.ToString(); + } + return ret; + } + + + /// <summary> + /// 获取指定连接的连接时长(毫秒) + /// </summary> + /// <param name="connId"></param> + /// <param name="period"></param> + /// <returns></returns> + public bool GetConnectPeriod(IntPtr connId, ref uint period) + { + return Sdk.HP_Server_GetConnectPeriod(pServer, connId, ref period); + } + + /// <summary> + /// 获取某个连接静默时间(毫秒) + /// </summary> + /// <param name="connId"></param> + /// <param name="period"></param> + /// <returns></returns> + public bool GetSilencePeriod(IntPtr connId, ref uint period) + { + return Sdk.HP_Server_GetSilencePeriod(pServer, connId, ref period); + } + + /////////////////////////////////////////////////////////////////////////////////////// + + /// <summary> + /// 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大) + /// </summary> + public uint MaxConnectionCount + { + get + { + return Sdk.HP_Server_GetMaxConnectionCount(pServer); + } + set + { + Sdk.HP_Server_SetMaxConnectionCount(pServer, value); + } + } + + /// <summary> + /// 读取或设置工作线程数量(通常设置为 2 * CPU + 2) + /// </summary> + public uint WorkerThreadCount + { + get + { + return Sdk.HP_Server_GetWorkerThreadCount(pServer); + } + set + { + Sdk.HP_Server_SetWorkerThreadCount(pServer, value); + } + } + + /// <summary> + /// 读取或设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多) + /// </summary> + public uint AcceptSocketCount + { + get + { + return Sdk.HP_TcpServer_GetAcceptSocketCount(pServer); + } + set + { + Sdk.HP_TcpServer_SetAcceptSocketCount(pServer, value); + } + } + + /// <summary> + /// 读取或设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// </summary> + public uint SocketBufferSize + { + get + { + return Sdk.HP_TcpServer_GetSocketBufferSize(pServer); + } + set + { + Sdk.HP_TcpServer_SetSocketBufferSize(pServer, value); + } + } + + /// <summary> + /// 读取或设置监听 Socket 的等候队列大小(根据并发连接数量调整设置) + /// </summary> + public uint SocketListenQueue + { + get + { + return Sdk.HP_TcpServer_GetSocketListenQueue(pServer); + } + set + { + Sdk.HP_TcpServer_SetSocketListenQueue(pServer, value); + } + } + + /// <summary> + /// 读取或设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// </summary> + public uint FreeSocketObjLockTime + { + get + { + return Sdk.HP_Server_GetFreeSocketObjLockTime(pServer); + } + set + { + Sdk.HP_Server_SetFreeSocketObjLockTime(pServer, value); + } + } + + /// <summary> + /// 读取或设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// </summary> + public uint FreeSocketObjPool + { + get + { + return Sdk.HP_Server_GetFreeSocketObjPool(pServer); + } + set + { + Sdk.HP_Server_SetFreeSocketObjPool(pServer, value); + } + } + + /// <summary> + /// 读取或设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// </summary> + public uint FreeBufferObjPool + { + get + { + return Sdk.HP_Server_GetFreeBufferObjPool(pServer); + } + set + { + Sdk.HP_Server_SetFreeBufferObjPool(pServer, value); + } + } + + /// <summary> + /// 读取或设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// </summary> + public uint FreeSocketObjHold + { + get + { + return Sdk.HP_Server_GetFreeSocketObjHold(pServer); + } + set + { + Sdk.HP_Server_SetFreeSocketObjHold(pServer, value); + } + } + + /// <summary> + /// 读取或设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// </summary> + public uint FreeBufferObjHold + { + get + { + return Sdk.HP_Server_GetFreeBufferObjHold(pServer); + } + set + { + Sdk.HP_Server_SetFreeBufferObjHold(pServer, value); + } + } + + /// <summary> + /// 读取或设置心跳包间隔(毫秒,0 则不发送心跳包) + /// </summary> + public uint KeepAliveTime + { + get + { + return Sdk.HP_TcpServer_GetKeepAliveTime(pServer); + } + set + { + Sdk.HP_TcpServer_SetKeepAliveTime(pServer, value); + } + } + + /// <summary> + /// 读取或设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// </summary> + public uint KeepAliveInterval + { + get + { + return Sdk.HP_TcpServer_GetKeepAliveInterval(pServer); + } + set + { + Sdk.HP_TcpServer_SetKeepAliveInterval(pServer, value); + } + } + + /// <summary> + /// 读取或设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:FALSE) + /// </summary> + public bool MarkSilence + { + get + { + return Sdk.HP_Server_IsMarkSilence(pServer); + } + set + { + Sdk.HP_Server_SetMarkSilence(pServer, value); + } + } + + /// <summary> + /// 获取或设置数据发送策略 + /// </summary> + public SendPolicy SendPolicy + { + get + { + return Sdk.HP_Server_GetSendPolicy(pServer); + } + set + { + Sdk.HP_Server_SetSendPolicy(pServer, value); + } + } + + + /// <summary> + /// 获取或设置 OnSend 事件同步策略 + /// </summary> + public OnSendSyncPolicy OnSendSyncPolicy + { + get + { + return Sdk.HP_Server_GetOnSendSyncPolicy(pServer); + } + set + { + Sdk.HP_Server_SetOnSendSyncPolicy(pServer, value); + } + } + + /////////////////////////////////////////////////////////////////////////////////////// + + /// <summary> + /// 获取系统返回的错误码 + /// </summary> + public int SYSGetLastError() + { + return Sdk.SYS_GetLastError(); + } + + /// <summary> + /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 + /// </summary> + public int SYSWSAGetLastError() + { + return Sdk.SYS_WSAGetLastError(); + } + + /// <summary> + /// 获取错误码 + /// </summary> + public SocketError ErrorCode + { + get + { + return Sdk.HP_Server_GetLastError(pServer); + } + } + + /// <summary> + /// 版本号 + /// </summary> + public string Version + { + get + { + return Sdk.GetHPSocketVersion(); + } + } + + /// <summary> + /// 获取错误信息 + /// </summary> + public string ErrorMessage + { + get + { + IntPtr ptr = Sdk.HP_Server_GetLastErrorDesc(pServer); + string desc = Marshal.PtrToStringAnsi(ptr); + return desc; + } + } + + + /////////////////////////////////////////////////////////////////////////////////////// + protected Sdk.OnPrepareListen _OnPrepareListen = null; + protected Sdk.OnAccept _OnAccept = null; + protected Sdk.OnReceive _OnReceive = null; + protected Sdk.OnSend _OnSend = null; + protected Sdk.OnClose _OnClose = null; + protected Sdk.OnShutdown _OnShutdown = null; + protected Sdk.OnHandShake _OnHandShake = null; + + protected virtual void SetCallback() + { + _OnPrepareListen = new Sdk.OnPrepareListen(SDK_OnPrepareListen); + _OnAccept = new Sdk.OnAccept(SDK_OnAccept); + _OnSend = new Sdk.OnSend(SDK_OnSend); + _OnReceive = new Sdk.OnReceive(SDK_OnReceive); + _OnClose = new Sdk.OnClose(SDK_OnClose); + _OnShutdown = new Sdk.OnShutdown(SDK_OnShutdown); + _OnHandShake = new Sdk.OnHandShake(SDK_OnHandShake); + + Sdk.HP_Set_FN_Server_OnPrepareListen(pListener, _OnPrepareListen); + Sdk.HP_Set_FN_Server_OnAccept(pListener, _OnAccept); + Sdk.HP_Set_FN_Server_OnSend(pListener, _OnSend); + Sdk.HP_Set_FN_Server_OnReceive(pListener, _OnReceive); + Sdk.HP_Set_FN_Server_OnClose(pListener, _OnClose); + Sdk.HP_Set_FN_Server_OnShutdown(pListener, _OnShutdown); + Sdk.HP_Set_FN_Server_OnHandShake(pListener, _OnHandShake); + } + + protected HandleResult SDK_OnHandShake(IntPtr pSender, IntPtr connId) + { + if (OnHandShake != null) + { + return OnHandShake(this, connId); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnPrepareListen(IntPtr pSender, IntPtr soListen) + { + if (OnPrepareListen != null) + { + return OnPrepareListen(this, soListen); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnAccept(IntPtr pSender, IntPtr connId, IntPtr pClient) + { + if (OnAccept != null) + { + return OnAccept(this, connId, pClient); + } + + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnSend(IntPtr pSender, IntPtr connId, IntPtr pData, int length) + { + if (OnSend != null) + { + byte[] bytes = new byte[length]; + Marshal.Copy(pData, bytes, 0, length); + return OnSend(this, connId, bytes); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnReceive(IntPtr pSender, IntPtr connId, IntPtr pData, int length) + { + if (OnPointerDataReceive != null) + { + return OnPointerDataReceive(this, connId, pData, length); + } + else if (OnReceive != null) + { + byte[] bytes = new byte[length]; + Marshal.Copy(pData, bytes, 0, length); + return OnReceive(this, connId, bytes); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnClose(IntPtr pSender, IntPtr connId, SocketOperation enOperation, int errorCode) + { + if (OnClose != null) + { + return OnClose(this, connId, enOperation, errorCode); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnShutdown(IntPtr pSender) + { + if (OnShutdown != null) + { + return OnShutdown(this); + } + return HandleResult.Ignore; + } + + + ///////////////////////////////////////////////////////////////////////// + + /// <summary> + /// 根据错误码返回错误信息 + /// </summary> + /// <param name="code"></param> + /// <returns></returns> + public string GetSocketErrorDesc(SocketError code) + { + IntPtr ptr = Sdk.HP_GetSocketErrorDesc(code); + string desc = Marshal.PtrToStringAnsi(ptr); + return desc; + } + + + /// <summary> + /// 调用系统的 setsockopt() + /// </summary> + /// <param name="sock"></param> + /// <param name="level"></param> + /// <param name="name"></param> + /// <param name="val"></param> + /// <param name="len"></param> + /// <returns></returns> + /// + public int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len) + { + return Sdk.SYS_SetSocketOption(sock, level, name, val, len); + } + + /// <summary> + /// 调用系统的 getsockopt() + /// </summary> + /// <param name="sock"></param> + /// <param name="level"></param> + /// <param name="name"></param> + /// <param name="val"></param> + /// <param name="len"></param> + /// <returns></returns> + /// + public int SYSGetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len) + { + return Sdk.SYS_GetSocketOption(sock, level, name, val, ref len); + } + /// <summary> + /// 调用系统的 ioctlsocket() + /// </summary> + /// <param name="sock"></param> + /// <param name="cmd"></param> + /// <param name="arg"></param> + /// <returns></returns> + /// + public int SYSIoctlSocket(IntPtr sock, long cmd, IntPtr arg) + { + return Sdk.SYS_IoctlSocket(sock, cmd, arg); + } + + /// <summary> + /// 调用系统的 ::WSAIoctl() + /// </summary> + /// <param name="sock"></param> + /// <param name="dwIoControlCode"></param> + /// <param name="lpvInBuffer"></param> + /// <param name="cbInBuffer"></param> + /// <param name="lpvOutBuffer"></param> + /// <param name="cbOutBuffer"></param> + /// <param name="lpcbBytesReturned"></param> + /// <returns></returns> + public int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, + IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned) + { + return Sdk.SYS_WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer, + lpvOutBuffer, cbOutBuffer, lpcbBytesReturned); + } + + /// <summary> + /// 由结构体转换为byte数组 + /// </summary> + public byte[] StructureToByte<T>(T structure) + { + int size = Marshal.SizeOf(typeof(T)); + byte[] buffer = new byte[size]; + IntPtr bufferIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(structure, bufferIntPtr, true); + Marshal.Copy(bufferIntPtr, buffer, 0, size); + } + finally + { + Marshal.FreeHGlobal(bufferIntPtr); + } + return buffer; + } + + /// <summary> + /// 由byte数组转换为结构体 + /// </summary> + public T ByteToStructure<T>(byte[] dataBuffer) + { + object structure = null; + int size = Marshal.SizeOf(typeof(T)); + IntPtr allocIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.Copy(dataBuffer, 0, allocIntPtr, size); + structure = Marshal.PtrToStructure(allocIntPtr, typeof(T)); + } + finally + { + Marshal.FreeHGlobal(allocIntPtr); + } + return (T)structure; + } + + /// <summary> + /// 对象序列化成byte[] + /// </summary> + /// <param name="obj"></param> + /// <returns></returns> + public byte[] ObjectToBytes(object obj) + { + using (MemoryStream ms = new MemoryStream()) + { + IFormatter formatter = new BinaryFormatter(); + formatter.Serialize(ms, obj); + return ms.GetBuffer(); + } + } + + /// <summary> + /// byte[]序列化成对象 + /// </summary> + /// <param name="Bytes"></param> + /// <returns></returns> + public object BytesToObject(byte[] bytes) + { + using (MemoryStream ms = new MemoryStream(bytes)) + { + IFormatter formatter = new BinaryFormatter(); + return formatter.Deserialize(ms); + } + } + /// <summary> + /// byte[]转结构体 + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="bytes"></param> + /// <returns></returns> + public T BytesToStruct<T>(byte[] bytes) + { + Type strcutType = typeof(T); + int size = Marshal.SizeOf(strcutType); + IntPtr buffer = Marshal.AllocHGlobal(size); + try + { + Marshal.Copy(bytes, 0, buffer, size); + return (T)Marshal.PtrToStructure(buffer, strcutType); + } + finally + { + Marshal.FreeHGlobal(buffer); + } + } + } +} diff --git a/PCRobot/LogHelper.cs b/PCRobot/LogHelper.cs new file mode 100644 index 0000000..a36b6f5 --- /dev/null +++ b/PCRobot/LogHelper.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot +{ + /// <summary> + /// 日志参数类 + /// </summary> + internal sealed class LogParameter + { +        /// <summary> +        /// 日志等级 +        /// </summary> +        public int LogGrade { get; set; } + + /// <summary> +         /// 日志类型 +         /// </summary> + public string LogType { get; set; } + + /// <summary> +         /// 日志记录类名和方法名(className/methodName) +         /// </summary> + public string LogName { get; set; } + + /// <summary> +         /// 日志记录文本内容 +         /// </summary> + public string LogContent { get; set; } + } + + /// <summary> + /// 自定义之日助手 + /// </summary> + internal sealed class LogHelper + { + #region 单利模式 + //创建私有静态字段,接收类的实例化对象 + private static readonly LogHelper _LogHelper = null; + //构造函数私有化 + internal LogHelper() { } + //静态构造函数,创建单利对象资源 + static LogHelper() + { + _LogHelper = new LogHelper(); + } + + //获取单利对象资源 + public static LogHelper GetSingleObj() + { + return _LogHelper; + } + #endregion + + /// <summary> + /// 日志等级 + /// </summary> + private enum LogType { ERROR = 1, INFO = 2, DEBUG = 3 }; + + /// <summary> + /// 指定日志文件夹(项目跟路劲文件夹) + /// </summary> + public string Path { get; set; } + + /// <summary> + /// 向日志文件写入调试信息 + /// </summary> + /// <param name="logName">类名/方法名</param> + /// <param name="logContent">日志记录内容</param> + public void Debug(string logName, string logContent) + { + try + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.DEBUG, LogType = nameof(LogType.DEBUG), LogName = logName, LogContent = logContent }); + } + catch (Exception) + { } + } + + /// <summary> + /// 向日志文件写入运行时信息 + /// </summary> + /// <param name="logName">类名/方法名</param> + /// <param name="logContent">日志记录内容</param> + public void Info(string logName, string logContent) + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.INFO, LogType = nameof(LogType.INFO), LogName = logName, LogContent = logContent }); + } + + /// <summary> + /// 向日志文件写入出错信息 + /// </summary> + /// <param name="logName">类名/方法名</param> + /// <param name="logContent">日志记录内容</param> + public void Error(string logName, string logContent) + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.ERROR, LogType = nameof(LogType.ERROR), LogName = logName, LogContent = logContent }); + } + + /// <summary> + /// 实际的写日志操作 + /// </summary> + /// <param name="logParameter">日志参数model</param> + private void WriteLog(LogParameter _logParameter) + { + var logParameter = _logParameter; + //var m = new Action(delegate () + //Task.Factory.StartNew(delegate () + //{ + try + { + string filename = string.Empty; + filename = CsharpHttpHelper.HttpExtend.MapFile($"{DateTime.Now.ToString("yyyy-MM-dd HH")}.log", $"Cache\\{_logParameter.LogType}"); + + #region 原始写法 + //创建或打开日志文件,向日志文件末尾追加记录 + //StreamWriter mySw = File.AppendText(filename); + + //向日志文件写入内容 + //string writeContent = time + "|" + typeGrade + ":" + type + "|" + className + ":" + content; + //mySw.WriteLine(writeContent); + + //关闭日志文件 + //mySw.Close(); + #endregion + + //(优化写法)创建或打开日志文件,向日志文件末尾追加记录,关闭日志文件 + using (StreamWriter mySw = File.AppendText(filename)) + { + string writeContent = $"{DateTime.Now.ToString("HH:mm:ss")}---{logParameter.LogGrade}|{logParameter.LogType}|{logParameter.LogName}---{logParameter.LogContent}"; + mySw.WriteLine(writeContent);//向日志文件写入内容 + mySw.Close(); //关闭日志文件 + } + } + catch (Exception) + { + } + //}); + //m.BeginInvoke(null, null); + } + } + +} diff --git a/PCRobot/MessageBox1.Designer.cs b/PCRobot/MessageBox1.Designer.cs new file mode 100644 index 0000000..62ab14a --- /dev/null +++ b/PCRobot/MessageBox1.Designer.cs @@ -0,0 +1,86 @@ +namespace PCRobot +{ + partial class MessageBox1 + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.label1 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.SuspendLayout(); + // + // label1 + // + this.label1.Font = new System.Drawing.Font("宋体", 12F); + this.label1.Location = new System.Drawing.Point(1, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(367, 54); + this.label1.TabIndex = 0; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(92, 75); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(160, 32); + this.button1.TabIndex = 1; + this.button1.Text = "确定{0}"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // timer1 + // + this.timer1.Interval = 1000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // MessageBox1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(368, 119); + this.Controls.Add(this.button1); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MessageBox1"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "温馨提示"; + this.Load += new System.EventHandler(this.MessageBox_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Timer timer1; + } +} \ No newline at end of file diff --git a/PCRobot/MessageBox1.cs b/PCRobot/MessageBox1.cs new file mode 100644 index 0000000..c07f507 --- /dev/null +++ b/PCRobot/MessageBox1.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PCRobot +{ + public partial class MessageBox1 : Form + { + public MessageBox1(string mess) + { + InitializeComponent(); + label1.Text = mess; + } + + private void MessageBox_Load(object sender, EventArgs e) + { + this.button1.Text = "[5]秒后自动确定"; + timer1.Enabled = true; + } + + private void timer1_Tick(object sender, EventArgs e) + { + try + { + this.Invoke(new Action(delegate + { + try + { + var reg = Regex.Match(this.button1.Text, @"^\[(\d+)\]秒后自动确定$"); + if (reg.Success) + { + int number = int.Parse(reg.Groups[1].Value) - 1; + if (number < 0) + { + this.timer1.Enabled = false; + this.Close(); + } + else + this.button1.Text = "[" + number + "]秒后自动确定"; + } + } + catch (Exception ex) + { } + })); + } + catch (Exception) + { } + } + + private void button1_Click(object sender, EventArgs e) + { + timer1.Stop(); + this.Close(); + } + } +} diff --git a/PCRobot/MessageBox1.resx b/PCRobot/MessageBox1.resx new file mode 100644 index 0000000..1f666f2 --- /dev/null +++ b/PCRobot/MessageBox1.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/PCRobot/MyReceiveFilter.cs b/PCRobot/MyReceiveFilter.cs new file mode 100644 index 0000000..61a93ef --- /dev/null +++ b/PCRobot/MyReceiveFilter.cs @@ -0,0 +1,28 @@ +using SuperSocket.ProtoBase; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot +{ + class MyReceiveFilter : TerminatorReceiveFilter<StringPackageInfo> + { + public MyReceiveFilter() + : base(Encoding.ASCII.GetBytes("\r\n")) + { + + } + + public override StringPackageInfo ResolvePackage(IBufferStream bufferStream) + { + var msg = bufferStream.ReadString((int)bufferStream.Length, Encoding.UTF8); + var arr = msg.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); + StringPackageInfo spi = new StringPackageInfo(arr[0], arr[1], null); + return spi; + } + + // other code you need implement according yoru protocol details + } +} diff --git a/PCRobot/NmClient.cs b/PCRobot/NmClient.cs new file mode 100644 index 0000000..a692091 --- /dev/null +++ b/PCRobot/NmClient.cs @@ -0,0 +1,758 @@ +using HPSocketCS; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Pack; +using PCRobot.WechatApi; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using static PCRobot.WechatApi.NMHelper; + +namespace PCRobot +{ + public class NmClient + { + private static readonly object SequenceLock = new object(); + HPSocketCS.TcpPackServer HP_Server = new HPSocketCS.TcpPackServer(); + NMHelper nmHeler = new NMHelper(); + public NMCore nmCore { get; set; } + public string NewLine; + + public static bool isReady { get; set; } + + Action<nmWxidInfo> LgCall; + + nmWxidInfo curWx; + + public void IniWechat(SocketClient skc, Action<nmWxidInfo> LgCall) + { + if (!isReady) + { + NewLine = Environment.NewLine; + this.skc = skc; + this.LgCall = LgCall; + HP_Server.OnAccept += new ServerEvent.OnAcceptEventHandler(OnAccept); + HP_Server.OnReceive += new ServerEvent.OnReceiveEventHandler(OnReceive); + HP_Server.OnClose += new ServerEvent.OnCloseEventHandler(OnClose); + HP_Server.MaxPackSize = 0x3FFFFF; + HP_Server.IpAddress = "127.0.0.1"; + HP_Server.Port = 0; + if (HP_Server.Start() == true) + { + isReady = true; + + nmCore = new NMCore(HP_Server); + string szIPAddress = string.Empty; + ushort dwPort = 0; + HP_Server.GetListenAddress(ref szIPAddress, ref dwPort); + if (dwPort == 0) + { + //MessageBox.Show("通信端口创建失败,请重试!", "错误"); + //Environment.Exit(0); + } + nmHeler.Socket_Port = dwPort; + WriteLog("[初始化]" + NewLine + "绑定地址:" + szIPAddress + NewLine + "通信端口:" + nmHeler.Socket_Port.ToString()); + } + else + { + //MessageBox.Show("创建通信服务失败,请重试!", "错误"); + //Environment.Exit(0); + } + //byte[] bytPath = new byte[260]; + //if (NMHelper.NM_GetWeChatPath(bytPath, 260) == true) + //{ + // string Path = System.Text.Encoding.GetEncoding("GB2312").GetString(bytPath, 0, bytPath.Length); + // text_WeChatPath.Text = Path; + //} + + NMHelper.NM_LinkWeChat(201912121, nmHeler.Socket_Port, 0, 0); + } + + + } + + HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr pClient) + { + nmCore.NM_Init((int)connId, "C#-275569550"); + return HandleResult.Ok; + } + + HandleResult OnReceive(IServer sender, IntPtr connId, byte[] bytes) + { + string s_Recv = Encoding.Default.GetString(bytes); + JObject RecvJson = JObject.Parse(s_Recv); + int RecvType; + if (nmHeler.Json_GetInt(RecvJson, "PackType", out RecvType) == true) + { + if (RecvType == NMHelper.Recv_QRCode) + { + Event_QRCode(RecvJson); + } + else if (RecvType == NMHelper.Recv_Login) + { + Event_Login((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_Logout) + { + Event_Logout((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_Msg) + { + Event_RecvMsg((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_SelectTalker) + { + Event_SelectTalker((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetContactList) + { + Event_RecvContactList((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetGroupMember) + { + Event_RecvGroupMember((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetWxidInfo) + { + Event_RecvWxidInfo((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_AddFriend) + { + Event_AddFriend((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_CreateGroup) + { + Event_CreateGroup((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetFavList) + { + Event_GetFavList((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetA8Key) + { + Event_GetA8Key((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_InvitePull) + { + Event_GroupInvite((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_QuitGroup) + { + Event_GroupQuit((int)connId, RecvJson); + } + } + return HandleResult.Ok; + } + + HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation enOperation, int errorCode) + { + Event_Logout((int)connId, new JObject()); + return HandleResult.Ok; + } + + + SocketClient skc; + + + /// <summary> + /// 通信事件_接收登录二维码 + /// </summary> + /// <param name="RecvJson"></param> + void Event_QRCode(JObject RecvJson) + { + int dwPid = 0; + nmHeler.Json_GetInt(RecvJson, "ProcessId", out dwPid); + string B64_QRCode = nmHeler.Json_GetString(RecvJson, "QRCode", false); + if (B64_QRCode != string.Empty) + { + byte[] imageBytes = Convert.FromBase64String(B64_QRCode); + MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length); + ms.Write(imageBytes, 0, imageBytes.Length); + //pictureBox1.Image = System.Drawing.Image.FromStream(ms, true); + WriteLog("[二维码]" + NewLine + "接收来自进程(PID:" + dwPid.ToString() + ")的登录二维码"); + } + } + + /// <summary> + /// 通信事件_登录成功 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="RecvJson"></param> + void Event_Login(int ConnID, JObject RecvJson) + { + lock (SequenceLock) + { + NMHelper.nmWxidInfo WxidInfo = new NMHelper.nmWxidInfo(); + WxidInfo.Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + WxidInfo.Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + WxidInfo.WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + WxidInfo.HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + WxidInfo.handle = (int)DwPid; + WxidInfo.socketHandle = ConnID; + curWx = WxidInfo; + LgCall(curWx); + } + } + /// <summary> + /// 通信事件_退出登录 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="RecvJson"></param> + void Event_Logout(int ConnID, JObject RecvJson) + { + //int dwRowIndex = nmHeler.FindRowIndex(list_Login, ConnID.ToString(), 0); + //if (dwRowIndex != -1) + //{ + // if (ConnID == nmHeler.Socket_ConnId) + // { + // nmHeler.Socket_ConnId = 0; + // groupBox1.Text = "登录列表"; + // } + // string szNick = list_Login.Items[dwRowIndex].SubItems[1].Text; + // string szWxid = list_Login.Items[dwRowIndex].SubItems[2].Text; + // list_Login.Items.RemoveAt(dwRowIndex); + // WriteLog("[微信退出]" + NewLine + "昵称:" + szNick + NewLine + "Wxid:" + szWxid); + //} + } + /// <summary> + /// 通信事件_接收消息 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="RecvJson"></param> + void Event_RecvMsg(int ConnID, JObject RecvJson) + { + NMHelper.nmMsgInfo MsgInfo = new NMHelper.nmMsgInfo(); + MsgInfo.RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + MsgInfo.Type = nmHeler.Json_GetIntEx(RecvJson, "Type"); + MsgInfo.State = nmHeler.Json_GetIntEx(RecvJson, "State"); + MsgInfo.Time = nmHeler.Json_GetIntEx(RecvJson, "Time"); + MsgInfo.IsSend = nmHeler.Json_GetIntEx(RecvJson, "Sender"); + MsgInfo.LocalMsgID = nmHeler.Json_GetIntEx(RecvJson, "LocalID"); + MsgInfo.ServerMsgID = nmHeler.Json_GetString(RecvJson, "ServerID", false); + MsgInfo.Wxid_1 = nmHeler.Json_GetString(RecvJson, "Wxid_1", true); + MsgInfo.Nick_1 = nmHeler.Json_GetString(RecvJson, "Nick_1", true); + MsgInfo.Wxid_2 = nmHeler.Json_GetString(RecvJson, "Wxid_2", true); + MsgInfo.Nick_2 = nmHeler.Json_GetString(RecvJson, "Nick_2", true); + MsgInfo.Msg = nmHeler.Json_GetString(RecvJson, "Msg", true); + MsgInfo.Source = nmHeler.Json_GetString(RecvJson, "Source", true); + + string outLog = (MsgInfo.IsSend > 0 ? "[发出消息]" : "[接收消息]") + MsgInfo.RecvWxid + NewLine; + outLog += "类型:" + MsgInfo.Type.ToString() + " 状态:" + MsgInfo.State.ToString() + " 时间:" + nmHeler.Timestamp2DataTime(MsgInfo.Time) + NewLine; + outLog += "本地ID:" + MsgInfo.LocalMsgID.ToString() + " 服务器ID:" + MsgInfo.ServerMsgID + NewLine; + outLog += "Wxid1:" + MsgInfo.Wxid_1 + (MsgInfo.Nick_1 == String.Empty ? string.Empty : "(" + MsgInfo.Nick_1 + ")") + NewLine; + outLog += "Wxid2:" + MsgInfo.Wxid_2 + (MsgInfo.Nick_2 == String.Empty ? string.Empty : "(" + MsgInfo.Nick_2 + ")") + NewLine; + outLog += "消息内容:" + MsgInfo.Msg + NewLine + "附加消息:" + MsgInfo.Source + NewLine; + + if (MsgInfo.Type == 43 || MsgInfo.Type == 49) + { + string FilePath = nmHeler.Json_GetString(RecvJson, "File", true); + if (FilePath != string.Empty) + { + outLog += "文件路径:" + FilePath; + } + } + else if (MsgInfo.Type == 3 || MsgInfo.Type == 34) + { + string FileData = nmHeler.Json_GetString(RecvJson, "File", false); + if (FileData != string.Empty) + { + byte[] FileBytes = Convert.FromBase64String(FileData); + string FilePath = nmHeler.SaveFile(MsgInfo.RecvWxid, MsgInfo.Wxid_1, (MsgInfo.Type == 3 ? "IMAGE" : "VOICE"), MsgInfo.ServerMsgID, (MsgInfo.Type == 3 ? "jpg" : "silk"), FileBytes); + outLog += "文件路径:" + FilePath; + + //if (MsgInfo.Type == 3 && chk_MaxPicture.Checked == true && MsgInfo.IsSend == 0) + //{ + // string MaxFilePath = FilePath.Replace(MsgInfo.ServerMsgID, MsgInfo.ServerMsgID + "_MAX"); + // nmCore.NM_GetImageByCDN(ConnID, MsgInfo.Msg, MaxFilePath); + //} + } + } + WriteLog(outLog+"@####"); + + //自动通过好友 + if (MsgInfo.Type == 37) + { + Console.WriteLine("@@@@@ = " + MsgInfo.Msg); + + nmCore.NM_PassApply(ConnID, MsgInfo.Msg); + + + } + if (MsgInfo.Type == 1) + { + Console.WriteLine("####### = " + MsgInfo.Msg); + if (skc != null && MsgInfo.IsSend == 0) + { + WechatReceiveMsg msg = new WechatReceiveMsg(); + msg.Cmd = PCRobotCMD.rcvTxt; + msg.IsSend = MsgInfo.IsSend == 1 ? true : false; + msg.RobotUsername = curWx.Wxid; + msg.RobotUsernick = curWx.Nick; + + msg.RobotType = RobotType.客户端微信; + msg.FromMessageType = WechatMsgType.文本; + + + + if (MsgInfo.Wxid_1.Contains("@chatroom")) + { + msg.FromGroupid = MsgInfo.Wxid_1; + + msg.FromUsername = MsgInfo.Wxid_2; + msg.FromUsernick = MsgInfo.Wxid_2; + } + else if (MsgInfo.Wxid_2.Contains("@chatroom")) + { + msg.FromGroupid = MsgInfo.Wxid_2; + + msg.FromUsername = MsgInfo.Wxid_1; + msg.FromUsernick = MsgInfo.Wxid_1; + } + else + { + msg.FromUsername = MsgInfo.Wxid_1; + msg.FromUsernick = MsgInfo.Wxid_1; + } + msg.FromMessage = MsgInfo.Msg; + msg.FromUsernick = ""; + skc.Send(msg); + } + } + + //自动填充消息内容,用于撤回消息 + if (MsgInfo.IsSend == 1 && ConnID == nmHeler.Socket_ConnId) + { + //text_Recvke_Wxid.Text = MsgInfo.Wxid_1; + //text_Recvke_Sid.Text = MsgInfo.ServerMsgID; + //text_Recvke_Message.Text = MsgInfo.Msg; + } + //转账自动收款 + if (MsgInfo.IsSend == 0 && MsgInfo.Type == 49) + { + //if (MsgInfo.Msg.IndexOf("微信转账") != -1 && MsgInfo.Msg.IndexOf("收到转账") != -1) + //{ + // string State = nmHeler.StringMid(MsgInfo.Msg, "<paysubtype>", "</paysubtype>"); + // string Transid = nmHeler.StringMid(MsgInfo.Msg, "transferid><![CDATA[", "]]></transferid>"); + // int dwTime = 0; + // int.TryParse(nmHeler.StringMid(MsgInfo.Msg, "<invalidtime><![CDATA[", "]]></invalidtime>"), out dwTime); + // if (State == "1" && Transid != string.Empty) + // { + // nmCore.NM_GetMoney(ConnID, MsgInfo.Wxid_1, Transid, dwTime); + // } + //} + } + //名片消息自动填充数据 + if (MsgInfo.IsSend == 0 && MsgInfo.Type == 42 && ConnID == nmHeler.Socket_ConnId) + { + //string v1 = nmHeler.StringMid(MsgInfo.Msg, "username=\"", "\" nickname="); + //string v2 = nmHeler.StringMid(MsgInfo.Msg, "antispamticket=\"", "\" /"); + //text_Friend_v1.Text = v1; + //text_Friend_v2.Text = v2; + } + //自动接受群聊邀请 + if (MsgInfo.IsSend == 0 && MsgInfo.Type == 49) + { + //if (MsgInfo.Msg.IndexOf("邀请你加入群聊") != -1 && MsgInfo.Msg.IndexOf("mmsupport-bin/addchatroombyinvite") != -1) + //{ + // string InviteURL = nmHeler.StringMid(MsgInfo.Msg, "<url><![CDATA[", "]]></url>"); + // if (InviteURL != string.Empty) + // { + // nmCore.NM_GetA8Key(ConnID, MsgInfo.Wxid_1, InviteURL); + // } + //} + } + } + /// <summary> + /// 通信事件_切换聊天对象 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="RecvJson"></param> + void Event_SelectTalker(int ConnID, JObject RecvJson) + { + NMHelper.nmWxidInfo WxidInfo = new NMHelper.nmWxidInfo(); + string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + WxidInfo.Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + WxidInfo.WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + WxidInfo.Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + WxidInfo.Mark = nmHeler.Json_GetString(RecvJson, "Mark", true); + WxidInfo.HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + string outLog = "[切换聊天对象]" + RecvWxid + NewLine; + outLog += "Wxid:" + WxidInfo.Wxid + NewLine; + outLog += WxidInfo.WxNo == string.Empty ? string.Empty : "微信号:" + WxidInfo.Wxid + NewLine; + outLog += "昵称:" + WxidInfo.Nick + NewLine; + outLog += WxidInfo.Mark == string.Empty ? string.Empty : "备注:" + WxidInfo.Mark; + //outLog += "头像:" + WxidInfo.HeadIMG; + WriteLog(outLog); + } + + void Event_RecvContactList(int ConnID, JObject RecvJson) + { + //string outLog = "[通讯录列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + //if (dwState == 0) + //{ + // outLog += "通讯录列表读取失败!"; + // WriteLog(outLog); + // return; + //} + //JArray m_List = RecvJson.Value<JArray>("List"); + //if (m_List != null) + //{ + // list_Friend.BeginUpdate(); list_Group.BeginUpdate(); list_GHFriend.BeginUpdate(); + // list_Friend.Items.Clear(); list_Group.Items.Clear(); list_GHFriend.Items.Clear(); + // for (int i = 0; i < m_List.Count; i++) + // { + // JToken JtMember = m_List.ElementAt(i); + // if (JtMember != null) + // { + // NMHelper.nmWxidInfo MemberInfo = new NMHelper.nmWxidInfo(); + // MemberInfo.Type = nmHeler.Json_GetIntEx((JObject)JtMember, "Type"); + // MemberInfo.List = nmHeler.Json_GetIntEx((JObject)JtMember, "List"); + // MemberInfo.Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + // MemberInfo.WxNo = nmHeler.Json_GetString((JObject)JtMember, "WxNo", true); + // MemberInfo.Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + // MemberInfo.Mark = nmHeler.Json_GetString((JObject)JtMember, "Mark", true); + // MemberInfo.HeadIMG = nmHeler.Json_GetString((JObject)JtMember, "HeadIMG", true); + // ListViewItem UserItem = new ListViewItem(); + + // if (MemberInfo.Type == 8 || MemberInfo.Type == 24 || MemberInfo.Type == 29) + // { + // UserItem.Text = MemberInfo.Nick; + // UserItem.SubItems.Add(MemberInfo.Wxid); + // UserItem.SubItems.Add(MemberInfo.WxNo); + // UserItem.SubItems.Add(MemberInfo.HeadIMG); + // list_GHFriend.Items.Add(UserItem); + // } + // else if (MemberInfo.Wxid.LastIndexOf("@chatroom") != -1) + // { + // UserItem.Text = MemberInfo.Nick == string.Empty ? "群聊" : MemberInfo.Nick; + // UserItem.SubItems.Add(MemberInfo.Wxid); + // UserItem.SubItems.Add(MemberInfo.WxNo); + // UserItem.SubItems.Add(MemberInfo.List.ToString()); + // UserItem.SubItems.Add(MemberInfo.HeadIMG); + // list_Group.Items.Add(UserItem); + // } + // else if (MemberInfo.List != 2) + // { + // UserItem.Text = MemberInfo.Nick; + // UserItem.SubItems.Add(MemberInfo.Mark); + // UserItem.SubItems.Add(MemberInfo.Wxid); + // UserItem.SubItems.Add(MemberInfo.WxNo); + // UserItem.SubItems.Add(MemberInfo.HeadIMG); + // list_Friend.Items.Add(UserItem); + // } + // } + // } + // list_Friend.EndUpdate(); list_Group.EndUpdate(); list_GHFriend.EndUpdate(); + // outLog += "通讯录列表读取成功"; + // outLog += ",好友:" + list_Friend.Items.Count.ToString(); + // outLog += ",群聊:" + list_Group.Items.Count.ToString(); + // outLog += ",好友:" + list_GHFriend.Items.Count.ToString(); + // WriteLog(outLog); + //} + } + + void Event_RecvGroupMember(int ConnID, JObject RecvJson) + { + //string outLog = "[群员列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + //if (dwState == 0) + //{ + // outLog += nmHeler.Json_GetString(RecvJson, "GroupID", false) + "的群员列表读取失败!"; + // WriteLog(outLog); + // return; + //} + //JArray m_List = RecvJson.Value<JArray>("List"); + //if (m_List != null) + //{ + // list_GroupMember.BeginUpdate(); list_GroupMember.Items.Clear(); + // for (int i = 0; i < m_List.Count; i++) + // { + // JToken JtMember = m_List.ElementAt(i); + // if (JtMember != null) + // { + // NMHelper.nmWxidInfo MemberInfo = new NMHelper.nmWxidInfo(); + // MemberInfo.Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + // MemberInfo.Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + // MemberInfo.Mark = nmHeler.Json_GetString((JObject)JtMember, "Mark", true); + // MemberInfo.HeadIMG = nmHeler.Json_GetString((JObject)JtMember, "HeadIMG", true); + // ListViewItem UserItem = new ListViewItem(); + // UserItem.Text = MemberInfo.Nick; + // UserItem.SubItems.Add(MemberInfo.Mark); + // UserItem.SubItems.Add(MemberInfo.Wxid); + // UserItem.SubItems.Add(MemberInfo.HeadIMG); + // list_GroupMember.Items.Add(UserItem); + // } + // } + // list_GroupMember.EndUpdate(); + // outLog += nmHeler.Json_GetString(RecvJson, "GroupID", true) + "的群员列表读取成功,群员数:" + list_GroupMember.Items.Count.ToString(); + // WriteLog(outLog); + //} + } + + void Event_RecvWxidInfo(int ConnID, JObject RecvJson) + { + //string outLog = "[下载详细信息]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + //if (dwState == -1) { outLog += "下载详细信息超时(原因:服务器无返回)!"; } + //else if (dwState == 0) { outLog += "下载详细信息失败(原因:可能是输入的Wxid不正确)!"; } + //else if (dwState == 1) + //{ + // string szGroupID = nmHeler.Json_GetString(RecvJson, "GroupId", true); + // NMHelper.nmWxidInfo MemberInfo = new NMHelper.nmWxidInfo(); + // MemberInfo.Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + // MemberInfo.WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + // MemberInfo.Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + // MemberInfo.V1 = nmHeler.Json_GetString(RecvJson, "v1", true); + // MemberInfo.HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + // MemberInfo.Address = nmHeler.Json_GetString(RecvJson, "Address", true); + // MemberInfo.Sex = MemberInfo.GetSex(nmHeler.Json_GetIntEx(RecvJson, "Sex")); + + // outLog += szGroupID == string.Empty ? string.Empty : "群ID:" + szGroupID + NewLine; + // outLog += "Wxid:" + MemberInfo.Wxid + NewLine; + // outLog += MemberInfo.WxNo == string.Empty ? string.Empty : "微信号:" + MemberInfo.WxNo + NewLine; + // outLog += "昵称:" + MemberInfo.Nick + NewLine; + // outLog += MemberInfo.V1 == string.Empty ? string.Empty : "v1:" + MemberInfo.V1 + NewLine; + // outLog += "性别:" + MemberInfo.Sex + NewLine; + // outLog += MemberInfo.Address == string.Empty ? string.Empty : "地区:" + MemberInfo.Address + NewLine; + // outLog += MemberInfo.HeadIMG == string.Empty ? string.Empty : "头像:" + MemberInfo.HeadIMG + NewLine; + //} + //WriteLog(outLog); + } + + void Event_AddFriend(int ConnID, JObject RecvJson) + { + //string outLog = "[添加好友]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //int DataType = nmHeler.Json_GetIntEx(RecvJson, "DataType"); + //string Data = nmHeler.Json_GetString(RecvJson, "Data", true); + //int Type = nmHeler.Json_GetIntEx(RecvJson, "Type"); + //int AddType = nmHeler.Json_GetIntEx(RecvJson, "AddType"); + //string Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + //string v2 = nmHeler.Json_GetString(RecvJson, "V2", true); + //string Message = nmHeler.Json_GetString(RecvJson, "Message", true); + + //outLog += "添加返回:[" + DataType.ToString() + "]" + (DataType == 0 ? "已发送好友请求或已添加好友。" : Data) + NewLine; + //outLog += "添加类型:" + Type.ToString() + " 添加来源:" + AddType.ToString() + NewLine; + //outLog += "Wxid:" + Wxid; + //outLog += v2 == string.Empty ? string.Empty : NewLine + "v2:" + v2; + //outLog += Message == string.Empty ? string.Empty : NewLine + "附加消息:" + Message; + //WriteLog(outLog); + + //if (Type == 1 && DataType == -44) + //{ + // nmCore.NM_AddFriend(ConnID, 2, AddType, Wxid, v2, text_Friend_Message.Text); + //} + } + + void Event_CreateGroup(int ConnID, JObject RecvJson) + { + //string outLog = "[创建群聊]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //string Data = nmHeler.Json_GetString(RecvJson, "Data", true); + //string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + //outLog += "建群返回:" + Data; + //outLog += GroupID == string.Empty ? string.Empty : NewLine + "群聊ID:" + GroupID + NewLine; + //JArray MemberList = RecvJson.Value<JArray>("List"); + //if (MemberList != null) + //{ + // outLog += "群员列表:"; + // for (int i = 0; i < MemberList.Count; i++) + // { + // JToken JtMember = MemberList.ElementAt(i); + // if (JtMember != null) + // { + // string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + // string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + // int state = nmHeler.Json_GetIntEx((JObject)JtMember, "State"); + // if (Wxid != string.Empty) + // { + // outLog += NewLine + "[" + state.ToString() + "]" + (state == 0 ? "[成功]" : "[失败]"); + // outLog += Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")"); + // } + // } + // } + //} + //WriteLog(outLog); + } + + void Event_GetFavList(int ConnID, JObject RecvJson) + { + //string outLog = "[收藏列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //JArray FavList = RecvJson.Value<JArray>("List"); + //if (FavList != null) + //{ + // list_Fav.Items.Clear(); + // int dwCount = FavList.Count; + // if (dwCount != 0) + // { + // list_Fav.BeginUpdate(); + + // for (int i = 0; i < dwCount; i++) + // { + // JToken JtMember = FavList.ElementAt(i); + // if (JtMember != null) + // { + // int Type = nmHeler.Json_GetIntEx((JObject)JtMember, "Type"); + // string SearchKey = nmHeler.Json_GetString((JObject)JtMember, "SearchKey", true); + // string TypeName = nmHeler.GetFavType(Type); + // ListViewItem FavItem = new ListViewItem(); + // FavItem.Text = i.ToString(); + // FavItem.SubItems.Add(TypeName); + // FavItem.SubItems.Add(SearchKey == string.Empty ? "[" + TypeName + "文件]" : SearchKey); + // list_Fav.Items.Add(FavItem); + // } + // } + // list_Fav.EndUpdate(); + // outLog += "收藏列表读取成功,共" + dwCount.ToString() + "条记录!"; + // } + // else + // { + // outLog += "没有收藏"; + // } + //} + //WriteLog(outLog); + } + + void Event_GetA8Key(int ConnID, JObject RecvJson) + { + //string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + //string outLog = "[GetA8Key]" + RecvWxid + NewLine; + //string URL = nmHeler.Json_GetString(RecvJson, "URL", true); + //string LastURL = nmHeler.Json_GetString(RecvJson, "LastURL", true); + //outLog += "获取链接:" + URL + NewLine; + //outLog += "返回链接:" + LastURL; + //WriteLog(outLog); + + //if (URL.IndexOf("mmsupport-bin/addchatroombyinvite") != -1) + //{ + // HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(URL); + // Request.Method = "POST"; + // Request.AllowAutoRedirect = false; + // Request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; + // Request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.556.400 QQBrowser/9.0.2524.400"; + // Request.Referer = URL; + // Request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8,en-us;q=0.6,en;q=0.5;q=0.4"); + // HttpWebResponse Response = (HttpWebResponse)Request.GetResponse(); + // string hLocation = Response.GetResponseHeader("Location").ToString(); + // if (hLocation != "") + // { + // if (hLocation.IndexOf("chatroom") != -1) + // { + // string GroupID = nmHeler.StringMid(hLocation, "weixin://jump/mainframe/", "@chatroom"); + // WriteLog("[接受群聊邀请]" + RecvWxid + NewLine + "群聊ID:" + GroupID + "@chatroom"); + // } + // } + //} + } + + void Event_GroupInvite(int ConnID, JObject RecvJson) + { + string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[群员动态-进群]" + RecvWxid + NewLine; + string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + outLog = "群聊ID:" + GroupID + NewLine; + JArray MemberList = RecvJson.Value<JArray>("List"); + if (MemberList != null) + { + for (int i = 0; i < MemberList.Count; i++) + { + JToken JtMember = MemberList.ElementAt(i); + if (JtMember != null) + { + string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + string InvWxid = nmHeler.Json_GetString((JObject)JtMember, "InvWxid", true); + string InvNick = nmHeler.Json_GetString((JObject)JtMember, "InvNick", true); + outLog += "[" + (i + 1).ToString() + "]" + NewLine; + outLog += "进群人:" + Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")" + NewLine); + outLog += "邀请人:" + InvWxid + (InvNick == string.Empty ? string.Empty : "(" + InvNick + ")" + NewLine); + } + } + } + WriteLog(outLog); + } + void Event_GroupQuit(int ConnID, JObject RecvJson) + { + string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[群员动态-退群]" + RecvWxid + NewLine; + string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + outLog += "群聊ID:" + GroupID + NewLine; + JArray MemberList = RecvJson.Value<JArray>("List"); + if (MemberList != null) + { + for (int i = 0; i < MemberList.Count; i++) + { + JToken JtMember = MemberList.ElementAt(i); + if (JtMember != null) + { + string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + + outLog += "[" + (i + 1).ToString() + "]" + NewLine; + outLog += Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")" + NewLine); + } + } + } + WriteLog(outLog); + } + + [DllImport("User32.dll", EntryPoint = "PostMessage")] + public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam); + + [DllImport("LIB.KTY.WC.dll", EntryPoint = "Run")] + public static extern IntPtr Run(string path, string dll, int port); + + private IntPtr DwPid = IntPtr.Zero; + + public int handle { get { return (int)DwPid; } } + + public IntPtr StartWechat() + { + var path = CsharpHttpHelper.HttpExtend.MapPath("PCWechat\\2.8.0.112"); + string szDllPath = System.IO.Directory.GetCurrentDirectory() + "\\bin\\NanMuCore.dll"; + DwPid = (IntPtr)NMHelper.NM_CreateWeChatProcess(path, "WeChat.exe", szDllPath, nmHeler.Socket_Port); + return DwPid; + } + + public void CloseWechat() + { + try + { + if (DwPid != IntPtr.Zero) + { + PostMessage(DwPid, 18, 0, 0); + Process[] myproc = Process.GetProcesses(); + foreach (Process item in myproc) + { + try + { + if (item.Id == (int)DwPid) + { + item.Kill(); + break; + } + + } + catch (Exception) + { + } + } + } + } + catch (Exception) + { + } + + } + + public void WriteLog(string str) + { + + } + } +} diff --git a/PCRobot/PCRobot.csproj b/PCRobot/PCRobot.csproj new file mode 100644 index 0000000..84e3799 --- /dev/null +++ b/PCRobot/PCRobot.csproj @@ -0,0 +1,359 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}</ProjectGuid> + <OutputType>WinExe</OutputType> + <RootNamespace>PCRobot</RootNamespace> + <AssemblyName>易转发</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects> + <Deterministic>true</Deterministic> + <TargetFrameworkProfile /> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>x86</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup> + <StartupObject /> + </PropertyGroup> + <PropertyGroup> + <ApplicationIcon>tencent_qqpim_72px_1127550_easyicon.net.ico</ApplicationIcon> + </PropertyGroup> + <ItemGroup> + <Reference Include="FluentScheduler, Version=5.5.1.0, Culture=neutral, processorArchitecture=MSIL"> + <HintPath>..\packages\FluentScheduler.5.5.1\lib\netstandard2.0\FluentScheduler.dll</HintPath> + </Reference> + <Reference Include="Google.Protobuf"> + <HintPath>C:\Users\XianSenWu\Desktop\CshapWechatDemo\CshapWechatDemo\bin\Debug\Google.Protobuf.dll</HintPath> + </Reference> + <Reference Include="HttpHelper, Version=2.1.10.0, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\Debug\HttpHelper.dll</HintPath> + </Reference> + <Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" /> + <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>DLL\Newtonsoft.Json.dll</HintPath> + <Private>True</Private> + </Reference> + <Reference Include="PCRobot.Pack"> + <HintPath>..\PCRobot.Pack\bin\Debug\PCRobot.Pack.dll</HintPath> + </Reference> + <Reference Include="protobuf-net, Version=3.0.0.0, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL"> + <HintPath>..\packages\protobuf-net.3.0.0\lib\net461\protobuf-net.dll</HintPath> + </Reference> + <Reference Include="protobuf-net.Core, Version=3.0.0.0, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL"> + <HintPath>..\packages\protobuf-net.Core.3.0.0\lib\net461\protobuf-net.Core.dll</HintPath> + </Reference> + <Reference Include="SuperSocket.ClientEngine, Version=0.10.0.0, Culture=neutral, PublicKeyToken=ee9af13f57f00acc, processorArchitecture=MSIL"> + <HintPath>..\packages\SuperSocket.ClientEngine.0.10.0\lib\net45\SuperSocket.ClientEngine.dll</HintPath> + </Reference> + <Reference Include="SuperSocket.ProtoBase, Version=1.7.0.17, Culture=neutral, PublicKeyToken=6c80000676988ebb, processorArchitecture=MSIL"> + <HintPath>..\packages\SuperSocket.ProtoBase.1.7.0.17\lib\net45\SuperSocket.ProtoBase.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath> + </Reference> + <Reference Include="System.Collections.Immutable, Version=1.2.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll</HintPath> + </Reference> + <Reference Include="System.Collections.Specialized, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Configuration" /> + <Reference Include="System.Core" /> + <Reference Include="System.Data.Linq" /> + <Reference Include="System.IdentityModel" /> + <Reference Include="System.Management" /> + <Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath> + </Reference> + <Reference Include="System.Net.NameResolution, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Net.NameResolution.4.3.0\lib\net46\System.Net.NameResolution.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Net.Security, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Net.Security.4.3.0\lib\net46\System.Net.Security.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Numerics" /> + <Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath> + </Reference> + <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.ServiceModel" /> + <Reference Include="System.ServiceModel.Primitives, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\packages\System.ServiceModel.Primitives.4.7.0\lib\net461\System.ServiceModel.Primitives.dll</HintPath> + </Reference> + <Reference Include="System.Web" /> + <Reference Include="System.Web.Extensions" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Deployment" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="EasySoc_.cs" /> + <Compile Include="Entitys\Display_Real.cs" /> + <Compile Include="Entitys\Enterprise\CreateGroupInfo.cs" /> + <Compile Include="Entitys\Enterprise\FileC2cCdnInfo.cs" /> + <Compile Include="Entitys\Enterprise\FriendInfoHandlerEnterprise.cs" /> + <Compile Include="Entitys\PcCircle.cs" /> + <Compile Include="Entitys\RemoteLoginCode.cs" /> + <Compile Include="Entitys\UpLoadImage.cs" /> + <Compile Include="Enums\RoutineEnum.cs" /> + <Compile Include="LogHelper.cs" /> + <Compile Include="MessageBox1.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MessageBox1.Designer.cs"> + <DependentUpon>MessageBox1.cs</DependentUpon> + </Compile> + <Compile Include="MyReceiveFilter.cs" /> + <Compile Include="PCRobotForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="PCRobotForm.Designer.cs"> + <DependentUpon>PCRobotForm.cs</DependentUpon> + </Compile> + <Compile Include="PCWechat\Dazong\Extra.cs" /> + <Compile Include="PCWechat\Dazong\NMCore.cs" /> + <Compile Include="PCWechat\Dazong\NMHelper.cs" /> + <Compile Include="PCWechat\Dazong\Sdk.cs" /> + <Compile Include="PCWechat\Dazong\TcpPackServer.cs" /> + <Compile Include="PCWechat\Dazong\TcpServer.cs" /> + <Compile Include="PCWechat\Enterprise\WechatEnterpriseBase.cs" /> + <Compile Include="PCWechat\Enterprise\Wechat_Xiaoxie_QY.cs" /> + <Compile Include="PCWechat\Enterprise\Wechat_Xiaoxie_QY_Analysis.cs" /> + <Compile Include="PCWechat\Enterprise\Wechat_Xiaoxie_QY_Override.cs" /> + <Compile Include="PCWechat\Enterprise\Wechat_Xiaoxie_QY_Type.cs" /> + <Compile Include="PCWechat\Routine\WechatRoutineBase.cs" /> + <Compile Include="PCWechat\Routine\Wechat_Xiaoxie.cs" /> + <Compile Include="PCWechat\Routine\Wechat_Xiaoxie_Analysis.cs" /> + <Compile Include="PCWechat\Routine\Wechat_Xiaoxie_Override.cs" /> + <Compile Include="PCWechat\Routine\Wechat_Xiaoxie_Type.cs" /> + <Compile Include="PCWechat\WechatBase.cs" /> + <Compile Include="PCWechat\WechatClient.cs" /> + <Compile Include="PCWechat\WechatUser.cs" /> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="UpdateForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="UpdateForm.Designer.cs"> + <DependentUpon>UpdateForm.cs</DependentUpon> + </Compile> + <Compile Include="Util.cs" /> + <Compile Include="Utils\Common.cs" /> + <Compile Include="Utils\ProtoBufExtension.cs" /> + <Compile Include="Utils\RegistryHelper.cs" /> + <Compile Include="Utils\UpdateClient.cs" /> + <Compile Include="Utils\WechatExtend.cs" /> + <Compile Include="Utils\ZipArchive.cs" /> + <Compile Include="Utils\ZIP\BZip2\BZip2.cs" /> + <Compile Include="Utils\ZIP\BZip2\BZip2Constants.cs" /> + <Compile Include="Utils\ZIP\BZip2\BZip2Exception.cs" /> + <Compile Include="Utils\ZIP\BZip2\BZip2InputStream.cs" /> + <Compile Include="Utils\ZIP\BZip2\BZip2OutputStream.cs" /> + <Compile Include="Utils\ZIP\Checksums\Adler32.cs" /> + <Compile Include="Utils\ZIP\Checksums\CRC32.cs" /> + <Compile Include="Utils\ZIP\Checksums\IChecksum.cs" /> + <Compile Include="Utils\ZIP\Checksums\StrangeCRC.cs" /> + <Compile Include="Utils\ZIP\Core\FileSystemScanner.cs" /> + <Compile Include="Utils\ZIP\Core\INameTransform.cs" /> + <Compile Include="Utils\ZIP\Core\IScanFilter.cs" /> + <Compile Include="Utils\ZIP\Core\NameFilter.cs" /> + <Compile Include="Utils\ZIP\Core\PathFilter.cs" /> + <Compile Include="Utils\ZIP\Core\StreamUtils.cs" /> + <Compile Include="Utils\ZIP\Core\WindowsPathUtils.cs" /> + <Compile Include="Utils\ZIP\Encryption\PkzipClassic.cs" /> + <Compile Include="Utils\ZIP\Encryption\ZipAESStream.cs" /> + <Compile Include="Utils\ZIP\Encryption\ZipAESTransform.cs" /> + <Compile Include="Utils\ZIP\GZip\GZIPConstants.cs" /> + <Compile Include="Utils\ZIP\GZip\GZipException.cs" /> + <Compile Include="Utils\ZIP\GZip\GzipInputStream.cs" /> + <Compile Include="Utils\ZIP\GZip\GzipOutputStream.cs" /> + <Compile Include="Utils\ZIP\Lzw\LzwConstants.cs" /> + <Compile Include="Utils\ZIP\Lzw\LzwException.cs" /> + <Compile Include="Utils\ZIP\Lzw\LzwInputStream.cs" /> + <Compile Include="Utils\ZIP\SharpZipBaseException.cs" /> + <Compile Include="Utils\ZIP\Tar\InvalidHeaderException.cs" /> + <Compile Include="Utils\ZIP\Tar\TarArchive.cs" /> + <Compile Include="Utils\ZIP\Tar\TarBuffer.cs" /> + <Compile Include="Utils\ZIP\Tar\TarEntry.cs" /> + <Compile Include="Utils\ZIP\Tar\TarException.cs" /> + <Compile Include="Utils\ZIP\Tar\TarHeader.cs" /> + <Compile Include="Utils\ZIP\Tar\TarInputStream.cs" /> + <Compile Include="Utils\ZIP\Tar\TarOutputStream.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\Deflater.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\DeflaterConstants.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\DeflaterEngine.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\DeflaterHuffman.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\DeflaterPending.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\Inflater.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\InflaterDynHeader.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\InflaterHuffmanTree.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\PendingBuffer.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\Streams\DeflaterOutputStream.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\Streams\InflaterInputStream.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\Streams\OutputWindow.cs" /> + <Compile Include="Utils\ZIP\Zip\Compression\Streams\StreamManipulator.cs" /> + <Compile Include="Utils\ZIP\Zip\FastZip.cs" /> + <Compile Include="Utils\ZIP\Zip\IEntryFactory.cs" /> + <Compile Include="Utils\ZIP\Zip\WindowsNameTransform.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipConstants.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipEntry.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipEntryFactory.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipException.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipExtraData.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipFile.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipHelperStream.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipInputStream.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipNameTransform.cs" /> + <Compile Include="Utils\ZIP\Zip\ZipOutputStream.cs" /> + <Compile Include="WechatLoginHelper.cs" /> + <Compile Include="WechatLoginForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="WechatLoginForm.Designer.cs"> + <DependentUpon>WechatLoginForm.cs</DependentUpon> + </Compile> + <Compile Include="WechatUpdate.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="WechatUpdate.Designer.cs"> + <DependentUpon>WechatUpdate.cs</DependentUpon> + </Compile> + <Compile Include="XxType.cs" /> + <EmbeddedResource Include="MessageBox1.resx"> + <DependentUpon>MessageBox1.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="PCRobotForm.resx"> + <DependentUpon>PCRobotForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Resources.resx</DependentUpon> + <DesignTime>True</DesignTime> + </Compile> + <EmbeddedResource Include="UpdateForm.resx"> + <DependentUpon>UpdateForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="WechatLoginForm.resx"> + <DependentUpon>WechatLoginForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="WechatUpdate.resx"> + <DependentUpon>WechatUpdate.cs</DependentUpon> + </EmbeddedResource> + <None Include="packages.config" /> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> + <Compile Include="Properties\Settings.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Settings.settings</DependentUpon> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + </Compile> + </ItemGroup> + <ItemGroup> + <None Include="App.config"> + <SubType>Designer</SubType> + </None> + </ItemGroup> + <ItemGroup> + <None Include="Resources\OnlineUpdate.exe" /> + <None Include="Resources\VersionUpdate.exe" /> + <None Include="Resources\VersionUpdate.xml" /> + <None Include="Resources\NanMuCore_3.2.1.154.dll" /> + <None Include="bin\Debug\Bin\WeChatHelper_3.3.0.93_2.dll" /> + <None Include="bin\Debug\Bin\WxWorkHelper_3.1.10.3010.dll" /> + <None Include="bin\Debug\Bin\WxWorkHelper_3.0.27.2701.dll" /> + <None Include="Resources\Fix.dll" /> + <None Include="Resources\msimg32.dll" /> + <None Include="Resources\WeChatWin.dll" /> + <None Include="Resources\Fix_32.dll" /> + <None Include="Resources\msimg32_32.dll" /> + <None Include="Resources\msimg32_QY.dll" /> + <None Include="Resources\Fix2_QY.dll" /> + <None Include="Resources\libcurl.dll" /> + <None Include="Resources\libcurlOrg.dll" /> + <None Include="Resources\WeChatHelper_3.4.0.38.dll" /> + <None Include="Resources\WeChatHelper_3.3.0.93.dll" /> + <None Include="bin\Debug\Bin\NanMuCore_3.3.5.50.dll" /> + <None Include="Resources\未登录.png" /> + <Content Include="tencent_qqpim_72px_1127550_easyicon.net.ico" /> + </ItemGroup> + <ItemGroup> + <WCFMetadata Include="Connected Services\" /> + </ItemGroup> + <ItemGroup> + <Folder Include="Entitys\Routine\" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/PCRobot/PCRobot.sln b/PCRobot/PCRobot.sln new file mode 100644 index 0000000..6fe4567 --- /dev/null +++ b/PCRobot/PCRobot.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32014.148 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCRobot", "PCRobot.csproj", "{676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PCRobot.Pack", "..\PCRobot.Pack\PCRobot.Pack.csproj", "{C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {676D6EF4-FD4E-48E2-8AAE-14AC4B2F4B1D}.Release|Any CPU.Build.0 = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1EC66C6-7E57-4780-9EA3-13369BD7C9FC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DC92E732-FBAB-4A19-BC38-5391B1F9E213} + EndGlobalSection +EndGlobal diff --git a/PCRobot/PCRobotClient.cs b/PCRobot/PCRobotClient.cs new file mode 100644 index 0000000..1b6773b --- /dev/null +++ b/PCRobot/PCRobotClient.cs @@ -0,0 +1,642 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Pack; +using PCRobot.WechatApi; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PCRobot +{ + public class PCRobotClient + { + public static void Test() + { + + } + + public static void Rcv(string str) + { + try + { + var head = str.Substring(0, str.IndexOf(" ")); + var cmd = (PCRobotCMD)Enum.Parse(typeof(PCRobotCMD), head); + str = CsharpHttpHelper.HttpHelper.URLDecode(str.Replace(head + " ", "")); + var msg = JsonConvert.DeserializeObject<WechatReceiveMsg>(str); + switch (cmd) + { + case PCRobotCMD.sendTxt: + WechatAPI.Wx_SendTextMsg(WechatAPI.Client_Handle, msg.FromUsername, WechatAPI.Client_Wxid, msg.FromMessage); + break; + case PCRobotCMD.sendFile: + //文件接口 + WechatAPI.Wx_SendFileMsg(WechatAPI.Client_Handle, 3, msg.FromUsername, msg.FromMessage); + break; + case PCRobotCMD.sendImg: + byte[] ImageByte = Convert.FromBase64String(msg.FromMessage); + string temp = System.Environment.GetEnvironmentVariable("TEMP"); + //DirectoryInfo info = new DirectoryInfo(temp); + string uFile = temp + "//" + Guid.NewGuid().ToString() + ".png"; + File.WriteAllBytes(uFile, ImageByte); + //图片接口 + WechatAPI.Wx_SendFileMsg(WechatAPI.Client_Handle, 3, msg.FromUsername, uFile); + break; + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + } + SocketClient skc; + Action<string> lc; + public PCRobotClient(SocketClient skc, Action<string> lc) + { + this.skc = skc; + this.lc = lc; + } + + public PCRobotClient() + { + + } + + + private static PCRobotClient Client; + public static PCRobotClient GetClient() + { + if (Client == null) Client = new PCRobotClient(); + return Client; + } + [DllImport("User32.dll", EntryPoint = "PostMessage")] + public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam); + + [DllImport("LIB.KTY.WC.dll", EntryPoint = "Run")] + public static extern IntPtr Run(string path, string dll, int port); + + private IntPtr DwPid = IntPtr.Zero; + private static readonly object SequenceLock = new object(); + public static WeChatAPI WechatAPI { get; private set; } + public void IniWechat() + { + WechatAPI = new WeChatAPI(); + WechatAPI.sc = new KstAPI.dele_Server_CallBack(Server_CallBack); + WechatAPI.cc = new KstAPI.dele_Client_CallBack(Client_CallBack); + + WechatAPI.Socket_Port = WechatAPI.Socket_Init(Marshal.GetFunctionPointerForDelegate(WechatAPI.sc), Marshal.GetFunctionPointerForDelegate(WechatAPI.cc)); + + if (WechatAPI.Socket_Port == 0) throw new Exception("通信端口创建失败,请重试!"); + + //Console.WriteLine("[初始化完成]" + Environment.NewLine + "服务端口:" + wxAPI.Socket_Port.ToString() + Environment.NewLine + "通信句柄:" + wxAPI.Socket_Handle.ToString()); + + KstAPI.kst_DLLConnect(201906061, WechatAPI.Socket_Port); + } + // private static readonly object SequenceLock = new object(); + HPSocketCS.TcpPackServer HP_Server = new HPSocketCS.TcpPackServer(); + NMHelper nmHeler = new NMHelper(); + NMCore nmCore; + + public IntPtr StartWechat() + { + var path = CsharpHttpHelper.HttpExtend.MapPath("WeChat"); + string szDllPath = System.IO.Directory.GetCurrentDirectory() + "\\NanMuCore.dll"; + DwPid = (IntPtr)NMHelper.NM_CreateWeChatProcess(path, "WeChat.exe", szDllPath, nmHeler.Socket_Port); + //KstAPI.kst_CreateWx(path, "WeChat.exe", "kst.dll",WechatAPI.Socket_Port); + return DwPid; + } + public void CloseWechat() + { + try + { + if (DwPid != IntPtr.Zero) + { + PostMessage(DwPid, 18, 0, 0); + Process[] myproc = Process.GetProcesses(); + foreach (Process item in myproc) + { + try + { + if (item.Id == (int)DwPid) + { + item.Kill(); + break; + } + + } + catch (Exception) + { + } + } + } + } + catch (Exception) + { + } + + } + private void Client_CallBack(int so, int sPoint, int type, int buf, int buflen) + { + + } + + private void Server_CallBack(int sPoint, int so, int type, int buf, int buflen, int cso) + { + try + { + if (type == KstAPI.通信_连接成功) + { + WechatAPI.Wx_Init(so, "C#-20190605"); + WechatAPI.Client_Handle = so; + } + else if (type == KstAPI.通信_连接断开) + { + //int uIndex = FindRowIndex(LOGIN_LIST, so.ToString(), 4); + //if (uIndex != -1) + //{ + //if (so == wxAPI.Client_Handle) + //{ + // LOGIN_TXT_SOCKET.Text = "[未选择]"; + // LOGIN_TXT_NICK.Text = "[未选择]"; + // LOGIN_TXT_WXID.Text = "[未选择]"; + // PIC_HEADIMG.Image = null; + // wxAPI.Client_Handle = 0; + // wxAPI.Client_Wxid = ""; + //} + //LOGIN_LIST.Items.RemoveAt(uIndex); + //} + } + else if (type == KstAPI.通信_数据到达) + { + byte[] s_buf = new byte[buflen + 1]; + KstAPI.RtlMoveMemory(s_buf, buf, buflen); + string s_Recv = Encoding.Default.GetString(s_buf).TrimEnd('\0'); + + //Log(s_Recv); + + JObject recvJson = JObject.Parse(s_Recv); + int RecvType = (int)recvJson["packtype"]; + + if (RecvType == KstAPI.回调_二维码) + { + string B64_QRCode = recvJson["qrcode"].ToString(); + byte[] imageBytes = Convert.FromBase64String(B64_QRCode); + MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length); + ms.Write(imageBytes, 0, imageBytes.Length); + //PIC_HEADIMG.Image = System.Drawing.Image.FromStream(ms, true); + } + else if (RecvType == KstAPI.回调_登录成功) + { + lock (SequenceLock) + { + ListViewItem UserItem = new ListViewItem(); + + UserItem.Text = recvJson["nick"].ToString(); + UserItem.SubItems.Add(recvJson["wxid"].ToString()); + UserItem.SubItems.Add(recvJson["wxno"].ToString()); + UserItem.SubItems.Add(recvJson["himg"].ToString()); + UserItem.SubItems.Add(so.ToString()); + WechatAPI.Client_Nick= recvJson["nick"].ToString(); + WechatAPI.Client_Wxid = recvJson["wxid"].ToString(); + lc?.Invoke(WechatAPI.Client_Nick + $"({ WechatAPI.Client_Wxid})"); + + //LOGIN_LIST.Items.Add(UserItem); + } + } + else if (RecvType == KstAPI.回调_退出登陆) + { + //int uIndex = FindRowIndex(LOGIN_LIST, so.ToString(), 4); + //if (uIndex != -1) + //{ + // if (so == wxAPI.Client_Handle) + // { + // LOGIN_TXT_SOCKET.Text = "[未选择]"; + // LOGIN_TXT_NICK.Text = "[未选择]"; + // LOGIN_TXT_WXID.Text = "[未选择]"; + // PIC_HEADIMG.Image = null; + // wxAPI.Client_Handle = 0; + // wxAPI.Client_Wxid = ""; + // } + // LOGIN_LIST.Items.RemoveAt(uIndex); + //} + } + else if (RecvType == KstAPI.回调_好友列表) + { + JArray uList = recvJson.Value<JArray>("list"); + //FRIEND_LIST.BeginUpdate(); + //FRIEND_GH_LIST.BeginUpdate(); + //GROUP_LIST.BeginUpdate(); + for (int i = 0; i < uList.Count; i++) + { + ListViewItem UserItem = new ListViewItem(); + + WeChatAPI.UserInfo uInfo = new WeChatAPI.UserInfo(); + uInfo.Type = (int)recvJson["list"][i]["Type"]; + uInfo.List = (int)recvJson["list"][i]["List"]; + uInfo.Wxid = recvJson["list"][i]["Wxid"].ToString(); + uInfo.WxNo = recvJson["list"][i]["WxNo"].ToString(); + uInfo.Nick = recvJson["list"][i]["Nick"].ToString(); + uInfo.Nick = KstAPI.DeUnicode(uInfo.Nick); + uInfo.Mark = recvJson["list"][i]["Mark"].ToString(); + uInfo.Mark = KstAPI.DeUnicode(uInfo.Mark); + uInfo.HImg = recvJson["list"][i]["HImg"].ToString(); + + if (uInfo.Type == 8 || uInfo.Type == 24 || uInfo.Type == 29) + {//公众号 + UserItem.Text = uInfo.Nick; + UserItem.SubItems.Add(uInfo.Wxid); + UserItem.SubItems.Add(uInfo.WxNo); + UserItem.SubItems.Add(uInfo.HImg); + //FRIEND_GH_LIST.Items.Add(UserItem); + } + else if (uInfo.Wxid.LastIndexOf("@chatroom") != -1) + {//群 + if (uInfo.Nick == "") + uInfo.Nick = "群聊"; + UserItem.Text = uInfo.Nick; + UserItem.SubItems.Add(uInfo.Wxid); + UserItem.SubItems.Add(uInfo.WxNo); + UserItem.SubItems.Add(uInfo.List.ToString()); + UserItem.SubItems.Add(uInfo.HImg); + //GROUP_LIST.Items.Add(UserItem); + } + else if (uInfo.List != 2) + {//好友 + UserItem.Text = uInfo.Nick; + UserItem.SubItems.Add(uInfo.Mark); + UserItem.SubItems.Add(uInfo.Wxid); + UserItem.SubItems.Add(uInfo.WxNo); + UserItem.SubItems.Add(uInfo.HImg); + //FRIEND_LIST.Items.Add(UserItem); + } + } + //FRIEND_LIST.EndUpdate(); + //FRIEND_GH_LIST.EndUpdate(); + //GROUP_LIST.EndUpdate(); + + //string OutLog = "[刷新好友列表][" + recvJson["mywxid"].ToString() + "]" + Environment.NewLine + + //"好友数:" + FRIEND_LIST.Items.Count.ToString() + Environment.NewLine + + //"公众号:" + FRIEND_GH_LIST.Items.Count.ToString() + Environment.NewLine + + //"群聊数:" + GROUP_LIST.Items.Count.ToString(); + //Log(OutLog); + //Console.WriteLine(OutLog); + + + } + else if (RecvType == KstAPI.回调_群员列表) + { + JArray uList = recvJson.Value<JArray>("list"); + + //GROUP_MEMBER_LIST.BeginUpdate(); + for (int i = 0; i < uList.Count; i++) + { + ListViewItem UserItem = new ListViewItem(); + + UserItem.Text = KstAPI.DeUnicode(recvJson["list"][i]["Nick"].ToString()); + UserItem.SubItems.Add(KstAPI.DeUnicode(recvJson["list"][i]["Mark"].ToString())); + UserItem.SubItems.Add(recvJson["list"][i]["Wxid"].ToString()); + UserItem.SubItems.Add(recvJson["list"][i]["HImg"].ToString()); + + //GROUP_MEMBER_LIST.Items.Add(UserItem); + } + //GROUP_MEMBER_LIST.EndUpdate(); + } + else if (RecvType == KstAPI.回调_接收消息) + { + WeChatAPI.MsgInfo mInfo = new WeChatAPI.MsgInfo(); + mInfo.RecvWxid = recvJson["mywxid"].ToString(); + mInfo.Type = (int)recvJson["type"]; + mInfo.Time = Timestamp2DataTime((int)recvJson["time"]); + mInfo.IsSend = (int)recvJson["isme"]; + mInfo.LocalMsgID = (int)recvJson["msgid"]; + mInfo.ServerMsgID = recvJson["smsgid"].ToString(); + mInfo.Wxid_1 = recvJson["wxid1"].ToString(); + mInfo.Wxid_2 = recvJson["wxid2"].ToString(); + mInfo.Msg = Encoding.Default.GetString(Convert.FromBase64String(recvJson["msg"].ToString())); + mInfo.Msg = KstAPI.DeUnicode(mInfo.Msg); + mInfo.Source = Encoding.Default.GetString(Convert.FromBase64String(recvJson["source"].ToString())); + + if (mInfo.Type==1) + { + if (skc != null) + { + WechatReceiveMsg msg = new WechatReceiveMsg(); + msg.Cmd = PCRobotCMD.rcvTxt; + msg.RobotUsername = recvJson["mywxid"].ToString(); + msg.RobotUsernick = WechatAPI.Client_Nick; + + msg.RobotType = RobotType.客户端微信; + msg.FromMessageType = WechatMsgType.文本; + msg.FromUsername = recvJson["wxid1"].ToString(); + if (msg.FromUsername.Contains("@chatroom")) + { + msg.FromGroupid= recvJson["wxid1"].ToString(); + } + mInfo.Msg = Encoding.Default.GetString(Convert.FromBase64String(recvJson["msg"].ToString())); + mInfo.Msg = KstAPI.DeUnicode(mInfo.Msg); + msg.FromMessage = mInfo.Msg; + msg.FromUsernick = ""; + skc.Send(msg); + } + } + + string OutLog; + if (mInfo.IsSend == 0) + OutLog = "[接收消息]"; + else + OutLog = "[发送消息]"; + + OutLog += "[" + mInfo.Time + "][" + mInfo.RecvWxid + "]" + Environment.NewLine + + "Type:" + mInfo.Type.ToString() + Environment.NewLine + + "消息ID:" + mInfo.LocalMsgID.ToString() + Environment.NewLine + + "服务ID:" + mInfo.ServerMsgID + Environment.NewLine + + "Wxid_1:" + mInfo.Wxid_1 + Environment.NewLine + + "Wxid_2:" + mInfo.Wxid_2 + Environment.NewLine + + //"消息内容:" + mInfo.Msg + " | " + temmsg + Environment.NewLine + + "消息内容:" + mInfo.Msg + Environment.NewLine + + "附加内容:" + mInfo.Source; + + + //Log(OutLog); + Console.WriteLine(OutLog); + + if (mInfo.Type == 37)//好友请求 + { + //if (CHK_ADDFRIEND.Checked == true)//通过好友请求 + //{ + // string Add_v1 = StrBetween(mInfo.Msg, "encryptusername=\"", "\" fromnickname="); + // string Add_v2 = StrBetween(mInfo.Msg, "ticket=\"", "\" opcode="); + // wxAPI.Wx_AddFriend(so, 3, 14, Add_v1, Add_v2, ""); + //} + } + else if (mInfo.Type == 49 && mInfo.Msg.IndexOf("微信转账") != -1 && mInfo.Msg.IndexOf("收到转账") != -1) + { + //if (CHK_MONEY.Checked == true)//接收转账 + //{ + // string sState = StrBetween(mInfo.Msg, "<paysubtype>", "</paysubtype>"); + // string sTranID = StrBetween(mInfo.Msg, "transferid><![CDATA[", "]]></transferid>"); + // string sTime = StrBetween(mInfo.Msg, "<invalidtime><![CDATA[", "]]></invalidtime>"); + // if (sState == "1" && mInfo.IsSend == 0) + // wxAPI.Wx_GetMoney(so, mInfo.Wxid_1, sTranID, int.Parse(sTime)); + + //} + } + else if (mInfo.Type == 49 && mInfo.Msg.IndexOf("邀请你加入群聊") != -1 && mInfo.IsSend == 0) + { + //if (CHK_INVITE.Checked == true)//自动通过群聊邀请 + //{ + // string inviteURL = StrBetween(mInfo.Msg, "<url><![CDATA[", "]]></url>"); + // if (inviteURL != "") + // wxAPI.Wx_GetA8Key(so, 1, mInfo.Wxid_1, inviteURL); + //} + } + } + else if (RecvType == KstAPI.回调_语音消息 || + RecvType == KstAPI.回调_视频消息 || + RecvType == KstAPI.回调_文件消息|| RecvType == KstAPI.回调_图片消息) + { + WeChatAPI.MsgInfo mInfo = new WeChatAPI.MsgInfo(); + mInfo.RecvWxid = recvJson["mywxid"].ToString(); + mInfo.Type = (int)recvJson["type"]; + mInfo.Time = Timestamp2DataTime((int)recvJson["time"]); + mInfo.IsSend = (int)recvJson["isme"]; + mInfo.LocalMsgID = (int)recvJson["msgid"]; + mInfo.ServerMsgID = recvJson["smsgid"].ToString(); + mInfo.Wxid_1 = recvJson["wxid1"].ToString(); + mInfo.Wxid_2 = recvJson["wxid2"].ToString(); + mInfo.Msg = Encoding.Default.GetString(Convert.FromBase64String(recvJson["msg"].ToString())); + if (RecvType == KstAPI.回调_语音消息) + { + byte[] silkByte = Convert.FromBase64String(recvJson["source"].ToString()); + //mInfo.Source = SaveFile(mInfo.RecvWxid, mInfo.Wxid_1, "VOICE", mInfo.ServerMsgID, "silk", silkByte); + } + else if (RecvType == KstAPI.回调_图片消息) + { + //byte[] ImageByte = Convert.FromBase64String(recvJson["source"].ToString()); + //mInfo.Source = SaveFile(mInfo.RecvWxid, mInfo.Wxid_1, "IMAGE", mInfo.ServerMsgID, "jpg", ImageByte); + + //string MaxPicPath = mInfo.Source.Replace(mInfo.ServerMsgID, mInfo.ServerMsgID + "_MAX"); + + //if (skc != null && skc.IsConnected) + //{ + // WechatReceiveMsg msg = new WechatReceiveMsg(); + // msg.Cmd = ClientCMD.rcvImg; + + // msg.FromMessage = recvJson["source"].ToString(); + // msg.FromUsernick = ""; + // skc.Send(msg); + //} + //if (CHK_PIC.Checked == true) + // //wxAPI.DownLoadPic(so, mInfo.Msg, MaxPicPath); + // wxAPI.DownLoadPic(so, mInfo.Msg, "C:\\rra\\MAX_.jpg"); + } + else + { + mInfo.Source = recvJson["source"].ToString(); + } + + + string OutLog; + if (mInfo.IsSend == 0) + OutLog = "[接收消息]"; + else + OutLog = "[发送消息]"; + + OutLog += "[" + mInfo.Time + "][" + mInfo.RecvWxid + "]" + Environment.NewLine + + "Type:" + mInfo.Type.ToString() + Environment.NewLine + + "消息ID:" + mInfo.LocalMsgID.ToString() + Environment.NewLine + + "服务ID:" + mInfo.ServerMsgID + Environment.NewLine + + "Wxid_1:" + mInfo.Wxid_1 + Environment.NewLine + + "Wxid_2:" + mInfo.Wxid_2 + Environment.NewLine + + "消息内容:" + mInfo.Msg + Environment.NewLine + + "文件路径:" + mInfo.Source; + //Log(OutLog); + Console.WriteLine(OutLog); + } + else if (RecvType == KstAPI.回调_添加好友) + { + string RecvWxid = recvJson["mywxid"].ToString(); + int uType = (int)recvJson["id"]; + int uSource = (int)recvJson["scene"]; + string uWxid = recvJson["wxid"].ToString(); + //Log("[添加好友][" + RecvWxid + "]" + Environment.NewLine + "返回类型:" + uType.ToString() + Environment.NewLine + + Console.WriteLine("[添加好友][" + RecvWxid + "]" + Environment.NewLine + "返回类型:" + uType.ToString() + Environment.NewLine + + "添加来源:" + uSource.ToString() + Environment.NewLine + + "添加Wxid:" + uWxid); + if (uType == -44)//需要验证 + { + //wxAPI.Wx_AddFriend(so, 2, uSource, uWxid, "", FRI_TXT_MSG.Text); + } + } + else if (RecvType == KstAPI.回调_下载信息) + { + WeChatAPI.UserInfo uInfo = new WeChatAPI.UserInfo(); + uInfo.Wxid = recvJson["info"]["Wxid"].ToString(); + uInfo.WxNo = recvJson["info"]["WxNo"].ToString(); + uInfo.Nick = recvJson["info"]["Nick"].ToString(); + uInfo.Nick = KstAPI.DeUnicode(uInfo.Nick); + uInfo.V1 = recvJson["info"]["v1"].ToString(); + uInfo.HImg = recvJson["info"]["HImg"].ToString(); + uInfo.Sex = uInfo.GetSex((int)recvJson["info"]["Sex"]); + uInfo.Address = recvJson["info"]["Address"].ToString(); + string OutLog = "[详细信息][" + recvJson["mywxid"].ToString() + "]" + Environment.NewLine + + "Wxid:" + uInfo.Wxid + Environment.NewLine + + "微信号:" + uInfo.WxNo + Environment.NewLine + + "昵称:" + uInfo.Nick + Environment.NewLine + + "性别:" + uInfo.Sex + Environment.NewLine + + "地区:" + uInfo.Address + Environment.NewLine + + "v1:" + uInfo.V1 + Environment.NewLine + + "头像:" + uInfo.HImg; + //Log(OutLog); + Console.WriteLine(OutLog); + } + else if (RecvType == KstAPI.回调_建群返回) + { + string cdata = recvJson["data"].ToString(); + string RecvWxid = recvJson["mywxid"].ToString(); + if (cdata == "Everything is OK") + { + string OutLog = "[建群返回][" + RecvWxid + "]" + Environment.NewLine; + string GroupID = recvJson["gid"].ToString(); + OutLog += "群ID:" + GroupID + Environment.NewLine + "成员:" + Environment.NewLine; + JArray mList = recvJson.Value<JArray>("list"); + for (int i = 0; i < mList.Count; i++) + { + string uWxid = recvJson["list"][i]["wxid"].ToString(); + string uState = recvJson["list"][i]["status"].ToString(); + if (uState == "1") + OutLog += "成功 --> " + uWxid + Environment.NewLine; + else + OutLog += "失败 --> " + uWxid + Environment.NewLine; + } + //Log(OutLog); + Console.WriteLine(OutLog); + } + else + //Log("[建群返回][" + RecvWxid + "]" + Environment.NewLine + "建群失败!"); + Console.WriteLine("[建群返回][" + RecvWxid + "]" + Environment.NewLine + "建群失败!"); + } + else if (RecvType == KstAPI.回调_A8Key) + { + string RecvWxid = recvJson["mywxid"].ToString(); + string LastURL = recvJson["lasturl"].ToString(); + string NowURL = recvJson["url"].ToString(); + //Log("[GetA8Key][" + RecvWxid + "]" + Environment.NewLine + "访问链接:" + LastURL + Environment.NewLine + "返回链接:" + NowURL); + Console.WriteLine("[GetA8Key][" + RecvWxid + "]" + Environment.NewLine + "访问链接:" + LastURL + Environment.NewLine + "返回链接:" + NowURL); + if (NowURL.IndexOf("addchatroombyinvite") != -1) + { + HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(NowURL); + Request.Method = "POST"; + Request.AllowAutoRedirect = false; + Request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; + Request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.556.400 QQBrowser/9.0.2524.400"; + Request.Referer = NowURL; + Request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8,en-us;q=0.6,en;q=0.5;q=0.4"); + HttpWebResponse Response = (HttpWebResponse)Request.GetResponse(); + string hLocation = Response.GetResponseHeader("Location").ToString(); + if (hLocation != "") + { + if (hLocation.IndexOf("chatroom") != -1) + { + string GroupID = StrBetween(hLocation, "weixin://jump/mainframe/", "@chatroom"); + //Log("[入群成功][" + RecvWxid + "]" + Environment.NewLine + "群号:" + GroupID + "@chatroom"); + Console.WriteLine("[入群成功][" + RecvWxid + "]" + Environment.NewLine + "群号:" + GroupID + "@chatroom"); + } + } + } + } + else if (RecvType == KstAPI.回调_聊天对象) + { + WeChatAPI.UserInfo uInfo = new WeChatAPI.UserInfo(); + uInfo.Wxid = recvJson["wxid"].ToString(); + uInfo.WxNo = recvJson["wxno"].ToString(); + uInfo.Nick = recvJson["nick"].ToString(); + uInfo.Nick = KstAPI.DeUnicode(uInfo.Nick); + uInfo.Mark = recvJson["mark"].ToString(); + uInfo.Mark = KstAPI.DeUnicode(uInfo.Mark); + uInfo.HImg = recvJson["himg"].ToString(); + + string OutLog = "[聊天对象][" + recvJson["mywxid"].ToString() + "]" + Environment.NewLine + + "Wxid:" + uInfo.Wxid + Environment.NewLine + + "微信号:" + uInfo.WxNo + Environment.NewLine + + "昵称:" + uInfo.Nick + Environment.NewLine + + "备注:" + uInfo.Mark + Environment.NewLine + + "头像:" + uInfo.HImg; + //Log(OutLog); + Console.WriteLine(OutLog); + } + } + } + catch (Exception ex) + { + // MessageBox.Show(ex.Message, "启动失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + Console.WriteLine("Server_CallBack ERROR:"+ex.Message); + } + } + + private string StrBetween(string sText, string sLeft, string sRight) + { + try + { + int i = sText.IndexOf(sLeft) + sLeft.Length; + string temp = sText.Substring(i, sText.IndexOf(sRight, i) - i); + return temp; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "启动失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + return string.Empty; + } + + private string Timestamp2DataTime(long Timestamp) + { + System.DateTime dtDateTime = new DateTime(1970, 1, 1, 8, 0, 0, 0); + dtDateTime = dtDateTime.AddSeconds(Timestamp).ToLocalTime(); + return dtDateTime.ToString("yyyy-MM-dd HH:mm:ss"); + } + + //public void SendSocket(ClientCMD CMD, object json) + //{ + + //} + //public void SendSocket(ClientCMD CMD) + //{ + // this.SendSocket(CMD,string.Empty); + //} + //WeChatAPI wxAPI = new WeChatAPI(); + //public void ServerRequest() + //{ + // XxType XxType = new XxType(); + // string msg = ""; + // string wxid = ""; + // switch (XxType) + // { + // case XxType.语音消息: + // break; + // case XxType.文件消息: + + // break; + // case XxType.视频消息: + // break; + // case XxType.图片消息: + // break; + // case XxType.文字消息: + // string uMessage = KstAPI.EnUnicode(msg); + // WechatAPI.Wx_SendTextMsg(WechatAPI.Client_Handle, wxid, uMessage, uMessage); + // break; + // } + + + //} + + + } +} diff --git a/PCRobot/PCRobotForm.Designer.cs b/PCRobot/PCRobotForm.Designer.cs new file mode 100644 index 0000000..4368eea --- /dev/null +++ b/PCRobot/PCRobotForm.Designer.cs @@ -0,0 +1,542 @@ +namespace PCRobot +{ + partial class PCRobotForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PCRobotForm)); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.label7 = new System.Windows.Forms.Label(); + this.button6 = new System.Windows.Forms.Button(); + this.button5 = new System.Windows.Forms.Button(); + this.button8 = new System.Windows.Forms.Button(); + this.button4 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除微信ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.button1 = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.button7 = new System.Windows.Forms.Button(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.status = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.易转发 = new System.Windows.Forms.NotifyIcon(this.components); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.label5 = new System.Windows.Forms.Label(); + this.timer2 = new System.Windows.Forms.Timer(this.components); + this.timer3 = new System.Windows.Forms.Timer(this.components); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.contextMenuStrip1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.SuspendLayout(); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(635, 394); + this.tabControl1.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + this.tabControl1.TabIndex = 1; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.label7); + this.tabPage1.Controls.Add(this.button6); + this.tabPage1.Controls.Add(this.button5); + this.tabPage1.Controls.Add(this.button8); + this.tabPage1.Controls.Add(this.button4); + this.tabPage1.Controls.Add(this.button3); + this.tabPage1.Controls.Add(this.button2); + this.tabPage1.Controls.Add(this.listView1); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(627, 368); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "微信客户端"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label7.Location = new System.Drawing.Point(185, 183); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(240, 16); + this.label7.TabIndex = 6; + this.label7.Text = "正在识别已登录微信,请稍等...."; + this.label7.Visible = false; + // + // button6 + // + this.button6.Location = new System.Drawing.Point(498, 12); + this.button6.Name = "button6"; + this.button6.Size = new System.Drawing.Size(104, 27); + this.button6.TabIndex = 5; + this.button6.Text = "打开软件目录"; + this.button6.UseVisualStyleBackColor = true; + this.button6.Click += new System.EventHandler(this.button6_Click); + // + // button5 + // + this.button5.Location = new System.Drawing.Point(107, 12); + this.button5.Name = "button5"; + this.button5.Size = new System.Drawing.Size(88, 27); + this.button5.TabIndex = 4; + this.button5.Text = "企业微信登陆"; + this.button5.UseVisualStyleBackColor = true; + this.button5.Click += new System.EventHandler(this.button5_Click); + // + // button8 + // + this.button8.Location = new System.Drawing.Point(401, 12); + this.button8.Name = "button8"; + this.button8.Size = new System.Drawing.Size(88, 27); + this.button8.TabIndex = 3; + this.button8.Text = "清理系统缓存"; + this.button8.UseVisualStyleBackColor = true; + this.button8.Click += new System.EventHandler(this.button8_Click); + // + // button4 + // + this.button4.Location = new System.Drawing.Point(304, 12); + this.button4.Name = "button4"; + this.button4.Size = new System.Drawing.Size(88, 27); + this.button4.TabIndex = 3; + this.button4.Text = "检查更新"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // button3 + // + this.button3.Location = new System.Drawing.Point(206, 12); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(88, 27); + this.button3.TabIndex = 2; + this.button3.Text = "全部退出登陆"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(12, 12); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(88, 27); + this.button2.TabIndex = 1; + this.button2.Text = "个人微信登陆"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // listView1 + // + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader5, + this.columnHeader2, + this.columnHeader3, + this.columnHeader6, + this.columnHeader4, + this.columnHeader1}); + this.listView1.ContextMenuStrip = this.contextMenuStrip1; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HideSelection = false; + this.listView1.Location = new System.Drawing.Point(3, 53); + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(620, 311); + this.listView1.TabIndex = 0; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged); + // + // columnHeader5 + // + this.columnHeader5.Text = "序号"; + this.columnHeader5.Width = 40; + // + // columnHeader2 + // + this.columnHeader2.Text = "微信ID"; + this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader2.Width = 130; + // + // columnHeader3 + // + this.columnHeader3.Text = "微信昵称"; + this.columnHeader3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader3.Width = 200; + // + // columnHeader6 + // + this.columnHeader6.Text = "类型"; + this.columnHeader6.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // columnHeader4 + // + this.columnHeader4.Text = "版本号"; + this.columnHeader4.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader4.Width = 120; + // + // columnHeader1 + // + this.columnHeader1.Text = "协议"; + this.columnHeader1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除微信ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 26); + // + // 删除微信ToolStripMenuItem + // + this.删除微信ToolStripMenuItem.Name = "删除微信ToolStripMenuItem"; + this.删除微信ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.删除微信ToolStripMenuItem.Text = "删除微信"; + this.删除微信ToolStripMenuItem.Click += new System.EventHandler(this.删除微信ToolStripMenuItem_Click); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.groupBox2); + this.tabPage2.Controls.Add(this.button1); + this.tabPage2.Controls.Add(this.groupBox1); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(627, 368); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "设置"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.checkBox1); + this.groupBox2.Location = new System.Drawing.Point(118, 20); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(407, 64); + this.groupBox2.TabIndex = 8; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "其他设置"; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(35, 29); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(336, 16); + this.checkBox1.TabIndex = 7; + this.checkBox1.Text = "开启防微信消息延迟功能(注:会模拟切换点击微信界面)"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(149, 310); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(306, 33); + this.button1.TabIndex = 6; + this.button1.Text = "连接服务器"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.textBox3); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(118, 106); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(407, 186); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "通信設置"; + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(80, 143); + this.textBox3.Name = "textBox3"; + this.textBox3.PasswordChar = '*'; + this.textBox3.Size = new System.Drawing.Size(249, 21); + this.textBox3.TabIndex = 5; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(80, 94); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(249, 21); + this.textBox2.TabIndex = 4; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(80, 44); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(249, 21); + this.textBox1.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(33, 146); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(41, 12); + this.label3.TabIndex = 2; + this.label3.Text = "秘钥:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(33, 97); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(41, 12); + this.label2.TabIndex = 1; + this.label2.Text = "端口:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(45, 50); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(29, 12); + this.label1.TabIndex = 0; + this.label1.Text = "IP:"; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.checkBox2); + this.tabPage3.Controls.Add(this.button7); + this.tabPage3.Controls.Add(this.richTextBox1); + this.tabPage3.Controls.Add(this.label6); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(627, 368); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "隐藏设置"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(75, 175); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(132, 16); + this.checkBox2.TabIndex = 3; + this.checkBox2.Text = "自动处理会话为已读"; + this.checkBox2.UseVisualStyleBackColor = true; + // + // button7 + // + this.button7.Location = new System.Drawing.Point(222, 328); + this.button7.Name = "button7"; + this.button7.Size = new System.Drawing.Size(141, 34); + this.button7.TabIndex = 2; + this.button7.Text = "应用并保存"; + this.button7.UseVisualStyleBackColor = true; + this.button7.Click += new System.EventHandler(this.button7_Click); + // + // richTextBox1 + // + this.richTextBox1.Location = new System.Drawing.Point(23, 44); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.Size = new System.Drawing.Size(541, 93); + this.richTextBox1.TabIndex = 1; + this.richTextBox1.Text = ""; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(22, 27); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(125, 12); + this.label6.TabIndex = 0; + this.label6.Text = "允许接收的消息类型:"; + // + // status + // + this.status.Location = new System.Drawing.Point(60, 397); + this.status.Name = "status"; + this.status.Size = new System.Drawing.Size(399, 21); + this.status.TabIndex = 4; + this.status.Text = "准备就绪"; + this.status.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Font = new System.Drawing.Font("宋体", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label4.Location = new System.Drawing.Point(2, 400); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(52, 14); + this.label4.TabIndex = 3; + this.label4.Text = "状态:"; + // + // 易转发 + // + this.易转发.Icon = ((System.Drawing.Icon)(resources.GetObject("易转发.Icon"))); + this.易转发.Text = "易转发 - 双击我显示窗口"; + this.易转发.DoubleClick += new System.EventHandler(this.易转发_DoubleClick); + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 77000000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(464, 402); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(41, 12); + this.label5.TabIndex = 5; + this.label5.Text = "label5"; + // + // timer2 + // + this.timer2.Enabled = true; + this.timer2.Interval = 6000; + this.timer2.Tick += new System.EventHandler(this.timer2_Tick); + // + // timer3 + // + this.timer3.Enabled = true; + this.timer3.Interval = 60000; + this.timer3.Tick += new System.EventHandler(this.timer3_Tick); + // + // PCRobotForm + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(635, 422); + this.Controls.Add(this.label5); + this.Controls.Add(this.status); + this.Controls.Add(this.label4); + this.Controls.Add(this.tabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.Name = "PCRobotForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = " "; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.PCRobotForm_FormClosing); + this.Load += new System.EventHandler(this.PCRobotForm_Load); + this.SizeChanged += new System.EventHandler(this.PCRobotForm_SizeChanged); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage1.PerformLayout(); + this.contextMenuStrip1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label status; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.NotifyIcon 易转发; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除微信ToolStripMenuItem; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.Button button5; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.Button button6; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Timer timer2; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Button button7; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.Button button8; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.Timer timer3; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.GroupBox groupBox2; + } +} \ No newline at end of file diff --git a/PCRobot/PCRobotForm.cs b/PCRobot/PCRobotForm.cs new file mode 100644 index 0000000..c4595f3 --- /dev/null +++ b/PCRobot/PCRobotForm.cs @@ -0,0 +1,1092 @@ +using CsharpHttpHelper; +using PCRobot.Pack; +using PCRobot.PCWechat; +using PCRobot.Utils; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using PCRobot.PCWechat.Enterprise; +using PCRobot.PCWechat.Routine; + +namespace PCRobot +{ + public partial class PCRobotForm : Form + { + /// <summary> + /// 微信关闭事件触发的委托,实现主窗体弹窗 + /// </summary> + public static Action<string> ErrorMessAction; + + public PCRobotForm() + { + InitializeComponent(); + } + + /// <summary> + /// 允许上传的接口 + /// </summary> + public static List<string> AnalysisTypes = new List<string>(); + + public static bool IsHaveRead = false; + + private void PCRobotForm_Load(object sender, EventArgs e) + { + try + { + //var file = @"C:\Users\XianSenWu\Documents\WeChat Files\wxid_b9qk6hpmh0s812\config\AccInfo.dat"; + //var fileStream = File.ReadAllBytes(file); + + //var text = Encoding.UTF8.GetString(fileStream); + //Console.WriteLine(text); + + //var nickbyte = Encoding.UTF8.GetBytes("小张晚安"); + + //Console.WriteLine(); + + try + { + List<string> files = new List<string>(); + files.Add(HttpExtend.MapFile(@"7l_0W.exe")); + files.Add(HttpExtend.MapFile(@"OnlineUpdate.exe")); + files.Add(HttpExtend.MapFile(@"OnlineUpdate.xml")); + files.Add(HttpExtend.MapFile(@"VersionUpdate.exe")); + files.Add(HttpExtend.MapFile(@"VersionUpdate.xml")); + files.Add(HttpExtend.MapFile(@"OnlineUpdate.exe")); + //files.Add(Util.MapFile(@"WeiQ.Framework.dll", @"Assembly\apifile")); + //files.Add(Util.MapFile(@"Browser.dll", @"Assembly\apifile\Library")); + foreach (var item in files) + { + try + { + File.Delete(item); + } + catch (Exception ex) + { } + } + } + catch (Exception) + { } + + try + { + //删除缓存目录 + Common.DeleteDir(HttpExtend.MapPath(@"Cache")); + LogHelper.GetSingleObj().Info("删除缓存目录", $"定时删除缓存目录执行完毕"); + } + catch (Exception) + { + LogHelper.GetSingleObj().Info("删除缓存目录", $"定时删除缓存目录执行失败"); + } + + Wechat_Xiaoxie.ClickEvent += SystemLoginWechat; + + IniData(); + this.label5.Text = "版本:" + Common.CurVersion; + //MessageBox.Show("版本:" + Common.CurVersion); + + if (Config.GetValue("设置", "内部").ToUpper() == "TRUE") + { + #region 需要解析的微信消息 + var temp = "MT_USER_LOGIN,MT_USER_LOGOUT,MT_DATA_CHATROOM_MEMBERS_MSG,MT_DATA_CHATROOMS_MSG,MT_DATA_FRIENDS_MSG,MT_DATA_WXID_MSG"; + if (Common.AppConfig_ExistItem("AnalysisTypes")) + temp = Common.AppConfig_Get("AnalysisTypes"); + else + Common.AppConfig_Add("AnalysisTypes", temp); + + AnalysisTypes = temp.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim().ToUpper()).ToList(); + richTextBox1.Text = Common.AppConfig_Get("AnalysisTypes"); + #endregion + + #region 自动处理会话已读 + var temp2 = "0"; + if (Common.AppConfig_ExistItem("IsHaveRead")) + temp2 = Common.AppConfig_Get("IsHaveRead"); + else + Common.AppConfig_Add("IsHaveRead", "0"); + IsHaveRead = checkBox2.Checked = temp2 == "1"; + #endregion + + if (!Common.AppConfig_ExistItem("RunAppName")) + Common.AppConfig_Add("RunAppName", "易转发"); + } + else + tabPage3.Parent = null; + + if (!Common.AppConfig_ExistItem("设置")) + Common.AppConfig_Add("设置", "静态"); + + checkBox1.Checked = Config.GetValue("设置", "静态").ToUpper() != "TRUE"; + + ErrorMessAction = ErrorMess; + + //设置标题 + var title = Regex.Replace(Process.GetCurrentProcess().MainModule.ModuleName, ".exe", "", RegexOptions.IgnoreCase); + if (string.IsNullOrWhiteSpace(title) || title.Contains("易转发")) + title = Util.GetRandomString(5); + this.Text = title; + //this.Text = Guid.NewGuid().ToString("N"); + + //自动切换聊天对象 + var th = new Thread(OnHandle); + th.IsBackground = true; + th.Start(); + } + catch (Exception ex) + { } + } + + /// <summary> + /// 切换聊天对象 + /// </summary> + private void OnHandle() + { + return; + List<string> userNameList = new List<string>() { "newsapp", "weixin", "notifymessage" }; + while (true) + { + try + { + Thread.Sleep(1000 * (new Random(Guid.NewGuid().GetHashCode()).Next(120, 300))); + + var users = WechatClient.Users.Values.ToList(); + if (users.Count <= 0) + { + continue; + } + + if (Config.GetValue("设置", "静态").ToUpper() == "TRUE") + { + continue; + } + + foreach (var user in users) + { + try + { + var client = WechatClient.GetApi(user); + if (client != null) + { + if (client.User.Type == WechatType.Xiaoxie_QY) + { + continue; + } + + var robot = client as Wechat_Xiaoxie; + if (robot != null) + { + var index = new Random(Guid.NewGuid().GetHashCode()).Next(0, userNameList.Count - 1); + robot.ToChatWindow(userNameList[index]); + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("激活", ex.Message); + } + } + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("激活", ex.Message); + } + } + } + + private void SystemLoginWechat(string TagName, string TagMsg) + { + this.Invoke(new Action(delegate + { + if (TagName == "开始登录") + { + this.label7.Text = TagMsg; + this.label7.Visible = true; + } + else this.label7.Visible = false; + })); + } + + private void ErrorMess(string mess) + { + try + { + MessageBox.Show(mess); + } + catch (Exception ex) + { } + } + + //易转发,被双击 + private void 易转发_DoubleClick(object sender, EventArgs e) + { + this.Visible = true; + this.WindowState = FormWindowState.Normal; + this.ShowInTaskbar = true; + } + + //窗体发生改变 + private void PCRobotForm_SizeChanged(object sender, EventArgs e) + { + //判断是否选择的是最小化按钮 + if (WindowState == FormWindowState.Minimized) + { + //托盘显示图标等于托盘图标对象 + //注意notifyIcon1是控件的名字而不是对象的名字 + this.易转发.Visible = true; + + //隐藏任务栏区图标 + this.ShowInTaskbar = false; + } + else this.易转发.Visible = false; + } + + IniHelper Config = null; + //初始化界面 + private void IniData() + { + try + { + var fileName = HttpExtend.MapFile("服务器配置.ini", "Config"); + Config = new IniHelper(fileName); + textBox1.Text = Config.GetValue("服务器信息", "IP"); + textBox2.Text = Config.GetValue("服务器信息", "Port"); + textBox3.Text = Config.GetValue("秘钥", "SecretKey"); + WechatClient.IsDebug = Config.GetValue("设置", "调试").ToUpper() == "TRUE"; + try + { + var typeStr = Config.GetValue("设置", "备用").ToLower(); + if (!string.IsNullOrWhiteSpace(typeStr)) + { + BeiyongType type; + if (!Enum.TryParse<BeiyongType>(typeStr, out type)) + WechatClient.BeiYongT = BeiyongType.正版; + else + WechatClient.BeiYongT = type; + } + } + catch (Exception) + { } + + WechatClient.IsGzh = Config.GetValue("设置", "公众号").ToUpper() == "TRUE"; + WechatClient.IsLog = Config.GetValue("设置", "日志").ToUpper() == "TRUE"; + + WechatClient.RefUserEvent = RefUserMethod; + WechatClient.Install();//安装微信,初始化注入 + + EasySoc.GetSocket().Connection(Config.GetValue("服务器信息", "IP"), Convert.ToInt32(string.IsNullOrWhiteSpace(Config.GetValue("服务器信息", "Port")) ? "443" : Config.GetValue("服务器信息", "Port")), RcvServerSuccess, RcvServerError, Config.GetValue("秘钥", "SecretKey"), RcvServerState); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("加载窗体 ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + //更新状态信息 + private void RcvServerState(string str) + { + if (!string.IsNullOrEmpty(str)) + { + try + { + if (!str.EndsWith("连接成功.")) + LogHelper.GetSingleObj().Info("系统日志", $"{str}"); + this.Invoke(new Action(() => + { + status.Text = str; + if (str.Contains("成功")) + { + this.groupBox1.Enabled = false; + this.button1.Text = "断开服务器"; + } + else + { + this.groupBox1.Enabled = true; + this.button1.Text = "连接服务器"; + } + })); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Info("系统日志", $"{str}"); + LogHelper.GetSingleObj().Error("sc ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + } + + //服务器连接失败 + private void RcvServerError(Exception obj) + { + try + { + LogHelper.GetSingleObj().Info("连接异常1", $"{obj.Message}"); + RcvServerState("连接异常:" + obj.Message); + EasySoc.GetSocket().Close(); + } + catch (Exception) + { + } + } + + /// <summary> + /// 处理服务器消息 + /// </summary> + /// <param name="_str"></param> + private void RcvServerSuccess(string _key, string _str) + { + var str = _str; + var key = _key; + //var method = new Action(delegate () + //{ + ThreadPool.QueueUserWorkItem(z => + { + + try + { + var socketClient = EasySoc.GetSocket(); + try + { + //head = head.Replace("HeartBreak", "heartBreak"); + var cmd = (PCRobotCMD)Enum.Parse(typeof(PCRobotCMD), key); + + #region 远程更新 + if (cmd == PCRobotCMD.updateApp) + { + try + { + var LastData = UpdateClient.GetCloudFileHist(); + if (!string.IsNullOrWhiteSpace(LastData)) + { + Process.Start("检查更新.exe", "易转发.exe"); + LogHelper.GetSingleObj().Info("远程更新退出", $"收到远程更新请求,退出程序"); + Thread.Sleep(500); + Program.Exit(); + } + } + catch (Exception ex) + { } + } + #endregion + + var text = PackTool.DecompressString(str); + + //if (WechatClient.IsDebug) LogHelper.GetSingleObj().Debug("调试", $"服务器响应 -> {text}"); + var data = Util.JsonToObject<ServerWechatMsg>(text) as ServerWechatMsg; + if (data.Cmd == PCRobotCMD.getlogincode) + { + var getLCdata = Util.JsonToObject<LoginCodeMsg>(text) as LoginCodeMsg; + if (getLCdata != null) + { + try + { + if (getLCdata.Data == "-1") + { + if (getLCdata.RobotType == RobotType.客户端微信) + Wechat_Xiaoxie.LoginQrcode(getLCdata.RobotUsername, getLCdata.MsgId); + else if (getLCdata.RobotType == RobotType.客户端企业微信) + Wechat_Xiaoxie_QY.LoginQrcode(getLCdata.MsgId); + } + else + { + if (getLCdata.RobotType == RobotType.客户端微信) + Wechat_Xiaoxie.WaitLoginResult.Add(getLCdata.Data, getLCdata.MsgId); + else if (getLCdata.RobotType == RobotType.客户端企业微信) + Wechat_Xiaoxie_QY.WaitLoginResult.Add(getLCdata.Data, getLCdata.MsgId); + } + } + catch (Exception) + { } + } + return; + } + if (data.Key != socketClient.key) return; + var wechatUser = WechatClient.Users.FirstOrDefault(f => f.Key == data.RobotUsername.ToString()).Value; + if (wechatUser == null) return; + //data.MsgId; + //通过用户,获取对应的API,执行相应的函数 + var api = WechatClient.GetApi(wechatUser); + api.ServerMsgID = data.MsgId; + switch (cmd) + { + case PCRobotCMD.sendVideo: + api.SendVideo(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.sendTxt: + api.SendMessage(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.sendProgramMessage: + api.SendProgramMessage(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.sendFile: + api.SendFile(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.sendImg: + api.SendImage(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.agreeFriend: + api.AcceptFriend(data.ToMessage); + break; + case PCRobotCMD.sendCard: + case PCRobotCMD.sendInviteGroup: + api.SendCard(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.getContact: + api.GetContact(true); + break; + case PCRobotCMD.getGroupsNotInMember: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie)?.GetGroupsNotInMember(); + break; + case PCRobotCMD.getZombie: + { + if (api.GetType() == typeof(Wechat_Xiaoxie)) + { + var qy = api as Wechat_Xiaoxie; + qy.CheckZombiz(); + } + } + break; + case PCRobotCMD.getGroupMember: + api.GetGroupMemberInfo(data.ToMessage); + break; + case PCRobotCMD.getPay: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).AcceptFriendTransfer(data.ToMessage); + break; + case PCRobotCMD.deleteFriend: + api.DeleteFriend(data.ToMessage); + break; + case PCRobotCMD.editContacts: + api.ModifyFriendRemark(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.stateOpt: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).ModifyChatTop(data.ToUsername, int.Parse(data.ToMessage) == 1); + break; + case PCRobotCMD.getWxidInfo: + api.Ser_GetContact(data.ToMessage); + break; + case PCRobotCMD.getGroupWxidInfo://类型:图片表示不刷新,文件表示刷新 + api.GetFriendInfo(data.ToMessage, data.ToUsername, data.ToMessageType == WechatMsgType.文件); + break; + case PCRobotCMD.closeWechat: + api.OutLogin(data.ToMessage); + break; + case PCRobotCMD.inviteIntoGroup: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).InviteMemberToGroup_40Up(data.ToMessage, new string[] { data.ToUsername }); + else + (api as Wechat_Xiaoxie_QY).InviteMemberToGroup(data.ToMessage, new string[] { data.ToUsername }); + break; + case PCRobotCMD.inviteIntoGroup_40Down: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).InviteMemberToGroup_40Down(data.ToMessage, new string[] { data.ToUsername }); + else + (api as Wechat_Xiaoxie_QY).InviteMemberToGroup(data.ToMessage, new string[] { data.ToUsername }); + break; + case PCRobotCMD.createRoom: + if (string.IsNullOrWhiteSpace(data.ToMessage)) return; + var wxids = data.ToMessage.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + api.Ser_CreateGroup(wxids); + break; + case PCRobotCMD.checkUrl: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).CheckUrlStatus(data.ToMessage); + break; + case PCRobotCMD.openUrl: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).OpenBrowser(data.ToMessage); + break; + case PCRobotCMD.clearChatHistoryMsg: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).ClearChatHistoryMsg(); + break; + case PCRobotCMD.deleteGroupMember: + api.DeleteGroupMember(data.ToUsername, new string[] { data.ToMessage }); + break; + case PCRobotCMD.setSessionReadedMsg: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).SetMsgReaded(data.ToMessage); + break; + case PCRobotCMD.modRoomName: + case PCRobotCMD.setRoomName: + api.ModifyGroupName(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.setRoomNotice: + api.ModifyGroupNotice(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.modRoomMyName: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).ModifyGroupMyNick(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.setRoomShowMemeberName: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).ModifyGroupShowNick(data.ToUsername, bool.Parse(data.ToMessage)); + break; + case PCRobotCMD.setRecvNotify: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).ModifyRecvNotify(data.ToUsername, bool.Parse(data.ToMessage)); + break; + case PCRobotCMD.addPublicUser: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).AddPublicUser(data.ToUsername); + break; + case PCRobotCMD.setDisableRevoke: + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).DisableRevoke(bool.Parse(data.ToMessage)); + break; + case PCRobotCMD.findCircles://获取朋友圈 + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).Ser_GetCircles(data.ToMessage, data.ToUsername); + break; + case PCRobotCMD.autoAuthMiniAPPLogin://小程序自动授权登录 + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).AutoAuthMiniAPPLogin(data.ToMessage); + break; + case PCRobotCMD.sendCircle://发送朋友圈 + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).SendCircle(data.ToMessage); + break; + case PCRobotCMD.sendCircleComment://发送朋友圈评语 + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).CircleComment(data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.sendCirclePraise://朋友圈点赞 + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).CircleLink(data.ToMessage); + break; + case PCRobotCMD.uploadCiecleImage://上传朋友圈图片 + if (wechatUser.Type == WechatType.Xiaoxie) + (api as Wechat_Xiaoxie).CircleUpLoadImage(data.ToMessage); + break; + default: + break; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("RcvServerSuccess:", ex.Message + $"key = {key} :: str = {str}"); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("RcvServerSuccess:", ex.Message + $"key = {key} :: str = {str}"); + } + }); + } + + public bool DownloadFile(string URL, string filename) + { + try + { + float percent = 0; + if (File.Exists(filename)) File.Delete(filename); + + Stream st = null; + Stream so = null; + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + + totalDownloadedByte = osize + totalDownloadedByte; + Application.DoEvents(); + so.Write(by, 0, osize); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + return true; + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("下载文件异常", $"下载文件异常:{ex.Message}"); + } + return false; + } + + //刷新机器人列表 + private void RefUserMethod(WechatUser user) + { + this.Invoke(new Action(delegate + { + try + { + this.listView1.Items.Clear(); + int i = 1; + foreach (var item in WechatClient.Users.Values.ToList()) + { + var view = new ListViewItem(new string[] { i.ToString(), item.Wxid, item.Nickname, item.Type == WechatType.Xiaoxie_QY ? "企业" : "个人", WechatClient.GetApi(item.Wxid).GetVersion(), "正式" }); + view.Tag = item; + this.listView1.Items.Add(view); + i++; + //if (item.Type == WechatType.Xiaoxie) + // //BakWechatInfo(item.Wxid, item.Nickname); + // WechatLoginHelper.EndbeginLogin(item.Wxid, item.Nickname); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("RefUserMethod", ex.Message + " " + ex.StackTrace); + } + })); + } + + ///// <summary> + ///// 备份微信config.data文件 + ///// </summary> + //private void BakWechatInfo(string username, string nick) + //{ + // try + // { + // #region 备份登录微信的data文件 + // //微信登录信息文件备份 + // Task.Run(() => + // { + // Thread.Sleep(100); + + // var allWeChatsDirPath = HttpExtend.MapFile("Config\\AllWeChats"); + // //存储微信信息的目录 + // var dirPath = HttpExtend.MapPath(Path.Combine(allWeChatsDirPath, username)); + + // //存储微信其他信息的文件 + // var configPath = Path.Combine(dirPath, "config.nnt"); + + // //将微信其他信息写入到文件中 + // using (Stream stream = File.Open(configPath, FileMode.OpenOrCreate)) + // { + // byte[] buffer = Encoding.Default.GetBytes(nick); + // stream.Write(buffer, 0, buffer.Length); + // } + // }); + // #endregion + // } + // catch (Exception ex) + // { + // MessageBox.Show($"保存微信信息异常:{ex.Message}"); + // } + //} + + //开始连接服务器 + private void button1_Click(object sender, EventArgs e) + { + var socketClient = EasySoc.GetSocket(); + try + { + Config.SetValue("服务器信息", "IP", textBox1.Text); + Config.SetValue("服务器信息", "Port", textBox2.Text); + Config.SetValue("秘钥", "SecretKey", textBox3.Text); + + if (this.button1.Text != "连接服务器") + { + if (socketClient != null) + { + socketClient.Stop = true; + socketClient.Close(); + } + RcvServerState("您已断开与服务器的连接!"); + this.button1.Text = "连接服务器"; + return; + } + + if (socketClient != null) + { + socketClient.Close(); + } + socketClient.Stop = false; + socketClient.Connection(Config.GetValue("服务器信息", "IP"), Convert.ToInt32(Config.GetValue("服务器信息", "Port")), RcvServerSuccess, RcvServerError, Config.GetValue("秘钥", "SecretKey"), RcvServerState); + + Thread.Sleep(1000); + + if (socketClient.IsConnected) + { + this.button1.Text = "断开服务器"; + } + else throw new Exception("连接服务器失败,请检查是否填写正确!"); + } + catch (Exception ex) + { + if (socketClient != null) socketClient.Stop = true; + MessageBox.Show(ex.Message, "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + //全部退出 + private void button3_Click(object sender, EventArgs e) + { + try + { + if (MessageBox.Show("是否退出全部微信?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.No) return; + LogHelper.GetSingleObj().Info("系统", $"点击全部退出微信"); + foreach (var item in WechatClient.Users.Values.ToArray()) + WechatClient.RemoveUser(item, true); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("退出全部微信", $"退出全部微信异常:{ex.Message}"); + } + } + + //检查更新 + private void button4_Click(object sender, EventArgs e) + { + try + { + var LastData = UpdateClient.GetCloudFileHist(); + if (!string.IsNullOrWhiteSpace(LastData)) + { + #region 如果存在更新微信版本,将退出微信该软件目录下的所有微信 + //var v = versions.FirstOrDefault(f => f.Name == "PCWechat"); + //if (v != null) + //{ + // Process[] MyProcesses = Process.GetProcesses(); + // var path = HttpExtend.MapPath("PCWechat"); + // foreach (Process MyProcess in MyProcesses) + // { + // try + // { + // var name = MyProcess.ProcessName.ToUpper(); + // if (name == "WECHAT" && MyProcess.MainModule.FileName.StartsWith(path)) + // { + // LogHelper.GetSingleObj().Debug("", $"检测到新微信版本,已经登录的微信"); + // MyProcess.Kill(); + // } + // } + // catch (Exception ex) + // { + // LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + // } + // } + //} + #endregion + + //Process.Start("检查更新.exe", "易转发.exe"); + + //IsClose = true; + //this.Close(); + if (new UpdateForm(LastData).ShowDialog() == DialogResult.OK) + PCRobotForm_FormClosing(LastData, null); + } + else new MessageBox1("暂无新版本!").ShowDialog(); + } + catch (Exception ex) + { + new MessageBox1(ex.Message).ShowDialog(); + } + } + private bool IsClose = false; + //窗口即将关闭 + private void PCRobotForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (!IsClose && e != null) + { + var msg = MessageBox.Show("您确定要退出软件吗?", "谨慎操作", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (msg != DialogResult.Yes) { e.Cancel = true; return; } + } + + try + { + PCWechat.WechatClient.UnInstall(); + var socketClient = EasySoc.GetSocket(); + if (!e.Cancel && socketClient != null && socketClient.IsConnected) + { + socketClient.Close(true); + } + } + catch (Exception) + { + + } + if (sender != null && e == null) + { + LogHelper.GetSingleObj().Info("系统", $"关闭窗体退出"); + Process.Start("检查更新.exe", "易转发.exe"); + Thread.Sleep(600); + } + Process.GetCurrentProcess().Kill(); + } + + //删除微信 + private void 删除微信ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (listView1.SelectedItems.Count == 0) return; + else + { + var item = this.listView1.SelectedItems[0].Tag as WechatUser; + LogHelper.GetSingleObj().Info("系统", $"右击删除微信,Uin:{item.Uin},微信:{item.Nickname}({item.Wxid})"); + WechatClient.RemoveUser(item, true); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("Delete Wechat ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + //登陆微信 + private void button2_Click(object sender, EventArgs e) + { + try + { + var wtype = WechatType.Xiaoxie; + Wechat_Xiaoxie.Install(); + + //http://qiniu.down.api.52cmg.cn/PCWechat_2.7.1.82.zip + var socketClient = EasySoc.GetSocket(); + if (!socketClient.IsConnected) + { + this.tabControl1.SelectedIndex = 1; + MessageBox.Show("请先连接机器人服务器!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + //if (wtype == WechatType.Xiaoxie) + //{ + // var form = new WechatLoginForm(); + // if (form.ShowDialog() == DialogResult.OK) + // { + // //启动微信,暂时没有做MD5检查 + // //WechatClient.StartWechat(WechatType.Xiaoxie); + // WechatClient.StartWechat(wtype, form.wxid); + // } + //} + //else + WechatClient.StartWechat(wtype); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "启动失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + /// <summary> + /// 登录企业微信 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void button5_Click(object sender, EventArgs e) + { + try + { + Wechat_Xiaoxie_QY.Install(); + var socketClient = EasySoc.GetSocket(); + if (!socketClient.IsConnected) + { + this.tabControl1.SelectedIndex = 1; + MessageBox.Show("请先连接机器人服务器!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + //启动微信,暂时没有做MD5检查 + var rst = WechatClient.StartWechat(WechatType.Xiaoxie_QY); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "启动失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + //清理文件 + private void timer1_Tick(object sender, EventArgs e) + { + LogHelper.GetSingleObj().Info("清理文件", $"定时清理文件开始执行"); + try + { + string[] ClearDirs = new string[] { "VOICE", "IMAGE" }; + //删除微信缓存文件(图片/文件) + var cachePath = CsharpHttpHelper.HttpExtend.MapPath("Accounts"); + if (Directory.Exists(cachePath)) + { + DirectoryInfo dirs = new DirectoryInfo(cachePath); + FileSystemInfo[] fileinfos = dirs.GetFileSystemInfos(); //返回目录中所有文件和子目录 + for (int z = 0; z < fileinfos.Length; z++) + { + for (int k = 0; k < ClearDirs.Length; k++) + { + var path = HttpExtend.MapPath($@"Accounts\{fileinfos[z]}\{ClearDirs[k]}"); + Common.DeleteDir(path); + } + } + } + LogHelper.GetSingleObj().Info("清理文件", $"定时清理文件执行完毕"); + } + catch (Exception) + { + LogHelper.GetSingleObj().Info("清理文件", $"定时清理文件执行失败"); + } + + try + { + //删除缓存目录 + Common.DeleteDir(HttpExtend.MapPath(@"Cache")); + LogHelper.GetSingleObj().Info("删除缓存目录", $"定时删除缓存目录执行完毕"); + } + catch (Exception) + { + LogHelper.GetSingleObj().Info("删除缓存目录", $"定时删除缓存目录执行失败"); + } + } + + private void button6_Click(object sender, EventArgs e) + { + try + { + Process.Start(HttpExtend.MapPath()); + } + catch (Exception) + { } + } + + private void timer2_Tick(object sender, EventArgs e) + { + try + { + Process[] MyProcesses = Process.GetProcesses(); + foreach (Process MyProcess in MyProcesses) + { + if (MyProcess.ProcessName.ToUpper() == "WECHATAPP") + { + LogHelper.GetSingleObj().Info("杀死小程序app", $"检测到WECHATAPP进程,主动杀死"); + MyProcess.Kill(); + } + } + } + catch (Exception ex) + { } + } + + private void button7_Click(object sender, EventArgs e) + { + try + { + if (Common.AppConfig_ExistItem("AnalysisTypes")) + Common.AppConfig_Set("AnalysisTypes", richTextBox1.Text.Trim()); + else + Common.AppConfig_Add("AnalysisTypes", richTextBox1.Text.Trim()); + AnalysisTypes = richTextBox1.Text.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim().ToUpper()).ToList(); + + if (Common.AppConfig_ExistItem("IsHaveRead")) + Common.AppConfig_Set("IsHaveRead", checkBox2.Checked ? "1" : "0"); + else + Common.AppConfig_Add("IsHaveRead", checkBox2.Checked ? "1" : "0"); + IsHaveRead = checkBox2.Checked; + } + catch (Exception ex) + { + MessageBox.Show("保存异常:" + ex.Message); + } + } + + private void button8_Click(object sender, EventArgs e) + { + try + { + if (MessageBox.Show(@"是否立即执行清理硬盘垃圾 + +注:将会退出已登录的所有微信", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.No) + return; + var path = Environment.CurrentDirectory + "\\清理.bat"; + if (File.Exists(path)) + { + ProcessStartInfo info = new ProcessStartInfo(path); + info.UseShellExecute = true; + info.Verb = "runas";//管理员身份运行 + Process.Start(info); + } + else + throw new Exception("执行失败,清理.bat文件不存在~!"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + //new MessageBox1(ex.Message).ShowDialog(); + } + } + + private void timer3_Tick(object sender, EventArgs e) + { + try + { + if (Config.GetValue("设置", "静态").ToUpper() != "TRUE") + { + Common.ActivateWindow(); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("EnableError", $"{ex.Message} - {ex.StackTrace}"); + } + } + + private void button9_Click(object sender, EventArgs e) + { + Wechat_Xiaoxie.UnInstall(); + } + + private void listView1_SelectedIndexChanged(object sender, EventArgs e) + { + + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + try + { + Config.SetValue("设置", "静态", checkBox1.Checked ? "FALSE" : "TRUE"); + } + catch (Exception exception) + { + Console.WriteLine(exception); + throw; + } + } + } +} diff --git a/PCRobot/PCRobotForm.resx b/PCRobot/PCRobotForm.resx new file mode 100644 index 0000000..7d1c911 --- /dev/null +++ b/PCRobot/PCRobotForm.resx @@ -0,0 +1,871 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>95, 18</value> + </metadata> + <metadata name="易转发.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="易转发.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + AAABAAEASEgAAAEAIACIVAAAFgAAACgAAABIAAAAkAAAAAEAIAAAAAAAAFEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAA + AAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAACAAAAAgAAAAIAAAACAAAAAgAA + AAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAADAAAAA4AAAAOAAAADwAA + ABAAAAAQAAAAEAAAABEAAAAQAAAAEAAAABAAAAAPAAAADgAAAA0AAAAMAAAACgAAAAkAAAAIAAAABwAA + AAYAAAAFAAAABAAAAAIAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAwAAAAMAAAAFAAAABwAA + AAkAAAAMAAAADwAAABIAAAAVAAAAGAAAABoAAAAdAAAAIAAAACMAAAAlAAAAJgAAACcAAAAoAAAAKQAA + ACkAAAApAAAAKAAAACcAAAAlAAAAJAAAACIAAAAfAAAAHAAAABoAAAAXAAAAFAAAABEAAAAPAAAACwAA + AAgAAAAHAAAABQAAAAMAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAAFAAAABwAAAAoAAAANAAAAEgAAABYAAAAbAAAAIQAA + ACYAAAArAAAAMAAAADYAAAA7AAAAPgAAAEIAAABGAAAASAAAAEoAAABMAAAATQAAAE0AAABNAAAATAAA + AEoAAABHAAAARQAAAEEAAAA9AAAAOQAAADQAAAAuAAAAKgAAACQAAAAgAAAAGgAAABUAAAARAAAADQAA + AAoAAAAHAAAABAAAAAMAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAEAAAADAAAABQAAAAgAAAALAAAAEAAAABYAAAAcAAAAIwAAACsAAAA0AAAAPAAAAEUAAABNAAAAVQAA + AF0AAABkAAAAagAAAHEAAAB2AAAAeQAAAH0AAACAAAAAgQAAAIEAAACBAAAAfwAAAHwAAAB4AAAAdAAA + AG8AAABoAAAAYQAAAFoAAABSAAAASgAAAEIAAAA5AAAAMQAAACkAAAAhAAAAGgAAABUAAAAPAAAACgAA + AAcAAAAEAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAMAAAAFAAAACQAA + AA4AAAAVAAAAHAAAACYAAAAwAAAAOwAAAEYAAABSAAAAXgAAAGoAAAB2AAAAgQAAAIsAAACVAAAAnwAA + AKcAAgCtAAQCsgAFA7YABQS5AQUEugEGBLoBBgS6AQUEuAEEA7UBAgKxAAAAqwAAAKQAAACcAAAAkgAA + AIgAAAB+AAAAcgAAAGYAAABaAAAATgAAAEMAAAA4AAAALAAAACMAAAAZAAAAEgAAAAwAAAAIAAAABAAA + AAIAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAQAAAAIAAAADgAAABYAAAAfAAAAKwAA + ADkAAABGAAAAVQAAAGMAAAByAAAAgQAAAJAAAACfAAIBrgAWCb8BKxHNAT8b2QJYLOQCaz3sAXNG8AF5 + SfMCfUv1BoBM9QmDTvUMhVD1D4JQ9BB5S/IPaEDtDE8v5gg2H9wFIRPSAgwHxAAAALUAAACpAAAAmwAA + AI0AAAB9AAAAbQAAAF4AAABQAAAAQQAAADQAAAAnAAAAHAAAABMAAAAMAAAABgAAAAMAAAABAAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAYAAAALAAAAEwAAABwAAAApAAAANwAAAEcAAABXAAAAaAAA + AHkAAACKAA0FoQEqEbsBUSHWAnIu6gKHOPUCm0n8AqJb/wGaX/8BkFf/AI1R/wCOT/8AkU//AJJQ/wGU + Uv8Cl1P/BJdU/waWVP8IkVD/ColJ/wp+Qv8Kbjj8CVwv9QlJJ+kGLBjWAxMLwAABAakAAACWAAAAhQAA + AHQAAABjAAAAUgAAAEIAAAAzAAAAJQAAABkAAAAPAAAACAAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAABAAAAAwAAAAYAAAALAAAAFAAAAB8AAAAtAAAAPQAAAE8AAABfAAAAcQEdC5ECUyC/Anow5AKU + O/kCnj7/AqZI/wKjW/8Bj1n/AH9L/wB6Q/8AekH/AHpA/wB7QP8Ae0D/AHxA/wB+Qf8Af0H/AIBB/wB9 + P/8Adzr/AWwy/wFgKf8BWCX/AVgm/wJaKv8FXS7+B1Yt9AZCJN0DIxO4AQgElQAAAH4AAABtAAAAWwAA + AEkAAAA4AAAAKAAAABwAAAARAAAACQAAAAUAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAA + AAUAAAALAAAAEwAAAB4AAAAsAAAAOwAAAEsBIgxuAmEkrgOJM+cDmTr9A548/wOfPf8CplT/AZdf/wB6 + Sf8Abjr/AGo3/wBnNP8AYzH/AGAu/wBeLP8AXSv/AF4q/wBfK/8AYCv/AGEr/wBeKv8AWCb/AE4g/wBC + Gv8FPBb/HUcW/yhOGP8aTxz/Ck4i/wVRKP8BUSv4AEQl2QAoF6MABwVxAAAAVwAAAEcAAAA2AAAAJwAA + ABoAAAAQAAAACAAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAHAAAADwAA + ABgAAAAiABAGNwJiJIEEijPXBJg5/QScO/8EnTv/BKFA/wOlXf8BiFf/AGw6/wBiMf8AWyz/AFIl/wBL + If8DRh7/C0Md/xNCHf8ZQR3/HEIf/x1EH/8cRB//F0Qd/w4/Gv8FOBb/AC4Q/xYuDf+MaQ3/zpIN/9OQ + DP/IiAz/rXwO/4pvEv9gZBf/P1we/yhWI/YRSSHHASkVdQAAAT4AAAArAAAAHQAAABMAAAAMAAAABgAA + AAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAFAAAACgAAAA4DViAzBYgyogWX + OfQFmzz/Bp09/wafPv8GpET/A6Fg/wB7Tf8AYTD/AFco/wNLIv8PQR7/Ijod/zg2Hv9INCH/VDQj/1w1 + JP9iNib/Zjgo/2k6Kf9pPCr/ZTwq/1g2Jv9ELR7/MCQX/4pRC//snA7/6aEO/+aaDf/mlwz/6JQM/+mS + C//njgv/3okL/82EDf+xfhH/nncT6aJvDqCqZwdkn2EHQpJYByVQLwMMAAAAAf/pEwDgigsA3IYLANyF + CgDbgwoA3IQKANuDCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQEAAAACAAAAAwaHNDwGlzrCB5w8/weePv8IoEH/CKJB/win + SP8EomL/AHJE/wBXKf8JSiL/IT0e/z4zHv9SLh//Wywe/14sHv9eLR3/Xy0e/2AvH/9iMCD/ZDMi/2c1 + I/9oNST/ZjUl/10vIP9MJBr/VygU/8doCv/nnxL/5Z8S/+SbEP/kmBD/4pYP/+KVD//ikw//45IO/+WR + Df/nkQ3/6JAM/+SPDP/gjAz734sL6t2KC8rdiAuq3YgLht6IC1nehwsx3IYLG9uDCgzikgsA3IQKANuC + CgDagQoA2oEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAACKNCAAm0RgAP/4kAB5k8RQecPtQInz//CaFC/wmjRP8KpUb/CqlK/wamZP8AbkH/CE4k/yc+ + IP9JMB7/WCoc/1koGv9XJxj/VycY/1goGf9aKhr/XSwc/18uHf9hMB//ZDIh/2Y0Iv9mNCP/YzMi/1cr + HP9CHhT/WSYN/8poCf/noRX/5aAV/+ScE//kmhP/45kT/+SYEv/klxL/5JcR/+SWEf/klRH/45UQ/+OV + EP/jlA//45MO/+KRDv/hkA3/4I4N/+CMDPffiwvt3okL092HCqzchQqH3IMKYtuCCiPKdAAA2YAJANmA + CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKBCAAqh + QwAIn0BHCZ9B3QmhQ/8KpEb/C6ZI/wyoS/8Nq0z/CK9n/wNzSP8cRCH/RzMg/1sqHf9ZJxn/ViYX/1Ym + Fv9YJxf/WigZ/10rGv9gLRz/YzAe/2YyIP9oNCL/azck/205Jv9sOCX/aDYk/1krHP9CHRT/WyYM/8pm + Cf/noxn/5aAY/+WdF//lnBb/5JsW/+SaFv/kmhb/5JoV/+SaFf/kmRT/5JkT/+SZE//kmRL/5JgR/+SX + EP/jlhD/4pUP/+GTDv/hkQ3/4I8M/9+NDP/eigv/3YcL+tyECtHbggs93YQMANmACgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAymSQALo0UAC6RHAAqiRD4Ko0XcC6RH/wyn + Sv8NqUz/DqtP/xCsUP8Ntmb/CYNZ/y85If9XLR7/XSob/1opGf9bKRj/XCoY/18rGv9hLRv/ZC8d/2Yw + Hv9nMiD/ajQh/2w2I/9uOCT/cDom/3E8J/9wOyf/bDgl/1wtHf9DHhT/XygM/8xoCv/opB7/5qAc/+We + G//lnhv/5Z0a/+WdGv/lnRn/5Z0Z/+WcGP/lnBf/5ZwW/+WbFv/lmxX/5JsU/+SaE//kmhP/5JkS/+SY + EP/jlxD/4pUP/+GSDv/gkA7/3owN/9yGDP/bgQui2XwJB9p/CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+xVgAMp0oAC6VIKwumSM0Mp0v/DqpN/xCsUP8RrlP/ErBV/xK3 + X/8PnG//Nzcm/1gpG/9fLBv/YC0b/2IuHP9kLx3/ZjAd/2cxHv9nMR7/ZzEe/2gyH/9pMyD/ajQh/2w2 + Iv9uOCT/bzom/3A7J/9uOib/aDYk/1cqG/8+GhL/YCgK/85pC//ppyP/5qIi/+WgIP/loCD/5aAg/+ag + H//moB7/5qAe/+agHf/mnxz/5p8b/+afGv/mnhn/5Z4Y/+WdF//mnBb/5ZwV/+WbE//kmhL/45gS/+KV + Ef/hkhD/340P/9yGDf/bgAuN2HkIBNp+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAADq5TAA2qTgAMqEsSDalMrw6qTv8QrVH/Eq9V/xOxWP8Vs1v/F7de/w+5ev8rTz7/UyMX/18u + Hf9mMR7/aDIf/2kzH/9pMyD/aTMg/2kzIP9pMyD/aTMf/2kzIP9qNCD/azUh/2w2Iv9uOCT/bzkl/3A6 + Jv9uOSb/ZzQj/1QoGf85GBD/YigJ/9BsDf/qqyr/56Qn/+ajJv/noyb/56Mm/+ijJf/ooyT/56Mk/+ej + I//noiH/56Ig/+eiH//noR3/56Ac/+agGv/mnxn/5p8X/+WdFv/lnBX/5JoU/+OXE//hkhH/34sP/92E + DdbbgAws24EMANd7CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq1SAA2t + UQIOrVJ5D65T+xGwV/8Us1v/FbVe/xi3Yv8auWT/GMR2/xWMbf9FIxn/Xiwc/2kzIP9rNCD/azQh/2w0 + IP9sNSD/bDUg/2w1IP9sNSD/bDUg/2w1IP9sNSH/bDUh/202Iv9uNyP/cDkl/3A5Jf9tOCX/ZTMi/1Em + GP82Fg7/ZCkI/9JxDv/srzH/6Kct/+imLP/opiz/6Kcs/+inK//opyr/6Kcp/+imKP/opib/56Yl/+il + JP/opSL/6KQg/+ejHv/mohz/5qEa/+agGP/lnxf/5ZwW/+SZFf/hkhP/34oQ5d2EDk3fjBAA2n4LANl9 + CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUumIAELNaAA+xWDwQslnlErRc/xW2 + YP8XuWP/Grpm/xy9a/8fxHX/E8SR/ytHOP9WJBb/aDMg/242Iv9uNiL/bjYi/242Iv9uNyL/bjci/243 + Iv9uNyL/bjci/243Iv9uNiL/bjYi/283I/9vOCP/cDkl/3A5Jf9tOCT/ZTIg/08jFv8yEw3/ZikG/9V0 + Ef/ttDj/6ao0/+mqM//pqzP/6asz/+mqMv/pqjH/6aow/+mqLv/pqS3/6akr/+moKf/oqCf/6Kcl/+im + I//opSH/56Qf/+ejHP/noRr/5p8Y/+SbF//ikxTq4IwSXc9gBgHcgw4A24AMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARtl4AEbVcDRG1Xq0Tt2D/Frlj/xm7Z/8cvWv/H8Fx/yLH + fP8h1pb/E5t+/0MiFv9hLx7/bjcj/3E5JP9xOST/cjkk/3I5JP9yOiT/cjok/3I6JP9yOiT/cjok/3I6 + JP9yOST/cjkk/3E5JP9xOST/cjol/3E6Jf9uOCT/ZDEg/00iFf8wEQz/aisG/9d5E//uuUH/6q88/+qv + O//qrzv/6q87/+quOv/qrjj/6q43/+quNf/qrTP/6q0x/+qsL//qqy3/6qsq/+mpKP/pqSb/6agj/+im + If/opR//56Ic/+WdGfjklxZ034QQAuCLEgDdhQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAABS8aAATuWMAE7liVRS5Y/UXu2f/Gr1r/x2/b/8hw3b/JMqC/yjUk/8c2qz/IFxJ/1Qi + FP9qNSL/czol/3Q7Jf91PCb/dTwm/3U8J/92PCf/djwm/3Y8Jv92PCb/djwm/3Y8Jv92PCf/dTwm/3U8 + Jv90PCb/dDwm/3M7Jv9vOST/YzEg/0whFP8uEAv/bywF/9p9F//wv0z/67RF/+u0RP/rtET/67RE/+y0 + Q//ss0H/7LNA/+uzPv/rsjz/67E5/+uwN//qrzT/668x/+utLv/qrCv/6aso/+mpJf/oqCP/56Uh/+eh + Hf3mnhqA4ZEYAeWcGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFb9tABS8 + aAAUu2cPFbxouBe9av8bv27/HsFy/yLFeP8my4X/KdSX/y7fqf8VwqH/NDEi/18sHP9xOiX/dz4n/3g+ + KP95Pyj/eT8p/3k/Kf96QCn/ekAp/3pAKf96QCn/ekAp/3pAKf95QCn/eT8p/3k/Kf94Pyj/eD4o/3Y9 + J/9xOib/ZTIg/0whFP8vEQv/dC8E/9yCHP/xxFb/7LhN/+y5Tf/tuU3/7blM/+y4S//suEn/7LhI/+y3 + Rv/stkP/7LZB/+y1Pv/stDv/67M4/+uyNP/rsDD/6q4t/+qrKv/qqif/6agk/+ilIf/moR7f5Z4dLOae + HQDmnx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGsR3ABa+awAVvmtLF79t9BvB + cf8fw3T/I8Z6/yfMh/8r1pn/MN2n/y7nuf8Vl33/RiEU/2k0Iv93Pij/e0Eq/3xCKv98Qyv/fUMs/35D + LP9+Qyz/fkQs/35ELP9+RCz/fkQs/35ELP9+Qyz/fUMs/31DK/98Qiv/fEIr/3lAKf90PCf/ZzMh/00i + Ff8vEQv/ejIE/96HIf/yyGD/7r1W/+6+Vv/uvVb/7b1V/+29VP/tvVL/7bxR/+28Tv/tu0v/7bpJ/+25 + Rf/tuEL/7bc//+y2O//stDf/7LIy/+uvLv/rrSv/6qso/+moJf/npCL/5aEfh///mADmnRwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFsBvABS/bgQXwXChGsNz/x/Ed/8jx3v/KMyG/yzW + mP8w3qj/N+Ky/ynmwv8caFT/VSIU/3E7J/98Qyz/gEYt/4BGLv+CRy7/g0cv/4RIL/+ESC//hEgv/4VI + L/+FSS//hUgv/4RIL/+ESC//g0cv/4NHL/+CRi7/gUYu/35ELf95QCv/bDYj/1AjFf8xEQv/gDQE/+GN + Jv/zzmv/8MJf//DCYP/wwl//8MNf//DCXf/wwlv/8MFZ//DBV//vwFT/775R/+++Tf/uvUr/7rxG/+66 + Q//tuT7/7bY5/+yzNP/rsC//6a0r/+mrKP/oqCX/56Qi2OahICTmoSAA5aQjAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAZxncAGMN0ABjDcyoaxHXeHsV4/yLHe/8ny4T/LNSV/zHdp/8247T/PenC/yLc + wf8qRTP/YCkb/3hAK/+CRy//hUkw/4ZKMf+ISzH/iUwy/4lMMv+KTTL/ik0y/4tNM/+LTTP/i00y/4pN + Mv+KTDL/iUwy/4hLMv+HSzH/hkox/4NIMP9+RC3/cDkl/1MlFv80Egv/hTcE/+OSLf/10nX/8cZp//HH + av/xx2n/8sdo//LHZ//xxmX/8cZj//HFYP/xxF3/8MNa//DCVv/wwVL/8MBO//C/S//vvUb/7rpB/+24 + O//stDX/6rAw/+quLP/pqyj/6Kcl/uajI2nppyUA6qQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAZxXYAG8V3ABrFdmQcxnj9Icd8/ybKgv8r0ZH/Mduk/zbjtP886ML/QvHU/xzJs/82LyD/aTIi/39F + Lv+ITDL/i04z/4xPNP+NUDX/jlE2/49RNv+QUjb/kFI2/5BSNv+QUjb/kFI2/5BSNv+PUTb/j1E2/45Q + Nf+MTzX/i040/4lMM/+ESTH/dT0o/1coGP84FAz/izoD/+WYNP/21n//8sty//LMc//yzHL/8sxy//LL + cP/yy27/8sps//HJaf/yyGb/8sdi//HGX//xxVv/8cRW//DDUv/wwU7/779I/++9Q//uuTz/7LQ1/+uw + MP/qrSz/6aoo/+emJbrloSIL5qIiAOajJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAax3gAGMd3BxzH + eaMfx3v/JMmA/yrPi/8w2J//NeGy/zvowv9C7s//Rfjh/xiynf9CJRf/cTgm/4ZKMf+OUTb/kFI3/5JU + OP+UVTn/lVY6/5ZWOv+XVzr/l1c7/5hXO/+YVzv/l1c7/5dXO/+WVzr/lVY6/5RVOv+TVDn/klM4/49R + N/+KTjT/ekEr/1wqGv89Fg3/kjwD/+eePP/32on/8857//PQfP/z0Hv/89B7//PPef/zz3f/8850//PN + cv/zzG//88tr//LKZ//yyWP/8sde//HGWv/xxVX/8cNQ//DASv/vvUT/7rk7/+uzNP/qsC//6a0r/+io + J+jnpCU556QlAOSoJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcx3sAG8d7GR7IfNciyX//KMyH/y7V + mP80363/Oue//0Duzv9H8tn/R/rn/xqdif9NIRT/eT4r/41PNv+VVTr/l1c8/5lZPf+bWz7/nFs+/51c + P/+eXD//n10//6BdQP+gXUD/n11A/59dP/+eXD//nVw+/5tbPv+aWj3/mFk9/5VWO/+QUzn/gUYu/2Et + HP9BGA7/mEAD/+mkQv/43pH/9NOE//TUhP/01IT/9NSD//TUgv/004D/9NJ9//TSev/z0Hf/889z//PO + b//zzWv/8sxm//LKYv/yyV3/8sdX//DFUv/vwkv/771D/+y3Ov/rsjP/6q8u/+iqKv/npydw660qAOWk + JgAAAAAAAAAAAAAAAAAAAAAAAAAAAB7KgAAdyX0AHch9QiDJf+0ly4P/K9GQ/zLbpf845br/PuzL/0Xx + 2P9N9N3/SPnp/x+Oev9VIRT/gEMv/5RUO/+cWz//nl1B/6BfQv+iYEP/pGFE/6ViRP+mYkX/p2NF/6dj + Rf+oZEX/p2NF/6ZjRf+mYkX/pGJE/6NhQ/+hYEP/n15C/5xcQP+XWT7/iEsy/2gwH/9JGw//nkMD/+ur + Sv/44Zn/9daL//XXjP/114z/9deL//XXiv/11oj/9daF//TVgv/01H//9NN7//TSd//00XP/889u//PO + af/zzGT/8ste//HIWf/wxVP/8MJL/+68Qf/stTf/67Ey/+msLf/nqCmv5KQnCuWmKAAAAAAAAAAAAAAA + AAAAAAAAAAAAAB3KfgAfyoAAHsmAbCLKgvwozon/L9ab/zXhsv886sb/QvDU/0rz3P9S9N7/Svjp/yGG + cv9bIRX/h0cy/5taP/+iYUT/pWNG/6hlR/+qZkj/q2dJ/61oSf+uaUr/r2pK/69qS/+wakv/r2pK/69p + Sv+taUr/rGhJ/6pnSP+pZUj/p2RH/6NiRP+eX0P/jlA3/240If9PHhD/pEgE/+60U//55KH/9duT//bb + lP/225T/9tuT//bbkv/12pD/9dmN//XZiv/12If/9deD//XVf//11Hr/9NN1//TRcP/00Gv/885m//LM + YP/yyVr/8cZS//DBSP/tuT3/67M1/+quMP/oqSvb5qYoHuanKQAAAAAAAAAAAAAAAAAAAAAAAAAAAB/K + gQA91pEAIcuCiiTMhf8r0pH/Mtyn/zjnvv8/7s//RvLZ/07z3P9X9N7/Tvjp/ySFcf9fIhb/jEk1/6Ff + Q/+pZ0j/rGpL/65sTP+xbU3/s29O/7RwT/+2cE//t3FQ/7dxUP+3cVD/t3FQ/7ZxT/+1cE//tG9O/7Ju + Tv+vbE3/rWtM/6poSv+lZUj/llY7/3Q5Jf9WIRL/q00F//C8XP/55qf/9t2a//fem//33pv/996a//fe + mf/33Zf/9t2U//bckf/2247/9tqK//XZhv/114H/9dZ8//TVd//003L/9NJs//PPZv/yzWD/8slZ//DF + T//uvUP/67U5/+qwM//pqy3u56cqRuenKgDmpioAAAAAAAAAAAAAAAAAAAAAAB/LgwAdyoIJIsyEpSbO + if8t1pn/NOGx/zvqx/9C8NX/SvPa/1Hz3P9a9N7/VPnq/yWMeP9hIxb/j0o1/6dkR/+vbU3/s3FQ/7Vz + Uv+4dFL/unZT/7t3VP+9eFX/vnlV/795Vv+/eVb/v3lV/755Vf+8eFX/u3dU/7l1U/+3dFL/tHJR/7Fv + T/+tbE3/nl1B/30/Kf9fJhT/sVIG//LCZf/66K7/+OGh//jhov/44aH/9+Gg//jhn//44J3/+OCb//ff + mP/33pT/992R//bbjP/22oj/9tmD//XYfv/11nn/9NRy//PSbf/z0Gb/8sxf//HIVv/vwUr/7Lg9/+uy + Nf/prS/956grbeeoLADmuSoAAAAAAAAAAAAAAAAAAAAAACDMhQAfzIQSI82HvSjRjv8v2qL/NuW7/z7t + zv9F8df/TfLa/1Xy3P9d893/W/rr/ySbh/9hIxb/kUg0/61oS/+2dFP/unhW/716WP/AfFn/wn5a/8N/ + W//EgFv/xoBc/8aAXP/GgFz/xoFc/8WAXP/Ef1v/w35a/8F8Wf++e1j/vHlX/7h3Vf+1dVX/qGdJ/4lJ + MP9tLhn/t1cI//PIbv/66rP/+OOn//nkp//55Kf/+eOm//njpf/446P/+OKh//jhnv/44Jv/9+CX//fe + kv/33Y7/99yJ//bahP/22H//9dd5//TVc//002z/89Bm//LLXf/wxVL/7rtC/+u0OP/prjL/6Kkti//0 + hADmpioAAAAAAAAAAAAAAAAAAAAAACHNhwAgzYYZJM6KzynTlP8x3qv/OOnC/z/v0v9H8dj/T/LZ/1fy + 2/9f89z/ZPrp/yeynv9cJxn/kUQx/7JrTv+8elj/wYBd/8SCX//HhGD/yYVh/8uHYv/MiGL/zYhj/82J + Y//NiWP/zYlj/82IY//Mh2L/yoZh/8iFYP/Fg1//woBe/79+XP++fl3/s3NT/5hWO/9/OyL/vVwK//TN + d//667f/+eWs//nmrf/55az/+ear//nlqv/55an/++en//roqv/55aX/+OKc//jhmP/44JT/99+P//fd + if/324T/9tl///XXeP/01XL/9NJs//POY//xyFj/7r9I/+u1O//przP/56oupeamKQnmqCsAAAAAAAAA + AAAAAAAAAAAAACLOigAhzYkdJNCN2SvWmv8y4bH/OevH/0Hv0/9J8df/UfLY/1ny2v9h89v/a/nm/zLN + u/9TMiP/jjsr/7RpTf/Cfl3/x4Zj/8qJZf/Nimb/0Ixo/9KOaP/Tj2n/1I9q/9SQav/UkGr/1JBq/9SP + av/Tjmn/0Y1o/86LZ//MiWb/yYdk/8aFY//EhGP/vX9f/6hlSP+SSiv/w2MM//bTf//77Lv/+eew//ro + sf/66LH/+uiw//ror//56rH/16xv/+29bv/877n/+eSi//njnf/54pn/+OGU//jfjv/33Yn/9tuE//bZ + fv/113f/9NRx//PRaP/xy13/7sJO/+u3Pf/psDX/6KswvOeoLBLnqS0AAAAAAAAAAAAAAAAAAAAAACPP + jAAiz4sfJdGQ3ivZn/8y5Lf/OuzK/0Lw0/9K8db/UvHX/1ry2f9i8tr/bvbh/0Pm1v9ESzn/iDEj/7Fi + SP/GgWH/zYpo/9GPbP/TkW3/1ZNu/9iUb//ZlXD/2pVw/9qWcP/alXD/2pZw/9qWcP/ZlXD/1pRv/9SS + bv/SkG3/z45r/8yMaf/JiWj/xYdn/7d3Wf+kWzr/yGoO//fYh//77b//+um0//rptf/66bX/+um0//3u + t//Uuoz/cz4o/7RkG//84J3/+uuz//nlov/55J7/+eOZ//jhk//4347/992J//bbg//12Hz/9NZ1//PS + bf/yzWL/78VT/+y5QP/qsTb/6KwxzeeoLhnnqS4AAAAAAAAAAAAAAAAAAAAAACPQjgAi0IwfJdOT3yzb + o/8z5br/O+zM/0Lv0/9L8NT/U/HW/1vx2P9j8tn/bfPc/1r35/8zemb/gCsc/6lZP//IgWD/0Y9t/9aV + cv/Yl3P/25l1/92adf/em3X/3pl0/96Xcf/el3H/35p0/9+bdv/em3b/3Jt2/9qZdf/Yl3T/1JVy/9GS + cP/OkG//yoxs/8KFZ/+2b0z/znER//jdj//77sL/+uq4//rruf/667n//O+7/+bOof+kcln/e0g3/3s5 + GP/hoEv//vK8//roqP/55qL/+eSd//njmP/44ZP/+N+N//fdh//22oD/9th5//TUcf/zzmb/8MdX/+26 + Q//qsTf/6Kwx1+epLhzoqi8AAAAAAAAAAAAAAAAAAAAAACPRjwAi0I4dJdSV2izcpv8z5r3/O+3M/0Lv + 0f9L79P/U/DV/1vx1v9j8dj/a/La/3D66P8wuKX/bDMg/55MM//EeFb/1ZNv/9qadv/dnnn/3596/+Gf + ev/inHX/3pBp/9GEXP/NgFj/2I1k/+Gcdf/ioHv/4aF8/96gfP/cnXr/2Zt4/9aZdv/SlnT/z5Nz/8uR + cv/DgFv/0nkS//nilv/778X/+uy7//rsvP/88L//6teq/7WGav+mclv/l2NO/3NBMf+pWxj/+9yW//vu + t//656b/+uWh//nknP/545f/+OGR//ffiv/23IT/9tp9//TWdf/z0Gr/8Mhb/+y8Rv/psjj/6Kwy2+ep + Lx7nqjAAAAAAAAAAAAAAAAAAAAAAACPSkQAi0Y8aJdWY0CvdqP8y5r3/Ou3L/0Luz/9K79H/Uu/T/1vw + 1f9j8df/avHY/3b13/9M6dn/Sl9I/5M+JP+4akb/1Y9p/92eeP/ho33/5KN9/+ahef/Rnnj/oYpn/5xl + QP+tXDP/wnJG/92UZ//mpHz/5aeB/+Omgf/hpH//3qJ+/9qffP/XnHr/05l4/8+Xd//Jjmz/0noa//jc + fv/99dD/++6///3xwv/t3LD/vZF1/6x6Yv+se2P/pXRd/4hYRv+AQB7/46ZS//7zwP/66Kr/+uek//rm + oP/55Jr/+OKU//jgjv/33Yf/9tqA//TWeP/y0W7/8Mle/+y8Sf/psTn/6Kwz2eepMB3nqTEAAAAAAAAA + AAAAAAAAAAAAACLTkgAh0o8UJdeZwCrdqf8y5r3/OezJ/0Htzf9J7s//Ue/R/1nv0/9h8NX/afHX/3Ly + 2f9v+ej/M6yW/3w+I/+nVzb/zH9Y/9+cdv/lpH7/5KmD/73Msf+Z6df/aOve/zOznf+EWzT/s2Az/9aJ + W//opXz/6auG/+erh//lqYb/4aeF/96kg//boYH/155//9Obff/PmXz/zIVO/+WpOf/456n/9+rD/+bN + qf/ClXn/tIFp/7OCav+wf2j/rHxm/5trVv97Rzb/vHAl//7qrf/77LP/+umn//roo//55p3/+eSY//jh + kf/33or/9tuD//TXe//y0nD/8Mlh/+y9Sv/psTn/6Kwz0ueoMBrnqTEAAAAAAAAAAAAAAAAAAAAAACHU + lAAf0pALJNebqSneqf8w5rz/OOvI/z/szP9H7c3/T+7P/1fv0v9f79P/Z/DV/27w1/959d7/Ueva/0hx + Vv+YRSX/t2pC/9mOZf/mo3v/uNK2/5H25P+T9uL/mPnp/0Dn2/9FgV//r1os/9GDVf/qp33/7K+L/+qw + jf/nr43/5ayL/+Gqif/ep4f/2qSF/9ehgv/SnoD/zpp//8uTbf/OnG//yp2A/8CPdv+7inL/uYly/7aH + cP+zhG7/r4Fr/6d4Y/+HWUn/mFEc//bNgf/88b3/+uqq//ropv/55qD/+OSa//fik//334z/9tuF//TY + ff/y0nL/8Mpi/+y8Sv/psDn/56szw+anLxXmqDAAAAAAAAAAAAAAAAAAAAAAACHVlgAWx3oBI9ickCjd + qP8v5bn/NurF/z3ryf9F7Mz/Te3N/1Xuz/9d79H/ZO/T/2vw1f9z8df/d/jk/z3LuP9tVjb/pVMt/8Zz + Rv/At5P/kPPf/5D03/+R897/lvXi/1zt4P80lXX/qF0v/8yBUv/qqH7/7rSQ/+y2lP/qtZP/6LKS/+Sw + kP/hrY7/3qqM/9qnif/WpIf/0qGF/86ehP/JmYH/xpZ9/8OUe//Aknr/vY94/7qNd/+4inX/s4Zx/62B + bP+Xalj/gUcp/+KpWP/+9ML/+uus//npp//556L/+OWc//jilf/3347/9duH//TXf//z0nP/8Mli/+y7 + Sv/orzj/56ozrOanLgzmqDAAAAAAAAAAAAAAAAAAAAAAACHWlwAj2Z4AIticdSbdpv8t5Lf/NOnC/zvr + x/9C7Mn/SuzL/1Ltzf9Z7s//Ye7R/2jv0/9u8NT/d/HY/2335f82sJj/gU0p/6V2UP+Q587/i/Tf/43y + 3f+N8t3/kfTe/2zx4v8no4b/nmAy/8d8UP/opn3/8LeU/+66mf/suZn/6raY/+e0lf/jsZT/4K6R/9yr + j//ZqI3/1aWL/9GiiP/Nn4b/ypyE/8aZgv/Dl4D/wJR+/72SfP+7kHv/t4t3/7GGc/+hdWP/d0g1/8qH + N///8r3/++yw//rqqf/556T/+eWd//jil//334//9tuI//TXgP/y0XP/8Mhi/+u5SP/nrjf/5qkykOSd + JQHmpzAAAAAAAAAAAAAAAAAAAAAAACHWlwAh2JwAIdicUCTcpfIq4rP/Mei//zjqxP8/6sb/R+vI/07s + yv9W7Mz/Xu3O/2Xu0f9s79L/cu/U/3vy2f9l8uD/RKeN/4TGq/+G9t//ifLa/4ry2v+K8tr/i/Lb/3f0 + 4/8asZj/kGQ3/8J4Tf/lpHv/8LqX//C9nv/uvJ7/67ud/+i4m//ltpn/4rOX/96wlf/brZP/16qQ/9On + jv/Qo4z/zKGJ/8meiP/Gm4b/w5mE/8CXgv++lYD/upF9/7SKd/+me2n/dEw//7JvJv/+67H/+u20//rq + qv/556X/+eWe//jil//235D/9duI//PWgP/yz3P/7sZg/+q3Rf/mrDb+5akycOWpMgDkpDAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAg2J0AINibJiLbouIo4a//L+a7/zbpwf8+6sT/RerG/03ryP9U7Mr/XO3M/2Lt + zv9o7s//bu/R/3Pv0/978tn/c/Lb/33x2P+D8df/hPHY/4bx2P+G8dj/h/HY/3/14v8fv6j/f2s//751 + Sf/foXf/8byZ//DBov/vwaP/7L+i/+q9oP/nup7/47ec/+C0mv/dsZj/2a+V/9ask//SqJH/z6aP/8yj + jf/IoYv/xp6J/8OciP/Bmob/vZaD/7ePfP+nfWv/c09E/59fIv/75KT/++63//rpqv/556X/+OWe//fh + l//13pD/9NqI//PVf//xznH/7cNd/+m0Qf/mqjTu5acwRuWnMQDlpjAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAf2JwAHteaDSHaoL0m36v/LuS3/zTnvv876MH/QunD/0nqxf9Q6sf/V+vJ/17sy/9k7M3/au3O/2/u + 0P907tH/ee/T/3vv1P9979T/f/DV/4Dw1f+B8NX/gO/V/4D03v8szLf/anRK/7tyR//YnHP/8Lya//LE + pf/wxKf/7cKm/+vApf/ovqP/5buh/+K4n//ftp3/27Ob/9iwmf/VrZf/0qqV/86ok//LpZH/yaOP/8ah + jv/En4z/wJuI/7mSgP+le2r/ck9F/5JWIv/43Zv/+u+5//npqv/456X/+OSe//bgl//13I//89iH//LT + fv/wy2//7L9Z/+iwPf/mqDPX5aYwG+WmMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAAbpbASDZ + n34k3af/K+Ky/zHluv83577/PujA/0bpwv9N6cT/VOrG/1rryP9g7Mr/ZuzM/2vtzf9w7c//c+7Q/3fu + 0f957tL/eu7S/3vu0v9779L/eu/R/3zz2f831sP/UX5W/7dvRf/QlnD/7rua//LGqf/wx6z/7sWs/+zE + q//pwan/5r+n/+O8pf/guaP/3beh/9q0n//WsZ3/066b/9Gsmf/Oqpf/y6iV/8mmlP/Ho5L/w5+O/7qT + gv+fdGX/bU1F/4lRIP/325j/+u65//noqf/45aP/9+Kc//bflf/02o7/89aG//HQe//vyGr/67tR/+as + OP/lpjGf5KMtBuSlLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAHtmdAB7ZnUIh26PuJ+Ct/y7k + tf815rv/POe+/0Pov/9K6cL/UenE/1fqxf9d68f/Y+vJ/2fsy/9s7Mz/b+zN/3Ltzv907c//du3P/3bt + z/927c//de3O/3nx1P9B3sr/OIhj/7BtQ//JkWz/6rmY//HIrP/wyrD/7smw/+zHr//qxa3/58Ks/+TA + qv/hvqj/37um/9u4pP/YtqL/1rOg/9Oxn//Rr53/zq2b/8yrmf/JqJf/xaOS/7aOfv+XbWD/ZUhA/4ZQ + H//33Jv/+u23//jnp//35KH/9+Cb//bdlP/02Iz/8tOE//DNd//txGT/6bVJ/+WoNPrjpDBc5KQxAOOj + LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAHNibABvYmQ8f2qDAJd6p/y3isf8z5Lj/Oua7/0Hn + vf9I57//TujB/1Tpw/9a6cX/YOrH/2TqyP9o68n/bOvL/2/sy/9w7Mz/cezM/3Lszf9x7Mz/cOzM/3Pu + z/9O5M7/LpNx/6dsQv/CjGb/5LaU//HKrv/wzbT/7sy0/+zKs//qyLL/6Maw/+XErv/iwaz/4L+q/928 + qf/auqf/2Lil/9W1pP/Ts6L/0LGg/86vnv/LrJv/xKKR/62EdP+MZVj/WD83/4lUHv/54aL/+euz//jl + pv/34qD/9t6Z//Xakv/z1or/8dCA/+/Jcv/svl3/565A/+SlMdTjoi4f46IuAOOjLgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAG9iZACPfpwAf2p9vI92l/yrgrf8x47T/OeW4/z/lu/9G5r3/TOe//1Lo + wf9Y6cP/XOnE/2Hqxv9l68f/aOvI/2rryf9s68n/bezK/23ryv9s68n/a+vJ/2zsyv9a6dL/JqCB/5ps + Qv+7hmL/3bCQ/+/Kr//wzrf/7s64/+zMt//qy7b/6Mm1/+XGs//jxLH/4MKv/96/rv/bvaz/2buq/9e5 + qf/Vt6f/07Wl/9Cyo//Mrp7/vpmJ/6J3av99W0//STEr/5hfIP/86Kz/+Oet//fjo//3353/9duV//TX + jv/y0of/8M18/+3Fa//quFP/5ag3/+OiL4naixcB4J0rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAHtqeAB7ZngAe2Z0jINui1ybeqf8v4bD/N+O2/z7luf9F5rv/Sue9/1Dnv/9W6MH/W+nC/1/p + xP9i6cX/ZerG/2fqx/9o6sf/aerH/2jqx/9o6sf/ZurG/2Xqxf9g7NH/HK2Q/4huRP+2gV7/1aqL/+3J + sP/v0Lr/7tC8/+zPvP/rzrv/6cy5/+bJuP/kx7b/4sW0/+DDs//dwbH/27+v/9m9rv/Xu6z/1bmq/9K1 + p//JqZn/s4p7/5RrX/9oTkT/TyYZ/8h9NP/867b/9+Sn//bgoP/13Zn/9NmS//LUi//wz4L/7sh2/+u/ + Yv/nr0b/46My4+KfLjLioC8A4qQuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHticABzY + mgAy58EAH9uhfyTdp/8t4K3/NeOz/z7kt/9E5br/Sea8/0/nvv9U58D/WejC/13pw/9g6cT/YunF/2Pq + xf9k6sX/ZerG/2Xqxf9j6sX/YunE/1/pw/9i7c7/Gbmf/3RxSf+yfFr/zKKF/+rHrv/v0b3/7tPA/+zR + wP/r0L7/6c69/+fMvP/lyrr/48i5/+HHt//fxbb/3cO0/9rBsv/YvrD/1rut/9CzpP+/mon/o3lr/35c + Uf9ROTH/jC0G/+ijV//56rf/9uCi//XdnP/02ZX/89WO//HQhv/uy33/7MNt/+m3Vv/kpzn/46AvjOCX + JgPinS0A4p8tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3ZnAAg26EAH9qgIyPd + pNMq36r/M+Kw/zzjtf9D5bn/SOa8/07nvv9T6MD/V+jB/1vpwv9e6cT/YOnF/2Hpxf9i6cX/YunF/2Hp + xP9g6cP/XejC/1rnwP9g7Mn/JMWr/2B4UP+vd1T/w5t//+XErP/u0r7/7tTC/+zUw//r0sL/6dDB/+fP + wP/lzb7/48u9/+LJu//gx7n/3cW3/9vDtf/ZwLL/1Lmr/8akk/+vhHX/jWZb/15IP/91MBT/xkcG/+/F + fv/35a//9d2d//TZl//y1ZD/8dGJ/+/Mgv/txnX/6r1i/+atRv/ioDHW4Z0tKOKeLgDini0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2p8ALuGtACTcpGkp3qn4MuGv/zrj + tP9C5Lj/Sea8/07mvv9T58H/V+jC/1row/9d6cX/XunF/1/pxf9g6cX/YOnE/1/pw/9c6ML/WejB/1bn + v/9b68T/L9C1/0l/Wv+rcU//upV6/9+/qP/t0sD/7dXF/+zVxv/r1Mb/6dPF/+fRxP/m0ML/5M7A/+LM + vv/gybz/3se6/9vEt//XvbD/y6qa/7aMfP+YbmL/alBH/2c2IP+5OwL/0Wgd//Xcov/13qP/89mY//LV + kv/x0Iv/78yE/+3He//rv2v/57NT/+OkN/fhnS5o5KQ1AOGcLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf2qAAJdylACTbpBEq3qmvMeCu/zrjtP9C5bn/Sea9/0/n + wP9U6ML/V+nD/1vpxf9d6sb/XurG/1/qxv9f6sb/XurF/13pxP9a6cL/V+jA/1Pnvv9W6cH/ONm8/zCJ + Z/+jbUn/s450/9e3ov/q0cD/7dbI/+zWyf/r1sj/6dXI/+jTxv/m0cT/5M/D/+LNwf/gyr7/3ca6/9i+ + sP/Lq5v/uY9//55yZv9xVEz/Zzkl/7dCCP/FQwH/35pP//birf/z2Jj/8tST//DQjP/vzIX/7cd+/+vB + cf/ot13/5KhA/+GeL6PgmisO4JwtAOGdLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAFOCmACreqAAr3qk0MeCu2Tnjtf9C5br/See+/1Dowf9V6sT/WerF/1zr + x/9e68j/YOvI/2DryP9f68j/XurG/1zqxf9Y6cP/VejA/1Dnvv9Q6L7/P9+//yGVdf+YaUX/rYdt/86v + mf/oz77/7NbH/+vXyv/q1sn/6NXI/+fTx//l0cX/5M/C/+HMv//dx7n/1rur/8mmlf+3jHz/nXFl/3FT + S/9vPSP/ukgH/8lKBP/FVxD/78qK//PaoP/x05H/8M+M/+7Lhv/sx3//68F0/+m5ZP/lrEn/4Z8yzOCZ + KyXgmywA4Z4vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAJNmfAC3dqQAR1IwBM+CvjDrjtv9D5rz/S+fA/1LpxP9X6sf/XOvJ/1/ryv9h68v/YuvM/2Lr + y/9h68r/X+rJ/1zqx/9Y6MT/VOfB/0/mv/9M5rz/RePB/x6hg/+JZ0P/qH9k/8Wlj//jybj/6dPF/+rV + yP/p1Mj/59PH/+XRxf/jzsL/4Mm8/9rAsv/RsqH/w52L/7KEdv+Va2D/bk5E/4JCHf/FUAj/zVMG/75H + Av/ZkEb/89uj//DRkf/vzYv/7smF/+zFf//rwXb/6bpn/+avUP/ioTfd4JkrQeCdLwDitD8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAINaWACrd + pwAo26M0MuCu2TzkuP9G57//TejD/1Tqx/9a68r/X+zN/2Lszv9k7M//Ze3P/2Xsz/9j7M7/YevM/13q + yf9Z6cb/VOjD/07nwP9K5rz/SubB/xqtj/91ZUT/o3VY/7qZgv/cwK7/5c6//+XQwv/kz8H/4su9/9/G + t//Zvq3/0rKg/8mij/+7jn7/pXds/4RdVf93SjT/o00T/9BaCP/NWAj/wU4F/8VhF//tx4n/8NKV/+7L + if/tyIT/7MR+/+rAd//ouWn/5rBV/+KiO+Tgmi1T79dqAN+VKADgmSoAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2JwAI9mfACHYnRYp26W0NOGx/0Dm + vP9J6ML/UerG/1jryv9e7M3/Yu3Q/2bu0f9o7tL/ae7S/2ju0v9m7tD/Y+3O/1/sy/9a6sj/VenF/0/o + wv9J577/TOnC/xe5nP9fZUn/nWVG/6qBZf/NqI//2rqk/9q7p//YuKP/1LKd/86pk//Gm4j/uot8/6Z4 + bP+NYVf/gVE7/5tSHf/HXwz/1WMI/8xcCf/EVAf/vVAG/96kYP/w0pj/7cmH/+zGgv/rwn3/6r52/+i5 + av/lr1b/4qM+4t+aL1jUbwAB35YpAN+XKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2JwAAMl6ASTaoXos3qr9OeS3/0XowP9O6sb/VuvK/1zs + zv9j7tH/Z+7T/2rv1f9t79b/be/W/2zv1f9q79T/Z+7S/2Ltz/9d7Mz/WOrI/1Lpxf9N6MH/UOrE/x7G + qP9IaVL/jEs5/5NhTP+zgWz/wpN+/8GSf/+7jHv/s4Jz/6d1aP+aZ1n/kFxG/5NYMP+rXhr/y2kN/9lt + Cv/SaAv/ymAK/8RZCf+8TwX/0oZA/+7Mkf/sxoX/68N//+rAev/pvHP/57Zo/+SuVf/hoj/W35ovTNNi + AAHflioA35crAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAg2qAAHtmeGCbdpsgy4rH/Pua9/0npxP9T68r/Wu3O/2Hu0v9o79X/bfDX/3Hx + 2f9y8dr/c/Ha/3Lx2f9v8Nf/a+/V/2bu0v9h7c//W+zM/1bryP9S6cX/VezG/y7Ttv84clP/jzMU/5JG + Hv+gWiz/p2U1/6dmNf+nZjD/qmYp/7FoIP+9bhf/zXUQ/9l5Df/beAz/1XEM/85qC//JYwr/xF0K/7xT + Bv/KdjL/6sKH/+vEhP/qv3v/6b13/+e5cP/ms2T/5KtS/uGhPrrfmTA0569OAN6VKgDflywAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAj3KMAH9qfCyvfrJs147X9QOa+/0rpxf9U68r/XO3Q/2Tv0/9r8Nf/cfHa/3Xy2/9389z/d/Pc/3by + 3P908dr/cPHY/2rv1f9k7tL/X+3O/1rsy/9W68n/WezJ/zzdwf8vhmb/pz0H/7tXCP/HbQz/znkO/9J+ + Dv/WgQ//2YMQ/9qCD//ZgA7/13wP/9N2Dv/QcQ3/zGsN/8hmC//EYAn/vFYG/8d0L//nu3//6sCA/+i8 + dv/nuXL/5rVr/+SwXv/jqE3u4KA9jN+XLhjgnDUA3I8iAN6WLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3JsALOCtAC7g + rxg14rVvP+W8nEjnw7BR6sjHWuzO3WLu0u5p8Nb2b/HZ+XPy2/128tz/d/Pd/3bz3f9z9N3/b/Pc/2rx + 2P9l79P/YO3P/1zszP9a68r/XezK/zrjyf87iGf/qEAG/7dYCv/CaQ3/yXMP/8x4EP/PehD/0HoQ/9B6 + EP/Qdw//znQO/8xwDf/Jaw3/xmcM/8FgCf+8WQj/yXo2/+a3e//pvXv/57hx/+a1bf/ksWT/46tW++Gl + SL/gnTpN3ZElBt+aMwDgmzUA3pUsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm3KcAOeW5AC3grgA14rUAPOO6Akbl + wQ1P6ccYV+vMI2Dt0i5n79ZBbfDYW3Dx2ndz8dyRdPHcp3Py27l04MffcN7D/2nny/9h7dH/W/HU/1fy + 0/9W8tP/TvLT/ynNtf95YDD/r0kF/7dbC/+/Zg3/xG0O/8dwDv/Jcg//ynMP/8pyDv/JcA7/yG0N/8Zq + DP/DZQv/vl4G/71hEv/Ri0n/5rZ6/+e3c//lsmr/5LBj/+OrWf3ipk7N4KFCbN+bNRbjpkoA35kyAOCe + PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvkuQAx4rAAPuW8AEfmwQBP6ccAWOzNAGDt + 0gBn79YAbvDZAHTy2wB389wAKf//AHLkywqKg1kukHJEgZJsOdKPdT/7iIRR/3+WZ/93o3b/a5Ro/4Zk + Lv+tSgb/sVUJ/7ddC/+8Ywz/v2YN/8FoDf/Cag3/w2oN/8RqDf/DaQ3/wWYM/75hCf+9YQ3/x3ct/9uh + Yf/mtXP/5LBn/+OsX//iqVfx4aVOwOCiRWrfnDoc46tUAOCeOgDckCQA3pgxAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABx8dsAbf/wAHXcwgCGkWcA/wAAAK8vAB+rPgBfq0QAq6tGBeGsSAb3r0oF/7BOBf+vVAr/s1gK/7Zb + C/+4Xwv/umEM/7xiDP+9Ywz/vWIL/7xhCv+8YQr/vmUR/8d3LP/Xl1T/4q1p/+OsYv/hp1bu4aVRz+Cj + TI3goEVI3ps4EeKvXgDfnj0A4q5VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKcv + AACjXAsAoj0IAKdIBQCpQQAAqFcOCapTCyirUgpdrVIJjK5TCbewVQncslcK7rNYCvO0Wgr3tVsK+rdc + Cvy4Xgz8vGMR+8JvHvjNgzX12ZlP8OGmXOXiplfH4KJNn9+gSHbfnkRD350/FtuPIQPgoUYA3pw7AN6c + PADgoEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKlN + CACpTQgAqU8JAKpQCgCsUQkAslMIAa5TCRCwVAkfsFUKMLBVCkawVQlZtFsMab1lE3TEbxx1zXwncNeP + PGDenExP4aNRON+dQyTdlzQW3JEpB+ClUADfn0YA4J9FAN+dPwDfmDMA35s5AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK1R + CQC1WQkArlIJAK5TCQCwVAkAsVUKALJXCgCzWQoAs1gJALVZCgC4Xg4AwGsbANCHOQDgpFkA46lcAN+f + SQDemj0A3pk7AN6ZOwDemTsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8AAAAAAAP/8AAAD/4AAAAAAAD/8A + AAD/AAAAAAAAAf8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8A + AAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAD8A + AAD/gAAAAAAAAA8AAAD/gAAAAAAAAAcAAAD/wAAAAAAAAAcAAAD/AAAAAAAAAAcAAAD/AAAAAAAAAAcA + AAD+AAAAAAAAAAcAAAD+AAAAAAAAAAcAAAD8AAAAAAAAAA8AAAD8AAAAAAAAAB8AAAD4AAAAAAAAAD8A + AADwAAAAAAAAAB8AAADwAAAAAAAAAB8AAADwAAAAAAAAAA8AAADgAAAAAAAAAA8AAADgAAAAAAAAAAcA + AADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADAAAAAAAAAAAcAAADAAAAAAAAAAAcAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADgAAAAAAAAAAMAAADgAAAAAAAAAAcA + AADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADwAAAAAAAAAA8AAADwAAAAAAAAAA8A + AADwAAAAAAAAAA8AAAD4AAAAAAAAAB8AAAD8AAAAAAAAAD8AAAD8AAAAAAAAAD8AAAD+AAAAAAAAAH8A + AAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD8AAAAAAAAAf8AAAD8AAAAAAAAA/8AAAD8AAAAAAAAB/8A + AAD8AAAAAAAAD/8AAAD8AAAAAAAAH/8AAAD8AAAAAAAAf/8AAAD/AAAAAAAA//8AAAD//8AAAAAH//8A + AAD///AAAAAP//8AAAD///4AAAA///8AAAD////AAAP///8AAAD///////////8AAAD///////////8A + AAA= +</value> + </data> + <metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>252, 19</value> + </metadata> + <metadata name="timer2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>342, 21</value> + </metadata> + <metadata name="timer3.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>432, 21</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>58</value> + </metadata> + <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + AAABAAEASEgAAAEAIACIVAAAFgAAACgAAABIAAAAkAAAAAEAIAAAAAAAAFEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAA + AAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAACAAAAAgAAAAIAAAACAAAAAgAA + AAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAADAAAAA4AAAAOAAAADwAA + ABAAAAAQAAAAEAAAABEAAAAQAAAAEAAAABAAAAAPAAAADgAAAA0AAAAMAAAACgAAAAkAAAAIAAAABwAA + AAYAAAAFAAAABAAAAAIAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAwAAAAMAAAAFAAAABwAA + AAkAAAAMAAAADwAAABIAAAAVAAAAGAAAABoAAAAdAAAAIAAAACMAAAAlAAAAJgAAACcAAAAoAAAAKQAA + ACkAAAApAAAAKAAAACcAAAAlAAAAJAAAACIAAAAfAAAAHAAAABoAAAAXAAAAFAAAABEAAAAPAAAACwAA + AAgAAAAHAAAABQAAAAMAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAAFAAAABwAAAAoAAAANAAAAEgAAABYAAAAbAAAAIQAA + ACYAAAArAAAAMAAAADYAAAA7AAAAPgAAAEIAAABGAAAASAAAAEoAAABMAAAATQAAAE0AAABNAAAATAAA + AEoAAABHAAAARQAAAEEAAAA9AAAAOQAAADQAAAAuAAAAKgAAACQAAAAgAAAAGgAAABUAAAARAAAADQAA + AAoAAAAHAAAABAAAAAMAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAEAAAADAAAABQAAAAgAAAALAAAAEAAAABYAAAAcAAAAIwAAACsAAAA0AAAAPAAAAEUAAABNAAAAVQAA + AF0AAABkAAAAagAAAHEAAAB2AAAAeQAAAH0AAACAAAAAgQAAAIEAAACBAAAAfwAAAHwAAAB4AAAAdAAA + AG8AAABoAAAAYQAAAFoAAABSAAAASgAAAEIAAAA5AAAAMQAAACkAAAAhAAAAGgAAABUAAAAPAAAACgAA + AAcAAAAEAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAMAAAAFAAAACQAA + AA4AAAAVAAAAHAAAACYAAAAwAAAAOwAAAEYAAABSAAAAXgAAAGoAAAB2AAAAgQAAAIsAAACVAAAAnwAA + AKcAAgCtAAQCsgAFA7YABQS5AQUEugEGBLoBBgS6AQUEuAEEA7UBAgKxAAAAqwAAAKQAAACcAAAAkgAA + AIgAAAB+AAAAcgAAAGYAAABaAAAATgAAAEMAAAA4AAAALAAAACMAAAAZAAAAEgAAAAwAAAAIAAAABAAA + AAIAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAQAAAAIAAAADgAAABYAAAAfAAAAKwAA + ADkAAABGAAAAVQAAAGMAAAByAAAAgQAAAJAAAACfAAIBrgAWCb8BKxHNAT8b2QJYLOQCaz3sAXNG8AF5 + SfMCfUv1BoBM9QmDTvUMhVD1D4JQ9BB5S/IPaEDtDE8v5gg2H9wFIRPSAgwHxAAAALUAAACpAAAAmwAA + AI0AAAB9AAAAbQAAAF4AAABQAAAAQQAAADQAAAAnAAAAHAAAABMAAAAMAAAABgAAAAMAAAABAAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAYAAAALAAAAEwAAABwAAAApAAAANwAAAEcAAABXAAAAaAAA + AHkAAACKAA0FoQEqEbsBUSHWAnIu6gKHOPUCm0n8AqJb/wGaX/8BkFf/AI1R/wCOT/8AkU//AJJQ/wGU + Uv8Cl1P/BJdU/waWVP8IkVD/ColJ/wp+Qv8Kbjj8CVwv9QlJJ+kGLBjWAxMLwAABAakAAACWAAAAhQAA + AHQAAABjAAAAUgAAAEIAAAAzAAAAJQAAABkAAAAPAAAACAAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAABAAAAAwAAAAYAAAALAAAAFAAAAB8AAAAtAAAAPQAAAE8AAABfAAAAcQEdC5ECUyC/Anow5AKU + O/kCnj7/AqZI/wKjW/8Bj1n/AH9L/wB6Q/8AekH/AHpA/wB7QP8Ae0D/AHxA/wB+Qf8Af0H/AIBB/wB9 + P/8Adzr/AWwy/wFgKf8BWCX/AVgm/wJaKv8FXS7+B1Yt9AZCJN0DIxO4AQgElQAAAH4AAABtAAAAWwAA + AEkAAAA4AAAAKAAAABwAAAARAAAACQAAAAUAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAA + AAUAAAALAAAAEwAAAB4AAAAsAAAAOwAAAEsBIgxuAmEkrgOJM+cDmTr9A548/wOfPf8CplT/AZdf/wB6 + Sf8Abjr/AGo3/wBnNP8AYzH/AGAu/wBeLP8AXSv/AF4q/wBfK/8AYCv/AGEr/wBeKv8AWCb/AE4g/wBC + Gv8FPBb/HUcW/yhOGP8aTxz/Ck4i/wVRKP8BUSv4AEQl2QAoF6MABwVxAAAAVwAAAEcAAAA2AAAAJwAA + ABoAAAAQAAAACAAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAHAAAADwAA + ABgAAAAiABAGNwJiJIEEijPXBJg5/QScO/8EnTv/BKFA/wOlXf8BiFf/AGw6/wBiMf8AWyz/AFIl/wBL + If8DRh7/C0Md/xNCHf8ZQR3/HEIf/x1EH/8cRB//F0Qd/w4/Gv8FOBb/AC4Q/xYuDf+MaQ3/zpIN/9OQ + DP/IiAz/rXwO/4pvEv9gZBf/P1we/yhWI/YRSSHHASkVdQAAAT4AAAArAAAAHQAAABMAAAAMAAAABgAA + AAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAFAAAACgAAAA4DViAzBYgyogWX + OfQFmzz/Bp09/wafPv8GpET/A6Fg/wB7Tf8AYTD/AFco/wNLIv8PQR7/Ijod/zg2Hv9INCH/VDQj/1w1 + JP9iNib/Zjgo/2k6Kf9pPCr/ZTwq/1g2Jv9ELR7/MCQX/4pRC//snA7/6aEO/+aaDf/mlwz/6JQM/+mS + C//njgv/3okL/82EDf+xfhH/nncT6aJvDqCqZwdkn2EHQpJYByVQLwMMAAAAAf/pEwDgigsA3IYLANyF + CgDbgwoA3IQKANuDCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQEAAAACAAAAAwaHNDwGlzrCB5w8/weePv8IoEH/CKJB/win + SP8EomL/AHJE/wBXKf8JSiL/IT0e/z4zHv9SLh//Wywe/14sHv9eLR3/Xy0e/2AvH/9iMCD/ZDMi/2c1 + I/9oNST/ZjUl/10vIP9MJBr/VygU/8doCv/nnxL/5Z8S/+SbEP/kmBD/4pYP/+KVD//ikw//45IO/+WR + Df/nkQ3/6JAM/+SPDP/gjAz734sL6t2KC8rdiAuq3YgLht6IC1nehwsx3IYLG9uDCgzikgsA3IQKANuC + CgDagQoA2oEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAACKNCAAm0RgAP/4kAB5k8RQecPtQInz//CaFC/wmjRP8KpUb/CqlK/wamZP8AbkH/CE4k/yc+ + IP9JMB7/WCoc/1koGv9XJxj/VycY/1goGf9aKhr/XSwc/18uHf9hMB//ZDIh/2Y0Iv9mNCP/YzMi/1cr + HP9CHhT/WSYN/8poCf/noRX/5aAV/+ScE//kmhP/45kT/+SYEv/klxL/5JcR/+SWEf/klRH/45UQ/+OV + EP/jlA//45MO/+KRDv/hkA3/4I4N/+CMDPffiwvt3okL092HCqzchQqH3IMKYtuCCiPKdAAA2YAJANmA + CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKBCAAqh + QwAIn0BHCZ9B3QmhQ/8KpEb/C6ZI/wyoS/8Nq0z/CK9n/wNzSP8cRCH/RzMg/1sqHf9ZJxn/ViYX/1Ym + Fv9YJxf/WigZ/10rGv9gLRz/YzAe/2YyIP9oNCL/azck/205Jv9sOCX/aDYk/1krHP9CHRT/WyYM/8pm + Cf/noxn/5aAY/+WdF//lnBb/5JsW/+SaFv/kmhb/5JoV/+SaFf/kmRT/5JkT/+SZE//kmRL/5JgR/+SX + EP/jlhD/4pUP/+GTDv/hkQ3/4I8M/9+NDP/eigv/3YcL+tyECtHbggs93YQMANmACgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAymSQALo0UAC6RHAAqiRD4Ko0XcC6RH/wyn + Sv8NqUz/DqtP/xCsUP8Ntmb/CYNZ/y85If9XLR7/XSob/1opGf9bKRj/XCoY/18rGv9hLRv/ZC8d/2Yw + Hv9nMiD/ajQh/2w2I/9uOCT/cDom/3E8J/9wOyf/bDgl/1wtHf9DHhT/XygM/8xoCv/opB7/5qAc/+We + G//lnhv/5Z0a/+WdGv/lnRn/5Z0Z/+WcGP/lnBf/5ZwW/+WbFv/lmxX/5JsU/+SaE//kmhP/5JkS/+SY + EP/jlxD/4pUP/+GSDv/gkA7/3owN/9yGDP/bgQui2XwJB9p/CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+xVgAMp0oAC6VIKwumSM0Mp0v/DqpN/xCsUP8RrlP/ErBV/xK3 + X/8PnG//Nzcm/1gpG/9fLBv/YC0b/2IuHP9kLx3/ZjAd/2cxHv9nMR7/ZzEe/2gyH/9pMyD/ajQh/2w2 + Iv9uOCT/bzom/3A7J/9uOib/aDYk/1cqG/8+GhL/YCgK/85pC//ppyP/5qIi/+WgIP/loCD/5aAg/+ag + H//moB7/5qAe/+agHf/mnxz/5p8b/+afGv/mnhn/5Z4Y/+WdF//mnBb/5ZwV/+WbE//kmhL/45gS/+KV + Ef/hkhD/340P/9yGDf/bgAuN2HkIBNp+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAADq5TAA2qTgAMqEsSDalMrw6qTv8QrVH/Eq9V/xOxWP8Vs1v/F7de/w+5ev8rTz7/UyMX/18u + Hf9mMR7/aDIf/2kzH/9pMyD/aTMg/2kzIP9pMyD/aTMf/2kzIP9qNCD/azUh/2w2Iv9uOCT/bzkl/3A6 + Jv9uOSb/ZzQj/1QoGf85GBD/YigJ/9BsDf/qqyr/56Qn/+ajJv/noyb/56Mm/+ijJf/ooyT/56Mk/+ej + I//noiH/56Ig/+eiH//noR3/56Ac/+agGv/mnxn/5p8X/+WdFv/lnBX/5JoU/+OXE//hkhH/34sP/92E + DdbbgAws24EMANd7CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq1SAA2t + UQIOrVJ5D65T+xGwV/8Us1v/FbVe/xi3Yv8auWT/GMR2/xWMbf9FIxn/Xiwc/2kzIP9rNCD/azQh/2w0 + IP9sNSD/bDUg/2w1IP9sNSD/bDUg/2w1IP9sNSH/bDUh/202Iv9uNyP/cDkl/3A5Jf9tOCX/ZTMi/1Em + GP82Fg7/ZCkI/9JxDv/srzH/6Kct/+imLP/opiz/6Kcs/+inK//opyr/6Kcp/+imKP/opib/56Yl/+il + JP/opSL/6KQg/+ejHv/mohz/5qEa/+agGP/lnxf/5ZwW/+SZFf/hkhP/34oQ5d2EDk3fjBAA2n4LANl9 + CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUumIAELNaAA+xWDwQslnlErRc/xW2 + YP8XuWP/Grpm/xy9a/8fxHX/E8SR/ytHOP9WJBb/aDMg/242Iv9uNiL/bjYi/242Iv9uNyL/bjci/243 + Iv9uNyL/bjci/243Iv9uNiL/bjYi/283I/9vOCP/cDkl/3A5Jf9tOCT/ZTIg/08jFv8yEw3/ZikG/9V0 + Ef/ttDj/6ao0/+mqM//pqzP/6asz/+mqMv/pqjH/6aow/+mqLv/pqS3/6akr/+moKf/oqCf/6Kcl/+im + I//opSH/56Qf/+ejHP/noRr/5p8Y/+SbF//ikxTq4IwSXc9gBgHcgw4A24AMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARtl4AEbVcDRG1Xq0Tt2D/Frlj/xm7Z/8cvWv/H8Fx/yLH + fP8h1pb/E5t+/0MiFv9hLx7/bjcj/3E5JP9xOST/cjkk/3I5JP9yOiT/cjok/3I6JP9yOiT/cjok/3I6 + JP9yOST/cjkk/3E5JP9xOST/cjol/3E6Jf9uOCT/ZDEg/00iFf8wEQz/aisG/9d5E//uuUH/6q88/+qv + O//qrzv/6q87/+quOv/qrjj/6q43/+quNf/qrTP/6q0x/+qsL//qqy3/6qsq/+mpKP/pqSb/6agj/+im + If/opR//56Ic/+WdGfjklxZ034QQAuCLEgDdhQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAABS8aAATuWMAE7liVRS5Y/UXu2f/Gr1r/x2/b/8hw3b/JMqC/yjUk/8c2qz/IFxJ/1Qi + FP9qNSL/czol/3Q7Jf91PCb/dTwm/3U8J/92PCf/djwm/3Y8Jv92PCb/djwm/3Y8Jv92PCf/dTwm/3U8 + Jv90PCb/dDwm/3M7Jv9vOST/YzEg/0whFP8uEAv/bywF/9p9F//wv0z/67RF/+u0RP/rtET/67RE/+y0 + Q//ss0H/7LNA/+uzPv/rsjz/67E5/+uwN//qrzT/668x/+utLv/qrCv/6aso/+mpJf/oqCP/56Uh/+eh + Hf3mnhqA4ZEYAeWcGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFb9tABS8 + aAAUu2cPFbxouBe9av8bv27/HsFy/yLFeP8my4X/KdSX/y7fqf8VwqH/NDEi/18sHP9xOiX/dz4n/3g+ + KP95Pyj/eT8p/3k/Kf96QCn/ekAp/3pAKf96QCn/ekAp/3pAKf95QCn/eT8p/3k/Kf94Pyj/eD4o/3Y9 + J/9xOib/ZTIg/0whFP8vEQv/dC8E/9yCHP/xxFb/7LhN/+y5Tf/tuU3/7blM/+y4S//suEn/7LhI/+y3 + Rv/stkP/7LZB/+y1Pv/stDv/67M4/+uyNP/rsDD/6q4t/+qrKv/qqif/6agk/+ilIf/moR7f5Z4dLOae + HQDmnx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGsR3ABa+awAVvmtLF79t9BvB + cf8fw3T/I8Z6/yfMh/8r1pn/MN2n/y7nuf8Vl33/RiEU/2k0Iv93Pij/e0Eq/3xCKv98Qyv/fUMs/35D + LP9+Qyz/fkQs/35ELP9+RCz/fkQs/35ELP9+Qyz/fUMs/31DK/98Qiv/fEIr/3lAKf90PCf/ZzMh/00i + Ff8vEQv/ejIE/96HIf/yyGD/7r1W/+6+Vv/uvVb/7b1V/+29VP/tvVL/7bxR/+28Tv/tu0v/7bpJ/+25 + Rf/tuEL/7bc//+y2O//stDf/7LIy/+uvLv/rrSv/6qso/+moJf/npCL/5aEfh///mADmnRwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFsBvABS/bgQXwXChGsNz/x/Ed/8jx3v/KMyG/yzW + mP8w3qj/N+Ky/ynmwv8caFT/VSIU/3E7J/98Qyz/gEYt/4BGLv+CRy7/g0cv/4RIL/+ESC//hEgv/4VI + L/+FSS//hUgv/4RIL/+ESC//g0cv/4NHL/+CRi7/gUYu/35ELf95QCv/bDYj/1AjFf8xEQv/gDQE/+GN + Jv/zzmv/8MJf//DCYP/wwl//8MNf//DCXf/wwlv/8MFZ//DBV//vwFT/775R/+++Tf/uvUr/7rxG/+66 + Q//tuT7/7bY5/+yzNP/rsC//6a0r/+mrKP/oqCX/56Qi2OahICTmoSAA5aQjAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAZxncAGMN0ABjDcyoaxHXeHsV4/yLHe/8ny4T/LNSV/zHdp/8247T/PenC/yLc + wf8qRTP/YCkb/3hAK/+CRy//hUkw/4ZKMf+ISzH/iUwy/4lMMv+KTTL/ik0y/4tNM/+LTTP/i00y/4pN + Mv+KTDL/iUwy/4hLMv+HSzH/hkox/4NIMP9+RC3/cDkl/1MlFv80Egv/hTcE/+OSLf/10nX/8cZp//HH + av/xx2n/8sdo//LHZ//xxmX/8cZj//HFYP/xxF3/8MNa//DCVv/wwVL/8MBO//C/S//vvUb/7rpB/+24 + O//stDX/6rAw/+quLP/pqyj/6Kcl/uajI2nppyUA6qQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAZxXYAG8V3ABrFdmQcxnj9Icd8/ybKgv8r0ZH/Mduk/zbjtP886ML/QvHU/xzJs/82LyD/aTIi/39F + Lv+ITDL/i04z/4xPNP+NUDX/jlE2/49RNv+QUjb/kFI2/5BSNv+QUjb/kFI2/5BSNv+PUTb/j1E2/45Q + Nf+MTzX/i040/4lMM/+ESTH/dT0o/1coGP84FAz/izoD/+WYNP/21n//8sty//LMc//yzHL/8sxy//LL + cP/yy27/8sps//HJaf/yyGb/8sdi//HGX//xxVv/8cRW//DDUv/wwU7/779I/++9Q//uuTz/7LQ1/+uw + MP/qrSz/6aoo/+emJbrloSIL5qIiAOajJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAax3gAGMd3BxzH + eaMfx3v/JMmA/yrPi/8w2J//NeGy/zvowv9C7s//Rfjh/xiynf9CJRf/cTgm/4ZKMf+OUTb/kFI3/5JU + OP+UVTn/lVY6/5ZWOv+XVzr/l1c7/5hXO/+YVzv/l1c7/5dXO/+WVzr/lVY6/5RVOv+TVDn/klM4/49R + N/+KTjT/ekEr/1wqGv89Fg3/kjwD/+eePP/32on/8857//PQfP/z0Hv/89B7//PPef/zz3f/8850//PN + cv/zzG//88tr//LKZ//yyWP/8sde//HGWv/xxVX/8cNQ//DASv/vvUT/7rk7/+uzNP/qsC//6a0r/+io + J+jnpCU556QlAOSoJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcx3sAG8d7GR7IfNciyX//KMyH/y7V + mP80363/Oue//0Duzv9H8tn/R/rn/xqdif9NIRT/eT4r/41PNv+VVTr/l1c8/5lZPf+bWz7/nFs+/51c + P/+eXD//n10//6BdQP+gXUD/n11A/59dP/+eXD//nVw+/5tbPv+aWj3/mFk9/5VWO/+QUzn/gUYu/2Et + HP9BGA7/mEAD/+mkQv/43pH/9NOE//TUhP/01IT/9NSD//TUgv/004D/9NJ9//TSev/z0Hf/889z//PO + b//zzWv/8sxm//LKYv/yyV3/8sdX//DFUv/vwkv/771D/+y3Ov/rsjP/6q8u/+iqKv/npydw660qAOWk + JgAAAAAAAAAAAAAAAAAAAAAAAAAAAB7KgAAdyX0AHch9QiDJf+0ly4P/K9GQ/zLbpf845br/PuzL/0Xx + 2P9N9N3/SPnp/x+Oev9VIRT/gEMv/5RUO/+cWz//nl1B/6BfQv+iYEP/pGFE/6ViRP+mYkX/p2NF/6dj + Rf+oZEX/p2NF/6ZjRf+mYkX/pGJE/6NhQ/+hYEP/n15C/5xcQP+XWT7/iEsy/2gwH/9JGw//nkMD/+ur + Sv/44Zn/9daL//XXjP/114z/9deL//XXiv/11oj/9daF//TVgv/01H//9NN7//TSd//00XP/889u//PO + af/zzGT/8ste//HIWf/wxVP/8MJL/+68Qf/stTf/67Ey/+msLf/nqCmv5KQnCuWmKAAAAAAAAAAAAAAA + AAAAAAAAAAAAAB3KfgAfyoAAHsmAbCLKgvwozon/L9ab/zXhsv886sb/QvDU/0rz3P9S9N7/Svjp/yGG + cv9bIRX/h0cy/5taP/+iYUT/pWNG/6hlR/+qZkj/q2dJ/61oSf+uaUr/r2pK/69qS/+wakv/r2pK/69p + Sv+taUr/rGhJ/6pnSP+pZUj/p2RH/6NiRP+eX0P/jlA3/240If9PHhD/pEgE/+60U//55KH/9duT//bb + lP/225T/9tuT//bbkv/12pD/9dmN//XZiv/12If/9deD//XVf//11Hr/9NN1//TRcP/00Gv/885m//LM + YP/yyVr/8cZS//DBSP/tuT3/67M1/+quMP/oqSvb5qYoHuanKQAAAAAAAAAAAAAAAAAAAAAAAAAAAB/K + gQA91pEAIcuCiiTMhf8r0pH/Mtyn/zjnvv8/7s//RvLZ/07z3P9X9N7/Tvjp/ySFcf9fIhb/jEk1/6Ff + Q/+pZ0j/rGpL/65sTP+xbU3/s29O/7RwT/+2cE//t3FQ/7dxUP+3cVD/t3FQ/7ZxT/+1cE//tG9O/7Ju + Tv+vbE3/rWtM/6poSv+lZUj/llY7/3Q5Jf9WIRL/q00F//C8XP/55qf/9t2a//fem//33pv/996a//fe + mf/33Zf/9t2U//bckf/2247/9tqK//XZhv/114H/9dZ8//TVd//003L/9NJs//PPZv/yzWD/8slZ//DF + T//uvUP/67U5/+qwM//pqy3u56cqRuenKgDmpioAAAAAAAAAAAAAAAAAAAAAAB/LgwAdyoIJIsyEpSbO + if8t1pn/NOGx/zvqx/9C8NX/SvPa/1Hz3P9a9N7/VPnq/yWMeP9hIxb/j0o1/6dkR/+vbU3/s3FQ/7Vz + Uv+4dFL/unZT/7t3VP+9eFX/vnlV/795Vv+/eVb/v3lV/755Vf+8eFX/u3dU/7l1U/+3dFL/tHJR/7Fv + T/+tbE3/nl1B/30/Kf9fJhT/sVIG//LCZf/66K7/+OGh//jhov/44aH/9+Gg//jhn//44J3/+OCb//ff + mP/33pT/992R//bbjP/22oj/9tmD//XYfv/11nn/9NRy//PSbf/z0Gb/8sxf//HIVv/vwUr/7Lg9/+uy + Nf/prS/956grbeeoLADmuSoAAAAAAAAAAAAAAAAAAAAAACDMhQAfzIQSI82HvSjRjv8v2qL/NuW7/z7t + zv9F8df/TfLa/1Xy3P9d893/W/rr/ySbh/9hIxb/kUg0/61oS/+2dFP/unhW/716WP/AfFn/wn5a/8N/ + W//EgFv/xoBc/8aAXP/GgFz/xoFc/8WAXP/Ef1v/w35a/8F8Wf++e1j/vHlX/7h3Vf+1dVX/qGdJ/4lJ + MP9tLhn/t1cI//PIbv/66rP/+OOn//nkp//55Kf/+eOm//njpf/446P/+OKh//jhnv/44Jv/9+CX//fe + kv/33Y7/99yJ//bahP/22H//9dd5//TVc//002z/89Bm//LLXf/wxVL/7rtC/+u0OP/prjL/6Kkti//0 + hADmpioAAAAAAAAAAAAAAAAAAAAAACHNhwAgzYYZJM6KzynTlP8x3qv/OOnC/z/v0v9H8dj/T/LZ/1fy + 2/9f89z/ZPrp/yeynv9cJxn/kUQx/7JrTv+8elj/wYBd/8SCX//HhGD/yYVh/8uHYv/MiGL/zYhj/82J + Y//NiWP/zYlj/82IY//Mh2L/yoZh/8iFYP/Fg1//woBe/79+XP++fl3/s3NT/5hWO/9/OyL/vVwK//TN + d//667f/+eWs//nmrf/55az/+ear//nlqv/55an/++en//roqv/55aX/+OKc//jhmP/44JT/99+P//fd + if/324T/9tl///XXeP/01XL/9NJs//POY//xyFj/7r9I/+u1O//przP/56oupeamKQnmqCsAAAAAAAAA + AAAAAAAAAAAAACLOigAhzYkdJNCN2SvWmv8y4bH/OevH/0Hv0/9J8df/UfLY/1ny2v9h89v/a/nm/zLN + u/9TMiP/jjsr/7RpTf/Cfl3/x4Zj/8qJZf/Nimb/0Ixo/9KOaP/Tj2n/1I9q/9SQav/UkGr/1JBq/9SP + av/Tjmn/0Y1o/86LZ//MiWb/yYdk/8aFY//EhGP/vX9f/6hlSP+SSiv/w2MM//bTf//77Lv/+eew//ro + sf/66LH/+uiw//ror//56rH/16xv/+29bv/877n/+eSi//njnf/54pn/+OGU//jfjv/33Yn/9tuE//bZ + fv/113f/9NRx//PRaP/xy13/7sJO/+u3Pf/psDX/6KswvOeoLBLnqS0AAAAAAAAAAAAAAAAAAAAAACPP + jAAiz4sfJdGQ3ivZn/8y5Lf/OuzK/0Lw0/9K8db/UvHX/1ry2f9i8tr/bvbh/0Pm1v9ESzn/iDEj/7Fi + SP/GgWH/zYpo/9GPbP/TkW3/1ZNu/9iUb//ZlXD/2pVw/9qWcP/alXD/2pZw/9qWcP/ZlXD/1pRv/9SS + bv/SkG3/z45r/8yMaf/JiWj/xYdn/7d3Wf+kWzr/yGoO//fYh//77b//+um0//rptf/66bX/+um0//3u + t//Uuoz/cz4o/7RkG//84J3/+uuz//nlov/55J7/+eOZ//jhk//4347/992J//bbg//12Hz/9NZ1//PS + bf/yzWL/78VT/+y5QP/qsTb/6KwxzeeoLhnnqS4AAAAAAAAAAAAAAAAAAAAAACPQjgAi0IwfJdOT3yzb + o/8z5br/O+zM/0Lv0/9L8NT/U/HW/1vx2P9j8tn/bfPc/1r35/8zemb/gCsc/6lZP//IgWD/0Y9t/9aV + cv/Yl3P/25l1/92adf/em3X/3pl0/96Xcf/el3H/35p0/9+bdv/em3b/3Jt2/9qZdf/Yl3T/1JVy/9GS + cP/OkG//yoxs/8KFZ/+2b0z/znER//jdj//77sL/+uq4//rruf/667n//O+7/+bOof+kcln/e0g3/3s5 + GP/hoEv//vK8//roqP/55qL/+eSd//njmP/44ZP/+N+N//fdh//22oD/9th5//TUcf/zzmb/8MdX/+26 + Q//qsTf/6Kwx1+epLhzoqi8AAAAAAAAAAAAAAAAAAAAAACPRjwAi0I4dJdSV2izcpv8z5r3/O+3M/0Lv + 0f9L79P/U/DV/1vx1v9j8dj/a/La/3D66P8wuKX/bDMg/55MM//EeFb/1ZNv/9qadv/dnnn/3596/+Gf + ev/inHX/3pBp/9GEXP/NgFj/2I1k/+Gcdf/ioHv/4aF8/96gfP/cnXr/2Zt4/9aZdv/SlnT/z5Nz/8uR + cv/DgFv/0nkS//nilv/778X/+uy7//rsvP/88L//6teq/7WGav+mclv/l2NO/3NBMf+pWxj/+9yW//vu + t//656b/+uWh//nknP/545f/+OGR//ffiv/23IT/9tp9//TWdf/z0Gr/8Mhb/+y8Rv/psjj/6Kwy2+ep + Lx7nqjAAAAAAAAAAAAAAAAAAAAAAACPSkQAi0Y8aJdWY0CvdqP8y5r3/Ou3L/0Luz/9K79H/Uu/T/1vw + 1f9j8df/avHY/3b13/9M6dn/Sl9I/5M+JP+4akb/1Y9p/92eeP/ho33/5KN9/+ahef/Rnnj/oYpn/5xl + QP+tXDP/wnJG/92UZ//mpHz/5aeB/+Omgf/hpH//3qJ+/9qffP/XnHr/05l4/8+Xd//Jjmz/0noa//jc + fv/99dD/++6///3xwv/t3LD/vZF1/6x6Yv+se2P/pXRd/4hYRv+AQB7/46ZS//7zwP/66Kr/+uek//rm + oP/55Jr/+OKU//jgjv/33Yf/9tqA//TWeP/y0W7/8Mle/+y8Sf/psTn/6Kwz2eepMB3nqTEAAAAAAAAA + AAAAAAAAAAAAACLTkgAh0o8UJdeZwCrdqf8y5r3/OezJ/0Htzf9J7s//Ue/R/1nv0/9h8NX/afHX/3Ly + 2f9v+ej/M6yW/3w+I/+nVzb/zH9Y/9+cdv/lpH7/5KmD/73Msf+Z6df/aOve/zOznf+EWzT/s2Az/9aJ + W//opXz/6auG/+erh//lqYb/4aeF/96kg//boYH/155//9Obff/PmXz/zIVO/+WpOf/456n/9+rD/+bN + qf/ClXn/tIFp/7OCav+wf2j/rHxm/5trVv97Rzb/vHAl//7qrf/77LP/+umn//roo//55p3/+eSY//jh + kf/33or/9tuD//TXe//y0nD/8Mlh/+y9Sv/psTn/6Kwz0ueoMBrnqTEAAAAAAAAAAAAAAAAAAAAAACHU + lAAf0pALJNebqSneqf8w5rz/OOvI/z/szP9H7c3/T+7P/1fv0v9f79P/Z/DV/27w1/959d7/Ueva/0hx + Vv+YRSX/t2pC/9mOZf/mo3v/uNK2/5H25P+T9uL/mPnp/0Dn2/9FgV//r1os/9GDVf/qp33/7K+L/+qw + jf/nr43/5ayL/+Gqif/ep4f/2qSF/9ehgv/SnoD/zpp//8uTbf/OnG//yp2A/8CPdv+7inL/uYly/7aH + cP+zhG7/r4Fr/6d4Y/+HWUn/mFEc//bNgf/88b3/+uqq//ropv/55qD/+OSa//fik//334z/9tuF//TY + ff/y0nL/8Mpi/+y8Sv/psDn/56szw+anLxXmqDAAAAAAAAAAAAAAAAAAAAAAACHVlgAWx3oBI9ickCjd + qP8v5bn/NurF/z3ryf9F7Mz/Te3N/1Xuz/9d79H/ZO/T/2vw1f9z8df/d/jk/z3LuP9tVjb/pVMt/8Zz + Rv/At5P/kPPf/5D03/+R897/lvXi/1zt4P80lXX/qF0v/8yBUv/qqH7/7rSQ/+y2lP/qtZP/6LKS/+Sw + kP/hrY7/3qqM/9qnif/WpIf/0qGF/86ehP/JmYH/xpZ9/8OUe//Aknr/vY94/7qNd/+4inX/s4Zx/62B + bP+Xalj/gUcp/+KpWP/+9ML/+uus//npp//556L/+OWc//jilf/3347/9duH//TXf//z0nP/8Mli/+y7 + Sv/orzj/56ozrOanLgzmqDAAAAAAAAAAAAAAAAAAAAAAACHWlwAj2Z4AIticdSbdpv8t5Lf/NOnC/zvr + x/9C7Mn/SuzL/1Ltzf9Z7s//Ye7R/2jv0/9u8NT/d/HY/2335f82sJj/gU0p/6V2UP+Q587/i/Tf/43y + 3f+N8t3/kfTe/2zx4v8no4b/nmAy/8d8UP/opn3/8LeU/+66mf/suZn/6raY/+e0lf/jsZT/4K6R/9yr + j//ZqI3/1aWL/9GiiP/Nn4b/ypyE/8aZgv/Dl4D/wJR+/72SfP+7kHv/t4t3/7GGc/+hdWP/d0g1/8qH + N///8r3/++yw//rqqf/556T/+eWd//jil//334//9tuI//TXgP/y0XP/8Mhi/+u5SP/nrjf/5qkykOSd + JQHmpzAAAAAAAAAAAAAAAAAAAAAAACHWlwAh2JwAIdicUCTcpfIq4rP/Mei//zjqxP8/6sb/R+vI/07s + yv9W7Mz/Xu3O/2Xu0f9s79L/cu/U/3vy2f9l8uD/RKeN/4TGq/+G9t//ifLa/4ry2v+K8tr/i/Lb/3f0 + 4/8asZj/kGQ3/8J4Tf/lpHv/8LqX//C9nv/uvJ7/67ud/+i4m//ltpn/4rOX/96wlf/brZP/16qQ/9On + jv/Qo4z/zKGJ/8meiP/Gm4b/w5mE/8CXgv++lYD/upF9/7SKd/+me2n/dEw//7JvJv/+67H/+u20//rq + qv/556X/+eWe//jil//235D/9duI//PWgP/yz3P/7sZg/+q3Rf/mrDb+5akycOWpMgDkpDAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAg2J0AINibJiLbouIo4a//L+a7/zbpwf8+6sT/RerG/03ryP9U7Mr/XO3M/2Lt + zv9o7s//bu/R/3Pv0/978tn/c/Lb/33x2P+D8df/hPHY/4bx2P+G8dj/h/HY/3/14v8fv6j/f2s//751 + Sf/foXf/8byZ//DBov/vwaP/7L+i/+q9oP/nup7/47ec/+C0mv/dsZj/2a+V/9ask//SqJH/z6aP/8yj + jf/IoYv/xp6J/8OciP/Bmob/vZaD/7ePfP+nfWv/c09E/59fIv/75KT/++63//rpqv/556X/+OWe//fh + l//13pD/9NqI//PVf//xznH/7cNd/+m0Qf/mqjTu5acwRuWnMQDlpjAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAf2JwAHteaDSHaoL0m36v/LuS3/zTnvv876MH/QunD/0nqxf9Q6sf/V+vJ/17sy/9k7M3/au3O/2/u + 0P907tH/ee/T/3vv1P9979T/f/DV/4Dw1f+B8NX/gO/V/4D03v8szLf/anRK/7tyR//YnHP/8Lya//LE + pf/wxKf/7cKm/+vApf/ovqP/5buh/+K4n//ftp3/27Ob/9iwmf/VrZf/0qqV/86ok//LpZH/yaOP/8ah + jv/En4z/wJuI/7mSgP+le2r/ck9F/5JWIv/43Zv/+u+5//npqv/456X/+OSe//bgl//13I//89iH//LT + fv/wy2//7L9Z/+iwPf/mqDPX5aYwG+WmMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAAbpbASDZ + n34k3af/K+Ky/zHluv83577/PujA/0bpwv9N6cT/VOrG/1rryP9g7Mr/ZuzM/2vtzf9w7c//c+7Q/3fu + 0f957tL/eu7S/3vu0v9779L/eu/R/3zz2f831sP/UX5W/7dvRf/QlnD/7rua//LGqf/wx6z/7sWs/+zE + q//pwan/5r+n/+O8pf/guaP/3beh/9q0n//WsZ3/066b/9Gsmf/Oqpf/y6iV/8mmlP/Ho5L/w5+O/7qT + gv+fdGX/bU1F/4lRIP/325j/+u65//noqf/45aP/9+Kc//bflf/02o7/89aG//HQe//vyGr/67tR/+as + OP/lpjGf5KMtBuSlLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAHtmdAB7ZnUIh26PuJ+Ct/y7k + tf815rv/POe+/0Pov/9K6cL/UenE/1fqxf9d68f/Y+vJ/2fsy/9s7Mz/b+zN/3Ltzv907c//du3P/3bt + z/927c//de3O/3nx1P9B3sr/OIhj/7BtQ//JkWz/6rmY//HIrP/wyrD/7smw/+zHr//qxa3/58Ks/+TA + qv/hvqj/37um/9u4pP/YtqL/1rOg/9Oxn//Rr53/zq2b/8yrmf/JqJf/xaOS/7aOfv+XbWD/ZUhA/4ZQ + H//33Jv/+u23//jnp//35KH/9+Cb//bdlP/02Iz/8tOE//DNd//txGT/6bVJ/+WoNPrjpDBc5KQxAOOj + LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAHNibABvYmQ8f2qDAJd6p/y3isf8z5Lj/Oua7/0Hn + vf9I57//TujB/1Tpw/9a6cX/YOrH/2TqyP9o68n/bOvL/2/sy/9w7Mz/cezM/3Lszf9x7Mz/cOzM/3Pu + z/9O5M7/LpNx/6dsQv/CjGb/5LaU//HKrv/wzbT/7sy0/+zKs//qyLL/6Maw/+XErv/iwaz/4L+q/928 + qf/auqf/2Lil/9W1pP/Ts6L/0LGg/86vnv/LrJv/xKKR/62EdP+MZVj/WD83/4lUHv/54aL/+euz//jl + pv/34qD/9t6Z//Xakv/z1or/8dCA/+/Jcv/svl3/565A/+SlMdTjoi4f46IuAOOjLgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAG9iZACPfpwAf2p9vI92l/yrgrf8x47T/OeW4/z/lu/9G5r3/TOe//1Lo + wf9Y6cP/XOnE/2Hqxv9l68f/aOvI/2rryf9s68n/bezK/23ryv9s68n/a+vJ/2zsyv9a6dL/JqCB/5ps + Qv+7hmL/3bCQ/+/Kr//wzrf/7s64/+zMt//qy7b/6Mm1/+XGs//jxLH/4MKv/96/rv/bvaz/2buq/9e5 + qf/Vt6f/07Wl/9Cyo//Mrp7/vpmJ/6J3av99W0//STEr/5hfIP/86Kz/+Oet//fjo//3353/9duV//TX + jv/y0of/8M18/+3Fa//quFP/5ag3/+OiL4naixcB4J0rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAHtqeAB7ZngAe2Z0jINui1ybeqf8v4bD/N+O2/z7luf9F5rv/Sue9/1Dnv/9W6MH/W+nC/1/p + xP9i6cX/ZerG/2fqx/9o6sf/aerH/2jqx/9o6sf/ZurG/2Xqxf9g7NH/HK2Q/4huRP+2gV7/1aqL/+3J + sP/v0Lr/7tC8/+zPvP/rzrv/6cy5/+bJuP/kx7b/4sW0/+DDs//dwbH/27+v/9m9rv/Xu6z/1bmq/9K1 + p//JqZn/s4p7/5RrX/9oTkT/TyYZ/8h9NP/867b/9+Sn//bgoP/13Zn/9NmS//LUi//wz4L/7sh2/+u/ + Yv/nr0b/46My4+KfLjLioC8A4qQuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHticABzY + mgAy58EAH9uhfyTdp/8t4K3/NeOz/z7kt/9E5br/Sea8/0/nvv9U58D/WejC/13pw/9g6cT/YunF/2Pq + xf9k6sX/ZerG/2Xqxf9j6sX/YunE/1/pw/9i7c7/Gbmf/3RxSf+yfFr/zKKF/+rHrv/v0b3/7tPA/+zR + wP/r0L7/6c69/+fMvP/lyrr/48i5/+HHt//fxbb/3cO0/9rBsv/YvrD/1rut/9CzpP+/mon/o3lr/35c + Uf9ROTH/jC0G/+ijV//56rf/9uCi//XdnP/02ZX/89WO//HQhv/uy33/7MNt/+m3Vv/kpzn/46AvjOCX + JgPinS0A4p8tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3ZnAAg26EAH9qgIyPd + pNMq36r/M+Kw/zzjtf9D5bn/SOa8/07nvv9T6MD/V+jB/1vpwv9e6cT/YOnF/2Hpxf9i6cX/YunF/2Hp + xP9g6cP/XejC/1rnwP9g7Mn/JMWr/2B4UP+vd1T/w5t//+XErP/u0r7/7tTC/+zUw//r0sL/6dDB/+fP + wP/lzb7/48u9/+LJu//gx7n/3cW3/9vDtf/ZwLL/1Lmr/8akk/+vhHX/jWZb/15IP/91MBT/xkcG/+/F + fv/35a//9d2d//TZl//y1ZD/8dGJ/+/Mgv/txnX/6r1i/+atRv/ioDHW4Z0tKOKeLgDini0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2p8ALuGtACTcpGkp3qn4MuGv/zrj + tP9C5Lj/Sea8/07mvv9T58H/V+jC/1row/9d6cX/XunF/1/pxf9g6cX/YOnE/1/pw/9c6ML/WejB/1bn + v/9b68T/L9C1/0l/Wv+rcU//upV6/9+/qP/t0sD/7dXF/+zVxv/r1Mb/6dPF/+fRxP/m0ML/5M7A/+LM + vv/gybz/3se6/9vEt//XvbD/y6qa/7aMfP+YbmL/alBH/2c2IP+5OwL/0Wgd//Xcov/13qP/89mY//LV + kv/x0Iv/78yE/+3He//rv2v/57NT/+OkN/fhnS5o5KQ1AOGcLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf2qAAJdylACTbpBEq3qmvMeCu/zrjtP9C5bn/Sea9/0/n + wP9U6ML/V+nD/1vpxf9d6sb/XurG/1/qxv9f6sb/XurF/13pxP9a6cL/V+jA/1Pnvv9W6cH/ONm8/zCJ + Z/+jbUn/s450/9e3ov/q0cD/7dbI/+zWyf/r1sj/6dXI/+jTxv/m0cT/5M/D/+LNwf/gyr7/3ca6/9i+ + sP/Lq5v/uY9//55yZv9xVEz/Zzkl/7dCCP/FQwH/35pP//birf/z2Jj/8tST//DQjP/vzIX/7cd+/+vB + cf/ot13/5KhA/+GeL6PgmisO4JwtAOGdLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAFOCmACreqAAr3qk0MeCu2Tnjtf9C5br/See+/1Dowf9V6sT/WerF/1zr + x/9e68j/YOvI/2DryP9f68j/XurG/1zqxf9Y6cP/VejA/1Dnvv9Q6L7/P9+//yGVdf+YaUX/rYdt/86v + mf/oz77/7NbH/+vXyv/q1sn/6NXI/+fTx//l0cX/5M/C/+HMv//dx7n/1rur/8mmlf+3jHz/nXFl/3FT + S/9vPSP/ukgH/8lKBP/FVxD/78qK//PaoP/x05H/8M+M/+7Lhv/sx3//68F0/+m5ZP/lrEn/4Z8yzOCZ + KyXgmywA4Z4vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAJNmfAC3dqQAR1IwBM+CvjDrjtv9D5rz/S+fA/1LpxP9X6sf/XOvJ/1/ryv9h68v/YuvM/2Lr + y/9h68r/X+rJ/1zqx/9Y6MT/VOfB/0/mv/9M5rz/RePB/x6hg/+JZ0P/qH9k/8Wlj//jybj/6dPF/+rV + yP/p1Mj/59PH/+XRxf/jzsL/4Mm8/9rAsv/RsqH/w52L/7KEdv+Va2D/bk5E/4JCHf/FUAj/zVMG/75H + Av/ZkEb/89uj//DRkf/vzYv/7smF/+zFf//rwXb/6bpn/+avUP/ioTfd4JkrQeCdLwDitD8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAINaWACrd + pwAo26M0MuCu2TzkuP9G57//TejD/1Tqx/9a68r/X+zN/2Lszv9k7M//Ze3P/2Xsz/9j7M7/YevM/13q + yf9Z6cb/VOjD/07nwP9K5rz/SubB/xqtj/91ZUT/o3VY/7qZgv/cwK7/5c6//+XQwv/kz8H/4su9/9/G + t//Zvq3/0rKg/8mij/+7jn7/pXds/4RdVf93SjT/o00T/9BaCP/NWAj/wU4F/8VhF//tx4n/8NKV/+7L + if/tyIT/7MR+/+rAd//ouWn/5rBV/+KiO+Tgmi1T79dqAN+VKADgmSoAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2JwAI9mfACHYnRYp26W0NOGx/0Dm + vP9J6ML/UerG/1jryv9e7M3/Yu3Q/2bu0f9o7tL/ae7S/2ju0v9m7tD/Y+3O/1/sy/9a6sj/VenF/0/o + wv9J577/TOnC/xe5nP9fZUn/nWVG/6qBZf/NqI//2rqk/9q7p//YuKP/1LKd/86pk//Gm4j/uot8/6Z4 + bP+NYVf/gVE7/5tSHf/HXwz/1WMI/8xcCf/EVAf/vVAG/96kYP/w0pj/7cmH/+zGgv/rwn3/6r52/+i5 + av/lr1b/4qM+4t+aL1jUbwAB35YpAN+XKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2JwAAMl6ASTaoXos3qr9OeS3/0XowP9O6sb/VuvK/1zs + zv9j7tH/Z+7T/2rv1f9t79b/be/W/2zv1f9q79T/Z+7S/2Ltz/9d7Mz/WOrI/1Lpxf9N6MH/UOrE/x7G + qP9IaVL/jEs5/5NhTP+zgWz/wpN+/8GSf/+7jHv/s4Jz/6d1aP+aZ1n/kFxG/5NYMP+rXhr/y2kN/9lt + Cv/SaAv/ymAK/8RZCf+8TwX/0oZA/+7Mkf/sxoX/68N//+rAev/pvHP/57Zo/+SuVf/hoj/W35ovTNNi + AAHflioA35crAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAg2qAAHtmeGCbdpsgy4rH/Pua9/0npxP9T68r/Wu3O/2Hu0v9o79X/bfDX/3Hx + 2f9y8dr/c/Ha/3Lx2f9v8Nf/a+/V/2bu0v9h7c//W+zM/1bryP9S6cX/VezG/y7Ttv84clP/jzMU/5JG + Hv+gWiz/p2U1/6dmNf+nZjD/qmYp/7FoIP+9bhf/zXUQ/9l5Df/beAz/1XEM/85qC//JYwr/xF0K/7xT + Bv/KdjL/6sKH/+vEhP/qv3v/6b13/+e5cP/ms2T/5KtS/uGhPrrfmTA0569OAN6VKgDflywAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAj3KMAH9qfCyvfrJs147X9QOa+/0rpxf9U68r/XO3Q/2Tv0/9r8Nf/cfHa/3Xy2/9389z/d/Pc/3by + 3P908dr/cPHY/2rv1f9k7tL/X+3O/1rsy/9W68n/WezJ/zzdwf8vhmb/pz0H/7tXCP/HbQz/znkO/9J+ + Dv/WgQ//2YMQ/9qCD//ZgA7/13wP/9N2Dv/QcQ3/zGsN/8hmC//EYAn/vFYG/8d0L//nu3//6sCA/+i8 + dv/nuXL/5rVr/+SwXv/jqE3u4KA9jN+XLhjgnDUA3I8iAN6WLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3JsALOCtAC7g + rxg14rVvP+W8nEjnw7BR6sjHWuzO3WLu0u5p8Nb2b/HZ+XPy2/128tz/d/Pd/3bz3f9z9N3/b/Pc/2rx + 2P9l79P/YO3P/1zszP9a68r/XezK/zrjyf87iGf/qEAG/7dYCv/CaQ3/yXMP/8x4EP/PehD/0HoQ/9B6 + EP/Qdw//znQO/8xwDf/Jaw3/xmcM/8FgCf+8WQj/yXo2/+a3e//pvXv/57hx/+a1bf/ksWT/46tW++Gl + SL/gnTpN3ZElBt+aMwDgmzUA3pUsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm3KcAOeW5AC3grgA14rUAPOO6Akbl + wQ1P6ccYV+vMI2Dt0i5n79ZBbfDYW3Dx2ndz8dyRdPHcp3Py27l04MffcN7D/2nny/9h7dH/W/HU/1fy + 0/9W8tP/TvLT/ynNtf95YDD/r0kF/7dbC/+/Zg3/xG0O/8dwDv/Jcg//ynMP/8pyDv/JcA7/yG0N/8Zq + DP/DZQv/vl4G/71hEv/Ri0n/5rZ6/+e3c//lsmr/5LBj/+OrWf3ipk7N4KFCbN+bNRbjpkoA35kyAOCe + PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvkuQAx4rAAPuW8AEfmwQBP6ccAWOzNAGDt + 0gBn79YAbvDZAHTy2wB389wAKf//AHLkywqKg1kukHJEgZJsOdKPdT/7iIRR/3+WZ/93o3b/a5Ro/4Zk + Lv+tSgb/sVUJ/7ddC/+8Ywz/v2YN/8FoDf/Cag3/w2oN/8RqDf/DaQ3/wWYM/75hCf+9YQ3/x3ct/9uh + Yf/mtXP/5LBn/+OsX//iqVfx4aVOwOCiRWrfnDoc46tUAOCeOgDckCQA3pgxAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABx8dsAbf/wAHXcwgCGkWcA/wAAAK8vAB+rPgBfq0QAq6tGBeGsSAb3r0oF/7BOBf+vVAr/s1gK/7Zb + C/+4Xwv/umEM/7xiDP+9Ywz/vWIL/7xhCv+8YQr/vmUR/8d3LP/Xl1T/4q1p/+OsYv/hp1bu4aVRz+Cj + TI3goEVI3ps4EeKvXgDfnj0A4q5VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKcv + AACjXAsAoj0IAKdIBQCpQQAAqFcOCapTCyirUgpdrVIJjK5TCbewVQncslcK7rNYCvO0Wgr3tVsK+rdc + Cvy4Xgz8vGMR+8JvHvjNgzX12ZlP8OGmXOXiplfH4KJNn9+gSHbfnkRD350/FtuPIQPgoUYA3pw7AN6c + PADgoEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKlN + CACpTQgAqU8JAKpQCgCsUQkAslMIAa5TCRCwVAkfsFUKMLBVCkawVQlZtFsMab1lE3TEbxx1zXwncNeP + PGDenExP4aNRON+dQyTdlzQW3JEpB+ClUADfn0YA4J9FAN+dPwDfmDMA35s5AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK1R + CQC1WQkArlIJAK5TCQCwVAkAsVUKALJXCgCzWQoAs1gJALVZCgC4Xg4AwGsbANCHOQDgpFkA46lcAN+f + SQDemj0A3pk7AN6ZOwDemTsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8AAAAAAAP/8AAAD/4AAAAAAAD/8A + AAD/AAAAAAAAAf8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8A + AAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAD8A + AAD/gAAAAAAAAA8AAAD/gAAAAAAAAAcAAAD/wAAAAAAAAAcAAAD/AAAAAAAAAAcAAAD/AAAAAAAAAAcA + AAD+AAAAAAAAAAcAAAD+AAAAAAAAAAcAAAD8AAAAAAAAAA8AAAD8AAAAAAAAAB8AAAD4AAAAAAAAAD8A + AADwAAAAAAAAAB8AAADwAAAAAAAAAB8AAADwAAAAAAAAAA8AAADgAAAAAAAAAA8AAADgAAAAAAAAAAcA + AADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADAAAAAAAAAAAcAAADAAAAAAAAAAAcAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADgAAAAAAAAAAMAAADgAAAAAAAAAAcA + AADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADwAAAAAAAAAA8AAADwAAAAAAAAAA8A + AADwAAAAAAAAAA8AAAD4AAAAAAAAAB8AAAD8AAAAAAAAAD8AAAD8AAAAAAAAAD8AAAD+AAAAAAAAAH8A + AAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD8AAAAAAAAAf8AAAD8AAAAAAAAA/8AAAD8AAAAAAAAB/8A + AAD8AAAAAAAAD/8AAAD8AAAAAAAAH/8AAAD8AAAAAAAAf/8AAAD/AAAAAAAA//8AAAD//8AAAAAH//8A + AAD///AAAAAP//8AAAD///4AAAA///8AAAD////AAAP///8AAAD///////////8AAAD///////////8A + AAA= +</value> + </data> +</root> \ No newline at end of file diff --git a/PCRobot/PCWechat/BaseApi - 复制.cs b/PCRobot/PCWechat/BaseApi - 复制.cs new file mode 100644 index 0000000..29cba65 --- /dev/null +++ b/PCRobot/PCWechat/BaseApi - 复制.cs @@ -0,0 +1,329 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.PCWechat +{ + public class BaseApi + { + public static bool IsInstall { get; protected set; } = false; + public static bool IsKsfInstall { get; protected set; } = false; + public static bool IsQYInstall { get; protected set; } = false; + + public WechatUser User { get; private set; } + public BaseApi(WechatUser User) + { + this.User = User; + } + + const string NotImplemented = "当前版本暂时不支持此操作!"; + + /// <summary> + /// 服务器的消息包命令 + /// </summary> + public string ServerMsgID { get; set; } + + /// <summary> + /// 发送消息 + /// </summary> + /// <param name="wxid">发给谁</param> + /// <param name="message">消息内容</param> + public virtual void SendMessage(string wxid, string message) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送文件消息 + /// </summary> + /// <param name="wxid">接收者的微信</param> + /// <param name="file">文件的路径</param> + public virtual void SendFile(string wxid, string file) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取朋友圈 + /// </summary> + /// <param name="circleId">首页传0,后续的最后一个朋友圈的object_id</param> + /// <param name="username">获取谁的朋友圈,为空时查询朋友圈首页</param> + public virtual void FindCircles(string circleId, string username) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 小程序自动授权登录 + /// </summary> + /// <param name="appid">小程序的id</param> + public virtual void AutoAuthMiniAPPLogin(string appid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送朋友圈 + /// </summary> + /// <param name="xmlmsg">朋友圈xml</param> + public virtual void SendCircle(string xmlmsg) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送朋友圈评论 + /// </summary> + /// <param name="circleId"></param> + /// <param name="content"></param> + public virtual void SendCircleComment(string circleId, string content) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 朋友圈点赞 + /// </summary> + /// <param name="circleId">朋友圈的object_id</param> + public virtual void SendCirclePraise(string circleId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 朋友圈上传本地图片 + /// </summary> + /// <param name="circleId"></param> + public virtual void CircleUpLoadImage(string path) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送图片 + /// </summary> + /// <param name="wxid">接收者的微信</param> + /// <param name="path">图片的路径</param> + public virtual void SendImage(string wxid, string path) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送视频 + /// </summary>MT_SEND_VIDEOMSG + /// <param name="wxid"></param> + public virtual void SendVideo(string wxid, string path) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送小程序 + /// </summary> + /// <param name="wxid"></param> + /// <param name="dataJson"></param> + public virtual void SendProgramMessage(string wxid, string dataJson) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 查询好友信息 + /// </summary> + /// <param name="wxid">好友的微信ID</param> + public virtual void GetFriend(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + + /// <summary> + /// 同意加我好友 + /// </summary> + /// <param name="text">申请好友的校验信息</param> + public virtual void AgreeAddMe(string text) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送卡片 + /// </summary> + /// <param name="to_wxid">接收者的微信</param> + /// <param name="card_wxid">名片人的微信</param> + public virtual void SendCard(string to_wxid, string card_wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 创建群(支持企业和普通微信) + /// </summary> + /// <param name="wxidJson"></param> + public virtual void CreateRoom(string wxidData) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 邀请用户进群,40人以下无需告知用户,直接进群 + /// </summary> + /// <param name="wxidData"></param> + public virtual void InviteMemberToRoom_40Down(string groupid, string wxidData) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 邀请用户进群,40人以上发送群邀请卡片 + /// </summary> + /// <param name="message"></param> + public virtual void InviteMemberToRoom_40Up(string groupId, string wxidData) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 移除群用户 + /// </summary> + /// <param name="room">群id</param> + /// <param name="wxid">用户账号</param> + public virtual void DeleteRoomMember(string wxid, string room) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取通讯录 + /// </summary> + public virtual void GetContact() { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取通信录刷新 + /// </summary> + /// <param name="isUpdate"></param> + public virtual void GetContact(bool isUpdate) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取好友列表 + /// </summary> + /// <param name="flushGroupsCache">刷新缓存数据</param> + /// <returns></returns> + //public virtual List<FriendInfo> GetFriendInfos(bool flushGroupsCache = false) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + public virtual string GetFriendInfos(bool flushGroupsCache = false) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取群列表(不包含群成员) + /// </summary> + public virtual void GetGroupsNotInMember() { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 领取转账 + /// </summary> + /// <param name="data"></param> + public virtual void PayTransferConfirm(string data) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 删除好友 + /// </summary> + /// <param name="wxid">要删除的好友微信</param> + public virtual void DeleteFriend(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 用户备注 + /// </summary> + /// <param name="wxid">备注的用户微信</param> + /// <param name="remark">备注的内容,删除备注内容为空</param> + public virtual void EditCotacts(string wxid, string remark) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 置顶 + /// </summary> + /// <param name="wxid">好友或群聊wxid</param> + /// <param name="status">0是取消置顶,1置顶</param> + public virtual void StateOpt(string wxid, int status) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取微信用户的详细信息 + /// </summary> + /// <param name="wxid"></param> + public virtual void GetWxidInfo(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取群和用户 + /// </summary> + /// <param name="wxid"></param> + public virtual void GetGroupAndFriendInfo(string groupId, string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取群和用户 + /// </summary> + /// <param name="groupId"></param> + /// <param name="wxid"></param> + public virtual void GetGroupAndFriendInfo(string groupId, string wxid, bool flush = false) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取群成员 + /// </summary> + /// <param name="groupId"></param> + public virtual void GetGroupMemer(string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 刷新微信用户的详细信息(网络刷新) + /// </summary> + /// <param name="wxid"></param> + public virtual void UpdateWxidInfo(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 解密微信加密的图片(.dat) + /// </summary> + /// <param name="src_file">微信加密图片路径</param> + /// <param name="dest_file">解密后的文件路径</param> + public virtual void DecryptImage(string src_file, string dest_file) { throw new Exception(NotImplemented); } + + /// <summary> + /// 刷新微信群的详细信息(网络刷新) + /// </summary> + /// <param name="wxid"></param> + public virtual void UpdateGroupInfo(string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取当前登录版本微信 + /// </summary> + public virtual string GetVersion() { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 退出当前微信 + /// </summary> + public virtual void CloseWechat(string message) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 检测URL在微信中是否有效 + /// </summary> + /// <param name="url"></param> + /// <returns></returns> + public virtual void CheckUrl(string url) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 打开内置浏览器 + /// </summary> + /// <param name="url"></param> + public virtual void OpenUrl(string url) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 清理历史聊天记录 + /// </summary> + public virtual void ClearChatHistoryMsg() { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 设置会话为已读 + /// </summary> + public virtual void SetSessionReadedMsg(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 修改群聊名称 + /// </summary> + /// <param name="new_name">新的群名</param> + /// <param name="groupId">群id</param> + public virtual void SetRoomName(string new_name, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 修改群公告(可用于@全体) + /// </summary> + /// <param name="notice">新公告</param> + /// <param name="groupId">群聊wxid</param> + public virtual void SetRoomNotice(string notice, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 设置自己在群中昵称 + /// </summary> + /// <param name="nickname">要设置的昵称</param> + /// <param name="groupId">需要设置的群id</param> + public virtual void ModRoomMyName(string nickname, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 设置是否显示群成员昵称 + /// </summary> + /// <param name="status">true为开启</param> + /// <param name="groupId">要显示得到群</param> + public virtual void SetRoomShowMemeberName(bool status, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 修改群聊名称 + /// </summary> + /// <param name="newnick">新名称</param> + /// <param name="groupId">群号</param> + public virtual void ModRoomName(string newnick, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 是否消息免打扰 + /// </summary> + /// <param name="status">true为开启</param> + /// <param name="wxid">wxid</param> + public virtual void SetRecvNotify(bool status, string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 关注公众号 + /// </summary> + /// <param name="wxid">公众号wxid</param> + public virtual void AddPublicUser(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 开启/关闭防撤回功能 + /// </summary> + /// <param name="status">1是开启防撤回,0是关闭</param> + public virtual void SetDisableRevoke(bool status) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + public virtual + + } +} diff --git a/PCRobot/PCWechat/BaseApi.cs b/PCRobot/PCWechat/BaseApi.cs new file mode 100644 index 0000000..0601942 --- /dev/null +++ b/PCRobot/PCWechat/BaseApi.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.PCWechat +{ + public class BaseApi + { + public static bool IsInstall { get; protected set; } = false; + public static bool IsKsfInstall { get; protected set; } = false; + public static bool IsQYInstall { get; protected set; } = false; + + public WechatUser User { get; private set; } + public BaseApi(WechatUser User) + { + this.User = User; + } + + const string NotImplemented = "当前版本暂时不支持此操作!"; + + /// <summary> + /// 服务器的消息包命令 + /// </summary> + public string ServerMsgID { get; set; } + + /// <summary> + /// 发送消息 + /// </summary> + /// <param name="wxid">发给谁</param> + /// <param name="message">消息内容</param> + public virtual void SendMessage(string wxid, string message) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送文件消息 + /// </summary> + /// <param name="wxid">接收者的微信</param> + /// <param name="file">文件的路径</param> + public virtual void SendFile(string wxid, string file) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取朋友圈 + /// </summary> + /// <param name="circleId">首页传0,后续的最后一个朋友圈的object_id</param> + /// <param name="username">获取谁的朋友圈,为空时查询朋友圈首页</param> + public virtual void FindCircles(string circleId, string username) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 小程序自动授权登录 + /// </summary> + /// <param name="appid">小程序的id</param> + public virtual void AutoAuthMiniAPPLogin(string appid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送朋友圈 + /// </summary> + /// <param name="xmlmsg">朋友圈xml</param> + public virtual void SendCircle(string xmlmsg) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送朋友圈评论 + /// </summary> + /// <param name="circleId"></param> + /// <param name="content"></param> + public virtual void SendCircleComment(string circleId, string content) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 朋友圈点赞 + /// </summary> + /// <param name="circleId">朋友圈的object_id</param> + public virtual void SendCirclePraise(string circleId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 朋友圈上传本地图片 + /// </summary> + /// <param name="circleId"></param> + public virtual void CircleUpLoadImage(string path) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送图片 + /// </summary> + /// <param name="wxid">接收者的微信</param> + /// <param name="path">图片的路径</param> + public virtual void SendImage(string wxid, string path) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送视频 + /// </summary>MT_SEND_VIDEOMSG + /// <param name="wxid"></param> + public virtual void SendVideo(string wxid, string path) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送小程序 + /// </summary> + /// <param name="wxid"></param> + /// <param name="dataJson"></param> + public virtual void SendProgramMessage(string wxid, string dataJson) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 查询好友信息 + /// </summary> + /// <param name="wxid">好友的微信ID</param> + public virtual void GetFriend(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + + /// <summary> + /// 同意加我好友 + /// </summary> + /// <param name="text">申请好友的校验信息</param> + public virtual void AgreeAddMe(string text) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 发送卡片 + /// </summary> + /// <param name="to_wxid">接收者的微信</param> + /// <param name="card_wxid">名片人的微信</param> + public virtual void SendCard(string to_wxid, string card_wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 创建群(支持企业和普通微信) + /// </summary> + /// <param name="wxidJson"></param> + public virtual void CreateRoom(string wxidData) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 邀请用户进群,40人以下无需告知用户,直接进群 + /// </summary> + /// <param name="wxidData"></param> + public virtual void InviteMemberToRoom_40Down(string groupid, string wxidData) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 邀请用户进群,40人以上发送群邀请卡片 + /// </summary> + /// <param name="message"></param> + public virtual void InviteMemberToRoom_40Up(string groupId, string wxidData) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 移除群用户 + /// </summary> + /// <param name="room">群id</param> + /// <param name="wxid">用户账号</param> + public virtual void DeleteRoomMember(string wxid, string room) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取通讯录 + /// </summary> + public virtual void GetContact() { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取通信录刷新 + /// </summary> + /// <param name="isUpdate"></param> + public virtual void GetContact(bool isUpdate) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取好友列表 + /// </summary> + /// <param name="flushGroupsCache">刷新缓存数据</param> + /// <returns></returns> + //public virtual List<FriendInfo> GetFriendInfos(bool flushGroupsCache = false) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + public virtual string GetFriendInfos(bool flushGroupsCache = false) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取群列表(不包含群成员) + /// </summary> + public virtual void GetGroupsNotInMember() { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 领取转账 + /// </summary> + /// <param name="data"></param> + public virtual void PayTransferConfirm(string data) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 删除好友 + /// </summary> + /// <param name="wxid">要删除的好友微信</param> + public virtual void DeleteFriend(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 用户备注 + /// </summary> + /// <param name="wxid">备注的用户微信</param> + /// <param name="remark">备注的内容,删除备注内容为空</param> + public virtual void EditCotacts(string wxid, string remark) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 置顶 + /// </summary> + /// <param name="wxid">好友或群聊wxid</param> + /// <param name="status">0是取消置顶,1置顶</param> + public virtual void StateOpt(string wxid, int status) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取微信用户的详细信息 + /// </summary> + /// <param name="wxid"></param> + public virtual void GetWxidInfo(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取群和用户 + /// </summary> + /// <param name="wxid"></param> + public virtual void GetGroupAndFriendInfo(string groupId, string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取群和用户 + /// </summary> + /// <param name="groupId"></param> + /// <param name="wxid"></param> + public virtual void GetGroupAndFriendInfo(string groupId, string wxid, bool flush = false) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取群成员 + /// </summary> + /// <param name="groupId"></param> + public virtual void GetGroupMemer(string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 刷新微信用户的详细信息(网络刷新) + /// </summary> + /// <param name="wxid"></param> + public virtual void UpdateWxidInfo(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 解密微信加密的图片(.dat) + /// </summary> + /// <param name="src_file">微信加密图片路径</param> + /// <param name="dest_file">解密后的文件路径</param> + public virtual void DecryptImage(string src_file, string dest_file) { throw new Exception(NotImplemented); } + + /// <summary> + /// 刷新微信群的详细信息(网络刷新) + /// </summary> + /// <param name="wxid"></param> + public virtual void UpdateGroupInfo(string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 获取当前登录版本微信 + /// </summary> + public virtual string GetVersion() { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 退出当前微信 + /// </summary> + public virtual void CloseWechat(string message) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 检测URL在微信中是否有效 + /// </summary> + /// <param name="url"></param> + /// <returns></returns> + public virtual void CheckUrl(string url) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 打开内置浏览器 + /// </summary> + /// <param name="url"></param> + public virtual void OpenUrl(string url) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 清理历史聊天记录 + /// </summary> + public virtual void ClearChatHistoryMsg() { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 设置会话为已读 + /// </summary> + public virtual void SetSessionReadedMsg(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 修改群聊名称 + /// </summary> + /// <param name="new_name">新的群名</param> + /// <param name="groupId">群id</param> + public virtual void SetRoomName(string new_name, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 修改群公告(可用于@全体) + /// </summary> + /// <param name="notice">新公告</param> + /// <param name="groupId">群聊wxid</param> + public virtual void SetRoomNotice(string notice, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 设置自己在群中昵称 + /// </summary> + /// <param name="nickname">要设置的昵称</param> + /// <param name="groupId">需要设置的群id</param> + public virtual void ModRoomMyName(string nickname, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 设置是否显示群成员昵称 + /// </summary> + /// <param name="status">true为开启</param> + /// <param name="groupId">要显示得到群</param> + public virtual void SetRoomShowMemeberName(bool status, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 修改群聊名称 + /// </summary> + /// <param name="newnick">新名称</param> + /// <param name="groupId">群号</param> + public virtual void ModRoomName(string newnick, string groupId) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 是否消息免打扰 + /// </summary> + /// <param name="status">true为开启</param> + /// <param name="wxid">wxid</param> + public virtual void SetRecvNotify(bool status, string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 关注公众号 + /// </summary> + /// <param name="wxid">公众号wxid</param> + public virtual void AddPublicUser(string wxid) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + /// <summary> + /// 开启/关闭防撤回功能 + /// </summary> + /// <param name="status">1是开启防撤回,0是关闭</param> + public virtual void SetDisableRevoke(bool status) { throw new Exception(NotImplemented + new System.Diagnostics.StackTrace().GetFrame(0).GetMethod()?.Name); } + + } +} diff --git a/PCRobot/PCWechat/Dazong/Extra.cs b/PCRobot/PCWechat/Dazong/Extra.cs new file mode 100644 index 0000000..46b0985 --- /dev/null +++ b/PCRobot/PCWechat/Dazong/Extra.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections.Concurrent; + +namespace HPSocketCS +{ + public class Extra<T> + { + ConcurrentDictionary<IntPtr, T> dict = new ConcurrentDictionary<IntPtr, T>(); + + /// <summary> + /// 获取附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public T Get(IntPtr key) + { + T value; + if (dict.TryGetValue(key, out value)) + { + return value; + } + return default(T); + } + + /// <summary> + /// 设置附加数据 + /// + /// </summary> + /// <param name="key"></param> + /// <param name="newValue"></param> + /// <returns></returns> + public bool Set(IntPtr key, T newValue) + { + try + { + dict.AddOrUpdate(key, newValue, (tKey, existingVal) => { return newValue; }); + return true; + } + catch (OverflowException) + { + // 字典数目超过int.max + return false; + } + catch (ArgumentNullException) + { + // 参数为空 + return false; + } + catch (Exception) + { + return false; + } + } + + /// <summary> + /// 删除附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public bool Remove(IntPtr key) + { + T value; + return dict.TryRemove(key, out value); + } + } + + + public class ConnectionExtra + { + ConcurrentDictionary<IntPtr, object> dict = new ConcurrentDictionary<IntPtr, object>(); + + /// <summary> + /// 获取附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public object GetExtra(IntPtr key) + { + object value; + if (dict.TryGetValue(key, out value)) + { + return value; + } + return null; + } + + /// <summary> + /// 获取附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public T GetExtra<T>(IntPtr key) + { + object value; + if (dict.TryGetValue(key, out value)) + { + return (T)value; + } + return default(T); + } + + /// <summary> + /// 设置附加数据 + /// + /// </summary> + /// <param name="key"></param> + /// <param name="value"></param> + /// <returns></returns> + public bool SetExtra(IntPtr key, object newValue) + { + try + { + dict.AddOrUpdate(key, newValue, (tKey, existingVal) => { return newValue; }); + return true; + } + catch (OverflowException) + { + // 字典数目超过int.max + return false; + } + catch (ArgumentNullException) + { + // 参数为空 + return false; + } + catch (Exception) + { + return false; + } + } + + /// <summary> + /// 删除附加数据 + /// </summary> + /// <param name="key"></param> + /// <returns></returns> + public bool RemoveExtra(IntPtr key) + { + object value; + return dict.TryRemove(key, out value); + } + } +} diff --git a/PCRobot/PCWechat/Dazong/NMCore.cs b/PCRobot/PCWechat/Dazong/NMCore.cs new file mode 100644 index 0000000..407e91b --- /dev/null +++ b/PCRobot/PCWechat/Dazong/NMCore.cs @@ -0,0 +1,623 @@ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Utils; + +namespace NM_WeChat +{ + public class NMCore + { + HPSocketCS.TcpPackServer g_HPServer; + public NMCore(HPSocketCS.TcpPackServer HPServer) + { + g_HPServer = HPServer; + } + + public void SendPacket(int ConnID, string Packet) + { + byte[] PackBytes = System.Text.ASCIIEncoding.Default.GetBytes(Packet.ToString()); + g_HPServer.Send((IntPtr)ConnID, PackBytes, PackBytes.Length); + } + /// <summary> + /// 初始化,传输DLL调用密码,用于简单的防止DLL被盗用 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="PassWord"></param> + public void NM_Init(int ConnID, string PassWord) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = 100000; + sendJson["PassWord"] = PassWord; + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_读取通讯录列表 + /// </summary> + /// <param name="ConnID"></param> + public void NM_GetContactList(int ConnID, int PackMark, int PackSize = 5000) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetContactList; + sendJson["PackMark"] = PackMark; + sendJson["PackSize"] = PackSize; + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_读取群员列表 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="GroupID"></param> + public void NM_GetGroupMember(int ConnID, string GroupID) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetGroupMember; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_下载用户详细信息 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="GroupID"></param> + /// <param name="Wxid"></param> + public void NM_GetWxidInfo(int ConnID, string GroupID, string Wxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetWxidInfo; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_GetA8Key 微信浏览器操作 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="URL"></param> + public void NM_GetA8Key(int ConnID, string Wxid, string URL) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetA8Key; + sendJson["Type"] = 1; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["URL"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(URL)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_发送文本消息 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param>3 + /// <param name="AtWxidArray"></param> + /// <param name="Message"></param> + public void NM_SendTextMsg(int ConnID, string Wxid, string[] AtWxidArray, string Message) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendText; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Message"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Message)); + if (AtWxidArray.Length > 0) + { + JArray AtList = new JArray(); + for (int i = 0; i < AtWxidArray.Length; i++) + { + if (AtWxidArray[i] != string.Empty) + { + AtList.Add(Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(AtWxidArray[i]))); + } + } + if (AtList.Count > 0) { sendJson["AtWxid"] = AtList; } + } + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_发送文件消息 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Type"></param> + /// <param name="Wxid"></param> + /// <param name="FilePath">欲发送文件的完整路径</param> + public void NM_SendFileMsg(int ConnID, int Type, string Wxid, string FilePath) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = Type; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["File"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(FilePath)); + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_发送名片消息 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="CardWxid"></param> + public void NM_SendCardMsg(int ConnID, string Wxid, string CardWxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendCard; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["CardWxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(CardWxid)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_发送地图定位消息 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="MapXML"></param> + public void NM_SendMapMsg(int ConnID, string Wxid, string MapXML) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendMap; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Map"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(MapXML)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_发送图文链接消息 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="XML"></param> + public void NM_SendURLMsg(int ConnID, string Wxid, string XML) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendURL; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["XML"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(XML)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_发送小程序 2.7及以上版本有效 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="XML"></param> + /// <param name="ShowImage"></param> + public void NM_SendWeChatApp(int ConnID, string Wxid, string XML, string ShowImage) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendWeChatApp; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["XML"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(XML)); + sendJson["Image"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(ShowImage)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_撤回发出消息 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="ServerID"></param> + /// <param name="Message"></param> + public void NM_RevokeMsg(int ConnID, string Wxid, string ServerID, string Message) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_RevokeMsg; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["ServerID"] = ServerID; + sendJson["Message"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Message)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_接收的消息被撤回本地无提示 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Opt"></param> + public void NM_DesRevoke(int ConnID, bool Opt) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_DesRevoke; + sendJson["Opt"] = Opt; + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_接收转账 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="Transid"></param> + /// <param name="Time"></param> + public void NM_GetMoney(int ConnID, string Wxid, string Transid, int Time) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetMoney; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Transid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Transid)); + sendJson["Time"] = Time; + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_通过Wxid或v1添加好友 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Type"></param> + /// <param name="AddType"></param> + /// <param name="Wxid"></param> + /// <param name="v2"></param> + /// <param name="Message"></param> + public void NM_AddFriend(int ConnID, int Type, int AddType, string Wxid, string v2, string Message) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_AddFriend; + sendJson["Type"] = Type; + sendJson["AddType"] = AddType; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["V2"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(v2)); + sendJson["Message"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Message)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_通过请求消息XML通过好友请求 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="ApplyXML"></param> + public void NM_PassApply(int ConnID, string ApplyXML) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_PassApply; + //sendJson["XML"] = ApplyXML; 原代码,改为如下一行 + sendJson["XML"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(ApplyXML)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_删除好友 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + public void NM_DelFriend(int ConnID, string Wxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_DelFriend; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_取消关注公众号 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="GHWxid"></param> + public void NM_DelGHFriend(int ConnID, string GHWxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_DelGHFriend; + sendJson["GH_Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GHWxid)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_设置好友备注 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="Mark"></param> + public void NM_SetFriendMark(int ConnID, string Wxid, string Mark) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetFriendMark; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Mark"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Mark)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_创建群聊 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="MemberArray"></param> + public void NM_CreateGroup(int ConnID, string[] MemberArray) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_CreateGroup; + if (MemberArray.Length > 1 && MemberArray.Length < 40) + { + JArray MemberList = new JArray(); + for (int i = 0; i < MemberArray.Length; i++) + { + if (MemberArray[i] != string.Empty) + { + MemberList.Add(Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(MemberArray[i]))); + } + } + if (MemberList.Count > 0) + { + sendJson["List"] = MemberList; + SendPacket(ConnID, sendJson.ToString()); + } + } + } + /// <summary> + /// 功能_退出群聊 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="GroupID"></param> + public void NM_QuitGroup(int ConnID, string GroupID) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_QuitGroup; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_批量拉群 - 发送邀请链接或直接拉入 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Type"></param> + /// <param name="GroupID"></param> + /// <param name="MemberArray"></param> + public void NM_InviteToGroup(int ConnID, int Type, string GroupID, string[] MemberArray) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = Type; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + if (MemberArray.Length > 0 && MemberArray.Length < 40) + { + JArray MemberList = new JArray(); + for (int i = 0; i < MemberArray.Length; i++) + { + if (MemberArray[i] != string.Empty) + { + MemberList.Add(Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(MemberArray[i]))); + } + } + if (MemberList.Count > 0) + { + sendJson["List"] = MemberList; + SendPacket(ConnID, sendJson.ToString()); + } + } + } + /// <summary> + /// 功能_批量提出群员 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="GroupID"></param> + /// <param name="MemberArray"></param> + public void NM_KickGroupMember(int ConnID, string GroupID, string[] MemberArray) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_KickGroupMember; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + if (MemberArray.Length > 0 && MemberArray.Length < 40) + { + JArray MemberList = new JArray(); + for (int i = 0; i < MemberArray.Length; i++) + { + if (MemberArray[i] != string.Empty) + { + MemberList.Add(Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(MemberArray[i]))); + } + } + if (MemberList.Count > 0) + { + sendJson["List"] = MemberList; + SendPacket(ConnID, sendJson.ToString()); + } + } + } + /// <summary> + /// 功能_修改群名称 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="GroupID"></param> + /// <param name="Name"></param> + public void NM_SetGroupName(int ConnID, string GroupID, string Name) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetGroupName; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + sendJson["Name"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Name)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 群主功能_发送群公告(@所有人) + /// </summary> + /// <param name="ConnID"></param> + /// <param name="GroupID"></param> + /// <param name="Boss"></param> + /// <param name="Notice"></param> + public void NM_SetGroupNotice(int ConnID, string GroupID, string Boss, string Notice) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetGroupNotice; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Boss)); + sendJson["Notice"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Notice)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_设置自己的群昵称 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="GroupID"></param> + /// <param name="Nick"></param> + public void NM_SetMyGroupNick(int ConnID, string GroupID, string Nick) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetMyGroupNick; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + sendJson["Nick"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Nick)); + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_获取收藏列表 + /// </summary> + /// <param name="ConnID"></param> + public void NM_GetFavList(int ConnID) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetFavList; + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_发送指定收藏内容 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Wxid"></param> + /// <param name="Index"></param> + public void NM_SendFavMsg(int ConnID, string Wxid, int Index) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendFavMsg; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Index"] = Index; + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_状态操作 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Type">1=免打扰 2=置顶 3=保存通讯录 4=显示群员昵称</param> + /// <param name="Wxid"></param> + /// <param name="Opt"></param> + public void NM_StateOpt(int ConnID, int Type, string Wxid, bool Opt) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_StateOpt; + sendJson["Type"] = Type; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Opt"] = Opt; + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_对象操作 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="Type"> 1= 切换聊天对象 + /// 2= 设置指定Wxid消息已读(取消红点,不切换聊天对象,移动端同步) + /// 3= 一键全部已读(取消全部红点,移动端不同步) </param> + /// <param name="Wxid"></param> + public void NM_SetObject(int ConnID, int Type, string Wxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetObject; + sendJson["Type"] = Type; + if (Wxid != string.Empty) + { sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); } + SendPacket(ConnID, sendJson.ToString()); + } + /// <summary> + /// 功能_下载高清大图 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="XML"></param> + /// <param name="SavePath"></param> + public void NM_GetImageByCDN(int ConnID, string XML, string SavePath) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetImageByCDN; + sendJson["XML"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(XML)); + sendJson["SavePath"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(SavePath)); + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_获取朋友圈 + /// </summary> + /// <param name="ConnID"></param> + public void NM_GetCircles(int ConnID) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetCircles; + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_获取朋友圈_详情 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="SnsId">朋友圈ID</param> + public void NM_GetCircleDetails(int ConnID, string SnsId) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetCircleDetails; + sendJson["SnsId"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(SnsId)); + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_发朋友圈 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="SnsData">朋友圈内容</param> + public void NM_SendCircle(int ConnID, string SnsData) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendCircle; + sendJson["SnsData"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(SnsData)); + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_朋友圈上传图片 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="ImageFile">图片路径</param> + /// <param name="ImageMD5">图片Md5</param> + public void NM_CircleUpLoadImage(int ConnID, string ImageFile, string ImageMD5) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_CircleUpLoadImage; + sendJson["ImageFile"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(ImageFile)); + sendJson["ImageMD5"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(ImageMD5)); + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_朋友圈评论 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="SnsId">朋友圈ID</param> + /// <param name="Comment">评论内容</param> + public void NM_CircleComment(int ConnID, string SnsId, string Comment) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_CircleComment; + sendJson["SnsId"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(SnsId)); + sendJson["Comment"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Comment)); + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_朋友圈点赞 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="SnsId">朋友圈id</param> + /// <param name="Opt">1=赞 2=取消赞</param> + public void NM_CircleLink(int ConnID, string SnsId, int Opt) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_CircleLink; + sendJson["SnsId"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(SnsId)); + sendJson["Opt"] = Opt; + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_朋友圈删除 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="SnsId">删除朋友圈ID</param> + public void NM_DelCircle(int ConnID, string SnsId) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_DelCircle; + sendJson["SnsId"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(SnsId)); + SendPacket(ConnID, sendJson.ToString()); + } + + /// <summary> + /// 功能_朋友圈删除评论 + /// </summary> + /// <param name="ConnID"></param> + /// <param name="SnsId">朋友圈ID</param> + /// <param name="CommentId">评论ID</param> + public void NM_DelCircleComment(int ConnID, string SnsId, string CommentId) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_DelCircleComment; + sendJson["SnsId"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(SnsId)); + sendJson["CommentId"] = CommentId; + SendPacket(ConnID, sendJson.ToString()); + } + } +} \ No newline at end of file diff --git a/PCRobot/PCWechat/Dazong/NMHelper.cs b/PCRobot/PCWechat/Dazong/NMHelper.cs new file mode 100644 index 0000000..48bd829 --- /dev/null +++ b/PCRobot/PCWechat/Dazong/NMHelper.cs @@ -0,0 +1,329 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using System.Text; +using System.Windows.Forms; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.Net; +using System.Drawing; + +namespace NM_WeChat +{ + + public class NMHelper + { + public int Socket_Handle { get; set; } + public int Socket_Port { get; set; } + public int Socket_ConnId { get; set; } + public string Socket_MyWxid { get; set; } + public string Socket_GroupID { get; set; } + + public struct nmWxidInfo + { + public int Type { get; set; } + public int List { get; set; } + public string Wxid { get; set; } + public string WxNo { get; set; } + public string Nick { get; set; } + public string Mark { get; set; } + public string V1 { get; set; } + public string HeadIMG { get; set; } + public string Sex { get; set; } + public string Address { get; set; } + public string Phone { get; set; } + public string Config { get; set; } + public string GetSex(int uSex) + { + if (uSex == 1) + return "男"; + else if (uSex == 2) + return "女"; + else + return "未知(" + uSex.ToString() + ")"; + } + } + + + public struct nmMsgInfo + { + public string RecvWxid { get; set; } + public int Type { get; set; } + public int State { get; set; } + public int Time { get; set; } + public int IsSend { get; set; } + public int LocalMsgID { get; set; } + public string ServerMsgID { get; set; } + public string Wxid_1 { get; set; } + public string Nick_1 { get; set; } + public string Wxid_2 { get; set; } + public string Nick_2 { get; set; } + public string Msg { get; set; } + public string Source { get; set; } + public string FilePath { get; set; } + } + + public const int Recv_QRCode = 100000; + public const int Recv_Login = 100001; + public const int Recv_Logout = 100002; + public const int Recv_Msg = 100003; + public const int Recv_SelectTalker = 100004; + + + public const int NM_GetContactList = 200000; + public const int NM_GetGroupMember = 200001; + public const int NM_GetWxidInfo = 200002; + public const int NM_GetA8Key = 200003; + + public const int NM_SendText = 300001; + public const int NM_SendPic = 300002; + public const int NM_SendGif = 300003; + public const int NM_SendFile = 300004; + public const int NM_SendCard = 300005; + public const int NM_SendMap = 300006; + public const int NM_SendURL = 300007; + public const int NM_SendWeChatApp = 300008; + public const int NM_RevokeMsg = 300009; + public const int NM_DesRevoke = 300010; + public const int NM_ForwardAny = 300012; + public const int NM_SendVoice = 300013; + + public const int NM_AddFriend = 400001; + public const int NM_PassApply = 400002; + public const int NM_DelFriend = 400003; + public const int NM_SetFriendMark = 400004; + public const int NM_DelGHFriend = 400005; + + public const int NM_CreateGroup = 500001; + public const int NM_QuitGroup = 500002; + public const int NM_InvitePull = 500003; + public const int NM_InviteURL = 500004; + public const int NM_KickGroupMember = 500005; + public const int NM_SetGroupName = 500006; + public const int NM_SetGroupNotice = 500007; + public const int NM_SetMyGroupNick = 500008; + + public const int NM_GetFavList = 600001; + public const int NM_SendFavMsg = 600002; + + public const int NM_GetCircles = 700001; + public const int NM_SendCircle = 700002; + public const int NM_CircleUpLoadImage = 700003; + public const int NM_CircleComment = 700004; + public const int NM_CircleLink = 700005; + public const int NM_DelCircle = 700006; + public const int NM_GetCircleDetails = 700008; + public const int NM_DelCircleComment = 700009; + + public const int NM_GetMoney = 900001; + public const int NM_StateOpt = 900002; + public const int NM_SetObject = 900003; + public const int NM_GetImageByCDN = 900004; + + [DllImport("Bin\\NanMuHelper.dll")] + public static extern bool NM_GetWeChatPath(byte[] Path, int PathSize); + + [DllImport("Bin\\NanMuHelper.dll")] + public static extern int NM_CreateWeChatProcess(string ExePath, string ExeName, string DllPath, int lPort); + + [DllImport("Bin\\NanMuHelper.dll")] + public static extern int NM_LinkWeChat(int dwPsd, int dwPort, int dwUseLastPort, int dwProcessID); + public bool GetInt(JObject Json, string ObjectName, out int lResult) + { + bool bRet = false; + lResult = 0; + JToken JtObject; + if (Json.TryGetValue(ObjectName, out JtObject) == true) + { + if (JtObject.Type == JTokenType.Integer) + { + bRet = int.TryParse(JtObject.ToString(), out lResult); + if (bRet == false) + { + uint uResult = 0; + bRet = uint.TryParse(JtObject.ToString(), out uResult); + if (bRet == true) + { + lResult = (int)uResult; + } + } + } + } + return bRet; + } + public int GetIntEx(JObject Json, string ObjectName) + { + int lResult = 0; + JToken JtObject; + if (Json.TryGetValue(ObjectName, out JtObject) == true) + { + if (JtObject.Type == JTokenType.Integer) + { + if (int.TryParse(JtObject.ToString(), out lResult) == false) + { + uint uResult = 0; + if (uint.TryParse(JtObject.ToString(), out uResult) == true) + { + lResult = (int)uResult; + } + } + } + } + return lResult; + } + + public JArray GetArray(JObject Json, string ObjectName) + { + string lResult = string.Empty; + JToken JtObject; + if (Json.TryGetValue(ObjectName, out JtObject)) + { + if (JtObject.Type == JTokenType.Array) + { + return (JArray)Json[ObjectName]; + } + } + return null; + } + + public string GetString(JObject Json, string ObjectName, bool isDecode = true) + { + string lResult = string.Empty; + JToken JtObject; + if (Json.TryGetValue(ObjectName, out JtObject)) + { + if (JtObject.Type == JTokenType.String) + { + if (isDecode) + { + if (!string.IsNullOrWhiteSpace(JtObject.ToString())) + { + try + { + byte[] ResultBytes = Convert.FromBase64String(JtObject.ToString()); + lResult = System.Text.UnicodeEncoding.Unicode.GetString(ResultBytes); + } + catch (Exception) + { + return JtObject.ToString(); + } + } + else + return string.Empty; + } + else + lResult = JtObject.ToString(); + } + } + return lResult; + } + + public string JToken_GetString(JToken Jt, string ObjectName, bool isDecode = true) + { + string lResult = string.Empty; + if (Jt != null) + { + try + { + lResult = GetString((JObject)Jt, ObjectName, isDecode); + } + catch (Exception) + { } + } + return lResult; + } + + public int FindRowIndex(ListView lv, string text, int columnIndex) + { + foreach (ListViewItem li in lv.Items) + { + if (li.SubItems[columnIndex].Text == text) + { + return li.Index; + } + } + return -1; + } + + public string Timestamp2DataTime(long Timestamp) + { + System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0); + dtDateTime = dtDateTime.AddSeconds(Timestamp).ToLocalTime(); + return dtDateTime.ToString("yyyy-MM-dd HH:mm:ss"); + } + + public string SaveFile(string mWxid, string uWxid, string fName, string uName, string uExt, byte[] fData) + { + string filePath = Directory.GetCurrentDirectory() + "\\" + mWxid + "\\" + fName + "\\" + uWxid; + if (!Directory.Exists(filePath)) + Directory.CreateDirectory(filePath); + filePath += "\\" + uName + "." + uExt; + FileStream fs = new FileStream(filePath, FileMode.Create); + fs.Write(fData, 0, fData.Length); + fs.Flush(); + fs.Close(); + return filePath; + } + + public string StringMid(string Src, string Left, string Right) + { + string lRusult = string.Empty; + if (Src != string.Empty) + { + int dwLeft = Src.IndexOf(Left); + if (dwLeft != -1) + { + dwLeft += Left.Length; + int dwRight = Src.IndexOf(Right, dwLeft); + if (dwRight != -1) + { + lRusult = Src.Substring(dwLeft, dwRight - dwLeft); + } + } + } + return lRusult; + } + + public Image ShowPicFromURL(string PicUrl) + { + Image Img = null; + if (PicUrl.Length > 10) + { + if (PicUrl.Substring(0, 4) == "http") + { + WebRequest Request = (WebRequest)HttpWebRequest.Create(PicUrl); + WebResponse Resp = Request.GetResponse(); + Stream stream = Resp.GetResponseStream(); + Img = Image.FromStream(stream); + stream.Close(); + Resp.Close(); + } + } + return Img; + } + public string GetFavType(int Type) + { + if (Type == 1) + return "文本"; + else if (Type == 2) + return "图片"; + else if (Type == 3) + return "语音"; + else if (Type == 4) + return "视频"; + else if (Type == 5) + return "链接"; + else if (Type == 6) + return "定位"; + else if (Type == 8) + return "文件"; + else if (Type == 14) + return "聊天记录"; + else if (Type == 18) + return "笔记"; + else + return "未知(" + Type.ToString() + ")"; + } + } +} \ No newline at end of file diff --git a/PCRobot/PCWechat/Dazong/Sdk.cs b/PCRobot/PCWechat/Dazong/Sdk.cs new file mode 100644 index 0000000..c1b9d9a --- /dev/null +++ b/PCRobot/PCWechat/Dazong/Sdk.cs @@ -0,0 +1,3498 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; +using HPSocketCS; + +namespace HPSocketCS +{ + public interface IServer + { + + } + public class ServerEvent + { + public delegate HandleResult OnSendEventHandler(IServer sender, IntPtr connId, byte[] bytes); + public delegate HandleResult OnReceiveEventHandler(IServer sender, IntPtr connId, byte[] bytes); + public delegate HandleResult OnPointerDataReceiveEventHandler(IServer sender, IntPtr connId, IntPtr pData, int length); + public delegate HandleResult OnCloseEventHandler(IServer sender, IntPtr connId, SocketOperation enOperation, int errorCode); + public delegate HandleResult OnShutdownEventHandler(IServer sender); + public delegate HandleResult OnPrepareListenEventHandler(IServer sender, IntPtr soListen); + /// <summary> + /// 连接进入 + /// </summary> + /// <param name="sender"></param> + /// <param name="connId"></param> + /// <param name="pClient">如果为 TCP 连接,pClient为 SOCKET 句柄;如果为 UDP 连接,pClient为 SOCKADDR 指针;</param> + /// <returns></returns> + public delegate HandleResult OnAcceptEventHandler(IServer sender, IntPtr connId, IntPtr pClient); + public delegate HandleResult OnHandShakeEventHandler(IServer sender, IntPtr connId); + } + + public interface IClient + { + + } + + public class ClientEvent + { + public delegate HandleResult OnPrepareConnectEventHandler(IClient sender, IntPtr socket); + public delegate HandleResult OnConnectEventHandler(IClient sender); + public delegate HandleResult OnSendEventHandler(IClient sender, byte[] bytes); + public delegate HandleResult OnReceiveEventHandler(IClient sender, byte[] bytes); + public delegate HandleResult OnPointerDataReceiveEventHandler(IClient sender, IntPtr pData, int length); + public delegate HandleResult OnCloseEventHandler(IClient sender, SocketOperation enOperation, int errorCode); + public delegate HandleResult OnHandShakeEventHandler(IClient sender); + } + + + + /// <summary> + /// 通信组件服务状态,用程序可以通过通信组件的 GetState() 方法获取组件当前服务状态 + /// </summary> + public enum ServiceState + { + /// <summary> + /// 正在启动 + /// </summary> + Starting = 0, + /// <summary> + /// 已经启动 + /// </summary> + Started = 1, + /// <summary> + /// 正在停止 + /// </summary> + Stopping = 2, + /// <summary> + /// 已经启动 + /// </summary> + Stopped = 3, + } + + /// <summary> + /// Socket 操作类型,应用程序的 OnErrror() 事件中通过该参数标识是哪种操作导致的错误 + /// </summary> + public enum SocketOperation + { + Unknown = 0, // Unknown + Accept = 1, // Accept + Connect = 2, // Connect + Send = 3, // Send + Receive = 4, // Receive + Close = 5, // Receive + }; + + /// <summary> + /// 事件通知处理结果,事件通知的返回值,不同的返回值会影响通信组件的后续行为 + /// </summary> + public enum HandleResult + { + /// <summary> + /// 成功 + /// </summary> + Ok = 0, + /// <summary> + /// 忽略 + /// </summary> + Ignore = 1, + /// <summary> + /// 错误 + /// </summary> + Error = 2, + }; + + + /// <summary> + /// 名称:操作结果代码 + /// 描述:组件 Start() / Stop() 方法执行失败时,可通过 GetLastError() 获取错误代码 + /// </summary> + public enum SocketError + { + /// <summary> + /// 成功 + /// </summary> + Ok = 0, + /// <summary> + /// 当前状态不允许操作 + /// </summary> + IllegalState = 1, + /// <summary> + /// 非法参数 + /// </summary> + InvalidParam = 2, + /// <summary> + /// 创建 SOCKET 失败 + /// </summary> + SocketCreate = 3, + /// <summary> + /// 绑定 SOCKET 失败 + /// </summary> + SocketBind = 4, + /// <summary> + /// 设置 SOCKET 失败 + /// </summary> + SocketPrepare = 5, + /// <summary> + /// 监听 SOCKET 失败 + /// </summary> + SocketListen = 6, + /// <summary> + /// 创建完成端口失败 + /// </summary> + CPCreate = 7, + /// <summary> + /// 创建工作线程失败 + /// </summary> + WorkerThreadCreate = 8, + /// <summary> + /// 创建监测线程失败 + /// </summary> + DetectThreadCreate = 9, + /// <summary> + /// 绑定完成端口失败 + /// </summary> + SocketAttachToCP = 10, + /// <summary> + /// 连接服务器失败 + /// </summary> + ConnectServer = 11, + /// <summary> + /// 网络错误 + /// </summary> + Network = 12, + /// <summary> + /// 数据处理错误 + /// </summary> + DataProc = 13, + /// <summary> + /// 数据发送失败 + /// </summary> + DataSend = 14, + + /***** SSL Socket 扩展操作结果代码 *****/ + /// <summary> + /// SSL 环境未就绪 + /// </summary> + SSLEnvNotReady = 101, + }; + + /// <summary> + /// 数据抓取结果,数据抓取操作的返回值 + /// </summary> + public enum FetchResult + { + /// <summary> + /// 成功 + /// </summary> + Ok = 0, + /// <summary> + /// 抓取长度过大 + /// </summary> + LengthTooLong = 1, + /// <summary> + /// 找不到 ConnID 对应的数据 + /// </summary> + DataNotFound = 2, + }; + + /// <summary> + /// 发送策略 + /// </summary> + public enum SendPolicy + { + /// <summary> + /// 打包模式(默认) + /// </summary> + Pack = 0, + /// <summary> + /// 安全模式 + /// </summary> + Safe = 1, + /// <summary> + /// 直接模式 + /// </summary> + Direct = 2, + }; + + + /// <summary> + /// OnSend 事件同步策略 + /// Server 组件和 Agent 组件的 OnSend 事件同步策略 + /// </summary> + public enum OnSendSyncPolicy + { + /// <summary> + /// 不同步(默认) :不同步 OnSend 事件,此时可能同时触发 OnReceive 和 OnClose 事件 + /// </summary> + OSSP_NONE = 0, + /// <summary> + /// 同步 OnClose :只同步 OnClose 事件,此时可能同时触发 OnReceive 事件 + /// </summary> + OSSP_CLOSE = 1, + /// <summary> + /// 同步 OnReceive :(只用于 TCP 组件)同步 OnReceive 和 OnClose 事件,此处不可能同时触发 OnReceive 或 OnClose 事件 + /// </summary> + OSSP_RECEIVE = 2, + } + + + /// <summary> + /// 播送模式 UDP 组件的播送模式(组播或广播) + /// </summary> + public enum CastMode + { + /// <summary> + /// 组播 + /// </summary> + Multicast = 0, + /// <summary> + /// 广播 + /// </summary> + Broadcast = 1, + + } + + /// <summary> + /// 名称:IP 地址类型 + /// 描述:IP 地址类型枚举值 + /// </summary> + public enum IPAddrType + { + /// <summary> + /// 所有 + /// </summary> + All = 0, + /// <summary> + /// IPv4 + /// </summary> + IPV4 = 1, + /// <summary> + /// IPv6 + /// </summary> + IPV6 = 2, + /// <summary> + /// 其他 + /// </summary> + Other = 100, + } + + /// <summary> + /// 接收状态 + /// </summary> + public enum ReceiveState : int + { + /// <summary> + /// 未知 + /// </summary> + Unknown = -1, + /// <summary> + /// 唤醒状态 + /// </summary> + Resume = 0, + /// <summary> + /// 暂停状态 + /// </summary> + Pause = 1, + } + + /****************************************************/ + /************** sockaddr结构体,udp服务器时OnAccept最后个参数可转化 **************/ + [StructLayout(LayoutKind.Sequential)] + public struct in_addr + { + public ulong S_addr; + } + + //[StructLayout(LayoutKind.Sequential)] + //public struct in_addr + //{ + // public byte s_b1, s_b2, s_b3, s_b4; + //} + + [StructLayout(LayoutKind.Sequential)] + public struct sockaddr_in + { + public short sin_family; + public ushort sin_port; + public in_addr sin_addr; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] sLibNamesin_zero; + } + + /****************************************************/ + + [StructLayout(LayoutKind.Sequential)] + public struct WSABUF + { + public int Length; + public IntPtr Buffer; + } + + /// <summary> + /// 名称:IP 地址条目结构体 + /// 描述:IP 地址的地址簇/地址值结构体 + /// </summary> + public struct IPAddr + { + public IPAddrType Type; + public string Address; + public string TypeString; + } + + + /// <summary> + /// DnsHelper + /// </summary> + public class DnsHelper + { + /// <summary> + /// 获取本机ipv4+ipv6地址 + /// hp-socket可用的ip地址结构 + /// </summary> + /// <returns></returns> + public static List<IPAddr> GetLocalHostAddressesToIPAddrList() + { + return Dns.GetHostAddresses(Dns.GetHostName()).Where(p => p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork || + p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6). + Select(p => new IPAddr + { + Type = p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? IPAddrType.IPV4 : IPAddrType.IPV6, + Address = p.ToString(), + }).ToList(); + } + + /// <summary> + /// 获取本机ipv4+ipv6地址 + /// .net自带的ip地址结构 + /// </summary> + /// <returns></returns> + public static IPAddress[] GetLocalHostAddresses() + { + return Dns.GetHostAddresses(Dns.GetHostName()); + } + } +} + + +/// <summary> +/// ANSI版本 +/// </summary> +public class Sdk +{ + + + /// <summary> + /// HPSocket的文件路径 + /// </summary> + public const string HPSOCKET_DLL_PATH = "Bin\\hpsocket4c"; + + /*****************************************************************************************************/ + /******************************************** 公共类、接口 ********************************************/ + /*****************************************************************************************************/ + + + + /****************************************************/ + /************** HPSocket4C.dll 回调函数 **************/ + /* Agent & Server & Client */ + public delegate HandleResult OnSend(IntPtr pSender, IntPtr connId, IntPtr pData, int length); + public delegate HandleResult OnReceive(IntPtr pSender, IntPtr connId, IntPtr pData, int length); + public delegate HandleResult OnPullReceive(IntPtr pSender, IntPtr connId, int length); + public delegate HandleResult OnClose(IntPtr pSender, IntPtr connId, SocketOperation enOperation, int errorCode); + public delegate HandleResult OnHandShake(IntPtr pSender, IntPtr connId); + + + /* Agent & Server */ + public delegate HandleResult OnShutdown(IntPtr pSender); + + /* Agent & Client */ + public delegate HandleResult OnPrepareConnect(IntPtr pSender, IntPtr connId /* IntPtr pClient */, IntPtr socket); + public delegate HandleResult OnConnect(IntPtr pSender, IntPtr connId /* IntPtr pClient */); + + /* Server */ + public delegate HandleResult OnPrepareListen(IntPtr pSender, IntPtr soListen); + public delegate HandleResult OnAccept(IntPtr pSender, IntPtr connId, IntPtr pClient); + + /****************************************************/ + /************** HPSocket4C.dll 导出函数 **************/ + + /// <summary> + /// 创建 TcpServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpServer(IntPtr pListener); + + /// <summary> + /// 创建 TcpClient 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpClient(IntPtr pListener); + + /// <summary> + /// 创建 TcpAgent 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpAgent(IntPtr pListener); + + /// <summary> + /// 创建 TcpPullServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullServer(IntPtr pListener); + + /// <summary> + /// 创建 TcpPullClient 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullClient(IntPtr pListener); + + /// <summary> + /// 创建 TcpPullAgent 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullAgent(IntPtr pListener); + + /// <summary> + /// 创建 HP_TcpPackServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackServer(IntPtr pListener); + + /// <summary> + /// 创建 HP_TcpPackAgent 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackAgent(IntPtr pListener); + + /// <summary> + /// 创建 HP_TcpPackAgent 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackClient(IntPtr pListener); + + /// <summary> + /// 创建 UdpServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpServer(IntPtr pListener); + + /// <summary> + /// 创建 UdpClient 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpClient(IntPtr pListener); + + + /// <summary> + /// 创建 HP_UdpCast 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpCast(IntPtr pListener); + + + /// <summary> + /// 销毁 TcpServer 对象 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpServer(IntPtr pServer); + + /// <summary> + /// 销毁 TcpClient 对象 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpClient(IntPtr pClient); + + /// <summary> + /// 销毁 TcpAgent 对象 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpAgent(IntPtr pAgent); + + /// <summary> + /// 销毁 TcpPullServer 对象 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullServer(IntPtr pServer); + + /// <summary> + /// 销毁 TcpPullClient 对象 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullClient(IntPtr pClient); + + /// <summary> + /// 销毁 TcpPullAgent 对象 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullAgent(IntPtr pAgent); + + /// <summary> + /// 销毁 HP_TcpPackServer 对象 + /// </summary> + /// <param name="pServer"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackServer(IntPtr pServer); + + /// <summary> + /// 销毁 HP_TcpPackAgent 对象 + /// </summary> + /// <param name="pAgent"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackAgent(IntPtr pAgent); + + /// <summary> + /// 销毁 HP_TcpPackClient 对象 + /// </summary> + /// <param name="pClient"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackClient(IntPtr pClient); + + + /// <summary> + /// 销毁 UdpServer 对象 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpServer(IntPtr pServer); + + /// <summary> + /// 销毁 UdpClient 对象 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpClient(IntPtr pClient); + + /// <summary> + /// 销毁 HP_UdpCast 对象 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpCast(IntPtr pCast); + + + /// <summary> + /// 创建 TcpServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpServerListener(); + + /// <summary> + /// 创建 TcpClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpClientListener(); + + /// <summary> + /// 创建 TcpAgentListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpAgentListener(); + + /// <summary> + /// 创建 TcpPullServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullServerListener(); + + /// <summary> + /// 创建 TcpPullClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullClientListener(); + + /// <summary> + /// 创建 TcpPullAgentListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPullAgentListener(); + + /// <summary> + /// 创建 TcpPackServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackServerListener(); + + /// <summary> + /// 创建 TcpPackClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackClientListener(); + + /// <summary> + /// 创建 TcpPackAgentListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_TcpPackAgentListener(); + + /// <summary> + /// 创建 UdpServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpServerListener(); + + /// <summary> + /// 创建 UdpClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpClientListener(); + + /// <summary> + /// 创建 HP_UdpCastListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpCastListener(); + + + + /// <summary> + /// 销毁 TcpServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpClientListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpAgentListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpAgentListener(IntPtr pListener); + + + /// <summary> + /// 销毁 TcpPullServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPullClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullClientListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPullAgentListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPullAgentListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPackServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPackClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackClientListener(IntPtr pListener); + + /// <summary> + /// 销毁 TcpPackAgentListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_TcpPackAgentListener(IntPtr pListener); + + /// <summary> + /// 销毁 UdpServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 UdpClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpClientListener(IntPtr pListener); + + /// <summary> + /// 销毁 HP_UdpCastListener 对象 + /// </summary> + /// <param name="pListener"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpCastListener(IntPtr pListener); + + + /**********************************************************************************/ + /***************************** Server 回调函数设置方法 *****************************/ + + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnPrepareListen(IntPtr pListener, OnPrepareListen fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnAccept(IntPtr pListener, OnAccept fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnHandShake(IntPtr pListener, OnHandShake fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnSend(IntPtr pListener, OnSend fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnClose(IntPtr pListener, OnClose fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Server_OnShutdown(IntPtr pListener, OnShutdown fn); + + /**********************************************************************************/ + /***************************** Client 回调函数设置方法 *****************************/ + + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnPrepareConnect(IntPtr pListener, OnPrepareConnect fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnConnect(IntPtr pListener, OnConnect fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnHandShake(IntPtr pListener, OnHandShake fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnSend(IntPtr pListener, OnSend fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Client_OnClose(IntPtr pListener, OnClose fn); + + /**********************************************************************************/ + /****************************** Agent 回调函数设置方法 *****************************/ + + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnPrepareConnect(IntPtr pListener, OnPrepareConnect fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnConnect(IntPtr pListener, OnConnect fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnHandShake(IntPtr pListener, OnHandShake fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnSend(IntPtr pListener, OnSend fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnReceive(IntPtr pListener, OnReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnPullReceive(IntPtr pListener, OnPullReceive fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnClose(IntPtr pListener, OnClose fn); + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Set_FN_Agent_OnShutdown(IntPtr pListener, OnShutdown fn); + + /**************************************************************************/ + /***************************** Server 操作方法 *****************************/ + + /// <summary> + /// 名称:启动通信组件 + /// 描述:启动服务端通信组件,启动完成后可开始接收客户端连接并收发数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="pszBindAddress">监听地址</param> + /// <param name="usPort">监听端口</param> + /// <returns>失败,可通过 GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Start(IntPtr pServer, string pszBindAddress, ushort usPort); + + /// <summary> + /// 关闭服务端通信组件,关闭完成后断开所有客户端连接并释放所有资源 + /// </summary> + /// <param name="pServer"></param> + /// <returns>失败,可通过 GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Stop(IntPtr pServer); + + /// <summary> + /// 用户通过该方法向指定客户端发送数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">发送数据长度</param> + /// <param name="length">发送数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Send(IntPtr pServer, IntPtr connId, byte[] pBuffer, int length); + + /// <summary> + /// 用户通过该方法向指定客户端发送数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">发送数据长度</param> + /// <param name="length">发送数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Send(IntPtr pServer, IntPtr connId, IntPtr pBuffer, int length); + + /// <summary> + /// 用户通过该方法向指定客户端发送数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SendPart(IntPtr pServer, IntPtr connId, byte[] pBuffer, int length, int iOffset); + + /// <summary> + /// 用户通过该方法向指定客户端发送数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SendPart(IntPtr pServer, IntPtr connId, IntPtr pBuffer, int length, int iOffset); + + + /// <summary> + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffers">发送缓冲区数组</param> + /// <param name="iCount">发送缓冲区数目</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SendPackets(IntPtr pServer, IntPtr connId, WSABUF[] pBuffers, int iCount); + + /// <summary> + /// 名称:暂停/恢复接收 + /// 描述:暂停/恢复某个连接的数据接收工作 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwConnID">连接 ID</param> + /// <param name="bPause">TRUE - 暂停, FALSE - 恢复</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_PauseReceive(IntPtr pServer, IntPtr dwConnID, bool bPause); + + + + /// <summary> + /// 断开与某个客户端的连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_Disconnect(IntPtr pServer, IntPtr connId, bool bForce); + + /// <summary> + /// 断开超过指定时长的连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwPeriod">时长(毫秒)</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_DisconnectLongConnections(IntPtr pServer, uint dwPeriod, bool bForce); + + /// <summary> + /// 断开超过指定时长的静默连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwPeriod">时长(毫秒)</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_DisconnectSilenceConnections(IntPtr pServer, uint dwPeriod, bool bForce); + + /******************************************************************************/ + /***************************** Server 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据发送策略 + /// </summary> + /// <param name="pServer"></param> + /// <param name="enSendPolicy"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetSendPolicy(IntPtr pServer, SendPolicy enSendPolicy); + + /// <summary> + /// 获取数据发送策略 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SendPolicy HP_Server_GetSendPolicy(IntPtr pServer); + + /// <summary> + /// 设置连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pExtra"></param> + /// <returns>若返回 false 失败则为(无效的连接 ID)</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_SetConnectionExtra(IntPtr pServer, IntPtr connId, IntPtr pExtra); + + /// <summary> + /// 获取连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pExtra">数据指针</param> + /// <returns>若返回 false 失败则为(无效的连接 ID)</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetConnectionExtra(IntPtr pServer, IntPtr connId, ref IntPtr pExtra); + + /// <summary> + /// 检测是否为安全连接(SSL/HTTPS) + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_IsSecure(IntPtr pServer); + + + /// <summary> + /// 检查通信组件是否已启动 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_HasStarted(IntPtr pServer); + + /// <summary> + /// 查看通信组件当前状态 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ServiceState HP_Server_GetState(IntPtr pServer); + + /// <summary> + /// 获取最近一次失败操作的错误代码 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SocketError HP_Server_GetLastError(IntPtr pServer); + + /// <summary> + /// 获取最近一次失败操作的错误描述 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Server_GetLastErrorDesc(IntPtr pServer); + + + /// <summary> + /// 获取连接中未发出数据的长度 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="piPending"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetPendingDataLength(IntPtr pServer, IntPtr connId, ref int piPending); + + /// <summary> + /// 获取连接的数据接收状态 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwConnID"></param> + /// <param name="pbPaused"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_IsPauseReceive(IntPtr pServer, IntPtr dwConnID, ref int pbPaused); + + /// <summary> + /// 检测是否有效连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwConnID"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_IsConnected(IntPtr pServer, IntPtr dwConnID); + + + /// <summary> + /// 获取客户端连接数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetConnectionCount(IntPtr pServer); + + /// <summary> + /// 获取所有连接的 CONNID + /// </summary> + /// <param name="pServer"></param> + /// <param name="pIDs"></param> + /// <param name="pdwCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetAllConnectionIDs(IntPtr pServer, IntPtr[] pIDs, ref uint pdwCount); + + /// <summary> + /// 获取某个客户端连接时长(毫秒) + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pdwPeriod"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetConnectPeriod(IntPtr pServer, IntPtr connId, ref uint pdwPeriod); + + /// <summary> + /// 获取某个连接静默时间(毫秒) + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pdwPeriod"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetSilencePeriod(IntPtr pServer, IntPtr connId, ref uint pdwPeriod); + + /// <summary> + /// 获取监听 Socket 的地址信息 + /// </summary> + /// <param name="pServer"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetListenAddress(IntPtr pServer, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取某个连接的本地地址信息 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen">传入传出值,大小最好在222.222.222.222的长度以上</param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetLocalAddress(IntPtr pServer, IntPtr connId, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取某个连接的远程地址信息 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen">传入传出值,大小最好在222.222.222.222的长度以上</param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_GetRemoteAddress(IntPtr pServer, IntPtr connId, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + + + /// <summary> + /// 设置 OnSend 事件同步策略(默认:OSSP_NONE,不同步) + /// </summary> + /// <param name="pServer"></param> + /// <param name="syncPolicy"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetOnSendSyncPolicy(IntPtr pServer, OnSendSyncPolicy syncPolicy); + + /// <summary> + /// 获取 OnSend 事件同步策略 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern OnSendSyncPolicy HP_Server_GetOnSendSyncPolicy(IntPtr pServer); + + + /// <summary> + /// 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeSocketObjLockTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeSocketObjLockTime(IntPtr pServer, uint dwFreeSocketObjLockTime); + + /// <summary> + /// 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeSocketObjPool"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeSocketObjPool(IntPtr pServer, uint dwFreeSocketObjPool); + + /// <summary> + /// 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeBufferObjPool"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeBufferObjPool(IntPtr pServer, uint dwFreeBufferObjPool); + + /// <summary> + /// 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeSocketObjHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeSocketObjHold(IntPtr pServer, uint dwFreeSocketObjHold); + + /// <summary> + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFreeBufferObjHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetFreeBufferObjHold(IntPtr pServer, uint dwFreeBufferObjHold); + + /// <summary> + /// 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxConnectionCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetMaxConnectionCount(IntPtr pServer, uint dwWMaxConnectionCount); + + /// <summary> + /// 设置工作线程数量(通常设置为 2 * CPU + 2) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwWorkerThreadCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetWorkerThreadCount(IntPtr pServer, uint dwWorkerThreadCount); + + /// <summary> + /// 设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:FALSE) + /// </summary> + /// <param name="pServer"></param> + /// <param name="bMarkSilence"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Server_SetMarkSilence(IntPtr pServer, bool bMarkSilence); + + /// <summary> + /// 获取 Socket 缓存对象锁定时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeSocketObjLockTime(IntPtr pServer); + + /// <summary> + /// 获取 Socket 缓存池大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeSocketObjPool(IntPtr pServer); + + /// <summary> + /// 获取内存块缓存池大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeBufferObjPool(IntPtr pServer); + + /// <summary> + /// 获取 Socket 缓存池回收阀值 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeSocketObjHold(IntPtr pServer); + + /// <summary> + /// 获取内存块缓存池回收阀值 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetFreeBufferObjHold(IntPtr pServer); + + /// <summary> + /// 获取最大连接数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetMaxConnectionCount(IntPtr pServer); + + /// <summary> + /// 获取工作线程数量 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Server_GetWorkerThreadCount(IntPtr pServer); + + /// <summary> + /// 检测是否标记静默时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Server_IsMarkSilence(IntPtr pServer); + + /**********************************************************************************/ + /***************************** TCP Server 操作方法 *****************************/ + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="lpszFileName">文件路径</param> + /// <param name="pHead">头部附加数据</param> + /// <param name="pTail">尾部附加数据</param> + /// <returns>TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_TcpServer_SendSmallFile(IntPtr pServer, IntPtr connId, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /**********************************************************************************/ + /***************************** TCP Server 属性访问方法 *****************************/ + + /// <summary> + /// 设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwAcceptSocketCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetAcceptSocketCount(IntPtr pServer, uint dwAcceptSocketCount); + + /// <summary> + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwSocketBufferSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetSocketBufferSize(IntPtr pServer, uint dwSocketBufferSize); + + /// <summary> + /// 设置监听 Socket 的等候队列大小(根据并发连接数量调整设置) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwSocketListenQueue"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetSocketListenQueue(IntPtr pServer, uint dwSocketListenQueue); + + /// <summary> + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwKeepAliveTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetKeepAliveTime(IntPtr pServer, uint dwKeepAliveTime); + + /// <summary> + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwKeepAliveInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpServer_SetKeepAliveInterval(IntPtr pServer, uint dwKeepAliveInterval); + + + /// <summary> + /// 获取 Accept 预投递数量 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetAcceptSocketCount(IntPtr pServer); + + /// <summary> + /// 获取通信数据缓冲区大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetSocketBufferSize(IntPtr pServer); + + /// <summary> + /// 获取监听 Socket 的等候队列大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetSocketListenQueue(IntPtr pServer); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetKeepAliveTime(IntPtr pServer); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpServer_GetKeepAliveInterval(IntPtr pServer); + + + /**********************************************************************************/ + /***************************** UDP Server 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpServer_SetMaxDatagramSize(IntPtr pServer, uint dwMaxDatagramSize); + + /// <summary> + /// 获取数据报文最大长度 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpServer_GetMaxDatagramSize(IntPtr pServer); + + /// <summary> + /// 设置 Receive 预投递数量(根据负载调整设置,Receive 预投递数量越大则丢包概率越小) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwPostReceiveCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpServer_SetPostReceiveCount(IntPtr pServer, uint dwPostReceiveCount); + + /// <summary> + /// 获取 Receive 预投递数量 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpServer_GetPostReceiveCount(IntPtr pServer); + + /// <summary> + /// 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpServer_SetDetectAttempts(IntPtr pServer, uint dwMaxDatagramSize); + + /// <summary> + /// 设置监测包发送间隔(秒,0 不发送监测包) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpServer_SetDetectInterval(IntPtr pServer, uint dwMaxDatagramSize); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpServer_GetDetectAttempts(IntPtr pServer); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpServer_GetDetectInterval(IntPtr pServer); + /******************************************************************************/ + /***************************** Client 组件操作方法 *****************************/ + + /// <summary> + /// 启动客户端通信组件并连接服务端,启动完成后可开始收发数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="bAsyncConnect">是否采用异步 Connect</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Start(IntPtr pClient, string pszRemoteAddress, ushort usPort, bool bAsyncConnect); + + + /// <summary> + /// 启动通信组件(并指定绑定地址), 启动客户端通信组件并连接服务端,启动完成后可开始收发数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="bAsyncConnect">是否采用异步 Connect</param> + /// <param name="lpszBindAddress">绑定地址(默认:nullptr,TcpClient/UdpClient -> 不执行绑定操作,UdpCast 绑定 -> 0.0.0.0)</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_StartWithBindAddress(IntPtr pClient, string lpszRemoteAddress, ushort usPort, bool bAsyncConnect, string lpszBindAddress); + + /// <summary> + /// 名称:启动通信组件(并指定绑定地址) + /// 描述:启动客户端通信组件并连接服务端,启动完成后可开始收发数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="bAsyncConnect">是否采用异步 Connect</param> + /// <param name="lpszBindAddress">绑定地址(默认:nullptr,TcpClient/UdpClient -> 不执行绑定操作,UdpCast 绑定 -> 0.0.0.0)</param> + /// <param name="usLocalPort">本地端口(默认:0)</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_StartWithBindAddressAndLocalPort(IntPtr pClient, string lpszRemoteAddress, ushort usPort, bool bAsyncConnect, string lpszBindAddress, ushort usLocalPort); + + + /// <summary> + /// 关闭客户端通信组件,关闭完成后断开与服务端的连接并释放所有资源 + /// </summary> + /// <param name="pClient"></param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Stop(IntPtr pClient); + + /// <summary> + /// 用户通过该方法向服务端发送数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="connId">连接 ID(保留参数,目前该参数并未使用)</param> + /// <param name="pBuffer">发送数据缓冲区</param> + /// <param name="length">发送数据长度</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Send(IntPtr pClient, byte[] pBuffer, int length); + + /// <summary> + /// 用户通过该方法向服务端发送数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="connId">连接 ID(保留参数,目前该参数并未使用)</param> + /// <param name="pBuffer">发送数据缓冲区</param> + /// <param name="length">发送数据长度</param> + /// <returns>失败,可通过 HP_Client_GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_Send(IntPtr pClient, IntPtr pBuffer, int length); + + /// <summary> + /// 用户通过该方法向服务端发送数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_SendPart(IntPtr pClient, byte[] pBuffer, int length, int iOffset); + + /// <summary> + /// 用户通过该方法向服务端发送数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_SendPart(IntPtr pClient, IntPtr pBuffer, int length, int iOffset); + + + /// <summary> + /// 发送多组数据 + /// 向服务端发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// </summary> + /// <param name="pClient"></param> + /// <param name="pBuffers">发送缓冲区数组</param> + /// <param name="iCount">发送缓冲区数目</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_SendPackets(IntPtr pClient, WSABUF[] pBuffers, int iCount); + + + /// <summary> + /// 名称:暂停/恢复接收 + /// 描述:暂停/恢复某个连接的数据接收工作 + /// </summary> + /// <param name="pClient">TRUE - 暂停, FALSE - 恢复</param> + /// <param name="bPause">TRUE - 暂停, FALSE - 恢复</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_PauseReceive(IntPtr pClient, int bPause); + + /******************************************************************************/ + /***************************** Client 属性访问方法 *****************************/ + + /// <summary> + /// 设置连接的附加数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pExtra"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Client_SetExtra(IntPtr pClient, IntPtr pExtra); + + + /// <summary> + /// 获取连接的附加数据 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Client_GetExtra(IntPtr pClient); + + + /// <summary> + /// 检测是否为安全连接(SSL/HTTPS) + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_IsSecure(IntPtr pClient); + + + /// <summary> + /// 检查通信组件是否已启动 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_HasStarted(IntPtr pClient); + + /// <summary> + /// 查看通信组件当前状态 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ServiceState HP_Client_GetState(IntPtr pClient); + + /// <summary> + /// 获取最近一次失败操作的错误代码 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SocketError HP_Client_GetLastError(IntPtr pClient); + + /// <summary> + /// 获取最近一次失败操作的错误描述 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Client_GetLastErrorDesc(IntPtr pClient); + + /// <summary> + /// 获取该组件对象的连接 ID + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Client_GetConnectionID(IntPtr pClient); + + /// <summary> + /// 获取 Client Socket 的地址信息 + /// </summary> + /// <param name="pClient"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_GetLocalAddress(IntPtr pClient, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取连接的远程主机信息 + /// </summary> + /// <param name="pClient"></param> + /// <param name="lpszHost"></param> + /// <param name="piHostLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_GetRemoteHost(IntPtr pClient, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszHost, ref int piHostLen, ref ushort pusPort); + + + /// <summary> + /// 获取连接中未发出数据的长度 + /// </summary> + /// <param name="pClient"></param> + /// <param name="piPending"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_GetPendingDataLength(IntPtr pClient, ref int piPending); + + /// <summary> + /// 获取连接的数据接收状态 + /// </summary> + /// <param name="pClient"></param> + /// <param name="pbPaused"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_IsPauseReceive(IntPtr pClient, ref int pbPaused); + + /// <summary> + /// 检测是否有效连接 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Client_IsConnected(IntPtr pClient); + + + /// <summary> + /// 设置内存块缓存池大小(通常设置为 -> PUSH 模型:5 - 10;PULL 模型:10 - 20 ) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwFreeBufferPoolSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Client_SetFreeBufferPoolSize(IntPtr pClient, uint dwFreeBufferPoolSize); + + /// <summary> + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwFreeBufferPoolHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Client_SetFreeBufferPoolHold(IntPtr pClient, uint dwFreeBufferPoolHold); + + /// <summary> + /// 获取内存块缓存池大小 + /// </summary> + /// <param name="pClient"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Client_GetFreeBufferPoolSize(IntPtr pClient); + + /// <summary> + /// 获取内存块缓存池回收阀值 + /// </summary> + /// <param name="pClient"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Client_GetFreeBufferPoolHold(IntPtr pClient); + /**********************************************************************************/ + /***************************** TCP Client 操作方法 *****************************/ + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="pServer"></param> + /// <param name="lpszFileName">文件路径</param> + /// <param name="pHead">头部附加数据</param> + /// <param name="pTail">尾部附加数据</param> + /// <returns>TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_TcpClient_SendSmallFile(IntPtr pClient, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /**********************************************************************************/ + /***************************** TCP Client 属性访问方法 *****************************/ + + /// <summary> + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为:(N * 1024) - sizeof(TBufferObj)) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwSocketBufferSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpClient_SetSocketBufferSize(IntPtr pClient, uint dwSocketBufferSize); + + /// <summary> + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwKeepAliveTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpClient_SetKeepAliveTime(IntPtr pClient, uint dwKeepAliveTime); + + /// <summary> + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwKeepAliveInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpClient_SetKeepAliveInterval(IntPtr pClient, uint dwKeepAliveInterval); + + /// <summary> + /// 获取通信数据缓冲区大小 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpClient_GetSocketBufferSize(IntPtr pClient); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpClient_GetKeepAliveTime(IntPtr pClient); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpClient_GetKeepAliveInterval(IntPtr pClient); + + /**********************************************************************************/ + /***************************** UDP Client 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpClient_SetMaxDatagramSize(IntPtr pClient, uint dwMaxDatagramSize); + + /// <summary> + /// 获取数据报文最大长度 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpClient_GetMaxDatagramSize(IntPtr pClient); + + /// <summary> + /// 设置监测包尝试次数(0 则不发送监测跳包,如果超过最大尝试次数则认为已断线 + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwDetectAttempts"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpClient_SetDetectAttempts(IntPtr pClient, uint dwDetectAttempts); + + /// <summary> + /// 设置监测包发送间隔(秒,0 不发送监测包) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwDetectInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpClient_SetDetectInterval(IntPtr pClient, uint dwDetectInterval); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpClient_GetDetectAttempts(IntPtr pClient); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpClient_GetDetectInterval(IntPtr pClient); + + + /**********************************************************************************/ + /****************************** UDP Cast 属性访问方法 ******************************/ + + /// <summary> + /// 设置数据报文最大长度(建议在局域网环境下不超过 1472 字节,在广域网环境下不超过 548 字节 + /// </summary> + /// <param name="pCast"></param> + /// <param name="dwMaxDatagramSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetMaxDatagramSize(IntPtr pCast, uint dwMaxDatagramSize); + + /// <summary> + /// 获取数据报文最大长度 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpCast_GetMaxDatagramSize(IntPtr pCast); + + /// <summary> + /// 获取当前数据报的远程地址信息(通常在 OnReceive 事件中调用) + /// </summary> + /// <param name="pCast"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpCast_GetRemoteAddress(IntPtr pCast, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 设置是否启用地址重用机制(默认:不启用) + /// </summary> + /// <param name="pCast"></param> + /// <param name="bReuseAddress"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetReuseAddress(IntPtr pCast, bool bReuseAddress); + + /// <summary> + /// 检测是否启用地址重用机制 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpCast_IsReuseAddress(IntPtr pCast); + + /// <summary> + /// 设置传播模式(组播或广播) + /// </summary> + /// <param name="pCast"></param> + /// <param name="enCastMode"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetCastMode(IntPtr pCast, CastMode enCastMode); + + /// <summary> + /// 获取传播模式 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern CastMode HP_UdpCast_GetCastMode(IntPtr pCast); + + /// <summary> + /// 设置组播报文的 TTL(0 - 255) + /// </summary> + /// <param name="pCast"></param> + /// <param name="iMCTtl"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetMultiCastTtl(IntPtr pCast, int iMCTtl); + + /// <summary> + /// 获取组播报文的 TTL + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int HP_UdpCast_GetMultiCastTtl(IntPtr pCast); + + /// <summary> + /// 设置是否启用组播环路(TRUE or FALSE) + /// </summary> + /// <param name="pCast"></param> + /// <param name="bMCLoop"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpCast_SetMultiCastLoop(IntPtr pCast, bool bMCLoop); + + /// <summary> + /// 检测是否启用组播环路 + /// </summary> + /// <param name="pCast"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpCast_IsMultiCastLoop(IntPtr pCast); + + /**************************************************************************/ + /***************************** Agent 操作方法 *****************************/ + + /// <summary> + /// 启动通信组件 + /// 启动通信代理组件,启动完成后可开始连接远程服务器 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="pszBindAddress">监听地址</param> + /// <param name="bAsyncConnect">是否采用异步 Connect</param> + /// <returns>失败,可通过 GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Start(IntPtr pAgent, string pszBindAddress, bool bAsyncConnect); + + /// <summary> + /// 关闭通信组件 + /// 关闭通信组件,关闭完成后断开所有连接并释放所有资源 + /// </summary> + /// <param name="pAgent"></param> + /// <returns>-- 失败,可通过 GetLastError() 获取错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Stop(IntPtr pAgent); + + /// <summary> + /// 连接服务器 + /// 连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="pszBindAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pconnId">传出连接 ID</param> + /// <returns>失败,可通过 SYS_GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Connect(IntPtr pAgent, string pszBindAddress, ushort usPort, ref IntPtr pconnId); + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">传出连接</param> + /// <param name="pExtra">连接附加数据(默认:nullptr)</param> + /// <returns>失败,可通过函数 SYS_GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithExtra(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, IntPtr pExtra); + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">连接 ID(默认:nullptr,不获取连接 ID)</param> + /// <param name="usLocalPort">本地端口(默认:0)</param> + /// <returns>失败,可通过函数 SYS_GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithLocalPort(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, ushort usLocalPort); + + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">连接 ID(默认:nullptr,不获取连接 ID)</param> + /// <param name="lpszLocalAddress">本地地址(默认:nullptr,使用 Start() 方法中绑定的地址)</param> + /// <returns>失败,可通过函数 SYS_GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithLocalAddress(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, string lpszLocalAddress); + + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">连接 ID(默认:nullptr,不获取连接 ID)</param> + /// <param name="pExtra">连接附加数据(默认:nullptr)</param> + /// <param name="usLocalPort">本地端口(默认:0)</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithExtraAndLocalPort(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, IntPtr pExtra, ushort usLocalPort); + + + /// <summary> + /// 名称:连接服务器 + /// 描述:连接服务器,连接成功后 IAgentListener 会接收到 OnConnect() / OnHandShake() 事件 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="lpszRemoteAddress">服务端地址</param> + /// <param name="usPort">服务端端口</param> + /// <param name="pdwConnID">连接 ID(默认:nullptr,不获取连接 ID)</param> + /// <param name="pExtra">连接附加数据(默认:nullptr)</param> + /// <param name="usLocalPort">本地端口(默认:0)</param> + /// <param name="lpszLocalAddress">本地地址(默认:nullptr,使用 Start() 方法中绑定的地址)</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_ConnectWithExtraAndLocalAddressPort(IntPtr pAgent, string lpszRemoteAddress, ushort usPort, ref IntPtr pdwConnID, IntPtr pExtra, ushort usLocalPort, string lpszLocalAddress); + + + /// <summary> + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">发送数据缓冲区</param> + /// <param name="length">发送数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Send(IntPtr pAgent, IntPtr connId, byte[] pBuffer, int length); + + /// <summary> + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">发送数据缓冲区</param> + /// <param name="length">发送数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Send(IntPtr pAgent, IntPtr connId, IntPtr pBuffer, int length); + + /// <summary> + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_SendPart(IntPtr pAgent, IntPtr connId, byte[] pBuffer, int length, int iOffset); + + /// <summary> + /// 发送数据 + /// 用户通过该方法向指定连接发送数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="pBuffer"></param> + /// <param name="length"></param> + /// <param name="iOffset">针对pBuffer的偏移</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_SendPart(IntPtr pAgent, IntPtr connId, IntPtr pBuffer, int length, int iOffset); + + + /// <summary> + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// UDP - 把所有数据包组合成一个数据包发送(数据包的总长度不能大于设置的 UDP 包最大长度) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffers">发送缓冲区数组</param> + /// <param name="iCount">发送缓冲区数目</param> + /// <returns>TRUE.成功,FALSE .失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_SendPackets(IntPtr pAgent, IntPtr connId, WSABUF[] pBuffers, int iCount); + + /// <summary> + /// 名称:暂停/恢复接收 + /// 描述:暂停/恢复某个连接的数据接收工作 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwConnID"></param> + /// <param name="bPause">TRUE - 暂停, FALSE - 恢复</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_PauseReceive(IntPtr pAgent, IntPtr dwConnID, bool bPause); + + /// <summary> + /// 断开某个连接 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_Disconnect(IntPtr pAgent, IntPtr connId, bool bForce); + + /// <summary> + /// 断开超过指定时长的连接 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwPeriod">时长(毫秒)</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_DisconnectLongConnections(IntPtr pAgent, uint dwPeriod, bool bForce); + + /// <summary> + /// 断开超过指定时长的静默连接 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwPeriod">时长(毫秒)</param> + /// <param name="bForce">是否强制断开连接</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_DisconnectSilenceConnections(IntPtr pAgent, uint dwPeriod, bool bForce); + + /******************************************************************************/ + /***************************** Agent 操作方法 *****************************/ + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="lpszFileName">文件路径</param> + /// <param name="pHead">头部附加数据</param> + /// <param name="pTail">尾部附加数据</param> + /// <returns>TRUE.成功 FALSE -- 失败,可通过 Windows API 函数 ::GetLastError() 获取 Windows 错误代码</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_TcpAgent_SendSmallFile(IntPtr pAgent, IntPtr connId, string lpszFileName, ref WSABUF pHead, ref WSABUF pTail); + + /******************************************************************************/ + /***************************** Agent 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据发送策略 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="enSendPolicy"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetSendPolicy(IntPtr pAgent, SendPolicy enSendPolicy); + + /// <summary> + /// 获取数据发送策略 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SendPolicy HP_Agent_GetSendPolicy(IntPtr pAgent); + + + /// <summary> + /// 获取 OnSend 事件同步策略 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern OnSendSyncPolicy HP_Agent_GetOnSendSyncPolicy(IntPtr pAgent); + + /// <summary> + /// 设置 OnSend 事件同步策略(默认:OSSP_NONE,不同步 + /// </summary> + /// <param name="pServer"></param> + /// <param name="syncPolicy"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetOnSendSyncPolicy(IntPtr pAgent, OnSendSyncPolicy syncPolicy); + + + /// <summary> + /// 设置连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pExtra">数据</param> + /// <returns>FALSE -- 失败(无效的连接 ID)</returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_SetConnectionExtra(IntPtr pAgent, IntPtr connId, IntPtr pExtra); + + /// <summary> + /// 获取连接的附加数据 + /// 是否为连接绑定附加数据或者绑定什么样的数据,均由应用程序只身决定 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="pExtra"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetConnectionExtra(IntPtr pAgent, IntPtr connId, ref IntPtr pExtra); + + /// <summary> + /// 检测是否为安全连接(SSL/HTTPS) + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_IsSecure(IntPtr pAgent); + + /// <summary> + /// 检查通信组件是否已启动 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_HasStarted(IntPtr pAgent); + + /// <summary> + /// 查看通信组件当前状态 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ServiceState HP_Agent_GetState(IntPtr pAgent); + + /// <summary> + /// 获取连接数 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetConnectionCount(IntPtr pAgent); + + /// <summary> + /// 获取所有连接的 CONNID + /// </summary> + /// <param name="pServer"></param> + /// <param name="pIDs"></param> + /// <param name="pdwCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetAllConnectionIDs(IntPtr pAgent, IntPtr[] pIDs, ref uint pdwCount); + + /// <summary> + /// 获取某个连接时长(毫秒) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="pdwPeriod"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetConnectPeriod(IntPtr pAgent, IntPtr connId, ref uint pdwPeriod); + + /// <summary> + /// 获取某个连接静默时间(毫秒) + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId"></param> + /// <param name="pdwPeriod"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetSilencePeriod(IntPtr pAgent, IntPtr connId, ref uint pdwPeriod); + + /// <summary> + /// 获取某个连接的本地地址信息 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetLocalAddress(IntPtr pAgent, IntPtr connId, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取某个连接的远程地址信息 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetRemoteAddress(IntPtr pAgent, IntPtr connId, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取某个连接的远程主机信息 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwConnID"></param> + /// <param name="lpszAddress"></param> + /// <param name="piHostLen"></param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetRemoteHost(IntPtr pAgent, IntPtr dwConnID, [MarshalAs(UnmanagedType.LPStr)]StringBuilder lpszAddress, ref int piHostLen, ref ushort pusPort); + + + /// <summary> + /// 获取最近一次失败操作的错误代码 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern SocketError HP_Agent_GetLastError(IntPtr pAgent); + + /// <summary> + /// 获取最近一次失败操作的错误描述 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_Agent_GetLastErrorDesc(IntPtr pAgent); + + /// <summary> + /// 获取连接中未发出数据的长度 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId"></param> + /// <param name="piPending"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_GetPendingDataLength(IntPtr pAgent, IntPtr connId, ref int piPending); + + /// <summary> + /// 获取连接的数据接收状态 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwConnID"></param> + /// <param name="pbPaused"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_IsPauseReceive(IntPtr pAgent, IntPtr dwConnID, ref int pbPaused); + + /// <summary> + /// 检测是否有效连接 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwConnID"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_IsConnected(IntPtr pAgent, IntPtr dwConnID); + + + /// <summary> + /// 设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeSocketObjLockTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeSocketObjLockTime(IntPtr pAgent, uint dwFreeSocketObjLockTime); + + /// <summary> + /// 设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeSocketObjPool"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeSocketObjPool(IntPtr pAgent, uint dwFreeSocketObjPool); + + /// <summary> + /// 设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeBufferObjPool"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeBufferObjPool(IntPtr pAgent, uint dwFreeBufferObjPool); + + /// <summary> + /// 设置 Socket 缓存池回收阀值(通常设置为 Socket 缓存池大小的 3 倍) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeSocketObjHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeSocketObjHold(IntPtr pAgent, uint dwFreeSocketObjHold); + + /// <summary> + /// 设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwFreeBufferObjHold"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetFreeBufferObjHold(IntPtr pAgent, uint dwFreeBufferObjHold); + + /// <summary> + /// 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwMaxConnectionCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetMaxConnectionCount(IntPtr pAgent, uint dwMaxConnectionCount); + + /// <summary> + /// 设置工作线程数量(通常设置为 2 * CPU + 2) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwWorkerThreadCount"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetWorkerThreadCount(IntPtr pAgent, uint dwWorkerThreadCount); + + /// <summary> + /// 设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:FALSE) + /// </summary> + /// <param name="pServer"></param> + /// <param name="bMarkSilence"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_Agent_SetMarkSilence(IntPtr pAgent, bool bMarkSilence); + + /// <summary> + /// 获取 Socket 缓存对象锁定时间 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeSocketObjLockTime(IntPtr pAgent); + + /// <summary> + /// 获取 Socket 缓存池大小 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeSocketObjPool(IntPtr pAgent); + + /// <summary> + /// 获取内存块缓存池大小 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeBufferObjPool(IntPtr pAgent); + + /// <summary> + /// 获取 Socket 缓存池回收阀值 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeSocketObjHold(IntPtr pAgent); + + /// <summary> + /// 获取内存块缓存池回收阀值 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetFreeBufferObjHold(IntPtr pAgent); + + /// <summary> + /// 获取最大连接数 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetMaxConnectionCount(IntPtr pAgent); + + /// <summary> + /// 获取工作线程数量 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_Agent_GetWorkerThreadCount(IntPtr pAgent); + + /// <summary> + /// 检测是否标记静默时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_Agent_IsMarkSilence(IntPtr pAgent); + + /**********************************************************************************/ + /***************************** TCP Agent 属性访问方法 *****************************/ + + /// <summary> + /// 置是否启用地址重用机制(默认:不启用) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="bReuseAddress"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpAgent_SetReuseAddress(IntPtr pAgent, bool bReuseAddress); + + /// <summary> + /// 检测是否启用地址重用机制 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_TcpAgent_IsReuseAddress(IntPtr pAgent); + + /// <summary> + /// 设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwSocketBufferSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpAgent_SetSocketBufferSize(IntPtr pAgent, uint dwSocketBufferSize); + + /// <summary> + /// 设置心跳包间隔(毫秒,0 则不发送心跳包) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwKeepAliveTime"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpAgent_SetKeepAliveTime(IntPtr pAgent, uint dwKeepAliveTime); + + /// <summary> + /// 设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// </summary> + /// <param name="pAgent"></param> + /// <param name="dwKeepAliveInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpAgent_SetKeepAliveInterval(IntPtr pAgent, uint dwKeepAliveInterval); + + /// <summary> + /// 获取通信数据缓冲区大小 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpAgent_GetSocketBufferSize(IntPtr pAgent); + + /// <summary> + /// 获取心跳检查次数 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpAgent_GetKeepAliveTime(IntPtr pAgent); + + /// <summary> + /// 获取心跳检查间隔 + /// </summary> + /// <param name="pAgent"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpAgent_GetKeepAliveInterval(IntPtr pAgent); + + /***************************************************************************************/ + /***************************** TCP Pull Server 组件操作方法 *****************************/ + + /// <summary> + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullServer_Fetch(IntPtr pServer, IntPtr connId, IntPtr pBuffer, int length); + + /// <summary> + /// 窥探数据(不会移除缓冲区数据) + /// 描述:用户通过该方法从 Socket 组件中窥探数据 + /// </summary> + /// <param name="pServer"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">窥探缓冲区</param> + /// <param name="length">窥探数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullServer_Peek(IntPtr pServer, IntPtr connId, IntPtr pBuffer, int length); + + /***************************************************************************************/ + /***************************** TCP Pull Server 属性访问方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pull Client 组件操作方法 *****************************/ + + /// <summary> + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullClient_Fetch(IntPtr pClient, IntPtr pBuffer, int length); + + /// <summary> + /// 名称:窥探数据(不会移除缓冲区数据) + /// 描述:用户通过该方法从 Socket 组件中窥探数据 + /// </summary> + /// <param name="pClient"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullClient_Peek(IntPtr pClient, IntPtr pBuffer, int length); + + /***************************************************************************************/ + /***************************** TCP Pull Client 属性访问方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pull Agent 组件操作方法 *****************************/ + + /// <summary> + /// 抓取数据 + /// 用户通过该方法从 Socket 组件中抓取数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullAgent_Fetch(IntPtr pAgent, IntPtr connId, IntPtr pBuffer, int length); + + /// <summary> + /// 名称:窥探数据(不会移除缓冲区数据) + /// 描述:用户通过该方法从 Socket 组件中窥探数据 + /// </summary> + /// <param name="pAgent"></param> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffer">数据抓取缓冲区</param> + /// <param name="length">抓取数据长度</param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern FetchResult HP_TcpPullAgent_Peek(IntPtr pAgent, IntPtr connId, IntPtr pBuffer, int length); + + /***************************************************************************************/ + /***************************** TCP Pull Agent 属性访问方法 *****************************/ + + /***************************************************************************************/ + + /***************************************************************************************/ + /***************************** TCP Pack Server 组件操作方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pack Server 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据包最大长度(有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxPackSize">有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackServer_SetMaxPackSize(IntPtr pServer, uint dwMaxPackSize); + + /// <summary> + /// 设置包头标识(有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0) + /// </summary> + /// <param name="pServer"></param> + /// <param name="usPackHeaderFlag">有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackServer_SetPackHeaderFlag(IntPtr pServer, ushort usPackHeaderFlag); + + /// <summary> + /// 获取数据包最大长度 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpPackServer_GetMaxPackSize(IntPtr pServer); + + /// <summary> + /// 获取包头标识 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ushort HP_TcpPackServer_GetPackHeaderFlag(IntPtr pServer); + /***************************************************************************************/ + /***************************** TCP Pack Agent 组件操作方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pack Agent 属性访问方法 *****************************/ + + /// <summary> + /// 设置数据包最大长度(有效数据包最大长度不能超过 524287/0x7FFFF 字节,默认:262144/0x40000) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxPackSize">有效数据包最大长度不能超过 524287/0x7FFFF 字节,默认:262144/0x40000</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackAgent_SetMaxPackSize(IntPtr pAgent, uint dwMaxPackSize); + + /// <summary> + /// 设置包头标识(有效包头标识取值范围 0 ~ 8191/0x1FFF,当包头标识为 0 时不校验包头,默认:0) + /// </summary> + /// <param name="pServer"></param> + /// <param name="usPackHeaderFlag">有效包头标识取值范围 0 ~ 8191/0x1FFF,当包头标识为 0 时不校验包头,默认:0</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackAgent_SetPackHeaderFlag(IntPtr pAgent, ushort usPackHeaderFlag); + + /// <summary> + /// 获取数据包最大长度 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpPackAgent_GetMaxPackSize(IntPtr pAgent); + + /// <summary> + /// 获取包头标识 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ushort HP_TcpPackAgent_GetPackHeaderFlag(IntPtr pAgent); + /***************************************************************************************/ + /***************************** TCP Pack Client 组件操作方法 *****************************/ + + /***************************************************************************************/ + /***************************** TCP Pack Client 属性访问方法 *****************************/ + /// <summary> + /// 设置数据包最大长度(有效数据包最大长度不能超过 524287/0x7FFFF 字节,默认:262144/0x40000) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxPackSize">有效数据包最大长度不能超过 524287/0x7FFFF 字节,默认:262144/0x40000</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackClient_SetMaxPackSize(IntPtr pClient, uint dwMaxPackSize); + + /// <summary> + /// 设置包头标识(有效包头标识取值范围 0 ~ 8191/0x1FFF,当包头标识为 0 时不校验包头,默认:0) + /// </summary> + /// <param name="pServer"></param> + /// <param name="usPackHeaderFlag">有效包头标识取值范围 0 ~ 8191/0x1FFF,当包头标识为 0 时不校验包头,默认:0</param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_TcpPackClient_SetPackHeaderFlag(IntPtr pClient, ushort usPackHeaderFlag); + + /// <summary> + /// 获取数据包最大长度 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_TcpPackClient_GetMaxPackSize(IntPtr pClient); + + /// <summary> + /// 获取包头标识 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ushort HP_TcpPackClient_GetPackHeaderFlag(IntPtr pClient); + /***************************************************************************************/ + /*************************************** 其它方法 ***************************************/ + + /// <summary> + /// 获取 HPSocket 版本号(4 个字节分别为:主版本号,子版本号,修正版本号,构建编号) + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_GetHPSocketVersion(); + + /// <summary> + /// 获取版本号 + /// </summary> + /// <returns></returns> + public static string GetHPSocketVersion() + { + /* + var ver = BitConverter.GetBytes(HP_GetHPSocketVersion()); + var major = ver[3]; + var minor = ver[2]; + var revision = ver[1]; + var build = ver[0];*/ + + uint ver = HP_GetHPSocketVersion(); + var major = ver >> 24; + var minor = (ver << 8) >> 24; + var revision = (ver << 16) >> 24; + var build = (ver << 24) >> 24; + + return string.Format("{0}.{1}.{2}_{3}", major, minor, revision, build); + } + + /// <summary> + /// 获取错误描述文本 + /// </summary> + /// <param name="enCode"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr HP_GetSocketErrorDesc(SocketError enCode); + + /// <summary> + /// 调用系统的 ::GetLastError() 方法获取系统错误代码 + /// </summary> + /// <returns></returns> + public static int SYS_GetLastError() + { + return Marshal.GetLastWin32Error(); + } + + /// <summary> + /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_WSAGetLastError(); + + /// <summary> + /// 调用系统的 setsockopt() + /// </summary> + /// <param name="sock"></param> + /// <param name="level"></param> + /// <param name="name"></param> + /// <param name="val"></param> + /// <param name="len"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len); + + /// <summary> + /// 调用系统的 getsockopt() + /// </summary> + /// <param name="sock"></param> + /// <param name="level"></param> + /// <param name="name"></param> + /// <param name="val"></param> + /// <param name="len"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_GetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len); + + /// <summary> + /// 调用系统的 ioctlsocket() + /// </summary> + /// <param name="sock"></param> + /// <param name="cmd"></param> + /// <param name="arg"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_IoctlSocket(IntPtr sock, long cmd, IntPtr arg); + + /// <summary> + /// 调用系统的 ::WSAIoctl() + /// </summary> + /// <param name="sock"></param> + /// <param name="dwIoControlCode"></param> + /// <param name="lpvInBuffer"></param> + /// <param name="cbInBuffer"></param> + /// <param name="lpvOutBuffer"></param> + /// <param name="cbOutBuffer"></param> + /// <param name="lpcbBytesReturned"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, + IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned); + + /// <summary> + /// 设置 socket 选项:IPPROTO_TCP -> TCP_NODELAY + /// </summary> + /// <param name="sock"></param> + /// <param name="bNoDelay"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_NoDelay(IntPtr sock, bool bNoDelay); + + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_DONTLINGER + /// </summary> + /// <param name="sock"></param> + /// <param name="bDont"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_DontLinger(IntPtr sock, bool bDont); + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_LINGER + /// </summary> + /// <param name="sock"></param> + /// <param name="l_onoff"></param> + /// <param name="l_linger"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_Linger(IntPtr sock, ushort l_onoff, ushort l_linger); + + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_RCVBUF + /// </summary> + /// <param name="sock"></param> + /// <param name="size"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_RecvBuffSize(IntPtr sock, int size); + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_SNDBUF + /// </summary> + /// <param name="sock"></param> + /// <param name="size"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_SendBuffSize(IntPtr sock, int size); + + /// <summary> + /// 设置 socket 选项:SOL_SOCKET -> SO_REUSEADDR + /// </summary> + /// <param name="sock"></param> + /// <param name="bReuse"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern int SYS_SSO_ReuseAddress(IntPtr sock, bool bReuse); + + /// <summary> + /// 获取 SOCKET 本地地址信息 + /// </summary> + /// <param name="pSocket"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen">传入传出值,大小最好在222.222.222.222的长度以上</param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_GetSocketLocalAddress(IntPtr pSocket, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + /// <summary> + /// 获取 SOCKET 远程地址信息 + /// </summary> + /// <param name="pSocket"></param> + /// <param name="lpszAddress"></param> + /// <param name="piAddressLen">传入传出值,大小最好在222.222.222.222的长度以上</param> + /// <param name="pusPort"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_GetSocketRemoteAddress(IntPtr pSocket, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszAddress, ref int piAddressLen, ref ushort pusPort); + + + /// <summary> + /// 枚举主机 IP 地址 + /// 不要用,未测试 + /// 不要用,未测试 + /// 不要用,未测试 + /// </summary> + /// <param name="lpszHost"></param> + /// <param name="enType"></param> + /// <param name="lpppIPAddr"></param> + /// <param name="piIPAddrCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_EnumHostIPAddresses(string lpszHost, IPAddrType enType, ref IntPtr lpppIPAddr, ref int piIPAddrCount); + + + /// <summary> + /// 释放 HP_LPTIPAddr + /// </summary> + /// <param name="lppIPAddr"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_FreeHostIPAddresses(IntPtr lppIPAddr); + + + /* + * 已删除 + /// <summary> + /// 获取 IPv4 地址 + /// </summary> + /// <param name="lpszAddress"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint SYS_GetIPv4InAddr(string lpszAddress); + */ + /// <summary> + /// 检查字符串是否符合 IP 地址格式 + /// </summary> + /// <param name="lpszAddress"></param> + /// <param name="penType"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_IsIPAddress(string lpszAddress, ref IPAddrType penType); + + /// <summary> + /// 通过主机名获取 IP 地址 + /// </summary> + /// <param name="lpszHost"></param> + /// <param name="lpszIP"></param> + /// <param name="piIPLenth"></param> + /// <param name="penType"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_GetIPAddress(string lpszHost, [MarshalAs(UnmanagedType.LPStr)] StringBuilder lpszIP, ref int piIPLenth, ref IPAddrType penType); + + /* + * 已删除 + /// <summary> + /// 通过主机名获取最优的 IP 地址 + /// </summary> + /// <param name="lpszHost"></param> + /// <param name="pulAddr"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool SYS_GetOptimalIPByHostName(string lpszHost, ref uint pulAddr); + */ + + /// <summary> + /// 64 位网络字节序转主机字节序 + /// </summary> + /// <param name="value"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ulong SYS_NToH64(ulong value); + + /// <summary> + /// 64 位主机字节序转网络字节序 + /// </summary> + /// <param name="value"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern ulong SYS_HToN64(ulong value); + + + /// <summary> + /// 分配内存 + /// </summary> + /// <param name="value"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr SYS_Malloc(int value); + + /// <summary> + /// 重新分配内存 + /// </summary> + /// <param name="p"></param> + /// <param name="value"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr SYS_Realloc(IntPtr p, int value); + + /// <summary> + /// 释放内存 + /// </summary> + /// <param name="p"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void SYS_Free(IntPtr p); + + + + + + /// <summary> + /// 创建 HP_UdpArqServer 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpArqServer(IntPtr pListener); + + /// <summary> + /// 创建 HP_UdpArqClient 对象 + /// </summary> + /// <param name="pListener"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpArqClient(IntPtr pListener); + + /// <summary> + /// 销毁 HP_UdpArqServer 对象 + /// </summary> + /// <param name="pServer"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpArqServer(IntPtr pServer); + + /// <summary> + /// 销毁 HP_UdpArqClient 对象 + /// </summary> + /// <param name="pClient"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpArqClient(IntPtr pClient); + + /// <summary> + /// 创建 HP_UdpArqServerListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpArqServerListener(); + + /// <summary> + /// 创建 HP_UdpArqClientListener 对象 + /// </summary> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern IntPtr Create_HP_UdpArqClientListener(); + + /// <summary> + /// 销毁 HP_UdpArqServerListener 对象 + /// </summary> + /// <param name="pListener"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpArqServerListener(IntPtr pListener); + + /// <summary> + /// 销毁 HP_UdpArqClientListener 对象 + /// </summary> + /// <param name="pListener"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void Destroy_HP_UdpArqClientListener(IntPtr pListener); + + /**********************************************************************************/ + /*************************** UDP ARQ Server 属性访问方法 ***************************/ + + + /// <summary> + /// 设置是否开启 nodelay 模式(默认:FALSE,不开启) + /// </summary> + /// <param name="pServer"></param> + /// <param name="bNoDelay"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetNoDelay(IntPtr pServer, bool bNoDelay); + + /// <summary> + /// 设置是否关闭拥塞控制(默认:FALSE,不关闭) + /// </summary> + /// <param name="pServer"></param> + /// <param name="bTurnOff"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetTurnoffCongestCtrl(IntPtr pServer, bool bTurnOff); + + /// <summary> + /// 设置数据刷新间隔(毫秒,默认:20) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwFlushInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetFlushInterval(IntPtr pServer, uint dwFlushInterval); + + /// <summary> + /// 设置快速重传 ACK 跨越次数(默认:0,关闭快速重传) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwResendByAcks"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetResendByAcks(IntPtr pServer, uint dwResendByAcks); + + /// <summary> + /// 设置发送窗口大小(数据包数量,默认:128) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwSendWndSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetSendWndSize(IntPtr pServer, uint dwSendWndSize); + + /// <summary> + /// 设置接收窗口大小(数据包数量,默认:512) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwRecvWndSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetRecvWndSize(IntPtr pServer, uint dwRecvWndSize); + + /// <summary> + /// 设置最小重传超时时间(毫秒,默认:30) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMinRto"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetMinRto(IntPtr pServer, uint dwMinRto); + + /// <summary> + /// 设置最大传输单元(默认:0,与 SetMaxDatagramSize() 一致) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxTransUnit"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetMaxTransUnit(IntPtr pServer, uint dwMaxTransUnit); + + /// <summary> + /// 设置最大数据包大小(默认:4096) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwMaxMessageSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetMaxMessageSize(IntPtr pServer, uint dwMaxMessageSize); + + /// <summary> + /// 设置握手超时时间(毫秒,默认:5000) + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwHandShakeTimeout"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqServer_SetHandShakeTimeout(IntPtr pServer, uint dwHandShakeTimeout); + + + /// <summary> + /// 检测是否开启 nodelay 模式 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqServer_IsNoDelay(IntPtr pServer); + + /// <summary> + /// 检测是否关闭拥塞控制 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqServer_IsTurnoffCongestCtrl(IntPtr pServer); + + /// <summary> + /// 获取数据刷新间隔 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetFlushInterval(IntPtr pServer); + + /// <summary> + /// 获取快速重传 ACK 跨越次数 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetResendByAcks(IntPtr pServer); + + /// <summary> + /// 获取发送窗口大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetSendWndSize(IntPtr pServer); + + /// <summary> + /// 获取接收窗口大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetRecvWndSize(IntPtr pServer); + + /// <summary> + /// 获取最小重传超时时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetMinRto(IntPtr pServer); + + /// <summary> + /// 获取最大传输单元 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetMaxTransUnit(IntPtr pServer); + + /// <summary> + /// 获取最大数据包大小 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetMaxMessageSize(IntPtr pServer); + + /// <summary> + /// 获取握手超时时间 + /// </summary> + /// <param name="pServer"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqServer_GetHandShakeTimeout(IntPtr pServer); + + + /// <summary> + /// 获取等待发送包数量 + /// </summary> + /// <param name="pServer"></param> + /// <param name="dwConnId"></param> + /// <param name="piCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqServer_GetWaitingSendMessageCount(IntPtr pServer, IntPtr dwConnId, ref int piCount); + + /**********************************************************************************/ + /*************************** UDP ARQ Client 属性访问方法 ***************************/ + + + /// <summary> + /// 设置是否开启 nodelay 模式(默认:FALSE,不开启) + /// </summary> + /// <param name="pClient"></param> + /// <param name="bNoDelay"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetNoDelay(IntPtr pClient, bool bNoDelay); + + /// <summary> + /// 设置是否关闭拥塞控制(默认:FALSE,不关闭) + /// </summary> + /// <param name="pClient"></param> + /// <param name="bTurnOff"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetTurnoffCongestCtrl(IntPtr pClient, bool bTurnOff); + + /// <summary> + /// 设置数据刷新间隔(毫秒,默认:20) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwFlushInterval"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetFlushInterval(IntPtr pClient, uint dwFlushInterval); + + /// <summary> + /// 设置快速重传 ACK 跨越次数(默认:0,关闭快速重传) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwResendByAcks"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetResendByAcks(IntPtr pClient, uint dwResendByAcks); + + /// <summary> + /// 设置发送窗口大小(数据包数量,默认:128) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwSendWndSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetSendWndSize(IntPtr pClient, uint dwSendWndSize); + + /// <summary> + /// 设置接收窗口大小(数据包数量,默认:512) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwRecvWndSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetRecvWndSize(IntPtr pClient, uint dwRecvWndSize); + + /// <summary> + /// 设置最小重传超时时间(毫秒,默认:30) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwMinRto"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetMinRto(IntPtr pClient, uint dwMinRto); + + /// <summary> + /// 设置最大传输单元(默认:0,与 SetMaxDatagramSize() 一致) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwMaxTransUnit"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetMaxTransUnit(IntPtr pClient, uint dwMaxTransUnit); + + /// <summary> + /// 设置最大数据包大小(默认:4096) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwMaxMessageSize"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetMaxMessageSize(IntPtr pClient, uint dwMaxMessageSize); + + /// <summary> + /// 设置握手超时时间(毫秒,默认:5000) + /// </summary> + /// <param name="pClient"></param> + /// <param name="dwHandShakeTimeout"></param> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern void HP_UdpArqClient_SetHandShakeTimeout(IntPtr pClient, uint dwHandShakeTimeout); + + + /// <summary> + /// 检测是否开启 nodelay 模式 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqClient_IsNoDelay(IntPtr pClient); + + /// <summary> + /// 检测是否关闭拥塞控制 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqClient_IsTurnoffCongestCtrl(IntPtr pClient); + + /// <summary> + /// 获取数据刷新间隔 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetFlushInterval(IntPtr pClient); + + /// <summary> + /// 获取快速重传 ACK 跨越次数 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetResendByAcks(IntPtr pClient); + + /// <summary> + /// 获取发送窗口大小 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetSendWndSize(IntPtr pClient); + + /// <summary> + /// 获取接收窗口大小 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetRecvWndSize(IntPtr pClient); + + /// <summary> + /// 获取最小重传超时时间 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetMinRto(IntPtr pClient); + + /// <summary> + /// 获取最大传输单元 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetMaxTransUnit(IntPtr pClient); + + /// <summary> + /// 获取最大数据包大小 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetMaxMessageSize(IntPtr pClient); + + /// <summary> + /// 获取握手超时时间 + /// </summary> + /// <param name="pClient"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern uint HP_UdpArqClient_GetHandShakeTimeout(IntPtr pClient); + + + /// <summary> + /// 获取等待发送包数量 + /// </summary> + /// <param name="pClient"></param> + /// <param name="piCount"></param> + /// <returns></returns> + [DllImport(HPSOCKET_DLL_PATH, CharSet = CharSet.Ansi, SetLastError = true)] + public static extern bool HP_UdpArqClient_GetWaitingSendMessageCount(IntPtr pClient, ref int piCount); + + +} diff --git a/PCRobot/PCWechat/Dazong/TcpPackServer.cs b/PCRobot/PCWechat/Dazong/TcpPackServer.cs new file mode 100644 index 0000000..ed1fe4c --- /dev/null +++ b/PCRobot/PCWechat/Dazong/TcpPackServer.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace HPSocketCS +{ + public class TcpPackServer<T> : TcpPackServer + { + public new T GetExtra(IntPtr connId) + { + return base.GetExtra<T>(connId); + } + + public bool SetExtra(IntPtr connId, T obj) + { + return base.SetExtra(connId, obj); + } + } + + public class TcpPackServer : TcpServer + { + + /// <summary> + /// 创建socket监听&服务组件 + /// </summary> + /// <returns></returns> + protected override bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pServer != IntPtr.Zero) + { + return false; + } + + pListener = Sdk.Create_HP_TcpPackServerListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + + pServer = Sdk.Create_HP_TcpPackServer(pListener); + if (pServer == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// <summary> + /// 终止服务并释放资源 + /// </summary> + public override void Destroy() + { + Stop(); + + if (pServer != IntPtr.Zero) + { + Sdk.Destroy_HP_TcpPackServer(pServer); + pServer = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + Sdk.Destroy_HP_TcpPackServerListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + /// <summary> + /// 读取或设置数据包最大长度 + /// 有效数据包最大长度不能超过 4194303/0x3FFFFF 字节,默认:262144/0x40000 + /// </summary> + public uint MaxPackSize + { + get + { + return Sdk.HP_TcpPackServer_GetMaxPackSize(pServer); + } + set + { + Sdk.HP_TcpPackServer_SetMaxPackSize(pServer, value ); + } + } + + /// <summary> + /// 读取或设置包头标识 + /// 有效包头标识取值范围 0 ~ 1023/0x3FF,当包头标识为 0 时不校验包头,默认:0 + /// </summary> + public ushort PackHeaderFlag + { + get + { + return Sdk.HP_TcpPackServer_GetPackHeaderFlag(pServer); + } + set + { + Sdk.HP_TcpPackServer_SetPackHeaderFlag(pServer, value); + } + } + + + } +} diff --git a/PCRobot/PCWechat/Dazong/TcpServer.cs b/PCRobot/PCWechat/Dazong/TcpServer.cs new file mode 100644 index 0000000..79f2b3f --- /dev/null +++ b/PCRobot/PCWechat/Dazong/TcpServer.cs @@ -0,0 +1,1147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Serialization; + +namespace HPSocketCS +{ + + public class TcpServer<T> : TcpServer + { + public new T GetExtra(IntPtr connId) + { + return base.GetExtra<T>(connId); + } + + public bool SetExtra(IntPtr connId, T obj) + { + return base.SetExtra(connId, obj); + } + } + + public class TcpServer : ConnectionExtra, IServer + { + protected IntPtr pServer = IntPtr.Zero; + protected IntPtr pListener = IntPtr.Zero; + + /// <summary> + /// 服务器ip + /// </summary> + public string IpAddress { get; set; } + + /// <summary> + /// 服务器端口 + /// </summary> + public ushort Port { get; set; } + + /// <summary> + /// 连接到达事件 + /// </summary> + public event ServerEvent.OnAcceptEventHandler OnAccept; + /// <summary> + /// 数据包发送事件 + /// </summary> + public event ServerEvent.OnSendEventHandler OnSend; + /// <summary> + /// 准备监听了事件 + /// </summary> + public event ServerEvent.OnPrepareListenEventHandler OnPrepareListen; + /// <summary> + /// 数据到达事件 + /// </summary> + public event ServerEvent.OnReceiveEventHandler OnReceive; + /// <summary> + /// 数据到达事件(指针数据) + /// </summary> + public event ServerEvent.OnPointerDataReceiveEventHandler OnPointerDataReceive; + /// <summary> + /// 连接关闭事件 + /// </summary> + public event ServerEvent.OnCloseEventHandler OnClose; + /// <summary> + /// 服务器关闭事件 + /// </summary> + public event ServerEvent.OnShutdownEventHandler OnShutdown; + /// <summary> + /// 握手成功事件 + /// </summary> + public event ServerEvent.OnHandShakeEventHandler OnHandShake; + + protected bool IsCreate = false; + + + public TcpServer() + { + CreateListener(); + } + + ~TcpServer() + { + Destroy(); + } + + /// <summary> + /// 创建socket监听&服务组件 + /// </summary> + /// <returns></returns> + protected virtual bool CreateListener() + { + if (IsCreate == true || pListener != IntPtr.Zero || pServer != IntPtr.Zero) + { + return false; + } + + pListener = Sdk.Create_HP_TcpServerListener(); + if (pListener == IntPtr.Zero) + { + return false; + } + pServer = Sdk.Create_HP_TcpServer(pListener); + if (pServer == IntPtr.Zero) + { + return false; + } + + IsCreate = true; + + return true; + } + + /// <summary> + /// 终止服务并释放资源 + /// </summary> + public virtual void Destroy() + { + Stop(); + + if (pServer != IntPtr.Zero) + { + Sdk.Destroy_HP_TcpServer(pServer); + pServer = IntPtr.Zero; + } + if (pListener != IntPtr.Zero) + { + Sdk.Destroy_HP_TcpServerListener(pListener); + pListener = IntPtr.Zero; + } + + IsCreate = false; + } + + + /// <summary> + /// 启动服务 + /// </summary> + /// <returns></returns> + public bool Start() + { + if (IsCreate == false) + { + return false; + } + if (pServer == IntPtr.Zero) + { + return false; + } + + SetCallback(); + + return Sdk.HP_Server_Start(pServer, IpAddress, Port); + } + + /// <summary> + /// 停止服务 + /// </summary> + /// <returns></returns> + public bool Stop() + { + if (pServer == IntPtr.Zero) + { + return false; + } + + return Sdk.HP_Server_Stop(pServer); + } + + /// <summary> + /// 发送数据 + /// </summary> + /// <param name="connId"></param> + /// <param name="bytes"></param> + /// <param name="size"></param> + /// <returns></returns> + public bool Send(IntPtr connId, byte[] bytes, int size) + { + return Sdk.HP_Server_Send(pServer, connId, bytes, size); + } + + /// <summary> + /// 发送数据 + /// </summary> + /// <param name="connId"></param> + /// <param name="bufferPtr"></param> + /// <param name="size"></param> + /// <returns></returns> + public bool Send(IntPtr connId, IntPtr bufferPtr, int size) + { + return Sdk.HP_Server_Send(pServer, connId, bufferPtr, size); + } + + + /// <summary> + /// 发送数据 + /// </summary> + /// <param name="connId"></param> + /// <param name="bytes"></param> + /// <param name="offset">针对bytes的偏移</param> + /// <param name="size">发多大</param> + /// <returns></returns> + public bool Send(IntPtr connId, byte[] bytes, int offset, int size) + { + return Sdk.HP_Server_SendPart(pServer, connId, bytes, size, offset); + } + + /// <summary> + /// 发送数据 + /// </summary> + /// <param name="connId"></param> + /// <param name="bufferPtr"></param> + /// <param name="offset">针对bufferPtr的偏移</param> + /// <param name="size">发多大</param> + /// <returns></returns> + public bool Send(IntPtr connId, IntPtr bufferPtr, int offset, int size) + { + return Sdk.HP_Server_SendPart(pServer, connId, bufferPtr, size, offset); + } + + + /// <summary> + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// </summary> + /// <param name="connId">连接 ID</param> + /// <param name="pBuffers">发送缓冲区数组</param> + /// <param name="count">发送缓冲区数目</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendPackets(IntPtr connId, WSABUF[] pBuffers, int count) + { + return Sdk.HP_Server_SendPackets(pServer, connId, pBuffers, count); + } + + /// <summary> + /// 发送多组数据 + /// 向指定连接发送多组数据 + /// TCP - 顺序发送所有数据包 + /// </summary> + /// <param name="connId">连接 ID</param> + /// <param name="objects">发送缓冲区数组</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendPackets<T>(IntPtr connId, T[] objects) + { + bool ret = false; + + WSABUF[] buffer = new WSABUF[objects.Length]; + IntPtr[] ptrs = new IntPtr[buffer.Length]; + try + { + + for (int i = 0; i < objects.Length; i++) + { + buffer[i].Length = Marshal.SizeOf(typeof(T)); + + ptrs[i] = Marshal.AllocHGlobal(buffer[i].Length); + Marshal.StructureToPtr(objects[i], ptrs[i], true); + + buffer[i].Buffer = ptrs[i]; + } + ret = SendPackets(connId, buffer, buffer.Length); + } + catch (Exception ex) + { + throw ex; + } + finally + { + foreach (var ptr in ptrs) + { + if (ptr != IntPtr.Zero) + { + Marshal.FreeHGlobal(ptr); + } + } + } + + return ret; + } + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="connId"></param> + /// <param name="filePath">文件路径</param> + /// <param name="head">头部附加数据</param> + /// <param name="tail">尾部附加数据</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendSmallFile(IntPtr connId, string filePath, ref WSABUF head, ref WSABUF tail) + { + return Sdk.HP_TcpServer_SendSmallFile(pServer, connId, filePath, ref head, ref tail); + } + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="connId"></param> + /// <param name="filePath">文件路径</param> + /// <param name="head">头部附加数据,可以为null</param> + /// <param name="tail">尾部附加数据,可以为null</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendSmallFile(IntPtr connId, string filePath, byte[] head, byte[] tail) + { + IntPtr pHead = IntPtr.Zero; + IntPtr pTail = IntPtr.Zero; + WSABUF wsaHead = new WSABUF() { Length = 0, Buffer = pHead }; + WSABUF wsatail = new WSABUF() { Length = 0, Buffer = pTail }; + if (head != null) + { + wsaHead.Length = head.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(head, 0); + } + + if (tail != null) + { + wsaHead.Length = tail.Length; + wsaHead.Buffer = Marshal.UnsafeAddrOfPinnedArrayElement(tail, 0); + } + + return SendSmallFile(connId, filePath, ref wsaHead, ref wsatail); + } + + /// <summary> + /// 名称:发送小文件 + /// 描述:向指定连接发送 4096 KB 以下的小文件 + /// </summary> + /// <param name="connId"></param> + /// <param name="filePath">文件路径</param> + /// <param name="head">头部附加数据,可以为null</param> + /// <param name="tail">尾部附加数据,可以为null</param> + /// <returns>TRUE.成功,FALSE.失败,可通过 SYSGetLastError() 获取 Windows 错误代码</returns> + public bool SendSmallFile<T1, T2>(IntPtr connId, string filePath, T1 head, T2 tail) + { + + byte[] headBuffer = null; + if (head != null) + { + headBuffer = StructureToByte<T1>(head); + } + + byte[] tailBuffer = null; + if (tail != null) + { + tailBuffer = StructureToByte<T2>(tail); + } + return SendSmallFile(connId, filePath, headBuffer, tailBuffer); + } + + /// <summary> + /// 断开与某个客户的连接 + /// </summary> + /// <param name="connId"></param> + /// <param name="force">是否强制断开</param> + /// <returns></returns> + public bool Disconnect(IntPtr connId, bool force = true) + { + return Sdk.HP_Server_Disconnect(pServer, connId, force); + } + + /// <summary> + /// 断开超过指定时间的连接 + /// </summary> + /// <param name="period">毫秒</param> + /// <param name="force">强制</param> + /// <returns></returns> + public bool DisconnectLongConnections(uint period, bool force = true) + { + return Sdk.HP_Server_DisconnectLongConnections(pServer, period, force); + } + + + /// <summary> + /// 暂停接收 + /// </summary> + /// <param name="connId"></param> + /// <returns></returns> + public bool PauseReceive(IntPtr connId) + { + return Sdk.HP_Server_PauseReceive(pServer, connId, true); + } + + /// <summary> + /// 唤醒接收 + /// </summary> + /// <param name="connId"></param> + /// <returns></returns> + public bool ResumeReceive(IntPtr connId) + { + return Sdk.HP_Server_PauseReceive(pServer, connId, false); + } + + /// <summary> + /// 获取连接的接收状态 + /// </summary> + /// <param name="connId"></param> + /// <returns></returns> + public ReceiveState GetReceiveState(IntPtr connId) + { + int state = -1; + + if (Sdk.HP_Server_IsPauseReceive(pServer, connId, ref state)) + { + return (ReceiveState)state; + } + return ReceiveState.Unknown; + } + + /// <summary> + /// 断开超过指定时长的静默连接 + /// </summary> + /// <param name="period">毫秒</param> + /// <param name="force">强制</param> + /// <returns></returns> + public bool DisconnectSilenceConnections(uint period, bool force = true) + { + return Sdk.HP_Server_DisconnectSilenceConnections(pServer, period, force); + } + + /// <summary> + /// 获取某个连接的本地地址信息 + /// </summary> + /// <param name="connId"></param> + /// <param name="ip"></param> + /// <param name="port"></param> + /// <returns></returns> + public bool GetLocalAddress(IntPtr connId, ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = Sdk.HP_Server_GetLocalAddress(pServer, connId, sb, ref ipLength, ref port) && ipLength > 0; + if (ret == true) + { + ip = sb.ToString(); + } + + return ret; + } + + /// <summary> + /// 获取某个连接的远程地址信息 + /// </summary> + /// <param name="connId"></param> + /// <param name="ip"></param> + /// <param name="port"></param> + /// <returns></returns> + public bool GetRemoteAddress(IntPtr connId, ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = Sdk.HP_Server_GetRemoteAddress(pServer, connId, sb, ref ipLength, ref port) && ipLength > 0; + if (ret == true) + { + ip = sb.ToString(); + } + + return ret; + } + + /// <summary> + /// 获取连接中未发出数据的长度 + /// </summary> + /// <param name="connId"></param> + /// <param name="length"></param> + /// <returns></returns> + public bool GetPendingDataLength(IntPtr connId, ref int length) + { + return Sdk.HP_Server_GetPendingDataLength(pServer, connId, ref length); + } + + // 是否启动 + public bool IsStarted + { + get + { + if (pServer == IntPtr.Zero) + { + return false; + } + return Sdk.HP_Server_HasStarted(pServer); + } + } + + /// <summary> + /// 状态 + /// </summary> + public ServiceState State + { + get + { + return Sdk.HP_Server_GetState(pServer); + } + + } + + /// <summary> + /// 连接数 + /// </summary> + public uint ConnectionCount + { + get + { + return Sdk.HP_Server_GetConnectionCount(pServer); + } + + } + + /// <summary> + /// 检测是否为安全连接(SSL/HTTPS) + /// </summary> + public bool IsSecure + { + get + { + return Sdk.HP_Server_IsSecure(pServer); + } + } + + /// <summary> + /// 获取所有连接,未获取到连接返回null + /// </summary> + /// <returns></returns> + public IntPtr[] GetAllConnectionIDs() + { + IntPtr[] arr = null; + do + { + uint count = ConnectionCount; + if (count == 0) + { + break; + } + arr = new IntPtr[count]; + if (Sdk.HP_Server_GetAllConnectionIDs(pServer, arr, ref count)) + { + if (arr.Length > count) + { + IntPtr[] newArr = new IntPtr[count]; + Array.Copy(arr, newArr, count); + arr = newArr; + } + break; + } + } while (true); + + return arr; + } + + /// <summary> + /// 获取监听socket的地址信息 + /// </summary> + /// <param name="ip"></param> + /// <param name="port"></param> + /// <returns></returns> + public bool GetListenAddress(ref string ip, ref ushort port) + { + int ipLength = 40; + + StringBuilder sb = new StringBuilder(ipLength); + + bool ret = Sdk.HP_Server_GetListenAddress(pServer, sb, ref ipLength, ref port); + if (ret == true) + { + ip = sb.ToString(); + } + return ret; + } + + + /// <summary> + /// 获取指定连接的连接时长(毫秒) + /// </summary> + /// <param name="connId"></param> + /// <param name="period"></param> + /// <returns></returns> + public bool GetConnectPeriod(IntPtr connId, ref uint period) + { + return Sdk.HP_Server_GetConnectPeriod(pServer, connId, ref period); + } + + /// <summary> + /// 获取某个连接静默时间(毫秒) + /// </summary> + /// <param name="connId"></param> + /// <param name="period"></param> + /// <returns></returns> + public bool GetSilencePeriod(IntPtr connId, ref uint period) + { + return Sdk.HP_Server_GetSilencePeriod(pServer, connId, ref period); + } + + /////////////////////////////////////////////////////////////////////////////////////// + + /// <summary> + /// 设置最大连接数(组件会根据设置值预分配内存,因此需要根据实际情况设置,不宜过大) + /// </summary> + public uint MaxConnectionCount + { + get + { + return Sdk.HP_Server_GetMaxConnectionCount(pServer); + } + set + { + Sdk.HP_Server_SetMaxConnectionCount(pServer, value); + } + } + + /// <summary> + /// 读取或设置工作线程数量(通常设置为 2 * CPU + 2) + /// </summary> + public uint WorkerThreadCount + { + get + { + return Sdk.HP_Server_GetWorkerThreadCount(pServer); + } + set + { + Sdk.HP_Server_SetWorkerThreadCount(pServer, value); + } + } + + /// <summary> + /// 读取或设置 Accept 预投递数量(根据负载调整设置,Accept 预投递数量越大则支持的并发连接请求越多) + /// </summary> + public uint AcceptSocketCount + { + get + { + return Sdk.HP_TcpServer_GetAcceptSocketCount(pServer); + } + set + { + Sdk.HP_TcpServer_SetAcceptSocketCount(pServer, value); + } + } + + /// <summary> + /// 读取或设置通信数据缓冲区大小(根据平均通信数据包大小调整设置,通常设置为 1024 的倍数) + /// </summary> + public uint SocketBufferSize + { + get + { + return Sdk.HP_TcpServer_GetSocketBufferSize(pServer); + } + set + { + Sdk.HP_TcpServer_SetSocketBufferSize(pServer, value); + } + } + + /// <summary> + /// 读取或设置监听 Socket 的等候队列大小(根据并发连接数量调整设置) + /// </summary> + public uint SocketListenQueue + { + get + { + return Sdk.HP_TcpServer_GetSocketListenQueue(pServer); + } + set + { + Sdk.HP_TcpServer_SetSocketListenQueue(pServer, value); + } + } + + /// <summary> + /// 读取或设置 Socket 缓存对象锁定时间(毫秒,在锁定期间该 Socket 缓存对象不能被获取使用) + /// </summary> + public uint FreeSocketObjLockTime + { + get + { + return Sdk.HP_Server_GetFreeSocketObjLockTime(pServer); + } + set + { + Sdk.HP_Server_SetFreeSocketObjLockTime(pServer, value); + } + } + + /// <summary> + /// 读取或设置 Socket 缓存池大小(通常设置为平均并发连接数量的 1/3 - 1/2) + /// </summary> + public uint FreeSocketObjPool + { + get + { + return Sdk.HP_Server_GetFreeSocketObjPool(pServer); + } + set + { + Sdk.HP_Server_SetFreeSocketObjPool(pServer, value); + } + } + + /// <summary> + /// 读取或设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// </summary> + public uint FreeBufferObjPool + { + get + { + return Sdk.HP_Server_GetFreeBufferObjPool(pServer); + } + set + { + Sdk.HP_Server_SetFreeBufferObjPool(pServer, value); + } + } + + /// <summary> + /// 读取或设置内存块缓存池大小(通常设置为 Socket 缓存池大小的 2 - 3 倍) + /// </summary> + public uint FreeSocketObjHold + { + get + { + return Sdk.HP_Server_GetFreeSocketObjHold(pServer); + } + set + { + Sdk.HP_Server_SetFreeSocketObjHold(pServer, value); + } + } + + /// <summary> + /// 读取或设置内存块缓存池回收阀值(通常设置为内存块缓存池大小的 3 倍) + /// </summary> + public uint FreeBufferObjHold + { + get + { + return Sdk.HP_Server_GetFreeBufferObjHold(pServer); + } + set + { + Sdk.HP_Server_SetFreeBufferObjHold(pServer, value); + } + } + + /// <summary> + /// 读取或设置心跳包间隔(毫秒,0 则不发送心跳包) + /// </summary> + public uint KeepAliveTime + { + get + { + return Sdk.HP_TcpServer_GetKeepAliveTime(pServer); + } + set + { + Sdk.HP_TcpServer_SetKeepAliveTime(pServer, value); + } + } + + /// <summary> + /// 读取或设置心跳确认包检测间隔(毫秒,0 不发送心跳包,如果超过若干次 [默认:WinXP 5 次, Win7 10 次] 检测不到心跳确认包则认为已断线) + /// </summary> + public uint KeepAliveInterval + { + get + { + return Sdk.HP_TcpServer_GetKeepAliveInterval(pServer); + } + set + { + Sdk.HP_TcpServer_SetKeepAliveInterval(pServer, value); + } + } + + /// <summary> + /// 读取或设置是否标记静默时间(设置为 TRUE 时 DisconnectSilenceConnections() 和 GetSilencePeriod() 才有效,默认:FALSE) + /// </summary> + public bool MarkSilence + { + get + { + return Sdk.HP_Server_IsMarkSilence(pServer); + } + set + { + Sdk.HP_Server_SetMarkSilence(pServer, value); + } + } + + /// <summary> + /// 获取或设置数据发送策略 + /// </summary> + public SendPolicy SendPolicy + { + get + { + return Sdk.HP_Server_GetSendPolicy(pServer); + } + set + { + Sdk.HP_Server_SetSendPolicy(pServer, value); + } + } + + + /// <summary> + /// 获取或设置 OnSend 事件同步策略 + /// </summary> + public OnSendSyncPolicy OnSendSyncPolicy + { + get + { + return Sdk.HP_Server_GetOnSendSyncPolicy(pServer); + } + set + { + Sdk.HP_Server_SetOnSendSyncPolicy(pServer, value); + } + } + + /////////////////////////////////////////////////////////////////////////////////////// + + /// <summary> + /// 获取系统返回的错误码 + /// </summary> + public int SYSGetLastError() + { + return Sdk.SYS_GetLastError(); + } + + /// <summary> + /// 调用系统的 ::WSAGetLastError() 方法获取通信错误代码 + /// </summary> + public int SYSWSAGetLastError() + { + return Sdk.SYS_WSAGetLastError(); + } + + /// <summary> + /// 获取错误码 + /// </summary> + public SocketError ErrorCode + { + get + { + return Sdk.HP_Server_GetLastError(pServer); + } + } + + /// <summary> + /// 版本号 + /// </summary> + public string Version + { + get + { + return Sdk.GetHPSocketVersion(); + } + } + + /// <summary> + /// 获取错误信息 + /// </summary> + public string ErrorMessage + { + get + { + IntPtr ptr = Sdk.HP_Server_GetLastErrorDesc(pServer); + string desc = Marshal.PtrToStringAnsi(ptr); + return desc; + } + } + + + /////////////////////////////////////////////////////////////////////////////////////// + protected Sdk.OnPrepareListen _OnPrepareListen = null; + protected Sdk.OnAccept _OnAccept = null; + protected Sdk.OnReceive _OnReceive = null; + protected Sdk.OnSend _OnSend = null; + protected Sdk.OnClose _OnClose = null; + protected Sdk.OnShutdown _OnShutdown = null; + protected Sdk.OnHandShake _OnHandShake = null; + + protected virtual void SetCallback() + { + _OnPrepareListen = new Sdk.OnPrepareListen(SDK_OnPrepareListen); + _OnAccept = new Sdk.OnAccept(SDK_OnAccept); + _OnSend = new Sdk.OnSend(SDK_OnSend); + _OnReceive = new Sdk.OnReceive(SDK_OnReceive); + _OnClose = new Sdk.OnClose(SDK_OnClose); + _OnShutdown = new Sdk.OnShutdown(SDK_OnShutdown); + _OnHandShake = new Sdk.OnHandShake(SDK_OnHandShake); + + Sdk.HP_Set_FN_Server_OnPrepareListen(pListener, _OnPrepareListen); + Sdk.HP_Set_FN_Server_OnAccept(pListener, _OnAccept); + Sdk.HP_Set_FN_Server_OnSend(pListener, _OnSend); + Sdk.HP_Set_FN_Server_OnReceive(pListener, _OnReceive); + Sdk.HP_Set_FN_Server_OnClose(pListener, _OnClose); + Sdk.HP_Set_FN_Server_OnShutdown(pListener, _OnShutdown); + Sdk.HP_Set_FN_Server_OnHandShake(pListener, _OnHandShake); + } + + protected HandleResult SDK_OnHandShake(IntPtr pSender, IntPtr connId) + { + if (OnHandShake != null) + { + return OnHandShake(this, connId); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnPrepareListen(IntPtr pSender, IntPtr soListen) + { + if (OnPrepareListen != null) + { + return OnPrepareListen(this, soListen); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnAccept(IntPtr pSender, IntPtr connId, IntPtr pClient) + { + if (OnAccept != null) + { + return OnAccept(this, connId, pClient); + } + + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnSend(IntPtr pSender, IntPtr connId, IntPtr pData, int length) + { + if (OnSend != null) + { + byte[] bytes = new byte[length]; + Marshal.Copy(pData, bytes, 0, length); + return OnSend(this, connId, bytes); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnReceive(IntPtr pSender, IntPtr connId, IntPtr pData, int length) + { + if (OnPointerDataReceive != null) + { + return OnPointerDataReceive(this, connId, pData, length); + } + else if (OnReceive != null) + { + byte[] bytes = new byte[length]; + Marshal.Copy(pData, bytes, 0, length); + return OnReceive(this, connId, bytes); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnClose(IntPtr pSender, IntPtr connId, SocketOperation enOperation, int errorCode) + { + if (OnClose != null) + { + return OnClose(this, connId, enOperation, errorCode); + } + return HandleResult.Ignore; + } + + protected HandleResult SDK_OnShutdown(IntPtr pSender) + { + if (OnShutdown != null) + { + return OnShutdown(this); + } + return HandleResult.Ignore; + } + + + ///////////////////////////////////////////////////////////////////////// + + /// <summary> + /// 根据错误码返回错误信息 + /// </summary> + /// <param name="code"></param> + /// <returns></returns> + public string GetSocketErrorDesc(SocketError code) + { + IntPtr ptr = Sdk.HP_GetSocketErrorDesc(code); + string desc = Marshal.PtrToStringAnsi(ptr); + return desc; + } + + + /// <summary> + /// 调用系统的 setsockopt() + /// </summary> + /// <param name="sock"></param> + /// <param name="level"></param> + /// <param name="name"></param> + /// <param name="val"></param> + /// <param name="len"></param> + /// <returns></returns> + /// + public int SYS_SetSocketOption(IntPtr sock, int level, int name, IntPtr val, int len) + { + return Sdk.SYS_SetSocketOption(sock, level, name, val, len); + } + + /// <summary> + /// 调用系统的 getsockopt() + /// </summary> + /// <param name="sock"></param> + /// <param name="level"></param> + /// <param name="name"></param> + /// <param name="val"></param> + /// <param name="len"></param> + /// <returns></returns> + /// + public int SYSGetSocketOption(IntPtr sock, int level, int name, IntPtr val, ref int len) + { + return Sdk.SYS_GetSocketOption(sock, level, name, val, ref len); + } + /// <summary> + /// 调用系统的 ioctlsocket() + /// </summary> + /// <param name="sock"></param> + /// <param name="cmd"></param> + /// <param name="arg"></param> + /// <returns></returns> + /// + public int SYSIoctlSocket(IntPtr sock, long cmd, IntPtr arg) + { + return Sdk.SYS_IoctlSocket(sock, cmd, arg); + } + + /// <summary> + /// 调用系统的 ::WSAIoctl() + /// </summary> + /// <param name="sock"></param> + /// <param name="dwIoControlCode"></param> + /// <param name="lpvInBuffer"></param> + /// <param name="cbInBuffer"></param> + /// <param name="lpvOutBuffer"></param> + /// <param name="cbOutBuffer"></param> + /// <param name="lpcbBytesReturned"></param> + /// <returns></returns> + public int SYS_WSAIoctl(IntPtr sock, uint dwIoControlCode, IntPtr lpvInBuffer, uint cbInBuffer, + IntPtr lpvOutBuffer, uint cbOutBuffer, uint lpcbBytesReturned) + { + return Sdk.SYS_WSAIoctl(sock, dwIoControlCode, lpvInBuffer, cbInBuffer, + lpvOutBuffer, cbOutBuffer, lpcbBytesReturned); + } + + /// <summary> + /// 由结构体转换为byte数组 + /// </summary> + public byte[] StructureToByte<T>(T structure) + { + int size = Marshal.SizeOf(typeof(T)); + byte[] buffer = new byte[size]; + IntPtr bufferIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.StructureToPtr(structure, bufferIntPtr, true); + Marshal.Copy(bufferIntPtr, buffer, 0, size); + } + finally + { + Marshal.FreeHGlobal(bufferIntPtr); + } + return buffer; + } + + /// <summary> + /// 由byte数组转换为结构体 + /// </summary> + public T ByteToStructure<T>(byte[] dataBuffer) + { + object structure = null; + int size = Marshal.SizeOf(typeof(T)); + IntPtr allocIntPtr = Marshal.AllocHGlobal(size); + try + { + Marshal.Copy(dataBuffer, 0, allocIntPtr, size); + structure = Marshal.PtrToStructure(allocIntPtr, typeof(T)); + } + finally + { + Marshal.FreeHGlobal(allocIntPtr); + } + return (T)structure; + } + + /// <summary> + /// 对象序列化成byte[] + /// </summary> + /// <param name="obj"></param> + /// <returns></returns> + public byte[] ObjectToBytes(object obj) + { + using (MemoryStream ms = new MemoryStream()) + { + IFormatter formatter = new BinaryFormatter(); + formatter.Serialize(ms, obj); + return ms.GetBuffer(); + } + } + + /// <summary> + /// byte[]序列化成对象 + /// </summary> + /// <param name="Bytes"></param> + /// <returns></returns> + public object BytesToObject(byte[] bytes) + { + using (MemoryStream ms = new MemoryStream(bytes)) + { + IFormatter formatter = new BinaryFormatter(); + return formatter.Deserialize(ms); + } + } + /// <summary> + /// byte[]转结构体 + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="bytes"></param> + /// <returns></returns> + public T BytesToStruct<T>(byte[] bytes) + { + Type strcutType = typeof(T); + int size = Marshal.SizeOf(strcutType); + IntPtr buffer = Marshal.AllocHGlobal(size); + try + { + Marshal.Copy(bytes, 0, buffer, size); + return (T)Marshal.PtrToStructure(buffer, strcutType); + } + finally + { + Marshal.FreeHGlobal(buffer); + } + } + } +} diff --git a/PCRobot/PCWechat/Enterprise/WechatEnterpriseBase.cs b/PCRobot/PCWechat/Enterprise/WechatEnterpriseBase.cs new file mode 100644 index 0000000..a8efbf7 --- /dev/null +++ b/PCRobot/PCWechat/Enterprise/WechatEnterpriseBase.cs @@ -0,0 +1,398 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PCRobot.Entitys.Enterprise; +using PCRobot.Utils; + +namespace PCRobot.PCWechat.Enterprise +{ + /// <summary> + /// 企业微信基类 + /// </summary> + public abstract class WechatEnterpriseBase : WechatBase + { + /// <summary> + /// 是否初始化 + /// </summary> + internal static bool IsQYInstall { get; set; } + + public WechatEnterpriseBase(WechatUser User) : base(User) { } + + /// <summary> + /// 获取会话ID + /// </summary> + /// <param name="username"></param> + /// <returns></returns> + public string GetConversationId(string username) + { + var conversation_id = username; + if (!username.StartsWith("R:")) + conversation_id = $"S:{User.Wxid}_{username}"; + return conversation_id; + } + + #region 发送消息 + + /// <summary> + /// 发送目录 + /// </summary> + /// <param name="username">接收者的微信</param> + /// <param name="dirPath">目录路径</param> + /// <returns></returns> + public abstract void SendDirectory(string username, string dirPath); + + ///// <summary> + ///// 发送小程序 + ///// </summary> + ///// <param name="toUsername">接收者的账号</param> + ///// <param name="appUsername">小程序账号(xxxx@app)</param> + ///// <param name="appId">小程序id</param> + ///// <param name="appName">小程序名称</param> + ///// <param name="appicon">小程序图片地址</param> + ///// <param name="title">小程序标题</param> + ///// <param name="page_path">小程序指定的路径</param> + ///// <param name="file_id">cdn文件id</param> + ///// <param name="aes_key">cdnkey</param> + ///// <param name="md5">md5</param> + ///// <param name="size">大小</param> + ///// <exception cref="Exception"></exception> + //public abstract void SendProgramMessage(string username, string appUsername, string appId, string appName, + // string appicon, string title, string page_path); + + /// <summary> + /// 发送视频号 + /// </summary> + /// <param name="username">接收者的账号</param> + /// <param name="avatar">头像</param> + /// <param name="cover_url"></param> + /// <param name="desc">描述</param> + /// <param name="feed_type">类型</param> + /// <param name="nickname">标题</param> + /// <param name="thumb_url"></param> + /// <param name="url"></param> + /// <param name="extras">附加</param> + /// <exception cref="Exception"></exception> + public abstract void SendVideoHao(string username, string avatar, string cover_url, string desc, int feed_type, + string nickname, string thumb_url, string url, string extras); + + /// <summary> + /// 转让群主 + /// </summary> + public abstract void TransRoom(string username, string user_id); + + /// <summary> + /// 开启关闭群邀请确认 + /// </summary> + /// <param name="username"></param> + /// <param name="status">true开启,flase关闭</param> + public abstract void OnOffRoomInvite(string username, bool status); + + /// <summary> + /// 开启关闭修改群名 + /// </summary> + /// <param name="username"></param> + /// <param name="status">true开启,flase关闭</param> + public abstract void OnOffRoomModNick(string username, bool status); + + #endregion + + #region 群操作类 + + /// <summary> + /// 邀请用户进群 + /// </summary> + /// <param name="groupid">群ID</param> + /// <param name="usernames">邀请的用户账号集</param> + /// <returns></returns> + public abstract void InviteMemberToGroup(string groupid, string[] usernames); + + /// <summary> + /// 申请添加群成员为好友 + /// </summary> + /// <param name="groupid">用户所在群ID</param> + /// <param name="username">要加的用户账号(该用户一定要在群里)</param> + /// <param name="verify">验证消息</param> + /// <returns></returns> + public abstract void AddGroupMemberToFriend(string groupid, string username, string corp_id, string verify); + + #endregion + + #region 好友操作类 + + /// <summary> + /// 修改内/外部好友描述 + /// </summary> + /// <param name="username">要修改的user_id</param> + /// <param name="desc">好友描述信息</param> + /// <returns></returns> + public abstract void ModifyFriendDesc(string username, string desc); + + /// <summary> + /// 修改外部联系人手机号列表 + /// </summary> + /// <param name="username">要修改的user_id</param> + /// <param name="phone_list">手机号列表,最多5个</param> + /// <returns></returns> + public abstract void ModifyFriendPhone(string username, string[] phone_list); + + /// <summary> + /// 修改外部联系人公司名称 + /// </summary> + /// <param name="username">要修改的user_id</param> + /// <param name="company">公司名称</param> + /// <returns></returns> + public abstract void ModifyExternalFriendCompanyNick(string username, string company); + + /// <summary> + /// 通过手机号查询微信信息 + /// </summary> + /// <param name="search">搜索的内容</param> + /// <returns></returns> + public abstract Task<FriendInfoHandlerEnterprise> SearchContactMobile(string search); + + /// <summary> + /// 添加搜索到的微信用户 + /// </summary> + /// <param name="username">通过查询获取到的账号</param> + /// <param name="openid">搜索到的openid</param> + /// <param name="wx_ticket">搜索到的wx_ticket</param> + /// <param name="verify">验证消息</param> + /// <returns></returns> + public abstract void AddRoutineSearchContact(string username, string openid, string wx_ticket, string verify); + + /// <summary> + /// 添加搜索到的企业用户 + /// </summary> + /// <param name="username">通过查询获取到的账号</param> + /// <param name="corp_id">公司id</param> + /// <param name="verify">验证信息</param> + /// <exception cref="Exception"></exception> + public abstract void AddEnterpriseSearchContact(string username, string corp_id, string verify); + + /// <summary> + /// 添加名片为联系人 + /// </summary> + /// <param name="username"></param> + /// <param name="corp_id"></param> + /// <param name="from_user_id"></param> + /// <param name="verify"></param> + /// <exception cref="Exception"></exception> + public abstract void AddCardFriendContact(string username, string corp_id, string from_user_id, string verify); + + /// <summary> + /// 添加删除的联系人 + /// </summary> + /// <param name="username"></param> + /// <param name="corp_id"></param> + /// <param name="verify"></param> + /// <exception cref="Exception"></exception> + public abstract void AddDelFriendContact(string username, string corp_id, string verify); + + ///// <summary> + ///// 删除好友 + ///// </summary> + ///// <param name="username"></param> + ///// <param name="corp_id"></param> + ///// <exception cref="Exception"></exception> + //public abstract void DeleteFriend(string username, string corp_id); + + ///// <summary> + ///// 接受好友申请 + ///// </summary> + ///// <param name="username">用户账号</param> + ///// <param name="corp_id">公司id</param> + ///// <exception cref="Exception"></exception> + //public abstract Task<bool> AcceptFriend(string username, string corp_id); + + /// <summary> + /// 创建空外部群 + /// </summary> + /// <param name="usernames"></param> + /// <exception cref="Exception"></exception> + public abstract Task<CreateGroupInfo> CreateExternalGroup(); + + #endregion + + #region 基础信息类 + + ///// <summary> + ///// 获取内部好友类表 + ///// </summary> + ///// <returns></returns> + //public abstract Task<Dictionary<string, FriendBase>> GetInnerFirends(); + + /// <summary> + /// 获取外部好友列表 + /// </summary> + /// <returns></returns> + public abstract Task<Dictionary<string, WorkFriendInfo>> GetExternalFirends(); + + ///// <summary> + ///// 获取自己的二维码 + ///// </summary> + ///// <returns></returns> + ///// <exception cref="Exception"></exception> + //public abstract Task<QrImageInfo> GetOwnQrImage(); + + /// <summary> + /// 刷新登录二维码 + /// </summary> + /// <exception cref="Exception"></exception> + public abstract void FlushLoginQrImage(); + + /// <summary> + /// 解散群 + /// </summary> + /// <param name="GroupId">群号</param> + /// <exception cref="Exception"></exception> + public abstract void DissolveGroup(string GroupId); + + /// <summary> + /// Cdn下载 + /// </summary> + /// <param name="url">回复中的cdn地址</param> + /// <param name="auth_key">回复中的auth_key</param> + /// <param name="aes_key">回复中的aes_key</param> + /// <param name="size">回复中的size</param> + /// <param name="save_path">保存文件完整路径</param> + /// <exception cref="Exception"></exception> + public abstract Task<string> CdnDown(string url, string auth_key, string aes_key, int size, + FileSuffixType fileSuffixType); + + /// <summary> + /// Cdn下载 + /// </summary> + /// <param name="url">回复中的cdn地址</param> + /// <param name="auth_key">回复中的auth_key</param> + /// <param name="aes_key">回复中的aes_key</param> + /// <param name="size">回复中的size</param> + /// <param name="fileName">文件名带后缀</param> + /// <returns></returns> + /// <exception cref="Exception"></exception> + public abstract Task<string> CdnDown(string url, string auth_key, string aes_key, int size, string fileName); + + /// <summary> + /// C2cCdn下载 + /// </summary> + /// <param name="aes_key">回复中的aes_key</param> + /// <param name="file_id">回复中的file_id</param> + /// <param name="file_size">回复中的file_size</param> + /// <param name="file_type">回复中的file_type</param> + /// <param name="save_path">保存文件完整路径</param> + /// <exception cref="Exception"></exception> + public abstract Task<string> C2cCdnDown(string aes_key, string file_id, int file_size, QyCdnFileType file_type, + FileSuffixType fileSuffixType); + + /// <summary> + /// BigCdn下载 + /// </summary> + /// <param name="file_path"></param> + /// <param name="file_type"></param> + /// <returns></returns> + /// <exception cref="Exception"></exception> + public abstract Task<string> BigCdnDown(string file_path, string file_type); + + /// <summary> + /// 获取Cdn通过文件上传 + /// </summary> + /// <param name="file_path">文件路径</param> + /// <param name="file_type">文件类型</param> + /// <returns></returns> + /// <exception cref="Exception"></exception> + public abstract Task<FileC2cCdnInfo> GetCdnByUpLoadFile(string file_path, int file_type); + + #endregion + + public string FindNick(string wxid) + { + try + { + if (string.IsNullOrWhiteSpace(wxid)) return string.Empty; + + if (wxid.IsQun())//为群账号,就获取群昵称 + { + if (!User.WorkGroups.ContainsKey(wxid)) + { + var ggi = this.GetGroupInfos().Result;//获取群信息 + if (ggi != null && ggi.Count != 0) + { + if (ggi.ContainsKey(wxid)) + return (ggi[wxid] as WorkGroupInfo).GroupNick; + } + } + if (User.WorkGroups.ContainsKey(wxid)) + { + if (string.IsNullOrWhiteSpace(User.WorkGroups[wxid].GroupNick)) + { + var ggi = this.GetGroupInfos().Result;//获取群信息 + if (ggi != null && ggi.Count != 0) + { + if (ggi.ContainsKey(wxid)) + return (ggi[wxid] as WorkGroupInfo).GroupNick; + } + } + return User.WorkGroups[wxid].GroupNick; + } + } + else + { + if (!User.Friends.ContainsKey(wxid)) + { + var friend = GetFriendInfo(wxid).Result; + if (friend != null) + return (friend as WorkFriendInfo).username; + } + if (User.WorkFriends.ContainsKey(wxid)) + return User.WorkFriends[wxid].username; + } + } + catch (Exception ex) + { } + return string.Empty; + } + + /// <summary> + /// 获取群成员昵称 + /// </summary> + /// <param name="group">群号</param> + /// <param name="wxid">需要查找的用户账号</param> + /// <returns></returns> + public string FindNick(string group, string wxid) + { + try + { + if (string.IsNullOrWhiteSpace(wxid)) return string.Empty; + + if (User.WorkFriends.ContainsKey(wxid))//如果好友列表中存在就直接读取 + return User.WorkFriends[wxid].nickname; + else + { + if (string.IsNullOrWhiteSpace(group)) return string.Empty; + + if (!User.WorkGroups.ContainsKey(group)) + { + var gInfo = this.GetGroupMemberInfo(group).Result; + if (gInfo != null) + return (gInfo as WorkGroupInfo).GroupNick; + } + if (User.WorkGroups.ContainsKey(group)) + { + var friendDic = User.WorkGroups[group].friends; + if (friendDic != null) + { + var ftmp = friendDic.FirstOrDefault(f => f.user_id == wxid); + if (ftmp != null) + return ftmp.nickname; + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + } +} diff --git a/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY.cs b/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY.cs new file mode 100644 index 0000000..9f11f43 --- /dev/null +++ b/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY.cs @@ -0,0 +1,336 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using CsharpHttpHelper; +using Newtonsoft.Json; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Utils; + +namespace PCRobot.PCWechat.Enterprise +{ + public partial class Wechat_Xiaoxie_QY : WechatEnterpriseBase + { + + public Wechat_Xiaoxie_QY(WechatUser User) : base(User) { } + + #region 注入等操作 + public delegate void AcceptCallbackFunc(uint dwClientId); + public delegate void RecvCallbackFunc(uint dwClientId, IntPtr intPtr, uint dwSize); + public delegate void CloseCallbackFunc(uint dwClientId); + + private static AcceptCallbackFunc m_AcceptCallbackFunc; + private static RecvCallbackFunc m_RecvCallbackFunc; + private static CloseCallbackFunc m_CloseCallbackFunc; + + // 引入DLL导出函数 + //[DllImport("Bin\\WeChatServer_QY.dll")] + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool InitWxWorkSocket(AcceptCallbackFunc acceptCallback, + RecvCallbackFunc recvCallback, CloseCallbackFunc closeCallback); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWork(byte[] strDllPath, byte[] strWxWorkExePath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWorkMultiOpen(byte[] strDllPath, byte[] strWxWorkExePath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool SendWxWorkData(uint dwClienId, byte[] strJsonData); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool DestroyWxWork(); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWorkPid(int dwPid, byte[] strDllPath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool UseUtf8(); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool GetUserWxWorkVersion(StringBuilder v); + + [DllImport("Bin\\WxWorkLoader.dll", EntryPoint = "SendWxWorkData")] + public static extern bool _SendWxWorkData(uint dwClienId, byte[] strJsonData); + + public bool SendWxWorkData(uint dwClienId, string strJsonData) + { + var ss = User.DwClientId; + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("_调试发送_", $"{dwClienId} -> {strJsonData} - {User != null} - 微信id:{User?.Wxid}"); + + if (User != null && !string.IsNullOrEmpty(User.Wxid)) + { + var json = HttpExtend.JsonToDictionary(strJsonData); + var type = json["type"].ToString(); + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试发送@转换失败", $"{dwClienId} -> type:{type}"); + return false; + } + switch (msgType) + { + //截取发送消息 - 为是否是辅助输入提供判断 + + case MsgType.MT_SEND_TEXT_MSG:// 发送文本消息 + case MsgType.MT_SEND_IMAGE_MSG:// 发送图片消息 + case MsgType.MT_SEND_FILE_MSG:// 发送文件消息 + case MsgType.MT_SEND_FOLDER_MSG:// 发送目录消息 + case MsgType.MT_SEND_LINK_MSG:// 发送链接消息 + //case MsgType.MT_SEND_PERSON_CARD_MSG:// 发送个人名片 + case MsgType.MT_SEND_VIDEO_MSG:// 发送视频 + { + json = json["data"] as Dictionary<string, object>; + + string conversation_id = json["conversation_id"].ToString(); + var to_wxid = conversation_id; + if (conversation_id.StartsWith("S:"))//私人消息处理一下,群消息不用管 + { + to_wxid = conversation_id.Replace($"S:{User.Wxid}_", ""); + } + string message = string.Empty; + if (json.ContainsKey("content")) message = json["content"].ToString(); + else if (json.ContainsKey("card_wxid")) message = json["card_wxid"].ToString(); + else if (json.ContainsKey("file")) message = json["file"].ToString(); + //else if (json.ContainsKey("user_id")) message = json["user_id"].ToString(); + if (!string.IsNullOrEmpty(message)) + { + LogHelper.GetSingleObj().Debug("", "发送@@@@@@@@@@@@@@@@: " + message + @" +"); + + Common.SetCache(User.Wxid, to_wxid, message, 60 * 8); + } + } + break; + } + } + return _SendWxWorkData(dwClienId, Encoding.UTF8.GetBytes(strJsonData)); + } + + static string DllPath = HttpExtend.MapFile($"WxWorkHelper_{Version}.dll", "Bin"); + + private const string Version = "4.0.2.6026"; + private const string PcMd5 = "E77637926604364C4AD65625032B2E8A"; + + + public static void Install() + { + if (IsQYInstall) return; + try + { + m_AcceptCallbackFunc = WxAcceptCallback; + m_RecvCallbackFunc = WxRecvCallback; + m_CloseCallbackFunc = WxCloseCallback; + + UseUtf8(); + // 初始化Callback + InitWxWorkSocket(m_AcceptCallbackFunc, m_RecvCallbackFunc, m_CloseCallbackFunc); + + StringBuilder sb = new StringBuilder(); + + var path1 = HttpExtend.MapPath("WXWork"); + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + + InitPc(); + } + catch (Exception) + { + + } + finally + { + IsQYInstall = true; + } + } + + /// <summary> + /// 杀死注入 pc + /// </summary> + /// <param name="isInject"></param> + private static void KillPc(bool isInject = false) + { + Process[] MyProcesses = Process.GetProcesses(); + + var path1 = HttpExtend.MapPath("WXWork"); + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == "WXWORK" && MyProcess.MainModule.FileName.StartsWith(path1)) + { + try + { + //判断微信版本 + if (MyProcess.MainModule.FileName.StartsWith(path2)) + { + var id = MyProcess.Id; + if (isInject) + { + var result = Task<bool>.Factory.StartNew(delegate + { + try + { + var WechatWinFile = CsharpHttpHelper.HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + var md5 = Common.GetMD5Hash(WechatWinFile).ToUpper(); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + return false; + } + else + { + LogHelper.GetSingleObj().Info("系统", $"开始企业注入进程:{id}..."); + var uin = InjectWxWorkPid(id, Encoding.UTF8.GetBytes(DllPath)); + LogHelper.GetSingleObj().Info("系统", $"注入企业成功:{id},句柄ID:{uin}"); + return true; + } + } + catch (Exception) + { } + return false; + }).Wait(20000); + if (!result) + { + try + { + LogHelper.GetSingleObj().Info("系统cc", "杀死企业进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + else + { + try + { + LogHelper.GetSingleObj().Info("主动dd", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + } + catch (Exception) + { } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } + + private static void InitPc() + { + KillPc(); + } + + private static string RemoteCache = "get_login_code_cache_workwechat"; + + /// <summary> + /// 等待登录结果 + /// </summary> + public static Dictionary<string, string> WaitLoginResult = new Dictionary<string, string>(); + + /// <summary> + /// 远程登录微信 + /// </summary> + public static List<RemoteLoginCode> RemoteLoginCodes = new List<RemoteLoginCode>(); + + /// <summary> + /// pc微信登录二维码 + /// </summary> + /// <param name="ServerMsgID"></param> + public static void LoginQrcode(string ServerMsgID) + { + try + { + RemoteLoginCode result = null; + try + { + string downloadsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + var wxConfig = HttpExtend.MapFile(@"Config.cfg", downloadsPath + @"\WXWork\Global"); + if (File.Exists(wxConfig)) + { + try + { + File.Delete(wxConfig); + } + catch (Exception) + { } + StartWechat(true); + } + } + catch (Exception ex) + { + result = new RemoteLoginCode() { pid = -1, rType = RobotType.客户端企业微信, b64Md5 = ex.Message }; + } + + if (result == null) + { + result = Task.Factory.StartNew<RemoteLoginCode>(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[RemoteCache]; + if (item != null) + { + cache.Remove(RemoteCache); + var r = item as RemoteLoginCode; + return r; + } + } while (awaitTime >= DateTime.Now); + return null; + }).Result; + } + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = string.Empty; + msg.RobotUsernick = string.Empty; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvLoginCode_workWeChat; + msg.Data = result == null ? string.Empty : JsonConvert.SerializeObject(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// <summary> + /// 卸载安装 + /// </summary> + public static void UnInstall() + { + try + { + //DestroyWxWork(); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".."); + } + } + #endregion + } +} diff --git a/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Analysis.cs b/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Analysis.cs new file mode 100644 index 0000000..552afbc --- /dev/null +++ b/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Analysis.cs @@ -0,0 +1,2190 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Entitys; +using PCRobot.Entitys.Enterprise; +using PCRobot.Pack; +using PCRobot.Utils; +using System.Collections.Concurrent; + +namespace PCRobot.PCWechat.Enterprise +{ + public partial class Wechat_Xiaoxie_QY + { + private static Dictionary<uint, int> MT_APP_READY_MSG_BIND = new Dictionary<uint, int>(); + + /// <summary> + /// 历史接收到的消息 + /// </summary> + private static Dictionary<string, DateTime> HistMsg = new Dictionary<string, DateTime>(); + + private static ConcurrentDictionary<string, string> ServerIdCache = new ConcurrentDictionary<string, string>(); + + // 接收消息回调 + private static void WxRecvCallback(uint _dwClient, IntPtr intPtr, uint dwSize) + { + try + { + byte[] body = new byte[dwSize]; + Marshal.Copy(intPtr, body, 0, body.Length); + var recvData = Encoding.UTF8.GetString(body).Replace("\0", "").Trim();//再转成UTF8 + + var dwClientid = _dwClient; + + var msgMd5 = HttpExtend.GetMD5String(recvData); + if (HistMsg.ContainsKey(msgMd5)) + { + LogHelper.GetSingleObj().Error("调试企业收到文本消息", $"发现重复消息 => {dwClientid} -> {recvData}\r\n\r\n"); + return; + } + + HistMsg[msgMd5] = DateTime.Now; + if (HistMsg.Count > 2000) + { + var keys = HistMsg.Where(f => f.Value < DateTime.Now.AddMinutes(-10)).Select(f => f.Key).ToList(); + if (keys.Count != 0) + { + for (int i = 0; i < keys.Count; i++) + { + try + { + HistMsg.Remove(keys[i]); + } + catch (Exception e) + { } + } + } + } + + + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Info("调试企业收到文本消息", $"{dwClientid} -> {recvData}\r\n\r\n"); + + + //var method = new Action(delegate () + Task.Factory.StartNew(delegate () + { + try + { + //Console.WriteLine("企业收到消息:" + recvData); + + var jObj = JObject.Parse(recvData); + if (jObj == null) return; + if (!jObj.ContainsKey("type") || jObj["type"] == null) + return; + + var data = jObj["data"]; + var type = jObj["type"].ToString(); + + var serverId = data["server_id"]?.ToString(); + if (string.IsNullOrWhiteSpace(serverId) == false) + { + if (ServerIdCache.TryGetValue(serverId, out var serverIdOut)) + { + return; + } + + if (ServerIdCache.Count > 10000) + { + ServerIdCache = new ConcurrentDictionary<string, string>(); + } + + ServerIdCache.TryAdd(serverId, serverId); + } + + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return; + + + //获取机器人对象 + WechatUser user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + + //Console.WriteLine($"dwClientid = {dwClientid}"); + switch (msgType) + { + case MsgType.MT_APP_READY_MSG: + MT_APP_READY_MSG_BIND[dwClientid] = int.Parse(data["pid"].ToString()); + break; + case MsgType.MT_PARAMS_ERROR_MSG: + { } + break; + case MsgType.MT_USER_LOGIN://登陆消息 + { + var wxid = data["user_id"].ToString(); + user = WechatClient.GetUser(wxid, dwClientid, WechatType.Xiaoxie_QY); + user.Nickname = data["username"].ToString(); + user.HeaderUrl = data["avatar"].ToString(); + //user.DBFile = data["wx_user_dir"].ToString(); + user.Pid = MT_APP_READY_MSG_BIND.ContainsKey(dwClientid) ? MT_APP_READY_MSG_BIND[dwClientid] : 0; //uint.Parse(data["pid"].ToString()); + user.Phone = data["mobile"].ToString(); + user.Uin = wxid; + WechatClient.OnRefUserEvent(user, WaitLoginResult); + } + break; + case MsgType.MT_USER_LOGOUT: + { + var wxid = data["user_id"].ToString(); + user = WechatClient.Users.FirstOrDefault(f => f.Key == wxid).Value; + if (user != null) + { + LogHelper.GetSingleObj().Info("系统", $"LogOut_QY事件退出,Uin:{user.Uin},微信:{user.Nickname}({wxid})"); + WechatClient.RemoveUser(user); + } + } + break; + case MsgType.MT_LOGIN_QRCODE_MSG: + { + //{"data":{"file":"C:\\Users\\秒单客006\\Documents\\WXWork\\Global\\Image\\089d9de9-cc40-458a-af4a-b39a04e2f95f.jpg"},"type":11028} + if (data["file"] == null) return; + if (MT_APP_READY_MSG_BIND.ContainsKey(dwClientid)) + { + var file = data["file"].ToString(); + + if (File.Exists(file)) + { + var cfBase64 = Common.ConvertImageToBase64(Image.FromFile(file)); + + var codeInfo = new RemoteLoginCode() { pid = MT_APP_READY_MSG_BIND[dwClientid], cImgB64 = cfBase64, b64Md5 = HttpHelper.ToMD5(cfBase64), rType = RobotType.客户端企业微信, t = HttpExtend.GetTimeStamp(DateTime.Now) }; + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[RemoteCache]; + cache.Insert(RemoteCache, codeInfo, null, DateTime.Now.AddSeconds(3), Cache.NoSlidingExpiration); + + RemoteLoginCodes.Add(codeInfo); + } + } + } + break; + case MsgType.MT_GET_OWNER_INFO_MSG:// 获取自己信息 + { + #region 数据结构 + /* + { + "data": { + "account": "xxxxx@xxx.onexmail.com", // 帐号 + "acctid": "xxxxx", // acctid + "avatar": "http://wework.qpic.cn/bizmail/xxxDM808qnyFVjQ/0", // 头像 + "corp_id": "1970325032041886", // 公司id + "corp_name": "xxxxxxxxx有限公司", // 公司全称 + "corp_short_name": "xxxxx", // 公司简称 + "email": "xxxxx@qq.com", // 邮箱 + "job_name": "总经理", // 职位 + "mobile": "137xxxxxxxxx", // 手机号 + "nickname": "小邪212", // 昵称 + "position": "总经理", // 职位 + "sex": 2, // 性别 0 未知,1男,2女 + "user_id": "1688xxxx353xxxx", // 用户id + "username": "小邪" // 名称 + }, + "type": 11035 + } + */ + #endregion + if (data == null || user == null) return; + + var f = new WorkFriendInfo(); + f.avatar = data["avatar"]?.ToString(); + //f.conversation_id = data["conversation_id"]?.ToString(); + //f.desc = item["desc"]?.ToString(); + f.nickname = data["nickname"]?.ToString(); + f.position = data["position"]?.ToString(); + f.realname = data["username"]?.ToString(); + f.remark = data["username"]?.ToString(); + f.sex = data["sex"].ToObject<int>(); + f.user_id = data["user_id"].ToString(); + f.username = data["username"].ToString(); + + user.WorkFriends[f.user_id] = f; + + } + break; + case MsgType.MT_GET_INNER_USERS_MSG:// 获取内部联系人列表 + { + } + break; + case MsgType.MT_GET_EXTERNAL_USERS_MSG:// 获取外部联系列表 + { + #region 外部联系列表 + + #region 消息样式 + //{"data":{"page_num":1,"page_size":10000,"total":44,"total_page":1,"user_list":[{"acctid":"AoQi","add_time":1594358458,"avatar":"https://wework.qpic.cn/wwhead/duc2TvpEgST9hicuyypLEKMFMfDnH4KeYskpFLBx46N4YMPdu9ibu6uvic9tRMx1O5oc1e94LvWHZI/0","conversation_id":"S:1688853884018611_1688853956558440","corp_id":"1970325130121266","mobile":"","nickname":"A46「猫七」【置顶常用】","position":"","realname":"**新","remark":"","sex":2,"unionid":"ozynqspv4YiVjaa04jYgRulxWfQ8","user_id":"1688853884018611","username":"A46🐱「猫七」【置顶常用】"},{"acctid":"","add_time":1588747919,"avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM4pFj4ic9BTuoseZNnibY90lvKkoAFichAcjjao0WqvzvHnQ/0","conversation_id":"S:1688853956558440_7881301062943857","corp_id":"1970325134026788","mobile":"","nickname":"","position":"","realname":"","remark":"查优惠小助手(梦瑶)","sex":2,"unionid":"ozynqsjIzu8BxAu_dcoFLWuFSVWA","user_id":"7881301062943857","username":"A查优惠小助手-梦瑶"},{"acctid":"","add_time":1588745188,"avatar":"http://wx.qlogo.cn/mmhead/GtsibMna7cCkYQ3fJffrweyEvlODDOH1SCzOtwflnBsc/0","conversation_id":"S:1688853956558440_7881301162944044","corp_id":"1970325134026788","mobile":"","nickname":"","position":"","realname":"","remark":"查优惠小助手(抹茶)","sex":2,"unionid":"ozynqsjMTV4VYwLqjcDcfcH5VFsI","user_id":"7881301162944044","username":"老妖助理15"}]},"type":11037} + #endregion + + if (data == null || user == null) + return; + + var _type = RobotIsRunType.获取好友列表; + if (user.IsGetDic.ContainsKey(_type)) + { + if (user.IsGetDic[_type]) + return; + } + + try + { + user.IsGetDic[_type] = true; + + var jArr = (JArray)data["user_list"]; + for (int i = 0; i < jArr.Count; i++) + { + var item = jArr[i]; + var username = item["user_id"]?.ToString(); + //if (username.IsGongZhongHao()) continue; + + WorkFriendInfo f = new WorkFriendInfo(); + + f.acctid = item["acctid"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.conversation_id = item["conversation_id"]?.ToString(); + f.corp_id = item["corp_id"]?.ToString(); + f.mobile = item["mobile"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.position = item["position"]?.ToString(); + f.realname = item["realname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = item["sex"].ToObject<int>(); + f.user_id = username; + f.username = item["username"]?.ToString(); + + user.WorkFriends[f.user_id] = f; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业获取内部联系人列表", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetDic.Remove(_type); + } + #endregion + } + break; + case MsgType.MT_GET_ROOMS_MSG:// 获取群聊列表 + { + #region 数据结构 + //{"data":{"page_num":1,"page_size":100000,"room_list":[{"conversation_id":"R:10696051756073403","create_time":1587126543,"create_user_id":"7881302509911391","is_admin":0,"is_creator":0,"is_external":1,"nickname":"软件反馈群","total":21},{"conversation_id":"R:238567000711635","create_time":1644470134,"create_user_id":"1688850065257778","is_admin":0,"is_creator":0,"is_external":0,"nickname":"张谊玉、洪荒老道、祁举兵","total":5},{"conversation_id":"R:1970325073072411","create_time":1559292789,"create_user_id":"1688853956450720","is_admin":0,"is_creator":0,"is_external":0,"nickname":"成都秒单客网络科技有限公司","total":20},{"conversation_id":"R:95666354828251","create_time":1644746098,"create_user_id":"1688853956558440","is_admin":0,"is_creator":1,"is_external":0,"nickname":"..............................................","total":4},{"conversation_id":"R:10774828428256418","create_time":1644804316,"create_user_id":"1688853956558440","is_admin":0,"is_creator":1,"is_external":1,"nickname":",,,,,,,,,,","total":3},{"conversation_id":"R:289059290","create_time":1618382594,"create_user_id":"1688853956558440","is_admin":0,"is_creator":1,"is_external":0,"nickname":"转发综合群","total":4},{"conversation_id":"R:10757092148832341","create_time":1648025176,"create_user_id":"1688853956558440","is_admin":0,"is_creator":1,"is_external":1,"nickname":"企业外部群","total":41}],"total":7,"total_page":1},"type":11038} + + #endregion + + if (data == null || user == null) + return; + + var _type = RobotIsRunType.获取群列表; + if (user.IsGetDic.ContainsKey(_type)) + { + if (user.IsGetDic[_type]) + return; + } + + try + { + user.IsGetDic[_type] = true; + + var member_list = (JArray)data["room_list"]; + if (member_list == null) + return; + + var hook = WechatClient.GetApi(user); + + for (int i = 0; i < member_list.Count; i++) + { + //{"conversation_id":"R:10696051756073403","create_time":1587126543,"create_user_id":"7881302509911391","is_admin":0,"is_creator":0,"is_external":1,"nickname":"软件反馈群","total":21} + var item = member_list[i]; + + var f = new WorkFriendInfo(); + + f.avatar = string.Empty; + f.user_id = item["conversation_id"]?.ToString(); + f.manager_wxid = item["create_user_id"]?.ToString(); + f.is_manager = item["is_admin"].ToObject<int>(); + f.nickname = item["nickname"]?.ToString(); + f.username = item["nickname"]?.ToString(); + f.remark = item["nickname"]?.ToString(); + + user.WorkFriends[f.user_id] = f; + + var g = new WorkGroupInfo(); + g.friends = new List<WorkFriendInfo>(); + g.GroupNick = f.nickname; + g.conversation_id = f.user_id; + g.total = 0; + user.WorkGroups[f.user_id] = g; + + var groupMember = hook.GetGroupMemberInfo(f.user_id).Result; + if (groupMember != null) + { + var workGroupInfo = (groupMember as WorkGroupInfo); + if (workGroupInfo != null) + { + g.friends = workGroupInfo.friends; + g.total = workGroupInfo.total; + } + } + else //获取失败就赋值简单的 + { + var memberJarr = (JArray)item["member_list"]; + for (int o = 0; o < memberJarr.Count; o++) + { + var username = memberJarr[o].ToString(); + var ftmp = g.friends.FirstOrDefault(z => z.user_id == username); + if (ftmp == null) + g.friends.Add(new WorkFriendInfo() { user_id = username }); + } + } + user.WorkGroups[f.user_id] = g; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业微信解析群列表", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetDic.Remove(_type); + } + } + break; + case MsgType.MT_GET_USER_DETAIL_MSG:// 获取用户详细信息 + { + #region 数据结构 + //{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","corp_id":"1970325134026788","desc":"","external_job":"","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":"18"} + #endregion + + if (user == null || data == null) return; + //有时候接收到的数据为一下情况 + //{"data":{"user_id":"7881302484994318"},"type":11039} + + var username = data["user_id"]?.ToString(); + + if (user.IsGetContactDic.ContainsKey(username) && user.IsGetContactDic[username]) + return; + try + { + try + { + user.IsGetContactDic[username] = true; + } + catch (Exception) + { + } + + var f = new WorkFriendInfo(); + f.corp_id = data["corp_id"]?.ToString(); + f.mobile = data["mobile"]?.ToString(); + f.acctid = data["acctid"].ToString(); + f.avatar = data["avatar"]?.ToString(); + f.conversation_id = data["conversation_id"]?.ToString(); + f.desc = data["desc"]?.ToString(); + f.nickname = data["nickname"]?.ToString(); + f.position = data["position"]?.ToString(); + f.realname = data["realname"]?.ToString(); + f.remark = data["remark"]?.ToString(); + f.sex = data["sex"].ToObject<int>(); + f.user_id = data["user_id"]?.ToString(); + f.username = data["username"]?.ToString(); + + user.WorkFriends[f.user_id] = f; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业微信解析用户详细信息", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(username); + } + } + break; + case MsgType.MT_GET_ROOM_MEMBERS_MSG:// 获取群成员列表 + { + #region 数据样式 + /* + {"data":{"conversation_id":"R:10696051756073403","member_list":[{"acctid":"WuJiaHua","avatar":"http://wework.qpic.cn/bizmail/FxrNrXCeEh8Kwv4ia3iahWCbkR7Y0VqoBniaJ5hrlKggVaibBXIxmOBb8A/0","corp_id":"1970325073072411","invite_user_id":"7881302509911391","nickname":"洪荒老道","position":"","realname":"吴嘉华","remark":"","sex":1,"user_id":"1688853956558440","username":"洪荒老道"},{"acctid":"YuQi","avatar":"http://wework.qpic.cn/bizmail/PN2IeoKDkmhqqH0nlh2Lm6TVZRNAtgLPyg2ick4sPBEB0kzP0hDmQmg/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"秒单客_小鱼","position":"","realname":"虞祁","remark":"","sex":2,"user_id":"1688853956590186","username":"小鱼"},{"acctid":"ZhangYiYu","avatar":"http://wework.qpic.cn/bizmail/Yfk60WuPLgEuo6ViauAdDeqqtlOuH8EYEh0K0Cg9KGicYHGyg9gw1o2w/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"小张","position":"","realname":"张谊玉","remark":"","sex":0,"user_id":"1688853956590187","username":"张谊玉"},{"acctid":"XiaoZhangTongXue","avatar":"https://wework.qpic.cn/wwhead/duc2TvpEgST9hicuyypLEKE4HsVWEQswCosv5s4Je9eyrmicu2cvscczGLmSmwQBEzPaZO82TA7IY/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"秒单客-小张","position":"","realname":"张谊玉","remark":"","sex":1,"user_id":"1688853956642143","username":"张谊玉"},{"acctid":"WenQi","avatar":"http://wework.qpic.cn/bizmail/rftUYt0pUSNM9UGLVhJT8SADPRo7UUwEXc1TibElDW2b8OBbrUAibN2w/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"","position":"","realname":"文奇","remark":"","sex":1,"user_id":"1688853956644076","username":"文奇"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/U8XnjHx15KhdibgkJ49XtGJ44Y3bH7VkpMTy2UhJicrOs/0","corp_id":"1970325134026788","invite_user_id":"7881302509911391","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881299792900727","username":"小锋"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/ETNocE50L3oEX3eSEr47qkodhRfgpya2ZYt3D08Bh6k/0","corp_id":"1970325134026788","invite_user_id":"7881299792900727","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881299980969589","username":"嘿"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/USH8Nb3Hz5TauZmclE9wV7qAOMo3xTf4mPG8qHWicKjfgTExgLX8MHw/0","corp_id":"1970325134026788","invite_user_id":"7881301450899709","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881300660017681","username":"Suki_cc"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaELHEV52PNTeBgDTw7WZw5zaXqC3Dx8NlxzoWbZodIV6nA/0","corp_id":"1970325134026788","invite_user_id":"7881303073899390","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301052912667","username":"管家助理"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/le1D2uwOTUNrTr97NDfcJfBibsBcv6D95v5G8WaF5pWjRxsgo8AgOqQ/0","corp_id":"1970325134026788","invite_user_id":"7881303073899390","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301334966174","username":"M."},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM58vIBW7iaDy1L2LnWp6bFQaZageAQ1dUAQbBhtbFEia9XQ/0","corp_id":"1970325134026788","invite_user_id":"7881302509911391","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881301450899709","username":"幸运的小蔡"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/9qclib0CZpLj64d8S0eVZCgJhsF1V0wMicHrM3LRia1bq4/0","corp_id":"1970325134026788","invite_user_id":"7881301450899709","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881301996898661","username":"阿羣"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaEJUq43owiazPpKBwI044FZ6GbmOgiaHlt9TWWC7m7ajYnQQ/0","corp_id":"1970325134026788","invite_user_id":"7881302509911391","nickname":"","position":"","realname":"","remark":"阿威?? ?? ?? ?? ??","sex":1,"user_id":"7881302027905870","username":"阿威?? ?? ?? ?? ??"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM6CiaVp63VVTIRySkxia2KSGQ6hrYAvAkkjoMpl4wFjyhIA/0","corp_id":"1970325134026788","invite_user_id":"7881302509911391","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881302509911391","username":"千年老妖"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaEIkxibLqBfcon3IAic6a4DFICQIR7EdHM0mAuHPUXlcl5iag/0","corp_id":"1970325134026788","invite_user_id":"7881301450899709","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881302973987188","username":"chan??baek"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/aUwBqqfR4L9uicc3e31iafC57QBG8BjVwPhmNKE77LdKo/0","corp_id":"1970325134026788","invite_user_id":"7881301450899709","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881303073899390","username":"小明"}]},"type":11040} + */ + #endregion + + if (user == null || data == null) return; + + var conversation_id = data["conversation_id"].ToString(); + if (user.IsGetContactDic.ContainsKey(conversation_id) && user.IsGetContactDic[conversation_id]) + return; + try + { + user.IsGetContactDic[conversation_id] = true; + + var member_list = (JArray)data["member_list"]; + if (member_list == null) + return; + + var group = new WorkGroupInfo() { conversation_id = conversation_id }; + var groupTmp = user.WorkGroups.FirstOrDefault(z => z.Key == conversation_id) + .Value; + if (groupTmp != null) + group = groupTmp; + group.total = member_list.Count; + group.friends = new List<WorkFriendInfo>(); + + for (int i = 0; i < member_list.Count; i++) + { + //{"acctid":"WuJiaHua","avatar":"http://wework.qpic.cn/bizmail/FxrNrXCeEh8Kwv4ia3iahWCbkR7Y0VqoBniaJ5hrlKggVaibBXIxmOBb8A/0","corp_id":"1970325073072411","invite_user_id":"7881302509911391","nickname":"洪荒老道","position":"","realname":"吴嘉华","remark":"","sex":1,"user_id":"1688853956558440","username":"洪荒老道"} + + var item = member_list[i]; + + var f = new WorkFriendInfo(); + + f.acctid = item["acctid"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.conversation_id = conversation_id; + f.corp_id = item["corp_id"]?.ToString(); + f.mobile = item["mobile"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.position = item["position"]?.ToString(); + f.realname = item["realname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = item["sex"].ToObject<int>(); + f.nickname = item["username"]?.ToString(); + f.user_id = item["user_id"]?.ToString(); + + var friend = group.friends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend == null) + group.friends.Add(f); + } + + user.WorkGroups[conversation_id] = group; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业微信获取群成员列表", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(conversation_id); + } + } + break; + case MsgType.MT_ROOM_ADD_MEMBER_NOTIFY_MSG://群成员新增通知 + { + #region 数据结构 + //{"data":{"member_list":[{"name":"CoCo😘","user_id":"7881299477994410"},{"name":"秒单客-小张","user_id":"7881301029989846"},{"name":"秒单客-小鱼","user_id":"7881302305959168"}],"op_user_id":"1688853956558440","op_user_name":"洪荒老道","room_conversation_id":"R:10696053211008104","room_name":"洪荒老道、CoCo😘、秒单客-小张"},"type":11072} + #endregion + + if (data == null || user == null) + return; + var member_list = (JArray)data["member_list"]; + if (member_list == null || member_list.Count == 0) return; + + var socketClient = EasySoc.GetSocket(); + + var roomConversationId = data["room_conversation_id"]?.ToString(); + var roomName = data["room_name"]?.ToString(); + var opUserId = data["op_user_id"]?.ToString();//邀请人账号 + var opUserName = data["op_user_name"]?.ToString();//邀请人昵称 + + for (int i = 0; i < member_list.Count; i++) + { + var item = member_list[i]; + + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember_workWeChat; + newMember.RobotType = RobotType.客户端企业微信; + newMember.RobotUsername = user.Wxid; + newMember.RobotUsernick = user.Nickname; + + newMember.SourceNick = opUserName; + newMember.SourceName = opUserId; + newMember.MemberNick = item["name"]?.ToString(); ; + newMember.MemberName = item["user_id"]?.ToString(); ; + newMember.GroupId = roomConversationId; + newMember.GroupNick = roomName; + newMember.TotalMember = 0; + + socketClient.Send(newMember); + Thread.Sleep(50); + } + break; + } + case MsgType.MT_ROOM_DEL_MEMBER_NOTIFY_MSG://剔除群成员通知 + break; + case MsgType.MT_RECV_TEXT_MSG://收到文本 + { + if (data == null || user == null) return; + + var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + + #region 文本消息 + + #region 消息样式 + //{"data":{"content":"我17","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"19","receiver":"1688853956558440","send_time":"1584013142","sender":"7881301610989604","sender_name":"17","server_id":"1000481"},"type":11041} - 通过好友返回的数据 + //{"data":{"content":"哦哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"33","receiver":"1688853956558440","send_time":"1584014191","sender":"7881301610989604","sender_name":"17","server_id":"1000520"},"type":11041} - 别人给我发了条消息 + //{"data":{"content":"图婆","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"36","receiver":"1688853956558440","send_time":"1584014736","sender":"7881301610989604","sender_name":"17","server_id":"1000542"},"type":11041} + + //{"data":{"content":"哦哦哦","content_type":0,"conversation_id":"S:1688853956450720_1688853956558440","local_id":"22","receiver":"1688853956450720","send_time":"1584013962","sender":"1688853956558440","sender_name":"华","server_id":"1000498"},"type":11041} - 收到自己发的消息 + //{"data":{"content":"给我发条消息","content_type":0,"conversation_id":"S:1688853956450720_1688853956558440","local_id":"23","receiver":"1688853956450720","send_time":"1584014066","sender":"1688853956558440","sender_name":"华","server_id":"1000500"},"type":11041} + + //{"data":{"content":"饿的","content_type":0,"conversation_id":"R:10696053211008104","local_id":"42","receiver":"R:10696053211008104","send_time":"1584015069","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000574"},"type":11041} - 收到自己发送的群消息 + + #endregion + + //{"data":{"at_list":[],"content":"我是机器学习","content_type":2,"conversation_id":"S:1688853764215634_7881300713013122","local_id":"27946","receiver":"1688853764215634","send_time":"1589009390","sender":"7881300713013122","sender_name":"机器学习","server_id":"1088720"},"type":11041} + //0、2 - 发送的文字 (0) + //if (content_type == "0" || content_type == "2") + { + var content = data["content"]?.ToString(); //文本消息内容 + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = data["send_time"]?.ToString(); //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + + //是否为辅助 + var isSend = false; + + var wmsg = new WorkWechatReceiveMsg(); + + #region 处理辅助 + var sendWxid = sender; + var sendNick = sender_name; + LogHelper.GetSingleObj().Debug("", "接收##########: " + content + @" +"); + + if (!WechatClient.IsAuxiliaryInput(sender, receiver, content)) + { + LogHelper.GetSingleObj().Debug("", "此消息被过滤,因为是机器人自己发送的:" + content + @" +"); + return; + } + var ass = WechatClient.IsAssistance(sender, receiver, dwClientid, WechatType.Xiaoxie_QY); + if (ass.type == WechatClient.AssistanceType.终止) return; + + //if (ass.type == WechatClient.AssistanceType.辅助) + // return; + + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + var usernick = string.Empty; + if (receiver.IsQun()) + { + wmsg.FromGroupid = receiver; + wmsg.FromGroupNick = hook.FindNick(receiver); + } + else if (wmsg.IsSend) + { + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(ass.fromName); + } + + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = usernick; + + #endregion + + //wmsg.FromUsername = sender; + //wmsg.FromUsernick = sender_name; + //wmsg.IsSend = false; + + wmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + wmsg.RobotUsername = user.Wxid; + wmsg.RobotUsernick = user.Nickname; + wmsg.RobotType = RobotType.客户端企业微信; + + + //if (content == "[你收到了一个微信红包,暂时无法查看]") + // wmsg.FromMessageType = WechatMsgType.红包; + //else + wmsg.FromMessageType = WechatMsgType.文本; + + wmsg.FromMessage = content; + + socketClient.Send(wmsg); + } + #endregion + } + break; + //case MsgType.MT_RECV_IMG_MSG://收到图片 + // { + // #region 图片消息 + + // #region 消息样式 + + // //{"data":{"content_type":101,"conversation_id":"R:10696053211008104","file_name":"7305d3cd-e94f-47db-a604-ce079e6c9ac5.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\7305d3cd-e94f-47db-a604-ce079e6c9ac5.jpg","file_size":19457,"local_id":"73","receiver":"1688853956558440","send_time":"1584028981","sender":"7881301364988874","sender_name":"18","server_id":"1000677"},"type":11042} - 别人在群发的图片 + + // //{"data":{"content_type":101,"conversation_id":"S:1688853956558440_7881301364988874","file_name":"29c9c19d-e8d7-4cb0-95b5-e1a7d385003a.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\29c9c19d-e8d7-4cb0-95b5-e1a7d385003a.jpg","file_size":19457,"local_id":"74","receiver":"1688853956558440","send_time":"1584029032","sender":"7881301364988874","sender_name":"18","server_id":"1000680"},"type":11042} - 别人私聊发的图片 + + // //{"data":{"content_type":14,"conversation_id":"R:10696053211008104","file_name":"0f7890b8ea01f7205a76d1195dab66b0.png","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\0f7890b8ea01f7205a76d1195dab66b0.png","file_size":1627,"local_id":"75","receiver":"R:10696053211008104","send_time":"1584029085","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000685"},"type":11042} - 自己群里发的图片 + + // //{"data":{"content_type":14,"conversation_id":"S:1688853956558440_7881301364988874","file_name":"9c6d1a59d8f122fc85c3435ea2aa46fc.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\9c6d1a59d8f122fc85c3435ea2aa46fc.jpg","file_size":178092,"local_id":"76","receiver":"7881301364988874","send_time":"1584029534","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000689"},"type":11042} - 自己私聊发的图片 + + // #endregion + + // //14、101 (14) + + // if (data == null) return; + + // var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + // if (content_type == "14") return; + + // var socketClient = EasySoc.GetSocket(); + + // var conversation_id = data["conversation_id"]?.ToString(); //会话ID + // var local_id = data["local_id"]?.ToString(); //消息的本地ID + // var receiver = data["receiver"]?.ToString(); //接收者的user_id + // var send_time = data["send_time"]?.ToString(); //消息时间戳 + // var sender = data["sender"]?.ToString(); //发送者的user_id + // var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + // var server_id = data["server_id"]?.ToString(); //消息的服务器ID + // var file_path = data["file_path"]?.ToString(); //图片路径 + + // var wmsg = new WorkWechatReceiveMsg(); + // wmsg.Cmd = PCRobotCMD.rcvImg_workWeChat; + // wmsg.RobotType = RobotType.客户端企业微信; + // wmsg.IsSend = false; + // wmsg.RobotUsername = user.Wxid; + // wmsg.RobotUsernick = user.Nickname; + + // wmsg.FromMessage = $"[图片={file_path}]"; + // wmsg.FromMessageType = WechatMsgType.图片; + + // if (conversation_id.Contains("R:")) + // { + // wmsg.FromGroupid = conversation_id; + // wmsg.FromUsername = sender; + // wmsg.FromUsernick = sender_name; + // } + // else + // { + // wmsg.FromUsername = sender; + // wmsg.FromUsernick = sender_name; + // } + // wmsg.FromMessage = string.Empty; + + // socketClient.Send(wmsg); + // #endregion + // } + // break; + //case MsgType.MT_RECV_VIDEO_MSG://收到视频 + // { + // #region 收到视频 + + // #region 消息样式 + // //{"data":{"content_type":103,"conversation_id":"S:1688853956558440_7881301364988874","duration":1,"file_name":"video.MP4","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Video\\2020-03\\video.MP4","file_size":198490,"height":960,"local_id":"77","receiver":"1688853956558440","send_time":"1584031142","sender":"7881301364988874","sender_name":"18","server_id":"1000691","width":544},"type":11043} - 别人发 + + // //{"data":{"content_type":23,"conversation_id":"S:1688853956558440_7881301364988874","duration":1,"file_name":"video.MP4","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Video\\2020-03\\video.MP4","file_size":198490,"height":960,"local_id":"78","receiver":"7881301364988874","send_time":"1584031203","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000696","width":544},"type":11043} - 自己发 + // #endregion + + // //23、103 (23) + + // if (data == null) return; + + // var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + // if (content_type == "23") return; + + // var socketClient = EasySoc.GetSocket(); + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + // if (user == null) + // return; + + // var conversation_id = data["conversation_id"]?.ToString(); //会话ID + // var local_id = data["local_id"]?.ToString(); //消息的本地ID + // var receiver = data["receiver"]?.ToString(); //接收者的user_id + // var send_time = data["send_time"]?.ToString(); //消息时间戳 + // var sender = data["sender"]?.ToString(); //发送者的user_id + // var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + // var server_id = data["server_id"]?.ToString(); //消息的服务器ID + // var file_path = data["file_path"]?.ToString(); //图片路径 + + // var wmsg = new WorkWechatReceiveMsg(); + // wmsg.Cmd = PCRobotCMD.rcvFile_workWeChat; + // wmsg.RobotType = RobotType.客户端企业微信; + // wmsg.IsSend = false; + // wmsg.RobotUsername = user.Wxid; + // wmsg.RobotUsernick = user.Nickname; + + // wmsg.FromMessage = $"[视频={file_path}]"; + // wmsg.FromMessageType = WechatMsgType.视频; + + // if (conversation_id.Contains("R:")) + // { + // wmsg.FromGroupid = conversation_id; + // wmsg.FromUsername = sender; + // wmsg.FromUsernick = sender_name; + // } + // else + // { + // wmsg.FromUsername = sender; + // wmsg.FromUsernick = sender_name; + // } + // wmsg.FromMessage = string.Empty; + + // socketClient.Send(wmsg); + + // #endregion + // } + // break; + case MsgType.MT_RECV_IMG_MSG: //收到图片 + case MsgType.MT_RECV_VIDEO_MSG: //收到视频 + { + if (data == null || user == null) return; + + var socketClient = EasySoc.GetSocket(); + + var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = (long)data["send_time"]; //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + var cdn_type = data["cdn_type"].ToObject<int>(); //Cdn类型 + + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvFile_workWeChat; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.IsSend = false; + wmsg.RobotUsername = user.Wxid; + wmsg.RobotUsernick = user.Nickname; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + var filePath = string.Empty; + #region 下达事件 + if (MsgType.MT_RECV_IMG_MSG == msgType) + { + #region cdn + var cdn = data["cdn"]; + if (cdn != null) + { + if (cdn_type == 1) + { + var aes_key = cdn["aes_key"].ToObject<string>(); + var auth_key = cdn["auth_key"].ToObject<string>(); + var ld_size = cdn["ld_size"].ToObject<int>(); + var ld_url = cdn["ld_url"].ToObject<string>(); + var md5 = cdn["md5"].ToObject<string>(); + var md_size = cdn["md_size"].ToObject<int>(); + var md_url = cdn["md_url"].ToObject<string>(); + var size = cdn["size"].ToObject<int>(); + var url = cdn["url"].ToObject<string>(); + + filePath = hook.CdnDown(url, auth_key, aes_key, size, FileSuffixType.jpg).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收图片消息Cdn下载失败"); + } + else if (cdn_type == 2) + { + var aes_key = cdn["aes_key"].ToObject<string>(); + var file_id = cdn["file_id"].ToObject<string>(); + var file_name = cdn["file_name"].ToObject<string>(); + var md5 = cdn["md5"].ToObject<int>(); + //var preview_img_url = cdn["preview_img_url"].ToObject<string>(); + var size = cdn["size"].ToObject<int>(); + + filePath = hook.C2cCdnDown(aes_key, file_id, size, QyCdnFileType.图片_视频, FileSuffixType.jpg).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收图片消息C2cCdn下载失败"); + + } + + wmsg.FromMessage = $"[图片={filePath}]"; + wmsg.FromMessageType = WechatMsgType.图片; + } + #endregion + } + else if (MsgType.MT_RECV_VIDEO_MSG == msgType) + { + #region cdn + var cdn = data["cdn"]; + if (cdn != null) + { + if (cdn_type == 1) + { + var aes_key = cdn["aes_key"].ToObject<string>(); + var auth_key = cdn["auth_key"].ToObject<string>(); + var md5 = cdn["md5"].ToObject<string>(); + var preview_img_size = cdn["preview_img_size"].ToObject<int>(); + var preview_img_url = cdn["preview_img_url"].ToObject<string>(); + var size = cdn["size"].ToObject<int>(); + var url = cdn["url"].ToObject<string>(); + + filePath = hook.CdnDown(url, auth_key, aes_key, size, FileSuffixType.mp4).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收视频消息Cdn下载失败"); + } + else if (cdn_type == 2) + { + var aes_key = cdn["aes_key"].ToObject<string>(); + var file_id = cdn["file_id"].ToObject<string>(); + var file_name = cdn["file_name"].ToObject<string>(); + var md5 = cdn["md5"].ToObject<int>(); + //var preview_img_url = cdn["preview_img_url"].ToObject<string>(); + var size = cdn["size"].ToObject<int>(); + + filePath = hook.C2cCdnDown(aes_key, file_id, size, QyCdnFileType.图片_视频, FileSuffixType.mp4).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收视频消息C2cCdn下载失败"); + } + + //var filePath1 = hook.C2cCdnDown("65323164303935663365393634306639", "306902010204623060020100020483d92af902030f4241020473a3973d020462752be0042432353830373535362d613134372d343466612d613632342d38373461396539663630653302010002032cbb4004105c8576e1a816b54165c65f6fb6ccdbde0201040201000400", 2931518, QyCdnFileType.图片_视频, FileSuffixType.mp4).Result; + //if (string.IsNullOrWhiteSpace(filePath1) || !File.Exists(filePath1)) + // throw new Exception("企业接收图片消息C2cCdn下载失败"); + + + wmsg.FromMessage = $"[视频={filePath}]"; + wmsg.FromMessageType = WechatMsgType.视频; + } + #endregion + } + #endregion + + if (receiver.IsQun()) + { + wmsg.FromGroupid = receiver; + wmsg.FromGroupNick = hook.FindNick(receiver); + } + + + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + wmsg.Timestamp = send_time; + wmsg.MsgId = server_id.Trim(); + wmsg.IsSend = false; + wmsg.OriMessage = JsonConvert.SerializeObject(new { data = data, filePath = filePath }); + + socketClient.Send(wmsg); + } + break; + case MsgType.MT_RECV_VOICE_MSG: //收到语音 + break; + case MsgType.MT_RECV_FILE_MSG: //收到文件 + break; + case MsgType.MT_RECV_LOCATION_MSG://收到位置 + break; + case MsgType.MT_RECV_LINK_CARD_MSG://收到链接 + { + #region 链接消息 + + #region 消息样式 + //{"data":{"content_type":13,"conversation_id":"S:1688853956558440_7881301364988874","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"","local_id":"82","receiver":"1688853956558440","send_time":"1584033150","sender":"7881301364988874","sender_name":"18","server_id":"1000715","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 别人发送的私聊链接 + + //{"data":{"content_type":13,"conversation_id":"R:10696053211008104","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"","local_id":"85","receiver":"1688853956558440","send_time":"1584034341","sender":"7881301364988874","sender_name":"18","server_id":"1000724","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 别人发送的群聊链接 + + + //{"data":{"content_type":13,"conversation_id":"S:1688853956558440_7881301364988874","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"https://wework.qpic.cn/wwpic/51458_1ermIpIgTJu-_11_1584034011/0","local_id":"83","receiver":"7881301364988874","send_time":"1584034011","sender":"1688853956558440","sender_name":"吴","server_id":"1000720","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 自己发送的私聊 + + //{"data":{"content_type":13,"conversation_id":"R:10696053211008104","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"https://wework.qpic.cn/wwpic/51458_1ermIpIgTJu-_11_1584034011/0","local_id":"84","receiver":"R:10696053211008104","send_time":"1584034246","sender":"1688853956558440","sender_name":"吴","server_id":"1000722","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 自己发送的群聊 + + #endregion + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + var socketClient = EasySoc.GetSocket(); + + var content_type = data["content_type"]?.ToString(); + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var desc = data["desc"]?.ToString(); //链接描述 + var image_url = data["image_url"]?.ToString(); //链接缩略图url + var is_pc = (int)data["is_pc"]; + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = data["send_time"].ToObject<long>(); //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + var title = data["title"]?.ToString(); //链接标题 + var url = data["url"]?.ToString(); //链接url + var cdn_type = (int)data["cdn_type"]; + + var isSend = false; + + var filePath = string.Empty; + var cdn = data["cdn"]; + if (cdn != null) + { + var aes_key = cdn["aes_key"].ToString(); + var auth_key = cdn["auth_key"].ToString(); + var size = cdn["size"].ToObject<int>(); + var cdnUrl = cdn["url"].ToString(); + + filePath = hook.CdnDown(cdnUrl, auth_key, aes_key, size, FileSuffixType.jpg).Result; + if (!string.IsNullOrWhiteSpace(filePath) && File.Exists(filePath)) + { } + else + throw new Exception("企业接收链接消息Cdn下载失败"); + } + + var rmsg = new WorkWechatReceiveMsg(); + + rmsg.MsgId = server_id.Trim(); + + #region 处理辅助 + //var sendWxid = sender; + //var sendNick = sender_name; + //if (!WechatClient.IsAuxiliaryInput(sender, conversation_id, url)) + //{ + // //LogHepler.WriteLog("此消息被过滤,因为是机器人自己发送的:" + content,LogEnum.调试); + // return; + //} + //var ass = WechatClient.IsAssistance(sender, conversation_id, dwClientid, WechatType.Xiaoxie_QY); + //if (ass.type == WechatClient.AssistanceType.终止) return; + + //rmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + + //var usernick = string.Empty; + + //if (conversation_id.IsQun()) + //{ + // rmsg.FromGroupid = conversation_id; + // rmsg.FromGroupNick = hook.FindNick(conversation_id); + //} + //else if (rmsg.IsSend) + //{ + // sendWxid = receiver; + // sendNick = hook.FindNick(receiver); + //} + //rmsg.FromUsername = sendWxid; + //rmsg.FromUsernick = sendNick; + #endregion + + #region 1 + //#region 处理辅助 + var sendWxid = sender; + var sendNick = sender_name; + if (!WechatClient.IsAuxiliaryInput(sender, receiver, url)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + url); + return; + } + + var ass = WechatClient.IsAssistance(sender, receiver, dwClientid, + WechatType.Xiaoxie_QY); + + if (ass.type == WechatClient.AssistanceType.终止) return; + + rmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + + //var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + var usernick = string.Empty; + if (receiver.IsQun()) + { + rmsg.FromGroupid = receiver; + rmsg.FromGroupNick = hook.FindNick(receiver); + } + else if (rmsg.IsSend) + { + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(ass.fromName); + } + + rmsg.FromUsername = ass.fromName; + rmsg.FromUsernick = usernick; + + + #endregion + + + rmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + //rmsg.IsSend = isSend; + rmsg.RobotUsername = user.Wxid; + rmsg.RobotUsernick = user.Nickname; + rmsg.RobotType = RobotType.客户端企业微信; + rmsg.FromMessageType = WechatMsgType.链接; + + rmsg.FromMessage = url; + + socketClient.Send(rmsg); + + #endregion + } + break; + case MsgType.MT_RECV_EMOTION_MSG: //收到表情 + { + #region 收到表情 + + #region 数据结构 + //企业微信 + //{"data":{"content_type":29,"conversation_id":"R:10696053211018728","is_pc":0,"local_id":"159","name":"动画表情","receiver":"R:10696053211018728","send_time":"1610034507","sender":"1688853956558440","sender_name":"洪荒老道","server_id":"1042202","url":"http://p.qpic.cn/pic_wework/4121458178/eee874e28b58332c1f087836eecb7e06a5c3d08fa155e5e2/0"},"type":11048} + + //个人微信 + //{"data":{"content_type":29,"conversation_id":"R:10696053211018728","is_pc":0,"local_id":"161","name":"动画表情","receiver":"1688853956558440","send_time":"1610034880","sender":"7881302484994318","sender_name":"、","server_id":"1042206","url":"https://wework.qpic.cn/wwpic/wwwx_4e98356331438f1988a3b55a7edc7b3f/0"},"type":11048} + + //企业微信 + //{"data":{"cdn":{"aes_key":"","file_id":"","md5":"4e98356331438f1988a3b55a7edc7b3f","size":0},"cdn_type":1,"content_type":29,"conversation_id":"S:1688853956558440_7881302484994318","height":262,"is_pc":0,"local_id":"908","name":"动画表情","receiver":"1688853956558440","send_time":"1649232304","sender":"7881302484994318","sender_name":"派大星 。","server_id":"1064856","source_type":102,"type":1,"url":"https://wework.qpic.cn/wwpic/wwwx_4e98356331438f1988a3b55a7edc7b3f/0","width":264},"type":11048} + + + #endregion + + if (data == null || user == null) return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + var socketClient = EasySoc.GetSocket(); + + var content_type = data["content_type"]?.ToString(); + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var height = data["height"]?.ToString(); + var is_pc = data["is_pc"]?.ToString(); //设备端 PC/移动 + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var name = data["name"]?.ToString(); //名称 + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = (long)data["send_time"]; //发送时间 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + //var source_type = data["source_type"]?.ToString(); + //var type = data["type"]?.ToString(); + var url = data["url"]?.ToString(); //图片地址 + var width = data["width"]?.ToString(); + + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + var rmsg = new WorkWechatReceiveMsg(); + rmsg.MsgId = server_id.Trim(); + rmsg.IsSend = false; + rmsg.FromMessage = url; + rmsg.FromMessageType = WechatMsgType.表情; + rmsg.Timestamp = send_time; + rmsg.OriMessage = JsonConvert.SerializeObject(data); + + if (receiver.IsQun()) + { + rmsg.FromGroupid = receiver; + rmsg.FromGroupNick = hook.FindNick(receiver); + } + rmsg.FromUsername = sender; + rmsg.FromUsernick = sender_name; + + socketClient.Send(rmsg); + #endregion + } + break; + case MsgType.MT_RECV_RED_PACKET_MSG://收到红包 + { + #region 收到红包 + + #region 数据结构 + //企业微信红包(个人微信红包进的是文本消息) + //{"data":{"content_type":26,"conversation_id":"R:10696053211018728","desc":"来自洪荒老道的红包,请进入手机版企业微信查看","is_pc":0,"local_id":"164","money":1,"packet_id":"1800008896202101087215807323007","receiver":"R:10696053211018728","remark":"阳光普照,皆大欢喜","send_time":"1610035229","sender":"1688853956558440","sender_name":"洪荒老道","server_id":"1042219"},"type":11049} + #endregion + + if (data == null || user == null) return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + var socketClient = EasySoc.GetSocket(); + + var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var desc = data["desc"]?.ToString(); //描述 + var is_pc = data["is_pc"]?.ToString(); //pc/移动 + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var money = data["money"]?.ToString(); //描述 + var packet_id = data["packet_id"]?.ToString(); //数据包id + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var remark = data["remark"]?.ToString(); //备注 + var send_time = (long)data["send_time"]; //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + + var rmsg = new WorkWechatReceiveMsg(); + rmsg.MsgId = server_id.Trim(); + rmsg.IsSend = false; + rmsg.FromMessage = desc; + rmsg.FromMessageType = WechatMsgType.红包; + + if (receiver.IsQun()) + { + rmsg.FromGroupid = receiver; + rmsg.FromGroupNick = hook.FindNick(receiver); + } + rmsg.FromUsername = sender; + rmsg.FromUsernick = sender_name; + rmsg.Timestamp = send_time; + rmsg.OriMessage = JsonConvert.SerializeObject(data); + + socketClient.Send(rmsg); + #endregion + } + break; + case MsgType.MT_RECV_PERSON_CARD_MSG://收到个人名片 + { + //{"data":{"content":"推荐噢噢噢哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"81","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000703"},"type":11041} + + /* + {"data":{"avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaELtKaBvIBMGI7xTZdLA9mZglMaZQxPeBASJT1lCXCJnKg/0","content_type":41,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"80","nickname":"??欧尼桑","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000700","source":"微信","user_id":"7881301516989639"},"type":11050} + 收到消息:{"data":{"content":"推荐噢噢噢哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"81","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000703"},"type":11041} + */ + + //var content = data["content"]?.ToString(); + //var content_type = data["content_type"]?.ToString(); + //var conversation_id = data["conversation_id"]?.ToString(); + //var local_id = data["local_id"]?.ToString(); + //var receiver = data["receiver"]?.ToString(); + //var send_time = data["send_time"]?.ToString(); + //var sender = data["sender"]?.ToString(); + //var sender_name = data["sender_name"]?.ToString(); + //var server_id = data["server_id"]?.ToString(); + + #region 收到个人名片 + + #region 数据结构 + //收到个人微信名片 + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/b2ONlmmVZRq56aA1tGTq68BofibibsBtW4wicHoXLnnM1ib0CWjnUIkD6g/0","content_type":41,"conversation_id":"R:10696053211018728","is_pc":0,"local_id":"143","nickname":"壹十叄","receiver":"1688853956558440","send_time":"1610031853","sender":"7881301536005932","sender_name":"摸鱼樊","server_id":"1042150","source":"微信","user_id":"7881302995989894"},"type":11050} + + //收到企业微信名片 + //{"data":{"avatar":"http://wework.qpic.cn/bizmail/AU8vqVRBac5HFiaTI2qxv3RNr8Kib0wFyicBQZkvs06ayzBhlHE7dCAmA/0","content_type":41,"conversation_id":"R:10696053211018728","is_pc":0,"local_id":"145","nickname":"白龙马","receiver":"R:10696053211018728","send_time":"1610032777","sender":"1688853956558440","sender_name":"洪荒老道","server_id":"1042158","source":"秒单客","user_id":"1688853956589484"},"type":11050} + #endregion + + if (data == null || user == null) return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + var socketClient = EasySoc.GetSocket(); + + var content_type = data["content_type"]?.ToString(); + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var avatar = data["avatar"]?.ToString(); //头像地址 + var is_pc = data["is_pc"]?.ToString(); //设备端 PC/移动 + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var nickname = data["nickname"]?.ToString(); //名片用户昵称 + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = (long)data["send_time"]; //发送时间 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + var source = data["source"]?.ToString(); //来源 + var user_id = data["user_id"]?.ToString(); //用户id + + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + var rmsg = new WorkWechatReceiveMsg(); + rmsg.MsgId = server_id.Trim(); + rmsg.IsSend = false; + rmsg.FromMessage = "发送了一个名片"; + rmsg.OriMessage = JsonConvert.SerializeObject(new { user_id = user_id, nickname = nickname, avatar = avatar }); + rmsg.FromMessageType = WechatMsgType.名片; + + if (receiver.IsQun()) + { + rmsg.FromGroupid = receiver; + rmsg.FromGroupNick = hook.FindNick(receiver); + } + rmsg.FromUsername = sender; + rmsg.FromUsernick = sender_name; + rmsg.Timestamp = send_time; + + socketClient.Send(rmsg); + #endregion + + } + break; + case MsgType.MT_RECV_MINIAPP_MSG://收到小程序 + { + //个人微信/企业微信 + //{"data":{"content_type":78,"conversation_id":"R:10696053211018728","enterpoint":"pages/tab/home/index.html?_um_ssrc=oucfI5QRI-8SbyOTKSGYt5-ia0dk&_um_sts=1610033684099","ghid":"gh_a0d7a7672cf7@app","headimg":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM43LsxpXHKd7ua7kwMZQ8WHmZlkYTzr3Tdm8sMOJ7Ypog/96","image_key1":"306b020102046430620201000204bafc490e02030f4df9020473e6607102045ff72a530436333133373039353935305f313734393433343231315f3262393764653133616335373232353633383831336564376334396563616164020100020300ab1004000201010201000400","image_key2":"61747072666A766977766D69726D6168","image_key3":"2b97de13ac57225638813ed7c49ecaad","image_size":43791,"is_pc":0,"local_id":"155","name":"啄木鸟家庭维修","receiver":"1688853956558440","send_time":"1610033747","sender":"7881302484994318","sender_name":"、","server_id":"1042188","title":"直营一口价,维修无猫腻","wxid":"wx3d6b1af0cb07fa5a"},"type":11066} + + if (data == null || user == null) return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + var socketClient = EasySoc.GetSocket(); + + var appicon = data["appicon"]?.ToString(); + var appid = data["appid"]?.ToString(); + var appname = data["appname"]?.ToString(); + var content_type = data["content_type"]?.ToString();//内容类型 78 + var conversation_id = data["conversation_id"]?.ToString();//接收者的的会话ID + var local_id = data["local_id"]?.ToString(); + var page_path = data["page_path"]?.ToString();//入口点 - 链接(小程序里面的链接) + var receiver = data["receiver"]?.ToString();// 接收者的user_id + var send_time = (long)data["send_time"];//小程序标题 + var sender = data["sender"]?.ToString();// 发送者的user_id + var sender_name = data["sender_name"]?.ToString();//发送者昵称 + var server_id = data["server_id"]?.ToString();//消息的服务器ID + var thumb_height = data["thumb_height"]?.ToString(); + var thumb_width = data["thumb_width"]?.ToString(); + var title = data["title"]?.ToString();//小程序标题 + var username = data["username"]?.ToString(); + + var cdn_type = (int)data["cdn_type"]; + + var filePath = string.Empty; + var cdn = data["cdn"]; + if (cdn != null) + { + var aes_key = cdn["aes_key"].ToString(); + var file_id = cdn["file_id"].ToString(); + var size = (int)cdn["size"]; + + filePath = hook.C2cCdnDown(aes_key, file_id, size, QyCdnFileType.图片_视频, FileSuffixType.jpg).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收小程序消息Cdn下载失败"); + } + + + + var isSend = false; + var RobotUsername = string.Empty; + var RobotUsernick = string.Empty; + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + RobotUsername = user.Wxid; + RobotUsernick = user.Nickname; + FromUsername = sender; + FromUsernick = sender_name; + //} + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + wmsg.IsSend = isSend; + wmsg.RobotUsername = RobotUsername; + wmsg.RobotUsernick = RobotUsernick; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.FromMessageType = WechatMsgType.小程序; + + if (receiver.IsQun()) + { + wmsg.FromGroupid = receiver; + wmsg.FromGroupNick = hook.FindNick(receiver); + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + else + { + wmsg.FromUsername = FromUsername; + wmsg.FromUsernick = FromUsernick; + } + + wmsg.FromMessage = page_path; + + socketClient.Send(wmsg); + } + break; + case MsgType.MT_RECV_IMAGE_TEXT_MSG://接收图文消息 + break; + case MsgType.MT_RECV_REVOKE_MSG://消息撤回 + break; + case MsgType.MT_RECV_OTHER_MSG://接收其他未解析消息 + break; + case MsgType.MT_SEARCH_USER_MSG: //查询联系人 + { + #region 数据结构 + /* + { + "data":{ + "contact_info":{ + "acctid":"YiYi", + "alias":"", + "attr":146210880, + "bind_email":"", + "bind_email_status":1, + "birthday":"1970-01-01 00:00:00", + "bizuin":0, + "circle_language":0, + "corpid":1970325xxxxxx, + "create_source":1, + "create_time":0, + "department":"", + "display_order":0, + "emailaddr":"", + "english_name":"", + "extern_job":"", + "extern_position":"", + "external_corp_info":"", + "external_custom_info":null, + "external_pb":"", + "external_wxfinder":null, + "extra_info":null, + "gender":2, + "gid":2251800xxxxxx, + "hash":0, + "holiday_info":{ + "create_time":0, + "holiday_desc":"", + "holiday_generate_src":0, + "holiday_icon_index":0, + "holiday_info_id":0, + "holiday_status":0, + "holiday_status_new":0, + "new_holiday_icon_index":0 + }, + "holiday_list_read_time":0, + "iconurl":"http:\/\/wework.qpic.cn\/bizmail\/W9Sqc7EPicJeeR77ibdaMesvkicibwMdjCmaY6rIcpG8aytZJMCTrtVQgw\/0", + "internation_code":"86", + "is_name_verified":true, + "job":"", + "level":0, + "main_partyid":16888xxx81, + "mobile":"", + "name":"一一xx", + "name_status":1, + "nation_code":"", + "number":"", + "openkfprofile":null, + "partyid":0, + "partymember_order":0, + "personal_work_type":0, + "phone":"", + "position":"", + "pstn_extension_number":"", + "pstn_extension_number_new":"", + "qqmail_uin":0, + "realname":"xxxxx", + "robot_profile":null, + "school_parent_openid":"", + "school_staff_relation":"", + "school_user_type":0, + "staff_attr":0, + "staff_type":0, + "staff_xid":0, + "student_number":"", + "subjectname":"", + "tencent_info":{ + "work_card_image":"" + }, + "uin":16888xxx, + "under_verify_name":"", + "unionid":"ozynqsnJuiQexxxxbE", + "use_attr2":5898244, + "v_corp_name_full":"", + "v_corp_name_short":"", + "v_corp_use_status":1000, + "v_create_mail":"", + "v_hoster_vid":0, + "v_is_init_moder":true, + "v_recommend_info":null, + "vcode":"vce5e8f7825e87c408", + "xcx_corp_address":"", + "xcx_style":0 + }, + "corpinfo":{ + "admin_vid":0, + "appli_info":null, + "auth_time":0, + "authed_domain":"", + "b_authed_licence":true, + "b_has_info_corp":false, + "b_hastoken":false, + "b_internet_industry":false, + "b_need_not_verify":false, + "b_need_update_name":false, + "card_url":"https:\/\/work.weixin.qq.com\/wework_admin\/xxxxp?", + "coreate_source_info":"", + "corp_desc":"", + "corp_full_name":"xxxx科技有限公司", + "corp_logo":"https:\/\/p.qlogo.cn\/bizmail\/1icHEZ7xxxx\/0", + "corp_name":"xxxxxxxxx", + "corp_stat":0, + "corp_use_status":0, + "corpid":19703250xxxxxxx, + "create_time":1532394113, + "custom_check_url":"", + "email_need_auth":"", + "internation_code":"", + "isAccepted":false, + "isTrust":true, + "is_corp_verify":false, + "is_init_moduser":false, + "is_overseas_corp":false, + "join_need_verify":false, + "language":1, + "mail":"", + "mem_appli_time":0, + "mem_create_time":0, + "mobile_need_auth":"", + "moduser_info":{ + "name":"", + "vid":0 + }, + "ownername":"小邪", + "personal_work_info":"", + "personal_work_type":0, + "pstn_main_number":"", + "pstn_officephone_state":0, + "qyh_info":"", + "scorp_id":"wwfd561047d79e1a2d", + "staff_info":{ + "attr":0, + "corp_mail":"", + "corp_mail_active":false, + "corp_position":"", + "corp_rank":"", + "custom_check_status":0, + "english_name":"", + "head_image":"http:\/\/wework.qpic.cn\/bizmail\/xxxxxxxxxxw\/0", + "internation_code":"86", + "mail":"yiyimama@lcwsl999.onexmail.com", + "name":"一一xxxx", + "phone":"", + "pstn_extension_number":"", + "real_name":"" + }, + "staffnum":0, + "status":0, + "unreadNum":0, + "v_init_domain_name":"", + "v_superadmin_name":"", + "v_superadmin_vid":0, + "verify_msg":"", + "verify_submit_time":0, + "vid":16888505xxxxxx, + "virtual_can_change_full_name":false, + "virtual_corp_claiming_name":"", + "work_card_back_url":"", + "work_card_face_url":"" + }, + "datalist":[{ + "contact_info":{ + "acctid":"YiYiM", + "alias":"", + "attr":146210880, + "bind_email":"", + "bind_email_status":1, + "birthday":"1970-01-01 00:00:00", + "bizuin":0, + "circle_language":0, + "corpid":1970325xxx86, + "create_source":1, + "create_time":0, + "department":"", + "display_order":0, + "emailaddr":"", + "english_name":"", + "extern_job":"", + "extern_position":"", + "external_corp_info":"", + "external_custom_info":null, + "external_pb":"", + "external_wxfinder":null, + "extra_info":null, + "gender":2, + "gid":2251800xx9, + "hash":0, + "holiday_info":{ + "create_time":0, + "holiday_desc":"", + "holiday_generate_src":0, + "holiday_icon_index":0, + "holiday_info_id":0, + "holiday_status":0, + "holiday_status_new":0, + "new_holiday_icon_index":0 + }, + "holiday_list_read_time":0, + "iconurl":"http:\/\/wework.qpic.cn\/bizmail\/W9Sqc7EPicJeeR77ibdaMesvkicibwMdjCmaY6rIcpG8aytZJMCTrtVQgw\/0", + "internation_code":"86", + "is_name_verified":true, + "job":"", + "level":0, + "main_partyid":16888505xxx1, + "mobile":"", + "name":"一一x", + "name_status":1, + "nation_code":"", + "number":"", + "openkfprofile":null, + "partyid":0, + "partymember_order":0, + "personal_work_type":0, + "phone":"", + "position":"", + "pstn_extension_number":"", + "pstn_extension_number_new":"", + "qqmail_uin":0, + "realname":"xxxx", + "robot_profile":null, + "school_parent_openid":"", + "school_staff_relation":"", + "school_user_type":0, + "staff_attr":0, + "staff_type":0, + "staff_xid":0, + "student_number":"", + "subjectname":"", + "tencent_info":{ + "work_card_image":"" + }, + "uin":1688850xxxx3, + "under_verify_name":"", + "unionid":"ozynqsnJuiQerUcDxxE", + "use_attr2":5898244, + "v_corp_name_full":"", + "v_corp_name_short":"", + "v_corp_use_status":1000, + "v_create_mail":"", + "v_hoster_vid":0, + "v_is_init_moder":true, + "v_recommend_info":null, + "vcode":"vce5e8f78x8", + "xcx_corp_address":"", + "xcx_style":0 + }, + "contact_info_wx":{ + "acctid":"", + "alias":"", + "attr":0, + "bind_email":"", + "bind_email_status":0, + "birthday":"", + "bizuin":0, + "circle_language":0, + "corpid":0, + "create_source":0, + "create_time":0, + "department":"", + "display_order":0, + "emailaddr":"", + "english_name":"", + "extern_job":"", + "extern_position":"", + "external_corp_info":"", + "external_custom_info":null, + "external_pb":"", + "external_wxfinder":null, + "extra_info":null, + "gender":2, + "gid":0, + "hash":0, + "holiday_info":null, + "holiday_list_read_time":0, + "iconurl":"http:\/\/wx.qlogo.cn\/mmhead\/Q3auHgz\/0", + "internation_code":"", + "is_name_verified":false, + "job":"", + "level":0, + "main_partyid":0, + "mobile":"", + "name":"一小口", // 名称 + "name_status":0, + "nation_code":"", + "number":"", + "openkfprofile":null, + "partyid":0, + "partymember_order":0, + "personal_work_type":0, + "phone":"", + "position":"", + "pstn_extension_number":"", + "pstn_extension_number_new":"", + "qqmail_uin":0, + "realname":"", + "robot_profile":null, + "school_parent_openid":"", + "school_staff_relation":"", + "school_user_type":0, + "self_info":null, + "staff_attr":0, + "staff_type":0, + "staff_xid":0, + "student_number":"", + "subjectname":"", + "tencent_info":null, + "uin":7881299xxxxxx, // 用户id + "under_verify_name":"", + "unionid":"", + "use_attr2":0, + "v_corp_name_full":"", + "v_corp_name_short":"", + "v_corp_use_status":0, + "v_create_mail":"", + "v_hoster_vid":0, + "v_is_init_moder":false, + "v_recommend_info":null, + "vcode":"", + "xcx_corp_address":"", + "xcx_style":0 + }, + "corpinfo":{ + "admin_vid":0, + "appli_info":null, + "auth_time":0, + "authed_domain":"", + "b_authed_licence":true, + "b_has_info_corp":false, + "b_hastoken":false, + "b_internet_industry":false, + "b_need_not_verify":false, + "b_need_update_name":false, + "card_url":"https:\/\/work.weixin.qq.com\/wework_admin\/user\/h5\/corp?", + "coreate_source_info":"", + "corp_desc":"", + "corp_full_name":"xxxxxxx网络科技有限公司", + "corp_logo":"https:\/\/p.qlogo.cn\/bizmail\/1icHExxxxxxg\/0", + "corp_name":"xxxx", + "corp_stat":0, + "corp_use_status":0, + "corpid":197032xxxxx6, + "create_time":1532394113, + "custom_check_url":"", + "email_need_auth":"", + "internation_code":"", + "isAccepted":false, + "isTrust":true, + "is_corp_verify":false, + "is_init_moduser":false, + "is_overseas_corp":false, + "join_need_verify":false, + "language":1, + "mail":"", + "mem_appli_time":0, + "mem_create_time":0, + "mobile_need_auth":"", + "moduser_info":{ + "name":"", + "vid":0 + }, + "ownername":"小邪", + "personal_work_info":"", + "personal_work_type":0, + "pstn_main_number":"", + "pstn_officephone_state":0, + "qyh_info":"", + "scorp_id":"wwfd561047d79e1a2d", + "staff_info":{ + "attr":0, + "corp_mail":"", + "corp_mail_active":false, + "corp_position":"", + "corp_rank":"", + "custom_check_status":0, + "english_name":"", + "head_image":"http:\/\/wework.qpic.cn\/bizmail\/W9Sqc7EPicJeeR77ibdaMesvkicibwMdjCxxxxw\/0", // 头像 + "internation_code":"86", + "mail":"yiyxxa@lxxx.onexmail.com", + "name":"一一xxx", + "phone":"", + "pstn_extension_number":"", + "real_name":"" + }, + "staffnum":0, + "status":0, + "unreadNum":0, + "v_init_domain_name":"", + "v_superadmin_name":"", + "v_superadmin_vid":0, + "verify_msg":"", + "verify_submit_time":0, + "vid":16888505xxxxxx, + "virtual_can_change_full_name":false, + "virtual_corp_claiming_name":"", + "work_card_back_url":"", + "work_card_face_url":"" + }, + "flag":0, + "item_type":1, + "name":"", + "openid":"orFrbsuSYHirGxxxxxx", // 添加为客户时要用到 + "relation":1, + "search_status":1, + "wx_ticket":"6001221957E20E5D29D1E733EE712415FBE17551E97981837EFAE6FFE7C22D989C2C64ABFEFC22FB07A801B91A132985C1A360FCDEAA389547xxxDxxxxF" // 添加为客户时要用到 + }], + "error_code":0, + "error_message":"", + "flag":0, + "keyword":"151xxxxxxxx", // 搜索的手机号 + "name":"", + "relation":1, + "search_status":1 + }, + "type":11052 + } + */ + #endregion + + if (user == null || data == null) return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + var keyWord = string.Empty; + if (user.IsGetContactDic.ContainsKey(keyWord) && user.IsGetContactDic[keyWord]) + return; + try + { + user.IsGetContactDic[keyWord] = true; + + FriendInfoHandlerEnterprise friendInfo = null; + + var member_list = (JArray)data["member_list"]; + if (member_list == null) + return; + + var result = (JArray)data["datalist"][0]; + if (result != null) + { + var uin = string.Empty; + var openid = string.Empty; + var wx_ticket = string.Empty; + var corpid = string.Empty; + var flag = false;//是否赋值 + var contact_info_wx = result["contact_info_wx"]; + if (flag = contact_info_wx != null) + { + uin = contact_info_wx["uin"].ToString(); + openid = result["openid"].ToString(); + wx_ticket = result["wx_ticket "].ToString(); + } + var contact_info = result["contact_info"]; + if (flag = contact_info != null) + { + uin = contact_info["uin"].ToString(); + corpid = contact_info["corpid"].ToString(); + } + if (flag) + friendInfo = new FriendInfoHandlerEnterprise() { user_id = uin, openid = openid, wx_ticket = wx_ticket, corp_id = corpid }; + } + user.FriendHandlerDic[keyWord] = friendInfo; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业微信通过手机号搜索用户信息", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(keyWord); + } + } + break; + case MsgType.MT_ADD_SEARCH_USER_MSG://添加查询的联系人 + break; + case MsgType.MT_MODIFY_USER_REMARK_MSG://修改用户备注 + break; + case MsgType.MT_MODIFY_USER_DESC_MSG://修改用户描述 + break; + case MsgType.MT_MODIFY_EXTERNAl_USER_PHONES_MSG://修改外部联系人手机号 + break; + case MsgType.MT_MODIFY_EXTERNAl_USER_COMPANY_MSG://修改外部联系人公司 + break; + case MsgType.MT_CREATE_ROOM_MSG://创建群 + { + #region 数据结构 + /* + { + "data":{ + "createruin":168885053xx82, //创建者user_id + "createtime":1639322040, // 创建时间 + "error_code":0, + "error_message":"", + "failmem":[{ + "type":0, + "vid":0 + }], + "msgid":109xx35, + "msgseq":8513xxx, + "roomid":1069605293xxx1944, // 群id + "roomname":"", + "sessionid":"Nm5GdS10TURTd3lGdEZ1aQ==", + "success_add_vidlist":[{ + "success_add_vidlist":7881300xxx2093 // 添加成功的成员用户id + }] + }, + "type":11058 + } + */ + #endregion + if (data == null || user == null) + return; + + var _type = RobotIsRunType.创建群; + if (user.IsGetDic.ContainsKey(_type)) + { + if (user.IsGetDic[_type]) + return; + } + + try + { + user.IsGetDic[_type] = true; + + CreateGroupInfo CreateGroupInfo = null; + + var keyMd5 = HttpExtend.GetMD5String($"CACHE_CREATEGROUP{_type}"); + + if (data["error_code"].ToObject<int>() == 0) + { + var createruin = data["createruin"].ToObject<string>(); + var createtime = data["createtime"].ToObject<long>(); + var roomid = data["roomid"].ToObject<string>(); + var roomname = data["roomname"].ToObject<string>(); + + CreateGroupInfo = new CreateGroupInfo() { CreateUserName = createruin, CreateTime = createtime, GroupId = roomid, GroupNick = roomname }; + } + Common.SetCache(keyMd5, CreateGroupInfo, 10); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业微信创建群", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetDic.Remove(_type); + } + } + break; + case MsgType.MT_CREATE_NULL_ROOM_MSG://创建外部空群 + break; + case MsgType.MT_MODIFY_ROOM_NAME_MSG://修改群名 + break; + case MsgType.MT_ROOM_ADD_MEMBERS_MSG://添加群成员 + //break; + case MsgType.MT_ROOM_DEL_MEMBERS_MSG://删除群成员 + break; + case MsgType.MT_RECV_FRIEND_REQUEST://接收好友请求 + { + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/0T8yO33zeeg33jJCQibIWobapj6GX4xFBbOECtmG9VdkYpnzyiaUr5iag/0","corp_id":"1970325134026788","nickname":"17","sex":2,"user_id":"7881301610989604","verify":"我17"},"type":11063} + + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaEI8qvnXF9KjgTpvaSAzfhbE2kGoIspb7ibbEHGZEQxRibAQ/0","corp_id":"1970325134026788","nickname":"助将","sex":0,"user_id":"7881303410988876","verify":"欧珀new"},"type":11063} + + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/zroWGtm5tmsxaCHfI2ibibuBxtzsZc6brAIDCicIianoDYI/0","corp_id":"1970325134026788","nickname":"Boom","sex":1,"user_id":"7881303336175964","verify":"我是Boom"},"type":11063} + + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + + var avatar = data["avatar"]?.ToString();//头像 + var corp_id = data["corp_id"]?.ToString();//公司id + var nickname = data["nickname"]?.ToString();//申请人昵称 + var sex = data["sex"]?.ToString();//性别 + var user_id = data["user_id"]?.ToString();//用户id + var verify = data["verify"]?.ToString();//申请摘要 + + var wXApply = new WorkWechatApplyFriend(); + wXApply.Cmd = PCRobotCMD.applyFriend_workWeChat; + wXApply.RobotUsername = user.Wxid; + wXApply.RobotUsernick = user.Nickname; + wXApply.RobotType = RobotType.客户端企业微信; + wXApply.Message = verify; + wXApply.NewFriendWxid = user_id; + wXApply.NewFriendNick = nickname; + wXApply.OldFriendWxid = string.Empty; + wXApply.OldFriendNick = string.Empty; + + wXApply.Token = CsharpHttpHelper.HttpHelper.ObjectToJson(new { user_id = user_id, corp_id = corp_id }); + + //记录申请人,用于记录 + if (!FriendRequestRecord.ContainsKey(user_id)) + FriendRequestRecord.TryAdd(user_id, new FriendInfo() { account = user_id, avatar = avatar, nickname = nickname, sex = int.Parse(sex), wxid = user_id }); + + socketClient.Send(wXApply); + } + break; + case MsgType.MT_ADD_ROOM_USER_MSG://添加群成员为联系人 + break; + case MsgType.MT_ROOM_CREATE_NOTIFY_MSG://新群通知 + break; + case MsgType.MT_ROOM_MEMBER_QUIT_NOTIFY_MSG://群成员主动退出通知 + break; + case MsgType.MT_CONTACT_ADD_NOITFY_MSG://好友新增通知 + { + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM7fVNDOBibWpoNq079a20EfXcvBZKUALpibSIyVSfRiccAtw/0","conversation_id":"S:1688853956558440_7881299738174185","corp_id":"1970325134026788","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881299738174185","username":"蟹老板 。"},"type":11076} + + if (data == null || user == null) return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + var socketClient = EasySoc.GetSocket(); + + var user_id = data["user_id"]?.ToString();//账号 + + #region //如果为机器人自动通过的,等待结果的方法 + var md5 = HttpExtend.GetMD5String($"accept{user_id}"); + if (!(user.IsGetContactDic.ContainsKey(md5) && user.IsGetContactDic[md5])) + { + try + { + user.IsGetContactDic[md5] = true; + + Common.SetCache(md5, "", 5);//通知等待返回结果的方法 + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业自动通过添加响应缓存", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(md5); + } + } + #endregion + + var acctid = data["acctid"]?.ToString();//账号 + var avatar = data["avatar"]?.ToString();//头像 + var conversation_id = data["conversation_id"]?.ToString();//会话ID + var corp_id = data["corp_id"]?.ToString();//公司id + var mobile = data["mobile"]?.ToString();//公司id + var nickname = data["nickname"]?.ToString();//昵称 + var position = data["position"]?.ToString();//地址 + var realname = data["realname"]?.ToString();//真实名称 + var remark = data["remark"]?.ToString();//备注 + var sex = (int)data["sex"];//性别 + var unionid = data["unionid"]?.ToString(); + var username = data["username"]?.ToString();//微信昵称 + + WechatNewFriend msg = new WechatNewFriend(); + msg.FromUserName = user_id; + msg.Avatar = avatar; + msg.FromUserNick = username; + msg.Sex = sex; + + socketClient.Send(msg); + } + break; + case MsgType.MT_ACCEPT_FRIEND_REQUEST://接受加好友请求 + break; + case MsgType.MT_DEL_FRIEND_MSG: + case MsgType.MT_DEL_FRIEND_BY_MSG: + break; + case MsgType.MT_ROOM_MODIFY_NICK_MSG: + break; + case MsgType.MT_GET_OWN_QRIMAGE: + break; + case MsgType.MT_CDN_DOWN_MSG: + { + #region 数据结构 + //图片 + //{"data":{"error_code":0,"save_path":"D:\\项目\\秒单客项目\\返利机器人\\3.0\\yz_client\\yz_client\\yz_client\\bin\\Debug\\Cache\\Image\\1d7a78febfb843bb8ab77fd298aba1b5.jpg"},"type":11171} + + //视频 + //{"data":{"error_code":0,"save_path":"D:\\项目\\秒单客项目\\返利机器人\\3.0\\yz_client\\yz_client\\yz_client\\bin\\Debug\\Cache\\Image\\291d0e4442ee46a1a6cf3af21216863f.mp4"},"type":11171} + + #endregion + + if (user == null || data == null) + return; + + var hook = WechatClient.GetApi(user); + + var md5 = string.Empty; + try + { + var error_corde = data["error_code"].ToObject<int>(); + if (error_corde != 0) + throw new Exception($"Cdn下载异常:{recvData}"); + + var save_path = data["save_path"].ToString(); + md5 = HttpExtend.GetMD5String(save_path); + + try + { + user.IsGetContactDic[md5] = true; + } + catch (Exception) + { } + Common.SetCache(md5, 1, 5); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("企业微信解析Cdn消息", ex.Message); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(md5); + } + } + break; + case MsgType.MT_C2CCDN_DOWN_MSG: + { + #region 数据结构 + // {"data":{"error_code":0,"file_id":"3069020102046230600201000204bafc490e02031e903802040ac7f46d0204624ee2c20434333133373039353935305f31313832323539395f3631316535633864343430316166393935353530356432636437343665616238020100020300904004000201010201000400","save_path":"D:\\项目\\秒单客项目\\返利机器人\\3.0\\yz_client\\yz_client\\yz_client\\bin\\Debug\\Cache\\Image\\0b02274e4946420a97592bf07da6db6d.jpg"},"type":11170} + #endregion + + if (user == null || data == null) + return; + + var md5 = string.Empty; + try + { + var error_corde = data["error_code"].ToObject<int>(); + if (error_corde != 0) + throw new Exception($"Cdn下载异常:{recvData}"); + + var save_path = data["save_path"].ToString(); + md5 = HttpExtend.GetMD5String(save_path); + + try + { + user.IsGetContactDic[md5] = true; + } + catch (Exception) + { } + Common.SetCache(md5, 1, 5); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("企业微信解析C2cCdn消息", ex.Message); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(md5); + } + } + break; + case MsgType.MT_GETCDN_UPLOADFILE: + { + #region 数据结构 + //{"data":{"error_code":0,"file_aes_key":"34336366636637353562383135383465","file_id":"3072020102046b30690201000204f4287e6802030f59b102049317fa710204625050f7042d4e45574944315f6634323837653638393331376661373136323530353133375f3136343934333037373633303002010002030107d0041000fcd55383fba8807e1510efed058c400201010201000400","file_key":"1649430840411","file_md5":"00fcd55383fba8807e1510efed058c40","file_path":"D:\\项目\\秒单客项目\\返利机器人\\3.0\\yz_client\\yz_client\\yz_client\\bin\\Debug\\Cache\\Image\\3c78ef60613e43f1b5a369d528ce50b6.jpg","file_size":67523,"file_type":1,"image_height":960,"image_width":960},"type":11115} + #endregion + + if (user == null || data == null) return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + //有时候接收到的数据为一下情况 + //{"data":{"user_id":"7881302484994318"},"type":11039} + + var file_path = data["file_path"]?.ToString(); + var md5 = Path.GetFileNameWithoutExtension(file_path);//这里是之前传过来的以md5命名的文件名 + + if (user.IsGetContactDic.ContainsKey(md5) && user.IsGetContactDic[md5]) + return; + try + { + try + { + user.IsGetContactDic[md5] = true; + } + catch (Exception) + { } + + user.FileC2cCdnInfoDic[md5] = new FileC2cCdnInfo() + { + error_code = data["error_code"].ToObject<int>(), + file_aes_key = data["file_aes_key"].ToObject<string>(), + file_id = data["file_id"].ToObject<string>(), + file_key = data["file_key"].ToObject<string>(), + file_md5 = data["file_md5"].ToObject<string>(), + file_path = data["file_path"].ToObject<string>(), + file_size = data["file_size"].ToObject<int>(), + file_type = data["file_type"].ToObject<int>(), + image_height = data["image_height"].ToObject<int>(), + image_width = data["image_width"].ToObject<int>() + }; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业微信上传Cdn文件信息", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(md5); + } + } + break; + default: + break; + } + } + catch (Exception ex) + { + //Console.WriteLine("解析消息异常:" + ex.Message + "," + recvData); + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".._" + recvData); + } + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_."); + } + } + + private static ConcurrentDictionary<string, FriendInfo> FriendRequestRecord = new ConcurrentDictionary<string, FriendInfo>(); + + private static void WxCloseCallback(uint dwClientId) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == dwClientId && f.Value.Type == WechatType.Xiaoxie_QY).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"WxCloseCallbackQY关闭回调,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_.-"); + } + } + + private static void WxAcceptCallback(uint dwClientId) + { + Console.WriteLine("注入成功:" + dwClientId); + } + + /// <summary> + /// 启动微信 + /// </summary> + /// <param name="FileName"></param> + /// <returns></returns> + public static uint StartWechat(bool isError = false) + { + InitPc(); + + var WechatWinFile = HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + var md5 = Common.GetMD5Hash(WechatWinFile).ToUpper(); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + if (isError) throw new Exception("易转发客户端企业微信版本不支持,请登录易转发端手动处理"); + var _rst = MessageBox.Show("您的企业微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (_rst == DialogResult.Yes) + { + var f = new WechatUpdate(Version); + f.ShowDialog(); + if (!f.IsOk) return 0; + } + else return 0; + } + // 注入并多开 + //return InjectWxWork(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes("")); + + var path = HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + LogHelper.GetSingleObj().Debug("注入前", $"DPath = {DllPath},Path = {path}"); + return InjectWxWorkMultiOpen(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + } + } +} diff --git a/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Override.cs b/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Override.cs new file mode 100644 index 0000000..a895c2d --- /dev/null +++ b/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Override.cs @@ -0,0 +1,1294 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Entitys.Enterprise; +using PCRobot.Pack; +using PCRobot.Utils; + +namespace PCRobot.PCWechat.Enterprise +{ + public partial class Wechat_Xiaoxie_QY + { + public override void GetContact(bool isUpdata) + { + try + { + var result = GetExternalFirends().Result; + + var socketClient = EasySoc.GetSocket(); + CommonResult msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvFriendList_workWeChat; + msg.Data = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendMessage(string username, string message, string msgId = "", string usernick = "", string quoteMess = "") + { + try + { + //S:1688853956558440_7881301364988874 + //{"data":{"content":"我们","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"61","receiver":"1688853956558440","send_time":"1584028171","sender":"7881301364988874","sender_name":"18","server_id":"1000653"},"type":11041} + + var conversation_id = username; + if (!username.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{username}"; + } + else + { } + + var json = string.Empty; + message = message.Replace("\r\n", "\n"); + if (Common.isXML(message)) + { + message = message.Replace("&", "&"); + var title = string.Empty; + var desc = string.Empty; + var url = string.Empty; + var image_url = string.Empty; + var reg = Regex.Match(message, @"<title>(?<标题>[\w\W]+?)"); + if (reg.Success) title = reg.Groups["标题"].Value; + reg = Regex.Match(message, @"(?<介绍>[\w\W]+?)"); + if (reg.Success) desc = reg.Groups["介绍"].Value.Replace("(?<链接>[\w\W]+?)"); + if (!reg.Success) reg = Regex.Match(message, @"(?<链接>[\w\W]+?)"); + if (reg.Success) url = reg.Groups["链接"].Value; + reg = Regex.Match(message, @"(?<图片链接>[\w\W]+?)"); + if (reg.Success) image_url = reg.Groups["图片链接"].Value; + if (message.Contains("")) + { + var image_key1 = string.Empty; + var image_key2 = string.Empty; + var image_key3 = string.Empty; + var image_size = 0; + var ghid = string.Empty; + var pagepath = string.Empty; + var regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key1 = regKey.Groups["image_key1"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key2 = regKey.Groups["image_key2"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key3 = regKey.Groups["image_key3"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_size = int.Parse(regKey.Groups["image_size"].Value.XMLReplace(false)); + + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + ghid = regKey.Groups["username"].Value; + + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + pagepath = regKey.Groups["pagepath"].Value; + + var weapppagethumbrawurl = string.Empty; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + weapppagethumbrawurl = regKey.Groups["weapppagethumbrawurl"].Value; + + //小程序 + SendProgramMessage(conversation_id, ghid.XMLReplace(false), ghid.XMLReplace(false), title, image_url, desc, pagepath); + return; + } + else + { + image_url = + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_LINK_MSG, data = new { conversation_id = conversation_id, title = $"{title.XMLReplace(false)}", desc = $"{desc.XMLReplace(false)}", url = url.XMLReplace(false), image_url = image_url.XMLReplace(false) } }); + } + } + else + { + var atUsername = new List(); + var regs = Regex.Matches(message, @"\[@([^\]]+?)\]"); + if (regs.Count != 0 && username.IsQun()) + { + foreach (Match item in regs) + { + atUsername.Add(item.Groups[1].Value.Trim()); + } + message = Regex.Replace(message, @"(\[@[^\]]+?\])", "{$@}"); + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_ROOM_AT_MSG, data = new { conversation_id = conversation_id, content = message, at_list = atUsername.ToArray() } }); + } + else + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_TEXT_MSG, data = new { conversation_id = conversation_id, content = message } }); + } + SendWxWorkData(User.DwClientId, json); + + //LogHelper.GetSingleObj().Debug("发送状态", ($"发送:{conversation_id} - {flag}, 内容:{message}")); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "-."); + } + } + + public override void SendFile(string username, string file) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_FILE_MSG, data = new { conversation_id = GetConversationId(username), file = file } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void SendCard(string username, string cardwxid) + { + //群名片 + if (cardwxid.IsQun()) + { + if (!username.IsQun()) + InviteMemberToGroup(cardwxid, new string[] { username }); + return; + } + + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_PERSON_CARD_MSG, data = new { conversation_id = GetConversationId(username), share_user_id = cardwxid } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void SendLinkMessage(string username, string title, string desc, string url, string image_url) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_LINK_MSG, data = new { conversation_id = GetConversationId(username), url = url, image_url = image_url, title = title, desc = desc } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void SendImage(string wxid, string file) + { + //var json = string.Empty; + //if (imgPath.EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase | StringComparison.OrdinalIgnoreCase)) + // json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_GIF_MSG, data = new { conversation_id = GetConversationId(username), file = imgPath } }); + //else + // json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = GetConversationId(username), file = imgPath } }); + //SendWxWorkData(User.DwClientId, json); + + try + { + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + conversation_id = $"S:{User.Wxid}_{wxid}"; + + if (file.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + byte[] ImangByte = null; + string extension = Path.GetExtension(file); + extension = string.IsNullOrWhiteSpace(extension) ? ".jpg" : extension; + ImangByte = new System.Net.WebClient().DownloadData(file); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + + var path = Common.CacheFilePath(User.Wxid, conversation_id, "IMAGE", Guid.NewGuid().ToString("N"), extension); + if (!File.Exists(path)) + { + File.WriteAllBytes(path, ImangByte); + } + if (File.Exists(path)) + file = path; + } + else + { + if (!File.Exists(file)) + { + if (Common.IsBase64(file)) + { + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), "jpg"); + if (Common.Base64ToFileAndSave(file, path) && File.Exists(path)) + { + file = path; + } + } + else + { } + } + } + + var json = string.Empty; + if (File.Exists(file)) + { + if (file.Trim().EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase)) + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_GIF_MSG, data = new { conversation_id = conversation_id, file = file } }); + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = conversation_id, file = file } }); + } + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = conversation_id, file = file } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Debug("发送图片异常", ex.Message + ".-" + ex.StackTrace); + } + + } + + public override void SendVideo(string username, string path) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_VIDEO_MSG, data = new { conversation_id = GetConversationId(username), file = path } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void ModifyGroupNotice(string groupid, string notice) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MOD_ROOM_NOTICE_MSG, data = new { room_conversation_id = GetConversationId(groupid), notice = notice } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void Ser_CreateGroup(string[] usernames) + { + var result = CreateGroup(usernames).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CreateRoom(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCreateRoom_workWeChat; + msg.GroupId = result?.GroupId; + msg.MemberTotal = 0; + socketClient.Send(msg); + } + + public override Task CreateGroup(string[] usernames) + { + if (usernames != null && usernames.Length != 0) + { + try + { + var type = RobotIsRunType.创建群; + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetDic.ContainsKey(type)) + { + User.IsGetDic[type] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_CREATE_ROOM_MSG, data = usernames }); + SendWxWorkData(User.DwClientId, json); + } + + var result = Task.Factory.StartNew(delegate () + { + var keyMd5 = HttpExtend.GetMD5String($"CACHE_CREATEGROUP{type}"); + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetDic.ContainsKey(type))//等到解析完消息,解析完消息IsGetDic中的消息会被删除 + { + var createGroupInfo = Common.GetCache(keyMd5); + Common.RemoveCache(keyMd5); + return createGroupInfo; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业获取创建群信息", ex.Message); + } + } + return null; + } + + public override void DeleteGroupMember(string groupid, string[] usernames) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ROOM_DEL_MEMBERS_MSG, data = new { conversation_id = groupid, user_list = usernames } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void QuitAndDelGroup(string groupid) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_QUIT_ROOM, data = new { room_conversation_id = GetConversationId(groupid) } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void ModifyGroupName(string groupid, string newName) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MODIFY_ROOM_NAME_MSG, data = new { conversation_id = groupid, name = newName } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void Ser_GetSelfInfo() + { + var result = GetSelfInfo().Result; + var data = string.Empty; + if (result != null) + data = HttpHelper.ObjectToJson(result as WorkFriendInfo); + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + + public override Task GetSelfInfo() + { + try + { + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(User.Wxid)) + { + User.IsGetContactDic[User.Wxid] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_GET_OWNER_INFO_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetContactDic.ContainsKey(User.Wxid) && User.IsGetContactDic[User.Wxid])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(User.Wxid))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + { + if (User.WorkFriends.ContainsKey(User.Wxid)) + return User.WorkFriends[User.Wxid]; + return null; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业获取自己基础信息", ex.Message); + } + return null; + } + + /// + /// 获取群或者好友信息 + /// + /// + public override void Ser_GetContact(string username) + { + var data = string.Empty; + + if (User.WorkFriends.ContainsKey(username)) + data = HttpHelper.ObjectToJson(User.WorkFriends[username]); + else + { + + if (username.IsQun()) + { + var g = GetGroupInfos().Result; + if (User.WorkFriends.ContainsKey(username)) + data = HttpHelper.ObjectToJson(User.WorkFriends[username]); + } + else + { + var result = GetFriendInfo(username).Result; + if (result != null) + data = HttpHelper.ObjectToJson((result as WorkFriendInfo)); + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = data; + + socketClient.Send(msg); + } + + public override Task GetFriendInfo(string username) + { + try + { + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(username)) + { + User.IsGetContactDic[username] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_GET_USER_DETAIL_MSG, data = new { user_id = username } }); + SendWxWorkData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetContactDic.ContainsKey(username) && User.IsGetContactDic[username])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(username))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + { + if (User.WorkFriends.ContainsKey(username)) + return User.WorkFriends[username]; + return null; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业获取单个用户信息", ex.Message); + } + + return null; + } + + public override void GetFriendInfo(string userName, string groupId, bool IsFlush = false) + { + var result = Task.Factory.StartNew(() => + { + try + { + if (string.IsNullOrWhiteSpace(userName)) return null; + if (string.IsNullOrWhiteSpace(groupId)) return null; + + if (IsFlush) + { + var gInfo = GetGroupMemberInfo(groupId).Result; + if (gInfo == null) return null; + var g = gInfo as WorkGroupInfo; + if (g == null) return null; + + var ftmp = g.friends.FirstOrDefault(f => f.user_id == userName); + if (ftmp != null) + return new WorkGroupInfo() { conversation_id = groupId, friends = new List() { ftmp }, total = User.WorkGroups[groupId].total, GroupNick = User.WorkGroups[groupId].GroupNick }; + } + if (User.WorkGroups.ContainsKey(groupId)) + { + if (User.WorkGroups[groupId].friends == null) return null; + var ftmp = User.WorkGroups[groupId].friends.FirstOrDefault(f => f.user_id == userName); + if (ftmp != null) + return new WorkGroupInfo() { conversation_id = groupId, friends = new List() { ftmp }, total = User.WorkGroups[groupId].total, GroupNick = User.WorkGroups[groupId].GroupNick }; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业获取群用户信息", ex.Message); + } + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + + public override Task> GetGroupInfos() + { + try + { + var type = RobotIsRunType.获取群列表; + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetDic.ContainsKey(type)) + { + User.IsGetDic[type] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_GET_ROOMS_MSG, data = new { page_num = 1, page_size = 100000 } }); + SendWxWorkData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetDic.ContainsKey(type))//等到解析完消息,解析完消息IsGetDic中的消息会被删除 + { + Dictionary dic = new Dictionary(); + if (User.WorkGroups != null) + { + foreach (var item in User.WorkGroups) + { + dic.Add(item.Key, item.Value); + } + } + return dic; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业获取所有群组列表", ex.Message); + } + return Task.FromResult>(null); + } + + public override Task GetGroupMemberInfo(string groupid) + { + try + { + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(groupid)) + { + User.IsGetContactDic[groupid] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_GET_ROOM_MEMBERS_MSG, data = new { conversation_id = groupid, page_num = 1, page_size = 100000 } }); + SendWxWorkData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + try + { + if (User.IsGetContactDic.ContainsKey(groupid) && User.IsGetContactDic[groupid])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(groupid))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + { + if (User.WorkGroups.ContainsKey(groupid)) + return User.WorkGroups[groupid]; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + } + catch (Exception ex) + { } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业获取指定群组成员信息", $"群:{groupid} - {ex.Message} - {ex.StackTrace}"); + } + return Task.FromResult(null); + } + + public override void OutLogin() + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_QUIT_LOGIN_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void OutLogin(string message) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == User.DwClientId && f.Value.Type == WechatType.Xiaoxie_QY).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"CloseWechatQY事件退出,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v, true); + if (!string.IsNullOrWhiteSpace(message)) + PCRobotForm.ErrorMessAction?.Invoke(message); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "//"); + } + } + + public override string GetVersion() + { + return Version; + } + + public override void SendDirectory(string username, string dirPath) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_FOLDER_MSG, data = new { conversation_id = GetConversationId(username), folder = dirPath } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void SendProgramMessage(string username, string msg) + { + //new { data = new { conversation_id = username, ghid = ghid, wxid = wxid, name = name, title = title, enterpoint = enterpoint, headimg = headimg, image_key1 = image_key1, image_key2 = image_key2, image_key3 = image_key3, image_size = image_size } } + + var jObj = JObject.Parse(msg); + var data = jObj["data"]; + + var conversation_id = data["conversation_id"].ToString(); + var ghid = data["ghid"].ToString(); + var wxid = data["wxid"].ToString(); + var name = data["name"].ToString(); + var title = data["title"].ToString(); + var enterpoint = data["enterpoint"].ToString(); + var headimg = data["headimg"].ToString(); + + SendProgramMessage(username, ghid, wxid, name, headimg, title, enterpoint); + } + + private void SendProgramMessage(string username, string appUsername, string appId, string appName, string appicon, string title, + string page_path) + { + try + { + #region 数据结构 + /* + { + "type":11162, + "data":{ + "conversation_id":"S:168885xxx28682_788130xxxx912998", + + "username":"gh_52b46203a658@app", + "appid":"wx35f2a3937c9df889", + "appname":"博鸟绘本", + "appicon":"http:\/\/wx.qlogo.cn\/mmhead\/Q3auHgzwzM42Aa6BAq7rguLCx66IVTm7Qibr6paWic3rl9bfalX7gQLw\/96", + "title":"博鸟绘本,最新最全的儿童绘本租赁平台~", + "page_path":"pages\/shouye\/shouye.html", + + + // cdn参数为小程序封面,可以从cdn上传图片处获得 + "file_id":"3069020102046230600201000204283cabaa02030f424102043c986eb4020461967039042431376332326538612d656533342d346537642d623531332d37393762376436336531663702010002030ec8700410059b34e084cf19a38a92a677177863d20201010201000400", + "aes_key":"61393132623366353662313133653735", + "md5":"059b34e084cf19a38a92a677177863d2", + "size": 11122 + } + } + */ + #endregion + + FileC2cCdnInfo cdn = GetCdnByUpLoadFile(appicon, 1).Result; + if (cdn == null) + throw new Exception("小程序图片获取Cdn失败"); + + var _json = JsonConvert.SerializeObject(new { type = Wechat_Xiaoxie_QY.MsgType.MT_SEND_MINI_PROGRAM_MSG, data = new { conversation_id = GetConversationId(username), username = appUsername, appid = appId, appName = appName, appicon = appicon, title = title, page_path = page_path, file_id = cdn.file_id, aes_key = cdn.file_aes_key, md5 = cdn.file_md5, size = cdn.file_size } }); + + SendWxWorkData(User.DwClientId, _json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, $"发送小程序:{ex.Message}"); + } + } + + public override void SendVideoHao(string username, string avatar, string cover_url, string desc, int feed_type, string nickname, + string thumb_url, string url, string extras) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_VIDEOHAO_MSG, data = new { conversation_id = GetConversationId(username), cover_url = cover_url, desc = desc, feed_type = feed_type, nickname = nickname, thumb_url = thumb_url, url = url, extras = extras } }); + + SendWxWorkData(User.DwClientId, json); + } + + public override void TransRoom(string username, string user_id) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_TRANS_ROOM_MSG, data = new { room_conversation_id = GetConversationId(username), user_id = user_id } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void OnOffRoomInvite(string username, bool status) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DISABLE_INVITEROOMCONFIRM_MSG, data = new { room_conversation_id = GetConversationId(username), status = status ? 1 : 0 } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void OnOffRoomModNick(string username, bool status) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DISABLE_MODROOMNICK_MSG, data = new { room_conversation_id = GetConversationId(username), status = status ? 1 : 0 } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void InviteMemberToGroup(string groupid, string[] usernames) + { + if (groupid.IsQun()) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ROOM_ADD_MEMBERS_MSG, data = new { conversation_id = groupid, user_list = usernames } }); + SendWxWorkData(User.DwClientId, json); + } + } + + public override void AddGroupMemberToFriend(string groupid, string username, string corp_id, string verify) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ADD_ROOM_USER_MSG, data = new { room_conversation_id = groupid, user_id = username, corp_id = corp_id, verify = verify } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void ModifyFriendRemark(string username, string remark) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MODIFY_USER_REMARK_MSG, data = new { user_id = username, remark = remark } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void ModifyFriendDesc(string username, string desc) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MODIFY_USER_DESC_MSG, data = new { user_id = username, desc = desc } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void ModifyFriendPhone(string username, string[] phone_list) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MODIFY_EXTERNAl_USER_PHONES_MSG, data = new { user_id = username, phone_list = phone_list } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void ModifyExternalFriendCompanyNick(string username, string company) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MODIFY_EXTERNAl_USER_COMPANY_MSG, data = new { user_id = username, company = company } }); + SendWxWorkData(User.DwClientId, json); + } + + public override Task SearchContactMobile(string search) + { + try + { + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(search)) + { + User.IsGetContactDic[search] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEARCH_USER_MSG, data = new { keyword = search } }); + SendWxWorkData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + try + { + if (User.IsGetContactDic.ContainsKey(search) && User.IsGetContactDic[search])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(search))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + { + if (User.FriendHandlerDic.ContainsKey(search)) + { + var SeartchFriendInfo = User.FriendHandlerDic[search]; + //if (SeartchFriendInfo == null)//如果搜索的时候为空,就直接删除 + User.FriendHandlerDic.Remove(search);//处理完直接删除 + return SeartchFriendInfo; + } + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + } + catch (Exception ex) + { } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业搜索用户信息信息", $"搜索:{search} - {ex.Message} - {ex.StackTrace}"); + } + return Task.FromResult(null); + } + + public override void AddRoutineSearchContact(string username, string openid, string wx_ticket, string verify) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ADD_SEARCH_USER_MSG, data = new { user_id = username, openid = openid, wx_ticket = wx_ticket, verify = verify } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void AddEnterpriseSearchContact(string username, string corp_id, string verify) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ADD_SEARCH_E_USER_MSG, data = new { user_id = username, corp_id = corp_id, verify = verify } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void AddCardFriendContact(string username, string corp_id, string from_user_id, string verify) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ADD_CARDFRIEND_MSG, data = new { user_id = username, corp_id = corp_id, from_user_id = from_user_id, verify = verify } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void AddDelFriendContact(string username, string corp_id, string verify) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ADD_DELFRIEND_MSG, data = new { user_id = username, corp_id = corp_id, verify = verify } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void DeleteFriend(string username) + { + var ftmp = User.WorkFriends.FirstOrDefault(f => f.Key == username).Value; + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DEL_FRIEND, data = new { user_id = username, corp_id = ftmp != null ? ftmp.corp_id : "0" } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void AcceptFriend(string msg) + { + try + { + var reg = Regex.Match(msg, @"{""user_id"":""(?[^""]+?)"",""corp_id"":""(?[^""]+?)""}"); + if (reg.Success) + { + var user_id = reg.Groups["user_id"].Value; + var corp_id = reg.Groups["corp_id"].Value; + + var json = JsonConvert.SerializeObject(new + { + type = MsgType.MT_ACCEPT_FRIEND_REQUEST, + data = new { user_id = user_id, corp_id = corp_id } + }); + SendWxWorkData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"接受好友申请", ex.Message); + } + } + + public override Task CreateExternalGroup() + { + try + { + var type = RobotIsRunType.创建空外部群; + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetDic.ContainsKey(type)) + { + User.IsGetDic[type] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_CREATE_NULL_ROOM_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + var keyMd5 = HttpExtend.GetMD5String($"CACHE_CREATEGROUP{type}"); + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetDic.ContainsKey(type))//等到解析完消息,解析完消息IsGetDic中的消息会被删除 + { + var createGroupInfo = Common.GetCache(keyMd5); + Common.RemoveCache(keyMd5); + return createGroupInfo; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业获取创建群信息", ex.Message); + } + return Task.FromResult(null); + } + + //public override Task> GetInnerFirends() + //{ + // try + // { + // var type = RobotIsRunType.获取内部好友列表; + // //这里判断是否已经存在在获取所有好友信息,没有就去获取 + // if (!User.IsGetDic.ContainsKey(type)) + // { + // User.IsGetDic[type] = false;//这里添加要查询类型,状态为flase(还没收到微信那边返回的数据) + // var json = JsonConvert.SerializeObject(new { type = MsgType.MT_GET_INNER_USERS_MSG, data = new { page_num = 1, page_size = 100000 } }); + // SendWxWorkData(User.DwClientId, json); + // } + + // return Task.Factory.StartNew>(delegate () + // { + // DateTime endtime = DateTime.Now.AddSeconds(20); + // do + // { + // if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + // { + // do + // { + // if (!User.IsGetDic.ContainsKey(type))//等到解析完消息,解析完消息IsGetDic中的消息会被删除 + // {//这里只返回外部的好友 + // if (FriendDic != null) + // { + // var innerFirends = FriendDic.Where(f => f.Value.FriendType == EnterpriseFriendType.内部好友).ToDictionary(f => f.Key, z => z.Value); + // return innerFirends; + // } + // return FriendDic; + // } + // Thread.Sleep(200); + // } while (endtime > DateTime.Now); + // break; + // } + // Thread.Sleep(20); + // } while (endtime > DateTime.Now); + // return null; + // }); + // } + // catch (Exception ex) + // { + // LogHelper.GetSingleObj().Error($"企业获取内部好友列表", ex.Message); + // } + // return Task.FromResult>(null); + //} + + public override Task> GetExternalFirends() + { + try + { + var type = RobotIsRunType.获取好友列表; + //这里判断是否已经存在在获取所有好友信息,没有就去获取 + if (!User.IsGetDic.ContainsKey(type)) + { + User.IsGetDic[type] = false;//这里添加要查询类型,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_GET_EXTERNAL_USERS_MSG, data = new { page_num = 1, page_size = 100000 } }); + SendWxWorkData(User.DwClientId, json); + } + + return Task.Factory.StartNew>(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetDic.ContainsKey(type)) //等到解析完消息,解析完消息IsGetDic中的消息会被删除 + { + if (User.WorkFriends != null) + { + return User.WorkFriends; + } + return null; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取外部好友列表", ex.Message); + } + return Task.FromResult>(null); + } + + //public override Task GetOwnQrImage() + //{ + // try + // { + // var type = RobotIsRunType.获取自己的二维码; + // //这里判断是否已经存在在获取所有好友信息,没有就去获取 + // if (!User.IsGetDic.ContainsKey(type)) + // { + // QrImageInfo = null; + // User.IsGetDic[type] = false;//这里添加要查询类型,状态为flase(还没收到微信那边返回的数据) + // var json = JsonConvert.SerializeObject(new { type = MsgType.MT_GET_OWN_QRIMAGE, data = new { } }); + // SendWxWorkData(User.DwClientId, json); + // } + + // return Task.Factory.StartNew(delegate () + // { + // DateTime endtime = DateTime.Now.AddSeconds(20); + // do + // { + // if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + // { + // do + // { + // if (!User.IsGetDic.ContainsKey(type))//等到解析完消息,解析完消息IsGetDic中的消息会被删除 + // return QrImageInfo; + // Thread.Sleep(200); + // } while (endtime > DateTime.Now); + // break; + // } + // Thread.Sleep(20); + // } while (endtime > DateTime.Now); + // return null; + // }); + // } + // catch (Exception ex) + // { + // LogHelper.GetSingleObj().Error($"获取自己二维码", ex.Message); + // } + // return Task.FromResult(null); + //} + + public override void FlushLoginQrImage() + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_FLUSH_LOGINQRIMAGE_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + } + + public override void DissolveGroup(string GroupId) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DISSOLVE_ROOM, data = new { room_conversation_id = GetConversationId(GroupId) } }); + SendWxWorkData(User.DwClientId, json); + } + + public override Task CdnDown(string url, string auth_key, string aes_key, int size, FileSuffixType fileSuffixType) + { + #region 数据结构 + /* + { + "type":11171, + "data":{ + "url":"https:\/\/imunion.weixin.qq.com\/cgi-bin\/mmae-bin\/tpdownloadmedia?param=v1_84d696afdc73fbf997931c6eb898facc4830ae5cb891060fdd5cca540beccd2de56cbc84207058d80f2af266f925e458ca19263f710bc0905881589f0b816c5def9bb2a039e0127bb680b6f3c8db2f93abf477d369374598cea92a001adf3f5977ba47cfa347643a36b05f96c4fa54ebc7f4f00767a0ba2a859ac82b6c0e9efacd07eb5c15c098837f4a19f27a0a897a890394f88ae7dd215f75e4199ac4c5e9c893358e5aee215a07ac0882aad2e72e249cacaaf0e2929ebf15dc147fceb386f8560923cba106cea3f5c0548ace640455df853ab7606f6e88acf48cdcb9593d7873c487536327e8988d969a360da527c09d7765dfc382ed98071720c3b3ba108cc2c3504907d095575676333a64ae6a2fdf9a2af2138e1c0d953a56d6a3c281348a7e71fd10f7b80220e4b4a4c1473ac5f00e07d132ad000289d96bd8abc40a", + "auth_key":"v1_84d696afdc73fbf997931c6eb898facc4830ae5cb891060fdd5cca540beccd2d2d7fa866eb7f785638f4c69ac9c904a43685d48a39b7162bbab469dc884dd1e8", + "aes_key":"9385a744af20cba0e59a52d51e3cacd1", + "size":16504, + "save_path":"e:\\cdn\\3.jpg" + } + } + */ + #endregion + + return CdnDown(Common.CreateNewFilePath(fileSuffixType), url, auth_key, aes_key, size); + } + + public override Task CdnDown(string url, string auth_key, string aes_key, int size, string fileName) + { + var filePath = HttpExtend.MapFile(fileName, $"Cache\\Other"); + return CdnDown(filePath, url, auth_key, aes_key, size); + } + + /// + /// Cdn实际处理的地方 + /// + /// + /// + private Task CdnDown(string save_path, string url, string auth_key, string aes_key, int size) + { + try + { + var md5 = HttpExtend.GetMD5String(save_path); + + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(md5)) + { + User.IsGetContactDic[md5] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_CDN_DOWN_MSG, data = new { url = url, auth_key = auth_key, aes_key = aes_key, size = size, save_path = save_path } }); + SendWxWorkData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetContactDic.ContainsKey(md5) && User.IsGetContactDic[md5])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(md5)) //等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + //return Common.GetCache(md5) ? save_path : null; + return save_path; + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return save_path; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业Cdn下载", ex.Message); + } + return Task.FromResult(save_path); + } + + + public override Task C2cCdnDown(string aes_key, string file_id, int file_size, QyCdnFileType file_type, FileSuffixType fileSuffixType) + { + return C2cCdnDown(Common.CreateNewFilePath(fileSuffixType), aes_key, file_id, file_size, file_type); + } + + private Task C2cCdnDown(string save_path, string aes_key, string file_id, int file_size, QyCdnFileType file_type) + { + #region 第一版,请求以后返回的数据异常..现在用第二版,等修复以后可以使用第一版 + //try + //{ + // var md5 = HttpExtend.GetMD5String(save_path); + + // //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + // if (!IsGetContactDic.ContainsKey(md5)) + // { + // IsGetContactDic[md5] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + // var json = JsonConvert.SerializeObject(new { type = MsgType_QY.MT_C2CCDN_DOWN_MSG, data = new { aes_key = aes_key, file_id = file_id, save_path = save_path, file_size = file_size, file_type = (int)file_type } }); + // SendClient(CoreRobotMsgEnum.Cdn文件下载, json); + // } + + // return Task.Factory.StartNew(delegate () + // { + // DateTime endtime = DateTime.Now.AddSeconds(20); + // do + // { + // if (IsGetContactDic.ContainsKey(md5) && IsGetContactDic[md5])//等待收到微信查询的消息 + // { + // do + // { + // if (!IsGetContactDic.ContainsKey(md5))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + // return CacheClient.SigleClient.Cache.ContainsKey(md5) ? save_path : null; + // Thread.Sleep(200); + // } while (endtime > DateTime.Now); + // break; + // } + // Thread.Sleep(20); + // } while (endtime > DateTime.Now); + // return null; + // }); + //} + //catch (Exception ex) + //{ + // LogHelper.WriteLog($"企业小程序图片Cdn下载", ex); + //} + //return null; + #endregion + + #region 第二版 + + try + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_C2CCDN_DOWN_MSG, data = new { aes_key = aes_key, file_id = file_id, save_path = save_path, file_size = file_size, file_type = (int)file_type } }); + SendWxWorkData(User.DwClientId, json); + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(10); + do + { + if (File.Exists(save_path)) + return save_path; + Thread.Sleep(500); + } while (endtime > DateTime.Now); + return save_path; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业小程序图片Cdn下载", ex.Message); + } + #endregion + return Task.FromResult(save_path); + } + + + public override Task BigCdnDown(string file_path, string file_type) + { + //SendWxWorkData(User.DwClientId, json); + return null; + } + + public override Task GetCdnByUpLoadFile(string file_path, int file_type) + { + try + { + var md5 = HttpExtend.GetMD5String(file_path); + + if (User.FileC2cCdnInfoDic.ContainsKey(md5)) + return Task.FromResult(User.FileC2cCdnInfoDic[md5]); + + var imgPathTmp = Common.CreateNewFilePath(FileSuffixType.jpg, md5); + + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(md5)) + { + if (Common.DownFile(file_path, imgPathTmp)) //这里下载文件的名称以传入的文件本地路径或Url的md5,在收到回调后以这个为依据 + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_GETCDN_UPLOADFILE, data = new { file_path = imgPathTmp, file_type = file_type } }); + SendWxWorkData(User.DwClientId, json); + } + else + throw new Exception("传递的文件信息无法解析,终止获取文件Cdn"); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetContactDic.ContainsKey(md5) && User.IsGetContactDic[md5])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(md5))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + { + if (User.FileC2cCdnInfoDic.ContainsKey(md5)) + return User.FileC2cCdnInfoDic[md5]; + return null; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"企业上传文件获取Cdn信息", ex.Message); + } + return Task.FromResult(null); + } + } +} diff --git a/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Type.cs b/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Type.cs new file mode 100644 index 0000000..a74bd99 --- /dev/null +++ b/PCRobot/PCWechat/Enterprise/Wechat_Xiaoxie_QY_Type.cs @@ -0,0 +1,545 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.PCWechat.Enterprise +{ + public partial class Wechat_Xiaoxie_QY + { + #region 内部类 + + public enum MsgType + {/// + /// 接口准备完毕 + /// + MT_APP_READY_MSG = 11024, + /// + /// 参数错误提示 + /// + MT_PARAMS_ERROR_MSG = 11025, + /// + /// 登录消息 + /// + MT_USER_LOGIN = 11026, + /// + /// 注销消息通知 + /// + MT_USER_LOGOUT = 11027, + /// + /// 登录二维码 + /// + MT_LOGIN_QRCODE_MSG = 11028, + /// + /// 发送文本消息 + /// + MT_SEND_TEXT_MSG = 11029, + /// + /// 发送图片消息 + /// + MT_SEND_IMAGE_MSG = 11030, + /// + /// 发送文件消息 + /// + MT_SEND_FILE_MSG = 11031, + /// + /// 发送目录消息 + /// + MT_SEND_FOLDER_MSG = 11032, + ///// + ///// 发送链接消息 + ///// + //MT_SEND_LINK_MSG = 11033, + ///// + ///// 发送个人名片 + ///// + //MT_SEND_PERSON_CARD_MSG = 11034, + /// + /// 获取自己信息 + /// + MT_GET_OWNER_INFO_MSG = 11035, + /// + /// 获取内部联系人列表 + /// + MT_GET_INNER_USERS_MSG = 11036, + /// + /// 获取外部联系列表 + /// + MT_GET_EXTERNAL_USERS_MSG = 11037, + /// + /// 获取群聊列表 + /// + MT_GET_ROOMS_MSG = 11038, + /// + /// 获取用户详细信息 + /// + MT_GET_USER_DETAIL_MSG = 11039, + /// + /// 获取群成员列表 + /// + MT_GET_ROOM_MEMBERS_MSG = 11040, + /// + /// 接收文本消息 + /// + MT_RECV_TEXT_MSG = 11041, + /// + /// 接收图片消息 + /// + MT_RECV_IMG_MSG = 11042, + /// + /// 接收视频消息 + /// + MT_RECV_VIDEO_MSG = 11043, + /// + /// 接收语音消息 + /// + MT_RECV_VOICE_MSG = 11044, + /// + /// 接收文件消息 + /// + MT_RECV_FILE_MSG = 11045, + /// + /// 接收位置消息 + /// + MT_RECV_LOCATION_MSG = 11046, + /// + /// 接收链接消息 + /// + MT_RECV_LINK_CARD_MSG = 11047, + /// + /// 接收表情消息 + /// + MT_RECV_EMOTION_MSG = 11048, + /// + /// 接收红包消息 + /// + MT_RECV_RED_PACKET_MSG = 11049, + /// + /// 接收个人名片消息 + /// + MT_RECV_PERSON_CARD_MSG = 11050, + /// + /// 接收其他未解析消息 + /// + MT_RECV_OTHER_MSG = 11051, + /// + /// 查询联系人 + /// + MT_SEARCH_USER_MSG = 11052, + /// + /// 添加查询的联系人 + /// + MT_ADD_SEARCH_USER_MSG = 11053, + /// + /// 修改用户备注 + /// + MT_MODIFY_USER_REMARK_MSG = 11054, + /// + /// 修改用户描述 + /// + MT_MODIFY_USER_DESC_MSG = 11055, + /// + /// 修改外部联系人手机号 + /// + MT_MODIFY_EXTERNAl_USER_PHONES_MSG = 11056, + /// + /// 修改外部联系人公司 + /// + MT_MODIFY_EXTERNAl_USER_COMPANY_MSG = 11057, + /// + /// 创建群聊 + /// + MT_CREATE_ROOM_MSG = 11058, + /// + /// 修改群名 + /// + MT_MODIFY_ROOM_NAME_MSG = 11059, + /// + /// 添加群成员 + /// + MT_ROOM_ADD_MEMBERS_MSG = 11060, + /// + /// 删除群成员 + /// + MT_ROOM_DEL_MEMBERS_MSG = 11061, + /// + /// 接收好友请求 + /// + MT_RECV_FRIEND_REQUEST = 11063, + /// + /// 接受加好友请求 + /// + MT_ACCEPT_FRIEND_REQUEST = 11064, + ///// + ///// 发送小程序 + ///// + //MT_SEND_MINI_PROGRAM_MSG = 11065, + /// + /// 接收到小程序 + /// + MT_RECV_MINIAPP_MSG = 11066, + /// + /// 发送视频 + /// + MT_SEND_VIDEO_MSG = 11067, + /// + /// 接收图文消息 + /// + MT_RECV_IMAGE_TEXT_MSG = 11068, + /// + /// 发送群@消息 + /// + MT_SEND_ROOM_AT_MSG = 11069, + /// + /// 发送动图(gif)消息 + /// + MT_SEND_GIF_MSG = 11070, + /// + /// 添加群成员为联系人 + /// + MT_ADD_ROOM_USER_MSG = 11071, + /// + /// 群成员新增通知 + /// + MT_ROOM_ADD_MEMBER_NOTIFY_MSG = 11072, + /// + /// 剔除群成员通知 + /// + MT_ROOM_DEL_MEMBER_NOTIFY_MSG = 11073, + /// + /// 新群通知 + /// + MT_ROOM_CREATE_NOTIFY_MSG = 11074, + /// + /// 群成员主动退出通知 + /// + MT_ROOM_MEMBER_QUIT_NOTIFY_MSG = 11075, + /// + /// 好友新增通知 + /// + MT_CONTACT_ADD_NOITFY_MSG = 11076, + /// + /// 好友删除通知 + /// + MT_DEL_FRIEND_MSG = 11077, + /// + /// 被删除通知 + /// + MT_DEL_FRIEND_BY_MSG = 11173, + /// + /// 群昵称修改通知 + /// + MT_ROOM_MODIFY_NICK_MSG = 11078, + /// + /// 修改群公告 + /// + MT_MOD_ROOM_NOTICE_MSG = 11082, + /// + /// 添加查询的企业联系人 + /// + MT_ADD_SEARCH_E_USER_MSG = 11088, + /// + /// 转让群主 + /// + MT_TRANS_ROOM_MSG = 11090, + /// + /// 登录成功通知(包含公司名) + /// + MT_USER_LOGIN_CORP = 11179, + /// + /// 发送视频号 + /// + MT_SEND_VIDEOHAO_MSG = 11172, + /// + /// 发送链接消息 + /// + MT_SEND_LINK_MSG = 11159, + /// + /// 发送个人名片 + /// + MT_SEND_PERSON_CARD_MSG = 11161, + /// + /// 创建空外部群 + /// + MT_CREATE_NULL_ROOM_MSG = 11125, + /// + /// 开启关闭配置邀请群确定 + /// + MT_DISABLE_INVITEROOMCONFIRM_MSG = 11108, + /// + /// 开启关闭配置修改群名 + /// + MT_DISABLE_MODROOMNICK_MSG = 11089, + /// + /// 退出群聊 + /// + MT_QUIT_ROOM = 11105, + /// + /// 删除联系人 + /// + MT_DEL_FRIEND = 11111, + /// + /// 获取自己的二维码 + /// + MT_GET_OWN_QRIMAGE = 11122, + /// + /// 接收撤回消息 + /// + MT_RECV_REVOKE_MSG = 11123, + /// + /// 退出登录 + /// + MT_QUIT_LOGIN_MSG = 11112, + /// + /// 解散群 + /// + MT_DISSOLVE_ROOM = 11130, + /// + /// 添加删除的联系人 + /// + MT_ADD_DELFRIEND_MSG = 11152, + /// + /// 刷新扫码登录二维码 + /// + MT_FLUSH_LOGINQRIMAGE_MSG = 11153, + /// + /// 添加卡片用户 + /// + MT_ADD_CARDFRIEND_MSG = 11121, + /// + /// 发送小程序 + /// + MT_SEND_MINI_PROGRAM_MSG = 11162, + /// + /// C2cCdn下载消息 + /// + MT_C2CCDN_DOWN_MSG = 11170, + /// + /// Cdn下载消息 + /// + MT_CDN_DOWN_MSG = 11171, + /// + /// 登录二维码状态通知 + /// + MT_SCAN_QRSTATE_MSG = 11174, + /// + /// 上传文件获取文件Cdn + /// + MT_GETCDN_UPLOADFILE = 11115, + } + + //public enum MsgType : ushort + //{ + // /// + // /// 接口准备完毕 + // /// + // MT_APP_READY_MSG = 11024, + // /// + // /// 参数错误提示 + // /// + // MT_PARAMS_ERROR_MSG = 11025, + // /// + // /// 登录消息 + // /// + // MT_USER_LOGIN = 11026, + // /// + // /// 注销消息 + // /// + // MT_USER_LOGOUT = 11027, + // /// + // /// 登录二维码 + // /// + // MT_LOGIN_QRCODE_MSG = 11028, + // /// + // /// 发送文本消息 + // /// + // MT_SEND_TEXT_MSG = 11029, + // /// + // /// 发送图片消息 + // /// + // MT_SEND_IMAGE_MSG = 11030, + // /// + // /// 发送文件消息 + // /// + // MT_SEND_FILE_MSG = 11031, + // /// + // /// 发送目录消息 + // /// + // MT_SEND_FOLDER_MSG = 11032, + // /// + // /// 发送链接消息 + // /// + // MT_SEND_LINK_MSG = 11033, + // /// + // /// 发送个人名片 + // /// + // MT_SEND_PERSON_CARD_MSG = 11034, + // /// + // /// 获取自己信息 + // /// + // MT_GET_OWNER_INFO_MSG = 11035, + // /// + // /// 获取内部联系人列表 + // /// + // MT_GET_INNER_USERS_MSG = 11036, + // /// + // /// 获取外部联系列表 + // /// + // MT_GET_EXTERNAL_USERS_MSG = 11037, + // /// + // /// 获取群聊列表 + // /// + // MT_GET_ROOMS_MSG = 11038, + // /// + // /// 获取用户详细信息 + // /// + // MT_GET_USER_DETAIL_MSG = 11039, + // /// + // /// 获取群成员列表 + // /// + // MT_GET_ROOM_MEMBERS_MSG = 11040, + // /// + // /// 接收文本消息 + // /// + // MT_RECV_TEXT_MSG = 11041, + // /// + // /// 接收图片消息 + // /// + // MT_RECV_IMG_MSG = 11042, + // /// + // /// 接收视频消息 + // /// + // MT_RECV_VIDEO_MSG = 11043, + // /// + // /// 接收语音消息 + // /// + // MT_RECV_VOICE_MSG = 11044, + // /// + // /// 接收文件消息 + // /// + // MT_RECV_FILE_MSG = 11045, + // /// + // /// 接收位置消息 + // /// + // MT_RECV_LOCATION_MSG = 11046, + // /// + // /// 接收链接消息 + // /// + // MT_RECV_LINK_CARD_MSG = 11047, + // /// + // /// 接收表情消息 + // /// + // MT_RECV_EMOTION_MSG = 11048, + // /// + // /// 接收红包消息 + // /// + // MT_RECV_RED_PACKET_MSG = 11049, + // /// + // /// 接收个人名片消息 + // /// + // MT_RECV_PERSON_CARD_MSG = 11050, + // /// + // /// 接收其他未解析消息 + // /// + // MT_RECV_OTHER_MSG = 11051, + // /// + // /// 查询联系人 + // /// + // MT_SEARCH_USER_MSG = 11052, + // /// + // /// 添加查询的联系人 + // /// + // MT_ADD_SEARCH_USER_MSG = 11053, + // /// + // /// 修改用户备注 + // /// + // MT_MODIFY_USER_REMARK_MSG = 11054, + // /// + // /// 修改用户描述 + // /// + // MT_MODIFY_USER_DESC_MSG = 11055, + // /// + // /// 修改外部联系人手机号 + // /// + // MT_MODIFY_EXTERNAl_USER_PHONES_MSG = 11056, + // /// + // /// 修改外部联系人公司 + // /// + // MT_MODIFY_EXTERNAl_USER_COMPANY_MSG = 11057, + // /// + // /// 创建群聊 + // /// + // MT_CREATE_ROOM_MSG = 11058, + // /// + // /// 修改群名 + // /// + // MT_MODIFY_ROOM_NAME_MSG = 11059, + // /// + // /// 添加群成员 + // /// + // MT_ROOM_ADD_MEMBERS_MSG = 11060, + // /// + // /// 删除群成员 + // /// + // MT_ROOM_DEL_MEMBERS_MSG = 11061, + // /// + // /// 接收好友请求 + // /// + // MT_RECV_FRIEND_REQUEST = 11063, + // /// + // /// 接受加好友请求 + // /// + // MT_ACCEPT_FRIEND_REQUEST = 11064, + // /// + // /// 发送小程序 + // /// + // MT_SEND_MINI_PROGRAM_MSG = 11065, + // /// + // /// 接收到小程序 + // /// + // MT_RECV_MINIAPP_MSG = 11066, + // /// + // /// 发送视频 + // /// + // MT_SEND_VIDEO_MSG = 11067, + // /// + // /// 接收图文消息 + // /// + // MT_RECV_IMAGE_TEXT_MSG = 11068, + // /// + // /// 发送群@消息 + // /// + // MT_SEND_ROOM_AT_MSG = 11069, + // /// + // /// 发送动图(gif)消息 + // /// + // MT_SEND_GIF_MSG = 11070, + // /// + // /// 添加群成员为联系人 + // /// + // MT_ADD_ROOM_USER_MSG = 11071, + // /// + // /// 群成员新增通知 + // /// + // MT_ROOM_ADD_MEMBER_NOTIFY_MSG = 11072, + // /// + // /// 剔除群成员通知 + // /// + // MT_ROOM_DEL_MEMBER_NOTIFY_MSG = 11073, + // /// + // /// 新群通知 + // /// + // MT_ROOM_CREATE_NOTIFY_MSG = 11074, + // /// + // /// 群成员主动退出通知 + // /// + // MT_ROOM_MEMBER_QUIT_NOTIFY_MSG = 11075, + // /// + // /// 好友新增通知 + // /// + // MT_CONTACT_ADD_NOITFY_MSG = 11076, + //} + #endregion + } +} diff --git a/PCRobot/PCWechat/Routine/WechatRoutineBase.cs b/PCRobot/PCWechat/Routine/WechatRoutineBase.cs new file mode 100644 index 0000000..dc9d75b --- /dev/null +++ b/PCRobot/PCWechat/Routine/WechatRoutineBase.cs @@ -0,0 +1,610 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Utils; + +namespace PCRobot.PCWechat.Routine +{ + /// + /// 个人微信基类 + /// + public abstract class WechatRoutineBase : WechatBase + { + + /// + /// 是否初始化 + /// + internal static bool IsInstall { get; set; } + + public WechatRoutineBase(WechatUser User) : base(User) { } + + #region 发送操作 + + ///// + ///// 发送小程序 - 接收到的小程序消息id + ///// + ///// 接收者的微信 + ///// 发送 + //public abstract void SendProgramMessage(string username, string msgid); + + /// + /// 发送Xml(自己拼接Xml)【发送操作】 + /// + /// 发给谁 + /// Xml消息 + /// 自定义来源 + public abstract void SendXml(string username, string xml, string customSource = "Window wechat"); + + /// + /// 发送名片XML原始消息[可用于检验僵尸粉] + /// + /// + /// + public abstract void SendCardXml(string username, string xml); + + /// + /// 发送引用消息 + /// + /// 发送给谁 + /// 发送的内容 + /// 消息的类型 + /// 引用的内容 + /// 引用的消息id + /// 引用的用户账号 + /// 引用的账号昵称 + /// + public abstract void SendQuoteMessage(string username, string replyMess, WechatMsgType messageType, + string quoteMess, string quoteMsgid, string quoteUsername, string quoteUsernick); + + /// + /// 发送链接(卡片) + /// + /// 接收者的账号 + /// 链接标题 + /// 链接描述 + /// 链接地址 + /// 链接图片URL + /// 自定义来源 + public abstract void SendLinkMessage(string username, string title, string desc, string url, string imageUrl, + string customSource); + + #endregion + + #region 群操作 + + /// + /// 邀请用户进群(40人以下,不用用户同意)【群操作】 + /// + /// 群ID + /// 被邀请的用户账号集 + /// + public abstract void InviteMemberToGroup_40Down(string groupid, string[] usernames); + + /// + /// 邀请用户进群(40人以上,需要用户同意)【群操作】 + /// + /// 群ID + /// 被邀请的用户账号集 + public abstract void InviteMemberToGroup_40Up(string groupid, string[] usernames); + + /// + /// 修改自己在所群里的昵称【群操作】 + /// + /// 群ID + /// 新昵称 + /// + public abstract void ModifyGroupMyNick(string groupid, string newNick); + + /// + /// 自动同意进群邀请 + /// + /// 0是取消自动,1自动 + /// + public abstract void AutoAcceptGroup(bool isAuto); + + /// + /// 是否显示群成员昵称【群操作】 + /// + /// 群ID + /// 0不显示,1显示 + /// + public abstract void ModifyGroupShowNick(string groupid, bool isShow); + + /// + /// 群[保存到/移除]通讯录【群操作】 + /// + /// 群ID + /// 0移出通讯录,1保存到通讯录 + /// + public abstract void SaveGroupToContact(string groupid, bool status); + + public abstract void GetGroupsNotInMember(); + + /// + /// 检测僵尸粉 + /// + public abstract void CheckZombiz(); + + ///// + ///// 获取群用户邀请 + ///// + ///// 群ID + //public abstract Dictionary GetGroupMemberInvite(string groupid); + #endregion + + #region 转发消息操作 + + /// + /// 转发任意类型消息【转发消息操作】 + /// + /// 接收者的账号 + /// 转发的msgid + public abstract void ForwardAny(string username, string msgid); + #endregion + + #region 获取收藏列表 + + ///// + ///// 获取收藏列表【收藏消息类】 + ///// + //public abstract Task> GetCollects(); + + ///// + ///// 发送收藏【收藏消息类】 + ///// + ///// 接收者的账号 + ///// 收藏列表中local_id的值 + ///// + //public abstract void SendCollect(string username, string local_id); + + ///// + ///// 添加收藏【收藏消息类】 + ///// + ///// 接收到的消息ID + ///// + //public abstract void AddCollect(string msgid); + + #endregion + + #region 语音处理类 + + /// + /// 语音消息转文本【语音处理类】 + /// + /// 接收到的消息id + /// + public abstract string TransVoice(string msgid); + + #endregion + + #region 群和好友操作 + + /// + /// 开启/关闭消息免打扰【群和好友操作】 + /// + /// 好友账号或群ID + /// 0是关闭,1是开启 + /// + public abstract void ModifyRecvNotify(string username, bool status); + + /// + /// 置顶/取消置顶聊天【群和好友操作】 + /// + /// 好友账号或群ID + /// 0是关闭,1是开启 + /// + public abstract void ModifyChatTop(string username, bool status); + #endregion + + #region 公众号操作类 + + /// + /// 关注公众号【公众号操作类】 + /// + /// 公众号账号 + /// 添加来源,可为空 + /// + public abstract void AddPublicUser(string username, string source_type = ""); + #endregion + + #region 好友操作 + + /// + /// 添加好友【好友操作】 + /// + /// 用户账号 + /// 备注 + /// 来源 + /// 6:好友验证,这里可加之前加过的人; + /// 14:群聊,加群好友必须是群聊 + /// 17:名片分享,username需要传v1数据 + /// + /// 来自哪个群,可空 + /// + public abstract void AddFriend(string username, string remark, int source_type, string groupid); + + ///// + ///// 删除好友【好友操作】 + ///// + ///// 删除用户的账号 + ///// + //public abstract void DeleteFriend(string username); + + ///// + ///// 接受加好友请求【好友操作】 + ///// + ///// xml消息中encryptusername + ///// xml消息中ticket + ///// xml消息中scene + ///// + //public abstract Task AcceptFriend(string username, string encryptusername, string ticket, string scene); + + /// + /// 接受好友转账【好友操作】 + /// + /// xml消息中transferid + /// + public abstract void AcceptFriendTransfer(string data); + + /// + /// 退回好友转账【好友操作】 + /// + /// xml消息中transferid + /// + public abstract void RefuseFriendTransfer(string transferid); + + /// + /// 接受好友的进群邀请【好友操作】 + /// + /// 邀请人的账号 + /// 邀请的链接 + /// + public abstract void AcceptFriendInviteToGroup(string username, string inviteUrl); + + /// + /// 单向加好友(当不需要验证时)【好友操作】 + /// + /// 要加的好友账号 + /// + public abstract void AddOnewayFriend(string username); + + #endregion + + #region 基础消息 + + + /// + /// 获取所有用户信息【基础消息】 + /// + /// + public abstract Task> GetFriendInfos(); + + ///// + ///// 获取所有公众号信息【基础消息】 + ///// + ///// + //public abstract Task> GetPublicInfos(); + + /// + /// 网络获取个人信息【基础消息】 + /// + /// 要刷新信息的用户账号 + /// + public abstract Task UpdateFriendInfo(string username); + + /// + /// 网络获取群成员信息【基础消息】 + /// + /// 群ID + /// + public abstract void UpdateGroupMemberInfo(string groupid); + + #endregion + + #region 无痕清粉类 + + /// + /// 检测僵尸粉 + /// 0 正常状态(不是僵尸粉) + /// 1 检测为僵尸粉(对方把我拉黑了) + /// 2 检测为僵尸粉(对方把我从他的好友列表中删除了) + /// 3 检测为僵尸粉(原因未知, 如遇到3请反馈给我) + /// + /// 要检测的用户账号 + /// + public abstract Task CheckZombie(string username); + #endregion + + #region 自动处理类 + + /// + /// 自动同意加好友申请 + /// + /// 0是取消自动,1自动 + /// + public abstract void AutoAcceptFriend(bool isAuto); + + /// + /// 自动接受好友转账 + /// + /// 0是取消自动,1自动 + /// + public abstract void AutoAcceptFriendTransfer(bool isAuto); + + /// + /// 自动加好友分享的名片 + /// + /// 0是取消自动,1自动 + /// + public abstract void AutoAcceptCard(bool isAuto); + #endregion + + #region 解密文件类 + + /// + /// 解密微信加密的图片(.dat) + /// + /// 微信加密图片路径(.dat) + /// 解密后的文件路径(.jpg) + public abstract void DecryptImage(string src_file, string dest_file); + #endregion + + #region 浏览器类 + + /// + /// 打开内置的浏览器 + /// + /// 要打开的地址 + public abstract void OpenBrowser(string url); + #endregion + + #region 界面相关类 + + /// + /// 获取未读取消息数量 + /// + /// + public abstract Task GetUnReadMsgCount(); + + /// + /// 设置消息为已读 + /// + /// 用户账号 + public abstract void SetMsgReaded(string username); + + /// + /// 打开好友的聊天窗口(切换当前会话) + /// + /// 用户账号 + public abstract void ToChatWindow(string username); + + /// + /// 清理历史聊天记录 + /// + public abstract void ClearChatHistoryMsg(); + #endregion + + #region 防撤回类 + + /// + /// 开启/关闭防撤回功能 + /// + /// 1是开启防撤回,0是关闭 + /// + public abstract void DisableRevoke(bool status); + #endregion + + #region 二维码识别类 + + ///// + ///// 微信二维码识别接口(小程序码,普通二维码) + ///// + ///// 二维码图片地址 + ///// + //public abstract Task ScanQrCode(string file); + #endregion 特殊接口类 + + #region 特殊接口类 + + ///// + ///// 通过手机号/微信号/QQ号查询任意微信号信息 + ///// + ///// 搜索的内容 + ///// + //public abstract Task SearchContact(string search); + + /// + /// 添加搜索到的用户 + /// + /// 搜索到的信息v1 + /// 搜索到的信息v2 + /// 添加好友附加内容 + /// 来源通过微信号搜索添加是3,手机号是15 + /// + public abstract void AddSearchContact(string v1, string v2, string remark, int source_type); + + /// + /// 用户账号查询详细信息 + /// + /// 要查询的用户账号(wxid) + /// + public abstract void GerFriendDetails(string username); + + /// + /// 检查Url在微信中是否有效 + /// + /// 要检查的url地址 + /// + public abstract void CheckUrlStatus(string url); + + #endregion + + #region 朋友圈类 + + /// + /// 发送服务端_浏览朋友圈 + /// + /// + /// + /// + public abstract void Ser_GetCircles(string max_id = "0", string username = ""); + + /// + /// 浏览朋友圈 + /// + /// 首页传0,后续的最后一个朋友圈的object_id + /// 查看某个用户朋友圈,可为空 + /// + public abstract Task GetCircles(string max_id = "0", string username = ""); + + /// + /// 朋友圈点赞 + /// + /// 朋友圈的object_id + /// + public abstract void CircleLink(string object_id); + + /// + /// 朋友圈评论 + /// + /// 朋友圈的object_id + /// 评论内容 + /// + public abstract void CircleComment(string object_id, string content); + + /// + /// 朋友圈上传本地图片 + /// + /// + public abstract void CircleUpLoadImage(string imgData); + + /// + /// 发朋友圈 + /// + /// 朋友圈xml + /// + public abstract void SendCircle(string object_desc); + #endregion + + /// + /// 小程序自动授权登录 + /// + /// 小程序id + public abstract void AutoAuthMiniAPPLogin(string appid); + + public string FindNick(string wxid) + { + try + { + if (string.IsNullOrWhiteSpace(wxid)) return string.Empty; + + if (wxid.IsQun())//为群账号,就获取群昵称 + { + if (!User.Groups.ContainsKey(wxid)) + { + var ggi = this.GetGroupInfos().Result;//获取群信息 + if (ggi != null && ggi.Count != 0) + { + if (ggi.ContainsKey(wxid)) + return (ggi[wxid] as GroupInfo).nickname; + } + } + if (User.Groups.ContainsKey(wxid)) + { + if (string.IsNullOrWhiteSpace(User.Groups[wxid].nickname)) + { + var ggi = this.GetGroupInfos().Result;//获取群信息 + if (ggi != null && ggi.Count != 0) + { + if (ggi.ContainsKey(wxid)) + return (ggi[wxid] as GroupInfo).nickname; + } + } + return User.Groups[wxid].nickname; + } + } + else + { + if (!User.Friends.ContainsKey(wxid)) + { + var friend = GetFriendInfo(wxid).Result; + if (friend != null) + return friend.nickname; + } + var ftmp = User.Friends.FirstOrDefault(f => f.Key == wxid).Value; + if (ftmp != null) + return ftmp.nickname; + } + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 获取群成员昵称 + /// + /// 群号 + /// 需要查找的用户账号 + /// + public string FindNick(string group, string wxid) + { + try + { + if (string.IsNullOrWhiteSpace(wxid)) return string.Empty; + + var ftmp = User.Friends.FirstOrDefault(f => f.Key == wxid).Value; + if (ftmp != null)//如果好友列表中存在就直接读取 + return ftmp.nickname; + else + { + if (string.IsNullOrWhiteSpace(group)) return string.Empty; + + var gtmp = User.Groups.FirstOrDefault(f => f.Key == group).Value; + if (gtmp == null) + { + var gInfo = this.GetGroupMemberInfo(group).Result; + //if (gInfo != null && gInfo.FriendDic != null && gInfo.FriendDic.ContainsKey(wxid)) + if (gInfo != null) + { + var g = gInfo as GroupInfo; + if (g != null && g.friends != null && g.friends.Count != 0) + { + ftmp = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (ftmp != null) + { + return ftmp.nickname; + } + } + } + } + + gtmp = User.Groups.FirstOrDefault(f => f.Key == group).Value; + if (gtmp != null) + { + var friendDic = gtmp.friends; + if (friendDic != null) + { + ftmp = friendDic.FirstOrDefault(f => f.wxid == wxid); + if (ftmp != null) + return ftmp.nickname; + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + + + } +} diff --git a/PCRobot/PCWechat/Routine/Wechat_Xiaoxie.cs b/PCRobot/PCWechat/Routine/Wechat_Xiaoxie.cs new file mode 100644 index 0000000..523268e --- /dev/null +++ b/PCRobot/PCWechat/Routine/Wechat_Xiaoxie.cs @@ -0,0 +1,463 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; +using CsharpHttpHelper; +using Newtonsoft.Json; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.PCWechat.Enterprise; +using PCRobot.Utils; +using static PCRobot.PCWechat.Routine.Wechat_Xiaoxie_Type; + +namespace PCRobot.PCWechat.Routine +{ + public partial class Wechat_Xiaoxie : WechatRoutineBase + { + public Wechat_Xiaoxie(WechatUser User) : base(User) + { + } + + public delegate void OnEvent(string Name, string Message); + public static OnEvent ClickEvent; + + #region 静态函数 + public static void Install() + { + if (IsInstall) return; + + #region 自动登录新建设备信息,注册表开关 + try + { + if (Version == "3.4.0.38") + { + string Winrarpath = @"Software\Tencent\WeChat"; + string key = "FakeDeviceId"; + //yes为开,no为关 + RegistryHelper.SetRegistryKey("HKEY_CURRENT_USER", Winrarpath, key, "no"); + RegistryHelper.GetRegistryValue(Winrarpath, key); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("自动登录新建设备信息", $"注册表操作异常:{ex.Message} - {ex.StackTrace}"); + } + #endregion + + ClickEvent?.Invoke("开始登录", "正在检测已登录微信,请稍等...."); + try + { + //Thread.Sleep(5000); + //DllPath = HttpExtend.MapFile($"WeChatHelper_{Version}.dll", "Bin"); + m_AcceptCallbackFunc = WxAcceptCallback; + m_RecvCallbackFunc = WxRecvCallback; + m_CloseCallbackFunc = WxCloseCallback; + UseUtf8(); + // 初始化Callback + InitWeChatSocket(m_AcceptCallbackFunc, m_RecvCallbackFunc, m_CloseCallbackFunc); + + DllPath = HttpExtend.MapFile($"WeChatHelper_{Version}.dll", "Bin"); + KillPc(true); + } + catch (Exception) + { + + } + finally + { + IsInstall = true; + ClickEvent?.Invoke("登录完成", ""); + } + } + + private static string DllPath; + /// + /// 微信WeChatWin.dll基址 + /// + //private static IntPtr BaseAddress; + + public delegate void AcceptCallbackFunc(uint dwClientId); + public delegate void RecvCallbackFunc(uint dwClientId, IntPtr intPtr, uint dwSize); + public delegate void CloseCallbackFunc(uint dwClientId); + private static AcceptCallbackFunc m_AcceptCallbackFunc; + private static RecvCallbackFunc m_RecvCallbackFunc; + private static CloseCallbackFunc m_CloseCallbackFunc; + + // 引入DLL导出函数 + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool InitWeChatSocket(AcceptCallbackFunc acceptCallback, + RecvCallbackFunc recvCallback, CloseCallbackFunc closeCallback); + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChat(byte[] strDllPath); + //[DllImport("Bin\\WeChatServer.dll")] + //public static extern bool SetLoginWxid(byte[] szWxid); + + //BOOL __stdcall UseUtf8(); + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool UseUtf8(); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool GetUserWeChatVersion(StringBuilder v); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChat2(byte[] dllPath, byte[] wechatPath); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChatMultiOpen(byte[] dllPath, byte[] wechatPath); + + [DllImport("Bin\\WeChatServer.dll", EntryPoint = "SendWeChatData")] + public static extern bool _SendWeChatData(uint dwClienId, byte[] strJsonData); + public bool SendWeChatData(uint dwClienId, string strJsonData) + { + try + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试发送", $"{dwClienId} -> {strJsonData}"); + if (User != null && !string.IsNullOrEmpty(User.Wxid)) + { + var json = HttpExtend.JsonToDictionary(strJsonData); + var type = json["type"].ToString(); + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return false; + switch (msgType) + { + //截取发送消息 - 为是否是辅助输入提供判断 + case MsgType.MT_SEND_TEXTMSG: + case MsgType.MT_SEND_CHATROOM_ATMSG: + case MsgType.MT_SEND_CARDMSG: + case MsgType.MT_SEND_XMLMSG: + case MsgType.MT_SEND_IMGMSG: + case MsgType.MT_SEND_FILEMSG: + case MsgType.MT_SEND_VIDEOMSG: + case MsgType.MT_SEND_GIFMSG: + { + json = json["data"] as Dictionary; + string to_wxid = json["to_wxid"].ToString(); + string message = string.Empty; + if (json.ContainsKey("content")) message = json["content"].ToString(); + else if (json.ContainsKey("card_wxid")) message = json["card_wxid"].ToString(); + else if (json.ContainsKey("xml")) message = json["xml"].ToString(); + else if (json.ContainsKey("file")) message = json["file"].ToString(); + if (!string.IsNullOrEmpty(message)) + Common.SetCache(User.Wxid, to_wxid, message); + } + break; + } + } + return _SendWeChatData(dwClienId, Encoding.UTF8.GetBytes(strJsonData)); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, $"{ex.Message} - {ex.StackTrace}"); + } + return false; + } + + //[DllImport("Bin\\WeChatServer.dll")] + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool DestroyWeChat(); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChatPid(int dwPid, byte[] dllPath); + + /// + /// 卸载安装 + /// + public static void UnInstall() + { + try + { + DestroyWeChat(); + LogHelper.GetSingleObj().Info(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "卸载成功"); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + #region 微信版本基础变量 + + //private const string Version = "2.9.5.41"; + //private const int PcOffSet = 0x1769E00;//2.9.5.41 + //private const string PcMd5 = "194F44DF80553326711A4F576FE7166E";//2.9.5.41 + + //private const string Version = "3.3.0.93"; + //private const int PcOffSet = 0x1DAEB90;//3.3.0.93 + //private const string PcMd5 = "5EE8A5B9D4EE63BE1813632D8A7B2E77";//3.3.0.93 + + private const string Version = "3.4.0.38"; + private const int PcOffSet = 0x1DEE968;//3.4.0.38 + private const string PcMd5 = "AB0916C9949178A786192B188892AE2C";//3.4.0.38 + #endregion + + /// + /// 杀死注入 pc + /// + /// + private static void KillPc(bool isInject = false) + { + Process[] MyProcesses = Process.GetProcesses(); + + var path1 = HttpExtend.MapPath("PCWechat"); + var path2 = HttpExtend.MapPath("PCWechat\\" + Version); + //var path3 = HttpExtend.MapPath("PCWechat\\" + "3.3.0.93");//退出上个版本的微信 + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == "WECHAT" && MyProcess.MainModule.FileName.StartsWith(path1)) + { + try + { + #region 退掉这个版本的微信 + //if (MyProcess.MainModule.FileName.StartsWith(path3)) + //{ + // try + // { + // LogHelper.GetSingleObj().Info("主动Q", "版本不对杀死进程:" + MyProcess.Id); + // MyProcess.Kill(); + // } + // catch (Exception) + // { } + //} + #endregion + + //判断微信版本 + if (MyProcess.MainModule.FileName.StartsWith(path2)) + { + var id = MyProcess.Id; + if (isInject) + { + var result = Task.Factory.StartNew(delegate + { + try + { + var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + return false; + } + else + { + LogHelper.GetSingleObj().Info("系统", $"开始注入进程:{id}..."); + uint uin = InjectWeChatPid(id, Encoding.UTF8.GetBytes(DllPath)); + LogHelper.GetSingleObj().Info("系统", $"注入成功:{id},句柄ID:{uin}"); + return true; + } + } + catch (Exception) + { + } + return false; + }).Wait(30000); + if (!result) + { + try + { + LogHelper.GetSingleObj().Info("系统c", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + else + { + try + { + LogHelper.GetSingleObj().Info("主动d", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + Thread.Sleep(10); + } + + } + catch (Exception) + { } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } + + public static uint StartWechat(string wxid, bool isError = false) + { + var path = string.Empty; + + var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5.ToUpper() != PcMd5.ToUpper()) + { + if (isError) throw new Exception("易转发客户端微信版本不支持,请登录易转发端手动处理"); + var rst = MessageBox.Show("您的微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + var f = new WechatUpdate(Version); + f.ShowDialog(); + if (!f.IsOk) return 0; + } + else return 0; + } + path = HttpExtend.MapFile("WeChat.exe", $"PCWechat\\" + Version); + + //WechatLoginHelper.BeginLogin(wxid); + + //var ss = SetLoginWxid(Encoding.UTF8.GetBytes("")); + //返回dwClientId + var pid = InjectWeChat2(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + + //WechatLoginHelper.ClickLogin((int)pid); + + return pid; + + //return InjectWeChatMultiOpen(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + } + + /// + /// 远程登录微信 + /// + public static List RemoteLoginCodes = new List(); + + /// + /// 是否在获取二维码 + /// + private static string RemoteCache = "get_login_code_cache"; + + /// + /// pc微信登录二维码 + /// + /// + public static void LoginQrcode(string wxid, string ServerMsgID) + { + try + { + RemoteLoginCode result = null; + try + { + StartWechat(wxid, true); + } + catch (Exception ex) + { + result = new RemoteLoginCode() { pid = -1, rType = RobotType.客户端微信, b64Md5 = ex.Message }; + } + + if (result == null) + { + result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[RemoteCache]; + if (item != null) + { + cache.Remove(RemoteCache); + var r = item as RemoteLoginCode; + return r; + } + } while (awaitTime >= DateTime.Now); + return null; + }).Result; + } + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = string.Empty; + msg.RobotUsernick = string.Empty; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvLoginCode; + msg.Data = result == null ? string.Empty : JsonConvert.SerializeObject(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 等待登录结果 + /// + public static Dictionary WaitLoginResult = new Dictionary(); + + /// + /// 本地解密dat图片 + /// + /// + /// + /// + public static string DecodeImage(string FileName, byte XorKey, string DecodeImagePath) + { + var data = File.ReadAllBytes(FileName); + for (int i = 0; i < data.Length; i++) + data[i] = Convert.ToByte(data[i] ^ XorKey); + //var path = FileName.Replace(Path.GetFileName(FileName), Path.GetFileNameWithoutExtension(FileName) + ".jpg"); + File.WriteAllBytes(DecodeImagePath, data); + return DecodeImagePath; + } + + /// + /// 获取微信的uin的值 + /// + /// + /// + public static string GetUin(int pid) + { + try + { + Process[] processes = Process.GetProcesses(); + foreach (Process process in processes) + { + if (process.Id == pid) + { + foreach (ProcessModule processModule in process.Modules) + { + if (processModule.ModuleName == "WeChatWin.dll") + { + //微信基址 + var WeChatWinBaseAddress = processModule.BaseAddress; + //Console.WriteLine("微信基址:\t" + "0x" + ((int)(processModule.BaseAddress)).ToString("X8") + Environment.NewLine); + var WxNameAddress = WeChatWinBaseAddress + PcOffSet; + var uinStr = Common.GetString(process.Handle, WxNameAddress, 4); + //Console.WriteLine($"uinStr = {uinStr}"); + return uinStr; + } + } + break; + } + } + } + catch (Exception) + { } + return string.Empty; + } + + + + #endregion + + } +} \ No newline at end of file diff --git a/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Analysis.cs b/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Analysis.cs new file mode 100644 index 0000000..62fb4b4 --- /dev/null +++ b/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Analysis.cs @@ -0,0 +1,1568 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Utils; +using static PCRobot.PCWechat.Routine.Wechat_Xiaoxie_Type; + +namespace PCRobot.PCWechat.Routine +{ + public partial class Wechat_Xiaoxie + { + // 接收消息回调 + static void WxRecvCallback(uint dwClient, IntPtr intPtr, uint dwSize) + { + try + { + byte[] body = new byte[dwSize]; + Marshal.Copy(intPtr, body, 0, body.Length); + var recvData = Encoding.UTF8.GetString(body).Replace("\0", "").Trim();//再转成UTF8 + if (WechatClient.IsDebug) LogHelper.GetSingleObj().Debug("调试收到文本消息", $"{dwClient} -> {recvData}\r\n"); + + //Console.WriteLine($"{dwClient} -> {recvData}\r\n"); + + var dwClientid = dwClient; + Task.Factory.StartNew(delegate () + { + try + { + //Console.WriteLine("收到消息:" + recvData); + var jObj = JObject.Parse(recvData); + if (jObj == null) return; + var type = jObj["type"].ToString(); + + var data = jObj.ContainsKey("data") ? jObj["data"] : null; + + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return; + + if (PCRobotForm.AnalysisTypes != null && PCRobotForm.AnalysisTypes.Count != 0) + { + if (PCRobotForm.AnalysisTypes.FirstOrDefault(f => f == msgType.ToString().ToUpper()) == null) + return; + } + + WechatUser user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + + switch (msgType) + { + case MsgType.MT_SEND_XMLMSG: + break; + case MsgType.MT_DECRYPT_IMG_MSG: + break; + case MsgType.MT_DEBUG_LOG: + break; + case MsgType.MT_RECV_QRCODE_MSG: + { + //{"data":{"code":"http://weixin.qq.com/x/A98qrQOk3qB6L_fWPtxF","file":"C:\\Users\\????006\\AppData\\Local\\Temp\\qrcF451.tmp","pid":24088},"type":11087} + if (data == null || data["file"] == null) return; + var file = data["file"].ToString(); + + var reg = Regex.Match(file, @"Temp\\(?<文件名>[a-z0-9A-Z]+.tmp)", RegexOptions.IgnoreCase); + if (reg.Success) + { + var codeFile = HttpExtend.MapFile($"{reg.Groups["文件名"].Value}", Path.GetTempPath()); + if (File.Exists(codeFile)) + { + var pid = int.Parse(data["pid"].ToString()); + var codeFilePng = Path.ChangeExtension(codeFile, "png"); + try + { + if (File.Exists(codeFilePng)) + File.Delete(codeFilePng); + File.Move(codeFile, codeFilePng); + if (File.Exists(codeFilePng)) + { + var cfBase64 = Common.ConvertImageToBase64(Image.FromFile(codeFilePng)); + + var codeInfo = new RemoteLoginCode() { pid = pid, cImgB64 = cfBase64, b64Md5 = HttpHelper.ToMD5(cfBase64), rType = RobotType.客户端微信, t = HttpExtend.GetTimeStamp(DateTime.Now) }; + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[RemoteCache]; + cache.Insert(RemoteCache, codeInfo, null, DateTime.Now.AddSeconds(3), Cache.NoSlidingExpiration); + + RemoteLoginCodes.Add(codeInfo); + } + } + catch (Exception) + { } + } + } + } + break; + case MsgType.MT_USER_LOGIN://登陆消息 + { + WechatLoginHelper.EndBinginLogin(); + + + var wxid = data["wxid"].ToString(); + + user = WechatClient.GetUser(wxid, dwClientid, WechatType.Xiaoxie); + + var client = WechatClient.GetApi(user); + var friendInfo = (client as Wechat_Xiaoxie).UpdateFriendInfo(wxid).Result; + + + user.Nickname = (friendInfo != null && !string.IsNullOrWhiteSpace(friendInfo.nickname)) ? friendInfo.nickname : data["nickname"].ToString(); + user.HeaderUrl = data["avatar"].ToString(); + user.DBFile = data["wx_user_dir"].ToString(); + user.Pid = int.Parse(data["pid"].ToString()); + user.Phone = data["phone"].ToString(); + user.Uin = GetUin(user.Pid); + + WechatClient.OnRefUserEvent(user, WaitLoginResult); + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试登录", $"{wxid} - {user}"); + } + break; + case MsgType.MT_USER_LOGOUT: + { + var wxid = data["wxid"].ToString(); + user = WechatClient.Users.FirstOrDefault(f => f.Key == wxid).Value; + if (user != null) + { + LogHelper.GetSingleObj().Info("系统", $"LogOut事件退出,Uin:{user.Uin},微信:{user.Nickname}({wxid})"); + WechatClient.RemoveUser(user); + } + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试注销", $"{wxid} - {user}"); + } + break; + case MsgType.MT_SQL_QUERY: + break; + case MsgType.MT_DATA_OWNER_MSG: + break; + case MsgType.MT_DATA_WXID_MSG: + { + //{"data":{"account":"MOKA_1314_","avatar":"http://wx.qlogo.cn/mmhead/ver_1/UKuQPgzLzEY0UPqTgmqpSibLmx1BMibAlwJxOp4t8QksClGJP8tLHxUiaBDAax1Vf0Eiae6wKBIoT3ibAgOYTuuWiaVDiaiayiaaIZF46LcE5aBvTtSQ/132","city":"Chengdu","country":"CN","nickname":"进销存","province":"Sichuan","remark":"","sex":2,"wxid":"wxid_va4xpj22"},"type":11029} + + if (data == null || user == null) + return; + + //{"data":{"account":"MOKA_1314_","avatar":"http://wx.qlogo.cn/mmhead/ver_1/UKuQPgzLzEY0UPqTgmqpSibLmx1BMibAlwJxOp4t8QksClGJP8tLHxUiaBDAax1Vf0Eiae6wKBIoT3ibAgOYTuuWiaVDiaiayiaaIZF46LcE5aBvTtSQ/132","city":"Chengdu","country":"CN","nickname":"进销存","province":"Sichuan","remark":"","sex":2,"wxid":"wxid_va4xpj22"},"type":11029} + var username = data["wxid"]?.ToString(); + if (username.IsGzh()) return; + + if (user.IsGetContactDic.ContainsKey(username) && user.IsGetContactDic[username]) + return; + + try + { + try + { + user.IsGetContactDic[username] = true; + } + catch (Exception) + { } + + var wxid = data["wxid"]?.ToString(); + if (Common.IsGzh(wxid, WechatClient.IsGzh)) return; + + var f = new FriendInfo(); + + f.account = data["account"]?.ToString(); + f.wxid = wxid; + f.nickname = data["nickname"]?.ToString(); + f.remark = data["remark"]?.ToString(); + f.avatar = data["avatar"]?.ToString(); + f.city = data["city"]?.ToString(); + f.country = data["country"]?.ToString(); + f.province = data["province"]?.ToString(); + f.sex = int.Parse(data["sex"]?.ToString()); + + user.Friends[f.wxid] = f; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"个人微信解析群用户信息", ex.Message); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(username); + } + } + break; + case MsgType.MT_DATA_FRIENDS_MSG: + { + if (data == null || user == null) + return; + + var _type = RobotIsRunType.获取好友列表; + if (user.IsGetDic.ContainsKey(_type)) + { + if (user.IsGetDic[_type]) + return; + } + + try + { + user.IsGetDic[_type] = true; + + var jArr = (JArray)data; + for (int i = 0; i < jArr.Count; i++) + { + var item = jArr[i]; + + var wxid = item["wxid"]?.ToString(); + + if (wxid.IsGzh(WechatClient.IsGzh)) continue; + + var f = new FriendInfo(); + f.wxid = wxid; + f.account = item["account"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.sex = int.Parse(item["sex"]?.ToString()); + f.city = item["city"]?.ToString(); + + user.Friends[wxid] = f; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("获取好友列表消息", ex.Message); + } + finally + { + Thread.Sleep(100); + user.IsGetDic.Remove(_type); + } + } + break; + case MsgType.MT_DATA_CHATROOMS_MSG: + { + var _type = RobotIsRunType.获取群列表; + if (user.IsGetDic.ContainsKey(_type)) + { + if (user.IsGetDic[_type]) + return; + } + + + var hook = WechatClient.GetApi(user); + + #region 原始数据格式 + //{"data":[{"avatar":"http://wx.qlogo.cn/mmcrhead/iahdQicCC5VBRq5vMm7FxlfPct57WiadZ0NEnMUeicvXyS0fh73Hibw0QkkDMw9RQMETbWENFia9NQlmpibkH0bKsOothztfu8waTFy/0","is_manager":0,"manager_wxid":"wxid_yeh4ssxdjpqv12","member_list":["wxid_yeh4ssxdjpqv12","wujiahua0876","wxid_aiwyq8o6iqja12","wxid_lzssz365bwl222"],"nickname":"成都测试群","total_member":4,"wxid":"24444455370@chatroom"}],"type":11031} + + //{"data":[{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22","wxid_89qxkbyaxrok22","wxid_mjzeh4qj9hio22","wxid_z0ucghuw8q4d21","wujiahua0876"],"nickname":"Coco、小鱼、不摇莲","total_member":5,"wxid":"24135168489@chatroom"},{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22","wxid_89qxkbyaxrok22","wxid_6gkp3tl2brgw22","wxid_vebvd7abpq1m22","wxid_mjzeh4qj9hio22","wxid_jhr9qilcujjn22","wxid_z0ucghuw8q4d21"],"nickname":"Coco、小鱼、省钱助手@a17","total_member":7,"wxid":"23171893028@chatroom"},{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22"],"nickname":"Coco","total_member":1,"wxid":"24350471577@chatroom"},{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22"],"nickname":"Coco","total_member":1,"wxid":"22193183022@chatroom"},{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22"],"nickname":"Coco","total_member":1,"wxid":"21553892843@chatroom"},{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22"],"nickname":"Coco","total_member":1,"wxid":"23189492814@chatroom"},{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22"],"nickname":"Coco","total_member":1,"wxid":"21903182670@chatroom"},{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22"],"nickname":"Coco","total_member":1,"wxid":"24466267291@chatroom"},{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22"],"nickname":"Coco","total_member":1,"wxid":"24274273959@chatroom"},{"avatar":"","is_manager":0,"manager_wxid":"wujiahua0876","member_list":["wujiahua0876","wxid_tnizkijej5uq22"],"nickname":"先森吳、Coco","total_member":2,"wxid":"19070524816@chatroom"},{"avatar":"http://wx.qlogo.cn/mmcrhead/KdTWPmV0oYSq6awDribVAlPaHWWWGYMbPNt2d2DBbVzHm23kvp215MTjYx4Cttz6oXTF9GzkM0YYrNw4icyEctJKQICG6h7kic7/0","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22","wxid_vv7rev7a4xpj22","wxid_mjzeh4qj9hio22","wxid_z0ucghuw8q4d21","wxid_yeh4ssxdjpqv12","wxid_2ufntuf4purl22","wxid_8s44kddouuaj21","wujiahua0876"],"nickname":"ooooooooooooo","total_member":8,"wxid":"24487071687@chatroom"},{"avatar":"http://wx.qlogo.cn/mmcrhead/8ibIyIuZLEMHfDadJnw1uz97gsV1kVQL6f7RiadodacpWiaAVtDXE7g5Kb3Z1tCk7Q4J6keIndbSNI44dNH7RPGTOqKCftgBtzD/0","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":["wxid_tnizkijej5uq22","shulin6046","wxid_8s44kddouuaj21"],"nickname":"测试测试","total_member":3,"wxid":"18737615107@chatroom"}],"type":11031} + #endregion + + try + { + user.IsGetDic[_type] = true; + + var jArr = (JArray)data; + for (int i = 0; i < jArr.Count; i++) + { + var item = jArr[i]; + var f = new FriendInfo(); + + f.avatar = item["avatar"]?.ToString(); + f.wxid = item["wxid"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.remark = item["nickname"]?.ToString(); + + f.manager_wxid = item["manager_wxid"]?.ToString(); + f.is_manager = int.Parse(item["is_manager"]?.ToString()); + f.member_list = string.Join(",", (item["member_list"].ToArray().Select(z => z.ToString()))); + + //var group = user.Groups.FirstOrDefault(z => z.wxid == f.wxid); + //if (group == null) + //{ + // //群不存在,去获取群成员信息 + // var _json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = f.wxid } }); + // _SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + + // group = new GroupInfo() { wxid = f.wxid, nickname = f.nickname, avatar = f.avatar, total_member = f.member_list.Length, friends = new List() }; + // user.Groups.Add(group); + //} + //else + // group.total_member = f.member_list.Length; + + GroupInfo group = new GroupInfo(); + + group.wxid = item["wxid"]?.ToString(); + group.avatar = item["avatar"]?.ToString(); + group.nickname = item["nickname"]?.ToString(); + group.total_member = item["total_member"].ToObject(); + + var groupMember = hook.GetGroupMemberInfo(group.wxid).Result; + if (groupMember != null) + { + group.friends = (groupMember as GroupInfo)?.friends; + } + else //获取失败就赋值简单的 + { + var memberJarr = (JArray)item["member_list"]; + for (int o = 0; o < memberJarr.Count; o++) + { + var username = memberJarr[o].ToString(); + var ftmp = group.friends.FirstOrDefault(z => z.wxid == username); + if (ftmp == null) + group.friends.Add(new FriendInfo() { wxid = username }); + } + } + + user.Groups[group.wxid] = group; + + user.Friends[f.wxid] = f; + } + } + catch (Exception) + { } + finally + { + Thread.Sleep(100); + user.IsGetDic.Remove(_type); + } + } + break; + case MsgType.MT_DATA_CHATROOM_MEMBERS_MSG: + { + //获取群成员列表消息 + var groupId = data["group_wxid"].ToString(); + if (user.IsGetContactDic.ContainsKey(groupId) && user.IsGetContactDic[groupId]) + return; + try + { + try + { + user.IsGetContactDic[groupId] = true; + } + catch (Exception) + { + } + var total = data["total"].ToString(); + var member_list = (JArray)data["member_list"]; + if (member_list == null) + { + return; + } + + var group_wxid = data["group_wxid"].ToString(); + if (member_list == null) return; + + var group = user.Groups.FirstOrDefault(z => z.Key == group_wxid).Value; + if (group == null) + { + group = new GroupInfo() { wxid = group_wxid, total_member = member_list.Count, friends = new List() }; + user.Groups[group_wxid] = group; + } + else + group.total_member = member_list.Count; + + for (int i = 0; i < member_list.Count; i++) + { + //{"account":"","avatar":"http://wx.qlogo.cn/mmhead/ver_1/klibauQfLYtmfniaYAzsV9l6V4cSHmdDhniaTmJ6aGo0z035JTkB5QWrOUbAPnJnP4YXTMuKKmwNBMNv2Fbj5ia9icNicYeXGXbbsRiagGFKryASro/132","city":"","country":"","nickname":"陈建","province":"","remark":"","sex":0,"wxid":"wxid_e1j30jf2k5zdk022"} + + var item = member_list[i]; + + var f = new FriendInfo(); + f.account = item["account"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.city = item["city"]?.ToString(); + f.country = item["country"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.province = item["province"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = item["sex"].ToObject(); + f.wxid = item["wxid"]?.ToString(); + + var friend = group.friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + group.friends.Add(f); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("个人微信解析群成员列表消息", ex.Message); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(groupId); + } + } + break; + case MsgType.MT_DATA_PUBLICS_MSG: + { + + } + break; + case MsgType.MT_UPDATE_WXID_MSG: + { + if (data == null) + return; + + + var username = data["wxid"]?.ToString(); + if (username.IsGzh()) return; + + if (user.IsGetContactDic.ContainsKey(username) && user.IsGetContactDic[username]) + return; + + try + { + try + { + user.IsGetContactDic[username] = true; + } + catch (Exception) + { + } + #region 数据结构 + /* + { + "data": { + "account": "", // 微信号 + "avatar": "http://wx.qlogo.cn/xxxxx/0", // 高清头像 + "city": "", // 城市 + "country": "YE", // 国家 + "nickname": "xxxx", // 昵称 + "province": "", // 省 + "remark": "", // 备注 + "sex": 1, // 性别 0未知,1男,2女 + "signature": "", // 朋友圈个性签名 + "small_avatar": "http://wx.qlogo.cn/mmhead/xxxx/132", // 小头像 + "sns_pic": "http://szmmsns.qpic.cn/mmsns/xxxxx/0", // 朋友圈背景图片 + "source_type": 3, // 来源类型,参写添加来源表 + "status": 1, // 是否成功 1成功 ,0失败 + "v1": "v1_xxxe26@stranger", // 用户v1 + "v2": "", // 用户v2 + "wxid": "xxx" // wxid + }, + "type": MT_UPDATE_WXID_MSG + } + */ + #endregion + + var account = data["account"]?.ToString(); + var avatar = data["avatar"]?.ToString(); + var city = data["city"]?.ToString(); + var country = data["country"]?.ToString(); + var nickname = data["nickname"]?.ToString(); + var provice = data["provice"]?.ToString(); + var remark = data["remark"]?.ToString(); + var sex = data["sex"].ToObject(); + var signature = data["signature"]?.ToString(); + var small_avatar = data["small_avatar"]?.ToString(); + var sns_pic = data["sns_pic"]?.ToString(); + var source_type = (int)data["source_type"]; + var status = (int)data["status"]; + var v1 = data["v1"]?.ToString(); + var v2 = data["v2"]?.ToString(); + + var f = new FriendInfo() + { + account = account, + avatar = avatar, + city = city, + country = country, + nickname = nickname, + province = provice, + wxid = username, + remark = remark, + sex = sex + }; + user.Friends[f.wxid] = f; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"个人微信解析搜索用户信息", ex.Message); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(username); + } + } + break; + case MsgType.MT_UPDATE_ROOM_MEMBER_MSG: + { + + + } + break; + case MsgType.MT_RECV_LINK_MSG: + { + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试收到链接", $"{dwClientid} -> {recvData}"); + + var is_pc = data["is_pc"]?.ToString(); + var from_wxid = data["from_wxid"].ToString(); + + if (from_wxid.IsGzh(WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + var wx_sub_type = int.Parse(data["wx_sub_type"].ToString()); + + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie; + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + //if (!string.IsNullOrWhiteSpace(raw_msg)) + //{ + // var reg = Regex.Match(raw_msg, "(?<链接>.*)"); + // if (reg.Success) + // { + // raw_msg = reg.Groups["链接"].Value; + // } + //} + + var socketClient = EasySoc.GetSocket(); + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + + if (raw_msg.ToLower().Contains("chatroombyinvite")) + { + wmsg.FromMessageType = WechatMsgType.群邀请; + return; + } + else + wmsg.FromMessageType = WechatMsgType.链接; + + var usernick = string.Empty; + + if (room_wxid.IsQun()) + { + wmsg.FromGroupid = room_wxid; + wmsg.FromGroupNick = hook.FindNick(room_wxid); + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(room_wxid, from_wxid); + } + else + { + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(ass.fromName); + } + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = usernick; + wmsg.FromMessage = raw_msg; + + wmsg.Timestamp = data["timestamp"].ToObject(); + wmsg.Msgid = data["msgid"]?.ToString(); + wmsg.OriMessage = data["raw_msg"]?.ToString(); + + socketClient.Send(wmsg); + } + break; + case MsgType.MT_RECV_TEXT_MSG: + { + if (data == null || user == null) + return; + + var at_user_list = (JArray)data["at_user_list"]; + var from_wxid = data["from_wxid"]?.ToString(); + + var msg = data["msg"].ToString(); + + var msg_temp = string.Copy(msg); + #region 替换@里面的用户昵称 + if (at_user_list != null && at_user_list.Count != 0) + { + var client_temp = WechatClient.GetApi(user) as Wechat_Xiaoxie; + foreach (string username in at_user_list) + { + var firent = user.Friends.FirstOrDefault(f => f.Key == username).Value; + if (firent == null) + { + var tmp = client_temp.GetFriendInfo(username).Result; + + firent = user.Friends.FirstOrDefault(f => f.Key == username).Value; + } + if (firent != null) + msg_temp = msg_temp.Replace("@" + firent.nickname + " ", "{$@}"); + } + } + #endregion + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + var socketClient = EasySoc.GetSocket(); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, msg_temp)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + msg_temp); + return; + } + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + //if (room_wxid.Contains("@chatroom") || room_wxid.Contains("@im.chatroom")) + //{ + // wmsg.FromGroupid = room_wxid; + // wmsg.FromUsername = from_wxid; + // wmsg.FromUsernick = from_wxid == ass.robotName ? ass.robotNick : string.Empty; + //} + //else + //{ + // wmsg.FromUsername = ass.fromName; + // wmsg.FromUsernick = ass.fromNick; + //} + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie; + var usernick = string.Empty; + if (room_wxid.IsQun()) + { + wmsg.FromGroupid = room_wxid; + wmsg.FromGroupNick = hook.FindNick(room_wxid); + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(room_wxid, from_wxid); + } + else + { + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(ass.fromName); + } + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = usernick; + + wmsg.FromMessage = msg; + wmsg.Timestamp = data["timestamp"].ToObject(); + wmsg.Msgid = data["msgid"]?.ToString(); + wmsg.OriMessage = msg; + + socketClient.Send(wmsg); + + //从网络上下载群成员(刷新) + //var _json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_UPDATE_ROOM_MEMBER_MSG, data = new { room_wxid = "24444455370@chatroom" } }); + //_SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + //获取群成员列表 + //var _json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = "24444455370@chatroom" } }); + //_SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + } + break; + case MsgType.MT_ZOMBIE_CHECK_MSG: + { + //if (data == null) return; + //if (data.ContainsKey("errcode")) + //{ + // var status = int.Parse(data["status"].ToString()); + // var wxid = data["wxid"].ToString(); + + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // var firend = user.Friends.FirstOrDefault(f => f.wxid == wxid); + // if (firend == null) return; + // firend.is_zombie = status; + //} + } + break; + case MsgType.MT_SEND_CARD_XMLMSG: + { + + } + break; + case MsgType.MT_RECV_PICTURE_MSG: + case MsgType.MT_RECV_VOICE_MSG: + case MsgType.MT_RECV_FRIEND_MSG: + case MsgType.MT_RECV_CARD_MSG: + case MsgType.MT_RECV_VIDEO_MSG: + case MsgType.MT_RECV_EMOJI_MSG: + case MsgType.MT_RECV_LOCATION_MSG: + case MsgType.MT_RECV_FILE_MSG: + { + if (data == null || user == null) + return; + + var from_wxid = data["from_wxid"].ToString(); + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + var socketClient = EasySoc.GetSocket(); + + if (wx_type == 3 || wx_type == 34 || wx_type == 43 || wx_type == 49)//图片、语音、视频、文件 + { + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie; + + WechatReceiveMsg msg = new WechatReceiveMsg(); + msg.Cmd = PCRobotCMD.rcvFile; + + msg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + + var usernick = string.Empty; + + if (room_wxid.IsQun()) + { + msg.FromGroupid = room_wxid; + msg.FromGroupNick = hook.FindNick(room_wxid); + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(room_wxid, from_wxid); + } + else + { + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(from_wxid); + } + + //msg.FromUsername = ass.fromName; + //msg.FromUsernick = usernick; + msg.FromUsername = from_wxid; + msg.FromUsernick = usernick; + + msg.MsgId = data["msgid"]?.ToString(); + msg.OriMessage = JsonConvert.SerializeObject(data); + msg.Timestamp = data["timestamp"].ToObject(); + + + if (wx_type == 3)//图片 + { + //var image_thumb = data["image_thumb"].ToString(); + var image = data["image"].ToString(); + + #region 等待下载 + long size = -1L; + var reg = Regex.Match(raw_msg, @"hdlength=\""(\d+?)\"""); + if (reg.Success) + size = long.Parse(reg.Groups[1].Value); + else + { + reg = Regex.Match(raw_msg, @"\slength=\""(\d+?)\"""); + if (reg.Success) + size = long.Parse(reg.Groups[1].Value); + else + { } + } + var waitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + var size_temp = new FileInfo(image).Length; + if (File.Exists(image) && size == size_temp) + break; + } while (waitTime >= DateTime.Now); + #endregion + + msg.Cmd = PCRobotCMD.rcvImg; + + //msg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + msg.IsSend = true; + + var path = Common.CacheFilePath(ass.robotName, ass.fromName, "IMAGE", data["msgid"].ToString(), "jpg"); + + #region 等待图片解密 + //int i = 0; + //do + //{ + // i++; + // client.DecryptImage(image, path); + // var failureTime = DateTime.Now.AddSeconds(2); + // do + // { + // Thread.Sleep(200); + // if (File.Exists(path)) break; + // } while (failureTime >= DateTime.Now); + // if (File.Exists(path)) + // break; + //} while (4 >= i); + + DecodeImage(image, byte.Parse(data["xor_key"].ToString()), path); + if (!string.IsNullOrWhiteSpace(path) && File.Exists(path)) + { } + else + path = image; + #endregion + + msg.FromMessage = $"[图片={path}]"; + msg.FromMessageType = WechatMsgType.图片; + msg.FileCDNXML = raw_msg; + } + else if (wx_type == 34)//语音 + { + //msg.FromMessage = string.Empty;//$"[语音={FilePath}]";//TODO 语音文件 + //msg.FromMessageType = WechatMsgType.语音; + return; + } + else if (wx_type == 43)//视频 + { + //var video = data["video"].ToString(); + //msg.FromMessage = $"[视频={video}]"; + //msg.FromMessageType = WechatMsgType.视频; + return; + } + else if (wx_type == 49)//文件 + { + //msg.FromMessage = string.Empty;//$"[文件={FilePath}]";//TODO 文件 + //msg.FromMessageType = WechatMsgType.文件; + return; + } + + msg.IsSend = false; + msg.RobotUsername = ass.robotName; + msg.RobotUsernick = ass.robotNick; + msg.RobotType = RobotType.客户端微信; + + if (room_wxid.IsQun()) + msg.FromGroupid = room_wxid; + + socketClient.Send(msg); + } + else if (wx_type == 37)//接收到好友申请请求 + { + WechatApplyFriend wXApply = new WechatApplyFriend(); + wXApply.Cmd = PCRobotCMD.applyFriend; + wXApply.RobotUsername = to_wxid; + wXApply.RobotUsernick = WechatClient.GetUser(to_wxid)?.Nickname; + wXApply.RobotType = RobotType.客户端微信; + + var reg = Regex.Match(raw_msg, @"content=""(?<申请文本>[^""]*?)"""); + if (reg.Success) + wXApply.Message = reg.Groups["申请文本"].Value; + + reg = Regex.Match(raw_msg, @"sourceusername=""(?<账号>[^""]*?)"" sourcenickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + { + wXApply.OldFriendWxid = reg.Groups["账号"].Value; + wXApply.OldFriendNick = reg.Groups["昵称"].Value; + } + reg = Regex.Match(raw_msg, @"fromusername=""(?<账号>[^""]*?)"""); + if (reg.Success) + { + if (!string.IsNullOrWhiteSpace(reg.Groups["账号"].Value)) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + else + { + reg = Regex.Match(raw_msg, @"alias=""(?<账号>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + } + } + reg = Regex.Match(raw_msg, @"fromnickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendNick = reg.Groups["昵称"].Value; + + wXApply.Token = raw_msg;//TODO 这里好像要获取raw_msg 中 v1的值 + + socketClient.Send(wXApply); + } + //名片 + else if (wx_type == 42) { } + //接收表情 + else if (wx_type == 47) { } + //接收位置消息 + else if (wx_type == 48) { } + } + break; + case MsgType.MT_RECV_WCPAY_MSG: + { + if (data == null || user == null) + return; + + var from_wxid = data["from_wxid"].ToString(); + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = data["wx_type"].ToString(); + var wx_sub_type = data["wx_sub_type"].ToString(); + var timestamp = data["timestamp"].ToObject(); + + var socketClient = EasySoc.GetSocket(); + if (raw_msg.IndexOf("微信转账") != -1 && raw_msg.IndexOf("收到转账") != -1) + { + string State = Common.StringMid(raw_msg, "", ""); + string Transid = Common.StringMid(raw_msg, "transferid>"); + int dwTime = 0; + int.TryParse(Common.StringMid(raw_msg, ""), out dwTime); + if (State == "1" && Transid != string.Empty) + { + WechatReicevePay reicevePay = new WechatReicevePay(); + reicevePay.RobotUsername = user.Wxid; + reicevePay.RobotUsernick = user.Nickname; + reicevePay.RobotType = RobotType.客户端微信; + reicevePay.FromUsername = from_wxid; + reicevePay.FromUsernick = string.Empty;//TODO 没有获取昵称 + reicevePay.Cmd = PCRobotCMD.receivePay; + reicevePay.Invalidtime = dwTime.ToString(); + reicevePay.Transferid = Transid; + var reg = Regex.Match(raw_msg, "收到转账(?<金额>.+)元"); + if (reg.Success) + reicevePay.Money = double.Parse(reg.Groups["金额"].Value); + if (reicevePay.RobotUsernick == null) reicevePay.RobotUsernick = string.Empty; + socketClient.Send(reicevePay); + return; + } + } + } + break; + case MsgType.MT_RECV_SYSTEM_MSG: + { + //{"data":{"from_wxid":"wxid_lzssz365bwl222","is_pc":0,"msgid":"9071106463111673540","raw_msg":"\"先森吳\"邀请\"查优惠小助手(语馨)\"加入了群聊","room_wxid":"24444455370@chatroom","timestamp":1585398781,"to_wxid":"24444455370@chatroom","wx_type":10000},"type":11058} + + if (data == null || data["raw_msg"] == null || user == null) + return; + + var socketClient = EasySoc.GetSocket(); + var raw_msg = data["raw_msg"].ToString(); + var room_wxid = data["room_wxid"].ToString(); + var from_wxid = data["from_wxid"].ToString(); + + //新人入群 + if (!string.IsNullOrWhiteSpace(room_wxid) && room_wxid.IsQun()) + { + //var reg1 = Regex.Match(raw_msg, @"""(?<邀请人昵称>.*)""邀请""(?<新人昵称>.*)""加入了群聊"); + //var reg2 = Regex.Match(raw_msg, @"你邀请""(?<新人昵称>.*)""加入了群聊"); + //var reg3 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描""(?<邀请人昵称>.*)""分享的二维码加入群聊"); + //var reg4 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描你分享的二维码加入群聊"); + + //if (reg1.Success || reg2.Success || reg3.Success || reg4.Success) + //{ + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // if (user == null) + // return; + // WechatNewMemer newMember = new WechatNewMemer(); + // newMember.Cmd = PCRobotCMD.newMember; + // newMember.RobotType = RobotType.客户端微信; + // newMember.RobotUsername = user.Wxid; + // newMember.RobotUsernick = user.Nickname; + + // if (reg1.Success) + // { + // newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg1.Groups["新人昵称"].Value; + // } + // else if (reg2.Success) + // { + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg2.Groups["新人昵称"].Value; + // } + // else if (reg3.Success) + // { + // newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg3.Groups["新人昵称"].Value; + // } + // else if (reg4.Success) + // { + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg4.Groups["新人昵称"].Value; + // } + + // if (room_wxid.Contains("@chatroom")) + // { + // newMember.GroupId = room_wxid; + // newMember.GroupNick = string.Empty; + // } + // socketClient.Send(newMember); + //} + } + else//新增好友 + { + //#region 添加好友成功 + //var reg1 = Regex.Match(raw_msg, "^你已添加了(.*?),现在可以开始聊天了。$"); + //var reg2 = Regex.Match(raw_msg, "^(.*?)刚刚把你添加到通讯录,现在可以开始聊天了。$"); + //if (reg1.Success || reg2.Success) + //{ + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // if (user == null) + // return; + // WechatNewFriend msg = new WechatNewFriend(); + // msg.Cmd = PCRobotCMD.newfriend; + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + // msg.FromUserName = from_wxid; + // msg.FromUserNick = reg1.Success ? reg1.Groups[1].Value : reg2.Groups[1].Value; + // socketClient.Send(msg); + //} + //#endregion + + #region 检测僵尸粉 + //{"data":{"from_wxid":"wujiahua0876","is_pc":0,"msgid":"3624674612069828076","raw_msg":"先森吳开启了朋友验证,你还不是他(她)朋友。请先发送朋友验证请求,对方验证通过后,才能聊天。发送朋友验证","room_wxid":"","timestamp":1585125257,"to_wxid":"wxid_lzssz365bwl222","wx_type":10000},"type":11058} + + //{"data":{"from_wxid":"wxid_89qxkbyaxrok22","is_pc":0,"msgid":"7401397021380323657","raw_msg":"消息已发出,但被对方拒收了。","room_wxid":"","timestamp":1603436524,"to_wxid":"wujiahua0876","wx_type":10000},"type":11058} + if (raw_msg.Contains("开启了朋友验证") || raw_msg.Contains("但被对方拒收了"))//这里说明是僵尸粉 + { + LogHelper.GetSingleObj().Debug("调试清粉", $"{JsonConvert.SerializeObject(data)}"); + + var wxid = data["from_wxid"].ToString(); + var firend = user.Friends.FirstOrDefault(f => f.Key == wxid).Value; + if (firend == null) return; + if (raw_msg.Contains("但被对方拒收了")) + firend.is_zombie = 2;//拉黑了 + else + firend.is_zombie = 1;//单向好友 + + //var socketClient = EasySoc.GetSocket(); + WechatContact msg = new WechatContact(); + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", new List() { firend } } }); + + socketClient.Send(msg); + } + //{"data":{"from_wxid":"wxid_2ufntuf4purl22","is_pc":0,"msgid":"1580248074267233434","raw_msg":"由于名片类型或场景原因,暂不支持转发该名片。","room_wxid":"","timestamp":1585125880,"to_wxid":"wxid_lzssz365bwl222","wx_type":10000},"type":11058} + else if (raw_msg.Contains("暂不支持转发该名片"))//这里说明是好友 + { + LogHelper.GetSingleObj().Debug("调试清粉_", $"{JsonConvert.SerializeObject(data)}"); + + var wxid = data["from_wxid"].ToString(); + + var firend = user.Friends.FirstOrDefault(f => f.Key == wxid).Value; + if (firend == null) return; + firend.is_zombie = 0; + } + else + { + + } + #endregion + } + } + break; + case MsgType.MT_RECV_REVOKE_MSG: + { + //私聊用户撤回消息 + //{"data":{"from_wxid":"wujiahua0876","is_pc":0,"msgid":"3768878978337666344","raw_msg":"\n\t\n\t\twujiahua0876\n\t\t1097101643\n\t\t5572791720720581005\n\t\t\n\t\n\n","room_wxid":"","timestamp":1586758499,"to_wxid":"wxid_lzssz365bwl222","wx_type":10002},"type":11059} + //私聊用户机器人自己撤回消息 + //{"data":{"from_wxid":"wxid_lzssz365bwl222","is_pc":0,"msgid":"1526645333654331593","raw_msg":"wujiahua087617163236505998900618590839539","room_wxid":"","timestamp":1586758971,"to_wxid":"wujiahua0876","wx_type":10002},"type":11059} + + //var from_wxid = data["from_wxid"]?.ToString(); + //var raw_msg = data["raw_msg"]?.ToString(); + + //var to_wxid = data["to_wxid"]?.ToString(); + + } + break; + case MsgType.MT_RECV_OTHER_MSG: + break; + case MsgType.MT_RECV_OTHER_APP_MSG: + case MsgType.MT_RECV_MINIAPP_MSG: + { + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试收到小程序消息", $"{dwClientid} -> {recvData}"); + if (data == null || user == null) + return; + + var wx_type = data["wx_type"]?.ToString();//微信原始类型,值为 49 + if (wx_type == "49") + { + var wx_sub_type = data["wx_sub_type"]?.ToString();//微信原始应用子类型,值为 36 + if (wx_sub_type == "1" || wx_sub_type == "36" || wx_sub_type == "33" || wx_sub_type == "3" || wx_sub_type == "19") + { + var from_wxid = data["from_wxid"]?.ToString();//发送者的wxid + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var is_pc = data["is_pc"]?.ToString(); + var raw_msg = data["raw_msg"]?.ToString(); + var msgid = data["msgid"]?.ToString();// 接收到的消息id + var room_wxid = data["room_wxid"]?.ToString();//群聊的wxid + var to_wxid = data["to_wxid"]?.ToString();//接收者的wxid + + var socketClient = EasySoc.GetSocket(); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + //if (!string.IsNullOrWhiteSpace(raw_msg)) + //{ + // var reg = Regex.Match(raw_msg, @"(?<链接>.*)"); + // if (reg.Success) + // raw_msg = reg.Groups["链接"].Value; + //} + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie; + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + var usernick = string.Empty; + if (room_wxid.IsQun()) + { + wmsg.FromGroupid = room_wxid; + wmsg.FromGroupNick = hook.FindNick(room_wxid); + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(room_wxid, from_wxid); + } + else + { + if (string.IsNullOrWhiteSpace(usernick)) + usernick = hook.FindNick(ass.fromName); + } + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = usernick; + + wmsg.FromMessage = raw_msg; + + socketClient.Send(wmsg); + } + } + } + break; + case MsgType.MT_CHECK_URL_STATUS_MSG: + { + //if (CheckUrlCache.Count > 500) CheckUrlCache.Clear(); + //{"data":{"status":-2005,"url":"https://ycs9d.kuaizhan.com/?id=07E4060844959"},"type":11123} + if (data["status"] != null) + { + var url = data["url"]?.ToString(); + if (!string.IsNullOrWhiteSpace(url)) + { + //CheckUrlCache.Add(url.Trim(), int.Parse(data["status"].ToString())); + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[url.Trim()]; + cache.Insert(url.Trim(), int.Parse(data["status"].ToString()), null, DateTime.Now.AddSeconds(8), Cache.NoSlidingExpiration); + } + } + } + break; + //case MsgType.MT_CHECK_URL_STATUS2_MSG: + // { + + // if (data.ContainsKey("baseResponse")) + // { + // var baseResponse = data["baseResponse"] as Dictionary; + // if (baseResponse.ContainsKey("ret")) + // { + // var ret = baseResponse["ret"].ToString(); + // Cache cache = HttpRuntime.Cache; + // //查找 md5 的缓存,不存在则返回null + // object item = cache[url.Trim()]; + // cache.Insert(url.Trim(), int.Parse(ret), null, DateTime.Now.AddSeconds(8), Cache.NoSlidingExpiration); + // } + // } + // } + // break; + case MsgType.MT_ROOM_ADD_MEMBER_NOTIFY_MSG://群成员新增通知 + { + //{"data":{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":[{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/MpicosfFj1KMvlSPoxWHjUfT2KGqJvEKrDkDCUiaQp4ryYkv3NMdsYofXUVvgalGx0ylia2swn2MMNWwiaWWEUl4QvQayM2Y28pAaxShUZUH5ms/132","invite_by":"wujiahua0876","nickname":"A083赚钱鸭💯(葫芦娃)","wxid":"wxid_5fn1vpyjpfj022"}],"nickname":"111111","room_wxid":"24466267291@chatroom","total_member":5},"type":11098} + + if (data == null || user == null) + return; + + var hook = WechatClient.GetApi(user) as Wechat_Xiaoxie; + + var socketClient = EasySoc.GetSocket(); + var avatar = data["avatar"].ToString();//头像 + var is_manager = data["is_manager"].ToString();// + var manager_wxid = data["manager_wxid"].ToString();//管理账号 + var room_nick = data["nickname"].ToString();//群昵称 + var room_wxid = data["room_wxid"].ToString();//群账号 + var total_member = int.Parse(data["total_member"].ToString());//群人数 + + var member_list = (JArray)data["member_list"]; + if (member_list != null && member_list.Count != 0) + { + for (int i = 0; i < member_list.Count; i++) + { + var member = member_list[i]; + var avatar_user = member["avatar"].ToString();//头像 + var invite_by = member["invite_by"].ToString();//邀请者wxid + var nickname = member["nickname"].ToString();//新用户昵称 + var wxid = member["wxid"].ToString();//新用户账号 + + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember; + newMember.RobotType = RobotType.客户端微信; + newMember.RobotUsername = user.Wxid; + newMember.RobotUsernick = user.Nickname; + + //if (reg1.Success) + //{ + // newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg1.Groups["新人昵称"].Value; + //} + //else if (reg2.Success) + //{ + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg2.Groups["新人昵称"].Value; + //} + //else if (reg3.Success) + //{ + // newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg3.Groups["新人昵称"].Value; + //} + //else if (reg4.Success) + //{ + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg4.Groups["新人昵称"].Value; + //} + + newMember.SourceNick = string.Empty; + #region 获取邀请人的信息 + if (!string.IsNullOrWhiteSpace(invite_by) && invite_by != user.Wxid) + newMember.SourceNick = hook.FindNick(room_wxid, invite_by); + #endregion + + newMember.SourceName = (string.IsNullOrWhiteSpace(invite_by) || invite_by == user.Wxid) ? string.Empty : invite_by; + newMember.MemberNick = nickname; + newMember.MemberName = wxid; + newMember.GroupId = room_wxid; + newMember.GroupNick = room_nick; + newMember.TotalMember = total_member; + + socketClient.Send(newMember); + } + } + } + break; + case MsgType.MT_ROOM_DEL_MEMBER_NOTIFY_MSG://群成员删除/退出通知 + { + + } + break; + case MsgType.MT_ROOM_CREATE_NOTIFY_MSG://通过接口创建群聊的通知 + { + //{"data":{"avatar":"http://wx.qlogo.cn/mmcrhead/MvMkWKHbPUVricNicF781PXeuPMW2vHEywf6lkuMfLgHN4IlRAyPiaDX8AG9d9XEa1ibiaMXBr83ibDVmgCT70qkHXPN9SFn5iaHC7y/0","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":[{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/CVGILsl6SCMBjjCuyxUOZXNRgeiaPx4EwT1WMqCDz9qp3XcuzuVm3SHuPuial3wOMVUSbbJujBtUqPkB3Uz1ruTVzibqZ74FTnBKibNCq67qBcE/132","invite_by":"wxid_tnizkijej5uq22","nickname":"小张晚安","wxid":"wxid_uwbxwbt4ihjd22"},{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/cstPo5zCEb794wfD44BbnoQicfDOeOzkB3BficFYticVmQy7umm4SArThiaia6f6ZJFriaewskJ3foyuxrEVYic7NicwXQ/132","invite_by":"wxid_tnizkijej5uq22","nickname":"先森吳","wxid":"wujiahua0876"},{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/tbfVwxp5B5WkAx7KxDCTia8kzWgMIj3bqA1QaoHxXvQTwS5aRw6h9WjTQMWBhD6fkt4XjUxURDDGF5aBek8xSnY4kqPIQ9T4oweMyaKLSwnM/132","invite_by":"","nickname":"Coco","wxid":"wxid_tnizkijej5uq22"}],"nickname":"","room_wxid":"24652183014@chatroom","total_member":3},"type":11100} + + if (data == null) return; + + var wxids = new List(); + var member_list = (JArray)data["member_list"]; + for (int i = 0; i < member_list.Count; i++) + { + //{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/CVGILsl6SCMBjjCuyxUOZXNRgeiaPx4EwT1WMqCDz9qp3XcuzuVm3SHuPuial3wOMVUSbbJujBtUqPkB3Uz1ruTVzibqZ74FTnBKibNCq67qBcE/132","invite_by":"wxid_tnizkijej5uq22","nickname":"小安","wxid":"wxid_uwbxwbt4ihjd22"} + + var m = member_list[i]; + if (m == null) continue; + wxids.Add(m["wxid"]?.ToString()); + } + var client = WechatClient.GetApi(user); + wxids.Sort(StringComparer.CurrentCulture); + + var md5Text = Common.GetMD5(string.Join(",", wxids)); + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[md5Text]; + cache.Insert(md5Text, data["room_wxid"].ToString(), null, DateTime.Now.AddSeconds(8), Cache.NoSlidingExpiration); + } + break; + case MsgType.MT_ROOM_DEL_NOTIFY_MSG://群成员删除通知 + { + + } + break; + case MsgType.MT_CONTACT_ADD_NOITFY_MSG://好友新增通知 + { + //{"data":{"account":"dx21101","avatar":"http://wx.qlogo.cn/mmhead/ver_1/we0fG4Y8r0NjN7GUSHFXCu0qicqZf2KKHBeRKIByBNAvvJ8KcgeaomwSju0AqUicJztS6oiaEzDVJiblnZmrJQTibDdPyk7fwzwPbS5JxwibS6POI/0","city":"","country":"","nickname":"秒单客-小张","remark":"","sex":1,"wxid":"wxid_g9r17s6hdb6w22"},"type":11102} + + var socketClient = EasySoc.GetSocket(); + //var account = data["account"].ToString();//新用户账号 + //var avatar = data["avatar"].ToString();//新用户头像 + var nickname = data["nickname"].ToString();//新用户昵称 + //var sex = int.Parse(data["sex"].ToString());//性别 + var wxid = data["wxid"].ToString();//新用户微信id + + #region 添加好友成功 + var msg = new WechatNewFriend(); + msg.Cmd = PCRobotCMD.newfriend; + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.FromUserName = wxid; + msg.FromUserNick = nickname; + socketClient.Send(msg); + + #endregion + } + break; + case MsgType.MT_CONTACT_DEL_NOTIFY_MSG://群成员删除通知 + { + + } + break; + case MsgType.MT_SNS_TIMELINE_MSG://获取朋友圈首页 + { + #region 数据 + //{"data":{"advertiseCount":1,"advertiseList":[{"adInfo":{"string":"\n\n\t51Hky7pHhu%2BI0D6z6NGPpR15cypIpKvA%2B/WmCm0cjdoElUITIAFetWDTQN4vCIoS6ghxwuN0AHfz/Dd5uv0MOe0BAnqUde7RfcpcLvnU4pKwzvPOf09bD57/YLjKvDkkbHks%2BFQ8yTrjpqCQtrqKXVDJrR%2B/6t2%2BIcLfsbPDz%2B6jDc8gjbkn6ADHUW7tOArlAowZ3aNCjtfk5fBHzow8vwBuatiNIeQQySyetV69UB2exOBcR42IFoB%2BgD0ygOTBlYMnaiQtzS0upkBl4NSPHN9xen3lITxROz3Bj6ZRkqrlzrEJjj%2B%2BX0NTbO/ZduF8Fnsq47hKzFn3RzMmrMiMmRT%2BiJpTD3Tz/rwtYsS3tGTCmbneafTW0o%2B9uinX5C2QK45tKlFSDlAlYqEtepY51N2mrvp5aK8wd1A1dotcSJdRCv%2Bibez/B8KZud5p9NbSvb9U/x10HSpgNsWnqqfBc6UOyLTOR6sULIq3RYG3hO4ttiHsTqJ19OXmIJ18uKdRAwm0W%2B1UgpgsirdFgbeE7i22IexOonX0eoikpovBL67pm9Ry5rKfmdqujuKJIrqR7yAiM9QkVyqfLisGkW2BGdifn1WRZE2eZtz1TIwtr5RIz4fr%2BzWthJ%2B8b4mUiIvRnrvbxY2kLOMTQyaDsIwWCrVVcQmRZEtem7CV9y12Npy2t0P5SYgr9G%2B5LOMNBx0okUHnjJOesdHfVxBOI3ioGMEqURMdxzGKUPEh9cdQZT13OIB60lApJboBtPiusgt2pGeKIWX2go19ctm1ASL/nffmXkqCH/XmhdQh01bx83nD%2BNuVWBsGt7Z9yUJAhgfU2HILNweMjSHCmbneafTW0pglqgouP3YMJyDHsaOablYrOJ7sA5PLjhGJilyjGpsHWO0hq0fn1/6LGFYxykl1OjPcIHGFfpCHLlbaL5ZjZUhhz/C8BOcXNC6vq3hZ1wVbOWBOpKjp0CGTuQXg3A4f0G8kXEJdvrlDsxGnYDSTXSrxeCw34BZX0wRD99w7JmukOIQEjoOL%2BMDlCU9gndnYr00zc1cEpTNCjhbE8KAYJBZdF2AjSLljq1308TAxRKbRrFcgG%2BJiF686OhCWD1v6PpvXQtcAwKCuVWFqytU8Snl/XGkfveCEdkXHGR%2B5wQVpN8L6zzMEG%2BrGdae643cmQb9QbyClCgocIhr5xdxaJXPYn59VkWRNnrbPaWePalQctVk7VbyIJUOzQwHaGlZwKOw/ReHEmsuRdunnXbmrEQRK31EdpPUtw%2BrkaExxbpeSMYgHQ4BoIWvqWUJyOKxwPFyEo3Cvbyx3zs8YEIDR6RYMyvLMeZ593lX52lJXIuf7ZRO6kWIOBbYENyusw81Q0PWttkAUANcUYTIqQmpJ%2Bl18qm66d0POojRw0yPqMI/iLYxfYPjGjxhb1M2zfU9m6L39x5/vp8yN12xfT20Zd3eyVauOFxOb9E3aTDebYH0%2BxbxNh/vbG4SZj9HCaNr0679ITrLZHYXBMDckEiDLDwR8Kw37v7qSMMW8TYf72xuEmY/Rwmja9Ou/SE6y2R2FwX8i5x5zY5Tl5uNpEpeEFoAqMk%2BZ6vqgE02GIVVhiy4hc5/GHP79qRrm42kSl4QWgCoyT5nq%2BqATdoRifFt8u0d30DLV9rACLenS8pBrppyFKjJPmer6oBPjILouBe1NDxY74ukW5A91YGOCIYWrgLdFGxIyh6vP7RAgb9YYpXW87wJPd786IpFTQpa3wkYMP8KZud5p9NbSAzTjUvENRy8XeTjKE1qKCzYwKm%2BvgnNWRTCLfefMjKvCmbneafTW0gM041LxDUcvxxDLN%2BQh1dSf3TphpbYWRLoHQm6WpwmDgyX2IiPt3jiN3ZxN%2BdG6zHs8QtlMdETD2u/GbqAmsR47GXT6%2Bd9vzfByhJ%2BosnjffLJWXJQXjVhUDTGN5mqOpQk1YhZbSJ7Gl3YPDnKBt%2BrT/HSDJ%2Bl2Rgf0drS1gCA4TsUAXLNhv0/py7JV78weUyrsXfLMLC3iynBrDlriy8KB/M/vFXqo7T6zykyz/ykKHC9fpUczj0/%2BiYQb3B2u4h%2B9QlK5J0kaYbM9DtGs1EUIRKIqCLzwHz3wEe%2BlG/jvSp462KvE8TSFOCswenppPI1a65q11Y%2BlO8ydxJ0yKldx4NgHf19YAWnJZAl%2BTTbsgLcaCUPrWS5lz1ndLvPYPcbyJmoyss54YkoMCaTa42hTuW08DkxX84NfS0ImGwrDzyMDV8pAyc7VLiJ3BxfADIWMj9C3nfYHWkD5oDTvOHbrCS0oVJZ1y61s4g4lI3FyoWh1%2Bszkttr3tqOGmeY5mCk2pNpt19zSXB4%2B2Et6MfY5rX9USLkHs0PPXGYe6wXuyT4Luymi/Txdbmkt1cP7P6F2o6H5ahvnzLtULV02HVfYj7vBsaMStTPgp8Bsmt1Dyphn5nqGAASmhUDfXW24V7WKihAkyAHELyMNe%2BsOg6bsTHBBKNGKPGzR5p2LY9gYFVY5/qmRA5d8MkAWlZENvXpAfbBdhejCJLU4lQBGZ0eDGmGOZuaA%2BQ6RMJncv%2BR%2BTAP9TvkNsP5x7Yko/BM2IAtCWoMdFGbhobUaNtVkkvCOc%2BwkwlIOXrrn2yrxTx37JNMsN7RFYiEZJNViWH7dXQlLiz9MOANT8H5t5HmgKEctOb1WDmztxkdBkLAejjMY20ZfUiVjwKSEkrrfw03HXk/sbeLtUsrb7nfeb7wpBi2sU7b8X6/dzpHX9DXDm2i1pOR5s/Ng0yeD/6qROyXiFZLD66XRp7//JznTqFw2TWYDkazuFWAyB7ElWqOVd/DOs%2BCAoORBxxiRhbApMiOYRyTumUb%2B%2B6Zl4qOepsczZ29vS6uVWWJ0p0rEOI2RhVZ7btZ%2Ba3lZVRIf/hRMwBoyRlWyRWLyfEmArfOGNYSa4BdrmxeeV0tdIpmLBesqH%2BfzlDeIDk7mYMk0FEAe2cpwAcbBhbqspuYIxkrOTmw00bthKfiRChNDe%2BQee7ugp8pqvuhoz7xLRUD1lTtlqG/NViTumUb%2B%2B6Zl2S6T12VBePmOOxGKAf3beJ%2BnBqYMHgKRlN2Tkq4GQ/YgJNrT9CcDRl8GQ1XD0o6U3YyDCdZIJrEUeI/uSzP6ju5XimNM1qfeiTty4z6jWFh99u%2BfIUuDvxOIp4XGKpLpJ07p9SXuh1Zy%2Bo/31T9J1fWVO2Wob81W5KyA3Dyc2bO1jtlhgW9eAI47EYoB/dt4FQiAo2J5oyUX0qTwlZ90N6Lln5bTToih/GwuFeIuyfUpNqTabdfc0rQ0s06SldO6V93k1aTZhOJHm3uL1CBBMvhQgjxSWRtrp3DKjyMPfVpYPVWi5Ngj3Y5aIpCQuZXtqruCuUkaNnhqKrfImYGgGKmrjkQD2h3urPY6VezxI9OHcs%2BXYnYPN4PKT1x7h8SO2qEn264xwBl1V6YUdN1FXoZsAsPrnFzWcz5uqxEiT0sch%2BHvj9RxWk0HOHHe5NbmAMHuVM8G7t4hl1NT6tf4sD/1uHZDwAxdwJtX0l2GsaAX7It4cWddtlJ5lscfXYNcmftrlkis981E5N9H4zW918IEMg6uvzSz4T8Zay2P9sMQsCF%2Ba3w6VCY0ZuwxbJqN1QaGDzVOAqmJCgwXZe3RYp2/gyNcSjjkQtBUKhqP42BdVQgg%2BXSnthkM2BlKHdHbibjVedFgMtLy4jXQ0jD%2BwHpBztRpAg5ko9PX7d2z/pJt8YzG3w6JRH3V0XrfkwE0SMU46R%2BTSPmgMgjWPkNxa/m2uLgcrsVBMP%2BUoqGYb3MkzDDj01vctVPDoYnTPiyDmvPETC4UzEm8QE4WG1lCfhu527VjTlnq5vxoaY1zSczQop6cs4IaeerPjfv89hzROCUFTWY7AHyfUqeJVK%2BiPZ0ftd7A5I84adtGjRGgLam9vDrIGEgOytifn1WRZE2e7RfKdpxHe8YH986M%2BW1VEiSf6o6x3ZW13hrLgQASU4k2M2CmUcOsa56My716C8yACOene86zrRIbOKlmWY/LpTTFFDj2FS/wRUBIA92e/K3PY4bY3rnNirArVpfolQpqUdeELefv5t1ECPZk5I8tozTqrC6wrFRARf3dlHL0WpRZQzOkMnGblx51W2kSUpSu2/Hd91eDSEOBXvE/kanskVWtaO29jtIzaXdOdbo2JtGAJYzJ7QD93xQpz87qAUQXCBXuJQSB/bEiwpxez/q1U6KDkxquq0XUF9zkWsYKUjFogJilTpoYvjDtoQVtApmBOA2f7el/VIHnxuCNmQlqQFxZQwbWI4tu5EfUvvFSANAk4jag8a4HYuF8%2B8esOKs2PSsBnhQzc%2BY22OtuD3yCNeLZ5n1B5za16svARkdgiGtPGEKwhyvAcMPUfhiL7RxZprDKae8MX1PVHECjLItG2MDR7ZczhqZvA9CHH0GAbafIYSkOszxrBPPpNff7dYiB/j%2BMzZCgR4yfQ7CoDU3lRIFM7BEAf4od%2B3kzeNkAy7ZaAGZftgda2Ih%2BPdTIb6Hv5zgI2didIUjziKQ0Glppdv14mXUNSx8Osti8pEcBeFN3//o3aeh8wYx6bDo/zqIDhFnZE/QS%2BoLSkKdNBK1wPJao/BgEj8GEjOIqWUvm8R5dhNriF5xeYZcXmxbjnwREWQWbbbrLMFFLc7NK/Ol0iNdgpgmBjesJ%2BsrXt0d88f9txZDbMh0kQhWdc/B2bqPntbxWBM3n63FNQKwW6Ch81DpIHjAOJ9YxiEO6FohEbrgLoWfT/TU1eJfHWjklbn6GnbsY4E7mMRoJV7VKXV/GuPP7un5EV%2BwrNpNp0v%2BSybnvKAAEqdQL5cZuKVZMfIOOtopdZisTxabiDXUYViRIoVzvUrdfVGeQVdKAmHLZYjaWnzKUIgF8oyIi091o1BkDsWY8sbUptYLfqFIQR4BMl3xYuum%2BKt3/56SzrDXXPYI7Gb%2BAbdrUFEVeL/LdryKoWtq7jM1hSu5MhS5SOEuoFMbt5EuW5vdTKNlfgWJWsvkZsZNg2uPG%2Bt2HCI3m2MTqvavmupGW%2BmkwK7pwPy56I/8unXh6QMpuq9ifhaOLpfBQK/BLOuTqjqKOZ8yeTW/pJR30DlpUK8Pb1t0/oVUCHbFxhM2uqKlaHAGgTp817xa1p9a9sWAD9g==\n\t4\n\t720\n\t720\n\t3547325421|wx0tld43lkkrodqq|3547325421|1|1626955012|0|2|6041365717172948||AgIylt4GK8nVeUcuI+4pKmMsArrIRywgjntIrbYMoUfG0o+2+yULEOc9S+J+Wk6PLDoh6IKmSjk=|3400866612|21\n\t1\n\thttps://as.weixin.qq.com/cgi-bin/redirect?tid=3400866612&token=e8d51e642ec1fa8166c546c1f303cf95&wx_aid=3547325421&wx_traceid=wx0tld43lkkrodqq00&wx_uid=19681428\n\t4\n\t\n\t\t\n\t\t\t0\n\t\t\t最近有719人购买\n\t\t\t最近有719人购买\n\t\t\t最近有719人购买\n\t\t\n\t\t1\n\t\t1800\n\t\t\n\t\t\tgh_85ea230f6b61@app\n\t\t\t/pages/shop/index.html?storeId=2393731723\n\t\t\t\n\t\t\t1\n\t\t\n\t\n\t\n\t\twx0tld43lkkrodqq\n\t\t3547325421\n\t\n\n\n"},"snsAdObject":{"adXml":{"string":"1AlphaDog阿尔法机器狗19681428011平价阿尔法机器狗来喽时代的风景,AI相伴立即购买4gh_85ea230f6b61@app/pages/shop/index.html?storeId=23937317231新品推荐限量抢购IP联名活动1https://as.weixin.qq.com/cgi-bin/redirect?tid=3400866612&token=e8d51e642ec1fa8166c546c1f303cf9510广告廣告Ad赞助商提供的广告信息贊助商提供的廣告信息Sponsored storyclassify_zh_CNzh_CNclassify_zh_TWzh_TWclassify_enen_USnickname_zh_CNnickname_zh_CNnickname_zh_TWnickname_zh_TWnickname_ennickname_enhttps://mp.weixin.qq.com/promotion/res/htmledition/mobile/html/feedback.html投诉投訴Report654315520385879808https://wxa.wxs.qq.com/canvas-luodiye/h5/wxupdate.html"},"snsObject":{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1621049336,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13598347436105209699,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD4xMzU5ODM0NzQzNjEwNTIwOTY5OTwvaWQ+PGNyZWF0ZVRpbWU+MTYyMTA0OTMzNjwvY3JlYXRlVGltZT48dXNlcm5hbWU+Z2hfMWNmYmQ1NjAzNzliPC91c2VybmFtZT48Y29udGVudERlc2M+5pe25Luj55qE6aOO5pmv77yMQUnnm7jkvLQ8L2NvbnRlbnREZXNjPjxjb250ZW50RGVzY1Nob3dUeXBlPjA8L2NvbnRlbnREZXNjU2hvd1R5cGU+PGNvbnRlbnREZXNjU2NlbmU+MzwvY29udGVudERlc2NTY2VuZT48cHJpdmF0ZT4wPC9wcml2YXRlPjxDb250ZW50T2JqZWN0Pjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48Y29udGVudFN0eWxlPjE8L2NvbnRlbnRTdHlsZT48bWVkaWFMaXN0PjxtZWRpYT48aWQ+MTM1OTkwODQ4MTQ2ODQ0NjA5NDA8L2lkPjxwcml2YXRlPjA8L3ByaXZhdGU+PHR5cGU+MjwvdHlwZT48c3ViVHlwZT4wPC9zdWJUeXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjx1c2VyRGF0YT48L3VzZXJEYXRhPjxsb3dCYW5kVXJsIHR5cGU9IjEiPjwvbG93QmFuZFVybD48dXJsIHR5cGU9IjEiPmh0dHA6Ly93eHNuc2R5dGh1bWIud3hzLnFxLmNvbS8xNDEvMjAyMDQvc25zY29zZG93bmxvYWQvU0gvcmVzZXJ2ZWQvNjA5ZjNlOTQwMDBjOTk1ZDAwMDAwMDAwOWEyMDlkMDkwMDAwMDA4ZDAwMDA0ZWVjP209NzA3YzBiMmVjNDY1OTNiZDQ3NjJlZjRkYWY0MmE4OGYmYW1wO2NrPTcwN2MwYjJlYzQ2NTkzYmQ0NzYyZWY0ZGFmNDJhODhmPC91cmw+PHRodW1iIHR5cGU9IjEiPmh0dHA6Ly93eHNuc2R5dGh1bWIud3hzLnFxLmNvbS8xNDEvMjAyMDQvc25zY29zZG93bmxvYWQvU0gvcmVzZXJ2ZWQvNjA5ZjNlOTQwMDBjOTk1ZDAwMDAwMDAwOWEyMDlkMDkwMDAwMDA4ZDAwMDA0ZWVjP209NzA3YzBiMmVjNDY1OTNiZDQ3NjJlZjRkYWY0MmE4OGYmYW1wO2NrPTcwN2MwYjJlYzQ2NTkzYmQ0NzYyZWY0ZGFmNDJhODhmPC90aHVtYj48c2l6ZSBoZWlnaHQ9IjQ1MCIgd2lkdGg9IjgwMCIgdG90YWxTaXplPSI2NTEzMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PGNvbnRlbnRTdWJTdHlsZT44PC9jb250ZW50U3ViU3R5bGU+PC9Db250ZW50T2JqZWN0PjwvVGltZWxpbmVPYmplY3Q+","iLen":1152},"objectOperations":{"buffer":"CAI=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"gh_1cfbd560379b","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}}}],"baseResponse":{"ret":0},"controlFlag":2,"delAdvertiseCount":0,"firstPageMd5":"6935ad04c4ed4552","max_id":"13647311131165143274","newRequestTime":1626954952,"objectCount":10,"objectCountForSameMd5":10,"objectList":[{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626886264,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13647311131165143274,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"为美好的世界献上祝福","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NzMxMTEzMTE2NTE0MzI3NF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfbWp6ZWg0cWo5aGlvMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY4ODYyNjRdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGFwcEluZm8+PGlkPjwhW0NEQVRBW3d4YWI5YjcxYWQyYjkwZmYzNF1dPjwvaWQ+PHZlcnNpb24+MjY8L3ZlcnNpb24+PGFwcE5hbWU+PCFbQ0RBVEFb5b6u5L+h6K+75LmmXV0+PC9hcHBOYW1lPjxpbnN0YWxsVXJsPjwvaW5zdGFsbFVybD48ZnJvbVVybD48L2Zyb21Vcmw+PGNsaWNrYWJsZT4wPC9jbGlja2FibGU+PC9hcHBJbmZvPjxjb250ZW50RGVzYz48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0NzMxMTEzMTczNDA2MTI3N11dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSJmMjhmNTgyNjE4NmU2ZTZmMWY4NTVjYzAxMjU4MDIzYiI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9hRnJXNFBWVjRwS1NuU3ExcURRVWMxWExOTUNpY2pnaWNhbTdwTlVoN1AyanUxZFJheDdIaWJROHV2YlRvdDRYeHk0UVhmR1RMSFZvbFEvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL2FGclc0UFZWNHBLU25TcTFxRFFVYzFYTE5NQ2ljamdpY2FtN3BOVWg3UDJqdTFkUmF4N0hpYlE4dXZiVG90NFh4eTRRWGZHVExIVm9sUS8xNTBdXT48L3RodW1iPjx2aWRlb0R1cmF0aW9uPjwhW0NEQVRBWzAuMF1dPjwvdmlkZW9EdXJhdGlvbj48c2l6ZSB0b3RhbFNpemU9IjY1Mjg5LjAiIHdpZHRoPSIxMDgwLjAiIGhlaWdodD0iMTY0OC4wIj48L3NpemU+PC9tZWRpYT48L21lZGlhTGlzdD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVkaWFUYWdOYW1lPjwvbWVkaWFUYWdOYW1lPjxtZXNzYWdlRXh0PjwvbWVzc2FnZUV4dD48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PGFwcGlkPnd4YWI5YjcxYWQyYjkwZmYzNDwvYXBwaWQ+PC9hcHBNc2c+PHNjZW5lPjA8L3NjZW5lPjx0eXBlPjA8L3R5cGU+PHVybD48L3VybD48bmV3V29yZGluZ0tleT48L25ld1dvcmRpbmdLZXk+PG5ld3R5cGU+MDwvbmV3dHlwZT48aW5zdGFsbGVkV29yZGluZz48L2luc3RhbGxlZFdvcmRpbmc+PHVuaW5zdGFsbGVkV29yZGluZz48L3VuaW5zdGFsbGVkV29yZGluZz48L2FjdGlvbkluZm8+PHN0YXRFeHRTdHI+PCFbQ0RBVEFbR2hRS0VuZDRZV0k1WWpjeFlXUXlZamt3Wm1Zek5BPT1dXT48L3N0YXRFeHRTdHI+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2449},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_mjzeh4qj9hio22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626788321,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13646489531181052217,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NjQ4OTUzMTE4MTA1MjIxN11dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY3ODgzMjFdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+WPr+S4jeaYr+WYm++8jOWPiOeqgeeEtuS6huS4gOS4i+S4i1vml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0NjQ4OTUzMTgxNjk0ODAyNl1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSJkNTBkOWM5M2Q1NTk5NjkzMjQ2ZTBiZTc1NDZlMmM5OSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4NGI5d21MZDhSRG5yTjhqWlRqNnVYdHF0aWNyWUl2REFMQXBqZ0g0WWZES0JnampUVkh6WDdPVS8wXV0+PC91cmw+PHRodW1iIHR5cGU9IjEiPjwhW0NEQVRBW2h0dHA6Ly9zem1tc25zLnFwaWMuY24vbW1zbnMvVkVkb2ppYmV2alJQQ3Y5TTNBbkhTODRiOXdtTGQ4UkRuck44alpUajZ1WHRxdGljcllJdkRBTEFwamdINFlmREtCZ2pqVFZIelg3T1UvMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSI0NDUzOC4wIiB3aWR0aD0iMTA4MC4wIiBoZWlnaHQ9IjIzNDAuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2077},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626542926,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13644431003338420534,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NDQzMTAwMzMzODQyMDUzNF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY1NDI5MjZdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+aYr+WTquS4quS6uua4o+WcqOWPkeiqk++8jOaQnuW+l+S7iuaZmuWPiOaYr+aatOmbqO+8jOWPiOaYr+aJk+mbt+eahFvml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsyXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1496},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626442781,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13643590928611357004,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MzU5MDkyODYxMTM1NzAwNF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY0NDI3ODFdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S7iuaZmuaciOS6rvCfjJkg5b6I5byv77yM5Lq65rKh5byv5bCx5aW9W+aXuuaftF1b5pe65p+0XV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQzNTkwOTI5MjEzMjM5NjQxXV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9ImEwYzA1NTljMTE3MDUwOTIxM2YyNGMwNWMwMmVjODRkIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzh3UFEzaWJKZGRHRXI4SThOYU9WNnJFWHhtNmtLeG9Ob0xjdTVIMVZBN3hpY3BpYTZCZDJORHFNQ2svMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzh3UFEzaWJKZGRHRXI4SThOYU9WNnJFWHhtNmtLeG9Ob0xjdTVIMVZBN3hpY3BpYTZCZDJORHFNQ2svMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSI3MTYzNy4wIiB3aWR0aD0iOTc4LjAiIGhlaWdodD0iMTE2NC4wIj48L3NpemU+PC9tZWRpYT48L21lZGlhTGlzdD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVkaWFUYWdOYW1lPjwvbWVkaWFUYWdOYW1lPjxtZXNzYWdlRXh0PjwvbWVzc2FnZUV4dD48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PC9hcHBNc2c+PC9hY3Rpb25JbmZvPjxhcHBJbmZvPjxpZD48L2lkPjwvYXBwSW5mbz48bG9jYXRpb24gcG9pQ2xhc3NpZnlJZD0iIiBwb2lOYW1lPSIiIHBvaUFkZHJlc3M9IiIgcG9pQ2xhc3NpZnlUeXBlPSIwIiBjaXR5PSIiPjwvbG9jYXRpb24+PHB1YmxpY1VzZXJOYW1lPjwvcHVibGljVXNlck5hbWU+PHN0cmVhbXZpZGVvPjxzdHJlYW12aWRlb3VybD48L3N0cmVhbXZpZGVvdXJsPjxzdHJlYW12aWRlb3RodW1idXJsPjwvc3RyZWFtdmlkZW90aHVtYnVybD48c3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvPjwvVGltZWxpbmVPYmplY3Q+","iLen":2085},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626348290,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13642798280310927692,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626351692,"deleteFlag":0,"isNotRichText":0,"nickname":"Mr.Y","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_ocmmotiznvw122"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0Mjc5ODI4MDMxMDkyNzY5Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYzNDgyOTBdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+imgeW+l+eRn+W+l+eRn++8jOWHj+S4gOWNiuebruagh+S6hlvml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0Mjc5ODI4MTAzODMxMTc2Ml1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSI0NmE0OGE0YzgzOTNhMDA0NWZjZTUzZGU4ZmEzODg0OSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4OFRoT0dJczEwSGdDMEtLUDRidUJIQnh1eUhXa3BBT0VudnpvSmtyZElEbkJ3N2JRNjVSZ0VnLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4OFRoT0dJczEwSGdDMEtLUDRidUJIQnh1eUhXa3BBT0VudnpvSmtyZElEbkJ3N2JRNjVSZ0VnLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iOTM3MzEuMCIgd2lkdGg9IjE0NDAuMCIgaGVpZ2h0PSIxMDgwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2075},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626277124,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13642201292100546882,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626277179,"deleteFlag":0,"isNotRichText":0,"nickname":"为美好的世界献上祝福","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_mjzeh4qj9hio22"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MjIwMTI5MjEwMDU0Njg4Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYyNzcxMjRdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+WNp+anve+8jOaUtuWIsOS6humihOitpuitpuWRilvmg4rmgZBdW+aDiuaBkF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsyXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1457},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626099336,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13640709903944790348,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626134130,"deleteFlag":0,"isNotRichText":0,"nickname":"Mr.Y","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_ocmmotiznvw122"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MDcwOTkwMzk0NDc5MDM0OF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYwOTkzMzZdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S5n+eul+aYr+S4izcw5LqGW+aXuuaftF1b5pe65p+0XV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQwNzA5OTA0NjgyODU2Nzc0XV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9IjQzNjdkOTU4Yzc1MjJkY2E3NWZiNmM4MzY2ODYxZGQzIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTB2QmNPVzkzTnRVUDU4UWtONFM4d2VTa3RIS2lhdzM1YUFPUjNObGV2Z2hBYndTRU43ZTY3ZVljLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUk9OemoxUHUybUkwdkJjT1c5M050VVA1OFFrTjRTOHdlU2t0SEtpYXczNWFBT1IzTmxldmdoQWJ3U0VON2U2N2VZYy8xNTBdXT48L3RodW1iPjx2aWRlb0R1cmF0aW9uPjwhW0NEQVRBWzAuMF1dPjwvdmlkZW9EdXJhdGlvbj48c2l6ZSB0b3RhbFNpemU9IjE2OTMxLjAiIHdpZHRoPSI3MjYuMCIgaGVpZ2h0PSIyOTkuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2056},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626020250,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13640046480797544764,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MDA0NjQ4MDc5NzU0NDc2NF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYwMjAyNTBdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S9oOiLpeacquWHuueOsO+8jOa4uOaIj+S4jeWNuOi9ve+8gV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQwMDQ2NDgxNTA3OTU0OTk1XV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9Ijg4NDJkMGU0YjU2ZWZjMzhkZjVhMTlkMjgxMzA2OTYyIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTBqYmliM292bmlieG8xcTJpYm9taWNCbnZhU2dNRjRuRmtpYWZCYWJ0RlEyaEJYbGZCTUxnMmliZjg1VmsvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTBqYmliM292bmlieG8xcTJpYm9taWNCbnZhU2dNRjRuRmtpYWZCYWJ0RlEyaEJYbGZCTUxnMmliZjg1VmsvMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSIxMDk5Ny4wIiB3aWR0aD0iMjM0LjAiIGhlaWdodD0iNDQwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2069},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1625753812,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13637811438959997245,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzYzNzgxMTQzODk1OTk5NzI0NV1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjU3NTM4MTJdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+ivpeatu++8jOi3keS6huW/q+S4pOWFrOmHjOiuoeatpeWZqOaJjeW8gOWni+iuoeaVsO+8jOaIkeivtOaAjuS5iOi3keS6humCo+S5iOS5he+8jOi/mOayoeS4gOWFrOmHjOWSqVvoi6bmtqldW+iLpua2qV3vvIzmi7/lh7rmiYvmnLrkuIDnnIvvvIzmsqHorqHmraXvvIzmraPluLjmg4XlhrXml6nkupTlhazph4zkuoZb5pOm5rGXXVvmk6bmsZddXV0+PC9jb250ZW50RGVzYz48Y29udGVudGF0dHI+PCFbQ0RBVEFbMF1dPjwvY29udGVudGF0dHI+PHNvdXJjZVVzZXJOYW1lPjwvc291cmNlVXNlck5hbWU+PHNvdXJjZU5pY2tOYW1lPjwvc291cmNlTmlja05hbWU+PHN0YXRpc3RpY3NEYXRhPjwvc3RhdGlzdGljc0RhdGE+PHdlYXBwSW5mbz48YXBwVXNlck5hbWU+PC9hcHBVc2VyTmFtZT48cGFnZVBhdGg+PC9wYWdlUGF0aD48dmVyc2lvbj48IVtDREFUQVswXV0+PC92ZXJzaW9uPjxkZWJ1Z01vZGU+PCFbQ0RBVEFbMF1dPjwvZGVidWdNb2RlPjxzaGFyZUFjdGlvbklkPjwvc2hhcmVBY3Rpb25JZD48aXNHYW1lPjwhW0NEQVRBWzBdXT48L2lzR2FtZT48bWVzc2FnZUV4dHJhRGF0YT48L21lc3NhZ2VFeHRyYURhdGE+PHN1YlR5cGU+PCFbQ0RBVEFbMF1dPjwvc3ViVHlwZT48cHJlbG9hZFJlc291cmNlcz48L3ByZWxvYWRSZXNvdXJjZXM+PC93ZWFwcEluZm8+PGNhbnZhc0luZm9YbWw+PC9jYW52YXNJbmZvWG1sPjxDb250ZW50T2JqZWN0Pjxjb250ZW50U3R5bGU+PCFbQ0RBVEFbMV1dPjwvY29udGVudFN0eWxlPjxjb250ZW50U3ViU3R5bGU+PCFbQ0RBVEFbMF1dPjwvY29udGVudFN1YlN0eWxlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48bWVkaWFMaXN0PjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2Mzc4MTE0Mzk0MzkwNjU0MjhdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIHR5cGU9IjEiIG1kNT0iMGFkNGZmNWNjZDBhOWU1ODYxMjE3ODk1N2MwMmIzZTQiPjwhW0NEQVRBW2h0dHA6Ly9zem1tc25zLnFwaWMuY24vbW1zbnMvVkVkb2ppYmV2alJQQ3Y5TTNBbkhTODhuQTRTVTB4VWROMkhSbllqdGlhOEFVUGROR0EyMEQxS0FDd0JNN0VZNjlrT2g2MUZZQ0l2bWcvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzg4bkE0U1UweFVkTjJIUm5ZanRpYThBVVBkTkdBMjBEMUtBQ3dCTTdFWTY5a09oNjFGWUNJdm1nLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iNzUxODEuMCIgd2lkdGg9Ijk3OC4wIiBoZWlnaHQ9IjExNjQuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2221},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1625569697,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13636266972566990992,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"#A02选购助手","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzYzNjI2Njk3MjU2Njk5MDk5Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfMHV3YnpnaWxmbWg4MjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjU1Njk2OTddXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBWzQ3LjXlhYU1MOivnei0uSAgOTXlhYUxMDDor53otLlb5pe65p+0XSAK4pSB4pSB5omr56CB5YWF5YC84pSB4pSBCiAgICDkuInnvZHpg73lj6/ku6XvvIzliLDotKblv6tdXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzYzNjI2Njk3MzA0NjEyNDY3OF1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgbWQ1PSJiNzFjZjEyNDAzNzZlYjc4YzQwNjY0NmQ2NmZiYzY5MiIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3NobW1zbnMucXBpYy5jbi9tbXNucy9qaExkS0Jvb1VIOVdNZW5RRGhXeDZlRmpNMHh4SlhVZW91a2VpY01QTWtrMzl2RjNYaE9SNDRZd1JGUWljTkE1NDZpYWdOU3BIaWM2YzNFLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3NobW1zbnMucXBpYy5jbi9tbXNucy9qaExkS0Jvb1VIOVdNZW5RRGhXeDZlRmpNMHh4SlhVZW91a2VpY01QTWtrMzl2RjNYaE9SNDRZd1JGUWljTkE1NDZpYWdOU3BIaWM2YzNFLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIGhlaWdodD0iMTkyMC4wIiB3aWR0aD0iMTA4MC4wIiB0b3RhbFNpemU9IjUxMzc0LjAiPjwvc2l6ZT48L21lZGlhPjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2MzYyNjY5NzMwNDY2NDg5NjNdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIG1kNT0iNzIxZTY5MzdiMzBiOGUxYmY2MjBmNzY0ZWI4ZDgyYWQiIHR5cGU9IjEiPjwhW0NEQVRBW2h0dHA6Ly9zaG1tc25zLnFwaWMuY24vbW1zbnMvamhMZEtCb29VSDlXTWVuUURoV3g2ZUZqTTB4eEpYVWVEUkRHU2R0TWRVVTRpYkZ3NUpVN3QzaE1EYTlDdEFXQ3lFZWljS1JtMlVrbXcvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc2htbXNucy5xcGljLmNuL21tc25zL2poTGRLQm9vVUg5V01lblFEaFd4NmVGak0weHhKWFVlRFJER1NkdE1kVVU0aWJGdzVKVTd0M2hNRGE5Q3RBV0N5RWVpY0tSbTJVa213LzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIGhlaWdodD0iMjM0MC4wIiB3aWR0aD0iMTA4MC4wIiB0b3RhbFNpemU9Ijc2Mzc4LjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2717},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_0uwbzgilfmh822","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}],"recCount":0,"serverConfig":{"copyAndPasteWordLimit":100,"postMentionLimit":10},"session":{"buffer":"CIS65YcGEAEY6uHUgq2lv7K9ASDq4dSCraW/sr0BMIS65YcGSk8I/rLN8KwvEAoYhLrlhwYiIgjjrpTrop7C27wBEAQYBCDq4dSCraW/sr0BKIS65YcGMAEqGgjq4dSCraW/sr0BEJDh/JGEkvCevQEYCiABUIS65YcGYIS65YcG","iLen":129}},"type":11145} + #endregion + + if (data == null || user == null) + return; + + var key = "0"; + if (user.IsOperCirCleInfoDic.ContainsKey(key)) + { + if (user.IsOperCirCleInfoDic[key]) + return; + } + + try + { + user.IsOperCirCleInfoDic[key] = true; + + //var _data = json.ContainsKey("data") ? json["data"] as Dictionary : null; + //if (_data == null) return; + + //foreach (KeyValuePair item in _data) + //{ + // var wxid = item["wxid"]?.ToString(); + + //} + //for (int i = 0; i < _data.Count; i++) + //{ + // var item = _data[i] as Dictionary; + + // var wxid = item["wxid"]?.ToString(); + + + //} + + user.CirCleInfoOriDic[key] = recvData; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("获取朋友圈消息", ex.Message); + } + finally + { + Thread.Sleep(100); + user.IsOperCirCleInfoDic.Remove(key); + } + } + break; + case MsgType.MT_SNS_AUTO_AUTH_MINIAPP_LOGIN://小程序自动授权登录 + { + //{"data":{"appid":"wxde8ac0a21135c07d","code":"051QFNkl2pCwt748wlol2XID1B4QFNk8"},"type":11136} + + //{"data":{"appIconUrl":"","appName":"","baseResponse":{"errMsg":{"string":""},"ret":0},"code":"043ahM0w3h4kQY252N1w3zkH0z2ahM0C","jsApiBaseResponse":{"errcode":0,"errmsg":"ok"},"liftSpan":0,"openId":"","sessionKey":"","sessionTicket":"","signature":"","state":""},"type":11136} + + var appid = data["appid"].ToString(); + var code = data["code"].ToString(); + + if (user.AutoAuthLoginMiNiApps.ContainsKey(appid)) + user.AutoAuthLoginMiNiApps.Remove(appid); + user.AutoAuthLoginMiNiApps.Add(appid, code); + } + break; + case MsgType.MT_SNS_POST_MSG://发送朋友圈 + { + #region 数据结构 + /* + {"data":{"baseResponse":{"ret":0},"snsObject":{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1627522835,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13652651078544265545,"isNotRichText":0,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"、","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD4xMzY1MjY1MTA3ODU0NDI2NTU0NTwvaWQ+PHVzZXJuYW1lPnd4aWRfdnY3cmV2N2E0eHBqMjI8L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjE2Mjc1MjI4MzU8L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4zPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjA8L3ByaXZhdGU+PGNvbnRlbnREZXNjPui/meS4quS9oOiCr+WumuS4jeefpemBk+aIkeeOsOWcqOaDs+eahEE8L2NvbnRlbnREZXNjPjxzaWdodEZvbGRlZD4wPC9zaWdodEZvbGRlZD48c2hvd0ZsYWc+MDwvc2hvd0ZsYWc+PGFwcEluZm8+PGlkPjwvaWQ+PHZlcnNpb24+PC92ZXJzaW9uPjxhcHBOYW1lPjwvYXBwTmFtZT48aW5zdGFsbFVybD48L2luc3RhbGxVcmw+PGZyb21Vcmw+PC9mcm9tVXJsPjxpc0ZvcmNlVXBkYXRlPjA8L2lzRm9yY2VVcGRhdGU+PC9hcHBJbmZvPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjxzdGF0RXh0U3RyPjwvc3RhdEV4dFN0cj48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjI8L2NvbnRlbnRTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48bWVkaWFMaXN0PjwvbWVkaWFMaXN0Pjxjb250ZW50VXJsPjwvY29udGVudFVybD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PC9hcHBNc2c+PC9hY3Rpb25JbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1112},"objectOperations":{"buffer":"","iLen":0},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_vv7rev7a4xpj22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},"spamTips":""},"type":11148} + */ + #endregion + + if (data["snsObject"] != null) + { + var snsObject = data["snsObject"]; + if (snsObject["id"] != null) + { + user.SendCircleId = snsObject["id"].ToString(); + } + } + } + break; + case MsgType.MT_SNS_COMMENT_MSG://朋友圈评论 + { + + } + break; + case MsgType.MT_SNS_LIKE_MSG://朋友圈点赞 + { + + } + break; + case MsgType.MT_SNS_UPLOAD_IMAGE_MSG://朋友圈上传图片 + { + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGYkibHF8s3Pu0RAQNicdgRVsn/0"},"clientId":"wxid_vv7rev7a4xpj22_1627486860","id":0,"path":"D:\\PCRobot\\bin\\Debug\\Cache\\0728114016639.png","startPos":16627,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGYkibHF8s3Pu0RAQNicdgRVsn/150"}],"totalLen":16627,"type":2},"type":11149} + + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGa9quIRWhDvpnuvgkSLwxaz/0"},"clientId":"wxid_vv7rev7a4xpj22_1627491212","id":0,"path":"","startPos":59023,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGa9quIRWhDvpnuvgkSLwxaz/150"}],"totalLen":59023,"type":2},"type":11149} + + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGytHnYnRDfnZ3JnOPBfd4kopkfT9Kic2vlQibkXia04Zweib/0"},"clientId":"wxid_vv7rev7a4xpj22_1627523859","id":0,"path":"D:\\公司项目\\fl_system\\PCRobot\\bin\\Debug\\Cache\\0729095735481.jpg","startPos":47326,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGytHnYnRDfnZ3JnOPBfd4kopkfT9Kic2vlQibkXia04Zweib/150"}],"totalLen":47326,"type":2},"type":11149} + + LogHelper.GetSingleObj().Info(new StackTrace().GetFrame(0).GetMethod().Name, $"正在上传朋友圈图片:" + recvData); + + var upLoadImage = JsonConvert.DeserializeObject(recvData); + if (upLoadImage != null) + { + if (upLoadImage.data.startPos == upLoadImage.data.totalLen) + { + var path = upLoadImage.data.path; + var url = upLoadImage.data.bufferUrl.url; + if (!string.IsNullOrWhiteSpace(path) && !string.IsNullOrWhiteSpace(url)) + { + if (user.UpLoadImages.ContainsKey(path)) + user.UpLoadImages.Remove(path); + user.UpLoadImages.Add(path, url); + } + else + { + + } + } + } + } + break; + case MsgType.MT_SNS_TIMELINE_USER_MSG://获取指定用户的朋友圈 + { + #region 数据样式 + /* + {"data":{"baseResponse":{"ret":207},"continueId":0,"firstPageMd5":"b7e1f61580104448","limitedId":0,"newRequestTime":1627613128,"objectCount":1,"objectCountForSameMd5":1,"objectList":[{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1627612789,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13653405663930290388,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"先森吳","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY1MzQwNTY2MzkzMDI5MDM4OF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d1amlhaHVhMDg3Nl1dPjwvdXNlcm5hbWU+PGNyZWF0ZVRpbWU+PCFbQ0RBVEFbMTYyNzYxMjc4OV1dPjwvY3JlYXRlVGltZT48Y29udGVudERlc2NTaG93VHlwZT4wPC9jb250ZW50RGVzY1Nob3dUeXBlPjxjb250ZW50RGVzY1NjZW5lPjA8L2NvbnRlbnREZXNjU2NlbmU+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48Y29udGVudERlc2M+PCFbQ0RBVEFb5L2g6IKv5a6a5LiN55+l6YGT5oiR546w5Zyo5oOz6KGo6L6+5LuA5LmIXV0+PC9jb250ZW50RGVzYz48Y29udGVudGF0dHI+PCFbQ0RBVEFbMF1dPjwvY29udGVudGF0dHI+PHNvdXJjZVVzZXJOYW1lPjwvc291cmNlVXNlck5hbWU+PHNvdXJjZU5pY2tOYW1lPjwvc291cmNlTmlja05hbWU+PHN0YXRpc3RpY3NEYXRhPjwvc3RhdGlzdGljc0RhdGE+PHdlYXBwSW5mbz48YXBwVXNlck5hbWU+PC9hcHBVc2VyTmFtZT48cGFnZVBhdGg+PC9wYWdlUGF0aD48dmVyc2lvbj48IVtDREFUQVswXV0+PC92ZXJzaW9uPjxkZWJ1Z01vZGU+PCFbQ0RBVEFbMF1dPjwvZGVidWdNb2RlPjxzaGFyZUFjdGlvbklkPjwvc2hhcmVBY3Rpb25JZD48aXNHYW1lPjwhW0NEQVRBWzBdXT48L2lzR2FtZT48bWVzc2FnZUV4dHJhRGF0YT48L21lc3NhZ2VFeHRyYURhdGE+PHN1YlR5cGU+PCFbQ0RBVEFbMF1dPjwvc3ViVHlwZT48cHJlbG9hZFJlc291cmNlcz48L3ByZWxvYWRSZXNvdXJjZXM+PC93ZWFwcEluZm8+PGNhbnZhc0luZm9YbWw+PC9jYW52YXNJbmZvWG1sPjxDb250ZW50T2JqZWN0Pjxjb250ZW50U3R5bGU+PCFbQ0RBVEFbMV1dPjwvY29udGVudFN0eWxlPjxjb250ZW50U3ViU3R5bGU+PCFbQ0RBVEFbMF1dPjwvY29udGVudFN1YlN0eWxlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48bWVkaWFMaXN0PjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2NTM0MDU2NjQ1NTkyMzkzODZdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIHR5cGU9IjEiIG1kNT0iNDI1YTRiODEyNjQ2NzQwY2Y3MzlmYWI4Y2E2ZGIyNWUiPjwhW0NEQVRBW2h0dHA6Ly9zaG1tc25zLnFwaWMuY24vbW1zbnMvaWNySERtdkRpYjB4bUhUbkFPODJKSVVjaDFUVmUySWFtbDdYWHdaSlVuUWpZU3dsSjVNa09iQXlYRkpUbVNTbk5DZmNITFgyNE9RUncvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc2htbXNucy5xcGljLmNuL21tc25zL2ljckhEbXZEaWIweG1IVG5BTzgySklVY2gxVFZlMklhbWw3WFh3WkpVblFqWVN3bEo1TWtPYkF5WEZKVG1TU25OQ2ZjSExYMjRPUVJ3LzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iMTAxOTIuMCIgd2lkdGg9IjEwODAuMCIgaGVpZ2h0PSIyMzQwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2060},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wujiahua0876","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}],"objectTotalCount":5,"retTips":"朋友仅展示最近一个月的朋友圈","serverConfig":{"copyAndPasteWordLimit":100,"postMentionLimit":10},"snsUserInfo":{"snsBgImgId":"http://szmmsns.qpic.cn/mmsns/icrHDmvDib0xnEAtnSHHGziac6GNMlhWZK61YORztv9pl7x3AeNWibkAcdJstckibqwBFVFcFO9ovscc/0","snsBgObjectId":13404086805597261983,"snsFlag":1,"snsFlagEx":6273}},"type":11150} + */ + #endregion + + if (data == null || user == null) + return; + + if (data["objectList"] != null) + { + var objectList = (JArray)data["objectList"]; + if (objectList == null || objectList.Count == 0) + { + var tmp = user.IsOperCirCleInfoDic.Where(f => f.Key != "0" && !f.Value).ToDictionary(f => f.Key, f => f.Value); + if (tmp.Count == 1) + { + var keyTmp = string.Empty; + try + { + keyTmp = tmp.Keys.ToList()[0]; + user.IsOperCirCleInfoDic[keyTmp] = true; + + if (!string.IsNullOrWhiteSpace(keyTmp)) + user.CirCleInfoOriDic.Remove(keyTmp); + } + catch (Exception) + { } + finally + { + Thread.Sleep(100); + user.IsOperCirCleInfoDic.Remove(keyTmp); + } + } + return; + } + + var key = objectList[0]["username"]?.ToString();//获取用户账号 + if (string.IsNullOrWhiteSpace(key)) + return; + + if (user.IsOperCirCleInfoDic.ContainsKey(key)) + { + if (user.IsOperCirCleInfoDic[key]) + return; + } + + try + { + user.IsOperCirCleInfoDic[key] = true; + + user.CirCleInfoOriDic[key] = recvData; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("获取朋友圈消息", ex.Message); + } + finally + { + Thread.Sleep(100); + user.IsOperCirCleInfoDic.Remove(key); + } + } + } + break; + default: + + break; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + // 注入成功回调 + static void WxAcceptCallback(uint dwClientId) + { + LogHelper.GetSingleObj().Info(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "注入成功:" + dwClientId); + Console.WriteLine("注入成功:" + dwClientId); + } + + // 关闭回调 + static void WxCloseCallback(uint dwClientId) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == dwClientId && f.Value.Type == WechatType.Xiaoxie).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"WxCloseCallback关闭回调,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } +} diff --git a/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Override.cs b/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Override.cs new file mode 100644 index 0000000..470f882 --- /dev/null +++ b/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Override.cs @@ -0,0 +1,1504 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using CsharpHttpHelper; +using Newtonsoft.Json; +using PCRobot.Entitys; +using PCRobot.Entitys.Enterprise; +using PCRobot.Pack; +using PCRobot.Utils; +using static PCRobot.PCWechat.Routine.Wechat_Xiaoxie_Type; + +namespace PCRobot.PCWechat.Routine +{ + public partial class Wechat_Xiaoxie + { + public override string GetVersion() + { + return Version; + } + + public override void GetContact(bool isUpdata) + { + try + { + var result = GetFriendInfos().Result; + + var socketClient = EasySoc.GetSocket(); + CommonResult msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvFriendList; + msg.Data = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void CheckZombiz() + { + if (User.IsZombizRun) return; + try + { + User.IsZombizRun = true; + + var fDic = GetFriendInfos().Result; + + var friends = User.Friends.Where(f => !f.Key.IsQun() && f.Value.is_zombie == -1).Select(f => f.Value).ToList(); + foreach (var item in friends) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CARD_XMLMSG, data = new { to_wxid = item.wxid, xml = @" ".Replace("[wxid]", item.wxid).Replace("[name]", ".") } }); + var u = User.Friends.FirstOrDefault(f => f.Key == item.wxid).Value; + if (u != null && u.is_zombie == -1) + { + SendWeChatData(User.DwClientId, json); + Thread.Sleep(800 + new Random().Next(100, 200)); + } + } + } + catch (Exception) + { } + finally + { + User.IsZombizRun = false; + } + } + + public override void SendMessage(string wxid, string message, string msgId = "", string usernick = "", string quoteMess = "") + { + try + { + var json = string.Empty; + message = message.Replace("\r\n", "\n"); + if (Common.isXML(message)) + { + //var msgs = Regex.Matches(message, "(<.*?>)(.*?)()"); + //foreach (Match item in msgs) + //{ + // if (item.Success && !string.IsNullOrEmpty(item.Groups[2].Value) && !item.Groups[2].Value.StartsWith("" + item.Groups[3]; + // message = message.Replace(item.Groups[1].Value,temp); + // } + //} + + //wxfedd75bfcbbcd58c + //wx13e41a437b8a1d2e + //pages/index/index.html?orderid=[领取地址] + if (Regex.IsMatch(message, @"(?[^<]+)") || Regex.IsMatch(message, @"(.+?)")) + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_XMLMSG, data = new { to_wxid = wxid, xml = Common.XMLDispose(message.Replace("&", "&")) } }); + else + { + message = message.Replace("&", "&"); + var title = string.Empty; + var desc = string.Empty; + var url = string.Empty; + var image_url = string.Empty; + var reg = Regex.Match(message, @"(?<标题>[\w\W]+?)"); + if (reg.Success) title = reg.Groups["标题"].Value; + reg = Regex.Match(message, @"(?<介绍>[\w\W]+?)"); + if (reg.Success) desc = reg.Groups["介绍"].Value; + reg = Regex.Match(message, @"(?<链接>[\w\W]+?)"); + if (reg.Success) url = reg.Groups["链接"].Value; + reg = Regex.Match(message, @"(?<图片链接>[\w\W]+?)"); + if (reg.Success) image_url = reg.Groups["图片链接"].Value; + + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_LINKMSG, data = new { to_wxid = wxid, title = $"{title.XMLReplace()}", desc = $"{desc.XMLReplace()}", url = url.XMLReplace(), image_url = image_url.XMLReplace() } }); + } + } + else + { + var atUsername = new List(); + var regs = Regex.Matches(message, @"\[@([^\]]+?)\]"); + var flag = true; + if (wxid.IsQun()) + { + //[@wujiahua0876]你懂得,我只是测试一下 + + foreach (Match item in regs) + { + atUsername.Add(item.Groups[1].Value.Trim()); + } + if (atUsername.Count != 0) + { + flag = false; + message = Regex.Replace(message, @"(\[@[^\]]+?\])", "{$@}"); + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CHATROOM_ATMSG, data = new { to_wxid = wxid, content = message, at_list = atUsername.ToArray() } }); + } + } + if (flag) + { + message = Regex.Replace(message, @"(\[@[^\]]+?\])", ""); + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_TEXTMSG, data = new { to_wxid = wxid, content = message } }); + } + } + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendFile(string username, string file) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_FILEMSG, data = new { to_wxid = username, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendCard(string username, string cardwxid) + { + try + { + var json = string.Empty; + if (cardwxid.IsQun()) + //json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_INVITE_TO_ROOM_REQ_MSG, data = new { room_wxid = card_wxid, member_list = new string[] { to_wxid } } }); + { + InviteMemberToGroup_40Up(cardwxid, new string[] { username }); + return; + } + else + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CARDMSG, data = new { to_wxid = username, card_wxid = cardwxid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendLinkMessage(string username, string title, string desc, string url, string image_url) + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_LINKMSG, data = new { to_wxid = username, title = $"{title.XMLReplace()}", desc = $"{desc.XMLReplace()}", url = url.XMLReplace(), image_url = image_url.XMLReplace() } }); + SendWeChatData(User.DwClientId, json); + } + + public override void SendImage(string wxid, string file) + { + try + { + if (file.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + byte[] ImangByte = null; + string extension = Path.GetExtension(file); + extension = string.IsNullOrWhiteSpace(extension) ? ".jpg" : extension; + ImangByte = new System.Net.WebClient().DownloadData(file); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), extension); + if (!File.Exists(path)) + { + File.WriteAllBytes(path, ImangByte); + } + if (File.Exists(path)) + file = path; + } + else + { + if (!File.Exists(file)) + { + if (Common.IsBase64(file)) + { + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), "jpg"); + if (Common.Base64ToFileAndSave(file, path) && File.Exists(path)) + { + file = path; + } + } + else + { } + } + } + var json = string.Empty; + if (file.Trim().EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase)) + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_GIFMSG, data = new { to_wxid = wxid, file = file } }); + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMGMSG, data = new { to_wxid = wxid, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendVideo(string username, string file) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_VIDEOMSG, data = new { to_wxid = username, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void ModifyGroupNotice(string groupid, string notice) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_NOTICE_MSG, data = new { room_wxid = groupid, notice = notice } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void Ser_CreateGroup(string[] usernames) + { + var result = CreateGroup(usernames).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CreateRoom(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCreateRoom; + msg.GroupId = result?.GroupId; + msg.MemberTotal = 0; + socketClient.Send(msg); + } + + public override Task CreateGroup(string[] usernames) + { + if (usernames != null && usernames.Length != 0) + { + try + { + var type = RobotIsRunType.创建群; + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetDic.ContainsKey(type)) + { + User.IsGetDic[type] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_CREATE_ROOM_MSG, data = usernames }); + SendWeChatData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + var keyMd5 = HttpExtend.GetMD5String($"CACHE_CREATEGROUP{type}"); + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetDic.ContainsKey(type))//等到解析完消息,解析完消息IsGetDic中的消息会被删除 + { + var createGroupInfo = Common.GetCache(keyMd5); + Common.RemoveCache(keyMd5); + return createGroupInfo; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取创建群信息", ex.Message); + } + } + return Task.FromResult(null); + } + + public override void DeleteGroupMember(string groupid, string[] usernames) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DEL_ROOM_MEMBER_MSG, data = new { room_wxid = groupid, member_list = usernames } }); + SendWeChatData(User.DwClientId, json); + } + + public override void QuitAndDelGroup(string groupid) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_QUIT_DEL_ROOM_MSG, data = new { room_wxid = groupid } }); + SendWeChatData(User.DwClientId, json); + } + + public override void ModifyGroupName(string groupid, string newName) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_NAME_MSG, data = new { room_wxid = groupid, name = newName } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void Ser_GetSelfInfo() + { + var result = GetSelfInfo().Result; + + var data = string.Empty; + if (result != null) + data = HttpHelper.ObjectToJson(result as FriendInfo); + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = data; + + socketClient.Send(msg); + } + + public override Task GetSelfInfo() + { + try + { + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(User.Wxid)) + { + User.IsGetContactDic[User.Wxid] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DATA_OWNER_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetContactDic.ContainsKey(User.Wxid) && User.IsGetContactDic[User.Wxid])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(User.Wxid))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + { + if (User.Friends.ContainsKey(User.Wxid)) + return User.Friends[User.Wxid]; + return null; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取自己基础信息", ex.Message); + } + return Task.FromResult(null); + } + + public override void Ser_GetContact(string username) + { + var data = string.Empty; + + if (User.Friends.ContainsKey(username)) + data = HttpHelper.ObjectToJson(User.Friends[username]); + else + { + + if (username.IsQun()) + { + var g = GetGroupInfos().Result; + if (User.Friends.ContainsKey(username)) + data = HttpHelper.ObjectToJson(User.Friends[username]); + } + else + { + var result = GetFriendInfo(username).Result; + if (result != null) + data = HttpHelper.ObjectToJson((result as FriendInfo)); + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = data; + + socketClient.Send(msg); + } + + public override Task GetFriendInfo(string username) + { + try + { + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(username)) + { + User.IsGetContactDic[username] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DATA_WXID_MSG, data = new { wxid = username } }); + SendWeChatData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetContactDic.ContainsKey(username) && User.IsGetContactDic[username])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(username))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + { + if (User.Friends.ContainsKey(username)) + return User.Friends[username]; + return null; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取单个用户信息", ex.Message); + } + return Task.FromResult(null); + } + + public override void GetFriendInfo(string userName, string groupId, bool IsFlush = false) + { + var result = Task.Factory.StartNew(() => + { + try + { + if (string.IsNullOrWhiteSpace(userName)) return null; + if (string.IsNullOrWhiteSpace(groupId)) return null; + + if (IsFlush) + { + var gInfo = GetGroupMemberInfo(groupId).Result; + if (gInfo == null) return null; + var g = gInfo as GroupInfo; + if (g == null) return null; + + var ftmp = g.friends.FirstOrDefault(f => f.wxid == userName); + if (ftmp != null) + return new GroupInfo() { wxid = groupId, friends = new List() { ftmp }, total_member = User.Groups[groupId].total_member, nickname = User.Groups[groupId].nickname }; + } + if (User.Groups.ContainsKey(groupId)) + { + if (User.Groups[groupId].friends == null) return null; + var ftmp = User.Groups[groupId].friends.FirstOrDefault(f => f.wxid == userName); + if (ftmp != null) + return new GroupInfo() { wxid = groupId, friends = new List() { ftmp }, total_member = User.Groups[groupId].total_member, nickname = User.Groups[groupId].nickname }; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取群用户信息", ex.Message); + } + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + + public override Task> GetGroupInfos() + { + try + { + var type = RobotIsRunType.获取群列表; + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetDic.ContainsKey(type)) + { + User.IsGetDic[type] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DATA_CHATROOMS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetDic.ContainsKey(type))//等到解析完消息,解析完消息IsGetDic中的消息会被删除 + { + Dictionary dic = new Dictionary(); + if (User.Groups != null) + { + foreach (var item in User.Groups) + { + dic.Add(item.Key, item.Value); + } + } + return dic; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取所有群组列表", ex.Message); + } + return Task.FromResult>(null); + } + + public override Task GetGroupMemberInfo(string groupid) + { + try + { + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(groupid)) + { + User.IsGetContactDic[groupid] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = groupid } }); + SendWeChatData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetContactDic.ContainsKey(groupid) && User.IsGetContactDic[groupid])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(groupid))//等到解析完消息,解析完消息IsGetGroupMemberDic中的消息会被删除 + { + if (User.Groups.ContainsKey(groupid)) + return User.Groups[groupid]; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取指定群组成员信息", ex.Message); + } + return Task.FromResult(null); + } + + public override void GetGroupsNotInMember() + { + try + { + //获取群列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOMS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + Thread.Sleep(4000); + var groups = User.Friends.Where(f => f.Key.IsQun()).Select(f => f.Value).ToList(); + return groups == null ? string.Empty : HttpHelper.ObjectToJson(new Dictionary>() { { "data", groups } }); + }).Result; + + if (result == null) + result = HttpHelper.ObjectToJson(new Dictionary>() { { "data", User.Friends.Where(f => f.Key.IsQun()).Select(f => f.Value).ToList() } }); + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void OutLogin() + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_QUIT_LOGIN_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + } + + public override void OutLogin(string message) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == User.DwClientId && f.Value.Type == WechatType.Xiaoxie).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"CloseWechat事件退出,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v, true); + if (!string.IsNullOrWhiteSpace(message)) + PCRobotForm.ErrorMessAction?.Invoke(message); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendProgramMessage(string username, string msg) + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_XMLMSG, data = new { to_wxid = username, xml = Common.XMLDispose(msg.Replace("&", "&")) } }); + SendWeChatData(User.DwClientId, json); + } + + public override void SendXml(string username, string xml, string customSource = "Window wechat") + { + if (xml.Trim().StartsWith("", StringComparison.CurrentCultureIgnoreCase | StringComparison.InvariantCultureIgnoreCase)) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_XMLMSG, data = new { to_wxid = username, xml = $@"{User.Wxid}0{Common.XMLDispose(xml.Replace("&", "&"))}1{customSource}" } }); + SendWeChatData(User.DwClientId, json); + } + } + + public override void SendCardXml(string username, string xml) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SEND_CARD_XMLMSG, data = new { to_wxid = username, xml = xml } }); + SendWeChatData(User.DwClientId, json); + } + + public override void SendQuoteMessage(string username, string replyMess, WechatMsgType messageType, string quoteMess, string quoteMsgid, + string quoteUsername, string quoteUsernick) + { + var mess = quoteMess; + switch (messageType) + { + case WechatMsgType.文本: + mess = quoteMess; + break; + case WechatMsgType.语音: + case WechatMsgType.视频: + case WechatMsgType.图片: + case WechatMsgType.文件: + case WechatMsgType.红包: + case WechatMsgType.表情: + case WechatMsgType.名片: + case WechatMsgType.小程序: + case WechatMsgType.链接: + case WechatMsgType.群邀请: + mess = messageType.ToString(); + break; + default: + mess = "未知消息"; + break; + } + + var quoteXml = "[回复内容]view570001[引用的消息id][群号][引用用户的微信id][引用用户的昵称]<msgsource><silence>1</silence><membercount>7</membercount></msgsource>[引用的内容]000000nullnull0nullnullnullnull00000000000" + .Replace("[回复内容]", replyMess) + .Replace("[引用的消息id]", quoteMsgid) + .Replace("[引用用户的微信id]", quoteUsername) + .Replace("[引用用户的昵称]", quoteUsernick) + .Replace("[引用的内容]", mess) + .Replace("[群号]", username); + + SendXml(username, quoteXml); + } + + public override void SendLinkMessage(string username, string title, string desc, string url, string imageUrl, string customSource) + { + var xml = @" +[标题] +[描述] +view +5 +0 + +[地址] + + + + +[图片地址] + + + + + + +0 + + + + + +" + .Replace("[标题]", title) + .Replace("[描述]", desc) + .Replace("[地址]", url) + .Replace("[图片地址]", imageUrl); + + SendXml(username, xml); + } + + public override void InviteMemberToGroup_40Down(string groupid, string[] usernames) + { + if (usernames != null && usernames.Length != 0) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_INVITE_TO_ROOM_MSG, data = new { room_wxid = groupid, member_list = usernames } }); + SendWeChatData(User.DwClientId, json); + } + } + + public override void InviteMemberToGroup_40Up(string groupid, string[] usernames) + { + if (usernames != null && usernames.Length != 0) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_INVITE_TO_ROOM_REQ_MSG, data = new { room_wxid = groupid, member_list = usernames } }); + SendWeChatData(User.DwClientId, json); + } + } + + public override void ModifyGroupMyNick(string groupid, string newNick) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MOD_ROOM_NOTICE_MSG, data = new { room_wxid = groupid, notice = newNick } }); + SendWeChatData(User.DwClientId, json); + } + + public override void AutoAcceptGroup(bool isAuto) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_AUTO_ACCEPT_ROOM_MSG, data = new { auto = isAuto ? 1 : 0 } }); + SendWeChatData(User.DwClientId, json); + } + + public override void ModifyGroupShowNick(string groupid, bool isShow) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_SHOW_NAME_MSG, data = new { room_wxid = groupid, status = isShow ? 1 : 0 } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SaveGroupToContact(string groupid, bool status) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SAVE_ROOM_TO_CONTACT_MSG, data = new { room_wxid = groupid, status = status ? 1 : 0 } }); + SendWeChatData(User.DwClientId, json); + } + + public override void ForwardAny(string username, string msgid) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_FORWARD_ANY_MSG, data = new { to_wxid = username, msgid = msgid } }); + SendWeChatData(User.DwClientId, json); + } + + public override string TransVoice(string msgid) + { + try + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_TRANS_VOICE_MSG, data = new { msgid = msgid } }); + SendWeChatData(User.DwClientId, json); + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + var text = Common.GetCache($"TransVoiceResult-Wechat-{msgid}"); + if (!string.IsNullOrEmpty(text)) + { + return text; + } + Thread.Sleep(500); + } while (endtime > DateTime.Now); + return null; + }).Result; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"语音转文本", ex.Message); + } + return null; + } + + public override void ModifyRecvNotify(string username, bool status) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MOD_RECV_NOTIFY_MSG, data = new { wxid = username, status = status ? 1 : 0 } }); + SendWeChatData(User.DwClientId, json); + } + + public override void ModifyChatTop(string username, bool status) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MOD_CHAT_SESSION_TOP_MSG, data = new { wxid = username, status = status ? 1 : 0 } }); + SendWeChatData(User.DwClientId, json); + } + + public override void AddPublicUser(string username, string source_type = "") + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ADD_PUBLIC_USER_MSG, data = new { wxid = username, source_type = source_type } }); + SendWeChatData(User.DwClientId, json); + } + + public override void AddFriend(string username, string remark, int source_type, string groupid) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ADD_FRIEND_MSG, data = new { wxid = username, remark = remark, source_type = source_type, groupid = groupid } }); + SendWeChatData(User.DwClientId, json); + } + + public override void ModifyFriendRemark(string username, string remark) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_MOD_FRIEND_REMARK_MSG, data = new { wxid = username, remark = remark } }); + SendWeChatData(User.DwClientId, json); + } + + public override void DeleteFriend(string username) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DEL_FRIEND_MSG, data = new { wxid = username } }); + SendWeChatData(User.DwClientId, json); + } + + //public override Task AcceptFriend(string username, string encryptusername, string ticket, string scene) + public override void AcceptFriend(string text) + { + var v1 = string.Empty; + var v2 = string.Empty; + var scene = 0; + + var reg = Regex.Match(text, @"encryptusername=\\?""([^""]+?)\\?"""); + if (reg.Success) + v1 = reg.Groups[1].Value; + reg = Regex.Match(text, @"ticket=\\?""([^""]+?)\\?"""); + if (reg.Success) + v2 = reg.Groups[1].Value; + reg = Regex.Match(text, @"scene=\\?""([^""]+?)\\?"""); + if (reg.Success) + scene = int.Parse(reg.Groups[1].Value); + + LogHelper.GetSingleObj().Info("------", $"v1 = {v1} v2 = {v1} scene = {scene}"); + + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_FRIEND_MSG, data = new { v1 = v1, v2 = v2, scene = scene } }); + //var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_FRIEND_MSG, data = new { v1 = v1, v2 = v2 } }); + SendWeChatData(User.DwClientId, json); + } + + public override void AcceptFriendTransfer(string data) + { + try + { + var transferid = string.Empty; + var dic = HttpExtend.JsonToDictionary(data); + if (dic.ContainsKey("Transferid")) + transferid = dic["Transferid"].ToString(); + + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_WCPAY_MSG, data = new { transferid = transferid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void RefuseFriendTransfer(string transferid) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_REFUSE_FRIEND_WCPAY_MSG, data = new { transferid = transferid } }); + SendWeChatData(User.DwClientId, json); + } + + public override void AcceptFriendInviteToGroup(string username, string inviteUrl) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ACCEPT_ROOM_MSG, data = new { wxid = username, invite_url = inviteUrl } }); + SendWeChatData(User.DwClientId, json); + } + + public override void AddOnewayFriend(string username) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ACCEPT_ONEWAY_FRIEND_MSG, data = new { wxid = username } }); + SendWeChatData(User.DwClientId, json); + } + + public override Task> GetFriendInfos() + { + try + { + var type = RobotIsRunType.获取好友列表; + //这里判断是否已经存在在获取所有好友信息,没有就去获取 + if (!User.IsGetDic.ContainsKey(type)) + { + User.IsGetDic[type] = false;//这里添加要查询类型,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DATA_FRIENDS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + } + + return Task.Factory.StartNew>(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetDic.ContainsKey(type) && User.IsGetDic[type])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetDic.ContainsKey(type))//等到解析完消息,解析完消息IsGetDic中的消息会被删除 + { + return User.Friends; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取好友列表", ex.Message); + } + return Task.FromResult>(null); + } + + public override Task UpdateFriendInfo(string username) + { //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsGetContactDic.ContainsKey(username)) + { + User.IsGetContactDic[username] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_UPDATE_WXID_MSG, data = new { wxid = username } }); + SendWeChatData(User.DwClientId, json); + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsGetContactDic.ContainsKey(username) && User.IsGetContactDic[username])//等待收到微信查询的消息 + { + do + { + if (!User.IsGetContactDic.ContainsKey(username))//等到解析完消息,解析完消息IsGetContactDic中的消息会被删除 + { + if (User.Friends.ContainsKey(username)) + return User.Friends[username]; + return null; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + + public override void UpdateGroupMemberInfo(string groupid) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_UPDATE_ROOM_MEMBER_MSG, data = new { room_wxid = groupid } }); + SendWeChatData(User.DwClientId, json); + } + + public override Task CheckZombie(string username) + { + try + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ZOMBIE_CHECK_MSG, data = new { wxid = username } }); + SendWeChatData(User.DwClientId, json); + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + var text = Common.GetCache($"CheckZombieResult-Wechat-{User.Wxid}-{username}"); + if (!string.IsNullOrEmpty(text)) + { + return text; + } + Thread.Sleep(500); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"僵尸粉检测:{username}", ex.Message); + } + return Task.FromResult(null); + } + + public override void AutoAcceptFriend(bool isAuto) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_AUTO_ACCEPT_FRIEND_MSG, data = new { auto = isAuto ? 1 : 0 } }); + SendWeChatData(User.DwClientId, json); + } + + public override void AutoAcceptFriendTransfer(bool isAuto) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_AUTO_ACCEPT_WCPAY_MSG, data = new { auto = isAuto ? 1 : 0 } }); + SendWeChatData(User.DwClientId, json); + } + + public override void AutoAcceptCard(bool isAuto) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_AUTO_ACCPET_CARD_MSG, data = new { auto = isAuto ? 1 : 0 } }); + SendWeChatData(User.DwClientId, json); + } + + public override void DecryptImage(string src_file, string dest_file) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_DECRYPT_IMG_MSG, data = new { src_file = src_file, dest_file = dest_file } }); + SendWeChatData(User.DwClientId, json); + } + + public override void OpenBrowser(string url) + { + url = url.Trim(); + if (!string.IsNullOrWhiteSpace(url)) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_OPEN_BROWSER_MSG, data = new { url = url } }); + SendWeChatData(User.DwClientId, json); + } + } + + public override Task GetUnReadMsgCount() + { + try + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_UNREAD_MSG_COUNT_CHANGE_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + var text = Common.GetCache($"UnReadMsgCountResult-Wechat-{User.Wxid}"); + if (!string.IsNullOrEmpty(text)) + { + return int.Parse(text); + } + Thread.Sleep(500); + } while (endtime > DateTime.Now); + return 0; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取未读取消息数量:{User.Nickname}({User.Wxid})", ex.Message); + } + return Task.FromResult(0); + } + + public override void SetMsgReaded(string username) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SET_SESSION_READED_MSG, data = new { wxid = username } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void ToChatWindow(string username) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_TO_CHAT_MSG, data = new { to_wxid = username } }); + SendWeChatData(this.User.DwClientId, json); + } + + public override void ClearChatHistoryMsg() + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CLEAR_CHAT_HISTORY_MSG, data = new { } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void AutoAuthMiniAPPLogin(string appid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_AUTO_AUTH_MINIAPP_LOGIN, data = new { appid = appid } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (User.AutoAuthLoginMiNiApps.ContainsKey(appid)) + { + return User.AutoAuthLoginMiNiApps[appid]; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvMiniAppCode; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void DisableRevoke(bool status) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DISABLE_REVOKE_MSG, data = new { status = status ? 1 : 0 } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void AddSearchContact(string v1, string v2, string remark, int source_type) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_ADD_SEARCH_CONTACT_MSG, data = new { v1 = v1, v2 = v2, remark = remark, source_type = source_type } }); + SendWeChatData(this.User.DwClientId, json); + } + + public override void GerFriendDetails(string username) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_UPDATE_WXID_MSG, data = new { wxid = username } }); + SendWeChatData(this.User.DwClientId, json); + } + + public override void CheckUrlStatus(string url) + { + try + { + url = url.Trim(); + if (!string.IsNullOrWhiteSpace(url)) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CHECK_URL_STATUS_MSG, data = new { url = url } }); + //var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CHECK_URL_STATUS2_MSG, data = new { url = url } }); + SendWeChatData(this.User.DwClientId, json); + } + var result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + //if (CheckUrlCache.ContainsKey(url)) return CheckUrlCache[url]; + Cache cache = HttpRuntime.Cache; + object item = cache[url]; + if (item != null) + return int.Parse(item.ToString()); + } while (awaitTime >= DateTime.Now); + return -1; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CheckUrl(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCheckUrl; + msg.Status = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void Ser_GetCircles(string max_id = "0", string username = "") + { + var result = GetCircles(max_id, username).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleData; + msg.Data = result; + + socketClient.Send(msg); + } + + public override Task GetCircles(string max_id = "0", string username = "") + { + try + { + var key = username; + if (!string.IsNullOrWhiteSpace(username)) + { + User.IsOperCirCleInfoDic[key] = false; + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_TIMELINE_USER_MSG, data = new { username = username, first_page_md5 = "", max_id = max_id } }); + SendWeChatData(User.DwClientId, json); + } + else + { + key = "0"; + + //这里判断是否已经存在在获取的群邀请信息,没有就去获取 + if (!User.IsOperCirCleInfoDic.ContainsKey(key)) + { + User.IsOperCirCleInfoDic[key] = false;//这里添加要查询的群ID,状态为flase(还没收到微信那边返回的数据) + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SNS_TIMELINE_MSG, data = new { max_id = max_id } }); + SendWeChatData(User.DwClientId, json); + } + } + + return Task.Factory.StartNew(delegate () + { + DateTime endtime = DateTime.Now.AddSeconds(20); + do + { + if (User.IsOperCirCleInfoDic.ContainsKey(key) && User.IsOperCirCleInfoDic[key])//等待收到微信查询的消息 + { + do + { + if (!User.IsOperCirCleInfoDic.ContainsKey(key))//等到解析完消息,解析完消息IsOperCirCleInfoDic中的消息会被删除 + { + if (User.CirCleInfoOriDic.ContainsKey(key)) + return User.CirCleInfoOriDic[key]; + return null; + } + Thread.Sleep(200); + } while (endtime > DateTime.Now); + break; + } + Thread.Sleep(20); + } while (endtime > DateTime.Now); + return null; + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error($"获取朋友圈数据,{max_id} - {username}", ex.Message); + } + return Task.FromResult(null); + } + + public override void CircleLink(string object_id) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SNS_LIKE_MSG, data = new { object_id = object_id } }); + SendWeChatData(User.DwClientId, json); + } + + public override void CircleComment(string object_id, string content) + { + if (string.IsNullOrWhiteSpace(content)) return; + var comments = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + foreach (var comment in comments) + { + var json = JsonConvert.SerializeObject(new { type = MsgType.MT_SNS_COMMENT_MSG, data = new { object_id = object_id, content = comment } }); + SendWeChatData(User.DwClientId, json); + Thread.Sleep(1000); + } + } + + public override void CircleUpLoadImage(string data) + { + try + { + var path = string.Empty; + Bitmap bitmap = null; + if (data.StartsWith("http", StringComparison.CurrentCultureIgnoreCase)) + { + HttpHelper http = new HttpHelper(); + var item = http.GetItem(data); + item.ResultType = CsharpHttpHelper.Enum.ResultType.Byte; + + using (MemoryStream ms = new MemoryStream(http.GetHtml(item).ResultByte)) + { + using (Image mImage = Image.FromStream(ms, true)) + { + bitmap = new Bitmap(mImage); + path = HttpExtend.MapFile($@"{DateTime.Now.ToString("MMddhhmmssfff")}.{Common.GetImageExt(bitmap)}", @"Cache\IMAGE"); + bitmap.Save(path); + bitmap.Dispose(); + } + } + } + else + { + bitmap = Common.ConvertBase64ToImage(data); + using (MemoryStream stream = new MemoryStream()) + { + bitmap.Save(stream, ImageFormat.Jpeg); + byte[] data1 = new byte[stream.Length]; + stream.Seek(0, SeekOrigin.Begin); + stream.Read(data1, 0, Convert.ToInt32(stream.Length)); + bitmap = Common.CompressionImage(new MemoryStream(data1), 25); + } + + path = HttpExtend.MapFile($@"{DateTime.Now.ToString("MMddhhmmssfff")}.{Common.GetImageExt(bitmap)}", @"Cache\IMAGE"); + + bitmap.Save(path); + bitmap.Dispose(); + } + + if (!string.IsNullOrWhiteSpace(path) && File.Exists(path)) + { + LogHelper.GetSingleObj().Info(new StackTrace().GetFrame(0).GetMethod().Name, $"开始上传朋友圈图片:" + path); + + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_UPLOAD_IMAGE_MSG, data = new { path = path } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(60); + do + { + if (User.UpLoadImages.ContainsKey(path)) + { + return User.UpLoadImages[path]; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleUploadImageUrl; + msg.Data = result; + + socketClient.Send(msg); + } + else + { } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, $"上传朋友圈图片异常:{ex.Message},{ex.StackTrace}"); + } + } + + public override void SendCircle(string object_desc) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_POST_MSG, data = new { object_desc = object_desc } }); + User.SendCircleId = string.Empty; + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (!string.IsNullOrWhiteSpace(User.SendCircleId)) + { + return User.SendCircleId; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleReturnId; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + finally + { + User.SendCircleId = string.Empty; + } + } + } +} diff --git a/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Type.cs b/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Type.cs new file mode 100644 index 0000000..cbfb844 --- /dev/null +++ b/PCRobot/PCWechat/Routine/Wechat_Xiaoxie_Type.cs @@ -0,0 +1,502 @@ +namespace PCRobot.PCWechat.Routine +{ + public class Wechat_Xiaoxie_Type + { + #region 内部类 + + public enum MsgType : ushort + { + /// + /// DEBUG消息 + /// + MT_DEBUG_LOG = 11024, + /// + /// 登录消息 + /// + MT_USER_LOGIN = 11025, + /// + /// 注销消息 + /// + MT_USER_LOGOUT = 11026, + /// + /// 数据库查询消息 + /// + MT_SQL_QUERY = 11027, + /// + /// 获取我的信息消息 + /// + MT_DATA_OWNER_MSG = 11028, + /// + /// 获取单个好友消息 + /// + MT_DATA_WXID_MSG = 11029, + /// + /// 获取好友列表消息 + /// + MT_DATA_FRIENDS_MSG = 11030, + /// + /// 获取群聊列表消息 + /// + MT_DATA_CHATROOMS_MSG = 11031, + /// + /// 获取群成员消息 + /// + MT_DATA_CHATROOM_MEMBERS_MSG = 11032, + /// + /// 获取公众号消息 + /// + MT_DATA_PUBLICS_MSG = 11033, + /// + /// 从网络更新单个好友信息消息 + /// + MT_UPDATE_WXID_MSG = 11034, + /// + /// 从网络更新群成员信息消息 + /// + MT_UPDATE_ROOM_MEMBER_MSG = 11035, + /// + /// 发送文本消息 + /// + MT_SEND_TEXTMSG = 11036, + /// + /// 发送群@消息 + /// + MT_SEND_CHATROOM_ATMSG = 11037, + /// + /// 发送名片消息 + /// + MT_SEND_CARDMSG = 11038, + /// + /// 发送链接消息 + /// + MT_SEND_LINKMSG = 11039, + /// + /// 发送图片消息 + /// + MT_SEND_IMGMSG = 11040, + /// + /// 发送文件消息 + /// + MT_SEND_FILEMSG = 11041, + /// + /// 发送视频消息 + /// + MT_SEND_VIDEOMSG = 11042, + /// + /// 发送GIF消息 + /// + MT_SEND_GIFMSG = 11043, + /// + /// 接收文本消息 + /// + MT_RECV_TEXT_MSG = 11046, + /// + /// 接收图片消息 + /// + MT_RECV_PICTURE_MSG = 11047, + /// + /// 接收语音消息 + /// + MT_RECV_VOICE_MSG = 11048, + /// + /// 接收申请好友消息 + /// + MT_RECV_FRIEND_MSG = 11049, + /// + /// 接收名片消息 + /// + MT_RECV_CARD_MSG = 11050, + /// + /// 接收视频消息 + /// + MT_RECV_VIDEO_MSG = 11051, + /// + /// 接收表情消息 + /// + MT_RECV_EMOJI_MSG = 11052, + /// + /// 接收位置消息 + /// + MT_RECV_LOCATION_MSG = 11053, + /// + /// 接收链接消息 + /// + MT_RECV_LINK_MSG = 11054, + /// + /// 接收文件消息 + /// + MT_RECV_FILE_MSG = 11055, + /// + /// 接收小程序消息 + /// + MT_RECV_MINIAPP_MSG = 11056, + /// + /// 接收好友转账消息 + /// + MT_RECV_WCPAY_MSG = 11057, + /// + /// 接收系统消息 + /// + MT_RECV_SYSTEM_MSG = 11058, + /// + /// 接收撤回消息 + /// + MT_RECV_REVOKE_MSG = 11059, + /// + /// 接收其他未知消息 + /// + MT_RECV_OTHER_MSG = 11060, + /// + /// 接收应用类型未知消息 + /// + MT_RECV_OTHER_APP_MSG = 11061, + /// + /// 发送加好友消息 + /// + MT_ADD_FRIEND_MSG = 11062, + /// + /// 发送修改好友备注消息 + /// + MT_MOD_FRIEND_REMARK_MSG = 11063, + /// + /// 发送删除好友消息 + /// + MT_DEL_FRIEND_MSG = 11064, + /// + /// 发送同意加好友申请消息 + /// + MT_ACCEPT_FRIEND_MSG = 11065, + /// + /// 发送接收好友转帐消息 + /// + MT_ACCEPT_WCPAY_MSG = 11066, + /// + /// 发送同意进群邀请消息 + /// + MT_ACCEPT_ROOM_MSG = 11067, + /// + /// 发送创建群聊消息 + /// + MT_CREATE_ROOM_MSG = 11068, + /// + /// 发送邀请好友进群消息,40人以下 + /// + MT_INVITE_TO_ROOM_MSG = 11069, + /// + /// 发送邀请好友进群消息,40人以上 + /// + MT_INVITE_TO_ROOM_REQ_MSG = 11070, + /// + /// 发送删除群成员消息 + /// + MT_DEL_ROOM_MEMBER_MSG = 11071, + /// + /// 发送修改群名称消息 + /// + MT_MOD_ROOM_NAME_MSG = 11072, + /// + /// 发送修改群通知消息 + /// + MT_MOD_ROOM_NOTICE_MSG = 11073, + /// + /// 发送修改我在本群的昵称消息 + /// + MT_MOD_ROOM_MEMBER_NAME_MSG = 11074, + /// + /// 发送修改显示群昵称消息 + /// + MT_MOD_ROOM_SHOW_NAME_MSG = 11075, + /// + /// 发送保存到联系人消息 + /// + MT_SAVE_ROOM_TO_CONTACT_MSG = 11076, + /// + /// 发送退出并删除群消息 + /// + MT_QUIT_DEL_ROOM_MSG = 11077, + /// + /// 发送消息免打扰消息 + /// + MT_MOD_RECV_NOTIFY_MSG = 11078, + /// + /// 发送置顶消息 + /// + MT_MOD_CHAT_SESSION_TOP_MSG = 11079, + /// + /// 发送无痕清粉消息 + /// + MT_ZOMBIE_CHECK_MSG = 11080, + /// + /// 发送自动同意好友申请消息 + /// + MT_AUTO_ACCEPT_FRIEND_MSG = 11081, + /// + /// 发送自动同意好友转帐消息 + /// + MT_AUTO_ACCEPT_WCPAY_MSG = 11082, + /// + /// 发送自动进群邀请消息 + /// + MT_AUTO_ACCEPT_ROOM_MSG = 11083, + /// + /// 发送自动加名片消息 + /// + MT_AUTO_ACCPET_CARD_MSG = 11084, + /// + /// 发送解密图片消息 + /// + MT_DECRYPT_IMG_MSG = 11085, + /// + /// 发送打开浏览器消息 + /// + MT_OPEN_BROWSER_MSG = 11086, + /// + /// 获取用户登录二维码,于2019年5月28日新增 + /// + MT_RECV_QRCODE_MSG = 11087, + /// + /// 窗口变化通知消息 + /// + MT_WX_WND_CHANGE_MSG = 11088, + /// + /// 发送和获取未读数量变动消息 + /// + MT_UNREAD_MSG_COUNT_CHANGE_MSG = 11089, + /// + /// 与指定人聊天 + /// + MT_TO_CHAT_MSG = 11090, + /// + /// 当前聊天对象改变 + /// + MT_TALKER_CHANGE_MSG = 11091, + /// + /// 通过二维码进群 + /// + MT_ACCEPT_QRCODE_ROOM_MSG = 11092, + /// + /// 单向加好友 + /// + MT_ACCEPT_ONEWAY_FRIEND_MSG = 11093, + /// + /// 设置微信版本号 + /// + MT_CUSTOM_WX_VERSION_MSG = 11094, + /// + /// 接收到二微码付款消息 + /// + MT_RECV_QRCODE_WCPAY_MSG = 11095, + /// + /// 通过手机号/微信号/QQ号查询联系人 + /// + MT_SEARCH_CONTACT_MSG = 11096, + /// + /// 添加通过手机号/微信号/QQ号查询的联系人 + /// + MT_ADD_SEARCH_CONTACT_MSG = 11097, + /// + /// 群成员新增通知 + /// + MT_ROOM_ADD_MEMBER_NOTIFY_MSG = 11098, + /// + /// 群成员删除通知 + /// + MT_ROOM_DEL_MEMBER_NOTIFY_MSG = 11099, + /// + /// 通过接口创建群聊的通知 + /// + MT_ROOM_CREATE_NOTIFY_MSG = 11100, + /// + /// 退群或被踢通知 + /// + MT_ROOM_DEL_NOTIFY_MSG = 11101, + /// + /// 联系人新增通知 + /// + MT_CONTACT_ADD_NOITFY_MSG = 11102, + /// + /// 联系人删除通知 + /// + MT_CONTACT_DEL_NOTIFY_MSG = 11103, + /// + /// 注销登录 + /// + MT_QUIT_LOGIN_MSG = 11104, + /// + /// 无需确认退出 + /// + MT_QUIT_WECHAT_MSG = 11105, + /// + /// 当点击微信托盘图标和未读消息时消息 + /// + MT_TRAYICON_SHOW_WINDOW_MSG = 11106, + /// + /// 退还朋友的转账 + /// + MT_REFUSE_FRIEND_WCPAY_MSG = 11107, + /// + /// 清除聊天记录 + /// + MT_CLEAR_CHAT_HISTORY_MSG = 11108, + /// + /// 获取收藏列表 + /// + MT_DATA_FAVITEMS_MSG = 11109, + /// + /// 发送收藏 + /// + MT_SEND_FAVITEM_MSG = 11110, + /// + /// 收藏指定消息 + /// + MT_ADD_FAVITEM_FROM_MSG = 11111, + /// + /// 语音翻译 + /// + MT_TRANS_VOICE_MSG = 11112, + /// + /// 发送XML消息 + /// + MT_SEND_XMLMSG = 11113, + /// + /// 发送名版XML消息 + /// + MT_SEND_CARD_XMLMSG = 11114, + /// + /// 关注公众号 + /// + MT_ADD_PUBLIC_USER_MSG = 11115, + /// + /// 转发小程序 + /// + MT_FORWARD_APP_MSG = 11118, + /// + /// 开启/关闭防撤回消息 + /// + MT_DISABLE_REVOKE_MSG = 11121, + /// + /// 设置会话为已读 + /// + MT_SET_SESSION_READED_MSG = 11122, + /// + /// 检测URL在微信中是否有效 + /// + MT_CHECK_URL_STATUS_MSG = 11123, + /// + /// 检测URL在微信中是否有效2 + /// + MT_CHECK_URL_STATUS2_MSG = 11135, + ///// + ///// 微信二维码识别 + ///// + //MT_SCAN_QRCODE_IMG_MSG = 11127, + /// + /// 转发所有消息 + /// + MT_FORWARD_ANY_MSG = 11128, + /// + /// 自动授权登录小程序 + /// + MT_SNS_AUTO_AUTH_MINIAPP_LOGIN = 11136, + /// + /// 获取朋友圈首页 + /// + MT_SNS_TIMELINE_MSG = 11145, + /// + /// 评论 + /// + MT_SNS_COMMENT_MSG = 11146, + /// + /// 点赞 + /// + MT_SNS_LIKE_MSG = 11147, + /// + /// 发朋友圈 + /// + MT_SNS_POST_MSG = 11148, + /// + /// 朋友圈上传图片 + /// + MT_SNS_UPLOAD_IMAGE_MSG = 11149, + /// + /// 获取指定用户的朋友圈 + /// + MT_SNS_TIMELINE_USER_MSG = 11150, + } + + enum _EnRawMsgType + { + /// + /// 0x1 文本 + /// + WX_MSG_TEXT = 1, + /// + /// 0x3 图片 + /// + WX_MSG_PICTURE = 3, + /// + /// 0x22 语音 + /// + WX_MSG_VOICE = 34, + /// + /// 0x25 加好友请求 "from_wxid" : "fmessage" + /// + WX_MSG_FRIEND = 37, + /// + /// 0x2A 名片 + /// + WX_MSG_CARD = 42, + /// + /// 0x2B 视频 + /// + WX_MSG_VIDEO = 43, + /// + /// 0x2F 表情 + /// + WX_MSG_EMOJI = 47, + /// + /// 0x30 位置 + /// + WX_MSG_LOCATION = 48, + /// + /// 0x31 应用类型,子类型参考EnRawAppMsgType + /// + WX_MSG_APP = 49, + /// + /// 0x2710 系统消息 + /// + WX_MSG_SYSTEM = 10000, + /// + /// 0x2712 撤回消息 + /// + WX_MSG_REVOKE = 10002, + } + //EnRawMsgType; + // XML XPATH路径 /msg/appmsg/type/text() + enum _EnRawAppMsgType + { + /// + /// 链接(包含群邀请) + /// + WX_APPMSG_LINK = 5, + /// + /// 文件 + /// + WX_APPMSG_FILE = 6, + /// + /// 合并消息 + /// + WX_APPMSG_MUTIL = 19, + /// + /// 小程序 + /// + WX_APPMSG_MINIAPP = 33, + /// + /// 转帐 + /// + WX_APPMSG_WCPAY = 2000, + } + //EnRawAppMsgType; + #endregion + } +} \ No newline at end of file diff --git a/PCRobot/PCWechat/WechatBase.cs b/PCRobot/PCWechat/WechatBase.cs new file mode 100644 index 0000000..22d0ef6 --- /dev/null +++ b/PCRobot/PCWechat/WechatBase.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PCRobot.Entitys.Enterprise; + +namespace PCRobot.PCWechat +{ + /// + /// 微信基类 + /// + public abstract class WechatBase + { + + public WechatUser User { get; private set; } + public WechatBase(WechatUser User) + { + this.User = User; + } + + /// + /// 消息ID + /// + public string ServerMsgID { get; set; } + + /// + /// 获取列表 - 发送服务端 + /// + /// + public abstract void GetContact(bool isUpdata); + + /// + /// 删除好友 + /// + /// + public abstract void DeleteFriend(string msg); + + + /// + /// 修改好友备注【好友操作】 + /// + /// 好友账号 + /// 备注 + /// + public abstract void ModifyFriendRemark(string username, string remark); + + /// + /// 接收好友申请 + /// + /// + /// + /// + public abstract void AcceptFriend(string msg); + + /// + /// 发送消息 + /// + /// 接收者账号 + /// 发送的消息 + public abstract void SendMessage(string username, string message, string msgId = "", string usernick = "", + string quoteMess = ""); + + /// + /// 发送小程序 + /// + /// + /// + public abstract void SendProgramMessage(string username, string msg); + + /// + /// 发送文件消息 + /// + /// 接收者的微信 + /// 文件的路径 + public abstract void SendFile(string username, string file); + + /// + /// 发送名片 + /// + /// 接收者的微信 + /// 名片微信 + public abstract void SendCard(string username, string cardwxid); + + /// + /// 发送链接(卡片) + /// + /// 接收者的账号 + /// 链接标题 + /// 链接描述 + /// 链接地址 + /// 链接图片URL + public abstract void SendLinkMessage(string username, string title, string desc, string url, string image_url); + + /// + /// 发送图片 + /// + /// 接收者的微信 + /// 图片的路径 + public abstract void SendImage(string username, string imgPath); + + /// + /// 发送视频 + /// + /// 接收者的微信 + /// 视频路径 + public abstract void SendVideo(string username, string path); + + /// + /// 修改群公告(可用于@全体)【群操作】 + /// + /// 群ID + /// 新公告 + /// + public abstract void ModifyGroupNotice(string groupid, string notice); + + /// + /// 创建群 + /// + /// 两个以上用户账号 + public abstract Task CreateGroup(string[] usernames); + + /// + /// 发送服务端_创建群 + /// + /// + public abstract void Ser_CreateGroup(string[] usernames); + + /// + /// 删除群用户 + /// + /// 群ID + /// 要删除的用户账号 + public abstract void DeleteGroupMember(string groupid, string[] usernames); + + /// + /// 退出并删除群【群操作】 + /// + /// 群ID + /// + public abstract void QuitAndDelGroup(string groupid); + + /// + /// 修改群名称 + /// + /// 要修改的群账号 + /// 新群名 + /// + public abstract void ModifyGroupName(string groupid, string newName); + + /// + /// 获取个人信息 + /// + /// + public abstract Task GetSelfInfo(); + + /// + /// 发送服务端_获取个人信息 + /// + public abstract void Ser_GetSelfInfo(); + + /// + /// 发送服务端_获取好友或群信息 + /// + public abstract void Ser_GetContact(string username); + + /// + /// 获取单个用户信息 + /// + /// 获取信息的用户账号 + /// + public abstract Task GetFriendInfo(string username); + + /// + /// 获取群好友信息 + /// + /// 用户账号 + /// 群账号 + /// 是否刷新 + /// + public abstract void GetFriendInfo(string userName, string groupId, bool IsFlush = false); + + /// + /// 获取所有群组列表(不包含用户详细信息) + /// + /// + public abstract Task> GetGroupInfos(); + + + /// + /// 获取指定群组成员信息 + /// + /// 群ID + /// + public abstract Task GetGroupMemberInfo(string groupid); + + /// + /// 退出微信 + /// + /// + public abstract void OutLogin(); + + /// + /// 退出微信 + /// + public abstract void OutLogin(string message); + + /// + /// 微信版本 + /// + /// + public abstract string GetVersion(); + } +} diff --git a/PCRobot/PCWechat/WechatClient.cs b/PCRobot/PCWechat/WechatClient.cs new file mode 100644 index 0000000..85f0292 --- /dev/null +++ b/PCRobot/PCWechat/WechatClient.cs @@ -0,0 +1,330 @@ +using PCRobot.Pack; +using PCRobot.Utils; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using PCRobot.PCWechat.Enterprise; +using PCRobot.PCWechat.Routine; + +namespace PCRobot.PCWechat +{ + public class WechatClient + { + public static bool IsDebug { get; set; } + public static BeiyongType BeiYongT { get; set; } = BeiyongType.正版; + public static bool IsGzh { get; set; } + public static bool IsLog { get; set; } + static WechatClient() + { + Users = new Dictionary(); + } + + public static Dictionary Users { get; private set; } + + public delegate void RefUser(WechatUser user); + + /// + /// 更新用户信息事件 + /// + public static RefUser RefUserEvent; + + public static void OnRefUserEvent(WechatUser user, Dictionary WaitLoginResult = null) + { + if (RefUserEvent != null) + { + RefUserEvent?.Invoke(user); + var socketClient = EasySoc.GetSocket(); + if (socketClient != null) + { + var msg = new WechatStatus(); + msg.Cmd = user.Type == WechatType.Xiaoxie_QY ? PCRobotCMD.offline_workWeChat : PCRobotCMD.offline; + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = user.Type == WechatType.Xiaoxie_QY ? RobotType.客户端企业微信 : RobotType.客户端微信; + msg.Status = Status.在线; + msg.Uin = user.Uin; + socketClient.Send(msg); + } + if (WaitLoginResult != null) + { + if (WaitLoginResult.ContainsKey(user.Pid.ToString())) + { + Thread.Sleep(50); + var msgId = WaitLoginResult[user.Pid.ToString()]; + + var msg = new CommonResult(); + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = user.Type == WechatType.Xiaoxie_QY ? RobotType.客户端企业微信 : RobotType.客户端微信; + msg.MsgId = msgId; + msg.Cmd = user.Type == WechatType.Xiaoxie_QY ? PCRobotCMD.rcvLoginCode_workWeChat : PCRobotCMD.rcvLoginCode; + msg.Data = "成功"; + + socketClient.Send(msg); + } + } + } + } + + /// + /// 获取用户 + /// + /// wxid + /// 需要更新的DwClientId + /// + public static WechatUser GetUser(string wxid, uint dwClientId, WechatType type) + { + WechatUser u = null; + if (Users.ContainsKey(wxid)) + { + u = Users[wxid]; + } + else + { + u = new WechatUser() { Wxid = wxid }; + Users.Add(wxid, u); + // RefUserEvent?.Invoke(u); + } + u.Type = type; + u.DwClientId = dwClientId; + return u; + } + + /// + /// 通过dwClientId获取登陆的机器人对象 + /// + /// + /// + /// + public static WechatUser GetUser(uint dwClientId, WechatType type) + { + return Users.Values.FirstOrDefault(f => f.DwClientId == dwClientId && f.Type == type); + } + + public static WechatUser GetUser(string wxid) + { + return Users.FirstOrDefault(f => f.Key == wxid).Value; + } + + public static void RemoveUser(WechatUser user, bool kill = false) + { + try + { + var socketClient = EasySoc.GetSocket(); + if (socketClient != null) + { + WechatStatus msg = new WechatStatus(); + msg.Cmd = user.Type == WechatType.Xiaoxie_QY ? PCRobotCMD.offline_workWeChat : PCRobotCMD.offline; + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = user.Type == WechatType.Xiaoxie_QY ? RobotType.客户端企业微信 : RobotType.客户端微信; + msg.Status = Status.退出; + msg.Device = Common.GetDevice(); + msg.Uin = user.Uin; + socketClient.Send(msg); + } + + if (Users.ContainsKey(user.Wxid)) + { + Users.Remove(user.Wxid); + } + RefUserEvent?.Invoke(user); + + if ((IntPtr)user.Pid != IntPtr.Zero && kill) + { + Process[] myproc = Process.GetProcesses(); + foreach (Process items in myproc) + { + try + { + if (items.Id == user.Pid) + { + LogHelper.GetSingleObj().Info("系统", $"杀死进程.:{items.Id},Uin:{user.Uin},微信:{user.Nickname}({user.Wxid})"); + items.Kill(); + break; + } + } + catch (Exception) + { } + } + } + } + catch (Exception) + { + } + } + + /// + /// 是否为辅助输入,或者用户发送的消息 + /// + /// 消息来源 + /// 发送给谁 + /// 消息内容 + /// + public static bool IsAuxiliaryInput(string from_wxid, string to_wxid, string message) + { + //Console.WriteLine($"from_wxid:{from_wxid} to_wxid:{to_wxid} message:{message}"); + + //消息来源 - 为当前机器人列表,极有可能是辅助输入 + //if (Users.ContainsKey(from_wxid) && !to_wxid.Contains("@chatroom")) + if (from_wxid == to_wxid) return false; + if (Users.ContainsKey(from_wxid)) + { + if (Regex.IsMatch(message.Trim(), @"[\w\W]*?([\w\W]*?)")) + return false; + var robot = Users[from_wxid];//机器人 + //本消息,是否通过机器人自动发送过,如果为true. 表示非辅助输入 + if (Common.GetCache(robot.Wxid, to_wxid, message)) return false; + } + //Console.WriteLine("z" + message); + return true; + } + + #region 其他 + /// + /// 判断是否为辅助 + /// + /// 发送者的微信 + /// 接收者的微信 + /// 1.如果发送者的微信为机器人,那么为辅助返回1。 2.如果发送者和接收者的微信都为机器人那么不操作,返回-1。 3.如果发送者非机器人,接受者为机器人,那么为客户输入,返回0 + public static Assistance IsAssistance(string from_wxid, string to_wxid, uint dwClientId, WechatType wechatType = WechatType.Xiaoxie) + { + var ass = new Assistance() { type = AssistanceType.非辅助 }; + try + { + var robotName = string.Empty; + var robotNick = string.Empty; + var fromName = string.Empty; + var fromNaick = string.Empty;//TODO 昵称未赋值 + + var user = WechatClient.GetUser(dwClientId, wechatType); + if (user != null && from_wxid == user.Wxid)//机器人自己发送的消息 + { + //if (to_wxid.Contains("@chatroom"))//在群里不直接终止 + if (to_wxid.IsQun())//在群里不直接终止 + { + ass.robotName = from_wxid; + ass.robotNick = user.Nickname; + ass.fromName = from_wxid; + ass.fromNick = user.Nickname; + ass.type = AssistanceType.辅助; + } + else + { + //如果为辅助发送,需要将用户信息和机器人信息反回来 + ass.robotName = from_wxid; + ass.robotNick = user.Nickname; + ass.fromName = to_wxid; + ass.type = AssistanceType.辅助; + } + return ass; + } + else if (user != null) + { + ass.robotName = user.Wxid; + ass.robotNick = user.Nickname; + ass.fromName = from_wxid; + } + } + catch (Exception ex) + { } + return ass; + } + + /// + /// 保存辅助结果 + /// + public class Assistance + { + public AssistanceType type { get; set; } = AssistanceType.非辅助; + public string robotName { get; set; } = string.Empty; + public string robotNick { get; set; } = string.Empty; + public string fromName { get; set; } = string.Empty; + public string fromNick { get; set; } = string.Empty;//昵称未赋值 + } + + public enum AssistanceType + { + 终止 = 0, + 辅助 = 1, + 非辅助 = 2 + } + #endregion + + public static WechatBase GetApi(WechatUser user) + { + return GetApi(user.Wxid); + } + + public static WechatBase GetApi(string wxid) + { + var v = Users.ContainsKey(wxid) ? Users[wxid] : null; + if (v != null) + { + switch (v.Type) + { + case WechatType.Xiaoxie: + return new Wechat_Xiaoxie(v); + case WechatType.Xiaoxie_QY: + return new Wechat_Xiaoxie_QY(v); + default: + break; + } + + } + return null; + } + + public static void Install() + { + //if (Util.IsLinshi()) Task.Factory.StartNew(delegate { Wechat_Dazong.Install(); }); + //else Task.Factory.StartNew(delegate { Wechat_Xiaoxie.Install(); }); + try + { + Task.Factory.StartNew(delegate { Wechat_Xiaoxie.Install(); }); + Task.Factory.StartNew(delegate { Wechat_Xiaoxie_QY.Install(); }); + } + catch (Exception ex) + { } + } + public static void UnInstall() + { + try + { + Wechat_Xiaoxie.UnInstall(); + Wechat_Xiaoxie_QY.UnInstall(); + } + catch (Exception) + { } + } + public static uint StartWechat(WechatType type, string wxid = "") + { + try + { + switch (type) + { + case WechatType.Xiaoxie: + return Wechat_Xiaoxie.StartWechat(wxid); + case WechatType.Xiaoxie_QY: + return Wechat_Xiaoxie_QY.StartWechat(); + default: + break; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("StartWechat异常", $"{ex.Message} - {ex.StackTrace}"); + throw ex; + } + return 0; + } + + } +} diff --git a/PCRobot/PCWechat/WechatUser.cs b/PCRobot/PCWechat/WechatUser.cs new file mode 100644 index 0000000..6966936 --- /dev/null +++ b/PCRobot/PCWechat/WechatUser.cs @@ -0,0 +1,379 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PCRobot.Entitys.Enterprise; +using PCRobot.Utils; + +namespace PCRobot.PCWechat +{ + public enum WechatType + { + /// + /// 普通微信 + /// + Xiaoxie = 1, + /// + /// 企业微信 + /// + Xiaoxie_QY = 2, + } + public class WechatUser + { + public WechatUser() { } + + /// + /// 是否在检测僵尸粉 + /// + internal bool IsZombizRun = false; + + /// + /// 是否在获取信息操作中集合 + /// + public Dictionary IsGetDic { get; set; } = new Dictionary(); + + /// + /// 是否在获取群成员信息/好友信息/搜索信息/企业Cdn下载/通过好友 + /// + public Dictionary IsGetContactDic { get; internal set; } = new Dictionary(); + + /// + /// 是否在获取朋友圈数据/上传朋友圈图片 + /// + internal Dictionary IsOperCirCleInfoDic { get; set; } = new Dictionary(); + + /// + /// 类型 + /// + public WechatType Type { get; set; } + + /// + /// 句柄ID + /// + public int Pid { get; set; } + + /// + /// 客户端ID + /// + public uint DwClientId { get; set; } + + /// + /// 微信ID + /// + public string Wxid { get; set; } + + /// + /// 昵称 + /// + public string Nickname { get; set; } + + /// + /// 头像地址 + /// + public string HeaderUrl { get; set; } + + /// + /// 用户数据库地址 + /// + public string DBFile { get; set; } + public string Phone { get; set; } + + /// + /// 生命周期 + /// + public DateTime HeartBreakTime { get; set; } = DateTime.Now; + + /// + /// 微信Uin + /// + public string Uin { get; internal set; } + + /// + /// 个人微信用户数据 + /// + public Dictionary Friends = new Dictionary(); + /// + /// 个人群组数据 + /// + public Dictionary Groups = new Dictionary(); + + /// + /// 企业微信用户数据 + /// + public Dictionary WorkFriends { get; internal set; } = new Dictionary(); + /// + /// 企业微信群组数据 + /// + public Dictionary WorkGroups { get; internal set; } = new Dictionary(); + + /// + /// 企业搜索用户数据 + /// + public Dictionary FriendHandlerDic { get; internal set; } = new Dictionary(); + + /// + /// 企业Cdn文件数据 + /// + public Dictionary FileC2cCdnInfoDic { get; internal set; } = new Dictionary(); + + + + /// + /// 自动登录授权小程序 + /// + public Dictionary AutoAuthLoginMiNiApps = new Dictionary(); + + /// + /// 朋友圈上传图片,返回网络地址 + /// + public Dictionary UpLoadImages = new Dictionary(); + + /// + /// 发送朋友圈后返回的id + /// + public string SendCircleId; + + /// + /// 朋友圈数据保存,key为用户账号(0为非指定用户数据) + /// + internal Dictionary CirCleInfoOriDic { get; set; } = new Dictionary(); + + } + + /// + /// 获取普通微信运行类型 + /// + public enum RobotIsRunType + { + 获取收藏 = 0, + 获取群列表 = 1, + 获取好友列表 = 2,//如果是企业获取的是外部好友列表 + 获取公众号列表 = 3, + 上传朋友圈图片 = 4, + 获取未读消息数量 = 5, + 发送朋友圈 = 6, + 创建群 = 7, + + //企业特有 + 获取内部好友列表 = 50, + 获取自己的二维码 = 51, + 创建空外部群 = 52, + } + + public class FriendBase + { + /// + /// 昵称 + /// + public string nickname { get; set; } + + /// + /// 备注 + /// + public string remark { get; set; } + + /// + /// 群主ID + /// + public string manager_wxid { get; set; } = string.Empty; + + /// + /// 是否为管理员 + /// + public int is_manager { get; set; } = 0; + + + /// + /// 群成员 + /// + public string member_list { get; set; } = string.Empty; + } + + + /// + /// 个人微信信息 + /// + public class FriendInfo : FriendBase + { + /// + /// wxid + /// + public string wxid { get; set; } + + /// + /// 微信号 + /// + public string account { get; set; } + + /// + /// 头像地址 + /// + public string avatar { get; set; } + + + /// + /// 性别 0未知,1男,2女 + /// + public int sex { get; set; } + + /// + /// 祖国 + /// + public string country { get; set; } + + /// + /// 省份 + /// + public string province { get; set; } + + /// + /// 城市 + /// + public string city { get; set; } + + /// + /// 是否是僵尸粉 + /// + public int is_zombie { get; set; } = -1; + + } + + /// + /// 个人微信群信息 + /// + public class GroupInfo : GroupBase + { + public string wxid { get; set; } + /// + /// 昵称 + /// + public string nickname { get; set; } + /// + /// 群头像 + /// + public string avatar { get; set; } + + ///// + ///// 群主ID + ///// + //public string manager_wxid { get; set; } + + ///// + ///// 是否为管理员 + ///// + //public int is_manager { get; set; } + + /// + /// 群人数 + /// + public int total_member { get; set; } + + /// + /// 群成员 + /// + public List friends { get; set; } + } + + /// + /// 群基类 + /// + public class GroupBase + { + + } + + /// + /// 企业用户信息 + /// + public class WorkFriendInfo : FriendBase + { + /// + /// 账号 + /// + public string acctid { get; set; } + + /// + /// 手机号 + /// + public string mobile { get; set; } + + /// + /// 头像 + /// + public string avatar { get; set; } + /// + /// 会话id + /// + public string conversation_id { get; set; } + /// + /// 公司ID + /// + public string corp_id { get; set; } + /// + /// 用户描述 + /// + public string desc { get; set; } + /// + /// 对外职位名称 + /// + public string external_job { get; set; } + + /// + /// 公司内部职位 + /// + public string position { get; set; } + /// + /// 真实姓名 + /// + public string realname { get; set; } + + /// + /// 性别 + /// + public int sex { get; set; } + /// + /// 用户ID + /// + public string user_id { get; set; } + /// + /// 用户名称 + /// + public string username { get; set; } + } + + /// + /// 企业群数据 + /// + public class WorkGroupInfo : GroupBase + { + //{"conversation_id":"R:1970325073072411","create_user_id":"1688853956450720","is_manager":0,"nickname":"网络科技有限公司","total":5} + + /// + /// 会话ID + /// + public string conversation_id { get; set; } + ///// + ///// 群主 + ///// + //public string create_user_id { get; set; } + ///// + ///// 是否是管理员 + ///// + //public int is_manager { get; set; } + /// + /// 群昵称 + /// + public string GroupNick { get; set; } + /// + /// 群人数 + /// + public int total { get; set; } + /// + /// 群成员 + /// + public List friends { get; set; } + + } +} diff --git a/PCRobot/PCWechat/Wechat_Dazong - 复制.cs b/PCRobot/PCWechat/Wechat_Dazong - 复制.cs new file mode 100644 index 0000000..789196b --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Dazong - 复制.cs @@ -0,0 +1,1782 @@ +using CsharpHttpHelper; +using HPSocketCS; +using Newtonsoft.Json.Linq; +using NM_WeChat; +using PCRobot.Pack; +using PCRobot.Utils; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using static PCRobot.PCWechat.WechatClient; + +namespace PCRobot.PCWechat +{ + public class Wechat_Dazong : BaseApi + { + public Wechat_Dazong(WechatUser User) : base(User) { } + + static TcpPackServer HP_Server; + static NMCore nmCore; + static NMHelper nmHeler; + + #region 微信版本基础信息 + + //private const string Version = "2.7.1.88"; + //private const int PcOffSet = 0x138D6C0;//2.7.1.88 + //private const string PcMd5 = "ced61f308edd8cf3e2d864df285dc2af";//2.7.1.88 + + //private const string Version = "3.1.0.41"; + //private const int PcOffSet = 0x1885DE0;//3.1.0.41 + //private const string PcMd5 = "E9D55BB8A28F02FAC6645480FEC35B8D";//3.1.0.41 + + private const string Version = "3.2.1.154"; + private const int PcOffSet = 0x1AA82E8;//3.2.1.154 + private const string PcMd5 = "68B06E378747CD3C58935A70A9DBA431";//3.2.1.154 + + private const string NanMuCore = "NanMuCore_3.2.1.154.dll"; + + //private const string Version = "3.2.1.154"; + //private const int PcOffSet = 0x1CF9128;//3.3.5.50 + ////1D03368 + ////1D04228 + ////1D29830 + ////1D2C550 + //private const string PcMd5 = "68B06E378747CD3C58935A70A9DBA431";//3.3.5.50 + + //private const string NanMuCore = "NanMuCore_3.3.5.50.dll"; + + #endregion + + + public static void Install() + { + + + DllPath = HttpExtend.MapFile(NanMuCore, "Bin"); + if (IsKsfInstall) return; + + HP_Server = new TcpPackServer(); + nmHeler = new NMHelper(); + + HP_Server.OnAccept += new ServerEvent.OnAcceptEventHandler(OnAccept); + HP_Server.OnReceive += new ServerEvent.OnReceiveEventHandler(OnReceive); + HP_Server.OnClose += new ServerEvent.OnCloseEventHandler(OnClose); + HP_Server.MaxPackSize = 0x3FFFFF; + HP_Server.IpAddress = "127.0.0.1"; + HP_Server.Port = 0; + + if (HP_Server.Start() == true) + { + nmCore = new NMCore(HP_Server); + string szIPAddress = string.Empty; + ushort dwPort = 0; + HP_Server.GetListenAddress(ref szIPAddress, ref dwPort); + if (dwPort == 0) + { + MessageBox.Show("通信端口创建失败,请重试!", "错误"); + Environment.Exit(0); + } + nmHeler.Socket_Port = dwPort; + + try + { + NMHelper.NM_LinkWeChat(201912121, nmHeler.Socket_Port, 0, 0); + } + catch (Exception ex) + { } + + IsKsfInstall = true; + + return; + Process[] MyProcesses = Process.GetProcesses(); + var path1 = HttpExtend.MapPath("PCWechat"); + var path2 = HttpExtend.MapPath("PCWechat\\" + Version); + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == "WECHAT" && MyProcess.MainModule.FileName.StartsWith(path1)) + { + try + { + //判断微信版本 + //if (MyProcess.MainModule.FileName.StartsWith(path2) || is_inject) + if (MyProcess.MainModule.FileName.StartsWith(path2)) + { + var id = MyProcess.Id; + + bool flag = Task.Factory.StartNew(delegate + { + try + { + //var path = CsharpHttpHelper.HttpExtend.MapPath($"PCWechat\\" + Version); + + //string szDllPath = System.IO.Directory.GetCurrentDirectory() + "\\Bin\\"+NanMuCore; + //NMHelper.NM_CreateWeChatProcess(path, "WeChat.exe", szDllPath, nmHeler.Socket_Port); + NMHelper.NM_LinkWeChat(201912121, nmHeler.Socket_Port, 0, 0); + } + catch (Exception) + { } + }).Wait(5000); + if (!flag) + { + try + { + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + else + { + //终止掉,其他版本 + try + { + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + catch (Exception) + { } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } + } + + /// + /// 通信事件_登录成功 + /// + /// + /// + static void Event_Login(int ConnID, JObject RecvJson) + { + var wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + var user = WechatClient.GetUser(wxid, (uint)ConnID, WechatType.Dazong); + + user.Nickname = nmHeler.Json_GetString(RecvJson, "Nick", true); + user.Wxid = wxid; + user.HeaderUrl = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + + //user.DBFile = data["wx_user_dir"].ToString(); + int pid = 0; + nmHeler.Json_GetInt(RecvJson, "ProcessId", out pid); + user.Pid = pid; + user.Phone = nmHeler.Json_GetString(RecvJson, "phone", true); + user.Uin = GetUin(user.Pid); + WechatClient.OnRefUserEvent(user); + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试登录", $"{wxid} - {user}"); + } + /// + /// 获取微信的uin的值 + /// + /// + /// + public static string GetUin(int pid) + { + Process[] processes = Process.GetProcesses(); + foreach (Process process in processes) + { + if (process.Id == pid) + { + foreach (ProcessModule processModule in process.Modules) + { + if (processModule.ModuleName == "WeChatWin.dll") + { + //微信基址 + var WeChatWinBaseAddress = processModule.BaseAddress; + //Console.WriteLine("微信基址:\t" + "0x" + ((int)(processModule.BaseAddress)).ToString("X8") + Environment.NewLine); + var WxNameAddress = WeChatWinBaseAddress + PcOffSet; + var uinStr = Common.GetString(process.Handle, WxNameAddress, 4); + return uinStr; + } + } + break; + } + } + return string.Empty; + } + + /// + /// 关闭事件 + /// + /// + /// + /// + /// + /// + private static HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation enOperation, int errorCode) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == (uint)connId && f.Value.Type == WechatType.Dazong).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"WxCloseCallbackDaZong关闭回调,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v); + } + return HandleResult.Ok; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + return HandleResult.Error; + } + + private static HandleResult OnReceive(IServer sender, IntPtr connId, byte[] bytes) + { + try + { + string s_Recv = Encoding.Default.GetString(bytes); + JObject RecvJson = JObject.Parse(s_Recv); + Console.WriteLine(RecvJson); + int RecvType; + var method = new Action(delegate () + { + if (nmHeler.Json_GetInt(RecvJson, "PackType", out RecvType) == true) + { + if (RecvType == NMHelper.Recv_QRCode) + { + Event_QRCode(RecvJson); + } + else if (RecvType == NMHelper.Recv_Login) + { + Event_Login((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_Logout) + { + Event_Logout((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_Msg) + { + Event_RecvMsg((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_SelectTalker) + { + Event_SelectTalker((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetContactList) + { + Event_RecvContactList((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetGroupMember) + { + Event_RecvGroupMember((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetWxidInfo) + { + Event_RecvWxidInfo((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_AddFriend) + { + Event_AddFriend((int)connId, RecvJson);//主动申请加别人 + } + else if (RecvType == NMHelper.NM_CreateGroup) + { + Event_CreateGroup((int)connId, RecvJson);//建群 + } + else if (RecvType == NMHelper.NM_GetFavList) + { + Event_GetFavList((int)connId, RecvJson);//收藏 + } + else if (RecvType == NMHelper.NM_GetA8Key) + { + Event_GetA8Key((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_InvitePull) + { + Event_GroupInvite((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_QuitGroup) + { + Event_GroupQuit((int)connId, RecvJson); + } + } + }); + method.BeginInvoke(null, null); + return HandleResult.Ok; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + return HandleResult.Error; + } + + private static void Event_QRCode(JObject RecvJson) + { + try + { + int dwPid = 0; + nmHeler.Json_GetInt(RecvJson, "ProcessId", out dwPid); + string B64_QRCode = nmHeler.Json_GetString(RecvJson, "QRCode", false); + if (B64_QRCode != string.Empty) + { + byte[] imageBytes = Convert.FromBase64String(B64_QRCode); + MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length); + ms.Write(imageBytes, 0, imageBytes.Length); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GroupQuit(int ConnId, JObject RecvJson) + { + try + { + string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[群员动态-退群]" + RecvWxid; + string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + outLog += "群聊ID:" + GroupID; + JArray MemberList = RecvJson.Value("List"); + if (MemberList != null) + { + for (int i = 0; i < MemberList.Count; i++) + { + JToken JtMember = MemberList.ElementAt(i); + if (JtMember != null) + { + string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + + outLog += "[" + (i + 1).ToString() + "]"; + outLog += Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")"); + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GroupInvite(int ConnId, JObject RecvJson) + { + try + { + string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[群员动态-进群]" + RecvWxid; + string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + outLog = "群聊ID:" + GroupID; + JArray MemberList = RecvJson.Value("List"); + if (MemberList != null) + { + for (int i = 0; i < MemberList.Count; i++) + { + JToken JtMember = MemberList.ElementAt(i); + if (JtMember != null) + { + string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + string InvWxid = nmHeler.Json_GetString((JObject)JtMember, "InvWxid", true); + string InvNick = nmHeler.Json_GetString((JObject)JtMember, "InvNick", true); + outLog += "[" + (i + 1).ToString() + "]"; + outLog += "进群人:" + Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")"); + outLog += "邀请人:" + InvWxid + (InvNick == string.Empty ? string.Empty : "(" + InvNick + ")"); + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GetA8Key(int ConnId, JObject RecvJson) + { + try + { + string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[GetA8Key]" + RecvWxid; + string URL = nmHeler.Json_GetString(RecvJson, "URL", true); + string LastURL = nmHeler.Json_GetString(RecvJson, "LastURL", true); + outLog += "获取链接:" + URL; + outLog += "返回链接:" + LastURL; + + + //if (URL.IndexOf("mmsupport-bin/addchatroombyinvite") != -1) + //{ + // HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(URL); + // Request.Method = "POST"; + // Request.AllowAutoRedirect = false; + // Request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; + // Request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.556.400 QQBrowser/9.0.2524.400"; + // Request.Referer = URL; + // Request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8,en-us;q=0.6,en;q=0.5;q=0.4"); + // HttpWebResponse Response = (HttpWebResponse)Request.GetResponse(); + // string hLocation = Response.GetResponseHeader("Location").ToString(); + // if (hLocation != "") + // { + // if (hLocation.IndexOf("chatroom") != -1) + // { + // string GroupID = nmHeler.StringMid(hLocation, "weixin://jump/mainframe/", "@chatroom"); + // WriteLog("[接受群聊邀请]" + RecvWxid + "群聊ID:" + GroupID + "@chatroom"); + // } + // } + //} + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GetFavList(int connId, JObject recvJson) + { + try + { + //string outLog = "[收藏列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) ; + //JArray FavList = RecvJson.Value("List"); + //if (FavList != null) + //{ + // list_Fav.Items.Clear(); + // int dwCount = FavList.Count; + // if (dwCount != 0) + // { + // list_Fav.BeginUpdate(); + + // for (int i = 0; i < dwCount; i++) + // { + // JToken JtMember = FavList.ElementAt(i); + // if (JtMember != null) + // { + // int Type = nmHeler.Json_GetIntEx((JObject)JtMember, "Type"); + // string SearchKey = nmHeler.Json_GetString((JObject)JtMember, "SearchKey", true); + // string TypeName = nmHeler.GetFavType(Type); + // ListViewItem FavItem = new ListViewItem(); + // FavItem.Text = i.ToString(); + // FavItem.SubItems.Add(TypeName); + // FavItem.SubItems.Add(SearchKey == string.Empty ? "[" + TypeName + "文件]" : SearchKey); + // list_Fav.Items.Add(FavItem); + // } + // } + // list_Fav.EndUpdate(); + // outLog += "收藏列表读取成功,共" + dwCount.ToString() + "条记录!"; + // } + // else + // { + // outLog += "没有收藏"; + // } + //} + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_CreateGroup(int ConnId, JObject RecvJson) + { + //try + //{ + // string outLog = "[创建群聊]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + // string Data = nmHeler.Json_GetString(RecvJson, "Data", true); + // string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + // outLog += "建群返回:" + Data; + // outLog += GroupID == string.Empty ? string.Empty : "群聊ID:" + GroupID; + // JArray MemberList = RecvJson.Value("List"); + // if (MemberList != null) + // { + // outLog += "群员列表:"; + // for (int i = 0; i < MemberList.Count; i++) + // { + // JToken JtMember = MemberList.ElementAt(i); + // if (JtMember != null) + // { + // string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + // string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + // int state = nmHeler.Json_GetIntEx((JObject)JtMember, "State"); + // if (Wxid != string.Empty) + // { + // outLog += "[" + state.ToString() + "]" + (state == 0 ? "[成功]" : "[失败]"); + // outLog += Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")"); + // } + // } + // } + // } + + //} + //catch (Exception ex) + //{ + // LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + //} + } + + private static void Event_AddFriend(int ConnID, JObject RecvJson) + { + //try + //{ + // string outLog = "[添加好友]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + // int DataType = nmHeler.Json_GetIntEx(RecvJson, "DataType"); + // string Data = nmHeler.Json_GetString(RecvJson, "Data", true); + // int Type = nmHeler.Json_GetIntEx(RecvJson, "Type"); + // int AddType = nmHeler.Json_GetIntEx(RecvJson, "AddType"); + // string Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + // string v2 = nmHeler.Json_GetString(RecvJson, "V2", true); + // string Message = nmHeler.Json_GetString(RecvJson, "Message", true); + + // outLog += "添加返回:[" + DataType.ToString() + "]" + (DataType == 0 ? "已发送好友请求或已添加好友。" : Data); + // outLog += "添加类型:" + Type.ToString() + " 添加来源:" + AddType.ToString(); + // outLog += "Wxid:" + Wxid; + // outLog += v2 == string.Empty ? string.Empty : "v2:" + v2; + // outLog += Message == string.Empty ? string.Empty : "附加消息:" + Message; + + + // if (Type == 1 && DataType == -44) + // { + // //nmCore.NM_AddFriend(ConnID, 2, AddType, Wxid, v2, text_Friend_Message.Text); + // nmCore.NM_AddFriend(ConnID, 2, AddType, Wxid, v2, string.Empty);//TODO 改成了string.e + // } + //} + //catch (Exception ex) + //{ + //LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + //} + } + + private static void Event_RecvWxidInfo(int connId, JObject RecvJson) + { + try + { + //string outLog = "[下载详细信息]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + //if (dwState == -1) { outLog += "下载详细信息超时(原因:服务器无返回)!"; } + //else if (dwState == 0) { outLog += "下载详细信息失败(原因:可能是输入的Wxid不正确)!"; } + //else if (dwState == 1) + //{ + // string szGroupID = nmHeler.Json_GetString(RecvJson, "GroupId", true); + // NMHelper.nmWxidInfo MemberInfo = new NMHelper.nmWxidInfo(); + // MemberInfo.Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + // MemberInfo.WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + // MemberInfo.Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + // MemberInfo.V1 = nmHeler.Json_GetString(RecvJson, "v1", true); + // MemberInfo.HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + // MemberInfo.Address = nmHeler.Json_GetString(RecvJson, "Address", true); + // MemberInfo.Sex = MemberInfo.GetSex(nmHeler.Json_GetIntEx(RecvJson, "Sex")); + + // outLog += szGroupID == string.Empty ? string.Empty : "群ID:" + szGroupID + NewLine; + // outLog += "Wxid:" + MemberInfo.Wxid + NewLine; + // outLog += MemberInfo.WxNo == string.Empty ? string.Empty : "微信号:" + MemberInfo.WxNo + NewLine; + // outLog += "昵称:" + MemberInfo.Nick + NewLine; + // outLog += MemberInfo.V1 == string.Empty ? string.Empty : "v1:" + MemberInfo.V1 + NewLine; + // outLog += "性别:" + MemberInfo.Sex + NewLine; + // outLog += MemberInfo.Address == string.Empty ? string.Empty : "地区:" + MemberInfo.Address + NewLine; + // outLog += MemberInfo.HeadIMG == string.Empty ? string.Empty : "头像:" + MemberInfo.HeadIMG + NewLine; + //} + //WriteLog(outLog); + + + var wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + var WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + var Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + var V1 = nmHeler.Json_GetString(RecvJson, "v1", true); + var HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + var Address = nmHeler.Json_GetString(RecvJson, "Address", true); + //var Sex = MemberInfo.GetSex(nmHeler.Json_GetIntEx(RecvJson, "Sex")); + + if (Common.IsGzh(wxid, WechatClient.IsGzh)) return; + + var f = new FriendInfo(); + + f.account = WxNo; + f.wxid = wxid; + f.nickname = Nick; + f.remark = Nick; + f.avatar = HeadIMG; + f.city = string.Empty; + f.country = string.Empty; + f.province = string.Empty; + f.sex = nmHeler.Json_GetIntEx(RecvJson, "Sex"); + + var user = WechatClient.GetUser((uint)connId, WechatType.Dazong); + if (user == null) + return; + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend != null) + if (!user.Friends.TryTake(out friend)) return; + user.Friends.Add(f); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_RecvGroupMember(int ConnId, JObject RecvJson) + { + try + { + //string outLog = "[群员列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + if (dwState == 0)//群员列表读取失败! + return; + JArray m_List = RecvJson.Value("List"); + if (m_List != null) + { + //var recv_wxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true);//群主 + var user = WechatClient.GetUser((uint)ConnId, WechatType.Dazong); + if (user == null) + return; + var group_wxid = nmHeler.Json_GetString(RecvJson, "GroupID", true); + var Count = (int)RecvJson["Count"]; + var group = user.Groups.FirstOrDefault(z => z.wxid == group_wxid); + if (group == null) + { + group = new GroupInfo() { wxid = group_wxid, total_member = Count, friends = new List() }; + user.Groups.Add(group); + } + else + group.total_member = Count; + + for (int i = 0; i < m_List.Count; i++) + { + JToken JtMember = m_List.ElementAt(i); + if (JtMember != null) + { + var Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + var Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + var Mark = nmHeler.Json_GetString((JObject)JtMember, "Mark", true); + var HeadIMG = nmHeler.Json_GetString((JObject)JtMember, "HeadIMG", true); + + var f = new FriendInfo(); + f.account = Wxid;//item["account"]?.ToString(); + f.avatar = HeadIMG;//item["avatar"]?.ToString(); + f.city = string.Empty;//item["city"]?.ToString(); + f.country = string.Empty;//item["country"]?.ToString(); + f.nickname = Nick;//item["nickname"]?.ToString(); + f.province = string.Empty;//item["province"]?.ToString(); + f.remark = Mark;//item["remark"]?.ToString(); + f.sex = -1;//int.Parse(item["sex"]?.ToString()); + f.wxid = Wxid;//item["wxid"]?.ToString(); + + var friend = group.friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + group.friends.Add(f); + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_RecvContactList(int ConnId, JObject RecvJson) + { + try + { + var user = WechatClient.GetUser((uint)ConnId, WechatType.Dazong); + if (user == null) + return; + int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + if (dwState == 0)//通讯录列表读取失败! + return; + JArray m_List = RecvJson.Value("List"); + if (m_List != null) + { + for (int i = 0; i < m_List.Count; i++) + { + JToken JtMember = m_List.ElementAt(i); + if (JtMember != null) + { + var Type = nmHeler.Json_GetIntEx((JObject)JtMember, "Type"); + var List = nmHeler.Json_GetIntEx((JObject)JtMember, "List"); + var Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + var WxNo = nmHeler.Json_GetString((JObject)JtMember, "WxNo", true); + var Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + var Mark = nmHeler.Json_GetString((JObject)JtMember, "Mark", true); + var HeadIMG = nmHeler.Json_GetString((JObject)JtMember, "HeadIMG", true); + + if (Type == 8 || Type == 24 || Type == 29) + continue; + else if (Wxid.LastIndexOf("@chatroom") != -1) + { + ////UserItem.Text = MemberInfo.Nick == string.Empty ? "群聊" : MemberInfo.Nick; + ////UserItem.SubItems.Add(MemberInfo.Wxid); + ////UserItem.SubItems.Add(MemberInfo.WxNo); + ////UserItem.SubItems.Add(MemberInfo.List.ToString()); + ////UserItem.SubItems.Add(MemberInfo.HeadIMG); + ////list_Group.Items.Add(UserItem); + + var f = new FriendInfo(); + f.avatar = HeadIMG; + f.wxid = Wxid; + f.nickname = Nick; + f.remark = Mark; + f.manager_wxid = WxNo; + f.member_list = string.Empty; + + var group = user.Groups.FirstOrDefault(z => z.wxid == f.wxid); + if (group == null) + { + //群不存在,去获取群成员信息 + nmCore.NM_GetGroupMember(ConnId, f.wxid); + + group = new GroupInfo() { wxid = f.wxid, nickname = f.nickname, avatar = f.avatar, total_member = f.member_list.Length, friends = new List() }; + user.Groups.Add(group); + } + else + group.total_member = f.member_list.Length; + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + user.Friends.Add(f); + + } + else if (List != 2) + { + var f = new FriendInfo(); + f.wxid = Wxid; + //f.account = item["account"]?.ToString(); + f.nickname = Nick;//item["nickname"]?.ToString(); + f.remark = Mark;//item["remark"]?.ToString(); + f.avatar = HeadIMG;//item["avatar"]?.ToString(); + //f.sex = int.Parse(item["sex"]?.ToString()); + //f.city = item["city"]?.ToString(); + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + user.Friends.Add(f); + } + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_SelectTalker(int connId, JObject recvJson) + { + //throw new NotImplementedException(); + } + + private static void Event_RecvMsg(int _dwClientid, JObject RecvJson) + { + try + { + var dwClientid = (uint)_dwClientid; + //NMHelper.nmMsgInfo MsgInfo = new NMHelper.nmMsgInfo(); + var recv_wxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true);//机器人账号 + var wx_type = nmHeler.Json_GetIntEx(RecvJson, "Type"); + var State = nmHeler.Json_GetIntEx(RecvJson, "State"); + var Time = nmHeler.Json_GetIntEx(RecvJson, "Time"); + var IsSend = nmHeler.Json_GetIntEx(RecvJson, "Sender"); + var LocalMsgID = nmHeler.Json_GetIntEx(RecvJson, "LocalID"); + var ServerMsgID = nmHeler.Json_GetString(RecvJson, "ServerID", false); + var Wxid_1 = nmHeler.Json_GetString(RecvJson, "Wxid_1", true);//发送者的账号 //to_wxid 为群的时候 为群号 + var Nick_1 = nmHeler.Json_GetString(RecvJson, "Nick_1", true);//发送者的昵称 + var Wxid_2 = nmHeler.Json_GetString(RecvJson, "Wxid_2", true); //群内发送人的账号 + var Nick_2 = nmHeler.Json_GetString(RecvJson, "Nick_2", true);//发送者的昵称 + var raw_msg = nmHeler.Json_GetString(RecvJson, "Msg", true); + var Source = nmHeler.Json_GetString(RecvJson, "Source", true); + + + + var socketClient = EasySoc.GetSocket(); + if (wx_type == 1) + { + + if (Common.IsGzh(Wxid_1, WechatClient.IsGzh)) return; + + Assistance ass = null; + if (IsSend == 1) + { + var from_qun = Wxid_1.Contains("@chatroom"); + var from_wxid = from_qun ? Wxid_2 : Wxid_1; + + if (from_qun && string.IsNullOrWhiteSpace(Wxid_2)) return; + + if (!WechatClient.IsAuxiliaryInput(recv_wxid, from_qun ? Wxid_2 : Wxid_1, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + + ass = WechatClient.IsAssistance(recv_wxid, Wxid_1.Contains("@chatroom") ? Wxid_2 : Wxid_1, dwClientid, WechatType.Dazong); + // if (ass.type == WechatClient.AssistanceType.终止) return; + } + else + { + ass = WechatClient.IsAssistance(Wxid_1.Contains("@chatroom") ? Wxid_2 : Wxid_1, recv_wxid, dwClientid, WechatType.Dazong); + } + + if (ass.type == WechatClient.AssistanceType.终止) return; + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (Wxid_1.Contains("@chatroom")) + { + wmsg.FromGroupid = Wxid_1; + wmsg.FromUsername = Wxid_2; + wmsg.FromUsernick = Nick_1 == ass.robotName ? ass.robotNick : string.Empty; + } + else + { + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = ass.fromNick; + } + wmsg.FromMessage = raw_msg; + + socketClient.Send(wmsg); + } + + if (wx_type == 3 || wx_type == 34 || wx_type == 43 || wx_type == 49)//图片、语音、视频、文件 + { + var ass = WechatClient.IsAssistance(Wxid_1.Contains("@chatroom") ? Wxid_2 : Wxid_1, recv_wxid, dwClientid, WechatType.Dazong); + if (ass.type == WechatClient.AssistanceType.终止) return; + + WechatReceiveMsg msg = new WechatReceiveMsg(); + msg.Cmd = PCRobotCMD.rcvFile; + msg.IsSend = false; + if (wx_type == 3)//|| wx_type == 43)//图片 + { + //string FileData = nmHeler.Json_GetString(RecvJson, "File", false); + //if (FileData != string.Empty) + //{ + // byte[] FileBytes = Convert.FromBase64String(FileData); + // string FilePath = nmHeler.SaveFile(recv_wxid, Wxid_1, (wx_type == 3 ? "IMAGE" : "VOICE"), ServerMsgID, (wx_type == 3 ? "jpg" : "silk"), FileBytes); + + + + // msg.Cmd = PCRobotCMD.rcvImg; + // msg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + // var path = Common.CacheFilePath(ass.robotName, ass.fromName, "IMAGE", ServerMsgID, "jpg"); + // msg.FromMessage = $"[图片={path}]"; + // msg.FromUsername = ass.fromName; + // msg.FromUsernick = string.Empty;//没有获取昵称 + // msg.FromMessageType = WechatMsgType.图片; + // msg.FileCDNXML = raw_msg; + //} + //else + return; + } + else if (wx_type == 34)//语音 + { + //msg.FromMessage = string.Empty;//$"[语音={FilePath}]";//TODO 语音文件 + //msg.FromMessageType = WechatMsgType.语音; + return; + } + else if (wx_type == 43)//视频 + { + //var video = data["video"].ToString(); + //msg.FromMessage = $"[视频={video}]"; + //msg.FromMessageType = WechatMsgType.视频; + return; + } + else if (wx_type == 49)//文件/小程序 + { + //msg.FromMessage = string.Empty;//$"[文件={FilePath}]";//TODO 文件 + //msg.FromMessageType = WechatMsgType.文件; + + //转账自动收款 + if (IsSend == 0 && raw_msg.IndexOf("微信转账") != -1 && raw_msg.IndexOf("收到转账") != -1) + { + string state = Common.StringMid(raw_msg, "", ""); + string Transid = Common.StringMid(raw_msg, "transferid>"); + int dwTime = 0; + int.TryParse(Common.StringMid(raw_msg, ""), out dwTime); + if (state == "1" && Transid != string.Empty) + { + WechatReicevePay reicevePay = new WechatReicevePay(); + var user = WechatClient.GetUser(dwClientid, WechatType.Dazong); + if (user == null) + return; + reicevePay.RobotUsername = user.Wxid; + reicevePay.RobotUsernick = user.Nickname; + reicevePay.RobotType = RobotType.客户端微信; + reicevePay.FromUsername = recv_wxid; + reicevePay.FromUsernick = string.Empty;//没有获取昵称 + reicevePay.Cmd = PCRobotCMD.receivePay; + reicevePay.Invalidtime = dwTime.ToString(); + reicevePay.Transferid = Transid; + var reg = Regex.Match(raw_msg, "收到转账(?<金额>.+)元"); + if (reg.Success) + reicevePay.Money = double.Parse(reg.Groups["金额"].Value); + if (reicevePay.RobotUsernick == null) reicevePay.RobotUsernick = string.Empty; + socketClient.Send(reicevePay); + return; + } + } + else if (raw_msg.Trim().Contains(" + + var reg = Regex.Match(raw_msg, @"content=""(?<申请文本>[^""]*?)"""); + if (reg.Success) + wXApply.Message = reg.Groups["申请文本"].Value; + + reg = Regex.Match(raw_msg, @"sourceusername=""(?<账号>[^""]*?)"" sourcenickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + { + wXApply.OldFriendWxid = reg.Groups["账号"].Value; + wXApply.OldFriendNick = reg.Groups["昵称"].Value; + } + reg = Regex.Match(raw_msg, @"fromusername=""(?<账号>[^""]*?)"""); + if (reg.Success) + { + if (!string.IsNullOrWhiteSpace(reg.Groups["账号"].Value)) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + else + { + reg = Regex.Match(raw_msg, @"alias=""(?<账号>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + } + } + reg = Regex.Match(raw_msg, @"fromnickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendNick = reg.Groups["昵称"].Value; + + wXApply.Token = raw_msg;//这里好像要获取raw_msg 中 v1的值 + + socketClient.Send(wXApply); + } + + if (wx_type == 10000) + { + //新人入群 + if (!string.IsNullOrWhiteSpace(Wxid_1) && Wxid_1.Contains("@chatroom")) + { + var reg1 = Regex.Match(raw_msg, @"""(?<邀请人昵称>.*)""邀请""(?<新人昵称>.*)""加入了群聊"); + var reg2 = Regex.Match(raw_msg, @"你邀请""(?<新人昵称>.*)""加入了群聊"); + var reg3 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描""(?<邀请人昵称>.*)""分享的二维码加入群聊"); + var reg4 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描你分享的二维码加入群聊"); + + if (reg1.Success || reg2.Success || reg3.Success || reg4.Success) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Dazong); + if (user == null) + return; + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember; + newMember.RobotType = RobotType.客户端微信; + newMember.RobotUsername = user.Wxid; + newMember.RobotUsernick = user.Nickname; + + if (reg1.Success) + { + newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + newMember.MemberNick = reg1.Groups["新人昵称"].Value; + } + else if (reg2.Success) + { + newMember.SourceNick = newMember.RobotUsernick; + newMember.MemberNick = reg2.Groups["新人昵称"].Value; + } + else if (reg3.Success) + { + newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + newMember.MemberNick = reg3.Groups["新人昵称"].Value; + } + else if (reg4.Success) + { + newMember.SourceNick = newMember.RobotUsernick; + newMember.MemberNick = reg4.Groups["新人昵称"].Value; + } + + if (Wxid_1.Contains("@chatroom")) + { + newMember.GroupId = Wxid_1; + newMember.GroupNick = string.Empty; + } + socketClient.Send(newMember); + } + } + else//新增好友 + { + #region 添加好友成功 + var reg1 = Regex.Match(raw_msg, "^你已添加了(.*?),现在可以开始聊天了。$"); + var reg2 = Regex.Match(raw_msg, "^(.*?)刚刚把你添加到通讯录,现在可以开始聊天了。$"); + if (reg1.Success || reg2.Success) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Dazong); + if (user == null) + return; + WechatNewFriend msg = new WechatNewFriend(); + msg.Cmd = PCRobotCMD.newfriend; + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.FromUserName = Wxid_1; + msg.FromUserNick = reg1.Success ? reg1.Groups[1].Value : reg2.Groups[1].Value; + socketClient.Send(msg); + } + #endregion + } + } + + //自动填充消息内容,用于撤回消息 + //if (chk_RevokeFill.Checked == true && MsgInfo.IsSend == 1 && ConnID == (int)User.DwClientId) + //{ + // text_Recvke_Wxid.Text = MsgInfo.Wxid_1; + // text_Recvke_Sid.Text = MsgInfo.ServerMsgID; + // text_Recvke_Message.Text = MsgInfo.Msg; + //} + ////转账自动收款 + //if (chk_GetMoney.Checked == true && MsgInfo.IsSend == 0 && MsgInfo.Type == 49) + //{ + // if (MsgInfo.Msg.IndexOf("微信转账") != -1 && MsgInfo.Msg.IndexOf("收到转账") != -1) + // { + // string State = nmHeler.StringMid(MsgInfo.Msg, "", ""); + // string Transid = nmHeler.StringMid(MsgInfo.Msg, "transferid>"); + // int dwTime = 0; + // int.TryParse(nmHeler.StringMid(MsgInfo.Msg, ""), out dwTime); + // if (State == "1" && Transid != string.Empty) + // { + // nmCore.NM_GetMoney(ConnID, MsgInfo.Wxid_1, Transid, dwTime); + // } + // } + //} + ////名片消息自动填充数据 + //if (chk_CardFill.Checked == true && MsgInfo.IsSend == 0 && MsgInfo.Type == 42 && ConnID == (int)User.DwClientId) + //{ + // string v1 = nmHeler.StringMid(MsgInfo.Msg, "username=\"", "\" nickname="); + // string v2 = nmHeler.StringMid(MsgInfo.Msg, "antispamticket=\"", "\" /"); + // text_Friend_v1.Text = v1; + // text_Friend_v2.Text = v2; + //} + ////自动接受群聊邀请 + //if (chk_PassInvite.Checked == true && MsgInfo.IsSend == 0 && MsgInfo.Type == 49) + //{ + // if (MsgInfo.Msg.IndexOf("邀请你加入群聊") != -1 && MsgInfo.Msg.IndexOf("mmsupport-bin/addchatroombyinvite") != -1) + // { + // string InviteURL = nmHeler.StringMid(MsgInfo.Msg, ""); + // if (InviteURL != string.Empty) + // { + // nmCore.NM_GetA8Key(ConnID, MsgInfo.Wxid_1, InviteURL); + // } + // } + //} + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_Logout(int ConnID, JObject recvJson) + { + try + { + + var user = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == ConnID).Value; + if (user != null) + WechatClient.RemoveUser(user); + if (WechatClient.IsDebug) + { + LogHelper.GetSingleObj().Info("系统", $"LogOut_DaZong事件退出,Uin:{user.Uin},微信:{user.Nickname}({user.Wxid})"); + LogHelper.GetSingleObj().Debug("调试注销", $"{user.Wxid}"); + } + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr pClient) + { + nmCore.NM_Init((int)connId, "C#-864631110"); + return HandleResult.Ok; + } + + private static string DllPath; + + public override string GetVersion() + { + return Version; + } + + public static uint StartWechat() + { + try + { + var path = string.Empty; + + var WechatWinFile = CsharpHttpHelper.HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + var rst = MessageBox.Show("您的微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + var f = new WechatUpdate(Version); + f.ShowDialog(); + if (!f.IsOk) return 0; + } + else return 0; + } + //path = CsharpHttpHelper.HttpExtend.MapFile("WeChat.exe", $"PCWechat\\" + Version); + path = HttpExtend.MapPath($"PCWechat\\" + Version); + + string szDllPath = System.IO.Directory.GetCurrentDirectory() + "\\Bin\\" + NanMuCore; + var dwPid = NMHelper.NM_CreateWeChatProcess(path, "WeChat.exe", szDllPath, nmHeler.Socket_Port); + return (uint)dwPid; + } + catch (Exception ex) + { + } + return 0; + } + + public override void GetGroupAndFriendInfo(string groupId, string wxid) + { + try + { + GroupInfo group = null; + if (groupId.Contains("@chatroom")) + { + var g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + } + + if (group == null) + { + nmCore.NM_GetWxidInfo((int)User.DwClientId, groupId, wxid); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(5); + do + { + g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + { + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 获取朋友圈 + /// + /// + public override void FindCircles(string circleId, string username) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleData; + msg.Data = string.Empty; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void CreateRoom(string wxidData) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CreateRoom(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCreateRoom; + msg.GroupId = string.Empty; + msg.MemberTotal = 0; + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + + + + } + + + /// + /// 自动授权登录小程序 + /// + /// + public override void AutoAuthMiniAPPLogin(string appid) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvMiniAppCode; + msg.Data = string.Empty; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 发送朋友圈 + /// + /// + public override void SendCircle(string xmlmsg) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleReturnId; + msg.Data = string.Empty; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + finally + { + User.SendCircleId = string.Empty; + } + } + + public override void CircleUpLoadImage(string path) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleUploadImageUrl; + msg.Data = string.Empty; + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetGroupAndFriendInfo(string groupId, string wxid, bool flush = false) + { + try + { + GroupInfo group = null; + if (groupId.Contains("@chatroom")) + { + var g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + if (flush) + { + g.friends.Clear(); + } + else + { + var u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + } + } + + if (group == null) + { + nmCore.NM_GetWxidInfo((int)User.DwClientId, groupId, wxid); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(5); + do + { + g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + { + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void AgreeAddMe(string text) + { + try + { + nmCore.NM_PassApply((int)User.DwClientId, text); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void CloseWechat(string message) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == User.DwClientId && f.Value.Type == WechatType.Dazong).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"CloseWechatDaZong事件退出,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v, true); + if (!string.IsNullOrWhiteSpace(message)) + PCRobotForm.ErrorMessAction?.Invoke(message); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void DeleteFriend(string wxid) + { + nmCore.NM_DelFriend((int)User.DwClientId, wxid); + } + + public override void EditCotacts(string wxid, string remark) + { + nmCore.NM_SetFriendMark((int)User.DwClientId, wxid, remark); + } + + + + public override void GetGroupsNotInMember() + { + GetContact(); + var result = Task.Factory.StartNew(delegate () + { + Thread.Sleep(4000); + var groups = User.Friends.Where(f => f.wxid.Contains("@chatroom")).ToList(); + return groups == null ? string.Empty : HttpHelper.ObjectToJson(new Dictionary>() { { "data", groups } }); + }).Result; + + if (result == null) + result = HttpHelper.ObjectToJson(new Dictionary>() { { "data", User.Friends.Where(f => f.wxid.Contains("@chatroom")).ToList() } }); + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = result; + + socketClient.Send(msg); + } + + public override void PayTransferConfirm(string data) + { + try + { + var transferid = string.Empty; + var invalidtime = string.Empty; + var wxid = string.Empty; + var dic = HttpExtend.JsonToDictionary(data); + if (dic.ContainsKey("Transferid")) + transferid = dic["Transferid"].ToString(); + if (dic.ContainsKey("Invalidtime")) + invalidtime = dic["Invalidtime"].ToString(); + if (dic.ContainsKey("WxId")) + wxid = dic["WxId"].ToString(); + nmCore.NM_GetMoney((int)User.DwClientId, wxid, transferid, int.Parse(invalidtime)); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendFile(string wxid, string file) + { + try + { + nmCore.NM_SendFileMsg((int)User.DwClientId, NMHelper.NM_SendFile, wxid, file); + Common.SetCache(User.Wxid, wxid, file); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + public override void SendCard(string to_wxid, string card_wxid) + { + try + { + if (card_wxid.Contains("@chatroom")) + nmCore.NM_InviteToGroup((int)User.DwClientId, NMHelper.NM_InviteURL, card_wxid, new string[] { to_wxid }); + else + nmCore.NM_SendCardMsg((int)User.DwClientId, to_wxid, card_wxid); + Common.SetCache(User.Wxid, to_wxid, card_wxid); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendImage(string wxid, string file) + { + try + { + if (file.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + byte[] ImangByte = null; + string extension = Path.GetExtension(file); + extension = string.IsNullOrWhiteSpace(extension) ? ".jpg" : extension; + ImangByte = new System.Net.WebClient().DownloadData(file); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), extension); + if (!File.Exists(path)) + { + File.WriteAllBytes(path, ImangByte); + } + if (File.Exists(path)) + file = path; + } + else + { + if (!File.Exists(file)) + { + if (Common.IsBase64(file)) + { + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), "jpg"); + if (Common.Base64ToFileAndSave(file, path) && File.Exists(path)) + { + file = path; + } + } + else + { } + } + } + nmCore.NM_SendFileMsg((int)User.DwClientId, file.Trim().EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase) ? NMHelper.NM_SendGif : NMHelper.NM_SendPic, wxid, file); + Common.SetCache(User.Wxid, wxid, file); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void CheckUrl(string url) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CheckUrl(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCheckUrl; + msg.Status = 0; + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendMessage(string wxid, string message) + { + try + { + var json = string.Empty; + message = message.Replace("\r\n", "\n"); + if (Common.isXML(message)) + { + //小程序 + if (Regex.IsMatch(message, @"(?[^<]+)") || Regex.IsMatch(message, @"(.+?)")) + nmCore.NM_SendWeChatApp((int)User.DwClientId, wxid, message, string.Empty);//TODO 小程序未实现 + else + nmCore.NM_SendURLMsg((int)User.DwClientId, wxid, message); + } + else + nmCore.NM_SendTextMsg((int)User.DwClientId, wxid, new string[] { }, message); + Common.SetCache(User.Wxid, wxid, message); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendVideo(string wxid, string path) + { + try + { + SendFile(wxid, path); + Common.SetCache(User.Wxid, wxid, path); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void StateOpt(string wxid, int status) + { + try + { + nmCore.NM_StateOpt((int)User.DwClientId, 2, wxid, status == 1); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetWxidInfo(string wxid) + { + var u = User.Friends.FirstOrDefault(f => f.wxid == wxid); + if (u == null) + { + nmCore.NM_GetWxidInfo((int)User.DwClientId, string.Empty, wxid); + var friend = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + u = User.Friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) return u; + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + var socketClient = EasySoc.GetSocket(); + WechatContact msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = u == null ? string.Empty : HttpHelper.ObjectToJson(u); + + socketClient.Send(msg); + } + + public override void GetFriend(string wxid) + { + nmCore.NM_GetWxidInfo((int)User.DwClientId, string.Empty, wxid); + } + + public override void GetGroupMemer(string groupId) + { + try + { + nmCore.NM_GetGroupMember((int)User.DwClientId, groupId); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 卸载安装 + /// + public static void UnInstall() + { + try + { + HP_Server?.Destroy(); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + public override void GetContact() + { + try + { + //获取好友列表(数据库读取) + nmCore.NM_GetContactList((int)User.DwClientId); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + } +} diff --git a/PCRobot/PCWechat/Wechat_Dazong.cs b/PCRobot/PCWechat/Wechat_Dazong.cs new file mode 100644 index 0000000..e56bbab --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Dazong.cs @@ -0,0 +1,2010 @@ +using CsharpHttpHelper; +using HPSocketCS; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using NM_WeChat; +using PCRobot.Entitys; +using PCRobot.Enums; +using PCRobot.Pack; +using PCRobot.Utils; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using static PCRobot.PCWechat.WechatClient; + +namespace PCRobot.PCWechat +{ + public class Wechat_Dazong : BaseApi + { + public Wechat_Dazong(WechatUser User) : base(User) { } + + static TcpPackServer HP_Server; + static NMCore nmCore; + static NMHelper nmHeler; + + #region 微信版本基础信息 + + //private const string Version = "2.7.1.88"; + //private const int PcOffSet = 0x138D6C0;//2.7.1.88 + //private const string PcMd5 = "ced61f308edd8cf3e2d864df285dc2af";//2.7.1.88 + + //private const string Version = "3.1.0.41"; + //private const int PcOffSet = 0x1885DE0;//3.1.0.41 + //private const string PcMd5 = "E9D55BB8A28F02FAC6645480FEC35B8D";//3.1.0.41 + + //private const string Version = "3.2.1.154"; + //private const int PcOffSet = 0x1AA82E8;//3.2.1.154 + //private const string PcMd5 = "68B06E378747CD3C58935A70A9DBA431";//3.2.1.154 + + private const string Version = "3.3.5.50"; + private const int PcOffSet = 0x1CF9128;//3.3.5.50 + //1D03368 + //1D04228 + //1D29830 + //1D2C550 + private const string PcMd5 = "3E7D23A8B7AE5B1DE04B1B60A7AD3205";//3.3.5.50 + + private const string NanMuCore = "NanMuCore_3.3.5.50.dll"; + + + //private const string NanMuCore = "NanMuCore_3.2.1.154.dll"; + + //private const string Version = "3.2.1.154"; + //private const int PcOffSet = 0x1CF9128;//3.3.5.50 + ////1D03368 + ////1D04228 + ////1D29830 + ////1D2C550 + //private const string PcMd5 = "68B06E378747CD3C58935A70A9DBA431";//3.3.5.50 + + //private const string NanMuCore = "NanMuCore_3.3.5.50.dll"; + + #endregion + + + public static void Install() + { + if (IsKsfInstall) return; + try + { + DllPath = HttpExtend.MapFile(NanMuCore, "Bin"); + HP_Server = new TcpPackServer(); + nmHeler = new NMHelper(); + + HP_Server.OnAccept += new ServerEvent.OnAcceptEventHandler(OnAccept); + HP_Server.OnReceive += new ServerEvent.OnReceiveEventHandler(OnReceive); + HP_Server.OnClose += new ServerEvent.OnCloseEventHandler(OnClose); + HP_Server.MaxPackSize = 0x3FFFFF; + HP_Server.IpAddress = "127.0.0.1"; + HP_Server.Port = 0; + + if (HP_Server.Start() == true) + { + nmCore = new NMCore(HP_Server); + string szIPAddress = string.Empty; + ushort dwPort = 0; + HP_Server.GetListenAddress(ref szIPAddress, ref dwPort); + if (dwPort == 0) + { + MessageBox.Show("通信端口创建失败,请重试!", "错误"); + LogHelper.GetSingleObj().Info("KST获取通讯端口失败", "KST获取通讯端口失败,请稍后重试"); + //Environment.Exit(0); + } + nmHeler.Socket_Port = dwPort; + + NMHelper.NM_LinkWeChat(201912121, nmHeler.Socket_Port, 0, 0); + } + + ConformInject(); + } + catch (Exception ex) + { + MessageBox.Show($"检查登录异常:{ex.Message}"); + } + finally + { + IsKsfInstall = true; + } + } + + /// + /// 注入符合注入的微信 + /// + internal static void ConformInject() + { + var Pros = Process.GetProcesses(); + + var path1 = HttpExtend.MapPath("PCWechat"); + var path2 = HttpExtend.MapPath("PCWechat\\" + Version); + foreach (Process pro in Pros) + { + try + { + var name = pro.ProcessName.ToUpper(); + if (name == "WECHAT" && pro.MainModule.FileName.StartsWith(path1)) + { + try + { + //判断微信版本 + if (pro.MainModule.FileName.StartsWith(path2)) + { + var id = pro.Id; + var result = Task.Factory.StartNew(delegate + { + try + { + var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5.ToUpper() != PcMd5.ToUpper()) + return false; + else + { + return NMHelper.NM_LinkWeChat(201912121, nmHeler.Socket_Port, 0, 0) != 0; + } + } + catch { } + return false; + }).Wait(30000); + if (!result) + try { pro.Kill(); } catch { } + } + } + catch (Exception) + { } + } + } + catch { } + } + } + + /// + /// 通信事件_登录成功 + /// + /// + /// + static void Event_Login(int ConnID, JObject RecvJson) + { + var wxid = nmHeler.GetString(RecvJson, "Wxid", true); + var user = WechatClient.GetUser(wxid, (uint)ConnID, WechatType.Dazong); + + user.Nickname = nmHeler.GetString(RecvJson, "Nick", true); + user.Wxid = wxid; + user.HeaderUrl = nmHeler.GetString(RecvJson, "HeadIMG", true); + + //user.DBFile = data["wx_user_dir"].ToString(); + int pid = 0; + nmHeler.GetInt(RecvJson, "ProcessId", out pid); + user.Pid = pid; + user.Phone = nmHeler.GetString(RecvJson, "phone", true); + user.Uin = GetUin(user.Pid); + WechatClient.OnRefUserEvent(user); + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试登录", $"{wxid} - {user}"); + } + /// + /// 获取微信的uin的值 + /// + /// + /// + public static string GetUin(int pid) + { + Process[] processes = Process.GetProcesses(); + foreach (Process process in processes) + { + if (process.Id == pid) + { + foreach (ProcessModule processModule in process.Modules) + { + if (processModule.ModuleName == "WeChatWin.dll") + { + //微信基址 + var WeChatWinBaseAddress = processModule.BaseAddress; + //Console.WriteLine("微信基址:\t" + "0x" + ((int)(processModule.BaseAddress)).ToString("X8") + Environment.NewLine); + var WxNameAddress = WeChatWinBaseAddress + PcOffSet; + var uinStr = Common.GetString(process.Handle, WxNameAddress, 4); + return uinStr; + } + } + break; + } + } + return string.Empty; + } + + /// + /// 关闭事件 + /// + /// + /// + /// + /// + /// + private static HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation enOperation, int errorCode) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == (uint)connId && f.Value.Type == WechatType.Dazong).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"WxCloseCallbackDaZong关闭回调,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v); + } + return HandleResult.Ok; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + return HandleResult.Error; + } + + private static HandleResult OnReceive(IServer sender, IntPtr connId, byte[] bytes) + { + try + { + string s_Recv = Encoding.Default.GetString(bytes); + JObject RecvJson = JObject.Parse(s_Recv); + Console.WriteLine(RecvJson); + int RecvType; + ThreadPool.QueueUserWorkItem(z => + { + if (nmHeler.GetInt(RecvJson, "PackType", out RecvType) == true) + { + if (RecvType == NMHelper.Recv_QRCode) + { + Event_QRCode(RecvJson); + } + else if (RecvType == NMHelper.Recv_Login) + { + Event_Login((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_Logout) + { + Event_Logout((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_Msg) + { + Event_RecvMsg((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_SelectTalker) + { + Event_SelectTalker((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetContactList) + { + Event_RecvContactList((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetGroupMember) + { + Event_RecvGroupMember((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetWxidInfo) + { + Event_RecvWxidInfo((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_AddFriend) + { + Event_AddFriend((int)connId, RecvJson);//主动申请加别人 + } + else if (RecvType == NMHelper.NM_CreateGroup) + { + Event_CreateGroup((int)connId, RecvJson);//建群 + } + else if (RecvType == NMHelper.NM_GetFavList) + { + Event_GetFavList((int)connId, RecvJson);//收藏 + } + else if (RecvType == NMHelper.NM_GetA8Key) + { + Event_GetA8Key((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_InvitePull) + { + Event_GroupInvite((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_QuitGroup) + { + Event_GroupQuit((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetCircles) + { + Event_GetCircles((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetCircleDetails) + { + //Event_GetCircleDetails((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_CircleUpLoadImage) + { + Event_CircleUpLoadImage((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_SendCircle) + { + //Event_GetCircleDetails((int)connId, RecvJson); + } + } + }); + + return HandleResult.Ok; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + return HandleResult.Error; + } + + private static void Event_CircleUpLoadImage(int connId, JObject jObj) + { + try + { + var dwClientid = (uint)connId; + var recvWxid = nmHeler.GetString(jObj, "RecvWxid"); + var url_md5 = nmHeler.GetString(jObj, "url_md5");//05ddb266023345f6b428339bed5f6fd3 + var state = nmHeler.GetString(jObj, "state"); + var url_0 = nmHeler.GetString(jObj, "url_0"); + var url_150 = nmHeler.GetString(jObj, "url_150"); + + if (!string.IsNullOrWhiteSpace(url_0)) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + if (user.UpLoadImages.ContainsKey(url_md5)) + user.UpLoadImages.Remove(url_md5); + user.UpLoadImages.Add(url_md5, url_0); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_QRCode(JObject RecvJson) + { + try + { + int dwPid = 0; + nmHeler.GetInt(RecvJson, "ProcessId", out dwPid); + string B64_QRCode = nmHeler.GetString(RecvJson, "QRCode", false); + if (B64_QRCode != string.Empty) + { + byte[] imageBytes = Convert.FromBase64String(B64_QRCode); + MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length); + ms.Write(imageBytes, 0, imageBytes.Length); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GroupQuit(int ConnId, JObject RecvJson) + { + try + { + string RecvWxid = nmHeler.GetString(RecvJson, "RecvWxid", true); + string outLog = "[群员动态-退群]" + RecvWxid; + string GroupID = nmHeler.GetString(RecvJson, "GroupID", true); + outLog += "群聊ID:" + GroupID; + JArray MemberList = RecvJson.Value("List"); + if (MemberList != null) + { + for (int i = 0; i < MemberList.Count; i++) + { + JToken JtMember = MemberList.ElementAt(i); + if (JtMember != null) + { + string Wxid = nmHeler.GetString((JObject)JtMember, "Wxid", true); + string Nick = nmHeler.GetString((JObject)JtMember, "Nick", true); + + outLog += "[" + (i + 1).ToString() + "]"; + outLog += Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")"); + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GroupInvite(int ConnId, JObject RecvJson) + { + try + { + string RecvWxid = nmHeler.GetString(RecvJson, "RecvWxid", true); + string outLog = "[群员动态-进群]" + RecvWxid; + string GroupID = nmHeler.GetString(RecvJson, "GroupID", true); + outLog = "群聊ID:" + GroupID; + JArray MemberList = RecvJson.Value("List"); + if (MemberList != null) + { + for (int i = 0; i < MemberList.Count; i++) + { + JToken JtMember = MemberList.ElementAt(i); + if (JtMember != null) + { + string Wxid = nmHeler.GetString((JObject)JtMember, "Wxid", true); + string Nick = nmHeler.GetString((JObject)JtMember, "Nick", true); + string InvWxid = nmHeler.GetString((JObject)JtMember, "InvWxid", true); + string InvNick = nmHeler.GetString((JObject)JtMember, "InvNick", true); + outLog += "[" + (i + 1).ToString() + "]"; + outLog += "进群人:" + Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")"); + outLog += "邀请人:" + InvWxid + (InvNick == string.Empty ? string.Empty : "(" + InvNick + ")"); + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GetA8Key(int ConnId, JObject RecvJson) + { + try + { + string RecvWxid = nmHeler.GetString(RecvJson, "RecvWxid", true); + string outLog = "[GetA8Key]" + RecvWxid; + string URL = nmHeler.GetString(RecvJson, "URL", true); + string LastURL = nmHeler.GetString(RecvJson, "LastURL", true); + outLog += "获取链接:" + URL; + outLog += "返回链接:" + LastURL; + + + //if (URL.IndexOf("mmsupport-bin/addchatroombyinvite") != -1) + //{ + // HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(URL); + // Request.Method = "POST"; + // Request.AllowAutoRedirect = false; + // Request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; + // Request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.556.400 QQBrowser/9.0.2524.400"; + // Request.Referer = URL; + // Request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8,en-us;q=0.6,en;q=0.5;q=0.4"); + // HttpWebResponse Response = (HttpWebResponse)Request.GetResponse(); + // string hLocation = Response.GetResponseHeader("Location").ToString(); + // if (hLocation != "") + // { + // if (hLocation.IndexOf("chatroom") != -1) + // { + // string GroupID = nmHeler.StringMid(hLocation, "weixin://jump/mainframe/", "@chatroom"); + // WriteLog("[接受群聊邀请]" + RecvWxid + "群聊ID:" + GroupID + "@chatroom"); + // } + // } + //} + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GetFavList(int connId, JObject recvJson) + { + try + { + //string outLog = "[收藏列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) ; + //JArray FavList = RecvJson.Value("List"); + //if (FavList != null) + //{ + // list_Fav.Items.Clear(); + // int dwCount = FavList.Count; + // if (dwCount != 0) + // { + // list_Fav.BeginUpdate(); + + // for (int i = 0; i < dwCount; i++) + // { + // JToken JtMember = FavList.ElementAt(i); + // if (JtMember != null) + // { + // int Type = nmHeler.Json_GetIntEx((JObject)JtMember, "Type"); + // string SearchKey = nmHeler.Json_GetString((JObject)JtMember, "SearchKey", true); + // string TypeName = nmHeler.GetFavType(Type); + // ListViewItem FavItem = new ListViewItem(); + // FavItem.Text = i.ToString(); + // FavItem.SubItems.Add(TypeName); + // FavItem.SubItems.Add(SearchKey == string.Empty ? "[" + TypeName + "文件]" : SearchKey); + // list_Fav.Items.Add(FavItem); + // } + // } + // list_Fav.EndUpdate(); + // outLog += "收藏列表读取成功,共" + dwCount.ToString() + "条记录!"; + // } + // else + // { + // outLog += "没有收藏"; + // } + //} + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_CreateGroup(int ConnId, JObject RecvJson) + { + //try + //{ + // string outLog = "[创建群聊]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + // string Data = nmHeler.Json_GetString(RecvJson, "Data", true); + // string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + // outLog += "建群返回:" + Data; + // outLog += GroupID == string.Empty ? string.Empty : "群聊ID:" + GroupID; + // JArray MemberList = RecvJson.Value("List"); + // if (MemberList != null) + // { + // outLog += "群员列表:"; + // for (int i = 0; i < MemberList.Count; i++) + // { + // JToken JtMember = MemberList.ElementAt(i); + // if (JtMember != null) + // { + // string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + // string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + // int state = nmHeler.Json_GetIntEx((JObject)JtMember, "State"); + // if (Wxid != string.Empty) + // { + // outLog += "[" + state.ToString() + "]" + (state == 0 ? "[成功]" : "[失败]"); + // outLog += Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")"); + // } + // } + // } + // } + + //} + //catch (Exception ex) + //{ + // LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + //} + } + + private static void Event_AddFriend(int ConnID, JObject RecvJson) + { + //try + //{ + // string outLog = "[添加好友]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + // int DataType = nmHeler.Json_GetIntEx(RecvJson, "DataType"); + // string Data = nmHeler.Json_GetString(RecvJson, "Data", true); + // int Type = nmHeler.Json_GetIntEx(RecvJson, "Type"); + // int AddType = nmHeler.Json_GetIntEx(RecvJson, "AddType"); + // string Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + // string v2 = nmHeler.Json_GetString(RecvJson, "V2", true); + // string Message = nmHeler.Json_GetString(RecvJson, "Message", true); + + // outLog += "添加返回:[" + DataType.ToString() + "]" + (DataType == 0 ? "已发送好友请求或已添加好友。" : Data); + // outLog += "添加类型:" + Type.ToString() + " 添加来源:" + AddType.ToString(); + // outLog += "Wxid:" + Wxid; + // outLog += v2 == string.Empty ? string.Empty : "v2:" + v2; + // outLog += Message == string.Empty ? string.Empty : "附加消息:" + Message; + + + // if (Type == 1 && DataType == -44) + // { + // //nmCore.NM_AddFriend(ConnID, 2, AddType, Wxid, v2, text_Friend_Message.Text); + // nmCore.NM_AddFriend(ConnID, 2, AddType, Wxid, v2, string.Empty);//TODO 改成了string.e + // } + //} + //catch (Exception ex) + //{ + //LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + //} + } + + private static void Event_RecvWxidInfo(int connId, JObject RecvJson) + { + try + { + //string outLog = "[下载详细信息]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + //if (dwState == -1) { outLog += "下载详细信息超时(原因:服务器无返回)!"; } + //else if (dwState == 0) { outLog += "下载详细信息失败(原因:可能是输入的Wxid不正确)!"; } + //else if (dwState == 1) + //{ + // string szGroupID = nmHeler.Json_GetString(RecvJson, "GroupId", true); + // NMHelper.nmWxidInfo MemberInfo = new NMHelper.nmWxidInfo(); + // MemberInfo.Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + // MemberInfo.WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + // MemberInfo.Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + // MemberInfo.V1 = nmHeler.Json_GetString(RecvJson, "v1", true); + // MemberInfo.HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + // MemberInfo.Address = nmHeler.Json_GetString(RecvJson, "Address", true); + // MemberInfo.Sex = MemberInfo.GetSex(nmHeler.Json_GetIntEx(RecvJson, "Sex")); + + // outLog += szGroupID == string.Empty ? string.Empty : "群ID:" + szGroupID + NewLine; + // outLog += "Wxid:" + MemberInfo.Wxid + NewLine; + // outLog += MemberInfo.WxNo == string.Empty ? string.Empty : "微信号:" + MemberInfo.WxNo + NewLine; + // outLog += "昵称:" + MemberInfo.Nick + NewLine; + // outLog += MemberInfo.V1 == string.Empty ? string.Empty : "v1:" + MemberInfo.V1 + NewLine; + // outLog += "性别:" + MemberInfo.Sex + NewLine; + // outLog += MemberInfo.Address == string.Empty ? string.Empty : "地区:" + MemberInfo.Address + NewLine; + // outLog += MemberInfo.HeadIMG == string.Empty ? string.Empty : "头像:" + MemberInfo.HeadIMG + NewLine; + //} + //WriteLog(outLog); + + + var wxid = nmHeler.GetString(RecvJson, "Wxid", true); + var WxNo = nmHeler.GetString(RecvJson, "WxNo", true); + var Nick = nmHeler.GetString(RecvJson, "Nick", true); + var V1 = nmHeler.GetString(RecvJson, "v1", true); + var HeadIMG = nmHeler.GetString(RecvJson, "HeadIMG", true); + var Address = nmHeler.GetString(RecvJson, "Address", true); + //var Sex = MemberInfo.GetSex(nmHeler.Json_GetIntEx(RecvJson, "Sex")); + + if (Common.IsGzh(wxid, WechatClient.IsGzh)) return; + + var f = new FriendInfo(); + + f.account = WxNo; + f.wxid = wxid; + f.nickname = Nick; + f.remark = Nick; + f.avatar = HeadIMG; + f.city = string.Empty; + f.country = string.Empty; + f.province = string.Empty; + f.sex = nmHeler.GetIntEx(RecvJson, "Sex"); + + var user = WechatClient.GetUser((uint)connId, WechatType.Dazong); + if (user == null) + return; + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend != null) + if (!user.Friends.TryTake(out friend)) return; + user.Friends.Add(f); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_RecvGroupMember(int ConnId, JObject RecvJson) + { + try + { + //string outLog = "[群员列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + int dwState = nmHeler.GetIntEx(RecvJson, "State"); + if (dwState == 0)//群员列表读取失败! + return; + JArray m_List = RecvJson.Value("List"); + if (m_List != null) + { + //var recv_wxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true);//群主 + var user = WechatClient.GetUser((uint)ConnId, WechatType.Dazong); + if (user == null) + return; + var group_wxid = nmHeler.GetString(RecvJson, "GroupID", true); + var Count = (int)RecvJson["Count"]; + var group = user.Groups.FirstOrDefault(z => z.wxid == group_wxid); + if (group == null) + { + group = new GroupInfo() { wxid = group_wxid, total_member = Count, friends = new List() }; + user.Groups.Add(group); + } + else + group.total_member = Count; + + for (int i = 0; i < m_List.Count; i++) + { + JToken JtMember = m_List.ElementAt(i); + if (JtMember != null) + { + var Wxid = nmHeler.GetString((JObject)JtMember, "Wxid", true); + var Nick = nmHeler.GetString((JObject)JtMember, "Nick", true); + var Mark = nmHeler.GetString((JObject)JtMember, "Mark", true); + var HeadIMG = nmHeler.GetString((JObject)JtMember, "HeadIMG", true); + + var f = new FriendInfo(); + f.account = Wxid;//item["account"]?.ToString(); + f.avatar = HeadIMG;//item["avatar"]?.ToString(); + f.city = string.Empty;//item["city"]?.ToString(); + f.country = string.Empty;//item["country"]?.ToString(); + f.nickname = Nick;//item["nickname"]?.ToString(); + f.province = string.Empty;//item["province"]?.ToString(); + f.remark = Mark;//item["remark"]?.ToString(); + f.sex = -1;//int.Parse(item["sex"]?.ToString()); + f.wxid = Wxid;//item["wxid"]?.ToString(); + + var friend = group.friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + group.friends.Add(f); + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_RecvContactList(int ConnId, JObject RecvJson) + { + try + { + var user = WechatClient.GetUser((uint)ConnId, WechatType.Dazong); + if (user == null) + return; + int dwState = nmHeler.GetIntEx(RecvJson, "State"); + if (dwState == 0)//通讯录列表读取失败! + return; + JArray m_List = RecvJson.Value("List"); + if (m_List != null) + { + for (int i = 0; i < m_List.Count; i++) + { + JToken JtMember = m_List.ElementAt(i); + if (JtMember != null) + { + var Type = nmHeler.GetIntEx((JObject)JtMember, "Type"); + var List = nmHeler.GetIntEx((JObject)JtMember, "List"); + var Wxid = nmHeler.GetString((JObject)JtMember, "Wxid", true); + var WxNo = nmHeler.GetString((JObject)JtMember, "WxNo", true); + var Nick = nmHeler.GetString((JObject)JtMember, "Nick", true); + var Mark = nmHeler.GetString((JObject)JtMember, "Mark", true); + var HeadIMG = nmHeler.GetString((JObject)JtMember, "HeadIMG", true); + + if (Type == 8 || Type == 24 || Type == 29) + continue; + else if (Wxid.LastIndexOf("@chatroom") != -1) + { + ////UserItem.Text = MemberInfo.Nick == string.Empty ? "群聊" : MemberInfo.Nick; + ////UserItem.SubItems.Add(MemberInfo.Wxid); + ////UserItem.SubItems.Add(MemberInfo.WxNo); + ////UserItem.SubItems.Add(MemberInfo.List.ToString()); + ////UserItem.SubItems.Add(MemberInfo.HeadIMG); + ////list_Group.Items.Add(UserItem); + + var f = new FriendInfo(); + f.avatar = HeadIMG; + f.wxid = Wxid; + f.nickname = Nick; + f.remark = Mark; + f.manager_wxid = WxNo; + f.member_list = string.Empty; + + var group = user.Groups.FirstOrDefault(z => z.wxid == f.wxid); + if (group == null) + { + //群不存在,去获取群成员信息 + nmCore.NM_GetGroupMember(ConnId, f.wxid); + + group = new GroupInfo() { wxid = f.wxid, nickname = f.nickname, avatar = f.avatar, total_member = f.member_list.Length, friends = new List() }; + user.Groups.Add(group); + } + else + group.total_member = f.member_list.Length; + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + user.Friends.Add(f); + + } + else if (List != 2) + { + var f = new FriendInfo(); + f.wxid = Wxid; + //f.account = item["account"]?.ToString(); + f.nickname = Nick;//item["nickname"]?.ToString(); + f.remark = Mark;//item["remark"]?.ToString(); + f.avatar = HeadIMG;//item["avatar"]?.ToString(); + //f.sex = int.Parse(item["sex"]?.ToString()); + //f.city = item["city"]?.ToString(); + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + user.Friends.Add(f); + } + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_SelectTalker(int connId, JObject recvJson) + { + //throw new NotImplementedException(); + } + + private static void Event_RecvMsg(int _dwClientid, JObject RecvJson) + { + try + { + var dwClientid = (uint)_dwClientid; + //NMHelper.nmMsgInfo MsgInfo = new NMHelper.nmMsgInfo(); + var recv_wxid = nmHeler.GetString(RecvJson, "RecvWxid", true);//机器人账号 + var wx_type = nmHeler.GetIntEx(RecvJson, "Type"); + var State = nmHeler.GetIntEx(RecvJson, "State"); + var Time = nmHeler.GetIntEx(RecvJson, "Time"); + var IsSend = nmHeler.GetIntEx(RecvJson, "Sender"); + var LocalMsgID = nmHeler.GetIntEx(RecvJson, "LocalID"); + var ServerMsgID = nmHeler.GetString(RecvJson, "ServerID", false); + var Wxid_1 = nmHeler.GetString(RecvJson, "Wxid_1", true);//发送者的账号 //to_wxid 为群的时候 为群号 + var Nick_1 = nmHeler.GetString(RecvJson, "Nick_1", true);//发送者的昵称 + var Wxid_2 = nmHeler.GetString(RecvJson, "Wxid_2", true); //群内发送人的账号 + var Nick_2 = nmHeler.GetString(RecvJson, "Nick_2", true);//发送者的昵称 + var raw_msg = nmHeler.GetString(RecvJson, "Msg", true); + var Source = nmHeler.GetString(RecvJson, "Source", true); + + + + var socketClient = EasySoc.GetSocket(); + if (wx_type == 1) + { + + if (Common.IsGzh(Wxid_1, WechatClient.IsGzh)) return; + + Assistance ass = null; + if (IsSend == 1) + { + var from_qun = Wxid_1.Contains("@chatroom"); + var from_wxid = from_qun ? Wxid_2 : Wxid_1; + + if (from_qun && string.IsNullOrWhiteSpace(Wxid_2)) return; + + if (!WechatClient.IsAuxiliaryInput(recv_wxid, from_qun ? Wxid_2 : Wxid_1, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + + ass = WechatClient.IsAssistance(recv_wxid, Wxid_1.Contains("@chatroom") ? Wxid_2 : Wxid_1, dwClientid, WechatType.Dazong); + // if (ass.type == WechatClient.AssistanceType.终止) return; + } + else + { + ass = WechatClient.IsAssistance(Wxid_1.Contains("@chatroom") ? Wxid_2 : Wxid_1, recv_wxid, dwClientid, WechatType.Dazong); + } + + if (ass.type == WechatClient.AssistanceType.终止) return; + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (Wxid_1.Contains("@chatroom")) + { + wmsg.FromGroupid = Wxid_1; + wmsg.FromUsername = Wxid_2; + wmsg.FromUsernick = Nick_1 == ass.robotName ? ass.robotNick : string.Empty; + } + else + { + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = ass.fromNick; + } + wmsg.FromMessage = raw_msg; + + socketClient.Send(wmsg); + } + + if (wx_type == 3 || wx_type == 34 || wx_type == 43 || wx_type == 49)//图片、语音、视频、文件 + { + var ass = WechatClient.IsAssistance(Wxid_1.Contains("@chatroom") ? Wxid_2 : Wxid_1, recv_wxid, dwClientid, WechatType.Dazong); + if (ass.type == WechatClient.AssistanceType.终止) return; + + WechatReceiveMsg msg = new WechatReceiveMsg(); + msg.Cmd = PCRobotCMD.rcvFile; + msg.IsSend = false; + if (wx_type == 3)//|| wx_type == 43)//图片 + { + //string FileData = nmHeler.Json_GetString(RecvJson, "File", false); + //if (FileData != string.Empty) + //{ + // byte[] FileBytes = Convert.FromBase64String(FileData); + // string FilePath = nmHeler.SaveFile(recv_wxid, Wxid_1, (wx_type == 3 ? "IMAGE" : "VOICE"), ServerMsgID, (wx_type == 3 ? "jpg" : "silk"), FileBytes); + + + + // msg.Cmd = PCRobotCMD.rcvImg; + // msg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + // var path = Common.CacheFilePath(ass.robotName, ass.fromName, "IMAGE", ServerMsgID, "jpg"); + // msg.FromMessage = $"[图片={path}]"; + // msg.FromUsername = ass.fromName; + // msg.FromUsernick = string.Empty;//没有获取昵称 + // msg.FromMessageType = WechatMsgType.图片; + // msg.FileCDNXML = raw_msg; + //} + //else + return; + } + else if (wx_type == 34)//语音 + { + //msg.FromMessage = string.Empty;//$"[语音={FilePath}]";//TODO 语音文件 + //msg.FromMessageType = WechatMsgType.语音; + return; + } + else if (wx_type == 43)//视频 + { + //var video = data["video"].ToString(); + //msg.FromMessage = $"[视频={video}]"; + //msg.FromMessageType = WechatMsgType.视频; + return; + } + else if (wx_type == 49)//文件/小程序 + { + //msg.FromMessage = string.Empty;//$"[文件={FilePath}]";//TODO 文件 + //msg.FromMessageType = WechatMsgType.文件; + + //转账自动收款 + if (IsSend == 0 && raw_msg.IndexOf("微信转账") != -1 && raw_msg.IndexOf("收到转账") != -1) + { + string state = Common.StringMid(raw_msg, "", ""); + string Transid = Common.StringMid(raw_msg, "transferid>"); + int dwTime = 0; + int.TryParse(Common.StringMid(raw_msg, ""), out dwTime); + if (state == "1" && Transid != string.Empty) + { + WechatReicevePay reicevePay = new WechatReicevePay(); + var user = WechatClient.GetUser(dwClientid, WechatType.Dazong); + if (user == null) + return; + reicevePay.RobotUsername = user.Wxid; + reicevePay.RobotUsernick = user.Nickname; + reicevePay.RobotType = RobotType.客户端微信; + reicevePay.FromUsername = recv_wxid; + reicevePay.FromUsernick = string.Empty;//没有获取昵称 + reicevePay.Cmd = PCRobotCMD.receivePay; + reicevePay.Invalidtime = dwTime.ToString(); + reicevePay.Transferid = Transid; + var reg = Regex.Match(raw_msg, "收到转账(?<金额>.+)元"); + if (reg.Success) + reicevePay.Money = double.Parse(reg.Groups["金额"].Value); + if (reicevePay.RobotUsernick == null) reicevePay.RobotUsernick = string.Empty; + socketClient.Send(reicevePay); + return; + } + } + else if (raw_msg.Trim().Contains(" + + var reg = Regex.Match(raw_msg, @"content=""(?<申请文本>[^""]*?)"""); + if (reg.Success) + wXApply.Message = reg.Groups["申请文本"].Value; + + reg = Regex.Match(raw_msg, @"sourceusername=""(?<账号>[^""]*?)"" sourcenickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + { + wXApply.OldFriendWxid = reg.Groups["账号"].Value; + wXApply.OldFriendNick = reg.Groups["昵称"].Value; + } + reg = Regex.Match(raw_msg, @"fromusername=""(?<账号>[^""]*?)"""); + if (reg.Success) + { + if (!string.IsNullOrWhiteSpace(reg.Groups["账号"].Value)) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + else + { + reg = Regex.Match(raw_msg, @"alias=""(?<账号>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + } + } + reg = Regex.Match(raw_msg, @"fromnickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendNick = reg.Groups["昵称"].Value; + + wXApply.Token = raw_msg;//这里好像要获取raw_msg 中 v1的值 + + socketClient.Send(wXApply); + } + + if (wx_type == 10000) + { + //新人入群 + if (!string.IsNullOrWhiteSpace(Wxid_1) && Wxid_1.Contains("@chatroom")) + { + var reg1 = Regex.Match(raw_msg, @"""(?<邀请人昵称>.*)""邀请""(?<新人昵称>.*)""加入了群聊"); + var reg2 = Regex.Match(raw_msg, @"你邀请""(?<新人昵称>.*)""加入了群聊"); + var reg3 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描""(?<邀请人昵称>.*)""分享的二维码加入群聊"); + var reg4 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描你分享的二维码加入群聊"); + + if (reg1.Success || reg2.Success || reg3.Success || reg4.Success) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Dazong); + if (user == null) + return; + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember; + newMember.RobotType = RobotType.客户端微信; + newMember.RobotUsername = user.Wxid; + newMember.RobotUsernick = user.Nickname; + + if (reg1.Success) + { + newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + newMember.MemberNick = reg1.Groups["新人昵称"].Value; + } + else if (reg2.Success) + { + newMember.SourceNick = newMember.RobotUsernick; + newMember.MemberNick = reg2.Groups["新人昵称"].Value; + } + else if (reg3.Success) + { + newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + newMember.MemberNick = reg3.Groups["新人昵称"].Value; + } + else if (reg4.Success) + { + newMember.SourceNick = newMember.RobotUsernick; + newMember.MemberNick = reg4.Groups["新人昵称"].Value; + } + + if (Wxid_1.Contains("@chatroom")) + { + newMember.GroupId = Wxid_1; + newMember.GroupNick = string.Empty; + } + socketClient.Send(newMember); + } + } + else//新增好友 + { + #region 添加好友成功 + var reg1 = Regex.Match(raw_msg, "^你已添加了(.*?),现在可以开始聊天了。$"); + var reg2 = Regex.Match(raw_msg, "^(.*?)刚刚把你添加到通讯录,现在可以开始聊天了。$"); + if (reg1.Success || reg2.Success) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Dazong); + if (user == null) + return; + WechatNewFriend msg = new WechatNewFriend(); + msg.Cmd = PCRobotCMD.newfriend; + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.FromUserName = Wxid_1; + msg.FromUserNick = reg1.Success ? reg1.Groups[1].Value : reg2.Groups[1].Value; + socketClient.Send(msg); + } + #endregion + } + } + + //自动填充消息内容,用于撤回消息 + //if (chk_RevokeFill.Checked == true && MsgInfo.IsSend == 1 && ConnID == (int)User.DwClientId) + //{ + // text_Recvke_Wxid.Text = MsgInfo.Wxid_1; + // text_Recvke_Sid.Text = MsgInfo.ServerMsgID; + // text_Recvke_Message.Text = MsgInfo.Msg; + //} + ////转账自动收款 + //if (chk_GetMoney.Checked == true && MsgInfo.IsSend == 0 && MsgInfo.Type == 49) + //{ + // if (MsgInfo.Msg.IndexOf("微信转账") != -1 && MsgInfo.Msg.IndexOf("收到转账") != -1) + // { + // string State = nmHeler.StringMid(MsgInfo.Msg, "", ""); + // string Transid = nmHeler.StringMid(MsgInfo.Msg, "transferid>"); + // int dwTime = 0; + // int.TryParse(nmHeler.StringMid(MsgInfo.Msg, ""), out dwTime); + // if (State == "1" && Transid != string.Empty) + // { + // nmCore.NM_GetMoney(ConnID, MsgInfo.Wxid_1, Transid, dwTime); + // } + // } + //} + ////名片消息自动填充数据 + //if (chk_CardFill.Checked == true && MsgInfo.IsSend == 0 && MsgInfo.Type == 42 && ConnID == (int)User.DwClientId) + //{ + // string v1 = nmHeler.StringMid(MsgInfo.Msg, "username=\"", "\" nickname="); + // string v2 = nmHeler.StringMid(MsgInfo.Msg, "antispamticket=\"", "\" /"); + // text_Friend_v1.Text = v1; + // text_Friend_v2.Text = v2; + //} + ////自动接受群聊邀请 + //if (chk_PassInvite.Checked == true && MsgInfo.IsSend == 0 && MsgInfo.Type == 49) + //{ + // if (MsgInfo.Msg.IndexOf("邀请你加入群聊") != -1 && MsgInfo.Msg.IndexOf("mmsupport-bin/addchatroombyinvite") != -1) + // { + // string InviteURL = nmHeler.StringMid(MsgInfo.Msg, ""); + // if (InviteURL != string.Empty) + // { + // nmCore.NM_GetA8Key(ConnID, MsgInfo.Wxid_1, InviteURL); + // } + // } + //} + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_Logout(int ConnID, JObject recvJson) + { + try + { + var user = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == ConnID).Value; + if (user != null) + WechatClient.RemoveUser(user); + if (WechatClient.IsDebug) + { + LogHelper.GetSingleObj().Info("系统", $"LogOut_DaZong事件退出,Uin:{user.Uin},微信:{user.Nickname}({user.Wxid})"); + LogHelper.GetSingleObj().Debug("调试注销", $"{user.Wxid}"); + } + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static void Event_GetCircles(int _dwClientid, JObject jObj) + { + try + { + var dwClientid = (uint)_dwClientid; + + #region 数据结构 + //{"PackType":700001,"RecvWxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","List":[{"ID":"-4685137659200794410","Time":1640511323,"Wxid":"dwB1AGoAaQBhAGgAdQBhADAAOAA3ADYA","Nick":"SFHuaDNU","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADYAMQA2ADAANgA0ADEANAA1ADAAOAA3ADUANwAyADAANgBdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHUAagBpAGEAaAB1AGEAMAA4ADcANgBdAF0APgA8AC8AdQBzAGUAcgBuAGEAbQBlAD4APABjAHIAZQBhAHQAZQBUAGkAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAMQA2ADQAMAA1ADEAMQAzADIAMwBdAF0APgA8AC8AYwByAGUAYQB0AGUAVABpAG0AZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGgAbwB3AFQAeQBwAGUAPgA8AGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgAwADwALwBjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBjAGUAbgBlAD4APABwAHIAaQB2AGEAdABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcAByAGkAdgBhAHQAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAD4APAAhAFsAQwBEAEEAVABBAFsAEWImIDxPTk4JZ7lwqFJHZAoAHVLDXyhX6lQf/zIAMAAyADIAdF7Yj/2AOk4RYu1+KoIXVF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AEQAZQBzAGMAPgA8AGMAbwBuAHQAZQBuAHQAYQB0AHQAcgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAGMAbwBuAHQAZQBuAHQAYQB0AHQAcgA+ADwAcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APAAvAHMAbwB1AHIAYwBlAFUAcwBlAHIATgBhAG0AZQA+ADwAcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APAAvAHMAbwB1AHIAYwBlAE4AaQBjAGsATgBhAG0AZQA+ADwAcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAAvAHMAdABhAHQAaQBzAHQAaQBjAHMARABhAHQAYQA+ADwAdwBlAGEAcABwAEkAbgBmAG8APgA8AGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwALwBhAHAAcABVAHMAZQByAE4AYQBtAGUAPgA8AHAAYQBnAGUAUABhAHQAaAA+ADwALwBwAGEAZwBlAFAAYQB0AGgAPgA8AHYAZQByAHMAaQBvAG4APgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwB2AGUAcgBzAGkAbwBuAD4APABkAGUAYgB1AGcATQBvAGQAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAGQAZQBiAHUAZwBNAG8AZABlAD4APABzAGgAYQByAGUAQQBjAHQAaQBvAG4ASQBkAD4APAAvAHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AGkAcwBHAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AaQBzAEcAYQBtAGUAPgA8AG0AZQBzAHMAYQBnAGUARQB4AHQAcgBhAEQAYQB0AGEAPgA8AC8AbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwAcwB1AGIAVAB5AHAAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHMAdQBiAFQAeQBwAGUAPgA8AHAAcgBlAGwAbwBhAGQAUgBlAHMAbwB1AHIAYwBlAHMAPgA8AC8AcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYwBhAG4AdgBhAHMASQBuAGYAbwBYAG0AbAA+ADwALwBjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APABDAG8AbgB0AGUAbgB0AE8AYgBqAGUAYwB0AD4APABjAG8AbgB0AGUAbgB0AFMAdAB5AGwAZQA+ADwAIQBbAEMARABBAFQAQQBbADEANQBdAF0APgA8AC8AYwBvAG4AdABlAG4AdABTAHQAeQBsAGUAPgA8AGMAbwBuAHQAZQBuAHQAUwB1AGIAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABTAHUAYgBTAHQAeQBsAGUAPgA8AHQAaQB0AGwAZQA+AK5f4U8PXMaJkZg8AC8AdABpAHQAbABlAD4APABkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AC8AZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APABjAG8AbgB0AGUAbgB0AFUAcgBsAD4AaAB0AHQAcABzADoALwAvAHMAdQBwAHAAbwByAHQALgB3AGUAaQB4AGkAbgAuAHEAcQAuAGMAbwBtAC8AYwBnAGkALQBiAGkAbgAvAG0AbQBzAHUAcABwAG8AcgB0AC0AYgBpAG4ALwByAGUAYQBkAHQAZQBtAHAAbABhAHQAZQA/AHQAPQBwAGEAZwBlAC8AYwBvAG0AbQBvAG4AXwBwAGEAZwBlAF8AXwB1AHAAZwByAGEAZABlACYAYQBtAHAAOwB2AD0AMQA8AC8AYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAbQBlAGQAaQBhAEwAaQBzAHQAPgA8AG0AZQBkAGkAYQA+ADwAaQBkAD4APAAhAFsAQwBEAEEAVABBAFsAMQAzADcANgAxADYAMAA2ADQAMQA1ADIAMgAwADEANQAwADQANwAyAF0AXQA+ADwALwBpAGQAPgA8AHQAeQBwAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwA2AF0AXQA+ADwALwB0AHkAcABlAD4APAB0AGkAdABsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwARYiYgPE9OTglnuXCoUkdkCgAdUsNfKFfqVB//MgAwADIAMgB0XtiP/YA6ThFi7X4qghdUXQBdAD4APAAvAHQAaQB0AGwAZQA+ADwAZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APAAhAFsAQwBEAEEAVABBAFsAEWImIDxPTk4JZ7lwqFJHZAoAHVLDXyhX6lQf/zIAMAAyADIAdF7Yj/2AOk4RYu1+KoIXVF0AXQA+ADwALwBkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APAB1AHIAbAAgAHYAaQBkAGUAbwBtAGQANQA9ACIAYwBjAGYAYwA0AGEAZgA4ADAANABhAGYANABlAGQAZgA5AGQAZgAyADIAYgA4ADEAOQA1AGMAYwBjADEAZAAxACIAIAB0AHkAcABlAD0AIgAxACIAIABtAGQANQA9ACIAYwA4AGIANQA4ADYAZQBiADgAMwAwAGEAMABlADkAYwAxADMAZQBkADEAYgAwAGMAZgA1ADgAYQAzAGEAMwAwACIAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAHMAaAB6AGoAdwB4AHMAbgBzAC4AdgBpAGQAZQBvAC4AcQBxAC4AYwBvAG0ALwAxADAAMgAvADIAMAAyADAAMgAvAHMAbgBzAHYAaQBkAGUAbwBkAG8AdwBuAGwAbwBhAGQAPwBmAGkAbABlAGsAZQB5AD0AMwAwADMANAAwADIAMAAxADAAMQAwADQAMgAwADMAMAAxAGUAMAAyADAAMQA2ADYAMAA0ADAAMgA1ADMANAA4ADAANAAxADAAYwA4AGIANQA4ADYAZQBiADgAMwAwAGEAMABlADkAYwAxADMAZQBkADEAYgAwAGMAZgA1ADgAYQAzAGEAMwAwADAAMgAwADMAMgA1ADYAMAAxADYAMAA0ADAAZAAwADAAMAAwADAAMAAwADQANgAyADcANAA2ADYANwAzADAAMAAwADAAMAAwADAAMQAzADIAJgBoAHkAPQBTAEgAJgBzAHQAbwByAGUAaQBkAD0ANQA2ADEAYwA4ADMANwA1ADkAMAAwADAANgAxADUANAAzADIANAAxADQAMAAyAGMAZgAwADAAMAAwADAAMAA2ADYAMAAwADAAMAA0AGUAZQBhADUAMwA0ADgAMAA5ADYAZABlADkANgAwADkANgA1ADgAZQAyAGEAMQBlACYAZABvAHQAcgBhAG4AcwA9ADMAJgBlAGYAPQAzADAAXwAwACYAYgBpAHoAaQBkAD0AMQAwADIAMwBdAF0APgA8AC8AdQByAGwAPgA8AHQAaAB1AG0AYgAgAHQAeQBwAGUAPQAiADEAIgA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAOgAvAC8AdgB3AGUAaQB4AGkAbgB0AGgAdQBtAGIALgB0AGMALgBxAHEALgBjAG8AbQAvADEANQAwAC8AMgAwADIANQAwAC8AcwBuAHMAdgBpAGQAZQBvAGQAbwB3AG4AbABvAGEAZAA/AGYAaQBsAGUAawBlAHkAPQAzADAAMwA0ADAAMgAwADEAMAAxADAANAAyADAAMwAwADEAZQAwADIAMAAyADAAMAA5ADYAMAA0ADAAMgA1ADMANAA4ADAANAAxADAAYwA4AGUANgBlADEANQBjADIANQA2AGYAMQA0AGUAYwBmADMAYQA2ADYAYwBkAGEAMABhAGUANwAzADgAMwA0ADAAMgAwADIAMQA3AGIAZAAwADQAMABkADAAMAAwADAAMAAwADAANAA2ADIANwA0ADYANgA3ADMAMAAwADAAMAAwADAAMAAxADMAMgAmAGgAeQA9AFMASAAmAHMAdABvAHIAZQBpAGQAPQA1ADYAMQBjADgAMwA3ADUAOQAwADAAMAA1ADkAMwBlADkAMgA0ADEANAAwADIAYwBmADAAMAAwADAAMAAwADkANgAwADAAMAAwADQAZgAxAGEANQAzADQAOAAyADkANwAzADUAYgAwADAAYgA2ADUAYwAzAGQAZQA5AGUAJgBiAGkAegBpAGQAPQAxADAAMgAzAF0AXQA+ADwALwB0AGgAdQBtAGIAPgA8AHYAaQBkAGUAbwBEAHUAcgBhAHQAaQBvAG4APgA8ACEAWwBDAEQAQQBUAEEAWwAxADEALgAzADkAOQBdAF0APgA8AC8AdgBpAGQAZQBvAEQAdQByAGEAdABpAG8AbgA+ADwAcwBpAHoAZQAgAHQAbwB0AGEAbABTAGkAegBlAD0AIgA2ADAANwA3AC4AMAAiACAAdwBpAGQAdABoAD0AIgAyADAAMAAuADAAIgAgAGgAZQBpAGcAaAB0AD0AIgAzADYANAAuADAAIgA+ADwALwBzAGkAegBlAD4APAAvAG0AZQBkAGkAYQA+ADwALwBtAGUAZABpAGEATABpAHMAdAA+ADwALwBDAG8AbgB0AGUAbgB0AE8AYgBqAGUAYwB0AD4APABhAGMAdABpAG8AbgBJAG4AZgBvAD4APABhAHAAcABNAHMAZwA+ADwAbQBlAGQAaQBhAFQAYQBnAE4AYQBtAGUAPgA8AC8AbQBlAGQAaQBhAFQAYQBnAE4AYQBtAGUAPgA8AG0AZQBzAHMAYQBnAGUARQB4AHQAPgA8AC8AbQBlAHMAcwBhAGcAZQBFAHgAdAA+ADwAbQBlAHMAcwBhAGcAZQBBAGMAdABpAG8AbgA+ADwALwBtAGUAcwBzAGEAZwBlAEEAYwB0AGkAbwBuAD4APAAvAGEAcABwAE0AcwBnAD4APAAvAGEAYwB0AGkAbwBuAEkAbgBmAG8APgA8AGEAcABwAEkAbgBmAG8APgA8AGkAZAA+ADwALwBpAGQAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAbABvAGMAYQB0AGkAbwBuACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AEkAZAA9ACIAIgAgAHAAbwBpAE4AYQBtAGUAPQAiACIAIABwAG8AaQBBAGQAZAByAGUAcwBzAD0AIgAiACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AFQAeQBwAGUAPQAiADAAIgAgAGMAaQB0AHkAPQAiACIAPgA8AC8AbABvAGMAYQB0AGkAbwBuAD4APABwAHUAYgBsAGkAYwBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcAB1AGIAbABpAGMAVQBzAGUAcgBOAGEAbQBlAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdQByAGwAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB0AGgAdQBtAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHQAaAB1AG0AYgB1AHIAbAA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHcAZQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB3AGUAYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AC8AVABpAG0AZQBsAGkAbgBlAE8AYgBqAGUAYwB0AD4A"},{"ID":"-4685933857420406661","Time":1640416409,"Wxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","Nick":"d231fp1bnVsgACAAIAACMA==","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADYAMAA4ADEAMAAyADEANgAyADgAOQAxADQANAA5ADUANQBdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgAaQBkAF8AaABsAGcAbwByAG4AOAA0ADYAaQBoAHAAMgAyAF0AXQA+ADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADYANAAwADQAMQA2ADQAMAA5AF0AXQA+ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APABhAHAAcABJAG4AZgBvAD4APABpAGQAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQBdAF0APgA8AC8AaQBkAD4APAB2AGUAcgBzAGkAbwBuAD4ANQAzADwALwB2AGUAcgBzAGkAbwBuAD4APABhAHAAcABOAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAUQBRAPOXUE5dAF0APgA8AC8AYQBwAHAATgBhAG0AZQA+ADwAaQBuAHMAdABhAGwAbABVAHIAbAA+ADwALwBpAG4AcwB0AGEAbABsAFUAcgBsAD4APABmAHIAbwBtAFUAcgBsAD4APAAvAGYAcgBvAG0AVQByAGwAPgA8AGMAbABpAGMAawBhAGIAbABlAD4AMAA8AC8AYwBsAGkAYwBrAGEAYgBsAGUAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAD4APAAhAFsAQwBEAEEAVABBAFsA2X4RYgBOlplMa4R29mX0lV0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AEQAZQBzAGMAPgA8AGMAbwBuAHQAZQBuAHQAYQB0AHQAcgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAGMAbwBuAHQAZQBuAHQAYQB0AHQAcgA+ADwAcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APAAvAHMAbwB1AHIAYwBlAFUAcwBlAHIATgBhAG0AZQA+ADwAcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APAAvAHMAbwB1AHIAYwBlAE4AaQBjAGsATgBhAG0AZQA+ADwAcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAAvAHMAdABhAHQAaQBzAHQAaQBjAHMARABhAHQAYQA+ADwAdwBlAGEAcABwAEkAbgBmAG8APgA8AGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwALwBhAHAAcABVAHMAZQByAE4AYQBtAGUAPgA8AHAAYQBnAGUAUABhAHQAaAA+ADwALwBwAGEAZwBlAFAAYQB0AGgAPgA8AHYAZQByAHMAaQBvAG4APgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwB2AGUAcgBzAGkAbwBuAD4APABkAGUAYgB1AGcATQBvAGQAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAGQAZQBiAHUAZwBNAG8AZABlAD4APABzAGgAYQByAGUAQQBjAHQAaQBvAG4ASQBkAD4APAAvAHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AGkAcwBHAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AaQBzAEcAYQBtAGUAPgA8AG0AZQBzAHMAYQBnAGUARQB4AHQAcgBhAEQAYQB0AGEAPgA8AC8AbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwAcwB1AGIAVAB5AHAAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHMAdQBiAFQAeQBwAGUAPgA8AHAAcgBlAGwAbwBhAGQAUgBlAHMAbwB1AHIAYwBlAHMAPgA8AC8AcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYwBhAG4AdgBhAHMASQBuAGYAbwBYAG0AbAA+ADwALwBjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APABDAG8AbgB0AGUAbgB0AE8AYgBqAGUAYwB0AD4APABjAG8AbgB0AGUAbgB0AFMAdAB5AGwAZQA+ADwAIQBbAEMARABBAFQAQQBbADMAXQBdAD4APAAvAGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APABjAG8AbgB0AGUAbgB0AFMAdQBiAFMAdAB5AGwAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAGMAbwBuAHQAZQBuAHQAUwB1AGIAUwB0AHkAbABlAD4APAB0AGkAdABsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwDZfhFiAE6WmUxrhHb2ZfSVLQBoVHBnJk9dAF0APgA8AC8AdABpAHQAbABlAD4APABkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AC8AZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APABjAG8AbgB0AGUAbgB0AFUAcgBsAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcABzADoALwAvAGkALgB5AC4AcQBxAC4AYwBvAG0ALwB2ADgALwBwAGwAYQB5AHMAbwBuAGcALgBoAHQAbQBsAD8AcABsAGEAdABmAG8AcgBtAD0AMQAxACYAYQBwAHAAcwBoAGEAcgBlAD0AYQBuAGQAcgBvAGkAZABfAHEAcQAmAGEAcABwAHYAZQByAHMAaQBvAG4APQAxADEAMAAwADAAMQAwADYAJgBoAG8AcwB0AGUAdQBpAG4APQBvAEsANgBrAG8AdwBFAEEAbwBLADQAegA3AEsANgBQADcAZQBTAHEANwBLAC0AcwBvAGMAKgAqACYAcwBvAG4AZwBtAGkAZAA9ADAAMAA0AEIAaABRAGsAZQA0AGEAZABIAGMAZgAmAHQAeQBwAGUAPQAwACYAYQBwAHAAcwBvAG4AZwB0AHkAcABlAD0AMQAmAF8AdwB2AD0AMQAmAHMAbwB1AHIAYwBlAD0AdwBlAGkAeABpAG4AJgBzAGgAYQByAGUAZgByAG8AbQA9AGcAZQBkAGEAbgAmAGYAcgBvAG0AXwBpAGQAPQA3ADYAOQA4ADYAMgAyADcANQA5ACYAZgByAG8AbQBfAGkAZAB0AHkAcABlAD0AMAAmAGYAcgBvAG0AXwBuAGEAbQBlAD0ASgBVAFUAMQBKAFQAaABFAEoAVABoAEYASgBVAFUANABKAFUARgBHAEoAVQBGAEUATQBEAFkAdABNAFQAQQBsAFIAVQBZAGwAUQBrAFEAbABPAFUATQBsAFIAVABVAGwATwBUAEEAbABPAEUAVQBsAFIAVABrAGwATwBVAFEAbABPAFQASQBsAFIAVABZAGwATwBUAGcAbABRAFQAVQBsAFIAVABZAGwATwBVAE0AbABPAFUAWQBsAFIAVABjAGwATwBVAEUAbABPAEQAUQBsAFIAVABVAGwATwBVAEkAbABPAFUAVQBsAFIAVABVAGwAUQBrAFkAbABPAEQAWQAlADMARAAmAEEARABUAEEARwA9AGYAZgBzAGgAYQByAGUAXQBdAD4APAAvAGMAbwBuAHQAZQBuAHQAVQByAGwAPgA8AG0AZQBkAGkAYQBMAGkAcwB0AD4APABtAGUAZABpAGEAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADYAMAA4ADEAMAAyADEANwAwADAAMQA5ADEANAA1ADEANgBdAF0APgA8AC8AaQBkAD4APAB0AHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsAMgBdAF0APgA8AC8AdAB5AHAAZQA+ADwAdABpAHQAbABlAD4APAAvAHQAaQB0AGwAZQA+ADwAZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APAAvAGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAcAByAGkAdgBhAHQAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHAAcgBpAHYAYQB0AGUAPgA8AHUAcgBsACAAdAB5AHAAZQA9ACIAMQAiAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcAA6AC8ALwBzAGgAbQBtAHMAbgBzAC4AcQBwAGkAYwAuAGMAbgAvAG0AbQBzAG4AcwAvAEcARABBAE8AdAA1AGYATABrAEMAaQBhAEEAYgBnAE4AVABjAFUASwBwAFoAdgB5AHoATQBqADEAdQBjAFIAdgBuAHAAagAxAGYAMwBUAG8AYgBHAGoAYwBZAEsAdQB1AHQAdAB1AE0AVABVAGIAbABqADQASQAxAHkANwA3AEoASgBCAFoAUgBLAGkAYgB0AFgAeQBIADQAMAAvADAAXQBdAD4APAAvAHUAcgBsAD4APAB0AGgAdQBtAGIAIAB0AHkAcABlAD0AIgAxACIAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAHMAaABtAG0AcwBuAHMALgBxAHAAaQBjAC4AYwBuAC8AbQBtAHMAbgBzAC8ARwBEAEEATwB0ADUAZgBMAGsAQwBpAGEAQQBiAGcATgBUAGMAVQBLAHAAWgB2AHkAegBNAGoAMQB1AGMAUgB2AG4AcABqADEAZgAzAFQAbwBiAEcAagBjAFkASwB1AHUAdAB0AHUATQBUAFUAYgBsAGoANABJADEAeQA3ADcASgBKAEIAWgBSAEsAaQBiAHQAWAB5AEgANAAwAC8AMQA1ADAAXQBdAD4APAAvAHQAaAB1AG0AYgA+ADwAdgBpAGQAZQBvAEQAdQByAGEAdABpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAALgAwAF0AXQA+ADwALwB2AGkAZABlAG8ARAB1AHIAYQB0AGkAbwBuAD4APABzAGkAegBlACAAdABvAHQAYQBsAFMAaQB6AGUAPQAiADUANgAyADUALgAwACIAIAB3AGkAZAB0AGgAPQAiADEANQAwAC4AMAAiACAAaABlAGkAZwBoAHQAPQAiADEANQAwAC4AMAAiAD4APAAvAHMAaQB6AGUAPgA8AC8AbQBlAGQAaQBhAD4APAAvAG0AZQBkAGkAYQBMAGkAcwB0AD4APAAvAEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGEAYwB0AGkAbwBuAEkAbgBmAG8APgA8AGEAcABwAE0AcwBnAD4APABtAGUAZABpAGEAVABhAGcATgBhAG0AZQA+ADwALwBtAGUAZABpAGEAVABhAGcATgBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AD4APABtAGUAcwBzAGEAZwBlAEEAYwB0AGkAbwBuAD4APAAvAG0AZQBzAHMAYQBnAGUAQQBjAHQAaQBvAG4APgA8AGEAcABwAGkAZAA+AHcAeAA1AGEAYQAzADMAMwA2ADAANgA1ADUAMABkAGYAZAA1ADwALwBhAHAAcABpAGQAPgA8AC8AYQBwAHAATQBzAGcAPgA8AHMAYwBlAG4AZQA+ADAAPAAvAHMAYwBlAG4AZQA+ADwAdAB5AHAAZQA+ADAAPAAvAHQAeQBwAGUAPgA8AHUAcgBsAD4APAAvAHUAcgBsAD4APABuAGUAdwBXAG8AcgBkAGkAbgBnAEsAZQB5AD4APAAvAG4AZQB3AFcAbwByAGQAaQBuAGcASwBlAHkAPgA8AG4AZQB3AHQAeQBwAGUAPgAwADwALwBuAGUAdwB0AHkAcABlAD4APABpAG4AcwB0AGEAbABsAGUAZABXAG8AcgBkAGkAbgBnAD4APAAvAGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AHUAbgBpAG4AcwB0AGEAbABsAGUAZABXAG8AcgBkAGkAbgBnAD4APAAvAHUAbgBpAG4AcwB0AGEAbABsAGUAZABXAG8AcgBkAGkAbgBnAD4APAAvAGEAYwB0AGkAbwBuAEkAbgBmAG8APgA8AHMAdABhAHQARQB4AHQAUwB0AHIAPgA8ACEAWwBDAEQAQQBUAEEAWwBHAGgAUQBLAEUAbgBkADQATgBXAEYAaABNAHoATQB6AE4AagBBADIATgBUAFUAdwBaAEcAWgBrAE4AUQA9AD0AXQBdAD4APAAvAHMAdABhAHQARQB4AHQAUwB0AHIAPgA8AGwAbwBjAGEAdABpAG8AbgAgAHAAbwBpAEMAbABhAHMAcwBpAGYAeQBJAGQAPQAiACIAIABwAG8AaQBOAGEAbQBlAD0AIgAiACAAcABvAGkAQQBkAGQAcgBlAHMAcwA9ACIAIgAgAHAAbwBpAEMAbABhAHMAcwBpAGYAeQBUAHkAcABlAD0AIgAwACIAIABjAGkAdAB5AD0AIgAiAD4APAAvAGwAbwBjAGEAdABpAG8AbgA+ADwAcAB1AGIAbABpAGMAVQBzAGUAcgBOAGEAbQBlAD4APAAvAHAAdQBiAGwAaQBjAFUAcwBlAHIATgBhAG0AZQA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8AdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHUAcgBsAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8AdABoAHUAbQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB0AGgAdQBtAGIAdQByAGwAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB3AGUAYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdwBlAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAD4APAAvAFQAaQBtAGUAbABpAG4AZQBPAGIAagBlAGMAdAA+AA=="},{"ID":"-4685935678908722883","Time":1640416192,"Wxid":"dwB4AGkAZABfAHYAdgA3AHIAZQB2ADcAYQA0AHgAcABqADIAMgA=","Nick":"Pm0nWR9mIAACMA==","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADYAMAA4ADAAOAAzADkANAA4ADAAMAA4ADIAOAA3ADMAMwBdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgAaQBkAF8AdgB2ADcAcgBlAHYANwBhADQAeABwAGoAMgAyAF0AXQA+ADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADYANAAwADQAMQA2ADEAOQAyAF0AXQA+ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APABhAHAAcABJAG4AZgBvAD4APABpAGQAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQBdAF0APgA8AC8AaQBkAD4APAB2AGUAcgBzAGkAbwBuAD4ANQAzADwALwB2AGUAcgBzAGkAbwBuAD4APABhAHAAcABOAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAUQBRAPOXUE5dAF0APgA8AC8AYQBwAHAATgBhAG0AZQA+ADwAaQBuAHMAdABhAGwAbABVAHIAbAA+ADwALwBpAG4AcwB0AGEAbABsAFUAcgBsAD4APABmAHIAbwBtAFUAcgBsAD4APAAvAGYAcgBvAG0AVQByAGwAPgA8AGMAbABpAGMAawBhAGIAbABlAD4AMAA8AC8AYwBsAGkAYwBrAGEAYgBsAGUAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAD4APAAhAFsAQwBEAEEAVABBAFsAsosfd4R2XQBdAD4APAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwA+ADwAYwBvAG4AdABlAG4AdABhAHQAdAByAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABhAHQAdAByAD4APABzAG8AdQByAGMAZQBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APABzAG8AdQByAGMAZQBOAGkAYwBrAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APABzAHQAYQB0AGkAcwB0AGkAYwBzAEQAYQB0AGEAPgA8AC8AcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYQBwAHAAVQBzAGUAcgBOAGEAbQBlAD4APAAvAGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwAcABhAGcAZQBQAGEAdABoAD4APAAvAHAAYQBnAGUAUABhAHQAaAA+ADwAdgBlAHIAcwBpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHYAZQByAHMAaQBvAG4APgA8AGQAZQBiAHUAZwBNAG8AZABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AZABlAGIAdQBnAE0AbwBkAGUAPgA8AHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AC8AcwBoAGEAcgBlAEEAYwB0AGkAbwBuAEkAZAA+ADwAaQBzAEcAYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBpAHMARwBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AHIAYQBEAGEAdABhAD4APABzAHUAYgBUAHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcwB1AGIAVAB5AHAAZQA+ADwAcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwBwAHIAZQBsAG8AYQBkAFIAZQBzAG8AdQByAGMAZQBzAD4APAAvAHcAZQBhAHAAcABJAG4AZgBvAD4APABjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APAAvAGMAYQBuAHYAYQBzAEkAbgBmAG8AWABtAGwAPgA8AEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsANAAyAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFMAdAB5AGwAZQA+ADwAYwBvAG4AdABlAG4AdABTAHUAYgBTAHQAeQBsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFMAdQBiAFMAdAB5AGwAZQA+ADwAdABpAHQAbABlAD4APAAvAHQAaQB0AGwAZQA+ADwAZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APAAvAGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAcwA6AC8ALwBpAC4AeQAuAHEAcQAuAGMAbwBtAC8AdgA4AC8AcABsAGEAeQBzAG8AbgBnAC4AaAB0AG0AbAA/AHAAbABhAHQAZgBvAHIAbQA9ADEAMQAmAGEAcABwAHMAaABhAHIAZQA9AGEAbgBkAHIAbwBpAGQAXwBxAHEAJgBhAHAAcAB2AGUAcgBzAGkAbwBuAD0AMQAxADAAMAAwADEAMAA2ACYAaABvAHMAdABlAHUAaQBuAD0AbwBLADYAawBvAHcARQBBAG8ASwA0AHoANwBlAGMAcwBOAEsAYwBpADcAdwB2AEEANwBjACoAKgAmAHMAbwBuAGcAbQBpAGQAPQAwADAAMQBmAHIAawBZAGYAMgAyADEARQB5AGwAJgB0AHkAcABlAD0AMAAmAGEAcABwAHMAbwBuAGcAdAB5AHAAZQA9ADEAJgBfAHcAdgA9ADEAJgBzAG8AdQByAGMAZQA9AHcAZQBpAHgAaQBuACYAQQBEAFQAQQBHAD0AZgBmAHMAaABhAHIAZQBdAF0APgA8AC8AYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAbQBlAGQAaQBhAEwAaQBzAHQAPgA8AG0AZQBkAGkAYQA+ADwAaQBkAD4APAAhAFsAQwBEAEEAVABBAFsAMQAzADcANgAwADgAMAA4ADMAOQA1ADQAOAAyADIAMAA2ADUAMQAyAF0AXQA+ADwALwBpAGQAPgA8AHQAeQBwAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwA1AF0AXQA+ADwALwB0AHkAcABlAD4APAB0AGkAdABsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwCyix93hHZdAF0APgA8AC8AdABpAHQAbABlAD4APABkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8ACEAWwBDAEQAQQBUAEEAWwCCbYJtXQBdAD4APAAvAGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAcAByAGkAdgBhAHQAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHAAcgBpAHYAYQB0AGUAPgA8AHMAbwBuAGcAYQBsAGIAdQBtAHUAcgBsAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcAA6AC8ALwB3AHgAYQBwAHAALgB0AGMALgBxAHEALgBjAG8AbQAvADIAMAAyAC8AMgAwADMAMAA0AC8AcwB0AG8AZABvAHcAbgBsAG8AYQBkAD8AZgBpAGwAZQBrAGUAeQA9ADMAMAAzADUAMAAyADAAMQAwADEAMAA0ADIAMQAzADAAMQBmADAAMgAwADIAMAAwAGMAYQAwADQAMAAyADUAMwA0ADgAMAA0ADEAMAA4ADkAMAAxADAANgBiADgAZgBlADYAOAA3AGMAZgBhADEAZAAwADIAMwBkADcAMABjAGYAYgBjADQAZQA0AGUAMAAyADAAMwAwADEAMgA5ADMAYwAwADQAMABkADAAMAAwADAAMAAwADAANAA2ADIANwA0ADYANgA3ADMAMAAwADAAMAAwADAAMAAxADMAMQAmAGgAeQA9AFMASAAmAHMAdABvAHIAZQBpAGQAPQAzADIAMwAwADMAMgAzADEAMwAxADMAMgAzADIAMwA1ADMAMQAzADUAMwAwADMAOQAzADMAMwA2ADMAMAAzADAAMwAwADYANQA2ADQAMwA4ADMANwAzADIANgA0ADMANgA2ADMAMwA2ADMAMwA2ADQAMwAxADYANAA2ADQANgAzADYANQAzADUAMwA0ADYANgAzADAAMwA5ADMAMAAzADAAMwAwADMAMAAzADAAMwAwADYAMwA2ADEAJgBiAGkAegBpAGQAPQAxADAAMgAzAF0AXQA+ADwALwBzAG8AbgBnAGEAbABiAHUAbQB1AHIAbAA+ADwAdQByAGwAIAB0AHkAcABlAD0AIgAwACIAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAGMANgAuAHkALgBxAHEALgBjAG8AbQAvAHIAcwBjAC8AZgBjAGcAaQAtAGIAaQBuAC8AZgBjAGcAXwBwAHkAcQBfAHAAbABhAHkALgBmAGMAZwA/AHMAbwBuAGcAaQBkAD0AJgBzAG8AbgBnAG0AaQBkAD0AMAAwADEAZgByAGsAWQBmADIAMgAxAEUAeQBsACYAcwBvAG4AZwB0AHkAcABlAD0AMQAmAGYAcgBvAG0AdABhAGcAPQA0ADYAJgB1AGkAbgA9ADEAMQA1ADIAOQAyADEANQAwADQAOAA2ADkAOAAzADYANAAyADYAJgBjAG8AZABlAD0AQwA5AEQAMQA2AF0AXQA+ADwALwB1AHIAbAA+ADwAdABoAHUAbQBiACAAdAB5AHAAZQA9ACIAMQAiAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcAA6AC8ALwBzAGgAbQBtAHMAbgBzAC4AcQBwAGkAYwAuAGMAbgAvAG0AbQBzAG4AcwAvAGoANQBaAE0AUgB3AHQANwBTAEQAUQBGAHQATQBMAFcAWABWAEMAbABhAGYAagB3AGMAYQBtAHMAaABQAEoAZwBrAHQARQBEADcAMgBrAEkAcgBxAFgAOQBVAE0AVwBPAFAARQB5AFUAZAA4AGsARABzAHoARABpAGIAaQBiAGQARgB0ADYARABpAGMAVABRADkAYgBlAEUAegBzAC8AMQA1ADAAXQBdAD4APAAvAHQAaAB1AG0AYgA+ADwAdgBpAGQAZQBvAEQAdQByAGEAdABpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAALgAwAF0AXQA+ADwALwB2AGkAZABlAG8ARAB1AHIAYQB0AGkAbwBuAD4APABzAGkAegBlACAAdABvAHQAYQBsAFMAaQB6AGUAPQAiADMAMgA4ADAALgAwACIAIAB3AGkAZAB0AGgAPQAiADEANQAwAC4AMAAiACAAaABlAGkAZwBoAHQAPQAiADEANQAwAC4AMAAiAD4APAAvAHMAaQB6AGUAPgA8AC8AbQBlAGQAaQBhAD4APAAvAG0AZQBkAGkAYQBMAGkAcwB0AD4APABtAHUAcwBpAGMAUwBoAGEAcgBlAEkAdABlAG0APgA8AG0AdgBPAGIAagBlAGMAdABJAGQAPgA8AC8AbQB2AE8AYgBqAGUAYwB0AEkAZAA+ADwAbQB2AE4AbwBuAGMAZQBJAGQAPgA8AC8AbQB2AE4AbwBuAGMAZQBJAGQAPgA8AG0AdgBDAG8AdgBlAHIAVQByAGwAPgA8AC8AbQB2AEMAbwB2AGUAcgBVAHIAbAA+ADwAbQB2AE0AYQBrAGUAcgBGAGkAbgBkAGUAcgBOAGkAYwBrAG4AYQBtAGUAPgA8AC8AbQB2AE0AYQBrAGUAcgBGAGkAbgBkAGUAcgBOAGkAYwBrAG4AYQBtAGUAPgA8AG0AdgBTAGkAbgBnAGUAcgBOAGEAbQBlAD4Agm2CbTwALwBtAHYAUwBpAG4AZwBlAHIATgBhAG0AZQA+ADwAbQB2AEEAbABiAHUAbQBOAGEAbQBlAD4Asosfd4R2PAAvAG0AdgBBAGwAYgB1AG0ATgBhAG0AZQA+ADwAbQB2AE0AdQBzAGkAYwBHAGUAbgByAGUAPgA8AC8AbQB2AE0AdQBzAGkAYwBHAGUAbgByAGUAPgA8AG0AdgBJAHMAcwB1AGUARABhAHQAZQA+ADAAPAAvAG0AdgBJAHMAcwB1AGUARABhAHQAZQA+ADwAbQB2AEkAZABlAG4AdABpAGYAaQBjAGEAdABpAG8AbgA+ADwALwBtAHYASQBkAGUAbgB0AGkAZgBpAGMAYQB0AGkAbwBuAD4APABtAHUAcwBpAGMARAB1AHIAYQB0AGkAbwBuAD4AMgAzADQAMAAwADAAPAAvAG0AdQBzAGkAYwBEAHUAcgBhAHQAaQBvAG4APgA8AG0AdgBFAHgAdABJAG4AZgBvAD4APAAvAG0AdgBFAHgAdABJAG4AZgBvAD4APABtAHYATwBwAGUAcgBhAHQAaQBvAG4AVQByAGwAPgA8AC8AbQB2AE8AcABlAHIAYQB0AGkAbwBuAFUAcgBsAD4APABtAGkAZAA+ADwALwBtAGkAZAA+ADwALwBtAHUAcwBpAGMAUwBoAGEAcgBlAEkAdABlAG0APgA8AC8AQwBvAG4AdABlAG4AdABPAGIAagBlAGMAdAA+ADwAYQBjAHQAaQBvAG4ASQBuAGYAbwA+ADwAYQBwAHAATQBzAGcAPgA8AG0AZQBkAGkAYQBUAGEAZwBOAGEAbQBlAD4APAAvAG0AZQBkAGkAYQBUAGEAZwBOAGEAbQBlAD4APABtAGUAcwBzAGEAZwBlAEUAeAB0AD4APAAvAG0AZQBzAHMAYQBnAGUARQB4AHQAPgA8AG0AZQBzAHMAYQBnAGUAQQBjAHQAaQBvAG4APgA8AC8AbQBlAHMAcwBhAGcAZQBBAGMAdABpAG8AbgA+ADwAYQBwAHAAaQBkAD4AdwB4ADUAYQBhADMAMwAzADYAMAA2ADUANQAwAGQAZgBkADUAPAAvAGEAcABwAGkAZAA+ADwALwBhAHAAcABNAHMAZwA+ADwAcwBjAGUAbgBlAD4AMAA8AC8AcwBjAGUAbgBlAD4APAB0AHkAcABlAD4AMAA8AC8AdAB5AHAAZQA+ADwAdQByAGwAPgA8AC8AdQByAGwAPgA8AG4AZQB3AFcAbwByAGQAaQBuAGcASwBlAHkAPgA8AC8AbgBlAHcAVwBvAHIAZABpAG4AZwBLAGUAeQA+ADwAbgBlAHcAdAB5AHAAZQA+ADAAPAAvAG4AZQB3AHQAeQBwAGUAPgA8AGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwAdQBuAGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AdQBuAGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AYQBjAHQAaQBvAG4ASQBuAGYAbwA+ADwAcwB0AGEAdABFAHgAdABTAHQAcgA+ADwAIQBbAEMARABBAFQAQQBbAEcAaABRAEsARQBuAGQANABOAFcARgBoAE0AegBNAHoATgBqAEEAMgBOAFQAVQB3AFoARwBaAGsATgBRAD0APQBdAF0APgA8AC8AcwB0AGEAdABFAHgAdABTAHQAcgA+ADwAbABvAGMAYQB0AGkAbwBuACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AEkAZAA9ACIAIgAgAHAAbwBpAE4AYQBtAGUAPQAiACIAIABwAG8AaQBBAGQAZAByAGUAcwBzAD0AIgAiACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AFQAeQBwAGUAPQAiADAAIgAgAGMAaQB0AHkAPQAiACIAPgA8AC8AbABvAGMAYQB0AGkAbwBuAD4APABwAHUAYgBsAGkAYwBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcAB1AGIAbABpAGMAVQBzAGUAcgBOAGEAbQBlAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdQByAGwAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB0AGgAdQBtAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHQAaAB1AG0AYgB1AHIAbAA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHcAZQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB3AGUAYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AC8AVABpAG0AZQBsAGkAbgBlAE8AYgBqAGUAYwB0AD4A"},{"ID":"-4686445252318719895","Time":1640355446,"Wxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","Nick":"d231fp1bnVsgACAAIAACMA==","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADEAMwA3ADYAMAAyADkAOAA4ADIAMQAzADkAMAA4ADMAMQA3ADIAMQA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgB3AHgAaQBkAF8AaABsAGcAbwByAG4AOAA0ADYAaQBoAHAAMgAyADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgAxADYANAAwADMANQA1ADQANAA2ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADMAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgAwADwALwBwAHIAaQB2AGEAdABlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAPgALZ8tTCFdLbdWLIAAtACAAi3MnWSSVPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwA+ADwAcwBpAGcAaAB0AEYAbwBsAGQAZQBkAD4AMAA8AC8AcwBpAGcAaAB0AEYAbwBsAGQAZQBkAD4APABzAGgAbwB3AEYAbABhAGcAPgAwADwALwBzAGgAbwB3AEYAbABhAGcAPgA8AGEAcABwAEkAbgBmAG8APgA8AGkAZAA+ADwALwBpAGQAPgA8AHYAZQByAHMAaQBvAG4APgA8AC8AdgBlAHIAcwBpAG8AbgA+ADwAYQBwAHAATgBhAG0AZQA+ADwALwBhAHAAcABOAGEAbQBlAD4APABpAG4AcwB0AGEAbABsAFUAcgBsAD4APAAvAGkAbgBzAHQAYQBsAGwAVQByAGwAPgA8AGYAcgBvAG0AVQByAGwAPgA8AC8AZgByAG8AbQBVAHIAbAA+ADwAaQBzAEYAbwByAGMAZQBVAHAAZABhAHQAZQA+ADAAPAAvAGkAcwBGAG8AcgBjAGUAVQBwAGQAYQB0AGUAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APAAvAHMAbwB1AHIAYwBlAFUAcwBlAHIATgBhAG0AZQA+ADwAcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APAAvAHMAbwB1AHIAYwBlAE4AaQBjAGsATgBhAG0AZQA+ADwAcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAAvAHMAdABhAHQAaQBzAHQAaQBjAHMARABhAHQAYQA+ADwAcwB0AGEAdABFAHgAdABTAHQAcgA+ADwALwBzAHQAYQB0AEUAeAB0AFMAdAByAD4APABDAG8AbgB0AGUAbgB0AE8AYgBqAGUAYwB0AD4APABjAG8AbgB0AGUAbgB0AFMAdAB5AGwAZQA+ADIAPAAvAGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APAB0AGkAdABsAGUAPgA8AC8AdABpAHQAbABlAD4APABkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AC8AZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APABtAGUAZABpAGEATABpAHMAdAA+ADwALwBtAGUAZABpAGEATABpAHMAdAA+ADwAYwBvAG4AdABlAG4AdABVAHIAbAA+ADwALwBjAG8AbgB0AGUAbgB0AFUAcgBsAD4APAAvAEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGEAYwB0AGkAbwBuAEkAbgBmAG8APgA8AGEAcABwAE0AcwBnAD4APABtAGUAcwBzAGEAZwBlAEEAYwB0AGkAbwBuAD4APAAvAG0AZQBzAHMAYQBnAGUAQQBjAHQAaQBvAG4APgA8AC8AYQBwAHAATQBzAGcAPgA8AC8AYQBjAHQAaQBvAG4ASQBuAGYAbwA+ADwAbABvAGMAYQB0AGkAbwBuACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AEkAZAA9ACIAIgAgAHAAbwBpAE4AYQBtAGUAPQAiACIAIABwAG8AaQBBAGQAZAByAGUAcwBzAD0AIgAiACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AFQAeQBwAGUAPQAiADAAIgAgAGMAaQB0AHkAPQAiACIAPgA8AC8AbABvAGMAYQB0AGkAbwBuAD4APABwAHUAYgBsAGkAYwBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcAB1AGIAbABpAGMAVQBzAGUAcgBOAGEAbQBlAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdQByAGwAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB0AGgAdQBtAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHQAaAB1AG0AYgB1AHIAbAA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHcAZQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB3AGUAYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AC8AVABpAG0AZQBsAGkAbgBlAE8AYgBqAGUAYwB0AD4A"},{"ID":"-4696957636426133397","Time":1639102272,"Wxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","Nick":"d231fp1bnVsgACAAIAACMA==","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADQAOQA3ADgANgA0ADMANwAyADgAMwA0ADEAOAAyADEAOQBdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgAaQBkAF8AaABsAGcAbwByAG4AOAA0ADYAaQBoAHAAMgAyAF0AXQA+ADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADYAMwA5ADEAMAAyADIANwAyAF0AXQA+ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAPgA8ACEAWwBDAEQAQQBUAEEAWwA12OLcNdj+3DXY99w12PfcNdgC3QAmD/4KADsENQOxAqoAsQKqALECqgAgACgAURXiFesUMg4XIikA0gIKAPZlOF4AX8NfDP+kix93sItVXwz/0VOwc0lRkoIgACgnXQBdAD4APAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwA+ADwAYwBvAG4AdABlAG4AdABhAHQAdAByAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABhAHQAdAByAD4APABzAG8AdQByAGMAZQBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APABzAG8AdQByAGMAZQBOAGkAYwBrAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APABzAHQAYQB0AGkAcwB0AGkAYwBzAEQAYQB0AGEAPgA8AC8AcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYQBwAHAAVQBzAGUAcgBOAGEAbQBlAD4APAAvAGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwAcABhAGcAZQBQAGEAdABoAD4APAAvAHAAYQBnAGUAUABhAHQAaAA+ADwAdgBlAHIAcwBpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHYAZQByAHMAaQBvAG4APgA8AGQAZQBiAHUAZwBNAG8AZABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AZABlAGIAdQBnAE0AbwBkAGUAPgA8AHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AC8AcwBoAGEAcgBlAEEAYwB0AGkAbwBuAEkAZAA+ADwAaQBzAEcAYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBpAHMARwBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AHIAYQBEAGEAdABhAD4APABzAHUAYgBUAHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcwB1AGIAVAB5AHAAZQA+ADwAcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwBwAHIAZQBsAG8AYQBkAFIAZQBzAG8AdQByAGMAZQBzAD4APAAvAHcAZQBhAHAAcABJAG4AZgBvAD4APABjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APAAvAGMAYQBuAHYAYQBzAEkAbgBmAG8AWABtAGwAPgA8AEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsAMQBdAF0APgA8AC8AYwBvAG4AdABlAG4AdABTAHQAeQBsAGUAPgA8AGMAbwBuAHQAZQBuAHQAUwB1AGIAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABTAHUAYgBTAHQAeQBsAGUAPgA8AHQAaQB0AGwAZQA+ADwALwB0AGkAdABsAGUAPgA8AGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwALwBkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AGMAbwBuAHQAZQBuAHQAVQByAGwAPgA8AC8AYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAbQBlAGQAaQBhAEwAaQBzAHQAPgA8AG0AZQBkAGkAYQA+ADwAaQBkAD4APAAhAFsAQwBEAEEAVABBAFsAMQAzADcANAA5ADcAOAA2ADQAMwA3ADgAOQAzADEANgA1ADEANwAzAF0AXQA+ADwALwBpAGQAPgA8AHQAeQBwAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAyAF0AXQA+ADwALwB0AHkAcABlAD4APAB0AGkAdABsAGUAPgA8AC8AdABpAHQAbABlAD4APABkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AC8AZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APABwAHIAaQB2AGEAdABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcAByAGkAdgBhAHQAZQA+ADwAdQByAGwAIAB0AHkAcABlAD0AIgAxACIAIABtAGQANQA9ACIAMgA4ADcAYgA1AGEAMwA2ADAAYwAyADAAZQA3AGMAZgBmAGYAYgBhADkAYwBjAGEAMwA4AGQANQBkADQAMwAwACIAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAHMAegBtAG0AcwBuAHMALgBxAHAAaQBjAC4AYwBuAC8AbQBtAHMAbgBzAC8ARwBEAEEATwB0ADUAZgBMAGsAQwBnADYATABrAG4AVQBqADgAMQBpAGIAUQAzAEwATQBNAGMARgBQAHAAUgBxAGkAYwAzAFMAagBkAFgARQBlAEwAcQBmAEUANQBoAFUAMgBkAG0AYQBhAG4AZgBPAHAANQBiAGMAcgBwADMARAAzAFQAWABWAGgARQBGAHYAMAA2AGgAZABjAC8AMABdAF0APgA8AC8AdQByAGwAPgA8AHQAaAB1AG0AYgAgAHQAeQBwAGUAPQAiADEAIgA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAOgAvAC8AcwB6AG0AbQBzAG4AcwAuAHEAcABpAGMALgBjAG4ALwBtAG0AcwBuAHMALwBHAEQAQQBPAHQANQBmAEwAawBDAGcANgBMAGsAbgBVAGoAOAAxAGkAYgBRADMATABNAE0AYwBGAFAAcABSAHEAaQBjADMAUwBqAGQAWABFAGUATABxAGYARQA1AGgAVQAyAGQAbQBhAGEAbgBmAE8AcAA1AGIAYwByAHAAMwBEADMAVABYAFYAaABFAEYAdgAwADYAaABkAGMALwAxADUAMABdAF0APgA8AC8AdABoAHUAbQBiAD4APAB2AGkAZABlAG8ARAB1AHIAYQB0AGkAbwBuAD4APAAhAFsAQwBEAEEAVABBAFsAMAAuADAAXQBdAD4APAAvAHYAaQBkAGUAbwBEAHUAcgBhAHQAaQBvAG4APgA8AHMAaQB6AGUAIAB0AG8AdABhAGwAUwBpAHoAZQA9ACIAMgAzADIAMAA5AC4AMAAiACAAdwBpAGQAdABoAD0AIgA1ADAAMAAuADAAIgAgAGgAZQBpAGcAaAB0AD0AIgA0ADEANQAuADAAIgA+ADwALwBzAGkAegBlAD4APAAvAG0AZQBkAGkAYQA+ADwALwBtAGUAZABpAGEATABpAHMAdAA+ADwALwBDAG8AbgB0AGUAbgB0AE8AYgBqAGUAYwB0AD4APABhAGMAdABpAG8AbgBJAG4AZgBvAD4APABhAHAAcABNAHMAZwA+ADwAbQBlAGQAaQBhAFQAYQBnAE4AYQBtAGUAPgA8AC8AbQBlAGQAaQBhAFQAYQBnAE4AYQBtAGUAPgA8AG0AZQBzAHMAYQBnAGUARQB4AHQAPgA8AC8AbQBlAHMAcwBhAGcAZQBFAHgAdAA+ADwAbQBlAHMAcwBhAGcAZQBBAGMAdABpAG8AbgA+ADwALwBtAGUAcwBzAGEAZwBlAEEAYwB0AGkAbwBuAD4APAAvAGEAcABwAE0AcwBnAD4APAAvAGEAYwB0AGkAbwBuAEkAbgBmAG8APgA8AGEAcABwAEkAbgBmAG8APgA8AGkAZAA+ADwALwBpAGQAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAbABvAGMAYQB0AGkAbwBuACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AEkAZAA9ACIAIgAgAHAAbwBpAE4AYQBtAGUAPQAiACIAIABwAG8AaQBBAGQAZAByAGUAcwBzAD0AIgAiACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AFQAeQBwAGUAPQAiADAAIgAgAGMAaQB0AHkAPQAiACIAPgA8AC8AbABvAGMAYQB0AGkAbwBuAD4APABwAHUAYgBsAGkAYwBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcAB1AGIAbABpAGMAVQBzAGUAcgBOAGEAbQBlAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdQByAGwAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB0AGgAdQBtAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHQAaAB1AG0AYgB1AHIAbAA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHcAZQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB3AGUAYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AC8AVABpAG0AZQBsAGkAbgBlAE8AYgBqAGUAYwB0AD4A"},{"ID":"-4697696604165631885","Time":1639014180,"Wxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","Nick":"d231fp1bnVsgACAAIAACMA==","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADQAOQAwADQANwA0ADYAOQA1ADQAMwA5ADEAOQA3ADMAMQBdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgAaQBkAF8AaABsAGcAbwByAG4AOAA0ADYAaQBoAHAAMgAyAF0AXQA+ADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADYAMwA5ADAAMQA0ADEAOAAwAF0AXQA+ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APABhAHAAcABJAG4AZgBvAD4APABpAGQAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQBdAF0APgA8AC8AaQBkAD4APAB2AGUAcgBzAGkAbwBuAD4ANQAzADwALwB2AGUAcgBzAGkAbwBuAD4APABhAHAAcABOAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAUQBRAPOXUE5dAF0APgA8AC8AYQBwAHAATgBhAG0AZQA+ADwAaQBuAHMAdABhAGwAbABVAHIAbAA+ADwALwBpAG4AcwB0AGEAbABsAFUAcgBsAD4APABmAHIAbwBtAFUAcgBsAD4APAAvAGYAcgBvAG0AVQByAGwAPgA8AGMAbABpAGMAawBhAGIAbABlAD4AMAA8AC8AYwBsAGkAYwBrAGEAYgBsAGUAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAD4APAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwA+ADwAYwBvAG4AdABlAG4AdABhAHQAdAByAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABhAHQAdAByAD4APABzAG8AdQByAGMAZQBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APABzAG8AdQByAGMAZQBOAGkAYwBrAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APABzAHQAYQB0AGkAcwB0AGkAYwBzAEQAYQB0AGEAPgA8AC8AcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYQBwAHAAVQBzAGUAcgBOAGEAbQBlAD4APAAvAGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwAcABhAGcAZQBQAGEAdABoAD4APAAvAHAAYQBnAGUAUABhAHQAaAA+ADwAdgBlAHIAcwBpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHYAZQByAHMAaQBvAG4APgA8AGQAZQBiAHUAZwBNAG8AZABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AZABlAGIAdQBnAE0AbwBkAGUAPgA8AHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AC8AcwBoAGEAcgBlAEEAYwB0AGkAbwBuAEkAZAA+ADwAaQBzAEcAYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBpAHMARwBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AHIAYQBEAGEAdABhAD4APABzAHUAYgBUAHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcwB1AGIAVAB5AHAAZQA+ADwAcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwBwAHIAZQBsAG8AYQBkAFIAZQBzAG8AdQByAGMAZQBzAD4APAAvAHcAZQBhAHAAcABJAG4AZgBvAD4APABjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APAAvAGMAYQBuAHYAYQBzAEkAbgBmAG8AWABtAGwAPgA8AEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsANAAyAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFMAdAB5AGwAZQA+ADwAYwBvAG4AdABlAG4AdABTAHUAYgBTAHQAeQBsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFMAdQBiAFMAdAB5AGwAZQA+ADwAdABpAHQAbABlAD4APAAvAHQAaQB0AGwAZQA+ADwAZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APAAvAGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAcwA6AC8ALwBpAC4AeQAuAHEAcQAuAGMAbwBtAC8AdgA4AC8AcABsAGEAeQBzAG8AbgBnAC4AaAB0AG0AbAA/AHAAbABhAHQAZgBvAHIAbQA9ADEAMQAmAGEAcABwAHMAaABhAHIAZQA9AGEAbgBkAHIAbwBpAGQAXwBxAHEAJgBhAHAAcAB2AGUAcgBzAGkAbwBuAD0AMQAxADAAMAAwADEAMAA2ACYAaABvAHMAdABlAHUAaQBuAD0AbwBLADYAawBvAHcARQBBAG8ASwA0AHoANwBLADYAUAA3AGUAUwBxADcASwAtAHMAbwBjACoAKgAmAHMAbwBuAGcAbQBpAGQAPQAwADAAMABiAFIAYQBBAHMAMQBZAE4AdgA4AEoAJgB0AHkAcABlAD0AMAAmAGEAcABwAHMAbwBuAGcAdAB5AHAAZQA9ADEAJgBfAHcAdgA9ADEAJgBzAG8AdQByAGMAZQA9AHcAZQBpAHgAaQBuACYAcwBoAGEAcgBlAGYAcgBvAG0APQBwAGUAcgBzAG8AbgBhAGwAXwByAGEAZABpAG8AJgBmAHIAbwBtAF8AaQBkAD0AOQA5ACYAZgByAG8AbQBfAGkAZAB0AHkAcABlAD0AJgBmAHIAbwBtAF8AbgBhAG0AZQA9AFUAVgBFAGwAUgBUAGsAbABPAFUAWQBsAFEAagBNAGwAUgBUAFEAbABRAGoAawBsAE8AVABBAGwAUgBUAFEAbABRAGoAZwBsAFEAVQBFAGwAUgBUAFkAbABPAEQAQQBsAFEAVABjAGwAUgBUAGMAbABPAFQAUQBsAFEAagBVAGwAUgBUAFUAbABPAEUAWQBsAFEAagBBACUAMwBEACYAQQBEAFQAQQBHAD0AZgBmAHMAaABhAHIAZQBdAF0APgA8AC8AYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAbQBlAGQAaQBhAEwAaQBzAHQAPgA8AG0AZQBkAGkAYQA+ADwAaQBkAD4APAAhAFsAQwBEAEEAVABBAFsAMQAzADcANAA5ADAANAA3ADQANwAwADEANAA2ADcAOAA1ADMAOAA5AF0AXQA+ADwALwBpAGQAPgA8AHQAeQBwAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwA1AF0AXQA+ADwALwB0AHkAcABlAD4APAB0AGkAdABsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwDmXbmPIAAtACAAaGceTjN0XQBdAD4APAAvAHQAaQB0AGwAZQA+ADwAZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APAAhAFsAQwBEAEEAVABBAFsAZWfqgVEAUQDzl1BOKk4nYDV18FNdAF0APgA8AC8AZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APABwAHIAaQB2AGEAdABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcAByAGkAdgBhAHQAZQA+ADwAcwBvAG4AZwBhAGwAYgB1AG0AdQByAGwAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAHcAeABhAHAAcAAuAHQAYwAuAHEAcQAuAGMAbwBtAC8AMgAwADIALwAyADAAMwAwADQALwBzAHQAbwBkAG8AdwBuAGwAbwBhAGQAPwBmAGkAbABlAGsAZQB5AD0AMwAwADMANQAwADIAMAAxADAAMQAwADQAMgAxADMAMAAxAGYAMAAyADAAMgAwADAAYwBhADAANAAwADIANQAzADUAYQAwADQAMQAwADUAMQA1ADQANwBkAGMANABhADQANgBjADAAYQAyADAAMAAwADIAYgA3ADgAMgA0ADYANQBkADUAZQBmADgAOAAwADIAMAAzADAAMAA5AGQAZABhADAANAAwAGQAMAAwADAAMAAwADAAMAA0ADYAMgA3ADQANgA2ADcAMwAwADAAMAAwADAAMAAwADEAMwAxACYAaAB5AD0AUwBaACYAcwB0AG8AcgBlAGkAZAA9ADMAMgAzADAAMwAyADMAMQAzADEAMwAyADMAMAAzADkAMwAwADMAOQAzADQAMwAyADMANQAzADMAMwAwADMAMAAzADAANgA0ADMANQAzADQANgAzADMAMQAzADAAMwA2ADMAOAAzADcANgA2ADMANQAzADgAMwA2ADMAOQAzADAAMwA2ADMAMQAzADgAMwA4ADMAMAAzADkAMwAwADMAMAAzADAAMwAwADMAMAAzADAANgAzADYAMQAmAGIAaQB6AGkAZAA9ADEAMAAyADMAXQBdAD4APAAvAHMAbwBuAGcAYQBsAGIAdQBtAHUAcgBsAD4APAB1AHIAbAAgAHQAeQBwAGUAPQAiADAAIgA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAOgAvAC8AYwA2AC4AeQAuAHEAcQAuAGMAbwBtAC8AcgBzAGMALwBmAGMAZwBpAC0AYgBpAG4ALwBmAGMAZwBfAHAAeQBxAF8AcABsAGEAeQAuAGYAYwBnAD8AcwBvAG4AZwBpAGQAPQAmAHMAbwBuAGcAbQBpAGQAPQAwADAAMABiAFIAYQBBAHMAMQBZAE4AdgA4AEoAJgBzAG8AbgBnAHQAeQBwAGUAPQAxACYAZgByAG8AbQB0AGEAZwA9ADQANgAmAHUAaQBuAD0AMQAxADUAMgA5ADIAMQA1ADAANQAxADQANAA3ADkANQAyADYAMgAmAGMAbwBkAGUAPQBGADkAOQAwADcAXQBdAD4APAAvAHUAcgBsAD4APAB0AGgAdQBtAGIAIAB0AHkAcABlAD0AIgAxACIAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAHMAegBtAG0AcwBuAHMALgBxAHAAaQBjAC4AYwBuAC8AbQBtAHMAbgBzAC8ARwBEAEEATwB0ADUAZgBMAGsAQwBnADYATABrAG4AVQBqADgAMQBpAGIAUQBpAGMARgBqAFAATgBaAE4AeABmAGoAeQBpAGIAQgB4AHYAOABEAE4ANgBPAEMAWQBsAFoASgBNAHEAeQBhAHIAVgBpAGIASABmAGMAOQBOADcATwA1AGgAcABmAHUAeABwAG4AcwBVADcAWAAwAE4AbwAvADEANQAwAF0AXQA+ADwALwB0AGgAdQBtAGIAPgA8AHYAaQBkAGUAbwBEAHUAcgBhAHQAaQBvAG4APgA8ACEAWwBDAEQAQQBUAEEAWwAwAC4AMABdAF0APgA8AC8AdgBpAGQAZQBvAEQAdQByAGEAdABpAG8AbgA+ADwAcwBpAHoAZQAgAHQAbwB0AGEAbABTAGkAegBlAD0AIgAzADcAOAA2AC4AMAAiACAAdwBpAGQAdABoAD0AIgAxADUAMAAuADAAIgAgAGgAZQBpAGcAaAB0AD0AIgAxADUAMAAuADAAIgA+ADwALwBzAGkAegBlAD4APAAvAG0AZQBkAGkAYQA+ADwALwBtAGUAZABpAGEATABpAHMAdAA+ADwAbQB1AHMAaQBjAFMAaABhAHIAZQBJAHQAZQBtAD4APABtAHYATwBiAGoAZQBjAHQASQBkAD4APAAvAG0AdgBPAGIAagBlAGMAdABJAGQAPgA8AG0AdgBOAG8AbgBjAGUASQBkAD4APAAvAG0AdgBOAG8AbgBjAGUASQBkAD4APABtAHYAQwBvAHYAZQByAFUAcgBsAD4APAAvAG0AdgBDAG8AdgBlAHIAVQByAGwAPgA8AG0AdgBNAGEAawBlAHIARgBpAG4AZABlAHIATgBpAGMAawBuAGEAbQBlAD4APAAvAG0AdgBNAGEAawBlAHIARgBpAG4AZABlAHIATgBpAGMAawBuAGEAbQBlAD4APABtAHYAUwBpAG4AZwBlAHIATgBhAG0AZQA+AGhnHk4zdDwALwBtAHYAUwBpAG4AZwBlAHIATgBhAG0AZQA+ADwAbQB2AEEAbABiAHUAbQBOAGEAbQBlAD4AR5AKTjFyPAAvAG0AdgBBAGwAYgB1AG0ATgBhAG0AZQA+ADwAbQB2AE0AdQBzAGkAYwBHAGUAbgByAGUAPgA8AC8AbQB2AE0AdQBzAGkAYwBHAGUAbgByAGUAPgA8AG0AdgBJAHMAcwB1AGUARABhAHQAZQA+ADAAPAAvAG0AdgBJAHMAcwB1AGUARABhAHQAZQA+ADwAbQB2AEkAZABlAG4AdABpAGYAaQBjAGEAdABpAG8AbgA+ADwALwBtAHYASQBkAGUAbgB0AGkAZgBpAGMAYQB0AGkAbwBuAD4APABtAHUAcwBpAGMARAB1AHIAYQB0AGkAbwBuAD4AMgA3ADQAMAAwADAAPAAvAG0AdQBzAGkAYwBEAHUAcgBhAHQAaQBvAG4APgA8AG0AdgBFAHgAdABJAG4AZgBvAD4APAAvAG0AdgBFAHgAdABJAG4AZgBvAD4APABtAHYATwBwAGUAcgBhAHQAaQBvAG4AVQByAGwAPgA8AC8AbQB2AE8AcABlAHIAYQB0AGkAbwBuAFUAcgBsAD4APABtAGkAZAA+ADwALwBtAGkAZAA+ADwALwBtAHUAcwBpAGMAUwBoAGEAcgBlAEkAdABlAG0APgA8AC8AQwBvAG4AdABlAG4AdABPAGIAagBlAGMAdAA+ADwAYQBjAHQAaQBvAG4ASQBuAGYAbwA+ADwAYQBwAHAATQBzAGcAPgA8AG0AZQBkAGkAYQBUAGEAZwBOAGEAbQBlAD4APAAvAG0AZQBkAGkAYQBUAGEAZwBOAGEAbQBlAD4APABtAGUAcwBzAGEAZwBlAEUAeAB0AD4APAAvAG0AZQBzAHMAYQBnAGUARQB4AHQAPgA8AG0AZQBzAHMAYQBnAGUAQQBjAHQAaQBvAG4APgA8AC8AbQBlAHMAcwBhAGcAZQBBAGMAdABpAG8AbgA+ADwAYQBwAHAAaQBkAD4AdwB4ADUAYQBhADMAMwAzADYAMAA2ADUANQAwAGQAZgBkADUAPAAvAGEAcABwAGkAZAA+ADwALwBhAHAAcABNAHMAZwA+ADwAcwBjAGUAbgBlAD4AMAA8AC8AcwBjAGUAbgBlAD4APAB0AHkAcABlAD4AMAA8AC8AdAB5AHAAZQA+ADwAdQByAGwAPgA8AC8AdQByAGwAPgA8AG4AZQB3AFcAbwByAGQAaQBuAGcASwBlAHkAPgA8AC8AbgBlAHcAVwBvAHIAZABpAG4AZwBLAGUAeQA+ADwAbgBlAHcAdAB5AHAAZQA+ADAAPAAvAG4AZQB3AHQAeQBwAGUAPgA8AGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwAdQBuAGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AdQBuAGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AYQBjAHQAaQBvAG4ASQBuAGYAbwA+ADwAcwB0AGEAdABFAHgAdABTAHQAcgA+ADwAIQBbAEMARABBAFQAQQBbAEcAaABRAEsARQBuAGQANABOAFcARgBoAE0AegBNAHoATgBqAEEAMgBOAFQAVQB3AFoARwBaAGsATgBRAD0APQBdAF0APgA8AC8AcwB0AGEAdABFAHgAdABTAHQAcgA+ADwAbABvAGMAYQB0AGkAbwBuACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AEkAZAA9ACIAIgAgAHAAbwBpAE4AYQBtAGUAPQAiACIAIABwAG8AaQBBAGQAZAByAGUAcwBzAD0AIgAiACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AFQAeQBwAGUAPQAiADAAIgAgAGMAaQB0AHkAPQAiACIAPgA8AC8AbABvAGMAYQB0AGkAbwBuAD4APABwAHUAYgBsAGkAYwBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcAB1AGIAbABpAGMAVQBzAGUAcgBOAGEAbQBlAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdQByAGwAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB0AGgAdQBtAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHQAaAB1AG0AYgB1AHIAbAA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHcAZQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB3AGUAYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AC8AVABpAG0AZQBsAGkAbgBlAE8AYgBqAGUAYwB0AD4A"},{"ID":"-4700589717139025818","Time":1638669294,"Wxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","Nick":"d231fp1bnVsgACAAIAACMA==","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADQANgAxADUANAAzADUANgA1ADcAMAA1ADIANQA3ADkAOABdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgAaQBkAF8AaABsAGcAbwByAG4AOAA0ADYAaQBoAHAAMgAyAF0AXQA+ADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADYAMwA4ADYANgA5ADIAOQA0AF0AXQA+ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APABhAHAAcABJAG4AZgBvAD4APABpAGQAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQBdAF0APgA8AC8AaQBkAD4APAB2AGUAcgBzAGkAbwBuAD4ANQAzADwALwB2AGUAcgBzAGkAbwBuAD4APABhAHAAcABOAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAUQBRAPOXUE5dAF0APgA8AC8AYQBwAHAATgBhAG0AZQA+ADwAaQBuAHMAdABhAGwAbABVAHIAbAA+ADwALwBpAG4AcwB0AGEAbABsAFUAcgBsAD4APABmAHIAbwBtAFUAcgBsAD4APAAvAGYAcgBvAG0AVQByAGwAPgA8AGMAbABpAGMAawBhAGIAbABlAD4AMAA8AC8AYwBsAGkAYwBrAGEAYgBsAGUAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAD4APAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwA+ADwAYwBvAG4AdABlAG4AdABhAHQAdAByAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABhAHQAdAByAD4APABzAG8AdQByAGMAZQBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APABzAG8AdQByAGMAZQBOAGkAYwBrAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APABzAHQAYQB0AGkAcwB0AGkAYwBzAEQAYQB0AGEAPgA8AC8AcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYQBwAHAAVQBzAGUAcgBOAGEAbQBlAD4APAAvAGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwAcABhAGcAZQBQAGEAdABoAD4APAAvAHAAYQBnAGUAUABhAHQAaAA+ADwAdgBlAHIAcwBpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHYAZQByAHMAaQBvAG4APgA8AGQAZQBiAHUAZwBNAG8AZABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AZABlAGIAdQBnAE0AbwBkAGUAPgA8AHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AC8AcwBoAGEAcgBlAEEAYwB0AGkAbwBuAEkAZAA+ADwAaQBzAEcAYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBpAHMARwBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AHIAYQBEAGEAdABhAD4APABzAHUAYgBUAHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcwB1AGIAVAB5AHAAZQA+ADwAcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwBwAHIAZQBsAG8AYQBkAFIAZQBzAG8AdQByAGMAZQBzAD4APAAvAHcAZQBhAHAAcABJAG4AZgBvAD4APABjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APAAvAGMAYQBuAHYAYQBzAEkAbgBmAG8AWABtAGwAPgA8AEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsANQBdAF0APgA8AC8AYwBvAG4AdABlAG4AdABTAHQAeQBsAGUAPgA8AGMAbwBuAHQAZQBuAHQAUwB1AGIAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABTAHUAYgBTAHQAeQBsAGUAPgA8AHQAaQB0AGwAZQA+ADwAIQBbAEMARABBAFQAQQBbAAZSq07GiZGYOgBBbUyIKVkOVPBs0lKvZQFaK1l5cl55p36wczpXfgAtAA9c85d0ZTttRZ5dAF0APgA8AC8AdABpAHQAbABlAD4APABkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AC8AZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APABjAG8AbgB0AGUAbgB0AFUAcgBsAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcABzADoALwAvAGkALgB5AC4AcQBxAC4AYwBvAG0ALwBuADIALwBtAC8AcwBoAGEAcgBlAC8AZABlAHQAYQBpAGwAcwAvAG0AdgAuAGgAdABtAGwAPwBwAGwAYQB0AGYAbwByAG0APQAxADEAJgBhAHAAcABzAGgAYQByAGUAPQBhAG4AZAByAG8AaQBkAF8AcQBxACYAYQBwAHAAdgBlAHIAcwBpAG8AbgA9ADEAMQAwADAAMAAxADAANgAmAGgAbwBzAHQAZQB1AGkAbgA9AG8ASwA2AGsAbwB3AEUAQQBvAEsANAB6ADcASwA2AFAANwBlAFMAcQA3AEsALQBzAG8AYwAqACoAJgB2AGkAZAA9ADAAMQAwAE8AcABWAG0AMAAxAFcAagBTAFgAWgAmAEEARABUAEEARwA9AGYAZgBzAGgAYQByAGUAXQBdAD4APAAvAGMAbwBuAHQAZQBuAHQAVQByAGwAPgA8AG0AZQBkAGkAYQBMAGkAcwB0AD4APABtAGUAZABpAGEAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADQANgAxADUANAAzADUANwAwADUAOQAzADUAOAA4ADUANwBdAF0APgA8AC8AaQBkAD4APAB0AHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsANABdAF0APgA8AC8AdAB5AHAAZQA+ADwAdABpAHQAbABlAD4APAAhAFsAQwBEAEEAVABBAFsABlKrTsaJkZg6AEFtTIgpWQ5U8GzSUq9lAVorWXlyXnmnfrBzOld+AC0AD1zzl3RlO21Fnl0AXQA+ADwALwB0AGkAdABsAGUAPgA8AGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbAGVn6oFlZ+qBGv8PXPOXdGU7bUWehHbGiZGYXQBdAD4APAAvAGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAcAByAGkAdgBhAHQAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHAAcgBpAHYAYQB0AGUAPgA8AHUAcgBsACAAdAB5AHAAZQA9ACIAMAAiAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcABzADoALwAvAGkALgB5AC4AcQBxAC4AYwBvAG0ALwBuADIALwBtAC8AcwBoAGEAcgBlAC8AZABlAHQAYQBpAGwAcwAvAG0AdgAuAGgAdABtAGwAPwBwAGwAYQB0AGYAbwByAG0APQAxADEAJgBhAHAAcABzAGgAYQByAGUAPQBhAG4AZAByAG8AaQBkAF8AcQBxACYAYQBwAHAAdgBlAHIAcwBpAG8AbgA9ADEAMQAwADAAMAAxADAANgAmAGgAbwBzAHQAZQB1AGkAbgA9AG8ASwA2AGsAbwB3AEUAQQBvAEsANAB6ADcASwA2AFAANwBlAFMAcQA3AEsALQBzAG8AYwAqACoAJgB2AGkAZAA9ADAAMQAwAE8AcABWAG0AMAAxAFcAagBTAFgAWgAmAEEARABUAEEARwA9AGYAZgBzAGgAYQByAGUAXQBdAD4APAAvAHUAcgBsAD4APAB0AGgAdQBtAGIAIAB0AHkAcABlAD0AIgAxACIAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAHMAegBtAG0AcwBuAHMALgBxAHAAaQBjAC4AYwBuAC8AbQBtAHMAbgBzAC8ARwBEAEEATwB0ADUAZgBMAGsAQwBnADYATABrAG4AVQBqADgAMQBpAGIAUQAzAGkAYQBSAFEAeQBzAG0AcQBpAGEAdwBEAEsAUQBKAGcARQBDAEQANgBnAGkAYgBxAGYAdwBiAGcAUwB6AFMASAA1AEEARQBKAE4AZQBQAHgAZAAzAHAAdQBTAGYAVwBoAGQAbgBTAFQAeQBBAEoAbwAvADEANQAwAF0AXQA+ADwALwB0AGgAdQBtAGIAPgA8AHYAaQBkAGUAbwBEAHUAcgBhAHQAaQBvAG4APgA8ACEAWwBDAEQAQQBUAEEAWwAwAC4AMABdAF0APgA8AC8AdgBpAGQAZQBvAEQAdQByAGEAdABpAG8AbgA+ADwAbABvAHcAQgBhAG4AZABVAHIAbAAgAHQAeQBwAGUAPQAiADAAIgA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAcwA6AC8ALwBpAC4AeQAuAHEAcQAuAGMAbwBtAC8AbgAyAC8AbQAvAHMAaABhAHIAZQAvAGQAZQB0AGEAaQBsAHMALwBtAHYALgBoAHQAbQBsAD8AcABsAGEAdABmAG8AcgBtAD0AMQAxACYAYQBwAHAAcwBoAGEAcgBlAD0AYQBuAGQAcgBvAGkAZABfAHEAcQAmAGEAcABwAHYAZQByAHMAaQBvAG4APQAxADEAMAAwADAAMQAwADYAJgBoAG8AcwB0AGUAdQBpAG4APQBvAEsANgBrAG8AdwBFAEEAbwBLADQAegA3AEsANgBQADcAZQBTAHEANwBLAC0AcwBvAGMAKgAqACYAdgBpAGQAPQAwADEAMABPAHAAVgBtADAAMQBXAGoAUwBYAFoAJgBBAEQAVABBAEcAPQBmAGYAcwBoAGEAcgBlAF0AXQA+ADwALwBsAG8AdwBCAGEAbgBkAFUAcgBsAD4APABzAGkAegBlACAAdABvAHQAYQBsAFMAaQB6AGUAPQAiADQANQA2ADIALgAwACIAIAB3AGkAZAB0AGgAPQAiADEANQAwAC4AMAAiACAAaABlAGkAZwBoAHQAPQAiADEANQAwAC4AMAAiAD4APAAvAHMAaQB6AGUAPgA8AC8AbQBlAGQAaQBhAD4APAAvAG0AZQBkAGkAYQBMAGkAcwB0AD4APAAvAEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGEAYwB0AGkAbwBuAEkAbgBmAG8APgA8AGEAcABwAE0AcwBnAD4APABtAGUAZABpAGEAVABhAGcATgBhAG0AZQA+ADwALwBtAGUAZABpAGEAVABhAGcATgBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AD4APABtAGUAcwBzAGEAZwBlAEEAYwB0AGkAbwBuAD4APAAvAG0AZQBzAHMAYQBnAGUAQQBjAHQAaQBvAG4APgA8AGEAcABwAGkAZAA+AHcAeAA1AGEAYQAzADMAMwA2ADAANgA1ADUAMABkAGYAZAA1ADwALwBhAHAAcABpAGQAPgA8AC8AYQBwAHAATQBzAGcAPgA8AHMAYwBlAG4AZQA+ADAAPAAvAHMAYwBlAG4AZQA+ADwAdAB5AHAAZQA+ADAAPAAvAHQAeQBwAGUAPgA8AHUAcgBsAD4APAAvAHUAcgBsAD4APABuAGUAdwBXAG8AcgBkAGkAbgBnAEsAZQB5AD4APAAvAG4AZQB3AFcAbwByAGQAaQBuAGcASwBlAHkAPgA8AG4AZQB3AHQAeQBwAGUAPgAwADwALwBuAGUAdwB0AHkAcABlAD4APABpAG4AcwB0AGEAbABsAGUAZABXAG8AcgBkAGkAbgBnAD4APAAvAGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AHUAbgBpAG4AcwB0AGEAbABsAGUAZABXAG8AcgBkAGkAbgBnAD4APAAvAHUAbgBpAG4AcwB0AGEAbABsAGUAZABXAG8AcgBkAGkAbgBnAD4APAAvAGEAYwB0AGkAbwBuAEkAbgBmAG8APgA8AHMAdABhAHQARQB4AHQAUwB0AHIAPgA8ACEAWwBDAEQAQQBUAEEAWwBHAGgAUQBLAEUAbgBkADQATgBXAEYAaABNAHoATQB6AE4AagBBADIATgBUAFUAdwBaAEcAWgBrAE4AUQA9AD0AXQBdAD4APAAvAHMAdABhAHQARQB4AHQAUwB0AHIAPgA8AGwAbwBjAGEAdABpAG8AbgAgAHAAbwBpAEMAbABhAHMAcwBpAGYAeQBJAGQAPQAiACIAIABwAG8AaQBOAGEAbQBlAD0AIgAiACAAcABvAGkAQQBkAGQAcgBlAHMAcwA9ACIAIgAgAHAAbwBpAEMAbABhAHMAcwBpAGYAeQBUAHkAcABlAD0AIgAwACIAIABjAGkAdAB5AD0AIgAiAD4APAAvAGwAbwBjAGEAdABpAG8AbgA+ADwAcAB1AGIAbABpAGMAVQBzAGUAcgBOAGEAbQBlAD4APAAvAHAAdQBiAGwAaQBjAFUAcwBlAHIATgBhAG0AZQA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8AdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHUAcgBsAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8AdABoAHUAbQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB0AGgAdQBtAGIAdQByAGwAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB3AGUAYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdwBlAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAD4APAAvAFQAaQBtAGUAbABpAG4AZQBPAGIAagBlAGMAdAA+AA=="},{"ID":"-4704207042897244054","Time":1638238076,"Wxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","Nick":"d231fp1bnVsgACAAIAACMA==","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADQAMgA1ADMANwAwADMAMAA4ADEAMgAzADAANwA1ADYAMgBdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgAaQBkAF8AaABsAGcAbwByAG4AOAA0ADYAaQBoAHAAMgAyAF0AXQA+ADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADYAMwA4ADIAMwA4ADAANwA2AF0AXQA+ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APABhAHAAcABJAG4AZgBvAD4APABpAGQAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQBdAF0APgA8AC8AaQBkAD4APAB2AGUAcgBzAGkAbwBuAD4ANQAzADwALwB2AGUAcgBzAGkAbwBuAD4APABhAHAAcABOAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAUQBRAPOXUE5dAF0APgA8AC8AYQBwAHAATgBhAG0AZQA+ADwAaQBuAHMAdABhAGwAbABVAHIAbAA+ADwALwBpAG4AcwB0AGEAbABsAFUAcgBsAD4APABmAHIAbwBtAFUAcgBsAD4APAAvAGYAcgBvAG0AVQByAGwAPgA8AGMAbABpAGMAawBhAGIAbABlAD4AMAA8AC8AYwBsAGkAYwBrAGEAYgBsAGUAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAD4APAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwA+ADwAYwBvAG4AdABlAG4AdABhAHQAdAByAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABhAHQAdAByAD4APABzAG8AdQByAGMAZQBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APABzAG8AdQByAGMAZQBOAGkAYwBrAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APABzAHQAYQB0AGkAcwB0AGkAYwBzAEQAYQB0AGEAPgA8AC8AcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYQBwAHAAVQBzAGUAcgBOAGEAbQBlAD4APAAvAGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwAcABhAGcAZQBQAGEAdABoAD4APAAvAHAAYQBnAGUAUABhAHQAaAA+ADwAdgBlAHIAcwBpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHYAZQByAHMAaQBvAG4APgA8AGQAZQBiAHUAZwBNAG8AZABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AZABlAGIAdQBnAE0AbwBkAGUAPgA8AHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AC8AcwBoAGEAcgBlAEEAYwB0AGkAbwBuAEkAZAA+ADwAaQBzAEcAYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBpAHMARwBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AHIAYQBEAGEAdABhAD4APABzAHUAYgBUAHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcwB1AGIAVAB5AHAAZQA+ADwAcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwBwAHIAZQBsAG8AYQBkAFIAZQBzAG8AdQByAGMAZQBzAD4APAAvAHcAZQBhAHAAcABJAG4AZgBvAD4APABjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APAAvAGMAYQBuAHYAYQBzAEkAbgBmAG8AWABtAGwAPgA8AEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsANAAyAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFMAdAB5AGwAZQA+ADwAYwBvAG4AdABlAG4AdABTAHUAYgBTAHQAeQBsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFMAdQBiAFMAdAB5AGwAZQA+ADwAdABpAHQAbABlAD4APAAvAHQAaQB0AGwAZQA+ADwAZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APAAvAGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAcwA6AC8ALwBpAC4AeQAuAHEAcQAuAGMAbwBtAC8AdgA4AC8AcABsAGEAeQBzAG8AbgBnAC4AaAB0AG0AbAA/AHAAbABhAHQAZgBvAHIAbQA9ADEAMQAmAGEAcABwAHMAaABhAHIAZQA9AGEAbgBkAHIAbwBpAGQAXwBxAHEAJgBhAHAAcAB2AGUAcgBzAGkAbwBuAD0AMQAxADAAMAAwADEAMAA2ACYAaABvAHMAdABlAHUAaQBuAD0AbwBLADYAawBvAHcARQBBAG8ASwA0AHoANwBLADYAUAA3AGUAUwBxADcASwAtAHMAbwBjACoAKgAmAHMAbwBuAGcAbQBpAGQAPQAwADAAMgBqAE4AeQBvAEcAMwBGAGgASgBRAHQAJgB0AHkAcABlAD0AMAAmAGEAcABwAHMAbwBuAGcAdAB5AHAAZQA9ADEAJgBfAHcAdgA9ADEAJgBzAG8AdQByAGMAZQA9AHcAZQBpAHgAaQBuACYAcwBoAGEAcgBlAGYAcgBvAG0APQBnAGUAZABhAG4AJgBmAHIAbwBtAF8AaQBkAD0ANwAwADEAMwA3ADkANQAzADgAMAAmAGYAcgBvAG0AXwBpAGQAdAB5AHAAZQA9ADAAJgBmAHIAbwBtAF8AbgBhAG0AZQA9AEoAVQBVADEASgBUAGgARQBKAFQAZwB4AEoAVQBVADEASgBVAEkANQBKAFUASQAwAEoAVQBVADAASgBVAEkANQBKAFQAaABDAEoAVQBVADEASgBUAGsAdwBKAFQAaABGAEoAVQBWAEcASgBVAEoARABKAFQAaABEAEoAVQBVADQASgBVAEoARwBKAFQAawA0AEoAVQBVADIASgBUAGwARABKAFQAZwA1AEoAVQBVADQASgBVAEoARwBKAFQAawA1AEoAVQBVADAASgBVAEoAQgBKAFQAbABDAEoAVQBVADIASgBVAEYARQBKAFQAaABEAEoAVQBVADQASgBVAEYARgBKAFUARQA1AEoAVQBVADAASgBVAEoAQgBKAFUASgBCAEoAVQBVADIASgBUAGcAMABKAFQAbABHAEoAVQBVADEASgBUAGgAQgBKAFUARQA0ACYAQQBEAFQAQQBHAD0AZgBmAHMAaABhAHIAZQBdAF0APgA8AC8AYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAbQBlAGQAaQBhAEwAaQBzAHQAPgA8AG0AZQBkAGkAYQA+ADwAaQBkAD4APAAhAFsAQwBEAEEAVABBAFsAMQAzADcANAAyADUAMwA3ADAAMwAxADQAMwAxADIAOQA1ADEAMAA0AF0AXQA+ADwALwBpAGQAPgA8AHQAeQBwAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwA1AF0AXQA+ADwALwB0AHkAcABlAD4APAB0AGkAdABsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwABkGBPAE41Zw9con6xggj/CjABkGBPAE41Zw9con6xggswNXVxXztOmJjyZgn/XQBdAD4APAAvAHQAaQB0AGwAZQA+ADwAZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APAAhAFsAQwBEAEEAVABBAFsAdY3xgspPXQBdAD4APAAvAGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAcAByAGkAdgBhAHQAZQA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHAAcgBpAHYAYQB0AGUAPgA8AHMAbwBuAGcAYQBsAGIAdQBtAHUAcgBsAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcAA6AC8ALwB3AHgAYQBwAHAALgB0AGMALgBxAHEALgBjAG8AbQAvADIAMAAyAC8AMgAwADMAMAA0AC8AcwB0AG8AZABvAHcAbgBsAG8AYQBkAD8AZgBpAGwAZQBrAGUAeQA9ADMAMAAzADUAMAAyADAAMQAwADEAMAA0ADIAMQAzADAAMQBmADAAMgAwADIAMAAwAGMAYQAwADQAMAAyADUAMwA1AGEAMAA0ADEAMAA3AGYAZABiADgANgA5ADcAYwA1ADAAZQBhADAANAA2AGUAMQBhADUAZgBiAGQAZQAyADIAYgA3ADMAMgAxADkAMAAyADAAMwAwADAAYgBkADUAMgAwADQAMABkADAAMAAwADAAMAAwADAANAA2ADIANwA0ADYANgA3ADMAMAAwADAAMAAwADAAMAAxADMAMQAmAGgAeQA9AFMAWgAmAHMAdABvAHIAZQBpAGQAPQAzADIAMwAwADMAMgAzADEAMwAxADMAMQAzADMAMwAwADMAMQAzADAAMwAwADMANwAzADQAMwA3ADMAMAAzADAAMwAwADMAMwA2ADIANgAzADYAMwAzADkAMwAwADMANgAzADgAMwA3ADYANgAzADUAMwA4ADMANgAzADUANgA2ADMANgAzADAAMwA4ADMAOAAzADAAMwA5ADMAMAAzADAAMwAwADMAMAAzADAAMwAwADYAMwA2ADEAJgBiAGkAegBpAGQAPQAxADAAMgAzAF0AXQA+ADwALwBzAG8AbgBnAGEAbABiAHUAbQB1AHIAbAA+ADwAdQByAGwAIAB0AHkAcABlAD0AIgAwACIAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAGMANgAuAHkALgBxAHEALgBjAG8AbQAvAHIAcwBjAC8AZgBjAGcAaQAtAGIAaQBuAC8AZgBjAGcAXwBwAHkAcQBfAHAAbABhAHkALgBmAGMAZwA/AHMAbwBuAGcAaQBkAD0AJgBzAG8AbgBnAG0AaQBkAD0AMAAwADIAagBOAHkAbwBHADMARgBoAEoAUQB0ACYAcwBvAG4AZwB0AHkAcABlAD0AMQAmAGYAcgBvAG0AdABhAGcAPQA0ADYAJgB1AGkAbgA9ADEAMQA1ADIAOQAyADEANQAwADUAMQA0ADQANwA5ADUAMgA2ADIAJgBjAG8AZABlAD0ANABCAEYARAAzAF0AXQA+ADwALwB1AHIAbAA+ADwAdABoAHUAbQBiACAAdAB5AHAAZQA9ACIAMQAiAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcAA6AC8ALwBzAHoAbQBtAHMAbgBzAC4AcQBwAGkAYwAuAGMAbgAvAG0AbQBzAG4AcwAvAEcARABBAE8AdAA1AGYATABrAEMAZwA2AEwAawBuAFUAagA4ADEAaQBiAFEAeABNADkAQgBPAEcARQBRADAAaQBiAE0ASAA4AEEANABGAFgASwBoAGoAcQBvAGYARQBpAGIANQBQAGkAYQB3AHYAQgB2AEUAbQBwAGYAZQA1AGMAWgBRAFYAVQBkAEoAVABLAEkAQQBlAGcAVABYAGMALwAxADUAMABdAF0APgA8AC8AdABoAHUAbQBiAD4APAB2AGkAZABlAG8ARAB1AHIAYQB0AGkAbwBuAD4APAAhAFsAQwBEAEEAVABBAFsAMAAuADAAXQBdAD4APAAvAHYAaQBkAGUAbwBEAHUAcgBhAHQAaQBvAG4APgA8AHMAaQB6AGUAIAB0AG8AdABhAGwAUwBpAHoAZQA9ACIAMwA2ADIANgAuADAAIgAgAHcAaQBkAHQAaAA9ACIAMQA1ADAALgAwACIAIABoAGUAaQBnAGgAdAA9ACIAMQA1ADAALgAwACIAPgA8AC8AcwBpAHoAZQA+ADwALwBtAGUAZABpAGEAPgA8AC8AbQBlAGQAaQBhAEwAaQBzAHQAPgA8AG0AdQBzAGkAYwBTAGgAYQByAGUASQB0AGUAbQA+ADwAbQB2AE8AYgBqAGUAYwB0AEkAZAA+ADwALwBtAHYATwBiAGoAZQBjAHQASQBkAD4APABtAHYATgBvAG4AYwBlAEkAZAA+ADwALwBtAHYATgBvAG4AYwBlAEkAZAA+ADwAbQB2AEMAbwB2AGUAcgBVAHIAbAA+ADwALwBtAHYAQwBvAHYAZQByAFUAcgBsAD4APABtAHYATQBhAGsAZQByAEYAaQBuAGQAZQByAE4AaQBjAGsAbgBhAG0AZQA+ADwALwBtAHYATQBhAGsAZQByAEYAaQBuAGQAZQByAE4AaQBjAGsAbgBhAG0AZQA+ADwAbQB2AFMAaQBuAGcAZQByAE4AYQBtAGUAPgB1jfGCyk88AC8AbQB2AFMAaQBuAGcAZQByAE4AYQBtAGUAPgA8AG0AdgBBAGwAYgB1AG0ATgBhAG0AZQA+AAGQYE8ATjVnD1yifrGCIAA1dXFfTGvyZhNOkY88AC8AbQB2AEEAbABiAHUAbQBOAGEAbQBlAD4APABtAHYATQB1AHMAaQBjAEcAZQBuAHIAZQA+ADwALwBtAHYATQB1AHMAaQBjAEcAZQBuAHIAZQA+ADwAbQB2AEkAcwBzAHUAZQBEAGEAdABlAD4AMAA8AC8AbQB2AEkAcwBzAHUAZQBEAGEAdABlAD4APABtAHYASQBkAGUAbgB0AGkAZgBpAGMAYQB0AGkAbwBuAD4APAAvAG0AdgBJAGQAZQBuAHQAaQBmAGkAYwBhAHQAaQBvAG4APgA8AG0AdQBzAGkAYwBEAHUAcgBhAHQAaQBvAG4APgAyADMAMgAwADAAMAA8AC8AbQB1AHMAaQBjAEQAdQByAGEAdABpAG8AbgA+ADwAbQB2AEUAeAB0AEkAbgBmAG8APgA8AC8AbQB2AEUAeAB0AEkAbgBmAG8APgA8AG0AdgBPAHAAZQByAGEAdABpAG8AbgBVAHIAbAA+ADwALwBtAHYATwBwAGUAcgBhAHQAaQBvAG4AVQByAGwAPgA8AG0AaQBkAD4APAAvAG0AaQBkAD4APAAvAG0AdQBzAGkAYwBTAGgAYQByAGUASQB0AGUAbQA+ADwALwBDAG8AbgB0AGUAbgB0AE8AYgBqAGUAYwB0AD4APABhAGMAdABpAG8AbgBJAG4AZgBvAD4APABhAHAAcABNAHMAZwA+ADwAbQBlAGQAaQBhAFQAYQBnAE4AYQBtAGUAPgA8AC8AbQBlAGQAaQBhAFQAYQBnAE4AYQBtAGUAPgA8AG0AZQBzAHMAYQBnAGUARQB4AHQAPgA8AC8AbQBlAHMAcwBhAGcAZQBFAHgAdAA+ADwAbQBlAHMAcwBhAGcAZQBBAGMAdABpAG8AbgA+ADwALwBtAGUAcwBzAGEAZwBlAEEAYwB0AGkAbwBuAD4APABhAHAAcABpAGQAPgB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQA8AC8AYQBwAHAAaQBkAD4APAAvAGEAcABwAE0AcwBnAD4APABzAGMAZQBuAGUAPgAwADwALwBzAGMAZQBuAGUAPgA8AHQAeQBwAGUAPgAwADwALwB0AHkAcABlAD4APAB1AHIAbAA+ADwALwB1AHIAbAA+ADwAbgBlAHcAVwBvAHIAZABpAG4AZwBLAGUAeQA+ADwALwBuAGUAdwBXAG8AcgBkAGkAbgBnAEsAZQB5AD4APABuAGUAdwB0AHkAcABlAD4AMAA8AC8AbgBlAHcAdAB5AHAAZQA+ADwAaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwALwBpAG4AcwB0AGEAbABsAGUAZABXAG8AcgBkAGkAbgBnAD4APAB1AG4AaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwALwB1AG4AaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwALwBhAGMAdABpAG8AbgBJAG4AZgBvAD4APABzAHQAYQB0AEUAeAB0AFMAdAByAD4APAAhAFsAQwBEAEEAVABBAFsARwBoAFEASwBFAG4AZAA0AE4AVwBGAGgATQB6AE0AegBOAGoAQQAyAE4AVABVAHcAWgBHAFoAawBOAFEAPQA9AF0AXQA+ADwALwBzAHQAYQB0AEUAeAB0AFMAdAByAD4APABsAG8AYwBhAHQAaQBvAG4AIABwAG8AaQBDAGwAYQBzAHMAaQBmAHkASQBkAD0AIgAiACAAcABvAGkATgBhAG0AZQA9ACIAIgAgAHAAbwBpAEEAZABkAHIAZQBzAHMAPQAiACIAIABwAG8AaQBDAGwAYQBzAHMAaQBmAHkAVAB5AHAAZQA9ACIAMAAiACAAYwBpAHQAeQA9ACIAIgA+ADwALwBsAG8AYwBhAHQAaQBvAG4APgA8AHAAdQBiAGwAaQBjAFUAcwBlAHIATgBhAG0AZQA+ADwALwBwAHUAYgBsAGkAYwBVAHMAZQByAE4AYQBtAGUAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB1AHIAbAA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHQAaAB1AG0AYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdABoAHUAbQBiAHUAcgBsAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8AdwBlAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHcAZQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwA+ADwALwBUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA="},{"ID":"-4704207743492157314","Time":1638237992,"Wxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","Nick":"d231fp1bnVsgACAAIAACMA==","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADQAMgA1ADMANgAzADMAMAAyADEANwAzADkANAAzADAAMgBdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgAaQBkAF8AaABsAGcAbwByAG4AOAA0ADYAaQBoAHAAMgAyAF0AXQA+ADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADYAMwA4ADIAMwA3ADkAOQAyAF0AXQA+ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APABhAHAAcABJAG4AZgBvAD4APABpAGQAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQBdAF0APgA8AC8AaQBkAD4APAB2AGUAcgBzAGkAbwBuAD4ANQAzADwALwB2AGUAcgBzAGkAbwBuAD4APABhAHAAcABOAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAUQBRAPOXUE5dAF0APgA8AC8AYQBwAHAATgBhAG0AZQA+ADwAaQBuAHMAdABhAGwAbABVAHIAbAA+ADwALwBpAG4AcwB0AGEAbABsAFUAcgBsAD4APABmAHIAbwBtAFUAcgBsAD4APAAvAGYAcgBvAG0AVQByAGwAPgA8AGMAbABpAGMAawBhAGIAbABlAD4AMAA8AC8AYwBsAGkAYwBrAGEAYgBsAGUAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAD4APAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwA+ADwAYwBvAG4AdABlAG4AdABhAHQAdAByAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABhAHQAdAByAD4APABzAG8AdQByAGMAZQBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APABzAG8AdQByAGMAZQBOAGkAYwBrAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APABzAHQAYQB0AGkAcwB0AGkAYwBzAEQAYQB0AGEAPgA8AC8AcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYQBwAHAAVQBzAGUAcgBOAGEAbQBlAD4APAAvAGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwAcABhAGcAZQBQAGEAdABoAD4APAAvAHAAYQBnAGUAUABhAHQAaAA+ADwAdgBlAHIAcwBpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHYAZQByAHMAaQBvAG4APgA8AGQAZQBiAHUAZwBNAG8AZABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AZABlAGIAdQBnAE0AbwBkAGUAPgA8AHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AC8AcwBoAGEAcgBlAEEAYwB0AGkAbwBuAEkAZAA+ADwAaQBzAEcAYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBpAHMARwBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AHIAYQBEAGEAdABhAD4APABzAHUAYgBUAHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcwB1AGIAVAB5AHAAZQA+ADwAcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwBwAHIAZQBsAG8AYQBkAFIAZQBzAG8AdQByAGMAZQBzAD4APAAvAHcAZQBhAHAAcABJAG4AZgBvAD4APABjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APAAvAGMAYQBuAHYAYQBzAEkAbgBmAG8AWABtAGwAPgA8AEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsANAAyAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFMAdAB5AGwAZQA+ADwAYwBvAG4AdABlAG4AdABTAHUAYgBTAHQAeQBsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFMAdQBiAFMAdAB5AGwAZQA+ADwAdABpAHQAbABlAD4APAAvAHQAaQB0AGwAZQA+ADwAZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APAAvAGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAcwA6AC8ALwBpAC4AeQAuAHEAcQAuAGMAbwBtAC8AdgA4AC8AcABsAGEAeQBzAG8AbgBnAC4AaAB0AG0AbAA/AHAAbABhAHQAZgBvAHIAbQA9ADEAMQAmAGEAcABwAHMAaABhAHIAZQA9AGEAbgBkAHIAbwBpAGQAXwBxAHEAJgBhAHAAcAB2AGUAcgBzAGkAbwBuAD0AMQAxADAAMAAwADEAMAA2ACYAaABvAHMAdABlAHUAaQBuAD0AbwBLADYAawBvAHcARQBBAG8ASwA0AHoANwBLADYAUAA3AGUAUwBxADcASwAtAHMAbwBjACoAKgAmAHMAbwBuAGcAbQBpAGQAPQAwADAAMQAxAEgASgBFAHoAMQBLAHgAegBEAHAAJgB0AHkAcABlAD0AMAAmAGEAcABwAHMAbwBuAGcAdAB5AHAAZQA9ADEAJgBfAHcAdgA9ADEAJgBzAG8AdQByAGMAZQA9AHcAZQBpAHgAaQBuACYAcwBoAGEAcgBlAGYAcgBvAG0APQBnAGUAZABhAG4AJgBmAHIAbwBtAF8AaQBkAD0ANwAwADEAMwA3ADkANQAzADgAMAAmAGYAcgBvAG0AXwBpAGQAdAB5AHAAZQA9ADAAJgBmAHIAbwBtAF8AbgBhAG0AZQA9AEoAVQBVADEASgBUAGgARQBKAFQAZwB4AEoAVQBVADEASgBVAEkANQBKAFUASQAwAEoAVQBVADAASgBVAEkANQBKAFQAaABDAEoAVQBVADEASgBUAGsAdwBKAFQAaABGAEoAVQBWAEcASgBVAEoARABKAFQAaABEAEoAVQBVADQASgBVAEoARwBKAFQAawA0AEoAVQBVADIASgBUAGwARABKAFQAZwA1AEoAVQBVADQASgBVAEoARwBKAFQAawA1AEoAVQBVADAASgBVAEoAQgBKAFQAbABDAEoAVQBVADIASgBVAEYARQBKAFQAaABEAEoAVQBVADQASgBVAEYARgBKAFUARQA1AEoAVQBVADAASgBVAEoAQgBKAFUASgBCAEoAVQBVADIASgBUAGcAMABKAFQAbABHAEoAVQBVADEASgBUAGgAQgBKAFUARQA0ACYAQQBEAFQAQQBHAD0AZgBmAHMAaABhAHIAZQBdAF0APgA8AC8AYwBvAG4AdABlAG4AdABVAHIAbAA+ADwAbQBlAGQAaQBhAEwAaQBzAHQAPgA8AG0AZQBkAGkAYQA+ADwAaQBkAD4APAAhAFsAQwBEAEEAVABBAFsAMQAzADcANAAyADUAMwA2ADMAMwAwADgAMQA2ADAAMAAwADEANAA2AF0AXQA+ADwALwBpAGQAPgA8AHQAeQBwAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwA1AF0AXQA+ADwALwB0AHkAcABlAD4APAB0AGkAdABsAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAPWSlZhHbOmF0AXQA+ADwALwB0AGkAdABsAGUAPgA8AGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbAClumlxdAF0APgA8AC8AZABlAHMAYwByAGkAcAB0AGkAbwBuAD4APABwAHIAaQB2AGEAdABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcAByAGkAdgBhAHQAZQA+ADwAcwBvAG4AZwBhAGwAYgB1AG0AdQByAGwAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwADoALwAvAHcAeABhAHAAcAAuAHQAYwAuAHEAcQAuAGMAbwBtAC8AMgAwADIALwAyADAAMwAwADQALwBzAHQAbwBkAG8AdwBuAGwAbwBhAGQAPwBmAGkAbABlAGsAZQB5AD0AMwAwADMANAAwADIAMAAxADAAMQAwADQAMgAwADMAMAAxAGUAMAAyADAAMgAwADAAYwBhADAANAAwADIANQAzADUAYQAwADQAMQAwAGMANgAyADUAZQA1AGEAYwA1ADAAZgBhAGUAYgBkADkAYwAyADAAOABhADQANQA5AGYAZgA4AGIAZgA0AGIAOQAwADIAMAAyADQAZQBlAGUAMAA0ADAAZAAwADAAMAAwADAAMAAwADQANgAyADcANAA2ADYANwAzADAAMAAwADAAMAAwADAAMQAzADEAJgBoAHkAPQBTAFoAJgBzAHQAbwByAGUAaQBkAD0AMwAyADMAMAAzADIAMwAxADMAMQAzADEAMwAzADMAMAAzADEAMwAwADMAMAAzADYAMwAyADMAMQAzADAAMwAwADMAMAA2ADUAMwA1ADYANgAzADEANgAzADMAMAAzADYAMwA4ADMANwA2ADYAMwA1ADMAOAAzADYAMwA5ADYANgAzADYAMwAxADMAOAAzADgAMwAwADMAOQAzADAAMwAwADMAMAAzADAAMwAwADMAMAA2ADMANgAxACYAYgBpAHoAaQBkAD0AMQAwADIAMwBdAF0APgA8AC8AcwBvAG4AZwBhAGwAYgB1AG0AdQByAGwAPgA8AHUAcgBsACAAdAB5AHAAZQA9ACIAMAAiAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcAA6AC8ALwBjADYALgB5AC4AcQBxAC4AYwBvAG0ALwByAHMAYwAvAGYAYwBnAGkALQBiAGkAbgAvAGYAYwBnAF8AcAB5AHEAXwBwAGwAYQB5AC4AZgBjAGcAPwBzAG8AbgBnAGkAZAA9ACYAcwBvAG4AZwBtAGkAZAA9ADAAMAAxADEASABKAEUAegAxAEsAeAB6AEQAcAAmAHMAbwBuAGcAdAB5AHAAZQA9ADEAJgBmAHIAbwBtAHQAYQBnAD0ANAA2ACYAdQBpAG4APQAxADEANQAyADkAMgAxADUAMAA1ADEANAA0ADcAOQA1ADIANgAyACYAYwBvAGQAZQA9ADEAOABCAEMANwBdAF0APgA8AC8AdQByAGwAPgA8AHQAaAB1AG0AYgAgAHQAeQBwAGUAPQAiADEAIgA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAOgAvAC8AcwB6AG0AbQBzAG4AcwAuAHEAcABpAGMALgBjAG4ALwBtAG0AcwBuAHMALwBHAEQAQQBPAHQANQBmAEwAawBDAGcANgBMAGsAbgBVAGoAOAAxAGkAYgBRADcAWABiAFoARwA4AGkAYQBwAFQAUgBKAGsAZAAyAGwAbwB0AGoATQBnADYAWgB5ADkAUwByAHMAUwAwAGkAYgBJAGMAWgBPAEEAMABUAEMAeQBDAG8AMQBDAEQAQQBPAGMAMwBUAEkAdwBMAEYAawAvADEANQAwAF0AXQA+ADwALwB0AGgAdQBtAGIAPgA8AHYAaQBkAGUAbwBEAHUAcgBhAHQAaQBvAG4APgA8ACEAWwBDAEQAQQBUAEEAWwAwAC4AMABdAF0APgA8AC8AdgBpAGQAZQBvAEQAdQByAGEAdABpAG8AbgA+ADwAcwBpAHoAZQAgAHQAbwB0AGEAbABTAGkAegBlAD0AIgAzADkAMAAwAC4AMAAiACAAdwBpAGQAdABoAD0AIgAxADUAMAAuADAAIgAgAGgAZQBpAGcAaAB0AD0AIgAxADUAMAAuADAAIgA+ADwALwBzAGkAegBlAD4APAAvAG0AZQBkAGkAYQA+ADwALwBtAGUAZABpAGEATABpAHMAdAA+ADwAbQB1AHMAaQBjAFMAaABhAHIAZQBJAHQAZQBtAD4APABtAHYATwBiAGoAZQBjAHQASQBkAD4APAAvAG0AdgBPAGIAagBlAGMAdABJAGQAPgA8AG0AdgBOAG8AbgBjAGUASQBkAD4APAAvAG0AdgBOAG8AbgBjAGUASQBkAD4APABtAHYAQwBvAHYAZQByAFUAcgBsAD4APAAvAG0AdgBDAG8AdgBlAHIAVQByAGwAPgA8AG0AdgBNAGEAawBlAHIARgBpAG4AZABlAHIATgBpAGMAawBuAGEAbQBlAD4APAAvAG0AdgBNAGEAawBlAHIARgBpAG4AZABlAHIATgBpAGMAawBuAGEAbQBlAD4APABtAHYAUwBpAG4AZwBlAHIATgBhAG0AZQA+AClumlw8AC8AbQB2AFMAaQBuAGcAZQByAE4AYQBtAGUAPgA8AG0AdgBBAGwAYgB1AG0ATgBhAG0AZQA+ACluD19IZZRePAAvAG0AdgBBAGwAYgB1AG0ATgBhAG0AZQA+ADwAbQB2AE0AdQBzAGkAYwBHAGUAbgByAGUAPgA8AC8AbQB2AE0AdQBzAGkAYwBHAGUAbgByAGUAPgA8AG0AdgBJAHMAcwB1AGUARABhAHQAZQA+ADAAPAAvAG0AdgBJAHMAcwB1AGUARABhAHQAZQA+ADwAbQB2AEkAZABlAG4AdABpAGYAaQBjAGEAdABpAG8AbgA+ADwALwBtAHYASQBkAGUAbgB0AGkAZgBpAGMAYQB0AGkAbwBuAD4APABtAHUAcwBpAGMARAB1AHIAYQB0AGkAbwBuAD4AMgA0ADAAMAAwADAAPAAvAG0AdQBzAGkAYwBEAHUAcgBhAHQAaQBvAG4APgA8AG0AdgBFAHgAdABJAG4AZgBvAD4APAAvAG0AdgBFAHgAdABJAG4AZgBvAD4APABtAHYATwBwAGUAcgBhAHQAaQBvAG4AVQByAGwAPgA8AC8AbQB2AE8AcABlAHIAYQB0AGkAbwBuAFUAcgBsAD4APABtAGkAZAA+ADwALwBtAGkAZAA+ADwALwBtAHUAcwBpAGMAUwBoAGEAcgBlAEkAdABlAG0APgA8AC8AQwBvAG4AdABlAG4AdABPAGIAagBlAGMAdAA+ADwAYQBjAHQAaQBvAG4ASQBuAGYAbwA+ADwAYQBwAHAATQBzAGcAPgA8AG0AZQBkAGkAYQBUAGEAZwBOAGEAbQBlAD4APAAvAG0AZQBkAGkAYQBUAGEAZwBOAGEAbQBlAD4APABtAGUAcwBzAGEAZwBlAEUAeAB0AD4APAAvAG0AZQBzAHMAYQBnAGUARQB4AHQAPgA8AG0AZQBzAHMAYQBnAGUAQQBjAHQAaQBvAG4APgA8AC8AbQBlAHMAcwBhAGcAZQBBAGMAdABpAG8AbgA+ADwAYQBwAHAAaQBkAD4AdwB4ADUAYQBhADMAMwAzADYAMAA2ADUANQAwAGQAZgBkADUAPAAvAGEAcABwAGkAZAA+ADwALwBhAHAAcABNAHMAZwA+ADwAcwBjAGUAbgBlAD4AMAA8AC8AcwBjAGUAbgBlAD4APAB0AHkAcABlAD4AMAA8AC8AdAB5AHAAZQA+ADwAdQByAGwAPgA8AC8AdQByAGwAPgA8AG4AZQB3AFcAbwByAGQAaQBuAGcASwBlAHkAPgA8AC8AbgBlAHcAVwBvAHIAZABpAG4AZwBLAGUAeQA+ADwAbgBlAHcAdAB5AHAAZQA+ADAAPAAvAG4AZQB3AHQAeQBwAGUAPgA8AGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwAdQBuAGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AdQBuAGkAbgBzAHQAYQBsAGwAZQBkAFcAbwByAGQAaQBuAGcAPgA8AC8AYQBjAHQAaQBvAG4ASQBuAGYAbwA+ADwAcwB0AGEAdABFAHgAdABTAHQAcgA+ADwAIQBbAEMARABBAFQAQQBbAEcAaABRAEsARQBuAGQANABOAFcARgBoAE0AegBNAHoATgBqAEEAMgBOAFQAVQB3AFoARwBaAGsATgBRAD0APQBdAF0APgA8AC8AcwB0AGEAdABFAHgAdABTAHQAcgA+ADwAbABvAGMAYQB0AGkAbwBuACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AEkAZAA9ACIAIgAgAHAAbwBpAE4AYQBtAGUAPQAiACIAIABwAG8AaQBBAGQAZAByAGUAcwBzAD0AIgAiACAAcABvAGkAQwBsAGEAcwBzAGkAZgB5AFQAeQBwAGUAPQAiADAAIgAgAGMAaQB0AHkAPQAiACIAPgA8AC8AbABvAGMAYQB0AGkAbwBuAD4APABwAHUAYgBsAGkAYwBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcAB1AGIAbABpAGMAVQBzAGUAcgBOAGEAbQBlAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdQByAGwAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwB0AGgAdQBtAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHQAaAB1AG0AYgB1AHIAbAA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHcAZQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB3AGUAYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8APgA8AC8AVABpAG0AZQBsAGkAbgBlAE8AYgBqAGUAYwB0AD4A"},{"ID":"-4704804105862311814","Time":1638166900,"Wxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","Nick":"QgBvAG8AbQA=","SnsText":"PABUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA8AGkAZAA+ADwAIQBbAEMARABBAFQAQQBbADEAMwA3ADQAMQA5ADMAOQA5ADYANwA4ADQANwAyADMAOQA4ADAAMgBdAF0APgA8AC8AaQBkAD4APAB1AHMAZQByAG4AYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgAaQBkAF8AaABsAGcAbwByAG4AOAA0ADYAaQBoAHAAMgAyAF0AXQA+ADwALwB1AHMAZQByAG4AYQBtAGUAPgA8AGMAcgBlAGEAdABlAFQAaQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADYAMwA4ADEANgA2ADkAMAAwAF0AXQA+ADwALwBjAHIAZQBhAHQAZQBUAGkAbQBlAD4APABjAG8AbgB0AGUAbgB0AEQAZQBzAGMAUwBoAG8AdwBUAHkAcABlAD4AMAA8AC8AYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAaABvAHcAVAB5AHAAZQA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAFMAYwBlAG4AZQA+ADAAPAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwBTAGMAZQBuAGUAPgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APABhAHAAcABJAG4AZgBvAD4APABpAGQAPgA8ACEAWwBDAEQAQQBUAEEAWwB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQBdAF0APgA8AC8AaQBkAD4APAB2AGUAcgBzAGkAbwBuAD4ANQAzADwALwB2AGUAcgBzAGkAbwBuAD4APABhAHAAcABOAGEAbQBlAD4APAAhAFsAQwBEAEEAVABBAFsAUQBRAPOXUE5dAF0APgA8AC8AYQBwAHAATgBhAG0AZQA+ADwAaQBuAHMAdABhAGwAbABVAHIAbAA+ADwALwBpAG4AcwB0AGEAbABsAFUAcgBsAD4APABmAHIAbwBtAFUAcgBsAD4APAAvAGYAcgBvAG0AVQByAGwAPgA8AGMAbABpAGMAawBhAGIAbABlAD4AMAA8AC8AYwBsAGkAYwBrAGEAYgBsAGUAPgA8AC8AYQBwAHAASQBuAGYAbwA+ADwAYwBvAG4AdABlAG4AdABEAGUAcwBjAD4APAAvAGMAbwBuAHQAZQBuAHQARABlAHMAYwA+ADwAYwBvAG4AdABlAG4AdABhAHQAdAByAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABhAHQAdAByAD4APABzAG8AdQByAGMAZQBVAHMAZQByAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUAVQBzAGUAcgBOAGEAbQBlAD4APABzAG8AdQByAGMAZQBOAGkAYwBrAE4AYQBtAGUAPgA8AC8AcwBvAHUAcgBjAGUATgBpAGMAawBOAGEAbQBlAD4APABzAHQAYQB0AGkAcwB0AGkAYwBzAEQAYQB0AGEAPgA8AC8AcwB0AGEAdABpAHMAdABpAGMAcwBEAGEAdABhAD4APAB3AGUAYQBwAHAASQBuAGYAbwA+ADwAYQBwAHAAVQBzAGUAcgBOAGEAbQBlAD4APAAvAGEAcABwAFUAcwBlAHIATgBhAG0AZQA+ADwAcABhAGcAZQBQAGEAdABoAD4APAAvAHAAYQBnAGUAUABhAHQAaAA+ADwAdgBlAHIAcwBpAG8AbgA+ADwAIQBbAEMARABBAFQAQQBbADAAXQBdAD4APAAvAHYAZQByAHMAaQBvAG4APgA8AGQAZQBiAHUAZwBNAG8AZABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AZABlAGIAdQBnAE0AbwBkAGUAPgA8AHMAaABhAHIAZQBBAGMAdABpAG8AbgBJAGQAPgA8AC8AcwBoAGEAcgBlAEEAYwB0AGkAbwBuAEkAZAA+ADwAaQBzAEcAYQBtAGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBpAHMARwBhAG0AZQA+ADwAbQBlAHMAcwBhAGcAZQBFAHgAdAByAGEARABhAHQAYQA+ADwALwBtAGUAcwBzAGEAZwBlAEUAeAB0AHIAYQBEAGEAdABhAD4APABzAHUAYgBUAHkAcABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AcwB1AGIAVAB5AHAAZQA+ADwAcAByAGUAbABvAGEAZABSAGUAcwBvAHUAcgBjAGUAcwA+ADwALwBwAHIAZQBsAG8AYQBkAFIAZQBzAG8AdQByAGMAZQBzAD4APAAvAHcAZQBhAHAAcABJAG4AZgBvAD4APABjAGEAbgB2AGEAcwBJAG4AZgBvAFgAbQBsAD4APAAvAGMAYQBuAHYAYQBzAEkAbgBmAG8AWABtAGwAPgA8AEMAbwBuAHQAZQBuAHQATwBiAGoAZQBjAHQAPgA8AGMAbwBuAHQAZQBuAHQAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsAMwBdAF0APgA8AC8AYwBvAG4AdABlAG4AdABTAHQAeQBsAGUAPgA8AGMAbwBuAHQAZQBuAHQAUwB1AGIAUwB0AHkAbABlAD4APAAhAFsAQwBEAEEAVABBAFsAMABdAF0APgA8AC8AYwBvAG4AdABlAG4AdABTAHUAYgBTAHQAeQBsAGUAPgA8AHQAaQB0AGwAZQA+ADwAIQBbAEMARABBAFQAQQBbAAaQGGIoAAowBpAYYgswqmcYYlF/OG47TpiY8mYpAF0AXQA+ADwALwB0AGkAdABsAGUAPgA8AGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwALwBkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AGMAbwBuAHQAZQBuAHQAVQByAGwAPgA8ACEAWwBDAEQAQQBUAEEAWwBoAHQAdABwAHMAOgAvAC8AaQAuAHkALgBxAHEALgBjAG8AbQAvAHYAOAAvAHAAbABhAHkAcwBvAG4AZwAuAGgAdABtAGwAPwBwAGwAYQB0AGYAbwByAG0APQAxADEAJgBhAHAAcABzAGgAYQByAGUAPQBhAG4AZAByAG8AaQBkAF8AcQBxACYAYQBwAHAAdgBlAHIAcwBpAG8AbgA9ADEAMQAwADAAMAAxADAANgAmAGgAbwBzAHQAZQB1AGkAbgA9AG8ASwA2AGsAbwB3AEUAQQBvAEsANAB6ADcASwA2AFAANwBlAFMAcQA3AEsALQBzAG8AYwAqACoAJgBzAG8AbgBnAG0AaQBkAD0AMAAwADEAUgBkAFQAdQBxADAAYQBhAHIAcwBTACYAdAB5AHAAZQA9ADAAJgBhAHAAcABzAG8AbgBnAHQAeQBwAGUAPQAxACYAXwB3AHYAPQAxACYAcwBvAHUAcgBjAGUAPQB3AGUAaQB4AGkAbgAmAHMAaABhAHIAZQBmAHIAbwBtAD0AZwBlAGQAYQBuACYAZgByAG8AbQBfAGkAZAA9ADcAOQA1ADYAOAAxADIAMQA4ADcAJgBmAHIAbwBtAF8AaQBkAHQAeQBwAGUAPQAmAGYAcgBvAG0AXwBuAGEAbQBlAD0ASgBVAFUAMQBKAFQAaABFAEoAVABoAEYASgBVAFUANABKAFUARgBHAEoAVQBGAEUASgBVAFUAMwBKAFUASQB5AEoAVQBKAEYASgBVAFUANQBKAFQAZwB3AEoAVABnADUASgBVAFUAMABKAFUASQA0AEoAVQBFADQASgBVAFUANQBKAFQAZwB5AEoAVQBFAHoASgBVAFUAMABKAFUASgBCAEoAVABsAEMASgBVAFUANABKAFUASQAyAEoAVABnADEASgBVAFUAMQBKAFUARQAxAEoAVQBKAEUASgBVAFUAMQBKAFQAawB3AEoAVQBGAEQASgBVAFUAMwBKAFQAbABCAEoAVABnADAASgBVAFUAMgBKAFUASQAxAEoAVABnAHgASgBVAFUANABKAFUARQB4AEoAVABoAEQASgBVAFUAMwBKAFQAZwB6AEoAVQBGAEUASgBVAFUAMgBKAFUARgBFAEoAVABoAEQAJgBBAEQAVABBAEcAPQBmAGYAcwBoAGEAcgBlAF0AXQA+ADwALwBjAG8AbgB0AGUAbgB0AFUAcgBsAD4APABtAGUAZABpAGEATABpAHMAdAA+ADwAbQBlAGQAaQBhAD4APABpAGQAPgA8ACEAWwBDAEQAQQBUAEEAWwAxADMANwA0ADEAOQAzADkAOQA2ADgANQAwADcAMwA4ADMAOQAxADIAXQBdAD4APAAvAGkAZAA+ADwAdAB5AHAAZQA+ADwAIQBbAEMARABBAFQAQQBbADIAXQBdAD4APAAvAHQAeQBwAGUAPgA8AHQAaQB0AGwAZQA+ADwALwB0AGkAdABsAGUAPgA8AGQAZQBzAGMAcgBpAHAAdABpAG8AbgA+ADwALwBkAGUAcwBjAHIAaQBwAHQAaQBvAG4APgA8AHAAcgBpAHYAYQB0AGUAPgA8ACEAWwBDAEQAQQBUAEEAWwAwAF0AXQA+ADwALwBwAHIAaQB2AGEAdABlAD4APAB1AHIAbAAgAHQAeQBwAGUAPQAiADEAIgA+ADwAIQBbAEMARABBAFQAQQBbAGgAdAB0AHAAOgAvAC8AcwB6AG0AbQBzAG4AcwAuAHEAcABpAGMALgBjAG4ALwBtAG0AcwBuAHMALwBHAEQAQQBPAHQANQBmAEwAawBDAGcANgBMAGsAbgBVAGoAOAAxAGkAYgBRAHkAMgBUAFgARQByAHoAaAB1AFkASwB3AGUATgBFAGgAWQBUAEIASQAxADIAegBqAGwANwBnAE8ASQBvAEkAawBHAEQATwBIAGkAYQBCAGIAMgB1AGsASgBkAEwAWAB5AGYAMgBsAHEARABMAFEALwAwAF0AXQA+ADwALwB1AHIAbAA+ADwAdABoAHUAbQBiACAAdAB5AHAAZQA9ACIAMQAiAD4APAAhAFsAQwBEAEEAVABBAFsAaAB0AHQAcAA6AC8ALwBzAHoAbQBtAHMAbgBzAC4AcQBwAGkAYwAuAGMAbgAvAG0AbQBzAG4AcwAvAEcARABBAE8AdAA1AGYATABrAEMAZwA2AEwAawBuAFUAagA4ADEAaQBiAFEAeQAyAFQAWABFAHIAegBoAHUAWQBLAHcAZQBOAEUAaABZAFQAQgBJADEAMgB6AGoAbAA3AGcATwBJAG8ASQBrAEcARABPAEgAaQBhAEIAYgAyAHUAawBKAGQATABYAHkAZgAyAGwAcQBEAEwAUQAvADEANQAwAF0AXQA+ADwALwB0AGgAdQBtAGIAPgA8AHYAaQBkAGUAbwBEAHUAcgBhAHQAaQBvAG4APgA8ACEAWwBDAEQAQQBUAEEAWwAwAC4AMABdAF0APgA8AC8AdgBpAGQAZQBvAEQAdQByAGEAdABpAG8AbgA+ADwAcwBpAHoAZQAgAHQAbwB0AGEAbABTAGkAegBlAD0AIgAzADIAMwAyAC4AMAAiACAAdwBpAGQAdABoAD0AIgAxADUAMAAuADAAIgAgAGgAZQBpAGcAaAB0AD0AIgAxADUAMAAuADAAIgA+ADwALwBzAGkAegBlAD4APAAvAG0AZQBkAGkAYQA+ADwALwBtAGUAZABpAGEATABpAHMAdAA+ADwALwBDAG8AbgB0AGUAbgB0AE8AYgBqAGUAYwB0AD4APABhAGMAdABpAG8AbgBJAG4AZgBvAD4APABhAHAAcABNAHMAZwA+ADwAbQBlAGQAaQBhAFQAYQBnAE4AYQBtAGUAPgA8AC8AbQBlAGQAaQBhAFQAYQBnAE4AYQBtAGUAPgA8AG0AZQBzAHMAYQBnAGUARQB4AHQAPgA8AC8AbQBlAHMAcwBhAGcAZQBFAHgAdAA+ADwAbQBlAHMAcwBhAGcAZQBBAGMAdABpAG8AbgA+ADwALwBtAGUAcwBzAGEAZwBlAEEAYwB0AGkAbwBuAD4APABhAHAAcABpAGQAPgB3AHgANQBhAGEAMwAzADMANgAwADYANQA1ADAAZABmAGQANQA8AC8AYQBwAHAAaQBkAD4APAAvAGEAcABwAE0AcwBnAD4APABzAGMAZQBuAGUAPgAwADwALwBzAGMAZQBuAGUAPgA8AHQAeQBwAGUAPgAwADwALwB0AHkAcABlAD4APAB1AHIAbAA+ADwALwB1AHIAbAA+ADwAbgBlAHcAVwBvAHIAZABpAG4AZwBLAGUAeQA+ADwALwBuAGUAdwBXAG8AcgBkAGkAbgBnAEsAZQB5AD4APABuAGUAdwB0AHkAcABlAD4AMAA8AC8AbgBlAHcAdAB5AHAAZQA+ADwAaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwALwBpAG4AcwB0AGEAbABsAGUAZABXAG8AcgBkAGkAbgBnAD4APAB1AG4AaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwALwB1AG4AaQBuAHMAdABhAGwAbABlAGQAVwBvAHIAZABpAG4AZwA+ADwALwBhAGMAdABpAG8AbgBJAG4AZgBvAD4APABzAHQAYQB0AEUAeAB0AFMAdAByAD4APAAhAFsAQwBEAEEAVABBAFsARwBoAFEASwBFAG4AZAA0AE4AVwBGAGgATQB6AE0AegBOAGoAQQAyAE4AVABVAHcAWgBHAFoAawBOAFEAPQA9AF0AXQA+ADwALwBzAHQAYQB0AEUAeAB0AFMAdAByAD4APABsAG8AYwBhAHQAaQBvAG4AIABwAG8AaQBDAGwAYQBzAHMAaQBmAHkASQBkAD0AIgAiACAAcABvAGkATgBhAG0AZQA9ACIAIgAgAHAAbwBpAEEAZABkAHIAZQBzAHMAPQAiACIAIABwAG8AaQBDAGwAYQBzAHMAaQBmAHkAVAB5AHAAZQA9ACIAMAAiACAAYwBpAHQAeQA9ACIAIgA+ADwALwBsAG8AYwBhAHQAaQBvAG4APgA8AHAAdQBiAGwAaQBjAFUAcwBlAHIATgBhAG0AZQA+ADwALwBwAHUAYgBsAGkAYwBVAHMAZQByAE4AYQBtAGUAPgA8AHMAdAByAGUAYQBtAHYAaQBkAGUAbwA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwB1AHIAbAA+ADwAcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHQAaAB1AG0AYgB1AHIAbAA+ADwALwBzAHQAcgBlAGEAbQB2AGkAZABlAG8AdABoAHUAbQBiAHUAcgBsAD4APABzAHQAcgBlAGEAbQB2AGkAZABlAG8AdwBlAGIAdQByAGwAPgA8AC8AcwB0AHIAZQBhAG0AdgBpAGQAZQBvAHcAZQBiAHUAcgBsAD4APAAvAHMAdAByAGUAYQBtAHYAaQBkAGUAbwA+ADwALwBUAGkAbQBlAGwAaQBuAGUATwBiAGoAZQBjAHQAPgA="}]} + + #endregion + + var user = WechatClient.GetUser(dwClientid, WechatType.Dazong); + if (user == null) + return; + var client = WechatClient.GetApi(user) as Wechat_Dazong; + if (!user.IsGetCircle) return; + + try + { + var circlelist = new List(); + var jArr = nmHeler.GetArray(jObj, "List"); + for (int i = 0; i < jArr.Count; i++) + { + var item = (JObject)jArr[i]; + //{"PackType":700001,"RecvWxid":"dwB4AGkAZABfAGgAbABnAG8AcgBuADgANAA2AGkAaABwADIAMgA=","List":[{"ID":"-4685137659200794410","Time":1640511323,"Wxid":"dwB1AGoAaQBhAGgAdQBhADAAOAA3ADYA","Nick":"SFHuaDNU","SnsText":""}] + var circleInfo = new CirCleInfoOri(); + circleInfo.username = nmHeler.GetString(item, "Wxid"); + circleInfo.nickname = nmHeler.GetString(item, "Nick"); + circleInfo.createTime = nmHeler.GetIntEx(item, "Time"); + circleInfo.id = (long)item["ID"]; + circleInfo.objectDesc = new ObjectDesc(); + circleInfo.objectDesc.buffer = nmHeler.GetString(item, "SnsText"); + circlelist.Add(circleInfo); + } + user.CircleData = JsonConvert.SerializeObject(circlelist); + } + catch (Exception ex) + { + Debug.Write("获取朋友圈消息异常: " + ex.Message); + } + finally + { + user.IsGetCircle = false; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + private static HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr pClient) + { + //nmCore.NM_Init((int)connId, "C#-864631110"); + nmCore.NM_Init((int)connId, "E-614751150"); + return HandleResult.Ok; + } + + private static string DllPath; + + public override string GetVersion() + { + return Version; + } + + public static uint StartWechat() + { + try + { + var path = string.Empty; + + var WechatWinFile = CsharpHttpHelper.HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + var rst = MessageBox.Show("您的微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + var f = new WechatUpdate(Version); + f.ShowDialog(); + if (!f.IsOk) return 0; + } + else return 0; + } + //path = CsharpHttpHelper.HttpExtend.MapFile("WeChat.exe", $"PCWechat\\" + Version); + path = HttpExtend.MapPath($"PCWechat\\" + Version); + + string szDllPath = System.IO.Directory.GetCurrentDirectory() + "\\Bin\\" + NanMuCore; + var dwPid = NMHelper.NM_CreateWeChatProcess(path, "WeChat.exe", szDllPath, nmHeler.Socket_Port); + return (uint)dwPid; + } + catch (Exception ex) + { + } + return 0; + } + + public override void GetGroupAndFriendInfo(string groupId, string wxid) + { + try + { + GroupInfo group = null; + if (groupId.Contains("@chatroom")) + { + var g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + } + + if (group == null) + { + nmCore.NM_GetWxidInfo((int)User.DwClientId, groupId, wxid); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(5); + do + { + g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + { + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 获取朋友圈 + /// + /// + public override void FindCircles(string circleId, string username) + { + try + { + if (!User.IsGetCircle) + { + nmCore.NM_GetCircles((int)User.DwClientId); + User.IsGetCircle = true; + } + + var result = Task.Factory.StartNew(delegate () + { + Thread.Sleep(1000); + DateTime end_time = DateTime.Now.AddSeconds(30); + do + { + if (!User.IsGetCircle) + { + return User.CircleData; + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleData; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendCirclePraise(string circleId) + { + try + { + nmCore.NM_CircleLink((int)User.DwClientId, circleId, 1); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendCircleComment(string circleId, string content) + { + try + { + nmCore.NM_CircleComment((int)User.DwClientId, circleId, content); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + public override void CreateRoom(string wxidData) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CreateRoom(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCreateRoom; + msg.GroupId = string.Empty; + msg.MemberTotal = 0; + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + + + + } + + + /// + /// 自动授权登录小程序 + /// + /// + public override void AutoAuthMiniAPPLogin(string appid) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvMiniAppCode; + msg.Data = string.Empty; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 发送朋友圈 + /// + /// + public override void SendCircle(string xmlmsg) + { + try + { + nmCore.NM_SendCircle((int)User.DwClientId, xmlmsg); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (!string.IsNullOrWhiteSpace(User.SendCircleId)) + { + return User.SendCircleId; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleReturnId; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + finally + { + User.SendCircleId = string.Empty; + } + } + + + /// + /// 朋友圈上传本地图片,返回上传以后返回的地址 + /// + /// + public override void CircleUpLoadImage(string data) + { + try + { + var path = string.Empty; + Bitmap bitmap = null; + if (data.StartsWith("http", StringComparison.CurrentCultureIgnoreCase)) + { + HttpHelper http = new HttpHelper(); + var item = http.GetItem(data); + item.ResultType = CsharpHttpHelper.Enum.ResultType.Byte; + + using (MemoryStream ms = new MemoryStream(http.GetHtml(item).ResultByte)) + { + using (Image mImage = Image.FromStream(ms, true)) + { + bitmap = new Bitmap(mImage); + path = HttpExtend.MapFile($@"Cache\{DateTime.Now.ToString("MMddhhmmssfff")}.{Common.GetImageExt(bitmap)}"); + bitmap.Save(path); + bitmap.Dispose(); + } + } + } + else + { + bitmap = Common.ConvertBase64ToImage(data); + using (MemoryStream stream = new MemoryStream()) + { + bitmap.Save(stream, ImageFormat.Jpeg); + byte[] data1 = new byte[stream.Length]; + stream.Seek(0, SeekOrigin.Begin); + stream.Read(data1, 0, Convert.ToInt32(stream.Length)); + bitmap = Common.CompressionImage(new MemoryStream(data1), 25); + } + + path = HttpExtend.MapFile($@"Cache\{DateTime.Now.ToString("MMddhhmmssfff")}.{Common.GetImageExt(bitmap)}"); + + bitmap.Save(path); + bitmap.Dispose(); + } + + if (!string.IsNullOrWhiteSpace(path) && File.Exists(path)) + { + var md5 = Common.GetMD5Hash(path); + nmCore.NM_CircleUpLoadImage((int)User.DwClientId, path, md5); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(60); + do + { + if (User.UpLoadImages.ContainsKey(md5)) + { + return User.UpLoadImages[md5]; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleUploadImageUrl; + msg.Data = result; + + socketClient.Send(msg); + } + else + { } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetGroupAndFriendInfo(string groupId, string wxid, bool flush = false) + { + try + { + GroupInfo group = null; + if (groupId.Contains("@chatroom")) + { + var g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + if (flush) + { + g.friends.Clear(); + } + else + { + var u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + } + } + + if (group == null) + { + nmCore.NM_GetWxidInfo((int)User.DwClientId, groupId, wxid); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(5); + do + { + g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + { + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void AgreeAddMe(string text) + { + try + { + nmCore.NM_PassApply((int)User.DwClientId, text); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void CloseWechat(string message) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == User.DwClientId && f.Value.Type == WechatType.Dazong).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"CloseWechatDaZong事件退出,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v, true); + if (!string.IsNullOrWhiteSpace(message)) + PCRobotForm.ErrorMessAction?.Invoke(message); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void DeleteFriend(string wxid) + { + nmCore.NM_DelFriend((int)User.DwClientId, wxid); + } + + public override void EditCotacts(string wxid, string remark) + { + nmCore.NM_SetFriendMark((int)User.DwClientId, wxid, remark); + } + + + + public override void GetGroupsNotInMember() + { + GetContact(); + var result = Task.Factory.StartNew(delegate () + { + Thread.Sleep(4000); + var groups = User.Friends.Where(f => f.wxid.Contains("@chatroom")).ToList(); + return groups == null ? string.Empty : HttpHelper.ObjectToJson(new Dictionary>() { { "data", groups } }); + }).Result; + + if (result == null) + result = HttpHelper.ObjectToJson(new Dictionary>() { { "data", User.Friends.Where(f => f.wxid.Contains("@chatroom")).ToList() } }); + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = result; + + socketClient.Send(msg); + } + + public override void PayTransferConfirm(string data) + { + try + { + var transferid = string.Empty; + var invalidtime = string.Empty; + var wxid = string.Empty; + var dic = HttpExtend.JsonToDictionary(data); + if (dic.ContainsKey("Transferid")) + transferid = dic["Transferid"].ToString(); + if (dic.ContainsKey("Invalidtime")) + invalidtime = dic["Invalidtime"].ToString(); + if (dic.ContainsKey("WxId")) + wxid = dic["WxId"].ToString(); + nmCore.NM_GetMoney((int)User.DwClientId, wxid, transferid, int.Parse(invalidtime)); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendFile(string wxid, string file) + { + try + { + nmCore.NM_SendFileMsg((int)User.DwClientId, NMHelper.NM_SendFile, wxid, file); + Common.SetCache(User.Wxid, wxid, file); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + public override void SendCard(string to_wxid, string card_wxid) + { + try + { + if (card_wxid.Contains("@chatroom")) + nmCore.NM_InviteToGroup((int)User.DwClientId, NMHelper.NM_InviteURL, card_wxid, new string[] { to_wxid }); + else + nmCore.NM_SendCardMsg((int)User.DwClientId, to_wxid, card_wxid); + Common.SetCache(User.Wxid, to_wxid, card_wxid); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendImage(string wxid, string file) + { + try + { + if (file.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + byte[] ImangByte = null; + string extension = Path.GetExtension(file); + extension = string.IsNullOrWhiteSpace(extension) ? ".jpg" : extension; + ImangByte = new System.Net.WebClient().DownloadData(file); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), extension); + if (!File.Exists(path)) + { + File.WriteAllBytes(path, ImangByte); + } + if (File.Exists(path)) + file = path; + } + else + { + if (!File.Exists(file)) + { + if (Common.IsBase64(file)) + { + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), "jpg"); + if (Common.Base64ToFileAndSave(file, path) && File.Exists(path)) + { + file = path; + } + } + else + { } + } + } + nmCore.NM_SendFileMsg((int)User.DwClientId, file.Trim().EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase) ? NMHelper.NM_SendGif : NMHelper.NM_SendPic, wxid, file); + Common.SetCache(User.Wxid, wxid, file); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void CheckUrl(string url) + { + try + { + var socketClient = EasySoc.GetSocket(); + var msg = new CheckUrl(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCheckUrl; + msg.Status = 0; + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendMessage(string wxid, string message) + { + try + { + var json = string.Empty; + message = message.Replace("\r\n", "\n"); + if (Common.isXML(message)) + { + //小程序 + if (Regex.IsMatch(message, @"(?[^<]+)") || Regex.IsMatch(message, @"(.+?)")) + nmCore.NM_SendWeChatApp((int)User.DwClientId, wxid, message, string.Empty);//TODO 小程序未实现 + else + nmCore.NM_SendURLMsg((int)User.DwClientId, wxid, message); + } + else + nmCore.NM_SendTextMsg((int)User.DwClientId, wxid, new string[] { }, message); + Common.SetCache(User.Wxid, wxid, message); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendVideo(string wxid, string path) + { + try + { + SendFile(wxid, path); + Common.SetCache(User.Wxid, wxid, path); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void StateOpt(string wxid, int status) + { + try + { + nmCore.NM_StateOpt((int)User.DwClientId, 2, wxid, status == 1); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetWxidInfo(string wxid) + { + var u = User.Friends.FirstOrDefault(f => f.wxid == wxid); + if (u == null) + { + nmCore.NM_GetWxidInfo((int)User.DwClientId, string.Empty, wxid); + var friend = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + u = User.Friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) return u; + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + var socketClient = EasySoc.GetSocket(); + WechatContact msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = u == null ? string.Empty : HttpHelper.ObjectToJson(u); + + socketClient.Send(msg); + } + + public override void GetFriend(string wxid) + { + nmCore.NM_GetWxidInfo((int)User.DwClientId, string.Empty, wxid); + } + + public override void GetGroupMemer(string groupId) + { + try + { + nmCore.NM_GetGroupMember((int)User.DwClientId, groupId); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 卸载安装 + /// + public static void UnInstall() + { + try + { + HP_Server?.Destroy(); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + public override void GetContact() + { + try + { + //获取好友列表(数据库读取) + nmCore.NM_GetContactList((int)User.DwClientId, int.Parse(HttpExtend.GetTimeStamp()), 6000); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + } +} diff --git a/PCRobot/PCWechat/Wechat_Xiaoxie - 复制.cs b/PCRobot/PCWechat/Wechat_Xiaoxie - 复制.cs new file mode 100644 index 0000000..ae3cd04 --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Xiaoxie - 复制.cs @@ -0,0 +1,3800 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Properties; +using PCRobot.Utils; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; + +namespace PCRobot.PCWechat +{ + ///// + ///// 参考文档: + ///// https://www.showdoc.cc/wxtool + ///// https://www.showdoc.cc/WeApiUltimate + ///// 密码:784615627. + ///// + + public class Wechat_Xiaoxie : BaseApi + { + public delegate void OnEvent(string Name, string Message); + public static OnEvent ClickEvent; + + #region 静态函数 + public static void Install() + { + if (IsInstall) return; + + ClickEvent?.Invoke("开始登录", "正在检测已登录微信,请稍等...."); + try + { + //Thread.Sleep(5000); + //DllPath = HttpExtend.MapFile($"WeChatHelper_{Version}.dll", "Bin"); + m_AcceptCallbackFunc = WxAcceptCallback; + m_RecvCallbackFunc = WxRecvCallback; + m_CloseCallbackFunc = WxCloseCallback; + UseUtf8(); + // 初始化Callback + InitWeChatSocket(m_AcceptCallbackFunc, m_RecvCallbackFunc, m_CloseCallbackFunc); + + DllPath = HttpExtend.MapFile($"WeChatHelper_{Version}.dll", "Bin"); + InitPc(); + } + catch (Exception) + { + + } + finally + { + IsInstall = true; + ClickEvent?.Invoke("登录完成", ""); + } + } + + /// + /// 初始化pc,注入,杀死,删除dll,添加dll + /// + private static void InitPc() + { + //Version == "3.3.0.93"; + //if (Util.IsLinshi()) + // PJFileReplace(); + //else + //{ + // IsReplace = false; + // var isZanYong = DeletePJFile(); + + // KillPc(!isZanYong); + // if (isZanYong) + // { + // isZanYong = DeletePJFile(); + // if (isZanYong) + // throw new Exception("文件处理异常,"); + // } + //} + + KillPc(true); + } + + private static string DllPath; + /// + /// 微信WeChatWin.dll基址 + /// + //private static IntPtr BaseAddress; + + public delegate void AcceptCallbackFunc(uint dwClientId); + public delegate void RecvCallbackFunc(uint dwClientId, IntPtr intPtr, uint dwSize); + public delegate void CloseCallbackFunc(uint dwClientId); + private static AcceptCallbackFunc m_AcceptCallbackFunc; + private static RecvCallbackFunc m_RecvCallbackFunc; + private static CloseCallbackFunc m_CloseCallbackFunc; + + // 引入DLL导出函数 + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool InitWeChatSocket(AcceptCallbackFunc acceptCallback, + RecvCallbackFunc recvCallback, CloseCallbackFunc closeCallback); + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChat(byte[] strDllPath); + //[DllImport("Bin\\WeChatServer.dll")] + //public static extern bool SetLoginWxid(byte[] szWxid); + + //BOOL __stdcall UseUtf8(); + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool UseUtf8(); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool GetUserWeChatVersion(StringBuilder v); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChat2(byte[] dllPath, byte[] wechatPath); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChatMultiOpen(byte[] dllPath, byte[] wechatPath); + + [DllImport("Bin\\WeChatServer.dll", EntryPoint = "SendWeChatData")] + public static extern bool _SendWeChatData(uint dwClienId, byte[] strJsonData); + public bool SendWeChatData(uint dwClienId, string strJsonData) + { + try + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试发送", $"{dwClienId} -> {strJsonData}"); + if (User != null && !string.IsNullOrEmpty(User.Wxid)) + { + var json = HttpExtend.JsonToDictionary(strJsonData); + var type = json["type"].ToString(); + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return false; + switch (msgType) + { + //截取发送消息 - 为是否是辅助输入提供判断 + case MsgType.MT_SEND_TEXTMSG: + case MsgType.MT_SEND_CHATROOM_ATMSG: + case MsgType.MT_SEND_CARDMSG: + case MsgType.MT_SEND_XMLMSG: + case MsgType.MT_SEND_IMGMSG: + case MsgType.MT_SEND_FILEMSG: + case MsgType.MT_SEND_VIDEOMSG: + case MsgType.MT_SEND_GIFMSG: + { + json = json["data"] as Dictionary; + string to_wxid = json["to_wxid"].ToString(); + string message = string.Empty; + if (json.ContainsKey("content")) message = json["content"].ToString(); + else if (json.ContainsKey("card_wxid")) message = json["card_wxid"].ToString(); + else if (json.ContainsKey("xml")) message = json["xml"].ToString(); + else if (json.ContainsKey("file")) message = json["file"].ToString(); + if (!string.IsNullOrEmpty(message)) + Common.SetCache(User.Wxid, to_wxid, message); + } + break; + } + } + return _SendWeChatData(dwClienId, Encoding.UTF8.GetBytes(strJsonData)); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, $"{ex.Message} - {ex.StackTrace}"); + } + return false; + } + + //[DllImport("Bin\\WeChatServer.dll")] + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool DestroyWeChat(); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChatPid(int dwPid, byte[] dllPath); + + /// + /// 卸载安装 + /// + public static void UnInstall() + { + try + { + //DestroyWeChat(); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + // 注入成功回调 + static void WxAcceptCallback(uint dwClientId) + { + LogHelper.GetSingleObj().Info(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "注入成功:" + dwClientId); + Console.WriteLine("注入成功:" + dwClientId); + } + + #region 微信版本基础变量 + + //private const string Version = "2.9.5.41"; + //private const int PcOffSet = 0x1769E00;//2.9.5.41 + //private const string PcMd5 = "194F44DF80553326711A4F576FE7166E";//2.9.5.41 + + private const string Version = "3.3.0.93"; + private const int PcOffSet = 0x1DAEB90;//3.3.0.93 + private const string PcMd5 = "5EE8A5B9D4EE63BE1813632D8A7B2E77";//3.3.0.93 + + //private const string Version = "3.4.0.38"; + //private const int PcOffSet = 0x1DEE968;//3.4.0.38 + //private const string PcMd5 = "AB0916C9949178A786192B188892AE2C";//3.4.0.38 + #endregion + + public override string GetVersion() + { + return Version; + } + + /// + /// 杀死注入 pc + /// + /// + private static void KillPc(bool isInject = false) + { + Process[] MyProcesses = Process.GetProcesses(); + + var path1 = HttpExtend.MapPath("PCWechat"); + var path2 = HttpExtend.MapPath("PCWechat\\" + Version); + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == "WECHAT" && MyProcess.MainModule.FileName.StartsWith(path1)) + { + try + { + //判断微信版本 + if (MyProcess.MainModule.FileName.StartsWith(path2)) + { + var id = MyProcess.Id; + if (isInject) + { + var result = Task.Factory.StartNew(delegate + { + try + { + var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + return false; + } + else + { + LogHelper.GetSingleObj().Info("系统", $"开始注入进程:{id}..."); + uint uin = InjectWeChatPid(id, Encoding.UTF8.GetBytes(DllPath)); + LogHelper.GetSingleObj().Info("系统", $"注入成功:{id},句柄ID:{uin}"); + return true; + } + } + catch (Exception) + { + } + return false; + }).Wait(30000); + if (!result) + { + try + { + LogHelper.GetSingleObj().Info("系统c", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + else + { + try + { + LogHelper.GetSingleObj().Info("主动d", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + } + catch (Exception) + { } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } + + + + public static uint StartWechat(bool isError = false) + { + //InitPc(); + var path = string.Empty; + + var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + if (isError) throw new Exception("易转发客户端微信版本不支持,请登录易转发端手动处理"); + var rst = MessageBox.Show("您的微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + var f = new WechatUpdate(Version); + f.ShowDialog(); + if (!f.IsOk) return 0; + } + else return 0; + } + path = HttpExtend.MapFile("WeChat.exe", $"PCWechat\\" + Version); + + //var ss = SetLoginWxid(Encoding.UTF8.GetBytes("")); + //返回dwClientId + return InjectWeChat2(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + + //return InjectWeChatMultiOpen(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + } + + /// + /// 远程登录微信 + /// + public static List RemoteLoginCodes = new List(); + + /// + /// 是否在获取二维码 + /// + private static string RemoteCache = "get_login_code_cache"; + + private static readonly object Friend_Lock = new object(); + + /// + /// pc微信登录二维码 + /// + /// + public static void LoginQrcode(string ServerMsgID) + { + try + { + RemoteLoginCode result = null; + try + { + StartWechat(true); + } + catch (Exception ex) + { + result = new RemoteLoginCode() { pid = -1, rType = RobotType.客户端微信, b64Md5 = ex.Message }; + } + + if (result == null) + { + result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[RemoteCache]; + if (item != null) + { + cache.Remove(RemoteCache); + var r = item as RemoteLoginCode; + return r; + } + } while (awaitTime >= DateTime.Now); + return null; + }).Result; + } + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = string.Empty; + msg.RobotUsernick = string.Empty; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvLoginCode; + msg.Data = result == null ? string.Empty : JsonConvert.SerializeObject(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 等待登录结果 + /// + public static Dictionary WaitLoginResult = new Dictionary(); + + // 接收消息回调 + static void WxRecvCallback(uint dwClient, IntPtr intPtr, uint dwSize) + { + try + { + byte[] body = new byte[dwSize]; + Marshal.Copy(intPtr, body, 0, body.Length); + var recvData = Encoding.UTF8.GetString(body).Replace("\0", "").Trim();//再转成UTF8 + if (WechatClient.IsDebug) LogHelper.GetSingleObj().Debug("调试收到文本消息", $"{dwClient} -> {recvData}"); + + var dwClientid = dwClient; + Task.Factory.StartNew(delegate () + { + try + { + //Console.WriteLine("收到消息:" + recvData); + var json = HttpExtend.JsonToDictionary(recvData); + var type = json["type"].ToString(); + + var data = json.ContainsKey("data") ? json["data"] as Dictionary : null; + + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return; + + if (PCRobotForm.AnalysisTypes != null && PCRobotForm.AnalysisTypes.Count != 0) + { + if (PCRobotForm.AnalysisTypes.FirstOrDefault(f => f == msgType.ToString().ToUpper()) == null) + return; + } + + switch (msgType) + { + case MsgType.MT_SEND_XMLMSG: + break; + case MsgType.MT_DECRYPT_IMG_MSG: + break; + case MsgType.MT_DEBUG_LOG: + break; + case MsgType.MT_RECV_QRCODE_MSG: + { + //{"data":{"code":"http://weixin.qq.com/x/A98qrQOk3qB6L_fWPtxF","file":"C:\\Users\\????006\\AppData\\Local\\Temp\\qrcF451.tmp","pid":24088},"type":11087} + if (!data.ContainsKey("file")) return; + var file = data["file"].ToString(); + + var reg = Regex.Match(file, @"Temp\\(?<文件名>[a-z0-9A-Z]+.tmp)", RegexOptions.IgnoreCase); + if (reg.Success) + { + var codeFile = HttpExtend.MapFile($"{reg.Groups["文件名"].Value}", Path.GetTempPath()); + if (File.Exists(codeFile)) + { + var pid = int.Parse(data["pid"].ToString()); + var codeFilePng = Path.ChangeExtension(codeFile, "png"); + try + { + if (File.Exists(codeFilePng)) + File.Delete(codeFilePng); + File.Move(codeFile, codeFilePng); + if (File.Exists(codeFilePng)) + { + var cfBase64 = Common.ConvertImageToBase64(Image.FromFile(codeFilePng)); + + var codeInfo = new RemoteLoginCode() { pid = pid, cImgB64 = cfBase64, b64Md5 = HttpHelper.ToMD5(cfBase64), rType = RobotType.客户端微信, t = HttpExtend.GetTimeStamp(DateTime.Now) }; + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[RemoteCache]; + cache.Insert(RemoteCache, codeInfo, null, DateTime.Now.AddSeconds(3), Cache.NoSlidingExpiration); + + RemoteLoginCodes.Add(codeInfo); + } + } + catch (Exception) + { } + } + } + } + break; + case MsgType.MT_USER_LOGIN://登陆消息 + { + var wxid = data["wxid"].ToString(); + var user = WechatClient.GetUser(wxid, dwClientid, WechatType.Xiaoxie); + user.Nickname = data["nickname"].ToString(); + user.HeaderUrl = data["avatar"].ToString(); + user.DBFile = data["wx_user_dir"].ToString(); + user.Pid = int.Parse(data["pid"].ToString()); + user.Phone = data["phone"].ToString(); + user.Uin = GetUin(user.Pid); + + WechatClient.OnRefUserEvent(user, WaitLoginResult); + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试登录", $"{wxid} - {user}"); + } + break; + case MsgType.MT_USER_LOGOUT: + { + var wxid = data["wxid"].ToString(); + var user = WechatClient.Users.FirstOrDefault(f => f.Key == wxid).Value; + if (user != null) + { + LogHelper.GetSingleObj().Info("系统", $"LogOut事件退出,Uin:{user.Uin},微信:{user.Nickname}({wxid})"); + WechatClient.RemoveUser(user); + } + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试注销", $"{wxid} - {user}"); + } + break; + case MsgType.MT_SQL_QUERY: + break; + case MsgType.MT_DATA_OWNER_MSG: + break; + case MsgType.MT_DATA_WXID_MSG: + { + //{"data":{"account":"MOKA_1314_","avatar":"http://wx.qlogo.cn/mmhead/ver_1/UKuQPgzLzEY0UPqTgmqpSibLmx1BMibAlwJxOp4t8QksClGJP8tLHxUiaBDAax1Vf0Eiae6wKBIoT3ibAgOYTuuWiaVDiaiayiaaIZF46LcE5aBvTtSQ/132","city":"Chengdu","country":"CN","nickname":"进销存","province":"Sichuan","remark":"","sex":2,"wxid":"wxid_va4xpj22"},"type":11029} + + lock (Friend_Lock) + { + var wxid = data["wxid"]?.ToString(); + if (Common.IsGzh(wxid, WechatClient.IsGzh)) return; + + var f = new FriendInfo(); + + f.account = data["account"]?.ToString(); + f.wxid = wxid; + f.nickname = data["nickname"]?.ToString(); + f.remark = data["remark"]?.ToString(); + f.avatar = data["avatar"]?.ToString(); + f.city = data["city"]?.ToString(); + f.country = data["country"]?.ToString(); + f.province = data["province"]?.ToString(); + f.sex = int.Parse(data["sex"]?.ToString()); + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend != null) + if (!user.Friends.TryTake(out friend)) return; + user.Friends.Add(f); + } + + //var socketClient = EasySoc.GetSocket(); + //var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + //if (user != null) + //{ + // WechatContactList msg = new WechatContactList(); + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + + // msg.Cmd = PCRobotCMD.rcvContactList; + // msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", new List() { f } } }); + + // socketClient.Send(msg); + //} + } + break; + case MsgType.MT_DATA_FRIENDS_MSG: + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client = WechatClient.GetApi(user) as Wechat_Xiaoxie; + if (!user.IsGetFriend) return; + try + { + var _data = json.ContainsKey("data") ? json["data"] as ArrayList : null; + if (_data == null) return; + + for (int i = 0; i < _data.Count; i++) + { + var item = _data[i] as Dictionary; + + var wxid = item["wxid"]?.ToString(); + + if (Common.IsGzh(wxid, WechatClient.IsGzh)) continue; + + var f = new FriendInfo(); + f.wxid = wxid; + f.account = item["account"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.sex = int.Parse(item["sex"]?.ToString()); + f.city = item["city"]?.ToString(); + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + user.Friends.Add(f); + } + } + catch (Exception ex) + { } + finally + { + user.IsGetFriend = false; + } + } + break; + case MsgType.MT_DATA_CHATROOMS_MSG: + { + if (data == null) + { + lock (Friend_Lock) + { + //{"data":[{"avatar":"http://wx.qlogo.cn/mmcrhead/iahdQicCC5VBRq5vMm7FxlfPct57WiadZ0NEnMUeicvXyS0fh73Hibw0QkkDMw9RQMETbWENFia9NQlmpibkH0bKsOothztfu8waTFy/0","is_manager":0,"manager_wxid":"wxid_yeh4ssxdjpqv12","member_list":["wxid_yeh4ssxdjpqv12","wujiahua0876","wxid_aiwyq8o6iqja12","wxid_lzssz365bwl222"],"nickname":"成都测试群","total_member":4,"wxid":"24444455370@chatroom"}],"type":11031} + + + var _data = json.ContainsKey("data") ? json["data"] as ArrayList : null; + if (_data == null) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + for (int i = 0; i < _data.Count; i++) + { + Thread.Sleep(1000); + //{"avatar":"http://wx.qlogo.cn/mmcrhead/00GYaClAoOpPmXm2NY7u8dZ0mXndbaJvesrlr88KhsUXaPTGvDE8Rt5wpSv9qtHLZJSIHLNBbxEhwFBnbV9FmE6O2fAmlMW1/0","is_manager":0,"manager_wxid":"wzm881101","member_list":["wzmdd2562","wxid_axvwtp4221","huih2861","a30432165487","wangs381015","wxid_vy1kfbt22","wiujihcj056"],"nickname":"吃卤蛋不吐卤蛋壳群","total_member":7,"wxid":"6975286487@chatroom"} + + var item = _data[i] as Dictionary; + var f = new FriendInfo(); + + f.avatar = item["avatar"]?.ToString(); + f.wxid = item["wxid"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.remark = item["nickname"]?.ToString(); + + f.manager_wxid = item["manager_wxid"]?.ToString(); + f.is_manager = int.Parse(item["is_manager"]?.ToString()); + f.member_list = string.Join(",", (string[])(item["member_list"] as ArrayList).ToArray(typeof(string))); + + var group = user.Groups.FirstOrDefault(z => z.wxid == f.wxid); + if (group == null) + { + //群不存在,去获取群成员信息 + var _json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = f.wxid } }); + _SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + + group = new GroupInfo() { wxid = f.wxid, nickname = f.nickname, avatar = f.avatar, total_member = f.member_list.Length, friends = new List() }; + user.Groups.Add(group); + } + else + group.total_member = f.member_list.Length; + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + user.Friends.Add(f); + } + } + } + } + break; + case MsgType.MT_DATA_CHATROOM_MEMBERS_MSG: + { + lock (Friend_Lock) + { + var group_wxid = data["group_wxid"].ToString(); + var total = data["total"].ToString(); + var member_list = data["member_list"] as ArrayList; + if (member_list == null) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + var group = user.Groups.FirstOrDefault(z => z.wxid == group_wxid); + if (group == null) + { + group = new GroupInfo() { wxid = group_wxid, total_member = member_list.Count, friends = new List() }; + user.Groups.Add(group); + } + else + group.total_member = member_list.Count; + + for (int i = 0; i < member_list.Count; i++) + { + //{"account":"","avatar":"http://wx.qlogo.cn/mmhead/ver_1/klibauQfLYtmfniaYAzsV9l6V4cSHmdDhniaTmJ6aGo0z035JTkB5QWrOUbAPnJnP4YXTMuKKmwNBMNv2Fbj5ia9icNicYeXGXbbsRiagGFKryASro/132","city":"","country":"","nickname":"陈建","province":"","remark":"","sex":0,"wxid":"wxid_e1j30jf2k5zdk022"} + + var item = member_list[i] as Dictionary; + + var f = new FriendInfo(); + f.account = item["account"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.city = item["city"]?.ToString(); + f.country = item["country"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.province = item["province"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = int.Parse(item["sex"]?.ToString()); + f.wxid = item["wxid"]?.ToString(); + + var friend = group.friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + group.friends.Add(f); + } + } + + #region xx + + //List> nmss = new List>(); + //List mis = new List(); + //var count = 20; + //var rem = member_list.Count % count; + //var num = member_list.Count / count; + + //for (int i = 0; i < member_list.Count; i++) + //{ + // var item = member_list[i] as Dictionary; + + // var account = item["account"]?.ToString(); + // var avatar = item["avatar"]?.ToString(); + // var city = item["city"]?.ToString(); + // var country = item["country"]?.ToString(); + // var nickname = item["nickname"]?.ToString(); + // var province = item["province"]?.ToString(); + // var remark = item["remark"]?.ToString(); + // var sex = item["sex"]?.ToString(); + // var wxid = item["wxid"]?.ToString(); + + // nmWxidInfo MemberInfo = new nmWxidInfo(); + // MemberInfo.Wxid = wxid; + // MemberInfo.WxNo = account; + // MemberInfo.Nick = nickname; + // MemberInfo.Mark = remark; + // MemberInfo.HeadIMG = avatar; + // mis.Add(MemberInfo); + // if (mis.Count >= count) + // { + // nmss.Add(mis); + // mis = new List(); + // } + // else if (nmss.Count == num && mis.Count == rem) + // { + // nmss.Add(mis); + // } + + //} + //var socketClient = EasySoc.GetSocket(); + //var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + //if (user == null) return; + //foreach (var item in nmss) + //{ + // WechatGroupMember msg = new WechatGroupMember(); + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + + // msg.Cmd = PCRobotCMD.rcvGroupMember; + + // nmGroupInfo group = new nmGroupInfo(); + // group.Count = int.Parse(total); + // group.GroupID = group_wxid; + // group.List = item; + // msg.Message = HttpHelper.ObjectToJson(new Dictionary() { { "data", group } }); + + // socketClient.Send(msg); + // Thread.Sleep(5); + //} + #endregion + + } + break; + case MsgType.MT_DATA_PUBLICS_MSG: + { + + } + break; + case MsgType.MT_UPDATE_WXID_MSG: + { + + } + break; + case MsgType.MT_UPDATE_ROOM_MEMBER_MSG: + { + + + } + break; + case MsgType.MT_RECV_LINK_MSG: + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试收到链接", $"{dwClientid} -> {recvData}"); + + var is_pc = data["is_pc"]?.ToString(); + var from_wxid = data["from_wxid"].ToString(); + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + var wx_sub_type = int.Parse(data["wx_sub_type"].ToString()); + + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + //if (!string.IsNullOrWhiteSpace(raw_msg)) + //{ + // var reg = Regex.Match(raw_msg, "(?<链接>.*)"); + // if (reg.Success) + // { + // raw_msg = reg.Groups["链接"].Value; + // } + //} + + var socketClient = EasySoc.GetSocket(); + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (room_wxid.Contains("@chatroom")) + wmsg.FromGroupid = room_wxid; + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = ass.fromNick; + wmsg.FromMessage = raw_msg; + + socketClient.Send(wmsg); + } + break; + case MsgType.MT_RECV_TEXT_MSG: + { + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试收到文本消息", $"{dwClientid} -> {recvData}"); + + var at_user_list = data["at_user_list"] as ArrayList; + var from_wxid = data["from_wxid"].ToString(); + var msg = data["msg"].ToString(); + + var msg_temp = string.Copy(msg); + #region 替换@里面的用户昵称 + if (at_user_list != null && at_user_list.Count != 0) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client_temp = WechatClient.GetApi(user) as Wechat_Xiaoxie; + foreach (string username in at_user_list) + { + var firent = user.Friends.FirstOrDefault(f => f.wxid == username); + if (firent == null) + { + client_temp.GetWxidInfo(username); + Thread.Sleep(1000); + firent = user.Friends.FirstOrDefault(f => f.wxid == username); + } + if (firent != null) + msg_temp = msg_temp.Replace("@" + firent.nickname + " ", "{$@}"); + } + } + #endregion + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + var socketClient = EasySoc.GetSocket(); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, msg_temp)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + msg_temp); + return; + } + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (room_wxid.Contains("@chatroom") || room_wxid.Contains("@im.chatroom")) + { + wmsg.FromGroupid = room_wxid; + wmsg.FromUsername = from_wxid; + wmsg.FromUsernick = from_wxid == ass.robotName ? ass.robotNick : string.Empty; + } + else + { + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = ass.fromNick; + } + wmsg.FromMessage = msg; + + socketClient.Send(wmsg); + + //从网络上下载群成员(刷新) + //var _json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_UPDATE_ROOM_MEMBER_MSG, data = new { room_wxid = "24444455370@chatroom" } }); + //_SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + //获取群成员列表 + //var _json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = "24444455370@chatroom" } }); + //_SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + } + break; + case MsgType.MT_ZOMBIE_CHECK_MSG: + { + //if (data == null) return; + //if (data.ContainsKey("errcode")) + //{ + // var status = int.Parse(data["status"].ToString()); + // var wxid = data["wxid"].ToString(); + + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // var firend = user.Friends.FirstOrDefault(f => f.wxid == wxid); + // if (firend == null) return; + // firend.is_zombie = status; + //} + } + break; + case MsgType.MT_SEND_CARD_XMLMSG: + { + + } + break; + case MsgType.MT_RECV_PICTURE_MSG: + case MsgType.MT_RECV_VOICE_MSG: + case MsgType.MT_RECV_FRIEND_MSG: + case MsgType.MT_RECV_CARD_MSG: + case MsgType.MT_RECV_VIDEO_MSG: + case MsgType.MT_RECV_EMOJI_MSG: + case MsgType.MT_RECV_LOCATION_MSG: + case MsgType.MT_RECV_FILE_MSG: + { + var from_wxid = data["from_wxid"].ToString(); + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + var socketClient = EasySoc.GetSocket(); + + if (wx_type == 3 || wx_type == 34 || wx_type == 43 || wx_type == 49)//图片、语音、视频、文件 + { + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client = WechatClient.GetApi(user); + + WechatReceiveMsg msg = new WechatReceiveMsg(); + msg.Cmd = PCRobotCMD.rcvFile; + msg.IsSend = false; + if (wx_type == 3)//图片 + { + //var image_thumb = data["image_thumb"].ToString(); + var image = data["image"].ToString(); + + #region 等待下载 + long size = -1L; + var reg = Regex.Match(raw_msg, @"hdlength=\""(\d+?)\"""); + if (reg.Success) + size = long.Parse(reg.Groups[1].Value); + else + { + reg = Regex.Match(raw_msg, @"\slength=\""(\d+?)\"""); + if (reg.Success) + size = long.Parse(reg.Groups[1].Value); + else + { } + } + var waitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + var size_temp = new FileInfo(image).Length; + if (File.Exists(image) && size == size_temp) + break; + } while (waitTime >= DateTime.Now); + #endregion + + msg.Cmd = PCRobotCMD.rcvImg; + + msg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + + var path = Common.CacheFilePath(ass.robotName, ass.fromName, "IMAGE", data["msgid"].ToString(), "jpg"); + + #region 等待图片解密 + //int i = 0; + //do + //{ + // i++; + // client.DecryptImage(image, path); + // var failureTime = DateTime.Now.AddSeconds(2); + // do + // { + // Thread.Sleep(200); + // if (File.Exists(path)) break; + // } while (failureTime >= DateTime.Now); + // if (File.Exists(path)) + // break; + //} while (4 >= i); + + DecodeImage(image, byte.Parse(data["xor_key"].ToString()), path); + if (!string.IsNullOrWhiteSpace(path) && File.Exists(path)) + { } + else + path = image; + #endregion + + msg.FromMessage = $"[图片={path}]"; + msg.FromMessageType = WechatMsgType.图片; + msg.FileCDNXML = raw_msg; + } + else if (wx_type == 34)//语音 + { + //msg.FromMessage = string.Empty;//$"[语音={FilePath}]";//TODO 语音文件 + //msg.FromMessageType = WechatMsgType.语音; + return; + } + else if (wx_type == 43)//视频 + { + //var video = data["video"].ToString(); + //msg.FromMessage = $"[视频={video}]"; + //msg.FromMessageType = WechatMsgType.视频; + return; + } + else if (wx_type == 49)//文件 + { + //msg.FromMessage = string.Empty;//$"[文件={FilePath}]";//TODO 文件 + //msg.FromMessageType = WechatMsgType.文件; + return; + } + + msg.IsSend = false; + msg.RobotUsername = ass.robotName; + msg.RobotUsernick = ass.robotNick; + msg.RobotType = RobotType.客户端微信; + + if (room_wxid.Contains("@chatroom")) + msg.FromGroupid = room_wxid; + + msg.FromUsername = from_wxid; + //msg.FromUsernick = string.Empty;//TODO 昵称没有获取 + + socketClient.Send(msg); + } + else if (wx_type == 37)//接收到好友申请请求 + { + WechatApplyFriend wXApply = new WechatApplyFriend(); + wXApply.Cmd = PCRobotCMD.applyFriend; + wXApply.RobotUsername = to_wxid; + wXApply.RobotUsernick = WechatClient.GetUser(to_wxid)?.Nickname; + wXApply.RobotType = RobotType.客户端微信; + + var reg = Regex.Match(raw_msg, @"content=""(?<申请文本>[^""]*?)"""); + if (reg.Success) + wXApply.Message = reg.Groups["申请文本"].Value; + + reg = Regex.Match(raw_msg, @"sourceusername=""(?<账号>[^""]*?)"" sourcenickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + { + wXApply.OldFriendWxid = reg.Groups["账号"].Value; + wXApply.OldFriendNick = reg.Groups["昵称"].Value; + } + reg = Regex.Match(raw_msg, @"fromusername=""(?<账号>[^""]*?)"""); + if (reg.Success) + { + if (!string.IsNullOrWhiteSpace(reg.Groups["账号"].Value)) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + else + { + reg = Regex.Match(raw_msg, @"alias=""(?<账号>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + } + } + reg = Regex.Match(raw_msg, @"fromnickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendNick = reg.Groups["昵称"].Value; + + wXApply.Token = raw_msg;//TODO 这里好像要获取raw_msg 中 v1的值 + + socketClient.Send(wXApply); + } + //名片 + else if (wx_type == 42) { } + //接收表情 + else if (wx_type == 47) { } + //接收位置消息 + else if (wx_type == 48) { } + } + break; + case MsgType.MT_RECV_WCPAY_MSG: + { + var from_wxid = data["from_wxid"].ToString(); + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = data["wx_type"].ToString(); + var wx_sub_type = data["wx_sub_type"].ToString(); + + var socketClient = EasySoc.GetSocket(); + if (raw_msg.IndexOf("微信转账") != -1 && raw_msg.IndexOf("收到转账") != -1) + { + string State = Common.StringMid(raw_msg, "", ""); + string Transid = Common.StringMid(raw_msg, "transferid>"); + int dwTime = 0; + int.TryParse(Common.StringMid(raw_msg, ""), out dwTime); + if (State == "1" && Transid != string.Empty) + { + WechatReicevePay reicevePay = new WechatReicevePay(); + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + reicevePay.RobotUsername = user.Wxid; + reicevePay.RobotUsernick = user.Nickname; + reicevePay.RobotType = RobotType.客户端微信; + reicevePay.FromUsername = from_wxid; + reicevePay.FromUsernick = string.Empty;//TODO 没有获取昵称 + reicevePay.Cmd = PCRobotCMD.receivePay; + reicevePay.Invalidtime = dwTime.ToString(); + reicevePay.Transferid = Transid; + var reg = Regex.Match(raw_msg, "收到转账(?<金额>.+)元"); + if (reg.Success) + reicevePay.Money = double.Parse(reg.Groups["金额"].Value); + if (reicevePay.RobotUsernick == null) reicevePay.RobotUsernick = string.Empty; + socketClient.Send(reicevePay); + return; + } + } + } + break; + case MsgType.MT_RECV_SYSTEM_MSG: + { + //{"data":{"from_wxid":"wxid_lzssz365bwl222","is_pc":0,"msgid":"9071106463111673540","raw_msg":"\"先森吳\"邀请\"查优惠小助手(语馨)\"加入了群聊","room_wxid":"24444455370@chatroom","timestamp":1585398781,"to_wxid":"24444455370@chatroom","wx_type":10000},"type":11058} + + if (data != null && data.ContainsKey("raw_msg")) + { + var socketClient = EasySoc.GetSocket(); + var raw_msg = data["raw_msg"].ToString(); + var room_wxid = data["room_wxid"].ToString(); + var from_wxid = data["from_wxid"].ToString(); + + //新人入群 + if (!string.IsNullOrWhiteSpace(room_wxid) && room_wxid.Contains("@chatroom")) + { + //var reg1 = Regex.Match(raw_msg, @"""(?<邀请人昵称>.*)""邀请""(?<新人昵称>.*)""加入了群聊"); + //var reg2 = Regex.Match(raw_msg, @"你邀请""(?<新人昵称>.*)""加入了群聊"); + //var reg3 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描""(?<邀请人昵称>.*)""分享的二维码加入群聊"); + //var reg4 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描你分享的二维码加入群聊"); + + //if (reg1.Success || reg2.Success || reg3.Success || reg4.Success) + //{ + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // if (user == null) + // return; + // WechatNewMemer newMember = new WechatNewMemer(); + // newMember.Cmd = PCRobotCMD.newMember; + // newMember.RobotType = RobotType.客户端微信; + // newMember.RobotUsername = user.Wxid; + // newMember.RobotUsernick = user.Nickname; + + // if (reg1.Success) + // { + // newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg1.Groups["新人昵称"].Value; + // } + // else if (reg2.Success) + // { + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg2.Groups["新人昵称"].Value; + // } + // else if (reg3.Success) + // { + // newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg3.Groups["新人昵称"].Value; + // } + // else if (reg4.Success) + // { + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg4.Groups["新人昵称"].Value; + // } + + // if (room_wxid.Contains("@chatroom")) + // { + // newMember.GroupId = room_wxid; + // newMember.GroupNick = string.Empty; + // } + // socketClient.Send(newMember); + //} + } + else//新增好友 + { + //#region 添加好友成功 + //var reg1 = Regex.Match(raw_msg, "^你已添加了(.*?),现在可以开始聊天了。$"); + //var reg2 = Regex.Match(raw_msg, "^(.*?)刚刚把你添加到通讯录,现在可以开始聊天了。$"); + //if (reg1.Success || reg2.Success) + //{ + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // if (user == null) + // return; + // WechatNewFriend msg = new WechatNewFriend(); + // msg.Cmd = PCRobotCMD.newfriend; + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + // msg.FromUserName = from_wxid; + // msg.FromUserNick = reg1.Success ? reg1.Groups[1].Value : reg2.Groups[1].Value; + // socketClient.Send(msg); + //} + //#endregion + + #region 检测僵尸粉 + //{"data":{"from_wxid":"wujiahua0876","is_pc":0,"msgid":"3624674612069828076","raw_msg":"先森吳开启了朋友验证,你还不是他(她)朋友。请先发送朋友验证请求,对方验证通过后,才能聊天。发送朋友验证","room_wxid":"","timestamp":1585125257,"to_wxid":"wxid_lzssz365bwl222","wx_type":10000},"type":11058} + + //{"data":{"from_wxid":"wxid_89qxkbyaxrok22","is_pc":0,"msgid":"7401397021380323657","raw_msg":"消息已发出,但被对方拒收了。","room_wxid":"","timestamp":1603436524,"to_wxid":"wujiahua0876","wx_type":10000},"type":11058} + if (raw_msg.Contains("开启了朋友验证") || raw_msg.Contains("但被对方拒收了"))//这里说明是僵尸粉 + { + LogHelper.GetSingleObj().Debug("调试清粉", $"{JsonConvert.SerializeObject(data)}"); + + var wxid = data["from_wxid"].ToString(); + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + var firend = user.Friends.FirstOrDefault(f => f.wxid == wxid); + if (firend == null) return; + if (raw_msg.Contains("但被对方拒收了")) + firend.is_zombie = 2;//拉黑了 + else + firend.is_zombie = 1;//单向好友 + + //var socketClient = EasySoc.GetSocket(); + WechatContact msg = new WechatContact(); + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", new List() { firend } } }); + + socketClient.Send(msg); + } + //{"data":{"from_wxid":"wxid_2ufntuf4purl22","is_pc":0,"msgid":"1580248074267233434","raw_msg":"由于名片类型或场景原因,暂不支持转发该名片。","room_wxid":"","timestamp":1585125880,"to_wxid":"wxid_lzssz365bwl222","wx_type":10000},"type":11058} + else if (raw_msg.Contains("暂不支持转发该名片"))//这里说明是好友 + { + LogHelper.GetSingleObj().Debug("调试清粉_", $"{JsonConvert.SerializeObject(data)}"); + + var wxid = data["from_wxid"].ToString(); + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + var firend = user.Friends.FirstOrDefault(f => f.wxid == wxid); + if (firend == null) return; + firend.is_zombie = 0; + } + else + { + + } + #endregion + } + } + } + break; + case MsgType.MT_RECV_REVOKE_MSG: + { + //私聊用户撤回消息 + //{"data":{"from_wxid":"wujiahua0876","is_pc":0,"msgid":"3768878978337666344","raw_msg":"\n\t\n\t\twujiahua0876\n\t\t1097101643\n\t\t5572791720720581005\n\t\t\n\t\n\n","room_wxid":"","timestamp":1586758499,"to_wxid":"wxid_lzssz365bwl222","wx_type":10002},"type":11059} + //私聊用户机器人自己撤回消息 + //{"data":{"from_wxid":"wxid_lzssz365bwl222","is_pc":0,"msgid":"1526645333654331593","raw_msg":"wujiahua087617163236505998900618590839539","room_wxid":"","timestamp":1586758971,"to_wxid":"wujiahua0876","wx_type":10002},"type":11059} + + var from_wxid = string.Empty; + if (data.ContainsKey("from_wxid")) + from_wxid = data["from_wxid"]?.ToString(); + var raw_msg = string.Empty; + if (data.ContainsKey("raw_msg")) + { + raw_msg = data["raw_msg"]?.ToString(); + } + var to_wxid = string.Empty; + if (data.ContainsKey("to_wxid")) + to_wxid = data["to_wxid"]?.ToString(); + + } + break; + case MsgType.MT_RECV_OTHER_MSG: + break; + case MsgType.MT_RECV_OTHER_APP_MSG: + case MsgType.MT_RECV_MINIAPP_MSG: + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试收到小程序消息", $"{dwClientid} -> {recvData}"); + if (data == null) return; + + var wx_type = data["wx_type"]?.ToString();//微信原始类型,值为 49 + if (wx_type == "49") + { + var wx_sub_type = data["wx_sub_type"]?.ToString();//微信原始应用子类型,值为 36 + if (wx_sub_type == "1" || wx_sub_type == "36" || wx_sub_type == "33" || wx_sub_type == "3" || wx_sub_type == "19") + { + var from_wxid = data["from_wxid"]?.ToString();//发送者的wxid + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var is_pc = data["is_pc"]?.ToString(); + var raw_msg = data["raw_msg"]?.ToString(); + var msgid = data["msgid"]?.ToString();// 接收到的消息id + var room_wxid = data["room_wxid"]?.ToString();//群聊的wxid + var to_wxid = data["to_wxid"]?.ToString();//接收者的wxid + + var socketClient = EasySoc.GetSocket(); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + //if (!string.IsNullOrWhiteSpace(raw_msg)) + //{ + // var reg = Regex.Match(raw_msg, @"(?<链接>.*)"); + // if (reg.Success) + // raw_msg = reg.Groups["链接"].Value; + //} + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (room_wxid.Contains("@chatroom")) + { + wmsg.FromGroupid = room_wxid; + wmsg.FromUsername = from_wxid; + wmsg.FromUsernick = from_wxid == ass.robotName ? ass.robotNick : string.Empty; + } + else + { + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = ass.fromNick; + } + wmsg.FromMessage = raw_msg; + + socketClient.Send(wmsg); + } + } + } + break; + case MsgType.MT_CHECK_URL_STATUS_MSG: + { + //if (CheckUrlCache.Count > 500) CheckUrlCache.Clear(); + //{"data":{"status":-2005,"url":"https://ycs9d.kuaizhan.com/?id=07E4060844959"},"type":11123} + if (data["status"] != null) + { + var url = data["url"]?.ToString(); + if (!string.IsNullOrWhiteSpace(url)) + { + //CheckUrlCache.Add(url.Trim(), int.Parse(data["status"].ToString())); + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[url.Trim()]; + cache.Insert(url.Trim(), int.Parse(data["status"].ToString()), null, DateTime.Now.AddSeconds(8), Cache.NoSlidingExpiration); + } + } + } + break; + case MsgType.MT_ROOM_ADD_MEMBER_NOTIFY_MSG://群成员新增通知 + { + //{"data":{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":[{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/MpicosfFj1KMvlSPoxWHjUfT2KGqJvEKrDkDCUiaQp4ryYkv3NMdsYofXUVvgalGx0ylia2swn2MMNWwiaWWEUl4QvQayM2Y28pAaxShUZUH5ms/132","invite_by":"wujiahua0876","nickname":"A083赚钱鸭💯(葫芦娃)","wxid":"wxid_5fn1vpyjpfj022"}],"nickname":"111111","room_wxid":"24466267291@chatroom","total_member":5},"type":11098} + + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + var avatar = data["avatar"].ToString();//头像 + var is_manager = data["is_manager"].ToString();// + var manager_wxid = data["manager_wxid"].ToString();//管理账号 + var room_nick = data["nickname"].ToString();//群昵称 + var room_wxid = data["room_wxid"].ToString();//群账号 + var total_member = int.Parse(data["total_member"].ToString());//群人数 + + var member_list = data["member_list"] as ArrayList; + if (member_list != null && member_list.Count != 0) + { + var member = member_list[0] as Dictionary; + var avatar_user = member["avatar"].ToString();//头像 + var invite_by = member["invite_by"].ToString();//邀请者wxid + var nickname = member["nickname"].ToString();//新用户昵称 + var wxid = member["wxid"].ToString();//新用户账号 + + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember; + newMember.RobotType = RobotType.客户端微信; + newMember.RobotUsername = user.Wxid; + newMember.RobotUsernick = user.Nickname; + + //if (reg1.Success) + //{ + // newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg1.Groups["新人昵称"].Value; + //} + //else if (reg2.Success) + //{ + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg2.Groups["新人昵称"].Value; + //} + //else if (reg3.Success) + //{ + // newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg3.Groups["新人昵称"].Value; + //} + //else if (reg4.Success) + //{ + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg4.Groups["新人昵称"].Value; + //} + + + newMember.SourceNick = string.Empty; + newMember.SourceName = (string.IsNullOrWhiteSpace(invite_by) || invite_by == user.Wxid) ? string.Empty : invite_by; + newMember.MemberNick = nickname; + newMember.MemberName = wxid; + newMember.GroupId = room_wxid; + newMember.GroupNick = room_nick; + newMember.TotalMember = total_member; + + socketClient.Send(newMember); + } + } + break; + case MsgType.MT_ROOM_DEL_MEMBER_NOTIFY_MSG://群成员删除/退出通知 + { + + } + break; + case MsgType.MT_ROOM_CREATE_NOTIFY_MSG://通过接口创建群聊的通知 + { + //{"data":{"avatar":"http://wx.qlogo.cn/mmcrhead/MvMkWKHbPUVricNicF781PXeuPMW2vHEywf6lkuMfLgHN4IlRAyPiaDX8AG9d9XEa1ibiaMXBr83ibDVmgCT70qkHXPN9SFn5iaHC7y/0","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":[{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/CVGILsl6SCMBjjCuyxUOZXNRgeiaPx4EwT1WMqCDz9qp3XcuzuVm3SHuPuial3wOMVUSbbJujBtUqPkB3Uz1ruTVzibqZ74FTnBKibNCq67qBcE/132","invite_by":"wxid_tnizkijej5uq22","nickname":"小张晚安","wxid":"wxid_uwbxwbt4ihjd22"},{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/cstPo5zCEb794wfD44BbnoQicfDOeOzkB3BficFYticVmQy7umm4SArThiaia6f6ZJFriaewskJ3foyuxrEVYic7NicwXQ/132","invite_by":"wxid_tnizkijej5uq22","nickname":"先森吳","wxid":"wujiahua0876"},{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/tbfVwxp5B5WkAx7KxDCTia8kzWgMIj3bqA1QaoHxXvQTwS5aRw6h9WjTQMWBhD6fkt4XjUxURDDGF5aBek8xSnY4kqPIQ9T4oweMyaKLSwnM/132","invite_by":"","nickname":"Coco","wxid":"wxid_tnizkijej5uq22"}],"nickname":"","room_wxid":"24652183014@chatroom","total_member":3},"type":11100} + + if (data == null) return; + + var wxids = new List(); + var member_list = data["member_list"] as ArrayList; + for (int i = 0; i < member_list.Count; i++) + { + //{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/CVGILsl6SCMBjjCuyxUOZXNRgeiaPx4EwT1WMqCDz9qp3XcuzuVm3SHuPuial3wOMVUSbbJujBtUqPkB3Uz1ruTVzibqZ74FTnBKibNCq67qBcE/132","invite_by":"wxid_tnizkijej5uq22","nickname":"小安","wxid":"wxid_uwbxwbt4ihjd22"} + + var m = member_list[i] as Dictionary; + if (m == null) continue; + wxids.Add(m["wxid"]?.ToString()); + } + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client = WechatClient.GetApi(user); + wxids.Sort(StringComparer.CurrentCulture); + + var md5Text = Common.GetMD5(string.Join(",", wxids)); + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[md5Text]; + cache.Insert(md5Text, data["room_wxid"].ToString(), null, DateTime.Now.AddSeconds(8), Cache.NoSlidingExpiration); + } + break; + case MsgType.MT_ROOM_DEL_NOTIFY_MSG://群成员删除通知 + { + + } + break; + case MsgType.MT_CONTACT_ADD_NOITFY_MSG://好友新增通知 + { + //{"data":{"account":"dx21101","avatar":"http://wx.qlogo.cn/mmhead/ver_1/we0fG4Y8r0NjN7GUSHFXCu0qicqZf2KKHBeRKIByBNAvvJ8KcgeaomwSju0AqUicJztS6oiaEzDVJiblnZmrJQTibDdPyk7fwzwPbS5JxwibS6POI/0","city":"","country":"","nickname":"秒单客-小张","remark":"","sex":1,"wxid":"wxid_g9r17s6hdb6w22"},"type":11102} + + var socketClient = EasySoc.GetSocket(); + //var account = data["account"].ToString();//新用户账号 + //var avatar = data["avatar"].ToString();//新用户头像 + var nickname = data["nickname"].ToString();//新用户昵称 + //var sex = int.Parse(data["sex"].ToString());//性别 + var wxid = data["wxid"].ToString();//新用户微信id + + #region 添加好友成功 + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var msg = new WechatNewFriend(); + msg.Cmd = PCRobotCMD.newfriend; + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.FromUserName = wxid; + msg.FromUserNick = nickname; + socketClient.Send(msg); + + #endregion + } + break; + case MsgType.MT_CONTACT_DEL_NOTIFY_MSG://群成员删除通知 + { + + } + break; + case MsgType.MT_SNS_TIMELINE_MSG://获取朋友圈首页 + { + #region 数据 + //{"data":{"advertiseCount":1,"advertiseList":[{"adInfo":{"string":"\n\n\t51Hky7pHhu%2BI0D6z6NGPpR15cypIpKvA%2B/WmCm0cjdoElUITIAFetWDTQN4vCIoS6ghxwuN0AHfz/Dd5uv0MOe0BAnqUde7RfcpcLvnU4pKwzvPOf09bD57/YLjKvDkkbHks%2BFQ8yTrjpqCQtrqKXVDJrR%2B/6t2%2BIcLfsbPDz%2B6jDc8gjbkn6ADHUW7tOArlAowZ3aNCjtfk5fBHzow8vwBuatiNIeQQySyetV69UB2exOBcR42IFoB%2BgD0ygOTBlYMnaiQtzS0upkBl4NSPHN9xen3lITxROz3Bj6ZRkqrlzrEJjj%2B%2BX0NTbO/ZduF8Fnsq47hKzFn3RzMmrMiMmRT%2BiJpTD3Tz/rwtYsS3tGTCmbneafTW0o%2B9uinX5C2QK45tKlFSDlAlYqEtepY51N2mrvp5aK8wd1A1dotcSJdRCv%2Bibez/B8KZud5p9NbSvb9U/x10HSpgNsWnqqfBc6UOyLTOR6sULIq3RYG3hO4ttiHsTqJ19OXmIJ18uKdRAwm0W%2B1UgpgsirdFgbeE7i22IexOonX0eoikpovBL67pm9Ry5rKfmdqujuKJIrqR7yAiM9QkVyqfLisGkW2BGdifn1WRZE2eZtz1TIwtr5RIz4fr%2BzWthJ%2B8b4mUiIvRnrvbxY2kLOMTQyaDsIwWCrVVcQmRZEtem7CV9y12Npy2t0P5SYgr9G%2B5LOMNBx0okUHnjJOesdHfVxBOI3ioGMEqURMdxzGKUPEh9cdQZT13OIB60lApJboBtPiusgt2pGeKIWX2go19ctm1ASL/nffmXkqCH/XmhdQh01bx83nD%2BNuVWBsGt7Z9yUJAhgfU2HILNweMjSHCmbneafTW0pglqgouP3YMJyDHsaOablYrOJ7sA5PLjhGJilyjGpsHWO0hq0fn1/6LGFYxykl1OjPcIHGFfpCHLlbaL5ZjZUhhz/C8BOcXNC6vq3hZ1wVbOWBOpKjp0CGTuQXg3A4f0G8kXEJdvrlDsxGnYDSTXSrxeCw34BZX0wRD99w7JmukOIQEjoOL%2BMDlCU9gndnYr00zc1cEpTNCjhbE8KAYJBZdF2AjSLljq1308TAxRKbRrFcgG%2BJiF686OhCWD1v6PpvXQtcAwKCuVWFqytU8Snl/XGkfveCEdkXHGR%2B5wQVpN8L6zzMEG%2BrGdae643cmQb9QbyClCgocIhr5xdxaJXPYn59VkWRNnrbPaWePalQctVk7VbyIJUOzQwHaGlZwKOw/ReHEmsuRdunnXbmrEQRK31EdpPUtw%2BrkaExxbpeSMYgHQ4BoIWvqWUJyOKxwPFyEo3Cvbyx3zs8YEIDR6RYMyvLMeZ593lX52lJXIuf7ZRO6kWIOBbYENyusw81Q0PWttkAUANcUYTIqQmpJ%2Bl18qm66d0POojRw0yPqMI/iLYxfYPjGjxhb1M2zfU9m6L39x5/vp8yN12xfT20Zd3eyVauOFxOb9E3aTDebYH0%2BxbxNh/vbG4SZj9HCaNr0679ITrLZHYXBMDckEiDLDwR8Kw37v7qSMMW8TYf72xuEmY/Rwmja9Ou/SE6y2R2FwX8i5x5zY5Tl5uNpEpeEFoAqMk%2BZ6vqgE02GIVVhiy4hc5/GHP79qRrm42kSl4QWgCoyT5nq%2BqATdoRifFt8u0d30DLV9rACLenS8pBrppyFKjJPmer6oBPjILouBe1NDxY74ukW5A91YGOCIYWrgLdFGxIyh6vP7RAgb9YYpXW87wJPd786IpFTQpa3wkYMP8KZud5p9NbSAzTjUvENRy8XeTjKE1qKCzYwKm%2BvgnNWRTCLfefMjKvCmbneafTW0gM041LxDUcvxxDLN%2BQh1dSf3TphpbYWRLoHQm6WpwmDgyX2IiPt3jiN3ZxN%2BdG6zHs8QtlMdETD2u/GbqAmsR47GXT6%2Bd9vzfByhJ%2BosnjffLJWXJQXjVhUDTGN5mqOpQk1YhZbSJ7Gl3YPDnKBt%2BrT/HSDJ%2Bl2Rgf0drS1gCA4TsUAXLNhv0/py7JV78weUyrsXfLMLC3iynBrDlriy8KB/M/vFXqo7T6zykyz/ykKHC9fpUczj0/%2BiYQb3B2u4h%2B9QlK5J0kaYbM9DtGs1EUIRKIqCLzwHz3wEe%2BlG/jvSp462KvE8TSFOCswenppPI1a65q11Y%2BlO8ydxJ0yKldx4NgHf19YAWnJZAl%2BTTbsgLcaCUPrWS5lz1ndLvPYPcbyJmoyss54YkoMCaTa42hTuW08DkxX84NfS0ImGwrDzyMDV8pAyc7VLiJ3BxfADIWMj9C3nfYHWkD5oDTvOHbrCS0oVJZ1y61s4g4lI3FyoWh1%2Bszkttr3tqOGmeY5mCk2pNpt19zSXB4%2B2Et6MfY5rX9USLkHs0PPXGYe6wXuyT4Luymi/Txdbmkt1cP7P6F2o6H5ahvnzLtULV02HVfYj7vBsaMStTPgp8Bsmt1Dyphn5nqGAASmhUDfXW24V7WKihAkyAHELyMNe%2BsOg6bsTHBBKNGKPGzR5p2LY9gYFVY5/qmRA5d8MkAWlZENvXpAfbBdhejCJLU4lQBGZ0eDGmGOZuaA%2BQ6RMJncv%2BR%2BTAP9TvkNsP5x7Yko/BM2IAtCWoMdFGbhobUaNtVkkvCOc%2BwkwlIOXrrn2yrxTx37JNMsN7RFYiEZJNViWH7dXQlLiz9MOANT8H5t5HmgKEctOb1WDmztxkdBkLAejjMY20ZfUiVjwKSEkrrfw03HXk/sbeLtUsrb7nfeb7wpBi2sU7b8X6/dzpHX9DXDm2i1pOR5s/Ng0yeD/6qROyXiFZLD66XRp7//JznTqFw2TWYDkazuFWAyB7ElWqOVd/DOs%2BCAoORBxxiRhbApMiOYRyTumUb%2B%2B6Zl4qOepsczZ29vS6uVWWJ0p0rEOI2RhVZ7btZ%2Ba3lZVRIf/hRMwBoyRlWyRWLyfEmArfOGNYSa4BdrmxeeV0tdIpmLBesqH%2BfzlDeIDk7mYMk0FEAe2cpwAcbBhbqspuYIxkrOTmw00bthKfiRChNDe%2BQee7ugp8pqvuhoz7xLRUD1lTtlqG/NViTumUb%2B%2B6Zl2S6T12VBePmOOxGKAf3beJ%2BnBqYMHgKRlN2Tkq4GQ/YgJNrT9CcDRl8GQ1XD0o6U3YyDCdZIJrEUeI/uSzP6ju5XimNM1qfeiTty4z6jWFh99u%2BfIUuDvxOIp4XGKpLpJ07p9SXuh1Zy%2Bo/31T9J1fWVO2Wob81W5KyA3Dyc2bO1jtlhgW9eAI47EYoB/dt4FQiAo2J5oyUX0qTwlZ90N6Lln5bTToih/GwuFeIuyfUpNqTabdfc0rQ0s06SldO6V93k1aTZhOJHm3uL1CBBMvhQgjxSWRtrp3DKjyMPfVpYPVWi5Ngj3Y5aIpCQuZXtqruCuUkaNnhqKrfImYGgGKmrjkQD2h3urPY6VezxI9OHcs%2BXYnYPN4PKT1x7h8SO2qEn264xwBl1V6YUdN1FXoZsAsPrnFzWcz5uqxEiT0sch%2BHvj9RxWk0HOHHe5NbmAMHuVM8G7t4hl1NT6tf4sD/1uHZDwAxdwJtX0l2GsaAX7It4cWddtlJ5lscfXYNcmftrlkis981E5N9H4zW918IEMg6uvzSz4T8Zay2P9sMQsCF%2Ba3w6VCY0ZuwxbJqN1QaGDzVOAqmJCgwXZe3RYp2/gyNcSjjkQtBUKhqP42BdVQgg%2BXSnthkM2BlKHdHbibjVedFgMtLy4jXQ0jD%2BwHpBztRpAg5ko9PX7d2z/pJt8YzG3w6JRH3V0XrfkwE0SMU46R%2BTSPmgMgjWPkNxa/m2uLgcrsVBMP%2BUoqGYb3MkzDDj01vctVPDoYnTPiyDmvPETC4UzEm8QE4WG1lCfhu527VjTlnq5vxoaY1zSczQop6cs4IaeerPjfv89hzROCUFTWY7AHyfUqeJVK%2BiPZ0ftd7A5I84adtGjRGgLam9vDrIGEgOytifn1WRZE2e7RfKdpxHe8YH986M%2BW1VEiSf6o6x3ZW13hrLgQASU4k2M2CmUcOsa56My716C8yACOene86zrRIbOKlmWY/LpTTFFDj2FS/wRUBIA92e/K3PY4bY3rnNirArVpfolQpqUdeELefv5t1ECPZk5I8tozTqrC6wrFRARf3dlHL0WpRZQzOkMnGblx51W2kSUpSu2/Hd91eDSEOBXvE/kanskVWtaO29jtIzaXdOdbo2JtGAJYzJ7QD93xQpz87qAUQXCBXuJQSB/bEiwpxez/q1U6KDkxquq0XUF9zkWsYKUjFogJilTpoYvjDtoQVtApmBOA2f7el/VIHnxuCNmQlqQFxZQwbWI4tu5EfUvvFSANAk4jag8a4HYuF8%2B8esOKs2PSsBnhQzc%2BY22OtuD3yCNeLZ5n1B5za16svARkdgiGtPGEKwhyvAcMPUfhiL7RxZprDKae8MX1PVHECjLItG2MDR7ZczhqZvA9CHH0GAbafIYSkOszxrBPPpNff7dYiB/j%2BMzZCgR4yfQ7CoDU3lRIFM7BEAf4od%2B3kzeNkAy7ZaAGZftgda2Ih%2BPdTIb6Hv5zgI2didIUjziKQ0Glppdv14mXUNSx8Osti8pEcBeFN3//o3aeh8wYx6bDo/zqIDhFnZE/QS%2BoLSkKdNBK1wPJao/BgEj8GEjOIqWUvm8R5dhNriF5xeYZcXmxbjnwREWQWbbbrLMFFLc7NK/Ol0iNdgpgmBjesJ%2BsrXt0d88f9txZDbMh0kQhWdc/B2bqPntbxWBM3n63FNQKwW6Ch81DpIHjAOJ9YxiEO6FohEbrgLoWfT/TU1eJfHWjklbn6GnbsY4E7mMRoJV7VKXV/GuPP7un5EV%2BwrNpNp0v%2BSybnvKAAEqdQL5cZuKVZMfIOOtopdZisTxabiDXUYViRIoVzvUrdfVGeQVdKAmHLZYjaWnzKUIgF8oyIi091o1BkDsWY8sbUptYLfqFIQR4BMl3xYuum%2BKt3/56SzrDXXPYI7Gb%2BAbdrUFEVeL/LdryKoWtq7jM1hSu5MhS5SOEuoFMbt5EuW5vdTKNlfgWJWsvkZsZNg2uPG%2Bt2HCI3m2MTqvavmupGW%2BmkwK7pwPy56I/8unXh6QMpuq9ifhaOLpfBQK/BLOuTqjqKOZ8yeTW/pJR30DlpUK8Pb1t0/oVUCHbFxhM2uqKlaHAGgTp817xa1p9a9sWAD9g==\n\t4\n\t720\n\t720\n\t3547325421|wx0tld43lkkrodqq|3547325421|1|1626955012|0|2|6041365717172948||AgIylt4GK8nVeUcuI+4pKmMsArrIRywgjntIrbYMoUfG0o+2+yULEOc9S+J+Wk6PLDoh6IKmSjk=|3400866612|21\n\t1\n\thttps://as.weixin.qq.com/cgi-bin/redirect?tid=3400866612&token=e8d51e642ec1fa8166c546c1f303cf95&wx_aid=3547325421&wx_traceid=wx0tld43lkkrodqq00&wx_uid=19681428\n\t4\n\t\n\t\t\n\t\t\t0\n\t\t\t最近有719人购买\n\t\t\t最近有719人购买\n\t\t\t最近有719人购买\n\t\t\n\t\t1\n\t\t1800\n\t\t\n\t\t\tgh_85ea230f6b61@app\n\t\t\t/pages/shop/index.html?storeId=2393731723\n\t\t\t\n\t\t\t1\n\t\t\n\t\n\t\n\t\twx0tld43lkkrodqq\n\t\t3547325421\n\t\n\n\n"},"snsAdObject":{"adXml":{"string":"1AlphaDog阿尔法机器狗19681428011平价阿尔法机器狗来喽时代的风景,AI相伴立即购买4gh_85ea230f6b61@app/pages/shop/index.html?storeId=23937317231新品推荐限量抢购IP联名活动1https://as.weixin.qq.com/cgi-bin/redirect?tid=3400866612&token=e8d51e642ec1fa8166c546c1f303cf9510广告廣告Ad赞助商提供的广告信息贊助商提供的廣告信息Sponsored storyclassify_zh_CNzh_CNclassify_zh_TWzh_TWclassify_enen_USnickname_zh_CNnickname_zh_CNnickname_zh_TWnickname_zh_TWnickname_ennickname_enhttps://mp.weixin.qq.com/promotion/res/htmledition/mobile/html/feedback.html投诉投訴Report654315520385879808https://wxa.wxs.qq.com/canvas-luodiye/h5/wxupdate.html"},"snsObject":{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1621049336,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13598347436105209699,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD4xMzU5ODM0NzQzNjEwNTIwOTY5OTwvaWQ+PGNyZWF0ZVRpbWU+MTYyMTA0OTMzNjwvY3JlYXRlVGltZT48dXNlcm5hbWU+Z2hfMWNmYmQ1NjAzNzliPC91c2VybmFtZT48Y29udGVudERlc2M+5pe25Luj55qE6aOO5pmv77yMQUnnm7jkvLQ8L2NvbnRlbnREZXNjPjxjb250ZW50RGVzY1Nob3dUeXBlPjA8L2NvbnRlbnREZXNjU2hvd1R5cGU+PGNvbnRlbnREZXNjU2NlbmU+MzwvY29udGVudERlc2NTY2VuZT48cHJpdmF0ZT4wPC9wcml2YXRlPjxDb250ZW50T2JqZWN0Pjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48Y29udGVudFN0eWxlPjE8L2NvbnRlbnRTdHlsZT48bWVkaWFMaXN0PjxtZWRpYT48aWQ+MTM1OTkwODQ4MTQ2ODQ0NjA5NDA8L2lkPjxwcml2YXRlPjA8L3ByaXZhdGU+PHR5cGU+MjwvdHlwZT48c3ViVHlwZT4wPC9zdWJUeXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjx1c2VyRGF0YT48L3VzZXJEYXRhPjxsb3dCYW5kVXJsIHR5cGU9IjEiPjwvbG93QmFuZFVybD48dXJsIHR5cGU9IjEiPmh0dHA6Ly93eHNuc2R5dGh1bWIud3hzLnFxLmNvbS8xNDEvMjAyMDQvc25zY29zZG93bmxvYWQvU0gvcmVzZXJ2ZWQvNjA5ZjNlOTQwMDBjOTk1ZDAwMDAwMDAwOWEyMDlkMDkwMDAwMDA4ZDAwMDA0ZWVjP209NzA3YzBiMmVjNDY1OTNiZDQ3NjJlZjRkYWY0MmE4OGYmYW1wO2NrPTcwN2MwYjJlYzQ2NTkzYmQ0NzYyZWY0ZGFmNDJhODhmPC91cmw+PHRodW1iIHR5cGU9IjEiPmh0dHA6Ly93eHNuc2R5dGh1bWIud3hzLnFxLmNvbS8xNDEvMjAyMDQvc25zY29zZG93bmxvYWQvU0gvcmVzZXJ2ZWQvNjA5ZjNlOTQwMDBjOTk1ZDAwMDAwMDAwOWEyMDlkMDkwMDAwMDA4ZDAwMDA0ZWVjP209NzA3YzBiMmVjNDY1OTNiZDQ3NjJlZjRkYWY0MmE4OGYmYW1wO2NrPTcwN2MwYjJlYzQ2NTkzYmQ0NzYyZWY0ZGFmNDJhODhmPC90aHVtYj48c2l6ZSBoZWlnaHQ9IjQ1MCIgd2lkdGg9IjgwMCIgdG90YWxTaXplPSI2NTEzMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PGNvbnRlbnRTdWJTdHlsZT44PC9jb250ZW50U3ViU3R5bGU+PC9Db250ZW50T2JqZWN0PjwvVGltZWxpbmVPYmplY3Q+","iLen":1152},"objectOperations":{"buffer":"CAI=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"gh_1cfbd560379b","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}}}],"baseResponse":{"ret":0},"controlFlag":2,"delAdvertiseCount":0,"firstPageMd5":"6935ad04c4ed4552","max_id":"13647311131165143274","newRequestTime":1626954952,"objectCount":10,"objectCountForSameMd5":10,"objectList":[{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626886264,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13647311131165143274,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"为美好的世界献上祝福","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NzMxMTEzMTE2NTE0MzI3NF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfbWp6ZWg0cWo5aGlvMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY4ODYyNjRdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGFwcEluZm8+PGlkPjwhW0NEQVRBW3d4YWI5YjcxYWQyYjkwZmYzNF1dPjwvaWQ+PHZlcnNpb24+MjY8L3ZlcnNpb24+PGFwcE5hbWU+PCFbQ0RBVEFb5b6u5L+h6K+75LmmXV0+PC9hcHBOYW1lPjxpbnN0YWxsVXJsPjwvaW5zdGFsbFVybD48ZnJvbVVybD48L2Zyb21Vcmw+PGNsaWNrYWJsZT4wPC9jbGlja2FibGU+PC9hcHBJbmZvPjxjb250ZW50RGVzYz48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0NzMxMTEzMTczNDA2MTI3N11dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSJmMjhmNTgyNjE4NmU2ZTZmMWY4NTVjYzAxMjU4MDIzYiI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9hRnJXNFBWVjRwS1NuU3ExcURRVWMxWExOTUNpY2pnaWNhbTdwTlVoN1AyanUxZFJheDdIaWJROHV2YlRvdDRYeHk0UVhmR1RMSFZvbFEvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL2FGclc0UFZWNHBLU25TcTFxRFFVYzFYTE5NQ2ljamdpY2FtN3BOVWg3UDJqdTFkUmF4N0hpYlE4dXZiVG90NFh4eTRRWGZHVExIVm9sUS8xNTBdXT48L3RodW1iPjx2aWRlb0R1cmF0aW9uPjwhW0NEQVRBWzAuMF1dPjwvdmlkZW9EdXJhdGlvbj48c2l6ZSB0b3RhbFNpemU9IjY1Mjg5LjAiIHdpZHRoPSIxMDgwLjAiIGhlaWdodD0iMTY0OC4wIj48L3NpemU+PC9tZWRpYT48L21lZGlhTGlzdD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVkaWFUYWdOYW1lPjwvbWVkaWFUYWdOYW1lPjxtZXNzYWdlRXh0PjwvbWVzc2FnZUV4dD48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PGFwcGlkPnd4YWI5YjcxYWQyYjkwZmYzNDwvYXBwaWQ+PC9hcHBNc2c+PHNjZW5lPjA8L3NjZW5lPjx0eXBlPjA8L3R5cGU+PHVybD48L3VybD48bmV3V29yZGluZ0tleT48L25ld1dvcmRpbmdLZXk+PG5ld3R5cGU+MDwvbmV3dHlwZT48aW5zdGFsbGVkV29yZGluZz48L2luc3RhbGxlZFdvcmRpbmc+PHVuaW5zdGFsbGVkV29yZGluZz48L3VuaW5zdGFsbGVkV29yZGluZz48L2FjdGlvbkluZm8+PHN0YXRFeHRTdHI+PCFbQ0RBVEFbR2hRS0VuZDRZV0k1WWpjeFlXUXlZamt3Wm1Zek5BPT1dXT48L3N0YXRFeHRTdHI+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2449},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_mjzeh4qj9hio22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626788321,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13646489531181052217,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NjQ4OTUzMTE4MTA1MjIxN11dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY3ODgzMjFdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+WPr+S4jeaYr+WYm++8jOWPiOeqgeeEtuS6huS4gOS4i+S4i1vml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0NjQ4OTUzMTgxNjk0ODAyNl1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSJkNTBkOWM5M2Q1NTk5NjkzMjQ2ZTBiZTc1NDZlMmM5OSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4NGI5d21MZDhSRG5yTjhqWlRqNnVYdHF0aWNyWUl2REFMQXBqZ0g0WWZES0JnampUVkh6WDdPVS8wXV0+PC91cmw+PHRodW1iIHR5cGU9IjEiPjwhW0NEQVRBW2h0dHA6Ly9zem1tc25zLnFwaWMuY24vbW1zbnMvVkVkb2ppYmV2alJQQ3Y5TTNBbkhTODRiOXdtTGQ4UkRuck44alpUajZ1WHRxdGljcllJdkRBTEFwamdINFlmREtCZ2pqVFZIelg3T1UvMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSI0NDUzOC4wIiB3aWR0aD0iMTA4MC4wIiBoZWlnaHQ9IjIzNDAuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2077},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626542926,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13644431003338420534,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NDQzMTAwMzMzODQyMDUzNF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY1NDI5MjZdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+aYr+WTquS4quS6uua4o+WcqOWPkeiqk++8jOaQnuW+l+S7iuaZmuWPiOaYr+aatOmbqO+8jOWPiOaYr+aJk+mbt+eahFvml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsyXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1496},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626442781,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13643590928611357004,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MzU5MDkyODYxMTM1NzAwNF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY0NDI3ODFdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S7iuaZmuaciOS6rvCfjJkg5b6I5byv77yM5Lq65rKh5byv5bCx5aW9W+aXuuaftF1b5pe65p+0XV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQzNTkwOTI5MjEzMjM5NjQxXV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9ImEwYzA1NTljMTE3MDUwOTIxM2YyNGMwNWMwMmVjODRkIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzh3UFEzaWJKZGRHRXI4SThOYU9WNnJFWHhtNmtLeG9Ob0xjdTVIMVZBN3hpY3BpYTZCZDJORHFNQ2svMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzh3UFEzaWJKZGRHRXI4SThOYU9WNnJFWHhtNmtLeG9Ob0xjdTVIMVZBN3hpY3BpYTZCZDJORHFNQ2svMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSI3MTYzNy4wIiB3aWR0aD0iOTc4LjAiIGhlaWdodD0iMTE2NC4wIj48L3NpemU+PC9tZWRpYT48L21lZGlhTGlzdD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVkaWFUYWdOYW1lPjwvbWVkaWFUYWdOYW1lPjxtZXNzYWdlRXh0PjwvbWVzc2FnZUV4dD48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PC9hcHBNc2c+PC9hY3Rpb25JbmZvPjxhcHBJbmZvPjxpZD48L2lkPjwvYXBwSW5mbz48bG9jYXRpb24gcG9pQ2xhc3NpZnlJZD0iIiBwb2lOYW1lPSIiIHBvaUFkZHJlc3M9IiIgcG9pQ2xhc3NpZnlUeXBlPSIwIiBjaXR5PSIiPjwvbG9jYXRpb24+PHB1YmxpY1VzZXJOYW1lPjwvcHVibGljVXNlck5hbWU+PHN0cmVhbXZpZGVvPjxzdHJlYW12aWRlb3VybD48L3N0cmVhbXZpZGVvdXJsPjxzdHJlYW12aWRlb3RodW1idXJsPjwvc3RyZWFtdmlkZW90aHVtYnVybD48c3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvPjwvVGltZWxpbmVPYmplY3Q+","iLen":2085},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626348290,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13642798280310927692,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626351692,"deleteFlag":0,"isNotRichText":0,"nickname":"Mr.Y","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_ocmmotiznvw122"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0Mjc5ODI4MDMxMDkyNzY5Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYzNDgyOTBdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+imgeW+l+eRn+W+l+eRn++8jOWHj+S4gOWNiuebruagh+S6hlvml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0Mjc5ODI4MTAzODMxMTc2Ml1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSI0NmE0OGE0YzgzOTNhMDA0NWZjZTUzZGU4ZmEzODg0OSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4OFRoT0dJczEwSGdDMEtLUDRidUJIQnh1eUhXa3BBT0VudnpvSmtyZElEbkJ3N2JRNjVSZ0VnLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4OFRoT0dJczEwSGdDMEtLUDRidUJIQnh1eUhXa3BBT0VudnpvSmtyZElEbkJ3N2JRNjVSZ0VnLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iOTM3MzEuMCIgd2lkdGg9IjE0NDAuMCIgaGVpZ2h0PSIxMDgwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2075},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626277124,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13642201292100546882,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626277179,"deleteFlag":0,"isNotRichText":0,"nickname":"为美好的世界献上祝福","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_mjzeh4qj9hio22"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MjIwMTI5MjEwMDU0Njg4Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYyNzcxMjRdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+WNp+anve+8jOaUtuWIsOS6humihOitpuitpuWRilvmg4rmgZBdW+aDiuaBkF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsyXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1457},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626099336,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13640709903944790348,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626134130,"deleteFlag":0,"isNotRichText":0,"nickname":"Mr.Y","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_ocmmotiznvw122"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MDcwOTkwMzk0NDc5MDM0OF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYwOTkzMzZdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S5n+eul+aYr+S4izcw5LqGW+aXuuaftF1b5pe65p+0XV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQwNzA5OTA0NjgyODU2Nzc0XV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9IjQzNjdkOTU4Yzc1MjJkY2E3NWZiNmM4MzY2ODYxZGQzIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTB2QmNPVzkzTnRVUDU4UWtONFM4d2VTa3RIS2lhdzM1YUFPUjNObGV2Z2hBYndTRU43ZTY3ZVljLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUk9OemoxUHUybUkwdkJjT1c5M050VVA1OFFrTjRTOHdlU2t0SEtpYXczNWFBT1IzTmxldmdoQWJ3U0VON2U2N2VZYy8xNTBdXT48L3RodW1iPjx2aWRlb0R1cmF0aW9uPjwhW0NEQVRBWzAuMF1dPjwvdmlkZW9EdXJhdGlvbj48c2l6ZSB0b3RhbFNpemU9IjE2OTMxLjAiIHdpZHRoPSI3MjYuMCIgaGVpZ2h0PSIyOTkuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2056},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626020250,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13640046480797544764,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MDA0NjQ4MDc5NzU0NDc2NF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYwMjAyNTBdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S9oOiLpeacquWHuueOsO+8jOa4uOaIj+S4jeWNuOi9ve+8gV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQwMDQ2NDgxNTA3OTU0OTk1XV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9Ijg4NDJkMGU0YjU2ZWZjMzhkZjVhMTlkMjgxMzA2OTYyIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTBqYmliM292bmlieG8xcTJpYm9taWNCbnZhU2dNRjRuRmtpYWZCYWJ0RlEyaEJYbGZCTUxnMmliZjg1VmsvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTBqYmliM292bmlieG8xcTJpYm9taWNCbnZhU2dNRjRuRmtpYWZCYWJ0RlEyaEJYbGZCTUxnMmliZjg1VmsvMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSIxMDk5Ny4wIiB3aWR0aD0iMjM0LjAiIGhlaWdodD0iNDQwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2069},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1625753812,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13637811438959997245,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzYzNzgxMTQzODk1OTk5NzI0NV1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjU3NTM4MTJdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+ivpeatu++8jOi3keS6huW/q+S4pOWFrOmHjOiuoeatpeWZqOaJjeW8gOWni+iuoeaVsO+8jOaIkeivtOaAjuS5iOi3keS6humCo+S5iOS5he+8jOi/mOayoeS4gOWFrOmHjOWSqVvoi6bmtqldW+iLpua2qV3vvIzmi7/lh7rmiYvmnLrkuIDnnIvvvIzmsqHorqHmraXvvIzmraPluLjmg4XlhrXml6nkupTlhazph4zkuoZb5pOm5rGXXVvmk6bmsZddXV0+PC9jb250ZW50RGVzYz48Y29udGVudGF0dHI+PCFbQ0RBVEFbMF1dPjwvY29udGVudGF0dHI+PHNvdXJjZVVzZXJOYW1lPjwvc291cmNlVXNlck5hbWU+PHNvdXJjZU5pY2tOYW1lPjwvc291cmNlTmlja05hbWU+PHN0YXRpc3RpY3NEYXRhPjwvc3RhdGlzdGljc0RhdGE+PHdlYXBwSW5mbz48YXBwVXNlck5hbWU+PC9hcHBVc2VyTmFtZT48cGFnZVBhdGg+PC9wYWdlUGF0aD48dmVyc2lvbj48IVtDREFUQVswXV0+PC92ZXJzaW9uPjxkZWJ1Z01vZGU+PCFbQ0RBVEFbMF1dPjwvZGVidWdNb2RlPjxzaGFyZUFjdGlvbklkPjwvc2hhcmVBY3Rpb25JZD48aXNHYW1lPjwhW0NEQVRBWzBdXT48L2lzR2FtZT48bWVzc2FnZUV4dHJhRGF0YT48L21lc3NhZ2VFeHRyYURhdGE+PHN1YlR5cGU+PCFbQ0RBVEFbMF1dPjwvc3ViVHlwZT48cHJlbG9hZFJlc291cmNlcz48L3ByZWxvYWRSZXNvdXJjZXM+PC93ZWFwcEluZm8+PGNhbnZhc0luZm9YbWw+PC9jYW52YXNJbmZvWG1sPjxDb250ZW50T2JqZWN0Pjxjb250ZW50U3R5bGU+PCFbQ0RBVEFbMV1dPjwvY29udGVudFN0eWxlPjxjb250ZW50U3ViU3R5bGU+PCFbQ0RBVEFbMF1dPjwvY29udGVudFN1YlN0eWxlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48bWVkaWFMaXN0PjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2Mzc4MTE0Mzk0MzkwNjU0MjhdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIHR5cGU9IjEiIG1kNT0iMGFkNGZmNWNjZDBhOWU1ODYxMjE3ODk1N2MwMmIzZTQiPjwhW0NEQVRBW2h0dHA6Ly9zem1tc25zLnFwaWMuY24vbW1zbnMvVkVkb2ppYmV2alJQQ3Y5TTNBbkhTODhuQTRTVTB4VWROMkhSbllqdGlhOEFVUGROR0EyMEQxS0FDd0JNN0VZNjlrT2g2MUZZQ0l2bWcvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzg4bkE0U1UweFVkTjJIUm5ZanRpYThBVVBkTkdBMjBEMUtBQ3dCTTdFWTY5a09oNjFGWUNJdm1nLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iNzUxODEuMCIgd2lkdGg9Ijk3OC4wIiBoZWlnaHQ9IjExNjQuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2221},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1625569697,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13636266972566990992,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"#A02选购助手","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzYzNjI2Njk3MjU2Njk5MDk5Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfMHV3YnpnaWxmbWg4MjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjU1Njk2OTddXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBWzQ3LjXlhYU1MOivnei0uSAgOTXlhYUxMDDor53otLlb5pe65p+0XSAK4pSB4pSB5omr56CB5YWF5YC84pSB4pSBCiAgICDkuInnvZHpg73lj6/ku6XvvIzliLDotKblv6tdXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzYzNjI2Njk3MzA0NjEyNDY3OF1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgbWQ1PSJiNzFjZjEyNDAzNzZlYjc4YzQwNjY0NmQ2NmZiYzY5MiIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3NobW1zbnMucXBpYy5jbi9tbXNucy9qaExkS0Jvb1VIOVdNZW5RRGhXeDZlRmpNMHh4SlhVZW91a2VpY01QTWtrMzl2RjNYaE9SNDRZd1JGUWljTkE1NDZpYWdOU3BIaWM2YzNFLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3NobW1zbnMucXBpYy5jbi9tbXNucy9qaExkS0Jvb1VIOVdNZW5RRGhXeDZlRmpNMHh4SlhVZW91a2VpY01QTWtrMzl2RjNYaE9SNDRZd1JGUWljTkE1NDZpYWdOU3BIaWM2YzNFLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIGhlaWdodD0iMTkyMC4wIiB3aWR0aD0iMTA4MC4wIiB0b3RhbFNpemU9IjUxMzc0LjAiPjwvc2l6ZT48L21lZGlhPjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2MzYyNjY5NzMwNDY2NDg5NjNdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIG1kNT0iNzIxZTY5MzdiMzBiOGUxYmY2MjBmNzY0ZWI4ZDgyYWQiIHR5cGU9IjEiPjwhW0NEQVRBW2h0dHA6Ly9zaG1tc25zLnFwaWMuY24vbW1zbnMvamhMZEtCb29VSDlXTWVuUURoV3g2ZUZqTTB4eEpYVWVEUkRHU2R0TWRVVTRpYkZ3NUpVN3QzaE1EYTlDdEFXQ3lFZWljS1JtMlVrbXcvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc2htbXNucy5xcGljLmNuL21tc25zL2poTGRLQm9vVUg5V01lblFEaFd4NmVGak0weHhKWFVlRFJER1NkdE1kVVU0aWJGdzVKVTd0M2hNRGE5Q3RBV0N5RWVpY0tSbTJVa213LzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIGhlaWdodD0iMjM0MC4wIiB3aWR0aD0iMTA4MC4wIiB0b3RhbFNpemU9Ijc2Mzc4LjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2717},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_0uwbzgilfmh822","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}],"recCount":0,"serverConfig":{"copyAndPasteWordLimit":100,"postMentionLimit":10},"session":{"buffer":"CIS65YcGEAEY6uHUgq2lv7K9ASDq4dSCraW/sr0BMIS65YcGSk8I/rLN8KwvEAoYhLrlhwYiIgjjrpTrop7C27wBEAQYBCDq4dSCraW/sr0BKIS65YcGMAEqGgjq4dSCraW/sr0BEJDh/JGEkvCevQEYCiABUIS65YcGYIS65YcG","iLen":129}},"type":11145} + #endregion + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client = WechatClient.GetApi(user) as Wechat_Xiaoxie; + if (!user.IsGetCircle) return; + try + { + //var _data = json.ContainsKey("data") ? json["data"] as Dictionary : null; + //if (_data == null) return; + + //foreach (KeyValuePair item in _data) + //{ + // var wxid = item["wxid"]?.ToString(); + + //} + //for (int i = 0; i < _data.Count; i++) + //{ + // var item = _data[i] as Dictionary; + + // var wxid = item["wxid"]?.ToString(); + + + //} + + user.CircleData = recvData; + } + catch (Exception ex) + { } + finally + { + user.IsGetCircle = false; + } + } + break; + case MsgType.MT_SNS_AUTO_AUTH_MINIAPP_LOGIN://小程序自动授权登录 + { + //{"data":{"appid":"wxde8ac0a21135c07d","code":"051QFNkl2pCwt748wlol2XID1B4QFNk8"},"type":11136} + + var appid = data["appid"].ToString(); + var code = data["code"].ToString(); + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + if (user.AutoAuthLoginMiNiApps.ContainsKey(appid)) + user.AutoAuthLoginMiNiApps.Remove(appid); + user.AutoAuthLoginMiNiApps.Add(appid, code); + } + break; + case MsgType.MT_SNS_POST_MSG://发送朋友圈 + { + #region 数据结构 + /* + {"data":{"baseResponse":{"ret":0},"snsObject":{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1627522835,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13652651078544265545,"isNotRichText":0,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"、","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD4xMzY1MjY1MTA3ODU0NDI2NTU0NTwvaWQ+PHVzZXJuYW1lPnd4aWRfdnY3cmV2N2E0eHBqMjI8L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjE2Mjc1MjI4MzU8L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4zPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjA8L3ByaXZhdGU+PGNvbnRlbnREZXNjPui/meS4quS9oOiCr+WumuS4jeefpemBk+aIkeeOsOWcqOaDs+eahEE8L2NvbnRlbnREZXNjPjxzaWdodEZvbGRlZD4wPC9zaWdodEZvbGRlZD48c2hvd0ZsYWc+MDwvc2hvd0ZsYWc+PGFwcEluZm8+PGlkPjwvaWQ+PHZlcnNpb24+PC92ZXJzaW9uPjxhcHBOYW1lPjwvYXBwTmFtZT48aW5zdGFsbFVybD48L2luc3RhbGxVcmw+PGZyb21Vcmw+PC9mcm9tVXJsPjxpc0ZvcmNlVXBkYXRlPjA8L2lzRm9yY2VVcGRhdGU+PC9hcHBJbmZvPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjxzdGF0RXh0U3RyPjwvc3RhdEV4dFN0cj48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjI8L2NvbnRlbnRTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48bWVkaWFMaXN0PjwvbWVkaWFMaXN0Pjxjb250ZW50VXJsPjwvY29udGVudFVybD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PC9hcHBNc2c+PC9hY3Rpb25JbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1112},"objectOperations":{"buffer":"","iLen":0},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_vv7rev7a4xpj22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},"spamTips":""},"type":11148} + */ + #endregion + + if (data.ContainsKey("snsObject")) + { + var snsObject = data["snsObject"] as Dictionary; + if (snsObject.ContainsKey("id")) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + user.SendCircleId = snsObject["id"].ToString(); + } + } + } + break; + case MsgType.MT_SNS_COMMENT_MSG://朋友圈评论 + { + + } + break; + case MsgType.MT_SNS_LIKE_MSG://朋友圈点赞 + { + + } + break; + case MsgType.MT_SNS_UPLOAD_IMAGE_MSG://朋友圈上传图片 + { + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGYkibHF8s3Pu0RAQNicdgRVsn/0"},"clientId":"wxid_vv7rev7a4xpj22_1627486860","id":0,"path":"D:\\PCRobot\\bin\\Debug\\Cache\\0728114016639.png","startPos":16627,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGYkibHF8s3Pu0RAQNicdgRVsn/150"}],"totalLen":16627,"type":2},"type":11149} + + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGa9quIRWhDvpnuvgkSLwxaz/0"},"clientId":"wxid_vv7rev7a4xpj22_1627491212","id":0,"path":"","startPos":59023,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGa9quIRWhDvpnuvgkSLwxaz/150"}],"totalLen":59023,"type":2},"type":11149} + + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGytHnYnRDfnZ3JnOPBfd4kopkfT9Kic2vlQibkXia04Zweib/0"},"clientId":"wxid_vv7rev7a4xpj22_1627523859","id":0,"path":"D:\\公司项目\\fl_system\\PCRobot\\bin\\Debug\\Cache\\0729095735481.jpg","startPos":47326,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGytHnYnRDfnZ3JnOPBfd4kopkfT9Kic2vlQibkXia04Zweib/150"}],"totalLen":47326,"type":2},"type":11149} + + var upLoadImage = JsonConvert.DeserializeObject(recvData); + if (upLoadImage != null) + { + if (upLoadImage.data.startPos == upLoadImage.data.totalLen) + { + var path = upLoadImage.data.path; + var url = upLoadImage.data.bufferUrl.url; + if (!string.IsNullOrWhiteSpace(path) && !string.IsNullOrWhiteSpace(url)) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + if (user.UpLoadImages.ContainsKey(path)) + user.UpLoadImages.Remove(path); + user.UpLoadImages.Add(path, url); + } + else + { + + } + } + } + } + break; + case MsgType.MT_SNS_TIMELINE_USER_MSG://获取指定用户的朋友圈 + { + #region 数据样式 + /* + {"data":{"baseResponse":{"ret":207},"continueId":0,"firstPageMd5":"b7e1f61580104448","limitedId":0,"newRequestTime":1627613128,"objectCount":1,"objectCountForSameMd5":1,"objectList":[{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1627612789,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13653405663930290388,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"先森吳","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY1MzQwNTY2MzkzMDI5MDM4OF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d1amlhaHVhMDg3Nl1dPjwvdXNlcm5hbWU+PGNyZWF0ZVRpbWU+PCFbQ0RBVEFbMTYyNzYxMjc4OV1dPjwvY3JlYXRlVGltZT48Y29udGVudERlc2NTaG93VHlwZT4wPC9jb250ZW50RGVzY1Nob3dUeXBlPjxjb250ZW50RGVzY1NjZW5lPjA8L2NvbnRlbnREZXNjU2NlbmU+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48Y29udGVudERlc2M+PCFbQ0RBVEFb5L2g6IKv5a6a5LiN55+l6YGT5oiR546w5Zyo5oOz6KGo6L6+5LuA5LmIXV0+PC9jb250ZW50RGVzYz48Y29udGVudGF0dHI+PCFbQ0RBVEFbMF1dPjwvY29udGVudGF0dHI+PHNvdXJjZVVzZXJOYW1lPjwvc291cmNlVXNlck5hbWU+PHNvdXJjZU5pY2tOYW1lPjwvc291cmNlTmlja05hbWU+PHN0YXRpc3RpY3NEYXRhPjwvc3RhdGlzdGljc0RhdGE+PHdlYXBwSW5mbz48YXBwVXNlck5hbWU+PC9hcHBVc2VyTmFtZT48cGFnZVBhdGg+PC9wYWdlUGF0aD48dmVyc2lvbj48IVtDREFUQVswXV0+PC92ZXJzaW9uPjxkZWJ1Z01vZGU+PCFbQ0RBVEFbMF1dPjwvZGVidWdNb2RlPjxzaGFyZUFjdGlvbklkPjwvc2hhcmVBY3Rpb25JZD48aXNHYW1lPjwhW0NEQVRBWzBdXT48L2lzR2FtZT48bWVzc2FnZUV4dHJhRGF0YT48L21lc3NhZ2VFeHRyYURhdGE+PHN1YlR5cGU+PCFbQ0RBVEFbMF1dPjwvc3ViVHlwZT48cHJlbG9hZFJlc291cmNlcz48L3ByZWxvYWRSZXNvdXJjZXM+PC93ZWFwcEluZm8+PGNhbnZhc0luZm9YbWw+PC9jYW52YXNJbmZvWG1sPjxDb250ZW50T2JqZWN0Pjxjb250ZW50U3R5bGU+PCFbQ0RBVEFbMV1dPjwvY29udGVudFN0eWxlPjxjb250ZW50U3ViU3R5bGU+PCFbQ0RBVEFbMF1dPjwvY29udGVudFN1YlN0eWxlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48bWVkaWFMaXN0PjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2NTM0MDU2NjQ1NTkyMzkzODZdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIHR5cGU9IjEiIG1kNT0iNDI1YTRiODEyNjQ2NzQwY2Y3MzlmYWI4Y2E2ZGIyNWUiPjwhW0NEQVRBW2h0dHA6Ly9zaG1tc25zLnFwaWMuY24vbW1zbnMvaWNySERtdkRpYjB4bUhUbkFPODJKSVVjaDFUVmUySWFtbDdYWHdaSlVuUWpZU3dsSjVNa09iQXlYRkpUbVNTbk5DZmNITFgyNE9RUncvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc2htbXNucy5xcGljLmNuL21tc25zL2ljckhEbXZEaWIweG1IVG5BTzgySklVY2gxVFZlMklhbWw3WFh3WkpVblFqWVN3bEo1TWtPYkF5WEZKVG1TU25OQ2ZjSExYMjRPUVJ3LzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iMTAxOTIuMCIgd2lkdGg9IjEwODAuMCIgaGVpZ2h0PSIyMzQwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2060},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wujiahua0876","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}],"objectTotalCount":5,"retTips":"朋友仅展示最近一个月的朋友圈","serverConfig":{"copyAndPasteWordLimit":100,"postMentionLimit":10},"snsUserInfo":{"snsBgImgId":"http://szmmsns.qpic.cn/mmsns/icrHDmvDib0xnEAtnSHHGziac6GNMlhWZK61YORztv9pl7x3AeNWibkAcdJstckibqwBFVFcFO9ovscc/0","snsBgObjectId":13404086805597261983,"snsFlag":1,"snsFlagEx":6273}},"type":11150} + */ + #endregion + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + if (data.ContainsKey("objectList")) + { + var objectList = data["objectList"] as ArrayList; + if (objectList != null && objectList.Count != 0) + { + var result = objectList[0] as Dictionary; + if (result != null) + { + if (result.ContainsKey("username")) + { + var uname = result["username"].ToString(); + if (user.GetUserCircles.ContainsKey(uname)) + user.GetUserCircles.Remove(uname); + user.GetUserCircles.Add(uname, recvData); + } + } + } + } + } + break; + default: + break; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + }); + //method.BeginInvoke(null, null); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 本地解密dat图片 + /// + /// + /// + /// + public static string DecodeImage(string FileName, byte XorKey, string DecodeImagePath) + { + var data = File.ReadAllBytes(FileName); + for (int i = 0; i < data.Length; i++) + data[i] = Convert.ToByte(data[i] ^ XorKey); + //var path = FileName.Replace(Path.GetFileName(FileName), Path.GetFileNameWithoutExtension(FileName) + ".jpg"); + File.WriteAllBytes(DecodeImagePath, data); + return DecodeImagePath; + } + + /// + /// 获取微信的uin的值 + /// + /// + /// + public static string GetUin(int pid) + { + Process[] processes = Process.GetProcesses(); + foreach (Process process in processes) + { + if (process.Id == pid) + { + foreach (ProcessModule processModule in process.Modules) + { + if (processModule.ModuleName == "WeChatWin.dll") + { + //微信基址 + var WeChatWinBaseAddress = processModule.BaseAddress; + //Console.WriteLine("微信基址:\t" + "0x" + ((int)(processModule.BaseAddress)).ToString("X8") + Environment.NewLine); + var WxNameAddress = WeChatWinBaseAddress + PcOffSet; + var uinStr = Common.GetString(process.Handle, WxNameAddress, 4); + Console.WriteLine($"uinStr = {uinStr}"); + return uinStr; + } + } + break; + } + } + return string.Empty; + } + + // 关闭回调 + static void WxCloseCallback(uint dwClientId) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == dwClientId && f.Value.Type == WechatType.Xiaoxie).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"WxCloseCallback关闭回调,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + #endregion + + public Wechat_Xiaoxie(WechatUser User) : base(User) { } + + public override void SendMessage(string wxid, string message) + { + try + { + var json = string.Empty; + message = message.Replace("\r\n", "\n"); + if (Common.isXML(message)) + { + //var msgs = Regex.Matches(message, "(<.*?>)(.*?)()"); + //foreach (Match item in msgs) + //{ + // if (item.Success && !string.IsNullOrEmpty(item.Groups[2].Value) && !item.Groups[2].Value.StartsWith("" + item.Groups[3]; + // message = message.Replace(item.Groups[1].Value,temp); + // } + //} + + //wxfedd75bfcbbcd58c + //wx13e41a437b8a1d2e + //pages/index/index.html?orderid=[领取地址] + if (Regex.IsMatch(message, @"(?[^<]+)") || Regex.IsMatch(message, @"(.+?)")) + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_XMLMSG, data = new { to_wxid = wxid, xml = Common.XMLDispose(message.Replace("&", "&")) } }); + else + { + message = message.Replace("&", "&"); + var title = string.Empty; + var desc = string.Empty; + var url = string.Empty; + var image_url = string.Empty; + var reg = Regex.Match(message, @"(?<标题>[\w\W]+?)"); + if (reg.Success) title = reg.Groups["标题"].Value; + reg = Regex.Match(message, @"(?<介绍>[\w\W]+?)"); + if (reg.Success) desc = reg.Groups["介绍"].Value; + reg = Regex.Match(message, @"(?<链接>[\w\W]+?)"); + if (reg.Success) url = reg.Groups["链接"].Value; + reg = Regex.Match(message, @"(?<图片链接>[\w\W]+?)"); + if (reg.Success) image_url = reg.Groups["图片链接"].Value; + + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_LINKMSG, data = new { to_wxid = wxid, title = $"{title.XMLReplace()}", desc = $"{desc.XMLReplace()}", url = url.XMLReplace(), image_url = image_url.XMLReplace() } }); + } + } + else + { + var atUsername = new List(); + var regs = Regex.Matches(message, @"\[@([^\]]+?)\]"); + var flag = true; + if (wxid.Contains("@chatroom")) + { + //[@wujiahua0876]你懂得,我只是测试一下 + + foreach (Match item in regs) + { + atUsername.Add(item.Groups[1].Value.Trim()); + } + if (atUsername.Count != 0) + { + flag = false; + message = Regex.Replace(message, @"(\[@[^\]]+?\])", "{$@}"); + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CHATROOM_ATMSG, data = new { to_wxid = wxid, content = message, at_list = atUsername.ToArray() } }); + } + } + if (flag) + { + message = Regex.Replace(message, @"(\[@[^\]]+?\])", ""); + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_TEXTMSG, data = new { to_wxid = wxid, content = message } }); + } + } + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 获取朋友圈 + /// + /// + public override void FindCircles(string circleId, string username) + { + try + { + if (!string.IsNullOrWhiteSpace(username)) + { + #region 获取指定用户朋友圈数据 + try + { + if (!User.GetUserCircles.ContainsKey(username)) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_TIMELINE_USER_MSG, data = new { username = username, first_page_md5 = "", max_id = circleId } }); + SendWeChatData(User.DwClientId, json); + } + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(30); + do + { + if (User.GetUserCircles.ContainsKey(username)) + { + var res = User.GetUserCircles[username]; + + #region 修正数据格式 + var jsonDic = HttpExtend.JsonToDictionary(res); + var data = jsonDic["data"] as Dictionary; + //var firstPageMd5 = data["firstPageMd5"].ToString(); + //var data = new { FirFirstPageMd5 = firstPageMd5, SnsObjectsCount = long.Parse(HttpExtend.GetTimeStamp()), }; + + var cirCleInfoOriList = new List(); + if (data.ContainsKey("objectList")) + { + var objectList = data["objectList"] as ArrayList; + if (objectList != null && objectList.Count != 0) + { + for (int i = 0; i < objectList.Count; i++) + { + var obj = JsonConvert.SerializeObject(objectList[i]); + if (obj != null) + { + var cInfo = JsonConvert.DeserializeObject(obj); + if (cInfo != null) + { + cirCleInfoOriList.Add(cInfo); + } + } + } + cirCleInfoOriList = cirCleInfoOriList.OrderByDescending(f => f.createTime).ToList(); + + List> _objs = new List>(); + + for (int i = 0; i < cirCleInfoOriList.Count; i++) + { + var tmp = HttpHelper.ObjectToJson(cirCleInfoOriList[i]); + var dic = HttpExtend.JsonToDictionary(tmp); + _objs.Add(dic); + } + } + } + #endregion + if (cirCleInfoOriList != null && cirCleInfoOriList.Count != 0) + return HttpHelper.ObjectToJson(new { data = new { objectList = new List() { cirCleInfoOriList[0] } } }); + return string.Empty; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleData; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + throw ex; + } + finally + { + User.GetUserCircles.Remove(username); + } + #endregion + } + else + { + #region 朋友圈首页 + if (!User.IsGetCircle) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_TIMELINE_MSG, data = new { max_id = circleId } }); + SendWeChatData(User.DwClientId, json); + User.IsGetCircle = true; + } + + var result = Task.Factory.StartNew(delegate () + { + Thread.Sleep(1000); + DateTime end_time = DateTime.Now.AddSeconds(30); + do + { + if (!User.IsGetCircle) + { + return User.CircleData; + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleData; + msg.Data = result; + + socketClient.Send(msg); + #endregion + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 自动授权登录小程序 + /// + /// + public override void AutoAuthMiniAPPLogin(string appid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_AUTO_AUTH_MINIAPP_LOGIN, data = new { appid = appid } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (User.AutoAuthLoginMiNiApps.ContainsKey(appid)) + { + return User.AutoAuthLoginMiNiApps[appid]; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvMiniAppCode; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 发送朋友圈 + /// + /// + public override void SendCircle(string xmlmsg) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_POST_MSG, data = new { object_desc = xmlmsg } }); + User.SendCircleId = string.Empty; + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (!string.IsNullOrWhiteSpace(User.SendCircleId)) + { + return User.SendCircleId; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleReturnId; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + finally + { + User.SendCircleId = string.Empty; + } + } + + /// + /// 发送朋友圈评论 + /// + /// + /// + public override void SendCircleComment(string circleId, string content) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_COMMENT_MSG, data = new { object_id = circleId, content = content } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 朋友圈点赞 + /// + /// 朋友圈的object_id + public override void SendCirclePraise(string circleId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_LIKE_MSG, data = new { object_id = circleId } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 朋友圈上传本地图片,返回上传以后返回的地址 + /// + /// + public override void CircleUpLoadImage(string data) + { + try + { + var path = string.Empty; + Bitmap bitmap = null; + if (data.StartsWith("http", StringComparison.CurrentCultureIgnoreCase)) + { + HttpHelper http = new HttpHelper(); + var item = http.GetItem(data); + item.ResultType = CsharpHttpHelper.Enum.ResultType.Byte; + + using (MemoryStream ms = new MemoryStream(http.GetHtml(item).ResultByte)) + { + using (Image mImage = Image.FromStream(ms, true)) + { + bitmap = new Bitmap(mImage); + path = HttpExtend.MapFile($@"Cache\{DateTime.Now.ToString("MMddhhmmssfff")}.{Common.GetImageExt(bitmap)}"); + bitmap.Save(path); + bitmap.Dispose(); + } + } + } + else + { + bitmap = Common.ConvertBase64ToImage(data); + using (MemoryStream stream = new MemoryStream()) + { + bitmap.Save(stream, ImageFormat.Jpeg); + byte[] data1 = new byte[stream.Length]; + stream.Seek(0, SeekOrigin.Begin); + stream.Read(data1, 0, Convert.ToInt32(stream.Length)); + bitmap = Common.CompressionImage(new MemoryStream(data1), 25); + } + + path = HttpExtend.MapFile($@"Cache\{DateTime.Now.ToString("MMddhhmmssfff")}.{Common.GetImageExt(bitmap)}"); + + bitmap.Save(path); + bitmap.Dispose(); + } + + if (!string.IsNullOrWhiteSpace(path) && File.Exists(path)) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_UPLOAD_IMAGE_MSG, data = new { path = path } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(60); + do + { + if (User.UpLoadImages.ContainsKey(path)) + { + return User.UpLoadImages[path]; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleUploadImageUrl; + msg.Data = result; + + socketClient.Send(msg); + } + else + { } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendFile(string wxid, string file) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_FILEMSG, data = new { to_wxid = wxid, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendImage(string wxid, string file) + { + try + { + if (file.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + byte[] ImangByte = null; + string extension = Path.GetExtension(file); + extension = string.IsNullOrWhiteSpace(extension) ? ".jpg" : extension; + ImangByte = new System.Net.WebClient().DownloadData(file); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), extension); + if (!File.Exists(path)) + { + File.WriteAllBytes(path, ImangByte); + } + if (File.Exists(path)) + file = path; + } + else + { + if (!File.Exists(file)) + { + if (Common.IsBase64(file)) + { + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), "jpg"); + if (Common.Base64ToFileAndSave(file, path) && File.Exists(path)) + { + file = path; + } + } + else + { } + } + } + var json = string.Empty; + if (file.Trim().EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase)) + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_GIFMSG, data = new { to_wxid = wxid, file = file } }); + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMGMSG, data = new { to_wxid = wxid, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendVideo(string wxid, string file) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_VIDEOMSG, data = new { to_wxid = wxid, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void AgreeAddMe(string text) + { + try + { + var v1 = string.Empty; + var v2 = string.Empty; + var scene = 0; + + var reg = Regex.Match(text, @"encryptusername=\""([^""]+?)\"""); + if (reg.Success) + v1 = reg.Groups[1].Value; + reg = Regex.Match(text, @"ticket=\""([^""]+?)\"""); + if (reg.Success) + v2 = reg.Groups[1].Value; + reg = Regex.Match(text, @"scene=\""([^""]+?)\"""); + if (reg.Success) + scene = int.Parse(reg.Groups[1].Value); + + LogHelper.GetSingleObj().Info("------", $"v1 = {v1} v2 = {v1} scene = {scene}"); + + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_FRIEND_MSG, data = new { v1 = v1, v2 = v2, scene = scene } }); + //var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_FRIEND_MSG, data = new { v1 = v1, v2 = v2 } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendCard(string to_wxid, string card_wxid) + { + try + { + var json = string.Empty; + if (card_wxid.Contains("@chatroom")) + //json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_INVITE_TO_ROOM_REQ_MSG, data = new { room_wxid = card_wxid, member_list = new string[] { to_wxid } } }); + { + InviteMemberToRoom_40Up(card_wxid, to_wxid); + return; + } + else + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CARDMSG, data = new { to_wxid = to_wxid, card_wxid = card_wxid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 创建群 + /// + /// + public override void CreateRoom(string wxidData) + { + try + { + if (string.IsNullOrWhiteSpace(wxidData)) return; + var wxids = wxidData.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (wxids == null || wxids.Length == 0) return; + + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CREATE_ROOM_MSG, data = wxids }); + SendWeChatData(User.DwClientId, json); + + var wxidstmp = wxids.ToList(); + wxidstmp.Add(User.Wxid); + wxidstmp.Sort(StringComparer.CurrentCulture); + + var md5Text = Common.GetMD5(string.Join(",", wxidstmp)); + + var result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(15); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[md5Text]; + if (item != null) + { + try + { + cache.Remove(md5Text); + } + catch (Exception ex) + { } + return item.ToString(); + } + } while (awaitTime >= DateTime.Now); + return string.Empty; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CreateRoom(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCreateRoom; + msg.GroupId = result; + msg.MemberTotal = wxidstmp.Count - 1; + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + + + + } + + public override void InviteMemberToRoom_40Up(string groupid, string wxidData) + { + try + { + if (string.IsNullOrWhiteSpace(wxidData)) return; + var wxids = wxidData.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (wxids != null && wxids.Length != 0) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_INVITE_TO_ROOM_REQ_MSG, data = new { room_wxid = groupid, member_list = wxids } }); + SendWeChatData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void InviteMemberToRoom_40Down(string groupid, string wxidData) + { + try + { + if (string.IsNullOrWhiteSpace(wxidData)) return; + var wxids = wxidData.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (wxids != null && wxids.Length != 0) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_INVITE_TO_ROOM_MSG, data = new { room_wxid = groupid, member_list = wxids } }); + SendWeChatData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".._."); + } + } + + public override void DeleteRoomMember(string wxid, string room) + { + try + { + if (room.Contains("@chatroom") || room.Contains("@im.chatroom")) + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DEL_ROOM_MEMBER_MSG, data = new { room_wxid = room, member_list = new string[] { wxid } } }); + SendWeChatData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void DecryptImage(string src_file, string dest_file) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DECRYPT_IMG_MSG, data = new { src_file = src_file, dest_file = dest_file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void PayTransferConfirm(string data) + { + try + { + var transferid = string.Empty; + var dic = HttpExtend.JsonToDictionary(data); + if (dic.ContainsKey("Transferid")) + transferid = dic["Transferid"].ToString(); + + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_WCPAY_MSG, data = new { transferid = transferid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void DeleteFriend(string wxid) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DEL_FRIEND_MSG, data = new { wxid = wxid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void EditCotacts(string wxid, string remark) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_FRIEND_REMARK_MSG, data = new { wxid = wxid, remark = remark } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void StateOpt(string wxid, int status) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_CHAT_SESSION_TOP_MSG, data = new { wxid = wxid, status = status } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static bool IsZombizRun = false; + + internal void GetZombiz()//这个方法临时用,以后修改 (不应该用休眠的) + { + if (IsZombizRun) return; + try + { + IsZombizRun = true; + + GetContact(); + var flag = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + if (!User.IsGetFriend) + return true; + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return false; + }).Result; + + var friends = User.Friends.Where(f => !f.wxid.Contains("@chatroom") && f.is_zombie == -1).ToList(); + foreach (var item in friends) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CARD_XMLMSG, data = new { to_wxid = item.wxid, xml = @" ".Replace("[wxid]", item.wxid).Replace("[name]", ".") } }); + var u = User.Friends.FirstOrDefault(f => f.wxid == item.wxid); + if (u != null && u.is_zombie == -1) + { + SendWeChatData(User.DwClientId, json); + Thread.Sleep(800 + new Random().Next(100, 200)); + } + } + + //#region 发送xx + //var nmss = new List>(); + //var mis = new List(); + //var count = 30; + //var rem = friends.Count % count; + //var num = friends.Count / count; + + //for (int i = 0; i < friends.Count; i++) + //{ + // mis.Add(friends[i]); + // if (mis.Count >= count) + // { + // nmss.Add(mis); + // mis = new List(); + // } + // else if (nmss.Count == num && mis.Count == rem) + // { + // nmss.Add(mis); + // } + //} + //var user = WechatClient.GetUser(User.DwClientId, WechatType.Xiaoxie); + //if (user == null) return; + //var socketClient = EasySoc.GetSocket(); + //foreach (var item in nmss) + //{ + // var msg = new WechatContact(); + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + + // msg.Cmd = PCRobotCMD.rcvContactList; + // msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", item } }); + + // socketClient.Send(msg); + // Thread.Sleep(5); + //} + //#endregion + + } + catch (Exception) + { } + finally + { + IsZombizRun = false; + } + } + + public override void GetContact() + { + try + { + //获取好友列表(数据库读取) + //var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_FRIENDS_MSG, data = new { } }); + //SendWeChatData(User.DwClientId, json); + Task.Run(() => + { + GetFriendInfos(); + }); + + Thread.Sleep(1000); + + //获取群列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOMS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetContact(bool isUpdate) + { + try + { + var result = GetFriendInfos(true); + + var socketClient = EasySoc.GetSocket(); + CommonResult msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvFriendList; + msg.Data = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + /// + /// 获取好友列表 + /// + /// 刷新缓存数据 + /// + //public override List GetFriendInfos(bool flushGroupsCache = false) + public override string GetFriendInfos(bool flushGroupsCache = false) + { + List friends = null; + try + { + #region 获取缓存数据 + friends = User.Friends.Where(f => !f.wxid.Contains("@chatroom")).ToList(); + if (!flushGroupsCache && friends.Count != 0) + return JsonConvert.SerializeObject(friends); + #endregion + + if (!User.IsGetFriend) + { + //获取好友列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_FRIENDS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + User.IsGetFriend = true; + } + + var result_ = Task.Factory.StartNew>(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (!User.IsGetFriend) + { + friends = User.Friends.Where(f => !f.wxid.Contains("@chatroom")).ToList(); + return friends; + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + return JsonConvert.SerializeObject(friends); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "#__#"); + } + return string.Empty; + } + + /// + /// 获取群列表 + /// + public override void GetGroupsNotInMember() + { + try + { + //获取群列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOMS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + Thread.Sleep(4000); + var groups = User.Friends.Where(f => f.wxid.Contains("@chatroom")).ToList(); + return groups == null ? string.Empty : HttpHelper.ObjectToJson(new Dictionary>() { { "data", groups } }); + }).Result; + + if (result == null) + result = HttpHelper.ObjectToJson(new Dictionary>() { { "data", User.Friends.Where(f => f.wxid.Contains("@chatroom")).ToList() } }); + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 通过用户id查询用户 + /// + /// + public override void GetWxidInfo(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_WXID_MSG, data = new { wxid = wxid } }); + var u = User.Friends.FirstOrDefault(f => f.wxid == wxid); + if (u == null) + { + SendWeChatData(User.DwClientId, json); + var friend = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + u = User.Friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) return u; + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + var socketClient = EasySoc.GetSocket(); + WechatContact msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = u == null ? string.Empty : HttpHelper.ObjectToJson(u); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 通过群号查询指定的用户 + /// + /// 要查询群号 + /// 要查询的用户 + public override void GetGroupAndFriendInfo(string groupId, string wxid) + { + try + { + GroupInfo group = null; + FriendInfo u = null; + if (groupId.Contains("@chatroom") || groupId.Contains("@im.chatroom")) + { + var g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + } + + if (group == null) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = groupId } }); + SendWeChatData(User.DwClientId, json); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + { + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + if (group == null) group = new GroupInfo() { wxid = groupId, friends = new List() { new FriendInfo() { wxid = wxid } }, total_member = 1 }; + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 通过群号查询指定的用户 + /// + /// 要查询群号 + /// 要查询的用户 + public override void GetGroupAndFriendInfo(string groupId, string wxid, bool flush = false) + { + try + { + GroupInfo group = null; + FriendInfo u = null; + if (groupId.Contains("@chatroom") || groupId.Contains("@im.chatroom")) + { + var g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + if (flush) + { + g.friends.Clear(); + UpdateGroupInfo(groupId); + Thread.Sleep(100); + } + else + { + u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + } + } + + if (group == null) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = groupId } }); + SendWeChatData(User.DwClientId, json); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + { + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + if (group == null) group = new GroupInfo() { wxid = groupId, friends = new List() { new FriendInfo() { wxid = wxid } }, total_member = 1 }; + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + public override void UpdateWxidInfo(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_UPDATE_WXID_MSG, data = new { wxid = wxid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void UpdateGroupInfo(string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_UPDATE_ROOM_MEMBER_MSG, data = new { wxid = groupId } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetFriend(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_WXID_MSG, data = new { wxid = wxid } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 浏览器 + /// + //public void MtOpenBrowserMsg(string url) + //{ + // try + // { + // var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_OPEN_BROWSER_MSG, data = new { url = url } }); + // SendWeChatData(this.User.DwClientId, json); + // } + // catch (Exception ex) + // { + // LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + // } + //} + + public override void CloseWechat(string message) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == User.DwClientId && f.Value.Type == WechatType.Xiaoxie).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"CloseWechat事件退出,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v, true); + if (!string.IsNullOrWhiteSpace(message)) + PCRobotForm.ErrorMessAction?.Invoke(message); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 检测URL在微信中是否有效 + /// + /// 要检测的网址 + public override void CheckUrl(string url) + { + try + { + url = url.Trim(); + if (!string.IsNullOrWhiteSpace(url)) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CHECK_URL_STATUS_MSG, data = new { url = url } }); + SendWeChatData(this.User.DwClientId, json); + } + var result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + //if (CheckUrlCache.ContainsKey(url)) return CheckUrlCache[url]; + Cache cache = HttpRuntime.Cache; + object item = cache[url]; + if (item != null) + return int.Parse(item.ToString()); + } while (awaitTime >= DateTime.Now); + return -1; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CheckUrl(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCheckUrl; + msg.Status = result; + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void OpenUrl(string url) + { + try + { + url = url.Trim(); + if (!string.IsNullOrWhiteSpace(url)) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_OPEN_BROWSER_MSG, data = new { url = url } }); + SendWeChatData(this.User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + /// + /// 清理历史聊天记录 + /// + /// + public override void ClearChatHistoryMsg() + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CLEAR_CHAT_HISTORY_MSG, data = new { } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 设置会话已读 + /// + /// + public override void SetSessionReadedMsg(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SET_SESSION_READED_MSG, data = new { wxid = wxid } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 修改群聊名称 + /// + /// 新的群名 + /// 群id + public override void SetRoomName(string new_name, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_NAME_MSG, data = new { room_wxid = groupId, name = new_name } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 修改群公告(可用于@全体) + /// + /// 新公告 + /// 群聊wxid + public override void SetRoomNotice(string notice, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_NOTICE_MSG, data = new { room_wxid = groupId, notice = notice } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 设置自己在群中昵称 + /// + /// 要设置的昵称 + /// 需要设置的群id + public override void ModRoomMyName(string nickname, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_MEMBER_NAME_MSG, data = new { room_wxid = groupId, nickname = nickname } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 设置是否显示群成员昵称 + /// + /// true为开启 + /// 要显示得到群 + public override void SetRoomShowMemeberName(bool status, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_SHOW_NAME_MSG, data = new { room_wxid = groupId, status = status ? 1 : 0 } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 修改群聊名称 + /// + /// 新名称 + /// 群号 + public override void ModRoomName(string newnick, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_NAME_MSG, data = new { room_wxid = groupId, name = newnick } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 是否消息免打扰 + /// + /// true为开启 + /// wxid + public override void SetRecvNotify(bool status, string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_RECV_NOTIFY_MSG, data = new { wxid = wxid, status = status ? 1 : 0 } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 关注公众号 + /// + /// 公众号wxid + public override void AddPublicUser(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_ADD_PUBLIC_USER_MSG, data = new { wxid = wxid } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 开启/关闭防撤回功能 + /// + /// 1是开启防撤回,0是关闭 + public override void SetDisableRevoke(bool status) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DISABLE_REVOKE_MSG, data = new { status = status ? 1 : 0 } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + + #region 内部类 + + /// + /// 文件是否暂用 + /// + /// + private static bool DeletePJFile() + { + var isZanYong = false; + var path2 = HttpExtend.MapPath("PCWechat\\" + Version); + + var name1 = "Fix.dll"; + var name2 = "msimg32.dll"; + //if (!Environment.Is64BitOperatingSystem) + //{ + // #region 32位系统 + // name1 = "libcurl.dll"; + // name2 = "libcurlOrg.dll"; + // #endregion + //} + + var fixName = HttpExtend.MapFile(name1, path2); + var msimgName = HttpExtend.MapFile(name2, path2); + try + { + if (File.Exists(fixName)) + File.Delete(fixName); + if (File.Exists(msimgName)) + File.Delete(msimgName); + } + catch (Exception ex) + { + isZanYong = true; + } + return isZanYong; + } + + /// + /// 是否替换 + /// + private static bool IsReplace = false; + /// + /// pj文件需要杀死进程,并替换文件 + /// + public static void PJFileReplace() + { + //if (IsReplace) return; + //IsReplace = true; + //try + //{ + // KillPc(true); + + // var path2 = HttpExtend.MapPath("PCWechat\\" + Version); + // var fixName = HttpExtend.MapFile("Fix.dll", path2); + // var msimgName = HttpExtend.MapFile("msimg32.dll", path2); + // if (!Environment.Is64BitOperatingSystem) + // { + // #region 32位系统 + // //var fixName = HttpExtend.MapFile("libcurl.dll", path2); + // //var msimgName = HttpExtend.MapFile("libcurlOrg.dll", path2); + // //Util.WriteResource(fixName, Resources.libcurl); + // //Util.WriteResource(msimgName, Resources.libcurlOrg); + // Util.WriteResource(fixName, Resources.Fix_32); + // Util.WriteResource(msimgName, Resources.msimg32_32); + // #endregion + // } + // else + // { + // #region 64位系统 + // //var fixName = HttpExtend.MapFile("Fix.dll", path2); + // //var msimgName = HttpExtend.MapFile("msimg32.dll", path2); + // Util.WriteResource(fixName, Resources.Fix); + // Util.WriteResource(msimgName, Resources.msimg32); + // #endregion + // } + //} + //catch (Exception ex) + //{ + // throw ex; + //} + //finally + //{ + // IsReplace = true; + //} + } + + public enum MsgType : ushort + { + /// + /// DEBUG消息 + /// + MT_DEBUG_LOG = 11024, + /// + /// 登录消息 + /// + MT_USER_LOGIN = 11025, + /// + /// 注销消息 + /// + MT_USER_LOGOUT = 11026, + /// + /// 数据库查询消息 + /// + MT_SQL_QUERY = 11027, + /// + /// 获取我的信息消息 + /// + MT_DATA_OWNER_MSG = 11028, + /// + /// 获取单个好友消息 + /// + MT_DATA_WXID_MSG = 11029, + /// + /// 获取好友列表消息 + /// + MT_DATA_FRIENDS_MSG = 11030, + /// + /// 获取群聊列表消息 + /// + MT_DATA_CHATROOMS_MSG = 11031, + /// + /// 获取群成员消息 + /// + MT_DATA_CHATROOM_MEMBERS_MSG = 11032, + /// + /// 获取公众号消息 + /// + MT_DATA_PUBLICS_MSG = 11033, + /// + /// 从网络更新单个好友信息消息 + /// + MT_UPDATE_WXID_MSG = 11034, + /// + /// 从网络更新群成员信息消息 + /// + MT_UPDATE_ROOM_MEMBER_MSG = 11035, + /// + /// 发送文本消息 + /// + MT_SEND_TEXTMSG = 11036, + /// + /// 发送群@消息 + /// + MT_SEND_CHATROOM_ATMSG = 11037, + /// + /// 发送名片消息 + /// + MT_SEND_CARDMSG = 11038, + /// + /// 发送链接消息 + /// + MT_SEND_LINKMSG = 11039, + /// + /// 发送图片消息 + /// + MT_SEND_IMGMSG = 11040, + /// + /// 发送文件消息 + /// + MT_SEND_FILEMSG = 11041, + /// + /// 发送视频消息 + /// + MT_SEND_VIDEOMSG = 11042, + /// + /// 发送GIF消息 + /// + MT_SEND_GIFMSG = 11043, + /// + /// 接收文本消息 + /// + MT_RECV_TEXT_MSG = 11046, + /// + /// 接收图片消息 + /// + MT_RECV_PICTURE_MSG = 11047, + /// + /// 接收语音消息 + /// + MT_RECV_VOICE_MSG = 11048, + /// + /// 接收申请好友消息 + /// + MT_RECV_FRIEND_MSG = 11049, + /// + /// 接收名片消息 + /// + MT_RECV_CARD_MSG = 11050, + /// + /// 接收视频消息 + /// + MT_RECV_VIDEO_MSG = 11051, + /// + /// 接收表情消息 + /// + MT_RECV_EMOJI_MSG = 11052, + /// + /// 接收位置消息 + /// + MT_RECV_LOCATION_MSG = 11053, + /// + /// 接收链接消息 + /// + MT_RECV_LINK_MSG = 11054, + /// + /// 接收文件消息 + /// + MT_RECV_FILE_MSG = 11055, + /// + /// 接收小程序消息 + /// + MT_RECV_MINIAPP_MSG = 11056, + /// + /// 接收好友转账消息 + /// + MT_RECV_WCPAY_MSG = 11057, + /// + /// 接收系统消息 + /// + MT_RECV_SYSTEM_MSG = 11058, + /// + /// 接收撤回消息 + /// + MT_RECV_REVOKE_MSG = 11059, + /// + /// 接收其他未知消息 + /// + MT_RECV_OTHER_MSG = 11060, + /// + /// 接收应用类型未知消息 + /// + MT_RECV_OTHER_APP_MSG = 11061, + /// + /// 发送加好友消息 + /// + MT_ADD_FRIEND_MSG = 11062, + /// + /// 发送修改好友备注消息 + /// + MT_MOD_FRIEND_REMARK_MSG = 11063, + /// + /// 发送删除好友消息 + /// + MT_DEL_FRIEND_MSG = 11064, + /// + /// 发送同意加好友申请消息 + /// + MT_ACCEPT_FRIEND_MSG = 11065, + /// + /// 发送接收好友转帐消息 + /// + MT_ACCEPT_WCPAY_MSG = 11066, + /// + /// 发送同意进群邀请消息 + /// + MT_ACCEPT_ROOM_MSG = 11067, + /// + /// 发送创建群聊消息 + /// + MT_CREATE_ROOM_MSG = 11068, + /// + /// 发送邀请好友进群消息,40人以下 + /// + MT_INVITE_TO_ROOM_MSG = 11069, + /// + /// 发送邀请好友进群消息,40人以上 + /// + MT_INVITE_TO_ROOM_REQ_MSG = 11070, + /// + /// 发送删除群成员消息 + /// + MT_DEL_ROOM_MEMBER_MSG = 11071, + /// + /// 发送修改群名称消息 + /// + MT_MOD_ROOM_NAME_MSG = 11072, + /// + /// 发送修改群通知消息 + /// + MT_MOD_ROOM_NOTICE_MSG = 11073, + /// + /// 发送修改我在本群的昵称消息 + /// + MT_MOD_ROOM_MEMBER_NAME_MSG = 11074, + /// + /// 发送修改显示群昵称消息 + /// + MT_MOD_ROOM_SHOW_NAME_MSG = 11075, + /// + /// 发送保存到联系人消息 + /// + MT_SAVE_ROOM_TO_CONTACT_MSG = 11076, + /// + /// 发送退出并删除群消息 + /// + MT_QUIT_DEL_ROOM_MSG = 11077, + /// + /// 发送消息免打扰消息 + /// + MT_MOD_RECV_NOTIFY_MSG = 11078, + /// + /// 发送置顶消息 + /// + MT_MOD_CHAT_SESSION_TOP_MSG = 11079, + /// + /// 发送无痕清粉消息 + /// + MT_ZOMBIE_CHECK_MSG = 11080, + /// + /// 发送自动同意好友申请消息 + /// + MT_AUTO_ACCEPT_FRIEND_MSG = 11081, + /// + /// 发送自动同意好友转帐消息 + /// + MT_AUTO_ACCEPT_WCPAY_MSG = 11082, + /// + /// 发送自动进群邀请消息 + /// + MT_AUTO_ACCEPT_ROOM_MSG = 11083, + /// + /// 发送自动加名片消息 + /// + MT_AUTO_ACCPET_CARD_MSG = 11084, + /// + /// 发送解密图片消息 + /// + MT_DECRYPT_IMG_MSG = 11085, + /// + /// 发送打开浏览器消息 + /// + MT_OPEN_BROWSER_MSG = 11086, + /// + /// 获取用户登录二维码,于2019年5月28日新增 + /// + MT_RECV_QRCODE_MSG = 11087, + /// + /// 窗口变化通知消息 + /// + MT_WX_WND_CHANGE_MSG = 11088, + /// + /// 发送和获取未读数量变动消息 + /// + MT_UNREAD_MSG_COUNT_CHANGE_MSG = 11089, + /// + /// 与指定人聊天 + /// + MT_TO_CHAT_MSG = 11090, + /// + /// 当前聊天对象改变 + /// + MT_TALKER_CHANGE_MSG = 11091, + /// + /// 通过二维码进群 + /// + MT_ACCEPT_QRCODE_ROOM_MSG = 11092, + /// + /// 单向加好友 + /// + MT_ACCEPT_ONEWAY_FRIEND_MSG = 11093, + /// + /// 设置微信版本号 + /// + MT_CUSTOM_WX_VERSION_MSG = 11094, + /// + /// 接收到二微码付款消息 + /// + MT_RECV_QRCODE_WCPAY_MSG = 11095, + /// + /// 通过手机号/微信号/QQ号查询联系人 + /// + MT_SEARCH_CONTACT_MSG = 11096, + /// + /// 添加通过手机号/微信号/QQ号查询的联系人 + /// + MT_ADD_SEARCH_CONTACT_MSG = 11097, + /// + /// 群成员新增通知 + /// + MT_ROOM_ADD_MEMBER_NOTIFY_MSG = 11098, + /// + /// 群成员删除通知 + /// + MT_ROOM_DEL_MEMBER_NOTIFY_MSG = 11099, + /// + /// 通过接口创建群聊的通知 + /// + MT_ROOM_CREATE_NOTIFY_MSG = 11100, + /// + /// 退群或被踢通知 + /// + MT_ROOM_DEL_NOTIFY_MSG = 11101, + /// + /// 联系人新增通知 + /// + MT_CONTACT_ADD_NOITFY_MSG = 11102, + /// + /// 联系人删除通知 + /// + MT_CONTACT_DEL_NOTIFY_MSG = 11103, + /// + /// 注销登录 + /// + MT_QUIT_LOGIN_MSG = 11104, + /// + /// 无需确认退出 + /// + MT_QUIT_WECHAT_MSG = 11105, + /// + /// 当点击微信托盘图标和未读消息时消息 + /// + MT_TRAYICON_SHOW_WINDOW_MSG = 11106, + /// + /// 退还朋友的转账 + /// + MT_REFUSE_FRIEND_WCPAY_MSG = 11107, + /// + /// 清除聊天记录 + /// + MT_CLEAR_CHAT_HISTORY_MSG = 11108, + /// + /// 获取收藏列表 + /// + MT_DATA_FAVITEMS_MSG = 11109, + /// + /// 发送收藏 + /// + MT_SEND_FAVITEM_MSG = 11110, + /// + /// 收藏指定消息 + /// + MT_ADD_FAVITEM_FROM_MSG = 11111, + /// + /// 语音翻译 + /// + MT_TRANS_VOICE_MSG = 11112, + /// + /// 发送XML消息 + /// + MT_SEND_XMLMSG = 11113, + /// + /// 发送名版XML消息 + /// + MT_SEND_CARD_XMLMSG = 11114, + /// + /// 关注公众号 + /// + MT_ADD_PUBLIC_USER_MSG = 11115, + /// + /// 转发小程序 + /// + MT_FORWARD_APP_MSG = 11118, + /// + /// 开启/关闭防撤回消息 + /// + MT_DISABLE_REVOKE_MSG = 11121, + /// + /// 设置会话为已读 + /// + MT_SET_SESSION_READED_MSG = 11122, + /// + /// 检测URL在微信中是否有效 + /// + MT_CHECK_URL_STATUS_MSG = 11123, + /// + /// 微信二维码识别 + /// + MT_SCAN_QRCODE_IMG_MSG = 11127, + /// + /// 自动授权登录小程序 + /// + MT_SNS_AUTO_AUTH_MINIAPP_LOGIN = 11136, + /// + /// 获取朋友圈首页 + /// + MT_SNS_TIMELINE_MSG = 11145, + /// + /// 评论 + /// + MT_SNS_COMMENT_MSG = 11146, + /// + /// 点赞 + /// + MT_SNS_LIKE_MSG = 11147, + /// + /// 发朋友圈 + /// + MT_SNS_POST_MSG = 11148, + /// + /// 朋友圈上传图片 + /// + MT_SNS_UPLOAD_IMAGE_MSG = 11149, + /// + /// 获取指定用户的朋友圈 + /// + MT_SNS_TIMELINE_USER_MSG = 11150, + } + + enum _EnRawMsgType + { + /// + /// 0x1 文本 + /// + WX_MSG_TEXT = 1, + /// + /// 0x3 图片 + /// + WX_MSG_PICTURE = 3, + /// + /// 0x22 语音 + /// + WX_MSG_VOICE = 34, + /// + /// 0x25 加好友请求 "from_wxid" : "fmessage" + /// + WX_MSG_FRIEND = 37, + /// + /// 0x2A 名片 + /// + WX_MSG_CARD = 42, + /// + /// 0x2B 视频 + /// + WX_MSG_VIDEO = 43, + /// + /// 0x2F 表情 + /// + WX_MSG_EMOJI = 47, + /// + /// 0x30 位置 + /// + WX_MSG_LOCATION = 48, + /// + /// 0x31 应用类型,子类型参考EnRawAppMsgType + /// + WX_MSG_APP = 49, + /// + /// 0x2710 系统消息 + /// + WX_MSG_SYSTEM = 10000, + /// + /// 0x2712 撤回消息 + /// + WX_MSG_REVOKE = 10002, + } + //EnRawMsgType; + // XML XPATH路径 /msg/appmsg/type/text() + enum _EnRawAppMsgType + { + /// + /// 链接(包含群邀请) + /// + WX_APPMSG_LINK = 5, + /// + /// 文件 + /// + WX_APPMSG_FILE = 6, + /// + /// 合并消息 + /// + WX_APPMSG_MUTIL = 19, + /// + /// 小程序 + /// + WX_APPMSG_MINIAPP = 33, + /// + /// 转帐 + /// + WX_APPMSG_WCPAY = 2000, + } + //EnRawAppMsgType; + #endregion + + } +} diff --git a/PCRobot/PCWechat/Wechat_Xiaoxie.cs b/PCRobot/PCWechat/Wechat_Xiaoxie.cs new file mode 100644 index 0000000..6f05de0 --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Xiaoxie.cs @@ -0,0 +1,3747 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Utils; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; + +namespace PCRobot.PCWechat +{ + ///// + ///// 参考文档: + ///// https://www.showdoc.cc/wxtool + ///// https://www.showdoc.cc/WeApiUltimate + ///// 密码:784615627. + ///// + + public class Wechat_Xiaoxie : BaseApi + { + public delegate void OnEvent(string Name, string Message); + public static OnEvent ClickEvent; + + #region 静态函数 + public static void Install() + { + if (IsInstall) return; + + #region 自动登录新建设备信息,注册表开关 + try + { + if (Version == "3.4.0.38") + { + string Winrarpath = @"Software\Tencent\WeChat"; + string key = "FakeDeviceId"; + //yes为开,no为关 + RegistryHelper.SetRegistryKey("HKEY_CURRENT_USER", Winrarpath, key, "no"); + RegistryHelper.GetRegistryValue(Winrarpath, key); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("自动登录新建设备信息", $"注册表操作异常:{ex.Message} - {ex.StackTrace}"); + } + #endregion + + ClickEvent?.Invoke("开始登录", "正在检测已登录微信,请稍等...."); + try + { + //Thread.Sleep(5000); + //DllPath = HttpExtend.MapFile($"WeChatHelper_{Version}.dll", "Bin"); + m_AcceptCallbackFunc = WxAcceptCallback; + m_RecvCallbackFunc = WxRecvCallback; + m_CloseCallbackFunc = WxCloseCallback; + UseUtf8(); + // 初始化Callback + InitWeChatSocket(m_AcceptCallbackFunc, m_RecvCallbackFunc, m_CloseCallbackFunc); + + DllPath = HttpExtend.MapFile($"WeChatHelper_{Version}.dll", "Bin"); + KillPc(true); + } + catch (Exception) + { + + } + finally + { + IsInstall = true; + ClickEvent?.Invoke("登录完成", ""); + } + } + + private static string DllPath; + /// + /// 微信WeChatWin.dll基址 + /// + //private static IntPtr BaseAddress; + + public delegate void AcceptCallbackFunc(uint dwClientId); + public delegate void RecvCallbackFunc(uint dwClientId, IntPtr intPtr, uint dwSize); + public delegate void CloseCallbackFunc(uint dwClientId); + private static AcceptCallbackFunc m_AcceptCallbackFunc; + private static RecvCallbackFunc m_RecvCallbackFunc; + private static CloseCallbackFunc m_CloseCallbackFunc; + + // 引入DLL导出函数 + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool InitWeChatSocket(AcceptCallbackFunc acceptCallback, + RecvCallbackFunc recvCallback, CloseCallbackFunc closeCallback); + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChat(byte[] strDllPath); + //[DllImport("Bin\\WeChatServer.dll")] + //public static extern bool SetLoginWxid(byte[] szWxid); + + //BOOL __stdcall UseUtf8(); + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool UseUtf8(); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool GetUserWeChatVersion(StringBuilder v); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChat2(byte[] dllPath, byte[] wechatPath); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChatMultiOpen(byte[] dllPath, byte[] wechatPath); + + [DllImport("Bin\\WeChatServer.dll", EntryPoint = "SendWeChatData")] + public static extern bool _SendWeChatData(uint dwClienId, byte[] strJsonData); + public bool SendWeChatData(uint dwClienId, string strJsonData) + { + try + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试发送", $"{dwClienId} -> {strJsonData}"); + if (User != null && !string.IsNullOrEmpty(User.Wxid)) + { + var json = HttpExtend.JsonToDictionary(strJsonData); + var type = json["type"].ToString(); + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return false; + switch (msgType) + { + //截取发送消息 - 为是否是辅助输入提供判断 + case MsgType.MT_SEND_TEXTMSG: + case MsgType.MT_SEND_CHATROOM_ATMSG: + case MsgType.MT_SEND_CARDMSG: + case MsgType.MT_SEND_XMLMSG: + case MsgType.MT_SEND_IMGMSG: + case MsgType.MT_SEND_FILEMSG: + case MsgType.MT_SEND_VIDEOMSG: + case MsgType.MT_SEND_GIFMSG: + { + json = json["data"] as Dictionary; + string to_wxid = json["to_wxid"].ToString(); + string message = string.Empty; + if (json.ContainsKey("content")) message = json["content"].ToString(); + else if (json.ContainsKey("card_wxid")) message = json["card_wxid"].ToString(); + else if (json.ContainsKey("xml")) message = json["xml"].ToString(); + else if (json.ContainsKey("file")) message = json["file"].ToString(); + if (!string.IsNullOrEmpty(message)) + Common.SetCache(User.Wxid, to_wxid, message); + } + break; + } + } + return _SendWeChatData(dwClienId, Encoding.UTF8.GetBytes(strJsonData)); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, $"{ex.Message} - {ex.StackTrace}"); + } + return false; + } + + //[DllImport("Bin\\WeChatServer.dll")] + [DllImport("Bin\\WeChatServer.dll")] + public static extern bool DestroyWeChat(); + + [DllImport("Bin\\WeChatServer.dll")] + public static extern uint InjectWeChatPid(int dwPid, byte[] dllPath); + + /// + /// 卸载安装 + /// + public static void UnInstall() + { + try + { + DestroyWeChat(); + LogHelper.GetSingleObj().Info(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "卸载成功"); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + // 注入成功回调 + static void WxAcceptCallback(uint dwClientId) + { + LogHelper.GetSingleObj().Info(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, "注入成功:" + dwClientId); + Console.WriteLine("注入成功:" + dwClientId); + } + + #region 微信版本基础变量 + + //private const string Version = "2.9.5.41"; + //private const int PcOffSet = 0x1769E00;//2.9.5.41 + //private const string PcMd5 = "194F44DF80553326711A4F576FE7166E";//2.9.5.41 + + //private const string Version = "3.3.0.93"; + //private const int PcOffSet = 0x1DAEB90;//3.3.0.93 + //private const string PcMd5 = "5EE8A5B9D4EE63BE1813632D8A7B2E77";//3.3.0.93 + + private const string Version = "3.4.0.38"; + private const int PcOffSet = 0x1DEE968;//3.4.0.38 + private const string PcMd5 = "AB0916C9949178A786192B188892AE2C";//3.4.0.38 + #endregion + + public override string GetVersion() + { + return Version; + } + + /// + /// 杀死注入 pc + /// + /// + private static void KillPc(bool isInject = false) + { + Process[] MyProcesses = Process.GetProcesses(); + + var path1 = HttpExtend.MapPath("PCWechat"); + var path2 = HttpExtend.MapPath("PCWechat\\" + Version); + //var path3 = HttpExtend.MapPath("PCWechat\\" + "3.3.0.93");//退出上个版本的微信 + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == "WECHAT" && MyProcess.MainModule.FileName.StartsWith(path1)) + { + try + { + #region 退掉这个版本的微信 + //if (MyProcess.MainModule.FileName.StartsWith(path3)) + //{ + // try + // { + // LogHelper.GetSingleObj().Info("主动Q", "版本不对杀死进程:" + MyProcess.Id); + // MyProcess.Kill(); + // } + // catch (Exception) + // { } + //} + #endregion + + //判断微信版本 + if (MyProcess.MainModule.FileName.StartsWith(path2)) + { + var id = MyProcess.Id; + if (isInject) + { + var result = Task.Factory.StartNew(delegate + { + try + { + var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + return false; + } + else + { + LogHelper.GetSingleObj().Info("系统", $"开始注入进程:{id}..."); + uint uin = InjectWeChatPid(id, Encoding.UTF8.GetBytes(DllPath)); + LogHelper.GetSingleObj().Info("系统", $"注入成功:{id},句柄ID:{uin}"); + return true; + } + } + catch (Exception) + { + } + return false; + }).Wait(30000); + if (!result) + { + try + { + LogHelper.GetSingleObj().Info("系统c", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + else + { + try + { + LogHelper.GetSingleObj().Info("主动d", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + Thread.Sleep(10); + } + + } + catch (Exception) + { } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } + + public static uint StartWechat(string wxid, bool isError = false) + { + var path = string.Empty; + + var WechatWinFile = HttpExtend.MapFile("WeChatWin.dll", $"PCWechat\\" + Version); + var md5 = Common.GetMD5Hash(WechatWinFile); + if (!File.Exists(WechatWinFile) || md5.ToUpper() != PcMd5.ToUpper()) + { + if (isError) throw new Exception("易转发客户端微信版本不支持,请登录易转发端手动处理"); + var rst = MessageBox.Show("您的微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + var f = new WechatUpdate(Version); + f.ShowDialog(); + if (!f.IsOk) return 0; + } + else return 0; + } + path = HttpExtend.MapFile("WeChat.exe", $"PCWechat\\" + Version); + + //WechatLoginHelper.BeginLogin(wxid); + + //var ss = SetLoginWxid(Encoding.UTF8.GetBytes("")); + //返回dwClientId + var pid = InjectWeChat2(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + + //WechatLoginHelper.ClickLogin((int)pid); + + return pid; + + //return InjectWeChatMultiOpen(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + } + + /// + /// 远程登录微信 + /// + public static List RemoteLoginCodes = new List(); + + /// + /// 是否在获取二维码 + /// + private static string RemoteCache = "get_login_code_cache"; + + private static readonly object Friend_Lock = new object(); + + /// + /// pc微信登录二维码 + /// + /// + public static void LoginQrcode(string wxid, string ServerMsgID) + { + try + { + RemoteLoginCode result = null; + try + { + StartWechat(wxid, true); + } + catch (Exception ex) + { + result = new RemoteLoginCode() { pid = -1, rType = RobotType.客户端微信, b64Md5 = ex.Message }; + } + + if (result == null) + { + result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[RemoteCache]; + if (item != null) + { + cache.Remove(RemoteCache); + var r = item as RemoteLoginCode; + return r; + } + } while (awaitTime >= DateTime.Now); + return null; + }).Result; + } + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = string.Empty; + msg.RobotUsernick = string.Empty; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvLoginCode; + msg.Data = result == null ? string.Empty : JsonConvert.SerializeObject(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 等待登录结果 + /// + public static Dictionary WaitLoginResult = new Dictionary(); + + // 接收消息回调 + static void WxRecvCallback(uint dwClient, IntPtr intPtr, uint dwSize) + { + try + { + byte[] body = new byte[dwSize]; + Marshal.Copy(intPtr, body, 0, body.Length); + var recvData = Encoding.UTF8.GetString(body).Replace("\0", "").Trim();//再转成UTF8 + if (WechatClient.IsDebug) LogHelper.GetSingleObj().Debug("调试收到文本消息", $"{dwClient} -> {recvData}\r\n"); + + //Console.WriteLine($"{dwClient} -> {recvData}\r\n"); + + var dwClientid = dwClient; + Task.Factory.StartNew(delegate () + { + try + { + //Console.WriteLine("收到消息:" + recvData); + var json = HttpExtend.JsonToDictionary(recvData); + var type = json["type"].ToString(); + + var data = json.ContainsKey("data") ? json["data"] as Dictionary : null; + + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return; + + if (PCRobotForm.AnalysisTypes != null && PCRobotForm.AnalysisTypes.Count != 0) + { + if (PCRobotForm.AnalysisTypes.FirstOrDefault(f => f == msgType.ToString().ToUpper()) == null) + return; + } + + switch (msgType) + { + case MsgType.MT_SEND_XMLMSG: + break; + case MsgType.MT_DECRYPT_IMG_MSG: + break; + case MsgType.MT_DEBUG_LOG: + break; + case MsgType.MT_RECV_QRCODE_MSG: + { + //{"data":{"code":"http://weixin.qq.com/x/A98qrQOk3qB6L_fWPtxF","file":"C:\\Users\\????006\\AppData\\Local\\Temp\\qrcF451.tmp","pid":24088},"type":11087} + if (!data.ContainsKey("file")) return; + var file = data["file"].ToString(); + + var reg = Regex.Match(file, @"Temp\\(?<文件名>[a-z0-9A-Z]+.tmp)", RegexOptions.IgnoreCase); + if (reg.Success) + { + var codeFile = HttpExtend.MapFile($"{reg.Groups["文件名"].Value}", Path.GetTempPath()); + if (File.Exists(codeFile)) + { + var pid = int.Parse(data["pid"].ToString()); + var codeFilePng = Path.ChangeExtension(codeFile, "png"); + try + { + if (File.Exists(codeFilePng)) + File.Delete(codeFilePng); + File.Move(codeFile, codeFilePng); + if (File.Exists(codeFilePng)) + { + var cfBase64 = Common.ConvertImageToBase64(Image.FromFile(codeFilePng)); + + var codeInfo = new RemoteLoginCode() { pid = pid, cImgB64 = cfBase64, b64Md5 = HttpHelper.ToMD5(cfBase64), rType = RobotType.客户端微信, t = HttpExtend.GetTimeStamp(DateTime.Now) }; + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[RemoteCache]; + cache.Insert(RemoteCache, codeInfo, null, DateTime.Now.AddSeconds(3), Cache.NoSlidingExpiration); + + RemoteLoginCodes.Add(codeInfo); + } + } + catch (Exception) + { } + } + } + } + break; + case MsgType.MT_USER_LOGIN://登陆消息 + { + WechatLoginHelper.EndBinginLogin(); + + var wxid = data["wxid"].ToString(); + var user = WechatClient.GetUser(wxid, dwClientid, WechatType.Xiaoxie); + user.Nickname = data["nickname"].ToString(); + user.HeaderUrl = data["avatar"].ToString(); + user.DBFile = data["wx_user_dir"].ToString(); + user.Pid = int.Parse(data["pid"].ToString()); + user.Phone = data["phone"].ToString(); + user.Uin = GetUin(user.Pid); + + WechatClient.OnRefUserEvent(user, WaitLoginResult); + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试登录", $"{wxid} - {user}"); + } + break; + case MsgType.MT_USER_LOGOUT: + { + var wxid = data["wxid"].ToString(); + var user = WechatClient.Users.FirstOrDefault(f => f.Key == wxid).Value; + if (user != null) + { + LogHelper.GetSingleObj().Info("系统", $"LogOut事件退出,Uin:{user.Uin},微信:{user.Nickname}({wxid})"); + WechatClient.RemoveUser(user); + } + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试注销", $"{wxid} - {user}"); + } + break; + case MsgType.MT_SQL_QUERY: + break; + case MsgType.MT_DATA_OWNER_MSG: + break; + case MsgType.MT_DATA_WXID_MSG: + { + //{"data":{"account":"MOKA_1314_","avatar":"http://wx.qlogo.cn/mmhead/ver_1/UKuQPgzLzEY0UPqTgmqpSibLmx1BMibAlwJxOp4t8QksClGJP8tLHxUiaBDAax1Vf0Eiae6wKBIoT3ibAgOYTuuWiaVDiaiayiaaIZF46LcE5aBvTtSQ/132","city":"Chengdu","country":"CN","nickname":"进销存","province":"Sichuan","remark":"","sex":2,"wxid":"wxid_va4xpj22"},"type":11029} + + lock (Friend_Lock) + { + var wxid = data["wxid"]?.ToString(); + if (Common.IsGzh(wxid, WechatClient.IsGzh)) return; + + var f = new FriendInfo(); + + f.account = data["account"]?.ToString(); + f.wxid = wxid; + f.nickname = data["nickname"]?.ToString(); + f.remark = data["remark"]?.ToString(); + f.avatar = data["avatar"]?.ToString(); + f.city = data["city"]?.ToString(); + f.country = data["country"]?.ToString(); + f.province = data["province"]?.ToString(); + f.sex = int.Parse(data["sex"]?.ToString()); + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend != null) + if (!user.Friends.TryTake(out friend)) return; + user.Friends.Add(f); + } + } + break; + case MsgType.MT_DATA_FRIENDS_MSG: + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client = WechatClient.GetApi(user) as Wechat_Xiaoxie; + if (!user.IsGetFriend) return; + try + { + var _data = json.ContainsKey("data") ? json["data"] as ArrayList : null; + if (_data == null) return; + + for (int i = 0; i < _data.Count; i++) + { + var item = _data[i] as Dictionary; + + var wxid = item["wxid"]?.ToString(); + + if (Common.IsGzh(wxid, WechatClient.IsGzh)) continue; + + var f = new FriendInfo(); + f.wxid = wxid; + f.account = item["account"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.sex = int.Parse(item["sex"]?.ToString()); + f.city = item["city"]?.ToString(); + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + user.Friends.Add(f); + } + } + catch (Exception ex) + { } + finally + { + user.IsGetFriend = false; + } + } + break; + case MsgType.MT_DATA_CHATROOMS_MSG: + { + if (data == null) + { + lock (Friend_Lock) + { + //{"data":[{"avatar":"http://wx.qlogo.cn/mmcrhead/iahdQicCC5VBRq5vMm7FxlfPct57WiadZ0NEnMUeicvXyS0fh73Hibw0QkkDMw9RQMETbWENFia9NQlmpibkH0bKsOothztfu8waTFy/0","is_manager":0,"manager_wxid":"wxid_yeh4ssxdjpqv12","member_list":["wxid_yeh4ssxdjpqv12","wujiahua0876","wxid_aiwyq8o6iqja12","wxid_lzssz365bwl222"],"nickname":"成都测试群","total_member":4,"wxid":"24444455370@chatroom"}],"type":11031} + + + var _data = json.ContainsKey("data") ? json["data"] as ArrayList : null; + if (_data == null) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + for (int i = 0; i < _data.Count; i++) + { + Thread.Sleep(1000); + //{"avatar":"http://wx.qlogo.cn/mmcrhead/00GYaClAoOpPmXm2NY7u8dZ0mXndbaJvesrlr88KhsUXaPTGvDE8Rt5wpSv9qtHLZJSIHLNBbxEhwFBnbV9FmE6O2fAmlMW1/0","is_manager":0,"manager_wxid":"wzm881101","member_list":["wzmdd2562","wxid_axvwtp4221","huih2861","a30432165487","wangs381015","wxid_vy1kfbt22","wiujihcj056"],"nickname":"吃卤蛋不吐卤蛋壳群","total_member":7,"wxid":"6975286487@chatroom"} + + var item = _data[i] as Dictionary; + var f = new FriendInfo(); + + f.avatar = item["avatar"]?.ToString(); + f.wxid = item["wxid"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.remark = item["nickname"]?.ToString(); + + f.manager_wxid = item["manager_wxid"]?.ToString(); + f.is_manager = int.Parse(item["is_manager"]?.ToString()); + f.member_list = string.Join(",", (string[])(item["member_list"] as ArrayList).ToArray(typeof(string))); + + var group = user.Groups.FirstOrDefault(z => z.wxid == f.wxid); + if (group == null) + { + //群不存在,去获取群成员信息 + var _json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = f.wxid } }); + _SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + + group = new GroupInfo() { wxid = f.wxid, nickname = f.nickname, avatar = f.avatar, total_member = f.member_list.Length, friends = new List() }; + user.Groups.Add(group); + } + else + group.total_member = f.member_list.Length; + + var friend = user.Friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + user.Friends.Add(f); + } + } + } + } + break; + case MsgType.MT_DATA_CHATROOM_MEMBERS_MSG: + { + lock (Friend_Lock) + { + var group_wxid = data["group_wxid"].ToString(); + var total = data["total"].ToString(); + var member_list = data["member_list"] as ArrayList; + if (member_list == null) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + var group = user.Groups.FirstOrDefault(z => z.wxid == group_wxid); + if (group == null) + { + group = new GroupInfo() { wxid = group_wxid, total_member = member_list.Count, friends = new List() }; + user.Groups.Add(group); + } + else + group.total_member = member_list.Count; + + for (int i = 0; i < member_list.Count; i++) + { + //{"account":"","avatar":"http://wx.qlogo.cn/mmhead/ver_1/klibauQfLYtmfniaYAzsV9l6V4cSHmdDhniaTmJ6aGo0z035JTkB5QWrOUbAPnJnP4YXTMuKKmwNBMNv2Fbj5ia9icNicYeXGXbbsRiagGFKryASro/132","city":"","country":"","nickname":"陈建","province":"","remark":"","sex":0,"wxid":"wxid_e1j30jf2k5zdk022"} + + var item = member_list[i] as Dictionary; + + var f = new FriendInfo(); + f.account = item["account"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.city = item["city"]?.ToString(); + f.country = item["country"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.province = item["province"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = int.Parse(item["sex"]?.ToString()); + f.wxid = item["wxid"]?.ToString(); + + var friend = group.friends.FirstOrDefault(z => z.wxid == f.wxid); + if (friend == null) + group.friends.Add(f); + } + } + + #region xx + + //List> nmss = new List>(); + //List mis = new List(); + //var count = 20; + //var rem = member_list.Count % count; + //var num = member_list.Count / count; + + //for (int i = 0; i < member_list.Count; i++) + //{ + // var item = member_list[i] as Dictionary; + + // var account = item["account"]?.ToString(); + // var avatar = item["avatar"]?.ToString(); + // var city = item["city"]?.ToString(); + // var country = item["country"]?.ToString(); + // var nickname = item["nickname"]?.ToString(); + // var province = item["province"]?.ToString(); + // var remark = item["remark"]?.ToString(); + // var sex = item["sex"]?.ToString(); + // var wxid = item["wxid"]?.ToString(); + + // nmWxidInfo MemberInfo = new nmWxidInfo(); + // MemberInfo.Wxid = wxid; + // MemberInfo.WxNo = account; + // MemberInfo.Nick = nickname; + // MemberInfo.Mark = remark; + // MemberInfo.HeadIMG = avatar; + // mis.Add(MemberInfo); + // if (mis.Count >= count) + // { + // nmss.Add(mis); + // mis = new List(); + // } + // else if (nmss.Count == num && mis.Count == rem) + // { + // nmss.Add(mis); + // } + + //} + //var socketClient = EasySoc.GetSocket(); + //var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + //if (user == null) return; + //foreach (var item in nmss) + //{ + // WechatGroupMember msg = new WechatGroupMember(); + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + + // msg.Cmd = PCRobotCMD.rcvGroupMember; + + // nmGroupInfo group = new nmGroupInfo(); + // group.Count = int.Parse(total); + // group.GroupID = group_wxid; + // group.List = item; + // msg.Message = HttpHelper.ObjectToJson(new Dictionary() { { "data", group } }); + + // socketClient.Send(msg); + // Thread.Sleep(5); + //} + #endregion + + } + break; + case MsgType.MT_DATA_PUBLICS_MSG: + { + + } + break; + case MsgType.MT_UPDATE_WXID_MSG: + { + + } + break; + case MsgType.MT_UPDATE_ROOM_MEMBER_MSG: + { + + + } + break; + case MsgType.MT_RECV_LINK_MSG: + { + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试收到链接", $"{dwClientid} -> {recvData}"); + + var is_pc = data["is_pc"]?.ToString(); + var from_wxid = data["from_wxid"].ToString(); + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + var wx_sub_type = int.Parse(data["wx_sub_type"].ToString()); + + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + //if (!string.IsNullOrWhiteSpace(raw_msg)) + //{ + // var reg = Regex.Match(raw_msg, "(?<链接>.*)"); + // if (reg.Success) + // { + // raw_msg = reg.Groups["链接"].Value; + // } + //} + + var socketClient = EasySoc.GetSocket(); + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (room_wxid.Contains("@chatroom")) + wmsg.FromGroupid = room_wxid; + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = ass.fromNick; + wmsg.FromMessage = raw_msg; + + socketClient.Send(wmsg); + } + break; + case MsgType.MT_RECV_TEXT_MSG: + { + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试收到文本消息", $"{dwClientid} -> {recvData}"); + + var at_user_list = data["at_user_list"] as ArrayList; + var from_wxid = data["from_wxid"].ToString(); + var msg = data["msg"].ToString(); + + var msg_temp = string.Copy(msg); + #region 替换@里面的用户昵称 + if (at_user_list != null && at_user_list.Count != 0) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client_temp = WechatClient.GetApi(user) as Wechat_Xiaoxie; + foreach (string username in at_user_list) + { + var firent = user.Friends.FirstOrDefault(f => f.wxid == username); + if (firent == null) + { + client_temp.GetWxidInfo(username); + Thread.Sleep(1000); + firent = user.Friends.FirstOrDefault(f => f.wxid == username); + } + if (firent != null) + msg_temp = msg_temp.Replace("@" + firent.nickname + " ", "{$@}"); + } + } + #endregion + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + var socketClient = EasySoc.GetSocket(); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, msg_temp)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + msg_temp); + return; + } + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (room_wxid.Contains("@chatroom") || room_wxid.Contains("@im.chatroom")) + { + wmsg.FromGroupid = room_wxid; + wmsg.FromUsername = from_wxid; + wmsg.FromUsernick = from_wxid == ass.robotName ? ass.robotNick : string.Empty; + } + else + { + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = ass.fromNick; + } + wmsg.FromMessage = msg; + + socketClient.Send(wmsg); + + //从网络上下载群成员(刷新) + //var _json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_UPDATE_ROOM_MEMBER_MSG, data = new { room_wxid = "24444455370@chatroom" } }); + //_SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + //获取群成员列表 + //var _json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = "24444455370@chatroom" } }); + //_SendWeChatData(dwClientid, Encoding.UTF8.GetBytes(_json)); + } + break; + case MsgType.MT_ZOMBIE_CHECK_MSG: + { + //if (data == null) return; + //if (data.ContainsKey("errcode")) + //{ + // var status = int.Parse(data["status"].ToString()); + // var wxid = data["wxid"].ToString(); + + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // var firend = user.Friends.FirstOrDefault(f => f.wxid == wxid); + // if (firend == null) return; + // firend.is_zombie = status; + //} + } + break; + case MsgType.MT_SEND_CARD_XMLMSG: + { + + } + break; + case MsgType.MT_RECV_PICTURE_MSG: + case MsgType.MT_RECV_VOICE_MSG: + case MsgType.MT_RECV_FRIEND_MSG: + case MsgType.MT_RECV_CARD_MSG: + case MsgType.MT_RECV_VIDEO_MSG: + case MsgType.MT_RECV_EMOJI_MSG: + case MsgType.MT_RECV_LOCATION_MSG: + case MsgType.MT_RECV_FILE_MSG: + { + var from_wxid = data["from_wxid"].ToString(); + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + var room_wxid = data["room_wxid"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = int.Parse(data["wx_type"].ToString()); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + var socketClient = EasySoc.GetSocket(); + + if (wx_type == 3 || wx_type == 34 || wx_type == 43 || wx_type == 49)//图片、语音、视频、文件 + { + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client = WechatClient.GetApi(user); + + WechatReceiveMsg msg = new WechatReceiveMsg(); + msg.Cmd = PCRobotCMD.rcvFile; + msg.IsSend = false; + if (wx_type == 3)//图片 + { + //var image_thumb = data["image_thumb"].ToString(); + var image = data["image"].ToString(); + + #region 等待下载 + long size = -1L; + var reg = Regex.Match(raw_msg, @"hdlength=\""(\d+?)\"""); + if (reg.Success) + size = long.Parse(reg.Groups[1].Value); + else + { + reg = Regex.Match(raw_msg, @"\slength=\""(\d+?)\"""); + if (reg.Success) + size = long.Parse(reg.Groups[1].Value); + else + { } + } + var waitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + var size_temp = new FileInfo(image).Length; + if (File.Exists(image) && size == size_temp) + break; + } while (waitTime >= DateTime.Now); + #endregion + + msg.Cmd = PCRobotCMD.rcvImg; + + msg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + + var path = Common.CacheFilePath(ass.robotName, ass.fromName, "IMAGE", data["msgid"].ToString(), "jpg"); + + #region 等待图片解密 + //int i = 0; + //do + //{ + // i++; + // client.DecryptImage(image, path); + // var failureTime = DateTime.Now.AddSeconds(2); + // do + // { + // Thread.Sleep(200); + // if (File.Exists(path)) break; + // } while (failureTime >= DateTime.Now); + // if (File.Exists(path)) + // break; + //} while (4 >= i); + + DecodeImage(image, byte.Parse(data["xor_key"].ToString()), path); + if (!string.IsNullOrWhiteSpace(path) && File.Exists(path)) + { } + else + path = image; + #endregion + + msg.FromMessage = $"[图片={path}]"; + msg.FromMessageType = WechatMsgType.图片; + msg.FileCDNXML = raw_msg; + } + else if (wx_type == 34)//语音 + { + //msg.FromMessage = string.Empty;//$"[语音={FilePath}]";//TODO 语音文件 + //msg.FromMessageType = WechatMsgType.语音; + return; + } + else if (wx_type == 43)//视频 + { + //var video = data["video"].ToString(); + //msg.FromMessage = $"[视频={video}]"; + //msg.FromMessageType = WechatMsgType.视频; + return; + } + else if (wx_type == 49)//文件 + { + //msg.FromMessage = string.Empty;//$"[文件={FilePath}]";//TODO 文件 + //msg.FromMessageType = WechatMsgType.文件; + return; + } + + msg.IsSend = false; + msg.RobotUsername = ass.robotName; + msg.RobotUsernick = ass.robotNick; + msg.RobotType = RobotType.客户端微信; + + if (room_wxid.Contains("@chatroom")) + msg.FromGroupid = room_wxid; + + msg.FromUsername = from_wxid; + //msg.FromUsernick = string.Empty;//TODO 昵称没有获取 + + socketClient.Send(msg); + } + else if (wx_type == 37)//接收到好友申请请求 + { + WechatApplyFriend wXApply = new WechatApplyFriend(); + wXApply.Cmd = PCRobotCMD.applyFriend; + wXApply.RobotUsername = to_wxid; + wXApply.RobotUsernick = WechatClient.GetUser(to_wxid)?.Nickname; + wXApply.RobotType = RobotType.客户端微信; + + var reg = Regex.Match(raw_msg, @"content=""(?<申请文本>[^""]*?)"""); + if (reg.Success) + wXApply.Message = reg.Groups["申请文本"].Value; + + reg = Regex.Match(raw_msg, @"sourceusername=""(?<账号>[^""]*?)"" sourcenickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + { + wXApply.OldFriendWxid = reg.Groups["账号"].Value; + wXApply.OldFriendNick = reg.Groups["昵称"].Value; + } + reg = Regex.Match(raw_msg, @"fromusername=""(?<账号>[^""]*?)"""); + if (reg.Success) + { + if (!string.IsNullOrWhiteSpace(reg.Groups["账号"].Value)) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + else + { + reg = Regex.Match(raw_msg, @"alias=""(?<账号>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + } + } + reg = Regex.Match(raw_msg, @"fromnickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendNick = reg.Groups["昵称"].Value; + + wXApply.Token = raw_msg;//TODO 这里好像要获取raw_msg 中 v1的值 + + socketClient.Send(wXApply); + } + //名片 + else if (wx_type == 42) { } + //接收表情 + else if (wx_type == 47) { } + //接收位置消息 + else if (wx_type == 48) { } + } + break; + case MsgType.MT_RECV_WCPAY_MSG: + { + var from_wxid = data["from_wxid"].ToString(); + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var raw_msg = data["raw_msg"].ToString(); + var to_wxid = data["to_wxid"].ToString(); + var wx_type = data["wx_type"].ToString(); + var wx_sub_type = data["wx_sub_type"].ToString(); + + var socketClient = EasySoc.GetSocket(); + if (raw_msg.IndexOf("微信转账") != -1 && raw_msg.IndexOf("收到转账") != -1) + { + string State = Common.StringMid(raw_msg, "", ""); + string Transid = Common.StringMid(raw_msg, "transferid>"); + int dwTime = 0; + int.TryParse(Common.StringMid(raw_msg, ""), out dwTime); + if (State == "1" && Transid != string.Empty) + { + WechatReicevePay reicevePay = new WechatReicevePay(); + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + reicevePay.RobotUsername = user.Wxid; + reicevePay.RobotUsernick = user.Nickname; + reicevePay.RobotType = RobotType.客户端微信; + reicevePay.FromUsername = from_wxid; + reicevePay.FromUsernick = string.Empty;//TODO 没有获取昵称 + reicevePay.Cmd = PCRobotCMD.receivePay; + reicevePay.Invalidtime = dwTime.ToString(); + reicevePay.Transferid = Transid; + var reg = Regex.Match(raw_msg, "收到转账(?<金额>.+)元"); + if (reg.Success) + reicevePay.Money = double.Parse(reg.Groups["金额"].Value); + if (reicevePay.RobotUsernick == null) reicevePay.RobotUsernick = string.Empty; + socketClient.Send(reicevePay); + return; + } + } + } + break; + case MsgType.MT_RECV_SYSTEM_MSG: + { + //{"data":{"from_wxid":"wxid_lzssz365bwl222","is_pc":0,"msgid":"9071106463111673540","raw_msg":"\"先森吳\"邀请\"查优惠小助手(语馨)\"加入了群聊","room_wxid":"24444455370@chatroom","timestamp":1585398781,"to_wxid":"24444455370@chatroom","wx_type":10000},"type":11058} + + if (data != null && data.ContainsKey("raw_msg")) + { + var socketClient = EasySoc.GetSocket(); + var raw_msg = data["raw_msg"].ToString(); + var room_wxid = data["room_wxid"].ToString(); + var from_wxid = data["from_wxid"].ToString(); + + //新人入群 + if (!string.IsNullOrWhiteSpace(room_wxid) && room_wxid.Contains("@chatroom")) + { + //var reg1 = Regex.Match(raw_msg, @"""(?<邀请人昵称>.*)""邀请""(?<新人昵称>.*)""加入了群聊"); + //var reg2 = Regex.Match(raw_msg, @"你邀请""(?<新人昵称>.*)""加入了群聊"); + //var reg3 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描""(?<邀请人昵称>.*)""分享的二维码加入群聊"); + //var reg4 = Regex.Match(raw_msg, @"""(?<新人昵称>.*)""通过扫描你分享的二维码加入群聊"); + + //if (reg1.Success || reg2.Success || reg3.Success || reg4.Success) + //{ + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // if (user == null) + // return; + // WechatNewMemer newMember = new WechatNewMemer(); + // newMember.Cmd = PCRobotCMD.newMember; + // newMember.RobotType = RobotType.客户端微信; + // newMember.RobotUsername = user.Wxid; + // newMember.RobotUsernick = user.Nickname; + + // if (reg1.Success) + // { + // newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg1.Groups["新人昵称"].Value; + // } + // else if (reg2.Success) + // { + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg2.Groups["新人昵称"].Value; + // } + // else if (reg3.Success) + // { + // newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg3.Groups["新人昵称"].Value; + // } + // else if (reg4.Success) + // { + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg4.Groups["新人昵称"].Value; + // } + + // if (room_wxid.Contains("@chatroom")) + // { + // newMember.GroupId = room_wxid; + // newMember.GroupNick = string.Empty; + // } + // socketClient.Send(newMember); + //} + } + else//新增好友 + { + //#region 添加好友成功 + //var reg1 = Regex.Match(raw_msg, "^你已添加了(.*?),现在可以开始聊天了。$"); + //var reg2 = Regex.Match(raw_msg, "^(.*?)刚刚把你添加到通讯录,现在可以开始聊天了。$"); + //if (reg1.Success || reg2.Success) + //{ + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + // if (user == null) + // return; + // WechatNewFriend msg = new WechatNewFriend(); + // msg.Cmd = PCRobotCMD.newfriend; + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + // msg.FromUserName = from_wxid; + // msg.FromUserNick = reg1.Success ? reg1.Groups[1].Value : reg2.Groups[1].Value; + // socketClient.Send(msg); + //} + //#endregion + + #region 检测僵尸粉 + //{"data":{"from_wxid":"wujiahua0876","is_pc":0,"msgid":"3624674612069828076","raw_msg":"先森吳开启了朋友验证,你还不是他(她)朋友。请先发送朋友验证请求,对方验证通过后,才能聊天。发送朋友验证","room_wxid":"","timestamp":1585125257,"to_wxid":"wxid_lzssz365bwl222","wx_type":10000},"type":11058} + + //{"data":{"from_wxid":"wxid_89qxkbyaxrok22","is_pc":0,"msgid":"7401397021380323657","raw_msg":"消息已发出,但被对方拒收了。","room_wxid":"","timestamp":1603436524,"to_wxid":"wujiahua0876","wx_type":10000},"type":11058} + if (raw_msg.Contains("开启了朋友验证") || raw_msg.Contains("但被对方拒收了"))//这里说明是僵尸粉 + { + LogHelper.GetSingleObj().Debug("调试清粉", $"{JsonConvert.SerializeObject(data)}"); + + var wxid = data["from_wxid"].ToString(); + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + var firend = user.Friends.FirstOrDefault(f => f.wxid == wxid); + if (firend == null) return; + if (raw_msg.Contains("但被对方拒收了")) + firend.is_zombie = 2;//拉黑了 + else + firend.is_zombie = 1;//单向好友 + + //var socketClient = EasySoc.GetSocket(); + WechatContact msg = new WechatContact(); + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", new List() { firend } } }); + + socketClient.Send(msg); + } + //{"data":{"from_wxid":"wxid_2ufntuf4purl22","is_pc":0,"msgid":"1580248074267233434","raw_msg":"由于名片类型或场景原因,暂不支持转发该名片。","room_wxid":"","timestamp":1585125880,"to_wxid":"wxid_lzssz365bwl222","wx_type":10000},"type":11058} + else if (raw_msg.Contains("暂不支持转发该名片"))//这里说明是好友 + { + LogHelper.GetSingleObj().Debug("调试清粉_", $"{JsonConvert.SerializeObject(data)}"); + + var wxid = data["from_wxid"].ToString(); + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + var firend = user.Friends.FirstOrDefault(f => f.wxid == wxid); + if (firend == null) return; + firend.is_zombie = 0; + } + else + { + + } + #endregion + } + } + } + break; + case MsgType.MT_RECV_REVOKE_MSG: + { + //私聊用户撤回消息 + //{"data":{"from_wxid":"wujiahua0876","is_pc":0,"msgid":"3768878978337666344","raw_msg":"\n\t\n\t\twujiahua0876\n\t\t1097101643\n\t\t5572791720720581005\n\t\t\n\t\n\n","room_wxid":"","timestamp":1586758499,"to_wxid":"wxid_lzssz365bwl222","wx_type":10002},"type":11059} + //私聊用户机器人自己撤回消息 + //{"data":{"from_wxid":"wxid_lzssz365bwl222","is_pc":0,"msgid":"1526645333654331593","raw_msg":"wujiahua087617163236505998900618590839539","room_wxid":"","timestamp":1586758971,"to_wxid":"wujiahua0876","wx_type":10002},"type":11059} + + var from_wxid = string.Empty; + if (data.ContainsKey("from_wxid")) + from_wxid = data["from_wxid"]?.ToString(); + var raw_msg = string.Empty; + if (data.ContainsKey("raw_msg")) + { + raw_msg = data["raw_msg"]?.ToString(); + } + var to_wxid = string.Empty; + if (data.ContainsKey("to_wxid")) + to_wxid = data["to_wxid"]?.ToString(); + + } + break; + case MsgType.MT_RECV_OTHER_MSG: + break; + case MsgType.MT_RECV_OTHER_APP_MSG: + case MsgType.MT_RECV_MINIAPP_MSG: + { + //if (WechatClient.IsDebug) + // LogHelper.GetSingleObj().Debug("调试收到小程序消息", $"{dwClientid} -> {recvData}"); + if (data == null) return; + + var wx_type = data["wx_type"]?.ToString();//微信原始类型,值为 49 + if (wx_type == "49") + { + var wx_sub_type = data["wx_sub_type"]?.ToString();//微信原始应用子类型,值为 36 + if (wx_sub_type == "1" || wx_sub_type == "36" || wx_sub_type == "33" || wx_sub_type == "3" || wx_sub_type == "19") + { + var from_wxid = data["from_wxid"]?.ToString();//发送者的wxid + + if (Common.IsGzh(from_wxid, WechatClient.IsGzh)) return; + + var is_pc = data["is_pc"]?.ToString(); + var raw_msg = data["raw_msg"]?.ToString(); + var msgid = data["msgid"]?.ToString();// 接收到的消息id + var room_wxid = data["room_wxid"]?.ToString();//群聊的wxid + var to_wxid = data["to_wxid"]?.ToString();//接收者的wxid + + var socketClient = EasySoc.GetSocket(); + if (!WechatClient.IsAuxiliaryInput(from_wxid, to_wxid, raw_msg)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + raw_msg); + return; + } + + var ass = WechatClient.IsAssistance(from_wxid, to_wxid, dwClientid); + if (ass.type == WechatClient.AssistanceType.终止) return; + + //if (!string.IsNullOrWhiteSpace(raw_msg)) + //{ + // var reg = Regex.Match(raw_msg, @"(?<链接>.*)"); + // if (reg.Success) + // raw_msg = reg.Groups["链接"].Value; + //} + + WechatReceiveMsg wmsg = new WechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt; + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + wmsg.RobotUsername = ass.robotName; + wmsg.RobotUsernick = ass.robotNick; + wmsg.RobotType = RobotType.客户端微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (room_wxid.Contains("@chatroom")) + { + wmsg.FromGroupid = room_wxid; + wmsg.FromUsername = from_wxid; + wmsg.FromUsernick = from_wxid == ass.robotName ? ass.robotNick : string.Empty; + } + else + { + wmsg.FromUsername = ass.fromName; + wmsg.FromUsernick = ass.fromNick; + } + wmsg.FromMessage = raw_msg; + + socketClient.Send(wmsg); + } + } + } + break; + case MsgType.MT_CHECK_URL_STATUS_MSG: + { + //if (CheckUrlCache.Count > 500) CheckUrlCache.Clear(); + //{"data":{"status":-2005,"url":"https://ycs9d.kuaizhan.com/?id=07E4060844959"},"type":11123} + if (data["status"] != null) + { + var url = data["url"]?.ToString(); + if (!string.IsNullOrWhiteSpace(url)) + { + //CheckUrlCache.Add(url.Trim(), int.Parse(data["status"].ToString())); + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[url.Trim()]; + cache.Insert(url.Trim(), int.Parse(data["status"].ToString()), null, DateTime.Now.AddSeconds(8), Cache.NoSlidingExpiration); + } + } + } + break; + //case MsgType.MT_CHECK_URL_STATUS2_MSG: + // { + + // if (data.ContainsKey("baseResponse")) + // { + // var baseResponse = data["baseResponse"] as Dictionary; + // if (baseResponse.ContainsKey("ret")) + // { + // var ret = baseResponse["ret"].ToString(); + // Cache cache = HttpRuntime.Cache; + // //查找 md5 的缓存,不存在则返回null + // object item = cache[url.Trim()]; + // cache.Insert(url.Trim(), int.Parse(ret), null, DateTime.Now.AddSeconds(8), Cache.NoSlidingExpiration); + // } + // } + // } + // break; + case MsgType.MT_ROOM_ADD_MEMBER_NOTIFY_MSG://群成员新增通知 + { + //{"data":{"avatar":"","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":[{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/MpicosfFj1KMvlSPoxWHjUfT2KGqJvEKrDkDCUiaQp4ryYkv3NMdsYofXUVvgalGx0ylia2swn2MMNWwiaWWEUl4QvQayM2Y28pAaxShUZUH5ms/132","invite_by":"wujiahua0876","nickname":"A083赚钱鸭💯(葫芦娃)","wxid":"wxid_5fn1vpyjpfj022"}],"nickname":"111111","room_wxid":"24466267291@chatroom","total_member":5},"type":11098} + + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + var avatar = data["avatar"].ToString();//头像 + var is_manager = data["is_manager"].ToString();// + var manager_wxid = data["manager_wxid"].ToString();//管理账号 + var room_nick = data["nickname"].ToString();//群昵称 + var room_wxid = data["room_wxid"].ToString();//群账号 + var total_member = int.Parse(data["total_member"].ToString());//群人数 + + var member_list = data["member_list"] as ArrayList; + if (member_list != null && member_list.Count != 0) + { + var member = member_list[0] as Dictionary; + var avatar_user = member["avatar"].ToString();//头像 + var invite_by = member["invite_by"].ToString();//邀请者wxid + var nickname = member["nickname"].ToString();//新用户昵称 + var wxid = member["wxid"].ToString();//新用户账号 + + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember; + newMember.RobotType = RobotType.客户端微信; + newMember.RobotUsername = user.Wxid; + newMember.RobotUsernick = user.Nickname; + + //if (reg1.Success) + //{ + // newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg1.Groups["新人昵称"].Value; + //} + //else if (reg2.Success) + //{ + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg2.Groups["新人昵称"].Value; + //} + //else if (reg3.Success) + //{ + // newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + // newMember.MemberNick = reg3.Groups["新人昵称"].Value; + //} + //else if (reg4.Success) + //{ + // newMember.SourceNick = newMember.RobotUsernick; + // newMember.MemberNick = reg4.Groups["新人昵称"].Value; + //} + + + newMember.SourceNick = string.Empty; + newMember.SourceName = (string.IsNullOrWhiteSpace(invite_by) || invite_by == user.Wxid) ? string.Empty : invite_by; + newMember.MemberNick = nickname; + newMember.MemberName = wxid; + newMember.GroupId = room_wxid; + newMember.GroupNick = room_nick; + newMember.TotalMember = total_member; + + socketClient.Send(newMember); + } + } + break; + case MsgType.MT_ROOM_DEL_MEMBER_NOTIFY_MSG://群成员删除/退出通知 + { + + } + break; + case MsgType.MT_ROOM_CREATE_NOTIFY_MSG://通过接口创建群聊的通知 + { + //{"data":{"avatar":"http://wx.qlogo.cn/mmcrhead/MvMkWKHbPUVricNicF781PXeuPMW2vHEywf6lkuMfLgHN4IlRAyPiaDX8AG9d9XEa1ibiaMXBr83ibDVmgCT70qkHXPN9SFn5iaHC7y/0","is_manager":1,"manager_wxid":"wxid_tnizkijej5uq22","member_list":[{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/CVGILsl6SCMBjjCuyxUOZXNRgeiaPx4EwT1WMqCDz9qp3XcuzuVm3SHuPuial3wOMVUSbbJujBtUqPkB3Uz1ruTVzibqZ74FTnBKibNCq67qBcE/132","invite_by":"wxid_tnizkijej5uq22","nickname":"小张晚安","wxid":"wxid_uwbxwbt4ihjd22"},{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/cstPo5zCEb794wfD44BbnoQicfDOeOzkB3BficFYticVmQy7umm4SArThiaia6f6ZJFriaewskJ3foyuxrEVYic7NicwXQ/132","invite_by":"wxid_tnizkijej5uq22","nickname":"先森吳","wxid":"wujiahua0876"},{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/tbfVwxp5B5WkAx7KxDCTia8kzWgMIj3bqA1QaoHxXvQTwS5aRw6h9WjTQMWBhD6fkt4XjUxURDDGF5aBek8xSnY4kqPIQ9T4oweMyaKLSwnM/132","invite_by":"","nickname":"Coco","wxid":"wxid_tnizkijej5uq22"}],"nickname":"","room_wxid":"24652183014@chatroom","total_member":3},"type":11100} + + if (data == null) return; + + var wxids = new List(); + var member_list = data["member_list"] as ArrayList; + for (int i = 0; i < member_list.Count; i++) + { + //{"avatar":"http://wx.qlogo.cn/mmhead/ver_1/CVGILsl6SCMBjjCuyxUOZXNRgeiaPx4EwT1WMqCDz9qp3XcuzuVm3SHuPuial3wOMVUSbbJujBtUqPkB3Uz1ruTVzibqZ74FTnBKibNCq67qBcE/132","invite_by":"wxid_tnizkijej5uq22","nickname":"小安","wxid":"wxid_uwbxwbt4ihjd22"} + + var m = member_list[i] as Dictionary; + if (m == null) continue; + wxids.Add(m["wxid"]?.ToString()); + } + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client = WechatClient.GetApi(user); + wxids.Sort(StringComparer.CurrentCulture); + + var md5Text = Common.GetMD5(string.Join(",", wxids)); + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[md5Text]; + cache.Insert(md5Text, data["room_wxid"].ToString(), null, DateTime.Now.AddSeconds(8), Cache.NoSlidingExpiration); + } + break; + case MsgType.MT_ROOM_DEL_NOTIFY_MSG://群成员删除通知 + { + + } + break; + case MsgType.MT_CONTACT_ADD_NOITFY_MSG://好友新增通知 + { + //{"data":{"account":"dx21101","avatar":"http://wx.qlogo.cn/mmhead/ver_1/we0fG4Y8r0NjN7GUSHFXCu0qicqZf2KKHBeRKIByBNAvvJ8KcgeaomwSju0AqUicJztS6oiaEzDVJiblnZmrJQTibDdPyk7fwzwPbS5JxwibS6POI/0","city":"","country":"","nickname":"秒单客-小张","remark":"","sex":1,"wxid":"wxid_g9r17s6hdb6w22"},"type":11102} + + var socketClient = EasySoc.GetSocket(); + //var account = data["account"].ToString();//新用户账号 + //var avatar = data["avatar"].ToString();//新用户头像 + var nickname = data["nickname"].ToString();//新用户昵称 + //var sex = int.Parse(data["sex"].ToString());//性别 + var wxid = data["wxid"].ToString();//新用户微信id + + #region 添加好友成功 + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var msg = new WechatNewFriend(); + msg.Cmd = PCRobotCMD.newfriend; + msg.RobotUsername = user.Wxid; + msg.RobotUsernick = user.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.FromUserName = wxid; + msg.FromUserNick = nickname; + socketClient.Send(msg); + + #endregion + } + break; + case MsgType.MT_CONTACT_DEL_NOTIFY_MSG://群成员删除通知 + { + + } + break; + case MsgType.MT_SNS_TIMELINE_MSG://获取朋友圈首页 + { + #region 数据 + //{"data":{"advertiseCount":1,"advertiseList":[{"adInfo":{"string":"\n\n\t51Hky7pHhu%2BI0D6z6NGPpR15cypIpKvA%2B/WmCm0cjdoElUITIAFetWDTQN4vCIoS6ghxwuN0AHfz/Dd5uv0MOe0BAnqUde7RfcpcLvnU4pKwzvPOf09bD57/YLjKvDkkbHks%2BFQ8yTrjpqCQtrqKXVDJrR%2B/6t2%2BIcLfsbPDz%2B6jDc8gjbkn6ADHUW7tOArlAowZ3aNCjtfk5fBHzow8vwBuatiNIeQQySyetV69UB2exOBcR42IFoB%2BgD0ygOTBlYMnaiQtzS0upkBl4NSPHN9xen3lITxROz3Bj6ZRkqrlzrEJjj%2B%2BX0NTbO/ZduF8Fnsq47hKzFn3RzMmrMiMmRT%2BiJpTD3Tz/rwtYsS3tGTCmbneafTW0o%2B9uinX5C2QK45tKlFSDlAlYqEtepY51N2mrvp5aK8wd1A1dotcSJdRCv%2Bibez/B8KZud5p9NbSvb9U/x10HSpgNsWnqqfBc6UOyLTOR6sULIq3RYG3hO4ttiHsTqJ19OXmIJ18uKdRAwm0W%2B1UgpgsirdFgbeE7i22IexOonX0eoikpovBL67pm9Ry5rKfmdqujuKJIrqR7yAiM9QkVyqfLisGkW2BGdifn1WRZE2eZtz1TIwtr5RIz4fr%2BzWthJ%2B8b4mUiIvRnrvbxY2kLOMTQyaDsIwWCrVVcQmRZEtem7CV9y12Npy2t0P5SYgr9G%2B5LOMNBx0okUHnjJOesdHfVxBOI3ioGMEqURMdxzGKUPEh9cdQZT13OIB60lApJboBtPiusgt2pGeKIWX2go19ctm1ASL/nffmXkqCH/XmhdQh01bx83nD%2BNuVWBsGt7Z9yUJAhgfU2HILNweMjSHCmbneafTW0pglqgouP3YMJyDHsaOablYrOJ7sA5PLjhGJilyjGpsHWO0hq0fn1/6LGFYxykl1OjPcIHGFfpCHLlbaL5ZjZUhhz/C8BOcXNC6vq3hZ1wVbOWBOpKjp0CGTuQXg3A4f0G8kXEJdvrlDsxGnYDSTXSrxeCw34BZX0wRD99w7JmukOIQEjoOL%2BMDlCU9gndnYr00zc1cEpTNCjhbE8KAYJBZdF2AjSLljq1308TAxRKbRrFcgG%2BJiF686OhCWD1v6PpvXQtcAwKCuVWFqytU8Snl/XGkfveCEdkXHGR%2B5wQVpN8L6zzMEG%2BrGdae643cmQb9QbyClCgocIhr5xdxaJXPYn59VkWRNnrbPaWePalQctVk7VbyIJUOzQwHaGlZwKOw/ReHEmsuRdunnXbmrEQRK31EdpPUtw%2BrkaExxbpeSMYgHQ4BoIWvqWUJyOKxwPFyEo3Cvbyx3zs8YEIDR6RYMyvLMeZ593lX52lJXIuf7ZRO6kWIOBbYENyusw81Q0PWttkAUANcUYTIqQmpJ%2Bl18qm66d0POojRw0yPqMI/iLYxfYPjGjxhb1M2zfU9m6L39x5/vp8yN12xfT20Zd3eyVauOFxOb9E3aTDebYH0%2BxbxNh/vbG4SZj9HCaNr0679ITrLZHYXBMDckEiDLDwR8Kw37v7qSMMW8TYf72xuEmY/Rwmja9Ou/SE6y2R2FwX8i5x5zY5Tl5uNpEpeEFoAqMk%2BZ6vqgE02GIVVhiy4hc5/GHP79qRrm42kSl4QWgCoyT5nq%2BqATdoRifFt8u0d30DLV9rACLenS8pBrppyFKjJPmer6oBPjILouBe1NDxY74ukW5A91YGOCIYWrgLdFGxIyh6vP7RAgb9YYpXW87wJPd786IpFTQpa3wkYMP8KZud5p9NbSAzTjUvENRy8XeTjKE1qKCzYwKm%2BvgnNWRTCLfefMjKvCmbneafTW0gM041LxDUcvxxDLN%2BQh1dSf3TphpbYWRLoHQm6WpwmDgyX2IiPt3jiN3ZxN%2BdG6zHs8QtlMdETD2u/GbqAmsR47GXT6%2Bd9vzfByhJ%2BosnjffLJWXJQXjVhUDTGN5mqOpQk1YhZbSJ7Gl3YPDnKBt%2BrT/HSDJ%2Bl2Rgf0drS1gCA4TsUAXLNhv0/py7JV78weUyrsXfLMLC3iynBrDlriy8KB/M/vFXqo7T6zykyz/ykKHC9fpUczj0/%2BiYQb3B2u4h%2B9QlK5J0kaYbM9DtGs1EUIRKIqCLzwHz3wEe%2BlG/jvSp462KvE8TSFOCswenppPI1a65q11Y%2BlO8ydxJ0yKldx4NgHf19YAWnJZAl%2BTTbsgLcaCUPrWS5lz1ndLvPYPcbyJmoyss54YkoMCaTa42hTuW08DkxX84NfS0ImGwrDzyMDV8pAyc7VLiJ3BxfADIWMj9C3nfYHWkD5oDTvOHbrCS0oVJZ1y61s4g4lI3FyoWh1%2Bszkttr3tqOGmeY5mCk2pNpt19zSXB4%2B2Et6MfY5rX9USLkHs0PPXGYe6wXuyT4Luymi/Txdbmkt1cP7P6F2o6H5ahvnzLtULV02HVfYj7vBsaMStTPgp8Bsmt1Dyphn5nqGAASmhUDfXW24V7WKihAkyAHELyMNe%2BsOg6bsTHBBKNGKPGzR5p2LY9gYFVY5/qmRA5d8MkAWlZENvXpAfbBdhejCJLU4lQBGZ0eDGmGOZuaA%2BQ6RMJncv%2BR%2BTAP9TvkNsP5x7Yko/BM2IAtCWoMdFGbhobUaNtVkkvCOc%2BwkwlIOXrrn2yrxTx37JNMsN7RFYiEZJNViWH7dXQlLiz9MOANT8H5t5HmgKEctOb1WDmztxkdBkLAejjMY20ZfUiVjwKSEkrrfw03HXk/sbeLtUsrb7nfeb7wpBi2sU7b8X6/dzpHX9DXDm2i1pOR5s/Ng0yeD/6qROyXiFZLD66XRp7//JznTqFw2TWYDkazuFWAyB7ElWqOVd/DOs%2BCAoORBxxiRhbApMiOYRyTumUb%2B%2B6Zl4qOepsczZ29vS6uVWWJ0p0rEOI2RhVZ7btZ%2Ba3lZVRIf/hRMwBoyRlWyRWLyfEmArfOGNYSa4BdrmxeeV0tdIpmLBesqH%2BfzlDeIDk7mYMk0FEAe2cpwAcbBhbqspuYIxkrOTmw00bthKfiRChNDe%2BQee7ugp8pqvuhoz7xLRUD1lTtlqG/NViTumUb%2B%2B6Zl2S6T12VBePmOOxGKAf3beJ%2BnBqYMHgKRlN2Tkq4GQ/YgJNrT9CcDRl8GQ1XD0o6U3YyDCdZIJrEUeI/uSzP6ju5XimNM1qfeiTty4z6jWFh99u%2BfIUuDvxOIp4XGKpLpJ07p9SXuh1Zy%2Bo/31T9J1fWVO2Wob81W5KyA3Dyc2bO1jtlhgW9eAI47EYoB/dt4FQiAo2J5oyUX0qTwlZ90N6Lln5bTToih/GwuFeIuyfUpNqTabdfc0rQ0s06SldO6V93k1aTZhOJHm3uL1CBBMvhQgjxSWRtrp3DKjyMPfVpYPVWi5Ngj3Y5aIpCQuZXtqruCuUkaNnhqKrfImYGgGKmrjkQD2h3urPY6VezxI9OHcs%2BXYnYPN4PKT1x7h8SO2qEn264xwBl1V6YUdN1FXoZsAsPrnFzWcz5uqxEiT0sch%2BHvj9RxWk0HOHHe5NbmAMHuVM8G7t4hl1NT6tf4sD/1uHZDwAxdwJtX0l2GsaAX7It4cWddtlJ5lscfXYNcmftrlkis981E5N9H4zW918IEMg6uvzSz4T8Zay2P9sMQsCF%2Ba3w6VCY0ZuwxbJqN1QaGDzVOAqmJCgwXZe3RYp2/gyNcSjjkQtBUKhqP42BdVQgg%2BXSnthkM2BlKHdHbibjVedFgMtLy4jXQ0jD%2BwHpBztRpAg5ko9PX7d2z/pJt8YzG3w6JRH3V0XrfkwE0SMU46R%2BTSPmgMgjWPkNxa/m2uLgcrsVBMP%2BUoqGYb3MkzDDj01vctVPDoYnTPiyDmvPETC4UzEm8QE4WG1lCfhu527VjTlnq5vxoaY1zSczQop6cs4IaeerPjfv89hzROCUFTWY7AHyfUqeJVK%2BiPZ0ftd7A5I84adtGjRGgLam9vDrIGEgOytifn1WRZE2e7RfKdpxHe8YH986M%2BW1VEiSf6o6x3ZW13hrLgQASU4k2M2CmUcOsa56My716C8yACOene86zrRIbOKlmWY/LpTTFFDj2FS/wRUBIA92e/K3PY4bY3rnNirArVpfolQpqUdeELefv5t1ECPZk5I8tozTqrC6wrFRARf3dlHL0WpRZQzOkMnGblx51W2kSUpSu2/Hd91eDSEOBXvE/kanskVWtaO29jtIzaXdOdbo2JtGAJYzJ7QD93xQpz87qAUQXCBXuJQSB/bEiwpxez/q1U6KDkxquq0XUF9zkWsYKUjFogJilTpoYvjDtoQVtApmBOA2f7el/VIHnxuCNmQlqQFxZQwbWI4tu5EfUvvFSANAk4jag8a4HYuF8%2B8esOKs2PSsBnhQzc%2BY22OtuD3yCNeLZ5n1B5za16svARkdgiGtPGEKwhyvAcMPUfhiL7RxZprDKae8MX1PVHECjLItG2MDR7ZczhqZvA9CHH0GAbafIYSkOszxrBPPpNff7dYiB/j%2BMzZCgR4yfQ7CoDU3lRIFM7BEAf4od%2B3kzeNkAy7ZaAGZftgda2Ih%2BPdTIb6Hv5zgI2didIUjziKQ0Glppdv14mXUNSx8Osti8pEcBeFN3//o3aeh8wYx6bDo/zqIDhFnZE/QS%2BoLSkKdNBK1wPJao/BgEj8GEjOIqWUvm8R5dhNriF5xeYZcXmxbjnwREWQWbbbrLMFFLc7NK/Ol0iNdgpgmBjesJ%2BsrXt0d88f9txZDbMh0kQhWdc/B2bqPntbxWBM3n63FNQKwW6Ch81DpIHjAOJ9YxiEO6FohEbrgLoWfT/TU1eJfHWjklbn6GnbsY4E7mMRoJV7VKXV/GuPP7un5EV%2BwrNpNp0v%2BSybnvKAAEqdQL5cZuKVZMfIOOtopdZisTxabiDXUYViRIoVzvUrdfVGeQVdKAmHLZYjaWnzKUIgF8oyIi091o1BkDsWY8sbUptYLfqFIQR4BMl3xYuum%2BKt3/56SzrDXXPYI7Gb%2BAbdrUFEVeL/LdryKoWtq7jM1hSu5MhS5SOEuoFMbt5EuW5vdTKNlfgWJWsvkZsZNg2uPG%2Bt2HCI3m2MTqvavmupGW%2BmkwK7pwPy56I/8unXh6QMpuq9ifhaOLpfBQK/BLOuTqjqKOZ8yeTW/pJR30DlpUK8Pb1t0/oVUCHbFxhM2uqKlaHAGgTp817xa1p9a9sWAD9g==\n\t4\n\t720\n\t720\n\t3547325421|wx0tld43lkkrodqq|3547325421|1|1626955012|0|2|6041365717172948||AgIylt4GK8nVeUcuI+4pKmMsArrIRywgjntIrbYMoUfG0o+2+yULEOc9S+J+Wk6PLDoh6IKmSjk=|3400866612|21\n\t1\n\thttps://as.weixin.qq.com/cgi-bin/redirect?tid=3400866612&token=e8d51e642ec1fa8166c546c1f303cf95&wx_aid=3547325421&wx_traceid=wx0tld43lkkrodqq00&wx_uid=19681428\n\t4\n\t\n\t\t\n\t\t\t0\n\t\t\t最近有719人购买\n\t\t\t最近有719人购买\n\t\t\t最近有719人购买\n\t\t\n\t\t1\n\t\t1800\n\t\t\n\t\t\tgh_85ea230f6b61@app\n\t\t\t/pages/shop/index.html?storeId=2393731723\n\t\t\t\n\t\t\t1\n\t\t\n\t\n\t\n\t\twx0tld43lkkrodqq\n\t\t3547325421\n\t\n\n\n"},"snsAdObject":{"adXml":{"string":"1AlphaDog阿尔法机器狗19681428011平价阿尔法机器狗来喽时代的风景,AI相伴立即购买4gh_85ea230f6b61@app/pages/shop/index.html?storeId=23937317231新品推荐限量抢购IP联名活动1https://as.weixin.qq.com/cgi-bin/redirect?tid=3400866612&token=e8d51e642ec1fa8166c546c1f303cf9510广告廣告Ad赞助商提供的广告信息贊助商提供的廣告信息Sponsored storyclassify_zh_CNzh_CNclassify_zh_TWzh_TWclassify_enen_USnickname_zh_CNnickname_zh_CNnickname_zh_TWnickname_zh_TWnickname_ennickname_enhttps://mp.weixin.qq.com/promotion/res/htmledition/mobile/html/feedback.html投诉投訴Report654315520385879808https://wxa.wxs.qq.com/canvas-luodiye/h5/wxupdate.html"},"snsObject":{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1621049336,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13598347436105209699,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD4xMzU5ODM0NzQzNjEwNTIwOTY5OTwvaWQ+PGNyZWF0ZVRpbWU+MTYyMTA0OTMzNjwvY3JlYXRlVGltZT48dXNlcm5hbWU+Z2hfMWNmYmQ1NjAzNzliPC91c2VybmFtZT48Y29udGVudERlc2M+5pe25Luj55qE6aOO5pmv77yMQUnnm7jkvLQ8L2NvbnRlbnREZXNjPjxjb250ZW50RGVzY1Nob3dUeXBlPjA8L2NvbnRlbnREZXNjU2hvd1R5cGU+PGNvbnRlbnREZXNjU2NlbmU+MzwvY29udGVudERlc2NTY2VuZT48cHJpdmF0ZT4wPC9wcml2YXRlPjxDb250ZW50T2JqZWN0Pjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48Y29udGVudFN0eWxlPjE8L2NvbnRlbnRTdHlsZT48bWVkaWFMaXN0PjxtZWRpYT48aWQ+MTM1OTkwODQ4MTQ2ODQ0NjA5NDA8L2lkPjxwcml2YXRlPjA8L3ByaXZhdGU+PHR5cGU+MjwvdHlwZT48c3ViVHlwZT4wPC9zdWJUeXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjx1c2VyRGF0YT48L3VzZXJEYXRhPjxsb3dCYW5kVXJsIHR5cGU9IjEiPjwvbG93QmFuZFVybD48dXJsIHR5cGU9IjEiPmh0dHA6Ly93eHNuc2R5dGh1bWIud3hzLnFxLmNvbS8xNDEvMjAyMDQvc25zY29zZG93bmxvYWQvU0gvcmVzZXJ2ZWQvNjA5ZjNlOTQwMDBjOTk1ZDAwMDAwMDAwOWEyMDlkMDkwMDAwMDA4ZDAwMDA0ZWVjP209NzA3YzBiMmVjNDY1OTNiZDQ3NjJlZjRkYWY0MmE4OGYmYW1wO2NrPTcwN2MwYjJlYzQ2NTkzYmQ0NzYyZWY0ZGFmNDJhODhmPC91cmw+PHRodW1iIHR5cGU9IjEiPmh0dHA6Ly93eHNuc2R5dGh1bWIud3hzLnFxLmNvbS8xNDEvMjAyMDQvc25zY29zZG93bmxvYWQvU0gvcmVzZXJ2ZWQvNjA5ZjNlOTQwMDBjOTk1ZDAwMDAwMDAwOWEyMDlkMDkwMDAwMDA4ZDAwMDA0ZWVjP209NzA3YzBiMmVjNDY1OTNiZDQ3NjJlZjRkYWY0MmE4OGYmYW1wO2NrPTcwN2MwYjJlYzQ2NTkzYmQ0NzYyZWY0ZGFmNDJhODhmPC90aHVtYj48c2l6ZSBoZWlnaHQ9IjQ1MCIgd2lkdGg9IjgwMCIgdG90YWxTaXplPSI2NTEzMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PGNvbnRlbnRTdWJTdHlsZT44PC9jb250ZW50U3ViU3R5bGU+PC9Db250ZW50T2JqZWN0PjwvVGltZWxpbmVPYmplY3Q+","iLen":1152},"objectOperations":{"buffer":"CAI=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"gh_1cfbd560379b","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}}}],"baseResponse":{"ret":0},"controlFlag":2,"delAdvertiseCount":0,"firstPageMd5":"6935ad04c4ed4552","max_id":"13647311131165143274","newRequestTime":1626954952,"objectCount":10,"objectCountForSameMd5":10,"objectList":[{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626886264,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13647311131165143274,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"为美好的世界献上祝福","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NzMxMTEzMTE2NTE0MzI3NF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfbWp6ZWg0cWo5aGlvMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY4ODYyNjRdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGFwcEluZm8+PGlkPjwhW0NEQVRBW3d4YWI5YjcxYWQyYjkwZmYzNF1dPjwvaWQ+PHZlcnNpb24+MjY8L3ZlcnNpb24+PGFwcE5hbWU+PCFbQ0RBVEFb5b6u5L+h6K+75LmmXV0+PC9hcHBOYW1lPjxpbnN0YWxsVXJsPjwvaW5zdGFsbFVybD48ZnJvbVVybD48L2Zyb21Vcmw+PGNsaWNrYWJsZT4wPC9jbGlja2FibGU+PC9hcHBJbmZvPjxjb250ZW50RGVzYz48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0NzMxMTEzMTczNDA2MTI3N11dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSJmMjhmNTgyNjE4NmU2ZTZmMWY4NTVjYzAxMjU4MDIzYiI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9hRnJXNFBWVjRwS1NuU3ExcURRVWMxWExOTUNpY2pnaWNhbTdwTlVoN1AyanUxZFJheDdIaWJROHV2YlRvdDRYeHk0UVhmR1RMSFZvbFEvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL2FGclc0UFZWNHBLU25TcTFxRFFVYzFYTE5NQ2ljamdpY2FtN3BOVWg3UDJqdTFkUmF4N0hpYlE4dXZiVG90NFh4eTRRWGZHVExIVm9sUS8xNTBdXT48L3RodW1iPjx2aWRlb0R1cmF0aW9uPjwhW0NEQVRBWzAuMF1dPjwvdmlkZW9EdXJhdGlvbj48c2l6ZSB0b3RhbFNpemU9IjY1Mjg5LjAiIHdpZHRoPSIxMDgwLjAiIGhlaWdodD0iMTY0OC4wIj48L3NpemU+PC9tZWRpYT48L21lZGlhTGlzdD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVkaWFUYWdOYW1lPjwvbWVkaWFUYWdOYW1lPjxtZXNzYWdlRXh0PjwvbWVzc2FnZUV4dD48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PGFwcGlkPnd4YWI5YjcxYWQyYjkwZmYzNDwvYXBwaWQ+PC9hcHBNc2c+PHNjZW5lPjA8L3NjZW5lPjx0eXBlPjA8L3R5cGU+PHVybD48L3VybD48bmV3V29yZGluZ0tleT48L25ld1dvcmRpbmdLZXk+PG5ld3R5cGU+MDwvbmV3dHlwZT48aW5zdGFsbGVkV29yZGluZz48L2luc3RhbGxlZFdvcmRpbmc+PHVuaW5zdGFsbGVkV29yZGluZz48L3VuaW5zdGFsbGVkV29yZGluZz48L2FjdGlvbkluZm8+PHN0YXRFeHRTdHI+PCFbQ0RBVEFbR2hRS0VuZDRZV0k1WWpjeFlXUXlZamt3Wm1Zek5BPT1dXT48L3N0YXRFeHRTdHI+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2449},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_mjzeh4qj9hio22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626788321,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13646489531181052217,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NjQ4OTUzMTE4MTA1MjIxN11dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY3ODgzMjFdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+WPr+S4jeaYr+WYm++8jOWPiOeqgeeEtuS6huS4gOS4i+S4i1vml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0NjQ4OTUzMTgxNjk0ODAyNl1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSJkNTBkOWM5M2Q1NTk5NjkzMjQ2ZTBiZTc1NDZlMmM5OSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4NGI5d21MZDhSRG5yTjhqWlRqNnVYdHF0aWNyWUl2REFMQXBqZ0g0WWZES0JnampUVkh6WDdPVS8wXV0+PC91cmw+PHRodW1iIHR5cGU9IjEiPjwhW0NEQVRBW2h0dHA6Ly9zem1tc25zLnFwaWMuY24vbW1zbnMvVkVkb2ppYmV2alJQQ3Y5TTNBbkhTODRiOXdtTGQ4UkRuck44alpUajZ1WHRxdGljcllJdkRBTEFwamdINFlmREtCZ2pqVFZIelg3T1UvMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSI0NDUzOC4wIiB3aWR0aD0iMTA4MC4wIiBoZWlnaHQ9IjIzNDAuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2077},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626542926,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13644431003338420534,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0NDQzMTAwMzMzODQyMDUzNF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY1NDI5MjZdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+aYr+WTquS4quS6uua4o+WcqOWPkeiqk++8jOaQnuW+l+S7iuaZmuWPiOaYr+aatOmbqO+8jOWPiOaYr+aJk+mbt+eahFvml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsyXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1496},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626442781,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13643590928611357004,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MzU5MDkyODYxMTM1NzAwNF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjY0NDI3ODFdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S7iuaZmuaciOS6rvCfjJkg5b6I5byv77yM5Lq65rKh5byv5bCx5aW9W+aXuuaftF1b5pe65p+0XV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQzNTkwOTI5MjEzMjM5NjQxXV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9ImEwYzA1NTljMTE3MDUwOTIxM2YyNGMwNWMwMmVjODRkIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzh3UFEzaWJKZGRHRXI4SThOYU9WNnJFWHhtNmtLeG9Ob0xjdTVIMVZBN3hpY3BpYTZCZDJORHFNQ2svMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzh3UFEzaWJKZGRHRXI4SThOYU9WNnJFWHhtNmtLeG9Ob0xjdTVIMVZBN3hpY3BpYTZCZDJORHFNQ2svMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSI3MTYzNy4wIiB3aWR0aD0iOTc4LjAiIGhlaWdodD0iMTE2NC4wIj48L3NpemU+PC9tZWRpYT48L21lZGlhTGlzdD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVkaWFUYWdOYW1lPjwvbWVkaWFUYWdOYW1lPjxtZXNzYWdlRXh0PjwvbWVzc2FnZUV4dD48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PC9hcHBNc2c+PC9hY3Rpb25JbmZvPjxhcHBJbmZvPjxpZD48L2lkPjwvYXBwSW5mbz48bG9jYXRpb24gcG9pQ2xhc3NpZnlJZD0iIiBwb2lOYW1lPSIiIHBvaUFkZHJlc3M9IiIgcG9pQ2xhc3NpZnlUeXBlPSIwIiBjaXR5PSIiPjwvbG9jYXRpb24+PHB1YmxpY1VzZXJOYW1lPjwvcHVibGljVXNlck5hbWU+PHN0cmVhbXZpZGVvPjxzdHJlYW12aWRlb3VybD48L3N0cmVhbXZpZGVvdXJsPjxzdHJlYW12aWRlb3RodW1idXJsPjwvc3RyZWFtdmlkZW90aHVtYnVybD48c3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvPjwvVGltZWxpbmVPYmplY3Q+","iLen":2085},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626348290,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13642798280310927692,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626351692,"deleteFlag":0,"isNotRichText":0,"nickname":"Mr.Y","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_ocmmotiznvw122"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0Mjc5ODI4MDMxMDkyNzY5Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYzNDgyOTBdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+imgeW+l+eRn+W+l+eRn++8jOWHj+S4gOWNiuebruagh+S6hlvml7rmn7RdW+aXuuaftF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzY0Mjc5ODI4MTAzODMxMTc2Ml1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgdHlwZT0iMSIgbWQ1PSI0NmE0OGE0YzgzOTNhMDA0NWZjZTUzZGU4ZmEzODg0OSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4OFRoT0dJczEwSGdDMEtLUDRidUJIQnh1eUhXa3BBT0VudnpvSmtyZElEbkJ3N2JRNjVSZ0VnLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUlBDdjlNM0FuSFM4OFRoT0dJczEwSGdDMEtLUDRidUJIQnh1eUhXa3BBT0VudnpvSmtyZElEbkJ3N2JRNjVSZ0VnLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iOTM3MzEuMCIgd2lkdGg9IjE0NDAuMCIgaGVpZ2h0PSIxMDgwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2075},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626277124,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13642201292100546882,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626277179,"deleteFlag":0,"isNotRichText":0,"nickname":"为美好的世界献上祝福","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_mjzeh4qj9hio22"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MjIwMTI5MjEwMDU0Njg4Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYyNzcxMjRdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+WNp+anve+8jOaUtuWIsOS6humihOitpuitpuWRilvmg4rmgZBdW+aDiuaBkF1dXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsyXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1457},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626099336,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13640709903944790348,"isNotRichText":1,"likeCount":1,"likeFlag":0,"likeUserList":[{"commentFlag":0,"commentId":0,"commentId2":0,"content":"","createTime":1626134130,"deleteFlag":0,"isNotRichText":0,"nickname":"Mr.Y","replyCommentId":0,"replyCommentId2":0,"replyUsername":"","source":0,"type":1,"username":"wxid_ocmmotiznvw122"}],"likeUserListCount":1,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MDcwOTkwMzk0NDc5MDM0OF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYwOTkzMzZdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S5n+eul+aYr+S4izcw5LqGW+aXuuaftF1b5pe65p+0XV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQwNzA5OTA0NjgyODU2Nzc0XV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9IjQzNjdkOTU4Yzc1MjJkY2E3NWZiNmM4MzY2ODYxZGQzIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTB2QmNPVzkzTnRVUDU4UWtONFM4d2VTa3RIS2lhdzM1YUFPUjNObGV2Z2hBYndTRU43ZTY3ZVljLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3N6bW1zbnMucXBpYy5jbi9tbXNucy9WRWRvamliZXZqUk9OemoxUHUybUkwdkJjT1c5M050VVA1OFFrTjRTOHdlU2t0SEtpYXczNWFBT1IzTmxldmdoQWJ3U0VON2U2N2VZYy8xNTBdXT48L3RodW1iPjx2aWRlb0R1cmF0aW9uPjwhW0NEQVRBWzAuMF1dPjwvdmlkZW9EdXJhdGlvbj48c2l6ZSB0b3RhbFNpemU9IjE2OTMxLjAiIHdpZHRoPSI3MjYuMCIgaGVpZ2h0PSIyOTkuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2056},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1626020250,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13640046480797544764,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY0MDA0NjQ4MDc5NzU0NDc2NF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjYwMjAyNTBdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+S9oOiLpeacquWHuueOsO+8jOa4uOaIj+S4jeWNuOi9ve+8gV1dPjwvY29udGVudERlc2M+PGNvbnRlbnRhdHRyPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRhdHRyPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjx3ZWFwcEluZm8+PGFwcFVzZXJOYW1lPjwvYXBwVXNlck5hbWU+PHBhZ2VQYXRoPjwvcGFnZVBhdGg+PHZlcnNpb24+PCFbQ0RBVEFbMF1dPjwvdmVyc2lvbj48ZGVidWdNb2RlPjwhW0NEQVRBWzBdXT48L2RlYnVnTW9kZT48c2hhcmVBY3Rpb25JZD48L3NoYXJlQWN0aW9uSWQ+PGlzR2FtZT48IVtDREFUQVswXV0+PC9pc0dhbWU+PG1lc3NhZ2VFeHRyYURhdGE+PC9tZXNzYWdlRXh0cmFEYXRhPjxzdWJUeXBlPjwhW0NEQVRBWzBdXT48L3N1YlR5cGU+PHByZWxvYWRSZXNvdXJjZXM+PC9wcmVsb2FkUmVzb3VyY2VzPjwvd2VhcHBJbmZvPjxjYW52YXNJbmZvWG1sPjwvY2FudmFzSW5mb1htbD48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjwhW0NEQVRBWzFdXT48L2NvbnRlbnRTdHlsZT48Y29udGVudFN1YlN0eWxlPjwhW0NEQVRBWzBdXT48L2NvbnRlbnRTdWJTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48Y29udGVudFVybD48L2NvbnRlbnRVcmw+PG1lZGlhTGlzdD48bWVkaWE+PGlkPjwhW0NEQVRBWzEzNjQwMDQ2NDgxNTA3OTU0OTk1XV0+PC9pZD48dHlwZT48IVtDREFUQVsyXV0+PC90eXBlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PHVybCB0eXBlPSIxIiBtZDU9Ijg4NDJkMGU0YjU2ZWZjMzhkZjVhMTlkMjgxMzA2OTYyIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTBqYmliM292bmlieG8xcTJpYm9taWNCbnZhU2dNRjRuRmtpYWZCYWJ0RlEyaEJYbGZCTUxnMmliZjg1VmsvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpST056ajFQdTJtSTBqYmliM292bmlieG8xcTJpYm9taWNCbnZhU2dNRjRuRmtpYWZCYWJ0RlEyaEJYbGZCTUxnMmliZjg1VmsvMTUwXV0+PC90aHVtYj48dmlkZW9EdXJhdGlvbj48IVtDREFUQVswLjBdXT48L3ZpZGVvRHVyYXRpb24+PHNpemUgdG90YWxTaXplPSIxMDk5Ny4wIiB3aWR0aD0iMjM0LjAiIGhlaWdodD0iNDQwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2069},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1625753812,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13637811438959997245,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"小张晚安","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzYzNzgxMTQzODk1OTk5NzI0NV1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfdXdieHdidDRpaGpkMjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjU3NTM4MTJdXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBW+ivpeatu++8jOi3keS6huW/q+S4pOWFrOmHjOiuoeatpeWZqOaJjeW8gOWni+iuoeaVsO+8jOaIkeivtOaAjuS5iOi3keS6humCo+S5iOS5he+8jOi/mOayoeS4gOWFrOmHjOWSqVvoi6bmtqldW+iLpua2qV3vvIzmi7/lh7rmiYvmnLrkuIDnnIvvvIzmsqHorqHmraXvvIzmraPluLjmg4XlhrXml6nkupTlhazph4zkuoZb5pOm5rGXXVvmk6bmsZddXV0+PC9jb250ZW50RGVzYz48Y29udGVudGF0dHI+PCFbQ0RBVEFbMF1dPjwvY29udGVudGF0dHI+PHNvdXJjZVVzZXJOYW1lPjwvc291cmNlVXNlck5hbWU+PHNvdXJjZU5pY2tOYW1lPjwvc291cmNlTmlja05hbWU+PHN0YXRpc3RpY3NEYXRhPjwvc3RhdGlzdGljc0RhdGE+PHdlYXBwSW5mbz48YXBwVXNlck5hbWU+PC9hcHBVc2VyTmFtZT48cGFnZVBhdGg+PC9wYWdlUGF0aD48dmVyc2lvbj48IVtDREFUQVswXV0+PC92ZXJzaW9uPjxkZWJ1Z01vZGU+PCFbQ0RBVEFbMF1dPjwvZGVidWdNb2RlPjxzaGFyZUFjdGlvbklkPjwvc2hhcmVBY3Rpb25JZD48aXNHYW1lPjwhW0NEQVRBWzBdXT48L2lzR2FtZT48bWVzc2FnZUV4dHJhRGF0YT48L21lc3NhZ2VFeHRyYURhdGE+PHN1YlR5cGU+PCFbQ0RBVEFbMF1dPjwvc3ViVHlwZT48cHJlbG9hZFJlc291cmNlcz48L3ByZWxvYWRSZXNvdXJjZXM+PC93ZWFwcEluZm8+PGNhbnZhc0luZm9YbWw+PC9jYW52YXNJbmZvWG1sPjxDb250ZW50T2JqZWN0Pjxjb250ZW50U3R5bGU+PCFbQ0RBVEFbMV1dPjwvY29udGVudFN0eWxlPjxjb250ZW50U3ViU3R5bGU+PCFbQ0RBVEFbMF1dPjwvY29udGVudFN1YlN0eWxlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48bWVkaWFMaXN0PjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2Mzc4MTE0Mzk0MzkwNjU0MjhdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIHR5cGU9IjEiIG1kNT0iMGFkNGZmNWNjZDBhOWU1ODYxMjE3ODk1N2MwMmIzZTQiPjwhW0NEQVRBW2h0dHA6Ly9zem1tc25zLnFwaWMuY24vbW1zbnMvVkVkb2ppYmV2alJQQ3Y5TTNBbkhTODhuQTRTVTB4VWROMkhSbllqdGlhOEFVUGROR0EyMEQxS0FDd0JNN0VZNjlrT2g2MUZZQ0l2bWcvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc3ptbXNucy5xcGljLmNuL21tc25zL1ZFZG9qaWJldmpSUEN2OU0zQW5IUzg4bkE0U1UweFVkTjJIUm5ZanRpYThBVVBkTkdBMjBEMUtBQ3dCTTdFWTY5a09oNjFGWUNJdm1nLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iNzUxODEuMCIgd2lkdGg9Ijk3OC4wIiBoZWlnaHQ9IjExNjQuMCI+PC9zaXplPjwvbWVkaWE+PC9tZWRpYUxpc3Q+PC9Db250ZW50T2JqZWN0PjxhY3Rpb25JbmZvPjxhcHBNc2c+PG1lZGlhVGFnTmFtZT48L21lZGlhVGFnTmFtZT48bWVzc2FnZUV4dD48L21lc3NhZ2VFeHQ+PG1lc3NhZ2VBY3Rpb24+PC9tZXNzYWdlQWN0aW9uPjwvYXBwTXNnPjwvYWN0aW9uSW5mbz48YXBwSW5mbz48aWQ+PC9pZD48L2FwcEluZm8+PGxvY2F0aW9uIHBvaUNsYXNzaWZ5SWQ9IiIgcG9pTmFtZT0iIiBwb2lBZGRyZXNzPSIiIHBvaUNsYXNzaWZ5VHlwZT0iMCIgY2l0eT0iIj48L2xvY2F0aW9uPjxwdWJsaWNVc2VyTmFtZT48L3B1YmxpY1VzZXJOYW1lPjxzdHJlYW12aWRlbz48c3RyZWFtdmlkZW91cmw+PC9zdHJlYW12aWRlb3VybD48c3RyZWFtdmlkZW90aHVtYnVybD48L3N0cmVhbXZpZGVvdGh1bWJ1cmw+PHN0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW93ZWJ1cmw+PC9zdHJlYW12aWRlbz48L1RpbWVsaW5lT2JqZWN0Pg==","iLen":2221},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_uwbxwbt4ihjd22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1625569697,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13636266972566990992,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"#A02选购助手","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzYzNjI2Njk3MjU2Njk5MDk5Ml1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d4aWRfMHV3YnpnaWxmbWg4MjJdXT48L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjwhW0NEQVRBWzE2MjU1Njk2OTddXT48L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4wPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjwhW0NEQVRBWzBdXT48L3ByaXZhdGU+PGNvbnRlbnREZXNjPjwhW0NEQVRBWzQ3LjXlhYU1MOivnei0uSAgOTXlhYUxMDDor53otLlb5pe65p+0XSAK4pSB4pSB5omr56CB5YWF5YC84pSB4pSBCiAgICDkuInnvZHpg73lj6/ku6XvvIzliLDotKblv6tdXT48L2NvbnRlbnREZXNjPjxjb250ZW50YXR0cj48IVtDREFUQVswXV0+PC9jb250ZW50YXR0cj48c291cmNlVXNlck5hbWU+PC9zb3VyY2VVc2VyTmFtZT48c291cmNlTmlja05hbWU+PC9zb3VyY2VOaWNrTmFtZT48c3RhdGlzdGljc0RhdGE+PC9zdGF0aXN0aWNzRGF0YT48d2VhcHBJbmZvPjxhcHBVc2VyTmFtZT48L2FwcFVzZXJOYW1lPjxwYWdlUGF0aD48L3BhZ2VQYXRoPjx2ZXJzaW9uPjwhW0NEQVRBWzBdXT48L3ZlcnNpb24+PGRlYnVnTW9kZT48IVtDREFUQVswXV0+PC9kZWJ1Z01vZGU+PHNoYXJlQWN0aW9uSWQ+PC9zaGFyZUFjdGlvbklkPjxpc0dhbWU+PCFbQ0RBVEFbMF1dPjwvaXNHYW1lPjxtZXNzYWdlRXh0cmFEYXRhPjwvbWVzc2FnZUV4dHJhRGF0YT48c3ViVHlwZT48IVtDREFUQVswXV0+PC9zdWJUeXBlPjxwcmVsb2FkUmVzb3VyY2VzPjwvcHJlbG9hZFJlc291cmNlcz48L3dlYXBwSW5mbz48Y2FudmFzSW5mb1htbD48L2NhbnZhc0luZm9YbWw+PENvbnRlbnRPYmplY3Q+PGNvbnRlbnRTdHlsZT48IVtDREFUQVsxXV0+PC9jb250ZW50U3R5bGU+PGNvbnRlbnRTdWJTdHlsZT48IVtDREFUQVswXV0+PC9jb250ZW50U3ViU3R5bGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PGNvbnRlbnRVcmw+PC9jb250ZW50VXJsPjxtZWRpYUxpc3Q+PG1lZGlhPjxpZD48IVtDREFUQVsxMzYzNjI2Njk3MzA0NjEyNDY3OF1dPjwvaWQ+PHR5cGU+PCFbQ0RBVEFbMl1dPjwvdHlwZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48cHJpdmF0ZT48IVtDREFUQVswXV0+PC9wcml2YXRlPjx1cmwgbWQ1PSJiNzFjZjEyNDAzNzZlYjc4YzQwNjY0NmQ2NmZiYzY5MiIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3NobW1zbnMucXBpYy5jbi9tbXNucy9qaExkS0Jvb1VIOVdNZW5RRGhXeDZlRmpNMHh4SlhVZW91a2VpY01QTWtrMzl2RjNYaE9SNDRZd1JGUWljTkE1NDZpYWdOU3BIaWM2YzNFLzBdXT48L3VybD48dGh1bWIgdHlwZT0iMSI+PCFbQ0RBVEFbaHR0cDovL3NobW1zbnMucXBpYy5jbi9tbXNucy9qaExkS0Jvb1VIOVdNZW5RRGhXeDZlRmpNMHh4SlhVZW91a2VpY01QTWtrMzl2RjNYaE9SNDRZd1JGUWljTkE1NDZpYWdOU3BIaWM2YzNFLzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIGhlaWdodD0iMTkyMC4wIiB3aWR0aD0iMTA4MC4wIiB0b3RhbFNpemU9IjUxMzc0LjAiPjwvc2l6ZT48L21lZGlhPjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2MzYyNjY5NzMwNDY2NDg5NjNdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIG1kNT0iNzIxZTY5MzdiMzBiOGUxYmY2MjBmNzY0ZWI4ZDgyYWQiIHR5cGU9IjEiPjwhW0NEQVRBW2h0dHA6Ly9zaG1tc25zLnFwaWMuY24vbW1zbnMvamhMZEtCb29VSDlXTWVuUURoV3g2ZUZqTTB4eEpYVWVEUkRHU2R0TWRVVTRpYkZ3NUpVN3QzaE1EYTlDdEFXQ3lFZWljS1JtMlVrbXcvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc2htbXNucy5xcGljLmNuL21tc25zL2poTGRLQm9vVUg5V01lblFEaFd4NmVGak0weHhKWFVlRFJER1NkdE1kVVU0aWJGdzVKVTd0M2hNRGE5Q3RBV0N5RWVpY0tSbTJVa213LzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIGhlaWdodD0iMjM0MC4wIiB3aWR0aD0iMTA4MC4wIiB0b3RhbFNpemU9Ijc2Mzc4LjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2717},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_0uwbzgilfmh822","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}],"recCount":0,"serverConfig":{"copyAndPasteWordLimit":100,"postMentionLimit":10},"session":{"buffer":"CIS65YcGEAEY6uHUgq2lv7K9ASDq4dSCraW/sr0BMIS65YcGSk8I/rLN8KwvEAoYhLrlhwYiIgjjrpTrop7C27wBEAQYBCDq4dSCraW/sr0BKIS65YcGMAEqGgjq4dSCraW/sr0BEJDh/JGEkvCevQEYCiABUIS65YcGYIS65YcG","iLen":129}},"type":11145} + #endregion + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + var client = WechatClient.GetApi(user) as Wechat_Xiaoxie; + if (!user.IsGetCircle) return; + try + { + //var _data = json.ContainsKey("data") ? json["data"] as Dictionary : null; + //if (_data == null) return; + + //foreach (KeyValuePair item in _data) + //{ + // var wxid = item["wxid"]?.ToString(); + + //} + //for (int i = 0; i < _data.Count; i++) + //{ + // var item = _data[i] as Dictionary; + + // var wxid = item["wxid"]?.ToString(); + + + //} + + user.CircleData = recvData; + } + catch (Exception ex) + { } + finally + { + user.IsGetCircle = false; + } + } + break; + case MsgType.MT_SNS_AUTO_AUTH_MINIAPP_LOGIN://小程序自动授权登录 + { + //{"data":{"appid":"wxde8ac0a21135c07d","code":"051QFNkl2pCwt748wlol2XID1B4QFNk8"},"type":11136} + + var appid = data["appid"].ToString(); + var code = data["code"].ToString(); + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + if (user.AutoAuthLoginMiNiApps.ContainsKey(appid)) + user.AutoAuthLoginMiNiApps.Remove(appid); + user.AutoAuthLoginMiNiApps.Add(appid, code); + } + break; + case MsgType.MT_SNS_POST_MSG://发送朋友圈 + { + #region 数据结构 + /* + {"data":{"baseResponse":{"ret":0},"snsObject":{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1627522835,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13652651078544265545,"isNotRichText":0,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"、","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD4xMzY1MjY1MTA3ODU0NDI2NTU0NTwvaWQ+PHVzZXJuYW1lPnd4aWRfdnY3cmV2N2E0eHBqMjI8L3VzZXJuYW1lPjxjcmVhdGVUaW1lPjE2Mjc1MjI4MzU8L2NyZWF0ZVRpbWU+PGNvbnRlbnREZXNjU2hvd1R5cGU+MDwvY29udGVudERlc2NTaG93VHlwZT48Y29udGVudERlc2NTY2VuZT4zPC9jb250ZW50RGVzY1NjZW5lPjxwcml2YXRlPjA8L3ByaXZhdGU+PGNvbnRlbnREZXNjPui/meS4quS9oOiCr+WumuS4jeefpemBk+aIkeeOsOWcqOaDs+eahEE8L2NvbnRlbnREZXNjPjxzaWdodEZvbGRlZD4wPC9zaWdodEZvbGRlZD48c2hvd0ZsYWc+MDwvc2hvd0ZsYWc+PGFwcEluZm8+PGlkPjwvaWQ+PHZlcnNpb24+PC92ZXJzaW9uPjxhcHBOYW1lPjwvYXBwTmFtZT48aW5zdGFsbFVybD48L2luc3RhbGxVcmw+PGZyb21Vcmw+PC9mcm9tVXJsPjxpc0ZvcmNlVXBkYXRlPjA8L2lzRm9yY2VVcGRhdGU+PC9hcHBJbmZvPjxzb3VyY2VVc2VyTmFtZT48L3NvdXJjZVVzZXJOYW1lPjxzb3VyY2VOaWNrTmFtZT48L3NvdXJjZU5pY2tOYW1lPjxzdGF0aXN0aWNzRGF0YT48L3N0YXRpc3RpY3NEYXRhPjxzdGF0RXh0U3RyPjwvc3RhdEV4dFN0cj48Q29udGVudE9iamVjdD48Y29udGVudFN0eWxlPjI8L2NvbnRlbnRTdHlsZT48dGl0bGU+PC90aXRsZT48ZGVzY3JpcHRpb24+PC9kZXNjcmlwdGlvbj48bWVkaWFMaXN0PjwvbWVkaWFMaXN0Pjxjb250ZW50VXJsPjwvY29udGVudFVybD48L0NvbnRlbnRPYmplY3Q+PGFjdGlvbkluZm8+PGFwcE1zZz48bWVzc2FnZUFjdGlvbj48L21lc3NhZ2VBY3Rpb24+PC9hcHBNc2c+PC9hY3Rpb25JbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":1112},"objectOperations":{"buffer":"","iLen":0},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wxid_vv7rev7a4xpj22","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0},"spamTips":""},"type":11148} + */ + #endregion + + if (data.ContainsKey("snsObject")) + { + var snsObject = data["snsObject"] as Dictionary; + if (snsObject.ContainsKey("id")) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + user.SendCircleId = snsObject["id"].ToString(); + } + } + } + break; + case MsgType.MT_SNS_COMMENT_MSG://朋友圈评论 + { + + } + break; + case MsgType.MT_SNS_LIKE_MSG://朋友圈点赞 + { + + } + break; + case MsgType.MT_SNS_UPLOAD_IMAGE_MSG://朋友圈上传图片 + { + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGYkibHF8s3Pu0RAQNicdgRVsn/0"},"clientId":"wxid_vv7rev7a4xpj22_1627486860","id":0,"path":"D:\\PCRobot\\bin\\Debug\\Cache\\0728114016639.png","startPos":16627,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGYkibHF8s3Pu0RAQNicdgRVsn/150"}],"totalLen":16627,"type":2},"type":11149} + + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGa9quIRWhDvpnuvgkSLwxaz/0"},"clientId":"wxid_vv7rev7a4xpj22_1627491212","id":0,"path":"","startPos":59023,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGxEyianCKF1vsqwWh9GicmTGa9quIRWhDvpnuvgkSLwxaz/150"}],"totalLen":59023,"type":2},"type":11149} + + //{"data":{"baseResponse":{"ret":0},"bufferUrl":{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGytHnYnRDfnZ3JnOPBfd4kopkfT9Kic2vlQibkXia04Zweib/0"},"clientId":"wxid_vv7rev7a4xpj22_1627523859","id":0,"path":"D:\\公司项目\\fl_system\\PCRobot\\bin\\Debug\\Cache\\0729095735481.jpg","startPos":47326,"thumbUrlCount":1,"thumbUrls":[{"type":1,"url":"http://mmsns.qpic.cn/mmsns/PiajxSqBRaELvAyQVFmJhGytHnYnRDfnZ3JnOPBfd4kopkfT9Kic2vlQibkXia04Zweib/150"}],"totalLen":47326,"type":2},"type":11149} + + LogHelper.GetSingleObj().Info(new StackTrace().GetFrame(0).GetMethod().Name, $"正在上传朋友圈图片:" + recvData); + + var upLoadImage = JsonConvert.DeserializeObject(recvData); + if (upLoadImage != null) + { + if (upLoadImage.data.startPos == upLoadImage.data.totalLen) + { + var path = upLoadImage.data.path; + var url = upLoadImage.data.bufferUrl.url; + if (!string.IsNullOrWhiteSpace(path) && !string.IsNullOrWhiteSpace(url)) + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + if (user.UpLoadImages.ContainsKey(path)) + user.UpLoadImages.Remove(path); + user.UpLoadImages.Add(path, url); + } + else + { + + } + } + } + } + break; + case MsgType.MT_SNS_TIMELINE_USER_MSG://获取指定用户的朋友圈 + { + #region 数据样式 + /* + {"data":{"baseResponse":{"ret":207},"continueId":0,"firstPageMd5":"b7e1f61580104448","limitedId":0,"newRequestTime":1627613128,"objectCount":1,"objectCountForSameMd5":1,"objectList":[{"blackListCount":0,"commentCount":0,"commentUserListCount":0,"createTime":1627612789,"deleteFlag":0,"extFlag":1,"groupCount":0,"groupUserCount":0,"id":13653405663930290388,"isNotRichText":1,"likeCount":0,"likeFlag":0,"likeUserListCount":0,"nickname":"先森吳","noChange":0,"objectDesc":{"buffer":"PFRpbWVsaW5lT2JqZWN0PjxpZD48IVtDREFUQVsxMzY1MzQwNTY2MzkzMDI5MDM4OF1dPjwvaWQ+PHVzZXJuYW1lPjwhW0NEQVRBW3d1amlhaHVhMDg3Nl1dPjwvdXNlcm5hbWU+PGNyZWF0ZVRpbWU+PCFbQ0RBVEFbMTYyNzYxMjc4OV1dPjwvY3JlYXRlVGltZT48Y29udGVudERlc2NTaG93VHlwZT4wPC9jb250ZW50RGVzY1Nob3dUeXBlPjxjb250ZW50RGVzY1NjZW5lPjA8L2NvbnRlbnREZXNjU2NlbmU+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48Y29udGVudERlc2M+PCFbQ0RBVEFb5L2g6IKv5a6a5LiN55+l6YGT5oiR546w5Zyo5oOz6KGo6L6+5LuA5LmIXV0+PC9jb250ZW50RGVzYz48Y29udGVudGF0dHI+PCFbQ0RBVEFbMF1dPjwvY29udGVudGF0dHI+PHNvdXJjZVVzZXJOYW1lPjwvc291cmNlVXNlck5hbWU+PHNvdXJjZU5pY2tOYW1lPjwvc291cmNlTmlja05hbWU+PHN0YXRpc3RpY3NEYXRhPjwvc3RhdGlzdGljc0RhdGE+PHdlYXBwSW5mbz48YXBwVXNlck5hbWU+PC9hcHBVc2VyTmFtZT48cGFnZVBhdGg+PC9wYWdlUGF0aD48dmVyc2lvbj48IVtDREFUQVswXV0+PC92ZXJzaW9uPjxkZWJ1Z01vZGU+PCFbQ0RBVEFbMF1dPjwvZGVidWdNb2RlPjxzaGFyZUFjdGlvbklkPjwvc2hhcmVBY3Rpb25JZD48aXNHYW1lPjwhW0NEQVRBWzBdXT48L2lzR2FtZT48bWVzc2FnZUV4dHJhRGF0YT48L21lc3NhZ2VFeHRyYURhdGE+PHN1YlR5cGU+PCFbQ0RBVEFbMF1dPjwvc3ViVHlwZT48cHJlbG9hZFJlc291cmNlcz48L3ByZWxvYWRSZXNvdXJjZXM+PC93ZWFwcEluZm8+PGNhbnZhc0luZm9YbWw+PC9jYW52YXNJbmZvWG1sPjxDb250ZW50T2JqZWN0Pjxjb250ZW50U3R5bGU+PCFbQ0RBVEFbMV1dPjwvY29udGVudFN0eWxlPjxjb250ZW50U3ViU3R5bGU+PCFbQ0RBVEFbMF1dPjwvY29udGVudFN1YlN0eWxlPjx0aXRsZT48L3RpdGxlPjxkZXNjcmlwdGlvbj48L2Rlc2NyaXB0aW9uPjxjb250ZW50VXJsPjwvY29udGVudFVybD48bWVkaWFMaXN0PjxtZWRpYT48aWQ+PCFbQ0RBVEFbMTM2NTM0MDU2NjQ1NTkyMzkzODZdXT48L2lkPjx0eXBlPjwhW0NEQVRBWzJdXT48L3R5cGU+PHRpdGxlPjwvdGl0bGU+PGRlc2NyaXB0aW9uPjwvZGVzY3JpcHRpb24+PHByaXZhdGU+PCFbQ0RBVEFbMF1dPjwvcHJpdmF0ZT48dXJsIHR5cGU9IjEiIG1kNT0iNDI1YTRiODEyNjQ2NzQwY2Y3MzlmYWI4Y2E2ZGIyNWUiPjwhW0NEQVRBW2h0dHA6Ly9zaG1tc25zLnFwaWMuY24vbW1zbnMvaWNySERtdkRpYjB4bUhUbkFPODJKSVVjaDFUVmUySWFtbDdYWHdaSlVuUWpZU3dsSjVNa09iQXlYRkpUbVNTbk5DZmNITFgyNE9RUncvMF1dPjwvdXJsPjx0aHVtYiB0eXBlPSIxIj48IVtDREFUQVtodHRwOi8vc2htbXNucy5xcGljLmNuL21tc25zL2ljckhEbXZEaWIweG1IVG5BTzgySklVY2gxVFZlMklhbWw3WFh3WkpVblFqWVN3bEo1TWtPYkF5WEZKVG1TU25OQ2ZjSExYMjRPUVJ3LzE1MF1dPjwvdGh1bWI+PHZpZGVvRHVyYXRpb24+PCFbQ0RBVEFbMC4wXV0+PC92aWRlb0R1cmF0aW9uPjxzaXplIHRvdGFsU2l6ZT0iMTAxOTIuMCIgd2lkdGg9IjEwODAuMCIgaGVpZ2h0PSIyMzQwLjAiPjwvc2l6ZT48L21lZGlhPjwvbWVkaWFMaXN0PjwvQ29udGVudE9iamVjdD48YWN0aW9uSW5mbz48YXBwTXNnPjxtZWRpYVRhZ05hbWU+PC9tZWRpYVRhZ05hbWU+PG1lc3NhZ2VFeHQ+PC9tZXNzYWdlRXh0PjxtZXNzYWdlQWN0aW9uPjwvbWVzc2FnZUFjdGlvbj48L2FwcE1zZz48L2FjdGlvbkluZm8+PGFwcEluZm8+PGlkPjwvaWQ+PC9hcHBJbmZvPjxsb2NhdGlvbiBwb2lDbGFzc2lmeUlkPSIiIHBvaU5hbWU9IiIgcG9pQWRkcmVzcz0iIiBwb2lDbGFzc2lmeVR5cGU9IjAiIGNpdHk9IiI+PC9sb2NhdGlvbj48cHVibGljVXNlck5hbWU+PC9wdWJsaWNVc2VyTmFtZT48c3RyZWFtdmlkZW8+PHN0cmVhbXZpZGVvdXJsPjwvc3RyZWFtdmlkZW91cmw+PHN0cmVhbXZpZGVvdGh1bWJ1cmw+PC9zdHJlYW12aWRlb3RodW1idXJsPjxzdHJlYW12aWRlb3dlYnVybD48L3N0cmVhbXZpZGVvd2VidXJsPjwvc3RyZWFtdmlkZW8+PC9UaW1lbGluZU9iamVjdD4=","iLen":2060},"objectOperations":{"buffer":"CAA=","iLen":2},"preDownloadInfo":{"noPreDownloadRange":"","preDownloadNetType":0,"preDownloadPercent":0},"referId":0,"referUsername":"","snsRedEnvelops":{"reportId":0,"reportKey":0,"resourceId":0,"rewardCount":0},"username":"wujiahua0876","weAppInfo":{"appId":0,"mapPoiId":"","redirectUrl":"","score":0,"showType":0,"userName":""},"withUserCount":0,"withUserListCount":0}],"objectTotalCount":5,"retTips":"朋友仅展示最近一个月的朋友圈","serverConfig":{"copyAndPasteWordLimit":100,"postMentionLimit":10},"snsUserInfo":{"snsBgImgId":"http://szmmsns.qpic.cn/mmsns/icrHDmvDib0xnEAtnSHHGziac6GNMlhWZK61YORztv9pl7x3AeNWibkAcdJstckibqwBFVFcFO9ovscc/0","snsBgObjectId":13404086805597261983,"snsFlag":1,"snsFlagEx":6273}},"type":11150} + */ + #endregion + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + if (data.ContainsKey("objectList")) + { + var objectList = data["objectList"] as ArrayList; + if (objectList != null && objectList.Count != 0) + { + var result = objectList[0] as Dictionary; + if (result != null) + { + if (result.ContainsKey("username")) + { + var uname = result["username"].ToString(); + if (user.GetUserCircles.ContainsKey(uname)) + user.GetUserCircles.Remove(uname); + user.GetUserCircles.Add(uname, recvData); + } + } + } + } + } + break; + default: + + break; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 本地解密dat图片 + /// + /// + /// + /// + public static string DecodeImage(string FileName, byte XorKey, string DecodeImagePath) + { + var data = File.ReadAllBytes(FileName); + for (int i = 0; i < data.Length; i++) + data[i] = Convert.ToByte(data[i] ^ XorKey); + //var path = FileName.Replace(Path.GetFileName(FileName), Path.GetFileNameWithoutExtension(FileName) + ".jpg"); + File.WriteAllBytes(DecodeImagePath, data); + return DecodeImagePath; + } + + /// + /// 获取微信的uin的值 + /// + /// + /// + public static string GetUin(int pid) + { + try + { + Process[] processes = Process.GetProcesses(); + foreach (Process process in processes) + { + if (process.Id == pid) + { + foreach (ProcessModule processModule in process.Modules) + { + if (processModule.ModuleName == "WeChatWin.dll") + { + //微信基址 + var WeChatWinBaseAddress = processModule.BaseAddress; + //Console.WriteLine("微信基址:\t" + "0x" + ((int)(processModule.BaseAddress)).ToString("X8") + Environment.NewLine); + var WxNameAddress = WeChatWinBaseAddress + PcOffSet; + var uinStr = Common.GetString(process.Handle, WxNameAddress, 4); + Console.WriteLine($"uinStr = {uinStr}"); + return uinStr; + } + } + break; + } + } + } + catch (Exception) + { } + return string.Empty; + } + + // 关闭回调 + static void WxCloseCallback(uint dwClientId) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == dwClientId && f.Value.Type == WechatType.Xiaoxie).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"WxCloseCallback关闭回调,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + #endregion + + public Wechat_Xiaoxie(WechatUser User) : base(User) { } + + public override void SendMessage(string wxid, string message) + { + try + { + var json = string.Empty; + message = message.Replace("\r\n", "\n"); + if (Common.isXML(message)) + { + //var msgs = Regex.Matches(message, "(<.*?>)(.*?)()"); + //foreach (Match item in msgs) + //{ + // if (item.Success && !string.IsNullOrEmpty(item.Groups[2].Value) && !item.Groups[2].Value.StartsWith("" + item.Groups[3]; + // message = message.Replace(item.Groups[1].Value,temp); + // } + //} + + //wxfedd75bfcbbcd58c + //wx13e41a437b8a1d2e + //pages/index/index.html?orderid=[领取地址] + if (Regex.IsMatch(message, @"(?[^<]+)") || Regex.IsMatch(message, @"(.+?)")) + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_XMLMSG, data = new { to_wxid = wxid, xml = Common.XMLDispose(message.Replace("&", "&")) } }); + else + { + message = message.Replace("&", "&"); + var title = string.Empty; + var desc = string.Empty; + var url = string.Empty; + var image_url = string.Empty; + var reg = Regex.Match(message, @"(?<标题>[\w\W]+?)"); + if (reg.Success) title = reg.Groups["标题"].Value; + reg = Regex.Match(message, @"(?<介绍>[\w\W]+?)"); + if (reg.Success) desc = reg.Groups["介绍"].Value; + reg = Regex.Match(message, @"(?<链接>[\w\W]+?)"); + if (reg.Success) url = reg.Groups["链接"].Value; + reg = Regex.Match(message, @"(?<图片链接>[\w\W]+?)"); + if (reg.Success) image_url = reg.Groups["图片链接"].Value; + + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_LINKMSG, data = new { to_wxid = wxid, title = $"{title.XMLReplace()}", desc = $"{desc.XMLReplace()}", url = url.XMLReplace(), image_url = image_url.XMLReplace() } }); + } + } + else + { + var atUsername = new List(); + var regs = Regex.Matches(message, @"\[@([^\]]+?)\]"); + var flag = true; + if (wxid.Contains("@chatroom")) + { + //[@wujiahua0876]你懂得,我只是测试一下 + + foreach (Match item in regs) + { + atUsername.Add(item.Groups[1].Value.Trim()); + } + if (atUsername.Count != 0) + { + flag = false; + message = Regex.Replace(message, @"(\[@[^\]]+?\])", "{$@}"); + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CHATROOM_ATMSG, data = new { to_wxid = wxid, content = message, at_list = atUsername.ToArray() } }); + } + } + if (flag) + { + message = Regex.Replace(message, @"(\[@[^\]]+?\])", ""); + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_TEXTMSG, data = new { to_wxid = wxid, content = message } }); + } + } + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 获取朋友圈 + /// + /// + public override void FindCircles(string circleId, string username) + { + try + { + if (!string.IsNullOrWhiteSpace(username)) + { + #region 获取指定用户朋友圈数据 + try + { + if (!User.GetUserCircles.ContainsKey(username)) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_TIMELINE_USER_MSG, data = new { username = username, first_page_md5 = "", max_id = circleId } }); + SendWeChatData(User.DwClientId, json); + } + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(30); + do + { + if (User.GetUserCircles.ContainsKey(username)) + { + var res = User.GetUserCircles[username]; + + #region 修正数据格式 + var jsonDic = HttpExtend.JsonToDictionary(res); + var data = jsonDic["data"] as Dictionary; + //var firstPageMd5 = data["firstPageMd5"].ToString(); + //var data = new { FirFirstPageMd5 = firstPageMd5, SnsObjectsCount = long.Parse(HttpExtend.GetTimeStamp()), }; + + var cirCleInfoOriList = new List(); + if (data.ContainsKey("objectList")) + { + var objectList = data["objectList"] as ArrayList; + if (objectList != null && objectList.Count != 0) + { + for (int i = 0; i < objectList.Count; i++) + { + var obj = JsonConvert.SerializeObject(objectList[i]); + if (obj != null) + { + var cInfo = JsonConvert.DeserializeObject(obj); + if (cInfo != null) + { + cirCleInfoOriList.Add(cInfo); + } + } + } + cirCleInfoOriList = cirCleInfoOriList.OrderByDescending(f => f.createTime).ToList(); + + List> _objs = new List>(); + + for (int i = 0; i < cirCleInfoOriList.Count; i++) + { + var tmp = HttpHelper.ObjectToJson(cirCleInfoOriList[i]); + var dic = HttpExtend.JsonToDictionary(tmp); + _objs.Add(dic); + } + } + } + #endregion + if (cirCleInfoOriList != null && cirCleInfoOriList.Count != 0) + return HttpHelper.ObjectToJson(new { data = new { objectList = new List() { cirCleInfoOriList[0] } } }); + return string.Empty; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleData; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + throw ex; + } + finally + { + User.GetUserCircles.Remove(username); + } + #endregion + } + else + { + #region 朋友圈首页 + if (!User.IsGetCircle) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_TIMELINE_MSG, data = new { max_id = circleId } }); + SendWeChatData(User.DwClientId, json); + User.IsGetCircle = true; + } + + var result = Task.Factory.StartNew(delegate () + { + Thread.Sleep(1000); + DateTime end_time = DateTime.Now.AddSeconds(30); + do + { + if (!User.IsGetCircle) + { + return User.CircleData; + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleData; + msg.Data = result; + + socketClient.Send(msg); + #endregion + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 自动授权登录小程序 + /// + /// + public override void AutoAuthMiniAPPLogin(string appid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_AUTO_AUTH_MINIAPP_LOGIN, data = new { appid = appid } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (User.AutoAuthLoginMiNiApps.ContainsKey(appid)) + { + return User.AutoAuthLoginMiNiApps[appid]; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvMiniAppCode; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 发送朋友圈 + /// + /// + public override void SendCircle(string xmlmsg) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_POST_MSG, data = new { object_desc = xmlmsg } }); + User.SendCircleId = string.Empty; + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (!string.IsNullOrWhiteSpace(User.SendCircleId)) + { + return User.SendCircleId; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleReturnId; + msg.Data = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + finally + { + User.SendCircleId = string.Empty; + } + } + + /// + /// 发送朋友圈评论 + /// + /// + /// + public override void SendCircleComment(string circleId, string content) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_COMMENT_MSG, data = new { object_id = circleId, content = content } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 朋友圈点赞 + /// + /// 朋友圈的object_id + public override void SendCirclePraise(string circleId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_LIKE_MSG, data = new { object_id = circleId } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 朋友圈上传本地图片,返回上传以后返回的地址 + /// + /// + public override void CircleUpLoadImage(string data) + { + try + { + var path = string.Empty; + Bitmap bitmap = null; + if (data.StartsWith("http", StringComparison.CurrentCultureIgnoreCase)) + { + HttpHelper http = new HttpHelper(); + var item = http.GetItem(data); + item.ResultType = CsharpHttpHelper.Enum.ResultType.Byte; + + using (MemoryStream ms = new MemoryStream(http.GetHtml(item).ResultByte)) + { + using (Image mImage = Image.FromStream(ms, true)) + { + bitmap = new Bitmap(mImage); + path = HttpExtend.MapFile($@"{DateTime.Now.ToString("MMddhhmmssfff")}.{Common.GetImageExt(bitmap)}", @"Cache\IMAGE"); + bitmap.Save(path); + bitmap.Dispose(); + } + } + } + else + { + bitmap = Common.ConvertBase64ToImage(data); + using (MemoryStream stream = new MemoryStream()) + { + bitmap.Save(stream, ImageFormat.Jpeg); + byte[] data1 = new byte[stream.Length]; + stream.Seek(0, SeekOrigin.Begin); + stream.Read(data1, 0, Convert.ToInt32(stream.Length)); + bitmap = Common.CompressionImage(new MemoryStream(data1), 25); + } + + path = HttpExtend.MapFile($@"{DateTime.Now.ToString("MMddhhmmssfff")}.{Common.GetImageExt(bitmap)}", @"Cache\IMAGE"); + + bitmap.Save(path); + bitmap.Dispose(); + } + + if (!string.IsNullOrWhiteSpace(path) && File.Exists(path)) + { + LogHelper.GetSingleObj().Info(new StackTrace().GetFrame(0).GetMethod().Name, $"开始上传朋友圈图片:" + path); + + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SNS_UPLOAD_IMAGE_MSG, data = new { path = path } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(60); + do + { + if (User.UpLoadImages.ContainsKey(path)) + { + return User.UpLoadImages[path]; + } + Thread.Sleep(400); + } while (end_time > DateTime.Now); + return null; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCircleUploadImageUrl; + msg.Data = result; + + socketClient.Send(msg); + } + else + { } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, $"上传朋友圈图片异常:{ex.Message},{ex.StackTrace}"); + } + } + + public override void SendFile(string wxid, string file) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_FILEMSG, data = new { to_wxid = wxid, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendImage(string wxid, string file) + { + try + { + if (file.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + byte[] ImangByte = null; + string extension = Path.GetExtension(file); + extension = string.IsNullOrWhiteSpace(extension) ? ".jpg" : extension; + ImangByte = new System.Net.WebClient().DownloadData(file); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), extension); + if (!File.Exists(path)) + { + File.WriteAllBytes(path, ImangByte); + } + if (File.Exists(path)) + file = path; + } + else + { + if (!File.Exists(file)) + { + if (Common.IsBase64(file)) + { + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), "jpg"); + if (Common.Base64ToFileAndSave(file, path) && File.Exists(path)) + { + file = path; + } + } + else + { } + } + } + var json = string.Empty; + if (file.Trim().EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase)) + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_GIFMSG, data = new { to_wxid = wxid, file = file } }); + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMGMSG, data = new { to_wxid = wxid, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendVideo(string wxid, string file) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_VIDEOMSG, data = new { to_wxid = wxid, file = file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void AgreeAddMe(string text) + { + try + { + var v1 = string.Empty; + var v2 = string.Empty; + var scene = 0; + + var reg = Regex.Match(text, @"encryptusername=\\?""([^""]+?)\\?"""); + if (reg.Success) + v1 = reg.Groups[1].Value; + reg = Regex.Match(text, @"ticket=\\?""([^""]+?)\\?"""); + if (reg.Success) + v2 = reg.Groups[1].Value; + reg = Regex.Match(text, @"scene=\\?""([^""]+?)\\?"""); + if (reg.Success) + scene = int.Parse(reg.Groups[1].Value); + + LogHelper.GetSingleObj().Info("------", $"v1 = {v1} v2 = {v1} scene = {scene}"); + + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_FRIEND_MSG, data = new { v1 = v1, v2 = v2, scene = scene } }); + //var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_FRIEND_MSG, data = new { v1 = v1, v2 = v2 } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void SendCard(string to_wxid, string card_wxid) + { + try + { + var json = string.Empty; + if (card_wxid.Contains("@chatroom")) + //json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_INVITE_TO_ROOM_REQ_MSG, data = new { room_wxid = card_wxid, member_list = new string[] { to_wxid } } }); + { + InviteMemberToRoom_40Up(card_wxid, to_wxid); + return; + } + else + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CARDMSG, data = new { to_wxid = to_wxid, card_wxid = card_wxid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 创建群 + /// + /// + public override void CreateRoom(string wxidData) + { + try + { + if (string.IsNullOrWhiteSpace(wxidData)) return; + var wxids = wxidData.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (wxids == null || wxids.Length == 0) return; + + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CREATE_ROOM_MSG, data = wxids }); + SendWeChatData(User.DwClientId, json); + + var wxidstmp = wxids.ToList(); + wxidstmp.Add(User.Wxid); + wxidstmp.Sort(StringComparer.CurrentCulture); + + var md5Text = Common.GetMD5(string.Join(",", wxidstmp)); + + var result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(15); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[md5Text]; + if (item != null) + { + try + { + cache.Remove(md5Text); + } + catch (Exception ex) + { } + return item.ToString(); + } + } while (awaitTime >= DateTime.Now); + return string.Empty; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CreateRoom(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCreateRoom; + msg.GroupId = result; + msg.MemberTotal = wxidstmp.Count - 1; + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + + + + } + + public override void InviteMemberToRoom_40Up(string groupid, string wxidData) + { + try + { + if (string.IsNullOrWhiteSpace(wxidData)) return; + var wxids = wxidData.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (wxids != null && wxids.Length != 0) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_INVITE_TO_ROOM_REQ_MSG, data = new { room_wxid = groupid, member_list = wxids } }); + SendWeChatData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void InviteMemberToRoom_40Down(string groupid, string wxidData) + { + try + { + if (string.IsNullOrWhiteSpace(wxidData)) return; + var wxids = wxidData.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (wxids != null && wxids.Length != 0) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_INVITE_TO_ROOM_MSG, data = new { room_wxid = groupid, member_list = wxids } }); + SendWeChatData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".._."); + } + } + + public override void DeleteRoomMember(string wxid, string room) + { + try + { + if (room.Contains("@chatroom") || room.Contains("@im.chatroom")) + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DEL_ROOM_MEMBER_MSG, data = new { room_wxid = room, member_list = new string[] { wxid } } }); + SendWeChatData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void DecryptImage(string src_file, string dest_file) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DECRYPT_IMG_MSG, data = new { src_file = src_file, dest_file = dest_file } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void PayTransferConfirm(string data) + { + try + { + var transferid = string.Empty; + var dic = HttpExtend.JsonToDictionary(data); + if (dic.ContainsKey("Transferid")) + transferid = dic["Transferid"].ToString(); + + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_WCPAY_MSG, data = new { transferid = transferid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void DeleteFriend(string wxid) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DEL_FRIEND_MSG, data = new { wxid = wxid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void EditCotacts(string wxid, string remark) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_FRIEND_REMARK_MSG, data = new { wxid = wxid, remark = remark } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void StateOpt(string wxid, bool status) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_CHAT_SESSION_TOP_MSG, data = new { wxid = wxid, status = status ? 1 : 0 } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + private static bool IsZombizRun = false; + + internal void GetZombiz()//这个方法临时用,以后修改 (不应该用休眠的) + { + if (IsZombizRun) return; + try + { + IsZombizRun = true; + + GetContact(); + var flag = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + if (!User.IsGetFriend) + return true; + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return false; + }).Result; + + var friends = User.Friends.Where(f => !f.wxid.Contains("@chatroom") && f.is_zombie == -1).ToList(); + foreach (var item in friends) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_CARD_XMLMSG, data = new { to_wxid = item.wxid, xml = @" ".Replace("[wxid]", item.wxid).Replace("[name]", ".") } }); + var u = User.Friends.FirstOrDefault(f => f.wxid == item.wxid); + if (u != null && u.is_zombie == -1) + { + SendWeChatData(User.DwClientId, json); + Thread.Sleep(800 + new Random().Next(100, 200)); + } + } + + //#region 发送xx + //var nmss = new List>(); + //var mis = new List(); + //var count = 30; + //var rem = friends.Count % count; + //var num = friends.Count / count; + + //for (int i = 0; i < friends.Count; i++) + //{ + // mis.Add(friends[i]); + // if (mis.Count >= count) + // { + // nmss.Add(mis); + // mis = new List(); + // } + // else if (nmss.Count == num && mis.Count == rem) + // { + // nmss.Add(mis); + // } + //} + //var user = WechatClient.GetUser(User.DwClientId, WechatType.Xiaoxie); + //if (user == null) return; + //var socketClient = EasySoc.GetSocket(); + //foreach (var item in nmss) + //{ + // var msg = new WechatContact(); + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + + // msg.Cmd = PCRobotCMD.rcvContactList; + // msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", item } }); + + // socketClient.Send(msg); + // Thread.Sleep(5); + //} + //#endregion + + } + catch (Exception) + { } + finally + { + IsZombizRun = false; + } + } + + public override void GetContact() + { + try + { + //获取好友列表(数据库读取) + //var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_FRIENDS_MSG, data = new { } }); + //SendWeChatData(User.DwClientId, json); + Task.Run(() => + { + GetFriendInfos(); + }); + + Thread.Sleep(1000); + + //获取群列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOMS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetContact(bool isUpdate) + { + try + { + var result = GetFriendInfos(true); + + var socketClient = EasySoc.GetSocket(); + CommonResult msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvFriendList; + msg.Data = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + /// + /// 获取好友列表 + /// + /// 刷新缓存数据 + /// + //public override List GetFriendInfos(bool flushGroupsCache = false) + public override string GetFriendInfos(bool flushGroupsCache = false) + { + List friends = null; + try + { + #region 获取缓存数据 + friends = User.Friends.Where(f => !f.wxid.Contains("@chatroom")).ToList(); + if (!flushGroupsCache && friends.Count != 0) + return JsonConvert.SerializeObject(friends); + #endregion + + if (!User.IsGetFriend) + { + //获取好友列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_FRIENDS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + User.IsGetFriend = true; + } + + var result_ = Task.Factory.StartNew>(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (!User.IsGetFriend) + { + friends = User.Friends.Where(f => !f.wxid.Contains("@chatroom")).ToList(); + return friends; + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + return JsonConvert.SerializeObject(friends); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "#__#"); + } + return string.Empty; + } + + /// + /// 获取群列表 + /// + public override void GetGroupsNotInMember() + { + try + { + //获取群列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOMS_MSG, data = new { } }); + SendWeChatData(User.DwClientId, json); + + var result = Task.Factory.StartNew(delegate () + { + Thread.Sleep(4000); + var groups = User.Friends.Where(f => f.wxid.Contains("@chatroom")).ToList(); + return groups == null ? string.Empty : HttpHelper.ObjectToJson(new Dictionary>() { { "data", groups } }); + }).Result; + + if (result == null) + result = HttpHelper.ObjectToJson(new Dictionary>() { { "data", User.Friends.Where(f => f.wxid.Contains("@chatroom")).ToList() } }); + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = result; + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 通过用户id查询用户 + /// + /// + public override void GetWxidInfo(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_WXID_MSG, data = new { wxid = wxid } }); + var u = User.Friends.FirstOrDefault(f => f.wxid == wxid); + if (u == null) + { + SendWeChatData(User.DwClientId, json); + var friend = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + u = User.Friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) return u; + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + var socketClient = EasySoc.GetSocket(); + WechatContact msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = u == null ? string.Empty : HttpHelper.ObjectToJson(u); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 通过群号查询指定的用户 + /// + /// 要查询群号 + /// 要查询的用户 + public override void GetGroupAndFriendInfo(string groupId, string wxid) + { + try + { + GroupInfo group = null; + FriendInfo u = null; + if (groupId.Contains("@chatroom") || groupId.Contains("@im.chatroom")) + { + var g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + } + + if (group == null) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = groupId } }); + SendWeChatData(User.DwClientId, json); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + { + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + if (group == null) group = new GroupInfo() { wxid = groupId, friends = new List() { new FriendInfo() { wxid = wxid } }, total_member = 1 }; + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 通过群号查询指定的用户 + /// + /// 要查询群号 + /// 要查询的用户 + public override void GetGroupAndFriendInfo(string groupId, string wxid, bool flush = false) + { + try + { + GroupInfo group = null; + FriendInfo u = null; + if (groupId.Contains("@chatroom") || groupId.Contains("@im.chatroom")) + { + var g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + if (flush) + { + g.friends.Clear(); + UpdateGroupInfo(groupId); + Thread.Sleep(100); + } + else + { + u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + } + } + + if (group == null) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = groupId } }); + SendWeChatData(User.DwClientId, json); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + g = User.Groups.FirstOrDefault(f => f.wxid == groupId); + if (g != null) + { + u = g.friends.FirstOrDefault(f => f.wxid == wxid); + if (u != null) + { + group = new GroupInfo() { wxid = groupId, friends = new List() { u }, total_member = g.total_member }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + if (group == null) group = new GroupInfo() { wxid = groupId, friends = new List() { new FriendInfo() { wxid = wxid } }, total_member = 1 }; + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + public override void UpdateWxidInfo(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_UPDATE_WXID_MSG, data = new { wxid = wxid } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void UpdateGroupInfo(string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_UPDATE_ROOM_MEMBER_MSG, data = new { wxid = groupId } }); + SendWeChatData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetFriend(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DATA_WXID_MSG, data = new { wxid = wxid } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 浏览器 + /// + //public void MtOpenBrowserMsg(string url) + //{ + // try + // { + // var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_OPEN_BROWSER_MSG, data = new { url = url } }); + // SendWeChatData(this.User.DwClientId, json); + // } + // catch (Exception ex) + // { + // LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + // } + //} + + public override void CloseWechat(string message) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == User.DwClientId && f.Value.Type == WechatType.Xiaoxie).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"CloseWechat事件退出,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v, true); + if (!string.IsNullOrWhiteSpace(message)) + PCRobotForm.ErrorMessAction?.Invoke(message); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 检测URL在微信中是否有效 + /// + /// 要检测的网址 + public override void CheckUrl(string url) + { + try + { + url = url.Trim(); + if (!string.IsNullOrWhiteSpace(url)) + { + //var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CHECK_URL_STATUS_MSG, data = new { url = url } }); + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CHECK_URL_STATUS2_MSG, data = new { url = url } }); + SendWeChatData(this.User.DwClientId, json); + } + var result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + //if (CheckUrlCache.ContainsKey(url)) return CheckUrlCache[url]; + Cache cache = HttpRuntime.Cache; + object item = cache[url]; + if (item != null) + return int.Parse(item.ToString()); + } while (awaitTime >= DateTime.Now); + return -1; + }).Result; + + var socketClient = EasySoc.GetSocket(); + var msg = new CheckUrl(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvCheckUrl; + msg.Status = result; + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void OpenUrl(string url) + { + try + { + url = url.Trim(); + if (!string.IsNullOrWhiteSpace(url)) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_OPEN_BROWSER_MSG, data = new { url = url } }); + SendWeChatData(this.User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + /// + /// 清理历史聊天记录 + /// + /// + public override void ClearChatHistoryMsg() + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CLEAR_CHAT_HISTORY_MSG, data = new { } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 设置会话已读 + /// + /// + public override void SetSessionReadedMsg(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SET_SESSION_READED_MSG, data = new { wxid = wxid } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 修改群聊名称 + /// + /// 新的群名 + /// 群id + public override void SetRoomName(string new_name, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_NAME_MSG, data = new { room_wxid = groupId, name = new_name } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 修改群公告(可用于@全体) + /// + /// 新公告 + /// 群聊wxid + public override void SetRoomNotice(string notice, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_NOTICE_MSG, data = new { room_wxid = groupId, notice = notice } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 设置自己在群中昵称 + /// + /// 要设置的昵称 + /// 需要设置的群id + public override void ModRoomMyName(string nickname, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_MEMBER_NAME_MSG, data = new { room_wxid = groupId, nickname = nickname } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 设置是否显示群成员昵称 + /// + /// true为开启 + /// 要显示得到群 + public override void SetRoomShowMemeberName(bool status, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_SHOW_NAME_MSG, data = new { room_wxid = groupId, status = status ? 1 : 0 } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 修改群聊名称 + /// + /// 新名称 + /// 群号 + public override void ModRoomName(string newnick, string groupId) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_ROOM_NAME_MSG, data = new { room_wxid = groupId, name = newnick } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 是否消息免打扰 + /// + /// true为开启 + /// wxid + public override void SetRecvNotify(bool status, string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_MOD_RECV_NOTIFY_MSG, data = new { wxid = wxid, status = status ? 1 : 0 } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 关注公众号 + /// + /// 公众号wxid + public override void AddPublicUser(string wxid) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_ADD_PUBLIC_USER_MSG, data = new { wxid = wxid } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 开启/关闭防撤回功能 + /// + /// 1是开启防撤回,0是关闭 + public override void SetDisableRevoke(bool status) + { + try + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_DISABLE_REVOKE_MSG, data = new { status = status ? 1 : 0 } }); + SendWeChatData(this.User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + + + #region 内部类 + + public enum MsgType : ushort + { + /// + /// DEBUG消息 + /// + MT_DEBUG_LOG = 11024, + /// + /// 登录消息 + /// + MT_USER_LOGIN = 11025, + /// + /// 注销消息 + /// + MT_USER_LOGOUT = 11026, + /// + /// 数据库查询消息 + /// + MT_SQL_QUERY = 11027, + /// + /// 获取我的信息消息 + /// + MT_DATA_OWNER_MSG = 11028, + /// + /// 获取单个好友消息 + /// + MT_DATA_WXID_MSG = 11029, + /// + /// 获取好友列表消息 + /// + MT_DATA_FRIENDS_MSG = 11030, + /// + /// 获取群聊列表消息 + /// + MT_DATA_CHATROOMS_MSG = 11031, + /// + /// 获取群成员消息 + /// + MT_DATA_CHATROOM_MEMBERS_MSG = 11032, + /// + /// 获取公众号消息 + /// + MT_DATA_PUBLICS_MSG = 11033, + /// + /// 从网络更新单个好友信息消息 + /// + MT_UPDATE_WXID_MSG = 11034, + /// + /// 从网络更新群成员信息消息 + /// + MT_UPDATE_ROOM_MEMBER_MSG = 11035, + /// + /// 发送文本消息 + /// + MT_SEND_TEXTMSG = 11036, + /// + /// 发送群@消息 + /// + MT_SEND_CHATROOM_ATMSG = 11037, + /// + /// 发送名片消息 + /// + MT_SEND_CARDMSG = 11038, + /// + /// 发送链接消息 + /// + MT_SEND_LINKMSG = 11039, + /// + /// 发送图片消息 + /// + MT_SEND_IMGMSG = 11040, + /// + /// 发送文件消息 + /// + MT_SEND_FILEMSG = 11041, + /// + /// 发送视频消息 + /// + MT_SEND_VIDEOMSG = 11042, + /// + /// 发送GIF消息 + /// + MT_SEND_GIFMSG = 11043, + /// + /// 接收文本消息 + /// + MT_RECV_TEXT_MSG = 11046, + /// + /// 接收图片消息 + /// + MT_RECV_PICTURE_MSG = 11047, + /// + /// 接收语音消息 + /// + MT_RECV_VOICE_MSG = 11048, + /// + /// 接收申请好友消息 + /// + MT_RECV_FRIEND_MSG = 11049, + /// + /// 接收名片消息 + /// + MT_RECV_CARD_MSG = 11050, + /// + /// 接收视频消息 + /// + MT_RECV_VIDEO_MSG = 11051, + /// + /// 接收表情消息 + /// + MT_RECV_EMOJI_MSG = 11052, + /// + /// 接收位置消息 + /// + MT_RECV_LOCATION_MSG = 11053, + /// + /// 接收链接消息 + /// + MT_RECV_LINK_MSG = 11054, + /// + /// 接收文件消息 + /// + MT_RECV_FILE_MSG = 11055, + /// + /// 接收小程序消息 + /// + MT_RECV_MINIAPP_MSG = 11056, + /// + /// 接收好友转账消息 + /// + MT_RECV_WCPAY_MSG = 11057, + /// + /// 接收系统消息 + /// + MT_RECV_SYSTEM_MSG = 11058, + /// + /// 接收撤回消息 + /// + MT_RECV_REVOKE_MSG = 11059, + /// + /// 接收其他未知消息 + /// + MT_RECV_OTHER_MSG = 11060, + /// + /// 接收应用类型未知消息 + /// + MT_RECV_OTHER_APP_MSG = 11061, + /// + /// 发送加好友消息 + /// + MT_ADD_FRIEND_MSG = 11062, + /// + /// 发送修改好友备注消息 + /// + MT_MOD_FRIEND_REMARK_MSG = 11063, + /// + /// 发送删除好友消息 + /// + MT_DEL_FRIEND_MSG = 11064, + /// + /// 发送同意加好友申请消息 + /// + MT_ACCEPT_FRIEND_MSG = 11065, + /// + /// 发送接收好友转帐消息 + /// + MT_ACCEPT_WCPAY_MSG = 11066, + /// + /// 发送同意进群邀请消息 + /// + MT_ACCEPT_ROOM_MSG = 11067, + /// + /// 发送创建群聊消息 + /// + MT_CREATE_ROOM_MSG = 11068, + /// + /// 发送邀请好友进群消息,40人以下 + /// + MT_INVITE_TO_ROOM_MSG = 11069, + /// + /// 发送邀请好友进群消息,40人以上 + /// + MT_INVITE_TO_ROOM_REQ_MSG = 11070, + /// + /// 发送删除群成员消息 + /// + MT_DEL_ROOM_MEMBER_MSG = 11071, + /// + /// 发送修改群名称消息 + /// + MT_MOD_ROOM_NAME_MSG = 11072, + /// + /// 发送修改群通知消息 + /// + MT_MOD_ROOM_NOTICE_MSG = 11073, + /// + /// 发送修改我在本群的昵称消息 + /// + MT_MOD_ROOM_MEMBER_NAME_MSG = 11074, + /// + /// 发送修改显示群昵称消息 + /// + MT_MOD_ROOM_SHOW_NAME_MSG = 11075, + /// + /// 发送保存到联系人消息 + /// + MT_SAVE_ROOM_TO_CONTACT_MSG = 11076, + /// + /// 发送退出并删除群消息 + /// + MT_QUIT_DEL_ROOM_MSG = 11077, + /// + /// 发送消息免打扰消息 + /// + MT_MOD_RECV_NOTIFY_MSG = 11078, + /// + /// 发送置顶消息 + /// + MT_MOD_CHAT_SESSION_TOP_MSG = 11079, + /// + /// 发送无痕清粉消息 + /// + MT_ZOMBIE_CHECK_MSG = 11080, + /// + /// 发送自动同意好友申请消息 + /// + MT_AUTO_ACCEPT_FRIEND_MSG = 11081, + /// + /// 发送自动同意好友转帐消息 + /// + MT_AUTO_ACCEPT_WCPAY_MSG = 11082, + /// + /// 发送自动进群邀请消息 + /// + MT_AUTO_ACCEPT_ROOM_MSG = 11083, + /// + /// 发送自动加名片消息 + /// + MT_AUTO_ACCPET_CARD_MSG = 11084, + /// + /// 发送解密图片消息 + /// + MT_DECRYPT_IMG_MSG = 11085, + /// + /// 发送打开浏览器消息 + /// + MT_OPEN_BROWSER_MSG = 11086, + /// + /// 获取用户登录二维码,于2019年5月28日新增 + /// + MT_RECV_QRCODE_MSG = 11087, + /// + /// 窗口变化通知消息 + /// + MT_WX_WND_CHANGE_MSG = 11088, + /// + /// 发送和获取未读数量变动消息 + /// + MT_UNREAD_MSG_COUNT_CHANGE_MSG = 11089, + /// + /// 与指定人聊天 + /// + MT_TO_CHAT_MSG = 11090, + /// + /// 当前聊天对象改变 + /// + MT_TALKER_CHANGE_MSG = 11091, + /// + /// 通过二维码进群 + /// + MT_ACCEPT_QRCODE_ROOM_MSG = 11092, + /// + /// 单向加好友 + /// + MT_ACCEPT_ONEWAY_FRIEND_MSG = 11093, + /// + /// 设置微信版本号 + /// + MT_CUSTOM_WX_VERSION_MSG = 11094, + /// + /// 接收到二微码付款消息 + /// + MT_RECV_QRCODE_WCPAY_MSG = 11095, + /// + /// 通过手机号/微信号/QQ号查询联系人 + /// + MT_SEARCH_CONTACT_MSG = 11096, + /// + /// 添加通过手机号/微信号/QQ号查询的联系人 + /// + MT_ADD_SEARCH_CONTACT_MSG = 11097, + /// + /// 群成员新增通知 + /// + MT_ROOM_ADD_MEMBER_NOTIFY_MSG = 11098, + /// + /// 群成员删除通知 + /// + MT_ROOM_DEL_MEMBER_NOTIFY_MSG = 11099, + /// + /// 通过接口创建群聊的通知 + /// + MT_ROOM_CREATE_NOTIFY_MSG = 11100, + /// + /// 退群或被踢通知 + /// + MT_ROOM_DEL_NOTIFY_MSG = 11101, + /// + /// 联系人新增通知 + /// + MT_CONTACT_ADD_NOITFY_MSG = 11102, + /// + /// 联系人删除通知 + /// + MT_CONTACT_DEL_NOTIFY_MSG = 11103, + /// + /// 注销登录 + /// + MT_QUIT_LOGIN_MSG = 11104, + /// + /// 无需确认退出 + /// + MT_QUIT_WECHAT_MSG = 11105, + /// + /// 当点击微信托盘图标和未读消息时消息 + /// + MT_TRAYICON_SHOW_WINDOW_MSG = 11106, + /// + /// 退还朋友的转账 + /// + MT_REFUSE_FRIEND_WCPAY_MSG = 11107, + /// + /// 清除聊天记录 + /// + MT_CLEAR_CHAT_HISTORY_MSG = 11108, + /// + /// 获取收藏列表 + /// + MT_DATA_FAVITEMS_MSG = 11109, + /// + /// 发送收藏 + /// + MT_SEND_FAVITEM_MSG = 11110, + /// + /// 收藏指定消息 + /// + MT_ADD_FAVITEM_FROM_MSG = 11111, + /// + /// 语音翻译 + /// + MT_TRANS_VOICE_MSG = 11112, + /// + /// 发送XML消息 + /// + MT_SEND_XMLMSG = 11113, + /// + /// 发送名版XML消息 + /// + MT_SEND_CARD_XMLMSG = 11114, + /// + /// 关注公众号 + /// + MT_ADD_PUBLIC_USER_MSG = 11115, + /// + /// 转发小程序 + /// + MT_FORWARD_APP_MSG = 11118, + /// + /// 开启/关闭防撤回消息 + /// + MT_DISABLE_REVOKE_MSG = 11121, + /// + /// 设置会话为已读 + /// + MT_SET_SESSION_READED_MSG = 11122, + /// + /// 检测URL在微信中是否有效 + /// + MT_CHECK_URL_STATUS_MSG = 11123, + /// + /// 检测URL在微信中是否有效2 + /// + MT_CHECK_URL_STATUS2_MSG = 11135, + /// + /// 微信二维码识别 + /// + //MT_SCAN_QRCODE_IMG_MSG = 11127, + /// + /// 自动授权登录小程序 + /// + MT_SNS_AUTO_AUTH_MINIAPP_LOGIN = 11136, + /// + /// 获取朋友圈首页 + /// + MT_SNS_TIMELINE_MSG = 11145, + /// + /// 评论 + /// + MT_SNS_COMMENT_MSG = 11146, + /// + /// 点赞 + /// + MT_SNS_LIKE_MSG = 11147, + /// + /// 发朋友圈 + /// + MT_SNS_POST_MSG = 11148, + /// + /// 朋友圈上传图片 + /// + MT_SNS_UPLOAD_IMAGE_MSG = 11149, + /// + /// 获取指定用户的朋友圈 + /// + MT_SNS_TIMELINE_USER_MSG = 11150, + } + + enum _EnRawMsgType + { + /// + /// 0x1 文本 + /// + WX_MSG_TEXT = 1, + /// + /// 0x3 图片 + /// + WX_MSG_PICTURE = 3, + /// + /// 0x22 语音 + /// + WX_MSG_VOICE = 34, + /// + /// 0x25 加好友请求 "from_wxid" : "fmessage" + /// + WX_MSG_FRIEND = 37, + /// + /// 0x2A 名片 + /// + WX_MSG_CARD = 42, + /// + /// 0x2B 视频 + /// + WX_MSG_VIDEO = 43, + /// + /// 0x2F 表情 + /// + WX_MSG_EMOJI = 47, + /// + /// 0x30 位置 + /// + WX_MSG_LOCATION = 48, + /// + /// 0x31 应用类型,子类型参考EnRawAppMsgType + /// + WX_MSG_APP = 49, + /// + /// 0x2710 系统消息 + /// + WX_MSG_SYSTEM = 10000, + /// + /// 0x2712 撤回消息 + /// + WX_MSG_REVOKE = 10002, + } + //EnRawMsgType; + // XML XPATH路径 /msg/appmsg/type/text() + enum _EnRawAppMsgType + { + /// + /// 链接(包含群邀请) + /// + WX_APPMSG_LINK = 5, + /// + /// 文件 + /// + WX_APPMSG_FILE = 6, + /// + /// 合并消息 + /// + WX_APPMSG_MUTIL = 19, + /// + /// 小程序 + /// + WX_APPMSG_MINIAPP = 33, + /// + /// 转帐 + /// + WX_APPMSG_WCPAY = 2000, + } + //EnRawAppMsgType; + #endregion + + } +} diff --git a/PCRobot/PCWechat/Wechat_Xiaoxie_QY - 3.1.10.3010.cs b/PCRobot/PCWechat/Wechat_Xiaoxie_QY - 3.1.10.3010.cs new file mode 100644 index 0000000..f611e8a --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Xiaoxie_QY - 3.1.10.3010.cs @@ -0,0 +1,2455 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using NM_WeChat; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Properties; +using PCRobot.Utils; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; + +namespace PCRobot.PCWechat +{ + + /* + 接口文档:https://www.showdoc.cc/WxWorkNewHook?page_id=3846144660177490 + /////密码:784615627. + */ + + public class Wechat_Xiaoxie_QY : BaseApi + { + #region 注入等操作 + public delegate void AcceptCallbackFunc(uint dwClientId); + public delegate void RecvCallbackFunc(uint dwClientId, IntPtr intPtr, uint dwSize); + public delegate void CloseCallbackFunc(uint dwClientId); + + private static AcceptCallbackFunc m_AcceptCallbackFunc; + private static RecvCallbackFunc m_RecvCallbackFunc; + private static CloseCallbackFunc m_CloseCallbackFunc; + + // 引入DLL导出函数 + //[DllImport("Bin\\WeChatServer_QY.dll")] + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool InitWxWorkSocket(AcceptCallbackFunc acceptCallback, + RecvCallbackFunc recvCallback, CloseCallbackFunc closeCallback); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWork(byte[] strDllPath, byte[] strWxWorkExePath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWorkMultiOpen(byte[] strDllPath, byte[] strWxWorkExePath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool SendWxWorkData(uint dwClienId, byte[] strJsonData); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool DestroyWxWork(); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWorkPid(int dwPid, byte[] strDllPath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool UseUtf8(); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool GetUserWxWorkVersion(StringBuilder v); + + [DllImport("Bin\\WxWorkLoader.dll", EntryPoint = "SendWxWorkData")] + public static extern bool _SendWxWorkData(uint dwClienId, byte[] strJsonData); + + public bool SendWxWorkData(uint dwClienId, string strJsonData) + { + var ss = User.DwClientId; + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("_调试发送_", $"{dwClienId} -> {strJsonData} - {User != null} - 微信id:{User?.Wxid}"); + + if (User != null && !string.IsNullOrEmpty(User.Wxid)) + { + var json = HttpExtend.JsonToDictionary(strJsonData); + var type = json["type"].ToString(); + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试发送@转换失败", $"{dwClienId} -> type:{type}"); + return false; + } + switch (msgType) + { + //截取发送消息 - 为是否是辅助输入提供判断 + + case MsgType.MT_SEND_TEXT_MSG:// 发送文本消息 + case MsgType.MT_SEND_IMAGE_MSG:// 发送图片消息 + case MsgType.MT_SEND_FILE_MSG:// 发送文件消息 + case MsgType.MT_SEND_FOLDER_MSG:// 发送目录消息 + case MsgType.MT_SEND_LINK_MSG:// 发送链接消息 + //case MsgType.MT_SEND_PERSON_CARD_MSG:// 发送个人名片 + case MsgType.MT_SEND_VIDEO_MSG:// 发送视频 + { + json = json["data"] as Dictionary; + + string conversation_id = json["conversation_id"].ToString(); + var to_wxid = conversation_id; + if (conversation_id.StartsWith("S:"))//私人消息处理一下,群消息不用管 + { + to_wxid = conversation_id.Replace($"S:{User.Wxid}_", ""); + } + string message = string.Empty; + if (json.ContainsKey("content")) message = json["content"].ToString(); + else if (json.ContainsKey("card_wxid")) message = json["card_wxid"].ToString(); + else if (json.ContainsKey("file")) message = json["file"].ToString(); + //else if (json.ContainsKey("user_id")) message = json["user_id"].ToString(); + if (!string.IsNullOrEmpty(message)) + { + Common.SetCache(User.Wxid, to_wxid, message); + } + } + break; + } + } + return _SendWxWorkData(dwClienId, Encoding.UTF8.GetBytes(strJsonData)); + } + + static string DllPath = HttpExtend.MapFile($"WxWorkHelper_{Version}.dll", "Bin"); + + + //private const string Version = "3.0.27.2701"; + //private const string PcMd5 = "DE820FFBA84BC8E4C89A9C4857420BB7";//3.0.27.2701 + + //private const string Version = "3.1.1.3001"; + //private const string PcMd5 = "7EBF31BC0617397614E72907260B2A15";//3.1.1.3001 + + private const string Version = "3.1.10.3010"; + private const string PcMd5 = "5E7DF89ECC5FC04F1ECB96C1EE72F17E";//3.1.10.3010 + + public override string GetVersion() + { + return Version; + } + + public Wechat_Xiaoxie_QY(WechatUser User) : base(User) { } + + public static void Install() + { + if (IsQYInstall) return; + try + { + m_AcceptCallbackFunc = WxAcceptCallback; + m_RecvCallbackFunc = WxRecvCallback; + m_CloseCallbackFunc = WxCloseCallback; + + UseUtf8(); + // 初始化Callback + InitWxWorkSocket(m_AcceptCallbackFunc, m_RecvCallbackFunc, m_CloseCallbackFunc); + + StringBuilder sb = new StringBuilder(); + + var path1 = HttpExtend.MapPath("WXWork"); + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + + InitPc(); + } + catch (Exception) + { + + } + finally + { + IsQYInstall = true; + } + } + + /// + /// 是否替换 + /// + private static bool IsReplace = false; + /// + /// pj文件需要杀死进程,并替换文件 + /// + public static void PJFileReplace() + { + if (IsReplace) return; + IsReplace = true; + try + { + KillPc(); + + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + var fixName = HttpExtend.MapFile("Fix2.dll", path2); + var msimgName = HttpExtend.MapFile("msimg32.dll", path2); + //if (!Environment.Is64BitOperatingSystem) + //{ + // #region 32位系统 + // //Util.WriteResource(fixName, Resources.Fix2_QY_32); + // //Util.WriteResource(msimgName, Resources.msimg32_QY_32); + // #endregion + //} + //else + //{ + // #region 64位系统 + // Util.WriteResource(fixName, Resources.Fix2_QY); + // Util.WriteResource(msimgName, Resources.msimg32_QY); + // #endregion + //} + + //Util.WriteResource(fixName, Resources.Fix2_QY); + //Util.WriteResource(msimgName, Resources.msimg32_QY); + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 杀死注入 pc + /// + /// + private static void KillPc(bool isInject = false) + { + Process[] MyProcesses = Process.GetProcesses(); + + var path1 = HttpExtend.MapPath("WXWork"); + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == "WXWORK" && MyProcess.MainModule.FileName.StartsWith(path1)) + { + try + { + //判断微信版本 + if (MyProcess.MainModule.FileName.StartsWith(path2)) + { + var id = MyProcess.Id; + if (isInject) + { + var result = Task.Factory.StartNew(delegate + { + try + { + var WechatWinFile = CsharpHttpHelper.HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + var md5 = Common.GetMD5Hash(WechatWinFile).ToUpper(); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + return false; + } + else + { + LogHelper.GetSingleObj().Info("系统", $"开始企业注入进程:{id}..."); + var uin = InjectWxWorkPid(id, Encoding.UTF8.GetBytes(DllPath)); + LogHelper.GetSingleObj().Info("系统", $"注入企业成功:{id},句柄ID:{uin}"); + return true; + } + } + catch (Exception) + { } + return false; + }).Wait(20000); + if (!result) + { + try + { + LogHelper.GetSingleObj().Info("系统cc", "杀死企业进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + else + { + try + { + LogHelper.GetSingleObj().Info("主动dd", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + } + catch (Exception) + { } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } + + private static void InitPc() + { + if (Util.IsLinshi()) + PJFileReplace(); + else + { + IsReplace = false; + var isZanYong = DeletePJFile(); + + KillPc(!isZanYong); + if (isZanYong) + { + isZanYong = DeletePJFile(); + if (isZanYong) + throw new Exception("文件处理异常,,"); + } + } + } + + /// + /// 破解文件是否暂用 + /// + /// + private static bool DeletePJFile() + { + var isZanYong = false; + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + + var fixName = HttpExtend.MapFile("Fix2.dll", path2); + var msimgName = HttpExtend.MapFile("msimg32.dll", path2); + try + { + if (File.Exists(fixName)) + File.Delete(fixName); + if (File.Exists(msimgName)) + File.Delete(msimgName); + } + catch (Exception ex) + { + isZanYong = true; + } + return isZanYong; + } + + private static string RemoteCache = "get_login_code_cache_workwechat"; + + /// + /// 等待登录结果 + /// + public static Dictionary WaitLoginResult = new Dictionary(); + + /// + /// 远程登录微信 + /// + public static List RemoteLoginCodes = new List(); + + /// + /// pc微信登录二维码 + /// + /// + public static void LoginQrcode(string ServerMsgID) + { + try + { + RemoteLoginCode result = null; + try + { + string downloadsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + var wxConfig = HttpExtend.MapFile(@"Config.cfg", downloadsPath + @"\WXWork\Global"); + if (File.Exists(wxConfig)) + { + try + { + File.Delete(wxConfig); + } + catch (Exception) + { } + StartWechat(true); + } + } + catch (Exception ex) + { + result = new RemoteLoginCode() { pid = -1, rType = RobotType.客户端企业微信, b64Md5 = ex.Message }; + } + + if (result == null) + { + result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[RemoteCache]; + if (item != null) + { + cache.Remove(RemoteCache); + var r = item as RemoteLoginCode; + return r; + } + } while (awaitTime >= DateTime.Now); + return null; + }).Result; + } + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = string.Empty; + msg.RobotUsernick = string.Empty; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvLoginCode_workWeChat; + msg.Data = result == null ? string.Empty : JsonConvert.SerializeObject(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 卸载安装 + /// + public static void UnInstall() + { + try + { + //DestroyWxWork(); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".."); + } + } + #endregion + + private static Dictionary MT_APP_READY_MSG_BIND = new Dictionary(); + + private static readonly object Friend_Lock = new object(); + + // 接收消息回调 + private static void WxRecvCallback(uint _dwClient, IntPtr intPtr, uint dwSize) + { + + try + { + byte[] body = new byte[dwSize]; + Marshal.Copy(intPtr, body, 0, body.Length); + var recvData = Encoding.UTF8.GetString(body).Replace("\0", "").Trim();//再转成UTF8 + + var dwClientid = _dwClient; + + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试企业收到文本消息", $"{dwClientid} -> {recvData}\r\n"); + + //var method = new Action(delegate () + Task.Factory.StartNew(delegate () + { + try + { + Console.WriteLine("企业收到消息:" + recvData); + + var json = CsharpHttpHelper.HttpExtend.JsonToDictionary(recvData); + var type = json["type"].ToString(); + var data = json.ContainsKey("data") ? json["data"] as Dictionary : null; + + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return; + Console.WriteLine($"dwClientid = {dwClientid}"); + switch (msgType) + { + case MsgType.MT_APP_READY_MSG: + MT_APP_READY_MSG_BIND[dwClientid] = int.Parse(data["pid"].ToString()); + break; + case MsgType.MT_PARAMS_ERROR_MSG: + { } + break; + case MsgType.MT_USER_LOGIN://登陆消息 + { + var wxid = data["user_id"].ToString(); + var user = WechatClient.GetUser(wxid, dwClientid, WechatType.Xiaoxie_QY); + user.Nickname = data["username"].ToString(); + user.HeaderUrl = data["avatar"].ToString(); + //user.DBFile = data["wx_user_dir"].ToString(); + user.Pid = MT_APP_READY_MSG_BIND.ContainsKey(dwClientid) ? MT_APP_READY_MSG_BIND[dwClientid] : 0; //uint.Parse(data["pid"].ToString()); + user.Phone = data["mobile"].ToString(); + user.Uin = wxid; + WechatClient.OnRefUserEvent(user, WaitLoginResult); + } + break; + case MsgType.MT_USER_LOGOUT: + { + var wxid = data["user_id"].ToString(); + var user = WechatClient.Users.FirstOrDefault(f => f.Key == wxid).Value; + if (user != null) + { + LogHelper.GetSingleObj().Info("系统", $"LogOut_QY事件退出,Uin:{user.Uin},微信:{user.Nickname}({wxid})"); + WechatClient.RemoveUser(user); + } + } + break; + case MsgType.MT_LOGIN_QRCODE_MSG: + { + //{"data":{"file":"C:\\Users\\秒单客006\\Documents\\WXWork\\Global\\Image\\089d9de9-cc40-458a-af4a-b39a04e2f95f.jpg"},"type":11028} + if (!data.ContainsKey("file")) return; + if (MT_APP_READY_MSG_BIND.ContainsKey(dwClientid)) + { + var file = data["file"].ToString(); + + if (File.Exists(file)) + { + var cfBase64 = Common.ConvertImageToBase64(Image.FromFile(file)); + + var codeInfo = new RemoteLoginCode() { pid = MT_APP_READY_MSG_BIND[dwClientid], cImgB64 = cfBase64, b64Md5 = HttpHelper.ToMD5(cfBase64), rType = RobotType.客户端企业微信, t = HttpExtend.GetTimeStamp(DateTime.Now) }; + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[RemoteCache]; + cache.Insert(RemoteCache, codeInfo, null, DateTime.Now.AddSeconds(3), Cache.NoSlidingExpiration); + + RemoteLoginCodes.Add(codeInfo); + } + } + } + break; + case MsgType.MT_RECV_MINIAPP_MSG://收到小程序 + { + //个人微信/企业微信 + //{"data":{"content_type":78,"conversation_id":"R:10696053211018728","enterpoint":"pages/tab/home/index.html?_um_ssrc=oucfI5QRI-8SbyOTKSGYt5-ia0dk&_um_sts=1610033684099","ghid":"gh_a0d7a7672cf7@app","headimg":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM43LsxpXHKd7ua7kwMZQ8WHmZlkYTzr3Tdm8sMOJ7Ypog/96","image_key1":"306b020102046430620201000204bafc490e02030f4df9020473e6607102045ff72a530436333133373039353935305f313734393433343231315f3262393764653133616335373232353633383831336564376334396563616164020100020300ab1004000201010201000400","image_key2":"61747072666A766977766D69726D6168","image_key3":"2b97de13ac57225638813ed7c49ecaad","image_size":43791,"is_pc":0,"local_id":"155","name":"啄木鸟家庭维修","receiver":"1688853956558440","send_time":"1610033747","sender":"7881302484994318","sender_name":"、","server_id":"1042188","title":"直营一口价,维修无猫腻","wxid":"wx3d6b1af0cb07fa5a"},"type":11066} + + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + + //var content_type = data["content_type"]?.ToString();//内容类型 78 + //var conversation_id = data["conversation_id"]?.ToString();//接收者的的会话ID + //var enterpoint = data["enterpoint"]?.ToString();//入口点 - 链接(小程序里面的链接) + //var receiver = data["receiver"]?.ToString();// 接收者的user_id + //var sender = data["sender"]?.ToString();// 发送者的user_id + //var sender_name = data["sender_name"]?.ToString();//发送者昵称 + //var server_id = data["server_id"]?.ToString();//消息的服务器ID + + var content_type = data["content_type"]?.ToString();//内容类型 78 + var conversation_id = data["conversation_id"]?.ToString();//接收者的的会话ID + var enterpoint = data["enterpoint"]?.ToString();//入口点 - 链接(小程序里面的链接) + var headimg = data["headimg"]?.ToString();//小程序的头像 + var name = data["name"]?.ToString();//小程序的名称 + var receiver = data["receiver"]?.ToString();// 接收者的user_id + var sender = data["sender"]?.ToString();// 发送者的user_id + var sender_name = data["sender_name"]?.ToString();//发送者昵称 + var title = data["title"]?.ToString();//小程序标题 + var wxid = data["wxid"]?.ToString(); + var server_id = data["server_id"]?.ToString();//消息的服务器ID + + var isSend = false; + var RobotUsername = string.Empty; + var RobotUsernick = string.Empty; + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + //if (content_type != "78")//0自己发送的消息 + //{ + // if (!WechatClient.IsAuxiliaryInput(sender, receiver, enterpoint)) + // { + // Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + enterpoint); + // return; + // } + + // var ass = WechatClient.IsAssistance(sender, receiver, dwClientid, WechatType.Xiaoxie_QY); + // if (ass.type == WechatClient.AssistanceType.终止) return; + // isSend = ass.type == WechatClient.AssistanceType.辅助; + + // RobotUsername = ass.robotName; + // RobotUsernick = ass.robotNick; + // FromUsername = ass.fromName; + // FromUsernick = ass.fromNick; + //} + //else + //{ + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + RobotUsername = user.Wxid; + RobotUsernick = user.Nickname; + FromUsername = sender; + FromUsernick = sender_name; + //} + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + wmsg.IsSend = isSend; + wmsg.RobotUsername = RobotUsername; + wmsg.RobotUsernick = RobotUsernick; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (conversation_id.Contains("R:")) + { + wmsg.FromGroupid = conversation_id; + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + else + { + wmsg.FromUsername = FromUsername; + wmsg.FromUsernick = FromUsernick; + } + wmsg.FromMessage = enterpoint.Replace("pages/index/index.html?goods_id=", "https://mobile.yangkeduo.com/goods.html?goods_id=").Replace("pages/item/detail/detail.html?sku=", @"https://item.jd.com/"); + + socketClient.Send(wmsg); + + } + break; + case MsgType.MT_RECV_TEXT_MSG://收到文本 + { + + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + + var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + #region 文本消息 + + #region 消息样式 + //{"data":{"content":"我17","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"19","receiver":"1688853956558440","send_time":"1584013142","sender":"7881301610989604","sender_name":"17","server_id":"1000481"},"type":11041} - 通过好友返回的数据 + //{"data":{"content":"哦哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"33","receiver":"1688853956558440","send_time":"1584014191","sender":"7881301610989604","sender_name":"17","server_id":"1000520"},"type":11041} - 别人给我发了条消息 + //{"data":{"content":"图婆","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"36","receiver":"1688853956558440","send_time":"1584014736","sender":"7881301610989604","sender_name":"17","server_id":"1000542"},"type":11041} + + //{"data":{"content":"哦哦哦","content_type":0,"conversation_id":"S:1688853956450720_1688853956558440","local_id":"22","receiver":"1688853956450720","send_time":"1584013962","sender":"1688853956558440","sender_name":"华","server_id":"1000498"},"type":11041} - 收到自己发的消息 + //{"data":{"content":"给我发条消息","content_type":0,"conversation_id":"S:1688853956450720_1688853956558440","local_id":"23","receiver":"1688853956450720","send_time":"1584014066","sender":"1688853956558440","sender_name":"华","server_id":"1000500"},"type":11041} + + //{"data":{"content":"饿的","content_type":0,"conversation_id":"R:10696053211008104","local_id":"42","receiver":"R:10696053211008104","send_time":"1584015069","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000574"},"type":11041} - 收到自己发送的群消息 + + #endregion + + //{"data":{"at_list":[],"content":"我是机器学习","content_type":2,"conversation_id":"S:1688853764215634_7881300713013122","local_id":"27946","receiver":"1688853764215634","send_time":"1589009390","sender":"7881300713013122","sender_name":"机器学习","server_id":"1088720"},"type":11041} + //0、2 - 发送的文字 (0) + if (content_type == "0" || content_type == "2") + { + var content = data["content"]?.ToString(); //文本消息内容 + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = data["send_time"]?.ToString(); //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + + var isSend = false; + var RobotUsername = string.Empty; + var RobotUsernick = string.Empty; + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + if (content_type == "0")//0自己发送的消息 + { + if (!WechatClient.IsAuxiliaryInput(sender, receiver, content)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + content); + return; + } + + var ass = WechatClient.IsAssistance(sender, receiver, dwClientid, WechatType.Xiaoxie_QY); + if (ass.type == WechatClient.AssistanceType.终止) return; + isSend = ass.type == WechatClient.AssistanceType.辅助; + + RobotUsername = ass.robotName; + RobotUsernick = ass.robotNick; + FromUsername = ass.fromName; + FromUsernick = ass.fromNick; + } + else + { + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + RobotUsername = user.Wxid; + RobotUsernick = user.Nickname; + FromUsername = sender; + FromUsernick = sender_name; + } + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + wmsg.IsSend = isSend; + wmsg.RobotUsername = RobotUsername; + wmsg.RobotUsernick = RobotUsernick; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (conversation_id.Contains("R:")) + { + wmsg.FromGroupid = conversation_id; + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + else + { + wmsg.FromUsername = FromUsername; + wmsg.FromUsernick = FromUsernick; + } + wmsg.FromMessage = content; + + socketClient.Send(wmsg); + } + #endregion + } + break; + case MsgType.MT_RECV_IMG_MSG://收到图片 + { + #region 图片消息 + + #region 消息样式 + + //{"data":{"content_type":101,"conversation_id":"R:10696053211008104","file_name":"7305d3cd-e94f-47db-a604-ce079e6c9ac5.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\7305d3cd-e94f-47db-a604-ce079e6c9ac5.jpg","file_size":19457,"local_id":"73","receiver":"1688853956558440","send_time":"1584028981","sender":"7881301364988874","sender_name":"18","server_id":"1000677"},"type":11042} - 别人在群发的图片 + + //{"data":{"content_type":101,"conversation_id":"S:1688853956558440_7881301364988874","file_name":"29c9c19d-e8d7-4cb0-95b5-e1a7d385003a.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\29c9c19d-e8d7-4cb0-95b5-e1a7d385003a.jpg","file_size":19457,"local_id":"74","receiver":"1688853956558440","send_time":"1584029032","sender":"7881301364988874","sender_name":"18","server_id":"1000680"},"type":11042} - 别人私聊发的图片 + + //{"data":{"content_type":14,"conversation_id":"R:10696053211008104","file_name":"0f7890b8ea01f7205a76d1195dab66b0.png","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\0f7890b8ea01f7205a76d1195dab66b0.png","file_size":1627,"local_id":"75","receiver":"R:10696053211008104","send_time":"1584029085","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000685"},"type":11042} - 自己群里发的图片 + + //{"data":{"content_type":14,"conversation_id":"S:1688853956558440_7881301364988874","file_name":"9c6d1a59d8f122fc85c3435ea2aa46fc.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\9c6d1a59d8f122fc85c3435ea2aa46fc.jpg","file_size":178092,"local_id":"76","receiver":"7881301364988874","send_time":"1584029534","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000689"},"type":11042} - 自己私聊发的图片 + + #endregion + + //14、101 (14) + + if (data == null) return; + + var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + if (content_type == "14") return; + + var socketClient = EasySoc.GetSocket(); + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = data["send_time"]?.ToString(); //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + var file_path = data["file_path"]?.ToString(); //图片路径 + + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvImg_workWeChat; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.IsSend = false; + wmsg.RobotUsername = user.Wxid; + wmsg.RobotUsernick = user.Nickname; + + wmsg.FromMessage = $"[图片={file_path}]"; + wmsg.FromMessageType = WechatMsgType.图片; + + if (conversation_id.Contains("R:")) + { + wmsg.FromGroupid = conversation_id; + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + else + { + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + wmsg.FromMessage = string.Empty; + + socketClient.Send(wmsg); + #endregion + } + break; + case MsgType.MT_RECV_VIDEO_MSG://收到视频 + { + #region 收到视频 + + #region 消息样式 + //{"data":{"content_type":103,"conversation_id":"S:1688853956558440_7881301364988874","duration":1,"file_name":"video.MP4","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Video\\2020-03\\video.MP4","file_size":198490,"height":960,"local_id":"77","receiver":"1688853956558440","send_time":"1584031142","sender":"7881301364988874","sender_name":"18","server_id":"1000691","width":544},"type":11043} - 别人发 + + //{"data":{"content_type":23,"conversation_id":"S:1688853956558440_7881301364988874","duration":1,"file_name":"video.MP4","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Video\\2020-03\\video.MP4","file_size":198490,"height":960,"local_id":"78","receiver":"7881301364988874","send_time":"1584031203","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000696","width":544},"type":11043} - 自己发 + #endregion + + //23、103 (23) + + if (data == null) return; + + var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + if (content_type == "23") return; + + var socketClient = EasySoc.GetSocket(); + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = data["send_time"]?.ToString(); //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + var file_path = data["file_path"]?.ToString(); //图片路径 + + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvFile_workWeChat; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.IsSend = false; + wmsg.RobotUsername = user.Wxid; + wmsg.RobotUsernick = user.Nickname; + + wmsg.FromMessage = $"[视频={file_path}]"; + wmsg.FromMessageType = WechatMsgType.视频; + + if (conversation_id.Contains("R:")) + { + wmsg.FromGroupid = conversation_id; + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + else + { + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + wmsg.FromMessage = string.Empty; + + socketClient.Send(wmsg); + + #endregion + } + break; + case MsgType.MT_RECV_VOICE_MSG://收到语音 + break; + case MsgType.MT_RECV_FILE_MSG://收到文件 + break; + case MsgType.MT_RECV_LOCATION_MSG://收到位置 + break; + case MsgType.MT_RECV_LINK_CARD_MSG://收到链接 + { + #region 链接消息 + + #region 消息样式 + //{"data":{"content_type":13,"conversation_id":"S:1688853956558440_7881301364988874","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"","local_id":"82","receiver":"1688853956558440","send_time":"1584033150","sender":"7881301364988874","sender_name":"18","server_id":"1000715","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 别人发送的私聊链接 + + //{"data":{"content_type":13,"conversation_id":"R:10696053211008104","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"","local_id":"85","receiver":"1688853956558440","send_time":"1584034341","sender":"7881301364988874","sender_name":"18","server_id":"1000724","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 别人发送的群聊链接 + + + //{"data":{"content_type":13,"conversation_id":"S:1688853956558440_7881301364988874","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"https://wework.qpic.cn/wwpic/51458_1ermIpIgTJu-_11_1584034011/0","local_id":"83","receiver":"7881301364988874","send_time":"1584034011","sender":"1688853956558440","sender_name":"吴","server_id":"1000720","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 自己发送的私聊 + + //{"data":{"content_type":13,"conversation_id":"R:10696053211008104","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"https://wework.qpic.cn/wwpic/51458_1ermIpIgTJu-_11_1584034011/0","local_id":"84","receiver":"R:10696053211008104","send_time":"1584034246","sender":"1688853956558440","sender_name":"吴","server_id":"1000722","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 自己发送的群聊 + + #endregion + + var content_type = data["content_type"]?.ToString(); + //if (content_type != "13") return; + + var socketClient = EasySoc.GetSocket(); + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var desc = data["desc"]?.ToString(); //链接描述 + var image_url = data["image_url"]?.ToString(); //链接缩略图url + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = data["send_time"]?.ToString(); //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + var title = data["title"]?.ToString(); //链接标题 + var url = data["url"]?.ToString(); //链接url + + var isSend = false; + var RobotUsername = string.Empty; + var RobotUsernick = string.Empty; + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + if (user.Wxid == sender) //0自己发送的消息 + { + if (!WechatClient.IsAuxiliaryInput(sender, receiver, url)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + url); + return; + } + + var ass = WechatClient.IsAssistance(sender, receiver, dwClientid, WechatType.Xiaoxie_QY); + if (ass.type == WechatClient.AssistanceType.终止) return; + isSend = ass.type == WechatClient.AssistanceType.辅助; + + RobotUsername = ass.robotName; + RobotUsernick = ass.robotNick; + FromUsername = ass.fromName; + FromUsernick = ass.fromNick; + } + else + { + RobotUsername = user.Wxid; + RobotUsernick = user.Nickname; + FromUsername = sender; + FromUsernick = sender_name; + } + + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + wmsg.IsSend = isSend; + wmsg.RobotUsername = RobotUsername; + wmsg.RobotUsernick = RobotUsernick; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (conversation_id.Contains("R:")) + { + wmsg.FromGroupid = conversation_id; + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + else + { + wmsg.FromUsername = FromUsername; + wmsg.FromUsernick = FromUsernick; + } + wmsg.FromMessage = url; + + socketClient.Send(wmsg); + + #endregion + } + break; + case MsgType.MT_RECV_EMOTION_MSG://收到表情 + break; + case MsgType.MT_RECV_RED_PACKET_MSG://收到红包 + { + } + break; + case MsgType.MT_RECV_PERSON_CARD_MSG://收到个人名片 + { + //{"data":{"content":"推荐噢噢噢哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"81","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000703"},"type":11041} + + /* + {"data":{"avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaELtKaBvIBMGI7xTZdLA9mZglMaZQxPeBASJT1lCXCJnKg/0","content_type":41,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"80","nickname":"??欧尼桑","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000700","source":"微信","user_id":"7881301516989639"},"type":11050} + 收到消息:{"data":{"content":"推荐噢噢噢哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"81","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000703"},"type":11041} + */ + + //var content = data["content"]?.ToString(); + //var content_type = data["content_type"]?.ToString(); + //var conversation_id = data["conversation_id"]?.ToString(); + //var local_id = data["local_id"]?.ToString(); + //var receiver = data["receiver"]?.ToString(); + //var send_time = data["send_time"]?.ToString(); + //var sender = data["sender"]?.ToString(); + //var sender_name = data["sender_name"]?.ToString(); + //var server_id = data["server_id"]?.ToString(); + + } + break; + case MsgType.MT_RECV_OTHER_MSG: + break; + case MsgType.MT_SEARCH_USER_MSG://查询联系人 + break; + case MsgType.MT_ADD_SEARCH_USER_MSG://添加查询的联系人 + break; + case MsgType.MT_MODIFY_USER_REMARK_MSG://修改用户备注 + break; + case MsgType.MT_MODIFY_USER_DESC_MSG: + break; + case MsgType.MT_MODIFY_EXTERNAl_USER_PHONES_MSG: + break; + case MsgType.MT_MODIFY_EXTERNAl_USER_COMPANY_MSG: + break; + case MsgType.MT_CREATE_ROOM_MSG: + { + } + break; + case MsgType.MT_MODIFY_ROOM_NAME_MSG: + break; + case MsgType.MT_ROOM_ADD_MEMBERS_MSG: + { + + } + break; + case MsgType.MT_ROOM_DEL_MEMBERS_MSG://删除群成员 + break; + case MsgType.MT_RECV_FRIEND_REQUEST://接收好友请求 + { + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/0T8yO33zeeg33jJCQibIWobapj6GX4xFBbOECtmG9VdkYpnzyiaUr5iag/0","corp_id":"1970325134026788","nickname":"17","sex":2,"user_id":"7881301610989604","verify":"我17"},"type":11063} + + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaEI8qvnXF9KjgTpvaSAzfhbE2kGoIspb7ibbEHGZEQxRibAQ/0","corp_id":"1970325134026788","nickname":"助将","sex":0,"user_id":"7881303410988876","verify":"欧珀new"},"type":11063} + + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/zroWGtm5tmsxaCHfI2ibibuBxtzsZc6brAIDCicIianoDYI/0","corp_id":"1970325134026788","nickname":"Boom","sex":1,"user_id":"7881303336175964","verify":"我是Boom"},"type":11063} + + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + + var avatar = data["avatar"]?.ToString();//头像 + var corp_id = data["corp_id"]?.ToString();//公司id + var nickname = data["nickname"]?.ToString();//申请人昵称 + var sex = data["sex"]?.ToString();//性别 + var user_id = data["user_id"]?.ToString();//用户id + var verify = data["verify"]?.ToString();//申请摘要 + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + var wXApply = new WorkWechatApplyFriend(); + wXApply.Cmd = PCRobotCMD.applyFriend_workWeChat; + wXApply.RobotUsername = user.Wxid; + wXApply.RobotUsernick = user.Nickname; + wXApply.RobotType = RobotType.客户端企业微信; + wXApply.Message = verify; + wXApply.NewFriendWxid = user_id; + wXApply.NewFriendNick = nickname; + wXApply.OldFriendWxid = string.Empty; + wXApply.OldFriendNick = string.Empty; + + wXApply.Token = CsharpHttpHelper.HttpHelper.ObjectToJson(new { user_id = user_id, corp_id = corp_id }); + + //记录申请人,用于记录 + if (!FriendRequestRecord.ContainsKey(user_id)) + FriendRequestRecord.TryAdd(user_id, new FriendInfo() { account = user_id, avatar = avatar, nickname = nickname, sex = int.Parse(sex), wxid = user_id }); + + socketClient.Send(wXApply); + } + break; + case MsgType.MT_ACCEPT_FRIEND_REQUEST://接受加好友请求 + break; + case MsgType.MT_GET_OWNER_INFO_MSG:// 获取自己信息 + { + + } + break; + case MsgType.MT_GET_INNER_USERS_MSG:// 获取内部联系人列表 + { + } + break; + case MsgType.MT_GET_EXTERNAL_USERS_MSG:// 获取外部联系列表 + { + #region 外部联系列表 + + #region 消息样式 + //{"data":[{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","corp_id":"1970325134026788","desc":"","external_job":"","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":"18"},{"avatar":"http://wx.qlogo.cn/mmhead/0T8yO33zeeg33jJCQibIWobapj6GX4xFBbOECtmG9VdkYpnzyiaUr5iag/0","conversation_id":"S:1688853956558440_7881301610989604","corp_id":"1970325134026788","desc":"","external_job":"","nickname":"","position":"","realname":"","remark":"","sex":0,"user_id":"7881301610989604","username":"17"},{"avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM6CiaVp63VVTIRySkxia2KSGQ6hrYAvAkkjoMpl4wFjyhIA/0","conversation_id":"S:1688853956558440_7881302509911391","corp_id":"1970325134026788","desc":"","external_job":"","nickname":"","position":"","realname":"","remark":"千年老妖","sex":1,"user_id":"7881302509911391","username":"千年老妖"}],"type":11037} + #endregion + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + var client = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + if (!user.IsGetFriend) return; + try + { + if (data == null) + { + lock (Friend_Lock) + { + var _data = json.ContainsKey("data") ? json["data"] as ArrayList : null; + if (_data == null) return; + + for (int i = 0; i < _data.Count; i++) + { + var item = _data[i] as Dictionary; + var f = new WorkFriendInfo(); + f.avatar = item["avatar"]?.ToString(); + f.conversation_id = item["conversation_id"]?.ToString(); + //f.desc = item["desc"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.position = item["position"]?.ToString(); + f.realname = item["realname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = int.Parse(item["sex"]?.ToString()); + f.user_id = item["user_id"]?.ToString(); + f.username = item["username"]?.ToString(); + + //var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + //if (user == null) + // return; + + var friend = user.WorkFriends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend == null) + user.WorkFriends.Add(f); + } + } + #region xx + //var nmss = new List>(); + //var mis = new List(); + //var count = 40; + //var rem = _data.Count % count; + //var num = _data.Count / count; + + //for (int i = 0; i < _data.Count; i++) + //{ + // var item = _data[i] as Dictionary; + // var f = new WorkFriendInfo(); + + // f.avatar = item["avatar"]?.ToString(); + // f.conversation_id = item["conversation_id"]?.ToString(); + // f.corp_id = item["corp_id"]?.ToString(); + // f.desc = item["desc"]?.ToString(); + // f.external_job = item["external_job"]?.ToString(); + // f.nickname = item["nickname"]?.ToString(); + // f.position = item["position"]?.ToString(); + // f.realname = item["realname"]?.ToString(); + // f.remark = item["remark"]?.ToString(); + // f.sex = int.Parse(item["sex"]?.ToString()); + // f.nickname = item["username"]?.ToString(); + // f.user_id = item["user_id"]?.ToString(); + + // //f.manager_wxid = item["manager_wxid"]?.ToString(); + // //f.is_manager = int.Parse(item["is_manager"].ToString()); + + // mis.Add(f); + // if (mis.Count >= count) + // { + // nmss.Add(mis); + // mis = new List(); + // } + // else if (nmss.Count == num && mis.Count == rem) + // { + // nmss.Add(mis); + // } + //} + //var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + //if (user == null) return; + //var socketClient = EasySoc.GetSocket(); + //foreach (var item in nmss) + //{ + // var msg = new WorkWechatContactList(); + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端企业微信; + + // msg.Cmd = PCRobotCMD.rcvContactList_workWeChat; + // msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", item } }); + + // socketClient.Send(msg); + // Thread.Sleep(5); + //} + #endregion + } + } + catch { } + finally + { + user.IsGetFriend = false; + } + #endregion + } + break; + case MsgType.MT_GET_ROOMS_MSG:// 获取群聊列表 + { + //{"data":[{"conversation_id":"R:1970325073072411","create_user_id":"1688853956450720","is_manager":0,"nickname":"成都秒单客网络科技有限公司","total":5},{"conversation_id":"R:10696053211008104","create_user_id":"1688853956558440","is_manager":1,"nickname":"吴嘉华、18、17","total":3}],"type":11038} + + if (data == null) + { + lock (Friend_Lock) + { + var _data = json.ContainsKey("data") ? json["data"] as ArrayList : null; + if (_data == null) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + + for (int i = 0; i < _data.Count; i++) + { + var item = _data[i] as Dictionary; + var f = new WorkFriendInfo(); + + f.avatar = string.Empty; + f.user_id = item["conversation_id"]?.ToString(); + f.manager_wxid = item["create_user_id"]?.ToString(); + f.is_manager = int.Parse(item["is_manager"]?.ToString()); + f.nickname = item["nickname"]?.ToString(); + f.username = item["nickname"]?.ToString(); + f.remark = item["nickname"]?.ToString(); + + f.manager_wxid = item["create_user_id"]?.ToString(); + f.is_manager = int.Parse(item["is_manager"]?.ToString()); + + var friend = user.WorkFriends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend == null) + user.WorkFriends.Add(f); + } + } + } + } + break; + case MsgType.MT_GET_USER_DETAIL_MSG:// 获取用户详细信息 + { + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","desc":"","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":"18"},"type":11039} 获取到用户数据 + //{"data":{"user_id":"7881302447012216"},"type":11039} 获取的用户不存在 + if (!data.ContainsKey("conversation_id")) return; + lock (Friend_Lock) + { + var f = new WorkFriendInfo(); + f.avatar = data["avatar"]?.ToString(); + f.conversation_id = data["conversation_id"]?.ToString(); + if (data.ContainsKey("desc")) + f.desc = data["desc"]?.ToString(); + else + f.desc = string.Empty; + f.nickname = data["nickname"]?.ToString(); + f.position = data["position"]?.ToString(); + f.realname = data["realname"]?.ToString(); + f.remark = data["remark"]?.ToString(); + f.sex = int.Parse(data["sex"]?.ToString()); + f.user_id = data["user_id"]?.ToString(); + f.username = data["username"]?.ToString(); + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + + var friend = user.WorkFriends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend != null) + if (!user.WorkFriends.TryTake(out friend)) return; + user.WorkFriends.Add(f); + } + } + break; + case MsgType.MT_GET_ROOM_MEMBERS_MSG:// 获取群成员列表 + { + try + { + #region 数据样式 + /* + {"data":{"conversation_id":"R:10696053211008104","member_list":[{"avatar":"https://wework.qpic.cn/bizmail/FxrNrXCeEh8Kwv4ia3iahWCbkR7Y0VqoBnGSHAyhDIefRGkL7tT76SsA/0","conversation_id":"S:1688853956558440_1688853956558440","desc":"","nickname":"","position":"","realname":"吴嘉华","remark":"","sex":1,"user_id":"1688853956558440","username":"吴嘉华"},{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","desc":"","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":"18"},{"avatar":"http://wx.qlogo.cn/mmhead/0T8yO33zeeg33jJCQibIWobapj6GX4xFBbOECtmG9VdkYpnzyiaUr5iag/0","conversation_id":"S:1688853956558440_7881301610989604","desc":"","nickname":"","position":"","realname":"","remark":"","sex":0,"user_id":"7881301610989604","username":"17"}]},"type":11040} + + {"data":{"conversation_id":"R:1970325073072411","member_list":[{"avatar":"http://wework.qpic.cn/bizmail/UBH52fian6zLyTQm2YeWIEonTIT0snwXSojzt7AjPbWk0CBqbRBtshA/0","conversation_id":"S:1688853956558440_1688853956450720","desc":"","nickname":"","position":"","realname":"聂红利","remark":"","sex":1,"user_id":"1688853956450720","username":"千年老妖"},{"avatar":"https://wework.qpic.cn/bizmail/FxrNrXCeEh8Kwv4ia3iahWCbkR7Y0VqoBnGSHAyhDIefRGkL7tT76SsA/0","conversation_id":"S:1688853956558440_1688853956558440","desc":"","nickname":"","position":"","realname":"吴嘉华","remark":"","sex":1,"user_id":"1688853956558440","username":"吴嘉华"},{"avatar":"http://wework.qpic.cn/bizmail/AU8vqVRBac5HFiaTI2qxv3RNr8Kib0wFyicBQZkvs06ayzBhlHE7dCAmA/0","conversation_id":"S:1688853956558440_1688853956589484","desc":"","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"1688853956589484","username":"白龙马"},{"avatar":"http://p.qpic.cn/wwhead/duc2TvpEgSTPk74IwG7Bs8GzMNxjerMmg94LwYswvGEoKMZcpTicE7vkLsDwGdh8BcVJLibuGFXbc/0","conversation_id":"S:1688853956558440_10977528187716586","desc":"","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"10977528187716586","username":"嘿嘿"},{"avatar":"http://p.qpic.cn/wwhead/duc2TvpEgSTPk74IwG7Bs8GzMNxjerMmg94LwYswvGEoKMZcpTicE7vkLsDwGdh8BcVJLibuGFXbc/0","conversation_id":"S:1688853956558440_10977528187716587","desc":"","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"10977528187716587","username":"测试机器人"}]},"type":11040} + */ + #endregion + + lock (Friend_Lock) + { + //{"data":{"conversation_id":"R:10696053211018728","member_list":[{"acctid":"WuJiaHua","avatar":"http://wework.qpic.cn/bizmail/FxrNrXCeEh8Kwv4ia3iahWCbkR7Y0VqoBniaJ5hrlKggVaibBXIxmOBb8A/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"洪荒老道","position":"","realname":"吴嘉华","remark":"","sex":1,"user_id":"1688853956558440","username":"洪荒老道"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/FrdAUicrPIibe0Dd7mWcTkmSz8GHQp6YWcVzd4g62zicVnTPGI3G9S5vA/0","corp_id":"1970325134026788","invite_user_id":"1688853956558440","nickname":"","position":"","realname":"","remark":"ID3110-。/V1/T1/i1","sex":0,"user_id":"7881301536005932","username":"摸鱼樊"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/0T8yO33zeeg33jJCQibIWobapj6GX4xFBbOECtmG9VdkYpnzyiaUr5iag/0","corp_id":"1970325134026788","invite_user_id":"1688853956558440","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301610989604","username":"17"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM5qa6vY8BQAoN1ViclaTAFFuknicOeMHNluZcXyTQLUrKKg/0","corp_id":"1970325134026788","invite_user_id":"1688853956558440","nickname":"","position":"","realname":"","remark":"21","sex":2,"user_id":"7881302484994318","username":"、"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/ibhzWy4ibIEpCGTLwEuhBf4rqKAvx4bXHicib6uWPaZrtGtRPtv8UrUgSQ/0","corp_id":"1970325134026788","invite_user_id":"1688853956558440","nickname":"","position":"","realname":"","remark":"E-b-Coco-▲-Υ-","sex":0,"user_id":"7881303377020975","username":"Coco"}]},"type":11040} + + var conversation_id = data["conversation_id"].ToString(); + + //var username = data["username"].ToString(); + var member_list = data["member_list"] as ArrayList; + if (member_list == null) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + + var group = user.WorkGroups.FirstOrDefault(z => z.conversation_id == conversation_id); + if (group == null) + { + group = new WorkGroupInfo() { conversation_id = conversation_id, total = member_list.Count, friends = new List() }; + user.WorkGroups.Add(group); + } + else + group.total = member_list.Count; + for (int i = 0; i < member_list.Count; i++) + { + //{"account":"","avatar":"http://wx.qlogo.cn/mmhead/ver_1/klibauQfLYtmfniaYAzsV9l6V4cSHmdDhniaTmJ6aGo0z035JTkB5QWrOUbAPnJnP4YXTMuKKmwNBMNv2Fbj5ia9icNicYeXGXbbsRiagGFKryASro/132","city":"","country":"","nickname":"陈建","province":"","remark":"","sex":0,"wxid":"wxid_e1j30jf2k5zdk022"} + + //{"avatar":"http://wework.qpic.cn/bizmail/UBH52fian6zLyTQm2YeWIEonTIT0snwXSojzt7AjPbWk0CBqbRBtshA/0","conversation_id":"S:1688853956558440_1688853956450720","desc":"","nickname":"","position":"","realname":"利","remark":"","sex":1,"user_id":"1688853956450720","username":"千妖"} + + var item = member_list[i] as Dictionary; + + var f = new WorkFriendInfo(); + + f.avatar = item["avatar"]?.ToString(); + f.conversation_id = conversation_id; + //f.corp_id = item["corp_id"]?.ToString(); + //f.desc = item["desc"]?.ToString(); + //f.external_job = item["external_job"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.position = item["position"]?.ToString(); + f.realname = item["realname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = int.Parse(item["sex"]?.ToString()); + f.nickname = item["username"]?.ToString(); + f.user_id = item["user_id"]?.ToString(); + + var friend = group.friends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend == null) + group.friends.Add(f); + } + } + #region xx + //var nmss = new List>(); + //var mis = new List(); + //var count = 20; + //var rem = member_list.Count % count; + //var num = member_list.Count / count; + + //for (int i = 0; i < member_list.Count; i++) + //{ + // //{"account":"","avatar":"http://wx.qlogo.cn/mmhead/ver_1/klibauQfLYtmfniaYAzsV9l6V4cSHmdDhniaTmJ6aGo0z035JTkB5QWrOUbAPnJnP4YXTMuKKmwNBMNv2Fbj5ia9icNicYeXGXbbsRiagGFKryASro/132","city":"","country":"","nickname":"陈建","province":"","remark":"","sex":0,"wxid":"wxid_e1j30jf2k5zdk022"} + + // //{"avatar":"http://wework.qpic.cn/bizmail/UBH52fian6zLyTQm2YeWIEonTIT0snwXSojzt7AjPbWk0CBqbRBtshA/0","conversation_id":"S:1688853956558440_1688853956450720","desc":"","nickname":"","position":"","realname":"聂红利","remark":"","sex":1,"user_id":"1688853956450720","username":"千年老妖"} + + // var item = member_list[i] as Dictionary; + + // var f = new WorkFriendInfo(); + + // f.avatar = item["avatar"]?.ToString(); + // f.conversation_id = item["conversation_id"]?.ToString(); + // //f.corp_id = item["corp_id"]?.ToString(); + // f.desc = item["desc"]?.ToString(); + // //f.external_job = item["external_job"]?.ToString(); + // f.nickname = item["nickname"]?.ToString(); + // f.position = item["position"]?.ToString(); + // f.realname = item["realname"]?.ToString(); + // f.remark = item["remark"]?.ToString(); + // f.sex = int.Parse(item["sex"]?.ToString()); + // f.nickname = item["username"]?.ToString(); + // f.user_id = item["user_id"]?.ToString(); + + // mis.Add(f); + // if (mis.Count >= count) + // { + // nmss.Add(mis); + // mis = new List(); + // } + // else if (nmss.Count == num && mis.Count == rem) + // { + // nmss.Add(mis); + // } + //} + + //var socketClient = EasySoc.GetSocket(); + //var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + //if (user == null) return; + //foreach (var item in nmss) + //{ + // var msg = new WorkWechatGroupMember(); + // msg.RobotUsername = user.Wxid; + // msg.RobotUsernick = user.Nickname; + // msg.RobotType = RobotType.客户端微信; + + // msg.Cmd = PCRobotCMD.rcvGroupMember_workWeChat; + + // var g = new WorkGroupInfo(); + // g.conversation_id = conversation_id; + // g.member_list = item; + // msg.Message = HttpHelper.ObjectToJson(new Dictionary() { { "data", g } }); + + // socketClient.Send(msg); + // Thread.Sleep(5); + //} + #endregion + + + } + catch (Exception ex) + { + } + } + break; + case MsgType.MT_ROOM_ADD_MEMBER_NOTIFY_MSG://群成员新增通知 + { + if (data == null) return; + + var memberList = data["member_list"] as ArrayList; + if (memberList == null || memberList.Count == 0) return; + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie); + if (user == null) + return; + + var client = WechatClient.GetApi(user) as Wechat_Xiaoxie_QY; + + var socketClient = EasySoc.GetSocket(); + //var avatar = data["avatar"].ToString();//头像 + //var is_manager = data["is_manager"].ToString();// + //var manager_wxid = data["manager_wxid"].ToString();//管理账号 + //var room_nick = data["nickname"].ToString();//群昵称 + //var room_wxid = data["room_wxid"].ToString();//群账号 + //var total_member = int.Parse(data["total_member"].ToString());//群人数 + + //var member_list = data["member_list"] as ArrayList; + //if (member_list != null && member_list.Count != 0) + //{ + // var member = member_list[0] as Dictionary; + // var avatar_user = member["avatar"].ToString();//头像 + // var invite_by = member["invite_by"].ToString();//邀请者wxid + // var nickname = member["nickname"].ToString();//新用户昵称 + // var wxid = member["wxid"].ToString();//新用户账号 + + + + // WechatNewMemer newMember = new WechatNewMemer(); + // newMember.Cmd = PCRobotCMD.newMember; + // newMember.RobotType = RobotType.客户端微信; + // newMember.RobotUsername = user.Wxid; + // newMember.RobotUsernick = user.Nickname; + + // newMember.SourceNick = string.Empty; + // newMember.SourceName = (string.IsNullOrWhiteSpace(invite_by) || invite_by == user.Wxid) ? string.Empty : invite_by; + // newMember.MemberNick = nickname; + // newMember.MemberName = wxid; + // newMember.GroupId = room_wxid; + // newMember.GroupNick = room_nick; + // newMember.TotalMember = total_member; + + // socketClient.Send(newMember); + //} + //op_user_id 邀请用户的昵称 + //op_user_name 邀请用户的账号 + var room_conversation_id = data["room_conversation_id"]?.ToString(); + var room_name = data["room_name"]?.ToString(); + var op_user_name = data["op_user_name"]?.ToString(); + var op_user_id = data["op_user_id"]?.ToString(); + + for (int i = 0; i < memberList.Count; i++) + { + var item = memberList[i] as Dictionary; + + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember_workWeChat; + newMember.RobotType = RobotType.客户端企业微信; + newMember.RobotUsername = user.Wxid; + newMember.RobotUsernick = user.Nickname; + + newMember.SourceNick = op_user_name; + newMember.SourceName = op_user_id; + newMember.MemberNick = item["name"]?.ToString(); ; + newMember.MemberName = item["user_id"]?.ToString(); ; + newMember.GroupId = room_conversation_id; + newMember.GroupNick = room_name; + newMember.TotalMember = 0; + + socketClient.Send(newMember); + Thread.Sleep(50); + } + break; + } + default: + break; + } + } + catch (Exception ex) + { + //Console.WriteLine("解析消息异常:" + ex.Message + "," + recvData); + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".._" + recvData); + } + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_."); + } + } + + private static ConcurrentDictionary FriendRequestRecord = new ConcurrentDictionary(); + + private static void WxCloseCallback(uint dwClientId) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == dwClientId && f.Value.Type == WechatType.Xiaoxie_QY).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"WxCloseCallbackQY关闭回调,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_.-"); + } + } + + public override void AgreeAddMe(string text) + { + try + { + if (string.IsNullOrWhiteSpace(text)) return; + + var reg = Regex.Match(text, @"{""user_id"":""(?[^""]+?)"",""corp_id"":""(?[^""]+?)""}"); + if (reg.Success) + { + var user_id = reg.Groups["user_id"].Value; + var corp_id = reg.Groups["corp_id"].Value; + var __json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_FRIEND_REQUEST, data = new { user_id = user_id, corp_id = corp_id } }); + SendWxWorkData(User.DwClientId, __json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "-._"); + } + } + + public override void DeleteFriend(string wxid) + { + try + { + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "._"); + } + } + + + + public override void EditCotacts(string wxid, string remark) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_MODIFY_USER_REMARK_MSG, data = new { user_id = wxid, remark = remark } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "*_"); + } + } + + /// + /// 创建群 + /// + /// + public override void CreateRoom(string wxidData) + { + try + { + if (string.IsNullOrWhiteSpace(wxidData)) return; + var wxids = wxidData.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (wxids != null && wxids.Length != 0) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CREATE_ROOM_MSG, data = wxids }); + SendWxWorkData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 邀请用户进群 + /// + /// + /// + public override void InviteMemberToRoom_40Up(string conversation_id, string wxidData) + { + try + { + if (conversation_id.Trim().StartsWith("R:")) + { + var wxids = wxidData.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_ROOM_ADD_MEMBERS_MSG, data = new { conversation_id = conversation_id, user_list = wxids } }); + SendWxWorkData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".._."); + } + } + + + public override void InviteMemberToRoom_40Down(string groupid, string wxidData) + { + InviteMemberToRoom_40Up(groupid, wxidData); + } + + public override void DeleteRoomMember(string wxid, string room) + { + try + { + if (room.Trim().StartsWith("R:")) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_ROOM_DEL_MEMBERS_MSG, data = new { conversation_id = room, user_list = new string[] { wxid } } }); + SendWxWorkData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetContact() + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_EXTERNAL_USERS_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + + Thread.Sleep(1000); + + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOMS_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_*"); + } + } + + public override void GetContact(bool isUpdate) + { + try + { + var result = GetFriendInfos(true); + + var socketClient = EasySoc.GetSocket(); + CommonResult msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvFriendList_workWeChat; + msg.Data = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 获取好友列表 + /// + /// 刷新缓存数据 + /// + //public override List GetFriendInfos(bool flushGroupsCache = false) + public override string GetFriendInfos(bool flushGroupsCache = false) + { + List friends = null; + try + { + #region 获取缓存数据 + friends = User.WorkFriends.Where(f => !f.user_id.Contains("R:")).ToList(); + if (!flushGroupsCache && friends.Count != 0) + return JsonConvert.SerializeObject(friends); + #endregion + + if (!User.IsGetFriend) + { + //获取好友列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_EXTERNAL_USERS_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + User.IsGetFriend = true; + } + + var result_ = Task.Factory.StartNew>(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (!User.IsGetFriend) + { + friends = User.WorkFriends.Where(f => !f.user_id.Contains("R:")).ToList(); + return friends; + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + //return friends; + return JsonConvert.SerializeObject(friends); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "#__#"); + } + return string.Empty; + } + + + + //public override void GetFriend(string wxid) + //{ + // try + // { + // var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_USER_DETAIL_MSG, data = new { user_id = wxid } }); + // SendWxWorkData(User.DwClientId, json); + // } + // catch (Exception ex) + // { + // LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + // } + //} + + //public override void GetGroupMemer(string groupId) + //{ + // try + // { + // var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOM_MEMBERS_MSG, data = new { conversation_id = groupId } }); + // SendWxWorkData(User.DwClientId, json); + + + + // } + // catch (Exception ex) + // { + // LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + // } + //} + + public override void GetGroupAndFriendInfo(string groupId, string wxid) + { + try + { + var json = string.Empty; + WorkGroupInfo group = null; + if (groupId.Contains("R:")) + { + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOM_MEMBERS_MSG, data = new { conversation_id = groupId } }); + + var g = User.WorkGroups.FirstOrDefault(f => f.conversation_id == groupId); + //User.WorkGroups.Clear(); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) + group = new WorkGroupInfo() { conversation_id = groupId, friends = new List() { u }, total = g.total }; + } + + if (group == null) + { + SendWxWorkData(User.DwClientId, json); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + g = User.WorkGroups.FirstOrDefault(f => f.conversation_id == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) + { + group = new WorkGroupInfo() { conversation_id = groupId, friends = new List() { u }, total = g.total }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信;//客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "/_"); + } + } + + public override void GetGroupAndFriendInfo(string groupId, string wxid, bool flush = false) + { + try + { + var json = string.Empty; + WorkGroupInfo group = null; + if (groupId.Contains("R:")) + { + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOM_MEMBERS_MSG, data = new { conversation_id = groupId } }); + + var g = User.WorkGroups.FirstOrDefault(f => f.conversation_id == groupId); + //User.WorkGroups.Clear(); + if (g != null) + { + if (flush) + { + g.friends.Clear(); + } + else + { + var u = g.friends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) + group = new WorkGroupInfo() { conversation_id = groupId, friends = new List() { u }, total = g.total }; + } + } + + if (group == null) + { + SendWxWorkData(User.DwClientId, json); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + g = User.WorkGroups.FirstOrDefault(f => f.conversation_id == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) + { + group = new WorkGroupInfo() { conversation_id = groupId, friends = new List() { u }, total = g.total }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信;//客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "/_"); + } + } + + + public override void GetWxidInfo(string wxid) + { + try + { + var json = string.Empty; + + var u = User.WorkFriends.FirstOrDefault(f => f.user_id == wxid); + if (u == null) + { + if (wxid.Contains("R:")) + { + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOMS_MSG, data = new { } }); + } + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_USER_DETAIL_MSG, data = new { user_id = wxid } }); + + SendWxWorkData(User.DwClientId, json); + var friend = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + u = User.WorkFriends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) return u; + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信;//客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = u == null ? string.Empty : HttpHelper.ObjectToJson(u); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_/"); + } + } + + public override void SendImage(string wxid, string file) + { + //try + //{ + // var conversation_id = wxid; + // if (!wxid.StartsWith("R:")) + // { + // conversation_id = $"S:{User.Wxid}_{wxid}"; + // } + // var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = conversation_id, file = file } }); + // SendWxWorkData(User.DwClientId, json); + //} + //catch (Exception ex) + //{ + // LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".-"); + //} + + try + { + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + conversation_id = $"S:{User.Wxid}_{wxid}"; + + if (file.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + byte[] ImangByte = null; + string extension = Path.GetExtension(file); + extension = string.IsNullOrWhiteSpace(extension) ? ".jpg" : extension; + ImangByte = new System.Net.WebClient().DownloadData(file); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + + var path = Common.CacheFilePath(User.Wxid, conversation_id, "IMAGE", Guid.NewGuid().ToString("N"), extension); + if (!File.Exists(path)) + { + File.WriteAllBytes(path, ImangByte); + } + if (File.Exists(path)) + file = path; + } + else + { + if (!File.Exists(file)) + { + if (Common.IsBase64(file)) + { + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), "jpg"); + if (Common.Base64ToFileAndSave(file, path) && File.Exists(path)) + { + file = path; + } + } + else + { } + } + } + + var json = string.Empty; + if (File.Exists(file)) + { + if (file.Trim().EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase)) + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_GIF_MSG, data = new { conversation_id = conversation_id, file = file } }); + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = conversation_id, file = file } }); + } + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = conversation_id, file = file } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Debug("发送图片异常", ex.Message + ".-" + ex.StackTrace); + } + } + + public override void SendMessage(string wxid, string message) + { + try + { + //S:1688853956558440_7881301364988874 + //{"data":{"content":"我们","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"61","receiver":"1688853956558440","send_time":"1584028171","sender":"7881301364988874","sender_name":"18","server_id":"1000653"},"type":11041} + + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{wxid}"; + } + else + { } + + var json = string.Empty; + message = message.Replace("\r\n", "\n"); + if (Common.isXML(message)) + { + message = message.Replace("&", "&"); + var title = string.Empty; + var desc = string.Empty; + var url = string.Empty; + var image_url = string.Empty; + var reg = Regex.Match(message, @"(?<标题>[\w\W]+?)"); + if (reg.Success) title = reg.Groups["标题"].Value; + reg = Regex.Match(message, @"(?<介绍>[\w\W]+?)"); + if (reg.Success) desc = reg.Groups["介绍"].Value.Replace("(?<链接>[\w\W]+?)"); + if (!reg.Success) reg = Regex.Match(message, @"(?<链接>[\w\W]+?)"); + if (reg.Success) url = reg.Groups["链接"].Value; + reg = Regex.Match(message, @"(?<图片链接>[\w\W]+?)"); + if (reg.Success) image_url = reg.Groups["图片链接"].Value; + if (message.Contains("")) + { + var image_key1 = string.Empty; + var image_key2 = string.Empty; + var image_key3 = string.Empty; + var image_size = 0; + var ghid = string.Empty; + var pagepath = string.Empty; + var regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key1 = regKey.Groups["image_key1"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key2 = regKey.Groups["image_key2"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key3 = regKey.Groups["image_key3"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_size = int.Parse(regKey.Groups["image_size"].Value.XMLReplace(false)); + + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + ghid = regKey.Groups["username"].Value; + + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + pagepath = regKey.Groups["pagepath"].Value; + + var weapppagethumbrawurl = string.Empty; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + weapppagethumbrawurl = regKey.Groups["weapppagethumbrawurl"].Value; + + var _json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_MINI_PROGRAM_MSG, data = new { conversation_id = conversation_id, ghid = ghid.XMLReplace(false), wxid = conversation_id, name = title, title = desc, enterpoint = pagepath.XMLReplace(false), headimg = weapppagethumbrawurl.XMLReplace(false), image_key1 = image_key1.XMLReplace(false), image_key2 = image_key2.XMLReplace(false), image_key3 = image_key3.XMLReplace(false), image_size = image_size } }); + + SendWxWorkData(User.DwClientId, _json); + return; + } + else + { + image_url = + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_LINK_MSG, data = new { conversation_id = conversation_id, title = $"{title.XMLReplace(false)}", desc = $"{desc.XMLReplace(false)}", url = url.XMLReplace(false), image_url = image_url.XMLReplace(false) } }); + } + } + else + { + var atUsername = new List(); + var regs = Regex.Matches(message, @"\[@([^\]]+?)\]"); + if (regs.Count != 0 && wxid.StartsWith("R:")) + { + foreach (Match item in regs) + { + atUsername.Add(item.Groups[1].Value.Trim()); + } + message = Regex.Replace(message, @"(\[@[^\]]+?\])", "{$@}"); + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_ROOM_AT_MSG, data = new { conversation_id = conversation_id, content = message, at_list = atUsername.ToArray() } }); + } + else + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_TEXT_MSG, data = new { conversation_id = conversation_id, content = message } }); + } + SendWxWorkData(User.DwClientId, json); + + //LogHelper.GetSingleObj().Debug("发送状态", ($"发送:{conversation_id} - {flag}, 内容:{message}")); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "-."); + } + } + + /// + /// 发送小程序 + /// + /// 发送给谁 + /// 发送的内容json打包 + public override void SendProgramMessage(string wxid, string dataJson) + { + try + { + /* + "conversation_id": "S:16888xxxx_7881xxxxx", + "ghid": "gh_52b46203a658@app", + "wxid": "wx35f2a3937c9df889", + "name": "博鸟绘本", + "title": "博鸟绘本,最新最全的儿童绘本租赁平台~", + "enterpoint": "pages/shouye/shouye.html", + "headimg": "http://wx.qlogo.cn/mmhead/xxxx/96", + "image_key1": "306b020102046430620201000xxxxx", + "image_key2": "61706264616C7A77666875xxxx", + "image_key3": "b302e94d9c6f95xxxxxx", + "image_size": 56448 + */ + + //个人微信/企业微信 + //{"data":{"content_type":78,"conversation_id":"R:10696053211018728","enterpoint":"pages/tab/home/index.html?_um_ssrc=oucfI5QRI-8SbyOTKSGYt5-ia0dk&_um_sts=1610033684099","ghid":"gh_a0d7a7672cf7@app","headimg":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM43LsxpXHKd7ua7kwMZQ8WHmZlkYTzr3Tdm8sMOJ7Ypog/96","image_key1":"306b020102046430620201000204bafc490e02030f4df9020473e6607102045ff72a530436333133373039353935305f313734393433343231315f3262393764653133616335373232353633383831336564376334396563616164020100020300ab1004000201010201000400","image_key2":"61747072666A766977766D69726D6168","image_key3":"2b97de13ac57225638813ed7c49ecaad","image_size":43791,"is_pc":0,"local_id":"155","name":"啄木鸟家庭维修","receiver":"1688853956558440","send_time":"1610033747","sender":"7881302484994318","sender_name":"、","server_id":"1042188","title":"直营一口价,维修无猫腻","wxid":"wx3d6b1af0cb07fa5a"},"type":11066} + + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + conversation_id = $"S:{User.Wxid}_{wxid}"; + + var json = CsharpHttpHelper.HttpExtend.JsonToDictionary(dataJson); + var data = json.ContainsKey("data") ? json["data"] as Dictionary : null; + if (data == null) return; + + //var content_type = data["content_type"]?.ToString();//内容类型 78 + //var conversation_id = data["conversation_id"]?.ToString();//接收者的的会话ID + //var receiver = data["receiver"]?.ToString();//接收者的user_id + //var sender = data["sender"]?.ToString();//发送者的user_id + //var sender_name = data["sender_name"]?.ToString();//发送者昵称 + //var server_id = data["server_id"]?.ToString();//消息的服务器ID + var enterpoint = data["enterpoint"]?.ToString();//入口点 - 链接(小程序里面的链接) + var headimg = data["headimg"]?.ToString();//小程序的头像 + var name = data["name"]?.ToString();//小程序的名称 + var title = data["title"]?.ToString();//小程序标题 + var _wxid = data["wxid"]?.ToString(); + var image_size = int.Parse(data["image_size"].ToString()); + var image_key1 = data["image_key1"]?.ToString(); + var image_key2 = data["image_key2"]?.ToString(); + var image_key3 = data["image_key3"]?.ToString(); + var ghid = data["ghid"]?.ToString(); + + var _json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_MINI_PROGRAM_MSG, data = new { conversation_id = conversation_id, ghid = ghid, wxid = _wxid, name = name, title = title, enterpoint = enterpoint, headimg = headimg, image_key1 = image_key1, image_key2 = image_key2, image_key3 = image_key3, image_size = image_size } }); + + SendWxWorkData(User.DwClientId, _json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("发送小程序异常", ex.Message + ex.StackTrace); + } + } + + public override void SendVideo(string wxid, string file) + { + try + { + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{wxid}"; + } + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_VIDEO_MSG, data = new { conversation_id = conversation_id, file = file } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "-_"); + } + } + + public override void SendFile(string wxid, string file) + { + try + { + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{wxid}"; + } + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_FILE_MSG, data = new { conversation_id = conversation_id, file = file } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_-"); + } + } + + public override void SendCard(string to_wxid, string card_wxid) + { + try + { + var conversation_id = to_wxid; + if (!to_wxid.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{to_wxid}"; + } + + if (card_wxid.StartsWith("R:")) + { + InviteMemberToRoom_40Up(card_wxid, to_wxid); + return; + } + + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_PERSON_CARD_MSG, data = new { conversation_id = conversation_id, user_id = card_wxid } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "--"); + } + } + + public override void CloseWechat(string message) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == User.DwClientId && f.Value.Type == WechatType.Xiaoxie_QY).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"CloseWechatQY事件退出,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v, true); + if (!string.IsNullOrWhiteSpace(message)) + PCRobotForm.ErrorMessAction?.Invoke(message); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "//"); + } + } + + private static void WxAcceptCallback(uint dwClientId) + { + Console.WriteLine("注入成功:" + dwClientId); + } + + /// + /// 启动微信 + /// + /// + /// + public static uint StartWechat(bool isError = false) + { + InitPc(); + + var WechatWinFile = HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + var md5 = Common.GetMD5Hash(WechatWinFile).ToUpper(); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + if (isError) throw new Exception("易转发客户端企业微信版本不支持,请登录易转发端手动处理"); + var _rst = MessageBox.Show("您的企业微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (_rst == DialogResult.Yes) + { + var f = new WechatUpdate(Version); + f.ShowDialog(); + if (!f.IsOk) return 0; + } + else return 0; + } + // 注入并多开 + //return InjectWxWork(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes("")); + + var path = HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + LogHelper.GetSingleObj().Debug("注入前", $"DPath = {DllPath},Path = {path}"); + return InjectWxWorkMultiOpen(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + } + + #region 内部类 + public enum MsgType : ushort + { + /// + /// 接口准备完毕 + /// + MT_APP_READY_MSG = 11024, + /// + /// 参数错误提示 + /// + MT_PARAMS_ERROR_MSG = 11025, + /// + /// 登录消息 + /// + MT_USER_LOGIN = 11026, + /// + /// 注销消息 + /// + MT_USER_LOGOUT = 11027, + /// + /// 登录二维码 + /// + MT_LOGIN_QRCODE_MSG = 11028, + /// + /// 发送文本消息 + /// + MT_SEND_TEXT_MSG = 11029, + /// + /// 发送图片消息 + /// + MT_SEND_IMAGE_MSG = 11030, + /// + /// 发送文件消息 + /// + MT_SEND_FILE_MSG = 11031, + /// + /// 发送目录消息 + /// + MT_SEND_FOLDER_MSG = 11032, + /// + /// 发送链接消息 + /// + MT_SEND_LINK_MSG = 11033, + /// + /// 发送个人名片 + /// + MT_SEND_PERSON_CARD_MSG = 11034, + /// + /// 获取自己信息 + /// + MT_GET_OWNER_INFO_MSG = 11035, + /// + /// 获取内部联系人列表 + /// + MT_GET_INNER_USERS_MSG = 11036, + /// + /// 获取外部联系列表 + /// + MT_GET_EXTERNAL_USERS_MSG = 11037, + /// + /// 获取群聊列表 + /// + MT_GET_ROOMS_MSG = 11038, + /// + /// 获取用户详细信息 + /// + MT_GET_USER_DETAIL_MSG = 11039, + /// + /// 获取群成员列表 + /// + MT_GET_ROOM_MEMBERS_MSG = 11040, + /// + /// 接收文本消息 + /// + MT_RECV_TEXT_MSG = 11041, + /// + /// 接收图片消息 + /// + MT_RECV_IMG_MSG = 11042, + /// + /// 接收视频消息 + /// + MT_RECV_VIDEO_MSG = 11043, + /// + /// 接收语音消息 + /// + MT_RECV_VOICE_MSG = 11044, + /// + /// 接收文件消息 + /// + MT_RECV_FILE_MSG = 11045, + /// + /// 接收位置消息 + /// + MT_RECV_LOCATION_MSG = 11046, + /// + /// 接收链接消息 + /// + MT_RECV_LINK_CARD_MSG = 11047, + /// + /// 接收表情消息 + /// + MT_RECV_EMOTION_MSG = 11048, + /// + /// 接收红包消息 + /// + MT_RECV_RED_PACKET_MSG = 11049, + /// + /// 接收个人名片消息 + /// + MT_RECV_PERSON_CARD_MSG = 11050, + /// + /// 接收其他未解析消息 + /// + MT_RECV_OTHER_MSG = 11051, + /// + /// 查询联系人 + /// + MT_SEARCH_USER_MSG = 11052, + /// + /// 添加查询的联系人 + /// + MT_ADD_SEARCH_USER_MSG = 11053, + /// + /// 修改用户备注 + /// + MT_MODIFY_USER_REMARK_MSG = 11054, + /// + /// 修改用户描述 + /// + MT_MODIFY_USER_DESC_MSG = 11055, + /// + /// 修改外部联系人手机号 + /// + MT_MODIFY_EXTERNAl_USER_PHONES_MSG = 11056, + /// + /// 修改外部联系人公司 + /// + MT_MODIFY_EXTERNAl_USER_COMPANY_MSG = 11057, + /// + /// 创建群聊 + /// + MT_CREATE_ROOM_MSG = 11058, + /// + /// 修改群名 + /// + MT_MODIFY_ROOM_NAME_MSG = 11059, + /// + /// 添加群成员 + /// + MT_ROOM_ADD_MEMBERS_MSG = 11060, + /// + /// 删除群成员 + /// + MT_ROOM_DEL_MEMBERS_MSG = 11061, + /// + /// 接收好友请求 + /// + MT_RECV_FRIEND_REQUEST = 11063, + /// + /// 接受加好友请求 + /// + MT_ACCEPT_FRIEND_REQUEST = 11064, + /// + /// 发送小程序 + /// + MT_SEND_MINI_PROGRAM_MSG = 11065, + /// + /// 接收到小程序 + /// + MT_RECV_MINIAPP_MSG = 11066, + /// + /// 发送视频 + /// + MT_SEND_VIDEO_MSG = 11067, + /// + /// 接收图文消息 + /// + MT_RECV_IMAGE_TEXT_MSG = 11068, + /// + /// 发送群@消息 + /// + MT_SEND_ROOM_AT_MSG = 11069, + /// + /// 发送动图(gif)消息 + /// + MT_SEND_GIF_MSG = 11070, + /// + /// 添加群成员为联系人 + /// + MT_ADD_ROOM_USER_MSG = 11071, + /// + /// 群成员新增通知 + /// + MT_ROOM_ADD_MEMBER_NOTIFY_MSG = 11072, + /// + /// 剔除群成员通知 + /// + MT_ROOM_DEL_MEMBER_NOTIFY_MSG = 11073, + /// + /// 新群通知 + /// + MT_ROOM_CREATE_NOTIFY_MSG = 11074, + /// + /// 群成员主动退出通知 + /// + MT_ROOM_MEMBER_QUIT_NOTIFY_MSG = 11075, + /// + /// 好友新增通知 + /// + MT_CONTACT_ADD_NOITFY_MSG = 11076, + } + #endregion + + } +} diff --git a/PCRobot/PCWechat/Wechat_Xiaoxie_QY - 复制.cs b/PCRobot/PCWechat/Wechat_Xiaoxie_QY - 复制.cs new file mode 100644 index 0000000..a4f2c1f --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Xiaoxie_QY - 复制.cs @@ -0,0 +1,351 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using NM_WeChat; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Properties; +using PCRobot.Utils; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; + +namespace PCRobot.PCWechat +{ + + /* + 接口文档:https://www.showdoc.cc/WxWorkNewHook?page_id=3846144660177490 + /////密码:784615627. + */ + + public partial class Wechat_Xiaoxie_QY : BaseApi + { + #region 注入等操作 + public delegate void AcceptCallbackFunc(uint dwClientId); + public delegate void RecvCallbackFunc(uint dwClientId, IntPtr intPtr, uint dwSize); + public delegate void CloseCallbackFunc(uint dwClientId); + + private static AcceptCallbackFunc m_AcceptCallbackFunc; + private static RecvCallbackFunc m_RecvCallbackFunc; + private static CloseCallbackFunc m_CloseCallbackFunc; + + // 引入DLL导出函数 + //[DllImport("Bin\\WeChatServer_QY.dll")] + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool InitWxWorkSocket(AcceptCallbackFunc acceptCallback, + RecvCallbackFunc recvCallback, CloseCallbackFunc closeCallback); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWork(byte[] strDllPath, byte[] strWxWorkExePath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWorkMultiOpen(byte[] strDllPath, byte[] strWxWorkExePath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool SendWxWorkData(uint dwClienId, byte[] strJsonData); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool DestroyWxWork(); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWorkPid(int dwPid, byte[] strDllPath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool UseUtf8(); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool GetUserWxWorkVersion(StringBuilder v); + + [DllImport("Bin\\WxWorkLoader.dll", EntryPoint = "SendWxWorkData")] + public static extern bool _SendWxWorkData(uint dwClienId, byte[] strJsonData); + + public bool SendWxWorkData(uint dwClienId, string strJsonData) + { + var ss = User.DwClientId; + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("_调试发送_", $"{dwClienId} -> {strJsonData} - {User != null} - 微信id:{User?.Wxid}"); + + if (User != null && !string.IsNullOrEmpty(User.Wxid)) + { + var json = HttpExtend.JsonToDictionary(strJsonData); + var type = json["type"].ToString(); + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试发送@转换失败", $"{dwClienId} -> type:{type}"); + return false; + } + switch (msgType) + { + //截取发送消息 - 为是否是辅助输入提供判断 + + case MsgType.MT_SEND_TEXT_MSG:// 发送文本消息 + case MsgType.MT_SEND_IMAGE_MSG:// 发送图片消息 + case MsgType.MT_SEND_FILE_MSG:// 发送文件消息 + case MsgType.MT_SEND_FOLDER_MSG:// 发送目录消息 + case MsgType.MT_SEND_LINK_MSG:// 发送链接消息 + //case MsgType.MT_SEND_PERSON_CARD_MSG:// 发送个人名片 + case MsgType.MT_SEND_VIDEO_MSG:// 发送视频 + { + json = json["data"] as Dictionary; + + string conversation_id = json["conversation_id"].ToString(); + var to_wxid = conversation_id; + if (conversation_id.StartsWith("S:"))//私人消息处理一下,群消息不用管 + { + to_wxid = conversation_id.Replace($"S:{User.Wxid}_", ""); + } + string message = string.Empty; + if (json.ContainsKey("content")) message = json["content"].ToString(); + else if (json.ContainsKey("card_wxid")) message = json["card_wxid"].ToString(); + else if (json.ContainsKey("file")) message = json["file"].ToString(); + //else if (json.ContainsKey("user_id")) message = json["user_id"].ToString(); + if (!string.IsNullOrEmpty(message)) + { + Common.SetCache(User.Wxid, to_wxid, message); + } + } + break; + } + } + return _SendWxWorkData(dwClienId, Encoding.UTF8.GetBytes(strJsonData)); + } + + static string DllPath = HttpExtend.MapFile($"WxWorkHelper_{Version}.dll", "Bin"); + + private const string Version = "4.0.2.6026"; + private const string PcMd5 = "E77637926604364C4AD65625032B2E8A"; + + public override string GetVersion() + { + return Version; + } + + public Wechat_Xiaoxie_QY(WechatUser User) : base(User) { } + + public static void Install() + { + if (IsQYInstall) return; + try + { + m_AcceptCallbackFunc = WxAcceptCallback; + m_RecvCallbackFunc = WxRecvCallback; + m_CloseCallbackFunc = WxCloseCallback; + + UseUtf8(); + // 初始化Callback + InitWxWorkSocket(m_AcceptCallbackFunc, m_RecvCallbackFunc, m_CloseCallbackFunc); + + StringBuilder sb = new StringBuilder(); + + var path1 = HttpExtend.MapPath("WXWork"); + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + + InitPc(); + } + catch (Exception) + { + + } + finally + { + IsQYInstall = true; + } + } + + /// + /// 杀死注入 pc + /// + /// + private static void KillPc(bool isInject = false) + { + Process[] MyProcesses = Process.GetProcesses(); + + var path1 = HttpExtend.MapPath("WXWork"); + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == "WXWORK" && MyProcess.MainModule.FileName.StartsWith(path1)) + { + try + { + //判断微信版本 + if (MyProcess.MainModule.FileName.StartsWith(path2)) + { + var id = MyProcess.Id; + if (isInject) + { + var result = Task.Factory.StartNew(delegate + { + try + { + var WechatWinFile = CsharpHttpHelper.HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + var md5 = Common.GetMD5Hash(WechatWinFile).ToUpper(); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + return false; + } + else + { + LogHelper.GetSingleObj().Info("系统", $"开始企业注入进程:{id}..."); + var uin = InjectWxWorkPid(id, Encoding.UTF8.GetBytes(DllPath)); + LogHelper.GetSingleObj().Info("系统", $"注入企业成功:{id},句柄ID:{uin}"); + return true; + } + } + catch (Exception) + { } + return false; + }).Wait(20000); + if (!result) + { + try + { + LogHelper.GetSingleObj().Info("系统cc", "杀死企业进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + else + { + try + { + LogHelper.GetSingleObj().Info("主动dd", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + } + catch (Exception) + { } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } + + private static void InitPc() + { + KillPc(); + } + + private static string RemoteCache = "get_login_code_cache_workwechat"; + + /// + /// 等待登录结果 + /// + public static Dictionary WaitLoginResult = new Dictionary(); + + /// + /// 远程登录微信 + /// + public static List RemoteLoginCodes = new List(); + + /// + /// pc微信登录二维码 + /// + /// + public static void LoginQrcode(string ServerMsgID) + { + try + { + RemoteLoginCode result = null; + try + { + string downloadsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + var wxConfig = HttpExtend.MapFile(@"Config.cfg", downloadsPath + @"\WXWork\Global"); + if (File.Exists(wxConfig)) + { + try + { + File.Delete(wxConfig); + } + catch (Exception) + { } + StartWechat(true); + } + } + catch (Exception ex) + { + result = new RemoteLoginCode() { pid = -1, rType = RobotType.客户端企业微信, b64Md5 = ex.Message }; + } + + if (result == null) + { + result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[RemoteCache]; + if (item != null) + { + cache.Remove(RemoteCache); + var r = item as RemoteLoginCode; + return r; + } + } while (awaitTime >= DateTime.Now); + return null; + }).Result; + } + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = string.Empty; + msg.RobotUsernick = string.Empty; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvLoginCode_workWeChat; + msg.Data = result == null ? string.Empty : JsonConvert.SerializeObject(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 卸载安装 + /// + public static void UnInstall() + { + try + { + //DestroyWxWork(); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".."); + } + } + #endregion + + } +} diff --git a/PCRobot/PCWechat/Wechat_Xiaoxie_QY.cs b/PCRobot/PCWechat/Wechat_Xiaoxie_QY.cs new file mode 100644 index 0000000..b03a5bb --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Xiaoxie_QY.cs @@ -0,0 +1,350 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using NM_WeChat; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Properties; +using PCRobot.Utils; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; + +namespace PCRobot.PCWechat +{ + + /* + 接口文档:https://www.showdoc.cc/WxWorkNewHook?page_id=3846144660177490 + /////密码:784615627. + */ + + public partial class Wechat_Xiaoxie_QY : BaseApi + { + #region 注入等操作 + public delegate void AcceptCallbackFunc(uint dwClientId); + public delegate void RecvCallbackFunc(uint dwClientId, IntPtr intPtr, uint dwSize); + public delegate void CloseCallbackFunc(uint dwClientId); + + private static AcceptCallbackFunc m_AcceptCallbackFunc; + private static RecvCallbackFunc m_RecvCallbackFunc; + private static CloseCallbackFunc m_CloseCallbackFunc; + + // 引入DLL导出函数 + //[DllImport("Bin\\WeChatServer_QY.dll")] + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool InitWxWorkSocket(AcceptCallbackFunc acceptCallback, + RecvCallbackFunc recvCallback, CloseCallbackFunc closeCallback); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWork(byte[] strDllPath, byte[] strWxWorkExePath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWorkMultiOpen(byte[] strDllPath, byte[] strWxWorkExePath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool SendWxWorkData(uint dwClienId, byte[] strJsonData); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool DestroyWxWork(); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern uint InjectWxWorkPid(int dwPid, byte[] strDllPath); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool UseUtf8(); + + [DllImport("Bin\\WxWorkLoader.dll")] + public static extern bool GetUserWxWorkVersion(StringBuilder v); + + [DllImport("Bin\\WxWorkLoader.dll", EntryPoint = "SendWxWorkData")] + public static extern bool _SendWxWorkData(uint dwClienId, byte[] strJsonData); + + public bool SendWxWorkData(uint dwClienId, string strJsonData) + { + var ss = User.DwClientId; + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("_调试发送_", $"{dwClienId} -> {strJsonData} - {User != null} - 微信id:{User?.Wxid}"); + + if (User != null && !string.IsNullOrEmpty(User.Wxid)) + { + var json = HttpExtend.JsonToDictionary(strJsonData); + var type = json["type"].ToString(); + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) + { + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试发送@转换失败", $"{dwClienId} -> type:{type}"); + return false; + } + switch (msgType) + { + //截取发送消息 - 为是否是辅助输入提供判断 + + case MsgType.MT_SEND_TEXT_MSG:// 发送文本消息 + case MsgType.MT_SEND_IMAGE_MSG:// 发送图片消息 + case MsgType.MT_SEND_FILE_MSG:// 发送文件消息 + case MsgType.MT_SEND_FOLDER_MSG:// 发送目录消息 + case MsgType.MT_SEND_LINK_MSG:// 发送链接消息 + //case MsgType.MT_SEND_PERSON_CARD_MSG:// 发送个人名片 + case MsgType.MT_SEND_VIDEO_MSG:// 发送视频 + { + json = json["data"] as Dictionary; + + string conversation_id = json["conversation_id"].ToString(); + var to_wxid = conversation_id; + if (conversation_id.StartsWith("S:"))//私人消息处理一下,群消息不用管 + { + to_wxid = conversation_id.Replace($"S:{User.Wxid}_", ""); + } + string message = string.Empty; + if (json.ContainsKey("content")) message = json["content"].ToString(); + else if (json.ContainsKey("card_wxid")) message = json["card_wxid"].ToString(); + else if (json.ContainsKey("file")) message = json["file"].ToString(); + //else if (json.ContainsKey("user_id")) message = json["user_id"].ToString(); + if (!string.IsNullOrEmpty(message)) + { + Common.SetCache(User.Wxid, to_wxid, message); + } + } + break; + } + } + return _SendWxWorkData(dwClienId, Encoding.UTF8.GetBytes(strJsonData)); + } + + static string DllPath = HttpExtend.MapFile($"WxWorkHelper_{Version}.dll", "Bin"); + + private const string Version = "4.0.2.6026"; + private const string PcMd5 = "E77637926604364C4AD65625032B2E8A"; + + public override string GetVersion() + { + return Version; + } + + public Wechat_Xiaoxie_QY(WechatUser User) : base(User) { } + + public static void Install() + { + if (IsQYInstall) return; + try + { + m_AcceptCallbackFunc = WxAcceptCallback; + m_RecvCallbackFunc = WxRecvCallback; + m_CloseCallbackFunc = WxCloseCallback; + + UseUtf8(); + // 初始化Callback + InitWxWorkSocket(m_AcceptCallbackFunc, m_RecvCallbackFunc, m_CloseCallbackFunc); + + StringBuilder sb = new StringBuilder(); + + var path1 = HttpExtend.MapPath("WXWork"); + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + + InitPc(); + } + catch (Exception) + { + + } + finally + { + IsQYInstall = true; + } + } + + /// + /// 杀死注入 pc + /// + /// + private static void KillPc(bool isInject = false) + { + Process[] MyProcesses = Process.GetProcesses(); + + var path1 = HttpExtend.MapPath("WXWork"); + var path2 = HttpExtend.MapPath("WXWork\\" + Version); + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == "WXWORK" && MyProcess.MainModule.FileName.StartsWith(path1)) + { + try + { + //判断微信版本 + if (MyProcess.MainModule.FileName.StartsWith(path2)) + { + var id = MyProcess.Id; + if (isInject) + { + var result = Task.Factory.StartNew(delegate + { + try + { + var WechatWinFile = CsharpHttpHelper.HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + var md5 = Common.GetMD5Hash(WechatWinFile).ToUpper(); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + return false; + } + else + { + LogHelper.GetSingleObj().Info("系统", $"开始企业注入进程:{id}..."); + var uin = InjectWxWorkPid(id, Encoding.UTF8.GetBytes(DllPath)); + LogHelper.GetSingleObj().Info("系统", $"注入企业成功:{id},句柄ID:{uin}"); + return true; + } + } + catch (Exception) + { } + return false; + }).Wait(20000); + if (!result) + { + try + { + LogHelper.GetSingleObj().Info("系统cc", "杀死企业进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + else + { + try + { + LogHelper.GetSingleObj().Info("主动dd", "杀死进程:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + } + catch (Exception) + { } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + } + + private static void InitPc() + { + KillPc(); + } + + private static string RemoteCache = "get_login_code_cache_workwechat"; + + /// + /// 等待登录结果 + /// + public static Dictionary WaitLoginResult = new Dictionary(); + + /// + /// 远程登录微信 + /// + public static List RemoteLoginCodes = new List(); + + /// + /// pc微信登录二维码 + /// + /// + public static void LoginQrcode(string ServerMsgID) + { + try + { + RemoteLoginCode result = null; + try + { + string downloadsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + var wxConfig = HttpExtend.MapFile(@"Config.cfg", downloadsPath + @"\WXWork\Global"); + if (File.Exists(wxConfig)) + { + try + { + File.Delete(wxConfig); + } + catch (Exception) + { } + StartWechat(true); + } + } + catch (Exception ex) + { + result = new RemoteLoginCode() { pid = -1, rType = RobotType.客户端企业微信, b64Md5 = ex.Message }; + } + + if (result == null) + { + result = Task.Factory.StartNew(delegate () + { + var awaitTime = DateTime.Now.AddSeconds(10); + do + { + Thread.Sleep(200); + Cache cache = HttpRuntime.Cache; + object item = cache[RemoteCache]; + if (item != null) + { + cache.Remove(RemoteCache); + var r = item as RemoteLoginCode; + return r; + } + } while (awaitTime >= DateTime.Now); + return null; + }).Result; + } + var socketClient = EasySoc.GetSocket(); + var msg = new CommonResult(); + msg.RobotUsername = string.Empty; + msg.RobotUsernick = string.Empty; + msg.RobotType = RobotType.客户端企业微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvLoginCode_workWeChat; + msg.Data = result == null ? string.Empty : JsonConvert.SerializeObject(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 卸载安装 + /// + public static void UnInstall() + { + try + { + //DestroyWxWork(); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".."); + } + } + #endregion + } +} diff --git a/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Analysis.cs b/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Analysis.cs new file mode 100644 index 0000000..9f0d392 --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Analysis.cs @@ -0,0 +1,1158 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using NM_WeChat; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Properties; +using PCRobot.Utils; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; +using Newtonsoft.Json.Linq; + +namespace PCRobot.PCWechat +{ + + /* + 接口文档:https://www.showdoc.cc/WxWorkNewHook?page_id=3846144660177490 + /////密码:784615627. + */ + + public partial class Wechat_Xiaoxie_QY + { + + private static Dictionary MT_APP_READY_MSG_BIND = new Dictionary(); + + // 接收消息回调 + private static void WxRecvCallback(uint _dwClient, IntPtr intPtr, uint dwSize) + { + + try + { + byte[] body = new byte[dwSize]; + Marshal.Copy(intPtr, body, 0, body.Length); + var recvData = Encoding.UTF8.GetString(body).Replace("\0", "").Trim();//再转成UTF8 + + var dwClientid = _dwClient; + + if (WechatClient.IsDebug) + LogHelper.GetSingleObj().Debug("调试企业收到文本消息", $"{dwClientid} -> {recvData}\r\n"); + + //var method = new Action(delegate () + Task.Factory.StartNew(delegate () + { + try + { + Console.WriteLine("企业收到消息:" + recvData); + + var jObj = JObject.Parse(recvData); + if (jObj == null) return; + if (!jObj.ContainsKey("type") || jObj["type"] == null) + return; + + var data = jObj["data"]; + var type = jObj["type"].ToString(); + + MsgType msgType; + if (!Enum.TryParse(type, out msgType)) return; + + + //获取机器人对象 + WechatUser user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + + Console.WriteLine($"dwClientid = {dwClientid}"); + switch (msgType) + { + case MsgType.MT_APP_READY_MSG: + MT_APP_READY_MSG_BIND[dwClientid] = int.Parse(data["pid"].ToString()); + break; + case MsgType.MT_PARAMS_ERROR_MSG: + { } + break; + case MsgType.MT_USER_LOGIN://登陆消息 + { + var wxid = data["user_id"].ToString(); + user = WechatClient.GetUser(wxid, dwClientid, WechatType.Xiaoxie_QY); + user.Nickname = data["username"].ToString(); + user.HeaderUrl = data["avatar"].ToString(); + //user.DBFile = data["wx_user_dir"].ToString(); + user.Pid = MT_APP_READY_MSG_BIND.ContainsKey(dwClientid) ? MT_APP_READY_MSG_BIND[dwClientid] : 0; //uint.Parse(data["pid"].ToString()); + user.Phone = data["mobile"].ToString(); + user.Uin = wxid; + WechatClient.OnRefUserEvent(user, WaitLoginResult); + } + break; + case MsgType.MT_USER_LOGOUT: + { + var wxid = data["user_id"].ToString(); + user = WechatClient.Users.FirstOrDefault(f => f.Key == wxid).Value; + if (user != null) + { + LogHelper.GetSingleObj().Info("系统", $"LogOut_QY事件退出,Uin:{user.Uin},微信:{user.Nickname}({wxid})"); + WechatClient.RemoveUser(user); + } + } + break; + case MsgType.MT_LOGIN_QRCODE_MSG: + { + //{"data":{"file":"C:\\Users\\秒单客006\\Documents\\WXWork\\Global\\Image\\089d9de9-cc40-458a-af4a-b39a04e2f95f.jpg"},"type":11028} + if (data["file"] == null) return; + if (MT_APP_READY_MSG_BIND.ContainsKey(dwClientid)) + { + var file = data["file"].ToString(); + + if (File.Exists(file)) + { + var cfBase64 = Common.ConvertImageToBase64(Image.FromFile(file)); + + var codeInfo = new RemoteLoginCode() { pid = MT_APP_READY_MSG_BIND[dwClientid], cImgB64 = cfBase64, b64Md5 = HttpHelper.ToMD5(cfBase64), rType = RobotType.客户端企业微信, t = HttpExtend.GetTimeStamp(DateTime.Now) }; + + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[RemoteCache]; + cache.Insert(RemoteCache, codeInfo, null, DateTime.Now.AddSeconds(3), Cache.NoSlidingExpiration); + + RemoteLoginCodes.Add(codeInfo); + } + } + } + break; + case MsgType.MT_GET_OWNER_INFO_MSG:// 获取自己信息 + { + #region 数据结构 + /* + { + "data": { + "account": "xxxxx@xxx.onexmail.com", // 帐号 + "acctid": "xxxxx", // acctid + "avatar": "http://wework.qpic.cn/bizmail/xxxDM808qnyFVjQ/0", // 头像 + "corp_id": "1970325032041886", // 公司id + "corp_name": "xxxxxxxxx有限公司", // 公司全称 + "corp_short_name": "xxxxx", // 公司简称 + "email": "xxxxx@qq.com", // 邮箱 + "job_name": "总经理", // 职位 + "mobile": "137xxxxxxxxx", // 手机号 + "nickname": "小邪212", // 昵称 + "position": "总经理", // 职位 + "sex": 2, // 性别 0 未知,1男,2女 + "user_id": "1688xxxx353xxxx", // 用户id + "username": "小邪" // 名称 + }, + "type": 11035 + } + */ + #endregion + if (data == null || user == null) return; + + var f = new WorkFriendInfo(); + f.avatar = data["avatar"]?.ToString(); + //f.conversation_id = data["conversation_id"]?.ToString(); + //f.desc = item["desc"]?.ToString(); + f.nickname = data["nickname"]?.ToString(); + f.position = data["position"]?.ToString(); + f.realname = data["username"]?.ToString(); + f.remark = data["username"]?.ToString(); + f.sex = data["sex"].ToObject(); + f.user_id = data["user_id"].ToString(); + f.username = data["username"].ToString(); + + var friend = user.WorkFriends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend == null) + user.WorkFriends.Add(f); + + } + break; + case MsgType.MT_GET_INNER_USERS_MSG:// 获取内部联系人列表 + { + } + break; + case MsgType.MT_GET_EXTERNAL_USERS_MSG:// 获取外部联系列表 + { + #region 外部联系列表 + + #region 消息样式 + //{"data":{"page_num":1,"page_size":10000,"total":44,"total_page":1,"user_list":[{"acctid":"AoQi","add_time":1594358458,"avatar":"https://wework.qpic.cn/wwhead/duc2TvpEgST9hicuyypLEKMFMfDnH4KeYskpFLBx46N4YMPdu9ibu6uvic9tRMx1O5oc1e94LvWHZI/0","conversation_id":"S:1688853884018611_1688853956558440","corp_id":"1970325130121266","mobile":"","nickname":"A46「猫七」【置顶常用】","position":"","realname":"**新","remark":"","sex":2,"unionid":"ozynqspv4YiVjaa04jYgRulxWfQ8","user_id":"1688853884018611","username":"A46🐱「猫七」【置顶常用】"},{"acctid":"","add_time":1588747919,"avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM4pFj4ic9BTuoseZNnibY90lvKkoAFichAcjjao0WqvzvHnQ/0","conversation_id":"S:1688853956558440_7881301062943857","corp_id":"1970325134026788","mobile":"","nickname":"","position":"","realname":"","remark":"查优惠小助手(梦瑶)","sex":2,"unionid":"ozynqsjIzu8BxAu_dcoFLWuFSVWA","user_id":"7881301062943857","username":"A查优惠小助手-梦瑶"},{"acctid":"","add_time":1588745188,"avatar":"http://wx.qlogo.cn/mmhead/GtsibMna7cCkYQ3fJffrweyEvlODDOH1SCzOtwflnBsc/0","conversation_id":"S:1688853956558440_7881301162944044","corp_id":"1970325134026788","mobile":"","nickname":"","position":"","realname":"","remark":"查优惠小助手(抹茶)","sex":2,"unionid":"ozynqsjMTV4VYwLqjcDcfcH5VFsI","user_id":"7881301162944044","username":"老妖助理15"}]},"type":11037} + #endregion + + if (data == null || user == null) + return; + + var _type = RobotIsRunType.获取好友列表; + if (user.IsGetDic.ContainsKey(_type)) + { + if (user.IsGetDic[_type]) + return; + } + + try + { + user.IsGetDic[_type] = true; + + var jArr = (JArray)data["user_list"]; + for (int i = 0; i < jArr.Count; i++) + { + var item = jArr[i]; + var username = item["user_id"]?.ToString(); + //if (username.IsGongZhongHao()) continue; + + WorkFriendInfo f = new WorkFriendInfo(); + + f.acctid = item["acctid"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.conversation_id = item["conversation_id"]?.ToString(); + f.corp_id = item["corp_id"]?.ToString(); + f.mobile = item["mobile"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.position = item["position"]?.ToString(); + f.realname = item["realname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = item["sex"].ToObject(); + f.user_id = username; + f.username = item["username"]?.ToString(); + + var friend = user.WorkFriends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend == null) + user.WorkFriends.Add(f); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业获取内部联系人列表", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetDic.Remove(_type); + } + #endregion + } + break; + case MsgType.MT_GET_ROOMS_MSG:// 获取群聊列表 + { + #region 数据结构 + //{"data":{"page_num":1,"page_size":100000,"room_list":[{"conversation_id":"R:10696051756073403","create_time":1587126543,"create_user_id":"7881302509911391","is_admin":0,"is_creator":0,"is_external":1,"nickname":"软件反馈群","total":21},{"conversation_id":"R:238567000711635","create_time":1644470134,"create_user_id":"1688850065257778","is_admin":0,"is_creator":0,"is_external":0,"nickname":"张谊玉、洪荒老道、祁举兵","total":5},{"conversation_id":"R:1970325073072411","create_time":1559292789,"create_user_id":"1688853956450720","is_admin":0,"is_creator":0,"is_external":0,"nickname":"成都秒单客网络科技有限公司","total":20},{"conversation_id":"R:95666354828251","create_time":1644746098,"create_user_id":"1688853956558440","is_admin":0,"is_creator":1,"is_external":0,"nickname":"..............................................","total":4},{"conversation_id":"R:10774828428256418","create_time":1644804316,"create_user_id":"1688853956558440","is_admin":0,"is_creator":1,"is_external":1,"nickname":",,,,,,,,,,","total":3},{"conversation_id":"R:289059290","create_time":1618382594,"create_user_id":"1688853956558440","is_admin":0,"is_creator":1,"is_external":0,"nickname":"转发综合群","total":4},{"conversation_id":"R:10757092148832341","create_time":1648025176,"create_user_id":"1688853956558440","is_admin":0,"is_creator":1,"is_external":1,"nickname":"企业外部群","total":41}],"total":7,"total_page":1},"type":11038} + + #endregion + + if (data == null || user == null) + return; + + var _type = RobotIsRunType.获取群列表; + if (user.IsGetDic.ContainsKey(_type)) + { + if (user.IsGetDic[_type]) + return; + } + + try + { + user.IsGetDic[_type] = true; + + var member_list = (JArray)data["room_list"]; + if (member_list == null) + return; + + for (int i = 0; i < member_list.Count; i++) + { + //{"conversation_id":"R:10696051756073403","create_time":1587126543,"create_user_id":"7881302509911391","is_admin":0,"is_creator":0,"is_external":1,"nickname":"软件反馈群","total":21} + var item = member_list[i]; + + var f = new WorkFriendInfo(); + + f.avatar = string.Empty; + f.user_id = item["conversation_id"]?.ToString(); + f.manager_wxid = item["create_user_id"]?.ToString(); + f.is_manager = item["is_admin"].ToObject(); + f.nickname = item["nickname"]?.ToString(); + f.username = item["nickname"]?.ToString(); + f.remark = item["nickname"]?.ToString(); + + var friend = user.WorkFriends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend == null) + user.WorkFriends.Add(f); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业微信解析群列表", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetDic.Remove(_type); + } + } + break; + case MsgType.MT_GET_USER_DETAIL_MSG:// 获取用户详细信息 + { + #region 数据结构 + //{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","corp_id":"1970325134026788","desc":"","external_job":"","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":"18"} + #endregion + + if (user == null || data == null) return; + //有时候接收到的数据为一下情况 + //{"data":{"user_id":"7881302484994318"},"type":11039} + + var username = data["user_id"]?.ToString(); + + if (user.IsGetContactDic.ContainsKey(username) && user.IsGetContactDic[username]) + return; + try + { + try + { + user.IsGetContactDic[username] = true; + } + catch (Exception) + { + } + + var f = new WorkFriendInfo(); + f.corp_id = data["corp_id"]?.ToString(); + f.mobile = data["mobile"]?.ToString(); + f.acctid = data["acctid"].ToString(); + f.avatar = data["avatar"]?.ToString(); + f.conversation_id = data["conversation_id"]?.ToString(); + f.desc = data["desc"]?.ToString(); + f.nickname = data["nickname"]?.ToString(); + f.position = data["position"]?.ToString(); + f.realname = data["realname"]?.ToString(); + f.remark = data["remark"]?.ToString(); + f.sex = data["sex"].ToObject(); + f.user_id = data["user_id"]?.ToString(); + f.username = data["username"]?.ToString(); + + var friend = user.WorkFriends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend != null) + if (!user.WorkFriends.TryTake(out friend)) return; + user.WorkFriends.Add(f); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("机器人企业微信解析用户详细信息", $@"原始数据:{recvData} +错误:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Thread.Sleep(100); + user.IsGetContactDic.Remove(username); + } + } + break; + case MsgType.MT_GET_ROOM_MEMBERS_MSG:// 获取群成员列表 + { + #region 数据样式 + /* + {"data":{"conversation_id":"R:10696051756073403","member_list":[{"acctid":"WuJiaHua","avatar":"http://wework.qpic.cn/bizmail/FxrNrXCeEh8Kwv4ia3iahWCbkR7Y0VqoBniaJ5hrlKggVaibBXIxmOBb8A/0","corp_id":"1970325073072411","invite_user_id":"7881302509911391","nickname":"洪荒老道","position":"","realname":"吴嘉华","remark":"","sex":1,"user_id":"1688853956558440","username":"洪荒老道"},{"acctid":"YuQi","avatar":"http://wework.qpic.cn/bizmail/PN2IeoKDkmhqqH0nlh2Lm6TVZRNAtgLPyg2ick4sPBEB0kzP0hDmQmg/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"秒单客_小鱼","position":"","realname":"虞祁","remark":"","sex":2,"user_id":"1688853956590186","username":"小鱼"},{"acctid":"ZhangYiYu","avatar":"http://wework.qpic.cn/bizmail/Yfk60WuPLgEuo6ViauAdDeqqtlOuH8EYEh0K0Cg9KGicYHGyg9gw1o2w/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"小张","position":"","realname":"张谊玉","remark":"","sex":0,"user_id":"1688853956590187","username":"张谊玉"},{"acctid":"XiaoZhangTongXue","avatar":"https://wework.qpic.cn/wwhead/duc2TvpEgST9hicuyypLEKE4HsVWEQswCosv5s4Je9eyrmicu2cvscczGLmSmwQBEzPaZO82TA7IY/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"秒单客-小张","position":"","realname":"张谊玉","remark":"","sex":1,"user_id":"1688853956642143","username":"张谊玉"},{"acctid":"WenQi","avatar":"http://wework.qpic.cn/bizmail/rftUYt0pUSNM9UGLVhJT8SADPRo7UUwEXc1TibElDW2b8OBbrUAibN2w/0","corp_id":"1970325073072411","invite_user_id":"1688853956558440","nickname":"","position":"","realname":"文奇","remark":"","sex":1,"user_id":"1688853956644076","username":"文奇"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/U8XnjHx15KhdibgkJ49XtGJ44Y3bH7VkpMTy2UhJicrOs/0","corp_id":"1970325134026788","invite_user_id":"7881302509911391","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881299792900727","username":"小锋"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/ETNocE50L3oEX3eSEr47qkodhRfgpya2ZYt3D08Bh6k/0","corp_id":"1970325134026788","invite_user_id":"7881299792900727","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881299980969589","username":"嘿"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/USH8Nb3Hz5TauZmclE9wV7qAOMo3xTf4mPG8qHWicKjfgTExgLX8MHw/0","corp_id":"1970325134026788","invite_user_id":"7881301450899709","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881300660017681","username":"Suki_cc"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaELHEV52PNTeBgDTw7WZw5zaXqC3Dx8NlxzoWbZodIV6nA/0","corp_id":"1970325134026788","invite_user_id":"7881303073899390","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301052912667","username":"管家助理"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/le1D2uwOTUNrTr97NDfcJfBibsBcv6D95v5G8WaF5pWjRxsgo8AgOqQ/0","corp_id":"1970325134026788","invite_user_id":"7881303073899390","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301334966174","username":"M."},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM58vIBW7iaDy1L2LnWp6bFQaZageAQ1dUAQbBhtbFEia9XQ/0","corp_id":"1970325134026788","invite_user_id":"7881302509911391","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881301450899709","username":"幸运的小蔡"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/9qclib0CZpLj64d8S0eVZCgJhsF1V0wMicHrM3LRia1bq4/0","corp_id":"1970325134026788","invite_user_id":"7881301450899709","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881301996898661","username":"阿羣"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaEJUq43owiazPpKBwI044FZ6GbmOgiaHlt9TWWC7m7ajYnQQ/0","corp_id":"1970325134026788","invite_user_id":"7881302509911391","nickname":"","position":"","realname":"","remark":"阿威?? ?? ?? ?? ??","sex":1,"user_id":"7881302027905870","username":"阿威?? ?? ?? ?? ??"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM6CiaVp63VVTIRySkxia2KSGQ6hrYAvAkkjoMpl4wFjyhIA/0","corp_id":"1970325134026788","invite_user_id":"7881302509911391","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881302509911391","username":"千年老妖"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaEIkxibLqBfcon3IAic6a4DFICQIR7EdHM0mAuHPUXlcl5iag/0","corp_id":"1970325134026788","invite_user_id":"7881301450899709","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881302973987188","username":"chan??baek"},{"acctid":"","avatar":"http://wx.qlogo.cn/mmhead/aUwBqqfR4L9uicc3e31iafC57QBG8BjVwPhmNKE77LdKo/0","corp_id":"1970325134026788","invite_user_id":"7881301450899709","nickname":"","position":"","realname":"","remark":"","sex":1,"user_id":"7881303073899390","username":"小明"}]},"type":11040} + */ + #endregion + + if (user == null || data == null) return; + + var conversation_id = data["conversation_id"].ToString(); + if (user.IsGetContactDic.ContainsKey(conversation_id) && user.IsGetContactDic[conversation_id]) + return; + try + { + user.IsGetContactDic[conversation_id] = true; + + var member_list = (JArray)data["member_list"]; + if (member_list == null) + return; + + var group = new WorkGroupInfo() { conversation_id = conversation_id }; + var groupTmp = user.WorkGroups.FirstOrDefault(z => z.conversation_id == conversation_id); + if (groupTmp != null) + group = groupTmp; + group.total = member_list.Count; + group.friends = new List(); + + for (int i = 0; i < member_list.Count; i++) + { + //{"acctid":"WuJiaHua","avatar":"http://wework.qpic.cn/bizmail/FxrNrXCeEh8Kwv4ia3iahWCbkR7Y0VqoBniaJ5hrlKggVaibBXIxmOBb8A/0","corp_id":"1970325073072411","invite_user_id":"7881302509911391","nickname":"洪荒老道","position":"","realname":"吴嘉华","remark":"","sex":1,"user_id":"1688853956558440","username":"洪荒老道"} + + var item = member_list[i]; + + var f = new WorkFriendInfo(); + + f.acctid = item["acctid"]?.ToString(); + f.avatar = item["avatar"]?.ToString(); + f.conversation_id = conversation_id; + f.corp_id = item["corp_id"]?.ToString(); + f.mobile = item["mobile"]?.ToString(); + f.nickname = item["nickname"]?.ToString(); + f.position = item["position"]?.ToString(); + f.realname = item["realname"]?.ToString(); + f.remark = item["remark"]?.ToString(); + f.sex = item["sex"].ToObject(); + f.nickname = item["username"]?.ToString(); + f.user_id = item["user_id"]?.ToString(); + + var friend = group.friends.FirstOrDefault(z => z.user_id == f.user_id); + if (friend == null) + group.friends.Add(f); + } + } + catch (Exception ex) + { + } + } + break; + case MsgType.MT_ROOM_ADD_MEMBER_NOTIFY_MSG://群成员新增通知 + { + #region 数据结构 + //{"data":{"member_list":[{"name":"CoCo😘","user_id":"7881299477994410"},{"name":"秒单客-小张","user_id":"7881301029989846"},{"name":"秒单客-小鱼","user_id":"7881302305959168"}],"op_user_id":"1688853956558440","op_user_name":"洪荒老道","room_conversation_id":"R:10696053211008104","room_name":"洪荒老道、CoCo😘、秒单客-小张"},"type":11072} + #endregion + + if (data == null || user == null) + return; + var member_list = (JArray)data["member_list"]; + if (member_list == null || member_list.Count == 0) return; + + var socketClient = EasySoc.GetSocket(); + + var roomConversationId = data["room_conversation_id"]?.ToString(); + var roomName = data["room_name"]?.ToString(); + var opUserId = data["op_user_id"]?.ToString();//邀请人账号 + var opUserName = data["op_user_name"]?.ToString();//邀请人昵称 + + for (int i = 0; i < member_list.Count; i++) + { + var item = member_list[i]; + + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember_workWeChat; + newMember.RobotType = RobotType.客户端企业微信; + newMember.RobotUsername = user.Wxid; + newMember.RobotUsernick = user.Nickname; + + newMember.SourceNick = opUserName; + newMember.SourceName = opUserId; + newMember.MemberNick = item["name"]?.ToString(); ; + newMember.MemberName = item["user_id"]?.ToString(); ; + newMember.GroupId = roomConversationId; + newMember.GroupNick = roomName; + newMember.TotalMember = 0; + + socketClient.Send(newMember); + Thread.Sleep(50); + } + break; + } + case MsgType.MT_ROOM_DEL_MEMBER_NOTIFY_MSG://剔除群成员通知 + break; + case MsgType.MT_RECV_TEXT_MSG://收到文本 + { + if (data == null || user == null) return; + + var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + + #region 文本消息 + + #region 消息样式 + //{"data":{"content":"我17","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"19","receiver":"1688853956558440","send_time":"1584013142","sender":"7881301610989604","sender_name":"17","server_id":"1000481"},"type":11041} - 通过好友返回的数据 + //{"data":{"content":"哦哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"33","receiver":"1688853956558440","send_time":"1584014191","sender":"7881301610989604","sender_name":"17","server_id":"1000520"},"type":11041} - 别人给我发了条消息 + //{"data":{"content":"图婆","content_type":2,"conversation_id":"S:1688853956558440_7881301610989604","local_id":"36","receiver":"1688853956558440","send_time":"1584014736","sender":"7881301610989604","sender_name":"17","server_id":"1000542"},"type":11041} + + //{"data":{"content":"哦哦哦","content_type":0,"conversation_id":"S:1688853956450720_1688853956558440","local_id":"22","receiver":"1688853956450720","send_time":"1584013962","sender":"1688853956558440","sender_name":"华","server_id":"1000498"},"type":11041} - 收到自己发的消息 + //{"data":{"content":"给我发条消息","content_type":0,"conversation_id":"S:1688853956450720_1688853956558440","local_id":"23","receiver":"1688853956450720","send_time":"1584014066","sender":"1688853956558440","sender_name":"华","server_id":"1000500"},"type":11041} + + //{"data":{"content":"饿的","content_type":0,"conversation_id":"R:10696053211008104","local_id":"42","receiver":"R:10696053211008104","send_time":"1584015069","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000574"},"type":11041} - 收到自己发送的群消息 + + #endregion + + //{"data":{"at_list":[],"content":"我是机器学习","content_type":2,"conversation_id":"S:1688853764215634_7881300713013122","local_id":"27946","receiver":"1688853764215634","send_time":"1589009390","sender":"7881300713013122","sender_name":"机器学习","server_id":"1088720"},"type":11041} + //0、2 - 发送的文字 (0) + //if (content_type == "0" || content_type == "2") + { + var content = data["content"]?.ToString(); //文本消息内容 + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = data["send_time"]?.ToString(); //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + + //是否为辅助 + var isSend = false; + var RobotUsername = string.Empty; + var RobotUsernick = string.Empty; + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + var wmsg = new WorkWechatReceiveMsg(); + + #region 处理辅助 + var sendWxid = sender; + var sendNick = sender_name; + if (!WechatClient.IsAuxiliaryInput(sender, conversation_id, content)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + content); + return; + } + var ass = WechatClient.IsAssistance(sender, conversation_id, dwClientid, WechatType.Xiaoxie_QY); + if (ass.type == WechatClient.AssistanceType.终止) return; + + wmsg.IsSend = ass.type == WechatClient.AssistanceType.辅助; + + var usernick = string.Empty; + + if (conversation_id.IsQun()) + { + wmsg.FromGroupid = conversation_id; + //wmsg.GroupNick = hook.FindNick(conversation_id); + } + else if (wmsg.IsSend) + { + sendWxid = receiver; + sendNick = user.FindNick(receiver); + } + + wmsg.FromUsername = sendWxid; + wmsg.FromUsernick = sendNick; + + #endregion + + wmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + wmsg.IsSend = isSend; + wmsg.RobotUsername = RobotUsername; + wmsg.RobotUsernick = RobotUsernick; + wmsg.RobotType = RobotType.客户端企业微信; + + + //if (content == "[你收到了一个微信红包,暂时无法查看]") + // wmsg.FromMessageType = WechatMsgType.红包; + //else + wmsg.FromMessageType = WechatMsgType.文本; + + wmsg.FromMessage = content; + + socketClient.Send(wmsg); + } + #endregion + } + break; + //case MsgType.MT_RECV_IMG_MSG://收到图片 + // { + // #region 图片消息 + + // #region 消息样式 + + // //{"data":{"content_type":101,"conversation_id":"R:10696053211008104","file_name":"7305d3cd-e94f-47db-a604-ce079e6c9ac5.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\7305d3cd-e94f-47db-a604-ce079e6c9ac5.jpg","file_size":19457,"local_id":"73","receiver":"1688853956558440","send_time":"1584028981","sender":"7881301364988874","sender_name":"18","server_id":"1000677"},"type":11042} - 别人在群发的图片 + + // //{"data":{"content_type":101,"conversation_id":"S:1688853956558440_7881301364988874","file_name":"29c9c19d-e8d7-4cb0-95b5-e1a7d385003a.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\29c9c19d-e8d7-4cb0-95b5-e1a7d385003a.jpg","file_size":19457,"local_id":"74","receiver":"1688853956558440","send_time":"1584029032","sender":"7881301364988874","sender_name":"18","server_id":"1000680"},"type":11042} - 别人私聊发的图片 + + // //{"data":{"content_type":14,"conversation_id":"R:10696053211008104","file_name":"0f7890b8ea01f7205a76d1195dab66b0.png","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\0f7890b8ea01f7205a76d1195dab66b0.png","file_size":1627,"local_id":"75","receiver":"R:10696053211008104","send_time":"1584029085","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000685"},"type":11042} - 自己群里发的图片 + + // //{"data":{"content_type":14,"conversation_id":"S:1688853956558440_7881301364988874","file_name":"9c6d1a59d8f122fc85c3435ea2aa46fc.jpg","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Image\\2020-03\\9c6d1a59d8f122fc85c3435ea2aa46fc.jpg","file_size":178092,"local_id":"76","receiver":"7881301364988874","send_time":"1584029534","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000689"},"type":11042} - 自己私聊发的图片 + + // #endregion + + // //14、101 (14) + + // if (data == null) return; + + // var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + // if (content_type == "14") return; + + // var socketClient = EasySoc.GetSocket(); + + // var conversation_id = data["conversation_id"]?.ToString(); //会话ID + // var local_id = data["local_id"]?.ToString(); //消息的本地ID + // var receiver = data["receiver"]?.ToString(); //接收者的user_id + // var send_time = data["send_time"]?.ToString(); //消息时间戳 + // var sender = data["sender"]?.ToString(); //发送者的user_id + // var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + // var server_id = data["server_id"]?.ToString(); //消息的服务器ID + // var file_path = data["file_path"]?.ToString(); //图片路径 + + // var wmsg = new WorkWechatReceiveMsg(); + // wmsg.Cmd = PCRobotCMD.rcvImg_workWeChat; + // wmsg.RobotType = RobotType.客户端企业微信; + // wmsg.IsSend = false; + // wmsg.RobotUsername = user.Wxid; + // wmsg.RobotUsernick = user.Nickname; + + // wmsg.FromMessage = $"[图片={file_path}]"; + // wmsg.FromMessageType = WechatMsgType.图片; + + // if (conversation_id.Contains("R:")) + // { + // wmsg.FromGroupid = conversation_id; + // wmsg.FromUsername = sender; + // wmsg.FromUsernick = sender_name; + // } + // else + // { + // wmsg.FromUsername = sender; + // wmsg.FromUsernick = sender_name; + // } + // wmsg.FromMessage = string.Empty; + + // socketClient.Send(wmsg); + // #endregion + // } + // break; + //case MsgType.MT_RECV_VIDEO_MSG://收到视频 + // { + // #region 收到视频 + + // #region 消息样式 + // //{"data":{"content_type":103,"conversation_id":"S:1688853956558440_7881301364988874","duration":1,"file_name":"video.MP4","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Video\\2020-03\\video.MP4","file_size":198490,"height":960,"local_id":"77","receiver":"1688853956558440","send_time":"1584031142","sender":"7881301364988874","sender_name":"18","server_id":"1000691","width":544},"type":11043} - 别人发 + + // //{"data":{"content_type":23,"conversation_id":"S:1688853956558440_7881301364988874","duration":1,"file_name":"video.MP4","file_path":"C:\\Users\\先森吳\\Documents\\WXWork\\1688853956558440\\Cache\\Video\\2020-03\\video.MP4","file_size":198490,"height":960,"local_id":"78","receiver":"7881301364988874","send_time":"1584031203","sender":"1688853956558440","sender_name":"吴嘉华","server_id":"1000696","width":544},"type":11043} - 自己发 + // #endregion + + // //23、103 (23) + + // if (data == null) return; + + // var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + // if (content_type == "23") return; + + // var socketClient = EasySoc.GetSocket(); + // var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + // if (user == null) + // return; + + // var conversation_id = data["conversation_id"]?.ToString(); //会话ID + // var local_id = data["local_id"]?.ToString(); //消息的本地ID + // var receiver = data["receiver"]?.ToString(); //接收者的user_id + // var send_time = data["send_time"]?.ToString(); //消息时间戳 + // var sender = data["sender"]?.ToString(); //发送者的user_id + // var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + // var server_id = data["server_id"]?.ToString(); //消息的服务器ID + // var file_path = data["file_path"]?.ToString(); //图片路径 + + // var wmsg = new WorkWechatReceiveMsg(); + // wmsg.Cmd = PCRobotCMD.rcvFile_workWeChat; + // wmsg.RobotType = RobotType.客户端企业微信; + // wmsg.IsSend = false; + // wmsg.RobotUsername = user.Wxid; + // wmsg.RobotUsernick = user.Nickname; + + // wmsg.FromMessage = $"[视频={file_path}]"; + // wmsg.FromMessageType = WechatMsgType.视频; + + // if (conversation_id.Contains("R:")) + // { + // wmsg.FromGroupid = conversation_id; + // wmsg.FromUsername = sender; + // wmsg.FromUsernick = sender_name; + // } + // else + // { + // wmsg.FromUsername = sender; + // wmsg.FromUsernick = sender_name; + // } + // wmsg.FromMessage = string.Empty; + + // socketClient.Send(wmsg); + + // #endregion + // } + // break; + case MsgType.MT_RECV_IMG_MSG: //收到图片 + case MsgType.MT_RECV_VIDEO_MSG: //收到视频 + { + if (data == null || user == null) return; + + var content_type = data["content_type"]?.ToString(); //企业微信消息类型 + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = (long)data["send_time"]; //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + var cdn_type = data["cdn_type"].ToObject(); //Cdn类型 + + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvFile_workWeChat; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.IsSend = false; + wmsg.RobotUsername = user.Wxid; + wmsg.RobotUsernick = user.Nickname; + + + + var filePath = string.Empty; + #region 下达事件 + if (MsgType.MT_RECV_IMG_MSG == msgType) + { + #region cdn + var cdn = data["cdn"]; + if (cdn != null) + { + if (cdn_type == 1) + { + var aes_key = cdn["aes_key"].ToObject(); + var auth_key = cdn["auth_key"].ToObject(); + var ld_size = cdn["ld_size"].ToObject(); + var ld_url = cdn["ld_url"].ToObject(); + var md5 = cdn["md5"].ToObject(); + var md_size = cdn["md_size"].ToObject(); + var md_url = cdn["md_url"].ToObject(); + var size = cdn["size"].ToObject(); + var url = cdn["url"].ToObject(); + + filePath = user.CdnDown(url, auth_key, aes_key, size, FileSuffixType.jpg).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收图片消息Cdn下载失败"); + } + else if (cdn_type == 2) + { + var aes_key = cdn["aes_key"].ToObject(); + var file_id = cdn["file_id"].ToObject(); + var file_name = cdn["file_name"].ToObject(); + var md5 = cdn["md5"].ToObject(); + //var preview_img_url = cdn["preview_img_url"].ToObject(); + var size = cdn["size"].ToObject(); + + filePath = hook.C2cCdnDown(aes_key, file_id, size, QyCdnFileType.图片_视频, FileSuffixType.jpg).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收图片消息C2cCdn下载失败"); + } + + rmsg.Message = $"[图片={filePath}]"; + rmsg.MessageType = WechatMsgType.图片; + } + #endregion + } + else if (MsgType.MT_RECV_VIDEO_MSG == msgType) + { + #region cdn + var cdn = data["cdn"]; + if (cdn != null) + { + if (cdn_type == 1) + { + var aes_key = cdn["aes_key"].ToObject(); + var auth_key = cdn["auth_key"].ToObject(); + var md5 = cdn["md5"].ToObject(); + var preview_img_size = cdn["preview_img_size"].ToObject(); + var preview_img_url = cdn["preview_img_url"].ToObject(); + var size = cdn["size"].ToObject(); + var url = cdn["url"].ToObject(); + + filePath = hook.CdnDown(url, auth_key, aes_key, size, FileSuffixType.mp4).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收视频消息Cdn下载失败"); + } + else if (cdn_type == 2) + { + var aes_key = cdn["aes_key"].ToObject(); + var file_id = cdn["file_id"].ToObject(); + var file_name = cdn["file_name"].ToObject(); + var md5 = cdn["md5"].ToObject(); + //var preview_img_url = cdn["preview_img_url"].ToObject(); + var size = cdn["size"].ToObject(); + + filePath = hook.C2cCdnDown(aes_key, file_id, size, QyCdnFileType.图片_视频, FileSuffixType.silk).Result; + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + throw new Exception("企业接收视频消息C2cCdn下载失败"); + } + rmsg.Message = $"[视频={filePath}]"; + rmsg.MessageType = WechatMsgType.视频; + } + #endregion + } + if (conversation_id.IsQun()) + { + rmsg.GroupId = conversation_id; + rmsg.GroupNick = hook.FindNick(conversation_id); + } + + rmsg.SendUserWxid = sender; + rmsg.SendUserNick = sender_name; + rmsg.Timestamp = send_time; + rmsg.MsgId = server_id.Trim(); + rmsg.IsSend = false; + rmsg.OriMessage = JsonConvert.SerializeObject(new { data = data, filePath = filePath }); + + RobotClient.Events.OnEvent(hook, rmsg); + + #endregion + } + break; + case MsgType.MT_RECV_VOICE_MSG: //收到语音 + break; + case MsgType.MT_RECV_FILE_MSG://收到文件 + break; + case MsgType.MT_RECV_LOCATION_MSG://收到位置 + break; + case MsgType.MT_RECV_LINK_CARD_MSG://收到链接 + { + #region 链接消息 + + #region 消息样式 + //{"data":{"content_type":13,"conversation_id":"S:1688853956558440_7881301364988874","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"","local_id":"82","receiver":"1688853956558440","send_time":"1584033150","sender":"7881301364988874","sender_name":"18","server_id":"1000715","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 别人发送的私聊链接 + + //{"data":{"content_type":13,"conversation_id":"R:10696053211008104","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"","local_id":"85","receiver":"1688853956558440","send_time":"1584034341","sender":"7881301364988874","sender_name":"18","server_id":"1000724","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 别人发送的群聊链接 + + + //{"data":{"content_type":13,"conversation_id":"S:1688853956558440_7881301364988874","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"https://wework.qpic.cn/wwpic/51458_1ermIpIgTJu-_11_1584034011/0","local_id":"83","receiver":"7881301364988874","send_time":"1584034011","sender":"1688853956558440","sender_name":"吴","server_id":"1000720","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 自己发送的私聊 + + //{"data":{"content_type":13,"conversation_id":"R:10696053211008104","desc":"【正品险·全国联保】听音乐、语音遥控家电的人工智能音箱","image_url":"https://wework.qpic.cn/wwpic/51458_1ermIpIgTJu-_11_1584034011/0","local_id":"84","receiver":"R:10696053211008104","send_time":"1584034246","sender":"1688853956558440","sender_name":"吴","server_id":"1000722","title":"78元 小米(MI)小爱音箱 Play全新小爱同学升级版智能人工蓝牙WiFi音响 拼多多","url":"https://mobile.yangkeduo.com/goods1.html?goods_id=19287381820&page_from=35&share_uin=H3Z5B2UR6DQLWBIKN24YVO5XPQ_GEXDA&refer_share_id=e0d9d244358640aa853a8dcd1ff84216&refer_share_uid=4918926726&refer_share_channel=message&refer_share_form=card"},"type":11047} - 自己发送的群聊 + + #endregion + + var content_type = data["content_type"]?.ToString(); + //if (content_type != "13") return; + + var socketClient = EasySoc.GetSocket(); + + var conversation_id = data["conversation_id"]?.ToString(); //会话ID + var desc = data["desc"]?.ToString(); //链接描述 + var image_url = data["image_url"]?.ToString(); //链接缩略图url + var local_id = data["local_id"]?.ToString(); //消息的本地ID + var receiver = data["receiver"]?.ToString(); //接收者的user_id + var send_time = data["send_time"]?.ToString(); //消息时间戳 + var sender = data["sender"]?.ToString(); //发送者的user_id + var sender_name = data["sender_name"]?.ToString(); //发送者昵称 + var server_id = data["server_id"]?.ToString(); //消息的服务器ID + var title = data["title"]?.ToString(); //链接标题 + var url = data["url"]?.ToString(); //链接url + + var isSend = false; + var RobotUsername = string.Empty; + var RobotUsernick = string.Empty; + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + if (user.Wxid == sender) //0自己发送的消息 + { + if (!WechatClient.IsAuxiliaryInput(sender, receiver, url)) + { + Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + url); + return; + } + + var ass = WechatClient.IsAssistance(sender, receiver, dwClientid, WechatType.Xiaoxie_QY); + if (ass.type == WechatClient.AssistanceType.终止) return; + isSend = ass.type == WechatClient.AssistanceType.辅助; + + RobotUsername = ass.robotName; + RobotUsernick = ass.robotNick; + FromUsername = ass.fromName; + FromUsernick = ass.fromNick; + } + else + { + RobotUsername = user.Wxid; + RobotUsernick = user.Nickname; + FromUsername = sender; + FromUsernick = sender_name; + } + + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + wmsg.IsSend = isSend; + wmsg.RobotUsername = RobotUsername; + wmsg.RobotUsernick = RobotUsernick; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (conversation_id.Contains("R:")) + { + wmsg.FromGroupid = conversation_id; + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + else + { + wmsg.FromUsername = FromUsername; + wmsg.FromUsernick = FromUsernick; + } + wmsg.FromMessage = url; + + socketClient.Send(wmsg); + + #endregion + } + break; + case MsgType.MT_RECV_EMOTION_MSG://收到表情 + break; + case MsgType.MT_RECV_RED_PACKET_MSG://收到红包 + { + } + break; + case MsgType.MT_RECV_PERSON_CARD_MSG://收到个人名片 + { + //{"data":{"content":"推荐噢噢噢哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"81","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000703"},"type":11041} + + /* + {"data":{"avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaELtKaBvIBMGI7xTZdLA9mZglMaZQxPeBASJT1lCXCJnKg/0","content_type":41,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"80","nickname":"??欧尼桑","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000700","source":"微信","user_id":"7881301516989639"},"type":11050} + 收到消息:{"data":{"content":"推荐噢噢噢哦哦","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"81","receiver":"1688853956558440","send_time":"1584031525","sender":"7881301364988874","sender_name":"18","server_id":"1000703"},"type":11041} + */ + + //var content = data["content"]?.ToString(); + //var content_type = data["content_type"]?.ToString(); + //var conversation_id = data["conversation_id"]?.ToString(); + //var local_id = data["local_id"]?.ToString(); + //var receiver = data["receiver"]?.ToString(); + //var send_time = data["send_time"]?.ToString(); + //var sender = data["sender"]?.ToString(); + //var sender_name = data["sender_name"]?.ToString(); + //var server_id = data["server_id"]?.ToString(); + + } + break; + case MsgType.MT_RECV_MINIAPP_MSG://收到小程序 + { + //个人微信/企业微信 + //{"data":{"content_type":78,"conversation_id":"R:10696053211018728","enterpoint":"pages/tab/home/index.html?_um_ssrc=oucfI5QRI-8SbyOTKSGYt5-ia0dk&_um_sts=1610033684099","ghid":"gh_a0d7a7672cf7@app","headimg":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM43LsxpXHKd7ua7kwMZQ8WHmZlkYTzr3Tdm8sMOJ7Ypog/96","image_key1":"306b020102046430620201000204bafc490e02030f4df9020473e6607102045ff72a530436333133373039353935305f313734393433343231315f3262393764653133616335373232353633383831336564376334396563616164020100020300ab1004000201010201000400","image_key2":"61747072666A766977766D69726D6168","image_key3":"2b97de13ac57225638813ed7c49ecaad","image_size":43791,"is_pc":0,"local_id":"155","name":"啄木鸟家庭维修","receiver":"1688853956558440","send_time":"1610033747","sender":"7881302484994318","sender_name":"、","server_id":"1042188","title":"直营一口价,维修无猫腻","wxid":"wx3d6b1af0cb07fa5a"},"type":11066} + + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + + //var content_type = data["content_type"]?.ToString();//内容类型 78 + //var conversation_id = data["conversation_id"]?.ToString();//接收者的的会话ID + //var enterpoint = data["enterpoint"]?.ToString();//入口点 - 链接(小程序里面的链接) + //var receiver = data["receiver"]?.ToString();// 接收者的user_id + //var sender = data["sender"]?.ToString();// 发送者的user_id + //var sender_name = data["sender_name"]?.ToString();//发送者昵称 + //var server_id = data["server_id"]?.ToString();//消息的服务器ID + + var content_type = data["content_type"]?.ToString();//内容类型 78 + var conversation_id = data["conversation_id"]?.ToString();//接收者的的会话ID + var enterpoint = data["enterpoint"]?.ToString();//入口点 - 链接(小程序里面的链接) + var headimg = data["headimg"]?.ToString();//小程序的头像 + var name = data["name"]?.ToString();//小程序的名称 + var receiver = data["receiver"]?.ToString();// 接收者的user_id + var sender = data["sender"]?.ToString();// 发送者的user_id + var sender_name = data["sender_name"]?.ToString();//发送者昵称 + var title = data["title"]?.ToString();//小程序标题 + var wxid = data["wxid"]?.ToString(); + var server_id = data["server_id"]?.ToString();//消息的服务器ID + + var isSend = false; + var RobotUsername = string.Empty; + var RobotUsernick = string.Empty; + var FromUsername = string.Empty; + var FromUsernick = string.Empty; + + //if (content_type != "78")//0自己发送的消息 + //{ + // if (!WechatClient.IsAuxiliaryInput(sender, receiver, enterpoint)) + // { + // Console.WriteLine("此消息被过滤,因为是机器人自己发送的:" + enterpoint); + // return; + // } + + // var ass = WechatClient.IsAssistance(sender, receiver, dwClientid, WechatType.Xiaoxie_QY); + // if (ass.type == WechatClient.AssistanceType.终止) return; + // isSend = ass.type == WechatClient.AssistanceType.辅助; + + // RobotUsername = ass.robotName; + // RobotUsernick = ass.robotNick; + // FromUsername = ass.fromName; + // FromUsernick = ass.fromNick; + //} + //else + //{ + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + RobotUsername = user.Wxid; + RobotUsernick = user.Nickname; + FromUsername = sender; + FromUsernick = sender_name; + //} + var wmsg = new WorkWechatReceiveMsg(); + wmsg.Cmd = PCRobotCMD.rcvTxt_workWeChat; + wmsg.IsSend = isSend; + wmsg.RobotUsername = RobotUsername; + wmsg.RobotUsernick = RobotUsernick; + wmsg.RobotType = RobotType.客户端企业微信; + wmsg.FromMessageType = WechatMsgType.文本; + + if (conversation_id.Contains("R:")) + { + wmsg.FromGroupid = conversation_id; + wmsg.FromUsername = sender; + wmsg.FromUsernick = sender_name; + } + else + { + wmsg.FromUsername = FromUsername; + wmsg.FromUsernick = FromUsernick; + } + wmsg.FromMessage = enterpoint.Replace("pages/index/index.html?goods_id=", "https://mobile.yangkeduo.com/goods.html?goods_id=").Replace("pages/item/detail/detail.html?sku=", @"https://item.jd.com/"); + + socketClient.Send(wmsg); + + } + break; + case MsgType.MT_RECV_OTHER_MSG: + break; + case MsgType.MT_SEARCH_USER_MSG://查询联系人 + break; + case MsgType.MT_ADD_SEARCH_USER_MSG://添加查询的联系人 + break; + case MsgType.MT_MODIFY_USER_REMARK_MSG://修改用户备注 + break; + case MsgType.MT_MODIFY_USER_DESC_MSG: + break; + case MsgType.MT_MODIFY_EXTERNAl_USER_PHONES_MSG: + break; + case MsgType.MT_MODIFY_EXTERNAl_USER_COMPANY_MSG: + break; + case MsgType.MT_CREATE_ROOM_MSG: + { + } + break; + case MsgType.MT_MODIFY_ROOM_NAME_MSG: + break; + case MsgType.MT_ROOM_ADD_MEMBERS_MSG: + { + + } + break; + case MsgType.MT_ROOM_DEL_MEMBERS_MSG://删除群成员 + break; + case MsgType.MT_RECV_FRIEND_REQUEST://接收好友请求 + { + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/0T8yO33zeeg33jJCQibIWobapj6GX4xFBbOECtmG9VdkYpnzyiaUr5iag/0","corp_id":"1970325134026788","nickname":"17","sex":2,"user_id":"7881301610989604","verify":"我17"},"type":11063} + + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/PiajxSqBRaEI8qvnXF9KjgTpvaSAzfhbE2kGoIspb7ibbEHGZEQxRibAQ/0","corp_id":"1970325134026788","nickname":"助将","sex":0,"user_id":"7881303410988876","verify":"欧珀new"},"type":11063} + + //{"data":{"avatar":"http://wx.qlogo.cn/mmhead/zroWGtm5tmsxaCHfI2ibibuBxtzsZc6brAIDCicIianoDYI/0","corp_id":"1970325134026788","nickname":"Boom","sex":1,"user_id":"7881303336175964","verify":"我是Boom"},"type":11063} + + if (data == null) return; + + var socketClient = EasySoc.GetSocket(); + + var avatar = data["avatar"]?.ToString();//头像 + var corp_id = data["corp_id"]?.ToString();//公司id + var nickname = data["nickname"]?.ToString();//申请人昵称 + var sex = data["sex"]?.ToString();//性别 + var user_id = data["user_id"]?.ToString();//用户id + var verify = data["verify"]?.ToString();//申请摘要 + var user = WechatClient.GetUser(dwClientid, WechatType.Xiaoxie_QY); + if (user == null) + return; + var wXApply = new WorkWechatApplyFriend(); + wXApply.Cmd = PCRobotCMD.applyFriend_workWeChat; + wXApply.RobotUsername = user.Wxid; + wXApply.RobotUsernick = user.Nickname; + wXApply.RobotType = RobotType.客户端企业微信; + wXApply.Message = verify; + wXApply.NewFriendWxid = user_id; + wXApply.NewFriendNick = nickname; + wXApply.OldFriendWxid = string.Empty; + wXApply.OldFriendNick = string.Empty; + + wXApply.Token = CsharpHttpHelper.HttpHelper.ObjectToJson(new { user_id = user_id, corp_id = corp_id }); + + //记录申请人,用于记录 + if (!FriendRequestRecord.ContainsKey(user_id)) + FriendRequestRecord.TryAdd(user_id, new FriendInfo() { account = user_id, avatar = avatar, nickname = nickname, sex = int.Parse(sex), wxid = user_id }); + + socketClient.Send(wXApply); + } + break; + case MsgType.MT_ACCEPT_FRIEND_REQUEST://接受加好友请求 + break; + default: + break; + } + } + catch (Exception ex) + { + //Console.WriteLine("解析消息异常:" + ex.Message + "," + recvData); + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".._" + recvData); + } + }); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_."); + } + } + + private static ConcurrentDictionary FriendRequestRecord = new ConcurrentDictionary(); + + private static void WxCloseCallback(uint dwClientId) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == dwClientId && f.Value.Type == WechatType.Xiaoxie_QY).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"WxCloseCallbackQY关闭回调,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_.-"); + } + } + + private static void WxAcceptCallback(uint dwClientId) + { + Console.WriteLine("注入成功:" + dwClientId); + } + + /// + /// 启动微信 + /// + /// + /// + public static uint StartWechat(bool isError = false) + { + InitPc(); + + var WechatWinFile = HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + var md5 = Common.GetMD5Hash(WechatWinFile).ToUpper(); + if (!File.Exists(WechatWinFile) || md5 != PcMd5.ToUpper()) + { + if (isError) throw new Exception("易转发客户端企业微信版本不支持,请登录易转发端手动处理"); + var _rst = MessageBox.Show("您的企业微信版本暂时不支持,立即重新安装吗?", "版本不兼容", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (_rst == DialogResult.Yes) + { + var f = new WechatUpdate(Version); + f.ShowDialog(); + if (!f.IsOk) return 0; + } + else return 0; + } + // 注入并多开 + //return InjectWxWork(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes("")); + + var path = HttpExtend.MapFile("WXWork.exe", $"WXWork\\{Version}"); + LogHelper.GetSingleObj().Debug("注入前", $"DPath = {DllPath},Path = {path}"); + return InjectWxWorkMultiOpen(Encoding.UTF8.GetBytes(DllPath), Encoding.UTF8.GetBytes(path)); + } + + } +} diff --git a/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Override.cs b/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Override.cs new file mode 100644 index 0000000..4abf8c1 --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Override.cs @@ -0,0 +1,742 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using NM_WeChat; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Properties; +using PCRobot.Utils; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; + +namespace PCRobot.PCWechat +{ + + /* + 接口文档:https://www.showdoc.cc/WxWorkNewHook?page_id=3846144660177490 + /////密码:784615627. + */ + + public partial class Wechat_Xiaoxie_QY + { + + public override void AgreeAddMe(string text) + { + try + { + if (string.IsNullOrWhiteSpace(text)) return; + + var reg = Regex.Match(text, @"{""user_id"":""(?[^""]+?)"",""corp_id"":""(?[^""]+?)""}"); + if (reg.Success) + { + var user_id = reg.Groups["user_id"].Value; + var corp_id = reg.Groups["corp_id"].Value; + var __json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_ACCEPT_FRIEND_REQUEST, data = new { user_id = user_id, corp_id = corp_id } }); + SendWxWorkData(User.DwClientId, __json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "-._"); + } + } + + public override void DeleteFriend(string wxid) + { + try + { + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "._"); + } + } + + + + public override void EditCotacts(string wxid, string remark) + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_MODIFY_USER_REMARK_MSG, data = new { user_id = wxid, remark = remark } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "*_"); + } + } + + /// + /// 创建群 + /// + /// + public override void CreateRoom(string wxidData) + { + try + { + if (string.IsNullOrWhiteSpace(wxidData)) return; + var wxids = wxidData.Trim().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + if (wxids != null && wxids.Length != 0) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_CREATE_ROOM_MSG, data = wxids }); + SendWxWorkData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 邀请用户进群 + /// + /// + /// + public override void InviteMemberToRoom_40Up(string conversation_id, string wxidData) + { + try + { + if (conversation_id.Trim().StartsWith("R:")) + { + var wxids = wxidData.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_ROOM_ADD_MEMBERS_MSG, data = new { conversation_id = conversation_id, user_list = wxids } }); + SendWxWorkData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".._."); + } + } + + + public override void InviteMemberToRoom_40Down(string groupid, string wxidData) + { + InviteMemberToRoom_40Up(groupid, wxidData); + } + + public override void DeleteRoomMember(string wxid, string room) + { + try + { + if (room.Trim().StartsWith("R:")) + { + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_ROOM_DEL_MEMBERS_MSG, data = new { conversation_id = room, user_list = new string[] { wxid } } }); + SendWxWorkData(User.DwClientId, json); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + public override void GetContact() + { + try + { + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_EXTERNAL_USERS_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + + Thread.Sleep(1000); + + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOMS_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_*"); + } + } + + public override void GetContact(bool isUpdate) + { + try + { + var result = GetFriendInfos(true); + + var socketClient = EasySoc.GetSocket(); + CommonResult msg = new CommonResult(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvFriendList_workWeChat; + msg.Data = result == null ? string.Empty : HttpHelper.ObjectToJson(result); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message); + } + } + + /// + /// 获取好友列表 + /// + /// 刷新缓存数据 + /// + //public override List GetFriendInfos(bool flushGroupsCache = false) + public override string GetFriendInfos(bool flushGroupsCache = false) + { + List friends = null; + try + { + #region 获取缓存数据 + friends = User.WorkFriends.Where(f => !f.user_id.Contains("R:")).ToList(); + if (!flushGroupsCache && friends.Count != 0) + return JsonConvert.SerializeObject(friends); + #endregion + + if (!User.IsGetFriend) + { + //获取好友列表(数据库读取) + var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_EXTERNAL_USERS_MSG, data = new { } }); + SendWxWorkData(User.DwClientId, json); + User.IsGetFriend = true; + } + + var result_ = Task.Factory.StartNew>(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(20); + do + { + if (!User.IsGetFriend) + { + friends = User.WorkFriends.Where(f => !f.user_id.Contains("R:")).ToList(); + return friends; + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + //return friends; + return JsonConvert.SerializeObject(friends); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "#__#"); + } + return string.Empty; + } + + + public override void GetGroupAndFriendInfo(string groupId, string wxid) + { + try + { + var json = string.Empty; + WorkGroupInfo group = null; + if (groupId.Contains("R:")) + { + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOM_MEMBERS_MSG, data = new { conversation_id = groupId } }); + + var g = User.WorkGroups.FirstOrDefault(f => f.conversation_id == groupId); + //User.WorkGroups.Clear(); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) + group = new WorkGroupInfo() { conversation_id = groupId, friends = new List() { u }, total = g.total }; + } + + if (group == null) + { + SendWxWorkData(User.DwClientId, json); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + g = User.WorkGroups.FirstOrDefault(f => f.conversation_id == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) + { + group = new WorkGroupInfo() { conversation_id = groupId, friends = new List() { u }, total = g.total }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信;//客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "/_"); + } + } + + public override void GetGroupAndFriendInfo(string groupId, string wxid, bool flush = false) + { + try + { + var json = string.Empty; + WorkGroupInfo group = null; + if (groupId.Contains("R:")) + { + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOM_MEMBERS_MSG, data = new { conversation_id = groupId } }); + + var g = User.WorkGroups.FirstOrDefault(f => f.conversation_id == groupId); + //User.WorkGroups.Clear(); + if (g != null) + { + if (flush) + { + g.friends.Clear(); + } + else + { + var u = g.friends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) + group = new WorkGroupInfo() { conversation_id = groupId, friends = new List() { u }, total = g.total }; + } + } + + if (group == null) + { + SendWxWorkData(User.DwClientId, json); + var _group = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + g = User.WorkGroups.FirstOrDefault(f => f.conversation_id == groupId); + if (g != null) + { + var u = g.friends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) + { + group = new WorkGroupInfo() { conversation_id = groupId, friends = new List() { u }, total = g.total }; + return group; + } + } + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信;//客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = group == null ? string.Empty : HttpHelper.ObjectToJson(group); + + socketClient.Send(msg); + + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "/_"); + } + } + + + public override void GetWxidInfo(string wxid) + { + try + { + var json = string.Empty; + + var u = User.WorkFriends.FirstOrDefault(f => f.user_id == wxid); + if (u == null) + { + if (wxid.Contains("R:")) + { + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_ROOMS_MSG, data = new { } }); + } + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_GET_USER_DETAIL_MSG, data = new { user_id = wxid } }); + + SendWxWorkData(User.DwClientId, json); + var friend = Task.Factory.StartNew(delegate () + { + DateTime end_time = DateTime.Now.AddSeconds(15); + do + { + u = User.WorkFriends.FirstOrDefault(f => f.user_id == wxid); + if (u != null) return u; + Thread.Sleep(200); + } while (end_time > DateTime.Now); + return null; + }).Result; + } + + var socketClient = EasySoc.GetSocket(); + var msg = new WorkWechatContact(); + msg.RobotUsername = User.Wxid; + msg.RobotUsernick = User.Nickname; + msg.RobotType = RobotType.客户端企业微信;//客户端微信; + msg.MsgId = ServerMsgID; + msg.Cmd = PCRobotCMD.rcvContact_workWeChat; + msg.Message = u == null ? string.Empty : HttpHelper.ObjectToJson(u); + + socketClient.Send(msg); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_/"); + } + } + + public override void SendImage(string wxid, string file) + { + //try + //{ + // var conversation_id = wxid; + // if (!wxid.StartsWith("R:")) + // { + // conversation_id = $"S:{User.Wxid}_{wxid}"; + // } + // var json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = conversation_id, file = file } }); + // SendWxWorkData(User.DwClientId, json); + //} + //catch (Exception ex) + //{ + // LogHelper.GetSingleObj().Error(new StackTrace().GetFrame(0).GetMethod().Name, ex.Message + ".-"); + //} + + try + { + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + conversation_id = $"S:{User.Wxid}_{wxid}"; + + if (file.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + byte[] ImangByte = null; + string extension = Path.GetExtension(file); + extension = string.IsNullOrWhiteSpace(extension) ? ".jpg" : extension; + ImangByte = new System.Net.WebClient().DownloadData(file); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + + var path = Common.CacheFilePath(User.Wxid, conversation_id, "IMAGE", Guid.NewGuid().ToString("N"), extension); + if (!File.Exists(path)) + { + File.WriteAllBytes(path, ImangByte); + } + if (File.Exists(path)) + file = path; + } + else + { + if (!File.Exists(file)) + { + if (Common.IsBase64(file)) + { + var path = Common.CacheFilePath(User.Wxid, wxid, "IMAGE", Guid.NewGuid().ToString("N"), "jpg"); + if (Common.Base64ToFileAndSave(file, path) && File.Exists(path)) + { + file = path; + } + } + else + { } + } + } + + var json = string.Empty; + if (File.Exists(file)) + { + if (file.Trim().EndsWith(".gif", StringComparison.CurrentCultureIgnoreCase)) + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_GIF_MSG, data = new { conversation_id = conversation_id, file = file } }); + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = conversation_id, file = file } }); + } + else + json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_IMAGE_MSG, data = new { conversation_id = conversation_id, file = file } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Debug("发送图片异常", ex.Message + ".-" + ex.StackTrace); + } + } + + public override void SendMessage(string wxid, string message) + { + try + { + //S:1688853956558440_7881301364988874 + //{"data":{"content":"我们","content_type":2,"conversation_id":"S:1688853956558440_7881301364988874","local_id":"61","receiver":"1688853956558440","send_time":"1584028171","sender":"7881301364988874","sender_name":"18","server_id":"1000653"},"type":11041} + + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{wxid}"; + } + else + { } + + var json = string.Empty; + message = message.Replace("\r\n", "\n"); + if (Common.isXML(message)) + { + message = message.Replace("&", "&"); + var title = string.Empty; + var desc = string.Empty; + var url = string.Empty; + var image_url = string.Empty; + var reg = Regex.Match(message, @"(?<标题>[\w\W]+?)"); + if (reg.Success) title = reg.Groups["标题"].Value; + reg = Regex.Match(message, @"(?<介绍>[\w\W]+?)"); + if (reg.Success) desc = reg.Groups["介绍"].Value.Replace("(?<链接>[\w\W]+?)"); + if (!reg.Success) reg = Regex.Match(message, @"(?<链接>[\w\W]+?)"); + if (reg.Success) url = reg.Groups["链接"].Value; + reg = Regex.Match(message, @"(?<图片链接>[\w\W]+?)"); + if (reg.Success) image_url = reg.Groups["图片链接"].Value; + if (message.Contains("")) + { + var image_key1 = string.Empty; + var image_key2 = string.Empty; + var image_key3 = string.Empty; + var image_size = 0; + var ghid = string.Empty; + var pagepath = string.Empty; + var regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key1 = regKey.Groups["image_key1"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key2 = regKey.Groups["image_key2"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_key3 = regKey.Groups["image_key3"].Value; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + image_size = int.Parse(regKey.Groups["image_size"].Value.XMLReplace(false)); + + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + ghid = regKey.Groups["username"].Value; + + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + pagepath = regKey.Groups["pagepath"].Value; + + var weapppagethumbrawurl = string.Empty; + regKey = Regex.Match(message, @"(?[\w\W]+?)", RegexOptions.IgnoreCase); + if (regKey.Success) + weapppagethumbrawurl = regKey.Groups["weapppagethumbrawurl"].Value; + + var _json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_MINI_PROGRAM_MSG, data = new { conversation_id = conversation_id, ghid = ghid.XMLReplace(false), wxid = conversation_id, name = title, title = desc, enterpoint = pagepath.XMLReplace(false), headimg = weapppagethumbrawurl.XMLReplace(false), image_key1 = image_key1.XMLReplace(false), image_key2 = image_key2.XMLReplace(false), image_key3 = image_key3.XMLReplace(false), image_size = image_size } }); + + SendWxWorkData(User.DwClientId, _json); + return; + } + else + { + image_url = + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_LINK_MSG, data = new { conversation_id = conversation_id, title = $"{title.XMLReplace(false)}", desc = $"{desc.XMLReplace(false)}", url = url.XMLReplace(false), image_url = image_url.XMLReplace(false) } }); + } + } + else + { + var atUsername = new List(); + var regs = Regex.Matches(message, @"\[@([^\]]+?)\]"); + if (regs.Count != 0 && wxid.StartsWith("R:")) + { + foreach (Match item in regs) + { + atUsername.Add(item.Groups[1].Value.Trim()); + } + message = Regex.Replace(message, @"(\[@[^\]]+?\])", "{$@}"); + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_ROOM_AT_MSG, data = new { conversation_id = conversation_id, content = message, at_list = atUsername.ToArray() } }); + } + else + json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_TEXT_MSG, data = new { conversation_id = conversation_id, content = message } }); + } + SendWxWorkData(User.DwClientId, json); + + //LogHelper.GetSingleObj().Debug("发送状态", ($"发送:{conversation_id} - {flag}, 内容:{message}")); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "-."); + } + } + + /// + /// 发送小程序 + /// + /// 发送给谁 + /// 发送的内容json打包 + public override void SendProgramMessage(string wxid, string dataJson) + { + try + { + /* + "conversation_id": "S:16888xxxx_7881xxxxx", + "ghid": "gh_52b46203a658@app", + "wxid": "wx35f2a3937c9df889", + "name": "博鸟绘本", + "title": "博鸟绘本,最新最全的儿童绘本租赁平台~", + "enterpoint": "pages/shouye/shouye.html", + "headimg": "http://wx.qlogo.cn/mmhead/xxxx/96", + "image_key1": "306b020102046430620201000xxxxx", + "image_key2": "61706264616C7A77666875xxxx", + "image_key3": "b302e94d9c6f95xxxxxx", + "image_size": 56448 + */ + + //个人微信/企业微信 + //{"data":{"content_type":78,"conversation_id":"R:10696053211018728","enterpoint":"pages/tab/home/index.html?_um_ssrc=oucfI5QRI-8SbyOTKSGYt5-ia0dk&_um_sts=1610033684099","ghid":"gh_a0d7a7672cf7@app","headimg":"http://wx.qlogo.cn/mmhead/Q3auHgzwzM43LsxpXHKd7ua7kwMZQ8WHmZlkYTzr3Tdm8sMOJ7Ypog/96","image_key1":"306b020102046430620201000204bafc490e02030f4df9020473e6607102045ff72a530436333133373039353935305f313734393433343231315f3262393764653133616335373232353633383831336564376334396563616164020100020300ab1004000201010201000400","image_key2":"61747072666A766977766D69726D6168","image_key3":"2b97de13ac57225638813ed7c49ecaad","image_size":43791,"is_pc":0,"local_id":"155","name":"啄木鸟家庭维修","receiver":"1688853956558440","send_time":"1610033747","sender":"7881302484994318","sender_name":"、","server_id":"1042188","title":"直营一口价,维修无猫腻","wxid":"wx3d6b1af0cb07fa5a"},"type":11066} + + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + conversation_id = $"S:{User.Wxid}_{wxid}"; + + var json = CsharpHttpHelper.HttpExtend.JsonToDictionary(dataJson); + var data = json.ContainsKey("data") ? json["data"] as Dictionary : null; + if (data == null) return; + + //var content_type = data["content_type"]?.ToString();//内容类型 78 + //var conversation_id = data["conversation_id"]?.ToString();//接收者的的会话ID + //var receiver = data["receiver"]?.ToString();//接收者的user_id + //var sender = data["sender"]?.ToString();//发送者的user_id + //var sender_name = data["sender_name"]?.ToString();//发送者昵称 + //var server_id = data["server_id"]?.ToString();//消息的服务器ID + var enterpoint = data["enterpoint"]?.ToString();//入口点 - 链接(小程序里面的链接) + var headimg = data["headimg"]?.ToString();//小程序的头像 + var name = data["name"]?.ToString();//小程序的名称 + var title = data["title"]?.ToString();//小程序标题 + var _wxid = data["wxid"]?.ToString(); + var image_size = int.Parse(data["image_size"].ToString()); + var image_key1 = data["image_key1"]?.ToString(); + var image_key2 = data["image_key2"]?.ToString(); + var image_key3 = data["image_key3"]?.ToString(); + var ghid = data["ghid"]?.ToString(); + + var _json = HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_MINI_PROGRAM_MSG, data = new { conversation_id = conversation_id, ghid = ghid, wxid = _wxid, name = name, title = title, enterpoint = enterpoint, headimg = headimg, image_key1 = image_key1, image_key2 = image_key2, image_key3 = image_key3, image_size = image_size } }); + + SendWxWorkData(User.DwClientId, _json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("发送小程序异常", ex.Message + ex.StackTrace); + } + } + + public override void SendVideo(string wxid, string file) + { + try + { + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{wxid}"; + } + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_VIDEO_MSG, data = new { conversation_id = conversation_id, file = file } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "-_"); + } + } + + public override void SendFile(string wxid, string file) + { + try + { + var conversation_id = wxid; + if (!wxid.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{wxid}"; + } + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_FILE_MSG, data = new { conversation_id = conversation_id, file = file } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "_-"); + } + } + + public override void SendCard(string to_wxid, string card_wxid) + { + try + { + var conversation_id = to_wxid; + if (!to_wxid.StartsWith("R:")) + { + conversation_id = $"S:{User.Wxid}_{to_wxid}"; + } + + if (card_wxid.StartsWith("R:")) + { + InviteMemberToRoom_40Up(card_wxid, to_wxid); + return; + } + + var json = CsharpHttpHelper.HttpHelper.ObjectToJson(new { type = MsgType.MT_SEND_PERSON_CARD_MSG, data = new { conversation_id = conversation_id, user_id = card_wxid } }); + SendWxWorkData(User.DwClientId, json); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "--"); + } + } + + public override void CloseWechat(string message) + { + try + { + var v = WechatClient.Users.FirstOrDefault(f => f.Value.DwClientId == User.DwClientId && f.Value.Type == WechatType.Xiaoxie_QY).Value; + if (v != null) + { + LogHelper.GetSingleObj().Info("系统", $"CloseWechatQY事件退出,Uin:{v.Uin},微信:{v.Nickname}({v.Wxid})"); + WechatClient.RemoveUser(v, true); + if (!string.IsNullOrWhiteSpace(message)) + PCRobotForm.ErrorMessAction?.Invoke(message); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error(new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Name, ex.Message + "//"); + } + } + + + } +} diff --git a/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Type.cs b/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Type.cs new file mode 100644 index 0000000..7f67e3d --- /dev/null +++ b/PCRobot/PCWechat/Wechat_Xiaoxie_QY_Type.cs @@ -0,0 +1,571 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using NM_WeChat; +using PCRobot.Entitys; +using PCRobot.Pack; +using PCRobot.Properties; +using PCRobot.Utils; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using System.Windows.Forms; + +namespace PCRobot.PCWechat +{ + + /* + 接口文档:https://www.showdoc.cc/WxWorkNewHook?page_id=3846144660177490 + /////密码:784615627. + */ + + public partial class Wechat_Xiaoxie_QY + { + #region 内部类 + + public enum MsgType + {/// + /// 接口准备完毕 + /// + MT_APP_READY_MSG = 11024, + /// + /// 参数错误提示 + /// + MT_PARAMS_ERROR_MSG = 11025, + /// + /// 登录消息 + /// + MT_USER_LOGIN = 11026, + /// + /// 注销消息通知 + /// + MT_USER_LOGOUT = 11027, + /// + /// 登录二维码 + /// + MT_LOGIN_QRCODE_MSG = 11028, + /// + /// 发送文本消息 + /// + MT_SEND_TEXT_MSG = 11029, + /// + /// 发送图片消息 + /// + MT_SEND_IMAGE_MSG = 11030, + /// + /// 发送文件消息 + /// + MT_SEND_FILE_MSG = 11031, + /// + /// 发送目录消息 + /// + MT_SEND_FOLDER_MSG = 11032, + ///// + ///// 发送链接消息 + ///// + //MT_SEND_LINK_MSG = 11033, + ///// + ///// 发送个人名片 + ///// + //MT_SEND_PERSON_CARD_MSG = 11034, + /// + /// 获取自己信息 + /// + MT_GET_OWNER_INFO_MSG = 11035, + /// + /// 获取内部联系人列表 + /// + MT_GET_INNER_USERS_MSG = 11036, + /// + /// 获取外部联系列表 + /// + MT_GET_EXTERNAL_USERS_MSG = 11037, + /// + /// 获取群聊列表 + /// + MT_GET_ROOMS_MSG = 11038, + /// + /// 获取用户详细信息 + /// + MT_GET_USER_DETAIL_MSG = 11039, + /// + /// 获取群成员列表 + /// + MT_GET_ROOM_MEMBERS_MSG = 11040, + /// + /// 接收文本消息 + /// + MT_RECV_TEXT_MSG = 11041, + /// + /// 接收图片消息 + /// + MT_RECV_IMG_MSG = 11042, + /// + /// 接收视频消息 + /// + MT_RECV_VIDEO_MSG = 11043, + /// + /// 接收语音消息 + /// + MT_RECV_VOICE_MSG = 11044, + /// + /// 接收文件消息 + /// + MT_RECV_FILE_MSG = 11045, + /// + /// 接收位置消息 + /// + MT_RECV_LOCATION_MSG = 11046, + /// + /// 接收链接消息 + /// + MT_RECV_LINK_CARD_MSG = 11047, + /// + /// 接收表情消息 + /// + MT_RECV_EMOTION_MSG = 11048, + /// + /// 接收红包消息 + /// + MT_RECV_RED_PACKET_MSG = 11049, + /// + /// 接收个人名片消息 + /// + MT_RECV_PERSON_CARD_MSG = 11050, + /// + /// 接收其他未解析消息 + /// + MT_RECV_OTHER_MSG = 11051, + /// + /// 查询联系人 + /// + MT_SEARCH_USER_MSG = 11052, + /// + /// 添加查询的联系人 + /// + MT_ADD_SEARCH_USER_MSG = 11053, + /// + /// 修改用户备注 + /// + MT_MODIFY_USER_REMARK_MSG = 11054, + /// + /// 修改用户描述 + /// + MT_MODIFY_USER_DESC_MSG = 11055, + /// + /// 修改外部联系人手机号 + /// + MT_MODIFY_EXTERNAl_USER_PHONES_MSG = 11056, + /// + /// 修改外部联系人公司 + /// + MT_MODIFY_EXTERNAl_USER_COMPANY_MSG = 11057, + /// + /// 创建群聊 + /// + MT_CREATE_ROOM_MSG = 11058, + /// + /// 修改群名 + /// + MT_MODIFY_ROOM_NAME_MSG = 11059, + /// + /// 添加群成员 + /// + MT_ROOM_ADD_MEMBERS_MSG = 11060, + /// + /// 删除群成员 + /// + MT_ROOM_DEL_MEMBERS_MSG = 11061, + /// + /// 接收好友请求 + /// + MT_RECV_FRIEND_REQUEST = 11063, + /// + /// 接受加好友请求 + /// + MT_ACCEPT_FRIEND_REQUEST = 11064, + ///// + ///// 发送小程序 + ///// + //MT_SEND_MINI_PROGRAM_MSG = 11065, + /// + /// 接收到小程序 + /// + MT_RECV_MINIAPP_MSG = 11066, + /// + /// 发送视频 + /// + MT_SEND_VIDEO_MSG = 11067, + /// + /// 接收图文消息 + /// + MT_RECV_IMAGE_TEXT_MSG = 11068, + /// + /// 发送群@消息 + /// + MT_SEND_ROOM_AT_MSG = 11069, + /// + /// 发送动图(gif)消息 + /// + MT_SEND_GIF_MSG = 11070, + /// + /// 添加群成员为联系人 + /// + MT_ADD_ROOM_USER_MSG = 11071, + /// + /// 群成员新增通知 + /// + MT_ROOM_ADD_MEMBER_NOTIFY_MSG = 11072, + /// + /// 剔除群成员通知 + /// + MT_ROOM_DEL_MEMBER_NOTIFY_MSG = 11073, + /// + /// 新群通知 + /// + MT_ROOM_CREATE_NOTIFY_MSG = 11074, + /// + /// 群成员主动退出通知 + /// + MT_ROOM_MEMBER_QUIT_NOTIFY_MSG = 11075, + /// + /// 好友新增通知 + /// + MT_CONTACT_ADD_NOITFY_MSG = 11076, + /// + /// 好友删除通知 + /// + MT_DEL_FRIEND_MSG = 11077, + /// + /// 被删除通知 + /// + MT_DEL_FRIEND_BY_MSG = 11173, + /// + /// 群昵称修改通知 + /// + MT_ROOM_MODIFY_NICK_MSG = 11078, + /// + /// 修改群公告 + /// + MT_MOD_ROOM_NOTICE_MSG = 11082, + /// + /// 添加查询的企业联系人 + /// + MT_ADD_SEARCH_E_USER_MSG = 11088, + /// + /// 转让群主 + /// + MT_TRANS_ROOM_MSG = 11090, + /// + /// 登录成功通知(包含公司名) + /// + MT_USER_LOGIN_CORP = 11179, + /// + /// 发送视频号 + /// + MT_SEND_VIDEOHAO_MSG = 11172, + /// + /// 发送链接消息 + /// + MT_SEND_LINK_MSG = 11159, + /// + /// 发送个人名片 + /// + MT_SEND_PERSON_CARD_MSG = 11161, + /// + /// 创建空外部群 + /// + MT_CREATE_NULL_ROOM_MSG = 11125, + /// + /// 开启关闭配置邀请群确定 + /// + MT_DISABLE_INVITEROOMCONFIRM_MSG = 11108, + /// + /// 开启关闭配置修改群名 + /// + MT_DISABLE_MODROOMNICK_MSG = 11089, + /// + /// 退出群聊 + /// + MT_QUIT_ROOM = 11105, + /// + /// 删除联系人 + /// + MT_DEL_FRIEND = 11111, + /// + /// 获取自己的二维码 + /// + MT_GET_OWN_QRIMAGE = 11122, + /// + /// 接收撤回消息 + /// + MT_RECV_REVOKE_MSG = 11123, + /// + /// 退出登录 + /// + MT_QUIT_LOGIN_MSG = 11112, + /// + /// 解散群 + /// + MT_DISSOLVE_ROOM = 11130, + /// + /// 添加删除的联系人 + /// + MT_ADD_DELFRIEND_MSG = 11152, + /// + /// 刷新扫码登录二维码 + /// + MT_FLUSH_LOGINQRIMAGE_MSG = 11153, + /// + /// 添加卡片用户 + /// + MT_ADD_CARDFRIEND_MSG = 11121, + /// + /// 发送小程序 + /// + MT_SEND_MINI_PROGRAM_MSG = 11162, + /// + /// C2cCdn下载消息 + /// + MT_C2CCDN_DOWN_MSG = 11170, + /// + /// Cdn下载消息 + /// + MT_CDN_DOWN_MSG = 11171, + /// + /// 登录二维码状态通知 + /// + MT_SCAN_QRSTATE_MSG = 11174, + /// + /// 上传文件获取文件Cdn + /// + MT_GETCDN_UPLOADFILE = 11115, + } + + //public enum MsgType : ushort + //{ + // /// + // /// 接口准备完毕 + // /// + // MT_APP_READY_MSG = 11024, + // /// + // /// 参数错误提示 + // /// + // MT_PARAMS_ERROR_MSG = 11025, + // /// + // /// 登录消息 + // /// + // MT_USER_LOGIN = 11026, + // /// + // /// 注销消息 + // /// + // MT_USER_LOGOUT = 11027, + // /// + // /// 登录二维码 + // /// + // MT_LOGIN_QRCODE_MSG = 11028, + // /// + // /// 发送文本消息 + // /// + // MT_SEND_TEXT_MSG = 11029, + // /// + // /// 发送图片消息 + // /// + // MT_SEND_IMAGE_MSG = 11030, + // /// + // /// 发送文件消息 + // /// + // MT_SEND_FILE_MSG = 11031, + // /// + // /// 发送目录消息 + // /// + // MT_SEND_FOLDER_MSG = 11032, + // /// + // /// 发送链接消息 + // /// + // MT_SEND_LINK_MSG = 11033, + // /// + // /// 发送个人名片 + // /// + // MT_SEND_PERSON_CARD_MSG = 11034, + // /// + // /// 获取自己信息 + // /// + // MT_GET_OWNER_INFO_MSG = 11035, + // /// + // /// 获取内部联系人列表 + // /// + // MT_GET_INNER_USERS_MSG = 11036, + // /// + // /// 获取外部联系列表 + // /// + // MT_GET_EXTERNAL_USERS_MSG = 11037, + // /// + // /// 获取群聊列表 + // /// + // MT_GET_ROOMS_MSG = 11038, + // /// + // /// 获取用户详细信息 + // /// + // MT_GET_USER_DETAIL_MSG = 11039, + // /// + // /// 获取群成员列表 + // /// + // MT_GET_ROOM_MEMBERS_MSG = 11040, + // /// + // /// 接收文本消息 + // /// + // MT_RECV_TEXT_MSG = 11041, + // /// + // /// 接收图片消息 + // /// + // MT_RECV_IMG_MSG = 11042, + // /// + // /// 接收视频消息 + // /// + // MT_RECV_VIDEO_MSG = 11043, + // /// + // /// 接收语音消息 + // /// + // MT_RECV_VOICE_MSG = 11044, + // /// + // /// 接收文件消息 + // /// + // MT_RECV_FILE_MSG = 11045, + // /// + // /// 接收位置消息 + // /// + // MT_RECV_LOCATION_MSG = 11046, + // /// + // /// 接收链接消息 + // /// + // MT_RECV_LINK_CARD_MSG = 11047, + // /// + // /// 接收表情消息 + // /// + // MT_RECV_EMOTION_MSG = 11048, + // /// + // /// 接收红包消息 + // /// + // MT_RECV_RED_PACKET_MSG = 11049, + // /// + // /// 接收个人名片消息 + // /// + // MT_RECV_PERSON_CARD_MSG = 11050, + // /// + // /// 接收其他未解析消息 + // /// + // MT_RECV_OTHER_MSG = 11051, + // /// + // /// 查询联系人 + // /// + // MT_SEARCH_USER_MSG = 11052, + // /// + // /// 添加查询的联系人 + // /// + // MT_ADD_SEARCH_USER_MSG = 11053, + // /// + // /// 修改用户备注 + // /// + // MT_MODIFY_USER_REMARK_MSG = 11054, + // /// + // /// 修改用户描述 + // /// + // MT_MODIFY_USER_DESC_MSG = 11055, + // /// + // /// 修改外部联系人手机号 + // /// + // MT_MODIFY_EXTERNAl_USER_PHONES_MSG = 11056, + // /// + // /// 修改外部联系人公司 + // /// + // MT_MODIFY_EXTERNAl_USER_COMPANY_MSG = 11057, + // /// + // /// 创建群聊 + // /// + // MT_CREATE_ROOM_MSG = 11058, + // /// + // /// 修改群名 + // /// + // MT_MODIFY_ROOM_NAME_MSG = 11059, + // /// + // /// 添加群成员 + // /// + // MT_ROOM_ADD_MEMBERS_MSG = 11060, + // /// + // /// 删除群成员 + // /// + // MT_ROOM_DEL_MEMBERS_MSG = 11061, + // /// + // /// 接收好友请求 + // /// + // MT_RECV_FRIEND_REQUEST = 11063, + // /// + // /// 接受加好友请求 + // /// + // MT_ACCEPT_FRIEND_REQUEST = 11064, + // /// + // /// 发送小程序 + // /// + // MT_SEND_MINI_PROGRAM_MSG = 11065, + // /// + // /// 接收到小程序 + // /// + // MT_RECV_MINIAPP_MSG = 11066, + // /// + // /// 发送视频 + // /// + // MT_SEND_VIDEO_MSG = 11067, + // /// + // /// 接收图文消息 + // /// + // MT_RECV_IMAGE_TEXT_MSG = 11068, + // /// + // /// 发送群@消息 + // /// + // MT_SEND_ROOM_AT_MSG = 11069, + // /// + // /// 发送动图(gif)消息 + // /// + // MT_SEND_GIF_MSG = 11070, + // /// + // /// 添加群成员为联系人 + // /// + // MT_ADD_ROOM_USER_MSG = 11071, + // /// + // /// 群成员新增通知 + // /// + // MT_ROOM_ADD_MEMBER_NOTIFY_MSG = 11072, + // /// + // /// 剔除群成员通知 + // /// + // MT_ROOM_DEL_MEMBER_NOTIFY_MSG = 11073, + // /// + // /// 新群通知 + // /// + // MT_ROOM_CREATE_NOTIFY_MSG = 11074, + // /// + // /// 群成员主动退出通知 + // /// + // MT_ROOM_MEMBER_QUIT_NOTIFY_MSG = 11075, + // /// + // /// 好友新增通知 + // /// + // MT_CONTACT_ADD_NOITFY_MSG = 11076, + //} + #endregion + + } +} diff --git a/PCRobot/Program.cs b/PCRobot/Program.cs new file mode 100644 index 0000000..3ffaf45 --- /dev/null +++ b/PCRobot/Program.cs @@ -0,0 +1,218 @@ +using CsharpHttpHelper; +using PCRobot.Properties; +using PCRobot.Utils; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using System.Windows.Forms; +using System.Xml; + +namespace PCRobot +{ + static class Program + { + static void WriteResource() + { + //Util.WriteResource(HttpExtend.MapFile("WeChatHelper_3.3.0.93.dll", "Bin"), HttpExtend.MapFile("WeChatHelper_3.3.0.93.dll", @"TempFile")); + Util.WriteResource(HttpExtend.MapFile("WeChatHelper_3.4.0.38.dll", "Bin"), HttpExtend.MapFile("WeChatHelper_3.4.0.38.dll", @"TempFile"), "3.4.0.38"); + Util.WriteResource(HttpExtend.MapFile("WeChatServer.dll", "Bin"), HttpExtend.MapFile("WeChatServer.dll", @"TempFile"), "3.4.0.38"); + + //Util.WriteResource(HttpExtend.MapFile("NanMuCore_3.2.1.154.dll", "Bin"),HttpExtend.MapFile("NanMuCore_3.2.1.154.dll", @"TempFile")); + //Util.WriteResource(HttpExtend.MapFile("NanMuCore_3.3.5.50.dll", "Bin"), HttpExtend.MapFile("NanMuCore_3.3.5.50.dll", @"TempFile")); + Util.WriteResource(HttpExtend.MapFile("WxWorkHelper_4.0.2.6026.dll", "Bin"), HttpExtend.MapFile("WxWorkHelper_4.0.2.6026.dll", @"TempFile"), "3.1.10.3010", true); + Util.WriteResource(HttpExtend.MapFile("WxWorkLoader.dll", "Bin"), HttpExtend.MapFile("WxWorkLoader.dll", @"TempFile"), "3.1.10.3010", true); + //Util.WriteResource(HttpExtend.MapFile("WxWorkHelper_3.1.10.3010.dll", "Bin"), HttpExtend.MapFile("WxWorkHelper_3.1.10.3010.dll", @"TempFile"), "3.1.10.3010"); + //Util.WriteResource(HttpExtend.MapFile("WxWorkHelper_3.0.27.2701.dll", "Bin"), HttpExtend.MapFile("WxWorkHelper_3.0.27.2701.dll", @"TempFile")); + } + + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + try + { + string strFullPath = Application.ExecutablePath; + string strFileName = Path.GetFileName(strFullPath); + string curPath = HttpExtend.MapFile(strFileName).ToLower(); + int count = 0; + foreach (Process p in Process.GetProcessesByName(strFileName.Replace(".exe", ""))) + { + string path = p.MainModule.FileName.ToLower(); + if (path == curPath) count++; + } + + if (count > 1) + { + MessageBox.Show("抱歉,本程序禁止多开!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);//弹出提示信息 + return; + } + + try + { + WriteResource(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "请关闭微信后重试", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + //new LevelUpdate.UpdateForm().ShowDialog(); + + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.Automatic); + Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); + AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + SetAllowUnsafeHeaderParsing20(true); + + try + { + var LastData = UpdateClient.GetCloudFileHist(); + if (!string.IsNullOrWhiteSpace(LastData)) + { + if (new UpdateForm(LastData).ShowDialog() == DialogResult.OK) + { + Process.Start("检查更新.exe", "易转发.exe"); + return; + } + } + } + catch (Exception ex) + { } + Application.Run(new PCRobotForm()); + + } + catch (Exception ex) + { + MessageBox.Show(ex.Message + "#-#" + ex.StackTrace); + } + } + + #region 系统异常捕获 + static bool SetAllowUnsafeHeaderParsing20(bool useUnsafe) + { + try + { + //Get the assembly that contains the internal class + System.Reflection.Assembly aNetAssembly = System.Reflection.Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection)); + if (aNetAssembly != null) + { + //Use the assembly in order to get the internal type for the internal class + Type aSettingsType = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal"); + if (aSettingsType != null) + { + //Use the internal static property to get an instance of the internal settings class. + //If the static instance isn't created allready the property will create it for us. + object anInstance = aSettingsType.InvokeMember("Section", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.NonPublic, null, null, new object[] { }); + + if (anInstance != null) + { + //Locate the private bool field that tells the framework is unsafe header parsing should be allowed or not + System.Reflection.FieldInfo aUseUnsafeHeaderParsing = aSettingsType.GetField("useUnsafeHeaderParsing", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + if (aUseUnsafeHeaderParsing != null) + { + aUseUnsafeHeaderParsing.SetValue(anInstance, useUnsafe); + return true; + } + } + } + } + return false; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("系统异常捕获", $"系统异常捕获:{ex.Message} - {ex.StackTrace}"); + MessageBox.Show(ex.Message + " - " + ex.StackTrace); + } + return false; + } + static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) + { + try + { + string str = GetExceptionMsg(e.Exception, e.ToString()); + //MessageBox.Show(str, "子线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + throw new Exception(str); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("子线程错误", $"子线程错误:{ex.Message} - {ex.StackTrace}"); + MessageBox.Show(ex.Message, "子线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + try + { + string str = GetExceptionMsg(e.ExceptionObject as Exception, e.ToString()); + // MessageBox.Show(str, "主线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + throw new Exception(str); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("主线程错误", $"主线程错误:{ex.Message} - {ex.StackTrace}"); + MessageBox.Show(ex.Message, "主线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + static string GetExceptionMsg(Exception ex, string backStr) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("****************************异常文本****************************"); + sb.AppendLine("【出现时间】:" + DateTime.Now.ToString()); + if (ex != null) + { + sb.AppendLine("【异常类型】:" + ex.GetType().Name); + sb.AppendLine("【异常信息】:" + ex.Message); + sb.AppendLine("【堆栈调用】:" + ex.StackTrace); + } + else + { + sb.AppendLine("【未处理异常】:" + backStr); + } + sb.AppendLine("***************************************************************"); + return sb.ToString(); + } + + /// + /// 退出 + /// + public static void Exit(bool start = false) + { + try + { + if (start) + { + //程序位置 + string strAppFileName = Process.GetCurrentProcess().MainModule.FileName; + Process myNewProcess = new Process(); + //要启动的应用程序 + myNewProcess.StartInfo.FileName = strAppFileName; + // 设置要启动的进程的初始目录 + myNewProcess.StartInfo.WorkingDirectory = Application.ExecutablePath; + //启动程序 + myNewProcess.Start(); + } + //结束该程序 + // Application.Exit(); + //结束该所有线程 + //Environment.Exit(0); + + LogHelper.GetSingleObj().Info("调用Exit退出", $"调用Exit退出程序"); + Thread.Sleep(1000); + Process.GetCurrentProcess().Kill(); + } + catch (Exception) + { } + } + + #endregion + } +} diff --git a/PCRobot/Properties/AssemblyInfo.cs b/PCRobot/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c2c34f8 --- /dev/null +++ b/PCRobot/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("PCRobot")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PCRobot")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("676d6ef4-fd4e-48e2-8aae-14ac4b2f4b1d")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PCRobot/Properties/Resources.Designer.cs b/PCRobot/Properties/Resources.Designer.cs new file mode 100644 index 0000000..c024079 --- /dev/null +++ b/PCRobot/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace PCRobot.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PCRobot.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 未登录 { + get { + object obj = ResourceManager.GetObject("未登录", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/PCRobot/Properties/Resources.resx b/PCRobot/Properties/Resources.resx new file mode 100644 index 0000000..51ef9da --- /dev/null +++ b/PCRobot/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\未登录.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/PCRobot/Properties/Settings.Designer.cs b/PCRobot/Properties/Settings.Designer.cs new file mode 100644 index 0000000..593a4c6 --- /dev/null +++ b/PCRobot/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace PCRobot.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/PCRobot/Properties/Settings.settings b/PCRobot/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/PCRobot/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/PCRobot/Resources/Fix.dll b/PCRobot/Resources/Fix.dll new file mode 100644 index 0000000..558a53e Binary files /dev/null and b/PCRobot/Resources/Fix.dll differ diff --git a/PCRobot/Resources/Fix2_QY.dll b/PCRobot/Resources/Fix2_QY.dll new file mode 100644 index 0000000..b644cdd Binary files /dev/null and b/PCRobot/Resources/Fix2_QY.dll differ diff --git a/PCRobot/Resources/Fix_32.dll b/PCRobot/Resources/Fix_32.dll new file mode 100644 index 0000000..558a53e Binary files /dev/null and b/PCRobot/Resources/Fix_32.dll differ diff --git a/PCRobot/Resources/NanMuCore_3.2.1.154.dll b/PCRobot/Resources/NanMuCore_3.2.1.154.dll new file mode 100644 index 0000000..c480b88 Binary files /dev/null and b/PCRobot/Resources/NanMuCore_3.2.1.154.dll differ diff --git a/PCRobot/Resources/OnlineUpdate.exe b/PCRobot/Resources/OnlineUpdate.exe new file mode 100644 index 0000000..9e3c872 Binary files /dev/null and b/PCRobot/Resources/OnlineUpdate.exe differ diff --git a/PCRobot/Resources/VersionUpdate.exe b/PCRobot/Resources/VersionUpdate.exe new file mode 100644 index 0000000..a02a963 Binary files /dev/null and b/PCRobot/Resources/VersionUpdate.exe differ diff --git a/PCRobot/Resources/VersionUpdate.xml b/PCRobot/Resources/VersionUpdate.xml new file mode 100644 index 0000000..5227f0a --- /dev/null +++ b/PCRobot/Resources/VersionUpdate.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/PCRobot/Resources/WeChatHelper_3.3.0.93.dll b/PCRobot/Resources/WeChatHelper_3.3.0.93.dll new file mode 100644 index 0000000..9b2b78d Binary files /dev/null and b/PCRobot/Resources/WeChatHelper_3.3.0.93.dll differ diff --git a/PCRobot/Resources/WeChatHelper_3.4.0.38.dll b/PCRobot/Resources/WeChatHelper_3.4.0.38.dll new file mode 100644 index 0000000..1d023a4 Binary files /dev/null and b/PCRobot/Resources/WeChatHelper_3.4.0.38.dll differ diff --git a/PCRobot/Resources/WeChatWin.dll b/PCRobot/Resources/WeChatWin.dll new file mode 100644 index 0000000..f37b86b Binary files /dev/null and b/PCRobot/Resources/WeChatWin.dll differ diff --git a/PCRobot/Resources/libcurl.dll b/PCRobot/Resources/libcurl.dll new file mode 100644 index 0000000..330e74c Binary files /dev/null and b/PCRobot/Resources/libcurl.dll differ diff --git a/PCRobot/Resources/libcurlOrg.dll b/PCRobot/Resources/libcurlOrg.dll new file mode 100644 index 0000000..10bb8d5 Binary files /dev/null and b/PCRobot/Resources/libcurlOrg.dll differ diff --git a/PCRobot/Resources/msimg32_32.dll b/PCRobot/Resources/msimg32_32.dll new file mode 100644 index 0000000..653d747 Binary files /dev/null and b/PCRobot/Resources/msimg32_32.dll differ diff --git a/PCRobot/Resources/msimg32_QY.dll b/PCRobot/Resources/msimg32_QY.dll new file mode 100644 index 0000000..611fe86 Binary files /dev/null and b/PCRobot/Resources/msimg32_QY.dll differ diff --git a/PCRobot/Resources/未登录.png b/PCRobot/Resources/未登录.png new file mode 100644 index 0000000..f704472 Binary files /dev/null and b/PCRobot/Resources/未登录.png differ diff --git a/PCRobot/UpdateForm.Designer.cs b/PCRobot/UpdateForm.Designer.cs new file mode 100644 index 0000000..3694733 --- /dev/null +++ b/PCRobot/UpdateForm.Designer.cs @@ -0,0 +1,78 @@ +namespace PCRobot +{ + partial class UpdateForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // richTextBox1 + // + this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.richTextBox1.Location = new System.Drawing.Point(0, 0); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.Size = new System.Drawing.Size(315, 340); + this.richTextBox1.TabIndex = 0; + this.richTextBox1.Text = ""; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(117, 353); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(78, 27); + this.button1.TabIndex = 1; + this.button1.Text = "立即更新"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // UpdateForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(315, 392); + this.Controls.Add(this.button1); + this.Controls.Add(this.richTextBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UpdateForm"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "更新内容"; + this.Load += new System.EventHandler(this.UpdateForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/PCRobot/UpdateForm.cs b/PCRobot/UpdateForm.cs new file mode 100644 index 0000000..41957aa --- /dev/null +++ b/PCRobot/UpdateForm.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PCRobot +{ + public partial class UpdateForm : Form + { + private string strb = null; + public UpdateForm(string strb) + { + InitializeComponent(); + this.strb = strb; + } + + private void UpdateForm_Load(object sender, EventArgs e) + { + try + { + richTextBox1.Text = strb ?? "作者未填写更新内容"; + } + catch (Exception ex) + { } + } + + private void button1_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.OK; + } + } +} diff --git a/PCRobot/UpdateForm.resx b/PCRobot/UpdateForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/PCRobot/UpdateForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/PCRobot/Util.cs b/PCRobot/Util.cs new file mode 100644 index 0000000..4736aac --- /dev/null +++ b/PCRobot/Util.cs @@ -0,0 +1,1382 @@ +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Management; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Script.Serialization; + +namespace PCRobot +{ + public enum BeiyongType + { + 正版 = -1,//正版 + xx = 0,//小邪 + kst = 1,//kst + } + + + + /// + /// 字节缓冲处理类,本类仅处理大字节序
+ /// 本类非线程安全 + ///
+ [Serializable] + public class ByteBuffer : ICloneable + { + //字节缓存区 + private byte[] buf; + //读取索引 + private int readIndex = 0; + //写入索引 + private int writeIndex = 0; + //读取索引标记 + private int markReadIndex = 0; + //写入索引标记 + private int markWirteIndex = 0; + //缓存区字节数组的长度 + private int capacity; + + //对象池 + private static List pool = new List(); + private static int poolMaxCount = 200; + + //此对象是否池化 + private bool isPool = false; + + /// + /// 构造方法 + /// + /// 初始容量 + private ByteBuffer(int capacity) + { + this.buf = new byte[capacity]; + this.capacity = capacity; + this.readIndex = 0; + this.writeIndex = 0; + } + + /// + /// 构造方法 + /// + /// 初始字节数组 + private ByteBuffer(byte[] bytes) + { + this.buf = new byte[bytes.Length]; + Array.Copy(bytes, 0, buf, 0, buf.Length); + this.capacity = buf.Length; + this.readIndex = 0; + this.writeIndex = bytes.Length + 1; + } + + /// + /// 构建一个capacity长度的字节缓存区ByteBuffer对象 + /// + /// 初始容量 + /// + /// true表示获取一个池化的ByteBuffer对象,池化的对象必须在调用Dispose后才会推入池中,此方法为线程安全的。 + /// 当为true时,从池中获取的对象的实际capacity值。 + /// + /// ByteBuffer对象 + public static ByteBuffer Allocate(int capacity, bool fromPool = false) + { + if (!fromPool) + { + return new ByteBuffer(capacity); + } + lock (pool) + { + ByteBuffer bbuf; + if (pool.Count == 0) + { + bbuf = new ByteBuffer(capacity) + { + isPool = true + }; + return bbuf; + } + int lastIndex = pool.Count - 1; + bbuf = pool[lastIndex]; + pool.RemoveAt(lastIndex); + if (!bbuf.isPool) + { + bbuf.isPool = true; + } + return bbuf; + } + } + + /// + /// 构建一个以bytes为字节缓存区的ByteBuffer对象,一般不推荐使用 + /// + /// 初始字节数组 + /// + /// true表示获取一个池化的ByteBuffer对象,池化的对象必须在调用Dispose后才会推入池中,此方法为线程安全的。 + /// + /// ByteBuffer对象 + public static ByteBuffer Allocate(byte[] bytes, bool fromPool = false) + { + if (!fromPool) + { + return new ByteBuffer(bytes); + } + lock (pool) + { + ByteBuffer bbuf; + if (pool.Count == 0) + { + bbuf = new ByteBuffer(bytes) + { + isPool = true + }; + return bbuf; + } + int lastIndex = pool.Count - 1; + bbuf = pool[lastIndex]; + bbuf.WriteBytes(bytes); + pool.RemoveAt(lastIndex); + if (!bbuf.isPool) + { + bbuf.isPool = true; + } + return bbuf; + } + } + + /// + /// 根据value,确定大于此length的最近的2次方数,如length=7,则返回值为8;length=12,则返回16 + /// + /// 参考容量 + /// 比参考容量大的最接近的2次方数 + private int FixLength(int value) + { + if (value == 0) + { + return 1; + } + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + return value + 1; + //int n = 2; + //int b = 2; + //while (b < length) + //{ + // b = 2 << n; + // n++; + //} + //return b; + } + + /// + /// 翻转字节数组,如果本地字节序列为低字节序列,则进行翻转以转换为高字节序列 + /// + /// 待转为高字节序的字节数组 + /// 高字节序列的字节数组 + private byte[] Flip(byte[] bytes) + { + if (BitConverter.IsLittleEndian) + { + Array.Reverse(bytes); + } + return bytes; + } + + /// + /// 确定内部字节缓存数组的大小 + /// + /// 当前容量 + /// 将来的容量 + /// 当前缓冲区的最大容量 + private int FixSizeAndReset(int currLen, int futureLen) + { + if (futureLen > currLen) + { + //以原大小的2次方数的两倍确定内部字节缓存区大小 + int size = FixLength(currLen) * 2; + if (futureLen > size) + { + //以将来的大小的2次方的两倍确定内部字节缓存区大小 + size = FixLength(futureLen) * 2; + } + byte[] newbuf = new byte[size]; + Array.Copy(buf, 0, newbuf, 0, currLen); + buf = newbuf; + capacity = size; + } + return futureLen; + } + + /// + /// 将bytes字节数组从startIndex开始的length字节写入到此缓存区 + /// + /// 待写入的字节数据 + /// 写入的开始位置 + /// 写入的长度 + public void WriteBytes(byte[] bytes, int startIndex, int length) + { + int offset = length - startIndex; + if (offset <= 0) return; + int total = offset + writeIndex; + int len = buf.Length; + FixSizeAndReset(len, total); + for (int i = writeIndex, j = startIndex; i < total; i++, j++) + { + buf[i] = bytes[j]; + } + writeIndex = total; + } + + /// + /// 将字节数组中从0到length的元素写入缓存区 + /// + /// 待写入的字节数据 + /// 写入的长度 + public void WriteBytes(byte[] bytes, int length) + { + WriteBytes(bytes, 0, length); + } + + /// + /// 将字节数组全部写入缓存区 + /// + /// 待写入的字节数据 + public void WriteBytes(byte[] bytes) + { + WriteBytes(bytes, bytes.Length); + } + + /// + /// 将一个ByteBuffer的有效字节区写入此缓存区中 + /// + /// 待写入的字节缓存区 + public void Write(ByteBuffer buffer) + { + if (buffer == null) return; + if (buffer.ReadableBytes <= 0) return; + WriteBytes(buffer.ToArray()); + } + + /// + /// 写入一个int16数据 + /// + /// short数据 + public void WriteShort(short value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个uint16数据 + /// + /// ushort数据 + public void WriteUshort(ushort value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个int32数据 + /// + /// int数据 + public void WriteInt(int value) + { + //byte[] array = new byte[4]; + //for (int i = 3; i >= 0; i--) + //{ + // array[i] = (byte)(value & 0xff); + // value = value >> 8; + //} + //Array.Reverse(array); + //Write(array); + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个uint32数据 + /// + /// uint数据 + public void WriteUint(uint value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个int64数据 + /// + /// long数据 + public void WriteLong(long value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个uint64数据 + /// + /// ulong数据 + public void WriteUlong(ulong value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个float数据 + /// + /// float数据 + public void WriteFloat(float value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个byte数据 + /// + /// byte数据 + public void WriteByte(byte value) + { + int afterLen = writeIndex + 1; + int len = buf.Length; + FixSizeAndReset(len, afterLen); + buf[writeIndex] = value; + writeIndex = afterLen; + } + + /// + /// 写入一个byte数据 + /// + /// byte数据 + public void WriteByte(int value) + { + byte b = (byte)value; + WriteByte(b); + } + + /// + /// 写入一个double类型数据 + /// + /// double数据 + public void WriteDouble(double value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个字符 + /// + /// + public void WriteChar(char value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 写入一个布尔型数据 + /// + /// + public void WriteBoolean(bool value) + { + WriteBytes(Flip(BitConverter.GetBytes(value))); + } + + /// + /// 读取一个字节 + /// + /// 字节数据 + public byte ReadByte() + { + byte b = buf[readIndex]; + readIndex++; + return b; + } + + /// + /// 获取从index索引处开始len长度的字节 + /// + /// + /// + /// + private byte[] Get(int index, int len) + { + byte[] bytes = new byte[len]; + Array.Copy(buf, index, bytes, 0, len); + return Flip(bytes); + } + + /// + /// 从读取索引位置开始读取len长度的字节数组 + /// + /// 待读取的字节长度 + /// 字节数组 + private byte[] Read(int len) + { + byte[] bytes = Get(readIndex, len); + readIndex += len; + return bytes; + } + + /// + /// 读取一个uint16数据 + /// + /// ushort数据 + public ushort ReadUshort() + { + return BitConverter.ToUInt16(Read(2), 0); + } + + /// + /// 读取一个int16数据 + /// + /// short数据 + public short ReadShort() + { + return BitConverter.ToInt16(Read(2), 0); + } + + /// + /// 读取一个uint32数据 + /// + /// uint数据 + public uint ReadUint() + { + return BitConverter.ToUInt32(Read(4), 0); + } + + /// + /// 读取一个int32数据 + /// + /// int数据 + public int ReadInt() + { + return BitConverter.ToInt32(Read(4), 0); + } + + /// + /// 读取一个uint64数据 + /// + /// ulong数据 + public ulong ReadUlong() + { + return BitConverter.ToUInt64(Read(8), 0); + } + + /// + /// 读取一个long数据 + /// + /// long数据 + public long ReadLong() + { + return BitConverter.ToInt64(Read(8), 0); + } + + /// + /// 读取一个float数据 + /// + /// float数据 + public float ReadFloat() + { + return BitConverter.ToSingle(Read(4), 0); + } + + /// + /// 读取一个double数据 + /// + /// double数据 + public double ReadDouble() + { + return BitConverter.ToDouble(Read(8), 0); + } + + /// + /// 读取一个字符 + /// + /// + public char ReadChar() + { + return BitConverter.ToChar(Read(2), 0); + } + + /// + /// 读取布尔型数据 + /// + /// + public bool ReadBoolean() + { + return BitConverter.ToBoolean(Read(1), 0); + } + + /// + /// 从读取索引位置开始读取len长度的字节到disbytes目标字节数组中 + /// + /// 读取的字节将存入此字节数组 + /// 目标字节数组的写入索引 + /// 读取的长度 + public void ReadBytes(byte[] disbytes, int disstart, int len) + { + int size = disstart + len; + for (int i = disstart; i < size; i++) + { + disbytes[i] = this.ReadByte(); + } + } + + /// + /// 获取一个字节 + /// + /// + /// + public byte GetByte(int index) + { + return buf[index]; + } + + /// + /// 获取一个字节 + /// + /// + public byte GetByte() + { + return GetByte(readIndex); + } + + /// + /// 获取一个双精度浮点数据,不改变数据内容 + /// + /// 字节索引 + /// + public double GetDouble(int index) + { + return BitConverter.ToDouble(Get(index, 8), 0); + } + + /// + /// 获取一个双精度浮点数据,不改变数据内容 + /// + /// + public double GetDouble() + { + return GetDouble(readIndex); + } + + /// + /// 获取一个浮点数据,不改变数据内容 + /// + /// 字节索引 + /// + public float GetFloat(int index) + { + return BitConverter.ToSingle(Get(index, 4), 0); + } + + /// + /// 获取一个浮点数据,不改变数据内容 + /// + /// + public float GetFloat() + { + return GetFloat(readIndex); + } + + /// + /// 获取一个长整形数据,不改变数据内容 + /// + /// 字节索引 + /// + public long GetLong(int index) + { + return BitConverter.ToInt64(Get(index, 8), 0); + } + + /// + /// 获取一个长整形数据,不改变数据内容 + /// + /// + public long GetLong() + { + return GetLong(readIndex); + } + + /// + /// 获取一个长整形数据,不改变数据内容 + /// + /// 字节索引 + /// + public ulong GetUlong(int index) + { + return BitConverter.ToUInt64(Get(index, 8), 0); + } + + /// + /// 获取一个长整形数据,不改变数据内容 + /// + /// + public ulong GetUlong() + { + return GetUlong(readIndex); + } + + /// + /// 获取一个整形数据,不改变数据内容 + /// + /// 字节索引 + /// + public int GetInt(int index) + { + return BitConverter.ToInt32(Get(index, 4), 0); + } + + /// + /// 获取一个整形数据,不改变数据内容 + /// + /// + public int GetInt() + { + return GetInt(readIndex); + } + + /// + /// 获取一个整形数据,不改变数据内容 + /// + /// 字节索引 + /// + public uint GetUint(int index) + { + return BitConverter.ToUInt32(Get(index, 4), 0); + } + + /// + /// 获取一个整形数据,不改变数据内容 + /// + /// + public uint GetUint() + { + return GetUint(readIndex); + } + + /// + /// 获取一个短整形数据,不改变数据内容 + /// + /// 字节索引 + /// + public int GetShort(int index) + { + return BitConverter.ToInt16(Get(index, 2), 0); + } + + /// + /// 获取一个短整形数据,不改变数据内容 + /// + /// + public int GetShort() + { + return GetShort(readIndex); + } + + /// + /// 获取一个短整形数据,不改变数据内容 + /// + /// 字节索引 + /// + public int GetUshort(int index) + { + return BitConverter.ToUInt16(Get(index, 2), 0); + } + + /// + /// 获取一个短整形数据,不改变数据内容 + /// + /// + public int GetUshort() + { + return GetUshort(readIndex); + } + + /// + /// 获取一个char数据,不改变数据内容 + /// + /// 字节索引 + /// + public char GetChar(int index) + { + return BitConverter.ToChar(Get(index, 2), 0); + } + + /// + /// 获取一个char数据,不改变数据内容 + /// + /// + public char GetChar() + { + return GetChar(readIndex); + } + + /// + /// 获取一个布尔数据,不改变数据内容 + /// + /// 字节索引 + /// + public bool GetBoolean(int index) + { + return BitConverter.ToBoolean(Get(index, 1), 0); + } + + /// + /// 获取一个布尔数据,不改变数据内容 + /// + /// + public bool GetBoolean() + { + return GetBoolean(readIndex); + } + + /// + /// 清除已读字节并重建缓存区 + /// + public void DiscardReadBytes() + { + if (readIndex <= 0) return; + int len = buf.Length - readIndex; + byte[] newbuf = new byte[len]; + Array.Copy(buf, readIndex, newbuf, 0, len); + buf = newbuf; + writeIndex -= readIndex; + markReadIndex -= readIndex; + if (markReadIndex < 0) + { + //markReadIndex = readIndex; + markReadIndex = 0; + } + markWirteIndex -= readIndex; + if (markWirteIndex < 0 || markWirteIndex < readIndex || markWirteIndex < markReadIndex) + { + markWirteIndex = writeIndex; + } + readIndex = 0; + } + + /// + /// 设置/获取读指针位置 + /// + public int ReaderIndex + { + get + { + return readIndex; + } + set + { + if (value < 0) return; + readIndex = value; + } + } + + /// + /// 设置/获取写指针位置 + /// + public int WriterIndex + { + get + { + return writeIndex; + } + set + { + if (value < 0) return; + writeIndex = value; + } + } + + /// + /// 标记读取的索引位置 + /// + public void MarkReaderIndex() + { + markReadIndex = readIndex; + } + + /// + /// 标记写入的索引位置 + /// + public void MarkWriterIndex() + { + markWirteIndex = writeIndex; + } + + /// + /// 将读取的索引位置重置为标记的读取索引位置 + /// + public void ResetReaderIndex() + { + readIndex = markReadIndex; + } + + /// + /// 将写入的索引位置重置为标记的写入索引位置 + /// + public void ResetWriterIndex() + { + writeIndex = markWirteIndex; + } + + /// + /// 可读的有效字节数 + /// + /// 可读的字节数 + public int ReadableBytes + { + get + { + return writeIndex - readIndex; + } + } + + /// + /// 获取缓存区容量大小 + /// + /// 缓存区容量 + public int Capacity + { + get + { + return this.capacity; + } + } + + /// + /// 获取可读的字节数组 + /// + /// 字节数据 + public byte[] ToArray() + { + byte[] bytes = new byte[writeIndex]; + Array.Copy(buf, 0, bytes, 0, bytes.Length); + return bytes; + } + + /// + /// 简单的数据类型 + /// + public enum DataType + { + //byte类型 + BYTE = 1, + //short类型 + SHORT = 2, + //int类型 + INT = 3, + //long类型 + LONG = 4 + } + + /// + /// 写入一个数据 + /// + /// 待写入的数据 + /// 待写入的数据类型 + private void WriteValue(int value, DataType type) + { + switch (type) + { + case DataType.BYTE: + this.WriteByte(value); + break; + case DataType.SHORT: + this.WriteShort((short)value); + break; + case DataType.LONG: + this.WriteLong((long)value); + break; + default: + this.WriteInt(value); + break; + } + } + + /// + /// 读取一个值,值类型根据type决定,int或short或byte + /// + /// 值类型 + /// int数据 + private int ReadValue(DataType type) + { + switch (type) + { + case DataType.BYTE: + return (int)ReadByte(); + case DataType.SHORT: + return (int)ReadShort(); + case DataType.INT: + return (int)ReadInt(); + case DataType.LONG: + return (int)ReadLong(); + default: + return -1; + } + } + + /// + /// 写入可变长的UTF-8字符串 + /// 以长度类型(byte:1, short:2, int:3) + 长度(根据长度类型写入到字节缓冲区) + 字节数组表示一个字符串 + /// + /// + //public void WriteUTF8VarString(string content) + //{ + // byte[] bytes = System.Text.Encoding.UTF8.GetBytes(content); + // ValueType lenType; + // if (bytes.Length <= byte.MaxValue) + // { + // lenType = ValueType.BYTE; + // } + // else if (bytes.Length <= short.MaxValue) + // { + // lenType = ValueType.SHORT; + // } + // else + // { + // lenType = ValueType.INT; + // } + // WriteByte((int)lenType); + // if (lenType == ValueType.BYTE) + // { + // WriteByte(bytes.Length); + // } + // else if (lenType == ValueType.SHORT) + // { + // WriteShort((short)bytes.Length); + // } + // else + // { + // WriteInt(bytes.Length); + // } + // WriteBytes(bytes); + //} + + /// + /// 读取可变长的UTF-8字符串 + /// 以长度类型(byte:1, short:2, int:3) + 长度(根据长度类型从字节缓冲区读取) + 字节数组表示一个字符串 + /// + /// + //public string ReadUTF8VarString() + //{ + // int lenTypeValue = ReadByte(); + // int len = 0; + // if (lenTypeValue == (int)ValueType.BYTE) + // { + // len = ReadByte(); + // } + // else if (lenTypeValue == (int)ValueType.SHORT) + // { + // len = ReadShort(); + // } + // else if (lenTypeValue == (int)ValueType.INT) + // { + // len = ReadInt(); + // } + // if (len > 0) + // { + // byte[] bytes = new byte[len]; + // ReadBytes(bytes, 0, len); + // return System.Text.Encoding.UTF8.GetString(bytes); + // } + // return ""; + //} + + /// + /// 写入一个UTF-8字符串,UTF-8字符串无高低字节序问题 + /// 写入缓冲区的结构为字符串字节长度(类型由lenType指定) + 字符串字节数组 + /// + /// 待写入的字符串 + /// 写入的字符串长度类型 + public void WriteUTF8String(string content, DataType lenType) + { + byte[] bytes = System.Text.Encoding.UTF8.GetBytes(content); + int max; + if (lenType == DataType.BYTE) + { + WriteByte(bytes.Length); + max = byte.MaxValue; + } + else if (lenType == DataType.SHORT) + { + WriteShort((short)bytes.Length); + max = short.MaxValue; + } + else + { + WriteInt(bytes.Length); + max = int.MaxValue; + } + if (bytes.Length > max) + { + WriteBytes(bytes, 0, max); + } + else + { + WriteBytes(bytes, 0, bytes.Length); + } + } + + /// + /// 写入以short表示的字符串字节长度和字符串字节数据 + /// + /// + public void WriteUTF(string content) + { + this.WriteUTF8String(content, DataType.SHORT); + } + + /// + /// 读取一个UTF-8字符串,UTF-8字符串无高低字节序问题 + /// + /// 需读取的字符串长度 + /// 字符串 + public string ReadUTF8String(int len) + { + byte[] bytes = new byte[len]; + this.ReadBytes(bytes, 0, len); + return System.Text.Encoding.UTF8.GetString(bytes); + } + + /// + /// 读取一个UTF-8字符串,UTF-8字符串无高低字节序问题 + /// + /// 字符串长度类型 + /// 字符串 + public string ReadUTF8String(DataType lenType) + { + int len = ReadValue(lenType); + return ReadUTF8String(len); + } + + /// + /// 读取short类型的字符串字节长度,然后根据此长度读取对应数量的字节数据后转为字符串 + /// + /// UTF-8字符串 + public string ReadUTF() + { + return this.ReadUTF8String(DataType.SHORT); + } + + /// + /// 复制一个对象,具有与原对象相同的数据,不改变原对象的数据,不包括已读数据 + /// + /// + public ByteBuffer Copy() + { + if (buf == null) + { + return new ByteBuffer(16); + } + if (readIndex < writeIndex) + { + byte[] newbytes = new byte[writeIndex - readIndex]; + Array.Copy(buf, readIndex, newbytes, 0, newbytes.Length); + ByteBuffer buffer = new ByteBuffer(newbytes.Length); + buffer.WriteBytes(newbytes); + buffer.isPool = this.isPool; + return buffer; + } + return new ByteBuffer(16); + } + + /// + /// 深度复制,具有与原对象相同的数据,不改变原对象的数据,包括已读数据 + /// + /// + public object Clone() + { + if (buf == null) + { + return new ByteBuffer(16); + } + ByteBuffer newBuf = new ByteBuffer(buf) + { + capacity = this.capacity, + readIndex = this.readIndex, + writeIndex = this.writeIndex, + markReadIndex = this.markReadIndex, + markWirteIndex = this.markWirteIndex, + isPool = this.isPool + }; + return newBuf; + } + + /// + /// 遍历所有的字节数据 + /// + /// + public void ForEach(Action action) + { + for (int i = 0; i < this.ReadableBytes; i++) + { + action.Invoke(this.buf[i]); + } + } + + /// + /// 清空此对象,但保留字节缓存数组(空数组) + /// + public void Clear() + { + //buf = new byte[buf.Length]; + for (int i = 0; i < buf.Length; i++) + { + buf[i] = 0; + } + readIndex = 0; + writeIndex = 0; + markReadIndex = 0; + markWirteIndex = 0; + capacity = buf.Length; + } + + /// + /// 释放对象,清除字节缓存数组,如果此对象为可池化,那么调用此方法将会把此对象推入到池中等待下次调用 + /// + public void Dispose() + { + if (isPool) + { + lock (pool) + { + if (pool.Count < poolMaxCount) + { + this.Clear(); + pool.Add(this); + } + else + { + readIndex = 0; + writeIndex = 0; + markReadIndex = 0; + markWirteIndex = 0; + capacity = 0; + buf = null; + } + } + } + else + { + readIndex = 0; + writeIndex = 0; + markReadIndex = 0; + markWirteIndex = 0; + capacity = 0; + buf = null; + } + } + } + + class Util + { + /// + /// 将文件转换成byte[] 数组 + /// + /// 文件路径文件名称 + /// byte[] + + public static byte[] GetFileData(string fileUrl) + { + using (FileStream fs = new FileStream(fileUrl, FileMode.OpenOrCreate, FileAccess.ReadWrite)) + { + byte[] buffur = new byte[fs.Length]; + using (BinaryWriter bw = new BinaryWriter(fs)) + { + bw.Write(buffur); + bw.Close(); + } + return buffur; + } + } + + //public static void WriteResource(string fileName, byte[] writeData) + public static void WriteResource(string fileName, string srcFilePath, string version, bool isWXWork = false) + { + if (!File.Exists(srcFilePath)) + return; + var writeData = File.ReadAllBytes(srcFilePath); + var writeDataStr = BitConverter.ToString(writeData); + if (File.Exists(fileName)) + { + var oldFile = File.ReadAllBytes(fileName); + var oldFileStr = BitConverter.ToString(oldFile);//将字节数组装换为字符串 + if (writeDataStr != oldFileStr) + { + var name = isWXWork ? "WXWork" : "PCWechat"; + var path = HttpExtend.MapPath($"{name}\\" + version);//退出上个版本的微信 + KillApp(path, isWXWork); + Thread.Sleep(10); + + File.WriteAllBytes(fileName, writeData); + } + } + else File.WriteAllBytes(fileName, writeData); + } + + /// + /// 杀死App进程 + /// + /// + public static void KillApp(string dirPath, bool isWXWork = false) + { + Process[] MyProcesses = Process.GetProcesses(); + + var paoName = isWXWork ? "WXWORK" : "WECHAT"; + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToUpper(); + if (name == paoName && MyProcess.MainModule.FileName.StartsWith(dirPath)) + { + #region 退掉这个版本的微信 + try + { + LogHelper.GetSingleObj().Info("主动调用杀死进程", "KillApp:" + MyProcess.Id); + MyProcess.Kill(); + } + catch (Exception) + { + } + #endregion + + } + } + catch (Exception) + { + } + } + } + + public static bool IsLinshi() + { + return false; + try + { + var http = new CsharpHttpHelper.HttpHelper(); + var result = http.GetHtml("https://cps.api.52cmg.cn/api/webtool.asmx/get_config?type=wechat_type"); + if (result.Html.Contains("xiaoxie")) + return false; + } + catch (Exception) + { + } + return true; + } + + /// + /// 生成指定位数的随机数 + /// + /// + /// + public static string GetRandomString(int iLength) + { + try + { + string buffer = "aAbBcCdDhHfF_xXnNmMlLqQwWeErRcKlpO0123456789";// 随机字符中也可以为汉字(任何) + StringBuilder sb = new StringBuilder(); + Random r = new Random(); + int range = buffer.Length; + for (int i = 0; i < iLength; i++) + { + sb.Append(buffer.Substring(r.Next(range), 1)); + } + return sb.ToString(); + } + catch (Exception) + { } + return "kDc_o"; + } + /// + /// 文件转换成Base64字符串 + /// + /// 文件绝对路径 + /// + public static String FileToBase64(string fileName) + { + string strRet = ""; + + try + { + FileStream fs = new FileStream(fileName, FileMode.Open); + byte[] bt = new byte[fs.Length]; + fs.Read(bt, 0, bt.Length); + strRet = Convert.ToBase64String(bt); + fs.Close(); + } + catch (Exception ex) + { + strRet = null; + } + + return strRet; + } + + /// + /// Base64字符串转换成文件 + /// + /// base64字符串 + /// 保存文件的绝对路径 + /// + public static bool Base64ToFileAndSave(string strInput, string fileName) + { + bool bTrue = false; + try + { + byte[] buffer = Convert.FromBase64String(strInput); + FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate); + fs.Write(buffer, 0, buffer.Length); + fs.Close(); + bTrue = true; + } + catch (Exception ex) + { + + } + return bTrue; + } + + /// + /// 将指定的Json字符串转为指定的T类型对象 + /// + /// 字符串 + /// 转换后的对象,失败为Null + internal static object JsonToObject(string jsonstr) + { + try + { + JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); + return javaScriptSerializer.Deserialize(jsonstr); + } + catch (Exception ex) + { + return null; + } + } + + /// + /// 将指定的对象转为Json字符串 + /// + /// 对象 + /// 转换后的字符串失败为空字符串 + internal static string ObjectToJson(object obj) + { + try + { + JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); + return javaScriptSerializer.Serialize(obj); + } + catch (Exception) + { + return string.Empty; + } + } + + } +} diff --git a/PCRobot/Utils/Common.cs b/PCRobot/Utils/Common.cs new file mode 100644 index 0000000..0ba69b8 --- /dev/null +++ b/PCRobot/Utils/Common.cs @@ -0,0 +1,1257 @@ +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Management; +using System.Net; +using System.Runtime.InteropServices; +using System.Security.AccessControl; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; +using Newtonsoft.Json; + +namespace PCRobot.Utils +{ + + /// + /// 生成计算机的16字节唯一标识码 + /// Example: 4986-8FD5-EE85-69D3-FE52-8CF7-395D-E4A9 + /// + internal class FingerPrint + { + + + + + + private static string fingerPrint = string.Empty; + public static string Value() + { + if (string.IsNullOrEmpty(fingerPrint)) + fingerPrint = GetHash($"CPU >> {cpuId()}|BIOS >> {biosId()}|BASE >> {baseId()}|DISK >> {diskId()}|VIDEO >> {videoId()}|MAC >> {macId()}|PATH >> {Environment.CurrentDirectory}"); + return fingerPrint; + } + private static string GetHash(string s) + { + try + { + MD5 sec = new MD5CryptoServiceProvider(); + ASCIIEncoding enc = new ASCIIEncoding(); + byte[] bt = enc.GetBytes(s); + return GetHexString(sec.ComputeHash(bt)); + } + catch (Exception) + { } + return string.Empty; + } + private static string GetHexString(byte[] bt) + { + var s = string.Empty; + try + { + for (int i = 0; i < bt.Length; i++) + { + byte b = bt[i]; + int n, n1, n2; + n = (int)b; + n1 = n & 15; + n2 = (n >> 4) & 15; + if (n2 > 9) + s += ((char)(n2 - 10 + (int)'A')).ToString(); + else + s += n2.ToString(); + if (n1 > 9) + s += ((char)(n1 - 10 + (int)'A')).ToString(); + else + s += n1.ToString(); + if ((i + 1) != bt.Length && (i + 1) % 2 == 0) s += "-"; + } + } + catch (Exception) + { } + return s; + } + #region Original Device ID Getting Code + //Return a hardware identifier + private static string identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue) + { + var result = string.Empty; + try + { + System.Management.ManagementClass mc = + new System.Management.ManagementClass(wmiClass); + System.Management.ManagementObjectCollection moc = mc.GetInstances(); + foreach (System.Management.ManagementObject mo in moc) + { + if (mo[wmiMustBeTrue].ToString() == "True") + { + //Only get the first one + if (result == "") + { + try + { + result = mo[wmiProperty].ToString(); + break; + } + catch + { + } + } + } + } + } + catch (Exception) + { } + return result; + } + //Return a hardware identifier + private static string identifier(string wmiClass, string wmiProperty) + { + var result = string.Empty; + try + { + System.Management.ManagementClass mc = + new System.Management.ManagementClass(wmiClass); + System.Management.ManagementObjectCollection moc = mc.GetInstances(); + foreach (System.Management.ManagementObject mo in moc) + { + //Only get the first one + if (result == "") + { + try + { + result = mo[wmiProperty].ToString(); + break; + } + catch + { + } + } + } + } + catch (Exception ex) + { } + return result; + } + private static string cpuId() + { + //Uses first CPU identifier available in order of preference + //Don't get all identifiers, as it is very time consuming + try + { + string retVal = identifier("Win32_Processor", "UniqueId"); + if (retVal == "") //If no UniqueID, use ProcessorID + { + retVal = identifier("Win32_Processor", "ProcessorId"); + if (retVal == "") //If no ProcessorId, use Name + { + retVal = identifier("Win32_Processor", "Name"); + if (retVal == "") //If no Name, use Manufacturer + { + retVal = identifier("Win32_Processor", "Manufacturer"); + } + //Add clock speed for extra security + retVal += identifier("Win32_Processor", "MaxClockSpeed"); + } + } + return retVal; + } + catch (Exception) + { } + return string.Empty; + } + //BIOS Identifier + private static string biosId() + { + try + { + return identifier("Win32_BIOS", "Manufacturer") + + identifier("Win32_BIOS", "SMBIOSBIOSVersion") + + identifier("Win32_BIOS", "IdentificationCode") + + identifier("Win32_BIOS", "SerialNumber") + + identifier("Win32_BIOS", "ReleaseDate") + + identifier("Win32_BIOS", "Version"); + } + catch (Exception) + { } + return string.Empty; + } + //Main physical hard drive ID + private static string diskId() + { + try + { + return identifier("Win32_DiskDrive", "Model") + + identifier("Win32_DiskDrive", "Manufacturer") + + identifier("Win32_DiskDrive", "Signature") + + identifier("Win32_DiskDrive", "TotalHeads"); + } + catch (Exception) + { } + return string.Empty; + } + //Motherboard ID + private static string baseId() + { + try + { + return identifier("Win32_BaseBoard", "Model") + + identifier("Win32_BaseBoard", "Manufacturer") + + identifier("Win32_BaseBoard", "Name") + + identifier("Win32_BaseBoard", "SerialNumber"); + } + catch (Exception) + { } + return string.Empty; + } + //Primary video controller ID + private static string videoId() + { + try + { + return identifier("Win32_VideoController", "DriverVersion") + + identifier("Win32_VideoController", "Name"); + } + catch (Exception) + { } + return string.Empty; + } + //First enabled network card ID + private static string macId() + { + try + { + return identifier("Win32_NetworkAdapterConfiguration", + "MACAddress", "IPEnabled"); + } + catch (Exception ex) + { } + return string.Empty; + } + #endregion + } + + /// + /// 企业Cdn文件类型 + /// + public enum QyCdnFileType + { + 图片_视频 = 2, + 语音 = 5, + } + + /// + /// 常用文件后缀 + /// + public enum FileSuffixType + { + jpg = 0, + png = 1, + gif = 2, + mp4 = 3, + txt = 4, + doc = 5, + ico = 6, + rar = 7, + silk = 8, + mp3 = 9, + } + + public static class Common + { + /// + /// 下载文件 + /// + /// + /// + /// + public static bool DownFile(string url, string savePath) + { + try + { + if (!url.Trim().StartsWith("http", StringComparison.CurrentCultureIgnoreCase | StringComparison.OrdinalIgnoreCase) && File.Exists(url)) + { + File.Copy(url, savePath, true); + return true; + } + WebClient client = new WebClient(); + client.DownloadFile(url, savePath); + } + catch (Exception ex) + { + return false; + } + return true; + } + + #region 获取一个新的文件完整路径 + /// + /// 获取一个新的文件完整路径 + /// + /// 文件后缀 + /// 文件名称,为空时用Guid + /// + public static string CreateNewFilePath(FileSuffixType fileSuffix, string fileName = "") + { + return HttpExtend.MapFile((string.IsNullOrWhiteSpace(fileName) ? Guid.NewGuid().ToString("N") : fileName) + "." + fileSuffix.ToString(), $"Cache\\{GetDirNameByFileSuffixType(fileSuffix)}"); + } + + /// + /// 获取一个新的文件完整路径 + /// + /// 不带点的后缀名(例如:jpg) + /// 保存在缓存目录下的子目录名称 + /// + public static string CreateNewFilePath(string fileSuffix, string chipDirName) + { + return HttpExtend.MapFile(Guid.NewGuid().ToString("N") + "." + fileSuffix, $"Cache\\{chipDirName}"); + } + + /// + /// 后缀获取目录名 + /// + /// + /// + private static string GetDirNameByFileSuffixType(FileSuffixType fileSuffixType) + { + switch (fileSuffixType) + { + case FileSuffixType.jpg: + case FileSuffixType.png: + case FileSuffixType.gif: + case FileSuffixType.ico: + return "Image"; + case FileSuffixType.mp4: + return "Video"; + case FileSuffixType.txt: + case FileSuffixType.doc: + return "Doc"; + case FileSuffixType.rar: + return "Zip"; + case FileSuffixType.silk: + case FileSuffixType.mp3: + return "Audio"; + default: + return "Other"; + } + } + #endregion + + + //[System.Runtime.InteropServices.DllImport("USER32.DLL")] + //public static extern bool SetForegroundWindow(IntPtr hWnd); + //[System.Runtime.InteropServices.DllImport("USER32.dll")] + //private static extern int ShowWindow(IntPtr hwnd, uint nCmdShow); + //public static void ActivateWindow() + //{ + // ////if (DateTime.Now.Hour == 4) + // //{ + // List processes = new List(); + // var process = Process.GetProcessesByName("WECHAT").ToList(); + // process.Add(Process.GetCurrentProcess()); + // processes.AddRange(process); + + // var process2 = Process.GetProcessesByName("WXWORK").ToList(); + // //process2.Add(Process.GetCurrentProcess()); + // processes.AddRange(process2); + + // Task.Factory.StartNew(() => + // { + // foreach (var item in processes) + // { + // try + // { + // var hwnd = item.MainWindowHandle; + // ShowWindow(hwnd, 9); + // SetForegroundWindow(hwnd); + // } + // catch (Exception) + // { + + // } + // Thread.Sleep(1000); + // } + // }); + // //} + //} + + #region 激活窗体 + public struct Rect + { + public int Left; + public int Top; + public int Right; + public int Bottom; + } + + [DllImport("user32.dll")] + private static extern int GetWindowRect(IntPtr hwnd, out Rect lpRect); + + [DllImport("user32.dll")] + private static extern bool SetCursorPos(int x, int y); + + [DllImport("user32.dll")] + public static extern bool ReleaseCapture(); + + [DllImport("user32.dll", EntryPoint = "SendMessageA")] + public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam); + + [System.Runtime.InteropServices.DllImport("USER32.DLL")] + private static extern bool SetForegroundWindow(IntPtr hWnd); + [System.Runtime.InteropServices.DllImport("USER32.dll")] + private static extern int ShowWindow(IntPtr hwnd, uint nCmdShow); + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern IntPtr SetActiveWindow(IntPtr hWnd); + + [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow")] //声明FindWindowAPI + private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern IntPtr FindWindowExA(IntPtr parentHandle, IntPtr childAfter, string lpClassName, string lpWindowName); + + [System.Runtime.InteropServices.DllImport("user32")] + private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); + + const int MOUSEEVENTF_MOVE = 0x0001; //移动鼠标 + const int MOUSEEVENTF_LEFTDOWN = 0x0002; //模拟鼠标左键按下 + const int MOUSEEVENTF_LEFTUP = 0x0004; //模拟鼠标左键抬起 + const int MOUSEEVENTF_RIGHTDOWN = 0x0008; //模拟鼠标右键按下 + const int MOUSEEVENTF_RIGHTUP = 0x0010; //模拟鼠标右键抬起 + const int MOUSEEVENTF_MIDDLEDOWN = 0x0020; //模拟鼠标中键按下 + const int MOUSEEVENTF_MIDDLEUP = 0x0040; //模拟鼠标中键抬起 + const int MOUSEEVENTF_ABSOLUTE = 0x8000; //标示是否采用绝对坐标 + + private const int VM_NCLBUTTONDOWN = 0XA1;//定义鼠标左键按下 + private const int HTCAPTION = 2; + + /// + /// 激活个人微信窗口 + /// + private static void ActivateWindow(String lpClassName, string lpWindowName) + { + + + + try + { + //主窗口句柄 + var handle = IntPtr.Zero; + var handleList = new List(); + do + { + //查找窗口句柄并筛选 + handle = FindWindowExA(IntPtr.Zero, handle, lpClassName, lpWindowName); + if (handle == IntPtr.Zero) break; + if (handleList.Contains(handle)) break; + handleList.Add(handle); + + //开始通过win32激活 + var showWindow = ShowWindow(handle, 9); + Thread.Sleep(500); + var setActiveWindow = SetActiveWindow(handle); + Thread.Sleep(new Random(Guid.NewGuid().GetHashCode()).Next(1000, 3000)); + var setForegroundWindow = SetForegroundWindow(handle); + Thread.Sleep(new Random(Guid.NewGuid().GetHashCode()).Next(2000, 5000)); + + ////找窗口的坐标 + //Rect rect = new Rect(); + //var getWindowRect = GetWindowRect(handle, out var lpRect); + + ////设置鼠标的位置 + //var setCursorPos = SetCursorPos(lpRect.Left + new Random(Guid.NewGuid().GetHashCode()).Next(10, 30), lpRect.Top + new Random(Guid.NewGuid().GetHashCode()).Next(5, 12)); + + var release = ReleaseCapture(); + + int x = new Random(Guid.NewGuid().GetHashCode()).Next(10, 30); + int y = new Random(Guid.NewGuid().GetHashCode()).Next(5, 12); + var one = SendMessage(handle, 0x201, IntPtr.Zero, new IntPtr(x + (y << 16))); + Thread.Sleep(300); + var two = SendMessage(handle, 0x202, IntPtr.Zero, new IntPtr(x + (y << 16))); + + //LogHelper.GetSingleObj().Info("激活", $"激活窗口 => showWindow:{showWindow};setActiveWindow={setActiveWindow};setForegroundWindow={setForegroundWindow};getWindowRect={getWindowRect};{JsonConvert.SerializeObject(lpRect)};setCursorPos={setCursorPos};release={release};mouse={sendMessage}"); + LogHelper.GetSingleObj().Info("激活", $"激活窗口 => showWindow:{showWindow};setActiveWindow={setActiveWindow};setForegroundWindow={setForegroundWindow};release={release};x={x};y={y};one={one};two={two}"); + Thread.Sleep(2000); + } while (true); + } + catch (Exception e) + { + Console.WriteLine($"ActivateWindow Error:{e.Message}\r\nParams:lpClassName={lpClassName} lpWindowName={lpWindowName}"); + } + } + + /// + /// 激活windows窗口 + /// + public static void ActivateWindow() + { + Task.Factory.StartNew(() => + { + //激活个人微信 + ActivateWindow("WeChatMainWndForPC", "微信"); + Thread.Sleep(new Random(Guid.NewGuid().GetHashCode()).Next(4000, 10000)); + //激活企业微信 + ActivateWindow("WeWorkWindow", "企业微信"); + }); + } + #endregion + + + private static string Device = string.Empty; + /// + /// 获取设备信息 + /// + /// + internal static string GetDevice() + { + if (!string.IsNullOrWhiteSpace(Device)) return Device; + var info = string.Empty; + try + { + info = FingerPrint.Value(); //+ Dns.GetHostName(); + } + catch (Exception) + { } + if (string.IsNullOrWhiteSpace(info)) + info = Environment.CurrentDirectory; + return HttpExtend.GetMD5String(info); + } + + private static Version _version; + /// + /// 当前版本 + /// + public static Version CurVersion + { + get + { + if (_version == null) + { + try + { + _version = new Version(UpdateClient.GetVersionName()); + } + catch (Exception ex) + { + _version = Version.Parse("0.0.0.0"); + } + } + return _version; + } + } + + /// + /// xml处理 + /// + /// + /// + public static string XMLDispose(string xml) + { + try + { + var xmlCopy = xml; + var reg = Regex.Match(xmlCopy, @"(?<标题>[\w\W]+?)"); + if (reg.Success) + { + xmlCopy = xmlCopy.Replace($@"{reg.Groups["标题"].Value}", $@"{reg.Groups["标题"].Value.XMLReplace()}"); + } + reg = Regex.Match(xmlCopy, @"(?<介绍>[\w\W]+?)"); + if (reg.Success) + xmlCopy = xmlCopy.Replace($@"{reg.Groups["介绍"].Value}", $@"{reg.Groups["介绍"].Value.XMLReplace()}"); + reg = Regex.Match(xmlCopy, @"(?<链接>[\w\W]+?)"); + if (reg.Success) + xmlCopy = xmlCopy.Replace($@"{reg.Groups["链接"].Value}", $@"{reg.Groups["链接"].Value.XMLReplace()}"); + reg = Regex.Match(xmlCopy, @"(?<图片链接>[\w\W]+?)"); + if (reg.Success) + xmlCopy = xmlCopy.Replace($@"{reg.Groups["图片链接"].Value}", $@"{reg.Groups["图片链接"].Value.XMLReplace()}"); + return xmlCopy; + } + catch (Exception ex) + { } + return xml; + } + + public static string XMLReplace(this string str, bool addCdata = true) + { + var _str = string.Empty; + var reg = Regex.Match(str, @"[\w\W]+?)\]\]"); + _str = reg.Success ? reg.Groups["内容"].Value : str; + return addCdata ? $"" : _str; + } + + /// + /// 删除目录 + /// + public static void DeleteDir(string path) + { + if (Directory.Exists(path)) + { + try + { + DirectoryInfo dir = new DirectoryInfo(path); + FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //返回目录中所有文件和子目录 + foreach (FileSystemInfo i in fileinfo) + { + try + { + if (i is DirectoryInfo) //判断是否文件夹 + { + DirectoryInfo subdir = new DirectoryInfo(i.FullName); + subdir.Delete(true); //删除子目录和文件 + } + //else if (!IsOnlyDirectory) + // File.Delete(i.FullName); //删除指定文件 + } + catch (Exception ex) + { } + } + } + catch + { } + } + } + + + /// + /// 设置缓存(辅助输入) + /// + /// + /// + /// + /// + public static bool SetCache(string key, object value, int secondes = 60) + { + try + { + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[key]; + if (item == null) + cache.Insert(key, value, null, DateTime.Now.AddSeconds(secondes), System.Web.Caching.Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + /// + /// 缓存是否存在 + /// + /// + /// + /// + /// + public static T GetCache(string key) where T : class + { + try + { + Cache cache = HttpRuntime.Cache; + object item = cache[key]; + if (item != null) + return item as T; + } + catch (Exception) + { + } + return default(T); + } + + /// + /// 删除缓存 + /// + /// + /// + public static bool RemoveCache(string key) + { + try + { + Cache cache = HttpRuntime.Cache; + cache.Remove(key); + + return true; + } + catch (Exception e) + { + return false; + } + } + + + /// + /// 缓存是否存在 + /// + /// + /// + /// + /// + public static bool GetCache(string text) + { + try + { + var MD5 = GetMD5($"{text}"); + Cache cache = HttpRuntime.Cache; + object item = cache[MD5]; + return item != null ? true : false; + } + catch (Exception) + { + } + return false; + } + + /// + /// 设置缓存(辅助输入) + /// + /// + /// + /// + /// + public static bool SetCache(string text, int secondes = 60) + { + try + { + var MD5 = GetMD5($"{text}"); + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[MD5]; + if (item == null) + cache.Insert(MD5, 1, null, DateTime.Now.AddSeconds(secondes), System.Web.Caching.Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + /// + /// 缓存是否存在 + /// + /// + /// + /// + /// + public static bool GetCache(string robotname, string username, string text) + { + try + { + var MD5 = GetMD5(ToAllTrim($"{robotname}{username}{text}")); + Cache cache = HttpRuntime.Cache; + object item = cache[MD5]; + return item != null ? true : false; + } + catch (Exception) + { + } + return false; + } + + /// + /// 设置缓存(辅助输入) + /// + /// + /// + /// + /// + public static bool SetCache(string robotname, string username, string text, int seconds = 70) + { + try + { + var MD5 = GetMD5(ToAllTrim($"{robotname}{username}{text}")); + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[MD5]; + if (item == null) + cache.Insert(MD5, 1, null, DateTime.Now.AddSeconds(seconds), System.Web.Caching.Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + /// + /// 删除所有的不可见 + /// + /// + /// + public static string ToAllTrim(string str) + { + return Regex.Replace(str, @"\s", ""); + } + + [DllImport("Kernel32.dll")] + //BOOL ReadProcessMemory( + // HANDLE hProcess, + // LPCVOID lpBaseAddress, + // LPVOID lpBuffer, + // SIZE_T nSize, + // SIZE_T* lpNumberOfBytesRead + //); + public static extern int ReadProcessMemory( + IntPtr hProcess, //正在读取内存的进程句柄。句柄必须具有PROCESS_VM_READ访问权限。 + IntPtr lpBaseAddress, //指向要从中读取的指定进程中的基址的指针。在发生任何数据传输之前,系统会验证基本地址和指定大小的内存中的所有数据是否都可以进行读访问,如果无法访问,则该函数将失败。 + byte[] lpBuffer, //指向缓冲区的指针,该缓冲区从指定进程的地址空间接收内容。 + int nSize, //要从指定进程读取的字节数。 + int lpNumberOfBytesRead //指向变量的指针,该变量接收传输到指定缓冲区的字节数。如果lpNumberOfBytesRead为NULL,则忽略该参数。 + ); + + public static string GetString(IntPtr hProcess, IntPtr lpBaseAddress, int nSize = 100) + { + byte[] data = new byte[nSize]; + if (ReadProcessMemory(hProcess, lpBaseAddress, data, nSize, 0) == 0) + { + //读取内存失败! + return ""; + } + var result = string.Empty; + var uin = BitConverter.ToUInt32(data, 0);//将字节数组内容再转成int32类型 + return uin.ToString(); + //var TempString = Encoding.ASCII.GetString(data); + //// \0 + //foreach (char item in TempString) + //{ + // if (item == '\0') + // { + // break; + // } + // result += item.ToString(); + //} + //return result; + } + + /// + /// 是否公众号 + /// + /// + /// + public static bool IsGzh(this string wxid, bool isgzh = false) + { + if (isgzh && wxid.StartsWith("gh_")) + return false; + return (wxid.StartsWith("gh_") || wxid == "newsapp" || wxid == "weixin" || wxid == "notifymessage"); + } + + /// + /// 文件MD5校验 + /// + /// + /// + public static string GetMD5Hash(string pathName) + { + string strResult = ""; + string strHashData = ""; + byte[] arrbytHashValue; + FileStream oFileStream = null; + MD5CryptoServiceProvider oMD5Hasher = new System.Security.Cryptography.MD5CryptoServiceProvider(); + try + { + oFileStream = new FileStream(pathName, System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + arrbytHashValue = oMD5Hasher.ComputeHash(oFileStream);//计算指定Stream 对象的哈希值 +                oFileStream.Close(); +                //由以连字符分隔的十六进制对构成的String,其中每一对表示value 中对应的元素;例如“F-2C-4A” +                strHashData = BitConverter.ToString(arrbytHashValue); +                //替换- +                strHashData = strHashData.Replace("-", ""); + strResult = strHashData; + } + catch (System.Exception ex) + { } + return strResult; + } + + /// + /// MD5字符串加密 + /// + /// + /// 加密后字符串 + public static string GetMD5(string txt) + { + using (MD5 mi = MD5.Create()) + { + byte[] buffer = Encoding.Default.GetBytes(txt); + //开始加密 + byte[] newBuffer = mi.ComputeHash(buffer); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < newBuffer.Length; i++) + { + sb.Append(newBuffer[i].ToString("x2")); + } + return sb.ToString(); + } + } + + public static string StringMid(string Src, string Left, string Right) + { + string lRusult = string.Empty; + if (Src != string.Empty) + { + int dwLeft = Src.IndexOf(Left); + if (dwLeft != -1) + { + dwLeft += Left.Length; + int dwRight = Src.IndexOf(Right, dwLeft); + if (dwRight != -1) + { + lRusult = Src.Substring(dwLeft, dwRight - dwLeft); + } + } + } + return lRusult; + } + + public static string CacheFilePath(string mWxid, string uWxid, string fName, string uName, string uExt) + { + string filePath = Directory.GetCurrentDirectory() + "\\Accounts\\" + mWxid + "\\" + fName + "\\" + uWxid; + if (!Directory.Exists(filePath)) + Directory.CreateDirectory(filePath); + + SetFileRole(filePath); + + filePath += "\\" + uName + "." + uExt; + return filePath; + } + + /// + /// 设置文件夹权限,处理为Everyone所有权限 + /// + /// 文件夹路径 + public static void SetFileRole(string foldPath) + { + try + { + Thread.Sleep(500); + DirectorySecurity fsec = new DirectorySecurity(); + //添加Everyone用户组的访问权限规则 完全控制权限 + fsec.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, + InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow)); + //添加Users用户组的访问权限规则 完全控制权限 + fsec.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.FullControl, AccessControlType.Allow)); + //添加Authenticated Users用户组的访问权限规则 完全控制权限 + fsec.AddAccessRule(new FileSystemAccessRule("Authenticated Users", FileSystemRights.FullControl, AccessControlType.Allow)); + Directory.SetAccessControl(foldPath, fsec); + Thread.Sleep(500); + } + catch (Exception) + { } + } + + /** + * 判断是否是xml结构 + */ + public static bool isXML(string value) + { + try + { + //XmlDocument xdoc = new XmlDocument(); + //xdoc.LoadXml(value); + //return true; + + //上面的这里有些情况下不准 + var reg = Regex.IsMatch(value.Trim(), @"(.*0[\w\W]*1Window wechat)"); + return reg; + } + catch (Exception ex) + { + return false; + } + } + + /// + /// 文件转换成Base64字符串 + /// + /// 文件绝对路径 + /// + public static String FileToBase64(string fileName) + { + string strRet = ""; + + try + { + FileStream fs = new FileStream(fileName, FileMode.Open); + byte[] bt = new byte[fs.Length]; + fs.Read(bt, 0, bt.Length); + strRet = Convert.ToBase64String(bt); + fs.Close(); + } + catch (Exception ex) + { + strRet = null; + } + + return strRet; + } + + /// + /// Base64字符串转换成文件 + /// + /// base64字符串 + /// 保存文件的绝对路径 + /// + public static bool Base64ToFileAndSave(string strInput, string fileName) + { + bool bTrue = false; + try + { + byte[] buffer = Convert.FromBase64String(strInput); + FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate); + fs.Write(buffer, 0, buffer.Length); + fs.Close(); + bTrue = true; + } + catch (Exception ex) + { } + return bTrue; + } + #region 判断一个字符串是否是base64字符串 + /// + /// 是否base64字符串 + /// + /// 要判断的字符串 + /// + public static bool IsBase64(this string base64Str) + { + byte[] bytes = null; + return IsBase64(base64Str, out bytes); + } + + /// + /// 是否base64字符串 + /// + /// 要判断的字符串 + /// 字符串转换成的字节数组 + /// + private static bool IsBase64(string base64Str, out byte[] bytes) + { + //string strRegex = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$"; + bytes = null; + if (string.IsNullOrEmpty(base64Str)) + return false; + else + { + if (base64Str.Contains(",")) + base64Str = base64Str.Split(',')[1]; + if (base64Str.Length % 4 != 0) + return false; + if (base64Str.Any(c => !base64CodeArray.Contains(c))) + return false; + } + try + { + bytes = Convert.FromBase64String(base64Str); + return true; + } + catch (FormatException) + { + return false; + } + } + + + private static char[] base64CodeArray = new char[] + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=' + }; + #endregion + + + #region Base64 与 Image互转 + public static string ConvertImageToBase64(Image file) + { + using (MemoryStream memoryStream = new MemoryStream()) + { + file.Save(memoryStream, file.RawFormat); + byte[] imageBytes = memoryStream.ToArray(); + return Convert.ToBase64String(imageBytes); + } + } + + public static Bitmap ConvertBase64ToImage(string base64String) + { + byte[] imageBytes = Convert.FromBase64String(base64String); + using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length)) + { + ms.Write(imageBytes, 0, imageBytes.Length); + using (Image mImage = Image.FromStream(ms, true)) + { + return new Bitmap(mImage); + } + } + } + #endregion + + #region 获取图片后缀 + /// + /// 获取图片后缀 + /// + /// + /// + public static string GetImageExt(Image image) + { + string imageExt = "jpg"; + var RawFormatGuid = image.RawFormat.Guid; + if (ImageFormat.Png.Guid == RawFormatGuid) + { + imageExt = "png"; + } + if (ImageFormat.Jpeg.Guid == RawFormatGuid) + { + imageExt = "jpg"; + } + if (ImageFormat.Bmp.Guid == RawFormatGuid) + { + imageExt = "bmp"; + } + if (ImageFormat.Gif.Guid == RawFormatGuid) + { + imageExt = "gif"; + } + if (ImageFormat.Icon.Guid == RawFormatGuid) + { + imageExt = "icon"; + } + return imageExt; + } + #endregion + + #region 压缩图片 + /// + /// 壓縮圖片 /// + /// 圖片流 + /// 壓縮質量0-100之間 數值越大質量越高 + /// + public static Bitmap CompressionImage(Stream fileStream, long quality) + { + try + { + using (Image img = Image.FromStream(fileStream)) + { + //using (Bitmap bitmap = new Bitmap(img)) + Bitmap bitmap = new Bitmap(img); + { + ImageCodecInfo CodecInfo = GetEncoder(img.RawFormat); + System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality; + EncoderParameters myEncoderParameters = new EncoderParameters(1); + EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, quality); + myEncoderParameters.Param[0] = myEncoderParameter; + using (MemoryStream ms = new MemoryStream()) + { + bitmap.Save(ms, CodecInfo, myEncoderParameters); + myEncoderParameters.Dispose(); + myEncoderParameter.Dispose(); + return bitmap; + //return ms.ToArray(); + } + } + } + } + catch (Exception) + { return null; } + } + + + private static ImageCodecInfo GetEncoder(ImageFormat format) + { + ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); + foreach (ImageCodecInfo codec in codecs) + { + if (codec.FormatID == format.Guid) + { return codec; } + } + return null; + } + #endregion + + + public static bool AppConfig_ExistItem(string keyName) + { + //判断配置文件中是否存在键为keyName的项 + foreach (string key in ConfigurationManager.AppSettings) + { + if (key == keyName) + { + //存在 + return true; + } + } + return false; + } + + public static string AppConfig_Get(string keyName) + { + //返回配置文件中键为keyName的项的值 + return ConfigurationManager.AppSettings[keyName]; + } + + public static void AppConfig_Set(string key, string value) + { + var cfa = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + cfa.AppSettings.Settings[key].Value = value; + cfa.Save(); + System.Configuration.ConfigurationManager.RefreshSection("appSettings"); + } + + public static void AppConfig_Add(string key, string value) + { + var cfa = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + cfa.AppSettings.Settings.Add(key, value); + cfa.Save(); + System.Configuration.ConfigurationManager.RefreshSection("appSettings"); + } + + + public static List GetProcesses() + { + try + { + var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process"; + using (var searcher = new ManagementObjectSearcher(wmiQueryString)) + using (var results = searcher.Get()) + { + var sss = Process.GetProcesses(); + foreach (var s in sss) + { + //var dd = JsonConvert.SerializeObject(s); + } + + + var query = from p in Process.GetProcesses() + join mo in results.Cast() + on p.Id equals (int)(uint)mo["ProcessId"] + select new MyProcesses() + { + Process = p, + Path = (string)mo["ExecutablePath"], + CommandLine = (string)mo["CommandLine"], + MainWindowHandle = (IntPtr)mo["MainWindowHandle"], + }; + return query.ToList(); + } + } + catch (Exception ex) + { } + return null; + } + + public class MyProcesses + { + public Process Process { get; set; } + public string Path { get; set; } + public string CommandLine { get; set; } + + public IntPtr MainWindowHandle { get; set; } + } + + } +} diff --git a/PCRobot/Utils/ProtoBufExtension.cs b/PCRobot/Utils/ProtoBufExtension.cs new file mode 100644 index 0000000..0284565 --- /dev/null +++ b/PCRobot/Utils/ProtoBufExtension.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Utils +{ + /// + /// ProtoBuf-Net扩展方法类 + /// + public static class ProtoBufExtension + { + /// + /// 将对象实例序列化为字符串(Base64编码格式)——ProtoBuf + /// + /// 对象类型 + /// 对象实例 + /// 字符串(Base64编码格式) + public static string SerializeToString_PB(this T obj) + { + using (MemoryStream ms = new MemoryStream()) + { + ProtoBuf.Serializer.Serialize(ms, obj); + return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length); + } + } + + /// + /// 将字符串(Base64编码格式)反序列化为对象实例——ProtoBuf + /// + /// 对象类型 + /// 字符串(Base64编码格式) + /// 对象实例 + public static T DeserializeFromString_PB(this string txt) + { + byte[] arr = Convert.FromBase64String(txt); + using (MemoryStream ms = new MemoryStream(arr)) + return ProtoBuf.Serializer.Deserialize(ms); + } + + /// + /// 将对象实例序列化为字节数组——ProtoBuf + /// + /// 对象类型 + /// 对象实例 + /// 字节数组 + public static byte[] SerializeToByteAry_PB(this T obj) + { + using (MemoryStream ms = new MemoryStream()) + { + ProtoBuf.Serializer.Serialize(ms, obj); + return ms.ToArray(); + } + } + + /// + /// 将字节数组反序列化为对象实例——ProtoBuf + /// + /// 对象类型 + /// 字节数组 + /// + public static T DeserializeFromByteAry_PB(this byte[] arr) + { + try + { + using (MemoryStream ms = new MemoryStream(arr)) + return ProtoBuf.Serializer.Deserialize(ms); + } + catch (Exception) + { + return default(T); + } + } + + /// + /// 将对象实例序列化为二进制文件——ProtoBuf + /// + /// 对象类型 + /// 对象实例 + /// 文件路径(目录+文件名) + public static void SerializeToFile_PB(this T obj, string path) + { + using (var file = File.Create(path)) + { + ProtoBuf.Serializer.Serialize(file, obj); + } + } + + /// + /// 将二进制文件反序列化为对象实例——ProtoBuf + /// + /// + /// + /// + public static T DeserializeFromFile_PB(this string path) + { + using (var file = File.OpenRead(path)) + { + return ProtoBuf.Serializer.Deserialize(file); + } + } + } +} diff --git a/PCRobot/Utils/RegistryHelper.cs b/PCRobot/Utils/RegistryHelper.cs new file mode 100644 index 0000000..7e73528 --- /dev/null +++ b/PCRobot/Utils/RegistryHelper.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Win32; + +namespace PCRobot.Utils +{ + public class RegistryHelper + { + + static readonly IntPtr HKEY_CLASSES_ROOT = new IntPtr(unchecked((int)0x80000000)); + static readonly IntPtr HKEY_CURRENT_USER = new IntPtr(unchecked((int)0x80000001)); + static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int)0x80000002)); + static readonly IntPtr HKEY_USERS = new IntPtr(unchecked((int)0x80000003)); + static readonly IntPtr HKEY_PERFORMANCE_DATA = new IntPtr(unchecked((int)0x80000004)); + static readonly IntPtr HKEY_CURRENT_CONFIG = new IntPtr(unchecked((int)0x80000005)); + static readonly IntPtr HKEY_DYN_DATA = new IntPtr(unchecked((int)0x80000006)); + + // 获取操作Key值句柄 + [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int RegOpenKeyEx(IntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out IntPtr phkResult); + + //创建或打开Key值 + [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int RegCreateKeyEx(IntPtr hKey, string lpSubKey, int reserved, string type, int dwOptions, int REGSAM, IntPtr lpSecurityAttributes, out IntPtr phkResult, + out int lpdwDisposition); + + //关闭注册表转向(禁用特定项的注册表反射) + [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int RegDisableReflectionKey(IntPtr hKey); + + //使能注册表转向(开启特定项的注册表反射) + [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int RegEnableReflectionKey(IntPtr hKey); + + //获取Key值(即:Key值句柄所标志的Key对象的值) + [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int lpReserved, out uint lpType, System.Text.StringBuilder lpData, ref uint lpcbData); + + //设置Key值 + [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int RegSetValueEx(IntPtr hKey, string lpValueName, uint unReserved, uint unType, byte[] lpData, uint dataCount); + + //关闭Key值 + [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern int RegCloseKey(IntPtr hKey); + + public static IntPtr TransferKeyName(string keyName) + { + IntPtr ret = IntPtr.Zero; + switch (keyName) + { + case "HKEY_CLASSES_ROOT": + ret = HKEY_CLASSES_ROOT; + break; + case "HKEY_CURRENT_USER": + ret = HKEY_CURRENT_USER; + break; + case "HKEY_LOCAL_MACHINE": + ret = HKEY_LOCAL_MACHINE; + break; + case "HKEY_USERS": + ret = HKEY_USERS; + break; + case "HKEY_PERFORMANCE_DATA": + ret = HKEY_PERFORMANCE_DATA; + break; + case "HKEY_CURRENT_CONFIG": + ret = HKEY_CURRENT_CONFIG; + break; + case "HKEY_DYN_DATA": + ret = HKEY_DYN_DATA; + break; + default: + ret = HKEY_LOCAL_MACHINE; + break; + } + return ret; + } + + /// + /// 设置64位注册表 + /// + /// + /// + /// + /// + /// + public static int Set64BitRegistryKey(string key, string subKey, string name, string value) + { + int STANDARD_RIGHTS_ALL = (0x001F0000); + int KEY_QUERY_VALUE = (0x0001); + int KEY_SET_VALUE = (0x0002); + int KEY_CREATE_SUB_KEY = (0x0004); + int KEY_ENUMERATE_SUB_KEYS = (0x0008); + int KEY_NOTIFY = (0x0010); + int KEY_CREATE_LINK = (0x0020); + int SYNCHRONIZE = (0x00100000); + int KEY_WOW64_64KEY = (0x0100); + int REG_OPTION_NON_VOLATILE = (0x00000000); + int KEY_ALL_ACCESS = (STANDARD_RIGHTS_ALL | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS + | KEY_NOTIFY | KEY_CREATE_LINK) & (~SYNCHRONIZE); + + int ret = 0; + try + { + //将Windows注册表主键名转化成为不带正负号的整形句柄(与平台是32或者64位有关) + IntPtr hKey = TransferKeyName(key); + + //声明将要获取Key值的句柄 + IntPtr pHKey = IntPtr.Zero; + + //获得操作Key值的句柄 + int lpdwDisposition = 0; + ret = RegCreateKeyEx(hKey, subKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS | KEY_WOW64_64KEY, IntPtr.Zero, out pHKey, out lpdwDisposition); + if (ret != 0) + { + //Console.WriteLine(string.Format("Unable to create key {0} - {1}: {2}!", key, subKey, ret)); + return ret; + } + + //关闭注册表转向(禁止特定项的注册表反射) + RegDisableReflectionKey(pHKey); + + //设置访问的Key值 + uint REG_SZ = 1; + byte[] data = Encoding.Unicode.GetBytes(value); + + RegSetValueEx(pHKey, name, 0, REG_SZ, data, (uint)data.Length); + + //打开注册表转向(开启特定项的注册表反射) + RegEnableReflectionKey(pHKey); + + RegCloseKey(pHKey); + } + catch (Exception ex) + { + //Console.WriteLine(ex.ToString()); + return -1; + } + + return ret; + } + + public static void SetRegistryKey(string key, string subKey, string name, string value) + { + //Console.WriteLine("SetRegistryKey start."); + if (System.IntPtr.Size == 8) + { + // 写SOFTWARE\Huawei\VirtualDesktopAgent,需要关闭注册表重定向,再写64位路径的注册表 + int ret = Set64BitRegistryKey(key, subKey, name, value); + if (ret != 0) + { + Console.WriteLine(string.Format("Failed to write Reg {0}\\{1}\\{2},return {3}", key, subKey, name, ret)); + } + } + + try + { + Microsoft.Win32.Registry.SetValue(key + "\\" + subKey, name, value); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + + //Console.WriteLine("SetRegistryKey exit."); + } + + public static string GetRegistryValue(string path, string key) + { + RegistryKey regkey = null; + try + { + regkey = Registry.LocalMachine.OpenSubKey(path); + if (regkey == null) + { + //Console.WriteLine("Cannot find Registry path:" + path); + return null; + } + + object val = regkey.GetValue(key); + if (val == null) + { + //Console.WriteLine("Cannot find Registry key:" + key); + return null; + } + + return val.ToString(); + } + catch (Exception ex) + { + //Console.WriteLine(ex.ToString()); + return null; + } + finally + { + if (regkey != null) + { + regkey.Close(); + } + } + } + + } +} diff --git a/PCRobot/Utils/UpdateClient.cs b/PCRobot/Utils/UpdateClient.cs new file mode 100644 index 0000000..2e2e9cc --- /dev/null +++ b/PCRobot/Utils/UpdateClient.cs @@ -0,0 +1,131 @@ +using CsharpHttpHelper; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Utils +{ + + public class UpdateClient + { + private static string ExecName = "YiZhuanFa"; + /// + /// 获取云端的文件列表 + /// + public static string GetCloudFileHist() + { + try + { + int LastId = 1; + + try + { + var id = GetVersionId(); + LastId = int.Parse(id); + } + catch (Exception) + { + LastId = 1; + } + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = "http://file.api.52cmg.cn/file/QueryHist?Name=" + HttpHelper.URLEncode(ExecName, Encoding.UTF8) + "&LastId=" + LastId, + Timeout = 30000 + }; + var result = http.GetHtml(item).Html; + var data = JObject.Parse(result); + if ((bool)data["Ok"] && data["Data"] != null) + { + return ShowUpdate(data["Data"]); + } + } + catch (Exception) + { } + return null; + } + + private static IniHelper Ini { get; set; } + + + public static string ShowUpdate(JToken jToken) + { + var strb = new StringBuilder(); + try + { + + + foreach (var item in jToken) + { + strb.AppendLine(((DateTime)item["CreateTime"]).ToString("yyyy.MM.dd.HHmm")); + strb.AppendLine(item["Message"].ToString()); + strb.AppendLine(); + } + } + catch (Exception ex) + { } + return strb.ToString(); + } + + private static string GetVersionId() + { + Ini = new IniHelper(HttpExtend.MapFile("版本信息.ini")); + return Ini.GetValue("Version", "Id"); + } + + /// + /// 版本号 + /// + /// + public static string GetVersionName() + { + Ini = new IniHelper(HttpExtend.MapFile("版本信息.ini")); + return DateTime.Parse(Ini.GetValue("Version", "CreateTime")).ToString("yyyy.MM.dd.HHmm"); + } + + /// + /// 版本信息 + /// + public class FileVersion + { + public int Id { get; set; } + public string Name { get; set; } + public bool IsEnable { get; set; } + + private string _Message; + /// + /// 更新的内容 + /// + public string Message + { + get { return ShowMessage(_Message); } + set { _Message = value; } + } + public DateTime CreateTime { get; set; } + + private string ShowMessage(string Message) + { + try + { + var strb = new StringBuilder(); + var UpdateContent = Message.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + + strb.AppendLine($"{Name} - {CreateTime.ToString("yyyy.MM.dd.HHmmss")}"); + strb.AppendLine(); + for (int i = 0; i < UpdateContent.Length; i++) + { + strb.AppendLine(UpdateContent[i]); + } + } + catch (Exception ex) + { } + return Message; + } + } + + } +} diff --git a/PCRobot/Utils/WechatExtend.cs b/PCRobot/Utils/WechatExtend.cs new file mode 100644 index 0000000..bd7f786 --- /dev/null +++ b/PCRobot/Utils/WechatExtend.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Utils +{ + public static class WechatExtend + { + /// + /// 是否为群账号 + /// + /// + /// + public static bool IsQun(this string roomwxid) + { + roomwxid = roomwxid.Trim().ToLower(); + return (roomwxid.EndsWith("@chatroom") || roomwxid.EndsWith("@im.chatroom") || roomwxid.StartsWith("r:")); + } + + + } +} diff --git a/PCRobot/Utils/ZIP/BZip2/BZip2.cs b/PCRobot/Utils/ZIP/BZip2/BZip2.cs new file mode 100644 index 0000000..91669a8 --- /dev/null +++ b/PCRobot/Utils/ZIP/BZip2/BZip2.cs @@ -0,0 +1,105 @@ +// BZip2.cs +// +// Copyright (C) 2010 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// Suppress this in CF and 1.1, not needed. Static classes introduced in C# version 2.0 +#if !NETCF_2_0 && !NET_1_1 + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.BZip2 { + + /// + /// An example class to demonstrate compression and decompression of BZip2 streams. + /// + public static class BZip2 + { + /// + /// Decompress the input writing + /// uncompressed data to the output stream + /// + /// The readable stream containing data to decompress. + /// The output stream to receive the decompressed data. + /// Both streams are closed on completion if true. + public static void Decompress(Stream inStream, Stream outStream, bool isStreamOwner) + { + if (inStream == null || outStream == null) { + throw new Exception("Null Stream"); + } + + try { + using (BZip2InputStream bzipInput = new BZip2InputStream(inStream)) { + bzipInput.IsStreamOwner = isStreamOwner; + Core.StreamUtils.Copy(bzipInput, outStream, new byte[4096]); + } + } finally { + if (isStreamOwner) { + // inStream is closed by the BZip2InputStream if stream owner + outStream.Close(); + } + } + } + + /// + /// Compress the input stream sending + /// result data to output stream + /// + /// The readable stream to compress. + /// The output stream to receive the compressed data. + /// Both streams are closed on completion if true. + /// Block size acts as compression level (1 to 9) with 1 giving + /// the lowest compression and 9 the highest. + public static void Compress(Stream inStream, Stream outStream, bool isStreamOwner, int level) + { + if (inStream == null || outStream == null) { + throw new Exception("Null Stream"); + } + + try { + using (BZip2OutputStream bzipOutput = new BZip2OutputStream(outStream, level)) { + bzipOutput.IsStreamOwner = isStreamOwner; + Core.StreamUtils.Copy(inStream, bzipOutput, new byte[4096]); + } + } finally { + if (isStreamOwner) { + // outStream is closed by the BZip2OutputStream if stream owner + inStream.Close(); + } + } + } + + } +} +#endif diff --git a/PCRobot/Utils/ZIP/BZip2/BZip2Constants.cs b/PCRobot/Utils/ZIP/BZip2/BZip2Constants.cs new file mode 100644 index 0000000..ad3f40d --- /dev/null +++ b/PCRobot/Utils/ZIP/BZip2/BZip2Constants.cs @@ -0,0 +1,197 @@ +// BZip2Constants.cs +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + /// + /// Defines internal values for both compression and decompression + /// + internal sealed class BZip2Constants + { + /// + /// Random numbers used to randomise repetitive blocks + /// + public readonly static int[] RandomNumbers = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 + }; + + /// + /// When multiplied by compression parameter (1-9) gives the block size for compression + /// 9 gives the best compression but uses the most memory. + /// + public const int BaseBlockSize = 100000; + + /// + /// Backend constant + /// + public const int MaximumAlphaSize = 258; + + /// + /// Backend constant + /// + public const int MaximumCodeLength = 23; + + /// + /// Backend constant + /// + public const int RunA = 0; + + /// + /// Backend constant + /// + public const int RunB = 1; + + /// + /// Backend constant + /// + public const int GroupCount = 6; + + /// + /// Backend constant + /// + public const int GroupSize = 50; + + /// + /// Backend constant + /// + public const int NumberOfIterations = 4; + + /// + /// Backend constant + /// + public const int MaximumSelectors = (2 + (900000 / GroupSize)); + + /// + /// Backend constant + /// + public const int OvershootBytes = 20; + + private BZip2Constants() + { + } + } +} + +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/PCRobot/Utils/ZIP/BZip2/BZip2Exception.cs b/PCRobot/Utils/ZIP/BZip2/BZip2Exception.cs new file mode 100644 index 0000000..3b7c8ff --- /dev/null +++ b/PCRobot/Utils/ZIP/BZip2/BZip2Exception.cs @@ -0,0 +1,90 @@ +// BZip2.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + /// + /// BZip2Exception represents exceptions specific to Bzip2 algorithm + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class BZip2Exception : SharpZipBaseException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected BZip2Exception(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + /// + /// Initialise a new instance of BZip2Exception. + /// + public BZip2Exception() + { + } + + /// + /// Initialise a new instance of BZip2Exception with its message set to message. + /// + /// The message describing the error. + public BZip2Exception(string message) : base(message) + { + } + + /// + /// Initialise an instance of BZip2Exception + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public BZip2Exception(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/PCRobot/Utils/ZIP/BZip2/BZip2InputStream.cs b/PCRobot/Utils/ZIP/BZip2/BZip2InputStream.cs new file mode 100644 index 0000000..162c9d0 --- /dev/null +++ b/PCRobot/Utils/ZIP/BZip2/BZip2InputStream.cs @@ -0,0 +1,1003 @@ +// BZip2InputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + /// + /// An input stream that decompresses files in the BZip2 format + /// + public class BZip2InputStream : Stream + { + #region Constants + const int START_BLOCK_STATE = 1; + const int RAND_PART_A_STATE = 2; + const int RAND_PART_B_STATE = 3; + const int RAND_PART_C_STATE = 4; + const int NO_RAND_PART_A_STATE = 5; + const int NO_RAND_PART_B_STATE = 6; + const int NO_RAND_PART_C_STATE = 7; + #endregion + #region Constructors + /// + /// Construct instance for reading from stream + /// + /// Data source + public BZip2InputStream(Stream stream) + { + // init arrays + for (int i = 0; i < BZip2Constants.GroupCount; ++i) + { + limit[i] = new int[BZip2Constants.MaximumAlphaSize]; + baseArray[i] = new int[BZip2Constants.MaximumAlphaSize]; + perm[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + BsSetStream(stream); + Initialize(); + InitBlock(); + SetupBlock(); + } + + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + + #region Stream Overrides + /// + /// Gets a value indicating if the stream supports reading + /// + public override bool CanRead + { + get { + return baseStream.CanRead; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek { + get { + return baseStream.CanSeek; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// This property always returns false + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// Gets the length in bytes of the stream. + /// + public override long Length { + get { + return baseStream.Length; + } + } + + /// + /// Gets or sets the streams position. + /// Setting the position is not supported and will throw a NotSupportException + /// + /// Any attempt to set the position + public override long Position { + get { + return baseStream.Position; + } + set { + throw new NotSupportedException("BZip2InputStream position cannot be set"); + } + } + + /// + /// Flushes the stream. + /// + public override void Flush() + { + if (baseStream != null) { + baseStream.Flush(); + } + } + + /// + /// Set the streams position. This operation is not supported and will throw a NotSupportedException + /// + /// A byte offset relative to the parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// The new position of the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("BZip2InputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. + /// This operation is not supported and will throw a NotSupportedExceptionortedException + /// + /// The new length for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("BZip2InputStream SetLength not supported"); + } + + /// + /// Writes a block of bytes to this stream using data from a buffer. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The buffer to source data from. + /// The offset to start obtaining data from. + /// The number of bytes of data to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("BZip2InputStream Write not supported"); + } + + /// + /// Writes a byte to the current position in the file stream. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The value to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("BZip2InputStream WriteByte not supported"); + } + + /// + /// Read a sequence of bytes and advances the read position by one byte. + /// + /// Array of bytes to store values in + /// Offset in array to begin storing data + /// The maximum number of bytes to read + /// The total number of bytes read into the buffer. This might be less + /// than the number of bytes requested if that number of bytes are not + /// currently available or zero if the end of the stream is reached. + /// + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + for (int i = 0; i < count; ++i) { + int rb = ReadByte(); + if (rb == -1) { + return i; + } + buffer[offset + i] = (byte)rb; + } + return count; + } + + /// + /// Closes the stream, releasing any associated resources. + /// + public override void Close() + { + if ( IsStreamOwner && (baseStream != null) ) { + baseStream.Close(); + } + } + /// + /// Read a byte from stream advancing position + /// + /// byte read or -1 on end of stream + public override int ReadByte() + { + if (streamEnd) + { + return -1; // ok + } + + int retChar = currentChar; + switch (currentState) + { + case RAND_PART_B_STATE: + SetupRandPartB(); + break; + case RAND_PART_C_STATE: + SetupRandPartC(); + break; + case NO_RAND_PART_B_STATE: + SetupNoRandPartB(); + break; + case NO_RAND_PART_C_STATE: + SetupNoRandPartC(); + break; + case START_BLOCK_STATE: + case NO_RAND_PART_A_STATE: + case RAND_PART_A_STATE: + break; + default: + break; + } + return retChar; + } + + #endregion + + void MakeMaps() + { + nInUse = 0; + for (int i = 0; i < 256; ++i) { + if (inUse[i]) { + seqToUnseq[nInUse] = (byte)i; + unseqToSeq[i] = (byte)nInUse; + nInUse++; + } + } + } + + void Initialize() + { + char magic1 = BsGetUChar(); + char magic2 = BsGetUChar(); + + char magic3 = BsGetUChar(); + char magic4 = BsGetUChar(); + + if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') { + streamEnd = true; + return; + } + + SetDecompressStructureSizes(magic4 - '0'); + computedCombinedCRC = 0; + } + + void InitBlock() + { + char magic1 = BsGetUChar(); + char magic2 = BsGetUChar(); + char magic3 = BsGetUChar(); + char magic4 = BsGetUChar(); + char magic5 = BsGetUChar(); + char magic6 = BsGetUChar(); + + if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) { + Complete(); + return; + } + + if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) { + BadBlockHeader(); + streamEnd = true; + return; + } + + storedBlockCRC = BsGetInt32(); + + blockRandomised = (BsR(1) == 1); + + GetAndMoveToFrontDecode(); + + mCrc.Reset(); + currentState = START_BLOCK_STATE; + } + + void EndBlock() + { + computedBlockCRC = (int)mCrc.Value; + + // -- A bad CRC is considered a fatal error. -- + if (storedBlockCRC != computedBlockCRC) { + CrcError(); + } + + // 1528150659 + computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31); + computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC; + } + + void Complete() + { + storedCombinedCRC = BsGetInt32(); + if (storedCombinedCRC != (int)computedCombinedCRC) { + CrcError(); + } + + streamEnd = true; + } + + void BsSetStream(Stream stream) + { + baseStream = stream; + bsLive = 0; + bsBuff = 0; + } + + void FillBuffer() + { + int thech = 0; + + try { + thech = baseStream.ReadByte(); + } catch (Exception) { + CompressedStreamEOF(); + } + + if (thech == -1) { + CompressedStreamEOF(); + } + + bsBuff = (bsBuff << 8) | (thech & 0xFF); + bsLive += 8; + } + + int BsR(int n) + { + while (bsLive < n) { + FillBuffer(); + } + + int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1); + bsLive -= n; + return v; + } + + char BsGetUChar() + { + return (char)BsR(8); + } + + int BsGetIntVS(int numBits) + { + return BsR(numBits); + } + + int BsGetInt32() + { + int result = BsR(8); + result = (result << 8) | BsR(8); + result = (result << 8) | BsR(8); + result = (result << 8) | BsR(8); + return result; + } + + void RecvDecodingTables() + { + char[][] len = new char[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + len[i] = new char[BZip2Constants.MaximumAlphaSize]; + } + + bool[] inUse16 = new bool[16]; + + //--- Receive the mapping table --- + for (int i = 0; i < 16; i++) { + inUse16[i] = (BsR(1) == 1); + } + + for (int i = 0; i < 16; i++) { + if (inUse16[i]) { + for (int j = 0; j < 16; j++) { + inUse[i * 16 + j] = (BsR(1) == 1); + } + } else { + for (int j = 0; j < 16; j++) { + inUse[i * 16 + j] = false; + } + } + } + + MakeMaps(); + int alphaSize = nInUse + 2; + + //--- Now the selectors --- + int nGroups = BsR(3); + int nSelectors = BsR(15); + + for (int i = 0; i < nSelectors; i++) { + int j = 0; + while (BsR(1) == 1) { + j++; + } + selectorMtf[i] = (byte)j; + } + + //--- Undo the MTF values for the selectors. --- + byte[] pos = new byte[BZip2Constants.GroupCount]; + for (int v = 0; v < nGroups; v++) { + pos[v] = (byte)v; + } + + for (int i = 0; i < nSelectors; i++) { + int v = selectorMtf[i]; + byte tmp = pos[v]; + while (v > 0) { + pos[v] = pos[v - 1]; + v--; + } + pos[0] = tmp; + selector[i] = tmp; + } + + //--- Now the coding tables --- + for (int t = 0; t < nGroups; t++) { + int curr = BsR(5); + for (int i = 0; i < alphaSize; i++) { + while (BsR(1) == 1) { + if (BsR(1) == 0) { + curr++; + } else { + curr--; + } + } + len[t][i] = (char)curr; + } + } + + //--- Create the Huffman decoding tables --- + for (int t = 0; t < nGroups; t++) { + int minLen = 32; + int maxLen = 0; + for (int i = 0; i < alphaSize; i++) { + maxLen = Math.Max(maxLen, len[t][i]); + minLen = Math.Min(minLen, len[t][i]); + } + HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize); + minLens[t] = minLen; + } + } + + void GetAndMoveToFrontDecode() + { + byte[] yy = new byte[256]; + int nextSym; + + int limitLast = BZip2Constants.BaseBlockSize * blockSize100k; + origPtr = BsGetIntVS(24); + + RecvDecodingTables(); + int EOB = nInUse+1; + int groupNo = -1; + int groupPos = 0; + + /*-- + Setting up the unzftab entries here is not strictly + necessary, but it does save having to do it later + in a separate pass, and so saves a block's worth of + cache misses. + --*/ + for (int i = 0; i <= 255; i++) { + unzftab[i] = 0; + } + + for (int i = 0; i <= 255; i++) { + yy[i] = (byte)i; + } + + last = -1; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + int zt = selector[groupNo]; + int zn = minLens[zt]; + int zvec = BsR(zn); + int zj; + + while (zvec > limit[zt][zn]) { + if (zn > 20) { // the longest code + throw new BZip2Exception("Bzip data error"); + } + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive-1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) { + throw new BZip2Exception("Bzip data error"); + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + + while (true) { + if (nextSym == EOB) { + break; + } + + if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) { + int s = -1; + int n = 1; + do { + if (nextSym == BZip2Constants.RunA) { + s += (0 + 1) * n; + } else if (nextSym == BZip2Constants.RunB) { + s += (1 + 1) * n; + } + + n <<= 1; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + + while (zvec > limit[zt][zn]) { + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive - 1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + } while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB); + + s++; + byte ch = seqToUnseq[yy[0]]; + unzftab[ch] += s; + + while (s > 0) { + last++; + ll8[last] = ch; + s--; + } + + if (last >= limitLast) { + BlockOverrun(); + } + continue; + } else { + last++; + if (last >= limitLast) { + BlockOverrun(); + } + + byte tmp = yy[nextSym - 1]; + unzftab[seqToUnseq[tmp]]++; + ll8[last] = seqToUnseq[tmp]; + + for (int j = nextSym-1; j > 0; --j) { + yy[j] = yy[j - 1]; + } + yy[0] = tmp; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + while (zvec > limit[zt][zn]) { + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive-1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + continue; + } + } + } + + void SetupBlock() + { + int[] cftab = new int[257]; + + cftab[0] = 0; + Array.Copy(unzftab, 0, cftab, 1, 256); + + for (int i = 1; i <= 256; i++) { + cftab[i] += cftab[i - 1]; + } + + for (int i = 0; i <= last; i++) { + byte ch = ll8[i]; + tt[cftab[ch]] = i; + cftab[ch]++; + } + + cftab = null; + + tPos = tt[origPtr]; + + count = 0; + i2 = 0; + ch2 = 256; /*-- not a char and not EOF --*/ + + if (blockRandomised) { + rNToGo = 0; + rTPos = 0; + SetupRandPartA(); + } else { + SetupNoRandPartA(); + } + } + + void SetupRandPartA() + { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + ch2 ^= (int)((rNToGo == 1) ? 1 : 0); + i2++; + + currentChar = ch2; + currentState = RAND_PART_B_STATE; + mCrc.Update(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + void SetupNoRandPartA() + { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + i2++; + + currentChar = ch2; + currentState = NO_RAND_PART_B_STATE; + mCrc.Update(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + void SetupRandPartB() + { + if (ch2 != chPrev) { + currentState = RAND_PART_A_STATE; + count = 1; + SetupRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + z ^= (byte)((rNToGo == 1) ? 1 : 0); + j2 = 0; + currentState = RAND_PART_C_STATE; + SetupRandPartC(); + } else { + currentState = RAND_PART_A_STATE; + SetupRandPartA(); + } + } + } + + void SetupRandPartC() + { + if (j2 < (int)z) { + currentChar = ch2; + mCrc.Update(ch2); + j2++; + } else { + currentState = RAND_PART_A_STATE; + i2++; + count = 0; + SetupRandPartA(); + } + } + + void SetupNoRandPartB() + { + if (ch2 != chPrev) { + currentState = NO_RAND_PART_A_STATE; + count = 1; + SetupNoRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + currentState = NO_RAND_PART_C_STATE; + j2 = 0; + SetupNoRandPartC(); + } else { + currentState = NO_RAND_PART_A_STATE; + SetupNoRandPartA(); + } + } + } + + void SetupNoRandPartC() + { + if (j2 < (int)z) { + currentChar = ch2; + mCrc.Update(ch2); + j2++; + } else { + currentState = NO_RAND_PART_A_STATE; + i2++; + count = 0; + SetupNoRandPartA(); + } + } + + void SetDecompressStructureSizes(int newSize100k) + { + if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) { + throw new BZip2Exception("Invalid block size"); + } + + blockSize100k = newSize100k; + + if (newSize100k == 0) { + return; + } + + int n = BZip2Constants.BaseBlockSize * newSize100k; + ll8 = new byte[n]; + tt = new int[n]; + } + + static void CompressedStreamEOF() + { + throw new EndOfStreamException("BZip2 input stream end of compressed stream"); + } + + static void BlockOverrun() + { + throw new BZip2Exception("BZip2 input stream block overrun"); + } + + static void BadBlockHeader() + { + throw new BZip2Exception("BZip2 input stream bad block header"); + } + + static void CrcError() + { + throw new BZip2Exception("BZip2 input stream crc error"); + } + + static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize) + { + int pp = 0; + + for (int i = minLen; i <= maxLen; ++i) + { + for (int j = 0; j < alphaSize; ++j) + { + if (length[j] == i) + { + perm[pp] = j; + ++pp; + } + } + } + + for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) + { + baseArray[i] = 0; + } + + for (int i = 0; i < alphaSize; i++) + { + ++baseArray[length[i] + 1]; + } + + for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++) + { + baseArray[i] += baseArray[i - 1]; + } + + for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) + { + limit[i] = 0; + } + + int vec = 0; + + for (int i = minLen; i <= maxLen; i++) + { + vec += (baseArray[i + 1] - baseArray[i]); + limit[i] = vec - 1; + vec <<= 1; + } + + for (int i = minLen + 1; i <= maxLen; i++) + { + baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i]; + } + } + + #region Instance Fields + /*-- + index of the last char in the block, so + the block size == last + 1. + --*/ + int last; + + /*-- + index in zptr[] of original string after sorting. + --*/ + int origPtr; + + /*-- + always: in the range 0 .. 9. + The current block size is 100000 * this number. + --*/ + int blockSize100k; + + bool blockRandomised; + + int bsBuff; + int bsLive; + IChecksum mCrc = new StrangeCRC(); + + bool[] inUse = new bool[256]; + int nInUse; + + byte[] seqToUnseq = new byte[256]; + byte[] unseqToSeq = new byte[256]; + + byte[] selector = new byte[BZip2Constants.MaximumSelectors]; + byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors]; + + int[] tt; + byte[] ll8; + + /*-- + freq table collected to save a pass over the data + during decompression. + --*/ + int[] unzftab = new int[256]; + + int[][] limit = new int[BZip2Constants.GroupCount][]; + int[][] baseArray = new int[BZip2Constants.GroupCount][]; + int[][] perm = new int[BZip2Constants.GroupCount][]; + int[] minLens = new int[BZip2Constants.GroupCount]; + + Stream baseStream; + bool streamEnd; + + int currentChar = -1; + + int currentState = START_BLOCK_STATE; + + int storedBlockCRC, storedCombinedCRC; + int computedBlockCRC; + uint computedCombinedCRC; + + int count, chPrev, ch2; + int tPos; + int rNToGo; + int rTPos; + int i2, j2; + byte z; + bool isStreamOwner = true; + #endregion + } +} +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/PCRobot/Utils/ZIP/BZip2/BZip2OutputStream.cs b/PCRobot/Utils/ZIP/BZip2/BZip2OutputStream.cs new file mode 100644 index 0000000..582f7a4 --- /dev/null +++ b/PCRobot/Utils/ZIP/BZip2/BZip2OutputStream.cs @@ -0,0 +1,1916 @@ +// BZip2OutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + // TODO: Update to BZip2 1.0.1, 1.0.2 + + /// + /// An output stream that compresses into the BZip2 format + /// including file header chars into another stream. + /// + public class BZip2OutputStream : Stream + { + #region Constants + const int SETMASK = (1 << 21); + const int CLEARMASK = (~SETMASK); + const int GREATER_ICOST = 15; + const int LESSER_ICOST = 0; + const int SMALL_THRESH = 20; + const int DEPTH_THRESH = 10; + + /*-- + If you are ever unlucky/improbable enough + to get a stack overflow whilst sorting, + increase the following constant and try + again. In practice I have never seen the + stack go above 27 elems, so the following + limit seems very generous. + --*/ + const int QSORT_STACK_SIZE = 1000; + + /*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. + --*/ + readonly int[] increments = new int[] { + 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 + }; + #endregion + + #region Constructors + /// + /// Construct a default output stream with maximum block size + /// + /// The stream to write BZip data onto. + public BZip2OutputStream(Stream stream) : this(stream, 9) + { + } + + /// + /// Initialise a new instance of the + /// for the specified stream, using the given blocksize. + /// + /// The stream to write compressed data to. + /// The block size to use. + /// + /// Valid block sizes are in the range 1..9, with 1 giving + /// the lowest compression and 9 the highest. + /// + public BZip2OutputStream(Stream stream, int blockSize) + { + BsSetStream(stream); + + workFactor = 50; + if (blockSize > 9) { + blockSize = 9; + } + + if (blockSize < 1) { + blockSize = 1; + } + blockSize100k = blockSize; + AllocateCompressStructures(); + Initialize(); + InitBlock(); + } + #endregion + + #region Destructor + /// + /// Ensures that resources are freed and other cleanup operations + /// are performed when the garbage collector reclaims the BZip2OutputStream. + /// + ~BZip2OutputStream() + { + Dispose(false); + } + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + + #region Stream overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing + /// + public override bool CanWrite { + get { + return baseStream.CanWrite; + } + } + + /// + /// Gets the length in bytes of the stream + /// + public override long Length { + get { + return baseStream.Length; + } + } + + /// + /// Gets or sets the current position of this stream. + /// + public override long Position { + get { + return baseStream.Position; + } + set { + throw new NotSupportedException("BZip2OutputStream position cannot be set"); + } + } + + /// + /// Sets the current position of this stream to the given value. + /// + /// The point relative to the offset from which to being seeking. + /// The reference point from which to begin seeking. + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("BZip2OutputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. + /// + /// The new stream length. + public override void SetLength(long value) + { + throw new NotSupportedException("BZip2OutputStream SetLength not supported"); + } + + /// + /// Read a byte from the stream advancing the position. + /// + /// The byte read cast to an int; -1 if end of stream. + public override int ReadByte() + { + throw new NotSupportedException("BZip2OutputStream ReadByte not supported"); + } + + /// + /// Read a block of bytes + /// + /// The buffer to read into. + /// The offset in the buffer to start storing data at. + /// The maximum number of bytes to read. + /// The total number of bytes read. This might be less than the number of bytes + /// requested if that number of bytes are not currently available, or zero + /// if the end of the stream is reached. + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("BZip2OutputStream Read not supported"); + } + + /// + /// Write a block of bytes to the stream + /// + /// The buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + public override void Write(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( count < 0 ) + { + throw new ArgumentOutOfRangeException("count"); + } + + if ( buffer.Length - offset < count ) + { + throw new ArgumentException("Offset/count out of range"); + } + + for (int i = 0; i < count; ++i) { + WriteByte(buffer[offset + i]); + } + } + + /// + /// Write a byte to the stream. + /// + /// The byte to write to the stream. + public override void WriteByte(byte value) + { + int b = (256 + value) % 256; + if (currentChar != -1) { + if (currentChar == b) { + runLength++; + if (runLength > 254) { + WriteRun(); + currentChar = -1; + runLength = 0; + } + } else { + WriteRun(); + runLength = 1; + currentChar = b; + } + } else { + currentChar = b; + runLength++; + } + } + + /// + /// End the current block and end compression. + /// Close the stream and free any resources + /// + public override void Close() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + void MakeMaps() + { + nInUse = 0; + for (int i = 0; i < 256; i++) { + if (inUse[i]) { + seqToUnseq[nInUse] = (char)i; + unseqToSeq[i] = (char)nInUse; + nInUse++; + } + } + } + + /// + /// Get the number of bytes written to output. + /// + void WriteRun() + { + if (last < allowableBlockSize) { + inUse[currentChar] = true; + for (int i = 0; i < runLength; i++) { + mCrc.Update(currentChar); + } + + switch (runLength) { + case 1: + last++; + block[last + 1] = (byte)currentChar; + break; + case 2: + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + break; + case 3: + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + break; + default: + inUse[runLength - 4] = true; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)(runLength - 4); + break; + } + } else { + EndBlock(); + InitBlock(); + WriteRun(); + } + } + + /// + /// Get the number of bytes written to the output. + /// + public int BytesWritten + { + get { return bytesOut; } + } + + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. +#if NET_1_0 || NET_1_1 || NETCF_1_0 + protected virtual void Dispose(bool disposing) +#else + override protected void Dispose(bool disposing) +#endif + { + try { +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + base.Dispose(disposing); +#endif + if( !disposed_ ) { + disposed_=true; + + if( runLength>0 ) { + WriteRun(); + } + + currentChar=-1; + EndBlock(); + EndCompression(); + Flush(); + } + } + finally { + if ( disposing ) { + if ( IsStreamOwner ) { + baseStream.Close(); + } + } + } + } + + /// + /// Flush output buffers + /// + public override void Flush() + { + baseStream.Flush(); + } + + void Initialize() + { + bytesOut = 0; + nBlocksRandomised = 0; + + /*--- Write header `magic' bytes indicating file-format == huffmanised, + followed by a digit indicating blockSize100k. + ---*/ + + BsPutUChar('B'); + BsPutUChar('Z'); + + BsPutUChar('h'); + BsPutUChar('0' + blockSize100k); + + combinedCRC = 0; + } + + void InitBlock() + { + mCrc.Reset(); + last = -1; + + for (int i = 0; i < 256; i++) { + inUse[i] = false; + } + + /*--- 20 is just a paranoia constant ---*/ + allowableBlockSize = BZip2Constants.BaseBlockSize * blockSize100k - 20; + } + + void EndBlock() + { + if (last < 0) { // dont do anything for empty files, (makes empty files compatible with original Bzip) + return; + } + + blockCRC = unchecked((uint)mCrc.Value); + combinedCRC = (combinedCRC << 1) | (combinedCRC >> 31); + combinedCRC ^= blockCRC; + + /*-- sort the block and establish position of original string --*/ + DoReversibleTransformation(); + + /*-- + A 6-byte block header, the value chosen arbitrarily + as 0x314159265359 :-). A 32 bit value does not really + give a strong enough guarantee that the value will not + appear by chance in the compressed datastream. Worst-case + probability of this event, for a 900k block, is about + 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits. + For a compressed file of size 100Gb -- about 100000 blocks -- + only a 48-bit marker will do. NB: normal compression/ + decompression do *not* rely on these statistical properties. + They are only important when trying to recover blocks from + damaged files. + --*/ + BsPutUChar(0x31); + BsPutUChar(0x41); + BsPutUChar(0x59); + BsPutUChar(0x26); + BsPutUChar(0x53); + BsPutUChar(0x59); + + /*-- Now the block's CRC, so it is in a known place. --*/ + unchecked { + BsPutint((int)blockCRC); + } + + /*-- Now a single bit indicating randomisation. --*/ + if (blockRandomised) { + BsW(1,1); + nBlocksRandomised++; + } else { + BsW(1,0); + } + + /*-- Finally, block's contents proper. --*/ + MoveToFrontCodeAndSend(); + } + + void EndCompression() + { + /*-- + Now another magic 48-bit number, 0x177245385090, to + indicate the end of the last block. (sqrt(pi), if + you want to know. I did want to use e, but it contains + too much repetition -- 27 18 28 18 28 46 -- for me + to feel statistically comfortable. Call me paranoid.) + --*/ + BsPutUChar(0x17); + BsPutUChar(0x72); + BsPutUChar(0x45); + BsPutUChar(0x38); + BsPutUChar(0x50); + BsPutUChar(0x90); + + unchecked { + BsPutint((int)combinedCRC); + } + + BsFinishedWithStream(); + } + + void BsSetStream(Stream stream) + { + baseStream = stream; + bsLive = 0; + bsBuff = 0; + bytesOut = 0; + } + + void BsFinishedWithStream() + { + while (bsLive > 0) + { + int ch = (bsBuff >> 24); + baseStream.WriteByte((byte)ch); // write 8-bit + bsBuff <<= 8; + bsLive -= 8; + bytesOut++; + } + } + + void BsW(int n, int v) + { + while (bsLive >= 8) { + int ch = (bsBuff >> 24); + unchecked{baseStream.WriteByte((byte)ch);} // write 8-bit + bsBuff <<= 8; + bsLive -= 8; + ++bytesOut; + } + bsBuff |= (v << (32 - bsLive - n)); + bsLive += n; + } + + void BsPutUChar(int c) + { + BsW(8, c); + } + + void BsPutint(int u) + { + BsW(8, (u >> 24) & 0xFF); + BsW(8, (u >> 16) & 0xFF); + BsW(8, (u >> 8) & 0xFF); + BsW(8, u & 0xFF); + } + + void BsPutIntVS(int numBits, int c) + { + BsW(numBits, c); + } + + void SendMTFValues() + { + char[][] len = new char[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + len[i] = new char[BZip2Constants.MaximumAlphaSize]; + } + + int gs, ge, totc, bt, bc, iter; + int nSelectors = 0, alphaSize, minLen, maxLen, selCtr; + int nGroups; + + alphaSize = nInUse + 2; + for (int t = 0; t < BZip2Constants.GroupCount; t++) { + for (int v = 0; v < alphaSize; v++) { + len[t][v] = (char)GREATER_ICOST; + } + } + + /*--- Decide how many coding tables to use ---*/ + if (nMTF <= 0) { + Panic(); + } + + if (nMTF < 200) { + nGroups = 2; + } else if (nMTF < 600) { + nGroups = 3; + } else if (nMTF < 1200) { + nGroups = 4; + } else if (nMTF < 2400) { + nGroups = 5; + } else { + nGroups = 6; + } + + /*--- Generate an initial set of coding tables ---*/ + int nPart = nGroups; + int remF = nMTF; + gs = 0; + while (nPart > 0) { + int tFreq = remF / nPart; + int aFreq = 0; + ge = gs - 1; + while (aFreq < tFreq && ge < alphaSize - 1) { + ge++; + aFreq += mtfFreq[ge]; + } + + if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups - nPart) % 2 == 1)) { + aFreq -= mtfFreq[ge]; + ge--; + } + + for (int v = 0; v < alphaSize; v++) { + if (v >= gs && v <= ge) { + len[nPart - 1][v] = (char)LESSER_ICOST; + } else { + len[nPart - 1][v] = (char)GREATER_ICOST; + } + } + + nPart--; + gs = ge + 1; + remF -= aFreq; + } + + int[][] rfreq = new int[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + rfreq[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + int[] fave = new int[BZip2Constants.GroupCount]; + short[] cost = new short[BZip2Constants.GroupCount]; + /*--- + Iterate up to N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZip2Constants.NumberOfIterations; ++iter) { + for (int t = 0; t < nGroups; ++t) { + fave[t] = 0; + } + + for (int t = 0; t < nGroups; ++t) { + for (int v = 0; v < alphaSize; ++v) { + rfreq[t][v] = 0; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (true) { + /*--- Set group start & end marks. --*/ + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.GroupSize - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (int t = 0; t < nGroups; t++) { + cost[t] = 0; + } + + if (nGroups == 6) { + short cost0, cost1, cost2, cost3, cost4, cost5; + cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0; + for (int i = gs; i <= ge; ++i) { + short icv = szptr[i]; + cost0 += (short)len[0][icv]; + cost1 += (short)len[1][icv]; + cost2 += (short)len[2][icv]; + cost3 += (short)len[3][icv]; + cost4 += (short)len[4][icv]; + cost5 += (short)len[5][icv]; + } + cost[0] = cost0; + cost[1] = cost1; + cost[2] = cost2; + cost[3] = cost3; + cost[4] = cost4; + cost[5] = cost5; + } else { + for (int i = gs; i <= ge; ++i) { + short icv = szptr[i]; + for (int t = 0; t < nGroups; t++) { + cost[t] += (short)len[t][icv]; + } + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; + bt = -1; + for (int t = 0; t < nGroups; ++t) { + if (cost[t] < bc) { + bc = cost[t]; + bt = t; + } + } + totc += bc; + fave[bt]++; + selector[nSelectors] = (char)bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + for (int i = gs; i <= ge; ++i) { + ++rfreq[bt][szptr[i]]; + } + + gs = ge+1; + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + for (int t = 0; t < nGroups; ++t) { + HbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20); + } + } + + rfreq = null; + fave = null; + cost = null; + + if (!(nGroups < 8)) { + Panic(); + } + + if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZip2Constants.GroupSize)))) { + Panic(); + } + + /*--- Compute MTF values for the selectors. ---*/ + char[] pos = new char[BZip2Constants.GroupCount]; + char ll_i, tmp2, tmp; + + for (int i = 0; i < nGroups; i++) { + pos[i] = (char)i; + } + + for (int i = 0; i < nSelectors; i++) { + ll_i = selector[i]; + int j = 0; + tmp = pos[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + } + pos[0] = tmp; + selectorMtf[i] = (char)j; + } + + int[][] code = new int[BZip2Constants.GroupCount][]; + + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + code[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + /*--- Assign actual codes for the tables. --*/ + for (int t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (int i = 0; i < alphaSize; i++) { + if (len[t][i] > maxLen) { + maxLen = len[t][i]; + } + if (len[t][i] < minLen) { + minLen = len[t][i]; + } + } + if (maxLen > 20) { + Panic(); + } + if (minLen < 1) { + Panic(); + } + HbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize); + } + + /*--- Transmit the mapping table. ---*/ + bool[] inUse16 = new bool[16]; + for (int i = 0; i < 16; ++i) { + inUse16[i] = false; + for (int j = 0; j < 16; ++j) { + if (inUse[i * 16 + j]) { + inUse16[i] = true; + } + } + } + + for (int i = 0; i < 16; ++i) { + if (inUse16[i]) { + BsW(1,1); + } else { + BsW(1,0); + } + } + + for (int i = 0; i < 16; ++i) { + if (inUse16[i]) { + for (int j = 0; j < 16; ++j) { + if (inUse[i * 16 + j]) { + BsW(1,1); + } else { + BsW(1,0); + } + } + } + } + + /*--- Now the selectors. ---*/ + BsW(3, nGroups); + BsW(15, nSelectors); + for (int i = 0; i < nSelectors; ++i) { + for (int j = 0; j < selectorMtf[i]; ++j) { + BsW(1,1); + } + BsW(1,0); + } + + /*--- Now the coding tables. ---*/ + for (int t = 0; t < nGroups; ++t) { + int curr = len[t][0]; + BsW(5, curr); + for (int i = 0; i < alphaSize; ++i) { + while (curr < len[t][i]) { + BsW(2, 2); + curr++; /* 10 */ + } + while (curr > len[t][i]) { + BsW(2, 3); + curr--; /* 11 */ + } + BsW (1, 0); + } + } + + /*--- And finally, the block data proper ---*/ + selCtr = 0; + gs = 0; + while (true) { + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.GroupSize - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + for (int i = gs; i <= ge; i++) { + BsW(len[selector[selCtr]][szptr[i]], code[selector[selCtr]][szptr[i]]); + } + + gs = ge + 1; + ++selCtr; + } + if (!(selCtr == nSelectors)) { + Panic(); + } + } + + void MoveToFrontCodeAndSend () + { + BsPutIntVS(24, origPtr); + GenerateMTFValues(); + SendMTFValues(); + } + + void SimpleSort(int lo, int hi, int d) + { + int i, j, h, bigN, hp; + int v; + + bigN = hi - lo + 1; + if (bigN < 2) { + return; + } + + hp = 0; + while (increments[hp] < bigN) { + hp++; + } + hp--; + + for (; hp >= 0; hp--) { + h = increments[hp]; + + i = lo + h; + while (true) { + /*-- copy 1 --*/ + if (i > hi) + break; + v = zptr[i]; + j = i; + while (FullGtU(zptr[j-h]+d, v+d)) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) + break; + } + zptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU ( zptr[j-h]+d, v+d )) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU ( zptr[j-h]+d, v+d)) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + if (workDone > workLimit && firstAttempt) { + return; + } + } + } + } + + void Vswap(int p1, int p2, int n ) + { + int temp = 0; + while (n > 0) { + temp = zptr[p1]; + zptr[p1] = zptr[p2]; + zptr[p2] = temp; + p1++; + p2++; + n--; + } + } + + void QSort3(int loSt, int hiSt, int dSt) + { + int unLo, unHi, ltLo, gtHi, med, n, m; + int lo, hi, d; + + StackElement[] stack = new StackElement[QSORT_STACK_SIZE]; + + int sp = 0; + + stack[sp].ll = loSt; + stack[sp].hh = hiSt; + stack[sp].dd = dSt; + sp++; + + while (sp > 0) { + if (sp >= QSORT_STACK_SIZE) { + Panic(); + } + + sp--; + lo = stack[sp].ll; + hi = stack[sp].hh; + d = stack[sp].dd; + + if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) { + SimpleSort(lo, hi, d); + if (workDone > workLimit && firstAttempt) { + return; + } + continue; + } + + med = Med3(block[zptr[lo] + d + 1], + block[zptr[hi ] + d + 1], + block[zptr[(lo + hi) >> 1] + d + 1]); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (true) { + while (true) { + if (unLo > unHi) { + break; + } + n = ((int)block[zptr[unLo]+d + 1]) - med; + if (n == 0) { + int temp = zptr[unLo]; + zptr[unLo] = zptr[ltLo]; + zptr[ltLo] = temp; + ltLo++; + unLo++; + continue; + } + if (n > 0) { + break; + } + unLo++; + } + + while (true) { + if (unLo > unHi) { + break; + } + n = ((int)block[zptr[unHi]+d + 1]) - med; + if (n == 0) { + int temp = zptr[unHi]; + zptr[unHi] = zptr[gtHi]; + zptr[gtHi] = temp; + gtHi--; + unHi--; + continue; + } + if (n < 0) { + break; + } + unHi--; + } + + if (unLo > unHi) { + break; + } + + { + int temp = zptr[unLo]; + zptr[unLo] = zptr[unHi]; + zptr[unHi] = temp; + unLo++; + unHi--; + } + } + + if (gtHi < ltLo) { + stack[sp].ll = lo; + stack[sp].hh = hi; + stack[sp].dd = d+1; + sp++; + continue; + } + + n = ((ltLo-lo) < (unLo-ltLo)) ? (ltLo-lo) : (unLo-ltLo); + Vswap(lo, unLo-n, n); + m = ((hi-gtHi) < (gtHi-unHi)) ? (hi-gtHi) : (gtHi-unHi); + Vswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + stack[sp].ll = lo; + stack[sp].hh = n; + stack[sp].dd = d; + sp++; + + stack[sp].ll = n + 1; + stack[sp].hh = m - 1; + stack[sp].dd = d+1; + sp++; + + stack[sp].ll = m; + stack[sp].hh = hi; + stack[sp].dd = d; + sp++; + } + } + + void MainSort() + { + int i, j, ss, sb; + int[] runningOrder = new int[256]; + int[] copy = new int[256]; + bool[] bigDone = new bool[256]; + int c1, c2; + int numQSorted; + + /*-- + In the various block-sized structures, live data runs + from 0 to last+NUM_OVERSHOOT_BYTES inclusive. First, + set up the overshoot area for block. + --*/ + + // if (verbosity >= 4) fprintf ( stderr, " sort initialise ...\n" ); + for (i = 0; i < BZip2Constants.OvershootBytes; i++) { + block[last + i + 2] = block[(i % (last + 1)) + 1]; + } + for (i = 0; i <= last + BZip2Constants.OvershootBytes; i++) { + quadrant[i] = 0; + } + + block[0] = (byte)(block[last + 1]); + + if (last < 4000) { + /*-- + Use simpleSort(), since the full sorting mechanism + has quite a large constant overhead. + --*/ + for (i = 0; i <= last; i++) { + zptr[i] = i; + } + firstAttempt = false; + workDone = workLimit = 0; + SimpleSort(0, last, 0); + } else { + numQSorted = 0; + for (i = 0; i <= 255; i++) { + bigDone[i] = false; + } + for (i = 0; i <= 65536; i++) { + ftab[i] = 0; + } + + c1 = block[0]; + for (i = 0; i <= last; i++) { + c2 = block[i + 1]; + ftab[(c1 << 8) + c2]++; + c1 = c2; + } + + for (i = 1; i <= 65536; i++) { + ftab[i] += ftab[i - 1]; + } + + c1 = block[1]; + for (i = 0; i < last; i++) { + c2 = block[i + 2]; + j = (c1 << 8) + c2; + c1 = c2; + ftab[j]--; + zptr[ftab[j]] = i; + } + + j = ((block[last + 1]) << 8) + (block[1]); + ftab[j]--; + zptr[ftab[j]] = last; + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + + for (i = 0; i <= 255; i++) { + runningOrder[i] = i; + } + + int vv; + int h = 1; + do { + h = 3 * h + 1; + } while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ((ftab[((runningOrder[j-h])+1) << 8] - ftab[(runningOrder[j-h]) << 8]) > (ftab[((vv)+1) << 8] - ftab[(vv) << 8])) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) { + break; + } + } + runningOrder[j] = vv; + } + } while (h != 1); + + /*-- + The main sorting loop. + --*/ + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + --*/ + ss = runningOrder[i]; + + /*-- + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j]. Hopefully + previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + sb = (ss << 8) + j; + if(!((ftab[sb] & SETMASK) == SETMASK)) { + int lo = ftab[sb] & CLEARMASK; + int hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + QSort3(lo, hi, 2); + numQSorted += (hi - lo + 1); + if (workDone > workLimit && firstAttempt) { + return; + } + } + ftab[sb] |= SETMASK; + } + } + + /*-- + The ss big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + --*/ + bigDone[ss] = true; + + if (i < 255) { + int bbStart = ftab[ss << 8] & CLEARMASK; + int bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + int shifts = 0; + + while ((bbSize >> shifts) > 65534) { + shifts++; + } + + for (j = 0; j < bbSize; j++) { + int a2update = zptr[bbStart + j]; + int qVal = (j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZip2Constants.OvershootBytes) { + quadrant[a2update + last + 1] = qVal; + } + } + + if (!(((bbSize-1) >> shifts) <= 65535)) { + Panic(); + } + } + + /*-- + Now scan this big bucket so as to synthesise the + sorted order for small buckets [t, ss] for all t != ss. + --*/ + for (j = 0; j <= 255; j++) { + copy[j] = ftab[(j << 8) + ss] & CLEARMASK; + } + + for (j = ftab[ss << 8] & CLEARMASK; j < (ftab[(ss+1) << 8] & CLEARMASK); j++) { + c1 = block[zptr[j]]; + if (!bigDone[c1]) { + zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1; + copy[c1] ++; + } + } + + for (j = 0; j <= 255; j++) { + ftab[(j << 8) + ss] |= SETMASK; + } + } + } + } + + void RandomiseBlock() + { + int i; + int rNToGo = 0; + int rTPos = 0; + for (i = 0; i < 256; i++) { + inUse[i] = false; + } + + for (i = 0; i <= last; i++) { + if (rNToGo == 0) { + rNToGo = (int)BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + block[i + 1] ^= (byte)((rNToGo == 1) ? 1 : 0); + // handle 16 bit signed numbers + block[i + 1] &= 0xFF; + + inUse[block[i + 1]] = true; + } + } + + void DoReversibleTransformation() + { + workLimit = workFactor * last; + workDone = 0; + blockRandomised = false; + firstAttempt = true; + + MainSort(); + + if (workDone > workLimit && firstAttempt) { + RandomiseBlock(); + workLimit = workDone = 0; + blockRandomised = true; + firstAttempt = false; + MainSort(); + } + + origPtr = -1; + for (int i = 0; i <= last; i++) { + if (zptr[i] == 0) { + origPtr = i; + break; + } + } + + if (origPtr == -1) { + Panic(); + } + } + + bool FullGtU(int i1, int i2) + { + int k; + byte c1, c2; + int s1, s2; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + k = last + 1; + + do { + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + if (i1 > last) { + i1 -= last; + i1--; + } + if (i2 > last) { + i2 -= last; + i2--; + } + + k -= 4; + ++workDone; + } while (k >= 0); + + return false; + } + + void AllocateCompressStructures() + { + int n = BZip2Constants.BaseBlockSize * blockSize100k; + block = new byte[(n + 1 + BZip2Constants.OvershootBytes)]; + quadrant = new int[(n + BZip2Constants.OvershootBytes)]; + zptr = new int[n]; + ftab = new int[65537]; + + if (block == null || quadrant == null || zptr == null || ftab == null) { + // int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537; + // compressOutOfMemory ( totalDraw, n ); + } + + /* + The back end needs a place to store the MTF values + whilst it calculates the coding tables. We could + put them in the zptr array. However, these values + will fit in a short, so we overlay szptr at the + start of zptr, in the hope of reducing the number + of cache misses induced by the multiple traversals + of the MTF values when calculating coding tables. + Seems to improve compression speed by about 1%. + */ + // szptr = zptr; + + + szptr = new short[2 * n]; + } + + void GenerateMTFValues() + { + char[] yy = new char[256]; + int i, j; + char tmp; + char tmp2; + int zPend; + int wr; + int EOB; + + MakeMaps(); + EOB = nInUse+1; + + for (i = 0; i <= EOB; i++) { + mtfFreq[i] = 0; + } + + wr = 0; + zPend = 0; + for (i = 0; i < nInUse; i++) { + yy[i] = (char) i; + } + + + for (i = 0; i <= last; i++) { + char ll_i; + + ll_i = unseqToSeq[block[zptr[i]]]; + + j = 0; + tmp = yy[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = yy[j]; + yy[j] = tmp2; + } + yy[0] = tmp; + + if (j == 0) { + zPend++; + } else { + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short)BZip2Constants.RunA; + wr++; + mtfFreq[BZip2Constants.RunA]++; + break; + case 1: + szptr[wr] = (short)BZip2Constants.RunB; + wr++; + mtfFreq[BZip2Constants.RunB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + zPend = 0; + } + szptr[wr] = (short)(j + 1); + wr++; + mtfFreq[j + 1]++; + } + } + + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short)BZip2Constants.RunA; + wr++; + mtfFreq[BZip2Constants.RunA]++; + break; + case 1: + szptr[wr] = (short)BZip2Constants.RunB; + wr++; + mtfFreq[BZip2Constants.RunB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + } + + szptr[wr] = (short)EOB; + wr++; + mtfFreq[EOB]++; + + nMTF = wr; + } + + static void Panic() + { + throw new BZip2Exception("BZip2 output stream panic"); + } + + static void HbMakeCodeLengths(char[] len, int[] freq, int alphaSize, int maxLen) + { + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + int nNodes, nHeap, n1, n2, j, k; + bool tooLong; + + int[] heap = new int[BZip2Constants.MaximumAlphaSize + 2]; + int[] weight = new int[BZip2Constants.MaximumAlphaSize * 2]; + int[] parent = new int[BZip2Constants.MaximumAlphaSize * 2]; + + for (int i = 0; i < alphaSize; ++i) + { + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + } + + while (true) + { + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (int i = 1; i <= alphaSize; ++i) + { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + int zz = nHeap; + int tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) + { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + if (!(nHeap < (BZip2Constants.MaximumAlphaSize+2))) + { + Panic(); + } + + while (nHeap > 1) + { + n1 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + int zz = 1; + int yy = 0; + int tmp = heap[zz]; + while (true) + { + yy = zz << 1; + if (yy > nHeap) + { + break; + } + if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) + { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) + { + break; + } + + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + n2 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + + zz = 1; + yy = 0; + tmp = heap[zz]; + while (true) + { + yy = zz << 1; + if (yy > nHeap) + { + break; + } + if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) + { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) + { + break; + } + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + nNodes++; + parent[n1] = parent[n2] = nNodes; + + weight[nNodes] = (int)((weight[n1] & 0xffffff00) + (weight[n2] & 0xffffff00)) | + (int)(1 + (((weight[n1] & 0x000000ff) > (weight[n2] & 0x000000ff)) ? (weight[n1] & 0x000000ff) : (weight[n2] & 0x000000ff))); + + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + + zz = nHeap; + tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) + { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + if (!(nNodes < (BZip2Constants.MaximumAlphaSize * 2))) + { + Panic(); + } + + tooLong = false; + for (int i = 1; i <= alphaSize; ++i) + { + j = 0; + k = i; + while (parent[k] >= 0) + { + k = parent[k]; + j++; + } + len[i - 1] = (char)j; + if (j > maxLen) + { + tooLong = true; + } + } + + if (!tooLong) + { + break; + } + + for (int i = 1; i < alphaSize; ++i) + { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } + } + + static void HbAssignCodes (int[] code, char[] length, int minLen, int maxLen, int alphaSize) + { + int vec = 0; + for (int n = minLen; n <= maxLen; ++n) + { + for (int i = 0; i < alphaSize; ++i) + { + if (length[i] == n) + { + code[i] = vec; + ++vec; + } + } + vec <<= 1; + } + } + + static byte Med3(byte a, byte b, byte c ) + { + byte t; + if (a > b) + { + t = a; + a = b; + b = t; + } + if (b > c) + { + t = b; + b = c; + c = t; + } + if (a > b) + { + b = a; + } + return b; + } + + struct StackElement + { + public int ll; + public int hh; + public int dd; + } + + #region Instance Fields + bool isStreamOwner = true; + + /*-- + index of the last char in the block, so + the block size == last + 1. + --*/ + int last; + + /*-- + index in zptr[] of original string after sorting. + --*/ + int origPtr; + + /*-- + always: in the range 0 .. 9. + The current block size is 100000 * this number. + --*/ + int blockSize100k; + + bool blockRandomised; + + int bytesOut; + int bsBuff; + int bsLive; + IChecksum mCrc = new StrangeCRC(); + + bool[] inUse = new bool[256]; + int nInUse; + + char[] seqToUnseq = new char[256]; + char[] unseqToSeq = new char[256]; + + char[] selector = new char[BZip2Constants.MaximumSelectors]; + char[] selectorMtf = new char[BZip2Constants.MaximumSelectors]; + + byte[] block; + int[] quadrant; + int[] zptr; + short[] szptr; + int[] ftab; + + int nMTF; + + int[] mtfFreq = new int[BZip2Constants.MaximumAlphaSize]; + + /* + * Used when sorting. If too many long comparisons + * happen, we stop sorting, randomise the block + * slightly, and try again. + */ + int workFactor; + int workDone; + int workLimit; + bool firstAttempt; + int nBlocksRandomised; + + int currentChar = -1; + int runLength; + uint blockCRC, combinedCRC; + int allowableBlockSize; + Stream baseStream; + bool disposed_; + #endregion + } +} + +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/PCRobot/Utils/ZIP/Checksums/Adler32.cs b/PCRobot/Utils/ZIP/Checksums/Adler32.cs new file mode 100644 index 0000000..6e358bc --- /dev/null +++ b/PCRobot/Utils/ZIP/Checksums/Adler32.cs @@ -0,0 +1,237 @@ +// Adler32.cs - Computes Adler32 data checksum of a data stream +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Computes Adler32 checksum for a stream of data. An Adler32 + /// checksum is not as reliable as a CRC32 checksum, but a lot faster to + /// compute. + /// + /// The specification for Adler32 may be found in RFC 1950. + /// ZLIB Compressed Data Format Specification version 3.3) + /// + /// + /// From that document: + /// + /// "ADLER32 (Adler-32 checksum) + /// This contains a checksum value of the uncompressed data + /// (excluding any dictionary data) computed according to Adler-32 + /// algorithm. This algorithm is a 32-bit extension and improvement + /// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + /// standard. + /// + /// Adler-32 is composed of two sums accumulated per byte: s1 is + /// the sum of all bytes, s2 is the sum of all s1 values. Both sums + /// are done modulo 65521. s1 is initialized to 1, s2 to zero. The + /// Adler-32 checksum is stored as s2*65536 + s1 in most- + /// significant-byte first (network) order." + /// + /// "8.2. The Adler-32 algorithm + /// + /// The Adler-32 algorithm is much faster than the CRC32 algorithm yet + /// still provides an extremely low probability of undetected errors. + /// + /// The modulo on unsigned long accumulators can be delayed for 5552 + /// bytes, so the modulo operation time is negligible. If the bytes + /// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + /// and order sensitive, unlike the first sum, which is just a + /// checksum. That 65521 is prime is important to avoid a possible + /// large class of two-byte errors that leave the check unchanged. + /// (The Fletcher checksum uses 255, which is not prime and which also + /// makes the Fletcher check insensitive to single byte changes 0 - + /// 255.) + /// + /// The sum s1 is initialized to 1 instead of zero to make the length + /// of the sequence part of s2, so that the length does not have to be + /// checked separately. (Any sequence of zeroes has a Fletcher + /// checksum of zero.)" + /// + /// + /// + public sealed class Adler32 : IChecksum + { + /// + /// largest prime smaller than 65536 + /// + const uint BASE = 65521; + + /// + /// Returns the Adler32 data checksum computed so far. + /// + public long Value { + get { + return checksum; + } + } + + /// + /// Creates a new instance of the Adler32 class. + /// The checksum starts off with a value of 1. + /// + public Adler32() + { + Reset(); + } + + /// + /// Resets the Adler32 checksum to the initial value. + /// + public void Reset() + { + checksum = 1; + } + + /// + /// Updates the checksum with a byte value. + /// + /// + /// The data value to add. The high byte of the int is ignored. + /// + public void Update(int value) + { + // We could make a length 1 byte array and call update again, but I + // would rather not have that overhead + uint s1 = checksum & 0xFFFF; + uint s2 = checksum >> 16; + + s1 = (s1 + ((uint)value & 0xFF)) % BASE; + s2 = (s1 + s2) % BASE; + + checksum = (s2 << 16) + s1; + } + + /// + /// Updates the checksum with an array of bytes. + /// + /// + /// The source of the data to update with. + /// + public void Update(byte[] buffer) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Updates the checksum with the bytes taken from the array. + /// + /// + /// an array of bytes + /// + /// + /// the start of the data used for this update + /// + /// + /// the number of bytes to use for this update + /// + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if (offset < 0) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "cannot be negative"); +#endif + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "cannot be negative"); +#endif + } + + if (offset >= buffer.Length) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "not a valid index into buffer"); +#endif + } + + if (offset + count > buffer.Length) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "exceeds buffer size"); +#endif + } + + //(By Per Bothner) + uint s1 = checksum & 0xFFFF; + uint s2 = checksum >> 16; + + while (count > 0) { + // We can defer the modulo operation: + // s1 maximally grows from 65521 to 65521 + 255 * 3800 + // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 + int n = 3800; + if (n > count) { + n = count; + } + count -= n; + while (--n >= 0) { + s1 = s1 + (uint)(buffer[offset++] & 0xff); + s2 = s2 + s1; + } + s1 %= BASE; + s2 %= BASE; + } + + checksum = (s2 << 16) | s1; + } + + #region Instance Fields + uint checksum; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Checksums/CRC32.cs b/PCRobot/Utils/ZIP/Checksums/CRC32.cs new file mode 100644 index 0000000..41d5b4b --- /dev/null +++ b/PCRobot/Utils/ZIP/Checksums/CRC32.cs @@ -0,0 +1,223 @@ +// CRC32.cs - Computes CRC32 data checksum of a data stream +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + /// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + /// + /// Polynomials over GF(2) are represented in binary, one bit per coefficient, + /// with the lowest powers in the most significant bit. Then adding polynomials + /// is just exclusive-or, and multiplying a polynomial by x is a right shift by + /// one. If we call the above polynomial p, and represent a byte as the + /// polynomial q, also with the lowest power in the most significant bit (so the + /// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + /// where a mod b means the remainder after dividing a by b. + /// + /// This calculation is done using the shift-register method of multiplying and + /// taking the remainder. The register is initialized to zero, and for each + /// incoming bit, x^32 is added mod p to the register if the bit is a one (where + /// x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + /// x (which is shifting right by one and adding x^32 mod p if the bit shifted + /// out is a one). We start with the highest power (least significant bit) of + /// q and repeat for all eight bits of q. + /// + /// The table is simply the CRC of all possible eight bit values. This is all + /// the information needed to generate CRC's on data a byte at a time for all + /// combinations of CRC register values and incoming bytes. + /// + public sealed class Crc32 : IChecksum + { + const uint CrcSeed = 0xFFFFFFFF; + + readonly static uint[] CrcTable = new uint[] { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, + 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, + 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, + 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, + 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, + 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, + 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, + 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, + 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, + 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, + 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, + 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, + 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, + 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, + 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, + 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, + 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, + 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, + 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, + 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, + 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, + 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, + 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, + 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, + 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, + 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, + 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, + 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, + 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, + 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, + 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, + 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, + 0x2D02EF8D + }; + + internal static uint ComputeCrc32(uint oldCrc, byte value) + { + return (uint)(Crc32.CrcTable[(oldCrc ^ value) & 0xFF] ^ (oldCrc >> 8)); + } + + /// + /// The crc data checksum so far. + /// + uint crc; + + /// + /// Returns the CRC32 data checksum computed so far. + /// + public long Value { + get { + return (long)crc; + } + set { + crc = (uint)value; + } + } + + /// + /// Resets the CRC32 data checksum as if no update was ever called. + /// + public void Reset() + { + crc = 0; + } + + /// + /// Updates the checksum with the int bval. + /// + /// + /// the byte is taken as the lower 8 bits of value + /// + public void Update(int value) + { + crc ^= CrcSeed; + crc = CrcTable[(crc ^ value) & 0xFF] ^ (crc >> 8); + crc ^= CrcSeed; + } + + /// + /// Updates the checksum with the bytes taken from the array. + /// + /// + /// buffer an array of bytes + /// + public void Update(byte[] buffer) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Adds the byte array to the data checksum. + /// + /// + /// The buffer which contains the data + /// + /// + /// The offset in the buffer where the data starts + /// + /// + /// The number of data bytes to update the CRC with. + /// + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Count cannot be less than zero"); +#endif + } + + if (offset < 0 || offset + count > buffer.Length) { + throw new ArgumentOutOfRangeException("offset"); + } + + crc ^= CrcSeed; + + while (--count >= 0) { + crc = CrcTable[(crc ^ buffer[offset++]) & 0xFF] ^ (crc >> 8); + } + + crc ^= CrcSeed; + } + } +} diff --git a/PCRobot/Utils/ZIP/Checksums/IChecksum.cs b/PCRobot/Utils/ZIP/Checksums/IChecksum.cs new file mode 100644 index 0000000..e2679f9 --- /dev/null +++ b/PCRobot/Utils/ZIP/Checksums/IChecksum.cs @@ -0,0 +1,93 @@ +// IChecksum.cs - Interface to compute a data checksum +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Interface to compute a data checksum used by checked input/output streams. + /// A data checksum can be updated by one byte or with a byte array. After each + /// update the value of the current checksum can be returned by calling + /// getValue. The complete checksum object can also be reset + /// so it can be used again with new data. + /// + public interface IChecksum + { + /// + /// Returns the data checksum computed so far. + /// + long Value + { + get; + } + + /// + /// Resets the data checksum as if no update was ever called. + /// + void Reset(); + + /// + /// Adds one byte to the data checksum. + /// + /// + /// the data value to add. The high byte of the int is ignored. + /// + void Update(int value); + + /// + /// Updates the data checksum with the bytes taken from the array. + /// + /// + /// buffer an array of bytes + /// + void Update(byte[] buffer); + + /// + /// Adds the byte array to the data checksum. + /// + /// + /// The buffer which contains the data + /// + /// + /// The offset in the buffer where the data starts + /// + /// + /// the number of data bytes to add. + /// + void Update(byte[] buffer, int offset, int count); + } +} diff --git a/PCRobot/Utils/ZIP/Checksums/StrangeCRC.cs b/PCRobot/Utils/ZIP/Checksums/StrangeCRC.cs new file mode 100644 index 0000000..6ed7679 --- /dev/null +++ b/PCRobot/Utils/ZIP/Checksums/StrangeCRC.cs @@ -0,0 +1,208 @@ +// StrangeCRC.cs - computes a crc used in the bziplib +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + /// + /// Bzip2 checksum algorithm + /// + public class StrangeCRC : IChecksum + { + readonly static uint[] crc32Table = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + }; + + int globalCrc; + + /// + /// Initialise a default instance of + /// + public StrangeCRC() + { + Reset(); + } + + /// + /// Reset the state of Crc. + /// + public void Reset() + { + globalCrc = -1; + } + + /// + /// Get the current Crc value. + /// + public long Value { + get { + return ~globalCrc; + } + } + + /// + /// Update the Crc value. + /// + /// data update is based on + public void Update(int value) + { + int temp = (globalCrc >> 24) ^ value; + if (temp < 0) { + temp = 256 + temp; + } + globalCrc = unchecked((int)((globalCrc << 8) ^ crc32Table[temp])); + } + + /// + /// Update Crc based on a block of data + /// + /// The buffer containing data to update the crc with. + public void Update(byte[] buffer) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Update Crc based on a portion of a block of data + /// + /// block of data + /// index of first byte to use + /// number of bytes to use + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "cannot be less than zero"); +#endif + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "cannot be less than zero"); +#endif + } + + if ( offset + count > buffer.Length ) + { + throw new ArgumentOutOfRangeException("count"); + } + + for (int i = 0; i < count; ++i) { + Update(buffer[offset++]); + } + } + } +} diff --git a/PCRobot/Utils/ZIP/Core/FileSystemScanner.cs b/PCRobot/Utils/ZIP/Core/FileSystemScanner.cs new file mode 100644 index 0000000..4077a45 --- /dev/null +++ b/PCRobot/Utils/ZIP/Core/FileSystemScanner.cs @@ -0,0 +1,533 @@ +// FileSystemScanner.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +using System; + +namespace ICSharpCode.SharpZipLib.Core +{ + #region EventArgs + /// + /// Event arguments for scanning. + /// + public class ScanEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file or directory name. + public ScanEventArgs(string name) + { + name_ = name; + } + #endregion + + /// + /// The file or directory name for this event. + /// + public string Name + { + get { return name_; } + } + + /// + /// Get set a value indicating if scanning should continue or not. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + #region Instance Fields + string name_; + bool continueRunning_ = true; + #endregion + } + + /// + /// Event arguments during processing of a single file or directory. + /// + public class ProgressEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file or directory name if known. + /// The number of bytes processed so far + /// The total number of bytes to process, 0 if not known + public ProgressEventArgs(string name, long processed, long target) + { + name_ = name; + processed_ = processed; + target_ = target; + } + #endregion + + /// + /// The name for this event if known. + /// + public string Name + { + get { return name_; } + } + + /// + /// Get set a value indicating wether scanning should continue or not. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + /// + /// Get a percentage representing how much of the has been processed + /// + /// 0.0 to 100.0 percent; 0 if target is not known. + public float PercentComplete + { + get + { + float result; + if (target_ <= 0) + { + result = 0; + } + else + { + result = ((float)processed_ / (float)target_) * 100.0f; + } + return result; + } + } + + /// + /// The number of bytes processed so far + /// + public long Processed + { + get { return processed_; } + } + + /// + /// The number of bytes to process. + /// + /// Target may be 0 or negative if the value isnt known. + public long Target + { + get { return target_; } + } + + #region Instance Fields + string name_; + long processed_; + long target_; + bool continueRunning_ = true; + #endregion + } + + /// + /// Event arguments for directories. + /// + public class DirectoryEventArgs : ScanEventArgs + { + #region Constructors + /// + /// Initialize an instance of . + /// + /// The name for this directory. + /// Flag value indicating if any matching files are contained in this directory. + public DirectoryEventArgs(string name, bool hasMatchingFiles) + : base (name) + { + hasMatchingFiles_ = hasMatchingFiles; + } + #endregion + + /// + /// Get a value indicating if the directory contains any matching files or not. + /// + public bool HasMatchingFiles + { + get { return hasMatchingFiles_; } + } + + #region Instance Fields + bool hasMatchingFiles_; + #endregion + } + + /// + /// Arguments passed when scan failures are detected. + /// + public class ScanFailureEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The name to apply. + /// The exception to use. + public ScanFailureEventArgs(string name, Exception e) + { + name_ = name; + exception_ = e; + continueRunning_ = true; + } + #endregion + + /// + /// The applicable name. + /// + public string Name + { + get { return name_; } + } + + /// + /// The applicable exception. + /// + public Exception Exception + { + get { return exception_; } + } + + /// + /// Get / set a value indicating wether scanning should continue. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + #region Instance Fields + string name_; + Exception exception_; + bool continueRunning_; + #endregion + } + + #endregion + + #region Delegates + /// + /// Delegate invoked before starting to process a directory. + /// + public delegate void ProcessDirectoryHandler(object sender, DirectoryEventArgs e); + + /// + /// Delegate invoked before starting to process a file. + /// + /// The source of the event + /// The event arguments. + public delegate void ProcessFileHandler(object sender, ScanEventArgs e); + + /// + /// Delegate invoked during processing of a file or directory + /// + /// The source of the event + /// The event arguments. + public delegate void ProgressHandler(object sender, ProgressEventArgs e); + + /// + /// Delegate invoked when a file has been completely processed. + /// + /// The source of the event + /// The event arguments. + public delegate void CompletedFileHandler(object sender, ScanEventArgs e); + + /// + /// Delegate invoked when a directory failure is detected. + /// + /// The source of the event + /// The event arguments. + public delegate void DirectoryFailureHandler(object sender, ScanFailureEventArgs e); + + /// + /// Delegate invoked when a file failure is detected. + /// + /// The source of the event + /// The event arguments. + public delegate void FileFailureHandler(object sender, ScanFailureEventArgs e); + #endregion + + /// + /// FileSystemScanner provides facilities scanning of files and directories. + /// + public class FileSystemScanner + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file filter to apply when scanning. + public FileSystemScanner(string filter) + { + fileFilter_ = new PathFilter(filter); + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + /// The directory filter to apply. + public FileSystemScanner(string fileFilter, string directoryFilter) + { + fileFilter_ = new PathFilter(fileFilter); + directoryFilter_ = new PathFilter(directoryFilter); + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + public FileSystemScanner(IScanFilter fileFilter) + { + fileFilter_ = fileFilter; + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + /// The directory filter to apply. + public FileSystemScanner(IScanFilter fileFilter, IScanFilter directoryFilter) + { + fileFilter_ = fileFilter; + directoryFilter_ = directoryFilter; + } + #endregion + + #region Delegates + /// + /// Delegate to invoke when a directory is processed. + /// + public ProcessDirectoryHandler ProcessDirectory; + + /// + /// Delegate to invoke when a file is processed. + /// + public ProcessFileHandler ProcessFile; + + /// + /// Delegate to invoke when processing for a file has finished. + /// + public CompletedFileHandler CompletedFile; + + /// + /// Delegate to invoke when a directory failure is detected. + /// + public DirectoryFailureHandler DirectoryFailure; + + /// + /// Delegate to invoke when a file failure is detected. + /// + public FileFailureHandler FileFailure; + #endregion + + /// + /// Raise the DirectoryFailure event. + /// + /// The directory name. + /// The exception detected. + bool OnDirectoryFailure(string directory, Exception e) + { + DirectoryFailureHandler handler = DirectoryFailure; + bool result = (handler != null); + if ( result ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e); + handler(this, args); + alive_ = args.ContinueRunning; + } + return result; + } + + /// + /// Raise the FileFailure event. + /// + /// The file name. + /// The exception detected. + bool OnFileFailure(string file, Exception e) + { + FileFailureHandler handler = FileFailure; + + bool result = (handler != null); + + if ( result ){ + ScanFailureEventArgs args = new ScanFailureEventArgs(file, e); + FileFailure(this, args); + alive_ = args.ContinueRunning; + } + return result; + } + + /// + /// Raise the ProcessFile event. + /// + /// The file name. + void OnProcessFile(string file) + { + ProcessFileHandler handler = ProcessFile; + + if ( handler!= null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Raise the complete file event + /// + /// The file name + void OnCompleteFile(string file) + { + CompletedFileHandler handler = CompletedFile; + + if (handler != null) + { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Raise the ProcessDirectory event. + /// + /// The directory name. + /// Flag indicating if the directory has matching files. + void OnProcessDirectory(string directory, bool hasMatchingFiles) + { + ProcessDirectoryHandler handler = ProcessDirectory; + + if ( handler != null ) { + DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Scan a directory. + /// + /// The base directory to scan. + /// True to recurse subdirectories, false to scan a single directory. + public void Scan(string directory, bool recurse) + { + alive_ = true; + ScanDir(directory, recurse); + } + + void ScanDir(string directory, bool recurse) + { + + try { + string[] names = System.IO.Directory.GetFiles(directory); + bool hasMatch = false; + for (int fileIndex = 0; fileIndex < names.Length; ++fileIndex) { + if ( !fileFilter_.IsMatch(names[fileIndex]) ) { + names[fileIndex] = null; + } else { + hasMatch = true; + } + } + + OnProcessDirectory(directory, hasMatch); + + if ( alive_ && hasMatch ) { + foreach (string fileName in names) { + try { + if ( fileName != null ) { + OnProcessFile(fileName); + if ( !alive_ ) { + break; + } + } + } + catch (Exception e) { + if (!OnFileFailure(fileName, e)) { + throw; + } + } + } + } + } + catch (Exception e) { + if (!OnDirectoryFailure(directory, e)) { + throw; + } + } + + if ( alive_ && recurse ) { + try { + string[] names = System.IO.Directory.GetDirectories(directory); + foreach (string fulldir in names) { + if ((directoryFilter_ == null) || (directoryFilter_.IsMatch(fulldir))) { + ScanDir(fulldir, true); + if ( !alive_ ) { + break; + } + } + } + } + catch (Exception e) { + if (!OnDirectoryFailure(directory, e)) { + throw; + } + } + } + } + + #region Instance Fields + /// + /// The file filter currently in use. + /// + IScanFilter fileFilter_; + /// + /// The directory filter currently in use. + /// + IScanFilter directoryFilter_; + /// + /// Flag indicating if scanning should continue running. + /// + bool alive_; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Core/INameTransform.cs b/PCRobot/Utils/ZIP/Core/INameTransform.cs new file mode 100644 index 0000000..88c934f --- /dev/null +++ b/PCRobot/Utils/ZIP/Core/INameTransform.cs @@ -0,0 +1,57 @@ +// INameTransform.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// INameTransform defines how file system names are transformed for use with archives, or vice versa. + /// + public interface INameTransform + { + /// + /// Given a file name determine the transformed value. + /// + /// The name to transform. + /// The transformed file name. + string TransformFile(string name); + + /// + /// Given a directory name determine the transformed value. + /// + /// The name to transform. + /// The transformed directory name + string TransformDirectory(string name); + } +} diff --git a/PCRobot/Utils/ZIP/Core/IScanFilter.cs b/PCRobot/Utils/ZIP/Core/IScanFilter.cs new file mode 100644 index 0000000..64c99a8 --- /dev/null +++ b/PCRobot/Utils/ZIP/Core/IScanFilter.cs @@ -0,0 +1,50 @@ +// IScanFilter.cs +// +// Copyright 2006 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// Scanning filters support filtering of names. + /// + public interface IScanFilter + { + /// + /// Test a name to see if it 'matches' the filter. + /// + /// The name to test. + /// Returns true if the name matches the filter, false if it does not match. + bool IsMatch(string name); + } +} diff --git a/PCRobot/Utils/ZIP/Core/NameFilter.cs b/PCRobot/Utils/ZIP/Core/NameFilter.cs new file mode 100644 index 0000000..eea8fbe --- /dev/null +++ b/PCRobot/Utils/ZIP/Core/NameFilter.cs @@ -0,0 +1,290 @@ +// NameFilter.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2010-03-03 Z-1654 Fixed bug where escape characters were excluded in SplitQuoted() + +using System; +using System.Collections; +using System.Text; +using System.Text.RegularExpressions; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// NameFilter is a string matching class which allows for both positive and negative + /// matching. + /// A filter is a sequence of independant regular expressions separated by semi-colons ';'. + /// To include a semi-colon it may be quoted as in \;. Each expression can be prefixed by a plus '+' sign or + /// a minus '-' sign to denote the expression is intended to include or exclude names. + /// If neither a plus or minus sign is found include is the default. + /// A given name is tested for inclusion before checking exclusions. Only names matching an include spec + /// and not matching an exclude spec are deemed to match the filter. + /// An empty filter matches any name. + /// + /// The following expression includes all name ending in '.dat' with the exception of 'dummy.dat' + /// "+\.dat$;-^dummy\.dat$" + /// + public class NameFilter : IScanFilter + { + #region Constructors + /// + /// Construct an instance based on the filter expression passed + /// + /// The filter expression. + public NameFilter(string filter) + { + filter_ = filter; + inclusions_ = new ArrayList(); + exclusions_ = new ArrayList(); + Compile(); + } + #endregion + + /// + /// Test a string to see if it is a valid regular expression. + /// + /// The expression to test. + /// True if expression is a valid false otherwise. + public static bool IsValidExpression(string expression) + { + bool result = true; + try { + Regex exp = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + catch (ArgumentException) { + result = false; + } + return result; + } + + /// + /// Test an expression to see if it is valid as a filter. + /// + /// The filter expression to test. + /// True if the expression is valid, false otherwise. + public static bool IsValidFilterExpression(string toTest) + { + if ( toTest == null ) { + throw new ArgumentNullException("toTest"); + } + + bool result = true; + + try { + string[] items = SplitQuoted(toTest); + for (int i = 0; i < items.Length; ++i) { + if ((items[i] != null) && (items[i].Length > 0)) { + string toCompile; + + if (items[i][0] == '+') { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else if (items[i][0] == '-') { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else { + toCompile = items[i]; + } + + Regex testRegex = new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + } + } + catch (ArgumentException) { + result = false; + } + + return result; + } + + /// + /// Split a string into its component pieces + /// + /// The original string + /// Returns an array of values containing the individual filter elements. + public static string[] SplitQuoted(string original) + { + char escape = '\\'; + char[] separators = { ';' }; + + ArrayList result = new ArrayList(); + + if ((original != null) && (original.Length > 0)) { + int endIndex = -1; + StringBuilder b = new StringBuilder(); + + while (endIndex < original.Length) { + endIndex += 1; + if (endIndex >= original.Length) { + result.Add(b.ToString()); + } + else if (original[endIndex] == escape) { + endIndex += 1; + if (endIndex >= original.Length) { +#if NETCF_1_0 + throw new ArgumentException("Missing terminating escape character"); +#else + throw new ArgumentException("Missing terminating escape character", "original"); +#endif + } + // include escape if this is not an escaped separator + if (Array.IndexOf(separators, original[endIndex]) < 0) + b.Append(escape); + + b.Append(original[endIndex]); + } + else { + if (Array.IndexOf(separators, original[endIndex]) >= 0) { + result.Add(b.ToString()); + b.Length = 0; + } + else { + b.Append(original[endIndex]); + } + } + } + } + + return (string[])result.ToArray(typeof(string)); + } + + /// + /// Convert this filter to its string equivalent. + /// + /// The string equivalent for this filter. + public override string ToString() + { + return filter_; + } + + /// + /// Test a value to see if it is included by the filter. + /// + /// The value to test. + /// True if the value is included, false otherwise. + public bool IsIncluded(string name) + { + bool result = false; + if ( inclusions_.Count == 0 ) { + result = true; + } + else { + foreach ( Regex r in inclusions_ ) { + if ( r.IsMatch(name) ) { + result = true; + break; + } + } + } + return result; + } + + /// + /// Test a value to see if it is excluded by the filter. + /// + /// The value to test. + /// True if the value is excluded, false otherwise. + public bool IsExcluded(string name) + { + bool result = false; + foreach ( Regex r in exclusions_ ) { + if ( r.IsMatch(name) ) { + result = true; + break; + } + } + return result; + } + + #region IScanFilter Members + /// + /// Test a value to see if it matches the filter. + /// + /// The value to test. + /// True if the value matches, false otherwise. + public bool IsMatch(string name) + { + return (IsIncluded(name) && !IsExcluded(name)); + } + #endregion + + /// + /// Compile this filter. + /// + void Compile() + { + // TODO: Check to see if combining RE's makes it faster/smaller. + // simple scheme would be to have one RE for inclusion and one for exclusion. + if ( filter_ == null ) { + return; + } + + string[] items = SplitQuoted(filter_); + for ( int i = 0; i < items.Length; ++i ) { + if ( (items[i] != null) && (items[i].Length > 0) ) { + bool include = (items[i][0] != '-'); + string toCompile; + + if ( items[i][0] == '+' ) { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else if ( items[i][0] == '-' ) { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else { + toCompile = items[i]; + } + + // NOTE: Regular expressions can fail to compile here for a number of reasons that cause an exception + // these are left unhandled here as the caller is responsible for ensuring all is valid. + // several functions IsValidFilterExpression and IsValidExpression are provided for such checking + if ( include ) { + inclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)); + } + else { + exclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)); + } + } + } + } + + #region Instance Fields + string filter_; + ArrayList inclusions_; + ArrayList exclusions_; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Core/PathFilter.cs b/PCRobot/Utils/ZIP/Core/PathFilter.cs new file mode 100644 index 0000000..03b8ff3 --- /dev/null +++ b/PCRobot/Utils/ZIP/Core/PathFilter.cs @@ -0,0 +1,334 @@ +// PathFilter.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// PathFilter filters directories and files using a form of regular expressions + /// by full path name. + /// See NameFilter for more detail on filtering. + /// + public class PathFilter : IScanFilter + { + #region Constructors + /// + /// Initialise a new instance of . + /// + /// The filter expression to apply. + public PathFilter(string filter) + { + nameFilter_ = new NameFilter(filter); + } + #endregion + + #region IScanFilter Members + /// + /// Test a name to see if it matches the filter. + /// + /// The name to test. + /// True if the name matches, false otherwise. + /// is used to get the full path before matching. + public virtual bool IsMatch(string name) + { + bool result = false; + + if ( name != null ) { + string cooked = (name.Length > 0) ? Path.GetFullPath(name) : ""; + result = nameFilter_.IsMatch(cooked); + } + return result; + } + #endregion + + #region Instance Fields + NameFilter nameFilter_; + #endregion + } + + /// + /// ExtendedPathFilter filters based on name, file size, and the last write time of the file. + /// + /// Provides an example of how to customise filtering. + public class ExtendedPathFilter : PathFilter + { + #region Constructors + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + public ExtendedPathFilter(string filter, + long minSize, long maxSize) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + } + + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum to include. + /// The maximum to include. + public ExtendedPathFilter(string filter, + DateTime minDate, DateTime maxDate) + : base(filter) + { + MinDate = minDate; + MaxDate = maxDate; + } + + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + /// The minimum to include. + /// The maximum to include. + public ExtendedPathFilter(string filter, + long minSize, long maxSize, + DateTime minDate, DateTime maxDate) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + MinDate = minDate; + MaxDate = maxDate; + } + #endregion + + #region IScanFilter Members + /// + /// Test a filename to see if it matches the filter. + /// + /// The filename to test. + /// True if the filter matches, false otherwise. + /// The doesnt exist + public override bool IsMatch(string name) + { + bool result = base.IsMatch(name); + + if ( result ) { + FileInfo fileInfo = new FileInfo(name); + result = + (MinSize <= fileInfo.Length) && + (MaxSize >= fileInfo.Length) && + (MinDate <= fileInfo.LastWriteTime) && + (MaxDate >= fileInfo.LastWriteTime) + ; + } + return result; + } + #endregion + + #region Properties + /// + /// Get/set the minimum size/length for a file that will match this filter. + /// + /// The default value is zero. + /// value is less than zero; greater than + public long MinSize + { + get { return minSize_; } + set + { + if ( (value < 0) || (maxSize_ < value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + minSize_ = value; + } + } + + /// + /// Get/set the maximum size/length for a file that will match this filter. + /// + /// The default value is + /// value is less than zero or less than + public long MaxSize + { + get { return maxSize_; } + set + { + if ( (value < 0) || (minSize_ > value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + maxSize_ = value; + } + } + + /// + /// Get/set the minimum value that will match for this filter. + /// + /// Files with a LastWrite time less than this value are excluded by the filter. + public DateTime MinDate + { + get + { + return minDate_; + } + + set + { + if ( value > maxDate_ ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Exceeds MaxDate"); +#endif + } + + minDate_ = value; + } + } + + /// + /// Get/set the maximum value that will match for this filter. + /// + /// Files with a LastWrite time greater than this value are excluded by the filter. + public DateTime MaxDate + { + get + { + return maxDate_; + } + + set + { + if ( minDate_ > value ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Exceeds MinDate"); +#endif + } + + maxDate_ = value; + } + } + #endregion + + #region Instance Fields + long minSize_; + long maxSize_ = long.MaxValue; + DateTime minDate_ = DateTime.MinValue; + DateTime maxDate_ = DateTime.MaxValue; + #endregion + } + + /// + /// NameAndSizeFilter filters based on name and file size. + /// + /// A sample showing how filters might be extended. + [Obsolete("Use ExtendedPathFilter instead")] + public class NameAndSizeFilter : PathFilter + { + + /// + /// Initialise a new instance of NameAndSizeFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + public NameAndSizeFilter(string filter, long minSize, long maxSize) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + } + + /// + /// Test a filename to see if it matches the filter. + /// + /// The filename to test. + /// True if the filter matches, false otherwise. + public override bool IsMatch(string name) + { + bool result = base.IsMatch(name); + + if ( result ) { + FileInfo fileInfo = new FileInfo(name); + long length = fileInfo.Length; + result = + (MinSize <= length) && + (MaxSize >= length); + } + return result; + } + + /// + /// Get/set the minimum size for a file that will match this filter. + /// + public long MinSize + { + get { return minSize_; } + set { + if ( (value < 0) || (maxSize_ < value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + minSize_ = value; + } + } + + /// + /// Get/set the maximum size for a file that will match this filter. + /// + public long MaxSize + { + get { return maxSize_; } + set + { + if ( (value < 0) || (minSize_ > value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + maxSize_ = value; + } + } + + #region Instance Fields + long minSize_; + long maxSize_ = long.MaxValue; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Core/StreamUtils.cs b/PCRobot/Utils/ZIP/Core/StreamUtils.cs new file mode 100644 index 0000000..7abdce8 --- /dev/null +++ b/PCRobot/Utils/ZIP/Core/StreamUtils.cs @@ -0,0 +1,246 @@ +// StreamUtils.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// Provides simple " utilities. + /// + public sealed class StreamUtils + { + /// + /// Read from a ensuring all the required data is read. + /// + /// The stream to read. + /// The buffer to fill. + /// + static public void ReadFully(Stream stream, byte[] buffer) + { + ReadFully(stream, buffer, 0, buffer.Length); + } + + /// + /// Read from a " ensuring all the required data is read. + /// + /// The stream to read data from. + /// The buffer to store data in. + /// The offset at which to begin storing data. + /// The number of bytes of data to store. + /// Required parameter is null + /// and or are invalid. + /// End of stream is encountered before all the data has been read. + static public void ReadFully(Stream stream, byte[] buffer, int offset, int count) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + // Offset can equal length when buffer and count are 0. + if ( (offset < 0) || (offset > buffer.Length) ) { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( (count < 0) || (offset + count > buffer.Length) ) { + throw new ArgumentOutOfRangeException("count"); + } + + while ( count > 0 ) { + int readCount = stream.Read(buffer, offset, count); + if ( readCount <= 0 ) { + throw new EndOfStreamException(); + } + offset += readCount; + count -= readCount; + } + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + static public void Copy(Stream source, Stream destination, byte[] buffer) + { + if (source == null) { + throw new ArgumentNullException("source"); + } + + if (destination == null) { + throw new ArgumentNullException("destination"); + } + + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + // Ensure a reasonable size of buffer is used without being prohibitive. + if (buffer.Length < 128) { + throw new ArgumentException("Buffer is too small", "buffer"); + } + + bool copying = true; + + while (copying) { + int bytesRead = source.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) { + destination.Write(buffer, 0, bytesRead); + } + else { + destination.Flush(); + copying = false; + } + } + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + /// The progress handler delegate to use. + /// The minimum between progress updates. + /// The source for this event. + /// The name to use with the event. + /// This form is specialised for use within #Zip to support events during archive operations. + static public void Copy(Stream source, Stream destination, + byte[] buffer, ProgressHandler progressHandler, TimeSpan updateInterval, object sender, string name) + { + Copy(source, destination, buffer, progressHandler, updateInterval, sender, name, -1); + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + /// The progress handler delegate to use. + /// The minimum between progress updates. + /// The source for this event. + /// The name to use with the event. + /// A predetermined fixed target value to use with progress updates. + /// If the value is negative the target is calculated by looking at the stream. + /// This form is specialised for use within #Zip to support events during archive operations. + static public void Copy(Stream source, Stream destination, + byte[] buffer, + ProgressHandler progressHandler, TimeSpan updateInterval, + object sender, string name, long fixedTarget) + { + if (source == null) { + throw new ArgumentNullException("source"); + } + + if (destination == null) { + throw new ArgumentNullException("destination"); + } + + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + // Ensure a reasonable size of buffer is used without being prohibitive. + if (buffer.Length < 128) { + throw new ArgumentException("Buffer is too small", "buffer"); + } + + if (progressHandler == null) { + throw new ArgumentNullException("progressHandler"); + } + + bool copying = true; + + DateTime marker = DateTime.Now; + long processed = 0; + long target = 0; + + if (fixedTarget >= 0) { + target = fixedTarget; + } + else if (source.CanSeek) { + target = source.Length - source.Position; + } + + // Always fire 0% progress.. + ProgressEventArgs args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + + bool progressFired = true; + + while (copying) { + int bytesRead = source.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) { + processed += bytesRead; + progressFired = false; + destination.Write(buffer, 0, bytesRead); + } + else { + destination.Flush(); + copying = false; + } + + if (DateTime.Now - marker > updateInterval) { + progressFired = true; + marker = DateTime.Now; + args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + + copying = args.ContinueRunning; + } + } + + if (!progressFired) { + args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + } + } + + /// + /// Initialise an instance of + /// + private StreamUtils() + { + // Do nothing. + } + } +} diff --git a/PCRobot/Utils/ZIP/Core/WindowsPathUtils.cs b/PCRobot/Utils/ZIP/Core/WindowsPathUtils.cs new file mode 100644 index 0000000..2091945 --- /dev/null +++ b/PCRobot/Utils/ZIP/Core/WindowsPathUtils.cs @@ -0,0 +1,94 @@ +// WindowsPathUtils.cs +// +// Copyright 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// WindowsPathUtils provides simple utilities for handling windows paths. + /// + public abstract class WindowsPathUtils + { + /// + /// Initializes a new instance of the class. + /// + internal WindowsPathUtils() + { + } + + /// + /// Remove any path root present in the path + /// + /// A containing path information. + /// The path with the root removed if it was present; path otherwise. + /// Unlike the class the path isnt otherwise checked for validity. + public static string DropPathRoot(string path) + { + string result = path; + + if ( (path != null) && (path.Length > 0) ) { + if ((path[0] == '\\') || (path[0] == '/')) { + // UNC name ? + if ((path.Length > 1) && ((path[1] == '\\') || (path[1] == '/'))) { + int index = 2; + int elements = 2; + + // Scan for two separate elements \\machine\share\restofpath + while ((index <= path.Length) && + (((path[index] != '\\') && (path[index] != '/')) || (--elements > 0))) { + index++; + } + + index++; + + if (index < path.Length) { + result = path.Substring(index); + } + else { + result = ""; + } + } + } + else if ((path.Length > 1) && (path[1] == ':')) { + int dropCount = 2; + if ((path.Length > 2) && ((path[2] == '\\') || (path[2] == '/'))) { + dropCount = 3; + } + result = result.Remove(0, dropCount); + } + } + return result; + } + } +} diff --git a/PCRobot/Utils/ZIP/Encryption/PkzipClassic.cs b/PCRobot/Utils/ZIP/Encryption/PkzipClassic.cs new file mode 100644 index 0000000..7bed67a --- /dev/null +++ b/PCRobot/Utils/ZIP/Encryption/PkzipClassic.cs @@ -0,0 +1,498 @@ +// +// PkzipClassic encryption +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + + +#if !NETCF_1_0 + +using System; +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.Encryption +{ + /// + /// PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives. + /// While it has been superceded by more recent and more powerful algorithms, its still in use and + /// is viable for preventing casual snooping + /// + public abstract class PkzipClassic : SymmetricAlgorithm + { + /// + /// Generates new encryption keys based on given seed + /// + /// The seed value to initialise keys with. + /// A new key value. + static public byte[] GenerateKeys(byte[] seed) + { + if ( seed == null ) { + throw new ArgumentNullException("seed"); + } + + if ( seed.Length == 0 ) { + throw new ArgumentException("Length is zero", "seed"); + } + + uint[] newKeys = new uint[] { + 0x12345678, + 0x23456789, + 0x34567890 + }; + + for (int i = 0; i < seed.Length; ++i) { + newKeys[0] = Crc32.ComputeCrc32(newKeys[0], seed[i]); + newKeys[1] = newKeys[1] + (byte)newKeys[0]; + newKeys[1] = newKeys[1] * 134775813 + 1; + newKeys[2] = Crc32.ComputeCrc32(newKeys[2], (byte)(newKeys[1] >> 24)); + } + + byte[] result = new byte[12]; + result[0] = (byte)(newKeys[0] & 0xff); + result[1] = (byte)((newKeys[0] >> 8) & 0xff); + result[2] = (byte)((newKeys[0] >> 16) & 0xff); + result[3] = (byte)((newKeys[0] >> 24) & 0xff); + result[4] = (byte)(newKeys[1] & 0xff); + result[5] = (byte)((newKeys[1] >> 8) & 0xff); + result[6] = (byte)((newKeys[1] >> 16) & 0xff); + result[7] = (byte)((newKeys[1] >> 24) & 0xff); + result[8] = (byte)(newKeys[2] & 0xff); + result[9] = (byte)((newKeys[2] >> 8) & 0xff); + result[10] = (byte)((newKeys[2] >> 16) & 0xff); + result[11] = (byte)((newKeys[2] >> 24) & 0xff); + return result; + } + } + + /// + /// PkzipClassicCryptoBase provides the low level facilities for encryption + /// and decryption using the PkzipClassic algorithm. + /// + class PkzipClassicCryptoBase + { + /// + /// Transform a single byte + /// + /// + /// The transformed value + /// + protected byte TransformByte() + { + uint temp = ((keys[2] & 0xFFFF) | 2); + return (byte)((temp * (temp ^ 1)) >> 8); + } + + /// + /// Set the key schedule for encryption/decryption. + /// + /// The data use to set the keys from. + protected void SetKeys(byte[] keyData) + { + if ( keyData == null ) { + throw new ArgumentNullException("keyData"); + } + + if ( keyData.Length != 12 ) { + throw new InvalidOperationException("Key length is not valid"); + } + + keys = new uint[3]; + keys[0] = (uint)((keyData[3] << 24) | (keyData[2] << 16) | (keyData[1] << 8) | keyData[0]); + keys[1] = (uint)((keyData[7] << 24) | (keyData[6] << 16) | (keyData[5] << 8) | keyData[4]); + keys[2] = (uint)((keyData[11] << 24) | (keyData[10] << 16) | (keyData[9] << 8) | keyData[8]); + } + + /// + /// Update encryption keys + /// + protected void UpdateKeys(byte ch) + { + keys[0] = Crc32.ComputeCrc32(keys[0], ch); + keys[1] = keys[1] + (byte)keys[0]; + keys[1] = keys[1] * 134775813 + 1; + keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24)); + } + + /// + /// Reset the internal state. + /// + protected void Reset() + { + keys[0] = 0; + keys[1] = 0; + keys[2] = 0; + } + + #region Instance Fields + uint[] keys; + #endregion + } + + /// + /// PkzipClassic CryptoTransform for encryption. + /// + class PkzipClassicEncryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform + { + /// + /// Initialise a new instance of + /// + /// The key block to use. + internal PkzipClassicEncryptCryptoTransform(byte[] keyBlock) + { + SetKeys(keyBlock); + } + + #region ICryptoTransform Members + + /// + /// Transforms the specified region of the specified byte array. + /// + /// The input for which to compute the transform. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + /// The computed transform. + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + byte[] result = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, result, 0); + return result; + } + + /// + /// Transforms the specified region of the input byte array and copies + /// the resulting transform to the specified region of the output byte array. + /// + /// The input for which to compute the transform. + /// The offset into the input byte array from which to begin using data. + /// The number of bytes in the input byte array to use as data. + /// The output to which to write the transform. + /// The offset into the output byte array from which to begin writing data. + /// The number of bytes written. + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + for (int i = inputOffset; i < inputOffset + inputCount; ++i) { + byte oldbyte = inputBuffer[i]; + outputBuffer[outputOffset++] = (byte)(inputBuffer[i] ^ TransformByte()); + UpdateKeys(oldbyte); + } + return inputCount; + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform + { + get { + return true; + } + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks + { + get { + return true; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Cleanup internal state. + /// + public void Dispose() + { + Reset(); + } + + #endregion + } + + + /// + /// PkzipClassic CryptoTransform for decryption. + /// + class PkzipClassicDecryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform + { + /// + /// Initialise a new instance of . + /// + /// The key block to decrypt with. + internal PkzipClassicDecryptCryptoTransform(byte[] keyBlock) + { + SetKeys(keyBlock); + } + + #region ICryptoTransform Members + + /// + /// Transforms the specified region of the specified byte array. + /// + /// The input for which to compute the transform. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + /// The computed transform. + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + byte[] result = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, result, 0); + return result; + } + + /// + /// Transforms the specified region of the input byte array and copies + /// the resulting transform to the specified region of the output byte array. + /// + /// The input for which to compute the transform. + /// The offset into the input byte array from which to begin using data. + /// The number of bytes in the input byte array to use as data. + /// The output to which to write the transform. + /// The offset into the output byte array from which to begin writing data. + /// The number of bytes written. + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + for (int i = inputOffset; i < inputOffset + inputCount; ++i) { + byte newByte = (byte)(inputBuffer[i] ^ TransformByte()); + outputBuffer[outputOffset++] = newByte; + UpdateKeys(newByte); + } + return inputCount; + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform + { + get { + return true; + } + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks + { + get { + return true; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Cleanup internal state. + /// + public void Dispose() + { + Reset(); + } + + #endregion + } + + /// + /// Defines a wrapper object to access the Pkzip algorithm. + /// This class cannot be inherited. + /// + public sealed class PkzipClassicManaged : PkzipClassic + { + /// + /// Get / set the applicable block size in bits. + /// + /// The only valid block size is 8. + public override int BlockSize + { + get { + return 8; + } + + set { + if (value != 8) { + throw new CryptographicException("Block size is invalid"); + } + } + } + + /// + /// Get an array of legal key sizes. + /// + public override KeySizes[] LegalKeySizes + { + get { + KeySizes[] keySizes = new KeySizes[1]; + keySizes[0] = new KeySizes(12 * 8, 12 * 8, 0); + return keySizes; + } + } + + /// + /// Generate an initial vector. + /// + public override void GenerateIV() + { + // Do nothing. + } + + /// + /// Get an array of legal block sizes. + /// + public override KeySizes[] LegalBlockSizes + { + get { + KeySizes[] keySizes = new KeySizes[1]; + keySizes[0] = new KeySizes(1 * 8, 1 * 8, 0); + return keySizes; + } + } + + /// + /// Get / set the key value applicable. + /// + public override byte[] Key + { + get { + if ( key_ == null ) { + GenerateKey(); + } + + return (byte[]) key_.Clone(); + } + + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + + if ( value.Length != 12 ) { + throw new CryptographicException("Key size is illegal"); + } + + key_ = (byte[]) value.Clone(); + } + } + + /// + /// Generate a new random key. + /// + public override void GenerateKey() + { + key_ = new byte[12]; + Random rnd = new Random(); + rnd.NextBytes(key_); + } + + /// + /// Create an encryptor. + /// + /// The key to use for this encryptor. + /// Initialisation vector for the new encryptor. + /// Returns a new PkzipClassic encryptor + public override ICryptoTransform CreateEncryptor( + byte[] rgbKey, + byte[] rgbIV) + { + key_ = rgbKey; + return new PkzipClassicEncryptCryptoTransform(Key); + } + + /// + /// Create a decryptor. + /// + /// Keys to use for this new decryptor. + /// Initialisation vector for the new decryptor. + /// Returns a new decryptor. + public override ICryptoTransform CreateDecryptor( + byte[] rgbKey, + byte[] rgbIV) + { + key_ = rgbKey; + return new PkzipClassicDecryptCryptoTransform(Key); + } + + #region Instance Fields + byte[] key_; + #endregion + } +} +#endif diff --git a/PCRobot/Utils/ZIP/Encryption/ZipAESStream.cs b/PCRobot/Utils/ZIP/Encryption/ZipAESStream.cs new file mode 100644 index 0000000..d57dc34 --- /dev/null +++ b/PCRobot/Utils/ZIP/Encryption/ZipAESStream.cs @@ -0,0 +1,170 @@ +// +// ZipAESStream.cs +// +// Copyright 2009 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + +#if !NET_1_1 && !NETCF_2_0 + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace ICSharpCode.SharpZipLib.Encryption { + + // Based on information from http://www.winzip.com/aes_info.htm + // and http://www.gladman.me.uk/cryptography_technology/fileencrypt/ + + /// + /// Encrypts and decrypts AES ZIP + /// + internal class ZipAESStream : CryptoStream { + + /// + /// Constructor + /// + /// The stream on which to perform the cryptographic transformation. + /// Instance of ZipAESTransform + /// Read or Write + public ZipAESStream(Stream stream, ZipAESTransform transform, CryptoStreamMode mode) + : base(stream, transform, mode) { + + _stream = stream; + _transform = transform; + _slideBuffer = new byte[1024]; + + _blockAndAuth = CRYPTO_BLOCK_SIZE + AUTH_CODE_LENGTH; + + // mode: + // CryptoStreamMode.Read means we read from "stream" and pass decrypted to our Read() method. + // Write bypasses this stream and uses the Transform directly. + if (mode != CryptoStreamMode.Read) { + throw new Exception("ZipAESStream only for read"); + } + } + + // The final n bytes of the AES stream contain the Auth Code. + private const int AUTH_CODE_LENGTH = 10; + + private Stream _stream; + private ZipAESTransform _transform; + private byte[] _slideBuffer; + private int _slideBufStartPos; + private int _slideBufFreePos; + // Blocksize is always 16 here, even for AES-256 which has transform.InputBlockSize of 32. + private const int CRYPTO_BLOCK_SIZE = 16; + private int _blockAndAuth; + + /// + /// Reads a sequence of bytes from the current CryptoStream into buffer, + /// and advances the position within the stream by the number of bytes read. + /// + public override int Read(byte[] outBuffer, int offset, int count) { + int nBytes = 0; + while (nBytes < count) { + // Calculate buffer quantities vs read-ahead size, and check for sufficient free space + int byteCount = _slideBufFreePos - _slideBufStartPos; + + // Need to handle final block and Auth Code specially, but don't know total data length. + // Maintain a read-ahead equal to the length of (crypto block + Auth Code). + // When that runs out we can detect these final sections. + int lengthToRead = _blockAndAuth - byteCount; + if (_slideBuffer.Length - _slideBufFreePos < lengthToRead) { + // Shift the data to the beginning of the buffer + int iTo = 0; + for (int iFrom = _slideBufStartPos; iFrom < _slideBufFreePos; iFrom++, iTo++) { + _slideBuffer[iTo] = _slideBuffer[iFrom]; + } + _slideBufFreePos -= _slideBufStartPos; // Note the -= + _slideBufStartPos = 0; + } + int obtained = _stream.Read(_slideBuffer, _slideBufFreePos, lengthToRead); + _slideBufFreePos += obtained; + + // Recalculate how much data we now have + byteCount = _slideBufFreePos - _slideBufStartPos; + if (byteCount >= _blockAndAuth) { + // At least a 16 byte block and an auth code remains. + _transform.TransformBlock(_slideBuffer, + _slideBufStartPos, + CRYPTO_BLOCK_SIZE, + outBuffer, + offset); + nBytes += CRYPTO_BLOCK_SIZE; + offset += CRYPTO_BLOCK_SIZE; + _slideBufStartPos += CRYPTO_BLOCK_SIZE; + } else { + // Last round. + if (byteCount > AUTH_CODE_LENGTH) { + // At least one byte of data plus auth code + int finalBlock = byteCount - AUTH_CODE_LENGTH; + _transform.TransformBlock(_slideBuffer, + _slideBufStartPos, + finalBlock, + outBuffer, + offset); + + nBytes += finalBlock; + _slideBufStartPos += finalBlock; + } + else if (byteCount < AUTH_CODE_LENGTH) + throw new Exception("Internal error missed auth code"); // Coding bug + // Final block done. Check Auth code. + byte[] calcAuthCode = _transform.GetAuthCode(); + for (int i = 0; i < AUTH_CODE_LENGTH; i++) { + if (calcAuthCode[i] != _slideBuffer[_slideBufStartPos + i]) { + throw new Exception("AES Authentication Code does not match. This is a super-CRC check on the data in the file after compression and encryption. \r\n" + + "The file may be damaged."); + } + } + + break; // Reached the auth code + } + } + return nBytes; + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + public override void Write(byte[] buffer, int offset, int count) { + // ZipAESStream is used for reading but not for writing. Writing uses the ZipAESTransform directly. + throw new NotImplementedException(); + } + } +} +#endif \ No newline at end of file diff --git a/PCRobot/Utils/ZIP/Encryption/ZipAESTransform.cs b/PCRobot/Utils/ZIP/Encryption/ZipAESTransform.cs new file mode 100644 index 0000000..134c1eb --- /dev/null +++ b/PCRobot/Utils/ZIP/Encryption/ZipAESTransform.cs @@ -0,0 +1,219 @@ +// +// ZipAESTransform.cs +// +// Copyright 2009 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + +#if !NET_1_1 && !NETCF_2_0 +// Framework version 2.0 required for Rfc2898DeriveBytes + +using System; +using System.Security.Cryptography; + +namespace ICSharpCode.SharpZipLib.Encryption { + + /// + /// Transforms stream using AES in CTR mode + /// + internal class ZipAESTransform : ICryptoTransform { + + private const int PWD_VER_LENGTH = 2; + + // WinZip use iteration count of 1000 for PBKDF2 key generation + private const int KEY_ROUNDS = 1000; + + // For 128-bit AES (16 bytes) the encryption is implemented as expected. + // For 256-bit AES (32 bytes) WinZip do full 256 bit AES of the nonce to create the encryption + // block but use only the first 16 bytes of it, and discard the second half. + private const int ENCRYPT_BLOCK = 16; + + private int _blockSize; + private ICryptoTransform _encryptor; + private readonly byte[] _counterNonce; + private byte[] _encryptBuffer; + private int _encrPos; + private byte[] _pwdVerifier; + private HMACSHA1 _hmacsha1; + private bool _finalised; + + private bool _writeMode; + + /// + /// Constructor. + /// + /// Password string + /// Random bytes, length depends on encryption strength. + /// 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. + /// The encryption strength, in bytes eg 16 for 128 bits. + /// True when creating a zip, false when reading. For the AuthCode. + /// + public ZipAESTransform(string key, byte[] saltBytes, int blockSize, bool writeMode) { + + if (blockSize != 16 && blockSize != 32) // 24 valid for AES but not supported by Winzip + throw new Exception("Invalid blocksize " + blockSize + ". Must be 16 or 32."); + if (saltBytes.Length != blockSize / 2) + throw new Exception("Invalid salt len. Must be " + blockSize / 2 + " for blocksize " + blockSize); + // initialise the encryption buffer and buffer pos + _blockSize = blockSize; + _encryptBuffer = new byte[_blockSize]; + _encrPos = ENCRYPT_BLOCK; + + // Performs the equivalent of derive_key in Dr Brian Gladman's pwd2key.c + Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, saltBytes, KEY_ROUNDS); + RijndaelManaged rm = new RijndaelManaged(); + rm.Mode = CipherMode.ECB; // No feedback from cipher for CTR mode + _counterNonce = new byte[_blockSize]; + byte[] byteKey1 = pdb.GetBytes(_blockSize); + byte[] byteKey2 = pdb.GetBytes(_blockSize); + _encryptor = rm.CreateEncryptor(byteKey1, byteKey2); + _pwdVerifier = pdb.GetBytes(PWD_VER_LENGTH); + // + _hmacsha1 = new HMACSHA1(byteKey2); + _writeMode = writeMode; + } + + /// + /// Implement the ICryptoTransform method. + /// + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { + + // Pass the data stream to the hash algorithm for generating the Auth Code. + // This does not change the inputBuffer. Do this before decryption for read mode. + if (!_writeMode) { + _hmacsha1.TransformBlock(inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset); + } + // Encrypt with AES in CTR mode. Regards to Dr Brian Gladman for this. + int ix = 0; + while (ix < inputCount) { + if (_encrPos == ENCRYPT_BLOCK) { + /* increment encryption nonce */ + int j = 0; + while (++_counterNonce[j] == 0) { + ++j; + } + /* encrypt the nonce to form next xor buffer */ + _encryptor.TransformBlock(_counterNonce, 0, _blockSize, _encryptBuffer, 0); + _encrPos = 0; + } + outputBuffer[ix + outputOffset] = (byte)(inputBuffer[ix + inputOffset] ^ _encryptBuffer[_encrPos++]); + // + ix++; + } + if (_writeMode) { + // This does not change the buffer. + _hmacsha1.TransformBlock(outputBuffer, outputOffset, inputCount, outputBuffer, outputOffset); + } + return inputCount; + } + + /// + /// Returns the 2 byte password verifier + /// + public byte[] PwdVerifier { + get { + return _pwdVerifier; + } + } + + /// + /// Returns the 10 byte AUTH CODE to be checked or appended immediately following the AES data stream. + /// + public byte[] GetAuthCode() { + // We usually don't get advance notice of final block. Hash requres a TransformFinal. + if (!_finalised) { + byte[] dummy = new byte[0]; + _hmacsha1.TransformFinalBlock(dummy, 0, 0); + _finalised = true; + } + return _hmacsha1.Hash; + } + + #region ICryptoTransform Members + + /// + /// Not implemented. + /// + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { + + throw new NotImplementedException("ZipAESTransform.TransformFinalBlock"); + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize { + get { + return _blockSize; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize { + get { + return _blockSize; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks { + get { + return true; + } + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform { + get { + return true; + } + } + + /// + /// Cleanup internal state. + /// + public void Dispose() { + _encryptor.Dispose(); + } + + #endregion + + } +} +#endif \ No newline at end of file diff --git a/PCRobot/Utils/ZIP/GZip/GZIPConstants.cs b/PCRobot/Utils/ZIP/GZip/GZIPConstants.cs new file mode 100644 index 0000000..1c0e389 --- /dev/null +++ b/PCRobot/Utils/ZIP/GZip/GZIPConstants.cs @@ -0,0 +1,97 @@ +// GZipConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This class contains constants used for gzip. + /// + sealed public class GZipConstants + { + /// + /// Magic number found at start of GZIP header + /// + public const int GZIP_MAGIC = 0x1F8B; + + /* The flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + */ + + /// + /// Flag bit mask for text + /// + public const int FTEXT = 0x1; + + /// + /// Flag bitmask for Crc + /// + public const int FHCRC = 0x2; + + /// + /// Flag bit mask for extra + /// + public const int FEXTRA = 0x4; + + /// + /// flag bitmask for name + /// + public const int FNAME = 0x8; + + /// + /// flag bit mask indicating comment is present + /// + public const int FCOMMENT = 0x10; + + /// + /// Initialise default instance. + /// + /// Constructor is private to prevent instances being created. + GZipConstants() + { + } + } +} diff --git a/PCRobot/Utils/ZIP/GZip/GZipException.cs b/PCRobot/Utils/ZIP/GZip/GZipException.cs new file mode 100644 index 0000000..7f42931 --- /dev/null +++ b/PCRobot/Utils/ZIP/GZip/GZipException.cs @@ -0,0 +1,91 @@ +// GZipException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.GZip +{ + /// + /// GZipException represents a Gzip specific exception + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class GZipException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected GZipException(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + + /// + /// Initialise a new instance of GZipException + /// + public GZipException() + { + } + + /// + /// Initialise a new instance of GZipException with its message string. + /// + /// A that describes the error. + public GZipException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of . + /// + /// A that describes the error. + /// The that caused this exception. + public GZipException(string message, Exception innerException) + : base (message, innerException) + { + } + } +} diff --git a/PCRobot/Utils/ZIP/GZip/GzipInputStream.cs b/PCRobot/Utils/ZIP/GZip/GzipInputStream.cs new file mode 100644 index 0000000..4cbad94 --- /dev/null +++ b/PCRobot/Utils/ZIP/GZip/GzipInputStream.cs @@ -0,0 +1,384 @@ +// GzipInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 11-08-2009 GeoffHart T9121 Added Multi-member gzip support + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This filter stream is used to decompress a "GZIP" format stream. + /// The "GZIP" format is described baseInputStream RFC 1952. + /// + /// author of the original java version : John Leuner + /// + /// This sample shows how to unzip a gzipped file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.GZip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream inStream = new GZipInputStream(File.OpenRead(args[0]))) + /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + /// byte[] buffer = new byte[4096]; + /// StreamUtils.Copy(inStream, outStream, buffer); + /// } + /// } + /// } + /// + /// + public class GZipInputStream : InflaterInputStream + { + #region Instance Fields + /// + /// CRC-32 value for uncompressed data + /// + protected Crc32 crc; + + /// + /// Flag to indicate if we've read the GZIP header yet for the current member (block of compressed data). + /// This is tracked per-block as the file is parsed. + /// + bool readGZIPHeader; + #endregion + + #region Constructors + /// + /// Creates a GZipInputStream with the default buffer size + /// + /// + /// The stream to read compressed data from (baseInputStream GZIP format) + /// + public GZipInputStream(Stream baseInputStream) + : this(baseInputStream, 4096) + { + } + + /// + /// Creates a GZIPInputStream with the specified buffer size + /// + /// + /// The stream to read compressed data from (baseInputStream GZIP format) + /// + /// + /// Size of the buffer to use + /// + public GZipInputStream(Stream baseInputStream, int size) + : base(baseInputStream, new Inflater(true), size) + { + } + #endregion + + #region Stream overrides + /// + /// Reads uncompressed data into an array of bytes + /// + /// + /// The buffer to read uncompressed data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of uncompressed bytes to be read + /// + /// Returns the number of bytes actually read. + public override int Read(byte[] buffer, int offset, int count) + { + // A GZIP file can contain multiple blocks of compressed data, although this is quite rare. + // A compressed block could potentially be empty, so we need to loop until we reach EOF or + // we find data. + while (true) { + + // If we haven't read the header for this block, read it + if (! readGZIPHeader) { + + // Try to read header. If there is no header (0 bytes available), this is EOF. If there is + // an incomplete header, this will throw an exception. + if (! ReadHeader()) { + return 0; + } + } + + // Try to read compressed data + int bytesRead = base.Read(buffer, offset, count); + if (bytesRead > 0) { + crc.Update(buffer, offset, bytesRead); + } + + // If this is the end of stream, read the footer + if (inf.IsFinished) { + ReadFooter(); + } + + if (bytesRead > 0) { + return bytesRead; + } + } + } + #endregion + + #region Support routines + bool ReadHeader() + { + // Initialize CRC for this block + crc = new Crc32(); + + // Make sure there is data in file. We can't rely on ReadLeByte() to fill the buffer, as this could be EOF, + // which is fine, but ReadLeByte() throws an exception if it doesn't find data, so we do this part ourselves. + if (inputBuffer.Available <= 0) { + inputBuffer.Fill(); + if (inputBuffer.Available <= 0) { + // No header, EOF. + return false; + } + } + + // 1. Check the two magic bytes + Crc32 headCRC = new Crc32(); + int magic = inputBuffer.ReadLeByte(); + + if (magic < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + headCRC.Update(magic); + if (magic != (GZipConstants.GZIP_MAGIC >> 8)) { + throw new GZipException("Error GZIP header, first magic byte doesn't match"); + } + + //magic = baseInputStream.ReadByte(); + magic = inputBuffer.ReadLeByte(); + + if (magic < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + if (magic != (GZipConstants.GZIP_MAGIC & 0xFF)) { + throw new GZipException("Error GZIP header, second magic byte doesn't match"); + } + + headCRC.Update(magic); + + // 2. Check the compression type (must be 8) + int compressionType = inputBuffer.ReadLeByte(); + + if ( compressionType < 0 ) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + if ( compressionType != 8 ) { + throw new GZipException("Error GZIP header, data not in deflate format"); + } + headCRC.Update(compressionType); + + // 3. Check the flags + int flags = inputBuffer.ReadLeByte(); + if (flags < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(flags); + + /* This flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + */ + + // 3.1 Check the reserved bits are zero + + if ((flags & 0xE0) != 0) { + throw new GZipException("Reserved flag bits in GZIP header != 0"); + } + + // 4.-6. Skip the modification time, extra flags, and OS type + for (int i=0; i< 6; i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + // 7. Read extra field + if ((flags & GZipConstants.FEXTRA) != 0) { + // Skip subfield id + for (int i=0; i< 2; i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + if (inputBuffer.ReadLeByte() < 0 || inputBuffer.ReadLeByte() < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + int len1, len2; + len1 = inputBuffer.ReadLeByte(); + len2 = inputBuffer.ReadLeByte(); + if ((len1 < 0) || (len2 < 0)) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(len1); + headCRC.Update(len2); + + int extraLen = (len1 << 8) | len2; + for (int i = 0; i < extraLen;i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) + { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + } + + // 8. Read file name + if ((flags & GZipConstants.FNAME) != 0) { + int readByte; + while ( (readByte = inputBuffer.ReadLeByte()) > 0) { + headCRC.Update(readByte); + } + + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + // 9. Read comment + if ((flags & GZipConstants.FCOMMENT) != 0) { + int readByte; + while ( (readByte = inputBuffer.ReadLeByte()) > 0) { + headCRC.Update(readByte); + } + + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + headCRC.Update(readByte); + } + + // 10. Read header CRC + if ((flags & GZipConstants.FHCRC) != 0) { + int tempByte; + int crcval = inputBuffer.ReadLeByte(); + if (crcval < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + tempByte = inputBuffer.ReadLeByte(); + if (tempByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + crcval = (crcval << 8) | tempByte; + if (crcval != ((int) headCRC.Value & 0xffff)) { + throw new GZipException("Header CRC value mismatch"); + } + } + + readGZIPHeader = true; + return true; + } + + void ReadFooter() + { + byte[] footer = new byte[8]; + + // End of stream; reclaim all bytes from inf, read the final byte count, and reset the inflator + long bytesRead = inf.TotalOut & 0xffffffff; + inputBuffer.Available += inf.RemainingInput; + inf.Reset(); + + // Read footer from inputBuffer + int needed = 8; + while (needed > 0) { + int count = inputBuffer.ReadClearTextBuffer(footer, 8 - needed, needed); + if (count <= 0) { + throw new EndOfStreamException("EOS reading GZIP footer"); + } + needed -= count; // Jewel Jan 16 + } + + // Calculate CRC + int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8) | ((footer[2] & 0xff) << 16) | (footer[3] << 24); + if (crcval != (int) crc.Value) { + throw new GZipException("GZIP crc sum mismatch, theirs \"" + crcval + "\" and ours \"" + (int) crc.Value); + } + + // NOTE The total here is the original total modulo 2 ^ 32. + uint total = + (uint)((uint)footer[4] & 0xff) | + (uint)(((uint)footer[5] & 0xff) << 8) | + (uint)(((uint)footer[6] & 0xff) << 16) | + (uint)((uint)footer[7] << 24); + + if (bytesRead != total) { + throw new GZipException("Number of bytes mismatch in footer"); + } + + // Mark header read as false so if another header exists, we'll continue reading through the file + readGZIPHeader = false; + } + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/GZip/GzipOutputStream.cs b/PCRobot/Utils/ZIP/GZip/GzipOutputStream.cs new file mode 100644 index 0000000..0db2e4b --- /dev/null +++ b/PCRobot/Utils/ZIP/GZip/GzipOutputStream.cs @@ -0,0 +1,261 @@ +// GZipOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This filter stream is used to compress a stream into a "GZIP" stream. + /// The "GZIP" format is described in RFC 1952. + /// + /// author of the original java version : John Leuner + /// + /// This sample shows how to gzip a file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.GZip; + /// using ICSharpCode.SharpZipLib.Core; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz"))) + /// using (FileStream fs = File.OpenRead(args[0])) { + /// byte[] writeData = new byte[4096]; + /// Streamutils.Copy(s, fs, writeData); + /// } + /// } + /// } + /// } + /// + /// + public class GZipOutputStream : DeflaterOutputStream + { + enum OutputState + { + Header, + Footer, + Finished, + Closed, + }; + + #region Instance Fields + /// + /// CRC-32 value for uncompressed data + /// + protected Crc32 crc = new Crc32(); + OutputState state_ = OutputState.Header; + #endregion + + #region Constructors + /// + /// Creates a GzipOutputStream with the default buffer size + /// + /// + /// The stream to read data (to be compressed) from + /// + public GZipOutputStream(Stream baseOutputStream) + : this(baseOutputStream, 4096) + { + } + + /// + /// Creates a GZipOutputStream with the specified buffer size + /// + /// + /// The stream to read data (to be compressed) from + /// + /// + /// Size of the buffer to use + /// + public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size) + { + } + #endregion + + #region Public API + /// + /// Sets the active compression level (1-9). The new level will be activated + /// immediately. + /// + /// The compression level to set. + /// + /// Level specified is not supported. + /// + /// + public void SetLevel(int level) + { + if (level < Deflater.BEST_SPEED) { + throw new ArgumentOutOfRangeException("level"); + } + deflater_.SetLevel(level); + } + + /// + /// Get the current compression level. + /// + /// The current compression level. + public int GetLevel() + { + return deflater_.GetLevel(); + } + #endregion + + #region Stream overrides + /// + /// Write given buffer to output updating crc + /// + /// Buffer to write + /// Offset of first byte in buf to write + /// Number of bytes to write + public override void Write(byte[] buffer, int offset, int count) + { + if ( state_ == OutputState.Header ) { + WriteHeader(); + } + + if( state_!=OutputState.Footer ) + { + throw new InvalidOperationException("Write not permitted in current state"); + } + + crc.Update(buffer, offset, count); + base.Write(buffer, offset, count); + } + + /// + /// Writes remaining compressed output data to the output stream + /// and closes it. + /// + public override void Close() + { + try { + Finish(); + } + finally { + if ( state_ != OutputState.Closed ) { + state_ = OutputState.Closed; + if( IsStreamOwner ) { + baseOutputStream_.Close(); + } + } + } + } + #endregion + + #region DeflaterOutputStream overrides + /// + /// Finish compression and write any footer information required to stream + /// + public override void Finish() + { + // If no data has been written a header should be added. + if ( state_ == OutputState.Header ) { + WriteHeader(); + } + + if( state_ == OutputState.Footer) + { + state_=OutputState.Finished; + base.Finish(); + + uint totalin=(uint)(deflater_.TotalIn&0xffffffff); + uint crcval=(uint)(crc.Value&0xffffffff); + + byte[] gzipFooter; + + unchecked + { + gzipFooter=new byte[] { + (byte) crcval, (byte) (crcval >> 8), + (byte) (crcval >> 16), (byte) (crcval >> 24), + + (byte) totalin, (byte) (totalin >> 8), + (byte) (totalin >> 16), (byte) (totalin >> 24) + }; + } + + baseOutputStream_.Write(gzipFooter, 0, gzipFooter.Length); + } + } + #endregion + + #region Support Routines + void WriteHeader() + { + if ( state_ == OutputState.Header ) + { + state_=OutputState.Footer; + + int mod_time = (int)((DateTime.Now.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000L); // Ticks give back 100ns intervals + byte[] gzipHeader = { + // The two magic bytes + (byte) (GZipConstants.GZIP_MAGIC >> 8), (byte) (GZipConstants.GZIP_MAGIC & 0xff), + + // The compression type + (byte) Deflater.DEFLATED, + + // The flags (not set) + 0, + + // The modification time + (byte) mod_time, (byte) (mod_time >> 8), + (byte) (mod_time >> 16), (byte) (mod_time >> 24), + + // The extra flags + 0, + + // The OS type (unknown) + (byte) 255 + }; + baseOutputStream_.Write(gzipHeader, 0, gzipHeader.Length); + } + } + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Lzw/LzwConstants.cs b/PCRobot/Utils/ZIP/Lzw/LzwConstants.cs new file mode 100644 index 0000000..699ed09 --- /dev/null +++ b/PCRobot/Utils/ZIP/Lzw/LzwConstants.cs @@ -0,0 +1,94 @@ +// LzwConstants.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.LZW { + + /// + /// This class contains constants used for LZW + /// + sealed public class LzwConstants { + /// + /// Magic number found at start of LZW header: 0x1f 0x9d + /// + public const int MAGIC = 0x1f9d; + + /// + /// Maximum number of bits per code + /// + public const int MAX_BITS = 16; + + /* 3rd header byte: + * bit 0..4 Number of compression bits + * bit 5 Extended header + * bit 6 Free + * bit 7 Block mode + */ + + /// + /// Mask for 'number of compression bits' + /// + public const int BIT_MASK = 0x1f; + + /// + /// Indicates the presence of a fourth header byte + /// + public const int EXTENDED_MASK = 0x20; + //public const int FREE_MASK = 0x40; + + /// + /// Reserved bits + /// + public const int RESERVED_MASK = 0x60; + + /// + /// Block compression: if table is full and compression rate is dropping, + /// clear the dictionary. + /// + public const int BLOCK_MODE_MASK = 0x80; + + /// + /// LZW file header size (in bytes) + /// + public const int HDR_SIZE = 3; + + /// + /// Initial number of bits per code + /// + public const int INIT_BITS = 9; + + LzwConstants() { + } + } +} diff --git a/PCRobot/Utils/ZIP/Lzw/LzwException.cs b/PCRobot/Utils/ZIP/Lzw/LzwException.cs new file mode 100644 index 0000000..10a9547 --- /dev/null +++ b/PCRobot/Utils/ZIP/Lzw/LzwException.cs @@ -0,0 +1,88 @@ +// LzwException.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.LZW +{ + + /// + /// LzwException represents a LZW specific exception + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class LzwException : SharpZipBaseException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected LzwException(SerializationInfo info, StreamingContext context) + : base(info, context) { + } +#endif + + /// + /// Initialise a new instance of LzwException + /// + public LzwException() { + } + + /// + /// Initialise a new instance of LzwException with its message string. + /// + /// A that describes the error. + public LzwException(string message) + : base(message) { + } + + /// + /// Initialise a new instance of . + /// + /// A that describes the error. + /// The that caused this exception. + public LzwException(string message, Exception innerException) + : base(message, innerException) { + } + } +} diff --git a/PCRobot/Utils/ZIP/Lzw/LzwInputStream.cs b/PCRobot/Utils/ZIP/Lzw/LzwInputStream.cs new file mode 100644 index 0000000..94b8b66 --- /dev/null +++ b/PCRobot/Utils/ZIP/Lzw/LzwInputStream.cs @@ -0,0 +1,598 @@ +// LzwInputStream.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.LZW +{ + + /// + /// This filter stream is used to decompress a LZW format stream. + /// Specifically, a stream that uses the LZC compression method. + /// This file format is usually associated with the .Z file extension. + /// + /// See http://en.wikipedia.org/wiki/Compress + /// See http://wiki.wxwidgets.org/Development:_Z_File_Format + /// + /// The file header consists of 3 (or optionally 4) bytes. The first two bytes + /// contain the magic marker "0x1f 0x9d", followed by a byte of flags. + /// + /// Based on Java code by Ronald Tschalar, which in turn was based on the unlzw.c + /// code in the gzip package. + /// + /// This sample shows how to unzip a compressed file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.LZW; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream inStream = new LzwInputStream(File.OpenRead(args[0]))) + /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + /// byte[] buffer = new byte[4096]; + /// StreamUtils.Copy(inStream, outStream, buffer); + /// // OR + /// inStream.Read(buffer, 0, buffer.Length); + /// // now do something with the buffer + /// } + /// } + /// } + /// + /// + public class LzwInputStream : Stream + { + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + /// + /// The default value is true. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Creates a LzwInputStream + /// + /// + /// The stream to read compressed data from (baseInputStream LZW format) + /// + public LzwInputStream(Stream baseInputStream) { + this.baseInputStream = baseInputStream; + } + + /// + /// See + /// + /// + public override int ReadByte() { + int b = Read(one, 0, 1); + if (b == 1) + return (one[0] & 0xff); + return -1; + } + + /// + /// Reads decompressed data into the provided buffer byte array + /// + /// + /// The array to read and decompress data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of bytes to decompress + /// + /// The number of bytes read. Zero signals the end of stream + public override int Read(byte[] buffer, int offset, int count) { + if (!headerParsed) ParseHeader(); + + if (eof) return -1; + int start = offset; + + /* Using local copies of various variables speeds things up by as + * much as 30% in Java! Performance not tested in C#. + */ + int[] lTabPrefix = tabPrefix; + byte[] lTabSuffix = tabSuffix; + byte[] lStack = stack; + int lNBits = nBits; + int lMaxCode = maxCode; + int lMaxMaxCode = maxMaxCode; + int lBitMask = bitMask; + int lOldCode = oldCode; + byte lFinChar = finChar; + int lStackP = stackP; + int lFreeEnt = freeEnt; + byte[] lData = data; + int lBitPos = bitPos; + + + // empty stack if stuff still left + int sSize = lStack.Length - lStackP; + if (sSize > 0) { + int num = (sSize >= count) ? count : sSize; + Array.Copy(lStack, lStackP, buffer, offset, num); + offset += num; + count -= num; + lStackP += num; + } + + if (count == 0) { + stackP = lStackP; + return offset - start; + } + + + // loop, filling local buffer until enough data has been decompressed + MainLoop: do { + if (end < EXTRA) { + Fill(); + } + + int bitIn = (got > 0) ? (end - end % lNBits) << 3 : + (end << 3) - (lNBits - 1); + + while (lBitPos < bitIn) { + #region A + // handle 1-byte reads correctly + if (count == 0) { + nBits = lNBits; + maxCode = lMaxCode; + maxMaxCode = lMaxMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + return offset - start; + } + + // check for code-width expansion + if (lFreeEnt > lMaxCode) { + int nBytes = lNBits << 3; + lBitPos = (lBitPos - 1) + + nBytes - (lBitPos - 1 + nBytes) % nBytes; + + lNBits++; + lMaxCode = (lNBits == maxBits) ? lMaxMaxCode : + (1 << lNBits) - 1; + + lBitMask = (1 << lNBits) - 1; + lBitPos = ResetBuf(lBitPos); + goto MainLoop; + } + #endregion + + #region B + // read next code + int pos = lBitPos >> 3; + int code = (((lData[pos] & 0xFF) | + ((lData[pos + 1] & 0xFF) << 8) | + ((lData[pos + 2] & 0xFF) << 16)) >> + (lBitPos & 0x7)) & lBitMask; + + lBitPos += lNBits; + + // handle first iteration + if (lOldCode == -1) { + if (code >= 256) throw new LzwException("corrupt input: " + code + " > 255"); + + lFinChar = (byte) (lOldCode = code); + buffer[offset++] = lFinChar; + count--; + continue; + } + + // handle CLEAR code + if (code == TBL_CLEAR && blockMode) { + Array.Copy(zeros, 0, lTabPrefix, 0, zeros.Length); + lFreeEnt = TBL_FIRST - 1; + + int nBytes = lNBits << 3; + lBitPos = (lBitPos - 1) + nBytes - (lBitPos - 1 + nBytes) % nBytes; + lNBits = LzwConstants.INIT_BITS; + lMaxCode = (1 << lNBits) - 1; + lBitMask = lMaxCode; + + // Code tables reset + + lBitPos = ResetBuf(lBitPos); + goto MainLoop; + } + #endregion + + #region C + // setup + int inCode = code; + lStackP = lStack.Length; + + // Handle KwK case + if (code >= lFreeEnt) { + if (code > lFreeEnt) { + throw new LzwException("corrupt input: code=" + code + + ", freeEnt=" + lFreeEnt); + } + + lStack[--lStackP] = lFinChar; + code = lOldCode; + } + + // Generate output characters in reverse order + while (code >= 256) { + lStack[--lStackP] = lTabSuffix[code]; + code = lTabPrefix[code]; + } + + lFinChar = lTabSuffix[code]; + buffer[offset++] = lFinChar; + count--; + + // And put them out in forward order + sSize = lStack.Length - lStackP; + int num = (sSize >= count) ? count : sSize; + Array.Copy(lStack, lStackP, buffer, offset, num); + offset += num; + count -= num; + lStackP += num; + #endregion + + #region D + // generate new entry in table + if (lFreeEnt < lMaxMaxCode) { + lTabPrefix[lFreeEnt] = lOldCode; + lTabSuffix[lFreeEnt] = lFinChar; + lFreeEnt++; + } + + // Remember previous code + lOldCode = inCode; + + // if output buffer full, then return + if (count == 0) { + nBits = lNBits; + maxCode = lMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + return offset - start; + } + #endregion + } // while + + lBitPos = ResetBuf(lBitPos); + + } while (got > 0); // do..while + + nBits = lNBits; + maxCode = lMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + eof = true; + return offset - start; + } + + /// + /// Moves the unread data in the buffer to the beginning and resets + /// the pointers. + /// + /// + /// + private int ResetBuf(int bitPosition) { + int pos = bitPosition >> 3; + Array.Copy(data, pos, data, 0, end - pos); + end -= pos; + return 0; + } + + + private void Fill() { + got = baseInputStream.Read(data, end, data.Length - 1 - end); + if (got > 0) { + end += got; + } + } + + + private void ParseHeader() { + headerParsed = true; + + byte[] hdr = new byte[LzwConstants.HDR_SIZE]; + + int result = baseInputStream.Read(hdr, 0, hdr.Length); + + // Check the magic marker + if (result < 0) + throw new LzwException("Failed to read LZW header"); + + if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) { + throw new LzwException(String.Format( + "Wrong LZW header. Magic bytes don't match. 0x{0:x2} 0x{1:x2}", + hdr[0], hdr[1])); + } + + // Check the 3rd header byte + blockMode = (hdr[2] & LzwConstants.BLOCK_MODE_MASK) > 0; + maxBits = hdr[2] & LzwConstants.BIT_MASK; + + if (maxBits > LzwConstants.MAX_BITS) { + throw new LzwException("Stream compressed with " + maxBits + + " bits, but decompression can only handle " + + LzwConstants.MAX_BITS + " bits."); + } + + if ((hdr[2] & LzwConstants.RESERVED_MASK) > 0) { + throw new LzwException("Unsupported bits set in the header."); + } + + // Initialize variables + maxMaxCode = 1 << maxBits; + nBits = LzwConstants.INIT_BITS; + maxCode = (1 << nBits) - 1; + bitMask = maxCode; + oldCode = -1; + finChar = 0; + freeEnt = blockMode ? TBL_FIRST : 256; + + tabPrefix = new int[1 << maxBits]; + tabSuffix = new byte[1 << maxBits]; + stack = new byte[1 << maxBits]; + stackP = stack.Length; + + for (int idx = 255; idx >= 0; idx--) + tabSuffix[idx] = (byte)idx; + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get + { + return baseInputStream.CanRead; + } + } + + /// + /// Gets a value of false indicating seeking is not supported for this stream. + /// + public override bool CanSeek + { + get + { + return false; + } + } + + /// + /// Gets a value of false indicating that this stream is not writeable. + /// + public override bool CanWrite + { + get + { + return false; + } + } + + /// + /// A value representing the length of the stream in bytes. + /// + public override long Length + { + get + { + return got; + } + } + + /// + /// The current position within the stream. + /// Throws a NotSupportedException when attempting to set the position + /// + /// Attempting to set the position + public override long Position + { + get + { + return baseInputStream.Position; + } + set + { + throw new NotSupportedException("InflaterInputStream Position not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + baseInputStream.Flush(); + } + + /// + /// Sets the position within the current stream + /// Always throws a NotSupportedException + /// + /// The relative offset to seek to. + /// The defining where to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Seek not supported"); + } + + /// + /// Set the length of the current stream + /// Always throws a NotSupportedException + /// + /// The new length value for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("InflaterInputStream SetLength not supported"); + } + + /// + /// Writes a sequence of bytes to stream and advances the current position + /// This method always throws a NotSupportedException + /// + /// Thew buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("InflaterInputStream Write not supported"); + } + + /// + /// Writes one byte to the current stream and advances the current position + /// Always throws a NotSupportedException + /// + /// The byte to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("InflaterInputStream WriteByte not supported"); + } + + /// + /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. + /// + /// The buffer to write data from + /// Offset of first byte to write + /// The maximum number of bytes to write + /// The method to be called when the asynchronous write operation is completed + /// A user-provided object that distinguishes this particular asynchronous write request from other requests + /// An IAsyncResult that references the asynchronous write + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); + } + + /// + /// Closes the input stream. When + /// is true the underlying stream is also closed. + /// + public override void Close() + { + if (!isClosed) + { + isClosed = true; + if (isStreamOwner) + { + baseInputStream.Close(); + } + } + } + + #endregion + + #region Instance Fields + + Stream baseInputStream; + + /// + /// Flag indicating wether this instance is designated the stream owner. + /// When closing if this flag is true the underlying stream is closed. + /// + bool isStreamOwner = true; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + readonly byte[] one = new byte[1]; + bool headerParsed; + + // string table stuff + private const int TBL_CLEAR = 0x100; + private const int TBL_FIRST = TBL_CLEAR + 1; + + private int[] tabPrefix; + private byte[] tabSuffix; + private readonly int[] zeros = new int[256]; + private byte[] stack; + + // various state + private bool blockMode; + private int nBits; + private int maxBits; + private int maxMaxCode; + private int maxCode; + private int bitMask; + private int oldCode; + private byte finChar; + private int stackP; + private int freeEnt; + + // input buffer + private readonly byte[] data = new byte[1024 * 8]; + private int bitPos; + private int end; + int got; + private bool eof; + private const int EXTRA = 64; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/SharpZipBaseException.cs b/PCRobot/Utils/ZIP/SharpZipBaseException.cs new file mode 100644 index 0000000..7a5d136 --- /dev/null +++ b/PCRobot/Utils/ZIP/SharpZipBaseException.cs @@ -0,0 +1,94 @@ +// SharpZipBaseException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib +{ + /// + /// SharpZipBaseException is the base exception class for the SharpZipLibrary. + /// All library exceptions are derived from this. + /// + /// NOTE: Not all exceptions thrown will be derived from this class. + /// A variety of other exceptions are possible for example +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class SharpZipBaseException : ApplicationException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected SharpZipBaseException(SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } +#endif + + /// + /// Initializes a new instance of the SharpZipBaseException class. + /// + public SharpZipBaseException() + { + } + + /// + /// Initializes a new instance of the SharpZipBaseException class with a specified error message. + /// + /// A message describing the exception. + public SharpZipBaseException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the SharpZipBaseException class with a specified + /// error message and a reference to the inner exception that is the cause of this exception. + /// + /// A message describing the exception. + /// The inner exception + public SharpZipBaseException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/PCRobot/Utils/ZIP/Tar/InvalidHeaderException.cs b/PCRobot/Utils/ZIP/Tar/InvalidHeaderException.cs new file mode 100644 index 0000000..bac9343 --- /dev/null +++ b/PCRobot/Utils/ZIP/Tar/InvalidHeaderException.cs @@ -0,0 +1,109 @@ +// InvalidHeaderException.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Tar { + + /// + /// This exception is used to indicate that there is a problem + /// with a TAR archive header. + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class InvalidHeaderException : TarException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected InvalidHeaderException(SerializationInfo information, StreamingContext context) + : base(information, context) + + { + } +#endif + + /// + /// Initialise a new instance of the InvalidHeaderException class. + /// + public InvalidHeaderException() + { + } + + /// + /// Initialises a new instance of the InvalidHeaderException class with a specified message. + /// + /// Message describing the exception cause. + public InvalidHeaderException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of InvalidHeaderException + /// + /// Message describing the problem. + /// The exception that is the cause of the current exception. + public InvalidHeaderException(string message, Exception exception) + : base(message, exception) + { + } + } +} + +/* The original Java file had this header: +** Authored by Timothy Gerard Endres +** +** +** This work has been placed into the public domain. +** You may use this work in any way and for any purpose you wish. +** +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR +** REDISTRIBUTION OF THIS SOFTWARE. +** +*/ + diff --git a/PCRobot/Utils/ZIP/Tar/TarArchive.cs b/PCRobot/Utils/ZIP/Tar/TarArchive.cs new file mode 100644 index 0000000..5a5510b --- /dev/null +++ b/PCRobot/Utils/ZIP/Tar/TarArchive.cs @@ -0,0 +1,894 @@ +// TarArchive.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 28-01-2010 DavidPierson Added IsStreamOwner + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + /// + /// Used to advise clients of 'events' while processing archives + /// + public delegate void ProgressMessageHandler(TarArchive archive, TarEntry entry, string message); + + /// + /// The TarArchive class implements the concept of a + /// 'Tape Archive'. A tar archive is a series of entries, each of + /// which represents a file system object. Each entry in + /// the archive consists of a header block followed by 0 or more data blocks. + /// Directory entries consist only of the header block, and are followed by entries + /// for the directory's contents. File entries consist of a + /// header followed by the number of blocks needed to + /// contain the file's contents. All entries are written on + /// block boundaries. Blocks are 512 bytes long. + /// + /// TarArchives are instantiated in either read or write mode, + /// based upon whether they are instantiated with an InputStream + /// or an OutputStream. Once instantiated TarArchives read/write + /// mode can not be changed. + /// + /// There is currently no support for random access to tar archives. + /// However, it seems that subclassing TarArchive, and using the + /// TarBuffer.CurrentRecord and TarBuffer.CurrentBlock + /// properties, this would be rather trivial. + /// + public class TarArchive : IDisposable + { + /// + /// Client hook allowing detailed information to be reported during processing + /// + public event ProgressMessageHandler ProgressMessageEvent; + + /// + /// Raises the ProgressMessage event + /// + /// The TarEntry for this event + /// message for this event. Null is no message + protected virtual void OnProgressMessageEvent(TarEntry entry, string message) + { + ProgressMessageHandler handler = ProgressMessageEvent; + if (handler != null) { + handler(this, entry, message); + } + } + + #region Constructors + /// + /// Constructor for a default . + /// + protected TarArchive() + { + } + + /// + /// Initalise a TarArchive for input. + /// + /// The to use for input. + protected TarArchive(TarInputStream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + tarIn = stream; + } + + /// + /// Initialise a TarArchive for output. + /// + /// The to use for output. + protected TarArchive(TarOutputStream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + tarOut = stream; + } + #endregion + + #region Static factory methods + /// + /// The InputStream based constructors create a TarArchive for the + /// purposes of extracting or listing a tar archive. Thus, use + /// these constructors when you wish to extract files from or list + /// the contents of an existing tar archive. + /// + /// The stream to retrieve archive data from. + /// Returns a new suitable for reading from. + public static TarArchive CreateInputTarArchive(Stream inputStream) + { + if ( inputStream == null ) { + throw new ArgumentNullException("inputStream"); + } + + TarInputStream tarStream = inputStream as TarInputStream; + + TarArchive result; + if ( tarStream != null ) { + result = new TarArchive(tarStream); + } + else { + result = CreateInputTarArchive(inputStream, TarBuffer.DefaultBlockFactor); + } + return result; + } + + /// + /// Create TarArchive for reading setting block factor + /// + /// A stream containing the tar archive contents + /// The blocking factor to apply + /// Returns a suitable for reading. + public static TarArchive CreateInputTarArchive(Stream inputStream, int blockFactor) + { + if ( inputStream == null ) { + throw new ArgumentNullException("inputStream"); + } + + if ( inputStream is TarInputStream ) { + throw new ArgumentException("TarInputStream not valid"); + } + + return new TarArchive(new TarInputStream(inputStream, blockFactor)); + } + + /// + /// Create a TarArchive for writing to, using the default blocking factor + /// + /// The to write to + /// Returns a suitable for writing. + public static TarArchive CreateOutputTarArchive(Stream outputStream) + { + if ( outputStream == null ) { + throw new ArgumentNullException("outputStream"); + } + + TarOutputStream tarStream = outputStream as TarOutputStream; + + TarArchive result; + if ( tarStream != null ) { + result = new TarArchive(tarStream); + } + else { + result = CreateOutputTarArchive(outputStream, TarBuffer.DefaultBlockFactor); + } + return result; + } + + /// + /// Create a tar archive for writing. + /// + /// The stream to write to + /// The blocking factor to use for buffering. + /// Returns a suitable for writing. + public static TarArchive CreateOutputTarArchive(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) { + throw new ArgumentNullException("outputStream"); + } + + if ( outputStream is TarOutputStream ) { + throw new ArgumentException("TarOutputStream is not valid"); + } + + return new TarArchive(new TarOutputStream(outputStream, blockFactor)); + } + #endregion + + /// + /// Set the flag that determines whether existing files are + /// kept, or overwritten during extraction. + /// + /// + /// If true, do not overwrite existing files. + /// + public void SetKeepOldFiles(bool keepExistingFiles) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + keepOldFiles = keepExistingFiles; + } + + /// + /// Get/set the ascii file translation flag. If ascii file translation + /// is true, then the file is checked to see if it a binary file or not. + /// If the flag is true and the test indicates it is ascii text + /// file, it will be translated. The translation converts the local + /// operating system's concept of line ends into the UNIX line end, + /// '\n', which is the defacto standard for a TAR archive. This makes + /// text files compatible with UNIX. + /// + public bool AsciiTranslate + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return asciiTranslate; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + asciiTranslate = value; + } + + } + + /// + /// Set the ascii file translation flag. + /// + /// + /// If true, translate ascii text files. + /// + [Obsolete("Use the AsciiTranslate property")] + public void SetAsciiTranslation(bool translateAsciiFiles) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + asciiTranslate = translateAsciiFiles; + } + + /// + /// PathPrefix is added to entry names as they are written if the value is not null. + /// A slash character is appended after PathPrefix + /// + public string PathPrefix + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return pathPrefix; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + pathPrefix = value; + } + + } + + /// + /// RootPath is removed from entry names if it is found at the + /// beginning of the name. + /// + public string RootPath + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return rootPath; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + rootPath = value; + } + } + + /// + /// Set user and group information that will be used to fill in the + /// tar archive's entry headers. This information is based on that available + /// for the linux operating system, which is not always available on other + /// operating systems. TarArchive allows the programmer to specify values + /// to be used in their place. + /// is set to true by this call. + /// + /// + /// The user id to use in the headers. + /// + /// + /// The user name to use in the headers. + /// + /// + /// The group id to use in the headers. + /// + /// + /// The group name to use in the headers. + /// + public void SetUserInfo(int userId, string userName, int groupId, string groupName) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + this.userId = userId; + this.userName = userName; + this.groupId = groupId; + this.groupName = groupName; + applyUserInfoOverrides = true; + } + + /// + /// Get or set a value indicating if overrides defined by SetUserInfo should be applied. + /// + /// If overrides are not applied then the values as set in each header will be used. + public bool ApplyUserInfoOverrides + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return applyUserInfoOverrides; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + applyUserInfoOverrides = value; + } + } + + /// + /// Get the archive user id. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current user id. + /// + public int UserId { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return userId; + } + } + + /// + /// Get the archive user name. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current user name. + /// + public string UserName { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return userName; + } + } + + /// + /// Get the archive group id. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current group id. + /// + public int GroupId { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return groupId; + } + } + + /// + /// Get the archive group name. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current group name. + /// + public string GroupName { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return groupName; + } + } + + /// + /// Get the archive's record size. Tar archives are composed of + /// a series of RECORDS each containing a number of BLOCKS. + /// This allowed tar archives to match the IO characteristics of + /// the physical device being used. Archives are expected + /// to be properly "blocked". + /// + /// + /// The record size this archive is using. + /// + public int RecordSize { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + if (tarIn != null) { + return tarIn.RecordSize; + } else if (tarOut != null) { + return tarOut.RecordSize; + } + return TarBuffer.DefaultRecordSize; + } + } + + /// + /// Sets the IsStreamOwner property on the underlying stream. + /// Set this to false to prevent the Close of the TarArchive from closing the stream. + /// + public bool IsStreamOwner { + set { + if (tarIn != null) { + tarIn.IsStreamOwner = value; + } else { + tarOut.IsStreamOwner = value; + } + } + } + + /// + /// Close the archive. + /// + [Obsolete("Use Close instead")] + public void CloseArchive() + { + Close(); + } + + /// + /// Perform the "list" command for the archive contents. + /// + /// NOTE That this method uses the progress event to actually list + /// the contents. If the progress display event is not set, nothing will be listed! + /// + public void ListContents() + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + while (true) { + TarEntry entry = tarIn.GetNextEntry(); + + if (entry == null) { + break; + } + OnProgressMessageEvent(entry, null); + } + } + + /// + /// Perform the "extract" command and extract the contents of the archive. + /// + /// + /// The destination directory into which to extract. + /// + public void ExtractContents(string destinationDirectory) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + while (true) { + TarEntry entry = tarIn.GetNextEntry(); + + if (entry == null) { + break; + } + + ExtractEntry(destinationDirectory, entry); + } + } + + /// + /// Extract an entry from the archive. This method assumes that the + /// tarIn stream has been properly set with a call to GetNextEntry(). + /// + /// + /// The destination directory into which to extract. + /// + /// + /// The TarEntry returned by tarIn.GetNextEntry(). + /// + void ExtractEntry(string destDir, TarEntry entry) + { + OnProgressMessageEvent(entry, null); + + string name = entry.Name; + + if (Path.IsPathRooted(name)) { + // NOTE: + // for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt + name = name.Substring(Path.GetPathRoot(name).Length); + } + + name = name.Replace('/', Path.DirectorySeparatorChar); + + string destFile = Path.Combine(destDir, name); + + if (entry.IsDirectory) { + EnsureDirectoryExists(destFile); + } else { + string parentDirectory = Path.GetDirectoryName(destFile); + EnsureDirectoryExists(parentDirectory); + + bool process = true; + FileInfo fileInfo = new FileInfo(destFile); + if (fileInfo.Exists) { + if (keepOldFiles) { + OnProgressMessageEvent(entry, "Destination file already exists"); + process = false; + } else if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0) { + OnProgressMessageEvent(entry, "Destination file already exists, and is read-only"); + process = false; + } + } + + if (process) { + bool asciiTrans = false; + + Stream outputStream = File.Create(destFile); + if (this.asciiTranslate) { + asciiTrans = !IsBinary(destFile); + } + + StreamWriter outw = null; + if (asciiTrans) { + outw = new StreamWriter(outputStream); + } + + byte[] rdbuf = new byte[32 * 1024]; + + while (true) { + int numRead = tarIn.Read(rdbuf, 0, rdbuf.Length); + + if (numRead <= 0) { + break; + } + + if (asciiTrans) { + for (int off = 0, b = 0; b < numRead; ++b) { + if (rdbuf[b] == 10) { + string s = Encoding.ASCII.GetString(rdbuf, off, (b - off)); + outw.WriteLine(s); + off = b + 1; + } + } + } else { + outputStream.Write(rdbuf, 0, numRead); + } + } + + if (asciiTrans) { + outw.Close(); + } else { + outputStream.Close(); + } + } + } + } + + /// + /// Write an entry to the archive. This method will call the putNextEntry + /// and then write the contents of the entry, and finally call closeEntry() + /// for entries that are files. For directories, it will call putNextEntry(), + /// and then, if the recurse flag is true, process each entry that is a + /// child of the directory. + /// + /// + /// The TarEntry representing the entry to write to the archive. + /// + /// + /// If true, process the children of directory entries. + /// + public void WriteEntry(TarEntry sourceEntry, bool recurse) + { + if ( sourceEntry == null ) { + throw new ArgumentNullException("sourceEntry"); + } + + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + try + { + if ( recurse ) { + TarHeader.SetValueDefaults(sourceEntry.UserId, sourceEntry.UserName, + sourceEntry.GroupId, sourceEntry.GroupName); + } + WriteEntryCore(sourceEntry, recurse); + } + finally + { + if ( recurse ) { + TarHeader.RestoreSetValues(); + } + } + } + + /// + /// Write an entry to the archive. This method will call the putNextEntry + /// and then write the contents of the entry, and finally call closeEntry() + /// for entries that are files. For directories, it will call putNextEntry(), + /// and then, if the recurse flag is true, process each entry that is a + /// child of the directory. + /// + /// + /// The TarEntry representing the entry to write to the archive. + /// + /// + /// If true, process the children of directory entries. + /// + void WriteEntryCore(TarEntry sourceEntry, bool recurse) + { + string tempFileName = null; + string entryFilename = sourceEntry.File; + + TarEntry entry = (TarEntry)sourceEntry.Clone(); + + if ( applyUserInfoOverrides ) { + entry.GroupId = groupId; + entry.GroupName = groupName; + entry.UserId = userId; + entry.UserName = userName; + } + + OnProgressMessageEvent(entry, null); + + if (asciiTranslate && !entry.IsDirectory) { + + if (!IsBinary(entryFilename)) { + tempFileName = Path.GetTempFileName(); + + using (StreamReader inStream = File.OpenText(entryFilename)) { + using (Stream outStream = File.Create(tempFileName)) { + + while (true) { + string line = inStream.ReadLine(); + if (line == null) { + break; + } + byte[] data = Encoding.ASCII.GetBytes(line); + outStream.Write(data, 0, data.Length); + outStream.WriteByte((byte)'\n'); + } + + outStream.Flush(); + } + } + + entry.Size = new FileInfo(tempFileName).Length; + entryFilename = tempFileName; + } + } + + string newName = null; + + if (rootPath != null) { + if (entry.Name.StartsWith(rootPath)) { + newName = entry.Name.Substring(rootPath.Length + 1 ); + } + } + + if (pathPrefix != null) { + newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName; + } + + if (newName != null) { + entry.Name = newName; + } + + tarOut.PutNextEntry(entry); + + if (entry.IsDirectory) { + if (recurse) { + TarEntry[] list = entry.GetDirectoryEntries(); + for (int i = 0; i < list.Length; ++i) { + WriteEntryCore(list[i], recurse); + } + } + } + else { + using (Stream inputStream = File.OpenRead(entryFilename)) { + byte[] localBuffer = new byte[32 * 1024]; + while (true) { + int numRead = inputStream.Read(localBuffer, 0, localBuffer.Length); + + if (numRead <=0) { + break; + } + + tarOut.Write(localBuffer, 0, numRead); + } + } + + if ( (tempFileName != null) && (tempFileName.Length > 0) ) { + File.Delete(tempFileName); + } + + tarOut.CloseEntry(); + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if ( !isDisposed ) { + isDisposed = true; + if ( disposing ) { + if ( tarOut != null ) { + tarOut.Flush(); + tarOut.Close(); + } + + if ( tarIn != null ) { + tarIn.Close(); + } + } + } + } + + /// + /// Closes the archive and releases any associated resources. + /// + public virtual void Close() + { + Dispose(true); + } + + /// + /// Ensures that resources are freed and other cleanup operations are performed + /// when the garbage collector reclaims the . + /// + ~TarArchive() + { + Dispose(false); + } + + static void EnsureDirectoryExists(string directoryName) + { + if (!Directory.Exists(directoryName)) { + try { + Directory.CreateDirectory(directoryName); + } + catch (Exception e) { + throw new TarException("Exception creating directory '" + directoryName + "', " + e.Message, e); + } + } + } + + // TODO: TarArchive - Is there a better way to test for a text file? + // It no longer reads entire files into memory but is still a weak test! + // This assumes that byte values 0-7, 14-31 or 255 are binary + // and that all non text files contain one of these values + static bool IsBinary(string filename) + { + using (FileStream fs = File.OpenRead(filename)) + { + int sampleSize = Math.Min(4096, (int)fs.Length); + byte[] content = new byte[sampleSize]; + + int bytesRead = fs.Read(content, 0, sampleSize); + + for (int i = 0; i < bytesRead; ++i) { + byte b = content[i]; + if ( (b < 8) || ((b > 13) && (b < 32)) || (b == 255) ) { + return true; + } + } + } + return false; + } + + #region Instance Fields + bool keepOldFiles; + bool asciiTranslate; + + int userId; + string userName = string.Empty; + int groupId; + string groupName = string.Empty; + + string rootPath; + string pathPrefix; + + bool applyUserInfoOverrides; + + TarInputStream tarIn; + TarOutputStream tarOut; + bool isDisposed; + #endregion + } +} + + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ + diff --git a/PCRobot/Utils/ZIP/Tar/TarBuffer.cs b/PCRobot/Utils/ZIP/Tar/TarBuffer.cs new file mode 100644 index 0000000..40b8d93 --- /dev/null +++ b/PCRobot/Utils/ZIP/Tar/TarBuffer.cs @@ -0,0 +1,624 @@ +// TarBuffer.cs +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarBuffer class implements the tar archive concept + /// of a buffered input stream. This concept goes back to the + /// days of blocked tape drives and special io devices. In the + /// C# universe, the only real function that this class + /// performs is to ensure that files have the correct "record" + /// size, or other tars will complain. + ///

+ /// You should never have a need to access this class directly. + /// TarBuffers are created by Tar IO Streams. + ///

+ ///
+ public class TarBuffer + { + +/* A quote from GNU tar man file on blocking and records + A `tar' archive file contains a series of blocks. Each block +contains `BLOCKSIZE' bytes. Although this format may be thought of as +being on magnetic tape, other media are often used. + + Each file archived is represented by a header block which describes +the file, followed by zero or more blocks which give the contents of +the file. At the end of the archive file there may be a block filled +with binary zeros as an end-of-file marker. A reasonable system should +write a block of zeros at the end, but must not assume that such a +block exists when reading an archive. + + The blocks may be "blocked" for physical I/O operations. Each +record of N blocks is written with a single 'write ()' +operation. On magnetic tapes, the result of such a write is a single +record. When writing an archive, the last record of blocks should be +written at the full size, with blocks after the zero block containing +all zeros. When reading an archive, a reasonable system should +properly handle an archive whose last record is shorter than the rest, +or which contains garbage records after a zero block. +*/ + + #region Constants + /// + /// The size of a block in a tar archive in bytes. + /// + /// This is 512 bytes. + public const int BlockSize = 512; + + /// + /// The number of blocks in a default record. + /// + /// + /// The default value is 20 blocks per record. + /// + public const int DefaultBlockFactor = 20; + + /// + /// The size in bytes of a default record. + /// + /// + /// The default size is 10KB. + /// + public const int DefaultRecordSize = BlockSize * DefaultBlockFactor; + #endregion + + /// + /// Get the record size for this buffer + /// + /// The record size in bytes. + /// This is equal to the multiplied by the + public int RecordSize + { + get { + return recordSize; + } + } + + /// + /// Get the TAR Buffer's record size. + /// + /// The record size in bytes. + /// This is equal to the multiplied by the + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return recordSize; + } + + /// + /// Get the Blocking factor for the buffer + /// + /// This is the number of blocks in each record. + public int BlockFactor { + get { + return blockFactor; + } + } + + /// + /// Get the TAR Buffer's block factor + /// + /// The block factor; the number of blocks per record. + [Obsolete("Use BlockFactor property instead")] + public int GetBlockFactor() + { + return blockFactor; + } + + /// + /// Construct a default TarBuffer + /// + protected TarBuffer() + { + } + + /// + /// Create TarBuffer for reading with default BlockFactor + /// + /// Stream to buffer + /// A new suitable for input. + public static TarBuffer CreateInputTarBuffer(Stream inputStream) + { + if ( inputStream == null ) + { + throw new ArgumentNullException("inputStream"); + } + + return CreateInputTarBuffer(inputStream, DefaultBlockFactor); + } + + /// + /// Construct TarBuffer for reading inputStream setting BlockFactor + /// + /// Stream to buffer + /// Blocking factor to apply + /// A new suitable for input. + public static TarBuffer CreateInputTarBuffer(Stream inputStream, int blockFactor) + { + if ( inputStream == null ) + { + throw new ArgumentNullException("inputStream"); + } + + if ( blockFactor <= 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("blockFactor"); +#else + throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative"); +#endif + } + + TarBuffer tarBuffer = new TarBuffer(); + tarBuffer.inputStream = inputStream; + tarBuffer.outputStream = null; + tarBuffer.Initialize(blockFactor); + + return tarBuffer; + } + + /// + /// Construct TarBuffer for writing with default BlockFactor + /// + /// output stream for buffer + /// A new suitable for output. + public static TarBuffer CreateOutputTarBuffer(Stream outputStream) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + return CreateOutputTarBuffer(outputStream, DefaultBlockFactor); + } + + /// + /// Construct TarBuffer for writing Tar output to streams. + /// + /// Output stream to write to. + /// Blocking factor to apply + /// A new suitable for output. + public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + if ( blockFactor <= 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("blockFactor"); +#else + throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative"); +#endif + } + + TarBuffer tarBuffer = new TarBuffer(); + tarBuffer.inputStream = null; + tarBuffer.outputStream = outputStream; + tarBuffer.Initialize(blockFactor); + + return tarBuffer; + } + + /// + /// Initialization common to all constructors. + /// + void Initialize(int archiveBlockFactor) + { + blockFactor = archiveBlockFactor; + recordSize = archiveBlockFactor * BlockSize; + recordBuffer = new byte[RecordSize]; + + if (inputStream != null) { + currentRecordIndex = -1; + currentBlockIndex = BlockFactor; + } + else { + currentRecordIndex = 0; + currentBlockIndex = 0; + } + } + + /// + /// Determine if an archive block indicates End of Archive. End of + /// archive is indicated by a block that consists entirely of null bytes. + /// All remaining blocks for the record should also be null's + /// However some older tars only do a couple of null blocks (Old GNU tar for one) + /// and also partial records + /// + /// The data block to check. + /// Returns true if the block is an EOF block; false otherwise. + [Obsolete("Use IsEndOfArchiveBlock instead")] + public bool IsEOFBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if ( block.Length != BlockSize ) + { + throw new ArgumentException("block length is invalid"); + } + + for (int i = 0; i < BlockSize; ++i) { + if (block[i] != 0) { + return false; + } + } + + return true; + } + + + /// + /// Determine if an archive block indicates the End of an Archive has been reached. + /// End of archive is indicated by a block that consists entirely of null bytes. + /// All remaining blocks for the record should also be null's + /// However some older tars only do a couple of null blocks (Old GNU tar for one) + /// and also partial records + /// + /// The data block to check. + /// Returns true if the block is an EOF block; false otherwise. + public static bool IsEndOfArchiveBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if ( block.Length != BlockSize ) { + throw new ArgumentException("block length is invalid"); + } + + for ( int i = 0; i < BlockSize; ++i ) { + if ( block[i] != 0 ) { + return false; + } + } + + return true; + } + + /// + /// Skip over a block on the input stream. + /// + public void SkipBlock() + { + if (inputStream == null) { + throw new TarException("no input stream defined"); + } + + if (currentBlockIndex >= BlockFactor) { + if (!ReadRecord()) { + throw new TarException("Failed to read a record"); + } + } + + currentBlockIndex++; + } + + /// + /// Read a block from the input stream. + /// + /// + /// The block of data read. + /// + public byte[] ReadBlock() + { + if (inputStream == null) { + throw new TarException("TarBuffer.ReadBlock - no input stream defined"); + } + + if (currentBlockIndex >= BlockFactor) { + if (!ReadRecord()) { + throw new TarException("Failed to read a record"); + } + } + + byte[] result = new byte[BlockSize]; + + Array.Copy(recordBuffer, (currentBlockIndex * BlockSize), result, 0, BlockSize ); + currentBlockIndex++; + return result; + } + + /// + /// Read a record from data stream. + /// + /// + /// false if End-Of-File, else true. + /// + bool ReadRecord() + { + if (inputStream == null) { + throw new TarException("no input stream stream defined"); + } + + currentBlockIndex = 0; + + int offset = 0; + int bytesNeeded = RecordSize; + + while (bytesNeeded > 0) { + long numBytes = inputStream.Read(recordBuffer, offset, bytesNeeded); + + // + // NOTE + // We have found EOF, and the record is not full! + // + // This is a broken archive. It does not follow the standard + // blocking algorithm. However, because we are generous, and + // it requires little effort, we will simply ignore the error + // and continue as if the entire record were read. This does + // not appear to break anything upstream. We used to return + // false in this case. + // + // Thanks to 'Yohann.Roussel@alcatel.fr' for this fix. + // + if (numBytes <= 0) { + break; + } + + offset += (int)numBytes; + bytesNeeded -= (int)numBytes; + } + + currentRecordIndex++; + return true; + } + + /// + /// Get the current block number, within the current record, zero based. + /// + /// Block numbers are zero based values + /// + public int CurrentBlock + { + get { return currentBlockIndex; } + } + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner_; } + set { isStreamOwner_ = value; } + } + + /// + /// Get the current block number, within the current record, zero based. + /// + /// + /// The current zero based block number. + /// + /// + /// The absolute block number = (record number * block factor) + block number. + /// + [Obsolete("Use CurrentBlock property instead")] + public int GetCurrentBlockNum() + { + return currentBlockIndex; + } + + /// + /// Get the current record number. + /// + /// + /// The current zero based record number. + /// + public int CurrentRecord + { + get { return currentRecordIndex; } + } + + /// + /// Get the current record number. + /// + /// + /// The current zero based record number. + /// + [Obsolete("Use CurrentRecord property instead")] + public int GetCurrentRecordNum() + { + return currentRecordIndex; + } + + /// + /// Write a block of data to the archive. + /// + /// + /// The data to write to the archive. + /// + public void WriteBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if (outputStream == null) { + throw new TarException("TarBuffer.WriteBlock - no output stream defined"); + } + + if (block.Length != BlockSize) { + string errorText = string.Format("TarBuffer.WriteBlock - block to write has length '{0}' which is not the block size of '{1}'", + block.Length, BlockSize ); + throw new TarException(errorText); + } + + if (currentBlockIndex >= BlockFactor) { + WriteRecord(); + } + + Array.Copy(block, 0, recordBuffer, (currentBlockIndex * BlockSize), BlockSize); + currentBlockIndex++; + } + + /// + /// Write an archive record to the archive, where the record may be + /// inside of a larger array buffer. The buffer must be "offset plus + /// record size" long. + /// + /// + /// The buffer containing the record data to write. + /// + /// + /// The offset of the record data within buffer. + /// + public void WriteBlock(byte[] buffer, int offset) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if (outputStream == null) { + throw new TarException("TarBuffer.WriteBlock - no output stream stream defined"); + } + + if ( (offset < 0) || (offset >= buffer.Length) ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ((offset + BlockSize) > buffer.Length) { + string errorText = string.Format("TarBuffer.WriteBlock - record has length '{0}' with offset '{1}' which is less than the record size of '{2}'", + buffer.Length, offset, recordSize); + throw new TarException(errorText); + } + + if (currentBlockIndex >= BlockFactor) { + WriteRecord(); + } + + Array.Copy(buffer, offset, recordBuffer, (currentBlockIndex * BlockSize), BlockSize); + + currentBlockIndex++; + } + + /// + /// Write a TarBuffer record to the archive. + /// + void WriteRecord() + { + if (outputStream == null) { + throw new TarException("TarBuffer.WriteRecord no output stream defined"); + } + + outputStream.Write(recordBuffer, 0, RecordSize); + outputStream.Flush(); + + currentBlockIndex = 0; + currentRecordIndex++; + } + + /// + /// WriteFinalRecord writes the current record buffer to output any unwritten data is present. + /// + /// Any trailing bytes are set to zero which is by definition correct behaviour + /// for the end of a tar stream. + void WriteFinalRecord() + { + if (outputStream == null) { + throw new TarException("TarBuffer.WriteFinalRecord no output stream defined"); + } + + if (currentBlockIndex > 0) { + int dataBytes = currentBlockIndex * BlockSize; + Array.Clear(recordBuffer, dataBytes, RecordSize - dataBytes); + WriteRecord(); + } + + outputStream.Flush(); + } + + /// + /// Close the TarBuffer. If this is an output buffer, also flush the + /// current block before closing. + /// + public void Close() + { + if (outputStream != null) { + WriteFinalRecord(); + + if (isStreamOwner_) { + outputStream.Close(); + } + outputStream = null; + } + else if (inputStream != null) { + if (isStreamOwner_) { + inputStream.Close(); + } + inputStream = null; + } + } + + #region Instance Fields + Stream inputStream; + Stream outputStream; + + byte[] recordBuffer; + int currentBlockIndex; + int currentRecordIndex; + + int recordSize = DefaultRecordSize; + int blockFactor = DefaultBlockFactor; + bool isStreamOwner_ = true; + #endregion + } +} + +/* The original Java file had this header: + * + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/PCRobot/Utils/ZIP/Tar/TarEntry.cs b/PCRobot/Utils/ZIP/Tar/TarEntry.cs new file mode 100644 index 0000000..a733e32 --- /dev/null +++ b/PCRobot/Utils/ZIP/Tar/TarEntry.cs @@ -0,0 +1,559 @@ +// TarEntry.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + /// + /// This class represents an entry in a Tar archive. It consists + /// of the entry's header, as well as the entry's File. Entries + /// can be instantiated in one of three ways, depending on how + /// they are to be used. + ///

+ /// TarEntries that are created from the header bytes read from + /// an archive are instantiated with the TarEntry( byte[] ) + /// constructor. These entries will be used when extracting from + /// or listing the contents of an archive. These entries have their + /// header filled in using the header bytes. They also set the File + /// to null, since they reference an archive entry not a file.

+ ///

+ /// TarEntries that are created from files that are to be written + /// into an archive are instantiated with the CreateEntryFromFile(string) + /// pseudo constructor. These entries have their header filled in using + /// the File's information. They also keep a reference to the File + /// for convenience when writing entries.

+ ///

+ /// Finally, TarEntries can be constructed from nothing but a name. + /// This allows the programmer to construct the entry by hand, for + /// instance when only an InputStream is available for writing to + /// the archive, and the header information is constructed from + /// other information. In this case the header fields are set to + /// defaults and the File is set to null.

+ /// + ///
+ public class TarEntry : ICloneable + { + #region Constructors + /// + /// Initialise a default instance of . + /// + private TarEntry() + { + header = new TarHeader(); + } + + /// + /// Construct an entry from an archive's header bytes. File is set + /// to null. + /// + /// + /// The header bytes from a tar archive entry. + /// + public TarEntry(byte[] headerBuffer) + { + header = new TarHeader(); + header.ParseBuffer(headerBuffer); + } + + /// + /// Construct a TarEntry using the header provided + /// + /// Header details for entry + public TarEntry(TarHeader header) + { + if ( header == null ) + { + throw new ArgumentNullException("header"); + } + + this.header = (TarHeader)header.Clone(); + } + #endregion + + #region ICloneable Members + /// + /// Clone this tar entry. + /// + /// Returns a clone of this entry. + public object Clone() + { + TarEntry entry = new TarEntry(); + entry.file = file; + entry.header = (TarHeader)header.Clone(); + entry.Name = Name; + return entry; + } + #endregion + + /// + /// Construct an entry with only a name. + /// This allows the programmer to construct the entry's header "by hand". + /// + /// The name to use for the entry + /// Returns the newly created + public static TarEntry CreateTarEntry(string name) + { + TarEntry entry = new TarEntry(); + TarEntry.NameTarHeader(entry.header, name); + return entry; + } + + /// + /// Construct an entry for a file. File is set to file, and the + /// header is constructed from information from the file. + /// + /// The file name that the entry represents. + /// Returns the newly created + public static TarEntry CreateEntryFromFile(string fileName) + { + TarEntry entry = new TarEntry(); + entry.GetFileTarHeader(entry.header, fileName); + return entry; + } + + /// + /// Determine if the two entries are equal. Equality is determined + /// by the header names being equal. + /// + /// The to compare with the current Object. + /// + /// True if the entries are equal; false if not. + /// + public override bool Equals(object obj) + { + TarEntry localEntry = obj as TarEntry; + + if ( localEntry != null ) + { + return Name.Equals(localEntry.Name); + } + return false; + } + + /// + /// Derive a Hash value for the current + /// + /// A Hash code for the current + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + /// Determine if the given entry is a descendant of this entry. + /// Descendancy is determined by the name of the descendant + /// starting with this entry's name. + /// + /// + /// Entry to be checked as a descendent of this. + /// + /// + /// True if entry is a descendant of this. + /// + public bool IsDescendent(TarEntry toTest) + { + if ( toTest == null ) { + throw new ArgumentNullException("toTest"); + } + + return toTest.Name.StartsWith(Name); + } + + /// + /// Get this entry's header. + /// + /// + /// This entry's TarHeader. + /// + public TarHeader TarHeader + { + get { + return header; + } + } + + /// + /// Get/Set this entry's name. + /// + public string Name + { + get { + return header.Name; + } + set { + header.Name = value; + } + } + + /// + /// Get/set this entry's user id. + /// + public int UserId + { + get { + return header.UserId; + } + set { + header.UserId = value; + } + } + + /// + /// Get/set this entry's group id. + /// + public int GroupId + { + get { + return header.GroupId; + } + set { + header.GroupId = value; + } + } + + /// + /// Get/set this entry's user name. + /// + public string UserName + { + get { + return header.UserName; + } + set { + header.UserName = value; + } + } + + /// + /// Get/set this entry's group name. + /// + public string GroupName + { + get { + return header.GroupName; + } + set { + header.GroupName = value; + } + } + + /// + /// Convenience method to set this entry's group and user ids. + /// + /// + /// This entry's new user id. + /// + /// + /// This entry's new group id. + /// + public void SetIds(int userId, int groupId) + { + UserId = userId; + GroupId = groupId; + } + + /// + /// Convenience method to set this entry's group and user names. + /// + /// + /// This entry's new user name. + /// + /// + /// This entry's new group name. + /// + public void SetNames(string userName, string groupName) + { + UserName = userName; + GroupName = groupName; + } + + /// + /// Get/Set the modification time for this entry + /// + public DateTime ModTime { + get { + return header.ModTime; + } + set { + header.ModTime = value; + } + } + + /// + /// Get this entry's file. + /// + /// + /// This entry's file. + /// + public string File { + get { + return file; + } + } + + /// + /// Get/set this entry's recorded file size. + /// + public long Size { + get { + return header.Size; + } + set { + header.Size = value; + } + } + + /// + /// Return true if this entry represents a directory, false otherwise + /// + /// + /// True if this entry is a directory. + /// + public bool IsDirectory { + get { + if (file != null) { + return Directory.Exists(file); + } + + if (header != null) { + if ((header.TypeFlag == TarHeader.LF_DIR) || Name.EndsWith( "/" )) { + return true; + } + } + return false; + } + } + + /// + /// Fill in a TarHeader with information from a File. + /// + /// + /// The TarHeader to fill in. + /// + /// + /// The file from which to get the header information. + /// + public void GetFileTarHeader(TarHeader header, string file) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( file == null ) { + throw new ArgumentNullException("file"); + } + + this.file = file; + + // bugfix from torhovl from #D forum: + string name = file; + +#if !NETCF_1_0 && !NETCF_2_0 + // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory + if (name.IndexOf(Environment.CurrentDirectory) == 0) { + name = name.Substring(Environment.CurrentDirectory.Length); + } +#endif + +/* + if (Path.DirectorySeparatorChar == '\\') + { + // check if the OS is Windows + // Strip off drive letters! + if (name.Length > 2) + { + char ch1 = name[0]; + char ch2 = name[1]; + + if (ch2 == ':' && Char.IsLetter(ch1)) + { + name = name.Substring(2); + } + } + } +*/ + + name = name.Replace(Path.DirectorySeparatorChar, '/'); + + // No absolute pathnames + // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\", + // so we loop on starting /'s. + while (name.StartsWith("/")) { + name = name.Substring(1); + } + + header.LinkName = String.Empty; + header.Name = name; + + if (Directory.Exists(file)) { + header.Mode = 1003; // Magic number for security access for a UNIX filesystem + header.TypeFlag = TarHeader.LF_DIR; + if ( (header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') { + header.Name = header.Name + "/"; + } + + header.Size = 0; + } else { + header.Mode = 33216; // Magic number for security access for a UNIX filesystem + header.TypeFlag = TarHeader.LF_NORMAL; + header.Size = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length; + } + + header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime(); + header.DevMajor = 0; + header.DevMinor = 0; + } + + /// + /// Get entries for all files present in this entries directory. + /// If this entry doesnt represent a directory zero entries are returned. + /// + /// + /// An array of TarEntry's for this entry's children. + /// + public TarEntry[] GetDirectoryEntries() + { + if ( (file == null) || !Directory.Exists(file)) { + return new TarEntry[0]; + } + + string[] list = Directory.GetFileSystemEntries(file); + TarEntry[] result = new TarEntry[list.Length]; + + for (int i = 0; i < list.Length; ++i) { + result[i] = TarEntry.CreateEntryFromFile(list[i]); + } + + return result; + } + + /// + /// Write an entry's header information to a header buffer. + /// + /// + /// The tar entry header buffer to fill in. + /// + public void WriteEntryHeader(byte[] outBuffer) + { + header.WriteHeader(outBuffer); + } + + /// + /// Convenience method that will modify an entry's name directly + /// in place in an entry header buffer byte array. + /// + /// + /// The buffer containing the entry header to modify. + /// + /// + /// The new name to place into the header buffer. + /// + static public void AdjustEntryName(byte[] buffer, string newName) + { + TarHeader.GetNameBytes(newName, buffer, 0, TarHeader.NAMELEN); + } + + /// + /// Fill in a TarHeader given only the entry's name. + /// + /// + /// The TarHeader to fill in. + /// + /// + /// The tar entry name. + /// + static public void NameTarHeader(TarHeader header, string name) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + bool isDir = name.EndsWith("/"); + + header.Name = name; + header.Mode = isDir ? 1003 : 33216; + header.UserId = 0; + header.GroupId = 0; + header.Size = 0; + + header.ModTime = DateTime.UtcNow; + + header.TypeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL; + + header.LinkName = String.Empty; + header.UserName = String.Empty; + header.GroupName = String.Empty; + + header.DevMajor = 0; + header.DevMinor = 0; + } + + #region Instance Fields + /// + /// The name of the file this entry represents or null if the entry is not based on a file. + /// + string file; + + /// + /// The entry's header information. + /// + TarHeader header; + #endregion + } +} + + + +/* The original Java file had this header: + * + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/PCRobot/Utils/ZIP/Tar/TarException.cs b/PCRobot/Utils/ZIP/Tar/TarException.cs new file mode 100644 index 0000000..84a6eba --- /dev/null +++ b/PCRobot/Utils/ZIP/Tar/TarException.cs @@ -0,0 +1,91 @@ +// TarException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Tar { + + /// + /// TarExceptions are used for exceptions specific to tar classes and code. + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class TarException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected TarException(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + + /// + /// Initialises a new instance of the TarException class. + /// + public TarException() + { + } + + /// + /// Initialises a new instance of the TarException class with a specified message. + /// + /// The message that describes the error. + public TarException(string message) + : base(message) + { + } + + /// + /// + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public TarException(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/PCRobot/Utils/ZIP/Tar/TarHeader.cs b/PCRobot/Utils/ZIP/Tar/TarHeader.cs new file mode 100644 index 0000000..fc49f16 --- /dev/null +++ b/PCRobot/Utils/ZIP/Tar/TarHeader.cs @@ -0,0 +1,1156 @@ +// TarHeader.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +/* The tar format and its POSIX successor PAX have a long history which makes for compatability + issues when creating and reading files. + + This is further complicated by a large number of programs with variations on formats + One common issue is the handling of names longer than 100 characters. + GNU style long names are currently supported. + +This is the ustar (Posix 1003.1) header. + +struct header +{ + char t_name[100]; // 0 Filename + char t_mode[8]; // 100 Permissions + char t_uid[8]; // 108 Numerical User ID + char t_gid[8]; // 116 Numerical Group ID + char t_size[12]; // 124 Filesize + char t_mtime[12]; // 136 st_mtime + char t_chksum[8]; // 148 Checksum + char t_typeflag; // 156 Type of File + char t_linkname[100]; // 157 Target of Links + char t_magic[6]; // 257 "ustar" or other... + char t_version[2]; // 263 Version fixed to 00 + char t_uname[32]; // 265 User Name + char t_gname[32]; // 297 Group Name + char t_devmajor[8]; // 329 Major for devices + char t_devminor[8]; // 337 Minor for devices + char t_prefix[155]; // 345 Prefix for t_name + char t_mfill[12]; // 500 Filler up to 512 +}; + +*/ + +using System; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + + /// + /// This class encapsulates the Tar Entry Header used in Tar Archives. + /// The class also holds a number of tar constants, used mostly in headers. + /// + public class TarHeader : ICloneable + { + #region Constants + /// + /// The length of the name field in a header buffer. + /// + public const int NAMELEN = 100; + + /// + /// The length of the mode field in a header buffer. + /// + public const int MODELEN = 8; + + /// + /// The length of the user id field in a header buffer. + /// + public const int UIDLEN = 8; + + /// + /// The length of the group id field in a header buffer. + /// + public const int GIDLEN = 8; + + /// + /// The length of the checksum field in a header buffer. + /// + public const int CHKSUMLEN = 8; + + /// + /// Offset of checksum in a header buffer. + /// + public const int CHKSUMOFS = 148; + + /// + /// The length of the size field in a header buffer. + /// + public const int SIZELEN = 12; + + /// + /// The length of the magic field in a header buffer. + /// + public const int MAGICLEN = 6; + + /// + /// The length of the version field in a header buffer. + /// + public const int VERSIONLEN = 2; + + /// + /// The length of the modification time field in a header buffer. + /// + public const int MODTIMELEN = 12; + + /// + /// The length of the user name field in a header buffer. + /// + public const int UNAMELEN = 32; + + /// + /// The length of the group name field in a header buffer. + /// + public const int GNAMELEN = 32; + + /// + /// The length of the devices field in a header buffer. + /// + public const int DEVLEN = 8; + + // + // LF_ constants represent the "type" of an entry + // + + /// + /// The "old way" of indicating a normal file. + /// + public const byte LF_OLDNORM = 0; + + /// + /// Normal file type. + /// + public const byte LF_NORMAL = (byte) '0'; + + /// + /// Link file type. + /// + public const byte LF_LINK = (byte) '1'; + + /// + /// Symbolic link file type. + /// + public const byte LF_SYMLINK = (byte) '2'; + + /// + /// Character device file type. + /// + public const byte LF_CHR = (byte) '3'; + + /// + /// Block device file type. + /// + public const byte LF_BLK = (byte) '4'; + + /// + /// Directory file type. + /// + public const byte LF_DIR = (byte) '5'; + + /// + /// FIFO (pipe) file type. + /// + public const byte LF_FIFO = (byte) '6'; + + /// + /// Contiguous file type. + /// + public const byte LF_CONTIG = (byte) '7'; + + /// + /// Posix.1 2001 global extended header + /// + public const byte LF_GHDR = (byte) 'g'; + + /// + /// Posix.1 2001 extended header + /// + public const byte LF_XHDR = (byte) 'x'; + + // POSIX allows for upper case ascii type as extensions + + /// + /// Solaris access control list file type + /// + public const byte LF_ACL = (byte) 'A'; + + /// + /// GNU dir dump file type + /// This is a dir entry that contains the names of files that were in the + /// dir at the time the dump was made + /// + public const byte LF_GNU_DUMPDIR = (byte) 'D'; + + /// + /// Solaris Extended Attribute File + /// + public const byte LF_EXTATTR = (byte) 'E' ; + + /// + /// Inode (metadata only) no file content + /// + public const byte LF_META = (byte) 'I'; + + /// + /// Identifies the next file on the tape as having a long link name + /// + public const byte LF_GNU_LONGLINK = (byte) 'K'; + + /// + /// Identifies the next file on the tape as having a long name + /// + public const byte LF_GNU_LONGNAME = (byte) 'L'; + + /// + /// Continuation of a file that began on another volume + /// + public const byte LF_GNU_MULTIVOL = (byte) 'M'; + + /// + /// For storing filenames that dont fit in the main header (old GNU) + /// + public const byte LF_GNU_NAMES = (byte) 'N'; + + /// + /// GNU Sparse file + /// + public const byte LF_GNU_SPARSE = (byte) 'S'; + + /// + /// GNU Tape/volume header ignore on extraction + /// + public const byte LF_GNU_VOLHDR = (byte) 'V'; + + /// + /// The magic tag representing a POSIX tar archive. (includes trailing NULL) + /// + public const string TMAGIC = "ustar "; + + /// + /// The magic tag representing an old GNU tar archive where version is included in magic and overwrites it + /// + public const string GNU_TMAGIC = "ustar "; + + const long timeConversionFactor = 10000000L; // 1 tick == 100 nanoseconds + readonly static DateTime dateTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0); + #endregion + + #region Constructors + + /// + /// Initialise a default TarHeader instance + /// + public TarHeader() + { + Magic = TMAGIC; + Version = " "; + + Name = ""; + LinkName = ""; + + UserId = defaultUserId; + GroupId = defaultGroupId; + UserName = defaultUser; + GroupName = defaultGroupName; + Size = 0; + } + + #endregion + + #region Properties + /// + /// Get/set the name for this tar entry. + /// + /// Thrown when attempting to set the property to null. + public string Name + { + get { return name; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + name = value; + } + } + + /// + /// Get the name of this entry. + /// + /// The entry's name. + [Obsolete("Use the Name property instead", true)] + public string GetName() + { + return name; + } + + /// + /// Get/set the entry's Unix style permission mode. + /// + public int Mode + { + get { return mode; } + set { mode = value; } + } + + + /// + /// The entry's user id. + /// + /// + /// This is only directly relevant to unix systems. + /// The default is zero. + /// + public int UserId + { + get { return userId; } + set { userId = value; } + } + + + /// + /// Get/set the entry's group id. + /// + /// + /// This is only directly relevant to linux/unix systems. + /// The default value is zero. + /// + public int GroupId + { + get { return groupId; } + set { groupId = value; } + } + + + /// + /// Get/set the entry's size. + /// + /// Thrown when setting the size to less than zero. + public long Size + { + get { return size; } + set { + if ( value < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Cannot be less than zero"); +#endif + } + size = value; + } + } + + + /// + /// Get/set the entry's modification time. + /// + /// + /// The modification time is only accurate to within a second. + /// + /// Thrown when setting the date time to less than 1/1/1970. + public DateTime ModTime + { + get { return modTime; } + set { + if ( value < dateTime1970 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "ModTime cannot be before Jan 1st 1970"); +#endif + } + modTime = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second); + } + } + + + /// + /// Get the entry's checksum. This is only valid/updated after writing or reading an entry. + /// + public int Checksum + { + get { return checksum; } + } + + + /// + /// Get value of true if the header checksum is valid, false otherwise. + /// + public bool IsChecksumValid + { + get { return isChecksumValid; } + } + + + /// + /// Get/set the entry's type flag. + /// + public byte TypeFlag + { + get { return typeFlag; } + set { typeFlag = value; } + } + + + /// + /// The entry's link name. + /// + /// Thrown when attempting to set LinkName to null. + public string LinkName + { + get { return linkName; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + linkName = value; + } + } + + + /// + /// Get/set the entry's magic tag. + /// + /// Thrown when attempting to set Magic to null. + public string Magic + { + get { return magic; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + magic = value; + } + } + + + /// + /// The entry's version. + /// + /// Thrown when attempting to set Version to null. + public string Version + { + get { + return version; + } + + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + version = value; + } + } + + + /// + /// The entry's user name. + /// + public string UserName + { + get { return userName; } + set { + if (value != null) { + userName = value.Substring(0, Math.Min(UNAMELEN, value.Length)); + } + else { +#if NETCF_1_0 || NETCF_2_0 + string currentUser = "PocketPC"; +#else + string currentUser = Environment.UserName; +#endif + if (currentUser.Length > UNAMELEN) { + currentUser = currentUser.Substring(0, UNAMELEN); + } + userName = currentUser; + } + } + } + + + /// + /// Get/set the entry's group name. + /// + /// + /// This is only directly relevant to unix systems. + /// + public string GroupName + { + get { return groupName; } + set { + if ( value == null ) { + groupName = "None"; + } + else { + groupName = value; + } + } + } + + + /// + /// Get/set the entry's major device number. + /// + public int DevMajor + { + get { return devMajor; } + set { devMajor = value; } + } + + + /// + /// Get/set the entry's minor device number. + /// + public int DevMinor + { + get { return devMinor; } + set { devMinor = value; } + } + + #endregion + + #region ICloneable Members + /// + /// Create a new that is a copy of the current instance. + /// + /// A new that is a copy of the current instance. + public object Clone() + { + return MemberwiseClone(); + } + #endregion + + /// + /// Parse TarHeader information from a header buffer. + /// + /// + /// The tar entry header buffer to get information from. + /// + public void ParseBuffer(byte[] header) + { + if ( header == null ) + { + throw new ArgumentNullException("header"); + } + + int offset = 0; + + name = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString(); + offset += TarHeader.NAMELEN; + + mode = (int)TarHeader.ParseOctal(header, offset, TarHeader.MODELEN); + offset += TarHeader.MODELEN; + + UserId = (int)TarHeader.ParseOctal(header, offset, TarHeader.UIDLEN); + offset += TarHeader.UIDLEN; + + GroupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN); + offset += TarHeader.GIDLEN; + + Size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN); + offset += TarHeader.SIZELEN; + + ModTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN)); + offset += TarHeader.MODTIMELEN; + + checksum = (int)TarHeader.ParseOctal(header, offset, TarHeader.CHKSUMLEN); + offset += TarHeader.CHKSUMLEN; + + TypeFlag = header[ offset++ ]; + + LinkName = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString(); + offset += TarHeader.NAMELEN; + + Magic = TarHeader.ParseName(header, offset, TarHeader.MAGICLEN).ToString(); + offset += TarHeader.MAGICLEN; + + Version = TarHeader.ParseName(header, offset, TarHeader.VERSIONLEN).ToString(); + offset += TarHeader.VERSIONLEN; + + UserName = TarHeader.ParseName(header, offset, TarHeader.UNAMELEN).ToString(); + offset += TarHeader.UNAMELEN; + + GroupName = TarHeader.ParseName(header, offset, TarHeader.GNAMELEN).ToString(); + offset += TarHeader.GNAMELEN; + + DevMajor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN); + offset += TarHeader.DEVLEN; + + DevMinor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN); + + // Fields past this point not currently parsed or used... + + isChecksumValid = Checksum == TarHeader.MakeCheckSum(header); + } + + /// + /// 'Write' header information to buffer provided, updating the check sum. + /// + /// output buffer for header information + public void WriteHeader(byte[] outBuffer) + { + if ( outBuffer == null ) + { + throw new ArgumentNullException("outBuffer"); + } + + int offset = 0; + + offset = GetNameBytes(Name, outBuffer, offset, NAMELEN); + offset = GetOctalBytes(mode, outBuffer, offset, MODELEN); + offset = GetOctalBytes(UserId, outBuffer, offset, UIDLEN); + offset = GetOctalBytes(GroupId, outBuffer, offset, GIDLEN); + + offset = GetLongOctalBytes(Size, outBuffer, offset, SIZELEN); + offset = GetLongOctalBytes(GetCTime(ModTime), outBuffer, offset, MODTIMELEN); + + int csOffset = offset; + for (int c = 0; c < CHKSUMLEN; ++c) + { + outBuffer[offset++] = (byte)' '; + } + + outBuffer[offset++] = TypeFlag; + + offset = GetNameBytes(LinkName, outBuffer, offset, NAMELEN); + offset = GetAsciiBytes(Magic, 0, outBuffer, offset, MAGICLEN); + offset = GetNameBytes(Version, outBuffer, offset, VERSIONLEN); + offset = GetNameBytes(UserName, outBuffer, offset, UNAMELEN); + offset = GetNameBytes(GroupName, outBuffer, offset, GNAMELEN); + + if ((TypeFlag == LF_CHR) || (TypeFlag == LF_BLK)) + { + offset = GetOctalBytes(DevMajor, outBuffer, offset, DEVLEN); + offset = GetOctalBytes(DevMinor, outBuffer, offset, DEVLEN); + } + + for ( ; offset < outBuffer.Length; ) + { + outBuffer[offset++] = 0; + } + + checksum = ComputeCheckSum(outBuffer); + + GetCheckSumOctalBytes(checksum, outBuffer, csOffset, CHKSUMLEN); + isChecksumValid = true; + } + + /// + /// Get a hash code for the current object. + /// + /// A hash code for the current object. + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + /// Determines if this instance is equal to the specified object. + /// + /// The object to compare with. + /// true if the objects are equal, false otherwise. + public override bool Equals(object obj) + { + TarHeader localHeader = obj as TarHeader; + + bool result; + if ( localHeader != null ) + { + result = (name == localHeader.name) + && (mode == localHeader.mode) + && (UserId == localHeader.UserId) + && (GroupId == localHeader.GroupId) + && (Size == localHeader.Size) + && (ModTime == localHeader.ModTime) + && (Checksum == localHeader.Checksum) + && (TypeFlag == localHeader.TypeFlag) + && (LinkName == localHeader.LinkName) + && (Magic == localHeader.Magic) + && (Version == localHeader.Version) + && (UserName == localHeader.UserName) + && (GroupName == localHeader.GroupName) + && (DevMajor == localHeader.DevMajor) + && (DevMinor == localHeader.DevMinor); + } + else + { + result = false; + } + return result; + } + + /// + /// Set defaults for values used when constructing a TarHeader instance. + /// + /// Value to apply as a default for userId. + /// Value to apply as a default for userName. + /// Value to apply as a default for groupId. + /// Value to apply as a default for groupName. + static internal void SetValueDefaults(int userId, string userName, int groupId, string groupName) + { + defaultUserId = userIdAsSet = userId; + defaultUser = userNameAsSet = userName; + defaultGroupId = groupIdAsSet = groupId; + defaultGroupName = groupNameAsSet = groupName; + } + + static internal void RestoreSetValues() + { + defaultUserId = userIdAsSet; + defaultUser = userNameAsSet; + defaultGroupId = groupIdAsSet; + defaultGroupName = groupNameAsSet; + } + + /// + /// Parse an octal string from a header buffer. + /// + /// The header buffer from which to parse. + /// The offset into the buffer from which to parse. + /// The number of header bytes to parse. + /// The long equivalent of the octal string. + static public long ParseOctal(byte[] header, int offset, int length) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + long result = 0; + bool stillPadding = true; + + int end = offset + length; + for (int i = offset; i < end ; ++i) { + if (header[i] == 0) { + break; + } + + if (header[i] == (byte)' ' || header[i] == '0') { + if (stillPadding) { + continue; + } + + if (header[i] == (byte)' ') { + break; + } + } + + stillPadding = false; + + result = (result << 3) + (header[i] - '0'); + } + + return result; + } + + /// + /// Parse a name from a header buffer. + /// + /// + /// The header buffer from which to parse. + /// + /// + /// The offset into the buffer from which to parse. + /// + /// + /// The number of header bytes to parse. + /// + /// + /// The name parsed. + /// + static public StringBuilder ParseName(byte[] header, int offset, int length) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be less than zero"); +#endif + } + + if ( length < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("length"); +#else + throw new ArgumentOutOfRangeException("length", "Cannot be less than zero"); +#endif + } + + if ( offset + length > header.Length ) + { + throw new ArgumentException("Exceeds header size", "length"); + } + + StringBuilder result = new StringBuilder(length); + + for (int i = offset; i < offset + length; ++i) { + if (header[i] == 0) { + break; + } + result.Append((char)header[i]); + } + + return result; + } + + /// + /// Add name to the buffer as a collection of bytes + /// + /// The name to add + /// The offset of the first character + /// The buffer to add to + /// The index of the first byte to add + /// The number of characters/bytes to add + /// The next free index in the + public static int GetNameBytes(StringBuilder name, int nameOffset, byte[] buffer, int bufferOffset, int length) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name.ToString(), nameOffset, buffer, bufferOffset, length); + } + + /// + /// Add name to the buffer as a collection of bytes + /// + /// The name to add + /// The offset of the first character + /// The buffer to add to + /// The index of the first byte to add + /// The number of characters/bytes to add + /// The next free index in the + public static int GetNameBytes(string name, int nameOffset, byte[] buffer, int bufferOffset, int length) + { + if ( name == null ) + { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + int i; + + for (i = 0 ; i < length - 1 && nameOffset + i < name.Length; ++i) { + buffer[bufferOffset + i] = (byte)name[nameOffset + i]; + } + + for (; i < length ; ++i) { + buffer[bufferOffset + i] = 0; + } + + return bufferOffset + length; + } + + /// + /// Add an entry name to the buffer + /// + /// + /// The name to add + /// + /// + /// The buffer to add to + /// + /// + /// The offset into the buffer from which to start adding + /// + /// + /// The number of header bytes to add + /// + /// + /// The index of the next free byte in the buffer + /// + public static int GetNameBytes(StringBuilder name, byte[] buffer, int offset, int length) + { + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name.ToString(), 0, buffer, offset, length); + } + + /// + /// Add an entry name to the buffer + /// + /// The name to add + /// The buffer to add to + /// The offset into the buffer from which to start adding + /// The number of header bytes to add + /// The index of the next free byte in the buffer + public static int GetNameBytes(string name, byte[] buffer, int offset, int length) + { + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name, 0, buffer, offset, length); + } + + /// + /// Add a string to a buffer as a collection of ascii bytes. + /// + /// The string to add + /// The offset of the first character to add. + /// The buffer to add to. + /// The offset to start adding at. + /// The number of ascii characters to add. + /// The next free index in the buffer. + public static int GetAsciiBytes(string toAdd, int nameOffset, byte[] buffer, int bufferOffset, int length ) + { + if ( toAdd == null ) { + throw new ArgumentNullException("toAdd"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + for (int i = 0 ; i < length && nameOffset + i < toAdd.Length; ++i) + { + buffer[bufferOffset + i] = (byte)toAdd[nameOffset + i]; + } + return bufferOffset + length; + } + + /// + /// Put an octal representation of a value into a buffer + /// + /// + /// the value to be converted to octal + /// + /// + /// buffer to store the octal string + /// + /// + /// The offset into the buffer where the value starts + /// + /// + /// The length of the octal string to create + /// + /// + /// The offset of the character next byte after the octal string + /// + public static int GetOctalBytes(long value, byte[] buffer, int offset, int length) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + int localIndex = length - 1; + + // Either a space or null is valid here. We use NULL as per GNUTar + buffer[offset + localIndex] = 0; + --localIndex; + + if (value > 0) { + for ( long v = value; (localIndex >= 0) && (v > 0); --localIndex ) { + buffer[offset + localIndex] = (byte)((byte)'0' + (byte)(v & 7)); + v >>= 3; + } + } + + for ( ; localIndex >= 0; --localIndex ) { + buffer[offset + localIndex] = (byte)'0'; + } + + return offset + length; + } + + /// + /// Put an octal representation of a value into a buffer + /// + /// Value to be convert to octal + /// The buffer to update + /// The offset into the buffer to store the value + /// The length of the octal string + /// Index of next byte + public static int GetLongOctalBytes(long value, byte[] buffer, int offset, int length) + { + return GetOctalBytes(value, buffer, offset, length); + } + + /// + /// Add the checksum integer to header buffer. + /// + /// + /// The header buffer to set the checksum for + /// The offset into the buffer for the checksum + /// The number of header bytes to update. + /// It's formatted differently from the other fields: it has 6 digits, a + /// null, then a space -- rather than digits, a space, then a null. + /// The final space is already there, from checksumming + /// + /// The modified buffer offset + static int GetCheckSumOctalBytes(long value, byte[] buffer, int offset, int length) + { + TarHeader.GetOctalBytes(value, buffer, offset, length - 1); + return offset + length; + } + + /// + /// Compute the checksum for a tar entry header. + /// The checksum field must be all spaces prior to this happening + /// + /// The tar entry's header buffer. + /// The computed checksum. + static int ComputeCheckSum(byte[] buffer) + { + int sum = 0; + for (int i = 0; i < buffer.Length; ++i) { + sum += buffer[i]; + } + return sum; + } + + /// + /// Make a checksum for a tar entry ignoring the checksum contents. + /// + /// The tar entry's header buffer. + /// The checksum for the buffer + static int MakeCheckSum(byte[] buffer) + { + int sum = 0; + for ( int i = 0; i < CHKSUMOFS; ++i ) + { + sum += buffer[i]; + } + + for ( int i = 0; i < TarHeader.CHKSUMLEN; ++i) + { + sum += (byte)' '; + } + + for (int i = CHKSUMOFS + CHKSUMLEN; i < buffer.Length; ++i) + { + sum += buffer[i]; + } + return sum; + } + + static int GetCTime(System.DateTime dateTime) + { + return unchecked((int)((dateTime.Ticks - dateTime1970.Ticks) / timeConversionFactor)); + } + + static DateTime GetDateTimeFromCTime(long ticks) + { + DateTime result; + + try { + result = new DateTime(dateTime1970.Ticks + ticks * timeConversionFactor); + } + catch(ArgumentOutOfRangeException) { + result = dateTime1970; + } + return result; + } + + #region Instance Fields + string name; + int mode; + int userId; + int groupId; + long size; + DateTime modTime; + int checksum; + bool isChecksumValid; + byte typeFlag; + string linkName; + string magic; + string version; + string userName; + string groupName; + int devMajor; + int devMinor; + #endregion + + #region Class Fields + // Values used during recursive operations. + static internal int userIdAsSet; + static internal int groupIdAsSet; + static internal string userNameAsSet; + static internal string groupNameAsSet = "None"; + + static internal int defaultUserId; + static internal int defaultGroupId; + static internal string defaultGroupName = "None"; + static internal string defaultUser; + #endregion + } +} + +/* The original Java file had this header: + * +** Authored by Timothy Gerard Endres +** +** +** This work has been placed into the public domain. +** You may use this work in any way and for any purpose you wish. +** +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR +** REDISTRIBUTION OF THIS SOFTWARE. +** +*/ diff --git a/PCRobot/Utils/ZIP/Tar/TarInputStream.cs b/PCRobot/Utils/ZIP/Tar/TarInputStream.cs new file mode 100644 index 0000000..436b002 --- /dev/null +++ b/PCRobot/Utils/ZIP/Tar/TarInputStream.cs @@ -0,0 +1,695 @@ +// TarInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarInputStream reads a UNIX tar archive as an InputStream. + /// methods are provided to position at each successive entry in + /// the archive, and the read each entry as a normal input stream + /// using read(). + /// + public class TarInputStream : Stream + { + #region Constructors + /// + /// Construct a TarInputStream with default block factor + /// + /// stream to source data from + public TarInputStream(Stream inputStream) + : this(inputStream, TarBuffer.DefaultBlockFactor) + { + } + + /// + /// Construct a TarInputStream with user specified block factor + /// + /// stream to source data from + /// block factor to apply to archive + public TarInputStream(Stream inputStream, int blockFactor) + { + this.inputStream = inputStream; + tarBuffer = TarBuffer.CreateInputTarBuffer(inputStream, blockFactor); + } + + #endregion + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return tarBuffer.IsStreamOwner; } + set { tarBuffer.IsStreamOwner = value; } + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return inputStream.CanRead; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking + /// This property always returns false. + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value indicating if the stream supports writing. + /// This property always returns false. + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// The length in bytes of the stream + /// + public override long Length { + get { + return inputStream.Length; + } + } + + /// + /// Gets or sets the position within the stream. + /// Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException + /// + /// Any attempt to set position + public override long Position { + get { + return inputStream.Position; + } + set { + throw new NotSupportedException("TarInputStream Seek not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + inputStream.Flush(); + } + + /// + /// Set the streams position. This operation is not supported and will throw a NotSupportedException + /// + /// The offset relative to the origin to seek to. + /// The to start seeking from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("TarInputStream Seek not supported"); + } + + /// + /// Sets the length of the stream + /// This operation is not supported and will throw a NotSupportedException + /// + /// The new stream length. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("TarInputStream SetLength not supported"); + } + + /// + /// Writes a block of bytes to this stream using data from a buffer. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The buffer containing bytes to write. + /// The offset in the buffer of the frist byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("TarInputStream Write not supported"); + } + + /// + /// Writes a byte to the current position in the file stream. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The byte value to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("TarInputStream WriteByte not supported"); + } + /// + /// Reads a byte from the current tar archive entry. + /// + /// A byte cast to an int; -1 if the at the end of the stream. + public override int ReadByte() + { + byte[] oneByteBuffer = new byte[1]; + int num = Read(oneByteBuffer, 0, 1); + if (num <= 0) + { + // return -1 to indicate that no byte was read. + return -1; + } + return oneByteBuffer[0]; + } + + /// + /// Reads bytes from the current tar archive entry. + /// + /// This method is aware of the boundaries of the current + /// entry in the archive and will deal with them appropriately + /// + /// + /// The buffer into which to place bytes read. + /// + /// + /// The offset at which to place bytes read. + /// + /// + /// The number of bytes to read. + /// + /// + /// The number of bytes read, or 0 at end of stream/EOF. + /// + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + int totalRead = 0; + + if (entryOffset >= entrySize) + { + return 0; + } + + long numToRead = count; + + if ((numToRead + entryOffset) > entrySize) + { + numToRead = entrySize - entryOffset; + } + + if (readBuffer != null) + { + int sz = (numToRead > readBuffer.Length) ? readBuffer.Length : (int)numToRead; + + Array.Copy(readBuffer, 0, buffer, offset, sz); + + if (sz >= readBuffer.Length) + { + readBuffer = null; + } + else + { + int newLen = readBuffer.Length - sz; + byte[] newBuf = new byte[newLen]; + Array.Copy(readBuffer, sz, newBuf, 0, newLen); + readBuffer = newBuf; + } + + totalRead += sz; + numToRead -= sz; + offset += sz; + } + + while (numToRead > 0) + { + byte[] rec = tarBuffer.ReadBlock(); + if (rec == null) + { + // Unexpected EOF! + throw new TarException("unexpected EOF with " + numToRead + " bytes unread"); + } + + int sz = (int)numToRead; + int recLen = rec.Length; + + if (recLen > sz) + { + Array.Copy(rec, 0, buffer, offset, sz); + readBuffer = new byte[recLen - sz]; + Array.Copy(rec, sz, readBuffer, 0, recLen - sz); + } + else + { + sz = recLen; + Array.Copy(rec, 0, buffer, offset, recLen); + } + + totalRead += sz; + numToRead -= sz; + offset += sz; + } + + entryOffset += totalRead; + + return totalRead; + } + + /// + /// Closes this stream. Calls the TarBuffer's close() method. + /// The underlying stream is closed by the TarBuffer. + /// + public override void Close() + { + tarBuffer.Close(); + } + + #endregion + + /// + /// Set the entry factory for this instance. + /// + /// The factory for creating new entries + public void SetEntryFactory(IEntryFactory factory) + { + entryFactory = factory; + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + public int RecordSize + { + get { return tarBuffer.RecordSize; } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + /// + /// TarBuffer record size. + /// + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return tarBuffer.RecordSize; + } + + /// + /// Get the available data that can be read from the current + /// entry in the archive. This does not indicate how much data + /// is left in the entire archive, only in the current entry. + /// This value is determined from the entry's size header field + /// and the amount of data already read from the current entry. + /// + /// + /// The number of available bytes for the current entry. + /// + public long Available { + get { + return entrySize - entryOffset; + } + } + + /// + /// Skip bytes in the input buffer. This skips bytes in the + /// current entry's data, not the entire archive, and will + /// stop at the end of the current entry's data if the number + /// to skip extends beyond that point. + /// + /// + /// The number of bytes to skip. + /// + public void Skip(long skipCount) + { + // TODO: REVIEW efficiency of TarInputStream.Skip + // This is horribly inefficient, but it ensures that we + // properly skip over bytes via the TarBuffer... + // + byte[] skipBuf = new byte[8 * 1024]; + + for (long num = skipCount; num > 0;) { + int toRead = num > skipBuf.Length ? skipBuf.Length : (int)num; + int numRead = Read(skipBuf, 0, toRead); + + if (numRead == -1) { + break; + } + + num -= numRead; + } + } + + /// + /// Return a value of true if marking is supported; false otherwise. + /// + /// Currently marking is not supported, the return value is always false. + public bool IsMarkSupported { + get { + return false; + } + } + + /// + /// Since we do not support marking just yet, we do nothing. + /// + /// + /// The limit to mark. + /// + public void Mark(int markLimit) + { + } + + /// + /// Since we do not support marking just yet, we do nothing. + /// + public void Reset() + { + } + + /// + /// Get the next entry in this tar archive. This will skip + /// over any remaining data in the current entry, if there + /// is one, and place the input stream at the header of the + /// next entry, and read the header and instantiate a new + /// TarEntry from the header bytes and return that entry. + /// If there are no more entries in the archive, null will + /// be returned to indicate that the end of the archive has + /// been reached. + /// + /// + /// The next TarEntry in the archive, or null. + /// + public TarEntry GetNextEntry() + { + if (hasHitEOF) { + return null; + } + + if (currentEntry != null) { + SkipToNextEntry(); + } + + byte[] headerBuf = tarBuffer.ReadBlock(); + + if (headerBuf == null) { + hasHitEOF = true; + } else if (TarBuffer.IsEndOfArchiveBlock(headerBuf)) { + hasHitEOF = true; + } + + if (hasHitEOF) { + currentEntry = null; + } else { + try { + TarHeader header = new TarHeader(); + header.ParseBuffer(headerBuf); + if ( !header.IsChecksumValid ) + { + throw new TarException("Header checksum is invalid"); + } + this.entryOffset = 0; + this.entrySize = header.Size; + + StringBuilder longName = null; + + if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME) { + + byte[] nameBuffer = new byte[TarBuffer.BlockSize]; + long numToRead = this.entrySize; + + longName = new StringBuilder(); + + while (numToRead > 0) { + int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead)); + + if (numRead == -1) { + throw new InvalidHeaderException("Failed to read long name entry"); + } + + longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString()); + numToRead -= numRead; + } + + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_GHDR) { // POSIX global extended header + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_XHDR) { // POSIX extended header + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR) { + // TODO: could show volume name when verbose + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag != TarHeader.LF_NORMAL && + header.TypeFlag != TarHeader.LF_OLDNORM && + header.TypeFlag != TarHeader.LF_DIR) { + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = tarBuffer.ReadBlock(); + } + + if (entryFactory == null) { + currentEntry = new TarEntry(headerBuf); + if (longName != null) { + currentEntry.Name = longName.ToString(); + } + } else { + currentEntry = entryFactory.CreateEntry(headerBuf); + } + + // Magic was checked here for 'ustar' but there are multiple valid possibilities + // so this is not done anymore. + + entryOffset = 0; + + // TODO: Review How do we resolve this discrepancy?! + entrySize = this.currentEntry.Size; + } catch (InvalidHeaderException ex) { + entrySize = 0; + entryOffset = 0; + currentEntry = null; + string errorText = string.Format("Bad header in record {0} block {1} {2}", + tarBuffer.CurrentRecord, tarBuffer.CurrentBlock, ex.Message); + throw new InvalidHeaderException(errorText); + } + } + return currentEntry; + } + + /// + /// Copies the contents of the current tar archive entry directly into + /// an output stream. + /// + /// + /// The OutputStream into which to write the entry's data. + /// + public void CopyEntryContents(Stream outputStream) + { + byte[] tempBuffer = new byte[32 * 1024]; + + while (true) { + int numRead = Read(tempBuffer, 0, tempBuffer.Length); + if (numRead <= 0) { + break; + } + outputStream.Write(tempBuffer, 0, numRead); + } + } + + void SkipToNextEntry() + { + long numToSkip = entrySize - entryOffset; + + if (numToSkip > 0) + { + Skip(numToSkip); + } + + readBuffer = null; + } + + /// + /// This interface is provided, along with the method , to allow + /// the programmer to have their own subclass instantiated for the + /// entries return from . + /// + public interface IEntryFactory + { + /// + /// Create an entry based on name alone + /// + /// + /// Name of the new EntryPointNotFoundException to create + /// + /// created TarEntry or descendant class + TarEntry CreateEntry(string name); + + /// + /// Create an instance based on an actual file + /// + /// + /// Name of file to represent in the entry + /// + /// + /// Created TarEntry or descendant class + /// + TarEntry CreateEntryFromFile(string fileName); + + /// + /// Create a tar entry based on the header information passed + /// + /// + /// Buffer containing header information to create an an entry from. + /// + /// + /// Created TarEntry or descendant class + /// + TarEntry CreateEntry(byte[] headerBuffer); + } + + /// + /// Standard entry factory class creating instances of the class TarEntry + /// + public class EntryFactoryAdapter : IEntryFactory + { + /// + /// Create a based on named + /// + /// The name to use for the entry + /// A new + public TarEntry CreateEntry(string name) + { + return TarEntry.CreateTarEntry(name); + } + + /// + /// Create a tar entry with details obtained from file + /// + /// The name of the file to retrieve details from. + /// A new + public TarEntry CreateEntryFromFile(string fileName) + { + return TarEntry.CreateEntryFromFile(fileName); + } + + /// + /// Create an entry based on details in header + /// + /// The buffer containing entry details. + /// A new + public TarEntry CreateEntry(byte[] headerBuffer) + { + return new TarEntry(headerBuffer); + } + } + + #region Instance Fields + /// + /// Flag set when last block has been read + /// + protected bool hasHitEOF; + + /// + /// Size of this entry as recorded in header + /// + protected long entrySize; + + /// + /// Number of bytes read for this entry so far + /// + protected long entryOffset; + + /// + /// Buffer used with calls to Read() + /// + protected byte[] readBuffer; + + /// + /// Working buffer + /// + protected TarBuffer tarBuffer; + + /// + /// Current entry being read + /// + TarEntry currentEntry; + + /// + /// Factory used to create TarEntry or descendant class instance + /// + protected IEntryFactory entryFactory; + + /// + /// Stream used as the source of input data. + /// + readonly Stream inputStream; + #endregion + } +} + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ + diff --git a/PCRobot/Utils/ZIP/Tar/TarOutputStream.cs b/PCRobot/Utils/ZIP/Tar/TarOutputStream.cs new file mode 100644 index 0000000..fcac26f --- /dev/null +++ b/PCRobot/Utils/ZIP/Tar/TarOutputStream.cs @@ -0,0 +1,525 @@ +// TarOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarOutputStream writes a UNIX tar archive as an OutputStream. + /// Methods are provided to put entries, and then write their contents + /// by writing to this stream using write(). + /// + /// public + public class TarOutputStream : Stream + { + #region Constructors + /// + /// Construct TarOutputStream using default block factor + /// + /// stream to write to + public TarOutputStream(Stream outputStream) + : this(outputStream, TarBuffer.DefaultBlockFactor) + { + } + + /// + /// Construct TarOutputStream with user specified block factor + /// + /// stream to write to + /// blocking factor + public TarOutputStream(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + this.outputStream = outputStream; + buffer = TarBuffer.CreateOutputTarBuffer(outputStream, blockFactor); + + assemblyBuffer = new byte[TarBuffer.BlockSize]; + blockBuffer = new byte[TarBuffer.BlockSize]; + } + #endregion + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return buffer.IsStreamOwner; } + set { buffer.IsStreamOwner = value; } + } + + /// + /// true if the stream supports reading; otherwise, false. + /// + public override bool CanRead + { + get + { + return outputStream.CanRead; + } + } + + /// + /// true if the stream supports seeking; otherwise, false. + /// + public override bool CanSeek + { + get + { + return outputStream.CanSeek; + } + } + + /// + /// true if stream supports writing; otherwise, false. + /// + public override bool CanWrite + { + get + { + return outputStream.CanWrite; + } + } + + /// + /// length of stream in bytes + /// + public override long Length + { + get + { + return outputStream.Length; + } + } + + /// + /// gets or sets the position within the current stream. + /// + public override long Position + { + get + { + return outputStream.Position; + } + set + { + outputStream.Position = value; + } + } + + /// + /// set the position within the current stream + /// + /// The offset relative to the to seek to + /// The to seek from. + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + return outputStream.Seek(offset, origin); + } + + /// + /// Set the length of the current stream + /// + /// The new stream length. + public override void SetLength(long value) + { + outputStream.SetLength(value); + } + + /// + /// Read a byte from the stream and advance the position within the stream + /// by one byte or returns -1 if at the end of the stream. + /// + /// The byte value or -1 if at end of stream + public override int ReadByte() + { + return outputStream.ReadByte(); + } + + /// + /// read bytes from the current stream and advance the position within the + /// stream by the number of bytes read. + /// + /// The buffer to store read bytes in. + /// The index into the buffer to being storing bytes at. + /// The desired number of bytes to read. + /// The total number of bytes read, or zero if at the end of the stream. + /// The number of bytes may be less than the count + /// requested if data is not avialable. + public override int Read(byte[] buffer, int offset, int count) + { + return outputStream.Read(buffer, offset, count); + } + + /// + /// All buffered data is written to destination + /// + public override void Flush() + { + outputStream.Flush(); + } + + /// + /// Ends the TAR archive without closing the underlying OutputStream. + /// The result is that the EOF block of nulls is written. + /// + public void Finish() + { + if ( IsEntryOpen ) + { + CloseEntry(); + } + WriteEofBlock(); + } + + /// + /// Ends the TAR archive and closes the underlying OutputStream. + /// + /// This means that Finish() is called followed by calling the + /// TarBuffer's Close(). + public override void Close() + { + if ( !isClosed ) + { + isClosed = true; + Finish(); + buffer.Close(); + } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + public int RecordSize + { + get { return buffer.RecordSize; } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + /// + /// The TarBuffer record size. + /// + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return buffer.RecordSize; + } + + /// + /// Get a value indicating wether an entry is open, requiring more data to be written. + /// + bool IsEntryOpen + { + get { return (currBytes < currSize); } + + } + + /// + /// Put an entry on the output stream. This writes the entry's + /// header and positions the output stream for writing + /// the contents of the entry. Once this method is called, the + /// stream is ready for calls to write() to write the entry's + /// contents. Once the contents are written, closeEntry() + /// MUST be called to ensure that all buffered data + /// is completely written to the output stream. + /// + /// + /// The TarEntry to be written to the archive. + /// + public void PutNextEntry(TarEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if (entry.TarHeader.Name.Length >= TarHeader.NAMELEN) { + TarHeader longHeader = new TarHeader(); + longHeader.TypeFlag = TarHeader.LF_GNU_LONGNAME; + longHeader.Name = longHeader.Name + "././@LongLink"; + longHeader.UserId = 0; + longHeader.GroupId = 0; + longHeader.GroupName = ""; + longHeader.UserName = ""; + longHeader.LinkName = ""; + longHeader.Size = entry.TarHeader.Name.Length; + + longHeader.WriteHeader(blockBuffer); + buffer.WriteBlock(blockBuffer); // Add special long filename header block + + int nameCharIndex = 0; + + while (nameCharIndex < entry.TarHeader.Name.Length) { + Array.Clear(blockBuffer, 0, blockBuffer.Length); + TarHeader.GetAsciiBytes(entry.TarHeader.Name, nameCharIndex, this.blockBuffer, 0, TarBuffer.BlockSize); + nameCharIndex += TarBuffer.BlockSize; + buffer.WriteBlock(blockBuffer); + } + } + + entry.WriteEntryHeader(blockBuffer); + buffer.WriteBlock(blockBuffer); + + currBytes = 0; + + currSize = entry.IsDirectory ? 0 : entry.Size; + } + + /// + /// Close an entry. This method MUST be called for all file + /// entries that contain data. The reason is that we must + /// buffer data written to the stream in order to satisfy + /// the buffer's block based writes. Thus, there may be + /// data fragments still being assembled that must be written + /// to the output stream before this entry is closed and the + /// next entry written. + /// + public void CloseEntry() + { + if (assemblyBufferLength > 0) { + Array.Clear(assemblyBuffer, assemblyBufferLength, assemblyBuffer.Length - assemblyBufferLength); + + buffer.WriteBlock(assemblyBuffer); + + currBytes += assemblyBufferLength; + assemblyBufferLength = 0; + } + + if (currBytes < currSize) { + string errorText = string.Format( + "Entry closed at '{0}' before the '{1}' bytes specified in the header were written", + currBytes, currSize); + throw new TarException(errorText); + } + } + + /// + /// Writes a byte to the current tar archive entry. + /// This method simply calls Write(byte[], int, int). + /// + /// + /// The byte to be written. + /// + public override void WriteByte(byte value) + { + Write(new byte[] { value }, 0, 1); + } + + /// + /// Writes bytes to the current tar archive entry. This method + /// is aware of the current entry and will throw an exception if + /// you attempt to write bytes past the length specified for the + /// current entry. The method is also (painfully) aware of the + /// record buffering required by TarBuffer, and manages buffers + /// that are not a multiple of recordsize in length, including + /// assembling records from small buffers. + /// + /// + /// The buffer to write to the archive. + /// + /// + /// The offset in the buffer from which to get bytes. + /// + /// + /// The number of bytes to write. + /// + public override void Write(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( buffer.Length - offset < count ) + { + throw new ArgumentException("offset and count combination is invalid"); + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (currBytes + count) > currSize ) { + string errorText = string.Format("request to write '{0}' bytes exceeds size in header of '{1}' bytes", + count, this.currSize); +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", errorText); +#endif + } + + // + // We have to deal with assembly!!! + // The programmer can be writing little 32 byte chunks for all + // we know, and we must assemble complete blocks for writing. + // TODO REVIEW Maybe this should be in TarBuffer? Could that help to + // eliminate some of the buffer copying. + // + if (assemblyBufferLength > 0) { + if ((assemblyBufferLength + count ) >= blockBuffer.Length) { + int aLen = blockBuffer.Length - assemblyBufferLength; + + Array.Copy(assemblyBuffer, 0, blockBuffer, 0, assemblyBufferLength); + Array.Copy(buffer, offset, blockBuffer, assemblyBufferLength, aLen); + + this.buffer.WriteBlock(blockBuffer); + + currBytes += blockBuffer.Length; + + offset += aLen; + count -= aLen; + + assemblyBufferLength = 0; + } else { + Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count); + offset += count; + assemblyBufferLength += count; + count -= count; + } + } + + // + // When we get here we have EITHER: + // o An empty "assembly" buffer. + // o No bytes to write (count == 0) + // + while (count > 0) { + if (count < blockBuffer.Length) { + Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count); + assemblyBufferLength += count; + break; + } + + this.buffer.WriteBlock(buffer, offset); + + int bufferLength = blockBuffer.Length; + currBytes += bufferLength; + count -= bufferLength; + offset += bufferLength; + } + } + + /// + /// Write an EOF (end of archive) block to the tar archive. + /// An EOF block consists of all zeros. + /// + void WriteEofBlock() + { + Array.Clear(blockBuffer, 0, blockBuffer.Length); + buffer.WriteBlock(blockBuffer); + } + + #region Instance Fields + /// + /// bytes written for this entry so far + /// + long currBytes; + + /// + /// current 'Assembly' buffer length + /// + int assemblyBufferLength; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + /// + /// Size for the current entry + /// + protected long currSize; + + /// + /// single block working buffer + /// + protected byte[] blockBuffer; + + /// + /// 'Assembly' buffer used to assemble data before writing + /// + protected byte[] assemblyBuffer; + + /// + /// TarBuffer used to provide correct blocking factor + /// + protected TarBuffer buffer; + + /// + /// the destination stream for the archive contents + /// + protected Stream outputStream; + #endregion + } +} + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/PCRobot/Utils/ZIP/Zip/Compression/Deflater.cs b/PCRobot/Utils/ZIP/Zip/Compression/Deflater.cs new file mode 100644 index 0000000..dadbfb6 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/Deflater.cs @@ -0,0 +1,557 @@ +// Deflater.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This is the Deflater class. The deflater class compresses input + /// with the deflate algorithm described in RFC 1951. It has several + /// compression levels and three different strategies described below. + /// + /// This class is not thread safe. This is inherent in the API, due + /// to the split of deflate and setInput. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class Deflater + { + #region Deflater Documentation + /* + * The Deflater can do the following state transitions: + * + * (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---. + * / | (2) (5) | + * / v (5) | + * (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3) + * \ | (3) | ,--------' + * | | | (3) / + * v v (5) v v + * (1) -> BUSY_STATE ----> FINISHING_STATE + * | (6) + * v + * FINISHED_STATE + * \_____________________________________/ + * | (7) + * v + * CLOSED_STATE + * + * (1) If we should produce a header we start in INIT_STATE, otherwise + * we start in BUSY_STATE. + * (2) A dictionary may be set only when we are in INIT_STATE, then + * we change the state as indicated. + * (3) Whether a dictionary is set or not, on the first call of deflate + * we change to BUSY_STATE. + * (4) -- intentionally left blank -- :) + * (5) FINISHING_STATE is entered, when flush() is called to indicate that + * there is no more INPUT. There are also states indicating, that + * the header wasn't written yet. + * (6) FINISHED_STATE is entered, when everything has been flushed to the + * internal pending output buffer. + * (7) At any time (7) + * + */ + #endregion + #region Public Constants + /// + /// The best and slowest compression level. This tries to find very + /// long and distant string repetitions. + /// + public const int BEST_COMPRESSION = 9; + + /// + /// The worst but fastest compression level. + /// + public const int BEST_SPEED = 1; + + /// + /// The default compression level. + /// + public const int DEFAULT_COMPRESSION = -1; + + /// + /// This level won't compress at all but output uncompressed blocks. + /// + public const int NO_COMPRESSION = 0; + + /// + /// The compression method. This is the only method supported so far. + /// There is no need to use this constant at all. + /// + public const int DEFLATED = 8; + #endregion + #region Local Constants + private const int IS_SETDICT = 0x01; + private const int IS_FLUSHING = 0x04; + private const int IS_FINISHING = 0x08; + + private const int INIT_STATE = 0x00; + private const int SETDICT_STATE = 0x01; + // private static int INIT_FINISHING_STATE = 0x08; + // private static int SETDICT_FINISHING_STATE = 0x09; + private const int BUSY_STATE = 0x10; + private const int FLUSHING_STATE = 0x14; + private const int FINISHING_STATE = 0x1c; + private const int FINISHED_STATE = 0x1e; + private const int CLOSED_STATE = 0x7f; + #endregion + #region Constructors + /// + /// Creates a new deflater with default compression level. + /// + public Deflater() : this(DEFAULT_COMPRESSION, false) + { + + } + + /// + /// Creates a new deflater with given compression level. + /// + /// + /// the compression level, a value between NO_COMPRESSION + /// and BEST_COMPRESSION, or DEFAULT_COMPRESSION. + /// + /// if lvl is out of range. + public Deflater(int level) : this(level, false) + { + + } + + /// + /// Creates a new deflater with given compression level. + /// + /// + /// the compression level, a value between NO_COMPRESSION + /// and BEST_COMPRESSION. + /// + /// + /// true, if we should suppress the Zlib/RFC1950 header at the + /// beginning and the adler checksum at the end of the output. This is + /// useful for the GZIP/PKZIP formats. + /// + /// if lvl is out of range. + public Deflater(int level, bool noZlibHeaderOrFooter) + { + if (level == DEFAULT_COMPRESSION) { + level = 6; + } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) { + throw new ArgumentOutOfRangeException("level"); + } + + pending = new DeflaterPending(); + engine = new DeflaterEngine(pending); + this.noZlibHeaderOrFooter = noZlibHeaderOrFooter; + SetStrategy(DeflateStrategy.Default); + SetLevel(level); + Reset(); + } + #endregion + + /// + /// Resets the deflater. The deflater acts afterwards as if it was + /// just created with the same compression level and strategy as it + /// had before. + /// + public void Reset() + { + state = (noZlibHeaderOrFooter ? BUSY_STATE : INIT_STATE); + totalOut = 0; + pending.Reset(); + engine.Reset(); + } + + /// + /// Gets the current adler checksum of the data that was processed so far. + /// + public int Adler { + get { + return engine.Adler; + } + } + + /// + /// Gets the number of input bytes processed so far. + /// + public long TotalIn { + get { + return engine.TotalIn; + } + } + + /// + /// Gets the number of output bytes so far. + /// + public long TotalOut { + get { + return totalOut; + } + } + + /// + /// Flushes the current input block. Further calls to deflate() will + /// produce enough output to inflate everything in the current input + /// block. This is not part of Sun's JDK so I have made it package + /// private. It is used by DeflaterOutputStream to implement + /// flush(). + /// + public void Flush() + { + state |= IS_FLUSHING; + } + + /// + /// Finishes the deflater with the current input block. It is an error + /// to give more input after this method was called. This method must + /// be called to force all bytes to be flushed. + /// + public void Finish() + { + state |= (IS_FLUSHING | IS_FINISHING); + } + + /// + /// Returns true if the stream was finished and no more output bytes + /// are available. + /// + public bool IsFinished { + get { + return (state == FINISHED_STATE) && pending.IsFlushed; + } + } + + /// + /// Returns true, if the input buffer is empty. + /// You should then call setInput(). + /// NOTE: This method can also return true when the stream + /// was finished. + /// + public bool IsNeedingInput { + get { + return engine.NeedsInput(); + } + } + + /// + /// Sets the data which should be compressed next. This should be only + /// called when needsInput indicates that more input is needed. + /// If you call setInput when needsInput() returns false, the + /// previous input that is still pending will be thrown away. + /// The given byte array should not be changed, before needsInput() returns + /// true again. + /// This call is equivalent to setInput(input, 0, input.length). + /// + /// + /// the buffer containing the input data. + /// + /// + /// if the buffer was finished() or ended(). + /// + public void SetInput(byte[] input) + { + SetInput(input, 0, input.Length); + } + + /// + /// Sets the data which should be compressed next. This should be + /// only called when needsInput indicates that more input is needed. + /// The given byte array should not be changed, before needsInput() returns + /// true again. + /// + /// + /// the buffer containing the input data. + /// + /// + /// the start of the data. + /// + /// + /// the number of data bytes of input. + /// + /// + /// if the buffer was Finish()ed or if previous input is still pending. + /// + public void SetInput(byte[] input, int offset, int count) + { + if ((state & IS_FINISHING) != 0) { + throw new InvalidOperationException("Finish() already called"); + } + engine.SetInput(input, offset, count); + } + + /// + /// Sets the compression level. There is no guarantee of the exact + /// position of the change, but if you call this when needsInput is + /// true the change of compression level will occur somewhere near + /// before the end of the so far given input. + /// + /// + /// the new compression level. + /// + public void SetLevel(int level) + { + if (level == DEFAULT_COMPRESSION) { + level = 6; + } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) { + throw new ArgumentOutOfRangeException("level"); + } + + if (this.level != level) { + this.level = level; + engine.SetLevel(level); + } + } + + /// + /// Get current compression level + /// + /// Returns the current compression level + public int GetLevel() { + return level; + } + + /// + /// Sets the compression strategy. Strategy is one of + /// DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact + /// position where the strategy is changed, the same as for + /// SetLevel() applies. + /// + /// + /// The new compression strategy. + /// + public void SetStrategy(DeflateStrategy strategy) + { + engine.Strategy = strategy; + } + + /// + /// Deflates the current input block with to the given array. + /// + /// + /// The buffer where compressed data is stored + /// + /// + /// The number of compressed bytes added to the output, or 0 if either + /// IsNeedingInput() or IsFinished returns true or length is zero. + /// + public int Deflate(byte[] output) + { + return Deflate(output, 0, output.Length); + } + + /// + /// Deflates the current input block to the given array. + /// + /// + /// Buffer to store the compressed data. + /// + /// + /// Offset into the output array. + /// + /// + /// The maximum number of bytes that may be stored. + /// + /// + /// The number of compressed bytes added to the output, or 0 if either + /// needsInput() or finished() returns true or length is zero. + /// + /// + /// If Finish() was previously called. + /// + /// + /// If offset or length don't match the array length. + /// + public int Deflate(byte[] output, int offset, int length) + { + int origLength = length; + + if (state == CLOSED_STATE) { + throw new InvalidOperationException("Deflater closed"); + } + + if (state < BUSY_STATE) { + // output header + int header = (DEFLATED + + ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8; + int level_flags = (level - 1) >> 1; + if (level_flags < 0 || level_flags > 3) { + level_flags = 3; + } + header |= level_flags << 6; + if ((state & IS_SETDICT) != 0) { + // Dictionary was set + header |= DeflaterConstants.PRESET_DICT; + } + header += 31 - (header % 31); + + pending.WriteShortMSB(header); + if ((state & IS_SETDICT) != 0) { + int chksum = engine.Adler; + engine.ResetAdler(); + pending.WriteShortMSB(chksum >> 16); + pending.WriteShortMSB(chksum & 0xffff); + } + + state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING)); + } + + for (;;) { + int count = pending.Flush(output, offset, length); + offset += count; + totalOut += count; + length -= count; + + if (length == 0 || state == FINISHED_STATE) { + break; + } + + if (!engine.Deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0)) { + if (state == BUSY_STATE) { + // We need more input now + return origLength - length; + } else if (state == FLUSHING_STATE) { + if (level != NO_COMPRESSION) { + /* We have to supply some lookahead. 8 bit lookahead + * is needed by the zlib inflater, and we must fill + * the next byte, so that all bits are flushed. + */ + int neededbits = 8 + ((-pending.BitCount) & 7); + while (neededbits > 0) { + /* write a static tree block consisting solely of + * an EOF: + */ + pending.WriteBits(2, 10); + neededbits -= 10; + } + } + state = BUSY_STATE; + } else if (state == FINISHING_STATE) { + pending.AlignToByte(); + + // Compressed data is complete. Write footer information if required. + if (!noZlibHeaderOrFooter) { + int adler = engine.Adler; + pending.WriteShortMSB(adler >> 16); + pending.WriteShortMSB(adler & 0xffff); + } + state = FINISHED_STATE; + } + } + } + return origLength - length; + } + + /// + /// Sets the dictionary which should be used in the deflate process. + /// This call is equivalent to setDictionary(dict, 0, dict.Length). + /// + /// + /// the dictionary. + /// + /// + /// if SetInput () or Deflate () were already called or another dictionary was already set. + /// + public void SetDictionary(byte[] dictionary) + { + SetDictionary(dictionary, 0, dictionary.Length); + } + + /// + /// Sets the dictionary which should be used in the deflate process. + /// The dictionary is a byte array containing strings that are + /// likely to occur in the data which should be compressed. The + /// dictionary is not stored in the compressed output, only a + /// checksum. To decompress the output you need to supply the same + /// dictionary again. + /// + /// + /// The dictionary data + /// + /// + /// The index where dictionary information commences. + /// + /// + /// The number of bytes in the dictionary. + /// + /// + /// If SetInput () or Deflate() were already called or another dictionary was already set. + /// + public void SetDictionary(byte[] dictionary, int index, int count) + { + if (state != INIT_STATE) { + throw new InvalidOperationException(); + } + + state = SETDICT_STATE; + engine.SetDictionary(dictionary, index, count); + } + + #region Instance Fields + /// + /// Compression level. + /// + int level; + + /// + /// If true no Zlib/RFC1950 headers or footers are generated + /// + bool noZlibHeaderOrFooter; + + /// + /// The current state. + /// + int state; + + /// + /// The total bytes of output written. + /// + long totalOut; + + /// + /// The pending output. + /// + DeflaterPending pending; + + /// + /// The deflater engine. + /// + DeflaterEngine engine; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/DeflaterConstants.cs b/PCRobot/Utils/ZIP/Zip/Compression/DeflaterConstants.cs new file mode 100644 index 0000000..a973db2 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/DeflaterConstants.cs @@ -0,0 +1,186 @@ +// DeflaterConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class contains constants used for deflation. + /// + public class DeflaterConstants + { + /// + /// Set to true to enable debugging + /// + public const bool DEBUGGING = false; + + /// + /// Written to Zip file to identify a stored block + /// + public const int STORED_BLOCK = 0; + + /// + /// Identifies static tree in Zip file + /// + public const int STATIC_TREES = 1; + + /// + /// Identifies dynamic tree in Zip file + /// + public const int DYN_TREES = 2; + + /// + /// Header flag indicating a preset dictionary for deflation + /// + public const int PRESET_DICT = 0x20; + + /// + /// Sets internal buffer sizes for Huffman encoding + /// + public const int DEFAULT_MEM_LEVEL = 8; + + /// + /// Internal compression engine constant + /// + public const int MAX_MATCH = 258; + + /// + /// Internal compression engine constant + /// + public const int MIN_MATCH = 3; + + /// + /// Internal compression engine constant + /// + public const int MAX_WBITS = 15; + + /// + /// Internal compression engine constant + /// + public const int WSIZE = 1 << MAX_WBITS; + + /// + /// Internal compression engine constant + /// + public const int WMASK = WSIZE - 1; + + /// + /// Internal compression engine constant + /// + public const int HASH_BITS = DEFAULT_MEM_LEVEL + 7; + + /// + /// Internal compression engine constant + /// + public const int HASH_SIZE = 1 << HASH_BITS; + + /// + /// Internal compression engine constant + /// + public const int HASH_MASK = HASH_SIZE - 1; + + /// + /// Internal compression engine constant + /// + public const int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH; + + /// + /// Internal compression engine constant + /// + public const int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; + + /// + /// Internal compression engine constant + /// + public const int MAX_DIST = WSIZE - MIN_LOOKAHEAD; + + /// + /// Internal compression engine constant + /// + public const int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8); + + /// + /// Internal compression engine constant + /// + public static int MAX_BLOCK_SIZE = Math.Min(65535, PENDING_BUF_SIZE - 5); + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_STORED = 0; + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_FAST = 1; + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_SLOW = 2; + + /// + /// Internal compression engine constant + /// + public static int[] GOOD_LENGTH = { 0, 4, 4, 4, 4, 8, 8, 8, 32, 32 }; + + /// + /// Internal compression engine constant + /// + public static int[] MAX_LAZY = { 0, 4, 5, 6, 4, 16, 16, 32, 128, 258 }; + + /// + /// Internal compression engine constant + /// + public static int[] NICE_LENGTH = { 0, 8, 16, 32, 16, 32, 128, 128, 258, 258 }; + + /// + /// Internal compression engine constant + /// + public static int[] MAX_CHAIN = { 0, 4, 8, 32, 16, 32, 128, 256, 1024, 4096 }; + + /// + /// Internal compression engine constant + /// + public static int[] COMPR_FUNC = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/DeflaterEngine.cs b/PCRobot/Utils/ZIP/Zip/Compression/DeflaterEngine.cs new file mode 100644 index 0000000..3cbb5aa --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/DeflaterEngine.cs @@ -0,0 +1,869 @@ +// DeflaterEngine.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// Strategies for deflater + /// + public enum DeflateStrategy + { + /// + /// The default strategy + /// + Default = 0, + + /// + /// This strategy will only allow longer string repetitions. It is + /// useful for random data with a small character set. + /// + Filtered = 1, + + + /// + /// This strategy will not look for string repetitions at all. It + /// only encodes with Huffman trees (which means, that more common + /// characters get a smaller encoding. + /// + HuffmanOnly = 2 + } + + // DEFLATE ALGORITHM: + // + // The uncompressed stream is inserted into the window array. When + // the window array is full the first half is thrown away and the + // second half is copied to the beginning. + // + // The head array is a hash table. Three characters build a hash value + // and they the value points to the corresponding index in window of + // the last string with this hash. The prev array implements a + // linked list of matches with the same hash: prev[index & WMASK] points + // to the previous index with the same hash. + // + + + /// + /// Low level compression engine for deflate algorithm which uses a 32K sliding window + /// with secondary compression from Huffman/Shannon-Fano codes. + /// + public class DeflaterEngine : DeflaterConstants + { + #region Constants + const int TooFar = 4096; + #endregion + + #region Constructors + /// + /// Construct instance with pending buffer + /// + /// + /// Pending buffer to use + /// > + public DeflaterEngine(DeflaterPending pending) + { + this.pending = pending; + huffman = new DeflaterHuffman(pending); + adler = new Adler32(); + + window = new byte[2 * WSIZE]; + head = new short[HASH_SIZE]; + prev = new short[WSIZE]; + + // We start at index 1, to avoid an implementation deficiency, that + // we cannot build a repeat pattern at index 0. + blockStart = strstart = 1; + } + + #endregion + + /// + /// Deflate drives actual compression of data + /// + /// True to flush input buffers + /// Finish deflation with the current input. + /// Returns true if progress has been made. + public bool Deflate(bool flush, bool finish) + { + bool progress; + do + { + FillWindow(); + bool canFlush = flush && (inputOff == inputEnd); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.WriteLine("window: [" + blockStart + "," + strstart + "," + + lookahead + "], " + compressionFunction + "," + canFlush); + } +#endif + switch (compressionFunction) + { + case DEFLATE_STORED: + progress = DeflateStored(canFlush, finish); + break; + case DEFLATE_FAST: + progress = DeflateFast(canFlush, finish); + break; + case DEFLATE_SLOW: + progress = DeflateSlow(canFlush, finish); + break; + default: + throw new InvalidOperationException("unknown compressionFunction"); + } + } while (pending.IsFlushed && progress); // repeat while we have no pending output and progress was made + return progress; + } + + /// + /// Sets input data to be deflated. Should only be called when NeedsInput() + /// returns true + /// + /// The buffer containing input data. + /// The offset of the first byte of data. + /// The number of bytes of data to use as input. + public void SetInput(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( count < 0 ) + { + throw new ArgumentOutOfRangeException("count"); + } + + if (inputOff < inputEnd) + { + throw new InvalidOperationException("Old input was not completely processed"); + } + + int end = offset + count; + + /* We want to throw an ArrayIndexOutOfBoundsException early. The + * check is very tricky: it also handles integer wrap around. + */ + if ((offset > end) || (end > buffer.Length) ) + { + throw new ArgumentOutOfRangeException("count"); + } + + inputBuf = buffer; + inputOff = offset; + inputEnd = end; + } + + /// + /// Determines if more input is needed. + /// + /// Return true if input is needed via SetInput + public bool NeedsInput() + { + return (inputEnd == inputOff); + } + + /// + /// Set compression dictionary + /// + /// The buffer containing the dictionary data + /// The offset in the buffer for the first byte of data + /// The length of the dictionary data. + public void SetDictionary(byte[] buffer, int offset, int length) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (strstart != 1) ) + { + throw new InvalidOperationException("strstart not 1"); + } +#endif + adler.Update(buffer, offset, length); + if (length < MIN_MATCH) + { + return; + } + + if (length > MAX_DIST) + { + offset += length - MAX_DIST; + length = MAX_DIST; + } + + System.Array.Copy(buffer, offset, window, strstart, length); + + UpdateHash(); + --length; + while (--length > 0) + { + InsertString(); + strstart++; + } + strstart += 2; + blockStart = strstart; + } + + /// + /// Reset internal state + /// + public void Reset() + { + huffman.Reset(); + adler.Reset(); + blockStart = strstart = 1; + lookahead = 0; + totalIn = 0; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + + for (int i = 0; i < HASH_SIZE; i++) { + head[i] = 0; + } + + for (int i = 0; i < WSIZE; i++) { + prev[i] = 0; + } + } + + /// + /// Reset Adler checksum + /// + public void ResetAdler() + { + adler.Reset(); + } + + /// + /// Get current value of Adler checksum + /// + public int Adler { + get { + return unchecked((int)adler.Value); + } + } + + /// + /// Total data processed + /// + public long TotalIn { + get { + return totalIn; + } + } + + /// + /// Get/set the deflate strategy + /// + public DeflateStrategy Strategy { + get { + return strategy; + } + set { + strategy = value; + } + } + + /// + /// Set the deflate level (0-9) + /// + /// The value to set the level to. + public void SetLevel(int level) + { + if ( (level < 0) || (level > 9) ) + { + throw new ArgumentOutOfRangeException("level"); + } + + goodLength = DeflaterConstants.GOOD_LENGTH[level]; + max_lazy = DeflaterConstants.MAX_LAZY[level]; + niceLength = DeflaterConstants.NICE_LENGTH[level]; + max_chain = DeflaterConstants.MAX_CHAIN[level]; + + if (DeflaterConstants.COMPR_FUNC[level] != compressionFunction) { + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.WriteLine("Change from " + compressionFunction + " to " + + DeflaterConstants.COMPR_FUNC[level]); + } +#endif + switch (compressionFunction) { + case DEFLATE_STORED: + if (strstart > blockStart) { + huffman.FlushStoredBlock(window, blockStart, + strstart - blockStart, false); + blockStart = strstart; + } + UpdateHash(); + break; + + case DEFLATE_FAST: + if (strstart > blockStart) { + huffman.FlushBlock(window, blockStart, strstart - blockStart, + false); + blockStart = strstart; + } + break; + + case DEFLATE_SLOW: + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + if (strstart > blockStart) { + huffman.FlushBlock(window, blockStart, strstart - blockStart, false); + blockStart = strstart; + } + prevAvailable = false; + matchLen = MIN_MATCH - 1; + break; + } + compressionFunction = COMPR_FUNC[level]; + } + } + + /// + /// Fill the window + /// + public void FillWindow() + { + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (strstart >= WSIZE + MAX_DIST) + { + SlideWindow(); + } + + /* If there is not enough lookahead, but still some input left, + * read in the input + */ + while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd) + { + int more = 2 * WSIZE - lookahead - strstart; + + if (more > inputEnd - inputOff) + { + more = inputEnd - inputOff; + } + + System.Array.Copy(inputBuf, inputOff, window, strstart + lookahead, more); + adler.Update(inputBuf, inputOff, more); + + inputOff += more; + totalIn += more; + lookahead += more; + } + + if (lookahead >= MIN_MATCH) + { + UpdateHash(); + } + } + + void UpdateHash() + { +/* + if (DEBUGGING) { + Console.WriteLine("updateHash: "+strstart); + } +*/ + ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1]; + } + + /// + /// Inserts the current string in the head hash and returns the previous + /// value for this hash. + /// + /// The previous hash value + int InsertString() + { + short match; + int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)]) & HASH_MASK; + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^ + (window[strstart + 1] << HASH_SHIFT) ^ + (window[strstart + 2])) & HASH_MASK)) { + throw new SharpZipBaseException("hash inconsistent: " + hash + "/" + +window[strstart] + "," + +window[strstart + 1] + "," + +window[strstart + 2] + "," + HASH_SHIFT); + } + } +#endif + prev[strstart & WMASK] = match = head[hash]; + head[hash] = unchecked((short)strstart); + ins_h = hash; + return match & 0xffff; + } + + void SlideWindow() + { + Array.Copy(window, WSIZE, window, 0, WSIZE); + matchStart -= WSIZE; + strstart -= WSIZE; + blockStart -= WSIZE; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). + for (int i = 0; i < HASH_SIZE; ++i) { + int m = head[i] & 0xffff; + head[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0); + } + + // Slide the prev table. + for (int i = 0; i < WSIZE; i++) { + int m = prev[i] & 0xffff; + prev[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0); + } + } + + /// + /// Find the best (longest) string in the window matching the + /// string starting at strstart. + /// + /// Preconditions: + /// + /// strstart + MAX_MATCH <= window.length. + /// + /// + /// True if a match greater than the minimum length is found + bool FindLongestMatch(int curMatch) + { + int chainLength = this.max_chain; + int niceLength = this.niceLength; + short[] prev = this.prev; + int scan = this.strstart; + int match; + int best_end = this.strstart + matchLen; + int best_len = Math.Max(matchLen, MIN_MATCH - 1); + + int limit = Math.Max(strstart - MAX_DIST, 0); + + int strend = strstart + MAX_MATCH - 1; + byte scan_end1 = window[best_end - 1]; + byte scan_end = window[best_end]; + + // Do not waste too much time if we already have a good match: + if (best_len >= this.goodLength) { + chainLength >>= 2; + } + + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (niceLength > lookahead) { + niceLength = lookahead; + } + +#if DebugDeflation + + if (DeflaterConstants.DEBUGGING && (strstart > 2 * WSIZE - MIN_LOOKAHEAD)) + { + throw new InvalidOperationException("need lookahead"); + } +#endif + + do { + +#if DebugDeflation + + if (DeflaterConstants.DEBUGGING && (curMatch >= strstart) ) + { + throw new InvalidOperationException("no future"); + } +#endif + if (window[curMatch + best_len] != scan_end || + window[curMatch + best_len - 1] != scan_end1 || + window[curMatch] != window[scan] || + window[curMatch + 1] != window[scan + 1]) { + continue; + } + + match = curMatch + 2; + scan += 2; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart + 258. + */ + while ( + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + (scan < strend)) + { + // Do nothing + } + + if (scan > best_end) { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (ins_h == 0) ) + Console.Error.WriteLine("Found match: " + curMatch + "-" + (scan - strstart)); +#endif + matchStart = curMatch; + best_end = scan; + best_len = scan - strstart; + + if (best_len >= niceLength) { + break; + } + + scan_end1 = window[best_end - 1]; + scan_end = window[best_end]; + } + scan = strstart; + } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit && --chainLength != 0); + + matchLen = Math.Min(best_len, lookahead); + return matchLen >= MIN_MATCH; + } + + bool DeflateStored(bool flush, bool finish) + { + if (!flush && (lookahead == 0)) { + return false; + } + + strstart += lookahead; + lookahead = 0; + + int storedLength = strstart - blockStart; + + if ((storedLength >= DeflaterConstants.MAX_BLOCK_SIZE) || // Block is full + (blockStart < WSIZE && storedLength >= MAX_DIST) || // Block may move out of window + flush) { + bool lastBlock = finish; + if (storedLength > DeflaterConstants.MAX_BLOCK_SIZE) { + storedLength = DeflaterConstants.MAX_BLOCK_SIZE; + lastBlock = false; + } + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + Console.WriteLine("storedBlock[" + storedLength + "," + lastBlock + "]"); + } +#endif + + huffman.FlushStoredBlock(window, blockStart, storedLength, lastBlock); + blockStart += storedLength; + return !lastBlock; + } + return true; + } + + bool DeflateFast(bool flush, bool finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) { + return false; + } + + while (lookahead >= MIN_LOOKAHEAD || flush) { + if (lookahead == 0) { + // We are flushing everything + huffman.FlushBlock(window, blockStart, strstart - blockStart, finish); + blockStart = strstart; + return false; + } + + if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) { + /* slide window, as FindLongestMatch needs this. + * This should only happen when flushing and the window + * is almost full. + */ + SlideWindow(); + } + + int hashHead; + if (lookahead >= MIN_MATCH && + (hashHead = InsertString()) != 0 && + strategy != DeflateStrategy.HuffmanOnly && + strstart - hashHead <= MAX_DIST && + FindLongestMatch(hashHead)) { + // longestMatch sets matchStart and matchLen +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) { + if (window[strstart + i] != window[matchStart + i]) { + throw new SharpZipBaseException("Match failure"); + } + } + } +#endif + + bool full = huffman.TallyDist(strstart - matchStart, matchLen); + + lookahead -= matchLen; + if (matchLen <= max_lazy && lookahead >= MIN_MATCH) { + while (--matchLen > 0) { + ++strstart; + InsertString(); + } + ++strstart; + } else { + strstart += matchLen; + if (lookahead >= MIN_MATCH - 1) { + UpdateHash(); + } + } + matchLen = MIN_MATCH - 1; + if (!full) { + continue; + } + } else { + // No match found + huffman.TallyLit(window[strstart] & 0xff); + ++strstart; + --lookahead; + } + + if (huffman.IsFull()) { + bool lastBlock = finish && (lookahead == 0); + huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock); + blockStart = strstart; + return !lastBlock; + } + } + return true; + } + + bool DeflateSlow(bool flush, bool finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) { + return false; + } + + while (lookahead >= MIN_LOOKAHEAD || flush) { + if (lookahead == 0) { + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + prevAvailable = false; + + // We are flushing everything +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && !flush) + { + throw new SharpZipBaseException("Not flushing, but no lookahead"); + } +#endif + huffman.FlushBlock(window, blockStart, strstart - blockStart, + finish); + blockStart = strstart; + return false; + } + + if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) { + /* slide window, as FindLongestMatch needs this. + * This should only happen when flushing and the window + * is almost full. + */ + SlideWindow(); + } + + int prevMatch = matchStart; + int prevLen = matchLen; + if (lookahead >= MIN_MATCH) { + + int hashHead = InsertString(); + + if (strategy != DeflateStrategy.HuffmanOnly && + hashHead != 0 && + strstart - hashHead <= MAX_DIST && + FindLongestMatch(hashHead)) { + + // longestMatch sets matchStart and matchLen + + // Discard match if too small and too far away + if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TooFar))) { + matchLen = MIN_MATCH - 1; + } + } + } + + // previous match was better + if ((prevLen >= MIN_MATCH) && (matchLen <= prevLen) ) { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) { + if (window[strstart-1+i] != window[prevMatch + i]) + throw new SharpZipBaseException(); + } + } +#endif + huffman.TallyDist(strstart - 1 - prevMatch, prevLen); + prevLen -= 2; + do { + strstart++; + lookahead--; + if (lookahead >= MIN_MATCH) { + InsertString(); + } + } while (--prevLen > 0); + + strstart ++; + lookahead--; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + } else { + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + prevAvailable = true; + strstart++; + lookahead--; + } + + if (huffman.IsFull()) { + int len = strstart - blockStart; + if (prevAvailable) { + len--; + } + bool lastBlock = (finish && (lookahead == 0) && !prevAvailable); + huffman.FlushBlock(window, blockStart, len, lastBlock); + blockStart += len; + return !lastBlock; + } + } + return true; + } + + #region Instance Fields + + // Hash index of string to be inserted + int ins_h; + + /// + /// Hashtable, hashing three characters to an index for window, so + /// that window[index]..window[index+2] have this hash code. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xffff. + /// + short[] head; + + /// + /// prev[index & WMASK] points to the previous index that has the + /// same hash code as the string starting at index. This way + /// entries with the same hash code are in a linked list. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xffff. + /// + short[] prev; + + int matchStart; + // Length of best match + int matchLen; + // Set if previous match exists + bool prevAvailable; + int blockStart; + + /// + /// Points to the current character in the window. + /// + int strstart; + + /// + /// lookahead is the number of characters starting at strstart in + /// window that are valid. + /// So window[strstart] until window[strstart+lookahead-1] are valid + /// characters. + /// + int lookahead; + + /// + /// This array contains the part of the uncompressed stream that + /// is of relevance. The current character is indexed by strstart. + /// + byte[] window; + + DeflateStrategy strategy; + int max_chain, max_lazy, niceLength, goodLength; + + /// + /// The current compression function. + /// + int compressionFunction; + + /// + /// The input data for compression. + /// + byte[] inputBuf; + + /// + /// The total bytes of input read. + /// + long totalIn; + + /// + /// The offset into inputBuf, where input data starts. + /// + int inputOff; + + /// + /// The end offset of the input data. + /// + int inputEnd; + + DeflaterPending pending; + DeflaterHuffman huffman; + + /// + /// The adler checksum + /// + Adler32 adler; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/DeflaterHuffman.cs b/PCRobot/Utils/ZIP/Zip/Compression/DeflaterHuffman.cs new file mode 100644 index 0000000..8c89e59 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/DeflaterHuffman.cs @@ -0,0 +1,908 @@ +// DeflaterHuffman.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This is the DeflaterHuffman class. + /// + /// This class is not thread safe. This is inherent in the API, due + /// to the split of Deflate and SetInput. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class DeflaterHuffman + { + const int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6); + const int LITERAL_NUM = 286; + + // Number of distance codes + const int DIST_NUM = 30; + // Number of codes used to transfer bit lengths + const int BITLEN_NUM = 19; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + const int REP_3_6 = 16; + // repeat a zero length 3-10 times (3 bits of repeat count) + const int REP_3_10 = 17; + // repeat a zero length 11-138 times (7 bits of repeat count) + const int REP_11_138 = 18; + + const int EOF_SYMBOL = 256; + + // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit length codes. + static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + static readonly byte[] bit4Reverse = { + 0, + 8, + 4, + 12, + 2, + 10, + 6, + 14, + 1, + 9, + 5, + 13, + 3, + 11, + 7, + 15 + }; + + static short[] staticLCodes; + static byte[] staticLLength; + static short[] staticDCodes; + static byte[] staticDLength; + + class Tree + { + #region Instance Fields + public short[] freqs; + + public byte[] length; + + public int minNumCodes; + + public int numCodes; + + short[] codes; + int[] bl_counts; + int maxLength; + DeflaterHuffman dh; + #endregion + + #region Constructors + public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength) + { + this.dh = dh; + this.minNumCodes = minCodes; + this.maxLength = maxLength; + freqs = new short[elems]; + bl_counts = new int[maxLength]; + } + + #endregion + + /// + /// Resets the internal state of the tree + /// + public void Reset() + { + for (int i = 0; i < freqs.Length; i++) { + freqs[i] = 0; + } + codes = null; + length = null; + } + + public void WriteSymbol(int code) + { + // if (DeflaterConstants.DEBUGGING) { + // freqs[code]--; + // // Console.Write("writeSymbol("+freqs.length+","+code+"): "); + // } + dh.pending.WriteBits(codes[code] & 0xffff, length[code]); + } + + /// + /// Check that all frequencies are zero + /// + /// + /// At least one frequency is non-zero + /// + public void CheckEmpty() + { + bool empty = true; + for (int i = 0; i < freqs.Length; i++) { + if (freqs[i] != 0) { + //Console.WriteLine("freqs[" + i + "] == " + freqs[i]); + empty = false; + } + } + + if (!empty) { + throw new SharpZipBaseException("!Empty"); + } + } + + /// + /// Set static codes and length + /// + /// new codes + /// length for new codes + public void SetStaticCodes(short[] staticCodes, byte[] staticLengths) + { + codes = staticCodes; + length = staticLengths; + } + + /// + /// Build dynamic codes and lengths + /// + public void BuildCodes() + { + int numSymbols = freqs.Length; + int[] nextCode = new int[maxLength]; + int code = 0; + + codes = new short[freqs.Length]; + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("buildCodes: "+freqs.Length); + // } + + for (int bits = 0; bits < maxLength; bits++) { + nextCode[bits] = code; + code += bl_counts[bits] << (15 - bits); + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits] + // +" nextCode: "+code); + // } + } + +#if DebugDeflation + if ( DeflaterConstants.DEBUGGING && (code != 65536) ) + { + throw new SharpZipBaseException("Inconsistent bl_counts!"); + } +#endif + for (int i=0; i < numCodes; i++) { + int bits = length[i]; + if (bits > 0) { + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"), + // +bits); + // } + + codes[i] = BitReverse(nextCode[bits-1]); + nextCode[bits-1] += 1 << (16 - bits); + } + } + } + + public void BuildTree() + { + int numSymbols = freqs.Length; + + /* heap is a priority queue, sorted by frequency, least frequent + * nodes first. The heap is a binary tree, with the property, that + * the parent node is smaller than both child nodes. This assures + * that the smallest node is the first parent. + * + * The binary tree is encoded in an array: 0 is root node and + * the nodes 2*n+1, 2*n+2 are the child nodes of node n. + */ + int[] heap = new int[numSymbols]; + int heapLen = 0; + int maxCode = 0; + for (int n = 0; n < numSymbols; n++) { + int freq = freqs[n]; + if (freq != 0) { + // Insert n into heap + int pos = heapLen++; + int ppos; + while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) { + heap[pos] = heap[ppos]; + pos = ppos; + } + heap[pos] = n; + + maxCode = n; + } + } + + /* We could encode a single literal with 0 bits but then we + * don't see the literals. Therefore we force at least two + * literals to avoid this case. We don't care about order in + * this case, both literals get a 1 bit code. + */ + while (heapLen < 2) { + int node = maxCode < 2 ? ++maxCode : 0; + heap[heapLen++] = node; + } + + numCodes = Math.Max(maxCode + 1, minNumCodes); + + int numLeafs = heapLen; + int[] childs = new int[4 * heapLen - 2]; + int[] values = new int[2 * heapLen - 1]; + int numNodes = numLeafs; + for (int i = 0; i < heapLen; i++) { + int node = heap[i]; + childs[2 * i] = node; + childs[2 * i + 1] = -1; + values[i] = freqs[node] << 8; + heap[i] = i; + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + int first = heap[0]; + int last = heap[--heapLen]; + + // Propagate the hole to the leafs of the heap + int ppos = 0; + int path = 1; + + while (path < heapLen) { + if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) { + path++; + } + + heap[ppos] = heap[path]; + ppos = path; + path = path * 2 + 1; + } + + /* Now propagate the last element down along path. Normally + * it shouldn't go too deep. + */ + int lastVal = values[last]; + while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) { + heap[path] = heap[ppos]; + } + heap[path] = last; + + + int second = heap[0]; + + // Create a new node father of first and second + last = numNodes++; + childs[2 * last] = first; + childs[2 * last + 1] = second; + int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff); + values[last] = lastVal = values[first] + values[second] - mindepth + 1; + + // Again, propagate the hole to the leafs + ppos = 0; + path = 1; + + while (path < heapLen) { + if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) { + path++; + } + + heap[ppos] = heap[path]; + ppos = path; + path = ppos * 2 + 1; + } + + // Now propagate the new element down along path + while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) { + heap[path] = heap[ppos]; + } + heap[path] = last; + } while (heapLen > 1); + + if (heap[0] != childs.Length / 2 - 1) { + throw new SharpZipBaseException("Heap invariant violated"); + } + + BuildLength(childs); + } + + /// + /// Get encoded length + /// + /// Encoded length, the sum of frequencies * lengths + public int GetEncodedLength() + { + int len = 0; + for (int i = 0; i < freqs.Length; i++) { + len += freqs[i] * length[i]; + } + return len; + } + + /// + /// Scan a literal or distance tree to determine the frequencies of the codes + /// in the bit length tree. + /// + public void CalcBLFreq(Tree blTree) + { + int max_count; /* max repeat count */ + int min_count; /* min repeat count */ + int count; /* repeat count of the current code */ + int curlen = -1; /* length of current code */ + + int i = 0; + while (i < numCodes) { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else { + max_count = 6; + min_count = 3; + if (curlen != nextlen) { + blTree.freqs[nextlen]++; + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) { + i++; + if (++count >= max_count) { + break; + } + } + + if (count < min_count) { + blTree.freqs[curlen] += (short)count; + } else if (curlen != 0) { + blTree.freqs[REP_3_6]++; + } else if (count <= 10) { + blTree.freqs[REP_3_10]++; + } else { + blTree.freqs[REP_11_138]++; + } + } + } + + /// + /// Write tree values + /// + /// Tree to write + public void WriteTree(Tree blTree) + { + int max_count; // max repeat count + int min_count; // min repeat count + int count; // repeat count of the current code + int curlen = -1; // length of current code + + int i = 0; + while (i < numCodes) { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else { + max_count = 6; + min_count = 3; + if (curlen != nextlen) { + blTree.WriteSymbol(nextlen); + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) { + i++; + if (++count >= max_count) { + break; + } + } + + if (count < min_count) { + while (count-- > 0) { + blTree.WriteSymbol(curlen); + } + } else if (curlen != 0) { + blTree.WriteSymbol(REP_3_6); + dh.pending.WriteBits(count - 3, 2); + } else if (count <= 10) { + blTree.WriteSymbol(REP_3_10); + dh.pending.WriteBits(count - 3, 3); + } else { + blTree.WriteSymbol(REP_11_138); + dh.pending.WriteBits(count - 11, 7); + } + } + } + + void BuildLength(int[] childs) + { + this.length = new byte [freqs.Length]; + int numNodes = childs.Length / 2; + int numLeafs = (numNodes + 1) / 2; + int overflow = 0; + + for (int i = 0; i < maxLength; i++) { + bl_counts[i] = 0; + } + + // First calculate optimal bit lengths + int[] lengths = new int[numNodes]; + lengths[numNodes-1] = 0; + + for (int i = numNodes - 1; i >= 0; i--) { + if (childs[2 * i + 1] != -1) { + int bitLength = lengths[i] + 1; + if (bitLength > maxLength) { + bitLength = maxLength; + overflow++; + } + lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength; + } else { + // A leaf node + int bitLength = lengths[i]; + bl_counts[bitLength - 1]++; + this.length[childs[2*i]] = (byte) lengths[i]; + } + } + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Tree "+freqs.Length+" lengths:"); + // for (int i=0; i < numLeafs; i++) { + // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + // + " len: "+length[childs[2*i]]); + // } + // } + + if (overflow == 0) { + return; + } + + int incrBitLen = maxLength - 1; + do { + // Find the first bit length which could increase: + while (bl_counts[--incrBitLen] == 0) + ; + + // Move this node one down and remove a corresponding + // number of overflow nodes. + do { + bl_counts[incrBitLen]--; + bl_counts[++incrBitLen]++; + overflow -= 1 << (maxLength - 1 - incrBitLen); + } while (overflow > 0 && incrBitLen < maxLength - 1); + } while (overflow > 0); + + /* We may have overshot above. Move some nodes from maxLength to + * maxLength-1 in that case. + */ + bl_counts[maxLength-1] += overflow; + bl_counts[maxLength-2] -= overflow; + + /* Now recompute all bit lengths, scanning in increasing + * frequency. It is simpler to reconstruct all lengths instead of + * fixing only the wrong ones. This idea is taken from 'ar' + * written by Haruhiko Okumura. + * + * The nodes were inserted with decreasing frequency into the childs + * array. + */ + int nodePtr = 2 * numLeafs; + for (int bits = maxLength; bits != 0; bits--) { + int n = bl_counts[bits-1]; + while (n > 0) { + int childPtr = 2*childs[nodePtr++]; + if (childs[childPtr + 1] == -1) { + // We found another leaf + length[childs[childPtr]] = (byte) bits; + n--; + } + } + } + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("*** After overflow elimination. ***"); + // for (int i=0; i < numLeafs; i++) { + // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + // + " len: "+length[childs[2*i]]); + // } + // } + } + + } + + #region Instance Fields + /// + /// Pending buffer to use + /// + public DeflaterPending pending; + + Tree literalTree; + Tree distTree; + Tree blTree; + + // Buffer for distances + short[] d_buf; + byte[] l_buf; + int last_lit; + int extra_bits; + #endregion + + static DeflaterHuffman() + { + // See RFC 1951 3.2.6 + // Literal codes + staticLCodes = new short[LITERAL_NUM]; + staticLLength = new byte[LITERAL_NUM]; + + int i = 0; + while (i < 144) { + staticLCodes[i] = BitReverse((0x030 + i) << 8); + staticLLength[i++] = 8; + } + + while (i < 256) { + staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7); + staticLLength[i++] = 9; + } + + while (i < 280) { + staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9); + staticLLength[i++] = 7; + } + + while (i < LITERAL_NUM) { + staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8); + staticLLength[i++] = 8; + } + + // Distance codes + staticDCodes = new short[DIST_NUM]; + staticDLength = new byte[DIST_NUM]; + for (i = 0; i < DIST_NUM; i++) { + staticDCodes[i] = BitReverse(i << 11); + staticDLength[i] = 5; + } + } + + /// + /// Construct instance with pending buffer + /// + /// Pending buffer to use + public DeflaterHuffman(DeflaterPending pending) + { + this.pending = pending; + + literalTree = new Tree(this, LITERAL_NUM, 257, 15); + distTree = new Tree(this, DIST_NUM, 1, 15); + blTree = new Tree(this, BITLEN_NUM, 4, 7); + + d_buf = new short[BUFSIZE]; + l_buf = new byte [BUFSIZE]; + } + + /// + /// Reset internal state + /// + public void Reset() + { + last_lit = 0; + extra_bits = 0; + literalTree.Reset(); + distTree.Reset(); + blTree.Reset(); + } + + /// + /// Write all trees to pending buffer + /// + /// The number/rank of treecodes to send. + public void SendAllTrees(int blTreeCodes) + { + blTree.BuildCodes(); + literalTree.BuildCodes(); + distTree.BuildCodes(); + pending.WriteBits(literalTree.numCodes - 257, 5); + pending.WriteBits(distTree.numCodes - 1, 5); + pending.WriteBits(blTreeCodes - 4, 4); + for (int rank = 0; rank < blTreeCodes; rank++) { + pending.WriteBits(blTree.length[BL_ORDER[rank]], 3); + } + literalTree.WriteTree(blTree); + distTree.WriteTree(blTree); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + blTree.CheckEmpty(); + } +#endif + } + + /// + /// Compress current buffer writing data to pending buffer + /// + public void CompressBlock() + { + for (int i = 0; i < last_lit; i++) { + int litlen = l_buf[i] & 0xff; + int dist = d_buf[i]; + if (dist-- != 0) { + // if (DeflaterConstants.DEBUGGING) { + // Console.Write("["+(dist+1)+","+(litlen+3)+"]: "); + // } + + int lc = Lcode(litlen); + literalTree.WriteSymbol(lc); + + int bits = (lc - 261) / 4; + if (bits > 0 && bits <= 5) { + pending.WriteBits(litlen & ((1 << bits) - 1), bits); + } + + int dc = Dcode(dist); + distTree.WriteSymbol(dc); + + bits = dc / 2 - 1; + if (bits > 0) { + pending.WriteBits(dist & ((1 << bits) - 1), bits); + } + } else { + // if (DeflaterConstants.DEBUGGING) { + // if (litlen > 32 && litlen < 127) { + // Console.Write("("+(char)litlen+"): "); + // } else { + // Console.Write("{"+litlen+"}: "); + // } + // } + literalTree.WriteSymbol(litlen); + } + } + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.Write("EOF: "); + } +#endif + literalTree.WriteSymbol(EOF_SYMBOL); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + literalTree.CheckEmpty(); + distTree.CheckEmpty(); + } +#endif + } + + /// + /// Flush block to output with no compression + /// + /// Data to write + /// Index of first byte to write + /// Count of bytes to write + /// True if this is the last block + public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) + { +#if DebugDeflation + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Flushing stored block "+ storedLength); + // } +#endif + pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3); + pending.AlignToByte(); + pending.WriteShort(storedLength); + pending.WriteShort(~storedLength); + pending.WriteBlock(stored, storedOffset, storedLength); + Reset(); + } + + /// + /// Flush block to output with compression + /// + /// Data to flush + /// Index of first byte to flush + /// Count of bytes to flush + /// True if this is the last block + public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) + { + literalTree.freqs[EOF_SYMBOL]++; + + // Build trees + literalTree.BuildTree(); + distTree.BuildTree(); + + // Calculate bitlen frequency + literalTree.CalcBLFreq(blTree); + distTree.CalcBLFreq(blTree); + + // Build bitlen tree + blTree.BuildTree(); + + int blTreeCodes = 4; + for (int i = 18; i > blTreeCodes; i--) { + if (blTree.length[BL_ORDER[i]] > 0) { + blTreeCodes = i+1; + } + } + int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() + + literalTree.GetEncodedLength() + distTree.GetEncodedLength() + + extra_bits; + + int static_len = extra_bits; + for (int i = 0; i < LITERAL_NUM; i++) { + static_len += literalTree.freqs[i] * staticLLength[i]; + } + for (int i = 0; i < DIST_NUM; i++) { + static_len += distTree.freqs[i] * staticDLength[i]; + } + if (opt_len >= static_len) { + // Force static trees + opt_len = static_len; + } + + if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) { + // Store Block + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len + // + " <= " + static_len); + // } + FlushStoredBlock(stored, storedOffset, storedLength, lastBlock); + } else if (opt_len == static_len) { + // Encode with static tree + pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3); + literalTree.SetStaticCodes(staticLCodes, staticLLength); + distTree.SetStaticCodes(staticDCodes, staticDLength); + CompressBlock(); + Reset(); + } else { + // Encode with dynamic tree + pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3); + SendAllTrees(blTreeCodes); + CompressBlock(); + Reset(); + } + } + + /// + /// Get value indicating if internal buffer is full + /// + /// true if buffer is full + public bool IsFull() + { + return last_lit >= BUFSIZE; + } + + /// + /// Add literal to buffer + /// + /// Literal value to add to buffer. + /// Value indicating internal buffer is full + public bool TallyLit(int literal) + { + // if (DeflaterConstants.DEBUGGING) { + // if (lit > 32 && lit < 127) { + // //Console.WriteLine("("+(char)lit+")"); + // } else { + // //Console.WriteLine("{"+lit+"}"); + // } + // } + d_buf[last_lit] = 0; + l_buf[last_lit++] = (byte)literal; + literalTree.freqs[literal]++; + return IsFull(); + } + + /// + /// Add distance code and length to literal and distance trees + /// + /// Distance code + /// Length + /// Value indicating if internal buffer is full + public bool TallyDist(int distance, int length) + { + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("[" + distance + "," + length + "]"); + // } + + d_buf[last_lit] = (short)distance; + l_buf[last_lit++] = (byte)(length - 3); + + int lc = Lcode(length - 3); + literalTree.freqs[lc]++; + if (lc >= 265 && lc < 285) { + extra_bits += (lc - 261) / 4; + } + + int dc = Dcode(distance - 1); + distTree.freqs[dc]++; + if (dc >= 4) { + extra_bits += dc / 2 - 1; + } + return IsFull(); + } + + + /// + /// Reverse the bits of a 16 bit value. + /// + /// Value to reverse bits + /// Value with bits reversed + public static short BitReverse(int toReverse) + { + return (short) (bit4Reverse[toReverse & 0xF] << 12 | + bit4Reverse[(toReverse >> 4) & 0xF] << 8 | + bit4Reverse[(toReverse >> 8) & 0xF] << 4 | + bit4Reverse[toReverse >> 12]); + } + + static int Lcode(int length) + { + if (length == 255) { + return 285; + } + + int code = 257; + while (length >= 8) { + code += 4; + length >>= 1; + } + return code + length; + } + + static int Dcode(int distance) + { + int code = 0; + while (distance >= 4) { + code += 2; + distance >>= 1; + } + return code + distance; + } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/DeflaterPending.cs b/PCRobot/Utils/ZIP/Zip/Compression/DeflaterPending.cs new file mode 100644 index 0000000..4cecc2e --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/DeflaterPending.cs @@ -0,0 +1,57 @@ +// DeflaterPending.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class stores the pending output of the Deflater. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class DeflaterPending : PendingBuffer + { + /// + /// Construct instance with default buffer size + /// + public DeflaterPending() : base(DeflaterConstants.PENDING_BUF_SIZE) + { + } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/Inflater.cs b/PCRobot/Utils/ZIP/Zip/Compression/Inflater.cs new file mode 100644 index 0000000..16c3ef6 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/Inflater.cs @@ -0,0 +1,864 @@ +// Inflater.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + /// + /// Inflater is used to decompress data that has been compressed according + /// to the "deflate" standard described in rfc1951. + /// + /// By default Zlib (rfc1950) headers and footers are expected in the input. + /// You can use constructor public Inflater(bool noHeader) passing true + /// if there is no Zlib header information + /// + /// The usage is as following. First you have to set some input with + /// SetInput(), then Inflate() it. If inflate doesn't + /// inflate any bytes there may be three reasons: + ///
    + ///
  • IsNeedingInput() returns true because the input buffer is empty. + /// You have to provide more input with SetInput(). + /// NOTE: IsNeedingInput() also returns true when, the stream is finished. + ///
  • + ///
  • IsNeedingDictionary() returns true, you have to provide a preset + /// dictionary with SetDictionary().
  • + ///
  • IsFinished returns true, the inflater has finished.
  • + ///
+ /// Once the first output byte is produced, a dictionary will not be + /// needed at a later stage. + /// + /// author of the original java version : John Leuner, Jochen Hoenicke + ///
+ public class Inflater + { + #region Constants/Readonly + /// + /// Copy lengths for literal codes 257..285 + /// + static readonly int[] CPLENS = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 + }; + + /// + /// Extra bits for literal codes 257..285 + /// + static readonly int[] CPLEXT = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; + + /// + /// Copy offsets for distance codes 0..29 + /// + static readonly int[] CPDIST = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + /// + /// Extra bits for distance codes + /// + static readonly int[] CPDEXT = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + }; + + /// + /// These are the possible states for an inflater + /// + const int DECODE_HEADER = 0; + const int DECODE_DICT = 1; + const int DECODE_BLOCKS = 2; + const int DECODE_STORED_LEN1 = 3; + const int DECODE_STORED_LEN2 = 4; + const int DECODE_STORED = 5; + const int DECODE_DYN_HEADER = 6; + const int DECODE_HUFFMAN = 7; + const int DECODE_HUFFMAN_LENBITS = 8; + const int DECODE_HUFFMAN_DIST = 9; + const int DECODE_HUFFMAN_DISTBITS = 10; + const int DECODE_CHKSUM = 11; + const int FINISHED = 12; + #endregion + + #region Instance Fields + /// + /// This variable contains the current state. + /// + int mode; + + /// + /// The adler checksum of the dictionary or of the decompressed + /// stream, as it is written in the header resp. footer of the + /// compressed stream. + /// Only valid if mode is DECODE_DICT or DECODE_CHKSUM. + /// + int readAdler; + + /// + /// The number of bits needed to complete the current state. This + /// is valid, if mode is DECODE_DICT, DECODE_CHKSUM, + /// DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. + /// + int neededBits; + int repLength; + int repDist; + int uncomprLen; + + /// + /// True, if the last block flag was set in the last block of the + /// inflated stream. This means that the stream ends after the + /// current block. + /// + bool isLastBlock; + + /// + /// The total number of inflated bytes. + /// + long totalOut; + + /// + /// The total number of bytes set with setInput(). This is not the + /// value returned by the TotalIn property, since this also includes the + /// unprocessed input. + /// + long totalIn; + + /// + /// This variable stores the noHeader flag that was given to the constructor. + /// True means, that the inflated stream doesn't contain a Zlib header or + /// footer. + /// + bool noHeader; + + StreamManipulator input; + OutputWindow outputWindow; + InflaterDynHeader dynHeader; + InflaterHuffmanTree litlenTree, distTree; + Adler32 adler; + #endregion + + #region Constructors + /// + /// Creates a new inflater or RFC1951 decompressor + /// RFC1950/Zlib headers and footers will be expected in the input data + /// + public Inflater() : this(false) + { + } + + /// + /// Creates a new inflater. + /// + /// + /// True if no RFC1950/Zlib header and footer fields are expected in the input data + /// + /// This is used for GZIPed/Zipped input. + /// + /// For compatibility with + /// Sun JDK you should provide one byte of input more than needed in + /// this case. + /// + public Inflater(bool noHeader) + { + this.noHeader = noHeader; + this.adler = new Adler32(); + input = new StreamManipulator(); + outputWindow = new OutputWindow(); + mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; + } + #endregion + + /// + /// Resets the inflater so that a new stream can be decompressed. All + /// pending input and output will be discarded. + /// + public void Reset() + { + mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; + totalIn = 0; + totalOut = 0; + input.Reset(); + outputWindow.Reset(); + dynHeader = null; + litlenTree = null; + distTree = null; + isLastBlock = false; + adler.Reset(); + } + + /// + /// Decodes a zlib/RFC1950 header. + /// + /// + /// False if more input is needed. + /// + /// + /// The header is invalid. + /// + private bool DecodeHeader() + { + int header = input.PeekBits(16); + if (header < 0) { + return false; + } + input.DropBits(16); + + // The header is written in "wrong" byte order + header = ((header << 8) | (header >> 8)) & 0xffff; + if (header % 31 != 0) { + throw new SharpZipBaseException("Header checksum illegal"); + } + + if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) { + throw new SharpZipBaseException("Compression Method unknown"); + } + + /* Maximum size of the backwards window in bits. + * We currently ignore this, but we could use it to make the + * inflater window more space efficient. On the other hand the + * full window (15 bits) is needed most times, anyway. + int max_wbits = ((header & 0x7000) >> 12) + 8; + */ + + if ((header & 0x0020) == 0) { // Dictionary flag? + mode = DECODE_BLOCKS; + } else { + mode = DECODE_DICT; + neededBits = 32; + } + return true; + } + + /// + /// Decodes the dictionary checksum after the deflate header. + /// + /// + /// False if more input is needed. + /// + private bool DecodeDict() + { + while (neededBits > 0) { + int dictByte = input.PeekBits(8); + if (dictByte < 0) { + return false; + } + input.DropBits(8); + readAdler = (readAdler << 8) | dictByte; + neededBits -= 8; + } + return false; + } + + /// + /// Decodes the huffman encoded symbols in the input stream. + /// + /// + /// false if more input is needed, true if output window is + /// full or the current block ends. + /// + /// + /// if deflated stream is invalid. + /// + private bool DecodeHuffman() + { + int free = outputWindow.GetFreeSpace(); + while (free >= 258) + { + int symbol; + switch (mode) + { + case DECODE_HUFFMAN: + // This is the inner loop so it is optimized a bit + while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0) + { + outputWindow.Write(symbol); + if (--free < 258) + { + return true; + } + } + + if (symbol < 257) + { + if (symbol < 0) + { + return false; + } + else + { + // symbol == 256: end of block + distTree = null; + litlenTree = null; + mode = DECODE_BLOCKS; + return true; + } + } + + try + { + repLength = CPLENS[symbol - 257]; + neededBits = CPLEXT[symbol - 257]; + } + catch (Exception) + { + throw new SharpZipBaseException("Illegal rep length code"); + } + goto case DECODE_HUFFMAN_LENBITS; // fall through + + case DECODE_HUFFMAN_LENBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_LENBITS; + int i = input.PeekBits(neededBits); + if (i < 0) + { + return false; + } + input.DropBits(neededBits); + repLength += i; + } + mode = DECODE_HUFFMAN_DIST; + goto case DECODE_HUFFMAN_DIST; // fall through + + case DECODE_HUFFMAN_DIST: + symbol = distTree.GetSymbol(input); + if (symbol < 0) + { + return false; + } + + try + { + repDist = CPDIST[symbol]; + neededBits = CPDEXT[symbol]; + } + catch (Exception) + { + throw new SharpZipBaseException("Illegal rep dist code"); + } + + goto case DECODE_HUFFMAN_DISTBITS; // fall through + + case DECODE_HUFFMAN_DISTBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_DISTBITS; + int i = input.PeekBits(neededBits); + if (i < 0) + { + return false; + } + input.DropBits(neededBits); + repDist += i; + } + + outputWindow.Repeat(repLength, repDist); + free -= repLength; + mode = DECODE_HUFFMAN; + break; + + default: + throw new SharpZipBaseException("Inflater unknown mode"); + } + } + return true; + } + + /// + /// Decodes the adler checksum after the deflate stream. + /// + /// + /// false if more input is needed. + /// + /// + /// If checksum doesn't match. + /// + private bool DecodeChksum() + { + while (neededBits > 0) { + int chkByte = input.PeekBits(8); + if (chkByte < 0) { + return false; + } + input.DropBits(8); + readAdler = (readAdler << 8) | chkByte; + neededBits -= 8; + } + + if ((int) adler.Value != readAdler) { + throw new SharpZipBaseException("Adler chksum doesn't match: " + (int)adler.Value + " vs. " + readAdler); + } + + mode = FINISHED; + return false; + } + + /// + /// Decodes the deflated stream. + /// + /// + /// false if more input is needed, or if finished. + /// + /// + /// if deflated stream is invalid. + /// + private bool Decode() + { + switch (mode) { + case DECODE_HEADER: + return DecodeHeader(); + + case DECODE_DICT: + return DecodeDict(); + + case DECODE_CHKSUM: + return DecodeChksum(); + + case DECODE_BLOCKS: + if (isLastBlock) { + if (noHeader) { + mode = FINISHED; + return false; + } else { + input.SkipToByteBoundary(); + neededBits = 32; + mode = DECODE_CHKSUM; + return true; + } + } + + int type = input.PeekBits(3); + if (type < 0) { + return false; + } + input.DropBits(3); + + if ((type & 1) != 0) { + isLastBlock = true; + } + switch (type >> 1){ + case DeflaterConstants.STORED_BLOCK: + input.SkipToByteBoundary(); + mode = DECODE_STORED_LEN1; + break; + case DeflaterConstants.STATIC_TREES: + litlenTree = InflaterHuffmanTree.defLitLenTree; + distTree = InflaterHuffmanTree.defDistTree; + mode = DECODE_HUFFMAN; + break; + case DeflaterConstants.DYN_TREES: + dynHeader = new InflaterDynHeader(); + mode = DECODE_DYN_HEADER; + break; + default: + throw new SharpZipBaseException("Unknown block type " + type); + } + return true; + + case DECODE_STORED_LEN1: + { + if ((uncomprLen = input.PeekBits(16)) < 0) { + return false; + } + input.DropBits(16); + mode = DECODE_STORED_LEN2; + } + goto case DECODE_STORED_LEN2; // fall through + + case DECODE_STORED_LEN2: + { + int nlen = input.PeekBits(16); + if (nlen < 0) { + return false; + } + input.DropBits(16); + if (nlen != (uncomprLen ^ 0xffff)) { + throw new SharpZipBaseException("broken uncompressed block"); + } + mode = DECODE_STORED; + } + goto case DECODE_STORED; // fall through + + case DECODE_STORED: + { + int more = outputWindow.CopyStored(input, uncomprLen); + uncomprLen -= more; + if (uncomprLen == 0) { + mode = DECODE_BLOCKS; + return true; + } + return !input.IsNeedingInput; + } + + case DECODE_DYN_HEADER: + if (!dynHeader.Decode(input)) { + return false; + } + + litlenTree = dynHeader.BuildLitLenTree(); + distTree = dynHeader.BuildDistTree(); + mode = DECODE_HUFFMAN; + goto case DECODE_HUFFMAN; // fall through + + case DECODE_HUFFMAN: + case DECODE_HUFFMAN_LENBITS: + case DECODE_HUFFMAN_DIST: + case DECODE_HUFFMAN_DISTBITS: + return DecodeHuffman(); + + case FINISHED: + return false; + + default: + throw new SharpZipBaseException("Inflater.Decode unknown mode"); + } + } + + /// + /// Sets the preset dictionary. This should only be called, if + /// needsDictionary() returns true and it should set the same + /// dictionary, that was used for deflating. The getAdler() + /// function returns the checksum of the dictionary needed. + /// + /// + /// The dictionary. + /// + public void SetDictionary(byte[] buffer) + { + SetDictionary(buffer, 0, buffer.Length); + } + + /// + /// Sets the preset dictionary. This should only be called, if + /// needsDictionary() returns true and it should set the same + /// dictionary, that was used for deflating. The getAdler() + /// function returns the checksum of the dictionary needed. + /// + /// + /// The dictionary. + /// + /// + /// The index into buffer where the dictionary starts. + /// + /// + /// The number of bytes in the dictionary. + /// + /// + /// No dictionary is needed. + /// + /// + /// The adler checksum for the buffer is invalid + /// + public void SetDictionary(byte[] buffer, int index, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( index < 0 ) { + throw new ArgumentOutOfRangeException("index"); + } + + if ( count < 0 ) { + throw new ArgumentOutOfRangeException("count"); + } + + if (!IsNeedingDictionary) { + throw new InvalidOperationException("Dictionary is not needed"); + } + + adler.Update(buffer, index, count); + + if ((int)adler.Value != readAdler) { + throw new SharpZipBaseException("Wrong adler checksum"); + } + adler.Reset(); + outputWindow.CopyDict(buffer, index, count); + mode = DECODE_BLOCKS; + } + + /// + /// Sets the input. This should only be called, if needsInput() + /// returns true. + /// + /// + /// the input. + /// + public void SetInput(byte[] buffer) + { + SetInput(buffer, 0, buffer.Length); + } + + /// + /// Sets the input. This should only be called, if needsInput() + /// returns true. + /// + /// + /// The source of input data + /// + /// + /// The index into buffer where the input starts. + /// + /// + /// The number of bytes of input to use. + /// + /// + /// No input is needed. + /// + /// + /// The index and/or count are wrong. + /// + public void SetInput(byte[] buffer, int index, int count) + { + input.SetInput(buffer, index, count); + totalIn += (long)count; + } + + /// + /// Inflates the compressed stream to the output buffer. If this + /// returns 0, you should check, whether IsNeedingDictionary(), + /// IsNeedingInput() or IsFinished() returns true, to determine why no + /// further output is produced. + /// + /// + /// the output buffer. + /// + /// + /// The number of bytes written to the buffer, 0 if no further + /// output can be produced. + /// + /// + /// if buffer has length 0. + /// + /// + /// if deflated stream is invalid. + /// + public int Inflate(byte[] buffer) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + return Inflate(buffer, 0, buffer.Length); + } + + /// + /// Inflates the compressed stream to the output buffer. If this + /// returns 0, you should check, whether needsDictionary(), + /// needsInput() or finished() returns true, to determine why no + /// further output is produced. + /// + /// + /// the output buffer. + /// + /// + /// the offset in buffer where storing starts. + /// + /// + /// the maximum number of bytes to output. + /// + /// + /// the number of bytes written to the buffer, 0 if no further output can be produced. + /// + /// + /// if count is less than 0. + /// + /// + /// if the index and / or count are wrong. + /// + /// + /// if deflated stream is invalid. + /// + public int Inflate(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "count cannot be negative"); +#endif + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "offset cannot be negative"); +#endif + } + + if ( offset + count > buffer.Length ) { + throw new ArgumentException("count exceeds buffer bounds"); + } + + // Special case: count may be zero + if (count == 0) + { + if (!IsFinished) { // -jr- 08-Nov-2003 INFLATE_BUG fix.. + Decode(); + } + return 0; + } + + int bytesCopied = 0; + + do { + if (mode != DECODE_CHKSUM) { + /* Don't give away any output, if we are waiting for the + * checksum in the input stream. + * + * With this trick we have always: + * IsNeedingInput() and not IsFinished() + * implies more output can be produced. + */ + int more = outputWindow.CopyOutput(buffer, offset, count); + if ( more > 0 ) { + adler.Update(buffer, offset, more); + offset += more; + bytesCopied += more; + totalOut += (long)more; + count -= more; + if (count == 0) { + return bytesCopied; + } + } + } + } while (Decode() || ((outputWindow.GetAvailable() > 0) && (mode != DECODE_CHKSUM))); + return bytesCopied; + } + + /// + /// Returns true, if the input buffer is empty. + /// You should then call setInput(). + /// NOTE: This method also returns true when the stream is finished. + /// + public bool IsNeedingInput { + get { + return input.IsNeedingInput; + } + } + + /// + /// Returns true, if a preset dictionary is needed to inflate the input. + /// + public bool IsNeedingDictionary { + get { + return mode == DECODE_DICT && neededBits == 0; + } + } + + /// + /// Returns true, if the inflater has finished. This means, that no + /// input is needed and no output can be produced. + /// + public bool IsFinished { + get { + return mode == FINISHED && outputWindow.GetAvailable() == 0; + } + } + + /// + /// Gets the adler checksum. This is either the checksum of all + /// uncompressed bytes returned by inflate(), or if needsDictionary() + /// returns true (and thus no output was yet produced) this is the + /// adler checksum of the expected dictionary. + /// + /// + /// the adler checksum. + /// + public int Adler { + get { + return IsNeedingDictionary ? readAdler : (int) adler.Value; + } + } + + /// + /// Gets the total number of output bytes returned by Inflate(). + /// + /// + /// the total number of output bytes. + /// + public long TotalOut { + get { + return totalOut; + } + } + + /// + /// Gets the total number of processed compressed input bytes. + /// + /// + /// The total number of bytes of processed input bytes. + /// + public long TotalIn { + get { + return totalIn - (long)RemainingInput; + } + } + + /// + /// Gets the number of unprocessed input bytes. Useful, if the end of the + /// stream is reached and you want to further process the bytes after + /// the deflate stream. + /// + /// + /// The number of bytes of the input which have not been processed. + /// + public int RemainingInput { + // TODO: This should be a long? + get { + return input.AvailableBytes; + } + } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/InflaterDynHeader.cs b/PCRobot/Utils/ZIP/Zip/Compression/InflaterDynHeader.cs new file mode 100644 index 0000000..77e87ac --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/InflaterDynHeader.cs @@ -0,0 +1,218 @@ +// InflaterDynHeader.cs +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + class InflaterDynHeader + { + #region Constants + const int LNUM = 0; + const int DNUM = 1; + const int BLNUM = 2; + const int BLLENS = 3; + const int LENS = 4; + const int REPS = 5; + + static readonly int[] repMin = { 3, 3, 11 }; + static readonly int[] repBits = { 2, 3, 7 }; + + static readonly int[] BL_ORDER = + { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + #endregion + + #region Constructors + public InflaterDynHeader() + { + } + #endregion + + public bool Decode(StreamManipulator input) + { + decode_loop: + for (;;) { + switch (mode) { + case LNUM: + lnum = input.PeekBits(5); + if (lnum < 0) { + return false; + } + lnum += 257; + input.DropBits(5); + // System.err.println("LNUM: "+lnum); + mode = DNUM; + goto case DNUM; // fall through + case DNUM: + dnum = input.PeekBits(5); + if (dnum < 0) { + return false; + } + dnum++; + input.DropBits(5); + // System.err.println("DNUM: "+dnum); + num = lnum+dnum; + litdistLens = new byte[num]; + mode = BLNUM; + goto case BLNUM; // fall through + case BLNUM: + blnum = input.PeekBits(4); + if (blnum < 0) { + return false; + } + blnum += 4; + input.DropBits(4); + blLens = new byte[19]; + ptr = 0; + // System.err.println("BLNUM: "+blnum); + mode = BLLENS; + goto case BLLENS; // fall through + case BLLENS: + while (ptr < blnum) { + int len = input.PeekBits(3); + if (len < 0) { + return false; + } + input.DropBits(3); + // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); + blLens[BL_ORDER[ptr]] = (byte) len; + ptr++; + } + blTree = new InflaterHuffmanTree(blLens); + blLens = null; + ptr = 0; + mode = LENS; + goto case LENS; // fall through + case LENS: + { + int symbol; + while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) { + /* Normal case: symbol in [0..15] */ + + // System.err.println("litdistLens["+ptr+"]: "+symbol); + litdistLens[ptr++] = lastLen = (byte)symbol; + + if (ptr == num) { + /* Finished */ + return true; + } + } + + /* need more input ? */ + if (symbol < 0) { + return false; + } + + /* otherwise repeat code */ + if (symbol >= 17) { + /* repeat zero */ + // System.err.println("repeating zero"); + lastLen = 0; + } else { + if (ptr == 0) { + throw new SharpZipBaseException(); + } + } + repSymbol = symbol-16; + } + mode = REPS; + goto case REPS; // fall through + case REPS: + { + int bits = repBits[repSymbol]; + int count = input.PeekBits(bits); + if (count < 0) { + return false; + } + input.DropBits(bits); + count += repMin[repSymbol]; + // System.err.println("litdistLens repeated: "+count); + + if (ptr + count > num) { + throw new SharpZipBaseException(); + } + while (count-- > 0) { + litdistLens[ptr++] = lastLen; + } + + if (ptr == num) { + /* Finished */ + return true; + } + } + mode = LENS; + goto decode_loop; + } + } + } + + public InflaterHuffmanTree BuildLitLenTree() + { + byte[] litlenLens = new byte[lnum]; + Array.Copy(litdistLens, 0, litlenLens, 0, lnum); + return new InflaterHuffmanTree(litlenLens); + } + + public InflaterHuffmanTree BuildDistTree() + { + byte[] distLens = new byte[dnum]; + Array.Copy(litdistLens, lnum, distLens, 0, dnum); + return new InflaterHuffmanTree(distLens); + } + + #region Instance Fields + byte[] blLens; + byte[] litdistLens; + + InflaterHuffmanTree blTree; + + /// + /// The current decode mode + /// + int mode; + int lnum, dnum, blnum, num; + int repSymbol; + byte lastLen; + int ptr; + #endregion + + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/InflaterHuffmanTree.cs b/PCRobot/Utils/ZIP/Zip/Compression/InflaterHuffmanTree.cs new file mode 100644 index 0000000..2f61118 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/InflaterHuffmanTree.cs @@ -0,0 +1,232 @@ +// InflaterHuffmanTree.cs +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// Huffman tree used for inflation + /// + public class InflaterHuffmanTree + { + #region Constants + const int MAX_BITLEN = 15; + #endregion + + #region Instance Fields + short[] tree; + #endregion + + /// + /// Literal length tree + /// + public static InflaterHuffmanTree defLitLenTree; + + /// + /// Distance tree + /// + public static InflaterHuffmanTree defDistTree; + + static InflaterHuffmanTree() + { + try { + byte[] codeLengths = new byte[288]; + int i = 0; + while (i < 144) { + codeLengths[i++] = 8; + } + while (i < 256) { + codeLengths[i++] = 9; + } + while (i < 280) { + codeLengths[i++] = 7; + } + while (i < 288) { + codeLengths[i++] = 8; + } + defLitLenTree = new InflaterHuffmanTree(codeLengths); + + codeLengths = new byte[32]; + i = 0; + while (i < 32) { + codeLengths[i++] = 5; + } + defDistTree = new InflaterHuffmanTree(codeLengths); + } catch (Exception) { + throw new SharpZipBaseException("InflaterHuffmanTree: static tree length illegal"); + } + } + + #region Constructors + /// + /// Constructs a Huffman tree from the array of code lengths. + /// + /// + /// the array of code lengths + /// + public InflaterHuffmanTree(byte[] codeLengths) + { + BuildTree(codeLengths); + } + #endregion + + void BuildTree(byte[] codeLengths) + { + int[] blCount = new int[MAX_BITLEN + 1]; + int[] nextCode = new int[MAX_BITLEN + 1]; + + for (int i = 0; i < codeLengths.Length; i++) { + int bits = codeLengths[i]; + if (bits > 0) { + blCount[bits]++; + } + } + + int code = 0; + int treeSize = 512; + for (int bits = 1; bits <= MAX_BITLEN; bits++) { + nextCode[bits] = code; + code += blCount[bits] << (16 - bits); + if (bits >= 10) { + /* We need an extra table for bit lengths >= 10. */ + int start = nextCode[bits] & 0x1ff80; + int end = code & 0x1ff80; + treeSize += (end - start) >> (16 - bits); + } + } + +/* -jr comment this out! doesnt work for dynamic trees and pkzip 2.04g + if (code != 65536) + { + throw new SharpZipBaseException("Code lengths don't add up properly."); + } +*/ + /* Now create and fill the extra tables from longest to shortest + * bit len. This way the sub trees will be aligned. + */ + tree = new short[treeSize]; + int treePtr = 512; + for (int bits = MAX_BITLEN; bits >= 10; bits--) { + int end = code & 0x1ff80; + code -= blCount[bits] << (16 - bits); + int start = code & 0x1ff80; + for (int i = start; i < end; i += 1 << 7) { + tree[DeflaterHuffman.BitReverse(i)] = (short) ((-treePtr << 4) | bits); + treePtr += 1 << (bits-9); + } + } + + for (int i = 0; i < codeLengths.Length; i++) { + int bits = codeLengths[i]; + if (bits == 0) { + continue; + } + code = nextCode[bits]; + int revcode = DeflaterHuffman.BitReverse(code); + if (bits <= 9) { + do { + tree[revcode] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } while (revcode < 512); + } else { + int subTree = tree[revcode & 511]; + int treeLen = 1 << (subTree & 15); + subTree = -(subTree >> 4); + do { + tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } while (revcode < treeLen); + } + nextCode[bits] = code + (1 << (16 - bits)); + } + + } + + /// + /// Reads the next symbol from input. The symbol is encoded using the + /// huffman tree. + /// + /// + /// input the input source. + /// + /// + /// the next symbol, or -1 if not enough input is available. + /// + public int GetSymbol(StreamManipulator input) + { + int lookahead, symbol; + if ((lookahead = input.PeekBits(9)) >= 0) { + if ((symbol = tree[lookahead]) >= 0) { + input.DropBits(symbol & 15); + return symbol >> 4; + } + int subtree = -(symbol >> 4); + int bitlen = symbol & 15; + if ((lookahead = input.PeekBits(bitlen)) >= 0) { + symbol = tree[subtree | (lookahead >> 9)]; + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + int bits = input.AvailableBits; + lookahead = input.PeekBits(bits); + symbol = tree[subtree | (lookahead >> 9)]; + if ((symbol & 15) <= bits) { + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + return -1; + } + } + } else { + int bits = input.AvailableBits; + lookahead = input.PeekBits(bits); + symbol = tree[lookahead]; + if (symbol >= 0 && (symbol & 15) <= bits) { + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + return -1; + } + } + } + } +} + diff --git a/PCRobot/Utils/ZIP/Zip/Compression/PendingBuffer.cs b/PCRobot/Utils/ZIP/Zip/Compression/PendingBuffer.cs new file mode 100644 index 0000000..d205845 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/PendingBuffer.cs @@ -0,0 +1,295 @@ +// PendingBuffer.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class is general purpose class for writing data to a buffer. + /// + /// It allows you to write bits as well as bytes + /// Based on DeflaterPending.java + /// + /// author of the original java version : Jochen Hoenicke + /// + public class PendingBuffer + { + #region Instance Fields + /// + /// Internal work buffer + /// + byte[] buffer_; + + int start; + int end; + + uint bits; + int bitCount; + #endregion + + #region Constructors + /// + /// construct instance using default buffer size of 4096 + /// + public PendingBuffer() : this( 4096 ) + { + } + + /// + /// construct instance using specified buffer size + /// + /// + /// size to use for internal buffer + /// + public PendingBuffer(int bufferSize) + { + buffer_ = new byte[bufferSize]; + } + + #endregion + + /// + /// Clear internal state/buffers + /// + public void Reset() + { + start = end = bitCount = 0; + } + + /// + /// Write a byte to buffer + /// + /// + /// The value to write + /// + public void WriteByte(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + } + + /// + /// Write a short value to buffer LSB first + /// + /// + /// The value to write. + /// + public void WriteShort(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + buffer_[end++] = unchecked((byte) (value >> 8)); + } + + /// + /// write an integer LSB first + /// + /// The value to write. + public void WriteInt(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + buffer_[end++] = unchecked((byte) (value >> 8)); + buffer_[end++] = unchecked((byte) (value >> 16)); + buffer_[end++] = unchecked((byte) (value >> 24)); + } + + /// + /// Write a block of data to buffer + /// + /// data to write + /// offset of first byte to write + /// number of bytes to write + public void WriteBlock(byte[] block, int offset, int length) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + System.Array.Copy(block, offset, buffer_, end, length); + end += length; + } + + /// + /// The number of bits written to the buffer + /// + public int BitCount { + get { + return bitCount; + } + } + + /// + /// Align internal buffer on a byte boundary + /// + public void AlignToByte() + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + if (bitCount > 0) + { + buffer_[end++] = unchecked((byte) bits); + if (bitCount > 8) { + buffer_[end++] = unchecked((byte) (bits >> 8)); + } + } + bits = 0; + bitCount = 0; + } + + /// + /// Write bits to internal buffer + /// + /// source of bits + /// number of bits to write + public void WriteBits(int b, int count) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("writeBits("+b+","+count+")"); + // } +#endif + bits |= (uint)(b << bitCount); + bitCount += count; + if (bitCount >= 16) { + buffer_[end++] = unchecked((byte) bits); + buffer_[end++] = unchecked((byte) (bits >> 8)); + bits >>= 16; + bitCount -= 16; + } + } + + /// + /// Write a short value to internal buffer most significant byte first + /// + /// value to write + public void WriteShortMSB(int s) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) (s >> 8)); + buffer_[end++] = unchecked((byte) s); + } + + /// + /// Indicates if buffer has been flushed + /// + public bool IsFlushed { + get { + return end == 0; + } + } + + /// + /// Flushes the pending buffer into the given output array. If the + /// output array is to small, only a partial flush is done. + /// + /// The output array. + /// The offset into output array. + /// The maximum number of bytes to store. + /// The number of bytes flushed. + public int Flush(byte[] output, int offset, int length) + { + if (bitCount >= 8) { + buffer_[end++] = unchecked((byte) bits); + bits >>= 8; + bitCount -= 8; + } + + if (length > end - start) { + length = end - start; + System.Array.Copy(buffer_, start, output, offset, length); + start = 0; + end = 0; + } else { + System.Array.Copy(buffer_, start, output, offset, length); + start += length; + } + return length; + } + + /// + /// Convert internal buffer to byte array. + /// Buffer is empty on completion + /// + /// + /// The internal buffer contents converted to a byte array. + /// + public byte[] ToByteArray() + { + byte[] result = new byte[end - start]; + System.Array.Copy(buffer_, start, result, 0, result.Length); + start = 0; + end = 0; + return result; + } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs b/PCRobot/Utils/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs new file mode 100644 index 0000000..3e9fea9 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -0,0 +1,603 @@ +// DeflaterOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support + +using System; +using System.IO; + +#if !NETCF_1_0 +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Encryption; +using ICSharpCode.SharpZipLib.Zip1; +#endif + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + /// + /// A special stream deflating or compressing the bytes that are + /// written to it. It uses a Deflater to perform actual deflating.
+ /// Authors of the original java version : Tom Tromey, Jochen Hoenicke + ///
+ public class DeflaterOutputStream : Stream + { + #region Constructors + /// + /// Creates a new DeflaterOutputStream with a default Deflater and default buffer size. + /// + /// + /// the output stream where deflated output should be written. + /// + public DeflaterOutputStream(Stream baseOutputStream) + : this(baseOutputStream, new Deflater(), 512) + { + } + + /// + /// Creates a new DeflaterOutputStream with the given Deflater and + /// default buffer size. + /// + /// + /// the output stream where deflated output should be written. + /// + /// + /// the underlying deflater. + /// + public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater) + : this(baseOutputStream, deflater, 512) + { + } + + /// + /// Creates a new DeflaterOutputStream with the given Deflater and + /// buffer size. + /// + /// + /// The output stream where deflated output is written. + /// + /// + /// The underlying deflater to use + /// + /// + /// The buffer size in bytes to use when deflating (minimum value 512) + /// + /// + /// bufsize is less than or equal to zero. + /// + /// + /// baseOutputStream does not support writing + /// + /// + /// deflater instance is null + /// + public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int bufferSize) + { + if ( baseOutputStream == null ) { + throw new ArgumentNullException("baseOutputStream"); + } + + if (baseOutputStream.CanWrite == false) { + throw new ArgumentException("Must support writing", "baseOutputStream"); + } + + if (deflater == null) { + throw new ArgumentNullException("deflater"); + } + + if (bufferSize < 512) { + throw new ArgumentOutOfRangeException("bufferSize"); + } + + baseOutputStream_ = baseOutputStream; + buffer_ = new byte[bufferSize]; + deflater_ = deflater; + } + #endregion + + #region Public API + /// + /// Finishes the stream by calling finish() on the deflater. + /// + /// + /// Not all input is deflated + /// + public virtual void Finish() + { + deflater_.Finish(); + while (!deflater_.IsFinished) { + int len = deflater_.Deflate(buffer_, 0, buffer_.Length); + if (len <= 0) { + break; + } + +#if NETCF_1_0 + if ( keys != null ) { +#else + if (cryptoTransform_ != null) { +#endif + EncryptBlock(buffer_, 0, len); + } + + baseOutputStream_.Write(buffer_, 0, len); + } + + if (!deflater_.IsFinished) { + throw new SharpZipBaseException("Can't deflate all input?"); + } + + baseOutputStream_.Flush(); + +#if NETCF_1_0 + if ( keys != null ) { + keys = null; + } +#else + if (cryptoTransform_ != null) { +#if !NET_1_1 && !NETCF_2_0 + if (cryptoTransform_ is ZipAESTransform) { + AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode(); + } +#endif + cryptoTransform_.Dispose(); + cryptoTransform_ = null; + } +#endif + } + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner_; } + set { isStreamOwner_ = value; } + } + + /// + /// Allows client to determine if an entry can be patched after its added + /// + public bool CanPatchEntries { + get { + return baseOutputStream_.CanSeek; + } + } + + #endregion + + #region Encryption + + string password; + +#if NETCF_1_0 + uint[] keys; +#else + ICryptoTransform cryptoTransform_; + + /// + /// Returns the 10 byte AUTH CODE to be appended immediately following the AES data stream. + /// + protected byte[] AESAuthCode; +#endif + + /// + /// Get/set the password used for encryption. + /// + /// When set to null or if the password is empty no encryption is performed + public string Password { + get { + return password; + } + set { + if ( (value != null) && (value.Length == 0) ) { + password = null; + } else { + password = value; + } + } + } + + /// + /// Encrypt a block of data + /// + /// + /// Data to encrypt. NOTE the original contents of the buffer are lost + /// + /// + /// Offset of first byte in buffer to encrypt + /// + /// + /// Number of bytes in buffer to encrypt + /// + protected void EncryptBlock(byte[] buffer, int offset, int length) + { +#if NETCF_1_0 + for (int i = offset; i < offset + length; ++i) { + byte oldbyte = buffer[i]; + buffer[i] ^= EncryptByte(); + UpdateKeys(oldbyte); + } +#else + cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0); +#endif + } + + /// + /// Initializes encryption keys based on given . + /// + /// The password. + protected void InitializePassword(string password) + { +#if NETCF_1_0 + keys = new uint[] { + 0x12345678, + 0x23456789, + 0x34567890 + }; + + byte[] rawPassword = ZipConstants.ConvertToArray(password); + + for (int i = 0; i < rawPassword.Length; ++i) { + UpdateKeys((byte)rawPassword[i]); + } + +#else + PkzipClassicManaged pkManaged = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password)); + cryptoTransform_ = pkManaged.CreateEncryptor(key, null); +#endif + } + +#if !NET_1_1 && !NETCF_2_0 + /// + /// Initializes encryption keys based on given password. + /// + protected void InitializeAESPassword(ZipEntry entry, string rawPassword, + out byte[] salt, out byte[] pwdVerifier) { + salt = new byte[entry.AESSaltLen]; + // Salt needs to be cryptographically random, and unique per file + if (_aesRnd == null) + _aesRnd = new RNGCryptoServiceProvider(); + _aesRnd.GetBytes(salt); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true); + pwdVerifier = ((ZipAESTransform)cryptoTransform_).PwdVerifier; + } +#endif + +#if NETCF_1_0 + + /// + /// Encrypt a single byte + /// + /// + /// The encrypted value + /// + protected byte EncryptByte() + { + uint temp = ((keys[2] & 0xFFFF) | 2); + return (byte)((temp * (temp ^ 1)) >> 8); + } + + /// + /// Update encryption keys + /// + protected void UpdateKeys(byte ch) + { + keys[0] = Crc32.ComputeCrc32(keys[0], ch); + keys[1] = keys[1] + (byte)keys[0]; + keys[1] = keys[1] * 134775813 + 1; + keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24)); + } +#endif + + #endregion + + #region Deflation Support + /// + /// Deflates everything in the input buffers. This will call + /// def.deflate() until all bytes from the input buffers + /// are processed. + /// + protected void Deflate() + { + while (!deflater_.IsNeedingInput) + { + int deflateCount = deflater_.Deflate(buffer_, 0, buffer_.Length); + + if (deflateCount <= 0) { + break; + } +#if NETCF_1_0 + if (keys != null) +#else + if (cryptoTransform_ != null) +#endif + { + EncryptBlock(buffer_, 0, deflateCount); + } + + baseOutputStream_.Write(buffer_, 0, deflateCount); + } + + if (!deflater_.IsNeedingInput) { + throw new SharpZipBaseException("DeflaterOutputStream can't deflate all input?"); + } + } + #endregion + + #region Stream Overrides + /// + /// Gets value indicating stream can be read from + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Gets a value indicating if seeking is supported for this stream + /// This property always returns false + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Get value indicating if this stream supports writing + /// + public override bool CanWrite { + get { + return baseOutputStream_.CanWrite; + } + } + + /// + /// Get current length of stream + /// + public override long Length { + get { + return baseOutputStream_.Length; + } + } + + /// + /// Gets the current position within the stream. + /// + /// Any attempt to set position + public override long Position { + get { + return baseOutputStream_.Position; + } + set { + throw new NotSupportedException("Position property not supported"); + } + } + + /// + /// Sets the current position of this stream to the given value. Not supported by this class! + /// + /// The offset relative to the to seek. + /// The to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("DeflaterOutputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. Not supported by this class! + /// + /// The new stream length. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("DeflaterOutputStream SetLength not supported"); + } + + /// + /// Read a byte from stream advancing position by one + /// + /// The byte read cast to an int. THe value is -1 if at the end of the stream. + /// Any access + public override int ReadByte() + { + throw new NotSupportedException("DeflaterOutputStream ReadByte not supported"); + } + + /// + /// Read a block of bytes from stream + /// + /// The buffer to store read data in. + /// The offset to start storing at. + /// The maximum number of bytes to read. + /// The actual number of bytes read. Zero if end of stream is detected. + /// Any access + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("DeflaterOutputStream Read not supported"); + } + + /// + /// Asynchronous reads are not supported a NotSupportedException is always thrown + /// + /// The buffer to read into. + /// The offset to start storing data at. + /// The number of bytes to read + /// The async callback to use. + /// The state to use. + /// Returns an + /// Any access + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("DeflaterOutputStream BeginRead not currently supported"); + } + + /// + /// Asynchronous writes arent supported, a NotSupportedException is always thrown + /// + /// The buffer to write. + /// The offset to begin writing at. + /// The number of bytes to write. + /// The to use. + /// The state object. + /// Returns an IAsyncResult. + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("BeginWrite is not supported"); + } + + /// + /// Flushes the stream by calling Flush on the deflater and then + /// on the underlying stream. This ensures that all bytes are flushed. + /// + public override void Flush() + { + deflater_.Flush(); + Deflate(); + baseOutputStream_.Flush(); + } + + /// + /// Calls and closes the underlying + /// stream when is true. + /// + public override void Close() + { + if ( !isClosed_ ) { + isClosed_ = true; + + try { + Finish(); +#if NETCF_1_0 + keys=null; +#else + if ( cryptoTransform_ != null ) { + GetAuthCodeIfAES(); + cryptoTransform_.Dispose(); + cryptoTransform_ = null; + } +#endif + } + finally { + if( isStreamOwner_ ) { + baseOutputStream_.Close(); + } + } + } + } + + private void GetAuthCodeIfAES() { +#if !NET_1_1 && !NETCF_2_0 + if (cryptoTransform_ is ZipAESTransform) { + AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode(); + } +#endif + } + + /// + /// Writes a single byte to the compressed output stream. + /// + /// + /// The byte value. + /// + public override void WriteByte(byte value) + { + byte[] b = new byte[1]; + b[0] = value; + Write(b, 0, 1); + } + + /// + /// Writes bytes from an array to the compressed stream. + /// + /// + /// The byte array + /// + /// + /// The offset into the byte array where to start. + /// + /// + /// The number of bytes to write. + /// + public override void Write(byte[] buffer, int offset, int count) + { + deflater_.SetInput(buffer, offset, count); + Deflate(); + } + #endregion + + #region Instance Fields + /// + /// This buffer is used temporarily to retrieve the bytes from the + /// deflater and write them to the underlying output stream. + /// + byte[] buffer_; + + /// + /// The deflater which is used to deflate the stream. + /// + protected Deflater deflater_; + + /// + /// Base stream the deflater depends on. + /// + protected Stream baseOutputStream_; + + bool isClosed_; + + bool isStreamOwner_ = true; + #endregion + + #region Static Fields + +#if !NET_1_1 && !NETCF_2_0 + // Static to help ensure that multiple files within a zip will get different random salt + private static RNGCryptoServiceProvider _aesRnd; +#endif + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/Streams/InflaterInputStream.cs b/PCRobot/Utils/ZIP/Zip/Compression/Streams/InflaterInputStream.cs new file mode 100644 index 0000000..6699444 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/Streams/InflaterInputStream.cs @@ -0,0 +1,732 @@ +// InflaterInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 11-08-2009 GeoffHart T9121 Added Multi-member gzip support + +using System; +using System.IO; + +#if !NETCF_1_0 +using System.Security.Cryptography; +#endif + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// An input buffer customised for use by + /// + /// + /// The buffer supports decryption of incoming data. + /// + public class InflaterInputBuffer + { + #region Constructors + /// + /// Initialise a new instance of with a default buffer size + /// + /// The stream to buffer. + public InflaterInputBuffer(Stream stream) : this(stream , 4096) + { + } + + /// + /// Initialise a new instance of + /// + /// The stream to buffer. + /// The size to use for the buffer + /// A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB. + public InflaterInputBuffer(Stream stream, int bufferSize) + { + inputStream = stream; + if ( bufferSize < 1024 ) { + bufferSize = 1024; + } + rawData = new byte[bufferSize]; + clearText = rawData; + } + #endregion + + /// + /// Get the length of bytes bytes in the + /// + public int RawLength + { + get { + return rawLength; + } + } + + /// + /// Get the contents of the raw data buffer. + /// + /// This may contain encrypted data. + public byte[] RawData + { + get { + return rawData; + } + } + + /// + /// Get the number of useable bytes in + /// + public int ClearTextLength + { + get { + return clearTextLength; + } + } + + /// + /// Get the contents of the clear text buffer. + /// + public byte[] ClearText + { + get { + return clearText; + } + } + + /// + /// Get/set the number of bytes available + /// + public int Available + { + get { return available; } + set { available = value; } + } + + /// + /// Call passing the current clear text buffer contents. + /// + /// The inflater to set input for. + public void SetInflaterInput(Inflater inflater) + { + if ( available > 0 ) { + inflater.SetInput(clearText, clearTextLength - available, available); + available = 0; + } + } + + /// + /// Fill the buffer from the underlying input stream. + /// + public void Fill() + { + rawLength = 0; + int toRead = rawData.Length; + + while (toRead > 0) { + int count = inputStream.Read(rawData, rawLength, toRead); + if ( count <= 0 ) { + break; + } + rawLength += count; + toRead -= count; + } + +#if !NETCF_1_0 + if ( cryptoTransform != null ) { + clearTextLength = cryptoTransform.TransformBlock(rawData, 0, rawLength, clearText, 0); + } + else +#endif + { + clearTextLength = rawLength; + } + + available = clearTextLength; + } + + /// + /// Read a buffer directly from the input stream + /// + /// The buffer to fill + /// Returns the number of bytes read. + public int ReadRawBuffer(byte[] buffer) + { + return ReadRawBuffer(buffer, 0, buffer.Length); + } + + /// + /// Read a buffer directly from the input stream + /// + /// The buffer to read into + /// The offset to start reading data into. + /// The number of bytes to read. + /// Returns the number of bytes read. + public int ReadRawBuffer(byte[] outBuffer, int offset, int length) + { + if ( length < 0 ) { + throw new ArgumentOutOfRangeException("length"); + } + + int currentOffset = offset; + int currentLength = length; + + while ( currentLength > 0 ) { + if ( available <= 0 ) { + Fill(); + if (available <= 0) { + return 0; + } + } + int toCopy = Math.Min(currentLength, available); + System.Array.Copy(rawData, rawLength - (int)available, outBuffer, currentOffset, toCopy); + currentOffset += toCopy; + currentLength -= toCopy; + available -= toCopy; + } + return length; + } + + /// + /// Read clear text data from the input stream. + /// + /// The buffer to add data to. + /// The offset to start adding data at. + /// The number of bytes to read. + /// Returns the number of bytes actually read. + public int ReadClearTextBuffer(byte[] outBuffer, int offset, int length) + { + if ( length < 0 ) { + throw new ArgumentOutOfRangeException("length"); + } + + int currentOffset = offset; + int currentLength = length; + + while ( currentLength > 0 ) { + if ( available <= 0 ) { + Fill(); + if (available <= 0) { + return 0; + } + } + + int toCopy = Math.Min(currentLength, available); + Array.Copy(clearText, clearTextLength - (int)available, outBuffer, currentOffset, toCopy); + currentOffset += toCopy; + currentLength -= toCopy; + available -= toCopy; + } + return length; + } + + /// + /// Read a from the input stream. + /// + /// Returns the byte read. + public int ReadLeByte() + { + if (available <= 0) { + Fill(); + if (available <= 0) { + throw new ZipException("EOF in header"); + } + } + byte result = rawData[rawLength - available]; + available -= 1; + return result; + } + + /// + /// Read an in little endian byte order. + /// + /// The short value read case to an int. + public int ReadLeShort() + { + return ReadLeByte() | (ReadLeByte() << 8); + } + + /// + /// Read an in little endian byte order. + /// + /// The int value read. + public int ReadLeInt() + { + return ReadLeShort() | (ReadLeShort() << 16); + } + + /// + /// Read a in little endian byte order. + /// + /// The long value read. + public long ReadLeLong() + { + return (uint)ReadLeInt() | ((long)ReadLeInt() << 32); + } + +#if !NETCF_1_0 + /// + /// Get/set the to apply to any data. + /// + /// Set this value to null to have no transform applied. + public ICryptoTransform CryptoTransform + { + set { + cryptoTransform = value; + if ( cryptoTransform != null ) { + if ( rawData == clearText ) { + if ( internalClearText == null ) { + internalClearText = new byte[rawData.Length]; + } + clearText = internalClearText; + } + clearTextLength = rawLength; + if ( available > 0 ) { + cryptoTransform.TransformBlock(rawData, rawLength - available, available, clearText, rawLength - available); + } + } else { + clearText = rawData; + clearTextLength = rawLength; + } + } + } +#endif + + #region Instance Fields + int rawLength; + byte[] rawData; + + int clearTextLength; + byte[] clearText; +#if !NETCF_1_0 + byte[] internalClearText; +#endif + + int available; + +#if !NETCF_1_0 + ICryptoTransform cryptoTransform; +#endif + Stream inputStream; + #endregion + } + + /// + /// This filter stream is used to decompress data compressed using the "deflate" + /// format. The "deflate" format is described in RFC 1951. + /// + /// This stream may form the basis for other decompression filters, such + /// as the GZipInputStream. + /// + /// Author of the original java version : John Leuner. + /// + public class InflaterInputStream : Stream + { + #region Constructors + /// + /// Create an InflaterInputStream with the default decompressor + /// and a default buffer size of 4KB. + /// + /// + /// The InputStream to read bytes from + /// + public InflaterInputStream(Stream baseInputStream) + : this(baseInputStream, new Inflater(), 4096) + { + } + + /// + /// Create an InflaterInputStream with the specified decompressor + /// and a default buffer size of 4KB. + /// + /// + /// The source of input data + /// + /// + /// The decompressor used to decompress data read from baseInputStream + /// + public InflaterInputStream(Stream baseInputStream, Inflater inf) + : this(baseInputStream, inf, 4096) + { + } + + /// + /// Create an InflaterInputStream with the specified decompressor + /// and the specified buffer size. + /// + /// + /// The InputStream to read bytes from + /// + /// + /// The decompressor to use + /// + /// + /// Size of the buffer to use + /// + public InflaterInputStream(Stream baseInputStream, Inflater inflater, int bufferSize) + { + if (baseInputStream == null) { + throw new ArgumentNullException("baseInputStream"); + } + + if (inflater == null) { + throw new ArgumentNullException("inflater"); + } + + if (bufferSize <= 0) { + throw new ArgumentOutOfRangeException("bufferSize"); + } + + this.baseInputStream = baseInputStream; + this.inf = inflater; + + inputBuffer = new InflaterInputBuffer(baseInputStream, bufferSize); + } + + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + /// + /// The default value is true. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Skip specified number of bytes of uncompressed data + /// + /// + /// Number of bytes to skip + /// + /// + /// The number of bytes skipped, zero if the end of + /// stream has been reached + /// + /// + /// The number of bytes to skip is less than or equal to zero. + /// + public long Skip(long count) + { + if (count <= 0) { + throw new ArgumentOutOfRangeException("count"); + } + + // v0.80 Skip by seeking if underlying stream supports it... + if (baseInputStream.CanSeek) { + baseInputStream.Seek(count, SeekOrigin.Current); + return count; + } + else { + int length = 2048; + if (count < length) { + length = (int) count; + } + + byte[] tmp = new byte[length]; + int readCount = 1; + long toSkip = count; + + while ((toSkip > 0) && (readCount > 0) ) { + if (toSkip < length) { + length = (int)toSkip; + } + + readCount = baseInputStream.Read(tmp, 0, length); + toSkip -= readCount; + } + + return count - toSkip; + } + } + + /// + /// Clear any cryptographic state. + /// + protected void StopDecrypting() + { +#if !NETCF_1_0 + inputBuffer.CryptoTransform = null; +#endif + } + + /// + /// Returns 0 once the end of the stream (EOF) has been reached. + /// Otherwise returns 1. + /// + public virtual int Available + { + get { + return inf.IsFinished ? 0 : 1; + } + } + + /// + /// Fills the buffer with more data to decompress. + /// + /// + /// Stream ends early + /// + protected void Fill() + { + // Protect against redundant calls + if (inputBuffer.Available <= 0) { + inputBuffer.Fill(); + if (inputBuffer.Available <= 0) { + throw new SharpZipBaseException("Unexpected EOF"); + } + } + inputBuffer.SetInflaterInput(inf); + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return baseInputStream.CanRead; + } + } + + /// + /// Gets a value of false indicating seeking is not supported for this stream. + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value of false indicating that this stream is not writeable. + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// A value representing the length of the stream in bytes. + /// + public override long Length { + get { + return inputBuffer.RawLength; + } + } + + /// + /// The current position within the stream. + /// Throws a NotSupportedException when attempting to set the position + /// + /// Attempting to set the position + public override long Position { + get { + return baseInputStream.Position; + } + set { + throw new NotSupportedException("InflaterInputStream Position not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + baseInputStream.Flush(); + } + + /// + /// Sets the position within the current stream + /// Always throws a NotSupportedException + /// + /// The relative offset to seek to. + /// The defining where to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Seek not supported"); + } + + /// + /// Set the length of the current stream + /// Always throws a NotSupportedException + /// + /// The new length value for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("InflaterInputStream SetLength not supported"); + } + + /// + /// Writes a sequence of bytes to stream and advances the current position + /// This method always throws a NotSupportedException + /// + /// Thew buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("InflaterInputStream Write not supported"); + } + + /// + /// Writes one byte to the current stream and advances the current position + /// Always throws a NotSupportedException + /// + /// The byte to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("InflaterInputStream WriteByte not supported"); + } + + /// + /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. + /// + /// The buffer to write data from + /// Offset of first byte to write + /// The maximum number of bytes to write + /// The method to be called when the asynchronous write operation is completed + /// A user-provided object that distinguishes this particular asynchronous write request from other requests + /// An IAsyncResult that references the asynchronous write + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); + } + + /// + /// Closes the input stream. When + /// is true the underlying stream is also closed. + /// + public override void Close() + { + if ( !isClosed ) { + isClosed = true; + if ( isStreamOwner ) { + baseInputStream.Close(); + } + } + } + + /// + /// Reads decompressed data into the provided buffer byte array + /// + /// + /// The array to read and decompress data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of bytes to decompress + /// + /// The number of bytes read. Zero signals the end of stream + /// + /// Inflater needs a dictionary + /// + public override int Read(byte[] buffer, int offset, int count) + { + if (inf.IsNeedingDictionary) + { + throw new SharpZipBaseException("Need a dictionary"); + } + + int remainingBytes = count; + while (true) { + int bytesRead = inf.Inflate(buffer, offset, remainingBytes); + offset += bytesRead; + remainingBytes -= bytesRead; + + if (remainingBytes == 0 || inf.IsFinished) { + break; + } + + if ( inf.IsNeedingInput ) { + Fill(); + } + else if ( bytesRead == 0 ) { + throw new ZipException("Dont know what to do"); + } + } + return count - remainingBytes; + } + #endregion + + #region Instance Fields + /// + /// Decompressor for this stream + /// + protected Inflater inf; + + /// + /// Input buffer for this stream. + /// + protected InflaterInputBuffer inputBuffer; + + /// + /// Base stream the inflater reads from. + /// + private Stream baseInputStream; + + /// + /// The compressed size + /// + protected long csize; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + /// + /// Flag indicating wether this instance is designated the stream owner. + /// When closing if this flag is true the underlying stream is closed. + /// + bool isStreamOwner = true; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/Streams/OutputWindow.cs b/PCRobot/Utils/ZIP/Zip/Compression/Streams/OutputWindow.cs new file mode 100644 index 0000000..be828e2 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/Streams/OutputWindow.cs @@ -0,0 +1,235 @@ +// OutputWindow.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// Contains the output from the Inflation process. + /// We need to have a window so that we can refer backwards into the output stream + /// to repeat stuff.
+ /// Author of the original java version : John Leuner + ///
+ public class OutputWindow + { + #region Constants + const int WindowSize = 1 << 15; + const int WindowMask = WindowSize - 1; + #endregion + + #region Instance Fields + byte[] window = new byte[WindowSize]; //The window is 2^15 bytes + int windowEnd; + int windowFilled; + #endregion + + /// + /// Write a byte to this output window + /// + /// value to write + /// + /// if window is full + /// + public void Write(int value) + { + if (windowFilled++ == WindowSize) { + throw new InvalidOperationException("Window full"); + } + window[windowEnd++] = (byte) value; + windowEnd &= WindowMask; + } + + + private void SlowRepeat(int repStart, int length, int distance) + { + while (length-- > 0) { + window[windowEnd++] = window[repStart++]; + windowEnd &= WindowMask; + repStart &= WindowMask; + } + } + + /// + /// Append a byte pattern already in the window itself + /// + /// length of pattern to copy + /// distance from end of window pattern occurs + /// + /// If the repeated data overflows the window + /// + public void Repeat(int length, int distance) + { + if ((windowFilled += length) > WindowSize) { + throw new InvalidOperationException("Window full"); + } + + int repStart = (windowEnd - distance) & WindowMask; + int border = WindowSize - length; + if ( (repStart <= border) && (windowEnd < border) ) { + if (length <= distance) { + System.Array.Copy(window, repStart, window, windowEnd, length); + windowEnd += length; + } else { + // We have to copy manually, since the repeat pattern overlaps. + while (length-- > 0) { + window[windowEnd++] = window[repStart++]; + } + } + } else { + SlowRepeat(repStart, length, distance); + } + } + + /// + /// Copy from input manipulator to internal window + /// + /// source of data + /// length of data to copy + /// the number of bytes copied + public int CopyStored(StreamManipulator input, int length) + { + length = Math.Min(Math.Min(length, WindowSize - windowFilled), input.AvailableBytes); + int copied; + + int tailLen = WindowSize - windowEnd; + if (length > tailLen) { + copied = input.CopyBytes(window, windowEnd, tailLen); + if (copied == tailLen) { + copied += input.CopyBytes(window, 0, length - tailLen); + } + } else { + copied = input.CopyBytes(window, windowEnd, length); + } + + windowEnd = (windowEnd + copied) & WindowMask; + windowFilled += copied; + return copied; + } + + /// + /// Copy dictionary to window + /// + /// source dictionary + /// offset of start in source dictionary + /// length of dictionary + /// + /// If window isnt empty + /// + public void CopyDict(byte[] dictionary, int offset, int length) + { + if ( dictionary == null ) { + throw new ArgumentNullException("dictionary"); + } + + if (windowFilled > 0) { + throw new InvalidOperationException(); + } + + if (length > WindowSize) { + offset += length - WindowSize; + length = WindowSize; + } + System.Array.Copy(dictionary, offset, window, 0, length); + windowEnd = length & WindowMask; + } + + /// + /// Get remaining unfilled space in window + /// + /// Number of bytes left in window + public int GetFreeSpace() + { + return WindowSize - windowFilled; + } + + /// + /// Get bytes available for output in window + /// + /// Number of bytes filled + public int GetAvailable() + { + return windowFilled; + } + + /// + /// Copy contents of window to output + /// + /// buffer to copy to + /// offset to start at + /// number of bytes to count + /// The number of bytes copied + /// + /// If a window underflow occurs + /// + public int CopyOutput(byte[] output, int offset, int len) + { + int copyEnd = windowEnd; + if (len > windowFilled) { + len = windowFilled; + } else { + copyEnd = (windowEnd - windowFilled + len) & WindowMask; + } + + int copied = len; + int tailLen = len - copyEnd; + + if (tailLen > 0) { + System.Array.Copy(window, WindowSize - tailLen, output, offset, tailLen); + offset += tailLen; + len = copyEnd; + } + System.Array.Copy(window, copyEnd - len, output, offset, len); + windowFilled -= copied; + if (windowFilled < 0) { + throw new InvalidOperationException(); + } + return copied; + } + + /// + /// Reset by clearing window so GetAvailable returns 0 + /// + public void Reset() + { + windowFilled = windowEnd = 0; + } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/Compression/Streams/StreamManipulator.cs b/PCRobot/Utils/ZIP/Zip/Compression/Streams/StreamManipulator.cs new file mode 100644 index 0000000..ac57e1e --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/Compression/Streams/StreamManipulator.cs @@ -0,0 +1,297 @@ +// StreamManipulator.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// This class allows us to retrieve a specified number of bits from + /// the input buffer, as well as copy big byte blocks. + /// + /// It uses an int buffer to store up to 31 bits for direct + /// manipulation. This guarantees that we can get at least 16 bits, + /// but we only need at most 15, so this is all safe. + /// + /// There are some optimizations in this class, for example, you must + /// never peek more than 8 bits more than needed, and you must first + /// peek bits before you may drop them. This is not a general purpose + /// class but optimized for the behaviour of the Inflater. + /// + /// authors of the original java version : John Leuner, Jochen Hoenicke + /// + public class StreamManipulator + { + #region Constructors + /// + /// Constructs a default StreamManipulator with all buffers empty + /// + public StreamManipulator() + { + } + #endregion + + /// + /// Get the next sequence of bits but don't increase input pointer. bitCount must be + /// less or equal 16 and if this call succeeds, you must drop + /// at least n - 8 bits in the next call. + /// + /// The number of bits to peek. + /// + /// the value of the bits, or -1 if not enough bits available. */ + /// + public int PeekBits(int bitCount) + { + if (bitsInBuffer_ < bitCount) { + if (windowStart_ == windowEnd_) { + return -1; // ok + } + buffer_ |= (uint)((window_[windowStart_++] & 0xff | + (window_[windowStart_++] & 0xff) << 8) << bitsInBuffer_); + bitsInBuffer_ += 16; + } + return (int)(buffer_ & ((1 << bitCount) - 1)); + } + + /// + /// Drops the next n bits from the input. You should have called PeekBits + /// with a bigger or equal n before, to make sure that enough bits are in + /// the bit buffer. + /// + /// The number of bits to drop. + public void DropBits(int bitCount) + { + buffer_ >>= bitCount; + bitsInBuffer_ -= bitCount; + } + + /// + /// Gets the next n bits and increases input pointer. This is equivalent + /// to followed by , except for correct error handling. + /// + /// The number of bits to retrieve. + /// + /// the value of the bits, or -1 if not enough bits available. + /// + public int GetBits(int bitCount) + { + int bits = PeekBits(bitCount); + if (bits >= 0) { + DropBits(bitCount); + } + return bits; + } + + /// + /// Gets the number of bits available in the bit buffer. This must be + /// only called when a previous PeekBits() returned -1. + /// + /// + /// the number of bits available. + /// + public int AvailableBits { + get { + return bitsInBuffer_; + } + } + + /// + /// Gets the number of bytes available. + /// + /// + /// The number of bytes available. + /// + public int AvailableBytes { + get { + return windowEnd_ - windowStart_ + (bitsInBuffer_ >> 3); + } + } + + /// + /// Skips to the next byte boundary. + /// + public void SkipToByteBoundary() + { + buffer_ >>= (bitsInBuffer_ & 7); + bitsInBuffer_ &= ~7; + } + + /// + /// Returns true when SetInput can be called + /// + public bool IsNeedingInput { + get { + return windowStart_ == windowEnd_; + } + } + + /// + /// Copies bytes from input buffer to output buffer starting + /// at output[offset]. You have to make sure, that the buffer is + /// byte aligned. If not enough bytes are available, copies fewer + /// bytes. + /// + /// + /// The buffer to copy bytes to. + /// + /// + /// The offset in the buffer at which copying starts + /// + /// + /// The length to copy, 0 is allowed. + /// + /// + /// The number of bytes copied, 0 if no bytes were available. + /// + /// + /// Length is less than zero + /// + /// + /// Bit buffer isnt byte aligned + /// + public int CopyBytes(byte[] output, int offset, int length) + { + if (length < 0) { + throw new ArgumentOutOfRangeException("length"); + } + + if ((bitsInBuffer_ & 7) != 0) { + // bits_in_buffer may only be 0 or a multiple of 8 + throw new InvalidOperationException("Bit buffer is not byte aligned!"); + } + + int count = 0; + while ((bitsInBuffer_ > 0) && (length > 0)) { + output[offset++] = (byte) buffer_; + buffer_ >>= 8; + bitsInBuffer_ -= 8; + length--; + count++; + } + + if (length == 0) { + return count; + } + + int avail = windowEnd_ - windowStart_; + if (length > avail) { + length = avail; + } + System.Array.Copy(window_, windowStart_, output, offset, length); + windowStart_ += length; + + if (((windowStart_ - windowEnd_) & 1) != 0) { + // We always want an even number of bytes in input, see peekBits + buffer_ = (uint)(window_[windowStart_++] & 0xff); + bitsInBuffer_ = 8; + } + return count + length; + } + + /// + /// Resets state and empties internal buffers + /// + public void Reset() + { + buffer_ = 0; + windowStart_ = windowEnd_ = bitsInBuffer_ = 0; + } + + /// + /// Add more input for consumption. + /// Only call when IsNeedingInput returns true + /// + /// data to be input + /// offset of first byte of input + /// number of bytes of input to add. + public void SetInput(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if (windowStart_ < windowEnd_) { + throw new InvalidOperationException("Old input was not completely processed"); + } + + int end = offset + count; + + // We want to throw an ArrayIndexOutOfBoundsException early. + // Note the check also handles integer wrap around. + if ((offset > end) || (end > buffer.Length) ) { + throw new ArgumentOutOfRangeException("count"); + } + + if ((count & 1) != 0) { + // We always want an even number of bytes in input, see PeekBits + buffer_ |= (uint)((buffer[offset++] & 0xff) << bitsInBuffer_); + bitsInBuffer_ += 8; + } + + window_ = buffer; + windowStart_ = offset; + windowEnd_ = end; + } + + #region Instance Fields + private byte[] window_; + private int windowStart_; + private int windowEnd_; + + private uint buffer_; + private int bitsInBuffer_; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/FastZip.cs b/PCRobot/Utils/ZIP/Zip/FastZip.cs new file mode 100644 index 0000000..70be02b --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/FastZip.cs @@ -0,0 +1,730 @@ +// FastZip.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// FastZipEvents supports all events applicable to FastZip operations. + /// + public class FastZipEvents + { + /// + /// Delegate to invoke when processing directories. + /// + public ProcessDirectoryHandler ProcessDirectory; + + /// + /// Delegate to invoke when processing files. + /// + public ProcessFileHandler ProcessFile; + + /// + /// Delegate to invoke during processing of files. + /// + public ProgressHandler Progress; + + /// + /// Delegate to invoke when processing for a file has been completed. + /// + public CompletedFileHandler CompletedFile; + + /// + /// Delegate to invoke when processing directory failures. + /// + public DirectoryFailureHandler DirectoryFailure; + + /// + /// Delegate to invoke when processing file failures. + /// + public FileFailureHandler FileFailure; + + /// + /// Raise the directory failure event. + /// + /// The directory causing the failure. + /// The exception for this event. + /// A boolean indicating if execution should continue or not. + public bool OnDirectoryFailure(string directory, Exception e) + { + bool result = false; + DirectoryFailureHandler handler = DirectoryFailure; + + if ( handler != null ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the file failure handler delegate. + /// + /// The file causing the failure. + /// The exception for this failure. + /// A boolean indicating if execution should continue or not. + public bool OnFileFailure(string file, Exception e) + { + FileFailureHandler handler = FileFailure; + bool result = (handler != null); + + if ( result ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(file, e); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the ProcessFile delegate. + /// + /// The file being processed. + /// A boolean indicating if execution should continue or not. + public bool OnProcessFile(string file) + { + bool result = true; + ProcessFileHandler handler = ProcessFile; + + if ( handler != null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the delegate + /// + /// The file whose processing has been completed. + /// A boolean indicating if execution should continue or not. + public bool OnCompletedFile(string file) + { + bool result = true; + CompletedFileHandler handler = CompletedFile; + if ( handler != null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the process directory delegate. + /// + /// The directory being processed. + /// Flag indicating if the directory has matching files as determined by the current filter. + /// A of true if the operation should continue; false otherwise. + public bool OnProcessDirectory(string directory, bool hasMatchingFiles) + { + bool result = true; + ProcessDirectoryHandler handler = ProcessDirectory; + if ( handler != null ) { + DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// The minimum timespan between events. + /// + /// The minimum period of time between events. + /// + /// The default interval is three seconds. + public TimeSpan ProgressInterval + { + get { return progressInterval_; } + set { progressInterval_ = value; } + } + + #region Instance Fields + TimeSpan progressInterval_ = TimeSpan.FromSeconds(3); + #endregion + } + + /// + /// FastZip provides facilities for creating and extracting zip files. + /// + public class FastZip + { + #region Enumerations + /// + /// Defines the desired handling when overwriting files during extraction. + /// + public enum Overwrite + { + /// + /// Prompt the user to confirm overwriting + /// + Prompt, + /// + /// Never overwrite files. + /// + Never, + /// + /// Always overwrite files. + /// + Always + } + #endregion + + #region Constructors + /// + /// Initialise a default instance of . + /// + public FastZip() + { + } + + /// + /// Initialise a new instance of + /// + /// The events to use during operations. + public FastZip(FastZipEvents events) + { + events_ = events; + } + #endregion + + #region Properties + /// + /// Get/set a value indicating wether empty directories should be created. + /// + public bool CreateEmptyDirectories + { + get { return createEmptyDirectories_; } + set { createEmptyDirectories_ = value; } + } + +#if !NETCF_1_0 + /// + /// Get / set the password value. + /// + public string Password + { + get { return password_; } + set { password_ = value; } + } +#endif + + /// + /// Get or set the active when creating Zip files. + /// + /// + public INameTransform NameTransform + { + get { return entryFactory_.NameTransform; } + set { + entryFactory_.NameTransform = value; + } + } + + /// + /// Get or set the active when creating Zip files. + /// + public IEntryFactory EntryFactory + { + get { return entryFactory_; } + set { + if ( value == null ) { + entryFactory_ = new ZipEntryFactory(); + } + else { + entryFactory_ = value; + } + } + } + + /// + /// Gets or sets the setting for Zip64 handling when writing. + /// + /// + /// The default value is dynamic which is not backwards compatible with old + /// programs and can cause problems with XP's built in compression which cant + /// read Zip64 archives. However it does avoid the situation were a large file + /// is added and cannot be completed correctly. + /// NOTE: Setting the size for entries before they are added is the best solution! + /// By default the EntryFactory used by FastZip will set fhe file size. + /// + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + /// + /// Get/set a value indicating wether file dates and times should + /// be restored when extracting files from an archive. + /// + /// The default value is false. + public bool RestoreDateTimeOnExtract + { + get { + return restoreDateTimeOnExtract_; + } + set { + restoreDateTimeOnExtract_ = value; + } + } + + /// + /// Get/set a value indicating wether file attributes should + /// be restored during extract operations + /// + public bool RestoreAttributesOnExtract + { + get { return restoreAttributesOnExtract_; } + set { restoreAttributesOnExtract_ = value; } + } + #endregion + + #region Delegates + /// + /// Delegate called when confirming overwriting of files. + /// + public delegate bool ConfirmOverwriteDelegate(string fileName); + #endregion + + #region CreateZip + /// + /// Create a zip file. + /// + /// The name of the zip file to create. + /// The directory to source files from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + /// The directory filter to apply. + public void CreateZip(string zipFileName, string sourceDirectory, + bool recurse, string fileFilter, string directoryFilter) + { + CreateZip(File.Create(zipFileName), sourceDirectory, recurse, fileFilter, directoryFilter); + } + + /// + /// Create a zip file/archive. + /// + /// The name of the zip file to create. + /// The directory to obtain files and directories from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + public void CreateZip(string zipFileName, string sourceDirectory, bool recurse, string fileFilter) + { + CreateZip(File.Create(zipFileName), sourceDirectory, recurse, fileFilter, null); + } + + /// + /// Create a zip archive sending output to the passed. + /// + /// The stream to write archive data to. + /// The directory to source files from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + /// The directory filter to apply. + /// The is closed after creation. + public void CreateZip(Stream outputStream, string sourceDirectory, bool recurse, string fileFilter, string directoryFilter) + { + NameTransform = new ZipNameTransform(sourceDirectory); + sourceDirectory_ = sourceDirectory; + + using ( outputStream_ = new ZipOutputStream(outputStream) ) { + +#if !NETCF_1_0 + if ( password_ != null ) { + outputStream_.Password = password_; + } +#endif + + outputStream_.UseZip64 = UseZip64; + FileSystemScanner scanner = new FileSystemScanner(fileFilter, directoryFilter); + scanner.ProcessFile += new ProcessFileHandler(ProcessFile); + if ( this.CreateEmptyDirectories ) { + scanner.ProcessDirectory += new ProcessDirectoryHandler(ProcessDirectory); + } + + if (events_ != null) { + if ( events_.FileFailure != null ) { + scanner.FileFailure += events_.FileFailure; + } + + if ( events_.DirectoryFailure != null ) { + scanner.DirectoryFailure += events_.DirectoryFailure; + } + } + + scanner.Scan(sourceDirectory, recurse); + } + } + + #endregion + + #region ExtractZip + /// + /// Extract the contents of a zip file. + /// + /// The zip file to extract from. + /// The directory to save extracted information in. + /// A filter to apply to files. + public void ExtractZip(string zipFileName, string targetDirectory, string fileFilter) + { + ExtractZip(zipFileName, targetDirectory, Overwrite.Always, null, fileFilter, null, restoreDateTimeOnExtract_); + } + + /// + /// Extract the contents of a zip file. + /// + /// The zip file to extract from. + /// The directory to save extracted information in. + /// The style of overwriting to apply. + /// A delegate to invoke when confirming overwriting. + /// A filter to apply to files. + /// A filter to apply to directories. + /// Flag indicating whether to restore the date and time for extracted files. + public void ExtractZip(string zipFileName, string targetDirectory, + Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate, + string fileFilter, string directoryFilter, bool restoreDateTime) + { + Stream inputStream = File.Open(zipFileName, FileMode.Open, FileAccess.Read, FileShare.Read); + ExtractZip(inputStream, targetDirectory, overwrite, confirmDelegate, fileFilter, directoryFilter, restoreDateTime, true); + } + + /// + /// Extract the contents of a zip file held in a stream. + /// + /// The seekable input stream containing the zip to extract from. + /// The directory to save extracted information in. + /// The style of overwriting to apply. + /// A delegate to invoke when confirming overwriting. + /// A filter to apply to files. + /// A filter to apply to directories. + /// Flag indicating whether to restore the date and time for extracted files. + /// Flag indicating whether the inputStream will be closed by this method. + public void ExtractZip(Stream inputStream, string targetDirectory, + Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate, + string fileFilter, string directoryFilter, bool restoreDateTime, + bool isStreamOwner) + { + if ((overwrite == Overwrite.Prompt) && (confirmDelegate == null)) { + throw new ArgumentNullException("confirmDelegate"); + } + + continueRunning_ = true; + overwrite_ = overwrite; + confirmDelegate_ = confirmDelegate; + extractNameTransform_ = new WindowsNameTransform(targetDirectory); + + fileFilter_ = new NameFilter(fileFilter); + directoryFilter_ = new NameFilter(directoryFilter); + restoreDateTimeOnExtract_ = restoreDateTime; + + using (zipFile_ = new ZipFile(inputStream)) { + +#if !NETCF_1_0 + if (password_ != null) { + zipFile_.Password = password_; + } +#endif + zipFile_.IsStreamOwner = isStreamOwner; + System.Collections.IEnumerator enumerator = zipFile_.GetEnumerator(); + while (continueRunning_ && enumerator.MoveNext()) { + ZipEntry entry = (ZipEntry)enumerator.Current; + if (entry.IsFile) + { + // TODO Path.GetDirectory can fail here on invalid characters. + if (directoryFilter_.IsMatch(Path.GetDirectoryName(entry.Name)) && fileFilter_.IsMatch(entry.Name)) { + ExtractEntry(entry); + } + } + else if (entry.IsDirectory) { + if (directoryFilter_.IsMatch(entry.Name) && CreateEmptyDirectories) { + ExtractEntry(entry); + } + } + else { + // Do nothing for volume labels etc... + } + } + } + } + #endregion + + #region Internal Processing + void ProcessDirectory(object sender, DirectoryEventArgs e) + { + if ( !e.HasMatchingFiles && CreateEmptyDirectories ) { + if ( events_ != null ) { + events_.OnProcessDirectory(e.Name, e.HasMatchingFiles); + } + + if ( e.ContinueRunning ) { + if (e.Name != sourceDirectory_) { + ZipEntry entry = entryFactory_.MakeDirectoryEntry(e.Name); + outputStream_.PutNextEntry(entry); + } + } + } + } + + void ProcessFile(object sender, ScanEventArgs e) + { + if ( (events_ != null) && (events_.ProcessFile != null) ) { + events_.ProcessFile(sender, e); + } + + if ( e.ContinueRunning ) { + try { + // The open below is equivalent to OpenRead which gaurantees that if opened the + // file will not be changed by subsequent openers, but precludes opening in some cases + // were it could succeed. + using (FileStream stream = File.Open(e.Name, FileMode.Open, FileAccess.Read, FileShare.Read)) { + ZipEntry entry = entryFactory_.MakeFileEntry(e.Name); + outputStream_.PutNextEntry(entry); + AddFileContents(e.Name, stream); + } + } + catch(Exception ex) { + if (events_ != null) { + continueRunning_ = events_.OnFileFailure(e.Name, ex); + } + else { + continueRunning_ = false; + throw; + } + } + } + } + + void AddFileContents(string name, Stream stream) + { + if( stream==null ) { + throw new ArgumentNullException("stream"); + } + + if( buffer_==null ) { + buffer_=new byte[4096]; + } + + if( (events_!=null)&&(events_.Progress!=null) ) { + StreamUtils.Copy(stream, outputStream_, buffer_, + events_.Progress, events_.ProgressInterval, this, name); + } + else { + StreamUtils.Copy(stream, outputStream_, buffer_); + } + + if( events_!=null ) { + continueRunning_=events_.OnCompletedFile(name); + } + } + + void ExtractFileEntry(ZipEntry entry, string targetName) + { + bool proceed = true; + if ( overwrite_ != Overwrite.Always ) { + if ( File.Exists(targetName) ) { + if ( (overwrite_ == Overwrite.Prompt) && (confirmDelegate_ != null) ) { + proceed = confirmDelegate_(targetName); + } + else { + proceed = false; + } + } + } + + if ( proceed ) { + if ( events_ != null ) { + continueRunning_ = events_.OnProcessFile(entry.Name); + } + + if ( continueRunning_ ) { + try { + using ( FileStream outputStream = File.Create(targetName) ) { + if ( buffer_ == null ) { + buffer_ = new byte[4096]; + } + if ((events_ != null) && (events_.Progress != null)) + { + StreamUtils.Copy(zipFile_.GetInputStream(entry), outputStream, buffer_, + events_.Progress, events_.ProgressInterval, this, entry.Name, entry.Size); + } + else + { + StreamUtils.Copy(zipFile_.GetInputStream(entry), outputStream, buffer_); + } + + if (events_ != null) { + continueRunning_ = events_.OnCompletedFile(entry.Name); + } + } + +#if !NETCF_1_0 && !NETCF_2_0 + if ( restoreDateTimeOnExtract_ ) { + File.SetLastWriteTime(targetName, entry.DateTime); + } + + if ( RestoreAttributesOnExtract && entry.IsDOSEntry && (entry.ExternalFileAttributes != -1)) { + FileAttributes fileAttributes = (FileAttributes) entry.ExternalFileAttributes; + // TODO: FastZip - Setting of other file attributes on extraction is a little trickier. + fileAttributes &= (FileAttributes.Archive | FileAttributes.Normal | FileAttributes.ReadOnly | FileAttributes.Hidden); + File.SetAttributes(targetName, fileAttributes); + } +#endif + } + catch(Exception ex) { + if ( events_ != null ) { + continueRunning_ = events_.OnFileFailure(targetName, ex); + } + else { + continueRunning_ = false; + throw; + } + } + } + } + } + + void ExtractEntry(ZipEntry entry) + { + bool doExtraction = entry.IsCompressionMethodSupported(); + string targetName = entry.Name; + + if ( doExtraction ) { + if ( entry.IsFile ) { + targetName = extractNameTransform_.TransformFile(targetName); + } + else if ( entry.IsDirectory ) { + targetName = extractNameTransform_.TransformDirectory(targetName); + } + + doExtraction = !((targetName == null) || (targetName.Length == 0)); + } + + // TODO: Fire delegate/throw exception were compression method not supported, or name is invalid? + + string dirName = null; + + if ( doExtraction ) { + if ( entry.IsDirectory ) { + dirName = targetName; + } + else { + dirName = Path.GetDirectoryName(Path.GetFullPath(targetName)); + } + } + + if ( doExtraction && !Directory.Exists(dirName) ) { + if ( !entry.IsDirectory || CreateEmptyDirectories ) { + try { + Directory.CreateDirectory(dirName); + } + catch (Exception ex) { + doExtraction = false; + if ( events_ != null ) { + if ( entry.IsDirectory ) { + continueRunning_ = events_.OnDirectoryFailure(targetName, ex); + } + else { + continueRunning_ = events_.OnFileFailure(targetName, ex); + } + } + else { + continueRunning_ = false; + throw; + } + } + } + } + + if ( doExtraction && entry.IsFile ) { + ExtractFileEntry(entry, targetName); + } + } + + static int MakeExternalAttributes(FileInfo info) + { + return (int)info.Attributes; + } + +#if NET_1_0 || NET_1_1 || NETCF_1_0 + static bool NameIsValid(string name) + { + return (name != null) && + (name.Length > 0) && + (name.IndexOfAny(Path.InvalidPathChars) < 0); + } +#else + static bool NameIsValid(string name) + { + return (name != null) && + (name.Length > 0) && + (name.IndexOfAny(Path.GetInvalidPathChars()) < 0); + } +#endif + #endregion + + #region Instance Fields + bool continueRunning_; + byte[] buffer_; + ZipOutputStream outputStream_; + ZipFile zipFile_; + string sourceDirectory_; + NameFilter fileFilter_; + NameFilter directoryFilter_; + Overwrite overwrite_; + ConfirmOverwriteDelegate confirmDelegate_; + + bool restoreDateTimeOnExtract_; + bool restoreAttributesOnExtract_; + bool createEmptyDirectories_; + FastZipEvents events_; + IEntryFactory entryFactory_ = new ZipEntryFactory(); + INameTransform extractNameTransform_; + UseZip64 useZip64_=UseZip64.Dynamic; + +#if !NETCF_1_0 + string password_; +#endif + + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/IEntryFactory.cs b/PCRobot/Utils/ZIP/Zip/IEntryFactory.cs new file mode 100644 index 0000000..ed7001c --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/IEntryFactory.cs @@ -0,0 +1,83 @@ +// IEntryFactory.cs +// +// Copyright 2006 John Reilly +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// Defines factory methods for creating new values. + /// + public interface IEntryFactory + { + /// + /// Create a for a file given its name + /// + /// The name of the file to create an entry for. + /// Returns a file entry based on the passed. + ZipEntry MakeFileEntry(string fileName); + + /// + /// Create a for a file given its name + /// + /// The name of the file to create an entry for. + /// If true get details from the file system if the file exists. + /// Returns a file entry based on the passed. + ZipEntry MakeFileEntry(string fileName, bool useFileSystem); + + /// + /// Create a for a directory given its name + /// + /// The name of the directory to create an entry for. + /// Returns a directory entry based on the passed. + ZipEntry MakeDirectoryEntry(string directoryName); + + /// + /// Create a for a directory given its name + /// + /// The name of the directory to create an entry for. + /// If true get details from the file system for this directory if it exists. + /// Returns a directory entry based on the passed. + ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem); + + /// + /// Get/set the applicable. + /// + INameTransform NameTransform { get; set; } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/WindowsNameTransform.cs b/PCRobot/Utils/ZIP/Zip/WindowsNameTransform.cs new file mode 100644 index 0000000..31430c6 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/WindowsNameTransform.cs @@ -0,0 +1,272 @@ +// WindowsNameTransform.cs +// +// Copyright 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// WindowsNameTransform transforms names to windows compatible ones. + /// + public class WindowsNameTransform : INameTransform + { + /// + /// Initialises a new instance of + /// + /// + public WindowsNameTransform(string baseDirectory) + { + if ( baseDirectory == null ) { + throw new ArgumentNullException("baseDirectory", "Directory name is invalid"); + } + + BaseDirectory = baseDirectory; + } + + /// + /// Initialise a default instance of + /// + public WindowsNameTransform() + { + // Do nothing. + } + + /// + /// Gets or sets a value containing the target directory to prefix values with. + /// + public string BaseDirectory + { + get { return _baseDirectory; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + + _baseDirectory = Path.GetFullPath(value); + } + } + + /// + /// Gets or sets a value indicating wether paths on incoming values should be removed. + /// + public bool TrimIncomingPaths + { + get { return _trimIncomingPaths; } + set { _trimIncomingPaths = value; } + } + + /// + /// Transform a Zip directory name to a windows directory name. + /// + /// The directory name to transform. + /// The transformed name. + public string TransformDirectory(string name) + { + name = TransformFile(name); + if (name.Length > 0) { + while ( name.EndsWith(@"\") ) { + name = name.Remove(name.Length - 1, 1); + } + } + else { + throw new ZipException("Cannot have an empty directory name"); + } + return name; + } + + /// + /// Transform a Zip format file name to a windows style one. + /// + /// The file name to transform. + /// The transformed name. + public string TransformFile(string name) + { + if (name != null) { + name = MakeValidName(name, _replacementChar); + + if ( _trimIncomingPaths ) { + name = Path.GetFileName(name); + } + + // This may exceed windows length restrictions. + // Combine will throw a PathTooLongException in that case. + if ( _baseDirectory != null ) { + name = Path.Combine(_baseDirectory, name); + } + } + else { + name = string.Empty; + } + return name; + } + + /// + /// Test a name to see if it is a valid name for a windows filename as extracted from a Zip archive. + /// + /// The name to test. + /// Returns true if the name is a valid zip name; false otherwise. + /// The filename isnt a true windows path in some fundamental ways like no absolute paths, no rooted paths etc. + public static bool IsValidName(string name) + { + bool result = + (name != null) && + (name.Length <= MaxPath) && + (string.Compare(name, MakeValidName(name, '_')) == 0) + ; + + return result; + } + + /// + /// Initialise static class information. + /// + static WindowsNameTransform() + { + char[] invalidPathChars; + +#if NET_1_0 || NET_1_1 || NETCF_1_0 + invalidPathChars = Path.InvalidPathChars; +#else + invalidPathChars = Path.GetInvalidPathChars(); +#endif + int howMany = invalidPathChars.Length + 3; + + InvalidEntryChars = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length); + InvalidEntryChars[howMany - 1] = '*'; + InvalidEntryChars[howMany - 2] = '?'; + InvalidEntryChars[howMany - 3] = ':'; + } + + /// + /// Force a name to be valid by replacing invalid characters with a fixed value + /// + /// The name to make valid + /// The replacement character to use for any invalid characters. + /// Returns a valid name + public static string MakeValidName(string name, char replacement) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + name = WindowsPathUtils.DropPathRoot(name.Replace("/", @"\")); + + // Drop any leading slashes. + while ( (name.Length > 0) && (name[0] == '\\')) { + name = name.Remove(0, 1); + } + + // Drop any trailing slashes. + while ( (name.Length > 0) && (name[name.Length - 1] == '\\')) { + name = name.Remove(name.Length - 1, 1); + } + + // Convert consecutive \\ characters to \ + int index = name.IndexOf(@"\\"); + while (index >= 0) { + name = name.Remove(index, 1); + index = name.IndexOf(@"\\"); + } + + // Convert any invalid characters using the replacement one. + index = name.IndexOfAny(InvalidEntryChars); + if (index >= 0) { + StringBuilder builder = new StringBuilder(name); + + while (index >= 0 ) { + builder[index] = replacement; + + if (index >= name.Length) { + index = -1; + } + else { + index = name.IndexOfAny(InvalidEntryChars, index + 1); + } + } + name = builder.ToString(); + } + + // Check for names greater than MaxPath characters. + // TODO: Were is CLR version of MaxPath defined? Can't find it in Environment. + if ( name.Length > MaxPath ) { + throw new PathTooLongException(); + } + + return name; + } + + /// + /// Gets or set the character to replace invalid characters during transformations. + /// + public char Replacement + { + get { return _replacementChar; } + set { + for ( int i = 0; i < InvalidEntryChars.Length; ++i ) { + if ( InvalidEntryChars[i] == value ) { + throw new ArgumentException("invalid path character"); + } + } + + if ((value == '\\') || (value == '/')) { + throw new ArgumentException("invalid replacement character"); + } + + _replacementChar = value; + } + } + + /// + /// The maximum windows path name permitted. + /// + /// This may not valid for all windows systems - CE?, etc but I cant find the equivalent in the CLR. + const int MaxPath = 260; + + #region Instance Fields + string _baseDirectory; + bool _trimIncomingPaths; + char _replacementChar = '_'; + #endregion + + #region Class Fields + static readonly char[] InvalidEntryChars; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipConstants.cs b/PCRobot/Utils/ZIP/Zip/ZipConstants.cs new file mode 100644 index 0000000..3a19c5f --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipConstants.cs @@ -0,0 +1,632 @@ +// ZipConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support + +using System; +using System.Text; +using System.Threading; + +#if NETCF_1_0 || NETCF_2_0 +using System.Globalization; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + + #region Enumerations + + /// + /// Determines how entries are tested to see if they should use Zip64 extensions or not. + /// + public enum UseZip64 + { + /// + /// Zip64 will not be forced on entries during processing. + /// + /// An entry can have this overridden if required + Off, + /// + /// Zip64 should always be used. + /// + On, + /// + /// #ZipLib will determine use based on entry values when added to archive. + /// + Dynamic, + } + + /// + /// The kind of compression used for an entry in an archive + /// + public enum CompressionMethod + { + /// + /// A direct copy of the file contents is held in the archive + /// + Stored = 0, + + /// + /// Common Zip compression method using a sliding dictionary + /// of up to 32KB and secondary compression from Huffman/Shannon-Fano trees + /// + Deflated = 8, + + /// + /// An extension to deflate with a 64KB window. Not supported by #Zip currently + /// + Deflate64 = 9, + + /// + /// BZip2 compression. Not supported by #Zip. + /// + BZip2 = 11, + + /// + /// WinZip special for AES encryption, Now supported by #Zip. + /// + WinZipAES = 99, + + } + + /// + /// Identifies the encryption algorithm used for an entry + /// + public enum EncryptionAlgorithm + { + /// + /// No encryption has been used. + /// + None = 0, + /// + /// Encrypted using PKZIP 2.0 or 'classic' encryption. + /// + PkzipClassic = 1, + /// + /// DES encryption has been used. + /// + Des = 0x6601, + /// + /// RCS encryption has been used for encryption. + /// + RC2 = 0x6602, + /// + /// Triple DES encryption with 168 bit keys has been used for this entry. + /// + TripleDes168 = 0x6603, + /// + /// Triple DES with 112 bit keys has been used for this entry. + /// + TripleDes112 = 0x6609, + /// + /// AES 128 has been used for encryption. + /// + Aes128 = 0x660e, + /// + /// AES 192 has been used for encryption. + /// + Aes192 = 0x660f, + /// + /// AES 256 has been used for encryption. + /// + Aes256 = 0x6610, + /// + /// RC2 corrected has been used for encryption. + /// + RC2Corrected = 0x6702, + /// + /// Blowfish has been used for encryption. + /// + Blowfish = 0x6720, + /// + /// Twofish has been used for encryption. + /// + Twofish = 0x6721, + /// + /// RC4 has been used for encryption. + /// + RC4 = 0x6801, + /// + /// An unknown algorithm has been used for encryption. + /// + Unknown = 0xffff + } + + /// + /// Defines the contents of the general bit flags field for an archive entry. + /// + [Flags] + public enum GeneralBitFlags : int + { + /// + /// Bit 0 if set indicates that the file is encrypted + /// + Encrypted = 0x0001, + /// + /// Bits 1 and 2 - Two bits defining the compression method (only for Method 6 Imploding and 8,9 Deflating) + /// + Method = 0x0006, + /// + /// Bit 3 if set indicates a trailing data desciptor is appended to the entry data + /// + Descriptor = 0x0008, + /// + /// Bit 4 is reserved for use with method 8 for enhanced deflation + /// + ReservedPKware4 = 0x0010, + /// + /// Bit 5 if set indicates the file contains Pkzip compressed patched data. + /// Requires version 2.7 or greater. + /// + Patched = 0x0020, + /// + /// Bit 6 if set indicates strong encryption has been used for this entry. + /// + StrongEncryption = 0x0040, + /// + /// Bit 7 is currently unused + /// + Unused7 = 0x0080, + /// + /// Bit 8 is currently unused + /// + Unused8 = 0x0100, + /// + /// Bit 9 is currently unused + /// + Unused9 = 0x0200, + /// + /// Bit 10 is currently unused + /// + Unused10 = 0x0400, + /// + /// Bit 11 if set indicates the filename and + /// comment fields for this file must be encoded using UTF-8. + /// + UnicodeText = 0x0800, + /// + /// Bit 12 is documented as being reserved by PKware for enhanced compression. + /// + EnhancedCompress = 0x1000, + /// + /// Bit 13 if set indicates that values in the local header are masked to hide + /// their actual values, and the central directory is encrypted. + /// + /// + /// Used when encrypting the central directory contents. + /// + HeaderMasked = 0x2000, + /// + /// Bit 14 is documented as being reserved for use by PKware + /// + ReservedPkware14 = 0x4000, + /// + /// Bit 15 is documented as being reserved for use by PKware + /// + ReservedPkware15 = 0x8000 + } + + #endregion + + /// + /// This class contains constants used for Zip format files + /// + public sealed class ZipConstants + { + #region Versions + /// + /// The version made by field for entries in the central header when created by this library + /// + /// + /// This is also the Zip version for the library when comparing against the version required to extract + /// for an entry. See . + /// + public const int VersionMadeBy = 51; // was 45 before AES + + /// + /// The version made by field for entries in the central header when created by this library + /// + /// + /// This is also the Zip version for the library when comparing against the version required to extract + /// for an entry. See ZipInputStream.CanDecompressEntry. + /// + [Obsolete("Use VersionMadeBy instead")] + public const int VERSION_MADE_BY = 51; + + /// + /// The minimum version required to support strong encryption + /// + public const int VersionStrongEncryption = 50; + + /// + /// The minimum version required to support strong encryption + /// + [Obsolete("Use VersionStrongEncryption instead")] + public const int VERSION_STRONG_ENCRYPTION = 50; + + /// + /// Version indicating AES encryption + /// + public const int VERSION_AES = 51; + + /// + /// The version required for Zip64 extensions (4.5 or higher) + /// + public const int VersionZip64 = 45; + #endregion + + #region Header Sizes + /// + /// Size of local entry header (excluding variable length fields at end) + /// + public const int LocalHeaderBaseSize = 30; + + /// + /// Size of local entry header (excluding variable length fields at end) + /// + [Obsolete("Use LocalHeaderBaseSize instead")] + public const int LOCHDR = 30; + + /// + /// Size of Zip64 data descriptor + /// + public const int Zip64DataDescriptorSize = 24; + + /// + /// Size of data descriptor + /// + public const int DataDescriptorSize = 16; + + /// + /// Size of data descriptor + /// + [Obsolete("Use DataDescriptorSize instead")] + public const int EXTHDR = 16; + + /// + /// Size of central header entry (excluding variable fields) + /// + public const int CentralHeaderBaseSize = 46; + + /// + /// Size of central header entry + /// + [Obsolete("Use CentralHeaderBaseSize instead")] + public const int CENHDR = 46; + + /// + /// Size of end of central record (excluding variable fields) + /// + public const int EndOfCentralRecordBaseSize = 22; + + /// + /// Size of end of central record (excluding variable fields) + /// + [Obsolete("Use EndOfCentralRecordBaseSize instead")] + public const int ENDHDR = 22; + + /// + /// Size of 'classic' cryptographic header stored before any entry data + /// + public const int CryptoHeaderSize = 12; + + /// + /// Size of cryptographic header stored before entry data + /// + [Obsolete("Use CryptoHeaderSize instead")] + public const int CRYPTO_HEADER_SIZE = 12; + #endregion + + #region Header Signatures + + /// + /// Signature for local entry header + /// + public const int LocalHeaderSignature = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); + + /// + /// Signature for local entry header + /// + [Obsolete("Use LocalHeaderSignature instead")] + public const int LOCSIG = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); + + /// + /// Signature for spanning entry + /// + public const int SpanningSignature = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for spanning entry + /// + [Obsolete("Use SpanningSignature instead")] + public const int SPANNINGSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for temporary spanning entry + /// + public const int SpanningTempSignature = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24); + + /// + /// Signature for temporary spanning entry + /// + [Obsolete("Use SpanningTempSignature instead")] + public const int SPANTEMPSIG = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24); + + /// + /// Signature for data descriptor + /// + /// + /// This is only used where the length, Crc, or compressed size isnt known when the + /// entry is created and the output stream doesnt support seeking. + /// The local entry cannot be 'patched' with the correct values in this case + /// so the values are recorded after the data prefixed by this header, as well as in the central directory. + /// + public const int DataDescriptorSignature = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for data descriptor + /// + /// + /// This is only used where the length, Crc, or compressed size isnt known when the + /// entry is created and the output stream doesnt support seeking. + /// The local entry cannot be 'patched' with the correct values in this case + /// so the values are recorded after the data prefixed by this header, as well as in the central directory. + /// + [Obsolete("Use DataDescriptorSignature instead")] + public const int EXTSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for central header + /// + [Obsolete("Use CentralHeaderSignature instead")] + public const int CENSIG = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); + + /// + /// Signature for central header + /// + public const int CentralHeaderSignature = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); + + /// + /// Signature for Zip64 central file header + /// + public const int Zip64CentralFileHeaderSignature = 'P' | ('K' << 8) | (6 << 16) | (6 << 24); + + /// + /// Signature for Zip64 central file header + /// + [Obsolete("Use Zip64CentralFileHeaderSignature instead")] + public const int CENSIG64 = 'P' | ('K' << 8) | (6 << 16) | (6 << 24); + + /// + /// Signature for Zip64 central directory locator + /// + public const int Zip64CentralDirLocatorSignature = 'P' | ('K' << 8) | (6 << 16) | (7 << 24); + + /// + /// Signature for archive extra data signature (were headers are encrypted). + /// + public const int ArchiveExtraDataSignature = 'P' | ('K' << 8) | (6 << 16) | (7 << 24); + + /// + /// Central header digitial signature + /// + public const int CentralHeaderDigitalSignature = 'P' | ('K' << 8) | (5 << 16) | (5 << 24); + + /// + /// Central header digitial signature + /// + [Obsolete("Use CentralHeaderDigitalSignaure instead")] + public const int CENDIGITALSIG = 'P' | ('K' << 8) | (5 << 16) | (5 << 24); + + /// + /// End of central directory record signature + /// + public const int EndOfCentralDirectorySignature = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); + + /// + /// End of central directory record signature + /// + [Obsolete("Use EndOfCentralDirectorySignature instead")] + public const int ENDSIG = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); + #endregion + +#if NETCF_1_0 || NETCF_2_0 + // This isnt so great but is better than nothing. + // Trying to work out an appropriate OEM code page would be good. + // 850 is a good default for english speakers particularly in Europe. + static int defaultCodePage = CultureInfo.CurrentCulture.TextInfo.ANSICodePage; +#else + static int defaultCodePage = Thread.CurrentThread.CurrentCulture.TextInfo.OEMCodePage; +#endif + + /// + /// Default encoding used for string conversion. 0 gives the default system OEM code page. + /// Dont use unicode encodings if you want to be Zip compatible! + /// Using the default code page isnt the full solution neccessarily + /// there are many variable factors, codepage 850 is often a good choice for + /// European users, however be careful about compatability. + /// + public static int DefaultCodePage { + get { + return defaultCodePage; + } + set { + defaultCodePage = value; + } + } + + /// + /// Convert a portion of a byte array to a string. + /// + /// + /// Data to convert to string + /// + /// + /// Number of bytes to convert starting from index 0 + /// + /// + /// data[0]..data[length - 1] converted to a string + /// + public static string ConvertToString(byte[] data, int count) + { + if ( data == null ) { + return string.Empty; + } + + return Encoding.GetEncoding(DefaultCodePage).GetString(data, 0, count); + } + + /// + /// Convert a byte array to string + /// + /// + /// Byte array to convert + /// + /// + /// dataconverted to a string + /// + public static string ConvertToString(byte[] data) + { + if ( data == null ) { + return string.Empty; + } + return ConvertToString(data, data.Length); + } + + /// + /// Convert a byte array to string + /// + /// The applicable general purpose bits flags + /// + /// Byte array to convert + /// + /// The number of bytes to convert. + /// + /// dataconverted to a string + /// + public static string ConvertToStringExt(int flags, byte[] data, int count) + { + if ( data == null ) { + return string.Empty; + } + + if ( (flags & (int)GeneralBitFlags.UnicodeText) != 0 ) { + return Encoding.UTF8.GetString(data, 0, count); + } + else { + return ConvertToString(data, count); + } + } + + /// + /// Convert a byte array to string + /// + /// + /// Byte array to convert + /// + /// The applicable general purpose bits flags + /// + /// dataconverted to a string + /// + public static string ConvertToStringExt(int flags, byte[] data) + { + if ( data == null ) { + return string.Empty; + } + + if ( (flags & (int)GeneralBitFlags.UnicodeText) != 0 ) { + return Encoding.UTF8.GetString(data, 0, data.Length); + } + else { + return ConvertToString(data, data.Length); + } + } + + /// + /// Convert a string to a byte array + /// + /// + /// String to convert to an array + /// + /// Converted array + public static byte[] ConvertToArray(string str) + { + if ( str == null ) { + return new byte[0]; + } + + return Encoding.GetEncoding(DefaultCodePage).GetBytes(str); + } + + /// + /// Convert a string to a byte array + /// + /// The applicable general purpose bits flags + /// + /// String to convert to an array + /// + /// Converted array + public static byte[] ConvertToArray(int flags, string str) + { + if (str == null) { + return new byte[0]; + } + + if ((flags & (int)GeneralBitFlags.UnicodeText) != 0) { + return Encoding.UTF8.GetBytes(str); + } + else { + return ConvertToArray(str); + } + } + + + /// + /// Initialise default instance of ZipConstants + /// + /// + /// Private to prevent instances being created. + /// + ZipConstants() + { + // Do nothing + } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipEntry.cs b/PCRobot/Utils/ZIP/Zip/ZipEntry.cs new file mode 100644 index 0000000..0e34784 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipEntry.cs @@ -0,0 +1,1253 @@ +// ZipEntry.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support +// 02-02-2010 DavidPierson Changed NTFS Extra Data min length to 4 + +using ICSharpCode.SharpZipLib.Zip; +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Zip1 +{ + + /// + /// Defines known values for the property. + /// + public enum HostSystemID + { + /// + /// Host system = MSDOS + /// + Msdos = 0, + /// + /// Host system = Amiga + /// + Amiga = 1, + /// + /// Host system = Open VMS + /// + OpenVms = 2, + /// + /// Host system = Unix + /// + Unix = 3, + /// + /// Host system = VMCms + /// + VMCms = 4, + /// + /// Host system = Atari ST + /// + AtariST = 5, + /// + /// Host system = OS2 + /// + OS2 = 6, + /// + /// Host system = Macintosh + /// + Macintosh = 7, + /// + /// Host system = ZSystem + /// + ZSystem = 8, + /// + /// Host system = Cpm + /// + Cpm = 9, + /// + /// Host system = Windows NT + /// + WindowsNT = 10, + /// + /// Host system = MVS + /// + MVS = 11, + /// + /// Host system = VSE + /// + Vse = 12, + /// + /// Host system = Acorn RISC + /// + AcornRisc = 13, + /// + /// Host system = VFAT + /// + Vfat = 14, + /// + /// Host system = Alternate MVS + /// + AlternateMvs = 15, + /// + /// Host system = BEOS + /// + BeOS = 16, + /// + /// Host system = Tandem + /// + Tandem = 17, + /// + /// Host system = OS400 + /// + OS400 = 18, + /// + /// Host system = OSX + /// + OSX = 19, + /// + /// Host system = WinZIP AES + /// + WinZipAES = 99, + } + + /// + /// This class represents an entry in a zip archive. This can be a file + /// or a directory + /// ZipFile and ZipInputStream will give you instances of this class as + /// information about the members in an archive. ZipOutputStream + /// uses an instance of this class when creating an entry in a Zip file. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ public class ZipEntry : ICloneable + { + [Flags] + enum Known : byte + { + None = 0, + Size = 0x01, + CompressedSize = 0x02, + Crc = 0x04, + Time = 0x08, + ExternalAttributes = 0x10, + } + + #region Constructors + /// + /// Creates a zip entry with the given name. + /// + /// + /// The name for this entry. Can include directory components. + /// The convention for names is 'unix' style paths with relative names only. + /// There are with no device names and path elements are separated by '/' characters. + /// + /// + /// The name passed is null + /// + public ZipEntry(string name) + : this(name, 0, ZipConstants.VersionMadeBy, CompressionMethod.Deflated) + { + } + + /// + /// Creates a zip entry with the given name and version required to extract + /// + /// + /// The name for this entry. Can include directory components. + /// The convention for names is 'unix' style paths with no device names and + /// path elements separated by '/' characters. This is not enforced see CleanName + /// on how to ensure names are valid if this is desired. + /// + /// + /// The minimum 'feature version' required this entry + /// + /// + /// The name passed is null + /// + internal ZipEntry(string name, int versionRequiredToExtract) + : this(name, versionRequiredToExtract, ZipConstants.VersionMadeBy, + CompressionMethod.Deflated) + { + } + + /// + /// Initializes an entry with the given name and made by information + /// + /// Name for this entry + /// Version and HostSystem Information + /// Minimum required zip feature version required to extract this entry + /// Compression method for this entry. + /// + /// The name passed is null + /// + /// + /// versionRequiredToExtract should be 0 (auto-calculate) or > 10 + /// + /// + /// This constructor is used by the ZipFile class when reading from the central header + /// It is not generally useful, use the constructor specifying the name only. + /// + internal ZipEntry(string name, int versionRequiredToExtract, int madeByInfo, + CompressionMethod method) + { + if (name == null) { + throw new System.ArgumentNullException("name"); + } + + if ( name.Length > 0xffff ) { + throw new ArgumentException("Name is too long", "name"); + } + + if ( (versionRequiredToExtract != 0) && (versionRequiredToExtract < 10) ) { + throw new ArgumentOutOfRangeException("versionRequiredToExtract"); + } + + this.DateTime = System.DateTime.Now; + this.name = name; + this.versionMadeBy = (ushort)madeByInfo; + this.versionToExtract = (ushort)versionRequiredToExtract; + this.method = method; + } + + /// + /// Creates a deep copy of the given zip entry. + /// + /// + /// The entry to copy. + /// + [Obsolete("Use Clone instead")] + public ZipEntry(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + known = entry.known; + name = entry.name; + size = entry.size; + compressedSize = entry.compressedSize; + crc = entry.crc; + dosTime = entry.dosTime; + method = entry.method; + comment = entry.comment; + versionToExtract = entry.versionToExtract; + versionMadeBy = entry.versionMadeBy; + externalFileAttributes = entry.externalFileAttributes; + flags = entry.flags; + + zipFileIndex = entry.zipFileIndex; + offset = entry.offset; + + forceZip64_ = entry.forceZip64_; + + if ( entry.extra != null ) { + extra = new byte[entry.extra.Length]; + Array.Copy(entry.extra, 0, extra, 0, entry.extra.Length); + } + } + + #endregion + + /// + /// Get a value indicating wether the entry has a CRC value available. + /// + public bool HasCrc + { + get { + return (known & Known.Crc) != 0; + } + } + + /// + /// Get/Set flag indicating if entry is encrypted. + /// A simple helper routine to aid interpretation of flags + /// + /// This is an assistant that interprets the flags property. + public bool IsCrypted + { + get { + return (flags & 1) != 0; + } + set { + if (value) { + flags |= 1; + } + else { + flags &= ~1; + } + } + } + + /// + /// Get / set a flag indicating wether entry name and comment text are + /// encoded in unicode UTF8. + /// + /// This is an assistant that interprets the flags property. + public bool IsUnicodeText + { + get { + return ( flags & (int)GeneralBitFlags.UnicodeText ) != 0; + } + set { + if ( value ) { + flags |= (int)GeneralBitFlags.UnicodeText; + } + else { + flags &= ~(int)GeneralBitFlags.UnicodeText; + } + } + } + + /// + /// Value used during password checking for PKZIP 2.0 / 'classic' encryption. + /// + internal byte CryptoCheckValue + { + get { + return cryptoCheckValue_; + } + + set { + cryptoCheckValue_ = value; + } + } + + /// + /// Get/Set general purpose bit flag for entry + /// + /// + /// General purpose bit flag
+ ///
+ /// Bit 0: If set, indicates the file is encrypted
+ /// Bit 1-2 Only used for compression type 6 Imploding, and 8, 9 deflating
+ /// Imploding:
+ /// Bit 1 if set indicates an 8K sliding dictionary was used. If clear a 4k dictionary was used
+ /// Bit 2 if set indicates 3 Shannon-Fanno trees were used to encode the sliding dictionary, 2 otherwise
+ ///
+ /// Deflating:
+ /// Bit 2 Bit 1
+ /// 0 0 Normal compression was used
+ /// 0 1 Maximum compression was used
+ /// 1 0 Fast compression was used
+ /// 1 1 Super fast compression was used
+ ///
+ /// Bit 3: If set, the fields crc-32, compressed size + /// and uncompressed size are were not able to be written during zip file creation + /// The correct values are held in a data descriptor immediately following the compressed data.
+ /// Bit 4: Reserved for use by PKZIP for enhanced deflating
+ /// Bit 5: If set indicates the file contains compressed patch data
+ /// Bit 6: If set indicates strong encryption was used.
+ /// Bit 7-10: Unused or reserved
+ /// Bit 11: If set the name and comments for this entry are in unicode.
+ /// Bit 12-15: Unused or reserved
+ ///
+ /// + /// + public int Flags + { + get { + return flags; + } + set { + flags = value; + } + } + + /// + /// Get/Set index of this entry in Zip file + /// + /// This is only valid when the entry is part of a + public long ZipFileIndex + { + get { + return zipFileIndex; + } + set { + zipFileIndex = value; + } + } + + /// + /// Get/set offset for use in central header + /// + public long Offset + { + get { + return offset; + } + set { + offset = value; + } + } + + /// + /// Get/Set external file attributes as an integer. + /// The values of this are operating system dependant see + /// HostSystem for details + /// + public int ExternalFileAttributes + { + get { + if ((known & Known.ExternalAttributes) == 0) { + return -1; + } + else { + return externalFileAttributes; + } + } + + set { + externalFileAttributes = value; + known |= Known.ExternalAttributes; + } + } + + /// + /// Get the version made by for this entry or zero if unknown. + /// The value / 10 indicates the major version number, and + /// the value mod 10 is the minor version number + /// + public int VersionMadeBy + { + get { + return (versionMadeBy & 0xff); + } + } + + /// + /// Get a value indicating this entry is for a DOS/Windows system. + /// + public bool IsDOSEntry + { + get { + return ((HostSystem == ( int )HostSystemID.Msdos) || + (HostSystem == ( int )HostSystemID.WindowsNT)); + } + } + + /// + /// Test the external attributes for this to + /// see if the external attributes are Dos based (including WINNT and variants) + /// and match the values + /// + /// The attributes to test. + /// Returns true if the external attributes are known to be DOS/Windows + /// based and have the same attributes set as the value passed. + bool HasDosAttributes(int attributes) + { + bool result = false; + if ( (known & Known.ExternalAttributes) != 0 ) { + if ( ((HostSystem == (int)HostSystemID.Msdos) || + (HostSystem == (int)HostSystemID.WindowsNT)) && + (ExternalFileAttributes & attributes) == attributes) { + result = true; + } + } + return result; + } + + /// + /// Gets the compatability information for the external file attribute + /// If the external file attributes are compatible with MS-DOS and can be read + /// by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value + /// will be non-zero and identify the host system on which the attributes are compatible. + /// + /// + /// + /// The values for this as defined in the Zip File format and by others are shown below. The values are somewhat + /// misleading in some cases as they are not all used as shown. You should consult the relevant documentation + /// to obtain up to date and correct information. The modified appnote by the infozip group is + /// particularly helpful as it documents a lot of peculiarities. The document is however a little dated. + /// + /// 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + /// 1 - Amiga + /// 2 - OpenVMS + /// 3 - Unix + /// 4 - VM/CMS + /// 5 - Atari ST + /// 6 - OS/2 HPFS + /// 7 - Macintosh + /// 8 - Z-System + /// 9 - CP/M + /// 10 - Windows NTFS + /// 11 - MVS (OS/390 - Z/OS) + /// 12 - VSE + /// 13 - Acorn Risc + /// 14 - VFAT + /// 15 - Alternate MVS + /// 16 - BeOS + /// 17 - Tandem + /// 18 - OS/400 + /// 19 - OS/X (Darwin) + /// 99 - WinZip AES + /// remainder - unused + /// + /// + public int HostSystem + { + get { + return (versionMadeBy >> 8) & 0xff; + } + + set { + versionMadeBy &= 0xff; + versionMadeBy |= (ushort)((value & 0xff) << 8); + } + } + + /// + /// Get minimum Zip feature version required to extract this entry + /// + /// + /// Minimum features are defined as:
+ /// 1.0 - Default value
+ /// 1.1 - File is a volume label
+ /// 2.0 - File is a folder/directory
+ /// 2.0 - File is compressed using Deflate compression
+ /// 2.0 - File is encrypted using traditional encryption
+ /// 2.1 - File is compressed using Deflate64
+ /// 2.5 - File is compressed using PKWARE DCL Implode
+ /// 2.7 - File is a patch data set
+ /// 4.5 - File uses Zip64 format extensions
+ /// 4.6 - File is compressed using BZIP2 compression
+ /// 5.0 - File is encrypted using DES
+ /// 5.0 - File is encrypted using 3DES
+ /// 5.0 - File is encrypted using original RC2 encryption
+ /// 5.0 - File is encrypted using RC4 encryption
+ /// 5.1 - File is encrypted using AES encryption
+ /// 5.1 - File is encrypted using corrected RC2 encryption
+ /// 5.1 - File is encrypted using corrected RC2-64 encryption
+ /// 6.1 - File is encrypted using non-OAEP key wrapping
+ /// 6.2 - Central directory encryption (not confirmed yet)
+ /// 6.3 - File is compressed using LZMA
+ /// 6.3 - File is compressed using PPMD+
+ /// 6.3 - File is encrypted using Blowfish
+ /// 6.3 - File is encrypted using Twofish
+ ///
+ /// + public int Version + { + get { + // Return recorded version if known. + if (versionToExtract != 0) { + return versionToExtract; + } + else { + int result = 10; + if (AESKeySize > 0) { + result = ZipConstants.VERSION_AES; // Ver 5.1 = AES + } + else if (CentralHeaderRequiresZip64) { + result = ZipConstants.VersionZip64; + } + else if (CompressionMethod.Deflated == method) { + result = 20; + } + else if (IsDirectory == true) { + result = 20; + } + else if (IsCrypted == true) { + result = 20; + } + else if (HasDosAttributes(0x08) ) { + result = 11; + } + return result; + } + } + } + + /// + /// Get a value indicating whether this entry can be decompressed by the library. + /// + /// This is based on the and + /// wether the compression method is supported. + public bool CanDecompress + { + get { + return (Version <= ZipConstants.VersionMadeBy) && + ((Version == 10) || + (Version == 11) || + (Version == 20) || + (Version == 45) || + (Version == 51)) && + IsCompressionMethodSupported(); + } + } + + /// + /// Force this entry to be recorded using Zip64 extensions. + /// + public void ForceZip64() + { + forceZip64_ = true; + } + + /// + /// Get a value indicating wether Zip64 extensions were forced. + /// + /// A value of true if Zip64 extensions have been forced on; false if not. + public bool IsZip64Forced() + { + return forceZip64_; + } + + /// + /// Gets a value indicating if the entry requires Zip64 extensions + /// to store the full entry values. + /// + /// A value of true if a local header requires Zip64 extensions; false if not. + public bool LocalHeaderRequiresZip64 + { + get { + bool result = forceZip64_; + + if ( !result ) { + ulong trueCompressedSize = compressedSize; + + if ( (versionToExtract == 0) && IsCrypted ) { + trueCompressedSize += ZipConstants.CryptoHeaderSize; + } + + // TODO: A better estimation of the true limit based on compression overhead should be used + // to determine when an entry should use Zip64. + result = + ((this.size >= uint.MaxValue) || (trueCompressedSize >= uint.MaxValue)) && + ((versionToExtract == 0) || (versionToExtract >= ZipConstants.VersionZip64)); + } + + return result; + } + } + + /// + /// Get a value indicating wether the central directory entry requires Zip64 extensions to be stored. + /// + public bool CentralHeaderRequiresZip64 + { + get { + return LocalHeaderRequiresZip64 || (offset >= uint.MaxValue); + } + } + + /// + /// Get/Set DosTime value. + /// + /// + /// The MS-DOS date format can only represent dates between 1/1/1980 and 12/31/2107. + /// + public long DosTime + { + get { + if ((known & Known.Time) == 0) { + return 0; + } + else { + return dosTime; + } + } + + set { + unchecked { + dosTime = (uint)value; + } + + known |= Known.Time; + } + } + + /// + /// Gets/Sets the time of last modification of the entry. + /// + /// + /// The property is updated to match this as far as possible. + /// + public DateTime DateTime + { + get { + uint sec = Math.Min(59, 2 * (dosTime & 0x1f)); + uint min = Math.Min(59, (dosTime >> 5) & 0x3f); + uint hrs = Math.Min(23, (dosTime >> 11) & 0x1f); + uint mon = Math.Max(1, Math.Min(12, ((dosTime >> 21) & 0xf))); + uint year = ((dosTime >> 25) & 0x7f) + 1980; + int day = Math.Max(1, Math.Min(DateTime.DaysInMonth((int)year, (int)mon), (int)((dosTime >> 16) & 0x1f))); + return new System.DateTime((int)year, (int)mon, day, (int)hrs, (int)min, (int)sec); + } + + set { + uint year = (uint) value.Year; + uint month = (uint) value.Month; + uint day = (uint) value.Day; + uint hour = (uint) value.Hour; + uint minute = (uint) value.Minute; + uint second = (uint) value.Second; + + if ( year < 1980 ) { + year = 1980; + month = 1; + day = 1; + hour = 0; + minute = 0; + second = 0; + } + else if ( year > 2107 ) { + year = 2107; + month = 12; + day = 31; + hour = 23; + minute = 59; + second = 59; + } + + DosTime = ((year - 1980) & 0x7f) << 25 | + (month << 21) | + (day << 16) | + (hour << 11) | + (minute << 5) | + (second >> 1); + } + } + + /// + /// Returns the entry name. + /// + /// + /// The unix naming convention is followed. + /// Path components in the entry should always separated by forward slashes ('/'). + /// Dos device names like C: should also be removed. + /// See the class, or + /// + public string Name + { + get { + return name; + } + } + + /// + /// Gets/Sets the size of the uncompressed data. + /// + /// + /// The size or -1 if unknown. + /// + /// Setting the size before adding an entry to an archive can help + /// avoid compatability problems with some archivers which dont understand Zip64 extensions. + public long Size + { + get { + return (known & Known.Size) != 0 ? (long)size : -1L; + } + set { + this.size = (ulong)value; + this.known |= Known.Size; + } + } + + /// + /// Gets/Sets the size of the compressed data. + /// + /// + /// The compressed entry size or -1 if unknown. + /// + public long CompressedSize + { + get { + return (known & Known.CompressedSize) != 0 ? (long)compressedSize : -1L; + } + set { + this.compressedSize = (ulong)value; + this.known |= Known.CompressedSize; + } + } + + /// + /// Gets/Sets the crc of the uncompressed data. + /// + /// + /// Crc is not in the range 0..0xffffffffL + /// + /// + /// The crc value or -1 if unknown. + /// + public long Crc + { + get { + return (known & Known.Crc) != 0 ? crc & 0xffffffffL : -1L; + } + set { + if (((ulong)crc & 0xffffffff00000000L) != 0) { + throw new ArgumentOutOfRangeException("value"); + } + this.crc = (uint)value; + this.known |= Known.Crc; + } + } + + /// + /// Gets/Sets the compression method. Only Deflated and Stored are supported. + /// + /// + /// The compression method for this entry + /// + /// + /// + public CompressionMethod CompressionMethod { + get { + return method; + } + + set { + if ( !IsCompressionMethodSupported(value) ) { + throw new NotSupportedException("Compression method not supported"); + } + this.method = value; + } + } + + /// + /// Gets the compression method for outputting to the local or central header. + /// Returns same value as CompressionMethod except when AES encrypting, which + /// places 99 in the method and places the real method in the extra data. + /// + internal CompressionMethod CompressionMethodForHeader { + get { + return (AESKeySize > 0) ? CompressionMethod.WinZipAES : method; + } + } + + /// + /// Gets/Sets the extra data. + /// + /// + /// Extra data is longer than 64KB (0xffff) bytes. + /// + /// + /// Extra data or null if not set. + /// + public byte[] ExtraData { + + get { +// TODO: This is slightly safer but less efficient. Think about wether it should change. +// return (byte[]) extra.Clone(); + return extra; + } + + set { + if (value == null) { + extra = null; + } + else { + if (value.Length > 0xffff) { + throw new System.ArgumentOutOfRangeException("value"); + } + + extra = new byte[value.Length]; + Array.Copy(value, 0, extra, 0, value.Length); + } + } + } + + +#if !NET_1_1 && !NETCF_2_0 + /// + /// For AES encrypted files returns or sets the number of bits of encryption (128, 192 or 256). + /// When setting, only 0 (off), 128 or 256 is supported. + /// + public int AESKeySize { + get { + // the strength (1 or 3) is in the entry header + switch (_aesEncryptionStrength) { + case 0: return 0; // Not AES + case 1: return 128; + case 2: return 192; // Not used by WinZip + case 3: return 256; + default: throw new ZipException("Invalid AESEncryptionStrength " + _aesEncryptionStrength); + } + } + set { + switch (value) { + case 0: _aesEncryptionStrength = 0; break; + case 128: _aesEncryptionStrength = 1; break; + case 256: _aesEncryptionStrength = 3; break; + default: throw new ZipException("AESKeySize must be 0, 128 or 256: " + value); + } + } + } + + /// + /// AES Encryption strength for storage in extra data in entry header. + /// 1 is 128 bit, 2 is 192 bit, 3 is 256 bit. + /// + internal byte AESEncryptionStrength { + get { + return (byte)_aesEncryptionStrength; + } + } +#else + /// + /// AES unsupported prior to .NET 2.0 + /// + internal int AESKeySize; +#endif + + /// + /// Returns the length of the salt, in bytes + /// + internal int AESSaltLen { + get { + // Key size -> Salt length: 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. + return AESKeySize / 16; + } + } + + /// + /// Number of extra bytes required to hold the AES Header fields (Salt, Pwd verify, AuthCode) + /// + internal int AESOverheadSize { + get { + // File format: + // Bytes Content + // Variable Salt value + // 2 Password verification value + // Variable Encrypted file data + // 10 Authentication code + return 12 + AESSaltLen; + } + } + + /// + /// Process extra data fields updating the entry based on the contents. + /// + /// True if the extra data fields should be handled + /// for a local header, rather than for a central header. + /// + internal void ProcessExtraData(bool localHeader) + { + ZipExtraData extraData = new ZipExtraData(this.extra); + + if ( extraData.Find(0x0001) ) { + // Version required to extract is ignored here as some archivers dont set it correctly + // in theory it should be version 45 or higher + + // The recorded size will change but remember that this is zip64. + forceZip64_ = true; + + if ( extraData.ValueLength < 4 ) { + throw new ZipException("Extra data extended Zip64 information length is invalid"); + } + + if ( localHeader || (size == uint.MaxValue) ) { + size = (ulong)extraData.ReadLong(); + } + + if ( localHeader || (compressedSize == uint.MaxValue) ) { + compressedSize = (ulong)extraData.ReadLong(); + } + + if ( !localHeader && (offset == uint.MaxValue) ) { + offset = extraData.ReadLong(); + } + + // Disk number on which file starts is ignored + } + else { + if ( + ((versionToExtract & 0xff) >= ZipConstants.VersionZip64) && + ((size == uint.MaxValue) || (compressedSize == uint.MaxValue)) + ) { + throw new ZipException("Zip64 Extended information required but is missing."); + } + } + + if ( extraData.Find(10) ) { + // No room for any tags. + if ( extraData.ValueLength < 4 ) { + throw new ZipException("NTFS Extra data invalid"); + } + + extraData.ReadInt(); // Reserved + + while ( extraData.UnreadCount >= 4 ) { + int ntfsTag = extraData.ReadShort(); + int ntfsLength = extraData.ReadShort(); + if ( ntfsTag == 1 ) { + if ( ntfsLength >= 24 ) { + long lastModification = extraData.ReadLong(); + long lastAccess = extraData.ReadLong(); + long createTime = extraData.ReadLong(); + + DateTime = System.DateTime.FromFileTime(lastModification); + } + break; + } + else { + // An unknown NTFS tag so simply skip it. + extraData.Skip(ntfsLength); + } + } + } + else if ( extraData.Find(0x5455) ) { + int length = extraData.ValueLength; + int flags = extraData.ReadByte(); + + // Can include other times but these are ignored. Length of data should + // actually be 1 + 4 * no of bits in flags. + if ( ((flags & 1) != 0) && (length >= 5) ) { + int iTime = extraData.ReadInt(); + + DateTime = (new System.DateTime ( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime() + + new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime(); + } + } + if (method == CompressionMethod.WinZipAES) { + ProcessAESExtraData(extraData); + } + } + + // For AES the method in the entry is 99, and the real compression method is in the extradata + // + private void ProcessAESExtraData(ZipExtraData extraData) { + +#if !NET_1_1 && !NETCF_2_0 + if (extraData.Find(0x9901)) { + // Set version and flag for Zipfile.CreateAndInitDecryptionStream + versionToExtract = ZipConstants.VERSION_AES; // Ver 5.1 = AES see "Version" getter + // Set StrongEncryption flag for ZipFile.CreateAndInitDecryptionStream + Flags = Flags | (int)GeneralBitFlags.StrongEncryption; + // + // Unpack AES extra data field see http://www.winzip.com/aes_info.htm + int length = extraData.ValueLength; // Data size currently 7 + if (length < 7) + throw new ZipException("AES Extra Data Length " + length + " invalid."); + int ver = extraData.ReadShort(); // Version number (1=AE-1 2=AE-2) + int vendorId = extraData.ReadShort(); // 2-character vendor ID 0x4541 = "AE" + int encrStrength = extraData.ReadByte(); // encryption strength 1 = 128 2 = 192 3 = 256 + int actualCompress = extraData.ReadShort(); // The actual compression method used to compress the file + _aesVer = ver; + _aesEncryptionStrength = encrStrength; + method = (CompressionMethod)actualCompress; + } else + throw new ZipException("AES Extra Data missing"); +#else + throw new ZipException("AES unsupported"); +#endif + } + + /// + /// Gets/Sets the entry comment. + /// + /// + /// If comment is longer than 0xffff. + /// + /// + /// The comment or null if not set. + /// + /// + /// A comment is only available for entries when read via the class. + /// The class doesnt have the comment data available. + /// + public string Comment { + get { + return comment; + } + set { + // This test is strictly incorrect as the length is in characters + // while the storage limit is in bytes. + // While the test is partially correct in that a comment of this length or greater + // is definitely invalid, shorter comments may also have an invalid length + // where there are multi-byte characters + // The full test is not possible here however as the code page to apply conversions with + // isnt available. + if ( (value != null) && (value.Length > 0xffff) ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "cannot exceed 65535"); +#endif + } + + comment = value; + } + } + + /// + /// Gets a value indicating if the entry is a directory. + /// however. + /// + /// + /// A directory is determined by an entry name with a trailing slash '/'. + /// The external file attributes can also indicate an entry is for a directory. + /// Currently only dos/windows attributes are tested in this manner. + /// The trailing slash convention should always be followed. + /// + public bool IsDirectory + { + get { + int nameLength = name.Length; + bool result = + ((nameLength > 0) && + ((name[nameLength - 1] == '/') || (name[nameLength - 1] == '\\'))) || + HasDosAttributes(16) + ; + return result; + } + } + + /// + /// Get a value of true if the entry appears to be a file; false otherwise + /// + /// + /// This only takes account of DOS/Windows attributes. Other operating systems are ignored. + /// For linux and others the result may be incorrect. + /// + public bool IsFile + { + get { + return !IsDirectory && !HasDosAttributes(8); + } + } + + /// + /// Test entry to see if data can be extracted. + /// + /// Returns true if data can be extracted for this entry; false otherwise. + public bool IsCompressionMethodSupported() + { + return IsCompressionMethodSupported(CompressionMethod); + } + + #region ICloneable Members + /// + /// Creates a copy of this zip entry. + /// + /// An that is a copy of the current instance. + public object Clone() + { + ZipEntry result = (ZipEntry)this.MemberwiseClone(); + + // Ensure extra data is unique if it exists. + if ( extra != null ) { + result.extra = new byte[extra.Length]; + Array.Copy(extra, 0, result.extra, 0, extra.Length); + } + + return result; + } + + #endregion + + /// + /// Gets a string representation of this ZipEntry. + /// + /// A readable textual representation of this + public override string ToString() + { + return name; + } + + /// + /// Test a compression method to see if this library + /// supports extracting data compressed with that method + /// + /// The compression method to test. + /// Returns true if the compression method is supported; false otherwise + public static bool IsCompressionMethodSupported(CompressionMethod method) + { + return + ( method == CompressionMethod.Deflated ) || + ( method == CompressionMethod.Stored ); + } + + /// + /// Cleans a name making it conform to Zip file conventions. + /// Devices names ('c:\') and UNC share names ('\\server\share') are removed + /// and forward slashes ('\') are converted to back slashes ('/'). + /// Names are made relative by trimming leading slashes which is compatible + /// with the ZIP naming convention. + /// + /// The name to clean + /// The 'cleaned' name. + /// + /// The Zip name transform class is more flexible. + /// + public static string CleanName(string name) + { + if (name == null) { + return string.Empty; + } + + if (Path.IsPathRooted(name) == true) { + // NOTE: + // for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt + name = name.Substring(Path.GetPathRoot(name).Length); + } + + name = name.Replace(@"\", "/"); + + while ( (name.Length > 0) && (name[0] == '/')) { + name = name.Remove(0, 1); + } + return name; + } + + #region Instance Fields + Known known; + int externalFileAttributes = -1; // contains external attributes (O/S dependant) + + ushort versionMadeBy; // Contains host system and version information + // only relevant for central header entries + + string name; + ulong size; + ulong compressedSize; + ushort versionToExtract; // Version required to extract (library handles <= 2.0) + uint crc; + uint dosTime; + + CompressionMethod method = CompressionMethod.Deflated; + byte[] extra; + string comment; + + int flags; // general purpose bit flags + + long zipFileIndex = -1; // used by ZipFile + long offset; // used by ZipFile and ZipOutputStream + + bool forceZip64_; + byte cryptoCheckValue_; +#if !NET_1_1 && !NETCF_2_0 + int _aesVer; // Version number (2 = AE-2 ?). Assigned but not used. + int _aesEncryptionStrength; // Encryption strength 1 = 128 2 = 192 3 = 256 +#endif + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipEntryFactory.cs b/PCRobot/Utils/ZIP/Zip/ZipEntryFactory.cs new file mode 100644 index 0000000..aa02d2d --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipEntryFactory.cs @@ -0,0 +1,414 @@ +// ZipEntryFactory.cs +// +// Copyright 2006 John Reilly +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// Basic implementation of + /// + public class ZipEntryFactory : IEntryFactory + { + #region Enumerations + /// + /// Defines the possible values to be used for the . + /// + public enum TimeSetting + { + /// + /// Use the recorded LastWriteTime value for the file. + /// + LastWriteTime, + /// + /// Use the recorded LastWriteTimeUtc value for the file + /// + LastWriteTimeUtc, + /// + /// Use the recorded CreateTime value for the file. + /// + CreateTime, + /// + /// Use the recorded CreateTimeUtc value for the file. + /// + CreateTimeUtc, + /// + /// Use the recorded LastAccessTime value for the file. + /// + LastAccessTime, + /// + /// Use the recorded LastAccessTimeUtc value for the file. + /// + LastAccessTimeUtc, + /// + /// Use a fixed value. + /// + /// The actual value used can be + /// specified via the constructor or + /// using the with the setting set + /// to which will use the when this class was constructed. + /// The property can also be used to set this value. + Fixed, + } + #endregion + + #region Constructors + /// + /// Initialise a new instance of the class. + /// + /// A default , and the LastWriteTime for files is used. + public ZipEntryFactory() + { + nameTransform_ = new ZipNameTransform(); + } + + /// + /// Initialise a new instance of using the specified + /// + /// The time setting to use when creating Zip entries. + public ZipEntryFactory(TimeSetting timeSetting) + { + timeSetting_ = timeSetting; + nameTransform_ = new ZipNameTransform(); + } + + /// + /// Initialise a new instance of using the specified + /// + /// The time to set all values to. + public ZipEntryFactory(DateTime time) + { + timeSetting_ = TimeSetting.Fixed; + FixedDateTime = time; + nameTransform_ = new ZipNameTransform(); + } + + #endregion + + #region Properties + /// + /// Get / set the to be used when creating new values. + /// + /// + /// Setting this property to null will cause a default name transform to be used. + /// + public INameTransform NameTransform + { + get { return nameTransform_; } + set + { + if (value == null) { + nameTransform_ = new ZipNameTransform(); + } + else { + nameTransform_ = value; + } + } + } + + /// + /// Get / set the in use. + /// + public TimeSetting Setting + { + get { return timeSetting_; } + set { timeSetting_ = value; } + } + + /// + /// Get / set the value to use when is set to + /// + public DateTime FixedDateTime + { + get { return fixedDateTime_; } + set + { + if (value.Year < 1970) { + throw new ArgumentException("Value is too old to be valid", "value"); + } + fixedDateTime_ = value; + } + } + + /// + /// A bitmask defining the attributes to be retrieved from the actual file. + /// + /// The default is to get all possible attributes from the actual file. + public int GetAttributes + { + get { return getAttributes_; } + set { getAttributes_ = value; } + } + + /// + /// A bitmask defining which attributes are to be set on. + /// + /// By default no attributes are set on. + public int SetAttributes + { + get { return setAttributes_; } + set { setAttributes_ = value; } + } + + /// + /// Get set a value indicating wether unidoce text should be set on. + /// + public bool IsUnicodeText + { + get { return isUnicodeText_; } + set { isUnicodeText_ = value; } + } + + #endregion + + #region IEntryFactory Members + + /// + /// Make a new for a file. + /// + /// The name of the file to create a new entry for. + /// Returns a new based on the . + public ZipEntry MakeFileEntry(string fileName) + { + return MakeFileEntry(fileName, true); + } + + /// + /// Make a new from a name. + /// + /// The name of the file to create a new entry for. + /// If true entry detail is retrieved from the file system if the file exists. + /// Returns a new based on the . + public ZipEntry MakeFileEntry(string fileName, bool useFileSystem) + { + ZipEntry result = new ZipEntry(nameTransform_.TransformFile(fileName)); + result.IsUnicodeText = isUnicodeText_; + + int externalAttributes = 0; + bool useAttributes = (setAttributes_ != 0); + + FileInfo fi = null; + if (useFileSystem) + { + fi = new FileInfo(fileName); + } + + if ((fi != null) && fi.Exists) + { + switch (timeSetting_) + { + case TimeSetting.CreateTime: + result.DateTime = fi.CreationTime; + break; + + case TimeSetting.CreateTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.CreationTime.ToUniversalTime(); +#else + result.DateTime = fi.CreationTimeUtc; +#endif + break; + + case TimeSetting.LastAccessTime: + result.DateTime = fi.LastAccessTime; + break; + + case TimeSetting.LastAccessTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.LastAccessTime.ToUniversalTime(); +#else + result.DateTime = fi.LastAccessTimeUtc; +#endif + break; + + case TimeSetting.LastWriteTime: + result.DateTime = fi.LastWriteTime; + break; + + case TimeSetting.LastWriteTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.LastWriteTime.ToUniversalTime(); +#else + result.DateTime = fi.LastWriteTimeUtc; +#endif + break; + + case TimeSetting.Fixed: + result.DateTime = fixedDateTime_; + break; + + default: + throw new ZipException("Unhandled time setting in MakeFileEntry"); + } + + result.Size = fi.Length; + + useAttributes = true; + externalAttributes = ((int)fi.Attributes & getAttributes_); + } + else + { + if (timeSetting_ == TimeSetting.Fixed) + { + result.DateTime = fixedDateTime_; + } + } + + if (useAttributes) + { + externalAttributes |= setAttributes_; + result.ExternalFileAttributes = externalAttributes; + } + + return result; + } + + /// + /// Make a new for a directory. + /// + /// The raw untransformed name for the new directory + /// Returns a new representing a directory. + public ZipEntry MakeDirectoryEntry(string directoryName) + { + return MakeDirectoryEntry(directoryName, true); + } + + /// + /// Make a new for a directory. + /// + /// The raw untransformed name for the new directory + /// If true entry detail is retrieved from the file system if the file exists. + /// Returns a new representing a directory. + public ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem) + { + + ZipEntry result = new ZipEntry(nameTransform_.TransformDirectory(directoryName)); + result.IsUnicodeText = isUnicodeText_; + result.Size = 0; + + int externalAttributes = 0; + + DirectoryInfo di = null; + + if (useFileSystem) + { + di = new DirectoryInfo(directoryName); + } + + + if ((di != null) && di.Exists) + { + switch (timeSetting_) + { + case TimeSetting.CreateTime: + result.DateTime = di.CreationTime; + break; + + case TimeSetting.CreateTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.CreationTime.ToUniversalTime(); +#else + result.DateTime = di.CreationTimeUtc; +#endif + break; + + case TimeSetting.LastAccessTime: + result.DateTime = di.LastAccessTime; + break; + + case TimeSetting.LastAccessTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.LastAccessTime.ToUniversalTime(); +#else + result.DateTime = di.LastAccessTimeUtc; +#endif + break; + + case TimeSetting.LastWriteTime: + result.DateTime = di.LastWriteTime; + break; + + case TimeSetting.LastWriteTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.LastWriteTime.ToUniversalTime(); +#else + result.DateTime = di.LastWriteTimeUtc; +#endif + break; + + case TimeSetting.Fixed: + result.DateTime = fixedDateTime_; + break; + + default: + throw new ZipException("Unhandled time setting in MakeDirectoryEntry"); + } + + externalAttributes = ((int)di.Attributes & getAttributes_); + } + else + { + if (timeSetting_ == TimeSetting.Fixed) + { + result.DateTime = fixedDateTime_; + } + } + + // Always set directory attribute on. + externalAttributes |= (setAttributes_ | 16); + result.ExternalFileAttributes = externalAttributes; + + return result; + } + + #endregion + + #region Instance Fields + INameTransform nameTransform_; + DateTime fixedDateTime_ = DateTime.Now; + TimeSetting timeSetting_; + bool isUnicodeText_; + + int getAttributes_ = -1; + int setAttributes_; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipException.cs b/PCRobot/Utils/ZIP/Zip/ZipException.cs new file mode 100644 index 0000000..1cf4f16 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipException.cs @@ -0,0 +1,94 @@ +// ZipException.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Represents exception conditions specific to Zip archive handling + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class ZipException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected ZipException(SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } +#endif + + /// + /// Initializes a new instance of the ZipException class. + /// + public ZipException() + { + } + + /// + /// Initializes a new instance of the ZipException class with a specified error message. + /// + /// The error message that explains the reason for the exception. + public ZipException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of ZipException. + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public ZipException(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipExtraData.cs b/PCRobot/Utils/ZIP/Zip/ZipExtraData.cs new file mode 100644 index 0000000..aaeb0a6 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipExtraData.cs @@ -0,0 +1,987 @@ +// +// ZipExtraData.cs +// +// Copyright 2004-2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Zip +{ + // TODO: Sort out wether tagged data is useful and what a good implementation might look like. + // Its just a sketch of an idea at the moment. + + /// + /// ExtraData tagged value interface. + /// + public interface ITaggedData + { + /// + /// Get the ID for this tagged data value. + /// + short TagID { get; } + + /// + /// Set the contents of this instance from the data passed. + /// + /// The data to extract contents from. + /// The offset to begin extracting data from. + /// The number of bytes to extract. + void SetData(byte[] data, int offset, int count); + + /// + /// Get the data representing this instance. + /// + /// Returns the data for this instance. + byte[] GetData(); + } + + /// + /// A raw binary tagged value + /// + public class RawTaggedData : ITaggedData + { + /// + /// Initialise a new instance. + /// + /// The tag ID. + public RawTaggedData(short tag) + { + _tag = tag; + } + + #region ITaggedData Members + + /// + /// Get the ID for this tagged data value. + /// + public short TagID + { + get { return _tag; } + set { _tag = value; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int offset, int count) + { + if( data==null ) + { + throw new ArgumentNullException("data"); + } + + _data=new byte[count]; + Array.Copy(data, offset, _data, 0, count); + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + return _data; + } + + #endregion + + /// + /// Get /set the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] Data + { + get { return _data; } + set { _data=value; } + } + + #region Instance Fields + /// + /// The tag ID for this instance. + /// + short _tag; + + byte[] _data; + #endregion + } + + /// + /// Class representing extended unix date time values. + /// + public class ExtendedUnixData : ITaggedData + { + /// + /// Flags indicate which values are included in this instance. + /// + [Flags] + public enum Flags : byte + { + /// + /// The modification time is included + /// + ModificationTime = 0x01, + + /// + /// The access time is included + /// + AccessTime = 0x02, + + /// + /// The create time is included. + /// + CreateTime = 0x04, + } + + #region ITaggedData Members + + /// + /// Get the ID + /// + public short TagID + { + get { return 0x5455; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int index, int count) + { + using (MemoryStream ms = new MemoryStream(data, index, count, false)) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + // bit 0 if set, modification time is present + // bit 1 if set, access time is present + // bit 2 if set, creation time is present + + _flags = (Flags)helperStream.ReadByte(); + if (((_flags & Flags.ModificationTime) != 0) && (count >= 5)) + { + int iTime = helperStream.ReadLEInt(); + + _modificationTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + + if ((_flags & Flags.AccessTime) != 0) + { + int iTime = helperStream.ReadLEInt(); + + _lastAccessTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + + if ((_flags & Flags.CreateTime) != 0) + { + int iTime = helperStream.ReadLEInt(); + + _createTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + } + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + using (MemoryStream ms = new MemoryStream()) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.IsStreamOwner = false; + helperStream.WriteByte((byte)_flags); // Flags + if ( (_flags & Flags.ModificationTime) != 0) { + TimeSpan span = _modificationTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + if ( (_flags & Flags.AccessTime) != 0) { + TimeSpan span = _lastAccessTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + if ( (_flags & Flags.CreateTime) != 0) { + TimeSpan span = _createTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + return ms.ToArray(); + } + } + + #endregion + + /// + /// Test a value to see if is valid and can be represented here. + /// + /// The value to test. + /// Returns true if the value is valid and can be represented; false if not. + /// The standard Unix time is a signed integer data type, directly encoding the Unix time number, + /// which is the number of seconds since 1970-01-01. + /// Being 32 bits means the values here cover a range of about 136 years. + /// The minimum representable time is 1901-12-13 20:45:52, + /// and the maximum representable time is 2038-01-19 03:14:07. + /// + public static bool IsValidValue(DateTime value) + { + return (( value >= new DateTime(1901, 12, 13, 20, 45, 52)) || + ( value <= new DateTime(2038, 1, 19, 03, 14, 07) )); + } + + /// + /// Get /set the Modification Time + /// + /// + /// + public DateTime ModificationTime + { + get { return _modificationTime; } + set + { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.ModificationTime; + _modificationTime=value; + } + } + + /// + /// Get / set the Access Time + /// + /// + /// + public DateTime AccessTime + { + get { return _lastAccessTime; } + set { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.AccessTime; + _lastAccessTime=value; + } + } + + /// + /// Get / Set the Create Time + /// + /// + /// + public DateTime CreateTime + { + get { return _createTime; } + set { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.CreateTime; + _createTime=value; + } + } + + /// + /// Get/set the values to include. + /// + Flags Include + { + get { return _flags; } + set { _flags = value; } + } + + #region Instance Fields + Flags _flags; + DateTime _modificationTime = new DateTime(1970,1,1); + DateTime _lastAccessTime = new DateTime(1970, 1, 1); + DateTime _createTime = new DateTime(1970, 1, 1); + #endregion + } + + /// + /// Class handling NT date time values. + /// + public class NTTaggedData : ITaggedData + { + /// + /// Get the ID for this tagged data value. + /// + public short TagID + { + get { return 10; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int index, int count) + { + using (MemoryStream ms = new MemoryStream(data, index, count, false)) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.ReadLEInt(); // Reserved + while (helperStream.Position < helperStream.Length) + { + int ntfsTag = helperStream.ReadLEShort(); + int ntfsLength = helperStream.ReadLEShort(); + if (ntfsTag == 1) + { + if (ntfsLength >= 24) + { + long lastModificationTicks = helperStream.ReadLELong(); + _lastModificationTime = DateTime.FromFileTime(lastModificationTicks); + + long lastAccessTicks = helperStream.ReadLELong(); + _lastAccessTime = DateTime.FromFileTime(lastAccessTicks); + + long createTimeTicks = helperStream.ReadLELong(); + _createTime = DateTime.FromFileTime(createTimeTicks); + } + break; + } + else + { + // An unknown NTFS tag so simply skip it. + helperStream.Seek(ntfsLength, SeekOrigin.Current); + } + } + } + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + using (MemoryStream ms = new MemoryStream()) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.IsStreamOwner = false; + helperStream.WriteLEInt(0); // Reserved + helperStream.WriteLEShort(1); // Tag + helperStream.WriteLEShort(24); // Length = 3 x 8. + helperStream.WriteLELong(_lastModificationTime.ToFileTime()); + helperStream.WriteLELong(_lastAccessTime.ToFileTime()); + helperStream.WriteLELong(_createTime.ToFileTime()); + return ms.ToArray(); + } + } + + /// + /// Test a valuie to see if is valid and can be represented here. + /// + /// The value to test. + /// Returns true if the value is valid and can be represented; false if not. + /// + /// NTFS filetimes are 64-bit unsigned integers, stored in Intel + /// (least significant byte first) byte order. They determine the + /// number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", + /// which is "01-Jan-1601 00:00:00 UTC". 28 May 60056 is the upper limit + /// + public static bool IsValidValue(DateTime value) + { + bool result = true; + try + { + value.ToFileTimeUtc(); + } + catch + { + result = false; + } + return result; + } + + /// + /// Get/set the last modification time. + /// + public DateTime LastModificationTime + { + get { return _lastModificationTime; } + set { + if (! IsValidValue(value)) + { + throw new ArgumentOutOfRangeException("value"); + } + _lastModificationTime = value; + } + } + + /// + /// Get /set the create time + /// + public DateTime CreateTime + { + get { return _createTime; } + set { + if ( !IsValidValue(value)) { + throw new ArgumentOutOfRangeException("value"); + } + _createTime = value; + } + } + + /// + /// Get /set the last access time. + /// + public DateTime LastAccessTime + { + get { return _lastAccessTime; } + set { + if (!IsValidValue(value)) { + throw new ArgumentOutOfRangeException("value"); + } + _lastAccessTime = value; + } + } + + #region Instance Fields + DateTime _lastAccessTime = DateTime.FromFileTime(0); + DateTime _lastModificationTime = DateTime.FromFileTime(0); + DateTime _createTime = DateTime.FromFileTime(0); + #endregion + } + + /// + /// A factory that creates tagged data instances. + /// + interface ITaggedDataFactory + { + /// + /// Get data for a specific tag value. + /// + /// The tag ID to find. + /// The data to search. + /// The offset to begin extracting data from. + /// The number of bytes to extract. + /// The located value found, or null if not found. + ITaggedData Create(short tag, byte[] data, int offset, int count); + } + + /// + /// + /// A class to handle the extra data field for Zip entries + /// + /// + /// Extra data contains 0 or more values each prefixed by a header tag and length. + /// They contain zero or more bytes of actual data. + /// The data is held internally using a copy on write strategy. This is more efficient but + /// means that for extra data created by passing in data can have the values modified by the caller + /// in some circumstances. + /// + sealed public class ZipExtraData : IDisposable + { + #region Constructors + /// + /// Initialise a default instance. + /// + public ZipExtraData() + { + Clear(); + } + + /// + /// Initialise with known extra data. + /// + /// The extra data. + public ZipExtraData(byte[] data) + { + if ( data == null ) + { + _data = new byte[0]; + } + else + { + _data = data; + } + } + #endregion + + /// + /// Get the raw extra data value + /// + /// Returns the raw byte[] extra data this instance represents. + public byte[] GetEntryData() + { + if ( Length > ushort.MaxValue ) { + throw new ZipException("Data exceeds maximum length"); + } + + return (byte[])_data.Clone(); + } + + /// + /// Clear the stored data. + /// + public void Clear() + { + if ( (_data == null) || (_data.Length != 0) ) { + _data = new byte[0]; + } + } + + /// + /// Gets the current extra data length. + /// + public int Length + { + get { return _data.Length; } + } + + /// + /// Get a read-only for the associated tag. + /// + /// The tag to locate data for. + /// Returns a containing tag data or null if no tag was found. + public Stream GetStreamForTag(int tag) + { + Stream result = null; + if ( Find(tag) ) { + result = new MemoryStream(_data, _index, _readValueLength, false); + } + return result; + } + + /// + /// Get the tagged data for a tag. + /// + /// The tag to search for. + /// Returns a tagged value or null if none found. + private ITaggedData GetData(short tag) + { + ITaggedData result = null; + if (Find(tag)) + { + result = Create(tag, _data, _readValueStart, _readValueLength); + } + return result; + } + + static ITaggedData Create(short tag, byte[] data, int offset, int count) + { + ITaggedData result = null; + switch ( tag ) + { + case 0x000A: + result = new NTTaggedData(); + break; + case 0x5455: + result = new ExtendedUnixData(); + break; + default: + result = new RawTaggedData(tag); + break; + } + result.SetData(data, offset, count); + return result; + } + + /// + /// Get the length of the last value found by + /// + /// This is only valid if has previously returned true. + public int ValueLength + { + get { return _readValueLength; } + } + + /// + /// Get the index for the current read value. + /// + /// This is only valid if has previously returned true. + /// Initially the result will be the index of the first byte of actual data. The value is updated after calls to + /// , and . + public int CurrentReadIndex + { + get { return _index; } + } + + /// + /// Get the number of bytes remaining to be read for the current value; + /// + public int UnreadCount + { + get + { + if ((_readValueStart > _data.Length) || + (_readValueStart < 4) ) { + throw new ZipException("Find must be called before calling a Read method"); + } + + return _readValueStart + _readValueLength - _index; + } + } + + /// + /// Find an extra data value + /// + /// The identifier for the value to find. + /// Returns true if the value was found; false otherwise. + public bool Find(int headerID) + { + _readValueStart = _data.Length; + _readValueLength = 0; + _index = 0; + + int localLength = _readValueStart; + int localTag = headerID - 1; + + // Trailing bytes that cant make up an entry (as there arent enough + // bytes for a tag and length) are ignored! + while ( (localTag != headerID) && (_index < _data.Length - 3) ) { + localTag = ReadShortInternal(); + localLength = ReadShortInternal(); + if ( localTag != headerID ) { + _index += localLength; + } + } + + bool result = (localTag == headerID) && ((_index + localLength) <= _data.Length); + + if ( result ) { + _readValueStart = _index; + _readValueLength = localLength; + } + + return result; + } + + /// + /// Add a new entry to extra data. + /// + /// The value to add. + public void AddEntry(ITaggedData taggedData) + { + if (taggedData == null) + { + throw new ArgumentNullException("taggedData"); + } + AddEntry(taggedData.TagID, taggedData.GetData()); + } + + /// + /// Add a new entry to extra data + /// + /// The ID for this entry. + /// The data to add. + /// If the ID already exists its contents are replaced. + public void AddEntry(int headerID, byte[] fieldData) + { + if ( (headerID > ushort.MaxValue) || (headerID < 0)) { + throw new ArgumentOutOfRangeException("headerID"); + } + + int addLength = (fieldData == null) ? 0 : fieldData.Length; + + if ( addLength > ushort.MaxValue ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("fieldData"); +#else + throw new ArgumentOutOfRangeException("fieldData", "exceeds maximum length"); +#endif + } + + // Test for new length before adjusting data. + int newLength = _data.Length + addLength + 4; + + if ( Find(headerID) ) + { + newLength -= (ValueLength + 4); + } + + if ( newLength > ushort.MaxValue ) { + throw new ZipException("Data exceeds maximum length"); + } + + Delete(headerID); + + byte[] newData = new byte[newLength]; + _data.CopyTo(newData, 0); + int index = _data.Length; + _data = newData; + SetShort(ref index, headerID); + SetShort(ref index, addLength); + if ( fieldData != null ) { + fieldData.CopyTo(newData, index); + } + } + + /// + /// Start adding a new entry. + /// + /// Add data using , , , or . + /// The new entry is completed and actually added by calling + /// + public void StartNewEntry() + { + _newEntry = new MemoryStream(); + } + + /// + /// Add entry data added since using the ID passed. + /// + /// The identifier to use for this entry. + public void AddNewEntry(int headerID) + { + byte[] newData = _newEntry.ToArray(); + _newEntry = null; + AddEntry(headerID, newData); + } + + /// + /// Add a byte of data to the pending new entry. + /// + /// The byte to add. + /// + public void AddData(byte data) + { + _newEntry.WriteByte(data); + } + + /// + /// Add data to a pending new entry. + /// + /// The data to add. + /// + public void AddData(byte[] data) + { + if ( data == null ) { + throw new ArgumentNullException("data"); + } + + _newEntry.Write(data, 0, data.Length); + } + + /// + /// Add a short value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeShort(int toAdd) + { + unchecked { + _newEntry.WriteByte(( byte )toAdd); + _newEntry.WriteByte(( byte )(toAdd >> 8)); + } + } + + /// + /// Add an integer value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeInt(int toAdd) + { + unchecked { + AddLeShort(( short )toAdd); + AddLeShort(( short )(toAdd >> 16)); + } + } + + /// + /// Add a long value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeLong(long toAdd) + { + unchecked { + AddLeInt(( int )(toAdd & 0xffffffff)); + AddLeInt(( int )(toAdd >> 32)); + } + } + + /// + /// Delete an extra data field. + /// + /// The identifier of the field to delete. + /// Returns true if the field was found and deleted. + public bool Delete(int headerID) + { + bool result = false; + + if ( Find(headerID) ) { + result = true; + int trueStart = _readValueStart - 4; + + byte[] newData = new byte[_data.Length - (ValueLength + 4)]; + Array.Copy(_data, 0, newData, 0, trueStart); + + int trueEnd = trueStart + ValueLength + 4; + Array.Copy(_data, trueEnd, newData, trueStart, _data.Length - trueEnd); + _data = newData; + } + return result; + } + + #region Reading Support + /// + /// Read a long in little endian form from the last found data value + /// + /// Returns the long value read. + public long ReadLong() + { + ReadCheck(8); + return (ReadInt() & 0xffffffff) | ((( long )ReadInt()) << 32); + } + + /// + /// Read an integer in little endian form from the last found data value. + /// + /// Returns the integer read. + public int ReadInt() + { + ReadCheck(4); + + int result = _data[_index] + (_data[_index + 1] << 8) + + (_data[_index + 2] << 16) + (_data[_index + 3] << 24); + _index += 4; + return result; + } + + /// + /// Read a short value in little endian form from the last found data value. + /// + /// Returns the short value read. + public int ReadShort() + { + ReadCheck(2); + int result = _data[_index] + (_data[_index + 1] << 8); + _index += 2; + return result; + } + + /// + /// Read a byte from an extra data + /// + /// The byte value read or -1 if the end of data has been reached. + public int ReadByte() + { + int result = -1; + if ( (_index < _data.Length) && (_readValueStart + _readValueLength > _index) ) { + result = _data[_index]; + _index += 1; + } + return result; + } + + /// + /// Skip data during reading. + /// + /// The number of bytes to skip. + public void Skip(int amount) + { + ReadCheck(amount); + _index += amount; + } + + void ReadCheck(int length) + { + if ((_readValueStart > _data.Length) || + (_readValueStart < 4) ) { + throw new ZipException("Find must be called before calling a Read method"); + } + + if (_index > _readValueStart + _readValueLength - length ) { + throw new ZipException("End of extra data"); + } + + if ( _index + length < 4 ) { + throw new ZipException("Cannot read before start of tag"); + } + } + + /// + /// Internal form of that reads data at any location. + /// + /// Returns the short value read. + int ReadShortInternal() + { + if ( _index > _data.Length - 2) { + throw new ZipException("End of extra data"); + } + + int result = _data[_index] + (_data[_index + 1] << 8); + _index += 2; + return result; + } + + void SetShort(ref int index, int source) + { + _data[index] = (byte)source; + _data[index + 1] = (byte)(source >> 8); + index += 2; + } + + #endregion + + #region IDisposable Members + + /// + /// Dispose of this instance. + /// + public void Dispose() + { + if ( _newEntry != null ) { + _newEntry.Close(); + } + } + + #endregion + + #region Instance Fields + int _index; + int _readValueStart; + int _readValueLength; + + MemoryStream _newEntry; + byte[] _data; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipFile.cs b/PCRobot/Utils/ZIP/Zip/ZipFile.cs new file mode 100644 index 0000000..7be203c --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipFile.cs @@ -0,0 +1,4487 @@ +// ZipFile.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2009-12-22 Z-1649 Added AES support +// 2010-03-02 Z-1650 Fixed updating ODT archives in memory. Exposed exceptions in updating. +// 2010-05-25 Z-1663 Fixed exception when testing local header compressed size of -1 + +using System; +using System.Collections; +using System.IO; +using System.Text; +using System.Globalization; + +#if !NETCF_1_0 +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Encryption; +#endif + +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + #region Keys Required Event Args + /// + /// Arguments used with KeysRequiredEvent + /// + public class KeysRequiredEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The name of the file for which keys are required. + public KeysRequiredEventArgs(string name) + { + fileName = name; + } + + /// + /// Initialise a new instance of + /// + /// The name of the file for which keys are required. + /// The current key value. + public KeysRequiredEventArgs(string name, byte[] keyValue) + { + fileName = name; + key = keyValue; + } + + #endregion + #region Properties + /// + /// Gets the name of the file for which keys are required. + /// + public string FileName + { + get { return fileName; } + } + + /// + /// Gets or sets the key value + /// + public byte[] Key + { + get { return key; } + set { key = value; } + } + #endregion + + #region Instance Fields + string fileName; + byte[] key; + #endregion + } + #endregion + + #region Test Definitions + /// + /// The strategy to apply to testing. + /// + public enum TestStrategy + { + /// + /// Find the first error only. + /// + FindFirstError, + /// + /// Find all possible errors. + /// + FindAllErrors, + } + + /// + /// The operation in progress reported by a during testing. + /// + /// TestArchive + public enum TestOperation + { + /// + /// Setting up testing. + /// + Initialising, + + /// + /// Testing an individual entries header + /// + EntryHeader, + + /// + /// Testing an individual entries data + /// + EntryData, + + /// + /// Testing an individual entry has completed. + /// + EntryComplete, + + /// + /// Running miscellaneous tests + /// + MiscellaneousTests, + + /// + /// Testing is complete + /// + Complete, + } + + /// + /// Status returned returned by during testing. + /// + /// TestArchive + public class TestStatus + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The this status applies to. + public TestStatus(ZipFile file) + { + file_ = file; + } + #endregion + + #region Properties + + /// + /// Get the current in progress. + /// + public TestOperation Operation + { + get { return operation_; } + } + + /// + /// Get the this status is applicable to. + /// + public ZipFile File + { + get { return file_; } + } + + /// + /// Get the current/last entry tested. + /// + public ZipEntry Entry + { + get { return entry_; } + } + + /// + /// Get the number of errors detected so far. + /// + public int ErrorCount + { + get { return errorCount_; } + } + + /// + /// Get the number of bytes tested so far for the current entry. + /// + public long BytesTested + { + get { return bytesTested_; } + } + + /// + /// Get a value indicating wether the last entry test was valid. + /// + public bool EntryValid + { + get { return entryValid_; } + } + #endregion + + #region Internal API + internal void AddError() + { + errorCount_++; + entryValid_ = false; + } + + internal void SetOperation(TestOperation operation) + { + operation_ = operation; + } + + internal void SetEntry(ZipEntry entry) + { + entry_ = entry; + entryValid_ = true; + bytesTested_ = 0; + } + + internal void SetBytesTested(long value) + { + bytesTested_ = value; + } + #endregion + + #region Instance Fields + ZipFile file_; + ZipEntry entry_; + bool entryValid_; + int errorCount_; + long bytesTested_; + TestOperation operation_; + #endregion + } + + /// + /// Delegate invoked during testing if supplied indicating current progress and status. + /// + /// If the message is non-null an error has occured. If the message is null + /// the operation as found in status has started. + public delegate void ZipTestResultHandler(TestStatus status, string message); + #endregion + + #region Update Definitions + /// + /// The possible ways of applying updates to an archive. + /// + public enum FileUpdateMode + { + /// + /// Perform all updates on temporary files ensuring that the original file is saved. + /// + Safe, + /// + /// Update the archive directly, which is faster but less safe. + /// + Direct, + } + #endregion + + #region ZipFile Class + /// + /// This class represents a Zip archive. You can ask for the contained + /// entries, or get an input stream for a file entry. The entry is + /// automatically decompressed. + /// + /// You can also update the archive adding or deleting entries. + /// + /// This class is thread safe for input: You can open input streams for arbitrary + /// entries in different threads. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// + /// + /// using System; + /// using System.Text; + /// using System.Collections; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// static public void Main(string[] args) + /// { + /// using (ZipFile zFile = new ZipFile(args[0])) { + /// Console.WriteLine("Listing of : " + zFile.Name); + /// Console.WriteLine(""); + /// Console.WriteLine("Raw Size Size Date Time Name"); + /// Console.WriteLine("-------- -------- -------- ------ ---------"); + /// foreach (ZipEntry e in zFile) { + /// if ( e.IsFile ) { + /// DateTime d = e.DateTime; + /// Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize, + /// d.ToString("dd-MM-yy"), d.ToString("HH:mm"), + /// e.Name); + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipFile : IEnumerable, IDisposable + { + #region KeyHandling + + /// + /// Delegate for handling keys/password setting during compresion/decompression. + /// + public delegate void KeysRequiredEventHandler( + object sender, + KeysRequiredEventArgs e + ); + + /// + /// Event handler for handling encryption keys. + /// + public KeysRequiredEventHandler KeysRequired; + + /// + /// Handles getting of encryption keys when required. + /// + /// The file for which encryption keys are required. + void OnKeysRequired(string fileName) + { + if (KeysRequired != null) { + KeysRequiredEventArgs krea = new KeysRequiredEventArgs(fileName, key); + KeysRequired(this, krea); + key = krea.Key; + } + } + + /// + /// Get/set the encryption key value. + /// + byte[] Key + { + get { return key; } + set { key = value; } + } + +#if !NETCF_1_0 + /// + /// Password to be used for encrypting/decrypting files. + /// + /// Set to null if no password is required. + public string Password + { + set + { + if ( (value == null) || (value.Length == 0) ) { + key = null; + } + else { + rawPassword_ = value; + key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(value)); + } + } + } +#endif + + /// + /// Get a value indicating wether encryption keys are currently available. + /// + bool HaveKeys + { + get { return key != null; } + } + #endregion + + #region Constructors + /// + /// Opens a Zip file with the given name for reading. + /// + /// The name of the file to open. + /// The argument supplied is null. + /// + /// An i/o error occurs + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(string name) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + name_ = name; + + baseStream_ = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read); + isStreamOwner = true; + + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } + + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// The supplied argument is null. + /// + /// An i/o error occurs. + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(FileStream file) + { + if ( file == null ) { + throw new ArgumentNullException("file"); + } + + if ( !file.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "file"); + } + + baseStream_ = file; + name_ = file.Name; + isStreamOwner = true; + + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } + + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// + /// An i/o error occurs + /// + /// + /// The stream doesn't contain a valid zip archive.
+ ///
+ /// + /// The stream doesnt support seeking. + /// + /// + /// The stream argument is null. + /// + public ZipFile(Stream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + if ( !stream.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "stream"); + } + + baseStream_ = stream; + isStreamOwner = true; + + if ( baseStream_.Length > 0 ) { + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } else { + entries_ = new ZipEntry[0]; + isNewArchive_ = true; + } + } + + /// + /// Initialises a default instance with no entries and no file storage. + /// + internal ZipFile() + { + entries_ = new ZipEntry[0]; + isNewArchive_ = true; + } + + #endregion + + #region Destructors and Closing + /// + /// Finalize this instance. + /// + ~ZipFile() + { + Dispose(false); + } + + /// + /// Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. + /// Once closed, no further instance methods should be called. + /// + /// + /// An i/o error occurs. + /// + public void Close() + { + DisposeInternal(true); + GC.SuppressFinalize(this); + } + + #endregion + + #region Creators + /// + /// Create a new whose data will be stored in a file. + /// + /// The name of the archive to create. + /// Returns the newly created + /// is null + public static ZipFile Create(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + FileStream fs = File.Create(fileName); + + ZipFile result = new ZipFile(); + result.name_ = fileName; + result.baseStream_ = fs; + result.isStreamOwner = true; + return result; + } + + /// + /// Create a new whose data will be stored on a stream. + /// + /// The stream providing data storage. + /// Returns the newly created + /// is null + /// doesnt support writing. + public static ZipFile Create(Stream outStream) + { + if ( outStream == null ) { + throw new ArgumentNullException("outStream"); + } + + if ( !outStream.CanWrite ) { + throw new ArgumentException("Stream is not writeable", "outStream"); + } + + if ( !outStream.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "outStream"); + } + + ZipFile result = new ZipFile(); + result.baseStream_ = outStream; + return result; + } + + #endregion + + #region Properties + /// + /// Get/set a flag indicating if the underlying stream is owned by the ZipFile instance. + /// If the flag is true then the stream will be closed when Close is called. + /// + /// + /// The default value is true in all cases. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Get a value indicating wether + /// this archive is embedded in another file or not. + /// + public bool IsEmbeddedArchive + { + // Not strictly correct in all circumstances currently + get { return offsetOfFirstEntry > 0; } + } + + /// + /// Get a value indicating that this archive is a new one. + /// + public bool IsNewArchive + { + get { return isNewArchive_; } + } + + /// + /// Gets the comment for the zip file. + /// + public string ZipFileComment + { + get { return comment_; } + } + + /// + /// Gets the name of this zip file. + /// + public string Name + { + get { return name_; } + } + + /// + /// Gets the number of entries in this zip file. + /// + /// + /// The Zip file has been closed. + /// + [Obsolete("Use the Count property instead")] + public int Size + { + get + { + return entries_.Length; + } + } + + /// + /// Get the number of entries contained in this . + /// + public long Count + { + get + { + return entries_.Length; + } + } + + /// + /// Indexer property for ZipEntries + /// + [System.Runtime.CompilerServices.IndexerNameAttribute("EntryByIndex")] + public ZipEntry this[int index] + { + get { + return (ZipEntry) entries_[index].Clone(); + } + } + + #endregion + + #region Input Handling + /// + /// Gets an enumerator for the Zip entries in this Zip file. + /// + /// Returns an for this archive. + /// + /// The Zip file has been closed. + /// + public IEnumerator GetEnumerator() + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + return new ZipEntryEnumerator(entries_); + } + + /// + /// Return the index of the entry with a matching name + /// + /// Entry name to find + /// If true the comparison is case insensitive + /// The index position of the matching entry or -1 if not found + /// + /// The Zip file has been closed. + /// + public int FindEntry(string name, bool ignoreCase) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + // TODO: This will be slow as the next ice age for huge archives! + for (int i = 0; i < entries_.Length; i++) { + if (string.Compare(name, entries_[i].Name, ignoreCase, CultureInfo.InvariantCulture) == 0) { + return i; + } + } + return -1; + } + + /// + /// Searches for a zip entry in this archive with the given name. + /// String comparisons are case insensitive + /// + /// + /// The name to find. May contain directory components separated by slashes ('/'). + /// + /// + /// A clone of the zip entry, or null if no entry with that name exists. + /// + /// + /// The Zip file has been closed. + /// + public ZipEntry GetEntry(string name) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + int index = FindEntry(name, true); + return (index >= 0) ? (ZipEntry) entries_[index].Clone() : null; + } + + /// + /// Gets an input stream for reading the given zip entry data in an uncompressed form. + /// Normally the should be an entry returned by GetEntry(). + /// + /// The to obtain a data for + /// An input containing data for this + /// + /// The ZipFile has already been closed + /// + /// + /// The compression method for the entry is unknown + /// + /// + /// The entry is not found in the ZipFile + /// + public Stream GetInputStream(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + long index = entry.ZipFileIndex; + if ( (index < 0) || (index >= entries_.Length) || (entries_[index].Name != entry.Name) ) { + index = FindEntry(entry.Name, true); + if (index < 0) { + throw new ZipException("Entry cannot be found"); + } + } + return GetInputStream(index); + } + + /// + /// Creates an input stream reading a zip entry + /// + /// The index of the entry to obtain an input stream for. + /// + /// An input containing data for this + /// + /// + /// The ZipFile has already been closed + /// + /// + /// The compression method for the entry is unknown + /// + /// + /// The entry is not found in the ZipFile + /// + public Stream GetInputStream(long entryIndex) + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + long start = LocateEntry(entries_[entryIndex]); + CompressionMethod method = entries_[entryIndex].CompressionMethod; + Stream result = new PartialInputStream(this, start, entries_[entryIndex].CompressedSize); + + if (entries_[entryIndex].IsCrypted == true) { +#if NETCF_1_0 + throw new ZipException("decryption not supported for Compact Framework 1.0"); +#else + result = CreateAndInitDecryptionStream(result, entries_[entryIndex]); + if (result == null) { + throw new ZipException("Unable to decrypt this entry"); + } +#endif + } + + switch (method) { + case CompressionMethod.Stored: + // read as is. + break; + + case CompressionMethod.Deflated: + // No need to worry about ownership and closing as underlying stream close does nothing. + result = new InflaterInputStream(result, new Inflater(true)); + break; + + default: + throw new ZipException("Unsupported compression method " + method); + } + + return result; + } + + #endregion + + #region Archive Testing + /// + /// Test an archive for integrity/validity + /// + /// Perform low level data Crc check + /// true if all tests pass, false otherwise + /// Testing will terminate on the first error found. + public bool TestArchive(bool testData) + { + return TestArchive(testData, TestStrategy.FindFirstError, null); + } + + /// + /// Test an archive for integrity/validity + /// + /// Perform low level data Crc check + /// The to apply. + /// The handler to call during testing. + /// true if all tests pass, false otherwise + /// The object has already been closed. + public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandler resultHandler) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + TestStatus status = new TestStatus(this); + + if ( resultHandler != null ) { + resultHandler(status, null); + } + + HeaderTest test = testData ? (HeaderTest.Header | HeaderTest.Extract) : HeaderTest.Header; + + bool testing = true; + + try { + int entryIndex = 0; + + while ( testing && (entryIndex < Count) ) { + if ( resultHandler != null ) { + status.SetEntry(this[entryIndex]); + status.SetOperation(TestOperation.EntryHeader); + resultHandler(status, null); + } + + try { + TestLocalHeader(this[entryIndex], test); + } + catch(ZipException ex) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, + string.Format("Exception during test - '{0}'", ex.Message)); + } + + if ( strategy == TestStrategy.FindFirstError ) { + testing = false; + } + } + + if ( testing && testData && this[entryIndex].IsFile ) { + if ( resultHandler != null ) { + status.SetOperation(TestOperation.EntryData); + resultHandler(status, null); + } + + Crc32 crc = new Crc32(); + + using (Stream entryStream = this.GetInputStream(this[entryIndex])) + { + + byte[] buffer = new byte[4096]; + long totalBytes = 0; + int bytesRead; + while ((bytesRead = entryStream.Read(buffer, 0, buffer.Length)) > 0) + { + crc.Update(buffer, 0, bytesRead); + + if (resultHandler != null) + { + totalBytes += bytesRead; + status.SetBytesTested(totalBytes); + resultHandler(status, null); + } + } + } + + if (this[entryIndex].Crc != crc.Value) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, "CRC mismatch"); + } + + if ( strategy == TestStrategy.FindFirstError ) { + testing = false; + } + } + + if (( this[entryIndex].Flags & (int)GeneralBitFlags.Descriptor) != 0 ) { + ZipHelperStream helper = new ZipHelperStream(baseStream_); + DescriptorData data = new DescriptorData(); + helper.ReadDataDescriptor(this[entryIndex].LocalHeaderRequiresZip64, data); + if (this[entryIndex].Crc != data.Crc) { + status.AddError(); + } + + if (this[entryIndex].CompressedSize != data.CompressedSize) { + status.AddError(); + } + + if (this[entryIndex].Size != data.Size) { + status.AddError(); + } + } + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.EntryComplete); + resultHandler(status, null); + } + + entryIndex += 1; + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.MiscellaneousTests); + resultHandler(status, null); + } + + // TODO: the 'Corrina Johns' test where local headers are missing from + // the central directory. They are therefore invisible to many archivers. + } + catch (Exception ex) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, string.Format("Exception during test - '{0}'", ex.Message)); + } + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.Complete); + status.SetEntry(null); + resultHandler(status, null); + } + + return (status.ErrorCount == 0); + } + + [Flags] + enum HeaderTest + { + Extract = 0x01, // Check that this header represents an entry whose data can be extracted + Header = 0x02, // Check that this header contents are valid + } + + /// + /// Test a local header against that provided from the central directory + /// + /// + /// The entry to test against + /// + /// The type of tests to carry out. + /// The offset of the entries data in the file + long TestLocalHeader(ZipEntry entry, HeaderTest tests) + { + lock(baseStream_) + { + bool testHeader = (tests & HeaderTest.Header) != 0; + bool testData = (tests & HeaderTest.Extract) != 0; + + baseStream_.Seek(offsetOfFirstEntry + entry.Offset, SeekOrigin.Begin); + if ((int)ReadLEUint() != ZipConstants.LocalHeaderSignature) { + throw new ZipException(string.Format("Wrong local header signature @{0:X}", offsetOfFirstEntry + entry.Offset)); + } + + short extractVersion = ( short )ReadLEUshort(); + short localFlags = ( short )ReadLEUshort(); + short compressionMethod = ( short )ReadLEUshort(); + short fileTime = ( short )ReadLEUshort(); + short fileDate = ( short )ReadLEUshort(); + uint crcValue = ReadLEUint(); + long compressedSize = ReadLEUint(); + long size = ReadLEUint(); + int storedNameLength = ReadLEUshort(); + int extraDataLength = ReadLEUshort(); + + byte[] nameData = new byte[storedNameLength]; + StreamUtils.ReadFully(baseStream_, nameData); + + byte[] extraData = new byte[extraDataLength]; + StreamUtils.ReadFully(baseStream_, extraData); + + ZipExtraData localExtraData = new ZipExtraData(extraData); + + // Extra data / zip64 checks + if (localExtraData.Find(1)) + { + // 2010-03-04 Forum 10512: removed checks for version >= ZipConstants.VersionZip64 + // and size or compressedSize = MaxValue, due to rogue creators. + + size = localExtraData.ReadLong(); + compressedSize = localExtraData.ReadLong(); + + if ((localFlags & (int)GeneralBitFlags.Descriptor) != 0) + { + // These may be valid if patched later + if ( (size != -1) && (size != entry.Size)) { + throw new ZipException("Size invalid for descriptor"); + } + + if ((compressedSize != -1) && (compressedSize != entry.CompressedSize)) { + throw new ZipException("Compressed size invalid for descriptor"); + } + } + } + else + { + // No zip64 extra data but entry requires it. + if ((extractVersion >= ZipConstants.VersionZip64) && + (((uint)size == uint.MaxValue) || ((uint)compressedSize == uint.MaxValue))) + { + throw new ZipException("Required Zip64 extended information missing"); + } + } + + if ( testData ) { + if ( entry.IsFile ) { + if ( !entry.IsCompressionMethodSupported() ) { + throw new ZipException("Compression method not supported"); + } + + if ( (extractVersion > ZipConstants.VersionMadeBy) + || ((extractVersion > 20) && (extractVersion < ZipConstants.VersionZip64)) ) { + throw new ZipException(string.Format("Version required to extract this entry not supported ({0})", extractVersion)); + } + + if ( (localFlags & ( int )(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0 ) { + throw new ZipException("The library does not support the zip version required to extract this entry"); + } + } + } + + if (testHeader) + { + if ((extractVersion <= 63) && // Ignore later versions as we dont know about them.. + (extractVersion != 10) && + (extractVersion != 11) && + (extractVersion != 20) && + (extractVersion != 21) && + (extractVersion != 25) && + (extractVersion != 27) && + (extractVersion != 45) && + (extractVersion != 46) && + (extractVersion != 50) && + (extractVersion != 51) && + (extractVersion != 52) && + (extractVersion != 61) && + (extractVersion != 62) && + (extractVersion != 63) + ) + { + throw new ZipException(string.Format("Version required to extract this entry is invalid ({0})", extractVersion)); + } + + // Local entry flags dont have reserved bit set on. + if ((localFlags & (int)(GeneralBitFlags.ReservedPKware4 | GeneralBitFlags.ReservedPkware14 | GeneralBitFlags.ReservedPkware15)) != 0) + { + throw new ZipException("Reserved bit flags cannot be set."); + } + + // Encryption requires extract version >= 20 + if (((localFlags & (int)GeneralBitFlags.Encrypted) != 0) && (extractVersion < 20)) + { + throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion)); + } + + // Strong encryption requires encryption flag to be set and extract version >= 50. + if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0) + { + if ((localFlags & (int)GeneralBitFlags.Encrypted) == 0) + { + throw new ZipException("Strong encryption flag set but encryption flag is not set"); + } + + if (extractVersion < 50) + { + throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion)); + } + } + + // Patched entries require extract version >= 27 + if (((localFlags & (int)GeneralBitFlags.Patched) != 0) && (extractVersion < 27)) + { + throw new ZipException(string.Format("Patched data requires higher version than ({0})", extractVersion)); + } + + // Central header flags match local entry flags. + if (localFlags != entry.Flags) + { + throw new ZipException("Central header/local header flags mismatch"); + } + + // Central header compression method matches local entry + if (entry.CompressionMethod != (CompressionMethod)compressionMethod) + { + throw new ZipException("Central header/local header compression method mismatch"); + } + + if (entry.Version != extractVersion) + { + throw new ZipException("Extract version mismatch"); + } + + // Strong encryption and extract version match + if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0) + { + if (extractVersion < 62) + { + throw new ZipException("Strong encryption flag set but version not high enough"); + } + } + + if ((localFlags & (int)GeneralBitFlags.HeaderMasked) != 0) + { + if ((fileTime != 0) || (fileDate != 0)) + { + throw new ZipException("Header masked set but date/time values non-zero"); + } + } + + if ((localFlags & (int)GeneralBitFlags.Descriptor) == 0) + { + if (crcValue != (uint)entry.Crc) + { + throw new ZipException("Central header/local header crc mismatch"); + } + } + + // Crc valid for empty entry. + // This will also apply to streamed entries where size isnt known and the header cant be patched + if ((size == 0) && (compressedSize == 0)) + { + if (crcValue != 0) + { + throw new ZipException("Invalid CRC for empty entry"); + } + } + + // TODO: make test more correct... can't compare lengths as was done originally as this can fail for MBCS strings + // Assuming a code page at this point is not valid? Best is to store the name length in the ZipEntry probably + if (entry.Name.Length > storedNameLength) + { + throw new ZipException("File name length mismatch"); + } + + // Name data has already been read convert it and compare. + string localName = ZipConstants.ConvertToStringExt(localFlags, nameData); + + // Central directory and local entry name match + if (localName != entry.Name) + { + throw new ZipException("Central header and local header file name mismatch"); + } + + // Directories have zero actual size but can have compressed size + if (entry.IsDirectory) + { + if (size > 0) + { + throw new ZipException("Directory cannot have size"); + } + + // There may be other cases where the compressed size can be greater than this? + // If so until details are known we will be strict. + if (entry.IsCrypted) + { + if (compressedSize > ZipConstants.CryptoHeaderSize + 2) + { + throw new ZipException("Directory compressed size invalid"); + } + } + else if (compressedSize > 2) + { + // When not compressed the directory size can validly be 2 bytes + // if the true size wasnt known when data was originally being written. + // NOTE: Versions of the library 0.85.4 and earlier always added 2 bytes + throw new ZipException("Directory compressed size invalid"); + } + } + + if (!ZipNameTransform.IsValidName(localName, true)) + { + throw new ZipException("Name is invalid"); + } + } + + // Tests that apply to both data and header. + + // Size can be verified only if it is known in the local header. + // it will always be known in the central header. + if (((localFlags & (int)GeneralBitFlags.Descriptor) == 0) || + ((size > 0) || (compressedSize > 0))) { + + if (size != entry.Size) { + throw new ZipException( + string.Format("Size mismatch between central header({0}) and local header({1})", + entry.Size, size)); + } + + if (compressedSize != entry.CompressedSize && + compressedSize != 0xFFFFFFFF && compressedSize != -1) { + throw new ZipException( + string.Format("Compressed size mismatch between central header({0}) and local header({1})", + entry.CompressedSize, compressedSize)); + } + } + + int extraLength = storedNameLength + extraDataLength; + return offsetOfFirstEntry + entry.Offset + ZipConstants.LocalHeaderBaseSize + extraLength; + } + } + + #endregion + + #region Updating + + const int DefaultBufferSize = 4096; + + /// + /// The kind of update to apply. + /// + enum UpdateCommand + { + Copy, // Copy original file contents. + Modify, // Change encryption, compression, attributes, name, time etc, of an existing file. + Add, // Add a new file to the archive. + } + + #region Properties + /// + /// Get / set the to apply to names when updating. + /// + public INameTransform NameTransform + { + get { + return updateEntryFactory_.NameTransform; + } + + set { + updateEntryFactory_.NameTransform = value; + } + } + + /// + /// Get/set the used to generate values + /// during updates. + /// + public IEntryFactory EntryFactory + { + get { + return updateEntryFactory_; + } + + set { + if (value == null) { + updateEntryFactory_ = new ZipEntryFactory(); + } + else { + updateEntryFactory_ = value; + } + } + } + + /// + /// Get /set the buffer size to be used when updating this zip file. + /// + public int BufferSize + { + get { return bufferSize_; } + set { + if ( value < 1024 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "cannot be below 1024"); +#endif + } + + if ( bufferSize_ != value ) { + bufferSize_ = value; + copyBuffer_ = null; + } + } + } + + /// + /// Get a value indicating an update has been started. + /// + public bool IsUpdating + { + get { return updates_ != null; } + } + + /// + /// Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + /// + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + #endregion + + #region Immediate updating +// TBD: Direct form of updating +// +// public void Update(IEntryMatcher deleteMatcher) +// { +// } +// +// public void Update(IScanner addScanner) +// { +// } + #endregion + + #region Deferred Updating + /// + /// Begin updating this archive. + /// + /// The archive storage for use during the update. + /// The data source to utilise during updating. + /// ZipFile has been closed. + /// One of the arguments provided is null + /// ZipFile has been closed. + public void BeginUpdate(IArchiveStorage archiveStorage, IDynamicDataSource dataSource) + { + if ( archiveStorage == null ) { + throw new ArgumentNullException("archiveStorage"); + } + + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + if ( IsEmbeddedArchive ) { + throw new ZipException ("Cannot update embedded/SFX archives"); + } + + archiveStorage_ = archiveStorage; + updateDataSource_ = dataSource; + + // NOTE: the baseStream_ may not currently support writing or seeking. + + updateIndex_ = new Hashtable(); + + updates_ = new ArrayList(entries_.Length); + foreach(ZipEntry entry in entries_) { + int index = updates_.Add(new ZipUpdate(entry)); + updateIndex_.Add(entry.Name, index); + } + + // We must sort by offset before using offset's calculated sizes + updates_.Sort(new UpdateComparer()); + + int idx = 0; + foreach (ZipUpdate update in updates_) { + //If last entry, there is no next entry offset to use + if (idx == updates_.Count - 1) + break; + + update.OffsetBasedSize = ((ZipUpdate)updates_[idx + 1]).Entry.Offset - update.Entry.Offset; + idx++; + } + updateCount_ = updates_.Count; + + contentsEdited_ = false; + commentEdited_ = false; + newComment_ = null; + } + + /// + /// Begin updating to this archive. + /// + /// The storage to use during the update. + public void BeginUpdate(IArchiveStorage archiveStorage) + { + BeginUpdate(archiveStorage, new DynamicDiskDataSource()); + } + + /// + /// Begin updating this archive. + /// + /// + /// + /// + public void BeginUpdate() + { + if ( Name == null ) { + BeginUpdate(new MemoryArchiveStorage(), new DynamicDiskDataSource()); + } + else { + BeginUpdate(new DiskArchiveStorage(this), new DynamicDiskDataSource()); + } + } + + /// + /// Commit current updates, updating this archive. + /// + /// + /// + /// ZipFile has been closed. + public void CommitUpdate() + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + CheckUpdating(); + + try { + updateIndex_.Clear(); + updateIndex_=null; + + if( contentsEdited_ ) { + RunUpdates(); + } + else if( commentEdited_ ) { + UpdateCommentOnly(); + } + else { + // Create an empty archive if none existed originally. + if( entries_.Length==0 ) { + byte[] theComment=(newComment_!=null)?newComment_.RawComment:ZipConstants.ConvertToArray(comment_); + using( ZipHelperStream zhs=new ZipHelperStream(baseStream_) ) { + zhs.WriteEndOfCentralDirectory(0, 0, 0, theComment); + } + } + } + + } + finally { + PostUpdateCleanup(); + } + } + + /// + /// Abort updating leaving the archive unchanged. + /// + /// + /// + public void AbortUpdate() + { + PostUpdateCleanup(); + } + + /// + /// Set the file comment to be recorded when the current update is commited. + /// + /// The comment to record. + /// ZipFile has been closed. + public void SetComment(string comment) + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + CheckUpdating(); + + newComment_ = new ZipString(comment); + + if ( newComment_.RawLength > 0xffff ) { + newComment_ = null; + throw new ZipException("Comment length exceeds maximum - 65535"); + } + + // We dont take account of the original and current comment appearing to be the same + // as encoding may be different. + commentEdited_ = true; + } + + #endregion + + #region Adding Entries + + void AddUpdate(ZipUpdate update) + { + contentsEdited_ = true; + + int index = FindExistingUpdate(update.Entry.Name); + + if (index >= 0) { + if ( updates_[index] == null ) { + updateCount_ += 1; + } + + // Direct replacement is faster than delete and add. + updates_[index] = update; + } + else { + index = updates_.Add(update); + updateCount_ += 1; + updateIndex_.Add(update.Entry.Name, index); + } + } + + /// + /// Add a new entry to the archive. + /// + /// The name of the file to add. + /// The compression method to use. + /// Ensure Unicode text is used for name and comment for this entry. + /// Argument supplied is null. + /// ZipFile has been closed. + /// Compression method is not supported. + public void Add(string fileName, CompressionMethod compressionMethod, bool useUnicodeText ) + { + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + if (!ZipEntry.IsCompressionMethodSupported(compressionMethod)) { + throw new ArgumentOutOfRangeException("compressionMethod"); + } + + CheckUpdating(); + contentsEdited_ = true; + + ZipEntry entry = EntryFactory.MakeFileEntry(fileName); + entry.IsUnicodeText = useUnicodeText; + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(fileName, entry)); + } + + /// + /// Add a new entry to the archive. + /// + /// The name of the file to add. + /// The compression method to use. + /// ZipFile has been closed. + /// The compression method is not supported. + public void Add(string fileName, CompressionMethod compressionMethod) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + if ( !ZipEntry.IsCompressionMethodSupported(compressionMethod) ) { + throw new ArgumentOutOfRangeException("compressionMethod"); + } + + CheckUpdating(); + contentsEdited_ = true; + + ZipEntry entry = EntryFactory.MakeFileEntry(fileName); + entry.CompressionMethod = compressionMethod; + AddUpdate(new ZipUpdate(fileName, entry)); + } + + /// + /// Add a file to the archive. + /// + /// The name of the file to add. + /// Argument supplied is null. + public void Add(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(fileName, EntryFactory.MakeFileEntry(fileName))); + } + + /// + /// Add a file to the archive. + /// + /// The name of the file to add. + /// The name to use for the on the Zip file created. + /// Argument supplied is null. + public void Add(string fileName, string entryName) + { + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(fileName, EntryFactory.MakeFileEntry(entryName))); + } + + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + public void Add(IStaticDataSource dataSource, string entryName) + { + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(dataSource, EntryFactory.MakeFileEntry(entryName, false))); + } + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + /// The compression method to use. + public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod) + { + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + + ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false); + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(dataSource, entry)); + } + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + /// The compression method to use. + /// Ensure Unicode text is used for name and comments for this entry. + public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod, bool useUnicodeText) + { + if (dataSource == null) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + + ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false); + entry.IsUnicodeText = useUnicodeText; + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(dataSource, entry)); + } + + /// + /// Add a that contains no data. + /// + /// The entry to add. + /// This can be used to add directories, volume labels, or empty file entries. + public void Add(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + CheckUpdating(); + + if ( (entry.Size != 0) || (entry.CompressedSize != 0) ) { + throw new ZipException("Entry cannot have any data"); + } + + AddUpdate(new ZipUpdate(UpdateCommand.Add, entry)); + } + + /// + /// Add a directory entry to the archive. + /// + /// The directory to add. + public void AddDirectory(string directoryName) + { + if ( directoryName == null ) { + throw new ArgumentNullException("directoryName"); + } + + CheckUpdating(); + + ZipEntry dirEntry = EntryFactory.MakeDirectoryEntry(directoryName); + AddUpdate(new ZipUpdate(UpdateCommand.Add, dirEntry)); + } + + #endregion + + #region Modifying Entries +/* Modify not yet ready for public consumption. + Direct modification of an entry should not overwrite original data before its read. + Safe mode is trivial in this sense. + public void Modify(ZipEntry original, ZipEntry updated) + { + if ( original == null ) { + throw new ArgumentNullException("original"); + } + + if ( updated == null ) { + throw new ArgumentNullException("updated"); + } + + CheckUpdating(); + contentsEdited_ = true; + updates_.Add(new ZipUpdate(original, updated)); + } +*/ + #endregion + + #region Deleting Entries + /// + /// Delete an entry by name + /// + /// The filename to delete + /// True if the entry was found and deleted; false otherwise. + public bool Delete(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + CheckUpdating(); + + bool result = false; + int index = FindExistingUpdate(fileName); + if ( (index >= 0) && (updates_[index] != null) ) { + result = true; + contentsEdited_ = true; + updates_[index] = null; + updateCount_ -= 1; + } + else { + throw new ZipException("Cannot find entry to delete"); + } + return result; + } + + /// + /// Delete a from the archive. + /// + /// The entry to delete. + public void Delete(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + CheckUpdating(); + + int index = FindExistingUpdate(entry); + if ( index >= 0 ) { + contentsEdited_ = true; + updates_[index] = null; + updateCount_ -= 1; + } + else { + throw new ZipException("Cannot find entry to delete"); + } + } + + #endregion + + #region Update Support + + #region Writing Values/Headers + void WriteLEShort(int value) + { + baseStream_.WriteByte(( byte )(value & 0xff)); + baseStream_.WriteByte(( byte )((value >> 8) & 0xff)); + } + + /// + /// Write an unsigned short in little endian byte order. + /// + void WriteLEUshort(ushort value) + { + baseStream_.WriteByte(( byte )(value & 0xff)); + baseStream_.WriteByte(( byte )(value >> 8)); + } + + /// + /// Write an int in little endian byte order. + /// + void WriteLEInt(int value) + { + WriteLEShort(value & 0xffff); + WriteLEShort(value >> 16); + } + + /// + /// Write an unsigned int in little endian byte order. + /// + void WriteLEUint(uint value) + { + WriteLEUshort((ushort)(value & 0xffff)); + WriteLEUshort((ushort)(value >> 16)); + } + + /// + /// Write a long in little endian byte order. + /// + void WriteLeLong(long value) + { + WriteLEInt(( int )(value & 0xffffffff)); + WriteLEInt(( int )(value >> 32)); + } + + void WriteLEUlong(ulong value) + { + WriteLEUint(( uint )(value & 0xffffffff)); + WriteLEUint(( uint )(value >> 32)); + } + + void WriteLocalEntryHeader(ZipUpdate update) + { + ZipEntry entry = update.OutEntry; + + // TODO: Local offset will require adjusting for multi-disk zip files. + entry.Offset = baseStream_.Position; + + // TODO: Need to clear any entry flags that dont make sense or throw an exception here. + if (update.Command != UpdateCommand.Copy) { + if (entry.CompressionMethod == CompressionMethod.Deflated) { + if (entry.Size == 0) { + // No need to compress - no data. + entry.CompressedSize = entry.Size; + entry.Crc = 0; + entry.CompressionMethod = CompressionMethod.Stored; + } + } + else if (entry.CompressionMethod == CompressionMethod.Stored) { + entry.Flags &= ~(int)GeneralBitFlags.Descriptor; + } + + if (HaveKeys) { + entry.IsCrypted = true; + if (entry.Crc < 0) { + entry.Flags |= (int)GeneralBitFlags.Descriptor; + } + } + else { + entry.IsCrypted = false; + } + + switch (useZip64_) { + case UseZip64.Dynamic: + if (entry.Size < 0) { + entry.ForceZip64(); + } + break; + + case UseZip64.On: + entry.ForceZip64(); + break; + + case UseZip64.Off: + // Do nothing. The entry itself may be using Zip64 independantly. + break; + } + } + + // Write the local file header + WriteLEInt(ZipConstants.LocalHeaderSignature); + + WriteLEShort(entry.Version); + WriteLEShort(entry.Flags); + + WriteLEShort((byte)entry.CompressionMethod); + WriteLEInt(( int )entry.DosTime); + + if ( !entry.HasCrc ) { + // Note patch address for updating CRC later. + update.CrcPatchOffset = baseStream_.Position; + WriteLEInt(( int )0); + } + else { + WriteLEInt(unchecked(( int )entry.Crc)); + } + + if (entry.LocalHeaderRequiresZip64) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + if ( (entry.CompressedSize < 0) || (entry.Size < 0) ) { + update.SizePatchOffset = baseStream_.Position; + } + + WriteLEInt(( int )entry.CompressedSize); + WriteLEInt(( int )entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if ( name.Length > 0xFFFF ) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.LocalHeaderRequiresZip64 ) { + ed.StartNewEntry(); + + // Local entry header always includes size and compressed size. + // NOTE the order of these fields is reversed when compared to the normal headers! + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + ed.AddNewEntry(1); + } + else { + ed.Delete(1); + } + + entry.ExtraData = ed.GetEntryData(); + + WriteLEShort(name.Length); + WriteLEShort(entry.ExtraData.Length); + + if ( name.Length > 0 ) { + baseStream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 ) { + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cannot find extra data"); + } + + update.SizePatchOffset = baseStream_.Position + ed.CurrentReadIndex; + } + + if ( entry.ExtraData.Length > 0 ) { + baseStream_.Write(entry.ExtraData, 0, entry.ExtraData.Length); + } + } + + int WriteCentralDirectoryHeader(ZipEntry entry) + { + if ( entry.CompressedSize < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown csize"); + } + + if ( entry.Size < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown size"); + } + + if ( entry.Crc < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown crc"); + } + + // Write the central file header + WriteLEInt(ZipConstants.CentralHeaderSignature); + + // Version made by + WriteLEShort(ZipConstants.VersionMadeBy); + + // Version required to extract + WriteLEShort(entry.Version); + + WriteLEShort(entry.Flags); + + unchecked { + WriteLEShort((byte)entry.CompressionMethod); + WriteLEInt((int)entry.DosTime); + WriteLEInt((int)entry.Crc); + } + + if ( (entry.IsZip64Forced()) || (entry.CompressedSize >= 0xffffffff) ) { + WriteLEInt(-1); + } + else { + WriteLEInt((int)(entry.CompressedSize & 0xffffffff)); + } + + if ( (entry.IsZip64Forced()) || (entry.Size >= 0xffffffff) ) { + WriteLEInt(-1); + } + else { + WriteLEInt((int)entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if ( name.Length > 0xFFFF ) { + throw new ZipException("Entry name is too long."); + } + + WriteLEShort(name.Length); + + // Central header extra data is different to local header version so regenerate. + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.CentralHeaderRequiresZip64 ) { + ed.StartNewEntry(); + + if ( (entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) ) + { + ed.AddLeLong(entry.Size); + } + + if ( (entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) ) + { + ed.AddLeLong(entry.CompressedSize); + } + + if ( entry.Offset >= 0xffffffff ) { + ed.AddLeLong(entry.Offset); + } + + // Number of disk on which this file starts isnt supported and is never written here. + ed.AddNewEntry(1); + } + else { + // Should have already be done when local header was added. + ed.Delete(1); + } + + byte[] centralExtraData = ed.GetEntryData(); + + WriteLEShort(centralExtraData.Length); + WriteLEShort(entry.Comment != null ? entry.Comment.Length : 0); + + WriteLEShort(0); // disk number + WriteLEShort(0); // internal file attributes + + // External file attributes... + if ( entry.ExternalFileAttributes != -1 ) { + WriteLEInt(entry.ExternalFileAttributes); + } + else { + if ( entry.IsDirectory ) { + WriteLEUint(16); + } + else { + WriteLEUint(0); + } + } + + if ( entry.Offset >= 0xffffffff ) { + WriteLEUint(0xffffffff); + } + else { + WriteLEUint((uint)(int)entry.Offset); + } + + if ( name.Length > 0 ) { + baseStream_.Write(name, 0, name.Length); + } + + if ( centralExtraData.Length > 0 ) { + baseStream_.Write(centralExtraData, 0, centralExtraData.Length); + } + + byte[] rawComment = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : new byte[0]; + + if ( rawComment.Length > 0 ) { + baseStream_.Write(rawComment, 0, rawComment.Length); + } + + return ZipConstants.CentralHeaderBaseSize + name.Length + centralExtraData.Length + rawComment.Length; + } + #endregion + + void PostUpdateCleanup() + { + updateDataSource_ = null; + updates_ = null; + updateIndex_ = null; + + if (archiveStorage_ != null) + { + archiveStorage_.Dispose(); + archiveStorage_=null; + } + } + + string GetTransformedFileName(string name) + { + INameTransform transform = NameTransform; + return (transform != null) ? + transform.TransformFile(name) : + name; + } + + string GetTransformedDirectoryName(string name) + { + INameTransform transform = NameTransform; + return (transform != null) ? + transform.TransformDirectory(name) : + name; + } + + /// + /// Get a raw memory buffer. + /// + /// Returns a raw memory buffer. + byte[] GetBuffer() + { + if ( copyBuffer_ == null ) { + copyBuffer_ = new byte[bufferSize_]; + } + return copyBuffer_; + } + + void CopyDescriptorBytes(ZipUpdate update, Stream dest, Stream source) + { + int bytesToCopy = GetDescriptorSize(update); + + if ( bytesToCopy > 0 ) { + byte[] buffer = GetBuffer(); + + while ( bytesToCopy > 0 ) { + int readSize = Math.Min(buffer.Length, bytesToCopy); + + int bytesRead = source.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + dest.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + } + else { + throw new ZipException("Unxpected end of stream"); + } + } + } + } + + void CopyBytes(ZipUpdate update, Stream destination, Stream source, + long bytesToCopy, bool updateCrc) + { + if ( destination == source ) { + throw new InvalidOperationException("Destination and source are the same"); + } + + // NOTE: Compressed size is updated elsewhere. + Crc32 crc = new Crc32(); + byte[] buffer = GetBuffer(); + + long targetBytes = bytesToCopy; + long totalBytesRead = 0; + + int bytesRead; + do { + int readSize = buffer.Length; + + if ( bytesToCopy < readSize ) { + readSize = (int)bytesToCopy; + } + + bytesRead = source.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + if ( updateCrc ) { + crc.Update(buffer, 0, bytesRead); + } + destination.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + totalBytesRead += bytesRead; + } + } + while ( (bytesRead > 0) && (bytesToCopy > 0) ); + + if ( totalBytesRead != targetBytes ) { + throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); + } + + if ( updateCrc ) { + update.OutEntry.Crc = crc.Value; + } + } + + /// + /// Get the size of the source descriptor for a . + /// + /// The update to get the size for. + /// The descriptor size, zero if there isnt one. + int GetDescriptorSize(ZipUpdate update) + { + int result = 0; + if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) { + result = ZipConstants.DataDescriptorSize - 4; + if ( update.Entry.LocalHeaderRequiresZip64 ) { + result = ZipConstants.Zip64DataDescriptorSize - 4; + } + } + return result; + } + + void CopyDescriptorBytesDirect(ZipUpdate update, Stream stream, ref long destinationPosition, long sourcePosition) + { + int bytesToCopy = GetDescriptorSize(update); + + while ( bytesToCopy > 0 ) { + int readSize = (int)bytesToCopy; + byte[] buffer = GetBuffer(); + + stream.Position = sourcePosition; + int bytesRead = stream.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + stream.Position = destinationPosition; + stream.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + destinationPosition += bytesRead; + sourcePosition += bytesRead; + } + else { + throw new ZipException("Unxpected end of stream"); + } + } + } + + void CopyEntryDataDirect(ZipUpdate update, Stream stream, bool updateCrc, ref long destinationPosition, ref long sourcePosition) + { + long bytesToCopy = update.Entry.CompressedSize; + + // NOTE: Compressed size is updated elsewhere. + Crc32 crc = new Crc32(); + byte[] buffer = GetBuffer(); + + long targetBytes = bytesToCopy; + long totalBytesRead = 0; + + int bytesRead; + do + { + int readSize = buffer.Length; + + if ( bytesToCopy < readSize ) { + readSize = (int)bytesToCopy; + } + + stream.Position = sourcePosition; + bytesRead = stream.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + if ( updateCrc ) { + crc.Update(buffer, 0, bytesRead); + } + stream.Position = destinationPosition; + stream.Write(buffer, 0, bytesRead); + + destinationPosition += bytesRead; + sourcePosition += bytesRead; + bytesToCopy -= bytesRead; + totalBytesRead += bytesRead; + } + } + while ( (bytesRead > 0) && (bytesToCopy > 0) ); + + if ( totalBytesRead != targetBytes ) { + throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); + } + + if ( updateCrc ) { + update.OutEntry.Crc = crc.Value; + } + } + + int FindExistingUpdate(ZipEntry entry) + { + int result = -1; + string convertedName = GetTransformedFileName(entry.Name); + + if (updateIndex_.ContainsKey(convertedName)) { + result = (int)updateIndex_[convertedName]; + } +/* + // This is slow like the coming of the next ice age but takes less storage and may be useful + // for CF? + for (int index = 0; index < updates_.Count; ++index) + { + ZipUpdate zu = ( ZipUpdate )updates_[index]; + if ( (zu.Entry.ZipFileIndex == entry.ZipFileIndex) && + (string.Compare(convertedName, zu.Entry.Name, true, CultureInfo.InvariantCulture) == 0) ) { + result = index; + break; + } + } + */ + return result; + } + + int FindExistingUpdate(string fileName) + { + int result = -1; + + string convertedName = GetTransformedFileName(fileName); + + if (updateIndex_.ContainsKey(convertedName)) { + result = (int)updateIndex_[convertedName]; + } + +/* + // This is slow like the coming of the next ice age but takes less storage and may be useful + // for CF? + for ( int index = 0; index < updates_.Count; ++index ) { + if ( string.Compare(convertedName, (( ZipUpdate )updates_[index]).Entry.Name, + true, CultureInfo.InvariantCulture) == 0 ) { + result = index; + break; + } + } + */ + + return result; + } + + /// + /// Get an output stream for the specified + /// + /// The entry to get an output stream for. + /// The output stream obtained for the entry. + Stream GetOutputStream(ZipEntry entry) + { + Stream result = baseStream_; + + if ( entry.IsCrypted == true ) { +#if NETCF_1_0 + throw new ZipException("Encryption not supported for Compact Framework 1.0"); +#else + result = CreateAndInitEncryptionStream(result, entry); +#endif + } + + switch ( entry.CompressionMethod ) { + case CompressionMethod.Stored: + result = new UncompressedStream(result); + break; + + case CompressionMethod.Deflated: + DeflaterOutputStream dos = new DeflaterOutputStream(result, new Deflater(9, true)); + dos.IsStreamOwner = false; + result = dos; + break; + + default: + throw new ZipException("Unknown compression method " + entry.CompressionMethod); + } + return result; + } + + void AddEntry(ZipFile workFile, ZipUpdate update) + { + Stream source = null; + + if ( update.Entry.IsFile ) { + source = update.GetSource(); + + if ( source == null ) { + source = updateDataSource_.GetSource(update.Entry, update.Filename); + } + } + + if ( source != null ) { + using ( source ) { + long sourceStreamLength = source.Length; + if ( update.OutEntry.Size < 0 ) { + update.OutEntry.Size = sourceStreamLength; + } + else { + // Check for errant entries. + if ( update.OutEntry.Size != sourceStreamLength ) { + throw new ZipException("Entry size/stream size mismatch"); + } + } + + workFile.WriteLocalEntryHeader(update); + + long dataStart = workFile.baseStream_.Position; + + using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) { + CopyBytes(update, output, source, sourceStreamLength, true); + } + + long dataEnd = workFile.baseStream_.Position; + update.OutEntry.CompressedSize = dataEnd - dataStart; + + if ((update.OutEntry.Flags & (int)GeneralBitFlags.Descriptor) == (int)GeneralBitFlags.Descriptor) + { + ZipHelperStream helper = new ZipHelperStream(workFile.baseStream_); + helper.WriteDataDescriptor(update.OutEntry); + } + } + } + else { + workFile.WriteLocalEntryHeader(update); + update.OutEntry.CompressedSize = 0; + } + + } + + void ModifyEntry(ZipFile workFile, ZipUpdate update) + { + workFile.WriteLocalEntryHeader(update); + long dataStart = workFile.baseStream_.Position; + + // TODO: This is slow if the changes don't effect the data!! + if ( update.Entry.IsFile && (update.Filename != null) ) { + using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) { + using ( Stream source = this.GetInputStream(update.Entry) ) { + CopyBytes(update, output, source, source.Length, true); + } + } + } + + long dataEnd = workFile.baseStream_.Position; + update.Entry.CompressedSize = dataEnd - dataStart; + } + + void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition) + { + bool skipOver = false; + if ( update.Entry.Offset == destinationPosition ) { + skipOver = true; + } + + if ( !skipOver ) { + baseStream_.Position = destinationPosition; + workFile.WriteLocalEntryHeader(update); + destinationPosition = baseStream_.Position; + } + + long sourcePosition = 0; + + const int NameLengthOffset = 26; + + // TODO: Add base for SFX friendly handling + long entryDataOffset = update.Entry.Offset + NameLengthOffset; + + baseStream_.Seek(entryDataOffset, SeekOrigin.Begin); + + // Clumsy way of handling retrieving the original name and extra data length for now. + // TODO: Stop re-reading name and data length in CopyEntryDirect. + uint nameLength = ReadLEUshort(); + uint extraLength = ReadLEUshort(); + + sourcePosition = baseStream_.Position + nameLength + extraLength; + + if (skipOver) { + if (update.OffsetBasedSize != -1) + destinationPosition += update.OffsetBasedSize; + else + // TODO: Find out why this calculation comes up 4 bytes short on some entries in ODT (Office Document Text) archives. + // WinZip produces a warning on these entries: + // "caution: value of lrec.csize (compressed size) changed from ..." + destinationPosition += + (sourcePosition - entryDataOffset) + NameLengthOffset + // Header size + update.Entry.CompressedSize + GetDescriptorSize(update); + } + else { + if ( update.Entry.CompressedSize > 0 ) { + CopyEntryDataDirect(update, baseStream_, false, ref destinationPosition, ref sourcePosition ); + } + CopyDescriptorBytesDirect(update, baseStream_, ref destinationPosition, sourcePosition); + } + } + + void CopyEntry(ZipFile workFile, ZipUpdate update) + { + workFile.WriteLocalEntryHeader(update); + + if ( update.Entry.CompressedSize > 0 ) { + const int NameLengthOffset = 26; + + long entryDataOffset = update.Entry.Offset + NameLengthOffset; + + // TODO: This wont work for SFX files! + baseStream_.Seek(entryDataOffset, SeekOrigin.Begin); + + uint nameLength = ReadLEUshort(); + uint extraLength = ReadLEUshort(); + + baseStream_.Seek(nameLength + extraLength, SeekOrigin.Current); + + CopyBytes(update, workFile.baseStream_, baseStream_, update.Entry.CompressedSize, false); + } + CopyDescriptorBytes(update, workFile.baseStream_, baseStream_); + } + + void Reopen(Stream source) + { + if ( source == null ) { + throw new ZipException("Failed to reopen archive - no source"); + } + + isNewArchive_ = false; + baseStream_ = source; + ReadEntries(); + } + + void Reopen() + { + if (Name == null) { + throw new InvalidOperationException("Name is not known cannot Reopen"); + } + + Reopen(File.Open(Name, FileMode.Open, FileAccess.Read, FileShare.Read)); + } + + void UpdateCommentOnly() + { + long baseLength = baseStream_.Length; + + ZipHelperStream updateFile = null; + + if ( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { + Stream copyStream = archiveStorage_.MakeTemporaryCopy(baseStream_); + updateFile = new ZipHelperStream(copyStream); + updateFile.IsStreamOwner = true; + + baseStream_.Close(); + baseStream_ = null; + } + else { + if (archiveStorage_.UpdateMode == FileUpdateMode.Direct) { + // TODO: archiveStorage wasnt originally intended for this use. + // Need to revisit this to tidy up handling as archive storage currently doesnt + // handle the original stream well. + // The problem is when using an existing zip archive with an in memory archive storage. + // The open stream wont support writing but the memory storage should open the same file not an in memory one. + + // Need to tidy up the archive storage interface and contract basically. + baseStream_ = archiveStorage_.OpenForDirectUpdate(baseStream_); + updateFile = new ZipHelperStream(baseStream_); + } + else { + baseStream_.Close(); + baseStream_ = null; + updateFile = new ZipHelperStream(Name); + } + } + + using ( updateFile ) { + long locatedCentralDirOffset = + updateFile.LocateBlockWithSignature(ZipConstants.EndOfCentralDirectorySignature, + baseLength, ZipConstants.EndOfCentralRecordBaseSize, 0xffff); + if ( locatedCentralDirOffset < 0 ) { + throw new ZipException("Cannot find central directory"); + } + + const int CentralHeaderCommentSizeOffset = 16; + updateFile.Position += CentralHeaderCommentSizeOffset; + + byte[] rawComment = newComment_.RawComment; + + updateFile.WriteLEShort(rawComment.Length); + updateFile.Write(rawComment, 0, rawComment.Length); + updateFile.SetLength(updateFile.Position); + } + + if ( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { + Reopen(archiveStorage_.ConvertTemporaryToFinal()); + } + else { + ReadEntries(); + } + } + + /// + /// Class used to sort updates. + /// + class UpdateComparer : IComparer + { + /// + /// Compares two objects and returns a value indicating whether one is + /// less than, equal to or greater than the other. + /// + /// First object to compare + /// Second object to compare. + /// Compare result. + public int Compare( + object x, + object y) + { + ZipUpdate zx = x as ZipUpdate; + ZipUpdate zy = y as ZipUpdate; + + int result; + + if (zx == null) { + if (zy == null) { + result = 0; + } + else { + result = -1; + } + } + else if (zy == null) { + result = 1; + } + else { + int xCmdValue = ((zx.Command == UpdateCommand.Copy) || (zx.Command == UpdateCommand.Modify)) ? 0 : 1; + int yCmdValue = ((zy.Command == UpdateCommand.Copy) || (zy.Command == UpdateCommand.Modify)) ? 0 : 1; + + result = xCmdValue - yCmdValue; + if (result == 0) { + long offsetDiff = zx.Entry.Offset - zy.Entry.Offset; + if (offsetDiff < 0) { + result = -1; + } + else if (offsetDiff == 0) { + result = 0; + } + else { + result = 1; + } + } + } + return result; + } + } + + void RunUpdates() + { + long sizeEntries = 0; + long endOfStream = 0; + bool directUpdate = false; + long destinationPosition = 0; // NOT SFX friendly + + ZipFile workFile; + + if ( IsNewArchive ) { + workFile = this; + workFile.baseStream_.Position = 0; + directUpdate = true; + } + else if ( archiveStorage_.UpdateMode == FileUpdateMode.Direct ) { + workFile = this; + workFile.baseStream_.Position = 0; + directUpdate = true; + + // Sort the updates by offset within copies/modifies, then adds. + // This ensures that data required by copies will not be overwritten. + updates_.Sort(new UpdateComparer()); + } + else { + workFile = ZipFile.Create(archiveStorage_.GetTemporaryOutput()); + workFile.UseZip64 = UseZip64; + + if (key != null) { + workFile.key = (byte[])key.Clone(); + } + } + + try { + foreach ( ZipUpdate update in updates_ ) { + if (update != null) { + switch (update.Command) { + case UpdateCommand.Copy: + if (directUpdate) { + CopyEntryDirect(workFile, update, ref destinationPosition); + } + else { + CopyEntry(workFile, update); + } + break; + + case UpdateCommand.Modify: + // TODO: Direct modifying of an entry will take some legwork. + ModifyEntry(workFile, update); + break; + + case UpdateCommand.Add: + if (!IsNewArchive && directUpdate) { + workFile.baseStream_.Position = destinationPosition; + } + + AddEntry(workFile, update); + + if (directUpdate) { + destinationPosition = workFile.baseStream_.Position; + } + break; + } + } + } + + if ( !IsNewArchive && directUpdate ) { + workFile.baseStream_.Position = destinationPosition; + } + + long centralDirOffset = workFile.baseStream_.Position; + + foreach ( ZipUpdate update in updates_ ) { + if (update != null) { + sizeEntries += workFile.WriteCentralDirectoryHeader(update.OutEntry); + } + } + + byte[] theComment = (newComment_ != null) ? newComment_.RawComment : ZipConstants.ConvertToArray(comment_); + using ( ZipHelperStream zhs = new ZipHelperStream(workFile.baseStream_) ) { + zhs.WriteEndOfCentralDirectory(updateCount_, sizeEntries, centralDirOffset, theComment); + } + + endOfStream = workFile.baseStream_.Position; + + // And now patch entries... + foreach ( ZipUpdate update in updates_ ) { + if (update != null) + { + // If the size of the entry is zero leave the crc as 0 as well. + // The calculated crc will be all bits on... + if ((update.CrcPatchOffset > 0) && (update.OutEntry.CompressedSize > 0)) { + workFile.baseStream_.Position = update.CrcPatchOffset; + workFile.WriteLEInt((int)update.OutEntry.Crc); + } + + if (update.SizePatchOffset > 0) { + workFile.baseStream_.Position = update.SizePatchOffset; + if (update.OutEntry.LocalHeaderRequiresZip64) { + workFile.WriteLeLong(update.OutEntry.Size); + workFile.WriteLeLong(update.OutEntry.CompressedSize); + } + else { + workFile.WriteLEInt((int)update.OutEntry.CompressedSize); + workFile.WriteLEInt((int)update.OutEntry.Size); + } + } + } + } + } + catch { + workFile.Close(); + if (!directUpdate && (workFile.Name != null)) { + File.Delete(workFile.Name); + } + throw; + } + + if (directUpdate) { + workFile.baseStream_.SetLength(endOfStream); + workFile.baseStream_.Flush(); + isNewArchive_ = false; + ReadEntries(); + } + else { + baseStream_.Close(); + Reopen(archiveStorage_.ConvertTemporaryToFinal()); + } + } + + void CheckUpdating() + { + if ( updates_ == null ) { + throw new InvalidOperationException("BeginUpdate has not been called"); + } + } + + #endregion + + #region ZipUpdate class + /// + /// Represents a pending update to a Zip file. + /// + class ZipUpdate + { + #region Constructors + public ZipUpdate(string fileName, ZipEntry entry) + { + command_ = UpdateCommand.Add; + entry_ = entry; + filename_ = fileName; + } + + [Obsolete] + public ZipUpdate(string fileName, string entryName, CompressionMethod compressionMethod) + { + command_ = UpdateCommand.Add; + entry_ = new ZipEntry(entryName); + entry_.CompressionMethod = compressionMethod; + filename_ = fileName; + } + + [Obsolete] + public ZipUpdate(string fileName, string entryName) + : this(fileName, entryName, CompressionMethod.Deflated) + { + // Do nothing. + } + + [Obsolete] + public ZipUpdate(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod) + { + command_ = UpdateCommand.Add; + entry_ = new ZipEntry(entryName); + entry_.CompressionMethod = compressionMethod; + dataSource_ = dataSource; + } + + public ZipUpdate(IStaticDataSource dataSource, ZipEntry entry) + { + command_ = UpdateCommand.Add; + entry_ = entry; + dataSource_ = dataSource; + } + + public ZipUpdate(ZipEntry original, ZipEntry updated) + { + throw new ZipException("Modify not currently supported"); + /* + command_ = UpdateCommand.Modify; + entry_ = ( ZipEntry )original.Clone(); + outEntry_ = ( ZipEntry )updated.Clone(); + */ + } + + public ZipUpdate(UpdateCommand command, ZipEntry entry) + { + command_ = command; + entry_ = ( ZipEntry )entry.Clone(); + } + + + /// + /// Copy an existing entry. + /// + /// The existing entry to copy. + public ZipUpdate(ZipEntry entry) + : this(UpdateCommand.Copy, entry) + { + // Do nothing. + } + #endregion + + /// + /// Get the for this update. + /// + /// This is the source or original entry. + public ZipEntry Entry + { + get { return entry_; } + } + + /// + /// Get the that will be written to the updated/new file. + /// + public ZipEntry OutEntry + { + get { + if ( outEntry_ == null ) { + outEntry_ = (ZipEntry)entry_.Clone(); + } + + return outEntry_; + } + } + + /// + /// Get the command for this update. + /// + public UpdateCommand Command + { + get { return command_; } + } + + /// + /// Get the filename if any for this update. Null if none exists. + /// + public string Filename + { + get { return filename_; } + } + + /// + /// Get/set the location of the size patch for this update. + /// + public long SizePatchOffset + { + get { return sizePatchOffset_; } + set { sizePatchOffset_ = value; } + } + + /// + /// Get /set the location of the crc patch for this update. + /// + public long CrcPatchOffset + { + get { return crcPatchOffset_; } + set { crcPatchOffset_ = value; } + } + + /// + /// Get/set the size calculated by offset. + /// Specifically, the difference between this and next entry's starting offset. + /// + public long OffsetBasedSize + { + get { return _offsetBasedSize; } + set { _offsetBasedSize = value; } + } + + public Stream GetSource() + { + Stream result = null; + if ( dataSource_ != null ) { + result = dataSource_.GetSource(); + } + + return result; + } + + #region Instance Fields + ZipEntry entry_; + ZipEntry outEntry_; + UpdateCommand command_; + IStaticDataSource dataSource_; + string filename_; + long sizePatchOffset_ = -1; + long crcPatchOffset_ = -1; + long _offsetBasedSize = -1; + #endregion + } + + #endregion + #endregion + + #region Disposing + + #region IDisposable Members + void IDisposable.Dispose() + { + Close(); + } + #endregion + + void DisposeInternal(bool disposing) + { + if ( !isDisposed_ ) { + isDisposed_ = true; + entries_ = new ZipEntry[0]; + + if ( IsStreamOwner && (baseStream_ != null) ) { + lock(baseStream_) { + baseStream_.Close(); + } + } + + PostUpdateCleanup(); + } + } + + /// + /// Releases the unmanaged resources used by the this instance and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + DisposeInternal(disposing); + } + + #endregion + + #region Internal routines + #region Reading + /// + /// Read an unsigned short in little endian byte order. + /// + /// Returns the value read. + /// + /// The stream ends prematurely + /// + ushort ReadLEUshort() + { + int data1 = baseStream_.ReadByte(); + + if ( data1 < 0 ) { + throw new EndOfStreamException("End of stream"); + } + + int data2 = baseStream_.ReadByte(); + + if ( data2 < 0 ) { + throw new EndOfStreamException("End of stream"); + } + + + return unchecked((ushort)((ushort)data1 | (ushort)(data2 << 8))); + } + + /// + /// Read a uint in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + uint ReadLEUint() + { + return (uint)(ReadLEUshort() | (ReadLEUshort() << 16)); + } + + ulong ReadLEUlong() + { + return ReadLEUint() | ((ulong)ReadLEUint() << 32); + } + + #endregion + // NOTE this returns the offset of the first byte after the signature. + long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + { + using ( ZipHelperStream les = new ZipHelperStream(baseStream_) ) { + return les.LocateBlockWithSignature(signature, endLocation, minimumBlockSize, maximumVariableData); + } + } + + /// + /// Search for and read the central directory of a zip file filling the entries array. + /// + /// + /// An i/o error occurs. + /// + /// + /// The central directory is malformed or cannot be found + /// + void ReadEntries() + { + // Search for the End Of Central Directory. When a zip comment is + // present the directory will start earlier + // + // The search is limited to 64K which is the maximum size of a trailing comment field to aid speed. + // This should be compatible with both SFX and ZIP files but has only been tested for Zip files + // If a SFX file has the Zip data attached as a resource and there are other resources occuring later then + // this could be invalid. + // Could also speed this up by reading memory in larger blocks. + + if (baseStream_.CanSeek == false) { + throw new ZipException("ZipFile stream must be seekable"); + } + + long locatedEndOfCentralDir = LocateBlockWithSignature(ZipConstants.EndOfCentralDirectorySignature, + baseStream_.Length, ZipConstants.EndOfCentralRecordBaseSize, 0xffff); + + if (locatedEndOfCentralDir < 0) { + throw new ZipException("Cannot find central directory"); + } + + // Read end of central directory record + ushort thisDiskNumber = ReadLEUshort(); + ushort startCentralDirDisk = ReadLEUshort(); + ulong entriesForThisDisk = ReadLEUshort(); + ulong entriesForWholeCentralDir = ReadLEUshort(); + ulong centralDirSize = ReadLEUint(); + long offsetOfCentralDir = ReadLEUint(); + uint commentSize = ReadLEUshort(); + + if ( commentSize > 0 ) { + byte[] comment = new byte[commentSize]; + + StreamUtils.ReadFully(baseStream_, comment); + comment_ = ZipConstants.ConvertToString(comment); + } + else { + comment_ = string.Empty; + } + + bool isZip64 = false; + + // Check if zip64 header information is required. + if ( (thisDiskNumber == 0xffff) || + (startCentralDirDisk == 0xffff) || + (entriesForThisDisk == 0xffff) || + (entriesForWholeCentralDir == 0xffff) || + (centralDirSize == 0xffffffff) || + (offsetOfCentralDir == 0xffffffff) ) { + isZip64 = true; + + long offset = LocateBlockWithSignature(ZipConstants.Zip64CentralDirLocatorSignature, locatedEndOfCentralDir, 0, 0x1000); + if ( offset < 0 ) { + throw new ZipException("Cannot find Zip64 locator"); + } + + // number of the disk with the start of the zip64 end of central directory 4 bytes + // relative offset of the zip64 end of central directory record 8 bytes + // total number of disks 4 bytes + ReadLEUint(); // startDisk64 is not currently used + ulong offset64 = ReadLEUlong(); + uint totalDisks = ReadLEUint(); + + baseStream_.Position = (long)offset64; + long sig64 = ReadLEUint(); + + if ( sig64 != ZipConstants.Zip64CentralFileHeaderSignature ) { + throw new ZipException(string.Format("Invalid Zip64 Central directory signature at {0:X}", offset64)); + } + + // NOTE: Record size = SizeOfFixedFields + SizeOfVariableData - 12. + ulong recordSize = ReadLEUlong(); + int versionMadeBy = ReadLEUshort(); + int versionToExtract = ReadLEUshort(); + uint thisDisk = ReadLEUint(); + uint centralDirDisk = ReadLEUint(); + entriesForThisDisk = ReadLEUlong(); + entriesForWholeCentralDir = ReadLEUlong(); + centralDirSize = ReadLEUlong(); + offsetOfCentralDir = (long)ReadLEUlong(); + + // NOTE: zip64 extensible data sector (variable size) is ignored. + } + + entries_ = new ZipEntry[entriesForThisDisk]; + + // SFX/embedded support, find the offset of the first entry vis the start of the stream + // This applies to Zip files that are appended to the end of an SFX stub. + // Or are appended as a resource to an executable. + // Zip files created by some archivers have the offsets altered to reflect the true offsets + // and so dont require any adjustment here... + // TODO: Difficulty with Zip64 and SFX offset handling needs resolution - maths? + if ( !isZip64 && (offsetOfCentralDir < locatedEndOfCentralDir - (4 + (long)centralDirSize)) ) { + offsetOfFirstEntry = locatedEndOfCentralDir - (4 + (long)centralDirSize + offsetOfCentralDir); + if (offsetOfFirstEntry <= 0) { + throw new ZipException("Invalid embedded zip archive"); + } + } + + baseStream_.Seek(offsetOfFirstEntry + offsetOfCentralDir, SeekOrigin.Begin); + + for (ulong i = 0; i < entriesForThisDisk; i++) { + if (ReadLEUint() != ZipConstants.CentralHeaderSignature) { + throw new ZipException("Wrong Central Directory signature"); + } + + int versionMadeBy = ReadLEUshort(); + int versionToExtract = ReadLEUshort(); + int bitFlags = ReadLEUshort(); + int method = ReadLEUshort(); + uint dostime = ReadLEUint(); + uint crc = ReadLEUint(); + long csize = (long)ReadLEUint(); + long size = (long)ReadLEUint(); + int nameLen = ReadLEUshort(); + int extraLen = ReadLEUshort(); + int commentLen = ReadLEUshort(); + + int diskStartNo = ReadLEUshort(); // Not currently used + int internalAttributes = ReadLEUshort(); // Not currently used + + uint externalAttributes = ReadLEUint(); + long offset = ReadLEUint(); + + byte[] buffer = new byte[Math.Max(nameLen, commentLen)]; + + StreamUtils.ReadFully(baseStream_, buffer, 0, nameLen); + string name = ZipConstants.ConvertToStringExt(bitFlags, buffer, nameLen); + + ZipEntry entry = new ZipEntry(name, versionToExtract, versionMadeBy, (CompressionMethod)method); + entry.Crc = crc & 0xffffffffL; + entry.Size = size & 0xffffffffL; + entry.CompressedSize = csize & 0xffffffffL; + entry.Flags = bitFlags; + entry.DosTime = (uint)dostime; + entry.ZipFileIndex = (long)i; + entry.Offset = offset; + entry.ExternalFileAttributes = (int)externalAttributes; + + if ((bitFlags & 8) == 0) { + entry.CryptoCheckValue = (byte)(crc >> 24); + } + else { + entry.CryptoCheckValue = (byte)((dostime >> 8) & 0xff); + } + + if (extraLen > 0) { + byte[] extra = new byte[extraLen]; + StreamUtils.ReadFully(baseStream_, extra); + entry.ExtraData = extra; + } + + entry.ProcessExtraData(false); + + if (commentLen > 0) { + StreamUtils.ReadFully(baseStream_, buffer, 0, commentLen); + entry.Comment = ZipConstants.ConvertToStringExt(bitFlags, buffer, commentLen); + } + + entries_[i] = entry; + } + } + + /// + /// Locate the data for a given entry. + /// + /// + /// The start offset of the data. + /// + /// + /// The stream ends prematurely + /// + /// + /// The local header signature is invalid, the entry and central header file name lengths are different + /// or the local and entry compression methods dont match + /// + long LocateEntry(ZipEntry entry) + { + return TestLocalHeader(entry, HeaderTest.Extract); + } + +#if !NETCF_1_0 + Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) + { + CryptoStream result = null; + + if ( (entry.Version < ZipConstants.VersionStrongEncryption) + || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { + PkzipClassicManaged classicManaged = new PkzipClassicManaged(); + + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for encrypted stream"); + } + + result = new CryptoStream(baseStream, classicManaged.CreateDecryptor(key, null), CryptoStreamMode.Read); + CheckClassicPassword(result, entry); + } + else { +#if !NET_1_1 && !NETCF_2_0 + if (entry.Version == ZipConstants.VERSION_AES) { + // + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for AES encrypted stream"); + } + int saltLen = entry.AESSaltLen; + byte[] saltBytes = new byte[saltLen]; + int saltIn = baseStream.Read(saltBytes, 0, saltLen); + if (saltIn != saltLen) + throw new ZipException("AES Salt expected " + saltLen + " got " + saltIn); + // + byte[] pwdVerifyRead = new byte[2]; + baseStream.Read(pwdVerifyRead, 0, 2); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + ZipAESTransform decryptor = new ZipAESTransform(rawPassword_, saltBytes, blockSize, false); + byte[] pwdVerifyCalc = decryptor.PwdVerifier; + if (pwdVerifyCalc[0] != pwdVerifyRead[0] || pwdVerifyCalc[1] != pwdVerifyRead[1]) + throw new Exception("Invalid password for AES"); + result = new ZipAESStream(baseStream, decryptor, CryptoStreamMode.Read); + } + else +#endif + { + throw new ZipException("Decryption method not supported"); + } + } + + return result; + } + + Stream CreateAndInitEncryptionStream(Stream baseStream, ZipEntry entry) + { + CryptoStream result = null; + if ( (entry.Version < ZipConstants.VersionStrongEncryption) + || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { + PkzipClassicManaged classicManaged = new PkzipClassicManaged(); + + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for encrypted stream"); + } + + // Closing a CryptoStream will close the base stream as well so wrap it in an UncompressedStream + // which doesnt do this. + result = new CryptoStream(new UncompressedStream(baseStream), + classicManaged.CreateEncryptor(key, null), CryptoStreamMode.Write); + + if ( (entry.Crc < 0) || (entry.Flags & 8) != 0) { + WriteEncryptionHeader(result, entry.DosTime << 16); + } + else { + WriteEncryptionHeader(result, entry.Crc); + } + } + return result; + } + + static void CheckClassicPassword(CryptoStream classicCryptoStream, ZipEntry entry) + { + byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize]; + StreamUtils.ReadFully(classicCryptoStream, cryptbuffer); + if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue) { + throw new ZipException("Invalid password"); + } + } +#endif + + static void WriteEncryptionHeader(Stream stream, long crcValue) + { + byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize]; + Random rnd = new Random(); + rnd.NextBytes(cryptBuffer); + cryptBuffer[11] = (byte)(crcValue >> 24); + stream.Write(cryptBuffer, 0, cryptBuffer.Length); + } + + #endregion + + #region Instance Fields + bool isDisposed_; + string name_; + string comment_; + string rawPassword_; + Stream baseStream_; + bool isStreamOwner; + long offsetOfFirstEntry; + ZipEntry[] entries_; + byte[] key; + bool isNewArchive_; + + // Default is dynamic which is not backwards compatible and can cause problems + // with XP's built in compression which cant read Zip64 archives. + // However it does avoid the situation were a large file is added and cannot be completed correctly. + // Hint: Set always ZipEntry size before they are added to an archive and this setting isnt needed. + UseZip64 useZip64_ = UseZip64.Dynamic ; + + #region Zip Update Instance Fields + ArrayList updates_; + long updateCount_; // Count is managed manually as updates_ can contain nulls! + Hashtable updateIndex_; + IArchiveStorage archiveStorage_; + IDynamicDataSource updateDataSource_; + bool contentsEdited_; + int bufferSize_ = DefaultBufferSize; + byte[] copyBuffer_; + ZipString newComment_; + bool commentEdited_; + IEntryFactory updateEntryFactory_ = new ZipEntryFactory(); + #endregion + #endregion + + #region Support Classes + /// + /// Represents a string from a which is stored as an array of bytes. + /// + class ZipString + { + #region Constructors + /// + /// Initialise a with a string. + /// + /// The textual string form. + public ZipString(string comment) + { + comment_ = comment; + isSourceString_ = true; + } + + /// + /// Initialise a using a string in its binary 'raw' form. + /// + /// + public ZipString(byte[] rawString) + { + rawComment_ = rawString; + } + #endregion + + /// + /// Get a value indicating the original source of data for this instance. + /// True if the source was a string; false if the source was binary data. + /// + public bool IsSourceString + { + get { return isSourceString_; } + } + + /// + /// Get the length of the comment when represented as raw bytes. + /// + public int RawLength + { + get { + MakeBytesAvailable(); + return rawComment_.Length; + } + } + + /// + /// Get the comment in its 'raw' form as plain bytes. + /// + public byte[] RawComment + { + get { + MakeBytesAvailable(); + return (byte[])rawComment_.Clone(); + } + } + + /// + /// Reset the comment to its initial state. + /// + public void Reset() + { + if ( isSourceString_ ) { + rawComment_ = null; + } + else { + comment_ = null; + } + } + + void MakeTextAvailable() + { + if ( comment_ == null ) { + comment_ = ZipConstants.ConvertToString(rawComment_); + } + } + + void MakeBytesAvailable() + { + if ( rawComment_ == null ) { + rawComment_ = ZipConstants.ConvertToArray(comment_); + } + } + + /// + /// Implicit conversion of comment to a string. + /// + /// The to convert to a string. + /// The textual equivalent for the input value. + static public implicit operator string(ZipString zipString) + { + zipString.MakeTextAvailable(); + return zipString.comment_; + } + + #region Instance Fields + string comment_; + byte[] rawComment_; + bool isSourceString_; + #endregion + } + + /// + /// An enumerator for Zip entries + /// + class ZipEntryEnumerator : IEnumerator + { + #region Constructors + public ZipEntryEnumerator(ZipEntry[] entries) + { + array = entries; + } + + #endregion + #region IEnumerator Members + public object Current + { + get { + return array[index]; + } + } + + public void Reset() + { + index = -1; + } + + public bool MoveNext() + { + return (++index < array.Length); + } + #endregion + #region Instance Fields + ZipEntry[] array; + int index = -1; + #endregion + } + + /// + /// An is a stream that you can write uncompressed data + /// to and flush, but cannot read, seek or do anything else to. + /// + class UncompressedStream : Stream + { + #region Constructors + public UncompressedStream(Stream baseStream) + { + baseStream_ = baseStream; + } + + #endregion + + /// + /// Close this stream instance. + /// + public override void Close() + { + // Do nothing + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Write any buffered data to underlying storage. + /// + public override void Flush() + { + baseStream_.Flush(); + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + public override bool CanWrite + { + get { + return baseStream_.CanWrite; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek + { + get { + return false; + } + } + + /// + /// Get the length in bytes of the stream. + /// + public override long Length + { + get { + return 0; + } + } + + /// + /// Gets or sets the position within the current stream. + /// + public override long Position + { + get { + return baseStream_.Position; + } + + set + { + } + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + + /// + /// Sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// + /// The new position within the current stream. + /// + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. + public override long Seek(long offset, SeekOrigin origin) + { + return 0; + } + + /// + /// Sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. + public override void SetLength(long value) + { + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. + public override void Write(byte[] buffer, int offset, int count) + { + baseStream_.Write(buffer, offset, count); + } + + #region Instance Fields + Stream baseStream_; + #endregion + } + + /// + /// A is an + /// whose data is only a part or subsection of a file. + /// + class PartialInputStream : Stream + { + #region Constructors + /// + /// Initialise a new instance of the class. + /// + /// The containing the underlying stream to use for IO. + /// The start of the partial data. + /// The length of the partial data. + public PartialInputStream(ZipFile zipFile, long start, long length) + { + start_ = start; + length_ = length; + + // Although this is the only time the zipfile is used + // keeping a reference here prevents premature closure of + // this zip file and thus the baseStream_. + + // Code like this will cause apparently random failures depending + // on the size of the files and when garbage is collected. + // + // ZipFile z = new ZipFile (stream); + // Stream reader = z.GetInputStream(0); + // uses reader here.... + zipFile_ = zipFile; + baseStream_ = zipFile_.baseStream_; + readPos_ = start; + end_ = start + length; + } + #endregion + + /// + /// Read a byte from this stream. + /// + /// Returns the byte read or -1 on end of stream. + public override int ReadByte() + { + if (readPos_ >= end_) { + // -1 is the correct value at end of stream. + return -1; + } + + lock( baseStream_ ) { + baseStream_.Seek(readPos_++, SeekOrigin.Begin); + return baseStream_.ReadByte(); + } + } + + /// + /// Close this partial input stream. + /// + /// + /// The underlying stream is not closed. Close the parent ZipFile class to do that. + /// + public override void Close() + { + // Do nothing at all! + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. + public override int Read(byte[] buffer, int offset, int count) + { + lock(baseStream_) { + if (count > end_ - readPos_) { + count = (int) (end_ - readPos_); + if (count == 0) { + return 0; + } + } + + baseStream_.Seek(readPos_, SeekOrigin.Begin); + int readCount = baseStream_.Read(buffer, offset, count); + if (readCount > 0) { + readPos_ += readCount; + } + return readCount; + } + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + /// + /// When overridden in a derived class, sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + /// + /// When overridden in a derived class, sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// + /// The new position within the current stream. + /// + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. + public override long Seek(long offset, SeekOrigin origin) + { + long newPos = readPos_; + + switch ( origin ) + { + case SeekOrigin.Begin: + newPos = start_ + offset; + break; + + case SeekOrigin.Current: + newPos = readPos_ + offset; + break; + + case SeekOrigin.End: + newPos = end_ + offset; + break; + } + + if ( newPos < start_ ) { + throw new ArgumentException("Negative position is invalid"); + } + + if ( newPos >= end_ ) { + throw new IOException("Cannot seek past end"); + } + readPos_ = newPos; + return readPos_; + } + + /// + /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. + /// + /// An I/O error occurs. + public override void Flush() + { + // Nothing to do. + } + + /// + /// Gets or sets the position within the current stream. + /// + /// + /// The current position within the stream. + /// An I/O error occurs. + /// The stream does not support seeking. + /// Methods were called after the stream was closed. + public override long Position { + get { return readPos_ - start_; } + set { + long newPos = start_ + value; + + if ( newPos < start_ ) { + throw new ArgumentException("Negative position is invalid"); + } + + if ( newPos >= end_ ) { + throw new InvalidOperationException("Cannot seek past end"); + } + readPos_ = newPos; + } + } + + /// + /// Gets the length in bytes of the stream. + /// + /// + /// A long value representing the length of the stream in bytes. + /// A class derived from Stream does not support seeking. + /// Methods were called after the stream was closed. + public override long Length { + get { return length_; } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + /// false + /// true if the stream supports writing; otherwise, false. + public override bool CanWrite { + get { return false; } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + /// true + /// true if the stream supports seeking; otherwise, false. + public override bool CanSeek { + get { return true; } + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + /// true. + /// true if the stream supports reading; otherwise, false. + public override bool CanRead { + get { return true; } + } + +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + /// + /// Gets a value that determines whether the current stream can time out. + /// + /// + /// A value that determines whether the current stream can time out. + public override bool CanTimeout { + get { return baseStream_.CanTimeout; } + } +#endif + #region Instance Fields + ZipFile zipFile_; + Stream baseStream_; + long start_; + long length_; + long readPos_; + long end_; + #endregion + } + #endregion + } + + #endregion + + #region DataSources + /// + /// Provides a static way to obtain a source of data for an entry. + /// + public interface IStaticDataSource + { + /// + /// Get a source of data by creating a new stream. + /// + /// Returns a to use for compression input. + /// Ideally a new stream is created and opened to achieve this, to avoid locking problems. + Stream GetSource(); + } + + /// + /// Represents a source of data that can dynamically provide + /// multiple data sources based on the parameters passed. + /// + public interface IDynamicDataSource + { + /// + /// Get a data source. + /// + /// The to get a source for. + /// The name for data if known. + /// Returns a to use for compression input. + /// Ideally a new stream is created and opened to achieve this, to avoid locking problems. + Stream GetSource(ZipEntry entry, string name); + } + + /// + /// Default implementation of a for use with files stored on disk. + /// + public class StaticDiskDataSource : IStaticDataSource + { + /// + /// Initialise a new instnace of + /// + /// The name of the file to obtain data from. + public StaticDiskDataSource(string fileName) + { + fileName_ = fileName; + } + + #region IDataSource Members + + /// + /// Get a providing data. + /// + /// Returns a provising data. + public Stream GetSource() + { + return File.Open(fileName_, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + #endregion + #region Instance Fields + string fileName_; + #endregion + } + + + /// + /// Default implementation of for files stored on disk. + /// + public class DynamicDiskDataSource : IDynamicDataSource + { + /// + /// Initialise a default instance of . + /// + public DynamicDiskDataSource() + { + } + + #region IDataSource Members + /// + /// Get a providing data for an entry. + /// + /// The entry to provide data for. + /// The file name for data if known. + /// Returns a stream providing data; or null if not available + public Stream GetSource(ZipEntry entry, string name) + { + Stream result = null; + + if ( name != null ) { + result = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + return result; + } + + #endregion + } + + #endregion + + #region Archive Storage + /// + /// Defines facilities for data storage when updating Zip Archives. + /// + public interface IArchiveStorage + { + /// + /// Get the to apply during updates. + /// + FileUpdateMode UpdateMode { get; } + + /// + /// Get an empty that can be used for temporary output. + /// + /// Returns a temporary output + /// + Stream GetTemporaryOutput(); + + /// + /// Convert a temporary output stream to a final stream. + /// + /// The resulting final + /// + Stream ConvertTemporaryToFinal(); + + /// + /// Make a temporary copy of the original stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + Stream MakeTemporaryCopy(Stream stream); + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The current stream. + /// Returns a stream suitable for direct updating. + /// This may be the current stream passed. + Stream OpenForDirectUpdate(Stream stream); + + /// + /// Dispose of this instance. + /// + void Dispose(); + } + + /// + /// An abstract suitable for extension by inheritance. + /// + abstract public class BaseArchiveStorage : IArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The update mode. + protected BaseArchiveStorage(FileUpdateMode updateMode) + { + updateMode_ = updateMode; + } + #endregion + + #region IArchiveStorage Members + + /// + /// Gets a temporary output + /// + /// Returns the temporary output stream. + /// + public abstract Stream GetTemporaryOutput(); + + /// + /// Converts the temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + /// + public abstract Stream ConvertTemporaryToFinal(); + + /// + /// Make a temporary copy of a . + /// + /// The to make a copy of. + /// Returns a temporary output that is a copy of the input. + public abstract Stream MakeTemporaryCopy(Stream stream); + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The to open for direct update. + /// Returns a stream suitable for direct updating. + public abstract Stream OpenForDirectUpdate(Stream stream); + + /// + /// Disposes this instance. + /// + public abstract void Dispose(); + + /// + /// Gets the update mode applicable. + /// + /// The update mode. + public FileUpdateMode UpdateMode + { + get { + return updateMode_; + } + } + + #endregion + + #region Instance Fields + FileUpdateMode updateMode_; + #endregion + } + + /// + /// An implementation suitable for hard disks. + /// + public class DiskArchiveStorage : BaseArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The file. + /// The update mode. + public DiskArchiveStorage(ZipFile file, FileUpdateMode updateMode) + : base(updateMode) + { + if ( file.Name == null ) { + throw new ZipException("Cant handle non file archives"); + } + + fileName_ = file.Name; + } + + /// + /// Initializes a new instance of the class. + /// + /// The file. + public DiskArchiveStorage(ZipFile file) + : this(file, FileUpdateMode.Safe) + { + } + #endregion + + #region IArchiveStorage Members + + /// + /// Gets a temporary output for performing updates on. + /// + /// Returns the temporary output stream. + public override Stream GetTemporaryOutput() + { + if ( temporaryName_ != null ) { + temporaryName_ = GetTempFileName(temporaryName_, true); + temporaryStream_ = File.Open(temporaryName_, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + else { + // Determine where to place files based on internal strategy. + // Currently this is always done in system temp directory. + temporaryName_ = Path.GetTempFileName(); + temporaryStream_ = File.Open(temporaryName_, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + + return temporaryStream_; + } + + /// + /// Converts a temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + public override Stream ConvertTemporaryToFinal() + { + if ( temporaryStream_ == null ) { + throw new ZipException("No temporary stream has been created"); + } + + Stream result = null; + + string moveTempName = GetTempFileName(fileName_, false); + bool newFileCreated = false; + + try { + temporaryStream_.Close(); + File.Move(fileName_, moveTempName); + File.Move(temporaryName_, fileName_); + newFileCreated = true; + File.Delete(moveTempName); + + result = File.Open(fileName_, FileMode.Open, FileAccess.Read, FileShare.Read); + } + catch(Exception) { + result = null; + + // Try to roll back changes... + if ( !newFileCreated ) { + File.Move(moveTempName, fileName_); + File.Delete(temporaryName_); + } + + throw; + } + + return result; + } + + /// + /// Make a temporary copy of a stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + public override Stream MakeTemporaryCopy(Stream stream) + { + stream.Close(); + + temporaryName_ = GetTempFileName(fileName_, true); + File.Copy(fileName_, temporaryName_, true); + + temporaryStream_ = new FileStream(temporaryName_, + FileMode.Open, + FileAccess.ReadWrite); + return temporaryStream_; + } + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The current stream. + /// Returns a stream suitable for direct updating. + /// If the stream is not null this is used as is. + public override Stream OpenForDirectUpdate(Stream stream) + { + Stream result; + if ((stream == null) || !stream.CanWrite) + { + if (stream != null) { + stream.Close(); + } + + result = new FileStream(fileName_, + FileMode.Open, + FileAccess.ReadWrite); + } + else + { + result = stream; + } + + return result; + } + + /// + /// Disposes this instance. + /// + public override void Dispose() + { + if ( temporaryStream_ != null ) { + temporaryStream_.Close(); + } + } + + #endregion + + #region Internal routines + static string GetTempFileName(string original, bool makeTempFile) + { + string result = null; + + if ( original == null ) { + result = Path.GetTempFileName(); + } + else { + int counter = 0; + int suffixSeed = DateTime.Now.Second; + + while ( result == null ) { + counter += 1; + string newName = string.Format("{0}.{1}{2}.tmp", original, suffixSeed, counter); + if ( !File.Exists(newName) ) { + if ( makeTempFile) { + try { + // Try and create the file. + using ( FileStream stream = File.Create(newName) ) { + } + result = newName; + } + catch { + suffixSeed = DateTime.Now.Second; + } + } + else { + result = newName; + } + } + } + } + return result; + } + #endregion + + #region Instance Fields + Stream temporaryStream_; + string fileName_; + string temporaryName_; + #endregion + } + + /// + /// An implementation suitable for in memory streams. + /// + public class MemoryArchiveStorage : BaseArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + public MemoryArchiveStorage() + : base(FileUpdateMode.Direct) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The to use + /// This constructor is for testing as memory streams dont really require safe mode. + public MemoryArchiveStorage(FileUpdateMode updateMode) + : base(updateMode) + { + } + + #endregion + + #region Properties + /// + /// Get the stream returned by if this was in fact called. + /// + public MemoryStream FinalStream + { + get { return finalStream_; } + } + + #endregion + + #region IArchiveStorage Members + + /// + /// Gets the temporary output + /// + /// Returns the temporary output stream. + public override Stream GetTemporaryOutput() + { + temporaryStream_ = new MemoryStream(); + return temporaryStream_; + } + + /// + /// Converts the temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + public override Stream ConvertTemporaryToFinal() + { + if ( temporaryStream_ == null ) { + throw new ZipException("No temporary stream has been created"); + } + + finalStream_ = new MemoryStream(temporaryStream_.ToArray()); + return finalStream_; + } + + /// + /// Make a temporary copy of the original stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + public override Stream MakeTemporaryCopy(Stream stream) + { + temporaryStream_ = new MemoryStream(); + stream.Position = 0; + StreamUtils.Copy(stream, temporaryStream_, new byte[4096]); + return temporaryStream_; + } + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The original source stream + /// Returns a stream suitable for direct updating. + /// If the passed is not null this is used; + /// otherwise a new is returned. + public override Stream OpenForDirectUpdate(Stream stream) + { + Stream result; + if ((stream == null) || !stream.CanWrite) { + + result = new MemoryStream(); + + if (stream != null) { + stream.Position = 0; + StreamUtils.Copy(stream, result, new byte[4096]); + + stream.Close(); + } + } + else { + result = stream; + } + + return result; + } + + /// + /// Disposes this instance. + /// + public override void Dispose() + { + if ( temporaryStream_ != null ) { + temporaryStream_.Close(); + } + } + + #endregion + + #region Instance Fields + MemoryStream temporaryStream_; + MemoryStream finalStream_; + #endregion + } + + #endregion +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipHelperStream.cs b/PCRobot/Utils/ZIP/Zip/ZipHelperStream.cs new file mode 100644 index 0000000..1998b72 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipHelperStream.cs @@ -0,0 +1,624 @@ +// ZipHelperStream.cs +// +// Copyright 2006, 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using ICSharpCode.SharpZipLib.Zip1; +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Holds data pertinent to a data descriptor. + /// + public class DescriptorData + { + /// + /// Get /set the compressed size of data. + /// + public long CompressedSize + { + get { return compressedSize; } + set { compressedSize = value; } + } + + /// + /// Get / set the uncompressed size of data + /// + public long Size + { + get { return size; } + set { size = value; } + } + + /// + /// Get /set the crc value. + /// + public long Crc + { + get { return crc; } + set { crc = (value & 0xffffffff); } + } + + #region Instance Fields + long size; + long compressedSize; + long crc; + #endregion + } + + class EntryPatchData + { + public long SizePatchOffset + { + get { return sizePatchOffset_; } + set { sizePatchOffset_ = value; } + } + + public long CrcPatchOffset + { + get { return crcPatchOffset_; } + set { crcPatchOffset_ = value; } + } + + #region Instance Fields + long sizePatchOffset_; + long crcPatchOffset_; + #endregion + } + + /// + /// This class assists with writing/reading from Zip files. + /// + internal class ZipHelperStream : Stream + { + #region Constructors + /// + /// Initialise an instance of this class. + /// + /// The name of the file to open. + public ZipHelperStream(string name) + { + stream_ = new FileStream(name, FileMode.Open, FileAccess.ReadWrite); + isOwner_ = true; + } + + /// + /// Initialise a new instance of . + /// + /// The stream to use. + public ZipHelperStream(Stream stream) + { + stream_ = stream; + } + #endregion + + /// + /// Get / set a value indicating wether the the underlying stream is owned or not. + /// + /// If the stream is owned it is closed when this instance is closed. + public bool IsStreamOwner + { + get { return isOwner_; } + set { isOwner_ = value; } + } + + #region Base Stream Methods + public override bool CanRead + { + get { return stream_.CanRead; } + } + + public override bool CanSeek + { + get { return stream_.CanSeek; } + } + +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + public override bool CanTimeout + { + get { return stream_.CanTimeout; } + } +#endif + + public override long Length + { + get { return stream_.Length; } + } + + public override long Position + { + get { return stream_.Position; } + set { stream_.Position = value; } + } + + public override bool CanWrite + { + get { return stream_.CanWrite; } + } + + public override void Flush() + { + stream_.Flush(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + return stream_.Seek(offset, origin); + } + + public override void SetLength(long value) + { + stream_.SetLength(value); + } + + public override int Read(byte[] buffer, int offset, int count) + { + return stream_.Read(buffer, offset, count); + } + + public override void Write(byte[] buffer, int offset, int count) + { + stream_.Write(buffer, offset, count); + } + + /// + /// Close the stream. + /// + /// + /// The underlying stream is closed only if is true. + /// + override public void Close() + { + Stream toClose = stream_; + stream_ = null; + if (isOwner_ && (toClose != null)) + { + isOwner_ = false; + toClose.Close(); + } + } + #endregion + + // Write the local file header + // TODO: ZipHelperStream.WriteLocalHeader is not yet used and needs checking for ZipFile and ZipOuptutStream usage + void WriteLocalHeader(ZipEntry entry, EntryPatchData patchData) + { + CompressionMethod method = entry.CompressionMethod; + bool headerInfoAvailable = true; // How to get this? + bool patchEntryHeader = false; + + WriteLEInt(ZipConstants.LocalHeaderSignature); + + WriteLEShort(entry.Version); + WriteLEShort(entry.Flags); + WriteLEShort((byte)method); + WriteLEInt((int)entry.DosTime); + + if (headerInfoAvailable == true) { + WriteLEInt((int)entry.Crc); + if ( entry.LocalHeaderRequiresZip64 ) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + WriteLEInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize); + WriteLEInt((int)entry.Size); + } + } else { + if (patchData != null) { + patchData.CrcPatchOffset = stream_.Position; + } + WriteLEInt(0); // Crc + + if ( patchData != null ) { + patchData.SizePatchOffset = stream_.Position; + } + + // For local header both sizes appear in Zip64 Extended Information + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + WriteLEInt(0); // Compressed size + WriteLEInt(0); // Uncompressed size + } + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xFFFF) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if (entry.LocalHeaderRequiresZip64 && (headerInfoAvailable || patchEntryHeader)) { + ed.StartNewEntry(); + if (headerInfoAvailable) { + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + } + else { + ed.AddLeLong(-1); + ed.AddLeLong(-1); + } + ed.AddNewEntry(1); + + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cant find extra data"); + } + + if ( patchData != null ) { + patchData.SizePatchOffset = ed.CurrentReadIndex; + } + } + else { + ed.Delete(1); + } + + byte[] extra = ed.GetEntryData(); + + WriteLEShort(name.Length); + WriteLEShort(extra.Length); + + if ( name.Length > 0 ) { + stream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + patchData.SizePatchOffset += stream_.Position; + } + + if ( extra.Length > 0 ) { + stream_.Write(extra, 0, extra.Length); + } + } + + /// + /// Locates a block with the desired . + /// + /// The signature to find. + /// Location, marking the end of block. + /// Minimum size of the block. + /// The maximum variable data. + /// Eeturns the offset of the first byte after the signature; -1 if not found + public long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + { + long pos = endLocation - minimumBlockSize; + if ( pos < 0 ) { + return -1; + } + + long giveUpMarker = Math.Max(pos - maximumVariableData, 0); + + // TODO: This loop could be optimised for speed. + do { + if ( pos < giveUpMarker ) { + return -1; + } + Seek(pos--, SeekOrigin.Begin); + } while ( ReadLEInt() != signature ); + + return Position; + } + + /// + /// Write Zip64 end of central directory records (File header and locator). + /// + /// The number of entries in the central directory. + /// The size of entries in the central directory. + /// The offset of the dentral directory. + public void WriteZip64EndOfCentralDirectory(long noOfEntries, long sizeEntries, long centralDirOffset) + { + long centralSignatureOffset = stream_.Position; + WriteLEInt(ZipConstants.Zip64CentralFileHeaderSignature); + WriteLELong(44); // Size of this record (total size of remaining fields in header or full size - 12) + WriteLEShort(ZipConstants.VersionMadeBy); // Version made by + WriteLEShort(ZipConstants.VersionZip64); // Version to extract + WriteLEInt(0); // Number of this disk + WriteLEInt(0); // number of the disk with the start of the central directory + WriteLELong(noOfEntries); // No of entries on this disk + WriteLELong(noOfEntries); // Total No of entries in central directory + WriteLELong(sizeEntries); // Size of the central directory + WriteLELong(centralDirOffset); // offset of start of central directory + // zip64 extensible data sector not catered for here (variable size) + + // Write the Zip64 end of central directory locator + WriteLEInt(ZipConstants.Zip64CentralDirLocatorSignature); + + // no of the disk with the start of the zip64 end of central directory + WriteLEInt(0); + + // relative offset of the zip64 end of central directory record + WriteLELong(centralSignatureOffset); + + // total number of disks + WriteLEInt(1); + } + + /// + /// Write the required records to end the central directory. + /// + /// The number of entries in the directory. + /// The size of the entries in the directory. + /// The start of the central directory. + /// The archive comment. (This can be null). + public void WriteEndOfCentralDirectory(long noOfEntries, long sizeEntries, + long startOfCentralDirectory, byte[] comment) + { + + if ( (noOfEntries >= 0xffff) || + (startOfCentralDirectory >= 0xffffffff) || + (sizeEntries >= 0xffffffff) ) { + WriteZip64EndOfCentralDirectory(noOfEntries, sizeEntries, startOfCentralDirectory); + } + + WriteLEInt(ZipConstants.EndOfCentralDirectorySignature); + + // TODO: ZipFile Multi disk handling not done + WriteLEShort(0); // number of this disk + WriteLEShort(0); // no of disk with start of central dir + + + // Number of entries + if ( noOfEntries >= 0xffff ) { + WriteLEUshort(0xffff); // Zip64 marker + WriteLEUshort(0xffff); + } + else { + WriteLEShort(( short )noOfEntries); // entries in central dir for this disk + WriteLEShort(( short )noOfEntries); // total entries in central directory + } + + // Size of the central directory + if ( sizeEntries >= 0xffffffff ) { + WriteLEUint(0xffffffff); // Zip64 marker + } + else { + WriteLEInt(( int )sizeEntries); + } + + + // offset of start of central directory + if ( startOfCentralDirectory >= 0xffffffff ) { + WriteLEUint(0xffffffff); // Zip64 marker + } + else { + WriteLEInt(( int )startOfCentralDirectory); + } + + int commentLength = (comment != null) ? comment.Length : 0; + + if ( commentLength > 0xffff ) { + throw new ZipException(string.Format("Comment length({0}) is too long can only be 64K", commentLength)); + } + + WriteLEShort(commentLength); + + if ( commentLength > 0 ) { + Write(comment, 0, comment.Length); + } + } + + #region LE value reading/writing + /// + /// Read an unsigned short in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + public int ReadLEShort() + { + int byteValue1 = stream_.ReadByte(); + + if (byteValue1 < 0) { + throw new EndOfStreamException(); + } + + int byteValue2 = stream_.ReadByte(); + if (byteValue2 < 0) { + throw new EndOfStreamException(); + } + + return byteValue1 | (byteValue2 << 8); + } + + /// + /// Read an int in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + public int ReadLEInt() + { + return ReadLEShort() | (ReadLEShort() << 16); + } + + /// + /// Read a long in little endian byte order. + /// + /// The value read. + public long ReadLELong() + { + return (uint)ReadLEInt() | ((long)ReadLEInt() << 32); + } + + /// + /// Write an unsigned short in little endian byte order. + /// + /// The value to write. + public void WriteLEShort(int value) + { + stream_.WriteByte(( byte )(value & 0xff)); + stream_.WriteByte(( byte )((value >> 8) & 0xff)); + } + + /// + /// Write a ushort in little endian byte order. + /// + /// The value to write. + public void WriteLEUshort(ushort value) + { + stream_.WriteByte(( byte )(value & 0xff)); + stream_.WriteByte(( byte )(value >> 8)); + } + + /// + /// Write an int in little endian byte order. + /// + /// The value to write. + public void WriteLEInt(int value) + { + WriteLEShort(value); + WriteLEShort(value >> 16); + } + + /// + /// Write a uint in little endian byte order. + /// + /// The value to write. + public void WriteLEUint(uint value) + { + WriteLEUshort(( ushort )(value & 0xffff)); + WriteLEUshort(( ushort )(value >> 16)); + } + + /// + /// Write a long in little endian byte order. + /// + /// The value to write. + public void WriteLELong(long value) + { + WriteLEInt(( int )value); + WriteLEInt(( int )(value >> 32)); + } + + /// + /// Write a ulong in little endian byte order. + /// + /// The value to write. + public void WriteLEUlong(ulong value) + { + WriteLEUint(( uint )(value & 0xffffffff)); + WriteLEUint(( uint )(value >> 32)); + } + + #endregion + + /// + /// Write a data descriptor. + /// + /// The entry to write a descriptor for. + /// Returns the number of descriptor bytes written. + public int WriteDataDescriptor(ZipEntry entry) + { + if (entry == null) { + throw new ArgumentNullException("entry"); + } + + int result=0; + + // Add data descriptor if flagged as required + if ((entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) + { + // The signature is not PKZIP originally but is now described as optional + // in the PKZIP Appnote documenting trhe format. + WriteLEInt(ZipConstants.DataDescriptorSignature); + WriteLEInt(unchecked((int)(entry.Crc))); + + result+=8; + + if (entry.LocalHeaderRequiresZip64) + { + WriteLELong(entry.CompressedSize); + WriteLELong(entry.Size); + result+=16; + } + else + { + WriteLEInt((int)entry.CompressedSize); + WriteLEInt((int)entry.Size); + result+=8; + } + } + + return result; + } + + /// + /// Read data descriptor at the end of compressed data. + /// + /// if set to true [zip64]. + /// The data to fill in. + /// Returns the number of bytes read in the descriptor. + public void ReadDataDescriptor(bool zip64, DescriptorData data) + { + int intValue = ReadLEInt(); + + // In theory this may not be a descriptor according to PKZIP appnote. + // In practise its always there. + if (intValue != ZipConstants.DataDescriptorSignature) { + throw new ZipException("Data descriptor signature not found"); + } + + data.Crc = ReadLEInt(); + + if (zip64) { + data.CompressedSize = ReadLELong(); + data.Size = ReadLELong(); + } + else { + data.CompressedSize = ReadLEInt(); + data.Size = ReadLEInt(); + } + } + + #region Instance Fields + bool isOwner_; + Stream stream_; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipInputStream.cs b/PCRobot/Utils/ZIP/Zip/ZipInputStream.cs new file mode 100644 index 0000000..9c00125 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipInputStream.cs @@ -0,0 +1,676 @@ +// ZipInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2010-05-25 Z-1663 Fixed exception when testing local header compressed size of -1 + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using ICSharpCode.SharpZipLib.Zip; + +#if !NETCF_1_0 +using ICSharpCode.SharpZipLib.Encryption; +#endif + +namespace ICSharpCode.SharpZipLib.Zip1 +{ + /// + /// This is an InflaterInputStream that reads the files baseInputStream an zip archive + /// one after another. It has a special method to get the zip entry of + /// the next file. The zip entry contains information about the file name + /// size, compressed size, Crc, etc. + /// It includes support for Stored and Deflated entries. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// + /// This sample shows how to read a zip file + /// + /// using System; + /// using System.Text; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using ( ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]))) { + /// + /// ZipEntry theEntry; + /// const int size = 2048; + /// byte[] data = new byte[2048]; + /// + /// while ((theEntry = s.GetNextEntry()) != null) { + /// if ( entry.IsFile ) { + /// Console.Write("Show contents (y/n) ?"); + /// if (Console.ReadLine() == "y") { + /// while (true) { + /// size = s.Read(data, 0, data.Length); + /// if (size > 0) { + /// Console.Write(new ASCIIEncoding().GetString(data, 0, size)); + /// } else { + /// break; + /// } + /// } + /// } + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipInputStream : InflaterInputStream + { + #region Instance Fields + + /// + /// Delegate for reading bytes from a stream. + /// + delegate int ReadDataHandler(byte[] b, int offset, int length); + + /// + /// The current reader this instance. + /// + ReadDataHandler internalReader; + + Crc32 crc = new Crc32(); + ZipEntry entry; + + long size; + int method; + int flags; + string password; + #endregion + + #region Constructors + /// + /// Creates a new Zip input stream, for reading a zip archive. + /// + /// The underlying providing data. + public ZipInputStream(Stream baseInputStream) + : base(baseInputStream, new Inflater(true)) + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + } + + /// + /// Creates a new Zip input stream, for reading a zip archive. + /// + /// The underlying providing data. + /// Size of the buffer. + public ZipInputStream( Stream baseInputStream, int bufferSize ) + : base(baseInputStream, new Inflater(true), bufferSize) + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + } + #endregion + + /// + /// Optional password used for encryption when non-null + /// + /// A password for all encrypted entries in this + public string Password + { + get { + return password; + } + set { + password = value; + } + } + + + /// + /// Gets a value indicating if there is a current entry and it can be decompressed + /// + /// + /// The entry can only be decompressed if the library supports the zip features required to extract it. + /// See the ZipEntry Version property for more details. + /// + public bool CanDecompressEntry { + get { + return (entry != null) && entry.CanDecompress; + } + } + + /// + /// Advances to the next entry in the archive + /// + /// + /// The next entry in the archive or null if there are no more entries. + /// + /// + /// If the previous entry is still open CloseEntry is called. + /// + /// + /// Input stream is closed + /// + /// + /// Password is not set, password is invalid, compression method is invalid, + /// version required to extract is not supported + /// + public ZipEntry GetNextEntry() + { + if (crc == null) { + throw new InvalidOperationException("Closed."); + } + + if (entry != null) { + CloseEntry(); + } + + int header = inputBuffer.ReadLeInt(); + + if (header == ZipConstants.CentralHeaderSignature || + header == ZipConstants.EndOfCentralDirectorySignature || + header == ZipConstants.CentralHeaderDigitalSignature || + header == ZipConstants.ArchiveExtraDataSignature || + header == ZipConstants.Zip64CentralFileHeaderSignature) { + // No more individual entries exist + Close(); + return null; + } + + // -jr- 07-Dec-2003 Ignore spanning temporary signatures if found + // Spanning signature is same as descriptor signature and is untested as yet. + if ( (header == ZipConstants.SpanningTempSignature) || (header == ZipConstants.SpanningSignature) ) { + header = inputBuffer.ReadLeInt(); + } + + if (header != ZipConstants.LocalHeaderSignature) { + throw new ZipException("Wrong Local header signature: 0x" + String.Format("{0:X}", header)); + } + + short versionRequiredToExtract = (short)inputBuffer.ReadLeShort(); + + flags = inputBuffer.ReadLeShort(); + method = inputBuffer.ReadLeShort(); + uint dostime = (uint)inputBuffer.ReadLeInt(); + int crc2 = inputBuffer.ReadLeInt(); + csize = inputBuffer.ReadLeInt(); + size = inputBuffer.ReadLeInt(); + int nameLen = inputBuffer.ReadLeShort(); + int extraLen = inputBuffer.ReadLeShort(); + + bool isCrypted = (flags & 1) == 1; + + byte[] buffer = new byte[nameLen]; + inputBuffer.ReadRawBuffer(buffer); + + string name = ZipConstants.ConvertToStringExt(flags, buffer); + + entry = new ZipEntry(name, versionRequiredToExtract); + entry.Flags = flags; + + entry.CompressionMethod = (CompressionMethod)method; + + if ((flags & 8) == 0) { + entry.Crc = crc2 & 0xFFFFFFFFL; + entry.Size = size & 0xFFFFFFFFL; + entry.CompressedSize = csize & 0xFFFFFFFFL; + + entry.CryptoCheckValue = (byte)((crc2 >> 24) & 0xff); + + } else { + + // This allows for GNU, WinZip and possibly other archives, the PKZIP spec + // says these values are zero under these circumstances. + if (crc2 != 0) { + entry.Crc = crc2 & 0xFFFFFFFFL; + } + + if (size != 0) { + entry.Size = size & 0xFFFFFFFFL; + } + + if (csize != 0) { + entry.CompressedSize = csize & 0xFFFFFFFFL; + } + + entry.CryptoCheckValue = (byte)((dostime >> 8) & 0xff); + } + + entry.DosTime = dostime; + + // If local header requires Zip64 is true then the extended header should contain + // both values. + + // Handle extra data if present. This can set/alter some fields of the entry. + if (extraLen > 0) { + byte[] extra = new byte[extraLen]; + inputBuffer.ReadRawBuffer(extra); + entry.ExtraData = extra; + } + + entry.ProcessExtraData(true); + if ( entry.CompressedSize >= 0 ) { + csize = entry.CompressedSize; + } + + if ( entry.Size >= 0 ) { + size = entry.Size; + } + + if (method == (int)CompressionMethod.Stored && (!isCrypted && csize != size || (isCrypted && csize - ZipConstants.CryptoHeaderSize != size))) { + throw new ZipException("Stored, but compressed != uncompressed"); + } + + // Determine how to handle reading of data if this is attempted. + if (entry.IsCompressionMethodSupported()) { + internalReader = new ReadDataHandler(InitialRead); + } else { + internalReader = new ReadDataHandler(ReadingNotSupported); + } + + return entry; + } + + /// + /// Read data descriptor at the end of compressed data. + /// + void ReadDataDescriptor() + { + if (inputBuffer.ReadLeInt() != ZipConstants.DataDescriptorSignature) { + throw new ZipException("Data descriptor signature not found"); + } + + entry.Crc = inputBuffer.ReadLeInt() & 0xFFFFFFFFL; + + if ( entry.LocalHeaderRequiresZip64 ) { + csize = inputBuffer.ReadLeLong(); + size = inputBuffer.ReadLeLong(); + } else { + csize = inputBuffer.ReadLeInt(); + size = inputBuffer.ReadLeInt(); + } + entry.CompressedSize = csize; + entry.Size = size; + } + + /// + /// Complete cleanup as the final part of closing. + /// + /// True if the crc value should be tested + void CompleteCloseEntry(bool testCrc) + { + StopDecrypting(); + + if ((flags & 8) != 0) { + ReadDataDescriptor(); + } + + size = 0; + + if ( testCrc && + ((crc.Value & 0xFFFFFFFFL) != entry.Crc) && (entry.Crc != -1)) { + throw new ZipException("CRC mismatch"); + } + + crc.Reset(); + + if (method == (int)CompressionMethod.Deflated) { + inf.Reset(); + } + entry = null; + } + + /// + /// Closes the current zip entry and moves to the next one. + /// + /// + /// The stream is closed + /// + /// + /// The Zip stream ends early + /// + public void CloseEntry() + { + if (crc == null) { + throw new InvalidOperationException("Closed"); + } + + if (entry == null) { + return; + } + + if (method == (int)CompressionMethod.Deflated) { + if ((flags & 8) != 0) { + // We don't know how much we must skip, read until end. + byte[] tmp = new byte[4096]; + + // Read will close this entry + while (Read(tmp, 0, tmp.Length) > 0) { + } + return; + } + + csize -= inf.TotalIn; + inputBuffer.Available += inf.RemainingInput; + } + + if ( (inputBuffer.Available > csize) && (csize >= 0) ) { + inputBuffer.Available = (int)((long)inputBuffer.Available - csize); + } else { + csize -= inputBuffer.Available; + inputBuffer.Available = 0; + while (csize != 0) { + long skipped = base.Skip(csize); + + if (skipped <= 0) { + throw new ZipException("Zip archive ends early."); + } + + csize -= skipped; + } + } + + CompleteCloseEntry(false); + } + + /// + /// Returns 1 if there is an entry available + /// Otherwise returns 0. + /// + public override int Available { + get { + return entry != null ? 1 : 0; + } + } + + /// + /// Returns the current size that can be read from the current entry if available + /// + /// Thrown if the entry size is not known. + /// Thrown if no entry is currently available. + public override long Length + { + get { + if ( entry != null ) { + if ( entry.Size >= 0 ) { + return entry.Size; + } else { + throw new ZipException("Length not available for the current entry"); + } + } + else { + throw new InvalidOperationException("No current entry"); + } + } + + } + + /// + /// Reads a byte from the current zip entry. + /// + /// + /// The byte or -1 if end of stream is reached. + /// + public override int ReadByte() + { + byte[] b = new byte[1]; + if (Read(b, 0, 1) <= 0) { + return -1; + } + return b[0] & 0xff; + } + + /// + /// Handle attempts to read by throwing an . + /// + /// The destination array to store data in. + /// The offset at which data read should be stored. + /// The maximum number of bytes to read. + /// Returns the number of bytes actually read. + int ReadingNotAvailable(byte[] destination, int offset, int count) + { + throw new InvalidOperationException("Unable to read from this stream"); + } + + /// + /// Handle attempts to read from this entry by throwing an exception + /// + int ReadingNotSupported(byte[] destination, int offset, int count) + { + throw new ZipException("The compression method for this entry is not supported"); + } + + /// + /// Perform the initial read on an entry which may include + /// reading encryption headers and setting up inflation. + /// + /// The destination to fill with data read. + /// The offset to start reading at. + /// The maximum number of bytes to read. + /// The actual number of bytes read. + int InitialRead(byte[] destination, int offset, int count) + { + if ( !CanDecompressEntry ) { + throw new ZipException("Library cannot extract this entry. Version required is (" + entry.Version.ToString() + ")"); + } + + // Handle encryption if required. + if (entry.IsCrypted) { +#if NETCF_1_0 + throw new ZipException("Encryption not supported for Compact Framework 1.0"); +#else + if (password == null) { + throw new ZipException("No password set."); + } + + // Generate and set crypto transform... + PkzipClassicManaged managed = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password)); + + inputBuffer.CryptoTransform = managed.CreateDecryptor(key, null); + + byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize]; + inputBuffer.ReadClearTextBuffer(cryptbuffer, 0, ZipConstants.CryptoHeaderSize); + + if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue) { + throw new ZipException("Invalid password"); + } + + if (csize >= ZipConstants.CryptoHeaderSize) { + csize -= ZipConstants.CryptoHeaderSize; + } + else if ( (entry.Flags & (int)GeneralBitFlags.Descriptor) == 0 ) { + throw new ZipException(string.Format("Entry compressed size {0} too small for encryption", csize)); + } +#endif + } else { +#if !NETCF_1_0 + inputBuffer.CryptoTransform = null; +#endif + } + + if ((csize > 0) || ((flags & (int)GeneralBitFlags.Descriptor) != 0)) { + if ((method == (int)CompressionMethod.Deflated) && (inputBuffer.Available > 0)) { + inputBuffer.SetInflaterInput(inf); + } + + internalReader = new ReadDataHandler(BodyRead); + return BodyRead(destination, offset, count); + } + else { + internalReader = new ReadDataHandler(ReadingNotAvailable); + return 0; + } + } + + /// + /// Read a block of bytes from the stream. + /// + /// The destination for the bytes. + /// The index to start storing data. + /// The number of bytes to attempt to read. + /// Returns the number of bytes read. + /// Zero bytes read means end of stream. + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (buffer.Length - offset) < count ) { + throw new ArgumentException("Invalid offset/count combination"); + } + + return internalReader(buffer, offset, count); + } + + /// + /// Reads a block of bytes from the current zip entry. + /// + /// + /// The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. + /// + /// + /// An i/o error occured. + /// + /// + /// The deflated stream is corrupted. + /// + /// + /// The stream is not open. + /// + int BodyRead(byte[] buffer, int offset, int count) + { + if ( crc == null ) { + throw new InvalidOperationException("Closed"); + } + + if ( (entry == null) || (count <= 0) ) { + return 0; + } + + if ( offset + count > buffer.Length ) { + throw new ArgumentException("Offset + count exceeds buffer size"); + } + + bool finished = false; + + switch (method) { + case (int)CompressionMethod.Deflated: + count = base.Read(buffer, offset, count); + if (count <= 0) { + if (!inf.IsFinished) { + throw new ZipException("Inflater not finished!"); + } + inputBuffer.Available = inf.RemainingInput; + + // A csize of -1 is from an unpatched local header + if ((flags & 8) == 0 && + (inf.TotalIn != csize && csize != 0xFFFFFFFF && csize != -1 || inf.TotalOut != size)) { + throw new ZipException("Size mismatch: " + csize + ";" + size + " <-> " + inf.TotalIn + ";" + inf.TotalOut); + } + inf.Reset(); + finished = true; + } + break; + + case (int)CompressionMethod.Stored: + if ( (count > csize) && (csize >= 0) ) { + count = (int)csize; + } + + if ( count > 0 ) { + count = inputBuffer.ReadClearTextBuffer(buffer, offset, count); + if (count > 0) { + csize -= count; + size -= count; + } + } + + if (csize == 0) { + finished = true; + } else { + if (count < 0) { + throw new ZipException("EOF in stored block"); + } + } + break; + } + + if (count > 0) { + crc.Update(buffer, offset, count); + } + + if (finished) { + CompleteCloseEntry(true); + } + + return count; + } + + /// + /// Closes the zip input stream + /// + public override void Close() + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + crc = null; + entry = null; + + base.Close(); + } + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipNameTransform.cs b/PCRobot/Utils/ZIP/Zip/ZipNameTransform.cs new file mode 100644 index 0000000..9dc1176 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipNameTransform.cs @@ -0,0 +1,269 @@ +// ZipNameTransform.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +using System; +using System.IO; +using System.Text; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// ZipNameTransform transforms names as per the Zip file naming convention. + /// + /// The use of absolute names is supported although its use is not valid + /// according to Zip naming conventions, and should not be used if maximum compatability is desired. + public class ZipNameTransform : INameTransform + { + #region Constructors + /// + /// Initialize a new instance of + /// + public ZipNameTransform() + { + } + + /// + /// Initialize a new instance of + /// + /// The string to trim from the front of paths if found. + public ZipNameTransform(string trimPrefix) + { + TrimPrefix = trimPrefix; + } + #endregion + + /// + /// Static constructor. + /// + static ZipNameTransform() + { + char[] invalidPathChars; +#if NET_1_0 || NET_1_1 || NETCF_1_0 + invalidPathChars = Path.InvalidPathChars; +#else + invalidPathChars = Path.GetInvalidPathChars(); +#endif + int howMany = invalidPathChars.Length + 2; + + InvalidEntryCharsRelaxed = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryCharsRelaxed, 0, invalidPathChars.Length); + InvalidEntryCharsRelaxed[howMany - 1] = '*'; + InvalidEntryCharsRelaxed[howMany - 2] = '?'; + + howMany = invalidPathChars.Length + 4; + InvalidEntryChars = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length); + InvalidEntryChars[howMany - 1] = ':'; + InvalidEntryChars[howMany - 2] = '\\'; + InvalidEntryChars[howMany - 3] = '*'; + InvalidEntryChars[howMany - 4] = '?'; + } + + /// + /// Transform a windows directory name according to the Zip file naming conventions. + /// + /// The directory name to transform. + /// The transformed name. + public string TransformDirectory(string name) + { + name = TransformFile(name); + if (name.Length > 0) { + if ( !name.EndsWith("/") ) { + name += "/"; + } + } + else { + throw new ZipException("Cannot have an empty directory name"); + } + return name; + } + + /// + /// Transform a windows file name according to the Zip file naming conventions. + /// + /// The file name to transform. + /// The transformed name. + public string TransformFile(string name) + { + if (name != null) { + string lowerName = name.ToLower(); + if ( (trimPrefix_ != null) && (lowerName.IndexOf(trimPrefix_) == 0) ) { + name = name.Substring(trimPrefix_.Length); + } + + name = name.Replace(@"\", "/"); + name = WindowsPathUtils.DropPathRoot(name); + + // Drop any leading slashes. + while ((name.Length > 0) && (name[0] == '/')) + { + name = name.Remove(0, 1); + } + + // Drop any trailing slashes. + while ((name.Length > 0) && (name[name.Length - 1] == '/')) + { + name = name.Remove(name.Length - 1, 1); + } + + // Convert consecutive // characters to / + int index = name.IndexOf("//"); + while (index >= 0) + { + name = name.Remove(index, 1); + index = name.IndexOf("//"); + } + + name = MakeValidName(name, '_'); + } + else { + name = string.Empty; + } + return name; + } + + /// + /// Get/set the path prefix to be trimmed from paths if present. + /// + /// The prefix is trimmed before any conversion from + /// a windows path is done. + public string TrimPrefix + { + get { return trimPrefix_; } + set { + trimPrefix_ = value; + if (trimPrefix_ != null) { + trimPrefix_ = trimPrefix_.ToLower(); + } + } + } + + /// + /// Force a name to be valid by replacing invalid characters with a fixed value + /// + /// The name to force valid + /// The replacement character to use. + /// Returns a valid name + static string MakeValidName(string name, char replacement) + { + int index = name.IndexOfAny(InvalidEntryChars); + if (index >= 0) { + StringBuilder builder = new StringBuilder(name); + + while (index >= 0 ) { + builder[index] = replacement; + + if (index >= name.Length) { + index = -1; + } + else { + index = name.IndexOfAny(InvalidEntryChars, index + 1); + } + } + name = builder.ToString(); + } + + if (name.Length > 0xffff) { + throw new PathTooLongException(); + } + + return name; + } + + /// + /// Test a name to see if it is a valid name for a zip entry. + /// + /// The name to test. + /// If true checking is relaxed about windows file names and absolute paths. + /// Returns true if the name is a valid zip name; false otherwise. + /// Zip path names are actually in Unix format, and should only contain relative paths. + /// This means that any path stored should not contain a drive or + /// device letter, or a leading slash. All slashes should forward slashes '/'. + /// An empty name is valid for a file where the input comes from standard input. + /// A null name is not considered valid. + /// + public static bool IsValidName(string name, bool relaxed) + { + bool result = (name != null); + + if ( result ) { + if ( relaxed ) { + result = name.IndexOfAny(InvalidEntryCharsRelaxed) < 0; + } + else { + result = + (name.IndexOfAny(InvalidEntryChars) < 0) && + (name.IndexOf('/') != 0); + } + } + + return result; + } + + /// + /// Test a name to see if it is a valid name for a zip entry. + /// + /// The name to test. + /// Returns true if the name is a valid zip name; false otherwise. + /// Zip path names are actually in unix format, + /// and should only contain relative paths if a path is present. + /// This means that the path stored should not contain a drive or + /// device letter, or a leading slash. All slashes should forward slashes '/'. + /// An empty name is valid where the input comes from standard input. + /// A null name is not considered valid. + /// + public static bool IsValidName(string name) + { + bool result = + (name != null) && + (name.IndexOfAny(InvalidEntryChars) < 0) && + (name.IndexOf('/') != 0) + ; + return result; + } + + #region Instance Fields + string trimPrefix_; + #endregion + + #region Class Fields + static readonly char[] InvalidEntryChars; + static readonly char[] InvalidEntryCharsRelaxed; + #endregion + } +} diff --git a/PCRobot/Utils/ZIP/Zip/ZipOutputStream.cs b/PCRobot/Utils/ZIP/Zip/ZipOutputStream.cs new file mode 100644 index 0000000..4f93763 --- /dev/null +++ b/PCRobot/Utils/ZIP/Zip/ZipOutputStream.cs @@ -0,0 +1,901 @@ +// ZipOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 Z-1649 Added AES support +// 22-02-2010 Z-1648 Zero byte entries would create invalid zip files + +using System; +using System.IO; +using System.Collections; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// This is a DeflaterOutputStream that writes the files into a zip + /// archive one after another. It has a special method to start a new + /// zip entry. The zip entries contains information about the file name + /// size, compressed size, CRC, etc. + /// + /// It includes support for Stored and Deflated entries. + /// This class is not thread safe. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// This sample shows how to create a zip file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// string[] filenames = Directory.GetFiles(args[0]); + /// byte[] buffer = new byte[4096]; + /// + /// using ( ZipOutputStream s = new ZipOutputStream(File.Create(args[1])) ) { + /// + /// s.SetLevel(9); // 0 - store only to 9 - means best compression + /// + /// foreach (string file in filenames) { + /// ZipEntry entry = new ZipEntry(file); + /// s.PutNextEntry(entry); + /// + /// using (FileStream fs = File.OpenRead(file)) { + /// StreamUtils.Copy(fs, s, buffer); + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipOutputStream : DeflaterOutputStream + { + #region Constructors + /// + /// Creates a new Zip output stream, writing a zip archive. + /// + /// + /// The output stream to which the archive contents are written. + /// + public ZipOutputStream(Stream baseOutputStream) + : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true)) + { + } + + /// + /// Creates a new Zip output stream, writing a zip archive. + /// + /// The output stream to which the archive contents are written. + /// Size of the buffer to use. + public ZipOutputStream( Stream baseOutputStream, int bufferSize ) + : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), bufferSize) + { + } + #endregion + + /// + /// Gets a flag value of true if the central header has been added for this archive; false if it has not been added. + /// + /// No further entries can be added once this has been done. + public bool IsFinished + { + get { + return entries == null; + } + } + + /// + /// Set the zip file comment. + /// + /// + /// The comment text for the entire archive. + /// + /// + /// The converted comment is longer than 0xffff bytes. + /// + public void SetComment(string comment) + { + // TODO: Its not yet clear how to handle unicode comments here. + byte[] commentBytes = ZipConstants.ConvertToArray(comment); + if (commentBytes.Length > 0xffff) { + throw new ArgumentOutOfRangeException("comment"); + } + zipComment = commentBytes; + } + + /// + /// Sets the compression level. The new level will be activated + /// immediately. + /// + /// The new compression level (1 to 9). + /// + /// Level specified is not supported. + /// + /// + public void SetLevel(int level) + { + deflater_.SetLevel(level); + defaultCompressionLevel = level; + } + + /// + /// Get the current deflater compression level + /// + /// The current compression level + public int GetLevel() + { + return deflater_.GetLevel(); + } + + /// + /// Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + /// + /// Older archivers may not understand Zip64 extensions. + /// If backwards compatability is an issue be careful when adding entries to an archive. + /// Setting this property to off is workable but less desirable as in those circumstances adding a file + /// larger then 4GB will fail. + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + /// + /// Write an unsigned short in little endian byte order. + /// + private void WriteLeShort(int value) + { + unchecked { + baseOutputStream_.WriteByte((byte)(value & 0xff)); + baseOutputStream_.WriteByte((byte)((value >> 8) & 0xff)); + } + } + + /// + /// Write an int in little endian byte order. + /// + private void WriteLeInt(int value) + { + unchecked { + WriteLeShort(value); + WriteLeShort(value >> 16); + } + } + + /// + /// Write an int in little endian byte order. + /// + private void WriteLeLong(long value) + { + unchecked { + WriteLeInt((int)value); + WriteLeInt((int)(value >> 32)); + } + } + + /// + /// Starts a new Zip entry. It automatically closes the previous + /// entry if present. + /// All entry elements bar name are optional, but must be correct if present. + /// If the compression method is stored and the output is not patchable + /// the compression for that entry is automatically changed to deflate level 0 + /// + /// + /// the entry. + /// + /// + /// if entry passed is null. + /// + /// + /// if an I/O error occured. + /// + /// + /// if stream was finished + /// + /// + /// Too many entries in the Zip file
+ /// Entry name is too long
+ /// Finish has already been called
+ ///
+ public void PutNextEntry(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if (entries == null) { + throw new InvalidOperationException("ZipOutputStream was finished"); + } + + if (curEntry != null) { + CloseEntry(); + } + + if (entries.Count == int.MaxValue) { + throw new ZipException("Too many entries for Zip file"); + } + + CompressionMethod method = entry.CompressionMethod; + int compressionLevel = defaultCompressionLevel; + + // Clear flags that the library manages internally + entry.Flags &= (int)GeneralBitFlags.UnicodeText; + patchEntryHeader = false; + + bool headerInfoAvailable; + + // No need to compress - definitely no data. + if (entry.Size == 0) + { + entry.CompressedSize = entry.Size; + entry.Crc = 0; + method = CompressionMethod.Stored; + headerInfoAvailable = true; + } + else + { + headerInfoAvailable = (entry.Size >= 0) && entry.HasCrc; + + // Switch to deflation if storing isnt possible. + if (method == CompressionMethod.Stored) + { + if (!headerInfoAvailable) + { + if (!CanPatchEntries) + { + // Can't patch entries so storing is not possible. + method = CompressionMethod.Deflated; + compressionLevel = 0; + } + } + else // entry.size must be > 0 + { + entry.CompressedSize = entry.Size; + headerInfoAvailable = entry.HasCrc; + } + } + } + + if (headerInfoAvailable == false) { + if (CanPatchEntries == false) { + // Only way to record size and compressed size is to append a data descriptor + // after compressed data. + + // Stored entries of this form have already been converted to deflating. + entry.Flags |= 8; + } else { + patchEntryHeader = true; + } + } + + if (Password != null) { + entry.IsCrypted = true; + if (entry.Crc < 0) { + // Need to append a data descriptor as the crc isnt available for use + // with encryption, the date is used instead. Setting the flag + // indicates this to the decompressor. + entry.Flags |= 8; + } + } + + entry.Offset = offset; + entry.CompressionMethod = (CompressionMethod)method; + + curMethod = method; + sizePatchPos = -1; + + if ( (useZip64_ == UseZip64.On) || ((entry.Size < 0) && (useZip64_ == UseZip64.Dynamic)) ) { + entry.ForceZip64(); + } + + // Write the local file header + WriteLeInt(ZipConstants.LocalHeaderSignature); + + WriteLeShort(entry.Version); + WriteLeShort(entry.Flags); + WriteLeShort((byte)entry.CompressionMethodForHeader); + WriteLeInt((int)entry.DosTime); + + // TODO: Refactor header writing. Its done in several places. + if (headerInfoAvailable == true) { + WriteLeInt((int)entry.Crc); + if ( entry.LocalHeaderRequiresZip64 ) { + WriteLeInt(-1); + WriteLeInt(-1); + } + else { + WriteLeInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize); + WriteLeInt((int)entry.Size); + } + } else { + if (patchEntryHeader) { + crcPatchPos = baseOutputStream_.Position; + } + WriteLeInt(0); // Crc + + if ( patchEntryHeader ) { + sizePatchPos = baseOutputStream_.Position; + } + + // For local header both sizes appear in Zip64 Extended Information + if ( entry.LocalHeaderRequiresZip64 || patchEntryHeader ) { + WriteLeInt(-1); + WriteLeInt(-1); + } + else { + WriteLeInt(0); // Compressed size + WriteLeInt(0); // Uncompressed size + } + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xFFFF) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if (entry.LocalHeaderRequiresZip64) { + ed.StartNewEntry(); + if (headerInfoAvailable) { + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + } + else { + ed.AddLeLong(-1); + ed.AddLeLong(-1); + } + ed.AddNewEntry(1); + + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cant find extra data"); + } + + if ( patchEntryHeader ) { + sizePatchPos = ed.CurrentReadIndex; + } + } + else { + ed.Delete(1); + } + +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + AddExtraDataAES(entry, ed); + } +#endif + byte[] extra = ed.GetEntryData(); + + WriteLeShort(name.Length); + WriteLeShort(extra.Length); + + if ( name.Length > 0 ) { + baseOutputStream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + sizePatchPos += baseOutputStream_.Position; + } + + if ( extra.Length > 0 ) { + baseOutputStream_.Write(extra, 0, extra.Length); + } + + offset += ZipConstants.LocalHeaderBaseSize + name.Length + extra.Length; + // Fix offsetOfCentraldir for AES + if (entry.AESKeySize > 0) + offset += entry.AESOverheadSize; + + // Activate the entry. + curEntry = entry; + crc.Reset(); + if (method == CompressionMethod.Deflated) { + deflater_.Reset(); + deflater_.SetLevel(compressionLevel); + } + size = 0; + + if (entry.IsCrypted) { +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + WriteAESHeader(entry); + } else +#endif + { + if (entry.Crc < 0) { // so testing Zip will says its ok + WriteEncryptionHeader(entry.DosTime << 16); + } else { + WriteEncryptionHeader(entry.Crc); + } + } + } + } + + /// + /// Closes the current entry, updating header and footer information as required + /// + /// + /// An I/O error occurs. + /// + /// + /// No entry is active. + /// + public void CloseEntry() + { + if (curEntry == null) { + throw new InvalidOperationException("No open entry"); + } + + long csize = size; + + // First finish the deflater, if appropriate + if (curMethod == CompressionMethod.Deflated) { + if (size >= 0) { + base.Finish(); + csize = deflater_.TotalOut; + } + else { + deflater_.Reset(); + } + } + + // Write the AES Authentication Code (a hash of the compressed and encrypted data) + if (curEntry.AESKeySize > 0) { + baseOutputStream_.Write(AESAuthCode, 0, 10); + } + + if (curEntry.Size < 0) { + curEntry.Size = size; + } else if (curEntry.Size != size) { + throw new ZipException("size was " + size + ", but I expected " + curEntry.Size); + } + + if (curEntry.CompressedSize < 0) { + curEntry.CompressedSize = csize; + } else if (curEntry.CompressedSize != csize) { + throw new ZipException("compressed size was " + csize + ", but I expected " + curEntry.CompressedSize); + } + + if (curEntry.Crc < 0) { + curEntry.Crc = crc.Value; + } else if (curEntry.Crc != crc.Value) { + throw new ZipException("crc was " + crc.Value + ", but I expected " + curEntry.Crc); + } + + offset += csize; + + if (curEntry.IsCrypted) { + if (curEntry.AESKeySize > 0) { + curEntry.CompressedSize += curEntry.AESOverheadSize; + + } else { + curEntry.CompressedSize += ZipConstants.CryptoHeaderSize; + } + } + + // Patch the header if possible + if (patchEntryHeader) { + patchEntryHeader = false; + + long curPos = baseOutputStream_.Position; + baseOutputStream_.Seek(crcPatchPos, SeekOrigin.Begin); + WriteLeInt((int)curEntry.Crc); + + if ( curEntry.LocalHeaderRequiresZip64 ) { + + if ( sizePatchPos == -1 ) { + throw new ZipException("Entry requires zip64 but this has been turned off"); + } + + baseOutputStream_.Seek(sizePatchPos, SeekOrigin.Begin); + WriteLeLong(curEntry.Size); + WriteLeLong(curEntry.CompressedSize); + } + else { + WriteLeInt((int)curEntry.CompressedSize); + WriteLeInt((int)curEntry.Size); + } + baseOutputStream_.Seek(curPos, SeekOrigin.Begin); + } + + // Add data descriptor if flagged as required + if ((curEntry.Flags & 8) != 0) { + WriteLeInt(ZipConstants.DataDescriptorSignature); + WriteLeInt(unchecked((int)curEntry.Crc)); + + if ( curEntry.LocalHeaderRequiresZip64 ) { + WriteLeLong(curEntry.CompressedSize); + WriteLeLong(curEntry.Size); + offset += ZipConstants.Zip64DataDescriptorSize; + } + else { + WriteLeInt((int)curEntry.CompressedSize); + WriteLeInt((int)curEntry.Size); + offset += ZipConstants.DataDescriptorSize; + } + } + + entries.Add(curEntry); + curEntry = null; + } + + void WriteEncryptionHeader(long crcValue) + { + offset += ZipConstants.CryptoHeaderSize; + + InitializePassword(Password); + + byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize]; + Random rnd = new Random(); + rnd.NextBytes(cryptBuffer); + cryptBuffer[11] = (byte)(crcValue >> 24); + + EncryptBlock(cryptBuffer, 0, cryptBuffer.Length); + baseOutputStream_.Write(cryptBuffer, 0, cryptBuffer.Length); + } + +#if !NET_1_1 && !NETCF_2_0 + private static void AddExtraDataAES(ZipEntry entry, ZipExtraData extraData) { + + // Vendor Version: AE-1 IS 1. AE-2 is 2. With AE-2 no CRC is required and 0 is stored. + const int VENDOR_VERSION = 2; + // Vendor ID is the two ASCII characters "AE". + const int VENDOR_ID = 0x4541; //not 6965; + extraData.StartNewEntry(); + // Pack AES extra data field see http://www.winzip.com/aes_info.htm + //extraData.AddLeShort(7); // Data size (currently 7) + extraData.AddLeShort(VENDOR_VERSION); // 2 = AE-2 + extraData.AddLeShort(VENDOR_ID); // "AE" + extraData.AddData(entry.AESEncryptionStrength); // 1 = 128, 2 = 192, 3 = 256 + extraData.AddLeShort((int)entry.CompressionMethod); // The actual compression method used to compress the file + extraData.AddNewEntry(0x9901); + } + + // Replaces WriteEncryptionHeader for AES + // + private void WriteAESHeader(ZipEntry entry) { + byte[] salt; + byte[] pwdVerifier; + InitializeAESPassword(entry, Password, out salt, out pwdVerifier); + // File format for AES: + // Size (bytes) Content + // ------------ ------- + // Variable Salt value + // 2 Password verification value + // Variable Encrypted file data + // 10 Authentication code + // + // Value in the "compressed size" fields of the local file header and the central directory entry + // is the total size of all the items listed above. In other words, it is the total size of the + // salt value, password verification value, encrypted data, and authentication code. + baseOutputStream_.Write(salt, 0, salt.Length); + baseOutputStream_.Write(pwdVerifier, 0, pwdVerifier.Length); + } +#endif + + /// + /// Writes the given buffer to the current entry. + /// + /// The buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Archive size is invalid + /// No entry is active. + public override void Write(byte[] buffer, int offset, int count) + { + if (curEntry == null) { + throw new InvalidOperationException("No open entry."); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (buffer.Length - offset) < count ) { + throw new ArgumentException("Invalid offset/count combination"); + } + + crc.Update(buffer, offset, count); + size += count; + + switch (curMethod) { + case CompressionMethod.Deflated: + base.Write(buffer, offset, count); + break; + + case CompressionMethod.Stored: + if (Password != null) { + CopyAndEncrypt(buffer, offset, count); + } else { + baseOutputStream_.Write(buffer, offset, count); + } + break; + } + } + + void CopyAndEncrypt(byte[] buffer, int offset, int count) + { + const int CopyBufferSize = 4096; + byte[] localBuffer = new byte[CopyBufferSize]; + while ( count > 0 ) { + int bufferCount = (count < CopyBufferSize) ? count : CopyBufferSize; + + Array.Copy(buffer, offset, localBuffer, 0, bufferCount); + EncryptBlock(localBuffer, 0, bufferCount); + baseOutputStream_.Write(localBuffer, 0, bufferCount); + count -= bufferCount; + offset += bufferCount; + } + } + + /// + /// Finishes the stream. This will write the central directory at the + /// end of the zip file and flush the stream. + /// + /// + /// This is automatically called when the stream is closed. + /// + /// + /// An I/O error occurs. + /// + /// + /// Comment exceeds the maximum length
+ /// Entry name exceeds the maximum length + ///
+ public override void Finish() + { + if (entries == null) { + return; + } + + if (curEntry != null) { + CloseEntry(); + } + + long numEntries = entries.Count; + long sizeEntries = 0; + + foreach (ZipEntry entry in entries) { + WriteLeInt(ZipConstants.CentralHeaderSignature); + WriteLeShort(ZipConstants.VersionMadeBy); + WriteLeShort(entry.Version); + WriteLeShort(entry.Flags); + WriteLeShort((short)entry.CompressionMethodForHeader); + WriteLeInt((int)entry.DosTime); + WriteLeInt((int)entry.Crc); + + if ( entry.IsZip64Forced() || + (entry.CompressedSize >= uint.MaxValue) ) + { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.CompressedSize); + } + + if ( entry.IsZip64Forced() || + (entry.Size >= uint.MaxValue) ) + { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xffff) { + throw new ZipException("Name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.CentralHeaderRequiresZip64 ) { + ed.StartNewEntry(); + if ( entry.IsZip64Forced() || + (entry.Size >= 0xffffffff) ) + { + ed.AddLeLong(entry.Size); + } + + if ( entry.IsZip64Forced() || + (entry.CompressedSize >= 0xffffffff) ) + { + ed.AddLeLong(entry.CompressedSize); + } + + if ( entry.Offset >= 0xffffffff ) + { + ed.AddLeLong(entry.Offset); + } + + ed.AddNewEntry(1); + } + else { + ed.Delete(1); + } + +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + AddExtraDataAES(entry, ed); + } +#endif + byte[] extra = ed.GetEntryData(); + + byte[] entryComment = + (entry.Comment != null) ? + ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : + new byte[0]; + + if (entryComment.Length > 0xffff) { + throw new ZipException("Comment too long."); + } + + WriteLeShort(name.Length); + WriteLeShort(extra.Length); + WriteLeShort(entryComment.Length); + WriteLeShort(0); // disk number + WriteLeShort(0); // internal file attributes + // external file attributes + + if (entry.ExternalFileAttributes != -1) { + WriteLeInt(entry.ExternalFileAttributes); + } else { + if (entry.IsDirectory) { // mark entry as directory (from nikolam.AT.perfectinfo.com) + WriteLeInt(16); + } else { + WriteLeInt(0); + } + } + + if ( entry.Offset >= uint.MaxValue ) { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.Offset); + } + + if ( name.Length > 0 ) { + baseOutputStream_.Write(name, 0, name.Length); + } + + if ( extra.Length > 0 ) { + baseOutputStream_.Write(extra, 0, extra.Length); + } + + if ( entryComment.Length > 0 ) { + baseOutputStream_.Write(entryComment, 0, entryComment.Length); + } + + sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length; + } + + using ( ZipHelperStream zhs = new ZipHelperStream(baseOutputStream_) ) { + zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment); + } + + entries = null; + } + + #region Instance Fields + /// + /// The entries for the archive. + /// + ArrayList entries = new ArrayList(); + + /// + /// Used to track the crc of data added to entries. + /// + Crc32 crc = new Crc32(); + + /// + /// The current entry being added. + /// + ZipEntry curEntry; + + int defaultCompressionLevel = Deflater.DEFAULT_COMPRESSION; + + CompressionMethod curMethod = CompressionMethod.Deflated; + + /// + /// Used to track the size of data for an entry during writing. + /// + long size; + + /// + /// Offset to be recorded for each entry in the central header. + /// + long offset; + + /// + /// Comment for the entire archive recorded in central header. + /// + byte[] zipComment = new byte[0]; + + /// + /// Flag indicating that header patching is required for the current entry. + /// + bool patchEntryHeader; + + /// + /// Position to patch crc + /// + long crcPatchPos = -1; + + /// + /// Position to patch size. + /// + long sizePatchPos = -1; + + // Default is dynamic which is not backwards compatible and can cause problems + // with XP's built in compression which cant read Zip64 archives. + // However it does avoid the situation were a large file is added and cannot be completed correctly. + // NOTE: Setting the size for entries before they are added is the best solution! + UseZip64 useZip64_ = UseZip64.Dynamic; + #endregion + } +} diff --git a/PCRobot/Utils/ZipArchive.cs b/PCRobot/Utils/ZipArchive.cs new file mode 100644 index 0000000..2c58662 --- /dev/null +++ b/PCRobot/Utils/ZipArchive.cs @@ -0,0 +1,79 @@ +using ICSharpCode.SharpZipLib.Zip1; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.Utils +{ + internal class ZipArchive + { + /// + /// 功能:解压zip格式的文件。 + /// + /// 压缩文件路径 + /// 解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 + /// 出错信息 + /// 解压是否成功 + public static void UnZip(string zipFilePath, string unZipDir) + { + + if (zipFilePath == string.Empty) + { + throw new Exception("压缩文件不能为空!"); + } + if (!File.Exists(zipFilePath)) + { + throw new System.IO.FileNotFoundException("压缩文件不存在!"); + } + //解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 + if (unZipDir == string.Empty) + unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), + Path.GetFileNameWithoutExtension(zipFilePath)); + if (!unZipDir.EndsWith("/")) + unZipDir += "/"; + if (!Directory.Exists(unZipDir)) + Directory.CreateDirectory(unZipDir); + + using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath))) + { + + ZipEntry theEntry; + while ((theEntry = s.GetNextEntry()) != null) + { + string directoryName = Path.GetDirectoryName(theEntry.Name); + string fileName = Path.GetFileName(theEntry.Name); + if (directoryName.Length > 0) + { + Directory.CreateDirectory(unZipDir + directoryName); + } + if (!directoryName.EndsWith("/")) + directoryName += "/"; + if (fileName != String.Empty) + { + using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name)) + { + + int size = 5048; + byte[] data = new byte[size]; + while (true) + { + size = s.Read(data, 0, data.Length); + if (size > 0) + { + streamWriter.Write(data, 0, size); + } + else + { + break; + } + } + } + } + } + } + } + } +} diff --git a/PCRobot/WechatApi/KstAPI.cs b/PCRobot/WechatApi/KstAPI.cs new file mode 100644 index 0000000..f13b4f3 --- /dev/null +++ b/PCRobot/WechatApi/KstAPI.cs @@ -0,0 +1,98 @@ +/* + * 由SharpDevelop创建。 + * 用户: kst + * 日期: 2019/6/5 星期三 + * 时间: 11:27 + * + * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 + */ +using System; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using System.Text; +namespace PCRobot.WechatApi +{ + /// + /// Description of KstAPI. + /// + public class KstAPI + { + + public const int 通信_连接成功 = 1; + public const int 通信_数据到达 = 2; + public const int 通信_连接断开 = 3; + + public const int 回调_二维码 = 1; + public const int 回调_登录成功 = 2; + public const int 回调_退出登陆 = 3; + public const int 回调_接收消息 = 4; + + public const int 回调_添加好友 = 100001; + public const int 回调_下载信息 = 100002; + public const int 回调_建群返回 = 100003; + public const int 回调_A8Key = 100004; + public const int 回调_聊天对象 = 100007; + + public const int 回调_语音消息 = 100009; + public const int 回调_文件消息 = 100010; + public const int 回调_视频消息 = 100011; + public const int 回调_图片消息 = 100012; + + + public const int 回调_好友列表 = 300001; + public const int 回调_群员列表 = 300002; + + [DllImport("KstAPI.dll",EntryPoint="#7")] + public static extern int kst_DLLConnect(int Pwd,int Port); + + [DllImport("KstAPI.dll",EntryPoint="#6")] + public static extern int kst_GetPath(ref byte str); + + [DllImport("KstAPI.dll",EntryPoint="#5")] + public static extern int kst_CreateWx(string ExeFile,string ExeName,string DllName,int lPort); + + [DllImport("KstAPI.dll",EntryPoint="#1")] + public static extern int kstSocket_Init(IntPtr sFun, IntPtr cFun, int buflen); + + [DllImport("KstAPI.dll",EntryPoint="#2")] + public static extern int kstSocket_Create(string host, int sPort, int nIS); + + [DllImport("KstAPI.dll",EntryPoint="#3")] + public static extern int kstSocket_Send(int sPoint, int sPort, byte[] buf, int buflen); + + [DllImport("KstAPI.dll",EntryPoint="#4")] + public static extern int kstSocket_Port(int so); + + [DllImport("kernel32.dll",EntryPoint="RtlMoveMemory")] + public static extern int RtlMoveMemory(byte[] sByte, int Source, int Length); + + + //服务端回调 + public delegate void dele_Server_CallBack(int sPoint, int so, int type, int buf, int buflen, int cso); + public dele_Server_CallBack sc; + //客户端回调 + public delegate void dele_Client_CallBack(int so, int sPoint, int type, int buf, int buflen); + public dele_Client_CallBack cc; + + public static string EnUnicode(string str) + { + StringBuilder strResult = new StringBuilder(); + if (!string.IsNullOrEmpty(str)) + { + for (int i = 0; i < str.Length; i++) + { + strResult.Append("\\u"); + strResult.Append(((int)str[i]).ToString("X4")); + } + } + return strResult.ToString(); + } + + public static string DeUnicode(string str) + { + string strResult = Regex.Unescape(str); + return strResult; + } + + } +} diff --git a/PCRobot/WechatApi/NMCore.cs b/PCRobot/WechatApi/NMCore.cs new file mode 100644 index 0000000..1ee8d3e --- /dev/null +++ b/PCRobot/WechatApi/NMCore.cs @@ -0,0 +1,512 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot.WechatApi +{ + public class NMCore + { + HPSocketCS.TcpPackServer g_HPServer; + public NMCore(HPSocketCS.TcpPackServer HPServer) + { + g_HPServer = HPServer; + } + + public void SendPacket(int ConnID, string Packet) + { + byte[] PackBytes = System.Text.ASCIIEncoding.Default.GetBytes(Packet.ToString()); + g_HPServer.Send((IntPtr)ConnID, PackBytes, PackBytes.Length); + } + /// + /// 初始化,传输DLL调用密码,用于简单的防止DLL被盗用 + /// + /// + /// + public void NM_Init(int ConnID, string PassWord) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = 100000; + sendJson["PassWord"] = PassWord; + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_读取通讯录列表 + /// + /// + public void NM_GetContactList(int ConnID) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetContactList; + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_读取群员列表 + /// + /// + /// + public void NM_GetGroupMember(int ConnID, string GroupID) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetGroupMember; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_下载用户详细信息 + /// + /// + /// + /// + public void NM_GetWxidInfo(int ConnID, string GroupID, string Wxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetWxidInfo; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_GetA8Key 微信浏览器操作 + /// + /// + /// + /// + public void NM_GetA8Key(int ConnID, string Wxid, string URL) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetA8Key; + sendJson["Type"] = 1; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["URL"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(URL)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_发送文本消息 + /// + /// + /// 3 + /// + /// + public void NM_SendTextMsg(int ConnID, string Wxid, string[] AtWxidArray, string Message) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendText; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Message"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Message)); + if (AtWxidArray.Length > 0) + { + JArray AtList = new JArray(); + for (int i = 0; i < AtWxidArray.Length; i++) + { + if (AtWxidArray[i] != string.Empty) + { + AtList.Add(Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(AtWxidArray[i]))); + } + } + if (AtList.Count > 0) { sendJson["AtWxid"] = AtList; } + } + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_发送文件消息 + /// + /// + /// + /// + /// 欲发送文件的完整路径 + public void NM_SendFileMsg(int ConnID, int Type, string Wxid, string FilePath) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = Type; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["File"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(FilePath)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_发送名片消息 + /// + /// + /// + /// + public void NM_SendCardMsg(int ConnID, string Wxid, string CardWxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendCard; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["CardWxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(CardWxid)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_发送地图定位消息 + /// + /// + /// + /// + public void NM_SendMapMsg(int ConnID, string Wxid, string MapXML) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendMap; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Map"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(MapXML)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_发送图文链接消息 + /// + /// + /// + /// + public void NM_SendURLMsg(int ConnID, string Wxid, string XML) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendURL; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["XML"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(XML)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_发送小程序 2.7及以上版本有效 + /// + /// + /// + /// + /// + public void NM_SendWeChatApp(int ConnID, string Wxid, string XML, string ShowImage) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendWeChatApp; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["XML"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(XML)); + sendJson["Image"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(ShowImage)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_撤回发出消息 + /// + /// + /// + /// + /// + public void NM_RevokeMsg(int ConnID, string Wxid, string ServerID, string Message) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_RevokeMsg; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["ServerID"] = ServerID; + sendJson["Message"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Message)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_接收的消息被撤回本地无提示 + /// + /// + /// + public void NM_DesRevoke(int ConnID, bool Opt) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_DesRevoke; + sendJson["Opt"] = Opt; + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_接收转账 + /// + /// + /// + /// + /// + public void NM_GetMoney(int ConnID, string Wxid, string Transid, int Time) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetMoney; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Transid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Transid)); + sendJson["Time"] = Time; + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_通过Wxid或v1添加好友 + /// + /// + /// + /// + /// + /// + /// + public void NM_AddFriend(int ConnID, int Type, int AddType, string Wxid, string v2, string Message) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_AddFriend; + sendJson["Type"] = Type; + sendJson["AddType"] = AddType; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["V2"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(v2)); + sendJson["Message"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Message)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_通过请求消息XML通过好友请求 + /// + /// + /// + public void NM_PassApply(int ConnID, string ApplyXML) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_PassApply; + //sendJson["XML"] = ApplyXML; 原代码,改为如下一行 + sendJson["XML"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(ApplyXML)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_删除好友 + /// + /// + /// + public void NM_DelFriend(int ConnID, string Wxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_DelFriend; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_取消关注公众号 + /// + /// + /// + public void NM_DelGHFriend(int ConnID, string GHWxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_DelGHFriend; + sendJson["GH_Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GHWxid)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_设置好友备注 + /// + /// + /// + /// + public void NM_SetFriendMark(int ConnID, string Wxid, string Mark) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetFriendMark; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Mark"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Mark)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_创建群聊 + /// + /// + /// + public void NM_CreateGroup(int ConnID, string[] MemberArray) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_CreateGroup; + if (MemberArray.Length > 1 && MemberArray.Length < 40) + { + JArray MemberList = new JArray(); + for (int i = 0; i < MemberArray.Length; i++) + { + if (MemberArray[i] != string.Empty) + { + MemberList.Add(Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(MemberArray[i]))); + } + } + if (MemberList.Count > 0) + { + sendJson["List"] = MemberList; + SendPacket(ConnID, sendJson.ToString()); + } + } + } + /// + /// 功能_退出群聊 + /// + /// + /// + public void NM_QuitGroup(int ConnID, string GroupID) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_QuitGroup; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_批量拉群 - 发送邀请链接或直接拉入 + /// + /// + /// + /// + /// + public void NM_InviteToGroup(int ConnID, int Type, string GroupID, string[] MemberArray) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = Type; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + if (MemberArray.Length > 0 && MemberArray.Length < 40) + { + JArray MemberList = new JArray(); + for (int i = 0; i < MemberArray.Length; i++) + { + if (MemberArray[i] != string.Empty) + { + MemberList.Add(Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(MemberArray[i]))); + } + } + if (MemberList.Count > 0) + { + sendJson["List"] = MemberList; + SendPacket(ConnID, sendJson.ToString()); + } + } + } + /// + /// 功能_批量提出群员 + /// + /// + /// + /// + public void NM_KickGroupMember(int ConnID, string GroupID, string[] MemberArray) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_KickGroupMember; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + if (MemberArray.Length > 0 && MemberArray.Length < 40) + { + JArray MemberList = new JArray(); + for (int i = 0; i < MemberArray.Length; i++) + { + if (MemberArray[i] != string.Empty) + { + MemberList.Add(Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(MemberArray[i]))); + } + } + if (MemberList.Count > 0) + { + sendJson["List"] = MemberList; + SendPacket(ConnID, sendJson.ToString()); + } + } + } + /// + /// 功能_修改群名称 + /// + /// + /// + /// + public void NM_SetGroupName(int ConnID, string GroupID, string Name) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetGroupName; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + sendJson["Name"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Name)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 群主功能_发送群公告(@所有人) + /// + /// + /// + /// + /// + public void NM_SetGroupNotice(int ConnID, string GroupID, string Boss, string Notice) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetGroupNotice; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Boss)); + sendJson["Notice"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Notice)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_设置自己的群昵称 + /// + /// + /// + /// + public void NM_SetMyGroupNick(int ConnID, string GroupID, string Nick) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetMyGroupNick; + sendJson["GroupID"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(GroupID)); + sendJson["Nick"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Nick)); + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_获取收藏列表 + /// + /// + public void NM_GetFavList(int ConnID) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetFavList; + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_发送指定收藏内容 + /// + /// + /// + /// + public void NM_SendFavMsg(int ConnID, string Wxid, int Index) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SendFavMsg; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Index"] = Index; + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_状态操作 + /// + /// + /// 1=免打扰 2=置顶 3=保存通讯录 4=显示群员昵称 + /// + /// + public void NM_StateOpt(int ConnID, int Type, string Wxid, bool Opt) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_StateOpt; + sendJson["Type"] = Type; + sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); + sendJson["Opt"] = Opt; + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_对象操作 + /// + /// + /// 1= 切换聊天对象 + /// 2= 设置指定Wxid消息已读(取消红点,不切换聊天对象,移动端同步) + /// 3= 一键全部已读(取消全部红点,移动端不同步) + /// + public void NM_SetObject(int ConnID, int Type, string Wxid) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_SetObject; + sendJson["Type"] = Type; + if (Wxid != string.Empty) + { sendJson["Wxid"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(Wxid)); } + SendPacket(ConnID, sendJson.ToString()); + } + /// + /// 功能_下载高清大图 + /// + /// + /// + /// + public void NM_GetImageByCDN(int ConnID, string XML, string SavePath) + { + JObject sendJson = new JObject(); + sendJson["PackType"] = NMHelper.NM_GetImageByCDN; + sendJson["XML"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(XML)); + sendJson["SavePath"] = Convert.ToBase64String(System.Text.UnicodeEncoding.Unicode.GetBytes(SavePath)); + SendPacket(ConnID, sendJson.ToString()); + } + } +} diff --git a/PCRobot/WechatApi/NMHelper.cs b/PCRobot/WechatApi/NMHelper.cs new file mode 100644 index 0000000..a561528 --- /dev/null +++ b/PCRobot/WechatApi/NMHelper.cs @@ -0,0 +1,56 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PCRobot.WechatApi +{ + public class NMHelper + { + + //public struct nmWxidInfo + //{ + // public int Type { get; set; } + // public int List { get; set; } + // public string Wxid { get; set; } + // public string WxNo { get; set; } + // public string Nick { get; set; } + // public string Mark { get; set; } + // public string V1 { get; set; } + // public string HeadIMG { get; set; } + // public string Sex { get; set; } + // public string Address { get; set; } + // public string Phone { get; set; } + // public string Config { get; set; } + // public string GetSex(int uSex) + // { + // if (uSex == 1) + // return "男"; + // else if (uSex == 2) + // return "女"; + // else + // return "未知(" + uSex.ToString() + ")"; + // } + + // public int handle { get; set; } + + // public int socketHandle { get; set; } + //} + + //public struct nmGroupInfo + //{ + // public string GroupID { get; set; } + // public int Count { get; set; } + // public List List { get; set; } + //} + + } +} \ No newline at end of file diff --git a/PCRobot/WechatApi/NMResource.Designer.cs b/PCRobot/WechatApi/NMResource.Designer.cs new file mode 100644 index 0000000..01659ad --- /dev/null +++ b/PCRobot/WechatApi/NMResource.Designer.cs @@ -0,0 +1,132 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace PCRobot.WechatApi { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class NMResource { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal NMResource() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PCRobot.WechatApi.NMResource", typeof(NMResource).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 <?xml version="1.0"?> + ///<msg> + /// <location x="*坐标X*" y="*坐标Y*" scale="15" label="*副标题*" maptype="roadmap" poiname="*主标题*" poiid="City" /> + ///</msg> 的本地化字符串。 + /// + internal static string XML_MAP { + get { + return ResourceManager.GetString("XML_MAP", resourceCulture); + } + } + + /// + /// 查找类似 <msg> + /// <fromusername>*MYWXID*</fromusername> + /// <scene>0</scene> + /// <commenturl></commenturl> + /// <appmsg appid="" sdkver="0"> + /// <title>*标题*</title> + /// <des>*摘要*</des> + /// <action>view</action> + /// <type>5</type> + /// <showtype>0</showtype> + /// <content></content> + /// <url>*地址*</url> + /// <dataurl></dataurl> + /// <lowurl></lowurl> + /// <thumburl>*图片*</thumburl> + /// <recorditem> + /// <![CDATA[]]> + /// </recorditem> + /// <extinfo></extinfo> + /// [字符串的其余部分被截断]"; 的本地化字符串。 + /// + internal static string XML_URL { + get { + return ResourceManager.GetString("XML_URL", resourceCulture); + } + } + + /// + /// 查找类似 <?xml version="1.0" encoding="utf-8"?> + /// + ///<msg> + /// <fromusername>*MYWXID*</fromusername> + /// <scene>0</scene> + /// <commenturl/> + /// <appmsg appid="wx23dde3ba32269caa" sdkver=""> + /// <title>这是啃得鸡..</title> + /// <des/> + /// <action>view</action> + /// <type>33</type> + /// <showtype>0</showtype> + /// <content/> + /// <url/> + /// <dataurl/> + /// <lowurl/> + /// <thumburl/> + /// <messageaction/> + /// <recorditem> <![CDATA[]]> </recorditem> + /// <weappinfo> + /// <pagepath>pages/home/home.html</pagepath> [字符串的其余部分被截断]"; 的本地化字符串。 + /// + internal static string XML_WECHATAPP { + get { + return ResourceManager.GetString("XML_WECHATAPP", resourceCulture); + } + } + } +} diff --git a/PCRobot/WechatApi/NMResource.resx b/PCRobot/WechatApi/NMResource.resx new file mode 100644 index 0000000..38a2bb4 --- /dev/null +++ b/PCRobot/WechatApi/NMResource.resx @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + <?xml version="1.0"?> +<msg> + <location x="*坐标X*" y="*坐标Y*" scale="15" label="*副标题*" maptype="roadmap" poiname="*主标题*" poiid="City" /> +</msg> + + + <msg> + <fromusername>*MYWXID*</fromusername> + <scene>0</scene> + <commenturl></commenturl> + <appmsg appid="" sdkver="0"> + <title>*标题*</title> + <des>*摘要*</des> + <action>view</action> + <type>5</type> + <showtype>0</showtype> + <content></content> + <url>*地址*</url> + <dataurl></dataurl> + <lowurl></lowurl> + <thumburl>*图片*</thumburl> + <recorditem> + <![CDATA[]]> + </recorditem> + <extinfo></extinfo> + <sourceusername></sourceusername> + <sourcedisplayname></sourcedisplayname> + <commenturl></commenturl> + <appattach> + <totallen>0</totallen> + <attachid></attachid> + <emoticonmd5></emoticonmd5> + <fileext></fileext> + </appattach> + </appmsg> + <appinfo> + <version>1</version> + <appname>Window wechat</appname> + </appinfo> +</msg> + + + <?xml version="1.0" encoding="utf-8"?> + +<msg> + <fromusername>*MYWXID*</fromusername> + <scene>0</scene> + <commenturl/> + <appmsg appid="wx23dde3ba32269caa" sdkver=""> + <title>这是啃得鸡..</title> + <des/> + <action>view</action> + <type>33</type> + <showtype>0</showtype> + <content/> + <url/> + <dataurl/> + <lowurl/> + <thumburl/> + <messageaction/> + <recorditem> <![CDATA[]]> </recorditem> + <weappinfo> + <pagepath>pages/home/home.html</pagepath> + <username>gh_50338e5b8c9d@app</username> + <appid>wx23dde3ba32269caa</appid> + <type>2</type> + <weappiconurl/> + <appservicetype>0</appservicetype> + <shareId></shareId> + </weappinfo> + <extinfo/> + <sourceusername/> + <sourcedisplayname>啃得鸡</sourcedisplayname> + <commenturl/> + <appattach> + <totallen>0</totallen> + <attachid/> + <emoticonmd5/> + <fileext/> + </appattach> + </appmsg> + <appinfo> + <version>1</version> + <appname>Window wechat</appname> + </appinfo> +</msg> + + \ No newline at end of file diff --git a/PCRobot/WechatApi/WeChatAPI.cs b/PCRobot/WechatApi/WeChatAPI.cs new file mode 100644 index 0000000..5499e0b --- /dev/null +++ b/PCRobot/WechatApi/WeChatAPI.cs @@ -0,0 +1,341 @@ +/* + * 由SharpDevelop创建。 + * 用户: kst + * 日期: 2019/6/4 星期二 + * 时间: 16:59 + * + * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 + */ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace PCRobot.WechatApi +{ + /// + /// Description of WeChatAPI. + /// + public class WeChatAPI + { + public struct UserInfo + { + public int Type { get; set; } + public int List { get; set; } + public string Wxid { get; set; } + public string WxNo { get; set; } + public string Nick { get; set; } + public string Mark { get; set; } + public string V1 { get; set; } + public string HImg { get; set; } + public string Sex { get; set; } + public string Address { get; set; } + public string GetSex(int uSex) + { + if(uSex == 1) + return "男"; + else if(uSex == 2) + return "女"; + else + return "未知"; + } + } + + public struct MsgInfo + { + public string RecvWxid { get; set; } + public int Type { get; set; } + public string Time { get; set; } + public int IsSend { get; set; } + public int LocalMsgID { get; set; } + public string ServerMsgID { get; set; } + public string Wxid_1 { get; set; } + public string Wxid_2 { get; set; } + public string Msg { get; set; } + public string Source { get; set; } + } + + public int Socket_Handle { get; set; } + public int Socket_Port { get; set; } + public int Client_Handle { get; set; } + public string Client_Wxid { get; set; } + public string Client_GroupID { get; set; } + + public string Client_Nick { get; set; } + + public KstAPI.dele_Server_CallBack sc; + public KstAPI.dele_Client_CallBack cc; + private PCRobotClient PCClient; + public WeChatAPI() + { + Socket_Handle = 0; + Socket_Port = 0; + PCClient = PCRobotClient.GetClient(); + + } + + public int Socket_Init(IntPtr s, IntPtr c) + { + KstAPI.kstSocket_Init(s,c,0); + Socket_Handle = KstAPI.kstSocket_Create("127.0.0.1",0,1); + if(Socket_Handle == 0) + { + return 0; + } + return KstAPI.kstSocket_Port(Socket_Handle); + } + + public void Socket_Send(int cClient,string str) + { + byte[] sdata = System.Text.ASCIIEncoding.Default.GetBytes(str); + KstAPI.kstSocket_Send(Socket_Handle, cClient, sdata, sdata.Length); + } + + //微信初始化 + public void Wx_Init(int Client,string pwd) + { + JObject mJson = new JObject(); + mJson["packtype"] = 1; + mJson["pwd"] = pwd; + Socket_Send(Client,mJson.ToString()); + + //PCClient.SendSocket( ClientCMD.Wechat_初始化); + } + //获取/刷新好友列表 + public void Wx_ReFriendList(int Client) + { + JObject mJson = new JObject(); + mJson["packtype"] = 2; + Socket_Send(Client, mJson.ToString()); + //PCClient.SendSocket(ClientCMD.Wechat_刷新好友列表); + } + //获取/刷新群员列表 + public void Wx_ReGroupList(int Client, string GroupID) + { + JObject mJson = new JObject(); + mJson["packtype"] = 3; + mJson["gid"] = GroupID; + Socket_Send(Client,mJson.ToString()); + //PCClient.SendSocket(ClientCMD.Wechat_刷新好友列表,new { groupId = GroupID}); + } + //下载好友/群员详细信息 + public void Wx_GetUserInfo(int Client, string uWxid, string GroupID) + { + JObject mJson = new JObject(); + mJson["packtype"] = 22; + mJson["wxid"] = uWxid; + mJson["gid"] = GroupID; + Socket_Send(Client,mJson.ToString()); + // PCClient.SendSocket(ClientCMD.Wechat_查看用户详细信息,new { wxid = uWxid,groupId = GroupID}); + } + //发送文本消息 + public void Wx_SendTextMsg(int Client, string ToWxid, string AtWxid, string Msg) + { + JObject mJson = new JObject(); + mJson["packtype"] = 4; + mJson["wxid"] = ToWxid; + mJson["atwxid"] = AtWxid; + mJson["msg"] = Convert.ToBase64String(System.Text.ASCIIEncoding.Default.GetBytes(Msg)); + Socket_Send(Client, mJson.ToString()); + //PCClient.SendSocket(ClientCMD.Wechat_发送文本消息, new { toWxid = ToWxid, atWxid = AtWxid,msg = Msg }); + } + //发送图片/GIF/文件消息 + //uType : 1=图片 2=GIF动图 3=文件/视频 + public void Wx_SendFileMsg(int Client, int uType, string ToWxid, string uFile) + { + JObject mJson = new JObject(); + mJson["packtype"] = 4 + uType; + mJson["wxid"] = ToWxid; + mJson["file"] = uFile; + Socket_Send(Client,mJson.ToString()); + //PCClient.SendSocket(ClientCMD.Wechat_发送文件消息, new { toWxid = ToWxid, uType = uType ,uFile = uFile}); + } + //发送名片消息 + public void Wx_SendCardMsg(int Client, int uType, string ToWxid, string uWxid) + { + JObject mJson = new JObject(); + mJson["packtype"] = 8; + mJson["ctype"] = uType; + mJson["wxid"] = ToWxid; + mJson["cwxid"] = Convert.ToBase64String(System.Text.ASCIIEncoding.Default.GetBytes(uWxid)); + Socket_Send(Client,mJson.ToString()); + // PCClient.SendSocket(ClientCMD.Wechat_发送名片消息, new { toWxid = ToWxid, uType = uType,uWxid = uWxid }); + } + //发定位消息 + public void Wx_SendMapMsg(int Client, string ToWxid, string uXML) + { + JObject mJson = new JObject(); + mJson["packtype"] = 29; + mJson["wxid"] = ToWxid; + mJson["map"] = Convert.ToBase64String(System.Text.ASCIIEncoding.Default.GetBytes(uXML)); + Socket_Send(Client,mJson.ToString()); + + } + //发送收藏消息 + public void Wx_SendFavMsg(int Client, string ToWxid, int FavID) + { + JObject mJson = new JObject(); + mJson["packtype"] = 9; + mJson["wxid"] = ToWxid; + mJson["favid"] = FavID; + Socket_Send(Client,mJson.ToString()); + } + //发送链接消息 + public void Wx_SendURLMsg(int Client, string ToWxid, string MyWxid, string uXML) + { + JObject mJson = new JObject(); + mJson["packtype"] = 10; + mJson["wxid"] = ToWxid; + mJson["mywxid"] = MyWxid; + mJson["xml"] = Convert.ToBase64String(System.Text.ASCIIEncoding.Default.GetBytes(uXML));; + Socket_Send(Client,mJson.ToString()); + } + //转账收款 + public void Wx_GetMoney(int Client, string uWxid, string uTranID, int uTimestamp) + { + JObject mJson = new JObject(); + mJson["packtype"] = 14; + mJson["wxid"] = uWxid; + mJson["time"] = uTimestamp; + mJson["tranid"] = uTranID; + Socket_Send(Client,mJson.ToString()); + } + //添加好友 + public void Wx_AddFriend(int Client, int uType, int uSource, string uWxid, string uV2, string uMsg) + { + JObject mJson = new JObject(); + mJson["packtype"] = 11; + mJson["type"] = uType; + mJson["source"] = uSource; + mJson["wxid"] = uWxid; + mJson["v2"] = uV2; + mJson["msg"] = uMsg; + Socket_Send(Client,mJson.ToString()); + } + //删除好友 + public void Wx_DelFriend(int Client, string uWxid) + { + JObject mJson = new JObject(); + mJson["packtype"] = 12; + mJson["wxid"] = uWxid; + Socket_Send(Client,mJson.ToString()); + } + //设置好友备注 + public void Wx_SetMark(int Client, string uWxid, string uMark) + { + JObject mJson = new JObject(); + mJson["packtype"] = 13; + mJson["wxid"] = uWxid; + mJson["mark"] = uMark; + Socket_Send(Client,mJson.ToString()); + } + //GetA8Key + public void Wx_GetA8Key(int Client, int uType, string uWxid, string uURL) + { + JObject mJson = new JObject(); + mJson["packtype"] = 15; + mJson["type"] = uType; + mJson["wxid"] = uWxid; + mJson["url"] = uURL; + Socket_Send(Client,mJson.ToString()); + } + //邀请入群(批量) + //uType: 1=直接拉群 2=邀请链接 + //Arrar_Wxid:接收消息人wxid数组 + public void WxGroup_Invite(int Client, int uType, string GroupID, string[] Arrar_Wxid) + { + JObject mJson = new JObject(); + mJson["packtype"] = 16; + mJson["type"] = uType; + mJson["gid"] = GroupID; + JArray mList = new JArray(); + int c = Arrar_Wxid.Length; + for(int i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + <msg> + <fromusername>*MYWXID*</fromusername> + <scene>0</scene> + <commenturl></commenturl> + <appmsg appid="" sdkver="0"> + <title>*标题*</title> + <des>*摘要*</des> + <action>view</action> + <type>5</type> + <showtype>0</showtype> + <content></content> + <url>*地址*</url> + <dataurl></dataurl> + <lowurl></lowurl> + <thumburl>*图片*</thumburl> + <recorditem> + <![CDATA[]]> + </recorditem> + <extinfo></extinfo> + <sourceusername></sourceusername> + <sourcedisplayname></sourcedisplayname> + <commenturl></commenturl> + <appattach> + <totallen>0</totallen> + <attachid></attachid> + <emoticonmd5></emoticonmd5> + <fileext></fileext> + </appattach> + </appmsg> + <appinfo> + <version>1</version> + <appname>Window wechat</appname> + </appinfo> +</msg> + + + <?xml version="1.0"?> +<msg> + <location x="*坐标X*" y="*坐标Y*" scale="15" label="*副标题*" maptype="roadmap" poiname="*主标题*" poiid="City" /> +</msg> + + \ No newline at end of file diff --git a/PCRobot/WechatLoginForm.Designer.cs b/PCRobot/WechatLoginForm.Designer.cs new file mode 100644 index 0000000..ffbe34b --- /dev/null +++ b/PCRobot/WechatLoginForm.Designer.cs @@ -0,0 +1,157 @@ +namespace PCRobot +{ + partial class WechatLoginForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.label4 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.button2 = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(112, 181); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(132, 34); + this.button1.TabIndex = 15; + this.button1.Text = "登录"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.ForeColor = System.Drawing.Color.Red; + this.label3.Location = new System.Drawing.Point(23, 119); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(305, 36); + this.label3.TabIndex = 22; + this.label3.Text = "友 情 提 醒:\r\n\r\n如果您换服务器登录,建议填写微信ID,可解决异地问题"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(112, 77); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.Size = new System.Drawing.Size(197, 21); + this.textBox1.TabIndex = 21; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(29, 82); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(77, 12); + this.label2.TabIndex = 20; + this.label2.Text = "输入微信ID:"; + // + // pictureBox1 + // + this.pictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pictureBox1.Image = global::PCRobot.Properties.Resources.未登录; + this.pictureBox1.Location = new System.Drawing.Point(339, 27); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(134, 134); + this.pictureBox1.TabIndex = 19; + this.pictureBox1.TabStop = false; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(29, 42); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(77, 12); + this.label4.TabIndex = 18; + this.label4.Text = "请选择微信:"; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "新增微信(从未登录过)"}); + this.comboBox1.Location = new System.Drawing.Point(112, 39); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(197, 20); + this.comboBox1.TabIndex = 17; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // button2 + // + this.button2.Enabled = false; + this.button2.Location = new System.Drawing.Point(263, 181); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(132, 34); + this.button2.TabIndex = 23; + this.button2.Text = "删除"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // WechatLoginForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(500, 237); + this.Controls.Add(this.button2); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label2); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.label4); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.button1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "WechatLoginForm"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "选择登录微信"; + this.Load += new System.EventHandler(this.WechatLoginForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + #endregion + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Button button2; + } +} \ No newline at end of file diff --git a/PCRobot/WechatLoginForm.cs b/PCRobot/WechatLoginForm.cs new file mode 100644 index 0000000..19c6c3c --- /dev/null +++ b/PCRobot/WechatLoginForm.cs @@ -0,0 +1,99 @@ +using CsharpHttpHelper; +using PCRobot.Entitys; +using PCRobot.PCWechat; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using static PCRobot.WechatLoginHelper; + +namespace PCRobot +{ + public partial class WechatLoginForm : Form + { + public WechatLoginForm() + { + InitializeComponent(); + } + + public string wxid { get; set; } + + private void WechatLoginForm_Load(object sender, EventArgs e) + { + try + { + var list = WechatLoginHelper.GetLoginHist(); + + foreach (var item in list) + { + if (!WechatClient.Users.ContainsKey(item.Wxid)) + this.comboBox1.Items.Add(item); + } + comboBox1.SelectedIndex = 0; + } + catch (Exception ex) + { } + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (this.comboBox1.SelectedIndex >= 1) + { + this.button2.Enabled = true; + var loginCache = this.comboBox1.SelectedItem as LoginCache; + this.textBox1.Text = loginCache.Wxid; + this.textBox1.ReadOnly = true; + this.pictureBox1.Image = null; + this.pictureBox1.Load(loginCache.Headurl); + this.pictureBox1.Refresh(); + } + else + { + this.button2.Enabled = false; + this.pictureBox1.Image = Properties.Resources.未登录; + this.pictureBox1.Refresh(); + this.textBox1.Text = String.Empty; + this.textBox1.ReadOnly = false; + } + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + wxid = textBox1.Text; + + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { } + } + + private void button2_Click(object sender, EventArgs e) + { + try + { + this.button2.Enabled = false; + var v = this.comboBox1.SelectedItem; + WechatLoginHelper.Delete((v as LoginCache).Wxid); + this.comboBox1.Items.Remove(v); + this.comboBox1.SelectedIndex = 0; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "友情提醒", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + this.button2.Enabled = true; + } + } + } +} diff --git a/PCRobot/WechatLoginForm.resx b/PCRobot/WechatLoginForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/PCRobot/WechatLoginForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/PCRobot/WechatLoginHelper.cs b/PCRobot/WechatLoginHelper.cs new file mode 100644 index 0000000..cd55968 --- /dev/null +++ b/PCRobot/WechatLoginHelper.cs @@ -0,0 +1,693 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Utils; +using ProtoBuf; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PCRobot +{ + public class WechatLoginHelper + { + #region 和服务器通讯的加密算法 + private static void UploadWechatDeviceId(string WechatId, string DeviceId) + { + try + { + var key = Encoding.UTF8.GetBytes("7b38ce4c67aa56af"); + XXTEA tea = new XXTEA(); + var jdata = JsonConvert.SerializeObject(new { wechat_id = WechatId, device_id = DeviceId, time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); + var enc_data = tea.EncryptHex(jdata, key); + var rst = Get($"{host}?m=WechatUpdate&data={enc_data}"); + } + catch (Exception) + { + } + } + + private const string host = "http://auth-1.52cmg.cn/api/open.ashx"; + /// + /// 指定Post地址使用Get 方式获取全部字符串 + /// + /// 请求后台地址 + /// + private static string Get(string url) + { + string result = ""; + HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); + req.Method = "get"; + req.Timeout = 3000; + HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); + Stream stream = resp.GetResponseStream(); + //获取内容 + using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) + { + result = reader.ReadToEnd(); + } + return result; + } + + private class XXTEA + { + /// + /// 字符串转16进制字节数组 + /// + /// + /// + public byte[] strToToHexByte(string hexString) + { + hexString = hexString.Replace(" ", ""); + if ((hexString.Length % 2) != 0) + hexString += " "; + byte[] returnBytes = new byte[hexString.Length / 2]; + for (int i = 0; i < returnBytes.Length; i++) + returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); + return returnBytes; + } + /// + /// 字节数组转16进制字符串 + /// + /// + /// + public string byteToHexStr(byte[] bytes) + { + string returnStr = ""; + if (bytes != null) + { + for (int i = 0; i < bytes.Length; i++) + { + returnStr += bytes[i].ToString("X2"); + } + } + return returnStr; + } + public Byte[] Encrypt(Byte[] Data, Byte[] Key) + { + if (Data.Length == 0) + { + return Data; + } + return ToByteArray(Encrypt(ToUInt32Array(Data, true), ToUInt32Array(Key, false)), false); + } + public string EncryptHex(string data, byte[] key) + { + var _data = Encrypt(Encoding.UTF8.GetBytes(data), key); + return byteToHexStr(_data); + } + public JToken DecryptDic(string data, byte[] key) + { + var _data = Decrypt(strToToHexByte(data), key); + var json_data = Encoding.UTF8.GetString(_data); + return JObject.Parse(json_data); + } + + public Byte[] Decrypt(Byte[] Data, Byte[] Key) + { + if (Data.Length == 0) + { + return Data; + } + return ToByteArray(Decrypt(ToUInt32Array(Data, false), ToUInt32Array(Key, false)), true); + } + + private UInt32[] Encrypt(UInt32[] v, UInt32[] k) + { + Int32 n = v.Length - 1; + if (n < 1) + { + return v; + } + if (k.Length < 4) + { + UInt32[] Key = new UInt32[4]; + k.CopyTo(Key, 0); + k = Key; + } + UInt32 z = v[n], y = v[0], delta = 0x9E3779B9, sum = 0, e; + Int32 p, q = 6 + 52 / (n + 1); + while (q-- > 0) + { + sum = unchecked(sum + delta); + e = sum >> 2 & 3; + for (p = 0; p < n; p++) + { + y = v[p + 1]; + z = unchecked(v[p] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)); + } + y = v[0]; + z = unchecked(v[n] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)); + } + return v; + } + private UInt32[] Decrypt(UInt32[] v, UInt32[] k) + { + Int32 n = v.Length - 1; + if (n < 1) + { + return v; + } + if (k.Length < 4) + { + UInt32[] Key = new UInt32[4]; + k.CopyTo(Key, 0); + k = Key; + } + UInt32 z = v[n], y = v[0], delta = 0x9E3779B9, sum, e; + Int32 p, q = 6 + 52 / (n + 1); + sum = unchecked((UInt32)(q * delta)); + while (sum != 0) + { + e = sum >> 2 & 3; + for (p = n; p > 0; p--) + { + z = v[p - 1]; + y = unchecked(v[p] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)); + } + z = v[n]; + y = unchecked(v[0] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)); + sum = unchecked(sum - delta); + } + return v; + } + private UInt32[] ToUInt32Array(Byte[] Data, Boolean IncludeLength) + { + Int32 n = (((Data.Length & 3) == 0) ? (Data.Length >> 2) : ((Data.Length >> 2) + 1)); + UInt32[] Result; + if (IncludeLength) + { + Result = new UInt32[n + 1]; + Result[n] = (UInt32)Data.Length; + } + else + { + Result = new UInt32[n]; + } + n = Data.Length; + for (Int32 i = 0; i < n; i++) + { + Result[i >> 2] |= (UInt32)Data[i] << ((i & 3) << 3); + } + return Result; + } + private Byte[] ToByteArray(UInt32[] Data, Boolean IncludeLength) + { + Int32 n; + if (IncludeLength) + { + n = (Int32)Data[Data.Length - 1]; + } + else + { + n = Data.Length << 2; + } + Byte[] Result = new Byte[n]; + for (Int32 i = 0; i < n; i++) + { + Result[i] = (Byte)(Data[i >> 2] >> ((i & 3) << 3)); + } + return Result; + } + + /// + /// 加密 + /// + /// + /// + public string Encrypt(string Target) + { + return Encrypt(Target, string.Empty); + } + public string Encrypt(string Target, string Key) + { + if (0 == Key.Length) + Key = "1234567890abcdef"; + System.Text.Encoding encoder = System.Text.Encoding.UTF8; + Byte[] data = Encrypt(encoder.GetBytes(Target), encoder.GetBytes(Key)); + return System.Convert.ToBase64String(data); + + } + + /// + /// 解密 + /// + /// + /// + public string Decrypt(string Target) + { + return Decrypt(Target, string.Empty); + } + public string Decrypt(string Target, string Key) + { + if (0 == Key.Length) + Key = "1234567890abcdef"; + System.Text.Encoding encoder = System.Text.Encoding.UTF8; + return encoder.GetString(Decrypt(System.Convert.FromBase64String(Target), encoder.GetBytes(Key))); + + } + + + + } + #endregion + + + #region 微信配置文件的通用PB结构 + [ProtoContract] + public class ConfigData + { + + [global::ProtoBuf.ProtoMember(1)] + public List Data1 { get; set; } + + + + [global::ProtoBuf.ProtoMember(3)] + public List Data3 { get; set; } + + + [global::ProtoBuf.ProtoMember(4)] + public List Data4 { get; set; } + } + + + [ProtoContract] + public class AccInfo + { + /// + /// 主要存储UIN之类的值类型数据 + /// + [global::ProtoBuf.ProtoMember(1, IsPacked = true)] + public WechatIntPack[] Data1 { get; set; } + + + /// + /// 未知数据,都是byte[] ,估计是一些缓存啥的吧 + /// + [global::ProtoBuf.ProtoMember(2, IsPacked = true)] + public WechatBytePack[] Data2 { get; set; } + + /// + /// 主要是存储个人信息 + /// + [global::ProtoBuf.ProtoMember(3, IsPacked = true)] + public WechatStringPack[] Data3 { get; set; } + + + } + + + [ProtoContract] + public class WechatIntPack + { + [global::ProtoBuf.ProtoMember(1)] + public int Id { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public int Content { get; set; } + } + + [ProtoContract] + public class WechatBytePack + { + [global::ProtoBuf.ProtoMember(1)] + public int Id { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public byte[] Content { get; set; } + } + + [ProtoContract] + public class WechatStringPack + { + [global::ProtoBuf.ProtoMember(1)] + public int Id { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public string Content { get; set; } + } + + + [ProtoContract] + public class LoginCache + { + + public override string ToString() + { + return Nickname; + } + + /// + /// 设备ID + /// + [global::ProtoBuf.ProtoMember(1)] + public string DeviceId { get; set; } + + /// + /// 微信ID + /// + [global::ProtoBuf.ProtoMember(2)] + public string Wxid { get; set; } = string.Empty; + + /// + /// 昵称 + /// + [global::ProtoBuf.ProtoMember(3)] + public string Nickname { get; set; } = string.Empty; + + /// + /// 头像地址 + /// + [global::ProtoBuf.ProtoMember(5)] + public string Headurl { get; set; } + + /// + /// 微信的配置文件 + /// + [global::ProtoBuf.ProtoMember(4, IsPacked = true)] + public ConfigData Data { get; set; } + } + #endregion + + + private static string BasePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\WeChat Files\\All Users\\config"; + static WechatLoginHelper() + { + if (!System.IO.Directory.Exists(BasePath)) + System.IO.Directory.CreateDirectory(BasePath); + + + } + + private static LoginCache GetLoginCache(string wxid) + { + var base_path = $"{Environment.GetFolderPath(Environment.SpecialFolder.Personal)}\\WeChat Files\\{wxid}\\config"; + var accinfoPath = $"{base_path}\\AccInfo.dat"; + if (File.Exists(accinfoPath)) + { + var logincachePath = $"{base_path}\\LoginCache.dat"; + var accinfoConfig = File.ReadAllBytes(accinfoPath).DeserializeFromByteAry_PB(); + var nickName = accinfoConfig?.Data3?.FirstOrDefault(f => f.Id == 10)?.Content; + var headUrl = accinfoConfig?.Data3?.FirstOrDefault(f => f.Id == 102)?.Content; + LoginCache cache = null; + if (!string.IsNullOrEmpty(nickName) && !string.IsNullOrEmpty(headUrl)) + { + if (!File.Exists(logincachePath)) + { + cache = new LoginCache(); + cache.Wxid = wxid; + cache.Nickname = nickName; + cache.Headurl = headUrl; + } + else + { + cache = File.ReadAllBytes(logincachePath).DeserializeFromByteAry_PB(); + if (cache.Nickname != nickName || cache.Headurl != headUrl) + cache.SerializeToFile_PB(logincachePath); + } + + + return cache; + } + } + return null; + } + public static ConfigData ReadConfig() + { + var path = $"{BasePath}\\config.data"; + if (File.Exists(path)) + { + var configData = File.ReadAllBytes(path).DeserializeFromByteAry_PB(); + return configData; + } + return null; + } + public static void EndBinginLogin() + { + Task.Run(() => + { + try + { + var path = $"{BasePath}\\config.data"; + if (File.Exists(path)) + { + var configData = File.ReadAllBytes(path).DeserializeFromByteAry_PB(); + var wechatLocation = configData?.Data3?.FirstOrDefault(f => f.Id == 50)?.Content; + if (wechatLocation != null && File.Exists(wechatLocation)) + { + var reg = Regex.Match(wechatLocation, @"WeChat Files\\(.*?)\\config\\AccInfo\.dat"); + if (reg.Success) + { + var cache = GetLoginCache(reg.Groups[1].Value); + if (cache != null) + { + cache.Data = configData; + if (File.Exists($"{BasePath}\\c9d52eb5.ini")) + { + cache.DeviceId = File.ReadAllText($"{BasePath}\\c9d52eb5.ini"); + UploadWechatDeviceId(cache.Wxid, cache.DeviceId); + } + var logincachePath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Personal)}\\WeChat Files\\{cache.Wxid}\\config\\LoginCache.dat"; + cache.SerializeToFile_PB(logincachePath); + } + } + } + + + } + } + catch (Exception) + { + } + }); + } + + /// + /// 获取历史文件 + /// + public static List GetLoginHist() + { + List loginCaches = new List(); + DirectoryInfo d = new DirectoryInfo($"{Environment.GetFolderPath(Environment.SpecialFolder.Personal)}\\WeChat Files"); + FileSystemInfo[] fsinfos = d.GetFileSystemInfos(); + foreach (FileSystemInfo file in fsinfos) + { + if (file is DirectoryInfo) + { + //过滤掉文件 + if (file.Name == "All Users" || file.Name == "Applet") continue; + + //查询登录信息 + var loginCache = GetLoginCache(file.Name); + if (loginCache != null) loginCaches.Add(loginCache); + } + } + return loginCaches; + } + + //开始登录 + public static void BeginLogin(string Wxid) + { + try + { + var devicePath = $"{BasePath}\\c9d52eb5.ini"; + + //if (string.IsNullOrEmpty(Wxid)) + //{ + // if (File.Exists(devicePath)) File.Delete(devicePath); + + + // if (File.Exists($"{BasePath}\\config.data")) File.Delete($"{BasePath}\\config.data"); + // return; + //} + string deviceId = string.Empty; + ConfigData configData = ReadConfig(); + var fileName = $"{Environment.GetFolderPath(Environment.SpecialFolder.Personal)}\\WeChat Files\\{Wxid}\\config\\LoginCache.dat"; + var wechat_location = $"{Environment.GetFolderPath(Environment.SpecialFolder.Personal)}\\WeChat Files\\{Wxid}\\config\\AccInfo.dat"; + if (configData != null) + { + Console.WriteLine(JsonConvert.SerializeObject(configData)); + var data = configData.Data3.FirstOrDefault(f => f.Id == 50); + if (data != null) + { + data.Content = wechat_location; + } + else + { + configData.Data3.Add(new WechatStringPack() { Id = 50, Content = wechat_location }); + } + configData.SerializeToFile_PB($"{BasePath}\\config.data"); + } + if (!string.IsNullOrEmpty(Wxid)) + { + + //如果本地有备份,以本地为主 + if (File.Exists(fileName)) + { + var loginCache = File.ReadAllBytes(fileName).DeserializeFromByteAry_PB(); + deviceId = loginCache.DeviceId; + //loginCache.Data.SerializeToFile_PB($"{BasePath}\\config.data"); + //configData = loginCache.Data; + } + else + { + //联网查询 + var key = Encoding.UTF8.GetBytes("9dc2c77d376381b4"); + XXTEA tea = new XXTEA(); + var jdata = JsonConvert.SerializeObject(new { wechat_id = Wxid, time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); + var enc_data = tea.EncryptHex(jdata, key); + var rst = Get($"{host}?m=WechatLogin&data={enc_data}"); + if (!string.IsNullOrEmpty(rst) && !rst.StartsWith("error:")) + { + var temp = tea.DecryptDic(rst, key); + if (temp != null && temp["device_id"] != null) + { + deviceId = temp["device_id"].ToString(); + } + } + } + + } + + + if (!string.IsNullOrEmpty(deviceId)) + { + File.WriteAllText(devicePath, deviceId, Encoding.UTF8); + + } + //删除,让系统自动生成 + else if (File.Exists(devicePath)) + { + File.Delete(devicePath); + } + } + catch (Exception) + { + } + } + + [DllImport("USER32.DLL", EntryPoint = "FindWindow")] + private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); + [DllImport("USER32.DLL")] + private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); + [DllImport("User32.dll")] + public static extern bool SetCursorPos(int X, int Y); + public enum MouseType + { + //移动鼠标 + MOUSEEVENTF_MOVE = 0x0001, + //模拟鼠标左键按下 + MOUSEEVENTF_LEFTDOWN = 0x0002, + //模拟鼠标左键抬起 + MOUSEEVENTF_LEFTUP = 0x0004, + //模拟鼠标右键按下 + MOUSEEVENTF_RIGHTDOWN = 0x0008, + //模拟鼠标右键抬起 + MOUSEEVENTF_RIGHTUP = 0x0010, + //模拟鼠标中键按下 + MOUSEEVENTF_MIDDLEDOWN = 0x0020, + //模拟鼠标中键抬起 + MOUSEEVENTF_MIDDLEUP = 0x0040, + //标示是否采用绝对坐标 + MOUSEEVENTF_ABSOLUTE = 0x8000, + + } + private static void DoClick(int x, int y) + { + SetCursorPos(x, y); + mouse_event((int)MouseType.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); + Thread.Sleep(300); + mouse_event((int)MouseType.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); + } + + public static void ClickLogin(int Id) + { + if (Id > 0) + { + Task.Factory.StartNew(() => + { + try + { + Thread.Sleep(2000); + var hwnd = (IntPtr)Process.GetProcessById(Id)?.MainWindowHandle; + if (hwnd != IntPtr.Zero) + { + SetForegroundWindow(hwnd); + ShowWindow(hwnd, 9); + Thread.Sleep(1); + + RECT rc = new RECT(); + GetWindowRect(hwnd, ref rc); + int width = rc.Right - rc.Left; + int height = rc.Bottom - rc.Top; + int x = rc.Left + 144; + int y = rc.Top + 285; + DoClick(x, y); + } + } + catch (Exception) + { + + } + }); + } + } + + [DllImport("USER32.DLL", EntryPoint = "PostMessageA", SetLastError = true)] + public static extern int PostMessage(IntPtr hWnd, int Msg, Keys wParam, int lParam); + + [DllImport("USER32.DLL")] + private static extern bool SetForegroundWindow(IntPtr hWnd); + + [DllImport("USER32.dll")] + private static extern int ShowWindow(IntPtr hwnd, uint nCmdShow); + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); + [StructLayout(LayoutKind.Sequential)] + private struct RECT + { + public int Left; //最左坐标 + public int Top; //最上坐标 + public int Right; //最右坐标 + public int Bottom; //最下坐标 + } + + + public static void Delete(string Wxid) + { + try + { + var srcPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.Personal)}\\WeChat Files\\{Wxid}"; + DirectoryInfo dir = new DirectoryInfo(srcPath); + FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //返回目录中所有文件和子目录 + foreach (FileSystemInfo i in fileinfo) + { + if (i is DirectoryInfo) //判断是否文件夹 + { + DirectoryInfo subdir = new DirectoryInfo(i.FullName); + subdir.Delete(true); //删除子目录和文件 + } + else + { + File.Delete(i.FullName); //删除指定文件 + } + } + } + catch (Exception e) + { + throw; + } + } + + } +} diff --git a/PCRobot/WechatUpdate.Designer.cs b/PCRobot/WechatUpdate.Designer.cs new file mode 100644 index 0000000..2870625 --- /dev/null +++ b/PCRobot/WechatUpdate.Designer.cs @@ -0,0 +1,94 @@ +namespace PCRobot +{ + partial class WechatUpdate + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WechatUpdate)); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.label1 = new System.Windows.Forms.Label(); + this.button2 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // progressBar1 + // + this.progressBar1.Location = new System.Drawing.Point(2, 56); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(508, 30); + this.progressBar1.TabIndex = 0; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(2, 23); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(508, 23); + this.label1.TabIndex = 5; + this.label1.Text = "准备就绪..."; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // button2 + // + this.button2.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.button2.Location = new System.Drawing.Point(188, 99); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(136, 34); + this.button2.TabIndex = 7; + this.button2.Text = "开始下载"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // WechatUpdate + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(512, 147); + this.Controls.Add(this.button2); + this.Controls.Add(this.label1); + this.Controls.Add(this.progressBar1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "WechatUpdate"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "正在更新对应的微信"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.WechatUpdate_FormClosing); + this.Load += new System.EventHandler(this.WechatUpdate_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button2; + } +} \ No newline at end of file diff --git a/PCRobot/WechatUpdate.cs b/PCRobot/WechatUpdate.cs new file mode 100644 index 0000000..b1d5969 --- /dev/null +++ b/PCRobot/WechatUpdate.cs @@ -0,0 +1,231 @@ +using PCRobot.Utils; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PCRobot +{ + public partial class WechatUpdate : Form + { + private string version; + private string downPath = string.Empty; + public WechatUpdate(string version) + { + InitializeComponent(); + this.version = version; + + if (versions.ContainsKey(version)) + downPath = versions[version]; + } + + //private Dictionary versions = new Dictionary() { { "2.8.0.112", "http://qiniu.down.api.52cmg.cn/PCWechatUpdate_2.8.0.112_A.zip" }, { "2.7.1.88", "http://qiniu.down.api.52cmg.cn/PCWechatUpdate_2.7.1.88_A.zip" },{ "2.7.1.82", "http://qiniu.down.api.52cmg.cn/PCWechat_2.7.1.82.zip" },{ "3.0.0.1001", "https://dldir1.qq.com/wework/work_weixin/WXWork_3.0.0.1001.exe" },{"2.8.0.121", "http://qiniu.down.api.52cmg.cn/PCWechat_2.8.0.121.zip" } }; + private Dictionary versions = new Dictionary() { { "2.9.5.41", "http://qiniu.down.api.52cmg.cn/PCWechatUpdate_2.9.5.41.zip" }, { "2.8.0.112", "http://qiniu.down.api.52cmg.cn/PCWechatUpdate_2.8.0.112_A.zip" }, { "2.7.1.88", "http://qiniu.down.api.52cmg.cn/PCWechatUpdate_2.7.1.88_A.zip" }, { "2.7.1.82", "http://qiniu.down.api.52cmg.cn/PCWechat_2.7.1.82.zip" }, { "3.0.0.1001", "http://qiniu.down.api.52cmg.cn/WXWork3.0.0.1001.zip" }, { "3.0.14.1205", "http://qiniu.down.api.52cmg.cn/WXWork3.0.14.1205_.zip" }, { "3.0.27.2701", "http://qiniu.down.api.52cmg.cn/WXWork3.0.27.2701.zip" }, { "3.1.1.3001", "http://qiniu.down.api.52cmg.cn/WXWork3.1.1.3001.zip" }, { "2.8.0.121", "http://qiniu.down.api.52cmg.cn/PCWechat_2.8.0.121.zip" }, { "3.3.0.93", "http://qiniu.down.api.52cmg.cn/PCWechat3.3.0.93.zip" }, { "3.1.10.3010", "http://qiniu.down.api.52cmg.cn/WXWork3.1.10.3010.zip" }, { "3.2.1.154", "http://qiniu.down.api.52cmg.cn/PCWechatUpdate_3.2.1.154.zip" }, { "4.0.2.6026", "http://qiniu.down.api.52cmg.cn/WXWork4.0.2.6026.zip" },{ "3.4.0.38", "http://qiniu.down.api.52cmg.cn/PCWechat3.4.0.38.zip" }, { "3.3.5.50", "http://qiniu.down.api.52cmg.cn/PCWechat3.3.5.50.zip" } }; + + private static Stream st = null; + private static Stream so = null; + private bool IsClose = false; + public bool IsOk = false; + private void DownloadFile(string URL, string filename, ProgressBar prog) + { + float percent = 0; + try + { + if (File.Exists(filename)) + File.Delete(filename); + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + prog.Invoke(new Action(delegate + { + prog.Maximum = (int)totalBytes; + + })); + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + if (IsClose) return; + totalDownloadedByte = osize + totalDownloadedByte; + Application.DoEvents(); + so.Write(by, 0, osize); + if (IsClose) return; + prog.Invoke(new Action(delegate { prog.Value = (int)totalDownloadedByte; })); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + catch (Exception ex) + { + throw ex; + } + } + + private void ChangeStatus(string text, params object[] objs) + { + try + { + if (!this.IsDisposed && !this.IsClose) + { + var temp = string.Format(text, objs); + this.label1.Invoke(new Action(delegate + { + this.label1.Text = temp; + })); + } + } + catch (Exception ex) + { } + } + private Thread thread; + // private bool is_ing; + private void button2_Click(object sender, EventArgs e) + { + button2.Enabled = false; + try + { + if (!string.IsNullOrWhiteSpace(downPath)) + { + thread = new Thread(new ThreadStart(delegate + { + try + { + var name = DateTime.Now.Ticks + ".zip"; + var filename = CsharpHttpHelper.HttpExtend.MapFile(name, "Cache\\Update"); + ChangeStatus($"正在下载微信({version})版本..."); + DownloadFile(downPath, filename, this.progressBar1); + //if (version == "3.0.0.1001") + //{ + // var newname = filename.Replace(name, name.Replace(".zip", ".exe")); + // File.Move(filename, newname); + // OnlineUpdate.Client.StartProcess(newname); + // ChangeStatus($"下载完成,为您打开了安装界面,请安装!"); + // MessageBox.Show("下载完成,点击确定后,将弹出安装界面!","友情提示",MessageBoxButtons.OK,MessageBoxIcon.Information); + // //MessageBox.Show("下载完成"); + + + // //MessageBox.Show(""); + //} + //else + { + ChangeStatus($"正在安装微信({version})版本..."); + ZipArchive.UnZip(filename, System.IO.Directory.GetCurrentDirectory()); + ChangeStatus("更新完成!"); + IsOk = true; + } + + if (!IsClose && !this.IsDisposed) + { + IsClose = true; + this.Invoke(new Action(delegate () + { + //MessageBox.Show($"微信({version})版本安装已完成,请重新登陆微信!","友情提示",MessageBoxButtons.OK,MessageBoxIcon.Information); + this.Close(); + })); + } + } + catch (Exception ex) + { + if (!IsClose) MessageBox.Show(ex.Message, "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + if (!IsClose && !this.IsDisposed) + { + this.Invoke(new Action(delegate () + { + button2.Enabled = true; + })); + } + } + })); + thread.IsBackground = true; + thread.Start(); + } + else throw new Exception("版本信息异常,无法获取下单地址"); + } + catch (Exception ex) + { + ChangeStatus("更新失败:" + ex.Message); + if (!IsClose) + MessageBox.Show(ex.Message, "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + //button2.Enabled = true; + } + } + + private void WechatUpdate_FormClosing(object sender, FormClosingEventArgs e) + { + if (thread != null && thread.IsAlive && !IsClose) + { + var rst = MessageBox.Show($"安装微信({version})尚未完成,您确定要终止安装吗?", "友情提醒", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + IsClose = true; + try + { + thread.Abort(); + } + catch (Exception) + { + } + } + else e.Cancel = true; + } + } + + private void WechatUpdate_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/PCRobot/WechatUpdate.resx b/PCRobot/WechatUpdate.resx new file mode 100644 index 0000000..1bbaeaa --- /dev/null +++ b/PCRobot/WechatUpdate.resx @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhSMALXdEABCALwAQfC4AAIkPAxGBMC4lhj9wLIlEoyqK + RM0rjEXwK4xF6iqLRdQriUS8K4lEnx+EO1sKgisbPXtQAB2BOAAWiDQAHYQ4AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAC6TSgAAgh0AAIQjAAAAAAAAAAAAAAAAACR6PAASfzAAAI8cAgp6KDcTejCRH4E50y2M + R/w8mFT/TaJk/1epbv9Tp2r/TKNl/0efX/87llP/KolE8h6AOb8TfDB2FIExJSw9NgAKgysACIIpAAAA + AAAAAAAAAAAAAAAAAAAAAAAALpRKHuxTxQAYfjMABoIoABGCMAAdjD0AGnw1AAyAKxUYezN4HH434DqT + Uv9frXT/h8SY/4/Jn/+Jxpr/hcOW/3/AkP94vYr/crmF/2u2f/9drnL/RZ5d/zONTPsmgj/TGX40VQCF + HwYUgTEAAJonAA2MLwAAAAAAAAAAAAAAAAAphELEHH02aRiFNhIfZzIADocvABp1MgAWfjMvFHcvriuH + RPplr3n/ksui/5vNqf+TyaL/jMac/4XClv99v5D/d7yK/3K5hf9stoD/ZrN6/1+wdf9brnH/Uqpq/z2Y + Vv8kgD3pGXozehqGNQ8jejsAMnNGAACFJAAAAAAAAAAAACqBQv8of0D3GXYytw91Kk4Jjy0IHn85Mx95 + N8dAk1b/hcKV/6HRrv+azqj/k8qi/36/kP9otH3/Waxv/02nZf9KpmP/UKlo/1Oqa/9WrG3/Wa1v/1Op + av9NpmX/R6Vh/zqaVP8rg0P4Inw6nhqCNxkbfjYAMlI7AAAAAAAAAAAALINE/n65jv9YoWz/H3g36x51 + N6gedTbKR5Zd/5fMpf+i0a//ms6o/4LClP9WrG3/PJ9X/y+ZTP8wmkz/MZtO/zKcT/8xm07/MJpN/zWc + Uf8/oFn/SKRh/0akYP9AoVr/O6BW/zSaUP8qgkL8HHY0kACAIgoOfSwACYQrAAAAAAAqf0H+oMys/8Lj + y/+GwJb/PY1T/0mWXf+azqj/o9Kw/5bLpP9qtn//Op5V/y+ZTP8ynE//NZ1R/zOYT/8xkUv/MI9J/zCR + Sv8ylk3/NJ1Q/zOcT/81nFH/PJ9X/zueVf81nFH/NJxQ/zOYTv8ieTr0E3EsagCcIgMLhCwAG3k1ACp+ + Qf2WxqT/vN/G/7Xbv/+g0Kz/m86p/6LSr/+Wy6T/W69y/zGaTf8ym07/NZ5R/zGTS/8pfkD8JHc77Bty + M8wSayu0F28vxiF1OOkpf0H9MZNM/zWdUf80nFD/NZxR/zSbUP80m1D/NZ1R/zCSS/8hdDjiGnUzSSM3 + KgAZfzQAK3xB/JPDof+027//qdS0/6XSsf+g0K3/lsqk/1isb/8wmUz/M5xP/zSbUP8tiEb/H3E25BZu + LYUTdi4zCnAnEwBuFQ0AbB0REnQtMxluMIkgbzbnLIlF/zSdUf80nFD/NJtQ/zSbUP81nlH/M5lP/yZ4 + PP8bbjGvFIExDRh4MgAsekH8kMKe/67Zuv+j0bD/nc6r/5vNqP9ms3v/MJlN/zObT/80m1D/K4BB/yNr + NvcbdjR3AJgkCBVxLgAQcysAAm0gAAttJgAXbzAAAJQqAw5rJ1QYaC3WK4VE/zWeUf81nlH/NZxR/y6K + R/8fcDX1FWksqRJwKz0MgioEEHgsACx4QfyMv5r/qNa1/53Pq/+bzqn/eLyK/zSbUP8ymk//NJtQ/zSc + Uf8ylk3/Kn5B/htpMN4TZiqBD3UrJQDBGwAAiiQAAHQKAA91LAAJfCgARh9CAAhpI0cZZy7jMI5K/zGT + TP8ldjv+HGYwyxJrKWEAdyENHGUxABF4LAAlfT0ALHZA+4i8lv+i06//ms6o/4fEl/9AoVr/MZlN/zSb + UP80m1D/NJtQ/zWdUf82oVP/L4tI/x5kMf8OYCSsA3UhIQR0IwAAdAoAAAAAAAZ2IwAKdCYAALMYAhRm + K3IfZzL2IGg06RZlK4sOciklLTwyAAVtIAAadTMACGwgEyV+PVcsdD/6hLqS/53Qq/+RyaD/Tqhn/y+Z + TP80m1D/NJtQ/zSbUP81nlH/NJtQ/yyERP8gajPxGWMtpwxrJjwBdSAGBHMjAAB0CgAAAAAAAAAAABVh + KQAQcyoADXwrDgxiI3ATaypFE5Q3BRNqKgAIbyIAAGAJBw9xKUYfeDe0Jnw97SxxP/qAt4//m8+p/2y3 + gP8wmk3/M5tP/zSbUP81nVH/NZ5R/y+MSf8gazX6FFwoxBBiJlcNfywOEGYnAAN1IQAEcyMAAHQKAAAA + AAAAAAAAAYkmABtjLgATbiwAGlYtABpgLgAKcCUAAFgAAQBnFykNbieSRItY6EqSXv8meT35K289+X21 + jf+LyJz/QqJc/zGZTf80nFH/NZ9S/zGSTP8kcTn/Glws2BRfKXQIbyQZITknAA96LAAWcy8AAYkmAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAGERAABaBgALcSUAD3ApAABpGxgNbydvKX0/1m+lfv+izK7/P5lY/yV1 + O/krbT74e7SL/2i2ff8xmk3/NZ5S/zOZTv8nej7/GV0s7BFYJZQRaikwAP+hAA5lJQAHgCgADG4mAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9zKgAHcSIAFngyAAFrGQkDah1NEnEsuEyRX/mYwqP/weDJ/3W+ + iP8rjkb/JXE6+i1uP/durYD/QKVc/zKcT/8shET/HmMx9g5VIrAJXyFFBJMqBxRjKgAQmjUAE34wAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtvJgAFaRwADXApAACCEgEPcSg0EXErmjKCSO96roj/tdi+/7ne + w/+bzqj/P6JZ/y2OR/8kbTj6MHBC9kudYf8vj0n/IWo1/RZZKM0TXihjCnwqEhBaJAAMbiYAALwrAAGL + JwAAAAAAAAAAAAAAAAAAAAAAAAAAAABXDAAUfTMADnMoACiBRQAEbCEbEHAqdyJ5Otpam2z/pMyu/7nd + w/+t17n/qNS0/2Kxd/8vm0z/MI9K/yNpNvsmaDf2Imk1/xRZJ94OWSGCDGslHioAAAAOeywAH5I/ACuW + SwAZiTcAMpZNAAmBKQAAAAAAAAAAAAAAAAAAYxEAAGEOABR2LgALciYNEXEpVxRyLsQ9iVL7iryX/7fb + wv+y2r3/pdOx/6HRrv+Fw5b/NZtR/zOdUP8wjkn/IWMz+x5kMeMOViKiBmIfNwCzIAMMZyQAHpA9AACB + GwMVjDU6GI04cQ+GLhUYiDYAap9+AAAAAAAAAAAAAAAAAABjEQAAXwoFD3IpOR55N6QtgUTwbKl9/6vT + tv+13MD/qdW1/6HQrv+azaj/ksqh/06oZ/8wmUz/NZ5R/y+NSP8gXzH8KIFAPgx/KgsKVyAADoswACaU + RQAXjTcdGY04fiSRQeEwlUv5HYk7ghOEMwUXgTQAEXYtAACGJAAAAAAAAGIRAABhDhoUciygI3g6/Wqm + ev+33MH/stu+/6LRr/+bzan/lMqj/5HIoP9rtn//MppO/zObT/81nlH/L4xI/x5bL/whbjYABmwgAByQ + OwAEhScJG487UiKRQL9CoFz8o9Cv/5bIo/8likHrFH0wWP///wARdCwAHHg1AAAAAAAALAAAJKZaAA9u + KB4TbCt3HW802E2OX/2FuJP/mMyn/5DIn/+JxZr/fr+Q/z+gWf8xmk7/NJtQ/zWeUf8vi0j/HVgt/QCB + IQAAbgACFIszMyWTQ5kok0bwcreE/+Hw5f/6/Pv/7/fx/3OzhP8ZfDTfGHkyYA5yKAYVbiwACGIfAABc + FgAMYSEAEWopAABRAAUSZSlqGGQt8jp8TP+Cu5L/hMOV/37Akf9Vq23/MJpN/zSbUP80m1D/NZ5R/y+L + SP8dVy39B4InAAB0DQgcjTuXMZZM/y+YTP+KxZr/9fr2/+n07P/k8ef/1Ora/3Cwgf8kfjztEW8rkwxq + JDoFYRsSAFsQDgtjIRIJXx8zCVsfgRtkL99LjFz/e7mM/4HCk/96vYz/Y7J5/zacUv8zm0//NJxQ/zSb + UP81nlH/L4tI/x1YLf4KgyoAR5lgAB+LPTwrjkbaL5RL/zKbT/+czqn/4O/j/9br2//Q6Nf/yOXQ/4m+ + l/9Cjlj+HXEz7ApgIcsHXB24Dl8kyyJrNes4e0r8YqFz/4PDlP98v47/dLqG/2aze/87n1f/MpxP/zSb + T/80m0//NZ5R/zWeUv8vi0j/HVgt/gqDKgABeSIAAFsAARmANWQnh0HzLpVK/zScUP+Gw5b/yeTQ/8bj + zf+73sT/ut7E/6fTs/+Eu5P/cayB/2Cgcf9mpHj/crGD/4C+kP+AwpL/dbuI/2+4gv9hsXf/QKFa/zKc + T/80m1D/JnM7/yJnNf8vi0j/NqFT/y+OSf8dWC3+AAAAAAZ6JwAOeSsAAG4aCh59OI4rhUT5L5RK/y+a + Tf9brnL/nM6q/7LZvP+q1bX/otGv/57Qq/+Yzab/jsme/4jGmf+BwpL/d7yJ/2+4g/9ptX7/Wa1w/zuf + Vv8znE//NJtQ/yVxOv8YUSjZGFAnrhZSJuskcTn/K4FD/x1ZLv4AAAAAAAAAAP///wAdfzkAGnkzFBt1 + NI8jejr3L5BJ/y6aTP86n1b/XrB0/4fEmP+TyqL/jsie/4nEmf+BwZL/eb2M/3K5hv9rtX7/Xq90/0ak + X/82nFL/M55Q/zKXTv8jbjf/FVAl2Q1NHkYAUw8KBEYTTwtHGbgVUyb4HFYs/wAAAAAAAAAAAF0OACSB + PwAWdC8AAGIWDA1oJn4ecDXvLIVE/zCWTP8wnE3/M5xQ/0ChW/9Uq2z/XrB0/16wdP9arnH/Tqdm/0Gh + Wv82nVH/M51P/zSeUf8th0b/G14t/gpGGcEFRxY/ED8wAAFPEQAOTTEAAEIGEglKGGoZVinHAAAAAAAA + AAAAAAAAAIckABNoKwAFZB4AAFsQCg9iJFkXYyvIIW42+y2HRv8ymE7/M5xP/zGcTv8wnE7/MJxN/zGc + Tv8ynU//M51P/zScUP8tiEX/Ims1/xlVKesNSh2MAEIKIQxKGwAJURkABkgOAABDAAABRA4AN3NvACBi + MSEAAAAAAAAAAAAAAAAAAAAAAAAAAABfFwAAXhYAN4JfAAJXFh0TWSZ4GVwrzxxfLvYkbzn/Kn9C/y2G + Rf8uiUb/LolH/yqAQv8mczv/HV4v/hFOId8GQxWiBUgTSQlWGQUGRBMAGDooAAAAAAAAAAAAAAAAAAA/ + AAAAOAAAH2ExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhcHAACWBEACloeAAAzAAEATxIsDlIgWx1Z + LaAcVSzaG1Mr7BxVK/UcViz2G1Qr3RxVLLUTTyR/AUcSPQA+AAgMShYADFAcAAAeAAAATA0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/AAAPxwAAB8AAAAHAAAAAwAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAA + AAAAACAAAAAwAAAAMAAAAPgAAAPwAAAPwAAAHwAAAA4AAAAOAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAA + AACAAAAAwAAAAMAAAADgAAAA+AAAOPwAAD8= + + + \ No newline at end of file diff --git a/PCRobot/WinForm.Designer.cs b/PCRobot/WinForm.Designer.cs new file mode 100644 index 0000000..d82320b --- /dev/null +++ b/PCRobot/WinForm.Designer.cs @@ -0,0 +1,383 @@ +namespace PCRobot +{ + partial class WinForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WinForm)); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.label5 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.button4 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除微信ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.button1 = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.status = new System.Windows.Forms.Label(); + this.易转发 = new System.Windows.Forms.NotifyIcon(this.components); + this.ClearCache_Timer = new System.Windows.Forms.Timer(this.components); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.contextMenuStrip1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(572, 394); + this.tabControl1.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + this.tabControl1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.label5); + this.tabPage1.Controls.Add(this.comboBox1); + this.tabPage1.Controls.Add(this.button4); + this.tabPage1.Controls.Add(this.button3); + this.tabPage1.Controls.Add(this.button2); + this.tabPage1.Controls.Add(this.listView1); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(564, 368); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "微信客户端"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(355, 19); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(65, 12); + this.label5.TabIndex = 5; + this.label5.Text = "微信版本:"; + this.label5.Visible = false; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "2.7.1.88", + "2.8.0.112", + "2.7.1.82"}); + this.comboBox1.Location = new System.Drawing.Point(426, 16); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(118, 20); + this.comboBox1.TabIndex = 4; + this.comboBox1.Visible = false; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // button4 + // + this.button4.Location = new System.Drawing.Point(226, 12); + this.button4.Name = "button4"; + this.button4.Size = new System.Drawing.Size(104, 27); + this.button4.TabIndex = 3; + this.button4.Text = "检查更新"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click_1); + // + // button3 + // + this.button3.Location = new System.Drawing.Point(111, 12); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(104, 27); + this.button3.TabIndex = 2; + this.button3.Text = "全部退出登陆"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(8, 12); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(92, 27); + this.button2.TabIndex = 1; + this.button2.Text = "登陆微信"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // listView1 + // + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3, + this.columnHeader4}); + this.listView1.ContextMenuStrip = this.contextMenuStrip1; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HideSelection = false; + this.listView1.Location = new System.Drawing.Point(3, 53); + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(558, 311); + this.listView1.TabIndex = 0; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "序号"; + this.columnHeader1.Width = 0; + // + // columnHeader2 + // + this.columnHeader2.Text = "微信ID"; + this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader2.Width = 170; + // + // columnHeader3 + // + this.columnHeader3.Text = "微信昵称"; + this.columnHeader3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader3.Width = 182; + // + // columnHeader4 + // + this.columnHeader4.Text = "手机号码"; + this.columnHeader4.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader4.Width = 190; + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除微信ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 26); + // + // 删除微信ToolStripMenuItem + // + this.删除微信ToolStripMenuItem.Name = "删除微信ToolStripMenuItem"; + this.删除微信ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.删除微信ToolStripMenuItem.Text = "删除微信"; + this.删除微信ToolStripMenuItem.Click += new System.EventHandler(this.删除微信ToolStripMenuItem_Click); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.button1); + this.tabPage2.Controls.Add(this.groupBox1); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(564, 368); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "设置"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(124, 286); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(306, 33); + this.button1.TabIndex = 6; + this.button1.Text = "连接服务器"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.textBox3); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(83, 47); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(407, 219); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "通信設置"; + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(80, 143); + this.textBox3.Name = "textBox3"; + this.textBox3.PasswordChar = '*'; + this.textBox3.Size = new System.Drawing.Size(249, 21); + this.textBox3.TabIndex = 5; + this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(80, 94); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(249, 21); + this.textBox2.TabIndex = 4; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(80, 44); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(249, 21); + this.textBox1.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(33, 146); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(41, 12); + this.label3.TabIndex = 2; + this.label3.Text = "秘钥:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(33, 97); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(41, 12); + this.label2.TabIndex = 1; + this.label2.Text = "端口:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(45, 50); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(29, 12); + this.label1.TabIndex = 0; + this.label1.Text = "IP:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Font = new System.Drawing.Font("宋体", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label4.Location = new System.Drawing.Point(5, 397); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(52, 14); + this.label4.TabIndex = 1; + this.label4.Text = "状态:"; + // + // status + // + this.status.Location = new System.Drawing.Point(63, 394); + this.status.Name = "status"; + this.status.Size = new System.Drawing.Size(509, 21); + this.status.TabIndex = 2; + this.status.Text = "准备就绪"; + this.status.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // 易转发 + // + this.易转发.Icon = ((System.Drawing.Icon)(resources.GetObject("易转发.Icon"))); + this.易转发.Text = "易转发 - 双击我显示窗口"; + this.易转发.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.易转发_MouseDoubleClick); + // + // ClearCache_Timer + // + this.ClearCache_Timer.Enabled = true; + this.ClearCache_Timer.Interval = 7200000; + this.ClearCache_Timer.Tick += new System.EventHandler(this.ClearCache_Timer_Tick); + // + // WinForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(572, 418); + this.Controls.Add(this.status); + this.Controls.Add(this.label4); + this.Controls.Add(this.tabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.Name = "WinForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "易转发 - 消息中转客户端"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.WinForm_FormClosing); + this.Load += new System.EventHandler(this.WinForm_Load); + this.SizeChanged += new System.EventHandler(this.WinForm_SizeChanged); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage1.PerformLayout(); + this.contextMenuStrip1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label status; + private System.Windows.Forms.NotifyIcon 易转发; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除微信ToolStripMenuItem; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.Timer ClearCache_Timer; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.ComboBox comboBox1; + } +} \ No newline at end of file diff --git a/PCRobot/WinForm.cs b/PCRobot/WinForm.cs new file mode 100644 index 0000000..3dcdd52 --- /dev/null +++ b/PCRobot/WinForm.cs @@ -0,0 +1,2116 @@ +using CsharpHttpHelper; +using HPSocketCS; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PCRobot.Pack; +using PCRobot.PCWechat; +using PCRobot.Utils; +using PCRobot.WechatApi; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Caching; +using System.Windows.Forms; +using System.Xml; +using static PCRobot.PCWechat.Wechat_Xiaoxie; +using static PCRobot.WechatApi.NMHelper; + +namespace PCRobot +{ + public partial class WinForm : Form + { + public WinForm() + { + InitializeComponent(); + + + } + + private void WinForm_FormClosing(object sender, FormClosingEventArgs e) + { + var msg = MessageBox.Show("您确定要退出软件吗?\r\n退出后,已登陆的微信将会被强制关闭!", "谨慎操作", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (msg != DialogResult.Yes) e.Cancel = true; + else PCWechat.WechatClient.UnInstall(); + } + + private void PCForm_FormClosing(object sender, FormClosingEventArgs e) + { + if (!e.Cancel && socketClient != null && socketClient.IsConnected) + { + socketClient.Close(true); + } + } + + private void WinForm_SizeChanged(object sender, EventArgs e) + { + //判断是否选择的是最小化按钮 + if (WindowState == FormWindowState.Minimized) + { + //托盘显示图标等于托盘图标对象 + //注意notifyIcon1是控件的名字而不是对象的名字 + this.易转发.Visible = true; + + //隐藏任务栏区图标 + this.ShowInTaskbar = false; + } + else this.易转发.Visible = false; + } + + private void 易转发_MouseDoubleClick(object sender, MouseEventArgs e) + { + this.Visible = true; + this.WindowState = FormWindowState.Normal; + this.ShowInTaskbar = true; + } + + public static SocketClient socketClient = null; + + + private void button2_Click(object sender, EventArgs e) + { + try + { + if (!socketClient.IsConnected) + { + this.tabControl1.SelectedIndex = 1; + MessageBox.Show("请先连接机器人服务器!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + StartWechat(); + //NmClient nmClient = new NmClient(); + //nmClient.IniWechat(socketClient,lgCall); + //nmClient.StartWechat(); + //nmCore = nmClient.nmCore;WxRecvCallback + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "启动失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + //if (ex.Message == "微信版本") + //{ + // if (DialogResult.OK == MessageBox.Show($@"您的微信版本不兼容,以后请不要自己买升级微信!!!\r\n 点击确定按钮后,我们将为您还原指定的微信版本!", "微信版本异常", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning)) + // { + // new WechatUpdate(comboBox1.SelectedItem.ToString()).ShowDialog(); + + // } + //} + } + } + + #region 分析消息 + + private static readonly object SequenceLock = new object(); + static HPSocketCS.TcpPackServer HP_Server = new HPSocketCS.TcpPackServer(); + NMHelper nmHeler = new NMHelper(); + public NMCore nmCore { get; set; } + public string NewLine; + + public bool isReady { get; set; } = false; + + nmWxidInfo curWx; + + + + public void IniWechat() + { + if (!isReady) + { + try + { + PCWechat.Wechat_Xiaoxie.Install(); + NewLine = Environment.NewLine; + HP_Server.OnAccept += new ServerEvent.OnAcceptEventHandler(OnAccept); + HP_Server.OnReceive += new ServerEvent.OnReceiveEventHandler(OnReceive); + HP_Server.OnClose += new ServerEvent.OnCloseEventHandler(OnClose); + HP_Server.MaxPackSize = 0x3FFFFF; + HP_Server.IpAddress = "127.0.0.1"; + HP_Server.Port = 0; + if (HP_Server.Start() == true) + { + isReady = true; + + nmCore = new NMCore(HP_Server); + string szIPAddress = string.Empty; + ushort dwPort = 0; + HP_Server.GetListenAddress(ref szIPAddress, ref dwPort); + if (dwPort == 0) + { + //MessageBox.Show("通信端口创建失败,请重试!", "错误"); + //Environment.Exit(0); + } + nmHeler.Socket_Port = dwPort; + WriteLog("[初始化]" + NewLine + "绑定地址:" + szIPAddress + NewLine + "通信端口:" + nmHeler.Socket_Port.ToString()); + } + else + { + //MessageBox.Show("创建通信服务失败,请重试!", "错误"); + //Environment.Exit(0); + } + //byte[] bytPath = new byte[260]; + //if (NMHelper.NM_GetWeChatPath(bytPath, 260) == true) + //{ + // string Path = System.Text.Encoding.GetEncoding("GB2312").GetString(bytPath, 0, bytPath.Length); + // text_WeChatPath.Text = Path; + //} + + NMHelper.NM_LinkWeChat(201912121, nmHeler.Socket_Port, 0, 0); + } + catch (Exception) + { + + } + } + } + + HandleResult OnAccept(IServer sender, IntPtr connId, IntPtr pClient) + { + try + { + nmCore.NM_Init((int)connId, "C#-275569550"); + } + catch (Exception ex) + { } + return HandleResult.Ok; + } + + HandleResult OnReceive(IServer sender, IntPtr connId, byte[] bytes) + { + try + { + string s_Recv = Encoding.Default.GetString(bytes); + JObject RecvJson = JObject.Parse(s_Recv); + int RecvType; + if (nmHeler.Json_GetInt(RecvJson, "PackType", out RecvType) == true) + { + if (RecvType == NMHelper.Recv_QRCode)//二维码 + { + Event_QRCode(RecvJson); + } + else if (RecvType == NMHelper.Recv_Login)//登录 + { + Event_Login((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_Logout) + { + Event_Logout((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_Msg)//消息 + { + Event_RecvMsg((int)connId, RecvJson); + } + else if (RecvType == NMHelper.Recv_SelectTalker)//切换聊天对象 + { + Event_SelectTalker((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetContactList)//获取好友列表列表 + { + Event_RecvContactList((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetGroupMember)//获取群信息 + { + Event_RecvGroupMember((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetWxidInfo)//获取群或好友详细信息 + { + Event_RecvWxidInfo((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_AddFriend) + { + Event_AddFriend((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_CreateGroup) + { + Event_CreateGroup((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetFavList) + { + Event_GetFavList((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_GetA8Key) + { + Event_GetA8Key((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_InvitePull) + { + Event_GroupInvite((int)connId, RecvJson); + } + else if (RecvType == NMHelper.NM_QuitGroup) + { + Event_GroupQuit((int)connId, RecvJson); + } + } + } + catch (Exception ex) + { + } + return HandleResult.Ok; + } + + HandleResult OnClose(IServer sender, IntPtr connId, SocketOperation enOperation, int errorCode) + { + try + { + Event_Logout((int)connId, new JObject()); + } + catch (Exception) + { + } + return HandleResult.Ok; + } + + /// + /// 通信事件_接收登录二维码 + /// + /// + void Event_QRCode(JObject RecvJson) + { + try + { + int dwPid = 0; + nmHeler.Json_GetInt(RecvJson, "ProcessId", out dwPid); + string B64_QRCode = nmHeler.Json_GetString(RecvJson, "QRCode", false); + if (B64_QRCode != string.Empty) + { + byte[] imageBytes = Convert.FromBase64String(B64_QRCode); + MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length); + ms.Write(imageBytes, 0, imageBytes.Length); + //pictureBox1.Image = System.Drawing.Image.FromStream(ms, true); + WriteLog("[二维码]" + NewLine + "接收来自进程(PID:" + dwPid.ToString() + ")的登录二维码"); + } + } + catch (Exception) + { + } + } + + /// + /// 通信事件_登录成功 + /// + /// + /// + void Event_Login(int ConnID, JObject RecvJson) + { + try + { + lock (SequenceLock) + { + DwPid = (IntPtr)nmHeler.Json_GetIntEx(RecvJson, "ProcessId"); + + NMHelper.nmWxidInfo WxidInfo = new NMHelper.nmWxidInfo(); + WxidInfo.Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + WxidInfo.Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + WxidInfo.WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + WxidInfo.HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + WxidInfo.Sex = nmHeler.Json_GetIntEx(RecvJson, "Sex").ToString(); + WxidInfo.Phone = nmHeler.Json_GetString(RecvJson, "Phone", true); + WxidInfo.handle = (int)DwPid; + WxidInfo.socketHandle = ConnID; + curWx = WxidInfo; + lgCall(curWx); + + GetUsers(ConnID); + } + } + catch (Exception ex) + { + + } + } + public void GetUsers(int ConnID) + { + nmCore.NM_GetContactList(ConnID); + } + + Dictionary> nmWxidInfos = new Dictionary>(); + /// + /// 通信事件_退出登录 + /// + /// + /// + void Event_Logout(int ConnID, JObject RecvJson, bool isAll = false) + { + try + { + var nm = nms.FirstOrDefault(p => p.socketHandle == ConnID); + if (nm.Wxid != null) + { + if (socketClient != null) + { + WechatStatus msg = new WechatStatus(); + msg.Cmd = PCRobotCMD.offline; + msg.RobotUsername = nm.Wxid; + msg.RobotUsernick = nm.Nick; + msg.RobotType = RobotType.客户端微信; + msg.Status = Status.退出; + socketClient.Send(msg); + } + + WriteLog("[微信退出]" + NewLine + "昵称:" + nm.Nick + NewLine + "Wxid:" + nm.Wxid); + if (!isAll) + { + nms.Remove(nm); + UpdateUi(); + } + } + //int dwRowIndex = nmHeler.FindRowIndex(list_Login, ConnID.ToString(), 0); + //if (dwRowIndex != -1) + //{ + // if (ConnID == nmHeler.Socket_ConnId) + // { + // nmHeler.Socket_ConnId = 0; + // groupBox1.Text = "登录列表"; + // } + // string szNick = list_Login.Items[dwRowIndex].SubItems[1].Text; + // string szWxid = list_Login.Items[dwRowIndex].SubItems[2].Text; + // list_Login.Items.RemoveAt(dwRowIndex); + // WriteLog("[微信退出]" + NewLine + "昵称:" + szNick + NewLine + "Wxid:" + szWxid); + //} + + } + catch (Exception ex) + { + } + } + + private List filtrationWX = new List() { "weixin" };//gh_43f2581f6fd6 + + //private static string[] not_delete = new string[] { "fmessage", "floatbottle", "qmessage", "medianote", "qqmail", "weixin" }; + + /// + /// 客户端请求 + /// + /// + public void Rcv(string str) + { + try + { + var bodyIndex = str.IndexOf(" "); + if (bodyIndex == -1) return; + var head = str.Substring(0, bodyIndex); + var cmd = (PCRobotCMD)Enum.Parse(typeof(PCRobotCMD), head); + var msg = str.Substring(bodyIndex).Trim().Replace("\r\n", "\n").Replace("[换行]", "\n"); + + var text = PackTool.DecompressString(msg); + + //str = CsharpHttpHelper.HttpHelper.URLDecode(msg).Replace("\0", "").Trim().Replace("\r\n", "\n"); + //if (!str.StartsWith("{")) + //{ + // AESCryption aes = new AESCryption(); + // str = aes.AesDecrypt(msg, socketClient.key); + //} + //var msgT = JObject.Parse(str); + //var msg = JsonConvert.DeserializeObject(str); + // var _data = HttpExtend.JsonToDictionary(str); + + var data = Util.JsonToObject(text) as ServerWechatMsg; + if (data == null || data.Key != socketClient.key) return; + + var wechatUser = WechatClient.Users.FirstOrDefault(f => f.Key == data.RobotUsername.ToString()).Value; + if (wechatUser != null) + { + //if (cmd.ToString().ToLower().StartsWith("send")) + //{ + // var mess = data.ToMessage; + // if (cmd == PCRobotCMD.sendTxt) + // mess = mess.Replace("\r\n", "\n"); + // Common.SetCache(curWx.Wxid, data.ToUsername, mess); + //} + + object obj = null; + switch (cmd) + { + case PCRobotCMD.sendTxt: + obj = new { type = MsgType.MT_SEND_TEXTMSG, data = new { to_wxid = data.ToUsername.ToString(), content = data.ToMessage } }; + break; + case PCRobotCMD.sendFile: + case PCRobotCMD.sendImg: + obj = new { type = PCRobotCMD.sendImg == cmd ? MsgType.MT_SEND_IMGMSG : MsgType.MT_SEND_FILEMSG, data = new { to_wxid = data.ToUsername.ToString(), file = data.ToMessage } }; + break; + case PCRobotCMD.agreeFriend: + { + //data.ToMessage //TODO 这还没有获取v1 v2 scene 的值 + /* + "data" : { + "v1": "v1_xxxxxxxx@stranger", // v1 + "v2": "v2_xxxxxxxx@stranger", + "scene": 17 + }, + "type" : MT_ACCEPT_FRIEND_MSG + */ + var v1 = string.Empty; + var v2 = string.Empty; + var scene = string.Empty; + + obj = new { type = MsgType.MT_ACCEPT_FRIEND_MSG, data = new { v1 = v1, v2 = v2, scene = scene } }; + } + break; + case PCRobotCMD.sendCard: + obj = new { type = MsgType.MT_SEND_CARDMSG, data = new { to_wxid = data.ToUsername, card_wxid = data.ToMessage } }; + break; + case PCRobotCMD.getContact: + obj = new { type = MsgType.MT_DATA_FRIENDS_MSG, data = new { } }; + Thread.Sleep(330); + obj = new { type = MsgType.MT_DATA_CHATROOMS_MSG, data = new { } }; + break; + case PCRobotCMD.getGroupMember: + obj = new { type = MsgType.MT_DATA_CHATROOM_MEMBERS_MSG, data = new { room_wxid = data.ToMessage } }; + break; + case PCRobotCMD.getPay: + { + //var Invalidtime = 0; + var Transferid = string.Empty; + var dic = HttpExtend.JsonToDictionary(data.ToMessage); + //if (dic.ContainsKey("Invalidtime")) + // Invalidtime = int.Parse(dic["Invalidtime"].ToString()); + if (dic.ContainsKey("Transferid")) + Transferid = dic["Transferid"].ToString(); + + obj = new { type = MsgType.MT_ACCEPT_WCPAY_MSG, data = new { transferid = Transferid } }; + } + break; + case PCRobotCMD.deleteFriend: + obj = new { type = MsgType.MT_DEL_FRIEND_MSG, data = new { wxid = data.ToMessage } }; + break; + case PCRobotCMD.sendInviteGroup: + obj = new { type = MsgType.MT_SEND_CARDMSG, data = new { to_wxid = data.ToUsername, card_wxid = data.ToMessage } }; + break; + case PCRobotCMD.editContacts: + obj = new { type = MsgType.MT_MOD_FRIEND_REMARK_MSG, data = new { wxid = data.ToUsername, remark = data.ToMessage } }; + break; + case PCRobotCMD.stateOpt: + obj = new { type = MsgType.MT_MOD_CHAT_SESSION_TOP_MSG, data = new { wxid = data.ToUsername, status = int.Parse(data.ToMessage) } }; + break; + case PCRobotCMD.getWxidInfo: + obj = new { type = MsgType.MT_UPDATE_WXID_MSG, data = new { wxid = data.ToMessage } }; + break; + } + //if (obj != null) + // WechatClient.GetApi(wechatUser).SendMessage(wechatUser.Wxid.ToString(), obj); + } + else + { + var curWx = nms.FirstOrDefault(p => p.Wxid == data.RobotUsername.ToString()); + if (string.IsNullOrEmpty(curWx.Wxid)) + return; + + if (cmd.ToString().ToLower().StartsWith("send")) + { + var mess = data.ToMessage; + if (cmd == PCRobotCMD.sendTxt) + mess = mess.Replace("\r\n", "\n"); + Common.SetCache(curWx.Wxid, data.ToUsername, mess); + } + + switch (cmd) + { + case PCRobotCMD.sendTxt: + var dataMsg = data.ToMessage.Replace("\r\n", "\n"); + if (isXML(dataMsg)) + { + nmCore.NM_SendURLMsg(curWx.socketHandle, data.ToUsername.ToString(), dataMsg.Replace("&", "&")); + } + else + { + nmCore.NM_SendTextMsg(curWx.socketHandle, data.ToUsername.ToString(), new string[] { "" }, dataMsg); + } + break; + case PCRobotCMD.sendFile: + //文件接口 + //WechatAPI.Wx_SendFileMsg(WechatAPI.Client_Handle, 3, msg.FromUsername, msg.FromMessage); + + //Util.Base64ToFileAndSave(data.ToMessage,) + + + nmCore.NM_SendFileMsg(curWx.socketHandle, NMHelper.NM_SendFile, data.ToUsername.ToString(), data.ToMessage); + + break; + case PCRobotCMD.sendImg: + //byte[] ImageByte = Convert.FromBase64String(msg.FromMessage); + //string temp = System.Environment.GetEnvironmentVariable("TEMP"); + ////DirectoryInfo info = new DirectoryInfo(temp); + //string uFile = temp + "//" + Guid.NewGuid().ToString() + ".png"; + //File.WriteAllBytes(uFile, ImageByte); + ////图片接口 + //WechatAPI.Wx_SendFileMsg(WechatAPI.Client_Handle, 3, msg.FromUsername, uFile); + + nmCore.NM_SendFileMsg(curWx.socketHandle, NMHelper.NM_SendPic, data.ToUsername, data.ToMessage); + + break; + case PCRobotCMD.sendCard: + if (data.ToMessage.Contains("@")) + nmCore.NM_InviteToGroup(curWx.socketHandle, NMHelper.NM_InviteURL, data.ToMessage, new string[] { data.ToUsername }); + else + nmCore.NM_SendCardMsg(curWx.socketHandle, data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.sendInviteGroup: + nmCore.NM_InviteToGroup(curWx.socketHandle, NMHelper.NM_InviteURL, data.ToMessage, new string[] { data.ToUsername }); + break; + case PCRobotCMD.getContact: + nmCore.NM_GetContactList(curWx.socketHandle); + break; + case PCRobotCMD.getPay: + { + var Invalidtime = 0; + var Transferid = string.Empty; + var dic = HttpExtend.JsonToDictionary(data.ToMessage); + if (dic.ContainsKey("Invalidtime")) + Invalidtime = int.Parse(dic["Invalidtime"].ToString()); + if (dic.ContainsKey("Transferid")) + Transferid = dic["Transferid"].ToString(); + + nmCore.NM_GetMoney(curWx.socketHandle, data.ToUsername, Transferid, Invalidtime); + } + break; + case PCRobotCMD.agreeFriend: + nmCore.NM_PassApply(curWx.socketHandle, data.ToMessage); + break; + case PCRobotCMD.deleteFriend: + nmCore.NM_DelFriend(curWx.socketHandle, data.ToMessage); + break; + case PCRobotCMD.getGroupMember: + nmCore.NM_GetGroupMember(curWx.socketHandle, data.ToMessage); + break; + case PCRobotCMD.getWxidInfo: + nmCore.NM_GetWxidInfo(curWx.socketHandle, string.Empty, data.ToMessage); + break; + case PCRobotCMD.editContacts: + nmCore.NM_SetFriendMark(curWx.socketHandle, data.ToUsername, data.ToMessage); + break; + case PCRobotCMD.stateOpt: + nmCore.NM_StateOpt(curWx.socketHandle, 2, data.ToUsername, data.ToMessage == "1"); + break; + //case PCRobotCMD.heartBreak: + + // break;` + } + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + + /// + /// 通信事件_接收消息 + /// + /// + /// + void Event_RecvMsg(int ConnID, JObject RecvJson) + { + try + { + NMHelper.nmMsgInfo MsgInfo = new NMHelper.nmMsgInfo(); + MsgInfo.RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + MsgInfo.Type = nmHeler.Json_GetIntEx(RecvJson, "Type"); + MsgInfo.State = nmHeler.Json_GetIntEx(RecvJson, "State"); + MsgInfo.Time = nmHeler.Json_GetIntEx(RecvJson, "Time"); + MsgInfo.IsSend = nmHeler.Json_GetIntEx(RecvJson, "Sender"); + MsgInfo.LocalMsgID = nmHeler.Json_GetIntEx(RecvJson, "LocalID"); + MsgInfo.ServerMsgID = nmHeler.Json_GetString(RecvJson, "ServerID", false); + MsgInfo.Wxid_1 = nmHeler.Json_GetString(RecvJson, "Wxid_1", true); + MsgInfo.Nick_1 = nmHeler.Json_GetString(RecvJson, "Nick_1", true); + MsgInfo.Wxid_2 = nmHeler.Json_GetString(RecvJson, "Wxid_2", true); + MsgInfo.Nick_2 = nmHeler.Json_GetString(RecvJson, "Nick_2", true); + MsgInfo.Msg = nmHeler.Json_GetString(RecvJson, "Msg", true); + MsgInfo.Source = nmHeler.Json_GetString(RecvJson, "Source", true); + + if (filtrationWX.Contains(MsgInfo.Wxid_1)) return; + + + string outLog = (MsgInfo.IsSend > 0 ? "[发出消息]" : "[接收消息]") + MsgInfo.RecvWxid + NewLine; + outLog += "类型:" + MsgInfo.Type.ToString() + " 状态:" + MsgInfo.State.ToString() + " 时间:" + nmHeler.Timestamp2DataTime(MsgInfo.Time) + NewLine; + outLog += "本地ID:" + MsgInfo.LocalMsgID.ToString() + " 服务器ID:" + MsgInfo.ServerMsgID + NewLine; + outLog += "Wxid1:" + MsgInfo.Wxid_1 + (MsgInfo.Nick_1 == String.Empty ? string.Empty : "(" + MsgInfo.Nick_1 + ")") + NewLine; + outLog += "Wxid2:" + MsgInfo.Wxid_2 + (MsgInfo.Nick_2 == String.Empty ? string.Empty : "(" + MsgInfo.Nick_2 + ")") + NewLine; + outLog += "消息内容:" + MsgInfo.Msg + NewLine + "附加消息:" + MsgInfo.Source + NewLine; + + if ((MsgInfo.Type == 43 || MsgInfo.Type == 49) && MsgInfo.IsSend == 0)//视频、文件 + { + string FilePath = nmHeler.Json_GetString(RecvJson, "File", true); + if (FilePath != string.Empty) + { + outLog += "文件路径:" + FilePath; + + if (socketClient != null) + { + if (File.Exists(FilePath)) + { + WechatReceiveMsg msg = new WechatReceiveMsg(); + + msg.IsSend = MsgInfo.IsSend == 1 ? true : false; + msg.RobotUsername = MsgInfo.RecvWxid; + msg.RobotUsernick = GetRobotNick(MsgInfo.RecvWxid); + msg.RobotType = RobotType.客户端微信; + + msg.Cmd = PCRobotCMD.rcvFile; + + if (MsgInfo.Type == 43)//视频 + { + msg.FromMessage = $"[视频={FilePath}]"; + msg.FromMessageType = WechatMsgType.视频; + msg.FileCDNXML = MsgInfo.Msg; + } + else if (MsgInfo.Type == 49)//文件 + { + msg.FromMessage = $"[文件={FilePath}]"; + msg.FromMessageType = WechatMsgType.文件; + } + + if (MsgInfo.Wxid_1.Contains("@chatroom")) + { + msg.FromGroupid = MsgInfo.Wxid_1; + + msg.FromUsername = MsgInfo.Wxid_2; + msg.FromUsernick = MsgInfo.Nick_2; + } + else if (MsgInfo.Wxid_2.Contains("@chatroom")) + { + msg.FromGroupid = MsgInfo.Wxid_2; + + msg.FromUsername = MsgInfo.Wxid_1; + msg.FromUsernick = MsgInfo.Nick_1; + } + else + { + msg.FromUsername = MsgInfo.Wxid_1; + msg.FromUsernick = MsgInfo.Nick_1; + } + if (string.IsNullOrEmpty(msg.FromUsernick) || string.IsNullOrEmpty(msg.RobotUsernick)) + { + var t = nms.FirstOrDefault(p => p.Wxid == MsgInfo.RecvWxid); + if (t.Wxid != null) + { + msg.RobotUsernick = t.Nick; + var m = nmWxidInfos[t.socketHandle]; + if (m != null) + { + var tar = m.FirstOrDefault(p => p.Wxid == MsgInfo.Wxid_1); + if (!string.IsNullOrEmpty(tar.Nick) && string.IsNullOrEmpty(msg.FromUsernick)) + { + msg.FromUsernick = tar.Nick; + } + } + } + } + socketClient.Send(msg); + } + } + } + } + else if ((MsgInfo.Type == 3 || MsgInfo.Type == 34) && MsgInfo.IsSend == 0)//图片、语音 + { + string FileData = nmHeler.Json_GetString(RecvJson, "File", false); + if (FileData != string.Empty) + { + byte[] FileBytes = Convert.FromBase64String(FileData); + string FilePath = nmHeler.SaveFile(MsgInfo.RecvWxid, MsgInfo.Wxid_1, (MsgInfo.Type == 3 ? "IMAGE" : "VOICE"), MsgInfo.ServerMsgID, (MsgInfo.Type == 3 ? "jpg" : "silk"), FileBytes); + outLog += "文件路径:" + FilePath; + + //if (MsgInfo.Type == 3 && chk_MaxPicture.Checked == true && MsgInfo.IsSend == 0) + //{ + // string MaxFilePath = FilePath.Replace(MsgInfo.ServerMsgID, MsgInfo.ServerMsgID + "_MAX"); + // nmCore.NM_GetImageByCDN(ConnID, MsgInfo.Msg, MaxFilePath); + //} + + if (socketClient != null) + { + if (File.Exists(FilePath)) + { + WechatReceiveMsg msg = new WechatReceiveMsg(); + + //msg.IsSend = MsgInfo.IsSend == 1 ? true : false; + msg.RobotUsername = MsgInfo.RecvWxid; + msg.RobotUsernick = GetRobotNick(MsgInfo.RecvWxid); + msg.RobotType = RobotType.客户端微信; + + if (MsgInfo.Type == 3)//图片 + { + msg.IsSend = MsgInfo.IsSend == 1 ? true : false; + msg.Cmd = PCRobotCMD.rcvImg; + msg.FromMessage = $"[图片={FilePath}]"; + msg.FromMessageType = WechatMsgType.图片; + msg.FileCDNXML = MsgInfo.Msg; + } + else if (MsgInfo.Type == 34)//语音 + { + msg.IsSend = false;//MsgInfo.IsSend == 1 ? true : false; + msg.Cmd = PCRobotCMD.rcvFile; + msg.FromMessage = $"[语音={FilePath}]"; + msg.FromMessageType = WechatMsgType.语音; + } + + if (MsgInfo.Wxid_1.Contains("@chatroom")) + { + msg.FromGroupid = MsgInfo.Wxid_1; + + msg.FromUsername = MsgInfo.Wxid_2; + msg.FromUsernick = MsgInfo.Nick_2; + } + else if (MsgInfo.Wxid_2.Contains("@chatroom")) + { + msg.FromGroupid = MsgInfo.Wxid_2; + + msg.FromUsername = MsgInfo.Wxid_1; + msg.FromUsernick = MsgInfo.Nick_1; + } + else + { + msg.FromUsername = MsgInfo.Wxid_1; + msg.FromUsernick = MsgInfo.Nick_1; + } + if (string.IsNullOrEmpty(msg.FromUsernick) || string.IsNullOrEmpty(msg.RobotUsernick)) + { + var t = nms.FirstOrDefault(p => p.Wxid == MsgInfo.RecvWxid); + if (t.Wxid != null) + { + msg.RobotUsernick = t.Nick; + var m = nmWxidInfos[t.socketHandle]; + if (m != null) + { + var tar = m.FirstOrDefault(p => p.Wxid == MsgInfo.Wxid_1); + if (!string.IsNullOrEmpty(tar.Nick) && string.IsNullOrEmpty(msg.FromUsernick)) + { + msg.FromUsernick = tar.Nick; + } + } + } + } + socketClient.Send(msg); + } + } + } + } + WriteLog(outLog); + + //申请好友 + if (MsgInfo.Type == 37) + { + //nmCore.NM_PassApply(ConnID, MsgInfo.Msg); + WechatApplyFriend wXApply = new WechatApplyFriend(); + wXApply.Cmd = PCRobotCMD.applyFriend; + wXApply.RobotUsername = MsgInfo.RecvWxid; + wXApply.RobotUsernick = GetRobotNick(MsgInfo.RecvWxid); + wXApply.RobotType = RobotType.客户端微信; + + var reg = Regex.Match(MsgInfo.Msg, @"content=""(?<申请文本>[^""]*?)"""); + if (reg.Success) + wXApply.Message = reg.Groups["申请文本"].Value; + + reg = Regex.Match(MsgInfo.Msg, @"sourceusername=""(?<账号>[^""]*?)"" sourcenickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + { + wXApply.OldFriendWxid = reg.Groups["账号"].Value; + wXApply.OldFriendNick = reg.Groups["昵称"].Value; + } + reg = Regex.Match(MsgInfo.Msg, @"fromusername=""(?<账号>[^""]*?)"""); + if (reg.Success) + { + if (!string.IsNullOrWhiteSpace(reg.Groups["账号"].Value)) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + else + { + reg = Regex.Match(MsgInfo.Msg, @"alias=""(?<账号>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendWxid = reg.Groups["账号"].Value; + } + } + reg = Regex.Match(MsgInfo.Msg, @"fromnickname=""(?<昵称>[^""]*?)"""); + if (reg.Success) + wXApply.NewFriendNick = reg.Groups["昵称"].Value; + + wXApply.Token = MsgInfo.Msg; + + socketClient.Send(wXApply); + } + + + if (MsgInfo.IsSend == 0 && MsgInfo.Type == 49) + { + #region 收到转账 + //if (MsgInfo.Msg.IndexOf("微信转账") != -1 && MsgInfo.Msg.IndexOf("收到转账") != -1) + //{ + // string State = nmHeler.StringMid(MsgInfo.Msg, "", ""); + // string Transid = nmHeler.StringMid(MsgInfo.Msg, "transferid>"); + // int dwTime = 0; + // int.TryParse(nmHeler.StringMid(MsgInfo.Msg, ""), out dwTime); + // if (State == "1" && Transid != string.Empty) + // { + // nmCore.NM_GetMoney(ConnID, MsgInfo.Wxid_1, Transid, dwTime); + // } + //} + + if (MsgInfo.Msg.IndexOf("微信转账") != -1 && MsgInfo.Msg.IndexOf("收到转账") != -1) + { + string State = nmHeler.StringMid(MsgInfo.Msg, "", ""); + string Transid = nmHeler.StringMid(MsgInfo.Msg, "transferid>"); + int dwTime = 0; + int.TryParse(nmHeler.StringMid(MsgInfo.Msg, ""), out dwTime); + if (State == "1" && Transid != string.Empty) + { + WechatReicevePay reicevePay = new WechatReicevePay(); + + reicevePay.RobotUsername = MsgInfo.RecvWxid; + reicevePay.RobotUsernick = GetRobotNick(MsgInfo.RecvWxid); + reicevePay.RobotType = RobotType.客户端微信; + + if (!string.IsNullOrWhiteSpace(MsgInfo.Wxid_1)) + { + reicevePay.FromUsername = MsgInfo.Wxid_1; + reicevePay.FromUsernick = MsgInfo.Nick_1; + } + reicevePay.Cmd = PCRobotCMD.receivePay; + reicevePay.Invalidtime = dwTime.ToString(); + reicevePay.Transferid = Transid; + var reg = Regex.Match(MsgInfo.Msg, "收到转账(?<金额>.+)元"); + if (reg.Success) + reicevePay.Money = double.Parse(reg.Groups["金额"].Value); + if (reicevePay.RobotUsernick == null) reicevePay.RobotUsernick = string.Empty; + socketClient.Send(reicevePay); + return; + } + } + #endregion + + //自动接受群聊邀请 + //if (MsgInfo.IsSend == 0 && MsgInfo.Type == 49) + //{ + //if (MsgInfo.Msg.IndexOf("邀请你加入群聊") != -1 && MsgInfo.Msg.IndexOf("mmsupport-bin/addchatroombyinvite") != -1) + //{ + // string InviteURL = nmHeler.StringMid(MsgInfo.Msg, ""); + // if (InviteURL != string.Empty) + // { + // nmCore.NM_GetA8Key(ConnID, MsgInfo.Wxid_1, InviteURL); + // } + //} + //} + } + + //文本消息、xml + if (MsgInfo.Type == 1 || MsgInfo.Type == 49) + { + //if (socketClient != null && MsgInfo.IsSend == 0) + if (socketClient != null) + { + var isSend = true; + if (MsgInfo.IsSend == 1)//判断是否为机器人自动回复的内容(这里似乎有个问题,图片、xml、无法正常判断是否为自动回复) + { + isSend = !Regex.IsMatch(MsgInfo.Msg.Trim(), @"<\?xml version=""1\.0""\?>([\w\W]+)
"); + if (isSend) + isSend = !Regex.IsMatch(MsgInfo.Msg.Trim(), @"([\w\W]*?[\w\W]+)"); + if (isSend) + isSend = WechatClient.IsAuxiliaryInput(MsgInfo.RecvWxid, MsgInfo.Wxid_1, MsgInfo.Msg); + } + + if (isSend) + { + WechatReceiveMsg msg = new WechatReceiveMsg(); + msg.Cmd = PCRobotCMD.rcvTxt; + msg.IsSend = MsgInfo.IsSend == 1 ? true : false; + msg.RobotUsername = MsgInfo.RecvWxid; + msg.RobotUsernick = GetRobotNick(MsgInfo.RecvWxid); + msg.RobotType = RobotType.客户端微信; + msg.FromMessageType = WechatMsgType.文本; + + + if (MsgInfo.Wxid_1.Contains("@chatroom")) + { + msg.FromGroupid = MsgInfo.Wxid_1; + + msg.FromUsername = MsgInfo.Wxid_2; + msg.FromUsernick = MsgInfo.Nick_2; + + } + else if (MsgInfo.Wxid_2.Contains("@chatroom")) + { + msg.FromGroupid = MsgInfo.Wxid_2; + + msg.FromUsername = MsgInfo.Wxid_1; + msg.FromUsernick = MsgInfo.Nick_1; + } + else + { + msg.FromUsername = MsgInfo.Wxid_1; + msg.FromUsernick = MsgInfo.Nick_1; + } + if (string.IsNullOrEmpty(msg.FromUsernick) || string.IsNullOrEmpty(msg.RobotUsernick)) + { + var t = nms.FirstOrDefault(p => p.Wxid == MsgInfo.RecvWxid); + if (t.Wxid != null) + { + msg.RobotUsernick = t.Nick; + if (nmWxidInfos.ContainsKey(t.socketHandle)) + { + var m = nmWxidInfos[t.socketHandle]; + if (m != null) + { + var tar = m.FirstOrDefault(p => p.Wxid == MsgInfo.Wxid_1); + if (!string.IsNullOrEmpty(tar.Nick) && string.IsNullOrEmpty(msg.FromUsernick)) + { + msg.FromUsernick = tar.Nick; + } + } + } + } + } + + msg.FromMessage = MsgInfo.Msg; + + socketClient.Send(msg); + } + } + } + + if (MsgInfo.IsSend == 0 && MsgInfo.Type == 10000) //&& MsgInfo.State == 2) + { + if (socketClient != null) + { + //新人入群 + if (MsgInfo.Wxid_1.Contains("@")) + { + var reg1 = Regex.Match(MsgInfo.Msg, @"""(?<邀请人昵称>.*)""邀请""(?<新人昵称>.*)""加入了群聊"); + var reg2 = Regex.Match(MsgInfo.Msg, @"你邀请""(?<新人昵称>.*)""加入了群聊"); + var reg3 = Regex.Match(MsgInfo.Msg, @"""(?<新人昵称>.*)""通过扫描""(?<邀请人昵称>.*)""分享的二维码加入群聊"); + var reg4 = Regex.Match(MsgInfo.Msg, @"""(?<新人昵称>.*)""通过扫描你分享的二维码加入群聊"); + + if (reg1.Success || reg2.Success || reg3.Success || reg4.Success) + { + WechatNewMemer newMember = new WechatNewMemer(); + newMember.Cmd = PCRobotCMD.newMember; + newMember.RobotType = RobotType.客户端微信; + newMember.RobotUsername = MsgInfo.RecvWxid; + newMember.RobotUsernick = GetRobotNick(MsgInfo.RecvWxid); + + if (reg1.Success) + { + newMember.SourceNick = reg1.Groups["邀请人昵称"].Value; + newMember.MemberNick = reg1.Groups["新人昵称"].Value; + } + else if (reg2.Success) + { + newMember.SourceNick = newMember.RobotUsernick; + newMember.MemberNick = reg2.Groups["新人昵称"].Value; + } + else if (reg3.Success) + { + newMember.SourceNick = reg3.Groups["邀请人昵称"].Value; + newMember.MemberNick = reg3.Groups["新人昵称"].Value; + } + else if (reg4.Success) + { + newMember.SourceNick = newMember.RobotUsernick; + newMember.MemberNick = reg4.Groups["新人昵称"].Value; + } + + if (MsgInfo.Wxid_1.Contains("@chatroom")) + { + newMember.GroupId = MsgInfo.Wxid_1; + newMember.GroupNick = MsgInfo.Nick_1; + } + + var t = nms.FirstOrDefault(p => p.Wxid == MsgInfo.RecvWxid); + if (t.Wxid != null) + { + newMember.RobotUsernick = t.Nick; + if (nmWxidInfos.ContainsKey(t.socketHandle)) + { + var m = nmWxidInfos[t.socketHandle]; + if (m != null) + { + var tar = m.FirstOrDefault(p => p.Wxid == MsgInfo.Wxid_1); + if (!string.IsNullOrEmpty(tar.Nick) && string.IsNullOrEmpty(newMember.GroupNick)) + { + newMember.GroupNick = tar.Nick; + } + } + } + } + socketClient.Send(newMember); + } + } + else//新增好友 + { + #region 添加好友成功 + var reg1 = Regex.Match(MsgInfo.Msg, "^你已添加了(.*?),现在可以开始聊天了。$"); + var reg2 = Regex.Match(MsgInfo.Msg, "^(.*?)刚刚把你添加到通讯录,现在可以开始聊天了。$"); + if (reg1.Success || reg2.Success) + { + WechatNewFriend msg = new WechatNewFriend(); + msg.Cmd = PCRobotCMD.newfriend; + msg.RobotUsername = MsgInfo.RecvWxid; + msg.RobotUsernick = GetRobotNick(MsgInfo.RecvWxid); + msg.RobotType = RobotType.客户端微信; + msg.FromUserName = MsgInfo.Wxid_1; + msg.FromUserNick = MsgInfo.Nick_1; + socketClient.Send(msg); + } + #endregion + } + } + } + + + //自动填充消息内容,用于撤回消息 + //if (MsgInfo.IsSend == 1 && ConnID == nmHeler.Socket_ConnId) + //{ + //text_Recvke_Wxid.Text = MsgInfo.Wxid_1; + //text_Recvke_Sid.Text = MsgInfo.ServerMsgID; + //text_Recvke_Message.Text = MsgInfo.Msg; + //} + + //名片消息自动填充数据 + //if (MsgInfo.IsSend == 0 && MsgInfo.Type == 42 && ConnID == nmHeler.Socket_ConnId) + //{ + //string v1 = nmHeler.StringMid(MsgInfo.Msg, "username=\"", "\" nickname="); + //string v2 = nmHeler.StringMid(MsgInfo.Msg, "antispamticket=\"", "\" /"); + //text_Friend_v1.Text = v1; + //text_Friend_v2.Text = v2; + //} + + } + catch (Exception ex) + { + + } + } + + /// + /// 通信事件_切换聊天对象 + /// + /// + /// + void Event_SelectTalker(int ConnID, JObject RecvJson) + { + try + { + //NMHelper.nmWxidInfo WxidInfo = new NMHelper.nmWxidInfo(); + //string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + //WxidInfo.Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + //WxidInfo.WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + //WxidInfo.Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + //WxidInfo.Mark = nmHeler.Json_GetString(RecvJson, "Mark", true); + //WxidInfo.HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + //string outLog = "[切换聊天对象]" + RecvWxid + NewLine; + //outLog += "Wxid:" + WxidInfo.Wxid + NewLine; + //outLog += WxidInfo.WxNo == string.Empty ? string.Empty : "微信号:" + WxidInfo.Wxid + NewLine; + //outLog += "昵称:" + WxidInfo.Nick + NewLine; + //outLog += WxidInfo.Mark == string.Empty ? string.Empty : "备注:" + WxidInfo.Mark; + ////outLog += "头像:" + WxidInfo.HeadIMG; + //WriteLog(outLog); + var wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + nmCore.NM_SetObject(curWx.socketHandle, 2, wxid); + } + catch (Exception ex) + { + + } + } + + void Event_RecvContactList(int ConnID, JObject RecvJson) + { + try + { + var recvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[通讯录列表]" + recvWxid + NewLine; + int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + if (dwState == 0) + { + outLog += "通讯录列表读取失败!"; + WriteLog(outLog); + return; + } + JArray m_List = RecvJson.Value("List"); + if (m_List != null) + { + List> nmss = new List>(); + List mis = new List(); + var count = 40; + var rem = m_List.Count % count; + var num = m_List.Count / count; + + for (int i = 0; i < m_List.Count; i++) + { + JToken JtMember = m_List.ElementAt(i); + if (JtMember != null) + { + NMHelper.nmWxidInfo MemberInfo = new NMHelper.nmWxidInfo(); + MemberInfo.Type = nmHeler.Json_GetIntEx((JObject)JtMember, "Type"); + MemberInfo.List = nmHeler.Json_GetIntEx((JObject)JtMember, "List"); + MemberInfo.Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + MemberInfo.WxNo = nmHeler.Json_GetString((JObject)JtMember, "WxNo", true); + MemberInfo.Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + MemberInfo.Mark = nmHeler.Json_GetString((JObject)JtMember, "Mark", true); + MemberInfo.HeadIMG = nmHeler.Json_GetString((JObject)JtMember, "HeadIMG", true); + mis.Add(MemberInfo); + if (mis.Count >= count) + { + nmss.Add(mis); + mis = new List(); + } + else if (nmss.Count == num && mis.Count == rem) + { + nmss.Add(mis); + } + } + } + + if (socketClient != null) + { + foreach (var item in nmss) + { + WechatContactList msg = new WechatContactList(); + msg.RobotUsername = recvWxid; + msg.RobotUsernick = GetRobotNick(recvWxid); + msg.RobotType = RobotType.客户端微信; + + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", item } }); + + socketClient.Send(msg); + Thread.Sleep(5); + } + } + } + } + catch (Exception ex) + { + + } + } + + void Event_RecvGroupMember(int ConnID, JObject RecvJson) + { + try + { + //string outLog = "[群员列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + var recvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + if (dwState == 0) + { + //outLog += nmHeler.Json_GetString(RecvJson, "GroupID", false) + "的群员列表读取失败!"; + //WriteLog(outLog); + return; + } + + JArray m_List = RecvJson.Value("List"); + if (m_List != null) + { + List> nmss = new List>(); + List mis = new List(); + var count = 20; + var rem = m_List.Count % count; + var num = m_List.Count / count; + + for (int i = 0; i < m_List.Count; i++) + { + JToken JtMember = m_List.ElementAt(i); + if (JtMember != null) + { + NMHelper.nmWxidInfo MemberInfo = new NMHelper.nmWxidInfo(); + MemberInfo.Type = nmHeler.Json_GetIntEx((JObject)JtMember, "Type"); + MemberInfo.List = nmHeler.Json_GetIntEx((JObject)JtMember, "List"); + MemberInfo.Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + MemberInfo.WxNo = nmHeler.Json_GetString((JObject)JtMember, "WxNo", true); + MemberInfo.Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + MemberInfo.Mark = nmHeler.Json_GetString((JObject)JtMember, "Mark", true); + MemberInfo.HeadIMG = nmHeler.Json_GetString((JObject)JtMember, "HeadIMG", true); + mis.Add(MemberInfo); + if (mis.Count >= count) + { + nmss.Add(mis); + mis = new List(); + } + else if (nmss.Count == num && mis.Count == rem) + { + nmss.Add(mis); + } + } + } + + if (socketClient != null) + { + foreach (var item in nmss) + { + WechatGroupMember msg = new WechatGroupMember(); + msg.RobotUsername = recvWxid; + msg.RobotUsernick = GetRobotNick(recvWxid); + msg.RobotType = RobotType.客户端微信; + + msg.Cmd = PCRobotCMD.rcvGroupMember; + + nmGroupInfo group = new nmGroupInfo(); + group.Count = nmHeler.Json_GetIntEx(RecvJson, "Count"); + group.GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + group.List = item; + msg.Message = HttpHelper.ObjectToJson(new Dictionary() { { "data", group } }); + + socketClient.Send(msg); + Thread.Sleep(5); + } + } + //outLog += nmHeler.Json_GetString(RecvJson, "GroupID", true) + "的群员列表读取成功,群员数:" + list_GroupMember.Items.Count.ToString(); + //WriteLog(outLog); + } + } + catch (Exception ex) + { + + } + } + + void Event_RecvWxidInfo(int ConnID, JObject RecvJson) + { + try + { + var recvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[下载详细信息]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + int dwState = nmHeler.Json_GetIntEx(RecvJson, "State"); + if (dwState == -1) { outLog += "下载详细信息超时(原因:服务器无返回)!"; } + else if (dwState == 0) { outLog += "下载详细信息失败(原因:可能是输入的Wxid不正确)!"; } + else if (dwState == 1) + { + string szGroupID = nmHeler.Json_GetString(RecvJson, "GroupId", true); + NMHelper.nmWxidInfo MemberInfo = new NMHelper.nmWxidInfo(); + MemberInfo.Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + MemberInfo.WxNo = nmHeler.Json_GetString(RecvJson, "WxNo", true); + MemberInfo.Nick = nmHeler.Json_GetString(RecvJson, "Nick", true); + MemberInfo.V1 = nmHeler.Json_GetString(RecvJson, "v1", true); + MemberInfo.HeadIMG = nmHeler.Json_GetString(RecvJson, "HeadIMG", true); + MemberInfo.Address = nmHeler.Json_GetString(RecvJson, "Address", true); + MemberInfo.Sex = nmHeler.Json_GetIntEx(RecvJson, "Sex").ToString(); + + outLog += szGroupID == string.Empty ? string.Empty : "群ID:" + szGroupID + NewLine; + outLog += "Wxid:" + MemberInfo.Wxid + NewLine; + outLog += MemberInfo.WxNo == string.Empty ? string.Empty : "微信号:" + MemberInfo.WxNo + NewLine; + outLog += "昵称:" + MemberInfo.Nick + NewLine; + outLog += MemberInfo.V1 == string.Empty ? string.Empty : "v1:" + MemberInfo.V1 + NewLine; + outLog += "性别:" + MemberInfo.Sex + NewLine; + outLog += MemberInfo.Address == string.Empty ? string.Empty : "地区:" + MemberInfo.Address + NewLine; + outLog += MemberInfo.HeadIMG == string.Empty ? string.Empty : "头像:" + MemberInfo.HeadIMG + NewLine; + + WechatContactList msg = new WechatContactList(); + msg.RobotUsername = recvWxid; + msg.RobotUsernick = GetRobotNick(recvWxid); + msg.RobotType = RobotType.客户端微信; + + msg.Cmd = PCRobotCMD.rcvContactList; + msg.Message = HttpHelper.ObjectToJson(new Dictionary>() { { "data", new List() { MemberInfo } } }); + + socketClient.Send(msg); + Thread.Sleep(5); + } + WriteLog(outLog); + } + catch (Exception ex) + { + + } + } + + void Event_AddFriend(int ConnID, JObject RecvJson) + { + try + { + //string outLog = "[添加好友]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //int DataType = nmHeler.Json_GetIntEx(RecvJson, "DataType"); + //string Data = nmHeler.Json_GetString(RecvJson, "Data", true); + //int Type = nmHeler.Json_GetIntEx(RecvJson, "Type"); + //int AddType = nmHeler.Json_GetIntEx(RecvJson, "AddType"); + //string Wxid = nmHeler.Json_GetString(RecvJson, "Wxid", true); + //string v2 = nmHeler.Json_GetString(RecvJson, "V2", true); + //string Message = nmHeler.Json_GetString(RecvJson, "Message", true); + + //outLog += "添加返回:[" + DataType.ToString() + "]" + (DataType == 0 ? "已发送好友请求或已添加好友。" : Data) + NewLine; + //outLog += "添加类型:" + Type.ToString() + " 添加来源:" + AddType.ToString() + NewLine; + //outLog += "Wxid:" + Wxid; + //outLog += v2 == string.Empty ? string.Empty : NewLine + "v2:" + v2; + //outLog += Message == string.Empty ? string.Empty : NewLine + "附加消息:" + Message; + //WriteLog(outLog); + + //if (Type == 1 && DataType == -44) + //{ + // nmCore.NM_AddFriend(ConnID, 2, AddType, Wxid, v2, text_Friend_Message.Text); + //} + } + catch (Exception ex) + { + } + } + + void Event_CreateGroup(int ConnID, JObject RecvJson) + { + try + { + //string outLog = "[创建群聊]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //string Data = nmHeler.Json_GetString(RecvJson, "Data", true); + //string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + //outLog += "建群返回:" + Data; + //outLog += GroupID == string.Empty ? string.Empty : NewLine + "群聊ID:" + GroupID + NewLine; + //JArray MemberList = RecvJson.Value("List"); + //if (MemberList != null) + //{ + // outLog += "群员列表:"; + // for (int i = 0; i < MemberList.Count; i++) + // { + // JToken JtMember = MemberList.ElementAt(i); + // if (JtMember != null) + // { + // string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + // string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + // int state = nmHeler.Json_GetIntEx((JObject)JtMember, "State"); + // if (Wxid != string.Empty) + // { + // outLog += NewLine + "[" + state.ToString() + "]" + (state == 0 ? "[成功]" : "[失败]"); + // outLog += Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")"); + // } + // } + // } + //} + //WriteLog(outLog); + } + catch (Exception ex) + { + } + } + + void Event_GetFavList(int ConnID, JObject RecvJson) + { + try + { + //string outLog = "[收藏列表]" + nmHeler.Json_GetString(RecvJson, "RecvWxid", true) + NewLine; + //JArray FavList = RecvJson.Value("List"); + //if (FavList != null) + //{ + // list_Fav.Items.Clear(); + // int dwCount = FavList.Count; + // if (dwCount != 0) + // { + // list_Fav.BeginUpdate(); + + // for (int i = 0; i < dwCount; i++) + // { + // JToken JtMember = FavList.ElementAt(i); + // if (JtMember != null) + // { + // int Type = nmHeler.Json_GetIntEx((JObject)JtMember, "Type"); + // string SearchKey = nmHeler.Json_GetString((JObject)JtMember, "SearchKey", true); + // string TypeName = nmHeler.GetFavType(Type); + // ListViewItem FavItem = new ListViewItem(); + // FavItem.Text = i.ToString(); + // FavItem.SubItems.Add(TypeName); + // FavItem.SubItems.Add(SearchKey == string.Empty ? "[" + TypeName + "文件]" : SearchKey); + // list_Fav.Items.Add(FavItem); + // } + // } + // list_Fav.EndUpdate(); + // outLog += "收藏列表读取成功,共" + dwCount.ToString() + "条记录!"; + // } + // else + // { + // outLog += "没有收藏"; + // } + //} + //WriteLog(outLog); + } + catch (Exception ex) + { + } + } + + void Event_GetA8Key(int ConnID, JObject RecvJson) + { + try + { + //string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + //string outLog = "[GetA8Key]" + RecvWxid + NewLine; + //string URL = nmHeler.Json_GetString(RecvJson, "URL", true); + //string LastURL = nmHeler.Json_GetString(RecvJson, "LastURL", true); + //outLog += "获取链接:" + URL + NewLine; + //outLog += "返回链接:" + LastURL; + //WriteLog(outLog); + + //if (URL.IndexOf("mmsupport-bin/addchatroombyinvite") != -1) + //{ + // HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(URL); + // Request.Method = "POST"; + // Request.AllowAutoRedirect = false; + // Request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; + // Request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.556.400 QQBrowser/9.0.2524.400"; + // Request.Referer = URL; + // Request.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8,en-us;q=0.6,en;q=0.5;q=0.4"); + // HttpWebResponse Response = (HttpWebResponse)Request.GetResponse(); + // string hLocation = Response.GetResponseHeader("Location").ToString(); + // if (hLocation != "") + // { + // if (hLocation.IndexOf("chatroom") != -1) + // { + // string GroupID = nmHeler.StringMid(hLocation, "weixin://jump/mainframe/", "@chatroom"); + // WriteLog("[接受群聊邀请]" + RecvWxid + NewLine + "群聊ID:" + GroupID + "@chatroom"); + // } + // } + //} + } + catch (Exception ex) + { + + } + } + + void Event_GroupInvite(int ConnID, JObject RecvJson) + { + try + { + string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[群员动态-进群]" + RecvWxid + NewLine; + string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + outLog = "群聊ID:" + GroupID + NewLine; + JArray MemberList = RecvJson.Value("List"); + if (MemberList != null) + { + for (int i = 0; i < MemberList.Count; i++) + { + JToken JtMember = MemberList.ElementAt(i); + if (JtMember != null) + { + string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + string InvWxid = nmHeler.Json_GetString((JObject)JtMember, "InvWxid", true); + string InvNick = nmHeler.Json_GetString((JObject)JtMember, "InvNick", true); + outLog += "[" + (i + 1).ToString() + "]" + NewLine; + outLog += "进群人:" + Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")" + NewLine); + outLog += "邀请人:" + InvWxid + (InvNick == string.Empty ? string.Empty : "(" + InvNick + ")" + NewLine); + } + } + } + WriteLog(outLog); + } + catch (Exception ex) + { + + } + } + void Event_GroupQuit(int ConnID, JObject RecvJson) + { + try + { + string RecvWxid = nmHeler.Json_GetString(RecvJson, "RecvWxid", true); + string outLog = "[群员动态-退群]" + RecvWxid + NewLine; + string GroupID = nmHeler.Json_GetString(RecvJson, "GroupID", true); + outLog += "群聊ID:" + GroupID + NewLine; + JArray MemberList = RecvJson.Value("List"); + if (MemberList != null) + { + for (int i = 0; i < MemberList.Count; i++) + { + JToken JtMember = MemberList.ElementAt(i); + if (JtMember != null) + { + string Wxid = nmHeler.Json_GetString((JObject)JtMember, "Wxid", true); + string Nick = nmHeler.Json_GetString((JObject)JtMember, "Nick", true); + + outLog += "[" + (i + 1).ToString() + "]" + NewLine; + outLog += Wxid + (Nick == string.Empty ? string.Empty : "(" + Nick + ")" + NewLine); + } + } + } + WriteLog(outLog); + } + catch (Exception ex) + { + + } + } + + [DllImport("User32.dll", EntryPoint = "PostMessage")] + public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam); + + [DllImport("LIB.KTY.WC.dll", EntryPoint = "Run")] + public static extern IntPtr Run(string path, string dll, int port); + + private IntPtr DwPid = IntPtr.Zero; + + public int handle { get { return (int)DwPid; } } + + public int StartWechat() + { + try + { + // api.StartWechat(); + PCWechat.Wechat_Xiaoxie.StartWechat(HttpExtend.MapFile("WeChat.exe", $"PCWechat\\2.7.1.82")); + return -1; + bool isAlterXML = false; + //var path = CsharpHttpHelper.HttpExtend.MapPath("PCWechat\\2.8.0.112"); + //var path = CsharpHttpHelper.HttpExtend.MapPath("PCWechat\\2.7.1.88"); + + var path = CsharpHttpHelper.HttpExtend.MapPath($"PCWechat\\{comboBox1.SelectedItem.ToString()}"); + + var wechatPath = CsharpHttpHelper.HttpExtend.MapFile("WeChatWin.dll", path); + if (!File.Exists(wechatPath)) + { + + var rst = MessageBox.Show($"您还没有下载{comboBox1.SelectedItem.ToString()}版本微信,是否立即下载?", "微信版本异常", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + new WechatUpdate(comboBox1.SelectedItem.ToString()).ShowDialog(); + } + return -1; + + } + var md5 = Common.GetMD5Hash(wechatPath); + var version = comboBox1.SelectedItem.ToString(); + + //PCWechat.BaseApi api = null; + //if (version == "2.7.1.82") + //{ + // api = new PCWechat.Wechat_Xiaoxie(); + // api.StartWechat(HttpExtend.MapFile("WeChat.exe", $"PCWechat\\{version}")); + // return -1; + //} + + if ((version == "2.7.1.88" && md5 == "CED61F308EDD8CF3E2D864DF285DC2AF") || (version == "2.8.0.112" && md5 == "D13203AC5C3099D8563E16185DA944BC")) + { + + string szDllPath = System.IO.Directory.GetCurrentDirectory() + "\\bin\\NanMuCore.dll"; + var id = NMHelper.NM_CreateWeChatProcess(path, "WeChat.exe", szDllPath, nmHeler.Socket_Port); + + return id; + } + else + { + var rst = MessageBox.Show($"启动失败,您的微信{comboBox1.SelectedItem.ToString()}版本异常,是否重新下载?\r\n注意:平时请关闭微信自动升级,不要随意升级微信!!!", "微信版本异常", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + new WechatUpdate(comboBox1.SelectedItem.ToString()).ShowDialog(); + return -1; + } + } + } + catch (Exception ex) + { + throw ex; + } + return -1; + } + + public void WriteLog(string str) + { + + } + #endregion + + public static List nms = new List(); + + /** + * 判断是否是xml结构 + */ + public static bool isXML(string value) + { + try + { + //XmlDocument xdoc = new XmlDocument(); + //xdoc.LoadXml(value); + //return true; + + //上面的这里有些情况下不准 + var reg = Regex.IsMatch(value.Trim(), @"(.*0[\w\W]*1Window wechat)"); + return reg; + } + catch (Exception ex) + { + return false; + } + } + + public static void alterXML() + { + try + { + var updateXml = CsharpHttpHelper.HttpExtend.MapFile("LevelUpdate.xml"); + XmlDocument xdoc = new XmlDocument(); + xdoc.Load(updateXml); + var rootNode = xdoc.SelectSingleNode("Files"); + //获得该节点的子节点(即:该节点的第一层子节点) + bool isFind = false; + XmlNodeList firstLevelNodeList = rootNode.ChildNodes; + foreach (XmlNode node in firstLevelNodeList) + { + if (isFind) break; + //获得该节点的属性集合 + XmlAttributeCollection attributeCol = node.Attributes; + foreach (XmlAttribute attri in attributeCol) + { + //获取属性名称与属性值 + string name = attri.Name; + string value = attri.Value; + if (name == "Name" && value == "PCWechat") + { + isFind = true; + continue; + } + if (isFind && name == "Version") + { + attri.Value = "2020.02.14.1"; + break; + } + Console.WriteLine("{0} = {1}", name, value); + } + } + xdoc.Save(updateXml); + throw new Exception("微信版本"); + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 通过机器人id获取机器人昵称 + /// + /// + /// + private string GetRobotNick(string wxid) + { + var curWx = nms.FirstOrDefault(p => p.Wxid == wxid); + if (string.IsNullOrEmpty(curWx.Wxid)) + return string.Empty; + return curWx.Nick; + } + + public void lgCall(nmWxidInfo nm) + { + try + { + if (!nms.Contains(nm)) + { + //Process + nms.Add(nm); + + if (nm.Wxid != null) + { + if (socketClient != null) + { + WechatStatus msg = new WechatStatus(); + msg.Cmd = PCRobotCMD.offline; + msg.RobotUsername = nm.Wxid; + msg.RobotUsernick = nm.Nick; + msg.RobotType = RobotType.客户端微信; + msg.Status = Status.在线; + socketClient.Send(msg); + } + + WriteLog("[微信登陆]" + NewLine + "昵称:" + nm.Nick + NewLine + "Wxid:" + nm.Wxid); + } + } + //nms.Add(nm); + UpdateUi(); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("lgc ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + private void button3_Click(object sender, EventArgs e) + { + try + { + foreach (var item in nms) + { + Event_Logout(item.socketHandle, new JObject(), true); + if ((IntPtr)item.handle != IntPtr.Zero) + { + PostMessage((IntPtr)item.handle, 18, 0, 0); + Process[] myproc = Process.GetProcesses(); + foreach (Process items in myproc) + { + try + { + if (items.Id == item.handle) + { + items.Kill(); + break; + } + } + catch (Exception) + { } + } + } + } + nms.Clear(); + UpdateUi(); + } + catch (Exception ex) + { + + } + } + IniHelper config = null; + + private void Sleep(int number) + { + Thread t = new Thread(o => Thread.Sleep(number)); + t.Start(this); + while (t.IsAlive) + { + Application.DoEvents(); + } + } + private void button1_Click(object sender, EventArgs e) + { + //this.button1.Enabled = false; + try + { + if (config == null) + { + var fileName = HttpExtend.MapFile("服务器配置.ini", "Config"); + config = new IniHelper(fileName); + } + config.SetValue("服务器信息", "IP", textBox1.Text); + config.SetValue("服务器信息", "Port", textBox2.Text); + config.SetValue("秘钥", "SecretKey", textBox3.Text); + + if (this.button1.Text != "连接服务器") + { + if (socketClient != null) + { + socketClient.Stop = true; + socketClient.Close(); + } + StateCall("您已断开与服务器的连接!"); + this.button1.Text = "连接服务器"; + return; + } + + //MessageBox.Show("保存配置成功"); + if (socketClient != null) + { + socketClient.Close(); + } + socketClient.Stop = false; + socketClient.Connection(config.GetValue("服务器信息", "IP"), Convert.ToInt32(config.GetValue("服务器信息", "Port")), Rcv, Sea, config.GetValue("秘钥", "SecretKey"), StateCall); + + Thread.Sleep(1000); + + + if (socketClient.IsConnected) + { + //socketClient.Stop = false; + this.button1.Text = "断开服务器"; + + //this.Close(); + } + else throw new Exception("连接服务器失败,请检查是否填写正确!"); + + } + catch (Exception ex) + { + if (socketClient != null) socketClient.Stop = true; + MessageBox.Show(ex.Message, "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + public void StateCall(string str) + { + if (!string.IsNullOrEmpty(str)) + { + try + { + this.Invoke(new Action(() => + { + status.Text = str; + if (str.Contains("成功")) + { + this.groupBox1.Enabled = false; + this.button1.Text = "断开服务器"; + } + else + { + this.groupBox1.Enabled = true; + this.button1.Text = "连接服务器"; + } + })); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("sc ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + } + + private void Sea(Exception obj) + { + StateCall("连接异常:" + obj.Message); + socketClient.Close(); + } + private void RefUserMethod(WechatUser user) + { + + this.Invoke(new Action(delegate + { + try + { + this.listView1.Items.Clear(); + foreach (var item in WechatClient.Users.Values.ToList()) + { + var view = new ListViewItem(new string[] { item.Pid.ToString(),item.Wxid, item.Nickname, item.Phone }); + view.Tag = item; + this.listView1.Items.Add(view); + } + + } + catch (Exception) + { + + } + })); + } + private void WinForm_Load(object sender, EventArgs e) + { + this.FormClosing += PCForm_FormClosing; + contextMenuStrip1.Opening += ContextMenuStrip1_Opening; + //try + //{ + // IniWechat(); + //} + //catch (Exception ex) + //{ + // MessageBox.Show(ex.Message, "初始化微信失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + // this.Close(); + // return; + //} + try + { + WechatClient.RefUserEvent = RefUserMethod; + WechatClient.Install();//安装微信,初始化注入 + + var fileName = HttpExtend.MapFile("服务器配置.ini", "Config"); + var config = new IniHelper(fileName); + textBox1.Text = config.GetValue("服务器信息", "IP"); + textBox2.Text = config.GetValue("服务器信息", "Port"); + textBox3.Text = config.GetValue("秘钥", "SecretKey"); + var version = config.GetValue("微信版本", "Version"); + if (string.IsNullOrWhiteSpace(version)) + config.SetValue("微信版本", "Version", "2.7.1.88"); + + var v = config.GetValue("微信版本", "Version"); + for (int i = 0; i < comboBox1.Items.Count; i++) + { + if (comboBox1.Items[i].ToString() == v) + { + comboBox1.SelectedIndex = i; + break; + } + } + //comboBox1.SelectedIndex = config.GetValue("微信版本", "Version") == "2.7.1.88" ? 0 : 1; + socketClient = new SocketClient(); + socketClient.Connection(config.GetValue("服务器信息", "IP"), Convert.ToInt32(config.GetValue("服务器信息", "Port")), Rcv, Sea, config.GetValue("秘钥", "SecretKey"), StateCall); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("加载窗体 ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + private void ContextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + if (listView1.SelectedItems.Count == 0) + { + e.Cancel = true; + //删除微信ToolStripMenuItem.Enabled = false; + } + } + + private void 删除微信ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (listView1.SelectedItems.Count == 0) return; + else + { + string site = listView1.SelectedItems[0].Text; + int handle = 0; + if (int.TryParse(site, out handle)) + { + var nm = nms.FirstOrDefault(p => p.handle == handle); + Event_Logout(nm.socketHandle, new JObject()); + + CloseWechat(handle); + + //nms.Remove(nm); + //UpdateUi(); + } + } + var item = listView1.SelectedItems; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("Delete Wechat ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + public void UpdateUi() + { + try + { + listView1.Invoke(new Action(() => + { + listView1.Items.Clear(); + })); + + for (int i = 0; i < nms.Count; i++) + { + var temp = nms[i]; + ListViewItem UserItem = new ListViewItem(); + UserItem.Text = temp.handle.ToString(); + + UserItem.SubItems.Add(temp.Wxid); + UserItem.SubItems.Add(temp.Nick); + UserItem.SubItems.Add(temp.WxNo); + + UserItem.SubItems.Add(temp.HeadIMG); + listView1.Invoke(new Action(() => + { + listView1.Items.Add(UserItem); + })); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("ui ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + public void CloseWechat(int handle) + { + try + { + if ((IntPtr)handle != IntPtr.Zero) + { + PostMessage((IntPtr)handle, 18, 0, 0); + Process[] myproc = Process.GetProcesses(); + foreach (Process items in myproc) + { + try + { + if (items.Id == handle) + { + items.Kill(); + break; + } + } + catch (Exception) + { } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("CloseWechat ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + private void button4_Click(object sender, EventArgs e) + { + try + { + var nm = nms.FirstOrDefault(); + if (nm.Wxid != null) + { + string str = "\nwxid_u02qcv8eas7l51\n0\n\n \n公公和儿媳妇之间...\n内容儿童不宜,非礼勿视~~\nview\n5\n0\n\nhttps://www.baidu.com/\n\n\nhttp://ww2.sinaimg.cn/large/ceeb653ejw1fad1gv3wv5j20cm09g0t5.jpg\n\n\n\n\n\n\n\n \n0\n\n\n\n \n\n\n1\nWindow wechat\n\n"; + if (isXML(str)) + { + + } + + nmCore.NM_SendURLMsg(nm.socketHandle, "wxid_y5bnbqqa9d9721", str); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("SendUrlMsg ERROR:", $"{ex.Message} - {ex.StackTrace}"); + } + } + + private void button4_Click_1(object sender, EventArgs e) + { + OnlineUpdate.Client client = new OnlineUpdate.Client(); + if (client.CheckVersion()) + { + client.StartInstall(); + this.Close(); + //we + } + //new LevelUpdate.UpdateForm().ShowDialog(); + } + + private void textBox3_TextChanged(object sender, EventArgs e) + { + + } + + private void button5_Click_1(object sender, EventArgs e) + { + nmCore.NM_GetContactList(curWx.socketHandle); + } + + + string[] ClearDirs = new string[] { "VOICE", "IMAGE" }; + + /// + /// 清理缓存 + /// + /// + /// + private void ClearCache_Timer_Tick(object sender, EventArgs e) + { + this.Invoke(new Action(() => + { + try + { + //删除微信缓存文件(图片/文件) + var cachePath = CsharpHttpHelper.HttpExtend.MapPath("Accounts"); + if (Directory.Exists(cachePath)) + { + DirectoryInfo dirs = new DirectoryInfo(cachePath); + FileSystemInfo[] fileinfos = dirs.GetFileSystemInfos(); //返回目录中所有文件和子目录 + for (int z = 0; z < fileinfos.Length; z++) + { + for (int k = 0; k < ClearDirs.Length; k++) + { + var path = CsharpHttpHelper.HttpExtend.MapPath($@"Accounts\{fileinfos[z]}\{ClearDirs[k]}"); + Common.DeleteDir(path); + } + } + } + //删除更新包 + Common.DeleteDir(CsharpHttpHelper.HttpExtend.MapPath(@"Cache\Update")); + } + catch (Exception) + { } + })); + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (config == null) + { + var fileName = HttpExtend.MapFile("服务器配置.ini", "Config"); + config = new IniHelper(fileName); + } + config.SetValue("微信版本", "Version", comboBox1.SelectedItem.ToString()); + } + } + +} diff --git a/PCRobot/WinForm.resx b/PCRobot/WinForm.resx new file mode 100644 index 0000000..5a31dbe --- /dev/null +++ b/PCRobot/WinForm.resx @@ -0,0 +1,865 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 106, 17 + + + 17, 17 + + + + + AAABAAEASEgAAAEAIACIVAAAFgAAACgAAABIAAAAkAAAAAEAIAAAAAAAAFEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAA + AAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAACAAAAAgAAAAIAAAACAAAAAgAA + AAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAADAAAAA4AAAAOAAAADwAA + ABAAAAAQAAAAEAAAABEAAAAQAAAAEAAAABAAAAAPAAAADgAAAA0AAAAMAAAACgAAAAkAAAAIAAAABwAA + AAYAAAAFAAAABAAAAAIAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAwAAAAMAAAAFAAAABwAA + AAkAAAAMAAAADwAAABIAAAAVAAAAGAAAABoAAAAdAAAAIAAAACMAAAAlAAAAJgAAACcAAAAoAAAAKQAA + ACkAAAApAAAAKAAAACcAAAAlAAAAJAAAACIAAAAfAAAAHAAAABoAAAAXAAAAFAAAABEAAAAPAAAACwAA + AAgAAAAHAAAABQAAAAMAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAAFAAAABwAAAAoAAAANAAAAEgAAABYAAAAbAAAAIQAA + ACYAAAArAAAAMAAAADYAAAA7AAAAPgAAAEIAAABGAAAASAAAAEoAAABMAAAATQAAAE0AAABNAAAATAAA + AEoAAABHAAAARQAAAEEAAAA9AAAAOQAAADQAAAAuAAAAKgAAACQAAAAgAAAAGgAAABUAAAARAAAADQAA + AAoAAAAHAAAABAAAAAMAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAEAAAADAAAABQAAAAgAAAALAAAAEAAAABYAAAAcAAAAIwAAACsAAAA0AAAAPAAAAEUAAABNAAAAVQAA + AF0AAABkAAAAagAAAHEAAAB2AAAAeQAAAH0AAACAAAAAgQAAAIEAAACBAAAAfwAAAHwAAAB4AAAAdAAA + AG8AAABoAAAAYQAAAFoAAABSAAAASgAAAEIAAAA5AAAAMQAAACkAAAAhAAAAGgAAABUAAAAPAAAACgAA + AAcAAAAEAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAMAAAAFAAAACQAA + AA4AAAAVAAAAHAAAACYAAAAwAAAAOwAAAEYAAABSAAAAXgAAAGoAAAB2AAAAgQAAAIsAAACVAAAAnwAA + AKcAAgCtAAQCsgAFA7YABQS5AQUEugEGBLoBBgS6AQUEuAEEA7UBAgKxAAAAqwAAAKQAAACcAAAAkgAA + AIgAAAB+AAAAcgAAAGYAAABaAAAATgAAAEMAAAA4AAAALAAAACMAAAAZAAAAEgAAAAwAAAAIAAAABAAA + AAIAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAQAAAAIAAAADgAAABYAAAAfAAAAKwAA + ADkAAABGAAAAVQAAAGMAAAByAAAAgQAAAJAAAACfAAIBrgAWCb8BKxHNAT8b2QJYLOQCaz3sAXNG8AF5 + SfMCfUv1BoBM9QmDTvUMhVD1D4JQ9BB5S/IPaEDtDE8v5gg2H9wFIRPSAgwHxAAAALUAAACpAAAAmwAA + AI0AAAB9AAAAbQAAAF4AAABQAAAAQQAAADQAAAAnAAAAHAAAABMAAAAMAAAABgAAAAMAAAABAAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAYAAAALAAAAEwAAABwAAAApAAAANwAAAEcAAABXAAAAaAAA + AHkAAACKAA0FoQEqEbsBUSHWAnIu6gKHOPUCm0n8AqJb/wGaX/8BkFf/AI1R/wCOT/8AkU//AJJQ/wGU + Uv8Cl1P/BJdU/waWVP8IkVD/ColJ/wp+Qv8Kbjj8CVwv9QlJJ+kGLBjWAxMLwAABAakAAACWAAAAhQAA + AHQAAABjAAAAUgAAAEIAAAAzAAAAJQAAABkAAAAPAAAACAAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAABAAAAAwAAAAYAAAALAAAAFAAAAB8AAAAtAAAAPQAAAE8AAABfAAAAcQEdC5ECUyC/Anow5AKU + O/kCnj7/AqZI/wKjW/8Bj1n/AH9L/wB6Q/8AekH/AHpA/wB7QP8Ae0D/AHxA/wB+Qf8Af0H/AIBB/wB9 + P/8Adzr/AWwy/wFgKf8BWCX/AVgm/wJaKv8FXS7+B1Yt9AZCJN0DIxO4AQgElQAAAH4AAABtAAAAWwAA + AEkAAAA4AAAAKAAAABwAAAARAAAACQAAAAUAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAA + AAUAAAALAAAAEwAAAB4AAAAsAAAAOwAAAEsBIgxuAmEkrgOJM+cDmTr9A548/wOfPf8CplT/AZdf/wB6 + Sf8Abjr/AGo3/wBnNP8AYzH/AGAu/wBeLP8AXSv/AF4q/wBfK/8AYCv/AGEr/wBeKv8AWCb/AE4g/wBC + Gv8FPBb/HUcW/yhOGP8aTxz/Ck4i/wVRKP8BUSv4AEQl2QAoF6MABwVxAAAAVwAAAEcAAAA2AAAAJwAA + ABoAAAAQAAAACAAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAHAAAADwAA + ABgAAAAiABAGNwJiJIEEijPXBJg5/QScO/8EnTv/BKFA/wOlXf8BiFf/AGw6/wBiMf8AWyz/AFIl/wBL + If8DRh7/C0Md/xNCHf8ZQR3/HEIf/x1EH/8cRB//F0Qd/w4/Gv8FOBb/AC4Q/xYuDf+MaQ3/zpIN/9OQ + DP/IiAz/rXwO/4pvEv9gZBf/P1we/yhWI/YRSSHHASkVdQAAAT4AAAArAAAAHQAAABMAAAAMAAAABgAA + AAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAFAAAACgAAAA4DViAzBYgyogWX + OfQFmzz/Bp09/wafPv8GpET/A6Fg/wB7Tf8AYTD/AFco/wNLIv8PQR7/Ijod/zg2Hv9INCH/VDQj/1w1 + JP9iNib/Zjgo/2k6Kf9pPCr/ZTwq/1g2Jv9ELR7/MCQX/4pRC//snA7/6aEO/+aaDf/mlwz/6JQM/+mS + C//njgv/3okL/82EDf+xfhH/nncT6aJvDqCqZwdkn2EHQpJYByVQLwMMAAAAAf/pEwDgigsA3IYLANyF + CgDbgwoA3IQKANuDCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQEAAAACAAAAAwaHNDwGlzrCB5w8/weePv8IoEH/CKJB/win + SP8EomL/AHJE/wBXKf8JSiL/IT0e/z4zHv9SLh//Wywe/14sHv9eLR3/Xy0e/2AvH/9iMCD/ZDMi/2c1 + I/9oNST/ZjUl/10vIP9MJBr/VygU/8doCv/nnxL/5Z8S/+SbEP/kmBD/4pYP/+KVD//ikw//45IO/+WR + Df/nkQ3/6JAM/+SPDP/gjAz734sL6t2KC8rdiAuq3YgLht6IC1nehwsx3IYLG9uDCgzikgsA3IQKANuC + CgDagQoA2oEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAACKNCAAm0RgAP/4kAB5k8RQecPtQInz//CaFC/wmjRP8KpUb/CqlK/wamZP8AbkH/CE4k/yc+ + IP9JMB7/WCoc/1koGv9XJxj/VycY/1goGf9aKhr/XSwc/18uHf9hMB//ZDIh/2Y0Iv9mNCP/YzMi/1cr + HP9CHhT/WSYN/8poCf/noRX/5aAV/+ScE//kmhP/45kT/+SYEv/klxL/5JcR/+SWEf/klRH/45UQ/+OV + EP/jlA//45MO/+KRDv/hkA3/4I4N/+CMDPffiwvt3okL092HCqzchQqH3IMKYtuCCiPKdAAA2YAJANmA + CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKBCAAqh + QwAIn0BHCZ9B3QmhQ/8KpEb/C6ZI/wyoS/8Nq0z/CK9n/wNzSP8cRCH/RzMg/1sqHf9ZJxn/ViYX/1Ym + Fv9YJxf/WigZ/10rGv9gLRz/YzAe/2YyIP9oNCL/azck/205Jv9sOCX/aDYk/1krHP9CHRT/WyYM/8pm + Cf/noxn/5aAY/+WdF//lnBb/5JsW/+SaFv/kmhb/5JoV/+SaFf/kmRT/5JkT/+SZE//kmRL/5JgR/+SX + EP/jlhD/4pUP/+GTDv/hkQ3/4I8M/9+NDP/eigv/3YcL+tyECtHbggs93YQMANmACgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAymSQALo0UAC6RHAAqiRD4Ko0XcC6RH/wyn + Sv8NqUz/DqtP/xCsUP8Ntmb/CYNZ/y85If9XLR7/XSob/1opGf9bKRj/XCoY/18rGv9hLRv/ZC8d/2Yw + Hv9nMiD/ajQh/2w2I/9uOCT/cDom/3E8J/9wOyf/bDgl/1wtHf9DHhT/XygM/8xoCv/opB7/5qAc/+We + G//lnhv/5Z0a/+WdGv/lnRn/5Z0Z/+WcGP/lnBf/5ZwW/+WbFv/lmxX/5JsU/+SaE//kmhP/5JkS/+SY + EP/jlxD/4pUP/+GSDv/gkA7/3owN/9yGDP/bgQui2XwJB9p/CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+xVgAMp0oAC6VIKwumSM0Mp0v/DqpN/xCsUP8RrlP/ErBV/xK3 + X/8PnG//Nzcm/1gpG/9fLBv/YC0b/2IuHP9kLx3/ZjAd/2cxHv9nMR7/ZzEe/2gyH/9pMyD/ajQh/2w2 + Iv9uOCT/bzom/3A7J/9uOib/aDYk/1cqG/8+GhL/YCgK/85pC//ppyP/5qIi/+WgIP/loCD/5aAg/+ag + H//moB7/5qAe/+agHf/mnxz/5p8b/+afGv/mnhn/5Z4Y/+WdF//mnBb/5ZwV/+WbE//kmhL/45gS/+KV + Ef/hkhD/340P/9yGDf/bgAuN2HkIBNp+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAADq5TAA2qTgAMqEsSDalMrw6qTv8QrVH/Eq9V/xOxWP8Vs1v/F7de/w+5ev8rTz7/UyMX/18u + Hf9mMR7/aDIf/2kzH/9pMyD/aTMg/2kzIP9pMyD/aTMf/2kzIP9qNCD/azUh/2w2Iv9uOCT/bzkl/3A6 + Jv9uOSb/ZzQj/1QoGf85GBD/YigJ/9BsDf/qqyr/56Qn/+ajJv/noyb/56Mm/+ijJf/ooyT/56Mk/+ej + I//noiH/56Ig/+eiH//noR3/56Ac/+agGv/mnxn/5p8X/+WdFv/lnBX/5JoU/+OXE//hkhH/34sP/92E + DdbbgAws24EMANd7CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq1SAA2t + UQIOrVJ5D65T+xGwV/8Us1v/FbVe/xi3Yv8auWT/GMR2/xWMbf9FIxn/Xiwc/2kzIP9rNCD/azQh/2w0 + IP9sNSD/bDUg/2w1IP9sNSD/bDUg/2w1IP9sNSH/bDUh/202Iv9uNyP/cDkl/3A5Jf9tOCX/ZTMi/1Em + GP82Fg7/ZCkI/9JxDv/srzH/6Kct/+imLP/opiz/6Kcs/+inK//opyr/6Kcp/+imKP/opib/56Yl/+il + JP/opSL/6KQg/+ejHv/mohz/5qEa/+agGP/lnxf/5ZwW/+SZFf/hkhP/34oQ5d2EDk3fjBAA2n4LANl9 + CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUumIAELNaAA+xWDwQslnlErRc/xW2 + YP8XuWP/Grpm/xy9a/8fxHX/E8SR/ytHOP9WJBb/aDMg/242Iv9uNiL/bjYi/242Iv9uNyL/bjci/243 + Iv9uNyL/bjci/243Iv9uNiL/bjYi/283I/9vOCP/cDkl/3A5Jf9tOCT/ZTIg/08jFv8yEw3/ZikG/9V0 + Ef/ttDj/6ao0/+mqM//pqzP/6asz/+mqMv/pqjH/6aow/+mqLv/pqS3/6akr/+moKf/oqCf/6Kcl/+im + I//opSH/56Qf/+ejHP/noRr/5p8Y/+SbF//ikxTq4IwSXc9gBgHcgw4A24AMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARtl4AEbVcDRG1Xq0Tt2D/Frlj/xm7Z/8cvWv/H8Fx/yLH + fP8h1pb/E5t+/0MiFv9hLx7/bjcj/3E5JP9xOST/cjkk/3I5JP9yOiT/cjok/3I6JP9yOiT/cjok/3I6 + JP9yOST/cjkk/3E5JP9xOST/cjol/3E6Jf9uOCT/ZDEg/00iFf8wEQz/aisG/9d5E//uuUH/6q88/+qv + O//qrzv/6q87/+quOv/qrjj/6q43/+quNf/qrTP/6q0x/+qsL//qqy3/6qsq/+mpKP/pqSb/6agj/+im + If/opR//56Ic/+WdGfjklxZ034QQAuCLEgDdhQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAABS8aAATuWMAE7liVRS5Y/UXu2f/Gr1r/x2/b/8hw3b/JMqC/yjUk/8c2qz/IFxJ/1Qi + FP9qNSL/czol/3Q7Jf91PCb/dTwm/3U8J/92PCf/djwm/3Y8Jv92PCb/djwm/3Y8Jv92PCf/dTwm/3U8 + Jv90PCb/dDwm/3M7Jv9vOST/YzEg/0whFP8uEAv/bywF/9p9F//wv0z/67RF/+u0RP/rtET/67RE/+y0 + Q//ss0H/7LNA/+uzPv/rsjz/67E5/+uwN//qrzT/668x/+utLv/qrCv/6aso/+mpJf/oqCP/56Uh/+eh + Hf3mnhqA4ZEYAeWcGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFb9tABS8 + aAAUu2cPFbxouBe9av8bv27/HsFy/yLFeP8my4X/KdSX/y7fqf8VwqH/NDEi/18sHP9xOiX/dz4n/3g+ + KP95Pyj/eT8p/3k/Kf96QCn/ekAp/3pAKf96QCn/ekAp/3pAKf95QCn/eT8p/3k/Kf94Pyj/eD4o/3Y9 + J/9xOib/ZTIg/0whFP8vEQv/dC8E/9yCHP/xxFb/7LhN/+y5Tf/tuU3/7blM/+y4S//suEn/7LhI/+y3 + Rv/stkP/7LZB/+y1Pv/stDv/67M4/+uyNP/rsDD/6q4t/+qrKv/qqif/6agk/+ilIf/moR7f5Z4dLOae + HQDmnx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGsR3ABa+awAVvmtLF79t9BvB + cf8fw3T/I8Z6/yfMh/8r1pn/MN2n/y7nuf8Vl33/RiEU/2k0Iv93Pij/e0Eq/3xCKv98Qyv/fUMs/35D + LP9+Qyz/fkQs/35ELP9+RCz/fkQs/35ELP9+Qyz/fUMs/31DK/98Qiv/fEIr/3lAKf90PCf/ZzMh/00i + Ff8vEQv/ejIE/96HIf/yyGD/7r1W/+6+Vv/uvVb/7b1V/+29VP/tvVL/7bxR/+28Tv/tu0v/7bpJ/+25 + Rf/tuEL/7bc//+y2O//stDf/7LIy/+uvLv/rrSv/6qso/+moJf/npCL/5aEfh///mADmnRwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFsBvABS/bgQXwXChGsNz/x/Ed/8jx3v/KMyG/yzW + mP8w3qj/N+Ky/ynmwv8caFT/VSIU/3E7J/98Qyz/gEYt/4BGLv+CRy7/g0cv/4RIL/+ESC//hEgv/4VI + L/+FSS//hUgv/4RIL/+ESC//g0cv/4NHL/+CRi7/gUYu/35ELf95QCv/bDYj/1AjFf8xEQv/gDQE/+GN + Jv/zzmv/8MJf//DCYP/wwl//8MNf//DCXf/wwlv/8MFZ//DBV//vwFT/775R/+++Tf/uvUr/7rxG/+66 + Q//tuT7/7bY5/+yzNP/rsC//6a0r/+mrKP/oqCX/56Qi2OahICTmoSAA5aQjAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAZxncAGMN0ABjDcyoaxHXeHsV4/yLHe/8ny4T/LNSV/zHdp/8247T/PenC/yLc + wf8qRTP/YCkb/3hAK/+CRy//hUkw/4ZKMf+ISzH/iUwy/4lMMv+KTTL/ik0y/4tNM/+LTTP/i00y/4pN + Mv+KTDL/iUwy/4hLMv+HSzH/hkox/4NIMP9+RC3/cDkl/1MlFv80Egv/hTcE/+OSLf/10nX/8cZp//HH + av/xx2n/8sdo//LHZ//xxmX/8cZj//HFYP/xxF3/8MNa//DCVv/wwVL/8MBO//C/S//vvUb/7rpB/+24 + O//stDX/6rAw/+quLP/pqyj/6Kcl/uajI2nppyUA6qQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAZxXYAG8V3ABrFdmQcxnj9Icd8/ybKgv8r0ZH/Mduk/zbjtP886ML/QvHU/xzJs/82LyD/aTIi/39F + Lv+ITDL/i04z/4xPNP+NUDX/jlE2/49RNv+QUjb/kFI2/5BSNv+QUjb/kFI2/5BSNv+PUTb/j1E2/45Q + Nf+MTzX/i040/4lMM/+ESTH/dT0o/1coGP84FAz/izoD/+WYNP/21n//8sty//LMc//yzHL/8sxy//LL + cP/yy27/8sps//HJaf/yyGb/8sdi//HGX//xxVv/8cRW//DDUv/wwU7/779I/++9Q//uuTz/7LQ1/+uw + MP/qrSz/6aoo/+emJbrloSIL5qIiAOajJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAax3gAGMd3BxzH + eaMfx3v/JMmA/yrPi/8w2J//NeGy/zvowv9C7s//Rfjh/xiynf9CJRf/cTgm/4ZKMf+OUTb/kFI3/5JU + OP+UVTn/lVY6/5ZWOv+XVzr/l1c7/5hXO/+YVzv/l1c7/5dXO/+WVzr/lVY6/5RVOv+TVDn/klM4/49R + N/+KTjT/ekEr/1wqGv89Fg3/kjwD/+eePP/32on/8857//PQfP/z0Hv/89B7//PPef/zz3f/8850//PN + cv/zzG//88tr//LKZ//yyWP/8sde//HGWv/xxVX/8cNQ//DASv/vvUT/7rk7/+uzNP/qsC//6a0r/+io + J+jnpCU556QlAOSoJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcx3sAG8d7GR7IfNciyX//KMyH/y7V + mP80363/Oue//0Duzv9H8tn/R/rn/xqdif9NIRT/eT4r/41PNv+VVTr/l1c8/5lZPf+bWz7/nFs+/51c + P/+eXD//n10//6BdQP+gXUD/n11A/59dP/+eXD//nVw+/5tbPv+aWj3/mFk9/5VWO/+QUzn/gUYu/2Et + HP9BGA7/mEAD/+mkQv/43pH/9NOE//TUhP/01IT/9NSD//TUgv/004D/9NJ9//TSev/z0Hf/889z//PO + b//zzWv/8sxm//LKYv/yyV3/8sdX//DFUv/vwkv/771D/+y3Ov/rsjP/6q8u/+iqKv/npydw660qAOWk + JgAAAAAAAAAAAAAAAAAAAAAAAAAAAB7KgAAdyX0AHch9QiDJf+0ly4P/K9GQ/zLbpf845br/PuzL/0Xx + 2P9N9N3/SPnp/x+Oev9VIRT/gEMv/5RUO/+cWz//nl1B/6BfQv+iYEP/pGFE/6ViRP+mYkX/p2NF/6dj + Rf+oZEX/p2NF/6ZjRf+mYkX/pGJE/6NhQ/+hYEP/n15C/5xcQP+XWT7/iEsy/2gwH/9JGw//nkMD/+ur + Sv/44Zn/9daL//XXjP/114z/9deL//XXiv/11oj/9daF//TVgv/01H//9NN7//TSd//00XP/889u//PO + af/zzGT/8ste//HIWf/wxVP/8MJL/+68Qf/stTf/67Ey/+msLf/nqCmv5KQnCuWmKAAAAAAAAAAAAAAA + AAAAAAAAAAAAAB3KfgAfyoAAHsmAbCLKgvwozon/L9ab/zXhsv886sb/QvDU/0rz3P9S9N7/Svjp/yGG + cv9bIRX/h0cy/5taP/+iYUT/pWNG/6hlR/+qZkj/q2dJ/61oSf+uaUr/r2pK/69qS/+wakv/r2pK/69p + Sv+taUr/rGhJ/6pnSP+pZUj/p2RH/6NiRP+eX0P/jlA3/240If9PHhD/pEgE/+60U//55KH/9duT//bb + lP/225T/9tuT//bbkv/12pD/9dmN//XZiv/12If/9deD//XVf//11Hr/9NN1//TRcP/00Gv/885m//LM + YP/yyVr/8cZS//DBSP/tuT3/67M1/+quMP/oqSvb5qYoHuanKQAAAAAAAAAAAAAAAAAAAAAAAAAAAB/K + gQA91pEAIcuCiiTMhf8r0pH/Mtyn/zjnvv8/7s//RvLZ/07z3P9X9N7/Tvjp/ySFcf9fIhb/jEk1/6Ff + Q/+pZ0j/rGpL/65sTP+xbU3/s29O/7RwT/+2cE//t3FQ/7dxUP+3cVD/t3FQ/7ZxT/+1cE//tG9O/7Ju + Tv+vbE3/rWtM/6poSv+lZUj/llY7/3Q5Jf9WIRL/q00F//C8XP/55qf/9t2a//fem//33pv/996a//fe + mf/33Zf/9t2U//bckf/2247/9tqK//XZhv/114H/9dZ8//TVd//003L/9NJs//PPZv/yzWD/8slZ//DF + T//uvUP/67U5/+qwM//pqy3u56cqRuenKgDmpioAAAAAAAAAAAAAAAAAAAAAAB/LgwAdyoIJIsyEpSbO + if8t1pn/NOGx/zvqx/9C8NX/SvPa/1Hz3P9a9N7/VPnq/yWMeP9hIxb/j0o1/6dkR/+vbU3/s3FQ/7Vz + Uv+4dFL/unZT/7t3VP+9eFX/vnlV/795Vv+/eVb/v3lV/755Vf+8eFX/u3dU/7l1U/+3dFL/tHJR/7Fv + T/+tbE3/nl1B/30/Kf9fJhT/sVIG//LCZf/66K7/+OGh//jhov/44aH/9+Gg//jhn//44J3/+OCb//ff + mP/33pT/992R//bbjP/22oj/9tmD//XYfv/11nn/9NRy//PSbf/z0Gb/8sxf//HIVv/vwUr/7Lg9/+uy + Nf/prS/956grbeeoLADmuSoAAAAAAAAAAAAAAAAAAAAAACDMhQAfzIQSI82HvSjRjv8v2qL/NuW7/z7t + zv9F8df/TfLa/1Xy3P9d893/W/rr/ySbh/9hIxb/kUg0/61oS/+2dFP/unhW/716WP/AfFn/wn5a/8N/ + W//EgFv/xoBc/8aAXP/GgFz/xoFc/8WAXP/Ef1v/w35a/8F8Wf++e1j/vHlX/7h3Vf+1dVX/qGdJ/4lJ + MP9tLhn/t1cI//PIbv/66rP/+OOn//nkp//55Kf/+eOm//njpf/446P/+OKh//jhnv/44Jv/9+CX//fe + kv/33Y7/99yJ//bahP/22H//9dd5//TVc//002z/89Bm//LLXf/wxVL/7rtC/+u0OP/prjL/6Kkti//0 + hADmpioAAAAAAAAAAAAAAAAAAAAAACHNhwAgzYYZJM6KzynTlP8x3qv/OOnC/z/v0v9H8dj/T/LZ/1fy + 2/9f89z/ZPrp/yeynv9cJxn/kUQx/7JrTv+8elj/wYBd/8SCX//HhGD/yYVh/8uHYv/MiGL/zYhj/82J + Y//NiWP/zYlj/82IY//Mh2L/yoZh/8iFYP/Fg1//woBe/79+XP++fl3/s3NT/5hWO/9/OyL/vVwK//TN + d//667f/+eWs//nmrf/55az/+ear//nlqv/55an/++en//roqv/55aX/+OKc//jhmP/44JT/99+P//fd + if/324T/9tl///XXeP/01XL/9NJs//POY//xyFj/7r9I/+u1O//przP/56oupeamKQnmqCsAAAAAAAAA + AAAAAAAAAAAAACLOigAhzYkdJNCN2SvWmv8y4bH/OevH/0Hv0/9J8df/UfLY/1ny2v9h89v/a/nm/zLN + u/9TMiP/jjsr/7RpTf/Cfl3/x4Zj/8qJZf/Nimb/0Ixo/9KOaP/Tj2n/1I9q/9SQav/UkGr/1JBq/9SP + av/Tjmn/0Y1o/86LZ//MiWb/yYdk/8aFY//EhGP/vX9f/6hlSP+SSiv/w2MM//bTf//77Lv/+eew//ro + sf/66LH/+uiw//ror//56rH/16xv/+29bv/877n/+eSi//njnf/54pn/+OGU//jfjv/33Yn/9tuE//bZ + fv/113f/9NRx//PRaP/xy13/7sJO/+u3Pf/psDX/6KswvOeoLBLnqS0AAAAAAAAAAAAAAAAAAAAAACPP + jAAiz4sfJdGQ3ivZn/8y5Lf/OuzK/0Lw0/9K8db/UvHX/1ry2f9i8tr/bvbh/0Pm1v9ESzn/iDEj/7Fi + SP/GgWH/zYpo/9GPbP/TkW3/1ZNu/9iUb//ZlXD/2pVw/9qWcP/alXD/2pZw/9qWcP/ZlXD/1pRv/9SS + bv/SkG3/z45r/8yMaf/JiWj/xYdn/7d3Wf+kWzr/yGoO//fYh//77b//+um0//rptf/66bX/+um0//3u + t//Uuoz/cz4o/7RkG//84J3/+uuz//nlov/55J7/+eOZ//jhk//4347/992J//bbg//12Hz/9NZ1//PS + bf/yzWL/78VT/+y5QP/qsTb/6KwxzeeoLhnnqS4AAAAAAAAAAAAAAAAAAAAAACPQjgAi0IwfJdOT3yzb + o/8z5br/O+zM/0Lv0/9L8NT/U/HW/1vx2P9j8tn/bfPc/1r35/8zemb/gCsc/6lZP//IgWD/0Y9t/9aV + cv/Yl3P/25l1/92adf/em3X/3pl0/96Xcf/el3H/35p0/9+bdv/em3b/3Jt2/9qZdf/Yl3T/1JVy/9GS + cP/OkG//yoxs/8KFZ/+2b0z/znER//jdj//77sL/+uq4//rruf/667n//O+7/+bOof+kcln/e0g3/3s5 + GP/hoEv//vK8//roqP/55qL/+eSd//njmP/44ZP/+N+N//fdh//22oD/9th5//TUcf/zzmb/8MdX/+26 + Q//qsTf/6Kwx1+epLhzoqi8AAAAAAAAAAAAAAAAAAAAAACPRjwAi0I4dJdSV2izcpv8z5r3/O+3M/0Lv + 0f9L79P/U/DV/1vx1v9j8dj/a/La/3D66P8wuKX/bDMg/55MM//EeFb/1ZNv/9qadv/dnnn/3596/+Gf + ev/inHX/3pBp/9GEXP/NgFj/2I1k/+Gcdf/ioHv/4aF8/96gfP/cnXr/2Zt4/9aZdv/SlnT/z5Nz/8uR + cv/DgFv/0nkS//nilv/778X/+uy7//rsvP/88L//6teq/7WGav+mclv/l2NO/3NBMf+pWxj/+9yW//vu + t//656b/+uWh//nknP/545f/+OGR//ffiv/23IT/9tp9//TWdf/z0Gr/8Mhb/+y8Rv/psjj/6Kwy2+ep + Lx7nqjAAAAAAAAAAAAAAAAAAAAAAACPSkQAi0Y8aJdWY0CvdqP8y5r3/Ou3L/0Luz/9K79H/Uu/T/1vw + 1f9j8df/avHY/3b13/9M6dn/Sl9I/5M+JP+4akb/1Y9p/92eeP/ho33/5KN9/+ahef/Rnnj/oYpn/5xl + QP+tXDP/wnJG/92UZ//mpHz/5aeB/+Omgf/hpH//3qJ+/9qffP/XnHr/05l4/8+Xd//Jjmz/0noa//jc + fv/99dD/++6///3xwv/t3LD/vZF1/6x6Yv+se2P/pXRd/4hYRv+AQB7/46ZS//7zwP/66Kr/+uek//rm + oP/55Jr/+OKU//jgjv/33Yf/9tqA//TWeP/y0W7/8Mle/+y8Sf/psTn/6Kwz2eepMB3nqTEAAAAAAAAA + AAAAAAAAAAAAACLTkgAh0o8UJdeZwCrdqf8y5r3/OezJ/0Htzf9J7s//Ue/R/1nv0/9h8NX/afHX/3Ly + 2f9v+ej/M6yW/3w+I/+nVzb/zH9Y/9+cdv/lpH7/5KmD/73Msf+Z6df/aOve/zOznf+EWzT/s2Az/9aJ + W//opXz/6auG/+erh//lqYb/4aeF/96kg//boYH/155//9Obff/PmXz/zIVO/+WpOf/456n/9+rD/+bN + qf/ClXn/tIFp/7OCav+wf2j/rHxm/5trVv97Rzb/vHAl//7qrf/77LP/+umn//roo//55p3/+eSY//jh + kf/33or/9tuD//TXe//y0nD/8Mlh/+y9Sv/psTn/6Kwz0ueoMBrnqTEAAAAAAAAAAAAAAAAAAAAAACHU + lAAf0pALJNebqSneqf8w5rz/OOvI/z/szP9H7c3/T+7P/1fv0v9f79P/Z/DV/27w1/959d7/Ueva/0hx + Vv+YRSX/t2pC/9mOZf/mo3v/uNK2/5H25P+T9uL/mPnp/0Dn2/9FgV//r1os/9GDVf/qp33/7K+L/+qw + jf/nr43/5ayL/+Gqif/ep4f/2qSF/9ehgv/SnoD/zpp//8uTbf/OnG//yp2A/8CPdv+7inL/uYly/7aH + cP+zhG7/r4Fr/6d4Y/+HWUn/mFEc//bNgf/88b3/+uqq//ropv/55qD/+OSa//fik//334z/9tuF//TY + ff/y0nL/8Mpi/+y8Sv/psDn/56szw+anLxXmqDAAAAAAAAAAAAAAAAAAAAAAACHVlgAWx3oBI9ickCjd + qP8v5bn/NurF/z3ryf9F7Mz/Te3N/1Xuz/9d79H/ZO/T/2vw1f9z8df/d/jk/z3LuP9tVjb/pVMt/8Zz + Rv/At5P/kPPf/5D03/+R897/lvXi/1zt4P80lXX/qF0v/8yBUv/qqH7/7rSQ/+y2lP/qtZP/6LKS/+Sw + kP/hrY7/3qqM/9qnif/WpIf/0qGF/86ehP/JmYH/xpZ9/8OUe//Aknr/vY94/7qNd/+4inX/s4Zx/62B + bP+Xalj/gUcp/+KpWP/+9ML/+uus//npp//556L/+OWc//jilf/3347/9duH//TXf//z0nP/8Mli/+y7 + Sv/orzj/56ozrOanLgzmqDAAAAAAAAAAAAAAAAAAAAAAACHWlwAj2Z4AIticdSbdpv8t5Lf/NOnC/zvr + x/9C7Mn/SuzL/1Ltzf9Z7s//Ye7R/2jv0/9u8NT/d/HY/2335f82sJj/gU0p/6V2UP+Q587/i/Tf/43y + 3f+N8t3/kfTe/2zx4v8no4b/nmAy/8d8UP/opn3/8LeU/+66mf/suZn/6raY/+e0lf/jsZT/4K6R/9yr + j//ZqI3/1aWL/9GiiP/Nn4b/ypyE/8aZgv/Dl4D/wJR+/72SfP+7kHv/t4t3/7GGc/+hdWP/d0g1/8qH + N///8r3/++yw//rqqf/556T/+eWd//jil//334//9tuI//TXgP/y0XP/8Mhi/+u5SP/nrjf/5qkykOSd + JQHmpzAAAAAAAAAAAAAAAAAAAAAAACHWlwAh2JwAIdicUCTcpfIq4rP/Mei//zjqxP8/6sb/R+vI/07s + yv9W7Mz/Xu3O/2Xu0f9s79L/cu/U/3vy2f9l8uD/RKeN/4TGq/+G9t//ifLa/4ry2v+K8tr/i/Lb/3f0 + 4/8asZj/kGQ3/8J4Tf/lpHv/8LqX//C9nv/uvJ7/67ud/+i4m//ltpn/4rOX/96wlf/brZP/16qQ/9On + jv/Qo4z/zKGJ/8meiP/Gm4b/w5mE/8CXgv++lYD/upF9/7SKd/+me2n/dEw//7JvJv/+67H/+u20//rq + qv/556X/+eWe//jil//235D/9duI//PWgP/yz3P/7sZg/+q3Rf/mrDb+5akycOWpMgDkpDAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAg2J0AINibJiLbouIo4a//L+a7/zbpwf8+6sT/RerG/03ryP9U7Mr/XO3M/2Lt + zv9o7s//bu/R/3Pv0/978tn/c/Lb/33x2P+D8df/hPHY/4bx2P+G8dj/h/HY/3/14v8fv6j/f2s//751 + Sf/foXf/8byZ//DBov/vwaP/7L+i/+q9oP/nup7/47ec/+C0mv/dsZj/2a+V/9ask//SqJH/z6aP/8yj + jf/IoYv/xp6J/8OciP/Bmob/vZaD/7ePfP+nfWv/c09E/59fIv/75KT/++63//rpqv/556X/+OWe//fh + l//13pD/9NqI//PVf//xznH/7cNd/+m0Qf/mqjTu5acwRuWnMQDlpjAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAf2JwAHteaDSHaoL0m36v/LuS3/zTnvv876MH/QunD/0nqxf9Q6sf/V+vJ/17sy/9k7M3/au3O/2/u + 0P907tH/ee/T/3vv1P9979T/f/DV/4Dw1f+B8NX/gO/V/4D03v8szLf/anRK/7tyR//YnHP/8Lya//LE + pf/wxKf/7cKm/+vApf/ovqP/5buh/+K4n//ftp3/27Ob/9iwmf/VrZf/0qqV/86ok//LpZH/yaOP/8ah + jv/En4z/wJuI/7mSgP+le2r/ck9F/5JWIv/43Zv/+u+5//npqv/456X/+OSe//bgl//13I//89iH//LT + fv/wy2//7L9Z/+iwPf/mqDPX5aYwG+WmMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAAbpbASDZ + n34k3af/K+Ky/zHluv83577/PujA/0bpwv9N6cT/VOrG/1rryP9g7Mr/ZuzM/2vtzf9w7c//c+7Q/3fu + 0f957tL/eu7S/3vu0v9779L/eu/R/3zz2f831sP/UX5W/7dvRf/QlnD/7rua//LGqf/wx6z/7sWs/+zE + q//pwan/5r+n/+O8pf/guaP/3beh/9q0n//WsZ3/066b/9Gsmf/Oqpf/y6iV/8mmlP/Ho5L/w5+O/7qT + gv+fdGX/bU1F/4lRIP/325j/+u65//noqf/45aP/9+Kc//bflf/02o7/89aG//HQe//vyGr/67tR/+as + OP/lpjGf5KMtBuSlLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAHtmdAB7ZnUIh26PuJ+Ct/y7k + tf815rv/POe+/0Pov/9K6cL/UenE/1fqxf9d68f/Y+vJ/2fsy/9s7Mz/b+zN/3Ltzv907c//du3P/3bt + z/927c//de3O/3nx1P9B3sr/OIhj/7BtQ//JkWz/6rmY//HIrP/wyrD/7smw/+zHr//qxa3/58Ks/+TA + qv/hvqj/37um/9u4pP/YtqL/1rOg/9Oxn//Rr53/zq2b/8yrmf/JqJf/xaOS/7aOfv+XbWD/ZUhA/4ZQ + H//33Jv/+u23//jnp//35KH/9+Cb//bdlP/02Iz/8tOE//DNd//txGT/6bVJ/+WoNPrjpDBc5KQxAOOj + LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAHNibABvYmQ8f2qDAJd6p/y3isf8z5Lj/Oua7/0Hn + vf9I57//TujB/1Tpw/9a6cX/YOrH/2TqyP9o68n/bOvL/2/sy/9w7Mz/cezM/3Lszf9x7Mz/cOzM/3Pu + z/9O5M7/LpNx/6dsQv/CjGb/5LaU//HKrv/wzbT/7sy0/+zKs//qyLL/6Maw/+XErv/iwaz/4L+q/928 + qf/auqf/2Lil/9W1pP/Ts6L/0LGg/86vnv/LrJv/xKKR/62EdP+MZVj/WD83/4lUHv/54aL/+euz//jl + pv/34qD/9t6Z//Xakv/z1or/8dCA/+/Jcv/svl3/565A/+SlMdTjoi4f46IuAOOjLgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAG9iZACPfpwAf2p9vI92l/yrgrf8x47T/OeW4/z/lu/9G5r3/TOe//1Lo + wf9Y6cP/XOnE/2Hqxv9l68f/aOvI/2rryf9s68n/bezK/23ryv9s68n/a+vJ/2zsyv9a6dL/JqCB/5ps + Qv+7hmL/3bCQ/+/Kr//wzrf/7s64/+zMt//qy7b/6Mm1/+XGs//jxLH/4MKv/96/rv/bvaz/2buq/9e5 + qf/Vt6f/07Wl/9Cyo//Mrp7/vpmJ/6J3av99W0//STEr/5hfIP/86Kz/+Oet//fjo//3353/9duV//TX + jv/y0of/8M18/+3Fa//quFP/5ag3/+OiL4naixcB4J0rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAHtqeAB7ZngAe2Z0jINui1ybeqf8v4bD/N+O2/z7luf9F5rv/Sue9/1Dnv/9W6MH/W+nC/1/p + xP9i6cX/ZerG/2fqx/9o6sf/aerH/2jqx/9o6sf/ZurG/2Xqxf9g7NH/HK2Q/4huRP+2gV7/1aqL/+3J + sP/v0Lr/7tC8/+zPvP/rzrv/6cy5/+bJuP/kx7b/4sW0/+DDs//dwbH/27+v/9m9rv/Xu6z/1bmq/9K1 + p//JqZn/s4p7/5RrX/9oTkT/TyYZ/8h9NP/867b/9+Sn//bgoP/13Zn/9NmS//LUi//wz4L/7sh2/+u/ + Yv/nr0b/46My4+KfLjLioC8A4qQuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHticABzY + mgAy58EAH9uhfyTdp/8t4K3/NeOz/z7kt/9E5br/Sea8/0/nvv9U58D/WejC/13pw/9g6cT/YunF/2Pq + xf9k6sX/ZerG/2Xqxf9j6sX/YunE/1/pw/9i7c7/Gbmf/3RxSf+yfFr/zKKF/+rHrv/v0b3/7tPA/+zR + wP/r0L7/6c69/+fMvP/lyrr/48i5/+HHt//fxbb/3cO0/9rBsv/YvrD/1rut/9CzpP+/mon/o3lr/35c + Uf9ROTH/jC0G/+ijV//56rf/9uCi//XdnP/02ZX/89WO//HQhv/uy33/7MNt/+m3Vv/kpzn/46AvjOCX + JgPinS0A4p8tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3ZnAAg26EAH9qgIyPd + pNMq36r/M+Kw/zzjtf9D5bn/SOa8/07nvv9T6MD/V+jB/1vpwv9e6cT/YOnF/2Hpxf9i6cX/YunF/2Hp + xP9g6cP/XejC/1rnwP9g7Mn/JMWr/2B4UP+vd1T/w5t//+XErP/u0r7/7tTC/+zUw//r0sL/6dDB/+fP + wP/lzb7/48u9/+LJu//gx7n/3cW3/9vDtf/ZwLL/1Lmr/8akk/+vhHX/jWZb/15IP/91MBT/xkcG/+/F + fv/35a//9d2d//TZl//y1ZD/8dGJ/+/Mgv/txnX/6r1i/+atRv/ioDHW4Z0tKOKeLgDini0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2p8ALuGtACTcpGkp3qn4MuGv/zrj + tP9C5Lj/Sea8/07mvv9T58H/V+jC/1row/9d6cX/XunF/1/pxf9g6cX/YOnE/1/pw/9c6ML/WejB/1bn + v/9b68T/L9C1/0l/Wv+rcU//upV6/9+/qP/t0sD/7dXF/+zVxv/r1Mb/6dPF/+fRxP/m0ML/5M7A/+LM + vv/gybz/3se6/9vEt//XvbD/y6qa/7aMfP+YbmL/alBH/2c2IP+5OwL/0Wgd//Xcov/13qP/89mY//LV + kv/x0Iv/78yE/+3He//rv2v/57NT/+OkN/fhnS5o5KQ1AOGcLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf2qAAJdylACTbpBEq3qmvMeCu/zrjtP9C5bn/Sea9/0/n + wP9U6ML/V+nD/1vpxf9d6sb/XurG/1/qxv9f6sb/XurF/13pxP9a6cL/V+jA/1Pnvv9W6cH/ONm8/zCJ + Z/+jbUn/s450/9e3ov/q0cD/7dbI/+zWyf/r1sj/6dXI/+jTxv/m0cT/5M/D/+LNwf/gyr7/3ca6/9i+ + sP/Lq5v/uY9//55yZv9xVEz/Zzkl/7dCCP/FQwH/35pP//birf/z2Jj/8tST//DQjP/vzIX/7cd+/+vB + cf/ot13/5KhA/+GeL6PgmisO4JwtAOGdLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAFOCmACreqAAr3qk0MeCu2Tnjtf9C5br/See+/1Dowf9V6sT/WerF/1zr + x/9e68j/YOvI/2DryP9f68j/XurG/1zqxf9Y6cP/VejA/1Dnvv9Q6L7/P9+//yGVdf+YaUX/rYdt/86v + mf/oz77/7NbH/+vXyv/q1sn/6NXI/+fTx//l0cX/5M/C/+HMv//dx7n/1rur/8mmlf+3jHz/nXFl/3FT + S/9vPSP/ukgH/8lKBP/FVxD/78qK//PaoP/x05H/8M+M/+7Lhv/sx3//68F0/+m5ZP/lrEn/4Z8yzOCZ + KyXgmywA4Z4vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAJNmfAC3dqQAR1IwBM+CvjDrjtv9D5rz/S+fA/1LpxP9X6sf/XOvJ/1/ryv9h68v/YuvM/2Lr + y/9h68r/X+rJ/1zqx/9Y6MT/VOfB/0/mv/9M5rz/RePB/x6hg/+JZ0P/qH9k/8Wlj//jybj/6dPF/+rV + yP/p1Mj/59PH/+XRxf/jzsL/4Mm8/9rAsv/RsqH/w52L/7KEdv+Va2D/bk5E/4JCHf/FUAj/zVMG/75H + Av/ZkEb/89uj//DRkf/vzYv/7smF/+zFf//rwXb/6bpn/+avUP/ioTfd4JkrQeCdLwDitD8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAINaWACrd + pwAo26M0MuCu2TzkuP9G57//TejD/1Tqx/9a68r/X+zN/2Lszv9k7M//Ze3P/2Xsz/9j7M7/YevM/13q + yf9Z6cb/VOjD/07nwP9K5rz/SubB/xqtj/91ZUT/o3VY/7qZgv/cwK7/5c6//+XQwv/kz8H/4su9/9/G + t//Zvq3/0rKg/8mij/+7jn7/pXds/4RdVf93SjT/o00T/9BaCP/NWAj/wU4F/8VhF//tx4n/8NKV/+7L + if/tyIT/7MR+/+rAd//ouWn/5rBV/+KiO+Tgmi1T79dqAN+VKADgmSoAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2JwAI9mfACHYnRYp26W0NOGx/0Dm + vP9J6ML/UerG/1jryv9e7M3/Yu3Q/2bu0f9o7tL/ae7S/2ju0v9m7tD/Y+3O/1/sy/9a6sj/VenF/0/o + wv9J577/TOnC/xe5nP9fZUn/nWVG/6qBZf/NqI//2rqk/9q7p//YuKP/1LKd/86pk//Gm4j/uot8/6Z4 + bP+NYVf/gVE7/5tSHf/HXwz/1WMI/8xcCf/EVAf/vVAG/96kYP/w0pj/7cmH/+zGgv/rwn3/6r52/+i5 + av/lr1b/4qM+4t+aL1jUbwAB35YpAN+XKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2JwAAMl6ASTaoXos3qr9OeS3/0XowP9O6sb/VuvK/1zs + zv9j7tH/Z+7T/2rv1f9t79b/be/W/2zv1f9q79T/Z+7S/2Ltz/9d7Mz/WOrI/1Lpxf9N6MH/UOrE/x7G + qP9IaVL/jEs5/5NhTP+zgWz/wpN+/8GSf/+7jHv/s4Jz/6d1aP+aZ1n/kFxG/5NYMP+rXhr/y2kN/9lt + Cv/SaAv/ymAK/8RZCf+8TwX/0oZA/+7Mkf/sxoX/68N//+rAev/pvHP/57Zo/+SuVf/hoj/W35ovTNNi + AAHflioA35crAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAg2qAAHtmeGCbdpsgy4rH/Pua9/0npxP9T68r/Wu3O/2Hu0v9o79X/bfDX/3Hx + 2f9y8dr/c/Ha/3Lx2f9v8Nf/a+/V/2bu0v9h7c//W+zM/1bryP9S6cX/VezG/y7Ttv84clP/jzMU/5JG + Hv+gWiz/p2U1/6dmNf+nZjD/qmYp/7FoIP+9bhf/zXUQ/9l5Df/beAz/1XEM/85qC//JYwr/xF0K/7xT + Bv/KdjL/6sKH/+vEhP/qv3v/6b13/+e5cP/ms2T/5KtS/uGhPrrfmTA0569OAN6VKgDflywAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAj3KMAH9qfCyvfrJs147X9QOa+/0rpxf9U68r/XO3Q/2Tv0/9r8Nf/cfHa/3Xy2/9389z/d/Pc/3by + 3P908dr/cPHY/2rv1f9k7tL/X+3O/1rsy/9W68n/WezJ/zzdwf8vhmb/pz0H/7tXCP/HbQz/znkO/9J+ + Dv/WgQ//2YMQ/9qCD//ZgA7/13wP/9N2Dv/QcQ3/zGsN/8hmC//EYAn/vFYG/8d0L//nu3//6sCA/+i8 + dv/nuXL/5rVr/+SwXv/jqE3u4KA9jN+XLhjgnDUA3I8iAN6WLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3JsALOCtAC7g + rxg14rVvP+W8nEjnw7BR6sjHWuzO3WLu0u5p8Nb2b/HZ+XPy2/128tz/d/Pd/3bz3f9z9N3/b/Pc/2rx + 2P9l79P/YO3P/1zszP9a68r/XezK/zrjyf87iGf/qEAG/7dYCv/CaQ3/yXMP/8x4EP/PehD/0HoQ/9B6 + EP/Qdw//znQO/8xwDf/Jaw3/xmcM/8FgCf+8WQj/yXo2/+a3e//pvXv/57hx/+a1bf/ksWT/46tW++Gl + SL/gnTpN3ZElBt+aMwDgmzUA3pUsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm3KcAOeW5AC3grgA14rUAPOO6Akbl + wQ1P6ccYV+vMI2Dt0i5n79ZBbfDYW3Dx2ndz8dyRdPHcp3Py27l04MffcN7D/2nny/9h7dH/W/HU/1fy + 0/9W8tP/TvLT/ynNtf95YDD/r0kF/7dbC/+/Zg3/xG0O/8dwDv/Jcg//ynMP/8pyDv/JcA7/yG0N/8Zq + DP/DZQv/vl4G/71hEv/Ri0n/5rZ6/+e3c//lsmr/5LBj/+OrWf3ipk7N4KFCbN+bNRbjpkoA35kyAOCe + PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvkuQAx4rAAPuW8AEfmwQBP6ccAWOzNAGDt + 0gBn79YAbvDZAHTy2wB389wAKf//AHLkywqKg1kukHJEgZJsOdKPdT/7iIRR/3+WZ/93o3b/a5Ro/4Zk + Lv+tSgb/sVUJ/7ddC/+8Ywz/v2YN/8FoDf/Cag3/w2oN/8RqDf/DaQ3/wWYM/75hCf+9YQ3/x3ct/9uh + Yf/mtXP/5LBn/+OsX//iqVfx4aVOwOCiRWrfnDoc46tUAOCeOgDckCQA3pgxAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABx8dsAbf/wAHXcwgCGkWcA/wAAAK8vAB+rPgBfq0QAq6tGBeGsSAb3r0oF/7BOBf+vVAr/s1gK/7Zb + C/+4Xwv/umEM/7xiDP+9Ywz/vWIL/7xhCv+8YQr/vmUR/8d3LP/Xl1T/4q1p/+OsYv/hp1bu4aVRz+Cj + TI3goEVI3ps4EeKvXgDfnj0A4q5VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKcv + AACjXAsAoj0IAKdIBQCpQQAAqFcOCapTCyirUgpdrVIJjK5TCbewVQncslcK7rNYCvO0Wgr3tVsK+rdc + Cvy4Xgz8vGMR+8JvHvjNgzX12ZlP8OGmXOXiplfH4KJNn9+gSHbfnkRD350/FtuPIQPgoUYA3pw7AN6c + PADgoEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKlN + CACpTQgAqU8JAKpQCgCsUQkAslMIAa5TCRCwVAkfsFUKMLBVCkawVQlZtFsMab1lE3TEbxx1zXwncNeP + PGDenExP4aNRON+dQyTdlzQW3JEpB+ClUADfn0YA4J9FAN+dPwDfmDMA35s5AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK1R + CQC1WQkArlIJAK5TCQCwVAkAsVUKALJXCgCzWQoAs1gJALVZCgC4Xg4AwGsbANCHOQDgpFkA46lcAN+f + SQDemj0A3pk7AN6ZOwDemTsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8AAAAAAAP/8AAAD/4AAAAAAAD/8A + AAD/AAAAAAAAAf8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8A + AAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAD8A + AAD/gAAAAAAAAA8AAAD/gAAAAAAAAAcAAAD/wAAAAAAAAAcAAAD/AAAAAAAAAAcAAAD/AAAAAAAAAAcA + AAD+AAAAAAAAAAcAAAD+AAAAAAAAAAcAAAD8AAAAAAAAAA8AAAD8AAAAAAAAAB8AAAD4AAAAAAAAAD8A + AADwAAAAAAAAAB8AAADwAAAAAAAAAB8AAADwAAAAAAAAAA8AAADgAAAAAAAAAA8AAADgAAAAAAAAAAcA + AADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADAAAAAAAAAAAcAAADAAAAAAAAAAAcAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADgAAAAAAAAAAMAAADgAAAAAAAAAAcA + AADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADwAAAAAAAAAA8AAADwAAAAAAAAAA8A + AADwAAAAAAAAAA8AAAD4AAAAAAAAAB8AAAD8AAAAAAAAAD8AAAD8AAAAAAAAAD8AAAD+AAAAAAAAAH8A + AAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD8AAAAAAAAAf8AAAD8AAAAAAAAA/8AAAD8AAAAAAAAB/8A + AAD8AAAAAAAAD/8AAAD8AAAAAAAAH/8AAAD8AAAAAAAAf/8AAAD/AAAAAAAA//8AAAD//8AAAAAH//8A + AAD///AAAAAP//8AAAD///4AAAA///8AAAD////AAAP///8AAAD///////////8AAAD///////////8A + AAA= + + + + 271, 17 + + + 55 + + + + AAABAAEASEgAAAEAIACIVAAAFgAAACgAAABIAAAAkAAAAAEAIAAAAAAAAFEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAA + AAIAAAACAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAACAAAAAgAAAAIAAAACAAAAAgAA + AAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAABAAAAAgAAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAkAAAAKAAAADAAAAA4AAAAOAAAADwAA + ABAAAAAQAAAAEAAAABEAAAAQAAAAEAAAABAAAAAPAAAADgAAAA0AAAAMAAAACgAAAAkAAAAIAAAABwAA + AAYAAAAFAAAABAAAAAIAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAwAAAAMAAAAFAAAABwAA + AAkAAAAMAAAADwAAABIAAAAVAAAAGAAAABoAAAAdAAAAIAAAACMAAAAlAAAAJgAAACcAAAAoAAAAKQAA + ACkAAAApAAAAKAAAACcAAAAlAAAAJAAAACIAAAAfAAAAHAAAABoAAAAXAAAAFAAAABEAAAAPAAAACwAA + AAgAAAAHAAAABQAAAAMAAAACAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAMAAAAFAAAABwAAAAoAAAANAAAAEgAAABYAAAAbAAAAIQAA + ACYAAAArAAAAMAAAADYAAAA7AAAAPgAAAEIAAABGAAAASAAAAEoAAABMAAAATQAAAE0AAABNAAAATAAA + AEoAAABHAAAARQAAAEEAAAA9AAAAOQAAADQAAAAuAAAAKgAAACQAAAAgAAAAGgAAABUAAAARAAAADQAA + AAoAAAAHAAAABAAAAAMAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAEAAAADAAAABQAAAAgAAAALAAAAEAAAABYAAAAcAAAAIwAAACsAAAA0AAAAPAAAAEUAAABNAAAAVQAA + AF0AAABkAAAAagAAAHEAAAB2AAAAeQAAAH0AAACAAAAAgQAAAIEAAACBAAAAfwAAAHwAAAB4AAAAdAAA + AG8AAABoAAAAYQAAAFoAAABSAAAASgAAAEIAAAA5AAAAMQAAACkAAAAhAAAAGgAAABUAAAAPAAAACgAA + AAcAAAAEAAAAAgAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAMAAAAFAAAACQAA + AA4AAAAVAAAAHAAAACYAAAAwAAAAOwAAAEYAAABSAAAAXgAAAGoAAAB2AAAAgQAAAIsAAACVAAAAnwAA + AKcAAgCtAAQCsgAFA7YABQS5AQUEugEGBLoBBgS6AQUEuAEEA7UBAgKxAAAAqwAAAKQAAACcAAAAkgAA + AIgAAAB+AAAAcgAAAGYAAABaAAAATgAAAEMAAAA4AAAALAAAACMAAAAZAAAAEgAAAAwAAAAIAAAABAAA + AAIAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAQAAAAIAAAADgAAABYAAAAfAAAAKwAA + ADkAAABGAAAAVQAAAGMAAAByAAAAgQAAAJAAAACfAAIBrgAWCb8BKxHNAT8b2QJYLOQCaz3sAXNG8AF5 + SfMCfUv1BoBM9QmDTvUMhVD1D4JQ9BB5S/IPaEDtDE8v5gg2H9wFIRPSAgwHxAAAALUAAACpAAAAmwAA + AI0AAAB9AAAAbQAAAF4AAABQAAAAQQAAADQAAAAnAAAAHAAAABMAAAAMAAAABgAAAAMAAAABAAAAAQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAYAAAALAAAAEwAAABwAAAApAAAANwAAAEcAAABXAAAAaAAA + AHkAAACKAA0FoQEqEbsBUSHWAnIu6gKHOPUCm0n8AqJb/wGaX/8BkFf/AI1R/wCOT/8AkU//AJJQ/wGU + Uv8Cl1P/BJdU/waWVP8IkVD/ColJ/wp+Qv8Kbjj8CVwv9QlJJ+kGLBjWAxMLwAABAakAAACWAAAAhQAA + AHQAAABjAAAAUgAAAEIAAAAzAAAAJQAAABkAAAAPAAAACAAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAABAAAAAwAAAAYAAAALAAAAFAAAAB8AAAAtAAAAPQAAAE8AAABfAAAAcQEdC5ECUyC/Anow5AKU + O/kCnj7/AqZI/wKjW/8Bj1n/AH9L/wB6Q/8AekH/AHpA/wB7QP8Ae0D/AHxA/wB+Qf8Af0H/AIBB/wB9 + P/8Adzr/AWwy/wFgKf8BWCX/AVgm/wJaKv8FXS7+B1Yt9AZCJN0DIxO4AQgElQAAAH4AAABtAAAAWwAA + AEkAAAA4AAAAKAAAABwAAAARAAAACQAAAAUAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAA + AAUAAAALAAAAEwAAAB4AAAAsAAAAOwAAAEsBIgxuAmEkrgOJM+cDmTr9A548/wOfPf8CplT/AZdf/wB6 + Sf8Abjr/AGo3/wBnNP8AYzH/AGAu/wBeLP8AXSv/AF4q/wBfK/8AYCv/AGEr/wBeKv8AWCb/AE4g/wBC + Gv8FPBb/HUcW/yhOGP8aTxz/Ck4i/wVRKP8BUSv4AEQl2QAoF6MABwVxAAAAVwAAAEcAAAA2AAAAJwAA + ABoAAAAQAAAACAAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAHAAAADwAA + ABgAAAAiABAGNwJiJIEEijPXBJg5/QScO/8EnTv/BKFA/wOlXf8BiFf/AGw6/wBiMf8AWyz/AFIl/wBL + If8DRh7/C0Md/xNCHf8ZQR3/HEIf/x1EH/8cRB//F0Qd/w4/Gv8FOBb/AC4Q/xYuDf+MaQ3/zpIN/9OQ + DP/IiAz/rXwO/4pvEv9gZBf/P1we/yhWI/YRSSHHASkVdQAAAT4AAAArAAAAHQAAABMAAAAMAAAABgAA + AAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAFAAAACgAAAA4DViAzBYgyogWX + OfQFmzz/Bp09/wafPv8GpET/A6Fg/wB7Tf8AYTD/AFco/wNLIv8PQR7/Ijod/zg2Hv9INCH/VDQj/1w1 + JP9iNib/Zjgo/2k6Kf9pPCr/ZTwq/1g2Jv9ELR7/MCQX/4pRC//snA7/6aEO/+aaDf/mlwz/6JQM/+mS + C//njgv/3okL/82EDf+xfhH/nncT6aJvDqCqZwdkn2EHQpJYByVQLwMMAAAAAf/pEwDgigsA3IYLANyF + CgDbgwoA3IQKANuDCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQEAAAACAAAAAwaHNDwGlzrCB5w8/weePv8IoEH/CKJB/win + SP8EomL/AHJE/wBXKf8JSiL/IT0e/z4zHv9SLh//Wywe/14sHv9eLR3/Xy0e/2AvH/9iMCD/ZDMi/2c1 + I/9oNST/ZjUl/10vIP9MJBr/VygU/8doCv/nnxL/5Z8S/+SbEP/kmBD/4pYP/+KVD//ikw//45IO/+WR + Df/nkQ3/6JAM/+SPDP/gjAz734sL6t2KC8rdiAuq3YgLht6IC1nehwsx3IYLG9uDCgzikgsA3IQKANuC + CgDagQoA2oEKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAACKNCAAm0RgAP/4kAB5k8RQecPtQInz//CaFC/wmjRP8KpUb/CqlK/wamZP8AbkH/CE4k/yc+ + IP9JMB7/WCoc/1koGv9XJxj/VycY/1goGf9aKhr/XSwc/18uHf9hMB//ZDIh/2Y0Iv9mNCP/YzMi/1cr + HP9CHhT/WSYN/8poCf/noRX/5aAV/+ScE//kmhP/45kT/+SYEv/klxL/5JcR/+SWEf/klRH/45UQ/+OV + EP/jlA//45MO/+KRDv/hkA3/4I4N/+CMDPffiwvt3okL092HCqzchQqH3IMKYtuCCiPKdAAA2YAJANmA + CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACKBCAAqh + QwAIn0BHCZ9B3QmhQ/8KpEb/C6ZI/wyoS/8Nq0z/CK9n/wNzSP8cRCH/RzMg/1sqHf9ZJxn/ViYX/1Ym + Fv9YJxf/WigZ/10rGv9gLRz/YzAe/2YyIP9oNCL/azck/205Jv9sOCX/aDYk/1krHP9CHRT/WyYM/8pm + Cf/noxn/5aAY/+WdF//lnBb/5JsW/+SaFv/kmhb/5JoV/+SaFf/kmRT/5JkT/+SZE//kmRL/5JgR/+SX + EP/jlhD/4pUP/+GTDv/hkQ3/4I8M/9+NDP/eigv/3YcL+tyECtHbggs93YQMANmACgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAymSQALo0UAC6RHAAqiRD4Ko0XcC6RH/wyn + Sv8NqUz/DqtP/xCsUP8Ntmb/CYNZ/y85If9XLR7/XSob/1opGf9bKRj/XCoY/18rGv9hLRv/ZC8d/2Yw + Hv9nMiD/ajQh/2w2I/9uOCT/cDom/3E8J/9wOyf/bDgl/1wtHf9DHhT/XygM/8xoCv/opB7/5qAc/+We + G//lnhv/5Z0a/+WdGv/lnRn/5Z0Z/+WcGP/lnBf/5ZwW/+WbFv/lmxX/5JsU/+SaE//kmhP/5JkS/+SY + EP/jlxD/4pUP/+GSDv/gkA7/3owN/9yGDP/bgQui2XwJB9p/CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+xVgAMp0oAC6VIKwumSM0Mp0v/DqpN/xCsUP8RrlP/ErBV/xK3 + X/8PnG//Nzcm/1gpG/9fLBv/YC0b/2IuHP9kLx3/ZjAd/2cxHv9nMR7/ZzEe/2gyH/9pMyD/ajQh/2w2 + Iv9uOCT/bzom/3A7J/9uOib/aDYk/1cqG/8+GhL/YCgK/85pC//ppyP/5qIi/+WgIP/loCD/5aAg/+ag + H//moB7/5qAe/+agHf/mnxz/5p8b/+afGv/mnhn/5Z4Y/+WdF//mnBb/5ZwV/+WbE//kmhL/45gS/+KV + Ef/hkhD/340P/9yGDf/bgAuN2HkIBNp+CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAADq5TAA2qTgAMqEsSDalMrw6qTv8QrVH/Eq9V/xOxWP8Vs1v/F7de/w+5ev8rTz7/UyMX/18u + Hf9mMR7/aDIf/2kzH/9pMyD/aTMg/2kzIP9pMyD/aTMf/2kzIP9qNCD/azUh/2w2Iv9uOCT/bzkl/3A6 + Jv9uOSb/ZzQj/1QoGf85GBD/YigJ/9BsDf/qqyr/56Qn/+ajJv/noyb/56Mm/+ijJf/ooyT/56Mk/+ej + I//noiH/56Ig/+eiH//noR3/56Ac/+agGv/mnxn/5p8X/+WdFv/lnBX/5JoU/+OXE//hkhH/34sP/92E + DdbbgAws24EMANd7CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq1SAA2t + UQIOrVJ5D65T+xGwV/8Us1v/FbVe/xi3Yv8auWT/GMR2/xWMbf9FIxn/Xiwc/2kzIP9rNCD/azQh/2w0 + IP9sNSD/bDUg/2w1IP9sNSD/bDUg/2w1IP9sNSH/bDUh/202Iv9uNyP/cDkl/3A5Jf9tOCX/ZTMi/1Em + GP82Fg7/ZCkI/9JxDv/srzH/6Kct/+imLP/opiz/6Kcs/+inK//opyr/6Kcp/+imKP/opib/56Yl/+il + JP/opSL/6KQg/+ejHv/mohz/5qEa/+agGP/lnxf/5ZwW/+SZFf/hkhP/34oQ5d2EDk3fjBAA2n4LANl9 + CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUumIAELNaAA+xWDwQslnlErRc/xW2 + YP8XuWP/Grpm/xy9a/8fxHX/E8SR/ytHOP9WJBb/aDMg/242Iv9uNiL/bjYi/242Iv9uNyL/bjci/243 + Iv9uNyL/bjci/243Iv9uNiL/bjYi/283I/9vOCP/cDkl/3A5Jf9tOCT/ZTIg/08jFv8yEw3/ZikG/9V0 + Ef/ttDj/6ao0/+mqM//pqzP/6asz/+mqMv/pqjH/6aow/+mqLv/pqS3/6akr/+moKf/oqCf/6Kcl/+im + I//opSH/56Qf/+ejHP/noRr/5p8Y/+SbF//ikxTq4IwSXc9gBgHcgw4A24AMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARtl4AEbVcDRG1Xq0Tt2D/Frlj/xm7Z/8cvWv/H8Fx/yLH + fP8h1pb/E5t+/0MiFv9hLx7/bjcj/3E5JP9xOST/cjkk/3I5JP9yOiT/cjok/3I6JP9yOiT/cjok/3I6 + JP9yOST/cjkk/3E5JP9xOST/cjol/3E6Jf9uOCT/ZDEg/00iFf8wEQz/aisG/9d5E//uuUH/6q88/+qv + O//qrzv/6q87/+quOv/qrjj/6q43/+quNf/qrTP/6q0x/+qsL//qqy3/6qsq/+mpKP/pqSb/6agj/+im + If/opR//56Ic/+WdGfjklxZ034QQAuCLEgDdhQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAABS8aAATuWMAE7liVRS5Y/UXu2f/Gr1r/x2/b/8hw3b/JMqC/yjUk/8c2qz/IFxJ/1Qi + FP9qNSL/czol/3Q7Jf91PCb/dTwm/3U8J/92PCf/djwm/3Y8Jv92PCb/djwm/3Y8Jv92PCf/dTwm/3U8 + Jv90PCb/dDwm/3M7Jv9vOST/YzEg/0whFP8uEAv/bywF/9p9F//wv0z/67RF/+u0RP/rtET/67RE/+y0 + Q//ss0H/7LNA/+uzPv/rsjz/67E5/+uwN//qrzT/668x/+utLv/qrCv/6aso/+mpJf/oqCP/56Uh/+eh + Hf3mnhqA4ZEYAeWcGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFb9tABS8 + aAAUu2cPFbxouBe9av8bv27/HsFy/yLFeP8my4X/KdSX/y7fqf8VwqH/NDEi/18sHP9xOiX/dz4n/3g+ + KP95Pyj/eT8p/3k/Kf96QCn/ekAp/3pAKf96QCn/ekAp/3pAKf95QCn/eT8p/3k/Kf94Pyj/eD4o/3Y9 + J/9xOib/ZTIg/0whFP8vEQv/dC8E/9yCHP/xxFb/7LhN/+y5Tf/tuU3/7blM/+y4S//suEn/7LhI/+y3 + Rv/stkP/7LZB/+y1Pv/stDv/67M4/+uyNP/rsDD/6q4t/+qrKv/qqif/6agk/+ilIf/moR7f5Z4dLOae + HQDmnx4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGsR3ABa+awAVvmtLF79t9BvB + cf8fw3T/I8Z6/yfMh/8r1pn/MN2n/y7nuf8Vl33/RiEU/2k0Iv93Pij/e0Eq/3xCKv98Qyv/fUMs/35D + LP9+Qyz/fkQs/35ELP9+RCz/fkQs/35ELP9+Qyz/fUMs/31DK/98Qiv/fEIr/3lAKf90PCf/ZzMh/00i + Ff8vEQv/ejIE/96HIf/yyGD/7r1W/+6+Vv/uvVb/7b1V/+29VP/tvVL/7bxR/+28Tv/tu0v/7bpJ/+25 + Rf/tuEL/7bc//+y2O//stDf/7LIy/+uvLv/rrSv/6qso/+moJf/npCL/5aEfh///mADmnRwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFsBvABS/bgQXwXChGsNz/x/Ed/8jx3v/KMyG/yzW + mP8w3qj/N+Ky/ynmwv8caFT/VSIU/3E7J/98Qyz/gEYt/4BGLv+CRy7/g0cv/4RIL/+ESC//hEgv/4VI + L/+FSS//hUgv/4RIL/+ESC//g0cv/4NHL/+CRi7/gUYu/35ELf95QCv/bDYj/1AjFf8xEQv/gDQE/+GN + Jv/zzmv/8MJf//DCYP/wwl//8MNf//DCXf/wwlv/8MFZ//DBV//vwFT/775R/+++Tf/uvUr/7rxG/+66 + Q//tuT7/7bY5/+yzNP/rsC//6a0r/+mrKP/oqCX/56Qi2OahICTmoSAA5aQjAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAZxncAGMN0ABjDcyoaxHXeHsV4/yLHe/8ny4T/LNSV/zHdp/8247T/PenC/yLc + wf8qRTP/YCkb/3hAK/+CRy//hUkw/4ZKMf+ISzH/iUwy/4lMMv+KTTL/ik0y/4tNM/+LTTP/i00y/4pN + Mv+KTDL/iUwy/4hLMv+HSzH/hkox/4NIMP9+RC3/cDkl/1MlFv80Egv/hTcE/+OSLf/10nX/8cZp//HH + av/xx2n/8sdo//LHZ//xxmX/8cZj//HFYP/xxF3/8MNa//DCVv/wwVL/8MBO//C/S//vvUb/7rpB/+24 + O//stDX/6rAw/+quLP/pqyj/6Kcl/uajI2nppyUA6qQkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAZxXYAG8V3ABrFdmQcxnj9Icd8/ybKgv8r0ZH/Mduk/zbjtP886ML/QvHU/xzJs/82LyD/aTIi/39F + Lv+ITDL/i04z/4xPNP+NUDX/jlE2/49RNv+QUjb/kFI2/5BSNv+QUjb/kFI2/5BSNv+PUTb/j1E2/45Q + Nf+MTzX/i040/4lMM/+ESTH/dT0o/1coGP84FAz/izoD/+WYNP/21n//8sty//LMc//yzHL/8sxy//LL + cP/yy27/8sps//HJaf/yyGb/8sdi//HGX//xxVv/8cRW//DDUv/wwU7/779I/++9Q//uuTz/7LQ1/+uw + MP/qrSz/6aoo/+emJbrloSIL5qIiAOajJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAax3gAGMd3BxzH + eaMfx3v/JMmA/yrPi/8w2J//NeGy/zvowv9C7s//Rfjh/xiynf9CJRf/cTgm/4ZKMf+OUTb/kFI3/5JU + OP+UVTn/lVY6/5ZWOv+XVzr/l1c7/5hXO/+YVzv/l1c7/5dXO/+WVzr/lVY6/5RVOv+TVDn/klM4/49R + N/+KTjT/ekEr/1wqGv89Fg3/kjwD/+eePP/32on/8857//PQfP/z0Hv/89B7//PPef/zz3f/8850//PN + cv/zzG//88tr//LKZ//yyWP/8sde//HGWv/xxVX/8cNQ//DASv/vvUT/7rk7/+uzNP/qsC//6a0r/+io + J+jnpCU556QlAOSoJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcx3sAG8d7GR7IfNciyX//KMyH/y7V + mP80363/Oue//0Duzv9H8tn/R/rn/xqdif9NIRT/eT4r/41PNv+VVTr/l1c8/5lZPf+bWz7/nFs+/51c + P/+eXD//n10//6BdQP+gXUD/n11A/59dP/+eXD//nVw+/5tbPv+aWj3/mFk9/5VWO/+QUzn/gUYu/2Et + HP9BGA7/mEAD/+mkQv/43pH/9NOE//TUhP/01IT/9NSD//TUgv/004D/9NJ9//TSev/z0Hf/889z//PO + b//zzWv/8sxm//LKYv/yyV3/8sdX//DFUv/vwkv/771D/+y3Ov/rsjP/6q8u/+iqKv/npydw660qAOWk + JgAAAAAAAAAAAAAAAAAAAAAAAAAAAB7KgAAdyX0AHch9QiDJf+0ly4P/K9GQ/zLbpf845br/PuzL/0Xx + 2P9N9N3/SPnp/x+Oev9VIRT/gEMv/5RUO/+cWz//nl1B/6BfQv+iYEP/pGFE/6ViRP+mYkX/p2NF/6dj + Rf+oZEX/p2NF/6ZjRf+mYkX/pGJE/6NhQ/+hYEP/n15C/5xcQP+XWT7/iEsy/2gwH/9JGw//nkMD/+ur + Sv/44Zn/9daL//XXjP/114z/9deL//XXiv/11oj/9daF//TVgv/01H//9NN7//TSd//00XP/889u//PO + af/zzGT/8ste//HIWf/wxVP/8MJL/+68Qf/stTf/67Ey/+msLf/nqCmv5KQnCuWmKAAAAAAAAAAAAAAA + AAAAAAAAAAAAAB3KfgAfyoAAHsmAbCLKgvwozon/L9ab/zXhsv886sb/QvDU/0rz3P9S9N7/Svjp/yGG + cv9bIRX/h0cy/5taP/+iYUT/pWNG/6hlR/+qZkj/q2dJ/61oSf+uaUr/r2pK/69qS/+wakv/r2pK/69p + Sv+taUr/rGhJ/6pnSP+pZUj/p2RH/6NiRP+eX0P/jlA3/240If9PHhD/pEgE/+60U//55KH/9duT//bb + lP/225T/9tuT//bbkv/12pD/9dmN//XZiv/12If/9deD//XVf//11Hr/9NN1//TRcP/00Gv/885m//LM + YP/yyVr/8cZS//DBSP/tuT3/67M1/+quMP/oqSvb5qYoHuanKQAAAAAAAAAAAAAAAAAAAAAAAAAAAB/K + gQA91pEAIcuCiiTMhf8r0pH/Mtyn/zjnvv8/7s//RvLZ/07z3P9X9N7/Tvjp/ySFcf9fIhb/jEk1/6Ff + Q/+pZ0j/rGpL/65sTP+xbU3/s29O/7RwT/+2cE//t3FQ/7dxUP+3cVD/t3FQ/7ZxT/+1cE//tG9O/7Ju + Tv+vbE3/rWtM/6poSv+lZUj/llY7/3Q5Jf9WIRL/q00F//C8XP/55qf/9t2a//fem//33pv/996a//fe + mf/33Zf/9t2U//bckf/2247/9tqK//XZhv/114H/9dZ8//TVd//003L/9NJs//PPZv/yzWD/8slZ//DF + T//uvUP/67U5/+qwM//pqy3u56cqRuenKgDmpioAAAAAAAAAAAAAAAAAAAAAAB/LgwAdyoIJIsyEpSbO + if8t1pn/NOGx/zvqx/9C8NX/SvPa/1Hz3P9a9N7/VPnq/yWMeP9hIxb/j0o1/6dkR/+vbU3/s3FQ/7Vz + Uv+4dFL/unZT/7t3VP+9eFX/vnlV/795Vv+/eVb/v3lV/755Vf+8eFX/u3dU/7l1U/+3dFL/tHJR/7Fv + T/+tbE3/nl1B/30/Kf9fJhT/sVIG//LCZf/66K7/+OGh//jhov/44aH/9+Gg//jhn//44J3/+OCb//ff + mP/33pT/992R//bbjP/22oj/9tmD//XYfv/11nn/9NRy//PSbf/z0Gb/8sxf//HIVv/vwUr/7Lg9/+uy + Nf/prS/956grbeeoLADmuSoAAAAAAAAAAAAAAAAAAAAAACDMhQAfzIQSI82HvSjRjv8v2qL/NuW7/z7t + zv9F8df/TfLa/1Xy3P9d893/W/rr/ySbh/9hIxb/kUg0/61oS/+2dFP/unhW/716WP/AfFn/wn5a/8N/ + W//EgFv/xoBc/8aAXP/GgFz/xoFc/8WAXP/Ef1v/w35a/8F8Wf++e1j/vHlX/7h3Vf+1dVX/qGdJ/4lJ + MP9tLhn/t1cI//PIbv/66rP/+OOn//nkp//55Kf/+eOm//njpf/446P/+OKh//jhnv/44Jv/9+CX//fe + kv/33Y7/99yJ//bahP/22H//9dd5//TVc//002z/89Bm//LLXf/wxVL/7rtC/+u0OP/prjL/6Kkti//0 + hADmpioAAAAAAAAAAAAAAAAAAAAAACHNhwAgzYYZJM6KzynTlP8x3qv/OOnC/z/v0v9H8dj/T/LZ/1fy + 2/9f89z/ZPrp/yeynv9cJxn/kUQx/7JrTv+8elj/wYBd/8SCX//HhGD/yYVh/8uHYv/MiGL/zYhj/82J + Y//NiWP/zYlj/82IY//Mh2L/yoZh/8iFYP/Fg1//woBe/79+XP++fl3/s3NT/5hWO/9/OyL/vVwK//TN + d//667f/+eWs//nmrf/55az/+ear//nlqv/55an/++en//roqv/55aX/+OKc//jhmP/44JT/99+P//fd + if/324T/9tl///XXeP/01XL/9NJs//POY//xyFj/7r9I/+u1O//przP/56oupeamKQnmqCsAAAAAAAAA + AAAAAAAAAAAAACLOigAhzYkdJNCN2SvWmv8y4bH/OevH/0Hv0/9J8df/UfLY/1ny2v9h89v/a/nm/zLN + u/9TMiP/jjsr/7RpTf/Cfl3/x4Zj/8qJZf/Nimb/0Ixo/9KOaP/Tj2n/1I9q/9SQav/UkGr/1JBq/9SP + av/Tjmn/0Y1o/86LZ//MiWb/yYdk/8aFY//EhGP/vX9f/6hlSP+SSiv/w2MM//bTf//77Lv/+eew//ro + sf/66LH/+uiw//ror//56rH/16xv/+29bv/877n/+eSi//njnf/54pn/+OGU//jfjv/33Yn/9tuE//bZ + fv/113f/9NRx//PRaP/xy13/7sJO/+u3Pf/psDX/6KswvOeoLBLnqS0AAAAAAAAAAAAAAAAAAAAAACPP + jAAiz4sfJdGQ3ivZn/8y5Lf/OuzK/0Lw0/9K8db/UvHX/1ry2f9i8tr/bvbh/0Pm1v9ESzn/iDEj/7Fi + SP/GgWH/zYpo/9GPbP/TkW3/1ZNu/9iUb//ZlXD/2pVw/9qWcP/alXD/2pZw/9qWcP/ZlXD/1pRv/9SS + bv/SkG3/z45r/8yMaf/JiWj/xYdn/7d3Wf+kWzr/yGoO//fYh//77b//+um0//rptf/66bX/+um0//3u + t//Uuoz/cz4o/7RkG//84J3/+uuz//nlov/55J7/+eOZ//jhk//4347/992J//bbg//12Hz/9NZ1//PS + bf/yzWL/78VT/+y5QP/qsTb/6KwxzeeoLhnnqS4AAAAAAAAAAAAAAAAAAAAAACPQjgAi0IwfJdOT3yzb + o/8z5br/O+zM/0Lv0/9L8NT/U/HW/1vx2P9j8tn/bfPc/1r35/8zemb/gCsc/6lZP//IgWD/0Y9t/9aV + cv/Yl3P/25l1/92adf/em3X/3pl0/96Xcf/el3H/35p0/9+bdv/em3b/3Jt2/9qZdf/Yl3T/1JVy/9GS + cP/OkG//yoxs/8KFZ/+2b0z/znER//jdj//77sL/+uq4//rruf/667n//O+7/+bOof+kcln/e0g3/3s5 + GP/hoEv//vK8//roqP/55qL/+eSd//njmP/44ZP/+N+N//fdh//22oD/9th5//TUcf/zzmb/8MdX/+26 + Q//qsTf/6Kwx1+epLhzoqi8AAAAAAAAAAAAAAAAAAAAAACPRjwAi0I4dJdSV2izcpv8z5r3/O+3M/0Lv + 0f9L79P/U/DV/1vx1v9j8dj/a/La/3D66P8wuKX/bDMg/55MM//EeFb/1ZNv/9qadv/dnnn/3596/+Gf + ev/inHX/3pBp/9GEXP/NgFj/2I1k/+Gcdf/ioHv/4aF8/96gfP/cnXr/2Zt4/9aZdv/SlnT/z5Nz/8uR + cv/DgFv/0nkS//nilv/778X/+uy7//rsvP/88L//6teq/7WGav+mclv/l2NO/3NBMf+pWxj/+9yW//vu + t//656b/+uWh//nknP/545f/+OGR//ffiv/23IT/9tp9//TWdf/z0Gr/8Mhb/+y8Rv/psjj/6Kwy2+ep + Lx7nqjAAAAAAAAAAAAAAAAAAAAAAACPSkQAi0Y8aJdWY0CvdqP8y5r3/Ou3L/0Luz/9K79H/Uu/T/1vw + 1f9j8df/avHY/3b13/9M6dn/Sl9I/5M+JP+4akb/1Y9p/92eeP/ho33/5KN9/+ahef/Rnnj/oYpn/5xl + QP+tXDP/wnJG/92UZ//mpHz/5aeB/+Omgf/hpH//3qJ+/9qffP/XnHr/05l4/8+Xd//Jjmz/0noa//jc + fv/99dD/++6///3xwv/t3LD/vZF1/6x6Yv+se2P/pXRd/4hYRv+AQB7/46ZS//7zwP/66Kr/+uek//rm + oP/55Jr/+OKU//jgjv/33Yf/9tqA//TWeP/y0W7/8Mle/+y8Sf/psTn/6Kwz2eepMB3nqTEAAAAAAAAA + AAAAAAAAAAAAACLTkgAh0o8UJdeZwCrdqf8y5r3/OezJ/0Htzf9J7s//Ue/R/1nv0/9h8NX/afHX/3Ly + 2f9v+ej/M6yW/3w+I/+nVzb/zH9Y/9+cdv/lpH7/5KmD/73Msf+Z6df/aOve/zOznf+EWzT/s2Az/9aJ + W//opXz/6auG/+erh//lqYb/4aeF/96kg//boYH/155//9Obff/PmXz/zIVO/+WpOf/456n/9+rD/+bN + qf/ClXn/tIFp/7OCav+wf2j/rHxm/5trVv97Rzb/vHAl//7qrf/77LP/+umn//roo//55p3/+eSY//jh + kf/33or/9tuD//TXe//y0nD/8Mlh/+y9Sv/psTn/6Kwz0ueoMBrnqTEAAAAAAAAAAAAAAAAAAAAAACHU + lAAf0pALJNebqSneqf8w5rz/OOvI/z/szP9H7c3/T+7P/1fv0v9f79P/Z/DV/27w1/959d7/Ueva/0hx + Vv+YRSX/t2pC/9mOZf/mo3v/uNK2/5H25P+T9uL/mPnp/0Dn2/9FgV//r1os/9GDVf/qp33/7K+L/+qw + jf/nr43/5ayL/+Gqif/ep4f/2qSF/9ehgv/SnoD/zpp//8uTbf/OnG//yp2A/8CPdv+7inL/uYly/7aH + cP+zhG7/r4Fr/6d4Y/+HWUn/mFEc//bNgf/88b3/+uqq//ropv/55qD/+OSa//fik//334z/9tuF//TY + ff/y0nL/8Mpi/+y8Sv/psDn/56szw+anLxXmqDAAAAAAAAAAAAAAAAAAAAAAACHVlgAWx3oBI9ickCjd + qP8v5bn/NurF/z3ryf9F7Mz/Te3N/1Xuz/9d79H/ZO/T/2vw1f9z8df/d/jk/z3LuP9tVjb/pVMt/8Zz + Rv/At5P/kPPf/5D03/+R897/lvXi/1zt4P80lXX/qF0v/8yBUv/qqH7/7rSQ/+y2lP/qtZP/6LKS/+Sw + kP/hrY7/3qqM/9qnif/WpIf/0qGF/86ehP/JmYH/xpZ9/8OUe//Aknr/vY94/7qNd/+4inX/s4Zx/62B + bP+Xalj/gUcp/+KpWP/+9ML/+uus//npp//556L/+OWc//jilf/3347/9duH//TXf//z0nP/8Mli/+y7 + Sv/orzj/56ozrOanLgzmqDAAAAAAAAAAAAAAAAAAAAAAACHWlwAj2Z4AIticdSbdpv8t5Lf/NOnC/zvr + x/9C7Mn/SuzL/1Ltzf9Z7s//Ye7R/2jv0/9u8NT/d/HY/2335f82sJj/gU0p/6V2UP+Q587/i/Tf/43y + 3f+N8t3/kfTe/2zx4v8no4b/nmAy/8d8UP/opn3/8LeU/+66mf/suZn/6raY/+e0lf/jsZT/4K6R/9yr + j//ZqI3/1aWL/9GiiP/Nn4b/ypyE/8aZgv/Dl4D/wJR+/72SfP+7kHv/t4t3/7GGc/+hdWP/d0g1/8qH + N///8r3/++yw//rqqf/556T/+eWd//jil//334//9tuI//TXgP/y0XP/8Mhi/+u5SP/nrjf/5qkykOSd + JQHmpzAAAAAAAAAAAAAAAAAAAAAAACHWlwAh2JwAIdicUCTcpfIq4rP/Mei//zjqxP8/6sb/R+vI/07s + yv9W7Mz/Xu3O/2Xu0f9s79L/cu/U/3vy2f9l8uD/RKeN/4TGq/+G9t//ifLa/4ry2v+K8tr/i/Lb/3f0 + 4/8asZj/kGQ3/8J4Tf/lpHv/8LqX//C9nv/uvJ7/67ud/+i4m//ltpn/4rOX/96wlf/brZP/16qQ/9On + jv/Qo4z/zKGJ/8meiP/Gm4b/w5mE/8CXgv++lYD/upF9/7SKd/+me2n/dEw//7JvJv/+67H/+u20//rq + qv/556X/+eWe//jil//235D/9duI//PWgP/yz3P/7sZg/+q3Rf/mrDb+5akycOWpMgDkpDAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAg2J0AINibJiLbouIo4a//L+a7/zbpwf8+6sT/RerG/03ryP9U7Mr/XO3M/2Lt + zv9o7s//bu/R/3Pv0/978tn/c/Lb/33x2P+D8df/hPHY/4bx2P+G8dj/h/HY/3/14v8fv6j/f2s//751 + Sf/foXf/8byZ//DBov/vwaP/7L+i/+q9oP/nup7/47ec/+C0mv/dsZj/2a+V/9ask//SqJH/z6aP/8yj + jf/IoYv/xp6J/8OciP/Bmob/vZaD/7ePfP+nfWv/c09E/59fIv/75KT/++63//rpqv/556X/+OWe//fh + l//13pD/9NqI//PVf//xznH/7cNd/+m0Qf/mqjTu5acwRuWnMQDlpjAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAf2JwAHteaDSHaoL0m36v/LuS3/zTnvv876MH/QunD/0nqxf9Q6sf/V+vJ/17sy/9k7M3/au3O/2/u + 0P907tH/ee/T/3vv1P9979T/f/DV/4Dw1f+B8NX/gO/V/4D03v8szLf/anRK/7tyR//YnHP/8Lya//LE + pf/wxKf/7cKm/+vApf/ovqP/5buh/+K4n//ftp3/27Ob/9iwmf/VrZf/0qqV/86ok//LpZH/yaOP/8ah + jv/En4z/wJuI/7mSgP+le2r/ck9F/5JWIv/43Zv/+u+5//npqv/456X/+OSe//bgl//13I//89iH//LT + fv/wy2//7L9Z/+iwPf/mqDPX5aYwG+WmMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAAbpbASDZ + n34k3af/K+Ky/zHluv83577/PujA/0bpwv9N6cT/VOrG/1rryP9g7Mr/ZuzM/2vtzf9w7c//c+7Q/3fu + 0f957tL/eu7S/3vu0v9779L/eu/R/3zz2f831sP/UX5W/7dvRf/QlnD/7rua//LGqf/wx6z/7sWs/+zE + q//pwan/5r+n/+O8pf/guaP/3beh/9q0n//WsZ3/066b/9Gsmf/Oqpf/y6iV/8mmlP/Ho5L/w5+O/7qT + gv+fdGX/bU1F/4lRIP/325j/+u65//noqf/45aP/9+Kc//bflf/02o7/89aG//HQe//vyGr/67tR/+as + OP/lpjGf5KMtBuSlLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAHtmdAB7ZnUIh26PuJ+Ct/y7k + tf815rv/POe+/0Pov/9K6cL/UenE/1fqxf9d68f/Y+vJ/2fsy/9s7Mz/b+zN/3Ltzv907c//du3P/3bt + z/927c//de3O/3nx1P9B3sr/OIhj/7BtQ//JkWz/6rmY//HIrP/wyrD/7smw/+zHr//qxa3/58Ks/+TA + qv/hvqj/37um/9u4pP/YtqL/1rOg/9Oxn//Rr53/zq2b/8yrmf/JqJf/xaOS/7aOfv+XbWD/ZUhA/4ZQ + H//33Jv/+u23//jnp//35KH/9+Cb//bdlP/02Iz/8tOE//DNd//txGT/6bVJ/+WoNPrjpDBc5KQxAOOj + LgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe15oAHNibABvYmQ8f2qDAJd6p/y3isf8z5Lj/Oua7/0Hn + vf9I57//TujB/1Tpw/9a6cX/YOrH/2TqyP9o68n/bOvL/2/sy/9w7Mz/cezM/3Lszf9x7Mz/cOzM/3Pu + z/9O5M7/LpNx/6dsQv/CjGb/5LaU//HKrv/wzbT/7sy0/+zKs//qyLL/6Maw/+XErv/iwaz/4L+q/928 + qf/auqf/2Lil/9W1pP/Ts6L/0LGg/86vnv/LrJv/xKKR/62EdP+MZVj/WD83/4lUHv/54aL/+euz//jl + pv/34qD/9t6Z//Xakv/z1or/8dCA/+/Jcv/svl3/565A/+SlMdTjoi4f46IuAOOjLgAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAG9iZACPfpwAf2p9vI92l/yrgrf8x47T/OeW4/z/lu/9G5r3/TOe//1Lo + wf9Y6cP/XOnE/2Hqxv9l68f/aOvI/2rryf9s68n/bezK/23ryv9s68n/a+vJ/2zsyv9a6dL/JqCB/5ps + Qv+7hmL/3bCQ/+/Kr//wzrf/7s64/+zMt//qy7b/6Mm1/+XGs//jxLH/4MKv/96/rv/bvaz/2buq/9e5 + qf/Vt6f/07Wl/9Cyo//Mrp7/vpmJ/6J3av99W0//STEr/5hfIP/86Kz/+Oet//fjo//3353/9duV//TX + jv/y0of/8M18/+3Fa//quFP/5ag3/+OiL4naixcB4J0rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAHtqeAB7ZngAe2Z0jINui1ybeqf8v4bD/N+O2/z7luf9F5rv/Sue9/1Dnv/9W6MH/W+nC/1/p + xP9i6cX/ZerG/2fqx/9o6sf/aerH/2jqx/9o6sf/ZurG/2Xqxf9g7NH/HK2Q/4huRP+2gV7/1aqL/+3J + sP/v0Lr/7tC8/+zPvP/rzrv/6cy5/+bJuP/kx7b/4sW0/+DDs//dwbH/27+v/9m9rv/Xu6z/1bmq/9K1 + p//JqZn/s4p7/5RrX/9oTkT/TyYZ/8h9NP/867b/9+Sn//bgoP/13Zn/9NmS//LUi//wz4L/7sh2/+u/ + Yv/nr0b/46My4+KfLjLioC8A4qQuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHticABzY + mgAy58EAH9uhfyTdp/8t4K3/NeOz/z7kt/9E5br/Sea8/0/nvv9U58D/WejC/13pw/9g6cT/YunF/2Pq + xf9k6sX/ZerG/2Xqxf9j6sX/YunE/1/pw/9i7c7/Gbmf/3RxSf+yfFr/zKKF/+rHrv/v0b3/7tPA/+zR + wP/r0L7/6c69/+fMvP/lyrr/48i5/+HHt//fxbb/3cO0/9rBsv/YvrD/1rut/9CzpP+/mon/o3lr/35c + Uf9ROTH/jC0G/+ijV//56rf/9uCi//XdnP/02ZX/89WO//HQhv/uy33/7MNt/+m3Vv/kpzn/46AvjOCX + JgPinS0A4p8tAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3ZnAAg26EAH9qgIyPd + pNMq36r/M+Kw/zzjtf9D5bn/SOa8/07nvv9T6MD/V+jB/1vpwv9e6cT/YOnF/2Hpxf9i6cX/YunF/2Hp + xP9g6cP/XejC/1rnwP9g7Mn/JMWr/2B4UP+vd1T/w5t//+XErP/u0r7/7tTC/+zUw//r0sL/6dDB/+fP + wP/lzb7/48u9/+LJu//gx7n/3cW3/9vDtf/ZwLL/1Lmr/8akk/+vhHX/jWZb/15IP/91MBT/xkcG/+/F + fv/35a//9d2d//TZl//y1ZD/8dGJ/+/Mgv/txnX/6r1i/+atRv/ioDHW4Z0tKOKeLgDini0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2p8ALuGtACTcpGkp3qn4MuGv/zrj + tP9C5Lj/Sea8/07mvv9T58H/V+jC/1row/9d6cX/XunF/1/pxf9g6cX/YOnE/1/pw/9c6ML/WejB/1bn + v/9b68T/L9C1/0l/Wv+rcU//upV6/9+/qP/t0sD/7dXF/+zVxv/r1Mb/6dPF/+fRxP/m0ML/5M7A/+LM + vv/gybz/3se6/9vEt//XvbD/y6qa/7aMfP+YbmL/alBH/2c2IP+5OwL/0Wgd//Xcov/13qP/89mY//LV + kv/x0Iv/78yE/+3He//rv2v/57NT/+OkN/fhnS5o5KQ1AOGcLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf2qAAJdylACTbpBEq3qmvMeCu/zrjtP9C5bn/Sea9/0/n + wP9U6ML/V+nD/1vpxf9d6sb/XurG/1/qxv9f6sb/XurF/13pxP9a6cL/V+jA/1Pnvv9W6cH/ONm8/zCJ + Z/+jbUn/s450/9e3ov/q0cD/7dbI/+zWyf/r1sj/6dXI/+jTxv/m0cT/5M/D/+LNwf/gyr7/3ca6/9i+ + sP/Lq5v/uY9//55yZv9xVEz/Zzkl/7dCCP/FQwH/35pP//birf/z2Jj/8tST//DQjP/vzIX/7cd+/+vB + cf/ot13/5KhA/+GeL6PgmisO4JwtAOGdLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAFOCmACreqAAr3qk0MeCu2Tnjtf9C5br/See+/1Dowf9V6sT/WerF/1zr + x/9e68j/YOvI/2DryP9f68j/XurG/1zqxf9Y6cP/VejA/1Dnvv9Q6L7/P9+//yGVdf+YaUX/rYdt/86v + mf/oz77/7NbH/+vXyv/q1sn/6NXI/+fTx//l0cX/5M/C/+HMv//dx7n/1rur/8mmlf+3jHz/nXFl/3FT + S/9vPSP/ukgH/8lKBP/FVxD/78qK//PaoP/x05H/8M+M/+7Lhv/sx3//68F0/+m5ZP/lrEn/4Z8yzOCZ + KyXgmywA4Z4vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAJNmfAC3dqQAR1IwBM+CvjDrjtv9D5rz/S+fA/1LpxP9X6sf/XOvJ/1/ryv9h68v/YuvM/2Lr + y/9h68r/X+rJ/1zqx/9Y6MT/VOfB/0/mv/9M5rz/RePB/x6hg/+JZ0P/qH9k/8Wlj//jybj/6dPF/+rV + yP/p1Mj/59PH/+XRxf/jzsL/4Mm8/9rAsv/RsqH/w52L/7KEdv+Va2D/bk5E/4JCHf/FUAj/zVMG/75H + Av/ZkEb/89uj//DRkf/vzYv/7smF/+zFf//rwXb/6bpn/+avUP/ioTfd4JkrQeCdLwDitD8AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAINaWACrd + pwAo26M0MuCu2TzkuP9G57//TejD/1Tqx/9a68r/X+zN/2Lszv9k7M//Ze3P/2Xsz/9j7M7/YevM/13q + yf9Z6cb/VOjD/07nwP9K5rz/SubB/xqtj/91ZUT/o3VY/7qZgv/cwK7/5c6//+XQwv/kz8H/4su9/9/G + t//Zvq3/0rKg/8mij/+7jn7/pXds/4RdVf93SjT/o00T/9BaCP/NWAj/wU4F/8VhF//tx4n/8NKV/+7L + if/tyIT/7MR+/+rAd//ouWn/5rBV/+KiO+Tgmi1T79dqAN+VKADgmSoAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2JwAI9mfACHYnRYp26W0NOGx/0Dm + vP9J6ML/UerG/1jryv9e7M3/Yu3Q/2bu0f9o7tL/ae7S/2ju0v9m7tD/Y+3O/1/sy/9a6sj/VenF/0/o + wv9J577/TOnC/xe5nP9fZUn/nWVG/6qBZf/NqI//2rqk/9q7p//YuKP/1LKd/86pk//Gm4j/uot8/6Z4 + bP+NYVf/gVE7/5tSHf/HXwz/1WMI/8xcCf/EVAf/vVAG/96kYP/w0pj/7cmH/+zGgv/rwn3/6r52/+i5 + av/lr1b/4qM+4t+aL1jUbwAB35YpAN+XKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe2JwAAMl6ASTaoXos3qr9OeS3/0XowP9O6sb/VuvK/1zs + zv9j7tH/Z+7T/2rv1f9t79b/be/W/2zv1f9q79T/Z+7S/2Ltz/9d7Mz/WOrI/1Lpxf9N6MH/UOrE/x7G + qP9IaVL/jEs5/5NhTP+zgWz/wpN+/8GSf/+7jHv/s4Jz/6d1aP+aZ1n/kFxG/5NYMP+rXhr/y2kN/9lt + Cv/SaAv/ymAK/8RZCf+8TwX/0oZA/+7Mkf/sxoX/68N//+rAev/pvHP/57Zo/+SuVf/hoj/W35ovTNNi + AAHflioA35crAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAg2qAAHtmeGCbdpsgy4rH/Pua9/0npxP9T68r/Wu3O/2Hu0v9o79X/bfDX/3Hx + 2f9y8dr/c/Ha/3Lx2f9v8Nf/a+/V/2bu0v9h7c//W+zM/1bryP9S6cX/VezG/y7Ttv84clP/jzMU/5JG + Hv+gWiz/p2U1/6dmNf+nZjD/qmYp/7FoIP+9bhf/zXUQ/9l5Df/beAz/1XEM/85qC//JYwr/xF0K/7xT + Bv/KdjL/6sKH/+vEhP/qv3v/6b13/+e5cP/ms2T/5KtS/uGhPrrfmTA0569OAN6VKgDflywAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAj3KMAH9qfCyvfrJs147X9QOa+/0rpxf9U68r/XO3Q/2Tv0/9r8Nf/cfHa/3Xy2/9389z/d/Pc/3by + 3P908dr/cPHY/2rv1f9k7tL/X+3O/1rsy/9W68n/WezJ/zzdwf8vhmb/pz0H/7tXCP/HbQz/znkO/9J+ + Dv/WgQ//2YMQ/9qCD//ZgA7/13wP/9N2Dv/QcQ3/zGsN/8hmC//EYAn/vFYG/8d0L//nu3//6sCA/+i8 + dv/nuXL/5rVr/+SwXv/jqE3u4KA9jN+XLhjgnDUA3I8iAN6WLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3JsALOCtAC7g + rxg14rVvP+W8nEjnw7BR6sjHWuzO3WLu0u5p8Nb2b/HZ+XPy2/128tz/d/Pd/3bz3f9z9N3/b/Pc/2rx + 2P9l79P/YO3P/1zszP9a68r/XezK/zrjyf87iGf/qEAG/7dYCv/CaQ3/yXMP/8x4EP/PehD/0HoQ/9B6 + EP/Qdw//znQO/8xwDf/Jaw3/xmcM/8FgCf+8WQj/yXo2/+a3e//pvXv/57hx/+a1bf/ksWT/46tW++Gl + SL/gnTpN3ZElBt+aMwDgmzUA3pUsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm3KcAOeW5AC3grgA14rUAPOO6Akbl + wQ1P6ccYV+vMI2Dt0i5n79ZBbfDYW3Dx2ndz8dyRdPHcp3Py27l04MffcN7D/2nny/9h7dH/W/HU/1fy + 0/9W8tP/TvLT/ynNtf95YDD/r0kF/7dbC/+/Zg3/xG0O/8dwDv/Jcg//ynMP/8pyDv/JcA7/yG0N/8Zq + DP/DZQv/vl4G/71hEv/Ri0n/5rZ6/+e3c//lsmr/5LBj/+OrWf3ipk7N4KFCbN+bNRbjpkoA35kyAOCe + PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADvkuQAx4rAAPuW8AEfmwQBP6ccAWOzNAGDt + 0gBn79YAbvDZAHTy2wB389wAKf//AHLkywqKg1kukHJEgZJsOdKPdT/7iIRR/3+WZ/93o3b/a5Ro/4Zk + Lv+tSgb/sVUJ/7ddC/+8Ywz/v2YN/8FoDf/Cag3/w2oN/8RqDf/DaQ3/wWYM/75hCf+9YQ3/x3ct/9uh + Yf/mtXP/5LBn/+OsX//iqVfx4aVOwOCiRWrfnDoc46tUAOCeOgDckCQA3pgxAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABx8dsAbf/wAHXcwgCGkWcA/wAAAK8vAB+rPgBfq0QAq6tGBeGsSAb3r0oF/7BOBf+vVAr/s1gK/7Zb + C/+4Xwv/umEM/7xiDP+9Ywz/vWIL/7xhCv+8YQr/vmUR/8d3LP/Xl1T/4q1p/+OsYv/hp1bu4aVRz+Cj + TI3goEVI3ps4EeKvXgDfnj0A4q5VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKcv + AACjXAsAoj0IAKdIBQCpQQAAqFcOCapTCyirUgpdrVIJjK5TCbewVQncslcK7rNYCvO0Wgr3tVsK+rdc + Cvy4Xgz8vGMR+8JvHvjNgzX12ZlP8OGmXOXiplfH4KJNn9+gSHbfnkRD350/FtuPIQPgoUYA3pw7AN6c + PADgoEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKlN + CACpTQgAqU8JAKpQCgCsUQkAslMIAa5TCRCwVAkfsFUKMLBVCkawVQlZtFsMab1lE3TEbxx1zXwncNeP + PGDenExP4aNRON+dQyTdlzQW3JEpB+ClUADfn0YA4J9FAN+dPwDfmDMA35s5AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK1R + CQC1WQkArlIJAK5TCQCwVAkAsVUKALJXCgCzWQoAs1gJALVZCgC4Xg4AwGsbANCHOQDgpFkA46lcAN+f + SQDemj0A3pk7AN6ZOwDemTsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8AAAAAAAP/8AAAD/4AAAAAAAD/8A + AAD/AAAAAAAAAf8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8A + AAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD+AAAAAAAAAD8A + AAD/gAAAAAAAAA8AAAD/gAAAAAAAAAcAAAD/wAAAAAAAAAcAAAD/AAAAAAAAAAcAAAD/AAAAAAAAAAcA + AAD+AAAAAAAAAAcAAAD+AAAAAAAAAAcAAAD8AAAAAAAAAA8AAAD8AAAAAAAAAB8AAAD4AAAAAAAAAD8A + AADwAAAAAAAAAB8AAADwAAAAAAAAAB8AAADwAAAAAAAAAA8AAADgAAAAAAAAAA8AAADgAAAAAAAAAAcA + AADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADAAAAAAAAAAAcAAADAAAAAAAAAAAcAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMA + AADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADAAAAAAAAAAAMAAADgAAAAAAAAAAMAAADgAAAAAAAAAAcA + AADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADgAAAAAAAAAAcAAADwAAAAAAAAAA8AAADwAAAAAAAAAA8A + AADwAAAAAAAAAA8AAAD4AAAAAAAAAB8AAAD8AAAAAAAAAD8AAAD8AAAAAAAAAD8AAAD+AAAAAAAAAH8A + AAD+AAAAAAAAAP8AAAD+AAAAAAAAAP8AAAD8AAAAAAAAAf8AAAD8AAAAAAAAA/8AAAD8AAAAAAAAB/8A + AAD8AAAAAAAAD/8AAAD8AAAAAAAAH/8AAAD8AAAAAAAAf/8AAAD/AAAAAAAA//8AAAD//8AAAAAH//8A + AAD///AAAAAP//8AAAD///4AAAA///8AAAD////AAAP///8AAAD///////////8AAAD///////////8A + AAA= + + + \ No newline at end of file diff --git a/PCRobot/WxRobot.exe b/PCRobot/WxRobot.exe new file mode 100644 index 0000000..c0c3491 Binary files /dev/null and b/PCRobot/WxRobot.exe differ diff --git a/PCRobot/WxRobot.exe.config b/PCRobot/WxRobot.exe.config new file mode 100644 index 0000000..970c80b --- /dev/null +++ b/PCRobot/WxRobot.exe.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/PCRobot/WxRobot/API/KstAPI.cs b/PCRobot/WxRobot/API/KstAPI.cs new file mode 100644 index 0000000..4638b25 --- /dev/null +++ b/PCRobot/WxRobot/API/KstAPI.cs @@ -0,0 +1,98 @@ +/* + * 由SharpDevelop创建。 + * 用户: kst + * 日期: 2019/6/5 星期三 + * 时间: 11:27 + * + * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 + */ +using System; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using System.Text; +namespace WxRobot +{ + /// + /// Description of KstAPI. + /// + public class KstAPI + { + + public const int 通信_连接成功 = 1; + public const int 通信_数据到达 = 2; + public const int 通信_连接断开 = 3; + + public const int 回调_二维码 = 1; + public const int 回调_登录成功 = 2; + public const int 回调_退出登陆 = 3; + public const int 回调_接收消息 = 4; + + public const int 回调_添加好友 = 100001; + public const int 回调_下载信息 = 100002; + public const int 回调_建群返回 = 100003; + public const int 回调_A8Key = 100004; + public const int 回调_聊天对象 = 100007; + + public const int 回调_语音消息 = 100009; + public const int 回调_文件消息 = 100010; + public const int 回调_视频消息 = 100011; + public const int 回调_图片消息 = 100012; + + + public const int 回调_好友列表 = 300001; + public const int 回调_群员列表 = 300002; + + [DllImport("KstAPI.dll",EntryPoint="#7")] + public static extern int kst_DLLConnect(int Pwd,int Port); + + [DllImport("KstAPI.dll",EntryPoint="#6")] + public static extern int kst_GetPath(ref byte str); + + [DllImport("KstAPI.dll",EntryPoint="#5")] + public static extern int kst_CreateWx(string ExeFile,string ExeName,string DllName,int lPort); + + [DllImport("KstAPI.dll",EntryPoint="#1")] + public static extern int kstSocket_Init(IntPtr sFun, IntPtr cFun, int buflen); + + [DllImport("KstAPI.dll",EntryPoint="#2")] + public static extern int kstSocket_Create(string host, int sPort, int nIS); + + [DllImport("KstAPI.dll",EntryPoint="#3")] + public static extern int kstSocket_Send(int sPoint, int sPort, byte[] buf, int buflen); + + [DllImport("KstAPI.dll",EntryPoint="#4")] + public static extern int kstSocket_Port(int so); + + [DllImport("kernel32.dll",EntryPoint="RtlMoveMemory")] + public static extern int RtlMoveMemory(byte[] sByte, int Source, int Length); + + + //服务端回调 + public delegate void dele_Server_CallBack(int sPoint, int so, int type, int buf, int buflen, int cso); + public dele_Server_CallBack sc; + //客户端回调 + public delegate void dele_Client_CallBack(int so, int sPoint, int type, int buf, int buflen); + public dele_Client_CallBack cc; + + public static string EnUnicode(string str) + { + StringBuilder strResult = new StringBuilder(); + if (!string.IsNullOrEmpty(str)) + { + for (int i = 0; i < str.Length; i++) + { + strResult.Append("\\u"); + strResult.Append(((int)str[i]).ToString("X4")); + } + } + return strResult.ToString(); + } + + public static string DeUnicode(string str) + { + string strResult = Regex.Unescape(str); + return strResult; + } + + } +} diff --git a/PCRobot/WxRobot/API/WeChatAPI.cs b/PCRobot/WxRobot/API/WeChatAPI.cs new file mode 100644 index 0000000..c9cd8a2 --- /dev/null +++ b/PCRobot/WxRobot/API/WeChatAPI.cs @@ -0,0 +1,328 @@ +/* + * 由SharpDevelop创建。 + * 用户: kst + * 日期: 2019/6/4 星期二 + * 时间: 16:59 + * + * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 + */ +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace WxRobot +{ + /// + /// Description of WeChatAPI. + /// + public class WeChatAPI + { + public struct UserInfo + { + public int Type { get; set; } + public int List { get; set; } + public string Wxid { get; set; } + public string WxNo { get; set; } + public string Nick { get; set; } + public string Mark { get; set; } + public string V1 { get; set; } + public string HImg { get; set; } + public string Sex { get; set; } + public string Address { get; set; } + public string GetSex(int uSex) + { + if(uSex == 1) + return "男"; + else if(uSex == 2) + return "女"; + else + return "未知"; + } + } + + public struct MsgInfo + { + public string RecvWxid { get; set; } + public int Type { get; set; } + public string Time { get; set; } + public int IsSend { get; set; } + public int LocalMsgID { get; set; } + public string ServerMsgID { get; set; } + public string Wxid_1 { get; set; } + public string Wxid_2 { get; set; } + public string Msg { get; set; } + public string Source { get; set; } + } + + public int Socket_Handle { get; set; } + public int Socket_Port { get; set; } + public int Client_Handle { get; set; } + public string Client_Wxid { get; set; } + public string Client_GroupID { get; set; } + + public KstAPI.dele_Server_CallBack sc; + public KstAPI.dele_Client_CallBack cc; + + public WeChatAPI() + { + Socket_Handle = 0; + Socket_Port = 0; + } + + public int Socket_Init(IntPtr s, IntPtr c) + { + KstAPI.kstSocket_Init(s,c,0); + Socket_Handle = KstAPI.kstSocket_Create("127.0.0.1",0,1); + if(Socket_Handle == 0) + { + return 0; + } + return KstAPI.kstSocket_Port(Socket_Handle); + } + + public void Socket_Send(int cClient,string str) + { + byte[] sdata = System.Text.ASCIIEncoding.Default.GetBytes(str); + KstAPI.kstSocket_Send(Socket_Handle, cClient, sdata, sdata.Length); + } + + //微信初始化 + public void Wx_Init(int Client,string pwd) + { + JObject mJson = new JObject(); + mJson["packtype"] = 1; + mJson["pwd"] = pwd; + Socket_Send(Client,mJson.ToString()); + } + //获取/刷新好友列表 + public void Wx_ReFriendList(int Client) + { + JObject mJson = new JObject(); + mJson["packtype"] = 2; + Socket_Send(Client,mJson.ToString()); + } + //获取/刷新群员列表 + public void Wx_ReGroupList(int Client, string GroupID) + { + JObject mJson = new JObject(); + mJson["packtype"] = 3; + mJson["gid"] = GroupID; + Socket_Send(Client,mJson.ToString()); + } + //下载好友/群员详细信息 + public void Wx_GetUserInfo(int Client, string uWxid, string GroupID) + { + JObject mJson = new JObject(); + mJson["packtype"] = 22; + mJson["wxid"] = uWxid; + mJson["gid"] = GroupID; + Socket_Send(Client,mJson.ToString()); + } + //发送文本消息 + public void Wx_SendTextMsg(int Client, string ToWxid, string AtWxid, string Msg) + { + JObject mJson = new JObject(); + mJson["packtype"] = 4; + mJson["wxid"] = ToWxid; + mJson["atwxid"] = AtWxid; + mJson["msg"] = Convert.ToBase64String(System.Text.ASCIIEncoding.Default.GetBytes(Msg)); + Socket_Send(Client,mJson.ToString()); + } + //发送图片/GIF/文件消息 + //uType : 1=图片 2=GIF动图 3=文件/视频 + public void Wx_SendFileMsg(int Client, int uType, string ToWxid, string uFile) + { + JObject mJson = new JObject(); + mJson["packtype"] = 4 + uType; + mJson["wxid"] = ToWxid; + mJson["file"] = uFile; + Socket_Send(Client,mJson.ToString()); + } + //发送名片消息 + public void Wx_SendCardMsg(int Client, int uType, string ToWxid, string uWxid) + { + JObject mJson = new JObject(); + mJson["packtype"] = 8; + mJson["ctype"] = uType; + mJson["wxid"] = ToWxid; + mJson["cwxid"] = Convert.ToBase64String(System.Text.ASCIIEncoding.Default.GetBytes(uWxid)); + Socket_Send(Client,mJson.ToString()); + } + //发定位消息 + public void Wx_SendMapMsg(int Client, string ToWxid, string uXML) + { + JObject mJson = new JObject(); + mJson["packtype"] = 29; + mJson["wxid"] = ToWxid; + mJson["map"] = Convert.ToBase64String(System.Text.ASCIIEncoding.Default.GetBytes(uXML)); + Socket_Send(Client,mJson.ToString()); + } + //发送收藏消息 + public void Wx_SendFavMsg(int Client, string ToWxid, int FavID) + { + JObject mJson = new JObject(); + mJson["packtype"] = 9; + mJson["wxid"] = ToWxid; + mJson["favid"] = FavID; + Socket_Send(Client,mJson.ToString()); + } + //发送链接消息 + public void Wx_SendURLMsg(int Client, string ToWxid, string MyWxid, string uXML) + { + JObject mJson = new JObject(); + mJson["packtype"] = 10; + mJson["wxid"] = ToWxid; + mJson["mywxid"] = MyWxid; + mJson["xml"] = Convert.ToBase64String(System.Text.ASCIIEncoding.Default.GetBytes(uXML));; + Socket_Send(Client,mJson.ToString()); + } + //转账收款 + public void Wx_GetMoney(int Client, string uWxid, string uTranID, int uTimestamp) + { + JObject mJson = new JObject(); + mJson["packtype"] = 14; + mJson["wxid"] = uWxid; + mJson["time"] = uTimestamp; + mJson["tranid"] = uTranID; + Socket_Send(Client,mJson.ToString()); + } + //添加好友 + public void Wx_AddFriend(int Client, int uType, int uSource, string uWxid, string uV2, string uMsg) + { + JObject mJson = new JObject(); + mJson["packtype"] = 11; + mJson["type"] = uType; + mJson["source"] = uSource; + mJson["wxid"] = uWxid; + mJson["v2"] = uV2; + mJson["msg"] = uMsg; + Socket_Send(Client,mJson.ToString()); + } + //删除好友 + public void Wx_DelFriend(int Client, string uWxid) + { + JObject mJson = new JObject(); + mJson["packtype"] = 12; + mJson["wxid"] = uWxid; + Socket_Send(Client,mJson.ToString()); + } + //设置好友备注 + public void Wx_SetMark(int Client, string uWxid, string uMark) + { + JObject mJson = new JObject(); + mJson["packtype"] = 13; + mJson["wxid"] = uWxid; + mJson["mark"] = uMark; + Socket_Send(Client,mJson.ToString()); + } + //GetA8Key + public void Wx_GetA8Key(int Client, int uType, string uWxid, string uURL) + { + JObject mJson = new JObject(); + mJson["packtype"] = 15; + mJson["type"] = uType; + mJson["wxid"] = uWxid; + mJson["url"] = uURL; + Socket_Send(Client,mJson.ToString()); + } + //邀请入群(批量) + //uType: 1=直接拉群 2=邀请链接 + //Arrar_Wxid:接收消息人wxid数组 + public void WxGroup_Invite(int Client, int uType, string GroupID, string[] Arrar_Wxid) + { + JObject mJson = new JObject(); + mJson["packtype"] = 16; + mJson["type"] = uType; + mJson["gid"] = GroupID; + JArray mList = new JArray(); + int c = Arrar_Wxid.Length; + for(int i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + <msg> + <fromusername>*MYWXID*</fromusername> + <scene>0</scene> + <commenturl></commenturl> + <appmsg appid="" sdkver="0"> + <title>*标题*</title> + <des>*摘要*</des> + <action>view</action> + <type>5</type> + <showtype>0</showtype> + <content></content> + <url>*地址*</url> + <dataurl></dataurl> + <lowurl></lowurl> + <thumburl>*图片*</thumburl> + <recorditem> + <![CDATA[]]> + </recorditem> + <extinfo></extinfo> + <sourceusername></sourceusername> + <sourcedisplayname></sourcedisplayname> + <commenturl></commenturl> + <appattach> + <totallen>0</totallen> + <attachid></attachid> + <emoticonmd5></emoticonmd5> + <fileext></fileext> + </appattach> + </appmsg> + <appinfo> + <version>1</version> + <appname>Window wechat</appname> + </appinfo> +</msg> + + + <?xml version="1.0"?> +<msg> + <location x="*坐标X*" y="*坐标Y*" scale="15" label="*副标题*" maptype="roadmap" poiname="*主标题*" poiid="City" /> +</msg> + + \ No newline at end of file diff --git a/PCRobot/WxRobot/MainForm.Designer.cs b/PCRobot/WxRobot/MainForm.Designer.cs new file mode 100644 index 0000000..fc47fa8 --- /dev/null +++ b/PCRobot/WxRobot/MainForm.Designer.cs @@ -0,0 +1,1476 @@ +/* + * 由SharpDevelop创建。 + * 用户: Administrator + * 日期: 2019/6/4 星期二 + * 时间: 09:50 + * + * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 + */ +namespace WxRobot +{ + partial class MainForm + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.PictureBox PIC_HEADIMG; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox LOGIN_TXT_SOCKET; + private System.Windows.Forms.TextBox LOGIN_TXT_WXID; + private System.Windows.Forms.TextBox LOGIN_TXT_NICK; + private System.Windows.Forms.ListView LOGIN_LIST; + + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox OPENWX_TXT_PATH; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button BUTTON_OPEMWX; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.Button BUTTON_RE_LIST; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.TabPage tabPage4; + private System.Windows.Forms.ListView FRIEND_LIST; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ColumnHeader columnHeader7; + private System.Windows.Forms.ColumnHeader columnHeader8; + private System.Windows.Forms.ColumnHeader columnHeader9; + private System.Windows.Forms.ColumnHeader columnHeader10; + private System.Windows.Forms.ListView FRIEND_GH_LIST; + private System.Windows.Forms.ColumnHeader columnHeader11; + private System.Windows.Forms.ColumnHeader columnHeader13; + private System.Windows.Forms.ColumnHeader columnHeader14; + private System.Windows.Forms.ColumnHeader columnHeader15; + private System.Windows.Forms.ListView GROUP_LIST; + private System.Windows.Forms.ColumnHeader columnHeader12; + private System.Windows.Forms.ColumnHeader columnHeader16; + private System.Windows.Forms.ColumnHeader columnHeader17; + private System.Windows.Forms.ColumnHeader columnHeader18; + private System.Windows.Forms.ColumnHeader columnHeader19; + private System.Windows.Forms.ListView GROUP_MEMBER_LIST; + private System.Windows.Forms.ColumnHeader columnHeader20; + private System.Windows.Forms.ColumnHeader columnHeader21; + private System.Windows.Forms.ColumnHeader columnHeader22; + private System.Windows.Forms.ColumnHeader columnHeader23; + private System.Windows.Forms.TextBox DEBUG_TXT; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.TextBox MSG_TXT_MESSAGE; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox MSG_TXT_ATWXID; + private System.Windows.Forms.TextBox MSG_TXT_WXID; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button BUTTON_MSG_FAV; + private System.Windows.Forms.Button BUTTON_MSG_MAP; + private System.Windows.Forms.Button BUTTON_MSG_CARD; + private System.Windows.Forms.Button BUTTON_MSG_FILE; + private System.Windows.Forms.Button BUTTON_MSG_GIF; + private System.Windows.Forms.Button BUTTON_MSG_PIC; + private System.Windows.Forms.Button BUTTON_MSG_TEXT; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.TextBox FRI_TXT_MSG; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox FRI_TXT_SOURCE; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.TextBox FRI_TXT_WXID; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.CheckBox CHK_ADDFRIEND; + private System.Windows.Forms.Button BUTTON_FRI_MARK; + private System.Windows.Forms.Button BUTTON_FRI_DEL; + private System.Windows.Forms.Button BUTTON_FRI_ADD; + private System.Windows.Forms.CheckBox CHK_MONEY; + private System.Windows.Forms.GroupBox groupBox5; + private System.Windows.Forms.CheckBox CHK_INVITE; + private System.Windows.Forms.Button BUTTON_GROUP_CREATE; + private System.Windows.Forms.Button BUTTON_GROUP_NOTICE; + private System.Windows.Forms.Button BUTTON_GROUP_SETNICK; + private System.Windows.Forms.Button BUTTON_GROUP_EXIT; + private System.Windows.Forms.Button BUTTON_GROUP_KICK; + private System.Windows.Forms.Button BUTTON_GROUP_INV_2; + private System.Windows.Forms.Button BUTTON_GROUP_INV_1; + private System.Windows.Forms.TextBox GROUP_TXT_TEXT; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.TextBox GROUP_TXT_WXID; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.TextBox GROUP_TXT_GID; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.GroupBox groupBox6; + private System.Windows.Forms.TextBox URL_TXT_URL; + private System.Windows.Forms.TextBox URL_TXT_TEXT; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.TextBox URL_TXT_PIC; + private System.Windows.Forms.TextBox URL_TXT_TITLE; + private System.Windows.Forms.Button BUTTON_MSG_URL; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.ContextMenuStrip FRIEND_MENU; + private System.Windows.Forms.ToolStripMenuItem FRIEND_MENU_GETUSERINFO; + private System.Windows.Forms.ToolStripMenuItem FRIEND_MENU_TOP; + private System.Windows.Forms.ToolStripMenuItem FRIEND_MENU_TOP_ON; + private System.Windows.Forms.ToolStripMenuItem FRIEND_MENU_TOP_OFF; + private System.Windows.Forms.Label label17; + private System.Windows.Forms.Label label18; + private System.Windows.Forms.ToolStripMenuItem FRIEND_MENU_DISTURB; + private System.Windows.Forms.ToolStripMenuItem FRIEND_MENU_DISTURB_ON; + private System.Windows.Forms.ToolStripMenuItem FRIEND_MENU_DISTURB_OFF; + private System.Windows.Forms.ContextMenuStrip GROUP_MENU; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_TOP; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_TOP_ON; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_TOP_OFF; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_DISTURB; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_DISTURB_ON; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_DISTURB_OFF; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_SAVE; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_SAVE_ON; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_SAVE_OFF; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_NICK; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_NICK_ON; + private System.Windows.Forms.ToolStripMenuItem GROUP_MENU_NICK_OFF; + private System.Windows.Forms.ContextMenuStrip GROUPMEMBER_MENU; + private System.Windows.Forms.ToolStripMenuItem GROUPMEMBER_MENU_GETUSERINFO; + private System.Windows.Forms.CheckBox CHK_REVOKE; + private System.Windows.Forms.CheckBox CHK_PIC; + + + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.LOGIN_TXT_WXID = new System.Windows.Forms.TextBox(); + this.LOGIN_TXT_NICK = new System.Windows.Forms.TextBox(); + this.LOGIN_TXT_SOCKET = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.PIC_HEADIMG = new System.Windows.Forms.PictureBox(); + this.LOGIN_LIST = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.BUTTON_OPEMWX = new System.Windows.Forms.Button(); + this.OPENWX_TXT_PATH = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.label18 = new System.Windows.Forms.Label(); + this.FRIEND_LIST = new System.Windows.Forms.ListView(); + this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader10 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.FRIEND_GH_LIST = new System.Windows.Forms.ListView(); + this.columnHeader11 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader14 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader15 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.label17 = new System.Windows.Forms.Label(); + this.label16 = new System.Windows.Forms.Label(); + this.GROUP_MEMBER_LIST = new System.Windows.Forms.ListView(); + this.columnHeader20 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader21 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader22 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader23 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.GROUP_LIST = new System.Windows.Forms.ListView(); + this.columnHeader12 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader16 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader17 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader18 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader19 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.DEBUG_TXT = new System.Windows.Forms.TextBox(); + this.BUTTON_RE_LIST = new System.Windows.Forms.Button(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.CHK_PIC = new System.Windows.Forms.CheckBox(); + this.CHK_REVOKE = new System.Windows.Forms.CheckBox(); + this.BUTTON_MSG_FAV = new System.Windows.Forms.Button(); + this.BUTTON_MSG_MAP = new System.Windows.Forms.Button(); + this.BUTTON_MSG_CARD = new System.Windows.Forms.Button(); + this.BUTTON_MSG_FILE = new System.Windows.Forms.Button(); + this.BUTTON_MSG_GIF = new System.Windows.Forms.Button(); + this.BUTTON_MSG_PIC = new System.Windows.Forms.Button(); + this.BUTTON_MSG_TEXT = new System.Windows.Forms.Button(); + this.MSG_TXT_MESSAGE = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.MSG_TXT_ATWXID = new System.Windows.Forms.TextBox(); + this.MSG_TXT_WXID = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.CHK_MONEY = new System.Windows.Forms.CheckBox(); + this.CHK_ADDFRIEND = new System.Windows.Forms.CheckBox(); + this.BUTTON_FRI_MARK = new System.Windows.Forms.Button(); + this.BUTTON_FRI_DEL = new System.Windows.Forms.Button(); + this.BUTTON_FRI_ADD = new System.Windows.Forms.Button(); + this.FRI_TXT_MSG = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.FRI_TXT_SOURCE = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.FRI_TXT_WXID = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.CHK_INVITE = new System.Windows.Forms.CheckBox(); + this.BUTTON_GROUP_CREATE = new System.Windows.Forms.Button(); + this.BUTTON_GROUP_NOTICE = new System.Windows.Forms.Button(); + this.BUTTON_GROUP_SETNICK = new System.Windows.Forms.Button(); + this.BUTTON_GROUP_EXIT = new System.Windows.Forms.Button(); + this.BUTTON_GROUP_KICK = new System.Windows.Forms.Button(); + this.BUTTON_GROUP_INV_2 = new System.Windows.Forms.Button(); + this.BUTTON_GROUP_INV_1 = new System.Windows.Forms.Button(); + this.GROUP_TXT_TEXT = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.GROUP_TXT_WXID = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.GROUP_TXT_GID = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.URL_TXT_URL = new System.Windows.Forms.TextBox(); + this.URL_TXT_TEXT = new System.Windows.Forms.TextBox(); + this.label15 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.URL_TXT_PIC = new System.Windows.Forms.TextBox(); + this.URL_TXT_TITLE = new System.Windows.Forms.TextBox(); + this.BUTTON_MSG_URL = new System.Windows.Forms.Button(); + this.label13 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.FRIEND_MENU = new System.Windows.Forms.ContextMenuStrip(this.components); + this.FRIEND_MENU_GETUSERINFO = new System.Windows.Forms.ToolStripMenuItem(); + this.FRIEND_MENU_TOP = new System.Windows.Forms.ToolStripMenuItem(); + this.FRIEND_MENU_TOP_ON = new System.Windows.Forms.ToolStripMenuItem(); + this.FRIEND_MENU_TOP_OFF = new System.Windows.Forms.ToolStripMenuItem(); + this.FRIEND_MENU_DISTURB = new System.Windows.Forms.ToolStripMenuItem(); + this.FRIEND_MENU_DISTURB_ON = new System.Windows.Forms.ToolStripMenuItem(); + this.FRIEND_MENU_DISTURB_OFF = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU = new System.Windows.Forms.ContextMenuStrip(this.components); + this.GROUP_MENU_TOP = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_TOP_ON = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_TOP_OFF = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_DISTURB = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_DISTURB_ON = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_DISTURB_OFF = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_SAVE = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_SAVE_ON = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_SAVE_OFF = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_NICK = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_NICK_ON = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUP_MENU_NICK_OFF = new System.Windows.Forms.ToolStripMenuItem(); + this.GROUPMEMBER_MENU = new System.Windows.Forms.ContextMenuStrip(this.components); + this.GROUPMEMBER_MENU_GETUSERINFO = new System.Windows.Forms.ToolStripMenuItem(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PIC_HEADIMG)).BeginInit(); + this.groupBox2.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.tabPage4.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.groupBox6.SuspendLayout(); + this.FRIEND_MENU.SuspendLayout(); + this.GROUP_MENU.SuspendLayout(); + this.GROUPMEMBER_MENU.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.LOGIN_TXT_WXID); + this.groupBox1.Controls.Add(this.LOGIN_TXT_NICK); + this.groupBox1.Controls.Add(this.LOGIN_TXT_SOCKET); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.PIC_HEADIMG); + this.groupBox1.Controls.Add(this.LOGIN_LIST); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(293, 460); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "登录列表"; + // + // LOGIN_TXT_WXID + // + this.LOGIN_TXT_WXID.BackColor = System.Drawing.SystemColors.Control; + this.LOGIN_TXT_WXID.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.LOGIN_TXT_WXID.Location = new System.Drawing.Point(112, 424); + this.LOGIN_TXT_WXID.Name = "LOGIN_TXT_WXID"; + this.LOGIN_TXT_WXID.ReadOnly = true; + this.LOGIN_TXT_WXID.Size = new System.Drawing.Size(175, 14); + this.LOGIN_TXT_WXID.TabIndex = 5; + this.LOGIN_TXT_WXID.Text = "[未选择]"; + // + // LOGIN_TXT_NICK + // + this.LOGIN_TXT_NICK.BackColor = System.Drawing.SystemColors.Control; + this.LOGIN_TXT_NICK.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.LOGIN_TXT_NICK.Location = new System.Drawing.Point(112, 404); + this.LOGIN_TXT_NICK.Name = "LOGIN_TXT_NICK"; + this.LOGIN_TXT_NICK.ReadOnly = true; + this.LOGIN_TXT_NICK.Size = new System.Drawing.Size(175, 14); + this.LOGIN_TXT_NICK.TabIndex = 4; + this.LOGIN_TXT_NICK.Text = "[未选择]"; + // + // LOGIN_TXT_SOCKET + // + this.LOGIN_TXT_SOCKET.BackColor = System.Drawing.SystemColors.Control; + this.LOGIN_TXT_SOCKET.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.LOGIN_TXT_SOCKET.Location = new System.Drawing.Point(112, 384); + this.LOGIN_TXT_SOCKET.Name = "LOGIN_TXT_SOCKET"; + this.LOGIN_TXT_SOCKET.ReadOnly = true; + this.LOGIN_TXT_SOCKET.Size = new System.Drawing.Size(175, 14); + this.LOGIN_TXT_SOCKET.TabIndex = 3; + this.LOGIN_TXT_SOCKET.Text = "[未选择]"; + // + // label1 + // + this.label1.Location = new System.Drawing.Point(112, 366); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(100, 15); + this.label1.TabIndex = 2; + this.label1.Text = "当前操作:"; + // + // PIC_HEADIMG + // + this.PIC_HEADIMG.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.PIC_HEADIMG.Location = new System.Drawing.Point(6, 347); + this.PIC_HEADIMG.Name = "PIC_HEADIMG"; + this.PIC_HEADIMG.Size = new System.Drawing.Size(100, 100); + this.PIC_HEADIMG.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.PIC_HEADIMG.TabIndex = 1; + this.PIC_HEADIMG.TabStop = false; + // + // LOGIN_LIST + // + this.LOGIN_LIST.CheckBoxes = true; + this.LOGIN_LIST.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3, + this.columnHeader4, + this.columnHeader5}); + this.LOGIN_LIST.FullRowSelect = true; + this.LOGIN_LIST.GridLines = true; + this.LOGIN_LIST.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.LOGIN_LIST.HideSelection = false; + this.LOGIN_LIST.Location = new System.Drawing.Point(6, 20); + this.LOGIN_LIST.Name = "LOGIN_LIST"; + this.LOGIN_LIST.Size = new System.Drawing.Size(281, 317); + this.LOGIN_LIST.TabIndex = 0; + this.LOGIN_LIST.UseCompatibleStateImageBehavior = false; + this.LOGIN_LIST.View = System.Windows.Forms.View.Details; + this.LOGIN_LIST.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.LOGIN_LISTItemCheck); + this.LOGIN_LIST.SelectedIndexChanged += new System.EventHandler(this.LOGIN_LIST_SelectedIndexChanged); + // + // columnHeader1 + // + this.columnHeader1.Text = "昵称"; + this.columnHeader1.Width = 80; + // + // columnHeader2 + // + this.columnHeader2.Text = "Wxid"; + // + // columnHeader3 + // + this.columnHeader3.Text = "微信号"; + // + // columnHeader4 + // + this.columnHeader4.Text = "头像"; + this.columnHeader4.Width = 40; + // + // columnHeader5 + // + this.columnHeader5.Text = "#"; + this.columnHeader5.Width = 20; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.BUTTON_OPEMWX); + this.groupBox2.Controls.Add(this.OPENWX_TXT_PATH); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Location = new System.Drawing.Point(12, 478); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(293, 89); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "启动微信"; + // + // BUTTON_OPEMWX + // + this.BUTTON_OPEMWX.Location = new System.Drawing.Point(212, 50); + this.BUTTON_OPEMWX.Name = "BUTTON_OPEMWX"; + this.BUTTON_OPEMWX.Size = new System.Drawing.Size(75, 28); + this.BUTTON_OPEMWX.TabIndex = 2; + this.BUTTON_OPEMWX.Text = "启动微信"; + this.BUTTON_OPEMWX.UseVisualStyleBackColor = true; + this.BUTTON_OPEMWX.Click += new System.EventHandler(this.BUTTON_OPEMWXClick); + // + // OPENWX_TXT_PATH + // + this.OPENWX_TXT_PATH.Location = new System.Drawing.Point(64, 23); + this.OPENWX_TXT_PATH.Name = "OPENWX_TXT_PATH"; + this.OPENWX_TXT_PATH.Size = new System.Drawing.Size(223, 21); + this.OPENWX_TXT_PATH.TabIndex = 1; + // + // label2 + // + this.label2.Location = new System.Drawing.Point(6, 27); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(65, 16); + this.label2.TabIndex = 0; + this.label2.Text = "微信路径:"; + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Controls.Add(this.tabPage4); + this.tabControl1.Location = new System.Drawing.Point(311, 12); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(603, 555); + this.tabControl1.TabIndex = 3; + // + // tabPage1 + // + this.tabPage1.BackColor = System.Drawing.Color.WhiteSmoke; + this.tabPage1.Controls.Add(this.label18); + this.tabPage1.Controls.Add(this.FRIEND_LIST); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(595, 529); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "好友"; + // + // label18 + // + this.label18.ForeColor = System.Drawing.Color.Green; + this.label18.Location = new System.Drawing.Point(3, 512); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(583, 13); + this.label18.TabIndex = 5; + this.label18.Text = "提示:单击好友可查看头像图片,右键单击好友可下载好友详细信息(性别/地区)和设置免打扰/置顶"; + // + // FRIEND_LIST + // + this.FRIEND_LIST.CheckBoxes = true; + this.FRIEND_LIST.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader6, + this.columnHeader7, + this.columnHeader8, + this.columnHeader9, + this.columnHeader10}); + this.FRIEND_LIST.FullRowSelect = true; + this.FRIEND_LIST.GridLines = true; + this.FRIEND_LIST.HideSelection = false; + this.FRIEND_LIST.Location = new System.Drawing.Point(3, 3); + this.FRIEND_LIST.Name = "FRIEND_LIST"; + this.FRIEND_LIST.Size = new System.Drawing.Size(589, 506); + this.FRIEND_LIST.TabIndex = 0; + this.FRIEND_LIST.UseCompatibleStateImageBehavior = false; + this.FRIEND_LIST.View = System.Windows.Forms.View.Details; + this.FRIEND_LIST.MouseClick += new System.Windows.Forms.MouseEventHandler(this.FRIEND_LISTMouseClick); + // + // columnHeader6 + // + this.columnHeader6.Text = "昵称"; + this.columnHeader6.Width = 120; + // + // columnHeader7 + // + this.columnHeader7.Text = "备注"; + this.columnHeader7.Width = 120; + // + // columnHeader8 + // + this.columnHeader8.Text = "Wxid"; + this.columnHeader8.Width = 120; + // + // columnHeader9 + // + this.columnHeader9.Text = "微信号"; + this.columnHeader9.Width = 120; + // + // columnHeader10 + // + this.columnHeader10.Text = "头像"; + this.columnHeader10.Width = 88; + // + // tabPage2 + // + this.tabPage2.BackColor = System.Drawing.Color.WhiteSmoke; + this.tabPage2.Controls.Add(this.FRIEND_GH_LIST); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(595, 529); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "公众号"; + // + // FRIEND_GH_LIST + // + this.FRIEND_GH_LIST.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader11, + this.columnHeader13, + this.columnHeader14, + this.columnHeader15}); + this.FRIEND_GH_LIST.FullRowSelect = true; + this.FRIEND_GH_LIST.GridLines = true; + this.FRIEND_GH_LIST.HideSelection = false; + this.FRIEND_GH_LIST.Location = new System.Drawing.Point(3, 3); + this.FRIEND_GH_LIST.Name = "FRIEND_GH_LIST"; + this.FRIEND_GH_LIST.Size = new System.Drawing.Size(589, 522); + this.FRIEND_GH_LIST.TabIndex = 1; + this.FRIEND_GH_LIST.UseCompatibleStateImageBehavior = false; + this.FRIEND_GH_LIST.View = System.Windows.Forms.View.Details; + // + // columnHeader11 + // + this.columnHeader11.Text = "公众号名称"; + this.columnHeader11.Width = 150; + // + // columnHeader13 + // + this.columnHeader13.Text = "Wxid"; + this.columnHeader13.Width = 150; + // + // columnHeader14 + // + this.columnHeader14.Text = "微信号"; + this.columnHeader14.Width = 150; + // + // columnHeader15 + // + this.columnHeader15.Text = "头像"; + this.columnHeader15.Width = 110; + // + // tabPage3 + // + this.tabPage3.BackColor = System.Drawing.Color.WhiteSmoke; + this.tabPage3.Controls.Add(this.label17); + this.tabPage3.Controls.Add(this.label16); + this.tabPage3.Controls.Add(this.GROUP_MEMBER_LIST); + this.tabPage3.Controls.Add(this.GROUP_LIST); + this.tabPage3.Location = new System.Drawing.Point(4, 22); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(595, 529); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "群"; + // + // label17 + // + this.label17.ForeColor = System.Drawing.Color.Green; + this.label17.Location = new System.Drawing.Point(6, 512); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(583, 13); + this.label17.TabIndex = 5; + this.label17.Text = "提示:右键单击群成员可下载详细信息"; + // + // label16 + // + this.label16.ForeColor = System.Drawing.Color.Green; + this.label16.Location = new System.Drawing.Point(6, 232); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(583, 13); + this.label16.TabIndex = 4; + this.label16.Text = "提示:双击群可获取群成员列表,右键单击群可设置群置顶/免打扰/保存通讯录/显示群员昵称"; + // + // GROUP_MEMBER_LIST + // + this.GROUP_MEMBER_LIST.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader20, + this.columnHeader21, + this.columnHeader22, + this.columnHeader23}); + this.GROUP_MEMBER_LIST.FullRowSelect = true; + this.GROUP_MEMBER_LIST.GridLines = true; + this.GROUP_MEMBER_LIST.HideSelection = false; + this.GROUP_MEMBER_LIST.Location = new System.Drawing.Point(3, 247); + this.GROUP_MEMBER_LIST.Name = "GROUP_MEMBER_LIST"; + this.GROUP_MEMBER_LIST.Size = new System.Drawing.Size(589, 262); + this.GROUP_MEMBER_LIST.TabIndex = 3; + this.GROUP_MEMBER_LIST.UseCompatibleStateImageBehavior = false; + this.GROUP_MEMBER_LIST.View = System.Windows.Forms.View.Details; + this.GROUP_MEMBER_LIST.MouseClick += new System.Windows.Forms.MouseEventHandler(this.GROUP_MEMBER_LISTMouseClick); + // + // columnHeader20 + // + this.columnHeader20.Text = "昵称"; + this.columnHeader20.Width = 150; + // + // columnHeader21 + // + this.columnHeader21.Text = "群昵称"; + this.columnHeader21.Width = 150; + // + // columnHeader22 + // + this.columnHeader22.Text = "Wxid"; + this.columnHeader22.Width = 150; + // + // columnHeader23 + // + this.columnHeader23.Text = "头像"; + this.columnHeader23.Width = 115; + // + // GROUP_LIST + // + this.GROUP_LIST.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader12, + this.columnHeader16, + this.columnHeader17, + this.columnHeader18, + this.columnHeader19}); + this.GROUP_LIST.FullRowSelect = true; + this.GROUP_LIST.GridLines = true; + this.GROUP_LIST.HideSelection = false; + this.GROUP_LIST.Location = new System.Drawing.Point(3, 3); + this.GROUP_LIST.Name = "GROUP_LIST"; + this.GROUP_LIST.Size = new System.Drawing.Size(589, 225); + this.GROUP_LIST.TabIndex = 2; + this.GROUP_LIST.UseCompatibleStateImageBehavior = false; + this.GROUP_LIST.View = System.Windows.Forms.View.Details; + this.GROUP_LIST.MouseClick += new System.Windows.Forms.MouseEventHandler(this.GROUP_LISTMouseClick); + this.GROUP_LIST.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.GROUP_LISTMouseDoubleClick); + // + // columnHeader12 + // + this.columnHeader12.Text = "群名"; + this.columnHeader12.Width = 150; + // + // columnHeader16 + // + this.columnHeader16.Text = "群ID"; + this.columnHeader16.Width = 150; + // + // columnHeader17 + // + this.columnHeader17.Text = "群主"; + this.columnHeader17.Width = 150; + // + // columnHeader18 + // + this.columnHeader18.Text = "成员数"; + this.columnHeader18.Width = 50; + // + // columnHeader19 + // + this.columnHeader19.Text = "头像"; + this.columnHeader19.Width = 65; + // + // tabPage4 + // + this.tabPage4.BackColor = System.Drawing.Color.WhiteSmoke; + this.tabPage4.Controls.Add(this.DEBUG_TXT); + this.tabPage4.Location = new System.Drawing.Point(4, 22); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Size = new System.Drawing.Size(595, 529); + this.tabPage4.TabIndex = 3; + this.tabPage4.Text = "日志"; + // + // DEBUG_TXT + // + this.DEBUG_TXT.Location = new System.Drawing.Point(3, 3); + this.DEBUG_TXT.MaxLength = 0; + this.DEBUG_TXT.Multiline = true; + this.DEBUG_TXT.Name = "DEBUG_TXT"; + this.DEBUG_TXT.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.DEBUG_TXT.Size = new System.Drawing.Size(589, 522); + this.DEBUG_TXT.TabIndex = 0; + // + // BUTTON_RE_LIST + // + this.BUTTON_RE_LIST.Location = new System.Drawing.Point(744, 5); + this.BUTTON_RE_LIST.Name = "BUTTON_RE_LIST"; + this.BUTTON_RE_LIST.Size = new System.Drawing.Size(166, 26); + this.BUTTON_RE_LIST.TabIndex = 3; + this.BUTTON_RE_LIST.Text = "刷新好友/公众号/群列表"; + this.BUTTON_RE_LIST.UseVisualStyleBackColor = true; + this.BUTTON_RE_LIST.Click += new System.EventHandler(this.BUTTON_RE_LISTClick); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.CHK_PIC); + this.groupBox3.Controls.Add(this.CHK_REVOKE); + this.groupBox3.Controls.Add(this.BUTTON_MSG_FAV); + this.groupBox3.Controls.Add(this.BUTTON_MSG_MAP); + this.groupBox3.Controls.Add(this.BUTTON_MSG_CARD); + this.groupBox3.Controls.Add(this.BUTTON_MSG_FILE); + this.groupBox3.Controls.Add(this.BUTTON_MSG_GIF); + this.groupBox3.Controls.Add(this.BUTTON_MSG_PIC); + this.groupBox3.Controls.Add(this.BUTTON_MSG_TEXT); + this.groupBox3.Controls.Add(this.MSG_TXT_MESSAGE); + this.groupBox3.Controls.Add(this.label5); + this.groupBox3.Controls.Add(this.MSG_TXT_ATWXID); + this.groupBox3.Controls.Add(this.MSG_TXT_WXID); + this.groupBox3.Controls.Add(this.label4); + this.groupBox3.Controls.Add(this.label3); + this.groupBox3.Location = new System.Drawing.Point(916, 5); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(295, 192); + this.groupBox3.TabIndex = 4; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "消息操作"; + // + // CHK_PIC + // + this.CHK_PIC.Checked = true; + this.CHK_PIC.CheckState = System.Windows.Forms.CheckState.Checked; + this.CHK_PIC.Location = new System.Drawing.Point(228, 171); + this.CHK_PIC.Name = "CHK_PIC"; + this.CHK_PIC.Size = new System.Drawing.Size(60, 17); + this.CHK_PIC.TabIndex = 14; + this.CHK_PIC.Text = "高清图"; + this.CHK_PIC.UseVisualStyleBackColor = true; + // + // CHK_REVOKE + // + this.CHK_REVOKE.Location = new System.Drawing.Point(228, 153); + this.CHK_REVOKE.Name = "CHK_REVOKE"; + this.CHK_REVOKE.Size = new System.Drawing.Size(60, 17); + this.CHK_REVOKE.TabIndex = 13; + this.CHK_REVOKE.Text = "防撤回"; + this.CHK_REVOKE.UseVisualStyleBackColor = true; + this.CHK_REVOKE.CheckedChanged += new System.EventHandler(this.CHK_REVOKECheckedChanged); + // + // BUTTON_MSG_FAV + // + this.BUTTON_MSG_FAV.Location = new System.Drawing.Point(150, 156); + this.BUTTON_MSG_FAV.Name = "BUTTON_MSG_FAV"; + this.BUTTON_MSG_FAV.Size = new System.Drawing.Size(66, 28); + this.BUTTON_MSG_FAV.TabIndex = 12; + this.BUTTON_MSG_FAV.Text = "发收藏"; + this.BUTTON_MSG_FAV.UseVisualStyleBackColor = true; + this.BUTTON_MSG_FAV.Click += new System.EventHandler(this.BUTTON_MSG_FAVClick); + // + // BUTTON_MSG_MAP + // + this.BUTTON_MSG_MAP.Location = new System.Drawing.Point(79, 156); + this.BUTTON_MSG_MAP.Name = "BUTTON_MSG_MAP"; + this.BUTTON_MSG_MAP.Size = new System.Drawing.Size(66, 28); + this.BUTTON_MSG_MAP.TabIndex = 11; + this.BUTTON_MSG_MAP.Text = "发定位"; + this.BUTTON_MSG_MAP.UseVisualStyleBackColor = true; + this.BUTTON_MSG_MAP.Click += new System.EventHandler(this.BUTTON_MSG_MAPClick); + // + // BUTTON_MSG_CARD + // + this.BUTTON_MSG_CARD.Location = new System.Drawing.Point(6, 156); + this.BUTTON_MSG_CARD.Name = "BUTTON_MSG_CARD"; + this.BUTTON_MSG_CARD.Size = new System.Drawing.Size(66, 28); + this.BUTTON_MSG_CARD.TabIndex = 10; + this.BUTTON_MSG_CARD.Text = "发名片"; + this.BUTTON_MSG_CARD.UseVisualStyleBackColor = true; + this.BUTTON_MSG_CARD.Click += new System.EventHandler(this.BUTTON_MSG_CARDClick); + // + // BUTTON_MSG_FILE + // + this.BUTTON_MSG_FILE.Location = new System.Drawing.Point(222, 122); + this.BUTTON_MSG_FILE.Name = "BUTTON_MSG_FILE"; + this.BUTTON_MSG_FILE.Size = new System.Drawing.Size(66, 28); + this.BUTTON_MSG_FILE.TabIndex = 9; + this.BUTTON_MSG_FILE.Text = "发文件"; + this.BUTTON_MSG_FILE.UseVisualStyleBackColor = true; + this.BUTTON_MSG_FILE.Click += new System.EventHandler(this.BUTTON_MSG_FILEClick); + // + // BUTTON_MSG_GIF + // + this.BUTTON_MSG_GIF.Location = new System.Drawing.Point(150, 122); + this.BUTTON_MSG_GIF.Name = "BUTTON_MSG_GIF"; + this.BUTTON_MSG_GIF.Size = new System.Drawing.Size(66, 28); + this.BUTTON_MSG_GIF.TabIndex = 8; + this.BUTTON_MSG_GIF.Text = "发动图"; + this.BUTTON_MSG_GIF.UseVisualStyleBackColor = true; + this.BUTTON_MSG_GIF.Click += new System.EventHandler(this.BUTTON_MSG_GIFClick); + // + // BUTTON_MSG_PIC + // + this.BUTTON_MSG_PIC.Location = new System.Drawing.Point(78, 122); + this.BUTTON_MSG_PIC.Name = "BUTTON_MSG_PIC"; + this.BUTTON_MSG_PIC.Size = new System.Drawing.Size(66, 28); + this.BUTTON_MSG_PIC.TabIndex = 7; + this.BUTTON_MSG_PIC.Text = "发图片"; + this.BUTTON_MSG_PIC.UseVisualStyleBackColor = true; + this.BUTTON_MSG_PIC.Click += new System.EventHandler(this.BUTTON_MSG_PICClick); + // + // BUTTON_MSG_TEXT + // + this.BUTTON_MSG_TEXT.Location = new System.Drawing.Point(6, 122); + this.BUTTON_MSG_TEXT.Name = "BUTTON_MSG_TEXT"; + this.BUTTON_MSG_TEXT.Size = new System.Drawing.Size(66, 28); + this.BUTTON_MSG_TEXT.TabIndex = 6; + this.BUTTON_MSG_TEXT.Text = "发文本"; + this.BUTTON_MSG_TEXT.UseVisualStyleBackColor = true; + this.BUTTON_MSG_TEXT.Click += new System.EventHandler(this.BUTTON_MSG_TEXTClick); + // + // MSG_TXT_MESSAGE + // + this.MSG_TXT_MESSAGE.Location = new System.Drawing.Point(40, 51); + this.MSG_TXT_MESSAGE.Multiline = true; + this.MSG_TXT_MESSAGE.Name = "MSG_TXT_MESSAGE"; + this.MSG_TXT_MESSAGE.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.MSG_TXT_MESSAGE.Size = new System.Drawing.Size(248, 65); + this.MSG_TXT_MESSAGE.TabIndex = 5; + this.MSG_TXT_MESSAGE.Text = "🏑🎾⚾️💾⌨️🇦🇷🇦🇱🇲🇴❤️💟☸️"; + // + // label5 + // + this.label5.Location = new System.Drawing.Point(6, 51); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(48, 14); + this.label5.TabIndex = 4; + this.label5.Text = "uMsg:"; + // + // MSG_TXT_ATWXID + // + this.MSG_TXT_ATWXID.Location = new System.Drawing.Point(190, 24); + this.MSG_TXT_ATWXID.Name = "MSG_TXT_ATWXID"; + this.MSG_TXT_ATWXID.Size = new System.Drawing.Size(98, 21); + this.MSG_TXT_ATWXID.TabIndex = 3; + // + // MSG_TXT_WXID + // + this.MSG_TXT_WXID.Location = new System.Drawing.Point(40, 24); + this.MSG_TXT_WXID.Name = "MSG_TXT_WXID"; + this.MSG_TXT_WXID.Size = new System.Drawing.Size(105, 21); + this.MSG_TXT_WXID.TabIndex = 2; + this.MSG_TXT_WXID.Text = "filehelper"; + // + // label4 + // + this.label4.Location = new System.Drawing.Point(150, 27); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(47, 14); + this.label4.TabIndex = 1; + this.label4.Text = "@Wxid:"; + // + // label3 + // + this.label3.Location = new System.Drawing.Point(6, 27); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(41, 14); + this.label3.TabIndex = 0; + this.label3.Text = "Wxid:"; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.CHK_MONEY); + this.groupBox4.Controls.Add(this.CHK_ADDFRIEND); + this.groupBox4.Controls.Add(this.BUTTON_FRI_MARK); + this.groupBox4.Controls.Add(this.BUTTON_FRI_DEL); + this.groupBox4.Controls.Add(this.BUTTON_FRI_ADD); + this.groupBox4.Controls.Add(this.FRI_TXT_MSG); + this.groupBox4.Controls.Add(this.label8); + this.groupBox4.Controls.Add(this.FRI_TXT_SOURCE); + this.groupBox4.Controls.Add(this.label7); + this.groupBox4.Controls.Add(this.FRI_TXT_WXID); + this.groupBox4.Controls.Add(this.label6); + this.groupBox4.Location = new System.Drawing.Point(916, 203); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(295, 116); + this.groupBox4.TabIndex = 5; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "好友操作"; + // + // CHK_MONEY + // + this.CHK_MONEY.Checked = true; + this.CHK_MONEY.CheckState = System.Windows.Forms.CheckState.Checked; + this.CHK_MONEY.Location = new System.Drawing.Point(6, 94); + this.CHK_MONEY.Name = "CHK_MONEY"; + this.CHK_MONEY.Size = new System.Drawing.Size(72, 16); + this.CHK_MONEY.TabIndex = 14; + this.CHK_MONEY.Text = "接收转账"; + this.CHK_MONEY.UseVisualStyleBackColor = true; + // + // CHK_ADDFRIEND + // + this.CHK_ADDFRIEND.Checked = true; + this.CHK_ADDFRIEND.CheckState = System.Windows.Forms.CheckState.Checked; + this.CHK_ADDFRIEND.Location = new System.Drawing.Point(6, 78); + this.CHK_ADDFRIEND.Name = "CHK_ADDFRIEND"; + this.CHK_ADDFRIEND.Size = new System.Drawing.Size(72, 16); + this.CHK_ADDFRIEND.TabIndex = 13; + this.CHK_ADDFRIEND.Text = "通过好友"; + this.CHK_ADDFRIEND.UseVisualStyleBackColor = true; + // + // BUTTON_FRI_MARK + // + this.BUTTON_FRI_MARK.Location = new System.Drawing.Point(222, 78); + this.BUTTON_FRI_MARK.Name = "BUTTON_FRI_MARK"; + this.BUTTON_FRI_MARK.Size = new System.Drawing.Size(66, 28); + this.BUTTON_FRI_MARK.TabIndex = 12; + this.BUTTON_FRI_MARK.Text = "改备注"; + this.BUTTON_FRI_MARK.UseVisualStyleBackColor = true; + this.BUTTON_FRI_MARK.Click += new System.EventHandler(this.BUTTON_FRI_MARKClick); + // + // BUTTON_FRI_DEL + // + this.BUTTON_FRI_DEL.Location = new System.Drawing.Point(151, 78); + this.BUTTON_FRI_DEL.Name = "BUTTON_FRI_DEL"; + this.BUTTON_FRI_DEL.Size = new System.Drawing.Size(66, 28); + this.BUTTON_FRI_DEL.TabIndex = 11; + this.BUTTON_FRI_DEL.Text = "删好友"; + this.BUTTON_FRI_DEL.UseVisualStyleBackColor = true; + this.BUTTON_FRI_DEL.Click += new System.EventHandler(this.BUTTON_FRI_DELClick); + // + // BUTTON_FRI_ADD + // + this.BUTTON_FRI_ADD.Location = new System.Drawing.Point(78, 78); + this.BUTTON_FRI_ADD.Name = "BUTTON_FRI_ADD"; + this.BUTTON_FRI_ADD.Size = new System.Drawing.Size(66, 28); + this.BUTTON_FRI_ADD.TabIndex = 10; + this.BUTTON_FRI_ADD.Text = "加好友"; + this.BUTTON_FRI_ADD.UseVisualStyleBackColor = true; + this.BUTTON_FRI_ADD.Click += new System.EventHandler(this.BUTTON_FRI_ADDClick); + // + // FRI_TXT_MSG + // + this.FRI_TXT_MSG.Location = new System.Drawing.Point(40, 51); + this.FRI_TXT_MSG.MaxLength = 0; + this.FRI_TXT_MSG.Name = "FRI_TXT_MSG"; + this.FRI_TXT_MSG.Size = new System.Drawing.Size(248, 21); + this.FRI_TXT_MSG.TabIndex = 9; + this.FRI_TXT_MSG.Text = "有事找你!"; + // + // label8 + // + this.label8.Location = new System.Drawing.Point(6, 55); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(41, 14); + this.label8.TabIndex = 8; + this.label8.Text = "Text:"; + // + // FRI_TXT_SOURCE + // + this.FRI_TXT_SOURCE.Location = new System.Drawing.Point(196, 23); + this.FRI_TXT_SOURCE.Name = "FRI_TXT_SOURCE"; + this.FRI_TXT_SOURCE.Size = new System.Drawing.Size(92, 21); + this.FRI_TXT_SOURCE.TabIndex = 6; + this.FRI_TXT_SOURCE.Text = "14"; + this.FRI_TXT_SOURCE.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // label7 + // + this.label7.Location = new System.Drawing.Point(150, 27); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(56, 14); + this.label7.TabIndex = 5; + this.label7.Text = "Source:"; + // + // FRI_TXT_WXID + // + this.FRI_TXT_WXID.Location = new System.Drawing.Point(40, 23); + this.FRI_TXT_WXID.Name = "FRI_TXT_WXID"; + this.FRI_TXT_WXID.Size = new System.Drawing.Size(105, 21); + this.FRI_TXT_WXID.TabIndex = 4; + // + // label6 + // + this.label6.Location = new System.Drawing.Point(6, 27); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(41, 14); + this.label6.TabIndex = 3; + this.label6.Text = "Wxid:"; + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.CHK_INVITE); + this.groupBox5.Controls.Add(this.BUTTON_GROUP_CREATE); + this.groupBox5.Controls.Add(this.BUTTON_GROUP_NOTICE); + this.groupBox5.Controls.Add(this.BUTTON_GROUP_SETNICK); + this.groupBox5.Controls.Add(this.BUTTON_GROUP_EXIT); + this.groupBox5.Controls.Add(this.BUTTON_GROUP_KICK); + this.groupBox5.Controls.Add(this.BUTTON_GROUP_INV_2); + this.groupBox5.Controls.Add(this.BUTTON_GROUP_INV_1); + this.groupBox5.Controls.Add(this.GROUP_TXT_TEXT); + this.groupBox5.Controls.Add(this.label9); + this.groupBox5.Controls.Add(this.GROUP_TXT_WXID); + this.groupBox5.Controls.Add(this.label10); + this.groupBox5.Controls.Add(this.GROUP_TXT_GID); + this.groupBox5.Controls.Add(this.label11); + this.groupBox5.Location = new System.Drawing.Point(916, 325); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(295, 149); + this.groupBox5.TabIndex = 6; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "群操作"; + // + // CHK_INVITE + // + this.CHK_INVITE.Checked = true; + this.CHK_INVITE.CheckState = System.Windows.Forms.CheckState.Checked; + this.CHK_INVITE.Location = new System.Drawing.Point(6, 107); + this.CHK_INVITE.Name = "CHK_INVITE"; + this.CHK_INVITE.Size = new System.Drawing.Size(72, 36); + this.CHK_INVITE.TabIndex = 23; + this.CHK_INVITE.Text = "自动同意群聊邀请"; + this.CHK_INVITE.UseVisualStyleBackColor = true; + // + // BUTTON_GROUP_CREATE + // + this.BUTTON_GROUP_CREATE.Location = new System.Drawing.Point(222, 111); + this.BUTTON_GROUP_CREATE.Name = "BUTTON_GROUP_CREATE"; + this.BUTTON_GROUP_CREATE.Size = new System.Drawing.Size(66, 28); + this.BUTTON_GROUP_CREATE.TabIndex = 22; + this.BUTTON_GROUP_CREATE.Text = "创建群聊"; + this.BUTTON_GROUP_CREATE.UseVisualStyleBackColor = true; + this.BUTTON_GROUP_CREATE.Click += new System.EventHandler(this.BUTTON_GROUP_CREATEClick); + // + // BUTTON_GROUP_NOTICE + // + this.BUTTON_GROUP_NOTICE.Location = new System.Drawing.Point(150, 111); + this.BUTTON_GROUP_NOTICE.Name = "BUTTON_GROUP_NOTICE"; + this.BUTTON_GROUP_NOTICE.Size = new System.Drawing.Size(66, 28); + this.BUTTON_GROUP_NOTICE.TabIndex = 21; + this.BUTTON_GROUP_NOTICE.Text = "发群公告"; + this.BUTTON_GROUP_NOTICE.UseVisualStyleBackColor = true; + this.BUTTON_GROUP_NOTICE.Click += new System.EventHandler(this.BUTTON_GROUP_NOTICEClick); + // + // BUTTON_GROUP_SETNICK + // + this.BUTTON_GROUP_SETNICK.Location = new System.Drawing.Point(79, 111); + this.BUTTON_GROUP_SETNICK.Name = "BUTTON_GROUP_SETNICK"; + this.BUTTON_GROUP_SETNICK.Size = new System.Drawing.Size(66, 28); + this.BUTTON_GROUP_SETNICK.TabIndex = 20; + this.BUTTON_GROUP_SETNICK.Text = "改群名称"; + this.BUTTON_GROUP_SETNICK.UseVisualStyleBackColor = true; + this.BUTTON_GROUP_SETNICK.Click += new System.EventHandler(this.BUTTON_GROUP_SETNICKClick); + // + // BUTTON_GROUP_EXIT + // + this.BUTTON_GROUP_EXIT.Location = new System.Drawing.Point(222, 79); + this.BUTTON_GROUP_EXIT.Name = "BUTTON_GROUP_EXIT"; + this.BUTTON_GROUP_EXIT.Size = new System.Drawing.Size(66, 28); + this.BUTTON_GROUP_EXIT.TabIndex = 19; + this.BUTTON_GROUP_EXIT.Text = "退群"; + this.BUTTON_GROUP_EXIT.UseVisualStyleBackColor = true; + this.BUTTON_GROUP_EXIT.Click += new System.EventHandler(this.BUTTON_GROUP_EXITClick); + // + // BUTTON_GROUP_KICK + // + this.BUTTON_GROUP_KICK.Location = new System.Drawing.Point(150, 78); + this.BUTTON_GROUP_KICK.Name = "BUTTON_GROUP_KICK"; + this.BUTTON_GROUP_KICK.Size = new System.Drawing.Size(66, 28); + this.BUTTON_GROUP_KICK.TabIndex = 18; + this.BUTTON_GROUP_KICK.Text = "踢群成员"; + this.BUTTON_GROUP_KICK.UseVisualStyleBackColor = true; + this.BUTTON_GROUP_KICK.Click += new System.EventHandler(this.BUTTON_GROUP_KICKClick); + // + // BUTTON_GROUP_INV_2 + // + this.BUTTON_GROUP_INV_2.Location = new System.Drawing.Point(79, 78); + this.BUTTON_GROUP_INV_2.Name = "BUTTON_GROUP_INV_2"; + this.BUTTON_GROUP_INV_2.Size = new System.Drawing.Size(66, 28); + this.BUTTON_GROUP_INV_2.TabIndex = 17; + this.BUTTON_GROUP_INV_2.Text = "邀请链接"; + this.BUTTON_GROUP_INV_2.UseVisualStyleBackColor = true; + this.BUTTON_GROUP_INV_2.Click += new System.EventHandler(this.BUTTON_GROUP_INV_2Click); + // + // BUTTON_GROUP_INV_1 + // + this.BUTTON_GROUP_INV_1.Location = new System.Drawing.Point(6, 79); + this.BUTTON_GROUP_INV_1.Name = "BUTTON_GROUP_INV_1"; + this.BUTTON_GROUP_INV_1.Size = new System.Drawing.Size(66, 28); + this.BUTTON_GROUP_INV_1.TabIndex = 16; + this.BUTTON_GROUP_INV_1.Text = "直接拉群"; + this.BUTTON_GROUP_INV_1.UseVisualStyleBackColor = true; + this.BUTTON_GROUP_INV_1.Click += new System.EventHandler(this.BUTTON_GROUP_INV_1Click); + // + // GROUP_TXT_TEXT + // + this.GROUP_TXT_TEXT.Location = new System.Drawing.Point(69, 51); + this.GROUP_TXT_TEXT.MaxLength = 0; + this.GROUP_TXT_TEXT.Name = "GROUP_TXT_TEXT"; + this.GROUP_TXT_TEXT.Size = new System.Drawing.Size(219, 21); + this.GROUP_TXT_TEXT.TabIndex = 15; + // + // label9 + // + this.label9.Location = new System.Drawing.Point(6, 55); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(72, 14); + this.label9.TabIndex = 14; + this.label9.Text = "群名/公告:"; + // + // GROUP_TXT_WXID + // + this.GROUP_TXT_WXID.Location = new System.Drawing.Point(184, 23); + this.GROUP_TXT_WXID.Name = "GROUP_TXT_WXID"; + this.GROUP_TXT_WXID.Size = new System.Drawing.Size(104, 21); + this.GROUP_TXT_WXID.TabIndex = 13; + // + // label10 + // + this.label10.Location = new System.Drawing.Point(150, 27); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(41, 14); + this.label10.TabIndex = 12; + this.label10.Text = "Wxid:"; + // + // GROUP_TXT_GID + // + this.GROUP_TXT_GID.Location = new System.Drawing.Point(40, 23); + this.GROUP_TXT_GID.Name = "GROUP_TXT_GID"; + this.GROUP_TXT_GID.Size = new System.Drawing.Size(105, 21); + this.GROUP_TXT_GID.TabIndex = 11; + // + // label11 + // + this.label11.Location = new System.Drawing.Point(6, 27); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(41, 14); + this.label11.TabIndex = 10; + this.label11.Text = "群ID:"; + // + // groupBox6 + // + this.groupBox6.Controls.Add(this.URL_TXT_URL); + this.groupBox6.Controls.Add(this.URL_TXT_TEXT); + this.groupBox6.Controls.Add(this.label15); + this.groupBox6.Controls.Add(this.label14); + this.groupBox6.Controls.Add(this.URL_TXT_PIC); + this.groupBox6.Controls.Add(this.URL_TXT_TITLE); + this.groupBox6.Controls.Add(this.BUTTON_MSG_URL); + this.groupBox6.Controls.Add(this.label13); + this.groupBox6.Controls.Add(this.label12); + this.groupBox6.Location = new System.Drawing.Point(916, 480); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Size = new System.Drawing.Size(295, 87); + this.groupBox6.TabIndex = 7; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "发送链接"; + // + // URL_TXT_URL + // + this.URL_TXT_URL.Location = new System.Drawing.Point(167, 50); + this.URL_TXT_URL.Name = "URL_TXT_URL"; + this.URL_TXT_URL.Size = new System.Drawing.Size(87, 21); + this.URL_TXT_URL.TabIndex = 11; + this.URL_TXT_URL.Text = "https://www.baidu.com/"; + // + // URL_TXT_TEXT + // + this.URL_TXT_TEXT.Location = new System.Drawing.Point(167, 23); + this.URL_TXT_TEXT.Name = "URL_TXT_TEXT"; + this.URL_TXT_TEXT.Size = new System.Drawing.Size(87, 21); + this.URL_TXT_TEXT.TabIndex = 10; + this.URL_TXT_TEXT.Text = "儿童不宜,非礼勿视~~"; + // + // label15 + // + this.label15.Location = new System.Drawing.Point(133, 53); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(41, 15); + this.label15.TabIndex = 9; + this.label15.Text = "链接:"; + // + // label14 + // + this.label14.Location = new System.Drawing.Point(133, 27); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(41, 15); + this.label14.TabIndex = 8; + this.label14.Text = "摘要:"; + // + // URL_TXT_PIC + // + this.URL_TXT_PIC.Location = new System.Drawing.Point(40, 50); + this.URL_TXT_PIC.Name = "URL_TXT_PIC"; + this.URL_TXT_PIC.Size = new System.Drawing.Size(87, 21); + this.URL_TXT_PIC.TabIndex = 6; + this.URL_TXT_PIC.Text = "http://n.sinaimg.cn/sinacn/w591h591/20180123/acd1-fyqwiqi9140785.jpg"; + // + // URL_TXT_TITLE + // + this.URL_TXT_TITLE.Location = new System.Drawing.Point(40, 23); + this.URL_TXT_TITLE.Name = "URL_TXT_TITLE"; + this.URL_TXT_TITLE.Size = new System.Drawing.Size(87, 21); + this.URL_TXT_TITLE.TabIndex = 5; + this.URL_TXT_TITLE.Text = "公公和儿媳妇之间..."; + // + // BUTTON_MSG_URL + // + this.BUTTON_MSG_URL.Location = new System.Drawing.Point(260, 13); + this.BUTTON_MSG_URL.Name = "BUTTON_MSG_URL"; + this.BUTTON_MSG_URL.Size = new System.Drawing.Size(28, 66); + this.BUTTON_MSG_URL.TabIndex = 2; + this.BUTTON_MSG_URL.Text = "发送链接"; + this.BUTTON_MSG_URL.UseVisualStyleBackColor = true; + this.BUTTON_MSG_URL.Click += new System.EventHandler(this.BUTTON_MSG_URLClick); + // + // label13 + // + this.label13.Location = new System.Drawing.Point(6, 53); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(41, 15); + this.label13.TabIndex = 1; + this.label13.Text = "图片:"; + // + // label12 + // + this.label12.Location = new System.Drawing.Point(6, 27); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(41, 15); + this.label12.TabIndex = 0; + this.label12.Text = "标题:"; + // + // FRIEND_MENU + // + this.FRIEND_MENU.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FRIEND_MENU_GETUSERINFO, + this.FRIEND_MENU_TOP, + this.FRIEND_MENU_DISTURB}); + this.FRIEND_MENU.Name = "FRIEND_MENU"; + this.FRIEND_MENU.Size = new System.Drawing.Size(149, 70); + // + // FRIEND_MENU_GETUSERINFO + // + this.FRIEND_MENU_GETUSERINFO.Name = "FRIEND_MENU_GETUSERINFO"; + this.FRIEND_MENU_GETUSERINFO.Size = new System.Drawing.Size(148, 22); + this.FRIEND_MENU_GETUSERINFO.Text = "下载详细信息"; + this.FRIEND_MENU_GETUSERINFO.Click += new System.EventHandler(this.FRIEND_MENU_GETUSERINFOClick); + // + // FRIEND_MENU_TOP + // + this.FRIEND_MENU_TOP.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FRIEND_MENU_TOP_ON, + this.FRIEND_MENU_TOP_OFF}); + this.FRIEND_MENU_TOP.Name = "FRIEND_MENU_TOP"; + this.FRIEND_MENU_TOP.Size = new System.Drawing.Size(148, 22); + this.FRIEND_MENU_TOP.Text = "置顶"; + // + // FRIEND_MENU_TOP_ON + // + this.FRIEND_MENU_TOP_ON.Name = "FRIEND_MENU_TOP_ON"; + this.FRIEND_MENU_TOP_ON.Size = new System.Drawing.Size(124, 22); + this.FRIEND_MENU_TOP_ON.Text = "置顶聊天"; + this.FRIEND_MENU_TOP_ON.Click += new System.EventHandler(this.FRIEND_MENU_TOP_ONClick); + // + // FRIEND_MENU_TOP_OFF + // + this.FRIEND_MENU_TOP_OFF.Name = "FRIEND_MENU_TOP_OFF"; + this.FRIEND_MENU_TOP_OFF.Size = new System.Drawing.Size(124, 22); + this.FRIEND_MENU_TOP_OFF.Text = "取消置顶"; + this.FRIEND_MENU_TOP_OFF.Click += new System.EventHandler(this.FRIEND_MENU_TOP_OFFClick); + // + // FRIEND_MENU_DISTURB + // + this.FRIEND_MENU_DISTURB.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.FRIEND_MENU_DISTURB_ON, + this.FRIEND_MENU_DISTURB_OFF}); + this.FRIEND_MENU_DISTURB.Name = "FRIEND_MENU_DISTURB"; + this.FRIEND_MENU_DISTURB.Size = new System.Drawing.Size(148, 22); + this.FRIEND_MENU_DISTURB.Text = "免打扰"; + // + // FRIEND_MENU_DISTURB_ON + // + this.FRIEND_MENU_DISTURB_ON.Name = "FRIEND_MENU_DISTURB_ON"; + this.FRIEND_MENU_DISTURB_ON.Size = new System.Drawing.Size(136, 22); + this.FRIEND_MENU_DISTURB_ON.Text = "开启免打扰"; + this.FRIEND_MENU_DISTURB_ON.Click += new System.EventHandler(this.FRIEND_MENU_DISTURB_ONClick); + // + // FRIEND_MENU_DISTURB_OFF + // + this.FRIEND_MENU_DISTURB_OFF.Name = "FRIEND_MENU_DISTURB_OFF"; + this.FRIEND_MENU_DISTURB_OFF.Size = new System.Drawing.Size(136, 22); + this.FRIEND_MENU_DISTURB_OFF.Text = "取消免打扰"; + this.FRIEND_MENU_DISTURB_OFF.Click += new System.EventHandler(this.FRIEND_MENU_DISTURB_OFFClick); + // + // GROUP_MENU + // + this.GROUP_MENU.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GROUP_MENU_TOP, + this.GROUP_MENU_DISTURB, + this.GROUP_MENU_SAVE, + this.GROUP_MENU_NICK}); + this.GROUP_MENU.Name = "GROUP_MENU"; + this.GROUP_MENU.Size = new System.Drawing.Size(137, 92); + // + // GROUP_MENU_TOP + // + this.GROUP_MENU_TOP.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GROUP_MENU_TOP_ON, + this.GROUP_MENU_TOP_OFF}); + this.GROUP_MENU_TOP.Name = "GROUP_MENU_TOP"; + this.GROUP_MENU_TOP.Size = new System.Drawing.Size(136, 22); + this.GROUP_MENU_TOP.Text = "置顶"; + // + // GROUP_MENU_TOP_ON + // + this.GROUP_MENU_TOP_ON.Name = "GROUP_MENU_TOP_ON"; + this.GROUP_MENU_TOP_ON.Size = new System.Drawing.Size(124, 22); + this.GROUP_MENU_TOP_ON.Text = "置顶聊天"; + this.GROUP_MENU_TOP_ON.Click += new System.EventHandler(this.GROUP_MENU_TOP_ONClick); + // + // GROUP_MENU_TOP_OFF + // + this.GROUP_MENU_TOP_OFF.Name = "GROUP_MENU_TOP_OFF"; + this.GROUP_MENU_TOP_OFF.Size = new System.Drawing.Size(124, 22); + this.GROUP_MENU_TOP_OFF.Text = "取消置顶"; + this.GROUP_MENU_TOP_OFF.Click += new System.EventHandler(this.GROUP_MENU_TOP_OFFClick); + // + // GROUP_MENU_DISTURB + // + this.GROUP_MENU_DISTURB.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GROUP_MENU_DISTURB_ON, + this.GROUP_MENU_DISTURB_OFF}); + this.GROUP_MENU_DISTURB.Name = "GROUP_MENU_DISTURB"; + this.GROUP_MENU_DISTURB.Size = new System.Drawing.Size(136, 22); + this.GROUP_MENU_DISTURB.Text = "免打扰"; + // + // GROUP_MENU_DISTURB_ON + // + this.GROUP_MENU_DISTURB_ON.Name = "GROUP_MENU_DISTURB_ON"; + this.GROUP_MENU_DISTURB_ON.Size = new System.Drawing.Size(136, 22); + this.GROUP_MENU_DISTURB_ON.Text = "开启免打扰"; + this.GROUP_MENU_DISTURB_ON.Click += new System.EventHandler(this.GROUP_MENU_DISTURB_ONClick); + // + // GROUP_MENU_DISTURB_OFF + // + this.GROUP_MENU_DISTURB_OFF.Name = "GROUP_MENU_DISTURB_OFF"; + this.GROUP_MENU_DISTURB_OFF.Size = new System.Drawing.Size(136, 22); + this.GROUP_MENU_DISTURB_OFF.Text = "取消免打扰"; + this.GROUP_MENU_DISTURB_OFF.Click += new System.EventHandler(this.GROUP_MENU_DISTURB_OFFClick); + // + // GROUP_MENU_SAVE + // + this.GROUP_MENU_SAVE.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GROUP_MENU_SAVE_ON, + this.GROUP_MENU_SAVE_OFF}); + this.GROUP_MENU_SAVE.Name = "GROUP_MENU_SAVE"; + this.GROUP_MENU_SAVE.Size = new System.Drawing.Size(136, 22); + this.GROUP_MENU_SAVE.Text = "保存通讯录"; + // + // GROUP_MENU_SAVE_ON + // + this.GROUP_MENU_SAVE_ON.Name = "GROUP_MENU_SAVE_ON"; + this.GROUP_MENU_SAVE_ON.Size = new System.Drawing.Size(124, 22); + this.GROUP_MENU_SAVE_ON.Text = "保存群聊"; + this.GROUP_MENU_SAVE_ON.Click += new System.EventHandler(this.GROUP_MENU_SAVE_ONClick); + // + // GROUP_MENU_SAVE_OFF + // + this.GROUP_MENU_SAVE_OFF.Name = "GROUP_MENU_SAVE_OFF"; + this.GROUP_MENU_SAVE_OFF.Size = new System.Drawing.Size(124, 22); + this.GROUP_MENU_SAVE_OFF.Text = "取消保存"; + this.GROUP_MENU_SAVE_OFF.Click += new System.EventHandler(this.GROUP_MENU_SAVE_OFFClick); + // + // GROUP_MENU_NICK + // + this.GROUP_MENU_NICK.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GROUP_MENU_NICK_ON, + this.GROUP_MENU_NICK_OFF}); + this.GROUP_MENU_NICK.Name = "GROUP_MENU_NICK"; + this.GROUP_MENU_NICK.Size = new System.Drawing.Size(136, 22); + this.GROUP_MENU_NICK.Text = "显示群昵称"; + // + // GROUP_MENU_NICK_ON + // + this.GROUP_MENU_NICK_ON.Name = "GROUP_MENU_NICK_ON"; + this.GROUP_MENU_NICK_ON.Size = new System.Drawing.Size(160, 22); + this.GROUP_MENU_NICK_ON.Text = "开启显示群昵称"; + this.GROUP_MENU_NICK_ON.Click += new System.EventHandler(this.GROUP_MENU_NICK_ONClick); + // + // GROUP_MENU_NICK_OFF + // + this.GROUP_MENU_NICK_OFF.Name = "GROUP_MENU_NICK_OFF"; + this.GROUP_MENU_NICK_OFF.Size = new System.Drawing.Size(160, 22); + this.GROUP_MENU_NICK_OFF.Text = "取消显示群昵称"; + this.GROUP_MENU_NICK_OFF.Click += new System.EventHandler(this.GROUP_MENU_NICK_OFFClick); + // + // GROUPMEMBER_MENU + // + this.GROUPMEMBER_MENU.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.GROUPMEMBER_MENU_GETUSERINFO}); + this.GROUPMEMBER_MENU.Name = "GROUPMEMBER_MENU"; + this.GROUPMEMBER_MENU.Size = new System.Drawing.Size(149, 26); + // + // GROUPMEMBER_MENU_GETUSERINFO + // + this.GROUPMEMBER_MENU_GETUSERINFO.Name = "GROUPMEMBER_MENU_GETUSERINFO"; + this.GROUPMEMBER_MENU_GETUSERINFO.Size = new System.Drawing.Size(148, 22); + this.GROUPMEMBER_MENU_GETUSERINFO.Text = "下载详细信息"; + this.GROUPMEMBER_MENU_GETUSERINFO.Click += new System.EventHandler(this.GROUPMEMBER_MENU_GETUSERINFOClick); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1221, 578); + this.Controls.Add(this.groupBox6); + this.Controls.Add(this.groupBox5); + this.Controls.Add(this.groupBox4); + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.BUTTON_RE_LIST); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "WxRobot(2.6.8.52) --- kst"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.PIC_HEADIMG)).EndInit(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.tabPage4.ResumeLayout(false); + this.tabPage4.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + this.groupBox5.ResumeLayout(false); + this.groupBox5.PerformLayout(); + this.groupBox6.ResumeLayout(false); + this.groupBox6.PerformLayout(); + this.FRIEND_MENU.ResumeLayout(false); + this.GROUP_MENU.ResumeLayout(false); + this.GROUPMEMBER_MENU.ResumeLayout(false); + this.ResumeLayout(false); + + } + + } +} diff --git a/PCRobot/WxRobot/MainForm.cs b/PCRobot/WxRobot/MainForm.cs new file mode 100644 index 0000000..135ad06 --- /dev/null +++ b/PCRobot/WxRobot/MainForm.cs @@ -0,0 +1,1089 @@ +/* + * 由SharpDevelop创建。 + * 用户: Administrator + * 日期: 2019/6/4 星期二 + * 时间: 09:50 + * + * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 + */ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.IO; +using System.Net; +using System.Resources; +using System.Reflection; +namespace WxRobot +{ + /// + /// Description of MainForm. + /// + public partial class MainForm : Form + { + private static readonly object SequenceLock = new object(); + + WeChatAPI wxAPI = new WeChatAPI(); + + public MainForm() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + + Control.CheckForIllegalCrossThreadCalls = false; + + byte[] bytPath = new byte[260]; + int i = KstAPI.kst_GetPath(ref bytPath[0]); + string Path = System.Text.Encoding.GetEncoding("GB2312").GetString(bytPath, 0, bytPath.Length); + OPENWX_TXT_PATH.Text = Path; + + wxAPI.sc = new KstAPI.dele_Server_CallBack(Server_CallBack); + wxAPI.cc = new KstAPI.dele_Client_CallBack(Client_CallBack); + + wxAPI.Socket_Port = wxAPI.Socket_Init(Marshal.GetFunctionPointerForDelegate(wxAPI.sc), + Marshal.GetFunctionPointerForDelegate(wxAPI.cc)); + + if(wxAPI.Socket_Port == 0) + { + MessageBox.Show("通信端口创建失败,请重试!","错误"); + Environment.Exit(0); + } + + Log("[初始化完成]" + Environment.NewLine + "服务端口:" + wxAPI.Socket_Port.ToString() + Environment.NewLine + "通信句柄:" + wxAPI.Socket_Handle.ToString()); + + KstAPI.kst_DLLConnect(201906061,wxAPI.Socket_Port); + } + + void Log(string str) + { + str += Environment.NewLine + "--------------------------" + Environment.NewLine; + if(this.InvokeRequired == true) + { + this.Invoke((EventHandler)delegate + { + if(DEBUG_TXT.TextLength > 40000) + DEBUG_TXT.Clear(); + DEBUG_TXT.AppendText(str); + }); + } + else + { + DEBUG_TXT.AppendText(str); + } + } + + int FindRowIndex(ListView lv, string text, int columnIndex) + { + foreach (ListViewItem li in lv.Items) + { + if (li.SubItems[columnIndex].Text == text) + { + return li.Index; + } + } + return -1; + } + + Image ShowPicFromURL(string PicUrl) + { + WebRequest Request = (WebRequest)HttpWebRequest.Create(PicUrl); + WebResponse Resp = Request.GetResponse(); + Stream stream = Resp.GetResponseStream(); + Image Img = Image.FromStream(stream); + stream.Close(); + Resp.Close(); + return Img; + } + + string SaveFile(string mWxid, string uWxid, string fName, string uName, string uExt, byte[] fData) + { + string filePath = Directory.GetCurrentDirectory() + "\\" + mWxid + "\\" + fName + "\\" + uWxid; + if(!Directory.Exists(filePath)) + Directory.CreateDirectory(filePath); + filePath += "\\" + uName + "." + uExt; + FileStream fs = new FileStream(filePath, FileMode.Create); + fs.Write(fData, 0, fData.Length); + fs.Flush(); + fs.Close(); + return filePath; + } + + string Timestamp2DataTime(long Timestamp) + { + System.DateTime dtDateTime = new DateTime(1970,1,1,8,0,0,0); + dtDateTime = dtDateTime.AddSeconds( Timestamp ).ToLocalTime(); + return dtDateTime.ToString("yyyy-MM-dd HH:mm:ss"); + } + + string StrBetween(string sText, string sLeft, string sRight) + { + int i = sText.IndexOf(sLeft) + sLeft.Length; + string temp = sText.Substring(i, sText.IndexOf(sRight, i) - i); + return temp; + } + + //服务端通信回调 + void Server_CallBack(int sPoint, int so, int type, int buf, int buflen, int cso) + { + if(type == KstAPI.通信_连接成功) + { + wxAPI.Wx_Init(so,"C#-20190605"); + } + else if(type == KstAPI.通信_连接断开) + { + int uIndex = FindRowIndex(LOGIN_LIST,so.ToString(),4); + if(uIndex != -1) + { + if(so == wxAPI.Client_Handle) + { + LOGIN_TXT_SOCKET.Text = "[未选择]"; + LOGIN_TXT_NICK.Text = "[未选择]"; + LOGIN_TXT_WXID.Text = "[未选择]"; + PIC_HEADIMG.Image = null; + wxAPI.Client_Handle = 0; + wxAPI.Client_Wxid = ""; + } + LOGIN_LIST.Items.RemoveAt(uIndex); + } + } + else if(type == KstAPI.通信_数据到达) + { + byte[] s_buf = new byte[buflen + 1]; + KstAPI.RtlMoveMemory(s_buf,buf,buflen); + string s_Recv = Encoding.Default.GetString(s_buf).TrimEnd('\0'); + + //Log(s_Recv); + + JObject recvJson = JObject.Parse(s_Recv); + int RecvType = (int)recvJson["packtype"]; + + if(RecvType == KstAPI.回调_二维码) + { + string B64_QRCode = recvJson["qrcode"].ToString(); + byte[] imageBytes = Convert.FromBase64String(B64_QRCode); + MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length); + ms.Write(imageBytes, 0, imageBytes.Length); + PIC_HEADIMG.Image = System.Drawing.Image.FromStream(ms, true); + } + else if(RecvType == KstAPI.回调_登录成功) + { + lock (SequenceLock) + { + ListViewItem UserItem = new ListViewItem(); + + UserItem.Text = recvJson["nick"].ToString(); + UserItem.SubItems.Add(recvJson["wxid"].ToString()); + UserItem.SubItems.Add(recvJson["wxno"].ToString()); + UserItem.SubItems.Add(recvJson["himg"].ToString()); + UserItem.SubItems.Add(so.ToString()); + + LOGIN_LIST.Items.Add(UserItem); + } + } + else if(RecvType == KstAPI.回调_退出登陆) + { + int uIndex = FindRowIndex(LOGIN_LIST,so.ToString(),4); + if(uIndex != -1) + { + if(so == wxAPI.Client_Handle) + { + LOGIN_TXT_SOCKET.Text = "[未选择]"; + LOGIN_TXT_NICK.Text = "[未选择]"; + LOGIN_TXT_WXID.Text = "[未选择]"; + PIC_HEADIMG.Image = null; + wxAPI.Client_Handle = 0; + wxAPI.Client_Wxid = ""; + } + LOGIN_LIST.Items.RemoveAt(uIndex); + } + } + else if(RecvType == KstAPI.回调_好友列表) + { + JArray uList = recvJson.Value("list"); + FRIEND_LIST.BeginUpdate(); + FRIEND_GH_LIST.BeginUpdate(); + GROUP_LIST.BeginUpdate(); + for(int i=0;i("list"); + + GROUP_MEMBER_LIST.BeginUpdate(); + for(int i=0;i", ""); + string sTranID = StrBetween(mInfo.Msg, "transferid>"); + string sTime = StrBetween(mInfo.Msg, ""); + if(sState == "1" && mInfo.IsSend == 0) + wxAPI.Wx_GetMoney(so, mInfo.Wxid_1, sTranID, int.Parse(sTime)); + + } + } + else if(mInfo.Type == 49 && mInfo.Msg.IndexOf("邀请你加入群聊") != -1 && mInfo.IsSend == 0) + { + if(CHK_INVITE.Checked == true) + { + string inviteURL = StrBetween(mInfo.Msg, ""); + if(inviteURL != "") + wxAPI.Wx_GetA8Key(so, 1, mInfo.Wxid_1, inviteURL); + } + } + } + else if(RecvType == KstAPI.回调_语音消息 || + RecvType == KstAPI.回调_视频消息 || + RecvType == KstAPI.回调_文件消息 || + RecvType == KstAPI.回调_图片消息) + { + WeChatAPI.MsgInfo mInfo = new WeChatAPI.MsgInfo(); + mInfo.RecvWxid = recvJson["mywxid"].ToString(); + mInfo.Type = (int)recvJson["type"]; + mInfo.Time = Timestamp2DataTime((int)recvJson["time"]); + mInfo.IsSend = (int)recvJson["isme"]; + mInfo.LocalMsgID = (int)recvJson["msgid"]; + mInfo.ServerMsgID = recvJson["smsgid"].ToString(); + mInfo.Wxid_1 = recvJson["wxid1"].ToString(); + mInfo.Wxid_2 = recvJson["wxid2"].ToString(); + mInfo.Msg = Encoding.Default.GetString(Convert.FromBase64String(recvJson["msg"].ToString())); + if(RecvType == KstAPI.回调_语音消息) + { + byte[] silkByte = Convert.FromBase64String(recvJson["source"].ToString()); + mInfo.Source = SaveFile(mInfo.RecvWxid, mInfo.Wxid_1, "VOICE", mInfo.ServerMsgID, "silk", silkByte); + } + else if(RecvType == KstAPI.回调_图片消息) + { + byte[] ImageByte = Convert.FromBase64String(recvJson["source"].ToString()); + mInfo.Source = SaveFile(mInfo.RecvWxid, mInfo.Wxid_1, "IMAGE", mInfo.ServerMsgID, "jpg", ImageByte); + + string MaxPicPath = mInfo.Source.Replace(mInfo.ServerMsgID, mInfo.ServerMsgID + "_MAX"); + if(CHK_PIC.Checked == true) + //wxAPI.DownLoadPic(so, mInfo.Msg, MaxPicPath); + wxAPI.DownLoadPic(so, mInfo.Msg, "C:\\rra\\MAX_.jpg"); + } + else + { + mInfo.Source = recvJson["source"].ToString(); + } + + + string OutLog; + if(mInfo.IsSend == 0) + OutLog = "[接收消息]"; + else + OutLog = "[发送消息]"; + + OutLog += "[" + mInfo.Time + "][" + mInfo.RecvWxid + "]" + Environment.NewLine + + "Type:" + mInfo.Type.ToString() + Environment.NewLine + + "消息ID:" + mInfo.LocalMsgID.ToString() + Environment.NewLine + + "服务ID:" + mInfo.ServerMsgID + Environment.NewLine + + "Wxid_1:" + mInfo.Wxid_1 + Environment.NewLine + + "Wxid_2:" + mInfo.Wxid_2 + Environment.NewLine + + "消息内容:" + mInfo.Msg + Environment.NewLine + + "文件路径:" + mInfo.Source; + Log(OutLog); + } + else if(RecvType == KstAPI.回调_添加好友) + { + string RecvWxid = recvJson["mywxid"].ToString(); + int uType = (int)recvJson["id"]; + int uSource = (int)recvJson["scene"]; + string uWxid = recvJson["wxid"].ToString(); + Log("[添加好友][" + RecvWxid + "]" + Environment.NewLine + "返回类型:" + uType.ToString() + Environment.NewLine + + "添加来源:" + uSource.ToString() + Environment.NewLine + + "添加Wxid:" + uWxid); + if(uType == -44)//需要验证 + { + wxAPI.Wx_AddFriend(so, 2, uSource, uWxid, "", FRI_TXT_MSG.Text); + } + } + else if(RecvType == KstAPI.回调_下载信息) + { + WeChatAPI.UserInfo uInfo = new WeChatAPI.UserInfo(); + uInfo.Wxid = recvJson["info"]["Wxid"].ToString(); + uInfo.WxNo = recvJson["info"]["WxNo"].ToString(); + uInfo.Nick = recvJson["info"]["Nick"].ToString(); + uInfo.Nick = KstAPI.DeUnicode(uInfo.Nick); + uInfo.V1 = recvJson["info"]["v1"].ToString(); + uInfo.HImg = recvJson["info"]["HImg"].ToString(); + uInfo.Sex = uInfo.GetSex((int)recvJson["info"]["Sex"]); + uInfo.Address = recvJson["info"]["Address"].ToString(); + string OutLog = "[详细信息][" + recvJson["mywxid"].ToString() + "]" + Environment.NewLine + + "Wxid:" + uInfo.Wxid + Environment.NewLine + + "微信号:" + uInfo.WxNo + Environment.NewLine + + "昵称:" + uInfo.Nick + Environment.NewLine + + "性别:" + uInfo.Sex + Environment.NewLine + + "地区:" + uInfo.Address + Environment.NewLine + + "v1:" + uInfo.V1 + Environment.NewLine + + "头像:" + uInfo.HImg; + Log(OutLog); + } + else if(RecvType == KstAPI.回调_建群返回) + { + string cdata = recvJson["data"].ToString(); + string RecvWxid = recvJson["mywxid"].ToString(); + if(cdata == "Everything is OK") + { + string OutLog = "[建群返回][" + RecvWxid + "]" + Environment.NewLine; + string GroupID = recvJson["gid"].ToString(); + OutLog += "群ID:" + GroupID + Environment.NewLine + "成员:"+ Environment.NewLine; + JArray mList = recvJson.Value("list"); + for(int i=0;i 10) + { + if(HImgUrl.Substring(0,4) == "http") + { + PIC_HEADIMG.Image = ShowPicFromURL(HImgUrl); + } + } + } + else + { + wxAPI.Client_Handle = 0; + LOGIN_TXT_SOCKET.Text = "[未选择]"; + LOGIN_TXT_NICK.Text = "[未选择]"; + LOGIN_TXT_WXID.Text = "[未选择]"; + PIC_HEADIMG.Image = null; + } + } + + //好友列表框单击事件 + void FRIEND_LISTMouseClick(object sender, MouseEventArgs e) + { + if(e.Button == MouseButtons.Right) + { + ListViewItem xy = FRIEND_LIST.GetItemAt(e.X, e.Y); + if (xy != null) + { + Point point = this.PointToClient(FRIEND_LIST.PointToScreen(new Point(e.X, e.Y))); + this.FRIEND_MENU.Show(this, point); + } + } + else + { + if(FRIEND_LIST.FocusedItem != null) + { + string HImgUrl = FRIEND_LIST.FocusedItem.SubItems[4].Text; + if(HImgUrl.Length > 10) + { + if(HImgUrl.Substring(0,4) == "http") + { + PIC_HEADIMG.Image = ShowPicFromURL(HImgUrl); + } + } + + string uWxid = FRIEND_LIST.FocusedItem.SubItems[2].Text; + MSG_TXT_WXID.Text = uWxid; + FRI_TXT_WXID.Text = uWxid; + MSG_TXT_ATWXID.Text = ""; + } + } + } + //好友列表菜单操作 + //mType:0=下载信息 1=置顶 2=免打扰 + void FriendList_Menu(int mType,int mCheck = 0) + { + if(FRIEND_LIST.FocusedItem != null) + { + string uWxid = FRIEND_LIST.FocusedItem.SubItems[2].Text; + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(uWxid == "") + MessageBox.Show("请选择一个需要查询的Wxid!","错误"); + else + { + if(mType == 0) + wxAPI.Wx_GetUserInfo(wxAPI.Client_Handle, uWxid, string.Empty); + else + wxAPI.Wx_StateOpt(wxAPI.Client_Handle, mType, uWxid, mCheck); + + } + } + } + //好友列表菜单-下载详细信息被点击 + void FRIEND_MENU_GETUSERINFOClick(object sender, EventArgs e) + { + FriendList_Menu(0); + } + //好友列表菜单-置顶聊天 + void FRIEND_MENU_TOP_ONClick(object sender, EventArgs e) + { + FriendList_Menu(1,1); + } + //好友列表菜单-取消置顶 + void FRIEND_MENU_TOP_OFFClick(object sender, EventArgs e) + { + FriendList_Menu(1,0); + } + //好友列表菜单-开启免打扰 + void FRIEND_MENU_DISTURB_ONClick(object sender, EventArgs e) + { + FriendList_Menu(2,0); + } + //好友列表菜单-取消免打扰 + void FRIEND_MENU_DISTURB_OFFClick(object sender, EventArgs e) + { + FriendList_Menu(2,1); + } + //群列表框单击事件 + void GROUP_LISTMouseClick(object sender, MouseEventArgs e) + { + if(e.Button == MouseButtons.Right) + { + ListViewItem xy = GROUP_LIST.GetItemAt(e.X, e.Y); + if (xy != null) + { + Point point = this.PointToClient(GROUP_LIST.PointToScreen(new Point(e.X, e.Y))); + this.GROUP_MENU.Show(this, point); + } + } + else + { + if(GROUP_LIST.FocusedItem != null) + { + string uGroupID = GROUP_LIST.FocusedItem.SubItems[1].Text; + MSG_TXT_WXID.Text = uGroupID; + GROUP_TXT_GID.Text = uGroupID; + } + } + + } + //群列表菜单操作 + //mType:1=置顶 2=免打扰 3=保存通讯录 4=显示群员昵称 + void GroupList_Menu(int mType,int mCheck = 0) + { + if(GROUP_LIST.FocusedItem != null) + { + string uWxid = GROUP_LIST.FocusedItem.SubItems[1].Text; + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(uWxid == "") + MessageBox.Show("请选择一个需要查询的Wxid!","错误"); + else + wxAPI.Wx_StateOpt(wxAPI.Client_Handle, mType, uWxid, mCheck); + } + } + //群聊菜单-设置置顶 + void GROUP_MENU_TOP_ONClick(object sender, EventArgs e) + { + GroupList_Menu(1,1); + } + //群聊菜单-取消置顶 + void GROUP_MENU_TOP_OFFClick(object sender, EventArgs e) + { + GroupList_Menu(1,0); + } + //群聊菜单-开启免打扰 + void GROUP_MENU_DISTURB_ONClick(object sender, EventArgs e) + { + GroupList_Menu(2,0); + } + //群聊菜单-取消免打扰 + void GROUP_MENU_DISTURB_OFFClick(object sender, EventArgs e) + { + GroupList_Menu(2,1); + } + //群聊菜单-保存通讯录 + void GROUP_MENU_SAVE_ONClick(object sender, EventArgs e) + { + GroupList_Menu(3,1); + } + //群聊菜单-取消保存通讯录 + void GROUP_MENU_SAVE_OFFClick(object sender, EventArgs e) + { + GroupList_Menu(3,0); + } + //群聊菜单-显示群员昵称 + void GROUP_MENU_NICK_ONClick(object sender, EventArgs e) + { + GroupList_Menu(4,1); + } + //群聊菜单-取消显示群员昵称 + void GROUP_MENU_NICK_OFFClick(object sender, EventArgs e) + { + GroupList_Menu(4,0); + } + //群列表框双击事件 + void GROUP_LISTMouseDoubleClick(object sender, MouseEventArgs e) + { + if(GROUP_LIST.FocusedItem != null) + { + string uGroupID = GROUP_LIST.FocusedItem.SubItems[1].Text; + if(wxAPI.Client_Handle != 0) + { + GROUP_MEMBER_LIST.Items.Clear(); + wxAPI.Client_GroupID = uGroupID; + wxAPI.Wx_ReGroupList(wxAPI.Client_Handle, uGroupID); + } + } + } + //群员列表框单击事件 + void GROUP_MEMBER_LISTMouseClick(object sender, MouseEventArgs e) + { + if(e.Button == MouseButtons.Right) + { + ListViewItem xy = GROUP_MEMBER_LIST.GetItemAt(e.X, e.Y); + if (xy != null) + { + Point point = this.PointToClient(GROUP_MEMBER_LIST.PointToScreen(new Point(e.X, e.Y))); + this.GROUPMEMBER_MENU.Show(this, point); + } + } + else + { + if(GROUP_MEMBER_LIST.FocusedItem != null) + { + string uWxid = GROUP_MEMBER_LIST.FocusedItem.SubItems[2].Text; + MSG_TXT_ATWXID.Text = uWxid; + GROUP_TXT_WXID.Text = uWxid; + } + } + } + //群成员菜单-下载详细信息被点击 + void GROUPMEMBER_MENU_GETUSERINFOClick(object sender, EventArgs e) + { + if(GROUP_MEMBER_LIST.FocusedItem != null) + { + string uWxid = GROUP_MEMBER_LIST.FocusedItem.SubItems[2].Text; + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(uWxid == "") + MessageBox.Show("请选择一个需要查询的Wxid!","错误"); + else if(wxAPI.Client_GroupID == "") + MessageBox.Show("操作失败,群ID为空!","错误"); + else + wxAPI.Wx_GetUserInfo(wxAPI.Client_Handle, uWxid, wxAPI.Client_GroupID); + } + } + + //创建一个微信进程 + void BUTTON_OPEMWXClick(object sender, EventArgs e) + { + if(OPENWX_TXT_PATH.Text != "") + { + int dwPid = KstAPI.kst_CreateWx(OPENWX_TXT_PATH.Text, "WeChat.exe", "kst.dll", wxAPI.Socket_Port); + Log("[创建微信进程]"+Environment.NewLine+"进程PID:"+dwPid.ToString()); + } + } + + //刷新好友/公众号/群列表 + void BUTTON_RE_LISTClick(object sender, EventArgs e) + { + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else + FRIEND_LIST.Items.Clear(); + FRIEND_GH_LIST.Items.Clear(); + GROUP_LIST.Items.Clear(); + GROUP_MEMBER_LIST.Items.Clear(); + wxAPI.Wx_ReFriendList(wxAPI.Client_Handle); + } + //发送文本消息 + void BUTTON_MSG_TEXTClick(object sender, EventArgs e) + { + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(MSG_TXT_WXID.Text == "") + MessageBox.Show("请输入接收消息者的Wxid!","错误"); + else if(MSG_TXT_MESSAGE.Text == "") + MessageBox.Show("请输入欲发送的消息内容!","错误"); + else + { + string uMessage = KstAPI.EnUnicode(MSG_TXT_MESSAGE.Text); + wxAPI.Wx_SendTextMsg(wxAPI.Client_Handle, MSG_TXT_WXID.Text, MSG_TXT_ATWXID.Text, uMessage); + } + } + //发送图片消息 + void BUTTON_MSG_PICClick(object sender, EventArgs e) + { + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(MSG_TXT_WXID.Text == "") + MessageBox.Show("请输入接收消息者的Wxid!","错误"); + else if(!File.Exists(MSG_TXT_MESSAGE.Text)) + MessageBox.Show("欲发送的图片文件不存在!","错误"); + else + wxAPI.Wx_SendFileMsg(wxAPI.Client_Handle, 1, MSG_TXT_WXID.Text, MSG_TXT_MESSAGE.Text); + } + //发送GIF动图 + void BUTTON_MSG_GIFClick(object sender, EventArgs e) + { + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(MSG_TXT_WXID.Text == "") + MessageBox.Show("请输入接收消息者的Wxid!","错误"); + else if(!File.Exists(MSG_TXT_MESSAGE.Text)) + MessageBox.Show("欲发送的GIF文件不存在!","错误"); + else + wxAPI.Wx_SendFileMsg(wxAPI.Client_Handle, 2, MSG_TXT_WXID.Text, MSG_TXT_MESSAGE.Text); + } + //发送文件/视频 + void BUTTON_MSG_FILEClick(object sender, EventArgs e) + { + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(MSG_TXT_WXID.Text == "") + MessageBox.Show("请输入接收消息者的Wxid!","错误"); + else if(!File.Exists(MSG_TXT_MESSAGE.Text)) + MessageBox.Show("欲发送的文件不存在!","错误"); + else + wxAPI.Wx_SendFileMsg(wxAPI.Client_Handle, 3, MSG_TXT_WXID.Text, MSG_TXT_MESSAGE.Text); + } + //发送名片 + void BUTTON_MSG_CARDClick(object sender, EventArgs e) + { + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(MSG_TXT_WXID.Text == "") + MessageBox.Show("请输入接收消息者的Wxid!","错误"); + else + wxAPI.Wx_SendCardMsg(wxAPI.Client_Handle, 1, MSG_TXT_WXID.Text, wxAPI.Client_Wxid); + } + //发送定位消息 + void BUTTON_MSG_MAPClick(object sender, EventArgs e) + { + Assembly mAsm = Assembly.GetExecutingAssembly(); + ResourceManager resMan = new ResourceManager("WxRobot.API.WxXML", mAsm); + string XML = resMan.GetString("MAP_XML"); + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(MSG_TXT_WXID.Text == "") + MessageBox.Show("请输入接收消息者的Wxid!","错误"); + else + { + XML = XML.Replace("*坐标X*", "39.903740"); + XML = XML.Replace("*坐标Y*", "116.397827"); + XML = XML.Replace("*主标题*", "天安门广场"); + XML = XML.Replace("*副标题*", "北京市东城区东长安街"); + wxAPI.Wx_SendMapMsg(wxAPI.Client_Handle, MSG_TXT_WXID.Text, XML); + } + } + //发送收藏消息 + void BUTTON_MSG_FAVClick(object sender, EventArgs e) + { + int uIndex; + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(MSG_TXT_WXID.Text == "") + MessageBox.Show("请输入接收消息者的Wxid!","错误"); + else if(!int.TryParse(MSG_TXT_MESSAGE.Text, out uIndex)) + MessageBox.Show("请在[uMsg]输入欲发送的收藏序号(由0开始)","错误"); + else + wxAPI.Wx_SendFavMsg(wxAPI.Client_Handle, MSG_TXT_WXID.Text, uIndex); + } + //发送自定义链接 + void BUTTON_MSG_URLClick(object sender, EventArgs e) + { + Assembly mAsm = Assembly.GetExecutingAssembly(); + ResourceManager resMan = new ResourceManager("WxRobot.API.WxXML", mAsm); + string XML = resMan.GetString("URL_XML"); + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(MSG_TXT_WXID.Text == "") + MessageBox.Show("请输入接收消息者的Wxid!","错误"); + else if(URL_TXT_TITLE.Text == "") + MessageBox.Show("请输入链接消息的标题!","错误"); + else if(URL_TXT_TEXT.Text == "") + MessageBox.Show("请输入链接消息的摘要!","错误"); + else if(URL_TXT_PIC.Text == "") + MessageBox.Show("请输入链接消息的图片地址!","错误"); + else if(URL_TXT_URL.Text == "") + MessageBox.Show("请输入链接消息的链接地址!","错误"); + else + { + XML = XML.Replace("*MYWXID*",wxAPI.Client_Wxid); + XML = XML.Replace("*标题*",URL_TXT_TITLE.Text); + XML = XML.Replace("*摘要*",URL_TXT_TEXT.Text); + XML = XML.Replace("*图片*",URL_TXT_PIC.Text); + XML = XML.Replace("*地址*",URL_TXT_URL.Text); + wxAPI.Wx_SendURLMsg(wxAPI.Client_Handle, MSG_TXT_WXID.Text, wxAPI.Client_Wxid, XML); + } + } + //加好友 + void BUTTON_FRI_ADDClick(object sender, EventArgs e) + { + int uSource; + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(FRI_TXT_WXID.Text == "") + MessageBox.Show("请输入需要添加的Wxid!","错误"); + else if(!int.TryParse(FRI_TXT_SOURCE.Text,out uSource)) + MessageBox.Show("请输入需要添加的Wxid!","错误"); + else + wxAPI.Wx_AddFriend(wxAPI.Client_Handle, 1, uSource, FRI_TXT_WXID.Text, "", FRI_TXT_MSG.Text); + } + //删好友 + void BUTTON_FRI_DELClick(object sender, EventArgs e) + { + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(FRI_TXT_WXID.Text == "") + MessageBox.Show("请输入需要删除的好友Wxid!","错误"); + else + wxAPI.Wx_DelFriend(wxAPI.Client_Handle, FRI_TXT_WXID.Text); + } + //设置好友备注 + void BUTTON_FRI_MARKClick(object sender, EventArgs e) + { + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(FRI_TXT_WXID.Text == "") + MessageBox.Show("请输入需要设置备注的好友Wxid!","错误"); + else + { + string uMark = KstAPI.EnUnicode(FRI_TXT_MSG.Text); + wxAPI.Wx_SetMark(wxAPI.Client_Handle, FRI_TXT_WXID.Text, uMark); + } + } + //群聊邀请-直接拉群(批量) + void BUTTON_GROUP_INV_1Click(object sender, EventArgs e) + { + int c = FRIEND_LIST.CheckedItems.Count; + if(wxAPI.Client_Handle == 0) + MessageBox.Show("请选择一个操作账号!","错误"); + else if(GROUP_TXT_GID.Text == "") + MessageBox.Show("请输入需要邀请的群ID!","错误"); + else if(c < 1) + MessageBox.Show("请在好友列表框勾选需要邀请的好友","错误"); + else + { + string[] Array_Wxid = new string[c]; + for(int i=0;i 40) + MessageBox.Show("勾选不能超过40人","错误"); + else + { + string[] Array_Wxid = new string[c]; + for(int i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 137, 17 + + + 250, 17 + + + 41 + + \ No newline at end of file diff --git a/PCRobot/WxRobot/Program.cs b/PCRobot/WxRobot/Program.cs new file mode 100644 index 0000000..3a5e44a --- /dev/null +++ b/PCRobot/WxRobot/Program.cs @@ -0,0 +1,31 @@ +/* + * 由SharpDevelop创建。 + * 用户: Administrator + * 日期: 2019/6/4 星期二 + * 时间: 09:50 + * + * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件 + */ +using System; +using System.Windows.Forms; + +namespace WxRobot +{ + /// + /// Class with program entry point. + /// + internal sealed class Program + { + /// + /// Program entry point. + /// + [STAThread] + private static void Main(string[] args) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + } +} diff --git a/PCRobot/WxRobot/Properties/AssemblyInfo.cs b/PCRobot/WxRobot/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..912d4b5 --- /dev/null +++ b/PCRobot/WxRobot/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WxRobot")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WxRobot")] +[assembly: AssemblyCopyright("Copyright 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.*")] diff --git a/PCRobot/WxRobot/WxRobot.csproj b/PCRobot/WxRobot/WxRobot.csproj new file mode 100644 index 0000000..441338d --- /dev/null +++ b/PCRobot/WxRobot/WxRobot.csproj @@ -0,0 +1,98 @@ + + + + {665F185D-37F4-4D73-9685-4C0AB95C08BD} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Debug + AnyCPU + WinExe + WxRobot + WxRobot + v4.0 + Properties + False + False + False + OnBuildSuccess + False + False + False + obj\$(Configuration)\ + 4 + + + x86 + 4194304 + False + Auto + 4096 + + + ..\ + True + Full + False + True + DEBUG;TRACE + obj\ + + + C:\Users\Administrator\Desktop\定制\C# WxHook\ + False + None + True + False + TRACE + obj\ + + + bin\debug\ + + + + 4.0 + + + False + C:\Users\George\Desktop\Newtonsoft.Json.dll + + + + 3.5 + + + + 3.5 + + + + + + 3.5 + + + + + + + Form + + + MainForm.cs + + + + + + + + + + + + MainForm.cs + + + + + \ No newline at end of file diff --git a/PCRobot/WxRobot/WxRobot.sln b/PCRobot/WxRobot/WxRobot.sln new file mode 100644 index 0000000..3beb1ed --- /dev/null +++ b/PCRobot/WxRobot/WxRobot.sln @@ -0,0 +1,18 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +# SharpDevelop 5.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WxRobot", "WxRobot.csproj", "{665F185D-37F4-4D73-9685-4C0AB95C08BD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {665F185D-37F4-4D73-9685-4C0AB95C08BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {665F185D-37F4-4D73-9685-4C0AB95C08BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {665F185D-37F4-4D73-9685-4C0AB95C08BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {665F185D-37F4-4D73-9685-4C0AB95C08BD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/PCRobot/WxRobot/app.config b/PCRobot/WxRobot/app.config new file mode 100644 index 0000000..970c80b --- /dev/null +++ b/PCRobot/WxRobot/app.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/PCRobot/WxRobot/packages.config b/PCRobot/WxRobot/packages.config new file mode 100644 index 0000000..5710d21 --- /dev/null +++ b/PCRobot/WxRobot/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/PCRobot/XxType.cs b/PCRobot/XxType.cs new file mode 100644 index 0000000..a195f7c --- /dev/null +++ b/PCRobot/XxType.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PCRobot +{ + public enum XxType + { + 二维码=10000, + 登录成功=10001, + 退出登陆=10002, + + 接收消息=20000, + + 添加好友=30000, + 获取聊天对象=30001, + 建群返回=30002, + A8Key=30003, + + 语音消息 =40000, + 文件消息=40001, + 视频消息=40002, + 图片消息=40003, + 文字消息=40004, + + 好友列表=50000, + 群员列表=50001, + + 邀请入群=60000, + + + 微信转账=70000, + + + 好友请求=80000, + } + + + public class QrMsg + { + public XxType msgType { get; set; } = XxType.二维码; + + public string base64Data { get; set; } + } + + /// + /// 登录消息 + /// + public class LgSucMsg + { + public XxType msgType { get; set; } = XxType.登录成功; + + public string nickName { get; set; } + + public string wxId { get; set; } + + public string wxNo { get; set; } + + public string headImg { get; set; } + + public int packType { get; set; } + + public int pid { get; set; } + + public int hwnd { get; set; } + + public string phone { get; set; } + } + + public class msgBase + { + public string recvWxid { get; set; } + public string time { get; set; } + public int isSend { get; set; } + public int localMsgID { get; set; } + public string serverMsgID { get; set; } + public string wxid_1 { get; set; } + public string wxid_2 { get; set; } + public string msg { get; set; } + public string source { get; set; } + } + + /// + /// 语音消息 + /// + public class Vom:msgBase + { + public XxType msgType { get; set; } = XxType.语音消息; + } + /// + /// 文字消息 + /// + public class Tm : msgBase + { + public XxType msgType { get; set; } = XxType.文字消息; + } + + /// + /// 文字消息 + /// + public class Pm : msgBase + { + public XxType msgType { get; set; } = XxType.图片消息; + } + + /// + /// 文件消息 + /// + public class Fm : msgBase + { + public XxType msgType { get; set; } = XxType.文件消息; + } + + /// + /// 视频消息 + /// + public class Vm : msgBase + { + public XxType msgType { get; set; } = XxType.视频消息; + } + +} diff --git a/PCRobot/packages.config b/PCRobot/packages.config new file mode 100644 index 0000000..1c9526d --- /dev/null +++ b/PCRobot/packages.config @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PCRobot/tencent_qqpim_72px_1127550_easyicon.net.ico b/PCRobot/tencent_qqpim_72px_1127550_easyicon.net.ico new file mode 100644 index 0000000..8def10c Binary files /dev/null and b/PCRobot/tencent_qqpim_72px_1127550_easyicon.net.ico differ diff --git a/SelfFix/App.config b/SelfFix/App.config new file mode 100644 index 0000000..74ade9d --- /dev/null +++ b/SelfFix/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/SelfFix/Program.cs b/SelfFix/Program.cs new file mode 100644 index 0000000..e430a09 --- /dev/null +++ b/SelfFix/Program.cs @@ -0,0 +1,320 @@ +using SelfFix.Properties; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; + +namespace SelfFix +{ + class Program + { + static void Main(string[] args) + { + try + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("正在检测软件运行环境..."); + var path = Environment.CurrentDirectory; + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("正在检测是否有运行的软件"); + + #region 关闭运行的程序 + Process[] MyProcesses = Process.GetProcesses(); + var proNames = new List() { "FLSystem".ToLower(), "VersionUpdate".ToLower() }; + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToLower(); + foreach (var proName in proNames) + { + if (name == proName && MyProcess.MainModule.FileName.StartsWith(path)) + { + try + { + Console.WriteLine($"关闭运行中的软件:{MyProcess.Id},路径:{MyProcess.MainModule.FileName},进程名称:{name}"); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + } + catch (Exception ex) + { + Console.WriteLine($"未知异常:{ex.Message} - {ex.StackTrace}"); + } + } + #endregion + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine($"正在检测更新配置文件状态"); + #region 检查配置文件 + var vuName = "VersionUpdate"; + var xml = path + $@"\{vuName}.xml"; + + for (int i = 0; i < 3; i++) + { + try + { + if (File.Exists(xml)) + try { File.Delete(xml); } catch { } + FileStream fs = new FileStream(xml, FileMode.OpenOrCreate, FileAccess.ReadWrite); + StreamWriter sw = new StreamWriter(fs); + sw.Write(Resources.VersionUpdate); + sw.Flush(); + sw.Close(); + if (File.Exists(xml)) + break; + } + catch (Exception) + { } + } + #endregion + + var exe = path + $@"\{vuName}.exe"; + if (File.Exists(exe)) + try { File.Delete(exe); } catch { } + + Console.WriteLine($"正在检测更新程序"); + WriteResource(exe, Resources.VersionUpdate1); + + try + { + MapPath(@"Cache\VersionUpdate"); + var versions = GetVersions(xml); + if (versions.Count > 0) + { + Console.ForegroundColor = ConsoleColor.White; + foreach (var item in versions) + { + Console.WriteLine("下载文件:" + $@"{path}\Cache\VersionUpdate\{item.Name}_{item.Version}.zip"); + DownloadFile(item.Url, $@"{path}\Cache\VersionUpdate\{item.Name}_{item.Version}.zip"); + } + } + } + catch (Exception ex) + { } + Console.ForegroundColor = ConsoleColor.Black; + Console.WriteLine("修复完毕!!!!"); + StartProcess("VersionUpdate.exe", "FLSystem.exe"); + for (int i = 5; i < 1; i++) + { + Console.WriteLine($"{i}秒后自动退出"); + Thread.Sleep(1000); + } + } + catch (Exception) + { } + } + + public static void WriteResource(string fileName, byte[] writeData) + { + var writeDataStr = BitConverter.ToString(writeData); + if (File.Exists(fileName)) + { + var oldFile = File.ReadAllBytes(fileName); + var oldFileStr = BitConverter.ToString(oldFile);//将字节数组装换为字符串 + if (writeDataStr != oldFileStr) + { + File.WriteAllBytes(fileName, writeData); + } + } + else File.WriteAllBytes(fileName, writeData); + } + + public static string MapPath(string path = "", bool CreateDirectory = true) + { + if (string.IsNullOrWhiteSpace(path)) + { + return Environment.CurrentDirectory + "\\"; + } + path = Path.Combine(Environment.CurrentDirectory + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + return path; + } + + public static List GetVersions(string XMLPath) + { + List msgs = new List(); + try + { + XmlDocument XmlDoc = new XmlDocument(); + + if (!File.Exists(XMLPath)) throw new Exception("找不到VersionUpdate.xml必备文件!"); + //使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件. + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + XmlNode xn = XmlDoc.SelectSingleNode("Files"); + // 得到根节点的所有子节点 + XmlNodeList xnl = xn.ChildNodes; + foreach (XmlNode node in xnl) + { + try + { + var Name = node.Attributes["Name"].Value; + var Url = node.Attributes["Url"].Value; + var CurVersion = Version.Parse(node.Attributes["Version"].Value); + + XmlDocument temp_xml = new XmlDocument(); + temp_xml.Load(Url); + var temp_node = temp_xml.SelectSingleNode("History"); + + var temp_datas = temp_node.SelectNodes("Data"); + //更新内容 + List temp_update = new List(); + foreach (XmlNode item in temp_datas) + { + var ver = Version.Parse(item.Attributes["Ver"].Value); + if (ver > CurVersion) + { + //发现有更新 + temp_update.Add(item); + } + } + + if (temp_update.Count > 0) + { + var MSG = new UpdateClass() { Name = Name, Url = temp_update[0].Attributes["Url"].Value, Message = new List(), Version = temp_update[0].Attributes["Ver"].Value }; + msgs.Add(MSG); + foreach (var item in temp_update) + { + var temps = item.Attributes["Msg"].Value.Split(new string[] { "[br]" }, StringSplitOptions.None); + foreach (var temp in temps) MSG.Message.Add(temp); + } + } + } + catch (Exception) + { + + } + } + } + } + catch (Exception) + { } + return msgs; + } + + public static bool DownloadFile(string URL, string filename) + { + try + { + float percent = 0; + if (File.Exists(filename)) File.Delete(filename); + + Stream st = null; + Stream so = null; + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + + totalDownloadedByte = osize + totalDownloadedByte; + //Application.DoEvents(); + so.Write(by, 0, osize); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + //Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + return true; + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + catch (Exception ex) + { + } + return false; + } + + public class UpdateClass + { + public string Name { get; set; } + public string Url { get; set; } + public string Version { get; set; } + public List Message { get; set; } + } + + public static bool StartProcess(string filename, string param = null) + { + try + { + if (!File.Exists(filename)) + return false; + + try + { + if (!System.IO.File.Exists(filename)) + return false; + + if (param != null) + System.Diagnostics.Process.Start(filename, param); + else + System.Diagnostics.Process.Start(filename); + System.Threading.Thread.Sleep(100); + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + } + } +} diff --git a/SelfFix/Properties/AssemblyInfo.cs b/SelfFix/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d41fbf1 --- /dev/null +++ b/SelfFix/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("SelfFix")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SelfFix")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("b89f11e0-446e-47a6-8ffd-e9aa1b3942e5")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SelfFix/Properties/Resources.Designer.cs b/SelfFix/Properties/Resources.Designer.cs new file mode 100644 index 0000000..381280b --- /dev/null +++ b/SelfFix/Properties/Resources.Designer.cs @@ -0,0 +1,87 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace SelfFix.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SelfFix.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 <?xml version="1.0" encoding="utf-8"?> + ///<Files> + /// <File Name="核心组件" Version="2021.11.3.1647" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=MainUpdate" /> + /// <File Name="Library组件" Version="2020.02.16.1" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=LibraryUpdate" /> + /// <File Name="Dev界面组件" Version="2019.12.27.1" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=DevUpdate" /> + /// <File Name="QQ通讯组件" Version="2020.7.27.1" Url="http://version.api.52cmg [字符串的其余部分被截断]"; 的本地化字符串。 + /// + internal static string VersionUpdate { + get { + return ResourceManager.GetString("VersionUpdate", resourceCulture); + } + } + + /// + /// 查找 System.Byte[] 类型的本地化资源。 + /// + internal static byte[] VersionUpdate1 { + get { + object obj = ResourceManager.GetObject("VersionUpdate1", resourceCulture); + return ((byte[])(obj)); + } + } + } +} diff --git a/SelfFix/Properties/Resources.resx b/SelfFix/Properties/Resources.resx new file mode 100644 index 0000000..18d921b --- /dev/null +++ b/SelfFix/Properties/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\VersionUpdate.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + + ..\Resources\VersionUpdate.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SelfFix/Resources/VersionUpdate.exe b/SelfFix/Resources/VersionUpdate.exe new file mode 100644 index 0000000..a02a963 Binary files /dev/null and b/SelfFix/Resources/VersionUpdate.exe differ diff --git a/SelfFix/Resources/VersionUpdate.xml b/SelfFix/Resources/VersionUpdate.xml new file mode 100644 index 0000000..1febaed --- /dev/null +++ b/SelfFix/Resources/VersionUpdate.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/SelfFix/SelfFix.csproj b/SelfFix/SelfFix.csproj new file mode 100644 index 0000000..4948271 --- /dev/null +++ b/SelfFix/SelfFix.csproj @@ -0,0 +1,81 @@ + + + + + Debug + AnyCPU + {B89F11E0-446E-47A6-8FFD-E9AA1B3942E5} + Exe + SelfFix + 软件异常点我修复 + v4.0 + 512 + true + true + + + + AnyCPU + true + full + false + ..\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + app.manifest + + + 修复620.ico + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + \ No newline at end of file diff --git a/SelfFix/app.manifest b/SelfFix/app.manifest new file mode 100644 index 0000000..60a45a2 --- /dev/null +++ b/SelfFix/app.manifest @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SelfFix/修复620.ico b/SelfFix/修复620.ico new file mode 100644 index 0000000..9add55c Binary files /dev/null and b/SelfFix/修复620.ico differ diff --git a/XiaoxieDemo.sln b/XiaoxieDemo.sln new file mode 100644 index 0000000..74d9e09 --- /dev/null +++ b/XiaoxieDemo.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.960 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XiaoxieDemo", "XiaoxieDemo\XiaoxieDemo.csproj", "{CE2A5F83-E0E8-4C1A-90E2-C27C4203FDAF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CE2A5F83-E0E8-4C1A-90E2-C27C4203FDAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE2A5F83-E0E8-4C1A-90E2-C27C4203FDAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE2A5F83-E0E8-4C1A-90E2-C27C4203FDAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE2A5F83-E0E8-4C1A-90E2-C27C4203FDAF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2874B528-32E1-4B38-AD0E-B98752717B81} + EndGlobalSection +EndGlobal diff --git a/应用/Activity/Activity.csproj b/应用/Activity/Activity.csproj new file mode 100644 index 0000000..a2f00ce --- /dev/null +++ b/应用/Activity/Activity.csproj @@ -0,0 +1,156 @@ + + + + + Debug + AnyCPU + {ACA7A9DE-5EC4-42F7-A8DE-9AA6119F17AA} + Library + Properties + Activity + Activity + v4.6.1 + 512 + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + Form + + + EditActivityForm.cs + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + Form + + + TrophyForm.cs + + + + + EditActivityForm.cs + Designer + + + MainForm.cs + Designer + + + TrophyForm.cs + Designer + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + + + + + + + + + + + + + + + + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5} + SqlSugar + False + + + + \ No newline at end of file diff --git a/应用/Activity/Class1.cs b/应用/Activity/Class1.cs new file mode 100644 index 0000000..a6be98f --- /dev/null +++ b/应用/Activity/Class1.cs @@ -0,0 +1,212 @@ +using Activity.Entitys; +using Activity.Properties; +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Activity +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.活动; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 定义的变量 + + public static Config Config; // 插件配置 + private MainForm mainForm = null; //主窗体 + + #endregion + + + + public override void ShowForm() + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.Activate(); + } + + public override void Start() + { + var session = ApiClient.GetSession(); + + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) session.CreateTable(); + #endregion + + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public enum GameType : int + { + 幸运楼层 = 1 + } + public class Game + { + public string Groupid { get; set; } + public GameType GameType { get; set; } + public List Members{ get; set; } + /// + /// 打乱顺序 + /// + public List MembersOver { get; set; } + public bool Gameover { get; set; } + public Game() + { + this.Groupid = string.Empty; + this.Members = new List(); + } + + public int GetIndex(string username) + { + for (int i = 0; i < Members.Count; i++) + { + if (Members[i].ToString() == username) return i; + } + return -1; + } + } + private Dictionary Games = new Dictionary(); + + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + var client = e.Sender as Chat.Framework.WXSdk.Implement.WXClientImpl_IPAD; + try + { + if (string.IsNullOrEmpty(e.Groupid)) return; + + + if (e.Message == "开始游戏") + { + + var group = client.GetContact(e.Groupid); + if (group.ChatRoomOwner == e.Username) + { + if (Games.ContainsKey(e.Groupid)) + { + if (!Games[e.Groupid].Gameover) throw new Exception("当前游戏尚未结束,请耐心等待!"); + } + var game = new Game() { Groupid = e.Groupid, GameType = GameType.幸运楼层, Members = new List() }; + Games[e.Groupid] = game; + game.Members.Clear(); + e.SendMessage(@"😎游戏开始: +①邀请【1】人进群可参与 +②回复任意数字加入游戏 +③耐心等待几分钟,系统开奖 + +PS小提示: +商城地址:http://t.cn/EiuwmKd +每轮抽取3位幸运小伙伴,商城内任选9.9元以内的宝贝!(包邮免费送)"); + } + } + else if (e.Message == "公布结果") + { + var group = client.GetContact(e.Groupid); + if (group.ChatRoomOwner == e.Username) + { + if (Games.ContainsKey(e.Groupid)) + { + var game = Games[e.Groupid]; + if (game.MembersOver == null) + { + game.MembersOver = RandomSortList(game.Members); + } + game.Gameover = true; + StringBuilder sb = new StringBuilder("游戏结果如下:\r\n"); + int number = 0; + foreach (string item in game.MembersOver) + { + number++; + var member = client.GetMember(e.Groupid,item); + if (member == null) continue; + sb.Append($"{member.GetName()}(在{game.GetIndex(item) + 1}楼)\r\n"); + if (number >= 3) break; + } + + sb.Append("-----------------\r\nPS小提示:\r\n商城地址:http://t.cn/EiuwmKd\r\n请再商城内认选一个9.9元的宝贝,联系萌萌代付!"); + e.SendMessage(sb.ToString()); + + + } + else throw new Exception("游戏已结束!"); + + } + } + else + { + var reg = Regex.Match(e.Message, @"^\d+$"); + if (reg.Success) + { + if (Games.ContainsKey(e.Groupid) && !Games[e.Groupid].Gameover) + { + if (!Games[e.Groupid].Members.Contains(e.Username)) + { + var count = client.GetMembers(e.Groupid).Where(f => f.InviterUserName == e.Username).ToList().Count; + if (count >= 1) + { + Games[e.Groupid].Members.Add(e.Username); + client.SendMessage(e.Groupid, $"@{e.NickName}\r\n加入成功!您是第{Games[e.Groupid].Members.Count}位玩家!", e.Username); + } + else + { + throw new Exception($"需邀请{1}人进群才可以加入!\r\n查看数据请输入:邀请统计"); + } + + return; + } + else throw new Exception("您已加入,无需重复加入!"); + } + } + } + } + catch (Exception ex) + { + client.SendMessage(e.Groupid,"@"+e.NickName+":\r\n"+ex.Message,e.Username); + } + } + + public List RandomSortList(List ListT) + { + Random random = new Random(); + List newList = new List(); + foreach (T item in ListT) + { + newList.Insert(random.Next(newList.Count + 1), item); + } + return newList; + } + + } +} diff --git a/应用/Activity/Config.cs b/应用/Activity/Config.cs new file mode 100644 index 0000000..04cef26 --- /dev/null +++ b/应用/Activity/Config.cs @@ -0,0 +1,39 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace Activity +{ + [Config(Name = "插件-活动-配置")] + public class Config + { + + // [ + // Category("8)、兑换相关提示"), DisplayName("微信自动转账成功提示语"), DefaultValue(@"[昵称] + //订单已经处理 + //已经转账成功"), + // Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public string ExchangeTransmaticTip { get; set; } + + [ + Category("1)、抽奖活动设置"), DisplayName("抽奖开关"), DefaultValue(SwitchType.开启), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public SwitchType ActivityOnOff { get; set; } + + public Config() + { + this.ActivityOnOff = SwitchType.开启; + } + + } +} diff --git a/应用/Activity/EditActivityForm.Designer.cs b/应用/Activity/EditActivityForm.Designer.cs new file mode 100644 index 0000000..aa4b910 --- /dev/null +++ b/应用/Activity/EditActivityForm.Designer.cs @@ -0,0 +1,512 @@ +namespace Activity +{ + partial class EditActivityForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + DevExpress.XtraGrid.GridLevelNode gridLevelNode1 = new DevExpress.XtraGrid.GridLevelNode(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.tbx_ActivityName = new DevExpress.XtraEditors.TextEdit(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加奖品ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.nud_Amount = new System.Windows.Forms.NumericUpDown(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl3 = new DevExpress.XtraEditors.SeparatorControl(); + this.cbx_Settled = new System.Windows.Forms.CheckBox(); + this.cbx_Freezing = new System.Windows.Forms.CheckBox(); + this.cbx_AccountPaid = new System.Windows.Forms.CheckBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.cbx_OrderState = new DevExpress.XtraEditors.CheckEdit(); + this.cbx_Grade = new DevExpress.XtraEditors.CheckEdit(); + this.cbx_Amount = new DevExpress.XtraEditors.CheckEdit(); + this.dtp_OpeningTime = new DevExpress.XtraEditors.DateEdit(); + this.dtp_End = new DevExpress.XtraEditors.DateEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.dtp_Begin = new DevExpress.XtraEditors.DateEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.cbox_Grade = new System.Windows.Forms.ComboBox(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbx_ActivityName.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Amount)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbx_OrderState.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbx_Grade.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbx_Amount.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_OpeningTime.Properties.CalendarTimeProperties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_OpeningTime.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_End.Properties.CalendarTimeProperties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_End.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_Begin.Properties.CalendarTimeProperties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_Begin.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.tbx_ActivityName); + this.groupControl1.Controls.Add(this.groupControl3); + this.groupControl1.Controls.Add(this.groupControl2); + this.groupControl1.Controls.Add(this.dtp_OpeningTime); + this.groupControl1.Controls.Add(this.dtp_End); + this.groupControl1.Controls.Add(this.labelControl4); + this.groupControl1.Controls.Add(this.dtp_Begin); + this.groupControl1.Controls.Add(this.labelControl3); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Location = new System.Drawing.Point(31, 32); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(604, 633); + this.groupControl1.TabIndex = 0; + this.groupControl1.Text = "活动编辑"; + // + // tbx_ActivityName + // + this.tbx_ActivityName.Location = new System.Drawing.Point(119, 51); + this.tbx_ActivityName.Name = "tbx_ActivityName"; + this.tbx_ActivityName.Size = new System.Drawing.Size(212, 20); + this.tbx_ActivityName.TabIndex = 9; + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.gridControl1); + this.groupControl3.Location = new System.Drawing.Point(40, 364); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(526, 234); + this.groupControl3.TabIndex = 8; + this.groupControl3.Text = "奖品设置"; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + gridLevelNode1.RelationName = "Level1"; + this.gridControl1.LevelTree.Nodes.AddRange(new DevExpress.XtraGrid.GridLevelNode[] { + gridLevelNode1}); + this.gridControl1.Location = new System.Drawing.Point(2, 21); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(522, 211); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加奖品ToolStripMenuItem, + this.修改选中项ToolStripMenuItem, + this.删除选中项ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(137, 70); + // + // 增加奖品ToolStripMenuItem + // + this.增加奖品ToolStripMenuItem.Name = "增加奖品ToolStripMenuItem"; + this.增加奖品ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.增加奖品ToolStripMenuItem.Text = "增加奖品"; + this.增加奖品ToolStripMenuItem.Click += new System.EventHandler(this.增加奖品ToolStripMenuItem_Click); + // + // 修改选中项ToolStripMenuItem + // + this.修改选中项ToolStripMenuItem.Name = "修改选中项ToolStripMenuItem"; + this.修改选中项ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.修改选中项ToolStripMenuItem.Text = "修改选中项"; + this.修改选中项ToolStripMenuItem.Click += new System.EventHandler(this.修改选中项ToolStripMenuItem_Click); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 30; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "ID"; + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 52; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "奖品名称"; + this.gridColumn2.FieldName = "trophy_name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 157; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "数量"; + this.gridColumn3.FieldName = "trophy_num"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 69; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "备注"; + this.gridColumn4.FieldName = "remark"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + this.gridColumn4.Width = 212; + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.cbox_Grade); + this.groupControl2.Controls.Add(this.nud_Amount); + this.groupControl2.Controls.Add(this.separatorControl1); + this.groupControl2.Controls.Add(this.separatorControl2); + this.groupControl2.Controls.Add(this.separatorControl3); + this.groupControl2.Controls.Add(this.cbx_Settled); + this.groupControl2.Controls.Add(this.cbx_Freezing); + this.groupControl2.Controls.Add(this.cbx_AccountPaid); + this.groupControl2.Controls.Add(this.labelControl5); + this.groupControl2.Controls.Add(this.cbx_OrderState); + this.groupControl2.Controls.Add(this.cbx_Grade); + this.groupControl2.Controls.Add(this.cbx_Amount); + this.groupControl2.Location = new System.Drawing.Point(40, 157); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(526, 185); + this.groupControl2.TabIndex = 7; + this.groupControl2.Text = "设置参加活动条件"; + // + // nud_Amount + // + this.nud_Amount.Location = new System.Drawing.Point(353, 47); + this.nud_Amount.Name = "nud_Amount"; + this.nud_Amount.Size = new System.Drawing.Size(96, 22); + this.nud_Amount.TabIndex = 14; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(5, 68); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(516, 23); + this.separatorControl1.TabIndex = 13; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(5, 115); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(516, 23); + this.separatorControl2.TabIndex = 12; + // + // separatorControl3 + // + this.separatorControl3.LineOrientation = System.Windows.Forms.Orientation.Vertical; + this.separatorControl3.Location = new System.Drawing.Point(179, 24); + this.separatorControl3.Name = "separatorControl3"; + this.separatorControl3.Size = new System.Drawing.Size(49, 156); + this.separatorControl3.TabIndex = 8; + // + // cbx_Settled + // + this.cbx_Settled.AutoSize = true; + this.cbx_Settled.Location = new System.Drawing.Point(387, 140); + this.cbx_Settled.Name = "cbx_Settled"; + this.cbx_Settled.Size = new System.Drawing.Size(62, 18); + this.cbx_Settled.TabIndex = 10; + this.cbx_Settled.Text = "已结算"; + this.cbx_Settled.UseVisualStyleBackColor = true; + // + // cbx_Freezing + // + this.cbx_Freezing.AutoSize = true; + this.cbx_Freezing.Location = new System.Drawing.Point(313, 140); + this.cbx_Freezing.Name = "cbx_Freezing"; + this.cbx_Freezing.Size = new System.Drawing.Size(62, 18); + this.cbx_Freezing.TabIndex = 9; + this.cbx_Freezing.Text = "冻结中"; + this.cbx_Freezing.UseVisualStyleBackColor = true; + // + // cbx_AccountPaid + // + this.cbx_AccountPaid.AutoSize = true; + this.cbx_AccountPaid.Location = new System.Drawing.Point(239, 140); + this.cbx_AccountPaid.Name = "cbx_AccountPaid"; + this.cbx_AccountPaid.Size = new System.Drawing.Size(62, 18); + this.cbx_AccountPaid.TabIndex = 8; + this.cbx_AccountPaid.Text = "已付款"; + this.cbx_AccountPaid.UseVisualStyleBackColor = true; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(239, 49); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(108, 14); + this.labelControl5.TabIndex = 5; + this.labelControl5.Text = "订单金额不得低于:"; + // + // cbx_OrderState + // + this.cbx_OrderState.Location = new System.Drawing.Point(81, 139); + this.cbx_OrderState.Name = "cbx_OrderState"; + this.cbx_OrderState.Properties.Caption = "限制订单状态"; + this.cbx_OrderState.Size = new System.Drawing.Size(108, 19); + this.cbx_OrderState.TabIndex = 2; + // + // cbx_Grade + // + this.cbx_Grade.Location = new System.Drawing.Point(81, 93); + this.cbx_Grade.Name = "cbx_Grade"; + this.cbx_Grade.Properties.Caption = "限制会员等级"; + this.cbx_Grade.Size = new System.Drawing.Size(108, 19); + this.cbx_Grade.TabIndex = 1; + // + // cbx_Amount + // + this.cbx_Amount.Location = new System.Drawing.Point(81, 47); + this.cbx_Amount.Name = "cbx_Amount"; + this.cbx_Amount.Properties.Caption = "限制订单金额"; + this.cbx_Amount.Size = new System.Drawing.Size(108, 19); + this.cbx_Amount.TabIndex = 0; + // + // dtp_OpeningTime + // + this.dtp_OpeningTime.EditValue = null; + this.dtp_OpeningTime.Location = new System.Drawing.Point(119, 115); + this.dtp_OpeningTime.Name = "dtp_OpeningTime"; + this.dtp_OpeningTime.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.dtp_OpeningTime.Properties.CalendarTimeProperties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.dtp_OpeningTime.Size = new System.Drawing.Size(212, 20); + this.dtp_OpeningTime.TabIndex = 6; + // + // dtp_End + // + this.dtp_End.EditValue = null; + this.dtp_End.Location = new System.Drawing.Point(349, 83); + this.dtp_End.Name = "dtp_End"; + this.dtp_End.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.dtp_End.Properties.CalendarTimeProperties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.dtp_End.Size = new System.Drawing.Size(212, 20); + this.dtp_End.TabIndex = 5; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(339, 86); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(4, 14); + this.labelControl4.TabIndex = 4; + this.labelControl4.Text = "-"; + // + // dtp_Begin + // + this.dtp_Begin.EditValue = null; + this.dtp_Begin.Location = new System.Drawing.Point(119, 83); + this.dtp_Begin.Name = "dtp_Begin"; + this.dtp_Begin.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.dtp_Begin.Properties.CalendarTimeProperties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.dtp_Begin.Properties.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm"; + this.dtp_Begin.Properties.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.dtp_Begin.Properties.Mask.EditMask = "yyyy-MM-dd HH:mm"; + this.dtp_Begin.Size = new System.Drawing.Size(212, 20); + this.dtp_Begin.TabIndex = 3; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(53, 118); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 2; + this.labelControl3.Text = "开奖时间:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(53, 86); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "活动期间:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(53, 54); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "活动名称:"; + // + // cbox_Grade + // + this.cbox_Grade.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cbox_Grade.FormattingEnabled = true; + this.cbox_Grade.Location = new System.Drawing.Point(239, 92); + this.cbox_Grade.Name = "cbox_Grade"; + this.cbox_Grade.Size = new System.Drawing.Size(210, 22); + this.cbox_Grade.TabIndex = 15; + // + // EditActivityForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(669, 694); + this.Controls.Add(this.groupControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditActivityForm"; + this.Text = "EditActivityForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.EditActivityForm_FormClosing); + this.Load += new System.EventHandler(this.EditActivityForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbx_ActivityName.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Amount)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbx_OrderState.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbx_Grade.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbx_Amount.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_OpeningTime.Properties.CalendarTimeProperties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_OpeningTime.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_End.Properties.CalendarTimeProperties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_End.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_Begin.Properties.CalendarTimeProperties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dtp_Begin.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.DateEdit dtp_OpeningTime; + private DevExpress.XtraEditors.DateEdit dtp_End; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.DateEdit dtp_Begin; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.CheckEdit cbx_OrderState; + private DevExpress.XtraEditors.CheckEdit cbx_Grade; + private DevExpress.XtraEditors.CheckEdit cbx_Amount; + private DevExpress.XtraEditors.LabelControl labelControl5; + private System.Windows.Forms.CheckBox cbx_Settled; + private System.Windows.Forms.CheckBox cbx_Freezing; + private System.Windows.Forms.CheckBox cbx_AccountPaid; + private DevExpress.XtraEditors.SeparatorControl separatorControl3; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private System.Windows.Forms.NumericUpDown nud_Amount; + private DevExpress.XtraEditors.GroupControl groupControl3; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraEditors.TextEdit tbx_ActivityName; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 增加奖品ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ComboBox cbox_Grade; + } +} \ No newline at end of file diff --git a/应用/Activity/EditActivityForm.cs b/应用/Activity/EditActivityForm.cs new file mode 100644 index 0000000..02a129c --- /dev/null +++ b/应用/Activity/EditActivityForm.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Activity.Properties; +using Activity.Entitys; + +namespace Activity +{ + public partial class EditActivityForm : BaseForm + { + public EditActivityForm() + { + InitializeComponent(); + this.Text = Resources.EditActivityFormTitle; + } + + private void EditActivityForm_Load(object sender, EventArgs e) + { + try + { + + + } + catch (Exception ex) + { + ShowError(ex); + } + + } + + #region 右击菜单 奖品操作 + private void 增加奖品ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 修改选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + + + } + catch (Exception ex) + { + ShowError(ex); + } + } + #endregion + + + private List trophyList = new List(); + + /// + /// 关闭前保存数据 + /// + /// + /// + private void EditActivityForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + fl_plugin_activity_info activity = new fl_plugin_activity_info() + { + activity_name = tbx_ActivityName.Text.Trim(), + time_begin = DateTime.Parse(dtp_Begin.Text), + time_end = DateTime.Parse(dtp_End.Text), + opening_time = DateTime.Parse(dtp_OpeningTime.Text), + amount = cbx_Amount.Checked, + order_amount = (double)nud_Amount.Value, + grade = cbx_Grade.Checked, + grade_id = -1,//TODO + order_state = cbx_OrderState.Checked, + account_paid = cbx_AccountPaid.Checked, + freezing = cbx_Freezing.Checked, + settled = cbx_Settled.Checked, + trophyjson = "",//TODO + activity_state = Api.Framework.Enums.SwitchType.关闭//TODO + + }; + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/Activity/EditActivityForm.resx b/应用/Activity/EditActivityForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Activity/EditActivityForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/应用/Activity/Entitys/fl_plugin_activity_info.cs b/应用/Activity/Entitys/fl_plugin_activity_info.cs new file mode 100644 index 0000000..7df184a --- /dev/null +++ b/应用/Activity/Entitys/fl_plugin_activity_info.cs @@ -0,0 +1,81 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Activity.Entitys +{ + class fl_plugin_activity_info : base_model + { + /// + /// 活动名称 + /// + public string activity_name { get; set; } + /// + /// 活动开始时间 + /// + public DateTime time_begin { get; set; } + /// + /// 活动结束时间 + /// + public DateTime time_end { get; set; } + /// + /// 开奖时间 + /// + public DateTime opening_time { get; set; } + /// + /// 奖励 + /// + public string trophyjson { get; set; } + + #region 限制订单金额开关 + /// + /// 限制订单金额开关 + /// + public bool amount { get; set; } + /// + /// 订单金额 + /// + public double order_amount { get; set; } + #endregion + + #region 限制会员等级开关 + /// + /// 限制用户等级开关 + /// + public bool grade { get; set; } + /// + /// 用户等级id + /// + public int grade_id { get; set; } + #endregion + + #region 限制订单状态 + /// + /// 订单状态开关 + /// + public bool order_state { get; set; } + /// + /// 已付款开关 + /// + public bool account_paid { get; set; } + /// + /// 冻结中开关 + /// + public bool freezing { get; set; } + /// + /// 已结算开关 + /// + public bool settled { get; set; } + #endregion + + /// + /// 状态 + /// + public SwitchType activity_state { get; set; } + + } +} diff --git a/应用/Activity/Entitys/trophy_info.cs b/应用/Activity/Entitys/trophy_info.cs new file mode 100644 index 0000000..67242c1 --- /dev/null +++ b/应用/Activity/Entitys/trophy_info.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Activity.Entitys +{ + /// + /// 奖品类 + /// + public class trophy_info + { + /// + /// 序号 + /// + public int id { get; set; } + /// + /// 活动id + /// + //public int activity_id { get; set; } + + /// + /// 奖品名称 + /// + public string name { get; set; } + /// + /// 奖品数量 + /// + public int num { get; set; } + /// + /// 奖品描述 + /// + public string describe { get; set; } + ////用于生成,开奖时中奖的下标 + //public List Indexs { get; set; } + + } +} diff --git a/应用/Activity/MainForm.Designer.cs b/应用/Activity/MainForm.Designer.cs new file mode 100644 index 0000000..11a23cd --- /dev/null +++ b/应用/Activity/MainForm.Designer.cs @@ -0,0 +1,319 @@ +namespace Activity +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + DevExpress.XtraGrid.GridLevelNode gridLevelNode1 = new DevExpress.XtraGrid.GridLevelNode(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(); + this.增加活动ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改活动ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage4.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(735, 542); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3, + this.xtraTabPage4}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.ImageOptions.Image = global::Activity.Properties.Resources.抽奖; + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(729, 495); + this.xtraTabPage1.Text = "抽奖列表"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 474); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(729, 21); + this.pageControl1.TabIndex = 1; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + gridLevelNode1.RelationName = "Level1"; + this.gridControl1.LevelTree.Nodes.AddRange(new DevExpress.XtraGrid.GridLevelNode[] { + gridLevelNode1}); + this.gridControl1.Location = new System.Drawing.Point(-1, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(730, 474); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加活动ToolStripMenuItem, + this.修改活动ToolStripMenuItem, + this.删除选中ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 70); + // + // 增加活动ToolStripMenuItem + // + this.增加活动ToolStripMenuItem.Name = "增加活动ToolStripMenuItem"; + this.增加活动ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.增加活动ToolStripMenuItem.Text = "增加活动"; + this.增加活动ToolStripMenuItem.Click += new System.EventHandler(this.增加活动ToolStripMenuItem_Click); + // + // 修改活动ToolStripMenuItem + // + this.修改活动ToolStripMenuItem.Name = "修改活动ToolStripMenuItem"; + this.修改活动ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.修改活动ToolStripMenuItem.Text = "修改活动"; + this.修改活动ToolStripMenuItem.Click += new System.EventHandler(this.修改活动ToolStripMenuItem_Click); + // + // 删除选中ToolStripMenuItem + // + this.删除选中ToolStripMenuItem.Name = "删除选中ToolStripMenuItem"; + this.删除选中ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.删除选中ToolStripMenuItem.Text = "删除选中"; + this.删除选中ToolStripMenuItem.Click += new System.EventHandler(this.删除选中ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4, + this.gridColumn5, + this.gridColumn6}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 35; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomDrawRowIndicator += new DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventHandler(this.gridView1_CustomDrawRowIndicator); + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "ID"; + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 62; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "活动名称"; + this.gridColumn2.FieldName = "activity_name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 156; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "活动开始时间"; + this.gridColumn3.FieldName = "time_begin"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 136; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "活动结束时间"; + this.gridColumn4.FieldName = "time_end"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + this.gridColumn4.Width = 136; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn5.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "开奖时间"; + this.gridColumn5.FieldName = "opening_time"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 139; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn6.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "活动状态"; + this.gridColumn6.FieldName = "activity_state"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 5; + this.gridColumn6.Width = 64; + // + // xtraTabPage2 + // + this.xtraTabPage2.ImageOptions.Image = global::Activity.Properties.Resources.免费; + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(729, 495); + this.xtraTabPage2.Text = "免单活动"; + // + // xtraTabPage3 + // + this.xtraTabPage3.ImageOptions.Image = global::Activity.Properties.Resources.名单; + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(729, 495); + this.xtraTabPage3.Text = "中奖结果"; + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.settingControl1); + this.xtraTabPage4.ImageOptions.Image = global::Activity.Properties.Resources.基础管理; + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(729, 495); + this.xtraTabPage4.Text = "基础设置"; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(729, 495); + this.settingControl1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(735, 542); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage4.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 增加活动ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改活动ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/应用/Activity/MainForm.cs b/应用/Activity/MainForm.cs new file mode 100644 index 0000000..b598808 --- /dev/null +++ b/应用/Activity/MainForm.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Activity.Properties; +using UI.Framework.Controls; +using Api.Framework; +using Activity.Entitys; +using Api.Framework.Tools; + +namespace Activity +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + /// + /// 窗体关闭 + /// + public void CloseForm() + { + try + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + /// + /// 在列表的最前面加一个序号 + /// + /// + /// + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void MainForm_Load(object sender, EventArgs e) + { + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var param = session.NewParamMap(); + param.setPageParamters(page, size); + var result = session.FindPage("select * from fl_plugin_activity_info", param); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40); + } + + #region 右击菜单操作 + private void 增加活动ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var editActivityForm = new EditActivityForm(); + editActivityForm.ShowDialog(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 修改活动ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + #endregion + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Api.Framework.Tools.Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/Activity/MainForm.resx b/应用/Activity/MainForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Activity/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/应用/Activity/Properties/AssemblyInfo.cs b/应用/Activity/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c7650be --- /dev/null +++ b/应用/Activity/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Activity")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Activity")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("aca7a9de-5ec4-42f7-a8de-9aa6119f17aa")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/Activity/Properties/Resources.Designer.cs b/应用/Activity/Properties/Resources.Designer.cs new file mode 100644 index 0000000..8734901 --- /dev/null +++ b/应用/Activity/Properties/Resources.Designer.cs @@ -0,0 +1,158 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Activity.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Activity.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 设置活动列表 的本地化字符串。 + /// + internal static string EditActivityFormTitle { + get { + return ResourceManager.GetString("EditActivityFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 活动插件 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 活动插件 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 活动插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 设置奖品列表 的本地化字符串。 + /// + internal static string TrophyFormTitle { + get { + return ResourceManager.GetString("TrophyFormTitle", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 免费 { + get { + object obj = ResourceManager.GetObject("免费", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 名单 { + get { + object obj = ResourceManager.GetObject("名单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 抽奖 { + get { + object obj = ResourceManager.GetObject("抽奖", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 活动 { + get { + object obj = ResourceManager.GetObject("活动", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Activity/Properties/Resources.resx b/应用/Activity/Properties/Resources.resx new file mode 100644 index 0000000..7e8c4dd --- /dev/null +++ b/应用/Activity/Properties/Resources.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\活动.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 活动插件 + 插件介绍 + + + 活动插件 + 插件名 + + + ..\Resources\名单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 活动插件 + 插件主窗体名称 + + + ..\Resources\抽奖.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\免费.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 设置活动列表 + 设置活动列表窗体名称 + + + 设置奖品列表 + 设置奖品列表窗体名称 + + \ No newline at end of file diff --git a/应用/Activity/Properties/licenses.licx b/应用/Activity/Properties/licenses.licx new file mode 100644 index 0000000..e69de29 diff --git a/应用/Activity/Resources/免费.png b/应用/Activity/Resources/免费.png new file mode 100644 index 0000000..aa460fe Binary files /dev/null and b/应用/Activity/Resources/免费.png differ diff --git a/应用/Activity/Resources/名单.png b/应用/Activity/Resources/名单.png new file mode 100644 index 0000000..78a9155 Binary files /dev/null and b/应用/Activity/Resources/名单.png differ diff --git a/应用/Activity/Resources/基础管理.png b/应用/Activity/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/Activity/Resources/基础管理.png differ diff --git a/应用/Activity/Resources/抽奖.png b/应用/Activity/Resources/抽奖.png new file mode 100644 index 0000000..dfb6f73 Binary files /dev/null and b/应用/Activity/Resources/抽奖.png differ diff --git a/应用/Activity/Resources/活动.png b/应用/Activity/Resources/活动.png new file mode 100644 index 0000000..bcf7a3c Binary files /dev/null and b/应用/Activity/Resources/活动.png differ diff --git a/应用/Activity/TrophyForm.Designer.cs b/应用/Activity/TrophyForm.Designer.cs new file mode 100644 index 0000000..57428c2 --- /dev/null +++ b/应用/Activity/TrophyForm.Designer.cs @@ -0,0 +1,62 @@ +namespace Activity +{ + partial class TrophyForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.SuspendLayout(); + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(387, 438); + this.settingControl1.TabIndex = 0; + // + // TrophyForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(387, 438); + this.Controls.Add(this.settingControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "TrophyForm"; + this.Text = "TrophyForm"; + this.Load += new System.EventHandler(this.TrophyForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private UI.Framework.Controls.SettingControl settingControl1; + } +} \ No newline at end of file diff --git a/应用/Activity/TrophyForm.cs b/应用/Activity/TrophyForm.cs new file mode 100644 index 0000000..840324d --- /dev/null +++ b/应用/Activity/TrophyForm.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Activity.Properties; +using Activity.Entitys; + +namespace Activity +{ + public partial class TrophyForm : BaseForm + { + private trophy_info trophy { get; set; } + + public TrophyForm(trophy_info trophy) + { + InitializeComponent(); + this.Text = Resources.TrophyFormTitle; + this.trophy = trophy; + } + + private void TrophyForm_Load(object sender, EventArgs e) + { + try + { + settingControl1.Bind(trophy); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + + } +} \ No newline at end of file diff --git a/应用/Activity/TrophyForm.resx b/应用/Activity/TrophyForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/Activity/TrophyForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/Activity/enumType.cs b/应用/Activity/enumType.cs new file mode 100644 index 0000000..04ef14c --- /dev/null +++ b/应用/Activity/enumType.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Activity +{ + class EnumType + { + public enum ActivityType + { + + + + } + + + } +} diff --git a/应用/AllRebatesActivity/AllRebatesActivity.csproj b/应用/AllRebatesActivity/AllRebatesActivity.csproj new file mode 100644 index 0000000..91f62f2 --- /dev/null +++ b/应用/AllRebatesActivity/AllRebatesActivity.csproj @@ -0,0 +1,124 @@ + + + + + Debug + AnyCPU + {5A6B6B66-43EE-4EB2-8E10-1E2CBB8B15F5} + Library + Properties + AllRebatesActivity + AllRebatesActivity + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + Form + + + MainForm.cs + + + True + True + Resources.resx + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/AllRebatesActivity/AnalyzeGoods.cs b/应用/AllRebatesActivity/AnalyzeGoods.cs new file mode 100644 index 0000000..f0a5ed7 --- /dev/null +++ b/应用/AllRebatesActivity/AnalyzeGoods.cs @@ -0,0 +1,84 @@ +using AllRebatesActivity.Entitys; +using Api.Framework; +using Api.Framework.Enums; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Api.Framework.Tools; + +namespace AllRebatesActivity +{ + /// + /// 解析商品 + /// + class AnalyzeGoods + { + /// + /// 通过商品的id查询返回获取到自己返利商品信息 + /// + /// + /// + public goodsinfos FindGoodsInfoToItemId(string goods_id, string pid_cps_name = "", string pid = "", string biz_scene_id = "2") + { + try + { + if (!string.IsNullOrEmpty(goods_id))//符合搜索宝贝id的条件 + { + biz_scene_id = TBHelper.TbAnalysis.BizSceneId(goods_id); + + var member = (string.IsNullOrEmpty(pid_cps_name) ? CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈) : CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == pid_cps_name)); + if (member == null) { return null; } + var api = CpsClient.CreateAlimamaRequest(member); + + var itemInfo = api.GetItemInfo(goods_id, biz_scene_id); + if (itemInfo != null && itemInfo.n_tbk_item != null && itemInfo.n_tbk_item.Count > 0) + { + var tbk_item = itemInfo.n_tbk_item[0]; + //店铺名称 + var nick = tbk_item.nick; + //商品主图 + var pict_url = tbk_item.pict_url; + //商品id + goods_id = tbk_item.num_iid; + //商品标题 + var title = tbk_item.title; + //商品折扣价格(当前售价) + var zk_final_price = double.Parse(tbk_item.zk_final_price); + //30天销量 + var volume = tbk_item.volume; + var goods_desc = string.Empty; + + var coupon_remain_quantity = string.Empty; + + var pids = pid.Split('_'); + var privilege = api.SendTaobao("taobao.tbk.privilege.get", new { item_id = goods_id, site_id = pids[2], adzone_id = pids[3], biz_scene_id = biz_scene_id }); + var privilege_data = privilege["data"] as Dictionary; + //最高佣金率 + var max_commission_rate = double.Parse(privilege_data["max_commission_rate"].ToString()); + //优惠券地址 + var coupon_click_url = string.Empty; + var coupon_price = 0.00d; + if (privilege_data.ContainsKey("coupon_info")) + { + var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满\d+元减(\d+)元"); + if (quan_reg.Success) coupon_price = double.Parse(quan_reg.Groups[1].Value); + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + else + { + coupon_price = 0.00d; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + return new goodsinfos() { cur_time = DateTime.Today, goods_id = goods_id, goods_name = title, mall_name = nick, goods_thumbnail_url = pict_url, sold_quantity = volume, normal_price = zk_final_price, coupon_discount = coupon_price, promotion_rate = max_commission_rate, shopping_url = coupon_click_url, goods_desc = goods_desc, coupon_remain_quantity = coupon_remain_quantity }; + } + } + } + catch (Exception) + { } + return null; + } + + } +} diff --git a/应用/AllRebatesActivity/Class1.cs b/应用/AllRebatesActivity/Class1.cs new file mode 100644 index 0000000..a208e11 --- /dev/null +++ b/应用/AllRebatesActivity/Class1.cs @@ -0,0 +1,78 @@ +using AllRebatesActivity.Entitys; +using AllRebatesActivity.Properties; +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AllRebatesActivity +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.全额免单; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + + //创建配置文件 + Config = this.ReadConfig(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/AllRebatesActivity/Config.cs b/应用/AllRebatesActivity/Config.cs new file mode 100644 index 0000000..9901167 --- /dev/null +++ b/应用/AllRebatesActivity/Config.cs @@ -0,0 +1,17 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AllRebatesActivity +{ + [Config(Name = "插件-全额免单-配置")] + public class Config + { + + + + } +} diff --git a/应用/AllRebatesActivity/Entitys/goodsinfos.cs b/应用/AllRebatesActivity/Entitys/goodsinfos.cs new file mode 100644 index 0000000..f982210 --- /dev/null +++ b/应用/AllRebatesActivity/Entitys/goodsinfos.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AllRebatesActivity.Entitys +{ + /// + /// 商品信息 + /// + public class goodsinfos + { + /// + /// 商品id + /// + public string goods_id { get; set; } + /// + /// 商品连接 + /// + public string goods_url { get; set; } + /// + /// 商品标题 + /// + public string goods_name { get; set; } + /// + /// 商品描述 + /// + public string goods_desc { get; set; } + /// + /// 商品图片链接 + /// + public string goods_thumbnail_url { get; set; } + /// + /// 已售卖件数 + /// + public int sold_quantity { get; set; } + /// + /// 商品单价,单位为元 + /// + public double normal_price { get; set; } + /// + /// 店铺名 + /// + public string mall_name { get; set; } + /// + /// 优惠券面额,单位为元 + /// + public double coupon_discount { get; set; } + /// + /// 优惠券剩余数量 + /// + public string coupon_remain_quantity { get; set; } + /// + /// 优惠券连接 + /// + public string coupon_url { get; set; } + /// + /// 佣金比例,百分比 + /// + public double promotion_rate { get; set; } + /// + /// 购买链接 转连之后 + /// + public string shopping_url { get; set; } + /// + /// 采集的日期 + /// + public DateTime cur_time { get; set; } + } +} diff --git a/应用/AllRebatesActivity/MainForm.Designer.cs b/应用/AllRebatesActivity/MainForm.Designer.cs new file mode 100644 index 0000000..cf30d25 --- /dev/null +++ b/应用/AllRebatesActivity/MainForm.Designer.cs @@ -0,0 +1,754 @@ +namespace AllRebatesActivity +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label21 = new System.Windows.Forms.Label(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.linkLabel5 = new System.Windows.Forms.LinkLabel(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label20 = new System.Windows.Forms.Label(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.checkedComboBoxEdit1 = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label16 = new System.Windows.Forms.Label(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label19 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.checkedComboBoxEdit_ChatType = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.simpleButton = new DevExpress.XtraEditors.SimpleButton(); + this.time_end = new System.Windows.Forms.DateTimePicker(); + this.time_begin = new System.Windows.Forms.DateTimePicker(); + this.text_name = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).BeginInit(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(992, 567); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label21); + this.xtraTabPage1.Controls.Add(this.groupControl2); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Controls.Add(this.groupControl1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(990, 541); + this.xtraTabPage1.Text = " 免 单 活 动 设 置 "; + // + // label21 + // + this.label21.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label21.AutoSize = true; + this.label21.BackColor = System.Drawing.Color.Transparent; + this.label21.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label21.Location = new System.Drawing.Point(117, 189); + this.label21.Name = "label21"; + this.label21.Size = new System.Drawing.Size(267, 35); + this.label21.TabIndex = 17; + this.label21.Text = "当前无免单活动"; + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.linkLabel5); + this.groupControl2.Controls.Add(this.textBox2); + this.groupControl2.Controls.Add(this.label20); + this.groupControl2.Location = new System.Drawing.Point(499, 3); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(486, 73); + this.groupControl2.TabIndex = 16; + this.groupControl2.Text = "全局推广位"; + // + // linkLabel5 + // + this.linkLabel5.AutoSize = true; + this.linkLabel5.Location = new System.Drawing.Point(384, 39); + this.linkLabel5.Name = "linkLabel5"; + this.linkLabel5.Size = new System.Drawing.Size(67, 14); + this.linkLabel5.TabIndex = 12; + this.linkLabel5.TabStop = true; + this.linkLabel5.Text = "设置推广位"; + this.linkLabel5.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel5_LinkClicked); + // + // textBox2 + // + this.textBox2.Enabled = false; + this.textBox2.Location = new System.Drawing.Point(122, 36); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(247, 22); + this.textBox2.TabIndex = 11; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(43, 39); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(79, 14); + this.label20.TabIndex = 10; + this.label20.Text = "活动推广位:"; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(-5, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(498, 498); + this.gridControl1.TabIndex = 15; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中项ToolStripMenuItem, + this.删除所有ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 48); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有ToolStripMenuItem + // + this.删除所有ToolStripMenuItem.Name = "删除所有ToolStripMenuItem"; + this.删除所有ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.删除所有ToolStripMenuItem.Text = "删除所有"; + this.删除所有ToolStripMenuItem.Click += new System.EventHandler(this.删除所有ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn3, + this.gridColumn1, + this.gridColumn2, + this.gridColumn5}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + this.gridView1.DoubleClick += new System.EventHandler(this.gridView1_DoubleClick); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "id"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "活动名称"; + this.gridColumn3.FieldName = "name"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 1; + this.gridColumn3.Width = 138; + // + // gridColumn1 + // + this.gridColumn1.Caption = "领取开始时间"; + this.gridColumn1.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn1.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn1.FieldName = "time_begin"; + this.gridColumn1.Name = "gridColumn1"; + // + // gridColumn2 + // + this.gridColumn2.Caption = "领取结束时间"; + this.gridColumn2.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn2.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn2.FieldName = "time_end"; + this.gridColumn2.Name = "gridColumn2"; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "活动状态"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 148; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.labelControl9); + this.groupControl1.Controls.Add(this.labelControl8); + this.groupControl1.Controls.Add(this.numericUpDown2); + this.groupControl1.Controls.Add(this.checkedComboBoxEdit1); + this.groupControl1.Controls.Add(this.groupBox2); + this.groupControl1.Controls.Add(this.checkedComboBoxEdit_ChatType); + this.groupControl1.Controls.Add(this.simpleButton); + this.groupControl1.Controls.Add(this.time_end); + this.groupControl1.Controls.Add(this.time_begin); + this.groupControl1.Controls.Add(this.text_name); + this.groupControl1.Controls.Add(this.label3); + this.groupControl1.Controls.Add(this.label5); + this.groupControl1.Controls.Add(this.label4); + this.groupControl1.Controls.Add(this.label2); + this.groupControl1.Controls.Add(this.label8); + this.groupControl1.Controls.Add(this.label1); + this.groupControl1.Location = new System.Drawing.Point(499, 84); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(486, 414); + this.groupControl1.TabIndex = 14; + this.groupControl1.Text = "活动编辑"; + // + // labelControl9 + // + this.labelControl9.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl9.Appearance.Options.UseForeColor = true; + this.labelControl9.Location = new System.Drawing.Point(321, 35); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(130, 14); + this.labelControl9.TabIndex = 10; + this.labelControl9.Text = "(活动名称不存在为添加)"; + // + // labelControl8 + // + this.labelControl8.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl8.Appearance.Options.UseForeColor = true; + this.labelControl8.Location = new System.Drawing.Point(257, 146); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(194, 14); + this.labelControl8.TabIndex = 10; + this.labelControl8.Text = "(一次性购买数量超过设定值,将无效)"; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(122, 142); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(120, 22); + this.numericUpDown2.TabIndex = 9; + this.numericUpDown2.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // checkedComboBoxEdit1 + // + this.checkedComboBoxEdit1.Location = new System.Drawing.Point(122, 114); + this.checkedComboBoxEdit1.Name = "checkedComboBoxEdit1"; + this.checkedComboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit1.Size = new System.Drawing.Size(329, 20); + this.checkedComboBoxEdit1.TabIndex = 1; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.labelControl10); + this.groupBox2.Controls.Add(this.labelControl7); + this.groupBox2.Controls.Add(this.labelControl6); + this.groupBox2.Controls.Add(this.labelControl5); + this.groupBox2.Controls.Add(this.labelControl4); + this.groupBox2.Controls.Add(this.labelControl3); + this.groupBox2.Controls.Add(this.labelControl2); + this.groupBox2.Controls.Add(this.labelControl1); + this.groupBox2.Controls.Add(this.numericUpDown1); + this.groupBox2.Controls.Add(this.textBox1); + this.groupBox2.Controls.Add(this.label16); + this.groupBox2.Controls.Add(this.simpleButton1); + this.groupBox2.Controls.Add(this.label19); + this.groupBox2.Controls.Add(this.label15); + this.groupBox2.Controls.Add(this.label14); + this.groupBox2.Controls.Add(this.label13); + this.groupBox2.Controls.Add(this.label11); + this.groupBox2.Controls.Add(this.label12); + this.groupBox2.Location = new System.Drawing.Point(12, 176); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(462, 185); + this.groupBox2.TabIndex = 8; + this.groupBox2.TabStop = false; + this.groupBox2.Text = " 免单宝贝 "; + // + // labelControl10 + // + this.labelControl10.Appearance.ForeColor = System.Drawing.Color.DimGray; + this.labelControl10.Appearance.Options.UseForeColor = true; + this.labelControl10.Location = new System.Drawing.Point(369, 152); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(82, 14); + this.labelControl10.TabIndex = 8; + this.labelControl10.Text = "(给客户的金额)"; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(221, 152); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(60, 14); + this.labelControl7.TabIndex = 8; + this.labelControl7.Text = "客户所得:"; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(62, 152); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(60, 14); + this.labelControl6.TabIndex = 8; + this.labelControl6.Text = "返利金额:"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(221, 124); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(60, 14); + this.labelControl5.TabIndex = 8; + this.labelControl5.Text = "返利比例:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(50, 124); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(72, 14); + this.labelControl4.TabIndex = 8; + this.labelControl4.Text = "优惠券金额:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(221, 96); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 8; + this.labelControl3.Text = "商品单价:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(62, 96); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 8; + this.labelControl2.Text = "商品编码:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(62, 68); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 8; + this.labelControl1.Text = "商品标题:"; + // + // numericUpDown1 + // + this.numericUpDown1.DecimalPlaces = 2; + this.numericUpDown1.Location = new System.Drawing.Point(281, 148); + this.numericUpDown1.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(82, 22); + this.numericUpDown1.TabIndex = 2; + this.numericUpDown1.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(132, 30); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(219, 22); + this.textBox1.TabIndex = 1; + this.textBox1.Enter += new System.EventHandler(this.textBox1_Enter); + // + // label16 + // + this.label16.AutoSize = true; + this.label16.ForeColor = System.Drawing.Color.Blue; + this.label16.Location = new System.Drawing.Point(132, 152); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(14, 14); + this.label16.TabIndex = 0; + this.label16.Text = "0"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(357, 26); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(76, 29); + this.simpleButton1.TabIndex = 7; + this.simpleButton1.Text = " 解 析 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label19 + // + this.label19.AutoSize = true; + this.label19.ForeColor = System.Drawing.Color.Blue; + this.label19.Location = new System.Drawing.Point(291, 124); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(26, 14); + this.label19.TabIndex = 0; + this.label19.Text = "0%"; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.ForeColor = System.Drawing.Color.Blue; + this.label15.Location = new System.Drawing.Point(132, 124); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(14, 14); + this.label15.TabIndex = 0; + this.label15.Text = "0"; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.ForeColor = System.Drawing.Color.Blue; + this.label14.Location = new System.Drawing.Point(291, 96); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(14, 14); + this.label14.TabIndex = 0; + this.label14.Text = "0"; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.ForeColor = System.Drawing.Color.Blue; + this.label13.Location = new System.Drawing.Point(132, 96); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(0, 14); + this.label13.TabIndex = 0; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.ForeColor = System.Drawing.Color.Blue; + this.label11.Location = new System.Drawing.Point(132, 68); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(0, 14); + this.label11.TabIndex = 0; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(35, 33); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(91, 14); + this.label12.TabIndex = 0; + this.label12.Text = "免单商品链接:"; + // + // checkedComboBoxEdit_ChatType + // + this.checkedComboBoxEdit_ChatType.EditValue = ""; + this.checkedComboBoxEdit_ChatType.Location = new System.Drawing.Point(122, 59); + this.checkedComboBoxEdit_ChatType.Name = "checkedComboBoxEdit_ChatType"; + this.checkedComboBoxEdit_ChatType.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit_ChatType.Size = new System.Drawing.Size(329, 20); + this.checkedComboBoxEdit_ChatType.TabIndex = 2; + // + // simpleButton + // + this.simpleButton.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton.ImageOptions.Image"))); + this.simpleButton.Location = new System.Drawing.Point(191, 372); + this.simpleButton.Name = "simpleButton"; + this.simpleButton.Size = new System.Drawing.Size(96, 29); + this.simpleButton.TabIndex = 7; + this.simpleButton.Text = "保 存 配 置 "; + this.simpleButton.Click += new System.EventHandler(this.simpleButton_Click); + // + // time_end + // + this.time_end.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.time_end.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.time_end.Location = new System.Drawing.Point(293, 86); + this.time_end.Name = "time_end"; + this.time_end.Size = new System.Drawing.Size(158, 22); + this.time_end.TabIndex = 4; + this.time_end.Value = new System.DateTime(2019, 5, 9, 14, 21, 0, 0); + // + // time_begin + // + this.time_begin.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.time_begin.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.time_begin.Location = new System.Drawing.Point(122, 86); + this.time_begin.Name = "time_begin"; + this.time_begin.Size = new System.Drawing.Size(158, 22); + this.time_begin.TabIndex = 3; + this.time_begin.Value = new System.DateTime(2019, 5, 9, 14, 21, 0, 0); + // + // text_name + // + this.text_name.Location = new System.Drawing.Point(122, 32); + this.text_name.Name = "text_name"; + this.text_name.Size = new System.Drawing.Size(193, 22); + this.text_name.TabIndex = 1; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(281, 90); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(11, 14); + this.label3.TabIndex = 0; + this.label3.Text = "-"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(43, 146); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(79, 14); + this.label5.TabIndex = 0; + this.label5.Text = "限制购买量:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(43, 117); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(79, 14); + this.label4.TabIndex = 0; + this.label4.Text = "参加用户组:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(55, 90); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 0; + this.label2.Text = "活动日期:"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(43, 62); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(79, 14); + this.label8.TabIndex = 0; + this.label8.Text = "活动机器人:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(55, 35); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(67, 14); + this.label1.TabIndex = 0; + this.label1.Text = "活动名称:"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 504); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(990, 37); + this.pageControl1.TabIndex = 13; + // + // xtraTabPage2 + // + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.PageVisible = false; + this.xtraTabPage2.Size = new System.Drawing.Size(990, 541); + this.xtraTabPage2.Text = "xtraTabPage2"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(992, 567); + this.Controls.Add(this.xtraTabControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).EndInit(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit_ChatType; + private DevExpress.XtraEditors.SimpleButton simpleButton; + private System.Windows.Forms.DateTimePicker time_end; + private System.Windows.Forms.DateTimePicker time_begin; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox text_name; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl1; + private System.Windows.Forms.GroupBox groupBox2; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.Label label19; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.LinkLabel linkLabel5; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label20; + private DevExpress.XtraEditors.GroupControl groupControl2; + private System.Windows.Forms.Label label21; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.LabelControl labelControl7; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有ToolStripMenuItem; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraEditors.LabelControl labelControl10; + } +} \ No newline at end of file diff --git a/应用/AllRebatesActivity/MainForm.cs b/应用/AllRebatesActivity/MainForm.cs new file mode 100644 index 0000000..597b4de --- /dev/null +++ b/应用/AllRebatesActivity/MainForm.cs @@ -0,0 +1,424 @@ +using AllRebatesActivity.Properties; +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace AllRebatesActivity +{ + public partial class MainForm : BaseForm + { + + SqlSugarClient session = null; + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + session = ApiClient.GetSession(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + private void MainForm_Load(object sender, EventArgs e) + { + try + { + var adzone = ApiClient.GetSession().FindAdzoneInfos().FirstOrDefault(f => f.custom_type == Resources.SoftwareType && f.alliance_id == (int)CpsType.阿里妈妈); + if (adzone != null) + { + textBox2.Text = adzone.adzone_name; + textBox2.Tag = adzone; + } + + #region 加载所有的任务 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage($"select * from fl_plugin_allrebatesactivity_info order by time_end", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 50, true, true); + + label21.Visible = gridView1.RowCount == 0; + + #endregion + + time_begin.Value = DateTime.Now; + time_end.Value = DateTime.Now.AddDays(30); + + _RefreshMemberGroup(); + _RefreshRobotList(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 更新会员组数据 + /// + /// + private void _RefreshMemberGroup(List data = null) + { + try + { + var session = ApiClient.GetSession(); + checkedComboBoxEdit1.Properties.Items.Clear(); + var memberGroups = session.Queryable().ToList(); + foreach (var item in memberGroups) + { + if (data != null && data.Contains(item.id)) + checkedComboBoxEdit1.Properties.Items.Add(item.id, item.name, CheckState.Checked, true); + else + checkedComboBoxEdit1.Properties.Items.Add(item.id, item.name, CheckState.Unchecked, true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void _RefreshRobotList(List data = null) + { + try + { + checkedComboBoxEdit_ChatType.Properties.Items.Clear(); + var clients = Chat.Framework.ChatClient.WXClient; + foreach (var item in clients.Values) + { + if (data != null && data.FirstOrDefault(f => f == item.WeixinHao) != null) + checkedComboBoxEdit_ChatType.Properties.Items.Add(item.WeixinHao, item.User.Nick, CheckState.Checked, true); + else + checkedComboBoxEdit_ChatType.Properties.Items.Add(item.WeixinHao, item.User.Nick, CheckState.Unchecked, true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_DoubleClick(object sender, EventArgs e) + { + try + { + #region 将enum的值加载到列表中 修改的将勾选 + if (gridView1.GetSelectedRows().Length != 0) + { + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "id").ToString();//获取列的数据 + var allrebatesactivity_info = session.Queryable().First(f => f.id == int.Parse(id)); + var chatList = allrebatesactivity_info.robots.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + _RefreshRobotList(chatList); + + _RefreshMemberGroup(allrebatesactivity_info.groups.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => long.Parse(f)).ToList()); + + text_name.Text = allrebatesactivity_info.name; + time_begin.Value = allrebatesactivity_info.time_begin; + time_end.Value = allrebatesactivity_info.time_end; + textBox1.Text = $@"https://item.taobao.com/item.htm?id={allrebatesactivity_info.goods_id}"; + label11.Tag = allrebatesactivity_info.title; + label11.Text = allrebatesactivity_info.title.Substring(0, 23) + "..."; + label13.Text = allrebatesactivity_info.goods_id; + label14.Text = allrebatesactivity_info.price.ToString("0.00"); + label15.Text = allrebatesactivity_info.coupon.ToString("0.00"); + label16.Text = allrebatesactivity_info.brokerage_money.ToString("0.00"); + numericUpDown2.Value = allrebatesactivity_info.limit_quantity_number; + label19.Text = ((decimal)allrebatesactivity_info.brokerage_ratio / 100m).ToString("0.00") + "%"; + numericUpDown1.Value = (decimal)allrebatesactivity_info.return_money; + } + else + { + _RefreshRobotList(); + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(text_name.Text)) throw new Exception("活动名不能给空"); + if (string.IsNullOrWhiteSpace(checkedComboBoxEdit_ChatType.Text)) throw new Exception("请选择活动机器人"); + if (time_begin.Value >= time_end.Value) throw new Exception("活动结束时间不能晚于开始时间"); + if (string.IsNullOrWhiteSpace(checkedComboBoxEdit1.Text)) throw new Exception("请选择参加用户组"); + if (string.IsNullOrWhiteSpace(textBox1.Text) || string.IsNullOrWhiteSpace(label13.Text)) throw new Exception("请填写商品链接"); + + var name = text_name.Text.Trim(); + var mess = string.Empty; + var allrebatesactivity_info = session.Queryable().First(f => f.name == name); + if (allrebatesactivity_info == null) + { + allrebatesactivity_info = new fl_plugin_allrebatesactivity_info() + { + name = name, + robots = checkedComboBoxEdit_ChatType.EditValue.ToString(), + time_begin = DateTime.Parse(time_begin.Text), + time_end = DateTime.Parse(time_end.Text), + brokerage_money = double.Parse(label16.Text), + limit_quantity_number = (int)numericUpDown2.Value, + brokerage_ratio = (int)(decimal.Parse(label19.Text.Replace("%", "")) * 100m), + coupon = double.Parse(label15.Text), + goods_id = label13.Text, + title = label11.Tag.ToString(), + price = double.Parse(label14.Text), + return_money = (double)numericUpDown1.Value, + groups = checkedComboBoxEdit1.EditValue.ToString() + }; + mess = "免单任务增加成功"; + } + else + { + allrebatesactivity_info.name = name; + allrebatesactivity_info.robots = checkedComboBoxEdit_ChatType.EditValue.ToString(); + allrebatesactivity_info.time_begin = DateTime.Parse(time_begin.Text); + allrebatesactivity_info.time_end = DateTime.Parse(time_end.Text); + allrebatesactivity_info.brokerage_money = double.Parse(label16.Text); + allrebatesactivity_info.limit_quantity_number = (int)numericUpDown2.Value; + allrebatesactivity_info.brokerage_ratio = (int)(decimal.Parse(label19.Text.Replace("%", "")) * 100m); + allrebatesactivity_info.coupon = double.Parse(label15.Text); + allrebatesactivity_info.goods_id = label13.Text; + allrebatesactivity_info.title = label11.Tag.ToString(); + allrebatesactivity_info.price = double.Parse(label14.Text); + allrebatesactivity_info.return_money = (double)numericUpDown1.Value; + allrebatesactivity_info.groups = checkedComboBoxEdit1.EditValue.ToString(); + + mess = "免单任务修改成功"; + } + session.Saveable(allrebatesactivity_info).ExecuteCommand(); + ShowSuccess(mess); + pageControl1.GotoPage(); + label21.Visible = gridView1.RowCount == 0; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void linkLabel5_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType); + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + else + { + try + { + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = 0, //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + textBox2.Text = adzone.adzone_name; + textBox2.Tag = adzone; + session.FindAdzoneInfos(true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (textBox2.Tag != null) + { + var adzone = textBox2.Tag as fl_adzone_info; + var tbAnalysis = new TBHelper.TbAnalysis(); + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("请添加要解析的宝贝链接!"); + var tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + if (tb_cps == null) throw new Exception("推广位无法使用!"); + var api = CpsClient.CreateAlimamaRequest(tb_cps); + if (api == null) throw new Exception("创建阿里妈妈API请求失败"); + + var itemId = string.Empty; + try + { + itemId = tbAnalysis.FindItemIdByUrlAndTklAndMkl(textBox1.Text, api, adzone.adzone_pid.Split('_')); + } + catch (Exception) + { } + if (string.IsNullOrWhiteSpace(itemId)) throw new Exception("该商品宝贝无法解析"); + + var activityId = string.Empty; + var urls = CsharpHttpHelper.HttpExtend.RegexMatchesUrl(textBox1.Text); + if (urls != null && urls.Count != 0) + { + foreach (var item in urls) + { + if (item.ToLower().Contains("uland.taobao")) + { + var reg = Regex.Match(item, @"activityId=(?<活动ID>[A-Za-z0-9]+)", RegexOptions.IgnoreCase); + if (reg.Success) + activityId = reg.Groups["活动ID"].Value; + break; + } + } + } + + AnalyzeGoods analyze = new AnalyzeGoods(); + var goodsinfo = analyze.FindGoodsInfoToItemId(itemId, adzone.adzone_pid_cps_name, adzone.adzone_pid); + if (goodsinfo != null) + { + label11.Tag = goodsinfo.goods_name; + label11.Text = goodsinfo.goods_name.Length >= 24 ? goodsinfo.goods_name.Substring(0, 23) + "..." : goodsinfo.goods_name; + label13.Text = goodsinfo.goods_id; + label14.Text = goodsinfo.normal_price.ToString("0.00"); + label15.Text = goodsinfo.coupon_discount.ToString("0.00"); + label19.Text = goodsinfo.promotion_rate.ToString("0.00") + "%"; + decimal final_price = 0; + if (goodsinfo.coupon_discount > goodsinfo.normal_price) + final_price = (decimal)goodsinfo.normal_price; + else + final_price = ((decimal)goodsinfo.normal_price - (decimal)goodsinfo.coupon_discount); + label16.Text = (final_price * ((decimal)goodsinfo.promotion_rate / 100m)).ToString("0.00"); + } + else throw new Exception("该商品宝贝无返利"); + } + else throw new Exception("请先设置推广位!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.Caption == "活动状态") + { + var activity_time_begin = DateTime.Parse(gridView1.GetRowCellDisplayText(e.ListSourceRowIndex, "time_begin")); + var activity_time_end = DateTime.Parse(gridView1.GetRowCellDisplayText(e.ListSourceRowIndex, "time_end")); + var now = DateTime.Now; + if (now >= activity_time_end) + e.DisplayText = "活动已结束"; + else if (now < activity_time_begin) + e.DisplayText = "活动未开始"; + else if (activity_time_begin <= now && now < activity_time_end) + e.DisplayText = "活动进行中"; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var row = this.gridView1.GetRow(rows[0]) as fl_plugin_allrebatesactivity_info; + var session = ApiClient.GetSession(); + session.Deleteable(row).ExecuteCommand(); + ShowSuccess("删除成功"); + pageControl1.GotoPage(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除所有ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var session = ApiClient.GetSession(); + session.Deleteable().ExecuteCommand(); + ShowSuccess("删除成功"); + pageControl1.GotoPage(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void textBox1_Enter(object sender, EventArgs e) + { + textBox1.SelectAll(); + } + + } +} diff --git a/应用/AllRebatesActivity/MainForm.resx b/应用/AllRebatesActivity/MainForm.resx new file mode 100644 index 0000000..b875738 --- /dev/null +++ b/应用/AllRebatesActivity/MainForm.resx @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAAA6ZJREFUOE9Nk31Q03Ucx3+iqwzOhE6t + MxsDOcbDhgPtziPoCGXkJIq6FQsn0WSOjRKIpzTmgRMfuKwpA2zLjFUzIPAIXCDIIiYPTWyDxThQntp4 + iAeBjP569/3Nuut397r73X0/79fn87n7fqnJlQZq7qGJIt86wvqMC+yYXG2o7ng1p19pCFtQfsvtP6Hn + NGSVBwvJ+WMEj/m/zJTrzxvU1Eo9RblWje5wUhZrW6Y6yFhasw+tVhXsTgPmVrswNFMD09BZqJsFKPgy + tE9U6BdIN5p9eOuRgA4L0pnPZHwaPGwwHcPkchOGlyoxMK/Cnblc2BfPYHRZC9dqCxotBcjXcWeT8/24 + JOcxsVznFmx47zS7qc5cAMfCZXT8fgSdLgnMLhm6p+XomVGgZ1aOZrsYv81XoNV2GorPQqzbd3p60c2p + pGw//nFtLOx/lKPlvghtE2LcmnoXJqcEXU4pbk9LUXR1Lw5kMiE5z4ZjsRJltQk4VBSQSTen3v4ooKah + Ox83x9JwY1RIJMloG09BOxGZpg5DWsZG3icyjIw7wZdvww9Dh9E2WII0VaCZCDZSwkL/kXZHAa4PJ0Hd + EoUY2UbkacNgvPcWcqo4KNLkwDW7BMWZRFxuFeHHe+/g9oQSaaXsNSLwot7M8182OtJhsMUhRuqJPqsV + +RcyECv3docnpx/g/FfZUH0TR6YTo95xED9NyJF6KhAhkd7PUq9l+97X9wpgsO6DujERGcWvwjmzhKbO + DoxOLmJg9A4Sc7fDOJKK2qF4fGfno3bgdYg+DqAn2EQlKFjNZY1RuGLZi2uDAhRXx6K4QoaFB2tYWPkb + h5R7cPVnIQyDsdDboqH/9UWU34zBGzksCxF4Ui+Ld4jTz3HxhSUSFb27cM0mQFb5bujqS2Hqv47Uc/5k + vf240v8CPrdEoPpuNI5d4oEveV5JBI8TqCcFct+7J77moqo3AppuLlnnIFJKfBEppaBp34+qPh4qCdpf + dqOkjofED1g2Lx/G0yTrQQvWR8Rv5SVk+s1/qAsigjBoerhkTyGaho9CRybT9Owi8nAU6kOQlOO/Fh63 + JYrkGJ0T71OUaVxGSxjh8Vv3HJD5jqSc3Imi2iCou0JxqZuDi2YOTn4fjFRVAF45yhzgPQrTo69zZzvG + JLSAfokbyFg+0cnPFcZJmGaBnAU3Chb4R5jWl0Q7Tnk+xdhC6hh0PZ1zZ//7+VdE70Tb6Xu+meBD8CZs + IjxB8Ph/fceYhPoHAkQRj5PgdPMAAAAASUVORK5CYII= + + + + 57 + + \ No newline at end of file diff --git a/应用/AllRebatesActivity/Properties/Resources.Designer.cs b/应用/AllRebatesActivity/Properties/Resources.Designer.cs new file mode 100644 index 0000000..f898a69 --- /dev/null +++ b/应用/AllRebatesActivity/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace AllRebatesActivity.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AllRebatesActivity.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 全额免单 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 全额免单 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 免单活动所有金额退还金额 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 全额免单 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 全额免单 { + get { + object obj = ResourceManager.GetObject("全额免单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/AllRebatesActivity/Properties/Resources.resx b/应用/AllRebatesActivity/Properties/Resources.resx new file mode 100644 index 0000000..0f5aeed --- /dev/null +++ b/应用/AllRebatesActivity/Properties/Resources.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 全额免单 + 插件主窗体名称 + + + 全额免单 + 插件名称 + + + 免单活动所有金额退还金额 + 插件介绍 + + + 全额免单 + + + + ..\Resources\全额免单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/AllRebatesActivity/Properties/licenses.licx b/应用/AllRebatesActivity/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/AllRebatesActivity/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/AllRebatesActivity/Resources/全额免单.png b/应用/AllRebatesActivity/Resources/全额免单.png new file mode 100644 index 0000000..4c20f2b Binary files /dev/null and b/应用/AllRebatesActivity/Resources/全额免单.png differ diff --git a/应用/AutoAnswer/AutoAnswer.csproj b/应用/AutoAnswer/AutoAnswer.csproj new file mode 100644 index 0000000..dc66293 --- /dev/null +++ b/应用/AutoAnswer/AutoAnswer.csproj @@ -0,0 +1,261 @@ + + + + + Debug + AnyCPU + {E5A7E5DB-EB35-4542-BD69-22E263691CAA} + Library + Properties + AutoAnswer + AutoAnswer + v4.6.1 + 512 + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + ..\..\..\..\..\..\Software\DevExpress 19.2\Components\Bin\Framework\DevExpress.CodeParser.v19.2.dll + False + + + False + ..\..\..\..\..\..\Software\DevExpress 19.2\Components\Bin\Framework\DevExpress.Data.v19.2.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + ..\..\Debug\HttpHelper.dll + False + + + + False + ..\..\Debug\SqlSugar.dll + False + + + False + + + False + + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + Form + + + ClearForm.cs + + + + + Form + + + EditUserDefinedForm.cs + + + + + + + + + Form + + + CommonForm.cs + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + True + True + Settings.settings + + + + + + ClearForm.cs + Designer + + + EditUserDefinedForm.cs + Designer + + + CommonForm.cs + + + MainForm.cs + Designer + + + MainForm.cs + Designer + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/应用/AutoAnswer/Class1 - 复制.cs b/应用/AutoAnswer/Class1 - 复制.cs new file mode 100644 index 0000000..a845ccd --- /dev/null +++ b/应用/AutoAnswer/Class1 - 复制.cs @@ -0,0 +1,440 @@ +using Api.Framework; +using Api.Framework.SDK; +using AutoAnswer.Entitys; +using AutoAnswer.Properties; +using Chat.Framework; +using Api.Framework.Tools; +using Microsoft.JScript; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using static AutoAnswer.Controls.Enums; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.IPAD; +using Chat.Framework.WXSdk.Implement; + +namespace AutoAnswer +{ + + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.问答; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + try + { + session.CreateTable(); + + if (session.TableExist()) + { + var definedLibList = session.Find(""); + if (definedLibList != null && definedLibList.Count != 0) + { + var dlibList = new List(); + foreach (var item in definedLibList) + { + dlibList.Add(new fl_plugin_autoanswer_definedlib() + { + antistop = item.antistop, + chat_type = item.chat_type, + content = item.content, + is_alert_admin = item.is_alert_admin, + match_pattern = item.match_pattern, + specific_robot_setting_text = string.Empty + }); + } + session.Insertable(dlibList).ExecuteCommand(); + } + } + } + catch (Exception ex) + { } + } + if (!session.TableExist()) session.CreateTable(); + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + if (Config.TuLing_OnOff) + { + if (e.Message.Contains(@"[\w\W]+)" : "^(" + Config.TuLing_prefix.Replace("$", @"\$").Replace("^", @"\^") + @")(?[\w\W]+)"; + var reg = Regex.Match(e.Message.Trim(), regexMess); + if (reg.Success) + { + string htmlResult = Tools.GetHtml(reg.Groups["text"].Value, e.Username); + var _mess = string.Empty; + if (!Regex.IsMatch(htmlResult, @"""intent"":{ ""code"":(5000|6000|4000|4001|4002|4003|4004|4005|4007|4100|4200|4300|4400|4500|4600|4602|7002|8008)}")) + { + var result = CsharpHttpHelper.HttpExtend.JsonToDictionary(htmlResult); + var results = result["results"] as ArrayList; + var obj = results[0] as Dictionary; + var vaules = obj["values"] as Dictionary; + e.SendMessage(vaules["text"].ToString()); + if (Config.CellCustomerServiceSwitch == Api.Framework.Enums.SwitchType.开启) return; + } + else + this.OnLog("图灵响应异常"); + } + } + + //是否通知管理员 + bool isAlertAdmin; + bool isAutoAnswer, issendstatus = false; + string mess = MessageFactory(e, out isAlertAdmin, out isAutoAnswer); + bool issend = false; + if (!string.IsNullOrWhiteSpace(mess) && !isAutoAnswer)//非自动回复消息 + { + e.SendMessage(mess); + issend = true; + //发送管理员 + if (isAlertAdmin) + { + string msg = string.Format(@"呼叫客服 +———— +微信账号:{0} +微信昵称:{1} +客户账号:{2} +客户昵称:{3} +客户备注:{4} +呼叫时间:{5} +呼叫内容:{6}", e.RobotName, e.RobotNick, e.Username, e.RealNick, e.NickName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), e.Message); + Thread.Sleep(300); + ApiClient.SendNoticeMessage(msg, Config.notice_robotname); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "客户留言提醒", msg, true); + } + } + + #region 呼叫客服 + if (Class1.Config.CellCustomerServiceSwitch == Api.Framework.Enums.SwitchType.开启) + { + if (string.IsNullOrEmpty(e.Groupid)) //私聊信息 + { + var _event = e.Event as Chat.Framework.WXSdk.Events.WXReiceveFriendMsg; + if (_event != null && _event.IsRobot)//判断是否自己给自己发送消息 + return; + } + + //触发呼叫客服关键词 + if (!string.IsNullOrEmpty(Class1.Config.TriggerAntistop) && Regex.IsMatch(e.Message, Class1.Config.TriggerAntistop)) + { + var weekDays = Class1.Config.WeekDay.Replace(",", ",").Split(',');//获取设置的上班星期 + if (weekDays != null && weekDays.Length != 0) + { + string week = ((WorkdayType)Enum.ToObject(typeof(WorkdayType), System.Convert.ToInt32(DateTime.Now.DayOfWeek.ToString("d")))).ToString(); + //为上班星期 + if (weekDays.Contains(week)) + { + var isOnDutyTime = false;//记录当前时间是否为上班时间区间 + var now = DateTime.Now; + + for (int i = 0; i < Class1.Config.WorkDayTimes.Length; i++) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.WorkDayTimes[i])) + { + var times = Class1.Config.WorkDayTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0].Trim()); + var end = DateTime.Parse(times[1].Trim()); + if (begin <= now && now <= end) + { + isOnDutyTime = true; + break; + } + } + } + } + //为上班的时间段 + if (isOnDutyTime) + e.SendMessage(Class1.Config.OnDuty_ReplyMessage); + else + e.SendMessage(Class1.Config.OffDuty_ReplyMessage); + } + //非上班星期 + else + e.SendMessage(Class1.Config.UnWeekDay_ReplyMessage); + string msg = string.Empty; + if (Config.MatchModel == Enums.ReplyModel.传递最近5条消息) + { + var session = ApiClient.GetSession(); + var hist_message = session.Find("select * from fl_plugin_autoanswer__log where datetime > @datetime and useraccount=@useraccount and chatType = @chatType order by id desc limit 0,5", new { datetime = DateTime.Now.AddMinutes(-10).ToString("yyyy-MM-dd HH:mm:ss"), useraccount = e.Username, chatType = (int)e.ChatType }); + string message_hist = string.Empty; + int number = 1; + foreach (var item in hist_message) + { + if (item.content.Contains("")) continue; + + message_hist += number + "." + GlobalObject.unescape(item.content) + "\r\n"; + number++; + } + message_hist = message_hist.Trim(); + if (message_hist.Length > 200) message_hist = message_hist.Substring(0, 200) + "..."; + msg = string.Format(@"客户呼叫提醒 +———— +微信账号:{0} +微信昵称:{1} +客户账号:{2} +客户昵称:{3} +客户备注:{4} +呼叫时间:{5} +———— +未回复: +{6}", e.RobotName, e.RobotNick, e.Username, e.RealNick, e.NickName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), message_hist); + } + else + { + if (!e.Message.Contains("")) + { + msg = string.Format(@"客户呼叫提醒 +———— +微信账号:{0} +微信昵称:{1} +客户账号:{2} +客户昵称:{3} +客户备注:{4} +呼叫时间:{5} +———— +消息: +{6}", e.RobotName, e.RobotNick, e.Username, e.RealNick, e.NickName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), e.Message.Trim()); + } + } + if (!string.IsNullOrWhiteSpace(msg)) + { + var wx = e.Sender as WeixinBase; + if (wx != null && Config.IsStickSwitch == Api.Framework.Enums.SwitchType.开启) + wx.EditContacts(e.Username, Chat.Framework.WXSdk.Implement.EditContactsType.置顶, e.NickName); + + issendstatus = true; + ApiClient.SendNoticeMessage(msg, Config.notice_robotname); + if (Config.ForcedResponse == Api.Framework.Enums.SwitchType.开启 && !string.IsNullOrWhiteSpace(mess) && !issend) + { + Thread.Sleep(500); + e.SendMessage(Tools.UrlEncodFactory(Config.DefaultContents[new Random(Guid.NewGuid().GetHashCode()).Next(0, Config.DefaultContents.Count)])); + } + } + } + } + } + #endregion + + if (!string.IsNullOrWhiteSpace(mess) && isAutoAnswer && !issendstatus) + { + e.SendMessage(mess); + //发送管理员 + if (isAlertAdmin) + { + string msg = string.Format(@"呼叫客服 +———— +微信账号:{0} +微信昵称:{1} +客户账号:{2} +客户昵称:{3} +客户备注:{4} +呼叫时间:{5} +呼叫内容:{6}", e.RobotName, e.RobotNick, e.Username, e.RealNick, e.NickName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), e.Message); + var wx = e.Sender as WeixinBase; + if (wx != null && Config.IsStickSwitch == Api.Framework.Enums.SwitchType.开启) + { + wx.EditContacts(e.Username, Chat.Framework.WXSdk.Implement.EditContactsType.置顶, e.NickName); + } + Thread.Sleep(300); + ApiClient.SendNoticeMessage(msg, Config.notice_robotname); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "客户留言提醒", msg, true); + } + } + } + catch (Exception ex) + { + this.OnLog("C:" + ex.Message); + e.SendMessage(ApiClient.Setting.SystemConfig.msg_error); + } + } + + private string cache_autoanswer_key = "cache_autoanswer_key"; + + #region 自定义回复处理方法(非图灵) + /// + /// 自定义回复处理方法(非图灵) + /// + /// + private string MessageFactory(ReciveIMEvent e, out bool isAlertAdmin, out bool isAutoAnswer) + { + isAutoAnswer = false; + try + { + var session = ApiClient.GetSession(); + //先看全部匹配的情况,是否满足 + var wordbank = session.Find("select * from fl_plugin_autoanswer_definedlib where antistop = @antistop and match_pattern = '0' and chat_type like @chattype [随机排序]", new { antistop = GlobalObject.escape(e.Message), chattype = "%" + (int)e.ChatType + "%" }).FirstOrDefault(); + //在看模糊匹配,是否满足 + if (wordbank == null) + { + var wordbanks = Tools.wordbanck_cache.Where(f => f.chat_type.Contains(((int)e.ChatType).ToString())).ToList(); + wordbank = wordbanks.FirstOrDefault(f => e.Message.Trim().Contains(GlobalObject.unescape(f.antistop))); + + //还不满足 择用 正则表达式匹配.获取所有"平台"模糊模式的集合 再通过正则筛选 是否满足 + if (wordbank == null) + wordbank = wordbanks.FirstOrDefault(f => f.chat_type.Contains(((int)e.ChatType).ToString()) && Regex.IsMatch(e.Message.Trim(), GlobalObject.unescape(f.antistop))); + } + bool is_robot = false; + //如果以上都没有存在的,那看下是否开启默认回复 与 是否开启记录功能了 + if (wordbank == null) + { + isAlertAdmin = false; + string mess = string.Empty; + + if (string.IsNullOrEmpty(e.Groupid) && Config.Is_Top_User) + { + var wx = e.Sender as WeixinBase; + if (wx != null) + wx.EditContacts(e.Username, EditContactsType.置顶, e.NickName); + } + + //默认回复 + if (Config.Is_Auto_Answer && Config.DefaultContents.Count != 0) + { + if (string.IsNullOrEmpty(e.Groupid)) //私聊信息 + { + if ((e.GetMemberinfo().upd_time - e.GetMemberinfo().crt_time).TotalSeconds > 4) + { + var value = ApiClient.Cache.Get>(cache_autoanswer_key); + var _event = e.Event as Chat.Framework.WXSdk.Events.WXReiceveFriendMsg; + if (_event != null && _event.IsRobot)//判断是否自己给自己发送消息 + { + is_robot = true; + if (value == null) + value = new List(); + value.Add(e.GetMemberinfo().id); + ApiClient.Cache.Set(cache_autoanswer_key, value, 5); + return string.Empty; + } + else if (value != null && value.Contains(e.GetMemberinfo().id)) + return string.Empty; + } + } + mess = Tools.UrlEncodFactory(Config.DefaultContents[new Random(Guid.NewGuid().GetHashCode()).Next(0, Config.DefaultContents.Count)]); + isAutoAnswer = true; + } + if (Config.Is_Log && !is_robot) + AddAutoanswerLog(e.Message.Trim(), e.ChatType, e.RobotNick, e.Username, e.NickName, true); + return mess; + } + else //处理信息将随机的信息返回 + { + string[] result = Tools.UrlEncodFactory(GlobalObject.unescape(wordbank.content), false).Split(new string[] { "\r\n-----------分割线-----------\r\n", "\r\n-----------分割线-----------", "-----------分割线-----------\r\n" }, StringSplitOptions.RemoveEmptyEntries); + isAlertAdmin = (wordbank.is_alert_admin == 1); + return result[new Random(Guid.NewGuid().GetHashCode()).Next(0, result.Length)]; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + isAlertAdmin = false; + return string.Empty; + } + #endregion + + #region 自动记录包含默认回复的关键词 + /// + /// 自动记录包含默认回复的关键词 + /// + /// + /// + /// + /// + /// + private void AddAutoanswerLog(string mess, ChatType chatType, string robotnick, string username, string nicknname, bool status) + { + try + { + var recordignored = new fl_plugin_autoanswer__log() + { + content = GlobalObject.escape(mess), + robot_name = robotnick, + chatType = chatType, + useraccount = username, + username = GlobalObject.escape(nicknname), + status = status, + datetime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) + }; + var session = ApiClient.GetSession(); + session.Insertable(recordignored).ExecuteCommand(); ; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + #endregion + + } +} diff --git a/应用/AutoAnswer/Class1.cs b/应用/AutoAnswer/Class1.cs new file mode 100644 index 0000000..72069d8 --- /dev/null +++ b/应用/AutoAnswer/Class1.cs @@ -0,0 +1,590 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using AutoAnswer.Entitys; +using AutoAnswer.Properties; +using Chat.Framework.WXSdk.Implement; +using Microsoft.JScript; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using static AutoAnswer.Controls.Enums; + +namespace AutoAnswer +{ + + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.问答; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + try + { + session.CreateTable(); + + if (session.TableExist()) + { + var definedLibList = session.Find("select * from fl_plugin_autoanswer_userdefinedlibrary"); + if (definedLibList != null && definedLibList.Count != 0) + { + //var dlibList = new List(); + foreach (var item in definedLibList) + { + //dlibList.Add(new fl_plugin_autoanswer_definedlib() + //{ + // antistop = item.antistop, + // chat_type = item.chat_type, + // content = item.content, + // is_alert_admin = item.is_alert_admin, + // match_pattern = item.match_pattern, + // specific_robot_setting_text = string.Empty + //}); + try + { + session.Insertable(new fl_plugin_autoanswer_definedlib() + { + antistop = item.antistop, + chat_type = item.chat_type, + content = item.content, + is_alert_admin = item.is_alert_admin, + match_pattern = item.match_pattern, + specific_robot_setting_text = string.Empty + }).ExecuteCommand(); + } + catch (Exception ex) + { } + finally + { + Thread.Sleep(50); + } + } + + } + } + } + catch (Exception ex) + { } + } + if (!session.TableExist()) session.CreateTable(); + + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("rid"); + } + + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + if (Config.TuLing_OnOff) + { + if (e.Message.Contains(@"[\w\W]+)" : "^(" + Config.TuLing_prefix.Replace("$", @"\$").Replace("^", @"\^") + @")(?[\w\W]+)"; + var reg = Regex.Match(e.Message.Trim(), regexMess); + if (reg.Success) + { + string htmlResult = Tools.GetHtml(reg.Groups["text"].Value, e.Username); + var _mess = string.Empty; + if (!Regex.IsMatch(htmlResult, @"""intent"":{ ""code"":(5000|6000|4000|4001|4002|4003|4004|4005|4007|4100|4200|4300|4400|4500|4600|4602|7002|8008)}")) + { + var result = CsharpHttpHelper.HttpExtend.JsonToDictionary(htmlResult); + var results = result["results"] as ArrayList; + var obj = results[0] as Dictionary; + var vaules = obj["values"] as Dictionary; + e.SendMessage(vaules["text"].ToString()); + if (Config.CellCustomerServiceSwitch == Api.Framework.Enums.SwitchType.开启) return; + } + else + this.OnLog("图灵响应异常"); + } + } + + //是否通知管理员 + bool isAlertAdmin; + bool isAutoAnswer, issendstatus = false; + string mess = MessageFactory(e, out isAlertAdmin, out isAutoAnswer); + bool issend = false; + if (!string.IsNullOrWhiteSpace(mess) && !isAutoAnswer)//非自动回复消息 + { + e.SendMessage(mess); + issend = true; + //发送管理员 + if (isAlertAdmin) + { + string msg = string.Format(@"呼叫客服 +———— +微信账号:{0} +微信昵称:{1} +客户账号:{2} +客户昵称:{3} +客户备注:{4} +呼叫时间:{5} +呼叫内容:{6}", e.RobotName, e.RobotNick, e.Username, e.RealNick, e.NickName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), e.Message); + Thread.Sleep(300); + ApiClient.SendNoticeMessage(msg, Config.notice_robotname); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "客户留言提醒", msg, true); + } + } + + #region 呼叫客服 + if (Class1.Config.CellCustomerServiceSwitch == Api.Framework.Enums.SwitchType.开启) + { + if (string.IsNullOrEmpty(e.Groupid)) //私聊信息 + { + var _event = e.Event as Chat.Framework.WXSdk.Events.WXReiceveFriendMsg; + if (_event != null && _event.IsRobot)//判断是否自己给自己发送消息 + return; + } + + //触发呼叫客服关键词 + if (!string.IsNullOrEmpty(Class1.Config.TriggerAntistop) && Regex.IsMatch(e.Message, Class1.Config.TriggerAntistop)) + { + var weekDays = Class1.Config.WeekDay.Replace(",", ",").Split(',');//获取设置的上班星期 + if (weekDays != null && weekDays.Length != 0) + { + string week = ((WorkdayType)Enum.ToObject(typeof(WorkdayType), System.Convert.ToInt32(DateTime.Now.DayOfWeek.ToString("d")))).ToString(); + //为上班星期 + if (weekDays.Contains(week)) + { + var isOnDutyTime = false;//记录当前时间是否为上班时间区间 + var now = DateTime.Now; + + for (int i = 0; i < Class1.Config.WorkDayTimes.Length; i++) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.WorkDayTimes[i])) + { + var times = Class1.Config.WorkDayTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0].Trim()); + var end = DateTime.Parse(times[1].Trim()); + if (begin <= now && now <= end) + { + isOnDutyTime = true; + break; + } + } + } + } + //为上班的时间段 + if (isOnDutyTime) + e.SendMessage(Class1.Config.OnDuty_ReplyMessage); + else + e.SendMessage(Class1.Config.OffDuty_ReplyMessage); + } + //非上班星期 + else + e.SendMessage(Class1.Config.UnWeekDay_ReplyMessage); + string msg = string.Empty; + if (Config.MatchModel == Enums.ReplyModel.传递最近5条消息) + { + var session = ApiClient.GetSession(); + var hist_message = session.Find("select * from fl_plugin_autoanswer__log where datetime > @datetime and useraccount=@useraccount and chatType = @chatType order by id desc limit 0,5", new { datetime = DateTime.Now.AddMinutes(-10).ToString("yyyy-MM-dd HH:mm:ss"), useraccount = e.Username, chatType = (int)e.ChatType }); + string message_hist = string.Empty; + int number = 1; + foreach (var item in hist_message) + { + if (item.content.Contains("")) continue; + + message_hist += number + "." + GlobalObject.unescape(item.content) + "\r\n"; + number++; + } + message_hist = message_hist.Trim(); + if (message_hist.Length > 200) message_hist = message_hist.Substring(0, 200) + "..."; + msg = string.Format(@"客户呼叫提醒 +———— +微信账号:{0} +微信昵称:{1} +客户账号:{2} +客户昵称:{3} +客户备注:{4} +呼叫时间:{5} +———— +未回复: +{6}", e.RobotName, e.RobotNick, e.Username, e.RealNick, e.NickName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), message_hist); + } + else + { + if (!e.Message.Contains("")) + { + msg = string.Format(@"客户呼叫提醒 +———— +微信账号:{0} +微信昵称:{1} +客户账号:{2} +客户昵称:{3} +客户备注:{4} +呼叫时间:{5} +———— +消息: +{6}", e.RobotName, e.RobotNick, e.Username, e.RealNick, e.NickName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), e.Message.Trim()); + } + } + if (!string.IsNullOrWhiteSpace(msg)) + { + var wx = e.Sender as WeixinBase; + if (wx != null && Config.IsStickSwitch == Api.Framework.Enums.SwitchType.开启) + wx.EditContacts(e.Username, Chat.Framework.WXSdk.Implement.EditContactsType.置顶, e.NickName); + + issendstatus = true; + ApiClient.SendNoticeMessage(msg, Config.notice_robotname); + if (Config.ForcedResponse == Api.Framework.Enums.SwitchType.开启 && !string.IsNullOrWhiteSpace(mess) && !issend) + { + Thread.Sleep(500); + e.SendMessage(Tools.UrlEncodFactory(Config.DefaultContents[new Random(Guid.NewGuid().GetHashCode()).Next(0, Config.DefaultContents.Count)])); + } + } + } + } + } + #endregion + + if (!string.IsNullOrWhiteSpace(mess) && isAutoAnswer && !issendstatus) + { + e.SendMessage(mess); + //发送管理员 + if (isAlertAdmin) + { + string msg = string.Format(@"呼叫客服 +———— +微信账号:{0} +微信昵称:{1} +客户账号:{2} +客户昵称:{3} +客户备注:{4} +呼叫时间:{5} +呼叫内容:{6}", e.RobotName, e.RobotNick, e.Username, e.RealNick, e.NickName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), e.Message); + var wx = e.Sender as WeixinBase; + if (wx != null && Config.IsStickSwitch == Api.Framework.Enums.SwitchType.开启) + { + wx.EditContacts(e.Username, EditContactsType.置顶, e.NickName); + } + Thread.Sleep(300); + ApiClient.SendNoticeMessage(msg, Config.notice_robotname); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "客户留言提醒", msg, true); + } + } + } + catch (Exception ex) + { + this.OnLog("C:" + ex.Message); + e.SendMessage(ApiClient.Setting.SystemConfig.msg_error); + } + } + + private string cache_autoanswer_key = "cache_autoanswer_key"; + + #region 自定义回复处理方法(非图灵) + /// + /// 自定义回复处理方法(非图灵) + /// + /// + private string MessageFactory(ReciveIMEvent e, out bool isAlertAdmin, out bool isAutoAnswer) + { + var str = "微信"; + if (e.RobotInfo.type == ChatType.QQ) + str = "QQ"; + var robot_str = $"{e.RobotInfo.name}_{str}"; + + isAutoAnswer = false; + try + { + fl_plugin_autoanswer_definedlib wordbank = null; + var session = ApiClient.GetSession(); + + #region 这里是指定机器人回复的内容 + //先看全部匹配的情况,是否满足 + wordbank = session.Find("select * from fl_plugin_autoanswer_definedlib where specific_robot_setting_text != '' and antistop = @antistop and match_pattern = '0' and chat_type like @chattype and specific_robot_setting_text like @specific_robot_setting_text [随机排序]", new { antistop = GlobalObject.escape(e.Message), chattype = "%" + (int)e.ChatType + "%", specific_robot_setting_text = "%" + robot_str + "%" }).FirstOrDefault(); + + List wordbanks = null; + //在看模糊匹配,是否满足 + if (wordbank == null) + { + wordbanks = Tools.WordbanckCache.Where(f => f.chat_type.Contains(((int)e.ChatType).ToString()) && !string.IsNullOrWhiteSpace(f.specific_robot_setting_text) && f.specific_robot_setting_text.Contains(robot_str)).ToList(); + wordbank = wordbanks.FirstOrDefault(f => e.Message.Trim().Contains(GlobalObject.unescape(f.antistop))); + + //还不满足 择用 正则表达式匹配.获取所有"平台"模糊模式的集合 再通过正则筛选 是否满足 + if (wordbank == null) + { + try + { + wordbank = wordbanks.FirstOrDefault(f => Regex.IsMatch(e.Message.Trim(), GlobalObject.unescape(f.antistop))); + } + catch (Exception) + { } + } + } + #endregion + + #region 这里是非指定的机器人 + if (wordbank == null) + { + wordbank = session.Find("select * from fl_plugin_autoanswer_definedlib where specific_robot_setting_text = '' and antistop = @antistop and match_pattern = '0' and chat_type like @chattype [随机排序]", new { antistop = GlobalObject.escape(e.Message), chattype = "%" + (int)e.ChatType + "%" }).FirstOrDefault(); + + //在看模糊匹配,是否满足 + if (wordbank == null) + { + wordbanks = Tools.WordbanckCache.Where(f => string.IsNullOrWhiteSpace(f.specific_robot_setting_text) && f.chat_type.Contains(((int)e.ChatType).ToString())).ToList(); + wordbank = wordbanks.FirstOrDefault(f => e.Message.Trim().Contains(GlobalObject.unescape(f.antistop))); + //还不满足 择用 正则表达式匹配.获取所有"平台"模糊模式的集合 再通过正则筛选 是否满足 + if (wordbank == null) + { + try + { + wordbank = wordbanks.FirstOrDefault(f => Regex.IsMatch(e.Message.Trim(), GlobalObject.unescape(f.antistop))); + } + catch (Exception) + { } + } + } + } + #endregion + + bool is_robot = false; + //如果以上都没有存在的,那看下是否开启默认回复 与 是否开启记录功能了 + if (wordbank == null) + { + isAlertAdmin = false; + string mess = string.Empty; + + if (string.IsNullOrEmpty(e.Groupid) && Config.Is_Top_User) + { + var wx = e.Sender as WeixinBase; + if (wx != null) + wx.EditContacts(e.Username, EditContactsType.置顶, e.NickName); + } + + //默认回复 + if (Config.Is_Auto_Answer && Config.DefaultContents.Count != 0) + { + if (string.IsNullOrEmpty(e.Groupid)) //私聊信息 + { + if ((e.GetMemberinfo().upd_time - e.GetMemberinfo().crt_time).TotalSeconds > 4) + { + var value = ApiClient.Cache.Get>(cache_autoanswer_key); + var _event = e.Event as Chat.Framework.WXSdk.Events.WXReiceveFriendMsg; + if (_event != null && _event.IsRobot)//判断是否自己给自己发送消息 + { + is_robot = true; + if (value == null) + value = new List(); + value.Add(e.GetMemberinfo().id); + ApiClient.Cache.Set(cache_autoanswer_key, value, 5); + return string.Empty; + } + else if (value != null && value.Contains(e.GetMemberinfo().id)) + return string.Empty; + } + } + mess = Tools.UrlEncodFactory(Config.DefaultContents[new Random(Guid.NewGuid().GetHashCode()).Next(0, Config.DefaultContents.Count)]); + isAutoAnswer = true; + } + + //未处理消息转发 + var unprocesseds = Tools.FindUnprocesseds(); + if (unprocesseds != null && unprocesseds.Count != 0) + { + if (e.RobotName != e.Username) + { + var r = unprocesseds.FirstOrDefault(f => f.rid == e.RobotInfo.id); + if (r != null) + { + var flag = false; + if (r.messtype.Contains("所有类型")) + { + //<![CDATA[邀请你加入群聊]]>view500 + if (e.Message.Contains("appmsg appid=") && + e.Message.Contains("")) + flag = false; + else + flag = true; + } + //是否转发 + var isSend = false; + + var nick = string.Empty; + if (!string.IsNullOrWhiteSpace(e.Groupid) && (flag || r.messtype.Contains("群聊类型"))) + { + isSend = true; + if (e.Sender is WXClientImpl_HOOK) + { + var hook = e.Sender as WXClientImpl_HOOK; + if (hook != null) + { + if (hook.Friends.ContainsKey(e.Groupid)) + nick = hook.Friends[e.Groupid].NickName; + } + } + if (e.Sender is WXClientImpl_QYHOOK) + { + var hook = e.Sender as WXClientImpl_QYHOOK; + if (hook != null) + { + if (hook.Friends.ContainsKey(e.Groupid)) + nick = hook.Friends[e.Groupid].NickName; + } + } + if (e.Sender is WXClientImpl_IPAD) + { + var hook = e.Sender as WXClientImpl_IPAD; + if (hook != null) + { + if (hook.Friends.ContainsKey(e.Groupid)) + nick = hook.Friends[e.Groupid].NickName; + } + } + nick = $"群:{nick}"; + } + else + { + if (string.IsNullOrWhiteSpace(e.Groupid) && (flag || r.messtype.Contains("私聊类型"))) + { + isSend = true; + nick = $"私:{e.RealNick}"; + } + } + + if (isSend) + { + var reg = Regex.Match(e.Message, @"()", RegexOptions.IgnoreCase); + if (reg.Success) + { + ApiClient.SendMessage(e.RobotInfo, r.username, $@"{nick} +发送人:{e.NickName} +内容:小程序或卡片消息"); + Thread.Sleep(500); + ApiClient.SendMessage(e.RobotInfo, r.username, reg.Groups[1].Value); + } + else + ApiClient.SendMessage(e.RobotInfo, r.username, $@"{nick} +发送人:{e.NickName} +内容:{e.Message}"); + } + } + } + } + + if (Config.Is_Log && !is_robot) + AddAutoanswerLog(e.Message.Trim(), e.ChatType, e.RobotNick, e.Username, e.NickName, true); + return mess; + } + else //处理信息将随机的信息返回 + { + string[] result = Tools.UrlEncodFactory(GlobalObject.unescape(wordbank.content), false).Split(new string[] { "\r\n-----------分割线-----------\r\n", "\r\n-----------分割线-----------", "-----------分割线-----------\r\n" }, StringSplitOptions.RemoveEmptyEntries); + isAlertAdmin = (wordbank.is_alert_admin == 1); + return result[new Random(Guid.NewGuid().GetHashCode()).Next(0, result.Length)]; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + isAlertAdmin = false; + return string.Empty; + } + #endregion + + #region 自动记录包含默认回复的关键词 + /// + /// 自动记录包含默认回复的关键词 + /// + /// + /// + /// + /// + /// + private void AddAutoanswerLog(string mess, ChatType chatType, string robotnick, string username, string nicknname, bool status) + { + try + { + var recordignored = new fl_plugin_autoanswer__log() + { + content = GlobalObject.escape(mess), + robot_name = robotnick, + chatType = chatType, + useraccount = username, + username = GlobalObject.escape(nicknname), + status = status, + datetime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) + }; + var session = ApiClient.GetSession(); + session.Insertable(recordignored).ExecuteCommand(); ; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + #endregion + + } +} diff --git a/应用/AutoAnswer/ClearForm.Designer.cs b/应用/AutoAnswer/ClearForm.Designer.cs new file mode 100644 index 0000000..ae8a8c1 --- /dev/null +++ b/应用/AutoAnswer/ClearForm.Designer.cs @@ -0,0 +1,186 @@ +namespace AutoAnswer +{ + partial class ClearForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.bck_Is_Log = new UI.Framework.Controls.ButtonCheck(); + this.label4 = new System.Windows.Forms.Label(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.label3 = new System.Windows.Forms.Label(); + this.linkLabel_clear = new System.Windows.Forms.LinkLabel(); + this.numericUpDown_Day1 = new System.Windows.Forms.NumericUpDown(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.linkLabel_allclear = new System.Windows.Forms.LinkLabel(); + this.groupBox1.SuspendLayout(); + this.groupBox4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown_Day1)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.bck_Is_Log); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Location = new System.Drawing.Point(23, 25); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(319, 64); + this.groupBox1.TabIndex = 11; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 留言管理开关 "; + // + // bck_Is_Log + // + this.bck_Is_Log.BackColor = System.Drawing.Color.Transparent; + this.bck_Is_Log.Checked = false; + this.bck_Is_Log.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.bck_Is_Log.Cursor = System.Windows.Forms.Cursors.Hand; + this.bck_Is_Log.Location = new System.Drawing.Point(238, 26); + this.bck_Is_Log.Name = "bck_Is_Log"; + this.bck_Is_Log.Size = new System.Drawing.Size(59, 20); + this.bck_Is_Log.TabIndex = 18; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Font = new System.Drawing.Font("宋体", 9F); + this.label4.Location = new System.Drawing.Point(19, 31); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(197, 12); + this.label4.TabIndex = 7; + this.label4.Text = "记录未回复的信息(方便以后查询)"; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.label3); + this.groupBox4.Controls.Add(this.linkLabel_clear); + this.groupBox4.Controls.Add(this.numericUpDown_Day1); + this.groupBox4.Controls.Add(this.label2); + this.groupBox4.Controls.Add(this.label1); + this.groupBox4.Controls.Add(this.linkLabel_allclear); + this.groupBox4.Location = new System.Drawing.Point(23, 104); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(319, 124); + this.groupBox4.TabIndex = 9; + this.groupBox4.TabStop = false; + this.groupBox4.Text = " 手动清理 "; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(19, 86); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(127, 15); + this.label3.TabIndex = 5; + this.label3.Text = "删除所有未回复数据:"; + // + // linkLabel_clear + // + this.linkLabel_clear.AutoSize = true; + this.linkLabel_clear.Location = new System.Drawing.Point(242, 39); + this.linkLabel_clear.Name = "linkLabel_clear"; + this.linkLabel_clear.Size = new System.Drawing.Size(55, 15); + this.linkLabel_clear.TabIndex = 4; + this.linkLabel_clear.TabStop = true; + this.linkLabel_clear.Text = "确定清空"; + this.linkLabel_clear.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_clear_LinkClicked); + // + // numericUpDown_Day1 + // + this.numericUpDown_Day1.Location = new System.Drawing.Point(55, 35); + this.numericUpDown_Day1.Name = "numericUpDown_Day1"; + this.numericUpDown_Day1.Size = new System.Drawing.Size(49, 21); + this.numericUpDown_Day1.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(20, 39); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(31, 15); + this.label2.TabIndex = 2; + this.label2.Text = "删除"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(107, 39); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(67, 15); + this.label1.TabIndex = 1; + this.label1.Text = "天前的数据"; + // + // linkLabel_allclear + // + this.linkLabel_allclear.AutoSize = true; + this.linkLabel_allclear.Location = new System.Drawing.Point(242, 86); + this.linkLabel_allclear.Name = "linkLabel_allclear"; + this.linkLabel_allclear.Size = new System.Drawing.Size(55, 15); + this.linkLabel_allclear.TabIndex = 0; + this.linkLabel_allclear.TabStop = true; + this.linkLabel_allclear.Text = "全部清空"; + this.linkLabel_allclear.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_allclear_LinkClicked); + // + // ClearForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(360, 249); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.groupBox4); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ClearForm"; + this.ShowIcon = false; + this.Text = "清除缓存窗体"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ClearForm_FormClosing); + this.Load += new System.EventHandler(this.ClearForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown_Day1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.LinkLabel linkLabel_clear; + private System.Windows.Forms.NumericUpDown numericUpDown_Day1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.LinkLabel linkLabel_allclear; + private UI.Framework.Controls.ButtonCheck bck_Is_Log; + } +} \ No newline at end of file diff --git a/应用/AutoAnswer/ClearForm.cs b/应用/AutoAnswer/ClearForm.cs new file mode 100644 index 0000000..31f80f4 --- /dev/null +++ b/应用/AutoAnswer/ClearForm.cs @@ -0,0 +1,72 @@ +using Api.Framework; +using Api.Framework.Tools; +using AutoAnswer.Properties; +using System; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace AutoAnswer +{ + public partial class ClearForm : BaseForm + { + public ClearForm() + { + InitializeComponent(); + this.Text = Resources.ClearLogFormTile; + } + + /// + /// 窗体加载 + /// + /// + /// + private void ClearForm_Load(object sender, EventArgs e) + { + bck_Is_Log.Checked = Class1.Config.Is_Log; + } + + /// + /// 删除几天前所有的数据 + /// + /// + /// + private void linkLabel_clear_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("DELETE FROM 'fl_plugin_autoanswer__log' where datetime <= '" + DateTime.Parse(DateTime.Now.AddDays(-double.Parse(numericUpDown_Day1.Value.ToString())).ToString("yyyy-MM-dd HH:mm:ss")) + "';"); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 删除所有的数据 + /// + /// + /// + private void linkLabel_allclear_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("DELETE FROM 'fl_plugin_autoanswer__log';DELETE FROM sqlite_sequence WHERE name = 'fl_plugin_autoanswer__log';"); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void ClearForm_FormClosing(object sender, FormClosingEventArgs e) + { + Class1.Config.Is_Log = bck_Is_Log.Checked; + } + + } +} \ No newline at end of file diff --git a/应用/AutoAnswer/ClearForm.resx b/应用/AutoAnswer/ClearForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/AutoAnswer/ClearForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/AutoAnswer/CommonForm.Designer.cs b/应用/AutoAnswer/CommonForm.Designer.cs new file mode 100644 index 0000000..43238cb --- /dev/null +++ b/应用/AutoAnswer/CommonForm.Designer.cs @@ -0,0 +1,87 @@ +namespace AutoAnswer +{ + partial class CommonForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(152, 28); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(58, 14); + this.labelControl2.TabIndex = 5; + this.labelControl2.Text = "(一行一个)"; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(30, 48); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(486, 188); + this.memoEdit1.TabIndex = 4; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(30, 28); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(47, 14); + this.labelControl1.TabIndex = 3; + this.labelControl1.Text = "增加@:"; + // + // CommonForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(546, 270); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.memoEdit1); + this.Controls.Add(this.labelControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CommonForm"; + this.Text = "增加@"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CommonForm_FormClosing); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + } +} \ No newline at end of file diff --git a/应用/AutoAnswer/CommonForm.cs b/应用/AutoAnswer/CommonForm.cs new file mode 100644 index 0000000..b52aac9 --- /dev/null +++ b/应用/AutoAnswer/CommonForm.cs @@ -0,0 +1,23 @@ +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace AutoAnswer +{ + public partial class CommonForm : BaseForm + { + public CommonForm(string text) + { + InitializeComponent(); + this.Text = this.Text.Replace("@", text); + this.labelControl1.Text = labelControl1.Text.Replace("@", text); + } + + public string Strs = string.Empty; + + private void CommonForm_FormClosing(object sender, FormClosingEventArgs e) + { + Strs = memoEdit1.Text.Trim(); + this.DialogResult = DialogResult.OK; + } + } +} diff --git a/应用/AutoAnswer/CommonForm.resx b/应用/AutoAnswer/CommonForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/AutoAnswer/CommonForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/AutoAnswer/Config.cs b/应用/AutoAnswer/Config.cs new file mode 100644 index 0000000..27a546f --- /dev/null +++ b/应用/AutoAnswer/Config.cs @@ -0,0 +1,259 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using AutoAnswer.Controls; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static Api.Framework.Config.SystemConfig; +using static AutoAnswer.Enums; + +namespace AutoAnswer +{ + /// + /// 配置插件配置文件: Name = 文件名,IsSaveDB = 是否保存到数据库, IsEncryption = 是否对数据加密 + /// + [Config(Name = "插件-问答插件-配置")] + public class Config + { + + #region 基础属性 + /// + /// 图灵开关 + /// + [Browsable(false)] + public bool TuLing_OnOff { get; set; } + /// + /// 图灵apikey + /// + [Browsable(false)] + public string TuLing_apikey { get; set; } + /// + /// 图灵响应的前缀 + /// + [Browsable(false)] + public string TuLing_prefix { get; set; } + /// + /// 是否开启自动回复 + /// + [Browsable(false)] + public bool Is_Auto_Answer { get; set; } + /// + /// 是否置顶用户 + /// + [Browsable(false)] + public bool Is_Top_User { get; set; } + /// + /// 都否开启自动清理 + /// + [Browsable(false)] + public bool Is_AutoClear_Start { get; set; } + /// + /// 删除多少天之前的数据 + /// + [Browsable(false)] + public int Logs_Keep_Days { get; set; } + /// + /// 是否记录包含默认回复的关键词 + /// + [Browsable(false)] + public bool Is_Log { get; set; } + /// + /// 默认回复集合 + /// + [Browsable(false)] + public List DefaultContents { get; set; } + #endregion + + #region 呼叫客服属性 + + /// + /// 呼叫客服开关 + /// + [ + Category("1)、呼叫客服"), DisplayName("01.呼叫客服开关"), DefaultValue(SwitchType.开启) + ] + public SwitchType CellCustomerServiceSwitch { get; set; } + + /// + /// 触发关键词 + /// + [Category("1)、呼叫客服"), DisplayName("02.触发关键词"), DefaultValue(@"^(客服|在吗|人呢)$"), + Description(@"支持正则表达式,通过指令可以触发下面的提示语!")] + public string TriggerAntistop { get; set; } + + /// + /// 是否置顶 + /// + [ + Category("1)、呼叫客服"), DisplayName("03.呼叫后自动置顶"), DefaultValue(SwitchType.开启), + Description(@"只支持微信,呼叫后自动置顶") + ] + public SwitchType IsStickSwitch { get; set; } + + /// + /// 工作日 + /// + [ + Category("1)、呼叫客服"), DisplayName("04.工作日"), DefaultValue(@"星期一,星期二,星期三,星期四,星期五,星期六"), + Description(@""), + Editor(typeof(CategoryControl), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string WeekDay { get; set; } + + private string[] _workdayTimes; + /// + /// 发送任务时间段 + /// + [ + Category("1)、呼叫客服"), DisplayName("05.上班时间"), + Description(@"每一行为一个上班时间区间段 +格式:时间1-时间2 +注:时间1 必须大于 时间2") + ] + public string[] WorkDayTimes + { + get { return _workdayTimes; } + set + { + var sendTaskTimes = value as string[]; + if (sendTaskTimes != null && sendTaskTimes.Length != 0) + { + for (int i = 0; i < sendTaskTimes.Length; i++) + { + var times = sendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0]); + var end = DateTime.Parse(times[1]); + if (begin >= end) + throw new Exception($"开始时间必须小于结束时间:[{sendTaskTimes[i]}]"); + } + } + } + _workdayTimes = value; + } + } + + /// + /// 上班时间触发内容 + /// + [ + Category("1)、呼叫客服"), DisplayName("06.上班时回复"), DefaultValue(@"正在为您呼叫客服,请稍等...."), + Description(@""), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string OnDuty_ReplyMessage { get; set; } + + /// + /// 下班时间触发内容 + /// + [ + Category("1)、呼叫客服"), DisplayName("07.下班时回复"), DefaultValue(@"客服正在休息,您可以继续留言,客服上班后会联系您!"), + Description(@""), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string OffDuty_ReplyMessage { get; set; } + + /// + /// 休息日触发内容 + /// + [ + Category("1)、呼叫客服"), DisplayName("08.节假日回复"), DefaultValue(@"亲,今天客服不上班!\r\n您有疑问可以给我们留言哦,上班后会给您处理!"), + Description(@"用户触发关键词,将自动发送本文内容"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string UnWeekDay_ReplyMessage { get; set; } + + + ///// + ///// 休息日触发内容 + ///// + //[ + // Category("1)、呼叫客服"), DisplayName("09.钉钉群机器人"), DefaultValue(@""), + // Description(@"钉钉群机器人,不填写将会调用主程序链接!"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + //] + //public string DingdingRobot { get; set; } + + ///// + ///// 休息日触发内容 + ///// + //[ + // Category("1)、呼叫客服"), DisplayName("10.钉钉群Token"), DefaultValue(@""), + // Description(@"钉钉群机器人,不填写将会调用主程序链接!"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + //] + //public string DingdingRobotToken { get; set; } + + + /// + /// 钉钉群通知 + /// + [Category("1)、呼叫客服"), DisplayName("09.钉钉/微信群机器人"), DefaultValue("请选择(钉钉/微信群机器人API名称)"), Description("请选择已存在的机器人名称,如果还没有添加,在【系统管理->群通知机器人】中添加机器人!"), TypeConverter(typeof(notice_robotname_item))] + public string notice_robotname { get; set; } + + + /// + /// 回复模式 + /// + [ + Category("1)、呼叫客服"), DisplayName("10.钉钉传递消息模式"), DefaultValue(ReplyModel.传递最近5条消息), + Description(@"1、传递最近5条消息:钉钉将收到用户最近触发的5条消息 +2、传递当前消息:钉钉将收到用户当前发送的消息") + ] + public ReplyModel MatchModel { get; set; } + + /// + /// + /// + [ + Category("1)、呼叫客服"), DisplayName("11.触发客服关键词后继续推送默认消息"), DefaultValue(SwitchType.关闭), + Description(@"触发客服关键词后继续推送默认消息") + ] + public SwitchType ForcedResponse { get; set; } + + #endregion + + #region 未识别的消息转发 + + #endregion + + /// + /// 机器人调用默认的构造函数 + /// + public Config() + { + #region 基础属性 + TuLing_OnOff = false; + TuLing_prefix = "#|~"; + TuLing_apikey = ""; + DefaultContents = new List();//初始化集合对象 + Logs_Keep_Days = 15;//初始化天数 + Is_AutoClear_Start = true;//默认打开自动清理 + Is_Auto_Answer = false;//默认关闭自动回复 + Is_Top_User = false;//默认关闭自定置顶 + Is_Log = false; + #endregion + + #region 呼叫客服属性 + this.CellCustomerServiceSwitch = SwitchType.关闭; + this.IsStickSwitch = SwitchType.开启; + this.TriggerAntistop = @"^(客服|在吗|人呢)$"; + this.WeekDay = @"星期一,星期二,星期三,星期四,星期五,星期六"; + this._workdayTimes = new string[] { "09:00-12:00", "13:00-22:00" }; + + this.OnDuty_ReplyMessage = @"正在为您呼叫客服,请稍等...."; + this.OffDuty_ReplyMessage = @"客服正在休息,您可以继续留言,客服上班后会联系您!"; + this.UnWeekDay_ReplyMessage = @"亲,今天客服不上班!\r\n您有疑问可以给我们留言哦,上班后会给您处理!"; + this.notice_robotname = "请选择(钉钉/微信群机器人API名称)"; + this.MatchModel = ReplyModel.传递最近5条消息; + this.ForcedResponse = SwitchType.关闭; + #endregion + + } + } +} diff --git a/应用/AutoAnswer/Controls/CategoryControl.cs b/应用/AutoAnswer/Controls/CategoryControl.cs new file mode 100644 index 0000000..e5419f8 --- /dev/null +++ b/应用/AutoAnswer/Controls/CategoryControl.cs @@ -0,0 +1,68 @@ +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static AutoAnswer.Controls.Enums; + +namespace AutoAnswer.Controls +{ + public class Enums + { + /// + /// 工作日枚举 + /// + public enum WorkdayType + { + 星期一 = 1, + 星期二 = 2, + 星期三 = 3, + 星期四 = 4, + 星期五 = 5, + 星期六 = 6, + 星期日 = 0, + } + } + + class CategoryControl : PropertyGridEditStyle + { + public CategoryControl() + { + var listBox = new CheckedListBoxControl(); + foreach (WorkdayType item in Enum.GetValues(typeof(WorkdayType))) + { + listBox.Items.Add(new CheckedListBoxItem(null, item.ToString())); + } + Control = listBox; + } + + public override string GetValue() + { + var listBox = Control as CheckedListBoxControl; + string[] strs = new string[listBox.CheckedItems.Count]; + int i = 0; + foreach (var item in listBox.CheckedItems) + { + strs[i] = item.ToString(); + i++; + } + return string.Join(",", strs); + } + + public override void SetValue(object value) + { + var listBox = Control as CheckedListBoxControl; + var strs = value.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + foreach (var item in listBox.Items) + { + listBox.SetItemChecked(i, !string.IsNullOrEmpty(strs.FirstOrDefault(f => f == item.ToString()))); + i++; + } + } + + } +} diff --git a/应用/AutoAnswer/EditUserDefinedForm.Designer.cs b/应用/AutoAnswer/EditUserDefinedForm.Designer.cs new file mode 100644 index 0000000..738918c --- /dev/null +++ b/应用/AutoAnswer/EditUserDefinedForm.Designer.cs @@ -0,0 +1,293 @@ +namespace AutoAnswer +{ + partial class EditUserDefinedForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tBox_antistop = new DevExpress.XtraEditors.TextEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.checkedComboBoxEdit_ChatType = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); + this.label1 = new System.Windows.Forms.Label(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.cbox_alertAdmin = new DevExpress.XtraEditors.CheckEdit(); + this.hyperlinkLabelControl2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl4 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl5 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.checkedComboBoxEdit_Robot = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.tBox_antistop.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbox_alertAdmin.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_Robot.Properties)).BeginInit(); + this.SuspendLayout(); + // + // tBox_antistop + // + this.tBox_antistop.Location = new System.Drawing.Point(112, 27); + this.tBox_antistop.Name = "tBox_antistop"; + this.tBox_antistop.Size = new System.Drawing.Size(346, 20); + this.tBox_antistop.TabIndex = 0; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(46, 30); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(48, 14); + this.labelControl1.TabIndex = 1; + this.labelControl1.Text = "关键词:"; + // + // radioGroup1 + // + this.radioGroup1.Location = new System.Drawing.Point(112, 60); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.Columns = 2; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "全部匹配"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "模糊匹配(支持正则表达式)")}); + this.radioGroup1.Size = new System.Drawing.Size(346, 29); + this.radioGroup1.TabIndex = 2; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(46, 67); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(48, 14); + this.labelControl2.TabIndex = 3; + this.labelControl2.Text = "关键词:"; + // + // checkedComboBoxEdit_ChatType + // + this.checkedComboBoxEdit_ChatType.EditValue = ""; + this.checkedComboBoxEdit_ChatType.Location = new System.Drawing.Point(112, 104); + this.checkedComboBoxEdit_ChatType.Name = "checkedComboBoxEdit_ChatType"; + this.checkedComboBoxEdit_ChatType.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit_ChatType.Size = new System.Drawing.Size(303, 20); + this.checkedComboBoxEdit_ChatType.TabIndex = 5; + this.checkedComboBoxEdit_ChatType.Leave += new System.EventHandler(this.checkedComboBoxEdit_ChatType_Leave); + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(42, 107); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(52, 14); + this.labelControl3.TabIndex = 6; + this.labelControl3.Text = "回复平台:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(42, 212); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(52, 14); + this.labelControl4.TabIndex = 9; + this.labelControl4.Text = "回复内容:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(43, 507); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 12; + this.label1.Text = "快捷键:"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(30, 181); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(64, 14); + this.labelControl5.TabIndex = 13; + this.labelControl5.Text = "通知钉钉群:"; + // + // cbox_alertAdmin + // + this.cbox_alertAdmin.Location = new System.Drawing.Point(112, 178); + this.cbox_alertAdmin.Name = "cbox_alertAdmin"; + this.cbox_alertAdmin.Properties.Caption = "勾选通知"; + this.cbox_alertAdmin.Size = new System.Drawing.Size(75, 20); + this.cbox_alertAdmin.TabIndex = 14; + // + // hyperlinkLabelControl2 + // + this.hyperlinkLabelControl2.Location = new System.Drawing.Point(104, 507); + this.hyperlinkLabelControl2.Name = "hyperlinkLabelControl2"; + this.hyperlinkLabelControl2.Size = new System.Drawing.Size(46, 14); + this.hyperlinkLabelControl2.TabIndex = 23; + this.hyperlinkLabelControl2.Text = "[分割线]"; + this.hyperlinkLabelControl2.Click += new System.EventHandler(this.hyperlinkLabelControl2_Click); + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(42, 242); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(477, 252); + this.memoEdit1.TabIndex = 24; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(159, 507); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(82, 14); + this.hyperlinkLabelControl1.TabIndex = 23; + this.hyperlinkLabelControl1.Text = "[插入网络图片]"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl3 + // + this.hyperlinkLabelControl3.Location = new System.Drawing.Point(341, 507); + this.hyperlinkLabelControl3.Name = "hyperlinkLabelControl3"; + this.hyperlinkLabelControl3.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl3.TabIndex = 23; + this.hyperlinkLabelControl3.Text = "[插入视频]"; + this.hyperlinkLabelControl3.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl4 + // + this.hyperlinkLabelControl4.Location = new System.Drawing.Point(408, 507); + this.hyperlinkLabelControl4.Name = "hyperlinkLabelControl4"; + this.hyperlinkLabelControl4.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl4.TabIndex = 23; + this.hyperlinkLabelControl4.Text = "[插入语音]"; + this.hyperlinkLabelControl4.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl5 + // + this.hyperlinkLabelControl5.Location = new System.Drawing.Point(250, 507); + this.hyperlinkLabelControl5.Name = "hyperlinkLabelControl5"; + this.hyperlinkLabelControl5.Size = new System.Drawing.Size(82, 14); + this.hyperlinkLabelControl5.TabIndex = 23; + this.hyperlinkLabelControl5.Text = "[插入本地图片]"; + this.hyperlinkLabelControl5.Click += new System.EventHandler(this.hyperlinkLabelControl5_Click); + // + // checkedComboBoxEdit_Robot + // + this.checkedComboBoxEdit_Robot.EditValue = ""; + this.checkedComboBoxEdit_Robot.Location = new System.Drawing.Point(112, 140); + this.checkedComboBoxEdit_Robot.Name = "checkedComboBoxEdit_Robot"; + this.checkedComboBoxEdit_Robot.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit_Robot.Size = new System.Drawing.Size(303, 20); + this.checkedComboBoxEdit_Robot.TabIndex = 5; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(6, 143); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(100, 14); + this.labelControl6.TabIndex = 6; + this.labelControl6.Text = "指定回复的机器人:"; + // + // labelControl7 + // + this.labelControl7.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl7.Appearance.Options.UseForeColor = true; + this.labelControl7.Location = new System.Drawing.Point(421, 143); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(130, 14); + this.labelControl7.TabIndex = 25; + this.labelControl7.Text = "(为空时回复所有机器人)"; + // + // EditUserDefinedForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(562, 550); + this.Controls.Add(this.labelControl7); + this.Controls.Add(this.memoEdit1); + this.Controls.Add(this.hyperlinkLabelControl4); + this.Controls.Add(this.hyperlinkLabelControl3); + this.Controls.Add(this.hyperlinkLabelControl5); + this.Controls.Add(this.hyperlinkLabelControl1); + this.Controls.Add(this.hyperlinkLabelControl2); + this.Controls.Add(this.cbox_alertAdmin); + this.Controls.Add(this.labelControl5); + this.Controls.Add(this.label1); + this.Controls.Add(this.labelControl4); + this.Controls.Add(this.labelControl6); + this.Controls.Add(this.labelControl3); + this.Controls.Add(this.checkedComboBoxEdit_Robot); + this.Controls.Add(this.checkedComboBoxEdit_ChatType); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.radioGroup1); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.tBox_antistop); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.IconOptions.ShowIcon = false; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditUserDefinedForm"; + this.Text = "EditUserDefinedForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.EditUserDefinedForm_FormClosing); + this.Load += new System.EventHandler(this.EditUserDefinedForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.tBox_antistop.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.cbox_alertAdmin.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_Robot.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.TextEdit tBox_antistop; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit_ChatType; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.ComponentModel.BackgroundWorker backgroundWorker1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.CheckEdit cbox_alertAdmin; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl4; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl5; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit_Robot; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.LabelControl labelControl7; + } +} \ No newline at end of file diff --git a/应用/AutoAnswer/EditUserDefinedForm.cs b/应用/AutoAnswer/EditUserDefinedForm.cs new file mode 100644 index 0000000..5f8e1fd --- /dev/null +++ b/应用/AutoAnswer/EditUserDefinedForm.cs @@ -0,0 +1,231 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using AutoAnswer.Entitys; +using AutoAnswer.Properties; +using Chat.Framework; +using Chat.Framework.QQSdk; +using Chat.Framework.WXSdk.Implement; +using DevExpress.XtraEditors; +using Microsoft.JScript; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace AutoAnswer +{ + public partial class EditUserDefinedForm : BaseForm + { + private string _id { get; set; } + public EditUserDefinedForm(string id = "") + { + InitializeComponent(); + this.Text = string.IsNullOrEmpty(id) ? Resources.AddUserDefinedFormTitle : Resources.UpdateUserDefinedFormTitle; + this._id = id; + } + + private fl_plugin_autoanswer_definedlib userdefinedlibrary = null; + + /// + /// 窗体加载事件 + /// + /// + /// + private void EditUserDefinedForm_Load(object sender, EventArgs e) + { + #region 将enum的值加载到列表中 修改的将勾选 + if (!string.IsNullOrEmpty(_id)) + { + var session = ApiClient.GetSession(); + userdefinedlibrary = session.Find($"select * from fl_plugin_autoanswer_definedlib where id = '{_id}'").FirstOrDefault(); + if (userdefinedlibrary == null) throw new Exception("数据异常"); + var chatList = userdefinedlibrary.chat_type.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList(); + foreach (ChatType item in Enum.GetValues(typeof(ChatType))) + { + if (item == ChatType.未知来源 || item == ChatType.微信公众号) + continue; + if (chatList.FirstOrDefault(f => f == ((int)item).ToString()) != null) + checkedComboBoxEdit_ChatType.Properties.Items.Add(((int)item).ToString(), item.ToString(), CheckState.Checked, true); + else + checkedComboBoxEdit_ChatType.Properties.Items.Add(((int)item).ToString(), item.ToString(), CheckState.Unchecked, true); + } + + ViewRobot(userdefinedlibrary.specific_robot_setting_text); + + tBox_antistop.Text = GlobalObject.unescape(userdefinedlibrary.antistop); + radioGroup1.SelectedIndex = userdefinedlibrary.match_pattern; + cbox_alertAdmin.Checked = (userdefinedlibrary.is_alert_admin == 1); + memoEdit1.Text = GlobalObject.unescape(userdefinedlibrary.content); + } + else + { + foreach (ChatType item in Enum.GetValues(typeof(ChatType))) + { + if (item == ChatType.未知来源 || item == ChatType.微信公众号) + continue; + checkedComboBoxEdit_ChatType.Properties.Items.Add(((int)item).ToString(), item.ToString(), CheckState.Unchecked, true); + } + radioGroup1.SelectedIndex = 1; + } + #endregion + } + + private void checkedComboBoxEdit_ChatType_Leave(object sender, EventArgs e) + { + ViewRobot(userdefinedlibrary == null ? string.Empty : userdefinedlibrary.specific_robot_setting_text); + } + + private void ViewRobot(string specificRobotSetting = "") + { + try + { + checkedComboBoxEdit_Robot.Properties.Items.Clear(); + + var settingList = new List(); + if (!string.IsNullOrWhiteSpace(specificRobotSetting)) + settingList = specificRobotSetting.Split(new string[] { "[分割]" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + + //获取到勾选的平台名称数组 + var str_split = checkedComboBoxEdit_ChatType.Properties.GetCheckedItems().ToString().Replace("4", "2").Replace(", ", ",").Replace(" ,", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); + if (str_split.Count != 0) + { + foreach (var item in str_split) + { + switch ((ChatType)Enum.Parse(typeof(ChatType), item)) + { + case ChatType.QQ: + foreach (QQBase v in ChatClient.QQClients.Values) + { + CheckState check = settingList.Contains($"{(int)v.QQ}_QQ") ? CheckState.Checked : CheckState.Unchecked; + checkedComboBoxEdit_Robot.Properties.Items.Add($"{(int)v.QQ}_QQ", $"QQ:{v.Nickname}({v.QQ})", check, true); + } + break; + case ChatType.微信: + case ChatType.企业微信: + { + foreach (WeixinBase v in ChatClient.WXClient.Values) + { + CheckState check = settingList.Contains($"{v.WeixinHao}_微信") ? CheckState.Checked : CheckState.Unchecked; + checkedComboBoxEdit_Robot.Properties.Items.Add($"{v.WeixinHao}_微信", $"微信:{v.User.Nick}({v.WeixinHao})", check, true); + } + } + break; + case ChatType.微信公众号: + case ChatType.未知来源: + break; + default: + break; + } + } + } + else + { + + } + } + catch (Exception ex) + { } + } + + + /// + /// 关闭窗口时保存数据 + /// + /// + /// + private void EditUserDefinedForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(tBox_antistop.Text.Trim())) throw new Exception("关键词不能为空"); + if (string.IsNullOrWhiteSpace(memoEdit1.Text.Replace("-----------分割线-----------", ""))) throw new Exception("回复内容列表不能为空"); + if (string.IsNullOrEmpty(checkedComboBoxEdit_ChatType.EditValue.ToString()) && !cbox_alertAdmin.Checked) throw new Exception("请选择回复平台或通知管理员"); + //获取到勾选的平台名称数组 + if (userdefinedlibrary == null) + userdefinedlibrary = new fl_plugin_autoanswer_definedlib(); + userdefinedlibrary.antistop = GlobalObject.escape(tBox_antistop.Text.Trim()); + userdefinedlibrary.chat_type = checkedComboBoxEdit_ChatType.Properties.GetCheckedItems().ToString().Replace(", ", ",").Replace(" ,", ","); + + var CheckedRobots = checkedComboBoxEdit_Robot.Properties.GetCheckedItems().ToString().Replace(", ", ",").Replace(" ,", ","); + userdefinedlibrary.specific_robot_setting_text = CheckedRobots; + userdefinedlibrary.content = GlobalObject.escape(memoEdit1.Text.Trim()); + userdefinedlibrary.is_alert_admin = (cbox_alertAdmin.Checked ? 1 : 0); + userdefinedlibrary.match_pattern = radioGroup1.SelectedIndex; + var session = ApiClient.GetSession(); + session.Saveable(userdefinedlibrary).ExecuteCommand(); + } + catch (Exception ex) + { + if (XtraMessageBox.Show(ex.Message + " 是否关闭?", "操作失败", MessageBoxButtons.YesNo) == DialogResult.No) + e.Cancel = true; + } + } + + private void hyperlinkLabelControl2_Click(object sender, EventArgs e) + { + memoEdit1.Text = memoEdit1.Text.Insert(memoEdit1.SelectionStart, @" +-----------分割线----------- +"); + memoEdit1.SelectionStart = memoEdit1.SelectionStart; + } + + private void hyperlinkLabelControl5_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Multiselect = true;//等于true表示可以选择多个文件 + dlg.DefaultExt = ".jpg"; + dlg.Filter = "图片|*.jpg;*.png;*.gif;*.jpeg;*.bmp"; + if (dlg.ShowDialog() == DialogResult.OK) + { + StringBuilder strb = new StringBuilder(); + foreach (string file in dlg.FileNames) + { + strb.AppendLine($"[图片={file}]"); + } + memoEdit1.Text = memoEdit1.Text.Insert(memoEdit1.SelectionStart, strb.ToString().Trim()); + memoEdit1.SelectionStart = memoEdit1.SelectionStart; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + var label = sender as HyperlinkLabelControl; + var flag = label.Text.Substring(label.Text.Length - 3, 2); + CommonForm commonForm = new CommonForm(flag); + if (commonForm.ShowDialog() == DialogResult.OK) + { + if (!string.IsNullOrWhiteSpace(commonForm.Strs)) + { + var strs = commonForm.Strs.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + if (flag == "图片") + strs = strs.Select(f => $"[图片={f}]").ToList(); + else if (flag == "视频") + strs = strs.Select(f => $"[视频={f}]").ToList(); + else if (flag == "语音") + strs = strs.Select(f => $"[语音={f}]").ToList(); + memoEdit1.Text = memoEdit1.Text.Insert(memoEdit1.SelectionStart, string.Join("\r\n", strs).Trim()); + memoEdit1.SelectionStart = memoEdit1.SelectionStart; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + } +} diff --git a/应用/AutoAnswer/EditUserDefinedForm.resx b/应用/AutoAnswer/EditUserDefinedForm.resx new file mode 100644 index 0000000..b966dfd --- /dev/null +++ b/应用/AutoAnswer/EditUserDefinedForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/应用/AutoAnswer/Entitys/ShowTmp.cs b/应用/AutoAnswer/Entitys/ShowTmp.cs new file mode 100644 index 0000000..f1ed95e --- /dev/null +++ b/应用/AutoAnswer/Entitys/ShowTmp.cs @@ -0,0 +1,46 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AutoAnswer.Entitys +{ + public class ShowTmp + { + /// + /// id + /// + public long ID { get; set; } + + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + + /// + /// 用户账号 + /// + public string name { get; set; } + + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 填写转发到的账号 + /// + private string _username; + + public string username + { + get { return _username; } + set { _username = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + public string messtype { get; set; } + + } +} diff --git a/应用/AutoAnswer/Entitys/fl_plugin_autoanswer__log.cs b/应用/AutoAnswer/Entitys/fl_plugin_autoanswer__log.cs new file mode 100644 index 0000000..7600840 --- /dev/null +++ b/应用/AutoAnswer/Entitys/fl_plugin_autoanswer__log.cs @@ -0,0 +1,49 @@ +using Api.Framework.SDK; +using Api.Framework.Tools; +using Microsoft.JScript; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AutoAnswer.Entitys +{ + /// + /// 记录内容每日回复的内容 + /// + public class fl_plugin_autoanswer__log : base_model + { + /// + /// 记录发生时间 + /// + public DateTime datetime { get; set; } + /// + /// 机器人昵称 + /// + public string robot_name { get; set; } + /// + /// 用户账号 + /// + public string useraccount { get; set; } + /// + /// 用户名称 + /// + public string username { get; set; } + /// + /// 平台类型 + /// + public ChatType chatType { get; set; } + /// + /// 接收的内容 + /// + [SugarColumn(Length = 10000)] + public string content { get; set; } + /// + /// 记录这个关键词是已回复的,还是未回复的。true为已回复的,false为未回复的 + /// + public bool status { get; set; } + + } +} diff --git a/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_definedlib.cs b/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_definedlib.cs new file mode 100644 index 0000000..a3a843d --- /dev/null +++ b/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_definedlib.cs @@ -0,0 +1,52 @@ +using Api.Framework.SDK; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AutoAnswer.Entitys +{ + + /// + /// 用户自定义回复库 + /// + public class fl_plugin_autoanswer_definedlib : base_model + { + /// + /// 平台类型 + /// + public string chat_type { get; set; } + /// + /// 关键词 + /// + [SugarColumn(Length = 10000)]//设置字段为长文本 + public string antistop { get; set; } + /// + /// 匹配模式 0是为完全匹配,false为模糊 and 正则表达式 【这里用int类型,主要是因为dev中的Gridcontrol bool好像不支持 修改界面显示】 + /// + public int match_pattern { get; set; } + + /// + /// 指定回复的机器人信息,为空时所有机器人都使用 + /// + public string specific_robot_setting_text { get; set; } + /// + /// 回复内容 + /// + [SugarColumn(Length = 10000)]//设置字段为长文本 + public string content { get; set; } + /// + /// 是否通知管理员 【这里用int类型,主要是因为dev中的Gridcontrol bool好像不支持 修改界面显示】 + /// + public int is_alert_admin { get; set; } + + public bool CheckChatType(ChatType type) + { + return string.IsNullOrWhiteSpace(this.chat_type) ? false : this.chat_type.Split(',').FirstOrDefault(f => ushort.Parse(f) == (ushort)type) != null ? true : false; + } + + } +} diff --git a/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_unprocessed.cs b/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_unprocessed.cs new file mode 100644 index 0000000..ff758e3 --- /dev/null +++ b/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_unprocessed.cs @@ -0,0 +1,31 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AutoAnswer.Entitys +{ + /// + /// 未处理消息转发 + /// + public class fl_plugin_autoanswer_unprocessed : base_model + { + /// + /// 机器人id + /// + public int rid { get; set; } + + /// + /// 账号 + /// + public string username { get; set; } + + /// + /// 消息类型 + /// + public string messtype { get; set; } + + } +} diff --git a/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_userdefinedlibrary.cs b/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_userdefinedlibrary.cs new file mode 100644 index 0000000..d9b1fe1 --- /dev/null +++ b/应用/AutoAnswer/Entitys/fl_plugin_autoanswer_userdefinedlibrary.cs @@ -0,0 +1,47 @@ +using Api.Framework.SDK; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AutoAnswer.Entitys +{ + + /// + /// 用户自定义回复库 + /// + public class fl_plugin_autoanswer_userdefinedlibrary : base_model + { + /// + /// 平台类型 + /// + public string chat_type { get; set; } + /// + /// 关键词 + /// + public string antistop { get; set; } + /// + /// 匹配模式 0是为完全匹配,false为模糊 and 正则表达式 【这里用int类型,主要是因为dev中的Gridcontrol bool好像不支持 修改界面显示】 + /// + public int match_pattern { get; set; } + + /// + /// 回复内容 + /// + [SugarColumn(Length = 10000)]//设置字段为长文本 + public string content { get; set; } + /// + /// 是否通知管理员 【这里用int类型,主要是因为dev中的Gridcontrol bool好像不支持 修改界面显示】 + /// + public int is_alert_admin { get; set; } + + public bool CheckChatType(ChatType type) + { + return string.IsNullOrWhiteSpace(this.chat_type) ? false : this.chat_type.Split(',').FirstOrDefault(f => ushort.Parse(f) == (ushort)type) != null ? true : false; + } + + } +} diff --git a/应用/AutoAnswer/Enums.cs b/应用/AutoAnswer/Enums.cs new file mode 100644 index 0000000..256fa75 --- /dev/null +++ b/应用/AutoAnswer/Enums.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AutoAnswer +{ + public class Enums + { + public enum ReplyModel + { + 传递最近5条消息 = 1, + 传递当前消息 = 2 + } + + } +} diff --git a/应用/AutoAnswer/LogClearThread.cs b/应用/AutoAnswer/LogClearThread.cs new file mode 100644 index 0000000..3a45a74 --- /dev/null +++ b/应用/AutoAnswer/LogClearThread.cs @@ -0,0 +1,23 @@ +using Api.Framework; +using Api.Framework.SDK; +using System; + +namespace AutoAnswer +{ + class LogClearThread : TimerTask + { + public override void Run(object state, bool timedOut) + { + try + { + if (Class1.Config.Is_AutoClear_Start) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL($"delete from fl_plugin_autoanswer_log where datetime <= '{DateTime.Now.AddDays(-Class1.Config.Logs_Keep_Days).ToString("yyyy-MM-dd HH:mm:ss")}'"); + } + } + catch + {} + } + } +} diff --git a/应用/AutoAnswer/MainForm.Designer.cs b/应用/AutoAnswer/MainForm.Designer.cs new file mode 100644 index 0000000..9b05562 --- /dev/null +++ b/应用/AutoAnswer/MainForm.Designer.cs @@ -0,0 +1,1021 @@ +namespace AutoAnswer +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.label5 = new System.Windows.Forms.Label(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.hyperlinkLabelControl3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.checkBox = new DevExpress.XtraEditors.CheckEdit(); + this.barManager2 = new DevExpress.XtraBars.BarManager(this.components); + this.barDockControl1 = new DevExpress.XtraBars.BarDockControl(); + this.barDockControl2 = new DevExpress.XtraBars.BarDockControl(); + this.barDockControl3 = new DevExpress.XtraBars.BarDockControl(); + this.barDockControl4 = new DevExpress.XtraBars.BarDockControl(); + this.barButtonItem1 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem2 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem3 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem4 = new DevExpress.XtraBars.BarButtonItem(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown_days = new System.Windows.Forms.NumericUpDown(); + this.tBox_userInfo = new System.Windows.Forms.TextBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.cbx_chattype = new System.Windows.Forms.ComboBox(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.label3 = new System.Windows.Forms.Label(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.tbx_TuLing_apikey = new DevExpress.XtraEditors.TextEdit(); + this.tbx_TuLing_prefix = new DevExpress.XtraEditors.TextEdit(); + this.bck_TuLing_onoff = new UI.Framework.Controls.ButtonCheck(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.dropDownButton1 = new DevExpress.XtraEditors.DropDownButton(); + this.label6 = new System.Windows.Forms.Label(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.hyperlinkLabelControl4 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl5 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl6 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl7 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.label4 = new System.Windows.Forms.Label(); + this.hyperlinkLabelControl2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.label7 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.bck_acquiescent_Auto_Answer_onoff = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.label2 = new System.Windows.Forms.Label(); + this.xtraTabPage5 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage6 = new DevExpress.XtraTab.XtraTabPage(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemComboBox1 = new DevExpress.XtraEditors.Repository.RepositoryItemComboBox(); + this.repositoryItemPopupContainerEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPopupContainerEdit(); + this.popupMenu1 = new DevExpress.XtraBars.PopupMenu(this.components); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkBox.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.barManager2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown_days)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbx_TuLing_apikey.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.tbx_TuLing_prefix.Properties)).BeginInit(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.xtraTabPage5.SuspendLayout(); + this.xtraTabPage6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemComboBox1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPopupContainerEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.popupMenu1)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + resources.ApplyResources(this.xtraTabControl1, "xtraTabControl1"); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage4; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage4, + this.xtraTabPage3, + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage5, + this.xtraTabPage6}); + this.xtraTabControl1.Selected += new DevExpress.XtraTab.TabPageEventHandler(this.xtraTabControl1_Selected); + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.label5); + this.xtraTabPage4.Controls.Add(this.labelControl4); + this.xtraTabPage4.Controls.Add(this.hyperlinkLabelControl3); + this.xtraTabPage4.Controls.Add(this.simpleButton2); + this.xtraTabPage4.Controls.Add(this.labelControl7); + this.xtraTabPage4.Controls.Add(this.checkBox); + this.xtraTabPage4.Controls.Add(this.labelControl6); + this.xtraTabPage4.Controls.Add(this.numericUpDown_days); + this.xtraTabPage4.Controls.Add(this.tBox_userInfo); + this.xtraTabPage4.Controls.Add(this.labelControl5); + this.xtraTabPage4.Controls.Add(this.cbx_chattype); + this.xtraTabPage4.Controls.Add(this.gridControl2); + this.xtraTabPage4.Controls.Add(this.pageControl2); + this.xtraTabPage4.Name = "xtraTabPage4"; + resources.ApplyResources(this.xtraTabPage4, "xtraTabPage4"); + // + // label5 + // + resources.ApplyResources(this.label5, "label5"); + this.label5.BackColor = System.Drawing.Color.White; + this.label5.Name = "label5"; + // + // labelControl4 + // + this.labelControl4.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl4.Appearance.Options.UseForeColor = true; + resources.ApplyResources(this.labelControl4, "labelControl4"); + this.labelControl4.Name = "labelControl4"; + // + // hyperlinkLabelControl3 + // + resources.ApplyResources(this.hyperlinkLabelControl3, "hyperlinkLabelControl3"); + this.hyperlinkLabelControl3.Name = "hyperlinkLabelControl3"; + this.hyperlinkLabelControl3.Click += new System.EventHandler(this.hyperlinkLabelControl3_Click); + // + // simpleButton2 + // + resources.ApplyResources(this.simpleButton2, "simpleButton2"); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // labelControl7 + // + resources.ApplyResources(this.labelControl7, "labelControl7"); + this.labelControl7.Name = "labelControl7"; + // + // checkBox + // + resources.ApplyResources(this.checkBox, "checkBox"); + this.checkBox.MenuManager = this.barManager2; + this.checkBox.Name = "checkBox"; + this.checkBox.Properties.Caption = resources.GetString("checkBox.Properties.Caption"); + // + // barManager2 + // + this.barManager2.DockControls.Add(this.barDockControl1); + this.barManager2.DockControls.Add(this.barDockControl2); + this.barManager2.DockControls.Add(this.barDockControl3); + this.barManager2.DockControls.Add(this.barDockControl4); + this.barManager2.Form = this; + this.barManager2.Items.AddRange(new DevExpress.XtraBars.BarItem[] { + this.barButtonItem1, + this.barButtonItem2, + this.barButtonItem3, + this.barButtonItem4}); + this.barManager2.MaxItemId = 4; + // + // barDockControl1 + // + this.barDockControl1.CausesValidation = false; + resources.ApplyResources(this.barDockControl1, "barDockControl1"); + this.barDockControl1.Manager = this.barManager2; + // + // barDockControl2 + // + this.barDockControl2.CausesValidation = false; + resources.ApplyResources(this.barDockControl2, "barDockControl2"); + this.barDockControl2.Manager = this.barManager2; + // + // barDockControl3 + // + this.barDockControl3.CausesValidation = false; + resources.ApplyResources(this.barDockControl3, "barDockControl3"); + this.barDockControl3.Manager = this.barManager2; + // + // barDockControl4 + // + this.barDockControl4.CausesValidation = false; + resources.ApplyResources(this.barDockControl4, "barDockControl4"); + this.barDockControl4.Manager = this.barManager2; + // + // barButtonItem1 + // + resources.ApplyResources(this.barButtonItem1, "barButtonItem1"); + this.barButtonItem1.Id = 0; + this.barButtonItem1.Name = "barButtonItem1"; + this.barButtonItem1.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem2_ItemClick); + // + // barButtonItem2 + // + resources.ApplyResources(this.barButtonItem2, "barButtonItem2"); + this.barButtonItem2.Id = 1; + this.barButtonItem2.Name = "barButtonItem2"; + this.barButtonItem2.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem2_ItemClick); + // + // barButtonItem3 + // + resources.ApplyResources(this.barButtonItem3, "barButtonItem3"); + this.barButtonItem3.Id = 2; + this.barButtonItem3.Name = "barButtonItem3"; + this.barButtonItem3.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem2_ItemClick); + // + // barButtonItem4 + // + resources.ApplyResources(this.barButtonItem4, "barButtonItem4"); + this.barButtonItem4.Id = 3; + this.barButtonItem4.Name = "barButtonItem4"; + this.barButtonItem4.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem2_ItemClick); + // + // labelControl6 + // + resources.ApplyResources(this.labelControl6, "labelControl6"); + this.labelControl6.Name = "labelControl6"; + // + // numericUpDown_days + // + resources.ApplyResources(this.numericUpDown_days, "numericUpDown_days"); + this.numericUpDown_days.Maximum = new decimal(new int[] { + 3650, + 0, + 0, + 0}); + this.numericUpDown_days.Name = "numericUpDown_days"; + this.numericUpDown_days.Value = new decimal(new int[] { + 7, + 0, + 0, + 0}); + // + // tBox_userInfo + // + resources.ApplyResources(this.tBox_userInfo, "tBox_userInfo"); + this.tBox_userInfo.Name = "tBox_userInfo"; + // + // labelControl5 + // + resources.ApplyResources(this.labelControl5, "labelControl5"); + this.labelControl5.Name = "labelControl5"; + // + // cbx_chattype + // + this.cbx_chattype.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cbx_chattype.FormattingEnabled = true; + resources.ApplyResources(this.cbx_chattype, "cbx_chattype"); + this.cbx_chattype.Name = "cbx_chattype"; + // + // gridControl2 + // + resources.ApplyResources(this.gridControl2, "gridControl2"); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.MenuManager = this.barManager2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn8, + this.gridColumn14, + this.gridColumn9, + this.gridColumn10, + this.gridColumn11, + this.gridColumn12}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn8.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn8, "gridColumn8"); + this.gridColumn8.FieldName = "chatType"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn14.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn14, "gridColumn14"); + this.gridColumn14.FieldName = "robot_name"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.ReadOnly = true; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn9.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn9, "gridColumn9"); + this.gridColumn9.FieldName = "useraccount"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.ReadOnly = true; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn10.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn10, "gridColumn10"); + this.gridColumn10.FieldName = "username"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.ReadOnly = true; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn11.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn11, "gridColumn11"); + this.gridColumn11.FieldName = "content"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.ReadOnly = true; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn12.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn12, "gridColumn12"); + this.gridColumn12.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn12.FieldName = "datetime"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + // + // pageControl2 + // + resources.ApplyResources(this.pageControl2, "pageControl2"); + this.pageControl2.Name = "pageControl2"; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + resources.ApplyResources(this.xtraTabPage3, "xtraTabPage3"); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.label3); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.hyperlinkLabelControl1); + this.groupControl1.Controls.Add(this.tbx_TuLing_apikey); + this.groupControl1.Controls.Add(this.tbx_TuLing_prefix); + this.groupControl1.Controls.Add(this.bck_TuLing_onoff); + this.groupControl1.Controls.Add(this.labelControl3); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + resources.ApplyResources(this.groupControl1, "groupControl1"); + this.groupControl1.Name = "groupControl1"; + // + // label3 + // + resources.ApplyResources(this.label3, "label3"); + this.label3.ForeColor = System.Drawing.Color.Gray; + this.label3.Name = "label3"; + // + // simpleButton1 + // + resources.ApplyResources(this.simpleButton1, "simpleButton1"); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // hyperlinkLabelControl1 + // + resources.ApplyResources(this.hyperlinkLabelControl1, "hyperlinkLabelControl1"); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // tbx_TuLing_apikey + // + resources.ApplyResources(this.tbx_TuLing_apikey, "tbx_TuLing_apikey"); + this.tbx_TuLing_apikey.MenuManager = this.barManager2; + this.tbx_TuLing_apikey.Name = "tbx_TuLing_apikey"; + // + // tbx_TuLing_prefix + // + resources.ApplyResources(this.tbx_TuLing_prefix, "tbx_TuLing_prefix"); + this.tbx_TuLing_prefix.MenuManager = this.barManager2; + this.tbx_TuLing_prefix.Name = "tbx_TuLing_prefix"; + // + // bck_TuLing_onoff + // + this.bck_TuLing_onoff.BackColor = System.Drawing.Color.Transparent; + this.bck_TuLing_onoff.Checked = false; + this.bck_TuLing_onoff.CheckStyleX = UI.Framework.Controls.CheckStyle.style4; + this.bck_TuLing_onoff.Cursor = System.Windows.Forms.Cursors.Hand; + resources.ApplyResources(this.bck_TuLing_onoff, "bck_TuLing_onoff"); + this.bck_TuLing_onoff.Name = "bck_TuLing_onoff"; + // + // labelControl3 + // + resources.ApplyResources(this.labelControl3, "labelControl3"); + this.labelControl3.Name = "labelControl3"; + // + // labelControl2 + // + resources.ApplyResources(this.labelControl2, "labelControl2"); + this.labelControl2.Name = "labelControl2"; + // + // labelControl1 + // + resources.ApplyResources(this.labelControl1, "labelControl1"); + this.labelControl1.Name = "labelControl1"; + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.dropDownButton1); + this.xtraTabPage1.Controls.Add(this.label6); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + resources.ApplyResources(this.xtraTabPage1, "xtraTabPage1"); + // + // dropDownButton1 + // + this.dropDownButton1.DropDownArrowStyle = DevExpress.XtraEditors.DropDownArrowStyle.Show; + resources.ApplyResources(this.dropDownButton1, "dropDownButton1"); + this.dropDownButton1.MenuManager = this.barManager2; + this.dropDownButton1.Name = "dropDownButton1"; + // + // label6 + // + resources.ApplyResources(this.label6, "label6"); + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Name = "label6"; + // + // gridControl1 + // + resources.ApplyResources(this.gridControl1, "gridControl1"); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.MenuManager = this.barManager2; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4, + this.gridColumn13, + this.gridColumn5, + this.gridColumn7, + this.gridColumn6}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + this.gridView1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.gridView1_MouseUp); + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn1, "gridColumn1"); + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn2, "gridColumn2"); + this.gridColumn2.FieldName = "match_pattern"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.UnboundType = DevExpress.Data.UnboundColumnType.String; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn3, "gridColumn3"); + this.gridColumn3.FieldName = "antistop"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn4, "gridColumn4"); + this.gridColumn4.FieldName = "content"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn13, "gridColumn13"); + this.gridColumn13.FieldName = "is_alert_admin"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn5.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn5, "gridColumn5"); + this.gridColumn5.FieldName = "chat_type"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn7.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn7, "gridColumn7"); + this.gridColumn7.FieldName = "chat_type"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn6.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn6, "gridColumn6"); + this.gridColumn6.FieldName = "chat_type"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + // + // pageControl1 + // + resources.ApplyResources(this.pageControl1, "pageControl1"); + this.pageControl1.Name = "pageControl1"; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.panelControl1); + this.xtraTabPage2.Controls.Add(this.memoEdit1); + this.xtraTabPage2.Controls.Add(this.label2); + this.xtraTabPage2.Name = "xtraTabPage2"; + resources.ApplyResources(this.xtraTabPage2, "xtraTabPage2"); + // + // panelControl1 + // + this.panelControl1.Controls.Add(this.buttonCheck1); + this.panelControl1.Controls.Add(this.hyperlinkLabelControl4); + this.panelControl1.Controls.Add(this.hyperlinkLabelControl5); + this.panelControl1.Controls.Add(this.hyperlinkLabelControl6); + this.panelControl1.Controls.Add(this.hyperlinkLabelControl7); + this.panelControl1.Controls.Add(this.label4); + this.panelControl1.Controls.Add(this.hyperlinkLabelControl2); + this.panelControl1.Controls.Add(this.label7); + this.panelControl1.Controls.Add(this.label1); + this.panelControl1.Controls.Add(this.bck_acquiescent_Auto_Answer_onoff); + resources.ApplyResources(this.panelControl1, "panelControl1"); + this.panelControl1.Name = "panelControl1"; + // + // buttonCheck1 + // + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = false; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style4; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + resources.ApplyResources(this.buttonCheck1, "buttonCheck1"); + this.buttonCheck1.Name = "buttonCheck1"; + // + // hyperlinkLabelControl4 + // + resources.ApplyResources(this.hyperlinkLabelControl4, "hyperlinkLabelControl4"); + this.hyperlinkLabelControl4.Name = "hyperlinkLabelControl4"; + this.hyperlinkLabelControl4.Click += new System.EventHandler(this.hyperlinkLabelControl7_Click); + // + // hyperlinkLabelControl5 + // + resources.ApplyResources(this.hyperlinkLabelControl5, "hyperlinkLabelControl5"); + this.hyperlinkLabelControl5.Name = "hyperlinkLabelControl5"; + this.hyperlinkLabelControl5.Click += new System.EventHandler(this.hyperlinkLabelControl7_Click); + // + // hyperlinkLabelControl6 + // + resources.ApplyResources(this.hyperlinkLabelControl6, "hyperlinkLabelControl6"); + this.hyperlinkLabelControl6.Name = "hyperlinkLabelControl6"; + this.hyperlinkLabelControl6.Click += new System.EventHandler(this.hyperlinkLabelControl6_Click); + // + // hyperlinkLabelControl7 + // + resources.ApplyResources(this.hyperlinkLabelControl7, "hyperlinkLabelControl7"); + this.hyperlinkLabelControl7.Name = "hyperlinkLabelControl7"; + this.hyperlinkLabelControl7.Click += new System.EventHandler(this.hyperlinkLabelControl7_Click); + // + // label4 + // + resources.ApplyResources(this.label4, "label4"); + this.label4.BackColor = System.Drawing.Color.Transparent; + this.label4.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.label4.Name = "label4"; + // + // hyperlinkLabelControl2 + // + this.hyperlinkLabelControl2.Appearance.BackColor = System.Drawing.Color.Transparent; + this.hyperlinkLabelControl2.Appearance.Options.UseBackColor = true; + resources.ApplyResources(this.hyperlinkLabelControl2, "hyperlinkLabelControl2"); + this.hyperlinkLabelControl2.Name = "hyperlinkLabelControl2"; + this.hyperlinkLabelControl2.Click += new System.EventHandler(this.hyperlinkLabelControl2_Click); + // + // label7 + // + resources.ApplyResources(this.label7, "label7"); + this.label7.BackColor = System.Drawing.Color.Transparent; + this.label7.Name = "label7"; + // + // label1 + // + resources.ApplyResources(this.label1, "label1"); + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Name = "label1"; + // + // bck_acquiescent_Auto_Answer_onoff + // + this.bck_acquiescent_Auto_Answer_onoff.BackColor = System.Drawing.Color.Transparent; + this.bck_acquiescent_Auto_Answer_onoff.Checked = false; + this.bck_acquiescent_Auto_Answer_onoff.CheckStyleX = UI.Framework.Controls.CheckStyle.style4; + this.bck_acquiescent_Auto_Answer_onoff.Cursor = System.Windows.Forms.Cursors.Hand; + resources.ApplyResources(this.bck_acquiescent_Auto_Answer_onoff, "bck_acquiescent_Auto_Answer_onoff"); + this.bck_acquiescent_Auto_Answer_onoff.Name = "bck_acquiescent_Auto_Answer_onoff"; + this.bck_acquiescent_Auto_Answer_onoff.Click += new System.EventHandler(this.bck_acquiescent_Auto_Answer_onoff_Click); + // + // memoEdit1 + // + resources.ApplyResources(this.memoEdit1, "memoEdit1"); + this.memoEdit1.MenuManager = this.barManager2; + this.memoEdit1.Name = "memoEdit1"; + // + // label2 + // + this.label2.ForeColor = System.Drawing.Color.Gray; + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // xtraTabPage5 + // + this.xtraTabPage5.Controls.Add(this.settingControl1); + this.xtraTabPage5.Name = "xtraTabPage5"; + resources.ApplyResources(this.xtraTabPage5, "xtraTabPage5"); + // + // settingControl1 + // + resources.ApplyResources(this.settingControl1, "settingControl1"); + this.settingControl1.Name = "settingControl1"; + // + // xtraTabPage6 + // + this.xtraTabPage6.Controls.Add(this.gridControl3); + this.xtraTabPage6.Name = "xtraTabPage6"; + resources.ApplyResources(this.xtraTabPage6, "xtraTabPage6"); + // + // gridControl3 + // + resources.ApplyResources(this.gridControl3, "gridControl3"); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemComboBox1, + this.repositoryItemPopupContainerEdit1}); + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // gridView3 + // + this.gridView3.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView3.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn16, + this.gridColumn17, + this.gridColumn18, + this.gridColumn19, + this.gridColumn20}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsPrint.PrintVertLines = false; + this.gridView3.OptionsView.ShowGroupPanel = false; + this.gridView3.CellValueChanging += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(this.gridView3_CellValueChanging); + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn15, "gridColumn15"); + this.gridColumn15.FieldName = "ID"; + this.gridColumn15.Name = "gridColumn15"; + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn16, "gridColumn16"); + this.gridColumn16.FieldName = "chattype"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.OptionsColumn.AllowEdit = false; + this.gridColumn16.OptionsColumn.AllowFocus = false; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn17, "gridColumn17"); + this.gridColumn17.FieldName = "name"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.OptionsColumn.AllowFocus = false; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn18, "gridColumn18"); + this.gridColumn18.FieldName = "nick"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.OptionsColumn.AllowEdit = false; + this.gridColumn18.OptionsColumn.AllowFocus = false; + // + // gridColumn19 + // + this.gridColumn19.AppearanceCell.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this.gridColumn19.AppearanceCell.BackColor2 = ((System.Drawing.Color)(resources.GetObject("gridColumn19.AppearanceCell.BackColor2"))); + this.gridColumn19.AppearanceCell.Font = ((System.Drawing.Font)(resources.GetObject("gridColumn19.AppearanceCell.Font"))); + this.gridColumn19.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn19.AppearanceCell.Options.UseBackColor = true; + this.gridColumn19.AppearanceCell.Options.UseFont = true; + this.gridColumn19.AppearanceCell.Options.UseForeColor = true; + this.gridColumn19.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn19.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn19, "gridColumn19"); + this.gridColumn19.FieldName = "username"; + this.gridColumn19.Name = "gridColumn19"; + // + // gridColumn20 + // + this.gridColumn20.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn20.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + resources.ApplyResources(this.gridColumn20, "gridColumn20"); + this.gridColumn20.ColumnEdit = this.repositoryItemComboBox1; + this.gridColumn20.FieldName = "messtype"; + this.gridColumn20.Name = "gridColumn20"; + // + // repositoryItemComboBox1 + // + this.repositoryItemComboBox1.AllowDropDownWhenReadOnly = DevExpress.Utils.DefaultBoolean.True; + this.repositoryItemComboBox1.AllowFocused = false; + this.repositoryItemComboBox1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("repositoryItemComboBox1.Buttons"))))}); + this.repositoryItemComboBox1.Items.AddRange(new object[] { + resources.GetString("repositoryItemComboBox1.Items"), + resources.GetString("repositoryItemComboBox1.Items1"), + resources.GetString("repositoryItemComboBox1.Items2")}); + this.repositoryItemComboBox1.Name = "repositoryItemComboBox1"; + resources.ApplyResources(this.repositoryItemComboBox1, "repositoryItemComboBox1"); + this.repositoryItemComboBox1.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + // + // repositoryItemPopupContainerEdit1 + // + resources.ApplyResources(this.repositoryItemPopupContainerEdit1, "repositoryItemPopupContainerEdit1"); + this.repositoryItemPopupContainerEdit1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(((DevExpress.XtraEditors.Controls.ButtonPredefines)(resources.GetObject("repositoryItemPopupContainerEdit1.Buttons"))))}); + this.repositoryItemPopupContainerEdit1.Name = "repositoryItemPopupContainerEdit1"; + // + // popupMenu1 + // + this.popupMenu1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem3), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem4)}); + this.popupMenu1.Manager = this.barManager2; + this.popupMenu1.Name = "popupMenu1"; + // + // MainForm + // + this.Appearance.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(235)))), ((int)(((byte)(236)))), ((int)(((byte)(239))))); + this.Appearance.Options.UseBackColor = true; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.xtraTabControl1); + this.Controls.Add(this.barDockControl3); + this.Controls.Add(this.barDockControl4); + this.Controls.Add(this.barDockControl2); + this.Controls.Add(this.barDockControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage4.ResumeLayout(false); + this.xtraTabPage4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkBox.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.barManager2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown_days)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tbx_TuLing_apikey.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.tbx_TuLing_prefix.Properties)).EndInit(); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + this.panelControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.xtraTabPage5.ResumeLayout(false); + this.xtraTabPage6.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemComboBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPopupContainerEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.popupMenu1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraBars.PopupMenu popupMenu1; + private DevExpress.XtraBars.BarButtonItem barButtonItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem2; + private DevExpress.XtraBars.BarButtonItem barButtonItem3; + private DevExpress.XtraBars.BarManager barManager2; + private DevExpress.XtraBars.BarDockControl barDockControl1; + private DevExpress.XtraBars.BarDockControl barDockControl2; + private DevExpress.XtraBars.BarDockControl barDockControl3; + private DevExpress.XtraBars.BarDockControl barDockControl4; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.TextEdit tbx_TuLing_apikey; + private DevExpress.XtraEditors.TextEdit tbx_TuLing_prefix; + private UI.Framework.Controls.ButtonCheck bck_TuLing_onoff; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private UI.Framework.Controls.ButtonCheck bck_acquiescent_Auto_Answer_onoff; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private System.Windows.Forms.ComboBox cbx_chattype; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraEditors.LabelControl labelControl6; + private System.Windows.Forms.NumericUpDown numericUpDown_days; + private System.Windows.Forms.TextBox tBox_userInfo; + private DevExpress.XtraEditors.CheckEdit checkBox; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.Label label4; + private DevExpress.XtraEditors.PanelControl panelControl1; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private DevExpress.XtraTab.XtraTabPage xtraTabPage5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl4; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl5; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl6; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl7; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraEditors.DropDownButton dropDownButton1; + private DevExpress.XtraBars.BarButtonItem barButtonItem4; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private System.Windows.Forms.Label label7; + private DevExpress.XtraTab.XtraTabPage xtraTabPage6; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraEditors.Repository.RepositoryItemComboBox repositoryItemComboBox1; + private DevExpress.XtraEditors.Repository.RepositoryItemPopupContainerEdit repositoryItemPopupContainerEdit1; + } +} \ No newline at end of file diff --git a/应用/AutoAnswer/MainForm.byn-ER.resx b/应用/AutoAnswer/MainForm.byn-ER.resx new file mode 100644 index 0000000..6e73b1c --- /dev/null +++ b/应用/AutoAnswer/MainForm.byn-ER.resx @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAadEVYdFRpdGxlAEVkaXRDb21tZW50O0NvbW1lbnQ7 + y3KOzAAAAxVJREFUOE+Vk3tMjWEcxx8lVEeSttPMdrTlUjKXIZeNVW4VUZoJRVaUKMmhluJUhOOWsTal + i3WR0lBL5Sidbpy2JFmhc5JDK+mmzum0dXz93pM2MX94ts/evc/zfL7v83vf38toTCQm/cHkf2BATADA + xmB1Kd7lr9N8wFGfun+UFI59eMWR7I06jjveqE3cI+VCxgXUJuyEdrgTWk0HtEPtxBeMqD9Dq1ZiRNVG + tGJkUEG0oCbenQw2ZVzAi5seGPneCE17PjRfHkKjfEDcx1BbFtStGVArUqGSJ9NaPiqvbOMCDGU317LK + S6uZ5Mxyxqqvu2G4sxQDb85D/T4Bqg+JUMtTMEjXweYbNH8B/bVhULXcRn3mKS7AaEwuEC5mTHrZVZfe + LxOi7+UJ9L48jt6aY+ipDkZP1RH0VAaipyIA6o85UEjT8TTWLpZkFAgXReUE2DBWFudMi9norTpKGwPR + LQ0gDqG73A/dz33xrewA+uvioOmQoj4jGC2PPKD9oUBj5jYk77KMYk9jNkL1LgndpbT5mQ++SfajS+KN + rhIvfC3Zgz5ZNB0/F4qiCLzPc9PJGnkQpBG2EK+3ACuKcqQ6r6GvNpJKiKCn+lMJJwkhBhpvYehTERSF + 4Wi676qTBxv9USqcj1LxOkSuMBOxGx5zy+K3CnB9i4BKOEbHD0Je+Dpkn/RAdfpVVCX44m2Gi07ulflA + EmyF4pg1CF9qKgqxnkrvlL4rwU/3X0YBIcgVrsS+ebx4mjMribE715CySSd3lnmiONAS+RErELrQRET3 + zE9gyJh4w0wuxCTtwGLknFgFrzk62Tj84O5FFeLNOllZ4IYn/gLkhS5BsDVPxDWQssCdefKp6y848rkA + XpKXLfZaGXMyj9Cz2xoT9fh2HFTKFyg8KMC9wAU4bGUkkmc5MXmWM+HEdszgfo3RoU8YE1w5epKzy9ky + p9MNDTXFuHsxDNH2VvCbbShqSrRnTYkOv7Bnrqak/d7XHJwsdjRj02c5YJrFqmae+RKRLd/cZhffgG03 + 02cuJqM4T9VjTsRfAf8H2E/rLE5y9F1HmgAAAABJRU5ErkJggg== + + + + + -1 + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAadEVYdFRpdGxlAEVkaXRDb21tZW50O0NvbW1lbnQ7 + y3KOzAAACLFJREFUWEfFl3lUVdcVhy+ttQnOICJilcSgOLGKWrNal01qSuKYiHYBDtShqCAzSEFBRFSi + 4gCIojiAYFNRcEIGJyZBRFHmeVBBBUV4TDJV8+ve576HYNOV5o+2Z61v7cu75+1vn3PPOe8iAfi/8oMf + /i/p3dSU/Oy/BOfuae8XwDd/TvyC+CXxwX/Ihz+CujJyzn4EFyJa7wKEPOvcxi/LY52zKhNcUBXvgkol + FbGMMyquOgnKOcY4ovyKI8quOFC0R9llJZfsUXrJDqUXbFEisEFJtA3yI60eJIesmkseHqCYifcL6F8Z + 61T3ujYD33c9JWrwfWdvqpU8Ebzt4bGSR0SVTIfMm3amkihHS/UtFEVueEEeng0xC70L4A8+LIu2oi9W + ovtlFLprI9AlCJfj89N9eRqGrmfE01BBJ1PD8RRxkq6VVBNPTqC7IRH5py3YNoDgR92nAP5APT9sBd62 + lyglKoEs6SOoYXpJSCBzHB2CEJnHx3rofhGPrMNL2TZQ6evTRAHZIaZ405KvFBDVlJRHUCMnZ4kQPGbJ + u+SCR0fRUcUcIYLRXnlESRDaK4LQ8fQCMv0XcQGDiH5Vm9ZLKrhxAQMeHF2KbsUD+tJhStprBJxcECwk + InHVYdFPllAkyWum/JBMWYBMaQDaCv2o/xmUxe7jAoYS/QmxLYvtVlNQFpAVZELPKlN8oa14v0gqS1QC + Th74jjJGlrwu9cfrkoNoKz1I8QCxH21F+9CSswvND7ajszYVDVXZSFphsvvhGjNkrjbdTs6ebckFDMwM + XIyul2loyfNFS64vmim2FvlRMn9KrBQIDogC25SSNuojs1emYA+Jd6Apaxua729FW0UUOpurUXR0H8q8 + nfCmrgLFrutxY8n8HeTlbSkKGJRxYCG66lLQnO2D5odE9naKxANvkbA1dxda875Fa/5ukuxFK4n4ujVv + F93fiRbuS8Lme1vQlLkFirub0VYeidf1JUgK/w4F7jZ4U1uOxjA/tCZH4bbZ14j+4rOdXABPxaA7++bT + 6r+BZqq86b6XTNZWip6U2JOSeqDpHkHJBXeZzYS7iIoMNzQxd/6KxjtuNGtn0fayGGERMdgdfBO1je1o + CPXDE9e1qA0/ipxdHjgyaYLYh1zA4LQ9c2m1xskikZxFlFglyWDcoCABS3piuiuxCU3pLlCkuaDxtgta + is+gta4Q18+HwOtgLKqbuhF39xHSg0NQE/AtzhlOxgl9fXjr6u5RFTAk1dcYHdUxInHf5L0ggUqiuO1M + 0RmKVCe6dqRrIsUBzYURaKnNR2nsTjy+uhpdHbW4fLscoTHZSEgvh98CcxzW+whOGpp+5OWDSS4g2eeP + tO0ukICSMkLgJFCkUnJCkeogJAqCY2OKnUyyHRqS7NBUEIqmZ7kojvFB1SULOrar0FG0BenX/BGTUoJl + NsfwB5PtmD1y6n5y8qEkFiEXMDTR+3PacpFKib1SQJGSy9iSxBaNAhuZxI2ChlvWaMo7icaabBRc2oaK + 6OV0qlagPZseTfJCNOZ4w8PNHb+bvxmaYxccIN9gQnUeyAXc9Pw97euI9wQ2JCVBojVdEzet0NDDBmI9 + 6m+sgyL3OBqqHyIv2gtlZ03xtq0U7YV7oLjxFV7d90DK1kmIdzKA8bSpB8k1hBDymUPHU1Buw4TNs2qf + XOe9u1Pm3g4hUMGPpDmTdshdLzQzd7zQmE4LtvgsXtXkIifKCyURS+g4L6IFuRH1V+bgFe2GZLfxuGqj + j/3zdPzJM4zgdwNxEqprGVOQ//jgoOl4s9MrJryMWDEB4QSLGq5Z4tW1v9D0O9Ci9ECCz2KEmesjzEwf + oaaf4FaAM0rv3kD6cWcUh36DN035UCRaov78LLxMdcZNp3G4uP5j7DbWDiSHBnuUPrVVLmGSutYXdCm/ + D/As8G81dxp72XY6HTz+eJWwhqaeFleaO+K9v4bDb/Q40ShCWxn1T1hODC4IWYh/NGZTwavx4m8zUZdo + j2s2eoheo4ddnw8/RP00iR552hYDydfLR/rMYCL9KTdVEdxJ+5LNNDrZ/GjqrWlRuiJ+20I4zNALoHuc + iLcO/6qNDLM0OJR3eC666++j/upyPD1phNrrGxC3bgwiLX4F79maQdRPi1C9iKiluOpLgk2fSH6zeLzv + GhfB20LrovWv0XLPF4pkZ8R5zYfddDFylnMiRuvUGoPAHH9jdNZloPaCKZ4ET8Hz2LW4slYX35npwvPT + YUeo3whlfx6cWpLjx1KSw0eCRPuPJN+Z/OP4rvUUcGGDIS04b8R6zoPdNCFXPT9eQBqHzH8bmOpvjc5n + qXj+98V4HDABzy5b4KLFKJxZqgP3GUOCqd9Igl9KhfzWxrESc3PjGOmW9Rgpy3WMtMOIN8S7pipAM3rd + VMR5m6jkqufH9wY6zhm/6LztAnqbAp5FLMKjPeNQE22KKPMRCPtGG5uMBh+lfjpEj/z6+tGSYN1o6RqR + 6TRaKt06WtpmyE9S2aLXTeEgfheiLKfAYboe71keOY+aE/He1QpaNvtcBv2ovCh9iPKdeqiONMG5JVo4 + tUALToaDjlEfXpyqdz+1hLWjpIQ1o6R4ZtUoKcNWRyp215EK3XSkrZP5MOzbeBZYxHc4ieq0YgZoao+d + 7L7SvF1RU47q1HCkHnFHuN1SBJkYwWHywBDqo8v9CCGP+7OOFGchE7tSR0q3GikVuIwQFDqNkDwm/WsB + 3FjGCVRiLopnRsNolsk2W0cfPL8XjaTATThmMQd7vzKElZEuy0cTPfKry7UlwTKZNEstqcB+uCDXTlOw + ZSJ3//GmmpWRn85ZWezgGYZ5X/4J8wwndzjNGBuzaNxwM75HcDYuVC3GfIQkMJNJXUtSaw0ph7Ea1oMo + QPV+/u/ghITYHeMNjaGpM6lssMaY3f36q8+gz3jKeS/xIhUj32wwQPop/KC0N5xUmZxHyPuaF9lwgpdw + 7//51NwnqEs/DXXpn5JVD3kdPun9AAAAAElFTkSuQmCC + + + + -1 + + + + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAcdEVYdFRpdGxlAEluc2VydENvbW1lbnQ7Q29tbWVu + dDvHKjryAAACsklEQVQ4T6WPW0iTYRzGP5fkYdMgLVEGdpEV6YWWF3WhIlJSVBBYKDUPY6KZZ9xCzFV4 + LK00BC+STCmiLLEsz9NpOZ0z06nQQSFMRXdwWji/mfr0vluOGdFNL/z44P3+z+/9PwyA/+Kvl5TxokBm + rOgwM1p4iBkjjBYESAmMOj9Aqs7zZ0YIdI4eO4I9YfsfONgydM0PqlzfnvdSX5qyG7x60CqwH6qO7h6p + iQNl+GGshepYTDQX42NtEgayD2Btug4G5U38nHqCPokPFGKfG5sCB1Xleayb5rHOzmF9ZZYwgzXjNDZY + DTZWF6GuOAe9LAWsKhWal5GQp+zp6k7ztm7g2F8RgbXvY2BnG8HONID99oLwDKY5GSbqstCZxAervo75 + +jNg5RfRkeCJ9gRP6abASVF2Fqb5TvwYLYTxcyWWv9yHcbIaK9OvsapTkn/v0Crajf78UDQL3WnKuSnO + 3bqBU08pMc80YmlAjEVlFumaCUNfOhYUaVjoTcbK1BuMPxDCpO2D8k4UTXEbBTusAueuopMwfn0KQ28K + Ft5ehr7nEiEB+u546OUiLA2XYunDLSxPPsZgrcQsaIh0sQq47XnHsfypCvpOEXSyOOg6YqHtiIa2TQBN + 2wVoW6OgaYkkm11BU04oTfG2CFqkYaT/XSyqckmFHPJqIqkgIYhhUGSSGhlks1SyVTJeSYLMAhreFDjc + i9jXVX7aG2WnvMlgOhlMRX12CG6f4FsI56Mk3MtMcThfTjKOtgIOvSB4PEoMJIIMPBcfQcx+Xjm520lw + tcGF4ETg2AqYkmNe9ONaI/RHXdZRCHzMYS6Bo5PFM7p2EaNrEzLalhimMGQXnTWHrYLiMA/64VUJ/HBx + L5eGeQQOHS4IcWcKgi3kB7sx+UFudHar4PfZRqCv0jq01j+PRQDmFwrvEZ0U84FMAAAAAElFTkSuQmCC + + + + -1 + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAcdEVYdFRpdGxlAEluc2VydENvbW1lbnQ7Q29tbWVu + dDvHKjryAAAHH0lEQVRYR8WWCVRU1xnHn2k2s6ht6slJmjbUNY1pNjWNRYlNTKKpSZOmMe3xNMYYFVBk + k0AcHBCUqBgXFAUk4NLmtNSNfWSJLCPDsEYRRLaAkMohzrxZWGQC/vN9d94MTIrG02z3nN/57nnvcX// + ++69j5EA/KiMePFGaUueJ7UmPyd9lkR89KygJZHY/wc1ITUnMHOl5vi5UlPcM+rGuGekxn0eUgOz10OM + 8a1aSyIJ9pOAJYqsMZ4kcR4gmdohurDXQ30hdg7q98yWmPPMbvf/CTBK4aZvy4XY2ejSbkNtzOyw2hj3 + sK7iraiLccegtV4atJ6XanfOks7tmOUSgMU/IW4hbiNuv0FGj0Tdrt9jQC5He7ov2jMC8aVBh5rtv2Pb + TQOmaunMtqekM9EznQGEvCLF+4XGzICKZk0gWrID0azQlMkEoCnDX9DINd0PjWl+aEjzRUfJbrRlBINm + hHPbZ5HoaZwlme1SBvrb/kk1G/2t/8CnW2eimtkyA1WbZ6Dyg+kbhge4tTnTv7Pnkg5X+zuIdly9MpyL + Cm2CQSetuGrrxNUBGS3pUWhK8aHZlogZ97f/Bz01m9Bbs5FqpAhhu6TB+UNLkbXslxsylz3gfAO8bqMb + jnpisK8Ztq4j9OBh9AsO2et/D7rScQD9nxMdyQLbF9kYMFej4UgQqqNnw6L1QndZIHqqVeipVKFb7w9L + 0QqURTyB1CW/iEh7+36JqjMAr/0dNQcWY7C3XpE4BHbJFaadaxJV5qMh2hJh68zAgKkS7TlhaDz4OgVY + ATn7TzBmvQI582UYMxfCmPFH1MV6oHjdw+Fa1TSJcQlQnbAIA5YaRUBcTCRYQrVtvxD1Ue1rJdriqdrp + 70zDl3IFLmrUaEn5O816A8ynlsCYvgDGtPkwps6HIfVFGE68AFnzBhqSFqAo5CF1YfBDLgHurIx7HTa5 + Er3NsTRwglPQ91mcwj70tcTR/b3obYkVz3H/yufH0ZqlwmnVNGhVD/MMid/AcPx54jlcPkYcfRYF703F + qaApBNW1U5AfOFntEqBiz2uwGfToro1G9/kP0du0R5EQ1O9p2o2expghGphd6LtIe+ZyKaFzUkAS48lF + KAyajJw1v8YXKXOQFzCJbWOIm3P9JkrM8AB36WNeRX+XFpazUbCciYKZqrUuGj31O9F9YSfVHegWbBcB + u+uJum0EBRZsFdhoDJbpI59ARYInKuI9oQubRkEmsG0scTMxSrPKzSXA3brtC2k9C2GujoC5iuC1rCIq + w2H5NBLWM5tgPfsBrDWb0X1uK6zntoi+9ewmur8RFn62fD0tST5O0qzL41bQps0TlCf4QOPtxrZxhAiQ + 6fkrZwC+cHfJtpdo9+fCXBEGU7naTsV6qqE0cChMehVMZYR+nZ1S5n0iRFRZFwwTcaU9F3UfrxbVWhtP + QffRmy2FfvdbLgHSlw8dQ74wRrtlPvo6suwiMTiLaGCHRMcEQy55DybCWU8HEWthOh0IWRtIb2UfsVdg + LPaHTPQ2p6Aq2Y9tPyX4cz8q9Z37XAKMLYp6njZUuhjYdfBhkIAxFlMtDqAaALmIJX7U96O+L4yF1C/0 + hVzoA7lgDYyEpWozclRz2PYzQgRguUuAgoh5dOyOkYAGZYTA3z6LIhqUsAt4cHs1kkRQoHBqNVVmFYyf + MN4w5nvDUh6JnBD36wYY90n4XHpV/1YklFwIeAYOwWoYWCCgwRkWCLxgyCfyFPI9iZXUJ3JXwlwahuyg + p9l2DzFygLxQDzrXh78mWEVSbxhIwBJjHg3shAUrhshVyFkuuJzzrp2Ty2hJ1yErUPw7HjGAOIaa990v + tdG33Fy+0U5ZpIuAl8SspxNSqqYZESV0SnR0OnS0aUlgKuGqor0SYqeYNmwx7SOqTf9airQ1MzrJ4/wO + DA/A/w1v37FoypsHF0/tOrx4Kg4RLDKctM/AWOArBtdEvIoDf52MA28yk5C8SOENZiKSBBOQ9JcJSCQc + NeHPE7qiXnb7G3nuUHxC7gjg+DXEv2Z4kzyYuno6fXh24rJmKb16H5i0IcgOfwW+M91i6P59xHji59eA + 7w2Hr/H5Z7mYPeESgJsjBP/MuvfEqifp6ETTq/eiTRmE7LCF8J3htovucUAOeivBa8n1m+DnWMwzF3Ju + Xw/AjW/yw+OPez0OS1kUneMAZKlfgs90MXOW8+9Fx0A3jEm3Xjrh9Th1h9p1Axxb+ShtuHBkhi6Az5Ou + cpN+o2TSR0qm0gjJpNugEE6sl0wlQ8inVZKsXSfJxUwIBXiM/nyoXS/APUeX/xZZ4a855Hx07HIWlTBh + kuyUhZKMJA5ZUQgRrBBkp3DtNwc4uvwRLrxWY468+wh8p7vtoL5z5qpZkyTm48WT/y9u5A1w47fAG+cu + 4k6lL47Nd92uFYAbC/lEcP1e5NycARydH4sRL/5wQPoKK6FFzGEcvIEAAAAASUVORK5CYII= + + + + -1 + + + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABR0RVh0VGl0 + bGUAQXJyYW5nZUdyb3VwczsLi4TtAAACiUlEQVQ4T5WSW0iTYRjHPzutAw6tqy6CbrsJzftuAhe2FDMs + CSJj24UgJR5Sy5qmwTY1I1KipCQinK05UUpNm2XdiKk5s9TqC7VEm06/HZqb/Hueb1NM86IXft97eJ7n + /x6+v0BtM7GF2LoBHIsAIPwLwWAZsJsaB2G0OlbxAYZngzI3Gvq6AoFACSXrw2iJ/VzMCJz05feSzJhv + CaPeJYx4g/jsCWLYHcTFmnfw+/3X04x7kFlzcKK19341Feaklu0OCZTW98sFtpF5WD+5YBl24enHWZgd + s+gcd0NXbofP5yulZH1rb23dWeM+iccnSqJCAoUPezC0EJCTX353o12U0PptAc+/zqNlbB5nStrgcrl0 + XMSkFEdTt3Kdc4LW2N6RXNCC5PxmJOU1IzG3CcdzmqDOZmxQZTZ0ejweTcbtODH5WjSSrkYh8Uo0tBWH + RFmA2jan05k6PT19ampq6jTNd61BEQwG03lHXWWcqC6MgtYkF4dOwB+eXKpV9S0vEoKp0bECz8Pr+uzq + o3/lcUCvq4oV1UVKaCpiZGXekXZe5w+v15siSdJJ7sOxCEFbGSseu6xEQoESqvxIpBtixMXFxfMGS799 + I28wZeb3XbJw+Dh6VZ6SutCYH63gQQ9GyRerPTEkBeCgPzbg8uPCnbd0fmG7EJ8XKYuo8/dKtu57dTxm + 43DCMBXc6v6Bqjc/cbNrEhX2SZTbx8knc9CYXrHADuFIliyQY319tzq16MDE4YxI2Xkakx19c35YKNk8 + NIt6hxNPBn/h8cAMHvXPIK24LSRAxQx7mz0uX4G9n5hr7djIGwlZNsRnmjtJQLEssEJa8Qtap9clfxA7 + ibW+WEZBbFon8H9A+AOjXoE0kCr8/QAAAABJRU5ErkJggg== + + + + -1 + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABR0RVh0VGl0 + bGUAQXJyYW5nZUdyb3VwczsLi4TtAAAH80lEQVRYR8WWC1BTZxbHr7gSwPqoVNF116lasHS7Fu3UtqPd + Vjr1sVOLD0QQUEG7VGV2F8RHURARo+IGBCU8RQURhUIDBhIDKj5BkfcjICIimEB4CEWoiDtnz/luImkm + dju7O90z8+Pc3C8553znu/f84QDg/4rRm78m3HFpLRef38AlFjRyiVcaObQR/w3HpEp0vBlLaAgXmV3D + tQ4M0fcpgAkyUstvDBhlBFM96DP9juL8cgvLrCRnEiEpsxfL6+5Ey+pBjETl1iFKOE5IayESibiAZNfA + 0axqCJdUg+j7KhBlViJVEJpWdjcg4dIijEXF/qQrWl5ptDgyUqpsK1f1QeuP/2S0aHnUT7yA5v4haCKe + DsEDpJHoG4IG5N4PQ3CjqQdCUsraMJYZYtg1uqbuGi2Ebo4Kwx3V9D6Ha+oBxlXVMAWP+xlXkMutw1xq + ecrIf/QUSjqfQVBSMR4qNxoRRGatGoyQrBwUpa+4Lkz+yvczB5sxeJ91Z3/yV9y+U8vwkjeqTCBMLYWS + rmfa4HxgFlybIK/5KSia+3ge9sFFLfKmPpAhN9sGwD+hiAoYi1iEpi2Hjv6rUPEwFdIKAuHb6C+rnH3m + vYVr1JERvsc+R8cbFWC2J/E23Gr/URv4B5Ajsiae3Ac8OY29DOl9ngsNPNn3euEyFrkt6hYVMA4x9w77 + BNbvswVxlhu09maCsjUdfI/b177zodV4XNc9J8yoAPNdcYWQh0nPV3VCek03ZCq74fu6JwxJfQ+C10im + 8gmk13YzUqu6ILm8E06VaNj65tDLVAAloOfAfJ6D5dtLt/72QHiGw4silS/EyJzAM9huB64JEMrLjF6d + 0duiboAMd5dU1oFo4HQpDwUnTt4l2uEEUdwGCcVaf6cd4pHvsKBNB/N1BeheSUo0dsnmKQf2pMyGjApn + 8BTOvo336HlgR4HwBfwt4hq2soclSTRIRAkS7rQxH3e7DeKK2iAWiSEK1RCNpGLnNgQrqIDXEV2LKcmY + WR+Ne9c1YCZkNy0FjxDb53hvImKBUG72xwLbp46/2gwZtU/gOzwCOoa06i4GHUtqJVLRCWfRp6BPwdaf + KetkR5BU2gHh8kZwDcxRYyx6BnQFmK4LtsnwEFrD+hAbON/wMbgHW4Nb8Exw3j0jk9YR9kWB8/bTjpuE + eZpNwnxAD54HFOAZogCP/QjubP0+4iKsC5KDO+K2V44JZbA2IBfW7skFZ3+pZsnGSBeMZY7Q+RKj3pxr + Pv3zTVPUefe84Ez9B6Co/wt87DpRbfW26Qxcf1kAdYEeHDobOkNq4wQ9LA14Qw9qJ3n6DbVVt3td3NHW + n1qsXuYzGZKUc2DpXyfBtHmC1Xj/Ne06M/qyySK3aRa+0XPOf7pqKg0TOr9fgk4HCNo1S/7ectoLu6b1 + 8TM/M4vbHDUNps8XxOFnKpbu82+CX+xcrvd5Obctxk4kLz0EPmI7Ed7W7eJV6NpsiOF3aJfm5q+bWE2b + L5CYjTexos/atRFMEv2i53A+0Xb2kRIXaB9QQHjGSvCOmG2/9egfecnUWn33IDn9wAS1XB/97hC0U0pI + LacHlLo7vHtK4CN+b4L/iQUtDzqlcL83FspUR8BP/GHLN6J3JugXgGZyJLPUPiKn9k5EjhKIcFTJcFTJ + sOxaEKFSirJq4B+SGjiChJJKIocyKkGYXs4ITi25uzNasRhj8c8KJXAJnHHOOWA64I6hWOMH34j+AIu9 + J8PirVbn1AMXuC+8qGts5yNF2dVtRQ97oKFnkHGPeDIIdYgSqe0ehJou4hlUoUBVIhUdz6AcKWkfgIt1 + nbD3TAmpJj8NqYA1e6ZzS7ZMpkIGH/Qmw9+PvQ9fbLaaSMlVAxJu4deTdAWMOoz/AxSiWp6v7oZzVTiO + K/mRfBY9o6IL5wRB86ILzqBPLkeP84JmhgKFy/8kU016Y/gCsNXciu2/5xz8fnc9vzoI4uRrwEM4a5eq + X8I97s/k3INJxNiZCYJSSuESKiMF5IN28MMIR/hpohS1AQfTaaKkA8d4B5zE65PoE3Gc56CI+cUWUgH8 + a0gFfB1qyy3aYkV4BycthoJWL4iTub5wC7be7bb3rakugTN1BZjtiC+CXAxyimmDhgUl2Agv1uD41rDx + zWAjnB/l8beRonbIRM3wjrxOBdB7yhfgeWgWt2CdJTd/naXpwo1WVSl3HUD20BGic5zBK9QO/KI/oh9Q + AeY+4puQhi0Pu9IKR6+p4PgNNYgL20B8CzUBIW1g+oDXUTdxHTl6/TGICloh9FILdkUDG3DaYix+ZFMB + G0JsuPcdx3BzV43lPnAaN3WB+xvlW47ZQNw1e6jQhIDTt2/SD9hUo+rPYstD81sw4CP0wxzW4xCjmfnD + eejz8DOSiKLmiiMdY/H/F1ABrkHWnO2fLTjbpRbcu8te4+asGGs6z2m89ydulgULN04aXLRlCg0AVoCX + qADFR/MyuH6igywJn+ygovklQj1ii9TghNqBsXjVpAL+HVqjAiw8hPlqkfw+njfKNe7mBMpzgpZ4hGQ6 + lo4BE8UUqiDmlgqPA8GjECP7JXWwfGfWsGoaS2iI1ug1FCz3OeXoGiTTUBvXBl0EF1RF50A5rAmQsZ2t + 3p0LjrtzYJW/FFbuksKKnRcwIbIjGxy2Z8OX2ySaP7mHD6umsYSGaI0NIuR/q5rGEhqiZzodeNXc/zmM + qqbRhIb8jPFB/jN4M5bw1wO4fwEYOItb9gqEigAAAABJRU5ErkJggg== + + + + -1 + + + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAcdEVYdFRpdGxlAERlbGV0ZUNvbW1lbnQ7Q29tbWVu + dDtp3lUYAAACvklEQVQ4T6WSa0iTYRTH39TScihJMYhAqpkfchVooCgZeAHTDEv8YpsaVpZ30bJCIQUv + leUsUtSmK0Nc3sJAU/OWabpYFyMy53UqLZ33TQXl33lWVAv6EB34cV7OeZ/fe87LwwH4L1iYEZv+wPwv + bCQ2GAmUJeL2d7IwMN6Whn6nhBGCNwypGErGfTEURcEdTGIkUOQHYX1Vg/WVL1hfniQmsKYfx7pejTXd + KDGMtaUhQoVuyQk2s4WR4NXdQKwtfMDKZB1WJmqxoq4i5FgeLYd++BH0Q6XQDUqpV4fOnONMsNlI0JUb + gFVNCxb7MqD/nA/dQBH0gyVYorz0KY/qWZhXJEOnKkRbti8TbDESdNz0N9jne5Mw15OI2Z4EzHbHYaYr + FvPKNOjGmrA40oBlTS/6aq8zgRXBfrwJwXGtmUehH6nA7MtozLyIhLbjPHEO2vYz0I3UQ/1MitYgfyjT + kzDQWYXqI24PGjzdJ8sPu3obJE3p3tD1F0PbEo7p52GYbg7FVLMYU40izKueGA4vtNVg6F42GgJ8MXiH + VmqU46m7m5oEZlxDqgfteRtzihRa4Sq0bRG0wkUiicZvRnvCWfSlRGJBnovpykIsVhfgdVQwJII9UhKY + cnmBe1slx2yR62dLK8TR+DGovuyOHJ+dqM+Jh6JGCpmbM8bTLmAqKwqjySLc2r1rzIXHszasQGFB8Msi + nEgQj8okZ4TY8yRUsyG2ljk5VnxMTcDXzCj0h/thPPYk3keLINsvLKK+KXfDawdlzkp2+iAeJ7pAZGc4 + bEkwu5n8kKNm7Eo4mjydcI3PV9e7CqESe0G2z2GS9bksDz5ljlcscsApgSU7zCNMMty3s7pJgdDB56FQ + qLlks016wNzcOsbaWloksNdIBHY+rM9eYmFKsK+ydX4Wf4RhEoK9w55Z/nUPfr9V/w64bwk2Mu3OISlY + AAAAAElFTkSuQmCC + + + + -1 + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAcdEVYdFRpdGxlAERlbGV0ZUNvbW1lbnQ7Q29tbWVu + dDtp3lUYAAAHDUlEQVRYR8WXeVRUVRzHp8UtJShbTnUS6ri0mJW0d06nOi1Glng8oYW2HBdUwEEEhQQc + 2cwNFAGN1ECLogRMY8kIQYEBHEKZQhaH2HKr2QcQTvXt97vvzTQDtPxRds/5nN+de+/7fb/3vnvfe6MA + 8L8ybOPlxLlcIXPlfwTndpTBBrjzKmIEMYoY/Q8Z8zdcI0fOeTXBRkRxNiDENZ8tf6G1IFSjK16FtqJV + 0MmcKWBCcebLlYJWjodD0HooBC2HlBRXoOULmYMr0HwwGM15QWgSBKIpNxDanKV1ZRlvzSAdnqBYicEG + RuoKVp7vOafGb/3dRBd+u+RMp0yH4FcH7TI/EG0SfRK/9DI6ohWWzm/QmBNwgXR4NcQqOBvghjEtuUvp + Qh0GLh7AwLn96Bfsk+LZLFe6M9H/I9H9oeAS08VxL7GH6jKdRMduDOhLoc1awGpjCb7VLga44Rptpj9+ + 7W2SRewCkoiLQBfjJEICEh+gT5Ah0f6+g4ELRdCkzWG1cbLeUAP1GX74xaKVBYhOSsoz6JKSs4gQaGeR + P5ILftiFvjYmndiJXl26TCp6z6SirzsPNdteYTU3gjfjEANj63bNwYCxji5Ko6ROM+Dkgp1CRCRuSxPj + JBGKJNLDtO6QaNku0bwdtu830/iPULXlZVa7lhjegCZ1Nt2rGnGB7fRWkVQSsQtw8pQ/aGEkkZ7mbehp + SoatOZliErEVtsYtsJxMgLluPY3PROXGl/7SwLiaFF/0X6yApSERllOJMFO0Nm6mZNsosSwgSBIGbbKI + jcZIbJL4biMJx8GkWQfziWhBT1MGjie+wGruBBu4YrABN3XSTPSfL4e5Phbmb4n69RSJOpVIaD2VAGvD + Bli175HIJlhJiOvWhgTqj4eFx7Jg7bsw1TCREtWRtKrpKIt/jtU8iCEGuMGtaosP7f6vYSbnphMxEppo + ilGUOIqSrYWplhDJiWqGBSJENKrXwMRUrZbqHJnKMDK7HUdVz/6lgWsrNs6g3VooCYnk0iyMdhE1s0Yk + tScXsTJciHCfre0wes/Xi2ioXA3D8ZUwEpZTSWgqTGW1mwiXhxEXNuB+LPF59HUelly7JHeiYpXAcJzi + 8VCKoTAeWwlDBc2y/RuczdkDXZgSHblZ9PsIDOWh0JeFwNZVAV3OXrQsX6KvfvvNBNLj94hYBS7CQFns + c3Ts8kiAkjJCgJLzLI6FwEAYjykpqRJGgqOhPFhgbclD50e7cDEzDf3aMpxWRaAlOwMW3RGYWgvRdSgb + Z3dspr5yXNibisoFb2wgzRHOBjxKVU/TkcuRRVbIAhTLSEQQBP3RIBgEgRKlywXWbjW0Sxejtyofttwk + XKr4HCdXK9GwJwVnaFU6khLRrymA7QCdnOIsnHxzgZE0x7gYKIl6is71/kECgSS6HPrSZVQnSpZC7yCA + WCIwN2ajcV866oMWwpq/A+asOPQdzUZtcAB0G2JwSZ0Py/440V4xzxfJk+4OJc2RdgPiGBZHPnmu4wif + 3XiJ2jiHAMO3xFxDJ6Q6Bmamik6Jmk6Hei3tGTopbSWo352CyvmvwZiVAP3OCNgKd6OnaA8MOyOhT1+D + Ep9nEH+bZzjp8UvJsQd4R45O9ps8N8t/ysX9/lOwj2Ah/VeL8PNXC2n5lbQp16I41heZ8yYhcy4zER/6 + ybw2kdon48RnO1ASG4NSXx/8lBKGc3ELiUUiFj79GMKvuzmatPhp6HIK7F9DfDyuJzy/CPKmB882/Fz8 + Di19MEwVEShSvQrlw14p1H8LcSNxwyC47fb4qQ+q1AsX4Me4AHSGzXVQNd8Pm6Z5R9GYIQa42E3w8bj5 + YOB0erJtpqVfRpsyHEXrZkL5kNd26mODbHQkwV83HBn+5PLYeNf9q8vnz8PZreFoXeSD1sUyVO+KW4Yy + vzlInDItgsbya/lKZwNc2AQnvTF/2QOw1CbCWBaKwhgfBHuLmbM4C7F7HuvMqPg77gk7MusVtMcsQeMb + z+A08clET3x69yRRZ9pC/VHsMwMxnndF0jWOU2AvDgN5AdNow6lQEPUSgqe7iptq4hWmmjiFqTpWYVKv + F1AZlzbhHnNT0OvQzn4SDbOeQPadExB49bjowBFjY7Lv9ILW9wnBd2/NRKrnvWa6xuPPDIzPXXwfClWz + 7eLjCUlcrVKYqph1CmNVNEWGb6tidNR4r5R87+nQzHgEH0+4HStGur1L7fz2cw8a5R71sZcnNC8+irz7 + 78Oa6z3TqH2si4HcxVM5iPfCgUVTofT2Sqa6Y+ZrH5+oYLL9Jw2B+wn3MLfbUhI9PI3Bkrh9s4m+wNHX + RVGfKcTt1lT6zXmH7AEuvAq8qXiT8Fnlutix/6DwOP4fwG88xwtHLvY+Fnb5Lhyu8GAewNE5yb9aWFwY + sFf+L4ZtvJwM23j5gOJ35jqomOyw4+MAAAAASUVORK5CYII= + + + + -1 + + + + + + 0 + + + Regular + + + Horizontal + + + + + + 0 + + + Regular + + + Horizontal + + + + + + 0 + + + Regular + + + Horizontal + + + + + + 0 + + + Regular + + + Horizontal + + + + + \ No newline at end of file diff --git a/应用/AutoAnswer/MainForm.cs b/应用/AutoAnswer/MainForm.cs new file mode 100644 index 0000000..7a94d9a --- /dev/null +++ b/应用/AutoAnswer/MainForm.cs @@ -0,0 +1,668 @@ +using System; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; +using System.Text.RegularExpressions; +using Api.Framework; +using Api.Framework.Tools; +using AutoAnswer.Entitys; +using Api.Framework.SDK; +using UI.Framework.Controls; +using Microsoft.JScript; +using System.Text; +using DevExpress.XtraEditors; +using DevExpress.Utils.Menu; +using Eson.Utils.ExcelHelper; +using System.Data; +using System.Collections.Generic; +using AutoAnswer.Properties; +using Api.Framework.Model; +using Chat.Framework; +using DevExpress.XtraGrid.Views.Grid; + +namespace AutoAnswer +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + + #region 用户绑定自定义词库分页 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var pram = session.NewParamMap(); + pram.setPageParamters(page, size); + var result = session.FindPage("select * from fl_plugin_autoanswer_definedlib", pram); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label6.Visible = gridView1.RowCount == 0; + + #endregion + + #region 初始化赋值 + buttonCheck1.Checked = Class1.Config.Is_Top_User; + hyperlinkLabelControl7.Enabled = hyperlinkLabelControl6.Enabled = hyperlinkLabelControl5.Enabled = hyperlinkLabelControl4.Enabled = hyperlinkLabelControl2.Enabled = memoEdit1.Enabled = bck_acquiescent_Auto_Answer_onoff.Checked = Class1.Config.Is_Auto_Answer; + memoEdit1.Text = string.Join(@" +-----------分割线----------- +", Class1.Config.DefaultContents); + bck_TuLing_onoff.Checked = Class1.Config.TuLing_OnOff; + tbx_TuLing_prefix.Text = Class1.Config.TuLing_prefix; + tbx_TuLing_apikey.Text = Class1.Config.TuLing_apikey; + + cbx_chattype.Items.Clear(); + cbx_chattype.Items.Add("全部"); + cbx_chattype.SelectedIndex = 0; + foreach (ChatType item in Enum.GetValues(typeof(ChatType))) + cbx_chattype.Items.Add(item); + #endregion + + #region 用户绑定未回复记录分页 + pageControl2.Bind((page, size) => + { + string sql = string.Empty; + sql = "select * from fl_plugin_autoanswer__log where 1=1 "; + this.Invoke(new Action(() => + { + try + { + if (cbx_chattype.SelectedIndex != 0) + sql += $" and chatType = '{cbx_chattype.SelectedIndex - 1}'"; + } + catch (Exception) + { + } + })); + if (!string.IsNullOrWhiteSpace(tBox_userInfo.Text)) + sql += $" and (useraccount like '%{tBox_userInfo.Text.Replace("'", "''").Trim()}%' or username like '%{GlobalObject.escape(tBox_userInfo.Text.Replace("'", "''").Trim())}%')"; + if (checkBox.Checked) + sql += $" and '{DateTime.Now.AddDays(-(double)numericUpDown_days.Value).ToString("u")}' <= datetime and datetime <= '{DateTime.Now.ToString("u")}'"; + sql += " order by datetime DESC"; + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage(sql, parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl2, 40, true, true); + + label5.Visible = gridView2.RowCount == 0; + + #endregion + + #region 未识别的消息转发 + Refresh(); + + repositoryItemComboBox1.SelectedValueChanged += RepositoryItemComboBox1_SelectedValueChanged; + #endregion + + this.settingControl1.Bind(Class1.Config); + + this.dropDownButton1.DropDownControl = CreateDXPopupMenu(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private new void Refresh() + { + try + { + this.gridControl3.DataSource = null; + + #region 加载所有的账号 + + var db = ApiClient.GetSession(); + //所有机器人列表 + var robotList = db.FindRobots(true); + List list = new List(); + if (robotList != null && robotList.Count != 0) + { + var loginWxs = ChatClient.WXClient.Values.Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线).ToList(); + //在线集合 + var robotTemp_online = robotList.Where(f => loginWxs.FirstOrDefault(z => z.WeixinHao == f.name) != null).OrderBy(f => f.type).ToList(); + //离线集合 + var robotTemp_offline = robotList.Where(f => loginWxs.FirstOrDefault(z => z.WeixinHao == f.name) == null).ToList(); + + robotTemp_online.AddRange(robotTemp_offline); + robotList = robotTemp_online; + + var tbList = db.Find("select * from fl_plugin_autoanswer_unprocessed"); + + foreach (var item in robotList) + { + var info = tbList.FirstOrDefault(f => f.rid == item.id); + list.Add(new ShowTmp() { ID = item.id, name = item.name, nick = item.nick, chattype = item.type, username = info == null ? string.Empty : info.username, messtype = info == null ? "所有类型" : info.messtype }); + } + } + + this.gridControl3.DataSource = list; + + #endregion + } + catch (Exception) + { + + } + } + + private DXPopupMenu CreateDXPopupMenu() + { + DXPopupMenu menu = new DXPopupMenu(); + menu.Items.Add(new DXMenuItem("获取导入模板", OnItemClick)); + menu.Items.Add(new DXMenuItem("导入外部数据", OnItemClick)); + return menu; + } + + private void OnItemClick(object sender, EventArgs e) + { + try + { + DXMenuItem item = sender as DXMenuItem; + if (item.Caption == "获取导入模板") + { + SaveFileDialog fbd = new SaveFileDialog(); + fbd.FileName = "自定义问答导入模板"; + fbd.Filter = "Excel|*.xls;*.xlsx;"; + fbd.Title = "保存为"; + if (fbd.ShowDialog() == DialogResult.OK) + { + var path = fbd.FileName; + if (Util.WriteByteToFile(Resources.自定义问答导入模板, path)) + ShowSuccess("保存成功,设置方式请看表头提示"); + else + ShowError("保存失败"); + } + } + else if (item.Caption == "导入外部数据") + { + OpenFileDialog fileDialog = new OpenFileDialog(); + fileDialog.Multiselect = true; + fileDialog.Title = "请选择文件"; + fileDialog.Filter = "所有文件(*xls*)|*.xls*"; //设置要选择的文件的类型 + if (fileDialog.ShowDialog() == DialogResult.OK) + { + string file = fileDialog.FileName;//返回文件的完整路径 + var excelTool = new ExcelStreamExport(); + var dataTable = excelTool.ConvertExcelToTable(file, 0); + + var session = ApiClient.GetSession(); + + var userdefinedlibraryList = new List(); + + foreach (DataRow data in dataTable.Rows) + { + int match_pattern = -1; + var ss = data[0].ToString(); + switch (data[0].ToString()) + { + case "模糊": + match_pattern = 1; + break; + case "全部": + match_pattern = 0; + break; + default: + continue; + } + if (string.IsNullOrWhiteSpace(data[1].ToString()) || string.IsNullOrWhiteSpace(data[2].ToString())) continue; + var list = new List(); + var is_alert_admin = _ConvertData(data[3].ToString()); + if (-1 == is_alert_admin) continue; + var qq = _ConvertData(data[4].ToString()); + if (-1 == qq) continue; + else if (qq == 1) list.Add(1); + var wx = _ConvertData(data[5].ToString()); + if (-1 == wx) continue; + else if (wx == 1) list.Add(2); + var gzh = _ConvertData(data[6].ToString()); + if (-1 == gzh) continue; + else if (gzh == 1) list.Add(3); + + userdefinedlibraryList.Add(new fl_plugin_autoanswer_definedlib() + { + match_pattern = match_pattern, + antistop = GlobalObject.escape(data[1].ToString()), + content = GlobalObject.escape(data[2].ToString()), + is_alert_admin = is_alert_admin, + chat_type = string.Join(",", list) + }); + } + if (userdefinedlibraryList != null && userdefinedlibraryList.Count != 0) + session.Insertable(userdefinedlibraryList).ExecuteCommand(); + else + throw new Exception("数据为空,请填写数据后操作导入操作"); + + ShowSuccess($@"导入数据一共:{dataTable.Rows.Count}条 +导入成功:{userdefinedlibraryList.Count}条 +导入失败:{dataTable.Rows.Count - userdefinedlibraryList.Count}条"); + pageControl1.GotoPage(); + } + } + } + catch (Exception ex) + { + if (ex.Message == "InsertObjs is null") + { + ShowError("导入模板内容填写错误"); + return; + } + ShowError(ex); + } + } + + private int _ConvertData(string str) + { + switch (str) + { + case "是": + return 1; + case "否": + return 0; + default: + return -1; + } + } + + /// + /// 跳转到图灵注册页面 + /// + /// + /// + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start(@"http://www.tuling123.com/sso-web/register?ReturnURL=http%3A%2F%2Fwww.tuling123.com%2F"); + } + + private void barButtonItem2_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + try + { + var selectRows = gridView1.GetSelectedRows(); + if (e.Item.Caption.Trim().Contains("增")) + { + var editUserDefined = new EditUserDefinedForm(string.Empty); + editUserDefined.ShowDialog(); + } + else if (selectRows.Length > 0) + { + if (e.Item.Caption.Contains("修")) + { + var editUserDefined = new EditUserDefinedForm(gridView1.GetRowCellValue(selectRows[0], "id").ToString()); + editUserDefined.ShowDialog(); + } + else if (e.Item.Caption == "删除所有项") + { + if (MessageBox.Show("确定删除所有的数据吗", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.Deleteable().ExecuteCommand(); + } + } + else if (e.Item.Caption.Contains("删")) + { + var session = ApiClient.GetSession(); + try + { + for (int i = selectRows.Length - 1; i >= 0; i--) + { + var pram = session.NewParamMap(); + var id = gridView1.GetRowCellValue(selectRows[i], "id").ToString(); + session.ExcuteSQL($"DELETE FROM fl_plugin_autoanswer_definedlib where id = @id", new { id = id }); + } + } + catch (Exception ex) + { + throw ex; + } + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + Tools.RefreshWordbanck1(); + this.pageControl1.GotoPage(1); + label6.Visible = gridView1.RowCount == 0; + } + } + + /// + /// 检测图灵apikey是否可以正常使用 + /// + /// + /// + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (!string.IsNullOrEmpty(tbx_TuLing_apikey.Text)) + { + string htmlResult = Tools.GetHtml("测试1", "123123", tbx_TuLing_apikey.Text); + if (Regex.IsMatch(htmlResult, @".?intent.?:{.?code.?:(5000|6000|4000|4001|4002|4003|4004|4005|4007|4100|4200|4300|4400|4500|4600|4602|7002|8008)}")) + throw new Exception("测试失败"); + else + ShowSuccess("测试成功"); + } + else + throw new Exception("图灵ApiKey不能为空,请先填写后重试!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 选中的tab值发生变化时 + /// + /// + /// + private void xtraTabControl1_Selected(object sender, DevExpress.XtraTab.TabPageEventArgs e) + { + try + { + if (e.PageIndex == 0) + { + this.pageControl1.GotoPage(1); + label6.Visible = gridView1.RowCount == 0; + } + else if (e.PageIndex == 3) + { + this.pageControl2.GotoPage(1); + label5.Visible = gridView2.RowCount == 0; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 自定义显示文本 + /// + /// + /// + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.Caption == "匹配模式") + { + var value = e.Value.ToString().ToLower(); + if (value == "0") + e.DisplayText = "完全匹配"; + else if (value == "1") + e.DisplayText = "模糊匹配"; + } + else if (e.Column.Caption == "通知管理员") + { + var value = e.Value.ToString().ToLower(); + if (value == "1") + e.DisplayText = "√"; + else if (value == "0") + e.DisplayText = "×"; + } + else if (e.Column.FieldName == "antistop" || e.Column.FieldName == "content") + e.DisplayText = GlobalObject.unescape(e.Value.ToString()); + var temp = _SetDisplayText(e.Column.Caption, e.Value.ToString().ToLower()); + if (!string.IsNullOrEmpty(temp)) + e.DisplayText = temp; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private string _SetDisplayText(string caption, string value) + { + try + { + if (caption == "QQ" || caption == "微信公众号" || caption == "微信") + { + var strs = value.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList(); + var enumkey = (int)((ChatType)Enum.Parse(typeof(ChatType), caption)); + return strs.Contains(enumkey.ToString()) ? "√" : "×"; + } + return string.Empty; + } + catch (Exception ex) + { + ShowError(ex); + return string.Empty; + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.Is_Top_User = buttonCheck1.Checked; + if (bck_acquiescent_Auto_Answer_onoff.Checked) + Class1.Config.Is_Auto_Answer = !string.IsNullOrWhiteSpace(memoEdit1.Text.Replace("-----------分割线-----------", "")); + else + Class1.Config.Is_Auto_Answer = false; + Class1.Config.DefaultContents = memoEdit1.Text.Split(new string[] { @" +-----------分割线----------- +" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + Class1.Config.TuLing_prefix = tbx_TuLing_prefix.Text; + Class1.Config.TuLing_apikey = tbx_TuLing_apikey.Text; + if (bck_TuLing_onoff.Checked && !string.IsNullOrWhiteSpace(tbx_TuLing_apikey.Text)) + { + string htmlResult = Tools.GetHtml("测试", "123123", tbx_TuLing_apikey.Text); + Class1.Config.TuLing_OnOff = !Regex.IsMatch(htmlResult, @".?intent.?:{.?code.?:(5000|6000|4000|4001|4002|4003|4004|4005|4007|4100|4200|4300|4400|4500|4600|4602|7002|8008)}"); + } + else + Class1.Config.TuLing_OnOff = false; + + Util.Save(Class1.Config); + Tools.FindUnprocesseds(true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 显示菜单 + /// + /// + /// + private void gridView1_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + popupMenu1.ShowPopup(Control.MousePosition); + } + + private void hyperlinkLabelControl2_Click(object sender, EventArgs e) + { + memoEdit1.Text = memoEdit1.Text.Insert(memoEdit1.SelectionStart, @" +-----------分割线----------- +"); + memoEdit1.SelectionStart = memoEdit1.SelectionStart; + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.pageControl2.GotoPage(); + label5.Visible = gridView2.RowCount == 0; + } + + private void hyperlinkLabelControl3_Click(object sender, EventArgs e) + { + var clearForm = new ClearForm(); + clearForm.ShowDialog(); + this.pageControl2.GotoPage(); + label5.Visible = gridView2.RowCount == 0; + } + + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "chatType") + e.DisplayText = e.Value.ToString(); + else if (e.Column.FieldName == "username" || e.Column.FieldName == "content") + e.DisplayText = GlobalObject.unescape(e.Value.ToString()); + } + catch (Exception) + { + e.DisplayText = "其他"; + } + } + + private void bck_acquiescent_Auto_Answer_onoff_Click(object sender, EventArgs e) + { + hyperlinkLabelControl7.Enabled = hyperlinkLabelControl6.Enabled = hyperlinkLabelControl5.Enabled = hyperlinkLabelControl4.Enabled = hyperlinkLabelControl2.Enabled = memoEdit1.Enabled = bck_acquiescent_Auto_Answer_onoff.Checked; + } + + private void hyperlinkLabelControl6_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Multiselect = true;//等于true表示可以选择多个文件 + dlg.DefaultExt = ".jpg"; + dlg.Filter = "图片|*.jpg;*.png;*.gif;*.jpeg;*.bmp"; + if (dlg.ShowDialog() == DialogResult.OK) + { + StringBuilder strb = new StringBuilder(); + foreach (string file in dlg.FileNames) + { + strb.AppendLine($"[图片={file}]"); + } + memoEdit1.Text = memoEdit1.Text.Insert(memoEdit1.SelectionStart, strb.ToString().Trim()); + memoEdit1.SelectionStart = memoEdit1.SelectionStart; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void hyperlinkLabelControl7_Click(object sender, EventArgs e) + { + try + { + var label = sender as HyperlinkLabelControl; + var flag = label.Text.Substring(label.Text.Length - 3, 2); + CommonForm commonForm = new CommonForm(flag); + if (commonForm.ShowDialog() == DialogResult.OK) + { + if (!string.IsNullOrWhiteSpace(commonForm.Strs)) + { + var strs = commonForm.Strs.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + if (flag == "图片") + strs = strs.Select(f => $"[图片={f}]").ToList(); + else if (flag == "视频") + strs = strs.Select(f => $"[视频={f}]").ToList(); + else if (flag == "语音") + strs = strs.Select(f => $"[语音={f}]").ToList(); + memoEdit1.Text = memoEdit1.Text.Insert(memoEdit1.SelectionStart, string.Join("\r\n", strs).Trim()); + memoEdit1.SelectionStart = memoEdit1.SelectionStart; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView3_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e) + { + try + { + if (e.Column.Caption == "填写转发到的账号") + { + //var value = e.Value?.ToString(); + //if (!string.IsNullOrWhiteSpace(value) && value.Length == 9) + //{ + var selectRow = gridView3.GetSelectedRows()[0]; + var id = this.gridView3.GetRowCellValue(selectRow, "ID").ToString();//获取ID列的数据 + var messtype = this.gridView3.GetRowCellValue(selectRow, "messtype").ToString();//获取ID列的数据 + var session = ApiClient.GetSession(); + var result = session.FindSingle("select * from fl_plugin_autoanswer_unprocessed where rid = @id", new { id = id }); + if (result == null) + result = new fl_plugin_autoanswer_unprocessed() { rid = int.Parse(id) }; + result.username = e.Value?.ToString(); + result.messtype = messtype; + session.Saveable(result).ExecuteCommand(); + + //ShowSuccess("成功"); + //Refresh(); + //} + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void RepositoryItemComboBox1_SelectedValueChanged(object sender, EventArgs e) + { + try + { + var i = ((ComboBoxEdit)sender); + var text = i.SelectedItem.ToString(); + //获取gridview选中的行 + //GridView myView = (gridControl3.MainView as GridView); + //int dataIndex = myView.GetDataSourceRowIndex(myView.FocusedRowHandle); + + var selectRow = gridView3.GetSelectedRows()[0]; + var id = this.gridView3.GetRowCellValue(selectRow, "ID").ToString();//获取ID列的数据 + var username = this.gridView3.GetRowCellValue(selectRow, "username").ToString();//获取ID列的数据 + var session = ApiClient.GetSession(); + var result = session.FindSingle("select * from fl_plugin_autoanswer_unprocessed where rid = @id", new { id = id }); + if (result == null) + result = new fl_plugin_autoanswer_unprocessed() { rid = int.Parse(id) }; + result.username = username; + result.messtype = text; + session.Saveable(result).ExecuteCommand(); + + } + catch (Exception ex) + { + + } + } + + + } +} \ No newline at end of file diff --git a/应用/AutoAnswer/MainForm.resx b/应用/AutoAnswer/MainForm.resx new file mode 100644 index 0000000..c724d54 --- /dev/null +++ b/应用/AutoAnswer/MainForm.resx @@ -0,0 +1,1855 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + Fill + + + + 0, 0 + + + Top, Bottom + + + + True + + + 黑体, 26.25pt + + + NoControl + + + 271, 186 + + + 339, 35 + + + 33 + + + 尚未有为回复的数据 + + + label5 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + xtraTabPage4 + + + 0 + + + 55, 58 + + + 258, 14 + + + 31 + + + ( 功能介绍:该列表展示记录插件未回复的内容 ) + + + labelControl4 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage4 + + + 1 + + + 762, 26 + + + 72, 14 + + + 30 + + + 清除缓存设置 + + + hyperlinkLabelControl3 + + + DevExpress.XtraEditors.HyperlinkLabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage4 + + + 2 + + + 656, 16 + + + 87, 34 + + + 29 + + + 搜索 + + + simpleButton2 + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage4 + + + 3 + + + 602, 26 + + + 36, 14 + + + 28 + + + 天数据 + + + labelControl7 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage4 + + + 4 + + + 497, 24 + + + 241, 17 + + + Top + + + 0, 0 + + + 886, 0 + + + barDockControl1 + + + DevExpress.XtraBars.BarDockControl, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 4 + + + Bottom + + + 0, 481 + + + 886, 0 + + + barDockControl2 + + + DevExpress.XtraBars.BarDockControl, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 3 + + + Left + + + 0, 0 + + + 0, 481 + + + barDockControl3 + + + DevExpress.XtraBars.BarDockControl, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 1 + + + Right + + + 886, 0 + + + 0, 481 + + + barDockControl4 + + + DevExpress.XtraBars.BarDockControl, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 2 + + + True + + + 55 + + + 7, 14 + + + 886, 481 + + + 问答插件 + + + Loding + + + DevExpress.XtraSplashScreen.SplashScreenManager, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + barManager2 + + + DevExpress.XtraBars.BarManager, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + barButtonItem1 + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + barButtonItem2 + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + barButtonItem3 + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + barButtonItem4 + + + DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridView2 + + + DevExpress.XtraGrid.Views.Grid.GridView, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn8 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn14 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn9 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn10 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn11 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn12 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridView1 + + + DevExpress.XtraGrid.Views.Grid.GridView, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn1 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn2 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn3 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn4 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn13 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn5 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn7 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn6 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridView3 + + + DevExpress.XtraGrid.Views.Grid.GridView, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn15 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn16 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn17 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn18 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn19 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + gridColumn20 + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + repositoryItemComboBox1 + + + DevExpress.XtraEditors.Repository.RepositoryItemComboBox, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + repositoryItemPopupContainerEdit1 + + + DevExpress.XtraEditors.Repository.RepositoryItemPopupContainerEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + popupMenu1 + + + DevExpress.XtraBars.PopupMenu, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + MainForm + + + UI.Framework.Forms.BaseForm, UI.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + 增加自定义项 + + + 修改选中项 + + + 删除选中项 + + + 删除所有项 + + + 查询 + + + 52, 18 + + + 27 + + + checkBox + + + DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage4 + + + 5 + + + 201, 26 + + + 60, 14 + + + 26 + + + 用户信息: + + + labelControl6 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage4 + + + 6 + + + 549, 22 + + + 49, 22 + + + 22 + + + numericUpDown_days + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + xtraTabPage4 + + + 7 + + + 267, 22 + + + 212, 22 + + + 21 + + + tBox_userInfo + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + xtraTabPage4 + + + 8 + + + 36, 26 + + + 28, 14 + + + 8 + + + 平台: + + + labelControl5 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage4 + + + 9 + + + 72, 22 + + + 101, 22 + + + 7 + + + cbx_chattype + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + xtraTabPage4 + + + 10 + + + -1, 78 + + + 平台类型 + + + True + + + 0 + + + 102 + + + 机器人名称 + + + True + + + 1 + + + 174 + + + 用户账号 + + + 用户昵称 + + + True + + + 2 + + + 181 + + + 接收内容 + + + True + + + 3 + + + 259 + + + 接收时间 + + + 881, 336 + + + 6 + + + gridControl2 + + + DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage4 + + + 11 + + + Bottom + + + 0, 424 + + + 884, 33 + + + 5 + + + pageControl2 + + + UI.Framework.Controls.PageControl, UI.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + xtraTabPage4 + + + 12 + + + 884, 457 + + + 留 言 管 理 + + + xtraTabPage4 + + + DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabControl1 + + + 0 + + + 886, 481 + + + 1 + + + True + + + NoControl + + + 353, 80 + + + 189, 14 + + + 24 + + + (注:测试不通过时,功能自动关闭) + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupControl1 + + + 0 + + + 504, 260 + + + 114, 41 + + + 7 + + + 测试ApiKey + + + simpleButton1 + + + DevExpress.XtraEditors.SimpleButton, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + groupControl1 + + + 1 + + + 632, 210 + + + 48, 14 + + + 6 + + + 图灵注册 + + + hyperlinkLabelControl1 + + + DevExpress.XtraEditors.HyperlinkLabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + groupControl1 + + + 2 + + + 220, 207 + + + 398, 20 + + + 5 + + + tbx_TuLing_apikey + + + DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + groupControl1 + + + 3 + + + 220, 145 + + + 398, 20 + + + 4 + + + tbx_TuLing_prefix + + + DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + groupControl1 + + + 4 + + + 220, 74 + + + 80, 27 + + + 3 + + + bck_TuLing_onoff + + + UI.Framework.Controls.ButtonCheck, UI.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + groupControl1 + + + 5 + + + 134, 210 + + + 73, 14 + + + 2 + + + 图灵ApiKey: + + + labelControl3 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + groupControl1 + + + 6 + + + 123, 146 + + + 84, 14 + + + 1 + + + 触发图灵前缀: + + + labelControl2 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + groupControl1 + + + 7 + + + 147, 80 + + + 60, 14 + + + 0 + + + 图灵账号: + + + labelControl1 + + + DevExpress.XtraEditors.LabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + groupControl1 + + + 8 + + + 51, 39 + + + 782, 361 + + + 0 + + + 图灵基础设置 + + + groupControl1 + + + DevExpress.XtraEditors.GroupControl, DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage3 + + + 0 + + + 884, 457 + + + 图 灵 机 器 人 + + + xtraTabPage3 + + + DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabControl1 + + + 1 + + + 737, 426 + + + 123, 23 + + + 37 + + + 数据导入 + + + dropDownButton1 + + + DevExpress.XtraEditors.DropDownButton, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage1 + + + 0 + + + Top, Bottom + + + True + + + 黑体, 26.25pt + + + NoControl + + + 172, 186 + + + 537, 35 + + + 35 + + + 尚未有自定义数据,右击进行增加 + + + label6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + xtraTabPage1 + + + 1 + + + Fill + + + 0, 0 + + + ID + + + True + + + 0 + + + 48 + + + 匹配模式 + + + True + + + 1 + + + 66 + + + 关键词 + + + True + + + 2 + + + 118 + + + 回复内容 + + + True + + + 3 + + + 208 + + + 通知钉钉群 + + + True + + + 4 + + + 70 + + + QQ + + + True + + + 5 + + + 52 + + + 微信公众号 + + + True + + + 6 + + + 69 + + + 微信 + + + True + + + 7 + + + 55 + + + 884, 425 + + + 4 + + + gridControl1 + + + DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage1 + + + 2 + + + Bottom + + + 0, 425 + + + 884, 32 + + + 3 + + + pageControl1 + + + UI.Framework.Controls.PageControl, UI.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + xtraTabPage1 + + + 3 + + + 884, 457 + + + 自 定 义 词 库 + + + xtraTabPage1 + + + DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabControl1 + + + 2 + + + 765, 10 + + + 1, 1, 1, 1 + + + 56, 24 + + + 28 + + + buttonCheck1 + + + UI.Framework.Controls.ButtonCheck, UI.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + panelControl1 + + + 0 + + + 504, 30 + + + 58, 14 + + + 24 + + + [插入语音] + + + hyperlinkLabelControl4 + + + DevExpress.XtraEditors.HyperlinkLabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl1 + + + 1 + + + 418, 30 + + + 58, 14 + + + 25 + + + [插入视频] + + + hyperlinkLabelControl5 + + + DevExpress.XtraEditors.HyperlinkLabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl1 + + + 2 + + + 308, 30 + + + 82, 14 + + + 26 + + + [插入本地图片] + + + hyperlinkLabelControl6 + + + DevExpress.XtraEditors.HyperlinkLabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl1 + + + 3 + + + 198, 30 + + + 82, 14 + + + 27 + + + [插入网络图片] + + + hyperlinkLabelControl7 + + + DevExpress.XtraEditors.HyperlinkLabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl1 + + + 4 + + + True + + + Tahoma, 9pt, style=Bold + + + 52, 10 + + + 241, 14 + + + 23 + + + 无法处理用户消息时,随机回复的内容。 + + + label4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panelControl1 + + + 5 + + + 124, 30 + + + 46, 14 + + + 22 + + + [分隔线] + + + hyperlinkLabelControl2 + + + DevExpress.XtraEditors.HyperlinkLabelControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + panelControl1 + + + 6 + + + True + + + Tahoma, 9pt + + + NoControl + + + 717, 15 + + + 43, 14 + + + 19 + + + 置顶: + + + label7 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panelControl1 + + + 7 + + + True + + + Tahoma, 9pt + + + NoControl + + + 55, 30 + + + 55, 14 + + + 19 + + + 快捷键: + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panelControl1 + + + 8 + + + 620, 10 + + + 1, 1, 1, 1 + + + 56, 24 + + + 20 + + + bck_acquiescent_Auto_Answer_onoff + + + UI.Framework.Controls.ButtonCheck, UI.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + panelControl1 + + + 9 + + + 25, 18 + + + 833, 52 + + + 29 + + + panelControl1 + + + DevExpress.XtraEditors.PanelControl, DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage2 + + + 0 + + + 25, 76 + + + 833, 359 + + + 28 + + + memoEdit1 + + + DevExpress.XtraEditors.MemoEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage2 + + + 1 + + + 0, 0 + + + 100, 23 + + + 25 + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + xtraTabPage2 + + + 2 + + + 884, 457 + + + 默 认 回 复 词 库 + + + xtraTabPage2 + + + DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabControl1 + + + 3 + + + Fill + + + 0, 0 + + + 884, 457 + + + 2 + + + settingControl1 + + + UI.Framework.Controls.SettingControl, UI.Framework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + + xtraTabPage5 + + + 0 + + + 884, 457 + + + 呼 叫 客 服 + + + xtraTabPage5 + + + DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabControl1 + + + 4 + + + Fill + + + 0, 0 + + + ID + + + True + + + 0 + + + 72 + + + 平台类型 + + + True + + + 1 + + + 106 + + + 账号 + + + True + + + 2 + + + 155 + + + 账号昵称 + + + True + + + 3 + + + 172 + + + LightGray + + + Tahoma, 9pt, style=Underline + + + 填写转发到的账号 + + + True + + + 4 + + + 217 + + + 消息类型 + + + + Combo + + + 所有类型 + + + 群聊类型 + + + 私聊类型 + + + 所有类型 + + + True + + + 5 + + + 137 + + + False + + + Combo + + + 884, 457 + + + 9 + + + gridControl3 + + + DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabPage6 + + + 0 + + + 884, 457 + + + 未 处 理 消 息 转 发 + + + xtraTabPage6 + + + DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + xtraTabControl1 + + + 5 + + + xtraTabControl1 + + + DevExpress.XtraTab.XtraTabControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + + + $this + + + 0 + + + 109, 17 + + \ No newline at end of file diff --git a/应用/AutoAnswer/Properties/AssemblyInfo.cs b/应用/AutoAnswer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9c08215 --- /dev/null +++ b/应用/AutoAnswer/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("AutoAnswer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("AutoAnswer")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("e5a7e5db-eb35-4542-bd69-22e263691caa")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/AutoAnswer/Properties/Resources.Designer.cs b/应用/AutoAnswer/Properties/Resources.Designer.cs new file mode 100644 index 0000000..c3ad224 --- /dev/null +++ b/应用/AutoAnswer/Properties/Resources.Designer.cs @@ -0,0 +1,177 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace AutoAnswer.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AutoAnswer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 增加自定义词库 的本地化字符串。 + /// + internal static string AddUserDefinedFormTitle { + get { + return ResourceManager.GetString("AddUserDefinedFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 清除缓存窗体 的本地化字符串。 + /// + internal static string ClearLogFormTile { + get { + return ResourceManager.GetString("ClearLogFormTile", resourceCulture); + } + } + + /// + /// 查找类似 问答插件 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 问答插件 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 问答插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 修改自定义词库 的本地化字符串。 + /// + internal static string UpdateUserDefinedFormTitle { + get { + return ResourceManager.GetString("UpdateUserDefinedFormTitle", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 云 { + get { + object obj = ResourceManager.GetObject("云", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 呼叫客服 { + get { + object obj = ResourceManager.GetObject("呼叫客服", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 库 { + get { + object obj = ResourceManager.GetObject("库", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 管理库 { + get { + object obj = ResourceManager.GetObject("管理库", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Byte[] 类型的本地化资源。 + /// + internal static byte[] 自定义问答导入模板 { + get { + object obj = ResourceManager.GetObject("自定义问答导入模板", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 问答 { + get { + object obj = ResourceManager.GetObject("问答", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/AutoAnswer/Properties/Resources.resx b/应用/AutoAnswer/Properties/Resources.resx new file mode 100644 index 0000000..7f4b87a --- /dev/null +++ b/应用/AutoAnswer/Properties/Resources.resx @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 问答插件 + 插件名 + + + 问答插件 + 插件介绍 + + + + ..\Resources\库.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\问答.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 清除缓存窗体 + 清除缓存窗体标题 + + + 问答插件 + 插件主窗体名称 + + + ..\Resources\管理库.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 增加自定义词库 + 增加自定义词库 + + + 修改自定义词库 + 修改自定义词库 + + + ..\Resources\云.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\呼叫客服.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\自定义问答导入模板.xls;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/应用/AutoAnswer/Properties/Settings.Designer.cs b/应用/AutoAnswer/Properties/Settings.Designer.cs new file mode 100644 index 0000000..8187495 --- /dev/null +++ b/应用/AutoAnswer/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace AutoAnswer.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/应用/AutoAnswer/Properties/Settings.settings b/应用/AutoAnswer/Properties/Settings.settings new file mode 100644 index 0000000..049245f --- /dev/null +++ b/应用/AutoAnswer/Properties/Settings.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/应用/AutoAnswer/Properties/licenses.licx b/应用/AutoAnswer/Properties/licenses.licx new file mode 100644 index 0000000..c26328d --- /dev/null +++ b/应用/AutoAnswer/Properties/licenses.licx @@ -0,0 +1,5 @@ +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.Repository.RepositoryItemComboBox, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraBars.BarManager, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/AutoAnswer/Resources/云.png b/应用/AutoAnswer/Resources/云.png new file mode 100644 index 0000000..a610e21 Binary files /dev/null and b/应用/AutoAnswer/Resources/云.png differ diff --git a/应用/AutoAnswer/Resources/呼叫.png b/应用/AutoAnswer/Resources/呼叫.png new file mode 100644 index 0000000..a7a0d6f Binary files /dev/null and b/应用/AutoAnswer/Resources/呼叫.png differ diff --git a/应用/AutoAnswer/Resources/呼叫客服.png b/应用/AutoAnswer/Resources/呼叫客服.png new file mode 100644 index 0000000..a0170ef Binary files /dev/null and b/应用/AutoAnswer/Resources/呼叫客服.png differ diff --git a/应用/AutoAnswer/Resources/库.png b/应用/AutoAnswer/Resources/库.png new file mode 100644 index 0000000..13ea1d7 Binary files /dev/null and b/应用/AutoAnswer/Resources/库.png differ diff --git a/应用/AutoAnswer/Resources/管理库.png b/应用/AutoAnswer/Resources/管理库.png new file mode 100644 index 0000000..1fe085b Binary files /dev/null and b/应用/AutoAnswer/Resources/管理库.png differ diff --git a/应用/AutoAnswer/Resources/自定义问答导入模板.xls b/应用/AutoAnswer/Resources/自定义问答导入模板.xls new file mode 100644 index 0000000..0be698b Binary files /dev/null and b/应用/AutoAnswer/Resources/自定义问答导入模板.xls differ diff --git a/应用/AutoAnswer/Resources/问答.png b/应用/AutoAnswer/Resources/问答.png new file mode 100644 index 0000000..e7bf762 Binary files /dev/null and b/应用/AutoAnswer/Resources/问答.png differ diff --git a/应用/AutoAnswer/Tools.cs b/应用/AutoAnswer/Tools.cs new file mode 100644 index 0000000..398e160 --- /dev/null +++ b/应用/AutoAnswer/Tools.cs @@ -0,0 +1,114 @@ +using Api.Framework; +using AutoAnswer.Entitys; +using CsharpHttpHelper; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Web; + +namespace AutoAnswer +{ + public static class Tools + { + private static List _WordbanckCache = null; + + public static List WordbanckCache + { + get + { + if (_WordbanckCache == null) RefreshWordbanck1(); + + return _WordbanckCache; + } + } + + /// + /// 获取新的数据 + /// + public static void RefreshWordbanck1() + { + _WordbanckCache = ApiClient.GetSession().Find("select * from fl_plugin_autoanswer_definedlib where match_pattern = 1"); + } + + #region 图灵 + /// + /// 图灵API + /// + /// + /// + public static string GetHtml(string text, string userid, string apikey = "") + { + userid = Regex.Replace(userid, "[^a-zA-Z0-9\u4e00-\u9fa5]", ""); + userid = string.IsNullOrEmpty(userid) ? Guid.NewGuid().ToString("N") : userid; + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "http://openapi.tuling123.com/openapi/api/v2", + Encoding = System.Text.Encoding.GetEncoding("utf-8"), + Method = "post", + Postdata = "{\"reqType\":0,\"perception\": {\"inputText\": {\"text\": \"" + String2Unicode(text) + "\"}},\"userInfo\": {\"apiKey\": \"" + (string.IsNullOrEmpty(apikey) ? Class1.Config.TuLing_apikey.Trim() : apikey.Trim()) + "\",\"userId\":\"" + userid + "\"}}", + ContentType = "text/html" + }; + HttpResult result = http.GetHtml(item); + return result.Html; + } + catch (Exception ex) + { + throw ex; + } + } + /// + /// 字符串转Unicode + /// + /// 源字符串 + /// Unicode编码后的字符串 + private static string String2Unicode(string source) + { + var bytes = Encoding.Unicode.GetBytes(source); + var stringBuilder = new StringBuilder(); + for (var i = 0; i < bytes.Length; i += 2) + { + stringBuilder.AppendFormat("\\u{0:x2}{1:x2}", bytes[i + 1], bytes[i]); + } + return stringBuilder.ToString(); + } + #endregion + + #region url编码工厂 + /// + /// url编码工厂 + /// + /// + /// 编码还是解码,true编码,false解码 + /// + public static string UrlEncodFactory(string content, bool flag = false) + { + try + { + return flag ? HttpUtility.UrlEncode(content, Encoding.UTF8) : HttpUtility.UrlDecode(content, Encoding.UTF8); + } + catch (Exception) + { } + return string.Empty; + } + #endregion + + private static List unprocesseds = null; + public static List FindUnprocesseds(bool flush = false) + { + if (flush || unprocesseds == null) + { + var db = ApiClient.GetSession(); + unprocesseds = db.Find("select * from fl_plugin_autoanswer_unprocessed"); + } + return unprocesseds; + } + + } +} diff --git a/应用/CSIMTurnMoney/CSIMTurnMoney.csproj b/应用/CSIMTurnMoney/CSIMTurnMoney.csproj new file mode 100644 index 0000000..ac1e819 --- /dev/null +++ b/应用/CSIMTurnMoney/CSIMTurnMoney.csproj @@ -0,0 +1,99 @@ + + + + + Debug + AnyCPU + {91C665C6-BE69-4A0C-AFC1-C2DBD82E97DC} + Library + Properties + CSIMTurnMoney + CSIMTurnMoney + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/CSIMTurnMoney/Class1.cs b/应用/CSIMTurnMoney/Class1.cs new file mode 100644 index 0000000..daf5403 --- /dev/null +++ b/应用/CSIMTurnMoney/Class1.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Timers; +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using Chat.Framework.WXSdk.IPAD; +using CSIMTurnMoney.Properties; + +namespace CSIMTurnMoney +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = "客服指令转账"; + this.Note = "客服指令转账"; + this.Logo = Resources.转账; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + + #endregion + + public override void Start() + { + try + { + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + if (string.IsNullOrEmpty(e.Groupid)) //私聊信息 + { + var _event = e.Event as Chat.Framework.WXSdk.Events.WXReiceveFriendMsg; + if (_event != null && _event.IsRobot) //判断是否自己给自己发送消息 + { + if (string.IsNullOrWhiteSpace(Config.TurnCMD)) + { + return; + } + + try + { + var reg = Regex.Match(e.Message.Trim(), Config.TurnCMD, RegexOptions.IgnoreCase); + if (!reg.Success) + { + return; + } + + var result = reg.Groups[1].Value; + var isSucc = double.TryParse(result, out var money); + if (!isSucc) + { + throw new Exception("可能客服指令转账指令设置有问题,导致获取金额异常"); + } + + if (Config.MaxMoney < money || money < 0.3) + { + e.SendMessage("执行失败,操作金额不合规"); + return; + } + + var member = e.GetMemberinfo(); + string url = ApiClient.SendWechatPay(new { robot_name = e.RobotName, robot_nick = e.RobotNick, username = member.username, usernick = member.usernick }, $"转账成功:{money}{ApiClient.Setting.SystemConfig.PointName}", money, out var ispaid, out var appinfo); + + if (string.IsNullOrWhiteSpace(url)) + { + return; + } + + var session = ApiClient.GetSession(); + + //member = session.ChangePoint(PointType.提现扣除, money, member.id, "客服指令转账成功"); + session.Insertable(new fl_exchange_info() { point = money, state = ApplyType.已审核, time = DateTime.Now, check_time = DateTime.Now, uid = member.id, remark = $"客服指令转账成功 商户链接:{url}", rid = e.RobotInfo.id, IsTransmatic = true, groupid = e.Groupid }).ExecuteCommand();//保存记录 + + var mess = string.Empty; + if (!ispaid) + { + if (appinfo != null) + mess = Util.GetMiNiAppXml(appinfo, e.ChatType); + } + + var pay_url = ApiClient.ShortURL(url).Result; + LogHelper.GetSingleObj().Info("客服指令转账成功 商户链接", $"{member.usernick}({member.username});金额:{money};原始:{url} => 缩短:{pay_url}"); + + if (string.IsNullOrWhiteSpace(mess)) + { + mess = Config.MessInfo.Replace("[兑换金额]", money.ToString("0.00")).Replace("[领取地址]", pay_url).Replace("[长领取地址]", url); + } + + ApiClient.SendMessage( + new temp_send_data() { Groupid = e.Groupid, Message = mess, Robot = e.RobotInfo, TouserName = member.username } + ); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + } + } + catch (Exception ex) + { + this.OnLog($"客服指令转账插件异常.:{ex.Message} - {ex.StackTrace}"); + } + } + + } +} diff --git a/应用/CSIMTurnMoney/Config.cs b/应用/CSIMTurnMoney/Config.cs new file mode 100644 index 0000000..d11ea21 --- /dev/null +++ b/应用/CSIMTurnMoney/Config.cs @@ -0,0 +1,24 @@ +using Api.Framework.SDK; + +namespace CSIMTurnMoney +{ + [Config(Name = "插件-客服指令转账-配置")] + public class Config + { + /// + /// 转账执行 + /// + public string TurnCMD { get; set; } = @"转\s(?<金额>[0-9]{0,}.{0,1}[0-9]{1,})"; + + /// + /// 最大金额 + /// + public double MaxMoney { get; set; } = 0.3; + + /// + /// 回复文案 + /// + public string MessInfo { get; set; } + + } +} \ No newline at end of file diff --git a/应用/CSIMTurnMoney/MainForm.Designer.cs b/应用/CSIMTurnMoney/MainForm.Designer.cs new file mode 100644 index 0000000..1b1c048 --- /dev/null +++ b/应用/CSIMTurnMoney/MainForm.Designer.cs @@ -0,0 +1,209 @@ +namespace CSIMTurnMoney +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(22, 31); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(65, 12); + this.label1.TabIndex = 1; + this.label1.Text = "转账指令:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(21, 80); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(65, 12); + this.label2.TabIndex = 2; + this.label2.Text = "最大金额:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(89, 27); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(274, 21); + this.textBox1.TabIndex = 3; + // + // numericUpDown1 + // + this.numericUpDown1.DecimalPlaces = 2; + this.numericUpDown1.Location = new System.Drawing.Point(89, 76); + this.numericUpDown1.Maximum = new decimal(new int[] { + 9999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 3, + 0, + 0, + 65536}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(164, 21); + this.numericUpDown1.TabIndex = 4; + this.numericUpDown1.Value = new decimal(new int[] { + 3, + 0, + 0, + 65536}); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(385, 31); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(65, 12); + this.linkLabel1.TabIndex = 5; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "恢复默认值"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(22, 118); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(65, 12); + this.label3.TabIndex = 1; + this.label3.Text = "回复文案:"; + this.label3.Click += new System.EventHandler(this.label3_Click); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(23, 144); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(690, 371); + this.textBox2.TabIndex = 3; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(138, 119); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(65, 12); + this.label4.TabIndex = 1; + this.label4.Text = "支持变量:"; + this.label4.Click += new System.EventHandler(this.label3_Click); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Font = new System.Drawing.Font("宋体", 12F); + this.label5.Location = new System.Drawing.Point(206, 117); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(88, 16); + this.label5.TabIndex = 1; + this.label5.Text = "[兑换金额]"; + this.label5.Click += new System.EventHandler(this.label3_Click); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Font = new System.Drawing.Font("宋体", 12F); + this.label6.Location = new System.Drawing.Point(313, 117); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(88, 16); + this.label6.TabIndex = 1; + this.label6.Text = "[领取地址]"; + this.label6.Click += new System.EventHandler(this.label3_Click); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Font = new System.Drawing.Font("宋体", 12F); + this.label7.Location = new System.Drawing.Point(425, 118); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(104, 16); + this.label7.TabIndex = 1; + this.label7.Text = "[长领取地址]"; + this.label7.Click += new System.EventHandler(this.label3_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(739, 541); + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.numericUpDown1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label4); + this.Controls.Add(this.label7); + this.Controls.Add(this.label6); + this.Controls.Add(this.label5); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "设置"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + } +} \ No newline at end of file diff --git a/应用/CSIMTurnMoney/MainForm.cs b/应用/CSIMTurnMoney/MainForm.cs new file mode 100644 index 0000000..8d0c085 --- /dev/null +++ b/应用/CSIMTurnMoney/MainForm.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework.Tools; + +namespace CSIMTurnMoney +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + textBox1.Text = Class1.Config.TurnCMD; + textBox2.Text = Class1.Config.MessInfo; + numericUpDown1.Value = (decimal)Class1.Config.MaxMoney; + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.TurnCMD = textBox1.Text; + Class1.Config.MessInfo = textBox2.Text; + Class1.Config.MaxMoney = (double)numericUpDown1.Value; + + Util.Save(Class1.Config); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + textBox1.Text = @"转\s(?<金额>[0-9]{0,}.{0,1}[0-9]{1,})"; + } + + private void label3_Click(object sender, EventArgs e) + { + + } + } +} diff --git a/应用/CSIMTurnMoney/MainForm.resx b/应用/CSIMTurnMoney/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/应用/CSIMTurnMoney/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/应用/CSIMTurnMoney/Properties/AssemblyInfo.cs b/应用/CSIMTurnMoney/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c8678be --- /dev/null +++ b/应用/CSIMTurnMoney/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("CSIMTurnMoney")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CSIMTurnMoney")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("91c665c6-be69-4a0c-afc1-c2dbd82e97dc")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/CSIMTurnMoney/Properties/Resources.Designer.cs b/应用/CSIMTurnMoney/Properties/Resources.Designer.cs new file mode 100644 index 0000000..24eec1a --- /dev/null +++ b/应用/CSIMTurnMoney/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace CSIMTurnMoney.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CSIMTurnMoney.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 转账 { + get { + object obj = ResourceManager.GetObject("转账", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/CSIMTurnMoney/Properties/Resources.resx b/应用/CSIMTurnMoney/Properties/Resources.resx new file mode 100644 index 0000000..5bf08f3 --- /dev/null +++ b/应用/CSIMTurnMoney/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\转账.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/CSIMTurnMoney/Resources/转账.jpg b/应用/CSIMTurnMoney/Resources/转账.jpg new file mode 100644 index 0000000..3c4782b Binary files /dev/null and b/应用/CSIMTurnMoney/Resources/转账.jpg differ diff --git a/应用/CleaningTools/Class1.cs b/应用/CleaningTools/Class1.cs new file mode 100644 index 0000000..e082ae3 --- /dev/null +++ b/应用/CleaningTools/Class1.cs @@ -0,0 +1,72 @@ +using Api.Framework.SDK; +using CleaningTools.Properties; +using System; + +namespace CleaningTools +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.清理专家; + } + + #region 自定义变量 + public static Config Config = null; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + //创建配置文件 + Config = this.ReadConfig(); + TimerTask.NewTimer(60); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/CleaningTools/CleaningThread.cs b/应用/CleaningTools/CleaningThread.cs new file mode 100644 index 0000000..f21f0f2 --- /dev/null +++ b/应用/CleaningTools/CleaningThread.cs @@ -0,0 +1,260 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CleaningTools.Entity; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace CleaningTools +{ + class CleaningThread : TimerTask + { + + /// + /// 清理缓存时间 + /// + private DateTime delete_cache_time = DateTime.MinValue; + + /// + /// 清理微信聊天记录时间 + /// + private DateTime clear_msg_time = DateTime.MinValue; + + //public bool delete_friend_ing = false; + + public override void Run(object state, bool timedOut) + { + try + { + if (Class1.Config.timing) + { + //清理缓存 + if (delete_cache_time.Day != DateTime.Now.Day) + { + if (DateTime.Now.Hour >= 2 && DateTime.Now.Hour < 3 && DateTime.Now.Minute >= 30) + { + try + { + //清理图片数据 + var tools = new Tools(); + var cachePath = Util.MapPath(Util.MapPath(@"Cache")); + if (Directory.Exists(cachePath)) + { + tools.DelectDir(cachePath); + } + cachePath = Util.MapPath(Util.MapPath(@"Assembly\apifile")); + if (Directory.Exists(cachePath)) + { + tools.DelectDir(cachePath, true); + } + + //清理超过7天的加人数据 + var session = ApiClient.GetSession(); + //if (session.TableExist("fl_plugin_userfission_applyfriend_info")) session.ExcuteSQL("delete from fl_plugin_userfission_applyfriend_info where crt_time <= @crttime", new { crttime = DateTime.Now.AddDays(-60).ToString("yyyy-MM-dd HH:mm:ss") }); + + //清理问答7天未响应数据 + if (session.TableExist("fl_plugin_autoanswer__log")) session.ExcuteSQL("delete from fl_plugin_autoanswer__log where datetime <= @crttime", new { crttime = DateTime.Now.AddDays(-4).ToString("yyyy-MM-dd HH:mm:ss") }); + + //清理聊天记录3天之前的 + if (session.TableExist("fl_plugin_messagesupervises_messinfo")) session.ExcuteSQL("delete from fl_plugin_messagesupervises_messinfo where send_time <= @time", new { time = DateTime.Now.AddDays(-3) }); + + //清理查询记录7天前的所有记录 + if (session.TableExist("fl_query_hist")) session.ExcuteSQL("delete from fl_query_hist where crt_time <= @time", new { time = DateTime.Now.Date.AddDays(-7).ToString("yyyy-MM-dd HH:mm:ss") }); + + //清理Debug调试数据 + if (session.TableExist("fl_debug_log")) session.ExcuteSQL("delete from fl_debug_log where crt_time <= @crt_time", new { crt_time = DateTime.Now.AddDays(-1) }); + + EventClient.OnEvent(this, "清理管家:定时清理执行完毕!"); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "清理管家:" + ex.Message); + } + finally + { + delete_cache_time = DateTime.Now;//最后一次更新时间 + } + } + } + + } + + if (Class1.Config.isAutoClearChatMsg) + { + //清理微信聊天记录 + if (clear_msg_time.Day != DateTime.Now.Day) + { + var time = DateTime.Parse(Class1.Config.clear_msg_time); + if (DateTime.Now.Hour >= time.Hour && DateTime.Now.Hour < time.Hour + 1 && DateTime.Now.Minute >= time.Minute) + { + try + { + var clients = Chat.Framework.ChatClient.WXClient.Values.Where(f => f.WeixinType == WeixinType.Hook微信 && f.Status == WxStatus.在线).ToList(); + for (int i = 0; i < 2; i++) + { + foreach (var client in clients) + { + try + { + client.ClearChatHistoryMsg(); + Thread.Sleep(3100); + } + catch (Exception ex) + { } + } + Thread.Sleep(20000); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, " 清理管家:" + ex.Message); + } + finally + { + clear_msg_time = DateTime.Now;//最后一次更新时间 + } + EventClient.OnEvent(this, "清理管家:定时清理微信历史聊天执行完毕!"); + } + } + } + + if (Class1.Config.switch_delete_friend) + { + if (DateTime.Now.Hour >= 2 && DateTime.Now.Hour <= 4) + { + var last_time = DateTime.Parse(Class1.Config.delete_friend_lastTime); //最后一次时间 + var next_time = last_time.AddDays(Class1.Config.autocleanday); //下一次时间 + if (DateTime.Now > next_time) //如果时间已经过了 + { + Class1.Config.delete_friend_lastTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd 02:00:00")).AddMinutes(new Random().Next(0, 100)).ToString("yyyy-MM-dd HH:mm:ss"); + Util.Save(Class1.Config);//更新入库 + var wxBases = Chat.Framework.ChatClient.WXClient.Values.ToList().Where(f => f.WeixinType == WeixinType.Grpc微信 && f.Status == WxStatus.在线).ToList(); + if (wxBases != null && wxBases.Count > 0) + { + for (int i = 0; i < wxBases.Count; i++) + { + wxBases[i].RefreshContact(DeleteFriend); + if (IsRunning && wxBases.Count == (i + 1)) Thread.Sleep(2 * 60 * 1000); //3分钟刷新一个机器人 + } + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"清理专家:{ex.Message}"); + } + } + + private static string[] not_delete = new string[] { "fmessage", "floatbottle", "qmessage", "medianote", "qqmail", "weixin" }; + + /// + /// 获取非好友集合 + /// + /// + /// + public static List GetUnFriend(List> clients) + { + List unFriends = new List();//缓存 + try + { + foreach (var client in clients) + { + List friends = new List(); + if (client.Value.GetType() == typeof(WXClientImpl_IPAD)) + { + var ipad = client.Value as WXClientImpl_IPAD; + if (ipad == null || ipad.Friends == null) continue; + friends = ipad.Friends.Values.Where(f => string.IsNullOrEmpty(f.ChatRoomOwner) && !not_delete.Contains(f.UserName) && !string.IsNullOrEmpty(f.Ticket)).ToList(); + } + else if (client.Value.GetType() == typeof(WXClientImpl_HOOK)) + { + var hook = client.Value as WXClientImpl_HOOK; + if (hook == null || hook.Friends == null) continue; + friends = hook.Friends.Values.Where(f => !f.UserName.Contains("@") && !not_delete.Contains(f.UserName) && f.Ticket != "-1" && f.Ticket != "0").ToList(); + } + bool flag = true; + foreach (var item in friends) + { + unFriends.Add(new UnFriends(client.Value, item)); + } + } + } + catch (Exception) + { } + return unFriends; + } + + /// + /// 获取未互动好友集合 + /// + /// + /// + public static List GetNoInteractionFriend(List> clients, int day) + { + List unFriends = new List();//缓存 + var session = ApiClient.GetSession(); + foreach (var client in clients) + { + var ipad = client.Value as WXClientImpl_IPAD; + if (ipad == null || ipad.Friends == null) continue; + var notFriends = ipad.Friends.Values.Where(f => string.IsNullOrEmpty(f.ChatRoomOwner) && !not_delete.Contains(f.UserName) && string.IsNullOrEmpty(f.Ticket)).ToList(); + + var members = session.Find("upd_time <= @time", new { time = DateTime.Now.AddDays(-day) }); + + var NoInteractionFriends = notFriends.Where(a => members.Where(t => a.UserName == t.username).Any()).ToList(); // 方法2 + + foreach (var item in NoInteractionFriends) + { + unFriends.Add(new UnFriends(ipad, item)); + } + } + return unFriends; + } + + private void DeleteFriend(WXClientImpl_IPAD _ipad) + { + var ipad = _ipad; + Task.Run(() => + { + try + { + if (ipad.Status != WxStatus.在线) return; + var unFriends = ipad.Friends.Values.Where(f => string.IsNullOrEmpty(f.ChatRoomOwner) && !not_delete.Contains(f.UserName) && !string.IsNullOrEmpty(f.Ticket)).ToList(); + int number = 1; + StringBuilder sb = new StringBuilder("已自动清理僵尸粉:\r\n"); + var flag = true; + foreach (var item in unFriends) + { + if (ipad.Status != WxStatus.在线) break;//在线继续 + if (Class1.Config.cleanslimit == number) break;//数量限制 + + var member = ipad.GetContact(item.UserName, flag); + flag = false; + if (member != null && !string.IsNullOrEmpty(member.Ticket)) + { + ipad.DeleteFriend(item.UserName); + sb.AppendLine($"{item.GetName()}({item.UserName})-{item.Alias}"); + + Thread.Sleep(Class1.Config.cleansleep * 1000); + number++; + } + } + if (number > 0 && ipad.Status == WxStatus.在线) + ipad.SendMessage("filehelper", sb.ToString()); + } + catch (Exception) { } + }); + + } + } +} diff --git a/应用/CleaningTools/CleaningTools.csproj b/应用/CleaningTools/CleaningTools.csproj new file mode 100644 index 0000000..d2ebe2b --- /dev/null +++ b/应用/CleaningTools/CleaningTools.csproj @@ -0,0 +1,124 @@ + + + + + Debug + AnyCPU + {91A026DE-527F-4897-A1DC-01775E1CDD03} + Library + Properties + CleaningTools + CleaningTools + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/CleaningTools/Config.cs b/应用/CleaningTools/Config.cs new file mode 100644 index 0000000..57b5ddf --- /dev/null +++ b/应用/CleaningTools/Config.cs @@ -0,0 +1,82 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CleaningTools +{ + [Config(Name = "插件-清理专家-配置")] + public class Config + { + #region 缓存清理 + /// + /// 是否定时清理 + /// + public bool timing { get; set; } + + /// + /// 定时清理触发时间 + /// + public string timing_time { get; set; } + + #endregion + + #region 僵尸粉清理 + + /// + /// 是否开启自动清理死粉 + /// + public bool switch_delete_friend { get; set; } + + /// + /// 清理休眠僵尸粉时间(秒) + /// + public int cleansleep { get; set; } + + /// + /// 清理数量限制 + /// + public int cleanslimit { get; set; } + + /// + /// 自动清理僵尸粉的天数 + /// + public int autocleanday { get; set; } + + /// + /// 用于记录自动清理僵尸粉上次时间 + /// + public string delete_friend_lastTime { get; set; } + #endregion + + #region 清理pc端的微信聊天缓存 + + /// + /// 是否开启自动清理聊天记录 + /// + public bool isAutoClearChatMsg { get; set; } + + /// + /// 清理聊天记录的时间 + /// + public string clear_msg_time { get; set; } + + #endregion + + public Config() + { + this.isAutoClearChatMsg = false; + this.clear_msg_time = "01:30"; + this.timing = true; + this.timing_time = "02:30"; + this.cleansleep = 3; + this.cleanslimit = 50; + this.autocleanday = 7; + //保存为今天的2-4点钟某一刻 + this.delete_friend_lastTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd 02:00:00")).AddMinutes(new Random().Next(0, 120)).ToString("yyyy-MM-dd HH:mm:ss"); + } + + } +} diff --git a/应用/CleaningTools/Entity/UnFriends.cs b/应用/CleaningTools/Entity/UnFriends.cs new file mode 100644 index 0000000..3a345a9 --- /dev/null +++ b/应用/CleaningTools/Entity/UnFriends.cs @@ -0,0 +1,50 @@ +using Api.Framework.SDK; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CleaningTools.Entity +{ + /// + /// 非好友类 + /// + public class UnFriends + { + public Chat.Framework.WXSdk.Implement.WeixinBase Client { get; private set; } + public Chat.Framework.WXSdk.Friend Friend { get; private set; } + + public UnFriends(WeixinBase Client, Friend Friend) + { + this.Client = Client; + this.Friend = Friend; + } + + /// + /// 机器人微信号 + /// + public string weixinhao { get { return Client.WeixinHao; } } + /// + /// 机器人名称 + /// + public string robotnick { get { return Client.User.Nick; } } + /// + /// 微信id + /// + public string weixinid { get {return Friend.UserName; } } + + /// + /// 微信id + /// + public string usernick { get { return Friend.Remark; } } + + /// + /// 微信昵称 + /// + public string weixinnice { get { return Friend.NickName; } } + + } +} diff --git a/应用/CleaningTools/MainForm.Designer.cs b/应用/CleaningTools/MainForm.Designer.cs new file mode 100644 index 0000000..d25db9a --- /dev/null +++ b/应用/CleaningTools/MainForm.Designer.cs @@ -0,0 +1,1065 @@ +namespace CleaningTools +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tabPane1 = new DevExpress.XtraBars.Navigation.TabPane(); + this.tabNavigationPage2 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.tabNavigationPage1 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.label2 = new System.Windows.Forms.Label(); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.label1 = new System.Windows.Forms.Label(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.一键清理ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripComboBox1 = new System.Windows.Forms.ToolStripComboBox(); + this.点击更新ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.一键清理ToolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + this.tabNavigationPage3 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.label6 = new System.Windows.Forms.Label(); + this.numericUpDown4 = new System.Windows.Forms.NumericUpDown(); + this.label5 = new System.Windows.Forms.Label(); + this.progressBar5 = new System.Windows.Forms.ProgressBar(); + this.label4 = new System.Windows.Forms.Label(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.menuStrip2 = new System.Windows.Forms.MenuStrip(); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripComboBox2 = new System.Windows.Forms.ToolStripComboBox(); + this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripMenuItem(); + this.tabNavigationPage4 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.label10 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.checkBox5 = new System.Windows.Forms.CheckBox(); + this.checkBox4 = new System.Windows.Forms.CheckBox(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.button1 = new System.Windows.Forms.Button(); + this.tabNavigationPage5 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.dateTimePicker3 = new System.Windows.Forms.DateTimePicker(); + this.checkBox6 = new System.Windows.Forms.CheckBox(); + this.checkBox7 = new System.Windows.Forms.CheckBox(); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).BeginInit(); + this.tabPane1.SuspendLayout(); + this.tabNavigationPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + this.tabNavigationPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.menuStrip1.SuspendLayout(); + this.tabNavigationPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.menuStrip2.SuspendLayout(); + this.tabNavigationPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + this.tabNavigationPage5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + this.SuspendLayout(); + // + // tabPane1 + // + this.tabPane1.Controls.Add(this.tabNavigationPage2); + this.tabPane1.Controls.Add(this.tabNavigationPage1); + this.tabPane1.Controls.Add(this.tabNavigationPage3); + this.tabPane1.Controls.Add(this.tabNavigationPage4); + this.tabPane1.Controls.Add(this.tabNavigationPage5); + this.tabPane1.Location = new System.Drawing.Point(12, 12); + this.tabPane1.Name = "tabPane1"; + this.tabPane1.Pages.AddRange(new DevExpress.XtraBars.Navigation.NavigationPageBase[] { + this.tabNavigationPage1, + this.tabNavigationPage3, + this.tabNavigationPage2, + this.tabNavigationPage4, + this.tabNavigationPage5}); + this.tabPane1.RegularSize = new System.Drawing.Size(734, 430); + this.tabPane1.SelectedPage = this.tabNavigationPage1; + this.tabPane1.Size = new System.Drawing.Size(734, 430); + this.tabPane1.TabIndex = 0; + this.tabPane1.Text = "tabPane1"; + // + // tabNavigationPage2 + // + this.tabNavigationPage2.Caption = "自 动 清 理"; + this.tabNavigationPage2.Controls.Add(this.groupControl2); + this.tabNavigationPage2.Controls.Add(this.groupControl1); + this.tabNavigationPage2.Name = "tabNavigationPage2"; + this.tabNavigationPage2.Size = new System.Drawing.Size(734, 392); + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.labelControl5); + this.groupControl2.Controls.Add(this.labelControl3); + this.groupControl2.Controls.Add(this.numericUpDown3); + this.groupControl2.Controls.Add(this.labelControl1); + this.groupControl2.Controls.Add(this.numericUpDown2); + this.groupControl2.Controls.Add(this.labelControl4); + this.groupControl2.Controls.Add(this.numericUpDown1); + this.groupControl2.Controls.Add(this.checkBox3); + this.groupControl2.Location = new System.Drawing.Point(65, 47); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(599, 131); + this.groupControl2.TabIndex = 3; + this.groupControl2.Text = "微信好友清理"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(467, 92); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(48, 14); + this.labelControl5.TabIndex = 10; + this.labelControl5.Text = "个僵尸粉"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(289, 92); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(108, 14); + this.labelControl3.TabIndex = 9; + this.labelControl3.Text = "每次触发清理上限:"; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(403, 88); + this.numericUpDown3.Maximum = new decimal(new int[] { + 999999, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(58, 22); + this.numericUpDown3.TabIndex = 8; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(467, 47); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(24, 14); + this.labelControl1.TabIndex = 7; + this.labelControl1.Text = "秒钟"; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(403, 43); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(58, 22); + this.numericUpDown2.TabIndex = 6; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(171, 47); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(216, 14); + this.labelControl4.TabIndex = 5; + this.labelControl4.Text = "天,自动清理已删除好友,每删一个休眠"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(111, 43); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(54, 22); + this.numericUpDown1.TabIndex = 4; + // + // checkBox3 + // + this.checkBox3.AutoSize = true; + this.checkBox3.Location = new System.Drawing.Point(61, 45); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.Size = new System.Drawing.Size(50, 18); + this.checkBox3.TabIndex = 3; + this.checkBox3.Text = "每隔"; + this.checkBox3.UseVisualStyleBackColor = true; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Location = new System.Drawing.Point(65, 223); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(599, 111); + this.groupControl1.TabIndex = 2; + this.groupControl1.Text = "垃圾数据清理"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(481, 52); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 23); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = "立即清理"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(224, 56); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(249, 14); + this.labelControl2.TabIndex = 3; + this.labelControl2.Text = "自动清理Cache文件夹缓存数据,冗余数据等!"; + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "HH:mm"; + this.dateTimePicker1.Enabled = false; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(139, 53); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.ShowUpDown = true; + this.dateTimePicker1.Size = new System.Drawing.Size(68, 22); + this.dateTimePicker1.TabIndex = 2; + this.dateTimePicker1.Value = new System.DateTime(2019, 1, 27, 2, 30, 0, 0); + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(83, 55); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(50, 18); + this.checkBox1.TabIndex = 1; + this.checkBox1.Text = "每天"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // tabNavigationPage1 + // + this.tabNavigationPage1.Caption = "tabNavigationPage1"; + this.tabNavigationPage1.Controls.Add(this.label2); + this.tabNavigationPage1.Controls.Add(this.progressBar1); + this.tabNavigationPage1.Controls.Add(this.label1); + this.tabNavigationPage1.Controls.Add(this.gridControl1); + this.tabNavigationPage1.Controls.Add(this.menuStrip1); + this.tabNavigationPage1.Name = "tabNavigationPage1"; + this.tabNavigationPage1.PageText = "清 理 单 向 微 信 好 友"; + this.tabNavigationPage1.Size = new System.Drawing.Size(734, 392); + // + // label2 + // + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.ForeColor = System.Drawing.Color.Blue; + this.label2.Location = new System.Drawing.Point(187, 180); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(282, 24); + this.label2.TabIndex = 8; + this.label2.Text = "终止操作"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label2.Visible = false; + this.label2.Click += new System.EventHandler(this.label2_Click); + // + // progressBar1 + // + this.progressBar1.Location = new System.Drawing.Point(187, 154); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(282, 23); + this.progressBar1.TabIndex = 7; + this.progressBar1.Visible = false; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Location = new System.Drawing.Point(187, 127); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(282, 24); + this.label1.TabIndex = 6; + this.label1.Text = "label1"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label1.Visible = false; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 29); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(734, 354); + this.gridControl1.TabIndex = 5; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn5, + this.gridColumn9, + this.gridColumn3}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 48; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomDrawRowIndicator += new DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventHandler(this.gridView1_CustomDrawRowIndicator); + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "微信号"; + this.gridColumn1.FieldName = "weixinhao"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 80; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "机器人昵称"; + this.gridColumn2.FieldName = "robotnick"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 110; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "用户微信昵称"; + this.gridColumn5.FieldName = "weixinnice"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 146; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.gridColumn9.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn9.AppearanceCell.Options.UseFont = true; + this.gridColumn9.AppearanceCell.Options.UseForeColor = true; + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn9.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "用户微信备注"; + this.gridColumn9.FieldName = "usernick"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 3; + this.gridColumn9.Width = 119; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "用户微信Id"; + this.gridColumn3.FieldName = "weixinid"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 4; + this.gridColumn3.Width = 167; + // + // menuStrip1 + // + this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.一键清理ToolStripMenuItem, + this.toolStripComboBox1, + this.点击更新ToolStripMenuItem, + this.toolStripMenuItem1, + this.一键清理ToolStripMenuItem2}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(734, 29); + this.menuStrip1.TabIndex = 0; + this.menuStrip1.Text = "menuStrip1"; + // + // 一键清理ToolStripMenuItem + // + this.一键清理ToolStripMenuItem.Name = "一键清理ToolStripMenuItem"; + this.一键清理ToolStripMenuItem.Size = new System.Drawing.Size(68, 25); + this.一键清理ToolStripMenuItem.Text = "请选择:"; + // + // toolStripComboBox1 + // + this.toolStripComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.toolStripComboBox1.DropDownWidth = 230; + this.toolStripComboBox1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.toolStripComboBox1.Name = "toolStripComboBox1"; + this.toolStripComboBox1.Size = new System.Drawing.Size(230, 25); + this.toolStripComboBox1.SelectedIndexChanged += new System.EventHandler(this.toolStripComboBox1_SelectedIndexChanged); + // + // 点击更新ToolStripMenuItem + // + this.点击更新ToolStripMenuItem.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.点击更新ToolStripMenuItem.ForeColor = System.Drawing.Color.Blue; + this.点击更新ToolStripMenuItem.Name = "点击更新ToolStripMenuItem"; + this.点击更新ToolStripMenuItem.Size = new System.Drawing.Size(100, 25); + this.点击更新ToolStripMenuItem.Text = " 刷 新 通 讯 录"; + this.点击更新ToolStripMenuItem.Click += new System.EventHandler(this.点击更新ToolStripMenuItem_Click); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(23, 25); + this.toolStripMenuItem1.Text = "|"; + // + // 一键清理ToolStripMenuItem2 + // + this.一键清理ToolStripMenuItem2.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.一键清理ToolStripMenuItem2.ForeColor = System.Drawing.Color.Blue; + this.一键清理ToolStripMenuItem2.Name = "一键清理ToolStripMenuItem2"; + this.一键清理ToolStripMenuItem2.Size = new System.Drawing.Size(112, 25); + this.一键清理ToolStripMenuItem2.Text = "删 除 下 方 好 友"; + this.一键清理ToolStripMenuItem2.Click += new System.EventHandler(this.一键清理ToolStripMenuItem2_Click); + // + // tabNavigationPage3 + // + this.tabNavigationPage3.Caption = "清 理 长 期 未 交 互 好 友"; + this.tabNavigationPage3.Controls.Add(this.labelControl6); + this.tabNavigationPage3.Controls.Add(this.label6); + this.tabNavigationPage3.Controls.Add(this.numericUpDown4); + this.tabNavigationPage3.Controls.Add(this.label5); + this.tabNavigationPage3.Controls.Add(this.progressBar5); + this.tabNavigationPage3.Controls.Add(this.label4); + this.tabNavigationPage3.Controls.Add(this.gridControl2); + this.tabNavigationPage3.Controls.Add(this.menuStrip2); + this.tabNavigationPage3.Name = "tabNavigationPage3"; + this.tabNavigationPage3.Size = new System.Drawing.Size(734, 392); + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(597, 14); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(48, 14); + this.labelControl6.TabIndex = 14; + this.labelControl6.Text = "天未交涉"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(545, 14); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(0, 14); + this.label6.TabIndex = 13; + // + // numericUpDown4 + // + this.numericUpDown4.Location = new System.Drawing.Point(536, 10); + this.numericUpDown4.Maximum = new decimal(new int[] { + 4000, + 0, + 0, + 0}); + this.numericUpDown4.Name = "numericUpDown4"; + this.numericUpDown4.Size = new System.Drawing.Size(55, 22); + this.numericUpDown4.TabIndex = 12; + this.numericUpDown4.Value = new decimal(new int[] { + 30, + 0, + 0, + 0}); + this.numericUpDown4.ValueChanged += new System.EventHandler(this.numericUpDown4_ValueChanged); + // + // label5 + // + this.label5.BackColor = System.Drawing.Color.White; + this.label5.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label5.ForeColor = System.Drawing.Color.Blue; + this.label5.Location = new System.Drawing.Point(201, 188); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(282, 24); + this.label5.TabIndex = 11; + this.label5.Text = "终止操作"; + this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label5.Visible = false; + this.label5.Click += new System.EventHandler(this.label5_Click); + // + // progressBar5 + // + this.progressBar5.Location = new System.Drawing.Point(201, 162); + this.progressBar5.Name = "progressBar5"; + this.progressBar5.Size = new System.Drawing.Size(282, 23); + this.progressBar5.TabIndex = 10; + this.progressBar5.Visible = false; + // + // label4 + // + this.label4.BackColor = System.Drawing.Color.White; + this.label4.Location = new System.Drawing.Point(201, 135); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(282, 24); + this.label4.TabIndex = 9; + this.label4.Text = "label4"; + this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.label4.Visible = false; + // + // gridControl2 + // + this.gridControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.gridControl2.Location = new System.Drawing.Point(0, 63); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(734, 329); + this.gridControl2.TabIndex = 7; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn4, + this.gridColumn6, + this.gridColumn7, + this.gridColumn10, + this.gridColumn8}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.IndicatorWidth = 48; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.CustomDrawRowIndicator += new DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventHandler(this.gridView2_CustomDrawRowIndicator); + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "微信号"; + this.gridColumn4.FieldName = "weixinhao"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 0; + this.gridColumn4.Width = 110; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "机器人昵称"; + this.gridColumn6.FieldName = "robotnick"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 1; + this.gridColumn6.Width = 170; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "用户微信昵称"; + this.gridColumn7.FieldName = "weixinnice"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 2; + this.gridColumn7.Width = 170; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.gridColumn10.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn10.AppearanceCell.Options.UseFont = true; + this.gridColumn10.AppearanceCell.Options.UseForeColor = true; + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn10.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "用户微信备注"; + this.gridColumn10.FieldName = "usernick"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 3; + this.gridColumn10.Width = 138; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "用户微信Id"; + this.gridColumn8.FieldName = "weixinid"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 4; + this.gridColumn8.Width = 150; + // + // menuStrip2 + // + this.menuStrip2.Dock = System.Windows.Forms.DockStyle.None; + this.menuStrip2.ImageScalingSize = new System.Drawing.Size(20, 20); + this.menuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem2, + this.toolStripComboBox2, + this.toolStripMenuItem3, + this.toolStripMenuItem4, + this.toolStripMenuItem5, + this.toolStripMenuItem6}); + this.menuStrip2.Location = new System.Drawing.Point(3, 7); + this.menuStrip2.Name = "menuStrip2"; + this.menuStrip2.Size = new System.Drawing.Size(530, 29); + this.menuStrip2.TabIndex = 6; + this.menuStrip2.Text = "menuStrip2"; + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size(68, 25); + this.toolStripMenuItem2.Text = "请选择:"; + // + // toolStripComboBox2 + // + this.toolStripComboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.toolStripComboBox2.DropDownWidth = 230; + this.toolStripComboBox2.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.toolStripComboBox2.Name = "toolStripComboBox2"; + this.toolStripComboBox2.Size = new System.Drawing.Size(230, 25); + this.toolStripComboBox2.SelectedIndexChanged += new System.EventHandler(this.toolStripComboBox2_SelectedIndexChanged); + // + // toolStripMenuItem3 + // + this.toolStripMenuItem3.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.toolStripMenuItem3.ForeColor = System.Drawing.Color.Blue; + this.toolStripMenuItem3.Name = "toolStripMenuItem3"; + this.toolStripMenuItem3.Size = new System.Drawing.Size(84, 25); + this.toolStripMenuItem3.Text = " 刷新通讯录"; + this.toolStripMenuItem3.Click += new System.EventHandler(this.点击更新ToolStripMenuItem1_Click); + // + // toolStripMenuItem4 + // + this.toolStripMenuItem4.Name = "toolStripMenuItem4"; + this.toolStripMenuItem4.Size = new System.Drawing.Size(23, 25); + this.toolStripMenuItem4.Text = "|"; + // + // toolStripMenuItem5 + // + this.toolStripMenuItem5.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.toolStripMenuItem5.ForeColor = System.Drawing.Color.Blue; + this.toolStripMenuItem5.Name = "toolStripMenuItem5"; + this.toolStripMenuItem5.Size = new System.Drawing.Size(92, 25); + this.toolStripMenuItem5.Text = "删除下方好友"; + this.toolStripMenuItem5.Click += new System.EventHandler(this.toolStripMenuItem5_Click); + // + // toolStripMenuItem6 + // + this.toolStripMenuItem6.Name = "toolStripMenuItem6"; + this.toolStripMenuItem6.Size = new System.Drawing.Size(23, 25); + this.toolStripMenuItem6.Text = "|"; + // + // tabNavigationPage4 + // + this.tabNavigationPage4.Caption = "清 理 联 盟 历 史 订 单"; + this.tabNavigationPage4.Controls.Add(this.groupControl3); + this.tabNavigationPage4.Name = "tabNavigationPage4"; + this.tabNavigationPage4.Size = new System.Drawing.Size(734, 392); + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.checkBox7); + this.groupControl3.Controls.Add(this.separatorControl1); + this.groupControl3.Controls.Add(this.label10); + this.groupControl3.Controls.Add(this.label9); + this.groupControl3.Controls.Add(this.dateTimePicker2); + this.groupControl3.Controls.Add(this.label8); + this.groupControl3.Controls.Add(this.label7); + this.groupControl3.Controls.Add(this.label3); + this.groupControl3.Controls.Add(this.checkBox5); + this.groupControl3.Controls.Add(this.checkBox4); + this.groupControl3.Controls.Add(this.checkBox2); + this.groupControl3.Controls.Add(this.button1); + this.groupControl3.Location = new System.Drawing.Point(42, 29); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(652, 344); + this.groupControl3.TabIndex = 4; + this.groupControl3.Text = "清理联盟历史订单"; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(3, 134); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(647, 23); + this.separatorControl1.TabIndex = 7; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Font = new System.Drawing.Font("Tahoma", 15F, System.Drawing.FontStyle.Bold); + this.label10.ForeColor = System.Drawing.Color.Red; + this.label10.Location = new System.Drawing.Point(37, 57); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(493, 72); + this.label10.TabIndex = 6; + this.label10.Text = "数据无价,请决定要删除历史订单后在进行以下操作\r\n\r\n时间不要选错... 时间不要选错... 时间不要选错..."; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Font = new System.Drawing.Font("Tahoma", 11F, System.Drawing.FontStyle.Bold); + this.label9.ForeColor = System.Drawing.Color.Red; + this.label9.Location = new System.Drawing.Point(37, 35); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(184, 18); + this.label9.TabIndex = 6; + this.label9.Text = "删除之前请看清楚说明:"; + // + // dateTimePicker2 + // + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(177, 222); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(169, 22); + this.dateTimePicker2.TabIndex = 5; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Font = new System.Drawing.Font("Tahoma", 9F); + this.label8.ForeColor = System.Drawing.Color.Red; + this.label8.Location = new System.Drawing.Point(350, 226); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(247, 14); + this.label8.TabIndex = 4; + this.label8.Text = "(注:清理的时间为删除该时间之前的订单)"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Font = new System.Drawing.Font("Tahoma", 11F); + this.label7.ForeColor = System.Drawing.Color.Blue; + this.label7.Location = new System.Drawing.Point(15, 224); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(158, 18); + this.label7.TabIndex = 4; + this.label7.Text = "二、设置清理的时间:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Font = new System.Drawing.Font("Tahoma", 11F); + this.label3.ForeColor = System.Drawing.Color.Blue; + this.label3.Location = new System.Drawing.Point(15, 161); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(158, 18); + this.label3.TabIndex = 4; + this.label3.Text = "一、选择清理的联盟:"; + // + // checkBox5 + // + this.checkBox5.AutoSize = true; + this.checkBox5.Location = new System.Drawing.Point(341, 188); + this.checkBox5.Name = "checkBox5"; + this.checkBox5.Size = new System.Drawing.Size(134, 18); + this.checkBox5.TabIndex = 3; + this.checkBox5.Text = "清理拼多多历史订单"; + this.checkBox5.UseVisualStyleBackColor = true; + // + // checkBox4 + // + this.checkBox4.AutoSize = true; + this.checkBox4.Location = new System.Drawing.Point(196, 188); + this.checkBox4.Name = "checkBox4"; + this.checkBox4.Size = new System.Drawing.Size(122, 18); + this.checkBox4.TabIndex = 2; + this.checkBox4.Text = "清理京东历史订单"; + this.checkBox4.UseVisualStyleBackColor = true; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(51, 188); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(122, 18); + this.checkBox2.TabIndex = 1; + this.checkBox2.Text = "清理淘宝历史订单"; + this.checkBox2.UseVisualStyleBackColor = true; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(210, 268); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(225, 40); + this.button1.TabIndex = 0; + this.button1.Text = " 开 始 删 除 历 史 订 单 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // tabNavigationPage5 + // + this.tabNavigationPage5.Caption = "Pc微 信 清 理 聊 天 记 录"; + this.tabNavigationPage5.Controls.Add(this.groupControl4); + this.tabNavigationPage5.Name = "tabNavigationPage5"; + this.tabNavigationPage5.Size = new System.Drawing.Size(734, 392); + // + // groupControl4 + // + this.groupControl4.Controls.Add(this.simpleButton2); + this.groupControl4.Controls.Add(this.labelControl7); + this.groupControl4.Controls.Add(this.dateTimePicker3); + this.groupControl4.Controls.Add(this.checkBox6); + this.groupControl4.Location = new System.Drawing.Point(68, 98); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(599, 174); + this.groupControl4.TabIndex = 5; + this.groupControl4.Text = "定时清理PC微信历史聊天记录"; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(412, 71); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(116, 45); + this.simpleButton2.TabIndex = 5; + this.simpleButton2.Text = "立即清理"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(245, 85); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(137, 14); + this.labelControl7.TabIndex = 3; + this.labelControl7.Text = "自动清理Pc微信聊天记录!"; + // + // dateTimePicker3 + // + this.dateTimePicker3.CustomFormat = "HH:mm"; + this.dateTimePicker3.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker3.Location = new System.Drawing.Point(171, 82); + this.dateTimePicker3.Name = "dateTimePicker3"; + this.dateTimePicker3.ShowUpDown = true; + this.dateTimePicker3.Size = new System.Drawing.Size(68, 22); + this.dateTimePicker3.TabIndex = 2; + this.dateTimePicker3.Value = new System.DateTime(2019, 1, 27, 1, 30, 0, 0); + // + // checkBox6 + // + this.checkBox6.AutoSize = true; + this.checkBox6.Location = new System.Drawing.Point(115, 85); + this.checkBox6.Name = "checkBox6"; + this.checkBox6.Size = new System.Drawing.Size(50, 18); + this.checkBox6.TabIndex = 1; + this.checkBox6.Text = "每天"; + this.checkBox6.UseVisualStyleBackColor = true; + // + // checkBox7 + // + this.checkBox7.AutoSize = true; + this.checkBox7.Location = new System.Drawing.Point(498, 188); + this.checkBox7.Name = "checkBox7"; + this.checkBox7.Size = new System.Drawing.Size(134, 18); + this.checkBox7.TabIndex = 8; + this.checkBox7.Text = "清理唯品会历史订单"; + this.checkBox7.UseVisualStyleBackColor = true; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(758, 454); + this.Controls.Add(this.tabPane1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MainMenuStrip = this.menuStrip1; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).EndInit(); + this.tabPane1.ResumeLayout(false); + this.tabNavigationPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + this.tabNavigationPage1.ResumeLayout(false); + this.tabNavigationPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.tabNavigationPage3.ResumeLayout(false); + this.tabNavigationPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.menuStrip2.ResumeLayout(false); + this.menuStrip2.PerformLayout(); + this.tabNavigationPage4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + this.groupControl3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + this.tabNavigationPage5.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + this.groupControl4.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraBars.Navigation.TabPane tabPane1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage2; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.CheckBox checkBox1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem 一键清理ToolStripMenuItem; + private System.Windows.Forms.ToolStripComboBox toolStripComboBox1; + private System.Windows.Forms.ToolStripMenuItem 点击更新ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 一键清理ToolStripMenuItem2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.CheckBox checkBox3; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage3; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private System.Windows.Forms.MenuStrip menuStrip2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2; + private System.Windows.Forms.ToolStripComboBox toolStripComboBox2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem3; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem4; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem5; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.ProgressBar progressBar5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.NumericUpDown numericUpDown4; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage4; + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.CheckBox checkBox5; + private System.Windows.Forms.CheckBox checkBox4; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage5; + private DevExpress.XtraEditors.GroupControl groupControl4; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.LabelControl labelControl7; + private System.Windows.Forms.DateTimePicker dateTimePicker3; + private System.Windows.Forms.CheckBox checkBox6; + private System.Windows.Forms.CheckBox checkBox7; + } +} \ No newline at end of file diff --git a/应用/CleaningTools/MainForm.cs b/应用/CleaningTools/MainForm.cs new file mode 100644 index 0000000..c39d65c --- /dev/null +++ b/应用/CleaningTools/MainForm.cs @@ -0,0 +1,742 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CleaningTools.Entity; +using CleaningTools.Properties; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.Utils.Extensions; +using UI.Framework.Forms; + +namespace CleaningTools +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + + + toolStripComboBox1.Items.Clear(); + dateTimePicker1.Value = DateTime.Parse(Class1.Config.timing_time); + + #region 加载下拉框 + toolStripComboBox1.Items.Add($"选择机器人"); + toolStripComboBox1.Items.Add($"全部机器人"); + + toolStripComboBox2.Items.Add($"选择机器人"); + toolStripComboBox2.Items.Add($"全部机器人"); + toolStripComboBox1.SelectedIndex = toolStripComboBox2.SelectedIndex = 0; + + Dictionary dicstr = new Dictionary(); + var clients = Chat.Framework.ChatClient.WXClient; + foreach (var item in clients) + { + if ((item.Value.WeixinType == WeixinType.Grpc微信 || item.Value.WeixinType == WeixinType.Hook微信) && item.Value.Status == WxStatus.在线) + { + dicstr.Add(toolStripComboBox1.Items.Count, item.Value.WeixinHao); + toolStripComboBox1.Items.Add($"{item.Value.User.Nick}({item.Value.WeixinHao})"); + toolStripComboBox2.Items.Add($"{item.Value.User.Nick}({item.Value.WeixinHao})"); + } + } + toolStripComboBox1.Tag = toolStripComboBox2.Tag = dicstr; + #endregion + + this.checkBox3.Checked = Class1.Config.switch_delete_friend; + this.checkBox1.Checked = Class1.Config.timing; + this.numericUpDown1.Value = Class1.Config.autocleanday; + this.numericUpDown2.Value = Class1.Config.cleansleep; + this.numericUpDown3.Value = Class1.Config.cleanslimit; + + this.dateTimePicker3.Value = DateTime.Parse(Class1.Config.clear_msg_time); + this.checkBox6.Checked = Class1.Config.isAutoClearChatMsg; + + this.dateTimePicker2.Value = DateTime.Now.Date.AddMonths(-10); + + simpleButton2.Enabled = !isRunFlag; + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 缓存目录文件删除 + /// + /// + /// + private void simpleButton1_Click(object sender, EventArgs e) + { + Loding.ShowWaitForm(); + ThreadPool.QueueUserWorkItem(f => + { + try + { + var tools = new Tools(); + var cachePath = Util.MapPath(Util.MapPath(@"Cache")); + if (Directory.Exists(cachePath)) + { + tools.DelectDir(cachePath); + } + cachePath = Util.MapPath(Util.MapPath(@"Assembly\apifile")); + if (Directory.Exists(cachePath)) + { + tools.DelectDir(cachePath, true); + } + + //清理超过7天的加人数据 + var session = ApiClient.GetSession(); + if (session.TableExist("fl_plugin_userfission_applyfriend_info")) session.ExcuteSQL("delete from fl_plugin_userfission_applyfriend_info where crt_time <= @crttime", new { crttime = DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd HH:mm:ss") }); + + //清理问答7天未响应数据 + if (session.TableExist("fl_plugin_autoanswer__log")) session.ExcuteSQL("delete from fl_plugin_autoanswer__log where datetime <= @crttime", new { crttime = DateTime.Now.AddDays(-4).ToString("yyyy-MM-dd HH:mm:ss") }); + + //清理聊天记录3天之前的 + if (session.TableExist("fl_plugin_messagesupervises_messinfo")) session.ExcuteSQL("delete from fl_plugin_messagesupervises_messinfo where send_time <= @time", new { time = DateTime.Now.AddDays(-3) }); + + //清理查询记录7天前的所有记录 + if (session.TableExist("fl_query_hist")) session.ExcuteSQL("delete from fl_query_hist where crt_time <= @time", new { time = DateTime.Now.Date.AddDays(-7).ToString("yyyy-MM-dd HH:mm:ss") }); + + //清理Debug调试数据 + if (session.TableExist("fl_debug_log")) session.ExcuteSQL("delete from fl_debug_log where crt_time <= @crt_time", new { crt_time = DateTime.Now.AddDays(-1) }); + + ShowSuccessAutoClose("清理完成!"); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + ShowErrorAutoClose(ex); + })); + } + finally + { + try + { + this.Invoke(new Action(delegate + { + Loding.CloseWaitForm(); + })); + } + catch (Exception) + { } + } + }); + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.switch_delete_friend = this.checkBox3.Checked; + Class1.Config.timing = this.checkBox1.Checked; + Class1.Config.autocleanday = (int)this.numericUpDown1.Value; + Class1.Config.cleansleep = (int)this.numericUpDown2.Value; + Class1.Config.cleanslimit = (int)this.numericUpDown3.Value; + + Class1.Config.clear_msg_time = dateTimePicker3.Value.ToString("HH:mm"); + Class1.Config.isAutoClearChatMsg = checkBox6.Checked; + + Util.Save(Class1.Config); + } + catch (Exception) + { } + } + + #region + /// + /// 清粉之选机器人账号改变按钮状态 + /// + /// + /// + private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + if (toolStripComboBox1.SelectedIndex == 0) + { + 点击更新ToolStripMenuItem.Enabled = false; + 点击更新ToolStripMenuItem.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F); + 点击更新ToolStripMenuItem.ForeColor = System.Drawing.Color.FromArgb(64, 64, 64); + this.gridControl1.DataSource = null;//清空数据 + } + else + { + 点击更新ToolStripMenuItem.Enabled = true; + 点击更新ToolStripMenuItem.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Underline); + 点击更新ToolStripMenuItem.ForeColor = System.Drawing.Color.Blue; + + List> clients = null; + if (toolStripComboBox1.SelectedIndex == 1) clients = Chat.Framework.ChatClient.WXClient.Where(f => (f.Value.WeixinType == WeixinType.Grpc微信 || f.Value.WeixinType == WeixinType.Hook微信) && f.Value.Status == WxStatus.在线).ToList(); + else + { + var dicstr = toolStripComboBox1.Tag as Dictionary; + var weixinHao = dicstr[toolStripComboBox1.SelectedIndex]; + clients = Chat.Framework.ChatClient.WXClient.Where(f => f.Value.WeixinHao == weixinHao && (f.Value.WeixinType == WeixinType.Grpc微信 || f.Value.WeixinType == WeixinType.Hook微信) && f.Value.Status == WxStatus.在线).ToList(); + } + if (clients != null && clients.Count > 0) gridControl1.DataSource = CleaningThread.GetUnFriend(clients);//展示数据 + } + } + + + /// + /// 机器人好友僵尸粉列表(展示) + /// + /// + /// + private void 点击更新ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + Loding.ShowWaitForm();//开启等待 + _SetControlEnabled(false); + + List> clients = null; + if (toolStripComboBox1.SelectedIndex == 0)//还未选择 + throw new Exception("请选择要清理的机器人账号"); + else if (toolStripComboBox1.SelectedIndex == 1)//全部机器人的僵尸粉 + clients = Chat.Framework.ChatClient.WXClient.Where(f => (f.Value.WeixinType == WeixinType.Grpc微信 || f.Value.WeixinType == WeixinType.Hook微信) && f.Value.Status == WxStatus.在线).ToList(); + else//个体 + { + var dicstr = toolStripComboBox1.Tag as Dictionary; + var weixinHao = dicstr[toolStripComboBox1.SelectedIndex]; + + clients = Chat.Framework.ChatClient.WXClient.Where(f => f.Value.WeixinHao == weixinHao && (f.Value.WeixinType == WeixinType.Grpc微信 || f.Value.WeixinType == WeixinType.Hook微信) && f.Value.Status == WxStatus.在线).ToList(); + } + if (clients != null && clients.Count != 0) + { + foreach (var item in clients) + { + if (item.Value.GetType() == typeof(WXClientImpl_IPAD)) + { + var wx = item.Value as WXClientImpl_IPAD; + if (item.Value.Status == WxStatus.在线 && !wx.IsRefreshContact) + item.Value.RefreshContact(); + } + else if (item.Value.GetType() == typeof(WXClientImpl_HOOK)) + { + var wx = item.Value as WXClientImpl_HOOK; + wx.GetZombie(); + } + + } + ShowSuccess("已启动任务缓慢刷新通讯录,耗时可能较长!"); + } + else + throw new Exception("没有在线的微信号,或者没有符合的微信号"); + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + _SetControlEnabled(true); + Loding.CloseWaitForm();//关闭等待 + } + } + + /// + /// 设置控件的交互状态 + /// + /// + private void _SetControlEnabled(bool flag = false) + { + foreach (var item in menuStrip1.Items) + { + if (item is ToolStripTextBox) + (item as ToolStripTextBox).Enabled = flag; + else if (item is ToolStripMenuItem) + (item as ToolStripMenuItem).Enabled = flag; + else if (item is ToolStripComboBox) + (item as ToolStripComboBox).Enabled = flag; + } + } + #endregion + + + private string[] not_delete = new string[] { "fmessage", "floatbottle" }; + + private bool delete_ing = false; + private void DeleteIng(int count = 0) + { + if (count == 0) + { + delete_ing = false; + toolStripComboBox1.Enabled = 点击更新ToolStripMenuItem.Enabled = 一键清理ToolStripMenuItem2.Enabled = true; + label2.Visible = this.label1.Visible = this.progressBar1.Visible = false; + gridControl1.DataSource = new List(); + } + else + { + toolStripComboBox1.Enabled = 点击更新ToolStripMenuItem.Enabled = 一键清理ToolStripMenuItem2.Enabled = false; + delete_ing = true; + this.label1.Text = "准备就绪"; + this.progressBar1.Maximum = count; + this.progressBar1.Value = 0; + label2.Visible = this.label1.Visible = this.progressBar1.Visible = true; + } + } + + Thread delete_thread = null; + /// + /// 一键清理僵尸粉 + /// + /// + /// + private void 一键清理ToolStripMenuItem2_Click(object sender, EventArgs e) + { + try + { + if (delete_thread != null && delete_thread.IsAlive) throw new Exception("当前已经有线程正在执行清理操作,请稍后!"); + var unFriends = this.gridView1.DataSource as List; + if (unFriends == null || unFriends.Count == 0) throw new Exception("当前列表中,没有可清理数据!"); + + //初始化删除操作 + DeleteIng(unFriends.Count); + + //启动线程去执行删除 + delete_thread = new Thread(new ThreadStart(delegate + { + try + { + int number = 0; + do + { + if (!delete_ing) return;//便于做终止操作,防止卡死 + var item = unFriends.FirstOrDefault();//取出默认数据 + if (item == null) break;//没有数据了 + try + { + var wxBase = item.Client; //获取对应的微信对象 + if (wxBase.Status == WxStatus.在线) + { + number++; + var result = wxBase.DeleteFriend(item.Friend.UserName);//删除 + this.Invoke(new Action(delegate + { + this.label1.Text = string.Format("删除第{0}位:{1}={2}", number, item.weixinnice, string.IsNullOrEmpty(result) ? "成功" : result); + this.progressBar1.Value++; + Application.DoEvents();//不卡界面刷新 + })); //更新进度条 + Thread.Sleep(Class1.Config.cleansleep * 1000); + } + if (wxBase.GetType() == typeof(WXClientImpl_HOOK)) + { + var hook = wxBase as WXClientImpl_HOOK; + hook.Friends.Remove(item.Friend.UserName); + } + } + catch { } + unFriends.Remove(item);//不管是否删除成功,移除列表数据 + } while (true); + } + catch (Exception) { } + finally + { + this.Invoke(new Action(delegate + { + ShowSuccess("删除好友完成!"); + DeleteIng(); + })); + } + })); + delete_thread.IsBackground = true; + delete_thread.Start(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// gridviwe 增加标识列 + /// + /// + /// + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + + /// + /// 僵尸粉清理之休眠时间,自动清理天数,输入限制(只能为数字) + /// + /// + /// + private void toolStripTextBox_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar != '\b')//这是允许输入退格键 + { + if ((e.KeyChar < '0') || (e.KeyChar > '9'))//这是允许输入0-9数字 + { + e.Handled = true; + } + } + } + + private void label2_Click(object sender, EventArgs e) + { + try + { + //传0表示终止 + DeleteIng(); + + //强制销毁 + if (delete_thread != null) delete_thread.Abort(); + } + catch (Exception) { } + delete_thread = null; + } + + /// + /// 清粉之选机器人账号改变按钮状态 - 未交互的用户 + /// + /// + /// + private void toolStripComboBox2_SelectedIndexChanged(object sender, EventArgs e) + { + if (toolStripComboBox2.SelectedIndex == 0) + { + toolStripMenuItem3.Enabled = false; + toolStripMenuItem3.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F); + toolStripMenuItem3.ForeColor = System.Drawing.Color.FromArgb(64, 64, 64); + this.gridControl2.DataSource = null;//清空数据 + } + else + { + toolStripMenuItem3.Enabled = true; + toolStripMenuItem3.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F, System.Drawing.FontStyle.Underline); + toolStripMenuItem3.ForeColor = System.Drawing.Color.Blue; + + List> clients = null; + if (toolStripComboBox2.SelectedIndex == 1) clients = Chat.Framework.ChatClient.WXClient.Where(f => f.Value.WeixinType == WeixinType.Grpc微信 && f.Value.Status == WxStatus.在线).ToList(); + else + { + var dicstr = toolStripComboBox2.Tag as Dictionary; + var weixinHao = dicstr[toolStripComboBox2.SelectedIndex]; + clients = Chat.Framework.ChatClient.WXClient.Where(f => f.Value.WeixinHao == weixinHao && f.Value.WeixinType == WeixinType.Grpc微信 && f.Value.Status == WxStatus.在线).ToList(); + } + if (clients != null && clients.Count > 0) gridControl2.DataSource = CleaningThread.GetNoInteractionFriend(clients, (int)numericUpDown4.Value);//展示数据 + } + } + + //?? + private void label5_Click(object sender, EventArgs e) + { + try + { + //传0表示终止 + DeleteIng(); + + //强制销毁 + if (delete_thread != null) delete_thread.Abort(); + } + catch (Exception) { } + delete_thread = null; + } + + private void gridView2_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void numericUpDown4_ValueChanged(object sender, EventArgs e) + { + toolStripComboBox2_SelectedIndexChanged(null, null); + } + + private void 点击更新ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + Loding.ShowWaitForm();//开启等待 + _SetControlEnabled(false); + + List> clients = null; + if (toolStripComboBox2.SelectedIndex == 0)//还未选择 + throw new Exception("请选择要清理的机器人账号"); + else if (toolStripComboBox2.SelectedIndex == 1)//全部机器人的僵尸粉 + { + clients = Chat.Framework.ChatClient.WXClient.Where(f => f.Value.WeixinType == WeixinType.Grpc微信 && f.Value.Status == WxStatus.在线).ToList(); + } + else//个体 + { + var dicstr = toolStripComboBox2.Tag as Dictionary; + var weixinHao = dicstr[toolStripComboBox2.SelectedIndex]; + clients = Chat.Framework.ChatClient.WXClient.Where(f => f.Value.WeixinHao == weixinHao && f.Value.WeixinType == WeixinType.Grpc微信 && f.Value.Status == WxStatus.在线).ToList(); + } + if (clients != null && clients.Count != 0) + { + foreach (var item in clients) + { + var ipad = item.Value as WXClientImpl_IPAD; + if (ipad.Status == WxStatus.在线 && !ipad.IsRefreshContact) + { + ipad.RefreshContact(); + } + } + ShowSuccess("已启动任务缓慢刷新通讯录,耗时可能较长!"); + } + else + throw new Exception("没有在线的微信号,或者没有符合的微信号"); + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + _SetControlEnabled(true); + Loding.CloseWaitForm();//关闭等待 + } + } + + + private bool delete_ing2 = false; + private void DeleteIng2(int count = 0) + { + if (count == 0) + { + delete_ing2 = false; + toolStripComboBox2.Enabled = toolStripMenuItem3.Enabled = toolStripMenuItem5.Enabled = true; + label5.Visible = this.label4.Visible = this.progressBar5.Visible = false; + gridControl2.DataSource = new List(); + } + else + { + toolStripComboBox2.Enabled = toolStripMenuItem3.Enabled = toolStripMenuItem5.Enabled = false; + delete_ing2 = true; + this.label4.Text = "准备就绪"; + this.progressBar5.Maximum = count; + this.progressBar5.Value = 0; + label5.Visible = this.label4.Visible = this.progressBar5.Visible = true; + } + } + + private void toolStripMenuItem5_Click(object sender, EventArgs e) + { + try + { + if (delete_thread != null && delete_thread.IsAlive) throw new Exception("当前已经有线程正在执行清理操作,请稍后!"); + var unFriends = this.gridView2.DataSource as List; + if (unFriends == null || unFriends.Count == 0) throw new Exception("当前列表中,没有可清理数据!"); + + //初始化删除操作 + DeleteIng(unFriends.Count); + + //启动线程去执行删除 + delete_thread = new Thread(new ThreadStart(delegate + { + try + { + int number = 0; + + do + { + if (!delete_ing) return;//便于做终止操作,防止卡死 + var item = unFriends.FirstOrDefault();//取出默认数据 + if (item == null) break;//没有数据了 + try + { + var wxBase = item.Client; //获取对应的微信对象 + if (wxBase.Status == WxStatus.在线) + { + number++; + var result = wxBase.DeleteFriend(item.Friend.UserName);//删除 + this.Invoke(new Action(delegate + { + this.label4.Text = string.Format("删除第{0}位:{1}={2}", number, item.weixinnice, string.IsNullOrEmpty(result) ? "成功" : result); + this.progressBar5.Value++; + + System.Windows.Forms.Application.DoEvents();//不卡界面刷新 + })); //更新进度条 + Thread.Sleep(Class1.Config.cleansleep * 1000); + } + } + catch { } + unFriends.Remove(item);//不管是否删除成功,移除列表数据 + } while (true); + } + catch (Exception) { } + finally + { + this.Invoke(new Action(delegate + { + ShowSuccess("删除好友完成!"); + DeleteIng(); + })); + } + })); + delete_thread.IsBackground = true; + delete_thread.Start(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button1_Click(object sender, EventArgs e) + { + var tb = checkBox2.Checked; + var jd = checkBox4.Checked; + var pdd = checkBox5.Checked; + var wph = checkBox7.Checked; + + var datetime = dateTimePicker2.Value; + + try + { + if (!(tb || jd || pdd || wph)) throw new Exception("请选择要清理的联盟"); + + if (XtraMessageBox.Show($@"确定要清理{datetime.ToString("yyyy-MM-dd HH:mm:ss")}之前的订单吗? +清理后{datetime.ToString("yyyy-MM-dd HH:mm:ss")}之前的订单将不存在", "温馨提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.Cancel) + { + return; + } + } + catch (Exception ex) + { + ShowError(ex); + return; + } + + button1.Enabled = false; + + Task.Run(() => + { + try + { + var session = ApiClient.GetSession(); + + if (tb) + { + //session.Deleteable(f => f.create_time < datetime).ExecuteCommand(); + + session.ExcuteSQL("DELETE FROM fl_order_alimama where create_time < @datetime", new { datetime = datetime }); + } + if (jd) + { + //session.Deleteable(f => f.orderTime < datetime).ExecuteCommand(); + session.ExcuteSQL("DELETE FROM fl_order_jingdong where orderTime < @datetime", new { datetime = datetime }); + } + if (pdd) + { + //session.Deleteable(f => f.order_create_time < datetime).ExecuteCommand(); + session.ExcuteSQL("DELETE FROM fl_order_pinduoduo where order_create_time < @datetime", new { datetime = datetime }); + } + if (wph) + { + var timeSpan = Util.GetTimeSpan(datetime); + //session.Deleteable(f => f.orderTime < timeSpan).ExecuteCommand(); + session.ExcuteSQL("DELETE FROM fl_order_weipinhui where orderTime < @datetime", new { datetime = timeSpan }); + } + ShowSuccessAutoClose("历史订单清理完成"); + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + this.Invoke(new Action(() => + { + button1.Enabled = true; + })); + } + }); + ShowSuccessAutoClose("已成功创建历史订单清理任务,后台运行中"); + } + + private static bool isRunFlag = false; + + private void simpleButton2_Click(object sender, EventArgs e) + { + var msg = "清理任务执行完成,一共执行了{0}个机器人"; + //try + //{ + simpleButton2.Enabled = false; + + var task = Task.Run(() => + { + try + { + isRunFlag = true; + + var clients = Chat.Framework.ChatClient.WXClient.Values.Where(f => f.WeixinType == WeixinType.Hook微信 && f.Status == WxStatus.在线).ToList(); + msg = string.Format(msg, clients.Count); + foreach (var client in clients) + { + try + { + client.ClearChatHistoryMsg(); + Thread.Sleep(3300); + } + catch (Exception ex) + { } + } + + if (!this.IsDisposed) + { + this.simpleButton2.InvokeSafe(() => + { + simpleButton2.Enabled = true; + }); + } + isRunFlag = false; + } + catch (Exception ex) + { } + }); + //task.Wait(); + //} + //catch (Exception ex) + //{ + // msg = "清理任务异常:" + ex.Message; + //} + //finally + //{ + // simpleButton2.Enabled = true; + //} + //ShowSuccessAutoClose(msg); + } + } +} \ No newline at end of file diff --git a/应用/CleaningTools/MainForm.resx b/应用/CleaningTools/MainForm.resx new file mode 100644 index 0000000..23663da --- /dev/null +++ b/应用/CleaningTools/MainForm.resx @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 229, 17 + + + 109, 17 + + + 229, 17 + + + 60 + + \ No newline at end of file diff --git a/应用/CleaningTools/Properties/AssemblyInfo.cs b/应用/CleaningTools/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e289037 --- /dev/null +++ b/应用/CleaningTools/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("CleaningTools")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CleaningTools")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("91a026de-527f-4897-a1dc-01775e1cdd03")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/CleaningTools/Properties/Resources.Designer.cs b/应用/CleaningTools/Properties/Resources.Designer.cs new file mode 100644 index 0000000..1a9f802 --- /dev/null +++ b/应用/CleaningTools/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace CleaningTools.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CleaningTools.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 清理管家 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 清理管家 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 清理缓存文件、清粉 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 清理专家 { + get { + object obj = ResourceManager.GetObject("清理专家", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/CleaningTools/Properties/Resources.resx b/应用/CleaningTools/Properties/Resources.resx new file mode 100644 index 0000000..221ffd9 --- /dev/null +++ b/应用/CleaningTools/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 清理管家 + 插件窗体标题 + + + 清理管家 + 插件名称 + + + 清理缓存文件、清粉 + 插件介绍 + + + + ..\Resources\清理专家.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/CleaningTools/Properties/licenses.licx b/应用/CleaningTools/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/CleaningTools/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/CleaningTools/Resources/清理专家.png b/应用/CleaningTools/Resources/清理专家.png new file mode 100644 index 0000000..e0b5da6 Binary files /dev/null and b/应用/CleaningTools/Resources/清理专家.png differ diff --git a/应用/CleaningTools/Tools.cs b/应用/CleaningTools/Tools.cs new file mode 100644 index 0000000..f0d4a99 --- /dev/null +++ b/应用/CleaningTools/Tools.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CleaningTools +{ + public class Tools + { + /// + /// 通过目录删除目录下的所有文件,以及子目录文件 + /// + /// + public void DelectDir(string srcPath, bool IsOnlyDirectory = false) + { + try + { + DirectoryInfo dir = new DirectoryInfo(srcPath); + FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //返回目录中所有文件和子目录 + foreach (FileSystemInfo i in fileinfo) + { + try + { + if (i is DirectoryInfo) //判断是否文件夹 + { + if (i.FullName.Contains("Library")) + continue; + DirectoryInfo subdir = new DirectoryInfo(i.FullName); + subdir.Delete(true); //删除子目录和文件 + } + else if(!IsOnlyDirectory) + File.Delete(i.FullName); //删除指定文件 + } + catch (Exception ex) + { } + } + + } + catch { } + } + + } +} diff --git a/应用/CouponsSend/AnalyzeGoods.cs b/应用/CouponsSend/AnalyzeGoods.cs new file mode 100644 index 0000000..0d0dc77 --- /dev/null +++ b/应用/CouponsSend/AnalyzeGoods.cs @@ -0,0 +1,274 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Tools; +using CouponsSend.Entitys; +using CouponsSend.Entitys1; +using CouponsSend.Entitys2; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static CouponsSend.Entitys.Enum; + +namespace CouponsSend +{ + public class AnalyzeGoods + { + #region 采集大淘客数据 + public void GatherFactory() + { + try + { + var html = string.Empty; + var session = ApiClient.GetSession(); + var dtk = DtkApi.GetDtkApi(); + + var par = new ApiParameters(); + par.Add("pageId", "1"); + par.Add("pageSize", "100"); + + var ver = "v1.0.0"; + var api = "https://openapi.dataoke.com/api/goods/exclusive-goods-list"; + + switch (Class1.Config.GatherType) + { + case Entitys.Enum.GatherType.独家券商品: + api = "https://openapi.dataoke.com/api/goods/exclusive-goods-list"; + par.Add("sort", Class1.Config.ConditionType.ToString()); + + html = dtk.SendDtk(api, par, ver); + + if (!string.IsNullOrWhiteSpace(html)) + { + try + { + var egList = JsonConvert.DeserializeObject(html); + if (egList != null) + { + + var existGoods = session.Find("select * from fl_plugin_couponssend_goodsinfos"); + + var goodsinfos = new List(); + foreach (var item in egList.data.list) + { + try + { + var goods = new fl_plugin_couponssend_goodsinfos(); + goods.goods_quan = item.couponId; + goods.goods_id = item.goodsId; + var gTemp = existGoods.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + gTemp = goodsinfos.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + + goods.goods_desc = item.desc; + goods.coupon_discount = item.couponPrice; + goods.normal_price = item.originalPrice; + goods.actual_price = item.actualPrice; + goods.goods_thumbnail_url = item.mainPic; + goods.goods_name = item.title; + goods.promotion_rate = item.commissionRate; + + goods.state = StateType.未推广; + goods.cur_time = DateTime.Now; + goodsinfos.Add(goods); + } + catch (Exception ex) + { } + } + if (goodsinfos.Count != 0) + session.Insertable(goodsinfos.ToArray()).ExecuteCommand(); + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"群发优惠券采集异常.:{ex.Message}{ex.StackTrace}"); + } + } + break; + case Entitys.Enum.GatherType.每日爆品推荐: + api = "https://openapi.dataoke.com/api/goods/explosive-goods-list"; + par.Add("PriceCid", (Class1.Config.ConditionType + 1).ToString()); + + html = dtk.SendDtk(api, par, ver); + + if (!string.IsNullOrWhiteSpace(html)) + { + try + { + var egList = JsonConvert.DeserializeObject(html); + if (egList != null) + { + var existGoods = session.Find("select * from fl_plugin_couponssend_goodsinfos"); + + var goodsinfos = new List(); + foreach (var item in egList.data.list) + { + try + { + var goods = new fl_plugin_couponssend_goodsinfos(); + goods.goods_quan = item.couponId; + goods.goods_id = item.goodsId; + var gTemp = existGoods.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + gTemp = goodsinfos.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + + goods.goods_desc = item.desc; + goods.coupon_discount = item.couponPrice; + goods.normal_price = item.originalPrice; + goods.actual_price = item.actualPrice; + goods.goods_thumbnail_url = item.mainPic; + goods.goods_name = item.title; + goods.promotion_rate = item.commissionRate; + + goods.state = StateType.未推广; + goods.cur_time = DateTime.Now; + goodsinfos.Add(goods); + } + catch (Exception ex) + { } + } + if (goodsinfos.Count != 0) + session.Insertable(goodsinfos.ToArray()).ExecuteCommand(); + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"群发优惠券采集异常.:{ex.Message}{ex.StackTrace}"); + } + } + break; + case Entitys.Enum.GatherType.各大榜单: + api = "https://openapi.dataoke.com/api/goods/get-ranking-list"; + ver = "v1.3.0"; + par.Add("rankType", (Class1.Config.ConditionType + 1).ToString()); + + html = dtk.SendDtk(api, par, ver); + if (!string.IsNullOrWhiteSpace(html)) + { + try + { + + var egList = JsonConvert.DeserializeObject(html); + if (egList != null) + { + var existGoods = session.Find("select * from fl_plugin_couponssend_goodsinfos"); + + var goodsinfos = new List(); + foreach (var item in egList.data) + { + try + { + var goods = new fl_plugin_couponssend_goodsinfos(); + + var reg = Regex.Match(item.couponLink, @"activityId=(?[a-zA_Z0-9]+)"); + goods.goods_quan = reg.Success ? reg.Groups["activityid"].ToString() : string.Empty; + goods.goods_id = item.goodsId; + var gTemp = existGoods.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + gTemp = goodsinfos.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + + goods.goods_desc = item.desc; + goods.coupon_discount = item.couponPrice; + goods.normal_price = item.originalPrice; + goods.actual_price = item.actualPrice; + goods.goods_thumbnail_url = item.mainPic; + goods.goods_name = item.title; + goods.promotion_rate = item.commissionRate; + + goods.state = StateType.未推广; + goods.cur_time = DateTime.Now; + goodsinfos.Add(goods); + } + catch (Exception ex) + { } + } + if (goodsinfos.Count != 0) + session.Insertable(goodsinfos.ToArray()).ExecuteCommand(); + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"群发优惠券采集异常.:{ex.Message}{ex.StackTrace}"); + } + } + break; + case Entitys.Enum.GatherType.九块九包邮精选: + api = "https://openapi.dataoke.com/api/goods/nine/op-goods-list"; + par.Add("nineCid", (Class1.Config.ConditionType + 1).ToString()); + ver = "v2.0.0"; + html = dtk.SendDtk(api, par, ver); + + if (!string.IsNullOrWhiteSpace(html)) + { + try + { + var egList = JsonConvert.DeserializeObject(html); + if (egList != null) + { + + var existGoods = session.Find("select * from fl_plugin_couponssend_goodsinfos"); + + var goodsinfos = new List(); + foreach (var item in egList.data.list) + { + try + { + var goods = new fl_plugin_couponssend_goodsinfos(); + + var reg = Regex.Match(item.couponLink, @"activityId=(?[a-zA_Z0-9]+)"); + goods.goods_quan = reg.Success ? reg.Groups["activityid"].ToString() : string.Empty; + goods.goods_id = item.goodsId; + var gTemp = existGoods.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + gTemp = goodsinfos.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + + goods.goods_desc = item.desc; + goods.coupon_discount = item.couponPrice; + goods.normal_price = item.originalPrice; + goods.actual_price = item.actualPrice; + goods.goods_thumbnail_url = item.mainPic; + goods.goods_name = item.title; + goods.promotion_rate = item.commissionRate; + + goods.state = StateType.未推广; + goods.cur_time = DateTime.Now; + goodsinfos.Add(goods); + } + catch (Exception ex) + { } + } + if (goodsinfos.Count != 0) + session.Insertable(goodsinfos.ToArray()).ExecuteCommand(); + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"群发优惠券采集异常.:{ex.Message}{ex.StackTrace}"); + } + } + break; + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"群发优惠券采集异常:{ex.Message}{ex.StackTrace}"); + } + } + #endregion + } +} diff --git a/应用/CouponsSend/Class1.cs b/应用/CouponsSend/Class1.cs new file mode 100644 index 0000000..fbb61fd --- /dev/null +++ b/应用/CouponsSend/Class1.cs @@ -0,0 +1,84 @@ +using Api.Framework; +using Api.Framework.SDK; +using CouponsSend.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.Utils; +using CouponsSend.Entitys; +using Api.Framework.Tools; + +namespace CouponsSend +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.群发优惠券; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) session.CreateTable(); + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + TimerTask.NewTimer(10); //创建线程 - 10秒 + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void Stop() + { + try + { + TimerTask.Close(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/CouponsSend/Config.cs b/应用/CouponsSend/Config.cs new file mode 100644 index 0000000..2ee8af2 --- /dev/null +++ b/应用/CouponsSend/Config.cs @@ -0,0 +1,288 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static Api.Framework.ApiClient; +using static CouponsSend.Entitys.Enum; + +namespace CouponsSend +{ + [Config(Name = "插件-群发优惠券-配置")] + public class Config + { + + /// + /// 采集开关 + /// + [ + Category("1)、自动采集"), DisplayName("01.采集开关"), DefaultValue(SwitchType.开启) + ] + public SwitchType Switch { get; set; } = SwitchType.开启; + + /// + /// 采集数据触发数量 + /// + [ + Category("1)、自动采集"), DisplayName("02.采集触发量"), DefaultValue(10), + Description(@"当采集开关为开启时,该值为一个采集点,当采集剩余的商品数量少于等于采集触发量,将自动进行采集操作") + ] + public int GatherTouchNum { get; set; } = 10; + + /// + /// 采集类型 + /// + public GatherType GatherType { get; set; } = GatherType.各大榜单; + + /// + /// 采集条件 + /// + public int ConditionType { get; set; } + + [ + Category("2)、群发设置"), DisplayName("01.不限发送时间"), DefaultValue(SwitchType.关闭), + Description(@"开启发送时间将不受控制,一直发送") +] + public SwitchType NotCheckTime { get; set; } + + private string[] _sendTaskTimes; + /// + /// 发送任务时间段 + /// + public string[] SendTaskTimes + { + get { return _sendTaskTimes; } + set + { + var sendTaskTimes = value as string[]; + if (sendTaskTimes != null && sendTaskTimes.Length != 0) + { + for (int i = 0; i < sendTaskTimes.Length; i++) + { + var times = sendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0]); + var end = DateTime.Parse(times[1]); + if (begin >= end) + throw new Exception($"开始时间必须小于结束时间:[{sendTaskTimes[i]}]"); + } + } + } + _sendTaskTimes = value; + } + } + + // /// + // /// 优惠券最低价 + // /// + // // [ + // // Category("1)、群发设置"), DisplayName("03.优惠券最低价"), DefaultValue(0), + // // Description(@"优惠券最低价") + // //] + // // public double Coupon { get; set; } + // /// + // /// 券后最低价 + // /// + // [ + // Category("2)、群发设置"), DisplayName("04.券后最低价"), DefaultValue(3), + // Description(@"券后最低价") + //] + // public double Price_Lowest { get; set; } + // /// + // /// 券后最高价 + // /// + // [ + // Category("2)、群发设置"), DisplayName("05.券后最高价"), DefaultValue(99999), + // Description(@"券后最高价") + //] + // public double Price_Tallest { get; set; } + // /// + // /// 商品销量最低 + // /// + // [ + // Category("2)、群发设置"), DisplayName("06.商品销量最低"), DefaultValue(500), + // Description(@"商品销量最低") + // ] + // public int Sales { get; set; } + + /// + /// 群发送间隔 + /// + [ +Category("2)、群发设置"), DisplayName("09.群发送间隔"), DefaultValue(10), +Description(@"每个群发送的间隔,单位/秒") +] + public int IntervalTime_Group { get; set; } + /// + /// 券发送间隔 + /// + [ +Category("2)、群发设置"), DisplayName("10.券发送间隔"), DefaultValue(300), +Description(@"券发送间隔,单位/秒") +] + public int IntervalTime_Coupon { get; set; } + + /// + /// 优惠券模板 + /// + [ +Category("2)、群发设置"), DisplayName("11.优惠券模板"), DefaultValue(QrImageType.模板C), + Description(@"生成二维码图片的模板")] + public QrImageType qrImageType { get; set; } + + /// + /// 黑名单关键词 + /// + [ +Category("2)、群发设置"), DisplayName("12.黑名单关键词"), DefaultValue(""), +Description(@"黑名单关键词,包含设置的关键词将不发送,多个关键词用逗号"",""隔开") +] + public string BlackContent { get; set; } + /// + /// 白名单关键词 + /// + [ +Category("2)、群发设置"), DisplayName("13.白名单关键词"), DefaultValue(""), +Description(@"白名单关键词,包含设置的关键词才发送,多个关键词用逗号"",""隔开") +] + public string WhiteContent { get; set; } + + /// + /// QQ图文格式 + /// + [ +Category("2)、群发设置"), DisplayName("14.QQ图文格式"), DefaultValue(@"[商品图片] +限时抢购!!!! +-------------------- +[商品标题] +宝贝原价:[商品原价] 元 +内部优惠:[优惠券金额] 元 +券后价格:[券后价] 元 +返利积分:[返利积分][积分名称] +-------------------- +下单地址:[购买中间页地址] +购买口令:[购买淘口令] +推荐理由:[文案]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[商品标题]、[商品原价]、[优惠券金额]、[券后价]、[商品主图]、[积分名称]、[月销量]、[返利积分]、[购买地址]、[购买中间页地址]、[购买淘口令]、[共节省]、[商品图片]、[文案]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string QQMsg { get; set; } + + /// + /// 微信图文格式 + /// + [ +Category("2)、群发设置"), DisplayName("15.微信图文格式"), DefaultValue(@"[商品图片] +限时抢购!!!! +-------------------- +[商品标题] +宝贝原价:[商品原价] 元 +内部优惠:[优惠券金额] 元 +券后价格:[券后价] 元 +返利积分:[返利积分][积分名称] +-------------------- +下单地址:[购买中间页地址] +购买口令:[购买淘口令] +推荐理由:[文案]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[返利积分]、[购买地址]、[购买中间页地址]、[购买淘口令]、[共节省]、[商品图片]、[文案] XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string WXMsg { get; set; } + + ///// + ///// 采集的群 + ///// + //[Browsable(false)] + //public List CloudGroups { get; set; } + + /// + /// 短网址 + /// + [ + Category("2)、群发设置"), DisplayName("16.短网址"), DefaultValue(DwzType.快站短网址), + Description("缩短购买中间页地址") + ] + public DwzType SearchDwzType { get; set; } + + /// + /// 自动清理 + /// + [ + Category("3)、定时清理"), DisplayName("01.定时清理"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将在设置的时间进行采集数据的清空操作") + ] + public SwitchType Auto_IsClear { get; set; } = SwitchType.开启; + + private string _AutoClearTaskTimes; + [ + Category("3)、定时清理"), DisplayName("02.定时清理时间"), DefaultValue("23:59"), + Description(@"定时清理时间 + 格式:HH:mm + 例:23:59 + 注:时间为24小时制") + ] + public string AutoClearTaskTimes + { + get { return _AutoClearTaskTimes; } + set + { + try + { + var time = value as string; + var _time = DateTime.Parse(time); + } + catch (Exception) + { + throw new Exception($"时间格式不正确"); + } + _AutoClearTaskTimes = value; + } + } + + + public Config() + { + this.qrImageType = QrImageType.模板C; + this.NotCheckTime = SwitchType.关闭; + this._sendTaskTimes = new string[] { "09:00-22:00" }; + this.IntervalTime_Group = 10; + this.IntervalTime_Coupon = 300; + this.BlackContent = string.Empty; + this.WhiteContent = string.Empty; + //this.CloudGroups = new List(); + this.SearchDwzType = DwzType.快站短网址; + this._AutoClearTaskTimes = "23:59"; + this.QQMsg = @"[商品图片] +限时抢购!!!! +-------------------- +[商品标题] +宝贝原价:[商品原价] 元 +内部优惠:[优惠券金额] 元 +券后价格:[券后价] 元 +返利积分:[返利积分][积分名称] +-------------------- +下单地址:[购买中间页地址] +购买口令:[购买淘口令] +推荐理由:[文案]"; + this.WXMsg = @"[商品图片] +限时抢购!!!! +-------------------- +[商品标题] +宝贝原价:[商品原价] 元 +内部优惠:[优惠券金额] 元 +券后价格:[券后价] 元 +返利积分:[返利积分][积分名称] +-------------------- +下单地址:[购买中间页地址] +购买口令:[购买淘口令] +推荐理由:[文案]"; + } + + } +} diff --git a/应用/CouponsSend/CouponsSend.csproj b/应用/CouponsSend/CouponsSend.csproj new file mode 100644 index 0000000..5c32f42 --- /dev/null +++ b/应用/CouponsSend/CouponsSend.csproj @@ -0,0 +1,148 @@ + + + + + Debug + AnyCPU + {3D53BFC6-1C75-483A-BF7C-6B20F0152C66} + Library + Properties + CouponsSend + CouponsSend + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + Form + + + EditGroupInfoForm.cs + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + + + + EditGroupInfoForm.cs + Designer + + + MainForm.cs + Designer + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + + + \ No newline at end of file diff --git a/应用/CouponsSend/EditGroupInfoForm.Designer.cs b/应用/CouponsSend/EditGroupInfoForm.Designer.cs new file mode 100644 index 0000000..02dd238 --- /dev/null +++ b/应用/CouponsSend/EditGroupInfoForm.Designer.cs @@ -0,0 +1,235 @@ +namespace CouponsSend +{ + partial class EditGroupInfoForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.comboBoxEdit1); + this.groupBox1.Controls.Add(this.hyperlinkLabelControl1); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl6); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Location = new System.Drawing.Point(46, 43); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(469, 268); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 编辑群信息 "; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(142, 45); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Size = new System.Drawing.Size(269, 20); + this.comboBoxEdit1.TabIndex = 10; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(159, 156); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(48, 14); + this.hyperlinkLabelControl1.TabIndex = 9; + this.hyperlinkLabelControl1.Text = "双击设置"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // simpleButton2 + // + this.simpleButton2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton2.Location = new System.Drawing.Point(280, 193); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(88, 35); + this.simpleButton2.TabIndex = 7; + this.simpleButton2.Text = " 取 消 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton1.Location = new System.Drawing.Point(118, 193); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(88, 35); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = " 确 定 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(417, 115); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(7, 14); + this.labelControl5.TabIndex = 4; + this.labelControl5.Text = "*"; + // + // labelControl4 + // + this.labelControl4.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl4.Appearance.Options.UseForeColor = true; + this.labelControl4.Location = new System.Drawing.Point(417, 81); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(7, 14); + this.labelControl4.TabIndex = 4; + this.labelControl4.Text = "*"; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(88, 48); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(48, 14); + this.labelControl7.TabIndex = 4; + this.labelControl7.Text = "机器人:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(88, 81); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(48, 14); + this.labelControl2.TabIndex = 4; + this.labelControl2.Text = "群昵称:"; + // + // labelControl6 + // + this.labelControl6.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl6.Appearance.Options.UseForeColor = true; + this.labelControl6.Location = new System.Drawing.Point(290, 156); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(121, 14); + this.labelControl6.TabIndex = 5; + this.labelControl6.Text = "( 用于发券转链的PID )"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(81, 156); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(55, 14); + this.labelControl3.TabIndex = 5; + this.labelControl3.Text = "转链PID:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(88, 115); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(48, 14); + this.labelControl1.TabIndex = 5; + this.labelControl1.Text = "群账号:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(142, 77); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(269, 22); + this.textBox2.TabIndex = 2; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(142, 111); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(269, 22); + this.textBox1.TabIndex = 3; + // + // labelControl8 + // + this.labelControl8.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl8.Appearance.Options.UseForeColor = true; + this.labelControl8.Location = new System.Drawing.Point(417, 48); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(7, 14); + this.labelControl8.TabIndex = 4; + this.labelControl8.Text = "*"; + // + // EditGroupInfoForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.simpleButton2; + this.ClientSize = new System.Drawing.Size(561, 354); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditGroupInfoForm"; + this.Text = "编辑发券群信息"; + this.Load += new System.EventHandler(this.EditGroupInfoForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl8; + } +} \ No newline at end of file diff --git a/应用/CouponsSend/EditGroupInfoForm.cs b/应用/CouponsSend/EditGroupInfoForm.cs new file mode 100644 index 0000000..0a27ad3 --- /dev/null +++ b/应用/CouponsSend/EditGroupInfoForm.cs @@ -0,0 +1,171 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using CouponsSend.Entitys; +using CouponsSend.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace CouponsSend +{ + public partial class EditGroupInfoForm : BaseForm + { + string id = string.Empty; + public EditGroupInfoForm(string id = "") + { + InitializeComponent(); + this.id = id; + } + + private void EditGroupInfoForm_Load(object sender, EventArgs e) + { + var robotname = string.Empty; + if (!string.IsNullOrWhiteSpace(id)) + { + var session = ApiClient.GetSession(); + var adzone = session.FindSingle("select * from fl_adzone_info where id = @id", new { id = id }); + if (adzone != null)//数据库中存在的情况 + { + textBox2.Text = adzone.extend; + textBox1.Text = adzone.group_id; + hyperlinkLabelControl1.Text = string.IsNullOrWhiteSpace(adzone.adzone_name) ? "双击设置" : adzone.adzone_name; + Tuiguangwei tgw = null; + if (!string.IsNullOrWhiteSpace(adzone.adzone_pid)) + tgw = new Tuiguangwei() { Pid = adzone.adzone_pid, Name = adzone.adzone_name, Member = new fl_cps_member() { username = adzone.adzone_pid_cps_name } }; + hyperlinkLabelControl1.Tag = tgw; + + var robot = session.FindRobots().FirstOrDefault(f => f.id == adzone.robot_id); + if (robot == null) return; + robotname = robot.name; + } + } + + var realIndex = -1; + var comList = new List(); + this.comboBoxEdit1.Properties.Items.Add("请选择群所对应机器人"); + var wxs = Chat.Framework.ChatClient.WXClient.Values.ToList(); + foreach (var item in wxs) + { + comList.Add(new ComboxData() { Text = $"{item.User.Nick}({item.WeixinHao})", Value = item.WeixinHao, Type = (item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.QYHook微信 ? Api.Framework.SDK.ChatType.企业微信 : Api.Framework.SDK.ChatType.微信) }); + if (item.WeixinHao == robotname) + realIndex = comList.Count; + } + var qqs = Chat.Framework.ChatClient.QQClients.Values; + foreach (var item in qqs) + { + comList.Add(new ComboxData() { Text = $"{item.Nickname}({item.QQ})", Value = item.QQ.ToString(), Type = Api.Framework.SDK.ChatType.QQ }); + if (item.QQ.ToString() == robotname) + realIndex = comList.Count; + } + this.comboBoxEdit1.Properties.Items.AddRange(comList); + this.comboBoxEdit1.SelectedIndex = realIndex == -1 ? 0 : realIndex; + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (this.comboBoxEdit1.SelectedIndex == 0) throw new Exception("请选择群所对应机器人"); + if (string.IsNullOrWhiteSpace(textBox2.Text)) throw new Exception("请填写群昵称!"); + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("请填写群账号!"); + + var session = ApiClient.GetSession(); + var value = (comboBoxEdit1.SelectedItem as ComboxData); + var robot = session.FindRobots().FirstOrDefault(f => f.type == value.Type && f.name == value.Value); + + fl_adzone_info adzone = null; + if (string.IsNullOrWhiteSpace(id)) + { + adzone = session.FindSingle("select * from fl_adzone_info where alliance_id = @alliance_id and custom_type = @custom_type and robot_id = @robot_id and group_id = @group_id", new { alliance_id = CpsType.阿里妈妈, custom_type = Resources.SoftwareType, robot_id = robot.id, group_id = textBox1.Text.Trim() }); + } + else + adzone = session.FindSingle("select * from fl_adzone_info where id=@id", new { id = id }); + + Tuiguangwei tgw = null; + if (hyperlinkLabelControl1.Tag != null) + tgw = hyperlinkLabelControl1.Tag as Tuiguangwei; + + if (adzone != null)//数据库中存在的情况 + { + if (tgw != null) + { + adzone.adzone_name = tgw.Name; //推广位名称 + adzone.adzone_pid = tgw.Pid; //推广位pid + adzone.adzone_pid_cps_name = tgw.Member.username; //推广位cps名称 + } + adzone.extend = textBox2.Text.Trim(); + adzone.group_id = textBox1.Text.Trim(); + adzone.robot_id = robot.id; + session.SaveOrUpdate(adzone); + } + else + { + try + { + adzone = new fl_adzone_info() + { + extend = textBox2.Text.Trim(), + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw == null ? string.Empty : tgw.Name, //推广位名称 + adzone_pid = tgw == null ? string.Empty : tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw == null ? string.Empty : tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = robot.id, //机器人id + group_id = textBox1.Text.Trim(), //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + session.FindAdzoneInfos(true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + hyperlinkLabelControl1.Tag = tgwObj; + var tgw = tgwObj as Tuiguangwei; + hyperlinkLabelControl1.Text = tgw.Name; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} diff --git a/应用/CouponsSend/EditGroupInfoForm.resx b/应用/CouponsSend/EditGroupInfoForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/CouponsSend/EditGroupInfoForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/CouponsSend/Entitys/ComboxData.cs b/应用/CouponsSend/Entitys/ComboxData.cs new file mode 100644 index 0000000..ee4f700 --- /dev/null +++ b/应用/CouponsSend/Entitys/ComboxData.cs @@ -0,0 +1,25 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CouponsSend.Entitys +{ + /// + /// 用于在控件 comboBoxEdit 中实现显示值和实际值 + /// + public class ComboxData + { + public string Text { set; get; } + public string Value { set; get; } + + public ChatType Type { get; set; } + + public override string ToString() + { + return Text; + } + } +} diff --git a/应用/CouponsSend/Entitys/Enum.cs b/应用/CouponsSend/Entitys/Enum.cs new file mode 100644 index 0000000..f6de2f5 --- /dev/null +++ b/应用/CouponsSend/Entitys/Enum.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CouponsSend.Entitys +{ + public class Enum + { + public enum StateType + { + 已推广 = 0, + 未推广 = 1 + } + + /// + /// 采集类型 + /// + public enum GatherType + { + 独家券商品 = 0, + 每日爆品推荐 = 1, + 各大榜单 = 2, + 九块九包邮精选 = 3 + } + } +} diff --git a/应用/CouponsSend/Entitys/ExclusiveGoodsList.cs b/应用/CouponsSend/Entitys/ExclusiveGoodsList.cs new file mode 100644 index 0000000..52e429d --- /dev/null +++ b/应用/CouponsSend/Entitys/ExclusiveGoodsList.cs @@ -0,0 +1,277 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CouponsSend.Entitys1 +{ + public class List + { + /// + /// + /// + public int id { get; set; } + /// + /// + /// + public string goodsId { get; set; } + /// + /// 格力空调罩防尘罩北欧风格开机不取空调罩套挂式美的海尔挂机通用 + /// + public string title { get; set; } + /// + /// 格力空调罩防尘罩北欧风格开机不取空调罩 + /// + public string dtitle { get; set; } + /// + /// + /// + public double originalPrice { get; set; } + /// + /// + /// + public double actualPrice { get; set; } + /// + /// + /// + public int shopType { get; set; } + /// + /// + /// + public int goldSellers { get; set; } + /// + /// + /// + public int monthSales { get; set; } + /// + /// + /// + public int twoHoursSales { get; set; } + /// + /// + /// + public int dailySales { get; set; } + /// + /// + /// + public int commissionType { get; set; } + /// + /// 格力空调罩,防尘罩,北欧风格开机不取空调罩套,挂式美的海尔挂机通用,开机不取空调罩我们家是送内包的价格哦亲! + /// + public string desc { get; set; } + /// + /// + /// + public int couponRemainCount { get; set; } + /// + /// + /// + public int couponReceiveNum { get; set; } + /// + /// + /// + public string couponLink { get; set; } + /// + /// + /// + public DateTime couponEndTime { get; set; } + /// + /// + /// + public DateTime couponStartTime { get; set; } + /// + /// + /// + public double couponPrice { get; set; } + /// + /// + /// + public string couponConditions { get; set; } + /// + /// + /// + public string couponId { get; set; } + /// + /// + /// + public int activityType { get; set; } + /// + /// + /// + public DateTime createTime { get; set; } + /// + /// + /// + public string mainPic { get; set; } + /// + /// + /// + public string marketingMainPic { get; set; } + /// + /// + /// + public string sellerId { get; set; } + /// + /// + /// + public int cid { get; set; } + /// + /// + /// + public double discounts { get; set; } + /// + /// + /// + public double commissionRate { get; set; } + /// + /// + /// + public int couponTotalNum { get; set; } + /// + /// + /// + public string activityStartTime { get; set; } + /// + /// + /// + public string activityEndTime { get; set; } + /// + /// + /// + public string shopName { get; set; } + /// + /// + /// + public int shopLevel { get; set; } + /// + /// + /// + public double descScore { get; set; } + /// + /// + /// + public int brand { get; set; } + /// + /// + /// + public long brandId { get; set; } + /// + /// + /// + public string brandName { get; set; } + /// + /// + /// + public int hotPush { get; set; } + /// + /// 万惠 + /// + public string teamName { get; set; } + /// + /// + /// + public string itemLink { get; set; } + /// + /// + /// + public int tchaoshi { get; set; } + /// + /// + /// + public double dsrScore { get; set; } + /// + /// + /// + public double dsrPercent { get; set; } + /// + /// + /// + public double shipScore { get; set; } + /// + /// + /// + public double shipPercent { get; set; } + /// + /// + /// + public double serviceScore { get; set; } + /// + /// + /// + public double servicePercent { get; set; } + /// + /// + /// + public List subcid { get; set; } + /// + /// + /// + public string video { get; set; } + /// + /// + /// + public int quanMLink { get; set; } + /// + /// + /// + public int hzQuanOver { get; set; } + /// + /// + /// + public int yunfeixian { get; set; } + /// + /// + /// + public int estimateAmount { get; set; } + /// + /// + /// + public int freeshipRemoteDistrict { get; set; } + /// + /// + /// + public List specialText { get; set; } + } + + public class Data + { + /// + /// + /// + public List list { get; set; } + /// + /// + /// + public int totalNum { get; set; } + /// + /// + /// + public string pageId { get; set; } + } + + public class ExclusiveGoodsList + { + /// + /// + /// + public string requestId { get; set; } + /// + /// + /// + public long time { get; set; } + /// + /// + /// + public int code { get; set; } + /// + /// 成功 + /// + public string msg { get; set; } + /// + /// + /// + public Data data { get; set; } + } + +} diff --git a/应用/CouponsSend/Entitys/ExplosiveGoodsList.cs b/应用/CouponsSend/Entitys/ExplosiveGoodsList.cs new file mode 100644 index 0000000..f72d2e6 --- /dev/null +++ b/应用/CouponsSend/Entitys/ExplosiveGoodsList.cs @@ -0,0 +1,284 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CouponsSend.Entitys2 +{ + public class List + { + /// + /// + /// + public int id { get; set; } + /// + /// + /// + public string goodsId { get; set; } + /// + /// 东北大米新珍珠米一级粳米家常香软稻田米小町米粥米5斤装2.5kg + /// + public string title { get; set; } + /// + /// 【5斤装】家常香软东北大米新珍珠米 + /// + public string dtitle { get; set; } + /// + /// + /// + public double originalPrice { get; set; } + /// + /// + /// + public double actualPrice { get; set; } + /// + /// + /// + public int shopType { get; set; } + /// + /// + /// + public int goldSellers { get; set; } + /// + /// + /// + public int monthSales { get; set; } + /// + /// + /// + public int twoHoursSales { get; set; } + /// + /// + /// + public int dailySales { get; set; } + /// + /// + /// + public int commissionType { get; set; } + /// + /// 厨房必备~东北大米!优质一级东北好大米,天然健康食品,无化肥无香精原生态,精耕细作日照充足,颗粒均匀,香甜可口~煮饭煮粥都可,真空包装,抢! + /// + public string desc { get; set; } + /// + /// + /// + public int couponRemainCount { get; set; } + /// + /// + /// + public int couponReceiveNum { get; set; } + /// + /// + /// + public string couponLink { get; set; } + /// + /// + /// + public DateTime couponEndTime { get; set; } + /// + /// + /// + public DateTime couponStartTime { get; set; } + /// + /// + /// + public double couponPrice { get; set; } + /// + /// + /// + public string couponConditions { get; set; } + /// + /// + /// + public string couponId { get; set; } + /// + /// + /// + public int activityType { get; set; } + /// + /// + /// + public DateTime createTime { get; set; } + /// + /// + /// + public string teamLink { get; set; } + /// + /// + /// + public string mainPic { get; set; } + /// + /// + /// + public string marketingMainPic { get; set; } + /// + /// + /// + public string sellerId { get; set; } + /// + /// + /// + public int cid { get; set; } + /// + /// + /// + public double discounts { get; set; } + /// + /// + /// + public double commissionRate { get; set; } + /// + /// + /// + public int couponTotalNum { get; set; } + /// + /// + /// + public string activityStartTime { get; set; } + /// + /// + /// + public string activityEndTime { get; set; } + /// + /// 园侬鲜旗舰店 + /// + public string shopName { get; set; } + /// + /// + /// + public int shopLevel { get; set; } + /// + /// + /// + public double descScore { get; set; } + /// + /// + /// + public int brand { get; set; } + /// + /// + /// + public long brandId { get; set; } + /// + /// + /// + public string brandName { get; set; } + /// + /// + /// + public int hotPush { get; set; } + /// + /// 鲨鱼精品联盟 + /// + public string teamName { get; set; } + /// + /// + /// + public string itemLink { get; set; } + /// + /// + /// + public int tchaoshi { get; set; } + /// + /// + /// + public double dsrScore { get; set; } + /// + /// + /// + public double dsrPercent { get; set; } + /// + /// + /// + public double shipScore { get; set; } + /// + /// + /// + public double shipPercent { get; set; } + /// + /// + /// + public double serviceScore { get; set; } + /// + /// + /// + public double servicePercent { get; set; } + /// + /// + /// + public List subcid { get; set; } + /// + /// + /// + public string video { get; set; } + /// + /// + /// + public int quanMLink { get; set; } + /// + /// + /// + public int hzQuanOver { get; set; } + /// + /// + /// + public int yunfeixian { get; set; } + /// + /// + /// + public double estimateAmount { get; set; } + /// + /// + /// + public int freeshipRemoteDistrict { get; set; } + /// + /// + /// + public List specialText { get; set; } + /// + /// + /// + public int tbcid { get; set; } + } + + public class Data + { + /// + /// + /// + public List list { get; set; } + /// + /// + /// + public int totalNum { get; set; } + /// + /// + /// + public string pageId { get; set; } + } + + public class ExplosiveGoodsList + { + /// + /// + /// + public string requestId { get; set; } + /// + /// + /// + public long time { get; set; } + /// + /// + /// + public int code { get; set; } + /// + /// 成功 + /// + public string msg { get; set; } + /// + /// + /// + public Data data { get; set; } + } +} diff --git a/应用/CouponsSend/Entitys/GetRankinglist.cs b/应用/CouponsSend/Entitys/GetRankinglist.cs new file mode 100644 index 0000000..00626b5 --- /dev/null +++ b/应用/CouponsSend/Entitys/GetRankinglist.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CouponsSend.Entitys +{ + public class Data + { + /// + /// + /// + public int id { get; set; } + /// + /// + /// + public string goodsId { get; set; } + /// + /// + /// + public int ranking { get; set; } + /// + /// 【淘工厂可签到】懒人一次性抹布 + /// + public string dtitle { get; set; } + /// + /// + /// + public double actualPrice { get; set; } + /// + /// + /// + public double commissionRate { get; set; } + /// + /// + /// + public double couponPrice { get; set; } + /// + /// + /// + public int couponReceiveNum { get; set; } + /// + /// + /// + public int couponTotalNum { get; set; } + /// + /// + /// + public int monthSales { get; set; } + /// + /// + /// + public int twoHoursSales { get; set; } + /// + /// + /// + public int dailySales { get; set; } + /// + /// + /// + public int hotPush { get; set; } + /// + /// + /// + public string mainPic { get; set; } + /// + /// 加厚懒人抹布干湿两用厨房一次性抹布家务清洁洗碗布吸油无纺布巾 + /// + public string title { get; set; } + /// + /// 25片2.3元,50片3.4元,木浆无纺布面料,不掉毛絮,吸水更吸油,可用于擦拭灶台、餐盘,再脏的污渍,一擦就干净 + /// + public string desc { get; set; } + /// + /// + /// + public double originalPrice { get; set; } + /// + /// + /// + public string couponLink { get; set; } + /// + /// + /// + public DateTime couponStartTime { get; set; } + /// + /// + /// + public DateTime couponEndTime { get; set; } + /// + /// + /// + public int commissionType { get; set; } + /// + /// + /// + public DateTime createTime { get; set; } + /// + /// + /// + public int activityType { get; set; } + /// + /// 酷淘社群 + /// + public string guideName { get; set; } + /// + /// + /// + public int shopType { get; set; } + /// + /// + /// + public string couponConditions { get; set; } + /// + /// + /// + public int newRankingGoods { get; set; } + /// + /// + /// + public string sellerId { get; set; } + /// + /// + /// + public int quanMLink { get; set; } + /// + /// + /// + public int hzQuanOver { get; set; } + /// + /// + /// + public int yunfeixian { get; set; } + /// + /// + /// + public double estimateAmount { get; set; } + /// + /// + /// + public int freeshipRemoteDistrict { get; set; } + /// + /// + /// + public int haitao { get; set; } + /// + /// + /// + public int tchaoshi { get; set; } + /// + /// + /// + public int lowest { get; set; } + /// + /// + /// + public int fresh { get; set; } + /// + /// + /// + public int num { get; set; } + /// + /// + /// + public List specialText { get; set; } + } + + public class GetRankinglist + { + /// + /// + /// + public string requestId { get; set; } + /// + /// + /// + public long time { get; set; } + /// + /// + /// + public int code { get; set; } + /// + /// 成功 + /// + public string msg { get; set; } + /// + /// + /// + public List data { get; set; } + + } +} diff --git a/应用/CouponsSend/Entitys/Group.cs b/应用/CouponsSend/Entitys/Group.cs new file mode 100644 index 0000000..a8f31fa --- /dev/null +++ b/应用/CouponsSend/Entitys/Group.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CouponsSend.Entitys +{ + public class Group + { + public string groupid { get; set; } + + public string maxid { get; set; } + + /// + /// 群昵称 + /// + public string name { get; set; } + + public string markname { get; set; } + + /// + /// 群号 + /// + public string uin { get; set; } + + public int type { get; set; } + + public string gz { get; set; } + } +} \ No newline at end of file diff --git a/应用/CouponsSend/Entitys/fl_plugin_couponssend_goodsinfos.cs b/应用/CouponsSend/Entitys/fl_plugin_couponssend_goodsinfos.cs new file mode 100644 index 0000000..6a09d68 --- /dev/null +++ b/应用/CouponsSend/Entitys/fl_plugin_couponssend_goodsinfos.cs @@ -0,0 +1,79 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static CouponsSend.Entitys.Enum; + +namespace CouponsSend.Entitys +{ + public class fl_plugin_couponssend_goodsinfos : base_model + { + /// + /// 商品id + /// + public string goods_id { get; set; } + /// + /// 商品标题 + /// + public string goods_name { get; set; } + /// + /// 商品描述 + /// + public string goods_desc { get; set; } + /// + /// 商品图片链接 + /// + public string goods_thumbnail_url { get; set; } + /// + /// 已售卖件数 + /// + public int sold_quantity { get; set; } + /// + /// 商品单价,单位为元 + /// + public double normal_price { get; set; } + /// + /// 券后价 + /// + public double actual_price { get; set; } + /// + /// 店铺名 + /// + public string mall_name { get; set; } + /// + /// 类目id + /// + public string category_id { get; set; } + /// + /// 优惠券面额,单位为元 + /// + public double coupon_discount { get; set; } + /// + /// 优惠券剩余数量 + /// + public string coupon_remain_quantity { get; set; } + /// + /// 优惠券活动ID + /// + public string goods_quan { get; set; } + /// + /// 佣金比例,百分比 + /// + public double promotion_rate { get; set; } + /// + /// 购买链接 转连之后 + /// + public string shopping_url { get; set; } + /// + /// 发送状态,是否发送过 + /// + public StateType state { get; set; } + /// + /// 采集的日期 + /// + public DateTime cur_time { get; set; } + + } +} diff --git a/应用/CouponsSend/MainForm.Designer.cs b/应用/CouponsSend/MainForm.Designer.cs new file mode 100644 index 0000000..9a33908 --- /dev/null +++ b/应用/CouponsSend/MainForm.Designer.cs @@ -0,0 +1,1066 @@ +namespace CouponsSend +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabControl2 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加发券群ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改选中群ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中券ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage5 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有已发ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraScrollableControl1 = new DevExpress.XtraEditors.XtraScrollableControl(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.dt_AutoClearTaskTimes = new System.Windows.Forms.DateTimePicker(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.bc_AutoClearTask = new UI.Framework.Controls.ButtonCheck(); + this.me_WhiteContent = new DevExpress.XtraEditors.MemoEdit(); + this.me_BlackContent = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.me_WXMsg = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl23 = new DevExpress.XtraEditors.LabelControl(); + this.me_QQMsg = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl22 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl24 = new DevExpress.XtraEditors.LabelControl(); + this.cb_Short = new System.Windows.Forms.ComboBox(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.cb_Model = new System.Windows.Forms.ComboBox(); + this.labelControl17 = new DevExpress.XtraEditors.LabelControl(); + this.label4 = new System.Windows.Forms.Label(); + this.dt_SendTaskTimes2 = new System.Windows.Forms.DateTimePicker(); + this.dt_SendTaskTimes1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl18 = new DevExpress.XtraEditors.LabelControl(); + this.nud_qInterval = new System.Windows.Forms.NumericUpDown(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.nud_gInterval = new System.Windows.Forms.NumericUpDown(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.cb_ConditionType = new System.Windows.Forms.ComboBox(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.cb_GatherType = new System.Windows.Forms.ComboBox(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.nud_GatherTouchNum = new System.Windows.Forms.NumericUpDown(); + this.bc_CJSwitch = new UI.Framework.Controls.ButtonCheck(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl2)).BeginInit(); + this.xtraTabControl2.SuspendLayout(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.xtraScrollableControl1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.me_WhiteContent.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_BlackContent.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_WXMsg.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_QQMsg.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_qInterval)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_gInterval)).BeginInit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nud_GatherTouchNum)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(722, 625); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + this.xtraTabControl1.TabIndexChanged += new System.EventHandler(this.xtraTabControl1_TabIndexChanged); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.xtraTabControl2); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(720, 599); + this.xtraTabPage1.Text = " 发 送 群 列 表 "; + // + // xtraTabControl2 + // + this.xtraTabControl2.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl2.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl2.Name = "xtraTabControl2"; + this.xtraTabControl2.SelectedTabPage = this.xtraTabPage4; + this.xtraTabControl2.Size = new System.Drawing.Size(720, 599); + this.xtraTabControl2.TabIndex = 0; + this.xtraTabControl2.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage4, + this.xtraTabPage5}); + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.label1); + this.xtraTabPage4.Controls.Add(this.pageControl1); + this.xtraTabPage4.Controls.Add(this.gridControl2); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(718, 573); + this.xtraTabPage4.Text = "QQ群 / 微信群"; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(161, 103); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(393, 35); + this.label1.TabIndex = 10; + this.label1.Text = "列表为空,右击添加数据"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 536); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(718, 37); + this.pageControl1.TabIndex = 7; + // + // gridControl2 + // + this.gridControl2.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl2.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(718, 530); + this.gridControl2.TabIndex = 6; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加发券群ToolStripMenuItem, + this.修改选中群ToolStripMenuItem, + this.删除选中券ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(137, 70); + // + // 增加发券群ToolStripMenuItem + // + this.增加发券群ToolStripMenuItem.Name = "增加发券群ToolStripMenuItem"; + this.增加发券群ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.增加发券群ToolStripMenuItem.Text = "增加发券群"; + this.增加发券群ToolStripMenuItem.Click += new System.EventHandler(this.增加发券群ToolStripMenuItem_Click); + // + // 修改选中群ToolStripMenuItem + // + this.修改选中群ToolStripMenuItem.Name = "修改选中群ToolStripMenuItem"; + this.修改选中群ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.修改选中群ToolStripMenuItem.Text = "修改选中群"; + this.修改选中群ToolStripMenuItem.Click += new System.EventHandler(this.修改选中群ToolStripMenuItem_Click); + // + // 删除选中券ToolStripMenuItem + // + this.删除选中券ToolStripMenuItem.Name = "删除选中券ToolStripMenuItem"; + this.删除选中券ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.删除选中券ToolStripMenuItem.Text = "删除选中群"; + this.删除选中券ToolStripMenuItem.Click += new System.EventHandler(this.删除选中券ToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn4, + this.gridColumn5, + this.gridColumn6, + this.gridColumn9}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "id"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "群账号"; + this.gridColumn4.FieldName = "group_id"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 164; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "群昵称"; + this.gridColumn5.FieldName = "extend"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 138; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn6.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn6.AppearanceCell.Options.UseFont = true; + this.gridColumn6.AppearanceCell.Options.UseForeColor = true; + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "推广位"; + this.gridColumn6.FieldName = "adzone_name"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 3; + this.gridColumn6.Width = 148; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "禁止使用"; + this.gridColumn9.FieldName = "onoff"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 4; + this.gridColumn9.Width = 109; + // + // xtraTabPage5 + // + this.xtraTabPage5.Name = "xtraTabPage5"; + this.xtraTabPage5.PageVisible = false; + this.xtraTabPage5.Size = new System.Drawing.Size(718, 573); + this.xtraTabPage5.Text = "补位"; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.pageControl2); + this.xtraTabPage2.Controls.Add(this.gridControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(720, 599); + this.xtraTabPage2.Text = " 产 品 列 表 "; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 563); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(720, 36); + this.pageControl2.TabIndex = 15; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemPictureEdit1}); + this.gridControl1.Size = new System.Drawing.Size(720, 557); + this.gridControl1.TabIndex = 14; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中项ToolStripMenuItem, + this.删除所有已发ToolStripMenuItem, + this.删除所有数据ToolStripMenuItem}); + this.contextMenuStrip2.Name = "contextMenuStrip1"; + this.contextMenuStrip2.Size = new System.Drawing.Size(149, 70); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有已发ToolStripMenuItem + // + this.删除所有已发ToolStripMenuItem.Name = "删除所有已发ToolStripMenuItem"; + this.删除所有已发ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有已发ToolStripMenuItem.Text = "删除所有已发"; + this.删除所有已发ToolStripMenuItem.Click += new System.EventHandler(this.删除所有已发ToolStripMenuItem_Click); + // + // 删除所有数据ToolStripMenuItem + // + this.删除所有数据ToolStripMenuItem.Name = "删除所有数据ToolStripMenuItem"; + this.删除所有数据ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有数据ToolStripMenuItem.Text = "删除所有数据"; + this.删除所有数据ToolStripMenuItem.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn18, + this.gridColumn7, + this.gridColumn8, + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "商品ID"; + this.gridColumn1.FieldName = "goods_id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 86; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "商品标题"; + this.gridColumn2.FieldName = "goods_name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 162; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "商品单价"; + this.gridColumn3.FieldName = "normal_price"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 68; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "优惠券金额"; + this.gridColumn18.FieldName = "coupon_discount"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 4; + this.gridColumn18.Width = 89; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "优惠券数量"; + this.gridColumn7.FieldName = "coupon_remain_quantity"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Width = 73; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "佣金比例"; + this.gridColumn8.FieldName = "promotion_rate"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 5; + this.gridColumn8.Width = 66; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "月销量"; + this.gridColumn11.FieldName = "sold_quantity"; + this.gridColumn11.Name = "gridColumn11"; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "发送状态"; + this.gridColumn12.FieldName = "state"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 6; + this.gridColumn12.Width = 63; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "采集日期"; + this.gridColumn13.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn13.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn13.FieldName = "cur_time"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 7; + this.gridColumn13.Width = 100; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "数据来源"; + this.gridColumn14.FieldName = "goods_source"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Width = 83; + // + // repositoryItemPictureEdit1 + // + this.repositoryItemPictureEdit1.Name = "repositoryItemPictureEdit1"; + this.repositoryItemPictureEdit1.SizeMode = DevExpress.XtraEditors.Controls.PictureSizeMode.Stretch; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.xtraScrollableControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(720, 599); + this.xtraTabPage3.Text = " 基 础 设 置 "; + // + // xtraScrollableControl1 + // + this.xtraScrollableControl1.Controls.Add(this.groupBox2); + this.xtraScrollableControl1.Controls.Add(this.groupBox1); + this.xtraScrollableControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraScrollableControl1.Location = new System.Drawing.Point(0, 0); + this.xtraScrollableControl1.Name = "xtraScrollableControl1"; + this.xtraScrollableControl1.Size = new System.Drawing.Size(720, 599); + this.xtraScrollableControl1.TabIndex = 3; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.groupBox4); + this.groupBox2.Controls.Add(this.me_WhiteContent); + this.groupBox2.Controls.Add(this.me_BlackContent); + this.groupBox2.Controls.Add(this.labelControl7); + this.groupBox2.Controls.Add(this.me_WXMsg); + this.groupBox2.Controls.Add(this.labelControl23); + this.groupBox2.Controls.Add(this.me_QQMsg); + this.groupBox2.Controls.Add(this.labelControl22); + this.groupBox2.Controls.Add(this.labelControl24); + this.groupBox2.Controls.Add(this.cb_Short); + this.groupBox2.Controls.Add(this.labelControl8); + this.groupBox2.Controls.Add(this.cb_Model); + this.groupBox2.Controls.Add(this.labelControl17); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.dt_SendTaskTimes2); + this.groupBox2.Controls.Add(this.dt_SendTaskTimes1); + this.groupBox2.Controls.Add(this.labelControl18); + this.groupBox2.Controls.Add(this.nud_qInterval); + this.groupBox2.Controls.Add(this.labelControl6); + this.groupBox2.Controls.Add(this.nud_gInterval); + this.groupBox2.Controls.Add(this.labelControl20); + this.groupBox2.Location = new System.Drawing.Point(28, 164); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(647, 725); + this.groupBox2.TabIndex = 42; + this.groupBox2.TabStop = false; + this.groupBox2.Text = " 朋 友 圈 基 础 设 置 "; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.dt_AutoClearTaskTimes); + this.groupBox4.Controls.Add(this.labelControl30); + this.groupBox4.Controls.Add(this.labelControl29); + this.groupBox4.Controls.Add(this.bc_AutoClearTask); + this.groupBox4.Location = new System.Drawing.Point(34, 640); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(568, 74); + this.groupBox4.TabIndex = 79; + this.groupBox4.TabStop = false; + this.groupBox4.Text = " 清 理 设 置 "; + // + // dt_AutoClearTaskTimes + // + this.dt_AutoClearTaskTimes.CustomFormat = "HH:mm"; + this.dt_AutoClearTaskTimes.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dt_AutoClearTaskTimes.Location = new System.Drawing.Point(442, 31); + this.dt_AutoClearTaskTimes.Name = "dt_AutoClearTaskTimes"; + this.dt_AutoClearTaskTimes.ShowUpDown = true; + this.dt_AutoClearTaskTimes.Size = new System.Drawing.Size(74, 22); + this.dt_AutoClearTaskTimes.TabIndex = 44; + this.dt_AutoClearTaskTimes.Value = new System.DateTime(2020, 9, 14, 9, 0, 0, 0); + // + // labelControl30 + // + this.labelControl30.Location = new System.Drawing.Point(351, 35); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(84, 14); + this.labelControl30.TabIndex = 43; + this.labelControl30.Text = "定时清理时间:"; + // + // labelControl29 + // + this.labelControl29.Location = new System.Drawing.Point(74, 35); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(60, 14); + this.labelControl29.TabIndex = 36; + this.labelControl29.Text = "定时清理:"; + // + // bc_AutoClearTask + // + this.bc_AutoClearTask.BackColor = System.Drawing.Color.Transparent; + this.bc_AutoClearTask.Checked = false; + this.bc_AutoClearTask.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.bc_AutoClearTask.Cursor = System.Windows.Forms.Cursors.Hand; + this.bc_AutoClearTask.Location = new System.Drawing.Point(140, 31); + this.bc_AutoClearTask.Name = "bc_AutoClearTask"; + this.bc_AutoClearTask.Size = new System.Drawing.Size(59, 22); + this.bc_AutoClearTask.TabIndex = 37; + // + // me_WhiteContent + // + this.me_WhiteContent.Location = new System.Drawing.Point(34, 540); + this.me_WhiteContent.Name = "me_WhiteContent"; + this.me_WhiteContent.Size = new System.Drawing.Size(569, 84); + this.me_WhiteContent.TabIndex = 76; + // + // me_BlackContent + // + this.me_BlackContent.Location = new System.Drawing.Point(32, 425); + this.me_BlackContent.Name = "me_BlackContent"; + this.me_BlackContent.Size = new System.Drawing.Size(571, 84); + this.me_BlackContent.TabIndex = 76; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(32, 520); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(84, 14); + this.labelControl7.TabIndex = 73; + this.labelControl7.Text = "白名单关键词:"; + // + // me_WXMsg + // + this.me_WXMsg.Location = new System.Drawing.Point(30, 309); + this.me_WXMsg.Name = "me_WXMsg"; + this.me_WXMsg.Size = new System.Drawing.Size(573, 85); + this.me_WXMsg.TabIndex = 77; + // + // labelControl23 + // + this.labelControl23.Location = new System.Drawing.Point(30, 405); + this.labelControl23.Name = "labelControl23"; + this.labelControl23.Size = new System.Drawing.Size(84, 14); + this.labelControl23.TabIndex = 73; + this.labelControl23.Text = "黑名单关键词:"; + // + // me_QQMsg + // + this.me_QQMsg.Location = new System.Drawing.Point(30, 160); + this.me_QQMsg.Name = "me_QQMsg"; + this.me_QQMsg.Size = new System.Drawing.Size(573, 113); + this.me_QQMsg.TabIndex = 78; + // + // labelControl22 + // + this.labelControl22.Location = new System.Drawing.Point(30, 140); + this.labelControl22.Name = "labelControl22"; + this.labelControl22.Size = new System.Drawing.Size(78, 14); + this.labelControl22.TabIndex = 74; + this.labelControl22.Text = "QQ图文格式:"; + // + // labelControl24 + // + this.labelControl24.Location = new System.Drawing.Point(30, 289); + this.labelControl24.Name = "labelControl24"; + this.labelControl24.Size = new System.Drawing.Size(84, 14); + this.labelControl24.TabIndex = 75; + this.labelControl24.Text = "微信图文格式:"; + // + // cb_Short + // + this.cb_Short.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cb_Short.FormattingEnabled = true; + this.cb_Short.Location = new System.Drawing.Point(385, 104); + this.cb_Short.Name = "cb_Short"; + this.cb_Short.Size = new System.Drawing.Size(116, 22); + this.cb_Short.TabIndex = 70; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(331, 108); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(48, 14); + this.labelControl8.TabIndex = 69; + this.labelControl8.Text = "短连接:"; + // + // cb_Model + // + this.cb_Model.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cb_Model.FormattingEnabled = true; + this.cb_Model.Items.AddRange(new object[] { + "模板A", + "模板B", + "模板C"}); + this.cb_Model.Location = new System.Drawing.Point(156, 104); + this.cb_Model.Name = "cb_Model"; + this.cb_Model.Size = new System.Drawing.Size(116, 22); + this.cb_Model.TabIndex = 70; + // + // labelControl17 + // + this.labelControl17.Location = new System.Drawing.Point(78, 108); + this.labelControl17.Name = "labelControl17"; + this.labelControl17.Size = new System.Drawing.Size(72, 14); + this.labelControl17.TabIndex = 69; + this.labelControl17.Text = "二维码模板:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(230, 42); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(11, 14); + this.label4.TabIndex = 65; + this.label4.Text = "-"; + // + // dt_SendTaskTimes2 + // + this.dt_SendTaskTimes2.CustomFormat = "HH:mm"; + this.dt_SendTaskTimes2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dt_SendTaskTimes2.Location = new System.Drawing.Point(247, 38); + this.dt_SendTaskTimes2.Name = "dt_SendTaskTimes2"; + this.dt_SendTaskTimes2.ShowUpDown = true; + this.dt_SendTaskTimes2.Size = new System.Drawing.Size(57, 22); + this.dt_SendTaskTimes2.TabIndex = 42; + this.dt_SendTaskTimes2.Value = new System.DateTime(2020, 9, 14, 22, 0, 0, 0); + // + // dt_SendTaskTimes1 + // + this.dt_SendTaskTimes1.CustomFormat = "HH:mm"; + this.dt_SendTaskTimes1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dt_SendTaskTimes1.Location = new System.Drawing.Point(166, 38); + this.dt_SendTaskTimes1.Name = "dt_SendTaskTimes1"; + this.dt_SendTaskTimes1.ShowUpDown = true; + this.dt_SendTaskTimes1.Size = new System.Drawing.Size(60, 22); + this.dt_SendTaskTimes1.TabIndex = 42; + this.dt_SendTaskTimes1.Value = new System.DateTime(2020, 9, 14, 9, 0, 0, 0); + // + // labelControl18 + // + this.labelControl18.Location = new System.Drawing.Point(64, 42); + this.labelControl18.Name = "labelControl18"; + this.labelControl18.Size = new System.Drawing.Size(96, 14); + this.labelControl18.TabIndex = 38; + this.labelControl18.Text = "发送任务时间段:"; + // + // nud_qInterval + // + this.nud_qInterval.Location = new System.Drawing.Point(341, 69); + this.nud_qInterval.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_qInterval.Name = "nud_qInterval"; + this.nud_qInterval.Size = new System.Drawing.Size(46, 22); + this.nud_qInterval.TabIndex = 58; + this.nud_qInterval.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(255, 73); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(84, 14); + this.labelControl6.TabIndex = 47; + this.labelControl6.Text = "群间发送间隔:"; + // + // nud_gInterval + // + this.nud_gInterval.Location = new System.Drawing.Point(166, 69); + this.nud_gInterval.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_gInterval.Name = "nud_gInterval"; + this.nud_gInterval.Size = new System.Drawing.Size(55, 22); + this.nud_gInterval.TabIndex = 58; + this.nud_gInterval.Value = new decimal(new int[] { + 300, + 0, + 0, + 0}); + // + // labelControl20 + // + this.labelControl20.Location = new System.Drawing.Point(73, 73); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(84, 14); + this.labelControl20.TabIndex = 47; + this.labelControl20.Text = "商品发送间隔:"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.cb_ConditionType); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.cb_GatherType); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.nud_GatherTouchNum); + this.groupBox1.Controls.Add(this.bc_CJSwitch); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Location = new System.Drawing.Point(28, 19); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(647, 121); + this.groupBox1.TabIndex = 41; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 采 集 设 置 "; + // + // cb_ConditionType + // + this.cb_ConditionType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cb_ConditionType.FormattingEnabled = true; + this.cb_ConditionType.Items.AddRange(new object[] { + "10-20元区", + "20-40元区", + "40元以上区"}); + this.cb_ConditionType.Location = new System.Drawing.Point(423, 79); + this.cb_ConditionType.Name = "cb_ConditionType"; + this.cb_ConditionType.Size = new System.Drawing.Size(132, 22); + this.cb_ConditionType.TabIndex = 41; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(351, 82); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 38; + this.labelControl2.Text = "采集条件:"; + // + // cb_GatherType + // + this.cb_GatherType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cb_GatherType.FormattingEnabled = true; + this.cb_GatherType.Items.AddRange(new object[] { + "独家券商品", + "每日爆品推荐", + "各大榜单", + "九块九包邮精选"}); + this.cb_GatherType.Location = new System.Drawing.Point(162, 79); + this.cb_GatherType.Name = "cb_GatherType"; + this.cb_GatherType.Size = new System.Drawing.Size(132, 22); + this.cb_GatherType.TabIndex = 41; + this.cb_GatherType.SelectedIndexChanged += new System.EventHandler(this.cb_GatherType_SelectedIndexChanged); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(96, 82); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 38; + this.labelControl1.Text = "采集导航:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(351, 40); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(84, 14); + this.labelControl4.TabIndex = 38; + this.labelControl4.Text = "采集触发数量:"; + // + // nud_GatherTouchNum + // + this.nud_GatherTouchNum.Location = new System.Drawing.Point(441, 36); + this.nud_GatherTouchNum.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.nud_GatherTouchNum.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nud_GatherTouchNum.Name = "nud_GatherTouchNum"; + this.nud_GatherTouchNum.Size = new System.Drawing.Size(94, 22); + this.nud_GatherTouchNum.TabIndex = 39; + this.nud_GatherTouchNum.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + // + // bc_CJSwitch + // + this.bc_CJSwitch.BackColor = System.Drawing.Color.Transparent; + this.bc_CJSwitch.Checked = false; + this.bc_CJSwitch.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.bc_CJSwitch.Cursor = System.Windows.Forms.Cursors.Hand; + this.bc_CJSwitch.Location = new System.Drawing.Point(179, 36); + this.bc_CJSwitch.Name = "bc_CJSwitch"; + this.bc_CJSwitch.Size = new System.Drawing.Size(59, 22); + this.bc_CJSwitch.TabIndex = 37; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(87, 40); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 36; + this.labelControl3.Text = "商品采集开关:"; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(544, 40); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(12, 14); + this.labelControl5.TabIndex = 40; + this.labelControl5.Text = "个"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(722, 625); + this.Controls.Add(this.xtraTabControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl2)).EndInit(); + this.xtraTabControl2.ResumeLayout(false); + this.xtraTabPage4.ResumeLayout(false); + this.xtraTabPage4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraScrollableControl1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.me_WhiteContent.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_BlackContent.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_WXMsg.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_QQMsg.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_qInterval)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_gInterval)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nud_GatherTouchNum)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraTab.XtraTabControl xtraTabControl2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private DevExpress.XtraTab.XtraTabPage xtraTabPage5; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 增加发券群ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改选中群ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中券ToolStripMenuItem; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit1; + private DevExpress.XtraEditors.XtraScrollableControl xtraScrollableControl1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.DateTimePicker dt_SendTaskTimes2; + private System.Windows.Forms.DateTimePicker dt_SendTaskTimes1; + private DevExpress.XtraEditors.LabelControl labelControl18; + private System.Windows.Forms.NumericUpDown nud_gInterval; + private DevExpress.XtraEditors.LabelControl labelControl20; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ComboBox cb_ConditionType; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.ComboBox cb_GatherType; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.NumericUpDown nud_GatherTouchNum; + private UI.Framework.Controls.ButtonCheck bc_CJSwitch; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl5; + private System.Windows.Forms.NumericUpDown nud_qInterval; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.MemoEdit me_BlackContent; + private DevExpress.XtraEditors.MemoEdit me_WXMsg; + private DevExpress.XtraEditors.LabelControl labelControl23; + private DevExpress.XtraEditors.MemoEdit me_QQMsg; + private DevExpress.XtraEditors.LabelControl labelControl22; + private DevExpress.XtraEditors.LabelControl labelControl24; + private System.Windows.Forms.ComboBox cb_Model; + private DevExpress.XtraEditors.LabelControl labelControl17; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.DateTimePicker dt_AutoClearTaskTimes; + private DevExpress.XtraEditors.LabelControl labelControl30; + private DevExpress.XtraEditors.LabelControl labelControl29; + private UI.Framework.Controls.ButtonCheck bc_AutoClearTask; + private DevExpress.XtraEditors.MemoEdit me_WhiteContent; + private DevExpress.XtraEditors.LabelControl labelControl7; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有已发ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有数据ToolStripMenuItem; + private System.Windows.Forms.ComboBox cb_Short; + private DevExpress.XtraEditors.LabelControl labelControl8; + } +} \ No newline at end of file diff --git a/应用/CouponsSend/MainForm.cs b/应用/CouponsSend/MainForm.cs new file mode 100644 index 0000000..b55f65c --- /dev/null +++ b/应用/CouponsSend/MainForm.cs @@ -0,0 +1,380 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using CouponsSend.Properties; +using CouponsSend.Entitys; +using Api.Framework.Tools; +using Api.Framework; +using Api.Framework.Model; +using UI.Framework.Controls; +using Api.Framework.Enums; +using Api.Framework.Cps; +using static CouponsSend.Entitys.Enum; +using static Api.Framework.ApiClient; + +namespace CouponsSend +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + bc_CJSwitch.Checked = Class1.Config.Switch == SwitchType.开启; + nud_GatherTouchNum.Value = Class1.Config.GatherTouchNum; + cb_GatherType.SelectedIndex = (int)Class1.Config.GatherType; + + var times = Class1.Config.SendTaskTimes[0].Split('-'); + dt_SendTaskTimes1.Value = DateTime.Parse($"2020-01-01 {times[0]}"); + dt_SendTaskTimes2.Value = DateTime.Parse($"2020-01-01 {times[1]}"); + nud_gInterval.Value = Class1.Config.IntervalTime_Group; + nud_qInterval.Value = Class1.Config.IntervalTime_Coupon; + + cb_Model.SelectedIndex = (int)Class1.Config.qrImageType; + var shortType = EnumHelper.EnumToList(); + cb_Short.Items.AddRange(shortType.Select(f => f.EnumName).ToArray()); + cb_Short.SelectedIndex = (int)Class1.Config.SearchDwzType; + + me_QQMsg.Text = Class1.Config.QQMsg; + me_WXMsg.Text = Class1.Config.WXMsg; + me_WhiteContent.Text = Class1.Config.WhiteContent; + me_BlackContent.Text = Class1.Config.BlackContent; + + bc_AutoClearTask.Checked = Class1.Config.Auto_IsClear == SwitchType.开启; + dt_AutoClearTaskTimes.Value = DateTime.Parse(Class1.Config.AutoClearTaskTimes); + + #region 加载所有采集到的商品 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage("select * from fl_plugin_couponssend_goodsinfos order by state desc", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + #endregion + + #region 加载所有的账号 + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + int totalNumber = 0; + var result = session.Queryable().Where(f => f.custom_type == Resources.SoftwareType).ToPageList(page, size, ref totalNumber); + label1.Visible = result.Count == 0; + return new PageControl.SerchResult() { Result = result, Total = totalNumber }; + }, gridControl2, 40, true, true); + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void Save(FormClosingEventArgs e) + { + try + { + if (dt_SendTaskTimes1.Value > dt_SendTaskTimes2.Value) + throw new Exception("发送任务时间段第一个值不能大于第二个值"); + + Class1.Config.Switch = bc_CJSwitch.Checked ? SwitchType.开启 : SwitchType.关闭; + Class1.Config.GatherTouchNum = (int)nud_GatherTouchNum.Value; + Class1.Config.GatherType = Util.ConvertEnum(cb_GatherType.SelectedIndex); + Class1.Config.SendTaskTimes = new string[] { (dt_SendTaskTimes1.Value.ToString("HH:mm") + "-" + dt_SendTaskTimes2.Value.ToString("HH:mm")) }; + + Class1.Config.IntervalTime_Group = (int)nud_gInterval.Value; + Class1.Config.IntervalTime_Coupon = (int)nud_qInterval.Value; + + Class1.Config.qrImageType = Util.ConvertEnum(cb_Model.SelectedIndex); + Class1.Config.ConditionType = cb_ConditionType.SelectedIndex; + Class1.Config.SearchDwzType = Util.ConvertEnum(cb_Short.SelectedIndex); + + Class1.Config.QQMsg = me_QQMsg.Text; + Class1.Config.WXMsg = me_WXMsg.Text; + Class1.Config.WhiteContent = me_WhiteContent.Text; + Class1.Config.BlackContent = me_BlackContent.Text; + + Class1.Config.Auto_IsClear = bc_AutoClearTask.Checked ? SwitchType.开启 : SwitchType.关闭; + Class1.Config.AutoClearTaskTimes = dt_AutoClearTaskTimes.Value.ToString("HH:mm"); + + } + catch (Exception ex) + { + e.Cancel = true; + BaseForm.ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Save(e); + Util.Save(Class1.Config); + } + + private void 删除选中券ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView2.GetSelectedRows(); + if (rows != null && rows.Length != 0) + { + string id = this.gridView2.GetRowCellValue(rows[0], "id").ToString();//获取列的数据 + if (!string.IsNullOrWhiteSpace(id)) + { + var session = ApiClient.GetSession(); + session.Deleteable().Where(f => f.id == int.Parse(id)).ExecuteCommand(); + } + pageControl2.GotoPage(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 修改选中群ToolStripMenuItem_Click(object sender, EventArgs e) + { + var rows = gridView2.GetSelectedRows(); + if (rows != null && rows.Length != 0) + { + string id = this.gridView2.GetRowCellValue(rows[0], "id").ToString();//获取列的数据 + var form = new EditGroupInfoForm(id); + form.ShowDialog(); + pageControl2.GotoPage(); + } + } + + private void 增加发券群ToolStripMenuItem_Click(object sender, EventArgs e) + { + var form = new EditGroupInfoForm(); + form.ShowDialog(); + pageControl2.GotoPage(); + } + + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "adzone_name" && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView2_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + + var rows = gridView2.GetSelectedRows(); + if (rows != null && rows.Length != 0) + { + string id = this.gridView2.GetRowCellValue(rows[0], "id").ToString();//获取列的数据 + #region 双击单元格设置推广位 + if (e.Clicks >= 2) + { + var session = ApiClient.GetSession(); + if (e.Column.FieldName == "adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + #region 淘宝推广位 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.id == int.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + if (e.Column.FieldName == "adzone_name") + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + } + session.SaveOrUpdate(adzone); + } + #endregion + } + } + pageControl2.GotoPage(1); + session.FindAdzoneInfos(true); + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("确定禁用该群优惠券推送?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.id == int.Parse(id)); + if (adzone != null)//数据库中存在的情况,并且推广位设置了 + adzone.onoff = !adzone.onoff; + session.SaveOrUpdate(adzone); + pageControl2.GotoPage(1); + session.FindAdzoneInfos(true); + } + } + #endregion + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void cb_GatherType_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + cb_ConditionType.Items.Clear(); + object[] objArr = null; + + switch (cb_GatherType.SelectedIndex) + { + case 0: + objArr = new object[] { + "综合排序", + "商品上架时间从高到低", + "销量从高到低", + "领券量从高到低", + "佣金比例从高到低", + "价格(券后价)从高到低", + "价格(券后价)从低到高" }; + break; + case 1: + objArr = new object[] { + "10-20元区", + "20-40元区", + "40元以上区"}; + break; + case 2: + objArr = new object[] { + "实时榜", + "全天榜", + "热推榜", + "复购榜", + "热词飙升榜", + "热词排行榜", + "综合热搜榜"}; + break; + case 3: + objArr = new object[] { + //"精选", + "5.9元区", + "9.9元区", + "19.9元区"}; + break; + default: + break; + } + cb_ConditionType.Items.AddRange(objArr); + cb_ConditionType.SelectedIndex = 0; + if (cb_GatherType.SelectedIndex == (int)Class1.Config.GatherType) + cb_ConditionType.SelectedIndex = Class1.Config.ConditionType; + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose($"异常:{ex.Message}"); + } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView1.GetSelectedRows().ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + List goodsids = new List(); + foreach (var item in rownumber) + { + goodsids.Add("'" + gridView1.GetRowCellValue(item, "goods_id").ToString() + "'");//根据行号获取相应行的数据 + } + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_couponssend_goodsinfos where goods_id in (" + string.Join(",", goodsids) + ")"); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除所有已发ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_couponssend_goodsinfos where state = 0"); + } + + private void 删除所有数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_couponssend_goodsinfos"); + } + + private void RemoveGoodsInfos(string sql) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL(sql); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void xtraTabControl1_TabIndexChanged(object sender, EventArgs e) + { + if (xtraTabControl1.SelectedTabPageIndex == 1) + pageControl1.GotoPage(1); + } + } +} \ No newline at end of file diff --git a/应用/CouponsSend/MainForm.resx b/应用/CouponsSend/MainForm.resx new file mode 100644 index 0000000..194e258 --- /dev/null +++ b/应用/CouponsSend/MainForm.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 274, 17 + + + 56 + + \ No newline at end of file diff --git a/应用/CouponsSend/Properties/AssemblyInfo.cs b/应用/CouponsSend/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8462c38 --- /dev/null +++ b/应用/CouponsSend/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("CouponsSend")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CouponsSend")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("3d53bfc6-1c75-483a-bf7c-6b20f0152c66")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/CouponsSend/Properties/Resources.Designer.cs b/应用/CouponsSend/Properties/Resources.Designer.cs new file mode 100644 index 0000000..40134de --- /dev/null +++ b/应用/CouponsSend/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace CouponsSend.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CouponsSend.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 群发优惠券 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 群发优惠券 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 群发优惠券插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 群发优惠券 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 群发优惠券 { + get { + object obj = ResourceManager.GetObject("群发优惠券", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/CouponsSend/Properties/Resources.resx b/应用/CouponsSend/Properties/Resources.resx new file mode 100644 index 0000000..82727ec --- /dev/null +++ b/应用/CouponsSend/Properties/Resources.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 群发优惠券 + 插件窗体标题 + + + 群发优惠券 + 插件名称 + + + 群发优惠券插件 + 插件介绍 + + + 群发优惠券 + + + + ..\Resources\群发优惠券.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/CouponsSend/Properties/licenses.licx b/应用/CouponsSend/Properties/licenses.licx new file mode 100644 index 0000000..4c687c6 --- /dev/null +++ b/应用/CouponsSend/Properties/licenses.licx @@ -0,0 +1,3 @@ +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/CouponsSend/QuanInfo.cs b/应用/CouponsSend/QuanInfo.cs new file mode 100644 index 0000000..47fc3d3 --- /dev/null +++ b/应用/CouponsSend/QuanInfo.cs @@ -0,0 +1,179 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Tools; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace CouponsSend +{ + public class QuanInfo + { + public string imgUrl { get; set; } + public string duanTitle { get; set; } + public string wenan { get; set; } + public string quanUrl { get; set; } + public string itemUrl { get; set; } + public string itemId { get; set; } + public string activityId { get; set; } + public string sellerId { get; set; } + public QuanInfo(string imageUrl, string duanTitle, string wenan, string quanUrl, string itemUrl) + { + //http://shop.m.taobao.com/shop/coupon.htm?activityId=b3980dab2c9d457ab85d2bd30c756690&sellerId=208479060 + + if (!string.IsNullOrEmpty(imageUrl)) + { + var pic = "http://qun.qq.com/cgi/svr/chatimg/get?pic=" + imageUrl.Replace("{", "").Replace("}", "").Replace("-", ""); + + //var pic = "http://gchat.qpic.cn/gchatpic_new/{0}/{1}-2697951893-{2}/0?term=2&cldver=8.4.5.4745&rf=naio&msgTime={3}&mType=picGd"; + var url = GetLocation(pic); + if (!string.IsNullOrWhiteSpace(url)) + url = url.Replace(@"/gchatpic/", @"/gchatpic_new/"); + else + url = pic; + this.imgUrl = url; + } + this.duanTitle = this.duanTitle; + this.wenan = wenan; + this.quanUrl = quanUrl; + this.itemUrl = itemUrl; + } + public bool CheckOk(AlimamaApi api, string[] pids) + { + var tbAnalysis = new TBHelper.TbAnalysis(); + var item_id = string.Empty; + try + { + item_id = tbAnalysis.FindItemIdByUrlAndTklAndMkl(itemUrl, api, pids); + } + catch (Exception) + { + return false; + } + if (string.IsNullOrWhiteSpace(item_id)) return false; + this.itemId = item_id; + return true; + } + + /// + /// 搜索商品 + /// + //public ItemInfo SerchItem(AlimamaApi api, string q, string adzone_id = "", string site_id = "") + //{ + // try + // { + // var reg = Regex.Match(q, @"id=(\d+)"); + // Dictionary dic = null; + // if (!reg.Success) + // { + // dic = api.SendTaobao("taobao.tbk.sc.material.optional", new { adzone_id = adzone_id, site_id = site_id, q = q }); + // if (dic.ContainsKey("result_list")) + // { + // var result_list = dic["result_list"] as Dictionary; + // if (result_list != null && result_list.ContainsKey("map_data")) + // { + // var map_data = (result_list["map_data"]) as ArrayList; + // if (map_data != null && map_data.Count != 0) + // dic = map_data[0] as Dictionary; + // } + // } + // } + // else + // { + // dic = api.SendTaobao("taobao.tbk.item.info.get", new { num_iids = reg.Groups[1].Value }); + // var n_tbk_item = (dic["n_tbk_item"]) as ArrayList; + // if (n_tbk_item != null && n_tbk_item.Count != 0) + // dic = n_tbk_item[0] as Dictionary; + // } + + // ItemInfo info = new ItemInfo() + // { + // item_id = dic["num_iid"].ToString(), + // item_url = dic["item_url"].ToString(), + // pict_url = dic["pict_url"].ToString(), + // seller_id = dic["seller_id"].ToString(), + // quan_price = 0, + // reserve_price = double.Parse(dic["reserve_price"].ToString()), + // zk_final_price = double.Parse(dic["zk_final_price"].ToString()), + // title = dic["title"].ToString() + // }; + // return info; + // } + // catch (Exception ex) + // { + // if (!ex.Message.Contains("无结果") && !ex.Message.Contains("已过期")) + // EventClient.OnEvent(this, $"SerchItem:{ex.Message}"); + // } + // return null; + //} + + /// + /// + /// + /// + /// + private string GetLocation(string url) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = "get", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = "", + Timeout = 5000, + ReadWriteTimeout = 15000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = false, + ProxyIp = "" + }; + HttpResult result = http.GetHtml(item); + return result.Header.Get("Location"); + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"Location:{url},{ex.Message},{ex.StackTrace}"); + } + return string.Empty; + } + + } + + public class ItemInfo + { + public string item_url { get; set; } + public string pict_url { get; set; } + public string item_id { get; set; } + public string seller_id { get; set; } + public double reserve_price { get; set; } + public string title { get; set; } + public double zk_final_price { get; set; } + public double quan_price { get; set; } + private double _max_commission_rate; + public double max_commission_rate + { + get { return _max_commission_rate; } + set + { + tkCommFee = Math.Round((zk_final_price - quan_price) * (value / 100.00), 2); + _max_commission_rate = value; + + } + } + public double tkCommFee { get; set; } + + } + +} diff --git a/应用/CouponsSend/ReceiveMsg.cs b/应用/CouponsSend/ReceiveMsg.cs new file mode 100644 index 0000000..a4266d8 --- /dev/null +++ b/应用/CouponsSend/ReceiveMsg.cs @@ -0,0 +1,26 @@ +using CouponsSend.Entitys; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CouponsSend +{ + public class ReceiveMsg : EventArgs + { + public Group Group { get; set; } + + public string Message { get; set; } + + public string GetImg(string imgCode) + { + return "http://qun.qq.com/cgi/svr/chatimg/get?pic=" + imgCode; + } + public ReceiveMsg(Group group, string Message) + { + this.Group = group; + this.Message = Message; + } + } +} diff --git a/应用/CouponsSend/Resources/群发优惠券.png b/应用/CouponsSend/Resources/群发优惠券.png new file mode 100644 index 0000000..b584d73 Binary files /dev/null and b/应用/CouponsSend/Resources/群发优惠券.png differ diff --git a/应用/CouponsSend/SendCouponThread.cs b/应用/CouponsSend/SendCouponThread.cs new file mode 100644 index 0000000..d43ae58 --- /dev/null +++ b/应用/CouponsSend/SendCouponThread.cs @@ -0,0 +1,308 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk; +using CouponsSend.Entitys; +using CouponsSend.Properties; +using CsharpHttpHelper; +using SqlSugar; +using System; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using static Api.Framework.Tools.TBHelper; +using static CouponsSend.Entitys.Enum; + +namespace CouponsSend +{ + public class SendCouponThread : TimerTask + { + public DateTime quanTime; + SqlSugarClient session = ApiClient.GetSession(); + AnalyzeGoods analyzeGoods = new AnalyzeGoods(); + private bool IsRunning = false; + public override void Run(object state, bool timedOut) + { + if (IsRunning) return; + + try + { + IsRunning = true; + + #region 定时清空采集的数据 + if (!string.IsNullOrWhiteSpace(Class1.Config.AutoClearTaskTimes)) + { + if (Class1.Config.Auto_IsClear == SwitchType.开启) + { + try + { + if (DateTime.Now.AddSeconds(-3).ToString("HHmm") == DateTime.Parse(Class1.Config.AutoClearTaskTimes).ToString("HHmm")) + { + //session.ExcuteSQL("Delete from fl_plugin_couponssend_goodsinfos", new { }); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, "定时清理异常" + ex.Message + "-" + ex.StackTrace); + } + } + } + #endregion + + + var isSendTime = false; //是否是发送时间段内 + + if (Class1.Config.NotCheckTime == SwitchType.关闭) + { + //检查时间限制 + if (Class1.Config.SendTaskTimes != null && Class1.Config.SendTaskTimes.Length != 0) + { + var now = DateTime.Now; + foreach (var item in Class1.Config.SendTaskTimes) + { + try + { + var times = item.Trim().Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries); + if (times.Length != 2) throw new Exception("设置的时间段格式不正确"); + var begin = DateTime.Parse(times[0].Trim()); + var end = DateTime.Parse(times[1].Trim()); + if (begin <= now && now <= end) + { + isSendTime = true; + break; + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"{ex.Message} - {ex.StackTrace}"); + } + } + } + } + else isSendTime = true;//不限发送开启 + + if (!isSendTime) return;//不在发送时间终止 + + //删除N天前的数据 + session.ExcuteSQL("Delete from fl_plugin_couponssend_goodsinfos where cur_time <= @time", new { time = DateTime.Today.AddDays(-3) }); + + #region 采集数据 + if (Class1.Config.Switch == SwitchType.开启) + { + var num = session.Find("select * from fl_plugin_couponssend_goodsinfos where state = @state", new { state = StateType.未推广 }).Count(); + if (num <= Class1.Config.GatherTouchNum) + analyzeGoods.GatherFactory(); + } + #endregion + + #region 发送 + //未选择发送的群 + var adzones = session.Find("select * from fl_adzone_info where custom_type = @custom_type and onoff = @onoff", new { custom_type = Resources.SoftwareType, onoff = false }); + var wxGroups = adzones.Where(f => f.group_id.Contains("@") || f.group_id.Contains("R:")).ToList();//微信发送列表 + var qqGroups = adzones.Where(f => !f.group_id.Contains("@") && !f.group_id.Contains("R:")).ToList();//微信发送列表 + + if (qqGroups.Count == 0 && wxGroups.Count == 0) return; + + var goods_info = session.FindSingle($"select * from fl_plugin_couponssend_goodsinfos where state = 1 order by cur_time desc"); + + if (goods_info == null) throw new Exception("没有可发送的商品"); + + if (!string.IsNullOrEmpty(Class1.Config.BlackContent)) + { + var tempReg = Regex.Match(goods_info.goods_name, "(" + Class1.Config.BlackContent.Replace(",", ",").Replace(",", "|") + ")"); + if (tempReg.Success) return; + } + if (!string.IsNullOrEmpty(Class1.Config.WhiteContent)) + { + var tempReg = Regex.Match(goods_info.goods_name, "(" + Class1.Config.WhiteContent.Replace(",", ",").Replace(",", "|") + ")"); + if (!tempReg.Success) return; + } + + + if (quanTime > DateTime.Now) return; + + //商品介绍 + var introduce = goods_info.goods_desc; + + //随便找一个推广位 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && !string.IsNullOrWhiteSpace(f.adzone_pid)); + if (adzone == null) + adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && !string.IsNullOrWhiteSpace(f.adzone_pid)); + if (adzone == null) return; + var cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + if (cps == null) throw new Exception("群发优惠券推广位设置异常!"); + AlimamaApi api = CpsClient.CreateAlimamaRequest(cps); + + var pid_split = adzone.adzone_pid.Split('_'); + + //string adzone_id = pid_split[3]; + //string site_id = pid_split[2]; + + try + { + #region 微信群发送 + var wxTask = Task.Run(() => + { + var _session = ApiClient.GetSession(); + var wxClient = ChatClient.WXClient.Values.ToList().Where(f => f.Status == WxStatus.在线); + foreach (var item in wxGroups) + { + if (string.IsNullOrWhiteSpace(item.adzone_pid)) continue; + var robot = _session.FindRobots().FirstOrDefault(f => f.id == item.robot_id); + if (robot == null) continue; + var wx = wxClient.FirstOrDefault(f => f.WeixinHao == robot.name); + if (wx == null) continue; + var ipad = wx; //as WXClientImpl_IPAD; + if (ipad == null) continue; + var group = ipad.GetContact(item.group_id); + if (group == null) continue; + try + { + var msg = GetSendMsg(api, pid_split, item, goods_info, Class1.Config.WXMsg); + + if (string.IsNullOrWhiteSpace(msg)) return; + + ApiClient.SendMessage(robot, string.Empty, msg, item.group_id); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"发送群:{item.group_id} - {ex.Message} - {ex.StackTrace}"); + continue; + } + Thread.Sleep(Class1.Config.IntervalTime_Group * 1000 + new Random().Next(100, 1000)); + } + }); + #endregion + + #region QQ群发送 + var qqTask = Task.Run(() => + { + var _session = ApiClient.GetSession(); + var qqClient = ChatClient.QQClients.Values; + foreach (var item in qqGroups) + { + if (string.IsNullOrWhiteSpace(item.adzone_pid)) continue; + var robot = _session.FindRobots().FirstOrDefault(f => f.id == item.robot_id); + if (robot == null) continue; + var qq = qqClient.FirstOrDefault(f => f.QQ.ToString() == robot.name); + if (qq == null) continue; + if (!qq.IsLogin) continue; + + try + { + var msg = GetSendMsg(api, pid_split, item, goods_info, Class1.Config.QQMsg); + + if (string.IsNullOrWhiteSpace(msg)) return; + + ApiClient.SendMessage(robot, string.Empty, msg, item.group_id); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"发送群:{item.group_id} - {ex.Message} - {ex.StackTrace}"); + continue; + } + Thread.Sleep(Class1.Config.IntervalTime_Group * 1000 + new Random().Next(100, 1000)); + } + }); + #endregion + + Task.WaitAll(wxTask, qqTask); + + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"发送失败:{ex.Message} - {ex.StackTrace}"); + } + //} + quanTime = DateTime.Now.AddSeconds(Class1.Config.IntervalTime_Coupon); + #endregion + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"解析群发优惠券消息异常:{ex.Message} - {ex.StackTrace}"); + } + finally + { + IsRunning = false; + } + } + + private string GetSendMsg(AlimamaApi api, string[] pid_split, fl_adzone_info item, fl_plugin_couponssend_goodsinfos goods_info, string mess) + { + try + { + var _cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == item.adzone_pid_cps_name); + if (_cps == null) throw new Exception("阿里妈妈异常请重新登录!"); + AlimamaApi _api = CpsClient.CreateAlimamaRequest(_cps); + pid_split = item.adzone_pid.Split('_'); + + var turnItem = api.TurnItemId(goods_info.goods_id, goods_info.goods_quan, pid_split[3], pid_split[2], "2"); + + var coupon_price = goods_info.coupon_discount; + + //券后 总佣金 + var useCoupon_totalCommFee = (double)turnItem.CommissionUseCouponMoney; + //用券后 给用户的佣金 + var useCoupon_commFee = session.FindItemPoint(null, useCoupon_totalCommFee, 1, CpsType.阿里妈妈); + + var tbAnalysis = new TbAnalysis(); + + //淘口令的前/后符号有没有设置.有设置将替换掉 + var tkl = tbAnalysis.ReplaceTklModifier(turnItem.BuyPass); + + var composeUrl = api.ComposeTbClick(goods_info.goods_id, "https://img.alicdn.com/tfs/TB1MaLKRXXXXXaWXFXXXXXXXXXX-480-260.png", tkl, turnItem.BuyUrl, true, item.adzone_pid, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品, (int)Class1.Config.SearchDwzType);//中间页地址 + + //[机器人账号]、[机器人昵称]、[商品标题]、[商品原价]、[优惠券金额]、[券后价]、[商品主图]、[积分名称]、[月销量]、[返利积分]、[购买地址]、[购买中间页地址]、[购买淘口令]、[共节省]、[商品图片]、[文案] XML:[图片地址] + + string QRPic = string.Empty; + if (Class1.Config.WXMsg.Contains("[商品图片]")) + { + QRPic = ApiClient.GetQRImage(goods_info.goods_name, goods_info.normal_price.ToString(), coupon_price.ToString(), goods_info.actual_price.ToString(), goods_info.goods_thumbnail_url, composeUrl, Class1.Config.qrImageType, CpsType.阿里妈妈, goods_info.goods_desc); + if (!string.IsNullOrWhiteSpace(QRPic)) + QRPic = $"[图片={QRPic}]"; + } + if (goods_info.state != StateType.已推广) + { + goods_info.state = StateType.已推广; + goods_info = session.Saveable(goods_info).ExecuteReturnEntity(); + } + + return mess.Replace("[商品标题]", goods_info.goods_name) + .Replace("[商品原价]", goods_info.normal_price.ToString("0.00")) + .Replace("[商品主图]", $"[图片={goods_info.goods_thumbnail_url}]") + .Replace("[月销量]", "0") + .Replace("[返利积分]", useCoupon_commFee.UserPoint.ToString("0.00")) + .Replace("[券后价]", goods_info.actual_price.ToString("0.00")) + .Replace("[优惠券金额]", goods_info.coupon_discount.ToString("0.00")) + .Replace("[购买地址]", turnItem.BuyUrl) + .Replace("[购买中间页地址]", composeUrl) + .Replace("[购买淘口令]", tkl) + .Replace("[共节省]", (goods_info.coupon_discount + useCoupon_commFee.UserPoint).ToString("0.00")) + .Replace("[商品图片]", QRPic) + .Replace("[图片地址]", goods_info.goods_thumbnail_url) + .Replace("[文案]", goods_info.goods_desc); + } + catch (Exception ex) + { + } + return string.Empty; + } + + public double QueryDsr(string sellerId, string itemId) + { + string html = new HttpHelper().GetHtml("https://dsr-rate.tmall.com/list_dsr_info.htm?itemId=" + itemId + "&sellerId=" + sellerId + "&_ksTS=" + HttpExtend.GetTimeStamp() + "_194&callback=jsonp195").Html; + var reg = Regex.Match(html, "gradeAvg\":([^,]+)"); + if (reg.Success) + { + return double.Parse(reg.Groups[1].Value); + } + return 0.00; + } + + } +} diff --git a/应用/DYRebate/Class1.cs b/应用/DYRebate/Class1.cs new file mode 100644 index 0000000..82776d8 --- /dev/null +++ b/应用/DYRebate/Class1.cs @@ -0,0 +1,505 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using DYRebate.Entitys; +using DYRebate.Properties; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Timers; +using Chat.Framework; + +namespace DYRebate +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.抖音; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + + #endregion + + private System.Timers.Timer timersTimer = null; + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + + if (session.TableExist()) + { + + var dytgws = session.Find("select * from fl_plugin_dyrebate_dytgw").ToList(); + if (dytgws != null) + { + foreach (var item in dytgws) + { + //插入主推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_chief_name, //推广位名称 + adzone_pid = item.pid_chief, //推广位pid + adzone_pid_cps_name = item.pid_chief_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.抖音联盟, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "chief" + }).ExecuteCommand(); + //插入副推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_deputy_name, //推广位名称 + adzone_pid = item.pid_deputy, //推广位pid + adzone_pid_cps_name = item.pid_deputy_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.抖音联盟, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "deputy" + }).ExecuteCommand(); + } + } + session.DropTable(); + } + + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("cpsname", "pid"); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + + timersTimer = new System.Timers.Timer(); + timersTimer.Enabled = true; + timersTimer.Interval = 5 * 60 * 1000; + timersTimer.Elapsed += new ElapsedEventHandler(timersTimer_Elapsed); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + #region 清空抖音商品缓存 + private void timersTimer_Elapsed(object sender, ElapsedEventArgs e) + { + try + { + var cpss = CpsClient.Members.Where(f => f.cpstype == CpsType.抖音联盟).ToList(); + if (cpss != null && cpss.Count != 0) + { + for (int i = 0; i < cpss.Count; i++) + { + var cps = cpss[i]; + Task.Run(() => + { + var api = CpsClient.CreateDouyinRequest(cps); + if (api != null) + { + int total = 0; + do + { + var list = api.FindGoodsWindowUrls(out total); + if (list != null && list.Count != 0) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.PromotionWhiteList)) + { + var whiteList = Config.PromotionWhiteList.Replace(",", ",").Split(',').Where(f => !string.IsNullOrWhiteSpace(f)).Select(f => f.Trim()).ToList(); + for (int z = 0; z < whiteList.Count; z++) + { + if (list.Contains(whiteList[z])) + list.Remove(whiteList[z]); + } + } + api.DelGoodsWindowUrls(list); + } + Thread.Sleep(2000); + } while (total >= 20); + } + }); + Thread.Sleep(10); + } + } + } + catch (Exception ex) + { } + } + #endregion + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + timersTimer.Close(); + SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + //过滤表情xml和卡片xml + if ((e.Message.Contains(@" + /// 订单通知 + /// + /// + /// + public void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.ChatType == CpsType.抖音联盟) + { + //this.OnLog("淘宝订单:" + HttpHelper.ObjectToJson(e)); + var session = ApiClient.GetSession(); + //订单信息 + var order_dy = e.Order as fl_order_douyin; + + if (order_dy == null) return; + + if (e.Member != null) + { + #region 订单变化通知消息 + var robot_info = session.FindRobotInfo(e.Member.robot_name.Trim(), e.Member.robot_type); + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject(order_dy.db_point) as ItemPoint; + + #region 下单用户订单检测(防撸) + if (e.Customer == null) + { + var prevent_theft_cache = session.FindSingle("select * from fl_prevent_theft_cache where order_id = @order_id", new { order_id = order_dy.order_id });//防止上级多次触发 + if (prevent_theft_cache == null) + { + #region 收货时间验证时长 + + var status = Util.ConvertEnum(order_dy.order_status); + if (Class1.Config.ReceivingTimeCheck_Switch && (status == DouyinOrderStatus.CONFIRM || status == DouyinOrderStatus.SETTLE) && e.Member.status != MemberType.白名单) + { + if (order_dy.confirm_time != 0 && order_dy.confirm_time != 1) + { + var confirmTime = HttpExtend.GetDateTime(order_dy.confirm_time.ToString()); + var payTime = HttpExtend.GetDateTime(order_dy.pay_time.ToString()); + + var timeLag = (int)Math.Floor((confirmTime - payTime).TotalHours); + if (timeLag <= Class1.Config.ReceivingTimeCheck_Hour) + { + if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_dy, e.Member, point), order_dy.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + e.Cancel = true; + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.ReceivingTimeCheck_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_dy.product_id.ToString(); + prevent_theft_cache.order_id = order_dy.order_id.ToString(); + prevent_theft_cache.cps_type = CpsType.抖音联盟; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.ReceivingTimeCheck_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name); + if (wx != null) + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + return; + } + } + else if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + } + } + + } + } + #endregion + + } + } + #endregion + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + { + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + mess = _GetOrderStateMess(order_dy.db_status, SettleType.未结算提示, order_dy, e.Member, point); + + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order_dy.msg_groupid); + } + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order_dy.db_status == SystemOrderStatus.全额退款) + mess = Config.ClientOrderRefund_OneLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_dy.db_status == SystemOrderStatus.全额退款) + mess = Config.ClientOrderRefund_TwoLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_dy.db_status == SystemOrderStatus.全额退款) + mess = Config.ClientOrderRefund_ThreeLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order_dy.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_dy.db_status == SystemOrderStatus.全额退款) + mess = Config.ClientOrderRefund_LeaderTip; + else if (order_dy.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order_dy.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order_dy.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + //ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_tb, e.Member, point).Replace("[下级昵称]", string.IsNullOrEmpty(e.Customer.realnick) ? e.Customer.usernick : e.Customer.realnick)); + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_dy, e.Member, point).Replace("[下级昵称]", e.Customer.realnick ?? "")); + } + #endregion + } + else + { + #region 多人查询通知消息 + var querys = session.Find("select robot_name,type,userid from fl_query_hist where itemid=@itemid and adzoneid = @adzoneid and userid > 0 and crt_time>@time and is_multiple =@is_multiple group by userid,type,robot_name", new { itemid = order_dy.product_id, adzoneid = order_dy.db_cpsname, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss"), is_multiple = false }); + if (querys.Count > 0) + { + for (int i = 0; i < querys.Count; i++) + { + try + { + if (querys[i].type != CpsType.阿里妈妈) continue; + //未绑定的数量 + var unbound_count = int.Parse(session.FindTable($"select count(id) as num from fl_order_douyin where order_id = @order_id and db_userid != 0", new { order_id = order_dy.order_id }).Rows[0]["num"].ToString()); + if (unbound_count != 0) break;//已经被绑定直接停止 + + var queryhist_temp = querys[i]; + var userid = queryhist_temp.userid; + var robot_name = queryhist_temp.robot_name; + var robot_info = session.Find("select * from fl_robot_info where name = @name", new { name = robot_name }).FirstOrDefault();//机器人类型应该是没有的,直接通过机器人name查询机器人信息 + if (robot_info != null) + { + Thread.Sleep(5000); + var wxbase = Chat.Framework.ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot_name); + if (wxbase != null /*&& wxbase.WeixinType == WeixinType.Grpc微信*/ && wxbase.Status == WxStatus.在线) + { + var member = session.FindMemberInfoById(userid); + if (member != null) + { + ApiClient.SendMessage(robot_info, member.username, Config.LotUserQueryBindTip.Replace("[商品标题]", order_dy.product_name)); + + session.ExcuteSQL("update fl_query_hist set is_multiple = @is_multiple where itemid = @itemid and adzoneid = @adzoneid and robot_name = @robotname and userid = @userid", new { is_multiple = true, itemid = order_dy.product_id, adzoneid = order_dy.db_cpsname, robotname = robot_name, userid = member.id }); + } + } + } + } + catch (Exception) + { } + } + } + #endregion + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// + /// 订单状态 提示语替换 + /// + /// + /// + /// + public static string _GetOrderStateMess(SystemOrderStatus order, SettleType settle, params object[] objs) + { + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.订单维权中: + //mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(settle == SettleType.未结算提示 ? Config.OrderSettlementTip : Config.OrderAlreadySettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Config.OrderFreezeTip, objs); + break; + case SystemOrderStatus.全额退款: + mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + } + return mess; + } + + /// + /// 结账提示类型 + /// + public enum SettleType + { + 已结算提示 = 0, + 未结算提示 = 1 + } + + } +} diff --git a/应用/DYRebate/Comm.cs b/应用/DYRebate/Comm.cs new file mode 100644 index 0000000..a70aed1 --- /dev/null +++ b/应用/DYRebate/Comm.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; + +namespace DYRebate +{ + public class Comm + { + + public static bool SetCache(string key, string value, int seconds = 180) + { + try + { + var MD5 = CsharpHttpHelper.HttpExtend.GetMD5String($"{key}"); + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[MD5]; + if (item == null) + cache.Insert(MD5, value, null, DateTime.Now.AddSeconds(seconds), System.Web.Caching.Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + /// + /// 获取缓存数据 + /// + /// + /// + /// + /// + public static string GetCache(string key) + { + try + { + var MD5 = CsharpHttpHelper.HttpExtend.GetMD5String($"{key}"); + Cache cache = HttpRuntime.Cache; + object item = cache[MD5]; + return item?.ToString(); + } + catch (Exception) + { } + return null; + } + + } +} diff --git a/应用/DYRebate/Config.cs b/应用/DYRebate/Config.cs new file mode 100644 index 0000000..fd8be3d --- /dev/null +++ b/应用/DYRebate/Config.cs @@ -0,0 +1,956 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace DYRebate +{ + [Config(Name = "插件-抖音返利-配置")] + public class Config + { + #region 消费积分设置 + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("01.主账号使用条件 - 购物积分"), DefaultValue(20), + Description(@"用户消费积分≥主账号使用条件,才会使用主账号,否则均使用副账号(可以理解为:小号账号) +注:01、02条件为并且关系,两个都要满足") + ] + public int Point { get; set; } + + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("02.主账号使用条件 - 订单笔数"), DefaultValue(20), + Description(@"用户交易订单数≥主账号使用条件,才会使用主账号,否则均使用副账号(可以理解为:小号账号) +注:01、02条件为并且关系,两个都要满足") + ] + public int OrderNum { get; set; } + + + /// + /// 综合查询返利模式 + /// + [ + Category("1)、基础设置"), DisplayName(@"03.综合查询返利模式"), DefaultValue(SwitchType.开启), Description(@"开启综合查询返利模式时,返回的内容为口令或口令+链接; +关闭时只返回口令+连接") + ] + public SwitchType AllRebateModelSwitch { get; set; } = SwitchType.开启; + + #endregion + + #region 提示语 + /// + /// 正在搜索宝贝提示语 + /// + [ + Category("2)、商品查询"), DisplayName("03.正在搜索宝贝"), DefaultValue(@"优惠信息查询中....."), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchingTip { get; set; } + + /// + /// 搜索宝贝无佣金 + /// + [ + Category("2)、商品查询"), DisplayName("04.无佣金时提示"), DefaultValue(@"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchNoCommissionTip { get; set; } + + /// + /// 无优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("05.无优惠券时提示 - 链接"), DefaultValue(@"1:/一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +购买口令: +[购买口令] +━┉┉┉┉∞┉┉┉┉━ +复制内容到抖音聊天窗口并发送,点击链接购买! +下单10分钟后会收到【绑定成功】提示,没有请复制订单编号给我[分段]购买地址: +[购买地址]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[店铺名称]、[返利积分]、[购买地址]、[购买口令]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithoutCouponTip { get; set; } + + /// + /// 无优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("06.无优惠券时提示 - 口令"), DefaultValue(@"3:/一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +购买口令: +[购买口令] +━┉┉┉┉∞┉┉┉┉━ +复制内容到抖音跳转至购买窗口! +下单10分钟后会收到【绑定成功】提示,没有请复制订单编号给我"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[店铺名称]、[返利积分]、[购买口令]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithoutCouponTip_kl { get; set; } + + /// + /// 有优惠券提示语 + /// + [ + Category("2)、商品查询"), DisplayName("07.有优惠券时提示 - 链接"), DefaultValue(@"1:/一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +购买口令: +[购买口令] +━┉┉┉┉∞┉┉┉┉━ +复制内容到抖音聊天窗口并发送,点击链接购买! +下单10分钟后会收到【绑定成功】提示,没有请复制订单编号给我[分段]购买地址: +[购买地址]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[购买口令]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithCouponTip { get; set; } + + /// + /// 有优惠券提示语 + /// + [ + Category("2)、商品查询"), DisplayName("08.有优惠券时提示 - 口令"), DefaultValue(@"3:/一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +购买口令: +[购买口令] +━┉┉┉┉∞┉┉┉┉━ +复制内容到抖音跳转至购买窗口! +下单10分钟后会收到【绑定成功】提示,没有请复制订单编号给我"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买口令]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithCouponTip_kl { get; set; } + + /// + /// 无优惠券时提示(QQ) - 链接 + /// + [ + Category("2)、商品查询"), DisplayName("09.无优惠券时提示(QQ) - 链接"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""无优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[店铺名称]、[返利积分]、[购买地址]、[购买口令]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithoutCouponTip { get; set; } + + /// + /// 无优惠券时提示(QQ) - 口令 + /// + [ + Category("2)、商品查询"), DisplayName("10.无优惠券时提示(QQ) - 口令"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""无优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[店铺名称]、[返利积分]、[购买地址]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithoutCouponTip_kl { get; set; } + + /// + /// 有优惠券提示语(QQ) - 链接 + /// + [ + Category("2)、商品查询"), DisplayName("11.有优惠券时提示(QQ) - 链接"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""有优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[购买口令]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithCouponTip { get; set; } + + /// + /// 有优惠券提示语(QQ) - 口令 + /// + [ + Category("2)、商品查询"), DisplayName("12.有优惠券时提示(QQ) - 口令"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""有优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithCouponTip_kl { get; set; } + + [ + Category("2)、商品查询"), DisplayName("13.返利短网址"), DefaultValue(DwzType.官方短网址), + Description(@"抖音商品转链后,使用的短连接类型") +] + public DwzType Dwz_Type { get; set; } = DwzType.官方短网址; + #endregion + + #region 订单通知 + + /// + /// 用户订单变化通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"01.用户订单变化通知"), DefaultValue(SwitchType.开启), Description(@"开启用户订单变化通知功能时,用户的订单发生变化时,将通知用户订单的情况") + ] + public SwitchType UserOrderChangeSwitch { get; set; } + /// + /// 代理获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"02.代理获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启代理获得提成通知功能时,用户的订单发生变化时,将通知代理获得提成信息") + ] + public SwitchType AgentReceivedCommissionSwitch { get; set; } + /// + /// 群负责人获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"03.群负责人获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启群负责人获得提成通知功能时,用户的订单发生变化时,将通知群负责人获得提成信息") + ] + public SwitchType PrincipalReceivedCommissionSwitch { get; set; } + + /// + /// 绑定订单号非本人提示语 + /// + [Category("3)、订单通知"), DisplayName("04.已被其他用户绑定"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OccupyOrderErrorTip { get; set; } + + /// + /// 订单号未找到提示语 + /// + [Category("3)、订单通知"), DisplayName("05.未找到订单号"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过购买地址下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string NotFoundOrderErrorTip { get; set; } + + /// + /// 重复绑定订单号 + /// + [Category("3)、订单通知"), DisplayName("06.重复绑定订单号"), DefaultValue(@"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRepetBindTip { get; set; } + + /// + /// 订单付款提示语 + /// + [Category("3)、订单通知"), DisplayName("07.订单付款"), DefaultValue(@"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentTip { get; set; } + + /// + /// 订单付款通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("08.订单付款通知一级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_OneLevelTip { get; set; } + + /// + /// 订单付款通知二级 + /// + [Category("3)、订单通知"), DisplayName("09.订单付款通知二级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_TwoLevelTip { get; set; } + + /// + /// 订单付款通知三级 + /// + [Category("3)、订单通知"), DisplayName("10.订单付款通知三级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_ThreeLevelTip { get; set; } + + /// + /// 订单付款通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("11.订单付款通知群负责人"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_LeaderTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("12.订单冻结"), DefaultValue(@"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFreezeTip { get; set; } + + /// + /// 订单已经结算提示语 + /// + [Category("3)、订单通知"), DisplayName("13.订单已经结算"), DefaultValue(@"一一一一订 单 已 经 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【订单状态】该订单已经完成结算,请勿重复提交 +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderAlreadySettlementTip { get; set; } + + /// + /// 订单结算提示语 + /// + [Category("3)、订单通知"), DisplayName("14.订单结算"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlementTip { get; set; } + + // /// + // /// 订单冻结提示语 + // /// + // [Category("3)、订单通知"), DisplayName("15.订单结算 - 全额退款"), DefaultValue(@"一一一一订 单 结 算一一一一 + //[商品标题] + //【订单编号】[订单号] + //【付款金额】[付款金额] 元 + //【维权金额】[维权金额] 元 + //【返利积分】[返利积分] [积分名称] + //一一一一一一一一一一一一一 + //由于订单维权,全额退款,佣金为0 + //发送关键词:账单 (可查详细信息)"), + // Description(@"订单维权成功提示,维权类型为全额退款 + //支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[维权金额]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + // public string OrderFrozen_AllTip { get; set; } + + // /// + // /// 订单部分退款提示语 + // /// + // [Category("3)、订单通知"), DisplayName("16.订单结算 - 部分退款"), DefaultValue(@"一一一一订 单 结 算一一一一 + //[商品标题] + //【订单编号】[订单号] + //【付款金额】[付款金额] 元 + //【原始返利积分】[原始返利积分] [积分名称] + //【维权返利积分】[维权返利积分] [积分名称] + //【可兑换积分】[可兑换积分] [积分名称] + //一一一一一一一一一一一一一 + //由于订单维权,部分退款,返利将相应减少 + //发送关键词:兑换 (可兑换现金哦) + //发送关键词:账单 (可查详细信息)"), + // Description(@"订单维权成功提示,维权类型为部分退款 + //支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[原始返利积分]、[维权返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + // public string OrderFrozen_PartTip { get; set; } + + /// + /// 一级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("16.一级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_OneLevelTip { get; set; } + + /// + /// 二级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("17.二级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_TwoLevelTip { get; set; } + + /// + /// 三级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("18.三级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_ThreeLevelTip { get; set; } + + /// + /// 群负责人获得提成 + /// + [Category("3)、订单通知"), DisplayName("19.群负责人获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_LeaderTip { get; set; } + + /// + /// 订单退款提示语 + /// + [Category("3)、订单通知"), DisplayName("20.订单申请维权"), DefaultValue(@"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"用户申请退款通知改提示 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRefundTip { get; set; } + + /// + /// 客户维权一级代理 + /// + [Category("3)、订单通知"), DisplayName("21.客户维权一级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_OneLevelTip { get; set; } + + /// + /// 客户维权二级代理 + /// + [Category("3)、订单通知"), DisplayName("22.客户维权二级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_TwoLevelTip { get; set; } + + /// + /// 客户维权三级代理 + /// + [Category("3)、订单通知"), DisplayName("23.客户维权三级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_ThreeLevelTip { get; set; } + + /// + /// 客户维权群负责人 + /// + [Category("3)、订单通知"), DisplayName("24.客户维权群负责人"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_LeaderTip { get; set; } + + /// + /// 订单失效提示语 + /// + [Category("3)、订单通知"), DisplayName("25.订单失效"), DefaultValue(@"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFailureTip { get; set; } + + + /// + /// 订单失效通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("26.订单失效通知一级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_OneLevelTip { get; set; } + + /// + /// 订单失效通知二级 + /// + [Category("3)、订单通知"), DisplayName("27.订单失效通知二级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_TwoLevelTip { get; set; } + + /// + /// 订单失效通知三级 + /// + [Category("3)、订单通知"), DisplayName("28.订单失效通知三级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_ThreeLevelTip { get; set; } + + /// + /// 订单失效通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("29.订单失效通知群负责人"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_LeaderTip { get; set; } + + + // + /// 宝贝多人查询提示绑定 + /// + [Category("3)、订单通知"), DisplayName("30.宝贝多人查询提示绑定"), DefaultValue(@"一一一一绑 定 提 示一一一一 +【商品标题】[商品标题] +该商品被多人查询系统无法匹配是谁下单,请亲手动到抖音复制订单号给我手动绑定该订单"), + Description(@"多人查询同一个宝贝,导致无法自动绑定.则将推送该信息给查询过该宝贝的客户 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string LotUserQueryBindTip { get; set; } + + #endregion + + /// + /// 商品ID限制提示 + /// + [Category("4)、限制通知"), DisplayName("01.商品ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ItemIDRestrictTip { get; set; } + + /// + /// 拉黑提示 + /// + [Category("4)、限制通知"), DisplayName("02.用户被拉黑"), DefaultValue(@"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string Blocked_RestrictTip { get; set; } + + /// + /// 订单付款通知群负责人 + /// + [Category("4)、橱窗商品"), DisplayName("1.橱窗白名单"), DefaultValue(@""), + Description(@"填写商品的推广ID,多个用户逗号分隔,添加的推广ID将不会删除"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string PromotionWhiteList { get; set; } = string.Empty; + + #region 防撸设置 + + /// + /// 收货时间验证开关 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_Switch { get; set; } + + /// + /// 收货时间验证时长(小时) + /// + [Browsable(false)] + public int ReceivingTimeCheck_Hour { get; set; } + + /// + /// 收货时间验证处理方式 + /// + [Browsable(false)] + public OperateType ReceivingTimeCheck_OperateType { get; set; } + + /// + /// 收货时间验证置顶 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_UserTop { get; set; } + + /// + /// 收货时间验证订单冻结时间 + /// + [Browsable(false)] + public int ReceivingTimeCheck_FreezeTime { get; set; } + + /// + /// 屏蔽的商品ID集合 + /// + [Browsable(false)] + public List ItemIDRestrictList { get; set; } + + [Browsable(false)] + public string notice_robotname { get; set; } + + #endregion + + public Config() + { + this.ReceivingTimeCheck_Switch = false; + this.ReceivingTimeCheck_Hour = 24; + this.ReceivingTimeCheck_OperateType = OperateType.订单冻结; + this.ReceivingTimeCheck_FreezeTime = 24; + this.ReceivingTimeCheck_UserTop = false; + this.notice_robotname = string.Empty; + + this.ItemIDRestrictList = new List(); + + this.ItemIDRestrictTip = @"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"; + + this.Point = 20; + this.OrderNum = 20; + this.UserOrderChangeSwitch = SwitchType.开启; + this.PrincipalReceivedCommissionSwitch = SwitchType.关闭; + this.AgentReceivedCommissionSwitch = SwitchType.关闭; + this.QQSearchSuccessWithoutCouponTip = string.Empty; + this.QQSearchSuccessWithCouponTip = string.Empty; + this.SearchingTip = @"优惠信息查询中....."; + this.SearchSuccessWithCouponTip = @"1:/一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +购买口令: +[购买口令] +━┉┉┉┉∞┉┉┉┉━ +复制内容到抖音聊天窗口并发送,点击链接购买! +下单10分钟后会收到【绑定成功】提示,没有请复制订单编号给我[分段]购买地址: +[购买地址]"; + this.SearchSuccessWithCouponTip_kl = @"3:/一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +购买口令: +[购买口令] +━┉┉┉┉∞┉┉┉┉━ +复制内容到抖音跳转至购买窗口! +下单10分钟后会收到【绑定成功】提示,没有请复制订单编号给我"; + this.SearchSuccessWithoutCouponTip = @"1:/一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +购买口令: +[购买口令] +━┉┉┉┉∞┉┉┉┉━ +复制内容到抖音聊天窗口并发送,点击链接购买! +下单10分钟后会收到【绑定成功】提示,没有请复制订单编号给我[分段]购买地址: +[购买地址]"; + this.SearchSuccessWithoutCouponTip_kl = @"3:/一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +购买口令: +[购买口令] +━┉┉┉┉∞┉┉┉┉━ +复制内容到抖音跳转至购买窗口! +下单10分钟后会收到【绑定成功】提示,没有请复制订单编号给我"; + this.SearchNoCommissionTip = @"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"; + this.OrderRepetBindTip = @"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentTip = @"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentInform_OneLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_TwoLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_ThreeLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_LeaderTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderFailureTip = @"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderCountermandInform_OneLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_TwoLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_ThreeLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_LeaderTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderRefundTip = @"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderFreezeTip = @"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"; + this.OrderAlreadySettlementTip = @"一一一一订 单 已 经 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【订单状态】该订单已经完成结算,请勿重复提交 +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlementTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OccupyOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"; + this.NotFoundOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"; + // this.OrderFrozen_AllTip = @"一一一一订 单 结 算一一一一 + //[商品标题] + //【订单编号】[订单号] + //【付款金额】[付款金额] 元 + //【维权金额】[维权金额] 元 + //【返利积分】[返利积分] [积分名称] + //一一一一一一一一一一一一一 + //由于订单维权,全额退款,佣金为0 + //发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_OneLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_TwoLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_ThreeLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_LeaderTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_OneLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_TwoLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_ThreeLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_LeaderTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.LotUserQueryBindTip = @"一一一一绑 定 提 示一一一一 +【商品标题】[商品标题] +该商品被多人查询系统无法匹配是谁下单,请亲手动到抖音复制订单号给我手动绑定该订单"; + + this.Blocked_RestrictTip = @"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"; + + } + + } +} diff --git a/应用/DYRebate/DYRebate.csproj b/应用/DYRebate/DYRebate.csproj new file mode 100644 index 0000000..f88600e --- /dev/null +++ b/应用/DYRebate/DYRebate.csproj @@ -0,0 +1,128 @@ + + + + + Debug + AnyCPU + {6D011140-0E5F-4627-A010-529EFF6C9EFE} + Library + Properties + DYRebate + DYRebate + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + + Form + + + MainForm.cs + + + + + True + True + Resources.resx + + + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/DYRebate/Entitys/dyinfo_temp.cs b/应用/DYRebate/Entitys/dyinfo_temp.cs new file mode 100644 index 0000000..7f16c3a --- /dev/null +++ b/应用/DYRebate/Entitys/dyinfo_temp.cs @@ -0,0 +1,94 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DYRebate.Entitys +{ + /// + /// 临时的表 (用于数据显示) + /// + public class dyinfo_temp + { + public long ID { get; set; } + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string name { get; set; } + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 主推广位cps名称 + /// + private string _pid_chief_cps_name { get; set; } + public string pid_chief_cps_name + { + get { return _pid_chief_cps_name; } + set { _pid_chief_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_chief; + /// + /// 主推广位id + /// + public string pid_chief + { + get { return _pid_chief; } + set { _pid_chief = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 主推广位昵称 + /// + private string _pid_chief_name; + + public string pid_chief_name + { + get { return _pid_chief_name; } + set { _pid_chief_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位cps名称 + /// + private string _pid_deputy_cps_name { get; set; } + public string pid_deputy_cps_name + { + get { return _pid_deputy_cps_name; } + set { _pid_deputy_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_deputy; + + /// + /// 副推广位id + /// + public string pid_deputy + { + get { return _pid_deputy; } + set { _pid_deputy = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 副推广位名称 + /// + private string _pid_deputy_name; + + public string pid_deputy_name + { + get { return _pid_deputy_name; } + set { _pid_deputy_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } +} diff --git a/应用/DYRebate/Entitys/fl_plugin_dy_pidhist.cs b/应用/DYRebate/Entitys/fl_plugin_dy_pidhist.cs new file mode 100644 index 0000000..ff821ff --- /dev/null +++ b/应用/DYRebate/Entitys/fl_plugin_dy_pidhist.cs @@ -0,0 +1,28 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DYRebate.Entitys +{ + public class fl_plugin_dy_pidhist : base_model + { + /// + /// 抖音账号 + /// + public string cpsname { get; set; } + + /// + /// 推广id + /// + public string pid { get; set; } + + /// + /// 失效时间 + /// + public DateTime expirestime { get; set; } + + } +} diff --git a/应用/DYRebate/Entitys/fl_plugin_dyrebate_dytgw.cs b/应用/DYRebate/Entitys/fl_plugin_dyrebate_dytgw.cs new file mode 100644 index 0000000..938182c --- /dev/null +++ b/应用/DYRebate/Entitys/fl_plugin_dyrebate_dytgw.cs @@ -0,0 +1,46 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DYRebate.Entitys +{ + class fl_plugin_dyrebate_dytgw : base_model + { + /// + /// 左连接主表 fl_robot_info 的主键 + /// + public int robot_id { get; set; } + /// + /// 主推广位CPS名称 + /// + public string pid_chief_cps_name { get; set; } + /// + /// 主推广位id + /// + public string pid_chief { get; set; } + /// + /// 主推广位昵称 + /// + public string pid_chief_name { get; set; } + /// + /// 副推广位CPS名称 + /// + public string pid_deputy_cps_name { get; set; } + /// + /// 副推广位id + /// + public string pid_deputy { get; set; } + /// + /// 副推广位名称 + /// + public string pid_deputy_name { get; set; } + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } + +} diff --git a/应用/DYRebate/Entitys/queryhist_temp.cs b/应用/DYRebate/Entitys/queryhist_temp.cs new file mode 100644 index 0000000..d0adfcc --- /dev/null +++ b/应用/DYRebate/Entitys/queryhist_temp.cs @@ -0,0 +1,16 @@ +using Api.Framework.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DYRebate.Entitys +{ + public class queryhist_temp + { + public string robot_name { get; set; } + public CpsType type { get; set; } + public int userid { get; set; } + } +} diff --git a/应用/DYRebate/MainForm.Designer.cs b/应用/DYRebate/MainForm.Designer.cs new file mode 100644 index 0000000..af7e368 --- /dev/null +++ b/应用/DYRebate/MainForm.Designer.cs @@ -0,0 +1,530 @@ +namespace DYRebate +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl19 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox4 = new System.Windows.Forms.ComboBox(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.comboBox3 = new System.Windows.Forms.ComboBox(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl31 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.xtraTabPage3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(906, 535); + this.xtraTabControl1.TabIndex = 7; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(904, 509); + this.xtraTabPage1.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(175, 177); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 8; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl1 + // + this.pageControl1.Location = new System.Drawing.Point(0, 470); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(900, 36); + this.pageControl1.TabIndex = 5; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(904, 470); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 50; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "平台类型"; + this.gridColumn1.FieldName = "chattype"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 99; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 148; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 125; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "主推广账号"; + this.gridColumn5.FieldName = "pid_chief_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 149; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "副推广账号"; + this.gridColumn7.FieldName = "pid_deputy_name"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 158; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "禁止使用"; + this.gridColumn9.FieldName = "onoff"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 6; + this.gridColumn9.Width = 66; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(904, 509); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(904, 509); + this.settingControl1.TabIndex = 0; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupBox1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(904, 509); + this.xtraTabPage3.Text = " 防 撸 设 置 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.labelControl19); + this.groupBox1.Controls.Add(this.comboBox4); + this.groupBox1.Controls.Add(this.labelControl20); + this.groupBox1.Controls.Add(this.checkBox3); + this.groupBox1.Controls.Add(this.buttonCheck2); + this.groupBox1.Controls.Add(this.memoEdit5); + this.groupBox1.Controls.Add(this.numericUpDown2); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.comboBox3); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl31); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Location = new System.Drawing.Point(11, 5); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(882, 498); + this.groupBox1.TabIndex = 4; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础设置 "; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(624, 108); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(215, 14); + this.labelControl5.TabIndex = 60; + this.labelControl5.Text = "(在【系统管理->群通知机器人】中添加)"; + // + // labelControl19 + // + this.labelControl19.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl19.Appearance.Options.UseForeColor = true; + this.labelControl19.Location = new System.Drawing.Point(478, 108); + this.labelControl19.Name = "labelControl19"; + this.labelControl19.Size = new System.Drawing.Size(130, 14); + this.labelControl19.TabIndex = 59; + this.labelControl19.Text = "(未选择时使用系统设置)"; + // + // comboBox4 + // + this.comboBox4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox4.FormattingEnabled = true; + this.comboBox4.Location = new System.Drawing.Point(143, 105); + this.comboBox4.Name = "comboBox4"; + this.comboBox4.Size = new System.Drawing.Size(308, 22); + this.comboBox4.TabIndex = 58; + // + // labelControl20 + // + this.labelControl20.Location = new System.Drawing.Point(46, 108); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(91, 14); + this.labelControl20.TabIndex = 57; + this.labelControl20.Text = "群通知API接口:"; + // + // checkBox3 + // + this.checkBox3.AutoSize = true; + this.checkBox3.Location = new System.Drawing.Point(651, 47); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.Size = new System.Drawing.Size(108, 18); + this.checkBox3.TabIndex = 31; + this.checkBox3.Text = "置顶用户(微信)"; + this.checkBox3.UseVisualStyleBackColor = true; + this.checkBox3.Visible = false; + // + // buttonCheck2 + // + this.buttonCheck2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = true; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(55, 46); + this.buttonCheck2.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(57, 22); + this.buttonCheck2.TabIndex = 28; + // + // memoEdit5 + // + this.memoEdit5.Location = new System.Drawing.Point(21, 192); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Size = new System.Drawing.Size(840, 284); + this.memoEdit5.TabIndex = 27; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(708, 45); + this.numericUpDown2.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(75, 22); + this.numericUpDown2.TabIndex = 22; + this.numericUpDown2.Value = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.numericUpDown2.Visible = false; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(264, 46); + this.numericUpDown1.Maximum = new decimal(new int[] { + 999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(91, 22); + this.numericUpDown1.TabIndex = 22; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // comboBox3 + // + this.comboBox3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox3.FormattingEnabled = true; + this.comboBox3.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群", + "订单冻结"}); + this.comboBox3.Location = new System.Drawing.Point(507, 45); + this.comboBox3.Name = "comboBox3"; + this.comboBox3.Size = new System.Drawing.Size(121, 22); + this.comboBox3.TabIndex = 25; + this.comboBox3.SelectedIndexChanged += new System.EventHandler(this.comboBox3_SelectedIndexChanged); + // + // labelControl1 + // + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(99, 172); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(132, 14); + this.labelControl1.TabIndex = 18; + this.labelControl1.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl31 + // + this.labelControl31.Location = new System.Drawing.Point(21, 172); + this.labelControl31.Name = "labelControl31"; + this.labelControl31.Size = new System.Drawing.Size(72, 14); + this.labelControl31.TabIndex = 18; + this.labelControl31.Text = "屏蔽商品ID:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(653, 49); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(48, 14); + this.labelControl8.TabIndex = 19; + this.labelControl8.Text = "订单冻结"; + this.labelControl8.Visible = false; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(789, 49); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(28, 14); + this.labelControl7.TabIndex = 19; + this.labelControl7.Text = "小时."; + this.labelControl7.Visible = false; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(373, 50); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(64, 14); + this.labelControl4.TabIndex = 19; + this.labelControl4.Text = "小时内收货."; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(170, 50); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 19; + this.labelControl3.Text = "用户购买的商品"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(906, 535); + this.Controls.Add(this.xtraTabControl1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing_1); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl19; + private System.Windows.Forms.ComboBox comboBox4; + private DevExpress.XtraEditors.LabelControl labelControl20; + private System.Windows.Forms.CheckBox checkBox3; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.ComboBox comboBox3; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl31; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + } +} \ No newline at end of file diff --git a/应用/DYRebate/MainForm.cs b/应用/DYRebate/MainForm.cs new file mode 100644 index 0000000..ce59663 --- /dev/null +++ b/应用/DYRebate/MainForm.cs @@ -0,0 +1,298 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using DYRebate.Entitys; +using DYRebate.Properties; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace DYRebate +{ + public partial class MainForm : BaseForm + { + SqlSugarClient session = null; + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + session = ApiClient.GetSession(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + var apis = ApiClient.GetSession().FindNoticeapiRobots().ToArray(); + var rst = new List(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + comboBox4.DataSource = rst; + + this.settingControl1.Bind(Class1.Config, 110); + + this.buttonCheck2.Checked = Class1.Config.ReceivingTimeCheck_Switch; + this.numericUpDown1.Value = Class1.Config.ReceivingTimeCheck_Hour; + this.comboBox3.SelectedIndex = Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单 ? 0 : Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群 ? 1 : 2; + this.numericUpDown2.Value = Class1.Config.ReceivingTimeCheck_FreezeTime; + + this.comboBox4.SelectedIndex = rst.IndexOf(Class1.Config.notice_robotname) == -1 ? 0 : rst.IndexOf(Class1.Config.notice_robotname); + + this.memoEdit5.Text = string.Join(",", Class1.Config.ItemIDRestrictList); + + #region 加载所有的账号 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.抖音联盟}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.抖音联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label1.Visible = gridView1.RowCount == 0; + + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 行单元格单击事件 + /// + /// + /// + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.抖音联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.抖音联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzone == null) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzone.extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + #region 有出现两个重复无法修复的情况,删除一个 + var repetAdzone = adzones.Where(f => f.extend == pidName).ToList(); + if (repetAdzone.Count > 1) + { + for (int i = 1; i <= repetAdzone.Count - 1; i++) + { + session.Deleteable(repetAdzone[i]).ExecuteCommand(); + } + adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.抖音联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + } + #endregion + + adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindDyInfoTempGroups(true); + session.FindAdzoneInfos(true); + session.FindDouyinAutoBindPid(true);//刷新推广位 + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.抖音联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzones.Count == 0) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item, false); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzones[0].extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate, adzones[0].onoff); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + if (adzones != null)//数据库中存在 + session.ExcuteSQL("update fl_adzone_info set onoff = @onoff where robot_id = @robot_id and alliance_id = @alliance_id and custom_type = @custom_type", new { onoff = !adzones[0].onoff, robot_id = id, alliance_id = (int)CpsType.抖音联盟, custom_type = Resources.SoftwareType }); + session.FindDyInfoTempGroups(true); + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + session.FindDouyinAutoBindPid(true);//刷新推广位 + } + } + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 修改显示内容的事件 + /// + /// + /// + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + /// + /// 创建fl_adzone_info对象 + /// + /// + /// + /// + /// + /// + /// + private fl_adzone_info CreateAdzoneInfo(string adzone_name, string adzone_pid, string adzone_pid_cps_name, string rid, string item, bool onoff = false) + { + return new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = adzone_name, //推广位名称 + adzone_pid = adzone_pid, //推广位pid + adzone_pid_cps_name = adzone_pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.抖音联盟, //联盟id + robot_id = int.Parse(rid), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = onoff, //不禁用 + extend = item + }; + } + + private void MainForm_FormClosing_1(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.ReceivingTimeCheck_Switch = buttonCheck2.Checked; + Class1.Config.ReceivingTimeCheck_Hour = (int)numericUpDown1.Value; + Class1.Config.ReceivingTimeCheck_OperateType = comboBox3.SelectedIndex == 0 ? OperateType.拉入黑名单 : comboBox3.SelectedIndex == 1 ? OperateType.通知钉钉群 : OperateType.订单冻结; + Class1.Config.ReceivingTimeCheck_FreezeTime = (int)numericUpDown2.Value; + Class1.Config.ReceivingTimeCheck_UserTop = checkBox3.Checked; + + Class1.Config.notice_robotname = comboBox4.SelectedValue.ToString(); + + Class1.Config.ItemIDRestrictList = memoEdit5.Text.Trim().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + Util.Save(Class1.Config); + OrderHelper.RefreshDyConfig(true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void comboBox3_SelectedIndexChanged(object sender, EventArgs e) + { + labelControl7.Visible = labelControl8.Visible = numericUpDown2.Visible = comboBox3.SelectedIndex == 2; + checkBox3.Visible = comboBox3.SelectedIndex == 0; + } + } +} \ No newline at end of file diff --git a/应用/DYRebate/MainForm.resx b/应用/DYRebate/MainForm.resx new file mode 100644 index 0000000..4cad733 --- /dev/null +++ b/应用/DYRebate/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 65 + + \ No newline at end of file diff --git a/应用/DYRebate/MessageOperation.cs b/应用/DYRebate/MessageOperation.cs new file mode 100644 index 0000000..9d2c5c6 --- /dev/null +++ b/应用/DYRebate/MessageOperation.cs @@ -0,0 +1,667 @@ +using Api.Framework; +using Api.Framework.EntityTmp.Douyin; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using CsharpHttpHelper; +using DYRebate.Entitys; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework.Utils; +using static DYRebate.Class1; + +namespace DYRebate +{ + public class MessageOperation + { + private static List AddMessUsernameList = new List() { "wxid_mjzeh4qj9hio22", "wxid_lrf1mr7ond6622", "wujiahua0876", "wxid_2ufntuf4purl22", "wxid_bua0te17il7i22" }; + + ReciveIMEvent e = null; + Class1 plugin = null; + object sender = null; + + public MessageOperation(object sender, ReciveIMEvent e, Class1 plugin) + { + this.e = e; + this.plugin = plugin; + this.sender = sender; + } + + #region 订单绑定 + public bool BindOrderId() + { + try + { + #region 抖音订单绑定 + var orderid = e.Message.Trim(); + + #region 消息为订单类型 + if (Regex.IsMatch(orderid, @"^\d{19}$")) + { + var oid = long.Parse(orderid); + if (oid < 4000000000000000000) + { + return false; + } + var db = ApiClient.GetSession(); + + var dy_orders_temp = db.Find("select * from fl_order_douyin where order_id = @order_id", new { order_id = orderid }); + + var memberTmp = e.GetMemberinfo(); + + if (dy_orders_temp != null && dy_orders_temp.Count != 0) + { + var member = dy_orders_temp.FirstOrDefault(f => f.db_userid != 0 && f.db_userid != memberTmp.id); + if (member != null) + { + //订单已经被他人绑定 + e.SendMessage(Class1.Config.OccupyOrderErrorTip.Replace("[订单号]", orderid)); + return true; + } + var notices = new List(); + + var downDyTimer = new DownDouyinTimer(); + + #region 订单用户已经绑定 纯提示,非结算的订单也提示上级 + var bindOrders = dy_orders_temp.Where(f => f.db_userid != 0).ToList(); + if (bindOrders != null && bindOrders.Count != 0) + { + foreach (var order in bindOrders) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + memberTmp = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Class1.Config.OrderRepetBindTip, order, memberTmp, point)); + else + e.SendMessage(Class1._GetOrderStateMess(order.db_status, (order.db_status == SystemOrderStatus.订单结算 ? SettleType.已结算提示 : SettleType.未结算提示), order, memberTmp, point)); + Thread.Sleep(500); + } + //return; + } + #endregion + + #region 订单没有被绑定(两种情况 => 一个订单已经被结算 一个是订单未结算) + var notBindOrders = dy_orders_temp.Where(f => f.db_userid == 0).ToList(); + if (notBindOrders != null && notBindOrders.Count != 0) + { + if (HttpExtend.GetDateTime(notBindOrders[0].pay_time.ToString()) < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderid},已经过了有效绑定时间!"); + return true; + } + + foreach (var order in notBindOrders) + { + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + + //没有绑定用户的订单进行绑定 + order.db_userid = memberTmp.id; + order.db_robotname = e.RobotName; + order.db_robottype = e.RobotInfo.type; + order.msg_groupid = e.Groupid; + + #region 手动绑定,重新计算用户的返利积分 + + //查询历史查询比例 + var compute = db.FindQueryRatioHist(CpsType.抖音联盟, order.id); + if (compute == null) + { + var query_item = db.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid order by id desc", new { userid = e.GetMemberinfo().id, itemid = order.product_id, adzoneid = order.db_cpsname }); + + //计算公式不为空 + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + try + { + compute = JsonConvert.DeserializeObject(query_item.compute_configdic); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = order.id, + createtime = DateTime.Now, + cpstype = CpsType.抖音联盟 + }; + db.SaveOrUpdate(queryRatioHist); + } + catch (Exception ex) + { + EventClient.OnEvent("抖音计算", $"获取历史查询比异常:{ex.Message}"); + } + } + } + ItemPoint itempoint = null; + + //计算的佣金 + if (compute != null) + itempoint = db.FindItemPoint(CpsType.抖音联盟, compute, Util.ConvertDouble_FenToYuan(order.estimated_comission), 1); + else + itempoint = db.FindItemPoint(memberTmp, Util.ConvertDouble_FenToYuan(order.estimated_comission), 1, CpsType.抖音联盟); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + } + #endregion + + #region 用户的完成订单数量加1 + if (memberTmp != null) + { + memberTmp.bind_order++; + memberTmp = db.UpdateMemberGroup(memberTmp); + } + #endregion + + #region 首次付款时间 + var record = db.FindStatisticsRecord(memberTmp.id); + if (record == null) + { + record = new fl_statistics_record() { uid = memberTmp.id, ex2 = 0, ex4 = HttpExtend.GetTimeStamp(DateTime.Now) }; + db.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = HttpExtend.GetTimeStamp(DateTime.Now); + db.Saveable(record).ExecuteCommand(); + } + } + #endregion + + db.SaveOrUpdate(order); + downDyTimer.UpdateOrder(order, notices, db, isFrontData: true); + } + } + #endregion + + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.IsRewards) + tasks.Add(item); + //else + //plugin.SDK_OrderNoticeEvent(this, item); + } + } + #endregion + } + else + { + #region 未找到订单,提示用户并且加入绑定缓存中 + e.SendMessage(Class1.Config.NotFoundOrderErrorTip.Replace("[订单号]", orderid)); + + var bind = db.FindBindCache(orderid); + if (bind == null) + { + db.Insertable(new fl_bind_cache() { crt_time = DateTime.Now, db_robotid = e.RobotInfo.id, orderid = orderid, groupid = e.Groupid, db_userid = memberTmp.id }).ExecuteCommand(); + db.FindBindCache(orderid, true); + } + #endregion + } + //消息已经处理完成,将不往后面的插件传递 + e.Cancel = true; + return true; + } + + #endregion + + //判断消息是否是其他cps平台的订单号 + if (OrderHelper.IsOrderId(e.Message.Trim())) + return true; + #endregion + } + catch (Exception ex) + { + plugin.OnLog($"手动绑定订单号异常:{ex.Message}_{ex.StackTrace}"); + } + return false; + } + #endregion + + public bool AnalyseFanLi() + { + //计算公式 + Compute compute = null; + + var memberTmp = e.GetMemberinfo(); + try + { + var db = ApiClient.GetSession(); + + var dyinfoTemps = db.FindDyInfoTempGroups(); + var dyInfoTemp = dyinfoTemps.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (dyInfoTemp == null) return false; + + var message = e.Message.Trim(); + + //推广位 + var pid = string.Empty; + + fl_cps_member dy_cps = null; + var isDefault = true; + + if (!string.IsNullOrWhiteSpace(e.Groupid))//群pid + { + var groupAdzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.抖音联盟 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + pid = groupAdzone.adzone_pid; + dy_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.抖音联盟 && f.username == groupAdzone.adzone_pid_cps_name); + isDefault = false; + } + } + + if (isDefault)//私人pid + { + var memberAdzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.抖音联盟 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == memberTmp.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + pid = memberAdzone.adzone_pid; + dy_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.抖音联盟 && f.username == memberAdzone.adzone_pid_cps_name); + isDefault = false; + } + } + + if (isDefault)//默认推广位 + { + dy_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.抖音联盟 && f.username == ((memberTmp.buy_point >= Class1.Config.Point && memberTmp.finish_order >= Class1.Config.OrderNum) ? dyInfoTemp.pid_chief_cps_name : dyInfoTemp.pid_deputy_cps_name));//通过判断用户的购物积分,来判断用户使用哪个推广位 + pid = ((memberTmp.buy_point >= Class1.Config.Point && memberTmp.finish_order >= Class1.Config.OrderNum) ? dyInfoTemp.pid_chief : dyInfoTemp.pid_deputy); + } + + if (dy_cps == null) throw new Exception("抖音推广位设置异常,请检测后重试!"); + + var api = CpsClient.CreateDouyinRequest(dy_cps); + + if (api == null) throw new Exception("@创建抖音API请求失败"); + + var title = string.Empty;//商品标题 + + //判断消息中是否包含抖音链接信息 + var promotion_id = string.Empty;//促销id + + //api.ConvertInstPickSource(e.Message); + //api.GetShareMaterial(); + + //var itemid = e.Message.Trim(); + var itemid = api.GetDyGoodsID(message, out promotion_id); + + #region 标题搜索和商品id搜索 + if (string.IsNullOrEmpty(itemid)) + return false; + + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + e.SendMessage(Class1.Config.SearchingTip); + + try + { + //屏蔽商品 + if (Class1.Config.ItemIDRestrictList.Contains(itemid)) + { + e.SendMessage(Class1.Config.ItemIDRestrictTip.Replace("[商品ID]", itemid)); + return true; + } + + var items = api.FindItemInfo(itemid); + + if (items == null || items.products == null || items.products.Count == 0) + throw new Exception("商品不存在"); + + var goods = items.products[0]; + + var shopUrl = string.Empty; + + ShareInfo extInfo = null; + var isApiSharable = false; + if (Class1.Config.AllRebateModelSwitch == SwitchType.开启) + { + if (goods.sharable != "false") + { + try + { + extInfo = api.ConvertUrl(goods.detail_url, pid, $"{e.GetMemberinfo().username}"); + isApiSharable = true; + } + catch (Exception) + { } + } + } + + var rateTmp = 0m; + + //if (goods.sharable == "false")//throw new Exception("商品未推广"); + if (!isApiSharable)//throw new Exception("商品未推广"); + { + var key = $"{itemid}"; + var value = Comm.GetCache(key); + if (!string.IsNullOrWhiteSpace(value)) + shopUrl = value; + else + { + if (string.IsNullOrWhiteSpace(promotion_id)) + throw new Exception("商品未推广"); + isApiSharable = false; + + if (!api.BindGoods(itemid, promotion_id)) + { + throw new Exception("添加商品异常"); + } + shopUrl = api.GetShopWindow_PromotionUrlToGoodsId(itemid); + if (string.IsNullOrWhiteSpace(shopUrl)) + throw new Exception("未获取推广链接"); + + var info = api.FindGoodsInfo(promotion_id); + if (info != null) + rateTmp = (decimal)info.data.cos_ratio / 10000m; + + Comm.SetCache(key, shopUrl, 15 * 60); + } + + } + + //店铺名称 + var nick = goods.shop_name; + //商品主图 + var pict_url = !string.IsNullOrWhiteSpace(goods.cover) ? goods.cover : (goods.imgs != null && goods.imgs.Count != 0) ? goods.imgs[0] : string.Empty; + //商品标题//< >&"© <,>,&,",©; + title = goods.title.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©");//这里有个看不见的字符,要将其替换掉 + + //原价 + var price = decimal.Parse((goods.price / 100m).ToString()); + + //减去技术费的总佣金(不用券) + var calcPrice = Math.Round((price * 0.9m), 2, MidpointRounding.AwayFromZero); + + //30天销量 + var volume = goods.sales; + + //佣金率 + var commission_rate = (decimal)goods.cos_ratio / 100m; + + if (rateTmp != 0 && commission_rate != rateTmp) + commission_rate = rateTmp; + + //优惠券金额 + var coupon_price = 0.00m; + + #region xxx + //if (goods.sale_infos != null && goods.sale_infos.Count != 0) + //{ + // var coupon_tmp = 0m; + // for (int i = 0; i < goods.sale_infos.Count; i++) + // { + // if (goods.sale_infos[i].title.Contains("减")) + // { + // var splitStrs = goods.sale_infos[i].title.Split(new string[] { "减" }, StringSplitOptions.RemoveEmptyEntries); + // if (splitStrs != null && splitStrs.Length == 2) + // { + // var now = decimal.Parse(splitStrs[0]); + // if (price >= now) + // { + // if (now > coupon_tmp) + // { + // coupon_tmp = now; + // coupon_price = decimal.Parse(splitStrs[1]); + // } + // } + // } + // } + // } + //} + #endregion + + //券后价 + var endPrice = (decimal)((goods.coupon_price ?? 0) / 100d); + + if (endPrice != 0) + { + if (endPrice < price) + coupon_price = price - endPrice; + } + + //券后佣金 + var useCalcPrice = endPrice * 0.9m; + + //用券后 佣金 + var useCoupon_totalCommFee = (double)Math.Round(useCalcPrice * commission_rate, 2); + //用券后 给用户的佣金 + var useCoupon_commFee = db.FindItemPoint(memberTmp, useCoupon_totalCommFee, 1, CpsType.抖音联盟, out compute); + + Compute compute1 = null; + //不用券 佣金 + var unuseCoupon_totalCommFee = Math.Round(calcPrice * commission_rate, 2); + //不用券 给用户的佣金 + var unuseCoupon_commFee = db.FindItemPoint(memberTmp, (double)unuseCoupon_totalCommFee, 1, CpsType.抖音联盟, out compute1); + + if (compute == null) + compute = compute1; + + LogHelper.GetSingleObj().Info("", $"抖音佣金计算:券后价{useCoupon_totalCommFee},佣金:{useCalcPrice} ||| 无券价:{unuseCoupon_totalCommFee},佣金:{unuseCoupon_totalCommFee} @@ 佣金率:{commission_rate} => {itemid}"); + + // 获取短链接 + //var shopShortLink = ApiClient.ShortURL(shopUrl, Class1.Config.Dwz_Type).Result; + + //抖音缩短链接 + var shopShortLink = string.Empty; + + //抖音口令 + var password = string.Empty; + + if (isApiSharable) + { + if (extInfo == null) + extInfo = api.ConvertUrl(goods.detail_url, pid, $"{e.GetMemberinfo().username}"); + if (extInfo == null) + throw new Exception("转链异常"); + + password = extInfo.dy_password; + var reg = Regex.Match(extInfo.dy_password, "(?<口令>[︽#]{2}[0-9a-zA-Z]{9,}[︽#]{2})", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + password = reg.Groups["口令"].ToString(); + } + else + { + password = DYHelper.CreateKouling(shopUrl); + if (!string.IsNullOrWhiteSpace(password)) + { + shopShortLink = DYHelper.ShortDyUrl(shopUrl); + + shopUrl = string.Empty; + } + else + { + shopShortLink = DYHelper.ShortDyUrl(shopUrl); + } + //api.DelGoodsWindowUrl(promotion_id); + var pidhist = db.Queryable().First(g => g.cpsname == api.Member.username && g.pid == promotion_id); + if (pidhist == null) + pidhist = new fl_plugin_dy_pidhist() { pid = promotion_id, cpsname = api.Member.username }; + pidhist.expirestime = DateTime.Now.AddHours(1); + db.Saveable(pidhist).ExecuteCommand(); + } + + #region 正常订单 + //有券的情况 + if (coupon_price != 0) + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Class1.Config.QQSearchSuccessWithCouponTip))) + { + if (!string.IsNullOrWhiteSpace(shopShortLink)) + mess = Class1.Config.SearchSuccessWithCouponTip; + else + mess = Class1.Config.SearchSuccessWithCouponTip_kl; + } + else + { + if (!string.IsNullOrWhiteSpace(shopShortLink)) + mess = Class1.Config.QQSearchSuccessWithCouponTip; + else + mess = Class1.Config.QQSearchSuccessWithCouponTip_kl; + } + + if (AddMessUsernameList.Contains(e.GetMemberinfo().username)) + mess += "[分段][延迟=1]" + shopUrl; + + e.SendMessage(mess + .Replace("劵", "券") + .Replace("[商品标题]", mess.Contains("", "") : title) + .Replace("[商品原价]", string.Format("{0:F}", price)) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[月销量]", volume.ToString()) + .Replace("[店铺名称]", nick) + .Replace("[券后返利]", string.Format("{0:F}", useCoupon_commFee.UserPoint)) + .Replace("[弃券返利]", string.Format("{0:F}", unuseCoupon_commFee.UserPoint)) + .Replace("[券后价]", string.Format("{0:F}", endPrice)) + .Replace("[优惠券金额]", coupon_price.ToString()) + .Replace("[购买地址]", shopShortLink) + .Replace("[购买口令]", password.Replace("#", "︽")) + .Replace("[共节省]", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, string.Format("{0:F}", price), coupon_price.ToString(), endPrice.ToString(), pict_url, shopShortLink, ApiClient.QrImageType.模板B, CpsType.抖音联盟) + "]" : string.Empty) + ); + } + else//没有券的情况 + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Class1.Config.QQSearchSuccessWithoutCouponTip))) + { + if (!string.IsNullOrWhiteSpace(shopShortLink)) + mess = Class1.Config.SearchSuccessWithoutCouponTip; + else + mess = Class1.Config.SearchSuccessWithoutCouponTip_kl; + } + else + { + if (!string.IsNullOrWhiteSpace(shopShortLink)) + mess = Class1.Config.QQSearchSuccessWithoutCouponTip; + else + mess = Class1.Config.QQSearchSuccessWithoutCouponTip_kl; + } + + if (AddMessUsernameList.Contains(e.GetMemberinfo().username)) + mess += "[分段][延迟=1]" + shopUrl; + + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("", "") : title) + .Replace("[商品原价]", string.Format("{0:F}", price)) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[月销量]", volume.ToString()) + .Replace("[店铺名称]", nick) + .Replace("[返利积分]", string.Format("{0:F}", unuseCoupon_commFee.UserPoint)) + .Replace("[购买地址]", shopShortLink) + .Replace("[购买口令]", password.Replace("#", "︽")) + .Replace("[共节省]", string.Format("{0:F}", useCoupon_commFee.UserPoint)) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, price.ToString(), "0", price.ToString(), pict_url, shopShortLink, ApiClient.QrImageType.模板B, CpsType.抖音联盟) + "]" : string.Empty) + ); + } + #endregion + + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + db.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.抖音联盟, + itemid = itemid, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = memberTmp.id, + title = title, + adzoneid = dy_cps.username, + mallid = goods.shop_id.ToString(), + compute_configdic = compute == null ? string.Empty : JsonConvert.SerializeObject(compute) + }).ExecuteCommand(); + db.UpdateRecord(memberTmp.id); + + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.抖音联盟; + shared["msg_username"] = memberTmp.username; + shared["price"] = string.Format("{0:F}", price); + shared["title"] = title; + shared["coupon_price"] = string.Format("{0:F}", coupon_price); + shared["user_point"] = coupon_price != 0 ? string.Format("{0:F}", useCoupon_commFee.UserPoint) : string.Format("{0:F}", unuseCoupon_commFee.UserPoint); + shared["economize"] = coupon_price != 0 ? string.Format("{0:F}", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint)) : string.Format("{0:F}", useCoupon_commFee.UserPoint); + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + #endregion + return true; + } + catch (Exception ex) + { + //{"code":90000,"err_no":7,"log_id":"202202271755520101330360171F8980A6","message":"商家已设置该商品仅指定作者可推广,请您更换其他商品","msg":"未知错误,此错误会逐步细化明确,请不要依赖sub_code或sub_msg做业务判断","sub_code":"isp.unknown-error","sub_msg":"1025:商家已设置该商品仅指定作者可推广,请您更换其他商品"} + if (ex.Message.Contains("商品不存在") || ex.Message.Contains("商品未推广") || ex.Message.Contains("未获取推广链接") || ex.Message.Contains("添加商品异常") | ex.Message.Contains("商家已设置该商品仅指定作者可推广")) + { + e.SendMessage(Class1.Config.SearchNoCommissionTip);//未搜索到提示语 + db.UpdateRecord(memberTmp.id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.抖音联盟; + shared["msg_username"] = memberTmp.username; + shared["price"] = "未知"; + shared["title"] = message; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + } + else if (ex.Message.Contains("转链异常") || ex.Message.Contains("当前商品暂不支持站外分享")) + { + e.SendMessage(Class1.Config.SearchNoCommissionTip);//未搜索到提示语 + throw ex; + } + else + throw ex; + } + #endregion + } + catch (Exception ex) + { + if (ex.Message.Contains("商品不存在") || ex.Message.Contains("商品未推广") || ex.Message.Contains("商家已设置该商品仅指定作者可推广")) + { + e.SendMessage(Class1.Config.SearchNoCommissionTip);//未搜索到提示语 + ApiClient.GetSession().UpdateRecord(memberTmp.id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.抖音联盟; + shared["msg_username"] = memberTmp.username; + shared["price"] = "未知"; + shared["title"] = "未知"; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + return true; + } + + if (ex.Message.StartsWith("@")) + plugin.OnLog($"W :({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message.Replace("@", "")}"); + else + plugin.OnLog($"W:({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message} - {ex.StackTrace}"); + plugin.OnLog(ApiClient.Setting.SystemConfig.msg_error); + } + return false; + } + + } +} diff --git a/应用/DYRebate/Properties/AssemblyInfo.cs b/应用/DYRebate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1fe452f --- /dev/null +++ b/应用/DYRebate/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("DYRebate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DYRebate")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("6d011140-0e5f-4627-a010-529eff6c9efe")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/DYRebate/Properties/Resources.Designer.cs b/应用/DYRebate/Properties/Resources.Designer.cs new file mode 100644 index 0000000..f130a03 --- /dev/null +++ b/应用/DYRebate/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace DYRebate.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DYRebate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 抖音返利 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 抖音返利 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 抖音返利插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 抖音返利 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 抖音 { + get { + object obj = ResourceManager.GetObject("抖音", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/DYRebate/Properties/Resources.resx b/应用/DYRebate/Properties/Resources.resx new file mode 100644 index 0000000..7bf038f --- /dev/null +++ b/应用/DYRebate/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 抖音返利 + + + 抖音返利 + + + 抖音返利插件 + + + 抖音返利 + + + + ..\Resources\抖音.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/DYRebate/Properties/licenses.licx b/应用/DYRebate/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/DYRebate/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/DYRebate/Resources/抖音.png b/应用/DYRebate/Resources/抖音.png new file mode 100644 index 0000000..7f6991f Binary files /dev/null and b/应用/DYRebate/Resources/抖音.png differ diff --git a/应用/DYRebate/SessionExt.cs b/应用/DYRebate/SessionExt.cs new file mode 100644 index 0000000..1dfed6f --- /dev/null +++ b/应用/DYRebate/SessionExt.cs @@ -0,0 +1,48 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using DYRebate.Entitys; +using DYRebate.Properties; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DYRebate +{ + public static class SessionExt + { + const string dyinfo_temp_list_dyrebate = "dyinfo_temp_list_dyrebate"; + + /// + /// 获取fl_adzone_info表的数据集合缓存 + /// + /// + /// 刷新 + /// + public static List FindDyInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + + var dyinfo_temp_groups = ApiClient.Cache.Get>(dyinfo_temp_list_dyrebate);//根据KEY、获得缓存 + if (refresh || dyinfo_temp_groups == null) + { + dyinfo_temp_groups = session.Find($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.抖音联盟}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.抖音联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id"); + ApiClient.Cache.Set(dyinfo_temp_list_dyrebate, dyinfo_temp_groups, 60); + } + return dyinfo_temp_groups; + } + + public static fl_member_info FindMemberinfo(this SqlSugarClient session, long userid) + { + return session.Find("select * from fl_member_info where id = @id", new { id = userid }).FirstOrDefault(); + } + + public static void Clear() + { + ApiClient.Cache.Remove(dyinfo_temp_list_dyrebate); + } + } +} diff --git a/应用/Delivery.Plugin/Class1.cs b/应用/Delivery.Plugin/Class1.cs new file mode 100644 index 0000000..87c8c50 --- /dev/null +++ b/应用/Delivery.Plugin/Class1.cs @@ -0,0 +1,1187 @@ +using Api.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.Tools; +using Delivery.Plugin.Model; +using Api.Framework.Model; +using System.Text.RegularExpressions; +using CsharpHttpHelper; +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Events; +using System.Threading; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using System.Collections; +using System.IO; +using System.Drawing; + +namespace Delivery.Plugin +{ + public class Class1 : Api.Framework.SDK.Plugin + { + public Class1() + { + this.Name = "配送插件"; + this.Logo = Properties.Resources.快递; + } + + // public static Config config; + public override void Start() + { + // config = Util.Read(); + var session = ApiClient.GetSession(); + //session.CodeFirst.BackupTable().InitTables(typeof(fl_plugin_delivery_group),typeof(fl_plugin_delivery_item)); + bool is_first = false; + if (!session.TableExist()) + { + is_first = true; + session.CreateTable(); + session.AddIndex("group_id"); + } + + if (!session.TableExist()) + { + session.CreateTable(); + } + else + { + //首次创建fl_plugin_delivery_kuaidi 表,提取以前的快递点位置,并自动插入 + if (is_first) + { + var groups = GetGroups(); + foreach (var item in groups) + { + var list = item.position.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList(); + if (list != null) + { + int number = 0; + foreach (var kuaidi in list) + { + if (!string.IsNullOrEmpty(kuaidi)) + { + number++; + session.Insertable(new fl_plugin_delivery_kuaidi() { group_id = item.id, name = kuaidi }).ExecuteCommand(); + } + } + if (number > 0) + session.ExcuteSQL("update fl_plugin_delivery_group set position='' where id="+item.id); + + } + + } + + } + } + + if (!session.TableExist()) + { + session.CreateTable(); + }else if (!session.ColumnExist("fl_plugin_delivery_item", "q_location_id")) + { + session.AddColumn("fl_plugin_delivery_item", "q_location_id", " integer default 0"); + } + + //if (!session.ColumnExist("fl_plugin_delivery_group", "upload_msg")) session.AddColumn("fl_plugin_delivery_group", "upload_msg","varchar(255) default ''"); + if (!session.TableExist()) + { + session.CreateTable(); + session.AddIndex("robot_name", "new_friend_wxid");//增加索引.以后数据多了.查询速度会比较快 + session.AddUnique("robot_name", "new_friend_wxid");//增加唯一约束 + } + + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("order_code"); + } + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.WebRequestEvent += SDK_WebRequestEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + SDK.WXApplyFriendEvent += SDK_WXApplyFriendEvent; + SDK.WXNewFriendEvent += SDK_WXNewFriendEvent; + base.Start(); + } + + private List welcomeTip_Friends = new List(); + private static object lock_newfriend = new object(); + + private void SDK_WXNewFriendEvent(object sender, Chat.Framework.WXSdk.Events.WXNewFriend e) + { + try + { + fl_plugin_delivery_applyfriend_info friend = null; + var session = ApiClient.GetSession(); + fl_member_info new_member = null; + var robot = session.FindRobotInfo(e.Client.WeixinHao, ChatType.微信); + if (robot != null) + { + Thread.Sleep(1100); + lock (lock_newfriend) + { + if (!welcomeTip_Friends.Contains(e.Friend.UserName)) + { + friend = session.Queryable().OrderBy(f => f.id, SqlSugar.OrderByType.Desc).First(f => f.new_friend_wxid == e.Friend.UserName && f.robot_name == e.Client.WeixinHao); + + #region fl_plugin_delivery_applyfriend_info "已接受" + if (friend != null && friend.state != "已接受") + { + friend.state = "已接受"; + session.Saveable(friend).ExecuteReturnEntity(); + } + #endregion + + if (welcomeTip_Friends.Count > 10000) welcomeTip_Friends.Clear(); + welcomeTip_Friends.Add(e.Friend.UserName); + + new_member = session.Queryable().First(f => f.robot_type == ChatType.微信 && f.username == e.Friend.UserName); + if (new_member == null) + { + new_member = new fl_member_info() { crt_time = DateTime.Now, usernick = e.Friend.NickName, robot_name = e.Client.WeixinHao, robot_type = ChatType.微信, username = e.Friend.UserName, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + var groups = session.FindGroups(); + if (groups.Count != 0) + new_member.group_id = groups[0].id; + session.SaveOrUpdate(new_member); + var o = new fl_plugin_delivery_hist() //设备集合 + { + ordertable_cratetime = DateTime.MinValue, + ordertable_id = 0, + userid = new_member.id, + effective = true, + order_code = GetRandomCode(session)//Code值 + }; + session.Insertable(o).ExecuteCommand(); + var group = GetGroup(new_member); + if (group == null) return; + string qurl = string.Empty; + if (group.WelcomeTip.Contains("[取件地址]")) + qurl = GetURL(URLType.取件地址, new_member); + ApiClient.SendMessage(robot, e.Friend.UserName, group.WelcomeTip.Replace("[免单码]", o.order_code).Replace("[取件地址]", qurl)); + + } + } + } + } + } + catch (Exception ex) + { + this.OnLog("NewFriend = " + ex.Message); + } + } + + + private static readonly object applyFriendLock = new object(); + public static Queue queue = new Queue();//新加好友审核队列 + private bool IsApply = false; + private void ApplyWechatFriend() + { + if (IsApply) return; + IsApply = true; + Task.Run(() => + { + try + { + var session = ApiClient.GetSession(); + do + { + var apply_id = queue.Dequeue(); + var friend = session.Queryable().First(f => f.id == apply_id); + if (friend != null) + { + Thread.Sleep(3000); + if (friend != null && friend.state == "已接受") continue; + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == friend.robot_name /*&& f.WeixinType == WeixinType.Grpc微信*/ && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (client != null) + { + string result = client.AgreeAddMe(HttpHelper.URLDecode(friend.token)); + if (string.IsNullOrEmpty(result)) friend.state = "已接受"; + else friend.state = result; + session.Saveable(friend).ExecuteReturnEntity(); + } + } + } while (true); + } + catch (Exception) + { } + finally + { + IsApply = false; + } + }); + } + + /// + /// 微信 - 申请添加我为好友,需要审核 + /// + /// + /// + private void SDK_WXApplyFriendEvent(object sender, Chat.Framework.WXSdk.Events.WXApplyFriend e) + { + try + { + lock (applyFriendLock) + { + var session = ApiClient.GetSession(); + var friend = session.FindSingle("select * from fl_plugin_delivery_applyfriend_info where new_friend_wxid = @new_friend_wxid and robot_name = @robot_name", new { new_friend_wxid = e.NewFriendWxid, robot_name = e.Client.WeixinHao }); + if (friend != null && friend.state == "已接受") return; + if (friend == null) + { + friend = session.Insertable(friend = new fl_plugin_delivery_applyfriend_info() + { + state = "待审核", + crt_time = DateTime.Parse(e.CrtTime.ToString("yyyy-MM-dd HH:mm:ss")), + message = e.Message.Trim(), + robot_name = e.Client.WeixinHao, + user_nick = e.Client.User.Nick, + new_friend_nick = e.NewFriendNick, + new_friend_wxid = e.NewFriendWxid, + old_friend_nick = e.OldFriendNick, + old_friend_wxid = e.OldFriendWxid, + token = HttpHelper.URLEncode(e.Token) + }).ExecuteReturnEntity(); + } + var group = GetGroup(e.Client.WeixinHao); + if (group == null) return; + if (group.Accept == SwitchType.关闭) return; + var robot = session.FindRobots().FirstOrDefault(f => f.name == e.Client.WeixinHao && f.type == ChatType.微信); + if (robot == null) return; + if (!queue.Contains(friend.id)) + { + queue.Enqueue(friend.id); + ApplyWechatFriend(); + } + } + } + catch (Exception ex) + { + this.OnLog("ApplyFriend = " + ex.Message + " - " + ex.StackTrace); + } + } + + public override void ShowForm() + { + var form = new 会员数据操作(); + form.ShowDialog(); + } + public enum URLType : int + { + 取件地址 = 1, + 查看订单 = 2, + 凭证图片地址 = 3 + } + private string GetURL(URLType type, fl_member_info info,fl_plugin_delivery_item item=null) + { + var result = string.Empty; + switch (type) + { + case URLType.取件地址: + result = $"http://{ApiClient.Setting.ServerConfig.Domain}/kuaidi/qujian.html?token={GetEncuserinfo(info)}"; + break; + case URLType.查看订单: + result = $"http://{ApiClient.Setting.ServerConfig.Domain}/kuaidi/peisong.html?token={GetEncuserinfo(info)}"; + break; + case URLType.凭证图片地址: + result = $"http://{ApiClient.Setting.ServerConfig.Domain}/kuaidi/image/{item.id}.jpg"; + break; + default: + break; + } + if (!string.IsNullOrEmpty(result)) result = ApiClient.ShortURL(result).Result; + return result; + } + private void SDK_OrderNoticeEvent(object sender, Api.Framework.Events.OrderNoticeEvent e) + { + if (e.OrderNoticeType == Api.Framework.Enums.OrderNoticeType.客户订单) + { + #region 三个平台订单 + var session = ApiClient.GetSession(); + base_model_order order = null; + CpsType cps = CpsType.阿里妈妈; + DateTime createTime = DateTime.MinValue; + var title = string.Empty; + var orderId = string.Empty; + var orderSonId = string.Empty; + var fee = 0d; + + + if (e.Order is fl_order_alimama) + { + order = e.Order as fl_order_alimama; + var tbOrder = ((fl_order_alimama)order); + createTime = tbOrder.create_time; + title = tbOrder.item_title; + orderId = tbOrder.trade_parent_id; + orderSonId = tbOrder.trade_id; + fee = tbOrder.pub_share_pre_fee; + cps = CpsType.阿里妈妈; + } + if (e.Order is fl_order_pinduoduo) + { + order = e.Order as fl_order_pinduoduo; + var pddOrder = (fl_order_pinduoduo)order; + createTime = pddOrder.order_create_time; + title = pddOrder.goods_name; + orderId = pddOrder.order_sn; + fee = pddOrder.promotion_amount; + cps = CpsType.多多进宝; + } + if (e.Order is fl_order_jingdong) + { + order = e.Order as fl_order_jingdong; + var jdOrder = (fl_order_jingdong)order; + createTime = jdOrder.orderTime; + title = jdOrder.skuName; + orderId = jdOrder.orderId.ToString(); + fee = jdOrder.estimateFee; + cps = CpsType.京东联盟; + } + + if (order != null && order.db_userid != 0)//阿里妈妈订单 + { + var member = session.FindMemberInfoById(order.db_userid); + if (member == null) return; + var robot = session.FindRobotInfo(member.robot_name, member.robot_type); + if (robot == null) return; + var group = GetGroup(member); + if(group==null )return; + var msg = string.Empty; + + var o = session.Queryable().First(f => f.ordertable_id == order.id && f.ordertable_type == cps); + //付款成功赠送了一个免单码 + if (order.db_status == SystemOrderStatus.订单付款) + { + var freeCount = session.Find("select * from fl_plugin_delivery_hist where userid = @userid", new { userid = order.db_userid }).Count;//判断是否为前几单,前几单不判断佣金金额 + if (freeCount > group.FreeCount && fee < group.ConditionPoint)//订单不满足条件 + { + msg = group.BMsgError1 + .Replace("[商品标题]", title) + .Replace("[订单号]", orderId); + } + else + { + if (o != null && !o.effective) + { + if (o.using_userid == 0) + { + o.effective = true; + session.Saveable(o).ExecuteCommand(); + } + else o = null; + } + + if (o == null) + { + o = new fl_plugin_delivery_hist() //设备集合 + { + ordertable_cratetime = freeCount == 0 ? DateTime.MinValue : createTime, + ordertable_id = order.id, + ordertable_type = cps, + userid = order.db_userid, + effective = true, + order_code = GetRandomCode(session)//Code值 + }; + session.Insertable(o).ExecuteCommand(); + } + + var qurl = GetURL(URLType.取件地址, member); + //成功获得免单 + msg = group.BMsgSuccess1 + .Replace("[商品标题]", title) + .Replace("[订单号]", orderId) + .Replace("[免单码]", o.order_code) + .Replace("[取件地址]", qurl); + } + } + //订单失效/维权 失效一个免单码 + //else if (order.db_status == SystemOrderStatus.订单失效 || order.db_status == SystemOrderStatus.订单维权中 || order.db_status == SystemOrderStatus.全额退款 || order.db_status == SystemOrderStatus.订单退款)//订单失败,查看是否被绑定过 + else if (order.db_status == SystemOrderStatus.订单失效 || order.db_status == SystemOrderStatus.订单维权中)//订单失败,查看是否被绑定过 + { + if (o == null) return;//免单码 + if (!o.effective || o.using_userid != 0)//改免单码已经被使用,获取一个有效的免单码改成无效 + { + o = session.Queryable().First(f => f.userid == order.db_userid && f.effective && f.using_userid == 0); + if (o == null) return;//存在有效的,进行作废操作 + } + if (o.effective) + { + if (o.using_userid != 0) + { + o = session.Queryable().First(f => f.userid == order.db_userid && f.effective && f.using_userid == 0); + if (o == null) return;//存在有效的,进行作废操作 + } + o.effective = false; + session.Saveable(o).ExecuteCommand(); + } + + msg = (order.db_status == SystemOrderStatus.订单维权中 ? group.BMsgError4 : group.BMsgError3) + .Replace("[商品标题]", title) + .Replace("[订单号]", orderId) + .Replace("[免单码]", o.order_code); + } + + #region xxx + //else if (order.db_status == SystemOrderStatus.部分退款)//判断维权以后订单是否满足条件 + //{ + // //获取订单维权以后的金额 + // if (cps == CpsType.阿里妈妈) + // { + // var refundOrder = session.FindSingle("select * from fl_order_refund_alimama where tbtradeparentid = @tbtradeparentid and tbtradeid = @tbtradeid and showrefundstatus = @showrefundstatus", new { tbtradeparentid = orderId, tbtradeid = orderSonId, showrefundstatus = "维权成功" }); + + // if (refundOrder != null) + // fee = fee - refundOrder.refundfee; + // } + + // if (fee >= config.Condition)//订单满足条件 + // { + // if (o != null) + // { + // if (o.using_userid == 0) + // { + // if (!o.effective) + // { + // o.effective = true; + // session.Saveable(o).ExecuteCommand(); + // } + // else//该免单码没有被使用过并且为有效(似乎不存在这种情况) + // { } + // } + // else//免单码已经被用户使用过,重新生成一个给用户 + // { + // o = null; + // } + // } + + // if (o == null) + // { + // o = new fl_plugin_delivery_hist() //设备集合 + // { + // ordertable_cratetime = createTime, + // ordertable_id = order.id, + // ordertable_type = cps, + // userid = order.db_userid, + // effective = true, + // order_code = GetRandomCode(session)//Code值 + // }; + // session.Insertable(o).ExecuteCommand(); + // } + + // var qurl = GetURL(URLType.取件地址, member); + // //成功获得免单 + // msg = config.BMsgSuccess1 + // .Replace("[商品标题]", title) + // .Replace("[订单号]", orderId) + // .Replace("[免单码]", o.order_code) + // .Replace("[取件地址]", qurl); + // } + //} + #endregion + + //发送消息 + if (!string.IsNullOrWhiteSpace(msg)) + { + ApiClient.SendMessage(robot, member.username, msg); + e.Cancel = true; + return; + } + } + #endregion + } + } + private static object _lock_add = new object(); + private void SDK_WebRequestEvent(object sender, Api.Framework.Events.WebRequestEvents e) + { + if (e.Param.ContainsKey("method") && e.Param.ContainsKey("token")) + { + var method = e.Param["method"].ToString(); + var delivery = e.Param["token"].ToString(); + try + { + //解密用户信息 + var member = GetDecuserinfo(delivery); + if (member == null) throw new Exception("抱歉,您的连接已失效!"); + var group = GetGroup(member); + if (group == null) throw new Exception("抱歉,您的连接已失效!"); + + switch (method) + { + case "UploadPic": + { + var id = int.Parse(e.Param["id"].ToString()); + var session = ApiClient.GetSession(); + var v = session.Queryable().Single(x=>x.id == id); + if (v == null) throw new Exception("此订单已删除!"); + if (v.groupid != group.id) throw new Exception("非法操作!"); + if (!v.is_arrive) + { + + if (!string.IsNullOrEmpty(e.Param["img"])) + { + + var filename = Util.MapFile($"{id}.jpg", "wwwroot\\kuaidi\\image"); + var base64 = System.Web.HttpUtility.HtmlEncode(e.Param["img"]); + base64 = base64.Trim().Replace("%", "").Replace(",", "").Replace(" ", "+"); + if (base64.Length % 4 > 0) + { + base64 = base64.PadRight(base64.Length + 4 - base64.Length % 4, '='); + } + byte[] data = Convert.FromBase64String(base64); + // data = Util.AddWaterMark(data,"测试水印"); + File.WriteAllBytes(filename, data); + + } + + + session.ExcuteSQL("update fl_plugin_delivery_item set is_arrive = 1 where id=" + v.id); + var robot = session.FindRobotInfo(member.robot_name, member.robot_type); + if (robot != null) + { + var m = session.Queryable().Where(x => x.id == v.userid).First(); + if (m != null) + { + var pic_url = string.Empty; + if (!string.IsNullOrEmpty(e.Param["img"])) + { + pic_url = GetURL(URLType.凭证图片地址, m, v); + } + var msg = group.upload_msg.Replace("[取件码]", v.q_code).Replace("[凭证图片地址]",pic_url); + ApiClient.SendMessage(robot, m.username, msg); + } + } + } + + e.Send("保存成功!"); + break; + } + + case "GetPositions": + { + e.Send(group.GetPositions()); + break; + } + case "GetTasks": + { + var key = e.Param.ContainsKey("keyword") ? e.Param["keyword"] : string.Empty; + bool isadmin = group.admins.Split('|').Contains(member.id.ToString()); + if (isadmin) + { + var date_type = e.Param["date_type"].ToString(); + var star_time = DateTime.Parse(DateTime.Parse(e.Param["date_time"].ToString()).ToString("yyyy-MM-dd 00:00:00")); + var end_time = star_time.AddDays(1); + if (date_type == "2") end_time = star_time.AddHours(11); + else if (date_type == "3") + { + star_time = star_time.AddHours(11); + end_time = star_time.AddDays(1); + } + var location = e.Param["q_location"].ToString(); + List items; + var session = ApiClient.GetSession(); + if (location == "全部快递点位置") + items = session.Queryable().Where(f=>f.groupid == group.id && f.crt_time>= star_time && f.crt_time< end_time).OrderBy(f=>f.id, SqlSugar.OrderByType.Desc).ToList(); + else + items = session.Queryable().Where(f => f.crt_time >= star_time && f.crt_time < end_time && f.groupid == group.id && f.q_location ==location ).OrderBy(f => f.id, SqlSugar.OrderByType.Desc).ToList(); + var list = new ArrayList(); + foreach (var item in items) list.Add(new { real_name = item.real_name, q_location = item.q_location, crt_time = item.crt_time.ToString("yyyy-MM-dd HH:mm:ss"), is_arrive = item.is_arrive , q_code = item.q_code , real_telnumber = item.real_telnumber, s_location = item.s_location,id = item.id}); + e.Send(list); + break; + } + else throw new Exception("权限不足!"); + } + case "GetBasics": + { + if (!string.IsNullOrEmpty(group.stop_sumbmit_text)) throw new Exception(group.stop_sumbmit_text); + var temp_times = group.lastTime.Replace(":",":").Split(':'); + var h = int.Parse(temp_times[0]); + var m = int.Parse(temp_times[1]); + + var is_peisong = true; + if (DateTime.Now.Hour == h) is_peisong = DateTime.Now.Minute > m ? false : true; + else if (DateTime.Now.Hour > h) is_peisong = false; + if (!is_peisong) throw new Exception(@"明天在来提交新的取货码哦! +亲爱的同学,下午" + h + "点" + m + "分后停止配送啦!"); + + var session = ApiClient.GetSession(); + var _q_codes = session.Queryable().Where(f => f.userid == member.id && f.using_userid == 0 && f.effective).OrderBy(f => f.ordertable_cratetime, SqlSugar.OrderByType.Asc).ToPageList(0, 20); + List q_codes = new List(); + foreach (var item in _q_codes) q_codes.Add(item.order_code); + var q_locations = group.GetPositions(); + var q_hist = session.Queryable().Where(f => f.userid == member.id).OrderBy(f => f.crt_time, SqlSugar.OrderByType.Desc).First(); + var real_name = string.Empty; + var telnumber = string.Empty; + var s_location = string.Empty; + if (q_hist != null) + { + real_name = q_hist.real_name; + telnumber = q_hist.real_telnumber; + s_location = q_hist.s_location; + } + e.Send(new { q_codes = q_codes, q_locations = q_locations, real_name = real_name, telnumber = telnumber, s_location = s_location }); + + break; + } + case "AddDelivery": + { + if (!string.IsNullOrEmpty(group.stop_sumbmit_text)) throw new Exception(group.stop_sumbmit_text); + var temp_times = group.lastTime.Replace(":", ":").Split(':'); + var h = int.Parse(temp_times[0]); + var m = int.Parse(temp_times[1]); + + var is_peisong = false; + if (DateTime.Now.Hour == h) is_peisong = DateTime.Now.Minute > m ? false : true; + else if (DateTime.Now.Hour > h) is_peisong = false; + if (is_peisong) throw new Exception(@"明天在来提交新的取货码哦! +亲爱的同学,下午" + h + "点" + m + "分后停止配送啦!"); + + var real_name = e.Param["real_name"]; + if (string.IsNullOrEmpty(real_name)) throw new Exception("姓名为必填项!"); + var telnumber = e.Param["telnumber"]; + if (string.IsNullOrEmpty(telnumber)) throw new Exception("手机为必填项!"); + if (!Regex.Match(telnumber, @"^\d{11,}$").Success) throw new Exception("手机格式不对,必须为11位数字!"); + var qcode = e.Param["qcode"]; + if (string.IsNullOrEmpty(qcode)) throw new Exception("取件码为必填项!"); + var mcode = e.Param["mcode"]; + lock (_lock_add) + { + var session = ApiClient.GetSession(); + var hist = session.Queryable().Where(f => f.order_code == mcode).Single(); + if (hist == null) throw new Exception("免单码不存在,请核实后重试!"); + if (!hist.effective) throw new Exception("此免单码已失效!"); + if (hist.using_userid != 0) throw new Exception("此免单码已被使用!"); + if (hist.ordertable_cratetime > DateTime.Now.AddHours(-24)) + throw new Exception($"此免单码{mcode},需要{Math.Round((24.00 - (DateTime.Now - hist.ordertable_cratetime).TotalHours), 2)}小时候后,才可以使用!"); + var q_location = e.Param["q_location"]; + if (!group.GetPositions().Contains(q_location)) throw new Exception("无法查询您的取件位置!"); + var s_location = e.Param["s_location"]; + if (string.IsNullOrEmpty(s_location) || s_location.Length < 5) throw new Exception("您的配送地址不够详细!"); + var kuaidi = session.Queryable().Where(f=>f.group_id == group.id && f.name == q_location).First(); + var data = new fl_plugin_delivery_item() + { + userid = member.id, + crt_time = DateTime.Now, + m_code = mcode, + q_code = qcode, + q_location = q_location, + s_location = s_location, + groupid = group.id, + real_name = real_name, + real_telnumber = telnumber, + q_location_id = kuaidi!=null?kuaidi.id:0 + }; + session.Insertable(data).ExecuteCommand(); + session.ExcuteSQL($"update fl_plugin_delivery_hist set using_userid={member.id} where id={hist.id};"); + var robot = session.FindRobotInfo(member.robot_name, member.robot_type); + if (robot != null) + { + var msg = group.TMsgSuccess1.Replace("[免单码]", mcode).Replace("[取件码]", qcode).Replace("[手机号]", telnumber).Replace("[收货地址]", s_location).Replace("[姓名]", real_name); + ApiClient.SendMessage(robot, member.username, msg); + } + } + + e.Send("提交成功、请耐心等待配送!"); + break; + } + + + case "PrintOrder": + { + try + { + bool isadmin = group.admins.Split('|').Contains(member.id.ToString()); + if (isadmin) + { + + var id = int.Parse(e.Param["id"].ToString()); + var session = ApiClient.GetSession(); + fl_plugin_delivery_item v = session.Queryable().Single(x => x.id == id); + + if (v == null) throw new Exception("此订单已删除!"); + if (v.groupid != group.id) throw new Exception("非法操作!"); + + fl_plugin_delivery_kuaidi s = null; + if (v.q_location_id != 0) s = session.Queryable().Single(x => x.id == v.q_location_id); + else s = session.Queryable().Where(x => x.group_id == v.groupid && x.name == v.q_location).First(); + + if (s == null || string.IsNullOrEmpty(s.print_sn) || string.IsNullOrEmpty(s.print_model)) throw new Exception("该快递点,打印机已停止服务!"); + + var model = s.print_model.Replace("[姓名]",v.real_name).Replace("[手机]",v.real_telnumber).Replace("[取件码]",v.q_code).Replace("[收货位置]",v.s_location).Replace("[取件位置]",v.q_location).Replace("[编号]",v.id.ToString()).Replace("[免单码]",v.m_code); + HttpHelper http = new HttpHelper(); + var item = http.GetItem("https://www.yprinter.com/api/Order/addOrder", "", $"secret={s.print_secret}&print_sn={s.print_sn}&print_num=1&order_content={System.Web.HttpUtility.UrlEncode(model, Encoding.UTF8)}"); + var html = http.GetHtml(item).Html; + //{"code":104,"message":"\u5199\u5165\u65b0\u8ba2\u5355\u961f\u5217\u5931\u8d25","data":[]} + var dic = HttpExtend.JsonToDictionary(html); + if (dic != null) + { + int code = int.Parse(dic["code"].ToString()); + if (code != 100) throw new Exception(dic["message"].ToString()); + else e.Send(dic["message"].ToString()); + } + else throw new Exception(html); + //e.Send(dic==null?html:dic["message"].ToString()); + } + else throw new Exception("权限不足!"); + } + catch (Exception ex) + { + e.Send(ex); + } + break; + } + default: + throw new Exception("暂不支持此函数!"); + } + } + catch (Exception ex) + { + e.Send(ex); + } + } + } + + private void SDK_ReciveIMEvent(object sender, Api.Framework.SDK.ReciveIMEvent e) + { // + if (string.IsNullOrEmpty(e.Groupid)) + { + + //查询免单码 + if (e.Message == "免单码") + { + var group = GetGroup(e.RobotName); if (group == null) return; + var session = ApiClient.GetSession(); + var m = e.GetMemberinfo(); + var count = 0; + var histList = session.Queryable().Where(x => x.userid == m.id && x.using_userid == 0 && x.effective).OrderBy(x => x.id, SqlSugar.OrderByType.Desc).ToPageList(0, 100, ref count); + + StringBuilder sb = new StringBuilder(); + if (histList.Count == 0) sb.AppendLine("暂无"); + for (int i = 0; i < histList.Count; i++) + { + sb.AppendLine(histList[i].order_code); + } + var msg = group.CMsgSuccess1.Replace("[免单码列表]", sb.ToString().Trim()).Replace("[总数]", count.ToString()).Replace("[取件地址]", GetURL(URLType.取件地址, m)); + e.SendMessage(msg); + return; + } + else if (e.Message == "查看订单") + { + var group = GetGroup(e.RobotName); if (group == null) return; + var session = ApiClient.GetSession(); + var m = e.GetMemberinfo(); + if (group != null) + { + bool isadmin = group.admins.Split('|').Contains(m.id.ToString()); + if (isadmin) + { + e.SendMessage($"订单地址:\r\n"+GetURL(URLType.查看订单,m)); + e.Cancel = true; + return; + } + } + } + + #region 订单绑定 + + #region 淘宝订单绑定 + if (Regex.IsMatch(e.Message.Trim(), @"^\d{18}$")) + { + var group = GetGroup(e.RobotName); if (group == null) return; + var session = ApiClient.GetSession(); + var orderid = e.Message.Trim();//用户发送的订单号 + + var orders_temp = session.Find("select * from fl_order_alimama where trade_parent_id = @trade_parent_id", new { trade_parent_id = orderid }); + if (orders_temp != null && orders_temp.Count != 0) + { + var member = orders_temp.FirstOrDefault(f => f.db_userid != 0 && f.db_userid != e.GetMemberinfo().id); + if (member != null) + { + e.SendMessage(group.BMsgError6.Replace("[订单号]", orderid)); + return; + } + var notices = new List(); + + var downAlimamaTimer = new DownAlimamaTimer(); + + #region 订单用户已经绑定 纯提示,非结算的订单也提示上级 + var bindOrders = orders_temp.Where(f => f.db_userid != 0).ToList(); + if (bindOrders != null && bindOrders.Count != 0) + { + foreach (var order in bindOrders) + { + //var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + //if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(group.BMsgError5, order, e.GetMemberinfo(true))); + //else + // e.SendMessage(_GetOrderStateMess(order.db_status, (order.db_status == SystemOrderStatus.订单结算 ? SettleType.已结算提示 : SettleType.未结算提示), order, e.GetMemberinfo(true), point)); + Thread.Sleep(500); + } + //return; + } + #endregion + + #region 订单没有被绑定(两种情况 => 一个订单已经被结算 一个是订单未结算) + var notBindOrders = orders_temp.Where(f => f.db_userid == 0).ToList(); + if (notBindOrders != null && notBindOrders.Count != 0) + { + foreach (var order in notBindOrders) + { + //if (order.db_status == SystemOrderStatus.订单结算) + // order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + + //没有绑定用户的订单进行绑定 + order.db_userid = e.GetMemberinfo().id; + order.db_robotname = e.RobotName; + order.db_robottype = e.RobotInfo.type; + order.msg_groupid = e.Groupid; + + #region 手动绑定,重新计算用户的返利积分 xxx + //var itempoint = session.FindItemPoint(e.GetMemberinfo(), order.pub_share_pre_fee, order.item_num, CpsType.阿里妈妈); + //if (itempoint != null) + //{ + // order.db_point = HttpHelper.ObjectToJson(itempoint); + // order.db_userpoint = itempoint.UserPoint; + //} + #endregion + + session.SaveOrUpdate(order); + + #region 淘宝订单尾号自动采集 + if (ApiClient.Setting.SystemConfig.order_alimama_last_auto_capture == SwitchType.开启) + { + //订单尾号和用户进行绑定 + if (session.FindAlimamaOrderLastnums().FirstOrDefault(f => f.userid == e.GetMemberinfo().id) == null) + { + session.Insertable(new fl_alimama_order_lastnum() { userid = e.GetMemberinfo().id, lastnumber = order.trade_parent_id.Substring(order.trade_parent_id.Length - 6, 6) }).ExecuteCommand(); + session.FindAlimamaOrderLastnums(true); + } + } + #endregion + + if (order.db_status == SystemOrderStatus.订单付款 || order.db_status == SystemOrderStatus.订单失效 || order.db_status == SystemOrderStatus.订单维权中) + downAlimamaTimer.UpdateOrder(order, notices, session, isFrontData: true); + else + { + string mdcode = string.Empty; + if (group.BMsgError3.Contains("[免单码]")) + { + var delivery_hist = session.FindSingle("select * from fl_plugin_delivery_hist where userid = @userid and ordertable_id = @ordertable_id", new { userid = e.GetMemberinfo().id, ordertable_id = order.id }); + if (delivery_hist != null) mdcode = delivery_hist.order_code; + } + e.SendMessage(new VariateReplace().CommonReplace(group.BMsgError3, order, e.GetMemberinfo(true)).Replace("[免单码]", mdcode)); + } + } + } + #endregion + + #region 触发通知上级获得下级的提成奖励 + if (notices.Count != 0) + { + foreach (var item in notices) + { + SDK_OrderNoticeEvent(this, item); + } + } + #endregion + + e.Cancel = true; + + } + else + { + + e.SendMessage(group.BMsgError2.Replace("[订单号]", orderid)); + + //加入缓存 + var bind = session.FindBindCache(orderid); + if (bind == null) + { + session.Insertable(new fl_bind_cache() { crt_time = DateTime.Now, db_robotid = e.RobotInfo.id, orderid = orderid, groupid = e.Groupid, db_userid = e.GetMemberinfo().id }).ExecuteCommand(); + } + e.Cancel = true; + return; + } + } + #endregion + + #region 拼多多订单绑定 + if (Regex.IsMatch(e.Message.Trim(), @"^\d{6}-\d{15}$")) + { + var group = GetGroup(e.RobotName); if (group == null) return; + var session = ApiClient.GetSession(); + int i = 0; + Next: + var orderid = e.Message.Trim(); + + //通过宝贝的id 和 订单号 进行查询 查看是否存在 + var order = session.FindSingle("select * from fl_order_pinduoduo where order_sn = @order_sn", new { order_sn = orderid }); + if (order != null) + { + if (order.db_userid != 0 && order.db_userid != e.GetMemberinfo().id) + { + e.SendMessage(group.BMsgError6.Replace("[订单号]", orderid)); + return; + } + + var notices = new List(); + var downPinduoduoTimer = new DownPinduoduoTimer(); + + if (order.db_userid != 0) + { + //var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + //if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(group.BMsgError5, order, e.GetMemberinfo(true))); + //else + // e.SendMessage(_GetOrderStateMess(order.db_status, order, e.GetMemberinfo(true), point)); + } + else + { + //if (order.db_status == SystemOrderStatus.订单结算) + // order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + + //用户绑定订单 + order.db_robotname = e.RobotName; + order.db_robottype = e.ChatType; + order.msg_groupid = e.Groupid; + order.db_userid = e.GetMemberinfo().id; + session.SaveOrUpdate(order); + + if (order.db_status == SystemOrderStatus.订单付款 || order.db_status == SystemOrderStatus.订单维权中) + downPinduoduoTimer.UpdateOrder(order, session, notices, isFrontData: true); + else + e.SendMessage(new VariateReplace().CommonReplace(group.BMsgError3, order, e.GetMemberinfo(true))); + } + + //#region 触发通知上级获得下级的提成奖励 + //if (notices.Count != 0) + //{ + // var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + // foreach (var item in notices) + // { + // SDK_OrderNoticeEvent(this, item); + // } + //} + //#endregion + + e.Cancel = true; + } + else + { + if (i < 1) + { + CpsClient.UpdateOrder(CpsType.多多进宝, DateTime.Now.AddMinutes(-30), DateTime.Now, orderid); + i++; + goto Next; + } + e.SendMessage(group.BMsgError2.Replace("[订单号]", orderid)); + e.Cancel = true; + return; + } + } + #endregion + + #region 京东订单绑定 + if (Regex.IsMatch(e.Message.Trim(), @"^\d{11,12}$")) + { + var group = GetGroup(e.RobotName); if (group == null) return; + var session = ApiClient.GetSession(); + var orderId = e.Message.Trim(); //订单号 + var orders = session.Find("select * from fl_order_jingdong where orderId = @orderId", new { orderId = orderId }); + + var _order = orders.FirstOrDefault(f => f.db_userid != 0 && f.db_userid != e.GetMemberinfo().id); + if (_order != null) + { + e.SendMessage(group.BMsgError6.Replace("[订单号]", orderId)); + return; + } + + if (orders != null && orders.Count != 0) + { + var notices = new List(); + var downJingdongTimer = new DownJingdongTimer(); + + #region 订单用户已经绑定 纯提示,非结算的订单也提示上级 + var bindOrders = orders.Where(f => f.db_userid != 0).ToList(); + if (bindOrders != null && bindOrders.Count != 0) + { + foreach (var order in bindOrders) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + //if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(group.BMsgError5, order, point, e.GetMemberinfo(true))); + //else + // e.SendMessage(_GetOrderStateMess(order.db_status, (order.db_status == SystemOrderStatus.订单结算 ? SettleType.已结算提示 : SettleType.未结算提示), order, e.GetMemberinfo(true), point)); + Thread.Sleep(500); + } + } + #endregion + + #region 订单没有被绑定(两种情况 => 一个订单已经被结算 一个是订单未结算) + var notBindOrders = orders.Where(f => f.db_userid == 0).ToList(); + if (notBindOrders != null && notBindOrders.Count != 0) + { + foreach (var order in notBindOrders) + { + //if (order.db_status == SystemOrderStatus.订单结算) + // order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + + //没有绑定用户的订单进行绑定 + order.db_userid = e.GetMemberinfo().id; + order.db_robotname = e.RobotName; + order.db_robottype = e.RobotInfo.type; + order.msg_groupid = e.Groupid; + + //#region 手动绑定,重新计算用户的返利积分 + //var itempoint = session.FindItemPoint(e.GetMemberinfo(), order.actualFee == 0 ? order.estimateFee : order.actualFee, (int)order.skuNum, CpsType.京东联盟); + //if (itempoint != null) + //{ + // order.db_point = HttpHelper.ObjectToJson(itempoint); + // order.db_userpoint = itempoint.UserPoint; + //} + //#endregion + + session.SaveOrUpdate(order); + if (order.db_status == SystemOrderStatus.订单付款 || order.db_status == SystemOrderStatus.订单维权中) + downJingdongTimer.UpdateOrder(order, session, notices, isFrontData: true); + else + e.SendMessage(new VariateReplace().CommonReplace(group.BMsgError3, order, e.GetMemberinfo(true))); + } + } + #endregion + + #region 触发通知上级获得下级的提成奖励 xxx + //if (notices.Count != 0) + //{ + // var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + // foreach (var item in notices) + // { + // SDK_OrderNoticeEvent(this, item); + // } + //} + #endregion + + e.Cancel = true; + } + else + { + e.SendMessage(group.BMsgError2.Replace("[订单号]", orderId)); + + //加入缓存 + var bind = session.FindBindCache(orderId); + if (bind == null) + { + session.Insertable(new fl_bind_cache() { crt_time = DateTime.Now, db_robotid = e.RobotInfo.id, orderid = orderId, groupid = e.Groupid, db_userid = e.GetMemberinfo().id }).ExecuteCommand(); + } + e.Cancel = true; + return; + } + } + #endregion + + #endregion + + } + } + + + private static List _groups = null; + public static List GetGroups(bool f5 = false) + { + try + { + if (_groups == null || f5) + { + var session = ApiClient.GetSession(); + _groups = session.Queryable().ToList(); + } + } + catch (Exception) + { + } + return _groups; + } + /// + /// 获取分组信息 + /// + /// + /// + private fl_plugin_delivery_group GetGroup(fl_member_info member) + { + var group = GetGroups().FirstOrDefault(f => f.GetWeixinhao().Contains(member.robot_name)); + if (group == null) throw new Exception($"找不到->{member.robot_name},机器人!"); + return group; + } + private fl_plugin_delivery_group GetGroup(string robotname) + { + var group = GetGroups().FirstOrDefault(f => f.GetWeixinhao().Contains(robotname)); + if (group == null) throw new Exception($"找不到->{robotname},机器人!"); + return group; + } + private byte[] aeskey = Encoding.UTF8.GetBytes("7b3b639bb3599aaf"); + private string GetEncuserinfo(fl_member_info member) + { + try + { + var json = HttpHelper.ObjectToJson(new { username = member.username, type = (int)member.robot_type, time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); + AESCryption enc = new AESCryption(); + return HttpExtend.ByteToHex(Encoding.UTF8.GetBytes(enc.AesEncrypt(json, aeskey))); + } + catch (Exception) + { + } + return string.Empty; + } + private fl_member_info GetDecuserinfo(string data) + { + try + { + AESCryption enc = new AESCryption(); + var json = Encoding.UTF8.GetString(HttpExtend.HexToByte(data)); + var mw = HttpExtend.JsonToDictionary(enc.AesDecrypt(json, aeskey)); + var session = ApiClient.GetSession(); + var member = session.Queryable().Where(f => f.robot_type.ToString() == mw["type"].ToString() && f.username == mw["username"].ToString()).Single(); + return member; + } + catch (Exception) + { + + } + return null; + } + + static string _codes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";//要随机的字母 + public static string GetRandomCode(SqlSugar.SqlSugarClient session, int number = 6) + { + + Next: + Random _rand = new Random(Guid.NewGuid().GetHashCode()); //随机类 + string _result = ""; + int length = _codes.Length; + for (int i = 0; i < number; i++) //循环6次,生成6位数字,10位就循环10次 + { + _result += _codes[_rand.Next(length)]; //通过索引下标随机 + + } + var code = session.Queryable().Single(f => f.order_code == _result); + if (code != null) goto Next; + return _result; + } + + + + public override void Stop() + { + try + { + + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/Delivery.Plugin/Config.cs b/应用/Delivery.Plugin/Config.cs new file mode 100644 index 0000000..65b036e --- /dev/null +++ b/应用/Delivery.Plugin/Config.cs @@ -0,0 +1,32 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace Delivery.Plugin +{ + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + [Config(Name = "插件-代取快递-配置")] + public class Config + { + + + [Category("1)、设置"), DisplayName("02.服务器地址"),Description(@"服务器地址")] + /// + /// 取件网址 + /// + public string QUrl { get; set; } + + + public Config() + { + + + } + } +} diff --git a/应用/Delivery.Plugin/Delivery.Plugin.csproj b/应用/Delivery.Plugin/Delivery.Plugin.csproj new file mode 100644 index 0000000..748db25 --- /dev/null +++ b/应用/Delivery.Plugin/Delivery.Plugin.csproj @@ -0,0 +1,163 @@ + + + + + Debug + AnyCPU + {4311A2FD-1032-47CE-B627-FE527A962288} + Library + Properties + Delivery.Plugin + Delivery.Plugin + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + Form + + + InputKeywordForm.cs + + + Form + + + InsertQCode.cs + + + Form + + + KuaidiForm.cs + + + + + + + + + True + True + Resources.resx + + + Form + + + 会员数据操作.cs + + + + + InputKeywordForm.cs + + + InsertQCode.cs + + + KuaidiForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + 会员数据操作.cs + + + + + + + + + + \ No newline at end of file diff --git a/应用/Delivery.Plugin/InputKeywordForm.Designer.cs b/应用/Delivery.Plugin/InputKeywordForm.Designer.cs new file mode 100644 index 0000000..7b34ee8 --- /dev/null +++ b/应用/Delivery.Plugin/InputKeywordForm.Designer.cs @@ -0,0 +1,63 @@ +namespace Delivery.Plugin +{ + partial class InputKeywordForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.textBox1.Location = new System.Drawing.Point(0, 0); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(265, 22); + this.textBox1.TabIndex = 0; + // + // InputKeywordForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(265, 23); + this.Controls.Add(this.textBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InputKeywordForm"; + this.Text = "请输入关键词"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.InputKeywordForm_FormClosing); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + } +} \ No newline at end of file diff --git a/应用/Delivery.Plugin/InputKeywordForm.cs b/应用/Delivery.Plugin/InputKeywordForm.cs new file mode 100644 index 0000000..1c4afc5 --- /dev/null +++ b/应用/Delivery.Plugin/InputKeywordForm.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Delivery.Plugin +{ + public partial class InputKeywordForm : BaseForm + { + public string Code { get; private set; } + public InputKeywordForm() + { + InitializeComponent(); + } + + private void InputKeywordForm_FormClosing(object sender, FormClosingEventArgs e) + { + this.Code = this.textBox1.Text; + } + } +} diff --git a/应用/Delivery.Plugin/InputKeywordForm.resx b/应用/Delivery.Plugin/InputKeywordForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/Delivery.Plugin/InputKeywordForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/Delivery.Plugin/InsertGroup.Designer.cs b/应用/Delivery.Plugin/InsertGroup.Designer.cs new file mode 100644 index 0000000..1c843eb --- /dev/null +++ b/应用/Delivery.Plugin/InsertGroup.Designer.cs @@ -0,0 +1,134 @@ +namespace Delivery.Plugin +{ + partial class InsertGroup + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(38, 35); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 14); + this.label1.TabIndex = 0; + this.label1.Text = "名称:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(26, 86); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(55, 14); + this.label2.TabIndex = 1; + this.label2.Text = "快递点:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(85, 31); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(227, 22); + this.textBox1.TabIndex = 2; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(85, 83); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox2.Size = new System.Drawing.Size(227, 129); + this.textBox2.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(26, 249); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(55, 14); + this.label3.TabIndex = 4; + this.label3.Text = "微信号:"; + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(85, 246); + this.textBox3.Multiline = true; + this.textBox3.Name = "textBox3"; + this.textBox3.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox3.Size = new System.Drawing.Size(227, 123); + this.textBox3.TabIndex = 5; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(145, 385); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(99, 32); + this.simpleButton1.TabIndex = 6; + this.simpleButton1.Text = "保存"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // InsertGroup + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(360, 429); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InsertGroup"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "分组管理"; + this.Load += new System.EventHandler(this.InsertGroup_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox3; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/应用/Delivery.Plugin/InsertGroup.cs b/应用/Delivery.Plugin/InsertGroup.cs new file mode 100644 index 0000000..03d0af4 --- /dev/null +++ b/应用/Delivery.Plugin/InsertGroup.cs @@ -0,0 +1,65 @@ +using Api.Framework; +using Api.Framework.Model; +using Delivery.Plugin.Model; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Delivery.Plugin +{ + public partial class InsertGroup : BaseForm + { + public InsertGroup(fl_plugin_delivery_group group) + { + InitializeComponent(); + + if (group != null) + { + this.group = group; + this.textBox1.Enabled = false; + this.textBox1.Text = group.name; + this.textBox2.Text = group.position; + this.textBox3.Text = group.weixinhao; + } + } + fl_plugin_delivery_group group = null; + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(this.textBox1.Text)) throw new Exception("不能为空名称!"); + var session = ApiClient.GetSession(); + if (group == null) + { + group = session.Queryable().Where(f => f.name != this.textBox1.Text).Single(); + if (group != null) throw new Exception("此名称已经存在!"); + group = new fl_plugin_delivery_group() { name = this.textBox1.Text }; + } + + + + group.position = this.textBox2.Text; + group.weixinhao = this.textBox3.Text; + session.Saveable(group).ExecuteCommand(); + BaseForm.ShowSuccess("设置成功!"); + this.Close(); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void InsertGroup_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/应用/Delivery.Plugin/InsertGroup.resx b/应用/Delivery.Plugin/InsertGroup.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/Delivery.Plugin/InsertGroup.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/Delivery.Plugin/InsertQCode.Designer.cs b/应用/Delivery.Plugin/InsertQCode.Designer.cs new file mode 100644 index 0000000..0dd2302 --- /dev/null +++ b/应用/Delivery.Plugin/InsertQCode.Designer.cs @@ -0,0 +1,122 @@ +namespace Delivery.Plugin +{ + partial class InsertQCode + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.button1 = new System.Windows.Forms.Button(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(46, 43); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(65, 12); + this.label1.TabIndex = 0; + this.label1.Text = "用户编号:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(46, 99); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(65, 12); + this.label2.TabIndex = 1; + this.label2.Text = "生成数量:"; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(127, 97); + this.numericUpDown2.Maximum = new decimal(new int[] { + 1410065407, + 2, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(88, 21); + this.numericUpDown2.TabIndex = 3; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(48, 156); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(157, 32); + this.button1.TabIndex = 4; + this.button1.Text = "生成"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(127, 41); + this.numericUpDown1.Maximum = new decimal(new int[] { + 1410065407, + 2, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(88, 21); + this.numericUpDown1.TabIndex = 2; + // + // InsertQCode + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(260, 214); + this.Controls.Add(this.button1); + this.Controls.Add(this.numericUpDown2); + this.Controls.Add(this.numericUpDown1); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InsertQCode"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "生成免单码"; + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.NumericUpDown numericUpDown1; + } +} \ No newline at end of file diff --git a/应用/Delivery.Plugin/InsertQCode.cs b/应用/Delivery.Plugin/InsertQCode.cs new file mode 100644 index 0000000..75cd87a --- /dev/null +++ b/应用/Delivery.Plugin/InsertQCode.cs @@ -0,0 +1,58 @@ +using Api.Framework.Model; +using Delivery.Plugin.Model; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Delivery.Plugin +{ + public partial class InsertQCode : Form + { + public InsertQCode() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + var session = Api.Framework.ApiClient.GetSession(); + try + { + + session.Ado.BeginTran(); + var member = session.Queryable().Single(f=>f.id == this.numericUpDown1.Value); + if (member == null) throw new Exception("用户编号不存在!"); + var msg = MessageBox.Show($"您确定要生成{this.numericUpDown2.Value}个免单码给{member.usernick}吗?","请确认",MessageBoxButtons.YesNo,MessageBoxIcon.Question); + if (msg == DialogResult.Yes) + { + List list = new List(); + for (int i = 0; i < this.numericUpDown2.Value; i++) + { + list.Add(new fl_plugin_delivery_hist() + { + effective = true, + ordertable_cratetime = DateTime.MinValue, + order_code = Class1.GetRandomCode(session), + userid = member.id + }); + } + session.Insertable(list).ExecuteCommand(); + BaseForm.ShowSuccess("已生成!"); + } + session.Ado.CommitTran(); + } + catch (Exception ex) + { + session.Ado.RollbackTran(); + BaseForm.ShowError(ex); + } + } + } +} diff --git a/应用/Delivery.Plugin/InsertQCode.resx b/应用/Delivery.Plugin/InsertQCode.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/应用/Delivery.Plugin/InsertQCode.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/应用/Delivery.Plugin/KuaidiForm.Designer.cs b/应用/Delivery.Plugin/KuaidiForm.Designer.cs new file mode 100644 index 0000000..206afe0 --- /dev/null +++ b/应用/Delivery.Plugin/KuaidiForm.Designer.cs @@ -0,0 +1,163 @@ +namespace Delivery.Plugin +{ + partial class KuaidiForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加ToolStripMenuItem, + this.修改ToolStripMenuItem, + this.删除ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(181, 92); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 增加ToolStripMenuItem + // + this.增加ToolStripMenuItem.Name = "增加ToolStripMenuItem"; + this.增加ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.增加ToolStripMenuItem.Text = "增加"; + this.增加ToolStripMenuItem.Click += new System.EventHandler(this.增加ToolStripMenuItem_Click); + // + // 修改ToolStripMenuItem + // + this.修改ToolStripMenuItem.Name = "修改ToolStripMenuItem"; + this.修改ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.修改ToolStripMenuItem.Text = "修改"; + this.修改ToolStripMenuItem.Click += new System.EventHandler(this.修改ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(800, 450); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "快递点名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.Caption = "打印机账号秘钥"; + this.gridColumn2.FieldName = "print_secret"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // gridColumn3 + // + this.gridColumn3.Caption = "打印机驱动/SN码"; + this.gridColumn3.FieldName = "print_sn"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + // + // gridColumn4 + // + this.gridColumn4.Caption = "备注"; + this.gridColumn4.FieldName = "remark"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + // + // KuaidiForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.gridControl1); + this.Name = "KuaidiForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "快递点编辑"; + this.Load += new System.EventHandler(this.KuaidiForm_Load); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 增加ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + } +} \ No newline at end of file diff --git a/应用/Delivery.Plugin/KuaidiForm.cs b/应用/Delivery.Plugin/KuaidiForm.cs new file mode 100644 index 0000000..62bcb20 --- /dev/null +++ b/应用/Delivery.Plugin/KuaidiForm.cs @@ -0,0 +1,111 @@ +using Api.Framework; +using Api.Framework.Tools; +using Delivery.Plugin.Model; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Delivery.Plugin +{ + public partial class KuaidiForm : BaseForm + { + fl_plugin_delivery_group group; + public KuaidiForm(fl_plugin_delivery_group group) + { + InitializeComponent(); + this.group = group; + } + + private void KuaidiForm_Load(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var _temp = session.Queryable().Where(f => f.group_id == group.id).ToList(); + this.gridControl1.DataSource = _temp; + } + catch (Exception) + { + + } + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + + } + + private void 增加ToolStripMenuItem_Click(object sender, EventArgs e) + { + + + try + { + var obj = new fl_plugin_delivery_kuaidi() { group_id = group.id}; + new SettingForm(obj).ShowDialog(); + if (!string.IsNullOrEmpty(obj.name)) + { + var session = ApiClient.GetSession(); + session.Insertable(obj).ExecuteCommand(); + KuaidiForm_Load(null, null); + } + } + catch (Exception) + { + + } + } + + private void 修改ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var obj = this.gridView1.GetRow(rows[0]) as fl_plugin_delivery_kuaidi; + new SettingForm(obj).ShowDialog(); + if (!string.IsNullOrEmpty(obj.name)) + { + var session = ApiClient.GetSession(); + session.Saveable(obj).ExecuteCommand(); + KuaidiForm_Load(null, null); + } + } + + } + catch (Exception) + { + + } + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var obj = this.gridView1.GetRow(rows[0]) as fl_plugin_delivery_kuaidi; + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_delivery_kuaidi where id="+obj.id); + this.gridView1.DeleteRow(rows[0]); + } + } + catch (Exception) + { + + } + } + } +} diff --git a/应用/Delivery.Plugin/KuaidiForm.resx b/应用/Delivery.Plugin/KuaidiForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Delivery.Plugin/KuaidiForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/应用/Delivery.Plugin/Model/fl_plugin_delivery_applyfriend_info.cs b/应用/Delivery.Plugin/Model/fl_plugin_delivery_applyfriend_info.cs new file mode 100644 index 0000000..eb54757 --- /dev/null +++ b/应用/Delivery.Plugin/Model/fl_plugin_delivery_applyfriend_info.cs @@ -0,0 +1,64 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Delivery.Plugin +{ + + public class fl_plugin_delivery_applyfriend_info : base_model + { + public fl_plugin_delivery_applyfriend_info() + { + state = "待审核"; + } + /// + /// 机器人的name。 robotinfo中的name + /// + public string robot_name { get; set; } + /// + /// 机器人名称 + /// + public string user_nick { get; set; } + /// + /// 申请时间 + /// + public DateTime crt_time { get; set; } + /// + /// 申请通过时间 + /// + public DateTime allow_time { get; set; } + /// + /// 申请时对方发送的验证信息 + /// + public string message { get; set; } + /// + /// 申请人昵称 + /// + public string new_friend_nick { get; set; } + /// + /// 申请人微信号 + /// + public string new_friend_wxid { get; set; } + /// + /// 推荐人昵称 + /// + public string old_friend_nick { get; set; } + /// + /// 推荐人微信号 + /// + public string old_friend_wxid { get; set; } + /// + /// token + /// + public string token { get; set; } + /// + /// 状态 + /// + public string state { get; set; } + + } + +} diff --git a/应用/Delivery.Plugin/Model/fl_plugin_delivery_group.cs b/应用/Delivery.Plugin/Model/fl_plugin_delivery_group.cs new file mode 100644 index 0000000..761e108 --- /dev/null +++ b/应用/Delivery.Plugin/Model/fl_plugin_delivery_group.cs @@ -0,0 +1,340 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace Delivery.Plugin.Model +{ + public class fl_plugin_delivery_group : base_model + { + [Category("1)、基础设置"), DisplayName("01.大学名字"), DefaultValue(3), Description(@"")] + /// + /// 大学名 + /// + public string name { get; set; } + + [SqlSugar.SugarColumn(Length = 2000)] + + + [Category("1)、基础设置"), DisplayName("02.取件位置"), DefaultValue(@""), Description(""), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)),Browsable(false)] + /// + /// 取件位置 + /// + public string position { get; set; } + private List Positions; + public List GetPositions(bool f5 = false) + { + if (Positions == null || f5) + { + Positions = new List(); + var session = ApiClient.GetSession(); + var _temp = session.Queryable().Where(f=>f.group_id == this.id).ToList(); + foreach (var item in _temp) Positions.Add(item.name); + } + + return Positions; + } + + + [Category("1)、基础设置"), DisplayName("03.机器人微信号"), DefaultValue(@""), Description(""), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + [SqlSugar.SugarColumn(Length = 2000)] + /// + /// 微信号 + /// + public string weixinhao { get; set; } + + private List weixinhaos; + public List GetWeixinhao(bool f5=false) + { + if (weixinhaos==null || f5) + { + weixinhaos = weixinhao.Split(new string[] { "\r\n" },StringSplitOptions.None).ToList(); + } + + return weixinhaos; + } + + [Category("1)、基础设置"), DisplayName("04.管理员ID"), DefaultValue(@""), Description("软件上的数据编号ID,并非微信号,或者微信ID."), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + [SqlSugar.SugarColumn(Length = 2000)] + public string admins { get; set; } + + + [Category("1)、基础设置"), DisplayName("05.最迟几点可提交"), DefaultValue(@""), Description("例如:16:30")] + public string lastTime { get; set; } + + + [Category("1)、基础设置"), DisplayName("07.强制停止提交原因"), DefaultValue(@""), Description("此处请不要写,如果写了原因,所有人将无法提交成功,将会提示此原因!"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string stop_sumbmit_text { get; set; } + + [Category("1)、基础设置"), DisplayName("08.备注"), DefaultValue(@""), Description(""), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 备注信息 + /// + public string remark { get; set; } + + + [Category("1)、基础设置"), DisplayName("09.上传凭证成功"), DefaultValue(@"快递已经到啦! +取货码:[取件码] +请速度拿哦~ +您好 同学快递已经送达 .下面链接是快递位置图片 +[凭证图片地址] +请及时拿走.送达后.您未及时拿走.后果自负哦~ +您觉得好可以向同学宣传一下咱们免费配送快递 +如果您下次还想用免费配送.请看如下视频 +[教程]"), Description(""), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 上传凭证提示语 + /// + public string upload_msg { get; set; } + + + #region 基础设置 + [Category("2)、运营设置"), DisplayName("01.免费次数"), DefaultValue(3), Description(@"新用户都会赠送免单码")] + /// + /// 免费多少单 + /// + public int FreeCount { get; set; } + + [ Category("2)、运营设置"), DisplayName("02.最低标准"), DefaultValue(3), Description(@"最低多少佣金,才参与免单")] + /// + /// 满足多少加一次 + /// + public double ConditionPoint { get; set; } + + + + [Category("2)、运营设置"), DisplayName("03.自动通过好友申请开关"), DefaultValue(SwitchType.开启), Description(@"功能开启时,将自动通过好友申请")] + public SwitchType Accept { get; set; } + + /// + /// 申请延迟时间秒数 + /// + [Category("2)、运营设置"), DisplayName("04.自动通过好友申请延迟时间"), DefaultValue(10), Description(@"自动通过好友申请功能开启时,将延迟申请通过动作")] + public int Retardation { get; set; } + + /// + /// 新人欢迎提示 + /// + [SqlSugar.SugarColumn(Length = 2000), Category("2)、运营设置"), DisplayName("05.新人欢迎提示"), DefaultValue(@"您好同学,我们承诺“终身免费”配送快递,永不收费!!!!! + +👇👇👇赠送您一个免单码 +免 单 码 :[免单码] +代取地址:[取件地址] + +打开连接填写信息,就给您配送 +以后想继续免费,可参考教程 +[教程]"), Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[取件地址]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string WelcomeTip { get; set; } + + + + [ Category("2)、运营设置"), DisplayName("06.付款成功提示"), DefaultValue(@"--------【获得免单】-------- +[商品标题] +🔨订单号:[订单号] +🔥免单码:[免单码] +🚚取件地址:[取件地址] +---------------------------------- +🎁恭喜您,获得一个免单码🎁 +🉐使用后帮您免费取快递🉐 +"), Description("支持变量:[商品标题]、[订单号]、[免单码]、[取件地址]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 绑定订单 - 提示语 + /// + public string BMsgSuccess1 { get; set; } + + + [ Category("2)、运营设置"), DisplayName("07.订单不满足标准"), DefaultValue(@"一一一一免 单 失 败一一一一 +[商品标题] +🔨订单号:[订单号]🔨 + +抱歉,此订单不满足免单条件,暂无法代取!"), Description("支持变量:[商品标题]、[订单号]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + + /// + /// 订单不满足 + /// + public string BMsgError1 { get; set; } + + [ Category("2)、运营设置"), DisplayName("08.找不到这个订单号"), DefaultValue(@"一一一一免 单 失 败一一一一 +🔨订单号:[订单号] +我们无法查询此订单信息,请确认是否通过我们免单链接下单!"), Description("支持变量:[订单号]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 订单不存在 + /// + public string BMsgError2 { get; set; } + + + [Category("2)、运营设置"), DisplayName("09.订单退款或失效了"), DefaultValue(@"一一一一撤 销 免 单一一一一 +[商品标题] + +🔥免单码:[免单码] +🔨订单号:[订单号] +由于退款或取消交易、已撤销一个免单码!"), Description("支持变量:[商品标题]、[订单号]、[免单码]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + + /// + /// 订单失效、或退款 + /// + public string BMsgError3 { get; set; } + + [ Category("2)、运营设置"), DisplayName("10.订单维权中"), DefaultValue(@"一一一一撤 销 免 单一一一一 +[商品标题] +🔥免单码:[免单码] +🔨订单号:[订单号] +已经领取过,无法重复领取哦!"), Description(@"支持变量:[商品标题]、[订单号]、[免单码]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 订单维权中 + /// + public string BMsgError4 { get; set; } + + [ Category("2)、运营设置"), DisplayName("11.订单重复绑定"), DefaultValue(@"一一一一【获得免单】一一一一 +[商品标题] +🔨订单号:[订单号] +🔥免单码:[免单码] +🚚取件地址:[取件地址] +---------------------------------- +🎁恭喜您,获得一个免单码🎁 +🉐使用后帮您免费取快递🉐"), Description(@"支持变量:[商品标题]、[订单号]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 订单重复绑定 + /// + public string BMsgError5 { get; set; } + + [ Category("2)、运营设置"), DisplayName("12.订单号已被他人绑定"), DefaultValue(@"一一一一免 单 失 败一一一一 +订单号:[订单号] + +不好意思,这个订单被其他同学认领了哦!"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 订单重复绑定 + /// + public string BMsgError6 { get; set; } + + [ Category("2)、运营设置"), DisplayName("13.获取免单码列表"), DefaultValue(@"一一一一免 单 码一一一一 +[免单码列表] +🚚取件地址:[取件地址] +一一一一一一一一一一一一 +免单码可以分享给同学一起用哦~特别是她!"), Description(@"支持变量:[免单码列表]、[取件地址]、[总数]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 查询免单码 提示语 + /// + public string CMsgSuccess1 { get; set; } + + [ Category("2)、运营设置"), DisplayName("14.提交代取件成功"), DefaultValue(@"一一一一【提交成功】一一一一 +💞姓 名:[姓名] +🔥免单码:[免单码] +💬取件码:[取件码] +📞手机号:[手机号] +💒收货地:[收货地址] +---------------------------------- +⏳已收到您的订单,今天会给您配送 +⏳以后还想免费代拿快递 请看视频 +[教程]"), Description(@"支持变量:[免单码]、[取件码、[手机号]、[收货地址]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 提交订单 提示语 + /// + public string TMsgSuccess1 { get; set; } + + #endregion + + #region 自动通过好友 + + #endregion + + public fl_plugin_delivery_group() + { + this.stop_sumbmit_text = string.Empty; + this.remark = string.Empty; + this.lastTime = "17:00"; + this.name = string.Empty; + this.position = string.Empty; + this.weixinhao = string.Empty; + this.admins = string.Empty; + this.upload_msg = @"快递已经到啦! +取货码:[取件码] +请速度拿哦~ +您好 同学快递已经送达 .下面链接是快递位置图片 +[凭证图片地址] +请及时拿走.送达后.您未及时拿走.后果自负哦~ +您觉得好可以向同学宣传一下咱们免费配送快递 +如果您下次还想用免费配送.请看如下视频 +[教程]"; + + this.WelcomeTip = @"您好同学,我们承诺“终身免费”配送快递,永不收费!!!!! + +👇👇👇赠送您一个免单码 +免 单 码 :[免单码] +代取地址:[取件地址] + +打开连接填写信息,就给您配送 +以后想继续免费,可参考教程 +[教程]"; + + this.BMsgSuccess1 = @"一一一一免 单 失 败一一一一 +[商品标题] +🔨订单号:[订单号] + +抱歉,此订单不满足免单条件,暂无法代取!"; + + this.BMsgError1 = @"一一一一免 单 失 败一一一一 +[商品标题] +🔨订单号:[订单号] + +抱歉,此订单不满足免单条件,暂无法代取!"; + + this.BMsgError2 = @"一一一一免 单 失 败一一一一 +🔨订单号:[订单号] + +我们无法查询此订单信息,请确认是否通过我们免单链接下单!"; + + this.BMsgError3 = @"一一一一撤 销 免 单一一一一 +[商品标题] + +🔥免单码:[免单码] +🔨订单号:[订单号] +由于退款或取消交易、已撤销一个免单码!"; + + this.BMsgError4 = @"一一一一撤 销 免 单一一一一 +[商品标题] +🔥免单码:[免单码] +🔨订单号:[订单号] +已经领取过,无法重复领取哦!"; + + this.BMsgError5 = @"一一一一【获得免单】一一一一 +[商品标题] +🔨订单号:[订单号] +🔥免单码:[免单码] +🚚取件地址:[取件地址] +---------------------------------- +🎁恭喜您,获得一个免单码🎁 +🉐使用后帮您免费取快递🉐"; + + this.BMsgError6 = @"一一一一免 单 失 败一一一一 +订单号:[订单号] + +不好意思,这个订单被其他同学认领了哦!"; + + this.CMsgSuccess1 = @"一一一一免 单 码一一一一 +[免单码列表] +🚚取件地址:[取件地址] +一一一一一一一一一一一一 +免单码可以分享给同学一起用哦~特别是她!"; + + this.TMsgSuccess1 = @"一一一一【提交成功】一一一一 +💞姓 名:[姓名] +🔥免单码:[免单码] +💬取件码:[取件码] +📞手机号:[手机号] +💒收货地:[收货地址] +---------------------------------- +⏳已收到您的订单,今天会给您配送 +⏳以后还想免费代拿快递 请看视频 +[教程]"; + } + + + } +} diff --git a/应用/Delivery.Plugin/Model/fl_plugin_delivery_hist.cs b/应用/Delivery.Plugin/Model/fl_plugin_delivery_hist.cs new file mode 100644 index 0000000..239cd16 --- /dev/null +++ b/应用/Delivery.Plugin/Model/fl_plugin_delivery_hist.cs @@ -0,0 +1,55 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Delivery.Plugin.Model +{ + + public class fl_plugin_delivery_hist:base_model + { + + /// + /// 用户ID + /// + public long userid { get; set; } + + /// + /// 订单ID + /// + public long ordertable_id { get; set; } + + /// + /// 订单类型 + /// + public CpsType ordertable_type { get; set; } + + /// + /// 订单创建时间 + /// + public DateTime ordertable_cratetime { get; set; } + + /// + /// 免单码 + /// + public string order_code { get; set; } + + /// + /// 是否有效 + /// + public bool effective { get; set; } + + /// + /// 是否被使用 + /// + public int using_userid { get; set; } + + /// + /// 备注 + /// + public string remark { get; set; } + } +} diff --git a/应用/Delivery.Plugin/Model/fl_plugin_delivery_item.cs b/应用/Delivery.Plugin/Model/fl_plugin_delivery_item.cs new file mode 100644 index 0000000..dcce66b --- /dev/null +++ b/应用/Delivery.Plugin/Model/fl_plugin_delivery_item.cs @@ -0,0 +1,79 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Delivery.Plugin.Model +{ + public class fl_plugin_delivery_item : base_model + { + [Browsable(false)] + public long groupid { get; set; } + + [ReadOnly(true)] + /// + /// 用户ID + /// + public long userid { get; set; } + + [DisplayName("姓名")] + /// + /// 真实姓名 + /// + public string real_name { get; set; } + [DisplayName("手机号")] + /// + /// 真实手机号 + /// + public string real_telnumber { get; set; } + + [Browsable(false)] + /// + /// 免单码 + /// + public string m_code { get; set; } + + [DisplayName("取件码")] + /// + /// 取件码 + /// + public string q_code { get; set; } + + [DisplayName("快递点")] + /// + /// 取件位置 + /// + public string q_location { get; set; } + + /// + /// 取件位置 - ID + /// + public long q_location_id { get; set; } + + + [DisplayName("目的地")] + /// + /// 送达位置 + /// + public string s_location { get; set; } + + + + + [Browsable(false)] + /// + /// 是否送达 + /// + public bool is_arrive { get; set; } + + + [DisplayName("提交时间"),ReadOnly(true)] + /// + /// 创建时间 + /// + public DateTime crt_time { get; set; } + } +} diff --git a/应用/Delivery.Plugin/Model/fl_plugin_delivery_kuaidi.cs b/应用/Delivery.Plugin/Model/fl_plugin_delivery_kuaidi.cs new file mode 100644 index 0000000..cdc38d3 --- /dev/null +++ b/应用/Delivery.Plugin/Model/fl_plugin_delivery_kuaidi.cs @@ -0,0 +1,48 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace Delivery.Plugin.Model +{ + public class fl_plugin_delivery_kuaidi:base_model + { + /// + /// 快递点名称 + /// + public string name { get; set; } + [Browsable(false)] + /// + /// 学校ID + /// + public long group_id { get; set; } + /// + /// 打印机序号 + /// + public string print_sn { get; set; } + + /// + /// 打印机秘钥 + /// + public string print_secret { get; set; } + + [Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + /// + /// 打印Model + /// + public string print_model { get; set; } + + /// + /// 快递点备注 + /// + public string remark { get; set; } + public fl_plugin_delivery_kuaidi() + { + this.remark = this.print_secret = this.print_sn = this.print_model = this.name = string.Empty; + } + } +} diff --git a/应用/Delivery.Plugin/Properties/AssemblyInfo.cs b/应用/Delivery.Plugin/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f214c03 --- /dev/null +++ b/应用/Delivery.Plugin/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Delivery.Plugin")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Delivery.Plugin")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("4311a2fd-1032-47ce-b627-fe527a962288")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/Delivery.Plugin/Properties/Resources.Designer.cs b/应用/Delivery.Plugin/Properties/Resources.Designer.cs new file mode 100644 index 0000000..345cf8c --- /dev/null +++ b/应用/Delivery.Plugin/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Delivery.Plugin.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Delivery.Plugin.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 快递 { + get { + object obj = ResourceManager.GetObject("快递", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Delivery.Plugin/Properties/Resources.resx b/应用/Delivery.Plugin/Properties/Resources.resx new file mode 100644 index 0000000..3ae911c --- /dev/null +++ b/应用/Delivery.Plugin/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\快递.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/Delivery.Plugin/Resources/快递.jpg b/应用/Delivery.Plugin/Resources/快递.jpg new file mode 100644 index 0000000..b12b7b1 Binary files /dev/null and b/应用/Delivery.Plugin/Resources/快递.jpg differ diff --git a/应用/Delivery.Plugin/WindowsForm.Designer.cs b/应用/Delivery.Plugin/WindowsForm.Designer.cs new file mode 100644 index 0000000..736a94a --- /dev/null +++ b/应用/Delivery.Plugin/WindowsForm.Designer.cs @@ -0,0 +1,550 @@ +namespace Delivery.Plugin +{ + partial class WindowsForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox6 = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox5 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除学校ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.查询免单码ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.通过免单码搜索ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.增加免单码ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新免单码ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(817, 599); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3, + this.xtraTabPage4}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.settingControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(815, 573); + this.xtraTabPage1.Text = "设置"; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(815, 573); + this.settingControl1.TabIndex = 0; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.groupBox1); + this.xtraTabPage2.Controls.Add(this.gridControl1); + this.xtraTabPage2.Controls.Add(this.textBox1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(815, 573); + this.xtraTabPage2.Text = "分组数据"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.textBox6); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.simpleButton3); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.textBox5); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.textBox3); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Controls.Add(this.textBox4); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Location = new System.Drawing.Point(312, 13); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(500, 549); + this.groupBox1.TabIndex = 4; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "属性修改"; + // + // textBox6 + // + this.textBox6.Location = new System.Drawing.Point(131, 373); + this.textBox6.Multiline = true; + this.textBox6.Name = "textBox6"; + this.textBox6.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox6.Size = new System.Drawing.Size(319, 56); + this.textBox6.TabIndex = 19; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(43, 396); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(67, 14); + this.label5.TabIndex = 18; + this.label5.Text = "配送时间:"; + // + // simpleButton3 + // + this.simpleButton3.Location = new System.Drawing.Point(351, 495); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(99, 32); + this.simpleButton3.TabIndex = 17; + this.simpleButton3.Text = "新增"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(131, 495); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(99, 32); + this.simpleButton2.TabIndex = 16; + this.simpleButton2.Text = "清空"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // textBox5 + // + this.textBox5.Location = new System.Drawing.Point(131, 295); + this.textBox5.Multiline = true; + this.textBox5.Name = "textBox5"; + this.textBox5.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox5.Size = new System.Drawing.Size(319, 56); + this.textBox5.TabIndex = 15; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(55, 318); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(55, 14); + this.label4.TabIndex = 14; + this.label4.Text = "配送员:"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(241, 495); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(99, 32); + this.simpleButton1.TabIndex = 13; + this.simpleButton1.Text = "修改"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click_1); + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(131, 224); + this.textBox3.Multiline = true; + this.textBox3.Name = "textBox3"; + this.textBox3.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox3.Size = new System.Drawing.Size(319, 48); + this.textBox3.TabIndex = 12; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(55, 244); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(55, 14); + this.label3.TabIndex = 11; + this.label3.Text = "机器人:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(131, 91); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox2.Size = new System.Drawing.Size(319, 113); + this.textBox2.TabIndex = 10; + // + // textBox4 + // + this.textBox4.Location = new System.Drawing.Point(131, 48); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(319, 22); + this.textBox4.TabIndex = 9; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(55, 143); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(55, 14); + this.label2.TabIndex = 8; + this.label2.Text = "快递点:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(67, 52); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 14); + this.label1.TabIndex = 7; + this.label1.Text = "名称:"; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(11, 41); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(284, 521); + this.gridControl1.TabIndex = 3; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除学校ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 26); + // + // 删除学校ToolStripMenuItem + // + this.删除学校ToolStripMenuItem.Name = "删除学校ToolStripMenuItem"; + this.删除学校ToolStripMenuItem.Size = new System.Drawing.Size(129, 22); + this.删除学校ToolStripMenuItem.Text = "删除学校"; + this.删除学校ToolStripMenuItem.Click += new System.EventHandler(this.删除学校ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsSelection.ResetSelectionClickOutsideCheckboxSelector = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView1_RowClick); + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + // + // gridColumn1 + // + this.gridColumn1.Caption = "学校全名"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 188; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(11, 13); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(284, 22); + this.textBox1.TabIndex = 1; + this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.pageControl1); + this.xtraTabPage3.Controls.Add(this.gridControl2); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(815, 573); + this.xtraTabPage3.Text = "免单码管理"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 537); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(815, 36); + this.pageControl1.TabIndex = 1; + // + // gridControl2 + // + this.gridControl2.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl2.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(815, 531); + this.gridControl2.TabIndex = 0; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查询免单码ToolStripMenuItem, + this.增加免单码ToolStripMenuItem, + this.刷新免单码ToolStripMenuItem}); + this.contextMenuStrip2.Name = "contextMenuStrip2"; + this.contextMenuStrip2.Size = new System.Drawing.Size(137, 70); + // + // 查询免单码ToolStripMenuItem + // + this.查询免单码ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1, + this.通过免单码搜索ToolStripMenuItem}); + this.查询免单码ToolStripMenuItem.Name = "查询免单码ToolStripMenuItem"; + this.查询免单码ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.查询免单码ToolStripMenuItem.Text = "查询免单码"; + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(161, 22); + this.toolStripMenuItem1.Text = "通过用户ID搜索"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click); + // + // 通过免单码搜索ToolStripMenuItem + // + this.通过免单码搜索ToolStripMenuItem.Name = "通过免单码搜索ToolStripMenuItem"; + this.通过免单码搜索ToolStripMenuItem.Size = new System.Drawing.Size(161, 22); + this.通过免单码搜索ToolStripMenuItem.Text = "通过免单码搜索"; + this.通过免单码搜索ToolStripMenuItem.Click += new System.EventHandler(this.通过免单码搜索ToolStripMenuItem_Click); + // + // 增加免单码ToolStripMenuItem + // + this.增加免单码ToolStripMenuItem.Name = "增加免单码ToolStripMenuItem"; + this.增加免单码ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.增加免单码ToolStripMenuItem.Text = "增加免单码"; + this.增加免单码ToolStripMenuItem.Click += new System.EventHandler(this.增加免单码ToolStripMenuItem_Click); + // + // 刷新免单码ToolStripMenuItem + // + this.刷新免单码ToolStripMenuItem.Name = "刷新免单码ToolStripMenuItem"; + this.刷新免单码ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.刷新免单码ToolStripMenuItem.Text = "刷新免单码"; + this.刷新免单码ToolStripMenuItem.Click += new System.EventHandler(this.刷新免单码ToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn2, + this.gridColumn5, + this.gridColumn7, + this.gridColumn8, + this.gridColumn3, + this.gridColumn4, + this.gridColumn10}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn2 + // + this.gridColumn2.Caption = "用户ID"; + this.gridColumn2.FieldName = "userid"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 0; + // + // gridColumn5 + // + this.gridColumn5.Caption = "免单码"; + this.gridColumn5.FieldName = "order_code"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.ReadOnly = true; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 1; + // + // gridColumn7 + // + this.gridColumn7.Caption = "有效性"; + this.gridColumn7.FieldName = "effective"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.ReadOnly = true; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 2; + // + // gridColumn8 + // + this.gridColumn8.Caption = "使用人"; + this.gridColumn8.FieldName = "using_userid"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.ReadOnly = true; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 3; + // + // gridColumn3 + // + this.gridColumn3.Caption = "关联订单"; + this.gridColumn3.FieldName = "ordertable_id"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.ReadOnly = true; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 4; + // + // gridColumn4 + // + this.gridColumn4.Caption = "关联订单类型"; + this.gridColumn4.FieldName = "ordertable_type"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.ReadOnly = true; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 6; + // + // gridColumn10 + // + this.gridColumn10.Caption = "下单时间"; + this.gridColumn10.FieldName = "ordertable_cratetime"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.ReadOnly = true; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 5; + // + // xtraTabPage4 + // + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(815, 573); + this.xtraTabPage4.Text = "数据下载"; + // + // WindowsForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(817, 599); + this.Controls.Add(this.xtraTabControl1); + this.Name = "WindowsForm"; + this.Text = "会员操作"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.WindowsForm_FormClosing); + this.Load += new System.EventHandler(this.WindowsForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private UI.Framework.Controls.SettingControl settingControl1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除学校ToolStripMenuItem; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox5; + private System.Windows.Forms.Label label4; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem 查询免单码ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private System.Windows.Forms.ToolStripMenuItem 增加免单码ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 通过免单码搜索ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 刷新免单码ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private System.Windows.Forms.TextBox textBox6; + private System.Windows.Forms.Label label5; + } +} \ No newline at end of file diff --git a/应用/Delivery.Plugin/WindowsForm.cs b/应用/Delivery.Plugin/WindowsForm.cs new file mode 100644 index 0000000..777d4f4 --- /dev/null +++ b/应用/Delivery.Plugin/WindowsForm.cs @@ -0,0 +1,258 @@ +using Api.Framework; +using Api.Framework.Tools; +using Delivery.Plugin.Model; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Delivery.Plugin +{ + public partial class WindowsForm : BaseForm + { + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + public WindowsForm() + { + InitializeComponent(); + } + + private void 增加学校ToolStripMenuItem_Click(object sender, EventArgs e) + { + new InsertGroup(null).ShowDialog(); + simpleButton1_Click(null,null); + } + + private void 修改属性ToolStripMenuItem_Click(object sender, EventArgs e) + { + + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + //this.pageControl1.GotoPage(1); + } + + private void 删除学校ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rst = MessageBox.Show("您确定要删除吗?","友情提示",MessageBoxButtons.YesNo,MessageBoxIcon.Question); + if (rst == DialogResult.Yes) + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var row = this.gridView1.GetRow(rows[0]) as fl_plugin_delivery_group; + var session = ApiClient.GetSession(); + session.Ado.ExecuteCommand("DELETE FROM fl_plugin_delivery_group WHERE ID=" + row.id); + simpleButton1_Click(null, null); + } + } + + } + catch (Exception) + { + + } + } + private void ShowList() + { + try + { + this.settingControl1.Bind(Class1.config); + var session = ApiClient.GetSession(); + List list = null; + //总记录数 + + if (!string.IsNullOrEmpty(this.textBox1.Text)) + { + list = session.Queryable().Where(f => f.name.Contains(this.textBox1.Text) || f.weixinhao.Contains(this.textBox1.Text)).ToList(); + } + else + { + list = session.Queryable().ToList(); + } + + this.gridControl1.DataSource = list; + + + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + private string serch_mdm_keword = string.Empty; + private int serch_mdm_type = 0; + private void WindowsForm_Load(object sender, EventArgs e) + { + ShowList(); + + this.pageControl1.Bind(delegate (int index, int size) + { + try + { + var session = ApiClient.GetSession(); + var count = 0; + List list = null; + if (!string.IsNullOrEmpty(serch_mdm_keword)) + { + switch (serch_mdm_type) + { + case 1: + list = session.Queryable().Where(f=>f.userid == int.Parse(serch_mdm_keword)).OrderBy(f => f.id, SqlSugar.OrderByType.Desc).ToPageList(index, size, ref count); + break; + case 2: + list = session.Queryable().Where(f => f.order_code == serch_mdm_keword).OrderBy(f => f.id, SqlSugar.OrderByType.Desc).ToPageList(index, size, ref count); + break; + default: + break; + } + }else list = session.Queryable().OrderBy(f=>f.id, SqlSugar.OrderByType.Desc).ToPageList(index, size, ref count); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = list,Total = count}; + } + catch (Exception) + { + } + return null; + + }, this.gridControl2, 50); + + + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + group = null; + this.textBox4.Text = this.textBox2.Text = this.textBox3.Text = this.textBox5.Text = string.Empty; + } + fl_plugin_delivery_group group = null; + private void gridView1_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + group = this.gridView1.GetRow(rows[0]) as fl_plugin_delivery_group; + this.textBox4.Text = group.name; + this.textBox2.Text = group.position; + this.textBox3.Text = group.weixinhao; + this.textBox5.Text = group.admins; + } + else + { + simpleButton2_Click(null,null); + } + } + catch (Exception) + { + + } + } + + private void simpleButton1_Click_1(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(this.textBox4.Text)) throw new Exception("不能为空名称!"); + var session = ApiClient.GetSession(); + if (group == null) + { + group = session.Queryable().Where(f => f.name == this.textBox4.Text).Single(); + if (group != null) throw new Exception("此名称已经存在!"); + group = new fl_plugin_delivery_group() { name = this.textBox4.Text }; + } + + group.name = this.textBox4.Text; + group.position = this.textBox2.Text; + group.weixinhao = this.textBox3.Text; + group.admins = this.textBox5.Text; + session.Saveable(group).ExecuteReturnEntity(); + Class1.GetGroups(true); + BaseForm.ShowSuccess("设置成功!"); + ShowList(); + //this.Close(); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + gridView1_RowClick(null,null); + + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + group = null; + simpleButton1_Click_1(null,null); + ShowList(); + Class1.GetGroups(true); + } + + private void WindowsForm_FormClosing(object sender, FormClosingEventArgs e) + { + Util.Save(Class1.config); + } + + private void 增加免单码ToolStripMenuItem_Click(object sender, EventArgs e) + { + new InsertQCode().ShowDialog(); + } + + private void 刷新免单码ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.serch_mdm_keword = string.Empty; + this.pageControl1.GotoPage(1); + } + + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + var f = new InputKeywordForm(); + f.ShowDialog(); + this.serch_mdm_keword = f.Code; + this.serch_mdm_type = 1; + this.pageControl1.GotoPage(1); + } + + private void 通过免单码搜索ToolStripMenuItem_Click(object sender, EventArgs e) + { + var f = new InputKeywordForm(); + f.ShowDialog(); + this.serch_mdm_keword = f.Code; + this.serch_mdm_type = 2; + this.pageControl1.GotoPage(1); + } + } +} diff --git a/应用/Delivery.Plugin/WindowsForm.resx b/应用/Delivery.Plugin/WindowsForm.resx new file mode 100644 index 0000000..24d3d12 --- /dev/null +++ b/应用/Delivery.Plugin/WindowsForm.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 274, 17 + + \ No newline at end of file diff --git a/应用/Delivery.Plugin/会员数据操作.Designer.cs b/应用/Delivery.Plugin/会员数据操作.Designer.cs new file mode 100644 index 0000000..315fb07 --- /dev/null +++ b/应用/Delivery.Plugin/会员数据操作.Designer.cs @@ -0,0 +1,677 @@ +namespace Delivery.Plugin +{ + partial class 会员数据操作 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.tabPane1 = new DevExpress.XtraBars.Navigation.TabPane(); + this.tabNavigationPage1 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.新增学校ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改学校ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.清空绑定ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新列表ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除学校ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.tabNavigationPage2 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加免单码ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.刷新列表ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.tabNavigationPage3 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.label1 = new System.Windows.Forms.Label(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.gridControl4 = new DevExpress.XtraGrid.GridControl(); + this.gridView4 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip3 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改配置ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除订单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.编辑快递点ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).BeginInit(); + this.tabPane1.SuspendLayout(); + this.tabNavigationPage1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.tabNavigationPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.tabNavigationPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + this.contextMenuStrip3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + this.SuspendLayout(); + // + // tabPane1 + // + this.tabPane1.AllowCollapse = DevExpress.Utils.DefaultBoolean.Default; + this.tabPane1.Controls.Add(this.tabNavigationPage1); + this.tabPane1.Controls.Add(this.tabNavigationPage2); + this.tabPane1.Controls.Add(this.tabNavigationPage3); + this.tabPane1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabPane1.Location = new System.Drawing.Point(0, 0); + this.tabPane1.Name = "tabPane1"; + this.tabPane1.Pages.AddRange(new DevExpress.XtraBars.Navigation.NavigationPageBase[] { + this.tabNavigationPage1, + this.tabNavigationPage2, + this.tabNavigationPage3}); + this.tabPane1.RegularSize = new System.Drawing.Size(913, 586); + this.tabPane1.SelectedPage = this.tabNavigationPage2; + this.tabPane1.Size = new System.Drawing.Size(913, 586); + this.tabPane1.TabIndex = 0; + this.tabPane1.Text = "tabPane1"; + // + // tabNavigationPage1 + // + this.tabNavigationPage1.Caption = "大学管理"; + this.tabNavigationPage1.Controls.Add(this.groupBox2); + this.tabNavigationPage1.Controls.Add(this.groupBox1); + this.tabNavigationPage1.Name = "tabNavigationPage1"; + this.tabNavigationPage1.Size = new System.Drawing.Size(913, 558); + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.gridControl1); + this.groupBox2.Location = new System.Drawing.Point(3, 5); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(326, 548); + this.groupBox2.TabIndex = 6; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "学校汇总"; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(3, 18); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(320, 527); + this.gridControl1.TabIndex = 6; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.新增学校ToolStripMenuItem, + this.修改学校ToolStripMenuItem, + this.编辑快递点ToolStripMenuItem, + this.清空绑定ToolStripMenuItem, + this.刷新列表ToolStripMenuItem, + this.删除学校ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(181, 158); + // + // 新增学校ToolStripMenuItem + // + this.新增学校ToolStripMenuItem.Name = "新增学校ToolStripMenuItem"; + this.新增学校ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.新增学校ToolStripMenuItem.Text = "新增学校"; + this.新增学校ToolStripMenuItem.Click += new System.EventHandler(this.新增学校ToolStripMenuItem_Click_1); + // + // 修改学校ToolStripMenuItem + // + this.修改学校ToolStripMenuItem.Name = "修改学校ToolStripMenuItem"; + this.修改学校ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.修改学校ToolStripMenuItem.Text = "修改学校"; + this.修改学校ToolStripMenuItem.Click += new System.EventHandler(this.修改学校ToolStripMenuItem_Click); + // + // 清空绑定ToolStripMenuItem + // + this.清空绑定ToolStripMenuItem.Name = "清空绑定ToolStripMenuItem"; + this.清空绑定ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.清空绑定ToolStripMenuItem.Text = "清空绑定"; + this.清空绑定ToolStripMenuItem.Click += new System.EventHandler(this.清空绑定ToolStripMenuItem_Click); + // + // 刷新列表ToolStripMenuItem + // + this.刷新列表ToolStripMenuItem.Name = "刷新列表ToolStripMenuItem"; + this.刷新列表ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.刷新列表ToolStripMenuItem.Text = "刷新列表"; + this.刷新列表ToolStripMenuItem.Click += new System.EventHandler(this.刷新列表ToolStripMenuItem_Click); + // + // 删除学校ToolStripMenuItem + // + this.删除学校ToolStripMenuItem.Name = "删除学校ToolStripMenuItem"; + this.删除学校ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除学校ToolStripMenuItem.Text = "删除学校"; + this.删除学校ToolStripMenuItem.Click += new System.EventHandler(this.删除学校ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsSelection.ResetSelectionClickOutsideCheckboxSelector = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView1_RowClick); + // + // gridColumn1 + // + this.gridColumn1.Caption = "学校全名"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 188; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.settingControl1); + this.groupBox1.Location = new System.Drawing.Point(332, 5); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(572, 548); + this.groupBox1.TabIndex = 5; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "属性编辑"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(242, 511); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(107, 31); + this.simpleButton1.TabIndex = 1; + this.simpleButton1.Text = "保存"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.settingControl1.Location = new System.Drawing.Point(3, 18); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(566, 487); + this.settingControl1.TabIndex = 0; + // + // tabNavigationPage2 + // + this.tabNavigationPage2.Caption = "免单码管理"; + this.tabNavigationPage2.Controls.Add(this.pageControl1); + this.tabNavigationPage2.Controls.Add(this.gridControl2); + this.tabNavigationPage2.Name = "tabNavigationPage2"; + this.tabNavigationPage2.Size = new System.Drawing.Size(913, 558); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 522); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(913, 36); + this.pageControl1.TabIndex = 1; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl2.Location = new System.Drawing.Point(3, 3); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(907, 513); + this.gridControl2.TabIndex = 0; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加免单码ToolStripMenuItem, + this.刷新列表ToolStripMenuItem1}); + this.contextMenuStrip2.Name = "contextMenuStrip2"; + this.contextMenuStrip2.Size = new System.Drawing.Size(125, 48); + // + // 增加免单码ToolStripMenuItem + // + this.增加免单码ToolStripMenuItem.Name = "增加免单码ToolStripMenuItem"; + this.增加免单码ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.增加免单码ToolStripMenuItem.Text = "增免单码"; + this.增加免单码ToolStripMenuItem.Click += new System.EventHandler(this.增加免单码ToolStripMenuItem_Click); + // + // 刷新列表ToolStripMenuItem1 + // + this.刷新列表ToolStripMenuItem1.Name = "刷新列表ToolStripMenuItem1"; + this.刷新列表ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.刷新列表ToolStripMenuItem1.Text = "刷新列表"; + this.刷新列表ToolStripMenuItem1.Click += new System.EventHandler(this.刷新列表ToolStripMenuItem1_Click); + // + // gridView2 + // + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn3, + this.gridColumn4, + this.gridColumn5, + this.gridColumn6, + this.gridColumn7, + this.gridColumn8, + this.gridColumn9}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn3 + // + this.gridColumn3.Caption = "免单码"; + this.gridColumn3.FieldName = "m_code"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.ReadOnly = true; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 0; + this.gridColumn3.Width = 94; + // + // gridColumn4 + // + this.gridColumn4.Caption = "用户账号"; + this.gridColumn4.FieldName = "username"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.ReadOnly = true; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 151; + // + // gridColumn5 + // + this.gridColumn5.Caption = "用户昵称"; + this.gridColumn5.FieldName = "usernick"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.ReadOnly = true; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 128; + // + // gridColumn6 + // + this.gridColumn6.Caption = "有效性"; + this.gridColumn6.FieldName = "status"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.ReadOnly = true; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 3; + this.gridColumn6.Width = 128; + // + // gridColumn7 + // + this.gridColumn7.Caption = "订单时间"; + this.gridColumn7.FieldName = "crt_time"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.ReadOnly = true; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 4; + this.gridColumn7.Width = 128; + // + // gridColumn8 + // + this.gridColumn8.Caption = "使用人编号"; + this.gridColumn8.FieldName = "usingid"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.ReadOnly = true; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 5; + this.gridColumn8.Width = 128; + // + // gridColumn9 + // + this.gridColumn9.Caption = "关联订单ID"; + this.gridColumn9.FieldName = "orderid"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.ReadOnly = true; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 6; + this.gridColumn9.Width = 132; + // + // tabNavigationPage3 + // + this.tabNavigationPage3.Caption = "取件数据管理"; + this.tabNavigationPage3.Controls.Add(this.simpleButton2); + this.tabNavigationPage3.Controls.Add(this.label1); + this.tabNavigationPage3.Controls.Add(this.dateTimePicker1); + this.tabNavigationPage3.Controls.Add(this.gridControl4); + this.tabNavigationPage3.Controls.Add(this.pageControl2); + this.tabNavigationPage3.Controls.Add(this.gridControl3); + this.tabNavigationPage3.Name = "tabNavigationPage3"; + this.tabNavigationPage3.Size = new System.Drawing.Size(913, 558); + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(716, 11); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(75, 23); + this.simpleButton2.TabIndex = 10; + this.simpleButton2.Text = "搜索"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(234, 15); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(0, 14); + this.label1.TabIndex = 9; + // + // dateTimePicker1 + // + this.dateTimePicker1.Location = new System.Drawing.Point(507, 12); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(181, 22); + this.dateTimePicker1.TabIndex = 8; + // + // gridControl4 + // + this.gridControl4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.gridControl4.Location = new System.Drawing.Point(8, 11); + this.gridControl4.MainView = this.gridView4; + this.gridControl4.Name = "gridControl4"; + this.gridControl4.Size = new System.Drawing.Size(220, 508); + this.gridControl4.TabIndex = 7; + this.gridControl4.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView4}); + // + // gridView4 + // + this.gridView4.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10}); + this.gridView4.GridControl = this.gridControl4; + this.gridView4.Name = "gridView4"; + this.gridView4.OptionsBehavior.ReadOnly = true; + this.gridView4.OptionsSelection.ResetSelectionClickOutsideCheckboxSelector = true; + this.gridView4.OptionsView.ShowGroupPanel = false; + this.gridView4.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView4_RowClick); + this.gridView4.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView4_RowCellClick); + // + // gridColumn10 + // + this.gridColumn10.Caption = "学校全名"; + this.gridColumn10.FieldName = "name"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.ReadOnly = true; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 188; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 522); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(913, 36); + this.pageControl2.TabIndex = 1; + // + // gridControl3 + // + this.gridControl3.ContextMenuStrip = this.contextMenuStrip3; + this.gridControl3.Location = new System.Drawing.Point(234, 45); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.Size = new System.Drawing.Size(667, 474); + this.gridControl3.TabIndex = 0; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // contextMenuStrip3 + // + this.contextMenuStrip3.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改配置ToolStripMenuItem, + this.删除订单ToolStripMenuItem}); + this.contextMenuStrip3.Name = "contextMenuStrip3"; + this.contextMenuStrip3.Size = new System.Drawing.Size(125, 48); + // + // 修改配置ToolStripMenuItem + // + this.修改配置ToolStripMenuItem.Name = "修改配置ToolStripMenuItem"; + this.修改配置ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.修改配置ToolStripMenuItem.Text = "修改属性"; + this.修改配置ToolStripMenuItem.Click += new System.EventHandler(this.修改配置ToolStripMenuItem_Click); + // + // 删除订单ToolStripMenuItem + // + this.删除订单ToolStripMenuItem.Name = "删除订单ToolStripMenuItem"; + this.删除订单ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.删除订单ToolStripMenuItem.Text = "删除订单"; + this.删除订单ToolStripMenuItem.Click += new System.EventHandler(this.删除订单ToolStripMenuItem_Click); + // + // gridView3 + // + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn16, + this.gridColumn15, + this.gridColumn17, + this.gridColumn18}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsView.ShowGroupPanel = false; + // + // gridColumn11 + // + this.gridColumn11.Caption = "姓名"; + this.gridColumn11.FieldName = "real_name"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + // + // gridColumn12 + // + this.gridColumn12.Caption = "手机号"; + this.gridColumn12.FieldName = "real_telnumber"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + // + // gridColumn13 + // + this.gridColumn13.Caption = "取件码"; + this.gridColumn13.FieldName = "q_code"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 2; + // + // gridColumn14 + // + this.gridColumn14.Caption = "取件位置"; + this.gridColumn14.FieldName = "q_location"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + // + // gridColumn16 + // + this.gridColumn16.Caption = "时间"; + this.gridColumn16.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn16.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn16.FieldName = "crt_time"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 5; + // + // gridColumn15 + // + this.gridColumn15.Caption = "送往目的"; + this.gridColumn15.FieldName = "s_location"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 4; + // + // gridColumn17 + // + this.gridColumn17.Caption = "用户编号"; + this.gridColumn17.FieldName = "userid"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 6; + // + // gridColumn18 + // + this.gridColumn18.Caption = "是否送达"; + this.gridColumn18.FieldName = "is_arrive"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 7; + // + // gridColumn2 + // + this.gridColumn2.Caption = "负责人"; + this.gridColumn2.Name = "gridColumn2"; + // + // 编辑快递点ToolStripMenuItem + // + this.编辑快递点ToolStripMenuItem.Name = "编辑快递点ToolStripMenuItem"; + this.编辑快递点ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.编辑快递点ToolStripMenuItem.Text = "编辑快递点"; + this.编辑快递点ToolStripMenuItem.Click += new System.EventHandler(this.编辑快递点ToolStripMenuItem_Click); + // + // 会员数据操作 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(913, 586); + this.Controls.Add(this.tabPane1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "会员数据操作"; + this.Text = "会员数据操作"; + this.Load += new System.EventHandler(this.会员数据操作_Load); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).EndInit(); + this.tabPane1.ResumeLayout(false); + this.tabNavigationPage1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.tabNavigationPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.tabNavigationPage3.ResumeLayout(false); + this.tabNavigationPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + this.contextMenuStrip3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraBars.Navigation.TabPane tabPane1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage2; + private System.Windows.Forms.GroupBox groupBox2; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private System.Windows.Forms.GroupBox groupBox1; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 新增学校ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改学校ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 清空绑定ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 刷新列表ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除学校ToolStripMenuItem; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem 刷新列表ToolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem 增加免单码ToolStripMenuItem; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.GridControl gridControl4; + private DevExpress.XtraGrid.Views.Grid.GridView gridView4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip3; + private System.Windows.Forms.ToolStripMenuItem 修改配置ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private System.Windows.Forms.ToolStripMenuItem 删除订单ToolStripMenuItem; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private System.Windows.Forms.Label label1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private System.Windows.Forms.ToolStripMenuItem 编辑快递点ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/应用/Delivery.Plugin/会员数据操作.cs b/应用/Delivery.Plugin/会员数据操作.cs new file mode 100644 index 0000000..1742f80 --- /dev/null +++ b/应用/Delivery.Plugin/会员数据操作.cs @@ -0,0 +1,330 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using Delivery.Plugin.Model; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Delivery.Plugin +{ + public partial class 会员数据操作 : BaseForm + { + public 会员数据操作() + { + InitializeComponent(); + ShowList(); + this.tabPane1.SelectedPageIndex = 0; + } + + private void ShowList() + { + try + { + + var session = ApiClient.GetSession(); + List list = null; + //总记录数 + + list = Class1.GetGroups(true); + + this.gridControl1.DataSource = list; + this.gridControl4.DataSource = list; + + + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + + } + + private void 新增学校ToolStripMenuItem_Click(object sender, EventArgs e) + { + + } + + private void 修改学校ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var group = this.gridView1.GetRow(rows[0]) as fl_plugin_delivery_group; + this.settingControl1.Bind(group); + } + else + { + this.settingControl1.Bind(new object()); + } + } + catch (Exception) + { + } + } + + private void 清空绑定ToolStripMenuItem_Click(object sender, EventArgs e) + { + this.settingControl1.Bind(new object()); + } + + private void 新增学校ToolStripMenuItem_Click_1(object sender, EventArgs e) + { + this.settingControl1.Bind(new fl_plugin_delivery_group()); + } + + private void 刷新列表ToolStripMenuItem_Click(object sender, EventArgs e) + { + ShowList(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var group = this.settingControl1.PropertyControl.SelectedObject as fl_plugin_delivery_group; + if (group == null || group.GetType() != typeof(fl_plugin_delivery_group)) throw new Exception("保存失败,没有对象!"); + var session = ApiClient.GetSession(); + if (group.id == 0) + { + session.Insertable(group).ExecuteCommand(); + ShowList(); + } + else session.Updateable(group).ExecuteCommand(); + + BaseForm.ShowSuccess("保存成功!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void 删除学校ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var group = this.settingControl1.PropertyControl.SelectedObject as fl_plugin_delivery_group; + if (group == null || group.GetType() != typeof(fl_plugin_delivery_group)) throw new Exception("保存失败,没有对象!"); + var msg = MessageBox.Show($"您确定要删除{group.name}吗?","是否删除,删除后不可找回",MessageBoxButtons.YesNo,MessageBoxIcon.Question); + if (msg != DialogResult.Yes) return; + var session = ApiClient.GetSession(); + if (group.id != 0) + { + session.Deleteable(group).ExecuteCommand(); + } + ShowList(); + BaseForm.ShowSuccess("删除成功!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + public class temp_mcode_entity + { + public long id { get; set; } + public string username { get; set; } + public string usernick { get; set; } + public long userid { get; set; } + public string m_code { get; set; } + public long usingid { get; set; } + public long orderid { get; set; } + public bool status { get; set; } + public CpsType order_type { get; set; } + public DateTime crt_time { get; set; } + + } + private void 刷新列表ToolStripMenuItem1_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void 会员数据操作_Load(object sender, EventArgs e) + { + try + { + this.pageControl1.Bind(delegate(int index,int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var list = session.SqlQueryable($"select h.order_code m_code, h.id id,m.username username,m.usernick usernick,h.using_userid usingid,h.ordertable_type order_type,h.ordertable_id orderid,h.effective status,h.ordertable_cratetime crt_time from fl_plugin_delivery_hist h,fl_member_info m where h.userid=m.id order by h.id desc limit {(index-1) * pagesize},{pagesize}").ToList(); + var row = session.FindRow("select count(id) count from fl_plugin_delivery_hist", null); + var count = int.Parse(row[0].ToString()); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = list, Total = count }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + },this.gridControl2, 30,true); + + + this.pageControl2.Bind(delegate(int index,int pagesize) { + try + { + if (grid3_group == null) return null; + var session = ApiClient.GetSession(); + int toal = 0; + var str = DateTime.Parse(dateTimePicker1.Value.ToString("yyyy-MM-dd 00:00:00")); + var end = DateTime.Parse(dateTimePicker1.Value.ToString("yyyy-MM-dd 00:00:00")).AddDays(1); + var rst = session.Queryable().Where(f => f.groupid == grid3_group.id && f.crt_time>=str&& f.crt_time< end).OrderBy(f => f.crt_time, SqlSugar.OrderByType.Desc).ToPageList(index, pagesize, ref toal); + return new UI.Framework.Controls.PageControl.SerchResult() { Total = toal, Result = rst }; + } + catch (Exception ex) { } + return null; + },this.gridControl3,100,false); + } + + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void 增加免单码ToolStripMenuItem_Click(object sender, EventArgs e) + { + new InsertQCode().ShowDialog(); + this.pageControl1.GotoPage(1); + + } + private fl_plugin_delivery_group grid3_group; + private void gridView4_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + + this.gridControl3.DataSource = null; + var rows = this.gridView4.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + grid3_group = this.gridView4.GetRow(rows[0]) as fl_plugin_delivery_group; + this.pageControl2.GotoPage(1); + } + } + catch (Exception ) + { + + } + } + + private void gridView4_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + try + { + + this.gridControl3.DataSource = null; + var rows = this.gridView4.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + grid3_group = this.gridView4.GetRow(rows[0]) as fl_plugin_delivery_group; + label1.Text = grid3_group.name; + this.pageControl2.GotoPage(1); + } + else + { + grid3_group = null; + label1.Text = string.Empty; + } + } + catch (Exception) + { + + } + } + + private void 修改配置ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView3.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var info = this.gridView3.GetRow(rows[0]) as fl_plugin_delivery_item; + new SettingForm(info).ShowDialog(); + var session = ApiClient.GetSession(); + session.Updateable(info).ExecuteCommand(); + } + } + catch (Exception) + { + + } + } + + private void 删除订单ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView3.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var info = this.gridView3.GetRow(rows[0]) as fl_plugin_delivery_item; + var input = new InputKeywordForm(); + input.ShowDialog(); + if (!string.IsNullOrEmpty(input.Code)) + { + var session = ApiClient.GetSession(); + session.Deleteable(info).ExecuteCommand(); + this.gridView3.DeleteRow(rows[0]); + var member = session.FindMemberInfoById(info.userid); + if (member == null) return; + var robot = session.FindRobotInfo(member.robot_name,member.robot_type); + if (robot == null) return; + ApiClient.SendMessage(robot,member.username, $"一一一一代 取 失 败一一一一\r\n取件码:{info.q_code}\r\n免单码:{info.m_code}\r\n备注说明:{input.Code}"); + } + + } + } + catch (Exception) { } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.pageControl2.GotoPage(1); + } + + private void gridView1_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + 修改学校ToolStripMenuItem_Click(null,null); + } + + private void 编辑快递点ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + //获取选中数据 + var group = this.gridView1.GetRow(rows[0]) as fl_plugin_delivery_group; + new KuaidiForm(group).ShowDialog(); + group.GetPositions(true); + } + + } + catch (Exception) + { + } + } + } +} diff --git a/应用/Delivery.Plugin/会员数据操作.resx b/应用/Delivery.Plugin/会员数据操作.resx new file mode 100644 index 0000000..1bba79f --- /dev/null +++ b/应用/Delivery.Plugin/会员数据操作.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 274, 17 + + + 439, 17 + + \ No newline at end of file diff --git a/应用/DevPlugin/Class1.cs b/应用/DevPlugin/Class1.cs new file mode 100644 index 0000000..fc75337 --- /dev/null +++ b/应用/DevPlugin/Class1.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DevPlugin +{ + public class Class1 + { + } +} diff --git a/应用/DevPlugin/DevPlugin.csproj b/应用/DevPlugin/DevPlugin.csproj new file mode 100644 index 0000000..932cfd3 --- /dev/null +++ b/应用/DevPlugin/DevPlugin.csproj @@ -0,0 +1,53 @@ + + + + + Debug + AnyCPU + 64544f18-db01-42c6-a948-034ef0c02354 + Library + Properties + DevPlugin + DevPlugin + v4.6.1 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/应用/DevPlugin/Properties/AssemblyInfo.cs b/应用/DevPlugin/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2357472 --- /dev/null +++ b/应用/DevPlugin/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("DevPlugin")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DevPlugin")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("64544f18-db01-42c6-a948-034ef0c02354")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/EncourageUser/Class1.cs b/应用/EncourageUser/Class1.cs new file mode 100644 index 0000000..5787c46 --- /dev/null +++ b/应用/EncourageUser/Class1.cs @@ -0,0 +1,101 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using EncourageUser.Entitys; +using EncourageUser.Properties; +using SqlSugar; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EncourageUser +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.群发; + } + + #region 自定义变量 + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("note"); + + session.Insertable(new fl_plugin_encourage_user_messs() { note = "测试", mess = "本条为测试消息" }).ExecuteCommand(); + } + + if (!session.TableExist()) + { + session.CreateTable(); + } + + if (!session.TableExist()) + { + session.CreateTable(); + session.AddIndex("taskid", "issend", "sendtime"); + } + #endregion + + var thread = TimerTask.NewTimer(30) as TaskJob; //创建线程 - 监听好友朋友圈和接口的线程 1秒 + + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + + TaskJob.AbortAll(); + TimerTask.Close(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } + +} diff --git a/应用/EncourageUser/Common.cs b/应用/EncourageUser/Common.cs new file mode 100644 index 0000000..1e8f7d6 --- /dev/null +++ b/应用/EncourageUser/Common.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; + +namespace EncourageUser +{ + public class Common + { + /// + /// 缓存是否存在 + /// + /// + /// + /// + /// + public static bool GetCache(string text) + { + try + { + Cache cache = HttpRuntime.Cache; + object item = cache[text]; + return item != null ? true : false; + } + catch (Exception) + { } + return false; + } + + /// + /// 设置缓存(辅助输入) + /// + /// + /// + /// + /// + public static bool SetCache(string text) + { + try + { + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[text]; + if (item == null) + cache.Insert(text, 1, null, DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + } +} diff --git a/应用/EncourageUser/EncourageUser.csproj b/应用/EncourageUser/EncourageUser.csproj new file mode 100644 index 0000000..eb2cea8 --- /dev/null +++ b/应用/EncourageUser/EncourageUser.csproj @@ -0,0 +1,141 @@ + + + + + Debug + AnyCPU + {44593BAC-0617-483E-9AD7-BEF4336E14D7} + Library + Properties + EncourageUser + EncourageUser + v4.6.1 + 512 + true + + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + + False + ..\..\PCRobot\DLL\Newtonsoft.Json.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + Form + + + TaskForm.cs + + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + TaskForm.cs + + + + + + + + + + \ No newline at end of file diff --git a/应用/EncourageUser/Entitys/Enums.cs b/应用/EncourageUser/Entitys/Enums.cs new file mode 100644 index 0000000..d975891 --- /dev/null +++ b/应用/EncourageUser/Entitys/Enums.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EncourageUser.Entitys +{ + public enum UserType + { + 新用户未查询过 = 0, + 新用户查询后未下单 = 1, + 长时间未购买的老客户 = 2, + 用户分组 = 3, + 所有用户 = 4, + 已下单用户 = 5, + } + + public enum ExecType + { + 执行失效 = 0, + 未执行完毕 = 1, + 执行完毕 = 2 + } +} diff --git a/应用/EncourageUser/Entitys/SendState.cs b/应用/EncourageUser/Entitys/SendState.cs new file mode 100644 index 0000000..2ce6f36 --- /dev/null +++ b/应用/EncourageUser/Entitys/SendState.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EncourageUser.Entitys +{ + public class SendState + { + /// + /// 是否完成 + /// + public bool IsFinish { get; set; } + /// + /// 发送次数 + /// + public int Num { get; set; } + /// + /// 发送的时间 + /// + public long Time { get; set; } + + } + + +} diff --git a/应用/EncourageUser/Entitys/fl_plugin_encourage___tasks.cs b/应用/EncourageUser/Entitys/fl_plugin_encourage___tasks.cs new file mode 100644 index 0000000..884c6cf --- /dev/null +++ b/应用/EncourageUser/Entitys/fl_plugin_encourage___tasks.cs @@ -0,0 +1,73 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EncourageUser.Entitys +{ + public class fl_plugin_encourage___tasks : base_model + { + /// + /// 发送消息id + /// + public long messId { get; set; } + + /// + /// 开始时间 + /// + /// + public DateTime startTime { get; set; } + + /// + /// 结束时间 + /// + public DateTime endTime { get; set; } + + /// + /// 发送间隔 + /// + public int interval { get; set; } + + /// + /// 总发送量 + /// + public int totalSentCount { get; set; } + + /// + /// 发送多少数量休息 + /// + public int restSendCount { get; set; } + + /// + /// 休息间隔 + /// + public int restInterval { get; set; } + + /// + /// 需要发送的用户 + /// + [SugarColumn(ColumnDataType = "text")] + public string sendWaitDic { get; set; } + + /// + /// 已经发送用户 + /// + [SugarColumn(ColumnDataType = "text")] + public string sendFinishDic { get; set; } + + /// + /// 执行 + /// + [SugarColumn(ColumnDataType = "text")] + public string sendStateDic { get; set; } + + /// + /// 发送状态 + /// + public ExecType execType { get; set; } = ExecType.未执行完毕; + + } +} diff --git a/应用/EncourageUser/Entitys/fl_plugin_encourage_user__tasks.cs b/应用/EncourageUser/Entitys/fl_plugin_encourage_user__tasks.cs new file mode 100644 index 0000000..75c299f --- /dev/null +++ b/应用/EncourageUser/Entitys/fl_plugin_encourage_user__tasks.cs @@ -0,0 +1,73 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EncourageUser.Entitys +{ + public class fl_plugin_encourage_user__tasks : base_model + { + /// + /// 发送消息id + /// + public long messId { get; set; } + + /// + /// 开始时间 + /// + /// + public DateTime startTime { get; set; } + + /// + /// 结束时间 + /// + public DateTime endTime { get; set; } + + /// + /// 发送间隔 + /// + public int interval { get; set; } + + /// + /// 总发送量 + /// + public int totalSentCount { get; set; } + + /// + /// 发送多少数量休息 + /// + public int restSendCount { get; set; } + + /// + /// 休息间隔 + /// + public int restInterval { get; set; } + + /// + /// 需要发送的用户 + /// + [SugarColumn(ColumnDataType = "text")] + public string sendWaitDic { get; set; } + + /// + /// 已经发送用户 + /// + [SugarColumn(ColumnDataType = "text")] + public string sendFinishDic { get; set; } + + /// + /// 执行 + /// + [SugarColumn(ColumnDataType = "text")] + public string sendStateDic { get; set; } + + /// + /// 发送状态 + /// + public ExecType execType { get; set; } = ExecType.未执行完毕; + + } +} diff --git a/应用/EncourageUser/Entitys/fl_plugin_encourage_user_messs.cs b/应用/EncourageUser/Entitys/fl_plugin_encourage_user_messs.cs new file mode 100644 index 0000000..4344655 --- /dev/null +++ b/应用/EncourageUser/Entitys/fl_plugin_encourage_user_messs.cs @@ -0,0 +1,31 @@ +using Api.Framework.Tools; +using Microsoft.JScript; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EncourageUser.Entitys +{ + public class fl_plugin_encourage_user_messs : base_model + { + /// + /// 说明 + /// + public string note { get; set; } + + private string _mess; + /// + /// 发送的正文 + /// + [SugarColumn(ColumnDataType = "text")] + public string mess + { + get { return GlobalObject.unescape(_mess); } + set { _mess = GlobalObject.escape(value); } + } + + } +} diff --git a/应用/EncourageUser/Entitys/fl_qunfa_task.cs b/应用/EncourageUser/Entitys/fl_qunfa_task.cs new file mode 100644 index 0000000..12917c5 --- /dev/null +++ b/应用/EncourageUser/Entitys/fl_qunfa_task.cs @@ -0,0 +1,71 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EncourageUser.Entitys +{ + /// + /// 发送任务 + /// + public class fl_qunfa_task : base_model + { + /// + /// 发送文案模板 + /// + public long messid { get; set; } + + /// + /// 开始时间 + /// + /// + public DateTime startTime { get; set; } + + /// + /// 结束时间 + /// + public DateTime endTime { get; set; } + + /// + /// 发送间隔 + /// + public int interval { get; set; } + + /// + /// 总发送量 + /// + public int totalSentCount { get; set; } + + /// + /// 发送多少数量休息 + /// + public int restSendCount { get; set; } + + /// + /// 休息间隔 + /// + public int restInterval { get; set; } + + /// + /// 已经发送数量 + /// + public int sendnum { get; set; } + + /// + /// 未发送数量 + /// + public int unsendnum { get; set; } + + /// + /// 总发送数量 + /// + public int allsendnum { get; set; } + + /// + /// 发送状态 + /// + public ExecType execType { get; set; } = ExecType.未执行完毕; + } +} diff --git a/应用/EncourageUser/Entitys/fl_qunfa_user.cs b/应用/EncourageUser/Entitys/fl_qunfa_user.cs new file mode 100644 index 0000000..3374ec6 --- /dev/null +++ b/应用/EncourageUser/Entitys/fl_qunfa_user.cs @@ -0,0 +1,51 @@ +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EncourageUser.Entitys +{ + /// + /// 发送用户 + /// + public class fl_qunfa_user : base_model + { + /// + /// 任务id + /// + public long taskid { get; set; } + + /// + /// 用户id + /// + public long userid { get; set; } + + /// + /// 用户账号 + /// + public string username { get; set; } + + /// + /// 机器人类型 + /// + public ChatType chattype { get; set; } + + /// + /// 机器人账号 + /// + public string robotname { get; set; } + + /// + /// 发送状态 + /// + public bool issend { get; set; } = false; + + /// + /// 发送时间戳 + /// + public int sendtime { get; set; } + } +} diff --git a/应用/EncourageUser/MainForm.Designer.cs b/应用/EncourageUser/MainForm.Designer.cs new file mode 100644 index 0000000..c28fd74 --- /dev/null +++ b/应用/EncourageUser/MainForm.Designer.cs @@ -0,0 +1,1108 @@ +namespace EncourageUser +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.全部删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn28 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn29 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton4 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn47 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn48 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn49 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn50 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn51 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn52 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn53 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn54 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn55 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn56 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn57 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn58 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn59 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn60 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn61 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn62 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn63 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn64 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn65 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn66 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn67 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn68 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn69 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.添加任务ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView4 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.label5 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.checkedComboBoxEdit1 = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.simpleButton5 = new DevExpress.XtraEditors.SimpleButton(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).BeginInit(); + this.xtraTabPage1.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.gridControl3); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(916, 587); + this.xtraTabPage3.TabPageWidth = 100; + this.xtraTabPage3.Text = " 任 务 列 表 "; + // + // gridControl3 + // + this.gridControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl3.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl3.Location = new System.Drawing.Point(11, 13); + this.gridControl3.MainView = this.gridView2; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.Size = new System.Drawing.Size(894, 560); + this.gridControl3.TabIndex = 2; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改ToolStripMenuItem, + this.删除ToolStripMenuItem, + this.全部删除ToolStripMenuItem}); + this.contextMenuStrip2.Name = "contextMenuStrip2"; + this.contextMenuStrip2.Size = new System.Drawing.Size(181, 92); + // + // 修改ToolStripMenuItem + // + this.修改ToolStripMenuItem.Name = "修改ToolStripMenuItem"; + this.修改ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.修改ToolStripMenuItem.Text = "修改"; + this.修改ToolStripMenuItem.Click += new System.EventHandler(this.修改ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // 全部删除ToolStripMenuItem + // + this.全部删除ToolStripMenuItem.Name = "全部删除ToolStripMenuItem"; + this.全部删除ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.全部删除ToolStripMenuItem.Text = "全部删除"; + this.全部删除ToolStripMenuItem.Click += new System.EventHandler(this.全部删除ToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView2.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn24, + this.gridColumn27, + this.gridColumn2, + this.gridColumn26, + this.gridColumn25, + this.gridColumn28, + this.gridColumn29, + this.gridColumn5, + this.gridColumn4, + this.gridColumn3, + this.gridColumn1}); + this.gridView2.GridControl = this.gridControl3; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsView.ColumnAutoWidth = false; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn24 + // + this.gridColumn24.Caption = "编号"; + this.gridColumn24.FieldName = "id"; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 0; + this.gridColumn24.Width = 46; + // + // gridColumn27 + // + this.gridColumn27.Caption = "发送时间"; + this.gridColumn27.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn27.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn27.FieldName = "startTime"; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 1; + this.gridColumn27.Width = 111; + // + // gridColumn2 + // + this.gridColumn2.Caption = "结束时间"; + this.gridColumn2.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn2.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn2.FieldName = "endTime"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 117; + // + // gridColumn26 + // + this.gridColumn26.Caption = "当天发送数量"; + this.gridColumn26.FieldName = "totalSentCount"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 3; + this.gridColumn26.Width = 106; + // + // gridColumn25 + // + this.gridColumn25.Caption = "发送间隔"; + this.gridColumn25.FieldName = "interval"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 4; + this.gridColumn25.Width = 93; + // + // gridColumn28 + // + this.gridColumn28.Caption = "发送N条休息"; + this.gridColumn28.FieldName = "restSendCount"; + this.gridColumn28.Name = "gridColumn28"; + this.gridColumn28.Visible = true; + this.gridColumn28.VisibleIndex = 5; + this.gridColumn28.Width = 133; + // + // gridColumn29 + // + this.gridColumn29.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn29.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn29.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.Caption = "休息N秒"; + this.gridColumn29.FieldName = "restInterval"; + this.gridColumn29.Name = "gridColumn29"; + this.gridColumn29.Visible = true; + this.gridColumn29.VisibleIndex = 6; + this.gridColumn29.Width = 120; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "总发送数量"; + this.gridColumn5.FieldName = "allsendnum"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 7; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "未发送数量"; + this.gridColumn4.FieldName = "unsendnum"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 9; + this.gridColumn4.Width = 93; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "已发送数量"; + this.gridColumn3.FieldName = "sendnum"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 10; + this.gridColumn3.Width = 93; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "执行状态"; + this.gridColumn1.FieldName = "execType"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 8; + this.gridColumn1.Width = 142; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.groupControl4); + this.xtraTabPage2.Controls.Add(this.groupControl3); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(916, 587); + this.xtraTabPage2.TabPageWidth = 100; + this.xtraTabPage2.Text = " 消 息 列 表 "; + // + // groupControl4 + // + this.groupControl4.Controls.Add(this.labelControl5); + this.groupControl4.Controls.Add(this.labelControl3); + this.groupControl4.Controls.Add(this.labelControl2); + this.groupControl4.Controls.Add(this.memoEdit1); + this.groupControl4.Controls.Add(this.simpleButton3); + this.groupControl4.Controls.Add(this.simpleButton2); + this.groupControl4.Controls.Add(this.simpleButton4); + this.groupControl4.Controls.Add(this.textEdit4); + this.groupControl4.Controls.Add(this.labelControl4); + this.groupControl4.Location = new System.Drawing.Point(306, 9); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(599, 565); + this.groupControl4.TabIndex = 4; + this.groupControl4.Text = "消息编辑"; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(136, 84); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(106, 14); + this.labelControl5.TabIndex = 13; + this.labelControl5.Text = "(给客户推送的文本)"; + // + // labelControl3 + // + this.labelControl3.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl3.Appearance.Options.UseForeColor = true; + this.labelControl3.Location = new System.Drawing.Point(465, 51); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(34, 14); + this.labelControl3.TabIndex = 12; + this.labelControl3.Text = "(备注)"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(70, 84); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 11; + this.labelControl2.Text = "发送内容:"; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(70, 104); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(490, 363); + this.memoEdit1.TabIndex = 10; + // + // simpleButton3 + // + this.simpleButton3.Enabled = false; + this.simpleButton3.Location = new System.Drawing.Point(399, 486); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(106, 43); + this.simpleButton3.TabIndex = 9; + this.simpleButton3.Text = "删除"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.Enabled = false; + this.simpleButton2.Location = new System.Drawing.Point(245, 486); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(106, 43); + this.simpleButton2.TabIndex = 8; + this.simpleButton2.Text = "修改"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton4 + // + this.simpleButton4.Location = new System.Drawing.Point(99, 486); + this.simpleButton4.Name = "simpleButton4"; + this.simpleButton4.Size = new System.Drawing.Size(106, 43); + this.simpleButton4.TabIndex = 7; + this.simpleButton4.Text = "新增"; + this.simpleButton4.Click += new System.EventHandler(this.simpleButton4_Click); + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(136, 48); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(313, 20); + this.textEdit4.TabIndex = 4; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(70, 51); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(60, 14); + this.labelControl4.TabIndex = 3; + this.labelControl4.Text = "消息别名:"; + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.listView1); + this.groupControl3.Location = new System.Drawing.Point(11, 9); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(289, 565); + this.groupControl3.TabIndex = 3; + this.groupControl3.Text = "消息展示"; + // + // listView1 + // + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HideSelection = false; + this.listView1.Location = new System.Drawing.Point(2, 23); + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(285, 540); + this.listView1.TabIndex = 0; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + this.listView1.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.listView1_ItemSelectionChanged); + // + // columnHeader1 + // + this.columnHeader1.Text = "序号"; + // + // columnHeader2 + // + this.columnHeader2.Text = "消息备注"; + this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader2.Width = 100; + // + // columnHeader3 + // + this.columnHeader3.Text = "消息内容"; + this.columnHeader3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader3.Width = 118; + // + // gridView3 + // + this.gridView3.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView3.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Appearance.Row.Options.UseTextOptions = true; + this.gridView3.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Appearance.SelectedRow.Options.UseTextOptions = true; + this.gridView3.Appearance.SelectedRow.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn47, + this.gridColumn48, + this.gridColumn49, + this.gridColumn50, + this.gridColumn51, + this.gridColumn52, + this.gridColumn53, + this.gridColumn54, + this.gridColumn55, + this.gridColumn56, + this.gridColumn57, + this.gridColumn58, + this.gridColumn59, + this.gridColumn60, + this.gridColumn61, + this.gridColumn62, + this.gridColumn63, + this.gridColumn64, + this.gridColumn65, + this.gridColumn66, + this.gridColumn67, + this.gridColumn68, + this.gridColumn69}); + this.gridView3.GridControl = this.gridControl1; + this.gridView3.IndicatorWidth = 50; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsBehavior.ReadOnly = true; + this.gridView3.OptionsSelection.MultiSelect = true; + this.gridView3.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView3.OptionsView.ColumnAutoWidth = false; + this.gridView3.OptionsView.ShowGroupPanel = false; + this.gridView3.CustomDrawRowIndicator += new DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventHandler(this.gridView3_CustomDrawRowIndicator); + // + // gridColumn47 + // + this.gridColumn47.Caption = "编号"; + this.gridColumn47.FieldName = "id"; + this.gridColumn47.Name = "gridColumn47"; + this.gridColumn47.Visible = true; + this.gridColumn47.VisibleIndex = 1; + this.gridColumn47.Width = 46; + // + // gridColumn48 + // + this.gridColumn48.Caption = "用户类型"; + this.gridColumn48.FieldName = "robot_type"; + this.gridColumn48.Name = "gridColumn48"; + this.gridColumn48.Visible = true; + this.gridColumn48.VisibleIndex = 2; + this.gridColumn48.Width = 80; + // + // gridColumn49 + // + this.gridColumn49.Caption = "用户名"; + this.gridColumn49.FieldName = "username"; + this.gridColumn49.Name = "gridColumn49"; + this.gridColumn49.Visible = true; + this.gridColumn49.VisibleIndex = 3; + this.gridColumn49.Width = 130; + // + // gridColumn50 + // + this.gridColumn50.Caption = "微信号"; + this.gridColumn50.FieldName = "wechatid"; + this.gridColumn50.Name = "gridColumn50"; + this.gridColumn50.Visible = true; + this.gridColumn50.VisibleIndex = 4; + this.gridColumn50.Width = 102; + // + // gridColumn51 + // + this.gridColumn51.Caption = "昵称"; + this.gridColumn51.FieldName = "usernick"; + this.gridColumn51.Name = "gridColumn51"; + this.gridColumn51.Visible = true; + this.gridColumn51.VisibleIndex = 5; + this.gridColumn51.Width = 150; + // + // gridColumn52 + // + this.gridColumn52.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn52.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn52.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn52.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn52.Caption = "备注"; + this.gridColumn52.FieldName = "remark"; + this.gridColumn52.Name = "gridColumn52"; + this.gridColumn52.Visible = true; + this.gridColumn52.VisibleIndex = 6; + this.gridColumn52.Width = 120; + // + // gridColumn53 + // + this.gridColumn53.Caption = "状态"; + this.gridColumn53.FieldName = "status"; + this.gridColumn53.Name = "gridColumn53"; + this.gridColumn53.Visible = true; + this.gridColumn53.VisibleIndex = 7; + // + // gridColumn54 + // + this.gridColumn54.Caption = "剩余积分"; + this.gridColumn54.FieldName = "cur_point"; + this.gridColumn54.Name = "gridColumn54"; + this.gridColumn54.Visible = true; + this.gridColumn54.VisibleIndex = 8; + this.gridColumn54.Width = 80; + // + // gridColumn55 + // + this.gridColumn55.Caption = "消费奖励(共)"; + this.gridColumn55.FieldName = "buy_point"; + this.gridColumn55.Name = "gridColumn55"; + this.gridColumn55.Visible = true; + this.gridColumn55.VisibleIndex = 9; + this.gridColumn55.Width = 90; + // + // gridColumn56 + // + this.gridColumn56.Caption = "推荐提成(共)"; + this.gridColumn56.FieldName = "ext_point"; + this.gridColumn56.Name = "gridColumn56"; + this.gridColumn56.Visible = true; + this.gridColumn56.VisibleIndex = 10; + this.gridColumn56.Width = 90; + // + // gridColumn57 + // + this.gridColumn57.Caption = "其他奖励(共)"; + this.gridColumn57.FieldName = "rew_point"; + this.gridColumn57.Name = "gridColumn57"; + this.gridColumn57.Visible = true; + this.gridColumn57.VisibleIndex = 11; + this.gridColumn57.Width = 90; + // + // gridColumn58 + // + this.gridColumn58.Caption = "累计积分(共)"; + this.gridColumn58.FieldName = "sum_point"; + this.gridColumn58.Name = "gridColumn58"; + this.gridColumn58.Visible = true; + this.gridColumn58.VisibleIndex = 12; + this.gridColumn58.Width = 90; + // + // gridColumn59 + // + this.gridColumn59.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn59.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn59.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn59.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn59.Caption = "完成订单数"; + this.gridColumn59.FieldName = "finish_order"; + this.gridColumn59.Name = "gridColumn59"; + this.gridColumn59.Visible = true; + this.gridColumn59.VisibleIndex = 13; + // + // gridColumn60 + // + this.gridColumn60.Caption = "支付宝账号"; + this.gridColumn60.FieldName = "alipay_num"; + this.gridColumn60.Name = "gridColumn60"; + this.gridColumn60.Visible = true; + this.gridColumn60.VisibleIndex = 14; + this.gridColumn60.Width = 150; + // + // gridColumn61 + // + this.gridColumn61.Caption = "支付宝姓名"; + this.gridColumn61.FieldName = "alipay_name"; + this.gridColumn61.Name = "gridColumn61"; + this.gridColumn61.Visible = true; + this.gridColumn61.VisibleIndex = 15; + this.gridColumn61.Width = 80; + // + // gridColumn62 + // + this.gridColumn62.Caption = "身份证名称"; + this.gridColumn62.FieldName = "identity_name"; + this.gridColumn62.Name = "gridColumn62"; + this.gridColumn62.Visible = true; + this.gridColumn62.VisibleIndex = 16; + // + // gridColumn63 + // + this.gridColumn63.Caption = "身份证号码"; + this.gridColumn63.FieldName = "identity_card"; + this.gridColumn63.Name = "gridColumn63"; + this.gridColumn63.Visible = true; + this.gridColumn63.VisibleIndex = 17; + // + // gridColumn64 + // + this.gridColumn64.Caption = "邀请人编号"; + this.gridColumn64.FieldName = "inviter_id"; + this.gridColumn64.Name = "gridColumn64"; + this.gridColumn64.Visible = true; + this.gridColumn64.VisibleIndex = 18; + this.gridColumn64.Width = 80; + // + // gridColumn65 + // + this.gridColumn65.Caption = "分组等级"; + this.gridColumn65.FieldName = "gridColumn8"; + this.gridColumn65.Name = "gridColumn65"; + this.gridColumn65.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn65.Visible = true; + this.gridColumn65.VisibleIndex = 19; + this.gridColumn65.Width = 120; + // + // gridColumn66 + // + this.gridColumn66.Caption = "机器人账号"; + this.gridColumn66.FieldName = "robot_name"; + this.gridColumn66.Name = "gridColumn66"; + this.gridColumn66.Visible = true; + this.gridColumn66.VisibleIndex = 20; + this.gridColumn66.Width = 150; + // + // gridColumn67 + // + this.gridColumn67.Caption = "限制兑换时间"; + this.gridColumn67.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn67.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn67.FieldName = "ban_exchange_time"; + this.gridColumn67.Name = "gridColumn67"; + this.gridColumn67.Visible = true; + this.gridColumn67.VisibleIndex = 21; + this.gridColumn67.Width = 150; + // + // gridColumn68 + // + this.gridColumn68.Caption = "最后沟通时间"; + this.gridColumn68.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn68.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn68.FieldName = "upd_time"; + this.gridColumn68.Name = "gridColumn68"; + this.gridColumn68.Visible = true; + this.gridColumn68.VisibleIndex = 22; + this.gridColumn68.Width = 150; + // + // gridColumn69 + // + this.gridColumn69.Caption = "注册时间"; + this.gridColumn69.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn69.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn69.FieldName = "crt_time"; + this.gridColumn69.Name = "gridColumn69"; + this.gridColumn69.Visible = true; + this.gridColumn69.VisibleIndex = 23; + this.gridColumn69.Width = 150; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(11, 134); + this.gridControl1.MainView = this.gridView3; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(894, 440); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3, + this.gridView4}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.添加任务ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(197, 26); + // + // 添加任务ToolStripMenuItem + // + this.添加任务ToolStripMenuItem.Name = "添加任务ToolStripMenuItem"; + this.添加任务ToolStripMenuItem.Size = new System.Drawing.Size(196, 22); + this.添加任务ToolStripMenuItem.Text = "将所选用户添加至任务"; + this.添加任务ToolStripMenuItem.Click += new System.EventHandler(this.添加任务ToolStripMenuItem_Click); + // + // gridView4 + // + this.gridView4.GridControl = this.gridControl1; + this.gridView4.Name = "gridView4"; + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.labelControl9); + this.xtraTabPage1.Controls.Add(this.label5); + this.xtraTabPage1.Controls.Add(this.groupBox1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.ScrollBarSmallChange = 20; + this.xtraTabPage1.Size = new System.Drawing.Size(916, 587); + this.xtraTabPage1.TabPageWidth = 100; + this.xtraTabPage1.Text = " 用 户 搜 索 "; + // + // labelControl9 + // + this.labelControl9.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl9.Appearance.Options.UseForeColor = true; + this.labelControl9.Location = new System.Drawing.Point(745, 114); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(156, 14); + this.labelControl9.TabIndex = 35; + this.labelControl9.Text = "注:列表中右击添加发送任务"; + // + // label5 + // + this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label5.AutoSize = true; + this.label5.BackColor = System.Drawing.Color.White; + this.label5.Font = new System.Drawing.Font("黑体", 26.25F); + this.label5.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.label5.Location = new System.Drawing.Point(298, 257); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(339, 35); + this.label5.TabIndex = 34; + this.label5.Text = "没有符合的用户数据"; + this.label5.Visible = false; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.checkedComboBoxEdit1); + this.groupBox1.Controls.Add(this.labelControl6); + this.groupBox1.Controls.Add(this.comboBoxEdit2); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.simpleButton5); + this.groupBox1.Controls.Add(this.checkBox1); + this.groupBox1.Controls.Add(this.dateTimePicker2); + this.groupBox1.Controls.Add(this.dateTimePicker1); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.comboBoxEdit1); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Location = new System.Drawing.Point(11, 3); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(894, 107); + this.groupBox1.TabIndex = 2; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 过 滤 条 件 "; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(246, 56); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(56, 14); + this.labelControl8.TabIndex = 24; + this.labelControl8.Text = "选择分组: "; + this.labelControl8.Visible = false; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(280, 56); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(68, 14); + this.labelControl7.TabIndex = 23; + this.labelControl7.Text = "未购物天数: "; + this.labelControl7.Visible = false; + // + // checkedComboBoxEdit1 + // + this.checkedComboBoxEdit1.EditValue = "点击选择机器人"; + this.checkedComboBoxEdit1.Location = new System.Drawing.Point(537, 53); + this.checkedComboBoxEdit1.Name = "checkedComboBoxEdit1"; + this.checkedComboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit1.Size = new System.Drawing.Size(151, 20); + this.checkedComboBoxEdit1.TabIndex = 22; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(483, 56); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(48, 14); + this.labelControl6.TabIndex = 20; + this.labelControl6.Text = "机器人:"; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Location = new System.Drawing.Point(307, 54); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Size = new System.Drawing.Size(162, 20); + this.comboBoxEdit2.TabIndex = 17; + this.comboBoxEdit2.Visible = false; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(354, 52); + this.numericUpDown1.Maximum = new decimal(new int[] { + 999999, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(98, 22); + this.numericUpDown1.TabIndex = 15; + this.numericUpDown1.Value = new decimal(new int[] { + 60, + 0, + 0, + 0}); + this.numericUpDown1.Visible = false; + // + // simpleButton5 + // + this.simpleButton5.Location = new System.Drawing.Point(694, 49); + this.simpleButton5.Name = "simpleButton5"; + this.simpleButton5.Size = new System.Drawing.Size(83, 29); + this.simpleButton5.TabIndex = 13; + this.simpleButton5.Text = "点击校验数据"; + this.simpleButton5.Visible = false; + this.simpleButton5.Click += new System.EventHandler(this.simpleButton5_Click); + // + // checkBox1 + // + this.checkBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(244, 55); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(62, 18); + this.checkBox1.TabIndex = 12; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // dateTimePicker2 + // + this.dateTimePicker2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(307, 66); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(162, 22); + this.dateTimePicker2.TabIndex = 11; + this.dateTimePicker2.ValueChanged += new System.EventHandler(this.dateTimePicker2_ValueChanged); + // + // dateTimePicker1 + // + this.dateTimePicker1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(307, 39); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(162, 22); + this.dateTimePicker1.TabIndex = 10; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(27, 56); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 2; + this.labelControl1.Text = "搜索条件:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.EditValue = "新用户未查询过"; + this.comboBoxEdit1.Location = new System.Drawing.Point(90, 53); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "新用户未查询过", + "新用户查询后未下单", + "长时间未购买的老客户", + "用户分组", + "所有用户", + "已下单用户"}); + this.comboBoxEdit1.Size = new System.Drawing.Size(139, 20); + this.comboBoxEdit1.TabIndex = 1; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(788, 49); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(84, 29); + this.simpleButton1.TabIndex = 0; + this.simpleButton1.Text = " 查 询 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(918, 611); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + this.xtraTabControl1.SelectedPageChanging += new DevExpress.XtraTab.TabPageChangingEventHandler(this.xtraTabControl1_SelectedPageChanging); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(918, 611); + this.Controls.Add(this.xtraTabControl1); + this.Name = "MainForm"; + this.Text = "激活用户"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.xtraTabPage3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + this.groupControl4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).EndInit(); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn28; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn29; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn47; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn48; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn49; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn50; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn51; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn52; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn53; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn54; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn55; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn56; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn57; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn58; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn59; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn60; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn61; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn62; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn63; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn64; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn65; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn66; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn67; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn68; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn69; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView4; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 添加任务ToolStripMenuItem; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem 修改ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private DevExpress.XtraEditors.GroupControl groupControl4; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton4; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.SimpleButton simpleButton5; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.ToolStripMenuItem 全部删除ToolStripMenuItem; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl8; + private System.Windows.Forms.Label label5; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + } +} \ No newline at end of file diff --git a/应用/EncourageUser/MainForm.cs b/应用/EncourageUser/MainForm.cs new file mode 100644 index 0000000..96db199 --- /dev/null +++ b/应用/EncourageUser/MainForm.cs @@ -0,0 +1,680 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using EncourageUser.Properties; +using EncourageUser.Entitys; +using Api.Framework; +using Api.Framework.Tools; +using Api.Framework.Model; +using CsharpHttpHelper; +using Chat.Framework; +using Chat.Framework.WXSdk; +using System.Threading; + +namespace EncourageUser +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) + { + try + { + if (listView1.SelectedItems.Count == 0) + { + _ButtonEnabled(false); + return; + } + else + { + var session = ApiClient.GetSession(); + var id = long.Parse(listView1.SelectedItems[0].SubItems[0].Text); + + List messs = null; + + if (listView1.Tag != null) + messs = listView1.Tag as List; + else + messs = session.Find("select * from fl_plugin_encourage_user_messs"); + if (messs != null && messs.Count != 0) + { + var mess = messs.FirstOrDefault(f => f.id == id); + if (mess == null) return; + textEdit4.Text = mess.note; + memoEdit1.Text = mess.mess; + + groupControl4.Tag = mess; + _ButtonEnabled(true); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 按钮状态 + /// + /// + private void _ButtonEnabled(bool flag) + { + simpleButton2.Enabled = simpleButton3.Enabled = flag; + } + + private void simpleButton4_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var mess = new fl_plugin_encourage_user_messs(); + + mess.id = 0; + mess.note = textEdit4.Text.Trim(); + mess.mess = memoEdit1.Text.Trim(); + + var messs = session.Find("select * from fl_plugin_encourage_user_messs"); + if (messs != null && messs.Count != 0) + { + var _signInfo = messs.FirstOrDefault(f => f.note == mess.note); + if (_signInfo != null) throw new Exception("该消息别名已经存在,无法增加"); + } + session.Insertable(mess).ExecuteCommand(); + _RefreshData(); + simpleButton2.Enabled = simpleButton3.Enabled = false; + } + catch (Exception ex) + { + if (ex.Message.Contains("not unique")) + ShowError("数据重复"); + else + ShowError(ex); + } + } + /// + /// 数显数据 + /// + private void _RefreshData(int index = 0) + { + try + { + var session = ApiClient.GetSession(); + listView1.Tag = null; + if (groupControl4.Tag == null) + _ButtonEnabled(false); + var messs = session.Find("select * from fl_plugin_encourage_user_messs", new { signtype = index }); + listView1.Items.Clear(); + foreach (var mess in messs) + { + var item = new ListViewItem(); + item.Text = mess.id.ToString(); + item.SubItems.Add(mess.note); + item.SubItems.Add(mess.mess); + listView1.Items.Add(item); + } + listView1.Tag = messs; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + if (groupControl4.Tag != null) + { + var session = ApiClient.GetSession(); + var mess = groupControl4.Tag as fl_plugin_encourage_user_messs; + mess.note = textEdit4.Text.Trim(); + mess.mess = memoEdit1.Text.Trim(); + + //List messs = null; + //if (listView1.Tag != null) + // messs = listView1.Tag as List; + //else + // messs = session.Find("select * from fl_plugin_encourage_user_messs"); + //if (messs != null && messs.Count != 0) + //{ + //var _mess = messs.FirstOrDefault(f => f.note == mess.note); + //if (_mess != null) throw new Exception("该消息别名已经存在,无法增加"); + //} + + session.Updateable(mess).ExecuteCommand(); + _RefreshData(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + try + { + if (groupControl4.Tag != null) + { + var session = ApiClient.GetSession(); + var messs = session.Find("select * from fl_plugin_encourage_user_messs"); + if (messs.Count > 1) + { + var mess = groupControl4.Tag as fl_plugin_encourage_user_messs; + + var task = session.FindSingle("select * from fl_qunfa_task where messid = @messid", new { messid = mess.id }); + if (task == null) + { + session.Deleteable(mess).ExecuteCommand(); + _RefreshData(); + } + else + ShowError("当前提示语已被任务使用,无法删除"); + } + else + ShowSuccess("至少留一个提示语"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + //var wxs = ChatClient.WXClient.Values; + //foreach (var item in wxs) + //{ + // try + // { + + // if (item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信) + // { + // var friends = item.FindFriends(); + // Console.WriteLine(); + // } + // else if (item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.QYHook微信) + // { + // var friends = item.FindFriends(); + // Console.WriteLine(); + // } + // else if (item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信) + // { + // //var friends = item.FindFriends(); + // Console.WriteLine(); + // } + // } + // catch (Exception ex) + // { + // } + //} + + //return; + + try + { + if (!simpleButton5.Enabled) + throw new Exception("数据在校验中,等校验完毕后再试!"); + simpleButton1.Text = "查询中..."; + simpleButton1.Enabled = false; + var t = Task.Run(() => + { + try + { + gridControl1.DataSource = null; + + var uType = (UserType)comboBoxEdit1.SelectedIndex; + var results = checkedComboBoxEdit1.Properties.GetCheckedItems().ToString().Replace(", ", ",").Replace(" ,", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + + var session = ApiClient.GetSession(); + var robots = new List(); + for (int i = 0; i < results.Length; i++) + { + var split = results[i].Split('('); + var name = split[split.Length - 1].Replace(")", ""); + var nick = results[i].Replace($"({name})", ""); + var robot = session.FindRobots().FirstOrDefault(f => f.name.Trim() == name && f.nick == nick); + if (robot != null) + robots.Add(robot); + } + + var db = ApiClient.GetSession(); + + var members = new List(); + + var check = checkBox1.Checked; + var beginTime = dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss"); + var endTime = dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss"); + + var sql = $"select * from fl_member_info where 1 = 1 and status != 1"; + if (robots != null && robots.Count != 0) + { + sql += $" and robot_name in ('"; + var robotNameTmp = new List(); + for (int i = 0; i < robots.Count; i++) + { + robotNameTmp.Add(robots[i].name); + } + sql += string.Join("','", robotNameTmp) + "') "; + } + switch (uType) + { + case UserType.新用户未查询过: + case UserType.新用户查询后未下单: + { + //var sql = $"select * from fl_member_info where robot_name = {robot.name} and "; + if (check) + sql += " and '" + beginTime + "' <= crt_time and crt_time <= '" + endTime + "'"; + sql += " and bind_order = 0"; + var notQueryMember = db.Find(sql); + if (notQueryMember != null && notQueryMember.Count != 0) + { + var sRecord = db.Find("select * from fl_statistics_record"); + + if (UserType.新用户未查询过 == uType) + members = notQueryMember.Where(m => sRecord.FirstOrDefault(r => r.uid == m.id) == null).ToList(); + else if (UserType.新用户查询后未下单 == uType) + members = notQueryMember.Where(m => sRecord.FirstOrDefault(r => r.querynum != 0 && r.uid == m.id) != null).ToList(); + } + } + break; + case UserType.已下单用户: + { + if (check) + sql += " and '" + beginTime + "' <= crt_time and crt_time <= '" + endTime + "'"; + sql += " and bind_order != 0"; + members = db.Find(sql); + } + break; + case UserType.长时间未购买的老客户: + { + var _members = db.Find(sql); + var sql2 = "select * from fl_statistics_record "; + sql2 += " where ex5 <= " + HttpExtend.GetTimeStamp(DateTime.Now.AddDays(-(int)numericUpDown1.Value)); + var records = db.Find(sql2); + if (records != null) + { + foreach (var item in records) + { + var temp = _members.FirstOrDefault(f => f.id == item.uid); + if (temp != null) + members.Add(temp); + } + } + } + break; + case UserType.用户分组: + { + var mGroup = (fl_member_group)comboBoxEdit2.SelectedItem; + sql += $" and group_id = {mGroup.id}"; + members = db.Find(sql); + } + break; + case UserType.所有用户: + members = db.Find(sql); + break; + default: + break; + } + this.Invoke(new Action(() => + { + + if (members != null && members.Count != 0) + gridControl1.DataSource = members; + label5.Visible = (members == null || members.Count == 0); + })); + } + catch (Exception) + { } + finally + { + this.Invoke(new Action(() => + { + simpleButton1.Text = " 查 询 "; + simpleButton1.Enabled = true; + })); + } + }); + } + catch (Exception) + { } + + + //t.ContinueWith(o => + //{ + + //}); + //Task.WaitAll(t); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void GetTasks() + { + try + { + gridControl3.DataSource = null; + var db = ApiClient.GetSession(); + var tasks = db.Find("select * from fl_qunfa_task order by execType asc"); + + if (tasks != null && tasks.Count != 0) + { + gridControl3.DataSource = tasks; + } + } + catch (Exception ex) + { } + } + + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + numericUpDown1.Visible = labelControl7.Visible = simpleButton5.Visible = comboBoxEdit1.SelectedIndex == 2; + checkBox1.Visible = dateTimePicker1.Visible = dateTimePicker2.Visible = (comboBoxEdit1.SelectedIndex == 0 || comboBoxEdit1.SelectedIndex == 1 || comboBoxEdit1.SelectedIndex == 5); + labelControl8.Visible = comboBoxEdit2.Visible = comboBoxEdit1.SelectedIndex == 3; + + if (comboBoxEdit1.SelectedIndex == 3) + { + var groups = ApiClient.GetSession().Find("select * from fl_member_group"); + if (groups == null || groups.Count == 0) + throw new Exception("数据异常"); + this.comboBoxEdit2.Properties.Items.AddRange(groups); + this.comboBoxEdit2.SelectedIndex = 0; + } + else if (comboBoxEdit1.SelectedIndex == 4) + { + + + } + + } + catch (Exception ex) + { } + } + + //private void Visible(bool v) + //{ + // numericUpDown1.Visible = labelControl6.Visible = v; + //} + + private void xtraTabControl1_SelectedPageChanging(object sender, DevExpress.XtraTab.TabPageChangingEventArgs e) + { + try + { + if (e.Page.TabIndex == 1) + _RefreshData(); + else if (e.Page.TabIndex == 2) + GetTasks(); + } + catch (Exception ex) + { } + } + + private void 添加任务ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var result = gridControl1.DataSource; + if (result == null) throw new Exception("发送用户列表为空"); + var members = result as List; + + var rownumber = gridView3.GetSelectedRows().ToList();//获取选中行号; + if (rownumber == null || rownumber.Count == 0) throw new Exception("请选要发送的用户"); + if (rownumber != null & rownumber.Count != 0) + { + List mList = new List(); + foreach (var item in rownumber) + { + try + { + var id = int.Parse(gridView3.GetRowCellValue(item, "id").ToString()); + var m = members.FirstOrDefault(f => f.id == id); + if (m != null) + mList.Add(m); + } + catch (Exception) + { } + } + + if (mList == null) throw new Exception("发送用户存在未知情况,终止操作"); + if (mList != null && mList.Count != 0) + { + ////var stateDic = new Dictionary(); + //var dic = new Dictionary>(); + //var robotNames = mList.Select(f => f.robot_name).ToList().GroupBy(f => f).Select(f => f.Key).ToList(); + //if (robotNames != null && robotNames.Count != 0) + //{ + // foreach (var robot in robotNames) + // { + // dic.Add(robot, mList.Where(f => f.robot_name == robot).Select(f => f.id).ToList()); + // //stateDic.Add(robot, new SendState() { IsFinish = false, Num = 0, Time = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now.Date) }); + // } + //} + var tForm = new TaskForm(mList); + tForm.ShowDialog(); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 修改ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView2.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = this.gridView2.GetRow(rows[0]) as fl_qunfa_task; + if (row == null) return; + var tForm = new TaskForm(row); + tForm.ShowDialog(); + TaskJob.Abort(row.id); + GetTasks(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView2.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = this.gridView2.GetRow(rows[0]) as fl_qunfa_task; + if (row == null) return; + + var session = ApiClient.GetSession(); + session.Deleteable(row).ExecuteCommand(); + TaskJob.Abort(row.id); + GetTasks(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void dateTimePicker2_ValueChanged(object sender, EventArgs e) + { + + } + + /// + /// 是否在运行 + /// + public static bool isRun { get; set; } + + private void simpleButton5_Click(object sender, EventArgs e) + { + Task.Run(() => + { + try + { + this.Invoke(new Action(() => + { + simpleButton5.Enabled = false; + simpleButton5.Text = "正在校验数据中..."; + })); + + var session = ApiClient.GetSession(); + //var sql = "select * from fl_member_info "; + //if (check) + // sql += " where '" + begionTime + "' <= crt_time and crt_time <= '" + endTime + "'"; + + var members = session.Find("select * from fl_member_info"); + + //var members = session.Find("select * from fl_member_info"); + var records = session.Find("select * from fl_statistics_record", new { }); + + foreach (var member in members) + { + try + { + var paytime = DateTime.MinValue; + var mrecord = records.FirstOrDefault(f => f.uid == member.id); + if (mrecord != null && mrecord.ex5 != 0) + paytime = HttpExtend.GetDateTime(mrecord.ex5.ToString()); + + var alimama = session.FindSingle("select * from fl_order_alimama where db_userid = @uid order by id desc", new { uid = member.id }); + if (alimama != null && alimama.paid_time > paytime) + paytime = alimama.paid_time; + var jingdong = session.FindSingle("select * from fl_order_jingdong where db_userid = @uid order by id desc", new { uid = member.id }); + if (jingdong != null && jingdong.orderTime > paytime) + paytime = jingdong.orderTime; + var pinduoduo = session.FindSingle("select * from fl_order_pinduoduo where db_userid = @uid order by id desc", new { uid = member.id }); + if (pinduoduo != null && pinduoduo.order_pay_time > paytime) + paytime = pinduoduo.order_pay_time; + + var weipinhui = session.FindSingle("select * from fl_order_weipinhui where db_userid = @uid order by id desc", new { uid = member.id }); + var wphorderTime = Util.GetDateTime(weipinhui.orderTime); + if (weipinhui != null && wphorderTime > paytime) + paytime = wphorderTime; + + if (mrecord == null) + { + mrecord = new fl_statistics_record() { uid = member.id, ex5 = HttpExtend.GetTimeStamp(paytime) }; + session.Saveable(mrecord).ExecuteCommand(); + } + else if (mrecord.ex5 != HttpExtend.GetTimeStamp(paytime)) + { + mrecord.ex5 = HttpExtend.GetTimeStamp(paytime); + session.Saveable(mrecord).ExecuteCommand(); + } + } + catch (Exception ex) + { } + } + ShowSuccessAutoClose("校验数据完成,点击查询", 3000); + } + catch (Exception ex) + { } + finally + { + this.Invoke(new Action(() => + { + simpleButton5.Enabled = true; + simpleButton5.Text = "点击校验数据"; + simpleButton1_Click(null, null); + })); + } + }); + } + + private void 全部删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + session.Deleteable().ExecuteCommand(); + TaskJob.AbortAll(); + GetTasks(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + checkedComboBoxEdit1.Properties.SelectAllItemCaption = "全选"; + var robots = ApiClient.GetSession().Find("select * from fl_robot_info"); + if (robots == null || robots.Count == 0) + throw new Exception("当前不存在任何机器人账号信息,请登录机器人后在来操作该插件"); + for (int i = 0; i < robots.Count; i++) + { + this.checkedComboBoxEdit1.Properties.Items.Add(robots[i]); + } + } + catch (Exception ex) + { + ShowErrorAutoClose(ex, 6000); + this.Close(); + } + } + + private void gridView3_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) + { + e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + } + } + +} \ No newline at end of file diff --git a/应用/EncourageUser/MainForm.resx b/应用/EncourageUser/MainForm.resx new file mode 100644 index 0000000..d396faf --- /dev/null +++ b/应用/EncourageUser/MainForm.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 274, 17 + + + 109, 17 + + + 56 + + \ No newline at end of file diff --git a/应用/EncourageUser/Properties/AssemblyInfo.cs b/应用/EncourageUser/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5e86c53 --- /dev/null +++ b/应用/EncourageUser/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("EncourageUser")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EncourageUser")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("44593bac-0617-483e-9ad7-bef4336e14d7")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/EncourageUser/Properties/Resources.Designer.cs b/应用/EncourageUser/Properties/Resources.Designer.cs new file mode 100644 index 0000000..1728734 --- /dev/null +++ b/应用/EncourageUser/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace EncourageUser.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EncourageUser.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 群发工具 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 群发工具 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 群发工具 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 群发工具 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 群发 { + get { + object obj = ResourceManager.GetObject("群发", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/EncourageUser/Properties/Resources.resx b/应用/EncourageUser/Properties/Resources.resx new file mode 100644 index 0000000..8c0a2f7 --- /dev/null +++ b/应用/EncourageUser/Properties/Resources.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 群发工具 + 插件窗体标题 + + + 群发工具 + 插件名称 + + + 群发工具 + 插件介绍 + + + 群发工具 + + + + ..\Resources\群发.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/EncourageUser/Properties/licenses.licx b/应用/EncourageUser/Properties/licenses.licx new file mode 100644 index 0000000..301e7e3 --- /dev/null +++ b/应用/EncourageUser/Properties/licenses.licx @@ -0,0 +1,3 @@ +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/EncourageUser/Resources/客户激活.png b/应用/EncourageUser/Resources/客户激活.png new file mode 100644 index 0000000..2764f2c Binary files /dev/null and b/应用/EncourageUser/Resources/客户激活.png differ diff --git a/应用/EncourageUser/Resources/群发.png b/应用/EncourageUser/Resources/群发.png new file mode 100644 index 0000000..db1664b Binary files /dev/null and b/应用/EncourageUser/Resources/群发.png differ diff --git a/应用/EncourageUser/TaskForm.Designer.cs b/应用/EncourageUser/TaskForm.Designer.cs new file mode 100644 index 0000000..a9310c2 --- /dev/null +++ b/应用/EncourageUser/TaskForm.Designer.cs @@ -0,0 +1,374 @@ +namespace EncourageUser +{ + partial class TaskForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.dateTimePicker4 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown4 = new System.Windows.Forms.NumericUpDown(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.dateTimePicker3 = new System.Windows.Forms.DateTimePicker(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.dateTimePicker4); + this.groupBox1.Controls.Add(this.dateTimePicker2); + this.groupBox1.Controls.Add(this.labelControl12); + this.groupBox1.Controls.Add(this.labelControl9); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.labelControl6); + this.groupBox1.Controls.Add(this.numericUpDown2); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.numericUpDown4); + this.groupBox1.Controls.Add(this.labelControl10); + this.groupBox1.Controls.Add(this.numericUpDown3); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.dateTimePicker3); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl11); + this.groupBox1.Controls.Add(this.dateTimePicker1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.comboBoxEdit1); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(456, 323); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基 础 任 务 "; + // + // dateTimePicker4 + // + this.dateTimePicker4.CustomFormat = "HH:mm:ss"; + this.dateTimePicker4.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker4.Location = new System.Drawing.Point(139, 147); + this.dateTimePicker4.Name = "dateTimePicker4"; + this.dateTimePicker4.ShowUpDown = true; + this.dateTimePicker4.Size = new System.Drawing.Size(111, 22); + this.dateTimePicker4.TabIndex = 11; + // + // dateTimePicker2 + // + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(139, 89); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(111, 22); + this.dateTimePicker2.TabIndex = 11; + // + // labelControl12 + // + this.labelControl12.Location = new System.Drawing.Point(49, 152); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(84, 14); + this.labelControl12.TabIndex = 10; + this.labelControl12.Text = "每天结束时间:"; + // + // labelControl9 + // + this.labelControl9.Location = new System.Drawing.Point(49, 93); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(84, 14); + this.labelControl9.TabIndex = 10; + this.labelControl9.Text = "结束发送日期:"; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(244, 276); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(75, 30); + this.simpleButton2.TabIndex = 9; + this.simpleButton2.Text = "取 消"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(114, 276); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 30); + this.simpleButton1.TabIndex = 9; + this.simpleButton1.Text = "确 定"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(214, 181); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(36, 14); + this.labelControl6.TabIndex = 8; + this.labelControl6.Text = "条信息"; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(139, 177); + this.numericUpDown2.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(69, 22); + this.numericUpDown2.TabIndex = 7; + this.numericUpDown2.Value = new decimal(new int[] { + 300, + 0, + 0, + 0}); + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(49, 181); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(84, 14); + this.labelControl5.TabIndex = 6; + this.labelControl5.Text = "当天发送数量:"; + // + // numericUpDown4 + // + this.numericUpDown4.Location = new System.Drawing.Point(282, 236); + this.numericUpDown4.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown4.Name = "numericUpDown4"; + this.numericUpDown4.Size = new System.Drawing.Size(95, 22); + this.numericUpDown4.TabIndex = 5; + this.numericUpDown4.Value = new decimal(new int[] { + 50, + 0, + 0, + 0}); + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(383, 240); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(41, 14); + this.labelControl10.TabIndex = 4; + this.labelControl10.Text = "单位/秒"; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(139, 236); + this.numericUpDown3.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(69, 22); + this.numericUpDown3.TabIndex = 5; + this.numericUpDown3.Value = new decimal(new int[] { + 40, + 0, + 0, + 0}); + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(214, 240); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(60, 14); + this.labelControl8.TabIndex = 4; + this.labelControl8.Text = "条消息休息"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(139, 207); + this.numericUpDown1.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(69, 22); + this.numericUpDown1.TabIndex = 5; + this.numericUpDown1.Value = new decimal(new int[] { + 5, + 0, + 0, + 0}); + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(97, 240); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(36, 14); + this.labelControl7.TabIndex = 4; + this.labelControl7.Text = "每发送"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(214, 211); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(41, 14); + this.labelControl4.TabIndex = 4; + this.labelControl4.Text = "单位/秒"; + // + // dateTimePicker3 + // + this.dateTimePicker3.CustomFormat = "HH:mm:ss"; + this.dateTimePicker3.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker3.Location = new System.Drawing.Point(139, 118); + this.dateTimePicker3.Name = "dateTimePicker3"; + this.dateTimePicker3.ShowUpDown = true; + this.dateTimePicker3.Size = new System.Drawing.Size(111, 22); + this.dateTimePicker3.TabIndex = 3; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(49, 211); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 4; + this.labelControl3.Text = "每条发送间隔:"; + // + // labelControl11 + // + this.labelControl11.Location = new System.Drawing.Point(49, 123); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(84, 14); + this.labelControl11.TabIndex = 2; + this.labelControl11.Text = "每天开始时间:"; + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(139, 60); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(111, 22); + this.dateTimePicker1.TabIndex = 3; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(49, 64); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(84, 14); + this.labelControl2.TabIndex = 2; + this.labelControl2.Text = "开始发送日期:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(49, 34); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(84, 14); + this.labelControl1.TabIndex = 1; + this.labelControl1.Text = "发送消息模板:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(139, 31); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(164, 20); + this.comboBoxEdit1.TabIndex = 0; + // + // TaskForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(480, 347); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "TaskForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "编辑任务"; + this.Load += new System.EventHandler(this.TaskForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl6; + private System.Windows.Forms.NumericUpDown numericUpDown4; + private DevExpress.XtraEditors.LabelControl labelControl10; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private DevExpress.XtraEditors.LabelControl labelControl9; + private System.Windows.Forms.DateTimePicker dateTimePicker4; + private System.Windows.Forms.DateTimePicker dateTimePicker3; + private DevExpress.XtraEditors.LabelControl labelControl12; + private DevExpress.XtraEditors.LabelControl labelControl11; + } +} \ No newline at end of file diff --git a/应用/EncourageUser/TaskForm.cs b/应用/EncourageUser/TaskForm.cs new file mode 100644 index 0000000..2d9fdf2 --- /dev/null +++ b/应用/EncourageUser/TaskForm.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Api.Framework; +using EncourageUser.Entitys; +using Api.Framework.Tools; +using Api.Framework.Model; + +namespace EncourageUser +{ + public partial class TaskForm : BaseForm + { + /// + /// 需要发送的用户 + /// + private List mList = null; + public TaskForm(List mList) + { + InitializeComponent(); + dateTimePicker1.Value = DateTime.Now.AddHours(1); + dateTimePicker2.Value = DateTime.Parse($"{DateTime.Now.ToString("yyyy-MM-dd")} 19:00:00"); + this.mList = mList; + } + + public fl_qunfa_task eTask; + public TaskForm(fl_qunfa_task eTask) + { + InitializeComponent(); + this.eTask = eTask; + } + + private void TaskForm_Load(object sender, EventArgs e) + { + try + { + long select = 0; + if (eTask != null) + { + numericUpDown1.Value = eTask.interval; + numericUpDown2.Value = eTask.totalSentCount; + numericUpDown3.Value = eTask.restSendCount; + numericUpDown4.Value = eTask.restInterval; + dateTimePicker1.Value = eTask.startTime.Date; + dateTimePicker2.Value = eTask.endTime.Date; + //dateTimePicker3.Value = DateTime.Parse(eTask.startTime.Date.ToString("yyyy-MM-dd") + " " + eTask.startTime.ToString("HH:mm:ss")); + //dateTimePicker4.Value = DateTime.Parse(eTask.endTime.Date.ToString("yyyy-MM-dd") + " " + eTask.endTime.ToString("HH:mm:ss")); + dateTimePicker3.Value = DateTime.Parse(eTask.startTime.ToString("yyyy-MM-dd HH:mm:ss")); + dateTimePicker4.Value = DateTime.Parse(eTask.endTime.ToString("yyyy-MM-dd HH:mm:ss")); + select = eTask.id; + } + + var index = 0; + var session = ApiClient.GetSession(); + var messs = session.Find("select * from fl_plugin_encourage_user_messs"); + if (messs == null || messs.Count != 0) + { + var list = new List(); + for (int i = 0; i < messs.Count; i++) + { + if (messs[i].id == select) + index = i; + list.Add($"{messs[i].note.Trim()}"); + } + this.comboBoxEdit1.Properties.Items.AddRange(list); + + comboBoxEdit1.SelectedIndex = index; + + comboBoxEdit1.Tag = messs; + } + else + { + XtraMessageBox.Show($"当前还未设置发送的内容", "温馨提示", MessageBoxButtons.OK); + this.Close(); + } + + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var data1 = dateTimePicker1.Value.Date; + var data2 = dateTimePicker2.Value.Date; + if (data1 > data2) + throw new Exception("结束日期不能小于开始日期"); + var time1 = dateTimePicker3.Value.ToString("HH:mm:ss"); + var time2 = dateTimePicker4.Value.ToString("HH:mm:ss"); + if (DateTime.Parse("2000-01-01 " + time1) >= DateTime.Parse("2000-01-01 " + time2)) + throw new Exception("结束时间不能小于等于开始时间"); + + var messs = comboBoxEdit1.Tag as List; + if (messs == null) throw new Exception("数据异常,请稍后重试"); + var mess = messs.FirstOrDefault(f => f.note.Trim() == comboBoxEdit1.Text); + if (mess == null) throw new Exception("数据异常,请稍后重试"); + var session = ApiClient.GetSession(); + + if (eTask == null) + { + eTask = new fl_qunfa_task(); + eTask.id = session.Insertable(eTask).ExecuteReturnIdentity(); + var sendNum = HandlerUser(); + eTask.sendnum = 0; + eTask.allsendnum = eTask.unsendnum = sendNum; + eTask.execType = ExecType.未执行完毕; + } + + eTask.interval = (int)numericUpDown1.Value; + eTask.totalSentCount = (int)numericUpDown2.Value; + eTask.restSendCount = (int)numericUpDown3.Value; + eTask.restInterval = (int)numericUpDown4.Value; + + + eTask.startTime = DateTime.Parse(data1.ToString("yyyy-MM-dd") + " " + time1); + eTask.endTime = DateTime.Parse(data2.ToString("yyyy-MM-dd") + " " + time2); + + eTask.messid = mess.id; + + if (eTask.id == 0) + eTask.id = session.Insertable(eTask).ExecuteReturnIdentity(); + else + session.Updateable(eTask).ExecuteCommand(); + TaskJob.Abort(eTask.id); + this.Close(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 将用户添加到任务中 + /// + /// + private int HandlerUser() + { + try + { + List list = new List(); + foreach (var member in mList) + { + list.Add(new fl_qunfa_user() + { + chattype = member.robot_type, + robotname = member.robot_name, + taskid = eTask.id, + userid = member.id, + username = member.username, + issend = false + }); + } + ApiClient.GetSession().Insertable(list).ExecuteCommand(); + return list.Count; + } + catch (Exception ex) + { + EventClient.OnEvent("整理发送用户", $"{ex.Message} - {ex.StackTrace}"); + } + return 0; + } + + } +} \ No newline at end of file diff --git a/应用/EncourageUser/TaskForm.resx b/应用/EncourageUser/TaskForm.resx new file mode 100644 index 0000000..cb447e0 --- /dev/null +++ b/应用/EncourageUser/TaskForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 53 + + \ No newline at end of file diff --git a/应用/EncourageUser/TaskJob.cs b/应用/EncourageUser/TaskJob.cs new file mode 100644 index 0000000..2ce5988 --- /dev/null +++ b/应用/EncourageUser/TaskJob.cs @@ -0,0 +1,295 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using EncourageUser.Entitys; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace EncourageUser +{ + public class TaskJob : TimerTask + { + /// + /// 运行中的任务 + /// + public static Dictionary JobDic = new Dictionary(); + + public static bool isrun { get; set; } = false; + + public override void Run(object state, bool timedOut) + { + if (isrun) return; + try + { + isrun = true; + var session = ApiClient.GetSession(); + var jobs = session.Find("select * from fl_qunfa_task where execType = @execType", new { execType = ExecType.未执行完毕 }); + if (jobs == null || jobs.Count == 0) + return; + + foreach (var job in jobs) + { + //if (JobDic.ContainsKey(job.id)) + // continue; + + //更新任务发送用户数量 + var qfUser = session.Queryable().Where(f => f.taskid == job.id).ToList(); + if (qfUser.Count == 0) + continue; + else + { + var unSendNum = qfUser.Count(f => !f.issend); + if (unSendNum == 0) + { + job.execType = ExecType.执行完毕; + if (JobDic.ContainsKey(job.id)) + { + Abort(job.id); + continue; + } + } + else if (!CheckSendNum(job.id, job.totalSentCount) && IsSendTime(job) && job.endTime.Date == DateTime.Today)// + job.execType = ExecType.执行完毕; + else if (job.endTime < DateTime.Now)//已经超出任务结束日期 + job.execType = ExecType.执行失效; + else + job.execType = ExecType.未执行完毕; + + job.unsendnum = unSendNum; + job.allsendnum = qfUser.Count; + job.sendnum = qfUser.Count - unSendNum; + session.Updateable(job).ExecuteCommand(); + if (job.execType != ExecType.未执行完毕) + continue; + } + + if (!JobDic.ContainsKey(job.id) && IsSendTime(job) && CheckSendNum(job.id, job.totalSentCount)) + { + //回复语不存在直接不执行 + var mess = session.Queryable().First(f => f.id == job.messid); + if (mess == null) + { + job.execType = ExecType.执行失效; + session.Updateable(job).ExecuteCommand(); + continue; + } + + ExecTask(job, mess); + } + } + } + catch (Exception) + { + EventClient.OnEvent(this, $"群发工具异常 -> 检测时间:{DateTime.Now.ToString("HH:mm:ss")}"); + } + finally + { + isrun = false; + } + } + + private static void ExecTask(fl_qunfa_task job, fl_plugin_encourage_user_messs taskMess) + { + var task = job; + try + { + var taskCancel = new CancellationTokenSource(); + fl_plugin_encourage_user_messs taskmess = taskMess; + + Task.Factory.StartNew(() => + { + try + { + var db = ApiClient.GetSession(); + + var mList = db.Queryable().Where(f => f.taskid == job.id); + //未发送的用户集合 + var unSendMList = mList.Where(f => !f.issend).ToList(); + + //机器人分组 + var rGroup = unSendMList.GroupBy(f => f.robotname).Select(f => f.Key).ToList(); + + + foreach (var rname in rGroup) + { + if (taskCancel.IsCancellationRequested) + return; + + var sendMList = unSendMList.Where(f => f.robotname == rname).ToList(); + if (sendMList.Count != 0) + { + JobDic[task.id] = taskCancel; + EventClient.OnEvent("", $"成功下达群发任务:{task.id}"); + SendTask(task, sendMList, taskmess, taskCancel); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"处理群发任务{task.id}异常:{ex.Message} - {ex.StackTrace}"); + } + }, taskCancel.Token); + + } + catch (Exception ex) + { + EventClient.OnEvent("", $"处理群发任务{task.id}异常2:{ex.Message} - {ex.StackTrace}"); + } + } + + /// + /// 执行发送任务 + /// + /// 发送用户集合 + /// 取消任务 + private static void SendTask(fl_qunfa_task qunTask, List users, fl_plugin_encourage_user_messs taskMess, CancellationTokenSource tCancel) + { + fl_qunfa_task quntask = qunTask; + List sendUsers = users; + CancellationTokenSource taskCancel = tCancel; + fl_plugin_encourage_user_messs taskmess = taskMess; + Task.Factory.StartNew(() => + { + try + { + var num = 1; + foreach (var user in sendUsers) + { + //判断是否在可发送时间段 或者 今日发送数量已上限 + if (!IsSendTime(quntask) || !CheckSendNum(quntask.id, quntask.totalSentCount) || taskCancel.IsCancellationRequested) + return; + + var flag = false;//判断是否执行发送,执行了休眠才休眠 + if (user.chattype == ChatType.企业微信 || user.chattype == ChatType.微信) + { + var robot = ChatClient.WXClient.FirstOrDefault(f => f.Key == user.robotname).Value; + if (robot == null || robot.Status != Chat.Framework.WXSdk.WxStatus.在线) + continue; + flag = true; + robot.SendMessage(user.username, taskmess.mess); + UpdUser(user); + } + else if (user.chattype == ChatType.QQ) + { + var robot = ChatClient.QQClients.FirstOrDefault(f => f.Key == user.robotname).Value; + if (robot == null || !robot.IsLogin) + continue; + flag = true; + robot.SendMessage(uint.Parse(user.username), taskmess.mess); + UpdUser(user); + } + if (flag) + { + EventClient.OnEvent("发送任务", $"执行群发任务:{quntask.id},用户:{user.username},{DateTime.Now}"); + var second = quntask.interval; + if (quntask.restSendCount <= num) + { + second = quntask.restInterval; + num = 0; + } + //发送休眠时间 + Thread.Sleep(second * 1000 + new Random(Guid.NewGuid().GetHashCode()).Next(100, 1000)); + num++; + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"执行群发任务中异常:{ex.Message} - {ex.StackTrace}"); + } + finally + { + Abort(quntask.id); + } + }, taskCancel.Token); + } + + private static void UpdUser(fl_qunfa_user user) + { + user.sendtime = HttpExtend.GetTimeStamp(DateTime.Now); + user.issend = true; + var db = ApiClient.GetSession(); + db.Updateable(user).ExecuteCommand(); + } + + /// + /// 是否在发送时间段 + /// + /// + /// + private static bool IsSendTime(fl_qunfa_task job) + { + var now = DateTime.Now; + var date = now.ToString("yyyy-MM-dd"); + var startTime1 = DateTime.Parse($"{date} {job.startTime.Hour}:{job.startTime.Minute}:{job.startTime.Second}"); + var endTime1 = DateTime.Parse($"{date} {job.endTime.Hour}:{job.endTime.Minute}:{job.endTime.Second}"); + + var startTime = DateTime.Parse($"{job.startTime}"); + var endTime = DateTime.Parse($"{job.endTime}"); + //if (startTime <= now && now <= endTime && startTime1 <= now && now <= endTime1 && !JobDic.ContainsKey(job.id)) + return (startTime <= now && now <= endTime && startTime1 <= now && now <= endTime1); + } + + /// + /// 今日发送人数是否达标,还可发送返回true + /// + /// + private static bool CheckSendNum(long taskid, int dayCeilingNum) + { + var today = HttpExtend.GetTimeStamp(DateTime.Today); + var db = ApiClient.GetSession(); + var daySendNum = db.Queryable().Count(f => f.taskid == taskid && f.issend && today <= f.sendtime); + return dayCeilingNum > daySendNum;//今天发送的数量比限定的少返回true + } + + /// + /// 取消任务 + /// + /// + public static void Abort(long id) + { + try + { + if (JobDic == null || JobDic.Count == 0) return; + if (!JobDic.ContainsKey(id)) return; + JobDic[id].Cancel(); + JobDic.Remove(id); + EventClient.OnEvent("取消任务", $"取消群发任务:{id}"); + } + catch (Exception ex) + { + EventClient.OnEvent("取消任务", $"取消群发任务异常:{ex.Message} - {ex.StackTrace}"); + } + } + + public static void AbortAll() + { + try + { + if (JobDic == null || JobDic.Count == 0) return; + foreach (var taskCancel in JobDic.Values) + { + taskCancel.Cancel(); + } + JobDic.Clear(); + EventClient.OnEvent("取消任务", $"取消所有群发任务"); + } + catch (Exception ex) + { + EventClient.OnEvent("取消任务", $"取消所有群发任务异常:{ex.Message} - {ex.StackTrace}"); + } + } + } + +} diff --git a/应用/EncourageUser/新建文本文档.txt b/应用/EncourageUser/新建文本文档.txt new file mode 100644 index 0000000..e69de29 diff --git a/应用/FissionData/CashForm.Designer.cs b/应用/FissionData/CashForm.Designer.cs new file mode 100644 index 0000000..2c4dfb9 --- /dev/null +++ b/应用/FissionData/CashForm.Designer.cs @@ -0,0 +1,168 @@ +namespace FissionData +{ + partial class CashForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(90, 116); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(84, 14); + this.labelControl1.TabIndex = 1; + this.labelControl1.Text = "兑换扣减人数:"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(191, 114); + this.numericUpDown1.Maximum = new decimal(new int[] { + 999999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(111, 22); + this.numericUpDown1.TabIndex = 2; + this.numericUpDown1.Value = new decimal(new int[] { + 5, + 0, + 0, + 0}); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(145, 163); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(146, 37); + this.simpleButton1.TabIndex = 3; + this.simpleButton1.Text = " 兑 换 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(90, 23); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(84, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "一共邀请人数:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(90, 54); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 1; + this.labelControl3.Text = "已经兑换人数:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(90, 85); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(84, 14); + this.labelControl4.TabIndex = 1; + this.labelControl4.Text = "可以兑换人数:"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(191, 23); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(7, 14); + this.labelControl5.TabIndex = 1; + this.labelControl5.Text = "0"; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(191, 54); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(7, 14); + this.labelControl6.TabIndex = 1; + this.labelControl6.Text = "0"; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(191, 85); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(7, 14); + this.labelControl7.TabIndex = 1; + this.labelControl7.Text = "0"; + // + // CashForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(422, 264); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.labelControl7); + this.Controls.Add(this.labelControl6); + this.Controls.Add(this.labelControl4); + this.Controls.Add(this.labelControl5); + this.Controls.Add(this.labelControl3); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.numericUpDown1); + this.Controls.Add(this.labelControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CashForm"; + this.Text = "兑换"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CashForm_FormClosing); + this.Load += new System.EventHandler(this.CashForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.LabelControl labelControl7; + } +} \ No newline at end of file diff --git a/应用/FissionData/CashForm.cs b/应用/FissionData/CashForm.cs new file mode 100644 index 0000000..05c6322 --- /dev/null +++ b/应用/FissionData/CashForm.cs @@ -0,0 +1,73 @@ +using Api.Framework; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FissionData +{ + public partial class CashForm : BaseForm + { + FissionClass fissionClass = null; + public CashForm(FissionClass fissionClass) + { + InitializeComponent(); + this.fissionClass = fissionClass; + } + + private void CashForm_Load(object sender, EventArgs e) + { + try + { + labelControl5.Text = fissionClass.invited.ToString(); + labelControl6.Text = fissionClass.consumed.ToString(); + labelControl7.Text = fissionClass.fle.ToString(); + numericUpDown1.Value = Class1.Config.cash_rule; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void CashForm_FormClosing(object sender, FormClosingEventArgs e) + { + Util.Save(Class1.Config); + } + + bool isSuccess = true; + private void simpleButton1_Click(object sender, EventArgs e) + { + if (!isSuccess) return; + isSuccess = false; + try + { + int num = (int)numericUpDown1.Value; + if (fissionClass.fle < num) throw new Exception("兑换人数不足"); + + fissionClass.fle -= num; + fissionClass.consumed += num; + + var session = ApiClient.GetSession(); + session.Updateable(fissionClass).ExecuteCommand(); + this.DialogResult = DialogResult.OK; + ShowSuccessAutoClose("兑换成功",3000); + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + isSuccess = true; + } + } + } +} diff --git a/应用/FissionData/CashForm.resx b/应用/FissionData/CashForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/FissionData/CashForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/FissionData/Class1.cs b/应用/FissionData/Class1.cs new file mode 100644 index 0000000..3a52d9a --- /dev/null +++ b/应用/FissionData/Class1.cs @@ -0,0 +1,244 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk.Implement; +using FissionData.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace FissionData +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = "裂变数据"; + this.Note = "随便啦"; + this.Logo = Resources.aaaaaaa; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + // public static VariateReplace variateReplace = null; + #endregion + + #region 默认 + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("groupid", "username"); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.WXNewMemerEvent += SDK_WXNewMemerEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + #endregion + + private void SDK_WXNewMemerEvent(object sender, Chat.Framework.WXSdk.Events.WXNewMemer e) + { + try + { + if (sender.GetType() != typeof(WXClientImpl_IPAD)) return; + var ipad = sender as WXClientImpl_IPAD; + if (ipad == null) throw new Exception(); + var session = ApiClient.GetSession(); + var group = ipad.GetContact(e.GroupId); + if (group == null) throw new Exception($"无法获取群{e.GroupId}信息"); + + var members = ipad.GetMembers(e.GroupId, true); + if (members == null) throw new Exception($"无法获取群{group.NickName}({e.GroupId})用户信息"); + + var fcList = session.Queryable().Where(f => f.groupid == e.GroupId).ToList(); + + #region 数据库中插入不存在的用户 + foreach (var item in members) + { + if (null == fcList.FirstOrDefault(f => f.username == item.Username)) + { + var member = new FissionClass() { groupid = e.GroupId, groupnick = group.NickName, username = item.Username, nickname = Util.RemoveEmoji(item.NickName), logo = item.SmallHeadImgUrl, invitername = item.InviterUserName, GetIn = DateTime.Now, CurrentState = MemState.新人保护未发言 }; + + session.Insertable(member).ExecuteCommand(); + } + } + #endregion + + #region 重新计算邀请人数 + members = members.Where(f => !string.IsNullOrWhiteSpace(f.InviterUserName)).ToArray(); + var inviterUserNames = members.GroupBy(f => f.InviterUserName).Select(f => f.Key).ToList(); + + foreach (var username in inviterUserNames) + { + var fc = fcList.FirstOrDefault(f => f.username == username); + if (fc == null) continue; + fc.invited = members.Count(f => f.InviterUserName == username); + fc.fle = fc.invited - fc.consumed; + session.Saveable(fc).ExecuteCommand(); + } + #endregion + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} - {ex.StackTrace}"); + } + } + + private static object _lock1 = new object(); + + private static object _lock2 = new object(); + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + if (string.IsNullOrWhiteSpace(e.Groupid)) return; + if (sender.GetType() != typeof(WXClientImpl_IPAD)) return; + var ipad = sender as WXClientImpl_IPAD; + if (ipad == null) return; + + var mess = e.Message.Trim(); + + var session = ApiClient.GetSession(); + + #region 已拍 + if (!string.IsNullOrWhiteSpace(Config.cmd) && Regex.IsMatch(mess, Config.cmd)) + { + lock (_lock1) + { + var groupTemp = session.FindSingle("groupid = @groupid", new { groupid = e.Groupid }); + + var group = ipad.GetContact(e.Groupid); + if (group == null) throw new Exception($"无法获取群{e.Groupid}信息"); + + if (groupTemp == null)//数据中不存在该群,获取群用户列表进行保存 + { + var members = ipad.GetMembers(e.Groupid, true); + if (members == null) throw new Exception($"无法获取群{group.NickName}({e.Groupid})用户信息"); + + foreach (var item in members) + { + var member = new FissionClass() { groupid = e.Groupid, groupnick = group.NickName, username = item.Username, nickname = Util.RemoveEmoji(item.NickName), logo = item.SmallHeadImgUrl, invitername = item.InviterUserName, GetIn = DateTime.Now, CurrentState = MemState.新人保护未发言 }; + + if (item.Username == e.Username) + { + member.CurrentState = MemState.新人保护未拍单; + member.paidCnt++; + member.lastPr = DateTime.Now; + member.lastTime = DateTime.Now; + } + session.Insertable(member).ExecuteCommand(); + } + } + else + { + var member = session.FindSingle("groupid = @groupid and username = @username", new { groupid = e.Groupid, username = e.Username }); + if (member == null)//用户不存在,添加用户 + { + var memberTemp = ipad.GetMember(e.Groupid, e.Username); + if (memberTemp == null) throw new Exception($"获取群 {group.NickName}({e.Groupid})成员 {e.NickName}({e.Username})失败"); + + member = new FissionClass() { groupid = e.Groupid, username = memberTemp.Username, nickname = Util.RemoveEmoji(memberTemp.NickName), logo = memberTemp.SmallHeadImgUrl, invitername = memberTemp.InviterUserName, GetIn = DateTime.Now, paidCnt = 1, lastPr = DateTime.Now, lastTime = DateTime.Now, CurrentState = MemState.新人保护未拍单 }; + } + else + { + if (member.lastTime >= DateTime.Now.AddMinutes(-Config.valid_send_interval)) return; + + member.paidCnt++; + member.lastTime = DateTime.Now; + } + session.Saveable(member).ExecuteCommand(); + } + } + } + #endregion + + #region 统计 + if (!string.IsNullOrWhiteSpace(Config.query_cmd) && Regex.IsMatch(mess, Config.query_cmd)) + { + lock (_lock2) + { + var groupTemp = session.FindSingle("groupid = @groupid", new { groupid = e.Groupid }); + + var group = ipad.GetContact(e.Groupid); + if (group == null) throw new Exception($"无法获取群{e.Groupid}信息"); + + if (groupTemp == null)//数据中不存在该群,获取群用户列表进行保存 + { + var members = ipad.GetMembers(e.Groupid, true); + if (members == null) throw new Exception($"无法获取群{group.NickName}({e.Groupid})用户信息"); + + foreach (var item in members) + { + var _member = new FissionClass() { groupid = e.Groupid, groupnick = group.NickName, username = item.Username, nickname = Util.RemoveEmoji(item.NickName), logo = item.SmallHeadImgUrl, invitername = item.InviterUserName, GetIn = DateTime.Now, CurrentState = MemState.新人保护未发言 }; + session.Insertable(_member).ExecuteCommand(); + } + } + + var member = session.FindSingle("groupid = @groupid and username = @username", new { groupid = e.Groupid, username = e.Username }); + if (member == null) return; + e.SendMessage(new VariateReplace().CommonReplace(Config.msg_statistic.Replace("[邀请人数]", member.invited.ToString()).Replace("[已拍数量]", member.paidCnt.ToString()).Replace("[有效积分]", member.fle.ToString()).Replace("[编码]", e.GetMemberinfo().id.ToString()), e.GetMemberinfo())); + } + } + #endregion + + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} - {ex.StackTrace}"); + } + } + + } +} diff --git a/应用/FissionData/Config.cs b/应用/FissionData/Config.cs new file mode 100644 index 0000000..7e89b3e --- /dev/null +++ b/应用/FissionData/Config.cs @@ -0,0 +1,74 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace FissionData +{ + + [Config(Name = "插件-裂变数据-配置")] + public class Config + { + /// + /// 指令 + /// + [ + Category("1)、基础设置"), DisplayName("01.已拍指令"), DefaultValue(@"^已拍$"), Description(@"用户发送的指令,正则表达式") + ] + public string cmd { get; set; } = @"^已拍$"; + + /// + /// 规则 有效已拍间隔(与上次间隔时间超过为有效) + /// + [ + Category("1)、基础设置"), DisplayName("02.有效已拍间隔"), DefaultValue(5), Description(@"单位/分钟 +与上次发送已拍指令时间的间隔,超过为有效,以内为无效") + ] + public int valid_send_interval { get; set; } = 5; + + /// + /// 查询邀请指令 + /// + [ + Category("1)、基础设置"), DisplayName("03.查询邀请指令"), DefaultValue(@"^统计$"), Description(@"统计邀请的人数等信息,正则表达式") + ] + public string query_cmd { get; set; } + + /// + /// 邀请量 + /// + [ + Category("1)、基础设置"), DisplayName("04.邀请统计回复"), DefaultValue(@"邀请人数:[邀请人数] 人 +有效积分:[有效积分] 积分 +已拍数量:[已拍数量] 件 +—————————— +邀请1人,获得1积分,积分可以兑换活动免单礼物哦!"), Description(@"邀请统计回复语 +变量:[有效积分]、[已拍数量]、[邀请人数]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string msg_statistic { get; set; } = @"邀请人数:[邀请人数] 人 +有效积分:[有效积分] 积分 +已拍数量:[已拍数量] 件 +—————————— +邀请1人,获得1积分,积分可以兑换活动免单礼物哦!"; + + /// + /// 规则 未付款天数 + /// + [ + Category("1)、基础设置"), DisplayName("05.未派单天数"), DefaultValue(60), Description(@"发送已拍的间隔") + ] + public int unpay_day { get; set; } = 60; + + /// + /// 兑换上次数量 + /// + [Browsable(false)] + public int cash_rule { get; set; } = 5; + + } +} diff --git a/应用/FissionData/FissionClass.cs b/应用/FissionData/FissionClass.cs new file mode 100644 index 0000000..9c0d609 --- /dev/null +++ b/应用/FissionData/FissionClass.cs @@ -0,0 +1,105 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FissionData +{ + public class FissionClass : base_model + { + /// + /// 群id + /// + public string groupid { get; set; } + + /// + /// 群昵称 + /// + public string groupnick { get; set; } + + /// + /// 用户账号 + /// + public string username { get; set; } + /// + /// 用户昵称 + /// + public string nickname { get; set; } + /// + /// 用户头像 + /// + public string logo { get; set; } + /// + /// 上级id + /// + public string invitername { get; set; } + /// + /// 白名单 + /// + public bool white { get; set; } + /// + /// 拍单次数 + /// + public int paidCnt { get; set; } + /// + /// 最后一次拍单时间 + /// + public DateTime lastPr { get; set; } + /// + /// 黑名单 + /// + public bool black { get; set; } + + /// + /// 邀请人数 + /// + public int invited { get; set; } + + /// + /// 兑换人数 + /// + public int consumed { get; set; } + + /// + /// 剩余人数 + /// + public int fle { get; set; } + + /// + /// 最后拍单时间 + /// + public DateTime lastTime { get; set; } + + /// + /// 兑换次数 + /// + public int consumeTime { get; set; } + + /// + /// 进群时间 + /// + public DateTime GetIn { get; set; } + + public MemState CurrentState { get; set; } + + } + + public enum MemState + { + 新人保护未发言, + 新人保护未拍单, + 黑名单, + 白名单, + 长时间未拍 //2月 + } + + public class GroupInfo + { + public string groupid { get; set; } + public string groupnick { get; set; } + } + + +} diff --git a/应用/FissionData/FissionData.csproj b/应用/FissionData/FissionData.csproj new file mode 100644 index 0000000..2ccc269 --- /dev/null +++ b/应用/FissionData/FissionData.csproj @@ -0,0 +1,127 @@ + + + + + Debug + AnyCPU + {2DAF9579-77B2-44E2-B359-887D8FA01EE5} + Library + Properties + FissionData + FissionData + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + Form + + + CashForm.cs + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + CashForm.cs + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/FissionData/MainForm.Designer.cs b/应用/FissionData/MainForm.Designer.cs new file mode 100644 index 0000000..aa9f958 --- /dev/null +++ b/应用/FissionData/MainForm.Designer.cs @@ -0,0 +1,562 @@ +namespace FissionData +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.查看用户ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(895, 596); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + this.xtraTabControl1.Selected += new DevExpress.XtraTab.TabPageEventHandler(this.xtraTabControl1_Selected); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.textEdit1); + this.xtraTabPage1.Controls.Add(this.labelControl1); + this.xtraTabPage1.Controls.Add(this.simpleButton1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(893, 572); + this.xtraTabPage1.Text = " 数 据 列 表 "; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(315, 27); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(290, 20); + this.textEdit1.TabIndex = 36; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl1.Location = new System.Drawing.Point(203, 30); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(106, 14); + this.labelControl1.TabIndex = 35; + this.labelControl1.Text = "群信息(为空所有):"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(716, 20); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(93, 35); + this.simpleButton1.TabIndex = 15; + this.simpleButton1.Text = " 查 询 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(0, 71); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(894, 502); + this.gridControl1.TabIndex = 7; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.查看用户ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(137, 26); + // + // 查看用户ToolStripMenuItem + // + this.查看用户ToolStripMenuItem.Name = "查看用户ToolStripMenuItem"; + this.查看用户ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.查看用户ToolStripMenuItem.Text = "查看群用户"; + this.查看用户ToolStripMenuItem.Click += new System.EventHandler(this.查看用户ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn2, + this.gridColumn3}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "群账号"; + this.gridColumn2.FieldName = "groupid"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 0; + this.gridColumn2.Width = 272; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "群昵称"; + this.gridColumn3.FieldName = "groupnick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 1; + this.gridColumn3.Width = 233; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(893, 572); + this.xtraTabPage2.Text = " 基 础 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(893, 572); + this.settingControl1.TabIndex = 1; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.textEdit3); + this.xtraTabPage3.Controls.Add(this.labelControl4); + this.xtraTabPage3.Controls.Add(this.textEdit2); + this.xtraTabPage3.Controls.Add(this.labelControl3); + this.xtraTabPage3.Controls.Add(this.simpleButton2); + this.xtraTabPage3.Controls.Add(this.pageControl2); + this.xtraTabPage3.Controls.Add(this.gridControl2); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(893, 572); + this.xtraTabPage3.Text = " 用 户 信 息 "; + // + // textEdit3 + // + this.textEdit3.Location = new System.Drawing.Point(500, 20); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Size = new System.Drawing.Size(185, 20); + this.textEdit3.TabIndex = 45; + // + // labelControl4 + // + this.labelControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl4.Location = new System.Drawing.Point(376, 23); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(118, 14); + this.labelControl4.TabIndex = 44; + this.labelControl4.Text = "用户信息(为空所有):"; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(175, 20); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(180, 20); + this.textEdit2.TabIndex = 43; + // + // labelControl3 + // + this.labelControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.labelControl3.Location = new System.Drawing.Point(63, 23); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(94, 14); + this.labelControl3.TabIndex = 42; + this.labelControl3.Text = "群信息(可为空):"; + // + // simpleButton2 + // + this.simpleButton2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(750, 13); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(93, 35); + this.simpleButton2.TabIndex = 40; + this.simpleButton2.Text = " 查 询 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // pageControl2 + // + this.pageControl2.Location = new System.Drawing.Point(-1, 528); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(894, 34); + this.pageControl2.TabIndex = 38; + // + // gridControl2 + // + this.gridControl2.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl2.Location = new System.Drawing.Point(-1, 61); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(894, 461); + this.gridControl2.TabIndex = 37; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn4, + this.gridColumn9, + this.gridColumn8, + this.gridColumn11, + this.gridColumn14, + this.gridColumn15, + this.gridColumn16, + this.gridColumn17, + this.gridColumn19, + this.gridColumn18, + this.gridColumn12, + this.gridColumn7, + this.gridColumn10}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ColumnAutoWidth = false; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "ID"; + this.gridColumn4.FieldName = "id"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 0; + this.gridColumn4.Width = 50; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "群账号"; + this.gridColumn10.FieldName = "groupid"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 1; + this.gridColumn10.Width = 93; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "群昵称"; + this.gridColumn7.FieldName = "groupnick"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 2; + this.gridColumn7.Width = 96; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "用户账号"; + this.gridColumn9.FieldName = "username"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.OptionsColumn.AllowFocus = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 3; + this.gridColumn9.Width = 87; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "用户昵称"; + this.gridColumn8.FieldName = "nickname"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 4; + this.gridColumn8.Width = 103; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn11.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn11.AppearanceCell.Options.UseFont = true; + this.gridColumn11.AppearanceCell.Options.UseForeColor = true; + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "拍单数量"; + this.gridColumn11.FieldName = "paidCnt"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 5; + this.gridColumn11.Width = 78; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn12.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn12.AppearanceCell.Options.UseFont = true; + this.gridColumn12.AppearanceCell.Options.UseForeColor = true; + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "最后拍单时间"; + this.gridColumn12.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn12.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn12.FieldName = "lastPr"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 6; + this.gridColumn12.Width = 105; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "邀请人数"; + this.gridColumn14.FieldName = "invited"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 7; + this.gridColumn14.Width = 112; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "兑换人数"; + this.gridColumn15.FieldName = "consumed"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 8; + this.gridColumn15.Width = 62; + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "剩余人数"; + this.gridColumn16.FieldName = "fle"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 9; + this.gridColumn16.Width = 65; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "兑换次数"; + this.gridColumn17.FieldName = "consumeTime"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 10; + this.gridColumn17.Width = 72; + // + // gridColumn19 + // + this.gridColumn19.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn19.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn19.Caption = "当前状态"; + this.gridColumn19.FieldName = "CurrentState"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 11; + this.gridColumn19.Width = 74; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "进群时间"; + this.gridColumn18.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn18.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn18.FieldName = "GetIn"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.OptionsColumn.AllowEdit = false; + this.gridColumn18.OptionsColumn.AllowFocus = false; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 12; + this.gridColumn18.Width = 129; + // + // contextMenuStrip2 + // + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1}); + this.contextMenuStrip2.Name = "contextMenuStrip1"; + this.contextMenuStrip2.Size = new System.Drawing.Size(181, 48); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(180, 22); + this.toolStripMenuItem1.Text = "兑换"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(895, 596); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = " 裂 变 数 据 "; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage3.ResumeLayout(false); + this.xtraTabPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraEditors.TextEdit textEdit3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 查看用户ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + } +} \ No newline at end of file diff --git a/应用/FissionData/MainForm.cs b/应用/FissionData/MainForm.cs new file mode 100644 index 0000000..535418d --- /dev/null +++ b/应用/FissionData/MainForm.cs @@ -0,0 +1,259 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using DevExpress.XtraTab; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace FissionData +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + + + this.pageControl2.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + + var map = session.NewParamMap(); + map.setPageParamters(index, pagesize); + + var sql = "select * from FissionClass where 1 = 1 "; + var groupkey = textEdit2.Text.Trim(); + var friendkey = textEdit3.Text.Trim(); + + var flag = false; + if (!string.IsNullOrWhiteSpace(friendkey))//判断是否是用户数据id + { + var uid = 0; + if (int.TryParse(friendkey, out uid)) + { + var member = session.FindMemberInfoById(uid); + if (member != null) + { + flag = true; + if (string.IsNullOrWhiteSpace(groupkey)) + sql += $"and username = '{member.username}'"; + else + sql += $"and (groupid like '%{groupkey}%' or groupnick like '%{groupkey}%') and username = '{member.username}'"; + } + } + } + + if (!flag) + { + if (string.IsNullOrWhiteSpace(groupkey) && !string.IsNullOrWhiteSpace(friendkey)) + sql += $"and (username like '%{friendkey}%' or nickname like '%{friendkey}%')"; + else if (!string.IsNullOrWhiteSpace(groupkey) && string.IsNullOrWhiteSpace(friendkey)) + sql += $"and (groupid like '%{groupkey}%' or groupnick like '%{groupkey}%')"; + else if (!string.IsNullOrWhiteSpace(groupkey) && !string.IsNullOrWhiteSpace(friendkey)) + sql += $"and (groupid like '%{groupkey}%' or groupnick like '%{groupkey}%') and (username like '%{friendkey}%' or nickname like '%{friendkey}%')"; + } + PageResult result = session.FindPage(sql, map); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + }, this.gridControl2, 100, false, true); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + UpdateWxList(); + + settingControl1.Bind(Class1.Config, 100); + } + + public void UpdateWxList() + { + try + { + //comboBoxEdit1.Properties.Items.Clear(); + //comboBoxEdit1.Properties.Items.Add("全部机器人"); + //var wxs = Chat.Framework.ChatClient.WXClient.Values.Where(f => f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + + //var groupInfoList = new List() { "全部机器人" }; + //foreach (var wx in wxs) + //{ + // comboBoxEdit1.Properties.Items.Add($"{wx.User.Nick}({wx.WeixinHao})"); + // groupInfoList.Add(wx.WeixinHao); + //} + //comboBoxEdit1.Tag = groupInfoList; + //if (comboBoxEdit1.Properties.Items.Count != 0) + // comboBoxEdit1.SelectedIndex = 0; + } + catch (Exception ex) + { } + } + + private void xtraTabControl1_Selected(object sender, TabPageEventArgs e) + { + if (e.PageIndex == 2) + pageControl2.Go(sender, e); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + + //var groupList = comboBoxEdit1.Tag as List; + + //var groupInfos = new List(); + + //if (comboBoxEdit1.SelectedIndex == 0) + //{ + //var wxs = Chat.Framework.ChatClient.WXClient.Values.Where(f => f.WeixinType == WeixinType.Grpc微信 && f.Status == WxStatus.在线); + + //foreach (var wx in wxs) + //{ + // groupInfos.AddRange(GroupParse(wx)); + //} + //} + // else + // { + // var wx = Chat.Framework.ChatClient.WXClient.Values.First(f => f.WeixinType == WeixinType.Grpc微信 && f.Status == WxStatus.在线 && f.WeixinHao == groupList[comboBoxEdit1.SelectedIndex]); + // if (wx == null) throw new Exception("微信不在线"); + // groupInfos.AddRange(GroupParse(wx)); + //} + + + var groupInfos = new List(); + + var key = textEdit1.Text.Trim(); + + if (string.IsNullOrWhiteSpace(key)) + groupInfos = session.Queryable().GroupBy(f => f.groupid).Select(z => new GroupInfo() { groupid = z.groupid, groupnick = z.groupnick }).ToList(); + else + groupInfos = session.Queryable().Where(f => f.groupid.Contains(key) || f.groupnick.Contains(key)).GroupBy(f => f.groupid).Select(z => new GroupInfo() { groupid = z.groupid, groupnick = z.groupnick }).ToList(); + + gridControl1.DataSource = groupInfos; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + //public List GroupParse(WeixinBase wx) + //{ + // var groupInfos = new List(); + // try + // { + // var ipad = wx as WXClientImpl_IPAD; + // if (ipad == null) return null; + // ipad.GetContact + + + + // if (ipad.Friends.Count == 0) { } + + // var temps = ipad.Friends.Values.Where(f => f.UserName.Contains("@chatroom")); + // foreach (var item in temps) + // { + // groupInfos.Add(new GroupInfo() { robotname = ipad.WeixinHao, robotnick = ipad.User.Nick, groupid = item.UserName, groupnick = item.NickName }); + // } + // } + // catch (Exception ex) + // { } + // return groupInfos; + //} + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Util.Save(Class1.Config); + } + + private void 查看用户ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows == null || rows.Length <= 0) throw new Exception("获取数据异常"); + + //var username = gridView1.GetRowCellValue(rows[0], "robotname").ToString(); + //var robotnick = gridView1.GetRowCellValue(rows[0], "robotnick").ToString(); + var groupid = gridView1.GetRowCellValue(rows[0], "groupid").ToString(); + //var groupnick = gridView1.GetRowCellValue(rows[0], "groupnick").ToString(); + + xtraTabControl1.SelectedTabPageIndex = 2; + + textEdit2.Text = groupid; + textEdit3.Text = string.Empty; + + simpleButton2_Click(null, null); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + pageControl2.Go(sender, e); + } + + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView2.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = this.gridView2.GetRow(rows[0]) as FissionClass; + + var cashForm = new CashForm(row); + if (cashForm.ShowDialog() == DialogResult.OK) + { + pageControl2.Go(sender, e); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} diff --git a/应用/FissionData/MainForm.resx b/应用/FissionData/MainForm.resx new file mode 100644 index 0000000..5154bd4 --- /dev/null +++ b/应用/FissionData/MainForm.resx @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAAJmUlEQVRYR51XB1RUZxZ+lsTNrq51w5ZEjSYmujmWJMcSNEERBFFQUWNfexRF + F0FUIg6IggPSiwyKo6gURVQEUXpHQbGNNOltYGaAoTf12/s/GY4oErPfOd95vP/dud/333v/NwP3B9Dv + d/j/A0CvJKiS9ycOIA4kfkT8uOvKyNbYcz62tzwe5xLoUR/o7UMElnCAueDUMA9xzEof/5TA0wFpmT7+ + aXLRpbSmU37JDz3PJ4SePBWxaY+54z8olpliJt8x4eIbS8t9QBWou8Wf3fI71tRZOcjLL9H47OX06sT0 + ApRU1KK1rYPCXqOltYNfi0t7DtHF5AYHr1sCXYONI+izrCp8RSiMz+soiqbbPqAKJPDih476qnlfTE5M + uJuP5pbXop2dr9BCBhqa26FsbEN9Uzs966T1l7yx6OQcnBRFPtuxz34i5WDV6DYh9LxNf/YBFsRI6G9p + e/5TkX9qXnZBNdNFR8cLPMuXw0Wciu2HQ6Gz+SL0tgdg7/FIiIIeIbe4FnUNbWhvp7jcSjiJomQ7TR2n + UC7eBMtr6xbOcr8fXeL9NLQMB7mLE+Ky8qp48Za2TpwNfgDN9WLom0Vj7fFMbHPLx3biZvsn+M/RVKwz + D0dIVB5qG1r56khyK3DU6UbWIsMd/6ScbED7WTveYPn7BD9wTqJI49jkPF68nnZlJLiB+VsDcS2uAoUl + LcguaEZ4Wi3MxSUwFhVjj08JdnnkYbMgDnY+9yCrbeFbczPqEQ4e83ehnJ+wvJbCEKbRJ/pt32M33EMc + X93Y1Ia29k5Yu8dgodFVVFe3QSFvR0VlKwrIxNPnTUh53ADBpXKY+ZZg/9lSHBCXYrcwFb5XJZApm1Gj + bIGN840Ow7Wm31BuNpRsg+8FP3h2bmGbohKz8OoVkJklxZzVYkRnKLrE23hxCYnfz2pE0uN6XIqRw8Kv + DIcvlPMUXq7ANstoZBfWQKpowrVb92FscVpIuVkV+scLNLjeyMCXnwYlML9YRhPdiRM+SdA3j0Y57bpb + PJ/Es1+LRz9Q4ia1QuBP/Q6ohE1gJYTBUhw58xTnQrNQVdOMJ9nl2HNYfJ9yD2b5yy9rcir2ZmDgMZew + bHa22USvMrmC1Q4PUVDagnxWdiaeQ+JPSDyzDrfS63A1pQbHgythG0LiRIfrUniGleGgWypkdS0orVRS + BcRNI0b9i70bBv6egY+Ou4bVs+GrJvfzt53HJu/nuJVRy4tn5DQgSULiD+sQnlGHa3drII6TQXhDCoeb + UpwMk8LplhR+CTLstI2Dor4VJdIG7LEQ44cf9UczA0ynLwMfWzlcq2f9r5A3QnvnRWwS5eDg5RIkPVMi + UaJEFImHPahFSHotAtIUcLxThZO3q+ASWQXXqCp4xspwida3C2MgV1Lbyuux0/wMflA3GEf5+UHsswIH + bIKK2QkorW7EBjp+GzyfYMeFApgHl+BcsgxXM2oQQDs/k1QN+zu082gSj6uGW3w1PBNlOHdPAd/EChzw + TkEVHUdJvgwbd7t1DB2uNpLyD7R2ucNF+J7gDbgIvd41YHLELzyLXiJlska4Xr6PFfaJ2BFQAOPgIphe + K8Khm6UQRJTDJrICwjgpnMmIOxnzSpVDdE+OEKqS3bVnOBeZg3J5M2JS87B6m8Mzyv1XIm9AZcLKMYxz + czjVw8DAneaivZdD7/IT/KhAAQOLEPwamAfjkEKYhhbBIoIMRJXjeFw5HJIq4ZJWDY97Mng/kCMoi1qT + VYNtLnHIodIXSevheS4SBmsEHpT7L8QBKgOMzICLfU8DA7T1f1UzsTzfLJU3oKSqER7XM7HOOQYmN4tg + FkEViCQDsWU4nlQB+7RKuGZUw/uxHIG5tQgtVOLgpXSIY7JRVdeKzOwqrDdyeTH9p7U/Uu4/Efu/acD+ + mFuPFjDwbdi421VwITiBBkiJKhqkI+eTscE1mnafD0FcGQTxZCClHM73pTj9VI4r+XW4KJHCxC8NtsEZ + qGnuQF6Zkr6QwqGz/FAM5fwbcRDLb+V0+3ULzth3i79tYMC0GXojNuxyexabkoWcUvqWa3mB4JTnWC0M + w77AB7BPKICvRA6/bAU875XCOuwJNrtH43p6ERrbXyK/oh5BYfexbL01tJcdqJ04VW8W5WUvIv4YhvvY + 8UOYckKPS7Yj2urRMoGOP7vwVdBcZDSRprfmTqIE2cV1kDW0o5AG80yUBKa+8Vhx4iZWkqH94mSIY7NR + JG+CsrkTuaVKXLn1gPp+FL5+oUhIlWDVVkf59+qrephgBhKP6XIJNrpcvI0OLRGYgS4T7EfExxp6RlOW + bbTNdfYJR7qkki+rnIywXba+AM/GjpeoaexAobSRjznmEoIFy3+D1hIz+PjFoPPFS9zNLMDKLc7NWvP0 + e5iItVrAxVhpczECbbolvGGAVYE3MWmaltrCXw57/bJV2Cr0CMXV2w/xMFeOR/kKPHrOKEcwrTFh/TXW + mL3AOGK27r7avZYBWL7FGeKAJLBTlZseiiiLnxV7tcerU94hRP6ldMdCk7tzSJP+JKgM1Lf3MMHcfjJ5 + +pIJcxeb2sxfcjB5geFvrVpLLTDP4BA0iRp6ZunqWrtOTvpu8QyKHTX+W111LcOjchOrYOissEFaZADQ + LoPy7glE7FdXGGmMnU1x3SbCzH6mC0Fl4E0S+MEksmB2lNh5Zi+VocRhXWT3bJ09Z9M+eMLkxbPmGlg1 + +7vZodhbEy0Sd95EbZodbvx3pmKr+udzKI6Z4NtB5DjdFUc4neWWnNayw5w2UXOJBUe7pOsh9lhVEdX/ + BW+T/yneRXY/+Psps2cFbZ+sKL6yFkVeGmh56vbaxF1bBO+crtg254uZFPdnIsv7YVB9kbyPZUFzWVi3 + iQ3fqamfXz9RURS0DgUeP3WbKAg1x9kN0xIpZnhX7IehN9G3WRbQw8SQFf8eOdt7+ZeKwsA11A4tvh2v + 2mQQr52ipOejiKy9H4beBMuvvLvWBWaCJR+iP37oHCe9MYoMj2WoCNmCvHB7uC+d9McrcHr519xpwwmc + z9IJnIhxyVect8FX3Cn9LzmvxeM5way/c0dmqnGWM9S4w9PV2Ee6TeiMGTLTZOqoeCet0R22Gp/FGH77 + 6TRa538rEj8MXovGc54k5LFoHOexcBznrvsF50Z01RnLuS4Yy+2fOoozmzqSM51CnDyS20ckqNrBBo7t + mJWdXfmf60T2/MPgqj2Wc9Yaw9Np/mjOSXM05zjvc+7kXKLGZ5zxxGHcbsZvhnG7GL8eyhlNYKeUF1G9 + V1hF2JXd93OcN5b7H1cpDdS8q/oNAAAAAElFTkSuQmCC + + + + 274, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAAJmUlEQVRYR51XB1RUZxZ+lsTNrq51w5ZEjSYmujmWJMcSNEERBFFQUWNfexRF + F0FUIg6IggPSiwyKo6gURVQEUXpHQbGNNOltYGaAoTf12/s/GY4oErPfOd95vP/dud/333v/NwP3B9Dv + d/j/A0CvJKiS9ycOIA4kfkT8uOvKyNbYcz62tzwe5xLoUR/o7UMElnCAueDUMA9xzEof/5TA0wFpmT7+ + aXLRpbSmU37JDz3PJ4SePBWxaY+54z8olpliJt8x4eIbS8t9QBWou8Wf3fI71tRZOcjLL9H47OX06sT0 + ApRU1KK1rYPCXqOltYNfi0t7DtHF5AYHr1sCXYONI+izrCp8RSiMz+soiqbbPqAKJPDih476qnlfTE5M + uJuP5pbXop2dr9BCBhqa26FsbEN9Uzs966T1l7yx6OQcnBRFPtuxz34i5WDV6DYh9LxNf/YBFsRI6G9p + e/5TkX9qXnZBNdNFR8cLPMuXw0Wciu2HQ6Gz+SL0tgdg7/FIiIIeIbe4FnUNbWhvp7jcSjiJomQ7TR2n + UC7eBMtr6xbOcr8fXeL9NLQMB7mLE+Ky8qp48Za2TpwNfgDN9WLom0Vj7fFMbHPLx3biZvsn+M/RVKwz + D0dIVB5qG1r56khyK3DU6UbWIsMd/6ScbED7WTveYPn7BD9wTqJI49jkPF68nnZlJLiB+VsDcS2uAoUl + LcguaEZ4Wi3MxSUwFhVjj08JdnnkYbMgDnY+9yCrbeFbczPqEQ4e83ehnJ+wvJbCEKbRJ/pt32M33EMc + X93Y1Ia29k5Yu8dgodFVVFe3QSFvR0VlKwrIxNPnTUh53ADBpXKY+ZZg/9lSHBCXYrcwFb5XJZApm1Gj + bIGN840Ow7Wm31BuNpRsg+8FP3h2bmGbohKz8OoVkJklxZzVYkRnKLrE23hxCYnfz2pE0uN6XIqRw8Kv + DIcvlPMUXq7ANstoZBfWQKpowrVb92FscVpIuVkV+scLNLjeyMCXnwYlML9YRhPdiRM+SdA3j0Y57bpb + PJ/Es1+LRz9Q4ia1QuBP/Q6ohE1gJYTBUhw58xTnQrNQVdOMJ9nl2HNYfJ9yD2b5yy9rcir2ZmDgMZew + bHa22USvMrmC1Q4PUVDagnxWdiaeQ+JPSDyzDrfS63A1pQbHgythG0LiRIfrUniGleGgWypkdS0orVRS + BcRNI0b9i70bBv6egY+Ou4bVs+GrJvfzt53HJu/nuJVRy4tn5DQgSULiD+sQnlGHa3drII6TQXhDCoeb + UpwMk8LplhR+CTLstI2Dor4VJdIG7LEQ44cf9UczA0ynLwMfWzlcq2f9r5A3QnvnRWwS5eDg5RIkPVMi + UaJEFImHPahFSHotAtIUcLxThZO3q+ASWQXXqCp4xspwida3C2MgV1Lbyuux0/wMflA3GEf5+UHsswIH + bIKK2QkorW7EBjp+GzyfYMeFApgHl+BcsgxXM2oQQDs/k1QN+zu082gSj6uGW3w1PBNlOHdPAd/EChzw + TkEVHUdJvgwbd7t1DB2uNpLyD7R2ucNF+J7gDbgIvd41YHLELzyLXiJlska4Xr6PFfaJ2BFQAOPgIphe + K8Khm6UQRJTDJrICwjgpnMmIOxnzSpVDdE+OEKqS3bVnOBeZg3J5M2JS87B6m8Mzyv1XIm9AZcLKMYxz + czjVw8DAneaivZdD7/IT/KhAAQOLEPwamAfjkEKYhhbBIoIMRJXjeFw5HJIq4ZJWDY97Mng/kCMoi1qT + VYNtLnHIodIXSevheS4SBmsEHpT7L8QBKgOMzICLfU8DA7T1f1UzsTzfLJU3oKSqER7XM7HOOQYmN4tg + FkEViCQDsWU4nlQB+7RKuGZUw/uxHIG5tQgtVOLgpXSIY7JRVdeKzOwqrDdyeTH9p7U/Uu4/Efu/acD+ + mFuPFjDwbdi421VwITiBBkiJKhqkI+eTscE1mnafD0FcGQTxZCClHM73pTj9VI4r+XW4KJHCxC8NtsEZ + qGnuQF6Zkr6QwqGz/FAM5fwbcRDLb+V0+3ULzth3i79tYMC0GXojNuxyexabkoWcUvqWa3mB4JTnWC0M + w77AB7BPKICvRA6/bAU875XCOuwJNrtH43p6ERrbXyK/oh5BYfexbL01tJcdqJ04VW8W5WUvIv4YhvvY + 8UOYckKPS7Yj2urRMoGOP7vwVdBcZDSRprfmTqIE2cV1kDW0o5AG80yUBKa+8Vhx4iZWkqH94mSIY7NR + JG+CsrkTuaVKXLn1gPp+FL5+oUhIlWDVVkf59+qrephgBhKP6XIJNrpcvI0OLRGYgS4T7EfExxp6RlOW + bbTNdfYJR7qkki+rnIywXba+AM/GjpeoaexAobSRjznmEoIFy3+D1hIz+PjFoPPFS9zNLMDKLc7NWvP0 + e5iItVrAxVhpczECbbolvGGAVYE3MWmaltrCXw57/bJV2Cr0CMXV2w/xMFeOR/kKPHrOKEcwrTFh/TXW + mL3AOGK27r7avZYBWL7FGeKAJLBTlZseiiiLnxV7tcerU94hRP6ldMdCk7tzSJP+JKgM1Lf3MMHcfjJ5 + +pIJcxeb2sxfcjB5geFvrVpLLTDP4BA0iRp6ZunqWrtOTvpu8QyKHTX+W111LcOjchOrYOissEFaZADQ + LoPy7glE7FdXGGmMnU1x3SbCzH6mC0Fl4E0S+MEksmB2lNh5Zi+VocRhXWT3bJ09Z9M+eMLkxbPmGlg1 + +7vZodhbEy0Sd95EbZodbvx3pmKr+udzKI6Z4NtB5DjdFUc4neWWnNayw5w2UXOJBUe7pOsh9lhVEdX/ + BW+T/yneRXY/+Psps2cFbZ+sKL6yFkVeGmh56vbaxF1bBO+crtg254uZFPdnIsv7YVB9kbyPZUFzWVi3 + iQ3fqamfXz9RURS0DgUeP3WbKAg1x9kN0xIpZnhX7IehN9G3WRbQw8SQFf8eOdt7+ZeKwsA11A4tvh2v + 2mQQr52ipOejiKy9H4beBMuvvLvWBWaCJR+iP37oHCe9MYoMj2WoCNmCvHB7uC+d9McrcHr519xpwwmc + z9IJnIhxyVect8FX3Cn9LzmvxeM5way/c0dmqnGWM9S4w9PV2Ee6TeiMGTLTZOqoeCet0R22Gp/FGH77 + 6TRa538rEj8MXovGc54k5LFoHOexcBznrvsF50Z01RnLuS4Yy+2fOoozmzqSM51CnDyS20ckqNrBBo7t + mJWdXfmf60T2/MPgqj2Wc9Yaw9Np/mjOSXM05zjvc+7kXKLGZ5zxxGHcbsZvhnG7GL8eyhlNYKeUF1G9 + V1hF2JXd93OcN5b7H1cpDdS8q/oNAAAAAElFTkSuQmCC + + + + 109, 17 + + \ No newline at end of file diff --git a/应用/FissionData/Properties/AssemblyInfo.cs b/应用/FissionData/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..800ea3a --- /dev/null +++ b/应用/FissionData/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("FissionData")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FissionData")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("2daf9579-77b2-44e2-b359-887d8fa01ee5")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/FissionData/Properties/Resources.Designer.cs b/应用/FissionData/Properties/Resources.Designer.cs new file mode 100644 index 0000000..482a70c --- /dev/null +++ b/应用/FissionData/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace FissionData.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FissionData.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap aaaaaaa { + get { + object obj = ResourceManager.GetObject("aaaaaaa", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/FissionData/Properties/Resources.resx b/应用/FissionData/Properties/Resources.resx new file mode 100644 index 0000000..170eed9 --- /dev/null +++ b/应用/FissionData/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\aaaaaaa.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/FissionData/Properties/licenses.licx b/应用/FissionData/Properties/licenses.licx new file mode 100644 index 0000000..2bd7612 --- /dev/null +++ b/应用/FissionData/Properties/licenses.licx @@ -0,0 +1,4 @@ +DevExpress.XtraEditors.ButtonEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/FissionData/Resources/aaaaaaa.png b/应用/FissionData/Resources/aaaaaaa.png new file mode 100644 index 0000000..10b7ea7 Binary files /dev/null and b/应用/FissionData/Resources/aaaaaaa.png differ diff --git a/应用/FissionSend.rar b/应用/FissionSend.rar new file mode 100644 index 0000000..6cafd7f Binary files /dev/null and b/应用/FissionSend.rar differ diff --git a/应用/FissionSend/Class1.cs b/应用/FissionSend/Class1.cs new file mode 100644 index 0000000..e7c8f60 --- /dev/null +++ b/应用/FissionSend/Class1.cs @@ -0,0 +1,240 @@ +using Api.Framework.SDK; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using FissionSend.Properties; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace FissionSend +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = "裂变-辅助发送"; + this.Note = "随便啦"; + this.Logo = Resources.bbbbbbbb; + } + + #region 自定义变量 + public static Config Config; + private Form1 mainForm = null; + #endregion + + #region 默认 + public override void Start() + { + Config = this.ReadConfig(); + + SDK.WebRequestEvent += SDK_WebRequestEvent; + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new Form1(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + #endregion + + private ConcurrentDictionary groupDic = new ConcurrentDictionary(); + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + //try + //{ + // if (!string.IsNullOrWhiteSpace(e.Groupid)) + // { + // if (!groupDic.ContainsKey(e.Groupid)) + // { + // groupDic.TryAdd(e.Groupid, e.Groupid); + // if (sender.GetType() == typeof(WXClientImpl_HOOK)) + // { + // var hook = sender as WXClientImpl_HOOK; + // if (hook == null) return; + // var group = hook.GetContact(e.Groupid); + // this.OnLog($"添加群缓存 {e.Groupid} - {(group == null ? string.Empty : group.NickName)} ,当前群数量:{groupDic.Count}"); + // } + // else this.OnLog($"添加群缓存 {e.Groupid},当前群数量:{groupDic.Count}"); + // } + // } + //} + //catch (Exception ex) + //{ + // this.OnLog(ex.Message); + //} + } + + private void SDK_WebRequestEvent(object sender, Api.Framework.Events.WebRequestEvents e) + { + var method = e.Param.ContainsKey("method") ? e.Param["method"] : string.Empty; + if (string.IsNullOrWhiteSpace(method)) return; + if (method.ToLower() != "fission") return; + + var text = string.Empty; + var min = 0; + var max = 0; + var sleepmin = 5000; + var sleepmax = 40000; + var groups = string.Empty; + try + { + if (e.Param.ContainsKey("text"))//方法名称 + { + text = e.Param["text"].Trim(); + text = HttpHelper.URLEncode(text); + text = HttpHelper.URLDecode(text, Encoding.UTF8); + } + if (e.Param.ContainsKey("min"))//方法名称 + min = getInt(e.Param["min"]); + if (e.Param.ContainsKey("max"))//方法名称 + max = getInt(e.Param["max"]); + if (e.Param.ContainsKey("sleepmin")) + sleepmin = getInt(e.Param["sleepmin"]) * 1000; + if (e.Param.ContainsKey("sleepmax")) + sleepmax = getInt(e.Param["sleepmax"]) * 1000; + if (e.Param.ContainsKey("groups")) + groups = e.Param["groups"]; + + if (string.IsNullOrWhiteSpace(text)) throw new Exception("发送的内容不能为空"); + if (min <= 0) throw new Exception("min不能小于不能零"); + if (max <= 0) throw new Exception("max不能小于等于零"); + if (min > max) throw new Exception("min的值不能比max大"); + if (sleepmin > sleepmax) throw new Exception("sleepmin的值不能比sleepmax大"); + //e.Send("OK"); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + e.Send("异常:" + ex.Message, -1); + return; + } + + try + { + var wxs = Chat.Framework.ChatClient.WXClient.Values.Where(f => f.WeixinType == WeixinType.Hook微信 && f.Status == WxStatus.在线); + if (wxs == null || wxs.Count() == 0) throw new Exception("没有可执行的机器人"); + var count = wxs.Count(); + + //if (groupDic.Count == 0) + //{ + // var groupInfos = (wxs.ToArray()[0] as WXClientImpl_HOOK).GetGroupsNotInMember(); + // if (groupInfos == null || groupInfos.Count == 0) + // throw new Exception("群缓存列表为空"); + // foreach (var item in groupInfos) + // { + // if (!groupDic.ContainsKey(item.UserName)) + // { + // groupDic.TryAdd(item.UserName, item.UserName); + // this.OnLog($"添加群缓存 {item.UserName} - {item.NickName} ,当前群数量:{groupDic.Count}"); + // } + // } + //} + + var _list = new List(); + if (string.IsNullOrWhiteSpace(groups)) + //_list = groupDic.Keys.ToList(); + _list = Config.SendGroups.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).Where(f => f.EndsWith("@chatroom")).ToList(); + else + _list = groups.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).Where(f => f.EndsWith("@chatroom")).ToList(); + + //if (string.IsNullOrWhiteSpace(Config.SendGroups)) throw new Exception("没有设置要发送群id"); + + //var _list = Config.SendGroups.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).Where(f => f.EndsWith("@chatroom")).ToList(); + + e.Send(_list.Count); + + foreach (var group in _list) + { + //if (notSendGroups.Contains(group)) continue; + var textMsg = text; + var groupTemp = group; + Task.Run(() => + { + try + { + var num = getnum(count, min, max); + var _wxs = wxs.ToList().Select(a => new { a, newID = Guid.NewGuid() }).OrderBy(b => b.newID).Select(c => c.a).Distinct().ToList();//打乱顺序 + _wxs = _wxs.GetRange(0, num); + var sendUCache = new List();//缓存已经发送的账号 + foreach (var wx in _wxs) + { + if (sendUCache.Contains(wx.WeixinHao)) continue; + sendUCache.Add(wx.WeixinHao); + wx.SendMessage(groupTemp, textMsg); + this.OnLog($"群:{groupTemp},微信数量:{_wxs.Count}, 机器人:{wx.User.Username}({wx.User.Nick})({wx.User.Uin}),发送内容:text={textMsg} 已经发送"); + Thread.Sleep(new Random(Guid.NewGuid().GetHashCode()).Next(sleepmin, sleepmax)); + } + } + catch (Exception ex) + { + this.OnLog("!!" + ex.Message); + } + }); + Thread.Sleep(10); + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + e.Send(ex, -1); + } + } + + private int getnum(int count, int min, int max) + { + var num = 0;//执行的数量 + var random = new Random(Guid.NewGuid().GetHashCode()); + if (count >= max)//随机获取min max的区间值 + num = random.Next(min, max); + else if (count <= min)//执行count数量 + num = count; + else//随机获取min count的区间值 + num = random.Next(min, count); + return num; + } + + private int getInt(string intStr) + { + int result = 0; + int.TryParse(intStr, out result); + return result; + } + + + } +} diff --git a/应用/FissionSend/Config.cs b/应用/FissionSend/Config.cs new file mode 100644 index 0000000..d677948 --- /dev/null +++ b/应用/FissionSend/Config.cs @@ -0,0 +1,18 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FissionSend +{ + [Config(Name = "插件-裂变辅助发送-配置")] + public class Config + { + /// + /// 发送的群 + /// + public string SendGroups { get; set; } = string.Empty; + } +} diff --git a/应用/FissionSend/FissionSend.csproj b/应用/FissionSend/FissionSend.csproj new file mode 100644 index 0000000..ed97071 --- /dev/null +++ b/应用/FissionSend/FissionSend.csproj @@ -0,0 +1,95 @@ + + + + + Debug + AnyCPU + {09AFCD48-2450-42A2-851C-A83F28474D80} + Library + Properties + FissionSend + FissionSend + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + Form + + + Form1.cs + + + + True + True + Resources.resx + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/FissionSend/Form1.Designer.cs b/应用/FissionSend/Form1.Designer.cs new file mode 100644 index 0000000..ea0b867 --- /dev/null +++ b/应用/FissionSend/Form1.Designer.cs @@ -0,0 +1,76 @@ +namespace FissionSend +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(25, 27); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(65, 12); + this.label1.TabIndex = 0; + this.label1.Text = "发送的群:"; + // + // richTextBox1 + // + this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richTextBox1.Location = new System.Drawing.Point(25, 51); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.Size = new System.Drawing.Size(1114, 506); + this.richTextBox1.TabIndex = 1; + this.richTextBox1.Text = ""; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1166, 582); + this.Controls.Add(this.richTextBox1); + this.Controls.Add(this.label1); + this.Name = "Form1"; + this.Text = "Form1"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing); + this.Load += new System.EventHandler(this.Form1_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.RichTextBox richTextBox1; + } +} \ No newline at end of file diff --git a/应用/FissionSend/Form1.cs b/应用/FissionSend/Form1.cs new file mode 100644 index 0000000..7f3ad7f --- /dev/null +++ b/应用/FissionSend/Form1.cs @@ -0,0 +1,49 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace FissionSend +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + {} + } + + private void Form1_Load(object sender, EventArgs e) + { + richTextBox1.Text = Class1.Config.SendGroups; + } + + private void Form1_FormClosing(object sender, FormClosingEventArgs e) + { + Class1.Config.SendGroups = richTextBox1.Text; + Util.Save(Class1.Config); + } + } +} diff --git a/应用/FissionSend/Form1.resx b/应用/FissionSend/Form1.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/应用/FissionSend/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/应用/FissionSend/Properties/AssemblyInfo.cs b/应用/FissionSend/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..da43219 --- /dev/null +++ b/应用/FissionSend/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("FissionSend")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FissionSend")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("09afcd48-2450-42a2-851c-a83f28474d80")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/FissionSend/Properties/Resources.Designer.cs b/应用/FissionSend/Properties/Resources.Designer.cs new file mode 100644 index 0000000..a0eb2b8 --- /dev/null +++ b/应用/FissionSend/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace FissionSend.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FissionSend.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap bbbbbbbb { + get { + object obj = ResourceManager.GetObject("bbbbbbbb", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/FissionSend/Properties/Resources.resx b/应用/FissionSend/Properties/Resources.resx new file mode 100644 index 0000000..ad86353 --- /dev/null +++ b/应用/FissionSend/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\bbbbbbbb.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/FissionSend/Resources/bbbbbbbb.png b/应用/FissionSend/Resources/bbbbbbbb.png new file mode 100644 index 0000000..0d9dc16 Binary files /dev/null and b/应用/FissionSend/Resources/bbbbbbbb.png differ diff --git a/应用/FreeActivity/Class1.cs b/应用/FreeActivity/Class1.cs new file mode 100644 index 0000000..3ef3647 --- /dev/null +++ b/应用/FreeActivity/Class1.cs @@ -0,0 +1,298 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using FreeActivity.Entitys; +using FreeActivity.Properties; +using System; +using System.Data; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace FreeActivity +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.免单活动; + } + + #region 初始化 + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("name"); + session.AddIndex("name"); + } + if (!session.TableExist()) + session.CreateTable(); + + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + #endregion + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + + #region 查看任务列表 + if (!string.IsNullOrEmpty(Config.ViewTask_CMD) && Regex.IsMatch(e.Message.Trim(), Config.ViewTask_CMD)) + { + var session = ApiClient.GetSession(); + var freeactivity_infos = session.Find("activity_time_end >= @now", new { now = DateTime.Now }); + if (freeactivity_infos.Count != 0) + { + var now = DateTime.Now; + var freeactivity_unstart = freeactivity_infos.Where(f => f.activity_time_begin >= now).ToList();//活动未开始 + var freeactivity_start = freeactivity_infos.Where(f => f.activity_time_begin < now).ToList();//活动进行中 + var unstartStr = new StringBuilder(); + var startStr = new StringBuilder(); + for (int i = 0; i < freeactivity_unstart.Count; i++) + { + unstartStr.AppendLine($"{i + 1}、{freeactivity_unstart[i].name}"); + } + + for (int i = 0; i < freeactivity_start.Count; i++) + { + startStr.AppendLine($"{i + 1}、{freeactivity_start[i].name}"); + } + + e.SendMessage(Config.ViewTaskTips.Replace("[未开始任务列表]", string.IsNullOrEmpty(unstartStr.ToString().Trim()) ? "无" : unstartStr.ToString().Trim()).Replace("[进行中任务列表]", string.IsNullOrEmpty(startStr.ToString().Trim()) ? "无" : startStr.ToString().Trim())); + } + } + #endregion + + #region 领取任务 + var reg = Regex.Match(e.Message.Trim(), Config.GetTask_CMD); + if (reg.Success) + { + var taskName = reg.Groups["任务名"].Value.Trim(); + var session = ApiClient.GetSession(); + var now = DateTime.Now; + //var freeactivity = session.Find("name = @name and activity_time_end >= @now", new { name = taskName, now = now }).FirstOrDefault(); + var freeactivity = session.FindSingle("name = @name", new { name = taskName }); + if (freeactivity != null) + { + if (freeactivity.activity_time_end >= now) + { + if (freeactivity.activity_time_begin <= now) + { + var freeactivity_user = session.Find("uid = @uid and activityid = @activityid", new { uid = e.GetMemberinfo().id, activityid = freeactivity.id }).FirstOrDefault(); + if (freeactivity_user == null) + { + #region 任务条件 字符串 condition + var condition = new StringBuilder(); + var mess = freeactivity.condition_relation ? Config.GetTaskSuccessAndTips : Config.GetTaskSuccessOrTips; + if (mess.Contains("[任务条件]")) + { + if (freeactivity.check_ordernum) + condition.AppendLine(Config.ViewTaskDetails_OrderNum_ConditionTips.Replace("[订单笔数]", freeactivity.ordernum.ToString())); + if (freeactivity.check_pointsum) + condition.AppendLine(Config.ViewTaskDetails_PointNum_ConditionTips.Replace("[返利金额]", freeactivity.pointsum.ToString())); + if (freeactivity.check_invitenum) + condition.AppendLine(Config.ViewTaskDetails_InviteNum_ConditionTips.Replace("[邀请人数]", freeactivity.invitenum.ToString())); + } + #endregion + + #region 任务进度 字符串 process + var process = new StringBuilder(); + var flag = false; + bool orderflag = false; + if (freeactivity.check_ordernum) + { + int orderNum = 0; + if (Config.ViewTaskDetails_OrderNum_ConditionTips.Contains("[订单笔数]")) + { + var tbResult = session.FindRow($"select count(*) as count from fl_order_alimama where db_userid = @id and db_status = 1002 and create_time >= @time", new { id = e.GetMemberinfo().id, time = freeactivity.activity_time_begin }); + var tbReturnNum = int.Parse(tbResult["count"].ToString()); + + var jdResult = session.FindRow($"select count(*) as count from fl_order_jingdong where db_userid = @id and db_status = 1002 and orderTime >= @time", new { id = e.GetMemberinfo().id, time = freeactivity.activity_time_begin }); + var jdReturnNum = int.Parse(jdResult["count"].ToString()); + + var pddResult = session.FindRow($"select count(*) as count from fl_order_pinduoduo where db_userid = @id and db_status = 1002 and order_pay_time >= @time", new { id = e.GetMemberinfo().id, time = freeactivity.activity_time_begin }); + var pddReturnNum = int.Parse(pddResult["count"].ToString()); + + orderNum = tbReturnNum + jdReturnNum + pddReturnNum; + } + if (freeactivity.ordernum <= orderNum) orderflag = true; + process.AppendLine(Config.TaskProcess_OrderNumTips.Replace("[订单笔数]", orderNum.ToString())); + } + + bool pointflag = false; + if (freeactivity.check_pointsum) + { + decimal pointSum = 0m; + if (Config.ViewTaskDetails_PointNum_ConditionTips.Contains("[返利金额]")) + { + var pddResult = session.FindRow($"select round(sum(db_userpoint),2) as sum from fl_order_pinduoduo where db_userid = @id and db_status = 1002 and order_pay_time >= @time", new { id = e.GetMemberinfo().id, time = freeactivity.activity_time_begin }); + var pddPendingPoint = string.IsNullOrEmpty(pddResult["sum"].ToString()) ? 0m : decimal.Parse(pddResult["sum"].ToString()); + + + var tbResult = session.FindRow($"select round(sum(db_userpoint),2) as sum from fl_order_alimama where db_userid = @id and db_status = 1002 and create_time >= @time", new { id = e.GetMemberinfo().id, time = freeactivity.activity_time_begin }); + var tbPendingPoint = string.IsNullOrEmpty(tbResult["sum"].ToString()) ? 0m : decimal.Parse(tbResult["sum"].ToString()); + + + var jdResult = session.FindRow($"select round(sum(db_userpoint),2) as sum from fl_order_jingdong where db_userid = @id and db_status = 1002 and orderTime >= @time", new { id = e.GetMemberinfo().id, time = freeactivity.activity_time_begin }); + var jdPendingPoint = string.IsNullOrEmpty(jdResult["sum"].ToString()) ? 0m : decimal.Parse(jdResult["sum"].ToString()); + + pointSum = pddPendingPoint + tbPendingPoint + jdPendingPoint; + } + if (freeactivity.pointsum <= (double)pointSum) pointflag = true; + process.AppendLine(Config.TaskProcess_PointNumTips.Replace("[返利金额]", pointSum.ToString())); + } + + bool inviteflag = false; + if (freeactivity.check_invitenum) + { + int invitenum = 0; + if (Config.ViewTaskDetails_InviteNum_ConditionTips.Contains("[邀请人数]")) + { + var where = string.Empty; + var result = session.FindRow($"select count(*) as count from fl_member_info where inviter_id = @id and crt_time >= @time", new { id = e.GetMemberinfo().id, time = freeactivity.activity_time_begin }); + invitenum = int.Parse(result["count"].ToString()); + } + if (freeactivity.invitenum <= invitenum) inviteflag = true; + process.AppendLine(Config.TaskProcess_InviteNumTips.Replace("[邀请人数]", invitenum.ToString())); + } + + if (freeactivity.condition_relation) + flag = (freeactivity.check_ordernum ? orderflag : true) && (freeactivity.check_pointsum ? pointflag : true) && (freeactivity.check_invitenum ? inviteflag : true); + else + flag = orderflag || pointflag || inviteflag; + #endregion + + if (flag)//已经完成,可以兑换 + { + freeactivity_user = new fl_plugin_freeactivity_user_info() { activityid = freeactivity.id, get_time = DateTime.Now, uid = e.GetMemberinfo().id, exchange_time = DateTime.MinValue, is_exchange = ChooseType.否 }; + var value = session.Insertable(freeactivity_user).ExecuteCommand(); + + e.SendMessage(mess.Replace("[任务名]", freeactivity.name).Replace("[任务条件]", condition.ToString().Trim()).Replace("[任务进度]", process.ToString())); + } + else + { + mess = freeactivity.condition_relation ? Config.GetTaskUnSuccessAndTips : Config.GetTaskUnSuccessOrTips; + e.SendMessage(mess.Replace("[任务名]", freeactivity.name).Replace("[任务条件]", condition.ToString().Trim()).Replace("[任务进度]", process.ToString())); + } + + } + else + { + //已经参与过改活动 + e.SendMessage(Config.GetTaskRepeatTips.Replace("[任务名]", freeactivity.name)); + } + } + else + { + e.SendMessage(Config.TaskNotStartTips.Replace("[任务名]", freeactivity.name).Replace("[起始检验时间]", freeactivity.activity_time_begin.ToString("yyyy-MM-dd HH:mm:ss")).Replace("[结束检验时间]", freeactivity.activity_time_end.ToString("yyyy-MM-dd HH:mm:ss"))); + } + } + else + { + e.SendMessage(Config.TaskOutmodedTips.Replace("[任务名]", freeactivity.name)); + } + } + else + e.SendMessage(Config.TaskNotExistTips.Replace("[任务名]", taskName)); + return; + } + #endregion + + #region 查看任务详情 + if (!string.IsNullOrEmpty(Config.ViewTaskDetails_CMD)) + { + reg = Regex.Match(e.Message.Trim(), Config.ViewTaskDetails_CMD); + if (reg.Success) + { + var taskName = reg.Groups["任务名"].Value.Trim(); + var session = ApiClient.GetSession(); + var freeactivity = session.Find("name = @name", new { name = taskName }).FirstOrDefault(); + if (freeactivity != null) + { + var condition = new StringBuilder(); + if (Config.ViewTaskDetailsTips.Contains("[任务条件]")) + { + if (freeactivity.check_ordernum) + condition.AppendLine(Config.ViewTaskDetails_OrderNum_ConditionTips.Replace("[订单笔数]", freeactivity.ordernum.ToString())); + if (freeactivity.check_pointsum) + condition.AppendLine(Config.ViewTaskDetails_PointNum_ConditionTips.Replace("[返利金额]", freeactivity.pointsum.ToString())); + if (freeactivity.check_invitenum) + condition.AppendLine(Config.ViewTaskDetails_InviteNum_ConditionTips.Replace("[邀请人数]", freeactivity.invitenum.ToString())); + } + + e.SendMessage(Config.ViewTaskDetailsTips.Replace("[起始检验时间]", freeactivity.activity_time_begin.ToString("yyyy-MM-dd HH:mm:ss")).Replace("[结束检验时间]", freeactivity.activity_time_end.ToString("yyyy-MM-dd HH:mm:ss")).Replace("[免单商品详情]", freeactivity.goods_detail).Replace("[任务条件]", condition.ToString().Trim())); + } + else + e.SendMessage(Config.TaskNotExistTips.Replace("[任务名]", taskName)); + return; + } + } + #endregion + + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/FreeActivity/Config.cs b/应用/FreeActivity/Config.cs new file mode 100644 index 0000000..d7f42f1 --- /dev/null +++ b/应用/FreeActivity/Config.cs @@ -0,0 +1,345 @@ +using Api.Framework.SDK; +using System.ComponentModel; +using UI.Framework.Entitys; + +namespace FreeActivity +{ + [Config(Name = "插件-免单活动-配置")] + public class Config + { + /// + /// 查看任务列表指令 + /// + [ + Category("1)、基础指令"), DisplayName("01.查看任务列表指令"), DefaultValue(@"^免单任务$"), + Description(@"查看任务列表的指令") +] + public string ViewTask_CMD { get; set; } + + /// + /// 查看任务详情指令 + /// + [ + Category("1)、基础指令"), DisplayName("02.查看任务详情指令"), DefaultValue(@"^任务(?:\s*?)?(?<任务名>.+?)$"), + Description(@"查看任务详细的指令") +] + public string ViewTaskDetails_CMD { get; set; } + + /// + /// 领取任务指令 + /// + [ + Category("1)、基础指令"), DisplayName("03.领取任务指令"), DefaultValue(@"^领取(?:\s*?)?(?<任务名>.+?)$"), + Description(@"领取任务的指令") +] + public string GetTask_CMD { get; set; } + + /// + /// 查看任务提示语 + /// + [ + Category("2)、提示语"), DisplayName("01.查看任务列表"), DefaultValue(@"一一一一任 务 列 表一一一一 +未开始任务 +[未开始任务列表] +进行中任务 +[进行中任务列表] + +发送【任务xxxx】查看详情"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[未开始任务列表]、[进行中任务列表]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string ViewTaskTips { get; set; } + + /// + /// 查看任务详细 + /// + [ + Category("2)、提示语"), DisplayName("02.查看任务详细"), DefaultValue(@"一一一一任 务 详 情一一一一 +任务时间:[起始检验时间] 至 [结束检验时间] + +任务条件: +[任务条件] + +免单商品: +[免单商品详情]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[起始检验时间]、[结束检验时间]、[任务条件]、[免单商品详情]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string ViewTaskDetailsTips { get; set; } + + /// + /// 查看任务详细 - 订单数 条件格式 + /// + [ + Category("2)、提示语"), DisplayName("03_1.查看任务详细 - 订单数"), DefaultValue(@"结算订单[订单笔数]笔"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单笔数]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string ViewTaskDetails_OrderNum_ConditionTips { get; set; } + + /// + /// 查看任务详细 - 订单数 条件格式 + /// + [ + Category("2)、提示语"), DisplayName("03_2.查看任务详细 - 返利数"), DefaultValue(@"返利金额[返利金额]元"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[返利金额]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string ViewTaskDetails_PointNum_ConditionTips { get; set; } + + /// + /// 查看任务详细 - 订单数 条件格式 + /// + [ + Category("2)、提示语"), DisplayName("03_3.查看任务详细 - 邀请数"), DefaultValue(@"邀请用户[邀请人数]人"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[邀请人数]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string ViewTaskDetails_InviteNum_ConditionTips { get; set; } + + + //----------- + + + /// + /// 查看任务详细 - 订单数 条件格式 + /// + [ + Category("2)、提示语"), DisplayName("03_4.查看任务进度 - 订单数"), DefaultValue(@"当前结算订单[订单笔数]笔"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单笔数]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string TaskProcess_OrderNumTips { get; set; } + + /// + /// 查看任务详细 - 订单数 条件格式 + /// + [ + Category("2)、提示语"), DisplayName("03_5.查看任务进度 - 返利数"), DefaultValue(@"当前返利金额[返利金额]元"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[返利金额]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string TaskProcess_PointNumTips { get; set; } + + /// + /// 查看任务详细 - 订单数 条件格式 + /// + [ + Category("2)、提示语"), DisplayName("03_6.查看任务进度 - 邀请数"), DefaultValue(@"当前邀请用户[邀请人数]人"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[邀请人数]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string TaskProcess_InviteNumTips { get; set; } + /// + /// 符合免单任务 - 满足所有条件 + /// + [ + Category("2)、提示语"), DisplayName("04.符合免单任务 - 满足所有条件"), DefaultValue(@"一一一一领 取 成 功一一一一 +领取任务:[任务名] + +任务条件: +[任务条件] + +任务进度: +[任务进度] + +已满足所有条件,获得免单资格"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[任务名]、[任务条件]、[任务进度]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string GetTaskSuccessAndTips { get; set; } + + /// + /// 不符合免单任务 - 满足所有条件 + /// + [ + Category("2)、提示语"), DisplayName("05.不符合免单任务 - 满足所有条件"), DefaultValue(@"一一一一领 取 失 败一一一一 +领取任务:[任务名] + +任务条件: +[任务条件] + +任务进度: +[任务进度] + +当前还未完成以上多有的条件"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[任务名]、[任务条件]、[任务进度]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string GetTaskUnSuccessAndTips { get; set; } + + /// + /// 符合免单任务 - 满足任意条件 + /// + [ + Category("2)、提示语"), DisplayName("06.符合免单任务 - 满足任意条件"), DefaultValue(@"一一一一领 取 成 功一一一一 +领取任务:[任务名] + +任务条件: +[任务条件] + +任务进度: +[任务进度] + +已满足其中一条,获得免单条件"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[任务名]、[任务条件]、[任务进度]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string GetTaskSuccessOrTips { get; set; } + + + + /// + /// 不符合免单任务 - 满足任意条件 + /// + [ + Category("2)、提示语"), DisplayName("07.不符合免单任务 - 满足任意条件"), DefaultValue(@"一一一一领 取 失 败一一一一 +领取任务:[任务名] + +任务条件: +[任务条件] + +任务进度: +[任务进度] + +完成以上任意条件,即可获得免单"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[任务名]、[任务条件]、[任务进度]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string GetTaskUnSuccessOrTips { get; set; } + + /// + /// 任务重复领取 + /// + [ + Category("2)、提示语"), DisplayName("08.任务重复领取"), DefaultValue(@"一一一一重 复 领 取一一一一 +任务名:【[任务名]】 +已经参加过 + +查看其他任务发送【免单任务】"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[任务名]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string GetTaskRepeatTips { get; set; } + + /// + /// 任务还未开始 + /// + [ + Category("2)、提示语"), DisplayName("09.任务还未开始"), DefaultValue(@"一一一一任 务 未 开 始一一一一 +任务名:【[任务名]】 +当前任务还未开始 +任务时间:[起始检验时间] - [结束检验时间]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[任务名]、[起始检验时间]、[结束检验时间]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string TaskNotStartTips { get; set; } + + /// + /// 任务名不存在 + /// + [ + Category("2)、提示语"), DisplayName("10.任务名不存在"), DefaultValue(@"一一一一任 务 不 存 在一一一一 +任务【[任务名]】不存在 +请核对后重试"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[任务名]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string TaskNotExistTips { get; set; } + + /// + /// 任务过期 + /// + [ + Category("2)、提示语"), DisplayName("11.任务已经过期"), DefaultValue(@"一一一一任 务 已 过 期一一一一 +任务【[任务名]】已经过期 +请关注下次活动"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[任务名]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string TaskOutmodedTips { get; set; } + + public Config() + { + this.ViewTask_CMD = @"^免单任务$"; + this.ViewTaskDetails_CMD = @"^任务(?:\s*?)?(?<任务名>.+?)$"; + this.GetTask_CMD = @"^领取(?:\s*?)?(?<任务名>.+?)$"; + this.GetTaskUnSuccessOrTips = @"一一一一领 取 失 败一一一一 +领取任务:[任务名] + +任务条件: +[任务条件] + +任务进度: +[任务进度] + +完成以上任意条件,即可获得免单"; + this.GetTaskUnSuccessAndTips = @"一一一一领 取 失 败一一一一 +领取任务:[任务名] + +任务条件: +[任务条件] + +任务进度: +[任务进度] + +当前还未完成以上多有的条件"; + this.ViewTaskTips = @"一一一一任 务 列 表一一一一 +未开始任务 +[未开始任务列表] +进行中任务 +[进行中任务列表] + +发送【任务xxxx】查看详情"; + this.TaskNotStartTips = @"一一一一任 务 未 开 始一一一一 +任务名:【[任务名]】 +当前任务还未开始 +任务时间:[起始检验时间] - [结束检验时间]"; + this.ViewTaskDetailsTips = @"一一一一任 务 详 情一一一一 +任务时间:[起始检验时间] 至 [结束检验时间] + +任务条件: +[任务条件] + +免单商品: +[免单商品详情]"; + this.ViewTaskDetails_OrderNum_ConditionTips = @"结算订单[订单笔数]笔"; + this.ViewTaskDetails_PointNum_ConditionTips = @"返利金额[返利金额]元"; + this.ViewTaskDetails_InviteNum_ConditionTips = @"邀请用户[邀请人数]人"; + this.GetTaskRepeatTips = @"一一一一重 复 领 取一一一一 +任务名:【[任务名]】 +已经参加过 + +查看其他任务发送【免单任务】"; + this.TaskNotExistTips = @"一一一一任 务 详 情一一一一 +任务【[任务名]】不存在 +请核对后重试"; + this.GetTaskSuccessAndTips = @"一一一一领 取 成 功一一一一 +领取任务:[任务名] + +任务条件: +[任务条件] + +以上条件 [任务验收时间] 前全部完成才有效 + +任务进度发送【任务进度】查看"; + + this.GetTaskSuccessOrTips = @"一一一一领 取 成 功一一一一 +领取任务:[任务名] + +任务条件: +[任务条件] + +以上条件 [任务验收时间] 前完成其中一条 + +任务进度发送【任务进度】查看"; + this.TaskProcess_OrderNumTips = @"当前结算订单[订单笔数]笔"; + this.TaskProcess_PointNumTips = @"当前返利金额[返利金额]元"; + this.TaskProcess_InviteNumTips = @"当前邀请用户[邀请人数]人"; + this.TaskOutmodedTips = @"一一一一任 务 已 过 期一一一一 +任务【[任务名]】已经过期 +请关注下次活动"; + } + + } +} diff --git a/应用/FreeActivity/Entitys/Enums.cs b/应用/FreeActivity/Entitys/Enums.cs new file mode 100644 index 0000000..4929297 --- /dev/null +++ b/应用/FreeActivity/Entitys/Enums.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FreeActivity.Entitys +{ + public enum ChooseType + { + 否 = 0, + 是 = 1 + } + + +} diff --git a/应用/FreeActivity/Entitys/fl_plugin_freeactivity_info.cs b/应用/FreeActivity/Entitys/fl_plugin_freeactivity_info.cs new file mode 100644 index 0000000..3ef4f0c --- /dev/null +++ b/应用/FreeActivity/Entitys/fl_plugin_freeactivity_info.cs @@ -0,0 +1,72 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FreeActivity.Entitys +{ + public class fl_plugin_freeactivity_info : base_model + { + /// + /// 活动名称 + /// + public string name { get; set; } + /// + /// 条件校验开始时间 + /// + public DateTime activity_time_begin { get; set; } + /// + /// 条件校验结束时间 + /// + public DateTime activity_time_end { get; set; } + /// + /// 机器人列表 (机器人name) + /// + public string robots { get; set; } + + /// + /// 订单条件 + /// + public bool check_ordernum { get; set; } + /// + /// 订单数 + /// + public int ordernum { get; set; } + + /// + /// 返利条件 + /// + public bool check_pointsum { get; set; } + /// + /// 返利金额 + /// + public double pointsum { get; set; } + + /// + /// 邀请人条件 + /// + public bool check_invitenum { get; set; } + /// + /// 邀请人数 + /// + public int invitenum { get; set; } + + /// + /// 活动条件关系(true为并且关系) + /// + public bool condition_relation { get; set; } + + /// + /// 商品链接 + /// + public string goods_url { get; set; } + + /// + /// 商品介绍 + /// + public string goods_detail { get;set;} + + } +} diff --git a/应用/FreeActivity/Entitys/fl_plugin_freeactivity_user_info.cs b/应用/FreeActivity/Entitys/fl_plugin_freeactivity_user_info.cs new file mode 100644 index 0000000..932b892 --- /dev/null +++ b/应用/FreeActivity/Entitys/fl_plugin_freeactivity_user_info.cs @@ -0,0 +1,36 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FreeActivity.Entitys +{ + /// + /// 参加活动的用户信息 + /// + public class fl_plugin_freeactivity_user_info : base_model + { + /// + /// 用户id + /// + public long uid { get; set; } + /// + /// 活动id + /// + public long activityid { get; set; } + /// + /// 活动领取时间 + /// + public DateTime get_time { get; set; } + /// + /// 兑换时间 + /// + public DateTime exchange_time { get; set; } + /// + /// 是否进行兑换 + /// + public ChooseType is_exchange { get; set; } + } +} diff --git a/应用/FreeActivity/Entitys/temp_freeactivity_exchange_info.cs b/应用/FreeActivity/Entitys/temp_freeactivity_exchange_info.cs new file mode 100644 index 0000000..a16ad98 --- /dev/null +++ b/应用/FreeActivity/Entitys/temp_freeactivity_exchange_info.cs @@ -0,0 +1,62 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FreeActivity.Entitys +{ + public class temp_freeactivity_exchange_info + { + /// + /// 兑换用户id + /// + public long fuid { get; set; } + /// + /// 机器人id + /// + public long rid { get; set; } + /// + /// 机器人账号 + /// + public ChatType robot_type { get; set; } + /// + /// 机器人昵称 + /// + public string robot_nick { get; set; } + /// + /// 用户id + /// + public long uid { get; set; } + /// + /// 用户账号 + /// + public string username { get; set; } + /// + /// 用户昵称 + /// + public string usernick { get; set; } + /// + /// 活动id + /// + public int activityid { get; set; } + /// + /// 活动名称 + /// + public string activityname { get; set; } + + /// + /// 活动领取时间 + /// + public DateTime get_time { get; set; } + /// + /// 兑换时间 + /// + public DateTime exchange_time { get; set; } + /// + /// 是否进行兑换 + /// + public ChooseType is_exchange { get; set; } + } +} diff --git a/应用/FreeActivity/FreeActivity.csproj b/应用/FreeActivity/FreeActivity.csproj new file mode 100644 index 0000000..d9dc70b --- /dev/null +++ b/应用/FreeActivity/FreeActivity.csproj @@ -0,0 +1,125 @@ + + + + + Debug + AnyCPU + {8BA5CF87-767F-4D7A-996D-76D0CC790610} + Library + Properties + FreeActivity + FreeActivity + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + \ No newline at end of file diff --git a/应用/FreeActivity/MainForm.Designer.cs b/应用/FreeActivity/MainForm.Designer.cs new file mode 100644 index 0000000..a8ea594 --- /dev/null +++ b/应用/FreeActivity/MainForm.Designer.cs @@ -0,0 +1,776 @@ +namespace FreeActivity +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.xtraTabControl2 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label7 = new System.Windows.Forms.Label(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.checkedComboBoxEdit_ChatType = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.simpleButton = new DevExpress.XtraEditors.SimpleButton(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.radio_or = new System.Windows.Forms.RadioButton(); + this.radio_and = new System.Windows.Forms.RadioButton(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.check_invite_num = new System.Windows.Forms.CheckBox(); + this.check_point_num = new System.Windows.Forms.CheckBox(); + this.check_order_num = new System.Windows.Forms.CheckBox(); + this.time_end = new System.Windows.Forms.DateTimePicker(); + this.time_begin = new System.Windows.Forms.DateTimePicker(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.text_name = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改为兑换ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl2)).BeginInit(); + this.xtraTabControl2.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl2 + // + this.xtraTabControl2.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl2.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl2.Name = "xtraTabControl2"; + this.xtraTabControl2.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl2.Size = new System.Drawing.Size(986, 573); + this.xtraTabControl2.TabIndex = 16; + this.xtraTabControl2.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label7); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Controls.Add(this.groupControl1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(984, 549); + this.xtraTabPage1.Text = " 免 单 活 动 列 表 "; + // + // label7 + // + this.label7.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label7.AutoSize = true; + this.label7.BackColor = System.Drawing.Color.White; + this.label7.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label7.Location = new System.Drawing.Point(119, 196); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(267, 35); + this.label7.TabIndex = 13; + this.label7.Text = "当前无免单活动"; + // + // gridControl1 + // + this.gridControl1.Location = new System.Drawing.Point(-9, 1); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(498, 498); + this.gridControl1.TabIndex = 12; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn3, + this.gridColumn1, + this.gridColumn2, + this.gridColumn5}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + this.gridView1.DoubleClick += new System.EventHandler(this.gridView1_DoubleClick); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "id"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "活动名称"; + this.gridColumn3.FieldName = "name"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 1; + this.gridColumn3.Width = 138; + // + // gridColumn1 + // + this.gridColumn1.Caption = "领取开始时间"; + this.gridColumn1.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn1.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn1.FieldName = "activity_time_begin"; + this.gridColumn1.Name = "gridColumn1"; + // + // gridColumn2 + // + this.gridColumn2.Caption = "领取结束时间"; + this.gridColumn2.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn2.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn2.FieldName = "activity_time_end"; + this.gridColumn2.Name = "gridColumn2"; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "活动状态"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 148; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.labelControl6); + this.groupControl1.Controls.Add(this.labelControl5); + this.groupControl1.Controls.Add(this.labelControl4); + this.groupControl1.Controls.Add(this.labelControl3); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.checkedComboBoxEdit_ChatType); + this.groupControl1.Controls.Add(this.memoEdit1); + this.groupControl1.Controls.Add(this.simpleButton); + this.groupControl1.Controls.Add(this.groupBox1); + this.groupControl1.Controls.Add(this.time_end); + this.groupControl1.Controls.Add(this.time_begin); + this.groupControl1.Controls.Add(this.textBox1); + this.groupControl1.Controls.Add(this.text_name); + this.groupControl1.Controls.Add(this.label3); + this.groupControl1.Location = new System.Drawing.Point(495, 2); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(486, 497); + this.groupControl1.TabIndex = 11; + this.groupControl1.Text = "活动编辑"; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(37, 295); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(84, 14); + this.labelControl6.TabIndex = 8; + this.labelControl6.Text = "免单商品介绍:"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(37, 266); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(84, 14); + this.labelControl5.TabIndex = 8; + this.labelControl5.Text = "免单商品链接:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(25, 97); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(84, 14); + this.labelControl4.TabIndex = 8; + this.labelControl4.Text = "校验条件范围:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(37, 70); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(72, 14); + this.labelControl3.TabIndex = 8; + this.labelControl3.Text = "活动机器人:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(49, 42); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 8; + this.labelControl1.Text = "活动名称:"; + // + // checkedComboBoxEdit_ChatType + // + this.checkedComboBoxEdit_ChatType.EditValue = ""; + this.checkedComboBoxEdit_ChatType.Location = new System.Drawing.Point(115, 67); + this.checkedComboBoxEdit_ChatType.Name = "checkedComboBoxEdit_ChatType"; + this.checkedComboBoxEdit_ChatType.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit_ChatType.Size = new System.Drawing.Size(329, 20); + this.checkedComboBoxEdit_ChatType.TabIndex = 2; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(49, 315); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(395, 139); + this.memoEdit1.TabIndex = 6; + // + // simpleButton + // + this.simpleButton.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton.ImageOptions.Image"))); + this.simpleButton.Location = new System.Drawing.Point(198, 460); + this.simpleButton.Name = "simpleButton"; + this.simpleButton.Size = new System.Drawing.Size(96, 29); + this.simpleButton.TabIndex = 7; + this.simpleButton.Text = "保 存 配 置 "; + this.simpleButton.Click += new System.EventHandler(this.simpleButton_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.radio_or); + this.groupBox1.Controls.Add(this.radio_and); + this.groupBox1.Controls.Add(this.numericUpDown3); + this.groupBox1.Controls.Add(this.numericUpDown2); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.check_invite_num); + this.groupBox1.Controls.Add(this.check_point_num); + this.groupBox1.Controls.Add(this.check_order_num); + this.groupBox1.Location = new System.Drawing.Point(49, 128); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(395, 125); + this.groupBox1.TabIndex = 6; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 活动条件 "; + // + // radio_or + // + this.radio_or.AutoSize = true; + this.radio_or.Location = new System.Drawing.Point(201, 21); + this.radio_or.Name = "radio_or"; + this.radio_or.Size = new System.Drawing.Size(97, 18); + this.radio_or.TabIndex = 1; + this.radio_or.Text = "满足任意条件"; + this.radio_or.UseVisualStyleBackColor = true; + // + // radio_and + // + this.radio_and.AutoSize = true; + this.radio_and.Checked = true; + this.radio_and.Location = new System.Drawing.Point(75, 21); + this.radio_and.Name = "radio_and"; + this.radio_and.Size = new System.Drawing.Size(97, 18); + this.radio_and.TabIndex = 0; + this.radio_and.TabStop = true; + this.radio_and.Text = "满足所有条件"; + this.radio_and.UseVisualStyleBackColor = true; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(130, 87); + this.numericUpDown3.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(51, 22); + this.numericUpDown3.TabIndex = 9; + this.numericUpDown3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(310, 55); + this.numericUpDown2.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(51, 22); + this.numericUpDown2.TabIndex = 6; + this.numericUpDown2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(130, 55); + this.numericUpDown1.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(51, 22); + this.numericUpDown1.TabIndex = 3; + this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // check_invite_num + // + this.check_invite_num.AutoSize = true; + this.check_invite_num.Location = new System.Drawing.Point(44, 89); + this.check_invite_num.Name = "check_invite_num"; + this.check_invite_num.Size = new System.Drawing.Size(86, 18); + this.check_invite_num.TabIndex = 4; + this.check_invite_num.Text = "邀请人数满"; + this.check_invite_num.UseVisualStyleBackColor = true; + // + // check_point_num + // + this.check_point_num.AutoSize = true; + this.check_point_num.Location = new System.Drawing.Point(224, 57); + this.check_point_num.Name = "check_point_num"; + this.check_point_num.Size = new System.Drawing.Size(86, 18); + this.check_point_num.TabIndex = 4; + this.check_point_num.Text = "返利金额满"; + this.check_point_num.UseVisualStyleBackColor = true; + // + // check_order_num + // + this.check_order_num.AutoSize = true; + this.check_order_num.Location = new System.Drawing.Point(44, 57); + this.check_order_num.Name = "check_order_num"; + this.check_order_num.Size = new System.Drawing.Size(86, 18); + this.check_order_num.TabIndex = 4; + this.check_order_num.Text = "订单笔数满"; + this.check_order_num.UseVisualStyleBackColor = true; + // + // time_end + // + this.time_end.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.time_end.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.time_end.Location = new System.Drawing.Point(294, 93); + this.time_end.Name = "time_end"; + this.time_end.Size = new System.Drawing.Size(159, 22); + this.time_end.TabIndex = 4; + this.time_end.Value = new System.DateTime(2019, 5, 9, 14, 21, 0, 0); + // + // time_begin + // + this.time_begin.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.time_begin.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.time_begin.Location = new System.Drawing.Point(115, 93); + this.time_begin.Name = "time_begin"; + this.time_begin.Size = new System.Drawing.Size(159, 22); + this.time_begin.TabIndex = 3; + this.time_begin.Value = new System.DateTime(2019, 5, 9, 14, 21, 0, 0); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(134, 263); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(233, 22); + this.textBox1.TabIndex = 1; + // + // text_name + // + this.text_name.Location = new System.Drawing.Point(115, 39); + this.text_name.Name = "text_name"; + this.text_name.Size = new System.Drawing.Size(329, 22); + this.text_name.TabIndex = 1; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(279, 97); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(11, 14); + this.label3.TabIndex = 0; + this.label3.Text = "-"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 512); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(984, 37); + this.pageControl1.TabIndex = 10; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.groupControl2); + this.xtraTabPage2.Controls.Add(this.gridControl2); + this.xtraTabPage2.Controls.Add(this.pageControl2); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(984, 549); + this.xtraTabPage2.Text = " 完 成 列 表 "; + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.simpleButton3); + this.groupControl2.Controls.Add(this.labelControl2); + this.groupControl2.Controls.Add(this.textEdit1); + this.groupControl2.Dock = System.Windows.Forms.DockStyle.Top; + this.groupControl2.Location = new System.Drawing.Point(0, 0); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(984, 76); + this.groupControl2.TabIndex = 6; + this.groupControl2.Text = "搜索条件"; + // + // simpleButton3 + // + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(578, 34); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(79, 27); + this.simpleButton3.TabIndex = 7; + this.simpleButton3.Text = "搜索"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(267, 40); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(72, 14); + this.labelControl2.TabIndex = 6; + this.labelControl2.Text = "关键词搜索:"; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(357, 37); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(202, 20); + this.textEdit1.TabIndex = 1; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl2.Location = new System.Drawing.Point(3, 82); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(978, 426); + this.gridControl2.TabIndex = 7; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改为兑换ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(137, 26); + // + // 修改为兑换ToolStripMenuItem + // + this.修改为兑换ToolStripMenuItem.Name = "修改为兑换ToolStripMenuItem"; + this.修改为兑换ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.修改为兑换ToolStripMenuItem.Text = "修改为兑换"; + this.修改为兑换ToolStripMenuItem.Click += new System.EventHandler(this.修改为兑换ToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn15, + this.gridColumn4, + this.gridColumn9, + this.gridColumn22, + this.gridColumn14, + this.gridColumn6, + this.gridColumn7, + this.gridColumn8}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.IndicatorWidth = 50; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsView.ColumnAutoWidth = false; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn15 + // + this.gridColumn15.Caption = "ID"; + this.gridColumn15.FieldName = "fuid"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.OptionsColumn.AllowFocus = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 0; + this.gridColumn15.Width = 64; + // + // gridColumn4 + // + this.gridColumn4.Caption = "机器人类型"; + this.gridColumn4.FieldName = "robot_type"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 90; + // + // gridColumn9 + // + this.gridColumn9.Caption = "机器人名称"; + this.gridColumn9.FieldName = "robot_nick"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.OptionsColumn.AllowFocus = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 2; + this.gridColumn9.Width = 95; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn22.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "用户昵称"; + this.gridColumn22.FieldName = "usernick"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.OptionsColumn.AllowEdit = false; + this.gridColumn22.OptionsColumn.AllowFocus = false; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 3; + this.gridColumn22.Width = 138; + // + // gridColumn14 + // + this.gridColumn14.Caption = "用户账号"; + this.gridColumn14.FieldName = "username"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 4; + this.gridColumn14.Width = 121; + // + // gridColumn6 + // + this.gridColumn6.Caption = "任务名称"; + this.gridColumn6.FieldName = "activityname"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 5; + this.gridColumn6.Width = 169; + // + // gridColumn7 + // + this.gridColumn7.Caption = "领取时间"; + this.gridColumn7.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn7.FieldName = "get_time"; + this.gridColumn7.MinWidth = 120; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 6; + this.gridColumn7.Width = 145; + // + // gridColumn8 + // + this.gridColumn8.Caption = "兑换状态"; + this.gridColumn8.FieldName = "is_exchange"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.OptionsColumn.ReadOnly = true; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 7; + this.gridColumn8.Width = 102; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 516); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(984, 33); + this.pageControl2.TabIndex = 8; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.settingControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(984, 549); + this.xtraTabPage3.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(984, 549); + this.settingControl1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(986, 573); + this.Controls.Add(this.xtraTabControl2); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl2)).EndInit(); + this.xtraTabControl2.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.RadioButton radio_or; + private System.Windows.Forms.RadioButton radio_and; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.CheckBox check_invite_num; + private System.Windows.Forms.CheckBox check_point_num; + private System.Windows.Forms.CheckBox check_order_num; + private System.Windows.Forms.DateTimePicker time_end; + private System.Windows.Forms.DateTimePicker time_begin; + private System.Windows.Forms.TextBox text_name; + private System.Windows.Forms.Label label3; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.SettingControl settingControl1; + private System.Windows.Forms.Label label7; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit_ChatType; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private UI.Framework.Controls.PageControl pageControl2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 修改为兑换ToolStripMenuItem; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl6; + } +} \ No newline at end of file diff --git a/应用/FreeActivity/MainForm.cs b/应用/FreeActivity/MainForm.cs new file mode 100644 index 0000000..ea76f98 --- /dev/null +++ b/应用/FreeActivity/MainForm.cs @@ -0,0 +1,289 @@ +using Api.Framework; +using Api.Framework.Tools; +using FreeActivity.Entitys; +using FreeActivity.Properties; +using SqlSugar; +using System; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace FreeActivity +{ + public partial class MainForm : BaseForm + { + SqlSugarClient session = null; + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + session = ApiClient.GetSession(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + settingControl1.Bind(Class1.Config); + gridView1_DoubleClick(null, null); + + #region 加载所有的任务 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage($"select * from fl_plugin_freeactivity_info order by activity_time_end", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 50, true, true); + + label7.Visible = gridView1.RowCount == 0; + + #endregion + + #region 加载时间 + + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + parm.setOrderFields("exchange_time", false); + var result = session.FindPage($@"select +fu.id as fuid, +r.id as rid, +r.type as robot_type, +r.nick as robot_nick, +m.id as uid, +m.username as username, +m.usernick as usernick, +f.id as activityid, +f.name as activityname, +fu.get_time as get_time, +fu.exchange_time as exchange_time, +fu.is_exchange as is_exchange + from +fl_plugin_freeactivity_user_info fu INNER JOIN fl_plugin_freeactivity_info f on fu.activityid = f.id INNER JOIN fl_member_info m on fu.uid = m.id INNER JOIN fl_robot_info r on m.robot_name = r.name", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl2, 100, true, true); + + #endregion + } + + private void simpleButton_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(text_name.Text)) throw new Exception("活动名不能给空"); + if (string.IsNullOrWhiteSpace(checkedComboBoxEdit_ChatType.Text)) throw new Exception("请选择活动机器人"); + if (time_begin.Value >= time_end.Value) throw new Exception("领取结束时间不能晚于领取开始时间"); + if (!(check_order_num.Checked || check_point_num.Checked || check_invite_num.Checked)) throw new Exception("请选择活动条件"); + if (check_order_num.Checked) + if (numericUpDown1.Value == 0) + throw new Exception("条件订单数量不能为0"); + if (check_point_num.Checked) + if (numericUpDown2.Value == 0) + throw new Exception("条件返利金额不能为0"); + if (check_invite_num.Checked) + if (numericUpDown3.Value == 0) + throw new Exception("条件邀请人数不能为0"); + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("请填写商品链接"); + if (string.IsNullOrWhiteSpace(memoEdit1.Text)) throw new Exception("请填写免单商品介绍"); + + var name = text_name.Text.Trim(); + var mess = string.Empty; + var freeactivity_info = session.Find("name = @name", new { name = name }).FirstOrDefault(); + if (freeactivity_info == null) + { + freeactivity_info = new fl_plugin_freeactivity_info() + { + name = name, + robots = checkedComboBoxEdit_ChatType.Text.Trim(), + activity_time_begin = time_begin.Value, + activity_time_end = time_end.Value, + condition_relation = radio_and.Checked,//选中为并且关系 + + check_ordernum = check_order_num.Checked, + ordernum = (int)numericUpDown1.Value, + + check_pointsum = check_point_num.Checked, + pointsum = (int)numericUpDown2.Value, + + check_invitenum = check_invite_num.Checked, + invitenum = (int)numericUpDown3.Value, + goods_url = textBox1.Text, + goods_detail = memoEdit1.Text + }; + mess = "免单任务增加成功"; + } + else + { + freeactivity_info.name = name; + freeactivity_info.robots = checkedComboBoxEdit_ChatType.Text.Trim(); + freeactivity_info.activity_time_begin = time_begin.Value; + freeactivity_info.activity_time_end = time_end.Value; + freeactivity_info.condition_relation = radio_and.Checked;//选中为并且关系 + + freeactivity_info.check_ordernum = check_order_num.Checked; + freeactivity_info.ordernum = (int)numericUpDown1.Value; + + freeactivity_info.check_pointsum = check_point_num.Checked; + freeactivity_info.pointsum = (int)numericUpDown2.Value; + + freeactivity_info.check_invitenum = check_invite_num.Checked; + freeactivity_info.invitenum = (int)numericUpDown3.Value; + freeactivity_info.goods_url = textBox1.Text; + freeactivity_info.goods_detail = memoEdit1.Text; + + mess = "免单任务修改成功"; + } + session.Saveable(freeactivity_info).ExecuteCommand(); + ShowSuccess(mess); + pageControl1.GotoPage(); + label7.Visible = gridView1.RowCount == 0; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_DoubleClick(object sender, EventArgs e) + { + try + { + #region 将enum的值加载到列表中 修改的将勾选 + checkedComboBoxEdit_ChatType.Properties.Items.Clear(); + var clients = Chat.Framework.ChatClient.WXClient; + if (gridView1.GetSelectedRows().Length != 0) + { + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "id").ToString();//获取列的数据 + var freeactivity_info = session.Find($"select * from fl_plugin_freeactivity_info where id = '{id}'").FirstOrDefault(); + var chatList = freeactivity_info.robots.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList(); + foreach (var item in clients.Values) + { + if (chatList.FirstOrDefault(f => f == item.WeixinHao) != null) + checkedComboBoxEdit_ChatType.Properties.Items.Add(item.WeixinHao.ToString(), string.Empty, CheckState.Checked, true); + else + checkedComboBoxEdit_ChatType.Properties.Items.Add(item.WeixinHao.ToString(), string.Empty, CheckState.Unchecked, true); + } + + text_name.Text = freeactivity_info.name; + checkedComboBoxEdit_ChatType.Text = freeactivity_info.robots; + time_begin.Value = freeactivity_info.activity_time_begin; + time_end.Value = freeactivity_info.activity_time_end; + if (freeactivity_info.condition_relation) + radio_and.Checked = true; + else + radio_or.Checked = true; + check_order_num.Checked = freeactivity_info.check_ordernum; + numericUpDown1.Value = freeactivity_info.ordernum; + + check_point_num.Checked = freeactivity_info.check_pointsum; + numericUpDown2.Value = (decimal)freeactivity_info.pointsum; + + check_invite_num.Checked = freeactivity_info.check_invitenum; + numericUpDown3.Value = freeactivity_info.invitenum; + textBox1.Text = freeactivity_info.goods_url; + memoEdit1.Text = freeactivity_info.goods_detail; + } + else + { + foreach (var item in clients.Values) + { + //if (item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信) + checkedComboBoxEdit_ChatType.Properties.Items.Add(item.WeixinHao.ToString(), string.Empty, CheckState.Unchecked, true); + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.Caption == "活动状态") + { + var activity_time_begin = DateTime.Parse(gridView1.GetRowCellDisplayText(e.ListSourceRowIndex, "activity_time_begin")); + var activity_time_end = DateTime.Parse(gridView1.GetRowCellDisplayText(e.ListSourceRowIndex, "activity_time_end")); + var now = DateTime.Now; + if (now >= activity_time_end) + e.DisplayText = "活动已结束"; + else if (now < activity_time_begin) + e.DisplayText = "活动未开始"; + else if (activity_time_begin <= now && now < activity_time_end) + e.DisplayText = "活动进行中"; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Api.Framework.Tools.Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 修改为兑换ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + checkedComboBoxEdit_ChatType.Properties.Items.Clear(); + var clients = Chat.Framework.ChatClient.WXClient; + if (gridView2.GetSelectedRows().Length != 0) + { + var selectRow = gridView2.GetSelectedRows()[0]; + var is_exchange = this.gridView2.GetRowCellValue(selectRow, "is_exchange").ToString();//获取列的数据 + if (is_exchange == "是") throw new Exception("已经兑换,无法处理"); + var id = this.gridView2.GetRowCellValue(selectRow, "fuid").ToString();//获取列的数据 + var usernick = this.gridView2.GetRowCellValue(selectRow, "usernick").ToString();//获取列的数据 + var username = this.gridView2.GetRowCellValue(selectRow, "username").ToString();//获取列的数据 + var session = ApiClient.GetSession(); + if (MessageBox.Show($"确定要兑换 {usernick}({username}) 吗?", "确定提示", MessageBoxButtons.YesNo) == DialogResult.Yes) + { + session.ExcuteSQL("update fl_plugin_freeactivity_user_info set is_exchange = @is_exchange,exchange_time = @exchange_time where id = @id", new { is_exchange = true, exchange_time = DateTime.Now, id = id }); + pageControl2.GotoPage(); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/FreeActivity/MainForm.resx b/应用/FreeActivity/MainForm.resx new file mode 100644 index 0000000..8685fa7 --- /dev/null +++ b/应用/FreeActivity/MainForm.resx @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAAA6ZJREFUOE9Nk31Q03Ucx3+iqwzOhE6t + MxsDOcbDhgPtziPoCGXkJIq6FQsn0WSOjRKIpzTmgRMfuKwpA2zLjFUzIPAIXCDIIiYPTWyDxThQntp4 + iAeBjP569/3Nuut397r73X0/79fn87n7fqnJlQZq7qGJIt86wvqMC+yYXG2o7ng1p19pCFtQfsvtP6Hn + NGSVBwvJ+WMEj/m/zJTrzxvU1Eo9RblWje5wUhZrW6Y6yFhasw+tVhXsTgPmVrswNFMD09BZqJsFKPgy + tE9U6BdIN5p9eOuRgA4L0pnPZHwaPGwwHcPkchOGlyoxMK/Cnblc2BfPYHRZC9dqCxotBcjXcWeT8/24 + JOcxsVznFmx47zS7qc5cAMfCZXT8fgSdLgnMLhm6p+XomVGgZ1aOZrsYv81XoNV2GorPQqzbd3p60c2p + pGw//nFtLOx/lKPlvghtE2LcmnoXJqcEXU4pbk9LUXR1Lw5kMiE5z4ZjsRJltQk4VBSQSTen3v4ooKah + Ox83x9JwY1RIJMloG09BOxGZpg5DWsZG3icyjIw7wZdvww9Dh9E2WII0VaCZCDZSwkL/kXZHAa4PJ0Hd + EoUY2UbkacNgvPcWcqo4KNLkwDW7BMWZRFxuFeHHe+/g9oQSaaXsNSLwot7M8182OtJhsMUhRuqJPqsV + +RcyECv3docnpx/g/FfZUH0TR6YTo95xED9NyJF6KhAhkd7PUq9l+97X9wpgsO6DujERGcWvwjmzhKbO + DoxOLmJg9A4Sc7fDOJKK2qF4fGfno3bgdYg+DqAn2EQlKFjNZY1RuGLZi2uDAhRXx6K4QoaFB2tYWPkb + h5R7cPVnIQyDsdDboqH/9UWU34zBGzksCxF4Ui+Ld4jTz3HxhSUSFb27cM0mQFb5bujqS2Hqv47Uc/5k + vf240v8CPrdEoPpuNI5d4oEveV5JBI8TqCcFct+7J77moqo3AppuLlnnIFJKfBEppaBp34+qPh4qCdpf + dqOkjofED1g2Lx/G0yTrQQvWR8Rv5SVk+s1/qAsigjBoerhkTyGaho9CRybT9Owi8nAU6kOQlOO/Fh63 + JYrkGJ0T71OUaVxGSxjh8Vv3HJD5jqSc3Imi2iCou0JxqZuDi2YOTn4fjFRVAF45yhzgPQrTo69zZzvG + JLSAfokbyFg+0cnPFcZJmGaBnAU3Chb4R5jWl0Q7Tnk+xdhC6hh0PZ1zZ//7+VdE70Tb6Xu+meBD8CZs + IjxB8Ph/fceYhPoHAkQRj5PgdPMAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= + + + + 109, 17 + + + 56 + + \ No newline at end of file diff --git a/应用/FreeActivity/Properties/AssemblyInfo.cs b/应用/FreeActivity/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c7cf3de --- /dev/null +++ b/应用/FreeActivity/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("FreeActivity")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FreeActivity")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("8ba5cf87-767f-4d7a-996d-76d0cc790610")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/FreeActivity/Properties/Resources.Designer.cs b/应用/FreeActivity/Properties/Resources.Designer.cs new file mode 100644 index 0000000..fefbdb0 --- /dev/null +++ b/应用/FreeActivity/Properties/Resources.Designer.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace FreeActivity.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FreeActivity.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 免单活动 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 免单活动 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 活动插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 免单活动 { + get { + object obj = ResourceManager.GetObject("免单活动", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/FreeActivity/Properties/Resources.resx b/应用/FreeActivity/Properties/Resources.resx new file mode 100644 index 0000000..fd3d993 --- /dev/null +++ b/应用/FreeActivity/Properties/Resources.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 免单活动 + 插件窗体标题 + + + 活动插件 + 插件介绍 + + + 免单活动 + 插件名称 + + + + ..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\免单活动.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/FreeActivity/Properties/licenses.licx b/应用/FreeActivity/Properties/licenses.licx new file mode 100644 index 0000000..a360c69 --- /dev/null +++ b/应用/FreeActivity/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/FreeActivity/Resources/免单活动.png b/应用/FreeActivity/Resources/免单活动.png new file mode 100644 index 0000000..0bb0761 Binary files /dev/null and b/应用/FreeActivity/Resources/免单活动.png differ diff --git a/应用/FreeActivity/Resources/基础管理.png b/应用/FreeActivity/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/FreeActivity/Resources/基础管理.png differ diff --git a/应用/GroupManager/Class1.cs b/应用/GroupManager/Class1.cs new file mode 100644 index 0000000..e41daf1 --- /dev/null +++ b/应用/GroupManager/Class1.cs @@ -0,0 +1,109 @@ +using Api.Framework; +using Api.Framework.SDK; +using Chat.Framework.WXSdk.Implement; +using GroupManager.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace GroupManager +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.群管理; + this.Name = Resources.标题; + this.Note = Resources.介绍; + } + + #region 自定义变量 + //public static Config Config; + //private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + //if (session.TableExist()) + //{ + // var tbtgws = session.Find("select * from fl_plugin_tbrebate_tbtgw").ToList(); + // if (tbtgws != null) + // { + // foreach (var item in tbtgws) + // { + // //插入主推广位数据 + // session.Insertable(new fl_adzone_info() + // { + // adzone_name = item.pid_chief_name, //推广位名称 + // adzone_pid = item.pid_chief, //推广位pid + // adzone_pid_cps_name = item.pid_chief_cps_name, //推广位cps名称 + // alliance_id = (int)CpsType.阿里妈妈, //联盟id + // robot_id = item.robot_id, //机器人id + // group_id = string.Empty, //群id + // is_download = false, //不下载 + // member_id = 0, //私人id + // onoff = item.onoff, //不禁用 + // custom_type = Resources.SoftwareType, //自定义类型 + // extend = "chief" + // }).ExecuteCommand(); + // //插入副推广位数据 + // session.Insertable(new fl_adzone_info() + // { + // adzone_name = item.pid_deputy_name, //推广位名称 + // adzone_pid = item.pid_deputy, //推广位pid + // adzone_pid_cps_name = item.pid_deputy_cps_name, //推广位cps名称 + // alliance_id = (int)CpsType.阿里妈妈, //联盟id + // robot_id = item.robot_id, //机器人id + // group_id = string.Empty, //群id + // is_download = false, //不下载 + // member_id = 0, //私人id + // onoff = item.onoff, //不禁用 + // custom_type = Resources.SoftwareType, //自定义类型 + // extend = "deputy" + // }).ExecuteCommand(); + // } + // } + // session.DropTable(); + //} + //if (!session.TableExist()) + //{ + // session.CreateTable(); + // session.AddIndex("itemid");//增加索引. + // session.AddIndex("losetime");//增加索引. + //} + #endregion + + //创建配置文件 + //Config = this.ReadConfig(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + var ipad = sender as WXClientImpl_IPAD; + if (ipad == null) return; + var members = "wxid_vebvd7abpq1m22,wujiahua0876,wxid_qhs71yyalm0322,wxid_qhs71yyalm0322,wxid_fei0616"; + ipad.CreateChatRoom(members); + + } + catch (Exception ex) + { + this.OnLog(ex.Message + " - " + ex.StackTrace); + } + } + } +} diff --git a/应用/GroupManager/GroupManager.csproj b/应用/GroupManager/GroupManager.csproj new file mode 100644 index 0000000..be07ce7 --- /dev/null +++ b/应用/GroupManager/GroupManager.csproj @@ -0,0 +1,83 @@ + + + + + Debug + AnyCPU + {DF4B1E13-144C-4419-B289-FCA08A68BC23} + Library + Properties + GroupManager + GroupManager + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + ..\..\Debug\HttpHelper.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/GroupManager/Properties/AssemblyInfo.cs b/应用/GroupManager/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7cefe50 --- /dev/null +++ b/应用/GroupManager/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("GroupManager")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("GroupManager")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("df4b1e13-144c-4419-b289-fca08a68bc23")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/GroupManager/Properties/Resources.Designer.cs b/应用/GroupManager/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d1e02d4 --- /dev/null +++ b/应用/GroupManager/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace GroupManager.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GroupManager.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 群管理 的本地化字符串。 + /// + internal static string 介绍 { + get { + return ResourceManager.GetString("介绍", resourceCulture); + } + } + + /// + /// 查找类似 群管理 的本地化字符串。 + /// + internal static string 标题 { + get { + return ResourceManager.GetString("标题", resourceCulture); + } + } + + /// + /// 查找类似 群管理 的本地化字符串。 + /// + internal static string 窗体 { + get { + return ResourceManager.GetString("窗体", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 群管理 { + get { + object obj = ResourceManager.GetObject("群管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/GroupManager/Properties/Resources.resx b/应用/GroupManager/Properties/Resources.resx new file mode 100644 index 0000000..81dfa50 --- /dev/null +++ b/应用/GroupManager/Properties/Resources.resx @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 群管理 + + + 群管理 + + + 群管理 + + + + ..\Resources\群管理.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/GroupManager/Resources/群管理.jpg b/应用/GroupManager/Resources/群管理.jpg new file mode 100644 index 0000000..2c7f8d6 Binary files /dev/null and b/应用/GroupManager/Resources/群管理.jpg differ diff --git a/应用/HttpListener/ApiListener.csproj b/应用/HttpListener/ApiListener.csproj new file mode 100644 index 0000000..d28cd2e --- /dev/null +++ b/应用/HttpListener/ApiListener.csproj @@ -0,0 +1,127 @@ + + + + + Debug + AnyCPU + {549C5A6D-FB1C-4B29-9F8C-A1E334DB13F1} + Library + Properties + ApiListener + ApiListener + v4.6.1 + 512 + + + true + full + false + ..\..\主应用程序\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\主应用程序\Assembly\apifile\Api.Framework.dll + False + + + False + ..\..\主应用程序\Assembly\apifile\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + ..\..\主应用程序\Assembly\apifile\Easy4net.dll + False + + + False + ..\..\主应用程序\Assembly\apifile\HttpHelper.dll + False + + + + + + + + + + + + + False + ..\..\主应用程序\Assembly\apifile\UI.Framework.dll + False + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + MainForm.cs + Designer + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + + + + \ No newline at end of file diff --git a/应用/HttpListener/Class1.cs b/应用/HttpListener/Class1.cs new file mode 100644 index 0000000..83d916a --- /dev/null +++ b/应用/HttpListener/Class1.cs @@ -0,0 +1,92 @@ +using Api.Framework; +using Api.Framework.SDK; +using ApiListener; +using ApiListener.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HttpListener +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.Http监听; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + /// + /// 重写显示设置窗口 + /// + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.Activate(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Start() + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + //if (!session.TableExist()) session.CreateTable(); + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + //SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + + } + + +} diff --git a/应用/HttpListener/Config.cs b/应用/HttpListener/Config.cs new file mode 100644 index 0000000..4fc15d6 --- /dev/null +++ b/应用/HttpListener/Config.cs @@ -0,0 +1,39 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ApiListener +{ + [Config(Name = "插件-Api监听-配置")] + public class Config + { + /// + /// 监听的事件 + /// + public string ListenerEvents { get; set; } + /// + /// 监听链接 + /// + public string ListenerLinks { get; set; } + + + /// + /// 传递链接 + /// + public string SendLinks { get; set; } + /// + /// 传递的参数 + /// + public string Parameter { get; set; } + + /// + /// 加密解密key + /// + public string Key { get; set; } + + } + +} diff --git a/应用/HttpListener/MainForm.Designer.cs b/应用/HttpListener/MainForm.Designer.cs new file mode 100644 index 0000000..97e1903 --- /dev/null +++ b/应用/HttpListener/MainForm.Designer.cs @@ -0,0 +1,230 @@ +namespace HttpListener +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.tabPane1 = new DevExpress.XtraBars.Navigation.TabPane(); + this.tabNavigationPage1 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.checkedComboBoxEdit1 = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.tabNavigationPage2 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit2 = new DevExpress.XtraEditors.MemoEdit(); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).BeginInit(); + this.tabPane1.SuspendLayout(); + this.tabNavigationPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).BeginInit(); + this.tabNavigationPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).BeginInit(); + this.SuspendLayout(); + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn13.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn13.AppearanceCell.Options.UseFont = true; + this.gridColumn13.AppearanceCell.Options.UseForeColor = true; + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "副推广位"; + this.gridColumn13.FieldName = "pid_deputy_name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.Width = 158; + // + // tabPane1 + // + this.tabPane1.AllowCollapse = DevExpress.Utils.DefaultBoolean.Default; + this.tabPane1.Controls.Add(this.tabNavigationPage1); + this.tabPane1.Controls.Add(this.tabNavigationPage2); + this.tabPane1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabPane1.Location = new System.Drawing.Point(0, 0); + this.tabPane1.Name = "tabPane1"; + this.tabPane1.Pages.AddRange(new DevExpress.XtraBars.Navigation.NavigationPageBase[] { + this.tabNavigationPage1, + this.tabNavigationPage2}); + this.tabPane1.RegularSize = new System.Drawing.Size(709, 536); + this.tabPane1.SelectedPage = this.tabNavigationPage2; + this.tabPane1.Size = new System.Drawing.Size(709, 536); + this.tabPane1.TabIndex = 0; + this.tabPane1.Text = "tabPane1"; + // + // tabNavigationPage1 + // + this.tabNavigationPage1.Caption = "基 础 设 置"; + this.tabNavigationPage1.Controls.Add(this.groupControl3); + this.tabNavigationPage1.Name = "tabNavigationPage1"; + this.tabNavigationPage1.Size = new System.Drawing.Size(709, 508); + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.checkedComboBoxEdit1); + this.groupControl3.Controls.Add(this.label2); + this.groupControl3.Controls.Add(this.textBox1); + this.groupControl3.Controls.Add(this.label1); + this.groupControl3.Location = new System.Drawing.Point(52, 52); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(606, 409); + this.groupControl3.TabIndex = 0; + this.groupControl3.Text = "基础设置"; + // + // checkedComboBoxEdit1 + // + this.checkedComboBoxEdit1.Location = new System.Drawing.Point(185, 131); + this.checkedComboBoxEdit1.Name = "checkedComboBoxEdit1"; + this.checkedComboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit1.Size = new System.Drawing.Size(306, 20); + this.checkedComboBoxEdit1.TabIndex = 4; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(92, 134); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(43, 14); + this.label2.TabIndex = 3; + this.label2.Text = "事件:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(185, 75); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(306, 22); + this.textBox1.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(92, 78); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(87, 14); + this.label1.TabIndex = 0; + this.label1.Text = "加密解密Key:"; + // + // tabNavigationPage2 + // + this.tabNavigationPage2.Caption = "监听 | 投递 设置"; + this.tabNavigationPage2.Controls.Add(this.groupControl2); + this.tabNavigationPage2.Controls.Add(this.groupControl1); + this.tabNavigationPage2.Name = "tabNavigationPage2"; + this.tabNavigationPage2.Size = new System.Drawing.Size(709, 508); + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.memoEdit2); + this.groupControl2.Location = new System.Drawing.Point(12, 262); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(683, 231); + this.groupControl2.TabIndex = 3; + this.groupControl2.Text = "投递地址"; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.memoEdit1); + this.groupControl1.Location = new System.Drawing.Point(12, 14); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(683, 231); + this.groupControl1.TabIndex = 2; + this.groupControl1.Text = "监听地址"; + // + // memoEdit1 + // + this.memoEdit1.Dock = System.Windows.Forms.DockStyle.Fill; + this.memoEdit1.Location = new System.Drawing.Point(2, 21); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(679, 208); + this.memoEdit1.TabIndex = 0; + // + // memoEdit2 + // + this.memoEdit2.Dock = System.Windows.Forms.DockStyle.Fill; + this.memoEdit2.Location = new System.Drawing.Point(2, 21); + this.memoEdit2.Name = "memoEdit2"; + this.memoEdit2.Size = new System.Drawing.Size(679, 208); + this.memoEdit2.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(709, 536); + this.Controls.Add(this.tabPane1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).EndInit(); + this.tabPane1.ResumeLayout(false); + this.tabNavigationPage1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + this.groupControl3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).EndInit(); + this.tabNavigationPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraBars.Navigation.TabPane tabPane1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage2; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.MemoEdit memoEdit2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + } +} \ No newline at end of file diff --git a/应用/HttpListener/MainForm.cs b/应用/HttpListener/MainForm.cs new file mode 100644 index 0000000..51c52db --- /dev/null +++ b/应用/HttpListener/MainForm.cs @@ -0,0 +1,59 @@ +using ApiListener.Properties; +using System; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace HttpListener +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Api.Framework.Tools.Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/HttpListener/MainForm.resx b/应用/HttpListener/MainForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/HttpListener/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/HttpListener/Properties/AssemblyInfo.cs b/应用/HttpListener/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..72da184 --- /dev/null +++ b/应用/HttpListener/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("HttpListener")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HttpListener")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("549c5a6d-fb1c-4b29-9f8c-a1e334db13f1")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/HttpListener/Properties/Resources.Designer.cs b/应用/HttpListener/Properties/Resources.Designer.cs new file mode 100644 index 0000000..719c72e --- /dev/null +++ b/应用/HttpListener/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace ApiListener.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ApiListener.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap Http监听 { + get { + object obj = ResourceManager.GetObject("Http监听", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找类似 Api监听 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 Api监听 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 Api监听插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + } +} diff --git a/应用/HttpListener/Properties/Resources.resx b/应用/HttpListener/Properties/Resources.resx new file mode 100644 index 0000000..fec6ce4 --- /dev/null +++ b/应用/HttpListener/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\Http监听.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + Api监听 + 设置主窗体标题 + + + Api监听 + 插件名 + + + Api监听插件 + 插件介绍 + + \ No newline at end of file diff --git a/应用/HttpListener/Properties/licenses.licx b/应用/HttpListener/Properties/licenses.licx new file mode 100644 index 0000000..e69de29 diff --git a/应用/HttpListener/Resources/Http监听.png b/应用/HttpListener/Resources/Http监听.png new file mode 100644 index 0000000..3fc61ce Binary files /dev/null and b/应用/HttpListener/Resources/Http监听.png differ diff --git a/应用/JDRebate/Class1.cs b/应用/JDRebate/Class1.cs new file mode 100644 index 0000000..0049f43 --- /dev/null +++ b/应用/JDRebate/Class1.cs @@ -0,0 +1,938 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Api.Framework.Utils; +using Chat.Framework.WXSdk; +using CsharpHttpHelper; +using JDRebate.Entitys; +using JDRebate.Properties; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using static JDRebate.Enums; + +namespace JDRebate +{ + public class Class1 : Plugin + { + + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.京东; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + // public static VariateReplace variateReplace = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + // variateReplace = new VariateReplace(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void Stop() + { + try + { + SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.ChatType == CpsType.京东联盟) + { + var session = ApiClient.GetSession(); + //订单信息 + var order_jd = e.Order as fl_order_jingdong; + if (order_jd == null) return; + if (e.Member != null) + { + var robot_info = session.FindRobotInfo(e.Member.robot_name, e.Member.robot_type); + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject(order_jd.db_point) as ItemPoint; + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + mess = _GetOrderStateMess(order_jd.db_status, SettleType.未结算提示, order_jd, e.Member, point); + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order_jd.msg_groupid); + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order_jd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_OneLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_jd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_TwoLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_jd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_ThreeLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order_jd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_jd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_LeaderTip; + else if (order_jd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order_jd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order_jd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_jd, e.Member, point).Replace("[下级昵称]", e.Customer.realnick)); + + } + } + else//多人查询通知消息 + { + var querys = session.Find("select robot_name,type,userid from fl_query_hist where itemid=@itemid and adzoneid = @adzoneid and userid > 0 and crt_time>@time and is_multiple=@is_multiple group by userid,type,robot_name", new { itemid = order_jd.skuId, adzoneid = order_jd.positionId, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss"), is_multiple = false }); + if (querys.Count > 0) + { + for (int i = 0; i < querys.Count; i++) + { + try + { + if (querys[i].type != CpsType.京东联盟) continue; + //未绑定的数量 + var unbound_count = int.Parse(session.FindTable($"select count(id) as num from fl_order_jingdong where orderId = @orderId and db_userid != 0", new { orderId = order_jd.orderId }).Rows[0]["num"].ToString()); + if (unbound_count != 0) break;//已经被绑定直接停止 + + var queryhist_temp = querys[i]; + var userid = queryhist_temp.userid; + var robot_name = queryhist_temp.robot_name; + var robot_info = session.Find("select * from fl_robot_info where name = @name", new { name = robot_name }).FirstOrDefault();//机器人类型应该是没有的,直接通过机器人name查询机器人信息 + if (robot_info != null) + { + Thread.Sleep(5000); + var wxbase = Chat.Framework.ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot_name); + if (wxbase != null /*&& wxbase.WeixinType == WeixinType.Grpc微信*/ && wxbase.Status == WxStatus.在线) + { + var member = session.FindMemberInfoById(userid); + if (member != null) + { + ApiClient.SendMessage(robot_info, member.username, Config.LotUserQueryBindTip.Replace("[商品标题]", order_jd.skuName)); + + session.ExcuteSQL("update fl_query_hist set is_multiple = @is_multiple where itemid = @itemid and adzoneid = @adzoneid and robot_name = @robotname and userid = @userid", new { is_multiple = true, itemid = order_jd.skuId, adzoneid = order_jd.positionId, robotname = robot_name, userid = member.id }); + } + } + } + } + catch (Exception) + { } + } + } + } + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message},{ex.StackTrace}"); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + Compute compute = null; + string goodName = string.Empty; + try + { + //过滤表情xml和卡片xml + if ((e.Message.Contains(@"("select * from fl_order_jingdong where orderId = @orderId", new { orderId = orderId }); + + var _order = orders.FirstOrDefault(f => f.db_userid != 0 && f.db_userid != member.id); + if (_order != null) + { + e.SendMessage(Config.OccupyOrderErrorTip.Replace("[订单号]", orderId)); + return; + } + + if (orders != null && orders.Count != 0) + { + var notices = new List(); + var downJingdongTimer = new DownJingdongTimer(); + + #region 订单用户已经绑定 纯提示,非结算的订单也提示上级 + var bindOrders = orders.Where(f => f.db_userid != 0).ToList(); + if (bindOrders != null && bindOrders.Count != 0) + { + foreach (var order in bindOrders) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + member = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Config.OrderRepetBindTip, order, point, member)); + else + e.SendMessage(_GetOrderStateMess(order.db_status, (order.db_status == SystemOrderStatus.订单结算 ? SettleType.已结算提示 : SettleType.未结算提示), order, member, point)); + Thread.Sleep(500); + } + } + #endregion + + #region 订单没有被绑定(两种情况 => 一个订单已经被结算 一个是订单未结算) + var notBindOrders = orders.Where(f => f.db_userid == 0).ToList(); + if (notBindOrders != null && notBindOrders.Count != 0) + { + if (notBindOrders[0].orderTime < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderId},已经过了有效绑定时间!"); + return; + } + foreach (var order in notBindOrders) + { + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + + //没有绑定用户的订单进行绑定 + order.db_userid = member.id; + order.db_robotname = e.RobotName; + order.db_robottype = e.RobotInfo.type; + order.msg_groupid = e.Groupid; + + #region 手动绑定,重新计算用户的返利积分 + + //查询历史查询比例 + compute = db.FindQueryRatioHist(CpsType.京东联盟, order.id); + if (compute == null) + { + var query_item = db.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid order by id desc", new { userid = member.id, itemid = order.skuId, adzoneid = order.positionId }); + + //计算公式不为空 + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + try + { + compute = JsonConvert.DeserializeObject(query_item.compute_configdic); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = order.id, + createtime = DateTime.Now, + cpstype = CpsType.京东联盟 + }; + LogHelper.GetSingleObj().Error("历史查询记录5", JsonConvert.SerializeObject(queryRatioHist)); + db.SaveOrUpdate(queryRatioHist); + } + catch (Exception ex) + { + EventClient.OnEvent("京东计算", $"获取历史查询比异常:{ex.Message}"); + } + } + } + + ItemPoint itempoint = null; + + //计算的佣金 + if (compute != null) + itempoint = db.FindItemPoint(CpsType.京东联盟, compute, order.actualFee == 0 ? order.estimateFee : order.actualFee, (int)order.skuNum); + else + itempoint = db.FindItemPoint(member, order.actualFee == 0 ? order.estimateFee : order.actualFee, (int)order.skuNum, CpsType.京东联盟); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + } + #endregion + + if (member != null) + { + member.bind_order++; + member = db.UpdateMemberGroup(member); + } + + #region 首次付款时间 + var record = db.FindStatisticsRecord(member.id); + if (record == null) + { + record = new fl_statistics_record() { uid = member.id, ex2 = 0, ex4 = HttpExtend.GetTimeStamp(DateTime.Now), ex5 = HttpExtend.GetTimeStamp(order.orderTime) }; + db.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + record.ex4 = HttpExtend.GetTimeStamp(DateTime.Now); + record.ex5 = HttpExtend.GetTimeStamp(order.orderTime); + db.Saveable(record).ExecuteCommand(); + } + #endregion + + db.SaveOrUpdate(order); + + downJingdongTimer.UpdateOrder(order, db, notices, isFrontData: true); + } + } + #endregion + + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.IsRewards) + tasks.Add(item); + //else + //SDK_OrderNoticeEvent(this, item); + } + } + #endregion + + e.Cancel = true; + } + else + { + e.SendMessage(Config.NotFoundOrderErrorTip.Replace("[订单号]", orderId)); + + //加入缓存 + var bind = db.FindBindCache(orderId); + if (bind == null) + { + db.Insertable(new fl_bind_cache() { crt_time = DateTime.Now, db_robotid = e.RobotInfo.id, orderid = orderId, groupid = e.Groupid, db_userid = member.id }).ExecuteCommand(); + db.FindBindCache(orderId, true); + } + e.Cancel = true; + return; + } + } + + if (OrderHelper.IsOrderId(e.Message.Trim())) + return; + #endregion + + compute = null; + + #region 查询宝贝 + var jdinfoTemps = db.FindJdInfoTempGroups(); + var jdInfoTemp = jdinfoTemps.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (jdInfoTemp != null) + { + #region 京东解析商品图片 + string QRCodeUrl = string.Empty; + if (Config.QRCodeSearchSwitch == SwitchType.开启) + { + var reg_ = Regex.Match(e.Message, @"\[图片=(?<二维码图片>.+?)\]"); + if (reg_.Success) + QRCodeUrl = Util.DecodeQRCode(reg_.Groups["二维码图片"].Value);//解析的二维码图片所得到的二维码内容 + } + #endregion + + var itemId = JDHelper.GetJingdongItemId(string.IsNullOrEmpty(QRCodeUrl) ? e.Message : QRCodeUrl);//匹配京东链接获取京东宝贝ID + //this.OnLog($"京东商品编码:{itemId}"); + if (!string.IsNullOrEmpty(itemId)) + { + + JingdongApi api = null; + fl_cps_member jd_cps = null; + + var pid = string.Empty; + var isDefault = true; + + if (!string.IsNullOrWhiteSpace(e.Groupid))//群pid + { + var groupAdzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + pid = groupAdzone.adzone_pid; + jd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟 && f.username == groupAdzone.adzone_pid_cps_name); + isDefault = false; + } + } + + if (isDefault)//私人pid + { + var memberAdzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == member.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + pid = memberAdzone.adzone_pid; + jd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟 && f.username == memberAdzone.adzone_pid_cps_name); + isDefault = false; + } + } + + if (isDefault)//默认推广位 + { + pid = (member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? jdInfoTemp.pid_chief : jdInfoTemp.pid_deputy; + jd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟 && f.username == ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? jdInfoTemp.pid_chief_cps_name : jdInfoTemp.pid_deputy_cps_name));//通过判断用户的购物积分,来判断用户使用哪个推广位 + } + + if (jd_cps == null) { this.OnLog("京东联盟推广位异常,请检测后重试!"); return; } + + api = new JingdongApi(jd_cps); + + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + e.SendMessage(Config.SearchingTip);//正在搜索提示 + + var goodInfoResult = api.SendJingdong("jd.union.open.goods.query", new { goodsReqDTO = new { skuIds = new long[] { long.Parse(itemId) } } }); + + var goodData = goodInfoResult.ConvertToObj(); + if (goodData.data == null) throw new Exception("京东无返利信息"); + + foreach (Dictionary _goodinfo in goodData.data) + { + var goodinfo = _goodinfo.ConvertToObj(); + goodName = goodinfo.skuName = goodinfo.skuName.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); + + if (goodinfo.commissionInfo.Count != 0)//有佣金 + { + var isJdSale = goodinfo.isJdSale == 0 ? false : true;//是否已是京东自营 + + double price = double.Parse(goodinfo.priceInfo["price"].ToString()); //商品价格 + double lowestPrice = double.Parse(goodinfo.priceInfo["lowestPrice"].ToString()); //商品促销价格 + + var commissionshare = decimal.Parse(goodinfo.commissionInfo["commissionShare"].ToString()) / 100m;//普通用户佣金比例 ,通用接口中的佣金比例 + + #region 这里主要是获取改商品的实际佣金比例,上面的佣金比例是通用的佣金比例,会不准一些 + try + { + var goodResult = api.SendJingdong("jd.union.open.goods.promotiongoodsinfo.query", new { skuIds = itemId }); + if (goodResult != null && goodResult.ContainsKey("data")) + { + var _goodData = goodResult["data"] as ArrayList; + if (_goodData != null && _goodData.Count != 0) + { + foreach (Dictionary data in _goodData) + { + if (data.ContainsKey("commisionRatioWl")) + { + commissionshare = decimal.Parse(data["commisionRatioWl"].ToString()) / 100m; //接口中该商品的实际佣金,比较准一些, + break; + } + } + } + } + } + catch (Exception) + { } + #endregion + + #region plus用户的佣金比例 commissionshare_plus + // decimal commissionshare_plus = 0m; //plus会员佣金比例 + // int i = 0; + //Next: + // try + // { + + // var http = new HttpHelper(); + // var item = new HttpItem(); + // item.URL = @"https://union.jd.com/api/help/getCategoryCommiPlus?level=3&parentId= " + goodinfo.categoryInfo["cid2"].ToString(); + // var reuslt = http.GetHtml(item); + // var jsonObj = HttpExtend.JsonToDictionary(reuslt.Html); + // if (jsonObj["code"].ToString() == "200") + // { + // if (jsonObj.ContainsKey("data")) + // { + // var cid3 = goodinfo.categoryInfo["cid3"].ToString(); + // if (jsonObj.ContainsKey("data")) + // { + // var data = jsonObj["data"] as ArrayList; + // foreach (Dictionary obj in data) + // { + // if (obj["id"].ToString() == cid3) + // { + // //goodinfo.owner //g=自营,p=pop + // if (goodinfo.owner == "g") + // commissionshare_plus = decimal.Parse(obj["selfMobileComm"].ToString()); + // else + // commissionshare_plus = decimal.Parse(obj["popMobileComm"].ToString()); + // commissionshare_plus = commissionshare_plus / 100; + // break; + // } + // } + // } + // } + // } + // } + // catch (Exception ex) + // { + // this.OnLog(ex.Message); + // if (i <= 2) + // { + // i++; + // goto Next; + // } + // } + #endregion + + //原价的佣金 + ItemPoint usecoupon_commfee = null;//普通用户 用优惠券后积分信息 + //ItemPoint usecoupon_commfee_plus = null;//plus用户 用优惠券后积分信息 + //促销价的佣金 + ItemPoint usecoupon_commfee_lowest = null; + + double discount = -1; //优惠券金额 + List coupons = new List();//优惠券信息 + if (goodinfo.couponInfo.Count != 0) + { + var couponList = goodinfo.couponInfo["couponList"] as ArrayList; + if (couponList.Count != 0)//有优惠券 + { + Compute compute0 = null; + Compute compute_lowest = null; + foreach (Dictionary coupon in couponList) + { + ItemPoint _usecoupon_commfee = null; + //普通 + { + var quota = double.Parse(coupon["quota"].ToString()); //券消费限额 + if (quota <= price) //break;//优惠券面额大于商品单价时终止 + { + discount = double.Parse(coupon["discount"].ToString());//券面额 + #region 普通用户 + decimal usecoupon_totalcommfee = decimal.Round(((decimal)price - (decimal)discount) * commissionshare, 2);//券后 总佣金(自营) + if (!isJdSale) + usecoupon_totalcommfee = decimal.Round(usecoupon_totalcommfee * 0.9m, 2);//券后 总佣金(非自营) + _usecoupon_commfee = db.FindItemPoint(member, (double)usecoupon_totalcommfee, 1, CpsType.京东联盟, out compute0);//用券后 给用户的佣金 + #endregion + + #region plus用户 + //var usecoupon_totalcommfee_plus = decimal.Round(((decimal)price - (decimal)discount) * commissionshare_plus, 2);//plus 券后 总佣金(自营) + //if (!isJdSale) + // usecoupon_totalcommfee_plus = decimal.Round(usecoupon_totalcommfee_plus * 0.9m,2);//券后 总佣金(非自营) + //usecoupon_commfee_plus = session.FindItemPoint(member, (double)usecoupon_totalcommfee_plus, 1, CpsType.京东联盟);//plus 用券后 给用户的佣金 + #endregion + } + } + + ItemPoint _usecoupon_commfee_lowest = null; + //促销 + { + var quota = double.Parse(coupon["quota"].ToString()); //券消费限额 + if (quota <= lowestPrice) //break;//优惠券面额大于商品单价时终止 + { + discount = double.Parse(coupon["discount"].ToString());//券面额 + #region 普通用户 + decimal usecoupon_totalcommfee = decimal.Round(((decimal)lowestPrice - (decimal)discount) * commissionshare, 2);//券后 总佣金(自营) + if (!isJdSale) + usecoupon_totalcommfee = decimal.Round(usecoupon_totalcommfee * 0.9m, 2);//券后 总佣金(非自营) + _usecoupon_commfee_lowest = db.FindItemPoint(member, (double)usecoupon_totalcommfee, 1, CpsType.京东联盟, out compute_lowest);//用券后 给用户的佣金 + #endregion + } + } + + if (_usecoupon_commfee_lowest != null || _usecoupon_commfee != null) + { + coupons.Add(new Class1.coupon() { couponlike = coupon["link"].ToString(), discount = discount, isBest = int.Parse(coupon["isBest"].ToString()), usecoupon_commfee = _usecoupon_commfee, usecoupon_commfee_lowest = _usecoupon_commfee_lowest, compute_lowest = compute_lowest, compute = compute0 }); + } + } + } + } + + var buyshorturl = string.Empty; //转连后的地址 + #region 转连(生成自己推广的链接 [有券链接(二合一)或无券链接]) + Dictionary conversionlinkresult = null; //查询到的转换链接对象 + var positionId = pid.Substring(pid.LastIndexOf("_") + 1); + + //var custom = $"p_{positionId}_r_{e.RobotName}_u_{e.GetMemberinfo().username}_gid_{itemId}"; + + if (coupons.Count != 0) + { + coupons = coupons.OrderByDescending(s => s.isBest).ToList(); + for (int i = 0; i < coupons.Count; i++) + { + try + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{itemId}.html", positionId = positionId, unionId = jd_cps.usernick, couponUrl = coupons[i].couponlike, chainType = 3/*, subUnionId = custom*/ } }); + discount = coupons[i].discount; + usecoupon_commfee = coupons[i].usecoupon_commfee; + usecoupon_commfee_lowest = coupons[i].usecoupon_commfee; + compute = coupons[i].compute ?? coupons[i].compute_lowest; + break; + } + catch (Exception ex) + { + discount = -1; + conversionlinkresult = null; + compute = null; + continue; + } + } + } + + if (coupons.Count == 0 || conversionlinkresult == null) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{itemId}.html", positionId = positionId, unionId = jd_cps.usernick, chainType = 3/*, subUnionId = custom*/ } });//宝贝id 和 用户的目标推客的联盟id + } + + if (conversionlinkresult != null) + { + + #region 通过宝贝id查询接口返回的json样式 # + /* + //没有返利的样式 + { + result: { + apicodeenum: "user_unionid_err", + code: 411, + message: "unionid不正确,请检查unionid是否正确", + requestid: "21922_0b12a2ef_jul5xdgr_4036450" + }, + code: "0" + } + + //有返利的样式 + { + result: { + code: 200, + data: { + shorturl: "https://u.jd.com/q6xkht" + }, + message: "success", + requestid: "21922_0ab504e9_jul5xy3v_4135009" + }, + code: "0" + } + */ + #endregion + + if (conversionlinkresult["code"].ToString() != "200") throw new Exception($"京东查询接口调用失败:{conversionlinkresult["message"].ToString()}");//抛出错误信息 + if (conversionlinkresult.ContainsKey("data")) + { + var data = conversionlinkresult["data"] as Dictionary; + if (data.ContainsKey("shortURL")) buyshorturl = data["shortURL"].ToString();//购买短连接 + } + if (string.IsNullOrWhiteSpace(buyshorturl)) throw new Exception("京东转链失败,请稍后重试"); + } + #endregion + + #region 普通用户 + + Compute computeTmp = null; + //不用券 佣金 + var unusecoupon_totalcommfee = decimal.Round((decimal)price * commissionshare, 2);//券后 总佣金(自营) + if (!isJdSale) + unusecoupon_totalcommfee = decimal.Round(unusecoupon_totalcommfee * 0.9m, 2);//券后 总佣金(非自营) + //不用券 给用户的佣金 + var unusecoupon_commfee = db.FindItemPoint(member, (double)unusecoupon_totalcommfee, 1, CpsType.京东联盟, out computeTmp); + if (compute == null) + compute = computeTmp; + #endregion + + #region 促销用户 + //不用券 佣金 + var unusecoupon_totalcommfee_lowest = decimal.Round((decimal)lowestPrice * commissionshare, 2);//券后 总佣金(自营) + if (!isJdSale) + unusecoupon_totalcommfee_lowest = decimal.Round(unusecoupon_totalcommfee_lowest * 0.9m, 2);//券后 总佣金(非自营) + //不用券 给用户的佣金 + var unusecoupon_commfee_lowest = db.FindItemPoint(member, (double)unusecoupon_totalcommfee_lowest, 1, CpsType.京东联盟, out computeTmp); + if (compute == null) + compute = computeTmp; + #endregion + + + + #region Plus用户 + //plus 不用券 佣金 + //var unusecoupon_totalcommfee_plus = decimal.Round((decimal)price * commissionshare_plus, 2);//券后 总佣金(自营) + //if (!isJdSale) + // unusecoupon_totalcommfee_plus = decimal.Round(unusecoupon_totalcommfee_plus * 0.9m,2);//券后 总佣金(非自营) + //plus 不用券 给用户的佣金 + //var unusecoupon_commfee_plus = session.FindItemPoint(member, (double)unusecoupon_totalcommfee_plus, 1, CpsType.京东联盟); + #endregion + + var imageList = goodinfo.imageInfo["imageList"] as ArrayList; + string imageUrl = string.Empty; + if (imageList.Count > 0) + imageUrl = (imageList[0] as Dictionary)["url"].ToString(); //宝贝主图 + if (discount != -1) //有券的情况 + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithCouponTip))) + mess = Config.SearchSuccessWithCouponTip; + else + mess = Config.QQSearchSuccessWithCouponTip; + + e.SendMessage(mess + .Replace("劵", "券") + .Replace("[商品标题]", goodinfo.skuName) + .Replace("[商品原价]", goodinfo.priceInfo["price"].ToString()) + .Replace("[商品主图]", $"[图片={imageUrl}]") + .Replace("[图片地址]", imageUrl) + .Replace("[月销量]", goodinfo.inOrderCount30Days.ToString()) + .Replace("[券后返利]", usecoupon_commfee.UserPoint.ToString()) + .Replace("[弃券返利]", unusecoupon_commfee.UserPoint.ToString()) + //.Replace("[会员券后返利]", usecoupon_commfee_plus.UserPoint.ToString()) + //.Replace("[会员弃券返利]", unusecoupon_commfee_plus.UserPoint.ToString()) + .Replace("[券后价]", ((decimal)price - (decimal)discount).ToString()) + .Replace("[优惠券金额]", string.Format("{0:F}", discount)) + .Replace("[购买地址]", buyshorturl) + .Replace("[共节省]", ((decimal)discount + (decimal)usecoupon_commfee.UserPoint).ToString()) + + .Replace("[商品促销价]", string.Format("{0:F}", lowestPrice)) + .Replace("[促销价返利]", ((decimal)usecoupon_commfee_lowest.UserPoint).ToString()) + .Replace("[促销券后价]", ((decimal)lowestPrice - (decimal)discount).ToString()) + .Replace("[促销共节省]", (usecoupon_commfee_lowest == null ? ((decimal)discount + (decimal)usecoupon_commfee.UserPoint).ToString() : ((decimal)discount + (decimal)usecoupon_commfee_lowest.UserPoint).ToString())) + + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goodinfo.skuName, price.ToString(), discount.ToString(), ((decimal)price - (decimal)discount).ToString(), imageUrl, buyshorturl, ApiClient.QrImageType.模板B, CpsType.京东联盟) + "]" : string.Empty)); + } + else + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithoutCouponTip))) + mess = Config.SearchSuccessWithoutCouponTip; + else + mess = Config.QQSearchSuccessWithoutCouponTip; + + e.SendMessage(mess.Replace("[商品标题]", goodinfo.skuName) + .Replace("[商品原价]", goodinfo.priceInfo["price"].ToString()) + .Replace("[商品主图]", $"[图片={imageUrl}]") + .Replace("[图片地址]", imageUrl) + .Replace("[月销量]", goodinfo.inOrderCount30Days.ToString()) + .Replace("[返利积分]", string.Format("{0:F}", unusecoupon_commfee.UserPoint)) + //.Replace("[会员返利积分]", (unusecoupon_commfee_plus.UserPoint).ToString()) + .Replace("[购买地址]", buyshorturl) + .Replace("[共节省]", string.Format("{0:F}", unusecoupon_commfee.UserPoint)) + + .Replace("[商品促销价]", string.Format("{0:F}", lowestPrice)) + .Replace("[促销价返利]", ((decimal)unusecoupon_commfee_lowest.UserPoint).ToString()) + + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goodinfo.skuName, price.ToString(), "0", price.ToString(), imageUrl, buyshorturl, ApiClient.QrImageType.模板B, CpsType.京东联盟) + "]" : string.Empty) + ); + } + + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + db.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.京东联盟, + itemid = itemId, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = member.id, + title = goodinfo.skuName, + adzoneid = positionId, + compute_configdic = compute == null ? string.Empty : JsonConvert.SerializeObject(compute) + }).ExecuteCommand(); + db.UpdateRecord(member.id); + + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.京东联盟; + shared["msg_username"] = member.username; + shared["price"] = string.Format("{0:F}", lowestPrice); + shared["title"] = goodName; + shared["coupon_price"] = string.Format("{0:F}", (discount != -1 ? discount : 0)); + shared["user_point"] = discount != -1 ? string.Format("{0:F}", usecoupon_commfee_lowest.UserPoint) : string.Format("{0:F}", unusecoupon_commfee_lowest.UserPoint); + shared["economize"] = string.Format("{0:F}", (discount != -1 ? (usecoupon_commfee_lowest == null ? ((decimal)discount + (decimal)usecoupon_commfee.UserPoint) : ((decimal)discount + (decimal)usecoupon_commfee_lowest.UserPoint)) : (decimal)unusecoupon_commfee_lowest.UserPoint)); + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + + #endregion + } + } + } + } + #endregion + + } + catch (Exception ex) + { + if (ex.Message.Contains("商品不在推广中") || ex.Message.StartsWith("京东")) //自己抛出的错误,以京东开头 + { + e.SendMessage(Config.SearchNoCommissionTip); //提示没有返利提示 + + var session = ApiClient.GetSession(); + session.UpdateRecord(e.GetMemberinfo().id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.京东联盟; + shared["msg_username"] = e.GetMemberinfo().username; + shared["price"] = "未知"; + shared["title"] = goodName; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + return; + } + this.OnLog($"{ex.Message},{ex.StackTrace}"); + e.SendMessage(ApiClient.Setting.SystemConfig.msg_error); + } + } + + + /// + /// 订单状态 提示语替换 + /// + /// + /// + /// + private string _GetOrderStateMess(SystemOrderStatus order, SettleType settle, params object[] objs) + { + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.全额退款: + mess = new VariateReplace().CommonReplace(Config.OrderFrozen_AllTip, objs); + break; + case SystemOrderStatus.订单维权中: + mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(settle == SettleType.未结算提示 ? Config.OrderSettlementTip : Config.OrderAlreadySettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Config.OrderFreezeTip, objs); + break; + } + return mess; + } + + private class coupon + { + //优惠券链接 + public string couponlike { get; set; } + //券面额 + public double discount { get; set; } + //最优优惠券,1:是;0:否 + public int isBest { get; set; } + //分出佣金积分信息 + public ItemPoint usecoupon_commfee { get; set; } + + /// + /// 促销分出佣金积分信息 + /// + public ItemPoint usecoupon_commfee_lowest { get; set; } + + /// + /// 计算佣金的比例数据 + /// + public Compute compute { get; set; } + + /// + /// 促销计算佣金的比例数据 + /// + public Compute compute_lowest { get; set; } + } + + } +} diff --git a/应用/JDRebate/Config.cs b/应用/JDRebate/Config.cs new file mode 100644 index 0000000..9c763d9 --- /dev/null +++ b/应用/JDRebate/Config.cs @@ -0,0 +1,744 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System.ComponentModel; +using UI.Framework.Entitys; + +namespace JDRebate +{ + [Config(Name = "插件-京东返利-配置")] + public class Config + { + #region 消费积分设置 + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("01.主推广位使用条件 - 购物积分"), DefaultValue(20), + Description(@"用户消费积分≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int Point { get; set; } + + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("02.主推广位使用条件 - 订单笔数"), DefaultValue(20), + Description(@"用户交易订单数≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int OrderNum { get; set; } + #endregion + + #region 商品查询 + /// + /// 宝贝二维码识别功能 + /// + [ + Category("2)、商品查询"), DisplayName("01.智能图片识别"), DefaultValue(SwitchType.开启), Description(@"智能图片识别功能,开启可以通过宝贝中的二维码搜索宝贝") + ] + public SwitchType QRCodeSearchSwitch { get; set; } + + /// + /// 正在搜索宝贝提示语 + /// + [ + Category("2)、商品查询"), DisplayName("02.正在搜索提示"), DefaultValue(@"优惠信息查询中....."), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchingTip { get; set; } + + /// + /// 无佣金时提示 + /// + [ + Category("2)、商品查询"), DisplayName("03.无佣金时提示"), DefaultValue(@"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchNoCommissionTip { get; set; } + + /// + /// 无优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("04.无优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址领取优惠: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! + +注:京东Plus会员以实际返利为准"), + //Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[返利积分]、[会员返利积分]、[购买地址]、[共节省]、[商品图片] XML:[图片地址]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[返利积分]、[购买地址]、[共节省]、[商品促销价]、[促销价返利]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithoutCouponTip { get; set; } + + /// + /// 有优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("05.有优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +打开网址购买: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我 + +注:京东Plus会员以实际返利为准"), + //Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[优惠券金额]、[券后返利]、[弃券返利]、[会员券后返利]、[会员弃券返利]、[券后价]、[购买地址]、[共节省]、[商品图片]、XML:[图片地址]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[共节省]、[商品促销价]、[促销价返利]、[促销券后价]、[促销共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithCouponTip { get; set; } + + /// + /// 无优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("06.无优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""无优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[返利积分]、[购买地址]、[共节省]、[商品促销价]、[促销价返利]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithoutCouponTip { get; set; } + + /// + /// 有优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("07.有优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""有优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[共节省]、[商品促销价]、[促销价返利]、[促销券后价]、[促销共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithCouponTip { get; set; } + + #endregion + + #region 订单通知 + /// + /// 用户订单变化通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"01.用户订单变化通知"), DefaultValue(SwitchType.开启), Description(@"开启用户订单变化通知功能时,用户的订单发生变化时,将通知用户订单的情况") + ] + public SwitchType UserOrderChangeSwitch { get; set; } + /// + /// 代理获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"02.代理获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启代理获得提成通知功能时,用户的订单发生变化时,将通知代理获得提成信息") + ] + public SwitchType AgentReceivedCommissionSwitch { get; set; } + /// + /// 群负责人获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"03.群负责人获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启群负责人获得提成通知功能时,用户的订单发生变化时,将通知群负责人获得提成信息") + ] + public SwitchType PrincipalReceivedCommissionSwitch { get; set; } + + /// + /// 已被其他用户绑定 + /// + [Category("3)、订单通知"), DisplayName("04.已被其他用户绑定"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OccupyOrderErrorTip { get; set; } + + /// + /// 未找到订单号 + /// + [Category("3)、订单通知"), DisplayName("05.未找到订单号"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string NotFoundOrderErrorTip { get; set; } + + /// + /// 订单号未找到提示语 + /// + [Category("3)、订单通知"), DisplayName("06.重复绑定订单号"), DefaultValue(@"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRepetBindTip { get; set; } + + /// + /// 订单付款提示语 + /// + [Category("3)、订单通知"), DisplayName("07.订单付款"), DefaultValue(@"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentTip { get; set; } + + /// + /// 订单付款通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("08.订单付款通知一级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_OneLevelTip { get; set; } + + /// + /// 订单付款通知二级 + /// + [Category("3)、订单通知"), DisplayName("09.订单付款通知二级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_TwoLevelTip { get; set; } + + /// + /// 订单付款通知三级 + /// + [Category("3)、订单通知"), DisplayName("10.订单付款通知三级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_ThreeLevelTip { get; set; } + + /// + /// 订单付款通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("11.订单付款通知群负责人"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_LeaderTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("12.订单冻结"), DefaultValue(@"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFreezeTip { get; set; } + + /// + /// 订单已经结算提示语 + /// + [Category("3)、订单通知"), DisplayName("13.订单已经结算"), DefaultValue(@"一一一一订 单 已 经 结 算一一一一 + [商品标题] + 【订单编号】[订单号] + 【订单状态】该订单已经完成结算,请勿重复提交 + 一一一一一一一一一一一一一 + 发送关键词:兑换 (可兑换现金哦) + 发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderAlreadySettlementTip { get; set; } + + /// + /// 订单结算提示语 + /// + [Category("3)、订单通知"), DisplayName("14.订单结算"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlementTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("15.订单结算 - 全额退款"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFrozen_AllTip { get; set; } + + /// + /// 一级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("16.一级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_OneLevelTip { get; set; } + + /// + /// 二级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("17.二级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_TwoLevelTip { get; set; } + + /// + /// 三级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("18.三级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_ThreeLevelTip { get; set; } + + /// + /// 群负责人获得提成 + /// + [Category("3)、订单通知"), DisplayName("19.群负责人获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_LeaderTip { get; set; } + + /// + /// 订单退款提示语 + /// + [Category("3)、订单通知"), DisplayName("20.订单退款"), DefaultValue(@"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRefundTip { get; set; } + + /// + /// 客户维权一级代理 + /// + [Category("3)、订单通知"), DisplayName("21.客户维权一级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_OneLevelTip { get; set; } + + /// + /// 客户维权二级代理 + /// + [Category("3)、订单通知"), DisplayName("22.客户维权二级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_TwoLevelTip { get; set; } + + /// + /// 客户维权三级代理 + /// + [Category("3)、订单通知"), DisplayName("23.客户维权三级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_ThreeLevelTip { get; set; } + + /// + /// 客户维权群负责人 + /// + [Category("3)、订单通知"), DisplayName("24.客户维权群负责人"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_LeaderTip { get; set; } + + /// + /// 订单失效提示语 + /// + [Category("3)、订单通知"), DisplayName("25.订单失效"), DefaultValue(@"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFailureTip { get; set; } + + /// + /// 订单失效通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("26.订单失效通知一级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_OneLevelTip { get; set; } + + /// + /// 订单失效通知二级 + /// + [Category("3)、订单通知"), DisplayName("27.订单失效通知二级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_TwoLevelTip { get; set; } + + /// + /// 订单失效通知三级 + /// + [Category("3)、订单通知"), DisplayName("28.订单失效通知三级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_ThreeLevelTip { get; set; } + + /// + /// 订单失效通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("29.订单失效通知群负责人"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_LeaderTip { get; set; } + + [Category("3)、订单通知"), DisplayName("30.宝贝多人查询提示绑定"), DefaultValue(@"一一一一绑 定 提 示一一一一 +【商品标题】[商品标题] +该商品被多人查询系统无法匹配是谁下单,请亲手动到淘宝复制订单号给我手动绑定该订单"), + Description(@"多人查询同一个宝贝,导致无法自动绑定.则将推送该信息给查询过该宝贝的客户 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string LotUserQueryBindTip { get; set; } + + #endregion + + public Config() + { + this.Point = 20; + this.OrderNum = 20; + this.QRCodeSearchSwitch = SwitchType.开启; + this.UserOrderChangeSwitch = SwitchType.开启; + this.PrincipalReceivedCommissionSwitch = SwitchType.关闭; + this.AgentReceivedCommissionSwitch = SwitchType.关闭; + this.SearchingTip = @"优惠信息查询中....."; + this.QQSearchSuccessWithoutCouponTip = string.Empty; + this.QQSearchSuccessWithCouponTip = string.Empty; + this.OrderCountermandInform_LeaderTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_ThreeLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_TwoLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_OneLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.SearchSuccessWithCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +打开网址购买: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我 + +注:京东Plus会员以实际返利为准"; + this.SearchSuccessWithoutCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址领取优惠: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! + +注:京东Plus会员以实际返利为准"; + this.SearchNoCommissionTip = @"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"; + this.OrderRepetBindTip = @"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentTip = @"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentInform_OneLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderPaymentInform_TwoLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderPaymentInform_ThreeLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderPaymentInform_LeaderTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderFailureTip = @"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderFreezeTip = @"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"; + this.OrderRefundTip = @"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderAlreadySettlementTip = @"一一一一订 单 已 经 结 算一一一一 + [商品标题] + 【订单编号】[订单号] + 【订单状态】该订单已经完成结算,请勿重复提交 + 一一一一一一一一一一一一一 + 发送关键词:兑换 (可兑换现金哦) + 发送关键词:账单 (可查详细信息)"; + this.OrderSettlementTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OccupyOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"; + this.NotFoundOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"; + this.OrderFrozen_AllTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"; + // this.OrderFrozen_PartTip = @"一一一一订 单 结 算一一一一 + //[商品标题] + //【订单编号】[订单号] + //【付款金额】[付款金额] 元 + //【维权返利积分】[维权返利积分] [积分名称] + //【可兑换积分】[可兑换积分] [积分名称] + //一一一一一一一一一一一一一 + //由于订单维权,部分退款,返利将相应减少 + //发送关键词:兑换 (可兑换现金哦) + //发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_OneLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_TwoLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_ThreeLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_LeaderTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.LotUserQueryBindTip = @"一一一一绑 定 提 示一一一一 +【商品标题】[商品标题] +该商品被多人查询系统无法匹配是谁下单,请亲手动到淘宝复制订单号给我手动绑定该订单"; + this.ClientOrderRefund_OneLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_TwoLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_ThreeLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_LeaderTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + + } + + } +} diff --git a/应用/JDRebate/Entitys/goodInfo_temp.cs b/应用/JDRebate/Entitys/goodInfo_temp.cs new file mode 100644 index 0000000..0946a16 --- /dev/null +++ b/应用/JDRebate/Entitys/goodInfo_temp.cs @@ -0,0 +1,275 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JDRebate.Entitys +{ + public class CategoryInfo + { + /// + /// 一级类目ID + /// + public long cid1 { get; set; } + /// + /// 一级类目名称 + /// + public string cid1Name { get; set; } + /// + /// 二级类目ID + /// + public long cid2 { get; set; } + /// + /// 二级类目名称 + /// + public string cid2Name { get; set; } + /// + /// 三级类目ID + /// + public long cid3 { get; set; } + /// + /// 三级类目名称 + /// + public string cid3Name { get; set; } + } + + public class CommissionInfo + { + /// + /// 佣金 + /// + public double commission { get; set; } + /// + /// 佣金比例 + /// + public double commissionShare { get; set; } + } + + public class Coupon + { + /// + /// 券种类 (优惠券种类:0 - 全品类,1 - 限品类(自营商品),2 - 限店铺,3 - 店铺限商品券) + /// + public int bindType { get; set; } + /// + /// 券面额 + /// + public double discount { get; set; } + /// + /// 券领取结束时间(时间戳,毫秒) + /// + public long getEndTime { get; set; } + /// + /// 领取开始时间(时间戳,毫秒) + /// + public long getStartTime { get; set; } + /// + /// 券链接 + /// + public string link { get; set; } + /// + /// 券使用平台 (平台类型:0 - 全平台券,1 - 限平台券) + /// + public int platformType { get; set; } + /// + /// 券消费限额 + /// + public double quota { get; set; } + /// + /// 券有效使用结束时间(时间戳,毫秒) + /// + public long useEndTime { get; set; } + /// + /// 券有效使用开始时间(时间戳,毫秒) + /// + public long useStartTime { get; set; } + } + + public class CouponInfo + { + /// + /// 优惠券合集 + /// + //public List couponList { get; set; } + public Dictionary couponList { get; set; } + } + + public class UrlInfo + { + /// + /// 图片链接地址,第一个图片链接为主图链接 + /// + public string url { get; set; } + } + + public class ImageInfo + { + /// + /// 图片合集 + /// + //public List imageList { get; set; } + public Dictionary imageList { get; set; } + } + + /// + /// 拼购信息 + /// + public class PinGouInfo + { + } + + /// + /// 已废弃,请使用pinGouInfo + /// + public class PingGouInfo + { + } + /// + /// + /// + public class PriceInfo + { + /// + /// 价格信息 + /// + public double price { get; set; } + } + + public class ShopInfo + { + /// + /// 店铺Id + /// + public int shopId { get; set; } + /// + /// 店铺名称(或供应商名称) + /// + public string shopName { get; set; } + } + + /// + /// 数据明细 + /// + public class GoodsResp + { + /// + /// 品牌code + /// + public string brandCode { get; set; } + /// + /// 品牌名 + /// + public string brandName { get; set; } + /// + /// 类目信息 + /// + //public List categoryInfo { get; set; } + public Dictionary categoryInfo { get; set; } + /// + /// 评论数 + /// + public long comments { get; set; } + /// + /// 佣金信息 + /// + //public List commissionInfo { get; set; } + public Dictionary commissionInfo { get; set; } + /// + /// 优惠券信息,返回内容为空说明该SKU无可用优惠券 + /// + //public List couponInfo { get; set; } + public Dictionary couponInfo { get; set; } + /// + /// 商品好评率 + /// + public double goodCommentsShare { get; set; } + /// + /// 图片信息 + /// + //public List imageInfo { get; set; } + public Dictionary imageInfo { get; set; } + /// + /// 30天支出佣金 + /// + public double inOrderComm30Days { get; set; } + /// + /// 30天引单量 + /// + public long inOrderCount30Days { get; set; } + /// + /// 是否爆款,1:是,0:否 + /// + public int isHot { get; set; } + /// + /// 是否自营 (1 : 是, 0 : 否),后续会废弃,请用owner + /// + public int isJdSale { get; set; } + /// + /// 商品落地页 + /// + public string materialUrl { get; set; } + /// + /// g=自营,p=pop + /// + public string owner { get; set; } + /// + /// 拼购信息 + /// + //public List pinGouInfo { get; set; } + public Dictionary pinGouInfo { get; set; } + /// + /// 已废弃,请使用pinGouInfo + /// + //public List pingGouInfo { get; set; } + public Dictionary pingGouInfo { get; set; } + /// + /// 价格信息 + /// + //public List priceInfo { get; set; } + public Dictionary priceInfo { get; set; } + /// + /// 店铺信息 + /// + //public List shopInfo { get; set; } + public Dictionary shopInfo { get; set; } + /// + /// 商品ID + /// + public long skuId { get; set; } + /// + /// 商品名称 + /// + public string skuName { get; set; } + /// + /// spuid,其值为同款商品的主skuid + /// + public long spuid { get; set; } + } + + public class goodInfo_temp + { + /// + /// 返回码 + /// + public int code { get; set; } + /// + /// 数据明细 + /// + //public List data { get; set; } + public ArrayList data { get; set; } + /// + /// 返回消息 + /// + public string message { get; set; } + /// + /// + /// + public string requestId { get; set; } + /// + /// 有效商品总数量,上限10w + /// + public long totalCount { get; set; } + } +} diff --git a/应用/JDRebate/Entitys/jdinfo_temp.cs b/应用/JDRebate/Entitys/jdinfo_temp.cs new file mode 100644 index 0000000..4b43870 --- /dev/null +++ b/应用/JDRebate/Entitys/jdinfo_temp.cs @@ -0,0 +1,100 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JDRebate.Entitys +{ + /// + /// 临时的表 (用于数据显示) + /// + public class jdinfo_temp + { + /// + /// id + /// + public long ID { get; set; } + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string name { get; set; } + + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 主推广位cps名称 + /// + private string _pid_chief_cps_name { get; set; } + public string pid_chief_cps_name + { + get { return _pid_chief_cps_name; } + set { _pid_chief_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_chief; + /// + /// 主推广位id + /// + public string pid_chief + { + get { return _pid_chief; } + set { _pid_chief = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 主推广位昵称 + /// + private string _pid_chief_name; + + public string pid_chief_name + { + get { return _pid_chief_name; } + set { _pid_chief_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位cps名称 + /// + private string _pid_deputy_cps_name { get; set; } + public string pid_deputy_cps_name + { + get { return _pid_deputy_cps_name; } + set { _pid_deputy_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位id + /// + private string _pid_deputy; + + public string pid_deputy + { + get { return _pid_deputy; } + set { _pid_deputy = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位名称 + /// + private string _pid_deputy_name; + + public string pid_deputy_name + { + get { return _pid_deputy_name; } + set { _pid_deputy_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } +} diff --git a/应用/JDRebate/Entitys/promotion_info.cs b/应用/JDRebate/Entitys/promotion_info.cs new file mode 100644 index 0000000..5d42621 --- /dev/null +++ b/应用/JDRebate/Entitys/promotion_info.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JDRebate.Entitys +{ + /// + /// 通过查询商品id,返回的信息 + /// + public class promotion_info + { + //message:接口返回结果描述,result:商品推广信息实体类,sucessed:接口是否调用成功(true:成功,false:失败),skuId:SKUID,goodsName:商品名称,unitPrice:商品单价即京东价,wlUnitPrice:商品无线京东价(单价为-1表示未查询到改商品单价)imgUrl:图片地址 commisionRatioPc:PC佣金比例,commisionRatioWl:无线佣金比例,shopId:店铺ID,materialUrl:商品落地页,startDate:推广开始日期,endDate:推广结束日期,imgUrl:图片地址,WlUnitPrice:商品无线京东价(单价为-1表示未查询到改商品单价),cid2:二级类目,cid3:三级类目,vid:商家id,isJdSale:是否自营(1:是,0:否),isFreeShipping:是否包邮(1:是,0:否,2:自营商品遵从主站包邮规则),isFreeFreightRisk:是否支持运费险(1:是,0:否),isSeckill:是否秒杀(1:是,0:否),cid:一级类目名称,cidName:一级级类目名称,inOrderCount:30天引单数量 + + /// + /// 接口返回结果描述 + /// + public string message { get; set; } + + /// + /// 商品推广信息实体类 + /// + public string result { get; set; } + + /// + /// 接口是否调用成功 + /// + public bool sucessed { get; set; } + + /// + /// 接口返回结果描述 + /// + public long skuId { get; set; } + + /// + /// 商品名称 + /// + public string goodsName { get; set; } + + /// + /// 商品单价即京东价 + /// + public string unitPrice { get; set; } + + /// + /// 商品无线京东价(单价为-1表示未查询到改商品单价) + /// + public string wlUnitPrice { get; set; } + + /// + /// 图片地址 + /// + public string imgUrl { get; set; } + + /// + /// PC佣金比例 + /// + public string commisionRatioPc { get; set; } + + /// + /// 无线佣金比例 + /// + public string commisionRatioWl { get; set; } + + /// + /// 店铺ID + /// + public string shopId { get; set; } + + /// + /// 商品落地页 + /// + public string materialUrl { get; set; } + + /// + /// 推广开始日期 + /// + public DateTime startDate { get; set; } + + /// + /// 推广结束日期 + /// + public DateTime endDate { get; set; } + + /// + /// 二级类目 + /// + public string cid2 { get; set; } + + /// + /// 三级类目 + /// + public string cid3 { get; set; } + + /// + /// 商家id + /// + public string vid { get; set; } + + /// + /// 是否自营(1:是,0:否) + /// + public string isJdSale { get; set; } + + /// + /// 是否包邮(1:是,0:否,2:自营商品遵从主站包邮规则) + /// + public string isFreeShipping { get; set; } + + /// + /// 是否支持运费险(1:是,0:否) + /// + public string isFreeFreightRisk { get; set; } + + /// + /// 是否秒杀(1:是,0:否) + /// + public string isSeckill { get; set; } + + /// + /// 一级类目名称 + /// + public string cid { get; set; } + + /// + /// 一级级类目名称 + /// + public string cidName { get; set; } + + /// + /// 30天引单数量 + /// + public string inOrderCount { get; set; } + + } +} diff --git a/应用/JDRebate/Entitys/queryhist_temp.cs b/应用/JDRebate/Entitys/queryhist_temp.cs new file mode 100644 index 0000000..ea20ca0 --- /dev/null +++ b/应用/JDRebate/Entitys/queryhist_temp.cs @@ -0,0 +1,16 @@ +using Api.Framework.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JDRebate.Entitys +{ + public class queryhist_temp + { + public string robot_name { get; set; } + public CpsType type { get; set; } + public long userid { get; set; } + } +} diff --git a/应用/JDRebate/Enums.cs b/应用/JDRebate/Enums.cs new file mode 100644 index 0000000..c469750 --- /dev/null +++ b/应用/JDRebate/Enums.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JDRebate +{ + public class Enums + { + /// + /// 结账提示类型 + /// + public enum SettleType + { + 已结算提示 = 0, + 未结算提示 = 1 + } + } +} diff --git a/应用/JDRebate/JDRebate.csproj b/应用/JDRebate/JDRebate.csproj new file mode 100644 index 0000000..2dffab9 --- /dev/null +++ b/应用/JDRebate/JDRebate.csproj @@ -0,0 +1,135 @@ + + + + + Debug + AnyCPU + {7BB4FC1F-DFB0-43B1-85B0-A343DB109843} + Library + Properties + JDRebate + JDRebate + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + \ No newline at end of file diff --git a/应用/JDRebate/MainForm.Designer.cs b/应用/JDRebate/MainForm.Designer.cs new file mode 100644 index 0000000..ffd465a --- /dev/null +++ b/应用/JDRebate/MainForm.Designer.cs @@ -0,0 +1,274 @@ +namespace JDRebate +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(979, 529); + this.xtraTabControl1.TabIndex = 8; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(973, 500); + this.xtraTabPage1.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(224, 189); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 7; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 463); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(973, 37); + this.pageControl1.TabIndex = 5; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(973, 457); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "平台类型"; + this.gridColumn1.FieldName = "chattype"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 110; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 164; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 138; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "主推广位"; + this.gridColumn5.FieldName = "pid_chief_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 148; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "副推广位"; + this.gridColumn7.FieldName = "pid_deputy_name"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 130; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "禁止使用"; + this.gridColumn9.FieldName = "onoff"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 6; + this.gridColumn9.Width = 109; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(973, 515); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(973, 515); + this.settingControl1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(979, 529); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing_1); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + } +} \ No newline at end of file diff --git a/应用/JDRebate/MainForm.cs b/应用/JDRebate/MainForm.cs new file mode 100644 index 0000000..7ec5e93 --- /dev/null +++ b/应用/JDRebate/MainForm.cs @@ -0,0 +1,270 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using JDRebate.Entitys; +using JDRebate.Properties; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace JDRebate +{ + public partial class MainForm : BaseForm + { + SqlSugarClient session = null; + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + session = ApiClient.GetSession(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + this.settingControl1.Bind(Class1.Config,110); + + #region 加载所有的账号 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.京东联盟}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.京东联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id", parm); + + label1.Visible = result.Total == 0; + + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + + + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name" || e.Column.FieldName == "adzone_activity_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + /// + /// 创建fl_adzone_info对象 + /// + /// + /// + /// + /// + /// + /// + private fl_adzone_info CreateAdzoneInfo(string adzone_name, string adzone_pid, string adzone_pid_cps_name, string rid, string item, bool onoff = false) + { + return new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = adzone_name, //推广位名称 + adzone_pid = adzone_pid, //推广位pid + adzone_pid_cps_name = adzone_pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.京东联盟, //联盟id + robot_id = int.Parse(rid), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = onoff, //不禁用 + extend = item + }; + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.京东联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzone == null) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzone.extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + #region 有出现两个重复无法修复的情况,删除一个 + var repetAdzone = adzones.Where(f => f.extend == pidName).ToList(); + if (repetAdzone.Count > 1) + { + for (int i = 1; i <= repetAdzone.Count - 1; i++) + { + session.Deleteable(repetAdzone[i]).ExecuteCommand(); + } + adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + } + #endregion + + adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + + pageControl1.GotoPage(1); + session.FindJdInfoTempGroups(true); + session.FindAdzoneInfos(true); + session.FindJingdongAutoBindPid(true);//刷新推广位 + } + } + } + #endregion + + #region 开关单元格单击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzones.Count == 0) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item, false); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzones[0].extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate, adzones[0].onoff); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + if (adzones != null)//数据库中存在 + { + session.ExcuteSQL("update fl_adzone_info set onoff = @onoff where robot_id = @robot_id and alliance_id = @alliance_id and custom_type = @custom_type", new { onoff = !adzones[0].onoff, robot_id = id, alliance_id = (int)CpsType.京东联盟, custom_type = Resources.SoftwareType }); + } + session.FindJdInfoTempGroups(true); + pageControl1.GotoPage(1); + session.FindAdzoneInfos(true); + session.FindJingdongAutoBindPid(true); + } + } + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing_1(object sender, FormClosingEventArgs e) + { + try + { + Api.Framework.Tools.Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/JDRebate/MainForm.resx b/应用/JDRebate/MainForm.resx new file mode 100644 index 0000000..dc533a5 --- /dev/null +++ b/应用/JDRebate/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 48 + + \ No newline at end of file diff --git a/应用/JDRebate/Properties/AssemblyInfo.cs b/应用/JDRebate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0091feb --- /dev/null +++ b/应用/JDRebate/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("JDRebate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("JDRebate")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("7bb4fc1f-dfb0-43b1-85b0-a343db109843")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/JDRebate/Properties/Resources.Designer.cs b/应用/JDRebate/Properties/Resources.Designer.cs new file mode 100644 index 0000000..4b7eb18 --- /dev/null +++ b/应用/JDRebate/Properties/Resources.Designer.cs @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace JDRebate.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JDRebate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 京东返利 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 京东返利 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 京东返利插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 京东返利 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 京东 { + get { + object obj = ResourceManager.GetObject("京东", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 活动推广 { + get { + object obj = ResourceManager.GetObject("活动推广", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/JDRebate/Properties/Resources.resx b/应用/JDRebate/Properties/Resources.resx new file mode 100644 index 0000000..668a903 --- /dev/null +++ b/应用/JDRebate/Properties/Resources.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 京东返利 + 插件窗体标题 + + + 京东返利 + 插件名称 + + + 京东返利插件 + 插件介绍 + + + 京东返利 + + + + ..\Resources\京东.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\活动推广.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/JDRebate/Properties/licenses.licx b/应用/JDRebate/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/JDRebate/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/JDRebate/Resources/京东.png b/应用/JDRebate/Resources/京东.png new file mode 100644 index 0000000..f44ee98 Binary files /dev/null and b/应用/JDRebate/Resources/京东.png differ diff --git a/应用/JDRebate/Resources/基础管理.png b/应用/JDRebate/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/JDRebate/Resources/基础管理.png differ diff --git a/应用/JDRebate/Resources/活动推广.png b/应用/JDRebate/Resources/活动推广.png new file mode 100644 index 0000000..727aa42 Binary files /dev/null and b/应用/JDRebate/Resources/活动推广.png differ diff --git a/应用/JDRebate/SessionExt.cs b/应用/JDRebate/SessionExt.cs new file mode 100644 index 0000000..334c792 --- /dev/null +++ b/应用/JDRebate/SessionExt.cs @@ -0,0 +1,42 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using JDRebate.Entitys; +using JDRebate.Properties; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JDRebate +{ + public static class SessionExt + { + const string jdinfo_temp_list_jdrebate = "jdinfo_temp_list_jdrebates"; + + /// + /// 获取fl_adzone_info表的数据集合缓存 + /// + /// + /// 刷新 + /// + public static List FindJdInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + var jdinfo_temp_groups = ApiClient.Cache.Get>(jdinfo_temp_list_jdrebate);//根据KEY、获得缓存 + if (refresh || jdinfo_temp_groups == null) + { + jdinfo_temp_groups = session.Find($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = @allianceId and ai1.custom_type = @customType and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = @allianceId and ai2.custom_type = @customType and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id", new { allianceId = (int)CpsType.京东联盟, customType = Resources.SoftwareType }); + ApiClient.Cache.Set(jdinfo_temp_list_jdrebate, jdinfo_temp_groups, 60); + } + return jdinfo_temp_groups; + } + + public static void Clear() + { + ApiClient.Cache.Remove(jdinfo_temp_list_jdrebate); + } + } +} diff --git a/应用/KSRebate/Class1.cs b/应用/KSRebate/Class1.cs new file mode 100644 index 0000000..25896a4 --- /dev/null +++ b/应用/KSRebate/Class1.cs @@ -0,0 +1,483 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using KSRebate.Properties; + +namespace KSRebate +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.快手; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + //创建配置文件 + Config = this.ReadConfig(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.ChatType == CpsType.快手联盟) + { + var session = ApiClient.GetSession(); + //订单信息 + var order_ks = e.Order as fl_order_kuaishou; + + if (order_ks == null) return; + + if (e.Member != null) + { + #region 订单变化通知消息 + var robot_info = session.FindRobotInfo(e.Member.robot_name.Trim(), e.Member.robot_type); + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject(order_ks.db_point) as ItemPoint; + #region 下单用户订单检测(防撸) + if (e.Customer == null) + { + var prevent_theft_cache = session.FindSingle("select * from fl_prevent_theft_cache where order_id = @order_id", new { order_id = order_ks.oid });//防止上级多次触发 + if (prevent_theft_cache == null) + { + var isHint = false; + if (order_ks.sellerId != 0 && e.Member.status != MemberType.白名单) + { + #region 同一店铺多次购买(同一商品) + if (Class1.Config.AShop_SameCommodity_Switch) + { + var frequency = session.Find("select * from fl_order_kuaishou where db_userid = @db_userid and itemId = @itemId", new { db_userid = order_ks.db_userid, itemId = order_ks.itemId }).Count;//获取同价店铺同一件商品购买的次数 + if (Class1.Config.AShop_SameCommodity_Number <= frequency) + { + if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_ks, e.Member, point), order_ks.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户购买同一商品{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_SameCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_ks.itemId.ToString(); + prevent_theft_cache.mall_id = order_ks.sellerId.ToString(); + prevent_theft_cache.order_id = order_ks.oid.ToString(); + prevent_theft_cache.cps_type = CpsType.快手联盟; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_SameCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name); + if (wx != null) + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + + return; + } + } + else if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户购买同一商品{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + + #region 同一店铺多次购买(不同商品) + if (!isHint && Class1.Config.AShop_DifferentCommodity_Switch) + { + var frequency = session.Find("select * from fl_order_kuaishou where db_userid = @db_userid and sellerId = @sellerId", new { db_userid = order_ks.db_userid, sellerId = order_ks.sellerId }).Count; + if (Class1.Config.AShop_DifferentCommodity_Number <= frequency) + { + if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_ks, e.Member, point), order_ks.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_DifferentCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_ks.itemId.ToString(); + prevent_theft_cache.mall_id = order_ks.sellerId.ToString(); + prevent_theft_cache.order_id = order_ks.oid.ToString(); + prevent_theft_cache.cps_type = CpsType.快手联盟; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_DifferentCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name); + if (wx != null) + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + + return; + } + } + else if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + } + + #region 收货时间验证时长 + if (!isHint && Class1.Config.ReceivingTimeCheck_Switch && (order_ks.cpsOrderStatus == CpsOrderStatus.已收货 || order_ks.cpsOrderStatus == CpsOrderStatus.已结算) && e.Member.status != MemberType.白名单) + { + if (order_ks.settlementSuccessTime != DateTime.MinValue) + { + var timeLag = (int)Math.Floor((order_ks.settlementSuccessTime - order_ks.payTime).TotalHours); + if (timeLag <= Class1.Config.ReceivingTimeCheck_Hour) + { + if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_ks, e.Member, point), order_ks.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + e.Cancel = true; + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.ReceivingTimeCheck_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_ks.itemId.ToString(); + prevent_theft_cache.mall_id = order_ks.sellerId.ToString(); + prevent_theft_cache.order_id = order_ks.oid.ToString(); + prevent_theft_cache.cps_type = CpsType.快手联盟; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.ReceivingTimeCheck_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name); + if (wx != null) + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + return; + } + } + else if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + } + } + } + } + #endregion + + } + } + #endregion + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + { + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + mess = _GetOrderStateMess(order_ks.db_status, order_ks, e.Member, point); + + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order_ks.msg_groupid); + } + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order_ks.db_status == SystemOrderStatus.全额退款) + mess = Config.ClientOrderRefund_OneLevelTip; + if (order_ks.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order_ks.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order_ks.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_ks.db_status == SystemOrderStatus.全额退款) + mess = Config.ClientOrderRefund_TwoLevelTip; + if (order_ks.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order_ks.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order_ks.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_ks.db_status == SystemOrderStatus.全额退款) + mess = Config.ClientOrderRefund_ThreeLevelTip; + if (order_ks.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order_ks.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order_ks.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_ks.db_status == SystemOrderStatus.全额退款) + mess = Config.ClientOrderRefund_LeaderTip; + if (order_ks.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order_ks.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order_ks.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_ks, e.Member, point).Replace("[下级昵称]", e.Customer.realnick ?? "")); + } + #endregion + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + //过滤表情xml和卡片xml + if ((e.Message.Contains(@" {e.Message} => " + stopWatch.Elapsed.TotalSeconds.ToString("0.0000")); + //返利消息判断 + if (flag) return; + + + } + catch (Exception ex) + { + this.OnLog($"快手返利插件异常.:{ex.Message} - {ex.StackTrace}"); + } + } + + #region 变量替换 + /// + /// 订单状态 提示语替换 + /// + /// + /// + /// + public static string _GetOrderStateMess(SystemOrderStatus order, params object[] objs) + { + + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Class1.Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Class1.Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.全额退款: + mess = new VariateReplace().CommonReplace(Class1.Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.部分退款: + case SystemOrderStatus.订单维权中: + //mess = new VariateReplace().CommonReplace(Class1.Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(Class1.Config.OrderSettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Class1.Config.OrderFreezeTip, objs); + break; + } + return mess; + } + #endregion + + + } + +} diff --git a/应用/KSRebate/Config.cs b/应用/KSRebate/Config.cs new file mode 100644 index 0000000..bcf111d --- /dev/null +++ b/应用/KSRebate/Config.cs @@ -0,0 +1,896 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.Enums; +using Api.Framework.SDK; +using UI.Framework.Entitys; + +namespace KSRebate +{ + [Config(Name = "插件-快手返利-配置")] + public class Config + { + #region 消费积分设置 + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("01.主推广位使用条件 - 购物积分"), DefaultValue(20), + Description(@"用户消费积分≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int Point { get; set; } + + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("02.主推广位使用条件 - 订单笔数"), DefaultValue(20), + Description(@"用户交易订单数≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int OrderNum { get; set; } + #endregion + + #region 提示语 + + /// + /// 正在搜索宝贝提示语 + /// + [ + Category("2)、商品查询"), DisplayName("01.正在搜索宝贝"), DefaultValue(@"优惠信息查询中....."), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchingTip { get; set; } + + /// + /// 搜索宝贝无佣金 + /// + [ + Category("2)、商品查询"), DisplayName("02.无佣金时提示"), DefaultValue(@"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[关键词]、链接无返利变量:[商品标题]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchNoCommissionTip { get; set; } + + /// + /// 无优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("03.有佣金时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[店铺名称]、[返利积分]、[购买地址]、[购买口令]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithoutCouponTip { get; set; } + + /// + /// 无优惠券时提示(QQ) + /// + [ + Category("2)、商品查询"), DisplayName("04.有佣金时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""无优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[店铺名称]、[返利积分]、[购买地址]、[购买口令]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithoutCouponTip { get; set; } + + #endregion + + #region 订单通知 + + /// + /// 用户订单变化通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"01.用户订单变化通知"), DefaultValue(SwitchType.开启), Description(@"开启用户订单变化通知功能时,用户的订单发生变化时,将通知用户订单的情况") + ] + public SwitchType UserOrderChangeSwitch { get; set; } + /// + /// 代理获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"02.代理获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启代理获得提成通知功能时,用户的订单发生变化时,将通知代理获得提成信息") + ] + public SwitchType AgentReceivedCommissionSwitch { get; set; } + /// + /// 群负责人获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"03.群负责人获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启群负责人获得提成通知功能时,用户的订单发生变化时,将通知群负责人获得提成信息") + ] + public SwitchType PrincipalReceivedCommissionSwitch { get; set; } + + /// + /// 绑定订单号非本人提示语 + /// + [Category("3)、订单通知"), DisplayName("04.已被其他用户绑定"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OccupyOrderErrorTip { get; set; } + + /// + /// 订单号未找到提示语 + /// + [Category("3)、订单通知"), DisplayName("05.未找到订单号"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string NotFoundOrderErrorTip { get; set; } + + /// + /// 重复绑定订单号 + /// + [Category("3)、订单通知"), DisplayName("06.重复绑定订单号"), DefaultValue(@"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRepetBindTip { get; set; } + + /// + /// 订单付款提示语 + /// + [Category("3)、订单通知"), DisplayName("07.订单付款"), DefaultValue(@"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentTip { get; set; } + + /// + /// 订单付款通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("08.订单付款通知一级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_OneLevelTip { get; set; } + + /// + /// 订单付款通知二级 + /// + [Category("3)、订单通知"), DisplayName("09.订单付款通知二级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_TwoLevelTip { get; set; } + + /// + /// 订单付款通知三级 + /// + [Category("3)、订单通知"), DisplayName("10.订单付款通知三级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_ThreeLevelTip { get; set; } + + /// + /// 订单付款通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("11.订单付款通知群负责人"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_LeaderTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("12.订单冻结"), DefaultValue(@"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFreezeTip { get; set; } + + /// + /// 订单已经结算提示语 + /// + [Category("3)、订单通知"), DisplayName("13.订单已经结算"), DefaultValue(@"一一一一订 单 已 经 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【订单状态】该订单已经完成结算,请勿重复提交 +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderAlreadySettlementTip { get; set; } + + /// + /// 订单结算提示语 + /// + [Category("3)、订单通知"), DisplayName("14.订单结算"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlementTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("15.订单结算 - 全额退款"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【维权金额】[维权金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"), + Description(@"订单维权成功提示,维权类型为全额退款 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[维权金额]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFrozen_AllTip { get; set; } + + /// + /// 一级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("17.一级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_OneLevelTip { get; set; } + + /// + /// 二级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("18.二级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_TwoLevelTip { get; set; } + + /// + /// 三级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("19.三级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_ThreeLevelTip { get; set; } + + /// + /// 群负责人获得提成 + /// + [Category("3)、订单通知"), DisplayName("20.群负责人获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_LeaderTip { get; set; } + + /// + /// 订单退款提示语 + /// + [Category("3)、订单通知"), DisplayName("21.订单申请维权"), DefaultValue(@"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"用户申请退款通知改提示 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRefundTip { get; set; } = @"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + + /// + /// 客户维权一级代理 + /// + [Category("3)、订单通知"), DisplayName("22.客户维权一级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_OneLevelTip { get; set; } = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + + /// + /// 客户维权二级代理 + /// + [Category("3)、订单通知"), DisplayName("23.客户维权二级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_TwoLevelTip { get; set; } = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + + /// + /// 客户维权三级代理 + /// + [Category("3)、订单通知"), DisplayName("24.客户维权三级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_ThreeLevelTip { get; set; } = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + + /// + /// 客户维权群负责人 + /// + [Category("3)、订单通知"), DisplayName("25.客户维权群负责人"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_LeaderTip { get; set; } = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + + /// + /// 订单失效提示语 + /// + [Category("3)、订单通知"), DisplayName("26.订单失效"), DefaultValue(@"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFailureTip { get; set; } + + + /// + /// 订单失效通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("27.订单失效通知一级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_OneLevelTip { get; set; } + + /// + /// 订单失效通知二级 + /// + [Category("3)、订单通知"), DisplayName("28.订单失效通知二级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_TwoLevelTip { get; set; } + + /// + /// 订单失效通知三级 + /// + [Category("3)、订单通知"), DisplayName("29.订单失效通知三级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_ThreeLevelTip { get; set; } + + /// + /// 订单失效通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("30.订单失效通知群负责人"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_LeaderTip { get; set; } + + + // /// + // /// 宝贝多人查询提示绑定 + // /// + // [Category("3)、订单通知"), DisplayName("31.宝贝多人查询提示绑定"), DefaultValue(@"一一一一绑 定 提 示一一一一 + //【商品标题】[商品标题] + //该商品被多人查询系统无法匹配是谁下单,请亲手动到淘宝复制订单号给我手动绑定该订单"), + // Description(@"多人查询同一个宝贝,导致无法自动绑定.则将推送该信息给查询过该宝贝的客户 + //支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + // public string LotUserQueryBindTip { get; set; } + + #endregion + + #region 查询限制设置 + /// + /// 店铺ID限制提示 + /// + [Category("4)、限制通知"), DisplayName("01.店铺ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[店铺ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SellerIDRestrictTip { get; set; } + + /// + /// 商品ID限制提示 + /// + [Category("4)、限制通知"), DisplayName("02.商品ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ItemIDRestrictTip { get; set; } + + /// + /// 拉黑提示 + /// + [Category("4)、限制通知"), DisplayName("03.用户被拉黑"), DefaultValue(@"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string Blocked_RestrictTip { get; set; } + + #endregion + + #region 防撸设置 + /// + /// 同一店铺多次购买(同一商品)开关 + /// + [Browsable(false)] + public bool AShop_SameCommodity_Switch { get; set; } + + /// + /// 同一店铺多次购买(同一商品)数量 + /// + [Browsable(false)] + public int AShop_SameCommodity_Number { get; set; } + + /// + /// 同一店铺多次购买(同一商品)处理方式 + /// + [Browsable(false)] + public OperateType AShop_SameCommodity_OperateType { get; set; } + + /// + /// 同一店铺多次购买(同一商品)置顶 + /// + [Browsable(false)] + public bool AShop_SameCommodity_UserTop { get; set; } + + /// + /// 同一店铺多次购买(不同商品)开关 + /// + [Browsable(false)] + public bool AShop_DifferentCommodity_Switch { get; set; } + + /// + /// 同一店铺多次购买(不同商品)数量 + /// + [Browsable(false)] + public int AShop_DifferentCommodity_Number { get; set; } + + /// + /// 同一店铺多次购买(不同商品)置顶 + /// + [Browsable(false)] + public bool AShop_DifferentCommodity_UserTop { get; set; } + + /// + /// 同一店铺多次购买(不同商品)处理方式 + /// + [Browsable(false)] + public OperateType AShop_DifferentCommodity_OperateType { get; set; } + + /// + /// 收货时间验证开关 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_Switch { get; set; } + + /// + /// 收货时间验证时长(小时) + /// + [Browsable(false)] + public int ReceivingTimeCheck_Hour { get; set; } + + /// + /// 收货时间验证处理方式 + /// + [Browsable(false)] + public OperateType ReceivingTimeCheck_OperateType { get; set; } + + /// + /// 收货时间验证置顶 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_UserTop { get; set; } + + /// + /// 收货时间验证订单冻结时间 + /// + [Browsable(false)] + public int ReceivingTimeCheck_FreezeTime { get; set; } + + /// + /// 屏蔽的商品ID集合 + /// + [Browsable(false)] + public List ItemIDRestrictList { get; set; } + + /// + /// 屏蔽的卖家ID集合 + /// + [Browsable(false)] + public List SellerIDRestrictlist { get; set; } + + ///// + ///// 钉钉Api + ///// + //[Browsable(false)] + //public string Abnormal_DingDingApi { get; set; } + + ///// + ///// 钉钉token值 + ///// + //[Browsable(false)] + //public string Abnormal_DingDingApiToken { get; set; } + + [Browsable(false)] + public string notice_robotname { get; set; } + + #endregion + + public Config() + { + this.SellerIDRestrictTip = @"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"; + this.ItemIDRestrictTip = @"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"; + this.Blocked_RestrictTip = @"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"; + + this.AShop_SameCommodity_Switch = false; + this.AShop_SameCommodity_Number = 10; + this.AShop_SameCommodity_OperateType = OperateType.通知钉钉群; + this.AShop_SameCommodity_UserTop = false; + this.AShop_DifferentCommodity_Switch = false; + this.AShop_DifferentCommodity_Number = 10; + this.AShop_DifferentCommodity_UserTop = false; + this.AShop_DifferentCommodity_OperateType = OperateType.通知钉钉群; + this.ReceivingTimeCheck_Switch = false; + this.ReceivingTimeCheck_Hour = 24; + this.ReceivingTimeCheck_OperateType = OperateType.订单冻结; + this.ReceivingTimeCheck_FreezeTime = 24; + this.ReceivingTimeCheck_UserTop = false; + this.notice_robotname = string.Empty; + + this.ItemIDRestrictList = new List(); + this.SellerIDRestrictlist = new List(); + + this.Point = 20; + this.OrderNum = 20; + this.UserOrderChangeSwitch = SwitchType.开启; + this.PrincipalReceivedCommissionSwitch = SwitchType.关闭; + this.AgentReceivedCommissionSwitch = SwitchType.关闭; + this.QQSearchSuccessWithoutCouponTip = string.Empty; + this.SearchingTip = @"优惠信息查询中....."; + this.SearchSuccessWithoutCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"; + this.SearchNoCommissionTip = @"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"; + this.OrderRepetBindTip = @"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentTip = @"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentInform_OneLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_TwoLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_ThreeLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_LeaderTip = @"一一一一下 级 付 款一一一一 +【下级昵称】 [下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderFailureTip = @"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderCountermandInform_OneLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_TwoLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_ThreeLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_LeaderTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderFreezeTip = @"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"; + this.OrderAlreadySettlementTip = @"一一一一订 单 已 经 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【订单状态】该订单已经完成结算,请勿重复提交 +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlementTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OccupyOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"; + this.NotFoundOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"; + this.OrderFrozen_AllTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【维权金额】[维权金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_OneLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_TwoLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_ThreeLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_LeaderTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + // this.ClientOrderRefund_OneLevelTip = @"一一一一客 户 维 权一一一一 + //【下级昵称】[下级昵称] + //【维权金额】[一级提成积分] [积分名称] + //【剩余积分】[剩余积分] [积分名称] + //一一一一一一一一一一一一一 + //发送关键词:兑换 (可兑换现金哦) + //发送关键词:账单 (可查详细信息)"; + // this.ClientOrderRefund_TwoLevelTip = @"一一一一客 户 维 权一一一一 + //【下级昵称】[下级昵称] + //【维权金额】[二级提成积分] [积分名称] + //【剩余积分】[剩余积分] [积分名称] + //一一一一一一一一一一一一一 + //发送关键词:兑换 (可兑换现金哦) + //发送关键词:账单 (可查详细信息)"; + // this.ClientOrderRefund_ThreeLevelTip = @"一一一一客 户 维 权一一一一 + //【下级昵称】[下级昵称] + //【维权金额】[三级提成积分] [积分名称] + //【剩余积分】[剩余积分] [积分名称] + //一一一一一一一一一一一一一 + //发送关键词:兑换 (可兑换现金哦) + //发送关键词:账单 (可查详细信息)"; + // this.ClientOrderRefund_LeaderTip = @"一一一一客 户 维 权一一一一 + //【下级昵称】[下级昵称] + //【维权金额】[群负责人提成积分] [积分名称] + //【剩余积分】[剩余积分] [积分名称] + //一一一一一一一一一一一一一 + //发送关键词:兑换 (可兑换现金哦) + //发送关键词:账单 (可查详细信息)"; + // this.LotUserQueryBindTip = @"一一一一绑 定 提 示一一一一 + //【商品标题】[商品标题] + //该商品被多人查询系统无法匹配是谁下单,请亲手动到淘宝复制订单号给我手动绑定该订单"; + } + + } +} diff --git a/应用/KSRebate/Entitys/ksinfo_temp.cs b/应用/KSRebate/Entitys/ksinfo_temp.cs new file mode 100644 index 0000000..1b376ac --- /dev/null +++ b/应用/KSRebate/Entitys/ksinfo_temp.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.SDK; + +namespace KSRebate.Entitys +{ + /// + /// 临时的表 (用于数据显示) + /// + public class ksinfo_temp + { + public long ID { get; set; } + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string name { get; set; } + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 主推广位cps名称 + /// + private string _pid_chief_cps_name { get; set; } + public string pid_chief_cps_name + { + get { return _pid_chief_cps_name; } + set { _pid_chief_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_chief; + /// + /// 主推广位id + /// + public string pid_chief + { + get { return _pid_chief; } + set { _pid_chief = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 主推广位昵称 + /// + private string _pid_chief_name; + + public string pid_chief_name + { + get { return _pid_chief_name; } + set { _pid_chief_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位cps名称 + /// + private string _pid_deputy_cps_name { get; set; } + public string pid_deputy_cps_name + { + get { return _pid_deputy_cps_name; } + set { _pid_deputy_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_deputy; + + /// + /// 副推广位id + /// + public string pid_deputy + { + get { return _pid_deputy; } + set { _pid_deputy = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 副推广位名称 + /// + private string _pid_deputy_name; + + public string pid_deputy_name + { + get { return _pid_deputy_name; } + set { _pid_deputy_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } +} diff --git a/应用/KSRebate/KSRebate.csproj b/应用/KSRebate/KSRebate.csproj new file mode 100644 index 0000000..ee83fc6 --- /dev/null +++ b/应用/KSRebate/KSRebate.csproj @@ -0,0 +1,131 @@ + + + + + Debug + AnyCPU + {BD719746-8782-4DA2-9469-75A03E02FAB9} + Library + Properties + KSRebate + KSRebate + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + Form + + + MainForm.cs + + + + + True + True + Resources.resx + + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + \ No newline at end of file diff --git a/应用/KSRebate/MainForm.Designer.cs b/应用/KSRebate/MainForm.Designer.cs new file mode 100644 index 0000000..87fe018 --- /dev/null +++ b/应用/KSRebate/MainForm.Designer.cs @@ -0,0 +1,794 @@ +namespace KSRebate +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl19 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox4 = new System.Windows.Forms.ComboBox(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit6 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown4 = new System.Windows.Forms.NumericUpDown(); + this.comboBox3 = new System.Windows.Forms.ComboBox(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl32 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl31 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.xtraTabPage3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(991, 577); + this.xtraTabControl1.TabIndex = 8; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.simpleButton1); + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage1.Text = " 设 置 推 广 位 "; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(760, 514); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(205, 29); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "检测淘宝发单推广位重复项"; + this.simpleButton1.Visible = false; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(224, 189); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 7; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 514); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(989, 37); + this.pageControl1.TabIndex = 5; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(989, 508); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "平台类型"; + this.gridColumn1.FieldName = "chattype"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 110; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 164; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 138; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "主推广位"; + this.gridColumn5.FieldName = "pid_chief_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 148; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "副推广位"; + this.gridColumn7.FieldName = "pid_deputy_name"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 130; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "禁止使用"; + this.gridColumn9.FieldName = "onoff"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 6; + this.gridColumn9.Width = 109; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(989, 551); + this.settingControl1.TabIndex = 0; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupBox1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage3.Text = " 防 撸 设 置 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.labelControl19); + this.groupBox1.Controls.Add(this.comboBox4); + this.groupBox1.Controls.Add(this.labelControl20); + this.groupBox1.Controls.Add(this.separatorControl2); + this.groupBox1.Controls.Add(this.separatorControl1); + this.groupBox1.Controls.Add(this.checkBox3); + this.groupBox1.Controls.Add(this.checkBox2); + this.groupBox1.Controls.Add(this.checkBox1); + this.groupBox1.Controls.Add(this.buttonCheck2); + this.groupBox1.Controls.Add(this.buttonCheck1); + this.groupBox1.Controls.Add(this.buttonCheck); + this.groupBox1.Controls.Add(this.memoEdit6); + this.groupBox1.Controls.Add(this.memoEdit5); + this.groupBox1.Controls.Add(this.numericUpDown2); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.numericUpDown4); + this.groupBox1.Controls.Add(this.comboBox3); + this.groupBox1.Controls.Add(this.comboBox2); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Controls.Add(this.labelControl30); + this.groupBox1.Controls.Add(this.labelControl32); + this.groupBox1.Controls.Add(this.numericUpDown3); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl31); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl29); + this.groupBox1.Controls.Add(this.labelControl28); + this.groupBox1.Controls.Add(this.labelControl27); + this.groupBox1.Location = new System.Drawing.Point(38, 25); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(916, 498); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础设置 "; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(651, 188); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(215, 14); + this.labelControl5.TabIndex = 60; + this.labelControl5.Text = "(在【系统管理->群通知机器人】中添加)"; + // + // labelControl19 + // + this.labelControl19.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl19.Appearance.Options.UseForeColor = true; + this.labelControl19.Location = new System.Drawing.Point(505, 188); + this.labelControl19.Name = "labelControl19"; + this.labelControl19.Size = new System.Drawing.Size(130, 14); + this.labelControl19.TabIndex = 59; + this.labelControl19.Text = "(未选择时使用系统设置)"; + // + // comboBox4 + // + this.comboBox4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox4.FormattingEnabled = true; + this.comboBox4.Location = new System.Drawing.Point(170, 185); + this.comboBox4.Name = "comboBox4"; + this.comboBox4.Size = new System.Drawing.Size(308, 22); + this.comboBox4.TabIndex = 58; + // + // labelControl20 + // + this.labelControl20.Location = new System.Drawing.Point(73, 188); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(91, 14); + this.labelControl20.TabIndex = 57; + this.labelControl20.Text = "群通知API接口:"; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(44, 103); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(823, 23); + this.separatorControl2.TabIndex = 32; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(44, 50); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(823, 23); + this.separatorControl1.TabIndex = 32; + // + // checkBox3 + // + this.checkBox3.AutoSize = true; + this.checkBox3.Location = new System.Drawing.Point(651, 133); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.Size = new System.Drawing.Size(108, 18); + this.checkBox3.TabIndex = 31; + this.checkBox3.Text = "置顶用户(微信)"; + this.checkBox3.UseVisualStyleBackColor = true; + this.checkBox3.Visible = false; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(651, 81); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(108, 18); + this.checkBox2.TabIndex = 31; + this.checkBox2.Text = "置顶用户(微信)"; + this.checkBox2.UseVisualStyleBackColor = true; + this.checkBox2.Visible = false; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(651, 28); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(108, 18); + this.checkBox1.TabIndex = 31; + this.checkBox1.Text = "置顶用户(微信)"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.Visible = false; + // + // buttonCheck2 + // + this.buttonCheck2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = true; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(89, 132); + this.buttonCheck2.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(57, 22); + this.buttonCheck2.TabIndex = 28; + // + // buttonCheck1 + // + this.buttonCheck1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = true; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(89, 79); + this.buttonCheck1.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(57, 22); + this.buttonCheck1.TabIndex = 28; + // + // buttonCheck + // + this.buttonCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck.Checked = true; + this.buttonCheck.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck.Location = new System.Drawing.Point(89, 26); + this.buttonCheck.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck.Name = "buttonCheck"; + this.buttonCheck.Size = new System.Drawing.Size(57, 22); + this.buttonCheck.TabIndex = 28; + // + // memoEdit6 + // + this.memoEdit6.Location = new System.Drawing.Point(50, 389); + this.memoEdit6.Name = "memoEdit6"; + this.memoEdit6.Size = new System.Drawing.Size(817, 96); + this.memoEdit6.TabIndex = 26; + // + // memoEdit5 + // + this.memoEdit5.Location = new System.Drawing.Point(50, 263); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Size = new System.Drawing.Size(817, 96); + this.memoEdit5.TabIndex = 27; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(708, 131); + this.numericUpDown2.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(75, 22); + this.numericUpDown2.TabIndex = 22; + this.numericUpDown2.Value = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.numericUpDown2.Visible = false; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(264, 132); + this.numericUpDown1.Maximum = new decimal(new int[] { + 999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(91, 22); + this.numericUpDown1.TabIndex = 22; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // numericUpDown4 + // + this.numericUpDown4.Location = new System.Drawing.Point(370, 79); + this.numericUpDown4.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown4.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown4.Name = "numericUpDown4"; + this.numericUpDown4.Size = new System.Drawing.Size(93, 22); + this.numericUpDown4.TabIndex = 22; + this.numericUpDown4.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // comboBox3 + // + this.comboBox3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox3.FormattingEnabled = true; + this.comboBox3.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群", + "订单冻结"}); + this.comboBox3.Location = new System.Drawing.Point(507, 131); + this.comboBox3.Name = "comboBox3"; + this.comboBox3.Size = new System.Drawing.Size(121, 22); + this.comboBox3.TabIndex = 25; + this.comboBox3.SelectedIndexChanged += new System.EventHandler(this.comboBox3_SelectedIndexChanged); + // + // comboBox2 + // + this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox2.Location = new System.Drawing.Point(507, 79); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(121, 22); + this.comboBox2.TabIndex = 25; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox1.Location = new System.Drawing.Point(507, 26); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(121, 22); + this.comboBox1.TabIndex = 25; + // + // labelControl30 + // + this.labelControl30.Location = new System.Drawing.Point(471, 83); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(16, 14); + this.labelControl30.TabIndex = 16; + this.labelControl30.Text = "次."; + // + // labelControl32 + // + this.labelControl32.Location = new System.Drawing.Point(50, 369); + this.labelControl32.Name = "labelControl32"; + this.labelControl32.Size = new System.Drawing.Size(72, 14); + this.labelControl32.TabIndex = 17; + this.labelControl32.Text = "屏蔽店铺ID:"; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(370, 26); + this.numericUpDown3.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown3.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(93, 22); + this.numericUpDown3.TabIndex = 23; + this.numericUpDown3.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(128, 369); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(132, 14); + this.labelControl2.TabIndex = 18; + this.labelControl2.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl1 + // + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(128, 243); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(132, 14); + this.labelControl1.TabIndex = 18; + this.labelControl1.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl31 + // + this.labelControl31.Location = new System.Drawing.Point(50, 243); + this.labelControl31.Name = "labelControl31"; + this.labelControl31.Size = new System.Drawing.Size(72, 14); + this.labelControl31.TabIndex = 18; + this.labelControl31.Text = "屏蔽商品ID:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(653, 135); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(48, 14); + this.labelControl8.TabIndex = 19; + this.labelControl8.Text = "订单冻结"; + this.labelControl8.Visible = false; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(789, 135); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(28, 14); + this.labelControl7.TabIndex = 19; + this.labelControl7.Text = "小时."; + this.labelControl7.Visible = false; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(373, 136); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(64, 14); + this.labelControl4.TabIndex = 19; + this.labelControl4.Text = "小时内收货."; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(170, 136); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 19; + this.labelControl3.Text = "用户购买的商品"; + // + // labelControl29 + // + this.labelControl29.Location = new System.Drawing.Point(170, 83); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(190, 14); + this.labelControl29.TabIndex = 19; + this.labelControl29.Text = "用户在同家店铺多次购物(不同商品)"; + // + // labelControl28 + // + this.labelControl28.Location = new System.Drawing.Point(471, 30); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(16, 14); + this.labelControl28.TabIndex = 20; + this.labelControl28.Text = "次."; + // + // labelControl27 + // + this.labelControl27.Location = new System.Drawing.Point(170, 30); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(190, 14); + this.labelControl27.TabIndex = 21; + this.labelControl27.Text = "用户在同家店铺多次购买(同一商品)"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(991, 577); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl19; + private System.Windows.Forms.ComboBox comboBox4; + private DevExpress.XtraEditors.LabelControl labelControl20; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private System.Windows.Forms.CheckBox checkBox3; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.CheckBox checkBox1; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private UI.Framework.Controls.ButtonCheck buttonCheck; + private DevExpress.XtraEditors.MemoEdit memoEdit6; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.NumericUpDown numericUpDown4; + private System.Windows.Forms.ComboBox comboBox3; + private System.Windows.Forms.ComboBox comboBox2; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.LabelControl labelControl30; + private DevExpress.XtraEditors.LabelControl labelControl32; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl31; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl29; + private DevExpress.XtraEditors.LabelControl labelControl28; + private DevExpress.XtraEditors.LabelControl labelControl27; + } +} \ No newline at end of file diff --git a/应用/KSRebate/MainForm.cs b/应用/KSRebate/MainForm.cs new file mode 100644 index 0000000..f9ecb8b --- /dev/null +++ b/应用/KSRebate/MainForm.cs @@ -0,0 +1,306 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using KSRebate.Properties; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace KSRebate +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + var apis = ApiClient.GetSession().FindNoticeapiRobots().ToArray(); + var rst = new List(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + comboBox4.DataSource = rst; + + this.settingControl1.Bind(Class1.Config, 110); + + this.buttonCheck.Checked = Class1.Config.AShop_SameCommodity_Switch; + this.numericUpDown3.Value = Class1.Config.AShop_SameCommodity_Number; + this.comboBox1.SelectedIndex = Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单 ? 0 : 1; + + this.buttonCheck1.Checked = Class1.Config.AShop_DifferentCommodity_Switch; + this.numericUpDown4.Value = Class1.Config.AShop_DifferentCommodity_Number; + this.comboBox2.SelectedIndex = Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单 ? 0 : 1; + + this.buttonCheck2.Checked = Class1.Config.ReceivingTimeCheck_Switch; + this.numericUpDown1.Value = Class1.Config.ReceivingTimeCheck_Hour; + this.comboBox3.SelectedIndex = Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单 ? 0 : Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群 ? 1 : 2; + this.numericUpDown2.Value = Class1.Config.ReceivingTimeCheck_FreezeTime; + + this.comboBox4.SelectedIndex = rst.IndexOf(Class1.Config.notice_robotname) == -1 ? 0 : rst.IndexOf(Class1.Config.notice_robotname); + + this.memoEdit5.Text = string.Join(",", Class1.Config.ItemIDRestrictList); + this.memoEdit6.Text = string.Join(",", Class1.Config.SellerIDRestrictlist); + + #region 加载所有的账号 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.快手联盟}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.快手联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label1.Visible = gridView1.RowCount == 0; + + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 行单元格单击事件 + /// + /// + /// + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.快手联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzone == null) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzone.extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + #region 有出现两个重复无法修复的情况,删除一个 + var repetAdzone = adzones.Where(f => f.extend == pidName).ToList(); + if (repetAdzone.Count > 1) + { + for (int i = 1; i <= repetAdzone.Count - 1; i++) + { + session.Deleteable(repetAdzone[i]).ExecuteCommand(); + } + adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + } + #endregion + + adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindKsInfoTempGroups(true); + session.FindAdzoneInfos(true); + session.FindKuaishouAutoBindPid(true);//刷新推广位 + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzones.Count == 0) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item, false); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzones[0].extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate, adzones[0].onoff); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + if (adzones != null)//数据库中存在 + session.ExcuteSQL("update fl_adzone_info set onoff = @onoff where robot_id = @robot_id and alliance_id = @alliance_id and custom_type = @custom_type", new { onoff = !adzones[0].onoff, robot_id = id, alliance_id = (int)CpsType.快手联盟, custom_type = Resources.SoftwareType }); + session.FindKsInfoTempGroups(true); + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + session.FindPinduoduoAutoBindPid(true);//刷新推广位 + } + } + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 创建fl_adzone_info对象 + /// + /// + /// + /// + /// + /// + /// + private fl_adzone_info CreateAdzoneInfo(string adzone_name, string adzone_pid, string adzone_pid_cps_name, string rid, string item, bool onoff = false) + { + return new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = adzone_name, //推广位名称 + adzone_pid = adzone_pid, //推广位pid + adzone_pid_cps_name = adzone_pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.快手联盟, //联盟id + robot_id = int.Parse(rid), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = onoff, //不禁用 + extend = item + }; + } + + /// + /// 修改显示内容的事件 + /// + /// + /// + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.ReceivingTimeCheck_Switch = buttonCheck2.Checked; + Class1.Config.ReceivingTimeCheck_Hour = (int)numericUpDown1.Value; + Class1.Config.ReceivingTimeCheck_OperateType = comboBox3.SelectedIndex == 0 ? OperateType.拉入黑名单 : comboBox3.SelectedIndex == 1 ? OperateType.通知钉钉群 : OperateType.订单冻结; + Class1.Config.ReceivingTimeCheck_FreezeTime = (int)numericUpDown2.Value; + Class1.Config.ReceivingTimeCheck_UserTop = checkBox3.Checked; + + Class1.Config.notice_robotname = comboBox4.SelectedValue.ToString(); + + Class1.Config.ItemIDRestrictList = memoEdit5.Text.Trim().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void comboBox3_SelectedIndexChanged(object sender, EventArgs e) + { + labelControl7.Visible = labelControl8.Visible = numericUpDown2.Visible = comboBox3.SelectedIndex == 2; + checkBox3.Visible = comboBox3.SelectedIndex == 0; + } + } +} diff --git a/应用/KSRebate/MainForm.resx b/应用/KSRebate/MainForm.resx new file mode 100644 index 0000000..0bca80f --- /dev/null +++ b/应用/KSRebate/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 44 + + \ No newline at end of file diff --git a/应用/KSRebate/MessageOperation.cs b/应用/KSRebate/MessageOperation.cs new file mode 100644 index 0000000..d5ef936 --- /dev/null +++ b/应用/KSRebate/MessageOperation.cs @@ -0,0 +1,408 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.EntityTmp.KuaiShou; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using KSRebate.Properties; +using Newtonsoft.Json; + +namespace KSRebate +{ + public class MessageOperation + { + ReciveIMEvent e = null; + Class1 plugin = null; + object sender = null; + + public MessageOperation(object sender, ReciveIMEvent e, Class1 plugin) + { + this.e = e; + this.plugin = plugin; + this.sender = sender; + } + + #region 订单绑定 + public bool BindOrderId() + { + + if (!Regex.IsMatch(e.Message.Trim(), @"^\d{16}$"))//2214500070274639 + return false; + + var db = ApiClient.GetSession(); + var member = e.GetMemberinfo(); + + var orderid = e.Message.Trim(); + + //通过宝贝的id 和 订单号 进行查询 查看是否存在 + var orders = db.Find("select * from fl_order_kuaishou where oid = @oid", new { oid = orderid }); + if (orders != null && orders.Count != 0) + { + var notices = new List(); + var downkuaishouTimer = new DownKuaiShouTimer(); + foreach (var order in orders) + { + if (order.db_userid != 0 && order.db_userid != member.id) + { + e.SendMessage(Class1.Config.OccupyOrderErrorTip.Replace("[订单号]", orderid)); + return true; + } + + if (order.db_userid != 0) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + member = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Class1.Config.OrderRepetBindTip, order, member, point)); + else + e.SendMessage(Class1._GetOrderStateMess(order.db_status, order, member, point)); + } + else + { + if (order.payTime < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderid},已经过了有效绑定时间!"); + return true; + } + + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + //用户绑定订单 + order.db_robotname = e.RobotName; + order.db_robottype = e.ChatType; + order.msg_groupid = e.Groupid; + order.db_userid = member.id; + db.SaveOrUpdate(order); + + member.bind_order++; + member = db.UpdateMemberGroup(member); + + #region 首次付款时间 + var record = db.FindStatisticsRecord(member.id); + if (record == null) + { + record = new fl_statistics_record() { uid = member.id, ex2 = 0, ex4 = HttpExtend.GetTimeStamp(DateTime.Now) }; + db.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = HttpExtend.GetTimeStamp(DateTime.Now); + db.Saveable(record).ExecuteCommand(); + } + } + #endregion + + downkuaishouTimer.UpdateOrder(order, db, notices, isFrontData: true); + } + } + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.IsRewards) + tasks.Add(item); + //else + //SDK_OrderNoticeEvent(this, item); + } + } + #endregion + + e.Cancel = true; + } + else + { + CpsClient.UpdateOrder(CpsType.快手联盟, DateTime.Now.AddMinutes(-30), DateTime.Now, orderid); + + e.SendMessage(Class1.Config.NotFoundOrderErrorTip.Replace("[订单号]", orderid)); + e.Cancel = true; + return true; + } + return false; + } + #endregion + + private Dictionary debutTimes = new Dictionary(); + + public bool AnalyseFanLi() + { + var title = string.Empty; + Compute compute = null; + var msgid = Guid.NewGuid().ToString(); + try + { + var db = ApiClient.GetSession(); + + var ksinfoTemps = db.FindKsInfoTempGroups(); + var ksInfoTemp = ksinfoTemps.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (ksInfoTemp == null) return false; + var memberTmp = e.GetMemberinfo(); + + var message = e.Message.Trim(); + + //推广位 + var pid = string.Empty; + + fl_cps_member ks_cps = null; + + #region 判断使用的推广位 (群推广/私人推广位/默认推广位) + var isDefaultPid = true; + + //判断消息是否为群消息并且判断群是否设置了群pid + if (!string.IsNullOrWhiteSpace(e.Groupid))//群pid + { + var groupAdzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + pid = groupAdzone.adzone_pid; + ks_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.快手联盟 && f.username == groupAdzone.adzone_pid_cps_name); + isDefaultPid = false; + } + } + + if (isDefaultPid)//私人pid + { + var memberAdzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == memberTmp.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + pid = memberAdzone.adzone_pid; + ks_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.快手联盟 && f.username == memberAdzone.adzone_pid_cps_name); + isDefaultPid = false; + } + } + + if (isDefaultPid)//默认推广位 + { + ks_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.快手联盟 && f.username == ((memberTmp.buy_point >= Class1.Config.Point && memberTmp.finish_order >= Class1.Config.OrderNum) ? ksInfoTemp.pid_chief_cps_name : ksInfoTemp.pid_deputy_cps_name));//通过判断用户的购物积分,来判断用户使用哪个推广位 + pid = ((memberTmp.buy_point >= Class1.Config.Point && memberTmp.finish_order >= Class1.Config.OrderNum) ? ksInfoTemp.pid_chief : ksInfoTemp.pid_deputy); + } + + if (ks_cps == null) throw new Exception("快手推广位设置异常,请检测后重试!"); + #endregion + + if (string.IsNullOrWhiteSpace(pid)) throw new Exception("推广位数据异常,请重新设置推广位"); + + var api = CpsClient.CreateKuaiShouRequest(ks_cps); + if (api == null) throw new Exception("@创建快手联盟API请求失败"); + + //商品id + var item_id = KSHelper.GetItemId(message, out title); + + #region 标题搜索和商品id搜索 + + if (string.IsNullOrEmpty(item_id)) + return false; + + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + e.SendMessage(Class1.Config.SearchingTip); + + //商品的详细信息 + var itemInfo = api.GetItemInfo(item_id); + if (itemInfo == null || itemInfo.promotionRate == 0) + throw new Exception("商品无佣金"); + //店铺ID + var sellerId = itemInfo.mallId.ToString(); + if (Class1.Config.SellerIDRestrictlist.Contains(sellerId)) + { + e.SendMessage(Class1.Config.SellerIDRestrictTip.Replace("[店铺ID]", sellerId)); + return true; + } + + //商品标题//< >&"© <,>,&,",©; + itemInfo.goodsTitle = itemInfo.goodsTitle.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©");//这里有个看不见的字符,要将其替换掉 + + var price = Math.Round((itemInfo.goodsPrice / 100m), 2); + if (itemInfo.zkGoodsPrice != 0) + price = Math.Round((itemInfo.zkGoodsPrice / 100m), 2); + + //最高佣金率 + var promotionAmount = Math.Round((itemInfo.promotionAmount / 100d), 2); + + //用券后 给用户的佣金 + var commFee = db.FindItemPoint(memberTmp, promotionAmount * 0.9, 1, CpsType.快手联盟, out compute); + + var guid = Guid.NewGuid().ToString("N"); + + //返利信息入库 + var itempointId = db.Insertable(new fl_itempoint1_hist() { guidkey = guid, cpstype = e.RobotInfo.type, robotname = e.RobotInfo.name, uid = memberTmp.id, gid = e.Groupid, text = JsonConvert.SerializeObject(compute) }).ExecuteReturnBigIdentity(); + + var turnInfo = api.TurnUrl(item_id, pid, guid); + + if (turnInfo == null) + throw new Exception("商品转链异常"); + + var itemUrl = turnInfo.linkUrl; + var kl = turnInfo.shareToken; + + #region 正常订单 + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Class1.Config.QQSearchSuccessWithoutCouponTip))) + mess = Class1.Config.SearchSuccessWithoutCouponTip; + else + mess = Class1.Config.QQSearchSuccessWithoutCouponTip; + + e.SendMessage(mess + .Replace("[商品标题]", itemInfo.goodsTitle) + .Replace("[商品原价]", string.Format("{0:F}", price)) + .Replace("[商品主图]", $"[图片={itemInfo.goodsImageUrl}]") + .Replace("[图片地址]", itemInfo.goodsImageUrl) + .Replace("[月销量]", itemInfo.salesTip.ToString()) + .Replace("[店铺名称]", itemInfo.mallName) + .Replace("[返利积分]", string.Format("{0:F}", commFee.UserPoint)) + .Replace("[购买地址]", itemUrl) + .Replace("[购买口令]", kl) + .Replace("[共节省]", string.Format("{0:F}", commFee.UserPoint)) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(itemInfo.goodsTitle, price.ToString(), "0", price.ToString(), itemInfo.goodsImageUrl, itemUrl, ApiClient.QrImageType.模板B, CpsType.快手联盟) + "]" : string.Empty) + ); + #endregion + + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + db.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.快手联盟, + itemid = item_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = memberTmp.id, + title = itemInfo.goodsTitle, + adzoneid = pid, + mallid = sellerId, + compute_configdic = compute == null ? string.Empty : JsonConvert.SerializeObject(compute) + }).ExecuteCommand(); + db.UpdateRecord(memberTmp.id); + + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.快手联盟; + shared["msg_username"] = memberTmp.username; + shared["price"] = string.Format("{0:F}", price); + shared["title"] = itemInfo.goodsTitle; + shared["coupon_price"] = "0"; + shared["user_point"] = string.Format("{0:F}", commFee.UserPoint); + shared["economize"] = string.Format("{0:F}", commFee.UserPoint); + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + + #endregion + return true; + #endregion + + } + catch (Exception ex) + { + if (ex.Message.StartsWith("商品")) + { + + var searchUrl = string.Empty; + if (!string.IsNullOrWhiteSpace(title)) + { + try + { + var memberTmp = e.GetMemberinfo(); + + //推广位 + var pid = string.Empty; + + #region 判断使用的推广位 (群推广/私人推广位/默认推广位) + var isDefaultPid = true; + + #region 判断消息是否为群消息并且判断群是否设置了群pid + if (!string.IsNullOrWhiteSpace(e.Groupid)) + { + var groupAdzone = ApiClient.GetSession().FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + pid = groupAdzone.adzone_pid; + isDefaultPid = false; + } + } + #endregion + + #region 判断消息是否为私人消息并且判断私人是否设置了私人pid + if (isDefaultPid) + { + var memberAdzone = ApiClient.GetSession().FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == memberTmp.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + pid = memberAdzone.adzone_pid; + isDefaultPid = false; + } + } + #endregion + if (isDefaultPid)//默认推广位 + { + var tgw = Tools.GetTuiguangwei(e.RobotInfo.name, memberTmp); + if (tgw == null || string.IsNullOrWhiteSpace(tgw.Pid)) throw new Exception("@快手推广位异常.请检测后重试!!"); + pid = tgw.Pid; + } + #endregion + var pids = pid.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + if (pids == null || pids.Length == 0) throw new Exception("推广位数据异常,请重新设置推广位"); + + var tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.快手联盟 && f.username == pids[1]); + if (tb_cps == null) throw new Exception("@快手推广位异常,请检测后重试!"); + + //关键词/标题 + var keyword = string.Empty; + //是否是标题 + var IsTitle = false; + var api = CpsClient.CreateAlimamaRequest(tb_cps); + if (api == null) throw new Exception("@创建快手API请求失败"); + + searchUrl = api.ComposeTbCms(pid, keyword);//内置的搜索机制 + } + catch (Exception exception) + { } + } + + e.SendMessage(Class1.Config.SearchNoCommissionTip.Replace("[购买地址]", searchUrl)); //提示没有返利提示 + + var session = ApiClient.GetSession(); + session.UpdateRecord(e.GetMemberinfo().id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.快手联盟; + shared["msg_username"] = e.GetMemberinfo().username; + shared["price"] = "未知"; + shared["title"] = "未知"; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + return true; + } + + if (ex.Message.StartsWith("@")) + plugin.OnLog($"E :({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message.Replace("@", "")}"); + else + plugin.OnLog($"E:({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message} - {ex.StackTrace}"); + plugin.OnLog(ApiClient.Setting.SystemConfig.msg_error); + } + return false; + } + + } +} diff --git a/应用/KSRebate/Properties/AssemblyInfo.cs b/应用/KSRebate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b821c3d --- /dev/null +++ b/应用/KSRebate/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("KSRebate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("KSRebate")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("bd719746-8782-4da2-9469-75a03e02fab9")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/KSRebate/Properties/Resources.Designer.cs b/应用/KSRebate/Properties/Resources.Designer.cs new file mode 100644 index 0000000..06f8b3f --- /dev/null +++ b/应用/KSRebate/Properties/Resources.Designer.cs @@ -0,0 +1,118 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace KSRebate.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KSRebate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 快手返利 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 快手返利 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 快手返利插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 快手返利 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 淘宝强返 的本地化字符串。 + /// + internal static string TbActivitySoftwareType { + get { + return ResourceManager.GetString("TbActivitySoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 快手 { + get { + object obj = ResourceManager.GetObject("快手", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/KSRebate/Properties/Resources.resx b/应用/KSRebate/Properties/Resources.resx new file mode 100644 index 0000000..ad02deb --- /dev/null +++ b/应用/KSRebate/Properties/Resources.resx @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 快手返利 + 设置主窗体标题 + + + 快手返利 + 插件名 + + + 快手返利插件 + 插件介绍 + + + 快手返利 + fl_adzone_info自定义类型(custom_type) + + + 淘宝强返 + fl_adzone_info自定义类型(custom_type)淘宝强返 + + + + ..\Resources\快手.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/KSRebate/Properties/licenses.licx b/应用/KSRebate/Properties/licenses.licx new file mode 100644 index 0000000..81c8e65 --- /dev/null +++ b/应用/KSRebate/Properties/licenses.licx @@ -0,0 +1,3 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/KSRebate/Resources/快手.png b/应用/KSRebate/Resources/快手.png new file mode 100644 index 0000000..829ca6b Binary files /dev/null and b/应用/KSRebate/Resources/快手.png differ diff --git a/应用/KSRebate/SessionExt.cs b/应用/KSRebate/SessionExt.cs new file mode 100644 index 0000000..ca77f1f --- /dev/null +++ b/应用/KSRebate/SessionExt.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using KSRebate.Entitys; +using KSRebate.Properties; +using SqlSugar; + +namespace KSRebate +{ + public static class SessionExt + { + const string ksinfo_temp_list_ksrebate = "ksinfo_temp_list_ksrebate"; + + /// + /// 获取fl_adzone_info表的数据集合缓存 + /// + /// + /// 刷新 + /// + public static List FindKsInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + + var ksinfo_temp_groups = ApiClient.Cache.Get>(ksinfo_temp_list_ksrebate);//根据KEY、获得缓存 + if (refresh || ksinfo_temp_groups == null) + { + ksinfo_temp_groups = session.Find($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.快手联盟}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.快手联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id"); + ApiClient.Cache.Set(ksinfo_temp_list_ksrebate, ksinfo_temp_groups, 60); + } + return ksinfo_temp_groups; + } + + public static fl_member_info FindMemberinfo(this SqlSugarClient session, long userid) + { + return session.Find("select * from fl_member_info where id = @id", new { id = userid }).FirstOrDefault(); + } + + public static void Clear() + { + ApiClient.Cache.Remove(ksinfo_temp_list_ksrebate); + } + } +} diff --git a/应用/KSRebate/Tools.cs b/应用/KSRebate/Tools.cs new file mode 100644 index 0000000..dcc0cff --- /dev/null +++ b/应用/KSRebate/Tools.cs @@ -0,0 +1,278 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using CsharpHttpHelper; +using KSRebate.Properties; +using SqlSugar; + +namespace KSRebate +{ + public static class KsSessionExt + { + const string ksinfo_temp_list_ksrebate = "ksinfo_temp_list_ksrebates"; + + /// + /// 获取fl_fadzone_info表的数据集合缓存 + /// + /// + /// 刷新 + /// + public static List FindKsInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + //var stopWatch = new Stopwatch(); + //stopWatch.Start(); + var ksinfo_temp_groups = ApiClient.Cache.Get>(ksinfo_temp_list_ksrebate);//根据KEY、获得缓存 + //stopWatch.Stop(); + //EventClient.OnEvent("", "AAAA = " + stopWatch.Elapsed.TotalSeconds.ToString() + " ----------- " + (ksinfo_temp_groups == null ? "null" : ksinfo_temp_groups.Count.ToString())); + try + { + if (refresh || ksinfo_temp_groups == null) + { + ksinfo_temp_groups = new List(); + var robots = session.FindRobots(true); + foreach (var item in robots) + { + ksinfo_temp_groups.Add(new ksinfo_temp() + { + ID = item.id, + chattype = item.type, + nick = item.nick, + name = item.name + }); + } + + foreach (var item in ksinfo_temp_groups) + { + //var adzones = session.Queryable().Where(f => f.robot_id == item.ID && f.custom_type == Resources.SoftwareType && f.alliance_id == (int)CpsType.快手联盟).ToList(); + var adzones = session.Find("select * from fl_adzone_info where robot_id = @robot_id and custom_type = @custom_type and alliance_id = @alliance_id", new { robot_id = item.ID, custom_type = Resources.SoftwareType, alliance_id = (int)CpsType.快手联盟 }); + foreach (var adzone in adzones) + { + if (adzone.extend == "chief")//主 + { + item.onoff = adzone.onoff; + if (adzone.adzone_group != 0)//组 + { + var _adzone = session.FindAdzoneGroups(CpsType.快手联盟, true).Where(f => string.IsNullOrWhiteSpace(f.remark)).FirstOrDefault(f => f.id == adzone.adzone_group); + if (_adzone != null) + { + item.is_chief_group = true; + item.pid_chief = _adzone.adzones; + item.pid_chief_name = _adzone.name; + } + } + else//单 + { + item.is_chief_group = false; + item.pid_chief_cps_name = adzone.adzone_pid_cps_name; + item.pid_chief = adzone.adzone_pid; + item.pid_chief_name = adzone.adzone_name; + } + } + else//副 + { + item.onoff = adzone.onoff; + if (adzone.adzone_group != 0)//组 + { + var _adzone = session.FindAdzoneGroups(CpsType.快手联盟, true).Where(f => string.IsNullOrWhiteSpace(f.remark)).FirstOrDefault(f => f.id == adzone.adzone_group); + if (_adzone != null) + { + item.is_deputy_group = true; + item.pid_deputy = _adzone.adzones; + item.pid_deputy_name = _adzone.name; + } + } + else//单 + { + item.is_deputy_group = false; + item.pid_deputy_cps_name = adzone.adzone_pid_cps_name; + item.pid_deputy = adzone.adzone_pid; + item.pid_deputy_name = adzone.adzone_name; + } + } + } + + } + ApiClient.Cache.Set(ksinfo_temp_list_ksrebate, ksinfo_temp_groups, 60); + } + } + catch (Exception ex) + { + EventClient.OnEvent(null, $"【快手返利】 => 获取推广位异常:{ex.Message} - {ex.StackTrace}"); + } + return ksinfo_temp_groups; + } + + public static void Clear() + { + ApiClient.Cache.Remove(ksinfo_temp_list_ksrebate); + } + } + public class Tools + { + /// + /// 获取推广位 + /// + /// + /// + /// + public static Tuiguangwei GetTuiguangwei(string robotName, fl_member_info member) + { + try + { + var ksinfoTemps = ApiClient.GetSession().FindKsInfoTempGroups(); + var ksInfoTemp = ksinfoTemps.FirstOrDefault(f => f.name == robotName && f.onoff == false); + #region + var choose = (member.buy_point >= Class1.Config.Point && member.finish_order >= Class1.Config.OrderNum);//判断是主还是副 + if (choose) + { + if (ksInfoTemp.is_chief_group) + { + string key_chief = "fl_ksrebate_key_chief_" + robotName; + Tuiguangwei tgw = ApiClient.Cache.Get(key_chief); + return tgw; + } + else + return new Tuiguangwei() { Pid = ksInfoTemp.pid_chief, Name = ksInfoTemp.pid_chief_name, Member = new fl_cps_member() { username = ksInfoTemp.pid_chief_cps_name } }; + } + else + { + if (ksInfoTemp.is_deputy_group) + { + string key_deputy = "fl_ksrebate_key_deputy_" + robotName; + var tgw = ApiClient.Cache.Get(key_deputy); + + return tgw; + } + else + return new Tuiguangwei() { Pid = ksInfoTemp.pid_deputy, Name = ksInfoTemp.pid_deputy_name, Member = new fl_cps_member() { username = ksInfoTemp.pid_deputy_cps_name } }; + } + #endregion + } + catch (System.Exception ex) + { + EventClient.OnEvent(null, $"选择使用的推广位异常:{ex.Message} - {ex.StackTrace}"); + } + return null; + } + } + + /// + /// 临时的表 (用于数据显示) + /// + public class ksinfo_temp + { + /// + /// id + /// + public long ID { get; set; } + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string name { get; set; } + + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 主推广位是否是组推广位 + /// + public bool is_chief_group { get; set; } + + /// + /// 主推广位cps名称 + /// + private string _pid_chief_cps_name { get; set; } + public string pid_chief_cps_name + { + get { return _pid_chief_cps_name; } + set { _pid_chief_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_chief; + /// + /// 主推广位id + /// + public string pid_chief + { + get { return _pid_chief; } + set { _pid_chief = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 主推广位昵称 + /// + private string _pid_chief_name; + + public string pid_chief_name + { + get { return _pid_chief_name; } + set { _pid_chief_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 主推广位是否是组推广位 + /// + public bool is_deputy_group { get; set; } + /// + /// 副推广位cps名称 + /// + private string _pid_deputy_cps_name { get; set; } + public string pid_deputy_cps_name + { + get { return _pid_deputy_cps_name; } + set { _pid_deputy_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位id + /// + private string _pid_deputy; + + public string pid_deputy + { + get { return _pid_deputy; } + set { _pid_deputy = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位名称 + /// + private string _pid_deputy_name; + + public string pid_deputy_name + { + get { return _pid_deputy_name; } + set { _pid_deputy_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + //public string adzone_activity_name { get; set; } + + ///// + ///// 推广位 + ///// + //public string adzone_activity_pid { get; set; } + + + public string adzone_activity_pid_cps_name { get; set; } + + + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } + +} diff --git a/应用/Main/Class1.cs b/应用/Main/Class1.cs new file mode 100644 index 0000000..8908c7c --- /dev/null +++ b/应用/Main/Class1.cs @@ -0,0 +1,293 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Main.Entitys; +using Main.Properties; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static Api.Framework.Tools.TBHelper; + +namespace Main +{ + public class Class1 : Plugin + { + + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.通用; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + // public static VariateReplace variateReplace = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("rid"); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.WXNewFriendEvent += SDK_WXNewFriendEvent; + SDK.WXApplyFriendEvent += SDK_WXApplyFriendEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_WXApplyFriendEvent(object sender, Chat.Framework.WXSdk.Events.WXApplyFriend e) + { + var strb = new StringBuilder(); + strb.Append($"新用户:{e.NewFriendNick}({e.NewFriendWxid})申请加好友"); + if (!string.IsNullOrWhiteSpace(e.OldFriendWxid)) + strb.Append($"邀请者:{e.OldFriendNick}({e.OldFriendWxid})."); + if (Config.AcceptFriend) + { + string result = e.Client.AgreeAddMe(e.Token); + strb.Append($"自动接受申请"); + } + this.OnLog(strb.ToString()); + } + + private void SDK_WXNewFriendEvent(object sender, Chat.Framework.WXSdk.Events.WXNewFriend e) + { + try + { + if (!string.IsNullOrWhiteSpace(Config.NewFriendMess)) + e.Client.SendMessage(e.Friend.UserName, Config.NewFriendMess.Replace("[昵称]", e.Friend.NickName).Replace("[账号]", e.Friend.UserName)); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + //过滤表情xml和卡片xml + if ((e.Message.ToLower().Contains(@"(); + #region 正常口令 + var regs1 = Regex.Matches(_mess, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?"); + foreach (Match item in regs1) + { + if (item.Success) + { + var tkl = item.Groups[1].Value; + if (Regex.IsMatch(tkl, @"(\d{11})")) + continue; + flag = true; + break; + } + } + #endregion + + if (!flag) + { + var tklreg = TbAnalysis.GetTklReg(); + flag = Regex.IsMatch(e.Message, tklreg, RegexOptions.IgnoreCase); + } + if (!flag) + { + flag = Regex.IsMatch(e.Message, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|detail.yao.95095.com|laiwang.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com|m.tb.cn)", RegexOptions.IgnoreCase); + } + if (!flag) + { + flag = Regex.IsMatch(e.Message.Trim(), @"^找.+", RegexOptions.IgnoreCase); + } + + if (flag) + { + var db = ApiClient.GetSession(); + var data = db.FindSingle("rid = @rid", new { rid = e.RobotInfo.id }); + if (data == null || string.IsNullOrWhiteSpace(data.invitecode)) + return; + var mess = Send(e.Message, data.invitecode, e.GetMemberinfo().username); + if (!string.IsNullOrWhiteSpace(mess)) + { + var jObj = JObject.Parse(mess); + if (jObj["code"] == null || (int)jObj["code"] != 200) throw new Exception(mess); + var data1 = jObj["data"]; + + var cardTitle = data1["cardTitle"].ToString();//卡片标题 + var title = data1["title"].ToString();//标题 + var description = data1["description"].ToString();//描述 + var picUrl = data1["picUrl"].ToString();//图片 + var url = data1["url"].ToString();//卡片链接 + var shortUrl = data1["shortUrl"].ToString();//文案短链接 + var hb = (decimal)data1["lijin"];//红包 + var yhq = (decimal)data1["coupon"];//优惠券 + var xdj = (decimal)data1["priceAfterCoupon"];//下单价 + + var jy = hb + yhq;//节约 + + //{"code":200,"msg":"success","data":{"title":"预估购买奖励:0.53元,优惠券:1元,下单价:6.9元","description":"包邮 漫花 抽纸 绒触感5层80抽/4包/20包/30包家用卫生纸纸巾","picUrl":"https://img.alicdn.com/bao/uploaded/i4/6000000002192/O1CN012ZcrnM1S3yuYZVHF5_!!6000000002192-0-picassoopen.jpg","url":"https://52tlj.com:8095/m/#/pages/goods/detail?id=652169220578\u0026spm=uehOAiI7g.0.-1\u0026wxid=wxid_hlgorn846ihp22"}} + + var m = string.Empty; + switch (Config.SendType) + { + case SendTemplateType.卡片: + m = Config.CardText.Replace("[标题]", cardTitle).Replace("[下单地址]", url); + break; + case SendTemplateType.图文: + m = Config.ImageText; + break; + case SendTemplateType.自定义: + m = Config.CustomContent; + break; + default: + break; + } + e.SendMessage(m.Replace("[商品图片]", picUrl) + .Replace("[标题]", title) + .Replace("[下单价]", xdj.ToString("0.00")) + .Replace("[优惠券]", yhq.ToString("0.00")) + .Replace("[红包金额]", hb.ToString("0.00")) + .Replace("[文案描述]", description) + .Replace("[下单地址]", shortUrl) + .Replace("[合计节约]", jy.ToString("0.00")) + ); + } + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message}"); + } + } + catch (Exception ex) + { + + } + } + + private string Send(string message, string inviteCode, string wxid) + { + StringBuilder strb = new StringBuilder("Web接口请求:"); + try + { + strb.AppendLine($"内容:{message}"); + + message = HttpHelper.URLEncode(message, Encoding.UTF8); + var t = HttpExtend.GetTimeStamp(); + var sig = getSign(message, inviteCode, wxid, t); + + var postData = @"{""appKey"":""" + appKey + @""",""content"":""" + message + @""",""inviteCode"":""" + inviteCode + @""",""sign"":""" + sig + @""",""t"":" + t + @",""wxId"":""" + wxid + @"""}"; + HttpHelper _http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "https://www.52tlj.com/cms/v1/api/fl/transfer", + Method = "POST", + IsToLower = false, + Cookie = string.Empty, + Referer = "", + Postdata = postData, + Timeout = 5000, + ReadWriteTimeout = 5000, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + ContentType = "application/json", + Allowautoredirect = false + }; + //item.SetProxyipCDN(); + var result = _http.GetHtml(item); + var html = result.Html; + strb.AppendLine($"返回数据:{html}"); + return html; + } + catch (Exception ex) + { + strb.AppendLine($"异常:{ex.Message}"); + } + finally + { + LogHelper.GetSingleObj().Debug("", strb.ToString()); + } + return string.Empty; + } + + private string appKey = "qnly"; + private string appSec = "01ae2596ca8e9349"; + + private string getSign(string message, string inviteCode, string wxid, string t) + { + try + { + //http://39.103.223.90:18095/cms/v1/api/fl/transfer + //appKey: test + // appSec:1234 + //appkey+content+inviteCode+t+wxid+appsec + var md5 = CsharpHttpHelper.HttpHelper.ToMD5(appKey + message + inviteCode + t + wxid + appSec).ToLower(); + + return md5; + } + catch (Exception ex) + { } + return string.Empty; + } + + } +} diff --git a/应用/Main/Config.cs b/应用/Main/Config.cs new file mode 100644 index 0000000..6362640 --- /dev/null +++ b/应用/Main/Config.cs @@ -0,0 +1,78 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Main +{ + [Config(Name = "插件-Web淘宝返利-配置")] + public class Config + { + /// + /// 发送类型 + /// + public SendTemplateType SendType { get; set; } = SendTemplateType.卡片; + + /// + /// 自定义内容 + /// + public string CustomContent { get; set; } + + /// + /// 卡片 + /// + public string CardText { get; set; } = @" + [标题] + [文案描述] + view + 5 + 0 + + [下单地址] + + + + + [商品图片] + + + + + + + 0 + + + + + +"; + + /// + /// 图文 + /// + public string ImageText { get; set; } = @"[图片=[商品图片]][分段][延迟=1]----下单消息---- +[标题] +【下单价】[下单价]元 +【优惠券】[优惠券]元 +【红包金额】[红包金额]元 +【合计节约】[合计节约]元 +[文案描述] + +打开网址复制优惠口令: +[下单地址]"; + + /// + /// 接受好友申请 + /// + public bool AcceptFriend { get; set; } = false; + + /// + /// 增加新好友提示语 + /// + public string NewFriendMess { get; set; } = string.Empty; + + } +} diff --git a/应用/Main/Entitys/ShowTmp.cs b/应用/Main/Entitys/ShowTmp.cs new file mode 100644 index 0000000..9bab486 --- /dev/null +++ b/应用/Main/Entitys/ShowTmp.cs @@ -0,0 +1,44 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Main.Entitys +{ + public class ShowTmp + { + /// + /// id + /// + public long ID { get; set; } + + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + + /// + /// 用户账号 + /// + public string name { get; set; } + + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 邀请码 + /// + private string _invitecode; + + public string invitecode + { + get { return _invitecode; } + set { _invitecode = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + } +} diff --git a/应用/Main/Entitys/fl_plugin_tb.cs b/应用/Main/Entitys/fl_plugin_tb.cs new file mode 100644 index 0000000..da28165 --- /dev/null +++ b/应用/Main/Entitys/fl_plugin_tb.cs @@ -0,0 +1,23 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Main.Entitys +{ + public class fl_plugin_tb : base_model + { + /// + /// 机器人id + /// + public int rid { get; set; } + + /// + /// 邀请码 + /// + public string invitecode { get; set; } + + } +} diff --git a/应用/Main/Enums.cs b/应用/Main/Enums.cs new file mode 100644 index 0000000..265fac1 --- /dev/null +++ b/应用/Main/Enums.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Main +{ + /// + /// 发送内容模板 + /// + public enum SendTemplateType + { + 卡片 = 1, + 图文 = 2, + 自定义 = 3, + } +} diff --git a/应用/Main/Main.csproj b/应用/Main/Main.csproj new file mode 100644 index 0000000..c21a779 --- /dev/null +++ b/应用/Main/Main.csproj @@ -0,0 +1,124 @@ + + + + + Debug + AnyCPU + {DEE95656-0130-44D5-BD12-269BF5824957} + Library + Properties + Main + Main + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/Main/MainForm.Designer.cs b/应用/Main/MainForm.Designer.cs new file mode 100644 index 0000000..a1b91ba --- /dev/null +++ b/应用/Main/MainForm.Designer.cs @@ -0,0 +1,524 @@ +namespace Main +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.刷新数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label10 = new System.Windows.Forms.Label(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label9 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.radioButton1 = new System.Windows.Forms.RadioButton(); + this.radioButton2 = new System.Windows.Forms.RadioButton(); + this.radioButton3 = new System.Windows.Forms.RadioButton(); + this.button1 = new System.Windows.Forms.Button(); + this.label11 = new System.Windows.Forms.Label(); + this.label12 = new System.Windows.Forms.Label(); + this.contextMenuStrip1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.tabPage2.SuspendLayout(); + this.panel1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.刷新数据ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 26); + // + // 刷新数据ToolStripMenuItem + // + this.刷新数据ToolStripMenuItem.Name = "刷新数据ToolStripMenuItem"; + this.刷新数据ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.刷新数据ToolStripMenuItem.Text = "刷新数据"; + this.刷新数据ToolStripMenuItem.Click += new System.EventHandler(this.刷新数据ToolStripMenuItem_Click); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(800, 450); + this.tabControl1.TabIndex = 8; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.gridControl1); + this.tabPage1.Location = new System.Drawing.Point(4, 23); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(792, 423); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = " 数 据 列 表 "; + this.tabPage1.UseVisualStyleBackColor = true; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(3, 3); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(786, 417); + this.gridControl1.TabIndex = 8; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn4, + this.gridColumn2, + this.gridColumn3, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsPrint.PrintVertLines = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CellValueChanging += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(this.gridView1_CellValueChanging); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 70; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "平台类型"; + this.gridColumn4.FieldName = "chattype"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 1; + this.gridColumn4.Width = 103; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 150; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 172; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this.gridColumn9.AppearanceCell.BackColor2 = System.Drawing.Color.LightGray; + this.gridColumn9.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn9.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn9.AppearanceCell.Options.UseBackColor = true; + this.gridColumn9.AppearanceCell.Options.UseFont = true; + this.gridColumn9.AppearanceCell.Options.UseForeColor = true; + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "邀请码【直接输入】"; + this.gridColumn9.FieldName = "invitecode"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 4; + this.gridColumn9.Width = 257; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.panel1); + this.tabPage2.Controls.Add(this.button1); + this.tabPage2.Location = new System.Drawing.Point(4, 23); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(792, 423); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = " 基 础 设 置 "; + this.tabPage2.UseVisualStyleBackColor = true; + // + // panel1 + // + this.panel1.AutoScroll = true; + this.panel1.Controls.Add(this.label10); + this.panel1.Controls.Add(this.buttonCheck1); + this.panel1.Controls.Add(this.groupBox2); + this.panel1.Controls.Add(this.label1); + this.panel1.Controls.Add(this.groupBox1); + this.panel1.Controls.Add(this.radioButton1); + this.panel1.Controls.Add(this.radioButton2); + this.panel1.Controls.Add(this.radioButton3); + this.panel1.Location = new System.Drawing.Point(8, 6); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(776, 334); + this.panel1.TabIndex = 6; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(37, 311); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(91, 14); + this.label10.TabIndex = 35; + this.label10.Text = "自动通过好友:"; + // + // buttonCheck1 + // + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = false; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(134, 307); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(62, 22); + this.buttonCheck1.TabIndex = 34; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.textBox2); + this.groupBox2.Location = new System.Drawing.Point(24, 340); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(717, 147); + this.groupBox2.TabIndex = 6; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "新增好友回复语"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(16, 23); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(503, 114); + this.textBox2.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(21, 24); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(91, 14); + this.label1.TabIndex = 3; + this.label1.Text = "回复消息格式:"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.label12); + this.groupBox1.Controls.Add(this.label11); + this.groupBox1.Controls.Add(this.label9); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Location = new System.Drawing.Point(24, 84); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(717, 203); + this.groupBox1.TabIndex = 5; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 自定义模式设置 "; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.ForeColor = System.Drawing.Color.Blue; + this.label9.Location = new System.Drawing.Point(520, 125); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(65, 14); + this.label9.TabIndex = 11; + this.label9.Text = "[下单地址]"; + this.label9.Click += new System.EventHandler(this.label3_Click); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.ForeColor = System.Drawing.Color.Blue; + this.label8.Location = new System.Drawing.Point(590, 101); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(65, 14); + this.label8.TabIndex = 10; + this.label8.Text = "[文案描述]"; + this.label8.Click += new System.EventHandler(this.label3_Click); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.ForeColor = System.Drawing.Color.Blue; + this.label7.Location = new System.Drawing.Point(520, 101); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(65, 14); + this.label7.TabIndex = 9; + this.label7.Text = "[红包金额]"; + this.label7.Click += new System.EventHandler(this.label3_Click); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.ForeColor = System.Drawing.Color.Blue; + this.label6.Location = new System.Drawing.Point(590, 77); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(53, 14); + this.label6.TabIndex = 8; + this.label6.Text = "[优惠券]"; + this.label6.Click += new System.EventHandler(this.label3_Click); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.ForeColor = System.Drawing.Color.Blue; + this.label5.Location = new System.Drawing.Point(520, 77); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(53, 14); + this.label5.TabIndex = 7; + this.label5.Text = "[下单价]"; + this.label5.Click += new System.EventHandler(this.label3_Click); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.ForeColor = System.Drawing.Color.Blue; + this.label4.Location = new System.Drawing.Point(590, 53); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(41, 14); + this.label4.TabIndex = 6; + this.label4.Text = "[标题]"; + this.label4.Click += new System.EventHandler(this.label3_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.ForeColor = System.Drawing.Color.Blue; + this.label3.Location = new System.Drawing.Point(520, 53); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(65, 14); + this.label3.TabIndex = 5; + this.label3.Text = "[商品图片]"; + this.label3.Click += new System.EventHandler(this.label3_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(517, 25); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 4; + this.label2.Text = "支持变量:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(16, 32); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(485, 150); + this.textBox1.TabIndex = 0; + // + // radioButton1 + // + this.radioButton1.AutoSize = true; + this.radioButton1.Checked = true; + this.radioButton1.Location = new System.Drawing.Point(59, 50); + this.radioButton1.Name = "radioButton1"; + this.radioButton1.Size = new System.Drawing.Size(73, 18); + this.radioButton1.TabIndex = 0; + this.radioButton1.TabStop = true; + this.radioButton1.Text = "卡片模式"; + this.radioButton1.UseVisualStyleBackColor = true; + this.radioButton1.CheckedChanged += new System.EventHandler(this.CheckedChanged); + // + // radioButton2 + // + this.radioButton2.AutoSize = true; + this.radioButton2.Location = new System.Drawing.Point(152, 50); + this.radioButton2.Name = "radioButton2"; + this.radioButton2.Size = new System.Drawing.Size(73, 18); + this.radioButton2.TabIndex = 1; + this.radioButton2.Text = "图文模式"; + this.radioButton2.UseVisualStyleBackColor = true; + this.radioButton2.CheckedChanged += new System.EventHandler(this.CheckedChanged); + // + // radioButton3 + // + this.radioButton3.AutoSize = true; + this.radioButton3.Location = new System.Drawing.Point(241, 50); + this.radioButton3.Name = "radioButton3"; + this.radioButton3.Size = new System.Drawing.Size(85, 18); + this.radioButton3.TabIndex = 2; + this.radioButton3.TabStop = true; + this.radioButton3.Text = "自定义模式"; + this.radioButton3.UseVisualStyleBackColor = true; + this.radioButton3.CheckedChanged += new System.EventHandler(this.CheckedChanged); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(323, 357); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(180, 34); + this.button1.TabIndex = 4; + this.button1.Text = " 保 存 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(509, 157); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(107, 14); + this.label11.TabIndex = 12; + this.label11.Text = "发送图片使用变量:"; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.ForeColor = System.Drawing.Color.Blue; + this.label12.Location = new System.Drawing.Point(617, 157); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(89, 14); + this.label12.TabIndex = 13; + this.label12.Text = "[商品图片消息]"; + this.label12.Click += new System.EventHandler(this.label3_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.tabControl1); + this.Name = "MainForm"; + this.Text = "配置界面"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.contextMenuStrip1.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.tabPage2.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 刷新数据ToolStripMenuItem; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.RadioButton radioButton3; + private System.Windows.Forms.RadioButton radioButton2; + private System.Windows.Forms.RadioButton radioButton1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label10; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Label label11; + } +} \ No newline at end of file diff --git a/应用/Main/MainForm.cs b/应用/Main/MainForm.cs new file mode 100644 index 0000000..1d88947 --- /dev/null +++ b/应用/Main/MainForm.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using Chat.Framework; +using DevExpress.XtraGrid.Views.Grid; +using Main.Entitys; +using UI.Framework.Forms; + +namespace Main +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_CustomDrawRowIndicator(object sender, RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void MainForm_Load(object sender, EventArgs e) + { + radioButton3.Checked = true; + switch (Class1.Config.SendType) + { + case SendTemplateType.卡片: + radioButton1.Checked = true; + break; + case SendTemplateType.图文: + radioButton2.Checked = true; + break; + case SendTemplateType.自定义: + radioButton3.Checked = true; + break; + default: + break; + } + + textBox1.Text = Class1.Config.CustomContent; + textBox2.Text = Class1.Config.NewFriendMess; + buttonCheck1.Checked = Class1.Config.AcceptFriend; + + Refresh(); + } + + private new void Refresh() + { + try + { + this.gridControl1.DataSource = null; + + #region 加载所有的账号 + + var db = ApiClient.GetSession(); + //所有机器人列表 + var robotList = db.FindRobots(true); + List list = new List(); + if (robotList != null && robotList.Count != 0) + { + var loginWxs = ChatClient.WXClient.Values.Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线).ToList(); + //在线集合 + var robotTemp_online = robotList.Where(f => loginWxs.FirstOrDefault(z => z.WeixinHao == f.name) != null).OrderBy(f => f.type).ToList(); + //离线集合 + var robotTemp_offline = robotList.Where(f => loginWxs.FirstOrDefault(z => z.WeixinHao == f.name) == null).ToList(); + + robotTemp_online.AddRange(robotTemp_offline); + robotList = robotTemp_online; + + var tbList = db.Find("select * from fl_plugin_tb"); + + foreach (var item in robotList) + { + var info = tbList.FirstOrDefault(f => f.rid == item.id); + list.Add(new ShowTmp() { ID = item.id, name = item.name, nick = item.nick, chattype = item.type, invitecode = info == null ? string.Empty : info.invitecode }); + } + } + + this.gridControl1.DataSource = list; + + #endregion + } + catch (Exception) + { + + } + } + + private void 刷新数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + Refresh(); + } + + private void gridView1_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e) + { + try + { + if (e.Column.Caption == "邀请码【直接输入】") + { + var value = e.Value?.ToString(); + if (!string.IsNullOrWhiteSpace(value) && value.Length == 9) + { + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取ID列的数据 + var session = ApiClient.GetSession(); + var result = session.FindSingle("select * from fl_plugin_tb where rid = @id", new { id = id }); + if (result == null) + result = new fl_plugin_tb() { rid = int.Parse(id) }; + result.invitecode = e.Value?.ToString(); + session.Saveable(result).ExecuteCommand(); + + ShowSuccess("成功"); + Refresh(); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void CheckedChanged(object sender, EventArgs e) + { + try + { + var rb = sender as RadioButton; + groupBox1.Visible = rb.Text == "自定义模式"; + } + catch (Exception ex) + { } + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + Class1.Config.CustomContent = textBox1.Text; + Class1.Config.SendType = radioButton1.Checked ? SendTemplateType.卡片 : (radioButton2.Checked ? SendTemplateType.图文 : SendTemplateType.自定义); + Class1.Config.NewFriendMess = textBox2.Text; + Class1.Config.AcceptFriend = buttonCheck1.Checked; + + Util.Save(Class1.Config); + + MessageBox.Show("保存成功"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private void label3_Click(object sender, EventArgs e) + { + try + { + var label = sender as Label; + if (label.Text == "[商品图片消息]") + textBox1.Text = textBox1.Text + "[图片=[商品图片]]"; + else + textBox1.Text = textBox1.Text + label.Text; + } + catch (Exception ex) + { } + } + } +} diff --git a/应用/Main/MainForm.resx b/应用/Main/MainForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Main/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/应用/Main/Properties/AssemblyInfo.cs b/应用/Main/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6f0921d --- /dev/null +++ b/应用/Main/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Main")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Main")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("dee95656-0130-44d5-bd12-269bf5824957")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/Main/Properties/Resources.Designer.cs b/应用/Main/Properties/Resources.Designer.cs new file mode 100644 index 0000000..3279f56 --- /dev/null +++ b/应用/Main/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Main.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Main.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 淘宝返利 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 淘宝返利 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 淘宝返利插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 通用 { + get { + object obj = ResourceManager.GetObject("通用", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Main/Properties/Resources.resx b/应用/Main/Properties/Resources.resx new file mode 100644 index 0000000..2f53f9b --- /dev/null +++ b/应用/Main/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 淘宝返利 + 插件窗体标题 + + + 淘宝返利 + 插件名称 + + + 淘宝返利插件 + 插件介绍 + + + + ..\Resources\通用.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/Main/Properties/licenses.licx b/应用/Main/Properties/licenses.licx new file mode 100644 index 0000000..3fd7997 --- /dev/null +++ b/应用/Main/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/Main/Resources/通用.png b/应用/Main/Resources/通用.png new file mode 100644 index 0000000..f4076f4 Binary files /dev/null and b/应用/Main/Resources/通用.png differ diff --git a/应用/MessageForwarder/Class1.cs b/应用/MessageForwarder/Class1.cs new file mode 100644 index 0000000..d1d86c1 --- /dev/null +++ b/应用/MessageForwarder/Class1.cs @@ -0,0 +1,149 @@ +using Api.Framework; +using Api.Framework.SDK; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using MessageForwarder.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace MessageForwarder +{ + public class Class1 : Plugin + { + + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.消息转发; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + //public static VariateReplace variateReplace = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + + #endregion + Config = this.ReadConfig(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private static string _MessMD5 = string.Empty; + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + if (string.IsNullOrWhiteSpace(e.Groupid)) return; + if (e.Groupid != Config.ClusterId) return; + if (e.Username != Config.ListeningAccount) return; + var mess_MD5 = Api.Framework.Tools.Util.GetMd5_32byte(e.Message); + if (_MessMD5 != mess_MD5) + { + _MessMD5 = mess_MD5; + var result = CsharpHttpHelper.HttpExtend.JsonToDictionary(Class1.Config.Data); + if (result == null) return; + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + Parallel.ForEach(result.Keys, (item) => + { + try + { + var wx = weixinBases.FirstOrDefault(f => f.WeixinHao == item && f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wx != null) + { + var groupids = result[item].ToString().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + for (int i = 0; i < groupids.Count; i++) + { + var mess = e.Message; + var reg = Regex.Match(e.Message, @"\[图片=(?<图片地址>[^\]]+)\]"); + if (reg.Success) + { + var imagePath = reg.Groups["图片地址"].Value; + var MD5Hash = FileTools.GetMD5Hash(imagePath); + if (ChatClient.ImageCDNs.ContainsKey(MD5Hash)) + { + var obj = ChatClient.ImageCDNs[MD5Hash]; + string aeskey = obj.GetType().GetProperty("aeskey").GetValue(obj).ToString(); + string cdnurl = obj.GetType().GetProperty("cdnurl").GetValue(obj).ToString(); + var ipad = e.Sender as WXClientImpl_IPAD; + if (ipad != null) + { + ipad.SendCDNInfo(groupids[i], cdnurl, aeskey, Chat.Framework.WXSdk.IPAD.CDNType.发送图片); + Thread.Sleep(500); + continue; + } + } + } + wx.SendMessage(groupids[i], mess); + Thread.Sleep(500); + } + } + } + catch (Exception ex) + { + this.OnLog($"微信:{item} - {ex.Message}"); + } + }); + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/MessageForwarder/Config.cs b/应用/MessageForwarder/Config.cs new file mode 100644 index 0000000..d49cf6a --- /dev/null +++ b/应用/MessageForwarder/Config.cs @@ -0,0 +1,35 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System.Collections.Generic; +using System.ComponentModel; +using UI.Framework.Entitys; + +namespace MessageForwarder +{ + [Config(Name = "插件-消息转发-配置")] + public class Config + { + /// + /// 群Id + /// + public string ClusterId { get; set; } + + /// + /// 监听账号 + /// + public string ListeningAccount { get; set; } + + /// + /// + /// + public string Data { get; set; } + + public Config() + { + this.ClusterId = string.Empty; + this.ListeningAccount = string.Empty; + this.Data = string.Empty; + } + + } +} diff --git a/应用/MessageForwarder/MainForm.Designer.cs b/应用/MessageForwarder/MainForm.Designer.cs new file mode 100644 index 0000000..8b4cce1 --- /dev/null +++ b/应用/MessageForwarder/MainForm.Designer.cs @@ -0,0 +1,242 @@ +namespace MessageForwarder +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.panel1 = new System.Windows.Forms.Panel(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.textBox2 = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.panel1.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // gridControl1 + // + this.gridControl1.Location = new System.Drawing.Point(1, 76); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(253, 359); + this.gridControl1.TabIndex = 5; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + this.gridControl1.Click += new System.EventHandler(this.gridControl1_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "微信号"; + this.gridColumn10.FieldName = "WeixinHao"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // panel1 + // + this.panel1.Controls.Add(this.groupBox1); + this.panel1.Location = new System.Drawing.Point(260, 76); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(415, 359); + this.panel1.TabIndex = 6; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.memoEdit1); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Location = new System.Drawing.Point(15, 13); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(388, 334); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // textEdit1 + // + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(117, 40); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(215, 20); + this.textEdit1.TabIndex = 4; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(51, 43); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 3; + this.labelControl3.Text = "微信账号:"; + this.labelControl3.Click += new System.EventHandler(this.labelControl3_Click); + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(141, 78); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(146, 14); + this.labelControl2.TabIndex = 2; + this.labelControl2.Text = "(注:多个群号用\",\"分隔)"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(17, 78); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(96, 14); + this.labelControl1.TabIndex = 2; + this.labelControl1.Text = "需要转发的群号:"; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(19, 100); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(346, 182); + this.memoEdit1.TabIndex = 1; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(141, 291); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(91, 26); + this.simpleButton1.TabIndex = 0; + this.simpleButton1.Text = " 确 定 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(207, 12); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(272, 22); + this.textBox1.TabIndex = 7; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(128, 16); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(72, 14); + this.labelControl4.TabIndex = 3; + this.labelControl4.Text = "监听群账号:"; + this.labelControl4.Click += new System.EventHandler(this.labelControl3_Click); + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(116, 44); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(84, 14); + this.labelControl5.TabIndex = 3; + this.labelControl5.Text = "监听用户账号:"; + this.labelControl5.Click += new System.EventHandler(this.labelControl3_Click); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(207, 40); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(272, 22); + this.textBox2.TabIndex = 7; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(675, 435); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.labelControl5); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.labelControl4); + this.Controls.Add(this.panel1); + this.Controls.Add(this.gridControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.panel1.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl5; + private System.Windows.Forms.TextBox textBox2; + } +} \ No newline at end of file diff --git a/应用/MessageForwarder/MainForm.cs b/应用/MessageForwarder/MainForm.cs new file mode 100644 index 0000000..c54af4b --- /dev/null +++ b/应用/MessageForwarder/MainForm.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using MessageForwarder.Properties; +using Chat.Framework.WXSdk.Implement; +using Api.Framework.Tools; + +namespace MessageForwarder +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + Dictionary result = null; + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + textBox1.Text = Class1.Config.ClusterId; + textBox2.Text = Class1.Config.ListeningAccount; + + var weixinBases = Chat.Framework.ChatClient.WXClient.Values.ToList(); + gridControl1.DataSource = weixinBases; + + result = CsharpHttpHelper.HttpExtend.JsonToDictionary(Class1.Config.Data); + if (result == null) result = new Dictionary(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void labelControl3_Click(object sender, EventArgs e) + { + + } + + private void gridControl1_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows != null && rows.Length != 0) + { + var row = gridView1.GetRow(rows[0]) as WeixinBase; + if (row != null) + { + textEdit1.Text = row.WeixinHao; + if (result != null && result.Count != 0) + memoEdit1.Text = (result.ContainsKey(row.WeixinHao)) ? result[row.WeixinHao].ToString() : string.Empty; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.ClusterId = textBox1.Text.Trim(); + Class1.Config.ListeningAccount = textBox2.Text.Trim(); + Class1.Config.Data = CsharpHttpHelper.HttpHelper.ObjectToJson(result); + Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var wxh = textEdit1.Text.Trim(); + if (result.ContainsKey(wxh)) + result[wxh] = memoEdit1.Text; + else + result.Add(wxh, memoEdit1.Text); + ShowSuccessAutoClose("保存成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} \ No newline at end of file diff --git a/应用/MessageForwarder/MainForm.resx b/应用/MessageForwarder/MainForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/MessageForwarder/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/MessageForwarder/MessageForwarder.csproj b/应用/MessageForwarder/MessageForwarder.csproj new file mode 100644 index 0000000..f940f5e --- /dev/null +++ b/应用/MessageForwarder/MessageForwarder.csproj @@ -0,0 +1,118 @@ + + + + + Debug + AnyCPU + {58751D38-B801-473A-A75E-287A2557A37D} + Library + Properties + MessageForwarder + MessageForwarder + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + MainForm.cs + Designer + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/MessageForwarder/Properties/AssemblyInfo.cs b/应用/MessageForwarder/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..eea78e5 --- /dev/null +++ b/应用/MessageForwarder/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("MessageForwarder")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MessageForwarder")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("58751d38-b801-473a-a75e-287a2557a37d")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/MessageForwarder/Properties/Resources.Designer.cs b/应用/MessageForwarder/Properties/Resources.Designer.cs new file mode 100644 index 0000000..f3e6ef1 --- /dev/null +++ b/应用/MessageForwarder/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace MessageForwarder.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MessageForwarder.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 消息转发器 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 消息转发器 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 消息转发器插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 消息转发 { + get { + object obj = ResourceManager.GetObject("消息转发", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/MessageForwarder/Properties/Resources.resx b/应用/MessageForwarder/Properties/Resources.resx new file mode 100644 index 0000000..ac21eb5 --- /dev/null +++ b/应用/MessageForwarder/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 消息转发器 + 插件窗体标题 + + + 消息转发器 + 插件名称 + + + 消息转发器插件 + 插件介绍 + + + + ..\Resources\消息转发.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/MessageForwarder/Properties/licenses.licx b/应用/MessageForwarder/Properties/licenses.licx new file mode 100644 index 0000000..121a0ef --- /dev/null +++ b/应用/MessageForwarder/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/MessageForwarder/Resources/消息转发.png b/应用/MessageForwarder/Resources/消息转发.png new file mode 100644 index 0000000..f94a879 Binary files /dev/null and b/应用/MessageForwarder/Resources/消息转发.png differ diff --git a/应用/MessageSupervises/Class1.cs b/应用/MessageSupervises/Class1.cs new file mode 100644 index 0000000..eea3ecf --- /dev/null +++ b/应用/MessageSupervises/Class1.cs @@ -0,0 +1,369 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using MessageSupervises.Entitys; +using MessageSupervises.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace MessageSupervises +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.智能拦截; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config = null; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + session.CreateTable(); + session.AddIndex("member_id"); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.WXApplyGroupEvent += SDK_WXApplyGroupEvent; + SDK.WXApplyFriendEvent += SDK_WXApplyFriendEvent; + SDK.WXNewFriendEvent += SDK_WXNewFriendEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + private void Ding(string message) + { + if (Config.auth_dingding_swich) + ApiClient.SendNoticeMessage(message, Config.notice_robotname); + } + + + private bool _check_insert_black(fl_member_info info, WeixinBase client, string remark, string message = "") + { + if (info.status == MemberType.白名单) return false; + if (Config.auth_black_swich && client != null) + { + var session = ApiClient.GetSession(); + //15天内自动跳过 + if (session.TemporaryBypassedBlack(info)) + return false; + + bool flag = false; + + var time = DateTime.Now - info.crt_time; + if (time.TotalDays >= Config.auto_black_day && info.finish_order <= Config.auto_black_order) + { + var alimama_order = session.Queryable().Where(f => f.db_userid == info.id).Count(); + var pinduoduo_order = session.Queryable().Where(f => f.db_userid == info.id).Count(); + var jingdong_order = session.Queryable().Where(f => f.db_userid == info.id).Count(); + var count = alimama_order + pinduoduo_order + jingdong_order; + if (Config.auto_black_order >= count) + { + // this.OnLog("订单数量:" + count); + flag = true; + } + } + + if (!flag && !string.IsNullOrEmpty(Config.auto_black_message) && Regex.Match(message, Config.auto_black_message).Success) + flag = true; + + if (flag) + { + info.status = MemberType.黑名单; + info.blackout_time = DateTime.Now; + session.SaveOrUpdate(info); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + Ding($"增加黑名单提醒\r\n————\r\n事件类型:{"收到消息"}\r\n微信账号:{client.WeixinHao}\r\n微信昵称:{client.User.Nick}\r\n客户账号:{info.username}\r\n客户昵称:{info.usernick}\r\n添加时间:{info.crt_time.ToString("yyyy-MM-dd HH:mm:ss")}"); + return true; + } + } + + return false; + } + + /// + /// 禁止黑名单操作 + /// + private bool _ForbidBlacklist(string username, string usernick, string remark, WeixinBase client) + { + if (client == null) return false; + try + { + var session = ApiClient.GetSession(); + var info = session.Queryable().First(f => f.username == username && f.robot_type == (client.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信)/*f.robot_type == ChatType.微信*/); + if (info != null) + { + + if (info.status == MemberType.白名单) return false; + + if (info.status == MemberType.黑名单) + { + Ding($"增加黑名单提醒\r\n————\r\n事件类型:{"收到消息"}\r\n微信账号:{client.WeixinHao}\r\n微信昵称:{client.User.Nick}\r\n客户账号:{username}\r\n客户昵称:{usernick}"); + return true; + } + + if (Config.FrequencyCloudBlack) + { + CloudBlack cloud = new CloudBlack(); + var black = cloud.QueryBlack(info); + if (black != null) + { + Ding($"云黑名单提醒\r\n————\r\n事件类型:{"收到消息"}\r\n微信账号:{client.WeixinHao}\r\n微信昵称:{client.User.Nick}\r\n客户账号:{username}\r\n客户昵称:{usernick}\r\n拉黑原因:{black.remark}"); + if (black.iscloud) + { + info.status = MemberType.黑名单; + ApiClient.GetSession().SaveOrUpdate(info); + } + return true; + } + else + return false; + } + return _check_insert_black(info, client, remark); + } + else + { + CloudBlack cloud = new CloudBlack(); + return cloud.QueryBlack(username, (client.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信)) != null; + } + } + catch (Exception) + { } + return false; + } + + private void SDK_WXNewFriendEvent(object sender, Chat.Framework.WXSdk.Events.WXNewFriend e) + { + e.Cancel = _ForbidBlacklist(e.Friend.UserName, e.Friend.NickName, $"新增好友事件", e.Client); + } + + private void SDK_WXApplyFriendEvent(object sender, Chat.Framework.WXSdk.Events.WXApplyFriend e) + { + e.Cancel = _ForbidBlacklist(e.NewFriendWxid, e.NewFriendNick, $"申请添加好友", e.Client); + } + + private void SDK_WXApplyGroupEvent(object sender, Chat.Framework.WXSdk.Events.WXApplyGroup e) + { + e.Cancel = _ForbidBlacklist(e.Wxid, e.Usernick, $"申请入群", e.Client); + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) //关闭窗体 + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// + /// 收到通用消息 + /// + /// + /// + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + var client = e.Sender as WeixinBase; + //屏蔽机器人之间的消息 + if (Chat.Framework.ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.User.Username == e.Username) != null) + { + e.Cancel = true; + return; + } + var member = e.GetMemberinfo(); + if (Config.ProhibitSL && string.IsNullOrEmpty(e.Groupid)) + { + e.Cancel = true; return; + } + if (Config.ProhibitQL && !string.IsNullOrEmpty(e.Groupid)) + { + e.Cancel = true; return; + } + if (member.status == MemberType.白名单) + return; + else if (member.status == MemberType.黑名单) + { + //白名单关键词 + if (!string.IsNullOrWhiteSpace(Config.WhiteListWords)) + { + var strs = Config.WhiteListWords.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + if (strs.FirstOrDefault(f => e.Message.Contains(f)) != null) + return; + } + if (string.IsNullOrEmpty(e.Groupid) && Class1.Config.auth_delete_black) + { + var wechat = e.Sender as WXClientImpl_IPAD; + if (wechat != null) + { + this.OnLog($"自动删除黑名单好友:{e.NickName}({e.Username})"); + wechat.DeleteFriend(e.Username); + } + } + if (client != null) Ding($"黑名单警告\r\n————\r\n事件类型:{"收到消息"}\r\n微信账号:{client.WeixinHao}\r\n微信昵称:{client.User.Nick}\r\n客户账号:{e.Username}\r\n客户昵称:{e.NickName}"); + e.Cancel = true; + return; + } + else if (Config.FrequencyCloudBlack) + { + CloudBlack cloud = new CloudBlack(); + var black = cloud.QueryBlack(member); + if (black != null) + { + if (client != null) + Ding($"云黑名单警告\r\n————\r\n事件类型:{"收到消息"}\r\n微信账号:{client.WeixinHao}\r\n微信昵称:{client.User.Nick}\r\n客户账号:{e.Username}\r\n客户昵称:{e.NickName}\r\n拉黑原因:{black.remark}"); + e.Cancel = true; + + if (black.iscloud) + { + member.status = MemberType.黑名单; + ApiClient.GetSession().SaveOrUpdate(member); + } + return; + } + } + //if (!string.IsNullOrEmpty(e.Groupid) && !Config.WhiteListSwitch && !Config.GroupWhiteList.Contains(e.Groupid)) + //{ e.Cancel = true; return; } + if (!string.IsNullOrEmpty(e.Groupid)) + { + if (!Config.WhiteListSwitch) + { + if ((Config.GroupResponseType && !Config.GroupWhiteList.Contains(e.Groupid)) || (!Config.GroupResponseType && Config.GroupWhiteList.Contains(e.Groupid))) + { e.Cancel = true; return; } + } + + if (Config.ProhibitWxid && Config.ProhibitWxidList.Length != 0) + { + if (Config.ProhibitWxidList.ToList().Contains(e.Username)) + { + e.Cancel = true; + return; + } + } + + if (Config.ProhibitNick && Config.ProhibitNickList.Length != 0) + { + var result = Config.ProhibitNickList.FirstOrDefault(f => e.NickName.Contains(f)); + if (!string.IsNullOrEmpty(result)) + { + e.Cancel = true; + return; + } + } + } + else if (string.IsNullOrEmpty(e.Groupid)) + { + if (Config.ProhibitWxid && Config.ProhibitWxidList.Length != 0) + { + if (Config.ProhibitWxidList.ToList().Contains(e.Username)) + { + e.Cancel = true; + return; + } + } + + if (Config.ProhibitNick && Config.ProhibitNickList.Length != 0) + { + var result = Config.ProhibitNickList.FirstOrDefault(f => e.NickName.Contains(f)); + if (!string.IsNullOrEmpty(result)) + { + e.Cancel = true; + return; + } + } + + var session = ApiClient.GetSession(); + int mess_count = 1; + var _flag = true; + if (mess_count < Config.FrequencyIntervalSendNum) //用户发送消息 + { + mess_count = int.Parse(session.FindRow("select count(*) as num from fl_plugin_messagesupervises_messinfo where member_id = @id and send_time >= @time ", new { id = member.id, time = DateTime.Now.AddSeconds(-Config.FrequencyIntervalSecs) })["num"].ToString()) + 1; + if (mess_count < Config.FrequencyIntervalSendNum) //为超出了频率限制,插入数据库 + { + session.ExcuteSQL("insert into fl_plugin_messagesupervises_messinfo (member_id,send_time) values (@member_id,@send_time)", new { member_id = member.id, send_time = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")) }); + _flag = false; + } + } + + if (_flag) + { + e.SendMessage(Class1.Config.FrequencyDetentionTip); + member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + e.Cancel = true; + return; + } + } + + e.Cancel = _check_insert_black(e.GetMemberinfo(), client, "收到聊天消息", e.Message); + if (e.Cancel) + { + if (string.IsNullOrEmpty(e.Groupid) && Class1.Config.auth_delete_black) + { + var wechat = e.Sender as Chat.Framework.WXSdk.Implement.WXClientImpl_IPAD; + if (wechat != null) + { + wechat.DeleteFriend(e.Username); + this.OnLog($"自动删除黑名单好友:{e.NickName}({e.Username})"); + } + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message + " - " + ex.StackTrace); + } + } + } +} diff --git a/应用/MessageSupervises/Config.cs b/应用/MessageSupervises/Config.cs new file mode 100644 index 0000000..1a9fe17 --- /dev/null +++ b/应用/MessageSupervises/Config.cs @@ -0,0 +1,164 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace MessageSupervises +{ + [Config(Name = "插件-智能拦截-配置")] + public class Config + { + + #region 频率发送限制 + + /// + /// 发送频率检测开关 + /// + public bool FrequencySwitch { get; set; } + + /// + /// 是否开启云黑名单 + /// + public bool FrequencyCloudBlack { get; set; } + + /// + /// 消息时间间隔 + /// + public int FrequencyIntervalSecs { get; set; } + + /// + /// 发送消息数量 + /// + public int FrequencyIntervalSendNum { get; set; } + + /// + /// 拉入黑名单提示 + /// + public string FrequencyDetentionTip { get; set; } + + /// + /// 禁止私聊 + /// + public bool ProhibitSL { get; set; } + + /// + /// 禁止群聊 + /// + public bool ProhibitQL { get; set; } + + /// + /// 允许回复所有群开关 + /// + public bool WhiteListSwitch { get; set; } + + /// + /// 群应答类型(true为第一个,false为第二个) + /// + public bool GroupResponseType { get; set; } + + /// + /// 群白名单 - 2020年7月30日改成回复不回复用户选择设置的群名单 + /// + public string[] GroupWhiteList { get;set;} + + /// + /// 屏蔽昵称 + /// + public bool ProhibitNick { get; set; } + + /// + /// 屏蔽昵称名单 + /// + public string[] ProhibitNickList { get; set; } + + /// + /// 屏蔽微信id + /// + public bool ProhibitWxid { get; set; } + + /// + /// 屏蔽微信id名单 + /// + public string[] ProhibitWxidList { get; set; } + + #endregion + + #region 防同行设置 + /// + /// 添加时间 + /// + public int auto_black_day { get; set; } + /// + /// 已完成订单数 + /// + public int auto_black_order { get; set; } + + /// + /// 聊天次数 + /// + public int auto_black_chat { get; set; } + + /// + /// 自动拉黑内容 + /// + public string auto_black_message { get; set; } + + ///// + ///// 钉钉报警接口 + ///// + //public string black_chat_dingding { get; set; } + + ///// + ///// 钉钉Token + ///// + //public string black_chat_dingding_token { get; set; } + + /// + /// 钉钉群通知 + /// + public string notice_robotname { get; set; } + + + public bool auth_black_swich { get; set; } + public bool auth_dingding_swich { get; set; } + + public bool auth_delete_black { get; set; } + + public string WhiteListWords { get; set; } + #endregion + + + public Config() + { + this.GroupResponseType = true; + this.WhiteListWords = string.Empty; + this.FrequencyCloudBlack = false; + this.auth_dingding_swich = true; + this.auto_black_day = 15; + this.auto_black_order = 0; + this.auto_black_chat = 15; + this.auto_black_message = ""; + this.notice_robotname = "请选择(钉钉 / 微信群机器人API名称)"; + + this.FrequencySwitch = true; + this.FrequencyIntervalSecs = 10; + this.FrequencyIntervalSendNum = 8; + this.ProhibitSL = false; + this.ProhibitQL = false; + this.FrequencyDetentionTip = @"一一一一发 言 过 快一一一一 +由于您的发言过快,已被列入黑名单,请联系管理员解除!"; + this.WhiteListSwitch = true; + this.GroupWhiteList = new string[] { }; + this.ProhibitNick = false; + this.ProhibitNickList = new string[] { }; + this.ProhibitWxid = false; + this.ProhibitWxidList = new string[] { }; + } + + } +} diff --git a/应用/MessageSupervises/Entitys/fl_plugin_messagesupervises_messinfo.cs b/应用/MessageSupervises/Entitys/fl_plugin_messagesupervises_messinfo.cs new file mode 100644 index 0000000..e6f3459 --- /dev/null +++ b/应用/MessageSupervises/Entitys/fl_plugin_messagesupervises_messinfo.cs @@ -0,0 +1,22 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MessageSupervises.Entitys +{ + public class fl_plugin_messagesupervises_messinfo : base_model + { + /// + /// 用户对象id + /// + public long member_id { get; set; } + /// + /// 消息接受时间 + /// + public DateTime send_time { get; set; } + } +} diff --git a/应用/MessageSupervises/Entitys/user_mess_temp.cs b/应用/MessageSupervises/Entitys/user_mess_temp.cs new file mode 100644 index 0000000..b194a75 --- /dev/null +++ b/应用/MessageSupervises/Entitys/user_mess_temp.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MessageSupervises.Entitys +{ + public class user_mess_temp + { + /// + /// 消息 + /// + public string mess_md5 { get; set; } + /// + /// 累计消息数量 + /// + public int count { get; set; } + } +} diff --git a/应用/MessageSupervises/MainForm.Designer.cs b/应用/MessageSupervises/MainForm.Designer.cs new file mode 100644 index 0000000..8cbc04d --- /dev/null +++ b/应用/MessageSupervises/MainForm.Designer.cs @@ -0,0 +1,953 @@ +namespace MessageSupervises +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.xtraScrollableControl1 = new DevExpress.XtraEditors.XtraScrollableControl(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.separatorControl4 = new DevExpress.XtraEditors.SeparatorControl(); + this.checkEdit4 = new DevExpress.XtraEditors.CheckEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.checkEdit3 = new DevExpress.XtraEditors.CheckEdit(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.memoEdit4 = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.buttonCheck5 = new UI.Framework.Controls.ButtonCheck(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit3 = new DevExpress.XtraEditors.MemoEdit(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.labelControl17 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.buttonCheck4 = new UI.Framework.Controls.ButtonCheck(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl16 = new DevExpress.XtraEditors.LabelControl(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.checkEdit2 = new DevExpress.XtraEditors.CheckEdit(); + this.labelControl15 = new DevExpress.XtraEditors.LabelControl(); + this.checkEdit1 = new DevExpress.XtraEditors.CheckEdit(); + this.labelControl14 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.buttonCheck3 = new UI.Framework.Controls.ButtonCheck(); + this.labelControl13 = new DevExpress.XtraEditors.LabelControl(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.separatorControl5 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl3 = new DevExpress.XtraEditors.SeparatorControl(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl19 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit2 = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl18 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.labelControl25 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl24 = new DevExpress.XtraEditors.LabelControl(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl26 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl23 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl22 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl21 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.textBox5 = new System.Windows.Forms.TextBox(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.buttonCheck7 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck6 = new UI.Framework.Controls.ButtonCheck(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.移除黑名单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.移出白名单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + this.xtraScrollableControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl5)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).BeginInit(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + this.contextMenuStrip1.SuspendLayout(); + this.contextMenuStrip2.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage3; + this.xtraTabControl1.Size = new System.Drawing.Size(736, 585); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage3, + this.xtraTabPage4}); + // + // xtraTabPage3 + // + this.xtraTabPage3.Appearance.PageClient.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(235)))), ((int)(((byte)(236)))), ((int)(((byte)(239))))); + this.xtraTabPage3.Appearance.PageClient.Options.UseBackColor = true; + this.xtraTabPage3.Controls.Add(this.groupControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(734, 559); + this.xtraTabPage3.Text = " 智 能 拦 截"; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.xtraScrollableControl1); + this.groupControl1.Location = new System.Drawing.Point(22, 15); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(689, 521); + this.groupControl1.TabIndex = 6; + this.groupControl1.Text = "智能拦截设置"; + // + // xtraScrollableControl1 + // + this.xtraScrollableControl1.Controls.Add(this.comboBox2); + this.xtraScrollableControl1.Controls.Add(this.separatorControl4); + this.xtraScrollableControl1.Controls.Add(this.checkEdit4); + this.xtraScrollableControl1.Controls.Add(this.labelControl3); + this.xtraScrollableControl1.Controls.Add(this.checkEdit3); + this.xtraScrollableControl1.Controls.Add(this.numericUpDown1); + this.xtraScrollableControl1.Controls.Add(this.memoEdit4); + this.xtraScrollableControl1.Controls.Add(this.labelControl4); + this.xtraScrollableControl1.Controls.Add(this.buttonCheck5); + this.xtraScrollableControl1.Controls.Add(this.labelControl5); + this.xtraScrollableControl1.Controls.Add(this.memoEdit3); + this.xtraScrollableControl1.Controls.Add(this.numericUpDown2); + this.xtraScrollableControl1.Controls.Add(this.labelControl17); + this.xtraScrollableControl1.Controls.Add(this.labelControl6); + this.xtraScrollableControl1.Controls.Add(this.buttonCheck4); + this.xtraScrollableControl1.Controls.Add(this.labelControl28); + this.xtraScrollableControl1.Controls.Add(this.labelControl7); + this.xtraScrollableControl1.Controls.Add(this.labelControl16); + this.xtraScrollableControl1.Controls.Add(this.separatorControl1); + this.xtraScrollableControl1.Controls.Add(this.checkEdit2); + this.xtraScrollableControl1.Controls.Add(this.labelControl15); + this.xtraScrollableControl1.Controls.Add(this.checkEdit1); + this.xtraScrollableControl1.Controls.Add(this.labelControl14); + this.xtraScrollableControl1.Controls.Add(this.labelControl8); + this.xtraScrollableControl1.Controls.Add(this.buttonCheck3); + this.xtraScrollableControl1.Controls.Add(this.labelControl13); + this.xtraScrollableControl1.Controls.Add(this.separatorControl2); + this.xtraScrollableControl1.Controls.Add(this.buttonCheck2); + this.xtraScrollableControl1.Controls.Add(this.separatorControl5); + this.xtraScrollableControl1.Controls.Add(this.separatorControl3); + this.xtraScrollableControl1.Controls.Add(this.buttonCheck1); + this.xtraScrollableControl1.Controls.Add(this.memoEdit1); + this.xtraScrollableControl1.Controls.Add(this.memoEdit5); + this.xtraScrollableControl1.Controls.Add(this.labelControl19); + this.xtraScrollableControl1.Controls.Add(this.memoEdit2); + this.xtraScrollableControl1.Controls.Add(this.labelControl18); + this.xtraScrollableControl1.Controls.Add(this.labelControl10); + this.xtraScrollableControl1.Controls.Add(this.labelControl29); + this.xtraScrollableControl1.Controls.Add(this.labelControl12); + this.xtraScrollableControl1.Controls.Add(this.labelControl11); + this.xtraScrollableControl1.Location = new System.Drawing.Point(14, 24); + this.xtraScrollableControl1.Name = "xtraScrollableControl1"; + this.xtraScrollableControl1.Size = new System.Drawing.Size(670, 485); + this.xtraScrollableControl1.TabIndex = 41; + // + // comboBox2 + // + this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Items.AddRange(new object[] { + "允许回复的群号", + "不允许回复的群号"}); + this.comboBox2.Location = new System.Drawing.Point(17, 343); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(121, 22); + this.comboBox2.TabIndex = 41; + // + // separatorControl4 + // + this.separatorControl4.Location = new System.Drawing.Point(12, 265); + this.separatorControl4.Name = "separatorControl4"; + this.separatorControl4.Size = new System.Drawing.Size(611, 23); + this.separatorControl4.TabIndex = 35; + // + // checkEdit4 + // + this.checkEdit4.Location = new System.Drawing.Point(486, 12); + this.checkEdit4.Name = "checkEdit4"; + this.checkEdit4.Properties.Caption = "自动删除黑名单用户"; + this.checkEdit4.Size = new System.Drawing.Size(137, 20); + this.checkEdit4.TabIndex = 40; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(52, 64); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 5; + this.labelControl3.Text = "智能拦截开关:"; + // + // checkEdit3 + // + this.checkEdit3.EditValue = true; + this.checkEdit3.Enabled = false; + this.checkEdit3.Location = new System.Drawing.Point(370, 12); + this.checkEdit3.Name = "checkEdit3"; + this.checkEdit3.Properties.Caption = "屏蔽黑名单"; + this.checkEdit3.Size = new System.Drawing.Size(91, 20); + this.checkEdit3.TabIndex = 39; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(144, 96); + this.numericUpDown1.Maximum = new decimal(new int[] { + 60, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(75, 22); + this.numericUpDown1.TabIndex = 7; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // memoEdit4 + // + this.memoEdit4.Location = new System.Drawing.Point(209, 209); + this.memoEdit4.Name = "memoEdit4"; + this.memoEdit4.Size = new System.Drawing.Size(378, 48); + this.memoEdit4.TabIndex = 38; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(52, 100); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(84, 14); + this.labelControl4.TabIndex = 6; + this.labelControl4.Text = "智能拦截间隔:"; + // + // buttonCheck5 + // + this.buttonCheck5.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck5.Checked = false; + this.buttonCheck5.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck5.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck5.Location = new System.Drawing.Point(142, 212); + this.buttonCheck5.Name = "buttonCheck5"; + this.buttonCheck5.Size = new System.Drawing.Size(59, 22); + this.buttonCheck5.TabIndex = 37; + this.buttonCheck5.Click += new System.EventHandler(this.buttonCheck5_Click); + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(236, 100); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(22, 14); + this.labelControl5.TabIndex = 8; + this.labelControl5.Text = "(秒)"; + // + // memoEdit3 + // + this.memoEdit3.Location = new System.Drawing.Point(209, 150); + this.memoEdit3.Name = "memoEdit3"; + this.memoEdit3.Size = new System.Drawing.Size(378, 48); + this.memoEdit3.TabIndex = 38; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(412, 95); + this.numericUpDown2.Maximum = new decimal(new int[] { + 200, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(75, 22); + this.numericUpDown2.TabIndex = 10; + this.numericUpDown2.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl17 + // + this.labelControl17.Location = new System.Drawing.Point(13, 216); + this.labelControl17.Name = "labelControl17"; + this.labelControl17.Size = new System.Drawing.Size(123, 14); + this.labelControl17.TabIndex = 36; + this.labelControl17.Text = "微信ID(支持群/私聊):"; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(320, 99); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(84, 14); + this.labelControl6.TabIndex = 9; + this.labelControl6.Text = "限制消息数量:"; + // + // buttonCheck4 + // + this.buttonCheck4.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck4.Checked = false; + this.buttonCheck4.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck4.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck4.Location = new System.Drawing.Point(142, 152); + this.buttonCheck4.Name = "buttonCheck4"; + this.buttonCheck4.Size = new System.Drawing.Size(59, 22); + this.buttonCheck4.TabIndex = 37; + this.buttonCheck4.Click += new System.EventHandler(this.buttonCheck4_Click); + // + // labelControl28 + // + this.labelControl28.Location = new System.Drawing.Point(50, 576); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(84, 14); + this.labelControl28.TabIndex = 13; + this.labelControl28.Text = "白名单词名单:"; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(38, 485); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(96, 14); + this.labelControl7.TabIndex = 13; + this.labelControl7.Text = "列入黑名单提示:"; + // + // labelControl16 + // + this.labelControl16.Location = new System.Drawing.Point(9, 156); + this.labelControl16.Name = "labelControl16"; + this.labelControl16.Size = new System.Drawing.Size(135, 14); + this.labelControl16.TabIndex = 36; + this.labelControl16.Text = "屏蔽昵称(支持群/私聊):"; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(-3, 35); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(626, 23); + this.separatorControl1.TabIndex = 14; + // + // checkEdit2 + // + this.checkEdit2.Location = new System.Drawing.Point(236, 12); + this.checkEdit2.Name = "checkEdit2"; + this.checkEdit2.Properties.Caption = "屏蔽所有群聊"; + this.checkEdit2.Size = new System.Drawing.Size(101, 20); + this.checkEdit2.TabIndex = 18; + // + // labelControl15 + // + this.labelControl15.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl15.Appearance.Options.UseForeColor = true; + this.labelControl15.Location = new System.Drawing.Point(502, 97); + this.labelControl15.Name = "labelControl15"; + this.labelControl15.Size = new System.Drawing.Size(22, 14); + this.labelControl15.TabIndex = 34; + this.labelControl15.Text = "(条)"; + // + // checkEdit1 + // + this.checkEdit1.Location = new System.Drawing.Point(125, 12); + this.checkEdit1.Name = "checkEdit1"; + this.checkEdit1.Properties.Caption = "屏蔽所有私聊"; + this.checkEdit1.Size = new System.Drawing.Size(105, 20); + this.checkEdit1.TabIndex = 15; + // + // labelControl14 + // + this.labelControl14.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl14.Appearance.Options.UseForeColor = true; + this.labelControl14.Location = new System.Drawing.Point(480, 61); + this.labelControl14.Name = "labelControl14"; + this.labelControl14.Size = new System.Drawing.Size(155, 14); + this.labelControl14.TabIndex = 33; + this.labelControl14.Text = "(右击用户->添加到云黑名单)"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(26, 15); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(84, 14); + this.labelControl8.TabIndex = 17; + this.labelControl8.Text = "屏蔽消息类型:"; + // + // buttonCheck3 + // + this.buttonCheck3.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck3.Checked = false; + this.buttonCheck3.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck3.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck3.Location = new System.Drawing.Point(412, 59); + this.buttonCheck3.Name = "buttonCheck3"; + this.buttonCheck3.Size = new System.Drawing.Size(59, 22); + this.buttonCheck3.TabIndex = 32; + // + // labelControl13 + // + this.labelControl13.Enabled = false; + this.labelControl13.Location = new System.Drawing.Point(320, 63); + this.labelControl13.Name = "labelControl13"; + this.labelControl13.Size = new System.Drawing.Size(84, 14); + this.labelControl13.TabIndex = 31; + this.labelControl13.Text = "云黑名单拦截:"; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(-3, 123); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(626, 23); + this.separatorControl2.TabIndex = 21; + // + // buttonCheck2 + // + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = false; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(142, 59); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(59, 22); + this.buttonCheck2.TabIndex = 30; + this.buttonCheck2.Click += new System.EventHandler(this.buttonCheck2_Click); + // + // separatorControl5 + // + this.separatorControl5.Location = new System.Drawing.Point(0, 545); + this.separatorControl5.Name = "separatorControl5"; + this.separatorControl5.Size = new System.Drawing.Size(626, 23); + this.separatorControl5.TabIndex = 22; + // + // separatorControl3 + // + this.separatorControl3.Location = new System.Drawing.Point(-3, 450); + this.separatorControl3.Name = "separatorControl3"; + this.separatorControl3.Size = new System.Drawing.Size(626, 23); + this.separatorControl3.TabIndex = 22; + // + // buttonCheck1 + // + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = false; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(142, 290); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(59, 22); + this.buttonCheck1.TabIndex = 29; + this.buttonCheck1.Click += new System.EventHandler(this.buttonCheck1_Click); + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(144, 330); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(443, 114); + this.memoEdit1.TabIndex = 23; + // + // memoEdit5 + // + this.memoEdit5.Location = new System.Drawing.Point(142, 574); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Size = new System.Drawing.Size(443, 60); + this.memoEdit5.TabIndex = 24; + // + // labelControl19 + // + this.labelControl19.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl19.Appearance.Options.UseForeColor = true; + this.labelControl19.Location = new System.Drawing.Point(94, 180); + this.labelControl19.Name = "labelControl19"; + this.labelControl19.Size = new System.Drawing.Size(106, 14); + this.labelControl19.TabIndex = 28; + this.labelControl19.Text = "(多个请用 , 号分隔)"; + // + // memoEdit2 + // + this.memoEdit2.Location = new System.Drawing.Point(142, 482); + this.memoEdit2.Name = "memoEdit2"; + this.memoEdit2.Size = new System.Drawing.Size(443, 60); + this.memoEdit2.TabIndex = 24; + // + // labelControl18 + // + this.labelControl18.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl18.Appearance.Options.UseForeColor = true; + this.labelControl18.Location = new System.Drawing.Point(94, 240); + this.labelControl18.Name = "labelControl18"; + this.labelControl18.Size = new System.Drawing.Size(106, 14); + this.labelControl18.TabIndex = 28; + this.labelControl18.Text = "(多个请用 , 号分隔)"; + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(40, 294); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(96, 14); + this.labelControl10.TabIndex = 26; + this.labelControl10.Text = "允许回复所有群:"; + // + // labelControl29 + // + this.labelControl29.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl29.Appearance.Options.UseForeColor = true; + this.labelControl29.Location = new System.Drawing.Point(30, 596); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(106, 14); + this.labelControl29.TabIndex = 28; + this.labelControl29.Text = "(多个请用 , 号分隔)"; + // + // labelControl12 + // + this.labelControl12.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl12.Appearance.Options.UseForeColor = true; + this.labelControl12.Location = new System.Drawing.Point(26, 373); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(106, 14); + this.labelControl12.TabIndex = 28; + this.labelControl12.Text = "(多个请用 , 号分隔)"; + // + // labelControl11 + // + this.labelControl11.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl11.Appearance.Options.UseForeColor = true; + this.labelControl11.Location = new System.Drawing.Point(217, 294); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(370, 14); + this.labelControl11.TabIndex = 27; + this.labelControl11.Text = "(关闭的情况,请在下方填写具体要回复的群号.开启的情况,回复所有群)"; + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.label1); + this.xtraTabPage4.Controls.Add(this.groupControl3); + this.xtraTabPage4.Controls.Add(this.groupControl2); + this.xtraTabPage4.Controls.Add(this.buttonCheck7); + this.xtraTabPage4.Controls.Add(this.buttonCheck6); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(734, 559); + this.xtraTabPage4.Text = " 同 行 免 疫"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ForeColor = System.Drawing.Color.Gray; + this.label1.Location = new System.Drawing.Point(169, 434); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(389, 14); + this.label1.TabIndex = 42; + this.label1.Text = "如果人为取消黑名单、该用户15天内,不会再进入黑名单条件筛选逻辑中!"; + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.labelControl30); + this.groupControl3.Controls.Add(this.labelControl27); + this.groupControl3.Controls.Add(this.comboBox1); + this.groupControl3.Controls.Add(this.labelControl25); + this.groupControl3.Controls.Add(this.labelControl24); + this.groupControl3.Location = new System.Drawing.Point(11, 209); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(711, 175); + this.groupControl3.TabIndex = 1; + this.groupControl3.Text = "黑名单报警"; + // + // labelControl30 + // + this.labelControl30.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl30.Appearance.Options.UseForeColor = true; + this.labelControl30.Location = new System.Drawing.Point(211, 88); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(215, 14); + this.labelControl30.TabIndex = 55; + this.labelControl30.Text = "(在【系统管理->群通知机器人】中添加)"; + // + // labelControl27 + // + this.labelControl27.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl27.Appearance.Options.UseForeColor = true; + this.labelControl27.Location = new System.Drawing.Point(488, 63); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(130, 14); + this.labelControl27.TabIndex = 54; + this.labelControl27.Text = "(未选择时使用系统设置)"; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(153, 60); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(308, 22); + this.comboBox1.TabIndex = 53; + // + // labelControl25 + // + this.labelControl25.Location = new System.Drawing.Point(57, 63); + this.labelControl25.Name = "labelControl25"; + this.labelControl25.Size = new System.Drawing.Size(91, 14); + this.labelControl25.TabIndex = 52; + this.labelControl25.Text = "群通知API接口:"; + // + // labelControl24 + // + this.labelControl24.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl24.Appearance.Options.UseForeColor = true; + this.labelControl24.Location = new System.Drawing.Point(143, 119); + this.labelControl24.Name = "labelControl24"; + this.labelControl24.Size = new System.Drawing.Size(362, 14); + this.labelControl24.TabIndex = 51; + this.labelControl24.Text = "(注意:用戶被拉黑、或者有黑名單用戶发消息过来、会通知钉钉接口)"; + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.labelControl26); + this.groupControl2.Controls.Add(this.labelControl23); + this.groupControl2.Controls.Add(this.labelControl22); + this.groupControl2.Controls.Add(this.labelControl21); + this.groupControl2.Controls.Add(this.labelControl20); + this.groupControl2.Controls.Add(this.labelControl2); + this.groupControl2.Controls.Add(this.labelControl1); + this.groupControl2.Controls.Add(this.textBox5); + this.groupControl2.Controls.Add(this.textBox4); + this.groupControl2.Controls.Add(this.textBox3); + this.groupControl2.Controls.Add(this.textBox2); + this.groupControl2.Location = new System.Drawing.Point(11, 33); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(711, 132); + this.groupControl2.TabIndex = 0; + this.groupControl2.Text = "自动黑名单"; + // + // labelControl26 + // + this.labelControl26.Location = new System.Drawing.Point(569, 47); + this.labelControl26.Name = "labelControl26"; + this.labelControl26.Size = new System.Drawing.Size(123, 14); + this.labelControl26.TabIndex = 51; + this.labelControl26.Text = "次,且账户余额低于1元!"; + // + // labelControl23 + // + this.labelControl23.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl23.Appearance.Options.UseForeColor = true; + this.labelControl23.Location = new System.Drawing.Point(432, 85); + this.labelControl23.Name = "labelControl23"; + this.labelControl23.Size = new System.Drawing.Size(272, 14); + this.labelControl23.TabIndex = 50; + this.labelControl23.Text = "(聊天内容中,包含里面内容自动拉黑[正则表达式])"; + // + // labelControl22 + // + this.labelControl22.Location = new System.Drawing.Point(57, 85); + this.labelControl22.Name = "labelControl22"; + this.labelControl22.Size = new System.Drawing.Size(84, 14); + this.labelControl22.TabIndex = 49; + this.labelControl22.Text = "自动拉黑口令:"; + // + // labelControl21 + // + this.labelControl21.Location = new System.Drawing.Point(57, 47); + this.labelControl21.Name = "labelControl21"; + this.labelControl21.Size = new System.Drawing.Size(84, 14); + this.labelControl21.TabIndex = 48; + this.labelControl21.Text = "自动拉黑条件:"; + // + // labelControl20 + // + this.labelControl20.Location = new System.Drawing.Point(432, 47); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(73, 14); + this.labelControl20.TabIndex = 47; + this.labelControl20.Text = "单,聊天次数≥"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(268, 47); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(109, 14); + this.labelControl2.TabIndex = 46; + this.labelControl2.Text = "天,但是已完成订单≤"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(153, 47); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 45; + this.labelControl1.Text = "加好友超过"; + // + // textBox5 + // + this.textBox5.Location = new System.Drawing.Point(511, 43); + this.textBox5.Name = "textBox5"; + this.textBox5.Size = new System.Drawing.Size(43, 22); + this.textBox5.TabIndex = 44; + // + // textBox4 + // + this.textBox4.Location = new System.Drawing.Point(383, 43); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(43, 22); + this.textBox4.TabIndex = 43; + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(219, 43); + this.textBox3.Name = "textBox3"; + this.textBox3.Size = new System.Drawing.Size(43, 22); + this.textBox3.TabIndex = 42; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(153, 82); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(273, 22); + this.textBox2.TabIndex = 38; + // + // buttonCheck7 + // + this.buttonCheck7.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck7.Checked = true; + this.buttonCheck7.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck7.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck7.Location = new System.Drawing.Point(21, 186); + this.buttonCheck7.Name = "buttonCheck7"; + this.buttonCheck7.Size = new System.Drawing.Size(59, 20); + this.buttonCheck7.TabIndex = 34; + this.buttonCheck7.Click += new System.EventHandler(this.buttonCheck7_Click); + // + // buttonCheck6 + // + this.buttonCheck6.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck6.Checked = true; + this.buttonCheck6.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck6.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck6.Location = new System.Drawing.Point(17, 11); + this.buttonCheck6.Name = "buttonCheck6"; + this.buttonCheck6.Size = new System.Drawing.Size(59, 20); + this.buttonCheck6.TabIndex = 33; + this.buttonCheck6.Click += new System.EventHandler(this.buttonCheck6_Click); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.移除黑名单ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(137, 26); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 移除黑名单ToolStripMenuItem + // + this.移除黑名单ToolStripMenuItem.Name = "移除黑名单ToolStripMenuItem"; + this.移除黑名单ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.移除黑名单ToolStripMenuItem.Text = "移出黑名单"; + this.移除黑名单ToolStripMenuItem.Click += new System.EventHandler(this.移除ToolStripMenuItem_Click); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.移出白名单ToolStripMenuItem}); + this.contextMenuStrip2.Name = "contextMenuStrip2"; + this.contextMenuStrip2.Size = new System.Drawing.Size(137, 26); + this.contextMenuStrip2.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip2_Opening); + // + // 移出白名单ToolStripMenuItem + // + this.移出白名单ToolStripMenuItem.Name = "移出白名单ToolStripMenuItem"; + this.移出白名单ToolStripMenuItem.Size = new System.Drawing.Size(136, 22); + this.移出白名单ToolStripMenuItem.Text = "移出白名单"; + this.移出白名单ToolStripMenuItem.Click += new System.EventHandler(this.移除ToolStripMenuItem_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(736, 585); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.xtraScrollableControl1.ResumeLayout(false); + this.xtraScrollableControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl5)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).EndInit(); + this.xtraTabPage4.ResumeLayout(false); + this.xtraTabPage4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + this.groupControl3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + this.contextMenuStrip1.ResumeLayout(false); + this.contextMenuStrip2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.LabelControl labelControl6; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private DevExpress.XtraEditors.LabelControl labelControl7; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem 移除黑名单ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 移出白名单ToolStripMenuItem; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.CheckEdit checkEdit1; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private DevExpress.XtraEditors.CheckEdit checkEdit2; + private DevExpress.XtraEditors.SeparatorControl separatorControl3; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private DevExpress.XtraEditors.MemoEdit memoEdit2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl10; + private DevExpress.XtraEditors.LabelControl labelControl11; + private DevExpress.XtraEditors.LabelControl labelControl12; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private DevExpress.XtraEditors.LabelControl labelControl13; + private UI.Framework.Controls.ButtonCheck buttonCheck3; + private DevExpress.XtraEditors.LabelControl labelControl14; + private DevExpress.XtraEditors.LabelControl labelControl15; + private UI.Framework.Controls.ButtonCheck buttonCheck4; + private DevExpress.XtraEditors.LabelControl labelControl16; + private DevExpress.XtraEditors.SeparatorControl separatorControl4; + private DevExpress.XtraEditors.MemoEdit memoEdit3; + private DevExpress.XtraEditors.MemoEdit memoEdit4; + private UI.Framework.Controls.ButtonCheck buttonCheck5; + private DevExpress.XtraEditors.LabelControl labelControl17; + private DevExpress.XtraEditors.LabelControl labelControl19; + private DevExpress.XtraEditors.LabelControl labelControl18; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private DevExpress.XtraEditors.GroupControl groupControl2; + private UI.Framework.Controls.ButtonCheck buttonCheck6; + private DevExpress.XtraEditors.GroupControl groupControl3; + private UI.Framework.Controls.ButtonCheck buttonCheck7; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox5; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.TextBox textBox3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl20; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.CheckEdit checkEdit4; + private DevExpress.XtraEditors.CheckEdit checkEdit3; + private DevExpress.XtraEditors.LabelControl labelControl22; + private DevExpress.XtraEditors.LabelControl labelControl21; + private DevExpress.XtraEditors.LabelControl labelControl25; + private DevExpress.XtraEditors.LabelControl labelControl24; + private DevExpress.XtraEditors.LabelControl labelControl23; + private DevExpress.XtraEditors.LabelControl labelControl26; + private DevExpress.XtraEditors.XtraScrollableControl xtraScrollableControl1; + private DevExpress.XtraEditors.LabelControl labelControl28; + private DevExpress.XtraEditors.SeparatorControl separatorControl5; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private DevExpress.XtraEditors.LabelControl labelControl29; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.LabelControl labelControl27; + private DevExpress.XtraEditors.LabelControl labelControl30; + private System.Windows.Forms.ComboBox comboBox2; + } +} \ No newline at end of file diff --git a/应用/MessageSupervises/MainForm.cs b/应用/MessageSupervises/MainForm.cs new file mode 100644 index 0000000..14424c8 --- /dev/null +++ b/应用/MessageSupervises/MainForm.cs @@ -0,0 +1,203 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using MessageSupervises.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace MessageSupervises +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var apis = session.FindNoticeapiRobots().ToArray(); + var rst = new List(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + comboBox1.DataSource = rst; + + this.buttonCheck2.Checked = numericUpDown1.Enabled = numericUpDown2.Enabled = Class1.Config.FrequencySwitch; + this.buttonCheck3.Checked = Class1.Config.FrequencyCloudBlack; + this.buttonCheck1.Checked = Class1.Config.WhiteListSwitch; + this.memoEdit1.Enabled = !Class1.Config.WhiteListSwitch; + this.numericUpDown1.Value = Class1.Config.FrequencyIntervalSecs; + this.numericUpDown2.Value = Class1.Config.FrequencyIntervalSendNum; + this.memoEdit2.Text = Class1.Config.FrequencyDetentionTip; + this.memoEdit5.Text = Class1.Config.WhiteListWords; + this.checkEdit1.Checked = Class1.Config.ProhibitSL; + this.checkEdit2.Checked = Class1.Config.ProhibitQL; + this.comboBox2.SelectedIndex = Class1.Config.GroupResponseType ? 0 : 1; + this.memoEdit1.Text = string.Join(",", Class1.Config.GroupWhiteList); + this.buttonCheck4.Checked = this.memoEdit3.Enabled = Class1.Config.ProhibitNick; + this.memoEdit3.Text = string.Join(",", Class1.Config.ProhibitNickList); + this.buttonCheck5.Checked = this.memoEdit4.Enabled = Class1.Config.ProhibitWxid; + this.memoEdit4.Text = string.Join(",", Class1.Config.ProhibitWxidList); + this.checkEdit4.Checked = Class1.Config.auth_delete_black; + + this.textBox3.Text = Class1.Config.auto_black_day.ToString(); + this.textBox4.Text = Class1.Config.auto_black_order.ToString(); + this.textBox5.Text = Class1.Config.auto_black_chat.ToString(); + this.textBox2.Text = Class1.Config.auto_black_message; + this.comboBox1.SelectedIndex = rst.IndexOf(Class1.Config.notice_robotname) == -1 ? 0 : rst.IndexOf(Class1.Config.notice_robotname); + this.buttonCheck6.Checked = Class1.Config.auth_black_swich; + this.buttonCheck7.Checked = Class1.Config.auth_dingding_swich; + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.FrequencySwitch = buttonCheck2.Checked; + Class1.Config.WhiteListSwitch = buttonCheck1.Checked; + Class1.Config.FrequencyIntervalSecs = (int)numericUpDown1.Value; + Class1.Config.FrequencyIntervalSendNum = (int)numericUpDown2.Value; + Class1.Config.FrequencyDetentionTip = memoEdit2.Text; + Class1.Config.WhiteListWords = memoEdit5.Text; + Class1.Config.ProhibitSL = checkEdit1.Checked; + Class1.Config.ProhibitQL = checkEdit2.Checked; + Class1.Config.GroupResponseType = comboBox2.SelectedIndex == 0; + Class1.Config.GroupWhiteList = memoEdit1.Text.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + Class1.Config.ProhibitNick = buttonCheck4.Checked; + Class1.Config.ProhibitNickList = memoEdit3.Text.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + Class1.Config.ProhibitWxid = buttonCheck5.Checked; + Class1.Config.ProhibitWxidList = memoEdit4.Text.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + Class1.Config.auth_delete_black = this.checkEdit4.Checked; + + Class1.Config.auto_black_day = int.Parse(this.textBox3.Text); + Class1.Config.auto_black_order = int.Parse(this.textBox4.Text); + Class1.Config.auto_black_chat = int.Parse(this.textBox5.Text); + Class1.Config.auto_black_message = this.textBox2.Text; + Class1.Config.notice_robotname = this.comboBox1.SelectedValue.ToString(); + Class1.Config.auth_black_swich = this.buttonCheck6.Checked; + Class1.Config.auth_dingding_swich = this.buttonCheck7.Checked; + Class1.Config.FrequencyCloudBlack = this.buttonCheck3.Checked; + groupControl2.Enabled = buttonCheck6.Checked; + groupControl3.Enabled = buttonCheck7.Checked; + + Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + private void 移除ToolStripMenuItem_Click(object sender, EventArgs e) + { + //try + //{ + // int[] selectRows = gridView1.GetSelectedRows();//获取选中的列 + // if (selectRows.Length != 0) + // { + // string id = this.gridView1.GetRowCellValue(selectRows[0], "id").ToString();//获取列的数据 + // var session = ApiClient.GetSession(); + // session.ExcuteSQL("update fl_member_info set status = 0 where id=@id", new { id = id }); + // pageControl1.GotoPage(); + // label1.Visible = gridView1.RowCount == 0; + // pageControl2.GotoPage(); + // label2.Visible = gridView2.RowCount == 0; + // } + //} + //catch (Exception ex) + //{ + // ShowError(ex); + //} + } + + private void contextMenuStrip2_Opening(object sender, CancelEventArgs e) + { + //try + //{ + // int[] selectRows = gridView2.GetSelectedRows();//获取选中的列 + // if (selectRows.Length != 0) + // { + // if (selectRows.Length == 0) + // contextMenuStrip2.Items[0].Enabled = false; + // else + // contextMenuStrip2.Items[0].Enabled = true; + // } + //} + //catch (Exception ex) + //{ + // ShowError(ex); + //} + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + //try + //{ + // int[] selectRows = gridView1.GetSelectedRows();//获取选中的列 + // if (selectRows.Length == 0) + // contextMenuStrip1.Items[0].Enabled = false; + // else + // contextMenuStrip1.Items[0].Enabled = true; + //} + //catch (Exception ex) + //{ + // ShowError(ex); + //} + } + + private void buttonCheck1_Click(object sender, EventArgs e) + { + memoEdit1.Enabled = !buttonCheck1.Checked; + } + + private void buttonCheck2_Click(object sender, EventArgs e) + { + numericUpDown1.Enabled = numericUpDown2.Enabled = buttonCheck2.Checked; + } + + private void buttonCheck4_Click(object sender, EventArgs e) + { + memoEdit3.Enabled = buttonCheck4.Checked; + } + + private void buttonCheck5_Click(object sender, EventArgs e) + { + memoEdit4.Enabled = buttonCheck5.Checked; + } + + private void buttonCheck6_Click(object sender, EventArgs e) + { + groupControl2.Enabled = this.buttonCheck6.Checked; + } + + private void buttonCheck7_Click(object sender, EventArgs e) + { + groupControl3.Enabled = this.buttonCheck7.Checked; + } + } +} diff --git a/应用/MessageSupervises/MainForm.resx b/应用/MessageSupervises/MainForm.resx new file mode 100644 index 0000000..83e44e5 --- /dev/null +++ b/应用/MessageSupervises/MainForm.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 274, 17 + + + 52 + + \ No newline at end of file diff --git a/应用/MessageSupervises/MessInfoClearThread.cs b/应用/MessageSupervises/MessInfoClearThread.cs new file mode 100644 index 0000000..30b4eb9 --- /dev/null +++ b/应用/MessageSupervises/MessInfoClearThread.cs @@ -0,0 +1,29 @@ +using Api.Framework; +using Api.Framework.SDK; +using Easy4net.Common; +using Easy4net.Context; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MessageSupervises +{ + class MessInfoClearThread : TimerTask + { + public override void Run(object state, bool timedOut) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_messagesupervises_messinfo where send_time < @time",new { time = DateTime.Now.AddSeconds(-(Class1.Config.FrequencyIntervalSecs + 1)) }); + + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具:{ex.Message}"); + } + } + } +} diff --git a/应用/MessageSupervises/MessageSupervises.csproj b/应用/MessageSupervises/MessageSupervises.csproj new file mode 100644 index 0000000..baca760 --- /dev/null +++ b/应用/MessageSupervises/MessageSupervises.csproj @@ -0,0 +1,173 @@ + + + + + Debug + AnyCPU + {659742CF-6EAD-42C6-B2EF-93F1FF2465F1} + Library + Properties + MessageSupervises + MessageSupervises + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/应用/MessageSupervises/Properties/AssemblyInfo.cs b/应用/MessageSupervises/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..945e28b --- /dev/null +++ b/应用/MessageSupervises/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("MessageSupervises")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MessageSupervises")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("659742cf-6ead-42c6-b2ef-93f1ff2465f1")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2019.04.04.1")] +[assembly: AssemblyFileVersion("2019.04.04.1")] diff --git a/应用/MessageSupervises/Properties/Resources.Designer.cs b/应用/MessageSupervises/Properties/Resources.Designer.cs new file mode 100644 index 0000000..0f5afd9 --- /dev/null +++ b/应用/MessageSupervises/Properties/Resources.Designer.cs @@ -0,0 +1,150 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace MessageSupervises.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MessageSupervises.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 智能拦截 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 智能拦截 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 智能拦截插件,限制发送频率,高频者拉至黑名单 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 免疫 { + get { + object obj = ResourceManager.GetObject("免疫", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 智能拦截 { + get { + object obj = ResourceManager.GetObject("智能拦截", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 白名单 { + get { + object obj = ResourceManager.GetObject("白名单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 盾牌__1_ { + get { + object obj = ResourceManager.GetObject("盾牌 (1)", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 频率 { + get { + object obj = ResourceManager.GetObject("频率", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 黑名单 { + get { + object obj = ResourceManager.GetObject("黑名单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/MessageSupervises/Properties/Resources.resx b/应用/MessageSupervises/Properties/Resources.resx new file mode 100644 index 0000000..0cf85e8 --- /dev/null +++ b/应用/MessageSupervises/Properties/Resources.resx @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 智能拦截 + 插件名 + + + 智能拦截插件,限制发送频率,高频者拉至黑名单 + 插件介绍 + + + + ..\Resources\黑名单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\智能拦截.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\盾牌 (1).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\频率.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 智能拦截 + 设置主窗体标题 + + + ..\Resources\白名单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\免疫.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/MessageSupervises/Properties/licenses.licx b/应用/MessageSupervises/Properties/licenses.licx new file mode 100644 index 0000000..5a7d905 --- /dev/null +++ b/应用/MessageSupervises/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/MessageSupervises/Resources/免疫.png b/应用/MessageSupervises/Resources/免疫.png new file mode 100644 index 0000000..b4f3bcd Binary files /dev/null and b/应用/MessageSupervises/Resources/免疫.png differ diff --git a/应用/MessageSupervises/Resources/智能拦截.png b/应用/MessageSupervises/Resources/智能拦截.png new file mode 100644 index 0000000..a50d925 Binary files /dev/null and b/应用/MessageSupervises/Resources/智能拦截.png differ diff --git a/应用/MessageSupervises/Resources/白名单.png b/应用/MessageSupervises/Resources/白名单.png new file mode 100644 index 0000000..902e7e8 Binary files /dev/null and b/应用/MessageSupervises/Resources/白名单.png differ diff --git a/应用/MessageSupervises/Resources/盾牌 (1).png b/应用/MessageSupervises/Resources/盾牌 (1).png new file mode 100644 index 0000000..6cd1162 Binary files /dev/null and b/应用/MessageSupervises/Resources/盾牌 (1).png differ diff --git a/应用/MessageSupervises/Resources/盾牌.png b/应用/MessageSupervises/Resources/盾牌.png new file mode 100644 index 0000000..684a6fd Binary files /dev/null and b/应用/MessageSupervises/Resources/盾牌.png differ diff --git a/应用/MessageSupervises/Resources/频率.png b/应用/MessageSupervises/Resources/频率.png new file mode 100644 index 0000000..81b05e3 Binary files /dev/null and b/应用/MessageSupervises/Resources/频率.png differ diff --git a/应用/MessageSupervises/Resources/黑名单.png b/应用/MessageSupervises/Resources/黑名单.png new file mode 100644 index 0000000..ad988f2 Binary files /dev/null and b/应用/MessageSupervises/Resources/黑名单.png differ diff --git a/应用/NewFans/Class1.cs b/应用/NewFans/Class1.cs new file mode 100644 index 0000000..d2b9150 --- /dev/null +++ b/应用/NewFans/Class1.cs @@ -0,0 +1,100 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using NewFans.Entitys; +using NewFans.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewFans +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = "新粉助手"; + this.Note = "新粉助手"; + this.Logo = Resources._222; + } + + #region 自定义变量 + //public static Config Config; + private MainForm mainForm = null; + // public static VariateReplace variateReplace = null; + #endregion + + public static Config Config = null; + TaskJob taskJob = null; + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("uid"); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + + Config.hour3 = 20;//三个小时的改成20分钟了 + Config.hour24 = 24 * 60; + Config.hour48 = 48 * 60; + Config.hour72 = 72 * 60; + + Util.Save(Config); + + taskJob = new TaskJob(); + taskJob.Run(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + public override void Stop() + { + try + { + //SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + taskJob.Abort(); + taskJob = null; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/NewFans/Config.cs b/应用/NewFans/Config.cs new file mode 100644 index 0000000..c188351 --- /dev/null +++ b/应用/NewFans/Config.cs @@ -0,0 +1,23 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewFans +{ + [Config(Name = "插件-新粉助手-配置")] + public class Config + { + public bool isRun { get; set; } = false; + public int hour3 { get; set; } = 20; + public string mess3 { get; set; } = "你已经20分钟没有理我了呢"; + public int hour24 { get; set; } = 24 * 60; + public string mess24 { get; set; } = "你已经24小时没有理我了呢"; + public int hour48 { get; set; } = 48 * 60; + public string mess48 { get; set; } = "您已经48小时没有理我了呢"; + public int hour72 { get; set; } = 72 * 60; + public string mess72 { get; set; } = "您已经72小时没有理我了呢"; + } +} diff --git a/应用/NewFans/Entitys/fl_newfans_hist.cs b/应用/NewFans/Entitys/fl_newfans_hist.cs new file mode 100644 index 0000000..71b4e28 --- /dev/null +++ b/应用/NewFans/Entitys/fl_newfans_hist.cs @@ -0,0 +1,17 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewFans.Entitys +{ + public class fl_newfans__hist : base_model + { + public int uid { get; set; } + + public int time { get; set; } + + } +} diff --git a/应用/NewFans/Entitys/fl_newfans_hist_.cs b/应用/NewFans/Entitys/fl_newfans_hist_.cs new file mode 100644 index 0000000..a9e847d --- /dev/null +++ b/应用/NewFans/Entitys/fl_newfans_hist_.cs @@ -0,0 +1,20 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewFans.Entitys +{ + public class fl_newfans_hist_ : base_model + { + public int uid { get; set; } + + /// + /// 单位 分钟 + /// + public int time { get; set; } + + } +} diff --git a/应用/NewFans/MainForm.Designer.cs b/应用/NewFans/MainForm.Designer.cs new file mode 100644 index 0000000..5d87f8c --- /dev/null +++ b/应用/NewFans/MainForm.Designer.cs @@ -0,0 +1,174 @@ +namespace NewFans +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.textBox0 = new System.Windows.Forms.TextBox(); + this.label0 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.checkBox1); + this.groupBox1.Controls.Add(this.textBox0); + this.groupBox1.Controls.Add(this.label0); + this.groupBox1.Controls.Add(this.textBox3); + this.groupBox1.Controls.Add(this.textBox2); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Location = new System.Drawing.Point(12, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(603, 421); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基 础 设 置 "; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(117, 20); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(72, 16); + this.checkBox1.TabIndex = 11; + this.checkBox1.Text = "勾选启用"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // textBox0 + // + this.textBox0.Location = new System.Drawing.Point(117, 59); + this.textBox0.Multiline = true; + this.textBox0.Name = "textBox0"; + this.textBox0.Size = new System.Drawing.Size(459, 76); + this.textBox0.TabIndex = 10; + // + // label0 + // + this.label0.AutoSize = true; + this.label0.Location = new System.Drawing.Point(46, 62); + this.label0.Name = "label0"; + this.label0.Size = new System.Drawing.Size(65, 12); + this.label0.TabIndex = 9; + this.label0.Text = "20分钟话术"; + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(117, 327); + this.textBox3.Multiline = true; + this.textBox3.Name = "textBox3"; + this.textBox3.Size = new System.Drawing.Size(459, 76); + this.textBox3.TabIndex = 8; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(117, 238); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(459, 76); + this.textBox2.TabIndex = 7; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(117, 149); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(459, 76); + this.textBox1.TabIndex = 6; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(46, 241); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(65, 12); + this.label4.TabIndex = 5; + this.label4.Text = "48小时话术"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(46, 330); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(65, 12); + this.label6.TabIndex = 3; + this.label6.Text = "72小时话术"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(46, 152); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(65, 12); + this.label2.TabIndex = 1; + this.label2.Text = "24小时话术"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(627, 445); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = " 新 粉 助 手 "; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox textBox0; + private System.Windows.Forms.Label label0; + private System.Windows.Forms.CheckBox checkBox1; + } +} \ No newline at end of file diff --git a/应用/NewFans/MainForm.cs b/应用/NewFans/MainForm.cs new file mode 100644 index 0000000..1858462 --- /dev/null +++ b/应用/NewFans/MainForm.cs @@ -0,0 +1,76 @@ +using Api.Framework; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace NewFans +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + this.Text = "新粉助手"; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + checkBox1.Checked = Class1.Config.isRun; + textBox0.Text = Class1.Config.mess3; + textBox1.Text = Class1.Config.mess24; + textBox2.Text = Class1.Config.mess48; + textBox3.Text = Class1.Config.mess72; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.isRun = checkBox1.Checked; + Class1.Config.mess3 = textBox0.Text; + Class1.Config.mess24 = textBox1.Text; + Class1.Config.mess48 = textBox2.Text; + Class1.Config.mess72 = textBox3.Text; + Util.Save(Class1.Config); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + } +} diff --git a/应用/NewFans/MainForm.resx b/应用/NewFans/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/应用/NewFans/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/应用/NewFans/NewFans.csproj b/应用/NewFans/NewFans.csproj new file mode 100644 index 0000000..e7e6b26 --- /dev/null +++ b/应用/NewFans/NewFans.csproj @@ -0,0 +1,112 @@ + + + + + Debug + AnyCPU + {1185C5AA-3D1B-44F0-96EB-CFA4C4D7372B} + Library + Properties + NewFans + NewFans + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + + {DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07} + Api.Framework + False + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/NewFans/Properties/AssemblyInfo.cs b/应用/NewFans/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ffd92b0 --- /dev/null +++ b/应用/NewFans/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("NewFans")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NewFans")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("1185c5aa-3d1b-44f0-96eb-cfa4c4d7372b")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/NewFans/Properties/Resources.Designer.cs b/应用/NewFans/Properties/Resources.Designer.cs new file mode 100644 index 0000000..b7f8673 --- /dev/null +++ b/应用/NewFans/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace NewFans.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NewFans.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap _222 { + get { + object obj = ResourceManager.GetObject("_222", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/NewFans/Properties/Resources.resx b/应用/NewFans/Properties/Resources.resx new file mode 100644 index 0000000..b83a54c --- /dev/null +++ b/应用/NewFans/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\222.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/NewFans/Resources/222.png b/应用/NewFans/Resources/222.png new file mode 100644 index 0000000..51ebec9 Binary files /dev/null and b/应用/NewFans/Resources/222.png differ diff --git a/应用/NewFans/TaskJob.cs b/应用/NewFans/TaskJob.cs new file mode 100644 index 0000000..f19960f --- /dev/null +++ b/应用/NewFans/TaskJob.cs @@ -0,0 +1,171 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.Tools; +using NewFans.Entitys; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NewFans +{ + public class TaskJob + { + CancellationToken token; + ManualResetEvent resetEvent = null; + + public TaskJob() + { + token = tokenSource.Token; + resetEvent = new ManualResetEvent(true); + } + + private bool ISRUN1 = false; + + public void Run() + { + ThreadPool.RegisterWaitForSingleObject(new AutoResetEvent(true), new WaitOrTimerCallback((state, timedout) => + { + if (!Class1.Config.isRun) return; + if (ISRUN1) return; + ISRUN1 = true; + try + { + if (!string.IsNullOrWhiteSpace(Class1.Config.mess72)) + Send(InformMembers(Class1.Config.hour72, true), Class1.Config.hour72, Class1.Config.mess72); + if (!string.IsNullOrWhiteSpace(Class1.Config.mess48)) + Send(InformMembers(Class1.Config.hour48, true), Class1.Config.hour48, Class1.Config.mess48); + if (!string.IsNullOrWhiteSpace(Class1.Config.mess24)) + Send(InformMembers(Class1.Config.hour24, true), Class1.Config.hour24, Class1.Config.mess24); + if (!string.IsNullOrWhiteSpace(Class1.Config.mess3)) + Send(InformMembers(Class1.Config.hour3, false), Class1.Config.hour3, Class1.Config.mess3); + } + catch (Exception ex) + { } + finally + { + ISRUN1 = false; + } + }), null, 30000, false); + } + + private Random random = new Random(); + + /// + /// 给用户发消息 + /// + public void Send(List members, int interval, string mess) + { + try + { + if (members == null || members.Count == 0) + { } + else + { + var session = ApiClient.GetSession(); + foreach (var item in members) + { + try + { + if (token.IsCancellationRequested) + return; + // 初始化为true时执行WaitOne不阻塞 + resetEvent.WaitOne(); + + var wx = Chat.Framework.ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == item.robot_name && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wx == null) + continue; + + //var m = session.FindMemberInfoById(member); + + var friend = wx.GetContact(item.username); + if (friend == null) + continue; + wx.SendMessage(item.username, mess); + var hist = session.FindSingle("select * from fl_newfans_hist_ where uid = @uid", new { uid = item.id }); + if (hist == null) + hist = new fl_newfans_hist_() { uid = (int)item.id }; + hist.time = interval; + session.Saveable(hist).ExecuteCommand(); + Thread.Sleep(3000 + random.Next(500, 5000)); + } + catch (Exception ex) + { } + } + } + } + catch (Exception ex) + { } + } + + /// + /// 获取通知的用户集合,针对没有下单的用户 + /// + /// 时间间隔 + /// 是否查询过 + /// + public List InformMembers(double interval, bool isQuery) + { + try + { + var session = ApiClient.GetSession(); + List members = null; + members = session.Find("select * from fl_member_info where @begintime <= crt_time and crt_time <= @endtime and bind_order = 0", new { begintime = DateTime.Now.AddHours(-84), endtime = DateTime.Now.AddMinutes(-interval) }); + var records = session.Find("select * from fl_statistics_record", new { }); + var newfansHist = session.Find("select * from fl_newfans_hist_"); + + // 没有查询过的用户集合 + var not_query_member = new List(); + // 查询过的用户集合 + var query_member = new List(); + + if (isQuery) + { + foreach (var item in members) + { + var record = records.FirstOrDefault(o => o.uid == item.id); + if (record != null && record.querynum != 0) + { + var hist = newfansHist.FirstOrDefault(f => f.uid == item.id); + if (hist == null || (hist != null && hist.time < interval)) + query_member.Add(item); + } + } + return query_member; + } + else + { + foreach (var item in members) + { + var record = records.FirstOrDefault(o => o.uid == item.id); + if ((record != null && record.querynum == 0) || record == null) + { + var hist = newfansHist.FirstOrDefault(f => f.uid == item.id); + if ((hist != null && hist.time < interval) || hist == null) + not_query_member.Add(item); + } + } + return not_query_member; + } + } + catch (Exception ex) + { } + return null; + } + + public static CancellationTokenSource tokenSource = new CancellationTokenSource(); + + public void Abort() + { + try + { + tokenSource.Cancel(); + } + catch (Exception ex) + { } + } + + } +} diff --git a/应用/PDDGroupAD/Class1.cs b/应用/PDDGroupAD/Class1.cs new file mode 100644 index 0000000..75d4dce --- /dev/null +++ b/应用/PDDGroupAD/Class1.cs @@ -0,0 +1,78 @@ + +using Api.Framework; +using Api.Framework.SDK; +using PDDGroupAD.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PDDGroupAD +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.拼多多发单; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + /// + /// 重写显示设置窗口 + /// + public override void ShowForm() + { + //创建窗体并打开 + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + + public override void Start() + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + //if (!session.TableExist()) session.CreateTable(); + //if (!session.TableExist()) + //{ + // session.CreateTable(); + // session.AddIndex("robot_id"); + //} + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + //TimerTask.NewTimer(60); //创建线程 - 发送群的线程 60秒 + } + + public override void Stop() + { + try + { + //TimerTask.Close(); //关闭线程 + //关闭窗体 + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/PDDGroupAD/Config.cs b/应用/PDDGroupAD/Config.cs new file mode 100644 index 0000000..a266a37 --- /dev/null +++ b/应用/PDDGroupAD/Config.cs @@ -0,0 +1,64 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace PDDGroupAD +{ + [Config(Name = "插件-拼多多群推广-配置")] + public class Config + { + #region 群发设置 删除 + /// + /// 群发送间隔 + /// + //[ + // Category("1)、发单功能"), DisplayName("01.群消息发送间隔"), DefaultValue(5), + // Description(@"每个群之间发送间隔时间。单位:秒"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + //] + //public int SendIntervalGroup { get; set; } + + /// + /// 产品发送间隔 + /// + [ + Category("1)、发单功能"), DisplayName("01.产品发送间隔"), DefaultValue(5), + Description(@"产品之间发送间隔时间。单位:秒"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public int SendIntervalProduct { get; set; } + + /// + /// 指定在评论内追加内容 + /// + [ + Category("1)、发单功能"), DisplayName("02.评论内追加内容"), DefaultValue(@""), + Description(@"在指定评论内追加内容"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AppendContent { get; set; } + + /// + /// 黑名单列表 + /// + [ + Category("1)、发单功能"), DisplayName("03.黑名单列表"), + Description(@"不转发的群ID,群号之间用 , 分隔.可不填写"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string BlackList { get; set; } + + #endregion + + public Config() + { + this.SendIntervalProduct = 5; + } + + } +} diff --git a/应用/PDDGroupAD/MainForm.Designer.cs b/应用/PDDGroupAD/MainForm.Designer.cs new file mode 100644 index 0000000..82bca90 --- /dev/null +++ b/应用/PDDGroupAD/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace PDDGroupAD +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(462, 377); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.ResumeLayout(false); + + } + + #endregion + } +} \ No newline at end of file diff --git a/应用/PDDGroupAD/MainForm.cs b/应用/PDDGroupAD/MainForm.cs new file mode 100644 index 0000000..5035bf0 --- /dev/null +++ b/应用/PDDGroupAD/MainForm.cs @@ -0,0 +1,56 @@ +using PDDGroupAD.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace PDDGroupAD +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + + + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} diff --git a/应用/PDDGroupAD/MainForm.resx b/应用/PDDGroupAD/MainForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/PDDGroupAD/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/PDDGroupAD/PDDGroupAD.csproj b/应用/PDDGroupAD/PDDGroupAD.csproj new file mode 100644 index 0000000..6d95de4 --- /dev/null +++ b/应用/PDDGroupAD/PDDGroupAD.csproj @@ -0,0 +1,122 @@ + + + + + Debug + AnyCPU + {869EFBE4-FAF6-45AC-8B94-3D83633340CD} + Library + Properties + PDDGroupAD + PDDGroupAD + v4.6.1 + 512 + true + + + true + full + false + ..\..\主应用程序\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\返利机器人\Debug\Api.Framework.dll + False + + + ..\..\返利机器人\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\主应用程序\Assembly\apifile\Easy4net.dll + False + + + ..\..\主应用程序\Assembly\apifile\HttpHelper.dll + False + + + + + + + + + + + + + ..\..\主应用程序\Assembly\apifile\UI.Framework.dll + False + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + MainForm.cs + Designer + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + + + + + + \ No newline at end of file diff --git a/应用/PDDGroupAD/Properties/AssemblyInfo.cs b/应用/PDDGroupAD/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..67dfc3c --- /dev/null +++ b/应用/PDDGroupAD/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("PDDGroupAD")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PDDGroupAD")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("869efbe4-faf6-45ac-8b94-3d83633340cd")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/PDDGroupAD/Properties/Resources.Designer.cs b/应用/PDDGroupAD/Properties/Resources.Designer.cs new file mode 100644 index 0000000..fc26691 --- /dev/null +++ b/应用/PDDGroupAD/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace PDDGroupAD.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PDDGroupAD.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 拼多多发单 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 拼多多发单 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 拼多多发单插件,产品群推送 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 拼多多发单 { + get { + object obj = ResourceManager.GetObject("拼多多发单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/PDDGroupAD/Properties/Resources.resx b/应用/PDDGroupAD/Properties/Resources.resx new file mode 100644 index 0000000..c18114b --- /dev/null +++ b/应用/PDDGroupAD/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 拼多多发单 + 设置主窗体标题 + + + 拼多多发单 + 插件名 + + + 拼多多发单插件,产品群推送 + 插件介绍 + + + + ..\Resources\拼多多发单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/PDDGroupAD/Properties/licenses.licx b/应用/PDDGroupAD/Properties/licenses.licx new file mode 100644 index 0000000..e69de29 diff --git a/应用/PDDGroupAD/Resources/拼多多发单.png b/应用/PDDGroupAD/Resources/拼多多发单.png new file mode 100644 index 0000000..bef3376 Binary files /dev/null and b/应用/PDDGroupAD/Resources/拼多多发单.png differ diff --git a/应用/PDDRebate/Class1 - 复制(3).cs b/应用/PDDRebate/Class1 - 复制(3).cs new file mode 100644 index 0000000..651c42c --- /dev/null +++ b/应用/PDDRebate/Class1 - 复制(3).cs @@ -0,0 +1,992 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using PDDRebate.Entitys; +using PDDRebate.Properties; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Api.Framework.Model; +using Api.Framework.Enums; +using CsharpHttpHelper; +using System.Threading; +using Api.Framework.Cps; +using Api.Framework.Events; +using Api.Framework.Timers; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; + +namespace PDDRebate +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.拼多多; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + + if (session.TableExist()) + { + + var pddtgws = session.Find("select * from fl_plugin_pddrebate_pddtgw").ToList(); + if (pddtgws != null) + { + foreach (var item in pddtgws) + { + //插入主推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_chief_name, //推广位名称 + adzone_pid = item.pid_chief, //推广位pid + adzone_pid_cps_name = item.pid_chief_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "chief" + }).ExecuteCommand(); + //插入副推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_deputy_name, //推广位名称 + adzone_pid = item.pid_deputy, //推广位pid + adzone_pid_cps_name = item.pid_deputy_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "deputy" + }).ExecuteCommand(); + } + } + session.DropTable(); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// + /// 订单通知 + /// + /// + /// + private void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.Member != null && e.ChatType == CpsType.多多进宝) + { + //this.OnLog("拼多多订单:" + HttpHelper.ObjectToJson(e)); + + var session = ApiClient.GetSession(); + var order_pdd = e.Order as fl_order_pinduoduo; + if (order_pdd == null) return; + var robot_info = session.FindRobotInfo(e.Member.robot_name, e.Member.robot_type); + + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject(order_pdd.db_point) as ItemPoint; + + #region 下单用户订单检测(防撸) + if (e.Customer == null) + { + var prevent_theft_cache = session.FindSingle("select * from fl_prevent_theft_cache where order_id = @order_id", new { order_id = order_pdd.order_sn });//防止上级多次触发 + if (prevent_theft_cache == null) + { + var isHint = false; + if (!string.IsNullOrWhiteSpace(order_pdd.mall_id) && e.Member.status != MemberType.白名单) + { + #region 同一店铺多次购买(同一商品) + if (Class1.Config.AShop_SameCommodity_Switch) + { + var frequency = session.Find("select * from fl_order_pinduoduo where db_userid = @db_userid and goods_id = @goods_id", new { db_userid = order_pdd.db_userid, goods_id = order_pdd.goods_id }).Count; + if (Class1.Config.AShop_SameCommodity_Number <= frequency) + { + if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_pdd, e.Member, point), order_pdd.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户购买同一商品{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_SameCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_pdd.goods_id; + prevent_theft_cache.mall_id = order_pdd.mall_id; + prevent_theft_cache.order_id = order_pdd.order_sn; + prevent_theft_cache.cps_type = CpsType.多多进宝; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_SameCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户购买同一商品{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + + #region 同一店铺多次购买(不同商品) + if (!isHint && Class1.Config.AShop_DifferentCommodity_Switch) + { + var frequency = session.Find("select * from fl_order_pinduoduo where db_userid = @db_userid and mall_id = @mall_id", new { db_userid = order_pdd.db_userid, mall_id = order_pdd.mall_id }).Count; + if (Class1.Config.AShop_DifferentCommodity_Number <= frequency) + { + if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_pdd, e.Member, point), order_pdd.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_DifferentCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_pdd.goods_id; + prevent_theft_cache.mall_id = order_pdd.mall_id; + prevent_theft_cache.order_id = order_pdd.order_sn; + prevent_theft_cache.cps_type = CpsType.多多进宝; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_DifferentCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + } + + #region 收货时间验证时长 + if (!isHint && Class1.Config.ReceivingTimeCheck_Switch && order_pdd.order_status == 2 && e.Member.status != MemberType.白名单) + { + if (DateTime.Now != DateTime.MinValue) + { + var timeLag = (int)Math.Floor((DateTime.Now - order_pdd.order_create_time).TotalHours); + if (timeLag <= Class1.Config.ReceivingTimeCheck_Hour) + { + if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_pdd, e.Member, point), order_pdd.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.ReceivingTimeCheck_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_pdd.goods_id; + prevent_theft_cache.mall_id = order_pdd.mall_id; + prevent_theft_cache.order_id = order_pdd.order_sn; + prevent_theft_cache.cps_type = CpsType.多多进宝; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.ReceivingTimeCheck_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信 */); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + } + } + } + } + #endregion + } + } + #endregion + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + mess = _GetOrderStateMess(order_pdd.db_status, order_pdd, e.Member, point); + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order_pdd.msg_groupid); + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order_pdd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_OneLevelTip; + if (order_pdd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_pdd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_TwoLevelTip; + if (order_pdd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_pdd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_ThreeLevelTip; + if (order_pdd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_pdd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_LeaderTip; + if (order_pdd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order_pdd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order_pdd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + { + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_pdd, e.Member, point).Replace("[下级昵称]", string.IsNullOrWhiteSpace(e.Customer.realnick) ? e.Customer.usernick : e.Customer.realnick)); + } + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + //过滤表情xml + if (e.Message.Contains(@"("select * from fl_order_pinduoduo where order_sn = @order_sn", new { order_sn = orderid }); + if (order != null) + { + if (order.db_userid != 0 && order.db_userid != _member.id) + { + e.SendMessage(Config.OccupyOrderErrorTip.Replace("[订单号]", orderid)); + return; + } + + var notices = new List(); + var downPinduoduoTimer = new DownPinduoduoTimer(); + + if (order.db_userid != 0) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + _member = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Config.OrderRepetBindTip, order, _member, point)); + else + e.SendMessage(_GetOrderStateMess(order.db_status, order, _member, point)); + } + else + { + if (order.order_create_time < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderid},已经过了有效绑定时间!"); + return; + } + + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + //用户绑定订单 + order.db_robotname = e.RobotName; + order.db_robottype = e.ChatType; + order.msg_groupid = e.Groupid; + order.db_userid = _member.id; + session.SaveOrUpdate(order); + + if (_member != null) + { + _member.bind_order++; + _member = session.UpdateMemberGroup(_member); + } + + #region 首次付款时间 + var record = session.FindStatisticsRecord(_member.id); + if (record == null) + { + record = new fl_statistics_record() { uid = _member.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + #endregion + + downPinduoduoTimer.UpdateOrder(order, session, notices, isFrontData: true); + } + + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.IsRewards) + tasks.Add(item); + else + SDK_OrderNoticeEvent(this, item); + } + } + #endregion + + e.Cancel = true; + } + else + { + if (i < 1) + { + CpsClient.UpdateOrder(CpsType.多多进宝, DateTime.Now.AddMinutes(-30), DateTime.Now, orderid); + i++; + goto Next; + } + e.SendMessage(Config.NotFoundOrderErrorTip.Replace("[订单号]", orderid)); + e.Cancel = true; + return; + } + + } + + if (OrderHelper.IsOrderId(e.Message.Trim())) + return; + #endregion + + #region 拼多多链接解析 + + #region 拼多多解析商品图片 + string QRCodeUrl = string.Empty; + if (Config.QRCodeSearchSwitch == SwitchType.开启) + { + var reg_ = Regex.Match(e.Message, @"\[图片=(?<二维码图片>.+?)\]"); + if (reg_.Success) + QRCodeUrl = Util.DecodeQRCode(reg_.Groups["二维码图片"].Value);//解析的二维码图片所得到的二维码内容 + } + #endregion + + //判断消息中是否包含拼多多链接信息 + var goods_id = PDDHelper.GetPddGoodsID(string.IsNullOrEmpty(QRCodeUrl) ? e.Message.Trim() : QRCodeUrl); + if (!string.IsNullOrEmpty(goods_id)) + { + //this.OnLog($"拼多多编码 = {goods_id}"); + #region 限制商品ID + if (Class1.Config.ItemIDRestrictList.Contains(goods_id)) + { + e.SendMessage(Config.ItemIDRestrictTip.Replace("[商品ID]", goods_id)); + return; + } + #endregion + + var session = ApiClient.GetSession(); + var pddInfoTempGroups = session.FindPddInfoTempGroups();//获取pdd数据数据集合缓存 + var pddInfoTemp = pddInfoTempGroups.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (pddInfoTemp != null) + { + var member = session.FindMemberinfo(e);//获取用户信息 + + fl_cps_member pdd_cps = null; + var pid = string.Empty;//使用的pid + var isDefault = true; + + if (!string.IsNullOrWhiteSpace(e.Groupid))//群pid + { + var groupAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + pid = groupAdzone.adzone_pid; + pdd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == groupAdzone.adzone_pid_cps_name); + isDefault = false; + } + } + + if (isDefault)//私人pid + { + var memberAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == member.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + pid = memberAdzone.adzone_pid; + pdd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == memberAdzone.adzone_pid_cps_name); + isDefault = false; + } + } + + if (isDefault)//默认推广位 + { + pdd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? pddInfoTemp.pid_chief_cps_name : pddInfoTemp.pid_deputy_cps_name));//通过判断用户的购物积分,来判断用户使用哪个推广位 + pid = ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? pddInfoTemp.pid_chief : pddInfoTemp.pid_deputy); + } + + if (pdd_cps == null) throw new Exception("拼多多推广位设置异常,请检测后重试!"); + else + { + var isBind = true; + //正在搜索提示 + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + { + e.SendMessage(Config.SearchingTip); + Thread.Sleep(500); + } + + var api = CpsClient.CreatePinduoduoRequest(pdd_cps); + + + ArrayList goods_details = null; + var _temp_param = $"r={e.RobotName} t={(int)e.ChatType} u={e.Username}"; + //000000000000000000000000000000000000000000000000000000000000000000000 + try + { + ////var result = api.SendPinduoduo("pdd.ddk.oauth.member.authority.query", new { custom_parameters = _temp_param, pid = pid }); + //var result = api.SendPinduoduo("pdd.ddk.oauth.member.authority.query", new { pid = pid, custom_parameters = _temp_param }); + ////var result = api.SendPinduoduo("pdd.ddk.oauth.member.authority.query", new { pid = pid }); + //if (result.ContainsKey("authority_query_response")) + //{ + // var authority_query_response = result["authority_query_response"] as Dictionary; + // if (authority_query_response != null && authority_query_response.Count != 0) + // isBind = int.Parse(authority_query_response["bind"].ToString()) == 1;//1-已绑定;0-未绑定 + //} + + //if (!isBind) + //{ + //var data = new { p_id_list = "[\"" + pid + "\"]", channel_type = 10 }; + //var create_user_authority = api.SendPinduoduo("pdd.ddk.oauth.rp.prom.url.generate", data); + //} + + ////公用的账号 + //var guideCps = CpsClient.GuideMembers.FirstOrDefault(); + //var guideApi = CpsClient.CreatePinduoduoRequest(guideCps); + + //var data1 = new { p_id_list = "[\"" + guideCps.cookies + "\"]", channel_type = 10 }; + //var create_user_authority1 = guideApi.SendPinduoduo("pdd.ddk.oauth.rp.prom.url.generate", data1); + + //var obj_ = guideApi.SendPinduoduo("pdd.ddk.goods.search", new { keyword = $"{goods_id}", pid = guideCps.cookies }); + ////var obj_ = api.SendPinduoduo("pdd.ddk.oauth.goods.search", new { keyword = $"https://mobile.yangkeduo.com/goods2.html?goods_id={goods_id}" }); + + + + //if (obj_ == null) throw new Exception("创建拼多多API请求失败"); + ////解析商品,获取商品的信息 + //var goods_detail_response = obj_["goods_search_response"] as Dictionary; + //goods_details = goods_detail_response["goods_list"] as ArrayList; + + goods_details = PDDHelper.FindSendGuideGoodsInfo(api, pid, goods_id); + } + catch (Exception ex) + { + throw new Exception("公共异常:" + ex.Message + " - " + ex.StackTrace); + } + + //没有查到返利提示 + if (goods_details == null || goods_details.Count == 0) + throw new Exception("商品不存在"); + + foreach (var item in goods_details) + { + var temp = item as Dictionary; + + string mall_id = string.Empty; + if (temp.ContainsKey("mall_id")) + { + mall_id = temp["mall_id"].ToString(); + if (Config.SellerIDRestrictlist.Contains(mall_id)) + { + e.SendMessage(Config.SellerIDRestrictTip.Replace("[店铺ID]", mall_id)); + return; + } + } + + var goods_sign = temp["goods_sign"].ToString(); + + var goods_name = (temp["goods_name"] ?? string.Empty).ToString().Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); //获取商品标签 + var goods_desc = string.Empty; + if (temp.ContainsKey("goods_desc")) + goods_desc = (temp["goods_desc"] ?? string.Empty).ToString(); //商品描述 + var goods_thumbnail_url = string.Empty; //商品主图 + if (temp.ContainsKey("goods_thumbnail_url")) + goods_thumbnail_url = (temp["goods_thumbnail_url"] ?? string.Empty).ToString(); + else if (temp.ContainsKey("goods_image_url")) + goods_thumbnail_url = (temp["goods_image_url"] ?? string.Empty).ToString(); + + var sales_tip = "0";//已售卖件数 + if (temp.ContainsKey("sales_tip")) + sales_tip = (temp["sales_tip"] ?? string.Empty).ToString(); + + double min_group_price = 0d; + if (temp.ContainsKey("min_group_price")) + min_group_price = Math.Round(temp["min_group_price"] == null ? 0 : (double.Parse(temp["min_group_price"].ToString()) / 100.00), 2); //最低价sku的拼团价,单位为分 + double min_normal_price = 0d; + if (temp.ContainsKey("min_normal_price")) + min_normal_price = Math.Round(temp["min_normal_price"] == null ? 0 : (double.Parse(temp["min_normal_price"].ToString()) / 100.00), 2); //最低价sku的单买价,单位为分 + var mall_name = string.Empty; + if (temp.ContainsKey("mall_name")) + mall_name = (temp["mall_name"] ?? string.Empty).ToString(); //店铺名称 + double _coupon_min_order_amount = 0d; + if (temp.ContainsKey("coupon_min_order_amount")) + _coupon_min_order_amount = temp["coupon_min_order_amount"] == null ? 0 : double.Parse(temp["coupon_min_order_amount"].ToString()); + + var coupon_min_order_amount = _coupon_min_order_amount == 0 ? 0 : (_coupon_min_order_amount / 100); //优惠券门槛金额,单位为分 + double _coupon_discount = 0d; + if (temp.ContainsKey("coupon_discount")) + _coupon_discount = double.Parse((temp["coupon_discount"] ?? 0).ToString()); + var coupon_discount = _coupon_discount == 0 ? 0 : Math.Round(_coupon_discount / 100.00, 2); //优惠券面额,单位为分 + + var coupon_total_quantity = string.Empty; + if (temp.ContainsKey("coupon_total_quantity")) + coupon_total_quantity = (temp["coupon_total_quantity"] ?? "0").ToString(); //优惠券总数量 + + var coupon_start_time = DateTime.MinValue; + if (temp.ContainsKey("coupon_start_time")) + { + var _coupon_start_time = temp["coupon_start_time"]; + coupon_start_time = _coupon_start_time == null ? new DateTime() : TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddSeconds(double.Parse(_coupon_start_time.ToString())); //优惠券生效时间,UNIX时间戳 + } + + var coupon_end_time = DateTime.MinValue; + if (temp.ContainsKey("coupon_end_time")) + { + var _coupon_end_time = temp["coupon_end_time"]; + coupon_end_time = _coupon_end_time == null ? new DateTime() : TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddSeconds(double.Parse(_coupon_end_time.ToString())); //优惠券失效时间,UNIX时间戳 + } + + double promotion_rate = 0d;//佣金比例,千分比 + if (temp.ContainsKey("promotion_rate") && temp["promotion_rate"] != null) + promotion_rate = double.Parse(temp["promotion_rate"].ToString()) / 1000.00; + promotion_rate = Math.Round(promotion_rate, 3); + + //this.OnLog($@"goods_name = {goods_name}, mall_id = {mall_id}, promotion_rate = {promotion_rate}"); + + var groupCommisson = (min_group_price - coupon_discount) * promotion_rate; + var commission = session.GetPddComparisonFeeRate(groupCommisson); + var group = session.FindItemPoint(member, commission, 1, CpsType.多多进宝); //客户团购的佣金 + + var normalCommisson = (min_normal_price - coupon_discount) * promotion_rate; + commission = session.GetPddComparisonFeeRate(normalCommisson); + var normal = session.FindItemPoint(member, commission, 1, CpsType.多多进宝); //客户单买的佣金 + + var pdd_api = new PDDHelper(); + //string _temp_param = $"robot={e.RobotName} type={(int)e.ChatType} user={e.Username} mallid={mall_id}"; + //string _temp_param = $"robot={e.RobotName} type={(int)e.ChatType} user={e.Username} mallid="; + //搜索成功有券的情况下 + if (_coupon_discount != 0) + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithCouponTip))) + mess = Config.SearchSuccessWithCouponTip; + else + mess = Config.QQSearchSuccessWithCouponTip; + mess = new VariateReplace().CommonReplace(mess, _member); + //var oneShoppingUrl = string.Empty; + //var manyShoppingUrl = string.Empty; + Dictionary oneShoppingUrlDic = null; + Dictionary manyShoppingUrlDic = null; + if (mess.Contains("[单买地址")) + { + //oneShoppingUrl = pdd_api.GetShoppingUrl(api, new { p_id = pid, custom_parameters = _temp_param, goods_id_list = $"[{goods_id}]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + oneShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = pid, custom_parameters = _temp_param, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + } + if (mess.Contains("[拼团地址") || mess.Contains("[商品图片]")) + { + //manyShoppingUrl = pdd_api.GetShoppingUrl(api, new { p_id = pid, custom_parameters = _temp_param, goods_id_list = $"[{goods_id}]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + manyShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = pid, custom_parameters = _temp_param, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + } + + e.SendMessage(mess + .Replace("[商品标题]", goods_name) + .Replace("[商品描述]", goods_desc) + .Replace("[商品主图]", $"[图片={goods_thumbnail_url}]") + .Replace("[图片地址]", goods_thumbnail_url) + .Replace("[已售数量]", sales_tip) + .Replace("[店铺名称]", mall_name) + .Replace("[优惠券门槛金额]", coupon_min_order_amount.ToString()) + .Replace("[优惠券金额]", coupon_discount.ToString()) + .Replace("[优惠券数量]", coupon_total_quantity) + .Replace("[优惠券生效日]", coupon_start_time.ToString("yyyy-MM-dd HH:mm:ss")) + .Replace("[优惠券失效日]", coupon_end_time.ToString("yyyy-MM-dd HH:mm:ss")) + .Replace("[商品单买价]", min_normal_price.ToString()) + .Replace("[单买返利]", (normal.UserPoint == 0 ? 0.01 : normal.UserPoint).ToString()) + .Replace("[券后单买价]", ((decimal)min_normal_price - (decimal)coupon_discount).ToString()) + .Replace("[劵后单买价]", ((decimal)min_normal_price - (decimal)coupon_discount).ToString()) + .Replace("[单买地址跳转]", "[单买地址]") + .Replace("[单买地址]", oneShoppingUrlDic == null ? string.Empty : oneShoppingUrlDic["mobile_short_url"].ToString()) + .Replace("[单买地址不跳转]", oneShoppingUrlDic == null ? string.Empty : oneShoppingUrlDic["short_url"].ToString()) + .Replace("[商品拼团价]", min_group_price.ToString()) + .Replace("[拼团返利]", (group.UserPoint == 0 ? 0.01 : group.UserPoint).ToString()) + .Replace("[券后拼团价]", ((decimal)min_group_price - (decimal)coupon_discount).ToString()) + .Replace("[劵后拼团价]", ((decimal)min_group_price - (decimal)coupon_discount).ToString()) + .Replace("[拼团地址跳转]", "[拼团地址]") + .Replace("[拼团地址]", manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["mobile_short_url"].ToString()) + .Replace("[拼团地址不跳转]", manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["short_url"].ToString()) + .Replace("[单买共节省]", "[共节省]") + .Replace("[共节省]", ((decimal)coupon_discount + (decimal)(normal.UserPoint == 0 ? 0.01 : normal.UserPoint)).ToString()) + .Replace("[拼团共节省]", ((decimal)coupon_discount + (decimal)(group.UserPoint == 0 ? 0.01 : group.UserPoint)).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goods_name, min_normal_price.ToString(), coupon_discount.ToString(), ((decimal)min_normal_price - (decimal)coupon_discount).ToString(), goods_thumbnail_url, manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["mobile_short_url"].ToString(), ApiClient.QrImageType.模板B, CpsType.多多进宝) + "]" : string.Empty)); + } + //搜索成功没有券的情况下 + else + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithoutCouponTip))) + mess = Config.SearchSuccessWithoutCouponTip; + else + mess = Config.QQSearchSuccessWithoutCouponTip; + + //var oneShoppingUrl = string.Empty; + //var manyShoppingUrl = string.Empty; + Dictionary oneShoppingUrlDic = null; + Dictionary manyShoppingUrlDic = null; + if (mess.Contains("[拼团地址") || mess.Contains("[商品图片]")) + //manyShoppingUrl = pdd_api.GetShoppingUrl(api, new { p_id = pid, custom_parameters = _temp_param, goods_id_list = $"[{goods_id}]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = isBind, force_duo_id = true }); + manyShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = pid, custom_parameters = _temp_param, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + if (mess.Contains("[单买地址")) + //oneShoppingUrl = pdd_api.GetShoppingUrl(api, new { p_id = (member.buy_point <= Config.Point ? pddInfoTemp.pid_deputy : pddInfoTemp.pid_chief), custom_parameters = _temp_param, goods_id_list = $"[{goods_id}]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = isBind, force_duo_id = true }); + oneShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = (member.buy_point <= Config.Point ? pddInfoTemp.pid_deputy : pddInfoTemp.pid_chief), custom_parameters = _temp_param, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + + e.SendMessage(mess + .Replace("[商品标题]", goods_name) + .Replace("[商品描述]", goods_desc) + .Replace("[商品主图]", $"[图片={goods_thumbnail_url}]") + .Replace("[图片地址]", goods_thumbnail_url) + .Replace("[已售数量]", sales_tip) + .Replace("[店铺名称]", mall_name) + .Replace("[商品单买价]", min_normal_price.ToString()) + .Replace("[单买返利]", (normal.UserPoint == 0 ? 0.01 : normal.UserPoint).ToString()) + .Replace("[单买地址跳转]", "[单买地址]") + .Replace("[单买地址]", oneShoppingUrlDic == null ? string.Empty : oneShoppingUrlDic["mobile_short_url"].ToString()) + .Replace("[单买地址不跳转]", oneShoppingUrlDic == null ? string.Empty : oneShoppingUrlDic["short_url"].ToString()) + .Replace("[商品拼团价]", min_group_price.ToString()) + .Replace("[拼团返利]", (group.UserPoint == 0 ? 0.01 : group.UserPoint).ToString()) + .Replace("[拼团地址跳转]", "[拼团地址]") + .Replace("[拼团地址]", manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["mobile_short_url"].ToString()) + .Replace("[拼团地址不跳转]", manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["short_url"].ToString()) + .Replace("[单买共节省]", "[共节省]") + .Replace("[共节省]", (normal.UserPoint == 0 ? 0.01 : normal.UserPoint).ToString()) + .Replace("[拼团共节省]", (group.UserPoint == 0 ? 0.01 : group.UserPoint).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goods_name, min_normal_price.ToString(), coupon_discount.ToString(), ((decimal)min_normal_price - (decimal)coupon_discount).ToString(), goods_thumbnail_url, manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["short_url"].ToString(), ApiClient.QrImageType.模板B, CpsType.多多进宝) + "]" : string.Empty)); + } + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + session.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.多多进宝, + itemid = goods_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = _member.id, + title = goods_name, + adzoneid = pid, + mallid = mall_id + }).ExecuteCommand(); + session.UpdateRecord(_member.id); + + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["msg_username"] = _member.username; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + #endregion + } + } + } + } + #endregion + } + catch (Exception ex) + { + /* + * 返回异常时,提示查不到 + */ + if (ex.Message.Contains("商品不存在") || ex.Message.Contains("商品非多多进宝商品")) + { + e.SendMessage(Config.SearchErrorTip); + + var session = ApiClient.GetSession(); + session.UpdateRecord(e.GetMemberinfo().id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["msg_username"] = e.GetMemberinfo().username; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + } + else + { + this.OnLog("D:" + ex.Message); + e.SendMessage(ApiClient.Setting.SystemConfig.msg_error); + } + } + } + + #region 变量替换 + /// + /// 订单状态 提示语替换 + /// + /// + /// + /// + private string _GetOrderStateMess(SystemOrderStatus order, params object[] objs) + { + + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.全额退款: + case SystemOrderStatus.部分退款: + case SystemOrderStatus.订单维权中: + mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(Config.OrderSettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Config.OrderFreezeTip, objs); + break; + } + return mess; + } + #endregion + + } +} diff --git a/应用/PDDRebate/Class1.cs b/应用/PDDRebate/Class1.cs new file mode 100644 index 0000000..f6d3924 --- /dev/null +++ b/应用/PDDRebate/Class1.cs @@ -0,0 +1,1038 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using PDDRebate.Entitys; +using PDDRebate.Properties; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Api.Framework.Model; +using Api.Framework.Enums; +using CsharpHttpHelper; +using System.Threading; +using Api.Framework.Cps; +using Api.Framework.Events; +using Api.Framework.Timers; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using Chat.Framework.WXSdk; +using Newtonsoft.Json; + +namespace PDDRebate +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.拼多多; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + + if (session.TableExist()) + { + + var pddtgws = session.Find("select * from fl_plugin_pddrebate_pddtgw").ToList(); + if (pddtgws != null) + { + foreach (var item in pddtgws) + { + //插入主推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_chief_name, //推广位名称 + adzone_pid = item.pid_chief, //推广位pid + adzone_pid_cps_name = item.pid_chief_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "chief" + }).ExecuteCommand(); + //插入副推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_deputy_name, //推广位名称 + adzone_pid = item.pid_deputy, //推广位pid + adzone_pid_cps_name = item.pid_deputy_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "deputy" + }).ExecuteCommand(); + } + } + session.DropTable(); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// + /// 订单通知 + /// + /// + /// + private void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.ChatType == CpsType.多多进宝) + { + //this.OnLog("拼多多订单:" + HttpHelper.ObjectToJson(e)); + + var session = ApiClient.GetSession(); + var order_pdd = e.Order as fl_order_pinduoduo; + if (order_pdd == null) return; + + if (e.Member != null) + { + var robot_info = session.FindRobotInfo(e.Member.robot_name, e.Member.robot_type); + + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject(order_pdd.db_point) as ItemPoint; + + #region 下单用户订单检测(防撸) + if (e.Customer == null) + { + var prevent_theft_cache = session.FindSingle("select * from fl_prevent_theft_cache where order_id = @order_id", new { order_id = order_pdd.order_sn });//防止上级多次触发 + if (prevent_theft_cache == null) + { + var isHint = false; + if (!string.IsNullOrWhiteSpace(order_pdd.mall_id) && e.Member.status != MemberType.白名单) + { + #region 同一店铺多次购买(同一商品) + if (Class1.Config.AShop_SameCommodity_Switch) + { + var frequency = session.Find("select * from fl_order_pinduoduo where db_userid = @db_userid and goods_id = @goods_id", new { db_userid = order_pdd.db_userid, goods_id = order_pdd.goods_id }).Count; + if (Class1.Config.AShop_SameCommodity_Number <= frequency) + { + if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_pdd, e.Member, point), order_pdd.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户购买同一商品{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_SameCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_pdd.goods_id; + prevent_theft_cache.mall_id = order_pdd.mall_id; + prevent_theft_cache.order_id = order_pdd.order_sn; + prevent_theft_cache.cps_type = CpsType.多多进宝; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_SameCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户购买同一商品{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + + #region 同一店铺多次购买(不同商品) + if (!isHint && Class1.Config.AShop_DifferentCommodity_Switch) + { + var frequency = session.Find("select * from fl_order_pinduoduo where db_userid = @db_userid and mall_id = @mall_id", new { db_userid = order_pdd.db_userid, mall_id = order_pdd.mall_id }).Count; + if (Class1.Config.AShop_DifferentCommodity_Number <= frequency) + { + if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_pdd, e.Member, point), order_pdd.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_DifferentCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_pdd.goods_id; + prevent_theft_cache.mall_id = order_pdd.mall_id; + prevent_theft_cache.order_id = order_pdd.order_sn; + prevent_theft_cache.cps_type = CpsType.多多进宝; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_DifferentCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + } + + #region 收货时间验证时长 + if (!isHint && Class1.Config.ReceivingTimeCheck_Switch && order_pdd.order_status == 2 && e.Member.status != MemberType.白名单) + { + if (DateTime.Now != DateTime.MinValue) + { + var timeLag = (int)Math.Floor((DateTime.Now - order_pdd.order_create_time).TotalHours); + if (timeLag <= Class1.Config.ReceivingTimeCheck_Hour) + { + if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_pdd, e.Member, point), order_pdd.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.ReceivingTimeCheck_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_pdd.goods_id; + prevent_theft_cache.mall_id = order_pdd.mall_id; + prevent_theft_cache.order_id = order_pdd.order_sn; + prevent_theft_cache.cps_type = CpsType.多多进宝; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.ReceivingTimeCheck_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信 */); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + } + } + } + } + #endregion + } + } + #endregion + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + mess = _GetOrderStateMess(order_pdd.db_status, order_pdd, e.Member, point); + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order_pdd.msg_groupid); + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order_pdd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_OneLevelTip; + if (order_pdd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_pdd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_TwoLevelTip; + if (order_pdd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_pdd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_ThreeLevelTip; + if (order_pdd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order_pdd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_pdd.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_LeaderTip; + if (order_pdd.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order_pdd.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order_pdd.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + { + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_pdd, e.Member, point).Replace("[下级昵称]", e.Customer.realnick ?? "")); + } + } + } + else + { + #region 多人查询通知消息 + var querys = session.Find("select robot_name,type,userid from fl_query_hist where itemid=@itemid and adzoneid = @adzoneid and userid > 0 and crt_time>@time and is_multiple=@is_multiple group by userid,type,robot_name", new { itemid = order_pdd.goods_id, adzoneid = order_pdd.p_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss"), is_multiple = false }); + if (querys.Count > 0) + { + for (int i = 0; i < querys.Count; i++) + { + try + { + if (querys[i].type != CpsType.多多进宝) continue; + //未绑定的数量 + var unbound_count = int.Parse(session.FindTable($"select count(id) as num from fl_order_pinduoduo where order_sn = @order_sn and db_userid != 0", new { order_sn = order_pdd.order_sn }).Rows[0]["num"].ToString()); + if (unbound_count != 0) break;//已经被绑定直接停止 + + var queryhist_temp = querys[i]; + var userid = queryhist_temp.userid; + var robot_name = queryhist_temp.robot_name; + var robot_info = session.Find("select * from fl_robot_info where name = @name", new { name = robot_name }).FirstOrDefault();//机器人类型应该是没有的,直接通过机器人name查询机器人信息 + if (robot_info != null) + { + Thread.Sleep(5000); + var wxbase = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot_name); + if (wxbase != null && wxbase.Status == WxStatus.在线) + { + var member = session.FindMemberInfoById(userid); + if (member != null) + { + ApiClient.SendMessage(robot_info, member.username, Config.LotUserQueryBindTip.Replace("[商品标题]", order_pdd.goods_name)); + + //session.ExcuteSQL("update fl_query_hist set userid = @newuserid where itemid = @itemid and adzoneid = @adzoneid and robot_name = @robotname and userid = @userid", new { newuserid = (i - querys.Count + 1), itemid = order_pdd.goods_id, adzoneid = order_pdd.p_id, robotname = robot_name, userid = member.id }); + session.ExcuteSQL("update fl_query_hist set is_multiple = @is_multiple where itemid = @itemid and adzoneid = @adzoneid and robot_name = @robotname and userid = @userid", new { is_multiple = true, itemid = order_pdd.goods_id, adzoneid = order_pdd.p_id, robotname = robot_name, userid = member.id }); + } + } + } + } + catch (Exception) + { } + } + } + #endregion + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + Compute compute = null; + string goods_name = string.Empty; + try + { + //过滤表情xml + if (e.Message.Contains(@"("select * from fl_order_pinduoduo where order_sn = @order_sn", new { order_sn = orderid }); + if (order != null) + { + if (order.db_userid != 0 && order.db_userid != _member.id) + { + e.SendMessage(Config.OccupyOrderErrorTip.Replace("[订单号]", orderid)); + return; + } + + var notices = new List(); + var downPinduoduoTimer = new DownPinduoduoTimer(); + + if (order.db_userid != 0) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + _member = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Config.OrderRepetBindTip, order, _member, point)); + else + e.SendMessage(_GetOrderStateMess(order.db_status, order, _member, point)); + } + else + { + if (order.order_create_time < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderid},已经过了有效绑定时间!"); + return; + } + + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + //用户绑定订单 + order.db_robotname = e.RobotName; + order.db_robottype = e.ChatType; + order.msg_groupid = e.Groupid; + order.db_userid = _member.id; + session.SaveOrUpdate(order); + + if (_member != null) + { + _member.bind_order++; + _member = session.UpdateMemberGroup(_member); + } + + #region 首次付款时间 + var record = session.FindStatisticsRecord(_member.id); + if (record == null) + { + record = new fl_statistics_record() { uid = _member.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + #endregion + + downPinduoduoTimer.UpdateOrder(order, session, notices, isFrontData: true); + } + + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.IsRewards) + tasks.Add(item); + //else + //SDK_OrderNoticeEvent(this, item); + } + } + #endregion + + e.Cancel = true; + } + else + { + if (i < 1) + { + CpsClient.UpdateOrder(CpsType.多多进宝, DateTime.Now.AddMinutes(-30), DateTime.Now, orderid); + i++; + goto Next; + } + e.SendMessage(Config.NotFoundOrderErrorTip.Replace("[订单号]", orderid)); + e.Cancel = true; + return; + } + + } + + if (OrderHelper.IsOrderId(e.Message.Trim())) + return; + #endregion + + #region 拼多多链接解析 + + #region 拼多多解析商品图片 + string QRCodeUrl = string.Empty; + if (Config.QRCodeSearchSwitch == SwitchType.开启) + { + var reg_ = Regex.Match(e.Message, @"\[图片=(?<二维码图片>.+?)\]"); + if (reg_.Success) + QRCodeUrl = Util.DecodeQRCode(reg_.Groups["二维码图片"].Value, Util.DecodeQRCodeType.Caoliao);//解析的二维码图片所得到的二维码内容 + } + #endregion + + //判断消息中是否包含拼多多链接信息 + var goods_id = PDDHelper.GetPddGoodsID(string.IsNullOrEmpty(QRCodeUrl) ? e.Message.Trim() : QRCodeUrl); + if (!string.IsNullOrEmpty(goods_id)) + { + //this.OnLog($"拼多多编码 = {goods_id}"); + #region 限制商品ID + if (Class1.Config.ItemIDRestrictList.Contains(goods_id)) + { + e.SendMessage(Config.ItemIDRestrictTip.Replace("[商品ID]", goods_id)); + return; + } + #endregion + + var session = ApiClient.GetSession(); + var pddInfoTempGroups = session.FindPddInfoTempGroups();//获取pdd数据数据集合缓存 + var pddInfoTemp = pddInfoTempGroups.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (pddInfoTemp != null) + { + var member = session.FindMemberinfo(e);//获取用户信息 + + fl_cps_member pdd_cps = null; + var pid = string.Empty;//使用的pid + var isDefault = true; + + if (!string.IsNullOrWhiteSpace(e.Groupid))//群pid + { + var groupAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + pid = groupAdzone.adzone_pid; + pdd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == groupAdzone.adzone_pid_cps_name); + isDefault = false; + } + } + + if (isDefault)//私人pid + { + var memberAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == member.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + pid = memberAdzone.adzone_pid; + pdd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == memberAdzone.adzone_pid_cps_name); + isDefault = false; + } + } + + if (isDefault)//默认推广位 + { + pdd_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? pddInfoTemp.pid_chief_cps_name : pddInfoTemp.pid_deputy_cps_name));//通过判断用户的购物积分,来判断用户使用哪个推广位 + pid = ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? pddInfoTemp.pid_chief : pddInfoTemp.pid_deputy); + } + + if (pdd_cps == null) throw new Exception("拼多多推广位设置异常,请检测后重试!"); + + var isBind = true; + //正在搜索提示 + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + { + e.SendMessage(Config.SearchingTip); + Thread.Sleep(500); + } + + var api = CpsClient.CreatePinduoduoRequest(pdd_cps); + + + ArrayList goods_details = null; + //var _temp_param = $"r={e.RobotName} t={(int)e.ChatType} u={e.Username}"; + + try + { + //var result = api.SendPinduoduo("pdd.ddk.oauth.member.authority.query", new { custom_parameters = _temp_param, pid = pid }); + var result = api.SendPinduoduo("pdd.ddk.oauth.member.authority.query", new { pid = pid }); + if (result.ContainsKey("authority_query_response")) + { + var authority_query_response = result["authority_query_response"] as Dictionary; + if (authority_query_response != null && authority_query_response.Count != 0) + isBind = int.Parse(authority_query_response["bind"].ToString()) == 1;//1-已绑定;0-未绑定 + } + + //if (!isBind) + //{ + // var data = new { p_id_list = "[\"" + pid + "\"]", channel_type = 10 }; + // var create_user_authority = api.SendPinduoduo("pdd.ddk.oauth.rp.prom.url.generate", data); + //} + + goods_details = PDDHelper.FindSendGuideGoodsInfo(api, pid, goods_id, isBind); + } + catch (Exception ex) + { + throw new Exception("公共异常:" + ex.Message + " - " + ex.StackTrace + " - " + isBind); + } + + //没有查到返利提示 + if (goods_details == null || goods_details.Count == 0) + throw new Exception("商品不存在"); + + foreach (var item in goods_details) + { + var temp = item as Dictionary; + + string mall_id = string.Empty; + if (temp.ContainsKey("mall_id")) + { + mall_id = temp["mall_id"].ToString(); + if (Config.SellerIDRestrictlist.Contains(mall_id)) + { + e.SendMessage(Config.SellerIDRestrictTip.Replace("[店铺ID]", mall_id)); + return; + } + } + + var goods_sign = temp["goods_sign"].ToString(); + + goods_name = (temp["goods_name"] ?? string.Empty).ToString().Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); //获取商品标签 + var goods_desc = string.Empty; + if (temp.ContainsKey("goods_desc")) + goods_desc = (temp["goods_desc"] ?? string.Empty).ToString(); //商品描述 + var goods_thumbnail_url = string.Empty; //商品主图 + if (temp.ContainsKey("goods_thumbnail_url")) + goods_thumbnail_url = (temp["goods_thumbnail_url"] ?? string.Empty).ToString(); + else if (temp.ContainsKey("goods_image_url")) + goods_thumbnail_url = (temp["goods_image_url"] ?? string.Empty).ToString(); + + var sales_tip = "0";//已售卖件数 + if (temp.ContainsKey("sales_tip")) + sales_tip = (temp["sales_tip"] ?? string.Empty).ToString(); + + double min_group_price = 0d; + if (temp.ContainsKey("min_group_price")) + min_group_price = Math.Round(temp["min_group_price"] == null ? 0 : (double.Parse(temp["min_group_price"].ToString()) / 100.00), 2); //最低价sku的拼团价,单位为分 + double min_normal_price = 0d; + if (temp.ContainsKey("min_normal_price")) + min_normal_price = Math.Round(temp["min_normal_price"] == null ? 0 : (double.Parse(temp["min_normal_price"].ToString()) / 100.00), 2); //最低价sku的单买价,单位为分 + var mall_name = string.Empty; + if (temp.ContainsKey("mall_name")) + mall_name = (temp["mall_name"] ?? string.Empty).ToString(); //店铺名称 + double _coupon_min_order_amount = 0d; + if (temp.ContainsKey("coupon_min_order_amount")) + _coupon_min_order_amount = temp["coupon_min_order_amount"] == null ? 0 : double.Parse(temp["coupon_min_order_amount"].ToString()); + + var coupon_min_order_amount = _coupon_min_order_amount == 0 ? 0 : (_coupon_min_order_amount / 100); //优惠券门槛金额,单位为分 + double _coupon_discount = 0d; + if (temp.ContainsKey("coupon_discount")) + _coupon_discount = double.Parse((temp["coupon_discount"] ?? 0).ToString()); + var coupon_discount = _coupon_discount == 0 ? 0 : Math.Round(_coupon_discount / 100.00, 2); //优惠券面额,单位为分 + + var coupon_total_quantity = string.Empty; + if (temp.ContainsKey("coupon_total_quantity")) + coupon_total_quantity = (temp["coupon_total_quantity"] ?? "0").ToString(); //优惠券总数量 + + var coupon_start_time = DateTime.MinValue; + if (temp.ContainsKey("coupon_start_time")) + { + var _coupon_start_time = temp["coupon_start_time"]; + coupon_start_time = _coupon_start_time == null ? new DateTime() : TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddSeconds(double.Parse(_coupon_start_time.ToString())); //优惠券生效时间,UNIX时间戳 + } + + var coupon_end_time = DateTime.MinValue; + if (temp.ContainsKey("coupon_end_time")) + { + var _coupon_end_time = temp["coupon_end_time"]; + coupon_end_time = _coupon_end_time == null ? new DateTime() : TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddSeconds(double.Parse(_coupon_end_time.ToString())); //优惠券失效时间,UNIX时间戳 + } + + double promotion_rate = 0d;//佣金比例,千分比 + if (temp.ContainsKey("promotion_rate") && temp["promotion_rate"] != null) + promotion_rate = double.Parse(temp["promotion_rate"].ToString()) / 1000.00; + promotion_rate = Math.Round(promotion_rate, 3); + + //this.OnLog($@"goods_name = {goods_name}, mall_id = {mall_id}, promotion_rate = {promotion_rate}"); + + + + var groupCommisson = (min_group_price - coupon_discount) * promotion_rate; + var commission = session.GetPddComparisonFeeRate(groupCommisson); + var group = session.FindItemPoint(member, commission, 1, CpsType.多多进宝, out compute); //客户团购的佣金 + + Compute compute1 = null; + var normalCommisson = (min_normal_price - coupon_discount) * promotion_rate; + commission = session.GetPddComparisonFeeRate(normalCommisson); + var normal = session.FindItemPoint(member, commission, 1, CpsType.多多进宝, out compute1); //客户单买的佣金 + + if (compute == null) + compute = compute1; + + var pdd_api = new PDDHelper(); + //搜索成功有券的情况下 + if (_coupon_discount != 0) + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithCouponTip))) + mess = Config.SearchSuccessWithCouponTip; + else + mess = Config.QQSearchSuccessWithCouponTip; + mess = new VariateReplace().CommonReplace(mess, _member); + + Dictionary oneShoppingUrlDic = null; + Dictionary manyShoppingUrlDic = null; + if (mess.Contains("[单买地址")) + { + //oneShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = pid, custom_parameters = _temp_param, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + oneShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = pid, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = false, generate_short_url = true, /*custom_parameters = "{\"uid\":\"602172712\",\"sid\":\"jdds\"}",*/generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true, generate_schema_url = true }); + } + if (mess.Contains("[拼团地址") || mess.Contains("[商品图片]")) + { + //manyShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = pid, custom_parameters = _temp_param, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + manyShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = pid, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true, generate_schema_url = true }); + } + + e.SendMessage(mess + .Replace("劵", "券") + .Replace("[商品标题]", goods_name) + .Replace("[商品描述]", goods_desc) + .Replace("[商品主图]", $"[图片={goods_thumbnail_url}]") + .Replace("[图片地址]", goods_thumbnail_url) + .Replace("[已售数量]", sales_tip) + .Replace("[店铺名称]", mall_name) + .Replace("[优惠券门槛金额]", coupon_min_order_amount.ToString()) + .Replace("[优惠券金额]", string.Format("{0:F}", coupon_discount)) + .Replace("[优惠券数量]", coupon_total_quantity) + .Replace("[优惠券生效日]", coupon_start_time.ToString("yyyy-MM-dd HH:mm:ss")) + .Replace("[优惠券失效日]", coupon_end_time.ToString("yyyy-MM-dd HH:mm:ss")) + .Replace("[商品单买价]", string.Format("{0:F}", min_normal_price)) + .Replace("[单买返利]", (normal.UserPoint == 0 ? 0.01 : normal.UserPoint).ToString()) + .Replace("[券后单买价]", ((decimal)min_normal_price - (decimal)coupon_discount).ToString()) + .Replace("[单买地址跳转]", "[单买地址]") + .Replace("[单买地址]", oneShoppingUrlDic == null ? string.Empty : oneShoppingUrlDic["mobile_short_url"].ToString()) + .Replace("[单买地址不跳转]", oneShoppingUrlDic == null ? string.Empty : oneShoppingUrlDic["short_url"].ToString()) + .Replace("[商品拼团价]", string.Format("{0:F}", min_group_price)) + .Replace("[拼团返利]", (group.UserPoint == 0 ? 0.01 : group.UserPoint).ToString()) + .Replace("[券后拼团价]", ((decimal)min_group_price - (decimal)coupon_discount).ToString()) + .Replace("[拼团地址跳转]", "[拼团地址]") + .Replace("[拼团地址]", manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["mobile_short_url"].ToString()) + .Replace("[拼团地址不跳转]", manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["short_url"].ToString()) + .Replace("[单买共节省]", "[共节省]") + .Replace("[共节省]", ((decimal)coupon_discount + (decimal)(normal.UserPoint == 0 ? 0.01 : normal.UserPoint)).ToString()) + .Replace("[拼团共节省]", ((decimal)coupon_discount + (decimal)(group.UserPoint == 0 ? 0.01 : group.UserPoint)).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goods_name, min_normal_price.ToString(), coupon_discount.ToString(), ((decimal)min_normal_price - (decimal)coupon_discount).ToString(), goods_thumbnail_url, manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["mobile_short_url"].ToString(), ApiClient.QrImageType.模板B, CpsType.多多进宝) + "]" : string.Empty)); + } + //搜索成功没有券的情况下 + else + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithoutCouponTip))) + mess = Config.SearchSuccessWithoutCouponTip; + else + mess = Config.QQSearchSuccessWithoutCouponTip; + + //var oneShoppingUrl = string.Empty; + //var manyShoppingUrl = string.Empty; + Dictionary oneShoppingUrlDic = null; + Dictionary manyShoppingUrlDic = null; + if (mess.Contains("[拼团地址") || mess.Contains("[商品图片]")) + manyShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = pid, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true, generate_schema_url = true }); + if (mess.Contains("[单买地址")) + //oneShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = (member.buy_point <= Config.Point ? pddInfoTemp.pid_deputy : pddInfoTemp.pid_chief), custom_parameters = _temp_param, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true }); + oneShoppingUrlDic = pdd_api.GetShoppingUrls(api, new { p_id = (member.buy_point <= Config.Point ? pddInfoTemp.pid_deputy : pddInfoTemp.pid_chief), goods_sign_list = $"[\"{goods_sign}\"]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, generate_authority_url = !isBind, force_duo_id = true, generate_schema_url = true }); + + e.SendMessage(mess + .Replace("[商品标题]", goods_name) + .Replace("[商品描述]", goods_desc) + .Replace("[商品主图]", $"[图片={goods_thumbnail_url}]") + .Replace("[图片地址]", goods_thumbnail_url) + .Replace("[已售数量]", sales_tip) + .Replace("[店铺名称]", mall_name) + .Replace("[商品单买价]", min_normal_price.ToString()) + .Replace("[单买返利]", (normal.UserPoint == 0 ? 0.01 : normal.UserPoint).ToString()) + .Replace("[单买地址跳转]", "[单买地址]") + .Replace("[单买地址]", oneShoppingUrlDic == null ? string.Empty : oneShoppingUrlDic["mobile_short_url"].ToString()) + .Replace("[单买地址不跳转]", oneShoppingUrlDic == null ? string.Empty : oneShoppingUrlDic["short_url"].ToString()) + .Replace("[商品拼团价]", min_group_price.ToString()) + .Replace("[拼团返利]", (group.UserPoint == 0 ? 0.01 : group.UserPoint).ToString()) + .Replace("[拼团地址跳转]", "[拼团地址]") + .Replace("[拼团地址]", manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["mobile_short_url"].ToString()) + .Replace("[拼团地址不跳转]", manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["short_url"].ToString()) + .Replace("[单买共节省]", "[共节省]") + .Replace("[共节省]", (normal.UserPoint == 0 ? 0.01 : normal.UserPoint).ToString()) + .Replace("[拼团共节省]", (group.UserPoint == 0 ? 0.01 : group.UserPoint).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goods_name, min_normal_price.ToString(), coupon_discount.ToString(), ((decimal)min_normal_price - (decimal)coupon_discount).ToString(), goods_thumbnail_url, manyShoppingUrlDic == null ? string.Empty : manyShoppingUrlDic["short_url"].ToString(), ApiClient.QrImageType.模板B, CpsType.多多进宝) + "]" : string.Empty)); + } + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + session.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.多多进宝, + itemid = goods_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = _member.id, + title = goods_name, + adzoneid = pid, + mallid = mall_id, + compute_configdic = compute == null ? string.Empty : JsonConvert.SerializeObject(compute) + }).ExecuteCommand(); + session.UpdateRecord(_member.id); + + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.多多进宝; + shared["msg_username"] = _member.username; + shared["price"] = string.Format("{0:F}", min_group_price); + shared["title"] = goods_name; + shared["coupon_price"] = string.Format("{0:F}", _coupon_discount != 0 ? _coupon_discount : 0); + shared["user_point"] = string.Format("{0:F}", (group.UserPoint == 0 ? 0.01 : group.UserPoint)); + shared["economize"] = string.Format("{0:F}", (_coupon_discount != 0 ? ((decimal)coupon_discount + (decimal)(group.UserPoint == 0 ? 0.01 : group.UserPoint)) : (group.UserPoint == 0 ? 0.01m : (decimal)group.UserPoint))); + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + #endregion + } + } + } + #endregion + } + catch (Exception ex) + { + /* + * 返回异常时,提示查不到 + */ + if (ex.Message.Contains("商品不存在") || ex.Message.Contains("商品非多多进宝商品")) + { + e.SendMessage(Config.SearchErrorTip); + + var session = ApiClient.GetSession(); + session.UpdateRecord(e.GetMemberinfo().id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.多多进宝; + shared["msg_username"] = e.GetMemberinfo().username; + shared["price"] = "未知"; + shared["title"] = goods_name; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + } + else + { + this.OnLog("D:" + ex.Message); + e.SendMessage(ApiClient.Setting.SystemConfig.msg_error); + } + } + } + + #region 变量替换 + /// + /// 订单状态 提示语替换 + /// + /// + /// + /// + private string _GetOrderStateMess(SystemOrderStatus order, params object[] objs) + { + + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.全额退款: + case SystemOrderStatus.部分退款: + case SystemOrderStatus.订单维权中: + mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(Config.OrderSettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Config.OrderFreezeTip, objs); + break; + } + return mess; + } + #endregion + + } +} diff --git a/应用/PDDRebate/Config.cs b/应用/PDDRebate/Config.cs new file mode 100644 index 0000000..bb287b8 --- /dev/null +++ b/应用/PDDRebate/Config.cs @@ -0,0 +1,870 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using DevExpress.XtraBars.Customization; +using System.Collections.Generic; +using System.ComponentModel; +using UI.Framework.Entitys; + +namespace PDDRebate +{ + [Config(Name = "插件-拼多多返利-配置")] + public class Config + { + #region 消费积分设置 + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("01.主推广位使用条件 - 购物积分"), DefaultValue(20), + Description(@"用户消费积分≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int Point { get; set; } + //&& member.finish_order <= Config.OrderNum + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("02.主推广位使用条件 - 订单笔数"), DefaultValue(20), + Description(@"用户交易订单数≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int OrderNum { get; set; } + + #endregion + + #region 商品查询 + /// + /// 宝贝二维码识别功能 + /// + [ + Category("2)、商品查询"), DisplayName("01.智能图片识别"), DefaultValue(SwitchType.开启), Description(@"智能图片识别功能,开启可以通过宝贝中的二维码搜索宝贝") + ] + public SwitchType QRCodeSearchSwitch { get; set; } + + /// + /// 正在搜索宝贝提示语 + /// + [ + Category("2)、商品查询"), DisplayName("02.正在搜索提示"), DefaultValue(@"优惠信息查询中....."), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchingTip { get; set; } + + /// + /// 无佣金时提示 + /// + [ + Category("2)、商品查询"), DisplayName("03.无佣金时提示"), DefaultValue(@"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchErrorTip { get; set; } + + /// + /// 无优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("04.无优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品拼团价] [积分名称] +【返利金额】[拼团返利] [积分名称] + +打开网址领取优惠: +[拼团地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品描述]、[商品主图]、[已售数量]、[店铺名称]、[商品单买价]、[单买返利]、[单买地址]、[单买地址不跳转]、[商品拼团价]、[拼团返利]、[拼团地址]、[拼团地址不跳转]、[单买共节省]、[拼团共节省]、[积分名称]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithoutCouponTip { get; set; } + + /// + /// 有优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("05.有优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品拼团价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利红包】[拼团返利] [积分名称] +【为您节约】[拼团共节省]元 + +打开网址领取优惠: +[拼团地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"), + Description(@"支持变量:[商品标题]、[商品描述]、[商品主图]、[已售数量]、[店铺名称]、[优惠券门槛金额]、[优惠券金额]、[优惠券数量]、[优惠券生效日]、[优惠券失效日]、[商品单买价]、[单买返利]、[券后单买价]、[单买地址]、[单买地址不跳转]、[商品拼团价]、[拼团返利]、[券后拼团价]、[拼团地址]、[拼团地址不跳转]、[单买共节省]、[拼团共节省]、[积分名称]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithCouponTip { get; set; } + + /// + /// 无优惠券时提示(QQ) + /// + [ + Category("2)、商品查询"), DisplayName("06.无优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""无优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品描述]、[商品主图]、[已售数量]、[店铺名称]、[商品单买价]、[单买返利]、[单买地址]、[单买地址不跳转]、[商品拼团价]、[拼团返利]、[拼团地址]、[拼团地址不跳转]、[单买共节省]、[拼团共节省]、[积分名称]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithoutCouponTip { get; set; } + + /// + /// 有优惠券提示语(QQ) + /// + [ + Category("2)、商品查询"), DisplayName("07.有优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""有优惠券时提示""的提示语; +支持变量:[商品标题]、[商品描述]、[商品主图]、[已售数量]、[店铺名称]、[优惠券门槛金额]、[优惠券金额]、[优惠券数量]、[优惠券生效日]、[优惠券失效日]、[商品单买价]、[单买返利]、[券后单买价]、[单买地址]、[单买地址不跳转]、[商品拼团价]、[拼团返利]、[券后拼团价]、[拼团地址]、[拼团地址不跳转]、[单买共节省]、[拼团共节省]、[积分名称]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithCouponTip { get; set; } + + #endregion + + #region 订单通知 + /// + /// 用户订单变化通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"01.用户订单变化通知"), DefaultValue(SwitchType.开启), Description(@"开启用户订单变化通知功能时,用户的订单发生变化时,将通知用户订单的情况") + ] + public SwitchType UserOrderChangeSwitch { get; set; } + /// + /// 代理获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"02.代理获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启代理获得提成通知功能时,用户的订单发生变化时,将通知代理获得提成信息") + ] + public SwitchType AgentReceivedCommissionSwitch { get; set; } + /// + /// 群负责人获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"03.群负责人获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启群负责人获得提成通知功能时,用户的订单发生变化时,将通知群负责人获得提成信息") + ] + public SwitchType PrincipalReceivedCommissionSwitch { get; set; } + + /// + /// 已被其他用户绑定 + /// + [Category("3)、订单通知"), DisplayName("04.已被其他用户绑定"), DefaultValue(@"一一一一绑 定 失 败一一一一 + ,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OccupyOrderErrorTip { get; set; } + + /// + /// 未找到订单号 + /// + [Category("3)、订单通知"), DisplayName("05.未找到订单号"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string NotFoundOrderErrorTip { get; set; } + + /// + /// 重复绑定订单号 + /// + [Category("3)、订单通知"), DisplayName("06.重复绑定订单号"), DefaultValue(@"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRepetBindTip { get; set; } + + /// + /// 订单付款提示语 + /// + [Category("3)、订单通知"), DisplayName("07.订单付款"), DefaultValue(@"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentTip { get; set; } + + /// + /// 订单付款通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("08.订单付款通知一级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_OneLevelTip { get; set; } + + /// + /// 订单付款通知二级 + /// + [Category("3)、订单通知"), DisplayName("09.订单付款通知二级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_TwoLevelTip { get; set; } + + /// + /// 订单付款通知三级 + /// + [Category("3)、订单通知"), DisplayName("10.订单付款通知三级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_ThreeLevelTip { get; set; } + + /// + /// 订单付款通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("11.订单付款通知群负责人"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_LeaderTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("12.订单冻结"), DefaultValue(@"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题]] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFreezeTip { get; set; } + + /// + /// 订单结算提示语 + /// + [Category("3)、订单通知"), DisplayName("13.订单结算"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlementTip { get; set; } + + /// + /// 一级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("14.一级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_OneLevelTip { get; set; } + + /// + /// 二级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("15.二级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_TwoLevelTip { get; set; } + + /// + /// 三级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("16.三级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_ThreeLevelTip { get; set; } + + /// + /// 群负责人获得提成 + /// + [Category("3)、订单通知"), DisplayName("17.群负责人获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_LeaderTip { get; set; } + + /// + /// 订单退款提示语 + /// + [Category("3)、订单通知"), DisplayName("18.订单退款"), DefaultValue(@"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRefundTip { get; set; } + + /// + /// 一级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("19.客户维权一级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_OneLevelTip { get; set; } + + /// + /// 二级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("20.客户维权二级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_TwoLevelTip { get; set; } + + /// + /// 三级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("21.客户维权三级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_ThreeLevelTip { get; set; } + + /// + /// 群负责人获得提成 + /// + [Category("3)、订单通知"), DisplayName("22.客户维权群负责人"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_LeaderTip { get; set; } + + /// + /// 订单失效提示语 + /// + [Category("3)、订单通知"), DisplayName("23.订单失效"), DefaultValue(@"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFailureTip { get; set; } + + /// + /// 订单失效通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("24.订单失效通知一级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_OneLevelTip { get; set; } + + /// + /// 订单失效通知二级 + /// + [Category("3)、订单通知"), DisplayName("25.订单失效通知二级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_TwoLevelTip { get; set; } + + /// + /// 订单失效通知三级 + /// + [Category("3)、订单通知"), DisplayName("26.订单失效通知三级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_ThreeLevelTip { get; set; } + + /// + /// 订单失效通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("27.订单失效通知群负责人"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_LeaderTip { get; set; } + + // + /// 宝贝多人查询提示绑定 + /// + [Category("3)、订单通知"), DisplayName("28.宝贝多人查询提示绑定"), DefaultValue(@"一一一一绑 定 提 示一一一一 +【商品标题】[商品标题] +该商品被多人查询系统无法匹配是谁下单,请亲手动到拼多多复制订单号给我手动绑定该订单"), + Description(@"多人查询同一个宝贝,导致无法自动绑定.则将推送该信息给查询过该宝贝的客户 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string LotUserQueryBindTip { get; set; } + #endregion + + #region 限制设置 + /// + /// 店铺ID限制提示 + /// + [Category("4)、限制通知"), DisplayName("01.店铺ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[店铺ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SellerIDRestrictTip { get; set; } + + /// + /// 商品ID限制提示 + /// + [Category("4)、限制通知"), DisplayName("02.商品ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ItemIDRestrictTip { get; set; } + + /// + /// 拉黑提示 + /// + [Category("4)、限制通知"), DisplayName("03.用户被拉黑"), DefaultValue(@"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string Blocked_RestrictTip { get; set; } + #endregion + + private int _ComparisonFeeRate; + + [ + Category("5)、比价模式"), DisplayName(@"01.预扣除比例(单位%)"), DefaultValue(0), Description(@"查询商品时将佣金扣除预扣除的比例后再计算用户所得佣金 +比如正常订单总佣金为10块钱,扣除预扣除比例(例:10%),则按9元来计算用户所得") + ] + public int ComparisonFeeRate + { + get { return _ComparisonFeeRate; } + set + { + _ComparisonFeeRate = value < 0 ? 0 : value; + } + } + + #region 防撸设置 + /// + /// 同一店铺多次购买(同一商品)开关 + /// + [Browsable(false)] + public bool AShop_SameCommodity_Switch { get; set; } + + /// + /// 同一店铺多次购买(同一商品)数量 + /// + [Browsable(false)] + public int AShop_SameCommodity_Number { get; set; } + + /// + /// 同一店铺多次购买(同一商品)处理方式 + /// + [Browsable(false)] + public OperateType AShop_SameCommodity_OperateType { get; set; } + + /// + /// 同一店铺多次购买(同一商品)置顶 + /// + [Browsable(false)] + public bool AShop_SameCommodity_UserTop { get; set; } + + /// + /// 同一店铺多次购买(不同商品)开关 + /// + [Browsable(false)] + public bool AShop_DifferentCommodity_Switch { get; set; } + + /// + /// 同一店铺多次购买(不同商品)数量 + /// + [Browsable(false)] + public int AShop_DifferentCommodity_Number { get; set; } + + /// + /// 同一店铺多次购买(不同商品)置顶 + /// + [Browsable(false)] + public bool AShop_DifferentCommodity_UserTop { get; set; } + + /// + /// 同一店铺多次购买(不同商品)处理方式 + /// + [Browsable(false)] + public OperateType AShop_DifferentCommodity_OperateType { get; set; } + + /// + /// 收货时间验证开关 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_Switch { get; set; } + + /// + /// 收货时间验证时长(小时) + /// + [Browsable(false)] + public int ReceivingTimeCheck_Hour { get; set; } + + /// + /// 收货时间验证处理方式 + /// + [Browsable(false)] + public OperateType ReceivingTimeCheck_OperateType { get; set; } + + /// + /// 收货时间验证置顶 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_UserTop { get; set; } + + /// + /// 收货时间验证订单冻结时间 + /// + [Browsable(false)] + public int ReceivingTimeCheck_FreezeTime { get; set; } + + /// + /// 屏蔽的商品ID集合 + /// + [Browsable(false)] + public List ItemIDRestrictList { get; set; } + + /// + /// 屏蔽的卖家ID集合 + /// + [Browsable(false)] + public List SellerIDRestrictlist { get; set; } + + ///// + ///// + ///// + //[Browsable(false)] + //public string Abnormal_DingDingApi { get; set; } + + ///// + ///// + ///// + //[Browsable(false)] + //public string Abnormal_DingDingApi_Token { get; set; } + + [Browsable(false)] + public string notice_robotname { get; set; } + + #endregion + + public Config() + { + + this.SellerIDRestrictTip = @"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"; + this.ItemIDRestrictTip = @"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"; + this.Blocked_RestrictTip = @"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"; + + this.AShop_SameCommodity_Switch = false; + this.AShop_SameCommodity_Number = 10; + this.AShop_SameCommodity_OperateType = OperateType.通知钉钉群; + this.AShop_SameCommodity_UserTop = false; + this.AShop_DifferentCommodity_Switch = false; + this.AShop_DifferentCommodity_Number = 10; + this.AShop_DifferentCommodity_OperateType = OperateType.通知钉钉群; + this.AShop_DifferentCommodity_UserTop = false; + this.ReceivingTimeCheck_Switch = false; + this.ReceivingTimeCheck_Hour = 24; + this.ReceivingTimeCheck_OperateType = OperateType.订单冻结; + this.ReceivingTimeCheck_UserTop = false; + this.ReceivingTimeCheck_FreezeTime = 24; + this.notice_robotname = string.Empty; + + this.ItemIDRestrictList = new List(); + this.SellerIDRestrictlist = new List(); + + this.Point = 20; + this.OrderNum = 20; + this.QRCodeSearchSwitch = SwitchType.开启; + this.UserOrderChangeSwitch = SwitchType.开启; + this.PrincipalReceivedCommissionSwitch = SwitchType.关闭; + this.AgentReceivedCommissionSwitch = SwitchType.关闭; + this.SearchingTip = @"优惠信息查询中....."; + this.QQSearchSuccessWithoutCouponTip = string.Empty; + this.QQSearchSuccessWithCouponTip = string.Empty; + this.OrderCountermandInform_OneLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_TwoLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_ThreeLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_LeaderTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.LotUserQueryBindTip = @"一一一一绑 定 提 示一一一一 +【商品标题】[商品标题] +该商品被多人查询系统无法匹配是谁下单,请亲手动到拼多多复制订单号给我手动绑定该订单"; + this.SearchSuccessWithCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品拼团价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利红包】[拼团返利] [积分名称] +【为您节约】[拼团共节省]元 + +打开网址领取优惠: +[拼团地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"; + this.SearchSuccessWithoutCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品拼团价] [积分名称] +【返利金额】[拼团返利] [积分名称] + +打开网址领取优惠: +[拼团地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"; + this.SearchErrorTip = @"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"; + this.OrderRepetBindTip = @"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentTip = @"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentInform_OneLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderPaymentInform_TwoLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderPaymentInform_ThreeLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderPaymentInform_LeaderTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderFailureTip = @"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderFreezeTip = @"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题]] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"; + this.OrderRefundTip = @"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_OneLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_TwoLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_ThreeLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_LeaderTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlementTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OccupyOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"; + this.NotFoundOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"; + this.OrderSettlement_OneLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_TwoLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_ThreeLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_LeaderTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + } + + } +} diff --git a/应用/PDDRebate/Entitys/fl_plugin_pddrebate_pddtgw.cs b/应用/PDDRebate/Entitys/fl_plugin_pddrebate_pddtgw.cs new file mode 100644 index 0000000..21c41ee --- /dev/null +++ b/应用/PDDRebate/Entitys/fl_plugin_pddrebate_pddtgw.cs @@ -0,0 +1,49 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PDDRebate.Entitys +{ + /// + /// 平台推广位设置类 (数据库表) + /// + public class fl_plugin_pddrebate_pddtgw : base_model + { + /// + /// 左连接主表 fl_robot_info 的主键 + /// + public int robot_id { get; set; } + /// + /// 主推广位CPS名称 + /// + public string pid_chief_cps_name { get; set; } + /// + /// 主推广位id + /// + public string pid_chief { get; set; } + /// + /// 主推广位昵称 + /// + public string pid_chief_name { get; set; } + /// + /// 副推广位CPS名称 + /// + public string pid_deputy_cps_name { get; set; } + /// + /// 副推广位id + /// + public string pid_deputy { get; set; } + /// + /// 副推广位名称 + /// + public string pid_deputy_name { get; set; } + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } + +} diff --git a/应用/PDDRebate/Entitys/pddinfo_temp.cs b/应用/PDDRebate/Entitys/pddinfo_temp.cs new file mode 100644 index 0000000..5ffe920 --- /dev/null +++ b/应用/PDDRebate/Entitys/pddinfo_temp.cs @@ -0,0 +1,94 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PDDRebate.Entitys +{ + /// + /// 临时的表 (用于数据显示) + /// + public class pddinfo_temp + { + public long ID { get; set; } + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string name { get; set; } + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 主推广位cps名称 + /// + private string _pid_chief_cps_name { get; set; } + public string pid_chief_cps_name + { + get { return _pid_chief_cps_name; } + set { _pid_chief_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_chief; + /// + /// 主推广位id + /// + public string pid_chief + { + get { return _pid_chief; } + set { _pid_chief = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 主推广位昵称 + /// + private string _pid_chief_name; + + public string pid_chief_name + { + get { return _pid_chief_name; } + set { _pid_chief_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位cps名称 + /// + private string _pid_deputy_cps_name { get; set; } + public string pid_deputy_cps_name + { + get { return _pid_deputy_cps_name; } + set { _pid_deputy_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_deputy; + + /// + /// 副推广位id + /// + public string pid_deputy + { + get { return _pid_deputy; } + set { _pid_deputy = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 副推广位名称 + /// + private string _pid_deputy_name; + + public string pid_deputy_name + { + get { return _pid_deputy_name; } + set { _pid_deputy_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } +} diff --git a/应用/PDDRebate/Entitys/queryhist_temp.cs b/应用/PDDRebate/Entitys/queryhist_temp.cs new file mode 100644 index 0000000..3f1b88d --- /dev/null +++ b/应用/PDDRebate/Entitys/queryhist_temp.cs @@ -0,0 +1,16 @@ +using Api.Framework.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PDDRebate.Entitys +{ + public class queryhist_temp + { + public string robot_name { get; set; } + public CpsType type { get; set; } + public int userid { get; set; } + } +} diff --git a/应用/PDDRebate/MainForm.Designer.cs b/应用/PDDRebate/MainForm.Designer.cs new file mode 100644 index 0000000..57e53e7 --- /dev/null +++ b/应用/PDDRebate/MainForm.Designer.cs @@ -0,0 +1,759 @@ +namespace PDDRebate +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox4 = new System.Windows.Forms.ComboBox(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit6 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown4 = new System.Windows.Forms.NumericUpDown(); + this.comboBox3 = new System.Windows.Forms.ComboBox(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl32 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl31 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + this.xtraTabPage3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(904, 509); + this.xtraTabPage1.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(182, 177); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 8; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl1 + // + this.pageControl1.Location = new System.Drawing.Point(0, 470); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(900, 36); + this.pageControl1.TabIndex = 5; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(904, 470); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 50; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "平台类型"; + this.gridColumn1.FieldName = "chattype"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 99; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 148; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 125; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "主推广位"; + this.gridColumn5.FieldName = "pid_chief_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 149; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "副推广位"; + this.gridColumn7.FieldName = "pid_deputy_name"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 158; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "禁止使用"; + this.gridColumn9.FieldName = "onoff"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 6; + this.gridColumn9.Width = 66; + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(906, 535); + this.xtraTabControl1.TabIndex = 6; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(904, 509); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(904, 509); + this.settingControl1.TabIndex = 0; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupBox1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(904, 509); + this.xtraTabPage3.Text = " 防 撸 设 置 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl6); + this.groupBox1.Controls.Add(this.labelControl9); + this.groupBox1.Controls.Add(this.comboBox4); + this.groupBox1.Controls.Add(this.checkBox3); + this.groupBox1.Controls.Add(this.checkBox2); + this.groupBox1.Controls.Add(this.checkBox1); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.buttonCheck2); + this.groupBox1.Controls.Add(this.buttonCheck1); + this.groupBox1.Controls.Add(this.buttonCheck); + this.groupBox1.Controls.Add(this.memoEdit6); + this.groupBox1.Controls.Add(this.memoEdit5); + this.groupBox1.Controls.Add(this.numericUpDown2); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.numericUpDown4); + this.groupBox1.Controls.Add(this.comboBox3); + this.groupBox1.Controls.Add(this.comboBox2); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Controls.Add(this.labelControl30); + this.groupBox1.Controls.Add(this.labelControl32); + this.groupBox1.Controls.Add(this.numericUpDown3); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl31); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl29); + this.groupBox1.Controls.Add(this.labelControl28); + this.groupBox1.Controls.Add(this.labelControl27); + this.groupBox1.Location = new System.Drawing.Point(23, 27); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(844, 455); + this.groupBox1.TabIndex = 4; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础设置 "; + // + // labelControl6 + // + this.labelControl6.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl6.Appearance.Options.UseForeColor = true; + this.labelControl6.Location = new System.Drawing.Point(614, 154); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(215, 14); + this.labelControl6.TabIndex = 61; + this.labelControl6.Text = "(在【系统管理->群通知机器人】中添加)"; + // + // labelControl9 + // + this.labelControl9.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl9.Appearance.Options.UseForeColor = true; + this.labelControl9.Location = new System.Drawing.Point(471, 154); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(130, 14); + this.labelControl9.TabIndex = 56; + this.labelControl9.Text = "(未选择时使用系统设置)"; + // + // comboBox4 + // + this.comboBox4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox4.FormattingEnabled = true; + this.comboBox4.Location = new System.Drawing.Point(170, 151); + this.comboBox4.Name = "comboBox4"; + this.comboBox4.Size = new System.Drawing.Size(293, 22); + this.comboBox4.TabIndex = 55; + // + // checkBox3 + // + this.checkBox3.AutoSize = true; + this.checkBox3.Location = new System.Drawing.Point(664, 102); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.Size = new System.Drawing.Size(108, 18); + this.checkBox3.TabIndex = 32; + this.checkBox3.Text = "置顶用户(微信)"; + this.checkBox3.UseVisualStyleBackColor = true; + this.checkBox3.Visible = false; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(664, 66); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(108, 18); + this.checkBox2.TabIndex = 33; + this.checkBox2.Text = "置顶用户(微信)"; + this.checkBox2.UseVisualStyleBackColor = true; + this.checkBox2.Visible = false; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(664, 32); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(108, 18); + this.checkBox1.TabIndex = 34; + this.checkBox1.Text = "置顶用户(微信)"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.Visible = false; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(73, 154); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(91, 14); + this.labelControl5.TabIndex = 29; + this.labelControl5.Text = "群通知API接口:"; + // + // buttonCheck2 + // + this.buttonCheck2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = true; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(95, 100); + this.buttonCheck2.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(57, 22); + this.buttonCheck2.TabIndex = 28; + // + // buttonCheck1 + // + this.buttonCheck1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = true; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(95, 64); + this.buttonCheck1.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(57, 22); + this.buttonCheck1.TabIndex = 28; + // + // buttonCheck + // + this.buttonCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck.Checked = true; + this.buttonCheck.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck.Location = new System.Drawing.Point(95, 30); + this.buttonCheck.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck.Name = "buttonCheck"; + this.buttonCheck.Size = new System.Drawing.Size(57, 22); + this.buttonCheck.TabIndex = 28; + // + // memoEdit6 + // + this.memoEdit6.Location = new System.Drawing.Point(50, 342); + this.memoEdit6.Name = "memoEdit6"; + this.memoEdit6.Size = new System.Drawing.Size(740, 96); + this.memoEdit6.TabIndex = 26; + // + // memoEdit5 + // + this.memoEdit5.Location = new System.Drawing.Point(50, 218); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Size = new System.Drawing.Size(740, 96); + this.memoEdit5.TabIndex = 27; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(712, 100); + this.numericUpDown2.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(60, 22); + this.numericUpDown2.TabIndex = 22; + this.numericUpDown2.Value = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.numericUpDown2.Visible = false; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(264, 100); + this.numericUpDown1.Maximum = new decimal(new int[] { + 1000, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(91, 22); + this.numericUpDown1.TabIndex = 22; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // numericUpDown4 + // + this.numericUpDown4.Location = new System.Drawing.Point(370, 64); + this.numericUpDown4.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown4.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown4.Name = "numericUpDown4"; + this.numericUpDown4.Size = new System.Drawing.Size(93, 22); + this.numericUpDown4.TabIndex = 22; + this.numericUpDown4.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // comboBox3 + // + this.comboBox3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox3.FormattingEnabled = true; + this.comboBox3.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群", + "订单冻结"}); + this.comboBox3.Location = new System.Drawing.Point(507, 100); + this.comboBox3.Name = "comboBox3"; + this.comboBox3.Size = new System.Drawing.Size(121, 22); + this.comboBox3.TabIndex = 25; + this.comboBox3.SelectedIndexChanged += new System.EventHandler(this.comboBox3_SelectedIndexChanged); + // + // comboBox2 + // + this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox2.Location = new System.Drawing.Point(507, 64); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(121, 22); + this.comboBox2.TabIndex = 25; + this.comboBox2.SelectedIndexChanged += new System.EventHandler(this.comboBox2_SelectedIndexChanged); + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox1.Location = new System.Drawing.Point(507, 30); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(121, 22); + this.comboBox1.TabIndex = 25; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // labelControl30 + // + this.labelControl30.Location = new System.Drawing.Point(471, 68); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(16, 14); + this.labelControl30.TabIndex = 16; + this.labelControl30.Text = "次."; + // + // labelControl32 + // + this.labelControl32.Location = new System.Drawing.Point(50, 322); + this.labelControl32.Name = "labelControl32"; + this.labelControl32.Size = new System.Drawing.Size(72, 14); + this.labelControl32.TabIndex = 17; + this.labelControl32.Text = "屏蔽店铺ID:"; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(370, 30); + this.numericUpDown3.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown3.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(93, 22); + this.numericUpDown3.TabIndex = 23; + this.numericUpDown3.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(128, 322); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(132, 14); + this.labelControl2.TabIndex = 18; + this.labelControl2.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl1 + // + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(128, 198); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(132, 14); + this.labelControl1.TabIndex = 18; + this.labelControl1.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl31 + // + this.labelControl31.Location = new System.Drawing.Point(50, 198); + this.labelControl31.Name = "labelControl31"; + this.labelControl31.Size = new System.Drawing.Size(72, 14); + this.labelControl31.TabIndex = 18; + this.labelControl31.Text = "屏蔽商品ID:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(657, 104); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(48, 14); + this.labelControl8.TabIndex = 19; + this.labelControl8.Text = "订单冻结"; + this.labelControl8.Visible = false; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(779, 104); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(28, 14); + this.labelControl7.TabIndex = 19; + this.labelControl7.Text = "小时."; + this.labelControl7.Visible = false; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(373, 104); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(64, 14); + this.labelControl4.TabIndex = 19; + this.labelControl4.Text = "小时内收货."; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(170, 104); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 19; + this.labelControl3.Text = "用户购买的商品"; + // + // labelControl29 + // + this.labelControl29.Location = new System.Drawing.Point(170, 68); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(190, 14); + this.labelControl29.TabIndex = 19; + this.labelControl29.Text = "用户在同家店铺多次购物(不同商品)"; + // + // labelControl28 + // + this.labelControl28.Location = new System.Drawing.Point(471, 34); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(16, 14); + this.labelControl28.TabIndex = 20; + this.labelControl28.Text = "次."; + // + // labelControl27 + // + this.labelControl27.Location = new System.Drawing.Point(170, 34); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(190, 14); + this.labelControl27.TabIndex = 21; + this.labelControl27.Text = "用户在同家店铺多次购买(同一商品)"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(906, 535); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.IconOptions.ShowIcon = false; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private UI.Framework.Controls.ButtonCheck buttonCheck; + private DevExpress.XtraEditors.MemoEdit memoEdit6; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.NumericUpDown numericUpDown4; + private System.Windows.Forms.ComboBox comboBox3; + private System.Windows.Forms.ComboBox comboBox2; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.LabelControl labelControl30; + private DevExpress.XtraEditors.LabelControl labelControl32; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl31; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl29; + private DevExpress.XtraEditors.LabelControl labelControl28; + private DevExpress.XtraEditors.LabelControl labelControl27; + private System.Windows.Forms.CheckBox checkBox3; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.CheckBox checkBox1; + private DevExpress.XtraEditors.LabelControl labelControl9; + private System.Windows.Forms.ComboBox comboBox4; + private DevExpress.XtraEditors.LabelControl labelControl6; + } +} \ No newline at end of file diff --git a/应用/PDDRebate/MainForm.cs b/应用/PDDRebate/MainForm.cs new file mode 100644 index 0000000..e67a191 --- /dev/null +++ b/应用/PDDRebate/MainForm.cs @@ -0,0 +1,319 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using PDDRebate.Entitys; +using PDDRebate.Properties; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace PDDRebate +{ + public partial class MainForm : BaseForm + { + SqlSugarClient session = null; + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + session = ApiClient.GetSession(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + var apis = ApiClient.GetSession().FindNoticeapiRobots().ToArray(); + var rst = new List(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + comboBox4.DataSource = rst; + + this.settingControl1.Bind(Class1.Config, 110); + + this.buttonCheck.Checked = Class1.Config.AShop_SameCommodity_Switch; + this.numericUpDown3.Value = Class1.Config.AShop_SameCommodity_Number; + this.comboBox1.SelectedIndex = Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单 ? 0 : 1; + + this.buttonCheck1.Checked = Class1.Config.AShop_DifferentCommodity_Switch; + this.numericUpDown4.Value = Class1.Config.AShop_DifferentCommodity_Number; + this.comboBox2.SelectedIndex = Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单 ? 0 : 1; + + this.buttonCheck2.Checked = Class1.Config.ReceivingTimeCheck_Switch; + this.numericUpDown1.Value = Class1.Config.ReceivingTimeCheck_Hour; + this.comboBox3.SelectedIndex = Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单 ? 0 : Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群 ? 1 : 2; + this.numericUpDown2.Value = Class1.Config.ReceivingTimeCheck_FreezeTime; + + this.comboBox4.SelectedIndex = rst.IndexOf(Class1.Config.notice_robotname) == -1 ? 0 : rst.IndexOf(Class1.Config.notice_robotname); + + this.memoEdit5.Text = string.Join(",", Class1.Config.ItemIDRestrictList); + this.memoEdit6.Text = string.Join(",", Class1.Config.SellerIDRestrictlist); + + #region 加载所有的账号 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.多多进宝}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.多多进宝}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label1.Visible = gridView1.RowCount == 0; + + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 行单元格单击事件 + /// + /// + /// + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.多多进宝); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzone == null) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzone.extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + #region 有出现两个重复无法修复的情况,删除一个 + var repetAdzone = adzones.Where(f => f.extend == pidName).ToList(); + if (repetAdzone.Count > 1) + { + for (int i = 1; i <= repetAdzone.Count - 1; i++) + { + session.Deleteable(repetAdzone[i]).ExecuteCommand(); + } + adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + } + #endregion + + adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindPddInfoTempGroups(true); + session.FindAdzoneInfos(true); + session.FindPinduoduoAutoBindPid(true);//刷新推广位 + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzones.Count == 0) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item, false); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzones[0].extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate, adzones[0].onoff); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + if (adzones != null)//数据库中存在 + session.ExcuteSQL("update fl_adzone_info set onoff = @onoff where robot_id = @robot_id and alliance_id = @alliance_id and custom_type = @custom_type", new { onoff = !adzones[0].onoff, robot_id = id, alliance_id = (int)CpsType.多多进宝, custom_type = Resources.SoftwareType }); + session.FindPddInfoTempGroups(true); + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + session.FindPinduoduoAutoBindPid(true);//刷新推广位 + } + } + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 修改显示内容的事件 + /// + /// + /// + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + /// + /// 创建fl_adzone_info对象 + /// + /// + /// + /// + /// + /// + /// + private fl_adzone_info CreateAdzoneInfo(string adzone_name, string adzone_pid, string adzone_pid_cps_name, string rid, string item, bool onoff = false) + { + return new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = adzone_name, //推广位名称 + adzone_pid = adzone_pid, //推广位pid + adzone_pid_cps_name = adzone_pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = int.Parse(rid), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = onoff, //不禁用 + extend = item + }; + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Class1.Config.AShop_SameCommodity_Switch = buttonCheck.Checked; + Class1.Config.AShop_SameCommodity_Number = (int)numericUpDown3.Value; + Class1.Config.AShop_SameCommodity_OperateType = comboBox1.SelectedIndex == 0 ? OperateType.拉入黑名单 : OperateType.通知钉钉群; + + Class1.Config.AShop_DifferentCommodity_Switch = buttonCheck1.Checked; + Class1.Config.AShop_DifferentCommodity_Number = (int)numericUpDown4.Value; + Class1.Config.AShop_DifferentCommodity_OperateType = comboBox2.SelectedIndex == 0 ? OperateType.拉入黑名单 : OperateType.通知钉钉群; + + Class1.Config.ReceivingTimeCheck_Switch = buttonCheck2.Checked; + Class1.Config.ReceivingTimeCheck_Hour = (int)numericUpDown1.Value; + Class1.Config.ReceivingTimeCheck_OperateType = comboBox3.SelectedIndex == 0 ? OperateType.拉入黑名单 : comboBox3.SelectedIndex == 1 ? OperateType.通知钉钉群 : OperateType.订单冻结; + Class1.Config.ReceivingTimeCheck_FreezeTime = (int)numericUpDown2.Value; + + Class1.Config.notice_robotname = comboBox4.SelectedValue.ToString(); + + Class1.Config.ItemIDRestrictList = memoEdit5.Text.Trim().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + Class1.Config.SellerIDRestrictlist = memoEdit6.Text.Trim().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + Util.Save(Class1.Config); + + OrderHelper.RefreshPddConfig(true); + } + + private void comboBox3_SelectedIndexChanged(object sender, EventArgs e) + { + labelControl7.Visible = labelControl8.Visible = numericUpDown2.Visible = comboBox3.SelectedIndex == 2; + checkBox3.Visible = comboBox3.SelectedIndex == 0; + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + checkBox1.Visible = comboBox1.SelectedIndex == 0; + } + + private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) + { + checkBox2.Visible = comboBox2.SelectedIndex == 0; + } + } +} \ No newline at end of file diff --git a/应用/PDDRebate/MainForm.resx b/应用/PDDRebate/MainForm.resx new file mode 100644 index 0000000..d30f539 --- /dev/null +++ b/应用/PDDRebate/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 59 + + \ No newline at end of file diff --git a/应用/PDDRebate/PDDRebate.csproj b/应用/PDDRebate/PDDRebate.csproj new file mode 100644 index 0000000..cc463f4 --- /dev/null +++ b/应用/PDDRebate/PDDRebate.csproj @@ -0,0 +1,191 @@ + + + + + Debug + AnyCPU + {6E33B4DF-4A4C-4B16-8E1A-E4F43A616D33} + Library + Properties + PDDRebate + PDDRebate + v4.6.1 + 512 + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HtmlAgilityPack.dll + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/应用/PDDRebate/Properties/AssemblyInfo.cs b/应用/PDDRebate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d24a639 --- /dev/null +++ b/应用/PDDRebate/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("PDDRebate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PDDRebate")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("6e33b4df-4a4c-4b16-8e1a-e4f43a616d33")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2018.12.18.1")] +[assembly: AssemblyFileVersion("2018.12.18.1")] diff --git a/应用/PDDRebate/Properties/Resources.Designer.cs b/应用/PDDRebate/Properties/Resources.Designer.cs new file mode 100644 index 0000000..0223e65 --- /dev/null +++ b/应用/PDDRebate/Properties/Resources.Designer.cs @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace PDDRebate.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PDDRebate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 拼多多返利 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 拼多多返利 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 拼多多返利插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 拼多多返利 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 拼多多 { + get { + object obj = ResourceManager.GetObject("拼多多", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 活动推广 { + get { + object obj = ResourceManager.GetObject("活动推广", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/PDDRebate/Properties/Resources.resx b/应用/PDDRebate/Properties/Resources.resx new file mode 100644 index 0000000..7b29697 --- /dev/null +++ b/应用/PDDRebate/Properties/Resources.resx @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\拼多多.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 拼多多返利 + 设置主窗体标题 + + + 拼多多返利插件 + 插件介绍 + + + 拼多多返利 + 插件名 + + + ..\Resources\活动推广.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 拼多多返利 + fl_adzone_info自定义类型(custom_type) + + \ No newline at end of file diff --git a/应用/PDDRebate/Properties/licenses.licx b/应用/PDDRebate/Properties/licenses.licx new file mode 100644 index 0000000..121a0ef --- /dev/null +++ b/应用/PDDRebate/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/PDDRebate/Resources/基础管理.png b/应用/PDDRebate/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/PDDRebate/Resources/基础管理.png differ diff --git a/应用/PDDRebate/Resources/拼多多.png b/应用/PDDRebate/Resources/拼多多.png new file mode 100644 index 0000000..a2191d4 Binary files /dev/null and b/应用/PDDRebate/Resources/拼多多.png differ diff --git a/应用/PDDRebate/Resources/活动推广.png b/应用/PDDRebate/Resources/活动推广.png new file mode 100644 index 0000000..727aa42 Binary files /dev/null and b/应用/PDDRebate/Resources/活动推广.png differ diff --git a/应用/PDDRebate/SessionExt.cs b/应用/PDDRebate/SessionExt.cs new file mode 100644 index 0000000..7fdb154 --- /dev/null +++ b/应用/PDDRebate/SessionExt.cs @@ -0,0 +1,48 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using PDDRebate.Entitys; +using PDDRebate.Properties; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PDDRebate +{ + public static class SessionExt + { + const string pddinfo_temp_list_pddrebate = "pddinfo_temp_list_pddrebate"; + + /// + /// 获取fl_adzone_info表的数据集合缓存 + /// + /// + /// 刷新 + /// + public static List FindPddInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + + var pddinfo_temp_groups = ApiClient.Cache.Get>(pddinfo_temp_list_pddrebate);//根据KEY、获得缓存 + if (refresh || pddinfo_temp_groups == null) + { + pddinfo_temp_groups = session.Find($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.多多进宝}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.多多进宝}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id"); + ApiClient.Cache.Set(pddinfo_temp_list_pddrebate, pddinfo_temp_groups, 60); + } + return pddinfo_temp_groups; + } + + public static fl_member_info FindMemberinfo(this SqlSugarClient session, long userid) + { + return session.Find("select * from fl_member_info where id = @id", new { id = userid }).FirstOrDefault(); + } + + public static void Clear() + { + ApiClient.Cache.Remove(pddinfo_temp_list_pddrebate); + } + } +} diff --git a/应用/PointManage/ChatTypeControl.cs b/应用/PointManage/ChatTypeControl.cs new file mode 100644 index 0000000..babfaac --- /dev/null +++ b/应用/PointManage/ChatTypeControl.cs @@ -0,0 +1,59 @@ +using Api.Framework.SDK; +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace PointManage +{ + class ChatTypeControl : PropertyGridEditStyle + { + public ChatTypeControl() + { + var listBox = new CheckedListBoxControl(); + foreach (ChatType item in Enum.GetValues(typeof(ChatType))) + { + listBox.Items.Add(new CheckedListBoxItem(null, item.ToString())); + } + Control = listBox; + } + + /// + /// 将选着的数据进行展示 + /// + /// + public override string GetValue() + { + var listBox = Control as CheckedListBoxControl; + string[] strs = new string[listBox.CheckedItems.Count]; + int i = 0; + foreach (var item in listBox.CheckedItems) + { + strs[i] = item.ToString(); + i++; + } + return string.Join(",", strs); + } + + /// + /// 将内容在控件里面勾选 + /// + /// + public override void SetValue(object value) + { + var listBox = Control as CheckedListBoxControl; + var strs = value == null ? new string[] { } : value.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + foreach (var item in listBox.Items) + { + listBox.SetItemChecked(i, !string.IsNullOrEmpty(strs.FirstOrDefault(f => f == item.ToString()))); + i++; + } + } + + } +} \ No newline at end of file diff --git a/应用/PointManage/Class1.cs b/应用/PointManage/Class1.cs new file mode 100644 index 0000000..e8a9efd --- /dev/null +++ b/应用/PointManage/Class1.cs @@ -0,0 +1,890 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.IPAD; +using CsharpHttpHelper; +using PointManage.Entitys; +using PointManage.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework.Utils; + +namespace PointManage +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.积分管理; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static PointManageConfig Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + session.CreateTable(); + session.AddIndex("uid"); + } + if (!session.TableExist()) + { + session.CreateTable(); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + + + // Config.Unsettled_Forbid_Exchange_Tip = @"一一一申 请 失 败一一一 + + //亲,系统检测到你有【付款成功】订单, + //请收货完成后再来发起提现申请哦!"; + + // Config.NotReceiving_Forbid_Exchange_Tip = @"一一一申 请 失 败一一一 + + //亲,系统未检测到你有订单记录, + //请完成首单后再来发起提现申请哦!"; + + // Util.Save(Config); + + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private readonly object lockAward2 = new object(); + + private void SDK_OrderNoticeEvent(object sender, Api.Framework.Events.OrderNoticeEvent e) + { + try + { + if (Config.Extra_Award_Switch == SwitchType.开启 && e.OrderNoticeType == OrderNoticeType.客户订单) + { + if (e.ChatType == CpsType.多多进宝) + return; + var order = e.Order as base_model_order; + if (order.db_status != SystemOrderStatus.订单结算) return; + lock (lockAward2) + { + var session = ApiClient.GetSession(); + var award = session.FindSingle("select * from fl_plugin_pointmanage_extra_award where uid = @uid", new { uid = e.Member.id }); + if (award == null) + award = new fl_plugin_pointmanage_extra_award() { uid = e.Member.id, count = 1 }; + else + award.count++; + session.SaveExtraAward(award); + } + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} - {ex.StackTrace}"); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.Activate(); + } + catch (Exception ex) + { + this.OnLog("执行时被" + ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private static Queue exchangeQueue = new Queue();//提现队列 + private static exchange_info GetExchange_info() + { + try + { + return exchangeQueue.Dequeue(); + } + catch (Exception) + { } + return null; + } + + private static bool _IsRun = false; + + private void _ExchangeAction() + { + if (_IsRun) return; + _IsRun = true; + + Task.Run(() => + { + try + { + var info = GetExchange_info(); + while (info != null) + { + Thread.Sleep(100); + try + { + var session = ApiClient.GetSession(); + var member = session.FindMemberInfoById(info.uid); + if (member == null) throw new Exception("用户数据异常"); + var robot = session.FindRobots().Where(f => f.id == info.rid).FirstOrDefault(); + if (robot == null) continue; + var exchangePoint = member.cur_point; + + if (exchangePoint >= Config.Exchange_Min_Point) + { + //查询用户今日兑换数量 + var exchange_num = session.Queryable().Where(f => f.uid == member.id && f.type == "提现扣除" && f.crt_time >= DateTime.Today).Count(); + if (exchange_num >= Config.Exchange_Num) + { + ApiClient.SendMessage(robot, member.username, new VariateReplace().CommonReplace(Config.ExchangeInsufficientNumTip.Replace("[兑换次数]", Config.Exchange_Num.ToString()), member));//兑换次数不足 + continue; + } + } + else + { + ApiClient.SendMessage(robot, member.username, new VariateReplace().CommonReplace(Config.ExchangeErrorTip, member).Replace("[最低提现额度]", Config.Exchange_Min_Point.ToString()), info.groupid);//兑换失败,积分不足提示语 + continue; + } + + if (Config.Integer_Exchange_Switch == SwitchType.开启 && exchangePoint >= 1) + exchangePoint = Math.Floor(exchangePoint); + + var back_apply_wx = false;//微信后台申请提现 + var remark = string.Empty;//人工审核原因 + + #region 微信兑换 + //微信商户转账转账 (满足最低兑积分兑换以及自动转账的最高兑换) + if (member.exchange_type == ExchangeType.随系统设置) + { + if ((member.robot_type == ChatType.微信 || member.robot_type == ChatType.企业微信) && string.IsNullOrWhiteSpace(info.groupid) && Config.Exchange_PayType != PointPayType.关闭 && Config.Exchange_Transmatic_Maxpoint >= exchangePoint) + { + //当天微信自动转账金额中已经使用金额 + var sumpoint = session.Queryable().Where(f => f.IsTransmatic == true && f.rid == robot.id && f.time >= DateTime.Today).Sum(f => f.point); + + if (Config.Exchange_Transmatic_SumPoint >= sumpoint)//每天的微信自动转账每日上限 + { + //操作提现次数小于N次人工审核 + if (Config.Audit_Exchange_Frequency_SwitchType == SwitchType.开启) + { + if (long.Parse(session.FindTable("select count(id) as num from fl_exchange_info where uid = @uid", new { uid = member.id }).Rows[0]["num"].ToString()) < Config.Audit_Exchange_Frequency_Baseline) + { + member = session.ChangePoint(PointType.提现扣除, exchangePoint, member.id, "提现扣除【提交人工审核】.");//积分扣除 + + var exchangeList = new fl_exchange_info() { point = exchangePoint, state = ApplyType.未审核, time = DateTime.Now, uid = member.id, rid = robot.id, groupid = info.groupid };//保存用户兑换 + session.Insertable(exchangeList).ExecuteCommand(); + ApiClient.SendMessage(robot, member.username, new VariateReplace().CommonReplace(Config.ExchangeSuccessTip, member).Replace("[提现金额]", exchangePoint.ToString()), info.groupid);//成功提交兑换提示语 + string msg = new VariateReplace().CommonReplace(Config.ExchangeFrequencyLimitDingdingTip, member, robot).Replace("[提现金额]", exchangePoint.ToString()); + + //ApiClient.SendNoticeMessage(msg);//给钉钉发送消息 + if ((Config.notice_robotname == "请选择(钉钉/微信群机器人API名称)")) + ApiClient.SendNoticeMessage(msg);//给钉钉发送消息 + else + { + var api = session.FindNoticeapiRobots().FirstOrDefault(f => f.name == Config.notice_robotname); + if (api != null) ApiClient.SendNoticeMessage(api, msg); + } + + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "兑换次数限制需审核提醒", msg, true); + continue; + } + } + + if (Config.Exchange_PayType == PointPayType.商户) + { + if (string.IsNullOrWhiteSpace(Config.ExchangeCommercialPayTip)) + { + this.OnLog($"{robot.name} - {member.username}:商户付款提示语为空,操作终止,设置提示语后才能正常使用商户付款"); + continue; + } + + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay(new { robot_name = robot.name, robot_nick = robot.nick, username = member.username, usernick = member.usernick }, Class1.Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", exchangePoint.ToString()), exchangePoint, out ispaid, out appinfo); + + this.OnLog($@"{robot.name} - 【{member.usernick}({member.username})】商户连接:{(string.IsNullOrWhiteSpace(url) ? "空" : url)} +appinfo is null:{(appinfo == null)}"); + if (!string.IsNullOrEmpty(url)) + { + member = session.ChangePoint(PointType.提现扣除, exchangePoint, member.id, "提现扣除【商户付款成功】"); + session.Insertable(new fl_exchange_info() { point = exchangePoint, state = ApplyType.已审核, time = DateTime.Now, check_time = DateTime.Now, uid = member.id, remark = $"提现扣除【商户付款成功】 商户链接:{url}", rid = robot.id, IsTransmatic = true, groupid = info.groupid }).ExecuteCommand();//保存记录 + var pay_url = string.Empty; + var mess_1 = string.Empty; + if (ispaid) + mess_1 = Config.ExchangeCommercialEftTip.Replace("[兑换金额]", exchangePoint.ToString()); + else + { + //pay_url = url;// ApiClient.ShortURL(url).Result; + pay_url = ApiClient.ShortURL(url).Result; + LogHelper.GetSingleObj().Info("商户提现链接", $"{member.usernick}({member.username});金额:{exchangePoint};原始:{url} => 缩短:{pay_url}"); + //if (string.IsNullOrWhiteSpace(pay_url)) + //{ + // pay_url = url; + //} + + + + if (Config.ExchangeCommercialPayTip_MiniApp == SwitchType.开启 && appinfo != null) + mess_1 = Util.GetMiNiAppXml(appinfo, robot.type); + + if (string.IsNullOrWhiteSpace(mess_1)) + mess_1 = Config.ExchangeCommercialPayTip.Replace("[领取地址]", pay_url).Replace("[兑换金额]", exchangePoint.ToString()); + } + var mess_2 = new VariateReplace().CommonReplace(Config.ExchangeAdoptTip.Replace("[兑换金额]", exchangePoint.ToString()).Replace("[领取地址]", pay_url), member); + + ApiClient.SendMessage( + new temp_send_data() { Groupid = info.groupid, Message = mess_1, Robot = robot, TouserName = member.username }, + new temp_send_data() { Groupid = info.groupid, Message = mess_2, Robot = robot, TouserName = member.username } + ); + continue; + } + } + + var passInfo = session.FindWeixinpassword(robot.id);//微信自动转账 + if (passInfo != null && !string.IsNullOrEmpty(passInfo.password))//是否设置了账号密码 + { + if (member.robot_type != Api.Framework.SDK.ChatType.微信) throw new Exception("暂时不支持自动转账!"); + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot.name); + if (client == null) throw new Exception(robot.name + ",该帐号没有登录!"); + if (client.WeixinType != Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信) throw new Exception("您当前登录的微信版本,暂不支持自动转账!"); + + var flag = client.SendPay(member.username, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", exchangePoint.ToString()), (int)((decimal)exchangePoint * 100m), passInfo.password, 1, (Chat.Framework.WXSdk.IPAD.PayType)Enum.ToObject(typeof(Chat.Framework.WXSdk.IPAD.PayType), string.IsNullOrEmpty(info.groupid) ? ((int)Config.Exchange_PayType) : 2), passInfo.GetBank());//用户在群中进行提现操作时,将不会进行红包操作,强制以转账形式进行 + if (string.IsNullOrEmpty(flag)) + { + member = session.ChangePoint(PointType.提现扣除, exchangePoint, member.id, "提现扣除【微信自动转账成功】"); + session.Insertable(new fl_exchange_info() { point = exchangePoint, state = ApplyType.已审核, time = DateTime.Now, check_time = DateTime.Now, uid = member.id, remark = "微信自动转账.", rid = robot.id, IsTransmatic = true, groupid = info.groupid }).ExecuteCommand();//保存记录 + ApiClient.SendMessage(robot, member.username, new VariateReplace().CommonReplace(Config.ExchangeTransmaticTip.Replace("[兑换金额]", exchangePoint.ToString()), member), info.groupid);//微信自动转账成功提示语 + continue; + } + else//转账失败,将提现请求提交至后台 + { + if (Config.IsPaymentFailedUseCommercialPaySwitchType == SwitchType.开启)//微信支付失败,使用商户付款 + { + if (string.IsNullOrWhiteSpace(Config.ExchangeCommercialPayTip)) + { + this.OnLog($"{robot.name} - {member.username}:商户付款提示语为空,操作终止,设置提示语后才能正常使用商户付款"); + continue; + } + + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay(new { robot_name = robot.name, robot_nick = robot.nick, username = member.username, usernick = member.usernick }, Class1.Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", exchangePoint.ToString()), exchangePoint, out ispaid, out appinfo); + this.OnLog($@"{robot.name} - 【{member.usernick}({member.username})】商户连接:{url} +appinfo is null:{(appinfo == null)}"); + if (!string.IsNullOrEmpty(url)) + { + member = session.ChangePoint(PointType.提现扣除, exchangePoint, member.id, "提现扣除【微信自动转账失败,商户付款成功】"); + session.Insertable(new fl_exchange_info() { point = exchangePoint, state = ApplyType.已审核, time = DateTime.Now, check_time = DateTime.Now, uid = member.id, remark = $"提现扣除【微信自动转账失败,商户付款成功】 商户链接:{url}", rid = robot.id, IsTransmatic = true, groupid = info.groupid }).ExecuteCommand();//保存记录 + + var pay_url = string.Empty; + var mess_1 = string.Empty; + if (ispaid) + mess_1 = Config.ExchangeCommercialEftTip.Replace("[兑换金额]", exchangePoint.ToString()); + else + { + if (Config.ExchangeCommercialPayTip_MiniApp == SwitchType.开启 && appinfo != null) + mess_1 = Util.GetMiNiAppXml(appinfo, robot.type); + + //pay_url = url;//ApiClient.ShortURL(url).Result; + pay_url = ApiClient.ShortURL(url).Result; + + LogHelper.GetSingleObj().Info("商户提现链接", $"{member.usernick}({member.username});金额:{exchangePoint};原始:{url} = > 缩短:{pay_url}"); + + if (string.IsNullOrWhiteSpace(mess_1)) + { + mess_1 = Config.ExchangeCommercialPayTip.Replace("[领取地址]", pay_url).Replace("[兑换金额]", exchangePoint.ToString()); + } + } + var mess_2 = new VariateReplace().CommonReplace(Config.ExchangeAdoptTip.Replace("[兑换金额]", exchangePoint.ToString()).Replace("[领取地址]", pay_url), member); + + ApiClient.SendMessage( + new temp_send_data() { Groupid = info.groupid, Message = mess_1, Robot = robot, TouserName = member.username }, + new temp_send_data() { Groupid = info.groupid, Message = mess_2, Robot = robot, TouserName = member.username }); + continue; + } + else this.OnLog($"{robot.name} - {member.username}:商户付款兑换积分失败:创建订单号失败"); + } + back_apply_wx = true; + } + } + else + { + //未设置微信支付密码,使用商户开启 + if (Class1.Config.IsEmptyPasswordUseCommercialPaySwitchType == SwitchType.开启) + { + if (string.IsNullOrWhiteSpace(Config.ExchangeCommercialPayTip)) + { + this.OnLog($"{robot.name} - {member.username}:商户付款提示语为空,操作终止,设置提示语后才能正常使用商户付款"); + continue; + } + + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay(new { robot_name = robot.name, robot_nick = robot.nick, username = member.username, usernick = member.usernick }, Class1.Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", exchangePoint.ToString()), exchangePoint, out ispaid, out appinfo); + this.OnLog($@"{robot.name} - 【{member.usernick}({member.username})】商户连接:{url} +appinfo is null:{(appinfo == null)}"); + if (!string.IsNullOrEmpty(url)) + { + member = session.ChangePoint(PointType.提现扣除, exchangePoint, member.id, "提现扣除【微信字支付未开,商户付款成功】"); + session.Insertable(new fl_exchange_info() { point = exchangePoint, state = ApplyType.已审核, time = DateTime.Now, check_time = DateTime.Now, uid = member.id, remark = $"提现扣除【微信支付未开,商户付款成功】 商户链接:{url}", rid = robot.id, IsTransmatic = true, groupid = info.groupid }).ExecuteCommand();//保存记录 + + var pay_url = string.Empty; + var mess_1 = string.Empty; + if (ispaid) + mess_1 = Config.ExchangeCommercialEftTip.Replace("[兑换金额]", exchangePoint.ToString()); + else + { + if (Config.ExchangeCommercialPayTip_MiniApp == SwitchType.开启 && appinfo != null) + mess_1 = Util.GetMiNiAppXml(appinfo, robot.type); + + //pay_url = url;//ApiClient.ShortURL(url).Result; + pay_url = ApiClient.ShortURL(url).Result; + + LogHelper.GetSingleObj().Info("商户提现链接", $"{member.usernick}({member.username});金额:{exchangePoint};原始:{url} = > 缩短:{pay_url}"); + + if (string.IsNullOrWhiteSpace(mess_1)) + mess_1 = Config.ExchangeCommercialPayTip.Replace("[领取地址]", pay_url).Replace("[兑换金额]", exchangePoint.ToString()); + } + var mess_2 = new VariateReplace().CommonReplace(Config.ExchangeAdoptTip.Replace("[兑换金额]", exchangePoint.ToString()).Replace("[领取地址]", pay_url), member); + + ApiClient.SendMessage( + new temp_send_data() { Groupid = info.groupid, Message = mess_1, Robot = robot, TouserName = member.username }, + new temp_send_data() { Groupid = info.groupid, Message = mess_2, Robot = robot, TouserName = member.username }); + continue; + } + else this.OnLog($"{robot.name} - {member.username}:微信未设置支付密码。并且商户付款兑换积分失败:付款链接为空..已转至人工兑换"); + } + else + //this.OnLog($"{robot.name} - {member.username}:微信支付积分兑换失败:未设置支付密码。已转至人工兑换"); + this.OnLog($"{robot.name} - {member.username}:未设置支付密码使用商户付款-关闭状态。已转至人工兑换"); + } + } + else + this.OnLog($"{robot.name} - {member.username}:今日微信自动转账金额已达上限({Config.Exchange_Transmatic_SumPoint}元),已转至人工兑换"); + } + } + else + { + back_apply_wx = true; + remark = "系统设置人工审核"; + } + #endregion + + #region 支付宝兑换 (超出了自动转账的条件) + var exchange_NotAudited = session.Find("select * from fl_exchange_info where uid = @uid and state = 1", new { uid = member.id }); + if (exchange_NotAudited.Count != 0)//重复提交 + { + ApiClient.SendMessage(robot, member.username, new VariateReplace().CommonReplace(Config.ExchangeUntreatedTip, member).Replace("[提现金额]", exchange_NotAudited[0].point.ToString()), info.groupid);//尚有未处理的订单 + continue; + } + else + { + //微信人工兑换 + double point = 0d; + if (Config.AlipaySwitch == SwitchType.开启)//支付宝兑换 + { + //未绑定支付宝账号 + if (string.IsNullOrWhiteSpace(member.alipay_name) || string.IsNullOrWhiteSpace(member.alipay_num)) + { + ApiClient.SendMessage(robot, member.username, Config.ExchangeUnBindAlipayTip, info.groupid); + continue; + } + } + + if (back_apply_wx) + point = exchangePoint; + else + point = Config.Exchange_Max_Point >= exchangePoint ? exchangePoint : Config.Exchange_Max_Point;//如果积分高于最高兑换,则只能兑换最高的积分值.反之只能兑换所有的积分 + member = session.ChangePoint(PointType.提现扣除, point, member.id, $"提现扣除【提交人工审核】{remark}");//积分扣除 + + var exchangeList = new fl_exchange_info() { point = point, state = ApplyType.未审核, time = DateTime.Now, uid = member.id, rid = robot.id, groupid = info.groupid };//保存用户兑换 + session.Insertable(exchangeList).ExecuteCommand(); + ApiClient.SendMessage(robot, member.username, new VariateReplace().CommonReplace(Config.ExchangeSuccessTip, member).Replace("[提现金额]", point.ToString()), info.groupid);//成功提交兑换提示语 + string msg = new VariateReplace().CommonReplace(Config.ExchangeSuccessDingdingTip, member, robot).Replace("[提现金额]", point.ToString()); + if ((Config.notice_robotname == "请选择(钉钉/微信群机器人API名称)")) + ApiClient.SendNoticeMessage(msg);//给钉钉发送消息 + else + { + var api = session.FindNoticeapiRobots().FirstOrDefault(f => f.name == Config.notice_robotname); + if (api != null) ApiClient.SendNoticeMessage(api, msg); + } + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "兑换审核提醒", msg, true); + } + #endregion + + } + catch (Exception ex) + { + this.OnLog($"提现异常:{ex.Message} ~ {ex.StackTrace}"); + } + finally + { + info = GetExchange_info(); + } + } + } + catch (Exception ex) + { + this.OnLog($"提现异常:{ex.Message} - {ex.StackTrace}"); + } + finally + { + _IsRun = false; + } + }); + } + + private readonly object AwardLock = new object(); + private readonly object ExchangeLock = new object(); + private readonly object SignInLock = new object(); + + private static bool flag = false; + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + #region 抢红包功能 + if (Config.Extra_Award_Switch == SwitchType.开启 && !string.IsNullOrWhiteSpace(Config.Extra_Award_CMD)) + { + var reg = Regex.Match(e.Message.Trim(), Config.Extra_Award_CMD); + if (reg.Success) + { + var session = ApiClient.GetSession(); + var award = session.FindSingle("select * from fl_plugin_pointmanage_extra_award where uid = @uid", new { uid = e.GetMemberinfo().id }); + if (award == null) + { + award = new fl_plugin_pointmanage_extra_award() { uid = e.GetMemberinfo().id, count = 0 }; + session.SaveExtraAward(award); + } + + string mess = string.Empty; + if (award.count <= 0) + { + mess = new VariateReplace().CommonReplace(Config.Extra_AwardErrorTip, e.GetMemberinfo()); + } + else + { + lock (AwardLock) + { + var point = Math.Round((new Random().Next( + int.Parse(Math.Round(Config.Extra_Award_Min_Point * 100, 2).ToString()), + int.Parse(Math.Round((Config.Extra_Award_Max_Point + 0.01) * 100, 2).ToString()) + )) / 100d, 2); + var member = session.ChangePoint(PointType.其他奖励, point, e.GetMemberinfo().id, $"抢红包:{point}"); + mess = new VariateReplace().CommonReplace(Config.Extra_AwardSuccessTip.Replace("[红包金额]", point.ToString("0.00")), member); + award.count--; + session.SaveExtraAward(award); + } + } + e.SendMessage(mess); + } + } + #endregion + + #region 签到指令 + //签到指令 + if (Config.Checkin_Switch == SwitchType.开启) + { + if (!string.IsNullOrWhiteSpace(Config.Checkin_CMD) && Regex.IsMatch(e.Message.Trim(), Config.Checkin_CMD)) + { + lock (SignInLock) + { + var key = e.Username + "_SignIn"; + if (Util.GetCache(key)) + { + e.SendMessage(Config.CheckinRepeatTip);//重复签到提示 + return; + } + Util.SetCache(key, 30); + } + + string mess = string.Empty; + var session = ApiClient.GetSession(); + var memberinfo = e.GetMemberinfo(); + if (Config.Restrict_Switch == SwitchType.开启) + { + var day = DateTime.Today.AddMonths(-Config.CheckinRestrictMonth); + var data = session.FindRow($@"select COALESCE(SUM(num), 0) as num from(select count(*) as num from fl_order_alimama where db_userid = @id and db_status = 1002 and db_endtime >= @day +UNION all +select count(*) as num from fl_order_jingdong where db_userid = @id and db_status = 1002 and db_endtime >= @day +UNION all +select count(*) as num from fl_order_pinduoduo where db_userid = @id and db_status = 1002 and db_endtime >= @day +UNION all +select count(*) as num from fl_order_weipinhui where db_userid = @id and db_status = 1002 and db_endtime >= @day) as temp", new { id = e.GetMemberinfo().id, day = day.ToString("yyyy-MM-dd HH:mm:ss") })["num"].ToString(); + + if (int.Parse(data) <= 0) + { + e.SendMessage(Config.CheckinRestrictTip); + return; + } + } + + var checkin = session.Find($"select * from fl_plugin_pointmanage_checkin_info where uid = '{e.GetMemberinfo().id}'").FirstOrDefault(); + if (checkin == null) + { + checkin = new fl_plugin_pointmanage_checkin_info() { uid = e.GetMemberinfo().id, days = 1, time = DateTime.Now, chatType = e.ChatType, sumday = 1 }; + //签到成功1天,没有签到过 + var point = SigninReward(); + //积分的修改 + memberinfo = session.ChangePoint(PointType.其他奖励, point, memberinfo.id, "签到积分奖励"); + mess = new VariateReplace().CommonReplace(Config.CheckinSuccessTip, memberinfo) + .Replace("[签到奖励]", point.ToString()) + .Replace("[连续签到次数]", "1") + .Replace("[总共签到次数]", "1") + .Replace("[每日语录]", Config.CheckinSuccessTip.Contains("[每日语录]") ? FindYuLu() : string.Empty); + } + else + { + var baseTime = DateTime.Parse("2019-09-01 00:00:00"); + + var newTime = DateTime.Now; + + var intervalHours = Math.Floor((newTime - baseTime).TotalHours / Config.Checkin_Period); + var comparisonTime = baseTime.AddHours(intervalHours * Config.Checkin_Period); + if (comparisonTime < checkin.time)//如果用户的签到时间比当前签到时间大,那么这个用户已经签到过了 + { + e.SendMessage(Config.CheckinRepeatTip);//重复签到提示 + return; + } + else if ((checkin.time.AddHours(Config.Checkin_Period) >= comparisonTime)) + { + //连续签到 + checkin.time = DateTime.Now; + checkin.days += 1; + checkin.sumday += 1; + var point = SigninReward(); + //积分的修改 + memberinfo = session.ChangePoint(PointType.其他奖励, point, memberinfo.id, "签到积分奖励"); + mess = new VariateReplace().CommonReplace(Config.CheckinSuccessTip, memberinfo) + .Replace("[签到奖励]", point.ToString()) + .Replace("[连续签到次数]", checkin.days.ToString()) + .Replace("[总共签到次数]", checkin.sumday.ToString()) + .Replace("[每日语录]", Config.CheckinSuccessTip.Contains("[每日语录]") ? FindYuLu() : string.Empty); + } + else + { + //签到中断 + checkin.time = DateTime.Now; + checkin.days = 1; + checkin.sumday += 1; + var point = SigninReward(); + + //积分的修改 + memberinfo = session.ChangePoint(PointType.其他奖励, point, memberinfo.id, "签到积分奖励"); + mess = new VariateReplace().CommonReplace(Config.CheckinSuccessTip, memberinfo) + .Replace("[签到奖励]", point.ToString()) + .Replace("[连续签到次数]", "1") + .Replace("[总共签到次数]", checkin.sumday.ToString()) + .Replace("[每日语录]", Config.CheckinSuccessTip.Contains("[每日语录]") ? FindYuLu() : string.Empty); + } + } + session.Saveable(checkin).ExecuteReturnEntity(); + + if (!string.IsNullOrEmpty(mess)) + { + e.SendMessage(mess); + e.Cancel = true; + return; + } + //} + } + } + #endregion + + #region 用户支付宝绑定 + if (!string.IsNullOrWhiteSpace(Config.Alipay_Bind_CMD) && !string.IsNullOrWhiteSpace(Config.Alipay_ChatType)) + { + var chatStr = Config.Alipay_ChatType.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList(); + if (chatStr.Contains(e.ChatType.ToString())) + { + var reg = Regex.Match(e.Message.Trim(), Config.Alipay_Bind_CMD); + if (reg.Success) + { + var session = ApiClient.GetSession(); + e.GetMemberinfo().alipay_num = reg.Groups["账号"].ToString().Trim(); + e.GetMemberinfo().alipay_name = reg.Groups["名称"].ToString().Trim(); + session.SaveOrUpdate(e.GetMemberinfo()); + e.SendMessage(new VariateReplace().CommonReplace(Config.AlipayBindSuccessTip, e.GetMemberinfo())); + } + } + } + #endregion + + #region 用户身份证绑定 + if (!string.IsNullOrWhiteSpace(Config.IdentityId_Bind_CMD)) + { + var reg = Regex.Match(e.Message.Trim(), Config.IdentityId_Bind_CMD); + if (reg.Success) + { + var session = ApiClient.GetSession(); + if (Regex.IsMatch(reg.Groups["身份证号"].ToString().Trim(), @"(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)")) + { + var idcard = reg.Groups["身份证号"].ToString().Trim(); + var realname = reg.Groups["姓名"].ToString().Trim(); + try + { + var flag = false; + if (string.IsNullOrWhiteSpace(Config.IdentityIdCheckAppKey) && string.IsNullOrWhiteSpace(Config.IdentityIdMatchAppKey)) + { + flag = true; + } + + var http = new HttpHelper(); + var item = new HttpItem(); + + if (!string.IsNullOrWhiteSpace(Config.IdentityIdCheckAppKey)) + { + item.URL = $"http://apis.juhe.cn/idcard/index?key={Config.IdentityIdCheckAppKey}&cardno={idcard}"; + var result = http.GetHtml(item); + var jsonObj = HttpExtend.JsonToDictionary(result.Html); + if (jsonObj != null) + { + if (jsonObj.ContainsKey("resultcode")) + { + if (jsonObj["resultcode"].ToString() != "200" && jsonObj.ContainsKey("reason")) throw new Exception("异常"); + flag = true; + } + } + } + + if ((string.IsNullOrWhiteSpace(Config.IdentityIdCheckAppKey) || flag) && !string.IsNullOrWhiteSpace(Config.IdentityIdMatchAppKey)) + { + item.URL = $"http://op.juhe.cn/idcard/query?key={Config.IdentityIdMatchAppKey}&idcard={idcard}&realname={realname}"; + var result = http.GetHtml(item); + var jsonObj = HttpExtend.JsonToDictionary(result.Html); + if (jsonObj != null && jsonObj.ContainsKey("error_code")) + { + if (jsonObj["error_code"].ToString() == "0") + { + if (jsonObj.ContainsKey("result")) + { + var _result = jsonObj["result"] as Dictionary; + if (_result.ContainsKey("res")) + { + if (_result["res"].ToString() == "1") /*1:匹配 2:不匹配*/ + { + e.GetMemberinfo().identity_card = idcard; + e.GetMemberinfo().identity_name = realname; + session.SaveOrUpdate(e.GetMemberinfo()); + e.SendMessage(new VariateReplace().CommonReplace(Config.IdentityIdBindSuccessTip, e.GetMemberinfo())); + return; + } + } + } + } + throw new Exception("异常"); + } + } + else if (flag && string.IsNullOrWhiteSpace(Config.IdentityIdMatchAppKey)) + { + e.GetMemberinfo().identity_card = idcard; + e.GetMemberinfo().identity_name = realname; + session.SaveOrUpdate(e.GetMemberinfo()); + e.SendMessage(new VariateReplace().CommonReplace(Config.IdentityIdBindSuccessTip, e.GetMemberinfo())); + return; + } + } + catch (Exception) + { + e.SendMessage(new VariateReplace().CommonReplace(Config.IdentityIdBindUSuccessTip.Replace("[姓名]", "[身份证姓名]").Replace("[身份证姓名]", realname).Replace("[身份证号]", "[身份证号码]").Replace("[身份证号码]", idcard), e.GetMemberinfo())); + } + } + else + e.SendMessage(new VariateReplace().CommonReplace(Config.IdentityIdBindUSuccessTip.Replace("[姓名]", "[身份证姓名]").Replace("[身份证姓名]", reg.Groups["姓名"].ToString().Trim()).Replace("[身份证号]", "[身份证号码]").Replace("[身份证号码]", reg.Groups["身份证号"].ToString().Trim()), e.GetMemberinfo())); + } + } + #endregion + + #region 查看用户积分信息 + if (Regex.IsMatch(e.Message.Trim(), Config.CheckUserPoint_CMD)) + { + var session = ApiClient.GetSession(); + var _member = e.GetMemberinfo(true); + if (_member != null) + { + var str = new VariateReplace().CommonReplace(Config.CheckPointSuccessTip, _member); + e.SendMessage(str); + e.Cancel = true; + } + } + #endregion + + #region 兑换积分 + if (!string.IsNullOrWhiteSpace(Config.Exchange_CMD) && Regex.IsMatch(e.Message.Trim(), Config.Exchange_CMD)) + { + lock (ExchangeLock) + { + var memberinfo = e.GetMemberinfo(true); + double exchangePoint = memberinfo.cur_point;//兑换积分 + this.OnLog($"用户({memberinfo.username})余额:" + exchangePoint); + + //限制兑换 + if (DateTime.Now <= memberinfo.ban_exchange_time) + { + e.SendMessage(new VariateReplace().CommonReplace(Config.Ban_Exchange_Tip, memberinfo)); + return; + } + + //无购物不让提现 + if (Config.Unsettled_Forbid_Exchange == SwitchType.开启 && memberinfo.finish_order == 0) + { + if (memberinfo.bind_order != 0) + e.SendMessage(Config.Unsettled_Forbid_Exchange_Tip);//无购物记录不予兑换 + else + e.SendMessage(Config.NotReceiving_Forbid_Exchange_Tip);//无购物记录不予兑换 + return; + } + + #region 支付宝绑定 + if (Config.IdentityIdSwitch == SwitchType.开启 && (string.IsNullOrWhiteSpace(e.GetMemberinfo().identity_card) || string.IsNullOrWhiteSpace(e.GetMemberinfo().identity_name))) + { + e.SendMessage(Config.IdentityIdUnBindExchangeTip);//当前未绑定身份证 + return; + } + #endregion + + var session = ApiClient.GetSession(); + + #region 是否存在审核的订单 + var exchange_NotAudited_ = session.Find("select * from fl_exchange_info where uid = @uid and state = 1", new { uid = memberinfo.id }); + if (exchange_NotAudited_.Count != 0) + { + e.SendMessage(new VariateReplace().CommonReplace(Config.ExchangeUntreatedTip, memberinfo.id).Replace("[提现金额]", exchange_NotAudited_[0].point.ToString()));//尚有未处理的订单 + return; + } + #endregion + + #region 群内提现限制开关 + if (!string.IsNullOrWhiteSpace(e.Groupid) && Config.ExchangeErrorGroupBan_SwitchType == SwitchType.开启) + { + e.SendMessage(new VariateReplace().CommonReplace(Config.ExchangeErrorGroupBanTip, memberinfo)); + return; + } + #endregion + + if (exchangePoint >= Config.Exchange_Min_Point) + { + //查询用户今日兑换数量 + var exchange_num = session.Queryable().Where(f => f.uid == memberinfo.id && f.type == "提现扣除" && f.crt_time >= DateTime.Today).Count(); + + if (exchange_num >= Config.Exchange_Num) + { + e.SendMessage(new VariateReplace().CommonReplace(Config.ExchangeInsufficientNumTip.Replace("[兑换次数]", Config.Exchange_Num.ToString()), memberinfo));//兑换次数不足 + return; + } + else + { + var data = exchangeQueue.FirstOrDefault(f => f.uid == e.GetMemberinfo().id); + if (data == null) + { + exchangeQueue.Enqueue(new exchange_info() { uid = e.GetMemberinfo().id, rid = e.RobotInfo.id, groupid = e.Groupid }); + _ExchangeAction(); + } + else + { + e.SendMessage("提现处理中请稍后..."); + } + e.Cancel = true; + } + } + else + e.SendMessage(new VariateReplace().CommonReplace(Config.ExchangeErrorTip, memberinfo).Replace("[最低提现额度]", Config.Exchange_Min_Point.ToString()));//兑换失败,积分不足提示语 + } + } + #endregion + } + catch (Exception ex) + { + this.OnLog("A:" + ex.Message); + e.SendMessage(ApiClient.Setting.SystemConfig.msg_error); + } + } + + #region 签到奖励积分 + /// + /// 签到奖励积分 + /// + /// + private double SigninReward() + { + Random r = new Random(Guid.NewGuid().GetHashCode()); + return Math.Round((r.Next((int)(Config.Checkin_Reward_Min * 100.00d), (int)(Config.Checkin_Reward_Max * 100.00d))) / 100.00d, 2); + } + #endregion + + internal const string _key = "wmUZgme6iOPOaMTZtPu5DKQ8Dph9fSgy6abFyQv25MD8xOMPBBo0wsLUOVt8r9sk+li11mIg1fs1HPJ75UmIle+w9xhIx/nsXWejuQhXlQV0VyJtzI+id8G+FcyYaog91MfPndJoO3m30fSjE/0KDLDmv1EeQcP24RAzeA29p7c=AQAB"; + /// + /// + /// + /// + private string FindYuLu() + { + try + { + AuthEndpoint end = new AuthEndpoint() + { + Appid = 10004, + Enckey = _key, + //Host = "https://cps.api.52cmg.cn/api/webtool.asmx/send_data", + Host = $"{ApiClient.Setting.SystemConfig.cps_server_api}api/webtool.asmx/send_data", + Method = "find_yulu" + }; + HttpHelper http = new HttpHelper(); + var date = http.SendData(end, false); + if (date.ok) + return date.message.ToString(); + else + return string.Empty; + } + catch (Exception ex) + { + this.OnLog("获取语录失败:" + ex.Message); + } + return string.Empty; + } + + } +} diff --git a/应用/PointManage/Config.cs b/应用/PointManage/Config.cs new file mode 100644 index 0000000..dbce6db --- /dev/null +++ b/应用/PointManage/Config.cs @@ -0,0 +1,1003 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using System.Collections.Generic; +using System.ComponentModel; +using UI.Framework.Entitys; + +namespace PointManage +{ + + [Config(Name = "插件-积分管理-配置")] + public class Config + { + + #region 签到 + /// + /// 签到开关 + /// + [ + Category("1)、签到设置"), DisplayName("01.签到开关"), DefaultValue(SwitchType.开启), + Description(@"签到开关设置") + ] + public SwitchType Checkin_Switch { get; set; } + + /// + /// 签到周期 + /// + [ + Category("1)、签到设置"), DisplayName("02.签到周期"), DefaultValue(@"24"), + Description(@"签到周期,单位:小时"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public int Checkin_Period { get; set; } + + /// + /// 签到指令 + /// + [ + Category("1)、签到设置"), DisplayName("03.签到指令"), DefaultValue(@"^(签到|打卡)$"), + Description(@"签到指令,支持正则表达"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Checkin_CMD { get; set; } + /// + /// 签到最小积分奖励 + /// + [ + Category("1)、签到设置"), DisplayName("04.最小奖励"), DefaultValue(0.01), + Description(@"签到奖励积分区间最小值") + ] + public double Checkin_Reward_Min { get; set; } + /// + /// 签到最大积分奖励 + /// + [ + Category("1)、签到设置"), DisplayName("05.最大奖励"), DefaultValue(0.05), + Description(@"签到奖励积分区间最大值") + ] + public double Checkin_Reward_Max { get; set; } + + /// + /// 签到成功提示语 + /// + [ + Category("1)、签到设置"), DisplayName(@"06.签到成功"), DefaultValue(@"一一一一签 到 成 功一一一一 +【获得奖励】[签到奖励] [积分名称] +【连续签到】[连续签到次数] 次 +【签到次数】[总共签到次数] 次 +【剩余积分】[剩余积分] [积分名称] +【每日语录】[每日语录]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[签到奖励]、[连续签到次数]、[总共签到次数]、[剩余积分]、[积分名称]、[每日语录]、[连续签到次数]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckinSuccessTip { get; set; } + + /// + /// 重复签到提示语 + /// + [ + Category("1)、签到设置"), DisplayName(@"07.重复签到"), DefaultValue(@"一一一一签 到 失 败一一一一 +每日只可以签到一次哦,不要重复签到哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckinRepeatTip { get; set; } + /// + /// 无购物禁止签到开关 + /// + [ + Category("1)、签到设置"), DisplayName("08.无购物禁止签到开关"), DefaultValue(SwitchType.关闭), + Description(@"无购物禁止签到开关") + ] + public SwitchType Restrict_Switch { get; set; } + + private int _CheckinRestrictMonth; + /// + /// 限制签到提示语 + /// + [ + Category("1)、签到设置"), DisplayName(@"09.无购物禁止签到月数"), DefaultValue(1), + Description(@"自定义无购物禁止签到的月数,默认1个月") + ] + public int CheckinRestrictMonth + { + get + { + return _CheckinRestrictMonth; + } + set + { + if (value <= 0) + _CheckinRestrictMonth = 1; + else + _CheckinRestrictMonth = value; + } + } + + /// + /// 限制签到提示语 + /// + [ + Category("1)、签到设置"), DisplayName(@"10.无购物禁止签到提示语"), DefaultValue(@"一一一一签 到 限 制一一一一 +您的账号活跃度不足,签到已被限制!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckinRestrictTip { get; set; } + + #endregion + + #region 查看积分 + /// + /// 查看个人积分指令 + /// + [ + Category("2)、积分设置"), DisplayName("01.查询指令"), DefaultValue(@"^(余额|积分|账单|信息|明细|个人信息)$"), + Description(@"用户查看个人积分信息"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckUserPoint_CMD { get; set; } + + /// + /// 查看个人积分成功提示语 + /// + [ + Category("2)、积分设置"), DisplayName("02.查询成功"), DefaultValue(@"一一一一查 询 成 功一一一一 +【剩余积分】[剩余积分] [积分名称] +【累计获得】[累计积分] [积分名称] +一一一一订 单 相 关一一一一 +【多多待结】[拼多多待结算数量]笔/[拼多多待结算金额]元 +【淘宝待结】[淘宝待结算数量]笔/[淘宝待结算金额]元 +【京东待结】[京东待结算数量]笔/[京东待结算金额]元 +【唯品待结】[唯品会待结算数量]笔/[唯品会待结算金额]元 +【抖音待结】[抖音待结算数量]笔/[抖音待结算金额]元 +【苏宁待结】[苏宁待结算数量]笔/[苏宁待结算金额]元 +【待结汇总】[待结算总数数量]笔/[待结算总数金额]元 +【订单记录】[订单记录] +一一一一一一一一一一一一一 +收货后延迟2-5天,会自动给您结算!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[支付宝姓名]、[支付宝账号]、[剩余积分]、[提成积分]、[累计积分]、[其他积分]、[推广积分]、[消费积分]、[积分名称]、 +[拼多多冻结金额]、[拼多多冻结订单数]、[拼多多未收货金额]、[拼多多未收货订单数]、[拼多多待结算数量]、[拼多多待结算金额]、 +[淘宝冻结金额]、[淘宝冻结订单数]、[淘宝未收货金额]、[淘宝未收货订单数]、[淘宝待结算数量]、[淘宝待结算金额]、 +[京东冻结金额]、[京东冻结订单数]、[京东未收货金额]、[京东未收货订单数]、[京东待结算数量]、[京东待结算金额]、 +[抖音冻结金额]、[抖音冻结订单数]、[抖音未收货金额]、[抖音未收货订单数]、[抖音待结算数量]、[抖音待结算金额]、 +[苏宁冻结金额]、[苏宁冻结订单数]、[苏宁未收货金额]、[苏宁未收货订单数]、[苏宁待结算数量]、[苏宁待结算金额]、 +[唯品会冻结金额]、[唯品会冻结订单数]、[唯品会未收货金额]、[唯品会未收货订单数]、[唯品会待结算数量]、[唯品会待结算金额]、 +[未收货总金额]、[冻结总金额]、[未收货订单数]、[冻结订单数]、[待结算总数数量]、[待结算总数金额]、 +[淘宝售后中订单数]、[京东售后中订单数]、[唯品会售后中订单数]、[抖音售后中订单数]、[苏宁售后中订单数]、[订单总数]、[今日总订单]、[已退款订单数]、[今日总积分]、[已退款积分]、[已兑换积分]、[兑换中积分]、[下级总提成]、[推荐人数]、[订单记录]、 +[完成首单人数]、[未完成首单人数]、[三级有效人数]、[三级邀请人数]、[下级列表]"), + + //[待结算订单数]、[待收货订单数]、[待收货积分]、[待结算积分]、 + + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckPointSuccessTip { get; set; } + + #endregion + + #region 绑定支付宝 + /// + /// 绑定支付宝开关 + /// + [ + Category("3)、支付宝设置"), DisplayName("01.支付宝开关"), DefaultValue(SwitchType.关闭), + Description(@"支付宝开关功能,将决定是否使用支付宝人工审核") + ] + public SwitchType AlipaySwitch { get; set; } + + /// + /// 绑定支付宝指令 + /// + [ + Category("3)、支付宝设置"), DisplayName("02.绑定指令"), DefaultValue(@"^绑定\s+(?<账号>[^\s]+?)\s+(?<名称>[^\s]+?)$"), + Description(@"用户绑定支付宝,支持正则表达式 +正则变量别名:<账号>、<名称> 【 账户:支付宝账号 ; 名称:支付宝名称 】 +作用于:绑定支付宝、修改支付宝 操作 +"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Alipay_Bind_CMD { get; set; } + + /// + /// 支付宝绑定平台 + /// + [ + Category("3)、支付宝设置"), DisplayName("03.绑定平台"), DefaultValue(@"微信"), + Description(@"需要绑定的平台:微信、QQ、微信公众号"), + Editor(typeof(ChatTypeControl), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Alipay_ChatType { get; set; } + + /// + /// 支付宝绑定成功 + /// + [ + Category("3)、支付宝设置"), DisplayName("04.绑定成功"), DefaultValue(@"一一一一绑 定 成 功一一一一 +【姓名】[支付宝姓名] +【账号】[支付宝账号] +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[支付宝姓名]、[支付宝账号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AlipayBindSuccessTip { get; set; } + #endregion + + #region 绑定身份证 + /// + /// 绑定身份证开关 + /// + [ + Category("4)、身份证绑定"), DisplayName("01.提现绑定身份证开关"), DefaultValue(SwitchType.关闭), + Description(@"提现绑定身份证开关,关闭不用给用户绑定身份证即可提现,反之提现需要绑定身份证") + ] + public SwitchType IdentityIdSwitch { get; set; } + + /// + /// 身份证真实性AppKey + /// + [ + Category("4)、身份证绑定"), DisplayName("02.身份证真实性AppKey"), + Description(@""), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdCheckAppKey { get; set; } + + /// + /// 身份姓名匹配AppKey + /// + [ + Category("4)、身份证绑定"), DisplayName("03.身份姓名匹配AppKey"), + Description(@""), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdMatchAppKey { get; set; } + + /// + /// 身份证绑指令 + /// + [ + Category("4)、身份证绑定"), DisplayName("04.身份证绑定指令"), DefaultValue(@"^身份证\s+(?<身份证号>.+?)\s+(?<姓名>.+?)$"), + Description(@"用户绑定支付宝,支持正则表达式 +正则变量别名:<身份证号>、<姓名> 【身份证号:身份证上的证件号 ; 姓名:身份证上的姓名】 +作用于:绑定身份证、修改身份证 操作 +"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityId_Bind_CMD { get; set; } + + /// + /// 身份证绑定成功 + /// + [ + Category("4)、身份证绑定"), DisplayName("05.绑定成功"), DefaultValue(@"一一一一绑 定 成 功一一一一 +【姓名】[身份证姓名] +【身份证】[身份证号码] +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[身份证姓名]、[身份证号码]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdBindSuccessTip { get; set; } + + /// + /// 身份证绑定失败 + /// + [ + Category("4)、身份证绑定"), DisplayName("06.绑定失败"), DefaultValue(@"一一一一绑 定 失 败一一一一 +【姓名】[身份证姓名] +【身份证】[身份证号码] +【失败原因】姓名和身份证不匹配 +一一一一一一一一一一一一一 +以上身份证号码不合法,请核对后重试"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[身份证姓名]、[身份证号码]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdBindUSuccessTip { get; set; } + + /// + /// 身份证未绑定 - 提现操作 + /// + [ + Category("4)、身份证绑定"), DisplayName("07.身份证未绑定 - 提现操作"), DefaultValue(@"一一一一提 现 失 败一一一一 +当前无法提现 +原因: +未绑定身份证请发送 【身份证 身份证号 姓名】 +例如:身份证 123456789123456789 小明 +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[身份证姓名]、[身份证号码]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdUnBindExchangeTip { get; set; } + + #endregion + + #region 提现设置 + /// + /// 无购物记录禁止提现 + /// + [ + Category("5)、提现设置"), DisplayName("01.无购物记录禁止提现"), DefaultValue(SwitchType.关闭), + Description(@"开启时,禁止无购物记录的人进行提现操作") + ] + public SwitchType Unsettled_Forbid_Exchange { get; set; } + + /// + /// 兑换指令 + /// + [ + Category("5)、提现设置"), DisplayName("02.兑换指令"), DefaultValue(@"^(兑换|提现|转账)$"), + Description(@"积分提现指令"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Exchange_CMD { get; set; } + + /// + /// 开启整数提现 + /// + [ + Category("5)、提现设置"), DisplayName("03.开启整数提现"), DefaultValue(SwitchType.关闭), + Description(@"开启时,兑换的金额包含小数,小数部分将不予提现 +注:金额小于1将不生效") + ] + public SwitchType Integer_Exchange_Switch { get; set; } + + [Browsable(false)] + private double _exchange_Min_Point { get; set; } + /// + /// 兑换最低积分 + /// + [ + Category("5)、提现设置"), DisplayName("04.每次最低提现额度"), DefaultValue(1.00), + Description(@"每次最低提现额度,低于这个金额的用户无法执行提现操作") + ] + public double Exchange_Min_Point + { + get { return _exchange_Min_Point; } + set + { + if (value <= 0) + _exchange_Min_Point = 0.01; + else + _exchange_Min_Point = value; + } + } + + [Browsable(false)] + public double _exchange_Max_Point { get; set; } + /// + /// 兑换最高积分 + /// + [ + Category("5)、提现设置"), DisplayName("05.每次最高提现额度"), DefaultValue(100.00), + Description(@"每次最高提现额度") + ] + public double Exchange_Max_Point + { + get { return _exchange_Max_Point; } + set + { + if (value <= 0) + _exchange_Max_Point = 0.01; + else + _exchange_Max_Point = value; + } + } + + [Browsable(false)] + public long _exchange_Num { get; set; } + /// + /// 每日兑换次数 + /// + [ + Category("5)、提现设置"), DisplayName("06.每日最多兑换次数"), DefaultValue(1L), + Description(@"每位用户当天最多提现的次数") + ] + public long Exchange_Num + { + get { return _exchange_Num; } + set + { + if (value < 0) + _exchange_Num = 1; + else + _exchange_Num = value; + } + } + + /// + /// 新用户提现次数限制开关 + /// + [ + Category("5)、提现设置"), DisplayName("07.新用户提现限制开关"), DefaultValue(SwitchType.关闭), + Description(@"开启时,新人提现将被限制,直接进入人工审核") + ] + public SwitchType Audit_Exchange_Frequency_SwitchType { get; set; } + + /// + /// 新用户提现次数限制 + /// + [ + Category("5)、提现设置"), DisplayName("08.新用户提现限制"), DefaultValue(2), + Description(@"该值为提现次数限制值,新用户提现次数小于等于该值将人工审核") + ] + public long Audit_Exchange_Frequency_Baseline { get; set; } + + /// + /// 超过提现次数限制 + /// + [ + Category("5)、提现设置"), DisplayName("09.新用户提现限制 - 通知机器人"), DefaultValue(@"审核通知 +———— +通知事件:新用户提现 +兑换金额:[提现金额] +微信账号:[机器人账号] +微信昵称:[机器人昵称] +客户账号:[账号] +客户昵称:[昵称] +创建时间:[创建时间]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[提现金额]、[剩余积分]、[积分名称]、[支付宝姓名]、[支付宝账号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeFrequencyLimitDingdingTip { get; set; } + + [ +Category("5)、提现设置"), DisplayName("10.限制提现"), DefaultValue(@"一一一一提 现 限 制一一一一 +您的账户被冻结 +账户冻结解除:[限制兑换时间] + +如有疑问联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[限制兑换时间]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string Ban_Exchange_Tip { get; set; } + + [ + Category("5)、提现设置"), DisplayName("11.禁止提现"), DefaultValue(@"一一一一提 现 失 败一一一一 +您未有消费记录,系统积分不予提现操作"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Unsettled_Forbid_Exchange_Tip { get; set; } + + /// + /// 成功提交兑换提示语 + /// + [ + Category("5)、提现设置"), DisplayName("12.申请成功"), DefaultValue(@"一一一一申 请 成 功一一一一 +【申请金额】[提现金额][积分名称] +【剩余金额】[剩余积分][积分名称] +一一一一一一一一一一一一一 +客服会在24小时内处理,节假日会有延迟!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[提现金额]、[剩余积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeSuccessTip { get; set; } + + /// + /// 成功提交兑换提示语 + /// + [ + Category("5)、提现设置"), DisplayName("13.申请成功 - 通知机器人"), DefaultValue(@"审核通知 +———— +兑换金额:[提现金额] +平台类型:[平台类型] +平台账号:[机器人账号] +平台昵称:[机器人昵称] +客户账号:[账号] +客户昵称:[昵称] +创建时间:[创建时间]"), + Description(@"支持变量:[平台类型]、[机器人账号]、[机器人昵称]、[账号]、[昵称]、[提现金额]、[剩余积分]、[积分名称]、[支付宝姓名]、[支付宝账号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeSuccessDingdingTip { get; set; } + + /// + /// 申请失败-未绑定支付宝 + /// + [ + Category("5)、提现设置"), DisplayName("14.申请失败-未绑定支付宝"), DefaultValue(@"一一一一兑 换 失 败一一一一 +请告诉我们您的支付宝收款账号! + +指令:绑定 支付宝账号 姓名 +例如:绑定 18100000000 张三 +一一一一一一一一一一一一一 +绑定成功后,再重新申请提现哦"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeUnBindAlipayTip { get; set; } + + /// + /// 申请失败-重复提交 + /// + [ + Category("5)、提现设置"), DisplayName("15.申请失败-重复提交"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您有[提现金额][积分名称]正在审核,请耐心等待!"), + Description(@"上一笔未处理,不予申请二次兑换 + 支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[提现金额]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeUntreatedTip { get; set; } + + /// + /// 申请失败-积分不足 + /// + [ + Category("5)、提现设置"), DisplayName("16.申请失败-积分不足"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您当前有[剩余积分][积分名称],最低[最低提现额度][积分名称]才可以提现! +待结算积分:[冻结总金额][积分名称] +未收货积分:[未收货总金额][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余积分]、[最低提现额度]、[冻结总金额]、[未收货总金额]、[已兑换积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeErrorTip { get; set; } + + /// + /// 新用户提现次数限制开关 + /// + [ + Category("5)、提现设置"), DisplayName("17.群内提现限制开关"), DefaultValue(SwitchType.关闭), + Description(@"开启时,群内将无法提现,需要添加好友才能进行提现操作") + ] + public SwitchType ExchangeErrorGroupBan_SwitchType { get; set; } + + /// + /// 申请失败-微信群无法提现 + /// + [ + Category("5)、提现设置"), DisplayName("18.申请失败-微信群无法提现"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您当前有[剩余积分][积分名称] +如需兑换请添加好友"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余积分]、[最低提现额度]、[冻结总金额]、[未收货总金额]、[已兑换积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeErrorGroupBanTip { get; set; } + + /// + /// 申请失败-次数不足 + /// + [ + Category("5)、提现设置"), DisplayName("19.申请失败-次数不足"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您今日已兑换[兑换次数]次,已达到上限,请明天再兑换!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换次数]、[剩余积分]、[已兑换积分]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeInsufficientNumTip { get; set; } + + /// + /// 提现失败-审核未过退回 + /// + [ + Category("5)、提现设置"), DisplayName("20.提现失败-审核未过退回"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您申请的[兑换金额][积分名称]已退回! +原因:[备注]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[积分名称]、[剩余积分]、[已兑换积分]、[备注]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeReturnTip { get; set; } + + /// + /// 提现失败-审核未过没收 + /// + [ + Category("5)、提现设置"), DisplayName("21.提现失败-审核未过没收"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您申请的[兑换金额][积分名称]已没收! +原因:[备注]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[剩余积分]、[已兑换积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeConfiscateTip { get; set; } + + /// + /// 提现成功-通过审核 + /// + [ + Category("5)、提现设置"), DisplayName("22.提现成功-通过审核"), DefaultValue(@"一一一一兑 换 成 功一一一一 +您申请的[兑换金额][积分名称]已发放,请注意查收! + +Ps:如未收到,请及时给我们留言!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[剩余积分]、[已兑换积分]、[积分名称]、[领取地址](仅限商户有效)"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeAdoptTip { get; set; } + + [ + Category("5)、提现设置"), DisplayName("23.商户付款通知(优先使用小程序)"), DefaultValue(SwitchType.开启), + Description(@"如果商户支持小程序,将会优先推送小程序模板!(届时 5-22 设置的提示语,将不会推送)")] + public SwitchType ExchangeCommercialPayTip_MiniApp { get; set; } = SwitchType.开启; + + /// + /// 商户付款通知 + /// + [ + Category("5)、提现设置"), DisplayName("24.商户付款通知"), DefaultValue(@"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[领取地址]、[兑换金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeCommercialPayTip { get; set; } + + /// + /// 商户付款通知 + /// + [ + Category("5)、提现设置"), DisplayName("25.商户付款通知 - 直接到账"), DefaultValue(@"一一一一商 户 转 账 成 功一一一一 +[兑换金额]兑换成功 +已直接转入您的账户!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeCommercialEftTip { get; set; } + + private string _notice_robotname; + [Category("5)、提现设置"), DisplayName("26.钉钉/微信群机器人"), DefaultValue("请选择(钉钉/微信群机器人API名称)"), Description(@"请选择已存在的机器人名称,如果还没有添加,在【系统管理->群通知机器人】中添加机器人! +未选择则使用默认系统设置"), TypeConverter(typeof(notice_robotname_item))] + public string notice_robotname + { + get { return _notice_robotname; } + set + { + _notice_robotname = value; + } + } + + public class notice_robotname_item : MyTypeConverter + { + public override string[] GetValues() + { + var session = ApiClient.GetSession(); + var apis = session.FindNoticeapiRobots().ToArray(); + var rst = new List(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + return rst.ToArray(); + } + } + + #endregion + + #region 提现设置 - (微信自动转账设置) + /// + /// 支付方式 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("01.支付方式"), DefaultValue(Entitys.PayType.关闭), + Description(@"兑换支付方式: +1)、关闭 +2)、转账 +3)、发红包") + ] + public Entitys.PayType Exchange_PayType { get; set; } + + /// + /// 微信自动转账单笔最高上限 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("02.最高额度"), DefaultValue(40.00), + Description(@"微信自动转账,单笔最高兑换上限") + ] + /// + /// 每次自动转账最大金额 + /// + public double Exchange_Transmatic_Maxpoint { get; set; } + /// + /// 微信自动转账每日上限(总金额) + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("03.每日每个机器人最多支付"), DefaultValue(1000.00), + Description(@"微信自动转账,每日最高兑换金额 (防作弊设置,每天每个微信最多支出多少钱,防止被撸羊毛)") + ] + public double Exchange_Transmatic_SumPoint { get; set; } + + /// + /// 微信自动转账红包标题 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("04.红包标题"), DefaultValue(@"兑换成功:[兑换金额]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangePacketTitle { get; set; } + + /// + /// 微信自动转账成功提示语 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("05.转账成功"), DefaultValue(@"一一一一兑 换 成 功一一一一 +您申请的[兑换金额][积分名称]已发放,请注意查收! + +Ps:请及时查询微信红包"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[剩余积分]、[已兑换积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeTransmaticTip { get; set; } + + /// + /// 未设置支付密码使用商户付款 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("06.未设置支付密码使用商户付款"), DefaultValue(SwitchType.关闭), + Description(@"开启:未设置支付密码使用商户付款") + ] + public SwitchType IsEmptyPasswordUseCommercialPaySwitchType { get; set; } + + /// + /// 微信支付不成功使用商户付款 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("07.微信支付不成功使用商户付款"), DefaultValue(SwitchType.关闭), + Description(@"开启:微信支付失败使用商户付款") + ] + public SwitchType IsPaymentFailedUseCommercialPaySwitchType { get; set; } + #endregion + + #region + /// + /// 结算抢红包开关 + /// + [ + Category("7)、抢红包设置"), DisplayName("01.结算抢红包开关"), DefaultValue(SwitchType.关闭), + Description(@"开启时,结算一个订单可以获取一个抢红包的机会") + ] + public SwitchType Extra_Award_Switch { get; set; } + + /// + /// 结算抢红包指令 + /// + [ + Category("7)、抢红包设置"), DisplayName("02.结算抢红包指令"), DefaultValue(@"^(抢红包)$"), + Description(@"订单结算后抢红包指令"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Extra_Award_CMD { get; set; } + + [Browsable(false)] + private double _Extra_Award_Min_Point { get; set; } + /// + /// 抢红包最低金额 + /// + [ + Category("7)、抢红包设置"), DisplayName("03.抢红包最低金额"), DefaultValue(1.00), + Description(@"抢红包最低金额") + ] + public double Extra_Award_Min_Point + { + get { return _Extra_Award_Min_Point; } + set + { + if (value <= 0) + _Extra_Award_Min_Point = 0.01; + else + _Extra_Award_Min_Point = value; + } + } + + [Browsable(false)] + public double _Extra_Award_Max_Point { get; set; } + /// + /// 抢红包最高金额 + /// + [ + Category("7)、抢红包设置"), DisplayName("04.抢红包最高金额"), DefaultValue(1.50), + Description(@"抢红包最搞金额") + ] + public double Extra_Award_Max_Point + { + get { return _Extra_Award_Max_Point; } + set + { + if (value <= 0) + _Extra_Award_Max_Point = 0.01; + else + _Extra_Award_Max_Point = value; + } + } + + /// + /// 抢红包成功 + /// + [ + Category("7)、抢红包设置"), DisplayName("05.抢红包成功"), DefaultValue(@"一一一一抢 红 包 成 功一一一一 + +恭喜获得红包:[红包金额][积分名称] +当前剩余积分:[剩余积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余积分]、[剩余积分]、[冻结总金额]、[未收货总金额]、[红包金额]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Extra_AwardSuccessTip { get; set; } + + + /// + /// 抢红包失败 + /// + [ + Category("7)、抢红包设置"), DisplayName("05.抢红包失败"), DefaultValue(@"一一一一抢 红 包 失 败一一一一 + +当前无抢红包机会"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余积分]、[冻结总金额]、[未收货总金额]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Extra_AwardErrorTip { get; set; } + #endregion + + public Config() + { + + #region 签到 + this.Restrict_Switch = SwitchType.关闭; + this._CheckinRestrictMonth = 1; + this.Checkin_Period = 24; + this.Checkin_Switch = SwitchType.开启; + this.Checkin_CMD = @"^(签到|打卡)$"; + this.Checkin_Reward_Min = 0.01; + this.Checkin_Reward_Max = 0.05; + this.CheckinSuccessTip = @"一一一一签 到 成 功一一一一 +【获得奖励】[签到奖励] [积分名称] +【连续签到】[连续签到次数] 次 +【签到次数】[总共签到次数] 次 +【剩余积分】[剩余积分] [积分名称] +【每日语录】[每日语录]"; + this.CheckinRepeatTip = @"一一一一签 到 失 败一一一一 +每日只可以签到一次哦,不要重复签到哦!"; + this.CheckinRestrictTip = @"一一一一签 到 限 制一一一一 +您的账号活跃度不足,签到已被限制!"; + #endregion + + #region 支付宝绑定 + this.AlipaySwitch = SwitchType.关闭; + this.Alipay_ChatType = "微信"; + this.Alipay_Bind_CMD = @"^绑定\s+(?<账号>[^\s]+?)\s+(?<名称>[^\s]+?)$"; + this.CheckUserPoint_CMD = @"^(余额|积分|账单|信息|明细|个人信息)$"; + this.CheckPointSuccessTip = @"一一一一查 询 成 功一一一一 +【剩余积分】[剩余积分] [积分名称] +【累计获得】[累计积分] [积分名称] +一一一一订 单 相 关一一一一 +【多多待结】[拼多多待结算数量]笔/[拼多多待结算金额]元 +【淘宝待结】[淘宝待结算数量]笔/[淘宝待结算金额]元 +【京东待结】[京东待结算数量]笔/[京东待结算金额]元 +【唯品待结】[唯品会待结算数量]笔/[唯品会待结算金额]元 +【抖音待结】[抖音待结算数量]笔/[抖音待结算金额]元 +【苏宁待结】[苏宁待结算数量]笔/[苏宁待结算金额]元 +【待结汇总】[待结算总数数量]笔/[待结算总数金额]元 +【订单记录】[订单记录] +一一一一一一一一一一一一一 +收货后延迟2-5天,会自动给您结算!"; + this.AlipayBindSuccessTip = @"一一一一绑 定 成 功一一一一 +【姓名】[支付宝姓名] +【账号】[支付宝账号] +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"; + #endregion + + #region 初始化数据 + this.notice_robotname = "请选择(钉钉/微信群机器人API名称)"; + this.Integer_Exchange_Switch = SwitchType.关闭; + this.Audit_Exchange_Frequency_SwitchType = SwitchType.关闭; + this.Audit_Exchange_Frequency_Baseline = 2; + this.Unsettled_Forbid_Exchange = SwitchType.关闭; + this.Exchange_CMD = @"^(兑换|提现|转账)$"; + this._exchange_Num = 1L; + this._exchange_Min_Point = 1.00; + this._exchange_Max_Point = 100.00; + this.Exchange_PayType = Entitys.PayType.关闭; + this.Exchange_Transmatic_Maxpoint = 40.00; + this.Exchange_Transmatic_SumPoint = 1000.00; + this.IsEmptyPasswordUseCommercialPaySwitchType = SwitchType.关闭; + this.IsPaymentFailedUseCommercialPaySwitchType = SwitchType.关闭; + this.ExchangeFrequencyLimitDingdingTip = @"审核通知 +———— +通知事件:新用户提现 +兑换金额:[提现金额] +微信账号:[机器人账号] +微信昵称:[机器人昵称] +客户账号:[账号] +客户昵称:[昵称] +创建时间:[创建时间]"; + this.IdentityIdUnBindExchangeTip = @"一一一一提 现 失 败一一一一 +当前无法提现 +原因: +未绑定身份证请发送 【身份证 身份证号 姓名】 +例如:身份证 123456789123456789 小明 +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"; + this.IdentityIdBindUSuccessTip = @"一一一一绑 定 失 败一一一一 +【姓名】[身份证姓名] +【身份证】[身份证号码] +【失败原因】姓名和身份证不匹配 +一一一一一一一一一一一一一 +以上身份证号码不合法,请核对后重试"; + this.IdentityIdBindSuccessTip = @"一一一一绑 定 成 功一一一一 +【姓名】[身份证姓名] +【身份证】[身份证号码] +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"; + this.IdentityId_Bind_CMD = @"^身份证\s+(?<身份证号>.+?)\s+(?<姓名>.+?)$"; + this.IdentityIdCheckAppKey = string.Empty; + this.IdentityIdMatchAppKey = string.Empty; + this.IdentityIdSwitch = SwitchType.关闭; + this.Ban_Exchange_Tip = @"一一一一提 现 限 制一一一一 +您的账户被冻结 +账户冻结解除:[限制兑换时间] + +如有疑问联系管理员"; + this.Unsettled_Forbid_Exchange_Tip = @"一一一一提 现 失 败一一一一 +您未有消费记录,系统积分不予提现操作"; + this.ExchangeUnBindAlipayTip = @"一一一一兑 换 失 败一一一一 +请告诉我们您的支付宝收款账号! + +指令:绑定 支付宝账号 姓名 +例如:绑定 18100000000 张三 +一一一一一一一一一一一一一 +绑定成功后,再重新申请提现哦"; + this.ExchangeSuccessTip = @"一一一一申 请 成 功一一一一 +【申请金额】[提现金额][积分名称] +【剩余金额】[剩余积分][积分名称] +一一一一一一一一一一一一一 +客服会在24小时内处理,节假日会有延迟!"; + this.ExchangeSuccessDingdingTip = @"审核通知 +———— +兑换金额:[提现金额] +平台类型:[平台类型] +平台账号:[机器人账号] +平台昵称:[机器人昵称] +客户账号:[账号] +客户昵称:[昵称] +创建时间:[创建时间]"; + this.ExchangeErrorTip = @"一一一一兑 换 失 败一一一一 +您当前有[剩余积分][积分名称],最低[最低提现额度][积分名称]才可以提现! +待结算积分:[冻结总金额][积分名称] +未收货积分:[未收货总金额][积分名称]"; + this.ExchangeReturnTip = @"一一一一兑 换 失 败一一一一 +您申请的[兑换金额][积分名称]已退回! +原因:[备注]"; + this.ExchangeAdoptTip = @"一一一一兑 换 成 功一一一一 +您申请的[兑换金额][积分名称]已发放,请注意查收! + +Ps:如未收到,请及时给我们留言!"; + this.ExchangeInsufficientNumTip = @"一一一一兑 换 失 败一一一一 +您今日已兑换[兑换次数]次,已达到上限,请明天再兑换!"; + this.ExchangeErrorGroupBan_SwitchType = SwitchType.关闭; + this.ExchangeErrorGroupBanTip = @"一一一一兑 换 失 败一一一一 +您当前有[剩余积分][积分名称] +如需兑换请添加好友"; + this.ExchangeUntreatedTip = @"一一一一兑 换 失 败一一一一 +您有[提现金额][积分名称]正在审核,请耐心等待!"; + this.ExchangeTransmaticTip = @"一一一一兑 换 成 功一一一一 +您申请的[兑换金额][积分名称]已发放,请注意查收! + +Ps:请及时查询微信红包"; + this.ExchangeConfiscateTip = @"一一一一兑 换 失 败一一一一 +您申请的[兑换金额][积分名称]已没收! +原因:[备注]"; + this.ExchangePacketTitle = @"兑换成功:[兑换金额]"; + + this.ExchangeCommercialPayTip = @"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"; + this.ExchangeCommercialEftTip = @"一一一一商 户 转 账 成 功一一一一 +[兑换金额]兑换成功 +已直接转入您的账户!"; + #endregion + + #region 额外奖励设置 + this.Extra_Award_Switch = SwitchType.关闭; + this.Extra_Award_CMD = @"^(抢红包)$"; + this._Extra_Award_Min_Point = 1; + this._Extra_Award_Max_Point = 1.5; + this.Extra_AwardSuccessTip = @"一一一一抢 红 包 成 功一一一一 + +恭喜获得红包:[红包金额][积分名称] +当前剩余积分:[剩余积分][积分名称]"; + this.Extra_AwardErrorTip = @"一一一一抢 红 包 失 败一一一一 + +当前无抢红包机会"; + #endregion + + } + } + +} diff --git a/应用/PointManage/Entitys/checkin_list_temp.cs b/应用/PointManage/Entitys/checkin_list_temp.cs new file mode 100644 index 0000000..6ecfa63 --- /dev/null +++ b/应用/PointManage/Entitys/checkin_list_temp.cs @@ -0,0 +1,37 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PointManage.Entitys +{ + public class checkin_list_temp + { + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string username { get; set; } + /// + /// [昵称] + /// + public string usernick { get; set; } + /// + /// 签到天数 + /// + public int days { get; set; } + /// + /// 最后签到时间 + /// + public DateTime time { get; set; } + /// + /// 用户积分 + /// + public double point { get; set; } + } +} diff --git a/应用/PointManage/Entitys/exchange_info.cs b/应用/PointManage/Entitys/exchange_info.cs new file mode 100644 index 0000000..0e237f8 --- /dev/null +++ b/应用/PointManage/Entitys/exchange_info.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PointManage.Entitys +{ + public class exchange_info + { + public long uid { get; set; } + public string groupid { get; set; } + public long rid { get; set; } + } +} diff --git a/应用/PointManage/Entitys/exchange_list_temp.cs b/应用/PointManage/Entitys/exchange_list_temp.cs new file mode 100644 index 0000000..65039b4 --- /dev/null +++ b/应用/PointManage/Entitys/exchange_list_temp.cs @@ -0,0 +1,131 @@ +using Api.Framework.SDK; +using Chat.Framework.WXSdk.IPAD; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace PointManage.Entitys +{ + public class exchange_list_temp + { + /// + /// 用户fl_member_info的id + /// + [ + Browsable(false) + ] + public long id { get; set; } + /// + /// 平台类型 + /// + [ + Category("1)、平台信息"), DisplayName("平台"), ReadOnly(true), Description(@"只读:平台信息"), + ] + public ChatType chattype { get; set; } + /// + /// 用户fl_robot_info的机器人账号 robot_name + /// + [ + Category("1)、平台信息"), DisplayName("机器人账号"), ReadOnly(true), Description(@"只读:机器人账号"), + ] + public string robot_name { get; set; } + /// + /// 用户fl_robot_info的机器人昵称 nick + /// + [ + Category("1)、平台信息"), DisplayName("机器人昵称"), ReadOnly(true), Description(@"只读:机器人昵称"), + ] + public string robot_nick { get; set; } + /// + /// 用户账号 + /// + [ + Category("2)、用户信息"), DisplayName("用户账号"), ReadOnly(true), Description(@"只读:用户账号") + ] + public string username { get; set; } + /// + /// [昵称] + /// + [ + Category("2)、用户信息"), DisplayName("昵称"), ReadOnly(true), Description(@"只读:昵称") + ] + public string usernick { get; set; } + + /// + /// [昵称] + /// + [ + Category("2)、用户信息"), DisplayName("用户备注"), ReadOnly(true), Description(@"只读:用户备注") + ] + public string member_remark { get; set; } + /// + /// 支付宝账号 + /// + [ + Category("2)、用户信息"), DisplayName("支付宝账号"), ReadOnly(true), Description(@"只读:用户支付宝账号") + ] + public string alipay_num { get; set; } + /// + /// 支付宝名称 + /// + [ + Category("2)、用户信息"), DisplayName("支付宝名称"), ReadOnly(true), Description(@"只读:用户支付宝名称") + ] + public string alipay_name { get; set; } + /// + /// 身份证名称 + /// + [ + Category("2)、用户信息"), DisplayName("身份证名称"), ReadOnly(true), Description(@"只读:用户身份证名称") + ] + public string identity_name { get; set; } + /// + /// 身份证号码 + /// + [ + Category("2)、用户信息"), DisplayName("身份证号码"), ReadOnly(true), Description(@"只读:用户身份证号码") + ] + public string identity_card { get; set; } + /// + /// 兑换时间 + /// + [ + Category("2)、用户信息"), DisplayName("用户兑换时间"), ReadOnly(true), Description(@"只读:用户的兑换时间") + ] + public DateTime time { get; set; } + /// + /// 用户积分 + /// + [ + Category("2)、用户信息"), DisplayName("用户兑换积分"), ReadOnly(true), Description(@"只读:用户兑换积分") + ] + public double point { get; set; } + /// + /// 状态 + /// + [ + Category("3)、订单操作"), DisplayName("订单状态"), Description(@"设置订单状态") + ] + public ApplyType state { get; set; } + /// + /// 备注 + /// + [ + Category("3)、订单操作"), DisplayName("订单备注"), Description(@"用户兑换备注"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string remark { get; set; } + } + + //public enum PayType : ushort + //{ + // 关闭 = 0, + // 红包 = 1, + // 转账 = 2, + // 商户 = 3 + //} + +} diff --git a/应用/PointManage/Entitys/fl_plugin_pointmanage_checkin_info.cs b/应用/PointManage/Entitys/fl_plugin_pointmanage_checkin_info.cs new file mode 100644 index 0000000..d5a3fa4 --- /dev/null +++ b/应用/PointManage/Entitys/fl_plugin_pointmanage_checkin_info.cs @@ -0,0 +1,37 @@ +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PointManage.Entitys +{ + /// + /// 签到 + /// + public class fl_plugin_pointmanage_checkin_info : base_model + { + /// + /// 签到平台(用户所在平台) + /// + public ChatType chatType { get; set; } + /// + /// 用户fl_member_info的id + /// + public long uid { get; set; } + /// + /// 签到的时间 + /// + public DateTime time { get; set; } + /// + /// 签到累计的天数 + /// + public int days { get; set; } + /// + /// 总签到数 + /// + public long sumday { get; set; } + } +} diff --git a/应用/PointManage/Entitys/fl_plugin_pointmanage_exchange_list.cs b/应用/PointManage/Entitys/fl_plugin_pointmanage_exchange_list.cs new file mode 100644 index 0000000..343f2dc --- /dev/null +++ b/应用/PointManage/Entitys/fl_plugin_pointmanage_exchange_list.cs @@ -0,0 +1,46 @@ +using Api.Framework.Tools; +using Chat.Framework.WXSdk.IPAD; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PointManage.Entitys +{ + /// + /// 用户兑换类 + /// + //public class fl_plugin_pointmanage_exchange_list : base_model + //{ + // /// + // /// 用户fl_member_info的id + // /// + // public long uid { get; set; } + // /// + // /// 机器人的robot_name fl_robot_info表 + // /// + // public string robot_name { get; set; } + // /// + // /// 积分 + // /// + // public double point { get; set; } + // /// + // /// 兑换时间 + // /// + // public DateTime time { get; set; } + // /// + // /// 备注 + // /// + // public string remark { get; set; } + // /// + // /// 申请状态 + // /// + // public ApplyType state { get; set; } + // /// + // /// 是否为自动转账(之后用于计算当天自动转账金额总数) + // /// + // public bool IsTransmatic { get; set; } + //} + +} diff --git a/应用/PointManage/Entitys/fl_plugin_pointmanage_extra_award.cs b/应用/PointManage/Entitys/fl_plugin_pointmanage_extra_award.cs new file mode 100644 index 0000000..0c47284 --- /dev/null +++ b/应用/PointManage/Entitys/fl_plugin_pointmanage_extra_award.cs @@ -0,0 +1,16 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PointManage.Entitys +{ + public class fl_plugin_pointmanage_extra_award : base_model + { + public long uid { get; set; } + + public int count {get;set;} + } +} diff --git a/应用/PointManage/Entitys/pointlog_list_temp.cs b/应用/PointManage/Entitys/pointlog_list_temp.cs new file mode 100644 index 0000000..3dbb600 --- /dev/null +++ b/应用/PointManage/Entitys/pointlog_list_temp.cs @@ -0,0 +1,52 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PointManage.Entitys +{ + public class pointlog_list_temp + { + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string username { get; set; } + /// + /// 用户昵称 + /// + public string usernick { get; set; } + /// + /// 操作积分 + /// + public double point { get; set; } + /// + /// 平台类型 + /// + public string pointtype { get; set; } + /// + /// + /// + public string message { get; set; } + /// + /// + /// + public DateTime crt_time { get; set; } + + /// + /// 修改前积分 + /// + public double before_point { get; set; } + + /// + /// 修改后积分 + /// + public double after_point { get; set; } + } +} diff --git a/应用/PointManage/ExtraAward.cs b/应用/PointManage/ExtraAward.cs new file mode 100644 index 0000000..02a4dca --- /dev/null +++ b/应用/PointManage/ExtraAward.cs @@ -0,0 +1,19 @@ +using PointManage.Entitys; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PointManage +{ + public static class ExtraAward + { + public static fl_plugin_pointmanage_extra_award SaveExtraAward(this SqlSugarClient session, fl_plugin_pointmanage_extra_award award) + { + return session.Saveable(award).ExecuteReturnEntity(); + } + + } +} diff --git a/应用/PointManage/MainForm.Designer.cs b/应用/PointManage/MainForm.Designer.cs new file mode 100644 index 0000000..6f295f6 --- /dev/null +++ b/应用/PointManage/MainForm.Designer.cs @@ -0,0 +1,91 @@ +namespace PointManage +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage2; + this.xtraTabControl1.Size = new System.Drawing.Size(1120, 590); + this.xtraTabControl1.TabIndex = 8; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage2}); + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(1114, 561); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(1114, 561); + this.settingControl1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1120, 590); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + } +} \ No newline at end of file diff --git a/应用/PointManage/MainForm.cs b/应用/PointManage/MainForm.cs new file mode 100644 index 0000000..2256bc3 --- /dev/null +++ b/应用/PointManage/MainForm.cs @@ -0,0 +1,97 @@ +using Api.Framework; +using Api.Framework.Events; +using Api.Framework.Tools; +using PointManage.Properties; +using System; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace PointManage +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + this.settingControl1.Bind(Class1.Config, 215); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 窗体关闭检验签到积分是否符合规则 + /// + /// + /// + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (Class1.Config.Checkin_Reward_Min > Class1.Config.Checkin_Reward_Max) + { + ShowSuccessAutoClose("签到奖励积分:最小值不能大于最大值"); + e.Cancel = true; + } + else if (Class1.Config.Exchange_Min_Point > Class1.Config.Exchange_Max_Point) + { + ShowSuccessAutoClose("每次最低提现额度:最小值不能大于最大值"); + e.Cancel = true; + } + else if (Class1.Config.Exchange_Min_Point > Class1.Config.Exchange_Transmatic_Maxpoint) + { + ShowSuccessAutoClose("微信自动转账额度应该大于等于每次最低提现额度"); + e.Cancel = true; + } + else if (Class1.Config.Exchange_Transmatic_Maxpoint > Class1.Config.Exchange_Max_Point) + { + ShowSuccessAutoClose("微信自动转账额度应该小于等于每次最高提现额度"); + e.Cancel = true; + } + else if (Class1.Config.Extra_Award_Min_Point > Class1.Config.Extra_Award_Max_Point) + { + ShowSuccessAutoClose("结算抢红包金额:最小值不能大于最大值"); + e.Cancel = true; + } + if (!e.Cancel) + { + Util.Save(Class1.Config); + EventClient.OnEvent(this, MethodType.刷新配置文件);//刷新积分管理中的配置文件 + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} \ No newline at end of file diff --git a/应用/PointManage/MainForm.resx b/应用/PointManage/MainForm.resx new file mode 100644 index 0000000..fed81b1 --- /dev/null +++ b/应用/PointManage/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 28 + + \ No newline at end of file diff --git a/应用/PointManage/PointManage.csproj b/应用/PointManage/PointManage.csproj new file mode 100644 index 0000000..b088dcb --- /dev/null +++ b/应用/PointManage/PointManage.csproj @@ -0,0 +1,143 @@ + + + + + Debug + AnyCPU + {8ED1828E-52D2-448A-B586-537C9D45501B} + Library + Properties + PointManage + PointManage + v4.6.1 + 512 + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + MainForm.cs + Designer + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/应用/PointManage/PointManageEx.cs b/应用/PointManage/PointManageEx.cs new file mode 100644 index 0000000..5c3c486 --- /dev/null +++ b/应用/PointManage/PointManageEx.cs @@ -0,0 +1,13 @@ +using Api.Framework; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PointManage +{ + +} diff --git a/应用/PointManage/Properties/AssemblyInfo.cs b/应用/PointManage/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7980102 --- /dev/null +++ b/应用/PointManage/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("PointManage")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PointManage")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("8ed1828e-52d2-448a-b586-537c9d45501b")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/PointManage/Properties/Resources.Designer.cs b/应用/PointManage/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7db5673 --- /dev/null +++ b/应用/PointManage/Properties/Resources.Designer.cs @@ -0,0 +1,139 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace PointManage.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PointManage.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 兑换状态设置 的本地化字符串。 + /// + internal static string ExchangeStateTitle { + get { + return ResourceManager.GetString("ExchangeStateTitle", resourceCulture); + } + } + + /// + /// 查找类似 积分兑换设置 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 积分兑换 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 积分兑换插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 兑换 { + get { + object obj = ResourceManager.GetObject("兑换", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 打卡 { + get { + object obj = ResourceManager.GetObject("打卡", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 积分管理 { + get { + object obj = ResourceManager.GetObject("积分管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/PointManage/Properties/Resources.resx b/应用/PointManage/Properties/Resources.resx new file mode 100644 index 0000000..3561bf0 --- /dev/null +++ b/应用/PointManage/Properties/Resources.resx @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\打卡.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 积分兑换 + 插件名 + + + 积分兑换插件 + 插件介绍 + + + ..\Resources\积分管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\兑换.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 兑换状态设置 + 兑换状态窗体标题 + + + 积分兑换设置 + 设置主窗体标题 + + + ..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/PointManage/Properties/licenses.licx b/应用/PointManage/Properties/licenses.licx new file mode 100644 index 0000000..e69de29 diff --git a/应用/PointManage/Resources/兑换.png b/应用/PointManage/Resources/兑换.png new file mode 100644 index 0000000..ddd91a2 Binary files /dev/null and b/应用/PointManage/Resources/兑换.png differ diff --git a/应用/PointManage/Resources/基础管理.png b/应用/PointManage/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/PointManage/Resources/基础管理.png differ diff --git a/应用/PointManage/Resources/打卡.png b/应用/PointManage/Resources/打卡.png new file mode 100644 index 0000000..78e9d12 Binary files /dev/null and b/应用/PointManage/Resources/打卡.png differ diff --git a/应用/PointManage/Resources/积分管理.png b/应用/PointManage/Resources/积分管理.png new file mode 100644 index 0000000..27a856f Binary files /dev/null and b/应用/PointManage/Resources/积分管理.png differ diff --git a/应用/ProductClient/Class1.cs b/应用/ProductClient/Class1.cs new file mode 100644 index 0000000..5f37a71 --- /dev/null +++ b/应用/ProductClient/Class1.cs @@ -0,0 +1,85 @@ +using Api.Framework; +using Api.Framework.SDK; +using ProductClient.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProductClient +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = "爆单-代运营"; + this.Note = "专业的运营团队、代运营朋友圈、直播群!"; + this.Logo = Resources.爆单; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + //if (!session.TableExist<>()) + //{ + // session.CreateTable<>(); + // session.AddIndex<>(""); + //} + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + + var thread = TimerTask.NewTimer(60) as MonitorThread; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.Activate(); + } + catch (Exception ex) + { + this.OnLog("执行时被" + ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/ProductClient/Config.cs b/应用/ProductClient/Config.cs new file mode 100644 index 0000000..b453484 --- /dev/null +++ b/应用/ProductClient/Config.cs @@ -0,0 +1,79 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Api.Framework.ApiClient; + +namespace ProductClient +{ + [Config(Name = "插件-爆单-代运营-配置")] + public class Config + { + /// + /// 任务id,最后请求任务的Id + /// + public long SignId { get; set; } + + public QrImageType qrImageType { get; set; } + + public DwzType dwzType { get; set; } + + public string tbPid { get; set; } + + public string pddPid { get; set; } + + public string jdPid { get; set; } + + /// + /// 活动链接 + /// + public string actionLink { get; set; } + + /// + /// 监听时间间隔 + /// + public int Monitor_Interval { get; set; } + + /// + /// 记录最后发送时间 + /// + public DateTime LastSendTime { get; set; } + + /// + /// 历史发送过的订单 + /// + public List historyId { get; set; } + + /// + /// 评语以淘口令显示 + /// + public bool isPyTkl { get; set; } + + /// + /// 是否评论 + /// + public bool isPl { get; set; } + + /// + /// 追加自定义评语 + /// + public string appendComment { get; set; } + + public Config() + { + SignId = 0; + qrImageType = QrImageType.模板A; + dwzType = DwzType.不缩短域名; + Monitor_Interval = 0; + LastSendTime = DateTime.MinValue; + historyId = new List(); + isPyTkl = false; + isPl = false; + appendComment = string.Empty; + } + + } +} diff --git a/应用/ProductClient/Entitys/GoodsResp.cs b/应用/ProductClient/Entitys/GoodsResp.cs new file mode 100644 index 0000000..9ad7c06 --- /dev/null +++ b/应用/ProductClient/Entitys/GoodsResp.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProductClient.Entitys +{ + /// + /// 数据明细 + /// + public class GoodsResp + { + /// + /// 品牌code + /// + public string brandCode { get; set; } + /// + /// 品牌名 + /// + public string brandName { get; set; } + /// + /// 类目信息 + /// + //public List categoryInfo { get; set; } + public Dictionary categoryInfo { get; set; } + /// + /// 评论数 + /// + public long comments { get; set; } + /// + /// 佣金信息 + /// + //public List commissionInfo { get; set; } + public Dictionary commissionInfo { get; set; } + /// + /// 优惠券信息,返回内容为空说明该SKU无可用优惠券 + /// + //public List couponInfo { get; set; } + public Dictionary couponInfo { get; set; } + /// + /// 商品好评率 + /// + public double goodCommentsShare { get; set; } + /// + /// 图片信息 + /// + //public List imageInfo { get; set; } + public Dictionary imageInfo { get; set; } + /// + /// 30天支出佣金 + /// + public double inOrderComm30Days { get; set; } + /// + /// 30天引单量 + /// + public long inOrderCount30Days { get; set; } + /// + /// 是否爆款,1:是,0:否 + /// + public int isHot { get; set; } + /// + /// 是否自营 (1 : 是, 0 : 否),后续会废弃,请用owner + /// + public int isJdSale { get; set; } + /// + /// 商品落地页 + /// + public string materialUrl { get; set; } + /// + /// g=自营,p=pop + /// + public string owner { get; set; } + /// + /// 拼购信息 + /// + //public List pinGouInfo { get; set; } + public Dictionary pinGouInfo { get; set; } + /// + /// 已废弃,请使用pinGouInfo + /// + //public List pingGouInfo { get; set; } + public Dictionary pingGouInfo { get; set; } + /// + /// 价格信息 + /// + //public List priceInfo { get; set; } + public Dictionary priceInfo { get; set; } + /// + /// 店铺信息 + /// + //public List shopInfo { get; set; } + public Dictionary shopInfo { get; set; } + /// + /// 商品ID + /// + public long skuId { get; set; } + /// + /// 商品名称 + /// + public string skuName { get; set; } + /// + /// spuid,其值为同款商品的主skuid + /// + public long spuid { get; set; } + } +} diff --git a/应用/ProductClient/Entitys/goodInfo_temp.cs b/应用/ProductClient/Entitys/goodInfo_temp.cs new file mode 100644 index 0000000..3988cee --- /dev/null +++ b/应用/ProductClient/Entitys/goodInfo_temp.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProductClient.Entitys +{ + public class goodInfo_temp + { + /// + /// 返回码 + /// + public int code { get; set; } + /// + /// 数据明细 + /// + //public List data { get; set; } + public ArrayList data { get; set; } + /// + /// 返回消息 + /// + public string message { get; set; } + /// + /// + /// + public string requestId { get; set; } + /// + /// 有效商品总数量,上限10w + /// + public long totalCount { get; set; } + } +} diff --git a/应用/ProductClient/MainForm.Designer.cs b/应用/ProductClient/MainForm.Designer.cs new file mode 100644 index 0000000..4e103c7 --- /dev/null +++ b/应用/ProductClient/MainForm.Designer.cs @@ -0,0 +1,477 @@ +namespace ProductClient +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.label3 = new System.Windows.Forms.Label(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.hyperlinkLabelControl_3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.hyperlinkLabelControl_1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl_2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.hyperlinkLabelControl2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.label2 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(584, 435); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(582, 409); + this.xtraTabPage1.Text = " 公 告 "; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Tahoma", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(72, 68); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(428, 221); + this.label1.TabIndex = 0; + this.label1.Text = "内容包含:\r\n\r\n--内容运营:每日早报、每日晚报、每日电影推荐\r\n\r\n--爆款精选:人工精选爆款、精编朋友圈文案\r\n\r\n--选品策略:秒杀单、爆款单、过夜单、0" + + "元购等等\r\n\r\n带你节省人力物力,提升产出、增加用户粘度\r\n\r\n公司安排资深选品专员,资深文案写手,携手大家一起达到人生巅峰\r\n\r\n多位百万大牛测试数据:跟我们" + + "做朋友圈运营产出提升50%+"; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.label3); + this.xtraTabPage2.Controls.Add(this.checkBox2); + this.xtraTabPage2.Controls.Add(this.memoEdit1); + this.xtraTabPage2.Controls.Add(this.checkBox1); + this.xtraTabPage2.Controls.Add(this.comboBoxEdit2); + this.xtraTabPage2.Controls.Add(this.labelControl8); + this.xtraTabPage2.Controls.Add(this.labelControl7); + this.xtraTabPage2.Controls.Add(this.labelControl6); + this.xtraTabPage2.Controls.Add(this.numericUpDown1); + this.xtraTabPage2.Controls.Add(this.comboBoxEdit1); + this.xtraTabPage2.Controls.Add(this.labelControl9); + this.xtraTabPage2.Controls.Add(this.labelControl5); + this.xtraTabPage2.Controls.Add(this.labelControl4); + this.xtraTabPage2.Controls.Add(this.textEdit4); + this.xtraTabPage2.Controls.Add(this.textEdit3); + this.xtraTabPage2.Controls.Add(this.textEdit2); + this.xtraTabPage2.Controls.Add(this.textEdit1); + this.xtraTabPage2.Controls.Add(this.hyperlinkLabelControl_3); + this.xtraTabPage2.Controls.Add(this.hyperlinkLabelControl3); + this.xtraTabPage2.Controls.Add(this.labelControl10); + this.xtraTabPage2.Controls.Add(this.hyperlinkLabelControl_1); + this.xtraTabPage2.Controls.Add(this.labelControl3); + this.xtraTabPage2.Controls.Add(this.hyperlinkLabelControl1); + this.xtraTabPage2.Controls.Add(this.hyperlinkLabelControl_2); + this.xtraTabPage2.Controls.Add(this.labelControl2); + this.xtraTabPage2.Controls.Add(this.hyperlinkLabelControl2); + this.xtraTabPage2.Controls.Add(this.labelControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(582, 409); + this.xtraTabPage2.Text = " 朋 友 圈 代 运 营 "; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.ForeColor = System.Drawing.Color.Red; + this.label3.Location = new System.Drawing.Point(165, 354); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(211, 42); + this.label3.TabIndex = 25; + this.label3.Text = "变量:[活动口令]\r\n注:可用于双十一、双十二红包活动等\r\n支持朋友圈内容、评语"; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(330, 198); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(74, 18); + this.checkBox2.TabIndex = 23; + this.checkBox2.Text = "不发评论"; + this.checkBox2.UseVisualStyleBackColor = true; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(159, 222); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(245, 83); + this.memoEdit1.TabIndex = 22; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(159, 198); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(158, 18); + this.checkBox1.TabIndex = 21; + this.checkBox1.Text = "淘宝商品评语使用淘口令"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.EditValue = ""; + this.comboBoxEdit2.Location = new System.Drawing.Point(159, 42); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(245, 20); + this.comboBoxEdit2.TabIndex = 20; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(66, 48); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(72, 14); + this.labelControl8.TabIndex = 19; + this.labelControl8.Text = "淘宝短网址:"; + // + // labelControl7 + // + this.labelControl7.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl7.Appearance.Options.UseForeColor = true; + this.labelControl7.Location = new System.Drawing.Point(358, 174); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(109, 14); + this.labelControl7.TabIndex = 18; + this.labelControl7.Text = "[ 注:为0时不限制 ]"; + // + // labelControl6 + // + this.labelControl6.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl6.Appearance.Options.UseForeColor = true; + this.labelControl6.Location = new System.Drawing.Point(278, 174); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(63, 14); + this.labelControl6.TabIndex = 18; + this.labelControl6.Text = "(单位/分钟)"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(159, 170); + this.numericUpDown1.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(111, 22); + this.numericUpDown1.TabIndex = 17; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.EditValue = "模板A"; + this.comboBoxEdit1.Location = new System.Drawing.Point(159, 138); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "模板A", + "模板B", + "模板C"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(245, 20); + this.comboBoxEdit1.TabIndex = 16; + // + // labelControl9 + // + this.labelControl9.Location = new System.Drawing.Point(54, 223); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(84, 14); + this.labelControl9.TabIndex = 15; + this.labelControl9.Text = "宝贝评语追加:"; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(54, 174); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(84, 14); + this.labelControl5.TabIndex = 15; + this.labelControl5.Text = "宝贝发送间隔:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(66, 141); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(72, 14); + this.labelControl4.TabIndex = 15; + this.labelControl4.Text = "优惠券模板:"; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(159, 322); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(245, 20); + this.textEdit4.TabIndex = 14; + this.textEdit4.Leave += new System.EventHandler(this.textEdit_Leave); + // + // textEdit3 + // + this.textEdit3.Location = new System.Drawing.Point(159, 105); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Size = new System.Drawing.Size(245, 20); + this.textEdit3.TabIndex = 14; + this.textEdit3.Leave += new System.EventHandler(this.textEdit_Leave); + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(159, 75); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(245, 20); + this.textEdit2.TabIndex = 14; + this.textEdit2.Leave += new System.EventHandler(this.textEdit_Leave); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(159, 15); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(245, 20); + this.textEdit1.TabIndex = 14; + this.textEdit1.Leave += new System.EventHandler(this.textEdit_Leave); + // + // hyperlinkLabelControl_3 + // + this.hyperlinkLabelControl_3.Location = new System.Drawing.Point(487, 108); + this.hyperlinkLabelControl_3.Name = "hyperlinkLabelControl_3"; + this.hyperlinkLabelControl_3.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl_3.TabIndex = 8; + this.hyperlinkLabelControl_3.Text = "删除推广位"; + this.hyperlinkLabelControl_3.Click += new System.EventHandler(this.hyperlinkLabelControl_Click_1); + // + // hyperlinkLabelControl3 + // + this.hyperlinkLabelControl3.Location = new System.Drawing.Point(413, 108); + this.hyperlinkLabelControl3.Name = "hyperlinkLabelControl3"; + this.hyperlinkLabelControl3.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl3.TabIndex = 8; + this.hyperlinkLabelControl3.Text = "选择推广位"; + this.hyperlinkLabelControl3.Click += new System.EventHandler(this.hyperlinkLabelControl_Click); + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(54, 325); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(84, 14); + this.labelControl10.TabIndex = 11; + this.labelControl10.Text = "活动口令内容:"; + // + // hyperlinkLabelControl_1 + // + this.hyperlinkLabelControl_1.Location = new System.Drawing.Point(487, 18); + this.hyperlinkLabelControl_1.Name = "hyperlinkLabelControl_1"; + this.hyperlinkLabelControl_1.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl_1.TabIndex = 9; + this.hyperlinkLabelControl_1.Text = "删除推广位"; + this.hyperlinkLabelControl_1.Click += new System.EventHandler(this.hyperlinkLabelControl_Click_1); + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(66, 108); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(72, 14); + this.labelControl3.TabIndex = 11; + this.labelControl3.Text = "京东推广位:"; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(413, 18); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl1.TabIndex = 9; + this.hyperlinkLabelControl1.Text = "选择推广位"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl_Click); + // + // hyperlinkLabelControl_2 + // + this.hyperlinkLabelControl_2.Location = new System.Drawing.Point(487, 78); + this.hyperlinkLabelControl_2.Name = "hyperlinkLabelControl_2"; + this.hyperlinkLabelControl_2.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl_2.TabIndex = 10; + this.hyperlinkLabelControl_2.Text = "删除推广位"; + this.hyperlinkLabelControl_2.Click += new System.EventHandler(this.hyperlinkLabelControl_Click_1); + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(54, 78); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(84, 14); + this.labelControl2.TabIndex = 12; + this.labelControl2.Text = "拼多多推广位:"; + // + // hyperlinkLabelControl2 + // + this.hyperlinkLabelControl2.Location = new System.Drawing.Point(413, 78); + this.hyperlinkLabelControl2.Name = "hyperlinkLabelControl2"; + this.hyperlinkLabelControl2.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl2.TabIndex = 10; + this.hyperlinkLabelControl2.Text = "选择推广位"; + this.hyperlinkLabelControl2.Click += new System.EventHandler(this.hyperlinkLabelControl_Click); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(66, 18); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(72, 14); + this.labelControl1.TabIndex = 13; + this.labelControl1.Text = "淘宝推广位:"; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.label2); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.PageEnabled = false; + this.xtraTabPage3.Size = new System.Drawing.Size(582, 409); + this.xtraTabPage3.Text = " 微 信 群 产 品 直 播 "; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("Tahoma", 42F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.ForeColor = System.Drawing.Color.Gray; + this.label2.Location = new System.Drawing.Point(95, 74); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(248, 68); + this.label2.TabIndex = 0; + this.label2.Text = "内测中..."; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(584, 435); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "爆单 - 代运营"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraTabPage3.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.TextEdit textEdit3; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.LabelControl labelControl5; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private System.Windows.Forms.CheckBox checkBox1; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl_3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl_1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl_2; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.LabelControl labelControl10; + } +} \ No newline at end of file diff --git a/应用/ProductClient/MainForm.cs b/应用/ProductClient/MainForm.cs new file mode 100644 index 0000000..12164ba --- /dev/null +++ b/应用/ProductClient/MainForm.cs @@ -0,0 +1,213 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using ProductClient.Properties; +using System; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using UI.Framework.Forms; +using static Api.Framework.ApiClient; + +namespace ProductClient +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + textEdit1.Text = Class1.Config.tbPid; + textEdit2.Text = Class1.Config.pddPid; + textEdit3.Text = Class1.Config.jdPid; + textEdit4.Text = Class1.Config.actionLink; + numericUpDown1.Value = Class1.Config.Monitor_Interval; + checkBox1.Checked = Class1.Config.isPyTkl; + checkBox2.Checked = Class1.Config.isPl; + + this.comboBoxEdit2.Properties.Items.AddRange(Enum.GetNames(typeof(DwzType))); + comboBoxEdit2.SelectedIndex = (int)Class1.Config.dwzType; + + comboBoxEdit1.SelectedIndex = (int)Class1.Config.qrImageType; + + memoEdit1.Text = Class1.Config.appendComment; + + } + + private void hyperlinkLabelControl_Click(object sender, EventArgs e) + { + try + { + var label = sender as HyperlinkLabelControl; + if (label == null) return; + var session = ApiClient.GetSession(); + var cps = (CpsType)Enum.ToObject(typeof(CpsType), int.Parse(label.Name.ToLower().Replace("hyperlinklabelcontrol", ""))); + switch (cps) + { + case CpsType.阿里妈妈: + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + textEdit1.Text = tgw.Pid; + Class1.Config.tbPid = tgw.Pid; + } + } + break; + case CpsType.多多进宝: + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.多多进宝); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + textEdit2.Text = tgw.Pid; + Class1.Config.pddPid = tgw.Pid; + } + } + break; + case CpsType.京东联盟: + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.京东联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + textEdit3.Text = tgw.Pid + "_" + tgw.Member.username; + Class1.Config.jdPid = textEdit3.Text; + } + } + break; + default: + break; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + comboBoxEdit1.Focus(); + Class1.Config.qrImageType = (QrImageType)comboBoxEdit1.SelectedIndex; + Class1.Config.Monitor_Interval = (int)numericUpDown1.Value; + Class1.Config.dwzType = (DwzType)comboBoxEdit2.SelectedIndex; + Class1.Config.isPyTkl = checkBox1.Checked; + Class1.Config.isPl = checkBox2.Checked; + Class1.Config.appendComment = memoEdit1.Text; + Class1.Config.actionLink = textEdit4.Text; + Util.Save(Class1.Config); + } + + private void textEdit_Leave(object sender, EventArgs e) + { + try + { + var text = sender as TextEdit; + if (text == null) return; + var session = ApiClient.GetSession(); + var cps = (CpsType)Enum.ToObject(typeof(CpsType), int.Parse(text.Name.ToLower().Replace("textedit", ""))); + switch (cps) + { + case CpsType.阿里妈妈: + { + //mm_28592081_118450408_105567700447 + var pidstr = text.Text.Trim(); + if (!string.IsNullOrWhiteSpace(pidstr)) + { + var reg = Regex.Match(pidstr, @"mm_(?\d+)_(?\d+)_(?\d+)"); + if (reg.Success) + Class1.Config.tbPid = pidstr; + } + } + break; + case CpsType.多多进宝: + { + //1929015_26838864 + var pidstr = text.Text.Trim(); + if (!string.IsNullOrWhiteSpace(pidstr)) + { + var reg = Regex.Match(pidstr, @"(?\d+)_(\d+)"); + if (reg.Success) + Class1.Config.pddPid = pidstr; + } + } + break; + case CpsType.京东联盟: + { + //1000858402_0_1843753459_xxxxxxxxxxxxxxxxxxxxxxxxx + var pidstr = text.Text.Trim(); + if (!string.IsNullOrWhiteSpace(pidstr)) + { + var reg = Regex.Match(pidstr, @"(?(?\d+)_\d+_\d+)_(?.+)"); + if (reg.Success) + Class1.Config.jdPid = pidstr; + } + } + break; + default: + break; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void hyperlinkLabelControl_Click_1(object sender, EventArgs e) + { + try + { + var label = sender as HyperlinkLabelControl; + if (label == null) return; + var cps = (CpsType)Enum.ToObject(typeof(CpsType), int.Parse(label.Name.ToLower().Replace("hyperlinklabelcontrol_", ""))); + switch (cps) + { + case CpsType.阿里妈妈: + { + textEdit1.Text = Class1.Config.tbPid = string.Empty; + } + break; + case CpsType.多多进宝: + textEdit2.Text = Class1.Config.pddPid = string.Empty; + break; + case CpsType.京东联盟: + textEdit3.Text = Class1.Config.jdPid = string.Empty; + break; + default: + break; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/ProductClient/MainForm.resx b/应用/ProductClient/MainForm.resx new file mode 100644 index 0000000..4978d88 --- /dev/null +++ b/应用/ProductClient/MainForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 60 + + \ No newline at end of file diff --git a/应用/ProductClient/MonitorThread.cs b/应用/ProductClient/MonitorThread.cs new file mode 100644 index 0000000..a84510e --- /dev/null +++ b/应用/ProductClient/MonitorThread.cs @@ -0,0 +1,571 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using ProductClient.Entitys; +using ProductClient.Properties; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using static Api.Framework.Tools.TBHelper.TbAnalysis; + +namespace ProductClient +{ + class MonitorThread : TimerTask + { + private long count; + private bool IsRun = false; + + public override void Run(object state, bool timedOut) + { + try + { + count++; + + #region web接口检测 + if (count % 5 == 0) + { + if (IsRun) return; + IsRun = true; + try + { + var http = new HttpHelper(); + //http://item.sync.api.52cmg.cn/task.do?method=getCircle&lastId=@lastid&r=@r + var text = string.Empty; + Dictionary result = null; + try + { + if (Class1.Config.historyId.Count >= 100) + { + Class1.Config.historyId.RemoveRange(0, Class1.Config.historyId.Count - 20); + Util.Save(Class1.Config); + } + if (!Class1.Config.historyId.Contains(Class1.Config.SignId)) + { + text = http.GetHtml(HttpExtend.GetItem(http, Resources.ProductApi.Replace("@lastid", Class1.Config.SignId.ToString()).Replace("@r", HttpExtend.GetTimeStamp()))).Html; + result = HttpExtend.JsonToDictionary(text); + } + } + catch (Exception) + { + return; + } + + if (result != null && result.ContainsKey("Code")) + { + var code = result["Code"].ToString(); + //if (code == "-1") return; + //正常数据 + if (code == "0") + { + //检测是否在线 + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList().Where(f => (f.WeixinType == WeixinType.Grpc微信 || f.WeixinType == WeixinType.Hook微信) && f.Status == WxStatus.在线).ToList(); + if (clients.Count == 0) return; + + if (result.ContainsKey("Message")) + { + + var message = result["Message"] as Dictionary; + + if (message.ContainsKey("lastId")) + { + Class1.Config.historyId.Add(Class1.Config.SignId); + Class1.Config.SignId = long.Parse(message["lastId"].ToString()); + Util.Save(Class1.Config); + } + + string convertLink = string.Empty; //转链后 + string compositeQRCode = string.Empty;//合成的二维码图片 + + string objectDesc = string.Empty; //正文 + string comment = string.Empty; //评语 + + string quanUrl = string.Empty; //券链接 + string itemUrl = string.Empty; //商品连接 + var appendQrcode = false; //是否合成优惠券图片 + CpsType cps = CpsType.京东联盟; + + #region 获取正文内容并删除正文中的地址 + if (message.ContainsKey("circle")) + { + objectDesc = message["circle"].ToString();//主内容部分 + if (string.IsNullOrWhiteSpace(objectDesc)) + { + EventClient.OnEvent(this, $"未检测到要转发的正文数据,操作终止"); + return; + } + //处理用户朋友圈中的地址信息(有就删除) + var reg = Regex.Match(objectDesc, @"(?<地址信息>\)"); + if (reg.Success) + objectDesc = objectDesc.Replace(reg.Groups["地址信息"].Value, string.Empty); + } + #endregion + + #region 获取评语 + if (message.ContainsKey("comment")) + comment = message["comment"].ToString(); //评论内容 + #endregion + + var isItem = message.ContainsKey("isItem") && message["isItem"].ToString().ToLower() == "true"; //是否为商品 + //为商品获取去商品连接和优惠券链接 + if (isItem) + { + if (Class1.Config.Monitor_Interval != 0) + { + if (Class1.Config.LastSendTime == DateTime.MinValue || (Class1.Config.LastSendTime.AddMinutes(Class1.Config.Monitor_Interval) <= DateTime.Now)) + { + + } + else + return; + } + + appendQrcode = message.ContainsKey("appendQrcode") && message["appendQrcode"].ToString().ToLower() == "true"; + if (message.ContainsKey("itemUrl"))//获取宝贝连接 + itemUrl = message["itemUrl"].ToString(); + if (message.ContainsKey("quanUrl"))//获取优惠券链接 + quanUrl = message["quanUrl"].ToString(); + } + else + { + Class1.Config.LastSendTime = DateTime.MinValue; + } + + #region 评语不为空,判断评语中是否包含变量 + if (isItem && (appendQrcode || (!string.IsNullOrWhiteSpace(comment) && comment.Contains(Resources.BuyAddress)) || !string.IsNullOrWhiteSpace(comment))) + { + bool isTB = false; + try + { + convertLink = AlimamaConvertLink(itemUrl, quanUrl, appendQrcode, out compositeQRCode);//阿里妈妈 + isTB = true; + } + catch (Exception ex) + { + if (!ex.Message.StartsWith("@")) throw ex; + try + { + convertLink = PinDuoDuoConvertLink(itemUrl, appendQrcode, out compositeQRCode);//多多进宝 + } + catch (Exception ex_) + { + if (!ex_.Message.StartsWith("@")) throw ex_; + try + { + convertLink = JingDongConvertLink(itemUrl, appendQrcode, out compositeQRCode);//京东联盟 + } + catch (Exception) + { } + } + } + + if (string.IsNullOrWhiteSpace(convertLink)) return; + + //处理转链,替换变量 + { + #region 朋友圈内容中追加图片 + if (!string.IsNullOrWhiteSpace(compositeQRCode)) + { + StringBuilder sb = new StringBuilder(); + sb.Append(""); + sb.Append("" + Tools.GenerateRandomCode(20) + ""); + sb.Append("2"); + sb.Append(""); + sb.Append(""); + sb.Append("0"); + sb.Append("[图片=" + compositeQRCode + "]"); + sb.Append("[图片=" + compositeQRCode + "]"); + sb.Append(""); + sb.Append(""); + + var index = objectDesc.IndexOf(""); + if (index != -1) + objectDesc = objectDesc.Insert(index, sb.ToString()); + } + #endregion + + string address = string.Copy(convertLink); + if (isTB == true && !Class1.Config.isPyTkl && comment.Contains(Resources.BuyAddress)) + { + convertLink = ZJYUrl; + } + comment = comment.Replace(Resources.BuyAddress, convertLink).Replace(Resources.TKLBuyAddress, address); + } + } + #endregion + + _ExecuteSend(objectDesc, comment); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"代运营朋友圈 - web接口:{ex.Message}"); + } + finally + { + IsRun = false; + } + } + #endregion + + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"代运营朋友圈:{ex.Message}\r\n{ex.StackTrace}"); + } + } + + private string ZJYUrl = string.Empty; + + /// + /// 阿里妈妈转连接 + /// + /// + private string AlimamaConvertLink(string itemUrl, string quanUrl, bool appendQrcode, out string compositeQRCode) + { + compositeQRCode = string.Empty; + ZJYUrl = string.Empty; + var session = ApiClient.GetSession(); + if (string.IsNullOrWhiteSpace(Class1.Config.tbPid)) throw new Exception("@未设置淘宝推广位,终止操作"); + var reg = Regex.Match(Class1.Config.tbPid, @"mm_(?\d+)_(?\d+)_(?\d+)"); + if (!reg.Success) throw new Exception($@"阿里妈妈推广位格式不正确"); + var cpsname = reg.Groups["cpsname"].Value; + var pid1 = reg.Groups["pid1"].Value; + var pid2 = reg.Groups["pid2"].Value; + + var cps = new fl_cps_member() { username = cpsname, cpstype = CpsType.阿里妈妈, cookies = string.Empty, is_download = SwitchType.关闭, abnormal_tip = SwitchType.关闭, online = true, usernick = string.Empty }; + AlimamaApi api = CpsClient.CreateAlimamaRequest(cps); + if (api == null) throw new Exception("@创建阿里妈妈API请求失败,终止操作"); + var tbAnalysis = new TBHelper.TbAnalysis(); + var item_id = string.Empty; + try + { + item_id = tbAnalysis.FindItemIdByUrlAndTklAndMkl(itemUrl, api, Class1.Config.tbPid.Split('_')); + } + catch (Exception) + { + throw new Exception($"@解析淘宝商品Id失败:{itemUrl}"); + } + //标题搜索和商品id搜索 + if (string.IsNullOrEmpty(item_id)) throw new Exception($"@解析淘宝商品Id失败:{itemUrl}"); + + var title = string.Empty;//商品标题 + + #region 检测连接中是否包含优惠券信息 + var activityId = string.Empty; + if (quanUrl.Contains("uland.taobao")) + { + var _reg = Regex.Match(quanUrl, @"activityId=(?<活动ID>[A-Za-z0-9]+)"); + if (_reg.Success) activityId = _reg.Groups["活动ID"].Value; + } + #endregion + + var turnItem = api.TurnItemId(item_id, activityId, pid2, pid1, "2", "", true); + + //淘口令的前/后符号有没有设置.有设置将替换掉 + var tkl = tbAnalysis.ReplaceTklModifier(turnItem.BuyPass); + + ZJYUrl = api.ComposeTbClick(item_id, turnItem.ImageUrl, tkl, turnItem.BuyUrl, true, Class1.Config.tbPid, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品, (int)Class1.Config.dwzType, isCircleZjy: true); + if (string.IsNullOrWhiteSpace(ZJYUrl)) throw new Exception("生成防屏蔽连接为空,终止操作"); + if (appendQrcode) + { + compositeQRCode = ApiClient.GetQRImage(title, turnItem.Price.ToString("0.00"), turnItem.CouponPrice.ToString("0"), turnItem.UseCouponPrice.ToString("0.00"), turnItem.ImageUrl, ZJYUrl, Class1.Config.qrImageType); + } + + return tkl; + } + + /// + /// 多多进宝转连接 + /// + /// + private string PinDuoDuoConvertLink(string itemUrl, bool appendQrcode, out string compositeQRCode) + { + var goods_id = PDDHelper.GetPddGoodsID(itemUrl); + if (string.IsNullOrWhiteSpace(goods_id)) throw new Exception("@解析拼多多商品Id失败,操作终止"); + var session = ApiClient.GetSession(); + + if (string.IsNullOrWhiteSpace(Class1.Config.pddPid)) throw new Exception("未设置拼多多推广位,终止操作"); + var reg = Regex.Match(Class1.Config.pddPid, @"(?\d+)_(\d+)"); + if (!reg.Success) throw new Exception("拼多多推广位不符合格式,终止操作"); + var cpsname = reg.Groups["cpsname"].ToString(); + var adzone_pid = Class1.Config.pddPid; + + var cps = new fl_cps_member() { username = cpsname, usernick = string.Empty, cookies = string.Empty, cpstype = CpsType.多多进宝, abnormal_tip = SwitchType.关闭, is_download = SwitchType.关闭, online = true }; + + PinduoduoApi api = CpsClient.CreatePinduoduoRequest(cps); + + if (api == null) throw new Exception("创建多多进宝API请求失败,终止操作"); + + ArrayList goods_details = null; + + var isBind = false; + var result = api.SendPinduoduo("pdd.ddk.oauth.member.authority.query", new { pid = adzone_pid }); + if (result.ContainsKey("authority_query_response")) + { + var authority_query_response = result["authority_query_response"] as Dictionary; + if (authority_query_response != null && authority_query_response.Count != 0) + isBind = int.Parse(authority_query_response["bind"].ToString()) == 1;//1-已绑定;0-未绑定 + } + + goods_details = PDDHelper.FindSendGuideGoodsInfo(api, adzone_pid, goods_id, isBind); + + + //没有查到返利提示 + if (goods_details == null || goods_details.Count == 0) + throw new Exception("该商品无返利,操作终止"); + + foreach (var item in goods_details) + { + var temp = item as Dictionary; + + string mall_id = string.Empty; + if (temp.ContainsKey("mall_id")) mall_id = temp["mall_id"].ToString(); + + var goods_sign = temp["goods_sign"].ToString(); + + var goods_name = (temp["goods_name"] ?? string.Empty).ToString().Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); //获取商品标签 + var goods_desc = (temp["goods_desc"] ?? string.Empty).ToString(); //商品描述 + var goods_thumbnail_url = (temp["goods_thumbnail_url"] ?? string.Empty).ToString(); //商品主图 + + var min_group_price = Math.Round(temp["min_group_price"] == null ? 0 : (double.Parse(temp["min_group_price"].ToString()) / 100.00), 2); //最低价sku的拼团价,单位为分 + //var min_normal_price = Math.Round(temp["min_normal_price"] == null ? 0 : (double.Parse(temp["min_normal_price"].ToString()) / 100.00), 2); //最低价sku的单买价,单位为分 + + var _coupon_discount = double.Parse((temp["coupon_discount"] ?? 0).ToString()); + var coupon_discount = _coupon_discount == 0 ? 0 : Math.Round(_coupon_discount / 100.00, 2); //优惠券面额,单位为分 + + var pddHelper = new PDDHelper(); + + var manyShoppingUrl = pddHelper.GetShoppingUrl(api, new { p_id = adzone_pid, goods_sign_list = $"[\"{goods_sign}\"]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, force_duo_id = true, generate_authority_url = !isBind, generate_schema_url = true }); + + if (appendQrcode) + compositeQRCode = ApiClient.GetQRImage(goods_name, min_group_price.ToString(), coupon_discount.ToString(), ((decimal)min_group_price - (decimal)coupon_discount).ToString(), goods_thumbnail_url, manyShoppingUrl, Class1.Config.qrImageType, CpsType.多多进宝, goods_desc); + else compositeQRCode = string.Empty; + return manyShoppingUrl; + } + + //EventClient.OnEvent(this, $"朋友圈代运营拼多多转链异常:{ex.Message} - {ex.StackTrace}"); + + compositeQRCode = string.Empty; + return string.Empty; + } + + /// + /// 京东联盟转连接 + /// + /// + private string JingDongConvertLink(string itemUrl, bool appendQrcode, out string compositeQRCode) + { + var itemId = JDHelper.GetJingdongItemId(itemUrl);//匹配京东链接获取京东宝贝ID + if (string.IsNullOrEmpty(itemId)) throw new Exception($"@解析京东商品Id失败:{itemUrl}"); + + var session = ApiClient.GetSession(); + //var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.custom_type == Resources.SoftwareType && f.alliance_id == (int)CpsType.京东联盟); + //if (adzone == null) throw new Exception("未设置京东推广位,终止操作"); + if (string.IsNullOrWhiteSpace(Class1.Config.jdPid)) throw new Exception("未设置京东推广位,终止操作"); + var reg = Regex.Match(Class1.Config.jdPid, @"(?(?\d+)_\d+_(?\d+))_(?.+)"); + if (!reg.Success) throw new Exception("推广位格式不正确"); + var cpsname = reg.Groups["cpsname"].ToString(); + var key = reg.Groups["key"].ToString(); + //var pid = reg.Groups["pid"].ToString(); + var positionId = reg.Groups["positionId"].ToString(); + + var cps = new fl_cps_member() { username = key, usernick = cpsname, cpstype = CpsType.京东联盟, online = true, cookies = string.Empty, abnormal_tip = SwitchType.关闭, is_download = SwitchType.关闭 }; + + //var cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟 && f.username == adzone.adzone_pid_cps_name); + //if (cps == null) throw new Exception("京东账号异常,终止操作"); + var api = new JingdongApi(cps); + if (api == null) throw new Exception("创建京东联盟API请求失败,终止操作"); + + var goodInfoResult = api.SendJingdong("jd.union.open.goods.query", new { goodsReqDTO = new { skuIds = new string[] { itemId } } }); + + var goodData = goodInfoResult.ConvertToObj(); + if (goodData.data == null) throw new Exception("京东无返利信息"); + + foreach (Dictionary _goodinfo in goodData.data) + { + var goodinfo = _goodinfo.ConvertToObj(); + goodinfo.skuName = goodinfo.skuName.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); + + if (goodinfo.commissionInfo.Count != 0)//有佣金 + { + var isJdSale = goodinfo.isJdSale == 0 ? false : true;//是否已是京东自营 + + double price = double.Parse(goodinfo.priceInfo["price"].ToString()); //商品价格 + + var commissionshare = decimal.Parse(goodinfo.commissionInfo["commissionShare"].ToString()) / 100m;//普通用户佣金比例 ,通用接口中的佣金比例 + + #region 这里主要是获取改商品的实际佣金比例,上面的佣金比例是通用的佣金比例,会不准一些 + try + { + var goodResult = api.SendJingdong("jd.union.open.goods.promotiongoodsinfo.query", new { skuIds = itemId }); + if (goodResult != null && goodResult.ContainsKey("data")) + { + var _goodData = goodResult["data"] as ArrayList; + if (_goodData != null && _goodData.Count != 0) + { + foreach (Dictionary data in _goodData) + { + if (data.ContainsKey("commisionRatioWl")) + { + commissionshare = decimal.Parse(data["commisionRatioWl"].ToString()) / 100m; //接口中该商品的实际佣金,比较准一些, + break; + } + } + } + } + } + catch (Exception) + { } + #endregion + + ItemPoint usecoupon_commfee = null;//普通用户 用优惠券后积分信息 + //ItemPoint usecoupon_commfee_plus = null;//plus用户 用优惠券后积分信息 + string couponlike = string.Empty; //优惠券链接 + double discount = 0; //优惠券金额 + if (goodinfo.couponInfo.Count != 0) + { + //goodinfo.couponInfo[0].couponList[0]; + var couponList = goodinfo.couponInfo["couponList"] as ArrayList; + if (couponList.Count != 0)//有优惠券 + { + foreach (Dictionary coupon in couponList) + { + var quota = double.Parse(coupon["quota"].ToString()); //券消费限额 + if (quota > price) break;//优惠券面额大于商品单价时终止 + discount = double.Parse(coupon["discount"].ToString()); + couponlike = coupon["link"].ToString(); //优惠券链接 + break;//TODO 这里难道有多个优惠券?先不管,直接获取第一个 + } + } + } + + var buyshorturl = string.Empty; //转连后的地址 + #region 转连(生成自己推广的链接 [有券链接(二合一)或无券链接]) + Dictionary conversionlinkresult = null; //查询到的转换链接对象 + //var positionId = adzone.adzone_pid.Substring(adzone.adzone_pid.LastIndexOf("_") + 1); + if (string.IsNullOrWhiteSpace(couponlike)) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{itemId}.html", positionId = positionId, unionId = cps.usernick } });//宝贝id 和 用户的目标推客的联盟id + } + else + { + try + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{itemId}.html", positionId = positionId, unionId = cps.usernick, couponUrl = couponlike } }); + } + catch (Exception) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{itemId}.html", positionId = positionId, unionId = cps.usernick } });//宝贝id 和 用户的目标推客的联盟id + couponlike = string.Empty; + } + } + if (conversionlinkresult != null) + { + if (conversionlinkresult["code"].ToString() != "200") throw new Exception($"京东查询接口调用失败:{conversionlinkresult["message"].ToString()}");//抛出错误信息 + if (conversionlinkresult.ContainsKey("data")) + { + var data = conversionlinkresult["data"] as Dictionary; + if (data.ContainsKey("shortURL")) buyshorturl = data["shortURL"].ToString();//购买短连接 + } + if (string.IsNullOrWhiteSpace(buyshorturl)) throw new Exception("京东转链失败,请稍后重试"); + } + #endregion + + var imageList = goodinfo.imageInfo["imageList"] as ArrayList; + string imageUrl = string.Empty; + if (imageList.Count > 0) + imageUrl = (imageList[0] as Dictionary)["url"].ToString(); //宝贝主图 + + if (appendQrcode) + compositeQRCode = ApiClient.GetQRImage(goodinfo.skuName, price.ToString(), discount.ToString(), ((decimal)price - (decimal)discount).ToString(), imageUrl, buyshorturl, Class1.Config.qrImageType, CpsType.京东联盟); + else compositeQRCode = string.Empty; + return buyshorturl; + } + } + + //EventClient.OnEvent(this, $"朋友圈代运营京东转链异常:{ex.Message} - {ex.StackTrace}"); + + compositeQRCode = string.Empty; + return string.Empty; + } + + /// + /// 执行发送任务 + /// + private void _ExecuteSend(string objectDesc, string comment) + { + try + { + if (string.IsNullOrWhiteSpace(objectDesc)) return; + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList().Where(f => (f.WeixinType == WeixinType.Grpc微信 || f.WeixinType == WeixinType.Hook微信) && f.Status == WxStatus.在线).ToList(); + if (clients.Count != 0) + { + foreach (var _item in clients) + { + var item = _item; + //Task.Run(() => + //{ + try + { + //objectDesc = Regex.Replace(objectDesc, @"videomd5=""(.{32})""", @"videomd5=""" + Util.GetMD5Hash(Guid.NewGuid().ToByteArray()) + @""""); + //objectDesc = Regex.Replace(objectDesc, @"md5=""(.{32})""", @"md5=""" + Util.GetMD5Hash(Guid.NewGuid().ToByteArray()) + @""""); + + objectDesc = objectDesc.Replace("[活动口令]", Class1.Config.actionLink); + + var json = item.SendCircle(objectDesc);//发送朋友圈的主内容 + if (string.IsNullOrWhiteSpace(json)) + EventClient.OnEvent(this, $"【代运营朋友圈】 => {item.WeixinHao},转发失败"); + else + EventClient.OnEvent(this, $"【代运营朋友圈】 => {item.WeixinHao},转发成功"); + + if (!Class1.Config.isPl) + { + var reg = Regex.Match(json.Replace("", ""), @"(?\d{15,})");//获取返回的朋友圈id + if (reg.Success && !string.IsNullOrWhiteSpace(comment)) + { + var id = reg.Groups["id"].Value; + var commentStr = string.Empty; + if (string.IsNullOrWhiteSpace(Class1.Config.appendComment)) + commentStr = string.Join("[分段]", comment); + else + commentStr = string.Join("[分段]", comment, Class1.Config.appendComment); + if (!string.IsNullOrWhiteSpace(commentStr)) + item.SendCircleComment(item.User.Username, id, commentStr.Replace("[活动口令]", Class1.Config.actionLink)); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"【代运营朋友圈】 发送异常:{ex.Message} - {ex.StackTrace}"); + } + //}); + } + + if (Class1.Config.Monitor_Interval != 0) + { + Class1.Config.LastSendTime = DateTime.Now; + Util.Save(Class1.Config); + } + EventClient.OnEvent(this, $"【代运营朋友圈】 所有账号发送完毕"); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"【代运营朋友圈】 发送失败:{ex.Message} - {ex.StackTrace}"); + } + } + + } +} \ No newline at end of file diff --git a/应用/ProductClient/ProductClient.csproj b/应用/ProductClient/ProductClient.csproj new file mode 100644 index 0000000..01fc166 --- /dev/null +++ b/应用/ProductClient/ProductClient.csproj @@ -0,0 +1,114 @@ + + + + + Debug + AnyCPU + {B2FF88C8-B6B3-4FDE-ADFE-FCC702A9CD4C} + Library + Properties + ProductClient + ProductClient + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + Form + + + MainForm.cs + + + + + True + True + Resources.resx + + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + + + + \ No newline at end of file diff --git a/应用/ProductClient/Properties/AssemblyInfo.cs b/应用/ProductClient/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..83604dc --- /dev/null +++ b/应用/ProductClient/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("ProductClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ProductClient")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("b2ff88c8-b6b3-4fde-adfe-fcc702a9cd4c")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/ProductClient/Properties/Resources.Designer.cs b/应用/ProductClient/Properties/Resources.Designer.cs new file mode 100644 index 0000000..3f8505f --- /dev/null +++ b/应用/ProductClient/Properties/Resources.Designer.cs @@ -0,0 +1,136 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace ProductClient.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProductClient.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 [购买地址] 的本地化字符串。 + /// + internal static string BuyAddress { + get { + return ResourceManager.GetString("BuyAddress", resourceCulture); + } + } + + /// + /// 查找类似 爆单-代运营 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 爆单-代运营 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 爆单-代运营插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 http://item.sync.api.52cmg.cn/task.do?method=getCircle&lastId=@lastid&r=@r 的本地化字符串。 + /// + internal static string ProductApi { + get { + return ResourceManager.GetString("ProductApi", resourceCulture); + } + } + + /// + /// 查找类似 朋友圈代运营 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 [淘口令] 的本地化字符串。 + /// + internal static string TKLBuyAddress { + get { + return ResourceManager.GetString("TKLBuyAddress", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 爆单 { + get { + object obj = ResourceManager.GetObject("爆单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/ProductClient/Properties/Resources.resx b/应用/ProductClient/Properties/Resources.resx new file mode 100644 index 0000000..7f49b4a --- /dev/null +++ b/应用/ProductClient/Properties/Resources.resx @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + [购买地址] + 变量 + + + 爆单-代运营 + 设置主窗体标题 + + + 爆单-代运营 + 插件名 + + + 爆单-代运营插件 + 插件介绍 + + + http://item.sync.api.52cmg.cn/task.do?method=getCircle&lastId=@lastid&r=@r + 产品Api地址 + + + 朋友圈代运营 + fl_adzone_info自定义类型(custom_type) + + + [淘口令] + 变量 + + + + ..\Resources\爆单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/ProductClient/Properties/licenses.licx b/应用/ProductClient/Properties/licenses.licx new file mode 100644 index 0000000..a93a180 --- /dev/null +++ b/应用/ProductClient/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/ProductClient/Resources/爆单.png b/应用/ProductClient/Resources/爆单.png new file mode 100644 index 0000000..751ceb0 Binary files /dev/null and b/应用/ProductClient/Resources/爆单.png differ diff --git a/应用/ProductClient/Tools.cs b/应用/ProductClient/Tools.cs new file mode 100644 index 0000000..c219596 --- /dev/null +++ b/应用/ProductClient/Tools.cs @@ -0,0 +1,26 @@ +using Api.Framework.Cps; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace ProductClient +{ + class Tools + { + public static string GenerateRandomCode(int number) + { + StringBuilder sb = new StringBuilder(); + Random r = new Random(); + for (int i = 0; i < number; i++) + { + sb.Append(r.Next(0, 9)); + } + return sb.ToString(); + } + } +} diff --git a/应用/QQ采集项目.rar b/应用/QQ采集项目.rar new file mode 100644 index 0000000..bfac9f9 Binary files /dev/null and b/应用/QQ采集项目.rar differ diff --git a/应用/QQ采集项目/QQ采集项目/Demo.csproj b/应用/QQ采集项目/QQ采集项目/Demo.csproj new file mode 100644 index 0000000..8dc5d6a --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/Demo.csproj @@ -0,0 +1,102 @@ + + + + + Debug + AnyCPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E} + Library + Properties + QQ采集商品 + QQ采集商品 + v4.6.1 + 512 + true + + + true + full + false + ..\..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\..\Debug\Api.Framework.dll + False + + + ..\..\..\Debug\Chat.Framework.dll + False + + + ..\..\..\Debug\HttpHelper.dll + False + + + ..\..\..\Debug\Microsoft.Owin.dll + False + + + False + ..\..\返利机器人\Assembly\library\Newtonsoft.Json.dll + False + + + ..\..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + True + True + Resources.resx + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + \ No newline at end of file diff --git a/应用/QQ采集项目/QQ采集项目/Demo.sln b/应用/QQ采集项目/QQ采集项目/Demo.sln new file mode 100644 index 0000000..908fdb8 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/Demo.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31729.503 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", "Demo.csproj", "{955877A4-0126-4014-A7A8-40BCA9DD0B7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {955877A4-0126-4014-A7A8-40BCA9DD0B7E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D3A7BB48-2221-4EDD-9D14-94AEE109EB6C} + EndGlobalSection +EndGlobal diff --git a/应用/QQ采集项目/QQ采集项目/Entitys/DemoEntity.cs b/应用/QQ采集项目/QQ采集项目/Entitys/DemoEntity.cs new file mode 100644 index 0000000..098395d --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/Entitys/DemoEntity.cs @@ -0,0 +1,52 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo.Entitys +{ + /// + /// 自定义类 + /// + /// base_model 为增加id + /// + public class fl_qq_caiji : base_model + { + [SugarColumn(Length = 10000)] + //群号 + public string groupuin { get; set; } + //采集内容 + public string collectcontent { get; set; } + //采集时间 + public long collectime { get; set; } + //采集群昵称 + public string groupname { get; set; } + + } + + + public class fl_qq_save : base_model + { + /// + /// 请求的ip + /// + [SugarColumn(Length = 10000)] + public string recordip { get; set; } + /// + /// 请求的时间 + /// + public long recordstarttime { get; set; } + //群号 + public string groupuin { get; set; } + /// + /// 当天最后请求的id + /// + public long maxid { get; set; } + + public string groupName { get; set; } + + } +} diff --git a/应用/QQ采集项目/QQ采集项目/FirstPlugin.cs b/应用/QQ采集项目/QQ采集项目/FirstPlugin.cs new file mode 100644 index 0000000..7653f54 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/FirstPlugin.cs @@ -0,0 +1,256 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.QQSdk.Events; +using Demo.Entitys; +using Newtonsoft.Json.Linq; +using QQ采集商品.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Demo +{ + public class FirstPlugin : Plugin + { + #region 简单说明 + //第一步:引用Api.Framework.dll ----- 必须要引入 + //HttpHelper.dll 常用方法,http方法 等封装 ----- 看自己需求引入 + + //第二步:继承Plugin + #endregion + + public static MyConfig Config; + private MainForm mainForm = null;//插件的主窗体 + + public FirstPlugin() + { + this.Logo = Resources._666; //插件的图标 + this.Name = "QQ商品采集"; //插件名 + this.Note = "QQ采集爆款单群"; //说明 + } + + /// + /// 插件启动 + /// + public override void Start() + { + try + { + var db = ApiClient.GetSession();//操作数据库的对象 + #region 判断表是否存在,不存在创建表 + if (!db.TableExist()) + { + //这里只做约束和索引,并不是创建数据库字段的地方 + db.CreateTable();//插件表 + db.AddIndex("groupuin");//群号唯一索引 + + } + + if (!db.TableExist()) + { + db.CreateTable();//插件表 + db.AddIndex("recordip");//ip唯一索引 + } + + #endregion + + //创建配置文件 + //Config = this.ReadConfig(); //初始化并读取配置文件 + SDK.ReciveIMEvent += SDK_ReciveIMEvent; //私聊/群消息事件 + SDK.WebRequestEvent += SDK_WebRequestEvent; + + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// + /// QQ采集Api接口 + /// + /// + /// + private void SDK_WebRequestEvent(object sender, Api.Framework.Events.WebRequestEvents e) + { + try + { + //http: //127.0.0.1/80?Action=qq 请求格式 + //http: //127.0.0.1/80?Action=content&uin=[{"groupuin":"485048090","maxid":"0"},{"groupuin":"815345082","maxid":"0"}] + + var db = ApiClient.GetSession();//操作数据库的对象 + var ip = e.Context.Request.RemoteIpAddress;//记录请求的ip地址 + + if (e.Param == null || !e.Param.ContainsKey("Action")) return; + var Action = e.Param["Action"]; + //这里只是获取采集群号列表,并不发生保存 + if (Action.ToLower() == "qq") + { + var arr = new List(); + var gids = db.Queryable().GroupBy(f => f.groupuin).Select(f => f.groupuin).ToList(); + for (int i = 0; i < gids.Count; i++) + { + //获取采集群号 + var grou = gids[i]; + //this.OnLog("群号: " + grou); + //获取maxid + var maxid = 0L; + var groupname = string.Empty; + //以降序排列获取采集商品的最大id + var colls = db.Queryable().Where(f => f.groupuin == gids[i]).OrderBy(f => f.id, SqlSugar.OrderByType.Desc).ToList(); + if (colls != null && colls.Count != 0) + { + //将获取的最大商品id 赋值给maxid进行保存 + maxid = colls[0].id; + groupname = colls[0].groupname; + //this.OnLog("maxid: "+maxid.ToString()); + } + else + continue; + //获取请求ip 和当天的请求时间 + var first = db.Queryable().First(f => f.recordip == ip && f.recordstarttime == CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now.Date)); + if (first == null) + first = new fl_qq_save(); + + first.groupuin = grou;//记录当天采集的群号 + this.OnLog("采集群号: " + first.groupuin); + first.maxid = maxid;//记录当天采集的商品id + first.recordip = ip;//记录当天请求的ip + first.recordstarttime = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now.Date);//记录当天请求的时间 + db.Saveable(first).ExecuteCommand(); + + arr.Add(new { groupuin = first.groupuin, maxid = first.maxid, groupname = groupname }); ;//返回给请求方的内容 + } + e.Send(arr); + } + + //这里是获取商品信息 + else if (Action.ToLower() == "content") + { + //判断指定的键是否存在 + if (!e.Param.ContainsKey("uin")) throw new Exception(); + var uin = e.Param["uin"]; + //这里是要发送的列表对象 + var data = new List(); + //这里开始处理得到的json数据 + var jarray = JArray.Parse(uin); + foreach (JToken jToken in jarray) + { + var groupuin = jToken["groupuin"].ToString(); + var maxid = jToken["maxid"].ToString(); + var list = new List(); + //按降序排列 + var caiji = db.Find("select * from fl_qq_caiji where groupuin = @groupuin and id > @maxid order by id desc", new { groupuin = groupuin, maxid = maxid }); + + if (caiji != null && caiji.Count != 0) + { + List temps = new List(); + caiji = caiji.Take(6).ToList(); + for (int i = 0; i < caiji.Count; i++) + { + //获取到采集内容 + temps.Add(new { content = caiji[i].collectcontent }); + } + list.Add(new { groupuin = groupuin, maxid = caiji[0].id, groupname = caiji[0].groupname, data = temps }); + + //将此次请求的数据都保存在fl_qq_save表中 + var savesend = db.Queryable().First(f => f.groupuin == groupuin && f.recordip == ip && f.recordstarttime == CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now.Date)); + if (savesend == null) + { + //保存此次请求群号 这里必须new数据库表名,否则无法创建对象将对应的数据写进数据库 + savesend = new fl_qq_save() { groupuin = groupuin }; + //保存此次请求的ip + savesend.recordip = ip; + } + savesend.maxid = caiji[0].id;//保存此次请求的maxid最大值 + savesend.recordstarttime = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now.Date);//保存当天请求的时间 + db.Saveable(savesend).ExecuteCommand();//将数据保存在fl_qq_save数据库表中 + } + else + { + list.Add(new { groupuin = groupuin, maxid = maxid }); + } + data.Add(list); + //将采集的数据,发送给请求方 + e.Send(data); + } + } + } + catch (Exception error) + { + e.Send("请求失败"); + this.OnLog("【QQ采集】异常: " + error.Message); + } + } + + /// + /// 插件窗体 + /// + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// + /// 插件关闭 + /// + public override void Stop() + { + try + { + Util.Save(Config);//保存配置文件,在使用中修改了配置文件的内容,这个进行修改 + + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// + /// 接收所有消息的处理 + /// + /// + /// + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + if (e.Event is QQReceiveGroupMsgEvents) + { + var gEvent = e.Event as QQReceiveGroupMsgEvents; + if (gEvent != null) + { + var Group = e.Groupid;//获取QQ群id + var db = ApiClient.GetSession();//数据库操作对象 + db.Insertable(new fl_qq_caiji() { groupuin = Group, collectcontent = e.Message, groupname = gEvent.GroupName, collectime = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now.Date) }).ExecuteCommand(); + } + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} - {ex.StackTrace}"); + } + } + } +} diff --git a/应用/QQ采集项目/QQ采集项目/MainForm.Designer.cs b/应用/QQ采集项目/QQ采集项目/MainForm.Designer.cs new file mode 100644 index 0000000..ac7a534 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/MainForm.Designer.cs @@ -0,0 +1,49 @@ +namespace Demo +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(464, 306); + this.MaximizeBox = false; + this.Name = "MainForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "QQ采集"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.ResumeLayout(false); + + } + + #endregion + } +} \ No newline at end of file diff --git a/应用/QQ采集项目/QQ采集项目/MainForm.cs b/应用/QQ采集项目/QQ采集项目/MainForm.cs new file mode 100644 index 0000000..f89c896 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/MainForm.cs @@ -0,0 +1,46 @@ +using Api.Framework; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Demo +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + /// + /// 窗体的关闭 + /// + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception) { } + } + + + private void MainForm_Load(object sender, EventArgs e) + { + string[] vs = new string[] {""}; + } + } +} diff --git a/应用/QQ采集项目/QQ采集项目/MainForm.resx b/应用/QQ采集项目/QQ采集项目/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/应用/QQ采集项目/QQ采集项目/MyConfig.cs b/应用/QQ采集项目/QQ采集项目/MyConfig.cs new file mode 100644 index 0000000..9eaa1d6 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/MyConfig.cs @@ -0,0 +1,23 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Demo +{ + /// + /// 这个可以作为一个配置,下面内容自己按需添加 + /// + [Config(Name = "插件_QQdemo_配置")] //这里一定要确保每个插件的名称不一样 + public class MyConfig + { + /// + /// 下面我测试一个案例吧 + /// + public string Info { get; set; } + + } +} diff --git a/应用/QQ采集项目/QQ采集项目/Properties/AssemblyInfo.cs b/应用/QQ采集项目/QQ采集项目/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6a95d96 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Demo")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Demo")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("955877a4-0126-4014-a7a8-40bca9dd0b7e")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/QQ采集项目/QQ采集项目/Properties/Resources.Designer.cs b/应用/QQ采集项目/QQ采集项目/Properties/Resources.Designer.cs new file mode 100644 index 0000000..861b116 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace QQ采集商品.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("QQ采集商品.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap _666 { + get { + object obj = ResourceManager.GetObject("_666", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/QQ采集项目/QQ采集项目/Properties/Resources.resx b/应用/QQ采集项目/QQ采集项目/Properties/Resources.resx new file mode 100644 index 0000000..ea543f7 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\666.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/QQ采集项目/QQ采集项目/Resources/666.png b/应用/QQ采集项目/QQ采集项目/Resources/666.png new file mode 100644 index 0000000..e23bb06 Binary files /dev/null and b/应用/QQ采集项目/QQ采集项目/Resources/666.png differ diff --git a/应用/QQ采集项目/QQ采集项目/app.config b/应用/QQ采集项目/QQ采集项目/app.config new file mode 100644 index 0000000..a0cefc2 --- /dev/null +++ b/应用/QQ采集项目/QQ采集项目/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/应用/ReportData/Class1.cs b/应用/ReportData/Class1.cs new file mode 100644 index 0000000..1d8651b --- /dev/null +++ b/应用/ReportData/Class1.cs @@ -0,0 +1,99 @@ +using Api.Framework; +using Api.Framework.SDK; +using Easy4net.Context; +using ReportData.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ReportData +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.导购; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + private static object MyLock = new object(); + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + //if (!session.TableExist()) + //{ + // session.CreateTable(); + // session.AddIndex("uid"); + //} + //if (!session.TableExist()) session.CreateTable(); + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + TimerTask.NewTimer(24); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.Activate(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + } +} diff --git a/应用/ReportData/Properties/AssemblyInfo.cs b/应用/ReportData/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e354ecd --- /dev/null +++ b/应用/ReportData/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("ReportData")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ReportData")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("05d752ce-4035-4aa9-8559-51165f8181c6")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/ReportData/Properties/Resources.Designer.cs b/应用/ReportData/Properties/Resources.Designer.cs new file mode 100644 index 0000000..b9688b5 --- /dev/null +++ b/应用/ReportData/Properties/Resources.Designer.cs @@ -0,0 +1,148 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace ReportData.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ReportData.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 数据报告 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 增加自动生成报表任务 的本地化字符串。 + /// + internal static string PluginFormAddTask { + get { + return ResourceManager.GetString("PluginFormAddTask", resourceCulture); + } + } + + /// + /// 查找类似 修改自动生成报表任务 的本地化字符串。 + /// + internal static string PluginFormUpdateTask { + get { + return ResourceManager.GetString("PluginFormUpdateTask", resourceCulture); + } + } + + /// + /// 查找类似 数据报告 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 数据报告插件。自动统计每天数据、并准时通知管理员! 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 导购 { + get { + object obj = ResourceManager.GetObject("导购", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 数据统计 { + get { + object obj = ResourceManager.GetObject("数据统计", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 进群统计 { + get { + object obj = ResourceManager.GetObject("进群统计", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/ReportData/Properties/Resources.resx b/应用/ReportData/Properties/Resources.resx new file mode 100644 index 0000000..4556ead --- /dev/null +++ b/应用/ReportData/Properties/Resources.resx @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 数据报告 + 设置主窗体标题 + + + 增加自动生成报表任务 + 增加自动生成报表任务 + + + 修改自动生成报表任务 + 修改自动生成报表任务 + + + 数据报告 + 插件名 + + + 数据报告插件。自动统计每天数据、并准时通知管理员! + 插件介绍 + + + + ..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\导购.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\数据统计.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\进群统计.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/ReportData/ReportData.csproj b/应用/ReportData/ReportData.csproj new file mode 100644 index 0000000..487fcac --- /dev/null +++ b/应用/ReportData/ReportData.csproj @@ -0,0 +1,177 @@ + + + + + Debug + AnyCPU + {05D752CE-4035-4AA9-8559-51165F8181C6} + Library + Properties + ReportData + ReportData + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\Easy4net.dll + False + + + ..\..\Debug\HttpHelper.dll + False + + + ..\..\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll + False + + + ..\..\Debug\NPOI.dll + False + + + ..\..\Debug\NPOI.DDF.dll + False + + + ..\..\Debug\NPOI.HPSF.dll + False + + + ..\..\Debug\NPOI.HSSF.dll + False + + + ..\..\Debug\NPOI.POIFS.dll + False + + + ..\..\Debug\NPOI.Util.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + + Form + + + MainForm.cs + + + Form + + + TaskForm.cs + + + + + + True + True + Resources.resx + + + + + MainForm.cs + + + TaskForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/应用/ReportData/Resources/1.jpg b/应用/ReportData/Resources/1.jpg new file mode 100644 index 0000000..50fce67 Binary files /dev/null and b/应用/ReportData/Resources/1.jpg differ diff --git a/应用/RoomMembers/Class1.cs b/应用/RoomMembers/Class1.cs new file mode 100644 index 0000000..f0ac7fb --- /dev/null +++ b/应用/RoomMembers/Class1.cs @@ -0,0 +1,121 @@ +using Api.Framework.Events; +using Api.Framework.SDK; +using RoomMembers.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace RoomMembers +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = "群成员Api"; + this.Note = "获取群成员"; + this.Logo = Resources._22; + } + + #region 自定义变量 + //public static Config Config; + #endregion + + public override void Start() + { + try + { + SDK.WebRequestEvent += SDK_WebRequestEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_WebRequestEvent(object sender, WebRequestEvents e) + { + try + { + #region + if (e.Param.ContainsKey("method"))//方法名称 + { + var method = e.Param["method"].ToLower(); + switch (method) + { + case "roommembers"://用户 + { + try + { + if (!e.Param.ContainsKey("roomid")) throw new Exception("缺少参数roomid"); + if (!e.Param.ContainsKey("robotname")) throw new Exception("缺少参数roomname"); + + var robotname = e.Param["robotname"].ToString(); + var roomid = e.Param["roomid"].ToString(); + + if (string.IsNullOrWhiteSpace(robotname)) throw new Exception("robotname参数不能为空"); + if (string.IsNullOrWhiteSpace(roomid)) throw new Exception("roomid参数不能为空"); + + var client = Chat.Framework.ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robotname && f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (client == null) throw new Exception("机器人不存在或者不在线"); + + var members = client.GetMembers(roomid, true); + if (members == null) members = new Chat.Framework.WXSdk.GroupMember[] { }; + + e.Send(members); + } + catch (Exception ex) + { + e.Send(ex.Message, -1); + } + } + break; + case "removemembers": + { + try + { + if (!e.Param.ContainsKey("roomid")) throw new Exception("缺少参数roomid"); + if (!e.Param.ContainsKey("robotname")) throw new Exception("缺少参数roomname"); + if (!e.Param.ContainsKey("usernames")) throw new Exception("缺少参数roomname"); + + var robotname = e.Param["robotname"].ToString(); + var roomid = e.Param["roomid"].ToString(); + var usernames = e.Param["usernames"].ToString(); + + if (string.IsNullOrWhiteSpace(robotname)) throw new Exception("robotname参数不能为空"); + if (string.IsNullOrWhiteSpace(roomid)) throw new Exception("roomid参数不能为空"); + if (string.IsNullOrWhiteSpace(usernames)) throw new Exception("usernames参数不能为空"); + + var client = Chat.Framework.ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robotname && f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (client == null) throw new Exception("机器人不存在或者不在线"); + + var users = usernames.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + foreach (var item in users) + { + client.DeleteGroupMember(item, roomid); + Thread.Sleep(200); + } + e.Send("任务执行完成"); + } + catch (Exception ex) + { + e.Send(ex.Message, -1); + } + } + break; + } + } + #endregion + + } + catch (Exception ex) + { + + } + } + + + } +} diff --git a/应用/RoomMembers/Properties/AssemblyInfo.cs b/应用/RoomMembers/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..33e30c8 --- /dev/null +++ b/应用/RoomMembers/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("RoomMembers")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("RoomMembers")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("3caa5d74-7533-49b5-a91f-169561ceedac")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/RoomMembers/Properties/Resources.Designer.cs b/应用/RoomMembers/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7c22882 --- /dev/null +++ b/应用/RoomMembers/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace RoomMembers.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RoomMembers.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap _22 { + get { + object obj = ResourceManager.GetObject("_22", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/RoomMembers/Properties/Resources.resx b/应用/RoomMembers/Properties/Resources.resx new file mode 100644 index 0000000..0edcc92 --- /dev/null +++ b/应用/RoomMembers/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\22.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/RoomMembers/Resources/22.png b/应用/RoomMembers/Resources/22.png new file mode 100644 index 0000000..6de8128 Binary files /dev/null and b/应用/RoomMembers/Resources/22.png differ diff --git a/应用/RoomMembers/RoomMembers.csproj b/应用/RoomMembers/RoomMembers.csproj new file mode 100644 index 0000000..8d672e2 --- /dev/null +++ b/应用/RoomMembers/RoomMembers.csproj @@ -0,0 +1,77 @@ + + + + + Debug + AnyCPU + {3CAA5D74-7533-49B5-A91F-169561CEEDAC} + Library + Properties + RoomMembers + RoomMembers + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + + + ..\..\Debug\Chat.Framework.dll + + + ..\..\Debug\HttpHelper.dll + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/SNRebate/Class1.cs b/应用/SNRebate/Class1.cs new file mode 100644 index 0000000..a34ba6e --- /dev/null +++ b/应用/SNRebate/Class1.cs @@ -0,0 +1,684 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using CsharpHttpHelper; +using Newtonsoft.Json; +using SNRebate.Entitys; +using SNRebate.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using static Api.Framework.Tools.SNHelper; + +namespace SNRebate +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.苏宁; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (session.TableExist()) + { + var sntgws = session.Find("select * from fl_plugin_snrebate_sntgw").ToList(); + if (sntgws != null) + { + foreach (var item in sntgws) + { + //插入主推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_chief_name, //推广位名称 + adzone_pid = item.pid_chief, //推广位pid + adzone_pid_cps_name = item.pid_chief_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.苏宁易购, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "chief" + }).ExecuteCommand(); + //插入副推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_deputy_name, //推广位名称 + adzone_pid = item.pid_deputy, //推广位pid + adzone_pid_cps_name = item.pid_deputy_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.苏宁易购, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "deputy" + }).ExecuteCommand(); + } + } + session.DropTable(); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + #region 订单事件处理 + private void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.Member != null && e.ChatType == CpsType.苏宁易购) + { + var session = ApiClient.GetSession(); + var order = e.Order as fl_order_suning; + if (order == null) return; + var robot_info = session.FindRobotInfo(e.Member.robot_name, e.Member.robot_type); + + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + mess = _GetOrderStateMess(order.db_status, order, e.Member, point); + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order.msg_groupid); + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_OneLevelTip; + if (order.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_TwoLevelTip; + if (order.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_ThreeLevelTip; + if (order.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_LeaderTip; + if (order.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + { + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order, e.Member, point).Replace("[下级昵称]", e.Customer.realnick)); + } + } + } + } + catch (Exception ex) + { + this.OnLog($"苏宁订单通知异常:{ex.Message},{ex.StackTrace}"); + } + } + #endregion + + #region 消息事件处理 + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + Compute compute = null; + var goodsName = string.Empty; + try + { + //过滤表情xml和卡片xml + if (((e.Message.Contains(@"("select * from fl_order_suning where orderCode = @orderCode", new { orderCode = orderid }); + if (orders != null && orders.Count != 0) + { + var notices = new List(); + var downSuningTimer = new DownSuningTimer(); + foreach (var order in orders) + { + if (order.db_userid != 0 && order.db_userid != member.id) + { + e.SendMessage(Config.OccupyOrderErrorTip.Replace("[订单号]", orderid)); + return; + } + + if (order.db_userid != 0) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + member = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Config.OrderRepetBindTip, order, member, point)); + else + e.SendMessage(_GetOrderStateMess(order.db_status, order, member, point)); + } + else + { + if (order.payTime < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderid},已经过了有效绑定时间!"); + return; + } + + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + //用户绑定订单 + order.db_robotname = e.RobotName; + order.db_robottype = e.ChatType; + order.msg_groupid = e.Groupid; + order.db_userid = member.id; + session.SaveOrUpdate(order); + + if (member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + + #region 首次付款时间 + var record = session.FindStatisticsRecord(member.id); + if (record == null) + { + record = new fl_statistics_record() { uid = member.id, ex2 = 0, ex4 = HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + #endregion + + downSuningTimer.UpdateOrder(order, session, notices, isFrontData: true); + } + } + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.IsRewards) + tasks.Add(item); + //else + //SDK_OrderNoticeEvent(this, item); + } + } + #endregion + + e.Cancel = true; + } + else + { + if (i < 1) + { + CpsClient.UpdateOrder(CpsType.苏宁易购, DateTime.Now.AddMinutes(-30), DateTime.Now, orderid); + i++; + goto Next; + } + e.SendMessage(Config.NotFoundOrderErrorTip.Replace("[订单号]", orderid)); + e.Cancel = true; + return; + } + } + + if (OrderHelper.IsOrderId(e.Message.Trim())) + return; + #endregion + + #region 关键词解析、链接解析、标题查找 临时注释 + var sninfoTemps = session.FindSnInfoTempGroups(); + var snInfoTemp = sninfoTemps.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (snInfoTemp == null) return; + try + { + SNId snid = SNHelper.GetSNGoodsID(message); + if (snid == null) + return; + + fl_cps_member sn_cps = null; + var pid = string.Empty;//使用的推广位 + + #region 判断使用的推广位 + var isDefault = true; + if (!string.IsNullOrWhiteSpace(e.Groupid))//群pid + { + var groupAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + string username = groupAdzone.adzone_pid_cps_name; + pid = groupAdzone.adzone_pid; + sn_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.苏宁易购 && f.username == username); + isDefault = false; + } + } + + if (isDefault)//私人pid + { + var memberAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == member.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + string username = memberAdzone.adzone_pid_cps_name; + sn_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.苏宁易购 && f.username == username); + pid = memberAdzone.adzone_pid; + isDefault = false; + } + } + + if (isDefault)//默认推广位 + { + sn_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.苏宁易购 && f.username == ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? snInfoTemp.pid_chief_cps_name : snInfoTemp.pid_deputy_cps_name));//通过判断用户的购物积分,来判断用户使用哪个推广位 + pid = ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? snInfoTemp.pid_chief : snInfoTemp.pid_deputy); + } + #endregion + + if (sn_cps == null) throw new Exception("@苏宁易购推广位异常,请检测后重试!"); + if (string.IsNullOrWhiteSpace(pid)) throw new Exception("@苏宁易购推广位为空,请检测后重试!"); + + var api = CpsClient.CreateSuNingRequest(sn_cps); + if (api == null) throw new Exception("@创建苏宁易购API请求失败"); + + #region 判断商品Id是否为屏蔽的商品 + if (Class1.Config.ItemIDRestrictList.Contains(snid.goodid)) + { + e.SendMessage(Config.ItemIDRestrictTip.Replace("[商品ID]", snid.goodid)); + return; + } + #endregion + + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + e.SendMessage(Config.SearchingTip);//正在搜索提示 + + var snGInfo = api.QueryGoodInfo($"{snid.goodid}-{snid.shop}"); + + if (snGInfo.sn_responseContent.sn_error != null) + throw new Exception(snGInfo.sn_responseContent.sn_error.error_msg);//查询没结果 + else if (snGInfo.sn_responseContent.sn_body == null || snGInfo.sn_responseContent.sn_body.queryCommoditydetail == null || snGInfo.sn_responseContent.sn_body.queryCommoditydetail.Count == 0) + throw new Exception("查询没结果2"); + + + foreach (var item in snGInfo.sn_responseContent.sn_body.queryCommoditydetail) + { + #region 判断店铺ID是否为屏蔽的店铺 + if (!string.IsNullOrWhiteSpace(item.commodityInfo.supplierCode)) + { + if (Config.SellerIDRestrictlist.Contains(item.commodityInfo.supplierCode)) + { + e.SendMessage(Config.SellerIDRestrictTip.Replace("[店铺ID]", item.commodityInfo.supplierCode).Replace("[店铺名称]", item.commodityInfo.supplierName)); + return; + } + } + #endregion + + var vipPrice = -1d; + if (!string.IsNullOrWhiteSpace(item.commodityInfo.snPrice)) + vipPrice = double.Parse(item.commodityInfo.snPrice); + if (vipPrice == -1 && !string.IsNullOrWhiteSpace(item.commodityInfo.commodityPrice)) + vipPrice = double.Parse(item.commodityInfo.commodityPrice); + + var buyUrl = item.commodityInfo.productUrl; + + if (item.pgInfo != null) + { + if (!string.IsNullOrWhiteSpace(item.pgInfo.pgUrl)) + { + buyUrl = item.pgInfo.pgUrl; + if (!string.IsNullOrWhiteSpace(item.pgInfo.pgUrl)) + { + vipPrice = double.Parse(item.pgInfo.pgPrice); + } + } + } + + if (vipPrice == -1) + throw new Exception("当前价格不明"); + + //优惠券金额 + var coupon_price = 0.00d; + + //怕两个地址都没有链接.用自己拼的 + if (string.IsNullOrWhiteSpace(buyUrl)) + buyUrl = $@"https://product.suning.com/{snid.shop}/{snid.goodid}.html"; + + + //优惠券地址 + var couponUrl = (item.couponInfo != null && !string.IsNullOrWhiteSpace(item.couponInfo.couponUrl)) ? item.couponInfo.couponUrl : string.Empty; + + //优惠券地址 + //var coupon_click_url = string.Empty; + if (Config.NoCouponModeSwitch != SwitchType.开启) + { + if (!string.IsNullOrWhiteSpace(couponUrl))//有券 + { + //优惠券没有过期 + if (item.couponInfo.couponEndTime >= DateTime.Now && + ( + (!string.IsNullOrWhiteSpace(item.couponInfo.bounsLimit) && double.Parse(item.couponInfo.bounsLimit) <= vipPrice) || + (string.IsNullOrWhiteSpace(item.couponInfo.bounsLimit)) + ) + ) + coupon_price = double.Parse(item.couponInfo.couponValue); + } + } + //商品标题//< >&"© <,>,&,",©; + goodsName = item.commodityInfo.commodityName.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); + + var endPrice = vipPrice; + if (coupon_price != 0) + endPrice = (double)((decimal)vipPrice - (decimal)coupon_price); + + //佣金比例 + var commissionRate = double.Parse(item.commodityInfo.rate); + + //券后 总佣金 + var useCoupon_totalCommFee = Math.Round(endPrice * (commissionRate / 100.00), 2); + //用券后 给用户的佣金 + var useCoupon_commFee = session.FindItemPoint(member, useCoupon_totalCommFee, 1, CpsType.苏宁易购, out compute); + + Compute compute1 = null; + + //不用券 佣金 + var unuseCoupon_totalCommFee = Math.Round(vipPrice * (commissionRate / 100.00), 2); + //不用券 给用户的佣金 + var unuseCoupon_commFee = session.FindItemPoint(member, unuseCoupon_totalCommFee, 1, CpsType.苏宁易购, out compute1); + + if (compute == null) + compute = compute1; + + var storeName = item.commodityInfo.supplierName; + + #region 转链 + //pid=(?.+?)\sr=(?<机器人名>.*?)\st=(?<类型>\d+)\su=(?<会员名>.+?)\smid=(?<店铺ID>\d+)\sgid=(?<商品ID>\d+) + var custom = Util.EncryptDES($"pid={pid} r={e.RobotName} t={(int)e.RobotInfo.type} u={e.GetMemberinfo().username} mid={item.commodityInfo.supplierCode} gid={snid.goodid} g={e.Groupid}"); + var extension = api.GetExtensionUrl(custom, buyUrl, couponUrl); + if (extension.sn_responseContent.sn_body == null) + throw new Exception(); + #endregion + + var picUrl = (item.commodityInfo.pictureUrl != null && item.commodityInfo.pictureUrl.Count != 0) ? item.commodityInfo.pictureUrl[0].picUrl : string.Empty; + + #region 正常订单 + //有券的情况 + if (coupon_price != 0) + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithCouponTip))) + mess = Config.SearchSuccessWithCouponTip; + else + mess = Config.QQSearchSuccessWithCouponTip; + + e.SendMessage(mess + .Replace("劵", "券") + .Replace("[商品标题]", mess.Contains("", "") : goodsName) + .Replace("[商品原价]", string.Format("{0:F}", vipPrice)) + .Replace("[商品主图]", $"[图片={picUrl}]") + .Replace("[图片地址]", picUrl) + .Replace("[店铺名称]", storeName) + .Replace("[券后返利]", string.Format("{0:F}", useCoupon_commFee.UserPoint)) + .Replace("[弃券返利]", string.Format("{0:F}", unuseCoupon_commFee.UserPoint)) + .Replace("[券后价]", string.Format("{0:F}", endPrice)) + .Replace("[优惠券金额]", string.Format("{0:F}", coupon_price)) + .Replace("[购买地址]", extension.sn_responseContent.sn_body.getExtensionlink.shortLink) + .Replace("[共节省]", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goodsName, string.Format("{0:F}", vipPrice), string.Format("{0:F}", coupon_price), string.Format("{0:F}", endPrice), picUrl, couponUrl, ApiClient.QrImageType.模板B, CpsType.苏宁易购) + "]" : string.Empty) + ); + } + else//没有券的情况 + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithoutCouponTip))) + mess = Config.SearchSuccessWithoutCouponTip; + else + mess = Config.QQSearchSuccessWithoutCouponTip; + + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("", "") : goodsName) + .Replace("[商品原价]", string.Format("{0:F}", vipPrice)) + .Replace("[商品主图]", $"[图片={picUrl}]") + .Replace("[图片地址]", picUrl) + .Replace("[店铺名称]", storeName) + .Replace("[返利积分]", string.Format("{0:F}", unuseCoupon_commFee.UserPoint)) + .Replace("[购买地址]", extension.sn_responseContent.sn_body.getExtensionlink.shortLink) + .Replace("[共节省]", string.Format("{0:F}", useCoupon_commFee.UserPoint)) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goodsName, string.Format("{0:F}", vipPrice), "0", string.Format("{0:F}", vipPrice), picUrl, couponUrl, ApiClient.QrImageType.模板B, CpsType.苏宁易购) + "]" : string.Empty) + ); + } + #endregion + + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + session.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.苏宁易购, + itemid = snid.goodid, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = member.id, + title = goodsName, + adzoneid = pid, + mallid = item.commodityInfo.supplierCode, + compute_configdic = compute == null ? string.Empty : JsonConvert.SerializeObject(compute) + }).ExecuteCommand(); + session.UpdateRecord(member.id); + + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.苏宁易购; + shared["msg_username"] = member.username; + shared["price"] = string.Format("{0:F}", vipPrice); + shared["title"] = goodsName; + shared["coupon_price"] = string.Format("{0:F}", (coupon_price != 0 ? coupon_price : 0)); + shared["user_point"] = coupon_price != 0 ? string.Format("{0:F}", useCoupon_commFee.UserPoint) : string.Format("{0:F}", unuseCoupon_commFee.UserPoint); + shared["economize"] = string.Format("{0:F}", (coupon_price != 0 ? ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint) : (decimal)useCoupon_commFee.UserPoint)); + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + #endregion + + } + } + catch (Exception ex) + { + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", goodsName).Replace("[商品标题]", goodsName));//未搜索到提示语 + var db = ApiClient.GetSession(); + db.UpdateRecord(e.GetMemberinfo().id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.苏宁易购; + shared["msg_username"] = e.GetMemberinfo().username; + shared["price"] = "未知"; + shared["title"] = goodsName; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + + if (!ex.Message.Contains("查询没结果")) + throw ex; + } + #endregion + } + catch (Exception ex) + { + if (ex.Message.StartsWith("@")) + this.OnLog($"W :({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message.Replace("@", "")}"); + else + this.OnLog($"W:({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message} - {ex.StackTrace}"); + this.OnLog(ApiClient.Setting.SystemConfig.msg_error); + } + } + #endregion + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + #region 变量替换 + /// + /// 订单状态 提示语替换 + /// + /// + /// + /// + private string _GetOrderStateMess(SystemOrderStatus order, params object[] objs) + { + + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.全额退款: + case SystemOrderStatus.部分退款: + case SystemOrderStatus.订单维权中: + mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(Config.OrderSettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Config.OrderFreezeTip, objs); + break; + } + return mess; + } + #endregion + + } +} diff --git a/应用/SNRebate/Config.cs b/应用/SNRebate/Config.cs new file mode 100644 index 0000000..e51d398 --- /dev/null +++ b/应用/SNRebate/Config.cs @@ -0,0 +1,909 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace SNRebate +{ + [Config(Name = "插件-苏宁返利-配置")] + public class Config + { + #region 消费积分设置 + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("01.主推广位使用条件 - 购物积分"), DefaultValue(20), + Description(@"用户消费积分≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int Point { get; set; } + + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("02.主推广位使用条件 - 订单笔数"), DefaultValue(20), + Description(@"用户交易订单数≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int OrderNum { get; set; } + #endregion + + #region 提示语 + /// + /// 无券模式 + /// + [ + Category("2)、商品查询"), DisplayName(@"01.无券模式"), DefaultValue(SwitchType.关闭), Description(@"为开启时,有券的商品将以无券的形式返回") + ] + public SwitchType NoCouponModeSwitch { get; set; } + + /// + /// 正在搜索宝贝提示语 + /// + [ + Category("2)、商品查询"), DisplayName("02.正在搜索宝贝"), DefaultValue(@"优惠信息查询中....."), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchingTip { get; set; } + + /// + /// 搜索宝贝无佣金 + /// + [ + Category("2)、商品查询"), DisplayName("03.无佣金时提示"), DefaultValue(@"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[关键词]、链接无返利变量:[商品标题]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchNoCommissionTip { get; set; } + + /// + /// 无优惠券时提示 + /// + [ + Category("2)、商品查询"), DisplayName("04.无优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[店铺名称]、[返利积分]、[购买地址]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithoutCouponTip { get; set; } + + /// + /// 有优惠券提示语 + /// + [ + Category("2)、商品查询"), DisplayName("05.有优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithCouponTip { get; set; } + + /// + /// 无优惠券时提示(QQ) + /// + [ + Category("2)、商品查询"), DisplayName("06.无优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""无优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[店铺名称]、[返利积分]、[购买地址]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithoutCouponTip { get; set; } + + /// + /// 有优惠券提示语(QQ) + /// + [ + Category("2)、商品查询"), DisplayName("07.有优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""有优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithCouponTip { get; set; } + + + #endregion + + #region 订单通知 + + /// + /// 用户订单变化通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"01.用户订单变化通知"), DefaultValue(SwitchType.开启), Description(@"开启用户订单变化通知功能时,用户的订单发生变化时,将通知用户订单的情况") + ] + public SwitchType UserOrderChangeSwitch { get; set; } + /// + /// 代理获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"02.代理获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启代理获得提成通知功能时,用户的订单发生变化时,将通知代理获得提成信息") + ] + public SwitchType AgentReceivedCommissionSwitch { get; set; } + /// + /// 群负责人获得提成通知 + /// + [ + Category("3)、订单通知"), DisplayName(@"03.群负责人获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启群负责人获得提成通知功能时,用户的订单发生变化时,将通知群负责人获得提成信息") + ] + public SwitchType PrincipalReceivedCommissionSwitch { get; set; } + + /// + /// 绑定订单号非本人提示语 + /// + [Category("3)、订单通知"), DisplayName("04.已被其他用户绑定"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OccupyOrderErrorTip { get; set; } + + /// + /// 订单号未找到提示语 + /// + [Category("3)、订单通知"), DisplayName("05.未找到订单号"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string NotFoundOrderErrorTip { get; set; } + + /// + /// 重复绑定订单号 + /// + [Category("3)、订单通知"), DisplayName("06.重复绑定订单号"), DefaultValue(@"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRepetBindTip { get; set; } + + /// + /// 订单付款提示语 + /// + [Category("3)、订单通知"), DisplayName("07.订单付款"), DefaultValue(@"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentTip { get; set; } + + /// + /// 订单付款通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("08.订单付款通知一级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_OneLevelTip { get; set; } + + /// + /// 订单付款通知二级 + /// + [Category("3)、订单通知"), DisplayName("09.订单付款通知二级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_TwoLevelTip { get; set; } + + /// + /// 订单付款通知三级 + /// + [Category("3)、订单通知"), DisplayName("10.订单付款通知三级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_ThreeLevelTip { get; set; } + + /// + /// 订单付款通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("11.订单付款通知群负责人"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_LeaderTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("12.订单冻结"), DefaultValue(@"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFreezeTip { get; set; } + + /// + /// 订单结算提示语 + /// + [Category("3)、订单通知"), DisplayName("13.订单结算"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlementTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("14.订单结算 - 全额退款"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【维权金额】[维权金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"), + Description(@"订单维权成功提示,维权类型为全额退款 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[维权金额]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFrozen_AllTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("3)、订单通知"), DisplayName("15.订单结算 - 部分退款"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【原始返利积分】[原始返利积分] [积分名称] +【维权返利积分】[维权返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,部分退款,返利将相应减少 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"订单维权成功提示,维权类型为部分退款 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[原始返利积分]、[维权返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFrozen_PartTip { get; set; } + + /// + /// 一级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("16.一级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_OneLevelTip { get; set; } + + /// + /// 二级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("17.二级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_TwoLevelTip { get; set; } + + /// + /// 三级代理获得提成 + /// + [Category("3)、订单通知"), DisplayName("18.三级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_ThreeLevelTip { get; set; } + + /// + /// 群负责人获得提成 + /// + [Category("3)、订单通知"), DisplayName("19.群负责人获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_LeaderTip { get; set; } + + /// + /// 订单退款提示语 + /// + [Category("3)、订单通知"), DisplayName("20.订单申请维权"), DefaultValue(@"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"用户申请退款通知改提示 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRefundTip { get; set; } + + /// + /// 客户维权一级代理 + /// + [Category("3)、订单通知"), DisplayName("21.客户维权一级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_OneLevelTip { get; set; } + + /// + /// 客户维权二级代理 + /// + [Category("3)、订单通知"), DisplayName("22.客户维权二级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_TwoLevelTip { get; set; } + + /// + /// 客户维权三级代理 + /// + [Category("3)、订单通知"), DisplayName("23.客户维权三级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_ThreeLevelTip { get; set; } + + /// + /// 客户维权群负责人 + /// + [Category("3)、订单通知"), DisplayName("24.客户维权群负责人"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_LeaderTip { get; set; } + + /// + /// 订单失效提示语 + /// + [Category("3)、订单通知"), DisplayName("25.订单失效"), DefaultValue(@"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFailureTip { get; set; } + + + /// + /// 订单失效通知一级提示语 + /// + [Category("3)、订单通知"), DisplayName("26.订单失效通知一级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_OneLevelTip { get; set; } + + /// + /// 订单失效通知二级 + /// + [Category("3)、订单通知"), DisplayName("27.订单失效通知二级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_TwoLevelTip { get; set; } + + /// + /// 订单失效通知三级 + /// + [Category("3)、订单通知"), DisplayName("28.订单失效通知三级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_ThreeLevelTip { get; set; } + + /// + /// 订单失效通知群负责人 + /// + [Category("3)、订单通知"), DisplayName("29.订单失效通知群负责人"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_LeaderTip { get; set; } + + #endregion + + #region 查询限制设置 + /// + /// 店铺ID限制提示 + /// + [Category("4)、限制通知"), DisplayName("01.店铺ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[店铺ID]、[店铺名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SellerIDRestrictTip { get; set; } + + /// + /// 商品ID限制提示 + /// + [Category("4)、限制通知"), DisplayName("02.商品ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ItemIDRestrictTip { get; set; } + + /// + /// 拉黑提示 + /// + [Category("4)、限制通知"), DisplayName("03.用户被拉黑"), DefaultValue(@"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string Blocked_RestrictTip { get; set; } + + #endregion + + #region 防撸设置 + /// + /// 同一店铺多次购买(同一商品)开关 + /// + [Browsable(false)] + public bool AShop_SameCommodity_Switch { get; set; } + + /// + /// 同一店铺多次购买(同一商品)数量 + /// + [Browsable(false)] + public int AShop_SameCommodity_Number { get; set; } + + /// + /// 同一店铺多次购买(同一商品)处理方式 + /// + [Browsable(false)] + public OperateType AShop_SameCommodity_OperateType { get; set; } + + /// + /// 同一店铺多次购买(同一商品)置顶 + /// + [Browsable(false)] + public bool AShop_SameCommodity_UserTop { get; set; } + + /// + /// 同一店铺多次购买(不同商品)开关 + /// + [Browsable(false)] + public bool AShop_DifferentCommodity_Switch { get; set; } + + /// + /// 同一店铺多次购买(不同商品)数量 + /// + [Browsable(false)] + public int AShop_DifferentCommodity_Number { get; set; } + + /// + /// 同一店铺多次购买(不同商品)置顶 + /// + [Browsable(false)] + public bool AShop_DifferentCommodity_UserTop { get; set; } + + /// + /// 同一店铺多次购买(不同商品)处理方式 + /// + [Browsable(false)] + public OperateType AShop_DifferentCommodity_OperateType { get; set; } + + /// + /// 收货时间验证开关 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_Switch { get; set; } + + /// + /// 收货时间验证时长(小时) + /// + [Browsable(false)] + public int ReceivingTimeCheck_Hour { get; set; } + + /// + /// 收货时间验证处理方式 + /// + [Browsable(false)] + public OperateType ReceivingTimeCheck_OperateType { get; set; } + + /// + /// 收货时间验证置顶 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_UserTop { get; set; } + + /// + /// 收货时间验证订单冻结时间 + /// + [Browsable(false)] + public int ReceivingTimeCheck_FreezeTime { get; set; } + + /// + /// 屏蔽的商品ID集合 + /// + [Browsable(false)] + public List ItemIDRestrictList { get; set; } + + /// + /// 屏蔽的卖家ID集合 + /// + [Browsable(false)] + public List SellerIDRestrictlist { get; set; } + + ///// + ///// 钉钉Api + ///// + //[Browsable(false)] + //public string Abnormal_DingDingApi { get; set; } + + ///// + ///// 钉钉token值 + ///// + //[Browsable(false)] + //public string Abnormal_DingDingApiToken { get; set; } + + [Browsable(false)] + public string notice_robotname { get; set; } + + #endregion + + public Config() + { + this.SellerIDRestrictTip = @"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"; + this.ItemIDRestrictTip = @"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"; + this.Blocked_RestrictTip = @"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"; + + this.AShop_SameCommodity_Switch = false; + this.AShop_SameCommodity_Number = 10; + this.AShop_SameCommodity_OperateType = OperateType.通知钉钉群; + this.AShop_SameCommodity_UserTop = false; + this.AShop_DifferentCommodity_Switch = false; + this.AShop_DifferentCommodity_Number = 10; + this.AShop_DifferentCommodity_UserTop = false; + this.AShop_DifferentCommodity_OperateType = OperateType.通知钉钉群; + this.ReceivingTimeCheck_Switch = false; + this.ReceivingTimeCheck_Hour = 24; + this.ReceivingTimeCheck_OperateType = OperateType.订单冻结; + this.ReceivingTimeCheck_FreezeTime = 24; + this.ReceivingTimeCheck_UserTop = false; + this.notice_robotname = string.Empty; + + this.ItemIDRestrictList = new List(); + this.SellerIDRestrictlist = new List(); + + this.Point = 20; + this.OrderNum = 20; + this.NoCouponModeSwitch = SwitchType.关闭; + this.UserOrderChangeSwitch = SwitchType.开启; + this.PrincipalReceivedCommissionSwitch = SwitchType.关闭; + this.AgentReceivedCommissionSwitch = SwitchType.关闭; + this.QQSearchSuccessWithoutCouponTip = string.Empty; + this.QQSearchSuccessWithCouponTip = string.Empty; + this.SearchingTip = @"优惠信息查询中....."; + this.SearchSuccessWithCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"; + this.SearchSuccessWithoutCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"; + this.SearchNoCommissionTip = @"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"; + this.OrderRepetBindTip = @"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentTip = @"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentInform_OneLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_TwoLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_ThreeLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_LeaderTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderFailureTip = @"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderCountermandInform_OneLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_TwoLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_ThreeLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_LeaderTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderRefundTip = @"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderFreezeTip = @"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"; + this.OrderSettlementTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OccupyOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"; + this.NotFoundOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"; + this.OrderFrozen_AllTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【维权金额】[维权金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"; + this.OrderFrozen_PartTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【原始返利积分】[原始返利积分] [积分名称] +【维权返利积分】[维权返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,部分退款,返利将相应减少 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_OneLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_TwoLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_ThreeLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_LeaderTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_OneLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_TwoLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_ThreeLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_LeaderTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + } + + } +} diff --git a/应用/SNRebate/Entitys/fl_plugin_snrebate_sntgw.cs b/应用/SNRebate/Entitys/fl_plugin_snrebate_sntgw.cs new file mode 100644 index 0000000..f8c06ed --- /dev/null +++ b/应用/SNRebate/Entitys/fl_plugin_snrebate_sntgw.cs @@ -0,0 +1,45 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SNRebate.Entitys +{ + class fl_plugin_snrebate_sntgw : base_model + { + /// + /// 左连接主表 fl_robot_info 的主键 + /// + public int robot_id { get; set; } + /// + /// 主推广位CPS名称 + /// + public string pid_chief_cps_name { get; set; } + /// + /// 主推广位id + /// + public string pid_chief { get; set; } + /// + /// 主推广位昵称 + /// + public string pid_chief_name { get; set; } + /// + /// 副推广位CPS名称 + /// + public string pid_deputy_cps_name { get; set; } + /// + /// 副推广位id + /// + public string pid_deputy { get; set; } + /// + /// 副推广位名称 + /// + public string pid_deputy_name { get; set; } + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } +} diff --git a/应用/SNRebate/Entitys/sninfo_temp.cs b/应用/SNRebate/Entitys/sninfo_temp.cs new file mode 100644 index 0000000..cc24103 --- /dev/null +++ b/应用/SNRebate/Entitys/sninfo_temp.cs @@ -0,0 +1,94 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SNRebate.Entitys +{ + /// + /// 临时的表 (用于数据显示) + /// + public class sninfo_temp + { + public long ID { get; set; } + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string name { get; set; } + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 主推广位cps名称 + /// + private string _pid_chief_cps_name { get; set; } + public string pid_chief_cps_name + { + get { return _pid_chief_cps_name; } + set { _pid_chief_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_chief; + /// + /// 主推广位id + /// + public string pid_chief + { + get { return _pid_chief; } + set { _pid_chief = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 主推广位昵称 + /// + private string _pid_chief_name; + + public string pid_chief_name + { + get { return _pid_chief_name; } + set { _pid_chief_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位cps名称 + /// + private string _pid_deputy_cps_name { get; set; } + public string pid_deputy_cps_name + { + get { return _pid_deputy_cps_name; } + set { _pid_deputy_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_deputy; + + /// + /// 副推广位id + /// + public string pid_deputy + { + get { return _pid_deputy; } + set { _pid_deputy = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 副推广位名称 + /// + private string _pid_deputy_name; + + public string pid_deputy_name + { + get { return _pid_deputy_name; } + set { _pid_deputy_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } +} diff --git a/应用/SNRebate/MainForm.Designer.cs b/应用/SNRebate/MainForm.Designer.cs new file mode 100644 index 0000000..4f0e541 --- /dev/null +++ b/应用/SNRebate/MainForm.Designer.cs @@ -0,0 +1,779 @@ +namespace SNRebate +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl19 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox4 = new System.Windows.Forms.ComboBox(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit6 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown4 = new System.Windows.Forms.NumericUpDown(); + this.comboBox3 = new System.Windows.Forms.ComboBox(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl32 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl31 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.xtraTabPage3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(991, 577); + this.xtraTabControl1.TabIndex = 9; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(989, 553); + this.xtraTabPage1.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(224, 189); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 7; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 516); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(989, 37); + this.pageControl1.TabIndex = 5; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(989, 508); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "平台类型"; + this.gridColumn1.FieldName = "chattype"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 110; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 164; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 138; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "主推广位"; + this.gridColumn5.FieldName = "pid_chief_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 148; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "副推广位"; + this.gridColumn7.FieldName = "pid_deputy_name"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 130; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "禁止使用"; + this.gridColumn9.FieldName = "onoff"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 6; + this.gridColumn9.Width = 109; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(989, 553); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(989, 553); + this.settingControl1.TabIndex = 0; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupBox1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.PageVisible = false; + this.xtraTabPage3.Size = new System.Drawing.Size(989, 553); + this.xtraTabPage3.Text = " 防 撸 设 置 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.labelControl19); + this.groupBox1.Controls.Add(this.comboBox4); + this.groupBox1.Controls.Add(this.labelControl20); + this.groupBox1.Controls.Add(this.separatorControl2); + this.groupBox1.Controls.Add(this.separatorControl1); + this.groupBox1.Controls.Add(this.checkBox3); + this.groupBox1.Controls.Add(this.checkBox2); + this.groupBox1.Controls.Add(this.checkBox1); + this.groupBox1.Controls.Add(this.buttonCheck2); + this.groupBox1.Controls.Add(this.buttonCheck1); + this.groupBox1.Controls.Add(this.buttonCheck); + this.groupBox1.Controls.Add(this.memoEdit6); + this.groupBox1.Controls.Add(this.memoEdit5); + this.groupBox1.Controls.Add(this.numericUpDown2); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.numericUpDown4); + this.groupBox1.Controls.Add(this.comboBox3); + this.groupBox1.Controls.Add(this.comboBox2); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Controls.Add(this.labelControl30); + this.groupBox1.Controls.Add(this.labelControl32); + this.groupBox1.Controls.Add(this.numericUpDown3); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl31); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl29); + this.groupBox1.Controls.Add(this.labelControl28); + this.groupBox1.Controls.Add(this.labelControl27); + this.groupBox1.Location = new System.Drawing.Point(38, 25); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(916, 498); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础设置 "; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(651, 188); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(215, 14); + this.labelControl5.TabIndex = 60; + this.labelControl5.Text = "(在【系统管理->群通知机器人】中添加)"; + // + // labelControl19 + // + this.labelControl19.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl19.Appearance.Options.UseForeColor = true; + this.labelControl19.Location = new System.Drawing.Point(505, 188); + this.labelControl19.Name = "labelControl19"; + this.labelControl19.Size = new System.Drawing.Size(130, 14); + this.labelControl19.TabIndex = 59; + this.labelControl19.Text = "(未选择时使用系统设置)"; + // + // comboBox4 + // + this.comboBox4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox4.FormattingEnabled = true; + this.comboBox4.Location = new System.Drawing.Point(170, 185); + this.comboBox4.Name = "comboBox4"; + this.comboBox4.Size = new System.Drawing.Size(308, 22); + this.comboBox4.TabIndex = 58; + // + // labelControl20 + // + this.labelControl20.Location = new System.Drawing.Point(73, 188); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(91, 14); + this.labelControl20.TabIndex = 57; + this.labelControl20.Text = "群通知API接口:"; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(44, 103); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(823, 23); + this.separatorControl2.TabIndex = 32; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(44, 50); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(823, 23); + this.separatorControl1.TabIndex = 32; + // + // checkBox3 + // + this.checkBox3.AutoSize = true; + this.checkBox3.Location = new System.Drawing.Point(651, 133); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.Size = new System.Drawing.Size(108, 18); + this.checkBox3.TabIndex = 31; + this.checkBox3.Text = "置顶用户(微信)"; + this.checkBox3.UseVisualStyleBackColor = true; + this.checkBox3.Visible = false; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(651, 81); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(108, 18); + this.checkBox2.TabIndex = 31; + this.checkBox2.Text = "置顶用户(微信)"; + this.checkBox2.UseVisualStyleBackColor = true; + this.checkBox2.Visible = false; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(651, 28); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(108, 18); + this.checkBox1.TabIndex = 31; + this.checkBox1.Text = "置顶用户(微信)"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.Visible = false; + // + // buttonCheck2 + // + this.buttonCheck2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = true; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(89, 132); + this.buttonCheck2.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(57, 22); + this.buttonCheck2.TabIndex = 28; + // + // buttonCheck1 + // + this.buttonCheck1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = true; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(89, 79); + this.buttonCheck1.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(57, 22); + this.buttonCheck1.TabIndex = 28; + // + // buttonCheck + // + this.buttonCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck.Checked = true; + this.buttonCheck.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck.Location = new System.Drawing.Point(89, 26); + this.buttonCheck.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck.Name = "buttonCheck"; + this.buttonCheck.Size = new System.Drawing.Size(57, 22); + this.buttonCheck.TabIndex = 28; + // + // memoEdit6 + // + this.memoEdit6.Location = new System.Drawing.Point(50, 389); + this.memoEdit6.Name = "memoEdit6"; + this.memoEdit6.Size = new System.Drawing.Size(817, 96); + this.memoEdit6.TabIndex = 26; + // + // memoEdit5 + // + this.memoEdit5.Location = new System.Drawing.Point(50, 263); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Size = new System.Drawing.Size(817, 96); + this.memoEdit5.TabIndex = 27; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(708, 131); + this.numericUpDown2.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(75, 22); + this.numericUpDown2.TabIndex = 22; + this.numericUpDown2.Value = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.numericUpDown2.Visible = false; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(264, 132); + this.numericUpDown1.Maximum = new decimal(new int[] { + 999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(91, 22); + this.numericUpDown1.TabIndex = 22; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // numericUpDown4 + // + this.numericUpDown4.Location = new System.Drawing.Point(370, 79); + this.numericUpDown4.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown4.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown4.Name = "numericUpDown4"; + this.numericUpDown4.Size = new System.Drawing.Size(93, 22); + this.numericUpDown4.TabIndex = 22; + this.numericUpDown4.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // comboBox3 + // + this.comboBox3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox3.FormattingEnabled = true; + this.comboBox3.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群", + "订单冻结"}); + this.comboBox3.Location = new System.Drawing.Point(507, 131); + this.comboBox3.Name = "comboBox3"; + this.comboBox3.Size = new System.Drawing.Size(121, 22); + this.comboBox3.TabIndex = 25; + // + // comboBox2 + // + this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox2.Location = new System.Drawing.Point(507, 79); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(121, 22); + this.comboBox2.TabIndex = 25; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox1.Location = new System.Drawing.Point(507, 26); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(121, 22); + this.comboBox1.TabIndex = 25; + // + // labelControl30 + // + this.labelControl30.Location = new System.Drawing.Point(471, 83); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(16, 14); + this.labelControl30.TabIndex = 16; + this.labelControl30.Text = "次."; + // + // labelControl32 + // + this.labelControl32.Location = new System.Drawing.Point(50, 369); + this.labelControl32.Name = "labelControl32"; + this.labelControl32.Size = new System.Drawing.Size(72, 14); + this.labelControl32.TabIndex = 17; + this.labelControl32.Text = "屏蔽店铺ID:"; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(370, 26); + this.numericUpDown3.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown3.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(93, 22); + this.numericUpDown3.TabIndex = 23; + this.numericUpDown3.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(128, 369); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(132, 14); + this.labelControl2.TabIndex = 18; + this.labelControl2.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl1 + // + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(128, 243); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(132, 14); + this.labelControl1.TabIndex = 18; + this.labelControl1.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl31 + // + this.labelControl31.Location = new System.Drawing.Point(50, 243); + this.labelControl31.Name = "labelControl31"; + this.labelControl31.Size = new System.Drawing.Size(72, 14); + this.labelControl31.TabIndex = 18; + this.labelControl31.Text = "屏蔽商品ID:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(653, 135); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(48, 14); + this.labelControl8.TabIndex = 19; + this.labelControl8.Text = "订单冻结"; + this.labelControl8.Visible = false; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(789, 135); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(28, 14); + this.labelControl7.TabIndex = 19; + this.labelControl7.Text = "小时."; + this.labelControl7.Visible = false; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(373, 136); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(64, 14); + this.labelControl4.TabIndex = 19; + this.labelControl4.Text = "小时内收货."; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(170, 136); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 19; + this.labelControl3.Text = "用户购买的商品"; + // + // labelControl29 + // + this.labelControl29.Location = new System.Drawing.Point(170, 83); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(190, 14); + this.labelControl29.TabIndex = 19; + this.labelControl29.Text = "用户在同家店铺多次购物(不同商品)"; + // + // labelControl28 + // + this.labelControl28.Location = new System.Drawing.Point(471, 30); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(16, 14); + this.labelControl28.TabIndex = 20; + this.labelControl28.Text = "次."; + // + // labelControl27 + // + this.labelControl27.Location = new System.Drawing.Point(170, 30); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(190, 14); + this.labelControl27.TabIndex = 21; + this.labelControl27.Text = "用户在同家店铺多次购买(同一商品)"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(991, 577); + this.Controls.Add(this.xtraTabControl1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl19; + private System.Windows.Forms.ComboBox comboBox4; + private DevExpress.XtraEditors.LabelControl labelControl20; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private System.Windows.Forms.CheckBox checkBox3; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.CheckBox checkBox1; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private UI.Framework.Controls.ButtonCheck buttonCheck; + private DevExpress.XtraEditors.MemoEdit memoEdit6; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.NumericUpDown numericUpDown4; + private System.Windows.Forms.ComboBox comboBox3; + private System.Windows.Forms.ComboBox comboBox2; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.LabelControl labelControl30; + private DevExpress.XtraEditors.LabelControl labelControl32; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl31; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl29; + private DevExpress.XtraEditors.LabelControl labelControl28; + private DevExpress.XtraEditors.LabelControl labelControl27; + } +} \ No newline at end of file diff --git a/应用/SNRebate/MainForm.cs b/应用/SNRebate/MainForm.cs new file mode 100644 index 0000000..16f94ee --- /dev/null +++ b/应用/SNRebate/MainForm.cs @@ -0,0 +1,255 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using SNRebate.Entitys; +using SNRebate.Properties; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace SNRebate +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + //加载配置文件 + this.settingControl1.Bind(Class1.Config, 110); + + #region 加载所有的账号 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.苏宁易购}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.苏宁易购}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label1.Visible = gridView1.RowCount == 0; + + #endregion + } + + /// + /// 修改显示内容的事件 + /// + /// + /// + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name" || e.Column.FieldName == "adzone_activity_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.苏宁易购); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzone == null) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzone.extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + #region 有出现两个重复无法修复的情况,删除一个 + var repetAdzone = adzones.Where(f => f.extend == pidName).ToList(); + if (repetAdzone.Count > 1) + { + for (int i = 1; i <= repetAdzone.Count - 1; i++) + { + session.Deleteable(repetAdzone[i]).ExecuteCommand(); + } + adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + } + #endregion + + adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindSnInfoTempGroups(true); + session.FindAdzoneInfos(true); + session.FindWeipinhuiAutoBindPid(true);//刷新推广位 + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzones.Count == 0) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item, false); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzones[0].extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate, adzones[0].onoff); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + if (adzones != null)//数据库中存在 + session.ExcuteSQL("update fl_adzone_info set onoff = @onoff where robot_id = @robot_id and alliance_id = @alliance_id and custom_type = @custom_type", new { onoff = !adzones[0].onoff, robot_id = id, alliance_id = (int)CpsType.苏宁易购, custom_type = Resources.SoftwareType }); + session.FindSnInfoTempGroups(true); + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + session.FindWeipinhuiAutoBindPid(true);//刷新推广位 + } + } + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 创建fl_adzone_info对象 + /// + /// + /// + /// + /// + /// + /// + private fl_adzone_info CreateAdzoneInfo(string adzone_name, string adzone_pid, string adzone_pid_cps_name, string rid, string item, bool onoff = false) + { + return new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = adzone_name, //推广位名称 + adzone_pid = adzone_pid, //推广位pid + adzone_pid_cps_name = adzone_pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.苏宁易购, //联盟id + robot_id = int.Parse(rid), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = onoff, //不禁用 + extend = item + }; + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Api.Framework.Tools.Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} diff --git a/应用/SNRebate/MainForm.resx b/应用/SNRebate/MainForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/SNRebate/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/SNRebate/Properties/AssemblyInfo.cs b/应用/SNRebate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6c23ed1 --- /dev/null +++ b/应用/SNRebate/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("SNRebate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SNRebate")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("6b5413f2-9202-4b3e-8e79-a6c60be9cc7b")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/SNRebate/Properties/Resources.Designer.cs b/应用/SNRebate/Properties/Resources.Designer.cs new file mode 100644 index 0000000..58d4a83 --- /dev/null +++ b/应用/SNRebate/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace SNRebate.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SNRebate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 苏宁返利 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 苏宁返利 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 苏宁返利插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 苏宁返利 的本地化字符串。 + /// + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 苏宁 { + get { + object obj = ResourceManager.GetObject("苏宁", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/SNRebate/Properties/Resources.resx b/应用/SNRebate/Properties/Resources.resx new file mode 100644 index 0000000..f226d45 --- /dev/null +++ b/应用/SNRebate/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 苏宁返利 + + + 苏宁返利 + + + 苏宁返利插件 + + + 苏宁返利 + + + + ..\Resources\苏宁.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/SNRebate/Properties/licenses.licx b/应用/SNRebate/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/SNRebate/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/SNRebate/Resources/苏宁.png b/应用/SNRebate/Resources/苏宁.png new file mode 100644 index 0000000..5cc7c90 Binary files /dev/null and b/应用/SNRebate/Resources/苏宁.png differ diff --git a/应用/SNRebate/SNRebate.csproj b/应用/SNRebate/SNRebate.csproj new file mode 100644 index 0000000..af1c381 --- /dev/null +++ b/应用/SNRebate/SNRebate.csproj @@ -0,0 +1,123 @@ + + + + + Debug + AnyCPU + {6B5413F2-9202-4B3E-8E79-A6C60BE9CC7B} + Library + Properties + SNRebate + SNRebate + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/SNRebate/SessionExt.cs b/应用/SNRebate/SessionExt.cs new file mode 100644 index 0000000..bd48c77 --- /dev/null +++ b/应用/SNRebate/SessionExt.cs @@ -0,0 +1,42 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using SNRebate.Entitys; +using SNRebate.Properties; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SNRebate +{ + public static class SessionExt + { + const string sninfo_temp_list_snrebate = "sninfo_temp_list_snrebate"; + + /// + /// 获取fl_adzone_info表的数据集合缓存 + /// + /// + /// 刷新 + /// + public static List FindSnInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + + var sninfo_temp_groups = ApiClient.Cache.Get>(sninfo_temp_list_snrebate);//根据KEY、获得缓存 + if (refresh || sninfo_temp_groups == null) + { + sninfo_temp_groups = session.Find($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.苏宁易购}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.苏宁易购}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id"); + ApiClient.Cache.Set(sninfo_temp_list_snrebate, sninfo_temp_groups, 60); + } + return sninfo_temp_groups; + } + + public static void Clear() + { + ApiClient.Cache.Remove(sninfo_temp_list_snrebate); + } + } +} diff --git a/应用/SignContacts/Class1.cs b/应用/SignContacts/Class1.cs new file mode 100644 index 0000000..82bacd6 --- /dev/null +++ b/应用/SignContacts/Class1.cs @@ -0,0 +1,479 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using SignContacts.Entitys; +using SignContacts.Enums; +using SignContacts.Properties; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace SignContacts +{ + public class Class1 : Plugin + { + + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.标记; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist()) + { + session.CreateTable(); + session.AddUnique("signtype", "amount"); + + session.Insertable(new List(){ + new fl_plugin_signcontacts_sign_info() { signtype = SignType.好友天数,amount = 5,sign = "C"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.好友天数,amount = 15,sign = "B"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.好友天数,amount = 99999,sign = "A"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.推荐人数,amount = 5,sign = "▲"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.推荐人数,amount = 15,sign = "★"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.推荐人数,amount = 99999,sign = "◆"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.查询次数,amount = 5,sign = "。"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.查询次数,amount = 50,sign = "o"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.查询次数,amount = 99999,sign = "O"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.订单总数,amount = 5,sign = "M"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.订单总数,amount = 50,sign = "K"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.订单总数,amount = 99999,sign = "P"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.退款总数,amount = 20,sign = "Υ"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.退款总数,amount = 100,sign = "γ"}, + new fl_plugin_signcontacts_sign_info() { signtype = SignType.退款总数,amount = 99999,sign = "Ψ"} + }).ExecuteCommand(); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + SDK.WXNewFriendEvent += SDK_WXNewFriendEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + SDK.SharedEvent += SDK_SharedEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// + /// 新加好友 + /// + /// + /// + private void SDK_WXNewFriendEvent(object sender, Chat.Framework.WXSdk.Events.WXNewFriend e) + { + var session = ApiClient.GetSession(); + var member = session.Find("select * from fl_member_info where username = @username", new { username = e.Friend.UserName }).FirstOrDefault(); + if (member == null) + { + member = new fl_member_info() { crt_time = DateTime.Now, usernick = e.Friend.NickName, realnick = e.Friend.NickName, robot_name = e.Client.WeixinHao, robot_type = e.Client.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信, username = e.Friend.UserName, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + member = session.Saveable(member).ExecuteReturnEntity(); + } + NewUsername(e.Client, member, UserType.新用户); + } + + private void SDK_SharedEvent(object sender, Api.Framework.Events.SharedEvents e) + { + try + { + if (Config.NotesSwitch == Api.Framework.Enums.SwitchType.开启) + { + if (e.Shareds != null && e.Shareds.ContainsKey("msg_type") && e.Shareds["msg_type"].ToString() == "查询宝贝") + { + var wx = sender as WeixinBase; + if (wx == null) return; + + var session = ApiClient.GetSession(); + string username = e.Shareds["msg_username"].ToString(); + + var member = session.Find("select * from fl_member_info where username = @username", new { username = username }).FirstOrDefault(); + if (member == null) return; + + //if (!string.IsNullOrWhiteSpace(Config.NotesFormat_QueryNotOrder)) + //{ + // #region 首次查询 + // var incomeResult = session.FindSingle(@"select * from fl_statistics_record where uid = @userid and querynum = 1", new { userid = member.id }); + // if (incomeResult != null) + // { + // if (member.bind_order != 0 || member.finish_order != 0) return; + // var orderCount = 0; + // orderCount += session.Find("select * from fl_order_alimama where db_userid = @db_userid", new { db_userid = member.id }).Count; + // if (orderCount == 0) + // { + // orderCount += session.Find("select * from fl_order_jingdong where db_userid = @db_userid", new { db_userid = member.id }).Count; + // if (orderCount == 0) + // orderCount += session.Find("select * from fl_order_pinduoduo where db_userid = @db_userid", new { db_userid = member.id }).Count; + // } + // if (orderCount == 0) + // { + // NewUsername(wx, member, UserType.查询未下单); + // return; + // } + // } + // #endregion + //} + + NewUsername(wx, member, UserType.未知); + + //long inviter_id = 0; + //string inviter_username = string.Empty; + + //var notes = _ProcessStr(out inviter_id, out inviter_username, uid: member.id); + //if (!string.IsNullOrWhiteSpace(notes) && member.usernick != notes) + //{ + // wx.EditContacts(e.Shareds["msg_username"].ToString(), EditContactsType.备注, notes); + // member.usernick = notes; + // session.SaveOrUpdate(member); + //} + } + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} - {ex.StackTrace}."); + } + } + + /// + /// 订单通知接口 + /// + /// + /// + private void SDK_OrderNoticeEvent(object sender, Api.Framework.Events.OrderNoticeEvent e) + { + try + { + if (Config.NotesSwitch == Api.Framework.Enums.SwitchType.开启) + { + if (e.Customer == null && e.Member != null) + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == e.Member.robot_name).Value; + if (wx == null || wx.Status != Chat.Framework.WXSdk.WxStatus.在线) + return; + + if (e.Member.bind_order == 1) + NewUsername(wx, e.Member, UserType.首单用户); + else + { + var session = ApiClient.GetSession(); + + var systemOrderStatus = -1; + if (e.Order is fl_order_alimama) + systemOrderStatus = (int)(e.Order as fl_order_alimama).db_status; + if (e.Order is fl_order_pinduoduo) + systemOrderStatus = (int)(e.Order as fl_order_pinduoduo).db_status; + if (e.Order is fl_order_jingdong) + systemOrderStatus = (int)(e.Order as fl_order_jingdong).db_status; + if (e.Order is fl_order_weipinhui) + systemOrderStatus = (int)(e.Order as fl_order_weipinhui).db_status; + if (systemOrderStatus == 1002 || systemOrderStatus == 998 || systemOrderStatus == 999 || systemOrderStatus == 1003) + { + NewUsername(wx, e.Member, UserType.常规用户); + //long inviter_id = 0; + //string inviter_username = string.Empty; + //var notes = _ProcessStr(out inviter_id, out inviter_username, username: e.Member.username); + //if (!string.IsNullOrWhiteSpace(notes) && e.Member.usernick != notes) + //{ + // wx.EditContacts(e.Member.username, EditContactsType.备注, notes); + // e.Member.usernick = notes; + // session.SaveOrUpdate(e.Member); + //} + } + } + } + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} - {ex.StackTrace}"); + } + } + + public void NewUsername(WeixinBase wx, fl_member_info member, UserType userType) + { + try + { + if (Config.NotesSwitch == Api.Framework.Enums.SwitchType.开启 && !(string.IsNullOrWhiteSpace(Config.NotesFormat) && string.IsNullOrWhiteSpace(Config.NotesFormat_FirstOrder) && string.IsNullOrWhiteSpace(Config.NotesFormat_NewFirend) && string.IsNullOrWhiteSpace(Config.NotesFormat_QueryNotOrder))) + { + var session = ApiClient.GetSession(); + var format = string.Empty; + switch (userType) + { + case UserType.新用户: + format = Config.NotesFormat_NewFirend; + break; + case UserType.查询未下单: + format = Config.NotesFormat_QueryNotOrder; + break; + case UserType.首单用户: + format = Config.NotesFormat_FirstOrder; + break; + case UserType.常规用户: + format = Config.NotesFormat; + break; + case UserType.未知: + { + #region 判断是查询过 + var incomeResult = session.FindSingle(@"select * from fl_statistics_record where uid = @userid", new { userid = member.id }); + if (incomeResult != null) + { + if (incomeResult.querynum == 0) + format = Config.NotesFormat_NewFirend; + else + { + if (member.bind_order <= 0) + format = Config.NotesFormat_QueryNotOrder; + else if (member.bind_order == 1) + format = Config.NotesFormat_FirstOrder; + else + format = Config.NotesFormat; + } + } + else + { + if (member.bind_order <= 0) + format = Config.NotesFormat_NewFirend; + else if (member.bind_order == 1) + format = Config.NotesFormat_FirstOrder; + else if (member.bind_order > 1) + format = Config.NotesFormat; + //else + // format = Config.NotesFormat_QueryNotOrder; + } + #endregion + } + break; + } + + if (string.IsNullOrWhiteSpace(format) && !string.IsNullOrWhiteSpace(Config.NotesFormat)) + format = Config.NotesFormat; + + //if (string.IsNullOrWhiteSpace(format)) + // return; + + long inviter_id = 0; + string inviter_username = string.Empty; + + var notes = string.Empty; + //var member = session.Find("select * from fl_member_info where username = @username", new { username = username }).FirstOrDefault(); + if (member != null) + { + notes = _ProcessStr(format, out inviter_id, out inviter_username, uid: member.id); + if (!string.IsNullOrWhiteSpace(notes) && member.usernick != notes) + { + this.OnLog($"{member.usernick}({member.username}) => {notes}"); + wx.EditContacts(member.username, EditContactsType.备注, notes); + member.usernick = notes; + session.SaveOrUpdate(member); + Thread.Sleep(1000); + } + else + { + this.OnLog($"{member.usernick}({member.username}) => {notes},和之前一样"); + } + } + + //if (inviter_id != 0 && !string.IsNullOrWhiteSpace(inviter_username)) + //{ + // var inviter_member = session.Find("select * from fl_member_info where username = @username", new { username = inviter_username }).FirstOrDefault(); + // if (inviter_member == null) return; + + // notes = _ProcessStr(format, out inviter_id, out inviter_username, uid: inviter_member.id); + // if (string.IsNullOrWhiteSpace(notes) || inviter_member.usernick == notes) + // return; + // Thread.Sleep(1000); + // wx.EditContacts(inviter_username, EditContactsType.备注, notes); + // inviter_member.usernick = notes; + // session.SaveOrUpdate(inviter_member); + //} + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} . {ex.StackTrace}"); + } + } + + /// + /// 标签/备注 字符串替换方法 + /// + /// 标签/备注 模板 + /// 用户wxid + /// + private string _ProcessStr(string format, out long inviter_id, out string inviter_username, string username = "", long uid = 0) + { + inviter_id = 0; + inviter_username = string.Empty; + if (string.IsNullOrWhiteSpace(format)) + return string.Empty; + + try + { + var session = ApiClient.GetSession(); + fl_member_info member = null; + if (!string.IsNullOrWhiteSpace(username)) + member = session.Find("select * from fl_member_info where username = @username", new { username = username }).FirstOrDefault(); + else if (uid != 0) + member = session.Find("select * from fl_member_info where id = @id", new { id = uid }).FirstOrDefault(); + if (member == null) + return string.Empty; + + var days = (DateTime.Now.Date - member.crt_time.Date).Days; + + #region 查询次数/推荐人数/完成订单数(3)/退款数量(3) + + decimal query_amount = 0m;//查询次数 + decimal invite_amount = 0m;//推荐人数 + decimal order_amount = 0m;//完成订单数 + decimal refund_amount = 0m;//退款订单数 + + var incomeResult = session.FindTable( + //@"select querynum as num from fl_statistics_record where uid = @userid + @"select COALESCE(sum(querynum),0) as num from fl_statistics_record where uid = @userid +UNION ALL +select count(id) as num from fl_member_info where inviter_id = @userid +UNION ALL +select COALESCE(sum(item_num),0) as num from fl_order_alimama where db_userid = @userid and db_status not in (1006,1004) +UNION ALL +select COALESCE(sum(skuNum),0) as num from fl_order_jingdong where db_userid = @userid and db_status not in (1006,1004) +UNION ALL +select COALESCE(sum(goods_quantity),0) as num from fl_order_pinduoduo where db_userid = @userid and db_status not in (1006,1004) +UNION ALL +select COALESCE(sum(item_num),0) as num from fl_order_alimama where db_userid = @userid and db_status in (999,998,1003) +UNION ALL +select COALESCE(sum(skuNum),0) as num from fl_order_jingdong where db_userid = @userid and db_status in (999,998,1003) +UNION ALL +select COALESCE(sum(goods_quantity),0) as num from fl_order_pinduoduo where db_userid = @userid and db_status in (999,998,1003) ", new { userid = member.id }); + if (incomeResult.Rows.Count != 0) + { + query_amount = decimal.Parse(incomeResult.Rows[0]["num"].ToString()); + invite_amount = decimal.Parse(incomeResult.Rows[1]["num"].ToString()); + + order_amount = decimal.Parse(incomeResult.Rows[2]["num"].ToString()) + decimal.Parse(incomeResult.Rows[3]["num"].ToString()) + decimal.Parse(incomeResult.Rows[4]["num"].ToString()); + var ss = incomeResult.Rows[7]; + refund_amount = decimal.Parse(incomeResult.Rows[5]["num"].ToString()) + decimal.Parse(incomeResult.Rows[6]["num"].ToString()) + decimal.Parse(incomeResult.Rows[7]["num"].ToString()); + } + #endregion + + //查询次数/推荐人数/完成订单数/退款数量 + var signQuery = session.FindSignInfo(SignType.查询次数, (long)query_amount); + var signInvite = session.FindSignInfo(SignType.推荐人数, (long)invite_amount); + var signOrder = session.FindSignInfo(SignType.订单总数, (long)order_amount); + var signRefund = session.FindSignInfo(SignType.退款总数, (long)refund_amount); + var signDays = session.FindSignInfo(SignType.好友天数, days); + inviter_id = member.inviter_id; + inviter_username = member.username; + + //var format = string.Empty; + + //if (Config.NotesSwitch == Api.Framework.Enums.SwitchType.开启 && !(string.IsNullOrWhiteSpace(Config.NotesFormat) && string.IsNullOrWhiteSpace(Config.NotesFormat_FirstOrder) && string.IsNullOrWhiteSpace(Config.NotesFormat_NewFirend) && string.IsNullOrWhiteSpace(Config.NotesFormat_QueryNotOrder))) + + + //if (order_amount <= 0 && !string.IsNullOrWhiteSpace(Config.NotesFormat_NotOrder)) + // format = Config.NotesFormat_NotOrder; + //if (string.IsNullOrWhiteSpace(format) && !string.IsNullOrWhiteSpace(Config.NotesFormat)) + // format = Config.NotesFormat; + + //if (string.IsNullOrWhiteSpace(format)) + // return string.Empty; + + + + #region 最后下单时间 + var last_buy_time = DateTime.MinValue; + if (format.Contains("[最后下单")) + { + var tb_data = session.Queryable().OrderBy(f => f.create_time, SqlSugar.OrderByType.Desc).Where(f => f.db_userid == member.id).First(); + var jd_data = session.Queryable().OrderBy(f => f.orderTime, SqlSugar.OrderByType.Desc).Where(f => f.db_userid == member.id).First(); + var pdd_data = session.Queryable().OrderBy(f => f.order_create_time, SqlSugar.OrderByType.Desc).Where(f => f.db_userid == member.id).First(); + var wph_data = session.Queryable().OrderBy(f => f.orderTime, SqlSugar.OrderByType.Desc).Where(f => f.db_userid == member.id).First(); + if (tb_data != null) + last_buy_time = last_buy_time < tb_data.create_time ? tb_data.create_time : last_buy_time; + if (jd_data != null) + last_buy_time = last_buy_time < jd_data.orderTime ? jd_data.orderTime : last_buy_time; + if (pdd_data != null) + last_buy_time = last_buy_time < pdd_data.order_create_time ? pdd_data.order_create_time : last_buy_time; + if (wph_data != null) + last_buy_time = last_buy_time < Util.GetDateTime(wph_data.orderTime) ? Util.GetDateTime(wph_data.orderTime) : last_buy_time; + } + #endregion + + return format + .Replace("[编号]", member.id.ToString()) + .Replace("[天数]", signDays.sign) + .Replace("[查询]", signQuery.sign) + .Replace("[订单]", signOrder.sign) + .Replace("[退款]", signRefund.sign) + .Replace("[推荐]", signInvite.sign) + .Replace("[昵称]", member.realnick) + .Replace("[上级编码]", member.inviter_id.ToString()) + .Replace("[最后下单时间]", (last_buy_time == DateTime.MinValue ? "" : last_buy_time.ToString("yyyy-MM-dd HH:mm:ss"))) + .Replace("[最后下单年]", (last_buy_time == DateTime.MinValue ? "" : last_buy_time.ToString("yyyy"))) + .Replace("[最后下单月]", (last_buy_time == DateTime.MinValue ? "" : last_buy_time.ToString("MM"))) + .Replace("[最后下单日]", (last_buy_time == DateTime.MinValue ? "" : last_buy_time.ToString("dd"))) + .Replace("[好友注册时间]", (member.crt_time == DateTime.MinValue ? "" : member.crt_time.ToString("yyyy-MM-dd HH:mm:ss"))) + .Replace("[好友注册年]", (member.crt_time == DateTime.MinValue ? "" : member.crt_time.ToString("yyyy"))) + .Replace("[好友注册月]", (member.crt_time == DateTime.MinValue ? "" : member.crt_time.ToString("MM"))) + .Replace("[好友注册日]", (member.crt_time == DateTime.MinValue ? "" : member.crt_time.ToString("dd"))); + } + catch (Exception ex) + { } + return string.Empty; + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/SignContacts/Common.cs b/应用/SignContacts/Common.cs new file mode 100644 index 0000000..1d93611 --- /dev/null +++ b/应用/SignContacts/Common.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; +using System.Web.Caching; + +namespace SignContacts +{ + public class Common + { + /// + /// 缓存是否存在 + /// + /// + /// + /// + /// + public static bool GetCache(string text) + { + try + { + Cache cache = HttpRuntime.Cache; + object item = cache[text]; + return item != null ? true : false; + } + catch (Exception) + { } + return false; + } + + /// + /// 设置缓存(辅助输入) + /// + /// + /// + /// + /// + public static bool SetCache(string text) + { + try + { + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[text]; + if (item == null) + cache.Insert(text, 1, null, DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + } +} diff --git a/应用/SignContacts/Config.cs b/应用/SignContacts/Config.cs new file mode 100644 index 0000000..bea03fc --- /dev/null +++ b/应用/SignContacts/Config.cs @@ -0,0 +1,79 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SignContacts +{ + [Config(Name = "插件-自动打标签-配置")] + public class Config + { + + #region 自定义变量 + /// + /// 好友天数变量 + /// + public string DayVariate { get; set; } = "[天数]"; + /// + /// 查询次数变量 + /// + public string QueryVariate { get; set; } = "[查询]"; + /// + /// 订单数量变量 + /// + public string OrderVariate { get; set; } = "[订单]"; + /// + /// 退款变量 + /// + public string RefundVariate { get; set; } = "[退款]"; + /// + /// 推荐人数变量 + /// + public string InviteVariate { get; set; } = "[推荐]"; + + #endregion + + #region 标记/备注格式 + /// + /// 备注功能开关 + /// + public SwitchType NotesSwitch { get; set; } = SwitchType.关闭; + /// + /// 老客户备注格式 + /// + public string NotesFormat { get; set; } = "ID[编号]-[查询]/[订单]/[退款]/[推荐]"; + + /// + /// 新用户首单格式 + /// + public string NotesFormat_FirstOrder { get; set; } = string.Empty; + + /// + /// 查询未下单格式 + /// + public string NotesFormat_QueryNotOrder { get; set; } = string.Empty; + + /// + /// 新用户格式 + /// + public string NotesFormat_NewFirend { get; set; } = string.Empty; + + /// + /// 不用了 + /// + //public SwitchType NotesSwitch_NotOrder { get; set; } = SwitchType.关闭; + /// + /// 不用了 + /// + //public string NotesFormat_NotOrder { get; set; } = "A [编号]-[昵称]/[推荐]"; + + #endregion + + + + + } +} diff --git a/应用/SignContacts/Entitys/fl_plugin_signcontacts_sign_info.cs b/应用/SignContacts/Entitys/fl_plugin_signcontacts_sign_info.cs new file mode 100644 index 0000000..bfbdfb4 --- /dev/null +++ b/应用/SignContacts/Entitys/fl_plugin_signcontacts_sign_info.cs @@ -0,0 +1,22 @@ +using Api.Framework.Tools; +using SignContacts.Enums; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SignContacts.Entitys +{ + public class fl_plugin_signcontacts_sign_info : base_model + { + + public SignType signtype { get; set; } + + public long amount { get; set; } + + public string sign { get; set; } + + } +} diff --git a/应用/SignContacts/Enums/SignType.cs b/应用/SignContacts/Enums/SignType.cs new file mode 100644 index 0000000..4107ece --- /dev/null +++ b/应用/SignContacts/Enums/SignType.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SignContacts.Enums +{ + /// + /// 打标记条件 + /// + public enum SignType + { + 好友天数 = 0, + 查询次数 = 1, + 订单总数 = 2, + 退款总数 = 3, + 推荐人数 = 4 + } + + /// + /// 用户类型 + /// + public enum UserType + { + 新用户 = 0, + 查询未下单 = 1, + 首单用户 = 2, + 常规用户 = 3, + 未知 = 4 + } + +} diff --git a/应用/SignContacts/MainForm.Designer.cs b/应用/SignContacts/MainForm.Designer.cs new file mode 100644 index 0000000..4164051 --- /dev/null +++ b/应用/SignContacts/MainForm.Designer.cs @@ -0,0 +1,1001 @@ +namespace SignContacts +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit5 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage5 = new DevExpress.XtraTab.XtraTabPage(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.te_NotesFormat = new DevExpress.XtraEditors.TextEdit(); + this.te_QueryNotOrder = new DevExpress.XtraEditors.TextEdit(); + this.bc_NotesSwitch = new UI.Framework.Controls.ButtonCheck(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl8 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl4 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl5 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl6 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl12 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl7 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl9 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl10 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl11 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.button1 = new System.Windows.Forms.Button(); + this.hyperlinkLabelControl16 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl15 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl14 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl13 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.te_FirstOrder = new DevExpress.XtraEditors.TextEdit(); + this.te_NewFriend = new DevExpress.XtraEditors.TextEdit(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl13 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuS_Down = new System.Windows.Forms.ContextMenuStrip(this.components); + this.导出为EceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog(); + this.labelControl14 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.te_NotesFormat.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.te_QueryNotOrder.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.te_FirstOrder.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.te_NewFriend.Properties)).BeginInit(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuS_Down.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.SuspendLayout(); + // + // gridView1 + // + this.gridView1.Name = "gridView1"; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.groupControl4); + this.groupControl1.Controls.Add(this.groupControl3); + this.groupControl1.Controls.Add(this.xtraTabControl1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupControl1.Location = new System.Drawing.Point(3, 3); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(690, 412); + this.groupControl1.TabIndex = 0; + this.groupControl1.Text = "代号设置"; + // + // groupControl4 + // + this.groupControl4.Controls.Add(this.numericUpDown1); + this.groupControl4.Controls.Add(this.radioGroup1); + this.groupControl4.Controls.Add(this.labelControl9); + this.groupControl4.Controls.Add(this.labelControl8); + this.groupControl4.Controls.Add(this.textEdit5); + this.groupControl4.Controls.Add(this.labelControl7); + this.groupControl4.Controls.Add(this.simpleButton3); + this.groupControl4.Controls.Add(this.simpleButton2); + this.groupControl4.Controls.Add(this.simpleButton1); + this.groupControl4.Controls.Add(this.labelControl6); + this.groupControl4.Controls.Add(this.labelControl5); + this.groupControl4.Controls.Add(this.textEdit4); + this.groupControl4.Controls.Add(this.labelControl4); + this.groupControl4.Controls.Add(this.labelControl3); + this.groupControl4.Location = new System.Drawing.Point(306, 67); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(377, 335); + this.groupControl4.TabIndex = 2; + this.groupControl4.Text = "代号编辑"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(119, 178); + this.numericUpDown1.Maximum = new decimal(new int[] { + 1410065407, + 2, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(94, 22); + this.numericUpDown1.TabIndex = 15; + // + // radioGroup1 + // + this.radioGroup1.Location = new System.Drawing.Point(124, 36); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "天数", true, 0), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "查询", true, 1), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "订单", true, 2), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "退款", true, 3), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "推荐", true, 4)}); + this.radioGroup1.Size = new System.Drawing.Size(203, 72); + this.radioGroup1.TabIndex = 14; + this.radioGroup1.SelectedIndexChanged += new System.EventHandler(this.radioGroup1_SelectedIndexChanged); + // + // labelControl9 + // + this.labelControl9.Location = new System.Drawing.Point(62, 51); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(36, 14); + this.labelControl9.TabIndex = 13; + this.labelControl9.Text = "类型:"; + // + // labelControl8 + // + this.labelControl8.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl8.Appearance.Options.UseForeColor = true; + this.labelControl8.Location = new System.Drawing.Point(233, 130); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(94, 14); + this.labelControl8.TabIndex = 12; + this.labelControl8.Text = "(该值可自动变化)"; + // + // textEdit5 + // + this.textEdit5.Location = new System.Drawing.Point(119, 127); + this.textEdit5.Name = "textEdit5"; + this.textEdit5.Properties.ReadOnly = true; + this.textEdit5.Size = new System.Drawing.Size(94, 20); + this.textEdit5.TabIndex = 11; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(62, 130); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(36, 14); + this.labelControl7.TabIndex = 10; + this.labelControl7.Text = "变量:"; + // + // simpleButton3 + // + this.simpleButton3.Enabled = false; + this.simpleButton3.Location = new System.Drawing.Point(235, 282); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(78, 23); + this.simpleButton3.TabIndex = 9; + this.simpleButton3.Text = "删除"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.Enabled = false; + this.simpleButton2.Location = new System.Drawing.Point(151, 282); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(78, 23); + this.simpleButton2.TabIndex = 8; + this.simpleButton2.Text = "修改"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(67, 282); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(78, 23); + this.simpleButton1.TabIndex = 7; + this.simpleButton1.Text = "新增"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl6 + // + this.labelControl6.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl6.Appearance.Options.UseForeColor = true; + this.labelControl6.Location = new System.Drawing.Point(233, 233); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(94, 14); + this.labelControl6.TabIndex = 6; + this.labelControl6.Text = "(会自动替换字符)"; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(233, 182); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(94, 14); + this.labelControl5.TabIndex = 5; + this.labelControl5.Text = "(需要满足的条件)"; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(119, 230); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(94, 20); + this.textEdit4.TabIndex = 4; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(62, 233); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(36, 14); + this.labelControl4.TabIndex = 3; + this.labelControl4.Text = "代号:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(62, 182); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(36, 14); + this.labelControl3.TabIndex = 1; + this.labelControl3.Text = "数量:"; + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.listView1); + this.groupControl3.Location = new System.Drawing.Point(11, 67); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(289, 337); + this.groupControl3.TabIndex = 1; + this.groupControl3.Text = "数据展示"; + // + // listView1 + // + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HideSelection = false; + this.listView1.Location = new System.Drawing.Point(2, 23); + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(285, 312); + this.listView1.TabIndex = 0; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + this.listView1.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.listView1_ItemSelectionChanged); + // + // columnHeader1 + // + this.columnHeader1.Text = "序号"; + // + // columnHeader2 + // + this.columnHeader2.Text = "小于等于数量"; + this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader2.Width = 100; + // + // columnHeader3 + // + this.columnHeader3.Text = "代号"; + this.columnHeader3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader3.Width = 100; + // + // xtraTabControl1 + // + this.xtraTabControl1.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.xtraTabControl1.BorderStylePage = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.xtraTabControl1.Location = new System.Drawing.Point(5, 26); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.PaintStyleName = "Skin"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(685, 29); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3, + this.xtraTabPage4, + this.xtraTabPage5}); + this.xtraTabControl1.SelectedPageChanging += new DevExpress.XtraTab.TabPageChangingEventHandler(this.xtraTabControl1_SelectedPageChanging); + // + // xtraTabPage1 + // + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(683, 3); + this.xtraTabPage1.Tag = "0"; + this.xtraTabPage1.Text = " 天 数 "; + // + // xtraTabPage2 + // + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(683, 3); + this.xtraTabPage2.Tag = "1"; + this.xtraTabPage2.Text = " 查 询 "; + // + // xtraTabPage3 + // + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(683, 3); + this.xtraTabPage3.Tag = "2"; + this.xtraTabPage3.Text = " 订 单 "; + // + // xtraTabPage4 + // + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(683, 3); + this.xtraTabPage4.Tag = "3"; + this.xtraTabPage4.Text = " 退 款 "; + // + // xtraTabPage5 + // + this.xtraTabPage5.Name = "xtraTabPage5"; + this.xtraTabPage5.Size = new System.Drawing.Size(683, 3); + this.xtraTabPage5.Tag = "4"; + this.xtraTabPage5.Text = " 推 荐 "; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(64, 190); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(84, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "其他备注格式:"; + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(112, 227); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(36, 14); + this.labelControl10.TabIndex = 0; + this.labelControl10.Text = "变量:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(51, 113); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(96, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "查询未下单格式:"; + // + // te_NotesFormat + // + this.te_NotesFormat.EditValue = "[编号]-[查询]/[订单]/[退款]/[推荐]"; + this.te_NotesFormat.Location = new System.Drawing.Point(153, 187); + this.te_NotesFormat.Name = "te_NotesFormat"; + this.te_NotesFormat.Size = new System.Drawing.Size(394, 20); + this.te_NotesFormat.TabIndex = 2; + this.te_NotesFormat.Enter += new System.EventHandler(this.te_NotesFormat_Enter); + // + // te_QueryNotOrder + // + this.te_QueryNotOrder.EditValue = "查 ID[编号]/[查询]-[推荐]"; + this.te_QueryNotOrder.Location = new System.Drawing.Point(153, 110); + this.te_QueryNotOrder.Name = "te_QueryNotOrder"; + this.te_QueryNotOrder.Size = new System.Drawing.Size(394, 20); + this.te_QueryNotOrder.TabIndex = 3; + this.te_QueryNotOrder.Enter += new System.EventHandler(this.te_QueryNotOrder_Enter); + // + // bc_NotesSwitch + // + this.bc_NotesSwitch.BackColor = System.Drawing.Color.Transparent; + this.bc_NotesSwitch.Checked = false; + this.bc_NotesSwitch.CheckStyleX = UI.Framework.Controls.CheckStyle.style4; + this.bc_NotesSwitch.Cursor = System.Windows.Forms.Cursors.Hand; + this.bc_NotesSwitch.Location = new System.Drawing.Point(153, 38); + this.bc_NotesSwitch.Name = "bc_NotesSwitch"; + this.bc_NotesSwitch.Size = new System.Drawing.Size(68, 23); + this.bc_NotesSwitch.TabIndex = 4; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(153, 227); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(34, 14); + this.hyperlinkLabelControl1.TabIndex = 6; + this.hyperlinkLabelControl1.Text = "[编号]"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl8 + // + this.hyperlinkLabelControl8.Location = new System.Drawing.Point(199, 227); + this.hyperlinkLabelControl8.Name = "hyperlinkLabelControl8"; + this.hyperlinkLabelControl8.Size = new System.Drawing.Size(34, 14); + this.hyperlinkLabelControl8.TabIndex = 6; + this.hyperlinkLabelControl8.Text = "[天数]"; + this.hyperlinkLabelControl8.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl2 + // + this.hyperlinkLabelControl2.Location = new System.Drawing.Point(245, 227); + this.hyperlinkLabelControl2.Name = "hyperlinkLabelControl2"; + this.hyperlinkLabelControl2.Size = new System.Drawing.Size(34, 14); + this.hyperlinkLabelControl2.TabIndex = 6; + this.hyperlinkLabelControl2.Text = "[查询]"; + this.hyperlinkLabelControl2.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl3 + // + this.hyperlinkLabelControl3.Location = new System.Drawing.Point(291, 227); + this.hyperlinkLabelControl3.Name = "hyperlinkLabelControl3"; + this.hyperlinkLabelControl3.Size = new System.Drawing.Size(34, 14); + this.hyperlinkLabelControl3.TabIndex = 6; + this.hyperlinkLabelControl3.Text = "[订单]"; + this.hyperlinkLabelControl3.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl4 + // + this.hyperlinkLabelControl4.Location = new System.Drawing.Point(337, 227); + this.hyperlinkLabelControl4.Name = "hyperlinkLabelControl4"; + this.hyperlinkLabelControl4.Size = new System.Drawing.Size(34, 14); + this.hyperlinkLabelControl4.TabIndex = 6; + this.hyperlinkLabelControl4.Text = "[退款]"; + this.hyperlinkLabelControl4.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl5 + // + this.hyperlinkLabelControl5.Location = new System.Drawing.Point(383, 227); + this.hyperlinkLabelControl5.Name = "hyperlinkLabelControl5"; + this.hyperlinkLabelControl5.Size = new System.Drawing.Size(34, 14); + this.hyperlinkLabelControl5.TabIndex = 6; + this.hyperlinkLabelControl5.Text = "[推荐]"; + this.hyperlinkLabelControl5.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl6 + // + this.hyperlinkLabelControl6.Location = new System.Drawing.Point(429, 227); + this.hyperlinkLabelControl6.Name = "hyperlinkLabelControl6"; + this.hyperlinkLabelControl6.Size = new System.Drawing.Size(34, 14); + this.hyperlinkLabelControl6.TabIndex = 6; + this.hyperlinkLabelControl6.Text = "[昵称]"; + this.hyperlinkLabelControl6.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl12 + // + this.hyperlinkLabelControl12.Location = new System.Drawing.Point(475, 227); + this.hyperlinkLabelControl12.Name = "hyperlinkLabelControl12"; + this.hyperlinkLabelControl12.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl12.TabIndex = 6; + this.hyperlinkLabelControl12.Text = "[上级编码]"; + this.hyperlinkLabelControl12.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl7 + // + this.hyperlinkLabelControl7.Location = new System.Drawing.Point(153, 247); + this.hyperlinkLabelControl7.Name = "hyperlinkLabelControl7"; + this.hyperlinkLabelControl7.Size = new System.Drawing.Size(82, 14); + this.hyperlinkLabelControl7.TabIndex = 6; + this.hyperlinkLabelControl7.Text = "[最后下单时间]"; + this.hyperlinkLabelControl7.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl9 + // + this.hyperlinkLabelControl9.Location = new System.Drawing.Point(263, 247); + this.hyperlinkLabelControl9.Name = "hyperlinkLabelControl9"; + this.hyperlinkLabelControl9.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl9.TabIndex = 6; + this.hyperlinkLabelControl9.Text = "[最后下单年]"; + this.hyperlinkLabelControl9.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl10 + // + this.hyperlinkLabelControl10.Location = new System.Drawing.Point(361, 247); + this.hyperlinkLabelControl10.Name = "hyperlinkLabelControl10"; + this.hyperlinkLabelControl10.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl10.TabIndex = 6; + this.hyperlinkLabelControl10.Text = "[最后下单月]"; + this.hyperlinkLabelControl10.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl11 + // + this.hyperlinkLabelControl11.Location = new System.Drawing.Point(459, 247); + this.hyperlinkLabelControl11.Name = "hyperlinkLabelControl11"; + this.hyperlinkLabelControl11.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl11.TabIndex = 6; + this.hyperlinkLabelControl11.Text = "[最后下单日]"; + this.hyperlinkLabelControl11.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.button1); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl16); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl11); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl15); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl10); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl14); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl13); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl9); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl7); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl12); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl6); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl5); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl4); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl3); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl2); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl8); + this.groupControl2.Controls.Add(this.hyperlinkLabelControl1); + this.groupControl2.Controls.Add(this.bc_NotesSwitch); + this.groupControl2.Controls.Add(this.te_FirstOrder); + this.groupControl2.Controls.Add(this.te_QueryNotOrder); + this.groupControl2.Controls.Add(this.te_NewFriend); + this.groupControl2.Controls.Add(this.te_NotesFormat); + this.groupControl2.Controls.Add(this.labelControl12); + this.groupControl2.Controls.Add(this.labelControl2); + this.groupControl2.Controls.Add(this.labelControl14); + this.groupControl2.Controls.Add(this.labelControl13); + this.groupControl2.Controls.Add(this.labelControl11); + this.groupControl2.Controls.Add(this.labelControl10); + this.groupControl2.Controls.Add(this.labelControl1); + this.groupControl2.Location = new System.Drawing.Point(26, 18); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(636, 361); + this.groupControl2.TabIndex = 1; + this.groupControl2.Text = "备注信息"; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(459, 310); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(134, 30); + this.button1.TabIndex = 7; + this.button1.Text = " 一 键 同 步 (速度慢)"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // hyperlinkLabelControl16 + // + this.hyperlinkLabelControl16.Location = new System.Drawing.Point(459, 267); + this.hyperlinkLabelControl16.Name = "hyperlinkLabelControl16"; + this.hyperlinkLabelControl16.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl16.TabIndex = 6; + this.hyperlinkLabelControl16.Text = "[好友注册日]"; + this.hyperlinkLabelControl16.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl15 + // + this.hyperlinkLabelControl15.Location = new System.Drawing.Point(361, 267); + this.hyperlinkLabelControl15.Name = "hyperlinkLabelControl15"; + this.hyperlinkLabelControl15.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl15.TabIndex = 6; + this.hyperlinkLabelControl15.Text = "[好友注册月]"; + this.hyperlinkLabelControl15.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl14 + // + this.hyperlinkLabelControl14.Location = new System.Drawing.Point(263, 267); + this.hyperlinkLabelControl14.Name = "hyperlinkLabelControl14"; + this.hyperlinkLabelControl14.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl14.TabIndex = 6; + this.hyperlinkLabelControl14.Text = "[好友注册年]"; + this.hyperlinkLabelControl14.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // hyperlinkLabelControl13 + // + this.hyperlinkLabelControl13.Location = new System.Drawing.Point(153, 267); + this.hyperlinkLabelControl13.Name = "hyperlinkLabelControl13"; + this.hyperlinkLabelControl13.Size = new System.Drawing.Size(82, 14); + this.hyperlinkLabelControl13.TabIndex = 6; + this.hyperlinkLabelControl13.Text = "[好友注册时间]"; + this.hyperlinkLabelControl13.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // te_FirstOrder + // + this.te_FirstOrder.EditValue = "单 ID[编码]/[查询]/[推荐]"; + this.te_FirstOrder.Location = new System.Drawing.Point(153, 148); + this.te_FirstOrder.Name = "te_FirstOrder"; + this.te_FirstOrder.Size = new System.Drawing.Size(394, 20); + this.te_FirstOrder.TabIndex = 3; + this.te_FirstOrder.Enter += new System.EventHandler(this.te_FirstOrder_Enter); + // + // te_NewFriend + // + this.te_NewFriend.EditValue = "新 ID[编号]-[昵称]/[推荐]"; + this.te_NewFriend.Location = new System.Drawing.Point(153, 75); + this.te_NewFriend.Name = "te_NewFriend"; + this.te_NewFriend.Size = new System.Drawing.Size(394, 20); + this.te_NewFriend.TabIndex = 2; + this.te_NewFriend.Enter += new System.EventHandler(this.te_NewFriend_Enter); + // + // labelControl12 + // + this.labelControl12.Location = new System.Drawing.Point(64, 151); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(84, 14); + this.labelControl12.TabIndex = 1; + this.labelControl12.Text = "首次下单格式:"; + // + // labelControl13 + // + this.labelControl13.Location = new System.Drawing.Point(64, 42); + this.labelControl13.Name = "labelControl13"; + this.labelControl13.Size = new System.Drawing.Size(84, 14); + this.labelControl13.TabIndex = 0; + this.labelControl13.Text = "标记功能开关:"; + this.labelControl13.Click += new System.EventHandler(this.labelControl11_Click); + // + // labelControl11 + // + this.labelControl11.Location = new System.Drawing.Point(64, 78); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(84, 14); + this.labelControl11.TabIndex = 0; + this.labelControl11.Text = "新加用户格式:"; + this.labelControl11.Click += new System.EventHandler(this.labelControl11_Click); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(704, 445); + this.tabControl1.TabIndex = 2; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.groupControl1); + this.tabPage1.Location = new System.Drawing.Point(4, 23); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(696, 418); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = " 设 置 代 号 "; + this.tabPage1.UseVisualStyleBackColor = true; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.groupControl2); + this.tabPage2.Location = new System.Drawing.Point(4, 23); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(696, 418); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = " 设 置 标 记 格 式 "; + this.tabPage2.UseVisualStyleBackColor = true; + // + // tabPage3 + // + this.tabPage3.Location = new System.Drawing.Point(4, 23); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(696, 418); + this.tabPage3.TabIndex = 2; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuS_Down; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(3, 3); + this.gridControl1.MainView = this.gridView2; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(690, 409); + this.gridControl1.TabIndex = 5; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuS_Down + // + this.contextMenuS_Down.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.导出为EceToolStripMenuItem}); + this.contextMenuS_Down.Name = "contextMenuS_Down"; + this.contextMenuS_Down.Size = new System.Drawing.Size(142, 26); + // + // 导出为EceToolStripMenuItem + // + this.导出为EceToolStripMenuItem.Name = "导出为EceToolStripMenuItem"; + this.导出为EceToolStripMenuItem.Size = new System.Drawing.Size(141, 22); + this.导出为EceToolStripMenuItem.Text = "导出为Excel"; + this.导出为EceToolStripMenuItem.Click += new System.EventHandler(this.导出为EceToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn13}); + this.gridView2.GridControl = this.gridControl1; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "id"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "微信ID"; + this.gridColumn1.FieldName = "UserName"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 110; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "微信号"; + this.gridColumn2.FieldName = "Alias"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 164; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "昵称"; + this.gridColumn3.FieldName = "NickName"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 138; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "备注"; + this.gridColumn5.FieldName = "Remark"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 148; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "小头像"; + this.gridColumn7.FieldName = "SmallHeadImgUrl"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 130; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn13.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn13.AppearanceCell.Options.UseFont = true; + this.gridColumn13.AppearanceCell.Options.UseForeColor = true; + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "大头像"; + this.gridColumn13.FieldName = "BigHeadImgUrl"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 6; + this.gridColumn13.Width = 113; + // + // labelControl14 + // + this.labelControl14.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl14.Appearance.Options.UseForeColor = true; + this.labelControl14.Location = new System.Drawing.Point(112, 304); + this.labelControl14.Name = "labelControl14"; + this.labelControl14.Size = new System.Drawing.Size(247, 42); + this.labelControl14.TabIndex = 0; + this.labelControl14.Text = "注:\r\n 1、前三个如果为空时,使用第其他备注格式\r\n 2、首次下单以绑定为准"; + this.labelControl14.Click += new System.EventHandler(this.labelControl11_Click); + // + // MainForm + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(704, 445); + this.Controls.Add(this.tabControl1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + this.groupControl4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.te_NotesFormat.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.te_QueryNotOrder.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.te_FirstOrder.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.te_NewFriend.Properties)).EndInit(); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuS_Down.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private DevExpress.XtraTab.XtraTabPage xtraTabPage5; + private DevExpress.XtraEditors.GroupControl groupControl4; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.TextEdit textEdit5; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl10; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.TextEdit te_NotesFormat; + private DevExpress.XtraEditors.TextEdit te_QueryNotOrder; + private UI.Framework.Controls.ButtonCheck bc_NotesSwitch; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl8; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl4; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl5; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl6; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl12; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl7; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl9; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl10; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl11; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl16; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl15; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl14; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl13; + private System.Windows.Forms.Button button1; + private DevExpress.XtraEditors.TextEdit te_NewFriend; + private DevExpress.XtraEditors.LabelControl labelControl11; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private DevExpress.XtraEditors.TextEdit te_FirstOrder; + private DevExpress.XtraEditors.LabelControl labelControl12; + private DevExpress.XtraEditors.LabelControl labelControl13; + private System.Windows.Forms.TabPage tabPage3; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private System.Windows.Forms.ContextMenuStrip contextMenuS_Down; + private System.Windows.Forms.ToolStripMenuItem 导出为EceToolStripMenuItem; + private System.Windows.Forms.SaveFileDialog saveFileDialog1; + private DevExpress.XtraEditors.LabelControl labelControl14; + } +} \ No newline at end of file diff --git a/应用/SignContacts/MainForm.cs b/应用/SignContacts/MainForm.cs new file mode 100644 index 0000000..2737d93 --- /dev/null +++ b/应用/SignContacts/MainForm.cs @@ -0,0 +1,571 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using System.Text; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using DevExpress.XtraEditors; +using SignContacts.Entitys; +using SignContacts.Enums; +using SignContacts.Properties; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; +using System.Reflection; +using System.Data; + +namespace SignContacts +{ + public partial class MainForm : BaseForm + { + SqlSugarClient session = null; + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + session = ApiClient.GetSession(); + } + + public void Initialization() + { + try + { + var caption = string.Empty; + switch (radioGroup1.SelectedIndex) + { + case 0: + caption = "订单笔数低于"; + break; + case 1: + caption = "查询次数低于"; + break; + case 2: + caption = "提现次数低于"; + break; + case 3: + caption = "邀请人数低于"; + break; + default: + caption = "数量低于"; + break; + } + + var session = ApiClient.GetSession(); + var groups = session.FindSigns(int.Parse(this.radioGroup1.EditValue.ToString()), true); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + te_NotesFormat.Text = Class1.Config.NotesFormat; + bc_NotesSwitch.Checked = Class1.Config.NotesSwitch == SwitchType.开启; + + te_NewFriend.Text = Class1.Config.NotesFormat_NewFirend; + te_QueryNotOrder.Text = Class1.Config.NotesFormat_QueryNotOrder; + te_FirstOrder.Text = Class1.Config.NotesFormat_FirstOrder; + + _RefreshData(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) + { + try + { + if (listView1.SelectedItems.Count == 0) + { + _ButtonEnabled(false); + return; + } + else + { + var id = long.Parse(listView1.SelectedItems[0].SubItems[0].Text); + + List signInfoS = null; + + if (listView1.Tag != null) + signInfoS = listView1.Tag as List; + else + signInfoS = session.Find("select * from fl_plugin_signcontacts_sign_info where signtype = @signtype order by amount asc", new { signtype = xtraTabControl1.TabIndex }); + if (signInfoS != null && signInfoS.Count != 0) + { + var signInfo = signInfoS.FirstOrDefault(f => f.id == id); + if (signInfo == null) return; + _FillDate(signInfo); + _ButtonEnabled(true); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 填充数据到控件中 + /// + private void _FillDate(fl_plugin_signcontacts_sign_info signInfo) + { + radioGroup1.SelectedIndex = (int)signInfo.signtype; + var variate = string.Empty; + switch ((int)signInfo.signtype) + { + case 0: + variate = Class1.Config.DayVariate; + break; + case 1: + variate = Class1.Config.QueryVariate; + break; + case 2: + variate = Class1.Config.OrderVariate; + break; + case 3: + variate = Class1.Config.RefundVariate; + break; + case 4: + variate = Class1.Config.InviteVariate; + break; + } + textEdit5.Text = variate; + numericUpDown1.Value = (decimal)signInfo.amount; + textEdit4.Text = signInfo.sign; + + groupControl4.Tag = signInfo; + } + + /// + /// 按钮状态 + /// + /// + private void _ButtonEnabled(bool flag) + { + simpleButton2.Enabled = simpleButton3.Enabled = flag; + } + + + /// + /// 增加 + /// + /// + /// + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + fl_plugin_signcontacts_sign_info signInfo = new fl_plugin_signcontacts_sign_info(); + //if (groupControl4.Tag != null) + // signInfo = groupControl4.Tag as fl_plugin_signcontacts_sign_info; + //else + // signInfo = new fl_plugin_signcontacts_sign_info(); + + signInfo.id = 0; + signInfo.signtype = (SignType)radioGroup1.SelectedIndex; + signInfo.amount = (long)numericUpDown1.Value; + + List signInfoS = null; + //if (listView1.Tag != null) + // signInfoS = listView1.Tag as List; + //else + signInfoS = session.Find("select * from fl_plugin_signcontacts_sign_info where signtype = @signtype order by amount asc", new { signtype = xtraTabControl1.TabIndex }); + if (signInfoS != null && signInfoS.Count != 0) + { + var _signInfo = signInfoS.FirstOrDefault(f => f.signtype == signInfo.signtype && f.amount == signInfo.amount); + if (_signInfo != null) throw new Exception("该条件已经存在,无法增加"); + } + + signInfo.sign = textEdit4.Text.Trim(); + + session.Insertable(signInfo).ExecuteCommand(); + _RefreshData((int)signInfo.signtype); + simpleButton2.Enabled = simpleButton3.Enabled = false; + } + catch (Exception ex) + { + if (ex.Message.Contains("not unique")) + ShowError("数据重复"); + else + ShowError(ex); + } + } + + /// + /// 修改 + /// + /// + /// + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + fl_plugin_signcontacts_sign_info signInfo = null; + if (groupControl4.Tag != null) + { + signInfo = groupControl4.Tag as fl_plugin_signcontacts_sign_info; + signInfo.signtype = (SignType)radioGroup1.SelectedIndex; + signInfo.amount = (long)numericUpDown1.Value; + signInfo.sign = textEdit4.Text.Trim(); + + List signInfoS = null; + if (listView1.Tag != null) + signInfoS = listView1.Tag as List; + else + signInfoS = session.Find("select * from fl_plugin_signcontacts_sign_info where signtype = @signtype order by amount asc", new { signtype = xtraTabControl1.TabIndex }); + if (signInfoS != null && signInfoS.Count != 0) + { + var _signInfo = signInfoS.FirstOrDefault(f => f.signtype == signInfo.signtype && f.amount == signInfo.amount); + //if (_signInfo != null) throw new Exception("该条件已经存在,无法增加"); + } + + session.Updateable(signInfo).ExecuteCommand(); + _RefreshData((int)signInfo.signtype); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 删除 + /// + /// + /// + private void simpleButton3_Click(object sender, EventArgs e) + { + try + { + fl_plugin_signcontacts_sign_info signInfo = null; + if (groupControl4.Tag != null) + { + signInfo = groupControl4.Tag as fl_plugin_signcontacts_sign_info; + session.Deleteable(signInfo).ExecuteCommand(); + _RefreshData((int)signInfo.signtype); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// tab下标改变 (可以当刷新用) + /// + /// + /// + private void xtraTabControl1_SelectedPageChanging(object sender, DevExpress.XtraTab.TabPageChangingEventArgs e) + { + _RefreshData(e.Page.TabIndex); + } + + /// + /// 数显数据 + /// + private void _RefreshData(int index = 0) + { + try + { + listView1.Tag = null; + if (groupControl4.Tag == null) + _ButtonEnabled(false); + var signInfoS = session.Find("select * from fl_plugin_signcontacts_sign_info where signtype = @signtype order by amount asc", new { signtype = index }); + listView1.Items.Clear(); + foreach (var sign in signInfoS) + { + var item = new ListViewItem(); + item.Text = sign.id.ToString(); + item.SubItems.Add(sign.amount.ToString()); + item.SubItems.Add(sign.sign.ToString()); + listView1.Items.Add(item); + } + listView1.Tag = signInfoS; + session.FindSignInfos((SignType)index, true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + SaveConfig(); + } + + private void SaveConfig() + { + try + { + Class1.Config.NotesFormat = te_NotesFormat.Text; + Class1.Config.NotesSwitch = bc_NotesSwitch.Checked ? SwitchType.开启 : SwitchType.关闭; + Class1.Config.NotesFormat_NewFirend = te_NewFriend.Text; + Class1.Config.NotesFormat_QueryNotOrder = te_QueryNotOrder.Text; + Class1.Config.NotesFormat_FirstOrder = te_FirstOrder.Text; + + Util.Save(Class1.Config); + } + catch (Exception ex) + { } + } + + private void radioGroup1_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + var variate = string.Empty; + switch (radioGroup1.SelectedIndex) + { + case 0: + variate = Class1.Config.DayVariate; + break; + case 1: + variate = Class1.Config.QueryVariate; + break; + case 2: + variate = Class1.Config.OrderVariate; + break; + case 3: + variate = Class1.Config.RefundVariate; + break; + case 4: + variate = Class1.Config.InviteVariate; + break; + } + textEdit5.Text = variate; + xtraTabControl1.SelectedTabPageIndex = radioGroup1.SelectedIndex; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + if (sender is HyperlinkLabelControl) + { + var label = sender as HyperlinkLabelControl; + if (index == 0) + te_NewFriend.Text += label.Text; + else if (index == 1) + te_QueryNotOrder.Text += label.Text; + else if (index == 2) + te_FirstOrder.Text += label.Text; + else if (index == 3) + te_NotesFormat.Text += label.Text; + else + te_NotesFormat.Text += label.Text; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + Class1.Config.NotesSwitch = SwitchType.开启; + SaveConfig(); + + + + if (string.IsNullOrWhiteSpace(Class1.Config.NotesFormat) && + string.IsNullOrWhiteSpace(Class1.Config.NotesFormat_NewFirend) && + string.IsNullOrWhiteSpace(Class1.Config.NotesFormat_QueryNotOrder) && + string.IsNullOrWhiteSpace(Class1.Config.NotesFormat_FirstOrder)) + { + throw new Exception("请先设置所有备注格式"); + } + + if (MessageBox.Show(@"是否同步用户标记? +执行的过程会比较漫长", "温馨提示", MessageBoxButtons.OKCancel) == DialogResult.OK) + { + SaveConfig(); + + button1.Enabled = false; + var t = Task.Run(() => + { + SyncMembersSign(); + try + { + this.Invoke(new Action(() => + { + button1.Enabled = true; + })); + } + catch (Exception) + { } + }); + } + } + catch (Exception ex) + { + ShowErrorAutoClose(ex); + } + } + + #region 一键同步用户昵称 + private void SyncMembersSign() + { + try + { + var wxs = ChatClient.WXClient.Values.Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线).ToList(); + List tasks = new List(); + for (int i = 0; i < wxs.Count; i++) + { + var wx = wxs[i]; + var client = wx as WXClientImpl_IPAD; + if (client == null) continue; + tasks.Add(Task.Run(() => + { + if (!client.IsRefreshContact) + client.RefreshContact(); + var endTmp = DateTime.Now.AddMinutes(15); + do + { + if (!client.IsRefreshContact) + break; + Thread.Sleep(500); + } while (endTmp >= DateTime.Now); + + if (client.Friends == null) + { + EventClient.OnEvent("", $"获取{client.WeixinHao}({client.User.Nick}),好友列表异常,终止同步!"); + return; + } + + var friends = client.Friends.Where(f => !f.Key.Contains("@") && f.Key != "newsapp" && f.Key != "weixin" && !f.Key.StartsWith("gh_")).Select(f => f.Value).ToList(); + if (friends != null && friends.Count != 0) + { + //#region 导出用户 + //this.Invoke(new Action(() => + //{ + // gridControl1.DataSource = friends; + //})); + //#endregion + + var c = new Class1(); + var session = ApiClient.GetSession(); + foreach (var friend in friends) + { + var member = session.Find("select * from fl_member_info where username = @username", new { username = friend.UserName }).FirstOrDefault(); + if (member == null) + { + member = new fl_member_info() { crt_time = DateTime.Now, usernick = friend.NickName, realnick = friend.NickName, robot_name = client.WeixinHao, robot_type = client.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信, username = friend.UserName, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + member = session.Saveable(member).ExecuteReturnEntity(); + } + c.NewUsername(client, member, UserType.未知); + } + } + EventClient.OnEvent("", $"{client.WeixinHao}({client.User.Nick}),同步好友标记执行完毕!"); + })); + Thread.Sleep(10); + } + Task.WaitAll(tasks.ToArray()); + } + catch (Exception ex) + { } + } + #endregion + + + private void labelControl11_Click(object sender, EventArgs e) + { + + } + + private void 导出为EceToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (this.gridControl1 == null) throw new Exception("没有需要导出的数据!"); + if (XtraMessageBox.Show("确定要将本页面数据导入到Excel内?", "请选择", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) + { + var table = this.gridControl1.DataSource as DataTable; + //if (table == null || table.Rows.Count == 0) throw new Exception("没有需要导出的数据!"); + + this.saveFileDialog1.Filter = "Excel文件(*.xls)|*.xls"; + if (this.saveFileDialog1.ShowDialog(this) == DialogResult.OK) + { + DevExpress.XtraPrinting.XlsExportOptions options = new DevExpress.XtraPrinting.XlsExportOptions(); + this.gridControl1.ExportToXls(this.saveFileDialog1.FileName); + XtraMessageBox.Show("恭喜您,已完成数据导出!", "导出完成", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + } + catch (Exception vErr) + { + XtraMessageBox.Show(vErr.Message, "导出错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void tabPage3_MouseClick(object sender, MouseEventArgs e) + { + + } + + public int index = 0; + private void te_NewFriend_Enter(object sender, EventArgs e) + { + index = 0; + } + + private void te_QueryNotOrder_Enter(object sender, EventArgs e) + { + index = 1; + } + + private void te_FirstOrder_Enter(object sender, EventArgs e) + { + index = 2; + } + + private void te_NotesFormat_Enter(object sender, EventArgs e) + { + index = 3; + } + } +} \ No newline at end of file diff --git a/应用/SignContacts/MainForm.resx b/应用/SignContacts/MainForm.resx new file mode 100644 index 0000000..888fad8 --- /dev/null +++ b/应用/SignContacts/MainForm.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 286, 17 + + + 63 + + \ No newline at end of file diff --git a/应用/SignContacts/Properties/AssemblyInfo.cs b/应用/SignContacts/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cf42eb8 --- /dev/null +++ b/应用/SignContacts/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("SignContacts")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SignContacts")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("5407b027-5203-48b2-8191-a3ff43d57b16")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/SignContacts/Properties/Resources.Designer.cs b/应用/SignContacts/Properties/Resources.Designer.cs new file mode 100644 index 0000000..2862070 --- /dev/null +++ b/应用/SignContacts/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace SignContacts.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SignContacts.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 标记联系人 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 标记联系人 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 标记联系人,便于管理或群发 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 标记 { + get { + object obj = ResourceManager.GetObject("标记", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/SignContacts/Properties/Resources.resx b/应用/SignContacts/Properties/Resources.resx new file mode 100644 index 0000000..587a192 --- /dev/null +++ b/应用/SignContacts/Properties/Resources.resx @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 标记联系人 + + + 标记联系人 + + + 标记联系人,便于管理或群发 + + + + ..\Resources\标记.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/SignContacts/Properties/licenses.licx b/应用/SignContacts/Properties/licenses.licx new file mode 100644 index 0000000..a360c69 --- /dev/null +++ b/应用/SignContacts/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/SignContacts/Resources/标记.png b/应用/SignContacts/Resources/标记.png new file mode 100644 index 0000000..172d449 Binary files /dev/null and b/应用/SignContacts/Resources/标记.png differ diff --git a/应用/SignContacts/SignContacts.csproj b/应用/SignContacts/SignContacts.csproj new file mode 100644 index 0000000..5eac8b7 --- /dev/null +++ b/应用/SignContacts/SignContacts.csproj @@ -0,0 +1,124 @@ + + + + + Debug + AnyCPU + {5407B027-5203-48B2-8191-A3FF43D57B16} + Library + Properties + SignContacts + SignContacts + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + Form + + + MainForm.cs + + + + True + True + Resources.resx + + + + + + + MainForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/SignContacts/SignContactsEx.cs b/应用/SignContacts/SignContactsEx.cs new file mode 100644 index 0000000..1edc79c --- /dev/null +++ b/应用/SignContacts/SignContactsEx.cs @@ -0,0 +1,34 @@ +using Api.Framework; +using Api.Framework.Tools; +using SignContacts.Entitys; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SignContacts +{ + static class SignContactsEx + { + + /// + /// 获得修改备注信息 + /// + /// + /// 是否刷新缓存 + /// + public static List FindSigns(this SqlSugarClient session, int sign, bool refresh = false) + { + var key = $"fl_order_sleep_tables_{sign}"; + var list = ApiClient.Cache.Get>(key); + if (list != null && !refresh) return list; + list = session.Find("select * from fl_plugin_signcontacts_sign_info where sign = @sign order by number asc", new { sign = sign }); + if (list == null) list = new List(); + ApiClient.Cache.Set(key, list, 60); + return list; + } + + } +} diff --git a/应用/SignContacts/SignInfoEx.cs b/应用/SignContacts/SignInfoEx.cs new file mode 100644 index 0000000..e90d064 --- /dev/null +++ b/应用/SignContacts/SignInfoEx.cs @@ -0,0 +1,48 @@ +using Api.Framework; +using Api.Framework.Tools; +using SignContacts.Entitys; +using SignContacts.Enums; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SignContacts +{ + public static class SignInfoEx + { + public static fl_plugin_signcontacts_sign_info FindSignInfo(this SqlSugarClient session, SignType type, long amount) + { + var list = session.FindSignInfos(type); + if (list != null && list.Count > 0) + { + for (int i = 0; i < list.Count; i++) + { + if (amount <= list[i].amount) return list[i]; + } + return list[list.Count - 1]; + } + return new fl_plugin_signcontacts_sign_info() { sign = " . " }; + } + + /// + /// 获得延迟冻结信息 + /// + /// + /// 是否刷新缓存 + /// + public static List FindSignInfos(this SqlSugarClient session, SignType type, bool refresh = false) + { + var key = $"fl_plugin_signcontacts_sign_info_tables_{type}"; + var list = ApiClient.Cache.Get>(key); + if (list != null && !refresh) return list; + list = session.Find("select * from fl_plugin_signcontacts_sign_info where signtype = @sign order by amount asc", new { sign = (int)type }); + if (list == null) list = new List(); + ApiClient.Cache.Set(key, list, 60); + return list; + } + + } +} diff --git a/应用/StatisticalTools/Class1.cs b/应用/StatisticalTools/Class1.cs new file mode 100644 index 0000000..8b257be --- /dev/null +++ b/应用/StatisticalTools/Class1.cs @@ -0,0 +1,26 @@ +using Api.Framework.SDK; +using StatisticalTools.Properties; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StatisticalTools +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.; + } + + + + } + + + +} diff --git a/应用/StatisticalTools/Properties/AssemblyInfo.cs b/应用/StatisticalTools/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..02a90ee --- /dev/null +++ b/应用/StatisticalTools/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("StatisticalTools")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("StatisticalTools")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("483b59f2-abf3-41c2-8f10-a644aec7f4f2")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/StatisticalTools/Properties/Resources.Designer.cs b/应用/StatisticalTools/Properties/Resources.Designer.cs new file mode 100644 index 0000000..6c111bc --- /dev/null +++ b/应用/StatisticalTools/Properties/Resources.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace StatisticalTools.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("StatisticalTools.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 统计工具 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 统计工具 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 统计工具插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + } +} diff --git a/应用/StatisticalTools/Properties/Resources.resx b/应用/StatisticalTools/Properties/Resources.resx new file mode 100644 index 0000000..ce73c27 --- /dev/null +++ b/应用/StatisticalTools/Properties/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 统计工具 + 设置主窗体标题 + + + 统计工具 + 插件名 + + + 统计工具插件 + 插件介绍 + + \ No newline at end of file diff --git a/应用/StatisticalTools/StatisticalTools.csproj b/应用/StatisticalTools/StatisticalTools.csproj new file mode 100644 index 0000000..98ae1ce --- /dev/null +++ b/应用/StatisticalTools/StatisticalTools.csproj @@ -0,0 +1,82 @@ + + + + + Debug + AnyCPU + {483B59F2-ABF3-41C2-8F10-A644AEC7F4F2} + Library + Properties + StatisticalTools + StatisticalTools + v4.6 + 512 + true + + + + true + full + false + ..\..\..\返利机器人\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\..\返利机器人\Debug\Api.Framework.dll + + + False + ..\..\..\返利机器人\Debug\Chat.Framework.dll + + + False + ..\..\..\返利机器人\Debug\Easy4net.dll + + + False + ..\..\..\返利机器人\Debug\HttpHelper.dll + + + + + + + + + + + + False + ..\..\..\返利机器人\Debug\UI.Framework.dll + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + \ No newline at end of file diff --git a/应用/TBAppraisalTools/AnimatedGifEncoder.cs b/应用/TBAppraisalTools/AnimatedGifEncoder.cs new file mode 100644 index 0000000..0f8f846 --- /dev/null +++ b/应用/TBAppraisalTools/AnimatedGifEncoder.cs @@ -0,0 +1,2187 @@ +using System; +using System.Collections; +using System.Drawing; +using System.IO; + +namespace TBAppraisalTools +{ + public class AnimatedGifEncoder + { + protected int width; // image size + protected int height; + protected Color transparent = Color.Empty; // transparent color if given + protected int transIndex; // transparent index in color table + protected int repeat = -1; // no repeat + protected int delay = 0; // frame delay (hundredths) + protected bool started = false; // ready to output frames + // protected BinaryWriter bw; + protected FileStream fs; + + protected Image image; // current frame + protected byte[] pixels; // BGR byte array from frame + protected byte[] indexedPixels; // converted frame indexed to palette + protected int colorDepth; // number of bit planes + protected byte[] colorTab; // RGB palette + protected bool[] usedEntry = new bool[256]; // active palette entries + protected int palSize = 7; // color table size (bits-1) + protected int dispose = -1; // disposal code (-1 = use default) + protected bool closeStream = false; // close stream when finished + protected bool firstFrame = true; + protected bool sizeSet = false; // if false, get size from first frame + protected int sample = 10; // default sample interval for quantizer + + /** + * Sets the delay time between each frame, or changes it + * for subsequent frames (applies to last frame added). + * + * @param ms int delay time in milliseconds + */ + public void SetDelay(int ms) + { + delay = (int)Math.Round(ms / 10.0f); + } + + /** + * Sets the GIF frame disposal code for the last added frame + * and any subsequent frames. Default is 0 if no transparent + * color has been set, otherwise 2. + * @param code int disposal code. + */ + public void SetDispose(int code) + { + if (code >= 0) + { + dispose = code; + } + } + + /** + * Sets the number of times the set of GIF frames + * should be played. Default is 1; 0 means play + * indefinitely. Must be invoked before the first + * image is added. + * + * @param iter int number of iterations. + * @return + */ + public void SetRepeat(int iter) + { + if (iter >= 0) + { + repeat = iter; + } + } + + /** + * Sets the transparent color for the last added frame + * and any subsequent frames. + * Since all colors are subject to modification + * in the quantization process, the color in the final + * palette for each frame closest to the given color + * becomes the transparent color for that frame. + * May be set to null to indicate no transparent color. + * + * @param c Color to be treated as transparent on display. + */ + public void SetTransparent(Color c) + { + transparent = c; + } + + /** + * Adds next GIF frame. The frame is not written immediately, but is + * actually deferred until the next frame is received so that timing + * data can be inserted. Invoking finish() flushes all + * frames. If setSize was not invoked, the size of the + * first image is used for all subsequent frames. + * + * @param im BufferedImage containing frame to write. + * @return true if successful. + */ + public bool AddFrame(Image im) + { + if ((im == null) || !started) + { + return false; + } + bool ok = true; + try + { + if (!sizeSet) + { + // use first frame's size + SetSize(im.Width, im.Height); + } + image = im; + GetImagePixels(); // convert to correct format if necessary + AnalyzePixels(); // build color table & map pixels + if (firstFrame) + { + WriteLSD(); // logical screen descriptior + WritePalette(); // global color table + if (repeat >= 0) + { + // use NS app extension to indicate reps + WriteNetscapeExt(); + } + } + WriteGraphicCtrlExt(); // write graphic control extension + WriteImageDesc(); // image descriptor + if (!firstFrame) + { + WritePalette(); // local color table + } + WritePixels(); // encode and write pixel data + firstFrame = false; + } + catch (IOException e) + { + ok = false; + } + + return ok; + } + + /** + * Flushes any pending data and closes output file. + * If writing to an OutputStream, the stream is not + * closed. + */ + public bool Finish() + { + if (!started) return false; + bool ok = true; + started = false; + try + { + fs.WriteByte(0x3b); // gif trailer + fs.Flush(); + if (closeStream) + { + fs.Close(); + } + } + catch (IOException e) + { + ok = false; + } + + // reset for subsequent use + transIndex = 0; + fs = null; + image = null; + pixels = null; + indexedPixels = null; + colorTab = null; + closeStream = false; + firstFrame = true; + + return ok; + } + + /** + * Sets frame rate in frames per second. Equivalent to + * setDelay(1000/fps). + * + * @param fps float frame rate (frames per second) + */ + public void SetFrameRate(float fps) + { + if (fps != 0f) + { + delay = (int)Math.Round(100f / fps); + } + } + + /** + * Sets quality of color quantization (conversion of images + * to the maximum 256 colors allowed by the GIF specification). + * Lower values (minimum = 1) produce better colors, but slow + * processing significantly. 10 is the default, and produces + * good color mapping at reasonable speeds. Values greater + * than 20 do not yield significant improvements in speed. + * + * @param quality int greater than 0. + * @return + */ + public void SetQuality(int quality) + { + if (quality < 1) quality = 1; + sample = quality; + } + + /** + * Sets the GIF frame size. The default size is the + * size of the first frame added if this method is + * not invoked. + * + * @param w int frame width. + * @param h int frame width. + */ + public void SetSize(int w, int h) + { + if (started && !firstFrame) return; + width = w; + height = h; + if (width < 1) width = 320; + if (height < 1) height = 240; + sizeSet = true; + } + + /** + * Initiates GIF file creation on the given stream. The stream + * is not closed automatically. + * + * @param os OutputStream on which GIF images are written. + * @return false if initial write failed. + */ + public bool Start(FileStream os) + { + if (os == null) return false; + bool ok = true; + closeStream = false; + fs = os; + try + { + WriteString("GIF89a"); // header + } + catch (IOException e) + { + ok = false; + } + return started = ok; + } + + /** + * Initiates writing of a GIF file with the specified name. + * + * @param file String containing output file name. + * @return false if open or initial write failed. + */ + public bool Start(String file) + { + bool ok = true; + try + { + // bw = new BinaryWriter( new FileStream( file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None ) ); + fs = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + ok = Start(fs); + closeStream = true; + } + catch (IOException e) + { + ok = false; + } + return started = ok; + } + + /** + * Analyzes image colors and creates color map. + */ + protected void AnalyzePixels() + { + int len = pixels.Length; + int nPix = len / 3; + indexedPixels = new byte[nPix]; + NeuQuant nq = new NeuQuant(pixels, len, sample); + // initialize quantizer + colorTab = nq.Process(); // create reduced palette + // convert map from BGR to RGB + // for (int i = 0; i < colorTab.Length; i += 3) + // { + // byte temp = colorTab[i]; + // colorTab[i] = colorTab[i + 2]; + // colorTab[i + 2] = temp; + // usedEntry[i / 3] = false; + // } + // map image pixels to new palette + int k = 0; + for (int i = 0; i < nPix; i++) + { + int index = + nq.Map(pixels[k++] & 0xff, + pixels[k++] & 0xff, + pixels[k++] & 0xff); + usedEntry[index] = true; + indexedPixels[i] = (byte)index; + } + pixels = null; + colorDepth = 8; + palSize = 7; + // get closest match to transparent color if specified + if (transparent != Color.Empty) + { + transIndex = FindClosest(transparent); + } + } + + /** + * Returns index of palette color closest to c + * + */ + protected int FindClosest(Color c) + { + if (colorTab == null) return -1; + int r = c.R; + int g = c.G; + int b = c.B; + int minpos = 0; + int dmin = 256 * 256 * 256; + int len = colorTab.Length; + for (int i = 0; i < len;) + { + int dr = r - (colorTab[i++] & 0xff); + int dg = g - (colorTab[i++] & 0xff); + int db = b - (colorTab[i] & 0xff); + int d = dr * dr + dg * dg + db * db; + int index = i / 3; + if (usedEntry[index] && (d < dmin)) + { + dmin = d; + minpos = index; + } + i++; + } + return minpos; + } + + /** + * Extracts image pixels into byte array "pixels" + */ + protected void GetImagePixels() + { + int w = image.Width; + int h = image.Height; + // int type = image.GetType().; + if ((w != width) + || (h != height) + ) + { + // create new image with right size/format + Image temp = + new Bitmap(width, height); + Graphics g = Graphics.FromImage(temp); + g.DrawImage(image, 0, 0); + image = temp; + g.Dispose(); + } + /* + ToDo: + improve performance: use unsafe code + */ + pixels = new Byte[3 * image.Width * image.Height]; + int count = 0; + Bitmap tempBitmap = new Bitmap(image); + for (int th = 0; th < image.Height; th++) + { + for (int tw = 0; tw < image.Width; tw++) + { + Color color = tempBitmap.GetPixel(tw, th); + pixels[count] = color.R; + count++; + pixels[count] = color.G; + count++; + pixels[count] = color.B; + count++; + } + } + + // pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); + } + + /** + * Writes Graphic Control Extension + */ + protected void WriteGraphicCtrlExt() + { + fs.WriteByte(0x21); // extension introducer + fs.WriteByte(0xf9); // GCE label + fs.WriteByte(4); // data block size + int transp, disp; + if (transparent == Color.Empty) + { + transp = 0; + disp = 0; // dispose = no action + } + else + { + transp = 1; + disp = 2; // force clear if using transparent color + } + if (dispose >= 0) + { + disp = dispose & 7; // user override + } + disp <<= 2; + + // packed fields + fs.WriteByte(Convert.ToByte(0 | // 1:3 reserved + disp | // 4:6 disposal + 0 | // 7 user input - 0 = none + transp)); // 8 transparency flag + + WriteShort(delay); // delay x 1/100 sec + fs.WriteByte(Convert.ToByte(transIndex)); // transparent color index + fs.WriteByte(0); // block terminator + } + + /** + * Writes Image Descriptor + */ + protected void WriteImageDesc() + { + fs.WriteByte(0x2c); // image separator + WriteShort(0); // image position x,y = 0,0 + WriteShort(0); + WriteShort(width); // image size + WriteShort(height); + // packed fields + if (firstFrame) + { + // no LCT - GCT is used for first (or only) frame + fs.WriteByte(0); + } + else + { + // specify normal LCT + fs.WriteByte(Convert.ToByte(0x80 | // 1 local color table 1=yes + 0 | // 2 interlace - 0=no + 0 | // 3 sorted - 0=no + 0 | // 4-5 reserved + palSize)); // 6-8 size of color table + } + } + + /** + * Writes Logical Screen Descriptor + */ + protected void WriteLSD() + { + // logical screen size + WriteShort(width); + WriteShort(height); + // packed fields + fs.WriteByte(Convert.ToByte(0x80 | // 1 : global color table flag = 1 (gct used) + 0x70 | // 2-4 : color resolution = 7 + 0x00 | // 5 : gct sort flag = 0 + palSize)); // 6-8 : gct size + + fs.WriteByte(0); // background color index + fs.WriteByte(0); // pixel aspect ratio - assume 1:1 + } + + /** + * Writes Netscape application extension to define + * repeat count. + */ + protected void WriteNetscapeExt() + { + fs.WriteByte(0x21); // extension introducer + fs.WriteByte(0xff); // app extension label + fs.WriteByte(11); // block size + WriteString("NETSCAPE" + "2.0"); // app id + auth code + fs.WriteByte(3); // sub-block size + fs.WriteByte(1); // loop sub-block id + WriteShort(repeat); // loop count (extra iterations, 0=repeat forever) + fs.WriteByte(0); // block terminator + } + + /** + * Writes color table + */ + protected void WritePalette() + { + fs.Write(colorTab, 0, colorTab.Length); + int n = (3 * 256) - colorTab.Length; + for (int i = 0; i < n; i++) + { + fs.WriteByte(0); + } + } + + /** + * Encodes and writes pixel data + */ + protected void WritePixels() + { + LZWEncoder encoder = + new LZWEncoder(width, height, indexedPixels, colorDepth); + encoder.Encode(fs); + } + + /** + * Write 16-bit value to output stream, LSB first + */ + protected void WriteShort(int value) + { + fs.WriteByte(Convert.ToByte(value & 0xff)); + fs.WriteByte(Convert.ToByte((value >> 8) & 0xff)); + } + + /** + * Writes string to output stream + */ + protected void WriteString(String s) + { + char[] chars = s.ToCharArray(); + for (int i = 0; i < chars.Length; i++) + { + fs.WriteByte((byte)chars[i]); + } + } + } + + public class NeuQuant + { + protected static readonly int netsize = 256; /* number of colours used */ + /* four primes near 500 - assume no image has a length so large */ + /* that it is divisible by all four primes */ + protected static readonly int prime1 = 499; + protected static readonly int prime2 = 491; + protected static readonly int prime3 = 487; + protected static readonly int prime4 = 503; + protected static readonly int minpicturebytes = (3 * prime4); + /* minimum size for input image */ + /* Program Skeleton + ---------------- + [select samplefac in range 1..30] + [read image from input file] + pic = (unsigned char*) malloc(3*width*height); + initnet(pic,3*width*height,samplefac); + learn(); + unbiasnet(); + [write output image header, using writecolourmap(f)] + inxbuild(); + write output image using inxsearch(b,g,r) */ + + /* Network Definitions + ------------------- */ + protected static readonly int maxnetpos = (netsize - 1); + protected static readonly int netbiasshift = 4; /* bias for colour values */ + protected static readonly int ncycles = 100; /* no. of learning cycles */ + + /* defs for freq and bias */ + protected static readonly int intbiasshift = 16; /* bias for fractions */ + protected static readonly int intbias = (((int)1) << intbiasshift); + protected static readonly int gammashift = 10; /* gamma = 1024 */ + protected static readonly int gamma = (((int)1) << gammashift); + protected static readonly int betashift = 10; + protected static readonly int beta = (intbias >> betashift); /* beta = 1/1024 */ + protected static readonly int betagamma = + (intbias << (gammashift - betashift)); + + /* defs for decreasing radius factor */ + protected static readonly int initrad = (netsize >> 3); /* for 256 cols, radius starts */ + protected static readonly int radiusbiasshift = 6; /* at 32.0 biased by 6 bits */ + protected static readonly int radiusbias = (((int)1) << radiusbiasshift); + protected static readonly int initradius = (initrad * radiusbias); /* and decreases by a */ + protected static readonly int radiusdec = 30; /* factor of 1/30 each cycle */ + + /* defs for decreasing alpha factor */ + protected static readonly int alphabiasshift = 10; /* alpha starts at 1.0 */ + protected static readonly int initalpha = (((int)1) << alphabiasshift); + + protected int alphadec; /* biased by 10 bits */ + + /* radbias and alpharadbias used for radpower calculation */ + protected static readonly int radbiasshift = 8; + protected static readonly int radbias = (((int)1) << radbiasshift); + protected static readonly int alpharadbshift = (alphabiasshift + radbiasshift); + protected static readonly int alpharadbias = (((int)1) << alpharadbshift); + + /* Types and Global Variables + -------------------------- */ + + protected byte[] thepicture; /* the input image itself */ + protected int lengthcount; /* lengthcount = H*W*3 */ + + protected int samplefac; /* sampling factor 1..30 */ + + // typedef int pixel[4]; /* BGRc */ + protected int[][] network; /* the network itself - [netsize][4] */ + + protected int[] netindex = new int[256]; + /* for network lookup - really 256 */ + + protected int[] bias = new int[netsize]; + /* bias and freq arrays for learning */ + protected int[] freq = new int[netsize]; + protected int[] radpower = new int[initrad]; + /* radpower for precomputation */ + + /* Initialise network in range (0,0,0) to (255,255,255) and set parameters + ----------------------------------------------------------------------- */ + public NeuQuant(byte[] thepic, int len, int sample) + { + + int i; + int[] p; + + thepicture = thepic; + lengthcount = len; + samplefac = sample; + + network = new int[netsize][]; + for (i = 0; i < netsize; i++) + { + network[i] = new int[4]; + p = network[i]; + p[0] = p[1] = p[2] = (i << (netbiasshift + 8)) / netsize; + freq[i] = intbias / netsize; /* 1/netsize */ + bias[i] = 0; + } + } + + public byte[] ColorMap() + { + byte[] map = new byte[3 * netsize]; + int[] index = new int[netsize]; + for (int i = 0; i < netsize; i++) + index[network[i][3]] = i; + int k = 0; + for (int i = 0; i < netsize; i++) + { + int j = index[i]; + map[k++] = (byte)(network[j][0]); + map[k++] = (byte)(network[j][1]); + map[k++] = (byte)(network[j][2]); + } + return map; + } + + /* Insertion sort of network and building of netindex[0..255] (to do after unbias) + ------------------------------------------------------------------------------- */ + public void Inxbuild() + { + + int i, j, smallpos, smallval; + int[] p; + int[] q; + int previouscol, startpos; + + previouscol = 0; + startpos = 0; + for (i = 0; i < netsize; i++) + { + p = network[i]; + smallpos = i; + smallval = p[1]; /* index on g */ + /* find smallest in i..netsize-1 */ + for (j = i + 1; j < netsize; j++) + { + q = network[j]; + if (q[1] < smallval) + { /* index on g */ + smallpos = j; + smallval = q[1]; /* index on g */ + } + } + q = network[smallpos]; + /* swap p (i) and q (smallpos) entries */ + if (i != smallpos) + { + j = q[0]; + q[0] = p[0]; + p[0] = j; + j = q[1]; + q[1] = p[1]; + p[1] = j; + j = q[2]; + q[2] = p[2]; + p[2] = j; + j = q[3]; + q[3] = p[3]; + p[3] = j; + } + /* smallval entry is now in position i */ + if (smallval != previouscol) + { + netindex[previouscol] = (startpos + i) >> 1; + for (j = previouscol + 1; j < smallval; j++) + netindex[j] = i; + previouscol = smallval; + startpos = i; + } + } + netindex[previouscol] = (startpos + maxnetpos) >> 1; + for (j = previouscol + 1; j < 256; j++) + netindex[j] = maxnetpos; /* really 256 */ + } + + /* Main Learning Loop + ------------------ */ + public void Learn() + { + + int i, j, b, g, r; + int radius, rad, alpha, step, delta, samplepixels; + byte[] p; + int pix, lim; + + if (lengthcount < minpicturebytes) + samplefac = 1; + alphadec = 30 + ((samplefac - 1) / 3); + p = thepicture; + pix = 0; + lim = lengthcount; + samplepixels = lengthcount / (3 * samplefac); + delta = samplepixels / ncycles; + alpha = initalpha; + radius = initradius; + + rad = radius >> radiusbiasshift; + if (rad <= 1) + rad = 0; + for (i = 0; i < rad; i++) + radpower[i] = + alpha * (((rad * rad - i * i) * radbias) / (rad * rad)); + + //fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad); + + if (lengthcount < minpicturebytes) + step = 3; + else if ((lengthcount % prime1) != 0) + step = 3 * prime1; + else + { + if ((lengthcount % prime2) != 0) + step = 3 * prime2; + else + { + if ((lengthcount % prime3) != 0) + step = 3 * prime3; + else + step = 3 * prime4; + } + } + + i = 0; + while (i < samplepixels) + { + b = (p[pix + 0] & 0xff) << netbiasshift; + g = (p[pix + 1] & 0xff) << netbiasshift; + r = (p[pix + 2] & 0xff) << netbiasshift; + j = Contest(b, g, r); + + Altersingle(alpha, j, b, g, r); + if (rad != 0) + Alterneigh(rad, j, b, g, r); /* alter neighbours */ + + pix += step; + if (pix >= lim) + pix -= lengthcount; + + i++; + if (delta == 0) + delta = 1; + if (i % delta == 0) + { + alpha -= alpha / alphadec; + radius -= radius / radiusdec; + rad = radius >> radiusbiasshift; + if (rad <= 1) + rad = 0; + for (j = 0; j < rad; j++) + radpower[j] = + alpha * (((rad * rad - j * j) * radbias) / (rad * rad)); + } + } + //fprintf(stderr,"finished 1D learning: readonly alpha=%f !\n",((float)alpha)/initalpha); + } + + /* Search for BGR values 0..255 (after net is unbiased) and return colour index + ---------------------------------------------------------------------------- */ + public int Map(int b, int g, int r) + { + + int i, j, dist, a, bestd; + int[] p; + int best; + + bestd = 1000; /* biggest possible dist is 256*3 */ + best = -1; + i = netindex[g]; /* index on g */ + j = i - 1; /* start at netindex[g] and work outwards */ + + while ((i < netsize) || (j >= 0)) + { + if (i < netsize) + { + p = network[i]; + dist = p[1] - g; /* inx key */ + if (dist >= bestd) + i = netsize; /* stop iter */ + else + { + i++; + if (dist < 0) + dist = -dist; + a = p[0] - b; + if (a < 0) + a = -a; + dist += a; + if (dist < bestd) + { + a = p[2] - r; + if (a < 0) + a = -a; + dist += a; + if (dist < bestd) + { + bestd = dist; + best = p[3]; + } + } + } + } + if (j >= 0) + { + p = network[j]; + dist = g - p[1]; /* inx key - reverse dif */ + if (dist >= bestd) + j = -1; /* stop iter */ + else + { + j--; + if (dist < 0) + dist = -dist; + a = p[0] - b; + if (a < 0) + a = -a; + dist += a; + if (dist < bestd) + { + a = p[2] - r; + if (a < 0) + a = -a; + dist += a; + if (dist < bestd) + { + bestd = dist; + best = p[3]; + } + } + } + } + } + return (best); + } + public byte[] Process() + { + Learn(); + Unbiasnet(); + Inxbuild(); + return ColorMap(); + } + + /* Unbias network to give byte values 0..255 and record position i to prepare for sort + ----------------------------------------------------------------------------------- */ + public void Unbiasnet() + { + + int i, j; + + for (i = 0; i < netsize; i++) + { + network[i][0] >>= netbiasshift; + network[i][1] >>= netbiasshift; + network[i][2] >>= netbiasshift; + network[i][3] = i; /* record colour no */ + } + } + + /* Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|] + --------------------------------------------------------------------------------- */ + protected void Alterneigh(int rad, int i, int b, int g, int r) + { + + int j, k, lo, hi, a, m; + int[] p; + + lo = i - rad; + if (lo < -1) + lo = -1; + hi = i + rad; + if (hi > netsize) + hi = netsize; + + j = i + 1; + k = i - 1; + m = 1; + while ((j < hi) || (k > lo)) + { + a = radpower[m++]; + if (j < hi) + { + p = network[j++]; + try + { + p[0] -= (a * (p[0] - b)) / alpharadbias; + p[1] -= (a * (p[1] - g)) / alpharadbias; + p[2] -= (a * (p[2] - r)) / alpharadbias; + } + catch (Exception e) + { + } // prevents 1.3 miscompilation + } + if (k > lo) + { + p = network[k--]; + try + { + p[0] -= (a * (p[0] - b)) / alpharadbias; + p[1] -= (a * (p[1] - g)) / alpharadbias; + p[2] -= (a * (p[2] - r)) / alpharadbias; + } + catch (Exception e) + { + } + } + } + } + + /* Move neuron i towards biased (b,g,r) by factor alpha + ---------------------------------------------------- */ + protected void Altersingle(int alpha, int i, int b, int g, int r) + { + + /* alter hit neuron */ + int[] n = network[i]; + n[0] -= (alpha * (n[0] - b)) / initalpha; + n[1] -= (alpha * (n[1] - g)) / initalpha; + n[2] -= (alpha * (n[2] - r)) / initalpha; + } + + /* Search for biased BGR values + ---------------------------- */ + protected int Contest(int b, int g, int r) + { + + /* finds closest neuron (min dist) and updates freq */ + /* finds best neuron (min dist-bias) and returns position */ + /* for frequently chosen neurons, freq[i] is high and bias[i] is negative */ + /* bias[i] = gamma*((1/netsize)-freq[i]) */ + + int i, dist, a, biasdist, betafreq; + int bestpos, bestbiaspos, bestd, bestbiasd; + int[] n; + + bestd = ~(((int)1) << 31); + bestbiasd = bestd; + bestpos = -1; + bestbiaspos = bestpos; + + for (i = 0; i < netsize; i++) + { + n = network[i]; + dist = n[0] - b; + if (dist < 0) + dist = -dist; + a = n[1] - g; + if (a < 0) + a = -a; + dist += a; + a = n[2] - r; + if (a < 0) + a = -a; + dist += a; + if (dist < bestd) + { + bestd = dist; + bestpos = i; + } + biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift)); + if (biasdist < bestbiasd) + { + bestbiasd = biasdist; + bestbiaspos = i; + } + betafreq = (freq[i] >> betashift); + freq[i] -= betafreq; + bias[i] += (betafreq << gammashift); + } + freq[bestpos] += beta; + bias[bestpos] -= betagamma; + return (bestbiaspos); + } + } + + public class LZWEncoder + { + + private static readonly int EOF = -1; + + private int imgW, imgH; + private byte[] pixAry; + private int initCodeSize; + private int remaining; + private int curPixel; + + // GIFCOMPR.C - GIF Image compression routines + // + // Lempel-Ziv compression based on 'compress'. GIF modifications by + // David Rowley (mgardi@watdcsu.waterloo.edu) + + // General DEFINEs + + static readonly int BITS = 12; + + static readonly int HSIZE = 5003; // 80% occupancy + + // GIF Image compression - modified 'compress' + // + // Based on: compress.c - File compression ala IEEE Computer, June 1984. + // + // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) + // Jim McKie (decvax!mcvax!jim) + // Steve Davies (decvax!vax135!petsd!peora!srd) + // Ken Turkowski (decvax!decwrl!turtlevax!ken) + // James A. Woods (decvax!ihnp4!ames!jaw) + // Joe Orost (decvax!vax135!petsd!joe) + + int n_bits; // number of bits/code + int maxbits = BITS; // user settable max # bits/code + int maxcode; // maximum code, given n_bits + int maxmaxcode = 1 << BITS; // should NEVER generate this code + + int[] htab = new int[HSIZE]; + int[] codetab = new int[HSIZE]; + + int hsize = HSIZE; // for dynamic table sizing + + int free_ent = 0; // first unused entry + + // block compression parameters -- after all codes are used up, + // and compression rate changes, start over. + bool clear_flg = false; + + // Algorithm: use open addressing double hashing (no chaining) on the + // prefix code / next character combination. We do a variant of Knuth's + // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime + // secondary probe. Here, the modular division first probe is gives way + // to a faster exclusive-or manipulation. Also do block compression with + // an adaptive reset, whereby the code table is cleared when the compression + // ratio decreases, but after the table fills. The variable-length output + // codes are re-sized at this point, and a special CLEAR code is generated + // for the decompressor. Late addition: construct the table according to + // file size for noticeable speed improvement on small files. Please direct + // questions about this implementation to ames!jaw. + + int g_init_bits; + + int ClearCode; + int EOFCode; + + // output + // + // Output the given code. + // Inputs: + // code: A n_bits-bit integer. If == -1, then EOF. This assumes + // that n_bits =< wordsize - 1. + // Outputs: + // Outputs code to the file. + // Assumptions: + // Chars are 8 bits long. + // Algorithm: + // Maintain a BITS character long buffer (so that 8 codes will + // fit in it exactly). Use the VAX insv instruction to insert each + // code in turn. When the buffer fills up empty it and start over. + + int cur_accum = 0; + int cur_bits = 0; + + int[] masks = + { + 0x0000, + 0x0001, + 0x0003, + 0x0007, + 0x000F, + 0x001F, + 0x003F, + 0x007F, + 0x00FF, + 0x01FF, + 0x03FF, + 0x07FF, + 0x0FFF, + 0x1FFF, + 0x3FFF, + 0x7FFF, + 0xFFFF }; + + // Number of characters so far in this 'packet' + int a_count; + + // Define the storage for the packet accumulator + byte[] accum = new byte[256]; + + //---------------------------------------------------------------------------- + public LZWEncoder(int width, int height, byte[] pixels, int color_depth) + { + imgW = width; + imgH = height; + pixAry = pixels; + initCodeSize = Math.Max(2, color_depth); + } + + // Add a character to the end of the current packet, and if it is 254 + // characters, flush the packet to disk. + void Add(byte c, Stream outs) + { + accum[a_count++] = c; + if (a_count >= 254) + Flush(outs); + } + + // Clear out the hash table + + // table clear for block compress + void ClearTable(Stream outs) + { + ResetCodeTable(hsize); + free_ent = ClearCode + 2; + clear_flg = true; + + Output(ClearCode, outs); + } + + // reset code table + void ResetCodeTable(int hsize) + { + for (int i = 0; i < hsize; ++i) + htab[i] = -1; + } + + void Compress(int init_bits, Stream outs) + { + int fcode; + int i /* = 0 */; + int c; + int ent; + int disp; + int hsize_reg; + int hshift; + + // Set up the globals: g_init_bits - initial number of bits + g_init_bits = init_bits; + + // Set up the necessary values + clear_flg = false; + n_bits = g_init_bits; + maxcode = MaxCode(n_bits); + + ClearCode = 1 << (init_bits - 1); + EOFCode = ClearCode + 1; + free_ent = ClearCode + 2; + + a_count = 0; // clear packet + + ent = NextPixel(); + + hshift = 0; + for (fcode = hsize; fcode < 65536; fcode *= 2) + ++hshift; + hshift = 8 - hshift; // set hash code range bound + + hsize_reg = hsize; + ResetCodeTable(hsize_reg); // clear hash table + + Output(ClearCode, outs); + + outer_loop: while ((c = NextPixel()) != EOF) + { + fcode = (c << maxbits) + ent; + i = (c << hshift) ^ ent; // xor hashing + + if (htab[i] == fcode) + { + ent = codetab[i]; + continue; + } + else if (htab[i] >= 0) // non-empty slot + { + disp = hsize_reg - i; // secondary hash (after G. Knott) + if (i == 0) + disp = 1; + do + { + if ((i -= disp) < 0) + i += hsize_reg; + + if (htab[i] == fcode) + { + ent = codetab[i]; + goto outer_loop; + } + } while (htab[i] >= 0); + } + Output(ent, outs); + ent = c; + if (free_ent < maxmaxcode) + { + codetab[i] = free_ent++; // code -> hashtable + htab[i] = fcode; + } + else + ClearTable(outs); + } + // Put out the final code. + Output(ent, outs); + Output(EOFCode, outs); + } + + //---------------------------------------------------------------------------- + public void Encode(Stream os) + { + os.WriteByte(Convert.ToByte(initCodeSize)); // write "initial code size" byte + + remaining = imgW * imgH; // reset navigation variables + curPixel = 0; + + Compress(initCodeSize + 1, os); // compress and write the pixel data + + os.WriteByte(0); // write block terminator + } + + // Flush the packet to disk, and reset the accumulator + void Flush(Stream outs) + { + if (a_count > 0) + { + outs.WriteByte(Convert.ToByte(a_count)); + outs.Write(accum, 0, a_count); + a_count = 0; + } + } + + int MaxCode(int n_bits) + { + return (1 << n_bits) - 1; + } + + //---------------------------------------------------------------------------- + // Return the next pixel from the image + //---------------------------------------------------------------------------- + private int NextPixel() + { + if (remaining == 0) + return EOF; + + --remaining; + + int temp = curPixel + 1; + if (temp < pixAry.GetUpperBound(0)) + { + byte pix = pixAry[curPixel++]; + + return pix & 0xff; + } + return 0xff; + } + + void Output(int code, Stream outs) + { + cur_accum &= masks[cur_bits]; + + if (cur_bits > 0) + cur_accum |= (code << cur_bits); + else + cur_accum = code; + + cur_bits += n_bits; + + while (cur_bits >= 8) + { + Add((byte)(cur_accum & 0xff), outs); + cur_accum >>= 8; + cur_bits -= 8; + } + + // If the next entry is going to be too big for the code size, + // then increase it, if possible. + if (free_ent > maxcode || clear_flg) + { + if (clear_flg) + { + maxcode = MaxCode(n_bits = g_init_bits); + clear_flg = false; + } + else + { + ++n_bits; + if (n_bits == maxbits) + maxcode = maxmaxcode; + else + maxcode = MaxCode(n_bits); + } + } + + if (code == EOFCode) + { + // At EOF, write the rest of the buffer. + while (cur_bits > 0) + { + Add((byte)(cur_accum & 0xff), outs); + cur_accum >>= 8; + cur_bits -= 8; + } + + Flush(outs); + } + } + } + + public class GifDecoder + { + + /** + * File read status: No errors. + */ + public static readonly int STATUS_OK = 0; + + /** + * File read status: Error decoding file (may be partially decoded) + */ + public static readonly int STATUS_FORMAT_ERROR = 1; + + /** + * File read status: Unable to open source. + */ + public static readonly int STATUS_OPEN_ERROR = 2; + + protected Stream inStream; + protected int status; + + protected int width; // full image width + protected int height; // full image height + protected bool gctFlag; // global color table used + protected int gctSize; // size of global color table + protected int loopCount = 1; // iterations; 0 = repeat forever + + protected int[] gct; // global color table + protected int[] lct; // local color table + protected int[] act; // active color table + + protected int bgIndex; // background color index + protected int bgColor; // background color + protected int lastBgColor; // previous bg color + protected int pixelAspect; // pixel aspect ratio + + protected bool lctFlag; // local color table flag + protected bool interlace; // interlace flag + protected int lctSize; // local color table size + + protected int ix, iy, iw, ih; // current image rectangle + protected Rectangle lastRect; // last image rect + protected Image image; // current frame + protected Bitmap bitmap; + protected Image lastImage; // previous frame + + protected byte[] block = new byte[256]; // current data block + protected int blockSize = 0; // block size + + // last graphic control extension info + protected int dispose = 0; + // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev + protected int lastDispose = 0; + protected bool transparency = false; // use transparent color + protected int delay = 0; // delay in milliseconds + protected int transIndex; // transparent color index + + protected static readonly int MaxStackSize = 4096; + // max decoder pixel stack size + + // LZW decoder working arrays + protected short[] prefix; + protected byte[] suffix; + protected byte[] pixelStack; + protected byte[] pixels; + + protected ArrayList frames; // frames read from current file + protected int frameCount; + + public class GifFrame + { + public GifFrame(Image im, int del) + { + image = im; + delay = del; + } + public Image image; + public int delay; + } + + /** + * Gets display duration for specified frame. + * + * @param n int index of frame + * @return delay in milliseconds + */ + public int GetDelay(int n) + { + // + delay = -1; + if ((n >= 0) && (n < frameCount)) + { + delay = ((GifFrame)frames[n]).delay; + } + return delay; + } + + /** + * Gets the number of frames read from file. + * @return frame count + */ + public int GetFrameCount() + { + return frameCount; + } + + /** + * Gets the first (or only) image read. + * + * @return BufferedImage containing first frame, or null if none. + */ + public Image GetImage() + { + return GetFrame(0); + } + + /** + * Gets the "Netscape" iteration count, if any. + * A count of 0 means repeat indefinitiely. + * + * @return iteration count if one was specified, else 1. + */ + public int GetLoopCount() + { + return loopCount; + } + + /** + * Creates new frame image from current data (and previous + * frames as specified by their disposition codes). + */ + int[] GetPixels(Bitmap bitmap) + { + int[] pixels = new int[3 * image.Width * image.Height]; + int count = 0; + for (int th = 0; th < image.Height; th++) + { + for (int tw = 0; tw < image.Width; tw++) + { + Color color = bitmap.GetPixel(tw, th); + pixels[count] = color.R; + count++; + pixels[count] = color.G; + count++; + pixels[count] = color.B; + count++; + } + } + return pixels; + } + + void SetPixels(int[] pixels) + { + int count = 0; + for (int th = 0; th < image.Height; th++) + { + for (int tw = 0; tw < image.Width; tw++) + { + Color color = Color.FromArgb(pixels[count++]); + bitmap.SetPixel(tw, th, color); + } + } + } + + protected void SetPixels() + { + // expose destination image's pixels as int array + // int[] dest = + // (( int ) image.getRaster().getDataBuffer()).getData(); + int[] dest = GetPixels(bitmap); + + // fill in starting image contents based on last image's dispose code + if (lastDispose > 0) + { + if (lastDispose == 3) + { + // use image before last + int n = frameCount - 2; + if (n > 0) + { + lastImage = GetFrame(n - 1); + } + else + { + lastImage = null; + } + } + + if (lastImage != null) + { + // int[] prev = + // ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData(); + int[] prev = GetPixels(new Bitmap(lastImage)); + Array.Copy(prev, 0, dest, 0, width * height); + // copy pixels + + if (lastDispose == 2) + { + // fill last image rect area with background color + Graphics g = Graphics.FromImage(image); + Color c = Color.Empty; + if (transparency) + { + c = Color.FromArgb(0, 0, 0, 0); // assume background is transparent + } + else + { + c = Color.FromArgb(lastBgColor); + // c = new Color(lastBgColor); // use given background color + } + Brush brush = new SolidBrush(c); + g.FillRectangle(brush, lastRect); + brush.Dispose(); + g.Dispose(); + } + } + } + + // copy each source line to the appropriate place in the destination + int pass = 1; + int inc = 8; + int iline = 0; + for (int i = 0; i < ih; i++) + { + int line = i; + if (interlace) + { + if (iline >= ih) + { + pass++; + switch (pass) + { + case 2: + iline = 4; + break; + case 3: + iline = 2; + inc = 4; + break; + case 4: + iline = 1; + inc = 2; + break; + } + } + line = iline; + iline += inc; + } + line += iy; + if (line < height) + { + int k = line * width; + int dx = k + ix; // start of line in dest + int dlim = dx + iw; // end of dest line + if ((k + width) < dlim) + { + dlim = k + width; // past dest edge + } + int sx = i * iw; // start of line in source + while (dx < dlim) + { + // map color and insert in destination + int index = ((int)pixels[sx++]) & 0xff; + int c = act[index]; + if (c != 0) + { + dest[dx] = c; + } + dx++; + } + } + } + SetPixels(dest); + } + + /** + * Gets the image contents of frame n. + * + * @return BufferedImage representation of frame, or null if n is invalid. + */ + public Image GetFrame(int n) + { + Image im = null; + if ((n >= 0) && (n < frameCount)) + { + im = ((GifFrame)frames[n]).image; + } + return im; + } + + /** + * Gets image size. + * + * @return GIF image dimensions + */ + public Size GetFrameSize() + { + return new Size(width, height); + } + + /** + * Reads GIF image from stream + * + * @param BufferedInputStream containing GIF file. + * @return read status code (0 = no errors) + */ + public int Read(Stream inStream) + { + Init(); + if (inStream != null) + { + this.inStream = inStream; + ReadHeader(); + if (!Error()) + { + ReadContents(); + if (frameCount < 0) + { + status = STATUS_FORMAT_ERROR; + } + } + inStream.Close(); + } + else + { + status = STATUS_OPEN_ERROR; + } + return status; + } + + /** + * Reads GIF file from specified file/URL source + * (URL assumed if name contains ":/" or "file:") + * + * @param name String containing source + * @return read status code (0 = no errors) + */ + public int Read(String name) + { + status = STATUS_OK; + try + { + name = name.Trim().ToLower(); + status = Read(new FileInfo(name).OpenRead()); + } + catch (IOException e) + { + status = STATUS_OPEN_ERROR; + } + + return status; + } + + /** + * Decodes LZW image data into pixel array. + * Adapted from John Cristy's ImageMagick. + */ + protected void DecodeImageData() + { + int NullCode = -1; + int npix = iw * ih; + int available, + clear, + code_mask, + code_size, + end_of_information, + in_code, + old_code, + bits, + code, + count, + i, + datum, + data_size, + first, + top, + bi, + pi; + + if ((pixels == null) || (pixels.Length < npix)) + { + pixels = new byte[npix]; // allocate new pixel array + } + if (prefix == null) prefix = new short[MaxStackSize]; + if (suffix == null) suffix = new byte[MaxStackSize]; + if (pixelStack == null) pixelStack = new byte[MaxStackSize + 1]; + + // Initialize GIF data stream decoder. + + data_size = Read(); + clear = 1 << data_size; + end_of_information = clear + 1; + available = clear + 2; + old_code = NullCode; + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + for (code = 0; code < clear; code++) + { + prefix[code] = 0; + suffix[code] = (byte)code; + } + + // Decode GIF pixel stream. + + datum = bits = count = first = top = pi = bi = 0; + + for (i = 0; i < npix;) + { + if (top == 0) + { + if (bits < code_size) + { + // Load bytes until there are enough bits for a code. + if (count == 0) + { + // Read a new data block. + count = ReadBlock(); + if (count <= 0) + break; + bi = 0; + } + datum += (((int)block[bi]) & 0xff) << bits; + bits += 8; + bi++; + count--; + continue; + } + + // Get the next code. + + code = datum & code_mask; + datum >>= code_size; + bits -= code_size; + + // Interpret the code + + if ((code > available) || (code == end_of_information)) + break; + if (code == clear) + { + // Reset decoder. + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + available = clear + 2; + old_code = NullCode; + continue; + } + if (old_code == NullCode) + { + pixelStack[top++] = suffix[code]; + old_code = code; + first = code; + continue; + } + in_code = code; + if (code == available) + { + pixelStack[top++] = (byte)first; + code = old_code; + } + while (code > clear) + { + pixelStack[top++] = suffix[code]; + code = prefix[code]; + } + first = ((int)suffix[code]) & 0xff; + + // Add a new string to the string table, + + if (available >= MaxStackSize) + break; + pixelStack[top++] = (byte)first; + prefix[available] = (short)old_code; + suffix[available] = (byte)first; + available++; + if (((available & code_mask) == 0) + && (available < MaxStackSize)) + { + code_size++; + code_mask += available; + } + old_code = in_code; + } + + // Pop a pixel off the pixel stack. + + top--; + pixels[pi++] = pixelStack[top]; + i++; + } + + for (i = pi; i < npix; i++) + { + pixels[i] = 0; // clear missing pixels + } + + } + + /** + * Returns true if an error was encountered during reading/decoding + */ + protected bool Error() + { + return status != STATUS_OK; + } + + /** + * Initializes or re-initializes reader + */ + protected void Init() + { + status = STATUS_OK; + frameCount = 0; + frames = new ArrayList(); + gct = null; + lct = null; + } + + /** + * Reads a single byte from the input stream. + */ + protected int Read() + { + int curByte = 0; + try + { + curByte = inStream.ReadByte(); + } + catch (IOException e) + { + status = STATUS_FORMAT_ERROR; + } + return curByte; + } + + /** + * Reads next variable length block from input. + * + * @return number of bytes stored in "buffer" + */ + protected int ReadBlock() + { + blockSize = Read(); + int n = 0; + if (blockSize > 0) + { + try + { + int count = 0; + while (n < blockSize) + { + count = inStream.Read(block, n, blockSize - n); + if (count == -1) + break; + n += count; + } + } + catch (IOException e) + { + } + + if (n < blockSize) + { + status = STATUS_FORMAT_ERROR; + } + } + return n; + } + + /** + * Reads color table as 256 RGB integer values + * + * @param ncolors int number of colors to read + * @return int array containing 256 colors (packed ARGB with full alpha) + */ + protected int[] ReadColorTable(int ncolors) + { + int nbytes = 3 * ncolors; + int[] tab = null; + byte[] c = new byte[nbytes]; + int n = 0; + try + { + n = inStream.Read(c, 0, c.Length); + } + catch (IOException e) + { + } + if (n < nbytes) + { + status = STATUS_FORMAT_ERROR; + } + else + { + tab = new int[256]; // max size to avoid bounds checks + int i = 0; + int j = 0; + while (i < ncolors) + { + int r = ((int)c[j++]) & 0xff; + int g = ((int)c[j++]) & 0xff; + int b = ((int)c[j++]) & 0xff; + tab[i++] = (int)(0xff000000 | (r << 16) | (g << 8) | b); + } + } + return tab; + } + + /** + * Main file parser. Reads GIF content blocks. + */ + protected void ReadContents() + { + // read GIF file content blocks + bool done = false; + while (!(done || Error())) + { + int code = Read(); + switch (code) + { + + case 0x2C: // image separator + ReadImage(); + break; + + case 0x21: // extension + code = Read(); + switch (code) + { + case 0xf9: // graphics control extension + ReadGraphicControlExt(); + break; + + case 0xff: // application extension + ReadBlock(); + String app = ""; + for (int i = 0; i < 11; i++) + { + app += (char)block[i]; + } + if (app.Equals("NETSCAPE2.0")) + { + ReadNetscapeExt(); + } + else + Skip(); // don't care + break; + + default: // uninteresting extension + Skip(); + break; + } + break; + + case 0x3b: // terminator + done = true; + break; + + case 0x00: // bad byte, but keep going and see what happens + break; + + default: + status = STATUS_FORMAT_ERROR; + break; + } + } + } + + /** + * Reads Graphics Control Extension values + */ + protected void ReadGraphicControlExt() + { + Read(); // block size + int packed = Read(); // packed fields + dispose = (packed & 0x1c) >> 2; // disposal method + if (dispose == 0) + { + dispose = 1; // elect to keep old image if discretionary + } + transparency = (packed & 1) != 0; + delay = ReadShort() * 10; // delay in milliseconds + transIndex = Read(); // transparent color index + Read(); // block terminator + } + + /** + * Reads GIF file header information. + */ + protected void ReadHeader() + { + String id = ""; + for (int i = 0; i < 6; i++) + { + id += (char)Read(); + } + if (!id.StartsWith("GIF")) + { + status = STATUS_FORMAT_ERROR; + return; + } + + ReadLSD(); + if (gctFlag && !Error()) + { + gct = ReadColorTable(gctSize); + bgColor = gct[bgIndex]; + } + } + + /** + * Reads next frame image + */ + protected void ReadImage() + { + ix = ReadShort(); // (sub)image position & size + iy = ReadShort(); + iw = ReadShort(); + ih = ReadShort(); + + int packed = Read(); + lctFlag = (packed & 0x80) != 0; // 1 - local color table flag + interlace = (packed & 0x40) != 0; // 2 - interlace flag + // 3 - sort flag + // 4-5 - reserved + lctSize = 2 << (packed & 7); // 6-8 - local color table size + + if (lctFlag) + { + lct = ReadColorTable(lctSize); // read table + act = lct; // make local table active + } + else + { + act = gct; // make global table active + if (bgIndex == transIndex) + bgColor = 0; + } + int save = 0; + if (transparency) + { + save = act[transIndex]; + act[transIndex] = 0; // set transparent color if specified + } + + if (act == null) + { + status = STATUS_FORMAT_ERROR; // no color table defined + } + + if (Error()) return; + + DecodeImageData(); // decode pixel data + Skip(); + + if (Error()) return; + + frameCount++; + + // create new image to receive frame data + // image = + // new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); + + bitmap = new Bitmap(width, height); + image = bitmap; + SetPixels(); // transfer pixel data to image + + frames.Add(new GifFrame(bitmap, delay)); // add image to frame list + + if (transparency) + { + act[transIndex] = save; + } + ResetFrame(); + + } + + /** + * Reads Logical Screen Descriptor + */ + protected void ReadLSD() + { + + // logical screen size + width = ReadShort(); + height = ReadShort(); + + // packed fields + int packed = Read(); + gctFlag = (packed & 0x80) != 0; // 1 : global color table flag + // 2-4 : color resolution + // 5 : gct sort flag + gctSize = 2 << (packed & 7); // 6-8 : gct size + + bgIndex = Read(); // background color index + pixelAspect = Read(); // pixel aspect ratio + } + + /** + * Reads Netscape extenstion to obtain iteration count + */ + protected void ReadNetscapeExt() + { + do + { + ReadBlock(); + if (block[0] == 1) + { + // loop count sub-block + int b1 = ((int)block[1]) & 0xff; + int b2 = ((int)block[2]) & 0xff; + loopCount = (b2 << 8) | b1; + } + } while ((blockSize > 0) && !Error()); + } + + /** + * Reads next 16-bit value, LSB first + */ + protected int ReadShort() + { + // read 16-bit value, LSB first + return Read() | (Read() << 8); + } + + /** + * Resets frame state for reading next image. + */ + protected void ResetFrame() + { + lastDispose = dispose; + lastRect = new Rectangle(ix, iy, iw, ih); + lastImage = image; + lastBgColor = bgColor; + // int dispose = 0; + bool transparency = false; + int delay = 0; + lct = null; + } + + /** + * Skips variable length blocks up to and including + * next zero length block. + */ + protected void Skip() + { + do + { + ReadBlock(); + } while ((blockSize > 0) && !Error()); + } + } +} diff --git a/应用/TBAppraisalTools/Class1.cs b/应用/TBAppraisalTools/Class1.cs new file mode 100644 index 0000000..d802a78 --- /dev/null +++ b/应用/TBAppraisalTools/Class1.cs @@ -0,0 +1,232 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk.IPAD; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using TBAppraisalTools.Forms; +using TBAppraisalTools.Properties; + +namespace TBAppraisalTools +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.评价工具; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + #region 自定义变量 + private MainForm mainForm = null; + public static Config Config = null; + #endregion + + public override void Start() + { + try + { + this.SDK.ReciveIMEvent += SDK_ReciveIMEvent; + this.SDK.WXReiceveFriendMsgEvent += SDK_WXReiceveFriendMsgEvent; + Config = this.ReadConfig(); + //TimerTask.NewTimer(2 * 60); //创建线程 - 淘宝Cookies更新的线程 2分钟 + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_WXReiceveFriendMsgEvent(object sender, Chat.Framework.WXSdk.Events.WXReiceveFriendMsg e) + { + throw new NotImplementedException(); + } + + TbAnalysis tbAnalysis = new TbAnalysis(); + + + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + + var evt = e.Event as Chat.Framework.WXSdk.Events.WXReiceveFriendMsg; + if (evt.IsRobot) + { + var reg = Regex.Match(e.Message, Config.PointOperation);//查询指令是否正常 + if (reg.Success) + { + var point = double.Parse(reg.Groups["积分"].Value); + var session = ApiClient.GetSession(); + bool state = false; + if (Config.Point_RechargeType != Enums.RechargeType.余额) + { + var passinfo = session.FindWeixinpassword(e.RobotInfo.id); + if (passinfo != null && !string.IsNullOrEmpty(passinfo.password)) + { + + var ipad = sender as Chat.Framework.WXSdk.Implement.WXClientImpl_IPAD; + var flag = ipad.SendPay(e.Username, "评价助手 - 积分奖励", (int)(point * 100), passinfo.password, 1, Config.Point_RechargeType == Enums.RechargeType.红包 ? PayType.红包 : PayType.转账, passinfo.GetBank()); + if (string.IsNullOrEmpty(flag)) + { + e.SendMessage(Config.PointRechargeSuccess.Replace("[积分金额]", point.ToString())); + return; + } + } + else + this.OnLog("微信支付推荐人奖励失败:未设置支付密码.奖励以积分形式充值"); + + if (!state) + { + if (session.ChangePoint(PointType.其他奖励, point, e.GetMemberinfo(true), "评价助手 - 积分奖励")) + e.SendMessage(Config.PointRechargeSuccess.Replace("[奖励积分]", point.ToString()).Replace("[剩余积分]", e.GetMemberinfo(true).cur_point.ToString())); + else + e.SendMessage(Config.PointRechargeError.Replace("[奖励积分]", point.ToString()).Replace("[剩余积分]", e.GetMemberinfo(true).cur_point.ToString())); + } + } + else + { + if (session.ChangePoint(PointType.其他奖励, point, e.GetMemberinfo(true), "评价助手 - 积分奖励")) + e.SendMessage(Config.PointRechargeSuccess.Replace("[奖励积分]", point.ToString()).Replace("[剩余积分]", e.GetMemberinfo(true).cur_point.ToString())); + else + e.SendMessage(Config.PointRechargeError.Replace("[奖励积分]", point.ToString()).Replace("[剩余积分]", e.GetMemberinfo(true).cur_point.ToString())); + } + return; + } + } + + var analysis = new TBHelper.TbAnalysis(); + var itemid = analysis.FindItemIdByUrlAndTklAndMkl(e.Message); + if (!string.IsNullOrEmpty(itemid)) + { + e.SendMessage(Config.SearchingTip); + if (!Directory.Exists(TbTools.CACHEPATH)) + Directory.CreateDirectory(TbTools.CACHEPATH); + if (!Directory.Exists(TbTools.OTHERSICOPATH)) + Directory.CreateDirectory(TbTools.OTHERSICOPATH); + + #region 通过淘宝id获取宝贝的信息 + var tb = tbAnalysis.FindTbBaseInfo(itemid); + if (tb != null) + { + //var cookies = TbTools.RandomTbCookies(); + //if (string.IsNullOrEmpty(cookies)) throw new Exception("没有有效的淘宝Cookies该功能无法使用,请先登录"); + + var savePath = Config.TbItemSavePath; + if (string.IsNullOrEmpty(savePath)) throw new Exception("解析以后保存路径为空,请先设置保存路径"); + var dateNode = DateTime.Today.ToString("yyyyMMdd"); //当天保存的目录名称 + var itemNode = $"{DateTime.Now.ToString("HHmmss")}_{itemid}"; //保存宝贝的目录名称 + savePath = $"{savePath}\\{dateNode}";//解析的目录路径以当天日期 + var itemSavePath = $"{savePath}\\{itemNode}";//宝贝解析后图片等信息最终保存目录 + if (!Directory.Exists(itemSavePath)) + Directory.CreateDirectory(itemSavePath); + + var couponImage = tbAnalysis.GenerateCouponImage(tb); //生成优惠券图片 + var tags = tbAnalysis.FindTagsByItemId(tb.ItemId); //获取宝贝的标签 + var tagStr = tags == null ? string.Empty : string.Join(",", tags.Select(f => f.tag).ToArray()); //将标签名保存在数组中,用于拼接后传入评语中 + + var comments = tbAnalysis.FindWebappCommentInfos(tb.ItemId, Config.AnalyzePage); //移动端 获取评语、图片 + if (comments != null && comments.Count == 0) + comments = tbAnalysis.FindPcCommentInfos(tb.ItemId, tb.SellerId, Config.AnalyzePage); //PC端 获取评语、图片 + if (comments != null && comments.Count != 0) + { + var putImageNum = Config.PUTImage; //要多少几张GIF图片 + var Gifpics = new List(); + List commentstrb = new List(); + + if (File.Exists(TbTools.ABDUCTIONICO)) Gifpics.Add(TbTools.ABDUCTIONICO); + foreach (var item in comments) + { + if (Gifpics.Count <= putImageNum) //获取用户需要的图片数量 + { + if (item.pics.Count != 0) + { + foreach (var pic in item.pics) + { + try + { + var tempPic = TbTools.RandomFile(); + Tools.DownloadImage(pic, tempPic); + if (Gifpics.Count < putImageNum) Gifpics.Add(tempPic); + else break; + } + catch (Exception ex) + { + this.OnLog("将网络图片转成本地图片:" + ex.Message); + } + } + } + } + commentstrb.Add(item.rateContent); //将评价内容保存保存在集合中 + } + string content = TbTools.GetCommentContents(commentstrb); //截取的评论信息(要让客户评论的评语) + if (!string.IsNullOrWhiteSpace(tagStr)) + content = tagStr + content; //如果存在标签,将标签拼接在一起,追加到评语最前面 + File.WriteAllText($"{itemSavePath}\\text.txt", content); + tbAnalysis.FindGifsBySrcPic(Gifpics, couponImage, itemSavePath, itemid); + if (Directory.Exists(itemSavePath) && Directory.GetFiles(itemSavePath).Length != 0) + e.SendMessage(Config.AnalysisSuccess.Replace("[追加参数]", $"?y={dateNode}&gid={itemNode}")); + else + e.SendMessage(Config.AnalysisError); + } + else + e.SendMessage("获取不到评价数据,有可能该宝贝没有评价数据"); + } + #endregion + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close(); + Util.Save(Config); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/TBAppraisalTools/Config.cs b/应用/TBAppraisalTools/Config.cs new file mode 100644 index 0000000..b7e67bf --- /dev/null +++ b/应用/TBAppraisalTools/Config.cs @@ -0,0 +1,344 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static TBAppraisalTools.Enums; + +namespace TBAppraisalTools +{ + [Config(Name = "插件-评价工具")] + public class Config + { + /// + /// 登录的淘宝Cookies + /// + [Browsable(false)] + public List TbLoginInfos { get; set; } + + #region 优惠券配置 + public string _couponDenomination; + /// + /// 优惠券面值比例 + /// + [ + Category("1)、优惠券配置"), DisplayName("01.优惠券面值比例"), DefaultValue("50-80"), + Description(@"优惠券面值比例是以商品实价的基础上进行比例的计算.单位 百分比") + ] + public string CouponDenomination + { + get { return _couponDenomination; } + set + { + if (string.IsNullOrWhiteSpace(value)) throw new Exception("优惠券比例不能为空"); + var rates = value.Trim().Split('-'); + if (rates.Length == 2) + { + if (int.Parse(rates[0]) >= int.Parse(rates[1])) throw new Exception("比例区间必须前小后大"); + _couponDenomination = value; + } + else + throw new Exception("比例格式不正确,请看下方说明"); + } + } + + /// + /// 优惠券面值取整 + /// + [ + Category("1)、优惠券配置"), DisplayName("02.优惠券面值取整"), DefaultValue(SwitchType.开启), + Description(@"优惠券面值比例是以商品实价的基础上进行比例的计算.计算所得值取整(10的倍数),所得值必须大于10") + ] + public SwitchType IsRounding { get; set; } + + /// + /// 优惠券有效期计划天数 + /// + [ + Category("1)、优惠券配置"), DisplayName("03.优惠券有效期计划天数"), DefaultValue(0), + Description(@"优惠券有效期开始日期以优惠券生成时为基准(优惠券生成时为默认有效期开始时间),增加多少天. +例如:2019年1月1号生成,设置的值为2,那么优惠券的有效期开始日期为2019年1月3号开始") + ] + public int ManufacturePlansAddDay { get; set; } + + private int _expirationDate; + /// + /// 优惠券有效期有效天数 + /// + [ + Category("1)、优惠券配置"), DisplayName("04.优惠券有效期有效天数"), DefaultValue(7), + Description(@"优惠券有效期开始日期加上设置的有效天数为有效期结束时间. +例如:2019年1月3号生成,有效天数设置的值为7,那么优惠券的有效期输入日期为2019年1月10号结束") + ] + public int ExpirationDate + { + get { return _expirationDate; } + set + { + if (value < 0) throw new Exception("该值不能小于零"); + _expirationDate = value; + } + } + #endregion + + #region 其他选项 + private int _analyzePage; + /// + /// 解析评价的页数 + /// + [ + Category("2)、其他选项"), DisplayName("01.解析评价页数"), DefaultValue(2), + Description(@"解析评价页数,评价的页数必须大于0并且小于5") + ] + public int AnalyzePage + { + get { return _analyzePage; } + set + { + if (value <= 0) throw new Exception("该值应该大于0"); + else if (value > 6) throw new Exception("为了解析性能,评价页数不能超过5页"); + _analyzePage = value; + } + } + + private string _buttonPic; + /// + /// 诱导图地址 + /// + [ + Category("2)、其他选项"), DisplayName("02.按钮图标"), DefaultValue(""), + Description(@"设置按钮图标,评价图片中间将增加一个按钮标.支持本地图片和网络图片(请填写地址)") + ] + public string ButtonPic + { + get { return _buttonPic; } + set + { + try + { + var path = value.Trim(); + if (string.IsNullOrWhiteSpace(path)) + { + if (File.Exists(TbTools.BUTTONICO)) + File.Delete(TbTools.BUTTONICO);//用户设置为空的时候,删除图片 + _buttonPic = path; + } + else + { + if (File.Exists(path)) + { + if (path != TbTools.BUTTONICO) + { + File.Copy(path, TbTools.BUTTONICO, true); + _buttonPic = TbTools.BUTTONICO; + } + else + throw new Exception("路径不能为保存路径"); + } + else + { + try + { + Tools.DownloadImage(path, TbTools.BUTTONICO); + _buttonPic = TbTools.BUTTONICO; + } + catch (Exception) + { + throw new Exception("请输入正确的图片路径"); + } + } + } + } + catch (Exception ex) + { + throw ex; + } + } + } + + private string _abductionPic; + /// + /// 诱导图地址 + /// + [ + Category("2)、其他选项"), DisplayName("03.诱导图地址"), DefaultValue(""), + Description(@"设置诱导图,可以上传一张自己认为有空的图片.支持本地图片和网络图片(请填写地址)") + ] + public string AbductionPic + { + get { return _abductionPic; } + set + { + try + { + var path = value.Trim(); + if (string.IsNullOrWhiteSpace(path)) + { + if (File.Exists(TbTools.ABDUCTIONICO)) + File.Delete(TbTools.ABDUCTIONICO);//用户设置为空的时候,删除图片 + _abductionPic = path; + } + else + { + + if (File.Exists(path)) + { + if (path != TbTools.ABDUCTIONICO) + { + File.Copy(path, TbTools.ABDUCTIONICO, true); + _abductionPic = TbTools.ABDUCTIONICO; + } + else + throw new Exception("路径不能为保存路径"); + } + else + { + try + { + Tools.DownloadImage(path, TbTools.ABDUCTIONICO); + _abductionPic = TbTools.ABDUCTIONICO; + } + catch (Exception) + { + throw new Exception("请输入正确的图片路径"); + } + } + } + } + catch (Exception ex) + { + throw ex; + } + } + } + + /// + /// 评论图片合成GIF + /// + [ + Category("2)、其他选项"), DisplayName("04.评论图片合成GIF"), DefaultValue(SwitchType.开启), + Description(@"评论图片合成GIF图片") + ] + public SwitchType BondCommentPic { get; set; } + + private int _PUTImage; + /// + /// Gif图片数量 + /// + [ + Category("2)、其他选项"), DisplayName("05.Gif图片数量"), DefaultValue(5), + Description(@"转多少张图片为Gif,数量包含诱导图") + ] + public int PUTImage + { + get { return _PUTImage; } + set + { + if (value <= 0) throw new Exception("该值应该大于0"); + _PUTImage = value; + } + } + + private string _TbItemSavePath; + /// + /// 解析后保存路径 + /// + [ + Category("2)、其他选项"), DisplayName("06.解析后保存路径"), + Description(@"解析出来内容的保存路径") + ] + + public string TbItemSavePath + { + get { return _TbItemSavePath; } + set + { + if (string.IsNullOrWhiteSpace(value)) throw new Exception("保存路径不能为空"); + if (!Directory.Exists(value)) throw new Exception("目录路径不正确"); + else _TbItemSavePath = value; + } + } + + /// + /// 正在搜索宝贝提示语 + /// + [ + Category("2)、其他选项"), DisplayName("07.正在搜索宝贝"), DefaultValue(@"评价信息合成中....."), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchingTip { get; set; } + + [ + Category("2)、其他选项"), DisplayName("08.宝贝解析成功"), DefaultValue(@"宝贝解析成功.[追加参数]"), + Description(@"宝贝解析成功提示语 支持变量:[追加参数]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AnalysisSuccess { get; set; } + + [ + Category("2)、其他选项"), DisplayName("09.宝贝解析失败"), DefaultValue(@"宝贝解析失败,请稍后重试"), + Description(@"宝贝解析失败提示语"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AnalysisError { get; set; } + + [ + Category("3)、积分操作"), DisplayName("01.积分奖励指令"), DefaultValue(@"^[加|减]?\s*?(?<积分>[\+-]?\d+?)元$"), + Description(@"给评价的用户奖励") + ] + public string PointOperation { get; set; } + + [ + Category("3)、积分操作"), DisplayName("02.积分奖励方式"), DefaultValue(RechargeType.余额), + Description(@"给评价的用户奖励") + ] + public RechargeType Point_RechargeType { get; set; } + + [ + Category("3)、积分操作"), DisplayName("03.积分奖励成功"), DefaultValue(@"成功奖励积分[奖励积分][积分名称] +【剩余积分】[剩余积分] [积分名称]"), + Description(@"给评价的用户奖励成功提示语 支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[奖励积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string PointRechargeSuccess { get; set; } + + [ + Category("3)、积分操作"), DisplayName("04.积分奖励失败"), DefaultValue(@"积分奖励失败"), + Description(@"给评价的用户奖励失败提示语 支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[奖励积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string PointRechargeError { get; set; } + + #endregion + + public Config() + { + this.TbLoginInfos = new List(); + this.CouponDenomination = "50-80"; + this.IsRounding = SwitchType.开启; + this.BondCommentPic = SwitchType.开启; + this.ManufacturePlansAddDay = 0; + this.ExpirationDate = 7; + this.AnalyzePage = 2; + this.PUTImage = 5; + this.AbductionPic = ButtonPic = string.Empty; + this.TbItemSavePath = Util.MapPath(@"File\评价工具缓存\其他图片"); + this.PointOperation = @"^[加|减]?\s*?(?<积分>[\+-]?\d+?)元$"; + this.Point_RechargeType = RechargeType.余额; + this.SearchingTip = @"评价信息合成中....."; + this.AnalysisError = @"宝贝解析失败,请稍后重试"; + this.AnalysisSuccess = @"宝贝解析成功.[追加参数]"; + this.PointRechargeError = @"积分奖励失败"; + this.PointRechargeSuccess = @"成功奖励积分[奖励积分][积分名称] +【剩余积分】[剩余积分] [积分名称]"; + } + + } +} diff --git a/应用/TBAppraisalTools/Entitys/TbBaseInfo.cs b/应用/TBAppraisalTools/Entitys/TbBaseInfo.cs new file mode 100644 index 0000000..e6f3e78 --- /dev/null +++ b/应用/TBAppraisalTools/Entitys/TbBaseInfo.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBAppraisalTools.Entitys +{ + public class TbBaseInfo + { + /// + /// 宝贝ID + /// + public string ItemId { get; set; } + /// + /// 月销量 + /// + public string SellCount { get; set; } + /// + /// 价格 + /// + public string Price { get; set; } + /// + /// 店铺名称 + /// + public string ShopName { get; set; } + /// + /// 店铺头像 + /// + public string ShopIcon { get; set; } + /// + /// + /// + public string UserId { get; set; } + /// + /// 商品主图 + /// + public string ItemImage { get; set; } + /// + /// 商品标题 + /// + public string ItemTitle { get; set; } + /// + /// 店铺Id + /// + public string SellerId { get; set; } + + } +} diff --git a/应用/TBAppraisalTools/Enums.cs b/应用/TBAppraisalTools/Enums.cs new file mode 100644 index 0000000..dbb6be9 --- /dev/null +++ b/应用/TBAppraisalTools/Enums.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBAppraisalTools +{ + public class Enums + { + /// + /// 编辑的图片的类型 + /// + public enum EditImageType + { + 商品主图 = 0, + 店铺头像 = 1 , + 其他图片 = 2 + } + + public enum RechargeType + { + 红包 = 0, + 转账 = 1, + 余额 = 2 + } + + } +} diff --git a/应用/TBAppraisalTools/Forms/EditPhotoForm.Designer.cs b/应用/TBAppraisalTools/Forms/EditPhotoForm.Designer.cs new file mode 100644 index 0000000..8197e85 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/EditPhotoForm.Designer.cs @@ -0,0 +1,270 @@ +namespace TBAppraisalTools.Forms +{ + partial class EditPhotoForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.cBox_Variable = new System.Windows.Forms.ComboBox(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.numericUpDown_Height = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown_Width = new System.Windows.Forms.NumericUpDown(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.radioButton2 = new System.Windows.Forms.RadioButton(); + this.radioButton1 = new System.Windows.Forms.RadioButton(); + this.btn_LocalImage = new DevExpress.XtraEditors.SimpleButton(); + this.tBox_path = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown_Height)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown_Width)).BeginInit(); + this.SuspendLayout(); + // + // cBox_Variable + // + this.cBox_Variable.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cBox_Variable.FormattingEnabled = true; + this.cBox_Variable.Location = new System.Drawing.Point(143, 52); + this.cBox_Variable.Name = "cBox_Variable"; + this.cBox_Variable.Size = new System.Drawing.Size(156, 22); + this.cBox_Variable.TabIndex = 0; + this.cBox_Variable.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.numericUpDown_Height); + this.groupControl1.Controls.Add(this.numericUpDown_Width); + this.groupControl1.Controls.Add(this.simpleButton3); + this.groupControl1.Controls.Add(this.simpleButton2); + this.groupControl1.Controls.Add(this.radioButton2); + this.groupControl1.Controls.Add(this.radioButton1); + this.groupControl1.Controls.Add(this.btn_LocalImage); + this.groupControl1.Controls.Add(this.tBox_path); + this.groupControl1.Controls.Add(this.label6); + this.groupControl1.Controls.Add(this.label5); + this.groupControl1.Controls.Add(this.label4); + this.groupControl1.Controls.Add(this.label3); + this.groupControl1.Controls.Add(this.label2); + this.groupControl1.Controls.Add(this.label1); + this.groupControl1.Controls.Add(this.cBox_Variable); + this.groupControl1.Location = new System.Drawing.Point(40, 39); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(467, 310); + this.groupControl1.TabIndex = 1; + this.groupControl1.Text = "基础信息"; + // + // numericUpDown_Height + // + this.numericUpDown_Height.Location = new System.Drawing.Point(311, 170); + this.numericUpDown_Height.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.numericUpDown_Height.Name = "numericUpDown_Height"; + this.numericUpDown_Height.Size = new System.Drawing.Size(93, 22); + this.numericUpDown_Height.TabIndex = 16; + this.numericUpDown_Height.Value = new decimal(new int[] { + 100, + 0, + 0, + 0}); + // + // numericUpDown_Width + // + this.numericUpDown_Width.Location = new System.Drawing.Point(141, 170); + this.numericUpDown_Width.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.numericUpDown_Width.Name = "numericUpDown_Width"; + this.numericUpDown_Width.Size = new System.Drawing.Size(93, 22); + this.numericUpDown_Width.TabIndex = 15; + this.numericUpDown_Width.Value = new decimal(new int[] { + 100, + 0, + 0, + 0}); + // + // simpleButton3 + // + this.simpleButton3.Location = new System.Drawing.Point(284, 215); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(75, 22); + this.simpleButton3.TabIndex = 14; + this.simpleButton3.Text = "取 消"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(151, 215); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(75, 22); + this.simpleButton2.TabIndex = 13; + this.simpleButton2.Text = "确 定"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // radioButton2 + // + this.radioButton2.AutoSize = true; + this.radioButton2.Location = new System.Drawing.Point(255, 131); + this.radioButton2.Name = "radioButton2"; + this.radioButton2.Size = new System.Drawing.Size(73, 18); + this.radioButton2.TabIndex = 10; + this.radioButton2.Text = "雏形图片"; + this.radioButton2.UseVisualStyleBackColor = true; + // + // radioButton1 + // + this.radioButton1.AutoSize = true; + this.radioButton1.Checked = true; + this.radioButton1.Location = new System.Drawing.Point(144, 131); + this.radioButton1.Name = "radioButton1"; + this.radioButton1.Size = new System.Drawing.Size(73, 18); + this.radioButton1.TabIndex = 9; + this.radioButton1.TabStop = true; + this.radioButton1.Text = "矩形图片"; + this.radioButton1.UseVisualStyleBackColor = true; + // + // btn_LocalImage + // + this.btn_LocalImage.Location = new System.Drawing.Point(344, 91); + this.btn_LocalImage.Name = "btn_LocalImage"; + this.btn_LocalImage.Size = new System.Drawing.Size(75, 22); + this.btn_LocalImage.TabIndex = 8; + this.btn_LocalImage.Text = "图 片"; + this.btn_LocalImage.Click += new System.EventHandler(this.btn_LocalImage_Click); + // + // tBox_path + // + this.tBox_path.Location = new System.Drawing.Point(143, 91); + this.tBox_path.Name = "tBox_path"; + this.tBox_path.Size = new System.Drawing.Size(195, 22); + this.tBox_path.TabIndex = 7; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(95, 267); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(290, 14); + this.label6.TabIndex = 6; + this.label6.Text = "注意:其他图片支持:本地上传、网络HTTP下载地址"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(71, 133); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(67, 14); + this.label5.TabIndex = 5; + this.label5.Text = "图片样式:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(252, 174); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(55, 14); + this.label4.TabIndex = 4; + this.label4.Text = "初始高:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(80, 174); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(55, 14); + this.label3.TabIndex = 3; + this.label3.Text = "初始宽:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(70, 94); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 2; + this.label2.Text = "图片地址:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(70, 55); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(67, 14); + this.label1.TabIndex = 1; + this.label1.Text = "图片类型:"; + // + // EditPhotoForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(552, 388); + this.Controls.Add(this.groupControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditPhotoForm"; + this.Text = "EditPhotoForm"; + this.Load += new System.EventHandler(this.EditPhotoForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown_Height)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown_Width)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ComboBox cBox_Variable; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.SimpleButton btn_LocalImage; + private System.Windows.Forms.TextBox tBox_path; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.RadioButton radioButton2; + private System.Windows.Forms.RadioButton radioButton1; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private System.Windows.Forms.NumericUpDown numericUpDown_Height; + private System.Windows.Forms.NumericUpDown numericUpDown_Width; + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/EditPhotoForm.cs b/应用/TBAppraisalTools/Forms/EditPhotoForm.cs new file mode 100644 index 0000000..4824701 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/EditPhotoForm.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using TBAppraisalTools.Properties; +using UI.Framework.Forms; +using static TBAppraisalTools.Enums; +using Api.Framework.Tools; +using System.IO; + +namespace TBAppraisalTools.Forms +{ + public partial class EditPhotoForm : BaseForm + { + public TbConfig tbConfig = null; + + /// + /// 增加/编辑图片 + /// + /// 为null时,添加 + public EditPhotoForm(TbConfig tbConfig = null) + { + InitializeComponent(); + this.Text = tbConfig == null ? Resources.AddPhotoTitle : Resources.EditPhotoTitle; + this.tbConfig = tbConfig; + } + + /// + /// 窗体加载 + /// + /// + /// + private void EditPhotoForm_Load(object sender, EventArgs e) + { + ImageInfo imageInfo = null; + if (tbConfig != null)//编辑图片信息 + { + imageInfo = tbConfig.C_Tag as ImageInfo; + radioButton1.Checked = imageInfo.Shape; + radioButton2.Checked = !imageInfo.Shape; + if (imageInfo.Varible.Contains(EditImageType.其他图片.ToString())) tBox_path.Text = imageInfo.ImagePath; + numericUpDown_Width.Value = tbConfig.C_Size.Width; + numericUpDown_Height.Value = tbConfig.C_Size.Height; + } + int i = -1;//定义这个是为了选中之后,带动触发事件 + foreach (EditImageType item in Enum.GetValues(typeof(EditImageType))) + { + i++; + cBox_Variable.Items.Add("#" + item.ToString()); + if (imageInfo != null && "#" + item.ToString() == imageInfo.Varible) + cBox_Variable.SelectedIndex = i; + } + if (cBox_Variable.SelectedIndex == -1) cBox_Variable.SelectedIndex = 0; + } + + /// + /// 图片类型下标改变时间 + /// + /// + /// + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + if (cBox_Variable.SelectedItem.ToString().Contains(EditImageType.其他图片.ToString())) + btn_LocalImage.Enabled = tBox_path.Enabled = true; + else + btn_LocalImage.Enabled = tBox_path.Enabled = false; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 上传图片 + /// + /// + /// + private void btn_LocalImage_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog fdlg = new OpenFileDialog(); + fdlg.Title = "选择要上传的图片"; + fdlg.InitialDirectory = @"c:\"; + fdlg.Filter = "jpg,png,bmp,gif|*.jpg;*.png;*.bmp;*.gif"; + fdlg.FilterIndex = 1; + fdlg.RestoreDirectory = true; + if (fdlg.ShowDialog() == DialogResult.OK) + tBox_path.Text = fdlg.FileName; + fdlg.Dispose(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + string path = string.Empty; + if (string.IsNullOrWhiteSpace(tBox_path.Text.Trim()) && cBox_Variable.SelectedItem.ToString().Contains(EditImageType.其他图片.ToString())) + throw new Exception("图片地址不能为空,请选择要添加的图片"); + if (cBox_Variable.SelectedItem.ToString().Contains(EditImageType.店铺头像.ToString())) + path = TbTools.SHOPICO; + else if (cBox_Variable.SelectedItem.ToString().Contains(EditImageType.商品主图.ToString())) + path = TbTools.ITEMICO; + else + { + path = tBox_path.Text.Trim(); + if (!File.Exists(path)) + { + var path_temp = Util.MapFile(Guid.NewGuid().ToString() + ".png", TbTools.OTHERSICOPATH); + Tools.DownloadImage(path, path_temp); + path = path_temp; + } + } + if (tbConfig == null) + tbConfig = new TbConfig() { C_Size = new Size() { Height = (int)numericUpDown_Height.Value, Width = (int)numericUpDown_Width.Value }, C_Tag = new ImageInfo() { Shape = radioButton1.Checked, ImagePath = path, Varible = cBox_Variable.SelectedItem.ToString() } }; + else + { + tbConfig.C_Size = new Size() { Height = (int)numericUpDown_Height.Value, Width = (int)numericUpDown_Width.Value }; + tbConfig.C_Tag = new ImageInfo() { Shape = radioButton1.Checked, ImagePath = path, Varible = cBox_Variable.SelectedItem.ToString() }; + } + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 关闭窗体 + /// + /// + /// + private void simpleButton3_Click(object sender, EventArgs e) + { + this.Close(); + } + + + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/EditPhotoForm.resx b/应用/TBAppraisalTools/Forms/EditPhotoForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/EditPhotoForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/EditTextForm.Designer.cs b/应用/TBAppraisalTools/Forms/EditTextForm.Designer.cs new file mode 100644 index 0000000..0e83279 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/EditTextForm.Designer.cs @@ -0,0 +1,1448 @@ +namespace TBAppraisalTools.Forms +{ + partial class EditTextForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditTextForm)); + this.repositoryItemFontEdit2 = new DevExpress.XtraEditors.Repository.RepositoryItemFontEdit(); + this.repositoryItemRichEditFontSizeEdit2 = new DevExpress.XtraRichEdit.Design.RepositoryItemRichEditFontSizeEdit(); + this.repositoryItemRichEditStyleEdit2 = new DevExpress.XtraRichEdit.Design.RepositoryItemRichEditStyleEdit(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label9 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.richEditControl1 = new DevExpress.XtraRichEdit.RichEditControl(); + this.barManager1 = new DevExpress.XtraBars.BarManager(this.components); + this.fontBar1 = new DevExpress.XtraRichEdit.UI.FontBar(); + this.changeFontNameItem2 = new DevExpress.XtraRichEdit.UI.ChangeFontNameItem(); + this.repositoryItemFontEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemFontEdit(); + this.changeFontSizeItem2 = new DevExpress.XtraRichEdit.UI.ChangeFontSizeItem(); + this.repositoryItemRichEditFontSizeEdit1 = new DevExpress.XtraRichEdit.Design.RepositoryItemRichEditFontSizeEdit(); + this.barEditItem1 = new DevExpress.XtraBars.BarEditItem(); + this.repositoryItemColorEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemColorEdit(); + this.toggleFontBoldItem1 = new DevExpress.XtraRichEdit.UI.ToggleFontBoldItem(); + this.toggleFontItalicItem1 = new DevExpress.XtraRichEdit.UI.ToggleFontItalicItem(); + this.toggleFontUnderlineItem1 = new DevExpress.XtraRichEdit.UI.ToggleFontUnderlineItem(); + this.toggleFontStrikeoutItem2 = new DevExpress.XtraRichEdit.UI.ToggleFontStrikeoutItem(); + this.barDockControlTop = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlBottom = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlLeft = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlRight = new DevExpress.XtraBars.BarDockControl(); + this.pasteItem2 = new DevExpress.XtraRichEdit.UI.PasteItem(); + this.cutItem2 = new DevExpress.XtraRichEdit.UI.CutItem(); + this.copyItem2 = new DevExpress.XtraRichEdit.UI.CopyItem(); + this.pasteSpecialItem2 = new DevExpress.XtraRichEdit.UI.PasteSpecialItem(); + this.fontSizeIncreaseItem2 = new DevExpress.XtraRichEdit.UI.FontSizeIncreaseItem(); + this.fontSizeDecreaseItem2 = new DevExpress.XtraRichEdit.UI.FontSizeDecreaseItem(); + this.toggleFontDoubleUnderlineItem2 = new DevExpress.XtraRichEdit.UI.ToggleFontDoubleUnderlineItem(); + this.toggleFontDoubleStrikeoutItem2 = new DevExpress.XtraRichEdit.UI.ToggleFontDoubleStrikeoutItem(); + this.toggleFontSuperscriptItem2 = new DevExpress.XtraRichEdit.UI.ToggleFontSuperscriptItem(); + this.toggleFontSubscriptItem2 = new DevExpress.XtraRichEdit.UI.ToggleFontSubscriptItem(); + this.changeFontColorItem1 = new DevExpress.XtraRichEdit.UI.ChangeFontColorItem(); + this.changeFontHighlightColorItem2 = new DevExpress.XtraRichEdit.UI.ChangeFontHighlightColorItem(); + this.changeTextCaseItem2 = new DevExpress.XtraRichEdit.UI.ChangeTextCaseItem(); + this.makeTextUpperCaseItem2 = new DevExpress.XtraRichEdit.UI.MakeTextUpperCaseItem(); + this.makeTextLowerCaseItem2 = new DevExpress.XtraRichEdit.UI.MakeTextLowerCaseItem(); + this.capitalizeEachWordCaseItem2 = new DevExpress.XtraRichEdit.UI.CapitalizeEachWordCaseItem(); + this.toggleTextCaseItem2 = new DevExpress.XtraRichEdit.UI.ToggleTextCaseItem(); + this.clearFormattingItem2 = new DevExpress.XtraRichEdit.UI.ClearFormattingItem(); + this.showFontFormItem2 = new DevExpress.XtraRichEdit.UI.ShowFontFormItem(); + this.toggleBulletedListItem2 = new DevExpress.XtraRichEdit.UI.ToggleBulletedListItem(); + this.toggleNumberingListItem2 = new DevExpress.XtraRichEdit.UI.ToggleNumberingListItem(); + this.toggleMultiLevelListItem2 = new DevExpress.XtraRichEdit.UI.ToggleMultiLevelListItem(); + this.decreaseIndentItem2 = new DevExpress.XtraRichEdit.UI.DecreaseIndentItem(); + this.increaseIndentItem2 = new DevExpress.XtraRichEdit.UI.IncreaseIndentItem(); + this.toggleParagraphAlignmentLeftItem2 = new DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentLeftItem(); + this.toggleParagraphAlignmentCenterItem2 = new DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentCenterItem(); + this.toggleParagraphAlignmentRightItem2 = new DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentRightItem(); + this.toggleParagraphAlignmentJustifyItem2 = new DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentJustifyItem(); + this.toggleShowWhitespaceItem2 = new DevExpress.XtraRichEdit.UI.ToggleShowWhitespaceItem(); + this.changeParagraphLineSpacingItem2 = new DevExpress.XtraRichEdit.UI.ChangeParagraphLineSpacingItem(); + this.setSingleParagraphSpacingItem2 = new DevExpress.XtraRichEdit.UI.SetSingleParagraphSpacingItem(); + this.setSesquialteralParagraphSpacingItem2 = new DevExpress.XtraRichEdit.UI.SetSesquialteralParagraphSpacingItem(); + this.setDoubleParagraphSpacingItem2 = new DevExpress.XtraRichEdit.UI.SetDoubleParagraphSpacingItem(); + this.showLineSpacingFormItem2 = new DevExpress.XtraRichEdit.UI.ShowLineSpacingFormItem(); + this.addSpacingBeforeParagraphItem2 = new DevExpress.XtraRichEdit.UI.AddSpacingBeforeParagraphItem(); + this.removeSpacingBeforeParagraphItem2 = new DevExpress.XtraRichEdit.UI.RemoveSpacingBeforeParagraphItem(); + this.addSpacingAfterParagraphItem2 = new DevExpress.XtraRichEdit.UI.AddSpacingAfterParagraphItem(); + this.removeSpacingAfterParagraphItem2 = new DevExpress.XtraRichEdit.UI.RemoveSpacingAfterParagraphItem(); + this.changeParagraphBackColorItem2 = new DevExpress.XtraRichEdit.UI.ChangeParagraphBackColorItem(); + this.showParagraphFormItem2 = new DevExpress.XtraRichEdit.UI.ShowParagraphFormItem(); + this.changeStyleItem1 = new DevExpress.XtraRichEdit.UI.ChangeStyleItem(); + this.repositoryItemRichEditStyleEdit1 = new DevExpress.XtraRichEdit.Design.RepositoryItemRichEditStyleEdit(); + this.showEditStyleFormItem2 = new DevExpress.XtraRichEdit.UI.ShowEditStyleFormItem(); + this.findItem2 = new DevExpress.XtraRichEdit.UI.FindItem(); + this.replaceItem2 = new DevExpress.XtraRichEdit.UI.ReplaceItem(); + this.clipboardBar1 = new DevExpress.XtraRichEdit.UI.ClipboardBar(); + this.paragraphBar1 = new DevExpress.XtraRichEdit.UI.ParagraphBar(); + this.stylesBar1 = new DevExpress.XtraRichEdit.UI.StylesBar(); + this.editingBar1 = new DevExpress.XtraRichEdit.UI.EditingBar(); + this.commonBar1 = new DevExpress.XtraRichEdit.UI.CommonBar(); + this.fileInfoBar1 = new DevExpress.XtraRichEdit.UI.FileInfoBar(); + this.fontBar2 = new DevExpress.XtraRichEdit.UI.FontBar(); + this.cutItem1 = new DevExpress.XtraRichEdit.UI.CutItem(); + this.copyItem1 = new DevExpress.XtraRichEdit.UI.CopyItem(); + this.pasteSpecialItem1 = new DevExpress.XtraRichEdit.UI.PasteSpecialItem(); + this.pasteItem1 = new DevExpress.XtraRichEdit.UI.PasteItem(); + this.changeFontNameItem1 = new DevExpress.XtraRichEdit.UI.ChangeFontNameItem(); + this.changeFontSizeItem1 = new DevExpress.XtraRichEdit.UI.ChangeFontSizeItem(); + this.fontSizeIncreaseItem1 = new DevExpress.XtraRichEdit.UI.FontSizeIncreaseItem(); + this.fontSizeDecreaseItem1 = new DevExpress.XtraRichEdit.UI.FontSizeDecreaseItem(); + this.toggleFontBoldItem2 = new DevExpress.XtraRichEdit.UI.ToggleFontBoldItem(); + this.toggleFontItalicItem2 = new DevExpress.XtraRichEdit.UI.ToggleFontItalicItem(); + this.toggleFontUnderlineItem2 = new DevExpress.XtraRichEdit.UI.ToggleFontUnderlineItem(); + this.toggleFontDoubleUnderlineItem1 = new DevExpress.XtraRichEdit.UI.ToggleFontDoubleUnderlineItem(); + this.toggleFontStrikeoutItem1 = new DevExpress.XtraRichEdit.UI.ToggleFontStrikeoutItem(); + this.toggleFontDoubleStrikeoutItem1 = new DevExpress.XtraRichEdit.UI.ToggleFontDoubleStrikeoutItem(); + this.toggleFontSuperscriptItem1 = new DevExpress.XtraRichEdit.UI.ToggleFontSuperscriptItem(); + this.toggleFontSubscriptItem1 = new DevExpress.XtraRichEdit.UI.ToggleFontSubscriptItem(); + this.changeFontColorItem2 = new DevExpress.XtraRichEdit.UI.ChangeFontColorItem(); + this.changeFontHighlightColorItem1 = new DevExpress.XtraRichEdit.UI.ChangeFontHighlightColorItem(); + this.changeTextCaseItem1 = new DevExpress.XtraRichEdit.UI.ChangeTextCaseItem(); + this.makeTextUpperCaseItem1 = new DevExpress.XtraRichEdit.UI.MakeTextUpperCaseItem(); + this.makeTextLowerCaseItem1 = new DevExpress.XtraRichEdit.UI.MakeTextLowerCaseItem(); + this.capitalizeEachWordCaseItem1 = new DevExpress.XtraRichEdit.UI.CapitalizeEachWordCaseItem(); + this.toggleTextCaseItem1 = new DevExpress.XtraRichEdit.UI.ToggleTextCaseItem(); + this.clearFormattingItem1 = new DevExpress.XtraRichEdit.UI.ClearFormattingItem(); + this.showFontFormItem1 = new DevExpress.XtraRichEdit.UI.ShowFontFormItem(); + this.toggleBulletedListItem1 = new DevExpress.XtraRichEdit.UI.ToggleBulletedListItem(); + this.toggleNumberingListItem1 = new DevExpress.XtraRichEdit.UI.ToggleNumberingListItem(); + this.toggleMultiLevelListItem1 = new DevExpress.XtraRichEdit.UI.ToggleMultiLevelListItem(); + this.decreaseIndentItem1 = new DevExpress.XtraRichEdit.UI.DecreaseIndentItem(); + this.increaseIndentItem1 = new DevExpress.XtraRichEdit.UI.IncreaseIndentItem(); + this.toggleParagraphAlignmentLeftItem1 = new DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentLeftItem(); + this.toggleParagraphAlignmentCenterItem1 = new DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentCenterItem(); + this.toggleParagraphAlignmentRightItem1 = new DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentRightItem(); + this.toggleParagraphAlignmentJustifyItem1 = new DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentJustifyItem(); + this.toggleShowWhitespaceItem1 = new DevExpress.XtraRichEdit.UI.ToggleShowWhitespaceItem(); + this.changeParagraphLineSpacingItem1 = new DevExpress.XtraRichEdit.UI.ChangeParagraphLineSpacingItem(); + this.setSingleParagraphSpacingItem1 = new DevExpress.XtraRichEdit.UI.SetSingleParagraphSpacingItem(); + this.setSesquialteralParagraphSpacingItem1 = new DevExpress.XtraRichEdit.UI.SetSesquialteralParagraphSpacingItem(); + this.setDoubleParagraphSpacingItem1 = new DevExpress.XtraRichEdit.UI.SetDoubleParagraphSpacingItem(); + this.showLineSpacingFormItem1 = new DevExpress.XtraRichEdit.UI.ShowLineSpacingFormItem(); + this.addSpacingBeforeParagraphItem1 = new DevExpress.XtraRichEdit.UI.AddSpacingBeforeParagraphItem(); + this.removeSpacingBeforeParagraphItem1 = new DevExpress.XtraRichEdit.UI.RemoveSpacingBeforeParagraphItem(); + this.addSpacingAfterParagraphItem1 = new DevExpress.XtraRichEdit.UI.AddSpacingAfterParagraphItem(); + this.removeSpacingAfterParagraphItem1 = new DevExpress.XtraRichEdit.UI.RemoveSpacingAfterParagraphItem(); + this.changeParagraphBackColorItem1 = new DevExpress.XtraRichEdit.UI.ChangeParagraphBackColorItem(); + this.showParagraphFormItem1 = new DevExpress.XtraRichEdit.UI.ShowParagraphFormItem(); + this.changeStyleItem2 = new DevExpress.XtraRichEdit.UI.ChangeStyleItem(); + this.showEditStyleFormItem1 = new DevExpress.XtraRichEdit.UI.ShowEditStyleFormItem(); + this.findItem1 = new DevExpress.XtraRichEdit.UI.FindItem(); + this.replaceItem1 = new DevExpress.XtraRichEdit.UI.ReplaceItem(); + this.barButtonItem4 = new DevExpress.XtraBars.BarButtonItem(); + this.showDocumentPropertiesFormItem1 = new DevExpress.XtraRichEdit.UI.ShowDocumentPropertiesFormItem(); + this.barDockControl4 = new DevExpress.XtraBars.BarDockControl(); + this.richEditBarController1 = new DevExpress.XtraRichEdit.UI.RichEditBarController(this.components); + this.clipboardBar2 = new DevExpress.XtraRichEdit.UI.ClipboardBar(); + this.paragraphBar2 = new DevExpress.XtraRichEdit.UI.ParagraphBar(); + this.stylesBar2 = new DevExpress.XtraRichEdit.UI.StylesBar(); + this.editingBar2 = new DevExpress.XtraRichEdit.UI.EditingBar(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemFontEdit2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemRichEditFontSizeEdit2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemRichEditStyleEdit2)).BeginInit(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.barManager1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemFontEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemRichEditFontSizeEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemColorEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemRichEditStyleEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.richEditBarController1)).BeginInit(); + this.SuspendLayout(); + // + // repositoryItemFontEdit2 + // + this.repositoryItemFontEdit2.AutoHeight = false; + this.repositoryItemFontEdit2.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemFontEdit2.Name = "repositoryItemFontEdit2"; + // + // repositoryItemRichEditFontSizeEdit2 + // + this.repositoryItemRichEditFontSizeEdit2.AutoHeight = false; + this.repositoryItemRichEditFontSizeEdit2.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemRichEditFontSizeEdit2.Control = null; + this.repositoryItemRichEditFontSizeEdit2.Items.AddRange(new object[] { + 8, + 9, + 10, + 11, + 12, + 14, + 16, + 18, + 20, + 22, + 24, + 26, + 28, + 36, + 48, + 72}); + this.repositoryItemRichEditFontSizeEdit2.Name = "repositoryItemRichEditFontSizeEdit2"; + // + // repositoryItemRichEditStyleEdit2 + // + this.repositoryItemRichEditStyleEdit2.AutoHeight = false; + this.repositoryItemRichEditStyleEdit2.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemRichEditStyleEdit2.Control = null; + this.repositoryItemRichEditStyleEdit2.Name = "repositoryItemRichEditStyleEdit2"; + // + // panel1 + // + this.panel1.Controls.Add(this.label9); + this.panel1.Controls.Add(this.label8); + this.panel1.Controls.Add(this.label7); + this.panel1.Controls.Add(this.label6); + this.panel1.Controls.Add(this.label5); + this.panel1.Controls.Add(this.label4); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.label2); + this.panel1.Controls.Add(this.label1); + this.panel1.Controls.Add(this.richEditControl1); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 31); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(739, 478); + this.panel1.TabIndex = 0; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Font = new System.Drawing.Font("Tahoma", 16F); + this.label9.Location = new System.Drawing.Point(19, 394); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(64, 27); + this.label9.TabIndex = 9; + this.label9.Text = "变量:"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Font = new System.Drawing.Font("新宋体", 16F, System.Drawing.FontStyle.Bold); + this.label8.ForeColor = System.Drawing.Color.Fuchsia; + this.label8.Location = new System.Drawing.Point(574, 438); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(114, 22); + this.label8.TabIndex = 8; + this.label8.Text = "#结束时间"; + this.label8.Click += new System.EventHandler(this.label_Click); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Font = new System.Drawing.Font("新宋体", 16F, System.Drawing.FontStyle.Bold); + this.label7.ForeColor = System.Drawing.Color.Fuchsia; + this.label7.Location = new System.Drawing.Point(413, 438); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(114, 22); + this.label7.TabIndex = 7; + this.label7.Text = "#开始时间"; + this.label7.Click += new System.EventHandler(this.label_Click); + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Font = new System.Drawing.Font("新宋体", 16F, System.Drawing.FontStyle.Bold); + this.label6.ForeColor = System.Drawing.Color.Fuchsia; + this.label6.Location = new System.Drawing.Point(252, 438); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(114, 22); + this.label6.TabIndex = 6; + this.label6.Text = "#券后特价"; + this.label6.Click += new System.EventHandler(this.label_Click); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Font = new System.Drawing.Font("新宋体", 16F, System.Drawing.FontStyle.Bold); + this.label5.ForeColor = System.Drawing.Color.Fuchsia; + this.label5.Location = new System.Drawing.Point(91, 438); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(114, 22); + this.label5.TabIndex = 5; + this.label5.Text = "#优惠券价"; + this.label5.Click += new System.EventHandler(this.label_Click); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Font = new System.Drawing.Font("新宋体", 16F, System.Drawing.FontStyle.Bold); + this.label4.ForeColor = System.Drawing.Color.Fuchsia; + this.label4.Location = new System.Drawing.Point(574, 397); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(114, 22); + this.label4.TabIndex = 4; + this.label4.Text = "#商品现价"; + this.label4.Click += new System.EventHandler(this.label_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Font = new System.Drawing.Font("新宋体", 16F, System.Drawing.FontStyle.Bold); + this.label3.ForeColor = System.Drawing.Color.Fuchsia; + this.label3.Location = new System.Drawing.Point(413, 397); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(114, 22); + this.label3.TabIndex = 3; + this.label3.Text = "#月销售量"; + this.label3.Click += new System.EventHandler(this.label_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("新宋体", 16F, System.Drawing.FontStyle.Bold); + this.label2.ForeColor = System.Drawing.Color.Fuchsia; + this.label2.Location = new System.Drawing.Point(252, 397); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(114, 22); + this.label2.TabIndex = 2; + this.label2.Text = "#商品标题"; + this.label2.Click += new System.EventHandler(this.label_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("新宋体", 16F, System.Drawing.FontStyle.Bold); + this.label1.ForeColor = System.Drawing.Color.Fuchsia; + this.label1.Location = new System.Drawing.Point(91, 397); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(114, 22); + this.label1.TabIndex = 1; + this.label1.Text = "#店铺名称"; + this.label1.Click += new System.EventHandler(this.label_Click); + // + // richEditControl1 + // + this.richEditControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.richEditControl1.Location = new System.Drawing.Point(0, 0); + this.richEditControl1.MenuManager = this.barManager1; + this.richEditControl1.Name = "richEditControl1"; + this.richEditControl1.Options.HorizontalScrollbar.Visibility = DevExpress.XtraRichEdit.RichEditScrollbarVisibility.Hidden; + this.richEditControl1.Options.Printing.PrintPreviewFormKind = DevExpress.XtraRichEdit.PrintPreviewFormKind.Bars; + this.richEditControl1.Options.VerticalScrollbar.Visibility = DevExpress.XtraRichEdit.RichEditScrollbarVisibility.Hidden; + this.richEditControl1.Size = new System.Drawing.Size(739, 378); + this.richEditControl1.TabIndex = 0; + // + // barManager1 + // + this.barManager1.Bars.AddRange(new DevExpress.XtraBars.Bar[] { + this.fontBar1}); + this.barManager1.DockControls.Add(this.barDockControlTop); + this.barManager1.DockControls.Add(this.barDockControlBottom); + this.barManager1.DockControls.Add(this.barDockControlLeft); + this.barManager1.DockControls.Add(this.barDockControlRight); + this.barManager1.Form = this; + this.barManager1.Items.AddRange(new DevExpress.XtraBars.BarItem[] { + this.pasteItem2, + this.cutItem2, + this.copyItem2, + this.pasteSpecialItem2, + this.changeFontNameItem2, + this.changeFontSizeItem2, + this.fontSizeIncreaseItem2, + this.fontSizeDecreaseItem2, + this.toggleFontBoldItem1, + this.toggleFontItalicItem1, + this.toggleFontUnderlineItem1, + this.toggleFontDoubleUnderlineItem2, + this.toggleFontStrikeoutItem2, + this.toggleFontDoubleStrikeoutItem2, + this.toggleFontSuperscriptItem2, + this.toggleFontSubscriptItem2, + this.changeFontColorItem1, + this.changeFontHighlightColorItem2, + this.changeTextCaseItem2, + this.makeTextUpperCaseItem2, + this.makeTextLowerCaseItem2, + this.capitalizeEachWordCaseItem2, + this.toggleTextCaseItem2, + this.clearFormattingItem2, + this.showFontFormItem2, + this.toggleBulletedListItem2, + this.toggleNumberingListItem2, + this.toggleMultiLevelListItem2, + this.decreaseIndentItem2, + this.increaseIndentItem2, + this.toggleParagraphAlignmentLeftItem2, + this.toggleParagraphAlignmentCenterItem2, + this.toggleParagraphAlignmentRightItem2, + this.toggleParagraphAlignmentJustifyItem2, + this.toggleShowWhitespaceItem2, + this.changeParagraphLineSpacingItem2, + this.setSingleParagraphSpacingItem2, + this.setSesquialteralParagraphSpacingItem2, + this.setDoubleParagraphSpacingItem2, + this.showLineSpacingFormItem2, + this.addSpacingBeforeParagraphItem2, + this.removeSpacingBeforeParagraphItem2, + this.addSpacingAfterParagraphItem2, + this.removeSpacingAfterParagraphItem2, + this.changeParagraphBackColorItem2, + this.showParagraphFormItem2, + this.changeStyleItem1, + this.showEditStyleFormItem2, + this.findItem2, + this.replaceItem2, + this.barEditItem1}); + this.barManager1.MaxItemId = 61; + this.barManager1.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemFontEdit1, + this.repositoryItemRichEditFontSizeEdit1, + this.repositoryItemRichEditStyleEdit1, + this.repositoryItemColorEdit1}); + // + // fontBar1 + // + this.fontBar1.Control = this.richEditControl1; + this.fontBar1.DockCol = 0; + this.fontBar1.DockRow = 0; + this.fontBar1.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.fontBar1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(((DevExpress.XtraBars.BarLinkUserDefines)((DevExpress.XtraBars.BarLinkUserDefines.PaintStyle | DevExpress.XtraBars.BarLinkUserDefines.KeyTip))), this.changeFontNameItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph, "FF", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.PaintStyle, this.changeFontSizeItem2, DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.PaintStyle, this.barEditItem1, DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph), + new DevExpress.XtraBars.LinkPersistInfo(this.toggleFontBoldItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.toggleFontItalicItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.toggleFontUnderlineItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.toggleFontStrikeoutItem2)}); + // + // changeFontNameItem2 + // + this.changeFontNameItem2.Caption = "字体"; + this.changeFontNameItem2.Edit = this.repositoryItemFontEdit1; + this.changeFontNameItem2.Id = 11; + this.changeFontNameItem2.Name = "changeFontNameItem2"; + this.changeFontNameItem2.EditValueChanged += new System.EventHandler(this.changeFontNameItem2_EditValueChanged); + // + // repositoryItemFontEdit1 + // + this.repositoryItemFontEdit1.AutoHeight = false; + this.repositoryItemFontEdit1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemFontEdit1.Name = "repositoryItemFontEdit1"; + // + // changeFontSizeItem2 + // + this.changeFontSizeItem2.Caption = "字体大小"; + this.changeFontSizeItem2.Edit = this.repositoryItemRichEditFontSizeEdit1; + this.changeFontSizeItem2.Id = 12; + this.changeFontSizeItem2.Name = "changeFontSizeItem2"; + this.changeFontSizeItem2.EditValueChanged += new System.EventHandler(this.changeFontSizeItem2_EditValueChanged); + // + // repositoryItemRichEditFontSizeEdit1 + // + this.repositoryItemRichEditFontSizeEdit1.AutoHeight = false; + this.repositoryItemRichEditFontSizeEdit1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemRichEditFontSizeEdit1.Control = this.richEditControl1; + this.repositoryItemRichEditFontSizeEdit1.Name = "repositoryItemRichEditFontSizeEdit1"; + // + // barEditItem1 + // + this.barEditItem1.Caption = "颜色"; + this.barEditItem1.Edit = this.repositoryItemColorEdit1; + this.barEditItem1.Id = 10; + this.barEditItem1.Name = "barEditItem1"; + this.barEditItem1.EditValueChanged += new System.EventHandler(this.barEditItem1_EditValueChanged); + // + // repositoryItemColorEdit1 + // + this.repositoryItemColorEdit1.AutoHeight = false; + this.repositoryItemColorEdit1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemColorEdit1.Name = "repositoryItemColorEdit1"; + // + // toggleFontBoldItem1 + // + this.toggleFontBoldItem1.Id = 15; + this.toggleFontBoldItem1.Name = "toggleFontBoldItem1"; + this.toggleFontBoldItem1.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.toggleFontBoldItem1_ItemClick); + // + // toggleFontItalicItem1 + // + this.toggleFontItalicItem1.Id = 16; + this.toggleFontItalicItem1.Name = "toggleFontItalicItem1"; + this.toggleFontItalicItem1.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.toggleFontItalicItem1_ItemClick); + // + // toggleFontUnderlineItem1 + // + this.toggleFontUnderlineItem1.Id = 17; + this.toggleFontUnderlineItem1.Name = "toggleFontUnderlineItem1"; + this.toggleFontUnderlineItem1.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.toggleFontUnderlineItem1_ItemClick); + // + // toggleFontStrikeoutItem2 + // + this.toggleFontStrikeoutItem2.Id = 18; + this.toggleFontStrikeoutItem2.Name = "toggleFontStrikeoutItem2"; + this.toggleFontStrikeoutItem2.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.toggleFontStrikeoutItem2_ItemClick); + // + // barDockControlTop + // + this.barDockControlTop.CausesValidation = false; + this.barDockControlTop.Dock = System.Windows.Forms.DockStyle.Top; + this.barDockControlTop.Location = new System.Drawing.Point(0, 0); + this.barDockControlTop.Manager = this.barManager1; + this.barDockControlTop.Size = new System.Drawing.Size(739, 31); + // + // barDockControlBottom + // + this.barDockControlBottom.CausesValidation = false; + this.barDockControlBottom.Dock = System.Windows.Forms.DockStyle.Bottom; + this.barDockControlBottom.Location = new System.Drawing.Point(0, 509); + this.barDockControlBottom.Manager = this.barManager1; + this.barDockControlBottom.Size = new System.Drawing.Size(739, 0); + // + // barDockControlLeft + // + this.barDockControlLeft.CausesValidation = false; + this.barDockControlLeft.Dock = System.Windows.Forms.DockStyle.Left; + this.barDockControlLeft.Location = new System.Drawing.Point(0, 31); + this.barDockControlLeft.Manager = this.barManager1; + this.barDockControlLeft.Size = new System.Drawing.Size(0, 478); + // + // barDockControlRight + // + this.barDockControlRight.CausesValidation = false; + this.barDockControlRight.Dock = System.Windows.Forms.DockStyle.Right; + this.barDockControlRight.Location = new System.Drawing.Point(739, 31); + this.barDockControlRight.Manager = this.barManager1; + this.barDockControlRight.Size = new System.Drawing.Size(0, 478); + // + // pasteItem2 + // + this.pasteItem2.Id = 23; + this.pasteItem2.Name = "pasteItem2"; + // + // cutItem2 + // + this.cutItem2.Id = 24; + this.cutItem2.Name = "cutItem2"; + // + // copyItem2 + // + this.copyItem2.Id = 25; + this.copyItem2.Name = "copyItem2"; + // + // pasteSpecialItem2 + // + this.pasteSpecialItem2.Id = 26; + this.pasteSpecialItem2.Name = "pasteSpecialItem2"; + // + // fontSizeIncreaseItem2 + // + this.fontSizeIncreaseItem2.Id = 13; + this.fontSizeIncreaseItem2.Name = "fontSizeIncreaseItem2"; + // + // fontSizeDecreaseItem2 + // + this.fontSizeDecreaseItem2.Id = 14; + this.fontSizeDecreaseItem2.Name = "fontSizeDecreaseItem2"; + // + // toggleFontDoubleUnderlineItem2 + // + this.toggleFontDoubleUnderlineItem2.Id = 27; + this.toggleFontDoubleUnderlineItem2.Name = "toggleFontDoubleUnderlineItem2"; + // + // toggleFontDoubleStrikeoutItem2 + // + this.toggleFontDoubleStrikeoutItem2.Id = 28; + this.toggleFontDoubleStrikeoutItem2.Name = "toggleFontDoubleStrikeoutItem2"; + // + // toggleFontSuperscriptItem2 + // + this.toggleFontSuperscriptItem2.Id = 29; + this.toggleFontSuperscriptItem2.Name = "toggleFontSuperscriptItem2"; + // + // toggleFontSubscriptItem2 + // + this.toggleFontSubscriptItem2.Id = 30; + this.toggleFontSubscriptItem2.Name = "toggleFontSubscriptItem2"; + // + // changeFontColorItem1 + // + this.changeFontColorItem1.Id = 19; + this.changeFontColorItem1.Name = "changeFontColorItem1"; + // + // changeFontHighlightColorItem2 + // + this.changeFontHighlightColorItem2.Id = 20; + this.changeFontHighlightColorItem2.Name = "changeFontHighlightColorItem2"; + // + // changeTextCaseItem2 + // + this.changeTextCaseItem2.Id = 31; + this.changeTextCaseItem2.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.makeTextUpperCaseItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.makeTextLowerCaseItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.capitalizeEachWordCaseItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.toggleTextCaseItem2)}); + this.changeTextCaseItem2.Name = "changeTextCaseItem2"; + // + // makeTextUpperCaseItem2 + // + this.makeTextUpperCaseItem2.Id = 32; + this.makeTextUpperCaseItem2.Name = "makeTextUpperCaseItem2"; + // + // makeTextLowerCaseItem2 + // + this.makeTextLowerCaseItem2.Id = 33; + this.makeTextLowerCaseItem2.Name = "makeTextLowerCaseItem2"; + // + // capitalizeEachWordCaseItem2 + // + this.capitalizeEachWordCaseItem2.Id = 34; + this.capitalizeEachWordCaseItem2.Name = "capitalizeEachWordCaseItem2"; + // + // toggleTextCaseItem2 + // + this.toggleTextCaseItem2.Id = 35; + this.toggleTextCaseItem2.Name = "toggleTextCaseItem2"; + // + // clearFormattingItem2 + // + this.clearFormattingItem2.Id = 21; + this.clearFormattingItem2.Name = "clearFormattingItem2"; + // + // showFontFormItem2 + // + this.showFontFormItem2.Id = 22; + this.showFontFormItem2.Name = "showFontFormItem2"; + // + // toggleBulletedListItem2 + // + this.toggleBulletedListItem2.Id = 36; + this.toggleBulletedListItem2.Name = "toggleBulletedListItem2"; + // + // toggleNumberingListItem2 + // + this.toggleNumberingListItem2.Id = 37; + this.toggleNumberingListItem2.Name = "toggleNumberingListItem2"; + // + // toggleMultiLevelListItem2 + // + this.toggleMultiLevelListItem2.Id = 38; + this.toggleMultiLevelListItem2.Name = "toggleMultiLevelListItem2"; + // + // decreaseIndentItem2 + // + this.decreaseIndentItem2.Id = 39; + this.decreaseIndentItem2.Name = "decreaseIndentItem2"; + // + // increaseIndentItem2 + // + this.increaseIndentItem2.Id = 40; + this.increaseIndentItem2.Name = "increaseIndentItem2"; + // + // toggleParagraphAlignmentLeftItem2 + // + this.toggleParagraphAlignmentLeftItem2.Id = 41; + this.toggleParagraphAlignmentLeftItem2.Name = "toggleParagraphAlignmentLeftItem2"; + // + // toggleParagraphAlignmentCenterItem2 + // + this.toggleParagraphAlignmentCenterItem2.Id = 42; + this.toggleParagraphAlignmentCenterItem2.Name = "toggleParagraphAlignmentCenterItem2"; + // + // toggleParagraphAlignmentRightItem2 + // + this.toggleParagraphAlignmentRightItem2.Id = 43; + this.toggleParagraphAlignmentRightItem2.Name = "toggleParagraphAlignmentRightItem2"; + // + // toggleParagraphAlignmentJustifyItem2 + // + this.toggleParagraphAlignmentJustifyItem2.Id = 44; + this.toggleParagraphAlignmentJustifyItem2.Name = "toggleParagraphAlignmentJustifyItem2"; + // + // toggleShowWhitespaceItem2 + // + this.toggleShowWhitespaceItem2.Id = 45; + this.toggleShowWhitespaceItem2.Name = "toggleShowWhitespaceItem2"; + // + // changeParagraphLineSpacingItem2 + // + this.changeParagraphLineSpacingItem2.Id = 46; + this.changeParagraphLineSpacingItem2.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.setSingleParagraphSpacingItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.setSesquialteralParagraphSpacingItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.setDoubleParagraphSpacingItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.showLineSpacingFormItem2), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.addSpacingBeforeParagraphItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "B", ""), + new DevExpress.XtraBars.LinkPersistInfo(this.removeSpacingBeforeParagraphItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.addSpacingAfterParagraphItem2), + new DevExpress.XtraBars.LinkPersistInfo(this.removeSpacingAfterParagraphItem2)}); + this.changeParagraphLineSpacingItem2.Name = "changeParagraphLineSpacingItem2"; + // + // setSingleParagraphSpacingItem2 + // + this.setSingleParagraphSpacingItem2.Id = 47; + this.setSingleParagraphSpacingItem2.Name = "setSingleParagraphSpacingItem2"; + // + // setSesquialteralParagraphSpacingItem2 + // + this.setSesquialteralParagraphSpacingItem2.Id = 48; + this.setSesquialteralParagraphSpacingItem2.Name = "setSesquialteralParagraphSpacingItem2"; + // + // setDoubleParagraphSpacingItem2 + // + this.setDoubleParagraphSpacingItem2.Id = 49; + this.setDoubleParagraphSpacingItem2.Name = "setDoubleParagraphSpacingItem2"; + // + // showLineSpacingFormItem2 + // + this.showLineSpacingFormItem2.Id = 50; + this.showLineSpacingFormItem2.Name = "showLineSpacingFormItem2"; + // + // addSpacingBeforeParagraphItem2 + // + this.addSpacingBeforeParagraphItem2.Id = 51; + this.addSpacingBeforeParagraphItem2.Name = "addSpacingBeforeParagraphItem2"; + // + // removeSpacingBeforeParagraphItem2 + // + this.removeSpacingBeforeParagraphItem2.Id = 52; + this.removeSpacingBeforeParagraphItem2.Name = "removeSpacingBeforeParagraphItem2"; + // + // addSpacingAfterParagraphItem2 + // + this.addSpacingAfterParagraphItem2.Id = 53; + this.addSpacingAfterParagraphItem2.Name = "addSpacingAfterParagraphItem2"; + // + // removeSpacingAfterParagraphItem2 + // + this.removeSpacingAfterParagraphItem2.Id = 54; + this.removeSpacingAfterParagraphItem2.Name = "removeSpacingAfterParagraphItem2"; + // + // changeParagraphBackColorItem2 + // + this.changeParagraphBackColorItem2.Id = 55; + this.changeParagraphBackColorItem2.Name = "changeParagraphBackColorItem2"; + // + // showParagraphFormItem2 + // + this.showParagraphFormItem2.Id = 56; + this.showParagraphFormItem2.Name = "showParagraphFormItem2"; + // + // changeStyleItem1 + // + this.changeStyleItem1.Edit = this.repositoryItemRichEditStyleEdit1; + this.changeStyleItem1.Id = 57; + this.changeStyleItem1.Name = "changeStyleItem1"; + // + // repositoryItemRichEditStyleEdit1 + // + this.repositoryItemRichEditStyleEdit1.AutoHeight = false; + this.repositoryItemRichEditStyleEdit1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemRichEditStyleEdit1.Control = this.richEditControl1; + this.repositoryItemRichEditStyleEdit1.Name = "repositoryItemRichEditStyleEdit1"; + // + // showEditStyleFormItem2 + // + this.showEditStyleFormItem2.Id = 58; + this.showEditStyleFormItem2.Name = "showEditStyleFormItem2"; + // + // findItem2 + // + this.findItem2.Id = 59; + this.findItem2.Name = "findItem2"; + // + // replaceItem2 + // + this.replaceItem2.Id = 60; + this.replaceItem2.Name = "replaceItem2"; + // + // clipboardBar1 + // + this.clipboardBar1.BarName = ""; + this.clipboardBar1.Control = null; + this.clipboardBar1.DockCol = 3; + this.clipboardBar1.DockRow = 0; + this.clipboardBar1.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.clipboardBar1.Offset = 733; + this.clipboardBar1.Text = ""; + this.clipboardBar1.Visible = false; + // + // paragraphBar1 + // + this.paragraphBar1.BarName = ""; + this.paragraphBar1.Control = null; + this.paragraphBar1.DockCol = 1; + this.paragraphBar1.DockRow = 0; + this.paragraphBar1.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.paragraphBar1.Text = ""; + this.paragraphBar1.Visible = false; + // + // stylesBar1 + // + this.stylesBar1.BarName = ""; + this.stylesBar1.Control = null; + this.stylesBar1.DockCol = 4; + this.stylesBar1.DockRow = 0; + this.stylesBar1.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.stylesBar1.Offset = 450; + this.stylesBar1.Text = ""; + this.stylesBar1.Visible = false; + // + // editingBar1 + // + this.editingBar1.BarName = ""; + this.editingBar1.Control = null; + this.editingBar1.DockCol = 2; + this.editingBar1.DockRow = 0; + this.editingBar1.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.editingBar1.Offset = 485; + this.editingBar1.Text = ""; + this.editingBar1.Visible = false; + // + // commonBar1 + // + this.commonBar1.BarName = ""; + this.commonBar1.Control = null; + this.commonBar1.DockCol = 0; + this.commonBar1.DockRow = 1; + this.commonBar1.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.commonBar1.Text = ""; + // + // fileInfoBar1 + // + this.fileInfoBar1.BarName = ""; + this.fileInfoBar1.Control = null; + this.fileInfoBar1.DockCol = 0; + this.fileInfoBar1.DockRow = 0; + this.fileInfoBar1.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.fileInfoBar1.Text = ""; + this.fileInfoBar1.Visible = false; + // + // fontBar2 + // + this.fontBar2.BarName = ""; + this.fontBar2.Control = null; + this.fontBar2.DockCol = 1; + this.fontBar2.DockRow = 1; + this.fontBar2.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.fontBar2.FloatLocation = new System.Drawing.Point(270, 277); + this.fontBar2.Offset = 3; + this.fontBar2.Text = ""; + // + // cutItem1 + // + this.cutItem1.Id = 1; + this.cutItem1.Name = "cutItem1"; + // + // copyItem1 + // + this.copyItem1.Id = 2; + this.copyItem1.Name = "copyItem1"; + // + // pasteSpecialItem1 + // + this.pasteSpecialItem1.Id = 3; + this.pasteSpecialItem1.Name = "pasteSpecialItem1"; + // + // pasteItem1 + // + this.pasteItem1.Id = 0; + this.pasteItem1.Name = "pasteItem1"; + // + // changeFontNameItem1 + // + this.changeFontNameItem1.Edit = this.repositoryItemFontEdit2; + this.changeFontNameItem1.Id = 4; + this.changeFontNameItem1.Name = "changeFontNameItem1"; + // + // changeFontSizeItem1 + // + this.changeFontSizeItem1.Edit = this.repositoryItemRichEditFontSizeEdit2; + this.changeFontSizeItem1.Id = 5; + this.changeFontSizeItem1.Name = "changeFontSizeItem1"; + // + // fontSizeIncreaseItem1 + // + this.fontSizeIncreaseItem1.Id = 6; + this.fontSizeIncreaseItem1.Name = "fontSizeIncreaseItem1"; + this.fontSizeIncreaseItem1.Visibility = DevExpress.XtraBars.BarItemVisibility.Never; + // + // fontSizeDecreaseItem1 + // + this.fontSizeDecreaseItem1.Id = 7; + this.fontSizeDecreaseItem1.Name = "fontSizeDecreaseItem1"; + this.fontSizeDecreaseItem1.Visibility = DevExpress.XtraBars.BarItemVisibility.Never; + // + // toggleFontBoldItem2 + // + this.toggleFontBoldItem2.Caption = "加粗"; + this.toggleFontBoldItem2.Id = 8; + this.toggleFontBoldItem2.Name = "toggleFontBoldItem2"; + // + // toggleFontItalicItem2 + // + this.toggleFontItalicItem2.Caption = "斜体"; + this.toggleFontItalicItem2.Id = 9; + this.toggleFontItalicItem2.Name = "toggleFontItalicItem2"; + // + // toggleFontUnderlineItem2 + // + this.toggleFontUnderlineItem2.Caption = "下划线"; + this.toggleFontUnderlineItem2.Id = 10; + this.toggleFontUnderlineItem2.Name = "toggleFontUnderlineItem2"; + // + // toggleFontDoubleUnderlineItem1 + // + this.toggleFontDoubleUnderlineItem1.Id = 11; + this.toggleFontDoubleUnderlineItem1.Name = "toggleFontDoubleUnderlineItem1"; + // + // toggleFontStrikeoutItem1 + // + this.toggleFontStrikeoutItem1.Id = 12; + this.toggleFontStrikeoutItem1.Name = "toggleFontStrikeoutItem1"; + // + // toggleFontDoubleStrikeoutItem1 + // + this.toggleFontDoubleStrikeoutItem1.Id = 13; + this.toggleFontDoubleStrikeoutItem1.Name = "toggleFontDoubleStrikeoutItem1"; + // + // toggleFontSuperscriptItem1 + // + this.toggleFontSuperscriptItem1.Id = 14; + this.toggleFontSuperscriptItem1.Name = "toggleFontSuperscriptItem1"; + // + // toggleFontSubscriptItem1 + // + this.toggleFontSubscriptItem1.Id = 15; + this.toggleFontSubscriptItem1.Name = "toggleFontSubscriptItem1"; + // + // changeFontColorItem2 + // + this.changeFontColorItem2.Caption = "颜色"; + this.changeFontColorItem2.Id = 16; + this.changeFontColorItem2.Name = "changeFontColorItem2"; + // + // changeFontHighlightColorItem1 + // + this.changeFontHighlightColorItem1.Id = 17; + this.changeFontHighlightColorItem1.Name = "changeFontHighlightColorItem1"; + // + // changeTextCaseItem1 + // + this.changeTextCaseItem1.Id = 18; + this.changeTextCaseItem1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.makeTextUpperCaseItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.makeTextLowerCaseItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.capitalizeEachWordCaseItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.toggleTextCaseItem1)}); + this.changeTextCaseItem1.Name = "changeTextCaseItem1"; + // + // makeTextUpperCaseItem1 + // + this.makeTextUpperCaseItem1.Id = 19; + this.makeTextUpperCaseItem1.Name = "makeTextUpperCaseItem1"; + // + // makeTextLowerCaseItem1 + // + this.makeTextLowerCaseItem1.Id = 20; + this.makeTextLowerCaseItem1.Name = "makeTextLowerCaseItem1"; + // + // capitalizeEachWordCaseItem1 + // + this.capitalizeEachWordCaseItem1.Id = 21; + this.capitalizeEachWordCaseItem1.Name = "capitalizeEachWordCaseItem1"; + // + // toggleTextCaseItem1 + // + this.toggleTextCaseItem1.Id = 22; + this.toggleTextCaseItem1.Name = "toggleTextCaseItem1"; + // + // clearFormattingItem1 + // + this.clearFormattingItem1.Id = 23; + this.clearFormattingItem1.Name = "clearFormattingItem1"; + // + // showFontFormItem1 + // + this.showFontFormItem1.Id = 24; + this.showFontFormItem1.Name = "showFontFormItem1"; + // + // toggleBulletedListItem1 + // + this.toggleBulletedListItem1.Id = 25; + this.toggleBulletedListItem1.Name = "toggleBulletedListItem1"; + // + // toggleNumberingListItem1 + // + this.toggleNumberingListItem1.Id = 26; + this.toggleNumberingListItem1.Name = "toggleNumberingListItem1"; + // + // toggleMultiLevelListItem1 + // + this.toggleMultiLevelListItem1.Id = 27; + this.toggleMultiLevelListItem1.Name = "toggleMultiLevelListItem1"; + // + // decreaseIndentItem1 + // + this.decreaseIndentItem1.Id = 28; + this.decreaseIndentItem1.Name = "decreaseIndentItem1"; + // + // increaseIndentItem1 + // + this.increaseIndentItem1.Id = 29; + this.increaseIndentItem1.Name = "increaseIndentItem1"; + // + // toggleParagraphAlignmentLeftItem1 + // + this.toggleParagraphAlignmentLeftItem1.Id = 30; + this.toggleParagraphAlignmentLeftItem1.Name = "toggleParagraphAlignmentLeftItem1"; + // + // toggleParagraphAlignmentCenterItem1 + // + this.toggleParagraphAlignmentCenterItem1.Id = 31; + this.toggleParagraphAlignmentCenterItem1.Name = "toggleParagraphAlignmentCenterItem1"; + // + // toggleParagraphAlignmentRightItem1 + // + this.toggleParagraphAlignmentRightItem1.Id = 32; + this.toggleParagraphAlignmentRightItem1.Name = "toggleParagraphAlignmentRightItem1"; + // + // toggleParagraphAlignmentJustifyItem1 + // + this.toggleParagraphAlignmentJustifyItem1.Id = 33; + this.toggleParagraphAlignmentJustifyItem1.Name = "toggleParagraphAlignmentJustifyItem1"; + // + // toggleShowWhitespaceItem1 + // + this.toggleShowWhitespaceItem1.Id = 34; + this.toggleShowWhitespaceItem1.Name = "toggleShowWhitespaceItem1"; + // + // changeParagraphLineSpacingItem1 + // + this.changeParagraphLineSpacingItem1.Id = 35; + this.changeParagraphLineSpacingItem1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.setSingleParagraphSpacingItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.setSesquialteralParagraphSpacingItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.setDoubleParagraphSpacingItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.showLineSpacingFormItem1), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.addSpacingBeforeParagraphItem1, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "B", ""), + new DevExpress.XtraBars.LinkPersistInfo(this.removeSpacingBeforeParagraphItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.addSpacingAfterParagraphItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.removeSpacingAfterParagraphItem1)}); + this.changeParagraphLineSpacingItem1.Name = "changeParagraphLineSpacingItem1"; + // + // setSingleParagraphSpacingItem1 + // + this.setSingleParagraphSpacingItem1.Id = 36; + this.setSingleParagraphSpacingItem1.Name = "setSingleParagraphSpacingItem1"; + // + // setSesquialteralParagraphSpacingItem1 + // + this.setSesquialteralParagraphSpacingItem1.Id = 37; + this.setSesquialteralParagraphSpacingItem1.Name = "setSesquialteralParagraphSpacingItem1"; + // + // setDoubleParagraphSpacingItem1 + // + this.setDoubleParagraphSpacingItem1.Id = 38; + this.setDoubleParagraphSpacingItem1.Name = "setDoubleParagraphSpacingItem1"; + // + // showLineSpacingFormItem1 + // + this.showLineSpacingFormItem1.Id = 39; + this.showLineSpacingFormItem1.Name = "showLineSpacingFormItem1"; + // + // addSpacingBeforeParagraphItem1 + // + this.addSpacingBeforeParagraphItem1.Id = 40; + this.addSpacingBeforeParagraphItem1.Name = "addSpacingBeforeParagraphItem1"; + // + // removeSpacingBeforeParagraphItem1 + // + this.removeSpacingBeforeParagraphItem1.Id = 41; + this.removeSpacingBeforeParagraphItem1.Name = "removeSpacingBeforeParagraphItem1"; + // + // addSpacingAfterParagraphItem1 + // + this.addSpacingAfterParagraphItem1.Id = 42; + this.addSpacingAfterParagraphItem1.Name = "addSpacingAfterParagraphItem1"; + // + // removeSpacingAfterParagraphItem1 + // + this.removeSpacingAfterParagraphItem1.Id = 43; + this.removeSpacingAfterParagraphItem1.Name = "removeSpacingAfterParagraphItem1"; + // + // changeParagraphBackColorItem1 + // + this.changeParagraphBackColorItem1.Id = 44; + this.changeParagraphBackColorItem1.Name = "changeParagraphBackColorItem1"; + // + // showParagraphFormItem1 + // + this.showParagraphFormItem1.Id = 45; + this.showParagraphFormItem1.Name = "showParagraphFormItem1"; + // + // changeStyleItem2 + // + this.changeStyleItem2.Edit = this.repositoryItemRichEditStyleEdit2; + this.changeStyleItem2.Id = 46; + this.changeStyleItem2.Name = "changeStyleItem2"; + // + // showEditStyleFormItem1 + // + this.showEditStyleFormItem1.Id = 47; + this.showEditStyleFormItem1.Name = "showEditStyleFormItem1"; + // + // findItem1 + // + this.findItem1.Id = 48; + this.findItem1.Name = "findItem1"; + // + // replaceItem1 + // + this.replaceItem1.Id = 49; + this.replaceItem1.Name = "replaceItem1"; + // + // barButtonItem4 + // + this.barButtonItem4.Caption = "保存"; + this.barButtonItem4.Id = 264; + this.barButtonItem4.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem4.ImageOptions.Image"))); + this.barButtonItem4.Name = "barButtonItem4"; + // + // showDocumentPropertiesFormItem1 + // + this.showDocumentPropertiesFormItem1.Enabled = false; + this.showDocumentPropertiesFormItem1.Id = 263; + this.showDocumentPropertiesFormItem1.Name = "showDocumentPropertiesFormItem1"; + // + // barDockControl4 + // + this.barDockControl4.CausesValidation = false; + this.barDockControl4.Dock = System.Windows.Forms.DockStyle.Right; + this.barDockControl4.Location = new System.Drawing.Point(739, 31); + this.barDockControl4.Manager = null; + this.barDockControl4.Size = new System.Drawing.Size(0, 478); + // + // richEditBarController1 + // + this.richEditBarController1.BarItems.Add(this.pasteItem2); + this.richEditBarController1.BarItems.Add(this.cutItem2); + this.richEditBarController1.BarItems.Add(this.copyItem2); + this.richEditBarController1.BarItems.Add(this.pasteSpecialItem2); + this.richEditBarController1.BarItems.Add(this.changeFontNameItem2); + this.richEditBarController1.BarItems.Add(this.changeFontSizeItem2); + this.richEditBarController1.BarItems.Add(this.fontSizeIncreaseItem2); + this.richEditBarController1.BarItems.Add(this.fontSizeDecreaseItem2); + this.richEditBarController1.BarItems.Add(this.toggleFontBoldItem1); + this.richEditBarController1.BarItems.Add(this.toggleFontItalicItem1); + this.richEditBarController1.BarItems.Add(this.toggleFontUnderlineItem1); + this.richEditBarController1.BarItems.Add(this.toggleFontDoubleUnderlineItem2); + this.richEditBarController1.BarItems.Add(this.toggleFontStrikeoutItem2); + this.richEditBarController1.BarItems.Add(this.toggleFontDoubleStrikeoutItem2); + this.richEditBarController1.BarItems.Add(this.toggleFontSuperscriptItem2); + this.richEditBarController1.BarItems.Add(this.toggleFontSubscriptItem2); + this.richEditBarController1.BarItems.Add(this.changeFontColorItem1); + this.richEditBarController1.BarItems.Add(this.changeFontHighlightColorItem2); + this.richEditBarController1.BarItems.Add(this.changeTextCaseItem2); + this.richEditBarController1.BarItems.Add(this.makeTextUpperCaseItem2); + this.richEditBarController1.BarItems.Add(this.makeTextLowerCaseItem2); + this.richEditBarController1.BarItems.Add(this.capitalizeEachWordCaseItem2); + this.richEditBarController1.BarItems.Add(this.toggleTextCaseItem2); + this.richEditBarController1.BarItems.Add(this.clearFormattingItem2); + this.richEditBarController1.BarItems.Add(this.showFontFormItem2); + this.richEditBarController1.BarItems.Add(this.toggleBulletedListItem2); + this.richEditBarController1.BarItems.Add(this.toggleNumberingListItem2); + this.richEditBarController1.BarItems.Add(this.toggleMultiLevelListItem2); + this.richEditBarController1.BarItems.Add(this.decreaseIndentItem2); + this.richEditBarController1.BarItems.Add(this.increaseIndentItem2); + this.richEditBarController1.BarItems.Add(this.toggleParagraphAlignmentLeftItem2); + this.richEditBarController1.BarItems.Add(this.toggleParagraphAlignmentCenterItem2); + this.richEditBarController1.BarItems.Add(this.toggleParagraphAlignmentRightItem2); + this.richEditBarController1.BarItems.Add(this.toggleParagraphAlignmentJustifyItem2); + this.richEditBarController1.BarItems.Add(this.toggleShowWhitespaceItem2); + this.richEditBarController1.BarItems.Add(this.changeParagraphLineSpacingItem2); + this.richEditBarController1.BarItems.Add(this.setSingleParagraphSpacingItem2); + this.richEditBarController1.BarItems.Add(this.setSesquialteralParagraphSpacingItem2); + this.richEditBarController1.BarItems.Add(this.setDoubleParagraphSpacingItem2); + this.richEditBarController1.BarItems.Add(this.showLineSpacingFormItem2); + this.richEditBarController1.BarItems.Add(this.addSpacingBeforeParagraphItem2); + this.richEditBarController1.BarItems.Add(this.removeSpacingBeforeParagraphItem2); + this.richEditBarController1.BarItems.Add(this.addSpacingAfterParagraphItem2); + this.richEditBarController1.BarItems.Add(this.removeSpacingAfterParagraphItem2); + this.richEditBarController1.BarItems.Add(this.changeParagraphBackColorItem2); + this.richEditBarController1.BarItems.Add(this.showParagraphFormItem2); + this.richEditBarController1.BarItems.Add(this.changeStyleItem1); + this.richEditBarController1.BarItems.Add(this.showEditStyleFormItem2); + this.richEditBarController1.BarItems.Add(this.findItem2); + this.richEditBarController1.BarItems.Add(this.replaceItem2); + this.richEditBarController1.Control = this.richEditControl1; + // + // clipboardBar2 + // + this.clipboardBar2.BarName = ""; + this.clipboardBar2.Control = this.richEditControl1; + this.clipboardBar2.DockCol = 0; + this.clipboardBar2.DockRow = 0; + this.clipboardBar2.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.clipboardBar2.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.pasteItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "V", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.cutItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "X", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.copyItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "C", ""), + new DevExpress.XtraBars.LinkPersistInfo(this.pasteSpecialItem2)}); + this.clipboardBar2.Text = ""; + // + // paragraphBar2 + // + this.paragraphBar2.BarName = ""; + this.paragraphBar2.Control = this.richEditControl1; + this.paragraphBar2.DockCol = 3; + this.paragraphBar2.DockRow = 0; + this.paragraphBar2.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.paragraphBar2.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.toggleBulletedListItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "U", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.toggleNumberingListItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "N", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.toggleMultiLevelListItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "M", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.decreaseIndentItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "AO", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.increaseIndentItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "AI", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.toggleParagraphAlignmentLeftItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "AL", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.toggleParagraphAlignmentCenterItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "AC", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.toggleParagraphAlignmentRightItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "AR", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.toggleParagraphAlignmentJustifyItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "AJ", ""), + new DevExpress.XtraBars.LinkPersistInfo(this.toggleShowWhitespaceItem2), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.changeParagraphLineSpacingItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "K", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.changeParagraphBackColorItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "H", ""), + new DevExpress.XtraBars.LinkPersistInfo(this.showParagraphFormItem2)}); + this.paragraphBar2.Text = ""; + // + // stylesBar2 + // + this.stylesBar2.BarName = ""; + this.stylesBar2.Control = this.richEditControl1; + this.stylesBar2.DockCol = 2; + this.stylesBar2.DockRow = 0; + this.stylesBar2.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.stylesBar2.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.changeStyleItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.showEditStyleFormItem2)}); + this.stylesBar2.Text = ""; + // + // editingBar2 + // + this.editingBar2.BarName = ""; + this.editingBar2.Control = this.richEditControl1; + this.editingBar2.DockCol = 4; + this.editingBar2.DockRow = 0; + this.editingBar2.DockStyle = DevExpress.XtraBars.BarDockStyle.Top; + this.editingBar2.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.findItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "FD", ""), + new DevExpress.XtraBars.LinkPersistInfo(DevExpress.XtraBars.BarLinkUserDefines.KeyTip, this.replaceItem2, "", false, true, true, 0, null, DevExpress.XtraBars.BarItemPaintStyle.Standard, "R", "")}); + this.editingBar2.Text = ""; + // + // EditTextForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(739, 509); + this.Controls.Add(this.panel1); + this.Controls.Add(this.barDockControl4); + this.Controls.Add(this.barDockControlLeft); + this.Controls.Add(this.barDockControlRight); + this.Controls.Add(this.barDockControlBottom); + this.Controls.Add(this.barDockControlTop); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditTextForm"; + this.Text = "EditTextForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.EditTextForm_FormClosing); + this.Load += new System.EventHandler(this.EditTextForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemFontEdit2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemRichEditFontSizeEdit2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemRichEditStyleEdit2)).EndInit(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.barManager1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemFontEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemRichEditFontSizeEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemColorEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemRichEditStyleEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.richEditBarController1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private DevExpress.XtraRichEdit.UI.ClipboardBar clipboardBar1; + private DevExpress.XtraRichEdit.UI.ParagraphBar paragraphBar1; + private DevExpress.XtraRichEdit.UI.StylesBar stylesBar1; + private DevExpress.XtraRichEdit.UI.EditingBar editingBar1; + private DevExpress.XtraRichEdit.UI.CommonBar commonBar1; + private DevExpress.XtraRichEdit.UI.FileInfoBar fileInfoBar1; + private DevExpress.XtraRichEdit.UI.FontBar fontBar2; + private DevExpress.XtraRichEdit.UI.CutItem cutItem1; + private DevExpress.XtraRichEdit.UI.CopyItem copyItem1; + private DevExpress.XtraRichEdit.UI.PasteSpecialItem pasteSpecialItem1; + private DevExpress.XtraRichEdit.UI.PasteItem pasteItem1; + private DevExpress.XtraRichEdit.UI.ChangeFontNameItem changeFontNameItem1; + private DevExpress.XtraRichEdit.UI.ChangeFontSizeItem changeFontSizeItem1; + private DevExpress.XtraRichEdit.UI.FontSizeIncreaseItem fontSizeIncreaseItem1; + private DevExpress.XtraRichEdit.UI.FontSizeDecreaseItem fontSizeDecreaseItem1; + private DevExpress.XtraRichEdit.UI.ToggleFontBoldItem toggleFontBoldItem2; + private DevExpress.XtraRichEdit.UI.ToggleFontItalicItem toggleFontItalicItem2; + private DevExpress.XtraRichEdit.UI.ToggleFontUnderlineItem toggleFontUnderlineItem2; + private DevExpress.XtraRichEdit.UI.ToggleFontDoubleUnderlineItem toggleFontDoubleUnderlineItem1; + private DevExpress.XtraRichEdit.UI.ToggleFontStrikeoutItem toggleFontStrikeoutItem1; + private DevExpress.XtraRichEdit.UI.ToggleFontDoubleStrikeoutItem toggleFontDoubleStrikeoutItem1; + private DevExpress.XtraRichEdit.UI.ToggleFontSuperscriptItem toggleFontSuperscriptItem1; + private DevExpress.XtraRichEdit.UI.ToggleFontSubscriptItem toggleFontSubscriptItem1; + private DevExpress.XtraRichEdit.UI.ChangeFontColorItem changeFontColorItem2; + private DevExpress.XtraRichEdit.UI.ChangeFontHighlightColorItem changeFontHighlightColorItem1; + private DevExpress.XtraRichEdit.UI.ChangeTextCaseItem changeTextCaseItem1; + private DevExpress.XtraRichEdit.UI.MakeTextUpperCaseItem makeTextUpperCaseItem1; + private DevExpress.XtraRichEdit.UI.MakeTextLowerCaseItem makeTextLowerCaseItem1; + private DevExpress.XtraRichEdit.UI.CapitalizeEachWordCaseItem capitalizeEachWordCaseItem1; + private DevExpress.XtraRichEdit.UI.ToggleTextCaseItem toggleTextCaseItem1; + private DevExpress.XtraRichEdit.UI.ClearFormattingItem clearFormattingItem1; + private DevExpress.XtraRichEdit.UI.ShowFontFormItem showFontFormItem1; + private DevExpress.XtraRichEdit.UI.ToggleBulletedListItem toggleBulletedListItem1; + private DevExpress.XtraRichEdit.UI.ToggleNumberingListItem toggleNumberingListItem1; + private DevExpress.XtraRichEdit.UI.ToggleMultiLevelListItem toggleMultiLevelListItem1; + private DevExpress.XtraRichEdit.UI.DecreaseIndentItem decreaseIndentItem1; + private DevExpress.XtraRichEdit.UI.IncreaseIndentItem increaseIndentItem1; + private DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentLeftItem toggleParagraphAlignmentLeftItem1; + private DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentCenterItem toggleParagraphAlignmentCenterItem1; + private DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentRightItem toggleParagraphAlignmentRightItem1; + private DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentJustifyItem toggleParagraphAlignmentJustifyItem1; + private DevExpress.XtraRichEdit.UI.ToggleShowWhitespaceItem toggleShowWhitespaceItem1; + private DevExpress.XtraRichEdit.UI.ChangeParagraphLineSpacingItem changeParagraphLineSpacingItem1; + private DevExpress.XtraRichEdit.UI.SetSingleParagraphSpacingItem setSingleParagraphSpacingItem1; + private DevExpress.XtraRichEdit.UI.SetSesquialteralParagraphSpacingItem setSesquialteralParagraphSpacingItem1; + private DevExpress.XtraRichEdit.UI.SetDoubleParagraphSpacingItem setDoubleParagraphSpacingItem1; + private DevExpress.XtraRichEdit.UI.ShowLineSpacingFormItem showLineSpacingFormItem1; + private DevExpress.XtraRichEdit.UI.AddSpacingBeforeParagraphItem addSpacingBeforeParagraphItem1; + private DevExpress.XtraRichEdit.UI.RemoveSpacingBeforeParagraphItem removeSpacingBeforeParagraphItem1; + private DevExpress.XtraRichEdit.UI.AddSpacingAfterParagraphItem addSpacingAfterParagraphItem1; + private DevExpress.XtraRichEdit.UI.RemoveSpacingAfterParagraphItem removeSpacingAfterParagraphItem1; + private DevExpress.XtraRichEdit.UI.ChangeParagraphBackColorItem changeParagraphBackColorItem1; + private DevExpress.XtraRichEdit.UI.ShowParagraphFormItem showParagraphFormItem1; + private DevExpress.XtraRichEdit.UI.ChangeStyleItem changeStyleItem2; + private DevExpress.XtraRichEdit.UI.ShowEditStyleFormItem showEditStyleFormItem1; + private DevExpress.XtraRichEdit.UI.FindItem findItem1; + private DevExpress.XtraRichEdit.UI.ReplaceItem replaceItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem4; + private DevExpress.XtraRichEdit.UI.ShowDocumentPropertiesFormItem showDocumentPropertiesFormItem1; + private DevExpress.XtraBars.BarDockControl barDockControl4; + private DevExpress.XtraRichEdit.RichEditControl richEditControl1; + private DevExpress.XtraBars.BarManager barManager1; + private DevExpress.XtraRichEdit.UI.FontBar fontBar1; + private DevExpress.XtraRichEdit.UI.ChangeFontNameItem changeFontNameItem2; + private DevExpress.XtraEditors.Repository.RepositoryItemFontEdit repositoryItemFontEdit1; + private DevExpress.XtraRichEdit.UI.ChangeFontSizeItem changeFontSizeItem2; + private DevExpress.XtraRichEdit.Design.RepositoryItemRichEditFontSizeEdit repositoryItemRichEditFontSizeEdit1; + private DevExpress.XtraRichEdit.UI.FontSizeIncreaseItem fontSizeIncreaseItem2; + private DevExpress.XtraRichEdit.UI.FontSizeDecreaseItem fontSizeDecreaseItem2; + private DevExpress.XtraRichEdit.UI.ToggleFontBoldItem toggleFontBoldItem1; + private DevExpress.XtraRichEdit.UI.ToggleFontItalicItem toggleFontItalicItem1; + private DevExpress.XtraRichEdit.UI.ToggleFontUnderlineItem toggleFontUnderlineItem1; + private DevExpress.XtraRichEdit.UI.ToggleFontStrikeoutItem toggleFontStrikeoutItem2; + private DevExpress.XtraRichEdit.UI.ChangeFontColorItem changeFontColorItem1; + private DevExpress.XtraRichEdit.UI.ChangeFontHighlightColorItem changeFontHighlightColorItem2; + private DevExpress.XtraRichEdit.UI.ClearFormattingItem clearFormattingItem2; + private DevExpress.XtraRichEdit.UI.ShowFontFormItem showFontFormItem2; + private DevExpress.XtraBars.BarEditItem barEditItem1; + private DevExpress.XtraEditors.Repository.RepositoryItemColorEdit repositoryItemColorEdit1; + private DevExpress.XtraBars.BarDockControl barDockControlTop; + private DevExpress.XtraBars.BarDockControl barDockControlBottom; + private DevExpress.XtraBars.BarDockControl barDockControlLeft; + private DevExpress.XtraBars.BarDockControl barDockControlRight; + private DevExpress.XtraRichEdit.UI.PasteItem pasteItem2; + private DevExpress.XtraRichEdit.UI.CutItem cutItem2; + private DevExpress.XtraRichEdit.UI.CopyItem copyItem2; + private DevExpress.XtraRichEdit.UI.PasteSpecialItem pasteSpecialItem2; + private DevExpress.XtraRichEdit.UI.ToggleFontDoubleUnderlineItem toggleFontDoubleUnderlineItem2; + private DevExpress.XtraRichEdit.UI.ToggleFontDoubleStrikeoutItem toggleFontDoubleStrikeoutItem2; + private DevExpress.XtraRichEdit.UI.ToggleFontSuperscriptItem toggleFontSuperscriptItem2; + private DevExpress.XtraRichEdit.UI.ToggleFontSubscriptItem toggleFontSubscriptItem2; + private DevExpress.XtraRichEdit.UI.ChangeTextCaseItem changeTextCaseItem2; + private DevExpress.XtraRichEdit.UI.MakeTextUpperCaseItem makeTextUpperCaseItem2; + private DevExpress.XtraRichEdit.UI.MakeTextLowerCaseItem makeTextLowerCaseItem2; + private DevExpress.XtraRichEdit.UI.CapitalizeEachWordCaseItem capitalizeEachWordCaseItem2; + private DevExpress.XtraRichEdit.UI.ToggleTextCaseItem toggleTextCaseItem2; + private DevExpress.XtraRichEdit.UI.ToggleBulletedListItem toggleBulletedListItem2; + private DevExpress.XtraRichEdit.UI.ToggleNumberingListItem toggleNumberingListItem2; + private DevExpress.XtraRichEdit.UI.ToggleMultiLevelListItem toggleMultiLevelListItem2; + private DevExpress.XtraRichEdit.UI.DecreaseIndentItem decreaseIndentItem2; + private DevExpress.XtraRichEdit.UI.IncreaseIndentItem increaseIndentItem2; + private DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentLeftItem toggleParagraphAlignmentLeftItem2; + private DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentCenterItem toggleParagraphAlignmentCenterItem2; + private DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentRightItem toggleParagraphAlignmentRightItem2; + private DevExpress.XtraRichEdit.UI.ToggleParagraphAlignmentJustifyItem toggleParagraphAlignmentJustifyItem2; + private DevExpress.XtraRichEdit.UI.ToggleShowWhitespaceItem toggleShowWhitespaceItem2; + private DevExpress.XtraRichEdit.UI.ChangeParagraphLineSpacingItem changeParagraphLineSpacingItem2; + private DevExpress.XtraRichEdit.UI.SetSingleParagraphSpacingItem setSingleParagraphSpacingItem2; + private DevExpress.XtraRichEdit.UI.SetSesquialteralParagraphSpacingItem setSesquialteralParagraphSpacingItem2; + private DevExpress.XtraRichEdit.UI.SetDoubleParagraphSpacingItem setDoubleParagraphSpacingItem2; + private DevExpress.XtraRichEdit.UI.ShowLineSpacingFormItem showLineSpacingFormItem2; + private DevExpress.XtraRichEdit.UI.AddSpacingBeforeParagraphItem addSpacingBeforeParagraphItem2; + private DevExpress.XtraRichEdit.UI.RemoveSpacingBeforeParagraphItem removeSpacingBeforeParagraphItem2; + private DevExpress.XtraRichEdit.UI.AddSpacingAfterParagraphItem addSpacingAfterParagraphItem2; + private DevExpress.XtraRichEdit.UI.RemoveSpacingAfterParagraphItem removeSpacingAfterParagraphItem2; + private DevExpress.XtraRichEdit.UI.ChangeParagraphBackColorItem changeParagraphBackColorItem2; + private DevExpress.XtraRichEdit.UI.ShowParagraphFormItem showParagraphFormItem2; + private DevExpress.XtraRichEdit.UI.ChangeStyleItem changeStyleItem1; + private DevExpress.XtraRichEdit.Design.RepositoryItemRichEditStyleEdit repositoryItemRichEditStyleEdit1; + private DevExpress.XtraRichEdit.UI.ShowEditStyleFormItem showEditStyleFormItem2; + private DevExpress.XtraRichEdit.UI.FindItem findItem2; + private DevExpress.XtraRichEdit.UI.ReplaceItem replaceItem2; + private DevExpress.XtraRichEdit.UI.RichEditBarController richEditBarController1; + private DevExpress.XtraRichEdit.UI.ClipboardBar clipboardBar2; + private DevExpress.XtraRichEdit.UI.ParagraphBar paragraphBar2; + private DevExpress.XtraRichEdit.UI.StylesBar stylesBar2; + private DevExpress.XtraRichEdit.UI.EditingBar editingBar2; + private DevExpress.XtraEditors.Repository.RepositoryItemFontEdit repositoryItemFontEdit2; + private DevExpress.XtraRichEdit.Design.RepositoryItemRichEditFontSizeEdit repositoryItemRichEditFontSizeEdit2; + private DevExpress.XtraRichEdit.Design.RepositoryItemRichEditStyleEdit repositoryItemRichEditStyleEdit2; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label9; + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/EditTextForm.cs b/应用/TBAppraisalTools/Forms/EditTextForm.cs new file mode 100644 index 0000000..4d3f272 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/EditTextForm.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using TBAppraisalTools.Properties; +using DevExpress.XtraRichEdit.UI; +using DevExpress.XtraRichEdit.API.Native; +using UI.Framework.Forms; +using DevExpress.XtraBars; +using System.Text.RegularExpressions; + +namespace TBAppraisalTools.Forms +{ + public partial class EditTextForm : BaseForm + { + public TbConfig tbConfig; + + string fontName = "宋体";//字体名称 + float fontSize = 12f;//字体大小 + bool fontBold = false;//字体加粗/正常 + bool fontItalic = false;//字体斜体/正常 + bool fontUnderline = false;//字体下划线/正常 + bool fontStrikeout = false;//字体删除线/正常 + Color fontColor = Color.Black; + + public EditTextForm(TbConfig tbConfig = null) + { + InitializeComponent(); + this.Text = tbConfig == null ? Resources.AddTextTitle : Resources.EditTextTitle; + this.tbConfig = tbConfig; + } + + private void EditTextForm_Load(object sender, EventArgs e) + { + if (tbConfig != null) + { + richEditControl1.Document.Text = tbConfig.T_Text; + changeFontNameItem2.EditValue = fontName = tbConfig.T_Font.Name; + changeFontSizeItem2.EditValue = fontSize = tbConfig.T_Font.Size; + barEditItem1.EditValue = fontColor = tbConfig.T_ForeColor; + fontBold = tbConfig.T_Font.Bold; + fontItalic = tbConfig.T_Font.Italic; + fontUnderline = tbConfig.T_Font.Underline; + fontStrikeout = tbConfig.T_Font.Strikeout; + } + } + + /// + /// 样式有变化时. + /// + private void Changed() + { + try + { + var doc = richEditControl1.Document; + doc.BeginUpdate(); + var cp = doc.BeginUpdateCharacters(0, doc.Text.Length); + cp.FontName = fontName; + cp.FontSize = fontSize; + cp.Bold = fontBold; + cp.Italic = fontItalic; + cp.Underline = fontUnderline ? UnderlineType.Single : UnderlineType.None; + cp.Strikeout = fontStrikeout ? StrikeoutType.Single : StrikeoutType.None; + cp.ForeColor = fontColor; + doc.EndUpdateCharacters(cp); + doc.EndUpdate(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 窗体关闭 + /// + /// + /// + private void EditTextForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(richEditControl1.Document.Text)) throw new Exception("内容不能为空"); + if (MessageBox.Show("是否保存?", "温馨提示", MessageBoxButtons.OKCancel) == DialogResult.OK) + { + if (tbConfig == null) + { + tbConfig = new TbConfig() + { + T_Font = new Font(fontName, fontSize, (fontBold ? FontStyle.Bold : FontStyle.Regular) | (fontItalic ? FontStyle.Italic : FontStyle.Regular) | (fontUnderline ? FontStyle.Underline : FontStyle.Regular) | (fontStrikeout ? FontStyle.Strikeout : FontStyle.Regular)), + T_ForeColor = fontColor, + T_Text = richEditControl1.Document.Text + }; + } + else + { + tbConfig.T_Text = richEditControl1.Document.Text; + tbConfig.T_ForeColor = fontColor; + tbConfig.T_Font = new Font(fontName, fontSize, (fontBold ? FontStyle.Bold : FontStyle.Regular) | (fontItalic ? FontStyle.Italic : FontStyle.Regular) | (fontUnderline ? FontStyle.Underline : FontStyle.Regular) | (fontStrikeout ? FontStyle.Strikeout : FontStyle.Regular)); + } + this.DialogResult = DialogResult.OK; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 字体名字 + /// + /// + /// + private void changeFontNameItem2_EditValueChanged(object sender, EventArgs e) + { + if (changeFontNameItem2.EditValue != null) + { + fontName = changeFontNameItem2.EditValue.ToString(); + Changed(); + } + } + + /// + /// 字体大小 + /// + /// + /// + private void changeFontSizeItem2_EditValueChanged(object sender, EventArgs e) + { + if (changeFontSizeItem2.EditValue != null) + { + fontSize = float.Parse(changeFontSizeItem2.EditValue.ToString()); + Changed(); + } + } + + /// + /// 字体颜色 + /// + /// + /// + private void barEditItem1_EditValueChanged(object sender, EventArgs e) + { + if (barEditItem1.EditValue != null) + { + var barEditItem = barEditItem1.EditValue; + if (barEditItem != null) + { + var fontColorStr = barEditItem1.EditValue.ToString(); + var reg = Regex.Match(fontColorStr, @"Color \[A=(?\d+?), R=(?\d+?), G=(?\d+?), B=(?\d+?)\]"); + if (reg.Success) + { + fontColor = Color.FromArgb(int.Parse(reg.Groups["A"].Value), int.Parse(reg.Groups["R"].Value), int.Parse(reg.Groups["G"].Value), int.Parse(reg.Groups["B"].Value)); + richEditControl1.Document.DefaultCharacterProperties.ForeColor = fontColor; + Changed(); + } + } + } + } + + /// + /// 字体粗体/正常 + /// + /// + /// + private void toggleFontBoldItem1_ItemClick(object sender, ItemClickEventArgs e) + { + var toggleFontBoldItem = e.Item as ToggleFontBoldItem; + fontBold = toggleFontBoldItem.Checked; + Changed(); + } + + /// + /// 文字斜体/正常 + /// + /// + /// + private void toggleFontItalicItem1_ItemClick(object sender, ItemClickEventArgs e) + { + var toggleFontItalicItem = e.Item as ToggleFontItalicItem; + fontItalic = toggleFontItalicItem.Checked; + Changed(); + } + + /// + /// 文字下划线/正常 + /// + /// + /// + private void toggleFontUnderlineItem1_ItemClick(object sender, ItemClickEventArgs e) + { + var toggleFontUnderlineItem = e.Item as ToggleFontUnderlineItem; + fontUnderline = toggleFontUnderlineItem.Checked; + Changed(); + } + + /// + /// 文字删除线/正常 + /// + /// + /// + private void toggleFontStrikeoutItem2_ItemClick(object sender, ItemClickEventArgs e) + { + var toggleFontStrikeoutItem = e.Item as ToggleFontStrikeoutItem; + fontStrikeout = toggleFontStrikeoutItem.Checked; + Changed(); + } + + private void label_Click(object sender, EventArgs e) + { + try + { + if (sender.GetType() == typeof(Label)) + { + var label = sender as Label; + richEditControl1.Text += label.Text; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/EditTextForm.resx b/应用/TBAppraisalTools/Forms/EditTextForm.resx new file mode 100644 index 0000000..c7266c1 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/EditTextForm.resx @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAU2F2ZTv56PkJAAAJQElEQVRYR8WWd1TUVxbH3ZItycYkpm39d/+Ku1FRikjvvQ0ww9AZGJgBBhh6 + GRh6R6RIQEWxIGKkKKLYgsEaY8EuKEWRCCrShKjnu/f9hiEhuMecPSdn3zkfHo+Zw/d77yv3LgHwf+Wn + 41fEr/9HfvMzUH+X6Swa7IO3iN8Tf/wJb7+Bd34m7Lvs/zMzC0ywxVth6Vsy5Hk7X0YX1COmcDfiiuvB + F6fD1iMGtoIYeIhSkV+2G7ml9cgu2YHMou1QFmxDal4tUrI3IzGjBnHKKsQoNiIqqQwWjsFw8pbD0UsO + B49I2PFlL614kh2kxUywgOcHW/whInfHbNPxK2g50Y3mzm60dV2Hpp4HjCw8YeMcDM8gJZ5NzWKMeDqp + 4snEDB6Pz2B0/DlGnql4NDaN755Mw8w+EFV1+1FZ24ryTc3YUNMEW7fwl6TFssGyMD/Y4u3w7Do0HbuM + 3E3tyN7cjpK6o3MGhLBxCoYwMJUTvNr/BN19j3Hl3mNcvjuKS70jWKllTlhipTZB8/2RCRjbiiCNKYE4 + qhCBEXlIpixZu4ayk/funOb8YIt3wtK3ofHIRWRVtxEHULytA2v0BDA0F8LaSQx+QAoX3cWeEXzb8wgX + 7jzCN7e/w/lbw1ilY40Vmk4k7gx72q67Q89gaOWHkLgiBEXlQRSRi/jMarWBpcRvmbB6MAN/kio3o+Hw + BaRXtSKjaj8Kt3Zg9To+DOYMuPkm48HoJM7dHMbZG8M4c/0hTl8bwqmrQ9DQtYPGWh4ZdoetezRuDTyB + noUPQmKKERhJBsJzEZteBSsXKTPwHrHYgERRg11t55BW0QJlZQsKtrRjtS4ZMPOAlWMgeN6J6BseR1f3 + A3zdfR+dlwfx1aVBnLg4QMJO0DH0wFpjL4oyCldpW3TNvBAsL6LocxAQloXo1ApYOEuYgfeJRQbeDUmu + Rt3+M1CUfYnUsn3I33yQInOHPhmwdBDB2TMed+4/xYlv+3H8Qj+OEh3n+9Bx7h60DHjQN/eFkbUIFrwI + XLj5EDrGHhDLC+AXng2f0GxEppTDnG4Gab3WwNKghErUNnUhqaQRyaV7kVPTSml1g56pABb2IrpKsbh2 + bwQdZ+/iENF+phcHT/ei7VQPtA3dYeEig7mzDGZO4ThNGdIy5NMBzIdfaCa8JZmQJW6AmaOYGfiAWGCA + LZYGxJZj095OJNIbkFjcgKyqFjpcrlhnwoe5XQDd42hcuj2MA109OPD1HbQyTt5GC9HceQunrgyi6/IA + Tl4aQOfFfmjqu3H77yXNhFdIOsLii2FCV5O0ls1pzg+2eM9PXoKN9ccRm7cT8fm7kFnZBEuXMKzQdsEK + LRfomfnAyCoABlb+0Lfwha65N3RNvbDWRAhtSre2oQCaFPUafXc6E67cNQyg/fckcaFYSQeyEEY2IrUB + 9urOD2bgfS9ZIcq2d0CevR3ynO1QlDZAWd6I9LK9UDI2NNLM1o1I27AHSvo8taQBEakbIYkpQkh0IcQM + 2vcgunYiWQ586fAJg9LApzckKDKfM09aHxKLDXhI87B+y0FEZNSqyKxF1BxyNmcxts7/Ls/cgghlDXwo + Qh9JOrxpZtF6BjOU8BCnQcDERQrw/RV0E3JgYOnHDHxELDLwgXtwFgqqWxGetglhCoJm9ruMzUqa1aTV + ENX0txoE0CsnnBNkaWbRenARkygJuwcQ/slw80uGb2gWvQ2+PzYwX5CYgWUugenIrmiCJLEKkuQvIEn5 + AlI2J1dBmkJ/I9gcmrJRtU6sIDElBEyMUsxEBSzaOWEmyvNLAs83CS4+CXQQldzbQFofEwsMsMUyJ98U + KNfvQVBsBYISyiGOL4cX3V8PikxAEQrYzKWVxIIU9I8T4OgZTdeTVbsoeoIjYc9nVS8CNm4ymiPB80nk + xJ284rnM6Bh7MgOfzGkuMPChnWciFIU7ESDfwCGSr+eimn3xEjOzKp4T07MvMDXzEhPTsxinysgq5DOq + jGOTM3hKVfExg6qihZOUhOPIZCwcBLHcOdA2EqoN/I5YaMCaH4O4nG3wlRURxfCjmaWPCU8+f0F8/4Mo + K8VUhpnQ6BhjGiPEo6dTXCkefjJJ5TiYe7zs+bHcG+JK2dA04DMDnxKLDHxkSW94NBUkoSSfUp8HT2k+ + nH3iuagnSLz52C18eeQm9hy+hk2NF1C56zxK686guPYU8qtPIrvyBNJLj5L4FIYfT8LYJpATtnWX05bI + 4SyMp+Lmxgz8mZg3wH4wAx+bOYcjnA6cICibOiEVDsJoTM+8wPj095RqBjUiE7PzaVZFrY6cCROjUxgi + AwaW/rChoGx4UbB2ofNB26CxzvW/GzCyl1L9LodrQAbcROk0UzvmHokpin6cxHe3X8PO/VdQVf8NSref + RQmLvEYd+TEoig8jsaCdEx+isr2OXk4mbE31wcJJRt1QNFbquDADfyEWGfhEz1qMwKj1cPZN43DxVcCK + F8alf4y1YCxy6ojYnrPIR7jIWfulivwhg4SHRibxgNCm0syEGeaO4bDmRWKFjtNrDbDFp7oWgfAPK6BT + mwwHhjAJ5nSSWfRjJP50fBajXNp/6Ps4ceIhRc2Jj05w4qwl09IXwMwhnAiDqX0Y9QIR+FyLM/BXgjWm + Cw1om/rRi5ZNBycedgIVJnZiVHT2I+dQDzLa7iCx+Qbi991AzN7riG68jsiG65DVX0PYzquQ7LiK4Lpu + BG3rRuDWbjpw7lT9QmFqFwoTWynMyci/1zgyA38jFhvQNPamlyydTmwsrN1iOAypwdh45hEKTgwh88gD + pB0aRMrBASQdGED8/n7EtvQhuqkPkfvuQdZ4F+GEtKEXkt091KDy6CZIYETiRjSbkpnlaxxea4C7hmsM + PF+5+adSCZbDyjkKloQedTllXcPIPaYSV7QPIrltEAlkIK6lH9HNfYgi8Yi9KvHQPb2cgZD6Xq5JZcJq + jG0l+Gy1/QvSWvAOsB9cR7Rc06FolR7/lQY1oiupFWNo0j56FnbBNesrOKYdhW1yB6wTDsEi9iBM5Adg + GNGKdaFN0JHsg6a4EatFe7DKfzc+99mF5RoO+EzDnmO5ilf//JdJPmmpWzLOABvsF+aItcvsmWSHhKXp + Tfz9DfzjR7A1u/9MfD796sEW6kyw7WBf+CVgQaojX2BAPdQf/NLMjSVL/gMGC1sK0EICNQAAAABJRU5E + rkJggg== + + + + 240, 17 + + \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/MainForm.Designer.cs b/应用/TBAppraisalTools/Forms/MainForm.Designer.cs new file mode 100644 index 0000000..1668792 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/MainForm.Designer.cs @@ -0,0 +1,371 @@ +namespace TBAppraisalTools.Forms +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.myPanel = new TBAppraisalTools.重绘.MyPanel(); + this.menuStrip_Add = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加图片ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.增加文字ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改底图ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.myPictureBox2 = new TBAppraisalTools.重绘.MyPictureBox(); + this.myPictureBox1 = new TBAppraisalTools.重绘.MyPictureBox(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.menuStrip_Photo = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改选中图片ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中图片ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.menuStrip_Text = new System.Windows.Forms.ContextMenuStrip(this.components); + this.修改选中文本ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中控件ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.myPanel.SuspendLayout(); + this.menuStrip_Add.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.myPictureBox2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.myPictureBox1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.menuStrip_Photo.SuspendLayout(); + this.menuStrip_Text.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(680, 624); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.AutoScroll = true; + this.xtraTabPage1.Controls.Add(this.button2); + this.xtraTabPage1.Controls.Add(this.button1); + this.xtraTabPage1.Controls.Add(this.myPanel); + this.xtraTabPage1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("xtraTabPage1.ImageOptions.Image"))); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(674, 577); + this.xtraTabPage1.Text = " 优 惠 券 模 板 "; + // + // button2 + // + this.button2.Enabled = false; + this.button2.Location = new System.Drawing.Point(491, 517); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(149, 38); + this.button2.TabIndex = 2; + this.button2.Text = "登录淘宝"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Visible = false; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(491, 94); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(149, 117); + this.button1.TabIndex = 1; + this.button1.Text = "保存模板"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // myPanel + // + this.myPanel.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("myPanel.BackgroundImage"))); + this.myPanel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.myPanel.ContextMenuStrip = this.menuStrip_Add; + this.myPanel.Controls.Add(this.label7); + this.myPanel.Controls.Add(this.label6); + this.myPanel.Controls.Add(this.label5); + this.myPanel.Controls.Add(this.label4); + this.myPanel.Controls.Add(this.label3); + this.myPanel.Controls.Add(this.label2); + this.myPanel.Controls.Add(this.label1); + this.myPanel.Controls.Add(this.myPictureBox2); + this.myPanel.Controls.Add(this.myPictureBox1); + this.myPanel.Location = new System.Drawing.Point(11, 12); + this.myPanel.Name = "myPanel"; + this.myPanel.Size = new System.Drawing.Size(387, 555); + this.myPanel.TabIndex = 0; + this.myPanel.Tag = "#底图"; + this.myPanel.MouseEnter += new System.EventHandler(this.MouseEnter); + // + // menuStrip_Add + // + this.menuStrip_Add.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加图片ToolStripMenuItem, + this.增加文字ToolStripMenuItem, + this.修改底图ToolStripMenuItem}); + this.menuStrip_Add.Name = "menuStrip_Photo"; + this.menuStrip_Add.Size = new System.Drawing.Size(125, 70); + // + // 增加图片ToolStripMenuItem + // + this.增加图片ToolStripMenuItem.Name = "增加图片ToolStripMenuItem"; + this.增加图片ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.增加图片ToolStripMenuItem.Text = "增加图片"; + this.增加图片ToolStripMenuItem.Click += new System.EventHandler(this.增加图片ToolStripMenuItem_Click); + // + // 增加文字ToolStripMenuItem + // + this.增加文字ToolStripMenuItem.Name = "增加文字ToolStripMenuItem"; + this.增加文字ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.增加文字ToolStripMenuItem.Text = "增加文字"; + this.增加文字ToolStripMenuItem.Click += new System.EventHandler(this.增加文字ToolStripMenuItem_Click); + // + // 修改底图ToolStripMenuItem + // + this.修改底图ToolStripMenuItem.Name = "修改底图ToolStripMenuItem"; + this.修改底图ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.修改底图ToolStripMenuItem.Text = "修改底图"; + this.修改底图ToolStripMenuItem.Click += new System.EventHandler(this.修改底图ToolStripMenuItem_Click); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(248, 412); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(64, 14); + this.label7.TabIndex = 8; + this.label7.Tag = ""; + this.label7.Text = "#券后特价"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(220, 384); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(64, 14); + this.label6.TabIndex = 7; + this.label6.Tag = ""; + this.label6.Text = "#商品现价"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(248, 356); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(64, 14); + this.label5.TabIndex = 6; + this.label5.Tag = ""; + this.label5.Text = "#月销售量"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(156, 306); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(64, 14); + this.label4.TabIndex = 5; + this.label4.Tag = ""; + this.label4.Text = "#商品标题"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(80, 251); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(133, 14); + this.label3.TabIndex = 4; + this.label3.Tag = ""; + this.label3.Text = "#开始时间 - #结束时间"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(136, 199); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(64, 14); + this.label2.TabIndex = 3; + this.label2.Tag = ""; + this.label2.Text = "#优惠券价"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(166, 141); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(64, 14); + this.label1.TabIndex = 2; + this.label1.Tag = ""; + this.label1.Text = "#店铺名称"; + // + // myPictureBox2 + // + this.myPictureBox2.Location = new System.Drawing.Point(13, 316); + this.myPictureBox2.Name = "myPictureBox2"; + this.myPictureBox2.Size = new System.Drawing.Size(121, 148); + this.myPictureBox2.TabIndex = 1; + this.myPictureBox2.TabStop = false; + this.myPictureBox2.Tag = "#商品主图"; + // + // myPictureBox1 + // + this.myPictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.myPictureBox1.Location = new System.Drawing.Point(159, 55); + this.myPictureBox1.Name = "myPictureBox1"; + this.myPictureBox1.Size = new System.Drawing.Size(80, 80); + this.myPictureBox1.TabIndex = 0; + this.myPictureBox1.TabStop = false; + this.myPictureBox1.Tag = "#店铺头像"; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("xtraTabPage2.ImageOptions.Image"))); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(674, 577); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(674, 577); + this.settingControl1.TabIndex = 0; + // + // menuStrip_Photo + // + this.menuStrip_Photo.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改选中图片ToolStripMenuItem, + this.删除选中图片ToolStripMenuItem}); + this.menuStrip_Photo.Name = "menuStrip_Photo"; + this.menuStrip_Photo.Size = new System.Drawing.Size(149, 48); + // + // 修改选中图片ToolStripMenuItem + // + this.修改选中图片ToolStripMenuItem.Name = "修改选中图片ToolStripMenuItem"; + this.修改选中图片ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.修改选中图片ToolStripMenuItem.Text = "修改选中图片"; + this.修改选中图片ToolStripMenuItem.Click += new System.EventHandler(this.修改选中图片ToolStripMenuItem_Click); + // + // 删除选中图片ToolStripMenuItem + // + this.删除选中图片ToolStripMenuItem.Name = "删除选中图片ToolStripMenuItem"; + this.删除选中图片ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除选中图片ToolStripMenuItem.Text = "删除选中图片"; + this.删除选中图片ToolStripMenuItem.Click += new System.EventHandler(this.删除选中图片ToolStripMenuItem_Click); + // + // menuStrip_Text + // + this.menuStrip_Text.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.修改选中文本ToolStripMenuItem, + this.删除选中控件ToolStripMenuItem}); + this.menuStrip_Text.Name = "menuStrip_Photo"; + this.menuStrip_Text.Size = new System.Drawing.Size(149, 48); + // + // 修改选中文本ToolStripMenuItem + // + this.修改选中文本ToolStripMenuItem.Name = "修改选中文本ToolStripMenuItem"; + this.修改选中文本ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.修改选中文本ToolStripMenuItem.Text = "修改选中文本"; + this.修改选中文本ToolStripMenuItem.Click += new System.EventHandler(this.修改选中文本ToolStripMenuItem_Click); + // + // 删除选中控件ToolStripMenuItem + // + this.删除选中控件ToolStripMenuItem.Name = "删除选中控件ToolStripMenuItem"; + this.删除选中控件ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除选中控件ToolStripMenuItem.Text = "删除选中控件"; + this.删除选中控件ToolStripMenuItem.Click += new System.EventHandler(this.删除选中控件ToolStripMenuItem_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(680, 624); + this.Controls.Add(this.xtraTabControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.myPanel.ResumeLayout(false); + this.myPanel.PerformLayout(); + this.menuStrip_Add.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.myPictureBox2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.myPictureBox1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.menuStrip_Photo.ResumeLayout(false); + this.menuStrip_Text.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private 重绘.MyPanel myPanel; + private 重绘.MyPictureBox myPictureBox1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private 重绘.MyPictureBox myPictureBox2; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.ContextMenuStrip menuStrip_Photo; + private System.Windows.Forms.ContextMenuStrip menuStrip_Text; + private System.Windows.Forms.ContextMenuStrip menuStrip_Add; + private System.Windows.Forms.ToolStripMenuItem 修改选中图片ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中图片ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改选中文本ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中控件ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 增加图片ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 增加文字ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改底图ToolStripMenuItem; + private UI.Framework.Controls.SettingControl settingControl1; + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/MainForm.cs b/应用/TBAppraisalTools/Forms/MainForm.cs new file mode 100644 index 0000000..723fd58 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/MainForm.cs @@ -0,0 +1,450 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using TBAppraisalTools.Properties; +using TBAppraisalTools.重绘; +using System.IO; +using Api.Framework.Tools; +using Newtonsoft.Json; +using CsharpHttpHelper; +using System.Text.RegularExpressions; +using UI.Framework.Tools; +using static TBAppraisalTools.Enums; +using Newtonsoft.Json.Linq; + +namespace TBAppraisalTools.Forms +{ + public partial class MainForm : BaseForm + { + //拾取框对象 + private PickBox pickBox = new PickBox(); + + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + /// + /// 关闭窗口 + /// + internal void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate () + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + + } + } + + /// + /// 窗体加载 + /// + /// + /// + private void MainForm_Load(object sender, EventArgs e) + { + try + { + settingControl1.Bind(Class1.Config); + TemplateLoad(); + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + //优惠券设计样板加载 + private void TemplateLoad() + { + myPanel.Controls.Clear(); + try + { + if (!File.Exists(TbTools.TBCONFIGJSON)) + { + File.WriteAllText(TbTools.TBCONFIGJSON, "{\"panel1\":{\"C_Name\":\"panel1\",\"C_Point\":\"11, 12\",\"C_Size\":\"387, 555\",\"C_Tag\":{\"ImagePath\":\"D:\\\\1\\\\2\\\\3\\\\File\\\\评价工具缓存\\\\优惠券背景.png\",\"Shape\":true,\"Varible\":\"#背景\"},\"T_Text\":null,\"T_Font\":null,\"T_ForeColor\":\"\"},\"picbox2\":{\"C_Name\":\"picbox0\",\"C_Point\":\"13, 316\",\"C_Size\":\"121, 148\",\"C_Tag\":{\"ImagePath\":\"D:\\\\1\\\\2\\\\3\\\\File\\\\评价工具缓存\\\\商品主图.png\",\"Shape\":true,\"Varible\":\"#商品主图\"},\"T_Text\":null,\"T_Font\":null,\"T_ForeColor\":\"\"},\"picbox3\":{\"C_Name\":\"picbox1\",\"C_Point\":\"159, 55\",\"C_Size\":\"80, 80\",\"C_Tag\":{\"ImagePath\":\"D:\\\\1\\\\2\\\\3\\\\File\\\\评价工具缓存\\\\店铺头像.png\",\"Shape\":false,\"Varible\":\"#店铺头像\"},\"T_Text\":null,\"T_Font\":null,\"T_ForeColor\":\"\"},\"label4\":{\"C_Name\":\"label0\",\"C_Point\":\"248, 412\",\"C_Size\":\"62, 15\",\"C_Tag\":\"\",\"T_Text\":\"#券后特价\",\"T_Font\":\"Microsoft Sans Serif, 9pt\",\"T_ForeColor\":\"64, 64, 64\"},\"label5\":{\"C_Name\":\"label1\",\"C_Point\":\"220, 384\",\"C_Size\":\"62, 15\",\"C_Tag\":\"\",\"T_Text\":\"#商品现价\",\"T_Font\":\"Microsoft Sans Serif, 9pt\",\"T_ForeColor\":\"64, 64, 64\"},\"label6\":{\"C_Name\":\"label2\",\"C_Point\":\"248, 356\",\"C_Size\":\"62, 15\",\"C_Tag\":\"\",\"T_Text\":\"#月销售量\",\"T_Font\":\"Microsoft Sans Serif, 9pt\",\"T_ForeColor\":\"64, 64, 64\"},\"label7\":{\"C_Name\":\"label3\",\"C_Point\":\"156, 306\",\"C_Size\":\"62, 15\",\"C_Tag\":\"\",\"T_Text\":\"#商品标题\",\"T_Font\":\"Microsoft Sans Serif, 9pt\",\"T_ForeColor\":\"64, 64, 64\"},\"label8\":{\"C_Name\":\"label4\",\"C_Point\":\"80, 251\",\"C_Size\":\"127, 15\",\"C_Tag\":\"\",\"T_Text\":\"#开始时间 - #结束时间\",\"T_Font\":\"Microsoft Sans Serif, 9pt\",\"T_ForeColor\":\"64, 64, 64\"},\"label9\":{\"C_Name\":\"label5\",\"C_Point\":\"136, 199\",\"C_Size\":\"62, 15\",\"C_Tag\":\"\",\"T_Text\":\"#优惠券价\",\"T_Font\":\"Microsoft Sans Serif, 9pt\",\"T_ForeColor\":\"64, 64, 64\"},\"label10\":{\"C_Name\":\"label6\",\"C_Point\":\"166, 141\",\"C_Size\":\"62, 15\",\"C_Tag\":\"\",\"T_Text\":\"#店铺名称\",\"T_Font\":\"Microsoft Sans Serif, 9pt\",\"T_ForeColor\":\"64, 64, 64\"}}"); + } + + if (File.Exists(TbTools.TBCONFIGJSON))//存在优惠券模板的情况 + { + var objDic = JsonConvert.DeserializeObject>(File.ReadAllText(TbTools.TBCONFIGJSON)); + if (objDic != null) + { + var panel = objDic.FirstOrDefault(f => f.Key.Contains("panel")); + if (!default(KeyValuePair).Equals(panel)) + { + TbConfig tbConfig = objDic[panel.Key] as TbConfig; + if (!File.Exists(TbTools.BACKICO)) + { + using (var bitmap = Resources.背景) + { + bitmap.Save(TbTools.BACKICO); + } + } + if (!File.Exists(TbTools.ITEMICO)) + { + using (var bitmap = Resources.商品主图) + { + bitmap.Save(TbTools.ITEMICO); + } + } + if (!File.Exists(TbTools.SHOPICO)) + { + using (var bitmap = Resources.店铺头像) + { + bitmap.Save(TbTools.SHOPICO); + } + } + + myPanel.Name = "panel1"; + myPanel.Location = tbConfig.C_Point; + myPanel.Size = tbConfig.C_Size; + myPanel.TabIndex = 1; + myPanel.BackgroundImage = Tools.ReadImageFile(Tools.RefreshFileAddress(TbTools.BACKICO, TbTools.BASEPATH + @"\", Util.MapPath(TbTools.BASEPATH))); + myPanel.BackgroundImageLayout = ImageLayout.Stretch; + myPanel.Tag = tbConfig.C_Tag; + } + + var picboxs = objDic.Where(f => f.Key.Contains("picbox")).ToList(); + int i = 0; + foreach (var item in picboxs) + { + AddImage(item.Value, i); + i++; + } + + int j = 0; + var labels = objDic.Where(f => f.Key.Contains("label")).ToList(); + foreach (var item in labels) + { + AddText(item.Value, j); + j++; + } + } + } + else + { + throw new Exception("对不起不存在优惠券模板"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + #region 增加图片,文字控件 + /// + /// 增加图片控件 + /// + /// 控件的基础信息 + /// 第几个图片控件(用于名字使用) + private void AddImage(TbConfig config, int i) + { + try + { + var pic = new MyPictureBox(); + ImageInfo imageInfo = FindImageInfoByTag(config.C_Tag); + var backImage = imageInfo.ImagePath; + if (imageInfo.Varible.Contains(EditImageType.其他图片.ToString())) + backImage = Tools.RefreshFileAddress(backImage, TbTools.OTHERSICOPATH + @"\", Util.MapPath(TbTools.OTHERSICOPATH)); + else + backImage = Tools.RefreshFileAddress(backImage, TbTools.BASEPATH + @"\", Util.MapPath(TbTools.BASEPATH)); + + var bitmapImage = Tools.ReadImageFile(backImage); + pic.BackgroundImage = imageInfo.Shape ? bitmapImage : Tools.CutEllipse(bitmapImage, new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height), new Size(500, 500)); + pic.Location = config.C_Point; + pic.Size = config.C_Size; + pic.Tag = config.C_Tag; + pic.Name = "picbox" + i; + + pic.BackColor = Color.Transparent; + pic.SizeMode = PictureBoxSizeMode.Zoom; + pic.BackgroundImageLayout = ImageLayout.Stretch; + pic.TabStop = false; + pic.WaitOnLoad = true; + pic.MouseEnter += MouseEnter; + pic.ContextMenuStrip = this.menuStrip_Photo; + myPanel.Controls.Add(pic); + pickBox.WireControl(pic); + } + catch (Exception ex) + { + ShowError(ex); + } + } + /// + /// 增加文字控件 + /// + private void AddText(TbConfig config, int i) + { + try + { + var label = new Label(); + label.Font = config.T_Font; + label.ForeColor = config.T_ForeColor; + label.Location = config.C_Point; + label.AutoSize = false; + label.TextAlign = ContentAlignment.MiddleCenter; + label.Size = config.C_Size; + label.Name = "label" + i; + label.BackColor = Color.Transparent; + label.AutoSize = true; + label.Text = config.T_Text; + label.Tag = config.C_Tag ?? string.Empty; + label.ContextMenuStrip = this.menuStrip_Text; + label.MouseEnter += MouseEnter; + myPanel.Controls.Add(label); + pickBox.WireControl(label); + } + catch (Exception ex) + { + ShowError(ex); + } + } + #endregion + + private void button1_Click(object sender, EventArgs e) + { + try + { + int seed = 1; + var tbConfigDic = new Dictionary();//将优惠券模板控件的信息保存至字典中 + var myPanelSize = myPanel.Size;//获取背景图的大小 + tbConfigDic.Add($"panel{seed}", new TbConfig() { C_Name = myPanel.Name, C_Size = myPanel.Size, C_Point = myPanel.Location, C_Tag = myPanel.Tag });//保存底图信息至字典中 + #region 保存底图中的控件信息至字典中 + foreach (Control item in myPanel.Controls) + { + seed++; + var tbConfig = new TbConfig(); + #region 公共属性 + tbConfig.C_Name = item.Name; + tbConfig.C_Size = item.Size;//(图片|文字)的大小 + tbConfig.C_Point = item.Location;//(图片|文字)的坐标 + tbConfig.C_Tag = item.Tag; + #endregion + if (item.GetType() == typeof(Label))//文字信息 + { + var label = item as Label; + tbConfig.T_Text = label.Text; + tbConfig.T_ForeColor = label.ForeColor; + tbConfig.T_Font = label.Font; + tbConfigDic.Add($"label{seed}", tbConfig); + } + else if (item.GetType() == typeof(MyPictureBox))//图片信息 + tbConfigDic.Add($"picbox{seed}", tbConfig); + } + #endregion + //File.WriteAllText(TbTools.TBCONFIGJSON, CsharpHttpHelper.HttpHelper.ObjectToJson(tbConfigDic));//将字典保存为json,再将json保存至文件中 + File.WriteAllText(TbTools.TBCONFIGJSON, JsonConvert.SerializeObject(tbConfigDic));//将字典保存为json,再将json保存至文件中 + ShowSuccess("保存成功!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 登录淘宝按钮 + /// + /// + /// + private void button2_Click(object sender, EventArgs e) + { + try + { + var tbLoginListForm = new TbLoginListForm(); + tbLoginListForm.ShowDialog(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + #region 设计设置中,图片的可操作控件的右击菜单事件 + private void 增加图片ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var photoForm = new EditPhotoForm(); + if (photoForm.ShowDialog() == DialogResult.OK) + { + var tbConfig = photoForm.tbConfig; + AddImage(tbConfig, myPanel.Controls.Count + 1); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + private void 增加文字ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var textForm = new EditTextForm(); + if (textForm.ShowDialog() == DialogResult.OK) + { + var tbConfig = textForm.tbConfig; + AddText(tbConfig, myPanel.Controls.Count + 1); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 修改底图ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog fdlg = new OpenFileDialog(); + fdlg.Title = "选择要上传的图片"; + fdlg.InitialDirectory = @"c:\"; + fdlg.Filter = "jpg,png|*.jpg;*.png;"; + fdlg.FilterIndex = 1; + fdlg.RestoreDirectory = true; + if (fdlg.ShowDialog() == DialogResult.OK) + { + string oldImagePath = TbTools.BACKICO; + if (!string.IsNullOrWhiteSpace(oldImagePath)) + File.Delete(oldImagePath); + File.Copy(fdlg.FileName, TbTools.BACKICO); + myPanel.BackgroundImage = Tools.ReadImageFile(TbTools.BACKICO); + myPanel.Tag = new ImageInfo() { ImagePath = TbTools.BACKICO, Shape = true, Varible = "#底图" }; + } + fdlg.Dispose(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + private void 修改选中图片ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var pic = (MyPictureBox)_sender; + var photoForm = new EditPhotoForm(new TbConfig() { C_Tag = FindImageInfoByTag(pic.Tag), C_Size = pic.Size, C_Point = pic.Location }); + if (photoForm.ShowDialog() == DialogResult.OK) + { + AddImage(photoForm.tbConfig, myPanel.Controls.Count + 1); + pickBox.RemoveSelect(); + myPanel.Controls.Remove(pic); + + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + private void 删除选中图片ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + pickBox.RemoveSelect(); + myPanel.Controls.Remove((Control)_sender); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 修改选中文本ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var label = (Label)_sender; + var textForm = new EditTextForm(new TbConfig() { C_Point = label.Location, C_Size = label.Size, T_Font = label.Font, T_ForeColor = label.ForeColor, T_Text = label.Text }); + if (textForm.ShowDialog() == DialogResult.OK) + { + AddText(textForm.tbConfig, myPanel.Controls.Count + 1); + pickBox.RemoveSelect(); + myPanel.Controls.Remove(label); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中控件ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + pickBox.RemoveSelect(); + myPanel.Controls.Remove((Control)_sender); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + #endregion + + #region 鼠标进入事件,将获取到的控件信息保存起来,在删除控件的时候用 + /// + /// 鼠标进入事件,将获取到的控件信息保存起来,在删除控件的时候用 + /// + private object _sender = null; + /// + /// 鼠标进去控件时发生,这方法针对所有的要增加修改操作的控件 + /// + /// + /// + private new void MouseEnter(object sender, EventArgs e)//当鼠标移到pictuBox内,获取焦点 + { + this._sender = sender; + } + + #endregion + + /// + /// 将图片控件中的Tag内容,转成ImageInfo对象 + /// + /// + /// + private ImageInfo FindImageInfoByTag(object obj) + { + ImageInfo imageInfo = null; + if (obj.GetType() == typeof(JObject))//这是因为配置文件中json转出来之后还没完全转完毕. + { + var imageInfoJson = HttpExtend.JsonToDictionary(obj.ToString().Replace("{{", "{").Replace("}}", "}")); + imageInfo = new ImageInfo() { ImagePath = imageInfoJson["ImagePath"].ToString(), Varible = imageInfoJson["Varible"].ToString(), Shape = imageInfoJson["Shape"].ToString().ToLower() == "true" }; + } + else//这里是用户在设计模板的时候,添加修改操作时.正常的类型 + imageInfo = obj as ImageInfo; + return imageInfo; + } + + + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/MainForm.resx b/应用/TBAppraisalTools/Forms/MainForm.resx new file mode 100644 index 0000000..0d3ff37 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/MainForm.resx @@ -0,0 +1,1178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAAeAAAAKnCAMAAABpv27uAAAABGdBTUEAALGPC/xhBQAAAwBQTFRF+fX7 + /4dc/4hQ/oda+fn59/f3/Qob+/X7////+/v7/4VR///8/P/5/4dL/gcZ/2Io/y8602wH/Pj+/YNS/oZO + /3xT/2pP/XM2/2sw/2Yu+f/5/mUq/nJN/v3+/odX/n1E/mhM/m9M/ntO/hYh/mVL+PT5/FNL/lck/3ZN + /3A1//7//2s0/l1L/VxE/3Y8/3I2/G80+WUt4aJV/Qse/3Y4/l0m/4FG+f///4BW/Dgs/UBC/vn//iYp + /3VQ/Tkh/k8n/DAizmwG/3s+/hsp+WJF/CIg/DU4/kMy+fj5/ldE/29S/i8q/n9P/jg/0nMQ/3dS+i03 + 2hws14Qp/UhI6yQu/4JY/lJD9hAi8ioz25E+/2JF9/j82m4J/k48/WpI5alf5q5o/1NQ2Yoz/mNR8+70 + 9Q0Z/kMe3JdH6w0Y/ltR782Z9vL45rRy8vPz/kIn+2sv7MWM/vP54pxM/U4f/Ypc9kdD/mM2/Q8k+3Y/ + 7MCC+OK4+E84/9na/ks0+UM1+0Qg92400R0p91gi7evu/vj2//z4/vPy/lk6/Sc29tuq/klB79Wm1X0i + 9lxD//js0Xca8/z9+m9M9mAk57t//lou7BMl/uzf4hEb4SYy6rh4/3ZD91c88zY4+F4q9tKc+ntG+ns9 + /vry+HQ28vrz/kI63nUQ8kVa7MeU8kg2/klO+IdJ8Pj5/mxA+WxF/uzv+E8d/tHOxsTG/N/K/e7K//X9 + /Pz94khY6ZY52Hkc7//86F8b7p2Z/cHD0s/T5+Xnube53Rof+fz97FAc/fXh4d7i2oJ68Jl59XY/29fb + x19o8oF+80Ib3ow4818t9YJX519v425G9vf/7rBw/NO+5Icl9fbt2byVtFxgy5x14Uk2/IqU051W8q6W + 8TMp724n9cGmuCk42qxy6lhe4V01y4U453Bz6ztOzlBZtoxh56RXl5OWpaOmhICEnhEb5lxG+LCzsK2w + 5EhGz5aRcnByugcN821i1GgJ/oJeUU5R/3NawHhv4IJXZ2JlKRQYdxIa4tG9z7t3PgAA5sFJREFUeF7s + vQtgVOW19p/WTEkKFosVEiByEYEQCImCEZBSMWJAKJyiQEHwgneMkVIiEsE0CUHAUIiYVkIEAtbYADHA + nCNYkiYg0NL4YTlQ/bgoH5xTK4hUz2m1+j/+n2ettffsuYSES2v1+Exm3+aSmf2bdXvfd+8dFf2Vvsha + smXL/pKSQ7Nm3LunfuvWI798bNOmTSWt0l5//fVJlb6C6S0mfQX4i60lW9Ys3vjB3q1VM2b03wrEx4/O + 3l6yfwkALwHggowlXwH+gqvVxn07j79ZX3Xvnrz6ehI+tG/j9jWVBnjJlq8Af7FVsHjfzmNbt+6ZUQW8 + VVVVW9/cu3Pf4vaVlUuWLPG1yKj8CvAXXIUlh3aB7J6q+q1HgHnPnvo39x4qWb1GAGdkbPkK8Bdci/d9 + srWK9rt114/LYcFItt58bd9iAbwkw/cV4C+6Fh86Vj+jqkfe1m/u3HkpLHnGvffuoQlnTpoEE/ZVVn4F + +Iut7TuRQCO9Svnxzp176/Oq9gDwsUObFucTMAj7vgJ8gRSTmemP9sdE+6L90div0TGx+ZkxMfZgc8QX + Qf5Yf2ZsTI1saoa2HwPUvOL61GN7d+7dijRrxoyqN3du3F7QImrJliWTWkz/CvAFks/nj/FlRsf4fLH+ + WJDOr/HFZORn2qPNVYYPPxQffhl+29CUSo5VzajaurU+b+sRBQzEx3buKymYLoCnfwX4Qgl4830xsTUJ + vkwfaMfGEDg428NNKoO/C7wwE+/kz/SLNTdDJUckw6qv2nrkx7u2Am99Xg8CLpze4ivAF1gZAAsfnenz + x8IKfb4MGrU91rR8fn90Bjnn796NVzfbgo/sqZrBCrjeAG/dmncMLloAb1nyFeALJlgerbimuvbE6drq + HfCymZkJGZnNJuyL5U8jITr/xMkPT2zTeNwMbX+tvmoGGFdVHflxOQHnba0/trNk8RoF3GLzV4AvkGIy + M2Kid5/48NOTJ09++unJd7f5YuCnY5sdhH2xGZm+BH/mux++e+LDd2ua+zqWSSiO4KbNgpFR731r+5o1 + LQh4y6QWXwG+QIpBUlV7EmC37d6Rv/vEp5++WwMbjmmuJYoFZ8ADfHQiI+b0h7ub66ILX3p16x7URojB + SLIEcN5rCwA4qsUkAK58/SvAF0gZ/swTn57ckemLSWDBlH/605OZ/sxmZ8OIwWAck7n7o22Z/t2fVtvW + JlWw4ZVj9Xvu3bMHFnwEgMVDb1xck++bzq7EJeG9SRkZ0bFID2J9Cb6a/MzaT5EvxPr9/lhsRKLHTO8r + RVKmr/bTE74aN+ZmVn96sjk5dEImfhoxsaivGLbzd3/0rs/37snq5sbugpJ9f3izfs+Me6vq67fm9Z9R + /9PjO/dt35+ZFltQUBC9JALgBGQGmRnI12vwX2s/fRdJf0JMTALydjJudvD/X6eY6pPv7mCuZfLFVH94 + IrPmXVttVEjDWD3H5KNq9u1496MPP/3www9PBH4oTahg8cYPPjn2JjKtGVV5hHz86L6SDXdPmxRbsHo1 + CYdbcDTrOfzHmAxf7Ycn8jNhuDDbjMzohFiUeMjkv1JEvfvhjhhPzIUtnDi57d1PbbVR5eOJqKZqMjMz + a2o//LC2pvbEidqaZrv2gg0bNu47JIjZYdiwd+dbGxcX+F+/G4AXry6oCwdMG/XHgGWm78SHJ3ZHS0mH + NbHq6K9cdGPa8eHpWPz+XTAJNdHbPkRKbKuNyh+TX117ejdS7m2sj/L9fsRCuEp7uCllbN5QUrLxrVc/ + OQad+mTnoY0lJYWvL3n99YyCQgCODh+yE+OPifFnZsbG5MN+YbDwz/TQ/lg/wgzM2p72lUJU++mOhBo2 + Vpr8CKTvfvoRvPaZlQkrP/nhh6d34MdQnY8ELZbNWUjTmqeMNlH5NdsXb9z31qFDh97at2l7SeG81ysr + l6RFK+DoMMB85wwfyrrTH55AuR5L+6XYgOZLaH5d979NJz/MhIcO7J/M6pMffvTRh02mWTEnT9bu3nbi + ow9PntjB3R6TkMFGreaqzTT/jtrq/Ythxhs3lmzfvj+/wF9ZuWVJpbroCIAzEW59MbGw39MI/jXmKmJj + 86NjEIcDScRXCtan7/r9MYhjjpClVp/8tEkPHV3zUW1Mfqzv5Kcoj6Lz/Zn5+ZnY277mtmG3aZN/8qNP + T+wo3A+tXrNmjW8a7XdJfjSSLACuC4/BSNaR09V+9OG7p2tr+Xcak9rabfn4efq+isGN6dPTSIT9cLAm + fz6S1d1NJ6XVn25DRosaK4OJdExmAqpSWpg93JTqllR/9P99dHJ3TF37LVuAti5mWmXaksrKGAKOmEXH + 8IcUk//uRx99+tGHHyJrhzh5FwEmAY/Y075SiD46wRzak0XjhgS1SUus/rCaLzzxaUwCnGd0rB9VsQ+/ + FHu4KS2p3Pbh//fRu/l1lVu2bFmSsXn65lgK6TUUG6kO9uX7EzL9/t0nP62NqanxZeYjgaZ2IJX3xQZ+ + oV8pWB++iwwrIZBkZcZm+qvfbbrBwv/pu/k1+ds+OokMB+kssh32Bzc7Ei5Zk3/65MnqDAHsy5g+nWBN + 5BsBcGYCByfE1CALzPQz7FIZGezO9ksY/kqR9O6HNZnwsgm2ilCXkfHuh7ubBJwJPqffha88sduPN4jN + Z6aF7Mcebkrt17RfU1PTqn37NQC8xudj5F2M++qCAo7ZiQA4GrUcyiSfXwhnxjitk9yU4AL/SqGq/rTa + nxGd6QKOzYypOflu02NvfAnV77578t1tp1kq5WfGIv/J8De7SsLr97ds6WuV3x75FeVbXbgYWr3a5xO+ + 4YDZruH3+zJ3+He8e7IWZTEdOvI6P/IFQNYnfaUw5X/4bqavJuBbYSS1J2ub4WtjMmu27YB73H3iw5O1 + +Qm+/G27icAebUoFGzYUbsgvKCykT/b51qwpoA1Dyte3JtxFMw7E+mOR8u8GYfDWRDAGib8v+iwqtP9t + Ql0pLbqmmJhtJ9+taTpnqYmRlmF/rC9z24lPT27LR0Z7srr5ZdLd07edrq3pNZ0CYVigxF/2MyxZ0n71 + 6jDA/hiWQ7EZvprYmB3vfggv7UNqF8usEB/kK76NyVeDneX1rTAPpFhNujz44wTUvmCcEe2rPYnKpXrb + yZPN7myoW7Ljw48+OlFZ16LF9OktMjIQeOu43eG7ODwGI5uTCJKJ/7zj5Kf5AMw4zFYaX8ZXLroxIaqd + /GhbwGDzT35andEMO0R1FOND5EUai+Il8/RH22oyGc/t4aa0ZEv1Rx99dLKmclJGC4qZFQjXnQGwCdaa + ERNT0+ye5//t8vuid7yLPZ2fwd64HbUfndwGboHOhyaFChglTP5H1fnR2z6tbW4yW5dWjTr4BPt2RbF1 + dWLB0TovKGgUMFxyJgru5saC//ViT8yO0yc//fDd2toTJz/89MQ21LOxzW6woC+Pjc7wZXI8Fkqu5jco + ZVa/ewJJmq2FqVHAmf7YzPyMhK+CbjOVgHhLxO+e/PBDpMM1jKrMnuzhJiXJbGxsbC1e/uGJsyhX2Pfn + k1Inohq3YH7ir4Jus5UZDYeMuIaqh41/SEc1d2m+MjKi/Qkx/t21NP5mWzCPpgDiRp/fuAUDrT+m2SPs + /9crUwa9Uxnss6diOWzCHm5S+C2wJToGls8auvmuncPswdhWw9QoYPw0MmNj3IaZr9SE5MCEBNLBnmNj + IBaJ2B5uUtrCEOtnN9TZNEYzuzqTo2gUcAK7+tn1/5WaJRgsEhag8Ut7kF8OWzmLhgNlFBuL6hQ1afOP + WuPg65jM/LOPwSx/8alt7Ss1JR6pApvFPkMkxmoC+2Z4IFoz5UMIZqnky89AXZzR7BiM2A8XnXD2gL/S + l0NfAf6S6yvAX3J9BfhLrq8Af8n1FeAvub4C/CVXEGAdcSnTRmVP1SfX1dXJRo/s0WYLbxEk2wzZJ3Hm + VJs2OrdmAZU8o7FbuLyP4haQPX4+quMeUdkW5x/YGsRFz/PqJlH2LMq7DNmzzllRHN8hXxVFdgI0aVJd + XRuPWrRoM0jUpk1UVJs2CZOk8SM2NiNKPtkk/6SoNpOmRfXis1pEtWjj89WlTWJHYx3ezp+RkZCZn+mr + zOSZ1+rS0iozKzGdlFnpS6vjVszT6qR3Ok26qNPSYvAavL3P55sU3aaNP0H3QFQLvP3mzdOnT2+BD9Qm + to0MMpGxJljmLSFhkL9NRtSVk7CHeNOt+AKDEnr1SpBvIGqDL93G38bfC8/GZ+6le90P8dsOsi8LcRlr + +MNbD2qD/yqPRSUMuvLKNm2u7NUGe+PKSQl8Ffec7AzsO34L7liu8TFsEskaXn+lT56G9depJUvkpINp + +PrYMZCuU3wHZ+icrlHyJMg2Q6+f8RZV6EqaJrHXfL4M6MorZRCIjPWZPn3z5hYtroRaZPjW4An4UfDp + V+Ke4Jvma+G78kp5WuH06Xy9j/1XvszMQjytwFfQsiXeuSVH/cjO5LxlS/46ZZU/LNzq5D9Pip4nA8jw + DiEqkH+AT4KfXAt+QHk+HzD5fHL4RmbmNLnxKVTmNH4dflJ9vb5INY0Tfh+TjIko0JuvUG+FhdMLcJM9 + hO9XMK2gReE0Dn7KnBaNn2HBtEIfvmJGAf4vNmbw3DoyxbebN2hewjy+r35A/jwGDSoomDePlhSLHxTB + Z3IopCk6usD5Vr6WLedBBQUZvknCwx87iLdBXPaKP6IzKYqDLAPSEXkq/ViFtraa4zE55hY3PnGxfOXC + 1fNWy92VPipTPmvxhg2Yl2xYjNmG7du5sQRr3MTp4sING+yFJr5SXi7vyeVgzdMvbmvOP/IoZPt+m7uy + x0Ol3xbvK98w+G3l49hi6HKwPFu24+bRBkeytRDfm+MhAyrBbglVpG1nq6h9QdoIvdS49r1kz/uVo5fw + B3FqG3SLLtl2LPDPtsqMc850g0e6MXizfCpORC/xE9oyNFtla2HS7+QosGJLQY/K/9qnt1DZFr5hhEeD + 9SvcHHHJ+5Vs+R+mqJ3Qb5uv/wgXNwYetDVdwPQ//s//+z+q/8D9/8kKp1j7fxTXA+JLTPqWweKH/TvL + /lPjevVVW8AX5D1U/x0i22xfUL90qP61+frPs1SUfQxX9i8bEf7Dn0X28v/81z//KzfysV/8Ait//sW/ + /isW/vM/f/GLX+BZv/gFnvOLF3/xnz9/8UV9AfTzn8smzH/+n//p2Y6X4PnyH+wtXdmHE7322mt/NWGx + uWrsuUuDZf8jgk6dcu6i/55qCybdLVTFnyugmSbbuGLmTP2SKwKaEKpbQvQM5Fk8J0V9rBohk6n//d9T + RQ8E5F3uTukHHzv2RVH3B+7s3v3OO7vPxASbsTCTCy9ismLmiy/OXLFi4NiB+C4DR624ZcKKUVi8xeay + sGLUqDFY5HzgwLEv4k0J+T9/ceedd8p/xCcyfTz6tctcsj+OLAC71XSt6WsX3Xrpa69de61uu+wyxfra + ZVymRqs+Xip74OMR4SJ3zNKXfvxxevrSEUvT0zu3TS9q27ZbUVFRn6I+fTArKiqlcgKaPDdIhhQyliqQ + e1J1w5M3qMYH65nxgCQLOjtrATC/RFtI0ULdeqf3hmQHOxK0hBsArMJDM7vjXiGPjL1zLO53rliBBZn8 + HNgGrrhlxcBRw8aMGTZq1Khh+F6jBnI6YcIYUB11ySVj8AgeGih68cWxeHf8PhTwA/xAYltLu3bteuml + txph6jWsfO3yS1WXc+G1X742sutlejNh88iVK1d2HTlyZNeuXOANuqzr4KUde44e3XGwSiByT3RWTTG1 + bYvFzpgWpQNyUXrbLph0Ti+d2G1in9I+fUqHD58/3wt3jkc3qeYO8OpmR09eJzKwpiuMy6OPXvGoyNav + 1rVHH706VN84s6L0W3nwkq3ogd7dewNdQOO6Lxy7UPEuXDhw7FiwG3vnA2B+J/CO7Q6LvfNOLIAxHwRf + MMZzRsF8xw4bNYY8h03AbMwlwy4Zc8uESwD1kgnEyyXQF8CAS7rwCg7g9G6dly7tOBo2B1ZKmKb5Gm63 + 3qp0TV//+uUUlsxOX3sNL/nmN8F2pQCGbAbAPfGj6Tm6o0n3gv7UjbEI5tq228T0bt06d57YrfPEoqIR + bYuK2nbLAdzhk3PG9RkOzZ9MtJNzJk+ebGhduDcZVujmmz10b1a6lKGlrrjhikevuAJ3AQp4V9+DVaHY + CMlvNSUBzC9leGG+AQFqAPC47uPGKuCF1EAiHvsiXbIY9gPdxYZhtS8C7YsD4ZnHLgQw+udhAweCMgiC + MjFzJnMCV8OGlC+cNPia/XZ/4IGios4jPh49GIAvA6ORI6+9FnhpmuQdKqUbpJEjZaIW7KpnT9yXL+/Y + s6fx7dixS5cunTvLrggiTLLdqM7dABhuuTPseGI3WC4JjwNdEAZgwAXeUMBzzwowYF5xxXhOHsWUgO+5 + B3TvoQKAv+W9NSm1YHwv4xsgTLfc+06vBXenS1YLhocGC/CFqUHg61jynQi7M18cuwK+lhY+cOyKWwiZ + Xlr4IvwiGksYBt8VACxoeV+BTAROwOgyESiC/bb9+OO/ju64fjSMj6RGjrxMyZnEZiGxV/D95ndcjRx5 + zTV4vjyNLxTE8NKOllOzZLochJfCIS/tooTbdnZuRIvVbt1gyKRc1I3Bt/fEPsP79O49fNzwUqAeDgct + 9jsZU3HUFnqhhw2vyfB6AUMGOCwCjx8vcL0yyq6MY6MKs2Bz0WpA2NXY3d3pMLt3R3SkxH6VtMuXbNWI + HwBfjb+ALJbMKZMsNV9aK3ILoaqGLNF3lCQgGnuVb3eJvpL5jGaEBBthJLYL43Wc8+UXqQTwa7cKyUu/ + KVKqr5GwpVQewMuX9+wJG541a5ZG+I5Lu3RZirvg9YjGKzNZbNu2CPlJehHhDp86lQ6ahMcJXEcevHOD + 428jgI1uOF4PYFow58Y1IAPZmKKUrgIWqoHkSva17HERc2ZFDLsUyebuQI07HTQTLPhm2O6ogS8OHDYM + pjsKlkovPWas8L2EYRfhly75EttADSNfZNEKmIgBGBERKWBH7H0E4MHw0aR07ceSYKlu/eutX/varXq7 + 9VreJF22R/+qeTNehs0CWBJmyalGjBiMRfy4Oy6F8fJXDnFXhIoObWrbqeSMRZgvUits6gO4mIKtSMku + XBssOmkDSxlaUcQMC2JSpdmUJ50ix0ZicNOAsfv4PeCDpipaT1kEvDJTSVVErg5gpcHcGYzHAu9CZsAS + f1+kVybkFaOQasEfS9wlzUtgtcR8yZgncaOfZhpNM9a6S96T/xbWy53eEWkusRAU+Rk7FQDbEmBKHRT8 + ONMx8vUWRR/zjjfWoqiLxF/+I5EwpVwX3blbb6AlYMzTe3ebSsDdevdBEt2nDwjnTHb4LpzjcHVukQAj + 58D9SQVsVB0RazheR8rSsLoSimcQAUOaSNA905K9pa8IvhoSAAHA6qDpm+VO+5VMWpIsJtCSSov7hRPW + tOqSJ82Mx9B8wXvgJViWJ/D98AOR/8QITAL4ZCR7WdelS681lLBY6tKLEHcv/fqll170NUcXyQPBebVI + vfTIS0fSRYvgnVVwD/TXsg8QhZcuXQ8n3QVYp9iNmtINiXzn9PQpnVEhgTImyKYnphcVpadL/SuAJbVa + i5twdWVwBxzm/fDhAQAMETD+DKwjgjUDvhqVkWFVnSfgAGEBHEqYgVaisFlwgK8kWACsydhMYSsmrfEX + RkzfC8rK13HT+I5Yh/myPIKZky8Bvwi3j9SdfOme8cGA4zXWQ6x5v/a1v170NZJFrszp1wnYBMDQrWGJ + 9OUsmdxES/lCDuDlK3eR8KxZ69dzN6wH4C5LOy+d4txYAk9JT08H4CICLiLqovSJ6aXpnbGSXlGaA8IO + X8i4ulK8HsD0z9CZLZjhVwE7cfc8AJtTUrIq4yoSkxJ8TppFwdIkd+4u7VYz73xA2zVAmkaMEnnFi7Bk + hN9hbNcgXqZXYybcQr7APAFrkMRe4tU3hVj/Em9b7G46ZyCGb0aoFYwAaXPoxxchw1LrDUjxq+Cxr738 + cpo1XLTZ70oUSKiCRwfqIxXxUmq0AbEOxo+/c9tu6bRjSaSLYMGlEyeWlnbr1ifHk2PBgteiMgqS4hWJ + i6YELmVgXUnjBtE6eBuNvB6hWj7DTZMsD19JXo0tRbgOYMUAwURlm24Hle7dV2gkhv3CFoUYDXjsQNZD + oHwL+A4zt0y+Clj4sjHE+engLfE/pyLps+ArNAj41luVqnFsVHyOIlVxWVYkBrtNk5JqGVuR8e0SDpiB + GAJgEIa3ho8uAt2Jkm71KXVTLAE8Z24jgI2tyPBed92NNxpZEwHTdl37bQ7gMysqhG+zAAOkuxk2DCOm + S9bGZ8yZScOIha/Y57AVrHZBmeUR3bRUv8qXDVhMr+jXlS/+P+yky9KOTJwhh5LwbRKwg5hMKXmpLMmb + Gd7Rl0ku7UHcGGCTRmFMNQr3acu2yuFsznLxEvCc8wJsfAHY6ELG6ZylgDuTqqpZgFkgjQUMApEEi70M + tF02cGgrNPGCL/zzwAm3MIsmX+TPgpfpNBunV6CUIl++JwDz9yL/H3sTIXEwTJetksLI+DYphRwMWJcE + cJAFNw8wqLYFXC5hEfe23YqQREPIo0HYWrGgCwCYfImYugeB98IA7hwC2NiKBK4HMA1NHDSjpWvA0iaN + rTNXMBMWtE4SPXDFLbewrRJkmV45fC8BX23k4BPZLCb/Qv1z2xHY9T3hmw0uZPyaVATAMg/Ga4ABFklV + kEIBgy0BWyLNjiTckUTj3geISwnYIXx+gK+QCAymBMwmSmZWFwQwvobCpcIAy35XCVuioAFzqgbMTJr5 + FT01Ey0G4cMrxH4Hjh21YsKEYexLYvyVbGvMJRBrBaZdBEzBA1DSqkC+Wh1BijcAWAGeWUEuWmfBeIWu + mK9hDUixBiQZFkTANN8R3ZBIw0kLYIbh4eNcwmcC7CVseCMBlvjL9itFewEBewqkpgCTr/ltemq2dLAU + 1gQLoMHX4i/IIYuG/Q5DFq1pNOBKlQTM5KuApUYSvL27tR3BVibQ1ayXdM4OsPweXMAiBy6oyoRow9mK + CDNEtF4YLgl3S6e3JmHUwn3gqAGYLdHW13A+gJWvuud7aMHEc0EA8ztIE3QzAbM6uhOFETuChTONmPaL + IgePSiSG/bKp486xh4dNAGZSZtWL4pdcCdj4CmCrqck3XfjCO6M47dp1pDYzevg2CVhz6DC+BCxWKxNE + XLY9RxL3RqjolYGUHYeMxem04dLObfswk242YA9hwxsEmF1IDmDWvgZYIJ2PQpIso+ooUAKPBULhyJTq + TmAnXiRW3emjH3hgZgVyLLZizTzMrgZWSRNuGQVLRn4F/7zCqmDyFQM2usi02ER5550v4j16F6HARPnb + ESzYKQC+QGvcIB20YSsRJb8AD1+Cpcx4HYn9SsvkCKPqkTH1iCaQnj5CimHNtlgrTSwF5qLSbqXDkWhZ + Jk3A0tQRgGxwKaMLGV4PYMWLAAzvDAu+2m2qNEznruAky7g6Il8HsAh82XBFH23babdIthB7+RTaL0Cr + f5YOf5gvojCKIRnKweJI/TPCsmqsuWcYcFFReucRqI4G9+zp8g0AVr5nJHwGvh7AwlcBG1SvjKpH3D90 + zQQs1owleGj8Grv1KZoIC2atJCZ8RsAGlzK8EQEbWFfG6ZwVBNi4ugpwJD3YqPBlyyWSK7HfOx8Yiy0w + 7AeYSQPoTE5gwDbBVLIsmPGYW4Sv2DFm7A1mEi0N3C/yX/RGbOuCIIlihf55ZCT7hWw9koIBB+BCBhcC + WsZf8tXvruIyZatecRvDLpelFsZyEZs7sMI6iSbsSbOA9WwBSx+/AA6TcTpnSZLVrVtEwOQbasDCl9sR + c7uzHAZoSZ41yZqJO/v7WSXRiAeOpeHqiA4zXy4g7mKFfAkYNox/UTS1c2fUvuQrnb+Xkq80QKvrvUj5 + 6nK4vIDD+JKraQRukQA3JYm+dM6SY9F82TA9sVRGZrFTqQnAxlZkeCMCDlA2QuepKHxD9jJAwcPsCJHy + AHbtVyZ8CMmWOGkE54qxL+JxNkADNAA6vQwTbhG+2reAKliLo1EDOWMJLOK/QP1LttRKdg4gsfqaABZ+ + Dt/mAI5ovorX0zNofYOK74wWDFl6RTOmJdOCObCjW7cQwCQMrBcAsPE5b0UJXwJGCuvp7HcAC14F7PDl + FEkWHkKyRUOmt9YsmgGYfLW/EEF41GGLv2yLpneewP7/UStWDGMbJpso2fX4It6J/ftLtUun62WX3no5 + E2fwFQv2OOimXXTAfD32q4AZYw3uUk/fb5AUaECygdvNRXPCGEzSAIwgTA3XLkMhDKznAThUxumc5QJm + jQJ8LuJwwGzaML60XdowJ8CulRKfIXwl/lopfJjmysHAoEzvzKZJbBDrFr4QkixpwGJvHfi+9tq1BHzR + Rdb/SxlcSjdEFAELX68BC17ylRzKADvjJ9u6luuIAL0ywCOcJIti04c0d6Rz8CzwQk6Xwz8dYOJ1AAek + PtjBS3hAQYtlPoWqCImVrGlfMEol2u+L7HNgUzQH7dCAtSnabetgY8cYGX4FxMqX8Vf4CmDy1c6jW+mh + zxmw4A2x3y5Owwb5LnUAi3EGSREGpIDxGpqwvgCBuO2IIuTVE9n1D8LNARw5yQrw/bsBZvQ1kSx+j0JY + LdllPBbZMUhOBUqxX3DF/EUwRqKFR/gMHTDLPqWxLw68ZYJEYcPLjBnBGPGXrR1uEzRNnhUw1Hvq1PT0 + 9cixbiWea2+1yOvh2Ry+GoA9touYO1hvhrdLW6f/uxEJVchWg9ZJWsukbt3a0kHzwAZk0biNG5eTM1f4 + inQ8lpdvgLDBhRSvARbCwRH4W+H9+2etcMD8OQ4XxhwXbWIDpSZXvDtOWn20JlkWhHmX+AuC6qrVfpFF + kzMd9RjJomG8eA1fyncs6k0HOOLjj0eL+QGwtl39+KIzEQ1RIMNSwCAcyKmMb9ioyVAZzzDAYr2csJWj + 20TQncjOBhMNWJuzggF7CRvfcMDK9+8PWJg2Angcy11SRS2FVcBlogXAM5lojb2zux7RgHCKIunOgYe1 + SholHQ5sq9QuB7pn48thecCr/hk1Uu/0zhyERSzkiwpJ7PfMJhuiEAs21xysRlKrxqV0VVwb0Q1+Wcbu + dOvTh3cXsOpsABvhfwhguEiF6gGsbE0CuOiBqVikS7UsrLv2AoEtHTWDsKcpS1IttlVKY5Zsm7BCqmDW + UeDL9Mr4qv1yCDSPUfEAFkNuhpoJ2E2jHRnHRmVsJbPCWjrrJRbDasKSYxFwqdPxP5cx2COjCxnfzwWw + 8FS5gAnOI5BgTjWVoB9AgsUtbMpikQS/jDvHZK1YwQUdcCf2ewvTLDZ2ECk4D5PDCCGOcle+eDvpJMTe + Rq47WJMstmGJARu/JtVswCEyjo3K8LqAOaADE/Yu0X47Ey92Wuk4G5o1F/ZrbEVG15NjGVyRh+/fE7Ci + VTmAjasrGhphMNPiOrlaAAbksTLWTpIsAB5451geqQLIEovBF7S1OkIUFr7MoYH3RebkkmIBL0qkjh3V + QROw8D0LDx0Z8HkTNpExp0XdQLmo2wg2ShOwY8IAPJyA1UUHIBvffyLAIi4JV0csnHi8IZy08oXN2tBK + FsF3dl9RIQk0nTS8NLv6yZfeeMVhRuGBw1asGMYBWCrxzvyJ6CEq3IXgO3j0aO39ZSvWhQHMKcWGjggy + ymGeO8x1C11MtNMQ1sxUGsbsOGkBjDzL+LrdhsYXuvnm733ve6GI/yGABawj/bhhFky87NGrmDq1ewVM + WRzzWCZYD9xZIZUw+4JhlnTQ8NRjWSWBMvkepvnSjAk2iC/Und3Q8M9yiCjir+Klx/37AOaRKl4Z3yYB + UwCs25lKS89htyIAZltlH/poHnhmfBsDLIQNLvUPtmA6Z6uDDWz3cbTQ3lMfKOqO55UWTZ1aVDr1AUUq + DRzsSmLzB5MrVMIajdmeNQpAx45duOLwirVw1kiyxF1LJs0eBknO8EuR/4/dtXTpCBmmc610MlBnDRiE + L7oIeFVdR+vQ9iZkfF0ZX5U7aFzgytSRNkWzx0EsgpFNMuk5c2RCvnNvmht67Jl6aoN73XU3XufihYIA + 69xIn4eCLTgSYKg7fTO2FcHc5DFmWnI3J81WLmbRbKpkFg2y5p/nCl9pmxT3PGogN7MNi2+ufKeyZZf+ + mVyu5UkYpOvgPAHDjM8FcBBhRA2hC5Gph680drCpMggwCKsJzz1PwFc7gM+bcJOAhyPC4ilFQFtayknv + qd1LQQYPSZalOZZkW2Ppn8V+eWSDVknga8FYxDZK0mUrB96hNyK6AIbvk+PLLrvs1tekiUPpQsauWQoH + PLhJwI4Mb6OADa7LWHw0SmL2CgcAjxsngOXAURCGDKwrIewgvvHGG0MJG1dXxumcFRUUgfEpVUGAgbUI + vhkTGHFRb7BlugWmDKF0yWSlfFEKa38wQJLvisMyc8IvrRjhl/arfBHV00G48wjwZQsHUqzXiOmiZpdH + jiIBHt2z0eQqTIa3ccCCNmDEAMySmDWTA1h0ZsCWZXkBewh7ARuf81aUoVXZhwwCPA4r4NtWjBgLva1I + dlqqacAMwmylJF+SVnMVyx270DVgRl9WR+xD4hvgZ4I3xE9H2ihpwNdeeymPNzp7vB7A117Lg8RlRKYE + YZNxbFrGFgLeCICXCl/4aNpwN47qSGcibTuOo6TdA8BJ+KabHja4lAP45u8ZXxcwsy0Cdn30BVIjgIcP + J1xK+JYWtUU2ASPu03vqcDpp8lXAuEsAtpHRwldTZcGr/f4IzMoX/lmOQsXrmJQL37ZyrK5Z8KXqnNVH + E9rZCHwvB2A14lDCJjetDpHhbRywYnUB03xhwwBshzjYfkMUdowYtTD4BhF2AYsNK2Al7AIO8dLG6ZzV + JGDwHQ6/jFgj0ZoGjEx6nLRmaSYMG2YCzSrpzrHsSgJMABV71WRrIflSWCde1EgEzP+YLuargLt2vfTW + y4Wvybg1W0GAGyMcrI42dy3c4FJBgMlUIGObAJY0SyU+WghLIg3Ak3meLFCWSslDOAgw+XoBO4QNrco4 + nbMaA6zoKGxFlgW+H08t6vMAkyxkWt3ViO/kqFmtlHgmJYMsvf6IvAH7hZsmXunf51O02VNGYrcl3REj + 9DQcl95q2dU5W7CO6JBTeYS76QgKq5MNLltNQwDr1BFCMNstpb1DozAJy8AO6VYSwE57luGNBNjJshzQ + oYSN0zkrGDDVXfiyYYPtkayQSpHrvknGHNTTHbUS1h9gfzAQk68g4wRVMBCyqRJkacXIqOcu1CgM6OSL + p8Crs3kSFmxNlGIrwIL66DUDbMTOQWwnUcbe0yZBRjRUxpdSwiFyki6hzAYZE5bJdiL+eJeeYXXTylgz + rVDAICxSxEqYMromF7Ic4evV2Td8hAFWs3VFjAAhAdhGAVASQ2mI0qLFALxC+YoR00wFMLjylFpqxmK/ + TvilYL/SSIndN1ibKJFBG6dzFgETMU+wY2hNRjREcgIQiITFbkNEK/YiNr701wRMxgLYRMDsGmYcjgSY + Nsyb14ZFxpYCXdeIgwB/6xyatlzA8uODDKyKGLqzGauI9SptjlhYI3HMDl0051olsW0aGdTAmQPZ4c8j + DDmj/c5dMReRGaUv+SIz47vKG1HdpnTmoUg0ultvvejyy43TuUsJ3xoOODJhsV2TMQ2W0oUUsCMwFrza + Jh0CWNs7AoADQfi7rgUDcyOAeQo0Rx7AxHsBAWslpOpd9AA7jEGWvJkdYaPaMDIsigeUki8MmfYrbZWY + wm0vXDt3LrMrNm0IX31LSAF3Xs82SvJVwIyj5yPXho2wB7QhDZaxVRnTIBleyNCqwFcIO4BlbBYJS3sW + BL6GFzK8AKyEacHBNuzx0cbWZKCM7wUAzJ8gMAMwUYp/Zl5FwHweIzEAT53Jvn9gEr6slrQpegWMWEZl + sVWLGTV+xsDLQT+M1FI5yw9H8WJP6ZH84qF5fg3jdM5yjNhObqdnTzPExjRIhtaRUQ2VAO5CrIo34KrV + jieiWOqjI6Tnz58vfMWEb3LSrADj7ypjIfw9lMMG2GvD4VmW0YVk9SwUZVxdOYCZPtMX0357j5jKIkmi + MPHSggmYnblsqoTcJAuAQVZ7lUBdsiw2a4A/CysHMN4tnUnoiI95RCdSXkIhX3Gz5ynpVbKzF6oarZok + 9lLuQog8gGHCEQALYQJWN11qgJ1+Q8MLGWCxYo3C4qZdxB4b9hI2UMb3QgBmiyoxECRgYAq0mmQBrM3F + SYMUn4i5tGTxnMI8wF/SLJovKyZUTxSfFfDOar8cpsMmygsPGG8k56b1yCHMqUcBwI0Q9gLu0nnKFLZm + GmO6abZmOYBpw9B8MA4H/PDDFohhwTRhNWDpQTTAwXHY8ApfYysSamehMMA0YAewWjH4FhUVtSVYRGFp + kkY4/tjhK0Ph76zgCOkKWC6rYKbSAMxkGrDFPWvLtYNWJOmzAPZ46AtC+CIQDgesdXGoHB+Nj2FLwWoM + MCNyKOCJCljkdP0bXxJWwEZYeh2I9x8FGH45SDnaKMnqF950alu5I5vWfiUYNIdidO+ufcMVFayYZs7E + hIkVLRfpFLNorjD88hdD08WL5SfDXcQmytHioIWvnOHs/OskiIB5niyCdeZAbEiDZa7alXGllK2JJyoN + kpwJb4rcAZgSN02+6qYVsEMYFiwSvpZLU4LZACvh8eN5v2d8gLCxFSm25qtRwGyiHD51ah/wBFawtSMQ + yRd51tTewgs2TGuX4fBSDmsolvSK9gvf7DhoJm10ApKPq/WOGGx9DKDrGPDfEXCzCBtckbEVhQGWI4l5 + TnhMjDCjMK0XVhwWhY2vAHaKJZEXsMeGx/OchleP1yP9gdX4ng/gYMTkS1vtM7Ub/POIIg5PgZ+WA64Y + kIsYh6c+0L10eO+Z8M9aCUvHIc88Sy/NKYlLbzGewNgtv5FuU5GqEO/gwSOWCl4gUb7nD5jtYMymCZZo + nTllSM8oRasSrpACVsRYFLxE6xX5Ss+hnOFfTupggJWw8X344e8+HGLDlPEVuYCveHT8Pfc4CRdYnT9g + k6yTL0do9QbQ9LZt5SIU6d168zxg7MJlVk37ndl9ePeZ43rTfMWIH3hAjJj9hyQugKVtkoOfle9UpqJL + iRfuuav6Z9qcAb5A0vMZOoBRZdOGDeKZxJxAZIQdhQIOIwzE6elssKQJs9NQOpWoYMBATBt2Wi0tDnsQ + K2DRo6TsAhbEMj8LNQpY+cKGeeKbtulFI3jIRnpRbxkQLIGZf92Lpg7PATmYKxkylQJSBGRMbQX+mcVR + 797p6VM7T2V5QfPF7nLGcGgbhwE+f8LWl4y3UrYmB7GYckCG1ZWO11OFIA5ICYciFhNmpSSA4aK9hI2t + ihbMdMvYioyuyc7sD8QEfD7ny4oEWAjztNfDCRhM2/IsUUVFnUEbrNM53kyzLyTZU0uRjonpdp95Jw9O + g/kSqMwZfrmqgHnUJYefwjvTHnimYHbtEXDg1Pzn6aKlq4JOmu9lbOWkpBTjsIF1ZWBdGVwRCTsyth1l + ISJhx0drGEYUdgFHIiwJtafzwcialK4IgOW8LOfIOMqYeiXANQh3gxF345CptkV0zjyoTg2Zll0khyoV + 4Zl00IAsHYck2p1pFWfKF75cvDPTks7WdG/tG8B7KTJoAP6m8P27AHYQG9MgGVdXxlZEsJZ7uf3FuhQA + HKDMKDxxIuma3CBMwobWkQPYYjEzLW/LNBE7HYgIx3JRHSIOP6N/UwoFzPOXEy/Pao5iqFspgi+Sq49H + FDlseeAks2r8zXxAky06aKmGEXDVUY/lWVkAm8uSbBOw8GXjxscfD15q/vky5M+X33q5E4IvTJLlAL78 + 0m8GAY5E2Lh6NDpw8+TUQhdyFh3CATtWwGK/Kk8YnjPHwJqYaRGvk2wJYCHsYjbAbvsWCRu0s5ELmD56 + MvACLtd689T1PC1yUdvewlQGAiPTIltJsrQLsZQj4XlMGixXRnjQHWOqoz0EbXc687ZT2SAA9yzd+/DR + Uv5i18u1yi6SvnqRY4OOjFvzhVfwfYg3koyrK6PqkV1YCwUUSyjF2whgyvCiVuLoLG2vVMCSahnfOXOG + DBlidFUMxCYH8nXBPYgc7QG+jMasja0FE9DsHOFnFJ9KRbFgo1zAbKuEAeNjwjnDMSM54gAzHowDt6zJ + lYiLRUUPFHFIvIySZpUkqTR8NQ1ZTBe1L34Q0jtO41XB/cF4X7MLWOmBDCbj6so2n5XOBnAEwq7omtnE + RTmtWQ5sLithuiVUw9qiNVEHdyhhGnEAL2VwRUYXagxw2EAAQWYEmykXsPAVwLTiPr0r+nAoCj4ziiTc + ebJGacmSe/rUEW1plaWlWMcdQRgoJQqzQCJaDgYR9WYLCXIz5Svm+7GkV0ytjK+HsHF1ZZvPSmcC7Mjw + ujKmQRLAESQmbDbMMxA7ognLEEuRIjbAEQgbXZEChsiYMsAq4wvxumiQYBbaYbilWIZs1QsYaR+mPJRh + OK8mwgSapyso6jYCDhr+GYBRMQGuAEaWxQD8sSTTiMFMoHlguOKVmZx3S+iy3Vbwin8W7+wAZg3sBSxr + F0BnC9iRsVX17OkmXcZWe508gLt4AMMiNA4H+IYCDiXsYjbACMaGGDK+QUm1SelCxjEgA+zIASz2y5kC + pg3D//JQdrZygPEpOGoEYMbRbmQMsxWHXQGDLsVEj2cxsGzVYIbNiZCV2gh7aURH610QxKx+jYdL2FbP + W00BNhnWgAytK6ELCV3IFj2Eu/CSaSZrsgRixesGYcOrgJ94QgAj1XLteMB3Hb4QmQYB9iK+BzdwtLWg + TgmZGViuU26SBbooznWZaTQKJGm1kjN+SfU7oht4Fk3lNTg1AIsNF+GHUNoHRlyq47lotUU82kWf4LQ6 + S7/vYADGDiLe0cIXXI2HK/PMroz7WYnv00zAYYT54USNA9ZlD2GPDTuEWS6VSpoVzDck0/I6amFMvkLY + HRnvijglJPNktLxopVcaniHj6ipKrlS3UA04J8AXXrpIkixeDoopEr3s1KlchiUzo+iNQoo5GDLt3lO7 + FVX0QTpdyhauB5B6Yza1dzqnxtcZnordo/sPeJk+w3KFqytjdF4SvAD8dQDUq9yFS/F6G0FU+ukoBWzH + oorsCxhsM2JpszG+kPHVcql0/vxly5bl5Bhbk6F9WOxY2Mp0AG6Wb6lCMy5XBjVIV1/9qF2xVGW8rzbA + CxcCr1zEi3x5L9VuBvYtdPu4cxHPH9R2xFRpteSg77YsoJBwteVpSLp16wP7pU8HWaTVwlcGbLTtrHit + BWjw6Mt0fM5llzmD4xRIQELoPHU2gMNKZMMLGWFhKzK+XsLaRr00tBqmsomYgCFD6xU9NRBjQnks2fC6 + MqqhMrABsTFEmkOC5AKGBG9F997jSof3psuFAaePACwE3c4jmAUDG3Mu9jq0ZWzmpd76lOoFZtqqPYM5 + 02xIRreQLg9a4J6RsZPYawQsY5cFr3F1JXzwCO88jNQ2u+Bt1ZVtDhIBG75GATuyp4kMcZACnYzMqZ0R + IYGWLe1vErbrZWp457t8z8BY4d6rqB1zVqzfdXohRAY1goxumIxvEGAlDDHJ4jWBGIPpf3ka9rYAxiv4 + 6QWSwRcPdgZUXl6GVy9gOwgtV813qpzTsS08GHyz/OJhCLzIBpIYTa9UQiNIso5H/kGA7Vkmg+qVa8kK + 2F02vJAL2KSAsxWwY8KQUfVI+aoE8L1CmPpeuCVHpnwP7sY0ooIAk3D3cTkMwqV92FTZthvyYwBFYgXC + KJG0ZwkreIgeOL1I/PNEoJej09iN2HYEfgnpnZe2pevSfQDI2E8jR6ojhFskPTuQ30A5kgfc+fkDbkri + nymuyMcLVgAwJRfqEpG2frkA4vUeG85WeQkv69FjyBDOjS9kdEX3igywyMAGSbGGy3iGKRzwTAAWJ92H + gEtJMb1t56IRiLsA3PZjFk6A6xw+2Zl8xXzZoIHfAkpdvSo7hC/Pg46WDob12g5jBy35OmiMkysFe5GF + 6PAsuynpezYfcDDhcMSBYExFBkzEEoQN8LoA4CDCPSBbNMBDhswwvNC9ytjoqmDJETgb1OYoDPDCmTDg + nFI5GQvypHTxyyiHGYjZ0MEkq3N6unPOxs523HAp6icmXelw5jxinz2C+OI9e8I/6xlGbefJbvym9irw + XKPGxRV2uLLVKB0OWPInV7YxoLMGHCL5kB7JBoPqFQE7ImJEo/UQAa+jjC8VYsOhmkEZYkdK1ytDG6Lr + mmQdBngmANOAhxf16S3GykoY7hkhlSelbVu0lGxh0ryKAUCiXIKdg29bacn8WPm21QsvuzGL9it7T2Ki + krFjEAyMI8FK0ajwqPM4wRm7INn2IJ0P4FDCtsG+R0DG1qQ1seOjQwBnZxveyIAN8QxjK/LWxyojGiyn + bj6DTQcDBmFCHje8jyRZOj6H5c6ItlYMp8MHw35HFEktjIl0P2jinA4rhn+W2lfxKmA4OdtVsN2vQ0QM + ZArSADriJrIV/QMA29uc6QVC2GVsS8LVIw7oMQsOBxwg7MrYmhRxMGQjG6LvBaGOkGqzgcTTRhIKeGH3 + 7uMmj+vdu3Q4kqxSjuPoNpV+t5vcYaRwyqh/kEzzNFEslKZO7dO7bdveilf6EjgD4MFmvsyaR45cyV31 + S9mfX+dEULruOFhKl8KKFzBCMl/rFR4JvgEvnyRoICTKwbcQSS4tsg0RpICVsLNkXF3JiK0A38ZM2FWQ + LQOtMPZ6aYhNmffe+8QTxtaVAY0g8L3ZbqYQF71wIbLoyXDQOWyn6jOxTwX7+eCi0z/unD4FdsxzOXRr + m96NDZZtcWd/E/Lnth+zM+Ljj9vCVSvl0aMlN1nZdeS1l9966UrhSyBsfiQBYFCaogBpIwvZuvUm8rWX + X3r5pc5gDVkXXRR0cyRkmqySwiUAmxK/WRBji8JdlK3J4EIGdVn//v05Y7KlAty8IVVDqgDYFBqOsbhH + iigsG98gBVu0dVnw0Bi7BQF22qKh4RxQObFPn6KJIAhP3BmRV6Ayt2KjRzfm1symJEhLpwTyqyl4kgDm + gCv5tTv1hzlD5WtShJAhDZE+5gHMdzIf7QEcLOPk2KOtNV8CsEmdB+H+/Q2uKk9UBcQCmTOVg1cJAzjv + 3/2uw9lL29iKCNWrKJ46w/gC8ORxTKJRCqNIGi5nU4WNCsf16ethwOkjYLfIrbBJJjRqMedSdhpNSV/P + MzLQgOXa+5cCLsxX8ivufNJ1ACs9kxENkT4m/cVmwc2QcTpnGcFG5U26SBaT5a4Adf16hUsZXZERJuMy + InbtGHh1QQ14SA8DLHIQq4SxR8bXpEBDbVoAO4TZ4cAkmoCHD+/Do17b0gkz2kr2rIkWx0aCLSFP6VKa + jsQKThpQ205Zv1TsF5DJF4jAVQHLzvfwDQJMmqw3KUFrkgetx1jeoBkyTm5EtdVG9Z1ghbdNm2yzU+25 + hHk3vBQIG10oyeCqlrU2xK4UbLhoyx6nbXghA+uV0TXpgTFeBQFWqYtmS0cf+ueJMFGwXD9iKey3LcdH + M6cW/4yEIr10CiyX/hlFAgdM0n4BWFgBj4EEXHc4HKVbTbLjhC4kK47sCZTxo5u2pcgybucO2KQYA7LN + It2iiMWMjS5lbEVJkNGF4uNbt+7fvzUkjlrVo4dMPDLbNbqUE5ZpwoY1IInOBlMUglwBewiPm5kzmV4a + gNnO3IfBtjOro/T0pRz8/jHi8Mf01Ui6UPkB9BTG39Hgv37E6MGK969/FWoEw8unwP5uVbwR/LOQbAQw + 3gJvJbJ9qzKYkWTczlmOBdt/cmWb5QEPYCoYscEVeQHHE3Dr1jYDaCXsyPD2mGGEDa5KNwVXUSYmX7iz + JVukW8HcbmGAFypgno0AWTRPMCJJ1pQRLJZow53lGtldsIyyIH0KYcOI2S3Ki8bRR3/88bUKmIQvvfVy + FC/syOcUea7xlccdGdwQyUO3CuCQHW4wI8k4nbPsP5xRIYC7ei14+fJZswyvWDBlfOM7dBDAHQQxZXAp + 46sSmgZXJWvcKjaMuVCk1LKfMMS2MaAwwDNnSio9HFUwqqQ+3Zgi0ysXwYA7p3f+GMEWHnkEkq4pg7uk + pw9G5sicCvatlx1cOvqvf71WvDPxXAq+ZAr/bI0UkQAb0DDxsX9GwOEmbGxVDuAU40vC5CuEZQbCDuSy + srIIhHv0YFo9BInXjKohWFPAxpiPBHVTBBQBsHuOfeU7diZicE7OuKk50t2ALJrDdtjdv5QxGNEXdrx+ + 9Iii9V2Wphet79hx/fopXQZ3XLp+/eDLRi9dj+RZqNwaCJ/EqxKywXiN5BkkLhrPtF1LGcpg2WOXhgZV + 43bWsrcLi+HOFmUMyp06rVy5cvnyToJ21iydEq8qKSkRhLOEr6mDyAAHiZwtpw4VEBtc4LW7zQwu9TAM + nPNA9u0CVr6Q8B0+Tk5jjhSLY7JgxEUjYJzIqzhCA0vri3gduvVMrDhoZf3SpdJrxHM+K7lbb/W0NBtg + IRwE2CB65QzpcSTvgqfa/hYZ0yDZQ/9wwJ0gFzDYCl8ANr4EnJiYlNV8wirkXkY2SEo1sogTgAVrQKGA + 1y7sPq4ip/fwCjZFT2zbrRQpNJRe9PFS1sFFnYF3BFzzFJhux8EIwoNHD+Yl6UZfiw1LAYTcyMSYSuD1 + DJ0TvGfge5mOirEVyJ4q4g7Xd+fFK3XuSGhA5wvYXuaKbeeUrZoCgFeuFBPGVAE7UryJiXKHCWdlxYmw + kKWAISB15ibj6yjA2ZnPsJkjWTH/LcK2J2DZT2DKGwGbjxatXTguRwDzzLLsy0cVLIXw0vXpS9t2Y4MW + W9WXgu2UwYNhxMoXlgvAg4nD9rwDlIdzesdG8jHF1QjgYL4OYXmNEORKQIb3wgG2t3Et1/hyeJdH3/mO + 8R15DdCqk1YZ3yDAiSkOXsgLmErlBKCNsEcGWRRWTUFVVQF3bnRFQMyp3oIBw4RnMouGpg7noDvwncjm + ZoBFDO7GGCzXCCXbjoi560dzgvDLEWj0zyxnsLsDbtkpjbiMcErAZAUJPuIMk/cBLjvP5g6Vl3oYK94A + YOPqyjg1W6FvYHyDLFj/i/AdeQ19tDD20IXamVJSeE9xAdOCIcFKpYp0mVQFtktb6ZoUZWAxNForXqL1 + SAC7hAUw+LIlq3Q4APdB9tyNI2ZR5LJIGtF56Qj6YmRVS3v2BOTLiPuya5FADxYUusM9cdcLWIgYocb4 + ymbPdl0PAA4lbFxdCQGPjFuzZS9zZXzDXLS56e84gI2rKXm58RXAmGSlpAQBhhVrPHYAMzATqaJ2EAtN + V6Roiy7uvDyAzsur4gqBqvcO+PBwwNqSNS6HHcKoglkmdWYLFpIrtlHCIzObWtqxZ0dwxmR9x56ju/bk + ZZ0BQQHTLQtdiIB/LBeKdfJhkWCLZL+ycbAzPpXXUdKnUgLYCCvevz/gxsVnA7AR3rXL2FIwZsXbty/5 + EjAcdWIAsFEMUwCwEtaWL5WBdcVOCp1SgltUBemUipJLghpdITx8eM5kxGD2CfP44G5MrVAmofCF/XYe + MTq9qCP8M0fiwH57IjJfBisGXnb83nqt+GfYrOFVvl+76K8X/ZUFrbKBFJgxDBI2SkJuq+cNGCDO6ubo + 0l/qzVZDhB8C8ULXGOEgwMkCuC9lgBmJQTixCcCQx12Tqcw9Urgi8hUZWVUesXoAy7Ujh40a+OKKFSiC + K2C/2mk4dXhR7wdKi3qP4PBnuOl0gJ7y8Whe47cjy6HR69dfdhmjMQwX5nsr9r/sdXa5E6pzEAq8M+7C + QslAhCX0OHqcQ8hlELlaL0M5FvgceYKu8s1FbqO/vONFX7Oz6VDSn889H3Q7X9FOg+TZIr+3a7p2WikR + eCjy6Fmzysv7JZv6gW8iIQtckXhpgYyJLMQBZlxcvLhoyjy2yahGkLENElNtW3ShRxlfTGG+M2eOG6e9 + wsMf6M6r6fSeygv78shPROIpnZFboewFA44U7SmAwWEwjVcYYJ+7Zmti/A1u3FCTNL6ostiVyuOWsM6f + TsA7i5w1vob7097DLBhll4M3sgzTucveJ5KErzRogbADGPbaD+orE5PRhZJcwo6zdgELYbA1wt5UyyN3 + m3FsVMa3R9RAeGgChiWD78xxC+eCr7RG89DAqVM1yaLYn91lPdwnbA3uGVgJmfkV0MrAHOx18c0KVvgq + YNB1+ApdiNAMMN5xMC1XBhhzGyTUA6wHSwrHZkHHlhXwrf8EgEeyUIIVD+00dGhysvI1/yykFbFL2QWs + hMEWgOOYcglhAuaCRmOjGVAHbuaCcXRduK26Mr4EzCiMKYwYgMHXxnUMl4MDe2sSDRtu22UEj8BR/9xx + KRsm1/e89lb456Wg19X2ufBUeQErFEjgqn8WvqAogBl2BalsNMmKPZdoOUTEddbCFzLATvS1ne9IN56H + 7H1cudsUrkiCcCfwBWDi7cegmwLvLCsGOIhwnBdwPAHHGeAsr4eGjF8g+YJsE3TGGC1CFk37Fb5zByII + zx3XfWEOCyU5RLg3B9lxWFZn8O3YZekUtnFIwER+tX4pgDF75nX3ZWcLTVXAOYsBi5SuF2+wiNNZsEdJ + XZ5ur3Xeg28n//LzAKwSttdImiU2LISHDiVfAZxigMNdtSCGBDCmXLTVVE6anYRFkHF1FTUMBgzAY3it + MjjpFWsN8HAeRQaxmYMxeAr4QkiYaW09L2NhdOut8NKX3fo1ZFiu+ardUsLXm14JGaEldAMEsYCs2cNb + H+ZmGra8Ql7svAnEN5T3Nry2/0NlMM5d9j6ubLPyBVuZevjCih3CYYC9hAOummxtcgbAWjXDzJsJ2FZb + C2CG4YHDVgxcOLcCdZKO6eDxo32KiuwosxEj0jsO7kK2HF+G+helUcdrbx0t9kt+1jTpANZlDb4OYAUT + wOsCpXPuKLEYch6QORfkjFqjOQb3Mo6wdsR3/DwBk68XMO5DVxnioUqYSF3E5qlVgOkEY4Us1gulGuBw + xMbXSbbDABtXV7a5tTZ0UCtWjF24oqJ797kogcexCs7p07uIh6iwu7/LiKLBCLq40zUv7wnMS7teO3r9 + 0q99TfA6bc9ewNqzYIANC8tcAUyAhKsJOYIwJus5l4eVOQnLj0EzbXcUvYiA5b0/R8Agq4BBNxiwGHEw + 4BDCMlHGHsABGUdXxrdJwM6CbW6NOnjUmDHgewsz6ZlgDLwMwKVyjo5uPNCMfYRdBG/H9euvXb6+58iu + yK8uu5b++WtiwpAiBVTJn2URWwWD45xJlXyFMLFqcqVXJgJdTDl6gJGApyuSVVmi5On4YekbBErjM+L9 + OwCWNsuLL74YVEWdrmFf0sqVXHS8NJFa+0aKZtX92KYFKV6KuD3EE0ncaQahNCobVVcgG5qE2bysDEz7 + cxKsqFHDhO8YCcVaCU8G4JzePPYM/hk5Fs+KjJR5/eCe3MXLl/fsii/E6o81C3Yz6LqA1YBDACtfNUaK + CxpfFSZAgq6eDUEBi8gdUm9NtrRgeQOomYQF0vnI3seRbANfFzDVaeWqVZ1WDSVgIO5XXu7USikpuVgJ + ABaUKgMcsGmZBAiLdSO1DpGUycY0SIq2f5lQ9ShK7XfYBMbgsWMHVujxheNypvYpnZheVNSZ5jslfUqX + onT2MHS8bP3yTitnrew6suvKXVYeucbraeHgivLlb8BSKwHl4IXAcMoUYQi0gzFhK7eCFtiGuIs4a75B + KGAhrID/US5a6XoAy/LKVbt2rVoFxNdcM3RoeblDtV+73FxdBnGxZ3YfqoxvwISpMMABwrIMkJqGRXLZ + Og2VAh42RpKssQsHzuyu3Q3D+5SWwn6njADbEV2mdGHPAm2u5y42u6IgBd+ut37tWmTSglZzKjeJ1p4j + 4lUSozWYmkgX/ECY53p0bBdylrFR1014PnI7Rn5NqSF5WxI2wP+gMskBbHgprHRatUoAw4iHDl1VbibM + dJqAsUbAasKKtxHAHh9tnU9BAk/LsyMA5qYIhKPAdtQlwnfYwIUDwRhJ9OSc4b2H9+lTWsRLUIABcKxn + ooM9vBR+aNcu8oWDpgEF0isP34vUfomALGi16mgpxbteLm+Bt7fzLKVP0RNqdea5PWQLW886d9ZnCWCR + E8aN8GVGF2oEyHnK3sdRmH+W6AsvDb4iCcKr+pmX7tcOfIUwrZhYjW8EwFxJyUrJ5aMA7PQvekXAJuPr + Albk4YSjxgjgUQMxY4+SDrorBd5uE0tL101JHzyCVra+aDQK357XXrb8mk6zZq28Bg66K9s3Any9LdBa + /Yr9iohV6l0XLwErYeVKnJhw0BcJyxZswrI8CeJr8QNzTy3oIDa6/1AXLUhNlmBBxnjoUPHTYrX9+g1t + V07GzQCsK4jafDQri6ZuWL0yvMFjvCghjIlxdYU6eNiYS+ikRw3ULGvcuJmThw/PmSint+bg56VTltJt + dkSKddllXWHBMkSl60g2LxOk8PUCvuii1yz8koLUOMyCBbDhpZC6AZzaK62VPHnwGuZqw842nqVITvYR + CbBzyIEBCJVhOnfZ+zgKS7Cu+SUyLEHcySVMgSexcskFzBZqTj1yARtt0hUlcjCm9U14pXh12diKxIgj + uWipksaOugVZ9DA46LkcdDeu9/A3JxYV8eyayK+AYunoa9f3RG2E3HnWrGu+AyfNscFaHxEwTDYAmPYr + BwI4gMl2tAvY8CLYgnBnjtIkUizhXxlXsWKIa3yAFowsHm9hbgDCWwth1qN/T8L2No6+E0wXEfialUiw + lDDhgqYyhnfORX4lCyBMd02gxi/Mgm3NHpWEWwm7OFUBvMGAtVwyqh5FjZowYdRABmLEYF6ne9zMipkc + zoEUq6gIe/XUlBFdBl/Wdf2slSt3jfz6yF0rR36TAfib7LgjXj1WQcTGydfsGA/2D4uDdmxOj65kTrx0 + afr6pXD8wlBO2tOZvlk6rXSEH9u/CReZFkIzr0+ESs1+GPpu5hF4aiYh7KRal/Mc4NYxbPL0DfPWtLzP + tvcw8V8JVSZWKI5WImsWdWIWLQsEjHxr6NDkock04lxx1JgDNlTurZQ8koYPkfF13bMuKVRFyUKJc/jk + uHh2UnDJsWCT0YWQZCGLRpJFA2YQBt+c0qI+cuqGovT167GrsTfX7+rEb4Mf60gUSCtXjrwUO5XHDoqU + L2z4osCoDSf+OoAlRRZmmICnY6ZFMpJPxC2QHCrTuRvILl3PjQTPHwetN+CixZgdwPi1OYRtfs4Gbc+L + JPlHAhRCoJIJZ5hbd4OMzdq1a1YyO5aS2yGJVsAwYvKFjGOoXMAE6ZGy1mYPx2Iln5IuZAJmf6MBBk/O + dMkUNWEMgjADsPyxT7i0lOclLOoGB81hsW2XDu4J59xp5TXfAd/vkK86xWDA4qEJ2MIvAAMDR2ioFHDb + tkuXwjh5dGJbJZkux6J2Q/oM03Up83hGFfHSniUKewCbujrXUeEH4qdyZFBCZRgblz0vkuT/qI8mUZlj + vxCrbFo1a5Yh5qgdMWECBmJBq1JXHOSabakRcURmcMyVhTMDDiAmYCbStN9RrIRndh9OwBqB109Z32Xp + lMGDly+HP6IBr/w6s8aRIzl+2OUrgDX8GmD1zxZ7AxJURGcURaSIvFmOKYfYdQXrFitW8VUM2DbYz2SA + e15mp80IOr4TMihhMo6Nyp4WLv0vZsEBwLzLspAlYCZbs8rbccwOwy+pWgCmFG9w7LXFRhScTZOvTI10 + k4AvuURaOlasoIOWLFr6kVADTwHfjkvTsUt7clDKNZ0Qf7+DICzflQPEDa8XME/w7bhnVkbSiSAiIoEl + I7ykj1nocsQIx/WxY5IPEzHdN7FSfJZcPm4Ks6xwwGzd0l2PT+SxYcMSJuPYqOxprpxt+j9kGDTJkqiA + hUHzNy9g1XbZ8ZCsY7NcsC5gt+vQ6DnZ8xkVGFUNnHFxTL0MMFebAIwkmvY7QQAvXLi2IqcUIZg7Hnu0 + S8+O7GLoObLrLubOK8F318jLkWWNRDJjdCGBC4Hvax7/TA4cNg0pInITeyVldjTTZLFGvAQp6/IADVjS + LXkiXiqZtJA1KV87k4/ufEOrEjoRJBTPIHuaK2eb/ouRoOkQNsAXc8EIA/EuATxUh+4gFBtXQ+3pGw6W + oWxEASNOIlXorADTgEeNmjt3LfuCc3JKh/fukz5RAMOCB49G4IMF6w8VmTSzaKTSejqzyy9y6UoO/dpr + pEtJVYTIizAOwR1I1kxmQEdq+A1xNAHP31JaykjMs/UQtNbffA6frLCtwQNgPZglyVLp3j8jWZNQPIPs + aa64Td9dpByFr7tEh+1NsmZJmUQH3a/f0GAbJmiVgdV+YkhS56DuCBM34i55dGISkjCQFcrNBHzJhDGw + 32GogFfMXbh2IRz08N7d+rAZWk7Nt/6ypaiAV65kgsUY/M3LvwnM5Kvnq/ux98wqt3oBs6ChAYumyFke + ZIg1iXIUAbn24UlqK4CXcJHcAW9nACZoxas1MR22nOoT7+QAhq+WYlh7iT2EBUvjEopnkD3NFbfpm1Nd + jS1NVpZswehiEYiRRQ+lmxagUiydCbAtCV7IsLriI5JpCWBm2WcJ+JZLRo2ZgAzrMOx37mQY8HBeMKlz + Onfoeh7/uxLmiy+xayVKerhmfEt+bz2PEUIvZ5TQfe01Dr2Rxg1p0OjIHwksb0p6EfwzwQKocJwIhnKi + WnHOgE2msiTqoy4bvMWQIQZhumoR3lpd/9KlPYWwO6K2OUZ8DuLbU9qQRylVOjUFTbLinaVMQp0EsgpW + TZhQbaFdSgo7Imxd2adgK5YwT8wi1NREoAfefikpubls3HCaN4g3SNJ/KICBMxguFTUGgOGkV6yYu5YD + KnOGIwLzLKTCd/3S5fwK6oL4XeRbyldWqj9WwNipGnovk2umc/gNG7CAAYkarzYzZQoDrZDkqXporYKX + 4Z4nnC4t7TYRS+l9YM99JtIxw1Era1o7bNjQagM2hXenJRtgadJyCMsHvKCS7w0FAJsc4yXkQJm0q7xc + cmjlinlurizYlsB2kFXAZKukxW45lcAM+w0GHEoYBiwNHwaYC0rWFDUKWTSyrBVr4aInj5uc0xtFUjcW + SUJ46SwE3JVILXZ9HTYMvsihRTRgSZ0V76WXylia0Zddpi0QcNDSGUjA5AtCzJc7p5fSTmGvoMgLoitl + zCfaxWj68KJ6eKiP0aWrZhCGi1YpXaLVPIvt0w5h14SBWOcXirXx9QDmT562S+tVdy02LIhXKWC1Upmw + IUsWlK0BFqDumA8lnZrSr19KlvVKcMLOBy9iA+uILtqGAACna8quUCZdcsmwYcPWLpw7N2dyTs44OfUK + Q7AAnjWL7VasgC/G9xj5za67+HV5AKXx/bHiHSkD4gZ35IhpWhZjrwIR50rI6XJ93SKx3olkCKy9e/dB + USaA6TiobrYJhPU0ThBfre8jchALXzNh9dLhgMMOVrKtjcqe5kr4RgLMiXIVwFxzCA9FkQTCkmjBTZOe + tEsLRcHpEoYL5jJ+Dobe6XHqywMS+wKvBzAUBjgJG2ykJXBGADzmkkuYRC9cO3fu5JyKnD7De0/sUwQW + ALx06fLlyKuYP3e6ZtXKay7GFxQL5l6if0aBJHyxvSuMF3Cx2wEY/jMAmBPkTQAszMhOzZbXNh1eUcGu + yT6lKM6EL082j4d4/hcIgBWuJl1sWpM3hVw7lj6mAGJ+nn8EYLFYjVsCedYqAjbEQ1EHG2BrrOwXACzz + cm6j2BKSzGYvPMDWzX7AyxgsfcICOBeIHTcdAbAQPgPgCZdIUzQMGAEYgEt7I//p1rkIBtylZ08H8DUX + 71p18XdGruw6UtPQQCsH9gmPzuFguMFLpyydAu+8fikAEwKRwE8L3W7pgrCIeCeSMs/xIh3PasN8UJbk + DE4qSb3UTXskfJlnyTgQD2BJpRVT4y7atjcme1aohC4UBBhAwdcAs/712DCPcRAXLb0MKIgFrckLmOsC + GIQJOJn+uR8Bi/DzAGHrIxYnbWAdqdc+A2AkWOzvXzt3LVKs+fPFnti0ABPkrtNvgK+zStIsFMHys/66 + nBL48stfwz6hXTPmcpdP4bFLPDGLQFAcNL+JvPoOxWgLJ92nN3DmVFTw+lulsGKuw6rNjsWICVsBC1ZK + 3tREC7Z2rYAJw4YdTjr/OwK2OSS2vGqVrpAw62A3yZKOBqmWlLWsyiMQkBpZBzBgkrnEZlDFUwmYy5Et + WIslIQycABzfoQxzLBhgGvCYgQORRDMAz6/Aboa1pXeBN1zO3cYkC99gF/s92cswkoS/+fXL3V1Fvj1p + SyyIALjjFC2MiDa9cxdyQQY1saJP527D5ajyHE57V1TAXSDemo+mZ4YDkXM3ATwvzErYSLh4RU/4aDZY + uiLdQIuHAGaOB4UCvkCEja82VYqYZIkZSwOQMHbkENYef8zonocKKUBsB6skduUrzwN/BmFO2x1h90RK + v6EyCwBGSFa+oBl0SxUblmKYRRIBE3QA8ECpgueu4LUpxWPCxLBDYcC7UAGPZAfwd6RlHXy/8/WRu375 + Szkm+puX40vji6+Ef165Ent4PYpe7vuOirZ0xBQ4WGbMRVjFIsIu3x4gUWkD7Js5YDkuZxwviQcbZnQQ + 0wVd8oWndiRxG7jVoGnJFP+X46LZ9a/jO6RaMlQmt2+YHxsf3DY3KutPdm6OrLUDMIFQsDpzkZqxadYu + HkqaDFsGsuW0ytx2RAnioNqXcJNJnaM9+pXjQQBPZrpF8KyoUtolMwInpmbBWTMcpySzdmKDZWJWfGIS + 7tqFmJSIGsnMmkZMKVhHHJM1bC20UIxmeJ/5fVy+EI+NxK+WXYUskvB1xEWb5PfLNHs57BdmxZ1Ov8wp + syP8VIpwYzNGZ1CCeQ7PESMdlwOcwzENzAESDwrdcfyZjeP4bAqvmw+22ITfnl7e07FmAnYQ6/iOawk4 + hLBjlfqZmwQcLH0phJcqYEGILy5z7Bmlrps1AHOGuRDmwf6zCNPyKDDksB2O1XIAW4cT7nIcBJ4MzvTI + Ug8zv0pJ4dGn2iCdiO1xqanO0A4BrCO0NJc2rq6iOFZn1FypknTPZmMvwj3P4qfWDy6/T9gvjfga7iQB + e7Gsw8LJFz8IOmgR7UvFcDul6FgplytKUemWTua/INBxmBIlT07NGf8UrxybrNBzciZP5or6FRV8tjRe + IklwBnkAMVstxYAFMPu6wpw0Pzhka2ctvJTv7JLlPuCukWNXVu7CbiDYXeUOYZ43C7l0LgjDcgERhC30 + Ik+mx5bhPEy2ZCurJbZcDqUJJ6McBra+/RJpvrmwZXcQnowIoNUqYM50gIdZsHF1BcAD165YiyqJe1as + RABLdkVZtOkEtp3wNa65GN9UAOP7ATC2AzD5Wt4s4Vc8qSZIU0qPoepiXtWnT07FOOAVG2WGJXxJMQCU + W2wRK1iTbMxJrI0xKOM/8d85fHtKs7QgJgXpzAySsFXZlubKXiVSwCTMqCuk6eTo2LBruLpKepNIWE+a + VV7OJXYegjCh5vZlvkVn7EgGbSHmpkirNHCXw2W3yyXZxH59U/u2Q0YtoIWvRGEeQyyA3bXGAPfvz2OT + RkkzNPem7sT0des70vG6cOULASe+hIxG4peT4INoA7yzhK8B5uA5DZXsPuiD4ih9YhHMtxsCLf7FZOU6 + jj8n8cGyImFXL44pbhps9Th0sB0+TsKvaj4/Ih0C4gD/o+Clj5YsWtuzwgEbHwg/T9vWXNkLVUpY9ofs + GKxgSSbSTYjHgBQPDFXnnCxxGDPaMMumdrBGsV6HMPudCDhZAONB0mU0bkjpx1PzZElN3C+x2O0whIjT + mWLuAmaWZWRFPAiNRxfCgBdW8GAGAczzpCKBFn5KGGxXruRQSvA114SN4I1f6q6u+J2CLo1YADtCaTRR + 0iOkWqUAjBwLcRYsYa9sMQM5wBaUYsyC1KHLNeLHGjcwEAeEDymRXU1Y+MJ+rVDSbiWPiw54WOriMBet + zwrINruyFzqyb287BuJ+4vIq1klY31XOviTaMBMsN9USwgTMKpc2TLripQkYCyyOmDUzx2qX225oKv1y + FmIvLRmQhSxpkizuCpgj4ePjHRcdDrisLGrgKFRIa+XMK2rBCtg6GfBFAHXVLjbTaALhbJdAA4EvAa9b + vy49fR3u1JSJ6WxtBlRYHBJggka2DLfsGOxkOmLGW2CcW4F/DnOezKZSLgtaxT1X+Iop80KP/ID8jOlM + BD2JtFRKasYKmLFWiXgxXXwxLFg3uNJHArLNrmyzIzuY38Hc6RrJsGQjh0R3ukaOXOGoShV3j9kwiyWp + ZzUCY6W8XPiWY0UfSknJ7ZebO7Rfau5QZlkA3I+UA6dCJExJsQQwLdcCMETAQWdElMNIo9auWLF27tyF + jIU0DkCa0mUdB8nax6YD4pjQWfal8DXkAdb1s8pnLd+1XgBnky0AFwHuxCkTUUyzsbm0Tze8LRb57mQK + wOAm5gp0wFoBmrRpRSl+mRaNjEAkaNlibVHYCcPS20TAcNQWho1wRMC6yDHrYSasDwVkmx3ZVlewWHxx + mq7sDng2EGaGRTMg2WuGgqSOqgQ2Vknl5QZYyqG+Wah9QBV1Ln4JBEzTblc+tJ+2Og/NPTJ0aG5qv6FZ + xUisYMFZWf36MnNWvvHFZMp+fwGcSsD6QGTAeVGHYb9w0VqH9pkoV3UCsF1dr0G4gQu+GK6ZbPlRqFkg + C290zTUMM/jg63Jz163jeeyz161jfoaQOzFdrLd0/nxYbwXtl2VtTgUvxyQUxUTFOcOGSXEuRJjjJs8l + 6ApbU9GU+Xz+SPCeMGNlTLw8jTXw4g68PKS1K5GMHIlq3eSeiVDw0oTPLHu+K9vsSIboUEIYRsBRlivl + 6MJOsF05hhTzWdhTrH9RG7FIYvcwvTTJMoeGclkNgTA2oV5CWQysWf36pbJhI6VfuyOIwIi/iVn9slJT + EvGjQD0Ul8RBlDwpD+4gy2xa0FJlbNmI7+AeHyzmC0Wxo3/hwskVk2FuBJQOXrNmrYQJy/fgL3OVy3f5 + 8qEMNfRFmkfg46/DC8g3e102dns29z4vb86L2M8HEjZM5cwfDhvmQamc0EIrcmC8EA0WEqCEe/gw28QV + K9fnHlYnHSQ6fhKWXmL8GIF3/fqOiHfidpj0uMU6L6OnS8b3vAGLuF9kTtOV+apy7BjsHHrnoauQNdOE + YbtDEYTB0gCzQcsA06BpwgIYUTkXBVJKv765KZpFH0FyxQicBQuOo7eW6AucDmDAxbLrn+NbE3AHl6ur + qLkLUSItnJzDViQALgVg7KquFmvZBi3fYBXgivgt8B2SwbcdswehC8mFJ6AQwDm8M+4y3jLDAjoewAjM + c+mqUX/jE2ADFlboMrdysyvavP4QIAFMxOnw01IOL5VGS/t4QhjFqfEIyPiGATaOLkhbdeW+UIQ9wd0B + ojbvtEqWOiF7Zp5iAZj1LfaNtD7CR9OSOcKDoVZbrPAYDBuiFQN38lC2dQE+7FcCMrJtOuZEo8sWSTnf + Eo9kEM5xHcqw3IFnyKN3VsCt+ztnNwycJ4slEgzJjgdGdoqMGHwJWH6m+NhwSjReFSyXKQTzK37gdu2C + +WbDiUqwJF/CnTxf8DKBkvQYPybOEHQnD+8N5DrWb+3aw8j1gtlyO5/qEd7L3hwflyNAGIiBd7B71QT5 + YTqiizZucK0qW3dlHBsDbCbL0ZMUUdoGE/+PGAKNF79+DaxInIRwv3YsiMESJsysuV07oSjVLwybTxbI + 7Wi+CMMpyQIYQjKdlQrACMSpqdp2lUrbNYOF9ZbJoSvxOl6Hw+Dpl8MuCEALnjsXmQx3GGsP8tUUmh9f + fdFQfHSmhBRds7W6tUMR3i7Rg5dMGSW9EpeMPAp8CXimgMJvCtPJcL802bXI8ohXFldAuuzR5Ll8ORMv + OHtHcBUkzDZSWjARa1AR8SsEADuAIN3gykAGANvckb5bALCzTzDnPuKgWSkyrlG0MlsFwGx2ptHmzlre + SaIxDZq2rE2VMFeslCP0qhXTsJFMpQyVjTDn3L4AnJWSpZFWHDQjrws4vkNZGQCXiQXzYi5MryJc8QFJ + lpgJgiVHM07pQjMwvkwn5KMz5ipetqhKXZfMtjeEk3Yp69alGF/nqvUUfLPc54MibHXcOIZbtWG2ei+c + jMKMGdc4wbt2IZBiLm5a6SL1k3XylsSLEsx4V8XrjPZAGJafpfCVj35xKKezABwie5WJO8UhjFREwpee + v4FNHCCrZRKY4fdPR0zAKIbLCRhWkQtu7G3gY1ghYAnINOHcduxUwFb2TaBMovlmpbBRktGXEZd01V5x + 7yA+uiwenHkHX0TgPNc1O4paIY5xHHNo8Xf4OLN2IcXiR5fvwpxq1SynrnPFzsu+7RL7IsVyLv6kaFUO + 4Jy5c+cALRw0Q/BMeOCZM+fOhO9dUYHpwplrGXjxERiCA6ZrXPGIPG5SvJTEAUVsfAGYWT2HNPKzGy3g + 4tToqGR7QLRyj5oEHNgt/DFJLzCmMAFmWEQss3INuBwVzSppeTKLYOJmS5Y0VSHkMgrjj4Tb5bIN2urg + 8pTcXCmNkDnjj/lVfBLzKVRBGmvl3qEMcwPcPx7uOTJgxERYBhKsdDljA3fULrZRydfghJ9+1SzyFJXj + zqRAPjYApyYlJaWmBgij+FXCBnjyfMTbCgQBZs0wZAVoZ1xbu+KwZvFzDx+WIAzSa+diI7Npgw3xF2ji + W0vZxJqJjZYcEd+xy3JU47tIl6fKQKEuP1ACMzCNS7AGdLFxVdlzAiJdTu0/rOQ/xF5aOWsXcqxORCYB + WDqE2PrMHSYBmC4bgFHr0oRzs3JTkoEUgI8go2L0FaIokuGqJb3ql5raty8BF6eytTmxAyJwfHEZg7A4 + ZbVb8C7WJQUcekJ4AB5Ox1dRysNFnXF28HUAK2wxZcoMh4IfYqdOybOSr+lEz5zYbvms9bPW5TYgSmRl + JcWllmXjLzu7LE/ogi1qo/k6oSeeP3/OnDkIofTXAA5+WJmDIgjOee1NAwYcPjwAPLFI0oCLZ6vYk7l2 + LRZgwfigk/XtKbZa4j8yBqMGFvdMuPi4YlZcpgRzQHSxBiuyBCyqZ322ldEXf/1i82nalK3NV9xEM8Z/ + YzfS8k7LURHRCJCaSEO0iNA7DdXRldhzoIg5ils16PJUPACkHA2dyHYrGAwyqKSkxPjUpL4wHhLWPJr3 + 1NSy4vg4pFdlxXJ1LWZa4N06r0OHvDzM+rcOjcJR3P0MwABsrk6DmUQaxmD8Ijn0IJmN6MvhBGG/ffv2 + Q3W3a9b6XLDFf8/KSm2gYMMNYsDY92plOaVuEStBFKVRTsVh1L9gDZBrJ08WK6a1IuaC7QCaLsPvZIZg + bhhwE0UXzZfLx8XvhWVYaWlDg44BwOeGLe1atRK/SLqdgC6WTAsyfk1KidpraMPmygXnNd/5Jt9v5KWX + ch2y06ARMQwD09x2fbGvkEexkZLpCq1acmZmXToilj4aubJUxuWofwm/L1s1khL7JsXBWkA2Fb+BpHVJ + WQHAHSTdik8lYDpmFzD/8uIdwMGn9wdgASB8FTBswQCv6nTxxavgclipwS7YFD10KBvRBTjH7/PifFmS + FBBvaSmqLNqVCjh1fAZ7CkCaaCaPmzkTW2bKdAXc9EyJvHMHDhyo+RRP9DNw4NphKw5zbcUw1Sj2eBE7 + /vBCeUfpi1zPa9zqkjDWfS0nkJRK+JvhyVPQSgTpWLPLL5duJD7dDbzy02FbJbm6F+NAhgX98mJ665Xw + 2bqzGHnZ3rFrlkTkcgRmWCtjsoK2bRDsexXH9cCRo/hFGtYutyFlaHKDJluIyzxvEnsJGYQDgBGOO5T1 + Z+ukAQZc3nmRjiAJYGbQE5XvrK42rkwsGEn/Kn6YfjyDGySbtaLDrxPlUXw2vEZqNvCSrRxfZCKG4RxP + J2QRPWdWzOz+wLiKFTPHdh9bQZZjxw4kxIFjX8TCz7mETWMHDuQB6bjraXB5vnJKDn104zHfX+r2tiPs + 6DQZqEvG4oFYB1i7tLUpN1sc762Xir/0UmkHg+3DV4tfB2N6ZcutZJcwCtB3SBsHEwBCE6PAlCvccuRI + uU5BGHF3VT95lj6Xc0oAYwLTzs0dOqsBPwgDTPOVFqwOjMepxR3i4J8JuLiMjc8slwwwmznkCh0eyFFI + cEvh7NInsgV6PXN6fnb9xbJ2l0+hgNkNhq0cW1TeDnxTkrLj4yW7WraMURGabJ0E8MAIuQyiWJwzd7KU + PYy3K9bCQPUaAgOHjZmgFxMYRSvlFp6ta8WEwyt4Nom1eN5awytd1ioBDNGKpY+qNy860Llb5ynSjM5m + OFdsm3ZE2JRQNGuNIM9BsdRr6qtFRPxLeGgWRhT2EBgx6GMPMY4xD4Zxqo0y3SJmPBGZFJ4GwCAstouH + xWzMkrFzEfEEcG5yw6zl4OzYrwu4dZIALkailUrA8WCbl2eAOyhgJtEheJlkMR0VwOvWIcFSwqSLP/zz + TrBg7Zamdxa75vAEfIoUOQtM0rJlgcuXC2IS5V0SozmYc8tNEmXnMmVei8SZGjBgAGeEK3RlaczhYQNu + 4mZOkHwNGMCHMXOrJenaROHFpg58bn54FnhF6QG6nbrixl/pSNy4QHGZt++w6cNoRpJw1UUDq9qlIfmX + CPRkrIRJDzuHTRhsiII37UvM7DaykCvHJEkYxnJqVgrLp3IUUEiWZYxdOXIbAk4uh3tGjg3fnJySilyb + o93hnFOzkrJQJKEcQgXcobg4K46ZNACXdWhdVta6Nbx0cXGHYgXcIxJgxEXspD6l2EHYNwAsjlhE6+UX + AVxMmUdgR7HchE+aJYBRAyMCIOJTyhh3OH1Mhwyp4oWaEAIkkSZzAkfmhOlNTJ9umjxH5yQqCdXcuZJR + 3TTALkAPETKSbD5KPUzITBvm99HfZMOxY9ijx47w185ouJIAzkPKlsmWbfAKERnOX3YOdwwE68UEOwoW + KybMFCsFmRZy4r7JyIqBsW/fFB4nyK7duEQ8wDF0kiAjr0pJbtcOWQ9elZiELCspmUaTjTSL2TTJpgIw + fCQIouothvkK4NbxhNu/desyAoYtK+AePaq8eLn/oyrGDWePbYMDeKh068OA5fSp5bnCF4DxO5M0C3wJ + GB4FKRaiMGtg4oUdlzU00IqV8JCqKiwP2YNlpkWYHgZkTFACMT2eexPmwEaec+cOQPosHZditZTxDQH8 + MH4DkGVaSAyZORjaIBmRs5cD+OIQwD++/Ou/ZOPnd9gBTMZ26iT+M6Za7CLE3smlC4SPS17OWikZhsgm + PxonsutEJMXSggXEcL1JAri8XAFzgA4AJ2eXZaNQSiyLS5KLDafmogp2ANNHE3Be67g8BYz6SAHDPQtg + b5kkgHuzFZptusK3PBd0mUFoAMZPE3/8ia66mNx3oTZazsFZu5Yn5+auyy1avzRdYq+IhuVKvDQmskIg + c8ctrDgsnpZ5M22WK3DTSJmhYcyThx0+fHOIxkCClxPOtYnLzaaBmOM6urBPmFnEyl12C5GF4JHOBa8a + uV3K4yWZQTPisiD+5Ws8SkeqXw7yX6nzlTxTCd8VuLE3Vl4zElP8/peTN4SHZL6qE1fwM8BvcOVK7N5c + uHislKOEYibTb2g5u9u5s2fNktYvgO7LFqzEuDg5KfiR8napDfHZZcuyW/cHYARgWC8cdl4HvUx8nF4f + Kx4TsvW6Z/IdEsVhbWyGhgGLaZIjpY4ZsYN+CBO2erDvHz561y5Wy8nr1u/du/cT3PfuPdWU/vxnTt58 + 889YcvWmzYOE5+itCen7njrFf//fkBx+fhbikZERtBPCDI/b0z6R59qKzjz6Je7YBboi2vsJhImTnuHj + wZ1gAsC7dsmKkOfEZniWrOyCGyhfBfpMuHNzkZRBW4/kHmmA1wbgsvjWxR1gwQoY1tsaNosMmoBZIZGu + XMNQRbwzZhCwJCmIZyjbxHjhfjoNZZub1nQATN4ELJE4dxeK5XXrUnKBd+crh1y9ciZ9gD/oFT4Ls8bF + Z3llmxuV/XNXb10A8X1+Dz322GPPct483XGHLTi6Hfr97X/60+1Y/JP+fqDbb//xj370yx8rfpWt/Buk + S6tW4U+rqCP4a8iKhwUvQ6ErMZh5M7w0i6IeeR3omwm4RzBgMV8oisdqKmBmx0O1IYgNfW4LB7Mu+mya + 9Sy4Fhhwx+XrssF356F9j28XlZTwfp56/HFbCNL5v+9Za+O+ffsWOHrurPUIhR+Hib8TTD26HcxJ/0fQ + 7fgF/EmWfkTA/wbMJC20qVW/vKYcYbisNQB3aI3sKo9VEc1XASP+AnAP6QjmJQsVrwt4BgBLPxJyLGRP + tFUSJt9VjBCskDrJRuJlTY/wsXz9etYkez85tK+koFV7R62w6K61Us1zNrTClpYtW0b7uIGPYGUe1bJl + bDQVGxuLu27zKgHCc90HEhIGJSTgybHz5rUqgGwz3if8tV6tDpFtDlOr1asXb9+4ceNslVGmFokepEDx + wQdfcKVAnxaRLGbPPkTRqu9QYU6moqugH4EroN6HP+iH1O9Ed0E/+MG/ewQ7S4ynBXsA98dfDwJmCMYi + JdekDNiuKkqONwPf3HWz6I3phKWhHvbbDsaLu3jma3aRLvKEI+XLl5Nvau7enftKNkxaskVVWVm5ZAkm + HnF9jSnw4Bq9rVnj8/nWTEpbYuJDS3CLLsiQW6zeov3+Nn5/rD82Ixp7v6AgehKfPIlvDvl8MnOEzZUJ + /gS/qK4ujarTNb/8iqKj3RfURVb7Jfho+zd+ZnAVqiOB64IVQ6WEKK1UCB9VAa+Avf32gwevOqh3V2Tq + YP0hiap+QD0F/ZSTl19++affh55//kh5Vof+AEysHfLK4vuXuYB5AeEzAWYMJmCWlMkKWIRFNrTAgtnO + 4gLGHRY8C0/OhoveuXFx/hbZi2kJCXX+XjG9EmznQhmx/kGDBrXJoMX6YLCxwBQbm9CrVfuWrVq28rfy + weZod/66hLQY3BLSEupw88e20hufhVtLefeWCS39NOOW81rRohN6QTRs3OXfQ8ZtEraLYmJiZDvmwZKt + Z9CSVvO2b5y9Kdh+vYCVMKdYfMQ4A66ZsMjwmsWqzQKykIb1mtX+7of/9m9qtrRbwQsRLhiD7/PPEzAJ + FxeXuYD7xyPkCmAmWXTRAA3EeQLYwJokySJgIKOHVoHj0KG5cM5EzLEK2HYNZruQ0ucORX43a1ZK6vL1 + e3duAuAlkybV1bVp02bQIO70lvNgQSLAhAYVtIQ7hh9t6Sugt+0lmCjxqfCwsa0IPsMX0zIh1t8qoWVs + e73Bp8ttEtS+fWysT72+D29PvL1iYwvm0T/XGVkz2Bj+1yDhx8EbvTpFb8BbTMuIt5i0unkBwC7iRYsc + Y1bn/OCDgArIjzwtbEVmwQ+J9R4lYKMreGUCwvDJ5EvTJVgDbHSfeioAGISV7/W3PX8ktQPslliLCRgF + EgC3dgDLVWUjAuYVwHP6TJyYnb1ueTnosbEcxTpstvwIW2cEN3w2KFuT1qzypBQ+MTeXOdbG7fu3VMIL + LsFdTEoYOBJDtmWVH7cwuSjlBvFZRC03V/JuEPjaFpXf8cGQbRLZprB/KBnBGZTmn7d6u4MXMr4CmHBN + AQdt6RTZPvushl6KBuwiVrgQ6XqiLkS6KmXs8v3p93GHGcOAtx5JLUbdC/MtLo7Ly2MbJS2YSVY8XLOn + e5+XeFcfDbZPUFHz54OwlEjQypVsFoWvLs91AAt0Il41C9uTU5KS8FMoZ8sgk+iNi30JtKG0Ouz3li2b + 3H1Ny7gEwaJsc6PbHdlmZ3vTREMEwIu9gB3CCtghjAhMPx3gC8BevI0AVr5BgEE4AmCwNXkAFxNwfAAw + YzABSyx2Yq8zF7oQAM9nAM7liJeVACy91MmrZkmmhYSLZo08i52b2N4uN4mnfYGys4tQBh/aWNgyui4N + JqyAz5+wgfnnAWxeWt2zQ5h0qb8XYCMsLloAb6UFszvJA5iWy+ZJk4JVmfk+8fDDAcAIwQqYZ3liaqW9 + DuQsQpU8i21toqzs7OzSU6f2/vb9knm+2DT4aSlmmuECm5LxuVBCTD87nQmwEFbEkQEDsUP5HAE/5bVg + 4fttAVxfLGG3OLUDkirkzcysREYXMrZ0zo5/VsD00E6KtZIH1fBoGrdPSTNrPMxmFQ7sNb7LsueXFp1a + uvMl1JSt1iDD+d8A2GPDlBfwYwoYOjfAghd0PYCFrwMYRosCuBh2XBYRsNF1+BpgumgJwWyIJmEDzPAr + TZaBbrFkBQwBMOyXQ+zWpRftfatw9ep5vva+tDTmxucP2IqZsGzYNje63ZFtdrafdVrQNGBPpuUF/JgX + 7xkBk68D+C4nyQoHrHwdwEic+7cG4LK8MmvIAlyXb5WbPQfjBeCJffpks6cQgFXJCMJMrwQwj3eFd+bg + MWBnZzUB4wexriG1oSEpu2HvByWrF9OGpW3qywLY0KpcwLgHAQ5Kss4M+E9/CvD1Ar6LgIWw8RW4vBte + 6DYCZlXUv3VZXnwZbDdv2bKqZT16LOuBuQIeMsP4CmBjC8FF86yCLt9du2i9s5AuD101VAFrvz+HCQGw + jgNUwLkNW1NTG/a+EQL4fAkbmH9SwNI0rXgV8GN/d8Dfvu02AQyc8f0JeJkCzgPgHs0ADBcNXBz3XD6L + HdY0YGTRq+Cb2cLBDgbpy4Zjdi0Y3jk7O3UrjLj+mADe3/6CATY+F0oXzEVDQQbMudeELcmCvIAVMeGK + AnwdF/27uwJ4BbBAtkZK6vrvE3AxmA5ZtkysF389qmC8QrYK3pntG3sUr3EVPSyK0hAs54GB4fIcmrMw + h/0KXCmBWSBxIKjApQRwUkM9CMNFLw4CbPvpnGVgLpT+XoBf4F34KmBt5gDdMwEWvsGAYcLhgJ1WaEoB + pxpg0jXAylcADxkCwDNoxcYWUrwAPFEAp3BcWDLHlrCZgzLALJeUfjsZFdagfOfPH5K9rKGUSdbiwtUt + 92PHXKAky8BcKJ0/YGNLH+3h6xRJAb5WB4cADjfgIMDGNwgw8IYDLhPAVWTM0MvOQY55m1ElsyEz1IKf + eNjwegEjxVoHdrk86IiH04hguJho/qyEOZKIhHPlQCSOvJpflH5q786NqwvntcxkS8cF8dD/pGUSM2gB + LHjPEbCHr+IlYFUAMONvCOC/bD2CyOsCRuSVqSCF1TL8igVHcNAAXIpqZx3sloAD9gvjlV4kZtAAj4eA + loCzOM5dDzPLOXXqk537NszztUoDYOzLLzFgRezyBWBl7OELwAQbBJh4z+ygVV6+YsEu329f/+1vK+D5 + Q+YHAA9Z5rZJimY8gYmhVRlfA0zjLZfjFbyAhS+cswCmaL8MvyScM7/01Kuv7CspaOmrS6sE4AvUVGlg + LpQuWAwOBaw6R8DGtxmAr/cAFgtGfSTW7PYqUMibQ/gGAAOWWDCSqHZykJkg7tSpnIA7SQksfHlmgdzU + XB4LLGG4ovTUb9/aWLK/vR/u2W2Ltr10HjIwF0rnC3iBk2MJYMPr4UvAgjcSYC9fxRsE2Og6fBVvaAh2 + ACPrAV3URQbY2y84o0qQClhHxpeAGYNTyvshCoNvO/hlsWEH8Co9P0x5gxw0k5LsAF5XeurQpsVrtmyp + q0tjb5J0wDdrb3o6B3ELlYG5UGppb9tshVow2UYCLPEXCgVscg3Y+DYDsEOYMdgBfD1EwA0KWIx4iCwI + YIcyK1/wfdjDWPF+97tRPP/Rur6JWXqRn2Rteoau4ZlXOnXqxCMzeCyzRGG2cUxMVxedvvfQRgCG8UJS + IzEEN4kY5VTQzTa7MjAXSmcN2N8yDLDglUkgywJjh6+HsOZZToblNWAoDHCoi3b4Sjuli/j7ArjB+IKu + LBhZR0LUsWFlS7oQAScJYB4p088d1bEKfDHlqI6hcrA6IrAQJt3s7GXsadi5cXvlFo7ZIVhHtp8alf4U + XH0xANN8acEuXseGha8DmIQ9fEMAK99gwEbYy9cINwY4TwHPMbAmwjUF+A5QwDBgAtaTY/ZzRnEArc1l + uwAWwpJkpSrgQyWFlbRgHUxjsv3UqL5ggAWvA9jgQpH4ugbs5RvRRRtd14Ij8HXlAubhQAQspOcoYk7m + zJljREMkfAEYITgxUc9+2q+fa8AuYD3IUQDDSac2COAyAD6191BJwZYtSwysI9tPjeqLBdhjvpDRhbwO + +twBN8o3ImDNowF4zpyKAGD8GVCVa8FqwANowYkEzBiMBJqtVxSirzR2DOVRkLRgnjEJgFOz4wUwDPiP + rzy+AR7awAotyPZTo/qnB5zgAUy+HgftuGhLoIP4uni9ARgyvl4PbXgNsOBt3IADgOcoYJjvnCeI92HS + fRh/ETXguyQ8AICTwDeRGTKPSedxUAHAJIziiUm0HBKHEJzKQ75Ty+bDgv/70OMb2lQSkgO4OQ0dXzjA + hndBMGDHgJ2xlAJY+EYGHMAbasBNAZYyCVk0AM8ZsqxqzrKKIWcCLHbrCoBTk3h6l779eFSypM3CFzUS + zXfoLGwHYCmRqJQkO6YfMfi/d77/0oYNPBgAWNO4M0nY9lOj+iIBDuCFwuxX+LqjoUP4hgBWvsEZVlAr + dBBggwt9WwFvJeDJCMND9syZX0ELnjPnpocf5oRzrxywsN/vcRalR6nSEc9KJlQH8KxVcNjsZQgGnOie + 9azo2KlXD71UwmNAwJeDsprTlBXCN4ywDmy/cAr/BZ1ZrUIAe/yz4g3wVcAml++ZAAvfswIsZbABhgXP + ydmT4wF8UxhgxUvAmMjB1VFJWVlZPFQZfniWS1e9s7RqsX2rXbu+yTzby7rkJG2KFh07tvePr/6qZPX+ + ee3bL1mSluCXlg7x12eQcXVlm10ZmAul8H9wZrVMCDR0kC/l9CQ5fBUv+OLPw9cI28FIivdP0tFPheKF + vB2FAcAvu4hJFyZ8222OBc/JydkzhwfQEzHtFwk0bjcN8ED2AKYBw4LBNwX51axyHsDvBZzMRsqhUh87 + gNe5gJflZZc1nDrG3qTF83wCeJCf4ydsRzUq4+rKNrsyMBdK5wHY8JoNh8ZfMWBPAFa64KuAla8LONx+ + oQiAvfYLti7gPAKeDAuuMMBzXcBPzLnpuwZYE2cqBHC7djJgh5GX49wl+rIFmmLxxJNOJKZkJSUmJTUI + 37IytnuXNRw79slbi1evXtM+DYDbwIS/jICJmPariF2+HsDg6xIO4UvA4p7DAYe7aOIN+OdQwDyhjQJm + 6TuHDprzAXMe/i7pClivBgzgGRKiUrNS+hLw0EAjlhDWTgbhyyaOlL4pSVBqA0y4oaGBI/v6V+Xl1R97 + pYSAYcH+NoN6IaWxHdWojKsr2+zKwFwonTtgRcuGaLNfx0UrXQ9gL1/BG2rAkQGH8Q2PvwTMMVkAnMMz + Fk2ePHeyF/BNsF+YrwAOIczzmyjgVF7nhadP0rM/CV1M2HXIXiQ5vzEBJyZl0UELXwKWcSNDTr3x+OLV + cNGVaf5Bg5izhhE8SxmYCyV71+YLgOXYJOEr7hnWSwleOeiMfJ3BdobXAWx83QjshGCXb0iKZYBdvB7C + NF4v4AoBPIeAef4a0uX5iBiADz9MZ6wyvgBMvAScm8UIzHOrrIR/ZnkEyoJWAPPct33bJQpg4ZtaVga+ + HJ67bNn8OadefXz74lbtKyvTeIBhwpcMMPkaYOMbBtj4ni1g46uAhW8Y4CALzpk8d+4cXuLZjcEK+DBu + BlgpG9+ABedKEr1czv7HU+PSfjmyUviCcF9aLyIw4q+M5uD5t3jSJFhx9vz5k099ULJ9ccv2lWkC2P+/ + BDDIKmCXrwA2usYXeENSrB/+0AHsHK8ifIMAG14nBHsBwz8TMEDfFAJY0IpcuK4Fp0gSvXw5cmhEYQOM + jMsB3I6nOOYZhHlaaGRYHVovE8DrGhrmz88pPXVo8eL9BpiH4q/R3XQmWRzmTMIeqk8U0e3b8xgYaTC5 + oJL/1XwlhLtoJWx8QyzYicBmwcbXa8A/uuo+x3gJVwE7hzN4DFjxOoA1vQpYcEPOfJ5Ejn8EzBw6AHhA + ALCihZQuFNWQhSwqJXl5sp7ojKcPhouexR5g8pWjVdhMmZyYtI7nPeN4rOyGZcvqs5fl3FRx6tWSgnkt + W8bExPCwbO7PJm4JV0Zz+Eeb2LQt7X37W7VfsyQtv3LLks3TatZs37598ZotF57wWd0SYpBklYQVSZ6+ + fveYfs2wRA5gyAjTcAMGbIAd/6xwqXDAwT4adwFcL2cKhGemCPjwnAFzEX6Bl4HYzhc3AKiD6EJRyLGQ + RaPeZWWEOy2YB5t5ALMFC4DBd102zwk9nyenzMtuyKl48z/e2hCthxDY7mxSLSYt2ZJWV1dXmRkzb/dn + j8+7O61yy5bKQZvXbN+3b+PiLRce8FkqplVEwG5PkqcZywvY8AYDFrwXBHCDnlhOAB9WwHO9gG8OADaw + jqLooAUweQIwE2kmWaoAYF5eJYldwRBPSLms4dip//7khZLVftJtPuA2AIyiKm1L/t0v/e1//vD+hul3 + J7xe+fr0x199772/fZZf+U8K2GPB4YA99usFbHIicATAwjcEsOF1g7Djosl3ztyKOWB7EwDfNPemmx5m + Fh1kwVr7BnTddVGsgQBXASc7gJ2GDrA3wImJ7sU39OyyRcc+ObRv0/ZWhBt2WHbjqps0qXIJT82zZPOG + V957+7cbCu6OGhRVueGlP7739vuFvT5vvgkJwYAdvgY4qJnD8AYBNr4hgIP5hgAWviExmN3AXsB5Bvjh + JwCYWdZhnrf14YdvgqMGYJqwAA3hS8DMnwSuEQ4GTBt2ACcFAZ4vQ3b257cS2w0/8r4xtdm8eXrU6wR8 + 94aXfvPeH3+1OjpzUIuMDb997+1XSuYVyqlbPlcFATa+YQ7aCzg0AEuC5Zx0heYb6qFdwMI3ImBFq1LA + wnfOkABgnsIVmjtXTuBqQAO6zhTVrq/EYAHMKKyAZVkkgFEqsU5SB60GPB8JdMn+NWvSYgD3LGx4UtTm + zZsnAXBa/obHX3n7vVcfb7mkbnPh42+/95v3p8Ndf94KdtFhfD0e2vg2BlgIR+QbBFjxuoAdvoi+Shd8 + vYAfRrFEwHMHADDICulw1+wBnAuw7VLk6ok0205OkuU6aQAmXwDOYpm0DFUS+c7PIeBpbXrxhEnND8Fp + lZUtNreBi65cEz1v8+Ov/s/brxRs2RKNCPz2K48PSsjMtOd9bgoCTLjs6Te+AQNmBFbCbonk5lcBwII3 + HHCERg4HsPKlczYbdgFL+xUmBngOgu+A5gFOSU5O4aW2ALgTAIMwAZeHAE6EiwbgVAJGkbRs/mRa8LxB + 03v5o6N5MK7tn6aUtmXLpEEEnOZL8+3Y8P7/vPcfj6/JL/jVe2//8fENd7eJOYto/vdRKGBMBDDvwXwF + sIevCxhwIwE2vJFaKUMMOAxwcd4Q1r3UYQE8Z7ICRhmsnrpxwEiieSEYEaxXDVgsmIjblbOpI2C/dM95 + KJWWDZk//NQrJaun390L3jkmxh9t+6cpAbA/ATn0kkm+mFb5rTb8DZa7oX0JUuj3p9f1qsz850qyaMGe + Vo5wAw7Q9SRYYsF/kirJw9cIu20cBhhy+SpepFeuwPfbtz0PC15G6yVinicf/hmYJX8OyLjKxKMo8HUB + K2EFrFGYQ/FCAWenYrJsTgUseHvhZgXcbMtLW7KkDSZblvQalNE+f828lxB7X9rwPmNxQWXakso19rzP + T+cH+HYHsOqcAHsTLC9gcdLOVQ9ExlakfMMBI8fixRIhh7EDGIJ/Zp0MwEmJcfHxzKPLylLLynh825vH + DpUs3r+mJdieTUNHVJvNg3gw06CEwoJ5+1eX/Pa99377/m/ee/tXG9ZUojyeZE/7/OQBTL4EHJEvAHv9 + syfBgpw2Di9h4RvSSkm5Htr4GlsI3hn35wk4Z+4cuQDcTWzrWLtwLXLnILwCmEBD+HoBkzBdswLmKopg + HjPaLiUrKzUxSQDLNZJgwEOGlB7buW/74v0tgfZsACPFasODXSb1Kiws2LDh8V/963t//D9vv/1/H99Q + 4FtSh3z885YAFvttyoDD+bqADS8BG9wAXwFscC0Ee8bpeACDL/X8ka319Tm8CIJ4aQU8wHN5C5OQDeUb + AOxYrAO4nM4Z63ThiXDPCjie3cFlCMEzhmQXvbbz0Mbt85Rvs8HUyZkPIf/0wpfef//9/wu6b7/39v/F + 4q9qfP7PH3AsAcvxZs+dyYCVbwQDZifSn9SCab5KWOk2xvepl18GYuPrADa8CrhCAAOqXKEGM8yFqoey + AlasASEGqwRwchBgacfq164vDTg1SVx0fCrH7JTlDenRI7vh2LE/Htq0WIqk5gNmgrXk9bq0JZmxhR/8 + AXr7vff+6733uPS36v0ZIaca/cfLHztvdclncrBZ04ANLhUAHOhlIGEzYNPv7moEsPeY72C+XsAAK5cz + GYCpor1pgNMMrU46HDAzqADggIsmYDppBOAsSq6MyEskIdHKq+dxqnv2HP753kMlGaDrb35LFs/s3GZz + m7ot+Vt8tcT6hz+8918/+SPnJ6vX+KRL6vNUAPBzBjgi31APLYDJ1wGsfYXBgAk3Et8zAX4egBs8FkwT + RmVklnvTTaCqi7yGWKh/hgywJNAhgLHaL7md0kUVHE++qWVJ2WUNWxGF9wzZs2fAgFO/KSnkWb0BWDoL + m+6wh3Ou27x58+tbKitbbngcMfjx9//w3v/71a9eevzxl/a3//zLJACmi3YAuwbM4dCUMxpLPTTP/K0S + C77jKCCDLWIw0+mrfqQneNczvNN+QZmAoeMhfBGFPYBB1hA/v/XIkYaKislybUBXWvsOQCQecPOwAXaD + IgBGhOU1ukTLly8fOgtwNYdmR3C7dryADxs5pExCkrUsb+vW3KRlTzxRsadi+PyGYx8UbljdslKGzSa0 + bNWqfVOEeR7pQYNoyJOmbwDUlx7/1R/f/j/vP/4SVpBIf/7dhS1hwYjBml4t0sszPAfrBdwDB2YvAmBS + Bt87Hnr2oQMHeA5/nv77Iedc/gf/BDO+6uDRTbPfOHjw6aNvvHH0jaOYvnHwqrv+7a777jt+/Hc/OH78 + +B2P3feDp17+9+PgzAO+v88sywEsYEH5L395+diRBrnsFC80NXCg0XVFpAGNuXnCdWMcwjdcd4Mqikcm + eQAv9wLO9QJuaOAFbVN75DUcSS0b8sSeioqK+cvq33y1ZMPqVgaYl+BoAjAHciAvS0urXNKr8LMP/gb9 + 5u23//gbLnzwme/z7w/uFQTYbJcDOR584cFFn5VseuSxAwdA+OlnH3v2sYeeXoRfAM36kaeP4nGeRPrB + h8D34ME3Fm0vOXD06OxNFKouLDz3JwA+ePSxq3563/F3nltw8PgPfvpvv3/sOEokAL4+HPD3Xz4G5eQs + 1Ct7AjCv0qmUR/GSuwbWES8hNsZ10sY3BDB9tIhrSKERiPsmxklPEgGDb1leWW5u2Yx7792TU5ozZMie + N/9Wsnh1KybGzQfcchAIV9b12nD604+QZL399n8hj/6f/2Hn8KDP3UUDsGTRDmDcX3gQd+BTwE8fOMBT + +cOEH3v6hU0lm3gZnk2bDiwqIUgsPULAbxwA0QVPH32BYXzTpkUPzl703GPwzve9c2DTg+8cfOed2QsO + /vC+40dnzzbAHguGjwbgv9x2G/nSeBl+wdgutUu+c4etUL68EK8jAfzkJTdfd+ONHsQCGJWSAHb5EjBT + aAHMhmheajyVkIE5t6HqiXvvHQLzHTKk6tirJQWrfUvSltT5ByXENgtwbOwgv78uLa3X9N21H7zyyv/9 + 7R/f/tf/K5fLenx6m889iw4CDPvlZNGC2QvUCrdvWoCljaiTn3v6oaefXrB94759L23cB8Cfbd+44IUH + 9+3b9OAdt99x8I23Ni1aNHsBPDO0YPbRd954542Dx3/3u+PvvPHZpgPvvHN09oJ3jh9/Z8HGNwgYaP/d + AEsztAbhrccQex3AUBDgYcbXIcwrLruAwyyYtbACDlgwM2sohQMqxYKzkpLYyLEut6EefO9dlj1kzxMA + /MqGefP2w4ABeJC/GYB5gQ0A9qelJRRMn75hw4bpL/3mvd++VLJ4XkFhNELw5+6i5wHwZwHAPGfhAvW0 + ImLmZMFjR59+etH2zw4wvi6CBW96CwH4IRjo0atgwBtnY+vGtwTw7NlvvPPOG28c/yFc9BtvHEBwfmfR + 7AffeQfWPPud43eJBX/f+Dr9DH/ZyoFYljxrBFa+4qIxV6wuYMULwI6PNr43RAEf+WqfsEsYEVj5AjB/ + AYlJqQBchiJ4XUN9Pc+6tWzZE3uq6o/t3bd63jwfL8uBndMMwBw57ee1rfCCzMLCDY8XFr70h/959fGS + /DVrePmlfybADMAiWPDsRcisIbjqRZ/NXnTgOVrwUQKGyz6wgIAfPHoUqVbJg8iaj8KQD7xxYN8+PLYI + vwi+1wsHf3jX8dufW7AAbgBem20pszfNXvDczrt++pTE4ADf66/nEYXgC7AMwDDiuQPtYtlBgD0i3Usu + GfPkddc9+SQmLuSoOOXLcR1AjCzaAOtBZykp/fAIMu0kOGjWwDDi+nrQXVbFPOvYJztLeD7wOjmnvwDW + 3dS42rfXmhk+2h9bML2wwACvEcCvv/55u+iEEMASgxctOkCqLxxA+vyILCJ7Rv68CN589sYSIDvwGQHf + fvvT2z87evDoWxv3PTj7wQ8OPHcAJGnwtPuD9xEw3o+IFwA0Jlh9jCb8fRqxOWgKgMF3JsyWPGG/SpWA + w+AaWtwh0KWMMBA7gFNyZeQO02gFzMNGeVSDA7hvcnZD2bqkvPr6qjxe9bt+zxMVPLhwcUHhvNi0zDqx + PMRW2UlnEK9FxnnMJF9aQsagXr0GPf6H//lgw4b2a9iZ9HqbfzbAvPoVAW/a9Jlky488AmOdfUCO7D8A + wHDYALz9s8+2Lzp68ODtjwDwHQf2bTrwxqbZH7zxxjvwxyIsHEQRfPDgcWRYJzZuUv/8DgLx8eM0XgVs + eM2AFy6EWzbAIKyAQ/BibcwED2AjbHwJmEctZFlzFjy0VEra1UC0AMzrWmclJieXNSSty66vz6vPA16Y + ccWbp357aONiOQCcbcvYN4DTpIfVZya0ZJ5VB9b502uqa18q9C9ZEstz5vHqaZ+rxEWLO4Z1PWdHnMFL + fwaqSJ5pwbM3LUKZ9PSzDx1dwBh8VFz0Z5teOHrHn25/jBb84KZFiMDbP3vnKDAz6iKtAuC7fgi6BPxZ + CTbIlHyP//Spn14vgIGW6dX1f3n+yBEzYDFhzoyu4nXmFNA6cCkFTDkuOisrCyYKd2xR2Cw4OVn8tpyY + o10/mHAZG7Hq8/Ly+i9bVlZfX1906rfvb1wMvPMkJ7b906QEMI8haIUXYfnKXr3uzp/eC2n4oEHY8vkD + 1iyagEmXgNmA9SDCJqqjZx977DECloash44uKvkMmZUkWV7AR19AVnXgswOw3ADgTVfddfwqNoM9uGhj + yYIXXnhu36Z9hx557rHH/nT8qadovgqYFRIAN7xpfCMC9oi2GxkwzRiAyTclkfEWPtn4Gl7mVym5R47k + JiejSGIQrq8vK05tvWxIVX1D/am9hx7f0KLS39LfipeVs/3TZJljgHlmDwJOy49K8E/f7MtM82/e3CYt + 4XNviw4BDD0irVgvIFV6gY2UKH43vfD0Q8/+/vfPPr2oZOOBRZ8dgP8WwEevIuA33kB+zezqwQNHwfWN + Nx7Z9IJY8PHjdzz33OwF27fv24c6a/Zb+7Yv3oQY/9h9Tz2lV7FTAwbgrVtRABMrILuu2ZGRhYypl68X + sCBGmUQzhYfmkcAewNJNiPjcjqcK75fFi1CnIgCXpab2H1K1J6+s4djeQyWFr1emxca252U7bf80EzD9 + eizP7JF25ZVL0vyDJqGO3rwZ7/J58/W4aKELsZPhhRcAccELbIR+CCEYgH//+zsAeDticMlGxGACfuPo + VXc8tumzo28cfY5ZFf72fQDA7zyy6cBBAL7v+A8PwtoP4EeBmMzKqbak5AOG4Z/+9PrrzYAdwG9WzB04 + CoBnuqargnc2upAxDZKhNQFwHFsiAZl8ibg8FLCkWjz0DN4Z4TeuuGoP06xlx44dKlnNApgK9CY1DRgT + WvC82Fhx0mlblvg5xmNJdDSW9Emfo3rNW80kKwTwIy/AMc8WCz66YNOCRwj4988+9CDS4X0Qs+yNrIN3 + HoLTPnj7s2y8PrCgZOMbm5BOPTL7wMGDyKKP33ecnnvjZ4Arerca9o4g/NRPX/53y7BAWM668maFkJ05 + V7AGpA0cIiMaLoNLAXBqalZcX5BlDBYJ4HYBFy1Xw0pMFvNFmRSPOfnOqD+GEmkJ6iPkxZ7cuQnAvSQN + E8AtOfouLbqysnJSFK8fGr1ky5b2nzthF7DhdQEzCLMjiSH4AEPw7589+iDsFb54ETKtRRvhom8H4AMH + rzp4UBAu2ngALtoFfNVd9x18gyXSxgUPLpj93ILneDBWyYJnxYK/7TZx3Pbt6/+y9dibFcJzxVxpdQ7I + 4FJK0+ueHRldEQHDTh3AvHwdc+i+SLgUMI9rQAmVhLw5j4PuEH/zGlLLhuzZc2znpsUO4GZbsD7sAAbt + 6YN4tum0utgW0zMA+EKfJ+usFQp4kQFmlrUIdfAjL2zaiCqYgJFkAfDTL8yeDbYPzn7k6O1w0SVvHfzR + VUcPoWQ6AA9NC37jObhoAXz8KBZfeJAtHKyA31qwcdOB2bMfY5IFsgJY2joAuGLFKJAaNneuwjS8o1bo + qkhhBpdHTz4pxG2ZQpKVQkcsnf6AyauuAHBKSnI/pM503cyyslIb4J/Z11+1Z09eQ25D3ow9TxBwmnuB + aEfNBAzCLeVwiGmb4Z3r0iYR8Jp/BsD+MAuWILzoQVruC6iCtwPw0WfvePYhKZOQRKMqOvAGAB+8/eDt + T5csuuq+g4/MXvAOU+t3kEW/A6sl4NlXMcl6THzzgdlPvwN3/c4LtO/HpBC2Ng6Zf/9lAh41SgArWQpQ + Vwxb4TZOKthmAM5K7Nc3q6FdCqoh1LyMv8n92pXzTuPtR0POasjjUCwO1qkakp3VsLV+z5CKUwC8vxJB + GIE4LWoQlOBv+iQqmiazTnLXAj+PVp5fyuemeYs3AbBLV6okTBmEkRsf2I7aFxb80GMogKUtmmXwIuB8 + 4ehBZNGEefToC3huyb433jj42COokko2PvjO00cP/vCHx4/fdZyF8AKm1NBzs98BXW2GVsDfvh4LAPzm + TGE64LDMwAxTQA1YsGwMTqBFxtWVuujErFQHsOZa4q2lu9BGczRwLFZqGS833SEV7nrPnpz1O3lKf3+v + utdhwq+Tb4KcpuaLrbS0ll7AlkOTMJKrFw4c+Gy/AH6avcGIy1heNJtNlQR89Pbbn2WLJRC/sL1k+4F3 + kFfBWjd+Nnv2g2+8c/yHxzlgB4QfYeB96gcETL7E6wGMJQJ+kUgHWJIFcrBnAHYJjxILbgZgjshhLgWv + zDOu8OzBAliucwalAnA8B0OjTmJ+xXFZebwY0/ycN0+9+tb2gl5RbdLq0hK+bICtpZI2zA6lBx88sGjB + gwdeOPBZCZi+8PTTTz929OkDD26CWbOpedPsRZseIeA7nnsaoRiEEbIB+ODBpxfMPvDO0dmbHqHN3vW7 + p8gXYff4D36KRViww9cFTB9NwMyihw3QKhjgODO2JuIMBxxKGIBTpa1D2iopAyydDXDSKX37ZhUXN6Qm + JSWV5dXnlSWl9ifeHsuG7Dn8Jo/wTyjwx0yCa6WzbdnySwBYXbQDmHylM9i0XU+i9dxz7C58EMXxc8/B + rhfMXgDAB2+/6qo7Dh686qqr4KXpt9+447HZCxh2URk/d/txDso6+AjSq4PHf/fUy089dfy5TXDRHrzM + orn48jEnCLvDchQz8i5XshqmMSGEo4g3CLAQtml5Lqw7LrU4ryyuL/gizYpPLa6qmjFkWfaQqicenlxx + 6j8en1cwr6XPmiic0PoFVprFYMeA4aG1P5i9QvInnUOzFzxy9KGnH3nuwYfYVnn0hecWIIsG4B/paGgz + 3acXLHju2YPHDx4H4QWP3Qcf/RjKo4cOIm9++fmXBXAw3+u/LcsvH8l9cwUIe3gq3qYBw6jHGFsRYzAB + I1/W9mg6agI23n2zUlOLi1OTEhNTJY2Oz0Oaxe7CeuTTQ+YvO/VWYUFBQWbspJhe0BefL36mAOwm0ZJj + PfgcD3J4UP5eQJkjVv3I0wD8NCZ3IJuGMT/y3EOwXw6IJuD77jt4EGnYIwueuwNx+L77jh+8/ZHfIwj/ + 4PfEiwB8/fO3vfzTCIAlBF//05ePHHtTAF8yjMNhPTx1hbIN4RIjdgw5qlhNOJE9DgDajwPtCFg6Gvr2 + 7Qu8xXGJSXFlMOP4+Gz45zy2cwzZU4+A3L/qzQ9KCgsLfC19MST8ZQMMkrBkTBF2D3CKAunAI5xxLCV0 + FFRvv/3gUTB+Vg5Y+dN99xHwj36EYonp9MH77KiV+6667/gP73rqLmTS4PvU94MAK1vRXxCDv//9n76c + ++bhuQLYhCRLZKuQrodpjNqwE4wJOI4Dn5FL9wNhANYTCFtvYSLtt2/fuGI2Q8cjja6aAUMuq9pTn7f1 + SHH9nmN/e7xwQ6EDGIRtR31R5QUMsCLJol848AgAP/IIO/r1LOCPPXTH7Xf8/o7b8XcHIu8dB2//E7jC + eMWGyfXgwXcO/vCuH4LsD5E8Q3fdhcyKTZPsXSBgZNGhgP8i639Z1fBmhWTKXpSAp3Ap2xZBClgJiwXD + TXPgFVsnkUajDAbZfrBpFMCwX/wCEIaLYb/In/Nm9IhHOVy1J69461YAfvNVWPA8X6s15wvYn5CZkRAT + G5MR4/PHxGTGxvB4idjMGH9GjD+ayxmYYWtmTDSmPHdTNJ6UydNHZGScxbFRTahXTAwBAy+DsJCVliwV + 0T4riGXE+x13/P73PJhBxENVKCZZ4Ptv/wbE98GAf0f7leMZnCMannoKhDkKi7RDXfRf/iKz7x/Jbag4 + vGIYKY2B9Y4RAza0Km4weToMgzsPL7kEMZhiqWSENfRKO2VfsV/hm1ccDzedxzqYh65U5dV3KN5aX191 + 7BUBHHveLhqMYjN9mQLXB6oZfpLOjEmI9mdC4OnHks+fGYM1PA/PTMiMzsB/Buxo34Vqww4AVhlfdiNx + DIcesOLyhQwvAcsRSXDMBwH43yCgBd/fkTAAK9wfMHsmYRHnYYC1TcshTLAskbzuWiX8VGcCHA+88QzC + KmRaGoUFN8jCe9N+i8vikuJRJhV3iI/vsWdPXuv+mFXlNZx6a0NhQcvM2LrzTbLArmbbjh2Z+duqd+SD + ZEZM9O5qqLZ627Zt1dX5/pj86t1+X3VtzbbdWN/mi/Ht2LZtB1a27ebd3uZ81auXuGjDC5Gv4qW8RyQJ + XzseKXBEoQGGBQthOZ5QCIMtASN7BmKg5RErApcSpiJn3N33j5SDMBCDsfFtNmAvYgUcl5pKH+0CRvyl + /cbhwTiEZ/rpuLh4icNxWf3ZXxif3eOJJ3IqTr36UkEhy6SY8y2T4IUBEzp9ehvmuxMAtHr37t2nawm4 + NtafycXdtad3E3l1dUxMDRZqa0/zNXiVvc35q6UChukKYMd+7fIqLl/FK4AVrwD+kQA++CPkVeBLtASM + eQAwJDYsgG8TuMGAzYKff/5IeUrDm4cPgzFKJsIysibhpwoDTOk6ACN5AuA4jm8XwLwMR0ou8MbFd4iP + i4sTviyT6plHZxXDP/fv3z9vyJCcY6d2vrVh3jR/TKUL+JwbOmCx1dtqanbsqD6xe/eObfDJNdW7Y2J8 + tUAds/s0PPM2sj59evfpmpiYbbWx0Zm1Nfm1205v82Fx2wl7m/MWe5PEghl9PYAFrxL28g22YGbPBKzH + E9JyOUPw5XGFxBs44EwNOBywS/j66287sgrWduxN2vFA42lwKd0gcnF6Aeu2qLKyMvpoWKgQlgtkAXBW + 30SYr8sXfhr2WxwPM95an9chvnVeVR4Hzb61vWBQFI9DiTnfpspo/45aWOrp2tPvVtfW1iYgylZvy/T5 + aqsRcXfXxvgS4KJ9vm3V4JqZX10b7ffX1tRUZ5zGk6ELZ8E82awDWCSAidYD2OjegUQ6QBiAWSPJoYSQ + 4m3stGeMwuqiDacrEDYjfvn5I6t27dq1fGIFHLXg8xK2DZTBpBRtYD0K0VVBGmBeIEtGc2SllsXHJcXF + gW8HPFpcnJfXIQ5kUR7lZhVXVdUf++Stjdv3x7aZlJb2Os/3fn6AYcDVvuptO2CMO3bsrkXqlFl7gnpX + ZgnRMRnbTmOhOv/d0ydOn6hFMla9rXpbzOltNfn5MHt7m/OXAqbxhgBWuXxRG91x9CiPF/UCBmHjCwUA + /0AQkzGrpKd+6j1gVGB69W1m0vrIX/C0XRcvrzh8GDwlFBtdyAhSHqCKl9L1KKRNqakdYKFKOOWIdPD3 + G4rMCnabxAQrNRHZluZXrZFIFx85ciQPgPce2rS9Zk1lXV1a3esJfuDlyPdzvuZCTP6J077abTG+mtro + 6B21yMqZVPn91dWxsbDgzISEmtptfvwKMmrzfZnbqmOia+Cwa3ynd7BE2n2hAVMCVwG7178KAKZcwEI4 + MmCHbPMBX89KCVWUQP7+9S8fOVLPgolCKFa4vAXk4oxgwa1bt+4AcnGwVuDNIl3Yb79kgiX2hoaGRHY3 + 5BW3jud4nYYGtl3m5VUtO7Vz0+otHISRxhqHzfSShJ6jYqoBuHpHZszu2vyYmtP5Mb786h0ocEE1IXp3 + LWqhzGomWdX5tTUZiMHyA6g5EXuamVntCQZmqZ3t7c5ZvQpWL96oDVkCWGOw0TW+ImMseCV/lhDs4St4 + RcJYfbR6aMRfVkkCEFKsEQRnjYef31p/eNiYJ8EWVbFxa7YIuDUAx8dlJSWlpKTkcogdHTSUEpeVWtzQ + gHyLZ15JTUIBnMfDk/qzjaN/9qmdJQq4VcuWvWI4vup8CGciE0Zora0+fQJLp2NiM5BB1SCNqsYEPHf4 + 82sRpE9X52NDDdJqAK7x1+44jVS6ekc1APtjYxIuJGCXrwewixcKADa+LmDcDe0P75Icy+gGA1a4kNEM + FWMxh2jdRsBEC8sl5rOTBzD7lBLbDeXhKv2yilOzgDm1eGtWLgy4Ia+hLEnq4HgZdre1uMOyhmOHSnyV + +QoYFny+gGvyq30gubu2dveOmt2ZCTBj5E4IwJjUnvD5Y3ZUb8uvQdh9l5mYAN6BHPv0Dt+2bfkwez+e + Etv8k6I2pnDAgRQ6YL5U44AD5qtwXbxuDv0PBNy/v/lomKse4kALJmBG3tRiOOyUhq0NqfHsD85blhTX + oQcBxy/j5Rrmbdmy5AIB9iXsqM3Ph8HW7ohm06MPZdIOX2YCfHI+s+hoWC3TbDwhkyVzDG1+2+l8xGA+ + stvHhq+M8z8NU0TAyjcSYPJtPmAXLz20wj2jfxbA377tbAC7wdfkAk4i4KS+/VL69mMXIXsQ2c6RlZSY + wqO+E5Piy/LKWsfDjKvyigG+7E22Ui7ZknaBAKPYrc30+7cxmibEJPhiE7ZV10RnRiPviokFyOhMYK7e + dmJ3dXV+BlIvf0ImVqv9qJN9qJBjomOipXHT3u6cFQo4YL/BfAWvZVgevorXAQy0etokQ6x8gy5P2EzA + 7D5oHuAQAbAQ7pAUF58Fmn0T+w1lFyEdNDgDcArHYyUl0n7jk7Lj+wNwh7jUvPo3Tx3aWDKtEolzSwJW + vucBOCO/OjN2ByphNkPCgvOrqzOBrbY6IzpzWy3PaLu7uiYTRrwtIzq6utaXgJw7Mz8GqTbbvGpg1rBg + JnvnJwcw8IoBNwJY+YalWIbXY8BmxF6+IuH7dwAcqgBgmDDyrEQBywicGKftHOTLcXe8mA7NOK9/6/gO + xfV5DXsP7XuppJADnC8EYH/mDuTDtbUZNTDU2tqaaCbR/kyUxkiga6r9Pt/uaiTUO06f3p3gj9lWHR2b + WYsKyX96W2y0D056B6IvO5ns7c5ZEQA3ylfwntmAVYI3AmBDGVkKGLoAgEEYgJlIJ6ndcqBOKsfbJfLc + hUnJiTwFKcok8EW21YGDpBuO7d15aB+vH0zA5HtegH1MorZlMlXK92+rzvfnk2x0Qv6OaF/sjtrM2Jgd + 2zIQmfN3RyPUog5mGRUdnVCL9Bkl0+5qpGVYOu9LAjQLsPJtCrDRdfAqYMX7DwScB8D9mUfHJSXBhPsi + mSbgfmzhQGLFOjiVF6UsK0uNj4dn5mH+wJyX15C7d+8fd+5bPK9wXnRszKTzBRzt34GYG+G0035fgn/3 + Np+tseRGSby7mlBRJyOPzoBFn7fhBgTAmxSw8VWBr8jD1wCzk8ESLMjFSwUTFvulPIgh4xkmw+sC5oh3 + oxYmC7ihwiMETCNmoRQfjyAs/lksFx5aBkSXgTMAc0oDzs7mYWj94+MbGo7BiDnozhebVne+gDP9+Tt8 + MRkuSEf+hAxUTHTAKjnBfHQ+vHNmTQ2i7u58dhUnNPeE5E1LAXsMWPAaX7HfMwAW83UBN8I3GLDTtRAm + w3s+gKGovB4KOAmIwTBJmib7JcYXszCK6yADZuNTy1AH901qqC/mScEb6ut7xHcoq68H4k9+NW9egU+P + E+TuOXfAMRns1Q8DHAuvG+PLdE00NhrZsgzyiJaufrwI1u/PsIfPXwLYMeAQwF66joP+U+MW7MXbGN+/ + F2BnmwOYbR0gCosVA45nQyX4lhWb/cqsGAGYp2FpyFuWnZdXX986vmHvB4XzCqJbTQJh2T3n7qJRGkVq + iIpldozgaqtw0QncgE1ymlu5ngCfYA+ftzQGBwPWCBzC17Ff5esAbgZfBWx4ZZx7ZBneJgBr3aswI8kL + WOy3gS3QNGOk0B06YDuoNxBzakMerXlZWQOv2bAsr7g4r/+yvGMfbCgoiG3l43mUhO25Agak6FigslVX + sTBQ8rRV8CRhPDsWrhoLfl6z6e8G2OHr2m+IeyZgjwUTrwtYC2DjG2rAhpcchWYEGd7rmwDcBOGoHuai + 1YAbihtQIJEvKiQUT0y94uGf8RgcMxLopB55AjivHla9rEf9MQ6bbenn2fjPDzDMF+TCsywgz4j1ACRT + YoUF4/dAvGLAFywGhwAOHcgRBti5QmEYX4vAxjcEsPJtVhYdCtjAeRQR8IQJOvcARpJVRgfNM0OXdUDl + C/sVvuKfyxrqG7KSslpX9UAYnr8sbyuyr2VD8vZ+sIGAeYjv+QHOoJ36YZYhAllGXVuDRcfC0PlbiJEL + NmFGytEXLAa7gJVvE4Dt4ioRUqygFixI4b78cqgBmyLY8YUCLHylrRJ8G8riUCWBtgCGf06Ea26g80Zd + xHIpr6p/UlI2yObmpmbPzzm29/3CwoKWLesE8DkHYAr2KORCRAvlQFlbBVLh7adV03Rdk75AivERsGvA + KhdvBMAqF2+IAYdZsPA9K8DXO4BRBhNlOMyI2KEJEMqk1q2FsPji1CQG4LJUpMwcsYONKJekDmZ/IZ5R + X5zSL4UhOLU4Pi+n9NirJYUJvRgLdfecD+F/DvlaOlk0Eav9WgwOsmEF7LZyBFy08ZXRdh7ADuEA4GCO + rsDalkS3/UUsmMOjtZVjDBaANDAJ0CXQYbiPGTZmAn4NsiEqrxiAJcdKFV/MGSqkRA7GY9ZVxpNUskyS + XwAeS2mXmtdjWf/i4rL6N499cmhDhl9znS+JKv0ewJZBUwHCQYANb6QYHA5Y4VJnAByi2/4CC97zPQVM + wjIS3mOynkVROGA2VcJWO/Dgo6TEMmUJpmKyDWXgS99Noy7DM/BTyKsasiy+GEXw3k8ObVoMuEx3bP98 + 4TXJBSwG7LVgwat8DW+Ab8BHG17jG+SiQTYQgo3v2QDmeUYhr9G6GsaGTIqAMXWWo4qLxUEjAOfl0WTV + F9NyHafdlw6a2+Lz8jokte6fBwNetqxsKwdVblw8D+EwGnmP7Z8vvJoCLHzDATfmob2Aha3Iw7d5gMVF + T5AzyQpgwRckh68CthSLgC3F0m4EpFTioDnT/IqVkfKVbDo7rrWcrBJB+NixnbO3b1/dklnPl86CXb4K + WPh6AEfCG2TAxKtpdIBvALDXgM8C8BgXsNCLIMLFnRNn3QB3aA2+YrLEq/6ZLpk9/cSMjfTPSdllPLwh + KWlZXtUxjqpc3Z61zZcpBk9ikqWnTnIN2MM3ImDhGxmwh+85A/5LCGBmWY4UJEWwEUQX3Tq+Q1lePSGi + ACZfnpPDwcwBd+4KAvXWrQ0pKQ1leUNK9x4q2T8pTepQTGz/fOFFwBsVsPFVvGfg6zVgASx4w/g2AvjM + CgKseL2AzVI5N6ChImAYcDEAa8iV0pf2K/GX12rY2hCfyJPNcq1s69Yj5cm5W+uXzS/ae2j7/ro0GjCq + 1M//0uwXSGLBQQ7ay7dxA/bwDXPQyveCAjYvHXDFY8asUKIhklGVrcE3L176+EGRBbBjsQDb0JDFqSVd + W48cyT1yZGtDtgJOq5R2YiTStn+++IqFBR8AYPIlYKEbga/TxEG+ICuEBS/46vXNgu3X+BIuZQCb0rdv + ex518J5bgHWCk2SpBQOezGWJWrFCEfNYNZnLJKoYJVJxHvNjGq40bViaJdE4vqGhAStw0wq9LCsXK2yN + LjoGFx0zSduYwlugvqDqFRmwycs3BLDIBawK4nuugG8jYFpwADDJqSLwdWWAQZbjncmXXUhuADa+WEEh + DKTyCPIsadBMTVqXfezY7zctnrdGY/CXDrDgJWDy9cZfxz87gMP8szhoD+AgvOGALZdqVABsLjoSYFeO + 2U645RZnqutRiMDMoOOSYMeSRzsVMCnzYqPgy2xaYOMJHfrnlWUnZWenSpnE6wd/uQDH+Be7gJ0IHIGv + NUIL3mC+BBzONzgAnwXgv9zmxOBgwI7hqly+KwKAZXZLFPHm9Y93+vYtmdI4DKbwzzxTNB7SoByPZ+MR + uOkje1879Na+7fPMhG0HfdHVqxcAzz7gZlguYMVrgL19DKGAIydYjTpo49ioAoCloYPYnnQzq4DCHLSI + gPW4X8bhYvJzQq9NmXTxwJV4sd+kpGxaOx5p2Lo1d9fevZ8c2rhad8yXpUxyAD/9mJyKQwB77FcBG90z + 8z0TYINLGcdGFQFwIHUONeQg0YoBmC1TyLOQSNNNixcGWSZbsFNi5sBo4cuVMvwMcnM5lPZIbm7DsVOf + vLU4mvb7pWnoaAqwGLA3v3IAK95QBx0C2PgSMPsB9X5m8SIsIVm0AYwgWKxM6KBlBsBwuWXxKITLaMDM + llkHg6WcYxYrsGlpziqWtsu8+qyU8lw8K6VdbkPe/PS9r5awO1hP/fwl6CxEPRCrgDW7grRE8uANGHBE + wEF4Xb4v/9SON3Ouj9R8wEiy6m+5QQA/+eQlqJGMHgEG5EI1KeAJArhDHMfYucbKhg6sIObSllkgsSuR + aRamDXGJWQ3F8UnrWCtNmdiw99CGxfvn+dboiI7z6/L/p1CdzwNYbNf1zgLY0EJK1xy04XUBuwasjOV4 + b6IVEWzzJIBv21r/6wm3aPh98pLg4Otl7OVLtiIAhoNGgpUKcuDLgxscywVSuGaQx7IkWKScmMVse926 + ZaWl89dl5x17pWTx9nntfec7avafRu09gAnXIazGGxZ/Q/iqfza40FMKmHwh49t8wGLBtwlg88yIxCol + G2TEwYBtHsUMunVeMUfXgW9usjZUWh0M08WUxkxrpk0na02cnV2WvawMKdexDwi4Vfv2CviLr7r2BMzg + S7QC2DFekeF1+AYBtgTL4FIA7BiwA5jXfj4LqQXfQsDAhQza5AB2FLTiURT7CnmalSRpqExJZjqllssp + s2hNsBzw4Ju4LqkMdEG4rMMuA6xXp/wSKK394u0A/JDa7x0hgI0uZHwBmKcsdPkCsLGlCDeM79kCpgUT + MHFNeNIxWa6EIdXtQYqKQwJd3CE+LjEVmVPflKxUcmTjM32ytU3LltQGpFlsuVy3HMl0/2UwYjyMGLx6 + cUH79gjCXwYHLYBpwbTe4OCr8rZviMhW+AreYMBBeF9++fnnnz9rwOTrtWCdKMfmAU5kC1ZcXHwcAPdN + zm0QpmatAKwBmGO0mEwnptZnr4P98gil1mVlKblHPtm3evXqVu3TKmnAXwrAdQKYJws2uJBDV0e5G1qV + xztTXg8dzvd58j1LwM+7MdiQnVHhgDt0KON5sOifs1JSslgnIZtORWXEAZVZar/GmmlW0jqO6mHXfwOb + OnZunLd6dcv2aUvEgL8MgNNWK2BD68C9CmzD6KqH9vANt2Cjq3yfJ66zIMwnK2AUwuHW2Qz9PAr1UWqH + RNqvHhrMPBorqcmylpRI++VlOdRvlyVlAy2Ik+/evcdf3VcyD4VwnTpo8P3CR2IHsOI1BR2f4tV99/0b + 4MppKal/xz1A2MtX8FJnA5jPdQBrmRTBB59RPwdgntCdLGGtPDZYom1DVl+aMQ8VltP5x5exAVpauZBx + wUuD77pje1+1A8BRIzmAz/lEaP8sgotGkvWQkQ24ZQHsInZzZ7B16IKvyMVrbANwKYEWAbFu9zxi6wb4 + mVueeQbAJlwSEbFu/HkkATAqYGAUsphyDCV7kABbfLX2E5bJ2CwAjuvfn4VTduq6nnt3vrVxuxzgHwB8 + 7me6+ydRmhcw4YrANdh8YbkBCVvMlS/1gx/8e2S8DmDUPmchsWABHB5jAzKiIYKLlvMFg2/fLKBNTEYY + ziLrLBAXL22mi1gcD/FQ4uzU7HUIwIc2bvdVtlS+Xx7ASxZvX8ATFBpbKtQ1K1dXYrpevlREupAxOysJ + YOjXOoMcM/75z3XauKJSsxJ5vtEsOakOoTIaw4xp0bLF8ivwRRJdJiNs8YxkeGheXnYLyBpgEP4yAEYd + DMDIqVTG1JVBDZIx9agRupAxOxs9Hw7YEQEbyUYUlSIXZkAJnEWwfZPgn3nOytQUpNRCXPMry7LKyJuJ + dlKqDJutBGDha4A//4tLnqfSlgDwoqNMmlXGFTKa4TKoXjWG9ywB6/MJ2Bo6vDKCTSiqXTvyzUphQ0di + MjBn9e2bIhfpIOAUQZuYnKStWw3xybDnXCZZZQ1w0SUAbMLO+VIBNqquDGaYjGiwGsV7VoCd56sFO3Xw + r8UrQ0awCUUBY0NqX57cjqabhQmdNaYpSLNSUth1yKyKd4nHqbm569fnZsfHpexCDN4SDDjtiw94iwI2 + rEinODGYEWREQyRoIkvZhcseDjxu69jw/Naf/OQWSbGgX//614auOfqXf4mKyypuSBnaL3UrKKeAcjIL + pKykvjDgrCTwpT+28R3xicuTGnLLZ+U2NMT1jW84hix6f2bLlvTR2hXcsqWc9k4l++vs1CtCj3Lou9k6 + pKsJ8yhZwi1c8qyzUPvV27c/R8Cgd2a2kPEMk7GJrGB+zdARL2BYLhg3j/K/QFGoaLNmlR85klteTpvN + 6scsGkYMsImScSUn80xoffEDSIYN5wIvL9DROi732N6d+zaVLF5NFawugAoLCxdjSXY5173SLdOnywo0 + 3ZRAQgWbXemjtgIV2DvhvQv5fP1PKqwWbigslMcc+dq334/abb98CEheRPHlGzZslmVOCzds2GCL0zcP + StisjxQUbijZ9NxRpwz6pc4iSjNngfyyYAVXTo78+xFSwQ0UQ0C6aDmz+21/+QuLXdlqj8iSzo8cOZJa + /5Nf//oZLZMogyezn9tMRKCOnLWosrLsxPJcOc97LtwvfTLTKXpsqYPBGgEZUZkXsMzKyt2Fp8XHdWid + mMKzZB16a2Mjekllaxs3Pv744+7GSMLjopfkSbYCvYRXBj1uslV3/QySp/GJuP9KtuiUCiypHn/pV7/6 + 1aHX9u7q1Omaa67ptHLl0KFD+/UrLy/vl4ylocl6VWVoFXYa5+2440ABq0d4qnRmNKnFW4tTcdtazDNr + Q7LQiMIekQ3OC45s3Vpfv4cmC8LCmCFYYDpMZS5SpCpnJaohtV1y7hGejRI0YcYCluGWUZm+Ogs5Fnw3 + 7wCduwuE4zt06FCfuouj7j7ZG6JjNj91jDf8CIKEDaZTJls99qbJVt31xvVn0Ztv4ptxVb+jLDrL1E9w + dzb8+c8//8lPfv4mJpipsAtsifoXPoKHfv3rn/3s/vsPH/4ZFu7/men+Z55xl13dcpjFy+Ff/xp/yIR+ + 9rNn+Eq588nhL2hMfDU5/uxnh23Lz2XKD3SY5RHemI//+l+kMnLxBr6ArsiaLfK1UUdy27XLRVKVFN8h + NSu3HA5YOxsImdOG1JTkRDyOCWqpxNzcXeW5qaiGWxensrNhL362pjJRHtWjR49ly3oMqaqqqs9rMGFz + PYRtVVV7qCdE7oJJHjJ9F3r4JujhhwdE1rABN3/vxhtv/B4npvE3XnfjFfdcYbrxGaxfdx0y0BtvfAaP + 3P8zTp+5//77nxl/w3XX3XDD/fdQV199xQ3QFffc/8zPnnlm/D3fuOIe3PFuNzz66NXQo9QNWAkRXzT+ + mfFP3vDMDePHj8fy/Zxz8VFM7hmPtXt0w/h77se/wuyee9z5/ZjzPn68fCD8gPC7eOZGoMTvhI0Zz/zs + 1z/5r/+y8vcZ4YvoKwbs4RgsZzvpEnA54i/PrMOBlLzminpmWjEjMgBnMamGexYltgNgJN5IuFrnFaci + dKfKwU08z0dA4EsNobiwjJcrHTJkxoyqGSJFeS/1hLPuYOb6vU/c+8QTD6u+e5hSnDcfvlnWDh/+nkfP + 3K9kTffgfsU3rvjGN74h6LjnbrwOu4r7b7yhHY8pd++NN9xwtTztG1cTKAWg31Jh8/jxwvdbgtgwG3Gu + yGZAvR8g+a7ECHKcPjr+fs4EJLYRL4UnyZJ9AjoFW+CdAlvzFHDIarXYKM5Z+f5aITaC1wVvfH8S1S8F + ASQxkefESkpKyW1IEbBZSURMyiidUCDjjswrBYacm6uAW/dvHdehuLg1rdUR2FT1EBPmReChGaSqMn5q + sTNmDDHA9+KhKm7GJpE+516xXkrR3rRW5zcPGPDdm28m1ptd0Xqvu07vhAtbvAKETdzrMOHrnnnmxvFi + zMIDT+EDNNsrrgDjb9wjtLBudL9FfARMq1WiMlXA37BlPEVsePwNT8Ih0MJpuY/iLhvNkLFFpjBUmYrN + 4mNwjT8PLt1Al07A5DyeSIkYRoyp/Dppw4JXGTfG1xXYyjyqdevU1CPtUmjF4puTec5ZBGTlm8QYLL1K + zLSQaCGnYK4FwLTavDyeiTjIgsuYVBQXi6suo+maJbuiA+d2k20d4powqRtcSsECreg6BUtiKiIDOdmh + 2LPct1x59B4uU7CYZwgB+457XPeowuBT7Unj7+GdxscfhYsSD8uvBJuugI3DlV8xnt6fixIFuEVWZZNu + pxFjAgdBp0yD1anKWXRmNgdUor1xPG03IAm95A5pgfQvJCzoRC5o40mp6criM89E9e8Ql3oEbvpIFs+Q + lZqFWiiLBREY05Bpu31TUCwxm6aIW56pTFu3Lha+rQFVTJd0Ba6E4/p6M2bHQskWxGnbKlo35/DJvD0s + Zg3CDmTF+z2YrgNZ+T7JCfXkk4ikQYI93QAnqCK9G5588kkxsycfJXzKDaf8OWCb81Rgg03LK8ePB+dv + kAEYKjQ6WK7K7B78GMbfA2tWwniGkZefyhUALM8CQZkYUl3Gb0ym999/o0NYMjMnjXsGlvtr3m6ZwDXZ + 9mvEXgPsEg64agep0rWVX//LM1HIpdoxze83NLG4OKlvEgqi5GShSqNF+KUQfFknsfkSLMWiU+HUFW1/ + GDJF3pyruxYPTf9bVaUbKKwzvOKuHCmuYBNZY7YHW0jXa8Sq730PtJlNwYg9SRUZ33j/PYim9LbKBoDp + B2WPPwpHKwkUNhE88iJiYPAU30tOBpjC7hbi2ITY+61vMUIDFd/BeY6sCWM8E7Gexo73xj94lJvhO/C/ + 738UbyyvwBvQjeDZnDL8yhqfI6tiuc8gOWP8/dkzN8iUIlRxzVgkVMoh6rHXYBleSp70k6hdEPgeYX3E + JKuBSTPzZTpkRFsDLIUwtwlTJs2pWaiWZI1n+Xc5OyBVmmRRZqwzlGpkMakK8s9eETAmTJm9STMQ33zj + PcisSBfC/uSO5+5ncgwL+wbiMUhg23iwpQ+mt0XajEj9jXu4zG3CxmRWffU3QBgrIm6ghbsrnEtifTUD + NRexnVvlkftlKnJYgiBnTopHqjIVCdMAWplxo5RPTnrlcc1NAMbjP/nJ21TUJ9DevbtWpRQX9+2XeyT3 + SHJyakNuX7m+ewqAC2Ci1mmcICVeSkBTHZB00TMXw4p7IM+i/QKphllPoIWlSm788MNYpEsWqBQKoodZ + EukyUTLcClWRk1cpYmMLAe3Nkl0JXnOSMgfZb3zjW5JNk9+NMGGgdB7llOmVhFZJyZhPf4OuVqwMDPED + QCqtlBQm06RniAiPYpMt0OaVSEA/A06TUFR2NMrQeWBGhJg/iQ1Yo7CdG+mavXS9MqLB4mbA/cNvfvOH + qENHj+785JPXVu7KTU2Eqy5PTs4lX6RSKgHpkQAGYS4TbRkv/c5jT2m+iMl5WglDDl+DCxGqV4QZrAE2 + G+ACdfHqBql7QwDTSasJI0ciVwJTwN9ihUOaAHEjAd+AFfDAw5JO2fNg5qiEhTFZkjlXIbpo3aT5mC5S + RMy3uuFRZHFPwo8GBD6GiJmx0CNDR3yGR1gjPxPCLxMrfb1to2s2nppjGcMz6O23//ibVz945f0DUSWf + ffbWoZ004nUpqUdyy8E3pW87owsJVa+YXgFwhw5iuloG9+9B1ywFsNEVV42ZZFPwzIY0VIy+rrR1g2UU + 7Bvzw4eVLmYK+HvfQ6Z1+JZbDsNmJxwmVxVqn4CEAp0mHLQWNCSC8Is0WiQFjS7SryKEXj3+arASgFoN + 8bcB5iTsrOCHIJm1vB+FgIulq68GYXIWIBDMn+GBU5HmVLZiYtxFRgW5iB0pz3CBrJIjYp3Lapi4Gcb7 + x/945f1fvfR4TU3Umvyakn1vgfCuWevAsx38M4w4ZTm8s1mxcmX8FQlWZFhKmAUxaDLBIt+qqgBeTbQg + ib0Ou4A07tpKUAsWn2ZLew5/L6hZA5k0AF83QZOrG1EmEZYDDCIEJQdkQutq2S6AsVWeKYSxoyWG0iqd + qcRUcezIryR/ohXTjLEViJWxAIaXkCX9V8iRNJ7yIQLmTLjKPRiwZ1Woei1acGqHkUcKjwoAjowYG8H3 + N6+8/1LJhvy7p0VHbamsXLN90wIa8fp1PDUDueLONvSUdimELFwdwDw62OyWV0xL0gbK+Piysv5uMyU1 + o4rtVoYYdmycG82ywFJ8tlAFYDVex3QRe+GfwZR3ciVgYKJoZy7gR68gT5oUXCnpMhMGGGS5shWhl04W + MRlwvmFVLlIxLXMtW4bXpt3inYATjxM+X6XOWX4boGS/KyH8zPjrQgC7YJ17mDw2jNfpPBLgEJQGuxHA + 3Pr2H/72yksl+32Zd0dt3hy1ZcuWyvztm/a99erevcuz+7fum4yEuW/WVvYN81AWXliYYDF3AZche6bF + tgbgeh5XnBTPSykB7jJtpgRHwYqZbIdkOyTBOAJlwQnAmGor1sPfHRBIrQA3qHnjRimLKKlbmQPTtsiD + GEDqSRSi9KpslYKbZRS+B5SZW9GHkjC4I+YywxZ4fCH58U2dFWKVLTcQhm4iViROzIex9Og992PD/UiN + NGw+Iw5YE2VpkRTAXFegAbHuNcAIvBZ3zUcHEudbAnWuK92isk2OsOXtt//2/uP5a2C50zZv3hC1pBJa + s3/x44de/WTXkdZxcdqAxR5+ERup2XvkSFaBlwetdYB35nXfO8B2q3r0bx2/jAjFZJlEa45FOWAht4WD + 6bSbZgnSYA0YcNNN0sQheG/08L0ZIRf2qzsegk2yBlLv/OjVYm9gidBoIZVGTTuj9YkbZrGKF+KZfBmW + 2HLMV91zj5Mik4xukhZM3aSI+VZ8PnjgDcEP05/97MlbgElyLXLTogjAtI1KfhA0cSPP9EvAOs6ZbDm9 + RVflxyJzxXgGSUnk3v7l5z95+zcHSgqiJ0FR0zdsiPJlZlYuqZwUu2HfgU/2HkltbYBdwYClJ8JRXFwq + jyaOj+MxS2WpHeLiWkvTlcZg7U4wS122bM4cZen0MkDih7FJwQZkWE2wXDZdDUDSLISlSZK68cZbsAgP + zX1uYvLMdgkCJs5vwOXeA19NHy1uOgBYJGSFIwlDIGhGjM1ELje6VTzG6gmM1bXbk+Q3IT4ZbAWwZs7S + aqw8Za532+BsFLlkHRlPN3G+JbjJqnF58eL2k7f/+MFL+32Vk9q0adOCgNesyfRFXRk1qLBk39FPdmUV + S/D1Sv2y1cNZudr3l9tXZyl9E1NR/bbu0BrJlrZekS6MFgznzMmpGGJtj64kowJk3m+aM2cO4WKzgXUk + gVfQ6lJI0wb/sMu9ugElrXQEsXWCYgeRLVFMiYmVlPCbwD6WQH0Fn8MHmVo5z7X8WWhiTSbcIr8CyaLF + iAWYLOCddI2AFaAQ1UVnS2DqAsVcZ/xhIAD/TEog87W2dJZ6+9VfbSj0kS8AF26I2rIm88rN0wF48cZD + n+wtzwoDHKKtDZggEwNeTHP14u8d4K3hrqsk0mo2LZY7BOmScnWlgJklcyrGrGv3fhfZVRBfSABL45Wx + vdFDWvb5PZghafoGAEsfISmJvnHFt4ywZMESfAEI9/vHX3eDmCdLYXkGhEW2XN2j6TOFLWzocBgLdLwB + fkaMqvQHpMVfCacWgn9mWOmbGWVtldLWZkiBNlISGSYAtoWz1Nt/fOXxwv2xfgKOzSgsNMDTB/n2lyxC + Jj3LSaYcOf29jni9HfYscJaKOTNqTaMg0CXiqirr2K+q2mMzinxt3bZAUiJjHlQnHd7D2hflEWJwsPG6 + gNntC3d6IxIm0XXOgiNprvJqPFs6dDtZ6TJ/Ew5/bdZwJVu8bwKk7rr4Zf5KML8C82duJEECJkXyE6Bi + oMrUyIqlUgbUI3W5KieREmi2HEnyuFdv/+ZXJSX7W0aDb11ddIECng7A/v3bacK72ilfCb0iA+sKVDsg + 8nYg3WJrjK6vtxjsplhhUouVDv6qJ6qC616asm1BCi0d+oe/N4CAzYJDhWA8HrxE2GPY9/cEUmETSidM + 1c+KQARCwoTtTJ25jQgVu3YUYoVP4ha8AI6fwZaLhMmHmKERK3DecIOaJ7aCmds0qfhs5s4D0mcYU8oh + pfNQCTVbFnniLW8hevvtDx7fsN8Xmzm9xaS6JUsyfATsmz49qk2Cb3HJW2988skurYADEt4B8UxLPPaB + ITgVPwTHcoUu/C0tEhAxx4q0OId7ad6kcxA3Ga1xE6RJldslqFnzk26vICW7m5MbnnwSe5r9QUqNIglm + 0ZJLXz3+ajx6NXNqFbfLSyis6UyfzTnfhot8jqRgzL+4nRt1C/Xoo+x4FK7GU/Nkc9AUGSpY5+5arc0o + L9sgGahmy17m6O0/vF+yYX97H5hOWoIKyccs2pcx7cq6Sb7Cks8++Fv4KLrIssF0OkDu1PpTx2z43Ckb + LYfZKV06s/5s88CCiL1iTUl6Q7XHW1f+5SeyYvIuQ6HjS23mWRAFr8FEsOkW1KLujvwJnmL7Vhb/5Sf/ + hX/7E0xN/+UunUlv6/RtnXPhAukP72/Yv6Z9Zi8Y7ZItqIWjrvT5fGsqkVVPA+ADH7zxwSuvfPDBB69+ + sBM3zBvVzp07deGNN97QhXPU32x2Jv3mgusPNncUtu7KNrhyNutU1j3P/tz1wWeL5+XnRw+aPt1XKYCx + sGYNCLeZPn3D4yUlJTLY+Ox0Lq8JyMZN27hkWwuVPfc85BlqTYWshskz7tqZq3Ttn1gl+9fkrym4Oxjw + ljWVg1AU7yhZvLiQhxIU2qEDnmMGbAM0vXB6wWY8gum8zfPsYT3swJUelUANEtmKHT7gfbyAx0VA9i6F + i/c7WuzKHjLJh3CPjGiB5RbQlS02t2gR1aJNVEaQ2ti/sf/sfoDpG/QDcx0PBj6hbg1IP5l3T6jwCfQR + WXY+FSRvEBCfQ9mqux4qPCQvlwNFIsie1qQKNuRnZrZvWTj9SgHsMwtes2bahukbavIL8zPZdMnJGtwy + w8RHgxQNF+/zZWT4rhRF3W2aZtIXcWFapmz3PgjJu4r4wN2Z8mGgzEzFjAWP7O3OQa+/Xom3r3yd7zBt + 2qRJ+fn4Z1iiol5v0+Z10zR8QG7QR6ZNW2I7Qb4mhM/JG77ClVfiG2FvquzfyNfzyt7G3W5Pd2Rb78an + 4fs2rvxmqqaGu3BeAQyYCgC+++7N0+++0o9H27fnHROTL/iGkC1Tna9ZIxQIRLXFpK+FfNGxvDJaNBRb + EBst77skkth6OmlSHcRrqfH5Pl+Bz56LlF+fEB2dwYdQ5/GZVBvc6uqMz+uvy7Nc2cbXX3cI4o0qK5fw + aqkqf5uoqKg2bQaxYYAaNKgF1jFVRSWk1ck/xpeIxcOx/CAiefUSJDK8Y2JvqQ8GpFvDtzvCWy/hzVEd + /1HjqqvDrvDeQhRdU+NLW5MJjyCAr8SXiwIpYPC12Dwt/+5J+T6fAG5FgJSghMScIP6GA/L5VnOjPFPE + d4Xte8VXExZwFQCYKz6Ve9uRvSVEu542TV2OY9L2EAzb5mYZzpxmELCTSNKnqV+qXIN/LD7Kd6W+VJ4C + RV0pz1N/BCP1fF15HK+Vm7o68XXO9ILI/pcr+aeQfCqvwzPZyxz54FOWrPHNM8BR06Nen4Q9v3o1vGyb + afmv92qT4eclXRN68UoqNKOMjBbeW4tBg9rgJ46fNtSizaAEoYAA4vzi+Wun1Lrq6nStDe0Er2rBpF28 + Odejol6XLJ5ygDoRe948LPDwwNVykCDECIWQKBFJjmBsOa9ly5byENQSP++EXv7YQXyaR/AeuA2KbZHR + pgDvqEebUgX8wfl8LVupaTjCt4b00FNRK3mCvALarPt5+nTeqSuj2rS4chq+2vQWss7P75X6BXqGoFUT + /YXuOHvc8Ryyfyl5U49ssyt7I1fTa2rW+PwJBYUEzBYOAsZ+hZHV3V1z9+v5UUQIcHhu0D+SFcgBrLM2 + btJC4eHNm/E6vlJ3xLRp+m/tzUTTkQ7ZbTPuSFbs5SLZqgd1SkJCB8G5q/280ZOobGshgUXHZrjrjuyH + LhnANF/BPHk3kJrHxIgvMtnTKKxFR9tyJlwPtrhJlnyuIPHjBqVlwTJubhKne2Oz3qDphlAehOzpLmjb + HNjPtt3RlVdO996mT8vP5wcuLHAAR9En+fBMOqlpgV+EYm1SeCF+uvKvVLb9DMJv1nu7Ejev3J+SihZ+ + pecZV/p4Uy8g8vEdArKnuT8wR/Ywnh90OxvZO+Mbe2SboJDVRmQ7QaQbZOrKHnJlmwOy7QHZfrTblQge + vuhp+Uh7mftm8Bn0ly2iABh8zxbwP60Miivb/GXXlQAMwlLXiKL0myObIF/8PozvFx7w/1IJYNqwAs7M + jJp2Jaw3Sqq/KxE8XZdgL/jCyr6GK9v8ZRdCkBBGLamECRibp6HShgF7UiF9/hdX9jX+//bOprWRJN33 + uSiRU0yvcmnQMjf5BerS8QW8Oau71OpA7IKEo0VvBm0uYQuGA7oeLujc1QEjqEMhEE7ZZSjkTFE4ZdLe + +BRGLmMM7vaM7EJSIbU8Dcbtqrr/JzLteuk+M9On+1bL2c+vSql8i4gn4h9PvKTSmXdku/OO6y4uGoXp + WgF5cbrXODA10HZumuZM1zuy3XnHdTGVIIXNhVqITOMujDFNA41Vi/ve+42r0P1mcz5qohfNNN1cKEkn + 7Czw/QYCp6CVNhpjeGV6YSYfYJD1MSxwvvihwL+hiwC/BX4oMJMrWOCc80OB6dpGdpC5//yIwA797sfk + BBY453AfnHNY4JzDAuccFjjnsMA5hwXOOSxwzmGBcw4LnHNY4JzDAuccFjjnsMA5hwXOOSxwzmGBcw4L + nHNY4JzDAuccFjjnsMA5hwXOOSxwzmGBcw4LnHNY4JzDAuccFjjnsMA5hwXOOSxwzmGBcw4LnHNY4JzD + AuccFjjnsMA5hwXOOSxwzmGBcw4LnHNY4JzDAuccFjjnsMA5hwXOOSxwzsmjwOl7X9M1s4pMYdvkzuzP + 8mxeJovvEr0SG9CbaylUrsifwIXnBb3c0kL5zabfr1Y3ZLXvvxByhd4Lv7ixIXWhpLV5S3y/sLT8RaPR + 1I1+f2HVvGbaibJo5gZXOOYtv8KRWPPohWVYtxT2OrajtJK2wGFXCltiW6ah7sifwLqw0lju62Lx0aNH + C18sL2/IWr/xoiybEFT7UrqqVGquPFpoNHzfp9eJN1aaCwt93TcCP3rxIotnXtBaiVQ2aXuusouWsujl + 3UoUSXbPs1zHEp7jFh0XLZVnAr0nfwILpf2nvy+gCOhVbn1/RfejxorciPrb9XpVCMuxpCq5/nPoDPx6 + S0ndd3XhueP2tZw7gYUSnpSO9ITUtqs9D2oLxykqj7xYIje06UhNcrvY/pgcCizKG0vpu/Wr1WqtJlr1 + en9Bbqyu1iv1VrncEuVWq1rFpwXq2Fku1+tYq1Wr27XFTz3g10dreKuR1xZOpEhNUlEJLT0Hrm3bENeD + ukpL10Vz/RG5ExgKbm1tTd6D9dN3deXWtrcmW1tra1jQysHpHVsHZuOP+LTr1Xl77Zunk9hVuqhDLSwl + vUjZrnItFURhGGkFnxWu8uwkUUWInL3A/T35E7i19fLl1x/y8uuXLw+rqtae9WbXRK9nvjJ616/AtVm+ + Oq0vz10JhKNRd9pNguGo2+2G0ikWaZTlTnUcBLHnOUoppxh1uxG6H+WiY/6I3AlcrUxev3379vUdb7/G + Z9Yq19q9Dnnw2ulB++Cg/a4N1tbgvH+g9YO1dvvdu6PT7bkrgTjodqdBkkyhchgmykqCALu6wyCYjrpR + pINpSpc+Ye5H0dXa5O3rwd7Xr/+a8nrz+P++ft1rlVchcKVSr7cPT9fX67V6jUAf/OoPGHzV1yrY8e5o + q+bPWxMNEeNuEo2mVjhNtHS8EDIGQTjCJwgwZ0oSDc3jOAwSHce5H2RV6x3oeQqB/y0VeDC5eP36uNJa + bc9Oqsv97T+++pc//hEu3IasNb3afvmH+vq/fnNyfXS6fnB0Wm1m8cwNkXZ1IhOIOh1N0Q/ruEsv8Naj + mEZXji09KcJppDX0dywv/x5c77x9+/L0e/Lg//Vvf339enKCNnqv0qq2Z516o7/9f/7yl1evXlKH+267 + 9q57+PLk9ODk1c7Jy9Ptg+vT1cK8ebDsjtD2ogMOwgRT4qKVDKkvVtNQxEEcKcuBA4fK8XTYDSKVew8u + tyZv337dObn4+q+vIe/Xg4MeOuIBBK7MTloP++3rndNTcuD27F374Oi6d/F97+Skc3BwvVVrX5/WVuet + BEQS6yiCdnBSIGUyjZOgq4OuCLtaCzcKu92ErmVhV5D/JrpcnkDQ3ckEfkv6TjporeHB5SUIXBZrs16n + MzuczSr12SFUPT398wn07WzNJmsYZ0+2505gFSYhetwpDayCMHJk2JX4WHEXLusoqaMAJ2hLRWEUw4Wz + YLfkT+DqBIJC2EkHc6CZEdoIXK30Oq3WZFY5WHtXeXddWZuh03317//+l5PjzsnJwfVkrf5utlUtzVsT + 7cAvg2DYTZIkjiPpqbCrnKTr6ilGWZ4Hl468qJsIBx2xF8ncC1xtQWCMrV4en2wdHEyuSV8SeKPV3jlp + tdZOtzGCrh/M1tauT9fbr775j7/s9CDw6XVnaxsCL5WyeOaHCBrKIEA7HSdhrOC9joi7kd0dBVoIVZTC + 0RhBoyPWnqV/A6PoExpAU/N8cXFB7TTJ3auXSeDVhVr9KL2k0T6Yvau3X82O/vcO+uCjNlrrbcyDW9V5 + e7duGIZonYcjgHlu4rrJCE1yIL1gmlgRhtXK1UpiEoxdtpKfmp8/gWvGg0lhWtAqCdwqL7V7J9Vmf/1o + 5/SPpzRJalfq7eu1g5f/snNy8s36Olrsd0cn83epMuhOMeGdBlorS8eRJZMRjaocdMuhk0ytyLNtTwej + UaI9W/82pkm3ut5C06SNVmWn03rxrH8Edde3a/XWu9nawasDdMMk8B/WZ4ft9vWk3p+3ElCW0JbADNh1 + vGiUWDZE9aw4mIZhN4YnaykUXfsIu9NQCfnp79n5G2TVJ58KDGfea7VaNMhSfvTqFN67XWvVD2eV9tHh + 4asT9MH0fdg+6G3Nn8AOpr6OBQUTNNbTyMIAS0VotLWFaREmw0VojUmU52HntBvn/vfgcuXwzdu3Hyj8 + mi5NX2/4hfbRSavf3z46oUlwu/3uEIq+Ojp6hYkTBJ6dtmtrs7XthTksAQdDZIyloV+gJUbRQiWxKgpI + imGWTIJEKyWVUjTWyn0TXaiO3pDCRKbvmzdvrt1nCxB4e3t9HXPg2SHGJLPZpEI/PLTbmAgfttfblcrW + bCuaO4FtSzn0Sz6aX4joCTvsukK6ntSiqKQDWbXjCXOLBwbROvc/F7oLEBgK3/2gRPq+GeumpiEUGud6 + ZQ1TyiSJKtRst7ajCPvebW/X663KbKu1mMUzNwghHCU9TzkWdLSUiEO6bQOeKi2P7uqw4L7a9TwXGv9w + hJg/D/ZJ4DdvjcYG2hw2m6uVzkmlQj8xEK0qxIXA9do2advGqKte37reqi7P3bVoq2gr7QhyXwjrOVKi + zfZcy5MKe4VSNmns4j+a8t/ATXfN6Zury6vhFekKrrpX45s3Q+VW1nqD473ezvc7Kb0eFt8fpd87R0ff + fPPN0cvT9e1qFs+8ICWpaDle0SpKRXfgCVtKuCtWLBxCo23ZDqa/tLDpTryPyJ/AMngzHl0FQxIXn3H4 + Zjh6M5Yb9cpO7zhVE6L2oDM+R98c9Xb2BnsQGMOto6P19e1+Fs+84NlF7TnKci10uB5k1A6k9ERRKE8K + 8l3XcuDDOIKNLNB78iewF14NpzfdKQkMhcfYHN1M9Uqjtl1voUGmW+3oZju60a6V/eiPrtm01Nv9RuP+ + l8BH5E5guyy08PxHGFVFzWdNvbIUFZeXVuOVRqNWo7vd7Y0N26Z7Lstl2yq9eFFqZn/Y4LeqzWfPmvN3 + MfpnkT+BzX3ipVJJFUvS8V5o/7nUD3T0qNHo1/r9fq1qbqdNcQtuaYWAqiVVLr8AWTx5IX9NtMDAA/2U + JcWGKm/Yotn0C77+wkfeqn38q77XFxQKL8htm5a1olos8H1Ae1payovERplucy83Fhr9L1b7/QKaY6Oe + i0wDczLln/6+oVEoNPxWq/ksb/rmUGDlPfD9knDLEHhjQ8lGvx/1V/UyBF7J/BMNeOqr6IxtSAtoSX0w + Czz3PPWfP3rka1eXy9It+M1Hevn3S9VWVLaoq7Vt47zGm7OhVhk+DIGfNZVCY503hfMn8GLB95vPnyvh + SPXc1yuPLGm63bKFEXOB9L1tnm8FpiJwCyss8D3hw2uNaX5cmhfZ8Fvqf83+FNvMl8yfhNNBzJpK3EQz + 9wsWOOewwDmHBc45LHDOYYFzDgucc/InsLJdRztOpJTlOZruRHOksoRjRY4QjhZSSOXYQtrCsR3Htora + sZQnpCXp4Rc/8pP5/SZ/Aus4iuPIPNBgOgqgoIpGUyXi6WUgtadsUXQdujlCRkJIqZUy97Np2/ME3Z+a + xZIb8ifwaAyGV5dgfDPWUnnJ5QjueXNzGTqRp4Sl6LE0inxcFoXQgZbS0zLQ9KQx84SiPJE/gafdy5tg + eqVFGLqjMdpo2b3seuHlOBmOpYjpqTRCOV4SC+FaaKr1eCSlEKNx6ErLUfP2t2c/lxwOsuzhUAdXtj0c + FacQ2FXDsQ7Hl6EVjMeh0ELYFvrh6dgVjtCOlNObwNPx1TDy0CfnrQvO4yArGo7c5CZ2x0PyYEuEN5fB + 5WWCERe+YvivpVRRTi+lRsvsWXDhS1uNb2LPk66wuYmeexQ8OLmy1HjqwHeFe3N1dTnGmiWHw/GVq9FG + W8JKQgyxHBo7W8FNN7zqFoXSKn1KYJ7In8DjqzdvrsZXkb4cOaNhJKdXN8PYGd0oFY2HUWJbdG8x3dRD + D3hUynHteIwBmSVoLnX3W/E/zgc/MM8j+RNYx+NxFFxF8qar0QdjfjQcRtbwUngYTlnogelps7bl0CNc + MTO21HR4+ebqcjiMMXG2bJ1F84+SlZ9LBVey5u+mvRz2wckITfRNhGGTHI2lI6LhWBVHl8qOxiPzOG1H + YEIEbbEu0UZPR8Obm+EQc2W6oeunPm32rvywTvd6zdtt1fkTuKiHQ6Ev9ejqKgq6sVR6NFbO8MZxIDCG + URhIea60ky7kFBJz4qCLiVU3mGJSbOmffiXLFCC+57Ts8iewE47HozCKroY3cZRMpReNxhhxjZwiBHYd + IYv0N5j26FJ7yoM/q+l4fHU1vhkl8HaMvn4i1P2aG3Gz8vu0AE0X/SHZ/s9F/gQej28ux93gchzcxGp6 + qaUcXnrBVYA5EVR2pIbbSiGmY4cERn8cmV5bRfRXeor+7vYngm73xQfl+ImCmazvyfZ/LvIn8KhLj2K9 + HEfhTRAOx5H0MH4aX0YuPHhIfy5tK0yUvCjxFGbBdPnZQ6MeFW2BIbXwfrIL0x3W1PNm5Tdvz7rMn8BW + hGHVzVCK6BIT4EBIPRwPL7tw2ggDKcuDAI5Lz8inn5ps4Uld9OLYka6FQRf9vfVPhOQtscCfD0x+ZBI6 + UjmRVpGiCxlBktDlK9kNi5gAQ0b0vPTntkVX2UJo19JoriUcmB6HkUXzj5ONm7Pym7cCzKEHf2ZuCzDd + Il+eK1jgn8ld+ZlpcIkvdOSNDwU2461s/7zAAv9M7sqPJkA/InA2OXpPtv9zwQL/TLIC/C/FSw98QLb/ + c8EC/4LMYwGywD8bGlvhKys/ngf/0ri2fVemBdcum1cSfgy9qfAfolxOZ7Xp24eJ2xVqXNMC+oGA9AsS + QrmFrLHOds8J915g162WkYlSqfi7pv+oUG6tTTrg+PiYvgwTs6eTLv8mW62mhlb018QoF3JM2yYHzcqm + sLr6N9/K8mv0sX+P+y/wUrW6RGI4T1eajwrVtd7+BdjcPDvD52Ifa7u72Kad2fLiLP36BJw429JNyPpf + CEwPYZq/1+78HfIjsFt6/vz5UnWyf/aYODf/Nzc3swXA1/k5LbODWBDmCJ1xvrnfqbSouU0FpsJAY30r + 8OrqapUF/uy46dOuSmgbSw8LS9XZhZEuFZDIJCVNU51TUe+OA6Pz+ZPHj/eP11puE3G5aPZRMtTiUrOb + llK12u9Xq+n2ezI75pX7LzDKnZ5Y59obbsGvVmf7JNkZNdCGM1onpz4/27zYPNvHHnMGoKPpaWf7Z5uQ + ePOiV6Fn7iC2MilsysaoCEzpENn2LZkd80oOBC4sLdEtb2UhFYbLvQsSbvNscLyXMRgMyIc3B3uDi/3j + wcXZ3ndmm+SF4Ps4vrf33dnjf358dieweQBP2kxDaxukat6/AsqFwHRPow2Bq+VWq7cJ6c4uBmYgPZlg + cdw53idB94/3dgcQeHCMbRqB7dHBlD14NppwCLxEApOqAHFDbNI39VMab6GHvlfkQWDoUbDKLSHLotWa + nUGozYvBZHCxu7vXoSUJ+vjxAML2OpPeYA9ymiE2dB0M9nf3Meze3PyWGnEI3KrSY+9SgW16CF4he3Za + Ki9I070v5Efg8kaZLnL0NjFY2twcTDA32u10aLl3vI8xFTkqvdAfSyiLBpo8+uXtFOkMVeAJmvFJvaWX + Hmq3KElhEtiXUi0+wBi99PzRysqKNk/ghtpZ+vNOvgRuGYFJ4cGE+t7OBC663zk+w7j5DJ1tp9PbNUBP + 8uDeNR2nDyZXCIdme1KpLlUXHzriVuAHnuf6qlRqlprNlWbzEQv8efkRD4ZQEJh6VuOvnckETfR3e4Me + tdApe6aJpmtb5NjEHjz4yfnmbm8LtaT4QBZpnFWFwoWnXsF/8LRQeq79R899FvgzkwnsWh8K/HizBw/e + 60229tDJdjr7j2lE1UELDSknE6hK06XjDqTG2BoD7f0BhtEk8MXu7F2ltVSQJVSZMia+/YIPRR8+9P2C + X3iITyETOB1Wm955nsmHwJD4E4HTPniGPnjXCIwut3fc6VzvDvbhuIMLdLlnx72XaK0vLmiUhW748ZdG + 4Zcz+LBa8elVxCTwU+kKJQsFLZeXIr3Uv/XgTF8W+P8zsH/JmE0CoxOe3QpMnSsNmtEHk8BnNHq+3t0d + DHroiTOBd+HL6WRp72LzHAI/hsDXk5YuPGrChavVGjxYCqG1KC5XMcteXa7eenCW/ryTJ4HtpVRgukjV + o8b4eGutgzEz+mBqos3vRdiJPvn4GJOp745307No3zFmSl99iaBwe3hwwTxbGgLXVqUUG7LcCltoHpbq + SYsF/rwY+zHIsixn8SE0mME34Yc9jJ9pFA0Pxth5/2z/eLA7oEEX9cW9wfF3JPAAZ+3ST0z7xxD4/Msv + H59fXHS2Kq2y0iQwPWZ6dbksyq2NZHxY396uz4axawS+vRt67smFwDb95qNKhQIJfIE578UFKXZ20bud + B2+enaGj3cdoCj3u8eAMLo1ZkrmwhdHW5sXe3sW35//0T+S/lVarTO+JQ9y2uVjZr7fK5crh9el2/fS6 + u0FH7tGTWvIgMF05tkrNlWYq8JOvHsMl9+DJmxgtQ2AszY8PkHTfuKu5UgmvzQQ2R1KB92drLfMXLHcU + Gl+YG0IOXn6zvn7UWytDYKpQ94WcCAwPvhP4n7/8apOcNhV4k649n6Ed3twfYCh169CbONbb7XWOzY8R + eyc7F99+++X55mCrWnbo+Xd3D2Mp+I3GA99frZ98/x//enRSa1VZ4M8KCeyWsXIr8OaTL786Q5N7DoH3 + js9oArx3BkX3zTVoiAm9sXl2vLd7Mciuc3Qm8OBv6VLlWnUjfdHj7V8Zur6vV1Yatfbp96+Odk7b2yzw + 5+XHBH5ydvadEXgfvrpHvwUS+DJbe99hGHb+GFsQ/Tscw3xqb4AmmgTGAIve9/iBwMLVK88a9dOd//zz + n7/fOVxvscCfFSMwDbLoFYRG4K/+5xN0q6TXOb7pd99NcwcHrdBPwJD3yZMvsUzJ9qbXonuVclkZgW+b + 6HJ5o7nyrF8/PTn+H3/aOTndZoE/L7cCW3ej6K+ePDn/FqLS9Q50xOfmrisjZXr/BulLc+X3N+2cp+vn + j/d7lWXbwjCKmumUclRuNpur9Unn+E9/2ukctlngz0sqMFZI4H6VpknQFEoa6W4xIhuHfkwHjEe/FxjQ + 5vkmBFbCQQ9M7+NNsSOXBG7PZnt//s/O7LDOffDnxQhMK89/V9LVZb1Fv/3CddN7Kz+C3NeQbf+Ai91J + S3yinVtoPHv2rL9dr1d6O/XVWm3e3hD+d7j/AtMNd7Sinj73+8vVSod+3cW4ySx/GoNOpfrpIxwKjVTg + 7Vb95KTf7PfvWQnlSeCnhf7qarW+trW1NcHnv0F9uRCZWN9DAjca/VZNrx60G82CbxK7P+RDYJLYefr0 + gd/vry6vVpeW6FcCQ7XaqtFfHaVvc6/V8LWdrmW76bZqkG4sPWg2PxHQpduylnCCv1pvrTT/G49Z+nXJ + j8DFxcKDB/1+X2v/wfJSv+9DbSKTz8hoVug94Nn+atX3fXp/cFPhULXa9wu/+1Rg211aol8d+oVWq+CX + MU++V+RDYFop+X7h4UKj36DbXgm4Ht0guWjZGwSdQ/dZLS3RoUKhtEiz5xK94h2d7Erp4dLy8u8f/OB5 + 0TaFgMKoLlJimF5mgT8vJgO0olTBLywUGg8WLQUZyg+J5eWHzZUV8+yMlI0NUqjUTB+XQnusjRcv6C3+ + 8GX/YVGYl5F+zGKh0GxSzZFoH37k+Fxz7wVGDsyvwZYrikZhld7TXFbK95WqqluBISJ9ZQKn7wk2OyAw + aJaeLvj+4sYPBHzxIhN4YQUCRz/5SXi/NmjhPvqX7b6XUGeM5jp9K3D6xyamFb6DTvr0IgW20yenmMA/ + egkDpUJ/YEh/ZfhJD30foHcmf/iPYRiGYRiGYRiGYRiGYRiGYRiGYRiGYRiGYRiGYRiGYRiGYRiGYRiG + YRiGYRiGYRiGYRiGYRiGYRiGYRiGYRiGYRiG+ZvYGdkmkzcyfVngvJLpywLnlUxfFjivZPr+YgKbV1d8 + QLab+bXI9GWB80qm7y8ncPq6pDuy3cyvRabvLyXwD1+MJRwk4ji2wsexLWG2bculPZa0hCuKlrIdSzlK + CWwBnOEIOD9WbdMGKKVwjqUQmZK2i3C2hegoPkulJ1LUjuVkqwDRC+UKxCssCucKF/EjTZhBKQhL2E4R + IWyBE2CRKQY6hDQRw61dt+EArE7f1U4bJlNY2K4iWxANjLY9kW4hHtechk1jkHnHHe1wcZgyiG+XPsiz + hZQ82OkiPVsge4gLBiEcNmABmUhhsNdDwVF+YD0s8wRy4Cqc4GSlhgNYUAGQ7Q7McYpOEf8dZILCmrRh + OlIp4gTsoQSoGDO7lCjaJiy08FynSFHb9A5zkylHPVwsLD59+iCTl970Z4rbQglQzKZYSBgFwyhaUgpr + NjRTKH1FiZvyQKpUjNA1g96Vbna4lksCk/Y4iOwhDQSiAyhPE56qhaQt1BrsoKMSydCLuCk+solqA4ly + F39qKSlH2SSdjF0qDUcVwJxEi+xcg3mFO5BKKiWzDZRFek562u3JxpHwn8rBZAAFiaqLUJIsN+lR/UXB + I1o6MbWXoiKBbdvDjjSclNJ1Fao31X4cN/UTeTWn42PiQr5dWIYUqBJQVSQD6EMOYMorDUHHU7tMGbu2 + jfxQphTZjOI0xWW79gcOvLhICySEEFQJUf5U38kJEBE5HhJHpU3LxEF0yCulegtFjWpKCZNz4htQQhSK + zDUZpcpFcmCBJXJsqg/SkqZu0OtbTR5oBTIjHFKwUR0oIjIaiVI0FA+Fg9Og0mJfZhepi0I0wQiyn0oP + C6RnCoZ8iJom5Iv8KHUpKhNjFzaNmVlwEwRJpeWKr6IgH4d7majwZRIkaVChMYox+UbjhSRwGsxBVDjV + hVs78K5UYCpm44tknLErjQ6GI3pKgXYhIvKC1C5TXojeeAQZktpFUE0wbSHqFDYpP6joCCvtRR+q+r5f + 8AsPjcyoiGnCRihkF45lAiEwtaBIgxomRAgT6BSKjU4wqsAgfFFWcAJOQ5axTA0y3i9ME0Ba3iVCAiAO + 5NzUJFKfNMRplCk01iYt7KAaTgsUAlWrNBxqGrJMTfKdXUicioIqHFmWbVMxkcrYpuRoB7wJ0RijSaq0 + IBEPlkgmDY0iIzuRq9QuFARqJeoqghsD6GSS1mQfrZ1r8o5SNMfJIIrTRVEIR1IBkpImBLXBlKUsPTIF + JpKBZDEOmnpGB41dZCHZgdBk7p1d+KI0KBlESpUHtZ4igPtKx7gteEhCE2SmUQwlSoaSJ0lkTQq3aFke + OaipQvBwYwk1U6bSC5hB3oKTjQHYR1XL5B0mok2DutSFw1gILLE3JS1h0po6V9itpERMHnkAjEfThITJ + EyiXVCmhOo0QsrwqDTuF8u7sIquylgdnpPHjRDKHDKI+HiZlEZhqkJ6DE5CsMZoqLQxJnT8rB6MqeRE+ + 1IiasjYxQDH6RyMQWALXJXdGxURBUF0kcJ5A9YJfUxNqPDUNTXXGzF1ITOOjlBuK+zYcFTCOZxGRQRQx + VYXULgAzUX5U88gJ0z4f7kLKoQ9eWGg0GrSAH2MNnqYlmhoZISuW1Mi0jDQ1oBrJ2ihNGjghXiE1enUr + goe7Wks0RrS0rVibKKgMNDXjGtuOpSOBUYOW6EQRPfZHEtUP3QZExbkoYoguHK1hnYwQqVWUGqZKjapg + wiEm7HV1TJWajrlpuCim4YFGA5Pa5UhY5KgIQto4A+MtranENaoULCKFsIo2HYdwEH0AKg1ybOM0BI8k + 4kdOUBVp4VgROZ/WLkLSGdJGaNRXjWOIDtrQkoI4XlGhSKhgkL7AyZalNVoXmIETPK2KUM6UBvXHtkSk + WKW8UklhFUVFAzxqySEhGYcokDZVMsoPskIhEDMMuLULUaMchO1py0MtQSMhKDtwrAi+YEU+iUvS+jrS + 0NgSOo6lLaNQw5MiKk4dR64jo4SES7TrORFEtNwYS6FxGoyMtWsjHJKTYWQ7OopQFlESoUYlMbInkxB1 + F+swAadJ7IgxkKCIRKqnSiI4d5zAWAkDUP/jWAkVhTaGNHFEmYsjlG8UIjDZBYuQA8dNEjQH0Xu7FJbK + 0iFVOZjhOBpJoQ4mGhrGEXSCXUgqSWCijhP4NsxVRdiFqgEzkPk4iZSxC0qZ9Mgu7EbBIHRMUYSQmVJC + xcfJLp0hBMxA7aMqJwXlG+dRXTLhZJhAkCiE+yFm7VqICNmEXanJdHJsyiu1S93mh+yyVQgNXMSvTCYg + yod2RRjXyzCG9nGIwTbCUb1LNFJFNr9YQI4bC9An8n0UeBQiTR0HEaoKSg/OkFBxhgHMiYPY9ewEqZFm + 0CgKYBpOQ9lHZqmD2HEQQsPgMLE8hdiwNww8WiamZNEiYBWFg4hQ1aE4lAugpwyxw4FRlPMQZSiTwNYU + zvEgImqGTgJNtkNVCof8B6FyYG1yaxcZI2EoXAX5xzIKQ+Q0CiN4I9kl45DiD0KEhgWo9DGK2hiKqANk + SlPWqGJoTBaQQZRDCM8gu4SLXDlQMojQWIUoI8omqRyiEYkRDmknaKMcxO8qnOEUkQgM0EGIypwE8ErI + h5KCGWieYBc0hAFQC+VVlEEoPQ+lrTwL+UFtyOxKICjs0sgs8o3oMrtQEKg6nqWDhKpxYBddmIEyoZgl + Cj76fSEJEv8LSpUEZvIFXZ78kGw3wzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAM + wzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAM + wzAMwzAMwzAMwzAMwzAMwzAMwzDML4pl/T+d7/NckcJq8QAAAABJRU5ErkJggg== + + + + 406, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAr9JREFUWEfd + Vz2I1EAUjooIW2x+OgUtxEosBBVRQQS5ThvFRgXx0MLCzlOwshAtBIt1J9ktxc5fOCsVf4o7/Idr5HAm + gVNQULARFE4P4/cmL9kkFyRZEl384JHNm+997+3Mm0lijBScjmrbruw4Qr21hfzpuCqsw6D5A1eptZGD + 0y2G7arpfHDdhhxTnC4Lp6u2JUShbtie3GN5alcdRlqkmegjF6cdAMTxKLn8YIThEnbXh+vhMuh/ohyW + K4+ydwCszwQXcJ9dtcNx5YMoh3+KXQOMbAHwH0Tgc9hXW6jP4DyEwHYeNox+uJzWNL/usbWuvF/FzOoF + 4P6Y9uUMnfyrLYItxMHvC0WcxIT6bpwLl0Z6FQuAuE8+/PPJtvDXtbtyK3gzzLtFHKsrdyLJPXCfFJu8 + pMWAagV01Ap9TwV4/g7tAyzXP8n+N+wqjaELMHtyTPsAnJCn2d9wAQCmUC8BfLNoqHHcn8G93svxEkDs + OGLnta/AMDYTnyu1NqHZCzYTx/bUiSJObOgfNXQBBAgcgu8FgpNtSI3HwxqWkBvz2y82o/+xxbThCqgT + /3kBWGe7H6zhu0I0VoDp+psQ+4qaE3YnbtA8ai+g1Z9bica8Sol1bMrgf5Q+PwilCoDYAoInYXvpGc7D + WeCQAu8s+N/ihCj8GU7JI/j9NPGRnlCvcT1Az4NyM5A2vJzg5DuPgNVMM0xP7ofoXIbjqsM8rEHbj2Yy + rYUYBd67KOZPM0DiQr3MBNMUQxDXxwOfnAf3Ynqf50G9gLjbOj6jJyeYMkAyA9wDeABtQCGX4f+SDtYC + WCLTlWt1YAk4PbUeRVyDLUQ5qjQhXjgsEezD+F2MzZrdYDePVEaz50AJjHYB6NzotRyP20Zey7EN0Tv0 + MCt+LW/8w8SVNxP9og8TArp0KiE1ZMgxzekW459/nP59GMZveV5fH1DoJmkAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAA7RJREFUWEe9 + l9uLTVEcx8fBuMeDpzEP0zTGXE8yUcY1HlyeJU/iiX9AQu4ePCkvUvwL8kIRieSS3F4URW5RJOOWEI3P + d8137Tl7z95z5hh863vW3t/f7/dda6+999rr1NWKzs7Og/BXV1dXf4Y/4U6n/TvQ+flMxwmJnXPa6NHW + 1taK6dbGxsZJlgLiAGhXWZK2Om8ALS0tEzo6OrbMAZZGBozmw4++sgtI4wYiNQ1gHNpZ6x/hfOvDg4Je + kj+rsIKnCZXK5fIUYjel0Q4ZALzR0NAwGWmsaqwF2rN3oKIAJCyHX11wielbwnGfzuEFtDgr/e3t7Utd + FutiZx/Iu6hj2nfykJdj8l7usjRIWgy/ufBUT0/PeOnd3d1tnL+2gfgC7tP9DYWgqalpItpe8l5V5L2k + 8xbF5SVP6eoDz2WhsBIEdzpBr1jZcgCdNWJ2Eq7hdMyAmosSM7MWjxOtra2zrAXI097qY7flQSDWE7yi + BPheV+7QqCEvedr7imbMoTT0AJFw24lv/8Yg8GmXlz3jQ1qM5ubm6czGYxUw5ccs/zHwOe7OH+I71XIx + PAtfPIAFllNAX4fZXXI+mHekOZwCsV55wT69xpYHgdFhgpcjOb+vAtqrTkkB/ZDieSR20GkpELvm+D3a + yr4OKFhkttH1CdAWO/aMK17Pkz5T1DG6Xs9+lvCFTk9AfHP0rSQ+vyoHoMUkkMBc16ZALFxJ3ntMJysV + ozZ35ng950V/M/SbDMB5hdBiQt4POvhuKQstv/ok/+C4NCAVI+k3OagCOq7XlMFvlrIoaXAaQFxFh8OQ + AcCqtwD9Qcy1lIDYCsVo71pKofAWUJC3u5HRJtcmQNvg+BMMZ1uW+WxpiumBtJxg2IeQnwOc1PIa7leh + cjL8ib7HaSkQu64c4tnXcGg+m5dpBOMnOPf7jV7mqk5i8Bw+9XGHwykQW2CvvqrLsIDRVPhIRbRHLP8x + 8DnqAVRfir0M33DBW0YfvuejgZ+P5GNU+CVkdP/rc6ydVb1DgyAw7IYE/URWz0GJWVujZ0I11gJUa2/1 + sd3yIBCrbsloZXCGDnbkbMn2wfA9cO7reAuzWzK4KBRmQYIWiGRTCrW4hDeC44vwk45F7m3RplR8o5b8 + kW9KI0jQ9zsMooLalo/VQ4pZ4bac9hacy4zM4DzurALRq2/LI5ToAhWfRar5j4k2H2jhjUIf+R+TCK/d + 2yhMPbGcj/ivmWdsO3uEbkujRxxAHrMD+Cego110lPstgDX+Pa+r+w3pnjPegdbXdQAAAABJRU5ErkJg + gg== + + + + 109, 17 + + + 263, 17 + + + 65 + + \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/TbLoginForm.Designer.cs b/应用/TBAppraisalTools/Forms/TbLoginForm.Designer.cs new file mode 100644 index 0000000..f58c9ff --- /dev/null +++ b/应用/TBAppraisalTools/Forms/TbLoginForm.Designer.cs @@ -0,0 +1,64 @@ +namespace TBAppraisalTools.Forms +{ + partial class TbLoginForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.webBrowser1 = new System.Windows.Forms.WebBrowser(); + this.SuspendLayout(); + // + // webBrowser1 + // + this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webBrowser1.Location = new System.Drawing.Point(0, 0); + this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20); + this.webBrowser1.Name = "webBrowser1"; + this.webBrowser1.ScriptErrorsSuppressed = true; + this.webBrowser1.Size = new System.Drawing.Size(443, 381); + this.webBrowser1.TabIndex = 0; + this.webBrowser1.Url = new System.Uri("https://login.taobao.com/member/login.jhtml?style=mini&newMini2=true", System.UriKind.Absolute); + // + // TbLoginForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(443, 381); + this.Controls.Add(this.webBrowser1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "TbLoginForm"; + this.Text = "TbLoginForm"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.WebBrowser webBrowser1; + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/TbLoginForm.cs b/应用/TBAppraisalTools/Forms/TbLoginForm.cs new file mode 100644 index 0000000..095e426 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/TbLoginForm.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using TBAppraisalTools.Properties; + +namespace TBAppraisalTools.Forms +{ + public partial class TbLoginForm : BaseForm + { + public TbLoginForm() + { + InitializeComponent(); + this.Text = Resources.TbLoginFormTitle; + } + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/TbLoginForm.resx b/应用/TBAppraisalTools/Forms/TbLoginForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/TbLoginForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/TbLoginListForm.Designer.cs b/应用/TBAppraisalTools/Forms/TbLoginListForm.Designer.cs new file mode 100644 index 0000000..81d30be --- /dev/null +++ b/应用/TBAppraisalTools/Forms/TbLoginListForm.Designer.cs @@ -0,0 +1,173 @@ +namespace TBAppraisalTools.Forms +{ + partial class TbLoginListForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.panel1 = new System.Windows.Forms.Panel(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.登录淘宝ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除淘宝ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.gridControl1); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(604, 443); + this.panel1.TabIndex = 0; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(604, 443); + this.gridControl1.TabIndex = 7; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.登录淘宝ToolStripMenuItem, + this.删除淘宝ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(181, 70); + // + // 登录淘宝ToolStripMenuItem + // + this.登录淘宝ToolStripMenuItem.Name = "登录淘宝ToolStripMenuItem"; + this.登录淘宝ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.登录淘宝ToolStripMenuItem.Text = "登录淘宝"; + this.登录淘宝ToolStripMenuItem.Click += new System.EventHandler(this.登录淘宝ToolStripMenuItem_Click); + // + // 删除淘宝ToolStripMenuItem + // + this.删除淘宝ToolStripMenuItem.Name = "删除淘宝ToolStripMenuItem"; + this.删除淘宝ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除淘宝ToolStripMenuItem.Text = "删除选中"; + this.删除淘宝ToolStripMenuItem.Click += new System.EventHandler(this.删除淘宝ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn2, + this.gridColumn3, + this.gridColumn5}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "淘宝账号"; + this.gridColumn2.FieldName = "TbLoginName"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 0; + this.gridColumn2.Width = 139; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "Cookies"; + this.gridColumn3.FieldName = "Cookies"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 1; + this.gridColumn3.Width = 457; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "状态"; + this.gridColumn5.FieldName = "OnLine"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 2; + this.gridColumn5.Width = 108; + // + // TbLoginListForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(604, 443); + this.Controls.Add(this.panel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "TbLoginListForm"; + this.Text = "TbLoginListForm"; + this.Load += new System.EventHandler(this.TbLoginListForm_Load); + this.panel1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 登录淘宝ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除淘宝ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/TbLoginListForm.cs b/应用/TBAppraisalTools/Forms/TbLoginListForm.cs new file mode 100644 index 0000000..9003921 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/TbLoginListForm.cs @@ -0,0 +1,95 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using CsharpHttpHelper; +using System; +using System.Linq; +using System.Text.RegularExpressions; +using TBAppraisalTools.Properties; +using UI.Framework.Forms; + +namespace TBAppraisalTools.Forms +{ + public partial class TbLoginListForm : BaseForm + { + public TbLoginListForm() + { + InitializeComponent(); + this.Text = Resources.TbLoginListFormTitle; + } + + private void 登录淘宝ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var loginForm = new TbLoginForm(); + loginForm.ShowDialog(); + var cookies = HttpExtend.Wininet.GetCookies("http://www.taobao.com"); + ShowSuccess(cookies);//TODO + if (cookies.Contains("tracknick")) + { + var reg = Regex.Match(cookies, @"tracknick=(?<用户名>[^;]+?);"); + if (reg.Success) + { + var name = HttpExtend.Unicode2String(HttpHelper.URLDecode(reg.Groups["用户名"].Value)); + + var tbLoginInfo = Class1.Config.TbLoginInfos.FirstOrDefault(f => f.TbLoginName == name); + if (tbLoginInfo != null) + { + tbLoginInfo.OnLine = SwitchType.开启; + tbLoginInfo.Cookies = cookies; + } + else + Class1.Config.TbLoginInfos.Add(new TbLoginInfo() { Cookies = cookies, OnLine = SwitchType.开启, TbLoginName = name }); + Util.Save(Class1.Config); + gridControl1.DataSource = Class1.Config.TbLoginInfos; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void TbLoginListForm_Load(object sender, EventArgs e) + { + gridControl1.DataSource = Class1.Config.TbLoginInfos; + } + + private void 删除淘宝ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows()[0]; + var tbLoginName = gridView1.GetRowCellValue(rows, "TbLoginName").ToString(); + var tbLogin = Class1.Config.TbLoginInfos.FirstOrDefault(f => f.TbLoginName == tbLoginName); + if (tbLogin != null) + Class1.Config.TbLoginInfos.Remove(tbLogin); + gridControl1.DataSource = Class1.Config.TbLoginInfos; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "OnLine") + { + if (e.Value.ToString() == "开启") + e.DisplayText = "在线"; + else + e.DisplayText = "离线"; + } + + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/TBAppraisalTools/Forms/TbLoginListForm.resx b/应用/TBAppraisalTools/Forms/TbLoginListForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/TBAppraisalTools/Forms/TbLoginListForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/应用/TBAppraisalTools/Properties/AssemblyInfo.cs b/应用/TBAppraisalTools/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..40ea440 --- /dev/null +++ b/应用/TBAppraisalTools/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("TBAppraisalTools")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TBAppraisalTools")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("18260060-fb74-4413-aff6-0c4a8508f492")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/TBAppraisalTools/Properties/Resources.Designer.cs b/应用/TBAppraisalTools/Properties/Resources.Designer.cs new file mode 100644 index 0000000..8df7109 --- /dev/null +++ b/应用/TBAppraisalTools/Properties/Resources.Designer.cs @@ -0,0 +1,193 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TBAppraisalTools.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TBAppraisalTools.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 添加图片 的本地化字符串。 + /// + internal static string AddPhotoTitle { + get { + return ResourceManager.GetString("AddPhotoTitle", resourceCulture); + } + } + + /// + /// 查找类似 添加文字 的本地化字符串。 + /// + internal static string AddTextTitle { + get { + return ResourceManager.GetString("AddTextTitle", resourceCulture); + } + } + + /// + /// 查找类似 编辑图片 的本地化字符串。 + /// + internal static string EditPhotoTitle { + get { + return ResourceManager.GetString("EditPhotoTitle", resourceCulture); + } + } + + /// + /// 查找类似 编辑文字 的本地化字符串。 + /// + internal static string EditTextTitle { + get { + return ResourceManager.GetString("EditTextTitle", resourceCulture); + } + } + + /// + /// 查找类似 亲,小二正忙,滑动一下马上回来|挤爆|rgv587_flag 的本地化字符串。 + /// + internal static string KeyWords { + get { + return ResourceManager.GetString("KeyWords", resourceCulture); + } + } + + /// + /// 查找类似 评价工具 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 评价工具 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 评价工具插件 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找类似 淘宝登录 的本地化字符串。 + /// + internal static string TbLoginFormTitle { + get { + return ResourceManager.GetString("TbLoginFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 淘宝登录列表 的本地化字符串。 + /// + internal static string TbLoginListFormTitle { + get { + return ResourceManager.GetString("TbLoginListFormTitle", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 商品主图 { + get { + object obj = ResourceManager.GetObject("商品主图", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 店铺头像 { + get { + object obj = ResourceManager.GetObject("店铺头像", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 背景 { + get { + object obj = ResourceManager.GetObject("背景", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 评价工具 { + get { + object obj = ResourceManager.GetObject("评价工具", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/TBAppraisalTools/Properties/Resources.resx b/应用/TBAppraisalTools/Properties/Resources.resx new file mode 100644 index 0000000..4581256 --- /dev/null +++ b/应用/TBAppraisalTools/Properties/Resources.resx @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 添加图片 + + + 添加文字 + + + 编辑图片 + + + 编辑文字 + + + 亲,小二正忙,滑动一下马上回来|挤爆|rgv587_flag + + + 评价工具 + + + 评价工具 + + + 评价工具插件 + + + 淘宝登录 + + + 淘宝登录列表 + + + + ..\Resources\商品主图.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\店铺头像.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\背景.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\评价工具.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/TBAppraisalTools/Properties/licenses.licx b/应用/TBAppraisalTools/Properties/licenses.licx new file mode 100644 index 0000000..e69de29 diff --git a/应用/TBAppraisalTools/RefreshTbCookiesThread.cs b/应用/TBAppraisalTools/RefreshTbCookiesThread.cs new file mode 100644 index 0000000..21a84ac --- /dev/null +++ b/应用/TBAppraisalTools/RefreshTbCookiesThread.cs @@ -0,0 +1,57 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.SDK; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBAppraisalTools +{ + class RefreshTbCookiesThread : TimerTask + { + private HttpHelper http = new HttpHelper(); + + public override void Run(object state, bool timedOut) + { + try + { + var loginInfos = Class1.Config.TbLoginInfos.Where(f => f.OnLine == SwitchType.开启); + foreach (var tbInfo in loginInfos) + { + try + { + var item = http.GetItem("https://shoucang.taobao.com/shop_collect_list.htm", tbInfo.Cookies); + var result = http.GetHtml(item); + var html = result.Html.Trim(); + if (html.Contains("\"登录页面\"改进建议")) + { + tbInfo.OnLine = SwitchType.关闭; + EventClient.OnEvent(this, $"评价工具 - {tbInfo.TbLoginName} 的心跳包已经过期"); + } + else + { + tbInfo.Cookies = result.UpdateCookies(tbInfo.Cookies); + tbInfo.OnLine = SwitchType.开启; + EventClient.OnEvent(this, $"评价工具 - {tbInfo.TbLoginName} 的心跳成功"); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"评价工具 - 淘宝心跳异常:{ex.Message}"); + } + finally + { + //Api.Framework.Tools.Util.Save(Class1.Config); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"评价工具 - 淘宝心跳:{ex.Message}"); + } + } + } +} diff --git a/应用/TBAppraisalTools/Resources/商品主图.png b/应用/TBAppraisalTools/Resources/商品主图.png new file mode 100644 index 0000000..5f976b3 Binary files /dev/null and b/应用/TBAppraisalTools/Resources/商品主图.png differ diff --git a/应用/TBAppraisalTools/Resources/店铺头像.png b/应用/TBAppraisalTools/Resources/店铺头像.png new file mode 100644 index 0000000..2c676f5 Binary files /dev/null and b/应用/TBAppraisalTools/Resources/店铺头像.png differ diff --git a/应用/TBAppraisalTools/Resources/背景.jpg b/应用/TBAppraisalTools/Resources/背景.jpg new file mode 100644 index 0000000..c0c5f2f Binary files /dev/null and b/应用/TBAppraisalTools/Resources/背景.jpg differ diff --git a/应用/TBAppraisalTools/Resources/评价工具.png b/应用/TBAppraisalTools/Resources/评价工具.png new file mode 100644 index 0000000..418d03d Binary files /dev/null and b/应用/TBAppraisalTools/Resources/评价工具.png differ diff --git a/应用/TBAppraisalTools/TBAppraisalTools.csproj b/应用/TBAppraisalTools/TBAppraisalTools.csproj new file mode 100644 index 0000000..e391519 --- /dev/null +++ b/应用/TBAppraisalTools/TBAppraisalTools.csproj @@ -0,0 +1,234 @@ + + + + + Debug + AnyCPU + {18260060-FB74-4413-AFF6-0C4A8508F492} + Library + Properties + TBAppraisalTools + TBAppraisalTools + v4.6.1 + 512 + true + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + true + full + false + ..\..\..\返利机器人\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\主应用程序\Assembly\apifile\Api.Framework.dll + False + + + ..\..\主应用程序\Assembly\apifile\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\主应用程序\Assembly\apifile\Easy4net.dll + False + + + ..\..\主应用程序\Assembly\apifile\HttpHelper.dll + False + + + False + + + + + + + + + + + + + + ..\..\主应用程序\Assembly\apifile\UI.Framework.dll + False + + + + + + + + + + Form + + + EditPhotoForm.cs + + + Form + + + EditTextForm.cs + + + Form + + + MainForm.cs + + + Form + + + TbLoginForm.cs + + + Form + + + TbLoginListForm.cs + + + + True + True + Resources.resx + + + + + + + + Component + + + Component + + + + + + + + EditPhotoForm.cs + + + EditTextForm.cs + + + MainForm.cs + + + + TbLoginForm.cs + + + TbLoginListForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + False + Microsoft .NET Framework 4.6.1 %28x86 和 x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + + + \ No newline at end of file diff --git a/应用/TBAppraisalTools/TbAnalysis.cs b/应用/TBAppraisalTools/TbAnalysis.cs new file mode 100644 index 0000000..d379969 --- /dev/null +++ b/应用/TBAppraisalTools/TbAnalysis.cs @@ -0,0 +1,526 @@ +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using TBAppraisalTools.Entitys; + +namespace TBAppraisalTools +{ + /// + /// 淘宝解析类 + /// + public class TbAnalysis + { + /// + /// 获得淘宝的基础信息 + /// + /// 宝贝id + /// 淘宝的cookies + public TbBaseInfo FindTbBaseInfo(string itemId) + { + // 目标: 店铺名称,店铺头像,标题,主图,价格,月销 优惠券金额,有效期 - 自定义 + try + { + var html = ""; + //var item = TbTools.GetH5Result("mtop.taobao.detail.getdetail", new { itemNumId = itemId, exParams = new { id = itemId }, detail_v = "3.1.1", ttid = "2018@taobao_iphone_9.9.9", utdid = "123123123123123" }, out html); + + var item = TbTools.GetH5Result("mtop.taobao.detail.getdetail", new { itemNumId = itemId, exParams = new { id = itemId }, ttid = "2016@taobao_h5_2.0.0", isSec = "0", ecode = "0", AntiFlood = "true", AntiCreep = "true", H5Request = "true", type = "jsonp", dataType = "jsonp" }, out html); + + var _item = item["item"] as Dictionary; + var sellerId = string.Empty; + //这里可以通过图片的地址获取店铺的id + if (_item.ContainsKey("images")) + { + var images = _item["images"] as ArrayList; + if (images != null && images.Count != 0) + { + var reg = Regex.Match(images[0].ToString(), @"http://img.alicdn.com/imgextra/i\d/(?<店铺Id>\d+)/"); + if (reg.Success) + sellerId = reg.Groups["店铺Id"].Value; + } + } + + var price = string.Empty;//价格 + var sellCount = string.Empty; + var apiStack = item["apiStack"] as ArrayList; + if (apiStack != null && apiStack.Count != 0) + { + var _apiStack = apiStack[0] as Dictionary; + if (_apiStack.ContainsKey("value")) + { + var valueJsonStr = _apiStack["value"].ToString(); + var valueJson = HttpExtend.JsonToDictionary(valueJsonStr); + + #region 获取销量 sellCount + var itemTag = valueJson["item"] as Dictionary; + if (itemTag.ContainsKey("sellCount")) + sellCount = itemTag["sellCount"].ToString(); + #endregion + + #region 获取价格 price + var priceTag = valueJson["price"] as Dictionary; + if (priceTag.ContainsKey("price")) + { + var priceSub = priceTag["price"] as Dictionary; + if (priceSub.ContainsKey("priceText")) + price = priceSub["priceText"].ToString(); + } + if (string.IsNullOrEmpty(price) && priceTag.ContainsKey("transmitPrice")) + { + var transmitPrice = priceTag["transmitPrice"] as Dictionary; + if (transmitPrice.ContainsKey("priceText")) + price = transmitPrice["priceText"].ToString(); + } + if (!string.IsNullOrEmpty(price) && price.Contains("-")) //TODO 这里可能还存在带问号的价格,目前不清楚是什么情况,先空着 + price = price.Split('-')[0]; + #endregion + } + } + + var _seller = item["seller"] as Dictionary; + //店铺名称 + var shopName = _seller["shopName"].ToString(); + //店铺图片 + string shopIcon = _seller["shopIcon"].ToString(); + shopIcon = string.IsNullOrEmpty(shopIcon) ? "https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg" : shopIcon.StartsWith("http") ? _seller["shopIcon"].ToString() : "http:" + _seller["shopIcon"].ToString(); + if (string.IsNullOrEmpty(shopIcon) || shopName == "天猫超市") + shopIcon = "https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg"; + var userId = _seller["userId"].ToString(); + //主图图片 + var item_image = string.Empty; + if (_item.ContainsKey("images")) + item_image = (_item["images"] as ArrayList)[0].ToString(); + //商品标题 + var item_title = _item["title"].ToString(); + + return new TbBaseInfo() { ItemId = itemId, ItemImage = item_image, ItemTitle = item_title, Price = price, SellCount = sellCount, ShopIcon = shopIcon, ShopName = shopName, UserId = userId, SellerId = sellerId }; + } + catch (Exception ex) + { + return null; + } + } + + private Random ra = new Random(); + + /// + /// 生成优惠券图片 + /// + /// 宝贝的信息 + /// 返回生成后优惠券的路径,异常直接报错 + public string GenerateCouponImage(TbBaseInfo tb) + { + try + { + if (File.Exists(TbTools.TBCONFIGJSON))//存在优惠券模板的情况 + { + var objDic = JsonConvert.DeserializeObject>(File.ReadAllText(TbTools.TBCONFIGJSON)); + if (objDic != null) + { + var panel = objDic.FirstOrDefault(f => f.Key.Contains("panel")); + if (!default(KeyValuePair).Equals(panel)) + { + TbConfig tbConfig = objDic[panel.Key] as TbConfig; + if (!File.Exists(TbTools.BACKICO)) throw new Exception("不存在优惠券背景图"); + var backImage = Tools.RefreshFileAddress(TbTools.BACKICO, TbTools.BASEPATH + @"\", Util.MapPath(TbTools.BASEPATH)); + using (var backIco = new Bitmap(Image.FromFile(backImage), tbConfig.C_Size)) + { + using (Graphics g = Graphics.FromImage(backIco)) + { + #region 计算优惠券价 discounts + var srcPrice = float.Parse(tb.Price); + var rates = Class1.Config.CouponDenomination.Split('-'); + float min = 0.3f;//默认最小比例 + float max = 0.6f;//默认最大比例 + if (rates.Length == 2) + { + min = float.Parse(rates[0]) / 100f;//最小比例 + max = float.Parse(rates[1]) / 100f;//最大比例 + } + var discounts = (ra.Next(int.Parse(Math.Ceiling(srcPrice * min).ToString()), int.Parse(Math.Ceiling(srcPrice * max).ToString()))); + //默认选中取整 时 - 商品现价要是小于10的时候,将不会取整,其他的取十的倍数 + if (Class1.Config.IsRounding == Api.Framework.Enums.SwitchType.开启) + { + if (discounts > 10 && discounts < srcPrice) + { + double xx = discounts / 10; + discounts = int.Parse((Math.Round(xx) * 10).ToString()); + } + } + + #endregion + foreach (KeyValuePair item in objDic) + { + var temp = item.Value; + if (item.Key.Contains("label")) + { + var validityBegin = string.Empty;//优惠券有效期开始日期 + var validityEnd = string.Empty;//优惠券有效期结局日期 + #region 计算优惠券有效期区间 + if (temp.T_Text.Contains("#开始时间") || temp.T_Text.Contains("#结束时间")) + { + var tempDate = DateTime.Now.AddDays(Class1.Config.ManufacturePlansAddDay); + validityBegin = tempDate.ToString("yyyy.MM.dd"); + validityEnd = tempDate.AddDays(Class1.Config.ExpirationDate).ToString("yyyy.MM.dd"); + } + #endregion + + var txt = temp.T_Text + .Replace("#店铺名称", tb.ShopName) + .Replace("#商品标题", tb.ItemTitle) + .Replace("#商品现价", tb.Price) + .Replace("#月销售量", tb.SellCount) + .Replace("#优惠券价", discounts.ToString()) + .Replace("#券后特价", (float.Parse(tb.Price) - discounts).ToString()) + .Replace("#开始时间", validityBegin) + .Replace("#结束时间", validityEnd); + SizeF crSize = new SizeF(); + crSize = g.MeasureString(txt, temp.T_Font); + txt = Tools.RefreshTextFormat(tbConfig.C_Size.Width, temp.C_Point.X, txt, crSize.Width); + g.DrawString(txt, temp.T_Font, new SolidBrush(temp.T_ForeColor), temp.C_Point); + } + else if (item.Key.Contains("picbox")) + { + var tagDic = CsharpHttpHelper.HttpExtend.JsonToDictionary(temp.C_Tag.ToString()); + var imageInfo = new ImageInfo() { ImagePath = tagDic["ImagePath"].ToString(), Shape = tagDic["Shape"].ToString() == "false" ? false : true, Varible = tagDic["Varible"].ToString() }; + + Bitmap bitmap = null; + + if (imageInfo.Varible == "#店铺头像" || imageInfo.Varible == "#商品主图") + { + var cacheFile = TbTools.RandomFile(); + Tools.DownloadImage(imageInfo.Varible == "#商品主图" ? tb.ItemImage : tb.ShopIcon, cacheFile); + bitmap = new Bitmap(Tools.ReadImageFile(cacheFile), temp.C_Size); + } + else if (imageInfo.Varible == "#其他图片") + { + var otherImage = Tools.RefreshFileAddress(imageInfo.ImagePath, @"评价工具\其他图片\", TbTools.OTHERSICOPATH); + bitmap = Tools.ReadImageFile(otherImage); + } + if (bitmap != null) + { + g.DrawImage(bitmap, temp.C_Point); + bitmap.Dispose(); + bitmap = null; + } + } + } + } + var url = TbTools.RandomFile(); + backIco.Save(url); + return url; + } + } + } + } + else + throw new Exception("未找到优惠券模板配置文件"); + } + catch (Exception ex) + { + throw ex; + } + return string.Empty; + } + + /// + /// 通过宝贝id获取宝贝评价标签集合 + /// + /// 宝贝id + /// 返回标签集合 + public List FindTagsByItemId(string itemId) + { + try + { + var tags = TbTools.FindTagsByItemId(itemId); + if (tags != null) tags = tags.Where(f => f.posi).ToList(); + return tags; + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 获取PC端的评语信息 + /// + /// 宝贝Id + /// 店铺Id + /// 分析多少页 + /// 标签的id + /// + public List FindPcCommentInfos(string itemId, string sellerId, int analyticPageNum, int tagid = 0) + { + try + { + try + { + var comments = new List(); + for (int i = 1; i <= analyticPageNum; i++) + { + //int error = 0; + // Next: + string url = string.Format("https://rate.tmall.com/list_detail_rate.htm?itemId={0}&sellerId={1}&order=3¤tPage={2}&append=0&content=1&posi=1&picture=&callback=jsonp443&tagId={3}", itemId, sellerId, analyticPageNum, tagid); + + //var cookies = Tools.ReadTBCookies(); + HttpHelper http = new HttpHelper(); + var item = http.GetItem(url); + item.Cookie = TbTools.RandomTbCookies(); + item.Allowautoredirect = true; + item.UserAgent = @"Mozilla/4.0 (compatible; MSIE 9.0; Windows NT6.1)"; + item.ContentType = @"application/x-www-form-urlencoded"; + var result = http.GetHtml(item); + var html = result.Html.Trim(); + //TbCookies = result.Cookie;//这个就不保存了,因为写了淘宝心跳 + if (!html.StartsWith("jsonp443")) throw new Exception("评语解析不出:" + html); + + html = html.Replace("jsonp443(", "").Replace(")", ""); + var json = HttpExtend.JsonToDictionary(html) as Dictionary; + if (json != null && json.ContainsKey("rgv587_flag"))//登录过期 + throw new Exception("淘宝已经掉线,请重新登录~!");//这里可能会是频率显示(歇息一下,喝口水什么的) + if (json == null || !json.ContainsKey("rateDetail")) throw new Exception("未获得评价数据:" + html); + json = json["rateDetail"] as Dictionary; + + if (!json.ContainsKey("rateList")) throw new Exception("该宝贝没有评论数据"); + var list = json["rateList"] as ArrayList; + + foreach (Dictionary obj in list) + { + var pics = obj["pics"] as ArrayList; + var comment = new Comment() { position = obj["position"].ToString(), rateContent = obj["rateContent"].ToString() }; + if (pics != null) + { + foreach (var t in pics) + { + comment.pics.Add("http:" + t); + } + } + comments.Add(comment); + } + if (json.ContainsKey("paginator"))//获取评论区的页数 + { + var paginator = json["paginator"] as Dictionary; + var lastPage = int.Parse(paginator["lastPage"].ToString());//总页数 + var page = int.Parse(paginator["page"].ToString());//当前页数 + if (lastPage <= page) break; + } + } + return comments; + } + catch (Exception ex) + { + throw ex; + } + //return new List(); + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 获取移动端的评语信息 + /// + /// 宝贝Id + /// 店铺Id + /// 分析多少页 + /// 标签Id + /// + public List FindWebappCommentInfos(string itemId, int analyticPageNum) + { + try + { + List commentList = new List(); + TaskTool tasks = new TaskTool(); + for (int i = 1; i <= analyticPageNum; i++) + { + + var _i = i; + tasks.AddTask(delegate + { + try + { + //获取评价json数据 + var json = string.Empty; + var _url = @"https://rate.taobao.com/feedRateList.htm?auctionNumId=" + itemId + "&userNumId=" + new Random(Guid.NewGuid().GetHashCode()).Next(100000, 999999).ToString() + new Random(Guid.NewGuid().GetHashCode()).Next(10000, 99999) + "¤tPageNum=" + _i + "&pageSize=20&rateType=&orderType=sort_weight&attribute=&sku=&hasSku=false&folded=0&callback=jsonp_tbcrate_reviews_list"; + HttpHelper http = new HttpHelper(); + var temp = http.GetItem(_url); + temp.Cookie = TbTools.RandomTbCookies(); + temp.SetProxyipCDN(); + temp.Allowautoredirect = true; + temp.UserAgent = @"Mozilla/4.0 (compatible; MSIE 9.0; Windows NT6.1)"; + temp.ContentType = @"application/x-www-form-urlencoded"; + var rst = http.GetHtml(temp); + //if (!string.IsNullOrEmpty(rst.Cookie)) rst.UpdateCookies(temp.Cookie);//更新cookies + json = rst.Html.Replace("jsonp_tbcrate_reviews_list(", "").Trim(); + json = json.Substring(0, json.Length - 1); + //StringBuilder strb = new StringBuilder(); + //StringBuilder strbPic = new StringBuilder(); + + var obj = HttpExtend.JsonToDictionary(json); + + #region 最大页数 + var maxPageObj = obj["maxPage"]; + var maxPage = -1; + if (maxPageObj != null) + maxPage = int.Parse(maxPageObj.ToString()); + #endregion + + #region 获取评语和图片数据 + var comments = obj["comments"] as ArrayList; + if (comments != null && comments.Count != 0) + { + foreach (var _item in comments) + { + var pj = new Comment(); + var item = _item as Dictionary; + var photos = item["photos"] as ArrayList; + if (photos != null && photos.Count != 0) + { + foreach (var _pic in photos) + { + var pic = _pic as Dictionary; + var url = pic["url"].ToString();//图片 + pj.pics.Add("http:" + url); + } + } + var content = item["content"].ToString();//初评语 + if (content != "此用户没有填写评价。") + pj.rateContent = content; + var appendList = item["appendList"] as ArrayList;//追评数量 + if (appendList != null && appendList.Count != 0) + { + foreach (var _appendItem in appendList)//追评部分 + { + var appendItem = _appendItem as Dictionary; + var appendPhotos = appendItem["photos"] as ArrayList; + if (appendPhotos != null && appendPhotos.Count != 0) + { + foreach (var _appendPic in appendPhotos) + { + var appendPic = _appendPic as Dictionary; + var appendUrl = appendPic["url"].ToString();//追加图片 + pj.pics.Add("http:" + appendUrl); + } + } + var appendContent = appendItem["content"].ToString();//追评语 + if (content != "此用户没有填写评价。") + pj.rateContent += appendContent; + } + } + if (!string.IsNullOrEmpty(pj.rateContent)) commentList.Add(pj); + } + } + #endregion + } + catch { } + }); + } + tasks.Start(10, null); + return commentList; + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 将图片集合转换成Gif图片 + /// + /// 图片集合 + /// 最后一针图片(底图) + /// + /// 图片之间的间隔时间 + /// 是否重复 + public void FindGifsBySrcPic(List pics, string secondImage, string path, string itemId, int time = 0, bool repeat = false) + { + try + { + if (pics != null && pics.Count != 0) //判断是否图片集合为空 + { + //if (Directory.Exists(path)) //检测是否存在日期部分的目录 + //{ + // if (Directory.Exists($"{path}\\{itemId}")) //检测当天解析的宝贝一样时,删除之前解析的所有内容 + // Tools.DelectDir(path); + //} + //else + // throw new Exception("解析以后保存路径不存在,请先设置保存路径"); + + TaskTool tasks = new TaskTool(); //定义线程池 + + foreach (var pic in pics) //循环要遍历的图片 + { + tasks.AddTask(delegate () //添加线程任务 + { + try + { + var secondImg = Tools.ReadImageFile(secondImage); //获取优惠券bitmap + var bitmap = Tools.ZoomPicture(Image.FromFile(pic), secondImg.Width, secondImg.Height);//评价图压缩成和优惠券图大小一致 + Graphics g = null; + if (File.Exists(TbTools.BUTTONICO)) //是否有按钮图标 + { + g = Graphics.FromImage(bitmap); //创建以底图为基础的画板 + var bitmapLogo = Tools.ReadImageFile(TbTools.BUTTONICO); //按钮图片bitmap + int size = 200; //按钮大小 + float rate = 2.00f; //比例 + bitmapLogo = new Bitmap(bitmapLogo, new Size(size, size)); //固定按钮的大小 + var point = new PointF(secondImg.Width / rate - size / rate, secondImg.Height / rate - size / rate); //按钮的坐标 + g.DrawImage(bitmapLogo, point); //将按钮画在底图中 + } + //000000000000 + var saveImgPath = TbTools.RandomFile(); //带随机名字的缓存地址(临时图片) + bitmap.Save(saveImgPath); //将评价图保存只缓存 + if (g != null) //如果增加了按钮,则将画板释放 + g.Dispose(); + bitmap.Dispose(); //释放 + + if (Class1.Config.BondCommentPic == Api.Framework.Enums.SwitchType.开启) + { + var gifFile = Tools.PngsToGif(new string[] { saveImgPath, secondImage }, Util.MapFile(Guid.NewGuid().ToString() + ".png", path), time, repeat); //将处理好的图片保存在宝贝路径中 + if (!string.IsNullOrEmpty(gifFile)) + { + if (File.Exists(saveImgPath)) + try + { + File.Delete(saveImgPath); //删除临时图片 + } + catch (Exception ex) + { } + } + } + else + { + + } + } + catch (Exception ex) + { + + } + }); + } + tasks.Start(8, null); //执行线程池 + } + } + catch (Exception ex) + { + throw ex; + } + } + + + + } +} diff --git a/应用/TBAppraisalTools/TbConfig.cs b/应用/TBAppraisalTools/TbConfig.cs new file mode 100644 index 0000000..747d3ad --- /dev/null +++ b/应用/TBAppraisalTools/TbConfig.cs @@ -0,0 +1,143 @@ +using Api.Framework.Enums; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBAppraisalTools +{ + /// + /// TbConfig类中"C_"开头为公共的属性,"T_"开头为文本数据(Label) + /// + public class TbConfig + { + /// + /// 控件名字 + /// + public string C_Name { get; set; } + /// + /// 控件坐标 + /// + public Point C_Point { get; set; } + /// + /// 控件大小 + /// + public Size C_Size { get; set; } + /// + /// Tag内容 + /// + public Object C_Tag { get; set; } + + //public ImageInfo I_ImageInfo { get; set; } + /// + /// 文本内容 + /// + public string T_Text { get; set; } + /// + /// 文本的字体 + /// + public Font T_Font { get; set; } + /// + /// 字体的颜色 + /// + public Color T_ForeColor { get; set; } + + public TbConfig() + { + C_Point = new Point() { X = 30, Y = 30}; + } + + } + + /// + /// 图片控件的图片信息 + /// + public class ImageInfo + { + /// + /// 图片在本地的路径 + /// + public string ImagePath { get; set; } + /// + /// 图片的形状,true为矩形.false为雏形 + /// + public bool Shape { get; set; } + /// + /// 变量 + /// + public string Varible { get; set; } + } + + /// + /// 淘宝登录类 + /// + public class TbLoginInfo + { + /// + /// 登录的账号 + /// + public string TbLoginName { get; set; } + /// + /// 登录的Cookies + /// + public string Cookies { get; set; } + /// + /// Cookies的状态是否还有效 + /// + public SwitchType OnLine { get; set; } + } + + public class TagCloud + { + public int count { get; set; } + public string id { get; set; } + public bool posi { get; set; } + public string tag { get; set; } + public int weight { get; set; } + + public List pjIndex { get; set; } + + public TagCloud() + { + pjIndex = new List(); + } + } + + /// + /// 用户评价信息 + /// + public class Comment + { + /// + /// 关键词坐标 + /// + public string position { get; set; } + /// + /// 内容 + /// + public string rateContent { get; set; } + /// + /// 图片 + /// + public List pics { get; set; } + public Comment() { this.pics = new List(); } + } + + /// + /// 解析出来的所有评价信息 + /// + public class CommentInfo + { + /// + /// 评价集合 + /// + public List Comments { get; set; } + public CommentInfo() + { + Comments = new List(); + } + } +} diff --git a/应用/TBAppraisalTools/TbTools.cs b/应用/TBAppraisalTools/TbTools.cs new file mode 100644 index 0000000..3f27f8f --- /dev/null +++ b/应用/TBAppraisalTools/TbTools.cs @@ -0,0 +1,414 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using TBAppraisalTools.Properties; + +namespace TBAppraisalTools +{ + public class TbTools + { + /// + /// 基础路径 + /// + public static string BASEPATH = @"File\评价工具缓存"; + /// + /// 优惠模板的配置 + /// + public static string TBCONFIGJSON = Util.MapFile("TBAppraisalTools.ConfigJson.txt", BASEPATH); + /// + /// 商品主图保存地址 + /// + public static string ITEMICO = Util.MapFile("商品主图.png", BASEPATH); + /// + /// 店铺头像保存地址 + /// + public static string SHOPICO = Util.MapFile("店铺头像.png", BASEPATH); + /// + /// 优惠券背景保存地址 + /// + public static string BACKICO = Util.MapFile("优惠券背景.png", BASEPATH); + /// + /// 用户自定义诱导图保存地址 + /// + public static string ABDUCTIONICO = Util.MapFile("诱导图.png", BASEPATH); + /// + /// 用户自定义按钮图片保存地址 + /// + public static string BUTTONICO = Util.MapFile("按钮.png", BASEPATH); + /// + /// 其他图片保存路径 + /// + public static string OTHERSICOPATH = Util.MapPath(BASEPATH + @"\其他图片"); + + public static string CACHEPATH = Util.MapPath(@"Cache\image"); + + public static string RandomFile() + { + return Util.MapFile(Guid.NewGuid().ToString() + ".png", @"Cache\image"); + } + + /// + /// 随机返回一个Cookies + /// + /// + public static string RandomTbCookies() + { + return "x5sec=7b22726174656d616e616765723b32223a223532646630323530396539363062626235633533306632383630376138666231435053657165414645496e6e3265324c6d71336275674561444445314f54557a4e5467784d7a51374d513d3d227d; cookie2=1deb2e55c9854743bc58dab7e9713758; _tb_token_=f1e53753884e3; t=0240c13f37355b4b835b319127b5af8c"; + //if (Class1.Config.TbLoginInfos != null) + //{ + // var tbLoginInfo = Class1.Config.TbLoginInfos.Where(f => f.OnLine == SwitchType.开启).OrderBy(f => Guid.NewGuid()).Take(1).FirstOrDefault(); + // if (tbLoginInfo != null) return tbLoginInfo.Cookies; + //} + //return string.Empty; + } + + #region h5Top + + private static string _cookies = string.Empty; + + private static string Cookies + { + get + { + if (string.IsNullOrEmpty(_cookies)) + { + HttpHelper http = new HttpHelper(); + string cookies = http.GetHtml(new HttpItem() { URL = "http://api.m.taobao.com/h5/mtop.alimama.union.hsf.coupon.get/1.0/?v=1.0&api=mtop.alimama.union.hsf.coupon.get&appKey=12574478&t=1521082116428&callback=mtopjsonp1&type=jsonp&sign=e102e09c3da2505790412f4b5904cfec&data=%7B%22e%22%3A%22kKwRS8jKFeIGQASttHIRqX4ccS%252BmEB0fPkvI%252B9vDGidk3qypIGt1zv02HjWWzK8QrVVJXxMdEXoJP%252FpVy45HN79fwBwwUiqlbZt%252F%252F9VQxkYKu2xm%252BXzUVW7PVn13QcLNcISolD8QJ4rvZt%252BicRrQwg%253D%253D%22%2C%22pid%22%3A%22mm_96747532_17602904_63786428%22%7D", Timeout = 5000, ReadWriteTimeout = 5000 }).Cookie; + _cookies = HttpHelper.GetSmallCookie(cookies); + } + return _cookies; + } + set { _cookies = value; } + } + + const string appKey = "12574478"; + + public static Dictionary GetH5Result(string api, object data, out string html, string version = "6.0") + { + bool next = false; + Next: + string time = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString(); + string mh5Tk = HttpExtend.GetCookiesValue("_m_h5_tk", Cookies); + mh5Tk = string.IsNullOrEmpty(mh5Tk) ? "f64aa152f943661f750e6212ebc98804_1481170439770" : mh5Tk; + string json = (data.GetType() == typeof(string)) ? data.ToString() : HttpHelper.ObjectToJson(data).Replace("\\u0026", "&").Replace("_params", "param"); + string temp_ = mh5Tk + "&" + time + "&" + appKey + "&" + json; + string sign = HttpExtend.GetMD5String(temp_); + string send = HttpExtend.UrlEncode(json); + string temp = string.Format("http://h5api.m.taobao.com/h5/{5}/{4}/?jsv=2.4.11&v={4}&api={5}&appKey={0}&t={1}&callback=mtopjsonp1&type=jsonp&sign={2}&data={3}", appKey, time, sign, send, version, api); + html = M_GET_HTML(temp).Trim(); + if (html.Contains("令牌过期") || html.Contains("令牌为空") || html.Contains("失效")) + { + if (!next) + { + next = true; + goto Next; + } + } + if (html.Contains("挤爆")) + { + Dictionary _json = HttpExtend.JsonToDictionary(html); + + string _url = (_json["data"] as Dictionary)["url"].ToString(); + next = false; + goto Next; + } + + var reg = Regex.Match(html, @"^mtopjsonp1\((.*?)\)$", RegexOptions.IgnoreCase); + if (reg.Success) + { + var dic = HttpExtend.JsonToDictionary(reg.Groups[1].Value); + if (dic.ContainsKey("data") && html.Contains("SUCCESS::调用成功")) + return dic["data"] as Dictionary; + throw new Exception(reg.Groups[1].Value); + } + throw new Exception(html); + } + + internal const string _key = "wmUZgme6iOPOaMTZtPu5DKQ8Dph9fSgy6abFyQv25MD8xOMPBBo0wsLUOVt8r9sk+li11mIg1fs1HPJ75UmIle+w9xhIx/nsXWejuQhXlQV0VyJtzI+id8G+FcyYaog91MfPndJoO3m30fSjE/0KDLDmv1EeQcP24RAzeA29p7c=AQAB"; + internal const int _appid = 10004; + internal const string _host = "https://cps.api.52cmg.cn"; + + private static string M_GET_HTML(string tempUrl) + { + try + { + HttpItem item = new HttpItem() + { + URL = tempUrl,//URL 必需项 + Method = "get",//URL 可选项 默认为Get + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = Cookies + ";random=" + new Random().Next(),//字符串Cookie 可选项 + Referer = "http://m.taobao.com",//来源URL 可选项 + Timeout = 5000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 5000,//写入Post数据超时时间 可选项默认为30000 + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "text/html",//返回类型 可选项有默认值 + Allowautoredirect = false,//是否根据301跳转 可选项 + }; + HttpHelper http = new HttpHelper(); + int i = 0; + Next: + HttpResult result = http.GetHtml(item); + string html = result.Html; + if (Regex.IsMatch(html, Resources.KeyWords)) + { + var r = item.SetProxyIP(http, new AuthEndpoint() + { + Host = _host + "/api/webtool.asmx/send_data", + Appid = _appid, + Enckey = _key, + Method = "find_proxy" + }); + i++; + if (r && i < 3) goto Next; + } + if (!string.IsNullOrEmpty(result.Cookie)) + { + Cookies = HttpExtend.UpdateCookies(Cookies, result.Cookie); + } + return html; + } + catch (Exception) + { + return string.Empty; + } + } + #endregion + + #region GetXsign算法 + public string GetXsign(string api, object data, string v = "4.0") + { + try + { + var _data = HttpHelper.ObjectToJson(data); + //string goodid = "576534346099"; + //var _data = HttpHelper.ObjectToJson(new + //{ + // hasPic = "1", + // pageNo = "1", + // rateType = "2", + // auctionNumId = goodid, + // pageSize = "10" + //});// UrlEncode().Replace("\\u0026", "&"); + var byte_data = Encoding.UTF8.GetBytes(_data); + //var str = $"&xsid=&ttid=255200%40taobao_android_6.9.0&deviceId=AtDfW5xiq9pfKSGj8ZGohk11_7ho-iA4o_qrEZaVyYU1&lat=&lng=&features="; + string str_md52 = HttpExtend.GetMD5String(_data).ToLower(); + Dictionary obj = new Dictionary(); + obj["api"] = api; + obj["date"] = str_md52; + obj["v"] = v; + obj["x-lat"] = "39.916295"; + obj["x-lng"] = "116.410344"; + obj["x-utdid"] = "W8YPqceRx24DAFCBVtSNaUg8"; + obj["appkey"] = "21646297"; + obj["x-ttid"] = "600000@taobao_android_7.6.0"; + obj["x-devid"] = "AtDfW5xiq9pfKSGj8ZGohk11_7ho-iA4o_qrEZaVyYU1"; + obj["x-features"] = "27"; + obj["x-t"] = HttpExtend.GetTimeStamp(); + var _app = SendData("com.taobao.find.xsign", obj); + if (_app != null && _app.ok) + { + obj["x-sign"] = (_app.message as Dictionary)["result"].ToString(); + HttpHelper http = new HttpHelper(); + var result = _app.message as Dictionary; + var item = new HttpItem(); + var header = @"x-appkey:[appkey] +x-features:[x-features] +x-t:[x-t] +x-pv:5.1 +x-location:116.410344%2C39.916295 +x-ttid:[x-ttid] +x-utdid:[x-utdid] +x-devid:[x-devid] +x-sign:[x-sign] +x-page-url:http%3A%2F%2Fitem.taobao.com%2Fitem.htm +x-unitinfo:center"; + foreach (var _temp in obj) + { + header = header.Replace("[" + _temp.Key + "]", _temp.Value.ToString()); + } + var headers = header.Split(new string[] { "\r\n" }, StringSplitOptions.None); + foreach (var val in headers) + { + var s = val.Split(':'); + item.Header[s[0]] = s[1].Trim(); + } + _data = UrlEncode(_data); + item.URL = "https://acs.m.taobao.com/gw/" + api + "/" + v + "/?data=" + _data.Replace("\\u0026", "&"); + item.Timeout = 5000; + var temp = http.GetHtml(item); + return temp.Html; + } + + } + catch + { } + return null; + } + private string UrlEncode(string str) + { + StringBuilder builder = new StringBuilder(); + foreach (char c in str) + { + if (HttpUtility.UrlEncode(c.ToString()).Length > 1) + { + builder.Append(HttpUtility.UrlEncode(c.ToString()).ToUpper()); + } + else + { + builder.Append(c); + } + } + return builder.ToString(); + } + /// + /// 发送API数据 + /// + /// API接口 + /// 参数 + /// + private WebResult SendData(string method, object param = null) + { + int num = 0; + Next: + try + { + AuthEndpoint end = new AuthEndpoint() + { + Appid = _appid, + Enckey = _key, + Host = _host + "/api/alimama.asmx/send_data", + Method = method + }; + if (param != null) + { + if (param.GetType() == typeof(Dictionary)) + { + + foreach (var item in param as Dictionary) + { + end.Param[item.Key] = item.Value; + } + } + else + { + var _param = param.GetType().GetProperties(); + foreach (var item in _param) + { + end.Param[item.Name] = item.GetValue(param); + } + } + + } + HttpHelper http = new HttpHelper(); return http.SendData(end, true); + } + catch (Exception ex) + { + if (ex.Message == "未将对象引用设置到对象的实例。" && num < 2) + { + num++; + goto Next; + } + return new CsharpHttpHelper.WebResult() { ok = false, message = ex.Message }; + } + } + #endregion + + /// + /// 将c# DateTime时间格式转换为Unix时间戳格式 + /// + /// 时间 + /// long + private static long ConvertDateTimeToInt(System.DateTime time) + { + System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0)); + long t = (time.Ticks - startTime.Ticks) / 10000; //除10000调整为13位 + return t; + + } + + #region 获取评价标签Tag + /// + /// 通过宝贝id获取宝贝评价标签集合 + /// + /// 宝贝id + /// 返回标签集合 + public static List FindTagsByItemId(string itemId) + { + int count = 0; + Go: + try + { + //var item = GetItem("https://rate.tmall.com/listTagClouds.htm?itemId=" + itemId + "&isAll=true&isInner=true&t=" + ConvertDateTimeToInt(DateTime.Now) + "&_ksTS=" + ConvertDateTimeToInt(DateTime.Now) + "_1892&callback=jsonp1893", Encoding.UTF8); + //GetHtml(item); + + HttpHelper http = new HttpHelper(); + var item = http.GetItem("https://rate.tmall.com/listTagClouds.htm?itemId=" + itemId + "&isAll=true&isInner=true&t=" + ConvertDateTimeToInt(DateTime.Now) + "&_ksTS=" + ConvertDateTimeToInt(DateTime.Now) + "_1892&callback=jsonp1893", RandomTbCookies()); + item.Allowautoredirect = true; + item.Encoding = Encoding.UTF8; + var rest = http.GetHtml(item); + string html = rest.Html.Replace("jsonp1893(", "").Replace(")", "").Trim(); + //{"tags":{"rateSum":0,"structuredRateStatisticList":[],"tagClouds":[],"dimenSum":0,"innerTagCloudList":[],"userTagCloudList":[]}} + var dic = HttpExtend.JsonToDictionary(html) as Dictionary; + if (dic == null) throw new Exception("获取Tag失败。"); + if (!dic.ContainsKey("tags")) throw new Exception("不包含tags:" + html); + var tags = dic["tags"] as Dictionary; + if (!tags.ContainsKey("tagClouds")) throw new Exception("不包含tagClouds:" + html); + + var clouds = HttpHelper.JsonToObject(HttpHelper.ObjectToJson(tags["tagClouds"])) as TagCloud[]; + return clouds.ToList(); + } + catch (Exception ex) + { + if (count <= 3) + { + count++; + Thread.Sleep(150); + goto Go; + } + throw ex; + } + } + #endregion + + /// + /// 获取要保存的评价内容 + /// + /// + /// + public static string GetCommentContents(List commentContents) + { + try + { + StringBuilder strb = new StringBuilder(); + //这里是随机取10条数据 + for (int i = 0; i < 16; i++) + { + if (commentContents.Count > i && commentContents[i] != null && !string.IsNullOrEmpty(commentContents[i])) + { + var positions = commentContents[i].Trim().Split(new string[] { ",", ",", "。", "?", "?", "!", "!", "~", " " }, StringSplitOptions.RemoveEmptyEntries); + if (positions.Length != 0) + strb.Append(positions[new Random().Next(0, positions.Length)] + (new Random().Next(0, 2) == 1 ? "。" : ",")); + } + } + return strb.ToString(); + } + catch (Exception ex) + { + return string.Empty; + } + } + + } +} diff --git a/应用/TBAppraisalTools/Tools.cs b/应用/TBAppraisalTools/Tools.cs new file mode 100644 index 0000000..5ac33a8 --- /dev/null +++ b/应用/TBAppraisalTools/Tools.cs @@ -0,0 +1,247 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace TBAppraisalTools +{ + class Tools + { + + /// + /// 把directory文件夹里的png文件生成为gif文件,放在giffile + /// + /// 图片的数组 + /// gif保存路径 + /// 每帧的时间/ms + /// 是否重复 + public static string PngsToGif(string[] files, string giffile, int time = 0, bool repeat = false) + { + try + { + //一般文件名按顺序排 + AnimatedGifEncoder e = new AnimatedGifEncoder(); + e.Start(giffile); + //每帧播放时间 + e.SetDelay(time); + //1:不重复,0:重复 + e.SetRepeat(repeat ? 0 : -1); + for (int i = 0, count = files.Length; i < count; i++) + { + if (!string.IsNullOrEmpty(files[i]) && File.Exists(files[i])) + e.AddFrame(Tools.ReadImageFile(files[i])); + } + e.Finish(); + return giffile; + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 按比例缩放图片 + /// + /// 图片路径 + /// 宽度 + /// 高度 + /// + public static Image ZoomPicture(Image SourceImage, int TargetWidth, int TargetHeight) + { + int IntWidth; //新的图片宽 + int IntHeight; //新的图片高 + try + { + System.Drawing.Imaging.ImageFormat format = SourceImage.RawFormat; + Bitmap SaveImage = new Bitmap(TargetWidth, TargetHeight); + Graphics g = Graphics.FromImage(SaveImage); + g.Clear(Color.White); + if (SourceImage.Width > TargetWidth && SourceImage.Height <= TargetHeight)//宽度比目的图片宽度大,长度比目的图片长度小 + { + IntWidth = TargetWidth; + IntHeight = (IntWidth * SourceImage.Height) / SourceImage.Width; + } + else if (SourceImage.Width <= TargetWidth && SourceImage.Height > TargetHeight)//宽度比目的图片宽度小,长度比目的图片长度大 + { + IntHeight = TargetHeight; + IntWidth = (IntHeight * SourceImage.Width) / SourceImage.Height; + } + else if (SourceImage.Width <= TargetWidth && SourceImage.Height <= TargetHeight) //长宽比目的图片长宽都小 + { + IntHeight = SourceImage.Width; + IntWidth = SourceImage.Height; + } + else//长宽比目的图片的长宽都大 + { + IntWidth = TargetWidth; + IntHeight = (IntWidth * SourceImage.Height) / SourceImage.Width; + if (IntHeight > TargetHeight)//重新计算 + { + IntHeight = TargetHeight; + IntWidth = (IntHeight * SourceImage.Width) / SourceImage.Height; + } + } + g.DrawImage(SourceImage, (TargetWidth - IntWidth) / 2, (TargetHeight - IntHeight) / 2, IntWidth, IntHeight); + SourceImage.Dispose(); + return SaveImage; + } + catch (Exception ex) + { + } + return null; + } + + /// + /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// + /// + /// + public static Bitmap ReadImageFile(string path) + { + FileStream fs = File.OpenRead(path); //OpenRead + int filelength = 0; + filelength = (int)fs.Length; //获得文件长度 + Byte[] image = new Byte[filelength]; //建立一个字节数组 + fs.Read(image, 0, filelength); //按字节流读取 + Image result = Image.FromStream(fs); + fs.Close(); + Bitmap bit = new Bitmap(result); + return bit; + } + + /// + /// 下载网络图片 + /// + /// 图片的链接 + /// 下载图片保存的路径 + /// + public static void DownloadImage(string url, string path) + { + HttpWebResponse rsp = null; + try + { + url = (url.StartsWith("http") ? url : ("http:" + url)); + HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url); + req.ServicePoint.Expect100Continue = false; + req.Method = "GET"; + req.KeepAlive = true; + req.ContentType = "image/*"; + rsp = (HttpWebResponse)req.GetResponse(); + } + catch (Exception ex) + { + throw ex; + } + Stream stream = null; + try + { + // 以字符流的方式读取HTTP响应 + stream = rsp.GetResponseStream(); + Image.FromStream(stream).Save(path); + } + catch + { + if (stream != null) stream.Close(); + if (rsp != null) rsp.Close(); + } + finally + { + // 释放资源 + if (stream != null) stream.Close(); + if (rsp != null) rsp.Close(); + } + } + + /// + /// 图片放大缩小 变形操作 + /// + /// + /// + /// + /// + public static Bitmap CutEllipse(Image img, Rectangle rec, Size size) + { + Bitmap bitmap = new Bitmap(size.Width, size.Height); + using (Graphics g = Graphics.FromImage(bitmap)) + { + using (TextureBrush br = new TextureBrush(img, System.Drawing.Drawing2D.WrapMode.Clamp, rec)) + { + br.ScaleTransform(bitmap.Width / (float)rec.Width, bitmap.Height / (float)rec.Height); + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + g.FillEllipse(br, new Rectangle(Point.Empty, size)); + //g.FillRectangle(br, new Rectangle(Point.Empty, size)); + } + } + return bitmap; + } + + /// + /// 这方法将以前的地址更新成新的目录地址(防止用户更改了软件目录) + /// + /// 之前完整的路径 + /// 查找的节点(文件名前的那一段内容) + /// 软件的目录 + /// + public static string RefreshFileAddress(string currentFile, string node, string newPath) + { + var index = currentFile.IndexOf(node); + var imageNick = currentFile.Remove(0, index + node.Length);//获取图片名和后缀 + return Util.MapFile(imageNick, newPath);//当前项目的完成图片路径(以上操作是为了怕用户转移程序路径) + } + + /// + /// 更新文本格式,优惠券模板中label超出背景部分自动换行(比如标题过长) + /// + /// 总背景的宽 + /// 文本的X坐标(起点) + /// 文本内容 + /// 格式化后的文本真正的宽 + /// + public static string RefreshTextFormat(int totalWidth, int startPoint, string srcText, float tWidth) + { + var surLocation = totalWidth - startPoint; + if (surLocation < tWidth) + { + var nuit = Math.Ceiling(tWidth / srcText.Length);//一个字的宽度 + var rowNum = (int)Math.Ceiling(surLocation / nuit);//大约一列最多能放几个字 + double rows = srcText.Length / rowNum;//行数 + int count = (int)Math.Ceiling(rows); + + for (var i = 1; i <= count; i++) + { + srcText = srcText.Insert(rowNum * i, "\r\n"); + } + } + return srcText; + } + + /// + /// 通过路径删除所有的文件,以及文件夹 + /// + /// + public static void DelectDir(string srcPath) + { + DirectoryInfo dir = new DirectoryInfo(srcPath); + FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //返回目录中所有文件和子目录 + foreach (FileSystemInfo i in fileinfo) + { + if (i is DirectoryInfo) //判断是否文件夹 + { + DirectoryInfo subdir = new DirectoryInfo(i.FullName); + subdir.Delete(true); //删除子目录和文件 + } + else + { + File.Delete(i.FullName); //删除指定文件 + } + } + } + + } +} diff --git a/应用/TBAppraisalTools/重绘/MyPanel.cs b/应用/TBAppraisalTools/重绘/MyPanel.cs new file mode 100644 index 0000000..85f9988 --- /dev/null +++ b/应用/TBAppraisalTools/重绘/MyPanel.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace TBAppraisalTools.重绘 +{ + class MyPanel : Panel + { + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED + return cp; + } + } + } +} diff --git a/应用/TBAppraisalTools/重绘/MyPictureBox.cs b/应用/TBAppraisalTools/重绘/MyPictureBox.cs new file mode 100644 index 0000000..bb605f8 --- /dev/null +++ b/应用/TBAppraisalTools/重绘/MyPictureBox.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace TBAppraisalTools.重绘 +{ + class MyPictureBox : PictureBox + { + protected override void WndProc(ref Message m) + { + if (m.Msg == 0x0014) // 禁掉清除背景消息 + return; + base.WndProc(ref m); + } + protected override CreateParams CreateParams + { + get + { + var parms = base.CreateParams; + parms.Style &= ~0x02000000; // Turn off WS_CLIPCHILDREN + return parms; + } + } + } +} diff --git a/应用/TBGroupAD/Class1.cs b/应用/TBGroupAD/Class1.cs new file mode 100644 index 0000000..f325c5d --- /dev/null +++ b/应用/TBGroupAD/Class1.cs @@ -0,0 +1,14 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBGroupAD +{ + public class Class1 : Plugin + { + + } +} diff --git a/应用/TBGroupAD/Properties/AssemblyInfo.cs b/应用/TBGroupAD/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..44986a5 --- /dev/null +++ b/应用/TBGroupAD/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("TBGroupAD")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TBGroupAD")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("886e8b33-e49f-4f3b-8d94-de1428fe0d04")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/TBGroupAD/Properties/Resources.Designer.cs b/应用/TBGroupAD/Properties/Resources.Designer.cs new file mode 100644 index 0000000..3b223aa --- /dev/null +++ b/应用/TBGroupAD/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TBGroupAD.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TBGroupAD.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 淘宝发单 的本地化字符串。 + /// + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 淘宝发单 的本地化字符串。 + /// + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 淘宝发单插件,产品群推送 的本地化字符串。 + /// + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 淘宝发单 { + get { + object obj = ResourceManager.GetObject("淘宝发单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/TBGroupAD/Properties/Resources.resx b/应用/TBGroupAD/Properties/Resources.resx new file mode 100644 index 0000000..a9d85ff --- /dev/null +++ b/应用/TBGroupAD/Properties/Resources.resx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 淘宝发单 + 设置主窗体标题 + + + 淘宝发单 + 插件名 + + + 淘宝发单插件,产品群推送 + 插件介绍 + + + + ..\Resources\淘宝发单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/应用/TBGroupAD/Resources/淘宝发单.png b/应用/TBGroupAD/Resources/淘宝发单.png new file mode 100644 index 0000000..3f47194 Binary files /dev/null and b/应用/TBGroupAD/Resources/淘宝发单.png differ diff --git a/应用/TBGroupAD/TBGroupAD.csproj b/应用/TBGroupAD/TBGroupAD.csproj new file mode 100644 index 0000000..fd7160c --- /dev/null +++ b/应用/TBGroupAD/TBGroupAD.csproj @@ -0,0 +1,89 @@ + + + + + Debug + AnyCPU + {886E8B33-E49F-4F3B-8D94-DE1428FE0D04} + Library + Properties + TBGroupAD + TBGroupAD + v4.6.1 + 512 + true + + + true + full + false + ..\..\主应用程序\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\..\主应用程序\Assembly\apifile\Api.Framework.dll + False + + + False + ..\..\主应用程序\Assembly\apifile\Chat.Framework.dll + False + + + False + ..\..\主应用程序\Assembly\apifile\Easy4net.dll + False + + + False + ..\..\主应用程序\Assembly\apifile\HttpHelper.dll + False + + + + + + + + + + + + False + ..\..\主应用程序\Assembly\apifile\UI.Framework.dll + False + + + + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + \ No newline at end of file diff --git a/应用/TBRebate/Class1 - 复制.cs b/应用/TBRebate/Class1 - 复制.cs new file mode 100644 index 0000000..0c6e5ed --- /dev/null +++ b/应用/TBRebate/Class1 - 复制.cs @@ -0,0 +1,2297 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using TBRebate.Entitys; +using TBRebate.Properties; +using static Api.Framework.Cps.AlimamaApi; +using static Api.Framework.Tools.TBHelper; +using static TBRebate.Enums; +using System.Text; + +namespace TBRebate +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.淘宝; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (session.TableExist()) + { + var tbtgws = session.Find("select * from fl_plugin_tbrebate_tbtgw").ToList(); + if (tbtgws != null) + { + foreach (var item in tbtgws) + { + //插入主推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_chief_name, //推广位名称 + adzone_pid = item.pid_chief, //推广位pid + adzone_pid_cps_name = item.pid_chief_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "chief" + }).ExecuteCommand(); + //插入副推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_deputy_name, //推广位名称 + adzone_pid = item.pid_deputy, //推广位pid + adzone_pid_cps_name = item.pid_deputy_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "deputy" + }).ExecuteCommand(); + } + } + session.DropTable(); + } + if (!session.TableExist()) + { + session.CreateTable(); + session.AddIndex("itemid");//增加索引. + session.AddIndex("losetime");//增加索引. + } + #endregion + + //创建配置文件 + Config = this.ReadConfig(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + SDK.WebRequestEvent += SDK_WebRequestEvent; + InitIgnoreidsCache(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_WebRequestEvent(object sender, WebRequestEvents e) + { + try + { + #region + if (e.Param.ContainsKey("method"))//方法名称 + { + var method = e.Param["method"].ToLower(); + switch (method) + { + case "tbitem": + { + var resultJson = string.Empty; + try + { + if (!e.Param.ContainsKey("ids")) throw new Exception("缺少参数ids"); + var ids = e.Param["ids"].ToString(); + if (!string.IsNullOrWhiteSpace(ids)) + { + var idList = ids.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); + if (idList.Count != 0) + { + InitIgnoreidsCache(idList); + } + } + } + catch (Exception ex) + { + e.Send(ex.Message, 100); + return; + } + e.Send("请求成功", 200); + } + break; + } + } + #endregion + } + catch (Exception ex) + { + this.OnLog("淘宝返利web接收数据异常:" + ex.Message); + } + } + + public static List ignoreidsCache = new List(); + + private void InitIgnoreidsCache(List idList = null) + { + var nowTime = HttpExtend.GetTimeStamp(DateTime.Now); + + var session = ApiClient.GetSession(); + var temps = new List(); + var ignoreids = session.Find("select * from fl_plugin_tbrebate_ignoreids"); + if (ignoreids != null && ignoreids.Count != 0) + { + temps = ignoreids.Where(f => f.losetime < nowTime).ToList(); + if (temps != null && temps.Count != 0) + session.Deleteable(temps).ExecuteCommand(); + temps = ignoreids.Where(f => f.losetime >= nowTime).ToList(); + } + if (idList != null) + { + foreach (var itemid in idList) + { + var temp = temps.FirstOrDefault(f => f.itemid == itemid); + if (temp == null) + session.Insertable(new fl_plugin_tbrebate_ignoreids() { itemid = itemid, losetime = HttpExtend.GetTimeStamp(DateTime.Now.AddDays(2)) }).ExecuteCommand(); + else + { + temp.losetime = HttpExtend.GetTimeStamp(DateTime.Now.AddDays(2)); + session.Updateable(temp).ExecuteCommand(); + } + } + } + ignoreidsCache = session.Find("select * from fl_plugin_tbrebate_ignoreids"); + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.ChatType == CpsType.阿里妈妈) + { + //this.OnLog("淘宝订单:" + HttpHelper.ObjectToJson(e)); + var session = ApiClient.GetSession(); + //订单信息 + var order_tb = e.Order as fl_order_alimama; + + if (order_tb == null) return; + + if (e.Member != null) + { + #region 订单变化通知消息 + var robot_info = session.FindRobotInfo(e.Member.robot_name.Trim(), e.Member.robot_type); + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject(order_tb.db_point) as ItemPoint; + #region 下单用户订单检测(防撸) + if (e.Customer == null) + { + var prevent_theft_cache = session.FindSingle("select * from fl_prevent_theft_cache where order_id = @order_id", new { order_id = order_tb.trade_id });//防止上级多次触发 + if (prevent_theft_cache == null) + { + var isHint = false; + if (!string.IsNullOrWhiteSpace(order_tb.seller_id) && e.Member.status != MemberType.白名单) + { + #region 同一店铺多次购买(同一商品) + if (Class1.Config.AShop_SameCommodity_Switch) + { + var frequency = session.Find("select * from fl_order_alimama where db_userid = @db_userid and num_iid = @num_iid", new { db_userid = order_tb.db_userid, num_iid = order_tb.num_iid }).Count;//获取同价店铺同一件商品购买的次数 + if (Class1.Config.AShop_SameCommodity_Number <= frequency) + { + if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_tb, e.Member, point), order_tb.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户购买同一商品{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_SameCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_tb.num_iid; + prevent_theft_cache.mall_id = order_tb.seller_id; + prevent_theft_cache.order_id = order_tb.trade_id; + prevent_theft_cache.cps_type = CpsType.阿里妈妈; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_SameCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户购买同一商品{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + + #region 同一店铺多次购买(不同商品) + if (!isHint && Class1.Config.AShop_DifferentCommodity_Switch) + { + var frequency = session.Find("select * from fl_order_alimama where db_userid = @db_userid and seller_id = @seller_id", new { db_userid = order_tb.db_userid, seller_id = order_tb.seller_id }).Count; + if (Class1.Config.AShop_DifferentCommodity_Number <= frequency) + { + if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_tb, e.Member, point), order_tb.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_DifferentCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_tb.num_iid; + prevent_theft_cache.mall_id = order_tb.seller_id; + prevent_theft_cache.order_id = order_tb.trade_id; + prevent_theft_cache.cps_type = CpsType.阿里妈妈; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_DifferentCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + } + + #region 收货时间验证时长 + if (!isHint && Class1.Config.ReceivingTimeCheck_Switch && order_tb.tk_status == (int)AlimamaOrderStatus.订单结算 && e.Member.status != MemberType.白名单) + { + if (order_tb.earning_time != DateTime.MinValue) + { + var timeLag = (int)Math.Floor((order_tb.earning_time - order_tb.create_time).TotalHours); + if (timeLag <= Class1.Config.ReceivingTimeCheck_Hour) + { + if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_tb, e.Member, point), order_tb.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + e.Cancel = true; + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.ReceivingTimeCheck_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_tb.num_iid; + prevent_theft_cache.mall_id = order_tb.seller_id; + prevent_theft_cache.order_id = order_tb.trade_id; + prevent_theft_cache.cps_type = CpsType.阿里妈妈; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.ReceivingTimeCheck_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + //ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + return; + } + } + else if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + } + } + } + } + #endregion + + } + } + #endregion + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + { + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + #region 淘礼金订单只提示 付款/结算 + var is_tlj = session.CheckIsTljOrder(order_tb.adzone_id); + #endregion + + if (!is_tlj) + mess = _GetOrderStateMess(order_tb.db_status, SettleType.未结算提示, order_tb, e.Member, point); + else + { + if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.TljPaymentTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.TljSettlementTip; + else//淘礼金其他订单状态不给用户提示 + return; + mess = new VariateReplace().CommonReplace(mess, order_tb, e.Member, point); + } + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order_tb.msg_groupid); + } + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order_tb.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_OneLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_tb.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_TwoLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_tb.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_ThreeLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_tb.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_LeaderTip; + else if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order_tb.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + //ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_tb, e.Member, point).Replace("[下级昵称]", string.IsNullOrEmpty(e.Customer.realnick) ? e.Customer.usernick : e.Customer.realnick)); + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_tb, e.Member, point).Replace("[下级昵称]", e.Customer.realnick)); + } + #endregion + } + else + { + #region 多人查询通知消息 + var querys = session.Find("select robot_name,type,userid from fl_query_hist where itemid=@itemid and adzoneid = @adzoneid and userid > 0 and crt_time>@time group by userid,type,robot_name", new { itemid = order_tb.num_iid, adzoneid = order_tb.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (querys.Count > 0) + { + for (int i = 0; i < querys.Count; i++) + { + try + { + if (querys[i].type != CpsType.阿里妈妈) continue; + //未绑定的数量 + var unbound_count = int.Parse(session.FindTable($"select count(id) as num from fl_order_alimama where trade_parent_id = @trade_parent_id and db_userid != 0", new { trade_parent_id = order_tb.trade_parent_id }).Rows[0]["num"].ToString()); + if (unbound_count != 0) break;//已经被绑定直接停止 + + var queryhist_temp = querys[i]; + var userid = queryhist_temp.userid; + var robot_name = queryhist_temp.robot_name; + var robot_info = session.Find("select * from fl_robot_info where name = @name", new { name = robot_name }).FirstOrDefault();//机器人类型应该是没有的,直接通过机器人name查询机器人信息 + if (robot_info != null) + { + Thread.Sleep(5000); + var wxbase = Chat.Framework.ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot_name); + if (wxbase != null /*&& wxbase.WeixinType == WeixinType.Grpc微信*/ && wxbase.Status == WxStatus.在线) + { + var member = session.FindMemberInfoById(userid); + if (member != null) + { + ApiClient.SendMessage(robot_info, member.username, Config.LotUserQueryBindTip.Replace("[商品标题]", order_tb.item_title)); + + session.ExcuteSQL("update fl_query_hist set userid = @newuserid where itemid = @itemid and adzoneid = @adzoneid and robot_name = @robotname and userid = @userid", new { newuserid = (i - querys.Count + 1), itemid = order_tb.num_iid, adzoneid = order_tb.adzone_id, robotname = robot_name, userid = member.id }); + } + } + } + } + catch (Exception) + { } + } + } + #endregion + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private static List Regex_Items = new List() { @",\\""price\\"":{\\""priceText\\"":\\""(?.+?)\\"",", @",\\""price\\"":\\""(?.+?)\\""", @",\\""priceText\\"":\\""(?.+?)\\""," }; + /// + /// 判断网页链接的正则表达式 + /// + private string Reg_CheckIsUrl = @"(?<链接>((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?)"; + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + //过滤表情xml和卡片xml + if ((e.Message.Contains(@"("select * from fl_order_alimama where trade_parent_id = @trade_parent_id", new { trade_parent_id = orderid }); + + if (orders_temp != null && orders_temp.Count != 0) + { + var member = orders_temp.FirstOrDefault(f => f.db_userid != 0 && f.db_userid != _member.id); + if (member != null) + { + e.SendMessage(Config.OccupyOrderErrorTip.Replace("[订单号]", orderid)); + return; + } + var notices = new List(); + + var downAlimamaTimer = new DownAlimamaTimer(); + + #region 订单用户已经绑定 纯提示,非结算的订单也提示上级 + var bindOrders = orders_temp.Where(f => f.db_userid != 0).ToList(); + if (bindOrders != null && bindOrders.Count != 0) + { + foreach (var order in bindOrders) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + _member = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Config.OrderRepetBindTip, order, _member, point)); + else + e.SendMessage(_GetOrderStateMess(order.db_status, (order.db_status == SystemOrderStatus.订单结算 ? SettleType.已结算提示 : SettleType.未结算提示), order, _member, point)); + Thread.Sleep(500); + } + //return; + } + #endregion + + #region 订单没有被绑定(两种情况 => 一个订单已经被结算 一个是订单未结算) + var notBindOrders = orders_temp.Where(f => f.db_userid == 0).ToList(); + if (notBindOrders != null && notBindOrders.Count != 0) + { + if (notBindOrders[0].create_time < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderid},已经过了有效绑定时间!"); + return; + } + + foreach (var order in notBindOrders) + { + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + + + //没有绑定用户的订单进行绑定 + order.db_userid = _member.id; + order.db_robotname = e.RobotName; + order.db_robottype = e.RobotInfo.type; + order.msg_groupid = e.Groupid; + + bool is_allrebatesactivity = false; + #region 全额返利绑定 并且 将返利积分进行固定 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.TbAllRebatesSoftwareType && f.adzone_pid.EndsWith("_" + order.adzone_id)); + if (adzone != null) + { + var allrebatesactivity_infos = session.Find("select * from fl_plugin_allrebatesactivity_info where goods_id = @goods_id", new { goods_id = order.num_iid }); + if (allrebatesactivity_infos != null && allrebatesactivity_infos.Count != 0) + { + var allrebatesactivity_info = allrebatesactivity_infos.FirstOrDefault(f => f.time_begin <= order.create_time && order.create_time <= f.time_end && f.groups.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(z => Convert.ToInt64(z.Trim())).ToList().Contains(_member.group_id) && f.robots.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(z => z.Trim()).ToList().Contains(order.db_robotname)); + + if (allrebatesactivity_info != null) + { + //TODO这里还要判断已经成交的列表中是否存在订单数量 + + //var allrebatesactivity_orderlists = session.Queryable().Where(f => f.activity_id == allrebatesactivity_info.id && f.mid == _member.id).ToList(); + var allrebatesactivity_orderlists = session.Find("select * from fl_plugin_allrebatesactivity_orderlist where activity_id = @activity_id and mid = @mid", new { activity_id = allrebatesactivity_info.id, mid = _member.id }); + int purchased_quantity = 0;//已经购买的数量 + if (allrebatesactivity_orderlists != null && allrebatesactivity_orderlists.Count != 0) + { + foreach (var item in allrebatesactivity_orderlists) + { + var order_alimama = session.FindSingle("select * from fl_order_alimama where id = @id", new { id = item.oid }); + if (order_alimama != null) + { + if (order_alimama.db_status == SystemOrderStatus.订单结算 || order_alimama.db_status == SystemOrderStatus.全额退款 || order_alimama.db_status == SystemOrderStatus.部分退款 || order_alimama.db_status == SystemOrderStatus.订单付款 || order_alimama.db_status == SystemOrderStatus.订单冻结 || order_alimama.db_status == SystemOrderStatus.订单退款 || order_alimama.db_status == SystemOrderStatus.订单维权中) + { + purchased_quantity += order_alimama.item_num; + } + } + } + } + + if (allrebatesactivity_info.limit_quantity_number >= (order.item_num + purchased_quantity)) + { + is_allrebatesactivity = true; + var return_money = (double)((decimal)allrebatesactivity_info.return_money * (decimal)order.item_num); + var point = @"{""Type"":0,""Commission"":0,""SumPoint"":" + order.pub_share_pre_fee + @",""UserPoint"":" + return_money + @",""AwardOne"":0,""AwardTwo"":0,""AwardThree"":0,""AwardCreate"":0}"; + order.db_point = point; + order.db_userpoint = return_money; + + var robot = session.FindRobots().FirstOrDefault(f => f.name == order.db_robotname && order.db_robottype == f.type); + if (robot != null) + { + var allrebatesactivity_orderlist = new fl_plugin_allrebatesactivity_orderlist() + { + activity_id = allrebatesactivity_info.id, + mid = _member.id, + rid = robot.id, + oid = order.id + }; + session.Saveable(allrebatesactivity_orderlist).ExecuteCommand(); + } + } + } + } + } + #endregion + + #region 手动绑定,重新计算用户的返利积分 + if (!is_allrebatesactivity) + { + #region 判断是否为淘礼金订单,如果是淘礼金订单将不给这个订单返利 + var isTljOrder = session.CheckIsTljOrder(order.adzone_id); + #endregion + + //计算的佣金 - 判断使用设置模式,符合将扣除用户自定义预扣佣金 + var commission = session.GetTbComparisonFeeRate(order); + //var itempoint = session.FindItemPoint(_member, isTljOrder ? 0 : (order.commission == 0 ? order.pub_share_pre_fee : order.commission), order.item_num, CpsType.阿里妈妈); + var itempoint = session.FindItemPoint(_member, isTljOrder ? 0 : commission, order.item_num, CpsType.阿里妈妈); + + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + } + } + #endregion + + if (_member != null) + { + _member.bind_order++; + _member = session.UpdateMemberGroup(_member); + } + + #region 首次付款时间 + var record = session.FindStatisticsRecord(_member.id); + if (record == null) + { + record = new fl_statistics_record() { uid = _member.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + #endregion + + session.SaveOrUpdate(order); + + #region 淘宝订单尾号自动采集 + if (ApiClient.Setting.SystemConfig.order_alimama_last_auto_capture == SwitchType.开启) + { + //订单尾号和用户进行绑定 + if (session.FindAlimamaOrderLastnums().FirstOrDefault(f => f.userid == _member.id) == null) + { + session.Insertable(new fl_alimama_order_lastnum() { userid = _member.id, lastnumber = order.trade_parent_id.Substring(order.trade_parent_id.Length - 6, 6) }).ExecuteCommand(); + session.FindAlimamaOrderLastnums(true); + } + } + #endregion + + downAlimamaTimer.UpdateOrder(order, notices, session, isFrontData: true); + } + } + #endregion + + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.IsRewards) + tasks.Add(item); + else + SDK_OrderNoticeEvent(this, item); + } + } + #endregion + + e.Cancel = true; + } + else + { + e.SendMessage(Config.NotFoundOrderErrorTip.Replace("[订单号]", orderid)); + //加入缓存 + var bind = session.FindBindCache(orderid); + if (bind == null) + { + session.Insertable(new fl_bind_cache() { crt_time = DateTime.Now, db_robotid = e.RobotInfo.id, orderid = orderid, groupid = e.Groupid, db_userid = _member.id }).ExecuteCommand(); + session.FindBindCache(orderid, true); + } + e.Cancel = true; + } + return; + } + + if (OrderHelper.IsOrderId(e.Message.Trim())) + return; + #endregion + + #region 关键词解析、链接解析、标题查找 临时注释 + var tbinfoTemps = session.FindTbInfoTempGroups(); + var tbInfoTemp = tbinfoTemps.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (tbInfoTemp != null) + { + fl_cps_member tb_cps = null; + var pid = string.Empty;//使用的推广位 + + var isDefault = true; + if (!string.IsNullOrWhiteSpace(e.Groupid))//群pid + { + var groupAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + pid = groupAdzone.adzone_pid; + var pids = pid.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + if (pids.Length > 1) + { + string username = pids[1]; + tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == username); + isDefault = false; + } + } + } + + if (isDefault)//私人pid + { + var memberAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == _member.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + pid = memberAdzone.adzone_pid; + var pids = pid.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + if (pids.Length > 1) + { + string username = pids[1]; + tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == username); + isDefault = false; + } + } + } + + if (isDefault)//默认推广位 + { + var tgw = Tools.GetTuiguangwei(e.RobotInfo.name, _member, tbInfoTemp); + if (tgw == null || string.IsNullOrWhiteSpace(tgw.Pid)) throw new Exception("@阿里妈妈推广位异常.请检测后重试!!"); + pid = tgw.Pid; + var pids = pid.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + if (pids.Length > 1) + { + string username = pids[1]; + tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == username);//通过判断用户的购物积分,来判断用户使用哪个推广位 + } + } + + if (tb_cps == null) throw new Exception("@阿里妈妈推广位异常,请检测后重试!"); + else + { + string keyword = string.Empty; + bool IsTitle = false;//是否是标题 + AlimamaApi api = CpsClient.CreateAlimamaRequest(tb_cps); + + if (api == null) throw new Exception("@创建阿里妈妈API请求失败"); + + //var sss = api.SendTaobao("taobao.tbk.sc.invitecode.get", new { relation_app = "common", code_type = 3 }); + //var sss = api.SendTaobao("taobao.tbk.sc.publisher.info.save", new { info_type = 1, inviter_code = "RGA87B" }); + //Dictionary sss = null; + //try + //{ + // sss = api.SendTaobao("taobao.tbk.sc.publisher.info.get", new { info_type = 2, relation_app = "common" }); + //} + //catch (Exception ex) + //{} + + + if (Config.SearchCustomSwitch == SwitchType.开启) + { + if (!string.IsNullOrWhiteSpace(Config.SearchPrefix)) + { + //判断接收到的内容是都满足标题搜索或者关键词搜索 + var reg = Regex.Match(e.Message.Trim(), Config.SearchPrefix);//获取到符合关键词搜索的正则 + if (reg.Success) + { + keyword = reg.Groups["关键词"].Value.Trim(); + if (Config.SearchTitleSwitch == SwitchType.开启)//开启淘宝标题搜索 + { + var ileng = Tools.GetStringLength(keyword);//这里判断字符串的长度为 30个汉字,或者60个字节 + if (ileng >= 40 && ileng <= 100 && !Regex.IsMatch(keyword, Tools.Reg_CheckIsUrl))//非链接并且字符串字节长度符合小于等于40,大等于60的条件,才去查询标题 + IsTitle = true; + } + if (!IsTitle && !string.IsNullOrEmpty(keyword)) + { + var searchUrl = api.ComposeTbCms(pid, keyword);//内置的搜索机制 + e.SendMessage(Config.PreciseSearchSuccessTip.Replace("[关键词]", keyword).Replace("[购买地址]", ApiClient.ShortURL(searchUrl, Config.SearchDwzType).Result)); + return; + } + } + } + } + if (string.IsNullOrEmpty(keyword) && Config.SearchTitleSwitch == SwitchType.开启 && !Regex.IsMatch(e.Message, Tools.Reg_QRCode_Goods))//开启淘宝标题搜索 + { + if (!Regex.IsMatch(e.Message, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?") && !Regex.Match(e.Message, @"[!,<>!@#\$%\^&*()_+~>·@#¥%……&*()——+,。、!?\?]").Success) + { + var ipad = sender as WeixinBase; + var _event = e.Event as WXReiceveFriendMsg; + if (ipad != null && ((_event != null && !_event.IsRobot) || e.Event is WXReceiveGroupMsg)) + { + var ileng = Tools.GetStringLength(e.Message.Trim());//这里判断字符串的长度为 30个汉字,或者60个字节 + if (ileng >= 40 && ileng <= 100 && !Regex.IsMatch(e.Message.Trim(), Tools.Reg_CheckIsUrl))//非链接并且字符串字节长度符合小于等于40,大等于60的条件,才去查询标题 + { + keyword = e.Message.Trim(); + IsTitle = true; + } + } + } + } + + string message = e.Message; + //宝贝二维码识别 + string QRCodeUrl = string.Empty; + if (Config.QRCodeSearchSwitch == SwitchType.开启) + { + var reg_ = Regex.Match(e.Message, Tools.Reg_QRCode_Goods); + if (reg_.Success) + { + QRCodeUrl = Util.DecodeQRCode(reg_.Groups["二维码图片"].Value);//解析的二维码图片所得到的二维码内容 + message = message.Replace(reg_.Groups["二维码图片"].Value, ""); + } + } + + var pid_split = pid.Split('_'); + var tbAnalysis = new TBHelper.TbAnalysis(); + + var item_id = string.Empty; + try + { + item_id = tbAnalysis.FindItemIdByUrlAndTklAndMkl(string.IsNullOrEmpty(QRCodeUrl) ? message : QRCodeUrl, api, pid_split); + } + catch (Exception ex) + { + if (string.IsNullOrEmpty(keyword)) + { + //if (ex.Message.Contains("淘口令解析结果无效") || ex.Message.Contains("淘口令转链处理异常")) + //{ + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", "").Replace("[商品标题]", "")); + //} + return; + } + } + + Dictionary objData = null; + + if (!string.IsNullOrWhiteSpace(item_id)) + { + var temp = ignoreidsCache.FirstOrDefault(f => f.itemid == item_id); + if (temp != null && temp.losetime >= HttpExtend.GetTimeStamp(DateTime.Now)) + { + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", "").Replace("[商品标题]", "")); + return; + } + + } + + //标题搜索和商品id搜索 + if (!string.IsNullOrEmpty(keyword) || !string.IsNullOrEmpty(item_id)) + { + #region 限制商品ID + if (Class1.Config.ItemIDRestrictList.Contains(item_id)) + { + e.SendMessage(Config.ItemIDRestrictTip.Replace("[商品ID]", item_id)); + return; + } + #endregion + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + e.SendMessage(Config.SearchingTip);//正在搜索提示 + var title = string.Empty;//商品标题 + bool titleSuccess = false;//判断是否是标题搜索 + + for (int ii = 0; ii < 2; ii++) + { + titleSuccess = false; + try + { + //是否检测优惠券金额等信息 + bool isCheckCoupon = true; + + Dictionary privilege = null; + + Tools.GroupAdzoneCount(_member, tbInfoTemp); + + if (!string.IsNullOrEmpty(keyword) && IsTitle)//符合搜索标题查询宝贝 + { + try + { + objData = api.SendTaobao("taobao.tbk.sc.material.optional", new { adzone_id = pid_split[3], site_id = pid_split[2], q = keyword }); + titleSuccess = true; + } + catch (Exception _ex) + { + objData = null; + } + } + else if (!string.IsNullOrEmpty(item_id))//符合搜索宝贝id的条件 + { + try + { + objData = api.SendTaobao("taobao.tbk.item.info.get", new { num_iids = item_id }); + } + catch (Exception ex) + { + try + { + if (ex.Message.Contains("sub_msg\":\"无结果")) + { + #region 申请高佣 + privilege = tbAnalysis.GetPrivilege(api, item_id, pid_split); + if (privilege != null) + { + var _title = string.Empty; + var _price = "0"; + var _sellerNick = "天猫淘宝"; + var _pic = "https://timgsa.baidu.com/timg?image&size=b999_1000&imgtype=0&src=http%3A%2F%2Fpic.58pic.com%2F58pic%2F16%2F56%2F08%2F01358PICSDM_1024.jpg"; + + var tbinfo = tbAnalysis.FindTbInfoByItemId(item_id); + if (tbinfo != null) + { + _price = tbinfo.Price; + _sellerNick = tbinfo.ShopName; + _pic = tbinfo.ItemImage; + _title = tbinfo.ItemTitle; + } + else + { + HttpHelper http = new HttpHelper(); + var item = new HttpItem(); + item.URL = @"https://acs.m.taobao.com/gw/mtop.taobao.detail.getdetail/6.0/?data={%22itemNumId%22%3A%22" + item_id + @"%22&qq-pf-to=pcqq.group"; + var _html = http.GetHtml(item).Html; + + if (_html.Contains("SUCCESS::调用成功")) + { + var reg = Regex.Match(_html, @"item"":{""itemId"":""\d+?"",""title"":""(?.+?)"","""); + if (!reg.Success) + reg = Regex.Match(_html, @"""title"":""(?<title>.+?)"","""); + if (reg.Success) + _title = reg.Groups["title"].Value; + + foreach (var reg_item in Regex_Items) + { + reg = Regex.Match(_html, reg_item); + if (reg.Success) + { + _price = reg.Groups["price"].Value; + if (_price.Contains("-")) + _price = _price.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries)[0]; + break; + } + } + + reg = Regex.Match(_html, @"""sellerNick"":""(?<sellerNick>.+?)"""); + if (reg.Success) + _sellerNick = reg.Groups["sellerNick"].Value; + + reg = Regex.Match(_html, @"""images"":\[""(?<pic>.+?)"""); + if (reg.Success) + { + _pic = reg.Groups["pic"].Value; + if (!_pic.StartsWith("http")) + _pic = "https:" + _pic; + } + } + } + + if (_price == "0" || string.IsNullOrWhiteSpace(_price))//自己拼装的json 无法获取 + { + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", keyword).Replace("[商品标题]", title));//未搜索到提示语 + return; + } + + var temp = "{\"tbk_item_info_get_response\":{\"results\":{\"n_tbk_item\":[{\"cat_leaf_name\":\"\",\"cat_name\":\"\",\"item_url\":\"https:\\/\\/detail.tmall.com\\/item.htm?id=" + item_id + "\",\"material_lib_type\":\"1,2\",\"nick\":\"" + _sellerNick + "\",\"num_iid\":" + item_id + ",\"pict_url\":\"" + _pic + "\",\"provcity\":\"\",\"reserve_price\":\"" + _pic + "\",\"seller_id\":0,\"small_images\":{\"string\":[\"\",\"\",\"\",\"\"]},\"title\":\"" + _title + "\",\"user_type\":1,\"volume\":18,\"zk_final_price\":\"" + _price + "\"}]},\"request_id\":\"\"}}"; + + var dic = HttpExtend.JsonToDictionary(temp); + if (dic != null) + { + var key = "tbk_item_info_get_response"; + if (!dic.ContainsKey(key)) throw new Exception($"key = {key},html = {temp}"); + dic = dic[key] as Dictionary<String, object>; + if (dic.ContainsKey("result")) objData = dic["result"] as Dictionary<string, object>; + if (dic.ContainsKey("results")) objData = dic["results"] as Dictionary<string, object>; + } + } + #endregion + } + } + catch (Exception _ex) + { + objData = null; + } + } + } + if (objData != null && objData.Count != 0) + { + object tbk_temp_info = null; + if (titleSuccess) + { + if (objData.ContainsKey("result_list")) + { + var result_list = objData["result_list"] as Dictionary<string, object>; + if (result_list != null && result_list.ContainsKey("map_data")) + { + var map_data = (result_list["map_data"]) as ArrayList; + if (map_data != null && map_data.Count != 0) + tbk_temp_info = map_data[0]; + } + } + } + else + { + var n_tbk_item = (objData["n_tbk_item"]) as ArrayList; + if (n_tbk_item != null && n_tbk_item.Count != 0) + tbk_temp_info = n_tbk_item[0]; + } + + var tbk_item = tbk_temp_info as Dictionary<string, object>; + //店铺ID + var sellerId = string.Empty; + if (tbk_item.ContainsKey("pict_url")) + { + var reg = Regex.Match(tbk_item["pict_url"].ToString(), @"i\d+?/(?<店铺Id>\d+?)/"); + if (reg.Success) + { + sellerId = reg.Groups["店铺Id"].Value; + if (Config.SellerIDRestrictlist.Contains(sellerId)) + { + e.SendMessage(Config.SellerIDRestrictTip.Replace("[店铺ID]", sellerId)); + return; + } + } + } + + //商品链接 + var item_url = tbk_item["item_url"].ToString(); + //店铺名称 + var nick = tbk_item["nick"].ToString(); + //商品主图 + var pict_url = tbk_item["pict_url"].ToString(); + //商品id + item_id = tbk_item["num_iid"].ToString(); + //商品标题//< >&"© <,>,&,",©; + title = tbk_item["title"].ToString().Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©");//这里有个看不见的字符,要将其替换掉 + + //原价 + var reserve_price = double.Parse(tbk_item["reserve_price"].ToString()); + //商品折扣价格(当前售价) + var zk_final_price = double.Parse(tbk_item["zk_final_price"].ToString()); + //30天销量 + var volume = "0"; + if (tbk_item.ContainsKey("volume")) + volume = tbk_item["volume"].ToString(); + + //券后价 + var endPrice = -1d; + + #region 检测连接中是否包含优惠券信息 + var activityId = string.Empty; + activityId = tbAnalysis.activityId; + var regs = Regex.Matches(e.Message, Reg_CheckIsUrl); + if (regs != null && regs.Count != 0) + { + foreach (Match item in regs) + { + if (item.Groups["链接"].Value.Contains("uland.taobao")) + { + var reg = Regex.Match(item.Groups["链接"].Value, @"activityId=(?<活动ID>[A-Za-z0-9]+)"); + if (reg.Success) + activityId = reg.Groups["活动ID"].Value; + #region 获取店铺ID并且检测是否为屏蔽的店铺 + //https://uland.taobao.com/quan/detail?sellerId=2203061148088&activityId=91a71ae9a76445288724467712c0083d + reg = Regex.Match(item.Groups["链接"].Value, @"sellerId=(?<店铺ID>[^&]*)"); + if (reg.Success) + { + sellerId = reg.Groups["店铺ID"].Value; + if (Config.SellerIDRestrictlist.Contains(sellerId)) + { + e.SendMessage(Config.SellerIDRestrictTip.Replace("[店铺ID]", sellerId)); + return; + } + } + #endregion + break; + } + } + } + #endregion + + #region 申请高佣 + //最高佣金率 + var commission_rate = 0d; + + if (Config.QueryComparisonSwitch == QueryComparisonType.查询使用实时佣金) + { + #region 获取用户的special_id + var special_id = string.Empty; + try + { + var _data = new { info_type = 2, relation_app = "common", external_id = $"u:{e.GetMemberinfo().username}" }; + var result = api.SendTaobao("taobao.tbk.sc.publisher.info.get", _data); + if (result != null && result.ContainsKey("data")) + { + var data = result["data"] as Dictionary<string, object>; + if (data != null && data.ContainsKey("inviter_list")) + { + var inviter_list = data["inviter_list"] as Dictionary<string, object>; + if (inviter_list != null && inviter_list.ContainsKey("map_data")) + { + var map_data = inviter_list["map_data"] as ArrayList; + if (map_data != null && map_data.Count != 0) + { + foreach (Dictionary<string, object> item in map_data) + { + if (item.ContainsKey("special_id")) + special_id = item["special_id"].ToString(); + } + } + } + } + } + } + catch (Exception ex) + { } + #endregion + + if (privilege == null || !privilege.ContainsKey("min_commission_rate")) + privilege = tbAnalysis.GetPrivilege(api, item_id, pid_split, $"u:{e.GetMemberinfo().username}", special_id); + } + else if (Config.QueryComparisonSwitch == QueryComparisonType.查询使用正常佣金) + { + if (privilege == null || !privilege.ContainsKey("max_commission_rate")) + privilege = tbAnalysis.GetPrivilege(api, item_id, pid_split); + } + else if (Config.QueryComparisonSwitch == QueryComparisonType.查询使用比价佣金) + { + if (privilege == null) + privilege = tbAnalysis.GetPrivilege(api, item_id, pid_split); + if (privilege != null && !privilege.ContainsKey("min_commission_rate")) + { + var privilege_temp = tbAnalysis.GetPrivilege(api, item_id, pid_split, $"u:{e.GetMemberinfo().username}"); + if (privilege_temp != null) + { + var data_temp = privilege_temp["data"] as Dictionary<string, object>; + if (data_temp != null && data_temp.ContainsKey("min_commission_rate")) + commission_rate = double.Parse(data_temp["min_commission_rate"].ToString()); + } + } + } + if (privilege == null) throw new Exception("申请高佣失败,原因未知"); + #endregion + + var privilege_data = privilege["data"] as Dictionary<string, object>; + + #region 获取商品佣金 + if (commission_rate == 0) + { + if (privilege_data.ContainsKey("max_commission_rate")) + commission_rate = double.Parse(privilege_data["max_commission_rate"].ToString()); + else if (privilege_data.ContainsKey("min_commission_rate")) + commission_rate = double.Parse(privilege_data["min_commission_rate"].ToString()); + } + //this.OnLog("min_commission_rate3 = " + commission_rate); + #endregion + + //优惠券地址 + var coupon_click_url = string.Empty; + var coupon_price = 0.00d; + //if (privilege_data.ContainsKey("coupon_info") && Config.NoCouponModeSwitch == SwitchType.关闭)//无券 + //{ + // var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满\d+元减(\d+)元"); + // if (quan_reg.Success) + // coupon_price = double.Parse(quan_reg.Groups[1].Value); + //} + //else + // coupon_price = 0.00d; + + #region 2020年11月7日17:43:22 (商品获取不到折后价)xxx + //if (Config.NoCouponModeSwitch == SwitchType.开启)//无券 + // coupon_price = 0.00d; + //else if (privilege_data.ContainsKey("mm_coupon_info") && privilege_data.ContainsKey("coupon_info")) + //{ + // //正常优惠券 + // var coupon_price_temp = 0d; + // var condition_price_temp = 0d; + // var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + // if (quan_reg.Success) + // { + // coupon_price_temp = double.Parse(quan_reg.Groups["减"].Value); + // condition_price_temp = double.Parse(quan_reg.Groups["满"].Value); + // } + + // //妈妈优惠券 + // var mm_coupon_price_temp = 0d; + // var mm_condition_price_temp = 0d; + // var mm_quan_reg = Regex.Match(privilege_data["mm_coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + // if (mm_quan_reg.Success) + // { + // mm_coupon_price_temp = double.Parse(mm_quan_reg.Groups["减"].Value); + // mm_condition_price_temp = double.Parse(mm_quan_reg.Groups["满"].Value); + // } + + // var condition_price = 0d;//满减条件 + // if (mm_condition_price_temp <= zk_final_price && condition_price_temp <= zk_final_price) + // { + // if (mm_coupon_price_temp > coupon_price_temp) + // { + // coupon_price = mm_coupon_price_temp; + // condition_price = mm_condition_price_temp; + // coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + // } + // else + // { + // coupon_price = coupon_price_temp; + // condition_price = condition_price_temp; + // coupon_click_url = privilege_data["coupon_click_url"].ToString(); + // } + // } + // //妈妈优惠券条件金额小于最小的售价并且妈妈优惠券金额比正常优惠券高 + // else if (mm_condition_price_temp <= zk_final_price && mm_coupon_price_temp > coupon_price_temp) + // { + // coupon_price = mm_coupon_price_temp; + // condition_price = mm_condition_price_temp; + // coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + // } + // //正常优惠券条件金额小于最小的售价并且正常优惠券金额比妈妈优惠券高 + // else if (condition_price_temp <= zk_final_price && mm_coupon_price_temp < coupon_price_temp) + // { + // coupon_price = coupon_price_temp; + // condition_price = condition_price_temp; + // coupon_click_url = privilege_data["coupon_click_url"].ToString(); + // } + // else if (mm_condition_price_temp > zk_final_price && condition_price_temp > zk_final_price) + // { + // if (mm_coupon_price_temp < coupon_price_temp) + // { + // coupon_price = coupon_price_temp; + // condition_price = condition_price_temp; + // coupon_click_url = privilege_data["coupon_click_url"].ToString(); + // } + // else + // { + // coupon_price = mm_coupon_price_temp; + // condition_price = mm_condition_price_temp; + // coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + // } + // } + + // var multiple = Math.Ceiling(condition_price / zk_final_price); + // if (multiple != 0) + // zk_final_price = zk_final_price * multiple; + + //} + //else if (privilege_data.ContainsKey("mm_coupon_info")) + //{ + // var quan_reg = Regex.Match(privilege_data["mm_coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + // if (quan_reg.Success) + // { + // coupon_price = double.Parse(quan_reg.Groups["减"].Value); + // var condition_price = double.Parse(quan_reg.Groups["满"].Value); + + // var multiple = Math.Ceiling(condition_price / zk_final_price); + // if (multiple != 0) + // zk_final_price = zk_final_price * multiple; + // coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + // } + //} + //else if (privilege_data.ContainsKey("coupon_info")) + //{ + // var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + // if (quan_reg.Success) + // { + // coupon_price = double.Parse(quan_reg.Groups["减"].Value); + // var condition_price = double.Parse(quan_reg.Groups["满"].Value); + // var multiple = Math.Ceiling(condition_price / zk_final_price); + // if (multiple != 0) + // zk_final_price = zk_final_price * multiple; + // coupon_click_url = privilege_data["coupon_click_url"].ToString(); + // } + //} + //else + //{ + // //没有优惠券检测大淘客是否有优惠券 + // if (string.IsNullOrWhiteSpace(activityId)) + // { + // activityId = TBHelper.FindGoodsActivityIdAll(item_id, out sellerId, out oldPrice); + // if (oldPrice != -1) + // zk_final_price = oldPrice; + // } + //} + #endregion + + //优惠券满减比较的价格 + var coupon_comparison_price = (reserve_price > zk_final_price ? reserve_price : zk_final_price); + + #region 2020年11月7日17:44:08 (商品获取不到折后价,改成先获取大淘客等加个) + if (Config.NoCouponModeSwitch == SwitchType.开启)//无券 + coupon_price = 0.00d; + else + { + + //检测大淘客是否有优惠券,和价格 + //activityId = TBHelper.FindGoodsActivityIdAll(item_id, out sellerId, out payPrice); + TbExCoupon exCoupon = TBHelper.FindGoodsCouponInfo(item_id); + + if (exCoupon != null) + { + activityId = exCoupon.activityId; + sellerId = exCoupon.sellerId; + coupon_price = exCoupon.couponAmount; + zk_final_price = exCoupon.salePrice; + endPrice = exCoupon.endPrice; + if (privilege_data.ContainsKey("coupon_click_url")) + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + else if (privilege_data.ContainsKey("mm_coupon_click_url")) + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + else + coupon_click_url = privilege_data["item_url"].ToString(); + isCheckCoupon = false; + } + else + { + if (privilege_data.ContainsKey("mm_coupon_info") && privilege_data.ContainsKey("coupon_info")) + { + //正常优惠券 + var coupon_price_temp = 0d; + var condition_price_temp = 0d; + var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (quan_reg.Success) + { + coupon_price_temp = double.Parse(quan_reg.Groups["减"].Value); + condition_price_temp = double.Parse(quan_reg.Groups["满"].Value); + } + + //妈妈优惠券 + var mm_coupon_price_temp = 0d; + var mm_condition_price_temp = 0d; + var mm_quan_reg = Regex.Match(privilege_data["mm_coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (mm_quan_reg.Success) + { + mm_coupon_price_temp = double.Parse(mm_quan_reg.Groups["减"].Value); + mm_condition_price_temp = double.Parse(mm_quan_reg.Groups["满"].Value); + } + + var condition_price = 0d;//满减条件 + if (mm_condition_price_temp <= coupon_comparison_price && condition_price_temp <= coupon_comparison_price) + { + if (mm_coupon_price_temp > coupon_price_temp) + { + coupon_price = mm_coupon_price_temp; + condition_price = mm_condition_price_temp; + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + } + else + { + coupon_price = coupon_price_temp; + condition_price = condition_price_temp; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + } + //妈妈优惠券条件金额小于最小的售价并且妈妈优惠券金额比正常优惠券高 + else if (mm_condition_price_temp <= coupon_comparison_price && mm_coupon_price_temp > coupon_price_temp) + { + coupon_price = mm_coupon_price_temp; + condition_price = mm_condition_price_temp; + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + } + //正常优惠券条件金额小于最小的售价并且正常优惠券金额比妈妈优惠券高 + else if (condition_price_temp <= coupon_comparison_price && mm_coupon_price_temp < coupon_price_temp) + { + coupon_price = coupon_price_temp; + condition_price = condition_price_temp; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + else if (mm_condition_price_temp > coupon_comparison_price && condition_price_temp > coupon_comparison_price) + { + if (mm_coupon_price_temp < coupon_price_temp) + { + coupon_price = coupon_price_temp; + condition_price = condition_price_temp; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + else + { + coupon_price = mm_coupon_price_temp; + condition_price = mm_condition_price_temp; + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + } + } + + var multiple = Math.Ceiling(condition_price / coupon_comparison_price); + if (multiple != 0) + zk_final_price = zk_final_price * multiple; + } + else if (privilege_data.ContainsKey("mm_coupon_info")) + { + var quan_reg = Regex.Match(privilege_data["mm_coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (quan_reg.Success) + { + coupon_price = double.Parse(quan_reg.Groups["减"].Value); + var condition_price = double.Parse(quan_reg.Groups["满"].Value); + + var multiple = Math.Ceiling(condition_price / coupon_comparison_price); + if (multiple != 0) + zk_final_price = zk_final_price * multiple; + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + } + } + else if (privilege_data.ContainsKey("coupon_info")) + { + var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (quan_reg.Success) + { + coupon_price = double.Parse(quan_reg.Groups["减"].Value); + var condition_price = double.Parse(quan_reg.Groups["满"].Value); + var multiple = Math.Ceiling(condition_price / coupon_comparison_price); + if (multiple != 0) + zk_final_price = zk_final_price * multiple; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + } + else + { + ////没有优惠券检测大淘客是否有优惠券 + //if (string.IsNullOrWhiteSpace(activityId)) + //{ + // activityId = TBHelper.FindGoodsActivityIdAll(item_id, out sellerId, out oldPrice); + // if (oldPrice != -1) + // zk_final_price = oldPrice; + //} + } + } + } + #endregion + + if (Config.NoCouponModeSwitch == SwitchType.关闭) + { + if (string.IsNullOrWhiteSpace(coupon_click_url)) + coupon_click_url = privilege_data.ContainsKey("mm_coupon_click_url") ? privilege_data["mm_coupon_click_url"].ToString() : privilege_data["coupon_click_url"].ToString(); + + #region 新的 + if (isCheckCoupon && !string.IsNullOrWhiteSpace(activityId) && !string.IsNullOrWhiteSpace(sellerId)) + { + #region 获取优惠券金额 + var hsf_coupon = AlimamaApi.mtop_alimama_union_hsf_coupon_get(sellerId, activityId); + if (hsf_coupon != null) + { + if (hsf_coupon.ContainsKey("result")) + { + var result = hsf_coupon["result"] as Dictionary<string, object>; + + var isValid = true; + //var isValid = false; + //if (result.ContainsKey("effectiveStartTime")) + //{ + // var effectiveStartTime = result["effectiveStartTime"].ToString(); + // try + // { + // isValid = DateTime.Now >= DateTime.Parse(effectiveStartTime); + // } + // catch (Exception ex) + // { } + //} + + if (isValid) + { + if (result.ContainsKey("amount")) + coupon_price = double.Parse(result["amount"].ToString()); + if (result.ContainsKey("startFee")) + { + //zk_final_price = double.Parse(result["startFee"].ToString()); + var startFee = double.Parse(result["startFee"].ToString()); + var multiple = Math.Ceiling(startFee / coupon_comparison_price); + if (multiple != 0) + zk_final_price = zk_final_price * multiple; + } + } + } + } + #endregion + } + else + { + if (privilege_data.ContainsKey("coupon_start_time")) + { + var coupon_start_time = DateTime.Parse(privilege_data["coupon_start_time"].ToString()) <= DateTime.Now.Date; + isCheckCoupon = false; + } + if (isCheckCoupon) + { + var coupon = api.CheckCoupon(coupon_click_url);//检查优惠券有效性 + //优惠券过期 + if (coupon != null && coupon.retStatus != 0 && string.IsNullOrWhiteSpace(activityId)) + { + coupon_click_url = privilege_data["item_url"].ToString(); + coupon_price = 0.00d; + zk_final_price = double.Parse(tbk_item["zk_final_price"].ToString()); + } + } + } + #endregion + } + else + { + coupon_click_url = privilege_data["item_url"].ToString(); + coupon_price = 0.00d; + } + + if (endPrice == -1) + endPrice = (double)((decimal)zk_final_price - (decimal)coupon_price); + + //券后 总佣金 + //var useCoupon_totalCommFee = Math.Round((endPrice != -1 ? endPrice : (zk_final_price - coupon_price)) * (commission_rate / 100.00), 2); + var useCoupon_totalCommFee = Math.Round(endPrice * (commission_rate / 100.00), 2); + //用券后 给用户的佣金 + var useCoupon_commFee = session.FindItemPoint(_member, useCoupon_totalCommFee, 1, CpsType.阿里妈妈); + //不用券 佣金 + var unuseCoupon_totalCommFee = Math.Round(zk_final_price * (commission_rate / 100.00), 2); + //不用券 给用户的佣金 + var unuseCoupon_commFee = session.FindItemPoint(_member, unuseCoupon_totalCommFee, 1, CpsType.阿里妈妈); + + #region 淘礼金 + //生成淘礼金链接,如果返回空,这不能生成. + var tljUrl = TljMethod(e.GetMemberinfo(true), ref api, item_id, useCoupon_commFee.UserPoint); + if (!string.IsNullOrWhiteSpace(tljUrl)) + { + var _tlj = session.FindTljInfos().FirstOrDefault(f => f.username == api.Member.username); + if (_tlj != null) + pid_split = _tlj.adzone_pid.Split('_'); + } + #endregion + + //判断是否有淘礼金,有淘礼金用淘礼金 + var couponUrl = string.IsNullOrWhiteSpace(tljUrl) ? coupon_click_url : tljUrl; + + if (!string.IsNullOrWhiteSpace(activityId)) + couponUrl = couponUrl + "&activityId=" + activityId; + + #region 获取淘口令 tkl + var tkl = string.Empty; + try + { + string _pict_url = pict_url; + string _title = title; + if (Config.TKLCustomSwitch == SwitchType.开启) + { + if (!string.IsNullOrWhiteSpace(Config.TKLImageUrl)) + _pict_url = Config.TKLImageUrl; + if (!string.IsNullOrWhiteSpace(Config.TKLTitle)) + _title = Config.TKLTitle; + } + + tkl = tbAnalysis.FindTKL(couponUrl, _title, _pict_url, api); + if (string.IsNullOrEmpty(tkl)) + { + tkl = tbAnalysis.FindTKL(couponUrl, _title, _pict_url, api); + if (!string.IsNullOrEmpty(tkl)) break; + } + if (string.IsNullOrEmpty(tkl)) + { + //e.SendMessage(ApiClient.Setting.SystemConfig.msg_error); + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", keyword).Replace("[商品标题]", title));//未搜索到提示语 + return; + } + } + catch (Exception ex) + { + throw new Exception($"@获取淘口令异常:{ex.Message} - {ex.StackTrace}"); + } + #endregion + + //淘口令的前/后符号有没有设置.有设置将替换掉 + tkl = tbAnalysis.ReplaceTklModifier(tkl); + + #region 获取短连接 + couponUrl = tbAnalysis.FindShortUrlBySrcUrl(couponUrl, api); + #endregion + + var composeUrl = api.ComposeTbClick(item_id, pict_url, tkl, couponUrl, true);//中间页地址 + + //this.OnLog($"中间页地址:({item_id}){composeUrl},原始连接:{couponUrl}"); + + #region 淘礼金 + if (!string.IsNullOrWhiteSpace(tljUrl)) + { + var mess = Config.TljSearchSuccess; + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("<appmsg") ? title.Replace("<", "").Replace(">", "") : title) + .Replace("[商品原价]", zk_final_price.ToString()) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[月销量]", volume) + .Replace("[店铺名称]", nick) + //.Replace("[券后返利]", useCoupon_commFee.UserPoint.ToString()) + //.Replace("[劵后返利]", useCoupon_commFee.UserPoint.ToString()) + //.Replace("[弃券返利]", unuseCoupon_commFee.UserPoint.ToString()) + //.Replace("[券后价]", ((decimal)zk_final_price - (decimal)coupon_price).ToString()) + //.Replace("[劵后价]", ((decimal)zk_final_price - (decimal)coupon_price).ToString()) + .Replace("[优惠券金额]", (coupon_price != 0 ? coupon_price.ToString() : "0")) + .Replace("[淘礼金金额]", useCoupon_commFee.UserPoint.ToString()) + .Replace("[购买地址]", couponUrl) + .Replace("[购买中间页地址]", composeUrl) + .Replace("[购买淘口令]", tkl) + .Replace("[共节省]", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, zk_final_price.ToString(), coupon_price.ToString(), ((decimal)zk_final_price - (decimal)coupon_price).ToString(), pict_url, composeUrl, ApiClient.QrImageType.模板B, CpsType.阿里妈妈) + "]" : string.Empty) + ); + } + #endregion + #region 正常订单 + else + { + //有券的情况 + if (coupon_price != 0) + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithCouponTip))) + mess = Config.SearchSuccessWithCouponTip; + else + mess = Config.QQSearchSuccessWithCouponTip; + + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("<appmsg") ? title.Replace("<", "").Replace(">", "") : title) + .Replace("[商品原价]", zk_final_price.ToString()) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[月销量]", volume) + .Replace("[店铺名称]", nick) + .Replace("[券后返利]", useCoupon_commFee.UserPoint.ToString()) + .Replace("[劵后返利]", useCoupon_commFee.UserPoint.ToString()) + .Replace("[弃券返利]", unuseCoupon_commFee.UserPoint.ToString()) + .Replace("[劵后价]", "[券后价]") + .Replace("[券后价]", endPrice.ToString()) + .Replace("[优惠券金额]", coupon_price.ToString()) + .Replace("[购买地址]", couponUrl) + .Replace("[购买中间页地址]", composeUrl) + .Replace("[购买淘口令]", tkl) + .Replace("[共节省]", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint).ToString()) + //.Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, zk_final_price.ToString(), coupon_price.ToString(), ((decimal)zk_final_price - (decimal)coupon_price).ToString(), pict_url, composeUrl, ApiClient.QrImageType.模板B, CpsType.阿里妈妈) + "]" : string.Empty) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, zk_final_price.ToString(), coupon_price.ToString(), endPrice.ToString(), pict_url, composeUrl, ApiClient.QrImageType.模板B, CpsType.阿里妈妈) + "]" : string.Empty) + ); + } + else//没有券的情况 + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithoutCouponTip))) + mess = Config.SearchSuccessWithoutCouponTip; + else + mess = Config.QQSearchSuccessWithoutCouponTip; + + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("<appmsg") ? title.Replace("<", "").Replace(">", "") : title) + .Replace("[商品原价]", zk_final_price.ToString()) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[月销量]", volume) + .Replace("[店铺名称]", nick) + .Replace("[返利积分]", unuseCoupon_commFee.UserPoint.ToString()) + .Replace("[购买地址]", couponUrl) + .Replace("[购买中间页地址]", composeUrl) + .Replace("[购买淘口令]", tkl) + .Replace("[共节省]", (useCoupon_commFee.UserPoint).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, zk_final_price.ToString(), "0", zk_final_price.ToString(), pict_url, composeUrl, ApiClient.QrImageType.模板B, CpsType.阿里妈妈) + "]" : string.Empty) + ); + } + } + #endregion + + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + session.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.阿里妈妈, + itemid = item_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = _member.id, + title = title, + adzoneid = pid_split[3], + mallid = sellerId, + }).ExecuteCommand(); + session.UpdateRecord(_member.id); + + var shared = new Dictionary<string, object>(); + shared["msg_type"] = "查询宝贝"; + shared["msg_username"] = _member.username; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + #endregion + return; + } + else + { + var flag_tianmao = api.IsTianmao(item_id); + + #region 判断是否需要标题 + if (string.IsNullOrWhiteSpace(keyword) && string.IsNullOrWhiteSpace(title) && (flag_tianmao || Config.SearchTitleSwitch_NoCommission == SwitchType.开启 || Config.SearchNoCommissionTip.Contains("[商品标题]"))) + { + var reg = Regex.Match(e.Message, @"【(?<标题>.+)】"); + if (reg.Success) + title = reg.Groups["标题"].Value; + if (string.IsNullOrEmpty(title)) + { + #region 获取标题 + HttpHelper http = new HttpHelper(); + var item = new HttpItem(); + item.URL = @"https://acs.m.taobao.com/gw/mtop.taobao.detail.getdetail/6.0/?data={%22itemNumId%22%3A%22" + item_id + @"%22&qq-pf-to=pcqq.group"; + var _html = http.GetHtml(item).Html; + if (_html.Contains("SUCCESS::调用成功")) + { + reg = Regex.Match(_html, @"""title"":""(?<title>[^""]{10,})"","""); + if (reg.Success) + title = reg.Groups["title"].Value; + } + else + { + var html = string.Empty; + for (int i = 0; i < 4; i++) + { + HttpItem httpItem = new HttpItem() + { + URL = @"https://item.taobao.com/item.htm?id=" + item_id,//宝贝的链接 + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = true, + AutoRedirectCookie = true + }; + http = new HttpHelper(); + var result = http.GetHtml(httpItem); + + if (!(result != null && (result.Html.Contains("操作超时")) || result.Html.Contains("基础连接已经关闭"))) + { + html = result.Html; + break; + } + Thread.Sleep(200); + } + reg = Regex.Match(html, @"<meta name=""keywords"" content=""(?<标题>.+?)""/>"); + if (reg.Success) + { + title = reg.Groups["标题"].Value.Replace("淘宝,掏宝,网上购物,店铺, ", ""); + if (title.Last() == '.') + title = title.Substring(0, title.Length - 1); + } + else + { + + } + } + #endregion + } + } + #endregion + + if (flag_tianmao) + { + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.custom_type == Resources.TbActivitySoftwareType && f.robot_id == e.RobotInfo.id); + if (adzone != null) + { + var group = session.FindAdzoneGroups(CpsType.阿里妈妈).FirstOrDefault(f => f.id == adzone.adzone_group); + if (group != null) + { + var activity = Tools.GetActivityTuiguangwei(e.RobotInfo.name, tbInfoTemp); + if (activity == null) return; + + var pids = activity.Pid.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + if (pids.Length > 1) + { + string username = pids[1]; + tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == username);//通过判断用户的购物积分,来判断用户使用哪个推广位 + } + if (tb_cps == null) throw new Exception("@阿里妈妈推广位异常,请检测后重试 !"); + api = CpsClient.CreateAlimamaRequest(tb_cps); + if (api == null) throw new Exception("@创建阿里妈妈API请求失败"); + + #region 生成自己的淘口令 + var tkl = tbAnalysis.FindTKL(activity.ShortUrl, "复制宝贝标题,再天猫精选中搜索", "https://img.alicdn.com/tfs/TB1MaLKRXXXXXaWXFXXXXXXXXXX-480-260.png", api); + + if (!string.IsNullOrWhiteSpace(tkl)) + { + if (!string.IsNullOrEmpty(title)) + { + title = title.Replace("这个#聚划算团购#宝贝不错:", "").Replace("(分享自@手机淘宝android客户端)", ""); + var temp_url = api.ComposeTbClick(item_id, "https://img.alicdn.com/tfs/TB1MaLKRXXXXXaWXFXXXXXXXXXX-480-260.png", tkl, activity.ShortUrl, true, -1, Config.CoercePageUrl.Trim());//中间页地址 + e.SendMessage(Config.CoerceSearchSuccessTip + .Replace("[商品标题]", title) + .Replace("[商品原价]", "未知") + .Replace("[商品主图]", "")//$"[图片 ={tbInfo.ItemImage}]") + .Replace("[月销量]", "未知") + .Replace("[店铺名称]", "未知") + .Replace("[购买中间页地址]", temp_url) + .Replace("[购买淘口令]", tkl) + .Replace("[图片地址]", "") + ); + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + session.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.阿里妈妈, + itemid = item_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = _member.id, + title = title, + adzoneid = activity.Pid.Split('_')[3], + mallid = string.Empty + }).ExecuteCommand(); + session.UpdateRecord(_member.id); + + var _shared = new Dictionary<string, object>(); + _shared["msg_type"] = "查询宝贝"; + _shared["msg_username"] = _member.username; + EventClient.OnEvent(sender, new SharedEvents(_shared)); + #endregion + return; + } + } + #endregion + } + } + } + + session.UpdateRecord(_member.id); + var shared = new Dictionary<string, object>(); + shared["msg_type"] = "查询宝贝"; + shared["msg_username"] = _member.username; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + + if (string.IsNullOrWhiteSpace(keyword) && ii == 0 && !string.IsNullOrWhiteSpace(title) && Config.SearchTitleSwitch_NoCommission == SwitchType.开启) + { + keyword = title; + IsTitle = true; + var searchUrl = api.ComposeTbCms(pid, keyword);//内置的搜索机制 + e.SendMessage(Config.SearchTitle_NoCommissionTip.Replace("[商品标题]", title).Replace("[购买地址]", ApiClient.ShortURL(searchUrl).Result)); + //continue; + return; + } + else + { + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", keyword).Replace("[商品标题]", title));//未搜索到提示语 + //session.UpdateRecord(_member.id); + //var shared = new Dictionary<string, object>(); + //shared["msg_type"] = "查询宝贝"; + //shared["msg_username"] = _member.username; + //var sharedEvent = new SharedEvents(shared); + //EventClient.OnEvent(sender, sharedEvent); + return; + } + } + } + catch (Exception ex) + { + if (Regex.IsMatch(ex.Message, @"sub_msg\"":\""无结果")) + { + if (string.IsNullOrWhiteSpace(keyword) && ii == 0 && !string.IsNullOrWhiteSpace(title) && Config.SearchTitleSwitch_NoCommission == SwitchType.开启) + { + keyword = title; + IsTitle = true; + var searchUrl = api.ComposeTbCms(pid, keyword);//内置的搜索机制 + e.SendMessage(Config.SearchTitle_NoCommissionTip.Replace("[商品标题]", title).Replace("[购买地址]", ApiClient.ShortURL(searchUrl).Result)); + //continue; + return; + } + else + { + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", keyword).Replace("[商品标题]", title)); + session.UpdateRecord(_member.id); + var shared = new Dictionary<string, object>(); + shared["msg_type"] = "查询宝贝"; + shared["msg_username"] = _member.username; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + return; + } + } + else //if (ex.Message.Contains("该item_id对应宝贝已下架或非淘客宝贝")) + { + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", keyword).Replace("[商品标题]", title));//未搜索到提示语 + throw ex; + } + //else + //{ + // throw ex; + //} + } + } + } + } + } + #endregion + } + catch (Exception ex) + { + if (ex.Message.StartsWith("@")) + this.OnLog($"E :({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message.Replace("@", "")}"); + else + this.OnLog($"E:({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message} - {ex.StackTrace}"); + this.OnLog(ApiClient.Setting.SystemConfig.msg_error); + } + } + + /// <summary> + /// 订单状态 提示语替换 + /// </summary> + /// <param name="order"></param> + /// <param name="objs"></param> + /// <returns></returns> + public static string _GetOrderStateMess(SystemOrderStatus order, SettleType settle, params object[] objs) + { + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.订单维权中: + mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(settle == SettleType.未结算提示 ? Config.OrderSettlementTip : Config.OrderAlreadySettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Config.OrderFreezeTip, objs); + break; + case SystemOrderStatus.全额退款: + mess = new VariateReplace().CommonReplace(Config.OrderFrozen_AllTip, objs); + break; + case SystemOrderStatus.部分退款: + mess = new VariateReplace().CommonReplace(Config.OrderFrozen_PartTip, objs); + break; + } + return mess; + } + + + + /// <summary> + /// 淘礼金方法 + /// </summary> + /// <param name="member"></param> + /// <returns></returns> + public string TljMethod(fl_member_info member, ref AlimamaApi api, string item_id, double perface) + { + try + { + if (!Class1.Config.TljOnOff) return string.Empty; + if (perface < 1) return string.Empty; + + var session = ApiClient.GetSession(); + + var tljInfos = session.FindTljInfos(); + var tljCreateRecords = session.Find<fl_alimama_tlj_create_record>("select * from fl_alimama_tlj_create_record"); + if (tljInfos != null && tljInfos.Count != 0) + { + var cpsnames1 = tljInfos.Select(f => f.username).ToList(); + var cpsnames2 = tljCreateRecords.Select(f => f.cpsname).ToList(); + for (int i = 0; i < cpsnames1.Count; i++) + { + if (!cpsnames2.Contains(cpsnames1[i])) + { + var tljRecord = new fl_alimama_tlj_create_record() { cpsname = cpsnames1[i], date = DateTime.Now.ToString("yyyyMMdd"), number = 0 }; + tljCreateRecords.Add(session.Saveable(tljRecord).ExecuteReturnEntity()); + } + } + } + List<fl_alimama_tlj_create_record> tljs = null; + if (tljCreateRecords != null) + tljs = tljCreateRecords.Where(f => (f.date == DateTime.Now.ToString("yyyyMMdd") && f.number < 30) || f.date != DateTime.Now.ToString("yyyyMMdd")).ToList(); + + switch (Class1.Config.TljModel) + { + case TLJModel.新人首次查询时使用淘礼金: + { + var incomeResult = session.FindSingle<fl_statistics_record>(@"select * from fl_statistics_record where uid = @userid", new { userid = member.id }); + if (incomeResult == null) + return CreateTljUrl(ref api, tljs, item_id, perface); + } + break; + case TLJModel.首单付款前使用淘礼金: + { + if (member.bind_order == 0) + return CreateTljUrl(ref api, tljs, item_id, perface); + } + break; + case TLJModel.查询随机分配淘礼金: + { + var random = new Random(Guid.NewGuid().GetHashCode()); + var num = random.Next(1, 5000); + if ((1000 < num && num < 1250) || 10 < num && num < 260) + return CreateTljUrl(ref api, tljs, item_id, perface); + } + break; + } + } + catch (Exception ex) + { + + } + return string.Empty; + } + + private readonly object lock_tlj = new object(); + + /// <summary> + /// 创建淘礼金 + /// </summary> + /// <param name="api"></param> + /// <param name="item_id"></param> + /// <param name="image"></param> + /// <returns>返回淘礼金连接</returns> + private string CreateTljUrl(ref AlimamaApi api, List<fl_alimama_tlj_create_record> tljs, string item_id, double perface) + { + try + { + lock (lock_tlj) + { + var session = ApiClient.GetSession(); + + #region 寻找以前创建的并且现在有效的淘礼金 + var _tlj = session.FindTljByItemid(item_id); + if (_tlj != null) + { + var cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == _tlj.cpsname); + if (cps != null) + { + AlimamaApi _api = CpsClient.CreateAlimamaRequest(cps); + if (_api != null) + api = _api; + } + if (_tlj.number == 1) + session.Deleteable<fl_alimama_tlj_get_record>(_tlj).ExecuteCommand(); + else + { + _tlj.number--; + session.SaveOrUpdate(_tlj); + } + return _tlj.url; + } + #endregion + + if (!string.IsNullOrWhiteSpace(Class1.Config.TljItemIds)) + { + var itemids = Class1.Config.TljItemIds.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList(); + if (string.IsNullOrWhiteSpace(itemids.FirstOrDefault(f => f.Trim() == item_id))) + return string.Empty; + } + + if (tljs != null) + { + foreach (var item in tljs) + { + var cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == item.cpsname); + if (cps != null) + { + AlimamaApi _api = CpsClient.CreateAlimamaRequest(cps); + if (_api != null) + { + var tlj = session.FindTljInfos().FirstOrDefault(f => f.username == _api.Member.username); + if (tlj != null) + { + if (string.IsNullOrWhiteSpace(tlj.appkey) || string.IsNullOrWhiteSpace(tlj.appsecret) || string.IsNullOrWhiteSpace(tlj.adzone_pid)) + continue; + + var reg = Regex.Match(tlj.adzone_pid, @"mm_(?<cpsname>\d+)_(?<pid1>\d+)_(?<pid2>\d+)"); + if (!reg.Success) + continue; //throw new Exception($"淘宝推广位格式不正确"); + + var cpsname = reg.Groups["cpsname"].Value; + //var pid1 = reg.Groups["pid1"].Value; + var pid2 = reg.Groups["pid2"].Value; + + var now = DateTime.Now; + var send_end_time = now.AddHours(Class1.Config.TljExpireDate); + + var tljResult = _api.SendTaobao("taobao.tbk.dg.vegas.tlj.create", new { adzone_id = pid2, item_id = item_id, security_switch = "true", total_num = Class1.Config.TljCreateNum, name = Class1.Config.TljName, user_total_win_num_limit = Class1.Config.TljGetLimit, per_face = perface, send_start_time = now.ToString("yyyy-MM-dd HH:mm:ss"), send_end_time = send_end_time.ToString("yyyy-MM-dd HH:mm:ss") }, tlj.appkey, tlj.appsecret); + + if (tljResult != null && tljResult.ContainsKey("success")) + { + if (tljResult["success"].ToString().ToLower() == "false") + { + if (tljResult.ContainsKey("msg_info")) + { + var msg = tljResult["msg_info"].ToString(); + if (msg == "您创建的淘礼金商品数目已达上限") + session.ExcuteSQL("update fl_alimama_tlj_create_record set date = @date ,number = 30 where cpsname = @cpsname", new { date = now.ToString("yyyyMMdd"), cpsname = cpsname }); + //throw new Exception("该淘宝账号ID今日创建淘礼金次数已耗尽"); + } + //throw new Exception(tljResult.ContainsKey("msg_info") ? tljResult["msg_info"].ToString() : $"生成淘礼金失败,{HttpHelper.ObjectToJson(tljResult)}"); + continue; + } + + if (tljResult.ContainsKey("model")) + { + var model = tljResult["model"] as Dictionary<string, object>; + if (model.ContainsKey("send_url")) + { + var send_url = model["send_url"].ToString(); + + #region 统计次数 + session.AddTljCreateNum(cpsname); + #endregion + + #region 将创建的淘礼金保存在数据库中 + if (Class1.Config.TljCreateNum > 1) + { + session.SaveOrUpdate(new fl_alimama_tlj_get_record() { adzoneid = pid2, expiredate = send_end_time, itemid = item_id, number = Class1.Config.TljCreateNum - 1, url = send_url, cpsname = cpsname }); + } + #endregion + + api = _api; + return send_url; + } + } + } + } + } + } + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + } +} diff --git a/应用/TBRebate/Class1.cs b/应用/TBRebate/Class1.cs new file mode 100644 index 0000000..6ca1c7e --- /dev/null +++ b/应用/TBRebate/Class1.cs @@ -0,0 +1,841 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using TBRebate.Entitys; +using TBRebate.Properties; +using TBRebate.Uses; +using static Api.Framework.Cps.AlimamaApi; +using static TBRebate.Enums; + +namespace TBRebate +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.淘宝; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (session.TableExist<fl_plugin_tbrebate_tbtgw>()) + { + var tbtgws = session.Find<fl_plugin_tbrebate_tbtgw>("select * from fl_plugin_tbrebate_tbtgw").ToList(); + if (tbtgws != null) + { + foreach (var item in tbtgws) + { + //插入主推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_chief_name, //推广位名称 + adzone_pid = item.pid_chief, //推广位pid + adzone_pid_cps_name = item.pid_chief_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "chief" + }).ExecuteCommand(); + //插入副推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_deputy_name, //推广位名称 + adzone_pid = item.pid_deputy, //推广位pid + adzone_pid_cps_name = item.pid_deputy_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "deputy" + }).ExecuteCommand(); + } + } + session.DropTable<fl_plugin_tbrebate_tbtgw>(); + } + if (!session.TableExist<fl_plugin_tbrebate_ignoreids>()) + { + session.CreateTable<fl_plugin_tbrebate_ignoreids>(); + session.AddIndex<fl_plugin_tbrebate_ignoreids>("itemid");//增加索引. + session.AddIndex<fl_plugin_tbrebate_ignoreids>("losetime");//增加索引. + } + #endregion + + //创建配置文件 + Config = this.ReadConfig<Config>(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + SDK.WebRequestEvent += SDK_WebRequestEvent; + InitIgnoreidsCache(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_WebRequestEvent(object sender, WebRequestEvents e) + { + try + { + #region + if (e.Param.ContainsKey("method"))//方法名称 + { + var method = e.Param["method"].ToLower(); + switch (method) + { + case "tbitem": + { + var resultJson = string.Empty; + try + { + if (!e.Param.ContainsKey("ids")) throw new Exception("缺少参数ids"); + var ids = e.Param["ids"].ToString(); + if (!string.IsNullOrWhiteSpace(ids)) + { + var idList = ids.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Distinct().ToList(); + if (idList.Count != 0) + { + InitIgnoreidsCache(idList); + } + } + } + catch (Exception ex) + { + e.Send(ex.Message, 100); + return; + } + e.Send("请求成功", 200); + } + break; + } + } + #endregion + } + catch (Exception ex) + { + this.OnLog("淘宝返利web接收数据异常:" + ex.Message); + } + } + + public static List<fl_plugin_tbrebate_ignoreids> ignoreidsCache = new List<fl_plugin_tbrebate_ignoreids>(); + + private void InitIgnoreidsCache(List<string> idList = null) + { + var nowTime = HttpExtend.GetTimeStamp(DateTime.Now); + + var session = ApiClient.GetSession(); + var temps = new List<fl_plugin_tbrebate_ignoreids>(); + var ignoreids = session.Find<fl_plugin_tbrebate_ignoreids>("select * from fl_plugin_tbrebate_ignoreids"); + if (ignoreids != null && ignoreids.Count != 0) + { + temps = ignoreids.Where(f => f.losetime < nowTime).ToList(); + if (temps != null && temps.Count != 0) + session.Deleteable(temps).ExecuteCommand(); + temps = ignoreids.Where(f => f.losetime >= nowTime).ToList(); + } + if (idList != null) + { + foreach (var itemid in idList) + { + var temp = temps.FirstOrDefault(f => f.itemid == itemid); + if (temp == null) + session.Insertable(new fl_plugin_tbrebate_ignoreids() { itemid = itemid, losetime = HttpExtend.GetTimeStamp(DateTime.Now.AddDays(2)) }).ExecuteCommand(); + else + { + temp.losetime = HttpExtend.GetTimeStamp(DateTime.Now.AddDays(2)); + session.Updateable(temp).ExecuteCommand(); + } + } + } + ignoreidsCache = session.Find<fl_plugin_tbrebate_ignoreids>("select * from fl_plugin_tbrebate_ignoreids"); + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.ChatType == CpsType.阿里妈妈) + { + //this.OnLog("淘宝订单:" + HttpHelper.ObjectToJson(e)); + var session = ApiClient.GetSession(); + //订单信息 + var order_tb = e.Order as fl_order_alimama; + + if (order_tb == null) return; + + if (e.Member != null) + { + #region 订单变化通知消息 + var robot_info = session.FindRobotInfo(e.Member.robot_name.Trim(), e.Member.robot_type); + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject<ItemPoint>(order_tb.db_point) as ItemPoint; + #region 下单用户订单检测(防撸) + if (e.Customer == null) + { + var prevent_theft_cache = session.FindSingle<fl_prevent_theft_cache>("select * from fl_prevent_theft_cache where order_id = @order_id", new { order_id = order_tb.trade_id });//防止上级多次触发 + if (prevent_theft_cache == null) + { + var isHint = false; + if (!string.IsNullOrWhiteSpace(order_tb.seller_id) && e.Member.status != MemberType.白名单) + { + #region 同一店铺多次购买(同一商品) + if (Class1.Config.AShop_SameCommodity_Switch) + { + var frequency = session.Find<fl_order_alimama>("select * from fl_order_alimama where db_userid = @db_userid and num_iid = @num_iid", new { db_userid = order_tb.db_userid, num_iid = order_tb.num_iid }).Count;//获取同价店铺同一件商品购买的次数 + if (Class1.Config.AShop_SameCommodity_Number <= frequency) + { + if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_tb, e.Member, point), order_tb.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户购买同一商品{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_SameCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_tb.num_iid; + prevent_theft_cache.mall_id = order_tb.seller_id; + prevent_theft_cache.order_id = order_tb.trade_id; + prevent_theft_cache.cps_type = CpsType.阿里妈妈; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_SameCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户购买同一商品{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + + #region 同一店铺多次购买(不同商品) + if (!isHint && Class1.Config.AShop_DifferentCommodity_Switch) + { + var frequency = session.Find<fl_order_alimama>("select * from fl_order_alimama where db_userid = @db_userid and seller_id = @seller_id", new { db_userid = order_tb.db_userid, seller_id = order_tb.seller_id }).Count; + if (Class1.Config.AShop_DifferentCommodity_Number <= frequency) + { + if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_tb, e.Member, point), order_tb.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_DifferentCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_tb.num_iid; + prevent_theft_cache.mall_id = order_tb.seller_id; + prevent_theft_cache.order_id = order_tb.trade_id; + prevent_theft_cache.cps_type = CpsType.阿里妈妈; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_DifferentCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + } + + #region 收货时间验证时长 + if (!isHint && Class1.Config.ReceivingTimeCheck_Switch && order_tb.tk_status == (int)AlimamaOrderStatus.订单结算 && e.Member.status != MemberType.白名单) + { + if (order_tb.earning_time != DateTime.MinValue) + { + var timeLag = (int)Math.Floor((order_tb.earning_time - order_tb.create_time).TotalHours); + if (timeLag <= Class1.Config.ReceivingTimeCheck_Hour) + { + if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order_tb, e.Member, point), order_tb.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +拉黑原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + e.Cancel = true; + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.ReceivingTimeCheck_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order_tb.num_iid; + prevent_theft_cache.mall_id = order_tb.seller_id; + prevent_theft_cache.order_id = order_tb.trade_id; + prevent_theft_cache.cps_type = CpsType.阿里妈妈; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.ReceivingTimeCheck_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + //ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + return; + } + } + else if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 +———— +事件类型:订单检测 +微信账号:{robot_info.name} +微信昵称:{robot_info.nick} +客户账号:{e.Member.username} +客户昵称:{e.Member.usernick} +警告原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + } + } + } + } + #endregion + + } + } + #endregion + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + { + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + #region 淘礼金订单只提示 付款/结算 + var is_tlj = session.CheckIsTljOrder(order_tb.adzone_id); + #endregion + + if (!is_tlj) + mess = _GetOrderStateMess(order_tb.db_status, SettleType.未结算提示, order_tb, e.Member, point); + else + { + if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.TljPaymentTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.TljSettlementTip; + else//淘礼金其他订单状态不给用户提示 + return; + mess = new VariateReplace().CommonReplace(mess, order_tb, e.Member, point); + } + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order_tb.msg_groupid); + } + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order_tb.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_OneLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_tb.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_TwoLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_tb.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_ThreeLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order_tb.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_LeaderTip; + else if (order_tb.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order_tb.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order_tb.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order_tb, e.Member, point).Replace("[下级昵称]", e.Customer.realnick ?? "")); + } + #endregion + } + else + { + #region 多人查询通知消息 + var querys = session.Find<queryhist_temp>("select robot_name,type,userid from fl_query_hist where itemid=@itemid and adzoneid = @adzoneid and userid > 0 and crt_time>@time and is_multiple=@is_multiple group by userid,type,robot_name", new { itemid = order_tb.num_iid, adzoneid = order_tb.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss"), is_multiple = false }); + if (querys.Count > 0) + { + for (int i = 0; i < querys.Count; i++) + { + try + { + if (querys[i].type != CpsType.阿里妈妈) continue; + //未绑定的数量 + var unbound_count = int.Parse(session.FindTable($"select count(id) as num from fl_order_alimama where trade_parent_id = @trade_parent_id and db_userid != 0", new { trade_parent_id = order_tb.trade_parent_id }).Rows[0]["num"].ToString()); + if (unbound_count != 0) break;//已经被绑定直接停止 + + var queryhist_temp = querys[i]; + var userid = queryhist_temp.userid; + var robot_name = queryhist_temp.robot_name; + var robot_info = session.Find<fl_robot_info>("select * from fl_robot_info where name = @name", new { name = robot_name }).FirstOrDefault();//机器人类型应该是没有的,直接通过机器人name查询机器人信息 + if (robot_info != null) + { + Thread.Sleep(5000); + var wxbase = Chat.Framework.ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot_name); + if (wxbase != null /*&& wxbase.WeixinType == WeixinType.Grpc微信*/ && wxbase.Status == WxStatus.在线) + { + var member = session.FindMemberInfoById(userid); + if (member != null) + { + ApiClient.SendMessage(robot_info, member.username, Config.LotUserQueryBindTip.Replace("[商品标题]", order_tb.item_title)); + + //session.ExcuteSQL("update fl_query_hist set userid = @newuserid where itemid = @itemid and adzoneid = @adzoneid and robot_name = @robotname and userid = @userid", new { newuserid = (i - querys.Count + 1), itemid = order_tb.num_iid, adzoneid = order_tb.adzone_id, robotname = robot_name, userid = member.id }); + session.ExcuteSQL("update fl_query_hist set is_multiple = @is_multiple where itemid = @itemid and adzoneid = @adzoneid and robot_name = @robotname and userid = @userid", new { is_multiple = true, itemid = order_tb.num_iid, adzoneid = order_tb.adzone_id, robotname = robot_name, userid = member.id }); + } + } + } + } + catch (Exception) + { } + } + } + #endregion + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + //if (e.Message == "1") + //{ + // string url = ApiClient.SendWechatPay(new { robot_nick = e.RobotNick, robot_name = e.RobotName, username = e.Username, usernick = e.NickName }, "测试", 0.3, out var ispaid, out var appinfo); + + // Console.WriteLine(url); + //} + + //return; + + //var hook = sender as WXClientImpl_HOOK; + //var ss = hook.AutoAuthMiniAPPLogin("wxa918198f16869201"); + + //return; + + // var sss = @"<TimelineObject> + // <id><![CDATA[13817912067015979088]]></id> + // <username><![CDATA[wxid_fy2obibqhy5w22]]></username> + // <createTime><![CDATA[1647223480]]></createTime> + // <contentDescShowType>0</contentDescShowType> + // <contentDescScene>0</contentDescScene> + // <private><![CDATA[0]]></private> + // <contentDesc><![CDATA[润本高端货,低价贱卖!! + //润本?婴儿驱蚊喷雾2瓶,💰12.9 + + //德国进口MERCK原液!! + + //驱蚊 除螨,喷一下,防蚊5.7小时!]]></contentDesc> + // <contentattr><![CDATA[0]]></contentattr> + // <sourceUserName> + // </sourceUserName> + // <sourceNickName> + // </sourceNickName> + // <statisticsData> + // </statisticsData> + // <weappInfo> + // <appUserName> + // </appUserName> + // <pagePath> + // </pagePath> + // <version><![CDATA[0]]></version> + // <debugMode><![CDATA[0]]></debugMode> + // <shareActionId> + // </shareActionId> + // <isGame><![CDATA[0]]></isGame> + // <messageExtraData> + // </messageExtraData> + // <subType><![CDATA[0]]></subType> + // <preloadResources> + // </preloadResources> + // </weappInfo> + // <canvasInfoXml> + // </canvasInfoXml> + // <ContentObject> + // <contentStyle><![CDATA[1]]></contentStyle> + // <contentSubStyle><![CDATA[0]]></contentSubStyle> + // <title> + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // 1503486313201304704820[图片=C:\Users\Administrator\Desktop\秒单客-返利机器人\Cache\image\637828491427180612.jpg][图片=D:\其他\图片s\timg.jpg] + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + + // + // + // + // + // + // + // + // + // + // + //"; + + // var wx = sender as WXClientImpl_HOOK; + // wx.SendCircle(sss); + + // return; + + + //过滤表情xml和卡片xml + if ((e.Message.Contains(@" {e.Message} => " + stopWatch.Elapsed.TotalSeconds.ToString("0.0000")); + //返利消息判断 + if (flag) return; + + + } + catch (Exception ex) + { + this.OnLog($"淘宝返利插件异常.:{ex.Message} - {ex.StackTrace}"); + } + } + + /// + /// 订单状态 提示语替换 + /// + /// + /// + /// + public static string _GetOrderStateMess(SystemOrderStatus order, SettleType settle, params object[] objs) + { + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.订单维权中: + mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(settle == SettleType.未结算提示 ? Config.OrderSettlementTip : Config.OrderAlreadySettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Config.OrderFreezeTip, objs); + break; + case SystemOrderStatus.全额退款: + mess = new VariateReplace().CommonReplace(Config.OrderFrozen_AllTip, objs); + break; + case SystemOrderStatus.部分退款: + mess = new VariateReplace().CommonReplace(Config.OrderFrozen_PartTip, objs); + break; + } + return mess; + } + + } +} diff --git a/应用/TBRebate/Config.cs b/应用/TBRebate/Config.cs new file mode 100644 index 0000000..c98cb92 --- /dev/null +++ b/应用/TBRebate/Config.cs @@ -0,0 +1,1348 @@ +using Api.Framework.Enums; +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static TBRebate.Enums; + +namespace TBRebate +{ + [Config(Name = "插件-淘宝返利-配置")] + public class Config + { + #region 消费积分设置 + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("01.主推广位使用条件 - 购物积分"), DefaultValue(20), + Description(@"用户消费积分≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int Point { get; set; } + + /// + /// 消费积分设置 + /// + [ + Category("1)、基础设置"), DisplayName("02.主推广位使用条件 - 订单笔数"), DefaultValue(20), + Description(@"用户交易订单数≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int OrderNum { get; set; } + #endregion + + #region 搜索标题开关 + /// + /// 自定义搜索开关 + /// + [ + Category("2)、关键词搜索"), DisplayName(@"01.搜索功能"), DefaultValue(SwitchType.开启), Description(@"为开启时,关键词搜索功能才有效") + ] + public SwitchType SearchCustomSwitch { get; set; } + + /// + /// 关键词搜索指令 + /// + [ + Category("2)、关键词搜索"), DisplayName(@"02.搜索指令"), DefaultValue(@"^(有没有|有|找|下|查|买)\s?(?<关键词>[^吗嘛没\??]{2,})"), + Description(@"支持正则表达式,正则表达式关键词: <关键词> +如果关键字过长,将进行精准搜索 +如果自定义域名,请到主程序中 '系统设置' -> '自定义域名产品库' 设置") + ] + public string SearchPrefix { get; set; } + + /// + /// 关键词搜索成功提示语 + /// + [ + Category("2)、关键词搜索"), DisplayName(@"03.结果提示"), DefaultValue(@"一一一一搜 索 消 息一一一一 +找到【[关键词]】相关宝贝! + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[关键词]、[购买地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string PreciseSearchSuccessTip { get; set; } + + /// + /// 短网址 + /// + [ + Category("2)、关键词搜索"), DisplayName("04.关键词搜索短网址"), DefaultValue(DwzType.快站短网址), + Description("缩短购买地址网址") + ] + public DwzType SearchDwzType { get; set; } + + #endregion + + #region 提示语 + /// + /// 智能标题识别开关 + /// + [ + Category("3)、商品查询"), DisplayName("01.智能标题识别"), DefaultValue(SwitchType.开启), Description(@"智能标题识别功能,开启可以通过标题搜索宝贝") + ] + public SwitchType SearchTitleSwitch { get; set; } + /// + /// 宝贝二维码识别功能 + /// + [ + Category("3)、商品查询"), DisplayName("02.智能图片识别"), DefaultValue(SwitchType.开启), Description("智能图片识别功能,开启可以通过宝贝中的二维码搜索宝贝") + ] + public SwitchType QRCodeSearchSwitch { get; set; } + + /// + /// 无券模式 + /// + [ + Category("3)、商品查询"), DisplayName(@"03.无券模式"), DefaultValue(SwitchType.关闭), Description(@"为开启时,有券的商品将以无券的形式返回") + ] + public SwitchType NoCouponModeSwitch { get; set; } + + /// + /// 正在搜索宝贝提示语 + /// + [ + Category("3)、商品查询"), DisplayName("04.正在搜索宝贝"), DefaultValue(@"优惠信息查询中....."), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchingTip { get; set; } + + /// + /// 搜索宝贝无佣金 + /// + [ + Category("3)、商品查询"), DisplayName("05.无佣金时提示"), DefaultValue(@"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[关键词]、链接无返利变量:[商品标题]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchNoCommissionTip { get; set; } + + /// + /// 无佣金标题搜索 + /// + [ + Category("3)、商品查询"), DisplayName(@"06.无佣金标题搜索产品库"), DefaultValue(SwitchType.关闭), Description(@"为开启时,商品无佣金情况下通过商品标题搜索产品库") + ] + public SwitchType SearchTitleSwitch_NoCommission { get; set; } + + /// + /// 搜索宝贝无佣金 + /// + [ + Category("3)、商品查询"), DisplayName("07.无佣金正在标题搜索产品库"), DefaultValue(@"您分享的商品活动已经结束 + +相似的商品可以在产品库中查询:[购买地址]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[购买地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchTitle_NoCommissionTip { get; set; } + + /// + /// 无优惠券时提示 + /// + [ + Category("3)、商品查询"), DisplayName("08.无优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址复制优惠口令: +[购买中间页地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[店铺名称]、[返利积分]、[购买地址]、[购买中间页地址]、[购买淘口令]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithoutCouponTip { get; set; } + + /// + /// 有优惠券提示语 + /// + [ + Category("3)、商品查询"), DisplayName("09.有优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +打开网址复制优惠口令: +[购买中间页地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[购买中间页地址]、[购买淘口令]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithCouponTip { get; set; } + + /// + /// 无优惠券时提示(QQ) + /// + [ + Category("3)、商品查询"), DisplayName("10.无优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""无优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[月销量]、[店铺名称]、[返利积分]、[购买地址]、[购买中间页地址]、[购买淘口令]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithoutCouponTip { get; set; } + + /// + /// 有优惠券提示语(QQ) + /// + [ + Category("3)、商品查询"), DisplayName("11.有优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""有优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[月销量]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[购买中间页地址]、[购买淘口令]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithCouponTip { get; set; } + + /// + /// 自定义淘口令信息开关 + /// + [ + Category("3)、商品查询"), DisplayName(@"12.店铺返利开关"), DefaultValue(SwitchType.开启), Description(@"为开启时,查询是否有店铺推广") + ] + public SwitchType ShopAdSwitch { get; set; } = SwitchType.开启; + + /// + /// 店铺返提示 + /// + [ + Category("3)、商品查询"), DisplayName("13.店铺返利提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【返利金额】随机(付款后知晓) + +已经申请到该店铺所有商品补贴,请仔细查看操作方法! + +[购买中间页地址] + +━┉┉┉┉∞┉┉┉┉━ +操作方法: +①通过网址,复制口令去淘宝 +②找到需要购买的商品 +③付款成功,复制订单号给我"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品主图]、[图片地址]、[购买地址]、[购买中间页地址]、[购买淘口令]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ShopAdSuccessTip { get; set; } + + /// + /// 店铺返提示 + /// + [ + Category("3)、商品查询"), DisplayName("14.店铺返利提示(QQ)"), DefaultValue(@""), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[购买中间页地址]、[购买淘口令]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQShopAdSuccessTip { get; set; } = string.Empty; + + /// + /// 强返提示 + /// + [ + Category("3)、商品查询"), DisplayName("15.天猫精选产品强制返利提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【返利金额】随机(付款后知晓) + +由于此商品我们申请独家补贴,但要多一个步骤,请仔细查看操作方法! +[购买中间页地址] +━┉┉┉┉∞┉┉┉┉━ +操作方法: +①通过网址,复制口令去淘宝 +②回到微信,复制标题回淘宝 +③粘贴标题,再继续搜索购买 +④付款成功,复制订单号给我 +[分段] +[商品标题]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[购买中间页地址]、[购买淘口令]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CoerceSearchSuccessTip { get; set; } + + /// + /// 强反中间页 + /// + [ + Category("3)、商品查询"), DisplayName("16.天猫精选强制返利中间页"), DefaultValue(@""), + Description(@"强制返利中间页将会使用这个域名 +例如:http://xxxxxx.xxx?xxx=[淘口令] +支持变量:[淘口令]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string CoercePageUrl { get; set; } + + #endregion + + #region 淘口令设置 + + /// + /// 自定义淘口令信息开关 + /// + [ + Category("4)、淘口令设置"), DisplayName(@"01.自定义淘口令信息开关"), DefaultValue(SwitchType.开启), Description(@"为开启时,图片和标题使用自定义设置") + ] + public SwitchType TKLCustomSwitch { get; set; } + + /// + /// 淘口令显示图 + /// + [ + Category("4)、淘口令设置"), DisplayName("02.淘口令显示图"), DefaultValue(@""), + Description(@"手机淘宝/天猫识别淘口令后出现的弹窗图. +无设置将使用商品首图 +注:支持网络图"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string TKLImageUrl { get; set; } + + private string _TKLTitle; + /// + /// 淘口令标题 + /// + [ +Category("4)、淘口令设置"), DisplayName("03.淘口令标题"), DefaultValue(@"赶紧抢购哦,内部优惠数量有限!!"), +Description(@"手机淘宝/天猫识别淘口令后出现的弹窗图. +无设置将使用默认标题"), +Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string TKLTitle + { + get { return _TKLTitle; } + set + { + if (value.Length < 5) + throw new Exception("标题长度需要大于等于5"); + else + _TKLTitle = value; + } + } + + #endregion + + #region 订单通知 + + /// + /// 用户订单变化通知 + /// + [ + Category("5)、订单通知"), DisplayName(@"01.用户订单变化通知"), DefaultValue(SwitchType.开启), Description(@"开启用户订单变化通知功能时,用户的订单发生变化时,将通知用户订单的情况") + ] + public SwitchType UserOrderChangeSwitch { get; set; } + /// + /// 代理获得提成通知 + /// + [ + Category("5)、订单通知"), DisplayName(@"02.代理获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启代理获得提成通知功能时,用户的订单发生变化时,将通知代理获得提成信息") + ] + public SwitchType AgentReceivedCommissionSwitch { get; set; } + /// + /// 群负责人获得提成通知 + /// + [ + Category("5)、订单通知"), DisplayName(@"03.群负责人获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启群负责人获得提成通知功能时,用户的订单发生变化时,将通知群负责人获得提成信息") + ] + public SwitchType PrincipalReceivedCommissionSwitch { get; set; } + + /// + /// 绑定订单号非本人提示语 + /// + [Category("5)、订单通知"), DisplayName("04.已被其他用户绑定"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OccupyOrderErrorTip { get; set; } + + /// + /// 订单号未找到提示语 + /// + [Category("5)、订单通知"), DisplayName("05.未找到订单号"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string NotFoundOrderErrorTip { get; set; } + + /// + /// 重复绑定订单号 + /// + [Category("5)、订单通知"), DisplayName("06.重复绑定订单号"), DefaultValue(@"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRepetBindTip { get; set; } + + /// + /// 订单付款提示语 + /// + [Category("5)、订单通知"), DisplayName("07.订单付款"), DefaultValue(@"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentTip { get; set; } + + /// + /// 订单付款通知一级提示语 + /// + [Category("5)、订单通知"), DisplayName("08.订单付款通知一级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_OneLevelTip { get; set; } + + /// + /// 订单付款通知二级 + /// + [Category("5)、订单通知"), DisplayName("09.订单付款通知二级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_TwoLevelTip { get; set; } + + /// + /// 订单付款通知三级 + /// + [Category("5)、订单通知"), DisplayName("10.订单付款通知三级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_ThreeLevelTip { get; set; } + + /// + /// 订单付款通知群负责人 + /// + [Category("5)、订单通知"), DisplayName("11.订单付款通知群负责人"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_LeaderTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("5)、订单通知"), DisplayName("12.订单冻结"), DefaultValue(@"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFreezeTip { get; set; } + + /// + /// 订单已经结算提示语 + /// + [Category("5)、订单通知"), DisplayName("13.订单已经结算"), DefaultValue(@"一一一一订 单 已 经 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【订单状态】该订单已经完成结算,请勿重复提交 +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderAlreadySettlementTip { get; set; } + + /// + /// 订单结算提示语 + /// + [Category("5)、订单通知"), DisplayName("14.订单结算"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlementTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("5)、订单通知"), DisplayName("15.订单结算 - 全额退款"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【维权金额】[维权金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"), + Description(@"订单维权成功提示,维权类型为全额退款 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[维权金额]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFrozen_AllTip { get; set; } + + /// + /// 订单冻结提示语 + /// + [Category("5)、订单通知"), DisplayName("16.订单结算 - 部分退款"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【原始返利积分】[原始返利积分] [积分名称] +【维权返利积分】[维权返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,部分退款,返利将相应减少 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"订单维权成功提示,维权类型为部分退款 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[原始返利积分]、[维权返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFrozen_PartTip { get; set; } + + /// + /// 一级代理获得提成 + /// + [Category("5)、订单通知"), DisplayName("17.一级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_OneLevelTip { get; set; } + + /// + /// 二级代理获得提成 + /// + [Category("5)、订单通知"), DisplayName("18.二级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_TwoLevelTip { get; set; } + + /// + /// 三级代理获得提成 + /// + [Category("5)、订单通知"), DisplayName("19.三级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_ThreeLevelTip { get; set; } + + /// + /// 群负责人获得提成 + /// + [Category("5)、订单通知"), DisplayName("20.群负责人获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_LeaderTip { get; set; } + + /// + /// 订单退款提示语 + /// + [Category("5)、订单通知"), DisplayName("21.订单申请维权"), DefaultValue(@"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"用户申请退款通知改提示 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRefundTip { get; set; } + + /// + /// 客户维权一级代理 + /// + [Category("5)、订单通知"), DisplayName("22.客户维权一级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_OneLevelTip { get; set; } + + /// + /// 客户维权二级代理 + /// + [Category("5)、订单通知"), DisplayName("23.客户维权二级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_TwoLevelTip { get; set; } + + /// + /// 客户维权三级代理 + /// + [Category("5)、订单通知"), DisplayName("24.客户维权三级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_ThreeLevelTip { get; set; } + + /// + /// 客户维权群负责人 + /// + [Category("5)、订单通知"), DisplayName("25.客户维权群负责人"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_LeaderTip { get; set; } + + /// + /// 订单失效提示语 + /// + [Category("5)、订单通知"), DisplayName("26.订单失效"), DefaultValue(@"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[子订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFailureTip { get; set; } + + + /// + /// 订单失效通知一级提示语 + /// + [Category("5)、订单通知"), DisplayName("27.订单失效通知一级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_OneLevelTip { get; set; } + + /// + /// 订单失效通知二级 + /// + [Category("5)、订单通知"), DisplayName("28.订单失效通知二级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_TwoLevelTip { get; set; } + + /// + /// 订单失效通知三级 + /// + [Category("5)、订单通知"), DisplayName("29.订单失效通知三级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_ThreeLevelTip { get; set; } + + /// + /// 订单失效通知群负责人 + /// + [Category("5)、订单通知"), DisplayName("30.订单失效通知群负责人"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_LeaderTip { get; set; } + + + // + /// 宝贝多人查询提示绑定 + /// + [Category("5)、订单通知"), DisplayName("31.宝贝多人查询提示绑定"), DefaultValue(@"一一一一绑 定 提 示一一一一 +【商品标题】[商品标题] +该商品被多人查询系统无法匹配是谁下单,请亲手动到淘宝复制订单号给我手动绑定该订单"), + Description(@"多人查询同一个宝贝,导致无法自动绑定.则将推送该信息给查询过该宝贝的客户 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string LotUserQueryBindTip { get; set; } + + #endregion + + #region 查询限制设置 + /// + /// 店铺ID限制提示 + /// + [Category("6)、限制通知"), DisplayName("01.店铺ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[店铺ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SellerIDRestrictTip { get; set; } + + /// + /// 商品ID限制提示 + /// + [Category("6)、限制通知"), DisplayName("02.商品ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ItemIDRestrictTip { get; set; } + + /// + /// 拉黑提示 + /// + [Category("6)、限制通知"), DisplayName("03.用户被拉黑"), DefaultValue(@"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string Blocked_RestrictTip { get; set; } + + ///// + ///// 无佣金标题搜索 + ///// + //[ + // Category("7)、比价模式"), DisplayName(@"01.查询返佣模式"), DefaultValue(ComparisonType.开启比价接口), Description(@"为开启时,查询的商品为比价佣金;关闭时使用最高佣金") + //] + //public ComparisonType ComparisonSwitch { get; set; } + + [ + Category("7)、比价模式"), DisplayName(@"01.查询返佣模式"), DefaultValue(QueryComparisonType.查询使用比价佣金), Description(@"查询使用实时佣金:查询时自动判定比价/正常订单,显示实际佣金; +查询使用比价佣金:查询时所有订单以比价佣金显示用户所得佣金; +查询使用正常佣金:查询时所有订单以正常佣金显示用户所得佣金;") + ] + public QueryComparisonType QueryComparisonSwitch { get; set; } + + private int _ComparisonFeeRate; + + [ + Category("7)、比价模式"), DisplayName(@"02.查询使用比价佣金时预扣除比例(单位%)"), DefaultValue(0), Description(@"该设置只针对查询返佣模式中得(查询使用比价佣金)有效,查询时所有商品以比价佣金显示用户所得佣金,下单成功后为正常订单,那么将该订单扣除预扣除的比例后再计算用户所得佣金 +比如正常订单总佣金为10块钱,扣除预扣除比例(例:10%),则按9元来计算用户所得") + ] + public int ComparisonFeeRate + { + get { return _ComparisonFeeRate; } + set + { + _ComparisonFeeRate = value < 0 ? 0 : value; + } + } + + #endregion + + #region 防撸设置 + /// + /// 同一店铺多次购买(同一商品)开关 + /// + [Browsable(false)] + public bool AShop_SameCommodity_Switch { get; set; } + + /// + /// 同一店铺多次购买(同一商品)数量 + /// + [Browsable(false)] + public int AShop_SameCommodity_Number { get; set; } + + /// + /// 同一店铺多次购买(同一商品)处理方式 + /// + [Browsable(false)] + public OperateType AShop_SameCommodity_OperateType { get; set; } + + /// + /// 同一店铺多次购买(同一商品)置顶 + /// + [Browsable(false)] + public bool AShop_SameCommodity_UserTop { get; set; } + + /// + /// 同一店铺多次购买(不同商品)开关 + /// + [Browsable(false)] + public bool AShop_DifferentCommodity_Switch { get; set; } + + /// + /// 同一店铺多次购买(不同商品)数量 + /// + [Browsable(false)] + public int AShop_DifferentCommodity_Number { get; set; } + + /// + /// 同一店铺多次购买(不同商品)置顶 + /// + [Browsable(false)] + public bool AShop_DifferentCommodity_UserTop { get; set; } + + /// + /// 同一店铺多次购买(不同商品)处理方式 + /// + [Browsable(false)] + public OperateType AShop_DifferentCommodity_OperateType { get; set; } + + /// + /// 收货时间验证开关 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_Switch { get; set; } + + /// + /// 收货时间验证时长(小时) + /// + [Browsable(false)] + public int ReceivingTimeCheck_Hour { get; set; } + + /// + /// 收货时间验证处理方式 + /// + [Browsable(false)] + public OperateType ReceivingTimeCheck_OperateType { get; set; } + + /// + /// 收货时间验证置顶 + /// + [Browsable(false)] + public bool ReceivingTimeCheck_UserTop { get; set; } + + /// + /// 收货时间验证订单冻结时间 + /// + [Browsable(false)] + public int ReceivingTimeCheck_FreezeTime { get; set; } + + /// + /// 屏蔽的商品ID集合 + /// + [Browsable(false)] + public List ItemIDRestrictList { get; set; } + + /// + /// 屏蔽的卖家ID集合 + /// + [Browsable(false)] + public List SellerIDRestrictlist { get; set; } + + ///// + ///// 钉钉Api + ///// + //[Browsable(false)] + //public string Abnormal_DingDingApi { get; set; } + + ///// + ///// 钉钉token值 + ///// + //[Browsable(false)] + //public string Abnormal_DingDingApiToken { get; set; } + + [Browsable(false)] + public string notice_robotname { get; set; } + + #endregion + + #region 淘礼金 + + /// + /// 开启关闭 + /// + [Browsable(false)] + public bool TljOnOff { get; set; } + + /// + /// 淘礼金模式 + /// + [Browsable(false)] + public TLJModel TljModel { get; set; } + + /// + /// 淘礼金名称 + /// + [Browsable(false)] + public string TljName { get; set; } + + /// + /// 允许生成淘礼金商品id + /// + [Browsable(false)] + public string TljItemIds { get; set; } + + /// + /// 淘礼金创建数量 + /// + [Browsable(false)] + public int TljCreateNum { get; set; } + + /// + /// 淘礼金领取限制 + /// + [Browsable(false)] + public int TljGetLimit { get; set; } + + /// + /// 淘礼金有效期 + /// + [Browsable(false)] + public int TljExpireDate { get; set; } + + /// + /// 淘礼金查询成功 + /// + [Browsable(false)] + public string TljSearchSuccess { get; set; } + + /// + /// 淘礼金付款成功 + /// + [Browsable(false)] + public string TljPaymentTip { get; set; } + + /// + /// 淘礼金结算 + /// + [Browsable(false)] + public string TljSettlementTip { get; set; } + + #endregion + + public Config() + { + this.QueryComparisonSwitch = QueryComparisonType.查询使用比价佣金; + this.ComparisonFeeRate = 0; + TljItemIds = string.Empty; + TljCreateNum = 1; + TljGetLimit = 1; + TljExpireDate = 24; + + TljSearchSuccess = @"一一一一淘 礼 金 返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【淘礼金】[淘礼金金额] [积分名称] +【为您节约】[共节省]元 + +打开网址复制优惠口令: +[购买中间页地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"; + TljPaymentTip = @"一一一一淘 礼 金 绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + TljSettlementTip = @"一一一一淘 礼 金 订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + + SearchDwzType = DwzType.快站短网址; + + TljOnOff = false; + TljModel = TLJModel.新人首次查询时使用淘礼金; + TljName = "淘礼金补贴"; + + this.SellerIDRestrictTip = @"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"; + this.ItemIDRestrictTip = @"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"; + this.Blocked_RestrictTip = @"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"; + + this.AShop_SameCommodity_Switch = false; + this.AShop_SameCommodity_Number = 10; + this.AShop_SameCommodity_OperateType = OperateType.通知钉钉群; + this.AShop_SameCommodity_UserTop = false; + this.AShop_DifferentCommodity_Switch = false; + this.AShop_DifferentCommodity_Number = 10; + this.AShop_DifferentCommodity_UserTop = false; + this.AShop_DifferentCommodity_OperateType = OperateType.通知钉钉群; + this.ReceivingTimeCheck_Switch = false; + this.ReceivingTimeCheck_Hour = 24; + this.ReceivingTimeCheck_OperateType = OperateType.订单冻结; + this.ReceivingTimeCheck_FreezeTime = 24; + this.ReceivingTimeCheck_UserTop = false; + this.notice_robotname = string.Empty; + + this.ItemIDRestrictList = new List(); + this.SellerIDRestrictlist = new List(); + + this.TKLTitle = "赶紧抢购哦,内部优惠数量有限!!"; + this.TKLCustomSwitch = SwitchType.开启; + + this.TKLImageUrl = string.Empty; + this.CoercePageUrl = string.Empty; + this.Point = 20; + this.OrderNum = 20; + this.NoCouponModeSwitch = SwitchType.关闭; + this.SearchTitleSwitch = SwitchType.开启; + this.QRCodeSearchSwitch = SwitchType.开启; + this.SearchTitleSwitch_NoCommission = SwitchType.关闭; + this.SearchPrefix = @"^(有没有|有|找|下|查|买)\s?(?<关键词>[^吗嘛没\??]{2,})"; + this.SearchCustomSwitch = SwitchType.开启; + this.UserOrderChangeSwitch = SwitchType.开启; + this.PrincipalReceivedCommissionSwitch = SwitchType.关闭; + this.AgentReceivedCommissionSwitch = SwitchType.关闭; + this.QQSearchSuccessWithoutCouponTip = string.Empty; + this.QQSearchSuccessWithCouponTip = string.Empty; + this.SearchTitle_NoCommissionTip = @"您分享的商品活动已经结束 + +相似的商品可以在产品库中查询:[购买地址]"; + this.PreciseSearchSuccessTip = @"一一一一搜 索 消 息一一一一 +找到【[关键词]】相关宝贝! + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"; + this.SearchingTip = @"优惠信息查询中....."; + this.SearchSuccessWithCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +打开网址复制优惠口令: +[购买中间页地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"; + this.SearchSuccessWithoutCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址复制优惠口令: +[购买中间页地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"; + this.ShopAdSuccessTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【返利金额】随机(付款后知晓) + +已经申请到该店铺所有商品补贴,请仔细查看操作方法! + +[购买中间页地址] + +━┉┉┉┉∞┉┉┉┉━ +操作方法: +①通过网址,复制口令去淘宝 +②找到需要购买的商品 +③付款成功,复制订单号给我"; + + this.CoerceSearchSuccessTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【返利金额】随机(付款后知晓) + +由于此商品我们申请独家补贴,但要多一个步骤,请仔细查看操作方法! +[购买中间页地址] +━┉┉┉┉∞┉┉┉┉━ +操作方法: +①通过网址,复制口令去淘宝 +②回到微信,复制标题回淘宝 +③粘贴标题,再继续搜索购买 +④付款成功,复制订单号给我 +[分段] +[商品标题]"; + this.SearchNoCommissionTip = @"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"; + this.OrderRepetBindTip = @"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentTip = @"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentInform_OneLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_TwoLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_ThreeLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_LeaderTip = @"一一一一下 级 付 款一一一一 +【下级昵称】 [下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderFailureTip = @"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderCountermandInform_OneLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_TwoLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_ThreeLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_LeaderTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderRefundTip = @"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderFreezeTip = @"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"; + this.OrderAlreadySettlementTip = @"一一一一订 单 已 经 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【订单状态】该订单已经完成结算,请勿重复提交 +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlementTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OccupyOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"; + this.NotFoundOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"; + this.OrderFrozen_AllTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【维权金额】[维权金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"; + this.OrderFrozen_PartTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【子订单号】[子订单号] +【付款金额】[付款金额] 元 +【原始返利积分】[原始返利积分] [积分名称] +【维权返利积分】[维权返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,部分退款,返利将相应减少 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_OneLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_TwoLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_ThreeLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_LeaderTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_OneLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_TwoLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_ThreeLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_LeaderTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.LotUserQueryBindTip = @"一一一一绑 定 提 示一一一一 +【商品标题】[商品标题] +该商品被多人查询系统无法匹配是谁下单,请亲手动到淘宝复制订单号给我手动绑定该订单"; + } + + } +} diff --git a/应用/TBRebate/Entitys/cache_bind_orderid_temp.cs b/应用/TBRebate/Entitys/cache_bind_orderid_temp.cs new file mode 100644 index 0000000..4c795e7 --- /dev/null +++ b/应用/TBRebate/Entitys/cache_bind_orderid_temp.cs @@ -0,0 +1,32 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBRebate.Entitys +{ + public class cache_bind_orderid_temp + { + + + public string orderId { get; set; } + + public int db_userid { get; set; } + + public string groupid { get; set; } + + public string db_robotname { get; set; } + + public ChatType db_robottype { get; set; } + + public DateTime bind_time { get; set; } + + public cache_bind_orderid_temp() + { + this.bind_time = DateTime.Now; + } + + } +} diff --git a/应用/TBRebate/Entitys/fl_plugin_tbrebate_ignoreids.cs b/应用/TBRebate/Entitys/fl_plugin_tbrebate_ignoreids.cs new file mode 100644 index 0000000..7db3d67 --- /dev/null +++ b/应用/TBRebate/Entitys/fl_plugin_tbrebate_ignoreids.cs @@ -0,0 +1,21 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBRebate.Entitys +{ + public class fl_plugin_tbrebate_ignoreids : base_model + { + /// + /// 商品id + /// + public string itemid { get; set; } + /// + /// 失效时间 + /// + public long losetime { get; set; } + } +} diff --git a/应用/TBRebate/Entitys/fl_plugin_tbrebate_tbtgw.cs b/应用/TBRebate/Entitys/fl_plugin_tbrebate_tbtgw.cs new file mode 100644 index 0000000..66c21c7 --- /dev/null +++ b/应用/TBRebate/Entitys/fl_plugin_tbrebate_tbtgw.cs @@ -0,0 +1,48 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBRebate.Entitys +{ + /// + /// 平台推广位设置类 (数据库表) + /// + public class fl_plugin_tbrebate_tbtgw : base_model + { + /// + /// 左连接主表 fl_robot_info 的主键 + /// + public int robot_id { get; set; } + /// + /// 主推广位CPS名称 + /// + public string pid_chief_cps_name { get; set; } + /// + /// 主推广位id + /// + public string pid_chief { get; set; } + /// + /// 主推广位昵称 + /// + public string pid_chief_name { get; set; } + /// + /// 副推广位CPS名称 + /// + public string pid_deputy_cps_name { get; set; } + /// + /// 副推广位id + /// + public string pid_deputy { get; set; } + /// + /// 副推广位名称 + /// + public string pid_deputy_name { get; set; } + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } +} diff --git a/应用/TBRebate/Entitys/queryhist_temp.cs b/应用/TBRebate/Entitys/queryhist_temp.cs new file mode 100644 index 0000000..f9c5cdd --- /dev/null +++ b/应用/TBRebate/Entitys/queryhist_temp.cs @@ -0,0 +1,16 @@ +using Api.Framework.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBRebate.Entitys +{ + public class queryhist_temp + { + public string robot_name { get; set; } + public CpsType type { get; set; } + public int userid { get; set; } + } +} diff --git a/应用/TBRebate/Entitys/tbinfo_temp.cs b/应用/TBRebate/Entitys/tbinfo_temp.cs new file mode 100644 index 0000000..9a2fa84 --- /dev/null +++ b/应用/TBRebate/Entitys/tbinfo_temp.cs @@ -0,0 +1,120 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBRebate.Entitys +{ + /// + /// 临时的表 (用于数据显示) + /// + public class tbinfo_temp + { + /// + /// id + /// + public long ID { get; set; } + /// + /// 平台类型 + /// + public ChatType chattype { get; set; } + /// + /// 用户账号 + /// + public string name { get; set; } + + /// + /// [昵称] + /// + public string nick { get; set; } + + /// + /// 主推广位是否是组推广位 + /// + public bool is_chief_group { get; set; } + + /// + /// 主推广位cps名称 + /// + private string _pid_chief_cps_name { get; set; } + public string pid_chief_cps_name + { + get { return _pid_chief_cps_name; } + set { _pid_chief_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_chief; + /// + /// 主推广位id + /// + public string pid_chief + { + get { return _pid_chief; } + set { _pid_chief = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// + /// 主推广位昵称 + /// + private string _pid_chief_name; + + public string pid_chief_name + { + get { return _pid_chief_name; } + set { _pid_chief_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 主推广位是否是组推广位 + /// + public bool is_deputy_group { get; set; } + /// + /// 副推广位cps名称 + /// + private string _pid_deputy_cps_name { get; set; } + public string pid_deputy_cps_name + { + get { return _pid_deputy_cps_name; } + set { _pid_deputy_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位id + /// + private string _pid_deputy; + + public string pid_deputy + { + get { return _pid_deputy; } + set { _pid_deputy = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// + /// 副推广位名称 + /// + private string _pid_deputy_name; + + public string pid_deputy_name + { + get { return _pid_deputy_name; } + set { _pid_deputy_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + public string adzone_activity_name { get; set; } + + /// + /// 推广位 + /// + public string adzone_activity_pid { get; set; } + + + public string adzone_activity_pid_cps_name { get; set; } + + + /// + /// 是否禁用 + /// + public bool onoff { get; set; } + } +} diff --git a/应用/TBRebate/Enums.cs b/应用/TBRebate/Enums.cs new file mode 100644 index 0000000..55d0732 --- /dev/null +++ b/应用/TBRebate/Enums.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBRebate +{ + public class Enums + { + /// + /// 结账提示类型 + /// + public enum SettleType + { + 已结算提示 = 0, + 未结算提示 = 1 + } + + ///// + ///// 比价模式 + ///// + //public enum ComparisonType + //{ + // 开启比价接口 = 0, + // 关闭比价接口 = 1 + //} + + /// + /// 比价模式 + /// + public enum QueryComparisonType + { + 查询使用实时佣金 = 0, + 查询使用比价佣金 = 1, + 查询使用正常佣金 = 2 + } + } +} diff --git a/应用/TBRebate/MainForm.Designer.cs b/应用/TBRebate/MainForm.Designer.cs new file mode 100644 index 0000000..b4c737e --- /dev/null +++ b/应用/TBRebate/MainForm.Designer.cs @@ -0,0 +1,1431 @@ +namespace TBRebate +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(); + this.删除选中淘宝推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl19 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox4 = new System.Windows.Forms.ComboBox(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit6 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown4 = new System.Windows.Forms.NumericUpDown(); + this.comboBox3 = new System.Windows.Forms.ComboBox(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl32 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl31 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabControl2 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage5 = new DevExpress.XtraTab.XtraTabPage(); + this.hyperlinkLabelControl3_7 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.hyperlinkLabelControl3_6 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.labelControl13 = new DevExpress.XtraEditors.LabelControl(); + this.hyperlinkLabelControl3_5 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.labelControl14 = new DevExpress.XtraEditors.LabelControl(); + this.hyperlinkLabelControl3_4 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.hyperlinkLabelControl1_6 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.memoEdit2 = new DevExpress.XtraEditors.MemoEdit(); + this.hyperlinkLabelControl1_7 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.memoEdit3 = new DevExpress.XtraEditors.MemoEdit(); + this.hyperlinkLabelControl2_4 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl1_1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl3_3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl1_2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl1_5 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl2_1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl2_3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl1_3 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl3_2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl3_1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl1_4 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl2_2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.xtraTabPage6 = new DevExpress.XtraTab.XtraTabPage(); + this.labelControl18 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl17 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl16 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown7 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown5 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown6 = new System.Windows.Forms.NumericUpDown(); + this.labelControl62 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl61 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl60 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit4 = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl15 = new DevExpress.XtraEditors.LabelControl(); + this.bck_tlj_onoff = new UI.Framework.Controls.ButtonCheck(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit41 = new DevExpress.XtraEditors.TextEdit(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl59 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.xtraTabPage3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl2)).BeginInit(); + this.xtraTabControl2.SuspendLayout(); + this.xtraTabPage5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).BeginInit(); + this.xtraTabPage6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown7)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown5)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown6)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit41.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(991, 577); + this.xtraTabControl1.TabIndex = 7; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3, + this.xtraTabPage4}); + this.xtraTabControl1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.xtraTabControl1_KeyDown); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.simpleButton1); + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage1.Text = " 设 置 推 广 位 "; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(760, 514); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(205, 29); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "检测淘宝发单推广位重复项"; + this.simpleButton1.Visible = false; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(224, 189); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 7; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 514); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(989, 37); + this.pageControl1.TabIndex = 5; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(989, 508); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中淘宝推广位ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 26); + // + // 删除选中淘宝推广位ToolStripMenuItem + // + this.删除选中淘宝推广位ToolStripMenuItem.Name = "删除选中淘宝推广位ToolStripMenuItem"; + this.删除选中淘宝推广位ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除选中淘宝推广位ToolStripMenuItem.Text = "删除选中强返推广位"; + this.删除选中淘宝推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除选中淘宝推广位ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn13, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "平台类型"; + this.gridColumn1.FieldName = "chattype"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 110; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 164; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 138; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "主推广位"; + this.gridColumn5.FieldName = "pid_chief_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 148; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "副推广位"; + this.gridColumn7.FieldName = "pid_deputy_name"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 130; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn13.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn13.AppearanceCell.Options.UseFont = true; + this.gridColumn13.AppearanceCell.Options.UseForeColor = true; + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn13.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "强返推广位"; + this.gridColumn13.FieldName = "adzone_activity_name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 6; + this.gridColumn13.Width = 113; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "禁止使用"; + this.gridColumn9.FieldName = "onoff"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 7; + this.gridColumn9.Width = 109; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(989, 551); + this.settingControl1.TabIndex = 0; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupBox1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage3.Text = " 防 撸 设 置 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.labelControl19); + this.groupBox1.Controls.Add(this.comboBox4); + this.groupBox1.Controls.Add(this.labelControl20); + this.groupBox1.Controls.Add(this.separatorControl2); + this.groupBox1.Controls.Add(this.separatorControl1); + this.groupBox1.Controls.Add(this.checkBox3); + this.groupBox1.Controls.Add(this.checkBox2); + this.groupBox1.Controls.Add(this.checkBox1); + this.groupBox1.Controls.Add(this.buttonCheck2); + this.groupBox1.Controls.Add(this.buttonCheck1); + this.groupBox1.Controls.Add(this.buttonCheck); + this.groupBox1.Controls.Add(this.memoEdit6); + this.groupBox1.Controls.Add(this.memoEdit5); + this.groupBox1.Controls.Add(this.numericUpDown2); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.numericUpDown4); + this.groupBox1.Controls.Add(this.comboBox3); + this.groupBox1.Controls.Add(this.comboBox2); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Controls.Add(this.labelControl30); + this.groupBox1.Controls.Add(this.labelControl32); + this.groupBox1.Controls.Add(this.numericUpDown3); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl31); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl29); + this.groupBox1.Controls.Add(this.labelControl28); + this.groupBox1.Controls.Add(this.labelControl27); + this.groupBox1.Location = new System.Drawing.Point(38, 25); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(916, 498); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础设置 "; + this.groupBox1.Enter += new System.EventHandler(this.groupBox1_Enter); + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(651, 188); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(215, 14); + this.labelControl5.TabIndex = 60; + this.labelControl5.Text = "(在【系统管理->群通知机器人】中添加)"; + // + // labelControl19 + // + this.labelControl19.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl19.Appearance.Options.UseForeColor = true; + this.labelControl19.Location = new System.Drawing.Point(505, 188); + this.labelControl19.Name = "labelControl19"; + this.labelControl19.Size = new System.Drawing.Size(130, 14); + this.labelControl19.TabIndex = 59; + this.labelControl19.Text = "(未选择时使用系统设置)"; + // + // comboBox4 + // + this.comboBox4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox4.FormattingEnabled = true; + this.comboBox4.Location = new System.Drawing.Point(170, 185); + this.comboBox4.Name = "comboBox4"; + this.comboBox4.Size = new System.Drawing.Size(308, 22); + this.comboBox4.TabIndex = 58; + // + // labelControl20 + // + this.labelControl20.Location = new System.Drawing.Point(73, 188); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(91, 14); + this.labelControl20.TabIndex = 57; + this.labelControl20.Text = "群通知API接口:"; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(44, 103); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(823, 23); + this.separatorControl2.TabIndex = 32; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(44, 50); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(823, 23); + this.separatorControl1.TabIndex = 32; + // + // checkBox3 + // + this.checkBox3.AutoSize = true; + this.checkBox3.Location = new System.Drawing.Point(651, 133); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.Size = new System.Drawing.Size(108, 18); + this.checkBox3.TabIndex = 31; + this.checkBox3.Text = "置顶用户(微信)"; + this.checkBox3.UseVisualStyleBackColor = true; + this.checkBox3.Visible = false; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(651, 81); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(108, 18); + this.checkBox2.TabIndex = 31; + this.checkBox2.Text = "置顶用户(微信)"; + this.checkBox2.UseVisualStyleBackColor = true; + this.checkBox2.Visible = false; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(651, 28); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(108, 18); + this.checkBox1.TabIndex = 31; + this.checkBox1.Text = "置顶用户(微信)"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.Visible = false; + // + // buttonCheck2 + // + this.buttonCheck2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = true; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(89, 132); + this.buttonCheck2.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(57, 22); + this.buttonCheck2.TabIndex = 28; + // + // buttonCheck1 + // + this.buttonCheck1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = true; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(89, 79); + this.buttonCheck1.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(57, 22); + this.buttonCheck1.TabIndex = 28; + // + // buttonCheck + // + this.buttonCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck.Checked = true; + this.buttonCheck.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck.Location = new System.Drawing.Point(89, 26); + this.buttonCheck.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck.Name = "buttonCheck"; + this.buttonCheck.Size = new System.Drawing.Size(57, 22); + this.buttonCheck.TabIndex = 28; + // + // memoEdit6 + // + this.memoEdit6.Location = new System.Drawing.Point(50, 389); + this.memoEdit6.Name = "memoEdit6"; + this.memoEdit6.Size = new System.Drawing.Size(817, 96); + this.memoEdit6.TabIndex = 26; + // + // memoEdit5 + // + this.memoEdit5.Location = new System.Drawing.Point(50, 263); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Size = new System.Drawing.Size(817, 96); + this.memoEdit5.TabIndex = 27; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(708, 131); + this.numericUpDown2.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(75, 22); + this.numericUpDown2.TabIndex = 22; + this.numericUpDown2.Value = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.numericUpDown2.Visible = false; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(264, 132); + this.numericUpDown1.Maximum = new decimal(new int[] { + 999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(91, 22); + this.numericUpDown1.TabIndex = 22; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // numericUpDown4 + // + this.numericUpDown4.Location = new System.Drawing.Point(370, 79); + this.numericUpDown4.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown4.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown4.Name = "numericUpDown4"; + this.numericUpDown4.Size = new System.Drawing.Size(93, 22); + this.numericUpDown4.TabIndex = 22; + this.numericUpDown4.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // comboBox3 + // + this.comboBox3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox3.FormattingEnabled = true; + this.comboBox3.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群", + "订单冻结"}); + this.comboBox3.Location = new System.Drawing.Point(507, 131); + this.comboBox3.Name = "comboBox3"; + this.comboBox3.Size = new System.Drawing.Size(121, 22); + this.comboBox3.TabIndex = 25; + this.comboBox3.SelectedIndexChanged += new System.EventHandler(this.comboBox3_SelectedIndexChanged); + // + // comboBox2 + // + this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox2.Location = new System.Drawing.Point(507, 79); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(121, 22); + this.comboBox2.TabIndex = 25; + this.comboBox2.SelectedIndexChanged += new System.EventHandler(this.comboBox2_SelectedIndexChanged); + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox1.Location = new System.Drawing.Point(507, 26); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(121, 22); + this.comboBox1.TabIndex = 25; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // labelControl30 + // + this.labelControl30.Location = new System.Drawing.Point(471, 83); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(16, 14); + this.labelControl30.TabIndex = 16; + this.labelControl30.Text = "次."; + // + // labelControl32 + // + this.labelControl32.Location = new System.Drawing.Point(50, 369); + this.labelControl32.Name = "labelControl32"; + this.labelControl32.Size = new System.Drawing.Size(72, 14); + this.labelControl32.TabIndex = 17; + this.labelControl32.Text = "屏蔽店铺ID:"; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(370, 26); + this.numericUpDown3.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown3.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(93, 22); + this.numericUpDown3.TabIndex = 23; + this.numericUpDown3.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(128, 369); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(132, 14); + this.labelControl2.TabIndex = 18; + this.labelControl2.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl1 + // + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(128, 243); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(132, 14); + this.labelControl1.TabIndex = 18; + this.labelControl1.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl31 + // + this.labelControl31.Location = new System.Drawing.Point(50, 243); + this.labelControl31.Name = "labelControl31"; + this.labelControl31.Size = new System.Drawing.Size(72, 14); + this.labelControl31.TabIndex = 18; + this.labelControl31.Text = "屏蔽商品ID:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(653, 135); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(48, 14); + this.labelControl8.TabIndex = 19; + this.labelControl8.Text = "订单冻结"; + this.labelControl8.Visible = false; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(789, 135); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(28, 14); + this.labelControl7.TabIndex = 19; + this.labelControl7.Text = "小时."; + this.labelControl7.Visible = false; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(373, 136); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(64, 14); + this.labelControl4.TabIndex = 19; + this.labelControl4.Text = "小时内收货."; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(170, 136); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 19; + this.labelControl3.Text = "用户购买的商品"; + // + // labelControl29 + // + this.labelControl29.Location = new System.Drawing.Point(170, 83); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(190, 14); + this.labelControl29.TabIndex = 19; + this.labelControl29.Text = "用户在同家店铺多次购物(不同商品)"; + // + // labelControl28 + // + this.labelControl28.Location = new System.Drawing.Point(471, 30); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(16, 14); + this.labelControl28.TabIndex = 20; + this.labelControl28.Text = "次."; + // + // labelControl27 + // + this.labelControl27.Location = new System.Drawing.Point(170, 30); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(190, 14); + this.labelControl27.TabIndex = 21; + this.labelControl27.Text = "用户在同家店铺多次购买(同一商品)"; + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.xtraTabControl2); + this.xtraTabPage4.Controls.Add(this.bck_tlj_onoff); + this.xtraTabPage4.Controls.Add(this.labelControl11); + this.xtraTabPage4.Controls.Add(this.textEdit41); + this.xtraTabPage4.Controls.Add(this.comboBoxEdit1); + this.xtraTabPage4.Controls.Add(this.labelControl59); + this.xtraTabPage4.Controls.Add(this.labelControl10); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage4.Text = " 淘 礼 金 设 置 "; + // + // xtraTabControl2 + // + this.xtraTabControl2.Location = new System.Drawing.Point(37, 118); + this.xtraTabControl2.Name = "xtraTabControl2"; + this.xtraTabControl2.SelectedTabPage = this.xtraTabPage5; + this.xtraTabControl2.Size = new System.Drawing.Size(922, 409); + this.xtraTabControl2.TabIndex = 29; + this.xtraTabControl2.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage5, + this.xtraTabPage6}); + // + // xtraTabPage5 + // + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl3_7); + this.xtraTabPage5.Controls.Add(this.labelControl12); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl3_6); + this.xtraTabPage5.Controls.Add(this.labelControl13); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl3_5); + this.xtraTabPage5.Controls.Add(this.labelControl14); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl3_4); + this.xtraTabPage5.Controls.Add(this.memoEdit1); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl1_6); + this.xtraTabPage5.Controls.Add(this.memoEdit2); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl1_7); + this.xtraTabPage5.Controls.Add(this.memoEdit3); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl2_4); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl1_1); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl3_3); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl1_2); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl1_5); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl2_1); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl2_3); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl1_3); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl3_2); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl3_1); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl1_4); + this.xtraTabPage5.Controls.Add(this.hyperlinkLabelControl2_2); + this.xtraTabPage5.Name = "xtraTabPage5"; + this.xtraTabPage5.Size = new System.Drawing.Size(920, 383); + this.xtraTabPage5.Text = " 淘 礼 金 提 示 语 "; + // + // hyperlinkLabelControl3_7 + // + this.hyperlinkLabelControl3_7.Location = new System.Drawing.Point(701, 248); + this.hyperlinkLabelControl3_7.Name = "hyperlinkLabelControl3_7"; + this.hyperlinkLabelControl3_7.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl3_7.TabIndex = 28; + this.hyperlinkLabelControl3_7.Text = "[积分名称]"; + this.hyperlinkLabelControl3_7.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // labelControl12 + // + this.labelControl12.Location = new System.Drawing.Point(104, 40); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(108, 14); + this.labelControl12.TabIndex = 24; + this.labelControl12.Text = "淘礼金查询提示语:"; + // + // hyperlinkLabelControl3_6 + // + this.hyperlinkLabelControl3_6.Location = new System.Drawing.Point(609, 248); + this.hyperlinkLabelControl3_6.Name = "hyperlinkLabelControl3_6"; + this.hyperlinkLabelControl3_6.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl3_6.TabIndex = 28; + this.hyperlinkLabelControl3_6.Text = "[可兑换积分]"; + this.hyperlinkLabelControl3_6.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // labelControl13 + // + this.labelControl13.Location = new System.Drawing.Point(104, 157); + this.labelControl13.Name = "labelControl13"; + this.labelControl13.Size = new System.Drawing.Size(108, 14); + this.labelControl13.TabIndex = 24; + this.labelControl13.Text = "淘礼金付款提示语:"; + // + // hyperlinkLabelControl3_5 + // + this.hyperlinkLabelControl3_5.Location = new System.Drawing.Point(529, 248); + this.hyperlinkLabelControl3_5.Name = "hyperlinkLabelControl3_5"; + this.hyperlinkLabelControl3_5.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl3_5.TabIndex = 28; + this.hyperlinkLabelControl3_5.Text = "[返利积分]"; + this.hyperlinkLabelControl3_5.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // labelControl14 + // + this.labelControl14.Location = new System.Drawing.Point(104, 270); + this.labelControl14.Name = "labelControl14"; + this.labelControl14.Size = new System.Drawing.Size(108, 14); + this.labelControl14.TabIndex = 24; + this.labelControl14.Text = "淘礼金结算提示语:"; + // + // hyperlinkLabelControl3_4 + // + this.hyperlinkLabelControl3_4.Location = new System.Drawing.Point(449, 248); + this.hyperlinkLabelControl3_4.Name = "hyperlinkLabelControl3_4"; + this.hyperlinkLabelControl3_4.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl3_4.TabIndex = 28; + this.hyperlinkLabelControl3_4.Text = "[付款金额]"; + this.hyperlinkLabelControl3_4.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(219, 43); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(515, 76); + this.memoEdit1.TabIndex = 27; + // + // hyperlinkLabelControl1_6 + // + this.hyperlinkLabelControl1_6.Location = new System.Drawing.Point(593, 23); + this.hyperlinkLabelControl1_6.Name = "hyperlinkLabelControl1_6"; + this.hyperlinkLabelControl1_6.Size = new System.Drawing.Size(94, 14); + this.hyperlinkLabelControl1_6.TabIndex = 28; + this.hyperlinkLabelControl1_6.Text = "[购买中间页地址]"; + this.hyperlinkLabelControl1_6.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // memoEdit2 + // + this.memoEdit2.Location = new System.Drawing.Point(219, 155); + this.memoEdit2.Name = "memoEdit2"; + this.memoEdit2.Size = new System.Drawing.Size(515, 77); + this.memoEdit2.TabIndex = 27; + // + // hyperlinkLabelControl1_7 + // + this.hyperlinkLabelControl1_7.Location = new System.Drawing.Point(701, 23); + this.hyperlinkLabelControl1_7.Name = "hyperlinkLabelControl1_7"; + this.hyperlinkLabelControl1_7.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl1_7.TabIndex = 28; + this.hyperlinkLabelControl1_7.Text = "[积分名称]"; + this.hyperlinkLabelControl1_7.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // memoEdit3 + // + this.memoEdit3.Location = new System.Drawing.Point(219, 268); + this.memoEdit3.Name = "memoEdit3"; + this.memoEdit3.Size = new System.Drawing.Size(515, 84); + this.memoEdit3.TabIndex = 27; + // + // hyperlinkLabelControl2_4 + // + this.hyperlinkLabelControl2_4.Location = new System.Drawing.Point(464, 137); + this.hyperlinkLabelControl2_4.Name = "hyperlinkLabelControl2_4"; + this.hyperlinkLabelControl2_4.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl2_4.TabIndex = 28; + this.hyperlinkLabelControl2_4.Text = "[积分名称]"; + this.hyperlinkLabelControl2_4.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl1_1 + // + this.hyperlinkLabelControl1_1.Location = new System.Drawing.Point(221, 23); + this.hyperlinkLabelControl1_1.Name = "hyperlinkLabelControl1_1"; + this.hyperlinkLabelControl1_1.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl1_1.TabIndex = 28; + this.hyperlinkLabelControl1_1.Text = "[商品标题]"; + this.hyperlinkLabelControl1_1.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl3_3 + // + this.hyperlinkLabelControl3_3.Location = new System.Drawing.Point(369, 248); + this.hyperlinkLabelControl3_3.Name = "hyperlinkLabelControl3_3"; + this.hyperlinkLabelControl3_3.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl3_3.TabIndex = 28; + this.hyperlinkLabelControl3_3.Text = "[子订单号]"; + this.hyperlinkLabelControl3_3.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl1_2 + // + this.hyperlinkLabelControl1_2.Location = new System.Drawing.Point(293, 23); + this.hyperlinkLabelControl1_2.Name = "hyperlinkLabelControl1_2"; + this.hyperlinkLabelControl1_2.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl1_2.TabIndex = 28; + this.hyperlinkLabelControl1_2.Text = "[商品原价]"; + this.hyperlinkLabelControl1_2.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl1_5 + // + this.hyperlinkLabelControl1_5.Location = new System.Drawing.Point(533, 23); + this.hyperlinkLabelControl1_5.Name = "hyperlinkLabelControl1_5"; + this.hyperlinkLabelControl1_5.Size = new System.Drawing.Size(46, 14); + this.hyperlinkLabelControl1_5.TabIndex = 28; + this.hyperlinkLabelControl1_5.Text = "[共节省]"; + this.hyperlinkLabelControl1_5.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl2_1 + // + this.hyperlinkLabelControl2_1.Location = new System.Drawing.Point(221, 137); + this.hyperlinkLabelControl2_1.Name = "hyperlinkLabelControl2_1"; + this.hyperlinkLabelControl2_1.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl2_1.TabIndex = 28; + this.hyperlinkLabelControl2_1.Text = "[商品标题]"; + this.hyperlinkLabelControl2_1.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl2_3 + // + this.hyperlinkLabelControl2_3.Location = new System.Drawing.Point(379, 137); + this.hyperlinkLabelControl2_3.Name = "hyperlinkLabelControl2_3"; + this.hyperlinkLabelControl2_3.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl2_3.TabIndex = 28; + this.hyperlinkLabelControl2_3.Text = "[付款金额]"; + this.hyperlinkLabelControl2_3.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl1_3 + // + this.hyperlinkLabelControl1_3.Location = new System.Drawing.Point(365, 23); + this.hyperlinkLabelControl1_3.Name = "hyperlinkLabelControl1_3"; + this.hyperlinkLabelControl1_3.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl1_3.TabIndex = 28; + this.hyperlinkLabelControl1_3.Text = "[优惠券金额]"; + this.hyperlinkLabelControl1_3.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl3_2 + // + this.hyperlinkLabelControl3_2.Location = new System.Drawing.Point(301, 248); + this.hyperlinkLabelControl3_2.Name = "hyperlinkLabelControl3_2"; + this.hyperlinkLabelControl3_2.Size = new System.Drawing.Size(46, 14); + this.hyperlinkLabelControl3_2.TabIndex = 28; + this.hyperlinkLabelControl3_2.Text = "[订单号]"; + this.hyperlinkLabelControl3_2.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl3_1 + // + this.hyperlinkLabelControl3_1.Location = new System.Drawing.Point(221, 248); + this.hyperlinkLabelControl3_1.Name = "hyperlinkLabelControl3_1"; + this.hyperlinkLabelControl3_1.Size = new System.Drawing.Size(58, 14); + this.hyperlinkLabelControl3_1.TabIndex = 28; + this.hyperlinkLabelControl3_1.Text = "[商品标题]"; + this.hyperlinkLabelControl3_1.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl1_4 + // + this.hyperlinkLabelControl1_4.Location = new System.Drawing.Point(449, 23); + this.hyperlinkLabelControl1_4.Name = "hyperlinkLabelControl1_4"; + this.hyperlinkLabelControl1_4.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl1_4.TabIndex = 28; + this.hyperlinkLabelControl1_4.Text = "[淘礼金金额]"; + this.hyperlinkLabelControl1_4.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // hyperlinkLabelControl2_2 + // + this.hyperlinkLabelControl2_2.Location = new System.Drawing.Point(306, 137); + this.hyperlinkLabelControl2_2.Name = "hyperlinkLabelControl2_2"; + this.hyperlinkLabelControl2_2.Size = new System.Drawing.Size(46, 14); + this.hyperlinkLabelControl2_2.TabIndex = 28; + this.hyperlinkLabelControl2_2.Text = "[订单号]"; + this.hyperlinkLabelControl2_2.Click += new System.EventHandler(this.hyperlinkLabelControl1_1_Click); + // + // xtraTabPage6 + // + this.xtraTabPage6.Controls.Add(this.labelControl18); + this.xtraTabPage6.Controls.Add(this.labelControl17); + this.xtraTabPage6.Controls.Add(this.labelControl16); + this.xtraTabPage6.Controls.Add(this.numericUpDown7); + this.xtraTabPage6.Controls.Add(this.numericUpDown5); + this.xtraTabPage6.Controls.Add(this.numericUpDown6); + this.xtraTabPage6.Controls.Add(this.labelControl62); + this.xtraTabPage6.Controls.Add(this.labelControl61); + this.xtraTabPage6.Controls.Add(this.labelControl60); + this.xtraTabPage6.Controls.Add(this.memoEdit4); + this.xtraTabPage6.Controls.Add(this.labelControl15); + this.xtraTabPage6.Name = "xtraTabPage6"; + this.xtraTabPage6.Size = new System.Drawing.Size(920, 383); + this.xtraTabPage6.Text = " 淘 礼 金 基 础 设 置 "; + // + // labelControl18 + // + this.labelControl18.Location = new System.Drawing.Point(35, 77); + this.labelControl18.Name = "labelControl18"; + this.labelControl18.Size = new System.Drawing.Size(166, 14); + this.labelControl18.TabIndex = 38; + this.labelControl18.Text = "(多个商品ID之间使用逗号分隔)"; + // + // labelControl17 + // + this.labelControl17.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl17.Appearance.Options.UseForeColor = true; + this.labelControl17.Location = new System.Drawing.Point(117, 270); + this.labelControl17.Name = "labelControl17"; + this.labelControl17.Size = new System.Drawing.Size(691, 56); + this.labelControl17.TabIndex = 37; + this.labelControl17.Text = "注:\r\n1、淘礼金商品编码不为空时,符合条件的用户并且用户发送的商品编码存在,才会生成淘礼金链接;为空时,不受商品编码所限制\r\n\r\n2、发放的数量多于1时,将会保" + + "存起来,下次触发时再使用(受淘礼金生成时的有效期限制,过期将无效,重新生成)"; + // + // labelControl16 + // + this.labelControl16.Location = new System.Drawing.Point(372, 198); + this.labelControl16.Name = "labelControl16"; + this.labelControl16.Size = new System.Drawing.Size(77, 14); + this.labelControl16.TabIndex = 36; + this.labelControl16.Text = "(单位/小时)"; + // + // numericUpDown7 + // + this.numericUpDown7.Location = new System.Drawing.Point(207, 196); + this.numericUpDown7.Maximum = new decimal(new int[] { + 90000000, + 0, + 0, + 0}); + this.numericUpDown7.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown7.Name = "numericUpDown7"; + this.numericUpDown7.Size = new System.Drawing.Size(159, 22); + this.numericUpDown7.TabIndex = 35; + this.numericUpDown7.Value = new decimal(new int[] { + 24, + 0, + 0, + 0}); + // + // numericUpDown5 + // + this.numericUpDown5.Location = new System.Drawing.Point(570, 166); + this.numericUpDown5.Maximum = new decimal(new int[] { + 1000000, + 0, + 0, + 0}); + this.numericUpDown5.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown5.Name = "numericUpDown5"; + this.numericUpDown5.Size = new System.Drawing.Size(159, 22); + this.numericUpDown5.TabIndex = 34; + this.numericUpDown5.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // numericUpDown6 + // + this.numericUpDown6.Location = new System.Drawing.Point(207, 168); + this.numericUpDown6.Maximum = new decimal(new int[] { + 1000000, + 0, + 0, + 0}); + this.numericUpDown6.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown6.Name = "numericUpDown6"; + this.numericUpDown6.Size = new System.Drawing.Size(159, 22); + this.numericUpDown6.TabIndex = 33; + this.numericUpDown6.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl62 + // + this.labelControl62.Location = new System.Drawing.Point(117, 198); + this.labelControl62.Name = "labelControl62"; + this.labelControl62.Size = new System.Drawing.Size(84, 14); + this.labelControl62.TabIndex = 30; + this.labelControl62.Text = "领取有效时间:"; + // + // labelControl61 + // + this.labelControl61.Location = new System.Drawing.Point(480, 170); + this.labelControl61.Name = "labelControl61"; + this.labelControl61.Size = new System.Drawing.Size(84, 14); + this.labelControl61.TabIndex = 31; + this.labelControl61.Text = "每人限领个数:"; + // + // labelControl60 + // + this.labelControl60.Location = new System.Drawing.Point(105, 170); + this.labelControl60.Name = "labelControl60"; + this.labelControl60.Size = new System.Drawing.Size(96, 14); + this.labelControl60.TabIndex = 32; + this.labelControl60.Text = "淘礼金发放个数:"; + // + // memoEdit4 + // + this.memoEdit4.Location = new System.Drawing.Point(207, 55); + this.memoEdit4.Name = "memoEdit4"; + this.memoEdit4.Size = new System.Drawing.Size(515, 76); + this.memoEdit4.TabIndex = 28; + // + // labelControl15 + // + this.labelControl15.Location = new System.Drawing.Point(69, 57); + this.labelControl15.Name = "labelControl15"; + this.labelControl15.Size = new System.Drawing.Size(108, 14); + this.labelControl15.TabIndex = 25; + this.labelControl15.Text = "使用淘礼金商品ID:"; + // + // bck_tlj_onoff + // + this.bck_tlj_onoff.BackColor = System.Drawing.Color.Transparent; + this.bck_tlj_onoff.Checked = false; + this.bck_tlj_onoff.CheckStyleX = UI.Framework.Controls.CheckStyle.style4; + this.bck_tlj_onoff.Cursor = System.Windows.Forms.Cursors.Hand; + this.bck_tlj_onoff.Location = new System.Drawing.Point(305, 20); + this.bck_tlj_onoff.Margin = new System.Windows.Forms.Padding(4); + this.bck_tlj_onoff.Name = "bck_tlj_onoff"; + this.bck_tlj_onoff.Size = new System.Drawing.Size(69, 25); + this.bck_tlj_onoff.TabIndex = 26; + // + // labelControl11 + // + this.labelControl11.Location = new System.Drawing.Point(210, 25); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(72, 14); + this.labelControl11.TabIndex = 1; + this.labelControl11.Text = "淘礼金开关:"; + // + // textEdit41 + // + this.textEdit41.Location = new System.Drawing.Point(289, 77); + this.textEdit41.Name = "textEdit41"; + this.textEdit41.Properties.MaxLength = 10; + this.textEdit41.Properties.NullValuePrompt = "请填写淘礼金名称,最大10个字符"; + this.textEdit41.Size = new System.Drawing.Size(513, 20); + this.textEdit41.TabIndex = 25; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(289, 51); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(513, 20); + this.comboBoxEdit1.TabIndex = 0; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // labelControl59 + // + this.labelControl59.Location = new System.Drawing.Point(186, 80); + this.labelControl59.Name = "labelControl59"; + this.labelControl59.Size = new System.Drawing.Size(96, 14); + this.labelControl59.TabIndex = 24; + this.labelControl59.Text = "淘礼金领取名称:"; + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(210, 54); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(72, 14); + this.labelControl10.TabIndex = 1; + this.labelControl10.Text = "淘礼金用途:"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(991, 577); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MainForm_KeyDown); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + this.xtraTabPage4.ResumeLayout(false); + this.xtraTabPage4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl2)).EndInit(); + this.xtraTabControl2.ResumeLayout(false); + this.xtraTabPage5.ResumeLayout(false); + this.xtraTabPage5.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).EndInit(); + this.xtraTabPage6.ResumeLayout(false); + this.xtraTabPage6.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown7)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown5)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown6)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit41.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中淘宝推广位ToolStripMenuItem; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.MemoEdit memoEdit6; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private System.Windows.Forms.NumericUpDown numericUpDown4; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.LabelControl labelControl30; + private DevExpress.XtraEditors.LabelControl labelControl32; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private DevExpress.XtraEditors.LabelControl labelControl31; + private DevExpress.XtraEditors.LabelControl labelControl29; + private DevExpress.XtraEditors.LabelControl labelControl28; + private DevExpress.XtraEditors.LabelControl labelControl27; + private System.Windows.Forms.ComboBox comboBox2; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private UI.Framework.Controls.ButtonCheck buttonCheck; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private System.Windows.Forms.ComboBox comboBox3; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl7; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.CheckBox checkBox3; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private DevExpress.XtraEditors.LabelControl labelControl10; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit41; + private DevExpress.XtraEditors.LabelControl labelControl59; + private DevExpress.XtraEditors.LabelControl labelControl11; + private UI.Framework.Controls.ButtonCheck bck_tlj_onoff; + private DevExpress.XtraEditors.MemoEdit memoEdit3; + private DevExpress.XtraEditors.MemoEdit memoEdit2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl14; + private DevExpress.XtraEditors.LabelControl labelControl13; + private DevExpress.XtraEditors.LabelControl labelControl12; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1_4; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1_3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1_2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1_1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1_5; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1_6; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3_6; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3_5; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3_4; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2_4; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3_3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2_3; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3_2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2_2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3_1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2_1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1_7; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl3_7; + private DevExpress.XtraTab.XtraTabControl xtraTabControl2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage5; + private DevExpress.XtraTab.XtraTabPage xtraTabPage6; + private DevExpress.XtraEditors.LabelControl labelControl15; + private DevExpress.XtraEditors.MemoEdit memoEdit4; + private System.Windows.Forms.NumericUpDown numericUpDown5; + private System.Windows.Forms.NumericUpDown numericUpDown6; + private DevExpress.XtraEditors.LabelControl labelControl62; + private DevExpress.XtraEditors.LabelControl labelControl61; + private DevExpress.XtraEditors.LabelControl labelControl60; + private DevExpress.XtraEditors.LabelControl labelControl16; + private System.Windows.Forms.NumericUpDown numericUpDown7; + private DevExpress.XtraEditors.LabelControl labelControl17; + private DevExpress.XtraEditors.LabelControl labelControl18; + private DevExpress.XtraEditors.LabelControl labelControl19; + private System.Windows.Forms.ComboBox comboBox4; + private DevExpress.XtraEditors.LabelControl labelControl20; + private DevExpress.XtraEditors.LabelControl labelControl5; + } +} \ No newline at end of file diff --git a/应用/TBRebate/MainForm.cs b/应用/TBRebate/MainForm.cs new file mode 100644 index 0000000..e2fc42b --- /dev/null +++ b/应用/TBRebate/MainForm.cs @@ -0,0 +1,672 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using TBRebate.Entitys; +using TBRebate.Properties; +using UI.Framework.Controls; +using UI.Framework.Forms; + +namespace TBRebate +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + var apis = ApiClient.GetSession().FindNoticeapiRobots().ToArray(); + var rst = new List(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + comboBox4.DataSource = rst; + + #region 淘礼金模式加载 + + if (!Util.AppConfig_ExistItem("ShowTlj")) + Util.AppConfig_AddItem("ShowTlj", "0"); + + xtraTabPage4.PageVisible = ShowTlj(); + if (xtraTabPage4.PageVisible) + { + this.comboBoxEdit1.Properties.Items.AddRange(Enum.GetNames(typeof(TLJModel)).ToList()); + + bck_tlj_onoff.Checked = Class1.Config.TljOnOff; + comboBoxEdit1.SelectedIndex = (int)Class1.Config.TljModel; + this.textEdit41.Text = Class1.Config.TljName; + + this.memoEdit4.Text = Class1.Config.TljItemIds; + this.numericUpDown6.Value = Class1.Config.TljCreateNum; + this.numericUpDown5.Value = Class1.Config.TljGetLimit; + this.numericUpDown7.Value = Class1.Config.TljExpireDate; + + this.memoEdit1.Text = Class1.Config.TljSearchSuccess; + this.memoEdit2.Text = Class1.Config.TljPaymentTip; + this.memoEdit3.Text = Class1.Config.TljSettlementTip; + } + #endregion + + this.settingControl1.Bind(Class1.Config, 110); + + this.buttonCheck.Checked = Class1.Config.AShop_SameCommodity_Switch; + this.numericUpDown3.Value = Class1.Config.AShop_SameCommodity_Number; + this.comboBox1.SelectedIndex = Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单 ? 0 : 1; + this.checkBox1.Checked = Class1.Config.AShop_SameCommodity_UserTop; + + this.buttonCheck1.Checked = Class1.Config.AShop_DifferentCommodity_Switch; + this.numericUpDown4.Value = Class1.Config.AShop_DifferentCommodity_Number; + this.comboBox2.SelectedIndex = Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单 ? 0 : 1; + this.checkBox2.Checked = Class1.Config.AShop_DifferentCommodity_UserTop; + + this.buttonCheck2.Checked = Class1.Config.ReceivingTimeCheck_Switch; + this.numericUpDown1.Value = Class1.Config.ReceivingTimeCheck_Hour; + this.comboBox3.SelectedIndex = Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单 ? 0 : Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群 ? 1 : 2; + this.numericUpDown2.Value = Class1.Config.ReceivingTimeCheck_FreezeTime; + this.checkBox3.Checked = Class1.Config.ReceivingTimeCheck_UserTop; + + this.comboBox4.SelectedIndex = rst.IndexOf(Class1.Config.notice_robotname) == -1 ? 0 : rst.IndexOf(Class1.Config.notice_robotname); + + this.memoEdit5.Text = string.Join(",", Class1.Config.ItemIDRestrictList); + this.memoEdit6.Text = string.Join(",", Class1.Config.SellerIDRestrictlist); + + #region 加载所有的账号 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + + int totalNumber = 0; + var result = session.Queryable().Select(f => new tbinfo_temp() + { + ID = f.id, + chattype = f.type, + nick = f.nick, + name = f.name + }).ToPageList(page, size, ref totalNumber); + + foreach (var item in result) + { + var adzones = session.Find("select * from fl_adzone_info where robot_id = @robot_id and custom_type = @custom_type and alliance_id = @alliance_id", new { robot_id = item.ID, custom_type = Resources.SoftwareType, alliance_id = (int)CpsType.阿里妈妈 }); + foreach (var adzone in adzones) + { + if (adzone.extend == "chief")//主 + { + item.onoff = adzone.onoff; + if (adzone.adzone_group != 0)//组 + { + var _adzone = session.FindAdzoneGroups(CpsType.阿里妈妈, true).Where(f => string.IsNullOrWhiteSpace(f.remark)).FirstOrDefault(f => f.id == adzone.adzone_group); + if (_adzone != null) + { + item.is_chief_group = true; + item.pid_chief = _adzone.adzones; + item.pid_chief_name = _adzone.name; + } + } + else//单 + { + item.is_chief_group = false; + item.pid_chief_cps_name = adzone.adzone_pid_cps_name; + item.pid_chief = adzone.adzone_pid; + item.pid_chief_name = adzone.adzone_name; + } + } + else//副 + { + item.onoff = adzone.onoff; + if (adzone.adzone_group != 0)//组 + { + var _adzone = session.FindAdzoneGroups(CpsType.阿里妈妈, true).Where(f => string.IsNullOrWhiteSpace(f.remark)).FirstOrDefault(f => f.id == adzone.adzone_group); + if (_adzone != null) + { + item.is_deputy_group = true; + item.pid_deputy = _adzone.adzones; + item.pid_deputy_name = _adzone.name; + } + } + else//单 + { + item.is_deputy_group = false; + item.pid_deputy_cps_name = adzone.adzone_pid_cps_name; + item.pid_deputy = adzone.adzone_pid; + item.pid_deputy_name = adzone.adzone_name; + } + } + } + var activity = session.FindSingle("select * from fl_adzone_info where robot_id = @robot_id and custom_type = @custom_type", new { robot_id = item.ID, custom_type = Resources.TbActivitySoftwareType }); + if (activity != null) + { + var _adzone = session.FindAdzoneGroups(CpsType.阿里妈妈, true).Where(f => f.remark == fl_alimama_activity_type.天猫精选.ToString()).FirstOrDefault(f => f.id == activity.adzone_group); + if (_adzone != null) + { + item.adzone_activity_name = _adzone.name; + item.adzone_activity_pid = _adzone.adzones; + } + } + } + return new PageControl.SerchResult() { Result = result, Total = totalNumber }; + }, gridControl1, 40, true, true); + + label1.Visible = gridView1.RowCount == 0; + + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + var session = ApiClient.GetSession(); + if (e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈, isgroup: true); + if (tgwObj != null) + { + if (tgwObj is Tuiguangwei) + { + var tgw = tgwObj as Tuiguangwei; + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzone == null) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzone.extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + #region 有出现两个重复无法修复的情况,删除一个 + var repetAdzone = adzones.Where(f => f.extend == pidName).ToList(); + if (repetAdzone.Count > 1) + { + for (int i = 1; i <= repetAdzone.Count - 1; i++) + { + session.Deleteable(repetAdzone[i]).ExecuteCommand(); + } + adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + } + #endregion + + adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + adzone.adzone_group = 0; + session.SaveOrUpdate(adzone); + } + } + else if (tgwObj is fl_adzone_group) + { + var adzone_group = tgwObj as fl_adzone_group; + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzone == null) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzone.extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_name = string.Empty; + adzone.adzone_pid = string.Empty; + adzone.adzone_pid_cps_name = string.Empty; + adzone.adzone_group = adzone_group.id; + session.SaveOrUpdate(adzone); + } + } + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindTbInfoTempGroups(true); + session.FindAdzoneInfos(true); + session.FindAlimamaAutoBindPid(true);//刷新推广位 + session.FindAdzoneGroups(CpsType.阿里妈妈, true); + } + } + else if (e.Column.FieldName == "adzone_activity_name")//设置活动推广位 + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈, isalone: false, isgroup: true, isactivity: true); + if (tgwObj != null) + { + if (tgwObj is fl_adzone_group) + { + var adzone_group = tgwObj as fl_adzone_group; + var adzoneInfo = session.FindAdzoneInfos(true).FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.TbActivitySoftwareType && f.robot_id == long.Parse(id)); + if (adzoneInfo == null) + { + adzoneInfo = new fl_adzone_info() + { + custom_type = Resources.TbActivitySoftwareType, //自定义类型 + adzone_name = string.Empty, //推广位名称 + adzone_pid = string.Empty, //推广位pid + adzone_pid_cps_name = string.Empty, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false, //不禁用 + extend = string.Empty, + adzone_group = adzone_group.id + }; + } + else + { + adzoneInfo.adzone_group = adzone_group.id; + } + session.SaveOrUpdate(adzoneInfo); + } + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindAdzoneGroups(CpsType.阿里妈妈, true); + session.FindAdzoneInfos(true); + session.FindAlimamaAutoBindPid(true);//刷新推广位 + session.FindTbInfoTempGroups(true); + } + + } + } + #endregion + + #region 开关单元格单击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzones.Count == 0) + { + adzones = new List(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item, false); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzones[0].extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate, adzones[0].onoff); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + if (adzones != null)//数据库中存在 + { + session.ExcuteSQL("update fl_adzone_info set onoff = @onoff where robot_id = @robot_id and alliance_id = @alliance_id and custom_type = @custom_type", new { onoff = !adzones[0].onoff, robot_id = id, alliance_id = (int)CpsType.阿里妈妈, custom_type = Resources.SoftwareType }); + } + session.FindTbInfoTempGroups(true); + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + session.FindAlimamaAutoBindPid(true); + } + } + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 创建fl_adzone_info对象 + /// + /// + /// + /// + /// + /// + /// + private fl_adzone_info CreateAdzoneInfo(string adzone_name, string adzone_pid, string adzone_pid_cps_name, string rid, string item, bool onoff = false) + { + return new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = adzone_name, //推广位名称 + adzone_pid = adzone_pid, //推广位pid + adzone_pid_cps_name = adzone_pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = int.Parse(rid), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = onoff, //不禁用 + extend = item + }; + } + + /// + /// 修改显示内容的事件 + /// + /// + /// + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name" || e.Column.FieldName == "adzone_activity_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void MainForm_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e) + { + try + { + if (xtraTabPage4.PageVisible && (string.IsNullOrWhiteSpace(textEdit41.Text) || textEdit41.Text.Trim().Length < 5)) + { + ShowErrorAutoClose("淘礼金名称长度不能小于5并且不能大于10个字符"); + e.Cancel = true; + } + Class1.Config.AShop_SameCommodity_Switch = buttonCheck.Checked; + Class1.Config.AShop_SameCommodity_Number = (int)numericUpDown3.Value; + Class1.Config.AShop_SameCommodity_OperateType = comboBox1.SelectedIndex == 0 ? OperateType.拉入黑名单 : OperateType.通知钉钉群; + Class1.Config.AShop_SameCommodity_UserTop = checkBox1.Checked; + + Class1.Config.AShop_DifferentCommodity_Switch = buttonCheck1.Checked; + Class1.Config.AShop_DifferentCommodity_Number = (int)numericUpDown4.Value; + Class1.Config.AShop_DifferentCommodity_OperateType = comboBox2.SelectedIndex == 0 ? OperateType.拉入黑名单 : OperateType.通知钉钉群; + Class1.Config.AShop_DifferentCommodity_UserTop = checkBox2.Checked; + + Class1.Config.ReceivingTimeCheck_Switch = buttonCheck2.Checked; + Class1.Config.ReceivingTimeCheck_Hour = (int)numericUpDown1.Value; + Class1.Config.ReceivingTimeCheck_OperateType = comboBox3.SelectedIndex == 0 ? OperateType.拉入黑名单 : comboBox3.SelectedIndex == 1 ? OperateType.通知钉钉群 : OperateType.订单冻结; + Class1.Config.ReceivingTimeCheck_FreezeTime = (int)numericUpDown2.Value; + Class1.Config.ReceivingTimeCheck_UserTop = checkBox3.Checked; + + Class1.Config.notice_robotname = comboBox4.SelectedValue.ToString(); + + Class1.Config.ItemIDRestrictList = memoEdit5.Text.Trim().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + Class1.Config.SellerIDRestrictlist = memoEdit6.Text.Trim().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + if (xtraTabPage4.PageVisible) + { + Class1.Config.TljName = textEdit41.Text; + Class1.Config.TljOnOff = bck_tlj_onoff.Checked; + Class1.Config.TljModel = (TLJModel)comboBoxEdit1.SelectedIndex; + Class1.Config.TljItemIds = memoEdit4.Text; + Class1.Config.TljCreateNum = (int)numericUpDown6.Value; + Class1.Config.TljGetLimit = (int)numericUpDown5.Value; + Class1.Config.TljExpireDate = (int)numericUpDown7.Value; + Class1.Config.TljSearchSuccess = memoEdit1.Text; + Class1.Config.TljPaymentTip = memoEdit2.Text; + Class1.Config.TljSettlementTip = memoEdit3.Text; + } + OrderHelper.RefreshTbConfig(true); + Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 检测是否与发单推广位有重复 + /// + /// + /// + private void simpleButton1_Click(object sender, EventArgs e) + { + // try + // { + // var session = ApiClient.GetSession(); + + // var adzones = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType); + // var tbCricleAdzones = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.TbCricleSoftwareType).ToList();//发单推广位集合 + // var circleToolsAdzones = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.CricleToolsSoftwareType).ToList();//朋友圈推广位集合 + // tbCricleAdzones.AddRange(circleToolsAdzones); + + // if (tbCricleAdzones != null && adzones != null) + // { + + // var pidNames = tbCricleAdzones.Where(a => adzones.Where(t => a.adzone_pid == t.adzone_pid).Any()).Select(f => f.adzone_name).ToList(); + + // var namestr = string.Join("\r\n", pidNames); + + // if (namestr.Length != 0) + // ShowSuccess(@"以下推广位和发单推广设置有冲突 + //请及时处理,否则订单将无法自动绑定 + //" + namestr); + // else ShowSuccess("不存在冲突推广位"); + // } + // } + // catch (Exception ex) + // { + // ShowError(ex); + // } + } + + private void 删除选中淘宝推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var selectRow = gridView1.GetSelectedRows()[0]; + var rid = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + var robotName = this.gridView1.GetRowCellValue(selectRow, "name").ToString(); + session.ExcuteSQL("delete from fl_adzone_info where robot_id = @rid and custom_type = @custom_type", new { rid = rid, custom_type = Resources.TbActivitySoftwareType }); + ShowSuccess("删除成功"); + pageControl1.GotoPage(1); + session.FindAdzoneGroups(CpsType.阿里妈妈, true); + session.FindTbInfoTempGroups(true); + Tools.ClearActivityTuiguangwei(robotName); + session.FindAdzoneInfos(true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void comboBox3_SelectedIndexChanged(object sender, EventArgs e) + { + labelControl7.Visible = labelControl8.Visible = numericUpDown2.Visible = comboBox3.SelectedIndex == 2; + checkBox3.Visible = comboBox3.SelectedIndex == 0; + } + + private void groupBox1_Enter(object sender, EventArgs e) + { + + } + + private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) + { + checkBox2.Visible = comboBox2.SelectedIndex == 0; + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + checkBox1.Visible = comboBox1.SelectedIndex == 0; + } + + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + //try + //{ + // if (comboBoxEdit1.SelectedIndex == 0)//"首单使用淘礼金" + // { + // } + // else if (comboBoxEdit1.SelectedIndex == 1)//"随机分配淘礼金", + // { + // } + //} + //catch (Exception ex) + //{ + + //} + } + + private void MainForm_KeyDown(object sender, KeyEventArgs e) + { + + } + + public bool ShowTlj() + { + var ShowTlj = Util.AppConfig_GetValue("ShowTlj"); + if (ShowTlj != null && ShowTlj == "1") + return true; + else if (Class1.Config.TljOnOff) + return true; + return false; + } + + private void xtraTabControl1_KeyDown(object sender, KeyEventArgs e) + { + try + { + if (e.Alt) + { + if (e.KeyCode == Keys.Oem3) + { + var ShowTlj = Util.AppConfig_GetValue("ShowTlj"); + var state = ShowTlj == "1" ? "0" : "1"; + string mess = string.Empty; + if (Util.AppConfig_ModifyItem("ShowTlj", state)) + mess = state == "1" ? "成功激活淘礼金" : "成功隐藏淘礼金"; + else + mess = state == "1" ? "激活淘礼金失败" : "隐藏淘礼金失败"; + ShowSuccess(mess); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void hyperlinkLabelControl1_1_Click(object sender, EventArgs e) + { + try + { + var label = sender as HyperlinkLabelControl; + if (label != null) + { + var reg = Regex.Match(label.Name, @"^hyperlinkLabelControl(?<序列>\d)_.$"); + if (reg.Success) + { + var item = reg.Groups["序列"].Value; + if (item == "1") + memoEdit1.Text += label.Text; + if (item == "2") + memoEdit2.Text += label.Text; + if (item == "3") + memoEdit3.Text += label.Text; + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/TBRebate/MainForm.resx b/应用/TBRebate/MainForm.resx new file mode 100644 index 0000000..1a7f42e --- /dev/null +++ b/应用/TBRebate/MainForm.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 46 + + \ No newline at end of file diff --git a/应用/TBRebate/MonitorThread.cs b/应用/TBRebate/MonitorThread.cs new file mode 100644 index 0000000..34c118c --- /dev/null +++ b/应用/TBRebate/MonitorThread.cs @@ -0,0 +1,188 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using TBRebate.Entitys; +using static TBRebate.Enums; + +namespace TBRebate +{ + + + + + class MonitorThread : TimerTask + { + + private static Dictionary CacheBind = new Dictionary(); + public static void AddCache(cache_bind_orderid_temp cache_bind) + { + try + { + lock (CacheBind) + { + if (!CacheBind.ContainsKey(cache_bind.orderId)) CacheBind.Add(cache_bind.orderId, cache_bind); + } + } + catch (Exception) + { + } + } + public static void RemoveCache(cache_bind_orderid_temp cache_bind) + { + RemoveCache(cache_bind.orderId); + } + public static void RemoveCache(string orderid) + { + try + { + lock (CacheBind) + { + if (CacheBind.ContainsKey(orderid)) CacheBind.Remove(orderid); + } + } + catch (Exception) + { + } + } + + /// + /// 获取数据 + /// + /// 获取超时数据 + /// + public static List GetCacheList(DateTime time_out) + { + + try + { + lock (CacheBind) + { + var _list = CacheBind.Values.ToList(); + if (time_out != DateTime.MaxValue) return _list.Where(f => f.bind_time < time_out).ToList(); + else return _list; + + //if (!CacheBind.ContainsKey(cache_bind.orderId)) CacheBind.Remove(cache_bind.orderId); + } + } + catch (Exception) + { + } + return new List(); + } + + public static List GetCacheList() + { + return GetCacheList(DateTime.MaxValue); + } + public static void RemoveListCache(List orders) + { + foreach (var item in orders) RemoveCache(item); + } + + public override void Run(object state, bool timedOut) + { + try + { + var session = ApiClient.GetSession(); + + //获得缓存数据 + var list = GetCacheList(); + if (list != null && list.Count != 0) + { + //var delList = new List();//需要删除的 + var orders_temp = session.Find("select * from fl_order_alimama where (db_status != 1004 and db_status != 1003 and db_status != 999) and create_time > @time", new { time = DateTime.Now.AddHours(-5) }); + if (orders_temp != null && orders_temp.Count != 0) + { + foreach (var item in list) + { + try + { + var order = orders_temp.FirstOrDefault(f => f.trade_parent_id == item.orderId); + if (order != null && order.db_userid != 0) + RemoveCache(item); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "缓存处理异常:" + ex.Message + " - " + ex.StackTrace); + } + } + + + + //List orders = null; + //foreach (var item in list) + //{ + // try + // { + // orders = orders_temp.Where(f => f.trade_parent_id == item.orderId).ToList(); + // foreach (var order in orders) + // { + // //用户绑定订单 + // order.db_robotname = item.db_robotname; + // order.db_robottype = item.db_robottype; + // order.msg_groupid = item.groupid; + // order.db_userid = item.db_userid; + // var member = session.FindMemberinfo(item.db_userid); + // var itempoint = session.FindItemPoint(member, order.pub_share_pre_fee, order.item_num, CpsType.阿里妈妈); + // if (itempoint != null) + // { + // order.db_point = HttpHelper.ObjectToJson(itempoint); + // order.db_userpoint = itempoint.UserPoint; + // session.SaveOrUpdate(order); + + // var robotInfo = session.FindRobotInfo(item.db_robotname, item.db_robottype); + + // if (member != null && robotInfo != null) + // { + // ApiClient.SendMessage(robotInfo, member.username, Class1._GetOrderStateMess(order.db_status, SettleType.未结算提示, order, member, robotInfo).Replace("[返利积分]", itempoint.UserPoint.ToString()), item.groupid); + // Thread.Sleep(500); + // } + // } + // } + // } + // catch (Exception) + // { + // } + // //删除已存在订单 + // if (orders.Count != 0) RemoveCache(item); + //} + + } + } + + + //超过30分钟未绑定成功 - 应该给予客户提示 + var time_out_list = GetCacheList(DateTime.Now.AddHours(-20)); + foreach (var item in time_out_list) + { + RemoveCache(item); + + //if (item.db_robottype != ChatType.微信) continue; + //var ipad = Chat.Framework.ChatClient.WXClient.FirstOrDefault(f=>f.Key == item.db_robotname).Value; + //if (ipad == null) continue; + ////给予超时提示语 + ////ipad.SendMessage(); + } + + } + catch (System.Exception ex) + { + EventClient.OnEvent(this, $"缓存绑定异常:{ex.Message} - {ex.StackTrace}"); + } + } + + } +} \ No newline at end of file diff --git a/应用/TBRebate/Properties/AssemblyInfo.cs b/应用/TBRebate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..82657ca --- /dev/null +++ b/应用/TBRebate/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("TBRebate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TBRebate")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("1cf363a4-2f3f-4508-bf47-f1fcc86bf87b")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2019.03.24.1")] +[assembly: AssemblyFileVersion("2019.03.24.1")] diff --git a/应用/TBRebate/Properties/Resources.Designer.cs b/应用/TBRebate/Properties/Resources.Designer.cs new file mode 100644 index 0000000..0ffb65d --- /dev/null +++ b/应用/TBRebate/Properties/Resources.Designer.cs @@ -0,0 +1,194 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace TBRebate.Properties +{ + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if (object.ReferenceEquals(resourceMan, null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TBRebate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + + /// + /// 查找类似 淘宝返利 的本地化字符串。 + /// + internal static string MainFormTitle + { + get + { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// + /// 查找类似 淘宝返利 的本地化字符串。 + /// + internal static string PluginName + { + get + { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// + /// 查找类似 淘宝返利 的本地化字符串。 + /// + internal static string SoftwareType + { + get + { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 全额免单 的本地化字符串。 + /// + internal static string TbAllRebatesSoftwareType + { + get + { + return ResourceManager.GetString("TbAllRebatesSoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 淘宝发单 的本地化字符串。 + /// + internal static string TbCricleSoftwareType + { + get + { + return ResourceManager.GetString("TbCricleSoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 淘宝强返 的本地化字符串。 + /// + internal static string TbActivitySoftwareType + { + get + { + return ResourceManager.GetString("TbActivitySoftwareType", resourceCulture); + } + } + + + /// + /// 查找类似 朋友圈工具 的本地化字符串。 + /// + internal static string CricleToolsSoftwareType + { + get + { + return ResourceManager.GetString("CricleToolsSoftwareType", resourceCulture); + } + } + + internal static string PluginNote + { + get + { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 基础管理 + { + get + { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 活动推广 + { + get + { + object obj = ResourceManager.GetObject("活动推广", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 淘宝 + { + get + { + object obj = ResourceManager.GetObject("淘宝", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/TBRebate/Properties/Resources.resx b/应用/TBRebate/Properties/Resources.resx new file mode 100644 index 0000000..5aee1b1 --- /dev/null +++ b/应用/TBRebate/Properties/Resources.resx @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 淘宝返利 + 设置主窗体标题 + + + 淘宝返利 + 插件名 + + + 淘宝返利插件 + 插件介绍 + + + + ..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 朋友圈工具 + fl_adzone_info自定义类型(custom_type)朋友圈发单 + + + ..\Resources\淘宝.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 淘宝发单 + fl_adzone_info自定义类型(custom_type)淘宝发单 + + + ..\Resources\活动推广.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 淘宝返利 + fl_adzone_info自定义类型(custom_type) + + + 淘宝强返 + fl_adzone_info自定义类型(custom_type)淘宝强返 + + + 全额免单 + fl_adzone_info自定义类型(custom_type)全额免单 + + \ No newline at end of file diff --git a/应用/TBRebate/Properties/licenses.licx b/应用/TBRebate/Properties/licenses.licx new file mode 100644 index 0000000..81c8e65 --- /dev/null +++ b/应用/TBRebate/Properties/licenses.licx @@ -0,0 +1,3 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/TBRebate/Resources/基础管理.png b/应用/TBRebate/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/TBRebate/Resources/基础管理.png differ diff --git a/应用/TBRebate/Resources/活动推广.png b/应用/TBRebate/Resources/活动推广.png new file mode 100644 index 0000000..727aa42 Binary files /dev/null and b/应用/TBRebate/Resources/活动推广.png differ diff --git a/应用/TBRebate/Resources/淘宝.png b/应用/TBRebate/Resources/淘宝.png new file mode 100644 index 0000000..a548e68 Binary files /dev/null and b/应用/TBRebate/Resources/淘宝.png differ diff --git a/应用/TBRebate/SessionExt.cs b/应用/TBRebate/SessionExt.cs new file mode 100644 index 0000000..9fc6dc9 --- /dev/null +++ b/应用/TBRebate/SessionExt.cs @@ -0,0 +1,129 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using CsharpHttpHelper; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TBRebate.Entitys; +using TBRebate.Properties; + +namespace TBRebate +{ + public static class SessionExt + { + const string tbinfo_temp_list_tbrebate = "tbinfo_temp_list_tbrebates"; + + /// + /// 获取fl_fadzone_info表的数据集合缓存 + /// + /// + /// 刷新 + /// + public static List FindTbInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + //var stopWatch = new Stopwatch(); + //stopWatch.Start(); + var tbinfo_temp_groups = ApiClient.Cache.Get>(tbinfo_temp_list_tbrebate);//根据KEY、获得缓存 + //stopWatch.Stop(); + //EventClient.OnEvent("", "AAAA = " + stopWatch.Elapsed.TotalSeconds.ToString() + " ----------- " + (tbinfo_temp_groups == null ? "null" : tbinfo_temp_groups.Count.ToString())); + try + { + if (refresh || tbinfo_temp_groups == null) + { + tbinfo_temp_groups = new List(); + var robots = session.FindRobots(true); + foreach (var item in robots) + { + tbinfo_temp_groups.Add(new tbinfo_temp() + { + ID = item.id, + chattype = item.type, + nick = item.nick, + name = item.name + }); + } + + foreach (var item in tbinfo_temp_groups) + { + //var adzones = session.Queryable().Where(f => f.robot_id == item.ID && f.custom_type == Resources.SoftwareType && f.alliance_id == (int)CpsType.阿里妈妈).ToList(); + var adzones = session.Find("select * from fl_adzone_info where robot_id = @robot_id and custom_type = @custom_type and alliance_id = @alliance_id", new { robot_id = item.ID, custom_type = Resources.SoftwareType, alliance_id = (int)CpsType.阿里妈妈 }); + foreach (var adzone in adzones) + { + if (adzone.extend == "chief")//主 + { + item.onoff = adzone.onoff; + if (adzone.adzone_group != 0)//组 + { + var _adzone = session.FindAdzoneGroups(CpsType.阿里妈妈, true).Where(f => string.IsNullOrWhiteSpace(f.remark)).FirstOrDefault(f => f.id == adzone.adzone_group); + if (_adzone != null) + { + item.is_chief_group = true; + item.pid_chief = _adzone.adzones; + item.pid_chief_name = _adzone.name; + } + } + else//单 + { + item.is_chief_group = false; + item.pid_chief_cps_name = adzone.adzone_pid_cps_name; + item.pid_chief = adzone.adzone_pid; + item.pid_chief_name = adzone.adzone_name; + } + } + else//副 + { + item.onoff = adzone.onoff; + if (adzone.adzone_group != 0)//组 + { + var _adzone = session.FindAdzoneGroups(CpsType.阿里妈妈, true).Where(f => string.IsNullOrWhiteSpace(f.remark)).FirstOrDefault(f => f.id == adzone.adzone_group); + if (_adzone != null) + { + item.is_deputy_group = true; + item.pid_deputy = _adzone.adzones; + item.pid_deputy_name = _adzone.name; + } + } + else//单 + { + item.is_deputy_group = false; + item.pid_deputy_cps_name = adzone.adzone_pid_cps_name; + item.pid_deputy = adzone.adzone_pid; + item.pid_deputy_name = adzone.adzone_name; + } + } + } + + //var activity = session.Queryable().First(f => f.robot_id == item.ID && f.custom_type == Resources.TbActivitySoftwareType); + var activity = session.FindSingle("select * from fl_adzone_info where robot_id = @robot_id and custom_type = @custom_type", new { robot_id = item.ID, custom_type = Resources.TbActivitySoftwareType }); + if (activity != null) + { + var _adzone = session.FindAdzoneGroups(CpsType.阿里妈妈, true).Where(f => f.remark == fl_alimama_activity_type.天猫精选.ToString()).FirstOrDefault(f => f.id == activity.adzone_group); + if (_adzone != null) + { + item.adzone_activity_name = _adzone.name; + item.adzone_activity_pid = _adzone.adzones; + } + } + } + ApiClient.Cache.Set(tbinfo_temp_list_tbrebate, tbinfo_temp_groups, 60); + } + } + catch (Exception ex) + { + EventClient.OnEvent(null, $"【淘宝返利】 => 获取推广位异常:{ex.Message} - {ex.StackTrace}"); + } + return tbinfo_temp_groups; + } + + public static void Clear() + { + ApiClient.Cache.Remove(tbinfo_temp_list_tbrebate); + } + } +} diff --git a/应用/TBRebate/TBRebate.csproj b/应用/TBRebate/TBRebate.csproj new file mode 100644 index 0000000..898cfb8 --- /dev/null +++ b/应用/TBRebate/TBRebate.csproj @@ -0,0 +1,138 @@ + + + + + Debug + AnyCPU + {32FB3BAC-447A-471F-9A2F-698CE9700002} + Library + Properties + TBRebate + TBRebate + v4.6.1 + 512 + true + + + true + full + false + ..\..\Debug\Plugin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\Debug\Api.Framework.dll + False + + + ..\..\Debug\Chat.Framework.dll + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + ..\..\Debug\HtmlAgilityPack.dll + False + + + ..\..\Debug\HttpHelper.dll + False + + + False + ..\..\Debug\Newtonsoft.Json.dll + False + + + False + ..\..\Debug\SqlSugar.dll + False + + + + + + + + + + + + + + ..\..\Debug\UI.Framework.dll + False + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + + + + + + + MainForm.cs + + + + Designer + + + + + + + + + \ No newline at end of file diff --git a/应用/TBRebate/TLJModel.cs b/应用/TBRebate/TLJModel.cs new file mode 100644 index 0000000..522fe98 --- /dev/null +++ b/应用/TBRebate/TLJModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TBRebate +{ + public enum TLJModel + { + 首单付款前使用淘礼金 = 0, + 新人首次查询时使用淘礼金 = 1, + 查询随机分配淘礼金 = 2 + } +} diff --git a/应用/TBRebate/Tools.cs b/应用/TBRebate/Tools.cs new file mode 100644 index 0000000..21faab4 --- /dev/null +++ b/应用/TBRebate/Tools.cs @@ -0,0 +1,283 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Newtonsoft.Json.Linq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using TBRebate.Entitys; + +namespace TBRebate +{ + public static class Tools + { + public const string Reg_QRCode_Goods = @"\[图片=(?<二维码图片>.+?)\]"; + public static List Regex_Items = new List() { @",\\""price\\"":{\\""priceText\\"":\\""(?.+?)\\"",", @",\\""price\\"":\\""(?.+?)\\""", @",\\""priceText\\"":\\""(?.+?)\\""," }; + + /// + /// 获取中英文混排字符串的实际长度(字节数) + /// + /// 要获取长度的字符串 + /// 字符串的实际长度值(字节数) + public static int GetStringLength(string str) + { + if (str.Equals(string.Empty)) + return 0; + int strlen = 0; + ASCIIEncoding strData = new ASCIIEncoding(); + //将字符串转换为ASCII编码的字节数字 + byte[] strBytes = strData.GetBytes(str); + for (int i = 0; i <= strBytes.Length - 1; i++) + { + if (strBytes[i] == 63) //中文都将编码为ASCII编码63,即"?"号 + strlen++; + strlen++; + } + return strlen; + } + + private static int chief_group_count = 0; + private static int chief_group_index = -1; + + private static int deputy_group_count = 0; + private static int deputy_group_index = -1; + + /// + /// 累加推广位组调用次数 + /// + /// + public static void GroupAdzoneCount(fl_member_info member, tbinfo_temp tbInfoTemp) + { + if (member.buy_point >= Class1.Config.Point && member.finish_order >= Class1.Config.OrderNum) + { + if (tbInfoTemp.is_chief_group) + chief_group_count++; + } + else + { + if (tbInfoTemp.is_deputy_group) + deputy_group_count++; + } + } + + /// + /// 获取推广位 + /// + /// + /// + /// + public static Tuiguangwei GetTuiguangwei(string robotName, fl_member_info member, tbinfo_temp tbInfoTemp) + { + try + { + #region + var choose = (member.buy_point >= Class1.Config.Point && member.finish_order >= Class1.Config.OrderNum);//判断是主还是副 + if (choose) + { + if (tbInfoTemp.is_chief_group) + { + string key_chief = "fl_tbrebate_key_chief_" + robotName; + Tuiguangwei tgw = ApiClient.Cache.Get(key_chief); + if (chief_group_count >= ApiClient.Setting.SystemConfig.TGWRandomCount || tgw == null) + { + chief_group_count = 0; + chief_group_index++; + var list = HttpHelper.JsonToObject>(tbInfoTemp.pid_chief) as List; + if (list != null && list.Count != 0) + { + list = list.Where(o => CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == o.Member.username) != null).ToList(); + if (list == null || list.Count == 0) return null; + if (chief_group_index < list.Count) + tgw = list[chief_group_index]; + else + { + tgw = list[0]; + chief_group_index = 0; + } + } + ApiClient.Cache.Set(key_chief, tgw, 60); + } + return tgw; + } + else + return new Tuiguangwei() { Pid = tbInfoTemp.pid_chief, Name = tbInfoTemp.pid_chief_name, Member = new fl_cps_member() { username = tbInfoTemp.pid_chief_cps_name } }; + } + else + { + if (tbInfoTemp.is_deputy_group) + { + string key_deputy = "fl_tbrebate_key_deputy_" + robotName; + var tgw = ApiClient.Cache.Get(key_deputy); + if (deputy_group_count >= ApiClient.Setting.SystemConfig.TGWRandomCount || tgw == null) + { + deputy_group_count = 0; + deputy_group_index++; + var list = HttpHelper.JsonToObject>(tbInfoTemp.pid_deputy) as List; + if (list != null && list.Count != 0) + { + list = list.Where(o => CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == o.Member.username) != null).ToList(); + if (list == null || list.Count == 0) return null; + if (deputy_group_index < list.Count) + tgw = list[deputy_group_index]; + else + { + tgw = list[0]; + deputy_group_index = 0; + } + } + ApiClient.Cache.Set(key_deputy, tgw, 60); + } + return tgw; + } + else + return new Tuiguangwei() { Pid = tbInfoTemp.pid_deputy, Name = tbInfoTemp.pid_deputy_name, Member = new fl_cps_member() { username = tbInfoTemp.pid_deputy_cps_name } }; + } + #endregion + } + catch (System.Exception ex) + { + EventClient.OnEvent(null, $"选择使用的推广位异常:{ex.Message} - {ex.StackTrace}"); + } + return null; + } + + private static int activity_group_count = 0; + private static int activity_group_index = -1; + + /// + /// 强制推广位组 + /// + /// + /// + /// + public static TuiguangweiActivity GetActivityTuiguangwei(string robotName, tbinfo_temp tbInfoTemp) + { + try + { + string key_activity = "fl_tbrebate_key_activity_" + robotName; + + var tgw = ApiClient.Cache.Get(key_activity); + if (activity_group_count >= ApiClient.Setting.SystemConfig.TGWRandomCount || tgw == null) + { + activity_group_count = 0; + activity_group_index++; + var list = HttpHelper.JsonToObject>(tbInfoTemp.adzone_activity_pid) as List; + if (list != null && list.Count != 0) + { + list = list.Where(o => CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == o.Member.username) != null).ToList(); + if (list == null || list.Count == 0) return null; + if (activity_group_index < list.Count) + { + tgw = list[activity_group_index]; + } + else + { + tgw = list[0]; + activity_group_index = 0; + } + } + ApiClient.Cache.Set(key_activity, tgw, 60); + } + activity_group_count++; + return tgw; + + } + catch (Exception ex) + { + EventClient.OnEvent(null, $"选择使用的强返推广位异常:{ex.Message} - {ex.StackTrace}"); + } + return null; + } + + /// + /// 清除强制推广位组缓存 + /// + public static void ClearActivityTuiguangwei(string robotName) + { + string key_activity = "fl_tbrebate_key_activity_" + robotName; + ApiClient.Cache.Remove(key_activity); + } + + /// + /// 获取商品标题缓存 + /// + public static Dictionary GoodTitleCacheDic = new Dictionary(); + + /// + /// 获取商品的标题,这个会频繁 + /// + /// + /// + public static Task GetGoodTitle(string mess) + { + return Task.Run(() => + { + var md5 = Util.GetMD5(mess); + if (GoodTitleCacheDic.ContainsKey(md5)) + return GoodTitleCacheDic[md5]; + + for (int i = 0; i < 2; i++) + { + try + { + //{"tkl":"6.0 hi:/哈LpUPXfo8wU0嘻 【移动用户立减1000元/咨询客服享惊喜好礼!】Apple/苹果 iPhone 12 5G官网旗舰iphone12苹果12官方正品手机"} + + var postData = $"{{\"tkl\":\"{mess}\"}}"; + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "http://api.chaozhi.hk/tb/tklParse", + Method = "POST", + Timeout = 5000, + ReadWriteTimeout = 2000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "http://tool.chaozhi.hk/", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = postData, + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + var jOjb = JObject.Parse(html); + var error_code = jOjb["error_code"].ToString(); + if (error_code == "0") + { + var keyword = jOjb["data"]["content"].ToString(); + if (!string.IsNullOrWhiteSpace(keyword)) + { + if (!GoodTitleCacheDic.ContainsKey(md5)) + GoodTitleCacheDic.Add(md5, keyword); + return keyword; + } + } + else if (error_code == "113")//{"error_code":113,"msg":"频率太快了","data":{}} + { + Thread.Sleep(1000); + continue; + } + } + catch (Exception ex) + { + return string.Empty; + } + } + return string.Empty; + }); + } + + } +} diff --git a/应用/TBRebate/Uses/MessageOperation.cs b/应用/TBRebate/Uses/MessageOperation.cs new file mode 100644 index 0000000..8cc6466 --- /dev/null +++ b/应用/TBRebate/Uses/MessageOperation.cs @@ -0,0 +1,1919 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using TBRebate.Properties; +using static Api.Framework.Tools.TBHelper; +using static Api.Framework.Tools.TBHelper.TbAnalysis; +using static TBRebate.Enums; + +namespace TBRebate.Uses +{ + public class MessageOperation + { + ReciveIMEvent e = null; + Class1 plugin = null; + object sender = null; + + public MessageOperation(object sender, ReciveIMEvent e, Class1 plugin) + { + this.e = e; + this.plugin = plugin; + this.sender = sender; + } + + #region 订单绑定 + public bool BindOrderId() + { + try + { + //淘宝订单绑定 + var orderid = e.Message.Trim(); + if (Regex.IsMatch(e.Message.Trim(), @"^(\d{4})\s(\d{4})\s(\d{4})\s(\d{4})\s(\d{3})$")) + orderid = orderid.Replace(" ", ""); + + if (!Regex.IsMatch(orderid, @"^\d{18,19}$")) + return false; + + var db = ApiClient.GetSession(); + + var oid = long.Parse(orderid); + + if (oid >= 4000000000000000000) + return false; + + var orderList = db.Find("select * from fl_order_alimama where trade_parent_id = @trade_parent_id", new { trade_parent_id = orderid }); + + var memberTmp = e.GetMemberinfo(); + + if (orderList != null && orderList.Count != 0) + { + var member = orderList.FirstOrDefault(f => f.db_userid != 0 && f.db_userid != memberTmp.id); + if (member != null) + { + //订单已经被他人绑定 + e.SendMessage(Class1.Config.OccupyOrderErrorTip.Replace("[订单号]", orderid)); + return true; + } + var notices = new List(); + + var downAliTimer = new DownAlimamaTimer(); + + #region 订单用户已经绑定 纯提示,非结算的订单也提示上级 + var bindOrders = orderList.Where(f => f.db_userid != 0).ToList(); + if (bindOrders != null && bindOrders.Count != 0) + { + foreach (var order in bindOrders) + { + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + memberTmp = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Class1.Config.OrderRepetBindTip, order, memberTmp, point)); + else + e.SendMessage(Class1._GetOrderStateMess(order.db_status, (order.db_status == SystemOrderStatus.订单结算 ? SettleType.已结算提示 : SettleType.未结算提示), order, memberTmp, point)); + Thread.Sleep(500); + } + //return; + } + #endregion + + #region 订单没有被绑定(两种情况 => 一个订单已经被结算 一个是订单未结算) + var notBindOrders = orderList.Where(f => f.db_userid == 0).ToList(); + if (notBindOrders != null && notBindOrders.Count != 0) + { + if (notBindOrders[0].create_time < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderid},已经过了有效绑定时间!"); + return true; + } + + foreach (var order in notBindOrders) + { + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-2);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + + //没有绑定用户的订单进行绑定 + order.db_userid = memberTmp.id; + order.db_robotname = e.RobotName; + order.db_robottype = e.RobotInfo.type; + order.msg_groupid = e.Groupid; + + bool is_allrebatesactivity = false; + #region 全额返利绑定 并且 将返利积分进行固定 + var adzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.TbAllRebatesSoftwareType && f.adzone_pid.EndsWith("_" + order.adzone_id)); + if (adzone != null) + { + var allrebatesactivity_infos = db.Find("select * from fl_plugin_allrebatesactivity_info where goods_id = @goods_id", new { goods_id = order.num_iid }); + if (allrebatesactivity_infos != null && allrebatesactivity_infos.Count != 0) + { + var allrebatesactivity_info = allrebatesactivity_infos.FirstOrDefault(f => f.time_begin <= order.create_time && order.create_time <= f.time_end && f.groups.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(z => Convert.ToInt64(z.Trim())).ToList().Contains(memberTmp.group_id) && f.robots.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(z => z.Trim()).ToList().Contains(order.db_robotname)); + + if (allrebatesactivity_info != null) + { + var allrebatesactivity_orderlists = db.Find("select * from fl_plugin_allrebatesactivity_orderlist where activity_id = @activity_id and mid = @mid", new { activity_id = allrebatesactivity_info.id, mid = memberTmp.id }); + int purchased_quantity = 0;//已经购买的数量 + if (allrebatesactivity_orderlists != null && allrebatesactivity_orderlists.Count != 0) + { + foreach (var item in allrebatesactivity_orderlists) + { + var order_alimama = db.FindSingle("select * from fl_order_alimama where id = @id", new { id = item.oid }); + if (order_alimama != null && (order_alimama.db_status == SystemOrderStatus.订单结算 || order_alimama.db_status == SystemOrderStatus.全额退款 || order_alimama.db_status == SystemOrderStatus.部分退款 || order_alimama.db_status == SystemOrderStatus.订单付款 || order_alimama.db_status == SystemOrderStatus.订单冻结 || order_alimama.db_status == SystemOrderStatus.订单退款 || order_alimama.db_status == SystemOrderStatus.订单维权中)) + purchased_quantity += order_alimama.item_num; + } + } + + if (allrebatesactivity_info.limit_quantity_number >= (order.item_num + purchased_quantity)) + { + is_allrebatesactivity = true; + var return_money = (double)((decimal)allrebatesactivity_info.return_money * (decimal)order.item_num); + var point = @"{""Type"":0,""Commission"":0,""SumPoint"":" + order.pub_share_pre_fee + @",""UserPoint"":" + return_money + @",""AwardOne"":0,""AwardTwo"":0,""AwardThree"":0,""AwardCreate"":0}"; + order.db_point = point; + order.db_userpoint = return_money; + + var robot = db.FindRobots().FirstOrDefault(f => f.name == order.db_robotname && order.db_robottype == f.type); + if (robot != null) + { + var allrebatesactivity_orderlist = new fl_plugin_allrebatesactivity_orderlist() + { + activity_id = allrebatesactivity_info.id, + mid = memberTmp.id, + rid = robot.id, + oid = order.id + }; + db.Saveable(allrebatesactivity_orderlist).ExecuteCommand(); + } + } + } + } + } + #endregion + + #region 手动绑定,重新计算用户的返利积分 + if (!is_allrebatesactivity) + { + //判断是否为淘礼金订单,如果是淘礼金订单将不给这个订单返利 + var isTljOrder = db.CheckIsTljOrder(order.adzone_id); + + //计算的佣金 - 判断使用设置模式,符合将扣除用户自定义预扣佣金 + var commission = db.GetTbComparisonFeeRate(order); + + #region 历史查询时使用的比例 + //查询历史查询比例 + var compute = db.FindQueryRatioHist(CpsType.阿里妈妈, order.id); + if (compute == null) + { + var itemIdB = order.num_iid; + if (order.num_iid.Contains("-")) + { + var split = order.num_iid.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries); + itemIdB = split[1]; + } + + var query_item = db.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid order by id desc", new { userid = memberTmp.id, itemid = itemIdB, adzoneid = order.adzone_id }); + + //计算公式不为空 + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + try + { + compute = JsonConvert.DeserializeObject(query_item.compute_configdic); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = order.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + db.SaveOrUpdate(queryRatioHist); + } + catch (Exception ex) + { + EventClient.OnEvent("淘宝计算", $"获取历史查询比异常:{ex.Message}"); + } + } + } + #endregion + ItemPoint itempoint = null; + + //计算的佣金 + if (compute != null) + itempoint = db.FindItemPoint(CpsType.阿里妈妈, compute, isTljOrder ? 0 : commission, order.item_num); + else + itempoint = db.FindItemPoint(memberTmp, isTljOrder ? 0 : commission, order.item_num, CpsType.阿里妈妈); + if (itempoint != null) + { + order.db_point = HttpHelper.ObjectToJson(itempoint); + order.db_userpoint = itempoint.UserPoint; + } + } + #endregion + + #region 用户的完成订单数量加1 + if (memberTmp != null) + { + memberTmp.bind_order++; + memberTmp = db.UpdateMemberGroup(memberTmp); + } + #endregion + + #region 首次付款时间 + var record = db.FindStatisticsRecord(memberTmp.id); + if (record == null) + { + record = new fl_statistics_record() { uid = memberTmp.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + db.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = HttpExtend.GetTimeStamp(DateTime.Now); + db.Saveable(record).ExecuteCommand(); + } + } + #endregion + + db.SaveOrUpdate(order); + + #region 淘宝订单尾号自动采集 + if (ApiClient.Setting.SystemConfig.order_alimama_last_auto_capture == SwitchType.开启) + { + //订单尾号和用户进行绑定 + if (db.FindAlimamaOrderLastnums().FirstOrDefault(f => f.userid == memberTmp.id) == null) + { + db.Insertable(new fl_alimama_order_lastnum() { userid = memberTmp.id, lastnumber = order.trade_parent_id.Substring(order.trade_parent_id.Length - 6, 6) }).ExecuteCommand(); + db.FindAlimamaOrderLastnums(true); + } + } + #endregion + + //var strb = new StringBuilder(); + //try + //{ + // strb.Append($@"淘宝订单ID BIND 数据: {HttpHelper.ObjectToJson(order)}"); + //} + //catch (Exception) + //{ } + + downAliTimer.UpdateOrder(order, notices, db, isFrontData: true); + + //try + //{ + // strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(order)}"); + // EventClient.OnEvent("淘宝订单_: ", strb.ToString()); + //} + //catch (Exception) + //{ } + } + } + #endregion + + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.IsRewards) + tasks.Add(item); + //else + //plugin.SDK_OrderNoticeEvent(this, item); + } + } + #endregion + } + else + { + #region 未找到订单,提示用户并且加入绑定缓存中 + e.SendMessage(Class1.Config.NotFoundOrderErrorTip.Replace("[订单号]", orderid)); + + var bind = db.FindBindCache(orderid); + if (bind == null) + { + db.Insertable(new fl_bind_cache() { crt_time = DateTime.Now, db_robotid = e.RobotInfo.id, orderid = orderid, groupid = e.Groupid, db_userid = memberTmp.id }).ExecuteCommand(); + db.FindBindCache(orderid, true); + } + #endregion + } + //消息已经处理完成,将不往后面的插件传递 + e.Cancel = true; + return true; + } + catch (Exception ex) + { + plugin.OnLog($"手动绑定订单号异常:{ex.Message}_{ex.StackTrace}"); + } + return false; + } + #endregion + + private Dictionary debutTimes = new Dictionary(); + private void debug(string source, string msg) + { + return; + var start = DateTime.Now; + if (debutTimes.ContainsKey(source)) + { + start = debutTimes[source]; + } + else + { + debutTimes[source] = start; + } + + plugin.OnLog($"{source} - {(DateTime.Now - start).TotalSeconds} - {msg}"); + } + + public bool AnalyseFanLi() + { + Compute compute = null; + var msgid = Guid.NewGuid().ToString(); + try + { + var db = ApiClient.GetSession(); + + var tbinfoTemps = db.FindTbInfoTempGroups(); + var tbInfoTemp = tbinfoTemps.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (tbInfoTemp == null) return false; + var memberTmp = e.GetMemberinfo(); + + var message = e.Message.Trim(); + + //推广位 + var pid = string.Empty; + + #region 判断使用的推广位 (群推广/私人推广位/默认推广位) + var isDefaultPid = true; + + #region 判断消息是否为群消息并且判断群是否设置了群pid + if (!string.IsNullOrWhiteSpace(e.Groupid)) + { + var groupAdzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + pid = groupAdzone.adzone_pid; + isDefaultPid = false; + } + } + #endregion + + #region 判断消息是否为私人消息并且判断私人是否设置了私人pid + if (isDefaultPid) + { + var memberAdzone = db.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == memberTmp.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + pid = memberAdzone.adzone_pid; + isDefaultPid = false; + } + } + #endregion + if (isDefaultPid)//默认推广位 + { + var tgw = Tools.GetTuiguangwei(e.RobotInfo.name, memberTmp, tbInfoTemp); + if (tgw == null || string.IsNullOrWhiteSpace(tgw.Pid)) throw new Exception("@阿里妈妈推广位异常.请检测后重试!!"); + pid = tgw.Pid; + } + #endregion + var pids = pid.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + if (pids == null || pids.Length == 0) throw new Exception("推广位数据异常,请重新设置推广位"); + + var tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == pids[1]); + if (tb_cps == null) throw new Exception("@阿里妈妈推广位异常,请检测后重试!"); + + //关键词/标题 + var keyword = string.Empty; + //是否是标题 + var IsTitle = false; + var api = CpsClient.CreateAlimamaRequest(tb_cps); + if (api == null) throw new Exception("@创建阿里妈妈API请求失败"); + + #region 自定义搜索 (例:找衣服) + if (Class1.Config.SearchCustomSwitch == SwitchType.开启) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.SearchPrefix)) + { + //判断接收到的内容是都满足标题搜索或者关键词搜索 + var reg = Regex.Match(message, Class1.Config.SearchPrefix);//获取到符合关键词搜索的正则 + if (reg.Success) + { + keyword = reg.Groups["关键词"].Value.Trim(); + if (Class1.Config.SearchTitleSwitch == SwitchType.开启)//开启淘宝标题搜索 + { + var ileng = Tools.GetStringLength(keyword);//这里判断字符串的长度为 30个汉字,或者60个字节 + if (ileng >= 40 && ileng <= 100 && !Regex.IsMatch(keyword, HttpExtend.REGEX_GETURL, RegexOptions.IgnoreCase))//非链接并且字符串字节长度符合小于等于40,大等于60的条件,才去查询标题 + IsTitle = true; + } + if (!IsTitle && !string.IsNullOrEmpty(keyword)) + { + var searchUrl = api.ComposeTbCms(pid, keyword);//内置的搜索机制 + e.SendMessage(Class1.Config.PreciseSearchSuccessTip.Replace("[关键词]", keyword).Replace("[购买地址]", ApiClient.ShortURL(searchUrl, Class1.Config.SearchDwzType).Result)); + return true; + } + } + } + } + #endregion + #region 判断消息是否符合标题验证,如果符合将判断为标题搜索 + if (string.IsNullOrEmpty(keyword) && Class1.Config.SearchTitleSwitch == SwitchType.开启 && !Regex.IsMatch(message, Tools.Reg_QRCode_Goods))//开启淘宝标题搜索 + { + var tklreg = TbAnalysis.GetTklReg(); + + if ((!Regex.IsMatch(message, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?") && !Regex.IsMatch(message, tklreg)) && !Regex.Match(message, @"[!,<>!@#\$%\^&*()_+~>·@#¥%……&*()——+,。、!?\?]").Success) + { + var wx = sender as WeixinBase; + var wfm = e.Event as WXReiceveFriendMsg; + if (wx != null && ((wfm != null && !wfm.IsRobot) || e.Event is WXReceiveGroupMsg)) + { + var ileng = Tools.GetStringLength(message);//这里判断字符串的长度为 30个汉字,或者60个字节 + if (ileng >= 40 && ileng <= 100 && !Regex.IsMatch(message, HttpExtend.REGEX_GETURL, RegexOptions.IgnoreCase))//非链接并且字符串字节长度符合小于等于40,大等于60的条件,才去查询标题 + { + keyword = message; + IsTitle = true; + } + } + } + } + #endregion + + #region 宝贝二维码识别 + string QRCodeUrl = string.Empty; + if (Class1.Config.QRCodeSearchSwitch == SwitchType.开启) + { + var reg_ = Regex.Match(message, Tools.Reg_QRCode_Goods); + if (reg_.Success) + { + QRCodeUrl = Util.DecodeQRCode(reg_.Groups["二维码图片"].Value);//解析的二维码图片所得到的二维码内容 + message = message.Replace(reg_.Groups["二维码图片"].Value, ""); + } + } + #endregion + var tbAnalysis = new TbAnalysis(); + + var title = string.Empty;//商品标题 + + //商品id + var item_id = string.Empty; + try + { + item_id = tbAnalysis.FindItemIdByUrlAndTklAndMkl(string.IsNullOrEmpty(QRCodeUrl) ? message : QRCodeUrl, api, pids); + //TODO 淘宝商品Id转成字符串Id + + } + catch (Exception ex) + { + #region 获取标题xxx + if (string.IsNullOrWhiteSpace(keyword)) + { + //try + //{ + // var sss = api.SendTaobao("taobao.wireless.share.tpwd.query", new { password_content = e.Message }); + //} + //catch (Exception ex1) + //{ + //} + + + //var _title = Tools.GetGoodTitle(e.Message).Result; + //if (!string.IsNullOrWhiteSpace(_title)) + // title = _title; + } + #endregion + + if (!ex.Message.Contains("淘口令解析结果无效,当前淘口令无效") && string.IsNullOrEmpty(keyword) && string.IsNullOrWhiteSpace(title)) + { + e.SendMessage(Class1.Config.SearchNoCommissionTip.Replace("[关键词]", "").Replace("[商品标题]", "")); + db.UpdateRecord(memberTmp.id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.阿里妈妈; + shared["msg_username"] = memberTmp.username; + shared["price"] = "未知"; + shared["title"] = title ?? keyword; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + } + return true; + } + + #region 忽略的商品id 与 限制商品Id + if (!string.IsNullOrWhiteSpace(item_id)) + { + #region 忽略的商品id + var temp = Class1.ignoreidsCache.FirstOrDefault(f => f.itemid == item_id); + if (temp != null && temp.losetime >= HttpExtend.GetTimeStamp(DateTime.Now)) + { + e.SendMessage(Class1.Config.SearchNoCommissionTip.Replace("[关键词]", "").Replace("[商品标题]", "")); + db.UpdateRecord(memberTmp.id); + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.阿里妈妈; + shared["msg_username"] = memberTmp.username; + shared["price"] = "未知"; + shared["title"] = title ?? keyword; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + return true; + } + #endregion + + #region 限制商品ID + if (Class1.Config.ItemIDRestrictList.Contains(item_id)) + { + e.SendMessage(Class1.Config.ItemIDRestrictTip.Replace("[商品ID]", item_id)); + return true; + } + #endregion + } + #endregion + + #region 标题搜索和商品id搜索 + if (!string.IsNullOrWhiteSpace(title) || !string.IsNullOrEmpty(keyword) || !string.IsNullOrEmpty(item_id)) + { + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + e.SendMessage(Class1.Config.SearchingTip); + + var titleSuccess = false;//判断是否是标题搜索 + try + { + //是否检测优惠券金额等信息 (其他平台获取的优惠券信息/高佣查询的优惠券信息)不需要校验 + var isCheckCoupon = true; + + Dictionary privilege = null; + + //累计推广位组调用次数 + Tools.GroupAdzoneCount(memberTmp, tbInfoTemp); + //商品的详细信息 + Dictionary objData = null; + + if (!string.IsNullOrEmpty(keyword) && IsTitle && string.IsNullOrEmpty(item_id))//符合搜索标题查询宝贝 + { + try + { + objData = api.SendTaobao("taobao.tbk.sc.material.optional", new { adzone_id = pids[3], site_id = pids[2], q = keyword }); + titleSuccess = true; + } + catch (Exception) + { + objData = null; + } + } + else if (!string.IsNullOrEmpty(item_id))//符合搜索宝贝id的条件 + { + var biz_scene_id = TBHelper.TbAnalysis.BizSceneId(item_id); + objData = api.SendTaobao("taobao.tbk.item.info.get", new { num_iids = item_id, biz_scene_id = biz_scene_id }); + } + + //商品有返利 + if (objData != null && objData.Count != 0) + { + + #region 通过标题返回的结构 或者 通过商品id返回的结构 解析至相同部分 + object tbk_temp_info = null; + if (titleSuccess) + { + if (objData.ContainsKey("result_list")) + { + var result_list = objData["result_list"] as Dictionary; + if (result_list != null && result_list.ContainsKey("map_data")) + { + var map_data = (result_list["map_data"]) as ArrayList; + if (map_data != null && map_data.Count != 0) + tbk_temp_info = map_data[0]; + } + } + } + else + { + var n_tbk_item = (objData["n_tbk_item"]) as ArrayList; + if (n_tbk_item != null && n_tbk_item.Count != 0) + tbk_temp_info = n_tbk_item[0]; + } + #endregion + + var tbk_item = tbk_temp_info as Dictionary; + //店铺ID + var sellerId = string.Empty; + if (tbk_item.ContainsKey("pict_url")) + { + var reg = Regex.Match(tbk_item["pict_url"].ToString(), @"i\d+?/(?<店铺Id>\d+?)/"); + if (reg.Success) + { + sellerId = reg.Groups["店铺Id"].Value; + if (Class1.Config.SellerIDRestrictlist.Contains(sellerId)) + { + e.SendMessage(Class1.Config.SellerIDRestrictTip.Replace("[店铺ID]", sellerId)); + return true; + } + } + } + + //商品链接 + var item_url = tbk_item["item_url"].ToString(); + //店铺名称 + var nick = tbk_item["nick"].ToString(); + //商品主图 + var pict_url = tbk_item["pict_url"].ToString(); + //商品id + item_id = tbk_item["num_iid"].ToString(); + //商品标题//< >&"© <,>,&,",©; + title = tbk_item["title"].ToString().Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©");//这里有个看不见的字符,要将其替换掉 + + //原价 + var reserve_price = double.Parse(tbk_item["reserve_price"].ToString()); + //商品折扣价格(当前售价) + var zk_final_price = double.Parse(tbk_item["zk_final_price"].ToString()); + //30天销量 + var volume = "0"; + if (tbk_item.ContainsKey("volume")) + volume = tbk_item["volume"].ToString(); + + //券后价 + var endPrice = -1d; + #region 检测连接中是否包含优惠券信息 并且 获取店铺id且判断店铺id是否被屏蔽 + var activityIdTmp = string.Empty; + var activityId = string.Empty; + activityId = tbAnalysis.activityId; + var urls = HttpExtend.RegexMatchesUrl(e.Message); + if (urls != null && urls.Count != 0) + { + foreach (var url in urls) + { + if (url.ToLower().Contains("uland.taobao")) + { + var reg = Regex.Match(url, @"activityId=(?<活动ID>[A-Za-z0-9]+)", RegexOptions.IgnoreCase); + if (reg.Success) + { + activityIdTmp = activityId = reg.Groups["活动ID"].Value; + } + #region 获取店铺ID并且检测是否为屏蔽的店铺 + //https://uland.taobao.com/quan/detail?sellerId=2203061148088&activityId=91a71ae9a76445288724467712c0083d + reg = Regex.Match(url, @"sellerId=(?<店铺ID>[^&]*)", RegexOptions.IgnoreCase); + if (reg.Success) + { + sellerId = reg.Groups["店铺ID"].Value; + //店铺id限制 + if (Class1.Config.SellerIDRestrictlist.Contains(sellerId)) + { + e.SendMessage(Class1.Config.SellerIDRestrictTip.Replace("[店铺ID]", sellerId)); + return true; + } + } + #endregion + break; + } + } + } + #endregion + //最高佣金率 + var commission_rate = 0d; + + //实时佣金的时候special_id不为空 + var SpecialIdNotNull = false; + + #region 申请高佣(通过设置的返利模式获取对应的高佣信息) + switch (Class1.Config.QueryComparisonSwitch) + { + case QueryComparisonType.查询使用实时佣金: + { + #region 获取用户的special_id + if (string.IsNullOrWhiteSpace(e.Groupid)) + { + var special_id = string.Empty; + + var relation = db.FindTbRelations().FirstOrDefault(f => f.cps_memberid == api.Member.username && f.username == e.Username); + if (relation != null) + { + try + { + privilege = tbAnalysis.GetPrivilege(api, item_id, pids, "2", e.Username, relation.special_id.ToString()); + if (privilege != null) + SpecialIdNotNull = true; + } + catch (Exception ex) + { + db.Deleteable(relation).ExecuteCommand(); + } + } + if (privilege == null) + { + try + { + var _data = new { info_type = 2, relation_app = "common", external_id = e.Username, external_type = 1 }; + special_id = tbAnalysis.FindTbPublisherInfoFirst(api, _data); + + if (!string.IsNullOrWhiteSpace(special_id)) + SpecialIdNotNull = true; + #endregion + + if (privilege == null || !privilege.ContainsKey("min_commission_rate")) + privilege = tbAnalysis.GetPrivilege(api, item_id, pids, "2", SpecialIdNotNull ? e.Username : string.Empty, special_id); + } + catch (Exception ex) + { } + } + } + if (privilege == null) + privilege = tbAnalysis.GetPrivilege(api, item_id, pids, "2"); + } + break; + case QueryComparisonType.查询使用比价佣金: + { + if (privilege == null) + privilege = tbAnalysis.GetPrivilege(api, item_id, pids, "2"); + if (privilege != null && !privilege.ContainsKey("min_commission_rate")) + { + var privilege_temp = tbAnalysis.GetPrivilege(api, item_id, pids, "2", e.Username); + if (privilege_temp != null) + { + var data_temp = privilege_temp["data"] as Dictionary; + if (data_temp != null && data_temp.ContainsKey("min_commission_rate")) + commission_rate = double.Parse(data_temp["min_commission_rate"].ToString()); + } + } + } + break; + case QueryComparisonType.查询使用正常佣金: + { + if (privilege == null || !privilege.ContainsKey("max_commission_rate")) + privilege = tbAnalysis.GetPrivilege(api, item_id, pids, "2"); + } + break; + default: + break; + } + #endregion + if (privilege == null) throw new Exception("申请高佣失败,原因未知"); + + var privilege_data = privilege["data"] as Dictionary; + + #region 获取商品佣金 + if (commission_rate == 0) + { + if (privilege_data.ContainsKey("max_commission_rate")) + commission_rate = double.Parse(privilege_data["max_commission_rate"].ToString()); + else if (privilege_data.ContainsKey("min_commission_rate")) + commission_rate = double.Parse(privilege_data["min_commission_rate"].ToString()); + } + #endregion + + //新商品ID的话,获取新的字符串IdB段 + if (privilege_data.ContainsKey("item_id")) + { + item_id = privilege_data["item_id"].ToString(); + if (item_id.Contains("-")) + { + var split = item_id.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries); + item_id = split[1]; + } + } + + + //优惠券地址 + var coupon_click_url = string.Empty; + //优惠券金额 + var coupon_price = 0.00d; + //优惠券满减比较的价格(原价和最终的价格,满减金额好像是通过判断原价进行比较的) + var coupon_comparison_price = (reserve_price > zk_final_price ? reserve_price : zk_final_price); + + #region 有无券模式 获取对应的优惠券地址和优惠券金额 + if (Class1.Config.NoCouponModeSwitch == SwitchType.关闭) + { + #region 获取最终的付款金额 与 优惠券链接 优惠券金额 + //检测大淘客是否有优惠券,和价格 + //TbExCoupon exCoupon = TBHelper.FindGoodsCouponInfo(item_id); + //不要去获取外部的优惠券 + TbExCoupon exCoupon = null; + + if (exCoupon != null) + { + activityId = exCoupon.activityId; + sellerId = exCoupon.sellerId; + coupon_price = exCoupon.couponAmount; + //zk_final_price = exCoupon.salePrice; + + //这里因为外部获取到的金额有误差通过优惠券的判断,是使用外部获取的金额还是最终的金额 + //if (zk_final_price != exCoupon.salePrice && zk_final_price > exCoupon.couponAmount) + //{ } + //else + //{ + // zk_final_price = exCoupon.salePrice; + // endPrice = exCoupon.endPrice; + //} + + //TODO 这里外部获取的价格不正确,都会不准 + if (zk_final_price != exCoupon.salePrice) + { + //zk_final_price = exCoupon.salePrice; + //coupon_comparison_price = zk_final_price; + + //zk_final_price = exCoupon.salePrice; + coupon_comparison_price = zk_final_price; + if (exCoupon.salePrice < zk_final_price) + endPrice = exCoupon.endPrice; + isCheckCoupon = false; + } + //正常优惠券 + var coupon_price_temp = 0d; + var condition_price_temp = 0d; + if (privilege_data.ContainsKey("coupon_info")) + { + var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (quan_reg.Success) + { + coupon_price_temp = double.Parse(quan_reg.Groups["减"].Value); + condition_price_temp = double.Parse(quan_reg.Groups["满"].Value); + } + } + + //妈妈优惠券 + var mm_coupon_price_temp = 0d; + var mm_condition_price_temp = 0d; + if (privilege_data.ContainsKey("mm_coupon_info")) + { + var mm_quan_reg = Regex.Match(privilege_data["mm_coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (mm_quan_reg.Success) + { + mm_coupon_price_temp = double.Parse(mm_quan_reg.Groups["减"].Value); + mm_condition_price_temp = double.Parse(mm_quan_reg.Groups["满"].Value); + } + } + + var coupon = 0d; + if (zk_final_price >= mm_condition_price_temp) + { + if (mm_coupon_price_temp >= exCoupon.couponAmount) + { + activityId = string.Empty; + coupon = mm_coupon_price_temp; + if (privilege_data.ContainsKey("mm_coupon_click_url")) + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + endPrice = zk_final_price - mm_coupon_price_temp; + coupon_price = mm_coupon_price_temp; + + } + } + + if (zk_final_price >= condition_price_temp) + { + if (coupon_price_temp >= exCoupon.couponAmount && coupon_price_temp > coupon) + { + activityId = string.Empty; + if (privilege_data.ContainsKey("coupon_click_url")) + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + endPrice = zk_final_price - coupon_price_temp; + coupon_price = coupon_price_temp; + } + //else if (condition_price_temp <= zk_final_price && condition_price_temp < exCoupon.salePrice) + //{ + + //} + } + + //if (string.IsNullOrWhiteSpace(coupon_click_url)) + //{ + // if (privilege_data.ContainsKey("coupon_click_url")) + // coupon_click_url = privilege_data["coupon_click_url"].ToString(); + // else if (privilege_data.ContainsKey("mm_coupon_click_url")) + // coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + // else + // coupon_click_url = privilege_data["item_url"].ToString(); + //} + //isCheckCoupon = false; + } + else + { + if (privilege_data.ContainsKey("mm_coupon_info") && privilege_data.ContainsKey("coupon_info")) + { + //正常优惠券 + var coupon_price_temp = 0d; + var condition_price_temp = 0d; + var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (quan_reg.Success) + { + coupon_price_temp = double.Parse(quan_reg.Groups["减"].Value); + condition_price_temp = double.Parse(quan_reg.Groups["满"].Value); + } + + //妈妈优惠券 + var mm_coupon_price_temp = 0d; + var mm_condition_price_temp = 0d; + var mm_quan_reg = Regex.Match(privilege_data["mm_coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (mm_quan_reg.Success) + { + mm_coupon_price_temp = double.Parse(mm_quan_reg.Groups["减"].Value); + mm_condition_price_temp = double.Parse(mm_quan_reg.Groups["满"].Value); + } + + var condition_price = 0d;//满减条件 + if (mm_condition_price_temp <= coupon_comparison_price && condition_price_temp <= coupon_comparison_price) + { + if (mm_coupon_price_temp > coupon_price_temp) + { + coupon_price = mm_coupon_price_temp; + condition_price = mm_condition_price_temp; + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + } + else + { + coupon_price = coupon_price_temp; + condition_price = condition_price_temp; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + } + //妈妈优惠券条件金额小于最小的售价并且妈妈优惠券金额比正常优惠券高 + else if (mm_condition_price_temp <= coupon_comparison_price && mm_coupon_price_temp > coupon_price_temp) + { + coupon_price = mm_coupon_price_temp; + condition_price = mm_condition_price_temp; + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + } + //正常优惠券条件金额小于最小的售价并且正常优惠券金额比妈妈优惠券高 + else if (condition_price_temp <= coupon_comparison_price && mm_coupon_price_temp < coupon_price_temp) + { + coupon_price = coupon_price_temp; + condition_price = condition_price_temp; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + else if (mm_condition_price_temp > coupon_comparison_price && condition_price_temp > coupon_comparison_price) + { + if (mm_coupon_price_temp < coupon_price_temp) + { + coupon_price = coupon_price_temp; + condition_price = condition_price_temp; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + else + { + coupon_price = mm_coupon_price_temp; + condition_price = mm_condition_price_temp; + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + } + } + + var multiple = Math.Ceiling(condition_price / coupon_comparison_price); + if (multiple != 0) + zk_final_price = zk_final_price * multiple; + } + else if (privilege_data.ContainsKey("mm_coupon_info")) + { + var quan_reg = Regex.Match(privilege_data["mm_coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (quan_reg.Success) + { + coupon_price = double.Parse(quan_reg.Groups["减"].Value); + var condition_price = double.Parse(quan_reg.Groups["满"].Value); + + var multiple = Math.Ceiling(condition_price / coupon_comparison_price); + if (multiple != 0) + zk_final_price = zk_final_price * multiple; + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + } + } + else if (privilege_data.ContainsKey("coupon_info")) + { + var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (quan_reg.Success) + { + coupon_price = double.Parse(quan_reg.Groups["减"].Value); + var condition_price = double.Parse(quan_reg.Groups["满"].Value); + var multiple = Math.Ceiling(condition_price / coupon_comparison_price); + if (multiple != 0) + { + var zk_final_priceTmp = zk_final_price * multiple; + if (zk_final_priceTmp <= coupon_price) + { + var priceTmp = (decimal)zk_final_price * (decimal)Math.Ceiling(coupon_price / zk_final_price); + zk_final_price = (double)Math.Round(priceTmp, 2); + } + else + zk_final_price = zk_final_price * multiple; + } + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + } + } + #endregion + if (string.IsNullOrWhiteSpace(coupon_click_url)) + { + if (privilege_data.ContainsKey("mm_coupon_click_url")) + coupon_click_url = privilege_data["mm_coupon_click_url"].ToString(); + else if (privilege_data.ContainsKey("coupon_click_url")) + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + else if (privilege_data.ContainsKey("item_url")) + coupon_click_url = privilege_data["item_url"].ToString(); + } + #region 校验优惠券是否有效 (通过优惠券id和店铺id | 通过优惠券链接) + if (isCheckCoupon && !string.IsNullOrWhiteSpace(activityId) && !string.IsNullOrWhiteSpace(sellerId)) + { + #region 获取优惠券金额 + var hsf_coupon = AlimamaApi.mtop_alimama_union_hsf_coupon_get(sellerId, activityId); + if (hsf_coupon != null) + { + if (hsf_coupon.ContainsKey("result")) + { + var result = hsf_coupon["result"] as Dictionary; + + var isValid = true; + //var isValid = false; + //if (result.ContainsKey("effectiveStartTime")) + //{ + // var effectiveStartTime = result["effectiveStartTime"].ToString(); + // try + // { + // isValid = DateTime.Now >= DateTime.Parse(effectiveStartTime); + // } + // catch (Exception ex) + // { } + //} + + if (isValid) + { + if (result.ContainsKey("amount")) + coupon_price = double.Parse(result["amount"].ToString()); + if (result.ContainsKey("startFee")) + { + //zk_final_price = double.Parse(result["startFee"].ToString()); + var startFee = double.Parse(result["startFee"].ToString()); + var multiple = Math.Ceiling(startFee / coupon_comparison_price); + if (multiple != 0) + zk_final_price = zk_final_price * multiple; + } + } + } + } + #endregion + } + else + { + //if (privilege_data.ContainsKey("coupon_start_time")) + if (privilege_data.ContainsKey("coupon_start_time") && string.IsNullOrWhiteSpace(activityId)) + { + var coupon_start_time = DateTime.Parse(privilege_data["coupon_start_time"].ToString()) <= DateTime.Now.Date; + isCheckCoupon = false; + } + if (isCheckCoupon) + { + if (!string.IsNullOrWhiteSpace(activityId)) + coupon_click_url = coupon_click_url + "&activityId=" + activityId; + var coupon = api.CheckCoupon(coupon_click_url);//检查优惠券有效性 + if (coupon != null && coupon.retStatus != 0 && string.IsNullOrWhiteSpace(activityId))//优惠券过期 + { + coupon_click_url = privilege_data["item_url"].ToString(); + coupon_price = 0.00d; + zk_final_price = double.Parse(tbk_item["zk_final_price"].ToString()); + } + } + + } + #endregion + } + else + { + coupon_click_url = privilege_data["item_url"].ToString(); + coupon_price = 0.00d; + } + #endregion + + if (endPrice == -1 && zk_final_price > coupon_price) + endPrice = (double)((decimal)zk_final_price - (decimal)coupon_price); + else if (zk_final_price <= coupon_price) + { + coupon_price = 0; + endPrice = zk_final_price; + } + //plugin.OnLog("_" + commission_rate); + var useCoupon_totalCommFee = Math.Round(endPrice * (commission_rate / 100.00), 2); + + //用券后 给用户的佣金 + var useCoupon_commFee = db.FindItemPoint(memberTmp, useCoupon_totalCommFee, 1, CpsType.阿里妈妈, out compute); + + Compute compute1 = null; + + //不用券 佣金 + var unuseCoupon_totalCommFee = Math.Round(zk_final_price * (commission_rate / 100.00), 2); + //不用券 给用户的佣金 + var unuseCoupon_commFee = db.FindItemPoint(memberTmp, unuseCoupon_totalCommFee, 1, CpsType.阿里妈妈, out compute1); + + if (compute == null) + compute = compute1; + + #region 淘礼金 生成淘礼金链接,如果返回空,这不能生成. + var tljUrl = TljMethod(e.GetMemberinfo(true), ref api, item_id, useCoupon_commFee.UserPoint); + if (!string.IsNullOrWhiteSpace(tljUrl)) + { + var _tlj = db.FindTljInfos().FirstOrDefault(f => f.username == api.Member.username); + if (_tlj != null) + pids = _tlj.adzone_pid.Split('_'); + } + #endregion + + //判断是否有淘礼金,有淘礼金用淘礼金,没有就用购物地址 + var couponUrl = string.IsNullOrWhiteSpace(tljUrl) ? coupon_click_url : tljUrl; + + if (!string.IsNullOrWhiteSpace(activityId)) + couponUrl = couponUrl + "&activityId=" + activityId; + + //更新私域用户备案信息 + if (Class1.Config.QueryComparisonSwitch == QueryComparisonType.查询使用实时佣金 && !SpecialIdNotNull && string.IsNullOrWhiteSpace(e.Groupid)) + { + try + { + var tmpData2 = api.SendTaobao("taobao.tbk.sc.relation.record", new { external_id = e.Username, op_type = 2, redirect_url = couponUrl, external_type = 1 }); + if (tmpData2.ContainsKey("data")) + couponUrl = (tmpData2["data"] as Dictionary)["url"].ToString(); + + api.AddTBEid(e.Username); + } + catch (Exception ex) + { + plugin.OnLog($"更细私域异常关系 :({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message}"); + } + } + #region 获取淘口令 tkl + TklInfo tklInfo = null; + var tkl = string.Empty; + try + { + //生成淘口令的图片(看是否有设置自定义的图片) + string _pict_url = pict_url; + //生成淘口令的标题(看是否有设置自定义的标题) + string _title = title; + if (Class1.Config.TKLCustomSwitch == SwitchType.开启) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.TKLImageUrl)) + _pict_url = Class1.Config.TKLImageUrl; + if (!string.IsNullOrWhiteSpace(Class1.Config.TKLTitle)) + _title = Class1.Config.TKLTitle; + } + //生成淘口令 + tklInfo = tbAnalysis.FindTKL(couponUrl, api); + if (tklInfo == null) + { + e.SendMessage(Class1.Config.SearchNoCommissionTip?.Replace("[关键词]", keyword).Replace("[商品标题]", title));//未搜索到提示语 + db.UpdateRecord(memberTmp.id); + var shared1 = new Dictionary(); + shared1["msg_type"] = "查询宝贝"; + shared1["cps_type"] = CpsType.阿里妈妈; + shared1["msg_username"] = memberTmp?.username; + shared1["price"] = "未知"; + shared1["title"] = title ?? keyword; + shared1["coupon_price"] = "未知"; + shared1["user_point"] = "未知"; + shared1["economize"] = "未知"; + var sharedEvent1 = new SharedEvents(shared1); + EventClient.OnEvent(sender, sharedEvent1); + return true; + } + } + catch (Exception ex) + { + throw new Exception($"@获取淘口令异常:{ex.Message} - {ex.StackTrace}"); + } + #endregion + //淘口令的前/后符号有没有设置.有设置将替换掉 + tkl = tbAnalysis.ReplaceTklModifier(tklInfo.tkl); + //中间页地址 + //var composeUrl = api.ComposeTbClick(item_id, pict_url, tklInfo.tkl, couponUrl, true); + var composeUrl = api.ComposeTbClick(item_id, pict_url, tklInfo.tkl, tklInfo.isoUrl, true, pid, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品); + // 获取短连接 + //couponUrl = tbAnalysis.FindShortUrlBySrcUrl(couponUrl, api); + couponUrl = tklInfo.isoUrl; + #region 淘礼金 + if (!string.IsNullOrWhiteSpace(tljUrl)) + { + var mess = Class1.Config.TljSearchSuccess; + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("", "") : title) + .Replace("[商品原价]", zk_final_price.ToString()) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[月销量]", volume) + .Replace("[店铺名称]", nick) + .Replace("[优惠券金额]", (coupon_price != 0 ? coupon_price.ToString() : "0")) + .Replace("[淘礼金金额]", useCoupon_commFee.UserPoint.ToString()) + .Replace("[购买地址]", couponUrl) + .Replace("[购买中间页地址]", composeUrl) + .Replace("[购买淘口令]", tkl) + .Replace("[共节省]", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, zk_final_price.ToString(), coupon_price.ToString(), ((decimal)zk_final_price - (decimal)coupon_price).ToString(), pict_url, composeUrl, ApiClient.QrImageType.模板B, CpsType.阿里妈妈) + "]" : string.Empty) + ); + } + + + #endregion + #region 正常订单 + else + { + //有券的情况 + if (coupon_price != 0) + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Class1.Config.QQSearchSuccessWithCouponTip))) + mess = Class1.Config.SearchSuccessWithCouponTip; + else + mess = Class1.Config.QQSearchSuccessWithCouponTip; + + e.SendMessage(mess + .Replace("劵", "券") + .Replace("[商品标题]", mess.Contains("", "") : title) + .Replace("[商品原价]", string.Format("{0:F}", zk_final_price)) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[月销量]", volume) + .Replace("[店铺名称]", nick) + .Replace("[券后返利]", string.Format("{0:F}", useCoupon_commFee.UserPoint)) + .Replace("[弃券返利]", string.Format("{0:F}", unuseCoupon_commFee.UserPoint)) + .Replace("[券后价]", string.Format("{0:F}", endPrice)) + .Replace("[优惠券金额]", coupon_price.ToString()) + .Replace("[购买地址]", couponUrl) + .Replace("[购买中间页地址]", composeUrl) + .Replace("[购买淘口令]", tkl) + .Replace("[共节省]", string.Format("{0:F}", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint))) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, zk_final_price.ToString(), coupon_price.ToString(), endPrice.ToString(), pict_url, composeUrl, ApiClient.QrImageType.模板B, CpsType.阿里妈妈) + "]" : string.Empty) + + .Replace("[产品编号]", item_id) + .Replace("[推广PID]", pid) + .Replace("[淘口令]", tkl) + .Replace("[图片地址]", pict_url) + .Replace("[是否推荐]", (ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品).ToString()) + ); + } + else//没有券的情况 + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Class1.Config.QQSearchSuccessWithoutCouponTip))) + mess = Class1.Config.SearchSuccessWithoutCouponTip; + else + mess = Class1.Config.QQSearchSuccessWithoutCouponTip; + + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("", "") : title) + .Replace("[商品原价]", string.Format("{0:F}", zk_final_price)) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[月销量]", volume) + .Replace("[店铺名称]", nick) + .Replace("[返利积分]", string.Format("{0:F}", unuseCoupon_commFee.UserPoint)) + .Replace("[购买地址]", couponUrl) + .Replace("[购买中间页地址]", composeUrl) + .Replace("[购买淘口令]", tkl) + .Replace("[共节省]", string.Format("{0:F}", useCoupon_commFee.UserPoint)) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(title, zk_final_price.ToString(), "0", zk_final_price.ToString(), pict_url, composeUrl, ApiClient.QrImageType.模板B, CpsType.阿里妈妈) + "]" : string.Empty) + + .Replace("[产品编号]", item_id) + .Replace("[推广PID]", pid) + .Replace("[淘口令]", tkl) + .Replace("[图片地址]", pict_url) + .Replace("[是否推荐]", (ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品).ToString()) + ); + } + } + #endregion + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + db.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.阿里妈妈, + itemid = item_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = memberTmp.id, + title = title, + adzoneid = pids[3], + mallid = sellerId, + compute_configdic = compute == null ? string.Empty : JsonConvert.SerializeObject(compute) + }).ExecuteCommand(); + db.UpdateRecord(memberTmp.id); + + var shared = new Dictionary(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.阿里妈妈; + shared["msg_username"] = memberTmp.username; + shared["price"] = string.Format("{0:F}", zk_final_price); + shared["title"] = title; + shared["coupon_price"] = string.Format("{0:F}", coupon_price); + shared["user_point"] = coupon_price != 0 ? string.Format("{0:F}", useCoupon_commFee.UserPoint) : string.Format("{0:F}", unuseCoupon_commFee.UserPoint); + shared["economize"] = coupon_price != 0 ? string.Format("{0:F}", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint)) : string.Format("{0:F}", useCoupon_commFee.UserPoint); + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + #endregion + return true; + } + else + { + if (Class1.Config.ShopAdSwitch == SwitchType.开启) + { + #region 商品没有返利,店铺参加了推广,下单后有返利 + string data = new HttpHelper().GetHtml(new HttpItem() + { + URL = $"https://item.taobao.com/item.htm?ft=t&id={item_id}", + Method = "get", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "text/html", + Allowautoredirect = false, + ProxyIp = "", + ResultType = ResultType.String + }).Html; + + var reg_title = Regex.Match(data, @"title\s*:\s*'(?[^']+)'", RegexOptions.IgnoreCase); + title = reg_title.Success ? HttpExtend.Unicode2String(reg_title.Groups["title"].Value) : string.Empty; + + var pict_url = string.Empty; + var sellerId = string.Empty; + var reg_sellerId = Regex.Match(data, @"userid=(?<sellerId>\d+);", RegexOptions.IgnoreCase); + if (!reg_sellerId.Success) + reg_sellerId = Regex.Match(data, @"sellerId\s*:\s*'(?<sellerId>\d+)'", RegexOptions.IgnoreCase); + if (reg_sellerId.Success) + { + var reg_pic = Regex.Match(data, @"pic\s*:\s*'(?<pic>[^']+)'", RegexOptions.IgnoreCase); + pict_url = reg_pic.Success ? reg_pic.Groups["pic"].Value : string.Empty; + if (!pict_url.ToLower().StartsWith("http")) + pict_url = "http:" + pict_url; + + sellerId = reg_sellerId.Groups["sellerId"].Value; + } + else + { + var url = HttpExtend.RegexMatchUrl(message); + if (!string.IsNullOrWhiteSpace(url)) + { + data = new HttpHelper().GetHtml(new HttpItem() + { + URL = url, + Method = "get", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "text/html", + Allowautoredirect = false, + ProxyIp = "", + ResultType = ResultType.String + }).Html; + + var reg = Regex.Match(data, @"_!!(?<sellerId>\d+).jpg", RegexOptions.IgnoreCase); + if (reg.Success) + { + sellerId = reg.Groups["sellerId"].Value; + } + } + } + + if (!string.IsNullOrWhiteSpace(sellerId)) + { + try + { + var shopConvert = api.SendTaobao("taobao.tbk.sc.shop.convert", new { fields = "user_id,click_url", site_id = pids[2], user_ids = sellerId, adzone_id = pids[3] }); + if (shopConvert != null && shopConvert.Count != 0) + { + if (shopConvert.ContainsKey("n_tbk_shop")) + { + var n_tbk_shop = shopConvert["n_tbk_shop"] as ArrayList; + if (n_tbk_shop.Count != 0) + { + var shopInfo = n_tbk_shop[0] as Dictionary<string, object>; + if (shopInfo.ContainsKey("click_url")) + { + var click_url = shopInfo["click_url"].ToString(); + if (!string.IsNullOrWhiteSpace(click_url)) + { + var shopTGUrl = tbAnalysis.FindShortUrlBySrcUrl(click_url, api); + var tklInfo = tbAnalysis.FindTKL(shopTGUrl, api); + if (tklInfo == null) + { + e.SendMessage(Class1.Config.SearchNoCommissionTip.Replace("[关键词]", keyword).Replace("[商品标题]", title));//未搜索到提示语 + db.UpdateRecord(memberTmp.id); + var shared1 = new Dictionary<string, object>(); + shared1["msg_type"] = "查询宝贝"; + shared1["cps_type"] = CpsType.阿里妈妈; + shared1["msg_username"] = memberTmp.username; + shared1["price"] = "未知"; + shared1["title"] = title ?? keyword; + shared1["coupon_price"] = "未知"; + shared1["user_point"] = "未知"; + shared1["economize"] = "未知"; + var sharedEvent1 = new SharedEvents(shared1); + EventClient.OnEvent(sender, sharedEvent1); + return true; + } + //淘口令的前/后符号有没有设置.有设置将替换掉 + var tkl = tbAnalysis.ReplaceTklModifier(tklInfo.tkl); + + //中间页地址 + //var composeUrl = api.ComposeTbClick(item_id, pict_url, tklInfo.tkl, shopTGUrl, true); + var composeUrl = api.ComposeTbClick(item_id, pict_url, tklInfo.tkl, tklInfo.isoUrl, true, pid, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品); + + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Class1.Config.QQSearchSuccessWithCouponTip))) + mess = Class1.Config.ShopAdSuccessTip; + else + mess = Class1.Config.QQShopAdSuccessTip; + + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("<appmsg") ? title.Replace("<", "").Replace(">", "") : title) + .Replace("[商品主图]", $"[图片={pict_url}]") + .Replace("[图片地址]", pict_url) + .Replace("[购买地址]", shopTGUrl) + .Replace("[购买中间页地址]", composeUrl) + .Replace("[购买淘口令]", tkl) + ); + + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + db.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.阿里妈妈, + itemid = item_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = memberTmp.id, + title = title, + adzoneid = pids[3], + mallid = string.Empty + }).ExecuteCommand(); + db.UpdateRecord(memberTmp.id); + + var shar = new Dictionary<string, object>(); + shar["msg_type"] = "查询宝贝"; + shar["cps_type"] = CpsType.阿里妈妈; + shar["msg_username"] = memberTmp.username; + shar["price"] = "未知"; + shar["title"] = title; + shar["coupon_price"] = "未知"; + shar["user_point"] = "未知"; + shar["economize"] = "未知"; + + var sharEvent = new SharedEvents(shar); + EventClient.OnEvent(sender, sharEvent); + #endregion + return true; + } + } + } + } + } + } + catch (Exception ex) + { + } + } + #endregion + } + #region 强返 + //判断是否为天猫商品 + var flag_tianmao = api.IsTianmao(item_id); + var adzone = db.FindAdzoneInfos().FirstOrDefault(f => f.custom_type == Resources.TbActivitySoftwareType && f.robot_id == e.RobotInfo.id); + #region 判断是否需要标题,需要标题的情况获取标题 + if (string.IsNullOrWhiteSpace(keyword) && string.IsNullOrWhiteSpace(title) && ((flag_tianmao && adzone != null) || Class1.Config.SearchTitleSwitch_NoCommission == SwitchType.开启 || Class1.Config.SearchNoCommissionTip.Contains("[商品标题]"))) + { + var reg = Regex.Match(e.Message, @"「(?<标题>.{5,})」"); + if (reg.Success) + title = reg.Groups["标题"].Value; + if (string.IsNullOrEmpty(title)) + { + #region 一系列获取标题的操作,最终就是想获取标题 + HttpHelper http = new HttpHelper(); + var item = new HttpItem(); + item.URL = @"https://acs.m.taobao.com/gw/mtop.taobao.detail.getdetail/6.0/?data={%22itemNumId%22%3A%22" + item_id + @"%22&qq-pf-to=pcqq.group"; + var _html = http.GetHtml(item).Html; + if (_html.Contains("SUCCESS::调用成功")) + { + reg = Regex.Match(_html, @"""title"":""(?<title>[^""]{10,})"","""); + if (reg.Success) + title = reg.Groups["title"].Value; + } + else + { + var html = string.Empty; + for (int i = 0; i < 4; i++) + { + HttpItem httpItem = new HttpItem() + { + URL = @"https://item.taobao.com/item.htm?id=" + item_id,//宝贝的链接 + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = true, + AutoRedirectCookie = true + }; + http = new HttpHelper(); + var result = http.GetHtml(httpItem); + if (!(result != null && (result.Html.Contains("操作超时")) || result.Html.Contains("基础连接已经关闭"))) + { + html = result.Html; + break; + } + Thread.Sleep(200); + } + reg = Regex.Match(html, @"<meta name=""keywords"" content=""(?<标题>.+?)""/>"); + if (reg.Success) + { + title = reg.Groups["标题"].Value.Replace("淘宝,掏宝,网上购物,店铺, ", ""); + if (title.Last() == '.') + title = title.Substring(0, title.Length - 1); + } + else + { + + } + } + #endregion + } + } + #endregion + if (flag_tianmao) + { + //var adzone = db.FindAdzoneInfos().FirstOrDefault(f => f.custom_type == Resources.TbActivitySoftwareType && f.robot_id == e.RobotInfo.id); + if (adzone != null) + { + var group = db.FindAdzoneGroups(CpsType.阿里妈妈).FirstOrDefault(f => f.id == adzone.adzone_group); + if (group != null) + { + var activity = Tools.GetActivityTuiguangwei(e.RobotInfo.name, tbInfoTemp); + if (activity == null) throw new Exception(@"无结果"); + pids = activity.Pid.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + if (pids == null || pids.Length == 0) throw new Exception("推广位异常,请重新设置强返推广位"); + tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == pids[1]); + if (tb_cps == null) throw new Exception("@阿里妈妈推广位异常,请检测后重试 !"); + api = CpsClient.CreateAlimamaRequest(tb_cps); + if (api == null) throw new Exception("@创建阿里妈妈API请求失败"); + #region 生成自己的淘口令 + var tklInfo = tbAnalysis.FindTKL(activity.ShortUrl, api); + if (tklInfo != null) + { + if (!string.IsNullOrEmpty(title)) + { + title = title.Replace("这个#聚划算团购#宝贝不错:", "").Replace("(分享自@手机淘宝android客户端)", ""); + var temp_url = api.ComposeTbClick(item_id, "https://img.alicdn.com/tfs/TB1MaLKRXXXXXaWXFXXXXXXXXXX-480-260.png", tklInfo.tkl, tklInfo.isoUrl, true, activity.Pid, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品, -1, Class1.Config.CoercePageUrl.Trim());//中间页地址 + e.SendMessage(Class1.Config.CoerceSearchSuccessTip + .Replace("[商品标题]", title) + .Replace("[商品原价]", "未知") + .Replace("[商品主图]", "")//$"[图片 ={tbInfo.ItemImage}]") + .Replace("[月销量]", "未知") + .Replace("[店铺名称]", "未知") + .Replace("[购买中间页地址]", temp_url) + .Replace("[购买淘口令]", tklInfo.tkl) + .Replace("[图片地址]", "") + ); + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + db.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.阿里妈妈, + itemid = item_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = memberTmp.id, + title = title, + adzoneid = activity.Pid.Split('_')[3], + mallid = string.Empty + }).ExecuteCommand(); + + db.UpdateRecord(memberTmp.id); + + var _shared = new Dictionary<string, object>(); + _shared["msg_type"] = "查询宝贝"; + _shared["cps_type"] = CpsType.阿里妈妈; + _shared["msg_username"] = memberTmp.username; + _shared["price"] = "未知"; + _shared["title"] = title; + _shared["coupon_price"] = "未知"; + _shared["user_point"] = "未知"; + _shared["economize"] = "未知"; + + EventClient.OnEvent(sender, new SharedEvents(_shared)); + #endregion + return true; + } + } + #endregion + } + } + } + + if (string.IsNullOrWhiteSpace(keyword) && !string.IsNullOrWhiteSpace(title) && Class1.Config.SearchTitleSwitch_NoCommission == SwitchType.开启) + { + keyword = title; + IsTitle = true; + var searchUrl = api.ComposeTbCms(pid, keyword);//内置的搜索机制 + e.SendMessage(Class1.Config.SearchTitle_NoCommissionTip.Replace("[商品标题]", title).Replace("[购买地址]", ApiClient.ShortURL(searchUrl).Result)); + } + else + e.SendMessage(Class1.Config.SearchNoCommissionTip.Replace("[关键词]", keyword).Replace("[商品标题]", title));//未搜索到提示语 + + db.UpdateRecord(memberTmp.id); + + var shared = new Dictionary<string, object>(); + shared = new Dictionary<string, object>(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.阿里妈妈; + shared["msg_username"] = memberTmp.username; + shared["price"] = "未知"; + shared["title"] = (title ?? keyword) ?? "未知"; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + + return true; + #endregion + } + } + catch (Exception ex) + { + if (Regex.IsMatch(ex.Message, @"sub_msg\"":\""无结果", RegexOptions.IgnoreCase) || ex.Message == "无结果" || Regex.IsMatch(ex.Message, @"sub_msg\"":\""非淘客宝贝", RegexOptions.IgnoreCase)) + { + if (string.IsNullOrWhiteSpace(keyword) && !string.IsNullOrWhiteSpace(title) && Class1.Config.SearchTitleSwitch_NoCommission == SwitchType.开启) + { + keyword = title; + IsTitle = true; + var searchUrl = api.ComposeTbCms(pid, keyword);//内置的搜索机制 + e.SendMessage(Class1.Config.SearchTitle_NoCommissionTip.Replace("[商品标题]", title).Replace("[购买地址]", ApiClient.ShortURL(searchUrl).Result)); + return true; + } + else + { + e.SendMessage(Class1.Config.SearchNoCommissionTip.Replace("[关键词]", keyword).Replace("[商品标题]", title)); + db.UpdateRecord(memberTmp.id); + var shared = new Dictionary<string, object>(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.阿里妈妈; + shared["msg_username"] = memberTmp.username; + shared["price"] = "未知"; + shared["title"] = title ?? keyword; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + return true; + } + } + else //if (ex.Message.Contains("该item_id对应宝贝已下架或非淘客宝贝")) + { + e.SendMessage(Class1.Config?.SearchNoCommissionTip?.Replace("[关键词]", keyword).Replace("[商品标题]", title));//未搜索到提示语 + db.UpdateRecord(memberTmp.id); + var shared = new Dictionary<string, object>(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.阿里妈妈; + shared["msg_username"] = memberTmp?.username; + shared["price"] = "未知"; + shared["title"] = title ?? keyword; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + throw ex; + } + } + } + #endregion + + } + catch (Exception ex) + { + if (ex.Message.StartsWith("@")) + plugin.OnLog($"E :({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message.Replace("@", "")}"); + else + plugin.OnLog($"E:({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message} - {ex.StackTrace}"); + plugin.OnLog(ApiClient.Setting.SystemConfig.msg_error); + } + return false; + } + + + #region 淘礼金相关 + /// <summary> + /// 淘礼金方法 + /// </summary> + /// <param name="member"></param> + /// <returns></returns> + public string TljMethod(fl_member_info member, ref AlimamaApi api, string item_id, double perface) + { + try + { + if (!Class1.Config.TljOnOff) return string.Empty; + if (perface < 1) return string.Empty; + + var session = ApiClient.GetSession(); + + var tljInfos = session.FindTljInfos(); + var tljCreateRecords = session.Find<fl_alimama_tlj_create_record>("select * from fl_alimama_tlj_create_record"); + if (tljInfos != null && tljInfos.Count != 0) + { + var cpsnames1 = tljInfos.Select(f => f.username).ToList(); + var cpsnames2 = tljCreateRecords.Select(f => f.cpsname).ToList(); + for (int i = 0; i < cpsnames1.Count; i++) + { + if (!cpsnames2.Contains(cpsnames1[i])) + { + var tljRecord = new fl_alimama_tlj_create_record() { cpsname = cpsnames1[i], date = DateTime.Now.ToString("yyyyMMdd"), number = 0 }; + tljCreateRecords.Add(session.Saveable(tljRecord).ExecuteReturnEntity()); + } + } + } + List<fl_alimama_tlj_create_record> tljs = null; + if (tljCreateRecords != null) + tljs = tljCreateRecords.Where(f => (f.date == DateTime.Now.ToString("yyyyMMdd") && f.number < 30) || f.date != DateTime.Now.ToString("yyyyMMdd")).ToList(); + + switch (Class1.Config.TljModel) + { + case TLJModel.新人首次查询时使用淘礼金: + { + var incomeResult = session.FindSingle<fl_statistics_record>(@"select * from fl_statistics_record where uid = @userid", new { userid = member.id }); + if (incomeResult == null) + return CreateTljUrl(ref api, tljs, item_id, perface); + } + break; + case TLJModel.首单付款前使用淘礼金: + { + if (member.bind_order == 0) + return CreateTljUrl(ref api, tljs, item_id, perface); + } + break; + case TLJModel.查询随机分配淘礼金: + { + var random = new Random(Guid.NewGuid().GetHashCode()); + var num = random.Next(1, 5000); + if ((1000 < num && num < 1250) || 10 < num && num < 260) + return CreateTljUrl(ref api, tljs, item_id, perface); + } + break; + } + } + catch (Exception ex) + { + + } + return string.Empty; + } + + private readonly object lock_tlj = new object(); + + /// <summary> + /// 创建淘礼金 + /// </summary> + /// <param name="api"></param> + /// <param name="item_id"></param> + /// <param name="image"></param> + /// <returns>返回淘礼金连接</returns> + private string CreateTljUrl(ref AlimamaApi api, List<fl_alimama_tlj_create_record> tljs, string item_id, double perface) + { + try + { + lock (lock_tlj) + { + var session = ApiClient.GetSession(); + + #region 寻找以前创建的并且现在有效的淘礼金 + var _tlj = session.FindTljByItemid(item_id); + if (_tlj != null) + { + var cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == _tlj.cpsname); + if (cps != null) + { + AlimamaApi _api = CpsClient.CreateAlimamaRequest(cps); + if (_api != null) + api = _api; + } + if (_tlj.number == 1) + session.Deleteable<fl_alimama_tlj_get_record>(_tlj).ExecuteCommand(); + else + { + _tlj.number--; + session.SaveOrUpdate(_tlj); + } + return _tlj.url; + } + #endregion + + if (!string.IsNullOrWhiteSpace(Class1.Config.TljItemIds)) + { + var itemids = Class1.Config.TljItemIds.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList(); + if (string.IsNullOrWhiteSpace(itemids.FirstOrDefault(f => f.Trim() == item_id))) + return string.Empty; + } + + if (tljs != null) + { + foreach (var item in tljs) + { + var cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == item.cpsname); + if (cps != null) + { + AlimamaApi _api = CpsClient.CreateAlimamaRequest(cps); + if (_api != null) + { + var tlj = session.FindTljInfos().FirstOrDefault(f => f.username == _api.Member.username); + if (tlj != null) + { + if (string.IsNullOrWhiteSpace(tlj.appkey) || string.IsNullOrWhiteSpace(tlj.appsecret) || string.IsNullOrWhiteSpace(tlj.adzone_pid)) + continue; + + var reg = Regex.Match(tlj.adzone_pid, @"mm_(?<cpsname>\d+)_(?<pid1>\d+)_(?<pid2>\d+)"); + if (!reg.Success) + continue; //throw new Exception($"淘宝推广位格式不正确"); + + var cpsname = reg.Groups["cpsname"].Value; + //var pid1 = reg.Groups["pid1"].Value; + var pid2 = reg.Groups["pid2"].Value; + + var now = DateTime.Now; + var send_end_time = now.AddHours(Class1.Config.TljExpireDate); + + var tljResult = _api.SendTaobao("taobao.tbk.dg.vegas.tlj.create", new { adzone_id = pid2, item_id = item_id, security_switch = "true", total_num = Class1.Config.TljCreateNum, name = Class1.Config.TljName, user_total_win_num_limit = Class1.Config.TljGetLimit, per_face = perface, send_start_time = now.ToString("yyyy-MM-dd HH:mm:ss"), send_end_time = send_end_time.ToString("yyyy-MM-dd HH:mm:ss") }, tlj.appkey, tlj.appsecret); + + if (tljResult != null && tljResult.ContainsKey("success")) + { + if (tljResult["success"].ToString().ToLower() == "false") + { + if (tljResult.ContainsKey("msg_info")) + { + var msg = tljResult["msg_info"].ToString(); + if (msg == "您创建的淘礼金商品数目已达上限") + session.ExcuteSQL("update fl_alimama_tlj_create_record set date = @date ,number = 30 where cpsname = @cpsname", new { date = now.ToString("yyyyMMdd"), cpsname = cpsname }); + //throw new Exception("该淘宝账号ID今日创建淘礼金次数已耗尽"); + } + //throw new Exception(tljResult.ContainsKey("msg_info") ? tljResult["msg_info"].ToString() : $"生成淘礼金失败,{HttpHelper.ObjectToJson(tljResult)}"); + continue; + } + + if (tljResult.ContainsKey("model")) + { + var model = tljResult["model"] as Dictionary<string, object>; + if (model.ContainsKey("send_url")) + { + var send_url = model["send_url"].ToString(); + + #region 统计次数 + session.AddTljCreateNum(cpsname); + #endregion + + #region 将创建的淘礼金保存在数据库中 + if (Class1.Config.TljCreateNum > 1) + { + session.SaveOrUpdate(new fl_alimama_tlj_get_record() { adzoneid = pid2, expiredate = send_end_time, itemid = item_id, number = Class1.Config.TljCreateNum - 1, url = send_url, cpsname = cpsname }); + } + #endregion + + api = _api; + return send_url; + } + } + } + } + } + } + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + #endregion + + + } +} diff --git a/应用/UserFission/AdoptApplyFriendThread.cs b/应用/UserFission/AdoptApplyFriendThread.cs new file mode 100644 index 0000000..2755dbc --- /dev/null +++ b/应用/UserFission/AdoptApplyFriendThread.cs @@ -0,0 +1,82 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Utils; +using Chat.Framework; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using UserFission.Entitys; + +namespace UserFission +{ + class AdoptApplyFriendThread : TimerTask + { + private string user_fission_cache = "user_fission_cache"; + + public override void Run(object state, bool timedOut)//DOTO 这里还有问题,以前留下来的请求token,再次请求会出现未将对象实例化的问题.我将其个这个请求给删除了 + { + try + { + //var session = ApiClient.GetSession(); + //var clients = Chat.Framework.ChatClient.WXClient.Values.Where(f=>f.Status == Chat.Framework.WXSdk.WxStatus.在线).ToList(); + + //var clients = Chat.Framework.ChatClient.WXClient.Values;//获取所有的机器人集合 + //foreach (var item in friends) + //{ + // var client = clients.FirstOrDefault(f => f.User != null && f.WeixinHao == item.robot_name && f.Status == Chat.Framework.WXSdk.WxStatus.在线 && f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信);//获取账号相符、在线类型为Grpc微信的微信, + // if (client != null) + // { + // var values = FindforbidApplyFriendInfos();//获取需要等待的人 + // if (values.FirstOrDefault(f => f == client.WeixinHao) != null) return;//查看缓存中是否存在该机器人 + + // string result = client.AgreeAddMe(HttpHelper.URLDecode(item.token)); + + // if (string.IsNullOrEmpty(result)) + // { + // item.state = "已接受"; + // item.allow_time = DateTime.Now; + // session.Update(item); + // break; + // } + // else + // { + // item.state = "已接受"; + // item.allow_time = DateTime.Now; + // session.Update(item); + // break; + // } + // //由于判断有问题,导致无限请求,暂时先给你注释掉 + // //else if (result == "未将对象实例化") + // //{ + // // session.Delete(item); + // //} + // //else if (result.Contains("操作过于频繁") || result.Contains("不满足指定条件"))//token 不满足指定条件 + // //{ + // // values.Add(client.WeixinHao); + // // ApiClient.Cache.Set(user_fission_cache, values, 60); + // //} + // } + //} + } + catch + { } + } + + /// <summary> + /// 获取缓存 + /// </summary> + /// <returns></returns> + private List<string> FindforbidApplyFriendInfos() + { + var results = ApiClient.Cache.Get<List<string>>(user_fission_cache);//根据KEY、获得缓存 + if (results == null) + { + results = new List<string>(); + ApiClient.Cache.Set(user_fission_cache, results, 60); + } + return results; + } + + } +} diff --git a/应用/UserFission/ApplyFriendThread.cs b/应用/UserFission/ApplyFriendThread.cs new file mode 100644 index 0000000..2b48cf8 --- /dev/null +++ b/应用/UserFission/ApplyFriendThread.cs @@ -0,0 +1,43 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using SqlSugar; +using System.Linq; +using UserFission.Entitys; + +namespace UserFission +{ + class ApplyFriendThread : TimerTask + { + SqlSugarClient session = ApiClient.GetSession(); + public override void Run(object state, bool timedOut) + { + try + { + if (Class1.queue.Count != 0) + { + var id = Class1.queue.Dequeue(); + var friend = session.Find<fl_plugin_userfission_applyfriend_info>("select * from fl_plugin_userfission_applyfriend_info where id = @id", new { id = id }).FirstOrDefault(); + if (friend != null) + { + if (friend != null && friend.state == "已接受") return; + var client = Chat.Framework.ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == friend.robot_name && f.WeixinType == WeixinType.Grpc微信 && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (client != null) + { + string result = client.AgreeAddMe(HttpHelper.URLDecode(friend.token)); + if (string.IsNullOrEmpty(result)) friend.state = "已接受"; + else friend.state = result; + session.Saveable(friend).ExecuteReturnEntity(); + } + } + } + } + catch (System.Exception ex) + { + EventClient.OnEvent(this, "审核新加好友异常:" + ex.Message); + } + } + } +} \ No newline at end of file diff --git a/应用/UserFission/Class1.cs b/应用/UserFission/Class1.cs new file mode 100644 index 0000000..25eacb6 --- /dev/null +++ b/应用/UserFission/Class1.cs @@ -0,0 +1,2304 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.Implement; +using Chat.Framework.WXSdk.IPAD; +using CsharpHttpHelper; +using Newtonsoft.Json; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using UI.Framework.Tools; +using UserFission.Entitys; +using UserFission.Properties; +using System.Text; +using Api.Framework.Utils; + +namespace UserFission +{ + + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.用户分裂; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + public static PickBox pick; + private MainForm mainForm = null; + public static Queue<long> queue = new Queue<long>();//新加好友审核队列 + public static Queue<string> group_queue = new Queue<string>();//新加入群审核队列 + #endregion + + public CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<fl_plugin_userfission_applyfriend_info>()) + { + session.CreateTable<fl_plugin_userfission_applyfriend_info>(); + session.AddIndex<fl_plugin_userfission_applyfriend_info>("robot_name", "new_friend_wxid");//增加索引.以后数据多了.查询速度会比较快 + session.AddUnique<fl_plugin_userfission_applyfriend_info>("robot_name", "new_friend_wxid");//增加唯一约束 + } + if (!session.TableExist<fl_plugin_userfission_invite_record>()) + { + session.CreateTable<fl_plugin_userfission_invite_record>(); + } + if (!session.TableExist<fl_plugin_userfission_user_invitation_code>()) session.CreateTable<fl_plugin_userfission_user_invitation_code>(); + //if (!session.TableExist<fl_plugin_userfission_leadgroup_info>()) + //{ + // session.CreateTable<fl_plugin_userfission_leadgroup_info>(); + // session.AddIndex<fl_plugin_userfission_leadgroup_info>("rid");//增加索引. + // session.AddUnique<fl_plugin_userfission_leadgroup_info>("rid");//增加唯一约束. + //} + if (!session.TableExist<fl_plugin_userfission_automatic_approval_setting>()) + { + session.CreateTable<fl_plugin_userfission_automatic_approval_setting>(); + session.AddIndex<fl_plugin_userfission_automatic_approval_setting>("rid");//增加索引. + session.AddUnique<fl_plugin_userfission_automatic_approval_setting>("rid");//增加唯一约束. + } + if (!session.TableExist<fl_plugin_userfission_superior_reward>()) + { + session.CreateTable<fl_plugin_userfission_superior_reward>(); + session.AddUnique<fl_plugin_userfission_superior_reward>("subordinate_order_totle");//增加唯一约束. + } + if (!session.TableExist<fl_plugin_userfission_fan_notify>()) + { + session.CreateTable<fl_plugin_userfission_fan_notify>(); + session.AddUnique<fl_plugin_userfission_fan_notify>("mid");//增加唯一约束. + } + + if (!session.TableExist<fl_plugin_userfission_extra>()) + { + session.CreateTable<fl_plugin_userfission_extra>(); + session.AddUnique<fl_plugin_userfission_extra>("userid");//增加唯一约束. + } + + #endregion + + //创建配置文件 + Config = this.ReadConfig<Config>(); + + if ((Config.NewUserTipStartTime == DateTime.MinValue) && (!string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_UnFan) || !string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_Coupon) || !string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_UnCoupon) || !string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip))) + { + Config.NewUserTipStartTime = DateTime.Now; + } + + Tools.GetBaseIco(); + pick = new PickBox(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.WXApplyFriendEvent += SDK_WXApplyFriendEvent; + SDK.WXNewFriendEvent += SDK_WXNewFriendEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + SDK.WXNewMemerEvent += SDK_WXNewMemerEvent; + SDK.SharedEvent += SDK_SharedEvent; + + SDK.QQAddMeNeedAuthEvents += SDK_QQAddMeNeedAuthEvents; + SDK.QQNewFriendEvents += SDK_QQNewFriendEvents; + SDK.QQNewGroupMemberEvents += SDK_QQNewGroupMemberEvents; + SDK.QQAddToClusterNeedAuthEvents += SDK_QQAddToClusterNeedAuthEvents; + + //启动软件后,刷新一次数据库数据,防止软件重启部分好友未添加 + Task.Run(() => + { + try + { + Thread.Sleep(1000 * 60 * 4); + + var friends = ApiClient.GetSession().Find<fl_plugin_userfission_applyfriend_info>("select * from fl_plugin_userfission_applyfriend_info where crt_time>@crt_time and state == '待审核'", new { crt_time = DateTime.Now.AddMinutes(-30).ToString("yyyy-MM-dd HH:mm:ss") }).ToList(); + foreach (var item in friends) queue.Enqueue(item.id); + if (friends.Count > 0) ApplyWechatFriend(); + } + catch (Exception) + { } + }, cancellationTokenSource.Token); + + Task.Run(() => + { + do + { + Thread.Sleep(2 * 60 * 1000); + /// <summary> + /// 绑定群上下级的定时器 + /// </summary> + BindGroupInvite(); + } while (!cancellationTokenSource.IsCancellationRequested); + + }, cancellationTokenSource.Token); + + } + catch (Exception ex) + { + this.OnLog("Start = " + ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + cancellationTokenSource.Cancel(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private static readonly object padlock = new object(); + + /// <summary> + /// 记录已经拉群处理的用户id + /// </summary> + private static List<long> userIdlist = new List<long>(); + + /// <summary> + /// 首单奖励 + /// </summary> + private static List<long> sdjl = new List<long>(); + + /// <summary> + /// 订单通知 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.Member != null) + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == e.Member.robot_name).Value; + if (wx != null /*&& wx.WeixinType == WeixinType.Grpc微信*/ && wx.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + //{ + //var price = 0d; + CpsType cpstype = CpsType.阿里妈妈; + long orderid = 0; + var systemOrderStatus = -1; + if (e.Order is fl_order_alimama) + { + var alimama = e.Order as fl_order_alimama; + systemOrderStatus = (int)alimama.db_status; + cpstype = CpsType.阿里妈妈; + orderid = alimama.id; + } + if (e.Order is fl_order_pinduoduo) + { + var pdd = e.Order as fl_order_pinduoduo; + systemOrderStatus = (int)pdd.db_status; + cpstype = CpsType.多多进宝; + orderid = pdd.id; + } + if (e.Order is fl_order_jingdong) + { + var jd = e.Order as fl_order_jingdong; + systemOrderStatus = (int)jd.db_status; + cpstype = CpsType.京东联盟; + orderid = jd.id; + } + if (e.Order is fl_order_douyin) + { + var dy = e.Order as fl_order_douyin; + systemOrderStatus = (int)dy.db_status; + cpstype = CpsType.抖音联盟; + orderid = dy.id; + } + if (e.Order is fl_order_suning) + { + var sn = e.Order as fl_order_suning; + systemOrderStatus = (int)sn.db_status; + cpstype = CpsType.苏宁易购; + orderid = sn.id; + } + + #region 首单奖励 || 分红奖励 + var t1 = Task.Run(() => + { + try + { + #region 新的 + var isIpad = (wx.GetType() == typeof(WXClientImpl_IPAD)); + var session = ApiClient.GetSession(); + var memberinfo = e.Member; + + #region 首单付款额外提示语 + if (e.Customer == null && Config.Extra_FirstPay_Tip_Switch == SwitchType.开启 && systemOrderStatus == 1005 && memberinfo.bind_order == 1) + { + try + { + var robotInfo = session.FindRobotInfo(memberinfo.robot_name, memberinfo.robot_type); + if (robotInfo == null) throw new Exception("找不到对应的机器人账号,首付额外提示操作终止"); + ApiClient.SendMessage(robotInfo, memberinfo.username, Config.Extra_FirstPay_Tip); + } + catch (Exception ex) + { this.OnLog(ex.Message); } + } + + var strb = new StringBuilder(); + strb.AppendLine($"e.Customer == null = {(e.Customer == null ? string.Empty : $"{e.Customer.id}:{e.Customer.usernick}({e.Customer.username})")}"); + strb.AppendLine($"e.Member = {e.Member.id}:{e.Member.usernick}({e.Member.username})"); + strb.AppendLine($"e.Customer == null = {e.Customer == null}"); + strb.AppendLine($"Config.ExtraBonus_SwitchType == SwitchType.开启 = {Config.ExtraBonus_SwitchType == SwitchType.开启}"); + strb.AppendLine($"memberinfo.crt_time.AddHours(Config.ExtraBonus_ValidDay) = {memberinfo.crt_time.AddHours(Config.ExtraBonus_ValidDay)}"); + strb.AppendLine($"DateTime.Now = {DateTime.Now}"); + strb.AppendLine($"memberinfo.crt_time.AddHours(Config.ExtraBonus_ValidDay) >= DateTime.Now = {memberinfo.crt_time.AddHours(Config.ExtraBonus_ValidDay) >= DateTime.Now}"); + strb.AppendLine($"systemOrderStatus = " + systemOrderStatus); + strb.AppendLine($"systemOrderStatus == 1005 = {systemOrderStatus == 1005}"); + strb.AppendLine($"memberinfo.bind_order = {memberinfo.bind_order}"); + strb.AppendLine($"memberinfo.bind_order == 1 = {memberinfo.bind_order == 1}"); + strb.AppendLine($"memberinfo.inviter_id = {memberinfo.inviter_id}"); + strb.AppendLine($"memberinfo.inviter_id != 0 = {memberinfo.inviter_id != 0}"); + LogHelper.GetSingleObj().Debug("....", $"{strb.ToString()}"); + + if (e.Customer == null && Config.ExtraBonus_SwitchType == SwitchType.开启 && memberinfo.crt_time.AddHours(Config.ExtraBonus_ValidDay) >= DateTime.Now && systemOrderStatus == 1005 && memberinfo.bind_order == 1 && memberinfo.inviter_id != 0) + { + try + { + var extra = new fl_plugin_userfission_extra() + { + point = Config.ExtraBonus, + userid = memberinfo.id + }; + session.Insertable(extra).ExecuteCommand(); + } + catch (Exception ex) + { } + } + + #region 上级额外奖励xxx + ////以下为冗余代码,为了实现功能 + //if (e.Customer == null && systemOrderStatus == 1005) + //{ + // var extraTmp = session.Queryable<fl_plugin_userfission_extra>().First(f => f.orderid == orderid && f.cpstype == cpstype); + // if (extraTmp != null) + // { + // try + // { + // var robotInfo = session.FindRobotInfo(memberinfo.robot_name, memberinfo.robot_type); + // if (robotInfo == null) throw new Exception("找不到对应的机器人账号,下级首付款奖励操作终止"); + + // var inviter = session.FindMemberInfoById(memberinfo.inviter_id); + // if (inviter != null) + // { + // var _bonus = extraTmp.point;//奖励金额 + + // if (isIpad && inviter.robot_type == ChatType.微信 && (Config.ExtraBonus_RechargeType == RechargeType.发送红包 || Config.ExtraBonus_RechargeType == RechargeType.微信转账)) + // { + // var passinfo = session.FindWeixinpassword(session.FindRobotInfo(wx.WeixinHao, inviter.robot_type).id);//获取微信支付信息 + // if (passinfo != null && !string.IsNullOrEmpty(passinfo.password)) + // { + // var flag = wx.SendPay(inviter.username, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonus.ToString()), (int)((decimal)_bonus * 100m), passinfo.password, 1, (Config.ExtraBonus_RechargeType == RechargeType.发送红包 ? PayType.红包 : PayType.转账), passinfo.GetBank()); + // if (!string.IsNullOrEmpty(flag)) + // { + // this.OnLog("新人首付款上级奖励失败:" + flag + ",已添加积分到用户余额!");//发送红包不成功,将积分增加余额 + // inviter = session.ChangePoint(PointType.其他奖励, _bonus, inviter.id, $"新人{inviter.usernick}-{inviter.username},首新人首付款上级积分{_bonus}【微信红包操作失败】"); + // } + // } + // else + // { + // this.OnLog("新人首付款上级奖励失败:未设置支付密码,已添加积分到用户余额!"); + // inviter = session.ChangePoint(PointType.其他奖励, _bonus, inviter.id, $"新人{inviter.usernick}-{inviter.username},首付款上级积分{_bonus}【微信红包操作失败,未设置支付密码】"); + // } + // ApiClient.SendMessage(robotInfo, inviter.username, Config.ExtraBonusCompletedTip.Replace("[奖励金额]", _bonus.ToString()).Replace("[剩余积分]", inviter.cur_point.ToString())); + // } + // else if ((inviter.robot_type == ChatType.微信 || inviter.robot_type == ChatType.企业微信) && Config.ExtraBonus_RechargeType == RechargeType.商户付款) + // { + // if (_bonus >= 0.3) + // { + // var ispaid = false; + // object appinfo = null; + // string url = ApiClient.SendWechatPay(new { robot_name = robotInfo.name, robot_nick = robotInfo.nick, username = inviter.username, usernick = inviter.usernick }, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonus.ToString()), _bonus, out ispaid, out appinfo); + // if (!string.IsNullOrEmpty(url)) + // { + // inviter = session.ChangePoint(PointType.其他奖励, _bonus, inviter.id, $"新人首付款上级奖励金额"); + // Thread.Sleep(20); + // inviter = session.ChangePoint(PointType.提现扣除, _bonus, inviter.id, $"新人首付款上级金额【商户付款成功】 商户链接:{url}"); + + // var mess = string.Empty; + // if (ispaid) + // mess = Config.ExtraCommercialEftTip.Replace("[奖励金额]", _bonus.ToString()); + // else + // { + // if (Config.ShangHu_MiNiApp == SwitchType.开启 && appinfo != null) + // mess = Util.GetMiNiAppXml(appinfo, robotInfo.type); + // if (string.IsNullOrWhiteSpace(mess)) + // mess = Config.ExtraBonusCommercialPayTip.Replace("[领取地址]", url/*ApiClient.ShortURL(url).Result*/).Replace("[奖励金额]", _bonus.ToString()); + // } + // ApiClient.SendMessage(robotInfo, inviter.username, mess); + // this.OnLog("商户付款信息 = " + mess); + // } + // else + // { + // this.OnLog("新人首付款上级商户付款失败:获取不到商户付款地址,已添加积分到用户余额!"); + // inviter = session.ChangePoint(PointType.其他奖励, _bonus, inviter.id, $"新人{inviter.usernick}-{inviter.username},首付款上级奖励积分{_bonus}【商户付款操作失败,请求商户链接失败】"); + // ApiClient.SendMessage(robotInfo, inviter.username, Config.ExtraBonusCompletedTip.Replace("[奖励金额]", _bonus.ToString()).Replace("[剩余积分]", inviter.cur_point.ToString())); + // } + // } + // else + // { + // this.OnLog("新人首付款上级商户付款失败:奖励积分小于0.3,已添加积分到用户余额!"); + // inviter = session.ChangePoint(PointType.其他奖励, _bonus, inviter.id, $"新人{inviter.usernick}-{inviter.username},首付款上级奖励积分{_bonus}【商户付款操作失败,积分小于0.3】"); + // ApiClient.SendMessage(robotInfo, inviter.username, Config.ExtraBonusCompletedTip.Replace("[奖励金额]", _bonus.ToString()).Replace("[剩余积分]", inviter.cur_point.ToString())); + // } + // } + // else + // { + // inviter = session.ChangePoint(PointType.其他奖励, _bonus, inviter.id, $"新人{inviter.usernick}-{inviter.username},首付款上级奖励积分{_bonus}【增加积分操作】"); + // ApiClient.SendMessage(robotInfo, inviter.username, Config.ExtraBonusCompletedTip.Replace("[奖励金额]", _bonus.ToString()).Replace("[剩余积分]", inviter.cur_point.ToString())); + // } + // } + // } + // catch (Exception ex) + // { + // this.OnLog("额外奖励:" + ex.Message); + // } + // } + //} + #endregion + + #endregion + + #region 用户首单奖励 + if (e.Customer == null && e.IsRewards) + { + try + { + double _bonus = 0; + + var robotInfo = session.FindRobotInfo(memberinfo.robot_name, memberinfo.robot_type); + if (robotInfo == null) throw new Exception("找不到对应的机器人账号,首单奖励操作终止"); + + if (Config.FirstOrder_Sum2 < Config.FirstOrder_Sum1) throw new Exception("新用户首单奖励积分设置数据异常,最大奖励值应大于最小值"); + + _bonus = Math.Round(( + new Random().Next( + int.Parse(Math.Round(Config.FirstOrder_Sum1 * 100, 2).ToString()), + int.Parse(Math.Round((Config.FirstOrder_Sum2 + 0.01) * 100, 2).ToString()) + )) / 100d, 2); + + if (isIpad && memberinfo.robot_type == ChatType.微信 && (Config.FirstOrder_RechargeType == RechargeType.发送红包 || Config.FirstOrder_RechargeType == RechargeType.微信转账)) + { + var passinfo = session.FindWeixinpassword(session.FindRobotInfo(wx.WeixinHao, memberinfo.robot_type).id);//获取微信支付信息 + if (passinfo != null && !string.IsNullOrEmpty(passinfo.password)) + { + var flag = wx.SendPay(memberinfo.username, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonus.ToString()), (int)((decimal)_bonus * 100m), passinfo.password, 1, (Config.FirstOrder_RechargeType == RechargeType.发送红包 ? PayType.红包 : PayType.转账), passinfo.GetBank()); + if (!string.IsNullOrEmpty(flag)) + { + this.OnLog($"新人首单奖励失败:" + flag + ",已添加积分到用户余额!");//发送红包不成功,将积分增加余额 + memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, memberinfo.id, $"新人{memberinfo.usernick}-{memberinfo.username},首单奖励积分{_bonus}【微信红包操作失败】"); + } + } + else + { + this.OnLog($"新人首单奖励失败:未设置支付密码,已添加积分到用户余额!"); + memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, memberinfo.id, $"新人{memberinfo.usernick}-{memberinfo.username},首单奖励积分{_bonus}【微信红包操作失败,未设置支付密码】"); + } + ApiClient.SendMessage(robotInfo, memberinfo.username, Class1.Config.NewUserFirstOrderCompletedTip.Replace("[首单奖励金额]", _bonus.ToString()).Replace("[剩余积分]", memberinfo.cur_point.ToString())); + } + else if ((memberinfo.robot_type == ChatType.微信 || memberinfo.robot_type == ChatType.企业微信) && Config.FirstOrder_RechargeType == RechargeType.商户付款) + { + if (_bonus >= 0.3) + { + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay(new { robot_name = robotInfo.name, robot_nick = robotInfo.nick, username = memberinfo.username, usernick = memberinfo.usernick }, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonus.ToString()), _bonus, out ispaid, out appinfo); + if (!string.IsNullOrEmpty(url)) + { + memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, memberinfo.id, $"首单奖励金额"); + Thread.Sleep(20); + memberinfo = session.ChangePoint(PointType.提现扣除, _bonus, memberinfo.id, $"首单金额【商户付款成功】 商户链接:{url}"); + + var mess = string.Empty; + if (ispaid) + mess = Config.FirstOrder_CommercialEftTip.Replace("[首单奖励金额]", _bonus.ToString()); + else + { + if (Config.ShangHu_MiNiApp == SwitchType.开启 && appinfo != null) + mess = Util.GetMiNiAppXml(appinfo, robotInfo.type); + if (string.IsNullOrWhiteSpace(mess)) + mess = Config.FirstOrder_CommercialPayTip.Replace("[领取地址]", url/*ApiClient.ShortURL(url).Result*/).Replace("[首单奖励金额]", _bonus.ToString()); + } + ApiClient.SendMessage(robotInfo, memberinfo.username, mess); + this.OnLog("商户付款信息 = " + mess); + } + else + { + this.OnLog($"新人首单商户付款失败:获取不到商户付款地址,已添加积分到用户余额!"); + memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, memberinfo.id, $"新人{memberinfo.usernick}-{memberinfo.username},首单奖励积分{_bonus}【商户付款操作失败,请求商户链接失败】"); + ApiClient.SendMessage(robotInfo, memberinfo.username, Class1.Config.NewUserFirstOrderCompletedTip.Replace("[首单奖励金额]", _bonus.ToString()).Replace("[剩余积分]", memberinfo.cur_point.ToString())); + } + } + else + { + this.OnLog($"新人首单商户付款失败:奖励积分小于0.3,已添加积分到用户余额!"); + memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, memberinfo.id, $"新人{memberinfo.usernick}-{memberinfo.username},首单奖励积分{_bonus}【商户付款操作失败,积分小于0.3】"); + ApiClient.SendMessage(robotInfo, memberinfo.username, Config.NewUserFirstOrderCompletedTip.Replace("[首单奖励金额]", _bonus.ToString()).Replace("[剩余积分]", memberinfo.cur_point.ToString())); + } + } + else + { + memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, memberinfo.id, $"新人{memberinfo.usernick}-{memberinfo.username},首单奖励积分{_bonus}【增加积分操作】"); + ApiClient.SendMessage(robotInfo, memberinfo.username, Config.NewUserFirstOrderCompletedTip.Replace("[首单奖励金额]", _bonus.ToString()).Replace("[剩余积分]", memberinfo.cur_point.ToString())); + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} _ {ex.StackTrace}"); + } + } + #endregion + + #region 下级用户订单结算,统计下级用户订单是否满足条件(付款金额/订单数量),满足奖励上级(分红) + try + { + if (e.Customer == null && systemOrderStatus == 1002) + { + var rewards = Tools.FindRewards(); + var reward = rewards.FirstOrDefault(f => f.subordinate_order_totle == e.Member.finish_order); + if (reward != null && memberinfo.inviter_id != 0 && memberinfo.inviter_id != memberinfo.id) + { + var presenter_memberinfo = session.FindMemberInfoById(memberinfo.inviter_id); + if (presenter_memberinfo == null) throw new Exception("找不到对应的上级信息,分红奖励操作终止"); + var robotInfo = session.FindRobots().FirstOrDefault(f => f.name == presenter_memberinfo.robot_name && f.type == presenter_memberinfo.robot_type); + if (robotInfo == null) throw new Exception("找不到对应的机器人账号,分红奖励操作终止"); + + var _bonus = reward.superior_point_reward; + if (isIpad && robotInfo.type == ChatType.微信 && (Config.Superior_DividendType == RechargeType.发送红包 || Config.Superior_DividendType == RechargeType.微信转账)) + { + var passinfo = session.FindWeixinpassword(session.FindRobotInfo(robotInfo.name, robotInfo.type).id);//获取微信支付信息 + if (passinfo != null && !string.IsNullOrEmpty(passinfo.password)) + { + var flag = wx.SendPay(presenter_memberinfo.username, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonus.ToString()), (int)((decimal)_bonus * 100m), passinfo.password, 1, (Config.Superior_DividendType == RechargeType.发送红包 ? PayType.红包 : PayType.转账), passinfo.GetBank()); + if (!string.IsNullOrEmpty(flag)) + { + this.OnLog("分红奖励失败:" + flag + ",已添加积分到用户余额!");//发送红包不成功,将积分增加余额 + presenter_memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, presenter_memberinfo.id, $"分红奖励积分{_bonus}【微信红包操作失败】"); + } + } + else + { + this.OnLog("分红奖励失败:未设置支付密码,已添加积分到用户余额!"); + presenter_memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, presenter_memberinfo.id, $"分红奖励积分{_bonus}【微信红包操作失败,未设置支付密码】"); + } + ApiClient.SendMessage(robotInfo, presenter_memberinfo.username, Config.SuperiorDividendPayTip.Replace("[下级有效订单数]", reward.subordinate_order_totle.ToString()).Replace("[分红奖励金额]", _bonus.ToString()).Replace("[下级昵称]", memberinfo.realnick).Replace("[剩余积分]", presenter_memberinfo.cur_point.ToString())); + } + else if ((presenter_memberinfo.robot_type == ChatType.微信 || presenter_memberinfo.robot_type == ChatType.企业微信) && Config.Superior_DividendType == RechargeType.商户付款) + { + if (_bonus >= 0.3) + { + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay(new { robot_name = robotInfo.name, robot_nick = robotInfo.nick, username = presenter_memberinfo.username, usernick = presenter_memberinfo.usernick }, Class1.Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonus.ToString()), _bonus, out ispaid, out appinfo); + if (!string.IsNullOrEmpty(url)) + { + presenter_memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, presenter_memberinfo.id, $"分红奖励积分{_bonus}"); + Thread.Sleep(20); + presenter_memberinfo = session.ChangePoint(PointType.提现扣除, _bonus, presenter_memberinfo.id, $"分红奖励【商户付款成功】 商户链接:{url}"); + + var _mess = string.Empty; + if (ispaid) + _mess = Config.SuperiorDividendCommercialEftTip.Replace("[下级有效订单数]", reward.subordinate_order_totle.ToString()).Replace("[分红奖励金额]", _bonus.ToString()).Replace("[下级昵称]", memberinfo.realnick); + else + { + if (Config.ShangHu_MiNiApp == SwitchType.开启 && appinfo != null) + _mess = Util.GetMiNiAppXml(appinfo, robotInfo.type); + if (string.IsNullOrWhiteSpace(_mess)) + _mess = Config.SuperiorDividendCommercialPayTip.Replace("[下级有效订单数]", reward.subordinate_order_totle.ToString()).Replace("[领取地址]", url).Replace("[分红奖励金额]", _bonus.ToString()).Replace("[下级昵称]", memberinfo.realnick); + } + ApiClient.SendMessage(robotInfo, presenter_memberinfo.username, _mess); + this.OnLog("商户付款信息= " + _mess); + } + else + { + this.OnLog("分红奖励商户付款失败:获取不到商户付款地址,已添加积分到用户余额!"); + presenter_memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, presenter_memberinfo.id, $"分红奖励积分{_bonus}【商户付款操作失败,请求商户链接失败】"); + ApiClient.SendMessage(robotInfo, presenter_memberinfo.username, Config.SuperiorDividendPayTip.Replace("[下级有效订单数]", reward.subordinate_order_totle.ToString()).Replace("[下级昵称]", memberinfo.realnick).Replace("[分红奖励金额]", _bonus.ToString()).Replace("[剩余积分]", presenter_memberinfo.cur_point.ToString())); + } + } + else + { + this.OnLog("分红奖励商户付款失败:奖励积分小于0.3,已添加积分到用户余额!"); + presenter_memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, presenter_memberinfo.id, $"分红奖励积分{_bonus}【商户付款操作失败,积分小于0.3】"); + ApiClient.SendMessage(robotInfo, presenter_memberinfo.username, Config.SuperiorDividendPayTip.Replace("[下级有效订单数]", reward.subordinate_order_totle.ToString()).Replace("[下级昵称]", memberinfo.realnick).Replace("[分红奖励金额]", _bonus.ToString()).Replace("[剩余积分]", presenter_memberinfo.cur_point.ToString())); + } + } + else + { + presenter_memberinfo = session.ChangePoint(PointType.其他奖励, _bonus, presenter_memberinfo.id, $"分红奖励积分{_bonus}【增加积分操作】"); + ApiClient.SendMessage(robotInfo, presenter_memberinfo.username, Config.SuperiorDividendPayTip.Replace("[下级有效订单数]", reward.subordinate_order_totle.ToString()).Replace("[下级昵称]", memberinfo.realnick).Replace("[分红奖励金额]", _bonus.ToString()).Replace("[剩余积分]", presenter_memberinfo.cur_point.ToString())); + } + } + } + } + catch (Exception ex) + { + this.OnLog($"推荐者分红奖励异常:{ex.Message} - {ex.StackTrace}"); + } + #endregion + + #region 奖励开关开启,并且为新人完成首单奖励,并且用户有完成订单记录(推荐者奖励) + if (e.Customer != null && e.IsRewards) + { + var inviter = e.Member; + if (inviter == null) throw new Exception("上级奖励错误:上级用户数据不存在"); + + var member = e.Customer; + + if (Config.SuperiorSum2 < Config.SuperiorSum1) throw new Exception("上级奖励积分设置数据异常,最大奖励值应大于最小值"); + var remark = string.Empty; + try + { + var robotInfo = session.FindRobotInfo(inviter.robot_name, inviter.robot_type); + if (robotInfo == null) throw new Exception("找不到对应的机器人账号,上级奖励操作终止"); + + if (IsSuperiorReward(robotInfo)) + { + var _bonusSuperior = 0d; + + var extra = session.FindSingle<fl_plugin_userfission_extra>("select * from fl_plugin_userfission_extra where userid = @userid", new { userid = e.Customer.id }); + if (extra != null)//按默认的奖励执行 + { + _bonusSuperior = extra.point; + remark = "额外奖励"; + } + else + _bonusSuperior = Math.Round(( + new Random().Next( + int.Parse(Math.Round(Config.SuperiorSum1 * 100, 2).ToString()), + int.Parse(Math.Round((Config.SuperiorSum2 + 0.01) * 100, 2).ToString()) + )) / 100d, 2); + + if (isIpad && inviter.robot_type == ChatType.微信 && (Config.Superior_RechargeType == RechargeType.发送红包 || Config.Superior_RechargeType == RechargeType.微信转账)) + { + var passinfo = session.FindWeixinpassword(session.FindRobotInfo(wx.WeixinHao, ChatType.微信).id);//获取微信支付信息 + if (passinfo != null && !string.IsNullOrEmpty(passinfo.password)) + { + var flag = wx.SendPay(inviter.username, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonusSuperior.ToString()), (int)((decimal)_bonusSuperior * 100m), passinfo.password, 1, (Config.Superior_RechargeType == RechargeType.发送红包 ? PayType.红包 : PayType.转账), passinfo.GetBank()); + if (!string.IsNullOrEmpty(flag)) + { + this.OnLog($"推荐新人首单{remark}奖励失败:" + flag + ",已添加积分到用户余额!");//发送红包不成功,将积分增加余额 + inviter = session.ChangePoint(PointType.其他奖励, _bonusSuperior, inviter.id, $"推荐新人{member.usernick}-{member.username},首单{remark}奖励积分{_bonusSuperior}【微信红包操作失败】"); + } + } + else + { + this.OnLog($"推荐新人首单{remark}奖励失败:未设置支付密码,已添加积分到用户余额!"); + inviter = session.ChangePoint(PointType.其他奖励, _bonusSuperior, inviter.id, $"推荐新人{member.usernick}-{member.username},首单{remark}奖励积分{_bonusSuperior}【微信红包操作失败,未设置支付密码】"); + } + ApiClient.SendMessage(robotInfo, inviter.username, Class1.Config.ImmediateReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", inviter.cur_point.ToString())); + } + else if ((inviter.robot_type == ChatType.微信 || inviter.robot_type == ChatType.企业微信) && Config.Superior_RechargeType == RechargeType.商户付款) + { + if (_bonusSuperior >= 0.3) + { + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay(new { robot_name = robotInfo.name, robot_nick = robotInfo.nick, username = inviter.username, usernick = inviter.usernick }, Class1.Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonusSuperior.ToString()), _bonusSuperior, out ispaid, out appinfo); + if (!string.IsNullOrEmpty(url)) + { + inviter = session.ChangePoint(PointType.其他奖励, _bonusSuperior, inviter.id, $"推荐新人{member.usernick}-{member.username},首单{remark}奖励积分{_bonusSuperior}"); + Thread.Sleep(20); + inviter = session.ChangePoint(PointType.提现扣除, _bonusSuperior, inviter.id, $"推荐新人{member.usernick}-{member.username},首单{remark}奖励积分{_bonusSuperior}【商户付款成功】 商户链接:{url}"); + + var mess = string.Empty; + if (ispaid) + mess = Config.SuperiorCommercialEftTip.Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[下级昵称]", e.Customer.realnick); + else + { + if (Config.ShangHu_MiNiApp == SwitchType.开启 && appinfo != null) + mess = Util.GetMiNiAppXml(appinfo, robotInfo.type); + if (string.IsNullOrWhiteSpace(mess)) + mess = Config.SuperiorCommercialPayTip.Replace("[领取地址]", url/* ApiClient.ShortURL(url).Result*/).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[下级昵称]", e.Customer.realnick); + } + ApiClient.SendMessage(robotInfo, inviter.username, mess); + this.OnLog("商户付款信息 = " + mess); + } + else + { + this.OnLog($"推荐新人首单{remark}商户付款失败:获取不到商户付款地址,已添加积分到用户余额!"); + inviter = session.ChangePoint(PointType.其他奖励, _bonusSuperior, inviter.id, $"推荐新人{member.usernick}-{member.username},首单{remark}奖励积分{_bonusSuperior}【商户付款操作失败,请求商户链接失败】"); + ApiClient.SendMessage(robotInfo, inviter.username, Class1.Config.ImmediateReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", inviter.cur_point.ToString())); + } + } + else + { + this.OnLog($"推荐新人首单{remark}商户付款失败:奖励积分小于0.3,已添加积分到用户余额!"); + inviter = session.ChangePoint(PointType.其他奖励, _bonusSuperior, inviter.id, $"推荐新人{member.usernick}-{member.username},首单{remark}奖励积分{_bonusSuperior}【商户付款操作失败,积分小于0.3】"); + ApiClient.SendMessage(robotInfo, inviter.username, Class1.Config.ImmediateReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", inviter.cur_point.ToString())); + } + } + else + { + inviter = session.ChangePoint(PointType.其他奖励, _bonusSuperior, inviter.id, $"推荐新人{member.usernick}-{member.username},首单{remark}奖励积分{_bonusSuperior}【增加积分操作】"); + ApiClient.SendMessage(robotInfo, inviter.username, Class1.Config.ImmediateReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", inviter.cur_point.ToString())); + } + } + } + catch (Exception ex) + { + this.OnLog($"{remark} - {ex.Message} - {ex.StackTrace}"); + } + } + #endregion + + #endregion + } + catch (Exception ex) + { + this.OnLog($"用户首单奖励/新手完成首单奖励异常:{ex.Message} - {ex.StackTrace}"); + } + }); + #endregion + + #region 完成订单将用户拉入群操作 + var t2 = Task.Run(() => + { + try + { + if (Config.InvitedIntoGroupSwitch == SwitchType.关闭) return; + if (!Config.InvitegroupWay) return; + if (e.Member.finish_order < Config.FinishOrder_Rule) return;//没有满足设置的订单数 + if (Config.InviteGroupInfo2 == null || Config.InviteGroupInfo2.Count == 0) return; + if (userIdlist.Contains(e.Member.id)) return; + var groupInfo = Config.InviteGroupInfo2.Where(f => f.Key == wx.WeixinHao && !f.Value.onoff && f.Value.groupInfos.Count != 0); + if (groupInfo == null) return; + //查询的对象不为空 并且 自动拉进群的操作非禁用 && f.WeixinType == WeixinType.Grpc微信 + var wxBase = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == wx.WeixinHao && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wxBase == null) return; + var session = ApiClient.GetSession(); + if (Config.InviteGroupInfo2.ContainsKey(wx.WeixinHao) && Config.InviteGroupInfo2[wx.WeixinHao].groupInfos.Count != 0) + { + var robotInfo = session.FindRobots().FirstOrDefault(f => f.name == e.Member.robot_name && f.type == e.Member.robot_type); + if (robotInfo == null) throw new Exception("找不到对应的机器人账号,拉群操作终止"); + + var groupIds = Config.InviteGroupInfo2[wx.WeixinHao].groupInfos; + foreach (var groupId in groupIds) + { + lock (padlock) + { + if (!userIdlist.Contains(e.Member.id)) + userIdlist.Add(e.Member.id); + if (wx.GetType() == typeof(WXClientImpl_QYHOOK)) + { + var result = session.FindSingle<fl_plugin_userfission_invite_record>("username = @username and groupid = @groupid", new { username = e.Member.username, groupid = groupId.Key }); + if (result != null) return; + + ApiClient.SendMessage(robotInfo, e.Member.username, Config.InvitedIntoGroupTip.Replace("[账号]", e.Member.username).Replace("[昵称]", e.Member.usernick)); + wx.InviteIntoGroup(e.Member.username, groupId.Key); + } + else + { + var group = wx.GetContact(groupId.Key); + if (group == null) continue; + var result = session.FindSingle<fl_plugin_userfission_invite_record>("username = @username and groupid = @groupid", new { username = e.Member.username, groupid = group.UserName }); + if (result != null) return; + //该用户不在群内 并且 没有给用户发送过邀请入群卡片 + if (!group.ExtInfo.Contains(e.Member.username)) + { + wx.InviteIntoGroup(e.Member.username, group.UserName); + ApiClient.SendMessage(robotInfo, e.Member.username, new VariateReplace().CommonReplace(Config.InvitedIntoGroupTip, e.Member, robotInfo)); + } + } + var _result = new fl_plugin_userfission_invite_record() { groupid = groupId.Key, username = e.Member.username }; + session.Insertable(_result).ExecuteCommand(); + } + break; + } + } + } + catch (Exception ex) + { + this.OnLog($"用户拉入群操作失败:{ex.Message} - {ex.StackTrace}"); + } + }); + #endregion + + //} + } + } + } + catch (Exception ex) + { + this.OnLog("OrderNotice = " + ex.Message); + } + } + + #region QQ + + #region QQ - 申请添加我为好友,需要审核 + private void SDK_QQAddMeNeedAuthEvents(object sender, Chat.Framework.QQSdk.Events.QQAddMeNeedAuthEvents e) + { + try + { + var friend = ApiClient.GetSession().FindSingle<fl_plugin_userfission_applyfriend_info>("new_friend_wxid = @new_friend_wxid and robot_name = @robot_name", new { new_friend_wxid = e.QQ.ToString(), robot_name = e.QQBase.QQ.ToString() }); + if (friend != null && friend.state == "已接受") return; + + if (friend == null) + { + friend = new fl_plugin_userfission_applyfriend_info() + { + state = "待审核", + crt_time = DateTime.Parse(e.CrtTime.ToString("yyyy-MM-dd HH:mm:ss")), + message = e.Message.Trim(), + robot_name = e.QQBase.QQ.ToString(), + user_nick = e.Nickname, + new_friend_nick = e.Nickname, + new_friend_wxid = e.QQ.ToString(), + old_friend_nick = string.Empty, + old_friend_wxid = string.Empty + }; + friend.id = ApiClient.GetSession().Insertable<fl_plugin_userfission_applyfriend_info>(friend).ExecuteReturnIdentity(); + } + + if (Config.QQ_Accept == SwitchType.开启) + { + var id = ApiClient.GetSession().FindRobotInfo(e.QQBase.QQ.ToString(), ChatType.QQ).id; + var aas = ApiClient.GetSession().FindSingle<fl_plugin_userfission_automatic_approval_setting>("rid = @rid", new { rid = id }); + if (aas != null && aas.onoff) return; + + if (!queue.Contains(friend.id)) + { + queue.Enqueue(friend.id); + QQApplyWechatFriend(); + } + } + } + catch (Exception ex) + { + this.OnLog("新人申请处理 = " + ex.Message); + } + } + + private List<string> qqwelcomeTip_Friends = new List<string>(); + + private bool IsApplyQQ = false; + private void QQApplyWechatFriend() + { + if (IsApplyQQ) return; + IsApplyQQ = true; + Task.Run(() => + { + try + { + //var session = ApiClient.GetSession(); + do + { + var apply_id = queue.Dequeue(); + var friend = ApiClient.GetSession().FindSingle<fl_plugin_userfission_applyfriend_info>("id = @id", new { id = apply_id }); + if (friend != null) + { + Thread.Sleep(Config.QQ_Retardation * 1000); + if (friend != null && friend.state == "已接受") continue; + var client = ChatClient.QQClients.Values.FirstOrDefault(f => f.IsLogin && f.QQ.ToString() == friend.robot_name); + if (client != null) + { + client.AerifyAddMe(uint.Parse(friend.new_friend_wxid), 3); + friend.state = "已接受"; + friend.allow_time = DateTime.Now; + ApiClient.GetSession().Saveable(friend).ExecuteReturnEntity(); + + var robot = ApiClient.GetSession().FindRobotInfo(friend.robot_name, ChatType.QQ, true); + if (robot == null) continue; + var member = ApiClient.GetSession().FindSingle<fl_member_info>("select * from fl_member_info where robot_type = @robot_type and username = @username", new { username = friend.new_friend_wxid, robot_type = ChatType.QQ }); + if (member == null) + { + member = new fl_member_info() { crt_time = DateTime.Now, usernick = string.Empty, robot_name = friend.robot_name, robot_type = ChatType.QQ, username = friend.new_friend_wxid, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + var groups = ApiClient.GetSession().FindGroups(); + if (groups.Count != 0) + member.group_id = groups[0].id; + ApiClient.GetSession().SaveOrUpdate(member); + } + ApiClient.SendMessage(robot, friend.new_friend_wxid, new VariateReplace().CommonReplace(Config.QQ_WelcomeTip, member)); + } + } + } while (true); + } + catch (Exception) + { + } + finally + { + IsApplyQQ = false; + } + }); + } + #endregion + + #region QQ - 新增QQ好友 + private void SDK_QQNewFriendEvents(object sender, Chat.Framework.QQSdk.Events.QQNewFriendEvents e) + { + try + { + //fl_plugin_userfission_applyfriend_info friend = null; + //var session = ApiClient.GetSession(); + //var robot = session.FindRobotInfo(e.QQClient.QQ.ToString(), ChatType.QQ); + //if (robot != null) + //{ + // Thread.Sleep(1100); + // lock (lock_newfriend) + // { + // if (!qqwelcomeTip_Friends.Contains(e.QQ.ToString())) + // { + // friend = session.Queryable<fl_plugin_userfission_applyfriend_info>().First(f => f.new_friend_wxid == e.QQ.ToString() && f.robot_name == e.QQClient.QQ.ToString()); + + // #region 将表fl_plugin_userfission_applyfriend_info中的请求状态改成 "已接受" + // if (friend != null && friend.state != "已接受") + // { + // friend.state = "已接受"; + // session.Saveable(friend).ExecuteReturnEntity(); + // } + // #endregion + + // if (qqwelcomeTip_Friends.Count > 10000) qqwelcomeTip_Friends.Clear(); + // qqwelcomeTip_Friends.Add(e.QQ.ToString()); + + // var member = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username and robot_type = @robot_type", new { username = e.QQ.ToString(), robot_type = ChatType.QQ }); + // if (member == null) + // { + // member = new fl_member_info() { crt_time = DateTime.Now, usernick = e.Nickname, robot_name = e.QQClient.QQ.ToString(), robot_type = ChatType.QQ, username = e.QQ.ToString(), alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + // var groups = session.FindGroups(); + // if (groups.Count != 0) + // member.group_id = groups[0].id; + // session.SaveOrUpdate(member); + // } + // ApiClient.SendMessage(robot, e.QQ.ToString(), Config.QQ_WelcomeTip).Wait(); + // } + // } + //} + } + catch (Exception ex) + { + this.OnLog("NewMemer = " + ex.Message); + } + } + #endregion + + #region QQ群添加新用户 + private void SDK_QQAddToClusterNeedAuthEvents(object sender, Chat.Framework.QQSdk.Events.QQAddToClusterNeedAuthEvents e) + { + try + { + if (Config.QQ_AcceptGroupApplyForSwitch == SwitchType.开启) + { + var session = ApiClient.GetSession(); + var id = session.FindRobotInfo(e.QQBase.QQ.ToString(), ChatType.QQ).id; + var aas = session.FindSingle<fl_plugin_userfission_automatic_approval_setting>("rid = @rid", new { rid = id }); + if (aas != null && aas.onoff) return; + + if (!group_queue.Contains(e.ClusterId + "_" + e.QQ + "_" + e.QQBase.QQ)) + { + group_queue.Enqueue(e.ClusterId + "_" + e.QQ + "_" + e.QQBase.QQ); + QQApplyWechatGroup(); + } + } + } + catch (Exception ex) + { + this.OnLog(" " + ex.Message); + } + } + + private bool IsApplyGroupQQ = false; + private void QQApplyWechatGroup() + { + if (IsApplyGroupQQ) return; + IsApplyGroupQQ = true; + Task.Run(() => + { + try + { + var session = ApiClient.GetSession(); + do + { + var value = group_queue.Dequeue(); + var strs = value.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + if (strs.Length == 3) + { + Thread.Sleep(Config.QQ_RetardationAcceptGroup * 1000); + var client = ChatClient.QQClients.Values.FirstOrDefault(f => f.IsLogin && f.QQ.ToString() == strs[2]); + if (client != null) + { + client.AerifyAddGroup(uint.Parse(strs[0]), uint.Parse(strs[1])); + } + } + } while (true); + } + catch (Exception) + { } + finally + { + IsApplyGroupQQ = false; + } + }); + } + #endregion + + #region QQ - 新成员进群 + private void SDK_QQNewGroupMemberEvents(object sender, Chat.Framework.QQSdk.Events.QQNewGroupMemberEvents e) + { + try + { + if (!string.IsNullOrWhiteSpace(Config.QQ_GroupWelcomeTip)) + { + e.QQBase.SendGroupMessage(e.GroupId, Config.QQ_GroupWelcomeTip.Replace("[群昵称]", e.GroupName).Replace("[昵称]", e.NewFriendNick).Replace("[账号]", e.NewFriendQQ.ToString())); + } + + #region 用户是被用户邀请进群,绑定上级 + if (e.InviteQQ != 0 && Config.QQInviteBindSwitch == SwitchType.开启) + { + var session = ApiClient.GetSession(); + var invite_member = session.FindSingle<fl_member_info>("select * from fl_member_info where robot_type = @robot_type and username = @username", new { username = e.InviteQQ, robot_type = ChatType.QQ }); + if (invite_member == null) + { + invite_member = new fl_member_info() { crt_time = DateTime.Now, usernick = string.Empty, robot_name = e.QQBase.QQ.ToString(), robot_type = ChatType.QQ, username = e.InviteQQ.ToString(), alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + var groups = session.FindGroups(); + if (groups.Count != 0) + invite_member.group_id = groups[0].id; + session.SaveOrUpdate(invite_member); + } + var robot = session.FindRobots().FirstOrDefault(f => f.type == invite_member.robot_type && f.name == invite_member.robot_name); + if (robot == null) throw new Exception("上级用户对应的机器人数据异常"); + + var new_member = session.FindSingle<fl_member_info>("robot_type = @robot_type and username = @username", new { robot_type = ChatType.QQ, username = e.NewFriendQQ.ToString() }); + if (new_member == null) + { + new_member = new fl_member_info() { crt_time = DateTime.Now, usernick = e.NewFriendNick, robot_name = e.QQBase.QQ.ToString(), robot_type = ChatType.QQ, username = e.NewFriendQQ.ToString(), alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + var groups = session.FindGroups(); + if (groups.Count != 0) + new_member.group_id = groups[0].id; + session.SaveOrUpdate(new_member); + } + if (new_member.inviter_id != 0) return; + else + { + new_member.inviter_id = invite_member.id; + session.SaveOrUpdate(new_member); + + ApiClient.SendMessage(robot, e.InviteQQ.ToString(), Config.QQGroupInviteBind_AddANewSubordinateTip + .Replace("[账号]", e.NewFriendQQ.ToString()) + .Replace("[昵称]", e.NewFriendNick) + .Replace("[群昵称]", e.GroupName) + .Replace("[群账号]", e.GroupId.ToString()) + .Replace("[剩余积分]", invite_member.cur_point.ToString("0.00"))); + } + + } + #endregion + + } + catch (Exception ex) + { + this.OnLog("QQNewGroupMember = " + ex.Message); + } + } + #endregion + + #endregion + + #region 微信 + private void SDK_SharedEvent(object sender, SharedEvents e) + { + try + { + if (e.Shareds != null && e.Shareds.ContainsKey("msg_type") && e.Shareds["msg_type"].ToString() == "查询宝贝" && ((Config.SubordinateSumSwitch == SwitchType.开启 && Config.SubordinateRewardWay == NewcomerAwardType.首次查券奖励) || !string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip) || !string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_UnFan) || !string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_Coupon) || !string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_UnCoupon))) + { + var session = ApiClient.GetSession(); + var username = e.Shareds["msg_username"].ToString(); + var member = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = username }); + if (member == null) return; + var incomeResult = session.FindSingle<fl_statistics_record>(@"select * from fl_statistics_record where uid = @userid and querynum = 1", new { userid = member.id }); + if (incomeResult != null) + { + if (member.bind_order != 0 || member.finish_order != 0) return; + var orderCount = 0; + orderCount += session.Find<fl_order_alimama>("select * from fl_order_alimama where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0) + { + orderCount += session.Find<fl_order_jingdong>("select * from fl_order_jingdong where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0) + orderCount += session.Find<fl_order_pinduoduo>("select * from fl_order_pinduoduo where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0) + orderCount += session.Find<fl_order_douyin>("select * from fl_order_douyin where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0) + orderCount += session.Find<fl_order_weipinhui>("select * from fl_order_weipinhui where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0) + orderCount += session.Find<fl_order_douyin>("select * from fl_order_douyin where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0) + orderCount += session.Find<fl_order_suning>("select * from fl_order_suning where db_userid = @db_userid", new { db_userid = member.id }).Count; + } + if (orderCount != 0) return; + + if (Config.SubordinateSumSwitch == SwitchType.开启 && Config.SubordinateRewardWay == NewcomerAwardType.首次查券奖励) + { + try + { + if (Config.SubordinateSum2 < Config.SubordinateSum1) throw new Exception("新用户奖励积分设置数据异常,最大奖励值应大于最小值"); + + var robots = session.FindRobots(); + var robot = robots.FirstOrDefault(f => f.type == member.robot_type && f.name == member.robot_name); + if (robot == null) throw new Exception("用户对应的机器人信息异常"); + + var wxBase = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot.name && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wxBase == null) return; + + NewFriendRewards(wxBase, member, robot, e); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + + } + + if (!string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip)) + { + try + { + var robots = session.FindRobots(); + var robot = robots.FirstOrDefault(f => f.type == member.robot_type && f.name == member.robot_name); + if (robot == null) throw new Exception("用户对应的机器人信息异常"); + + var wxBase = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot.name && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wxBase == null) return; + var price = e.Shareds["price"].ToString(); + var title = e.Shareds["title"].ToString(); + var coupon_price = e.Shareds["coupon_price"].ToString(); + var user_point = e.Shareds["user_point"].ToString(); + var economize = e.Shareds["economize"].ToString(); + + wxBase.SendMessage(username, Config.FirstQueryGoodsTip.Replace("[商品原价]", price).Replace("[商品标题]", title).Replace("[优惠券金额]", coupon_price).Replace("[用户佣金]", user_point).Replace("[优惠券金额]", economize).Replace("[机器人账号]", wxBase.User.Username).Replace("[机器人昵称]", wxBase.User.Nick).Replace("[账号]", member.username).Replace("[昵称]", member.usernick)); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + } + + //由于业务需要,这里将时间设置为2021年11月24日12点整 + //var stateTime = DateTime.Parse("2021-11-24 11:00:00"); + if (Config.NewUserTipStartTime <= member.crt_time) + { + var notify = session.FindSingle<fl_plugin_userfission_fan_notify>("select * from fl_plugin_userfission_fan_notify where mid = @mid", new { mid = member.id }); + if (notify == null) + notify = new fl_plugin_userfission_fan_notify() { mid = member.id, coupon = 0, uncoupon = 0, unfan = 0 }; + + if (!string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_UnFan) && notify.unfan == 0) + { + try + { + var robots = session.FindRobots(); + var robot = robots.FirstOrDefault(f => f.type == member.robot_type && f.name == member.robot_name); + if (robot == null) throw new Exception("用户对应的机器人信息异常"); + + var wxBase = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot.name && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wxBase == null) return; + var price = e.Shareds["price"].ToString(); + if (price == "未知") + { + notify.unfan = HttpExtend.GetTimeStamp(DateTime.Now); + if (Config.FirstQueryGoodsTip_Switch == SwitchType.开启) + { + notify.coupon = HttpExtend.GetTimeStamp(DateTime.Now); + notify.uncoupon = HttpExtend.GetTimeStamp(DateTime.Now); + } + session.Saveable(notify).ExecuteCommand(); + wxBase.SendMessage(username, Config.FirstQueryGoodsTip_UnFan.Replace("[机器人账号]", wxBase.User.Username).Replace("[机器人昵称]", wxBase.User.Nick).Replace("[账号]", member.username).Replace("[昵称]", member.usernick)); + return; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + if (!string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_Coupon) && notify.coupon == 0) + { + try + { + var robots = session.FindRobots(); + var robot = robots.FirstOrDefault(f => f.type == member.robot_type && f.name == member.robot_name); + if (robot == null) throw new Exception("用户对应的机器人信息异常"); + + var wxBase = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot.name && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wxBase == null) return; + var coupon_price = e.Shareds["coupon_price"].ToString(); + if (coupon_price != "未知" && double.Parse(coupon_price) > 0) + { + notify.coupon = HttpExtend.GetTimeStamp(DateTime.Now); + if (Config.FirstQueryGoodsTip_Switch == SwitchType.开启) + { + notify.unfan = HttpExtend.GetTimeStamp(DateTime.Now); + notify.uncoupon = HttpExtend.GetTimeStamp(DateTime.Now); + } + session.Saveable(notify).ExecuteCommand(); + + var price = e.Shareds["price"].ToString(); + var title = e.Shareds["title"].ToString(); + var user_point = e.Shareds["user_point"].ToString(); + var economize = e.Shareds["economize"].ToString(); + + wxBase.SendMessage(username, Config.FirstQueryGoodsTip_Coupon.Replace("[商品原价]", price).Replace("[商品标题]", title).Replace("[优惠券金额]", coupon_price).Replace("[用户佣金]", user_point).Replace("[优惠券金额]", economize).Replace("[机器人账号]", wxBase.User.Username).Replace("[机器人昵称]", wxBase.User.Nick).Replace("[账号]", member.username).Replace("[昵称]", member.usernick)); + return; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + if (!string.IsNullOrWhiteSpace(Config.FirstQueryGoodsTip_UnCoupon) && notify.uncoupon == 0) + { + try + { + var robots = session.FindRobots(); + var robot = robots.FirstOrDefault(f => f.type == member.robot_type && f.name == member.robot_name); + if (robot == null) throw new Exception("用户对应的机器人信息异常"); + + var wxBase = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == robot.name && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wxBase == null) return; + var coupon_price = e.Shareds["coupon_price"].ToString(); + if (coupon_price != "未知" && double.Parse(coupon_price) <= 0) + { + notify.uncoupon = HttpExtend.GetTimeStamp(DateTime.Now); + if (Config.FirstQueryGoodsTip_Switch == SwitchType.开启) + { + notify.unfan = HttpExtend.GetTimeStamp(DateTime.Now); + notify.coupon = HttpExtend.GetTimeStamp(DateTime.Now); + } + session.Saveable(notify).ExecuteCommand(); + + var price = e.Shareds["price"].ToString(); + var title = e.Shareds["title"].ToString(); + var user_point = e.Shareds["user_point"].ToString(); + var economize = e.Shareds["economize"].ToString(); + + wxBase.SendMessage(username, Config.FirstQueryGoodsTip_UnCoupon.Replace("[商品原价]", price).Replace("[商品标题]", title).Replace("[优惠券金额]", coupon_price).Replace("[用户佣金]", user_point).Replace("[优惠券金额]", economize).Replace("[机器人账号]", wxBase.User.Username).Replace("[机器人昵称]", wxBase.User.Nick).Replace("[账号]", member.username).Replace("[昵称]", member.usernick)); + return; + } + + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + } + } + } + catch (Exception ex) + { + this.OnLog(" " + ex.Message); + } + } + + private void NewFriendRewards(WeixinBase wx, fl_member_info member, fl_robot_info robot, SharedEvents e = null) + { + try + { + var session = ApiClient.GetSession(); + var _bonusSubordinate = Math.Round((new Random().Next( + int.Parse(Math.Round(Config.SubordinateSum1 * 100, 2).ToString()), + int.Parse(Math.Round((Config.SubordinateSum2 + 0.01) * 100, 2).ToString()) + )) / 100d, 2);//新人奖励积分 + if (robot.type == ChatType.微信 && wx.GetType() == typeof(WXClientImpl_IPAD) && (Config.Subordinate_RechargeType == RechargeType.发送红包 || Config.Subordinate_RechargeType == RechargeType.微信转账)) + { + var passinfo = session.FindWeixinpassword(session.FindRobotInfo(wx.WeixinHao, ChatType.微信).id);//获取微信支付信息 + if (passinfo != null && !string.IsNullOrEmpty(passinfo.password)) + { + var flag = wx.SendPay(member.username, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonusSubordinate.ToString()), (int)((decimal)_bonusSubordinate * 100m), passinfo.password, 1, (Config.Subordinate_RechargeType == RechargeType.发送红包 ? PayType.红包 : PayType.转账), passinfo.GetBank()); + if (!string.IsNullOrEmpty(flag)) + { + this.OnLog("微信新人奖励失败:" + flag + ",已添加积分到用户余额!");//发送红包不成功,将积分增加余额 + member = session.ChangePoint(PointType.其他奖励, _bonusSubordinate, member.id, $"新人赠送积分{_bonusSubordinate}【微信红包操作失败】"); + } + } + else + { + this.OnLog("微信新人奖励失败:未设置支付密码,已添加积分到用户余额!"); + member = session.ChangePoint(PointType.其他奖励, _bonusSubordinate, member.id, $"新人赠送积分{_bonusSubordinate}【微信红包操作失败,未设置支付密码】"); + } + } + else if (Config.Subordinate_RechargeType == RechargeType.商户付款) + { + if (_bonusSubordinate >= 0.3) + { + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay(new { robot_name = robot.name, robot_nick = robot.nick, username = member.username, usernick = member.usernick }, Class1.Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonusSubordinate.ToString()), _bonusSubordinate, out ispaid, out appinfo); + if (!string.IsNullOrEmpty(url)) + { + member = session.ChangePoint(PointType.其他奖励, _bonusSubordinate, member.id, $"新人赠送积分{_bonusSubordinate}"); + Thread.Sleep(20); + member = session.ChangePoint(PointType.提现扣除, _bonusSubordinate, member.id, $"新人奖励【商户付款成功】 商户链接:{url}"); + + var mess = string.Empty; + if (ispaid) + mess = Config.SubordinateCommercialEftTip.Replace("[推荐奖励金额]", "[奖励金额]").Replace("[奖励金额]", _bonusSubordinate.ToString()); + else + { + if (Config.ShangHu_MiNiApp == SwitchType.开启 && appinfo != null) + mess = Util.GetMiNiAppXml(appinfo, robot.type); + if (string.IsNullOrWhiteSpace(mess)) + mess = Config.SubordinateCommercialPayTip.Replace("[领取地址]", url/*ApiClient.ShortURL(url).Result*/).Replace("[推荐奖励金额]", "[奖励金额]").Replace("[奖励金额]", _bonusSubordinate.ToString()); + } + + ApiClient.SendMessage(robot, member.username, mess); + this.OnLog("商户付款信息 = " + mess); + } + else + { + this.OnLog("新人奖励商户付款失败:获取不到商户付款地址,已添加积分到用户余额!"); + member = session.ChangePoint(PointType.其他奖励, _bonusSubordinate, member.id, $"新人赠送积分{_bonusSubordinate}【商户付款操作失败,请求商户链接失败】"); + } + } + else + { + this.OnLog("新人奖励商户付款失败:奖励积分小于0.3,已添加积分到用户余额!"); + member = session.ChangePoint(PointType.其他奖励, _bonusSubordinate, member.id, $"新人赠送积分{_bonusSubordinate}【商户付款操作失败,积分小于0.3】"); + } + } + else + member = session.ChangePoint(PointType.其他奖励, _bonusSubordinate, member.id, $"新人赠送积分{_bonusSubordinate}【增加积分操作】"); + + if (e != null) + { + wx.SendMessage(member.username, new VariateReplace().CommonReplace(Config.Subordinate_AdditionalTip_Query.Replace("[奖励金额]", _bonusSubordinate.ToString()) + .Replace("[商品标题]", e.Shareds["title"].ToString()) + .Replace("[商品价格]", e.Shareds["price"].ToString()) + .Replace("[商品优惠券]", e.Shareds["coupon_price"].ToString()) + .Replace("[用户返利]", e.Shareds["user_point"].ToString()) + .Replace("[共节省]", e.Shareds["economize"].ToString()) + , member)); + } + else + { + wx.SendMessage(member.username, new VariateReplace().CommonReplace(Config.Subordinate_AdditionalTip.Replace("[奖励金额]", _bonusSubordinate.ToString()), member)); + } + } + catch (Exception ex) + { + throw ex; + } + } + + private void SDK_WXOpenWindowEvent(object sender, WXOpenWindow e) + { + try + { + var session = ApiClient.GetSession(); + var friend = session.Find<fl_plugin_userfission_applyfriend_info>("select * from fl_plugin_userfission_applyfriend_info where new_friend_wxid = @new_friend_wxid and state != '已接受'", new { new_friend_wxid = e.Friend.UserName }).FirstOrDefault(); + if (friend != null) + { + var _e = new WXNewFriend(e.Client, e.Friend); + + Task.Run(() => + { + SDK_WXNewFriendEvent(sender, _e); + }); + } + } + catch (Exception ex) + { + this.OnLog("Open = " + ex.Message + " - " + ex.StackTrace); + } + } + + private bool IsApply = false; + private void ApplyWechatFriend() + { + if (IsApply) return; + IsApply = true; + Task.Run(() => + { + try + { + var session = ApiClient.GetSession(); + do + { + var apply_id = queue.Dequeue(); + var friend = session.FindSingle<fl_plugin_userfission_applyfriend_info>("id = @id", new { id = apply_id }); + if (friend != null) + { + Thread.Sleep(Config.Retardation * 1000); + if (friend != null && friend.state == "已接受") continue; + var client = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == friend.robot_name && /*f.WeixinType == WeixinType.Grpc微信 &&*/ f.Status == Chat.Framework.WXSdk.WxStatus.在线); + + if (client != null) + { + //%3cmsg+fromusername%3d%22wxid_syajaydqg2mi22%22+encryptusername%3d%22v1_98b2f7e33fdd0211eefe3c5a372bc565f3cae00066c66f67cd39f7a008c43ac66658d416fae14a20a434313a3ac3552f%40stranger%22+fromnickname%3d%22%b2%e9%d3%c5%bb%dd%d0%a1%d6%fa%ca%d6-%d4%cb%d3%aa-%c3%c8%c3%c8%22+content%3d%22%c7%d7++%df%e4%df%e4%d4%dd%ca%b1%b7%a2%b2%bb%b3%f6%c8%a5%d0%c5%cf%a2%2c%d0%e8%d2%aa%ba%c3%d3%d1%b0%ef%c3%a6%d1%e9%d6%a4%a3%ac%bf%c9%d2%d4%b0%ef%cf%c2%c3%a6%c2%f0%3f%3f%3f%3f%22+fullpy%3d%22zhayouhuixiaozhushouyunyingmengmeng%22+shortpy%3d%22ZYHXZSYYMM%22+imagestatus%3d%223%22+scene%3d%2217%22+country%3d%22%22+province%3d%22%22+city%3d%22%22+sign%3d%22%ce%d2%ca%c7%ca%a1%c7%ae%d0%a1%d6%fa%ca%d6%d4%cb%d3%aa%a1%a2%c3%c8%c3%c8%a1%a2%d0%bb%d0%bb%b4%f3%bc%d2%d2%bb%d6%b1%d2%d4%c0%b4%b6%d4%ce%d2%c3%c7%b5%c4%d6%a7%b3%d6!%22+percard%3d%221%22+sex%3d%222%22+alias%3d%22jb31818%22+weibo%3d%22%22+albumflag%3d%220%22+albumstyle%3d%220%22+albumbgimgid%3d%22%22+snsflag%3d%221%22+snsbgimgid%3d%22http%3a%2f%2fszmmsns.qpic.cn%2fmmsns%2fswxPWAic8Eyxld2DN94W2IkQ5Q17JShIQp3YKibvF4pzAfqmNrAzyAkW9fYElTSFjd6J4ylyCvKeI%2f0%22+snsbgobjectid%3d%2213282630333274796184%22+mhash%3d%22dcb3ac624574902decb75866a6934a6e%22+mfullhash%3d%22dcb3ac624574902decb75866a6934a6e%22+bigheadimgurl%3d%22http%3a%2f%2fwx.qlogo.cn%2fmmhead%2fver_1%2f1ibs5sUHIKr1hBvRWPaichaQXiaXib06icfsUn6EuoV5YskibBZlYLSTPztuVMdXiaqQyhys5ozEoQswhMd6cFbLkWnovzLH7iamsQ6aQnIKzCyUr48%2f0%22+smallheadimgurl%3d%22http%3a%2f%2fwx.qlogo.cn%2fmmhead%2fver_1%2f1ibs5sUHIKr1hBvRWPaichaQXiaXib06icfsUn6EuoV5YskibBZlYLSTPztuVMdXiaqQyhys5ozEoQswhMd6cFbLkWnovzLH7iamsQ6aQnIKzCyUr48%2f96%22+ticket%3d%22v2_ed61758c0d517c2a7b5fa83d26b48e3aad8cec1239bf37db9a381858fe2507ac1205b9b36114db60b0ac1d009249a9da17ebf506cc234e8723d1ef47bfdd34ecef24f5d86846a487d4dc53c5812f5c66619ad95253c341e7310e076299c985e05d8b5e70583f5e7602cc1a783bb136f286e9163e59b7042b964ae858aabcd6973b9519b9ae58997b1674826f459882a7d217a07259ae07e564f9b768e75b267939762dcd58be0ec242a434b06cddf04e1bfe69c6425caadf51be980ac5cf26dd3b32b5796ed4d6bdb6e3998b7e9cec56598e2c5df5288d562b0b6f5199ead90f974446656a9df971c7163a2e1bb8047f9116d316c289b43b50acbd9344b5132d%40stranger%22+opcode%3d%222%22+googlecontact%3d%22%22+qrticket%3d%22%22+chatroomusername%3d%22%22+sourceusername%3d%22wxid_2ufntuf4purl22%22+sourcenickname%3d%22%c7%ef%b1%b1%cf%c8%c9%fa%22+sharecardusername%3d%22wxid_2ufntuf4purl22%22+sharecardnickname%3d%22%c7%ef%b1%b1%cf%c8%c9%fa%22+cardversion%3d%220%22%3e%3cbrandlist+count%3d%220%22+ver%3d%22703522235%22%3e%3c%2fbrandlist%3e%3c%2fmsg%3e + var ss = HttpHelper.URLDecode(friend.token); + string result = client.AgreeAddMe(HttpHelper.URLDecode(friend.token)); + if (string.IsNullOrEmpty(result)) + { + friend.state = "已接受"; + friend.allow_time = DateTime.Now; + } + else friend.state = result; + session.Saveable(friend).ExecuteReturnEntity(); + } + } + } while (true); + } + catch (Exception) + { } + finally + { + IsApply = false; + } + }); + } + + private static readonly object applyFriendLock = new object(); + + /// <summary> + /// 微信 - 申请添加我为好友,需要审核 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void SDK_WXApplyFriendEvent(object sender, WXApplyFriend e) + { + try + { + lock (applyFriendLock) + { + var friend = ApiClient.GetSession().FindSingle<fl_plugin_userfission_applyfriend_info>("select * from fl_plugin_userfission_applyfriend_info where new_friend_wxid = @new_friend_wxid and robot_name = @robot_name", new { new_friend_wxid = e.NewFriendWxid, robot_name = e.Client.WeixinHao }); + if (friend != null && friend.state == "已接受") return; + if (friend == null) + { + friend = new fl_plugin_userfission_applyfriend_info() + { + state = "待审核", + crt_time = DateTime.Parse(e.CrtTime.ToString("yyyy-MM-dd HH:mm:ss")), + message = e.Message.Trim(), + robot_name = e.Client.WeixinHao, + user_nick = e.Client.User.Nick, + new_friend_nick = e.NewFriendNick, + new_friend_wxid = e.NewFriendWxid, + old_friend_nick = e.OldFriendNick, + old_friend_wxid = e.OldFriendWxid, + token = HttpHelper.URLEncode(e.Token) + }; + friend.id = ApiClient.GetSession().Insertable(friend).ExecuteReturnIdentity(); + } + if (Config.Accept == SwitchType.关闭) return; + var reg = Regex.Match(e.Token, @"sex=""(?<性别>\d+)"""); + if (reg.Success) + { + var sex = reg.Groups["性别"].ToString(); + if (sex == "1" && !Config.GenderType.Contains("男")) return; + else if (sex == "2" && !Config.GenderType.Contains("女")) return; + else if (sex == "0" && !Config.GenderType.Contains("未知")) return; + } + //var robot = session.FindRobots().FirstOrDefault(f => f.name == e.Client.WeixinHao && f.type == (e.Client.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信)); + var robot = ApiClient.GetSession().FindRobotInfo(e.Client.WeixinHao, (e.Client.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信)); + if (robot == null) return; + var aas = ApiClient.GetSession().FindSingle<fl_plugin_userfission_automatic_approval_setting>("select * from fl_plugin_userfission_automatic_approval_setting where rid = @rid", new { rid = robot.id }); + if (aas != null && aas.onoff) return; + if (!queue.Contains(friend.id)) + { + queue.Enqueue(friend.id); + ApplyWechatFriend(); + } + } + } + catch (Exception ex) + { + this.OnLog("ApplyFriend = " + ex.Message + " - " + ex.StackTrace); + } + } + + private List<string> welcomeTip_Friends = new List<string>(); + private static object lock_newfriend = new object(); + /// <summary> + /// 微信 - 新增微信好友 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void SDK_WXNewFriendEvent(object sender, WXNewFriend e) + { + var strb = new StringBuilder(); + try + { + strb.AppendLine("1"); + fl_plugin_userfission_applyfriend_info friend = null; + var isNewMember = false; + var chatType = e.Client.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信; + //var session = ApiClient.GetSession(); + fl_member_info new_member = null; + strb.AppendLine("2"); + var robot = ApiClient.GetSession().FindRobotInfo(e.Client.WeixinHao, chatType); + if (robot != null) + { + strb.AppendLine("3"); + Thread.Sleep(1100); + lock (lock_newfriend) + { + strb.AppendLine("4"); + if (!welcomeTip_Friends.Contains(e.Friend.UserName)) + { + strb.AppendLine("4-1"); + var mess = Config.WelcomeTip; + friend = ApiClient.GetSession().FindSingle<fl_plugin_userfission_applyfriend_info>( + "new_friend_wxid = @new_friend_wxid and robot_name = @robot_name", + new { new_friend_wxid = e.Friend.UserName, robot_name = e.Client.WeixinHao }); + if (friend != null && !string.IsNullOrWhiteSpace(friend.old_friend_wxid)) + mess = Config.WelcomeBeInvitedTip.Replace("[邀请人昵称]", friend.old_friend_nick); + strb.AppendLine("4-2"); + #region 将表fl_plugin_userfission_applyfriend_info中的请求状态改成 "已接受" + + if (friend != null && friend.state != "已接受") + { + strb.AppendLine("4-3"); + friend.state = "已接受"; + friend.allow_time = DateTime.Now; + ApiClient.GetSession().Saveable(friend).ExecuteReturnEntity(); + } + strb.AppendLine("4-4"); + #endregion + + if (welcomeTip_Friends.Count > 10000) welcomeTip_Friends.Clear(); + welcomeTip_Friends.Add(e.Friend.UserName); + strb.AppendLine("4-5"); + new_member = ApiClient.GetSession().FindSingle<fl_member_info>( + "robot_type = @robot_type and username = @username", + new { robot_type = robot.type, username = e.Friend.UserName }); + if (new_member == null) + { + strb.AppendLine("4-6"); + new_member = new fl_member_info() + { + crt_time = DateTime.Now, + usernick = e.Friend.NickName, + realnick = e.Friend.NickName, + robot_name = e.Client.WeixinHao, + robot_type = robot.type, + username = e.Friend.UserName, + alipay_name = string.Empty, + alipay_num = string.Empty, + remark = string.Empty + }; + var groups = ApiClient.GetSession().FindGroups(); + if (groups.Count != 0) + new_member.group_id = groups[0].id; + strb.AppendLine("4-7"); + ApiClient.GetSession().SaveOrUpdate(new_member); + isNewMember = true; + } + else if (new_member.crt_time.AddSeconds(15) > DateTime.Now) + { + strb.AppendLine("4-8"); + isNewMember = true; + } + strb.AppendLine("4-9"); + ApiClient.SendMessage(robot, e.Friend.UserName, mess); + } + } + } + + #region 新人加入奖励 + strb.AppendLine("5"); + if (new_member == null || !isNewMember) + { + strb.AppendLine("6"); + new_member = ApiClient.GetSession().FindSingle<fl_member_info>( + "select * from fl_member_info where robot_type = @robot_type and username = @username", + new { robot_type = chatType, username = e.Friend.UserName }); + if (new_member == null) + { + new_member = new fl_member_info() + { + crt_time = DateTime.Now, + usernick = e.Friend.NickName, + realnick = e.Friend.NickName, + robot_name = e.Client.WeixinHao, + robot_type = chatType, + username = e.Friend.UserName, + alipay_name = string.Empty, + alipay_num = string.Empty, + remark = string.Empty + }; + var groups = ApiClient.GetSession().FindGroups(); + if (groups.Count != 0) + new_member.group_id = groups[0].id; + ApiClient.GetSession().SaveOrUpdate(new_member); + isNewMember = true; + } + } + + if (isNewMember) + { + strb.AppendLine("7"); + if (Config.SubordinateSumSwitch == SwitchType.开启 && + Config.SubordinateRewardWay == NewcomerAwardType.通过立即奖励) + { + if (Config.SubordinateSum2 < Config.SubordinateSum1) + throw new Exception("新用户奖励积分设置数据异常,最大奖励值应大于最小值"); + + NewFriendRewards(e.Client, new_member, robot); + } + } + + #endregion + strb.AppendLine("8"); + //if (new_member != null || Config.Bind == SwitchType.开启) + if (Config.Bind == SwitchType.开启 && new_member != null) + { + strb.AppendLine("9"); + //this.OnLog($"新用户绑定:{new_member.usernick} - {new_member.username} - {isNewMember}"); + if (friend == null) + friend = ApiClient.GetSession().Find<fl_plugin_userfission_applyfriend_info>( + $"select * from fl_plugin_userfission_applyfriend_info where new_friend_wxid = @wxid and robot_name = @robotName order by id desc", + new { wxid = e.Friend.UserName, robotName = e.Client.WeixinHao }).FirstOrDefault(); + + this.OnLog( + $"新用户绑定:{new_member.usernick} - {new_member.username} {(friend == null ? "无" : $"{friend.old_friend_nick}({friend.old_friend_wxid})")} - {isNewMember}"); + + if (friend != null) + { + string mess = string.Empty; + if (new_member.inviter_id == 0) + { + //防止用户反复添加获取奖励 + if (!string.IsNullOrEmpty(friend.old_friend_wxid) || + !string.IsNullOrEmpty(friend.old_friend_nick)) + { + var old_member = ApiClient.GetSession() + .FindSingle<fl_member_info>("robot_type = @robot_type and username = @username", + new { username = friend.old_friend_wxid, robot_type = chatType }); + if (old_member == null) + { + old_member = new fl_member_info() + { + crt_time = DateTime.Now, + usernick = friend.old_friend_nick, + robot_name = e.Client.WeixinHao, + robot_type = chatType, + username = friend.old_friend_wxid, + alipay_name = string.Empty, + alipay_num = string.Empty, + remark = string.Empty + }; + var groups = ApiClient.GetSession().FindGroups(); + if (groups.Count != 0) + old_member.group_id = groups[0].id; + ApiClient.GetSession().SaveOrUpdate(old_member); + } + + if (old_member.inviter_id != new_member.id) //排除相互绑定 + { + new_member.inviter_id = old_member.id; + ApiClient.GetSession().SaveOrUpdate(new_member); + + //上级奖励开关 + if (Config.SuperiorSumSwitch == SwitchType.开启 && + Config.SuperiorRewardWay == ReferralJackpotType.推荐新人立马奖励) + { + if (IsSuperiorReward(robot)) + { + if (Config.SuperiorSum2 < Config.SuperiorSum1) + throw new Exception("上级奖励积分设置数据异常,最大奖励值应大于最小值"); + var _bonusSuperior = Math.Round(( + new Random().Next( + int.Parse(Math.Round(Config.SuperiorSum1 * 100, 2).ToString()), + int.Parse(Math.Round((Config.SuperiorSum2 + 0.01) * 100, 2) + .ToString()) + )) / 100d, 2); + if (Config.Superior_RechargeType == RechargeType.发送红包 || + Config.Superior_RechargeType == RechargeType.微信转账) + { + var passinfo = ApiClient.GetSession() + .FindWeixinpassword(ApiClient.GetSession() + .FindRobotInfo(e.Client.WeixinHao, chatType).id); //获取微信支付信息 + if (passinfo != null && !string.IsNullOrEmpty(passinfo.password)) + { + var flag = e.Client.SendPay(old_member.username, + Config.ExchangePacketTitle + .Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName) + .Replace("[兑换金额]", _bonusSuperior.ToString()), + (int)((decimal)_bonusSuperior * 100m), passinfo.password, 1, + (Config.Superior_RechargeType == RechargeType.发送红包 + ? PayType.红包 + : PayType.转账), passinfo.GetBank()); + if (!string.IsNullOrEmpty(flag)) + { + this.OnLog("推荐新人奖励失败:" + flag + + ",已添加积分到用户余额!"); //发送红包不成功,将积分增加余额 + old_member = ApiClient.GetSession().ChangePoint(PointType.其他奖励, + _bonusSuperior, old_member.id, + $"推荐新人{new_member.usernick}-{new_member.username},奖励积分{_bonusSuperior}【微信红包操作失败】"); + } + } + else + { + this.OnLog("推荐新人奖励失败:未设置支付密码,已添加积分到用户余额!"); + old_member = ApiClient.GetSession().ChangePoint(PointType.其他奖励, + _bonusSuperior, old_member.id, + $"推荐新人{new_member.usernick}-{new_member.username},奖励积分{_bonusSuperior}【微信红包操作失败,未设置支付密码】"); + } + } + else if (Config.Superior_RechargeType == RechargeType.商户付款) + { + if (_bonusSuperior >= 0.3) + { + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay( + new + { + robot_name = robot.name, + robot_nick = robot.nick, + username = old_member.username, + usernick = old_member.usernick + }, + Class1.Config.ExchangePacketTitle + .Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName) + .Replace("[兑换金额]", _bonusSuperior.ToString()), + _bonusSuperior, out ispaid, out appinfo); + if (!string.IsNullOrEmpty(url)) + { + old_member = ApiClient.GetSession().ChangePoint(PointType.其他奖励, + _bonusSuperior, old_member.id, + $"推荐新人{new_member.usernick}-{new_member.username},奖励积分{_bonusSuperior}"); + Thread.Sleep(20); + old_member = ApiClient.GetSession().ChangePoint(PointType.提现扣除, + _bonusSuperior, old_member.id, $"推荐新人【商户付款成功】 商户链接:{url}"); + + var _mess = string.Empty; + if (ispaid) + _mess = Config.SuperiorCommercialEftTip + .Replace("[下级昵称]", new_member.realnick) + .Replace("[推荐奖励金额]", _bonusSuperior.ToString()); + else + { + if (Config.ShangHu_MiNiApp == SwitchType.开启 && + appinfo != null) + _mess = Util.GetMiNiAppXml(appinfo, robot.type); + if (string.IsNullOrWhiteSpace(_mess)) + _mess = Config.SuperiorCommercialPayTip + .Replace("[领取地址]", + url /*ApiClient.ShortURL(url).Result*/) + .Replace("[下级昵称]", new_member.realnick) + .Replace("[推荐奖励金额]", _bonusSuperior.ToString()); + } + + ApiClient.SendMessage(robot, old_member.username, _mess); + this.OnLog("商户付款信息 = " + _mess); + } + else + { + this.OnLog("推荐新人商户付款失败:获取不到商户付款地址,已添加积分到用户余额!"); + old_member = ApiClient.GetSession().ChangePoint(PointType.其他奖励, + _bonusSuperior, old_member.id, + $"推荐新人{new_member.usernick}-{new_member.username},奖励积分{_bonusSuperior}【商户付款操作失败,请求商户链接失败】"); + } + } + else + { + this.OnLog("推荐新人商户付款失败:奖励积分小于0.3,已添加积分到用户余额!"); + old_member = ApiClient.GetSession().ChangePoint(PointType.其他奖励, + _bonusSuperior, old_member.id, + $"推荐新人{new_member.usernick}-{new_member.username},奖励积分{_bonusSuperior}【商户付款操作失败,积分小于0.3】"); + } + } + else + old_member = ApiClient.GetSession().ChangePoint(PointType.其他奖励, + _bonusSuperior, old_member.id, + $"推荐新人{new_member.usernick}-{new_member.username},奖励积分{_bonusSuperior}【增加积分操作】"); + + Thread.Sleep(400); + //邀请成功通知上级用户 + ApiClient.SendMessage(robot, old_member.username, + Config.ImmediateReward_AddANewSubordinateTip + .Replace("[使用者昵称]", new_member.realnick) + .Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", + old_member.cur_point.ToString())); + } + } + else + { + ApiClient.SendMessage(robot, old_member.username, + Config.FirstSingleReward_AddANewSubordinateTip + .Replace("[使用者昵称]", new_member.realnick).Replace("[剩余积分]", + old_member.cur_point.ToString())); + } + } + } + } + } + + } + + #region 将用户拉入群操作 + + Task.Run(() => + { + try + { + if (robot == null) return; + if (Config.InvitedIntoGroupSwitch == SwitchType.关闭) return; + if (Config.InvitegroupWay) return; + if (Config.InviteGroupInfo2 == null || Config.InviteGroupInfo2.Count == 0) return; + var _session = ApiClient.GetSession(); + var member = _session.FindSingle<fl_member_info>( + "robot_type = @robot_type and username = @username", + new { username = e.Friend.UserName, robot_type = chatType }); + if (member == null) return; + if (userIdlist.Contains(member.id)) return; + var groupInfo = Config.InviteGroupInfo2.Where(f => + f.Key == e.Client.WeixinHao && !f.Value.onoff && f.Value.groupInfos.Count != 0); + if (groupInfo != null) //查询的对象不为空 并且 自动拉进群的操作非禁用 + { + var wechat = ChatClient.WXClient.Values.ToList().FirstOrDefault(f => + f.WeixinHao == e.Client.WeixinHao && /*f.WeixinType == WeixinType.Grpc微信 &&*/ + f.Status == Chat.Framework.WXSdk.WxStatus.在线); + //if (wxBase == null) return; + //var ipad = wxBase as WXClientImpl_IPAD; + //if (ipad == null) return; + if (Config.InviteGroupInfo2.ContainsKey(e.Client.WeixinHao)) + { + var groupIds = Config.InviteGroupInfo2[e.Client.WeixinHao].groupInfos; + foreach (var groupId in groupIds) + { + lock (padlock) + { + if (!userIdlist.Contains(member.id)) + userIdlist.Add(member.id); + if (wechat.GetType() == typeof(WXClientImpl_QYHOOK)) + { + var result = _session.FindSingle<fl_plugin_userfission_invite_record>( + "username = @username and groupid = @groupid", + new { username = e.Friend.UserName, groupid = groupId.Key }); + if (result != null) return; + + ApiClient.SendMessage(robot, e.Friend.UserName, + Config.InvitedIntoGroupTip.Replace("[账号]", e.Friend.UserName) + .Replace("[昵称]", e.Friend.NickName)); + e.Client.InviteIntoGroup(e.Friend.UserName, groupId.Key); + } + else + { + var group = wechat.GetContact(groupId.Key); + if (group == null) continue; + + var result = _session.FindSingle<fl_plugin_userfission_invite_record>( + "username = @username and groupid = @groupid", + new { username = e.Friend.UserName, groupid = group.UserName }); + if (result != null) return; + //该用户不在群内 并且 没有给用户发送过邀请入群卡片 + if (string.IsNullOrWhiteSpace(group.ExtInfo) || + !group.ExtInfo.Contains(e.Friend.UserName)) + { + ApiClient.SendMessage(robot, e.Friend.UserName, + Config.InvitedIntoGroupTip.Replace("[账号]", e.Friend.UserName) + .Replace("[昵称]", e.Friend.NickName)); + var sss = e.Client.InviteIntoGroup(e.Friend.UserName, group.UserName); + } + } + + var _result = new fl_plugin_userfission_invite_record() + { groupid = groupId.Key, username = e.Friend.UserName }; + _session.Insertable(_result).ExecuteCommand(); + } + + break; + } + } + } + } + catch (Exception ex) + { + this.OnLog($"拉用户入群操作异常:{ex.Message} ~ {ex.StackTrace}"); + } + }); + + #endregion + + } + catch (Exception ex) + { + strb.AppendLine("10000:" + ex.Message); + this.OnLog("NewFriend = " + ex.Message + " - " + ex.StackTrace); + } + finally + { + //this.OnLog("......." + strb.ToString()); + } + } + + /// <summary> + /// 进群的用户 + /// </summary> + private static ConcurrentBag<string> JoinGroups = new ConcurrentBag<string>(); + private void JoinGroup(string groupId, string weixinhao) + { + try + { + if (!JoinGroups.Contains(groupId + "!!!" + weixinhao)) + JoinGroups.Add(groupId + "!!!" + weixinhao); + } + catch (Exception ex) + { } + } + + static bool isRunning = false; + private static void BindGroupInvite() + { + if (!isRunning) + { + isRunning = true; + try + { + if (Config.GroupBind == SwitchType.开启) + { + if (JoinGroups.Count != 0) + { + var joinGroups = JoinGroups.ToList(); + var session = ApiClient.GetSession(); + for (int i = 0; i < joinGroups.Count; i++) + { + var temp = joinGroups[i]; + var splits = temp.Split(new string[] { "!!!" }, StringSplitOptions.RemoveEmptyEntries); + + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinType == WeixinType.Grpc微信 && f.WeixinHao == splits[1] && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wx == null) continue; + var members = wx.GetMembers(splits[0], true); + if (members == null) continue; + for (int z = 0; z < members.Length; z++) + { + var item = members[z]; + var member = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = item.Username }); + if (member == null) + { + member = new fl_member_info() { crt_time = DateTime.Now, usernick = item.NickName, robot_name = wx.WeixinHao, robot_type = wx.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信, username = item.Username, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + session.SaveOrUpdate(member); + } + + if (member.inviter_id != 0) continue; + if (string.IsNullOrWhiteSpace(members[z].InviterUserName)) continue; + var member_inviter = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = members[z].InviterUserName }); + if (member_inviter != null) + { + member.inviter_id = member_inviter.id; + session.SaveOrUpdate(member); + } + } + JoinGroups.TryTake(out temp); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(null, "群绑定上下级异常:" + ex.Message); + } + finally + { + isRunning = false; + } + } + } + + /// <summary> + /// 微信 - 新成员进群 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void SDK_WXNewMemerEvent(object sender, WXNewMemer e) + { + try + { + //this.OnLog($"Wx = {e.Client.WeixinHao}" + string.Join("#", Config.NewComerGroupInfo.Keys)); + if (!Config.NewComerGroupInfo.ContainsKey(e.Client.WeixinHao)) return; + + //this.OnLog($"新人入群:{e.MemberNicks}({e.MemberName}),邀请人:{e.SourceNick}({e.SourceName})"); + + if (sender.GetType() == typeof(WXClientImpl_IPAD)) + JoinGroup(e.GroupId, e.Client.WeixinHao); + else if (sender.GetType() == typeof(WXClientImpl_HOOK) && Config.GroupBind == SwitchType.开启 && e.Client != null && e.Client.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + var session = ApiClient.GetSession(); + var member = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = e.MemberName }); + if (member == null) + { + member = new fl_member_info() { crt_time = DateTime.Now, usernick = e.MemberNicks, robot_name = e.Client.WeixinHao, robot_type = e.Client.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信, username = e.MemberName, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + session.SaveOrUpdate(member); + } + + if (member.inviter_id == 0 && !string.IsNullOrWhiteSpace(e.SourceName)) + { + var member_inviter = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = e.SourceName }); + if (member_inviter != null) + { + member.inviter_id = member_inviter.id; + session.SaveOrUpdate(member); + } + } + } + + var groups = Config.NewComerGroupInfo[e.Client.WeixinHao]; + if (groups != null && !groups.onoff && !string.IsNullOrWhiteSpace(Config.GroupWelcomeTip) && groups.groupIds.Contains(e.GroupId)) + e.Client.SendMessage(e.Group.UserName, Config.GroupWelcomeTip.Replace("[群昵称]", e.Group.NickName).Replace("[昵称]", e.MemberNicks).Replace("[账号]", e.MemberName)); + } + catch (Exception ex) + { + this.OnLog("NewMemer = " + ex.Message); + } + } + + #endregion + + /// <summary> + /// 通用消息 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + //return; + //var ss = HttpHelper.URLDecode("%3cmsg+fromusername%3d%22wxid_8s44kddouuaj21%22+encryptusername%3d%22v3_020b3826fd03010000000000a5d42b864ffd71000000501ea9a3dba12f95f6b60a0536a1adb6561f62944a04a2c4fdda9f7b55eb4da2fce833ad6a6599155cf7409f469a16e5c9d7a307a2b7a3d54984f749326f1c871b836e6f1a78b819e881de7f%40stranger%22+fromnickname%3d%22%c7%a7%c4%ea%c0%cf%d1%fd%22+content%3d%22%ce%d2%ca%c7%c7%a7%c4%ea%c0%cf%d1%fd%22+fullpy%3d%22qiannianlaoyao%22+shortpy%3d%22QNLY%22+imagestatus%3d%223%22+scene%3d%2230%22+country%3d%22CN%22+province%3d%22Sichuan%22+city%3d%22Chengdu%22+sign%3d%22%c3%bb%d3%d0%b8%b9%bc%a1%b5%c4%a3%ac%b6%bc%ca%c7%c5%d6%d7%d3%22+percard%3d%221%22+sex%3d%221%22+alias%3d%22my-object%22+weibo%3d%22%22+albumflag%3d%220%22+albumstyle%3d%220%22+albumbgimgid%3d%22%22+snsflag%3d%22273%22+snsbgimgid%3d%22http%3a%2f%2fszmmsns.qpic.cn%2fmmsns%2fA6bBbWlnGV5569R1Oj3I4mBORwqAic2BwzPzthtzlk6LVZ4svk6ExDKibds7l7ibtVSojkjL3A03jk%2f0%22+snsbgobjectid%3d%2213554445051344457821%22+mhash%3d%22823f3771ac7bcfb9bcde1b7efe76673a%22+mfullhash%3d%22823f3771ac7bcfb9bcde1b7efe76673a%22+bigheadimgurl%3d%22http%3a%2f%2fwx.qlogo.cn%2fmmhead%2fver_1%2fzRJZKRa7TNyUvlWQichZsq4aekeCkvVibmzicibh9MFc2JP03AwAwCpbhGtVy4S3otINAM21jc6yYQoahUibBXjLHJ7MNoiakgkfCNuHHQJqJymtE%2f0%22+smallheadimgurl%3d%22http%3a%2f%2fwx.qlogo.cn%2fmmhead%2fver_1%2fzRJZKRa7TNyUvlWQichZsq4aekeCkvVibmzicibh9MFc2JP03AwAwCpbhGtVy4S3otINAM21jc6yYQoahUibBXjLHJ7MNoiakgkfCNuHHQJqJymtE%2f96%22+ticket%3d%22v4_000b708f0b04000001000000000096e0c313574586ca6e8561a44e621000000050ded0b020927e3c97896a09d47e6e9ed1dcf0f5ef4fd59b8e9b5738dfead530b104a0f5e21ae8a3adb686632abc3da249a28815faf08e773472137ebcf6f953e649ddd5c6688ea6efa11292ad0c16c09ebb175ffeb47f63ebab11b4e7e18fa5556a4a076d31f654fa874f98fcc447700e3b4a0a4463f2a5%40stranger%22+opcode%3d%222%22+googlecontact%3d%22%22+qrticket%3d%22%22+chatroomusername%3d%22%22+sourceusername%3d%22%22+sourcenickname%3d%22%22+sharecardusername%3d%22%22+sharecardnickname%3d%22%22+cardversion%3d%22%22+extflag%3d%220%22%3e%3cbrandlist+count%3d%220%22+ver%3d%22768305994%22%3e%3c%2fbrandlist%3e%3c%2fmsg%3e"); + //string result = (sender as WXClientImpl_HOOK).AgreeAddMe(ss); + + + switch (e.ChatType) + { + //case ChatType.未知来源: + // break; + case ChatType.QQ: + case ChatType.微信: + case ChatType.企业微信: + { + if (!string.IsNullOrEmpty(e.Groupid)) return; + var session = ApiClient.GetSession(); + WeixinBase wx = null; + //QQClient ipad_qq = null; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信) + wx = sender as WeixinBase; + //else + //ipad_qq = sender as QQClient; + + var member = e.GetMemberinfo(); + if (member != null && member.inviter_id == 0) + { + if (Regex.IsMatch(e.Message.Trim(), Tools.Rex_Code))//输入的为邀请码格式的数据,不管是否开启强制绑定 + { + var reg = Regex.Match(e.Message.Trim(), Tools.Rex_Code); + if (reg.Success) + { + var old_member = session.Find<fl_member_info>($"select m.* from fl_member_info m join fl_plugin_userfission_user_invitation_code ic on m.id = ic.member_info_id where ic.code = @code and robot_type = @robotType", new { code = reg.Groups[1].Value, robotType = (int)e.ChatType }).FirstOrDefault(); + //上级用户存在 + if (old_member != null) + { + if (member.id == old_member.id) + { + e.SendMessage(Config.BindTheInvitationCodeOneselfTip); + return; + } + if (old_member.inviter_id == member.id) + { + e.SendMessage(Config.InviteEachOtherTip); + return; + } + + #region 绑定上级操作 + member.inviter_id = old_member.id; + session.SaveOrUpdate(member);//绑定上级关系 + e.SendMessage(Config.BindTheInvitationCodeSuccessfully.Replace("[邀请人昵称]", old_member.usernick)); + #endregion + + Thread.Sleep(300); + + if (Config.SuperiorSumSwitch == SwitchType.开启 && Config.SuperiorRewardWay == ReferralJackpotType.推荐新人立马奖励) + { + if (IsSuperiorReward(e.RobotInfo)) + { + if (Config.SuperiorSum2 < Config.SuperiorSum1) throw new Exception("上级奖励积分设置数据异常,最大奖励值应大于最小值"); + + var _bonusSuperior = Math.Round((new Random().Next(int.Parse(Math.Round(Config.SuperiorSum1 * 100, 2).ToString()), int.Parse(Math.Round(((Config.SuperiorSum2 + 0.01) * 100), 2).ToString()))) / 100d, 2); + if (e.ChatType == ChatType.微信 && (Config.Superior_RechargeType == RechargeType.发送红包 || Config.Superior_RechargeType == RechargeType.微信转账)) + { + var passinfo = session.FindWeixinpassword(session.FindRobotInfo(e.RobotInfo.name, e.ChatType).id);//获取微信支付信息 + if (passinfo != null && !string.IsNullOrEmpty(passinfo.password)) + { + var flag = wx.SendPay(old_member.username, Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonusSuperior.ToString()), (int)((decimal)_bonusSuperior * 100m), passinfo.password, 1, (Config.Superior_RechargeType == RechargeType.发送红包 ? PayType.红包 : PayType.转账), passinfo.GetBank()); + if (!string.IsNullOrEmpty(flag)) + { + this.OnLog("推荐新人奖励失败:" + flag + ",已添加积分到用户余额!");//发送红包不成功,将积分增加余额 + old_member = session.ChangePoint(PointType.其他奖励, _bonusSuperior, old_member.id, $"推荐新人{member.usernick}-{member.username},奖励积分{_bonusSuperior}【微信红包操作失败】"); + } + } + else + { + this.OnLog("推荐新人奖励失败:未设置支付密码,已添加积分到用户余额!"); + old_member = session.ChangePoint(PointType.其他奖励, _bonusSuperior, old_member.id, $"推荐新人{member.usernick}-{member.username},奖励积分{_bonusSuperior}【微信红包操作失败,未设置支付密码】"); + } + ApiClient.SendMessage(e.RobotInfo, old_member.username, Config.ImmediateReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", old_member.cur_point.ToString())); + } + else if ((e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信) && Config.Superior_RechargeType == RechargeType.商户付款) + { + if (_bonusSuperior >= 0.3) + { + var ispaid = false; + object appinfo = null; + string url = ApiClient.SendWechatPay(new { robot_name = e.RobotInfo.name, robot_nick = e.RobotInfo.nick, username = old_member.username, usernick = old_member.usernick }, Class1.Config.ExchangePacketTitle.Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName).Replace("[兑换金额]", _bonusSuperior.ToString()), _bonusSuperior, out ispaid, out appinfo); + if (!string.IsNullOrEmpty(url)) + { + old_member = session.ChangePoint(PointType.其他奖励, _bonusSuperior, old_member.id, $"推荐新人{member.usernick}-{member.username},奖励积分{_bonusSuperior}"); + Thread.Sleep(20); + old_member = session.ChangePoint(PointType.提现扣除, _bonusSuperior, old_member.id, $"推荐新人【商户付款成功】 商户链接:{url}"); + + var _mess = string.Empty; + if (ispaid) + _mess = Config.SuperiorCommercialEftTip.Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[下级昵称]", member.realnick); + else + { + if (Config.ShangHu_MiNiApp == SwitchType.开启 && appinfo != null) + _mess = Util.GetMiNiAppXml(appinfo, e.RobotInfo.type); + if (string.IsNullOrWhiteSpace(_mess)) + _mess = Config.SuperiorCommercialPayTip.Replace("[领取地址]", url/*ApiClient.ShortURL(url).Result*/).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[下级昵称]", member.realnick); + } + ApiClient.SendMessage(e.RobotInfo, old_member.username, _mess); + this.OnLog("商户付款信息 = " + _mess); + } + else + { + this.OnLog("推荐新人商户付款失败:获取不到商户付款地址,已添加积分到用户余额!"); + old_member = session.ChangePoint(PointType.其他奖励, _bonusSuperior, old_member.id, $"推荐新人{member.usernick}-{member.username},奖励积分{_bonusSuperior}【商户付款操作失败,请求商户链接失败】"); + ApiClient.SendMessage(e.RobotInfo, old_member.username, Config.ImmediateReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", old_member.cur_point.ToString())); + } + } + else + { + this.OnLog("推荐新人商户付款失败:奖励积分小于0.3,已添加积分到用户余额!"); + old_member = session.ChangePoint(PointType.其他奖励, _bonusSuperior, old_member.id, $"推荐新人{member.usernick}-{member.username},奖励积分{_bonusSuperior}【商户付款操作失败,积分小于0.3】"); + ApiClient.SendMessage(e.RobotInfo, old_member.username, Config.ImmediateReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", old_member.cur_point.ToString())); + } + } + else + { + old_member = session.ChangePoint(PointType.其他奖励, _bonusSuperior, old_member.id, $"推荐新人{member.usernick}-{member.username},奖励积分{_bonusSuperior}【增加积分操作】"); + ApiClient.SendMessage(e.RobotInfo, old_member.username, Config.ImmediateReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[推荐奖励金额]", _bonusSuperior.ToString()).Replace("[剩余积分]", old_member.cur_point.ToString())); + } + } + } + else + { + ApiClient.SendMessage(e.RobotInfo, old_member.username, Config.FirstSingleReward_AddANewSubordinateTip.Replace("[使用者昵称]", member.realnick).Replace("[剩余积分]", old_member.cur_point.ToString())); + } + } + } + } + else if (Config.ForcedBind == SwitchType.开启 && !Regex.IsMatch(e.Message.Trim(), Tools.Rex_Code))//强制开启并且输入的非邀请码格式的数据 + { + e.SendMessage(Config.EnterInvitationCodeTip); return; + } + } + else if (member != null && member.inviter_id != 0 && Regex.IsMatch(e.Message.Trim(), Tools.Rex_Code))//已经有上级的用户 + { + var count = int.Parse(session.FindRow("select count(*) as num from fl_plugin_userfission_user_invitation_code where code = @code", new { code = e.Message })["num"].ToString());//判断用户输入的是否为有效的邀请码 + if (count != 0) + { + e.SendMessage(Config.BindTheInvitationCodeRepeatTip); + return; + } + } + + #region 用户已经有绑定上级推荐人 或者没有开启强制开启邀请码 + if (member != null && (Config.ForcedBind != SwitchType.开启 || member.inviter_id != 0)) + { + var memberInfo = session.FindMemberinfo(e); + //海报功能开启 并且 为获取邀请码 + if ((e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信) && Config.ImageDesign == SwitchType.开启 && !string.IsNullOrWhiteSpace(Config.InviteCmd) && Regex.IsMatch(e.Message.Trim(), Config.InviteCmd.ToString())) + { + e.SendMessage(Config.PleaseWaitTip); + Controls control = null; + //邀请码 + var invitationCode = Tools.FindInvitationCode(memberInfo.id); + #region 通过海报模板绘制 推广海报 + try + { + //上面要先判断上面的图片是否已经加载到panel_Plot中 + var _controls = JsonConvert.DeserializeObject<Dictionary<string, Controls>>(Config.Controlsdic); + control = _controls["panel_Plot"]; + string url = string.Empty; + using (Bitmap bmp = new Bitmap(Image.FromFile(Tools.PosterPathImgUrl), control.C_Size)) + { + using (Graphics g = Graphics.FromImage(bmp)) + { + //绘制二维码 + control = _controls["pBox_QRcode"]; + string _QRCodeData = string.Empty; + if (Config.AutoQrCode && wx.GetType() == typeof(WXClientImpl_IPAD)) + { + var key = "qrcode_wx_" + wx.User.Username; + _QRCodeData = ApiClient.Cache.Get<string>(key); + if (string.IsNullOrEmpty(_QRCodeData)) + { + int count = 0; + while (count < 3) + { + var bitmap = wx.GetRobotQRcode(count != 0 ? true : false); + //获取机器人的二维码信息 + if (bitmap != null) + { + _QRCodeData = Util.DecodeQRCode(bitmap);//解析机器人二维码,获取到二维码的链接 + if (!string.IsNullOrEmpty(_QRCodeData)) + { + ApiClient.Cache.Set(key, _QRCodeData, 60); + break; + } + } + count++; + } + } + } + + if (string.IsNullOrWhiteSpace(_QRCodeData)) + { + //_QRCodeData = control.C_Tag;//后台二维码的内容 + + var qrCode = Config.QrCodes.FirstOrDefault(f => f.rname == wx.WeixinHao); + if (qrCode != null) + _QRCodeData = qrCode.url; + } + + if (string.IsNullOrEmpty(_QRCodeData)) + { + e.SendMessage("合成推广海报失败,请稍后重试!"); + throw new Exception($"合成推广码失败,解析机器人二维码异常."); + } + + string logourl = string.Empty; + if (Config.AutoPicture) + { + var robot = wx.GetContact(wx.User.Username); + if (string.IsNullOrEmpty(robot.BigHeadImgUrl)) robot = wx.GetContact(wx.User.Username, true); + logourl = robot.BigHeadImgUrl; + } + else if (!Config.AutoPicture && !string.IsNullOrEmpty(Config.LogoUrl)) + logourl = Config.LogoUrl.Trim(); + + if (string.IsNullOrEmpty(logourl)) logourl = string.Empty; + + Bitmap bitmapQrCode = Tools.CreateQRCode(_QRCodeData, logourl, Config.LogoSize, 5); + bitmapQrCode = new Bitmap(bitmapQrCode, control.C_Size); + g.DrawImage(bitmapQrCode, control.C_Point); + //扩展文本1 + control = _controls["lbltxt1"]; + if (control.C_Visible) + g.DrawString(control.C_Tag.ToString().Replace("[微信账号]", e.RobotName).Replace("[微信名称]", e.RobotNick).Replace("[邀请码]", Tools.FindInvitationCode(memberInfo.id)), JsonConvert.DeserializeObject<Font>(control.T_FontJson), new SolidBrush(control.T_ForeColor), control.C_Point); + //扩展文本2 + control = _controls["lbltxt2"]; + if (control.C_Visible) + g.DrawString(control.C_Tag.ToString().Replace("[微信账号]", e.RobotName).Replace("[微信名称]", e.RobotNick).Replace("[邀请码]", Tools.FindInvitationCode(memberInfo.id)), JsonConvert.DeserializeObject<Font>(control.T_FontJson), new SolidBrush(control.T_ForeColor), control.C_Point); + } + url = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + bmp.Save(url); + } + string mess = Config.ReplyToTheInvitationCodePrompt.Replace("[推广海报]", $"[图片={url}]").Replace("[邀请码]", Tools.FindInvitationCode(memberInfo.id)).Replace("[微信号]", wx.WeixinHao); + e.SendMessage(mess); + return; + } + catch (Exception ex) + { + this.OnLog("ex = " + ex.Message); + } + #endregion + } + //统计邀请 + if (!string.IsNullOrWhiteSpace(Config.RecommendedAmountCmd) && Regex.IsMatch(e.Message.Trim(), Config.RecommendedAmountCmd)) + { + e.SendMessage(new VariateReplace().CommonReplace(Config.ObtainRecommendationStatistics, e.GetMemberinfo())); + } + } + #endregion + } + break; + //case ChatType.微信公众号: + // break; + //default: + // break; + } + + } + catch (Exception ex) + { + this.OnLog("B:" + ex.Message); + e.SendMessage(ApiClient.Setting.SystemConfig.msg_error); + } + } + + /// <summary> + /// 获取上级奖励是否满足 + /// </summary> + /// <param name="info"></param> + /// <returns></returns> + private bool IsSuperiorReward(fl_robot_info info) + { + try + { + //if (info == null) return true; + + if (Config.SuperiorRewardCount <= 0) return true; + + var beginTime = DateTime.Now.Date.ToString("yyyy-MM-dd HH:mm:ss"); + var endTime = DateTime.Now.Date.AddDays(1).ToString("yyyy-MM-dd HH:mm:ss"); + var session = ApiClient.GetSession(); + var count = session.Find<fl_point_hist>("select * from fl_point_hist where @beginTime <= crt_time and crt_time < @endTime and type = @_type and rid = @rid and message like '推荐新人%'", new { beginTime = beginTime, endTime = endTime, rid = info.id, _type = "其他奖励" }).Count; + return Config.SuperiorRewardCount > count; + } + catch (Exception ex) + { } + return false; + } + + } +} diff --git a/应用/UserFission/Config.cs b/应用/UserFission/Config.cs new file mode 100644 index 0000000..986ec0c --- /dev/null +++ b/应用/UserFission/Config.cs @@ -0,0 +1,1071 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using Chat.Framework.WXSdk.IPAD; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using UI.Framework.Entitys; +using UserFission.Control_; +using UserFission.Entitys; + +namespace UserFission +{ + [Config(Name = "插件-用户裂变-配置")] + public class Config + { + + #region 海报配置 + /// <summary> + /// 自动获取二维码开关 + /// </summary> + [Browsable(false)] + public bool AutoQrCode { get; set; } + /// <summary> + /// 是否自动获取机器人头像。true:使用这群里的机器人头像。false:设置不为空的情况下,使用上传的logo + /// </summary> + [Browsable(false)] + public bool AutoPicture { get; set; } + /// <summary> + /// 上传的Logo地址 + /// </summary> + [Browsable(false)] + public string LogoUrl { get; set; } + /// <summary> + /// 设置的Logo大小 + /// </summary> + [Browsable(false)] + public int LogoSize { get; set; } + /// <summary> + /// Keys的值为控件的名称 Dictionary<string, Controls> Controlsdic + /// </summary> + [Browsable(false)] + public string Controlsdic { get; set; } + + /// <summary> + /// 二维码集合 + /// </summary> + [Browsable(false)] + public List<QrCode> QrCodes { get; set; } + #endregion + + #region QQ基础设置 + /// <summary> + /// 是否自动通过申请好友开关 + /// </summary> + [Category("1)、QQ基础设置"), DisplayName("01.自动通过好友申请开关"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将自动通过好友申请")] + public SwitchType QQ_Accept { get; set; } + + /// <summary> + /// 申请延迟时间秒数 + /// </summary> + [Category("1)、QQ基础设置"), DisplayName("02.自动通过好友申请延迟时间"), DefaultValue(10), + Description(@"自动通过好友申请功能开启时,将延迟申请通过动作")] + public int QQ_Retardation { get; set; } + + /// <summary> + /// 新人欢迎提示 + /// </summary> + [Category("1)、QQ基础设置"), DisplayName("03.新人欢迎提示"), DefaultValue(@"[昵称] +我是自动查券+返利的机器人,赶紧分享宝贝给我试试吧!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string QQ_WelcomeTip { get; set; } + + /// <summary> + /// 自动通过用户申请入群开关 + /// </summary> + [Category("1)、QQ基础设置"), DisplayName("04.自动通过用户申请入群开关"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,新用户申请入群将自动通过申请")] + public SwitchType QQ_AcceptGroupApplyForSwitch { get; set; } + + /// <summary> + /// 自动通过入群申请延迟时间 + /// </summary> + [Category("1)、QQ基础设置"), DisplayName("05.自动通过入群申请延迟时间"), DefaultValue(10), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public int QQ_RetardationAcceptGroup { get; set; } + + /// <summary> + /// 新人进群提示 + /// </summary> + [Category("1)、QQ基础设置"), DisplayName("06.新人进群提示"), DefaultValue(@"新增群成员[昵称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[群昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string QQ_GroupWelcomeTip { get; set; } + #endregion + + #region QQ推广功能 + + /// <summary> + /// 邀请推荐功能 + /// </summary> + [Category("2)、QQ推广功能"), DisplayName("01.QQ群邀请绑定功能"), DefaultValue(SwitchType.开启), + Description(@"QQ群邀请绑定功能开启时,新用户为老用户邀请进入,这会绑定上下级关系")] + public SwitchType QQInviteBindSwitch { get; set; } + + /// <summary> + /// QQ推荐客户成功 + /// </summary> + [Category("2)、QQ推广功能"), DisplayName("02.推荐QQ群新人成功"), DefaultValue(@"一一一一推 荐 成 功一一一一 +【群信息】[群昵称]([群账号]) +【新用户】[昵称]([账号]) +【可提现】[剩余积分] [积分名称] + +您可以发送【兑换】,领取现金哦!"), + Description(@"【推荐新人立马奖励】 和 【新人完成首单】 的提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[群昵称]、[群账号]、[剩余积分]、[积分名称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string QQGroupInviteBind_AddANewSubordinateTip { get; set; } + + #endregion + + #region 微信基础设置 + /// <summary> + /// 是否自动通过申请好友开关 + /// </summary> + [Category("3)、微信基础设置"), DisplayName("01.自动通过好友申请开关"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将自动通过好友申请")] + public SwitchType Accept { get; set; } + + /// <summary> + /// 同意好友性别 + /// </summary> + [ + Category("3)、微信基础设置"), DisplayName("02.同意性别选项"), DefaultValue(@"男,女,未知"), + Description(@"自动通过类目:男、女、未知"), + Editor(typeof(CategoryControl), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string GenderType { get; set; } + + /// <summary> + /// 申请延迟时间秒数 + /// </summary> + [Category("3)、微信基础设置"), DisplayName("03.自动通过好友申请延迟时间"), DefaultValue(10), + Description(@"自动通过好友申请功能开启时,将延迟申请通过动作")] + public int Retardation { get; set; } + + /// <summary> + /// 新人欢迎提示 + /// </summary> + [Category("3)、微信基础设置"), DisplayName("04.新人欢迎提示 - 无邀请"), DefaultValue(@"[昵称] +我是自动查券+返利的机器人,赶紧分享宝贝给我试试吧!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string WelcomeTip { get; set; } + + /// <summary> + /// 新人欢迎提示 + /// </summary> + [Category("3)、微信基础设置"), DisplayName("05.新人欢迎提示 - 受邀请"), DefaultValue(@"[昵称] +【邀请人】:[邀请人昵称] +我是自动查券+返利的机器人,赶紧分享宝贝给我试试吧!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[邀请人昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string WelcomeBeInvitedTip { get; set; } + + /// <summary> + /// 拉群开关 + /// </summary> + [Category("3)、微信基础设置"), DisplayName("06.邀请入群开关"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,满足入群条件的将发群卡片进行邀请")] + public SwitchType InvitedIntoGroupSwitch { get; set; } + + /// <summary> + /// 拉群邀请提示语 + /// </summary> + [Category("3)、微信基础设置"), DisplayName("07.邀请入群提示"), DefaultValue(@"感谢您长久以来的支持 +此群为我们的【VIP群】"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string InvitedIntoGroupTip { get; set; } + + /// <summary> + /// 新人欢迎提示 + /// </summary> + [Category("3)、微信基础设置"), DisplayName("08.新人进群提示"), DefaultValue(@"新增群成员[昵称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[群昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string GroupWelcomeTip { get; set; } + + #endregion + + #region 微信推广功能 + /// <summary> + /// 强制绑定上下级 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("01.强制绑定上下级"), DefaultValue(SwitchType.关闭), + Description(@"强制绑定上下级关系。在功能开启时,没有上级的用户将会受到限制")] + public SwitchType ForcedBind { get; set; } + + /// <summary> + /// 名片推荐好友,自动关联上下级关系开关 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("02.新人进群绑定上下级"), DefaultValue(SwitchType.关闭), + Description(@"名片推荐好友,相互通过后,自动绑定上下级用户关系。")] + public SwitchType GroupBind { get; set; } + + /// <summary> + /// 邀请推荐功能 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("03.邀请推荐功能"), DefaultValue(SwitchType.开启), + Description(@"邀请推荐功能开启时,则上下级关系绑定功能会开启.")] + public SwitchType ImageDesign { get; set; } + + /// <summary> + /// 名片推荐好友,自动关联上下级关系开关 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("04.名片推荐功能"), DefaultValue(SwitchType.开启), + Description(@"名片推荐好友,相互通过后,自动绑定上下级用户关系")] + public SwitchType Bind { get; set; } + + /// <summary> + /// 上级奖励开关 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("05.推荐奖励开关"), DefaultValue(SwitchType.关闭), + Description(@"功能开启时,推荐的好友成功通过申请,并且绑定推荐人的信息,推荐人将获得奖励")] + public SwitchType SuperiorSumSwitch { get; set; } + + /// <summary> + /// 推荐者奖励方式 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("06.推荐者奖励方案"), DefaultValue(ReferralJackpotType.新人完成首单奖励), + Description(@"该功能结合推荐奖励开关一起使用,当推荐奖励开启时,推荐人的获得奖励方式")] + public ReferralJackpotType SuperiorRewardWay { get; set; } + + /// <summary> + /// 推荐者奖励次数 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("07.当天推荐者奖励发放数量"), DefaultValue(0), + Description(@"每天推荐者奖励发放数量,超过奖励数量将终止奖励. +注:数量设置为0时不限制奖励数量")] + public int SuperiorRewardCount { get; set; } + + /// <summary> + /// 下级首单付款金额 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("08.推荐者奖励 - 下级首单付款金额"), DefaultValue(20), + Description(@"推荐者奖励方案为新人首单满足付款金额奖励时,订单结算后,推荐的好友付款金额必须大于等于设置值,推荐者才将获得奖励 +注:直到用户订单满足条件,才会奖励推荐者")] + public double SuperiorReward_FirstSinglePaymentSum { get; set; } + + /// <summary> + /// 上级奖励最小值 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("09.推荐最小奖励"), DefaultValue(0.05), + Description(@"上级奖励功能开启时,推荐的好友成功通过申请,并且绑定推荐人的信息,推荐人将获得奖励的最小值")] + public double SuperiorSum1 { get; set; } + + /// <summary> + /// 上级奖励最大值 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("10.推荐最大奖励"), DefaultValue(0.15), + Description(@"上级奖励功能开启时,推荐的好友成功通过申请,并且绑定推荐人的信息,推荐人将获得奖励的最大值")] + public double SuperiorSum2 { get; set; } + + + [ +Category("4)、微信推广功能"), DisplayName("11.下级N小时内完成首单"), DefaultValue(SwitchType.关闭), +Description(@"下级用户N小时内首次付款,收货并结算后,给推荐者额外奖励 +本功能在【推荐者奖励方案06】中,设置为【新人完成首单奖励模式】中有效")] + public SwitchType ExtraBonus_SwitchType { get; set; } = SwitchType.关闭; + + [ +Category("4)、微信推广功能"), DisplayName("12.完成首单时间(单位小时)"), DefaultValue(24), +Description(@"下级用户N小时内首次付款,收货并结算后,给推荐者额外奖励 +本功能在【推荐者奖励方案06】中,设置为【新人完成首单奖励模式】中有效")] + public int ExtraBonus_ValidDay { get; set; } = 24; + + [ +Category("4)、微信推广功能"), DisplayName("13.完成奖励金额"), DefaultValue(0.3d), +Description(@"下级用户N小时内首次付款,收货并结算后,给推荐者额外奖励 +本功能在【推荐者奖励方案06】中,设置为【新人完成首单奖励模式】中有效")] + public double ExtraBonus { get; set; } = 0.3d; + + /// <summary> + /// 上级奖励发包模式 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("14.推荐者奖励方式"), DefaultValue(RechargeType.增加余额), + Description(@"上级奖励方式: +1)、增加余额 +2)、发送红包 +3)、商户付款 +4)、微信余额")] + public RechargeType Superior_RechargeType { get; set; } + + /// <summary> + /// 上级奖励通知 - 商户付款 + /// </summary> + [ + Category("4)、微信推广功能"), DisplayName("15.推荐者奖励通知 - 商户付款"), DefaultValue(@"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[领取地址]、[推荐奖励金额]、[下级昵称]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SuperiorCommercialPayTip { get; set; } + + /// <summary> + /// 上级奖励通知 - 商户付款直接到账 + /// </summary> + [ + Category("4)、微信推广功能"), DisplayName("16.推荐者奖励通知 - 商户付款直接到账"), DefaultValue(@"一一一一商 户 转 账 成 功一一一一 +[推荐奖励金额]兑换成功 +已直接转入您的账户!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[推荐奖励金额]、[下级昵称]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SuperiorCommercialEftTip { get; set; } + + /// <summary> + /// 推荐客户成功 - 推荐新人立马奖励 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("17.推荐新人成功"), DefaultValue(@"一一一一推 荐 成 功一一一一 +【使用者】[使用者昵称] +【奖励额】[推荐奖励金额] [积分名称] +【可提现】[剩余积分] [积分名称] + +您可以发送【兑换】,领取现金哦!"), + Description(@"【推荐新人立马奖励】 和 【新人完成首单】 的提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[使用者昵称]、[推荐奖励金额]、[剩余积分]、[积分名称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ImmediateReward_AddANewSubordinateTip { get; set; } + + /// <summary> + /// 推荐客户成功 - 新人完成首单奖励 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("18.推荐客户成功 - 新人还未完成首单奖励"), DefaultValue(@"一一一一推 荐 成 功一一一一 +【使用者】[使用者昵称] +【可提现】[剩余积分] [积分名称] + +您可以发送【兑换】,领取现金哦!"), + Description(@"推荐者奖励方案设置为新人完成首单奖励 并且用户还未完成首单 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[使用者昵称]、[剩余积分]、[积分名称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string FirstSingleReward_AddANewSubordinateTip { get; set; } + + /// <summary> + /// 新用户奖励开关 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("19.新人奖励开关"), DefaultValue(SwitchType.关闭), +Description(@"功能开启时,成功通过好友申请,用户将获得奖励")] + public SwitchType SubordinateSumSwitch { get; set; } + + /// <summary> + /// 新用户查询奖励开关 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("20.新人奖励方案"), DefaultValue(NewcomerAwardType.通过立即奖励), +Description(@"通过立即奖励:成功通过好友申请,用户将获得奖励 +首次查券奖励:成功通过好友申请,并且该好友首次查券,用户将获得奖励")] + public NewcomerAwardType SubordinateRewardWay { get; set; } + + /// <summary> + /// 新用户奖励最小值 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("21.新人最小奖励"), DefaultValue(0.08), +Description(@"新用户奖励功能开启时,成功通过好友申请,用户获得奖励的最小值")] + public double SubordinateSum1 { get; set; } + + /// <summary> + /// 新用户奖励金额2 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("22.新人最大奖励"), DefaultValue(0.18), +Description(@"新用户奖励功能开启时,成功通过好友申请,用户获得奖励的最大值")] + public double SubordinateSum2 { get; set; } + + /// <summary> + /// 新用户奖励发包模式 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("23.新人奖励方式"), DefaultValue(RechargeType.增加余额), + Description(@"新人奖励方式: +1)、增加余额 +2)、发送红包 +3)、商户付款 +4)、微信余额")] + public RechargeType Subordinate_RechargeType { get; set; } + + /// <summary> + /// 新人奖励通知 - 通过立即奖励 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("24.新人奖励通知 - 通过立即奖励"), DefaultValue(@"一一一一奖 励 通 知一一一一 +奖励已发放 + +分享链接给我,我帮您省钱!"), + Description(@"推荐者奖励方案设置为新人完成首单奖励 并且用户还未完成首单 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[奖励金额]、[剩余积分]、[积分名称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string Subordinate_AdditionalTip { get; set; } + + /// <summary> + /// 新人奖励通知 - 通过立即奖励 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("25.新人奖励通知 - 首次查券奖励"), DefaultValue(@"一一一一奖 励 通 知一一一一 +奖励已发放 + +分享链接给我,我帮您省钱!"), + Description(@"推荐者奖励方案设置为新人完成首单奖励 并且用户还未完成首单 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[奖励金额]、[剩余积分]、[积分名称]、[商品价格]、[商品优惠券]、[用户返利]、[共节省]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string Subordinate_AdditionalTip_Query { get; set; } + + /// <summary> + /// 新人奖励通知 - 商户付款 + /// </summary> + [ + Category("4)、微信推广功能"), DisplayName("26.新人奖励通知 - 商户付款"), DefaultValue(@"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[领取地址]、[奖励金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SubordinateCommercialPayTip { get; set; } + + /// <summary> + /// 新人奖励通知 - 商户付款直接到账 + /// </summary> + [ + Category("4)、微信推广功能"), DisplayName("27.新人奖励通知 - 商户付款直接到账"), DefaultValue(@"一一一一商 户 转 账 成 功一一一一 +[奖励金额]兑换成功 +已直接转入您的账户!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[奖励金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SubordinateCommercialEftTip { get; set; } + + #region 新人首单奖励 + + /// <summary> + /// 新用户首单奖励开关 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("28.新人首单奖励开关"), DefaultValue(SwitchType.关闭), +Description(@"功能开启时,用户完成第一笔订单交易,用户将获得奖励")] + public SwitchType FirstOrder_SumSwitch { get; set; } + + /// <summary> + /// 首单奖励新人类型 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("29.首单奖励新人类型"), DefaultValue(InitialAwardNewcomerType.所有新用户), +Description(@"所有新用户:奖励的对象为所有新用户 +被邀请用户:奖励的对象为有上级的新用户 +非邀请用户:奖励的对象为没有上级的新用户")] + public InitialAwardNewcomerType FirstOrder_InitialAwardNewcomerType { get; set; } + + /// <summary> + /// 新用户查询奖励开关 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("30.新人首单奖励方案"), DefaultValue(NewcomerInitialAwardType.订单结算后奖励), +Description(@"订单付款:首笔订单付款后,用户将获得首单奖励奖励 +订单结算:首笔订单结算后,用户将获得首单奖励奖励")] + public NewcomerInitialAwardType FirstOrderAwardWay { get; set; } + + /// <summary> + /// 新用户首单奖励最小值 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("31.新人首单最小奖励"), DefaultValue(2), +Description(@"新用户首单奖励功能开启时,该用户完成首单,用户获得奖励的最小值")] + public double FirstOrder_Sum1 { get; set; } + + /// <summary> + /// 新用户首单奖励金额2 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("32.新人首单最大奖励"), DefaultValue(2), +Description(@"新用户首单奖励功能开启时,该用户完成首单,用户获得奖励的最大值")] + public double FirstOrder_Sum2 { get; set; } + + /// <summary> + /// 新用户首单奖励发包模式 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("33.新人首单奖励方式"), DefaultValue(RechargeType.增加余额), + Description(@"新人奖励方式: +1)、增加余额 +2)、发送红包 +3)、商户付款 +4)、微信余额")] + public RechargeType FirstOrder_RechargeType { get; set; } + + /// <summary> + /// 新人首单奖励通知 - 商户付款 + /// </summary> + [ + Category("4)、微信推广功能"), DisplayName("34.新人首单奖励通知 - 商户付款"), DefaultValue(@"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[领取地址]、[首单奖励金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string FirstOrder_CommercialPayTip { get; set; } + + /// <summary> + /// 新人首单奖励通知 - 商户付款直接到账 + /// </summary> + [ + Category("4)、微信推广功能"), DisplayName("35.新人首单奖励通知 - 商户付款直接到账"), DefaultValue(@"一一一一商 户 转 账 成 功一一一一 +[首单奖励金额]兑换成功 +已直接转入您的账户!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[首单奖励金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string FirstOrder_CommercialEftTip { get; set; } + + /// <summary> + /// 新用户完成首单奖励 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("36.新用户完成首单奖励"), DefaultValue(@"一一一一首 单 奖 励一一一一 +【昵称】[昵称] +【奖励额】[首单奖励金额] [积分名称] +【可提现】[剩余积分] [积分名称] + +您可以发送【兑换】,领取现金哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[首单奖励金额]、[剩余积分]、[积分名称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string NewUserFirstOrderCompletedTip { get; set; } + + #endregion + + /// <summary> + /// 微信自动转账红包标题 + /// </summary> + [ + Category("4)、微信推广功能"), DisplayName("37.红包标题"), DefaultValue(@"获得奖励:[兑换金额]"), + Description(@"当开启新人奖励,并且发送方式为发送红包,本处设置为红包的标题! +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangePacketTitle { get; set; } + + /// <summary> + /// 获取邀请码的指令 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("38.获取邀请码指令"), DefaultValue(@"^(生成|获取|给我)(邀请码|推广码)$"), + Description(@"通过获取邀请码指令,获取用户自己的推广海报.支持正则表达式")] + public string InviteCmd { get; set; } + + /// <summary> + /// 获取邀请统计的指令 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("39.查邀请统计指令"), DefaultValue(@"^(邀请统计|邀请记录)$"), + Description(@"通过邀请统计指令,统计用户邀请数量.支持正则表达式")] + public string RecommendedAmountCmd { get; set; } + + /// <summary> + /// 获取推荐统成功计语 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("40.查看邀请统计"), DefaultValue(@"一一一一邀 请 数 据一一一一 +【邀请人数】[推荐人数] +【完成首单人数】[完成首单人数] +【未完成首单人数】[未完成首单人数] + +分享我名片给您的好友一起来使用吧!"), + Description(@"支持变量:[账号]、[昵称]、[推荐人数]、[完成首单人数]、[未完成首单人数]、[下级列表]、[三级有效人数]、[三级邀请人数]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ObtainRecommendationStatistics { get; set; } + + /// <summary> + /// 正在生成邀请码 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("41.正在生成邀请码"), DefaultValue(@"生成中,请稍等...."), + Description(@"通过获取邀请码指令,获取用户自己的推广海报,温馨提示语,可为空")] + public string PleaseWaitTip { get; set; } + + /// <summary> + /// 输入邀请码提示 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("42.输入邀请码提示"), DefaultValue(@"请输入邀请码"), + Description(@"当强制绑定上下级关系时,没有上级的用户将会收到该提示 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string EnterInvitationCodeTip { get; set; } + + /// <summary> + /// 获取邀请码成功提示语 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("43.获得邀请码成功"), DefaultValue(@"[推广海报] +一一一一邀 请 码一一一一 +【邀请码】[邀请码] +【微信号】[机器人账号] + +复制本条消息给您朋友,加我就可以查券领返利咯!"), + Description(@"获得邀请码成功的提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[推广海报]、[邀请码]、[微信号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ReplyToTheInvitationCodePrompt { get; set; } + #endregion + + #region 邀请设置 + + /// <summary> + /// 绑定邀请码成功 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("41.绑定邀请码成功"), DefaultValue(@"一一一一激 活 成 功一一一一 +【使用者】[昵称] +【邀请人】[邀请人昵称] + +已获得查优惠特权,赶紧试试吧!"), + Description(@"绑定邀请码成功提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[邀请人昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string BindTheInvitationCodeSuccessfully { get; set; } + + /// <summary> + /// 重复绑定邀请码 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("42.重复绑定邀请码"), DefaultValue(@"一一一一激 活 失 败一一一一 +您已经绑定过了,请勿重复绑定~"), + Description(@"已经有上级的用户发送邀请码提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string BindTheInvitationCodeRepeatTip { get; set; } + + /// <summary> + /// 自己绑定自己 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("43.自己绑定自己"), DefaultValue(@"一一一一激 活 失 败一一一一 +自己的邀请码,禁止绑定自己哦~"), + Description(@"自己的邀请码绑定自己的账号错误的提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string BindTheInvitationCodeOneselfTip { get; set; } + + /// <summary> + /// 用户相互绑定 + /// </summary> + [Category("4)、微信推广功能"), DisplayName("44.客户相互绑定"), DefaultValue(@"一一一一激 活 失 败一一一一 +自己下级,禁止绑定为自己上级哦~"), + Description(@"下级的邀请码绑定自己的账号错误的提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string InviteEachOtherTip { get; set; } + + #endregion + + #region + /// <summary> + /// 新用户首次付款额外提示开关 + /// </summary> + [Category("5)、激活新粉设置"), DisplayName("01.新用户首次付款额外提示开关"), DefaultValue(SwitchType.关闭), + Description(@"新用户首次付款额外提示提示语开关")] + public SwitchType Extra_FirstPay_Tip_Switch { get; set; } + + /// <summary> + /// 上级奖励发包模式 + /// </summary> + [Category("5)、激活新粉设置"), DisplayName("02.新用户首次付款额外提示"), DefaultValue(@"一一一一温 馨 提 示一一一一 +"), + Description(@"新用户首次付款额外提示提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]")] + public string Extra_FirstPay_Tip { get; set; } + + #endregion + + + #region + /// <summary> + /// 上级奖励发包模式 + /// </summary> + [Category("6)、推广者分红奖励"), DisplayName("01.推荐者分红奖励方式"), DefaultValue(RechargeType.增加余额), + Description(@"上级奖励方式: +1)、增加余额 +2)、发送红包 +3)、商户付款 +4)、微信余额")] + public RechargeType Superior_DividendType { get; set; } + + /// <summary> + /// 上级奖励通知 - 商户付款 + /// </summary> + [ + Category("6)、推广者分红奖励"), DisplayName("02.推荐者分红奖励通知 - 商户付款"), DefaultValue(@"一一一一分 红 奖 励一一一一 + +下级有效订单达到:[下级有效订单数]笔 +您将获得分红奖励:[分红奖励金额][积分名称] + +[领取地址] + +点击链接,领取红包到您钱包!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[领取地址]、[下级有效订单数]、[分红奖励金额]、[下级昵称]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SuperiorDividendCommercialPayTip { get; set; } + + /// <summary> + /// 上级奖励通知 - 商户付款 + /// </summary> + [ + Category("6)、推广者分红奖励"), DisplayName("03.推荐者分红奖励通知 - 商户付款直接到账"), DefaultValue(@"一一一一分 红 奖 励一一一一 + +下级有效订单达到:[下级有效订单数]笔 +获得分红奖励:[分红奖励金额][积分名称] + +已直接转入您的账户!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[下级有效订单数]、[分红奖励金额]、[下级昵称]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SuperiorDividendCommercialEftTip { get; set; } + + /// <summary> + /// 推荐客户成功 - 推荐新人立马奖励 + /// </summary> + [Category("6)、推广者分红奖励"), DisplayName("03.推荐者分红奖励通知"), DefaultValue(@"一一一一分 红 奖 励一一一一 + +【下级有效订单达到】[下级有效订单数]笔 +【本次获得分红奖励】[分红奖励金额][积分名称] +【当前可提现】[剩余积分][积分名称] + +您可以发送【兑换】,领取现金哦!"), + Description(@"非商户付款的提示语 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[下级有效订单数]、[分红奖励金额]、[剩余积分]、[下级昵称]、[积分名称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SuperiorDividendPayTip { get; set; } + + #endregion + + #region 其他设置 + [ +Category("7)、其他设置"), DisplayName("01.商品首次查询通用提示语"), DefaultValue(@""), + Description(@"用户首次查询商品附加提示语,无券/有券/无返利的商品只会提示一次 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品原价]、[商品标题]、[优惠券金额]、[用户佣金]、[优惠券金额]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string FirstQueryGoodsTip { get; set; } = string.Empty; + + [ + Category("7)、其他设置"), DisplayName("02.商品首次查询所有状态,只提示一次开关"), DefaultValue(SwitchType.关闭), + Description(@"商品首次查询,所有商品状态(有券,无券,无返利),开启的情况下,以下所有设置只提示一次(3、4、5设置项)")] + public SwitchType FirstQueryGoodsTip_Switch { get; set; } = SwitchType.关闭; + + [ +Category("7)、其他设置"), DisplayName("03.商品首次查询无返利提示语"), DefaultValue(@""), +Description(@"用户首次查询商品无返利附加提示语,无返状态的商品只会提示一次 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), +Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string FirstQueryGoodsTip_UnFan { get; set; } = string.Empty; + + [ +Category("7)、其他设置"), DisplayName("04.商品首次查询有券提示语"), DefaultValue(@""), +Description(@"用户首次查询商品有券附加提示语,有券状态的商品只会提示一次 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品原价]、[商品标题]、[优惠券金额]、[用户佣金]、[优惠券金额]"), +Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string FirstQueryGoodsTip_Coupon { get; set; } = string.Empty; + + [ +Category("7)、其他设置"), DisplayName("05.商品首次查询无券提示语"), DefaultValue(@""), +Description(@"用户首次查询商品无券附加提示语,无券状态的商品只会提示一次 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品原价]、[商品标题]、[优惠券金额]、[用户佣金]、[优惠券金额]"), +Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string FirstQueryGoodsTip_UnCoupon { get; set; } = string.Empty; + + [ +Category("7)、其他设置"), DisplayName("06.商户付款通知(优先使用小程序)"), DefaultValue(SwitchType.开启), +Description(@"如果商户支持小程序,将会优先推送小程序模板!(届时商户相关的设置的提示语,将不会推送)")] + public SwitchType ShangHu_MiNiApp { get; set; } = SwitchType.开启; + #endregion + + #region 额外奖励 +// [ +//Category("8)、额外奖励"), DisplayName("01.N小时内下级付款上级额外奖励"), DefaultValue(SwitchType.关闭), +//Description(@"下级用户N小时内首次付款,收货后,给推荐者额外奖励")] +// public SwitchType ExtraBonus_SwitchType { get; set; } = SwitchType.关闭; + +// [ +//Category("8)、额外奖励"), DisplayName("02.设置有效小时"), DefaultValue(24), +//Description(@"下级用户N小时内首次付款,收货后,给推荐者额外奖励")] +// public int ExtraBonus_ValidDay { get; set; } = 24; + +// [ +//Category("8)、额外奖励"), DisplayName("03.额外奖励金额"), DefaultValue(0.3d), +//Description(@"如果商户支持小程序,将会优先推送小程序模板!(届时商户相关的设置的提示语,将不会推送)")] +// public double ExtraBonus { get; set; } = 0.3d; + +// /// <summary> +// /// 上级奖励发包模式 +// /// </summary> +// [Category("8)、额外奖励"), DisplayName("04.推荐者额外奖励方式"), DefaultValue(RechargeType.增加余额), +// Description(@"上级奖励方式: +//1)、增加余额 +//2)、发送红包 +//3)、商户付款 +//4)、微信余额")] +// public RechargeType ExtraBonus_RechargeType { get; set; } = RechargeType.增加余额; + +// /// <summary> +// /// 上级奖励通知 - 商户付款 +// /// </summary> +// [ +// Category("8)、额外奖励"), DisplayName("05.推荐者额外奖励方式"), DefaultValue(@"一一一一等 待 领 取一一一一 + +//[领取地址] + +//点击链接,领取红包到您钱包!"), +// Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[领取地址]、[奖励金额]、[下级昵称]、[积分名称]"), +// Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +// ] +// public string ExtraBonusCommercialPayTip { get; set; } = @"一一一一等 待 领 取一一一一 + +//[领取地址] + +//点击链接,领取红包到您钱包!"; + +// /// <summary> +// /// 上级奖励通知 - 商户付款直接到账 +// /// </summary> +// [ +// Category("8)、额外奖励"), DisplayName("06.推荐者额外奖励通知 - 商户付款直接到账"), DefaultValue(@"一一一一商 户 转 账 成 功一一一一 +//[奖励金额]兑换成功 +//已直接转入您的账户!"), +// Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[奖励金额]、[下级昵称]、[积分名称]"), +// Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +// ] +// public string ExtraCommercialEftTip { get; set; } = @"一一一一商 户 转 账 成 功一一一一 +//[奖励金额]兑换成功 +//已直接转入您的账户!"; + +// /// <summary> +// /// 新用户完成首付款上级奖励 +// /// </summary> +// [Category("8)、额外奖励"), DisplayName("07.新用户完成首单奖励推荐者"), DefaultValue(@"一一一一额 外 奖 励一一一一 +//【昵称】[昵称] +//【奖励额】[奖励金额] [积分名称] +//【可提现】[剩余积分] [积分名称] + +//您可以发送【兑换】,领取现金哦!"), +// Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[奖励金额]、[剩余积分]、[积分名称]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] +// public string ExtraBonusCompletedTip { get; set; } = @"一一一一额 外 奖 励一一一一 +//【昵称】[昵称] +//【奖励额】[奖励金额] [积分名称] +//【可提现】[剩余积分] [积分名称] + +//您可以发送【兑换】,领取现金哦!"; + + #endregion + + /// <summary> + /// 新用户提示开始时间 + /// </summary> + [Browsable(false)] + public DateTime NewUserTipStartTime { get; set; } = DateTime.MinValue; + + /// <summary> + /// 邀请入群方式 (true为完成多少订单后邀请入群,false为新加邀请入群) + /// </summary> + [Browsable(false)] + public bool InvitegroupWay { get; set; } + + /// <summary> + /// 完成订单规则 + /// </summary> + [Browsable(false)] + public int FinishOrder_Rule { get; set; } + + /// <summary> + /// 设置入群设置 + /// </summary> + [Browsable(false)] + public Dictionary<string, wx_info> InviteGroupInfo { get; set; } + + /// <summary> + /// 设置入群提示开关 + /// </summary> + [Browsable(false)] + public Dictionary<string, wx_info> NewComerGroupInfo { get; set; } + + /// <summary> + /// 设置入群设置 + /// </summary> + [Browsable(false)] + public Dictionary<string, wxinfo> InviteGroupInfo2 { get; set; } + + /// <summary> + /// 设置入群提示开关 + /// </summary> + //[Browsable(false)] + //public Dictionary<string, wxinfo> NewComerGroupInfo2 { get; set; } + + public Config() + { + Extra_FirstPay_Tip_Switch = SwitchType.关闭; + Extra_FirstPay_Tip = @"一一一一温 馨 提 示一一一一 +"; + + #region QQ基础设置 + this.QQ_Accept = SwitchType.开启; + this.QQ_Retardation = 10; + this.QQ_WelcomeTip = @"[昵称] +我是自动查券+返利的机器人,赶紧分享宝贝给我试试吧!"; + this.QQ_AcceptGroupApplyForSwitch = SwitchType.开启; + this.QQ_RetardationAcceptGroup = 10; + this.QQ_GroupWelcomeTip = @"新增群成员[昵称]"; + #endregion + + this.QQInviteBindSwitch = SwitchType.开启; + + this.QQGroupInviteBind_AddANewSubordinateTip = @"一一一一推 荐 成 功一一一一 +【群信息】[群昵称]([群账号]) +【新用户】[昵称]([账号]) +【可提现】[剩余积分] [积分名称] + +您可以发送【兑换】,领取现金哦!"; + + #region 初始化基础设置 + this.GroupBind = SwitchType.关闭; + + this.InvitegroupWay = true; + this.FinishOrder_Rule = 3; + this.InviteGroupInfo = new Dictionary<string, wx_info>(); + this.NewComerGroupInfo = new Dictionary<string, wx_info>(); + + this.GenderType = @"男,女,未知"; + this.Accept = SwitchType.开启; + this.Bind = SwitchType.开启; + this.ForcedBind = SwitchType.关闭; + this.ImageDesign = SwitchType.开启; + this.Retardation = 10; + this.InviteCmd = @"^(生成|获取|给我)(邀请码|推广码)$"; + this.RecommendedAmountCmd = @"^(邀请统计|邀请记录)$"; + this.SuperiorRewardCount = 0; + this.AutoQrCode = true; + this.AutoPicture = true; + this.SubordinateSumSwitch = SwitchType.关闭; + this.SubordinateRewardWay = NewcomerAwardType.通过立即奖励; + this.SubordinateSum1 = 0.08; + this.SubordinateSum2 = 0.18; + this.SuperiorSumSwitch = SwitchType.关闭; + this.SuperiorRewardWay = ReferralJackpotType.新人完成首单奖励; + this.SuperiorReward_FirstSinglePaymentSum = 20; + this.SuperiorSum1 = 0.05; + this.SuperiorSum2 = 0.15; + this.LogoSize = 30; + this.Controlsdic = "{\"lbltxt2\":{\"C_Name\":\"lbltxt2\",\"C_Point\":\"15, 459\",\"C_Size\":\"230, 22\",\"C_Visible\":true,\"C_Tag\":\"微信名称:[微信名称]\",\"T_FontJson\":\"\\\"宋体, 16pt\\\"\",\"T_ForeColor\":\"255, 121, 250\",\"T_Width\":230,\"T_Height\":22},\"lbltxt1\":{\"C_Name\":\"lbltxt1\",\"C_Point\":\"37, 425\",\"C_Size\":\"186, 22\",\"C_Visible\":true,\"C_Tag\":\"邀请码:[邀请码]\",\"T_FontJson\":\"\\\"宋体, 16pt\\\"\",\"T_ForeColor\":\"51, 255, 33\",\"T_Width\":186,\"T_Height\":22},\"pBox_QRcode\":{\"C_Name\":\"pBox_QRcode\",\"C_Point\":\"99, 65\",\"C_Size\":\"134, 131\",\"C_Visible\":false,\"C_Tag\":\"\",\"T_FontJson\":null,\"T_ForeColor\":\"\",\"T_Width\":0,\"T_Height\":0},\"panel_Plot\":{\"C_Name\":\"panel_Plot\",\"C_Point\":\"16, 17\",\"C_Size\":\"359, 521\",\"C_Visible\":false,\"C_Tag\":null,\"T_FontJson\":\"\\\"宋体, 9pt\\\"\",\"T_ForeColor\":\"\",\"T_Width\":0,\"T_Height\":0}}"; + #endregion + + this.QrCodes = new List<QrCode>(); + + #region 初始化提示语 + + // this.BindTheInvitationCardSuccessfully = @"一一一一绑 定 成 功一一一一 + //【昵称】[下级昵称] + //【推广人数】[推广人数] + //【可提现】[剩余积分] [积分名称]"; + // this.BindTheInvitationCardRepeatTip = @"一一一一重 复 绑 定一一一一 + //【昵称】[下级昵称] 已为你的下级无需重复绑定 + //【推广人数】[推广人数] + //【可提现】[剩余积分] [积分名称]"; + // this.BindTheInvitationCardNotFriend = @"一一一一无 效 绑 定一一一一 + //请将机器人名片发送给微信好友[下级昵称]好友添加后软件会自动绑定到您的名下"; + // this.BindTheInvitationCardRepeat = @"一一一一占 用 绑 定一一一一 + //【昵称】[下级昵称] 用户已有上级 + //【推广人数】[推广人数] + //【可提现】[剩余积分] [积分名称]"; + + this.InvitedIntoGroupSwitch = SwitchType.开启; + this.InvitedIntoGroupTip = @"感谢您长久以来的支持 +此群为我们的【VIP群】"; + + this.Superior_RechargeType = RechargeType.增加余额; + this.Subordinate_RechargeType = RechargeType.增加余额; + this.Subordinate_AdditionalTip = @"一一一一奖 励 通 知一一一一 +奖励已发放 + +分享链接给我,我帮您省钱!"; + this.Subordinate_AdditionalTip_Query = @"一一一一奖 励 通 知一一一一 +奖励已发放 + +分享链接给我,我帮您省钱!"; + this.SuperiorCommercialPayTip = @"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"; + this.SuperiorCommercialEftTip = @"一一一一商 户 转 账 成 功一一一一 +[推荐奖励金额]兑换成功 +已直接转入您的账户!"; + this.SubordinateCommercialPayTip = @"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"; + this.FirstOrder_SumSwitch = SwitchType.关闭; + this.FirstOrder_InitialAwardNewcomerType = InitialAwardNewcomerType.所有新用户; + this.FirstOrderAwardWay = NewcomerInitialAwardType.订单结算后奖励; + this.FirstOrder_Sum1 = 2; + this.FirstOrder_Sum2 = 2; + this.FirstOrder_RechargeType = RechargeType.增加余额; + this.FirstOrder_CommercialPayTip = @"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"; + this.FirstOrder_CommercialEftTip = @"一一一一商 户 转 账 成 功一一一一 +[首单奖励金额]兑换成功 +已直接转入您的账户!"; + this.SubordinateCommercialEftTip = @"一一一一商 户 转 账 成 功一一一一 +[奖励金额]兑换成功 +已直接转入您的账户!"; + this.WelcomeTip = @"[昵称] +我是自动查券+返利的机器人,赶紧分享宝贝给我试试吧!"; + this.WelcomeBeInvitedTip = @"[昵称] +【邀请人】:[邀请人昵称] +我是自动查券+返利的机器人,赶紧分享宝贝给我试试吧!"; + this.GroupWelcomeTip = @"新增群成员[昵称]"; + this.PleaseWaitTip = @"生成中,请稍等...."; + this.EnterInvitationCodeTip = "请输入邀请码"; + this.ReplyToTheInvitationCodePrompt = @"[推广海报] +一一一一邀 请 码一一一一 +【邀请码】[邀请码] +【微信号】[机器人账号] + +复制本条消息给您朋友,加我就可以查券领返利咯!"; + this.ImmediateReward_AddANewSubordinateTip = @"一一一一推 荐 成 功一一一一 +【使用者】[使用者昵称] +【奖励额】[推荐奖励金额] [积分名称] +【可提现】[剩余积分] [积分名称] + +您可以发送【兑换】,领取现金哦!"; + this.FirstSingleReward_AddANewSubordinateTip = @"一一一一推 荐 成 功一一一一 +【使用者】[使用者昵称] +【可提现】[剩余积分] [积分名称] + +您可以发送【兑换】,领取现金哦!"; + this.BindTheInvitationCodeSuccessfully = @"一一一一激 活 成 功一一一一 +【使用者】[昵称] +【邀请人】[邀请人昵称] + +已获得查优惠特权,赶紧试试吧!"; + this.BindTheInvitationCodeRepeatTip = @"一一一一激 活 失 败一一一一 +您已经绑定过了,请勿重复绑定~"; + this.BindTheInvitationCodeOneselfTip = @"一一一一激 活 失 败一一一一 +自己的邀请码,禁止绑定自己哦~"; + this.ObtainRecommendationStatistics = @"一一一一邀 请 统 计一一一一 +【邀请人数】[推荐人数] +【完成首单人数】[完成首单人数] +【未完成首单人数】[未完成首单人数] + +分享我名片给您的好友一起来使用吧!"; + this.ExchangePacketTitle = @"获得奖励:[兑换金额]"; + this.NewUserFirstOrderCompletedTip = @"一一一一首 单 奖 励一一一一 +【昵称】[昵称] +【奖励额】[首单奖励金额] [积分名称] +【可提现】[剩余积分] [积分名称] + +您可以发送【兑换】,领取现金哦!"; + this.InviteEachOtherTip = @"一一一一激 活 失 败一一一一 +自己下级,禁止绑定为自己上级哦~"; + + this.Superior_DividendType = RechargeType.增加余额; + this.SuperiorDividendCommercialPayTip = @"一一一一分 红 奖 励一一一一 + +下级有效订单达到:[下级有效订单数]笔 +您将获得分红奖励:[分红奖励金额][积分名称] + +[领取地址] + +点击链接,领取红包到您钱包!"; + this.SuperiorDividendCommercialEftTip = @"一一一一分 红 奖 励一一一一 + +下级有效订单达到:[下级有效订单数]笔 +获得分红奖励:[分红奖励金额][积分名称] + +已直接转入您的账户!"; + this.SuperiorDividendPayTip = @"一一一一分 红 奖 励一一一一 + +【下级有效订单达到】[下级有效订单数]笔 +【本次获得分红奖励】[分红奖励金额][积分名称] +【当前可提现】[剩余积分][积分名称] + +您可以发送【兑换】,领取现金哦!"; + + #endregion + + } + + } +} diff --git a/应用/UserFission/Control_/CategoryControl.cs b/应用/UserFission/Control_/CategoryControl.cs new file mode 100644 index 0000000..e1fa2ad --- /dev/null +++ b/应用/UserFission/Control_/CategoryControl.cs @@ -0,0 +1,58 @@ +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static UserFission.Control_.Enums; + +namespace UserFission.Control_ +{ + class CategoryControl : PropertyGridEditStyle + { + public CategoryControl() + { + var listBox = new CheckedListBoxControl(); + foreach (GenderType item in Enum.GetValues(typeof(GenderType))) + { + listBox.Items.Add(new CheckedListBoxItem(null, item.ToString())); + } + Control = listBox; + } + + /// <summary> + /// 将选着的数据进行展示 + /// </summary> + /// <returns></returns> + public override string GetValue() + { + var listBox = Control as CheckedListBoxControl; + string[] strs = new string[listBox.CheckedItems.Count]; + int i = 0; + foreach (var item in listBox.CheckedItems) + { + strs[i] = item.ToString(); + i++; + } + return string.Join(",", strs); + } + + /// <summary> + /// 将内容在控件里面勾选 + /// </summary> + /// <param name="value"></param> + public override void SetValue(object value) + { + var listBox = Control as CheckedListBoxControl; + var strs = value == null ? new string[] { } : value.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + foreach (var item in listBox.Items) + { + listBox.SetItemChecked(i, !string.IsNullOrEmpty(strs.FirstOrDefault(f => f == item.ToString()))); + i++; + } + } + } +} diff --git a/应用/UserFission/Control_/Enums.cs b/应用/UserFission/Control_/Enums.cs new file mode 100644 index 0000000..98dfcb0 --- /dev/null +++ b/应用/UserFission/Control_/Enums.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Control_ +{ + public class Enums + { + + /// <summary> + /// 性别枚举 + /// </summary> + public enum GenderType + { + 男 = 1, + 女 = 2, + 未知 = 3 + } + + } +} diff --git a/应用/UserFission/EditGroupForm.Designer.cs b/应用/UserFission/EditGroupForm.Designer.cs new file mode 100644 index 0000000..4ca9021 --- /dev/null +++ b/应用/UserFission/EditGroupForm.Designer.cs @@ -0,0 +1,152 @@ +namespace UserFission +{ + partial class EditGroupForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.textEdit2); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Location = new System.Drawing.Point(49, 45); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(483, 248); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // simpleButton2 + // + this.simpleButton2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton2.Location = new System.Drawing.Point(305, 197); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(85, 32); + this.simpleButton2.TabIndex = 4; + this.simpleButton2.Text = " 取 消 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton1.Location = new System.Drawing.Point(137, 197); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(85, 32); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = " 确 定 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(167, 66); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(237, 20); + this.textEdit2.TabIndex = 2; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(167, 102); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(237, 20); + this.textEdit1.TabIndex = 2; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(115, 105); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(36, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "备注:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(115, 69); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(36, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "群ID:"; + // + // labelControl3 + // + this.labelControl3.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl3.Appearance.Options.UseForeColor = true; + this.labelControl3.Location = new System.Drawing.Point(72, 137); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(382, 42); + this.labelControl3.TabIndex = 6; + this.labelControl3.Text = "注:\r\n群ID:获取方式,在群中发送消息,日志中获取(格式:xxxxx@chatroom)\r\n备注:用于区分群,自定义即可"; + // + // EditGroupForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.simpleButton2; + this.ClientSize = new System.Drawing.Size(581, 339); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "EditGroupForm"; + this.Text = "编辑群信息"; + this.Load += new System.EventHandler(this.EditGroupForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl3; + } +} \ No newline at end of file diff --git a/应用/UserFission/EditGroupForm.cs b/应用/UserFission/EditGroupForm.cs new file mode 100644 index 0000000..c954a10 --- /dev/null +++ b/应用/UserFission/EditGroupForm.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace UserFission +{ + public partial class EditGroupForm : BaseForm + { + public EditGroupForm(string weixinhao, string groupname = "", string groupnick = "") + { + InitializeComponent(); + this.WeiXinHao = weixinhao; + this.GroupName = groupname; + this.GroupNick = groupnick; + } + + private void EditGroupForm_Load(object sender, EventArgs e) + { + textEdit1.Text = GroupNick; + textEdit2.Text = GroupName; + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.No; + } + + public string GroupNick = string.Empty; + public string GroupName = string.Empty; + string WeiXinHao = string.Empty; + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("群昵称不能为空!"); + if (string.IsNullOrWhiteSpace(textEdit2.Text)) throw new Exception("群账号不能为空!"); + + GroupNick = textEdit1.Text; + GroupName = textEdit2.Text; + + var groups = Class1.Config.InviteGroupInfo2[WeiXinHao]; + var mess = string.Empty; + if (groups.groupInfos.ContainsKey(GroupName)) + { + groups.groupInfos[GroupName] = GroupNick; + mess = "修改成功"; + } + else + { + groups.groupInfos.Add(GroupName, GroupNick); + mess = "增加成功"; + } + ShowSuccessAutoClose(mess); + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} \ No newline at end of file diff --git a/应用/UserFission/EditGroupForm.resx b/应用/UserFission/EditGroupForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/UserFission/EditGroupForm.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/UserFission/Entitys/Controls.cs b/应用/UserFission/Entitys/Controls.cs new file mode 100644 index 0000000..4417908 --- /dev/null +++ b/应用/UserFission/Entitys/Controls.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + /// <summary> + /// 海报数据信息 + /// </summary> + public class Controls + { + /// <summary> + /// 公共属性控件名称 + /// </summary> + public string C_Name { get; set; } + /// <summary> + /// 公共属性控件坐标 + /// </summary> + public Point C_Point { get; set; } + /// <summary> + /// 公共属性控件大小 + /// </summary> + public Size C_Size { get; set; } + /// <summary> + /// 公共隐藏属性(这里只有label用到) + /// </summary> + public bool C_Visible { get; set; } + /// <summary> + /// Tag属性 + /// </summary> + public string C_Tag { get; set; } + /// <summary> + /// 文本属性字体样式 + /// </summary> + public string T_FontJson { get; set; } + /// <summary> + /// 文本属性控件前景色 + /// </summary> + public Color T_ForeColor { get; set; } + /// <summary> + /// 字体的宽度 + /// </summary> + public int T_Width { get; set; } + /// <summary> + /// 字体的高度 + /// </summary> + public int T_Height { get; set; } + } +} diff --git a/应用/UserFission/Entitys/QrCode.cs b/应用/UserFission/Entitys/QrCode.cs new file mode 100644 index 0000000..9109b2c --- /dev/null +++ b/应用/UserFission/Entitys/QrCode.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + public class QrCode + { + public string rname {get;set;} + public string rnick {get;set;} + public string url {get;set;} + + } +} diff --git a/应用/UserFission/Entitys/Subordinate.cs b/应用/UserFission/Entitys/Subordinate.cs new file mode 100644 index 0000000..5d1cc73 --- /dev/null +++ b/应用/UserFission/Entitys/Subordinate.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + public class Subordinate + { + public string Usernick { get; set; } + } +} diff --git a/应用/UserFission/Entitys/automatic_approval_setting_temp.cs b/应用/UserFission/Entitys/automatic_approval_setting_temp.cs new file mode 100644 index 0000000..1a3efa0 --- /dev/null +++ b/应用/UserFission/Entitys/automatic_approval_setting_temp.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + public class automatic_approval_setting_temp + { + /// <summary> + /// 机器人id + /// </summary> + public long rid { get; set; } + /// <summary> + /// 微信账号(机器人) + /// </summary> + public string name { get; set; } + /// <summary> + /// 微信昵称(机器人) + /// </summary> + public string nick { get; set; } + /// <summary> + /// 是否禁用自动通过好友审核 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/UserFission/Entitys/fl_plugin_userfission_applyfriend_info.cs b/应用/UserFission/Entitys/fl_plugin_userfission_applyfriend_info.cs new file mode 100644 index 0000000..7f288db --- /dev/null +++ b/应用/UserFission/Entitys/fl_plugin_userfission_applyfriend_info.cs @@ -0,0 +1,58 @@ +using Api.Framework.Tools; +using System; + +namespace UserFission.Entitys +{ + public class fl_plugin_userfission_applyfriend_info : base_model + { + public fl_plugin_userfission_applyfriend_info() + { + state = "待审核"; + } + /// <summary> + /// 机器人的name。 robotinfo中的name + /// </summary> + public string robot_name { get; set; } + /// <summary> + /// 机器人名称 + /// </summary> + public string user_nick { get; set; } + /// <summary> + /// 申请时间 + /// </summary> + public DateTime crt_time { get; set; } + /// <summary> + /// 申请通过时间 + /// </summary> + public DateTime allow_time { get; set; } + /// <summary> + /// 申请时对方发送的验证信息 + /// </summary> + public string message { get; set; } + /// <summary> + /// 申请人昵称 + /// </summary> + public string new_friend_nick { get; set; } + /// <summary> + /// 申请人微信号 + /// </summary> + public string new_friend_wxid { get; set; } + /// <summary> + /// 推荐人昵称 + /// </summary> + public string old_friend_nick { get; set; } + /// <summary> + /// 推荐人微信号 + /// </summary> + public string old_friend_wxid { get; set; } + /// <summary> + /// token + /// </summary> + public string token { get; set; } + /// <summary> + /// 状态 + /// </summary> + public string state { get; set; } + + } +} diff --git a/应用/UserFission/Entitys/fl_plugin_userfission_automatic_approval_setting.cs b/应用/UserFission/Entitys/fl_plugin_userfission_automatic_approval_setting.cs new file mode 100644 index 0000000..31e1f48 --- /dev/null +++ b/应用/UserFission/Entitys/fl_plugin_userfission_automatic_approval_setting.cs @@ -0,0 +1,21 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + public class fl_plugin_userfission_automatic_approval_setting : base_model + { + /// <summary> + /// 机器人id + /// </summary> + public long rid { get; set; } + /// <summary> + /// 是否禁用自动通过好友审核 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/UserFission/Entitys/fl_plugin_userfission_extra.cs b/应用/UserFission/Entitys/fl_plugin_userfission_extra.cs new file mode 100644 index 0000000..23856fc --- /dev/null +++ b/应用/UserFission/Entitys/fl_plugin_userfission_extra.cs @@ -0,0 +1,36 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + /// <summary> + /// 额外奖励 - 用户多少小时内下单,收货后将奖励用户一定的金额 + /// </summary> + public class fl_plugin_userfission_extra : base_model + { + /// <summary> + /// 用户id + /// </summary> + public long userid { get; set; } + + ///// <summary> + ///// 订单id + ///// </summary> + //public long orderid { get; set; } + + ///// <summary> + ///// 平台类型 + ///// </summary> + //public CpsType cpstype { get; set; } + + /// <summary> + /// 奖励的金额 + /// </summary> + public double point { get; set; } + } +} diff --git a/应用/UserFission/Entitys/fl_plugin_userfission_fan_notify.cs b/应用/UserFission/Entitys/fl_plugin_userfission_fan_notify.cs new file mode 100644 index 0000000..7a71507 --- /dev/null +++ b/应用/UserFission/Entitys/fl_plugin_userfission_fan_notify.cs @@ -0,0 +1,35 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + /// <summary> + /// 查返通知记录 + /// </summary> + public class fl_plugin_userfission_fan_notify : base_model + { + /// <summary> + /// 用户id + /// </summary> + public long mid { get; set; } + + /// <summary> + /// 无券 + /// </summary> + public long uncoupon { get; set; } + + /// <summary> + /// 有券 + /// </summary> + public long coupon { get; set; } + + /// <summary> + /// 午返 + /// </summary> + public long unfan { get; set; } + } +} diff --git a/应用/UserFission/Entitys/fl_plugin_userfission_invite_record.cs b/应用/UserFission/Entitys/fl_plugin_userfission_invite_record.cs new file mode 100644 index 0000000..235c4b1 --- /dev/null +++ b/应用/UserFission/Entitys/fl_plugin_userfission_invite_record.cs @@ -0,0 +1,16 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + public class fl_plugin_userfission_invite_record : base_model + { + public string groupid { get; set; } + + public string username { get; set; } + } +} diff --git a/应用/UserFission/Entitys/fl_plugin_userfission_leadgroup_info.cs b/应用/UserFission/Entitys/fl_plugin_userfission_leadgroup_info.cs new file mode 100644 index 0000000..3d8f274 --- /dev/null +++ b/应用/UserFission/Entitys/fl_plugin_userfission_leadgroup_info.cs @@ -0,0 +1,30 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + /// <summary> + /// 引导群类.(用于裂变增加的好友,引导至以下设置的群id中) + /// </summary> + public class fl_plugin_userfission_leadgroup_info : base_model + { + /// <summary> + /// 机器人id + /// </summary> + public string rid { get; set; } + + /// <summary> + /// 引导群ID + /// </summary> + public string group_id { get; set; } + + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/UserFission/Entitys/fl_plugin_userfission_superior_reward.cs b/应用/UserFission/Entitys/fl_plugin_userfission_superior_reward.cs new file mode 100644 index 0000000..06d54e5 --- /dev/null +++ b/应用/UserFission/Entitys/fl_plugin_userfission_superior_reward.cs @@ -0,0 +1,27 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + public class fl_plugin_userfission_superior_reward : base_model + { + + /// <summary> + /// 所有下级购物订单总数 + /// </summary> + [Category("属性编辑"), DisplayName("01.订单数量条件"), Description("单个下级购物有效订单数(包括:京东、淘宝、拼多多)")] + public double subordinate_order_totle { get; set; } + + /// <summary> + /// 上级奖励金额 + /// </summary> + [Category("属性编辑"), DisplayName("02.奖励上级金额"), Description("满足以上条件,奖励上级的金额")] + public double superior_point_reward { get;set;} + + } +} diff --git a/应用/UserFission/Entitys/fl_plugin_userfission_user_invitation_code.cs b/应用/UserFission/Entitys/fl_plugin_userfission_user_invitation_code.cs new file mode 100644 index 0000000..2e8f327 --- /dev/null +++ b/应用/UserFission/Entitys/fl_plugin_userfission_user_invitation_code.cs @@ -0,0 +1,22 @@ +using Api.Framework.Tools; +using System; + +namespace UserFission.Entitys +{ + public class fl_plugin_userfission_user_invitation_code : base_model + { + /// <summary> + /// 用户fl_member_info id + /// </summary> + public long member_info_id { get; set; } + /// <summary> + /// 邀请码创建时间 + /// </summary> + public DateTime crt_time { get; set; } + /// <summary> + /// 用户的邀请码 + /// </summary> + public string code { get; set; } + + } +} diff --git a/应用/UserFission/Entitys/leadgroup_temp.cs b/应用/UserFission/Entitys/leadgroup_temp.cs new file mode 100644 index 0000000..a4d749a --- /dev/null +++ b/应用/UserFission/Entitys/leadgroup_temp.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + public class leadgroup_temp + { + /// <summary> + /// id(机器人) + /// </summary> + public int id { get; set; } + /// <summary> + /// 微信账号(机器人) + /// </summary> + public string name { get; set; } + /// <summary> + /// 微信昵称(机器人) + /// </summary> + public string nick { get; set; } + /// <summary> + /// 引导群ID + /// </summary> + public string group_id { get; set; } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + + } + +} diff --git a/应用/UserFission/Entitys/user_invitation_code_temp.cs b/应用/UserFission/Entitys/user_invitation_code_temp.cs new file mode 100644 index 0000000..8d353c8 --- /dev/null +++ b/应用/UserFission/Entitys/user_invitation_code_temp.cs @@ -0,0 +1,33 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + public class user_invitation_code_temp + { + /// <summary> + /// id + /// </summary> + public long ID { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + /// <summary> + /// 创建时间 + /// </summary> + public DateTime crt_time { get; set; } + /// <summary> + /// code + /// </summary> + public string code { get; set; } + } +} diff --git a/应用/UserFission/Entitys/wx_info.cs b/应用/UserFission/Entitys/wx_info.cs new file mode 100644 index 0000000..bf1246d --- /dev/null +++ b/应用/UserFission/Entitys/wx_info.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace UserFission.Entitys +{ + /// <summary> + /// 进群设置的基础类 + /// </summary> + public class wx_info + { + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + /// <summary> + /// 群id + /// </summary> + public List<string> groupIds { get; set; } + + public wx_info() + { + onoff = false; + groupIds = new List<string>(); + } + } +} diff --git a/应用/UserFission/Entitys/wxinfo.cs b/应用/UserFission/Entitys/wxinfo.cs new file mode 100644 index 0000000..3653da3 --- /dev/null +++ b/应用/UserFission/Entitys/wxinfo.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UserFission.Entitys +{ + /// <summary> + /// 进群设置的基础类 + /// </summary> + public class wxinfo + { + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + /// <summary> + /// 键为群id,值为群名 + /// </summary> + public Dictionary<string, string> groupInfos { get; set; } + + public wxinfo() + { + onoff = false; + groupInfos = new Dictionary<string, string>(); + } + } +} diff --git a/应用/UserFission/Fakes/UI.Framework.fakes b/应用/UserFission/Fakes/UI.Framework.fakes new file mode 100644 index 0000000..b2d1fbb Binary files /dev/null and b/应用/UserFission/Fakes/UI.Framework.fakes differ diff --git a/应用/UserFission/ImageDesignForm.Designer.cs b/应用/UserFission/ImageDesignForm.Designer.cs new file mode 100644 index 0000000..7771e9c --- /dev/null +++ b/应用/UserFission/ImageDesignForm.Designer.cs @@ -0,0 +1,614 @@ +namespace UserFission +{ + partial class ImageDesignForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImageDesignForm)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.cBox_AutoPicture = new System.Windows.Forms.CheckBox(); + this.label12 = new System.Windows.Forms.Label(); + this.btn_BackIamge = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.label9 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.button2 = new System.Windows.Forms.Button(); + this.tBox_Size = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.tBox_Logo = new System.Windows.Forms.TextBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.colorPickEdit2 = new DevExpress.XtraEditors.ColorPickEdit(); + this.colorPickEdit1 = new DevExpress.XtraEditors.ColorPickEdit(); + this.label11 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.linkLabel3 = new System.Windows.Forms.LinkLabel(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.label4 = new System.Windows.Forms.Label(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.btn_txt2 = new System.Windows.Forms.Button(); + this.btn_txt1 = new System.Windows.Forms.Button(); + this.tBox_txt2 = new System.Windows.Forms.TextBox(); + this.tBox_txt1 = new System.Windows.Forms.TextBox(); + this.cBox_txt2 = new System.Windows.Forms.CheckBox(); + this.cBox_txt1 = new System.Windows.Forms.CheckBox(); + this.groupBox_ImageType = new System.Windows.Forms.GroupBox(); + this.button4 = new System.Windows.Forms.Button(); + this.label15 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.label13 = new System.Windows.Forms.Label(); + this.cBox_AutoQrCode = new System.Windows.Forms.CheckBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.panel_Plot = new UserFission.重绘.MyPanel(); + this.lbltxt2 = new System.Windows.Forms.Label(); + this.lbltxt1 = new System.Windows.Forms.Label(); + this.pBox_QRcode = new UserFission.重绘.MyPictureBox(); + this.groupBox1.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.colorPickEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.colorPickEdit1.Properties)).BeginInit(); + this.groupBox_ImageType.SuspendLayout(); + this.panel1.SuspendLayout(); + this.panel_Plot.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pBox_QRcode)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.cBox_AutoPicture); + this.groupBox1.Controls.Add(this.label12); + this.groupBox1.Controls.Add(this.btn_BackIamge); + this.groupBox1.Controls.Add(this.button1); + this.groupBox1.Controls.Add(this.button3); + this.groupBox1.Controls.Add(this.groupBox3); + this.groupBox1.Controls.Add(this.groupBox2); + this.groupBox1.Controls.Add(this.groupBox_ImageType); + this.groupBox1.Location = new System.Drawing.Point(485, 13); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(4); + this.groupBox1.Size = new System.Drawing.Size(641, 603); + this.groupBox1.TabIndex = 15; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 二维码生成 "; + // + // cBox_AutoPicture + // + this.cBox_AutoPicture.AutoSize = true; + this.cBox_AutoPicture.Location = new System.Drawing.Point(386, 202); + this.cBox_AutoPicture.Margin = new System.Windows.Forms.Padding(4); + this.cBox_AutoPicture.Name = "cBox_AutoPicture"; + this.cBox_AutoPicture.Size = new System.Drawing.Size(122, 18); + this.cBox_AutoPicture.TabIndex = 19; + this.cBox_AutoPicture.Text = "自动获取微信头像"; + this.cBox_AutoPicture.UseVisualStyleBackColor = true; + this.cBox_AutoPicture.CheckedChanged += new System.EventHandler(this.cBox_AutoPicture_CheckedChanged); + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(36, 29); + this.label12.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(67, 14); + this.label12.TabIndex = 21; + this.label12.Text = "修改背景:"; + // + // btn_BackIamge + // + this.btn_BackIamge.Location = new System.Drawing.Point(109, 21); + this.btn_BackIamge.Margin = new System.Windows.Forms.Padding(4); + this.btn_BackIamge.Name = "btn_BackIamge"; + this.btn_BackIamge.Size = new System.Drawing.Size(445, 29); + this.btn_BackIamge.TabIndex = 20; + this.btn_BackIamge.Text = "上传背景"; + this.btn_BackIamge.UseVisualStyleBackColor = true; + this.btn_BackIamge.Click += new System.EventHandler(this.btn_BackIamge_Click); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(328, 543); + this.button1.Margin = new System.Windows.Forms.Padding(4); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(203, 50); + this.button1.TabIndex = 19; + this.button1.Text = "预览效果"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button3 + // + this.button3.Location = new System.Drawing.Point(73, 543); + this.button3.Margin = new System.Windows.Forms.Padding(4); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(203, 50); + this.button3.TabIndex = 18; + this.button3.Text = "保存模板属性"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.label9); + this.groupBox3.Controls.Add(this.label8); + this.groupBox3.Controls.Add(this.button2); + this.groupBox3.Controls.Add(this.tBox_Size); + this.groupBox3.Controls.Add(this.label3); + this.groupBox3.Controls.Add(this.tBox_Logo); + this.groupBox3.Location = new System.Drawing.Point(19, 206); + this.groupBox3.Margin = new System.Windows.Forms.Padding(4); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Padding = new System.Windows.Forms.Padding(4); + this.groupBox3.Size = new System.Drawing.Size(605, 111); + this.groupBox3.TabIndex = 17; + this.groupBox3.TabStop = false; + this.groupBox3.Text = " 二维码属性 "; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.ForeColor = System.Drawing.Color.DimGray; + this.label9.Location = new System.Drawing.Point(77, 78); + this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(343, 14); + this.label9.TabIndex = 22; + this.label9.Text = "注:勾选自动获取微信头像,则会自动获取微信机器人的头像。"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(370, 37); + this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(70, 14); + this.label8.TabIndex = 21; + this.label8.Text = "Logo尺寸:"; + // + // button2 + // + this.button2.Location = new System.Drawing.Point(286, 31); + this.button2.Margin = new System.Windows.Forms.Padding(4); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(76, 25); + this.button2.TabIndex = 17; + this.button2.Text = "增加.."; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // tBox_Size + // + this.tBox_Size.Location = new System.Drawing.Point(442, 33); + this.tBox_Size.Margin = new System.Windows.Forms.Padding(4); + this.tBox_Size.Name = "tBox_Size"; + this.tBox_Size.Size = new System.Drawing.Size(130, 22); + this.tBox_Size.TabIndex = 20; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(77, 37); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(70, 14); + this.label3.TabIndex = 18; + this.label3.Text = "上传Logo:"; + // + // tBox_Logo + // + this.tBox_Logo.Location = new System.Drawing.Point(150, 33); + this.tBox_Logo.Margin = new System.Windows.Forms.Padding(4); + this.tBox_Logo.Name = "tBox_Logo"; + this.tBox_Logo.Size = new System.Drawing.Size(128, 22); + this.tBox_Logo.TabIndex = 16; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.colorPickEdit2); + this.groupBox2.Controls.Add(this.colorPickEdit1); + this.groupBox2.Controls.Add(this.label11); + this.groupBox2.Controls.Add(this.label10); + this.groupBox2.Controls.Add(this.label6); + this.groupBox2.Controls.Add(this.linkLabel3); + this.groupBox2.Controls.Add(this.linkLabel2); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.linkLabel1); + this.groupBox2.Controls.Add(this.btn_txt2); + this.groupBox2.Controls.Add(this.btn_txt1); + this.groupBox2.Controls.Add(this.tBox_txt2); + this.groupBox2.Controls.Add(this.tBox_txt1); + this.groupBox2.Controls.Add(this.cBox_txt2); + this.groupBox2.Controls.Add(this.cBox_txt1); + this.groupBox2.Location = new System.Drawing.Point(19, 334); + this.groupBox2.Margin = new System.Windows.Forms.Padding(4); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Padding = new System.Windows.Forms.Padding(4); + this.groupBox2.Size = new System.Drawing.Size(605, 201); + this.groupBox2.TabIndex = 16; + this.groupBox2.TabStop = false; + this.groupBox2.Text = " 扩展文本 "; + // + // colorPickEdit2 + // + this.colorPickEdit2.EditValue = System.Drawing.Color.Empty; + this.colorPickEdit2.Location = new System.Drawing.Point(311, 127); + this.colorPickEdit2.Name = "colorPickEdit2"; + this.colorPickEdit2.Properties.AutomaticColor = System.Drawing.Color.Black; + this.colorPickEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.colorPickEdit2.Size = new System.Drawing.Size(261, 20); + this.colorPickEdit2.TabIndex = 19; + this.colorPickEdit2.EditValueChanged += new System.EventHandler(this.colorPickEdit1_EditValueChanged); + // + // colorPickEdit1 + // + this.colorPickEdit1.EditValue = System.Drawing.Color.Empty; + this.colorPickEdit1.Location = new System.Drawing.Point(311, 57); + this.colorPickEdit1.Name = "colorPickEdit1"; + this.colorPickEdit1.Properties.AutomaticColor = System.Drawing.Color.Black; + this.colorPickEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.colorPickEdit1.Size = new System.Drawing.Size(261, 20); + this.colorPickEdit1.TabIndex = 18; + this.colorPickEdit1.EditValueChanged += new System.EventHandler(this.colorPickEdit1_EditValueChanged); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(261, 130); + this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(43, 14); + this.label11.TabIndex = 17; + this.label11.Text = "颜色:"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(261, 60); + this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(43, 14); + this.label10.TabIndex = 16; + this.label10.Text = "颜色:"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.ForeColor = System.Drawing.Color.DimGray; + this.label6.Location = new System.Drawing.Point(440, 169); + this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(127, 14); + this.label6.TabIndex = 13; + this.label6.Text = "(变量支持点击复制)"; + // + // linkLabel3 + // + this.linkLabel3.AutoSize = true; + this.linkLabel3.Location = new System.Drawing.Point(361, 169); + this.linkLabel3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.linkLabel3.Name = "linkLabel3"; + this.linkLabel3.Size = new System.Drawing.Size(53, 14); + this.linkLabel3.TabIndex = 12; + this.linkLabel3.TabStop = true; + this.linkLabel3.Text = "[邀请码]"; + this.linkLabel3.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(266, 169); + this.linkLabel2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(65, 14); + this.linkLabel2.TabIndex = 11; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "[微信名称]"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(77, 169); + this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 14); + this.label4.TabIndex = 10; + this.label4.Text = "支持变量:"; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(172, 169); + this.linkLabel1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(65, 14); + this.linkLabel1.TabIndex = 9; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "[微信账号]"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // btn_txt2 + // + this.btn_txt2.Location = new System.Drawing.Point(165, 123); + this.btn_txt2.Margin = new System.Windows.Forms.Padding(4); + this.btn_txt2.Name = "btn_txt2"; + this.btn_txt2.Size = new System.Drawing.Size(81, 29); + this.btn_txt2.TabIndex = 8; + this.btn_txt2.Text = "字体属性"; + this.btn_txt2.UseVisualStyleBackColor = true; + this.btn_txt2.Click += new System.EventHandler(this.btn_txt_Click); + // + // btn_txt1 + // + this.btn_txt1.Location = new System.Drawing.Point(165, 53); + this.btn_txt1.Margin = new System.Windows.Forms.Padding(4); + this.btn_txt1.Name = "btn_txt1"; + this.btn_txt1.Size = new System.Drawing.Size(81, 29); + this.btn_txt1.TabIndex = 7; + this.btn_txt1.Text = "字体属性"; + this.btn_txt1.UseVisualStyleBackColor = true; + this.btn_txt1.Click += new System.EventHandler(this.btn_txt_Click); + // + // tBox_txt2 + // + this.tBox_txt2.Location = new System.Drawing.Point(165, 97); + this.tBox_txt2.Margin = new System.Windows.Forms.Padding(4); + this.tBox_txt2.Name = "tBox_txt2"; + this.tBox_txt2.Size = new System.Drawing.Size(407, 22); + this.tBox_txt2.TabIndex = 3; + this.tBox_txt2.TextChanged += new System.EventHandler(this.tBox_txt_TextChanged); + // + // tBox_txt1 + // + this.tBox_txt1.Location = new System.Drawing.Point(165, 26); + this.tBox_txt1.Margin = new System.Windows.Forms.Padding(4); + this.tBox_txt1.Name = "tBox_txt1"; + this.tBox_txt1.Size = new System.Drawing.Size(407, 22); + this.tBox_txt1.TabIndex = 2; + this.tBox_txt1.TextChanged += new System.EventHandler(this.tBox_txt_TextChanged); + // + // cBox_txt2 + // + this.cBox_txt2.AutoSize = true; + this.cBox_txt2.Location = new System.Drawing.Point(79, 99); + this.cBox_txt2.Margin = new System.Windows.Forms.Padding(4); + this.cBox_txt2.Name = "cBox_txt2"; + this.cBox_txt2.Size = new System.Drawing.Size(93, 18); + this.cBox_txt2.TabIndex = 1; + this.cBox_txt2.Text = "扩展文本2:"; + this.cBox_txt2.UseVisualStyleBackColor = true; + this.cBox_txt2.CheckedChanged += new System.EventHandler(this.cBox_txt_CheckedChangedcBox_txt_CheckedChanged); + // + // cBox_txt1 + // + this.cBox_txt1.AutoSize = true; + this.cBox_txt1.ForeColor = System.Drawing.SystemColors.ControlText; + this.cBox_txt1.Location = new System.Drawing.Point(79, 28); + this.cBox_txt1.Margin = new System.Windows.Forms.Padding(4); + this.cBox_txt1.Name = "cBox_txt1"; + this.cBox_txt1.Size = new System.Drawing.Size(93, 18); + this.cBox_txt1.TabIndex = 0; + this.cBox_txt1.Text = "扩展文本1:"; + this.cBox_txt1.UseVisualStyleBackColor = true; + this.cBox_txt1.CheckedChanged += new System.EventHandler(this.cBox_txt_CheckedChangedcBox_txt_CheckedChanged); + // + // groupBox_ImageType + // + this.groupBox_ImageType.Controls.Add(this.button4); + this.groupBox_ImageType.Controls.Add(this.label15); + this.groupBox_ImageType.Controls.Add(this.label14); + this.groupBox_ImageType.Controls.Add(this.label13); + this.groupBox_ImageType.Controls.Add(this.cBox_AutoQrCode); + this.groupBox_ImageType.Location = new System.Drawing.Point(19, 66); + this.groupBox_ImageType.Margin = new System.Windows.Forms.Padding(4); + this.groupBox_ImageType.Name = "groupBox_ImageType"; + this.groupBox_ImageType.Padding = new System.Windows.Forms.Padding(4); + this.groupBox_ImageType.Size = new System.Drawing.Size(605, 132); + this.groupBox_ImageType.TabIndex = 11; + this.groupBox_ImageType.TabStop = false; + this.groupBox_ImageType.Text = " 二维码内容 "; + // + // button4 + // + this.button4.Location = new System.Drawing.Point(176, 79); + this.button4.Name = "button4"; + this.button4.Size = new System.Drawing.Size(288, 23); + this.button4.TabIndex = 26; + this.button4.Text = "设置机器人二维码(支持所有微信)"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(87, 83); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(79, 14); + this.label15.TabIndex = 25; + this.label15.Text = "第二种方式:"; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(87, 41); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(79, 14); + this.label14.TabIndex = 24; + this.label14.Text = "第一种方式:"; + // + // label13 + // + this.label13.AutoSize = true; + this.label13.ForeColor = System.Drawing.Color.Gray; + this.label13.Location = new System.Drawing.Point(317, 40); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(200, 14); + this.label13.TabIndex = 23; + this.label13.Text = "(pc版微信不支持获取自动二维码)"; + // + // cBox_AutoQrCode + // + this.cBox_AutoQrCode.AutoSize = true; + this.cBox_AutoQrCode.Location = new System.Drawing.Point(176, 39); + this.cBox_AutoQrCode.Name = "cBox_AutoQrCode"; + this.cBox_AutoQrCode.Size = new System.Drawing.Size(134, 18); + this.cBox_AutoQrCode.TabIndex = 22; + this.cBox_AutoQrCode.Text = "自动获取微信二维码"; + this.cBox_AutoQrCode.UseVisualStyleBackColor = true; + this.cBox_AutoQrCode.CheckedChanged += new System.EventHandler(this.cBox_AutoQrCode_CheckedChanged); + // + // panel1 + // + this.panel1.Controls.Add(this.panel_Plot); + this.panel1.Location = new System.Drawing.Point(13, 13); + this.panel1.Margin = new System.Windows.Forms.Padding(4); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(463, 603); + this.panel1.TabIndex = 16; + // + // panel_Plot + // + this.panel_Plot.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("panel_Plot.BackgroundImage"))); + this.panel_Plot.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.panel_Plot.Controls.Add(this.lbltxt2); + this.panel_Plot.Controls.Add(this.lbltxt1); + this.panel_Plot.Controls.Add(this.pBox_QRcode); + this.panel_Plot.Location = new System.Drawing.Point(25, 59); + this.panel_Plot.Name = "panel_Plot"; + this.panel_Plot.Size = new System.Drawing.Size(364, 474); + this.panel_Plot.TabIndex = 0; + // + // lbltxt2 + // + this.lbltxt2.AutoSize = true; + this.lbltxt2.BackColor = System.Drawing.Color.Transparent; + this.lbltxt2.Font = new System.Drawing.Font("宋体", 14F); + this.lbltxt2.Location = new System.Drawing.Point(22, 417); + this.lbltxt2.Name = "lbltxt2"; + this.lbltxt2.Size = new System.Drawing.Size(39, 19); + this.lbltxt2.TabIndex = 4; + this.lbltxt2.Text = "222"; + // + // lbltxt1 + // + this.lbltxt1.AutoSize = true; + this.lbltxt1.BackColor = System.Drawing.Color.Transparent; + this.lbltxt1.Font = new System.Drawing.Font("宋体", 14F); + this.lbltxt1.Location = new System.Drawing.Point(22, 388); + this.lbltxt1.Name = "lbltxt1"; + this.lbltxt1.Size = new System.Drawing.Size(39, 19); + this.lbltxt1.TabIndex = 3; + this.lbltxt1.Text = "111"; + // + // pBox_QRcode + // + this.pBox_QRcode.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.pBox_QRcode.Location = new System.Drawing.Point(102, 65); + this.pBox_QRcode.Name = "pBox_QRcode"; + this.pBox_QRcode.Size = new System.Drawing.Size(134, 120); + this.pBox_QRcode.TabIndex = 0; + this.pBox_QRcode.TabStop = false; + // + // ImageDesignForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1139, 634); + this.Controls.Add(this.panel1); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ImageDesignForm"; + this.Text = "ImageDesignForm"; + this.Load += new System.EventHandler(this.ImageDesignForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.colorPickEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.colorPickEdit1.Properties)).EndInit(); + this.groupBox_ImageType.ResumeLayout(false); + this.groupBox_ImageType.PerformLayout(); + this.panel1.ResumeLayout(false); + this.panel_Plot.ResumeLayout(false); + this.panel_Plot.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pBox_QRcode)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.CheckBox cBox_AutoPicture; + private System.Windows.Forms.CheckBox cBox_AutoQrCode; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.Button btn_BackIamge; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.TextBox tBox_Size; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox tBox_Logo; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.LinkLabel linkLabel3; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Button btn_txt2; + private System.Windows.Forms.Button btn_txt1; + private System.Windows.Forms.TextBox tBox_txt2; + private System.Windows.Forms.TextBox tBox_txt1; + private System.Windows.Forms.CheckBox cBox_txt2; + private System.Windows.Forms.CheckBox cBox_txt1; + private 重绘.MyPanel panel_Plot; + private System.Windows.Forms.Label lbltxt2; + private System.Windows.Forms.Label lbltxt1; + private 重绘.MyPictureBox pBox_QRcode; + private System.Windows.Forms.Panel panel1; + private DevExpress.XtraEditors.ColorPickEdit colorPickEdit2; + private DevExpress.XtraEditors.ColorPickEdit colorPickEdit1; + private System.Windows.Forms.GroupBox groupBox_ImageType; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.Button button4; + } +} \ No newline at end of file diff --git a/应用/UserFission/ImageDesignForm.cs b/应用/UserFission/ImageDesignForm.cs new file mode 100644 index 0000000..1b6d41c --- /dev/null +++ b/应用/UserFission/ImageDesignForm.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Newtonsoft.Json; +using UserFission.Properties; +using UserFission.Entitys; +using System.IO; +using UserFission.重绘; +using Api.Framework.Tools; +using UI.Framework.Tools; +using Chat.Framework; +using System.Linq; + +namespace UserFission +{ + public partial class ImageDesignForm : BaseForm + { + public ImageDesignForm() + { + InitializeComponent(); + this.Text = Resources.PluginBillTitle; + } + + private void cBox_txt_CheckedChangedcBox_txt_CheckedChanged(object sender, EventArgs e) + { + try + { + CheckBox check = (CheckBox)sender; + if (check.Name.Contains("1") && check.Checked) + lbltxt1.Visible = true; + else if (check.Name.Contains("1") && !check.Checked) + lbltxt1.Visible = false; + else if (check.Name.Contains("2") && check.Checked) + lbltxt2.Visible = true; + else if (check.Name.Contains("2") && !check.Checked) + lbltxt2.Visible = false; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void tBox_txt_TextChanged(object sender, EventArgs e) + { + try + { + TextBox text = (TextBox)sender; + if (text.Name.Contains("1")) + lbltxt1.Text = text.Text; + else + lbltxt2.Text = text.Text; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + //private void btn_QRCode_Click(object sender, EventArgs e) + //{ + // try + // { + // OpenFileDialog openDialog = new OpenFileDialog(); + // openDialog.Filter = "图片文件|*.jpg;*.png;*.gif|All files(*.*)|*.*"; + // if (openDialog.ShowDialog() == DialogResult.OK) + // { + // if (string.IsNullOrEmpty(openDialog.FileName)) + // throw new Exception("请先打开一张二维码图片!"); + // else + // tBox_QRCode.Text = Util.DecodeQRCode(openDialog.FileName, Util.DecodeQRCodeType.Caoliao); + // } + // } + // catch (Exception ex) + // { + // if (ex.Message == "Invalid number of Finder Pattern detected") + // ShowError("二维码无法解析,请换一个重试"); + // else + // ShowError(ex); + // } + //} + + private void ImageDesignForm_Load(object sender, EventArgs e) + { + try + { + Class1.pick = new PickBox(); + #region 海报加载模板 + if (!string.IsNullOrEmpty(Class1.Config.Controlsdic)) + { + var _controldic = JsonConvert.DeserializeObject<Dictionary<string, Controls>>(Class1.Config.Controlsdic); + foreach (KeyValuePair<string, Controls> item in _controldic) + { + if (item.Key == "pBox_QRcode") + { + pBox_QRcode.Name = item.Value.C_Name; + pBox_QRcode.Location = item.Value.C_Point; + pBox_QRcode.Size = item.Value.C_Size; + pBox_QRcode.BackgroundImage = null; + //tBox_QRCode.Text = item.Value.C_Tag; + } + else if (item.Value.C_Name == "lbltxt1") + { + lbltxt1.Font = JsonConvert.DeserializeObject<Font>(item.Value.T_FontJson); + lbltxt1.Size = item.Value.C_Size; + lbltxt1.ForeColor = item.Value.T_ForeColor; + lbltxt1.Width = item.Value.T_Width; + lbltxt1.Height = item.Value.T_Height; + lbltxt1.Location = item.Value.C_Point; + lbltxt1.Visible = item.Value.C_Visible; + cBox_txt1.Checked = item.Value.C_Visible; + tBox_txt1.Text = item.Value.C_Tag; + colorPickEdit1.Color = item.Value.T_ForeColor; + } + else if (item.Value.C_Name == "lbltxt2") + { + lbltxt2.Font = JsonConvert.DeserializeObject<Font>(item.Value.T_FontJson); + lbltxt2.Size = item.Value.C_Size; + lbltxt2.ForeColor = item.Value.T_ForeColor; + lbltxt2.Width = item.Value.T_Width; + lbltxt2.Height = item.Value.T_Height; + lbltxt2.Location = item.Value.C_Point; + lbltxt2.Visible = item.Value.C_Visible; + cBox_txt2.Checked = item.Value.C_Visible; + tBox_txt2.Text = item.Value.C_Tag; + colorPickEdit2.Color = item.Value.T_ForeColor; + } + else if (item.Key == "panel_Plot") + { + panel_Plot.Name = item.Value.C_Name; + panel_Plot.Location = item.Value.C_Point; + panel_Plot.Size = item.Value.C_Size; + panel_Plot.BackgroundImage = Tools.ReadImageFile(Tools.PosterPathImgUrl); + panel_Plot.BackgroundImageLayout = ImageLayout.Stretch; + panel_Plot.Font = JsonConvert.DeserializeObject<Font>(item.Value.T_FontJson); + } + } + } + cBox_AutoQrCode.Checked = Class1.Config.AutoQrCode; + cBox_AutoPicture.Checked = Class1.Config.AutoPicture; + tBox_Logo.Text = Class1.Config.LogoUrl; + tBox_Size.Text = Class1.Config.LogoSize.ToString(); + + if (panel_Plot.BackgroundImage == null) + panel_Plot.BackgroundImage = Resources.背景; + #endregion + + #region 给控件增加移动,变大变小方法 + foreach (Control item in panel1.Controls) + { + Class1.pick.WireControl(item); + } + foreach (Control item in panel_Plot.Controls) + { + Class1.pick.WireControl(item); + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 上传背景图 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void btn_BackIamge_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog fdlg = new OpenFileDialog(); + fdlg.Title = "选择要上传的图片"; + fdlg.InitialDirectory = @"c:\"; + fdlg.Filter = "jpg,png,bmp,gif|*.jpg;*.png;*.bmp;*.gif;"; + fdlg.FilterIndex = 1; + fdlg.RestoreDirectory = true; + if (fdlg.ShowDialog() == DialogResult.OK) + { + if (Tools.PosterPathImgUrl.Trim() == fdlg.FileName.Trim()) throw new Exception("选择的路径为非法路径~!"); + if (!string.IsNullOrWhiteSpace(Tools.PosterPathImgUrl)) + File.Delete(Tools.PosterPathImgUrl); + File.Copy(fdlg.FileName, Tools.PosterPathImgUrl); + panel_Plot.BackgroundImage = Tools.ReadImageFile(Tools.PosterPathImgUrl); + } + fdlg.Dispose(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 自动获取微信二维码 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void cBox_AutoQrCode_CheckedChanged(object sender, EventArgs e) + { + //try + //{ + // if (cBox_AutoQrCode.Checked) + // groupBox_ImageType.Enabled = false; + // else + // groupBox_ImageType.Enabled = true; + //} + //catch (Exception ex) + //{ + // ShowError(ex); + //} + } + + /// <summary> + /// 自动获取微信头像 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void cBox_AutoPicture_CheckedChanged(object sender, EventArgs e) + { + try + { + if (cBox_AutoPicture.Checked) + { + tBox_Logo.Enabled = false; + button2.Enabled = false; + } + else + { + tBox_Logo.Enabled = true; + button2.Enabled = true; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 上传Logo图片 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void button2_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog openDialog = new OpenFileDialog(); + openDialog.Filter = "图片文件|*.jpg;*.png;*.gif|All files(*.*)|*.*"; + if (openDialog.ShowDialog() == DialogResult.OK) tBox_Logo.Text = openDialog.FileName; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 修改字体属性 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void btn_txt_Click(object sender, EventArgs e) + { + try + { + Button button = (Button)sender; + FontDialog font = new FontDialog(); + if (font.ShowDialog() == DialogResult.OK) + { + if (button.Name.Contains("1")) + lbltxt1.Font = font.Font; + else + lbltxt2.Font = font.Font; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + Clipboard.SetDataObject(((LinkLabel)sender).Text); + } + + private void button3_Click(object sender, EventArgs e) + { + try + { + //if (string.IsNullOrWhiteSpace(tBox_QRCode.Text) && !cBox_AutoQrCode.Checked) + //if (!cBox_AutoQrCode.Checked) + // throw new Exception("二维码内容不能为空!"); + + Dictionary<string, Controls> _controls = new Dictionary<string, Controls>(); + + #region 保存控件的信息 + foreach (Control item in panel_Plot.Controls) + { + var _control = new Controls(); + _control.C_Name = item.Name; + _control.C_Point = item.Location; + _control.C_Size = item.Size; + if (typeof(Label) == item.GetType()) + { + Label label = (Label)item; + if (label.Tag == null && string.IsNullOrWhiteSpace(label.Text)) { continue; } + _control.C_Tag = label.Text; + _control.T_FontJson = JsonConvert.SerializeObject(label.Font); + _control.T_Width = label.Width; + _control.T_Height = label.Height; + _control.T_ForeColor = label.ForeColor; + _control.C_Visible = label.Visible; + _controls.Add(item.Name, _control); + } + else if (typeof(MyPictureBox) == item.GetType()) + { + _control.C_Tag = string.Empty;//tBox_QRCode.Text.Trim(); + _controls.Add(item.Name, _control); + } + } + //保存底图控件信息 + _controls.Add(panel_Plot.Name, new Controls() { C_Name = panel_Plot.Name, C_Point = panel_Plot.Location, C_Size = panel_Plot.Size, T_FontJson = JsonConvert.SerializeObject(panel_Plot.Font) }); + #endregion + + #region 保存窗体上的其他二维码属性 + + try + { + var imagePath = Util.MapFile("QRCodelogo.jpg", "File\\Image"); + if (imagePath.Trim() != tBox_Logo.Text.Trim() && !string.IsNullOrWhiteSpace(tBox_Logo.Text.Trim())) + { + if (tBox_Logo.Text.Contains("http")) + FileTools.DownloadImage(tBox_Logo.Text, imagePath); + else + File.Copy(tBox_Logo.Text, imagePath, true); + tBox_Logo.Text = imagePath; + Class1.Config.LogoUrl = imagePath; + } + } + catch (Exception) + { + throw new Exception("logo图片路径不正确"); + } + + Class1.Config.AutoQrCode = cBox_AutoQrCode.Checked; + Class1.Config.AutoPicture = cBox_AutoPicture.Checked; + Class1.Config.LogoSize = int.Parse(tBox_Size.Text); + #endregion + Class1.Config.Controlsdic = JsonConvert.SerializeObject(_controls); + ShowSuccess("保存成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 预览效果 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void button1_Click(object sender, EventArgs e) + { + try + { + try + { Class1.pick.RemoveSelect(); } + catch (Exception) + { } + QrCode qrCode = null; + if (Class1.Config.QrCodes.Count != 0) + qrCode = Class1.Config.QrCodes.First(); + + pBox_QRcode.BackgroundImage = Tools.CreateQRCode(qrCode != null ? qrCode.url : "未存在二维码,当前为测试内容", tBox_Logo.Text, string.IsNullOrEmpty(tBox_Size.Text) ? 0 : int.Parse(tBox_Size.Text), 6); + //pBox_QRcode.BackgroundImage = Tools.CreateQRCode(tBox_QRCode.Text, tBox_Logo.Text, string.IsNullOrEmpty(tBox_Size.Text) ? 0 : int.Parse(tBox_Size.Text), 6); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void colorPickEdit1_EditValueChanged(object sender, EventArgs e) + { + try + { + var color = (ColorPickEdit)sender; + if (color.Name.Contains("1")) + lbltxt1.ForeColor = color.Color; + else + lbltxt2.ForeColor = color.Color; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button4_Click(object sender, EventArgs e) + { + var form = new QRCodeForm(); + form.ShowDialog(); + } + + } +} \ No newline at end of file diff --git a/应用/UserFission/ImageDesignForm.resx b/应用/UserFission/ImageDesignForm.resx new file mode 100644 index 0000000..447a76b --- /dev/null +++ b/应用/UserFission/ImageDesignForm.resx @@ -0,0 +1,1404 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="panel_Plot.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + /9j/4AAQSkZJRgABAQEAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYa + HSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgo + KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAMgAhYDASIAAhEBAxEB/8QA + GwABAAIDAQEAAAAAAAAAAAAAAAQFAgMGAQf/xAAaAQEAAwEBAQAAAAAAAAAAAAAAAQIDBAUG/9oADAMB + AAIQAxAAAAHcPJ+hEyaw0rbaIC0q4BWwJPegvnzzbrrfwRIAAAAAAAAAJABAAQCQAAAAJBAAAAAC6pbf + THolN0HZ5eXmMC1LOkk+00pur5DqYvu38kmvUY8zYTXDlOw5nn7Yrq9VdOZZX1NOfdXQ2rCX9rNOL27u + xTwvmVpTSrmdTs34+ThdnvlwmN/Qc/ZOd3z2/HS6r7oE/OC+w69VP9H19XDwuzr1Z4XC3tsunn9nYa9u + Xg3Zs9uLn6+qrfj50y+vlyu6wgFNJ0ddTbntHccpfGruLuZanz4cnpAAlZ1i2fXy8NPd5NhH91XzYSI9 + L8d0nNdly98HpY0zs86ii3+FbcXb0k7l75VjI2dXDzvQ0VzW9FaUd7S+3Vy1mm+pb+u0x5KbYV/J6Hbe + e4+h5PiLLieZpL+Px+l2MDGD1efPsanYcR1NJ0PN23cX3X2edqzjaKa87snXXP2WdZaVfVwe6cpVb8Z1 + /Edjz9db09Tr25dszdzcqjsuE7DDrtqLoaPq4ZEyHMq+ejzvcABKdBvtMOlrY/LdHF9CfPeutSxhWFHb + Pndltfc/bxf0CG35IMzJanF7uo4rl9HqLXjNdsZXZfPNsadjAo401x6nmOorfyXxl1fLoeRy1Vv2Eqm5 + fXDu9XJdPalV5D9w6rm0r4/Rx3NT5tKvfXOfs61B86eLfjEoc9bGrj7+bu+g02/ieni7CZDi2pzXacb1 + GHXPixJW/HCl5q257pOTkY9XV0kvlb59baVuvXn5QcHsAAAAAAAAAAAAANW3m752075b9B0xtcrKV5Ol + Tp6DXFOeg+/O/Xj6Tv5Xqq7BnoAAAAEAHvgAAAAAAAAAAAAAAAAAI1zrjXrBfKvr+h4G1OloeT7++fPW + PfV3RxcZE7WNlPJbeq9KGN3UzWvzS4y4DHq+h2db0WXRXrBW9esBXrCkreW9Y9Hj0eAAAAPB681m32Lh + aJiJthuESAAAEggAAAABD+s/JvrPd5YdHEiSx857/egEgAANPGdyMMwAAfJfrXyXHqmvXn+x49I8AAxx + jTG+PJl5WqF2raglWfiNXuyJlr7X+bOjGdljleoJG6WOu3xvhVbvenmORy2Tq6Vnl1Soy8u69ENYzpUD + qNF8+eWVblvD+s/JvrPZ5odHGAAAAAAAAAA+TfWfk+PXM8PP9cEAMcoxhZ69/NfPLV7nZ5ljFgg07kzy + 9nvqu3muPdW2ZASI+U16Om06dMpVtz8k9sqPZE9BQNUxaK71FxM5nGa3EvnEW2azPeF9a+S/Wu3yw6OM + AAAAAAAAAB8l+tfJseqYPP8AXAA8iStEN03n6mkdsjSebcKyAB5SXkO8wZ9Pbd3JmK3Hp4karVwbENb3 + NbW2aw2Ea3uxGoLGWSK/6z8m+s9vlh0cYAAAAAAAAAHvyb6z8mw6pY4PXAA1e6Juc0fO7ZfXxdhuPL9I + Kzz/AJZcx38fWyed6Ll6EWVDy3qrKsse/j3hZKiyrUvq6XE6OFPib0VdnX7abSqa6oi5x2675RLSs3Rf + bD1xc9em5uxqZiF9a+TfWejkDo4wAAAAAAAAAHyb6z8mw65o4PWee+Dz3wgS8JWO3M9BOVzDDUJchz1v + D9bzOzsjy/RQJMKN6+0qLfv4NorcE7NZMAZ4CAS98IyYj3wSBC+tfJfrXb5QdHGAAAAAAAAAA+T/AFj5 + Nh1zRwes8B56ItvTz8p3Y64uG1gwzqGsg57qjdt9lVPZa4rfLTKaOdr1b81wxY12ZYzpjzX0lPry1ljq + 6A5Hbsn57wI3QUtq7cr3zTn5eZ7f105vRcY1tG09NSXpz/1n5L9a25g6OMAAAAAAAAAB8m+s/J8OuZ4c + HrDEyY+nkSbrRLyppvPpsxlZZ6Q/JgMK+WuPo1elNpBzh6JOdVM24b548/TZu0k2G+oXymXPNJjbKgK6 + W9T4RM3VokzqhMXldEFpqgIQvrXyX611+eHRxgAAAAAAAAAPkv1r5Fh1WHnuPB66Pvl0tSbLquiNeKVK + t23GjO1dIt+z6Of5pj9N4KmlRC2bvVtD09LFvtU6p0f1ebVs9z82tuyeQ2CugA1J2tcjO2tqzvXJrymM + hIIAQvrXyX613eUHRxgAAAAAAAAAPkv1r5Jj1TvPcfP9f2vsIMRlNjeYb7pGMGlrGFUdXtjY9Ty+rp82 + RRzYXF6NB7vrfazus8M9+qDG3xfRywlZ2nz6I1ubGyDQJDSrjYbsa54+6tnJ1bI+yBLLPDPqzCQEL618 + k+t93lB0cYAAAAAAAAAD5F9d+RY9Vhhnh5/r++NuN9W+FFrbPRul9OEHoKOzx1sc42OWe+Fs1V2gcv1l + R20myfMem9fsm1mmcjZsk8VIScTkIkeWrJ1ZWnreBzmuZV006HXT3edtPE9389871e68eU39F4AhfWvk + v1ru8oOjjAAAAAAAAAAfJPrfyXHqmjz/AF0OYIG+QmuOG3QnVM1zePpiZ6YTS19zzzpAq7am3i5nc/ut + npka52+OXosEAHvkfXCzuqzd1+ZRcf3fBc3Z01vV2PXxbPN0Pxfc91WEC1sxtQCF9a+S/Wu7yg6OMAAA + AAAAAAB8l+tfJceqaPP9cABE3wLRb56MuDq0Ud5T70up9Rb5REq7aI1izau17uDLIrqEAAHnqYj29Vj6 + HlTpNNptne85Y7cOmottWzz/AFduGOVqBaAIX1r5L9a7vKDo4wAAAAAAAAAHyX618lw6pp7wev4BjlpN + U3Vu5tfNO/ymuiptq/bPbbVFtSNXm+NTSClwOjG0917NKAAAMcsJNkHVjeVnqyi+MqLcK+1H0blOript + rVzdu492z8BB7HnG/J0bnGmXRucHRucHRucHRucHRucHRucHRucHRucHRucHRucHR8ZYM9Hvjn7PXgYZ + pQsJ+MIPk8iF7MymIuE3FMHyeiYOyVlMPRIQAAsep123f4/Gw+/Xyr/Z61a/ZMQieTCIHlgi0FOWiCnE + wU4QE9CAniAniAnpQE8QE9CAniAniAniAniAniAnpQE9CAniBrs9NFKkPJ3jpAjpAjpAjpAjpAjpAree + 7Pmr9VeL9oHcWlXK9Lw5ajn1ia8qr0tkDNMxB3IkInhMRI8TZo0eVh7BxLBA2EtWbiartxLVu8loJE7y + GTM9iZTElVzYneq5hIVcskq1E2SNrtWaixazaNOVo2ad2mqt9898bbzHCnrtee86jXovIVfNL72u1K22 + FZrWuVTbzn5znR85fWtGvogdwWnoeJV65sPObXmeir5adNhHpfzGdttSDBuNdbQq/oIlLexbWHavumUt + GjyV5EwZuG0gytEqJrJFhiiqmbxrgztaY+6YmtZaQLNMLJJmKqV5KiYTdsMYsrUaltGmPPdm/SkjTu03 + yrh43RHqLqup0wst/teiXXyt1sq6TqlRbTGsYUpk+qtZ5nOdHzml60a+iEu4taS79Hww0yAAAAAAAAAA + AAAAAAAAAAAad2nNXDxugIAAAAAec50nL36YI19ADf0PLtMercovn1blB1jkx1jkx1jkx1jkx1jkx1jk + x1jkx1jkx1jkx1jkx1blB1jkx1jkx1jkx1jkx1jkx1jkx1jkx1jkx1jkx1mHLIX6gYXv1AiL9QC/UAv1 + AL9QC/UAtaotqC4AAASAAASI/aaYcZLs+g0x4mN30RHGOzrK6c+triLcjYX1xphwGjvIMW5F1nMZb6hT + YSpiKkR4CdMQn0nX08Pzl2NVltTzLbotMvm52OXTxzv8teb59l9A8Rw8fvuCz3xGPSAAAAAAEggAAAAE + AmV9Q9pvyarnnrPq83Cr6KrW1yo0ms1lxxPc025jzqZFqce63US+C6LkabYrzps9fnvY2W/fk5Xn/onl + b/PLKB1WPVac3tmdHFNiS/L5arOstJj5tYV/Wcfp019lN6OL3kezrLU5+v7Dk+bv0DDqAAAAAACQQAAA + AABKdBu9MbKfrsu7yMI2zXNMMJUWt+IvqC34/VsbzmOl6/Oj1ljNmvHVdjXcXqWFrU2emE6yypunh0sG + PTz3VcrIx6u3lQZ3f5EH2Cz132VbZ2pxF1zc3l9C3sOYvdeezpbXlLVtq7VHw6oQ5+0AAAAAAAAAAAAA + JO34m425rCJVR4jpLbhL3TLodNZXXxzsaebnvLvOXaY3tjyKaWvM2NXj1x88GHX23F4tMQy3dnxmzXDr + rLh7vfisIHLy6bdPb83o15qLz3zh9e4v+dm9fn3fBWdZnsGHUAAAAAAAAAJsxCWe6+VM6FNeedDWxaAT + 66QHU8tagU1HR2z5xcyrU5x0cCFWylU1hulgaY1LsKWVSlxM9jpKS2cZZTpjnz3LfxYe3zrnTab5c+sf + Ka17PpleWZb40jOs5u+UdneVvQOhWz550I55axa6RFrFREdCtTnl5R01CLhAJBBKi9PpjN5jqeO25eju + PNm/Jx+m75fk9HsrHk+r6eHVo47totpj11Jnvn9ApLO+WvTom2xz169145ezh9dh1V++kutOfVGz2THt + NYac9r6DVdHrhSWMfmM9uw5Lp6Ct5c/nu3mqv04a4e1vU8Dl0W/U/Pe9tXnb/n+jmlVZapd6cVO2Y83Z + bQJcXXnkV95w9Ne2q6i3lb10mNphspew5GmnYfN/ofz+unWWXP5WyjUnT8xz9wZ9AQToM6+fdUl5857P + M6Oz5ro620VtCx6u+00F/wBHFFt/nXdV09ptNHnrf3vI9dplV3FXbXx56y2ItzPU8N2WXTGmQbXXmiaJ + NjNeYk1lpj1Wkvmuj35OM6TjrXn7byg6HnrZ6O44ft7UrdTC2dxwXe8FTfob/wCf93bOkm8l3CfavZtv + lR76Ody9/S6afqenix52+qYR5NVa5dE7RM0bcsFKU1l0NzUFT2/DXme9FpOftCJAdHzi+fY58W15+zcY + OyqqJF7npOD9R2Evg/LU7fTxyJm9dwmUX6Ww4rGadtG5L0ndHx6t+lkcljNO1cUs6PGgxpp3G7gV8ZPU + ccz37vlK9NexmcEtn17kB3sDkR0F3wiJu7Xjy3TWHEkXFxyHkW7GmpydvY8Sh0dXAJvodaiXS80ie95i + paZSL3mlNQpqAEAkZ9Npjyy53o5900Oa0rrIMxQuohxNG6n2Y5Vf2yOKXdqnj1vUZ7i5RTOpr75UzrK8 + o3RaUUbr40xzLo/Itzq/nnIr+UjlnQ5S5x1dXWah1dItXryki/jp2mPMOnnq8S6GbFuRW8+J5l0fkxzr + qKmtq1Mh57gkIAkJBEAZ9byEjXmvd/M6L06nVR+I7Gmqkxfubyien85ryY6Cdx20s7nkMomyrdXue+vq + uV3yv/KTC+PQZc56jqYFP5MdR5yuZ0sGo8h02PN4p6CbyO0vNvO+HT6Oc2HXUtZgXlfW5016zzmPNMen + 3cftmLydyO6trKy5bNPVaubjTXqYlRrrfPT75j1BEgAAAAGyxvSqWMmaUqz8TWrvTMVTpa1FYv8ASUwz + 6CXLtjUp9jMc+vNSKhdR01q7rImOsa5Yu4E1hrCBW/iVKmlWnTZUi29KhdQCISKaR1p5fKsXcYrU6aUi + y3FOsK+ugukUq9wvnSrfCJq17FKxb75ihS4mewRIAG/oucm7ctnL57DTHqa2twOkpNI6iqgx5jo/OeQh + YS4nP33c2jkbcmd3zm61LNV4yu6TDyl+hpvNM1sqmT5F7X2jztSTU7NGPTPt6TfpjP302CsyxpfZnoqL + GLDTOr9+XR0EOPq25emw5rdaljY86TZ2nJImxo52rPoidhx9kdRCosteW+q66PXXuqiBHtl0GdBtThVS + ovP2BXUIAErbbOAnezEBN0xfT5lITFWsNSMm6kx1hlatambYVzbqroLSa1aXvmK1eQ5rXrPCJr1vomK9 + I9rpGWcm2dGssU16fLRSreAtHJtbwl1GvlXLqNCuWutNcmy4U7fojQ9s1ataVxgl4kZc18xGb9FbhEhI + IAWUqH70ccyTX+Xzn1W3GmjBlW26vkaEx9sjyt+ogQfejil+Q4tb7K+yg49fnc8LY3xtdtbp0w6SDXRS + 3wqZqbXRCjzHuUVj0Wdny8/XCw2UO4l3HNbkT6zToptGt6jdlv2VJqrduXp6bVBrfo5FP7fOqv6iTn0V + zfjntl0vJ3OvNd8jK2TWdB3wTo+amV5OqpEfLpCmgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEyX5 + zvTxdI4Jtzd64Id75wY77zgh3zgR3zgR3zgR3zgR3zgSO+cCT3zgR3zgR3zgR3zgR3rgvTvHBDvnBDvf + OD8O9cEO9l/PO3pfoVq35arTdx6zQIc3h7MbOo6voxoUitrNpAsaOUrVpx597TVjB0zm7Y0Otugyn7e7 + iq1omKNYq2+ejzvdtuV6rlOngqvMXb5mTAZsBmwGbAZsBmwGbAZsBmwGbAZsBmwGbAZsRkxGTEnJiMmP + hn9B+efQ8ejtxrzIczCJ4yRNueDt5Dr6CfMe4xvDoeQto9qw8Ogr8doum1ymKvXcQq26HfFlel5wXiIK + 3+ejy/ftuU6vlengpGXnb5p74jx6PHo8ejx6PHo8ejx6PHo8ejx6PHo8ejx6PHo8ejx6PHofQ/nn0LHp + 7j3msc69P5y0k6Fx0yLdKpIlqdK57FPRuRkVnpnNS7VunO4xPSOd1y6b2uiXpeOZtonaitKcOPM+gtqW + 6od+SDj55rz5MUx68HrwevB68HrwevB68HrwevB68HrwevB68HrwevB68HrwSep5Lrc9Jmu005Z1u2TJ + i1Ln1FUR9Nxq0pHwzlo52x2+Y6xJm/fpSrwmSCBEuoMT0XN9BSdGF/X2UXXGMzTPBjzfftuV6rlengqf + PPO3zcnhGTEZMRkxGTEZMRkxGTEZMRkxGTEZMRkxGTEZMRkxGTEZMR79B+e/QsentxrzDGHrld3Pv0jk + pKekcb01ol+0mc1uHOYVt0rmcodKqKq0dZ7V2muQXrEFdfno8v3rfk+s5Pp8+le+dvmj08AAAAAAAAAA + AAAAAAB79E+d/Q8ujuPIWM42GuFuKrO8hZaQtMzOl66bt2WiOtIN84G3dtppqiT8EaNVhrgsoOjWlqg6 + rVkMEuAHme/b89cS+jj4bX9Cw25uAd/sPnj6B4jgHfjgHf5Hz53/AIngX0DxHAO/9Pn76B4cA78ngHfj + gHfjgHfjgHfenAO/HAO/HAO+zR8+d/6n5+78cR2O7fW8jTIwyrHl45xN/RyIfRhXydvvP0Rt+zVavR02 + 7TvhAn+Z5a6K6f5ndAn7ZQ41l5W0XGYJyE7Obkx53tDdaLH3dnvw0F9UWlNdlDd1kxb7MctuXmr6jv8A + Hrrq68p63totrX6c9Ve1lrXSPU9FSJnydvmmHP8AQ0V/W+PN9Ty1bXceWvnUWVfPptN5uT5CKzwy6fb6 + lvNeau028Ka5z2GuNB1VJaUvEr7SkrpcZQ8rZxbCr6KL6ue6vn5rZ1dxomKi4hXNZh01xSxe21SNl8+e + e5c3dgIkAABnglO1Rk0SoqLbsMBN9le7ctVKg9PW9XCs6cnZbLG+XM3NNe11rYk+dCt89yTFlQpUX2Rb + OqVl7sZWmVVqlXlb0+i55+E6DcyJpQzotlF6rVcz7V5eXK01vEw6GBNNES6mWjmZk+vpeLvs4Mxq0Ys9 + 88CJ9ywE6LrTEzdWprJ316JCtwgAEgAAGWO6Yv4tb7vyROjod9NLKolwUdHHpLK+VXcVs+myx5vya2sr + nkWlNUiLbIWeKLLfTb7U09Pye1PUUujRNbL2pmRMC6q5UXmb+dlWz2x47Pe1h+6JpbTOazvTo6jRriej + 5mTuRXjHqAAAAAAAA//EADUQAAICAQMCBQIGAgEEAwEAAAIDAQQAERITBRQQFSEzNCAyFiIjMDFAJFBg + BiU1QUJERXD/2gAIAQEAAQUC/wCDV65vx6DRNWtNjLNOa4fTHrPlh40JUz/b9JLSzeTzIoI4Ey1Wb04M + rLOpoAVdKGCdwqziX4EAFnEvOo11wj9qAOYmNM0zScr1ifNiqaM0nNJ8O1fnaPztH4aWLjwZ08wX/OAh + px2j8IZAsrVysFZqlXHxio6QWBMLsbGdjYxlA1rzt24um88ck0zHrJ9PMF/VRrw/JAqlpLeWG11sDy1O + V0Ci11b4vTmil1tZNR5c/PLn55c/KNViG9UaEJrpJxx0wMZ0z0mJiU9NkonpgZZrkiaNOGAdJBwSSh87 + atY5kio2Rr5Wtg8rNka+IuA47Nga8XLgOTkfbPU9JHqessGDXnTmpBZzECAAGVG8w138x9Vn/KSFTiQC + hh3AU8dLOOllrZFjp7I7RAQHVbTTUPevy1ZcwAnaVe+Lm2W8Clul97qMfoWfj/V09sKfbahyFpKK6FcQ + vrS00I4bHVvi55pnmuDO4bV7gb5plt/cM6N/PVWGLulnJ17A/wDc7hyut05zJs9W+PSmGU6NUq5LCDtd + VduPKXynMhKwZvBTYZCHQ7OqhAuyJ9O0r52laMmfTKsVeCPWDcnKO3ZUDYFmZJ9SvL2REAEtpzITUMr6 + F9tWGCd2NeYSqE9UOZiIvRy3JiKteYFyXoYTJERa1R2upexZ+N9Y007K4uYmmRSJy07SwMX9W+LlI1RV + 5E+BGuJ5E5Y9/pz4SxnbNyrxbbH/AJbqXw+m/M6t8ZLjTMW7DyZMIQvpw5co8QUvlO2cb1ya6lXt5WYk + zrHu9OSDmdjXy3RUKlUkEvsK+XUwh1OmAw161TxpevpcaI6eye56sG14NUgSmBjvK2Q5DXX/AImdK+KI + a9TuWSVYgRKerOnfnTK/GEzpllMDc6l7Fn431U18ll87UdOcE1hlY5qrfugrHVviiBFnC3OBuB9k7h6n + aWDlSlkZTSLz8rHK6RrqsO3XJ2PVXpAhnVmxtzpKdBbYguodQU5g+3TpfKv/ABmjyKrJ4Qr/ACese70f + 3upxMstfFX8bo8TC+rfJ6YwjsPeKpq6Snp3t1EBDOrM3PR8gpgR8wRgWVOdf+HnTBkaryNMdwteDedzW + mJeulp3Q3IZZvlIVwvExl5y2KtfG+rpzEpi7cUdfw6ea5rQaYzqdhZL6Y1as7yvneV87xGd5XzvK+OtJ + lYzpncuwnNKMBhhncOyfXB03TeSCf/aeoMCLNpj8qlA2L1hTK24srN2Pi5WHLz4e2g8a7PMk4++o0q6g + oV+ZJy84XtovFDfMk55knKNhQLawuTETo5tpEqxF1PFdurNQ6al1FexPUvy+ZJzzJOeZJx5Qx1ExCzfs + qZWxF1PDauqlP9xrBWFayuxGAEliglh2VcbdkwvLNldfEtFwf7nrk/opaSjqWgsBSmNBTtBap4LUjCrL + wrrsOJzOhl6f7d9tKJS5bo657XRulH1E+mdPXcafVbdXPO72ed3sHrFthdU6fFNPWekTRHoXuXLwV5o2 + 4tD/ALCwcgryu9nld7PK72eV3s670+xUappqNHTbPV6fTqFyjU6X0a309/UegWLtpH/TLVts/wDTTGsp + /wDTlitZ6t0i51GbPT7tjp7+l2OkVjKTLonS7RVfK72eV3s8rvZ5Xezyu9nld7K5mX7uua5rm7N+cmQz + IL+tb9j6HpXYV+FkdwpYqX+w0Bav8N0u4iNI+pHv/s65JZLM3zm+c5cBJHkV1jnGuMKFYHocf1bfsf2K + /v8A7EzkzJSFfBAR8ZiJwRgcmdMKdcezTEjpkfTsKQ8OMoXgxJFppOREz+xb9j+wj3vrnPVhLCBiR0zZ + OaTH0kOFG1y/pUEsOTgXWKsjipiCGIiGGTCpbAK/EDGUUMGwasoBvsMXEdRHR1gj4at9Yrdlv2P7Cfe+ + tk6QkdgeOs/VYXvFcyBDP0JI9dTJllkm5UqiJf8A4jDEsrcUBBgFNhDOVf0BejWKU8NYJ5Rt2m8hvNNM + zIyy37P9hHv/AF/ywbA8/wC1aDElrEeMTMYDDXHgbjNeAZBJMMvAiksFhjkzMz9Nv2f7CPe+qcT6u6ij + dJy+u2szlR+wyPVXoQ/1Lfs/2E+99R5Wj8rLUqumwmtSOxXjf3rZHUcQ4Xx4M+4/SwHjprnCzbtLYASc + 7S1nIGZHYW3AHeZAQzprkgUR4REzkgURb9n+wn3vqbPoEbVPn16Srkf9Fn883YSmx0mNfE/ub74fx4Vx + OTtRHG3Ts6aVskRmUXflDtCsSv02qNZV07U2hKI6fOlnWNs+iKclMq3QZMMst+z/AGEe99M4z+Vt1m1S + ZyVEcCfovnq+Z1np6+Op4/c8P48K2nI/QlPZsVVP8lc9MalmyXiI6LFkabtw9rrFhCdte0qxva9pzglI + lR1J2W/Z/sJ976ZxXq/hjd9V33qieZ3gyfQ52ijBn6BMhjxkpn6f4yZmZGZifCPTwt+z/YT730zgztcX + gJQX02aoOxK1Vly42ZDTDN+/GbrGEBKxLN0R/Tt+z/YR731MjWEnvBoyYAXDglBeMHEy8SKHLLZKxaCp + kDD80nopYMkyVEQ2PCImZ7dmNTK8iNZitEBix3m9fCzOBkZ25SOSnXGJJYx6zNVu81bIt+z/AGE+99U5 + rKyEoKMlIZxFGcR5wRBeDI4Jt+/WnQZgrJsdA5XHSI8Kcbm+s2b865WgJNmvI6Y3V4FOMEAhkDEguNu0 + BCpEGzSOW/GgU9vHI/5FyI2XPZ/sJ97x1zXNfAoz1XIWQLInX6N0Rj2aYywe3haSinlFmuQodVt0IZ8I + OYELGyP0NwNhYc65c31aqRXjnKcc/wA2G8h1TWAKbIYTwBswljkmK8XY2ZYbDV3PZ/sJn9bwL0jaycmS + DBbm/JZkzJYFWSyQ/Nsbm1+n6k4cTt2GC9hZ+XXjiZKdmGMlK41aP9O37P8AYT8jI/kvsAt0ToUMrDOd + vpgoGMgccewemo9eIYGQjHCO++WxS/z9NGdYriJrsqAWTH5tfzVo9B/p2/Z/sIj9fw/9SUrkLRzmrZwW + wOAwTw24kZsOrnCrhsAIt3OSD+3qPxukzvrVZ/Rq/wAPnWyPuesgK2LEGen0smYEYXnEucKCCfzZJZEx + P12/Z/sI9/Iyf4gd+CvXNSkt0DDTiJYZMzp6NVCgIya87TVIQz7bcao6GXpXyt9zPka6ZXVMQM+r42N+ + n+MUOsxHhEa5phLCcj+fpt+z/YT8nI/kvtUO/J1aeghDW+oL1yR9VNMV87IyLMxjWQUH9rI1X00+J6Wh + La/3tnSwtcLzlMpEm5s1+n+MAGPzgbGSpsZBevg20oMP6rns/wBhHycj+T+wSHhB8Kg2EzFr0zT001Ys + s/Lk6eDJ9Mpr2MIR4V1RiJUtM+riAM0zT6a6hdFm8RYYPjBa5cKYFoY1gnToqmatrvs+m37P9hHv+E5I + ZCsgfAsRGpEOmQUxnJgzMyQ6+ElAGz1YXplg+Q1j9c+uXp2LrVxrL6mX60WtlKPyqtTqrDVKXj+atHrH + 0W/Z/sI9/wCs8qx+XwJuxsfxhehW4/VgymDaZQpemR9Yzo8h16g8olnV4/MZ7ypTupP/AC9NH7ZASmW/ + nD0+m37P9hHvfW7+K0flP7csRq+qWoY3+bUfkV65tyI/Yd6QU8g7xMLwc6IUQF0xBbOoHqQKaeDqUjHq + PqX0W/Z/sI9/6pnGliz0gi1HGe/UnJw8ONwVy9In9mY1hD5QUgt8RUYORXmZdZWgV2GKc+xYsRVjSuwt + MiNI+i37P9hHv/TOREsIEKjJSvOKRnGfJrfeeu0a8aSlUYxMRiT1yP2WQMwCdmE5g5JMbK0aY1InkIEc + 5N2RGn1W/Z/sI9/6SxJbV8mb83+D4/yU+jN8ZvjCnWcj3x/YKdIWP6jZLRRaOPQj/NE8TNs9NOckNC/M + GROv03p0r+f9Oz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8 + QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOz8QdOzz/p2UzFhfSWbZjNTzVmaszVmCHrI5O/NWZqz + Pzziw0yP2D+0pmcncvI0jPWc/wDmj4tZoODrIaWkzuz/AOf+k0zTNM25t8dM0zTNP2adabBDSQMdY6cZ + x0mi4m9ojO0TnZoyK6oEELCWV1NztU6dmjO0RnaoztUZ2qM7VGdqjO0RnaIztEZ2iM7RGdojO0RnaIzt + EZ2iM7RGdojO0RnaIztEZ2iM7RGdojO0RnaIztEZ2iM7RGdojO0RnaIztEZ2iM7RGHVTA8Cs4FZwKzgV + nArOBWcCs4FZwKzgVnArOBWcCs4FY2oBZMaT49MjSr/rm/Z+/ejSx49N+J/rm/Z4wUTkzEZHr4TMR9Al + BfR1D5Pj0z4lhsJXutSNZ3MGd56LdJly/rIfyExohjXCrOdcLBomMWh1UzkDu16rfvnulbjsrAiaMZ3X + rDo4zsaGLJ4ws7ihsbwsrMmP2Ep28idEN5f1jcAYFxczDBkItxiWQ0ZtRGC0Czuozuh15B3k4YJjwXJW + duCcSAlE+Dfs8GFsFTNkTO4ddMbsdjj3ZBO2w8uOGsmAEwmXMHx6h8jx6Z8TqAzKotqldCNYn+NJ21tZ + dAkU/edpcC3/AO+r5JztcMROUi1hesYmZltkdq0+oJbtX+oTyd+ke3eoZmqsp1AZITKeN0MCVCwsZt5F + hG0R/wAWG6lIQuskp1r7u2TEQuttIjcuX1mJ490k6FDlqYFx+mDo9NeCJuN+zwcfGC4KY9NoxEk2AXLf + U1lAxTjWGcMGHHrXFRePUPkePTfiZKFzlQGKYyJIJSUQhJhJrZLOOe4crklqN5dqOxdcQiUloC9iYS0C + WtvPFOIw6sERpKSKHcjQNy5SeKTqta53iueUKkDMLM3RDxklu3bWDW2tAJS+ZLk4RrlMVxMRBJQpKNsE + trZ4jA5U3kKHyzjgsKuERWCQSmCEMb9ngwtg1p2jO5jFzKjdq1zEyRsVKorwS0cp5EHlcjX49Q+T49M+ + J/rm/Z+/1D5Hj0o9a/8Arm/Z+/cLdY8UtJJj1ONPMwzzMM8zDPMwzzMM8zDPMwzzMM8zDPMwzzMM8zDP + MwzzMM8zDPMwzzMM8zDPMwzzMM8zDPMwzzMM8zDPMwzzMM80DPNAzzQM80DPNAzzQM80DPNAzzMM8zDP + NAzzQM80DPNAzzQM80DPNAzzQM80DC6kEx3w53w53w53w53w53w53w53w53w53w53w53w53w53w424RR + /wAUhLJj+MXWa0WoYr64qOmGLJRfvgMkXZ2PqiJmeFv+g6Ye6t1NOjai+JD6wPzy9GeXoy7SFS6FcX55 + avPLV4oNgWaoWM8sXk9NDRgyDPFCSdLFGqfCj8r0yCAs6ksZr0KoPWdYEWD+3KS1TW40ZCUznAnBFQy5 + wLXPr/fq9ygalgnsEoKLFciDs7eVAaqz1P4fR/5umYI7q1ndWs7q1ndW8j+L3yvHpS9qerM1Z4dPGStW + S2I6T8m/ElV6UMiq775/bg1HTHZWM6alihtDJ1+zfnZPwhkS/vdMZvr9RVIm13CKSkl2LLwbVYxtrqfw + 1lIl3Kc7lOCUFBsAM7lOXbATXnWc6UIkzhVnCrIiIiVrKeFWF93T+NdVze9dXqdsfeIyocMK775/bir6 + hX5inK9gXww4WHmKM8xTjyg3f3qhM5CW8I7jFnDAKwMMBm+x1P4eIocqvLIxC+JVyt3GeVxlyt2/hTRL + y8tLKtKVNsBLFeWnnlp5PpNBC2Vl11LnTXO0RlYBA7vvl9tNEWGeWBnlgZVrRXhwci/LAzywMu1Irr/v + dJDdY6jOlb/1WCQQpci+fkdT+HirzFh5k3KzJai5YlJTv0tvNpZVsTXLzMsSUmqzflTvMyzzMsn+VE3K + iiUE/wAXUTx9KmSVd98vtS40z37879+dNcbhtFIV+/sZ39jHWWOH+909PEjq5/lV1ExHzTAY4hDklvUv + h06kWA8sjPK4xC+JVyt3GR6RZow5lpPC3A03d4niKdxeNIVqrLuQ2y72a1hcoDdFjgebT+zwTRJq6Nea + 43vif6AZ0nzF2PcTj8EdQlSvNMs2zeNa0aB8ybnmTc8ybnmTc8ybnmTce2XH9cmRRUbCXH1ECDKzeFnm + mO6iRh4VrhIDzMss2zeP/GKqYcy3UmvCKMtV5YWeWFnlhZarzXnKSYc+zTSpP0VaIsQykcnW6flnp+dg + /J9JqK5nWKAgEUH55crTsX46uxXhTpAxFkYB1FIubeqqQrw7N+dm/K3T4ldujtns352b8GNSPp6xUMSU + wlmrOnL4+FmEMjkdNKY8sLPKyzyss8rLLFI0ilBuzsH4SDBnlh55YeM6cYj+zVPjsWHIakLTVj05znMs + s4q/fWMJxNZ3VXRWwhfYSueevOTYrRjLNaVgMmURCU9PLenVp2dpgFBstDqHzOkK9bJ/5NwjBIC0xsNJ + TupfD6ahbo1BcNpJZnSlbca2vMgpDAtrhNhd9xlyXMDXY47MGT7YxPUWTFCsDQMdwnC6VlTeRc9RGJNs + iu68XnSe1rTU/F91z2BcpVGy5lm/8To38S2e76r+UFrsEHdWOQvQco1QBcEtmdRrQmfpoxXJNioolLAm + HVTCFP2cd2lEjlKpLiccISwpYfT/AInVvkZ0ytpF/wCJ056wrnKjwOGIBqF40O5vqCFhYmB6nLkmMwjX + 9HL71HV6N/HWfvV7QtgotJNJ9M+H1T5VD5R67N93CbcAQnet/vqmd7vYpVeXErFQFVUTWALAu1FKTSrL + cmE2FZXbzX73xVGSiZbcwOjfwX/kur+0MaLCq7nfGqSGQmOpfl6Ukt/WDjT6afyT+xJoq10Wifc6j8Sj + aGUWAXNsHrlnUviLvIEEnDFvtKSd60pyalot174q+zrzOrlSh1dzNrlgwK76DCal60narNVrcrcmVTsD + F1ac6N/FligwPbrnsu9RVyI6Z8PqnyqHyz1kOGxjFWYBHs2Pf6chZJOdoxAXzTSBRtSJh5aGXKsKkenN + GUBYDK1SVWbK5anyw88sPOj4X/kuq/Z5ieeYnlN/cB1eP164wTnHCEMOWH9NKNbRfbOsT035fUZjtPDp + XyupfEzp3xOrfJyl8q/8VSa6JbyaVyskV2wKV50r4rki65XlW1pWhkdYDqD4c3o38dZ9xXsn6M8xbp03 + 4nVPl0PlsjcHbLxlYdifZse+sy3P9hM6GogNa6hw6+6VK3lM99YxVm22UQYr3Q2bRW0Z31jOj5Ky73qB + 8eeYpzzFOUCE46v7yd3LZ7uU/V0yVKF98Vs5Kjs0pZpSzSll/g2dJ+Vb04tKWA6uAsmqyZilpS+Vf+KH + ThwWorgF5JYdRLyto7culfGfX7i6uumvJ30jhmiwDenRA9LYC4YdVmdwiIiY7jSlgOrgNtgttLimBE9B + Dso5so4NhEQwac505KmDaYAopVltXB1K+H1P8ybqm5bWM3or1FYV5C4sX2MxTCWVa2Dgt1lFlayVfPM2 + ZZtlYHKi6xoVKFR1JsNeg9jbF5bE/va/VrOazP0TOuRM5rP0RMx/y4fUpQlOPrhFaK3p26SSqvGppr8a + 0h3Q1Ym7YQMK7YIh9dOtNSmKOumcWoSszWVxX1QM+DR2KYqBr1QU9jqgGYJgbSEhxuXO3t9EorhBV66u + AkqUpFYBusrJIblcMNSoJ4J0FCppcSuenC9nCnddERb08BJecIKX2yDKsoOGVLjDWM2u3DLKlgdisopO + smMhCprgoOZK1TlpXC39wPutz+ezrNDj1AdYbWKRucsa15mLsb56hciQB4brVkZtqoB+lLS1ZtXaIx5e + oSMueqVHk7xpGxsI6e2efcBGevmp/pza0YvlUNOuQlNbXh3TJhP/AHIo/RukYjMbnu/PWF3+IBRPUKi+ + LNTht4NzwcFMXqlZNLbLCiMrjohkuiNpxePXW4BtfruMxLkDTt0vkij06k0pNn7vcNwmmcYDmBgtYOdw + 3Ie3WTKYlhyBuYcC1gwLDjJc2cFhjIuMZIpKTMjLOVmvO3BacELDAuVm6HMjCcwo5D2C5giLmDAtOMFp + wfIe/eWnOzUnMIRaYiJEM8zInnbnKeuQRREtMsNhHm4s5m5vLOdubzzmZs52+C2mvN0zP/EAiJNdYTY9 + ArWinB5NXK1blYNLVBVNtgenDpYrQmAoa4yltX4V1iwq9ZbpJStSoREtpQCwrLJcVA5FVtzm0dpOXxzw + QNXFUCnG12KFVRjQmNJrgBkusMpsI4ndjMrsVeMatUHjNZIwhXMyf5QIm1VdZMalQEqlEh2s5wjwMqAs + 1JWbWU45nIhdfwXRk0jSCYr0uQxpHIOqELIpjjaZAp1SBwqOkLTJx9Sp2sAY3vmF06u3tVyUnUL/ABKc + yVdPLNjdtC5MGCJiVN28Ok+HS51bSJcOYxbCk2SxrYlFeA2Xk7jFLGG95jjT2P5OMGqkZnYpSdk0ahwG + FMkVLXkERYjqJRu6eKt9oEgyiQil4jJ0iFduf5oT/kiS1XLbFsJUx2usktA8tCZ3srE3uznWxc+HIyPh + WeAUxJJZREIZWGOd36TBEVZe0CLJjCJ2sTXPT61HsPu53FZlgi/bWRZ4gr2OIBtnDitnu70trrJNHudB + dY5FA3ajK75Rg29CJ8axcLad0yiLWzF2SCF2SXnefn7kt83TmStya5sSRus8igYQBld3DMWpCCsQcusG + yIslIdzOHcOXLdK2YhvCfdzqx8HE2JmuFrYhdsgXNmJnn/WY+Te+xyhYbzFkWpGItTGKtcbq7uFhTqZX + pOX2ZaHdapXfMchxR/wpKuXO3mM7YuTtp2zXKFoXytKNCXXYyDqFAShkF2rcYk1xNUt7KhiI1mlHaljA + lZ+A1JlVhBJlFWW55ee1FUmsGoXHNYu57IsfW4gQvla9fE2tTJ0eXHk0z5e2wqxDA0C1KicYCiNeV0S6 + ewKJOtsYFHfjK4gI04Jba3GlKYYIUt+OXxn4FSZE2KTFQMalZTwMSk24fT2xDUGrGqJU/sJESQ8APN8C + 90bYufbR+U1it9GNbQmpr3REOxXoyC0bMf4yFrmtsHW6GyxgFIkpkMK4cSiowApgeuUtOR22ajxmb7Nq + ovBuT04NX9SD9aht4eP8oQMdRQGoP9K1edMuEa1Vi/w8ohrH3jbQRvqysFOAWJpwEUy/InHTw0/BJQDb + bBPLZAAq93qDtj6hR3GgGiwO0r87i/YpvhE2LEsZyqNh2BmGPGVpYlbJlBFDFrUk1LmDHfyKyWLxLki2 + bC+NFkFiDfWbOto53GOm7utuFaTJLsLWsL35q7oU437gZe3F30Y+zDRbY3Cl8hAO48i5AqVZ2WO4RjrI + mtN3Zk2ikwZArxTJWSrQg1hyZVXwmI/krMFPeSeBIQy08WCg+NrS3sybYYNmZxb0jDLamET5ggulCGNN + kOZvn/8AhlRUOdup5up5up5vp5vp5vp5vp5upZvpZupZupZupZupZupZrSzdSzdSzdSzdSzdSzdSzdSz + dSzdSzdSzdSzdSzdSzdSzdSzdSzdSzdSzdSzdSzdSzdSzdSzdSzdSysNN7Owr52FfOwr4yrVWOlDCGkM + iNIp7CvlivWSFevWcHYV8eqqo2qpqL/Bzt6cqFdGZcuoo5VRjIo15jsK+dhXzsK+OpIiPDpny7DNi+Q8 + 5DzkPOQ85DzkPOQ85DzkPOQ85DzkPOQ85DzkPOQ85DzkPOQ85DzkPOQ85DzkPOQ85DzkPOQ85DzkPOQ8 + 5DzkPOQ85DzkPOQ85DwHkM9I+Z4t27EGuGmf+W/TvM6n7FSzwqr2eY7YEL7QEB66iGvlnppcUoICRmVz + Eh42Pt8Ol/Lu+1/ppzo3y/GwuGL/APqHKdzYXsR7PU/Y6b7GWIZzN3cgD6qKZpaflLepu0nGnWF+Nj7f + Dpfy7nteGua/6LXw6N8vxn1jsJ027VOTZbhjYGGJtNFSbShGLe5qXNe6qLSbWIJq1p4JpCMJrHLTqug6 + 4StXjY+3w6Z8u77X+n6N8r+tY+3w6Z8u77X+n6N8pjDm0DzEzaZ5aMgbL270ERss9xoM2IRXG1AuJ0Oh + zNIJ2XnFvmXGusT3jZaZWHvPt0uPVqmGTAYuK0vadtkqTuk6/h0z5cjBrKpnaFnaTnaFnaTnaTnaTnaT + naTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTnaTna + TnaTnaTnaTi60DnSfm3oKCgtIj7LzIKwRauUyBtdRYc5bkeNSzJl9Jbi++pr3F0pJ3C6FUAMhvxow1nN + dc65H8dQ9bIxpF+Na0RpX8Ol/LM+NfdHndHndHndHndHndHndHndHndHndHndHndHndHndHndHndHndH + ndHndHndHndHndHndHndHndHndHndHndHndHndHndHndHndHndHndHndHndHndHi7Xr0n5rEMaxVdkv7 + dsnaQZuZE7E12dxeUTV2a0sWyu9ssCwZtoztmq7LqTZjgeUqrWFRcQbh2WCE6JxMxMLKu9rMeEsWQ7U+ + HTPl3Pb/ANP0f5n9ax9vh0z5dz2v9P0b5fjP8CZrwGFGIndn8093pX9igWrboFMKeYLMiGyGzuW6xaQW + 6V/ZTj8vjY+3w6X8u57X+n6N8vxLXSazMVWLVFcs7ZkqmqyQ4ThZVduGpjsZXMmkhnOoD5iqmWLUxaxr + Go6aiUPi/wC3w6X8u57X+n6N8s7AAcWlyRWgFgOA5wLAnHeBpFpch3S8Y8QHGWFrILaiw7AAQ2VkXdBB + KsA2O7XkWFyHer2nYWI92EY0tQ8Ol/LYvkUVc4zhZnCzOFmcLM4WZwszhZnCzOFmcLM4WZwszhZnCzOF + mcLM4WZwMzgZnAzOBmcDM4GZwMzgZnAzOBmcDM4GZwMzgZnAzOBmcDM4GZwMzgZi6pTnSfnWdeaNd1kY + 7np334n1q6RtmI4AiDL/APOj+LAasQMnFoxmTmSsz6LqAY5AztV7ID+iUaVzmYKPY8KTYVYFdGMBFQ82 + Us2UsBVMylVKJ2Uc2Uc2Uc2UcFVOc46WbKOQqlOcdHNlHBVSKZXSidlHNlHNlHNlHNlHNlHNlHIXTmeO + lrx0c46OcdHOOjnHRzjo5spZw1NvHRzjo5x0c46ObKOV5ppabqZnDae6W1CkH1Azvq+LfVCOapnNS289 + PCbUlff18ZbrGKrVVQxcqxK2VeTfUiYdUwrFQsB9QBh1OIl1TaTahEVqvAfQYxXUxPOvKoqIbp7IH7rC + wWqQCCykCwlnDEZU/wAcHInTKiQiL4hyxEzJcvCa2BjAJZGoBWgB3ZSWvmbwYhUuMaYTiUJEZ/nxhRRQ + BAzL1cLSFKlF+TAn847Vt4UwbhFdgFbsZPFX/NYaG9rbWm0Y3SivMVyrNhhqMCFJlSr8fGyJ3UVL5myi + S/aWfHMnHa2nGtesuZX2KO40DYsYOw3Vob97xiZlRAmOpSWLmBKkzlYyyYmLB3BOq2EUJJpEcqNgqYB4 + QjLmzuhc6W//AGkgqx1CTFFZnE6u6W2WG4iamV4QyPgsdxTtinVj9WdJtMsic8upWx3XbJqEyaKhYe9g + WpEGa9ihZMb6Lzi0e1cS9MfnNkNCw+SsCRkiu5hokiPEEFWL8mNbCEh/ZCdCGwXNYbLmYgxA2nvYJyGL + ssWC7BrADIMU3bg2igZKN/dGOd06RxXIpDbEsDO4ZotmxQFISiw0MTZNUgUgSm7cG0yMYQlOuk94/TkI + 2XHczdMACOWsetUsOfGs7hMykzxp8saT4NsG1QzIypxBL2y1ms5BlA5E6TuLd3J9uBSEg7Zi7ZxhGMnd + dzH+/CQBTBsOCY0mvXhcMIRD+cn0xwwpWdTMxbWQZlcQRF27NlZPN4VZ0sWq7SdHrK6/57EDJ8Ym5yRk + GiIpynMwl8NameRJ3/VVOAJDVi7DWmalaILBXpL3aH05eCCyW2upCkJgwGdUWuHX+0MSRP0hKwSxWV9E + h1LUYUJkbBMnnZ5fDqnv1R44EuGJZC6tW3rjnS3K0TzvW0nGBBNUOKIYfZqGTNY77DBWsLk8d1FyRx+n + a/zl/wBmlH+Oo1nYY+Cr12cTVulh2fkVZ40coqquJe+mG9zyHt5/trOQxbjXBWGHAFtKHsjF2iFZesiR + BI3T0ayWFYsKdm6dSKSnwWZLKbTpzmZnIWpMIye835E6YLTGE2CWTWS1i52nZdDMVIQVp4tHX0rt4i8K + 7iSZFuLCKSywzlbBlAIeaZa8Tj+j/8QAMhEAAgEDAwIGAgIBAwUBAAAAAQIAAxESBBMhFDEQIjJBUWEg + MDNAI0JicRVDUIGx8P/aAAgBAwEBPwGMwXkzcW2USori4l5ePWVO8DA8j+5qLYG8a4WwPEXH3Mpm1QWm + pvuTbQ/64VUDhppWtTu06unHrKguZT1CObCNq0U2lXUY2x94zFVuBG1bnygcwatxwRzKblhdhaLqar+k + RtTUQ+cSpUwW8TWMO8Orf4nUYoGInVtn9TrB8StWZVDLKmpcEBYtSqTK9R6fpEpV3fzHtG1TG2P4VFzW + xhtaywXvEN6gmqxAuwvKhU9haKyWsVlRf8NljMNvG0fkoDKiha4AlTTut7dpSZVObTdFSmcZxGt7Sk+N + C5i2vwYSCeTNQ4NMG8A+YVPmtGrWpDGILwXDiawEDIGPeow/4lNc3AE1ira5MpEQdh+FdiE4lHTZp5uJ + W0u2L3lFSXEq13VrBZVapV7iWf4lN3qKR2jaaq3DGVdNkBj7RNM2eTmanIjFY+mZbFJTolEa/vKWmaov + xKlF0Nu8wbYxm25sLTB7FbTbvQ+5tPbtFos7ETbwp4yhp875QU2zFhNWGYYqJtOvdZi17hZVo5jMzT0A + yeYTba4UD99VsEvNPqA/Bj1PaLV/0yvqBT7Sk+a3/tVK60+DOspx9YLeSNqg9OxgNu03G+YKjCE37xdR + hTxWJrFt5p1lOdZTiahXNh+nKX/ZrfX+zR/yfkEJm1BTi07ypjfFYPAm3MWtzzK1Yp2juVW8pPmt5vDL + GNWCtjOp+ojZi81vr/Zo/wCT8VWcweANo6YnLxYXEp0cTcypRyMelcWEpUsJtNfIQ6fLmdOvAgAHAmt9 + f7NH/J+A7xq2DWMU3F/wxyFovHHjkJkO0uIDeZC9pcDwuJrfX+zR+v8ABO8f/JUgFuPCtUwbiU2yW8p9 + 43rPhU9MpiVMi0YZKAsoFuYMssjKq5HIRKZx5lFLMbzW+v8AZo/X+FLG1jFpBWy8a3me0QYi0XgXl8jf + xAA8LeNvbx1nr/Zo/X+CfgKS+qWF7Qm/EqoEsV8HbFbynWZmsZVrEGwjVLLeUquQnUNKtYqeItY7eUp1 + 2dgDNb6/2aP1+N/BX8TP+J9x6jFvN4EX7w0R7RtOGhS4tEp4cQ0gVxhoqYKPFrwUQDcTW+v9mj/k8ALz + b+JtmKiytrdo2Aml1W8bWlSxqYxvKLLFyLWmoPnt+OB/LW+v9mk/k8LE9oBLW5MNUAHGVESo17zTKiiy + TUeXUAxuwlH1TYy8xmJ8S6r6jP8AqFH03iuHF1h+/wANb6/2aT+TwWFgO8Zy8SndOZsofaUkCcCaqnk6 + mG+MX/GLwFjLeDtiuUu2pe5h0y3xlFn0dXA9jNRe4Ih8dZ6/2aP+TxxhicCNiO8vK5suU3BPUbn8NUP8 + RtNDaPTKteaxxUdVWKyt5Y/146z1/s0f8n4gczV+mDkAxuUtF/Ei/Bh0D7l6Zlbqw22TNJoLearMVT0w + m/jrPX+zSfyfgtKBSJqu0p8rFUmVqYXkQfjmoMtTvmZVey3WafVsXwqRgPbxrafdN7zofudD9zofudD9 + zofudD9zofudD9zofudD9zofuUdNtte/4ZH5mTfMJJ7wEjtMm+Zye/416zFrTda1pm3zM2+ZkZuP8zNv + mZt8zNvmZt8zNvmZt8zNvmZt8zNvmZt8zNvmZt8zNvmZt8zNvmZt8zNvmB2+Zm3zM2+Zm3zM2+Zm3zM2 + +Zm3zNNUJOJ8agu5ENMiKpbtMDMTMTMDMTMTMTMTMTMTMTMTLGFSO8KkTEzBpiYEJloPBKWYvOm94lHK + bJmz8x6ZWaX1+LtjUJl1xOMpNjMhczOxi1FAi1BAwubTIA3mSmGxteMRaNUEzX2gPN4XvKh7WhYR2Fpd + bWg+otRe0Ld4PCk1lMy4iMEteOwK8RO3P/2VRzNN6/Gtw5/rj9GlHn8XoI/edJTnSU50dOdHTnSU50lO + dJTnSU50lOdJTnSU50lOdJTnR050dOdHTnR050dOdHTnR050dOdHTnSU50yTp0nTpOnSdOk6dJ06RECd + v016hpjISpqrIGWJrRbzRdWjG0fUohsZU1g/0RNatvNKddavp8CwUXMDBhcRmxF5131E1QKZmPqzcYyr + W2xedb9TrfgTT1mq9/6GrNljgHlZTZvSJ/3ReammRUzhrAd0m6D2SaOmb5GVdVttjaVtTuLaUtVguNpq + HtTgASmQ3czzKmJE9hKzuoGAlWpUK+YSi7qPKJQqVGPmH9CuQEN4TcXM45iesSuHI8krCqB54KlRF4lD + LDzSsK2XlgD1H4mNeVkLJGPM5KXvD2EqJVJ8plZKoXzmUFqEeSIlbLk/0NTTeoLLE04wxeVtLYf4xKen + qZAkSotfLyxqNd+GnTVSLTTpVU+btCLiUqApcjwrUjU4lTTEN5YdLYEidPVY8iCVkrNx7TS0jTWzfrZs + RczfS2U6mn8xa6MbCM4UXlKsKnaXlSqKfJh1KAXi6hGHeFgBeLqUMXUo0VgwuIlZXbERq6q+Hhup8wap + L4zeT5lSstPvC4HeU9Qrxqqp3nVU/mdVT+YKqEZXm8nzOpp/MSor+n8a74rNNgVMdlNTiUttxdRKyqpx + UypSFJbylQVlyvNQ+bhBGGLHiEcWlarjSCe8ZMcTPeLdaJligDgxU3X8009xVKzUBabWAip/xNOFqGxE + 1SEN3lYjt3MJTiwmVM0ovY2lBd2mY1I0qJBlIecSkym+U0XvHpvyzzSklOfGr6DNNT3LgyqgWqoWDTWY + lTGp7dULNTRWmLiafTqQHldAtUWlQ8zJmYD3mqQBL+8c+WZnG0dSKHMZLIDKlJiVdZQ/nM1vrgP/AOtN + H6zNShD8+8rKafA7Rbg4oYadXGwMcNTlFnXygyrubZzMQ+YWmP8AslDitNQmbjmKLCw8atPcGM6MDsZ0 + n+6JpypvlKmmzfK8Oky7mDSW7NKunzYNeHSl/WYNJjyhlSiXTEmdM1rFp0S+xmyzLixnRD5lShn7ylpt + s5Q6O/JM6T/dF0eJuDH0uTZExtOXPmMOjS3ENBiALxNKi8yrpxUi0fLi3MXTopuBKtPMcGUtNg2RMeiH + OR/GrWFOdQtrwalYNUpg1SkwatY2qANrRtUFiPmLiPUwg1IIvBqVMGqBNp1YnVLG1SgzqhOpFrwakEXt + KdcObRalyR8Tqlh1dvaHVATqBxOqWDUAxWDC4/OtSLkWg0xta86YxdMROma4MGnbvG0rFrxtMTEplLCV + aZedOcbTpiIumYGdIYNMRedKZ0xtadM1odM3YRNOym8FEryINKYdK17xtMxh07EAQaQ+5g09iYosLfm1 + QL3m+gGU30teDUIYupQmdQnbwasq94a6DvOoS14NQkWsrdorhu0FZSbXgcHgRqqrwYaygXm+tsotZSLw + tYXm8t7QV0m+k6hBwYj5C4j1AnqnUJN9INQk6hIGB7fhWpljxOnYrabDWMWiwvE07g3nTNlFJ7GVaTMx + jUWI7TYfG0WlUUWlOkw9oi1E9psNEp4sTKtJmbibDFcYaTlcZTosFIMqKSlhFom86du8OncmHTsTeUVZ + RYzUU9wcTpmsRF07AxNO+XM6d7cSmpUm/wCBqqDabyQOCLiFgBeCqpm4s3k+YaywG4vHqKnqm6tsoNQh + m8h94KyHi8zF8Ya6KbTfT5hr0/mLVVuRCwUXMFdDBXQ8TeS9oayjvFNxcRnVe8V1YXE3FtlFqq3YwG/b + 8WRi/ENIntFDKhFpzjjaIpU3tCTa2M2mB7TZfmUrgWM1NI1O02mxxg07WMFF1iUXBBtMXyzlSg5NxDQa + NQcr2iUSFsZVUsthKVB1aJRKuTDScm8dcmAl+bSvTLEESnTamCLREOONpRpOplIYrb/w1Q3c3M3l+TN5 + fuby/c3l+5vL9zeX7m8v3N5fuby/Jm8v3N5fuby/c3l+5vL9zeX7m8v3N4fc3h9zeH3MskLKTN1/mCo9 + +8KEH3lYstiDFDtTyB5lLMti5ip5QbxU78wJdbgmGo/zN1/mbj/PhW9Tf1Kf8beANjePXX2lYh1AvLDa + wvKH+NuTErqRabyAkRaq/wDuN38B4VvU39Sn/G02DNg3tG0xUXvFo3F7zY5teHTke82DYGbByxvNg2vF + S/vGpYtjDxx4cbjXhbTzLTy+nl9PL6eX08vp5fTy+nl9PL6eX08vp5fTy+nl9PL6eX08vQjYbJwi1Fxs + ZuLkDBXUqbynUUBZnZg141VGXvN3yqBN0buV4lRbEMZQsGyimzXhPPhV9Tf1Kf8AG3iaENDGVKOE2/Nj + Ng3tNnmLSvGFj4L28K3qb+pT/jaYNMGHNpuuRxMqg5tGeoeDAzGZVPiA1L9plU+IVdje0wPi/FQ3Ewp/ + c20+5tp9zaT7m0n3NpPubafc20+5tJ9zbT7m2nwZtp8GbdP7m0nwZtp8GbSfBm2n3NpPgzbT4MbEU8VB + gJta0ZiUxtEVlHaFyfaEk+0RXU3tGLM17RWI9pm172gZh7QP8iYN8eB4HEBa/HeV/TKPCS5moPlsJRPk + vFZs5XY2tKBOMLHvKzHiUPe8udyVdy/HaURifMe8BB7Su3YRahyMuT3lbzWlHJu8KNl5pWOPlEoVLcRa + jgmVXawlG+RJlyakuBx+JF4Kag3jLkLQKALTJL2tKzKovKQB5tCyD2lY3IWCoqHGf47RwMbmJiwuIxS8 + asqACUyje0FUIcBGN2HxDXCNa0Lq6mJVyNlE3hT8om4jeaBw/BECAC0AAlgYEA4hoqYKYvf9DXtxBQYS + rTL8SkrBcTDQYRg2Sm0NAubmHTgraMptisQMvENIk3lakX7SlRKNzDR8/ljAlxaPQvdotMBcYlPF+I2m + yN4tIhLCU0akf1f/xAAvEQACAgEDAgYCAgIDAAMAAAAAAQIRAxITIRAxBBQgIjJBMFFAYSNSBTNCUGJx + /9oACAECAQE/ARK+xod0OLj36xg5div5mO9RGnK/sdklcOTD8BTl/qRk33RmXupGxIjByJYpR5I4ZMhi + vuJJuhYY97NiL5TJRSfA8UUuRYYy7MjG3RLw6NiJt3KjYWk2H+zHBN0yGJNcjjBIxxUu5PFFcCwpd/RB + 6WLvycUP4Mw32IJr7JKX7IP/ACciXuuyPGoi7xuyOWLJxtUjS4y6Rt9ycbyUh39oVr6MUXqGJ9hQufIx + 8xMFfEj7UyTqPJgb7Ex/foxq5ck8ul8EM2pk2lEhji1dmNRh9ntJqMGLLBdkQy13JZlpqKMNJ2xZU71E + ppyVEsyiyGRSNS3bHKPPJqjw7NVZLNcf2PIkkOeqVmXLXY1rSYGlyzXF/Za+2Qnp9qMuSpcGpVd/nhHU + 6MuHTyiXi9MnFnnOdKMOLVyycdLr+VDE5Hl5EfD/AOwsOmVo7nlsXfSeXxf6i4Hi1Stk8Dv2nl5Hl5Es + Moq/w1+Xw/x/Jn+HqeZI3/6Hm/RrZii+76pWOH6IQ1CjbolHSzQ6FjtWbRJUeH+P5M/x9OSduvTjnqVd + U6JZLIzojMnLUKaqhZK4Nxj5PD/H8mf4+iXCFh1q4jWl16IS0ux/vrRT6UUV0o8P8fyZ/j6Mr4ojWPGN + 276YoKceTLHTKl0j8eke5KiFULhuzJRxVEHSpjlyTdo8P8fyZ/j6Mj5JZnKOnojFUYWTlqlZVuiqVdb/ + AAeH+P5M/wAfRmj9iRRRBuXtbFjhVEMOlkl0irZLGkrIQtCjyShRtIhCzR7qJQUVZ4f4/kz/AB9FXwSx + OPY1GohBydIx48kF/kIoyeFmo6l0Rr/YsjRq+xysUubFNo1/ZrbVHhvj+TP8ek5OJHP+zeiPLJ8GLw+4 + rM+HaP8Ai37JNHhlv5PeZoYo4b0mR7fh/wD99O6hTT9Phvj+TP8AHpa+x19HfsbenuY5zxqqM05SfuP+ + IfDR4T252jxzrAeM8Ym1GHZGpdVFvsS8FmfuocXHiRHU+xF2uvhvj+TP8emQUHLghFRM0nZuSX2Slq7n + g/EbFyMPjoQy7kjxXjvNrRDsjTHrFanR7fDxF4h1ZmhHxWPUjwtU0Y+vhvj+TP8ADrfSbuQo326YeXQ8 + UhLSq9GD5o8ZZjyJxo8NBwjKTJQlH3GLr4f4/kz/AA9LPD9yapmN0x+lOjzkNFTMS8O1rM3jor2wMuTd + 4RCOnr4f4/kz/D0TyM1Hh37jN8jUzDNvh+rbk+T31pIx5pmXDFR1QITfZ9cebQqPMf0eYPMHmDzB5g8w + eYPMHmDzBPNqVeio/oqIqXY4fc0x/Rwu3pxY1VmhGlGiJpRoj+jSjSjSjQjQjQjSjSjQjQjQjQjQjQjS + jQjQjJFKLLLZb6W+sX1i6hbI5U3RKaj3NaNa7mtDyRRriuTWjWhZExTTNaZrRrRrQskX2FNMU0zcia0P + JFFmX4vo2aiyyxMh106sdFSUlqM0XI0OkaLTJYpWSxSHB0jRJxo0TRFNWRTsjjaNuX2NcChRjT5sjF/Z + CLsSldjX7JY5dyMbpsyfB9H3F0QyJDrD4r+Pk+L/AAQ6wyOJvyN+RvyN+RvyN+RvyN+RvyN+RvyN+Rvy + N+RvyN+RvyN+RvyN+RvyN+Q80nwzSaUaUaUaUaUaUJV+HHDWyOH3UyWDngeGSVkcUmrIeH/2JeHf0Txu + HfouexTXcjy6PL/2PC1LSiOG+5CGrg2P7PL/ANmSCh/Awq2Qf7JJdz/wzDP26RY77SNFf+jxEvpEMGpW + Y8Oh2Tw6nZij7h+6Vo4crF3ZBJvkhGKfDMkY/ZkjFdv4GNe4ivo5JfFmPTfuMei/aOMW+TJV8GNwrkuM + UXiMcqZHsX7qP2RlBfIg4N8GRxT9xKWOuF/AwyUeWSyvVcTHmb+TJZY0QeOuSOTHEWaFmSUGuOk8mvpj + npIZrXJvX3N2C6QljjyZpqT4/GlfBtyujakPHJcsUW3RKDj0hDV2NmV0PFJCVuh4pIeKSKruODSsWNuN + 9NDNmVWaJfojjchRbJYpIUHLsbMzZmaGuDQzakOLj39OJWzLqTIpqJPVHuY26tkZubJ5GnRijpjYuUj+ + zHC56hO76OnkPl7WOWiNIy/GzFclyOX0ZbguGYWmjHZ7hKWs+zJLTJCmp5FRL4smnxR4ghJdkZV7uOsP + kZZaeSEm4Ox5bXIpaoWYZuTMmR3RjdwdkOxSSswS91EfkaebF/2CfJGapxZl/wCtHh/iUZ/iYZe0xNSG + l3YpQsi1ImovlkNOpaR9mX/9jJ/1mKVRZd9YS0uzfZvf0Sy2qohl0qhZq+jev6I5dKoWauyN6/kQmou0 + bq70b7NxJ2keY/ojk0ksupULPX0b/wDQ89/RHNSqhZdPZCzyFNL6Hlk+CGVxHk5tDySZCWklm1KiORxV + emENRtvsbTNlo2mbLI4W1ZHC2SjXBGNm0PEzaNlmyxYWzaZtPsbQ8ekcaNliwmyzaZsseJoar1456TdR + uoeVM3TdQsqSojlolKyEtPc3DdseVM3jdRvCyo3TdRLKpDnfc3hZULKkLIjeHktDd+uMWzQ7o22bUkPH + JG3LooNixs2pG2x43EaocH3NLQot9hQb4Nt3Q4NFG2zbkbbNtjVEYt9jakbcjbZtMa9EJJIWVXZuI3Ex + 5FRuqukJJCmkbisc4tksif2NxZuIlK0Y5pLk3EnYppOyU03ZF82Oao3UbiN1JE2pcmKWk3UPJwSyxo3U + Sd+hQfc0M0tcFWaGaWbcjQxqiMW+xod0PHI22bcivs25GiRtyY4tCV8G3JGho233FBsqhRb7Di13NLuh + wa9ScdIpIbTlZ92SdoXH2biNcSVMxT0mtXZuJmtMlkXYuNaSOSK4FkQsislkt8EXTJ5E0OaaFkVUJ6Uz + 6MckiUlJjlzdk5qSJu3/APDQ+KNtm2zbZts22bbNtm2zbZts22bbNtm2zbZts22bbNtlVKmaI/olFJcC + y2jA9dpkpqOXS+xmmlHVAlmd9h5argeZqVUKKaNEf0aI/rpD6/iT+S6SVqiGCX2YbhJuht7uujN/kjwi + WCSdmzOSTHil3IdvRD6/iT+SPMKzzC7kfFKTqh56dUb/ABdC8Sn9G+rao8wtOqjzKuiWRr6I5bjqFzz0 + /wDCoW6f5SspWUrKVlKylZSspWUrKVlKylZSspWUrKVlKyi1a/cSxS1cG3LTQ8EoyVE8c7kaLi40RxTh + Lsbb1SZtPaqiWOV2kZ7cdKJxuNC4VdMf1/EyfJdV4j+heIsx5tbNz2ajzCqzf4seeiL1K/Rj+v4mT5I1 + xQpxfFm1BO2acX7FDGuw4RihRx97Kx13NOP9inCCqzciX0j8eBSkbkjckbkjcka5GuRuSNyRrka5G5I3 + JG5I3JG5I1yNyRuSFblbY4c2Rx1PWTakxYqFjr7J6ZRqyONRjVjx39m1aqzZ/seL+yM6VdEUqMfcn8jg + x97ZPvQ0tJjomlZRjRlO0SGn7Ju+y6Yl3NKo4IcWZKNSrgx8mRDjGiCVk+xXtK9KZqfYTov7KkY7ZOxK + T+yHHJpcuRaiN2SsSdCg5ckrRov3EewsepWaXFjhS5NvVyaWuDTpLbL6ORraNf4F/ZuIhJR5JNN2LIiL + VNCyaVRuO7E13Y2mKaqjHPSTyKS4FP28kfiyOT6HJtjlaFloc+SUlNfi/8QARhAAAQMCAgcEBgcHAwQC + AwAAAQACEQMSITEQIjIzQVGREyBhcQQjQoGhsTBAUnKCkuFQYnN0orLBNENgFCRT8IPRY3Dx/9oACAEB + AAY/Av8Agxstw5oB/HknQYhXOeDjHf3g6JzXZj9sRzCIG0MQoO0cSsXt6raZ1WraUHtEGeCcHAHVWw3o + thvTRrNB9y2G9EXtbBHL6PBrj7lBwKwWRRAwjmhOIPJZFZHRuyt0VuitdhA0lxcIGKwUtYSFuiocIOgh + piEC5wM9y4MkZ5q1mJK3fxC2Pii4vbho3buiwZHmgH8dBcXNwHfPrC1w5KmX1HGnzKuAhnDxRaWxPJZu + UMnFq94RLzwTmMOJW23qttvVbbeqLnuBwTqU65yVrVi9y9W/HxUHMKajrfALB7pWtiDxXaVcuAWqIPgu + y9qV4NCJOZT7gTPJFrQ4HxQua4zyVjWuQLgTPJFrWuB8dJ9V8UPVf1Ig5HQ7tYmUS7KESAAnu4XQFUFs + WGPNHwCZd2d0KaQbB5KKxZI5r/a6r/a6p3ZxZwhMkjDBQMsSgWMvX+mPxUOp2N8kDyKDAwiUXkSqbndE + PvBVPunv6xhpCc3tGzwTWMeW4ZqC9z/FyuFZ7PALeOfLfaXv0br+pbr+pAossn3rdf1K6IwhVfcmhriB + HBEuJOPFAcyE9zc0GueSDzQ+8mgHhCcXOz5J9Xlqhdk3Jueil5ovdkEHBpxVzASE6ARbnKaRxGOnYC2B + pZ2nZXRx0Fr3s8iVUsi2/CE48S4lPLs5UeyMyuTQpJpE+Stb2RPknODACMcEwOyJWwEGNyWDbkKZpvDl + UJ5JhfkDiopkXeSl+XlKoCnmHY4IfeCqfd+gEsEpr+3tnhaFUD3XFryJhOYypYA0HKUO0qX6p4QvfoZc + 5sxxW0zRrloPitpnVVI5o35OQNQsKIoRaDwTfcqiYvepYYQptIE8lDR4AKazi5xzV9OSBmFT8163ZVrX + Wow+QeCqADWGap+ScKgmAtj4pzqeBAnNNJZmOa2Pii0ZZoPdrOUPdClrWkHinDk4qvTOUkhB32gqdMbT + uCJK2v6VT7N2sDy8FU8tHvT3cA1U208TxHNB5brfJClkM/PRe7adoo1BxMFN+8FU+732D3p55BNbMFqN + paJxV0tuylNtIOqV71qtJ8lu3/lW7f0TVNrrSImEWnPgYW7f0Ra51q3h6K2feu1GQIUZtcFeCSfFNZxm + dBqnjkqbZ1Gn4pvYnzxhetMkNxVLzR8x80WzE8UReXea9J8x8lT8k/yVCJzVX7pTfuqpcDnxQ+6jc47K + Ac1xnkFhIEnPzVT75TqwJkk/NBo9kKn94Ik8Fk7oqYaHSDy8FV8tAnjinvY0vJyhXCm51Q5w1AupmzlC + g3zwNpTL8vFMp09niVcMwR80wVQ0NmZQDHgm4Kp93vuNR2uU5tN0k6W32yMMVg5gXZtMmeCqdo4NyW9a + t41b0LetW9anAVBksMCt67qoc9xHno1HEeS3juqxzQuyVtKcBhgvFQ4XKHYN5BUy7IFODHgnBZu6ppeT + bxRhw6IFuyE4vnELJ/RPaA6SITWkOwCyf0Qc2YiMUXPmI4LJ3RZPTr3xLicU+x7rZOR0MJykJ4FQTGht + 74dGOCLKcmULtniiGB2WGC9a3HmFk/osndFk/onuGRKY5xgJzWPBOGhl7taMU5rDJOH10ueYARs4c9Do + 4CUGhQMjkg+MDo1zmr6eX7apjmUHMOIWGDuIR5p4o6rjxVvpBuPNAclLuiL35qo33/tiHux5BTTcCqfm + iZsot2nL0pvo1V7KlMyyeIXYWtY5mBwxlb34LffBBph84RGaoP8AS6jn16pxbyCZVpO7T0d3HiFU8laB + c7zTtW0j9oksiZAx81vfRuhW99G/KVvfRuhW99G6OQqVrXNf7TcpV1MwVTq30mN8iuwpv9HIxxMp1WnV + ouLhGMp1Z1Wi1zs4lBzn0KgHsuBVzHUKQ+y2VTrNrUSWGYMqmalWg2zlK/6V9T0e2AJg8FU9I7Sm8ZRC + LnYkrtqbqTO04PByW99G6Fb30boVvfRuhW99G6Fb30boVvfRuhVVtS26nULMPD9lfib8x3TTrMDmHgVd + 2zux+xGPVBlMQxuAH0LmVAHNOBBQqa9v2JwWHf8ATf5h/wBLkVsu6aNbALmfFbLVsBEDL6t+JvzH1n0z + +Yf9FDcSvWGfJarQNOIWrhptbn37gNUaQ+NU8dADc1B0YCfoPxN/u+s+l/zD/n9DaPeVDfoMEbuPeDWo + Cg2WjVP7yvpYs+S1m3BODRqZ4f8A8UuzQc465waIyTWlje0OJI0Mc5ur5ouNSn5ShOTcUyBquxVSi6my + 0cQFQIpsJPMLVESJ0fib/d9Z9L/mH/P6Hx4/R2u7ttPMqixhJtOs4J5BwlS/tLv3VIaYujaxWDA3xCqG + ncHNGfFEua50nJ61G2+9Gs7yb4rtaImmeA4KrVIngvRqgEWmIVRgdqqhZxCLnmTo/E35j6z6b/MP+gaP + FGkcD9HcMx3cCQiGmJz0hjjgNGoYK1nOPmdGJJ81qucPIqSZPe/E35j6z6Z/MP8An9B5BBzNs4RzRY4l + rxwlNecz9CURy+q/ib8x9Z9M/mH/AD+gc7mmvAB7PmiZlzj1TW8h3GVW8FixS3p3D3MFdYYCujVUNzUQ + ZGi6MAro1eegNHFGR4LBXFpjTgJWLSF+JvzH1n0z+Yf8/oAPBPPirzkzHutoti6obcU5lFxc1uEnmqj+ + GWk90FkYeKdabbtowmwbRwH2liXGBMAJk3tgE5+KemwC+eEZlChBwxv4SoeMUXuEPBG3hCqWPLqZ1iIy + QjimMdje7EXSvSAaYAadXBWB9vHKVSN79ecHCFrPcfevxN/uH1n0z+Yf8/oIcjYJBQbx4937qxTPHHuO + 7kl1tuKDPbeJ1cZRpE3PO0eSfTp4ahM8yuyu7R5GafWqiDKFrnuPjwTmvizxqLEaqeWkNDoE5ldjSOs3 + n7SN8m1UmAAMBwT2Tq3K5uBQcX7PPR+Jvz+s+mfx3/Pv+5T36iazr3Ce8bTHcxJPdwUkyUCMwsdGGj8T + fmPrPpf8d/z77Tpw7sza5G33lE3dlTHVS1xe3iHZ+5XDJW0tj7RWcx9V/E35j6z6X/MP+f0HioBhWvGH + 2lhpI4rBSWmAZKgZORa/aaUaI2QTPksdUBCGCw8804NynTgCUbobHNNxBB5aLnvzytx0BvNFhx0YgDzK + cQ5jozg6JpPDm8ZwhNcYIdyQRbCxcw+AK/E35j6z6X/MP+f0Ej3hS3RhqnwWrVd71jV+CDpM6bqe79pv + JU3806s72sVc7Y4BWUsXfa7lutj9kpw/eHRU5zhN27p4BWYxltRPREBgEHmtZwFY5cYXZ+kOc79+MlqO + uHkmOcNYU4jgU9tMg+rI8UG2XHmeCqNlmbYA81SAwxdgnYEzDTj4pzjbOHuVMgDGcQM8V+Jv931n0v8A + jv8An9DLFjqnvbdvgtiPFNxyyCZSGrhreCtY4vYpu1lGflpIGE5oBszhcU9/aTPs2rUGuePJAdoIwT45 + lBwrEHiA1S41fLgsELZgBVCZviFHAnEp7qclzuPJGo6sLDwVxlzuA4Jz7rnu4KnwcMwvxN/u+s+lfx3/ + AD0FFSGrWae5gJUuVtObvBYE4eC8PJbQThc66MFfDTMcV61jj8l6vVPOYUu1itQlNvKMcPqn4m/3fWfS + /wCO/QU7yUhYhYYLM6MAvHgoJxfiT4KANDyMlcEfAIHmnXNB1zmmtaInPFNb7088h9V/E35/WfS/479J + UtUdnPkthrfMrWdefBYHQIxWOzsqXOACtp7PPQU5qZ4YKp98p3gAneSwzcVLm9O/4cVi3qso8lqS5bDl + iCPcsD3/AMTf7vrPpn8w/SUScGhSLmBWF8t481DFJzXILFSTIy96djllPFTI5Hw0ORaqo5PKrffVX3Ko + fFNc/MZDQY75jZ4dzNcneCLXZjvfib/d9Z9L/jv0FFXHYGyP8qBg0ZlQAoZtKTiUEADguHRDVHDFQ0GJ + nHQ4JwiYKq4xJ4qt97/Cq+aNSrny5LU1QttScT3pYwlvwUGwLJp8lBkHkdJ1pI4Km/Ke9+Jvz+s+l/x3 + 6CneSFvJOac5WGA0jqo0Ydyo4+auqNBLscQpxaTwaUX4l3MqTl9AXVd0OH2lZQwb4KX3Y83K4F1kxJxC + h4h4/wDcEWP2vmnkZwn9rPaYFhQ8+9+Jv931n0z+Yf3OXdPfe3wVMcNFoy+ggccEykzigTBquXuValE3 + ZeCp1mKnWHD5FQnMPBDnah3fxN/u+s+mfzD/AKGdNrsZ7gKbzbkVgI+hpfeVGfsoeSYfciBkE4cpUO+y + EFLmglREojke7+Jv931n03+Yf9CNJ7gPL6MPGbTKZVp8MQhbmEabc+BVpablaciZd/8ASbRGJmSFqUjH + N2CNzhDT7PHQ8jn3fxN/u+s+mfzD/pH6BocOf0ha6Sz/ANxVzHZ8WrVq/Ba7p8kWUdZ/wajUpxd9pwUV + KzvIYBNCtG0fh3vxN/u+s+mfzD+/hlzWOJ8VsrVMjx0PRWrmtdxK2fippTPL6PH3K5xdd+6p7Q2rac73 + 4KXx5LkV6x8qKfVePe/E3+76z6Z/MP747p7zvoZUuxcPgtUhB1ocIxaVIAp+DVtppLsHYBZgotqCHjBf + aCw7pJyBb8wt/wD0Fb8/kK35/IVvz+Qrfn8hW/P5Ct+fyFb8/kK35/IVvz+Qrfn8hW/P5Ct+fyFb8/kK + 35/IVvz+Qrfn8hW/P5Ct+fyFb8/kK35/IVvz+Qrf/wBBW/P5CvSXsMtdWcR39UrP4LPRn8FjidGej9Fn + 9HqOzU3FzfFYrAR5rEzgruLHypbnxTHNjWGKPJef7YPBgzUdmPemv9EaJbm0YSp9Lp+rbldxW6Z0W7at + 03oiAxsFS1gBWvTa7zUdm1bpvRbpvRbpvRbpq3TVum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9F + um9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fum9Fumrd + N6I+ratgLYC2AtgLYC2AtgLYC2AtgLYC2AtgLdhamqUQcx3G+P7PP1Axx7jP2ee5gQViVhoxMdzAg9z3 + dxiuKuhsclMQeWiezdCjs3DzVkcJlOERGXim3e1gtZX3YFSDkh/7CuCO10UWOHiQolQShjnkgOzfJQc4 + Fs80WhjnEclc5hHgoDHf/SjhEyrQVFrz5BRa4eYQYrPCZWs4BOlwEeOauBkLBj+iuajhhdasHArYqdEA + WuE+CLJxCaMDKhxxR9W+Ag5YaDpmCfJPgY/JEkklNguUB2s1Di0LANT3cQtpiJDmYrEsx5afd3GIECYM + qZ9ye/g44IqnI1YPCVcNm3yVe90Y4wqQGrhMhU3jMuWP2U0ezcVXyAgZouml5FGCzyCOu4STgBKg1H5Z + EJoYG9jOML0ieaohzJwwKDtkuGATS+kcfgqjyX2zEhbwjjKJLnASoHGmqTOzLS0jFN9adYxkp7U4Hkq1 + 1MuPNC8XFzcHKm8vtIbmU4dq3w1U4eaoDhanWRMlUy462MBNcT6y1SSMMiEwPIkJ7HMGWCpXUw0nMIz9 + nBV4a4l0cE20kWlOqnAHIaDpmJT7cuKgXSmjWldoRitmByQJYSecp8oy13uTrmmEbR10+7uM0bAlPZ/t + 5gohuawxgQAm63DEKoAMHRimuGyGwmY7JlBwcWu8EACZGMp065PNPdY0vOEclDYviJTLIwbjKuqW7MYL + adZM2ow9zQ7MJtkAMyTXmmCR4poMM5oTTBbylOa9lonKVUuAtOSdLQGRaEDcXBuQV9WAG5BODWiCZlVb + Q2DzQa0C6ITGsDSAOKdqsx8Vsgv5KXOtfwjgiHhvu4q6NcTAVMnaaIRDrWM+aFhlvI8EagIuyjwQdY2R + 4qXgXQiWgk8pUHaKAfidB0kxKe60q6mwt8Ub2Eu5prOCkOgRCaZLk4x7luU+aZ1kGlhx0+7uM/Z5+oe7 + uW8v2efqDo7lzFrMM+C3b1u3rdvW7et29bt63b1u3rdvW7et29bt63b1u3rdvW7et29bt63b1u3rdvW7 + et29bt63b1u3rdvW7et29bt63b1u3rdvW7et29bt63b1u3rdvW7et29bt63b1u3rdvUWOWwVslbJWyVs + lbJWwVsFbBWwVsFbBWwVsFQwW/8AFZDHEeWi6myQh2jYnvyGKHiD9QDW5lbv4jvQASVu39P2B93BB7Rt + fNNahfOC9rquPVXsOSdcSIW05bTkG8kLsI5LacsHOlFp4dwhi12xpp+ejVLT5Jzo1giXzMqhZOLkdDLm + slbDFsM6Lds6KWhgKJJ/YBspSCi2qxotxWBlepcQ77xW+/qKtqvulvNP93zVRE09pZn8qzP5VmfyrM/l + 0VPPuXcXIMHDHSyOGKefBH7qeBiU4OEGV6N95HQCG4LY+Kf2giU9rcyFsfFbHxRBz+vwfZwQfT9vB0K2 + nSc4+AwTS4QTwRayjc3nCmpTt1Sn+75rBxC3jeq3jVLcQtdwHmt41O7OoLvArHEp9wBwWw3othvRQFJa + 0lbDeiK7QwJ4oUmGGc1ffIhbxVXDK5ejfeR0NBnAL2kbOCLjkF7XRe10TnDIn6/ZSdbcr6la5gMkQt1V + /Kg4ZFOYGvJbyCbqvGqcx5J/u+ehr74nwW9+CayZhN1rYW9PRN1pnQ4B1sLeq9z7k5rXRK3q3uhpe2VL + GCVBW7aqrWiBK9G+8inAkiFtuW2UQDMpzDxW2VtlBwcTj9fLvshHxI0Ma7MBVnHJ0QmfdP8AhP8Ad89A + aA2Atlqa85lUoiHHFYEdFbUABby0EgTK2Ag5wglOa1oIC2AtgaA2mXe5a7i5x0XUXOBHCc08nHFejfeR + RLDBW38Ft/BP7QzBT3NzC2vgtr4KKhn6/jtHFMb71Dmyt18UCKTcf30HPaGwDkZT/d80TdELeHot4eia + yck3WiEEX3QrJnQLskS12QyRJ7jX4CRJKFNmzzT/ACTLntmE5no1Rlp1kx1R7YaZwR0h4eE4OIMqp5fs + L2Oiuf8ADS1nZ3Rxlbr+pWxa1ENAPmtliyasmrZYsmrZYrnRP0ABOA4K8iURYcdF4ErdfFENbbPjptAl + bsdVbk3/AIzZdCBm4IPD4W8HRbwdFvB0TZdM6A05Jz8cPHute4mSj2QlowxR7fDyKHYDqVsjqsc0GnJa + hJdwWQXFbPxWuNAc+ZKc1uQVrsoUtmTp3a3a9cCHIdg0n3rdlbtAeKc6XYBYCVjTdHkjZN0Ldu6LEEea + ntB0W8HRbwdFvB0W8HRXTcEbBktn4prHiJW2Oi3g6KQ4H6JrvFOZ2jcVax8AeCN7tUJ7+IW38Ew1TMLM + dFczIq2oceSkD+lY4fhTrSJjkg0ZleDQi7m4lPbLw3mAIRLqzzHIBOLuaqJ1Q+QVBnjKJp5oHtXt8CAq + bA5xk8ck/wByf2jZhASAiYxPFPcfJW1SwxwKljGEeSIblmg1jGyt0zqhcNZHs6bS1SaIWy1XumQUWnIp + pEkQg9rcFBpulF7mYASg5oI81Y6obYWpX6gLsn1YwnAJz+3Jj90INe6Qqiq+5ClwtlU3DMFNd/1GY+yr + e04xkjoD3CXFEAtKDmbJ4d5geG3p1rADwhWsxJVoz4r1myr6IxHDQHOHq/mi7ki52ZTEPu6O2dmclU8k + A54BW9cPIrVrO/Mj6wY8ynBhwPFBrcgmlxgLeD3LGs78y1qpPHEpzWPBKqKmm+SNL0ci/wCS18ZxlM96 + PkmI2Z8Fu2IksYmnmFU+8U3PNP8AJO7cOwylWMyXaEYotORVzJlSTDp4L1dS8cnKSIIbBVTyVzM0Wudg + VU9yZ9xM80B4JpczC7mngYmFDhBUdn8Uapwbw8U1nHPvU/NHyTT7Th703g3kqiAqOAcMMUxzCHNccQuz + acY4J6Axy5IObkVa/NWszVGk3BvFVFN1zlxZPVf9uHEcZ4r19F0q+lrDxVz85TzWdEQuzoNw5ovucSMg + FbWpuc3mpAdTd5KooqxihGUKf3oRPFuKb70fJU0Q0wea/wBT/SnHt7vC1M8lU+8UHubJlFx4InWbarpL + vNFuU8ltuVMBx1jGKltSFrva4J9QuzTmDittq22qr7kz7ip8dZblblEkRBhN8kwHKUXRlwRc7M96n5or + HNNT9PuT9FND7uin5qogXuF3ivVFvvXrWta1H7RyGj3qp2joDQFbQIwQtDHT4L1kTxhauQVRU/JN8k7z + WTE33o+SpogmJX+oqfmRtrvnxcm+SqfeKY2TE5Kp91AF7mt4wopPVzqxcFq7RQlxMc1t/BQwz7l610uR + FOrBbnCkPuZzhbfwVX3IVPZthUn8nLJ3RZO6Kq5mRcm+SbZtcE7tQ23vlz3tDigG6zeYUuLJ8V/tr/bX + +2m9hbM8F+Fa2UiV/tqGvYB5qXmmSsOyVPzVRTUqFWh/xlbUeauFUz5ygLple9P1ogBXGpj4lYG7yVva + fFEtqYBVL3AStd1MreM6qTi25f7atY9gHmi4bKuaWXeaINRpB8V7HVex1UCo3qiZZJ8US/aB5p8nMIvq + ErUInwxWozV8VBNp5FBowBjJa1vvKhmPkobqhXMMFaxAPEFXUXtB5SnBoGK2WoBwGGhpfbd4lQxzR71q + 4gJrjkCnMAdJ+q5rEz3McdGfcwP/AC4Ijs6jp4xKFRl2cQV/pnfnVNskSc4xTgaZdB2phNAgnhjEpocw + 0/A4yiWwWDPwWFvaT7JzVBhsDs3TxVWSxs7PgnFzBq8ZTRY1O1Da3gMUdR2seWKuYwtHKNNIvo62XgUH + j0dpdxC2HT4ZLCmfcQgG03GMwVW1GyHe2mQylaXeyVIosvVPVm5kmfcm3bVXJCnUm5zswixxmMgeKdaB + 4Kaec2xHFNYaYJaJzhOd2ceTlMk/vWoUuzbsTKfe2TwkIwzMC2Qc1qCAq1zQYGin2obhi5DaF+ITZY1x + uiSFumdAiyKeHxVtjbPIyhk0chmjbqlrZVRoBkNumVsa1l0oU3UmYtnBPdUdABwaM0Wgz9KPNf72XsZI + bWftZplMvFtvPivR6Wdm0qpM2YrMoyyQSYngr41G4SvV6rWGfNUnHZaJJVOzDNDFwlNinIjMnJP1XvnE + CVSJD7zwnJFokOn3K0kaKJay5wVFwDjUnHBFlgbxKhrmkzwpoRyxRguGtcYEz4Jlvq2g4tIyQgTT2VSt + yDCPkvRcJz9yqMscfWSCOCqDm1Frb77Ac1TLRb9qOBTzJwaP8qo7XbH2mhDsm4B1oCj7LIT7nP1cYCeS + /UAmLVYy9z/FCntOO34LtKONPMEcFSqOxhuXMqgKmAcwgyqbfxLUxdOOKvtyE5p2ZPuVM2xdgvSDGqGQ + CqxjDs0CTh2UJttR7h9xPhl3gnF2f028coc8kaDa8yUbXlbx3VTeZWLiVaXG3koc4kKA8gIQ44LF7lIO + KJDjJUnEqXGTom90reO6q4ON3NEtdiUXXGTxUB7oUF5IVl2ryVrXkBQHuAWDzirg43c1dcbuaOOBzU3m + VBeSPNQ10BSCQUTeZK23dUTcZOggEwU2XbOS13Ssyt4/qtp3Vbxy2irLzatt2jUdCmTP/EQHZJ4v1WiZ + CY9j7g7wRuqNtH2VvafVOaTg0ZhXa4dOS7MuicjGaMvPRDXknhEJsnzxTjOI8eGktc6MMFb2hu44KGVZ + M8QmeszT3B51fBXh7/c1BnaOBPNqc1xhjTi5YVBHiouDl2jzrHZGh1/ugoF4wVwgcpUHNEPdbhmjUe+3 + GMF2cyhY4F/EStVwPPFbwg8cESajiByarW4eegNeYBVhqG6eARaKut5JznVGx4Fb2n1V4drAwQoc958m + otvc3lIQpMfLuMpj5Mkxp7S/xyTPWO1stVPBOq3CU77XDFNawTKqAPLnMHBB4nxHEIBrxfGLScUIvkhV + MYsxPfBGYVSi/AnWhvFQLmzgA5HsA7D4oteHWke1CrhogtGab2jjc7FMLzliLuKeahj3qi+mWkAxinWP + p9oOIGSa5po3cyMCiYwGhzDBBEo06Yx4lMdZNTIjgVSlurxVeGux/dhWCrTujAjNNd2opxgnBjr2g5yh + Yy7hmrqtIXRgEataDVdst5BNMyH43Kq9kW22jxVMVIgzmnGo6ez2QiTmVa0A3c0LrnGnhaxU2uJ8U57L + 8s3ZJ49Zd8FtuIGeGSPakubGXJbQt5opo5otaJe49EWvwe12Y5JvYNcB4QqoqA5e1CyEhwCxJYJ1cdpV + CdVs4pkOynVVL7xWsCNDdcXQrrm3kc1VMySfgi9jBacZ4q40mjhtZr1bQPcmVG6ri7Epj7s+QzVNwbhH + Er0gGG3NPfDomEX2N7Q8V61rX+OSNKM+KgMF32pT223XLtPCI5IEBogQFBY04QiCBCspsDGcfFCm1lrR + 4qpTja0OtAuPFXdk27mEC2kwEGVDmNOMqIaBEQvVMazx4pwdrtPByhgAEyr+yZdzTHEA2Imyn0QbUYDB + lAvaC0eyhTawNaE5oydnoJABJ4r1TWs8VL6TC7nkoybyCtqAPHig0sFg9kLtGgDCIV7QJ0XASVc6mwu5 + o+qaCeKbSjLiixrBJESgwNbbx8VjRYmviI4LtIjwTWBlrQgeQjRSAaNT4puqMHXJ7wza4K+JRPipNMdU + GWgAJrH0w63JYtaW8ByVTLXz/wCFOg6wyHNCalMTjmmslpuEhOcHsNvIqo52BbGCDJiURyKlgmfEJpG1 + xEq2MT4rZH5gpePimNx1vgpaCcY2VIbh5oS+mJ5lFpzGm57wycg5AOiTyQ1gAVg4ZotyjirnusxjFCjO + J4oQ9pxtV14OMJrJiU5kzCmQAm6w8VZLea3tL8yYbmm4xgtaowIw5hjxTnjJueg42tHFa72hvNBr6jB7 + 1q1mGOSJ7Zh8kXiq20ZrtA8OBUmq1vgVq1mFWzOltutInyUjWagOatmcEezEwhbrc0L2whdx+hqauu0Z + ymEvcDaGxZKo2ObqNjHBVm0+yi3HmvSfNqpp3qBn9opngo7Eazs7inhuQOhsCcclaWZ8Z4oYekbXvQbJ + 9a6DCoz2nq+FhRxmcdFzc1qvaQBiFUa97S/hgpDxq8wgxxbfmcE94wDsmoljpBesA44cDCaH9qSfGYWD + XEDjcrzstxJXaDFr062O0Gc8lTt7OeGJRDPs4+aoQxtvtKnb/wCQ5eagk+9SXlzpiRwXpA0Hj4WygwjH + xZghj8IVRlLEgSShWpwHe01HtTDahTh6Q1ljdjx0Uuz1b89LXOyCa1xLQ4Sndo467bck3zUdmx2HEK9w + hv7oVUlzsTnGKFpcW/vBU/u/QukZ8ULMGjJNqPBvGYHEqrAddUzlObrm4iSUHgVJHkiYq4+ScKU3u4ng + EHWvLx0TnVGXT4wtwPzFYUrfEOU9mW+MyrPXYYzOKALSYdKPaOqx+6UKsYBOPMoXZICm0MYDMc05/ZG8 + 8yrQ1zuME4Imo3PiMwi7EhMY0Q1uPmUx1kQZzWwdq7NBtpAunNWMFlPkrHi+nyKqWDB2CpBrJcziU6q4 + SSv9P/UmsZTtDTOaxbhwDU8xqu9lPaWTPHlokdEXlrvKUTJxVSRtDRrU9Vuy1EV2h7OXJS5pLOSYxjYa + 1NdyTnc9DCKeu0QJTm1Re12KHqJI4ypf6PJ+8vUzTbyTmkuLzkVruJQhobH/AOjQ12S2Kq3dVbuqt3VW + 7qrd1Vu6q2Kq3dVbFVbFVbFVbFVbFVbNVbFRbFVbFRbFRbFRbFRbNRbNRbNRbNRbNRbNRbNRbNRbNRbN + RbNRbNRbNRbNRbNRbNRbFRbFRbNRWNpvBicVsfFbHxWx8Vc9kDzKy+agsPxUWnqVu/iVcaU+8q4Uo95W + x8SmtNImfEq1zDPmVsH4rtLdXnJUDM+JQaaZP4lw/Mtj4lbHxK3fxK3fxKEM+J0jyKkZlbTltu6rbd1W + 27qtt3Vbbuq23dVtu6rbd1W27qtt3Vbbuq23dVtu6rbd1W27qtt3Vbbuq2ndVtO6rad1W07qtp3VbTuq + 2ndVtO6rad1W07qtt3VbTuq23dVtu6rbd1W27qtt3Vbbuq23dVtu6rEkhfgP+O4e0iE51RuryQa2LE0N + iNHvUWk+SLbHDzQudM/BNuJP7yMdqZ5jBOkQvR454qWOF3JSQ1rRmgRl3BpHkUzz/ZH/AMZ/x3CDknfe + Wux8+C9WHDzTfJe9e/QBVOJTaVQwwIy57R7Piq0mV6PbmVBZTuKcA1lwTbs+4NI8imef7IH8M/47sdrg + rRnCFwamikRACh5aQoYWgIXFsIFwEDirnEyh2Yc/8SqMq4XKWkkjJdpXOtyT7LSHJrScR3BpHkUzz/ZA + /hn/AB9XGkeRTPP9kD+Gf8Jze1saqvrL4avR3F0SeC3rhPANW8f+VW9u6eRanQW2fFbTY8TisI/EnS9z + Gc1JqVAPuqm5j3OBPJAC5sfFdo11gjIhT2sR4INpu2fFQ/B5ytTCO0PAqW1bRyhS/wBJ+CkONnMoubmm + OOZ0jyKgrVd1W0FtBbQW0FtBbQW0FtBbQW0FtBbQW0FtBbQW0FtBbQW0FtBbQW0FtBbQW0FtBbQW0FtB + bQW0FtBbQW0FtBbQW0FLsV+A/MKSxok5qpTNNgNuYXo3mmwdlB3aH70K9ziRzVtpDOfNMptzahUrm0cG + oObc6eHJAQ6ORQtvs8VMaswEde1oWo+0TlC3cfvc1gLGD2Exoe+TwHDRTByUBOVMaR5FSsgsmrJqyasm + rJqyasmrJqyasmrJqyasmrJqyasmrJqyasmrJqyasmrJqyasmrJqyasmrJqyasmrJqyasmrJqyasmrXC + /AfmFc+IGy1OfWDcQmS1gaw8FTc0CAtQC7xXaVLfcgGc022A4Jl9kBQ1waxCwy7iSsLW+RVOwTCNjmhn + ioY9ibBEhWlzWjwUMdLTzUNzhNdUtw0EB1vimgmY0jyKZ5/sj/4z/j6uNI8imef7IH8M/wCO66HZkozU + O7nFUmSYxWJdg7zXtQm55cVXx4ovnABUxqkZJzp42rAPAHmmi5zo8k/WqavOEJ+NWEcP6ru+PIpnn+yB + /DP+O4YzTRhAnHmvWW7MKnfGoPinNdGeCAwjlKbTYYHtFNNE2ub8VFQgM5DigQ1oEjGUKojyVR7gBOSI + wxxLuKcwW48VLLXCIxTruJnvjyKZ5/sgfwz/AIVpmfAIDETzCsMqGn4aHEB0N8ETrYeCuxiYyTccyg7M + HloDXHEpuOag3dFbiCeYTxjqrDohtY5YJz+Dc8FOKmZHgjquwzwQI0jyULKfJbBWwVsFbBWwVsFbBWwV + sFbBWwVsFbBWwVsFbBWwVsFbBWwVsFbBWwVsFbBWwVsFbBWwVsFbBWwVsFbBWwVsFbBWtgEB/wDjPzCq + 2zMDJM2o7TCUbBmnnRUA5lANuJdipaZl/kmjPWJKb5/50Ehr/MKXB5E8EGgntGmcBKo3C04rE+0ZVxwZ + bzVDB2PiqwmNbiUXD2c/FUwMyZUEZ55pmkOdkt7U6fojZUqH3fot8/p+i3z+n6KG1ak+X6LGrU6fot9U + 6fot9U6fot9U6fot9U6fosKtQ/h/Rb5/T9Fvn9P0WFWofd+i3tTp+i31Tp+igVak+X6KDVqdP0W+f0/R + b5/T9Fvn9P0W+f0/Rb5/T9Fvn9P0W+f0/RYVahPl+i3tTp+i31Tp+i31Tp+i31Tp+i31Tp+i31Tp+i31 + Tp+i31Tp+iu7SrHOP0W+qdP0W+qdP0W+qdP0W+qdP0W+qdP0V7ar5iMR+iuLzPvQN5w81L3l3mCtWoR4 + QVvPgnDtDDvApuudXAYFBs4DwKNronkE1naOAHgVt/AqO0PuBVrX4eRRIfif3SgQ9zneRRuec5ggo65g + 8MU3W2csCiA84+BTRfgPAqLznORUl5+KAa89D3af/nzXbURj7TdF7GQ9p8002NufnIQ4qr6puEWqr6un + aGTHHQ+oKt1o+yjhVLjkToNapxwaF2jNdh46GF5AqXSBPBPd2mt9mFhiqTK1MBk4Hin0qFLV4uPFQ8Yq + o7smxbKp6tOHMk89AcKs24xanOIqm7iVa2J8UwmrtcgpsLgWXSUYw7jg8hutzQDqzJPLFWuM+SY6xzi7 + mcl6SBFrW8kJ5qpAaGAY6qp3XO7ThyThEsByKbb6OwXZXPmUH9nTFS6Dghg0O6JrKgp3Mw1lHahtI5Br + ZUDMqo2pALzAlWhpPirXNMpjI4l2Kc/sRaOGZU2WA8ECKskYxanPIqmeP0choJ8V2j2N7R2SoxqvLZJU + 1H+8oevafAMz96LKhqavAAJopzbPFVdWJeB5r0hoA2DioGa7AHXdm7OCqTHcsStZt3gpe5s8GxkvVVSZ + zkImrTD/AIIVWtotx48F2zalM/giVdsn93BejXHLHHMr0q/Y81bSxByXpADcA0CYzTacDVZEqFY7ePz/ + AHVTY4yeJTX8lSENAbMQrXl08k0cSJWsCPPRFwb4lObQl2tB8U3/ALa3xKe6qYAMwnsY8cIuwARipRBc + RkJlFrQBwT21XnWyt4L0cuZdqpzuaYA0FzeJTSf/ACFBrM0+pTzENkqoHWdk/wBnxVlIOmeKZbuqUy7m + VSc6qGxMj3pz6bj4KZivZkVXJdkMOCFxJUP3j8/3QqbHGSTnGjWBHn9DMSu0cLvBXHDw0AvbKc7mtUq0 + JzeDuaNhheqp+s55otrN7TzUtYB4ZrUDGeQRxlvHV0ODqFzc8UGQ0ActBx4RKqt4vhS3AohmMpxGNylu + a1WB1TmcU4VReDwctVlqwwW38E1z3+9SMhhohgkprHAtjIrFzuumbbkXHM6KYaDqthTGhjHezxUtMFD2 + hyKLspRxzRaDgdGCukzzXZfFS3NTYC/7RR7T1gPAoFrQxCMh9Qp1OzfULuCA7INYMhopPMBwkuKqa7Xl + 37v+dFIOpBj+ZwlO7LAvxwE4aAA4gW5JrgNWc5TqtPWExDVeWGE/GLROinHNVHW4c9A9bTnwK9fVxbhq + tQZRJM/aTKbjABtb4p1OoTDdmSFgqjdk4EG2UxjA93MkQuLXL0YnO1VJDbgcy2UxjjDg244I1GB0gxir + exvd96EwmhSsJjOU+mGMtmMkXgicgvSOxJtMeKeXXE5BVHPNrWhWdnUqN8cEOw+tgDMoRUcBT1Taqjia + urxJ0BlQS+p8AqTDwG1C9XtIPIFtuMiYVQXupxs6G/dXanbODBzVGm90EgkynsFW5zin32DVwQujDkqe + HtBP1HxcoeIK7Z/4G81WdV9owAUAG3eCGDAGcBiQrxaHc7U409WETULnHgmVRe1zv3livRvuqq6+zEYo + up3bBmU2m1luMlNfyVFgaAwPBwVT7xRPqxdxd8kS2cThOEr0hr3ZgYHyQnYGJQul7J4O+uG3M8U4M4ot + c7BAjgiZ1j7SseA9visBAUtMeSh7Wu81Jj3KTTddEZoY5KXGTpuYYKxqFbx3VAuN0c1c4mULsgsFAdHF + a2u3kUXHMoEiRyTGsEMbwXrGkjwVMNbAZgo4JxIzbGmW9EXHM46BJyRdzVs4FauRzCMUWCeP1L//xAAs + EAEAAgEDAQcEAwEBAQAAAAABABEhMUFRYRAgcYGh8PGRscHRMEDhUGBw/9oACAEBAAE/If8Aw2R+S1Qi + TdeRG8NXNXCoBwBLOk8zuGgWhTPEG9n7zVqZfX/rplYf0qfsMEQY4jFnhE+BRtG5xDDnTCBwNjnefBp8 + emItaXLbs8TZ/m/jvRnJaM6HgSoJui+s+OjSDywiWHeR8dEstHU7PdE9qT2pLtyau2ibdkB0F8M9mnPl + Y0rOz2EIotuWihWO4WspRBDIbI07EaH45WuC4FtBl27HWFlfDCbBF4YaDlCUDVnfuJFslI5Hh1jNfdTr + 5IIAbhTPlf8AI/xLW3r2M04GpvmC4KqXxnzCfMJ8i/UEVNKG4pMURTzMD9LVlfLelQhq02P6iss1JCuU + z/pKeP1BKvwQ/M18PoX4xeGW7m7+D/Ztui8WKvaWwrR37oLMFxiIbzK27raFfeaFsFIvQJoOezS8IYHQ + 1NK3NRkHCuwMZ0bLmhZs+EAtjLiUDveBMpjlrcAkbJ55jKuJdprKW27vlejsvSeyJ7AhBOhwaRoWtxgB + zMK6kdmlqie5/SP3rq2+8tbQH1iTDcsFUpRXnKGgujhrCHD5p75x37nYArOXjy0YR0Ni2M7C7stmkBVb + RGyKTKusn7mp4YNIzwvbwj0PbwnXAuYV0LvCe74RLePcvmen/KZW+5VGhowcobgZc0HBQwbHtiv6Ql24 + JQWS/o6Q5SAK0TVrQ/NK9NzxdntfGDQ4rqYNYsuv3F4w1iv3KYsqBqFTW07Crk0i6udb1gizDnWBu7OB + ReNxGDSJ6CQSjdjgh6l6vmETZZRwyMGoP0JcmN0ZgsV6AJpleRUC7SpP2lEUUl58GW5lwIfePQ1qkMes + JXFyY+OsS65qxSOQ+p6JqLimG09+5nrX27+XBrB3emVgYQ0BKm3jhMTSaoHc/qa3KhrTJNXwzeCIdYRc + +fIaSp9WqnwaMdYLpgbgevDNKHpaRVQUXZeJ6mfsvvPTv2mn4ZZenbZjOF1Zz4wVaquc3REjnFTBctF1 + Int+jM7DI18cRfXuFDaZY8Z6xipSPniesSowsM1vPfcA534dJdZQXKWXXrxQ1qC5l+sl7QANuS4cLPEZ + vZeMtE+SsyrT/D2SrAoA8xScGWdF9UFc2TI3dnbTT8c4df1ZiA7p2SkcTF6w0Ijl2LM+k7EKl74gHfrG + e9cz1r7d9NpG3lOvaxonCRZq4Fs7wJG8CsQwpNBvcmr4Zd4vhc+aRo/NhonUCW146CSdVBsGW9gG96jt + FVm8+NSpbmqsQVyVT0IU24TiUxUotpKlTUdlIc4eGVDYT4hJYphwMkbTePz2T7/wlJuuqbSybbd9hL1i + ejyqarb4k9y4mw4/aUQWkemfdl8QKhttHcOWtGFKEAU6p7XzKUKUar2qA0v2fqO+T800yhfZQPRiXjq7 + I2lJ9TGg5ELrG8bNALb3VlEDeGsT4zOhekAKlLWmmJR2q/o6EY66EGRvhJoHNHjPUvt3zSmGquiaC9aJ + 2UcQYR4ia4HiQmPOdVTXAYX3gJQBflURKKQ3MdinXDT2AWn6q7DJSq+TmFAqvlmuBQLRVSuWZTWTdwwz + BIZqsx8o5UuB49lPGOSuJdiXlplw0EGi94ETKCuygrKxZ/stwQMHYQWwDTxMJpKnYt8VKRGAcIJwJjDi + 2OXrzAaUGfrL0kyrm0MYCAW1lj7jdUTx4KHECQOGxDoOnze4Q3LwswITIby+EQn3A8ewAV6ClzHdHdCf + 3hIrQ51Grxnn5wFm9Z+JupasuuShbMqh6TbWDGpoDWBUtf8Aac2Ksq7QvVR3YSqrNp1g8COqo3wZQq1W + gih87blicWvSP5P/ALDyxpbKznfknr0Q3FvoS4u50WVmOtt5bKFnQeBnsCNO+LDliYc2Rxv5849WjTKT + rPQfvOuhhSpsAdl3/wBG/pUbMgnsP8z3L+Z7j/M9xfmdcIWnDMJpHiJ26aG7iKVBVG6WiaAQMbCh+qa6 + 0KBmPyhRWU4EAylTMNU3TqDNntUNOOqW7rFItWsGkMhRdjie7/zPd/5nu/8AM93/AJnu/wDM93/mIZob + iP8AQBpvE9iyWQ0/tXGIWnQnW9f2nwgTSANiH8AwT1AYERrbvZdOahEEAxR3/euf4mkrnXl+jnNPYl+L + iZtXcZYBk8RcoW1+EUVj6FTiPNP/ADrvZuf4aZT+A62uMCeghDsEwJB0AHiVNMdIrlrf6vErfmaO6IXE + y9qo7bsClailCkw32O0y4MyqaSk27/u+j+yf4MKpXBfIJWbHXeYGdY7VR1B3b8wzhyGPEG+5q4Moq3CX + AVC+a36Kg+mzrC07FLz0jWHo0JUzyB5ppOw9Hl2UZgNtOJiZuqLtwU6a0rgayViPPl1QSABLnJCJXFH1 + 7Pd9H9l30Q77aXkpR1Z7VvMwVfeNPv1ijWJcdwN5t0CB4GxBeI5i1MOppNBA7ioOVjXQt9YOGV1LYwjM + GD5OIPbo5GI31ZlMD7Iu6V+sLktBCbUSAS2UNj2Ewq2rBmowsHJZcRgn9t72Dnvukrr8L6Cuz/E5xzED + 4HsRWdt7mMYajixjTttGZzsdNoVZAKF4s7ErY5VwmjXoSwBOW/8AjPIaYbWGo6ivdtU1EP5IgTBnuDfd + uJ0SK/1UX/UewVTxgj/nQaFjcVuruWdGw7gS2sL6xuvvTL66arU7gDqMxY7RKgrwStod5gyOBpZ43gXU + qfOKzAjSU8MWjlMoN1muwuoMMwkbDlWILQWU0uaduu3gLlmC5Sv+C9hRHLhFu8VMK/md22CCPynjzeG6 + YhqrtK4fZml25wr3BNBxGW+WD8xg2vy69TFi/YpV5y4WAsHiMV381DVdhfz3hL6e7B8OWqi03uDdoLxd + RL/gNEtnWKfZR+ktwXXOFc+MIM2PMS8xeQU6OUS5qW4r0glAOyq/teDvA0TIm+sfk95Rr/Ym3jDxrrXL + 3bzOiNdqlH3z9jgl2vWXYPCCh24pwMuekSJDjZmk3gPsdJCQHILDARUKKmzoESwolfmYV8GVH+o3hExm + fpcRK2Wl5hepgs9W/KJCcFGOEV1C5ZuxMI56pFE1TXnCyU6MN9qLSt07Pf8AT/fk0QYHOURq274S2MYY + 18EAADQxXZXXdlqbEWbZg7gAgda/fc2uOW+6KrVJuYl6CbsVKtCKtuS9idR/4N1miBsjia7N4tQC3Z07 + q11yEumBqjdwrdCyMTfnZOf0iEanI9IQwG7QfCWddFUM0ix/0rmNpecygXRhiDObz6WQY84BbE6dpdcI + J9MAlAUcXFNVGpLI/VEDbj6t4IzLBacTMxNcl1mgpX3Zp7K0xwFyoYHUuoSkLYxQBVvOCCDVPdYoWqqO + owpvTsdJCXYkK1jYsYa50g3EatBtAUq4aV1bVwxL9dBjsqdQ/wDB+4NkNTz6hLmYiWU6dYrIeTGf7glu + p5QE1TVc32gtjqD1H6mQaxRZhwK8ptMrAZTjlm7ph4eEIqhx2U7SDWjzhe9nDwMReMnnB2+iEmJoMM/Q + S+1yIn7zLCFGqfTA5Da08N7ytfRk0ZMFXgRAJE1u4ZSXZdmByksNWjqqMoRg2Aqi4bDYBaGdkqsBaJd3 + a5rSGG7FAYUntOj+zTucYB2rCXdqvU5mI8KwBhvw7jIObVWjNzRKKy8+krzjoM+s0UixvZivrER3FQq/ + PeYj55Up3l5u2xdtTdlcLMltTjpMWthqzeJuKX9kVYDqpTHW69IhOQsPnPilYRpTumFJS9sc6YhJVKRB + csGzMToJizV6S+MNeKdIxbvRuHYA3oW5l91x1B4ymtUCY8Z7bo/s2e4y7BthWuC5VwB5aj2J1gJKwNpq + 91EYt8ibGrXiSoVZqu1TWfVaVqF5Swsw7RlbUa1rzKNS8Li3peRPKXbq7sEuh21IIZF0NCE4YwJp/p++ + 6P7PuXPckAL2MxEEbzdJvKzXjMMNjmWtZWPFEQg4gwGGA2IYbcSwevEfE2cxYGrP0blGbBhxTDu3i+gF + JqIFYKNJHyGJVGjb+C/4/f8AT/Zofwvr2EfQiRa56xtofOENN5glgJqtLCGXm4mLWaRGg7dZtgZ80oSy + x7+UxUF+DLO6ess5h6MTT8S8JL8zJuATLPn/ANE04N3KA5964DVsjiUNTrlN7ZzhDh4F/cGmfClJ58wb + iTp3/fdH9le437FljrwpkvfLMzGcN1cM3jK+yFTgTwP8bzUnjINmLzdSkcxg5ycP3jUWvWReyZoN3YU4 + nkL8/wCzCIxDbL0Jl4w9IFJwJpomPbqxDCCPS5rjvKBXSJRJrtBNOxNEanKZ2+pgkaeIXJz3vf8AR/Z9 + 257Ybz7azE9hZRqXYn4hjh0mcV9G0RK9SUB1JUD4VC5lZvOiVBSqZagyh5Y9yzWnhBEGdga99IxaUhi6 + R+FTPkmacADmpiBfMH61dWC3fQg0q9TuqC3BzHaTwOniWa0I4bn3Iql1DgnaLcbJzFZRbB73tun+z7Nz + 2GAsOaRW6wqVQATfMUQqb89moQ0uxBEC9Snp2iim7EsTpC0bbIdQZkl9a1ZK6TxoEtl7U6ErId61Ruti + v1NhvAHHgH5njAmBmAGwHkTdcAn3X4lsMM3w5jaYOoivoFzeRmb9D3vf9H9n2znsJolt1fgahG2YZAmB + LU81NYTwSW4nTxLd3mbzfPY9Z40XKQ2yNWVhArvBq1LCzKOsa6QTNw48IoC8SrlTFO69ZZPkpSb6kKfU + iCK0SoUrwYELB2jc7vvuj+z7tz3KldumeaZ7Fu5TPTdVRiK07DZML3NZhswfolGyN5Qzlho75DdGDZoL + fSVm2AJ0G3ae1VzCZ4IMhmiL6ZDgJukop6kGr2u777o/s+8c/wACzlUMF2MfjmU9xKYNUvPumCEUfwJ0 + qxNTbg8m5OdTL+5dSnmCbYSJEIa8gflKSuAi59qOQWwohoUBlGhHHu++6P7PunPfrlkAw9IbV2G/HlFk + VngjETecriwmAO0uP4SYdNJdWspx0RRTdSfcjGLHKmYZ4Fesphp10/dHow1keYRquewJ0uJrn8DmVAaH + d9/0f2fdOe86IsHQ1gSw80K2eJiPkj6jsNeNcXoMDWPii7I+NEyLTzS2bctm5S6xWfw858NZhKa9kHo/ + XqQ4IHwRugmg0io+efqUjQNtJiw1pbH0Id91qur3vf8AR/Z90572mAGs6+cpxK8R4nZX1AYPNJyTDrMp + 2Y0aTR/ALqWaQ3ey6QH0KEgBwNz7VgZZAVJG2qmB1mGvOqukyDm1feZtfF1hG+6HXZMuv9vSe2fxPbP4 + ntn8T2z+J7Z/E9s/ie2fxPbP4ntn8T2z+J7Z/E9s/ie2fxPbP4ntn8T2z+J7Z/E9s/ie2fxPbP4ntn8T + qfb0nuv8Sw4e0w5HvCyOqA4lcul+k6x9IJw8IWylN2bo0m5KdPRPD+kOlDvPyKlPrMD+AXgWmTxiFVLz + 0gUuDSQwcLW6My9ucwCLI3cRVRoRcEIcG5MGSoVq4B9eXXRhLOZfbcuX1l9ZfWX1l9ZfWX1l9ZfWX1l9 + ZfWX1l9ZfWX1l9ZfWX1l9ZfWX1l9Z5zz7yJWVlJSBUqVlZWVgV/BYTuHLCdnrlMg4awPGKK4YalKYPh5 + lXVg8rUK1nX/AIR5WHhcNMjoTy3tCl8TPif70pGMYxjGMYxjGMYxjGMYxjGMb4HsE1H0+w/g58HPg58H + Pg58HPg58HPg58HPg58HPgYJfS8RMRSk7lgNcv8AvguEX3Pe8Yf9JbXnEJxHjMF5HSKGu/MFxDrDOnZt + nSWXlHc+w7nteMUZIdcrnA0AwqLRKfXeJeY+YenZIDrAcOYiFSqSmu27BcSOhYj60atomjAitsEQIMoA + tTWGwkAq2BNx3dXWL8ZctZrRdRcuR80pYALqiV3KqoPW6KRDYniYHjCpUIr8UmoW6Yw+cDzssINTGu6J + hbkVb0gcBBvaaWwuKWGCMlN3ElrJy0rrMgwZl9YxT3AxufvYZkShYNoK06Q3UOlvSBBimv8AMY/cQGBL + ljbTup6m1qGe9tyEwFNdIbQ4wyziZLmPFwbd5VY4YzGqrAH1lnxvMNP8UbLQu+Xt+MwclTmXxnXijJlW + R2YuNxaGstQVaqpM0ADyHETV/FsdJe5XHMNXDGDJNUeMoIu6GYuDQKr61CGA46SYzOBy0vOasO4WIhya + wjxeZLQr+hil8rfsdZnwwEd0dZdU0GJY6yvRJaXcXFON5oOaZZFitnlBs2Nsj6qKMap4OIF1iC3uAwVt + BohBRcKpwq26CJvC+sANzVxhjon1lgagosvmeA07TCCOR6MRbVYPMzz9bki27Dgh2gsn1S6AgDZpDglN + q02mAVh0O6loPKsbQs/LjajVsx+g3dIUujFRabos/KbUgwGqss184BLxrsjyptDaZL4q++Xv+MS43b1V + RWl/ARzKZQzL27debFRdFNc8oXK+3TKjC5AMUbDeAQAq4wXt1bnIBrC24ivgRfyDJxZi5RGeIEgxOgjD + oBaMuoN7sqwlMSOO5uriDAC2VPGoVrNtaAzqPFHbeY6kb2uLQhAEmvPnN1NLoRemHxSx8RkxoXw6IgJW + HGhJdrzliNAaFOD0lX4aOMZ41C3GWBuOq0gJ2dssD4b8/bTgKy0hJoGNsM7nRmsROULmCJctcxaTdoru + qxUOCI+pcqnHKNDzxQUJDm3fsDoMFBjBd68oa94ZsTZxEqQtXbt+17nt+P8A319v3Crauv8AvIhs0GL7 + l8adzmevcJ7w/c94fue8P3PeH7nvD9z3h+57w/c94fue8P3PeH7nvD9z3h+57w/c94fue8P3PeH7nvD9 + z3h+57w/c94fue8P3PeH7nvD9z3h+57w/c94fue0J7QntD9z2h+57Q/c9ofue0P3PaH7nvD9z3h+57Q/ + c9ofue0P3PaH7ntD9z2h+57Q/c9ofue0P3Hmr8P51/8A/wDVVVVVXNdzv/5W/OZEhLI6kug0dQhPQWTv + nlI5Gyc8vz/J5Ty7QQvEESFVR3jppAnyGJWuv9+qHVRp2YIRaeoZ8Y14RTU6UOlJO6tQ5iukGnb3Ae2G + sywNW7sNbRNdVV3KOrC8yuP1bdxsDNVMcrwhlcRSiESYimGo55N6ej7EhFNUJ8aQLD+SIGavBOrigIQf + SK1urn++d67an7mk4DGRiZqaWSo4tl7IV8YVCzv1nq/sT7aWH0rQvfub1suj3Ge06dy3epflPEtdu2TJ + DXd09x4QRVKoPGJ75JU9Uno46y7itMz2BCTKYzczgYhOu+ie0ISdHH997jLlIkEFulSDFBNR31vCI6Cq + sbgxTCLE3J6v7EPVKl01Cqb5WB2E3JV5nTRPlYTaByaxKt+RgpiGue00KkURxywmZ8QmNfMeWupOuZyC + WGse3UVlQcun0ji3iPAJ6pPRx1mb6BpPeIn22ZJpHtsOwE3hwf3xi2fSEqZUPMrLpHtlylC156mGVdj3 + j1/2Ow7TRdZTrJpDAq5q7y7a9gdPefauxQVF3PbJoIDSW5uFz3Se6QWHDUBgrdfGUGOcQHIOOxKESMHh + PVJ6eVhheO2JYXZeYLig1jtu7YRTP9/gD7kofA9exoLIZVdf9AnvPMer+x2O34C7/c+Jf3AFALxATQSd + iC3NrF/6h5Ep2DE1VPn5VIl1N0oFz5+fPxW3rcQ+DFKTrkrcra9IHXgbIclW9z2B6eWFjGlzpvonRfRF + 6xgxHzosM6X6Z0P0yicDeCs/36qlZX6lW/VgQJmLurlvf+pS8i/aoDXA6qunSet+xGC7qwX28ZrgpVsH + P5OGktoVctobqVLoPAbexBN3NQYZepxG1Et9xw2giCToVW/hPWJWGxIsrocO5YWwgqeh7auV2l8gXj/h + RQNXSOd57SmDVhXaYFhrRx9Jf3fqXoNys3BTS3Hxj+58e/ufH/7PjH9z4/8A2fEP7j0wsY/gau6UCkAK + omdaKhFPAFVpLRBqsLy7WZTd69mrYDWQ3/8AMs8mrKLmYJwukPAHau5jCDAH012WI4qzV9GO6HB2Bgjc + MlFbCmxBjOeWFJcBWDQxXWBq5d1xLY1aC7xTWLm4c21zLnA8IDGs517PBXDNW2qM7dTE1Dai2+wLQNWd + V9Sdd9SeEsDEovux84REVWOpCc0QesLF1mspDLgzKi3bOcQnAW7z53FqddgkM90sIQjB4da2mKTutqdF + FtK6HU7SQWqzav4rSaDKLjAxC3EVGMSpZKNYwGhjxnsiU0z47I2EyjWquUL7sLgXQPDilV8TPxDmwVTr + slQgTIpiQVP7jYEdYpcL6RfFqpepBXk/Y7Pg6euf6MvAzNC3WOPkXX2iZ47QYX4TP2NZtAFZqYBZgIRj + 56MYc6vlLiTrKluh3BNNpQisKnvn7jaEUyE6rbWYoPRuKBzx8oxagacKYb71Zc1AxZmLak1XWI4MBZcN + yBVQaE4AjzP4RJZrjQd5gtN1RL1aOKCeknsPGCEF8u9xu4SMBtMlVlHppzHb4ItrCEmu3NRJZNQgH1he + D3nbXZTrrKaaZYQ0URjrFyxBVG4NzCHqHfwic6kqpCKw4OCZZoD6f5no33eyr6A47AsfVwvWWGo6UDsO + 9rTArlbCqfB5Kg9bEpcG74StGDlK1v3i0RdRhUDKZVA9Z6knomen/aAWktvSKS7ecnrPuZ6ZPXv2jNYS + ap8h/sqLjOsvHkhqjQD1YYhpTA9ZfBd30lBFaZEl+GvLc62HXE0C6sMZ6ib3L6N0ppNwP5mULZa79nCW + o7y0FiSp7LxnrP3hufAGSkv11lpzGA2MCLUQoGxi4oE0VDqM7/xEw9ItZUPdG/RvPtvvMuMVtesHXGpu + AzJ8ifbfeMbIy7DvELML0mQOfFRZVDS1uDA7wAwvnBgv2ycwOtEUFKvFp5y4DVQYVLfXZtUpVxQurirK + uoMH7lLURhTylyWFyXk2M9SSm0R1LxAUK9BiFtUvNhmcSet+5npk9Yw2JyjVU676JmYBeDPSeg/aeydY + VDdPjB04LjLQxOuszyPolDjSsZ7PfEkUgrkuYDw3TAiJagOWICCNXsb4SGg8P5T1n7x01YWqdX9Z1/1j + 7KxcAo1f3gN2qQxWDiHrv2V3moHLEz8CFAWmMx07pT9ojPx9zs8J97+J9l9+z0X5npH57a9FHyublo+l + XHdU4M/eGGpV2Gj4oseBiFXI6YNHYWIr1jKvmaIG6O+Z68nqHZatGo31itMHg/uP6n3M9InrGCkAVZjs + iC2Vxoze8Z7Z1lQY/wBU9choS1WhwyBrqzf6oaZlbDlB46xcIKy10z3BLQH4YN6u1G6aaQ/eWHgxxOk+ + mOy3P5RVbF+aZtpl8O1CLgM7ONuz9v5wdDHNV3+QMToSiZjKXUQXvkM631w5frnvsJ6yT9x+JfWm+cX2 + cQd7AmzerWXup4nYHopXEN8YlNKHiRerPoqMHFvDZVXxNHxQQ4dpfMHsBvTEqXwJppvYpcS8hdJczk4q + 2omNDpbCgKjGiHw9RfF9n6CLjjBFwkGN4w5qSk60+tMECGNEyc3MD1s3DErzyBmFTU1rU/PmTBycoLoR + CKKbZNRJl9DowF8n17Bg4btEutZXSZZg3X2MUeK8dhA82CUVTnEBL0avrAngeoGLP5hTR+ktuvd8JzL6 + x1h4m+0a0i1s8LzAaL9YZ8uuZd9uvB/Ut/8ANCg6KEuWj0YvOVx1wOdZjatcIWYEDWOZVvKaapT3iJK6 + jZcsKTGBNXE20nRkyigB1uIETwODCEqqVS+ss6ysF1MFLVuPrFvvFGCFGTCqHaGKGRCsTb4JWUtTsxCg + DGJAChzRxtUWwyw0UY1mh2C7reLiEt+KvEXdR1GYZn5BVda6TbLQOuPxK+Y+IEM77fBuKz1imkB2InU9 + 1L5srQ48ILumUFBU9VF1l+sT0mZPiFq+m0oOH4TMd9ALL5gWgau0KCgqO/T3xLvnLxe8wGQnMbswW9JQ + kDACejw9ZmpNDRdzbh5zM7AgxvHIvi4bHJvEb6MMXarkZQqUan8vo33ihB8JDs399vDEyTeLJpWoo2sZ + rkwNU1mFpDei/iWlYNaOSJ+LO0EvmmDyePrHxe5oqHJWYNGTTFZrymf+Y0PNM/YgFIPjJYeOFJVXndLG + jV47FrQecprmHQSrwzHqC2QVFk30qOvMu2ZpcZgbLfbomtQuB1ay7ILhzEG7GFgELZq9DBr0Mr1SmmNG + d9I13TQH9paWLa4ESmNMAr5phnQAuX0VBG5KGrVQGbVXoN9In/Royzf6lVXM5WBMQnWiLzZNQgkNqTck + KWKDCsEG+tHO63czSvJ2K6QaW4bIagXNA3xQs6d343MawHM1hGq9b+sxJwdUF7wDjXm7TQBGY1qr/Lda + az5SdOLLcuoggZFvWYQbb17HA2/Wtx8ELdLDTg3M2G5UF8KDEUfZmCUocay08rV64hV2sxC9mWbSwdmJ + 9Q7NLyHrDhDWZ4k6B6YdYjVOWXZm+OnwSUtDYYmpdTTrExC80N53KY29t5bzLzwF3USLm2Uv0tuiWnne + 4AO6NyhsujZGUvZvtERZMu5tNbK6QIxXVayzX62LlNUcf1JmvOZ1dYBV0UsKWNy+wRGLmLKsZu//ACLW + U2llN7vFiKYTvSOOtW20esUvRkLbuasbBwOG18RLeOUjWa8vpNcIxFX1rdfwjFlRop2rnGypQBAsbfOV + OlTgCUzjrvfwlxDy1wakOuWol+VGGKApGgQNZslLgUGdNpXKPNITNtUaBzDDWxY3MQZ3NYjaDCdZuO4X + MamDSXKEZqbSop/CoqU66ErT0FOrdm2vrFd9yRhSaZjXNV1FWxYqWqaEpY2ji85VrFYvM8Z2nNKasp+r + DJWBRaqFEyhIvK/12kwATCEQhLG7KDm5ibFw0MZZyxaIF8XEK7MylQtSZAPoIG6Bew9YjAp+531L2hRz + HcrXUcNGWdYjhCqyrXnLMEND8IGYw0crmFmfDNMu6vgfJMSQl4tXpM5EjT5xMbqUSDSJQi9CdRDHZUK6 + LJelQr/aW0D1JtOjCONa2zNmjtcE1VNMXzcwMDGrHrDLBXoNwjdFhlZL1JCxs8YomHVMnmcJoJqwC5uz + NdrF7NZl5Xz4XM10i5fjciaZR1naekt3GpxfvWEBOjBDGLlTTKEFyMFCKb7apjq9Ijpqptm25ldQTFsu + YoarVBll7JVraWHYOp6xpt8XVxMU0Aa2s/2KNYGH24ipqVd+CFXN5a6az2vljFIa0ldg0iMR5jBog1OZ + UK31TFD6X+ippSK4QsQd1pQIzU2L6RUlaN0Ph4lUzmFsdOsDbJDjPHfwb1KeZgFpd81Gg5WK2POOHi93 + WX69a6EV8jXmXMDoaART88IlnJpzBjW2FaRsoGi7ei5Ww+90cjVM8dlkqFdEtcnriuK0AxFcgnWUJJTC + lqrC4qgyXJmAYV1zMEC10l7qFEyEHfNlSXMMbzS+HpJc210Z5lItFYdiFZULaVdx1GV84AvC6avGAmh6 + HibQDN5LjmMVcuYtRkjc1bViLavMam7V7QYhfhZfuymtzE2K8pWatLzgbhgY2zqxSWpDlhqeq8lSDbC7 + iqlUdggYvhd0q1OJWOcesoO8aMosStamzK2mar4iPpNfM2GS1zFANAqMSLn/AMUQEqLWEluIBRMOdcXj + f9Swni3I/aKzbHmnmEPKeFpcCBGjFDty1ziAWarCs9ofmBAgtaGB1altfREtTdLD4z06yJZros/UU8eD + tIIlsLiMvJF/OgFjmW7FVElYsILL4loQaAgkHUIWcouxpFahLaKzPMAx3eo0nQ++dYbCv6P3A6oiG+zj + oMyqyYUjowLeCjKUy8x7HBO46Rz5vVekVFn6JQUrxIRHmyiI+oqUrKoolkHdQJU/0zLutm52BbRq7QhK + ukjSQFrM+6gj3b0N1U9XJUZaJ0aVN7TTIwgrYvD/AAtPFlZ8pX2aBZfuNoWU72kUkdIYrXhPbOCeufsz + I7LZ3rn1wZkuweI1hIZIdjV2AVyzF0ONOuj5z3c/5HPfYUs1aYIgNDVW+MXUPHz2AtBpvA7iaGblknYF + EzNYgq0AX5lhUMQjHupc9c1+NWOoEpbfEz/K/wCiUYXwC+pGwUXb7iVOK9Eot0hGFUecJ9RNVhb6vKBF + TICkoboXMdhVXmaRctXOm/SX4BUAOiAL4K7Lq2DFq/GBpozf7kBzJMqhiKfox1cza4RY+kDcU3DeDFTL + HhFxqGZrNXl7BEVxxEDzCi0b0lQA5itc+s2elc+cybC5uZluGQVL8JfJ1EweBA6gyGYaitP8OQTE6Mx6 + s2x+YmdDGxBK08lg8IOBGNLxxE1thYeQKvWBYzRieL8BlKwb71bunZ0ms6zPUztcFHWZtbxRtm0MXNVL + flA1g0iFtMVb1NsbGvOVoF3hiXpZKNfNDuw06EsplsLLmJrjA0TiV5qoczMScGAGXXtV7TQTzjNVCLn7 + 1jeCxv4yslNfxTEDXq2IJTZMfKtxddjhJwzPyhJxCtD9Yggvaswii07uwFdoc8pfcuhxivoS1dwARwY8 + 4il3W5BtLguwR4C0Y8kW2DuzFYc1gImFneUEUK67GZS0LB1hFkrHHhNjY2fOaejVwqzOxueR/BgwNM0w + GUCqP/hrXuKtQ9O2/c+c/wBnz3+z5Y/c+WP3Plj9z2h++yvkP9h/tf72R7j/AGe0/wBntP8AZ89PY/72 + B7H/AGex/wBnyv8As+VP3Pl/97jmfyf+z5OfJ9rn8nPZ/wCz2f8As9n/ALPZ/wCz2f8As9n/ALPY/wCz + 2P8As9v/ALENss6cdes9l/uey/3PZf7jdAbw66S+gDhgqM2lwPavzLehe37pbkLrP7p7P7ove3n7oRwy + 9T8z2GTxAwCyNiFgE3F+5/pX7lkLmvuZ7P7u1SuTH3Z7kk3go6R/3nsx84nzifOJ847NfOJ84nzifKO/ + CEIQx84/k5znOc5zlMfPO9jGMY+YT5hPmEu26hbiv3te46Id5aiWlLqW1nHFS8zIQn2UCxfdRBAol3Aq + rdkYn8PujVilUAAp4jrAuVv8kyULba5rIW6u5rIjHcF+N3Bez6PZcuXLly5cuXLly5cuXL7bly5cuXLl + y/49E0PZnuOs2xDW3nUbUu2JVLF0xueE+yhLaRXGs1qijpDbWhXV6ywqTeUXf05iRhmzKHWvS4b+g2gC + phmtO4vqdwXvejLl9pcuXLly5cuXLly5cuXLly5cuXLly5cuXLly5cuX2Lwz3LnuDYcze27SDwKaF8wU + Y/DMc+G50rBdfib0kr2TfiZ8IHC/0SmiCsSsM5dEOBl2dpq6UF3lCjsG0oxg7uWFgq+56juQpi0/3/x9 + p7dz/X+q7kB4H+5UqVK/4e09+5n0jqFOC4axctoWS1DKljcWIAGPrR+kH8tgXKOmlQZ15Q2QxsC99spk + JsKi+GDlKOV9polXrGt1BBJZFZXNS0rmdZl0DLR9StNHWaBMoqx6y6OrklxoSFTLdFXNO3VXODgvchSO + yHcXxU+PnxU+OZ8cz45nxzPjmfHM+OZ8cz45nxzPjmfHM+OZ8cz45nxzPjmfHM+OZ8cz45nxzPjmfHM+ + OZ8cz45nxzPjmfHM+OZ8cz45nxzHrb+nZYxLUAyvjKiHfsC1MsFrRmcGvJ8oPA+FMsaGwPrgNcTqOSj2 + jXgEo4L1aacFUqbGoPFcsB7tRrZLpS55Lh4NWFnEjou5Rc4LaIGBD0Q+8MwoCYnqUzpYHcAIIzscvbee + 4Z7hnxE+IZ8Qz4hnxDPiGfEM+IZ8Qz4hnxDPiGfEM+IZ8Qz4hnxDPiGfEM+IZ8Qz4hnxDPiGfEM+IZ8Q + z4hnxDPiGfEM+IZ7hnxERoQO52WIW8jecJIKEGa9GFpushmpb9P2SmEG9rhblm6HOsm94AO3eIw2HTLN + xRadYlzVbV4Z1BmCiwqhmVJC7yQL1k3K7dxFsoa1GhiOmtC5Q7w07FrN2Rk56nd7lPa9Hsv/AIrpND2Z + 7u77BlyznsG5c1lnnLOZfZfd9R3Kex6MuXLly5cuXLly5cuXLly5cuXLly5cuXLly5cuXLly5cuXLnsX + PclVTTzGA/R8bwO4EXyqKWG2A1tCx64L3RNcuzWGn1nM9RAp2ZChH4hObIzRJli6O0vO0ZyhtON8vxH6 + SJ+qNWzXdIowwvXW7mh49wnvej/x9p7lz3PgRiMdErLUzP3gCHSBwiyt8oObC/15l8ab/BAYnPggChlD + t4pQCVLuIHFNyB0iNIteD9wdUIZXMgZDkunExzNGlvrKqUfNBKtrh3NLx7gPe+Mr+9UqVKlSpUrs925n + PIctjEDdgWkS5BuFkvSvxnZZcFMC1BaswpxjDquJ2tpZxXjGwuEOUJUT9CKEq89vGKDscNhkbRYRVcuj + WDL0u6FOVNS+YIF6hcPt6AshizeYsGXyEDPh07fUoZPDqPWL/wDGkREREREREREQAAAAAAAAAAAAAM/T + bzHaTfz42sBJBVz6QGxM49Yb2WDTeMvrzf8AGV4brVRiMNUeAwlExERzE0INuqqybKrGzM07QLnhGjDU + NYVnAGlq4fT7y5zwNc/DiCkbK/ZcApqdjjKkuy6ExAPN7Mvj4NO2zfGoJRV4oyRjWnD/ALqPnUDGHtBo + CTZUfMI+YR8wj5jCdNa0JhHX6qPmUM010cfJI+YQFWW14fApsuPmUfMo+ZR8yj5lHzKPmUV5hsNhBCSY + pfaAA+Qx8hj5DHyGPnEU/WrHyGPkEfII+QR8wgc4Vm6WfgRxecWBgbK5F3l+L7GkcKs6D7Trvr/UJT2K + MKGpBogbnVl6kas2AtT8Szo7xk9J7f6o8ZXuD8S6o6ocgAf8IM7NLX8RM6kqi/CoEOOrZmSeAwTNfLVR + lwDowWyQ+IfSZZ+2JWup3R7rdVXy4heFxzKrDrG7ALLfyIGBTQvrcVOlLGou0Csu2A9tTyY1hV5wczI0 + Ngj7yxmY4Z49lBT5y8wtrV01PHsQlQqjlx9ZVBbmP5SpFXBKmgAuiA6G8r+kEVKXVzQjZbzcWTWgoy8I + tq+kKUYVg9YrKuRgPKWWFL2QwFLVyeyC30MXSpVoU41x2hbXMuS1i7QbpaJ6DJS9EMubf5JQCqMVMsIc + 2ajpCckUH3sG+8gwW+YHcasr1hBCi0o8BBCMdVuZhhDBsh18Aan3UIdtV9xEUfDLidHjRrH216GPrK6W + utYCiNhxqoFd8O6fOEaeQKIz05BOcO2Dy/j6bK7IVFpTS3xzLZ0Rg+ka0C4hVUy1lQphFigg1NDrre5V + Sgpr6o4awMMum8FhaxBVXSCmwQYm0vyMGNDqqKyYHc+aOEcFhDyjLobD+MEO8LusHRi0n5E0r0YUKlNT + JrBEFsZLYl5VQJjYSDuOJSLbDnTmU9TSoZX6nolz6VArwluFlpSGlfUR0no2+kbYaWivKUY7rhXYJsDA + U71Q+uXgVGW/H1mVw+R4mQAtRS3LitGkL0IFvCYRDulBO3eDKoU5HmNvLupc5sNjwjWoNnjmIpT34iXI + W8yp8WIQ2seBNmYJtmFZkXFRs0RXZrwSuiwUxiEBoQ216xbVHgQ4OHtuA1eBnxJYzhTTG0C9JgbThX8I + kieGGohVbCoh6Y4dlXeNmck60rjSsKVZLDlajV1M30deXJL9YcXv9YmAYdb6QYgvTWSvMm5p6w1zc54C + k04Urs1XjpSz37A12YRu+KDpMaugl9+rCcKrpLjebiPPMt1WjS5btR5zwm+vHYlsPwtwVlkcQGhj4IuB + Y6s15QdoqdYoLTDo8x+mjSAO1wQGnDsp7bKocOMzVCrxFVtbeWZ3BIqFCFRqwdzUmmBlyYPqG8StF5hm + W9g0Om0zK16s6xCJrHYhOo3n3iotZpjqqW2rlVwrdZN+kptY2h8t2Ny3ZHV1V/0KBHvLB9CPjgAV6xEH + UxUrLGw2zLZz0LwCqC12IrFZ4BgzUuCeRXvPYp+mw0bzRtGhjMrY0QtKlKDOqn4gargr7EXqqQC6+pCG + ksLxbiJhK5WVubfq1vjrEKzdCGzKab8sXBstaU43gW1ZeInrtSUOMBXNvrCguts/qXtKrZ8ooVlW4dJU + 9ehVgEtGrXxnif64DJE6slfUKkpZmqL6sI8INDneZmgYrzVzeyocwqAbdiv1gOR1NT+2YdpUJtdjvnsb + irsbMw6q/EJXi9QUFlCDTOGmYdK3H06wtFuF1fZ6X92YsNV4tzKZFatL584VQxxenjEGmbFWzFp2UqXs + VakLhEqw1rLlNSYSz5jlqlf0Z72nOcZVcyX8NBwRoLEws2sxwVKo6RZ/mBgjdgSBZuKq1byz2/QjlaEM + s4Y8miDusk44w6eUUm3hBo6Oqe2cxsFKlrx0RMzKh6ANoTU4A3ppG9AWGRMdOsbWxFtacf29HQK5EZg0 + 5S5dRewARzRfIvMVAXZpmZQVcoVNtjMuDUebzGZRkcAomgJoYoS16M6TIo79uMBlx9BiW/txRgst8KLH + R4hhrwkZ2kdmDVAdGJdKajyczmHMQQMtVvD0z0KIGpaKoiYlLdvZLajldbQkBsPbr6N9jG16W7NWVKJg + esIsNNYDWZCvWdGGSfmf0v/aAAwDAQACAAMAAAAQ/wC9Pd/uOv8A/wD/AP8A/wD/AP8A/wC+/wD/AP8A + +/8A/wD73/8A/wD/AOiL2e1I3HD3XuJUu3Z+nvTJrIDlE739X/8A+/C8Wn4iLydDpx3Qs58g/qQ4OYHH + kaRC/wD/AKm+0Es9tQ/1G28si38D0hQk/Axx+Iu77/8A/wDv/wD/AP8A/wD/AP8A/wCv6Dzfzzzz3z// + AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A9vc3RmHbl1/ff/8Av/8A/wD89gMv/v8A/wB//wD/AP8A + /u88fc888ss88V8//wD+E/HXE3vuks8vS/dPfPPPPPPPPPPPOHP/AOL1nb6wr779QhrVde9+jzzzzzzz + zzzz3/8A/wDkNPtvt6fvtc+vNe/OgPPPPPPPPPPPA/8A/wDWnU++VrP++cDSrnNzeg88888888888u// + AO67PvdN2NvvvnHfPTXPKPPPPPPPPPPPKu//APkz/wDmDELw9i/mVlRPAV8888888888+qf637d4JxGx + twtt8tdus8e/8888888888+TqItjlkmMElhP/wD+uMf/AD/97zzzzzzzzzzymysyVWXNmBwkP/2enYjX + /wD+88888888888puCFNNXBOPEJ8/wCIU2TMP/8A7zzzzzzzzzzyH5gPq2R4Jx4X7+6f9gNX/wD+8888 + 8888888d/wD/AP2JYev+z/8A/wD9NBxxv/8A7zzzzzzzzzzz7/8A/e8QycLe/wD/APyQM+4rn10AAAAA + AAAAAw/v+wREFzzpz/8A/RDhBrmNMM+++88++++++8++3OMMMMMMp+/UK1M3LLKkOVO1VYhEH/iJHC+p + i3Gre7q//wDq8sEru7uTB0g5w00Qs0U5SPQL3pnpFb//ACbzzzzzzzzzzzzzzzzzzzzzz0AIIIIIKL/+ + /wC+OOOOMMMMMM8N+OOOOOOOd8//ADzzz/fv/v8A3333ihrTS5DH3nf3j9znHYn/AP8A/wD/AP8A/P8A + /wD/AP8A77gXBZLVlHaJrV1Xr4Mlb/8A/wD/AP8A/wDP/wD/AP8A/wD7ra8hkhRWKuP72dM9NuP/AP8A + /wD/AP8A/wD/AP8A/wD/AP8AbI3K+6b3v/f/AHJmnZBX/wD/AP8A/wD/AP8A/wD+9895088033zw19x4 + 4+y3848991zz+8/8/qZOP59UHPAyO7b/AF3mo2TKaM8rlUOku3PP6WXzeXJxc9hj2mrL4re0GefCqNEg + TfeVv/7HzvPBLKKOkf2NL/r7vfj/AA5ez36x9zzz3/3HD/nLjHDz/XL/AJ62x922956+19229/8AvP8A + /e6fwIXqvayiGC2Oa5dsB9hkmiXhb/8A/wD/AP8A4x+w398362yz1z37w0576w2/97+x692//wD09Tpx + gPd3TYk3FBcU1q12WcZQLHFfsFvP/wDb3Zz/ABw53/z145R38zw8wx4292456/8A/P8A+jiBeC/PNn1j + aWD/ANk+Y/2+K0xdb133/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/ + AP8A/wD/AP8A/wCfDHPDDDDB7DDPKOPMNPNspogJSIFYAQTvvk//AP8A/wD/AP8A73//AP8A/PPLLZL5 + aEJZkNOaPzP7oYf/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD+6s8Y/Ln/AHBvGO+tnNwwwwwwwwwwwwww + wwwjvCW8FtDFh5Xw+qWzDDDDDDDDDDDDDDDDDz97BfUjtThv9++XnLPPPPPPPPPPPPPPPPPNaZ5mkXwH + njZz/YZyzzT+33zyww4404/wwmvzMOl1dv8AeiP/APhoKx2R4/8Ax+njV1v9hTUOKnbFaT6uT+88/wDH + /nr784Jc4UEZMNm8kMj4BNfP77zHvf8A7/8A/wD+lIy1xthQ6TzQu8pfevHi/wDz/wC//wD/AP8A/8QA + KREBAAICAQQBAwQDAQAAAAAAAQARITFBUWFxkRAggaEwscHw0eHxQP/aAAgBAwEBPxCCqUHMTuSustDZ + AMpEwe4GJY/qV81K+mvmvoVLEea1CO4s3/ExZDxGu1FIcKoPPEdwemO29OKY7u0O3pBGrfUCLQ67y1Oe + 8Y1WtpqGSbdPEz2OMfvEMHyjZf8ALcb3HSMoDUDggxqYr2gjW3iBWhiKSG+nEWsX2czvYKG6sSEwZBzB + 4oF5pgA2FW9pfAAPzL2Ktphr5FNTFnKB56yhognMZa3k1ADZUZ1Kj/egwhet7l9XgxFC0TbU6KIQhKMa + jDZfLeyGdJgIqVx6harw3uALe65gle1Eckv+9Zm011/7Bwi9VzKqQg6jMmqXvEobU9REtL4mK2Wm/MCI + OKhoctLhka656QQZeg6y4iphqfkv8Q18skKuCoyFkuImabxCsHCRLeDmmEFpXQYoiMSuGPgvw1AQKSgq + kUQouJK4lvb2lBhQ08xu3C0Qg3YXZ4jminkJRizWudykjA/mBkbbuLATA1zMYvAlYPNbhdGaGVEUrXEr + ygJvzACG21moz3HcQLROjLu2wwd4xxN44ZliU7hr6alfoOh2TgV/eKKsdHpGs2py9YJWb+0Y3v6M/p3+ + mkW2k80P1O8RHTEyVMU2pnBYllWxy2dYQm/NTyTyTPi5X12G5QgX67+nV4+DEW4foCx4+lcgbmyxKdWC + NrcPBCo8Rk2zT4AqaCE0xvX+4iAv+SIa5rRNNqCMaAydYgpaF/6g3WTXPEMTzNPj+f1P2voWAF8yuDLV + n4RWRqWl9QpLPhUAHzLOh6fzKBM5tzo7SnZPvhiWXb3xELhbs4rpLy2lfx0hRioc94ABQTT4/n9T9r6B + YJYH48QCHP0AR8kTZcfC1L9J0mSzmIFrA1dRPJmLqWXKmlzNPj+f1P2foNp6S1Ju6+0IA+Fztl10jAuf + gFEfDpxrAtbv7QIbcN10JcS63UJg43rmKzQObNRlDFDctzZycwCZoE0+P1P2foYYZdMaDb8EKo2uJS9E + zFCz1PyopKgAolRBwyqYYlYolTV4/U/Z+hZq9fQvjc8qmGAOJp7ykFDLiMeILqr/ADC+Otx8Nt0fzEob + vrWGLOP2xDQMhfbMFaWrUYLDNHj/AD+p+z8LUpKps3AcO/jMsGcQRpzSWGRcxvRo6QcQzQlu0nWuY3do + 9YItxrzBFFrpKIUI7b94Akkx01D+4/tTR4/z+oq+yXUPJi3avMKrUILO2FlkslSukzRbC5caC+Zs1NhZ + LAdDK+c1UQ2Sk2S0+jT4/U1ePiwGHeOFrcKsATXQOa5h5IoBxth7Re+rE9SKitpVu6tYXt4uvESa+c6A + d5nOGXUEeSUC3Eph8afH6mrx8G2paq1wRu3BwQEoJdxw2sMOrEEarmYBtIFltcHmLqrPL4FloLgs9H8R + iBnGYJW6vENmxFp6nwzX4/n9QYeISnhmGYMRVHSKlxuNWwqOALpgtN4CKvo4gVL+ER6JYByOSXgYZlMS + rYYBFNxjQKr4Zr8fz+osPH0LqK24xFgd4u4QXwCBX0AeCDVI3czCTqGyXA/B/mA6NERW/DNfj9TV4+WI + g1EiCz5hRriKN6lLitmRD5WVxxjJN0zXWUnM1mJwK/aGt15ly4J4qKlJpNJpNJpNJpNJpNJ57xLlxZSU + IgfOYF3A6dHxlpstfB8vwoDWIG7b55gfL3F9r3M9231mCre533tnfe2d97Z33tnfe2d97Z33tnfe2d97 + Z33tnfe2d97Z33tnfe2d97Z33tnfe2W9vc7idxO4ncTuJ3E7iJEvFkr4QwysJuxrdS0pdTIlRBqswUun + MHaDUHUDW5nQFlIKbieyIApuJtJMlVC9AiaAbi2FQa0xEi0mK6gzgmaCWLsmxOIijZVS1ZZ8S3Sp1gl0 + 3moVGwPEoFRHpB+HzQvCy07C5zDDbtg1CaM/eBFHFZmYOUrxuDsHoX1i1VDq5Wp0aJWS95zxiJMFHJAi + nSeoharFMWbRi1vvK0kLCq8xFs3DW0rF5JUaRyY9xapyv+Y7+nzHnMCuvNQAK7PUqoJV4mx8WIC7PvHP + W61fMtDykarypWYmw+kMb2cZn7XyEb1+KlfFSpX/AINj9BFJoPlmznrO0+52n3Ow+52H3O0+55vc7b7n + afc7T7nafc7T7nbfc7b7nZfc7D7nYfc7D7nYfc7D7nYfc7D7nYfcDbp9zsvudtnbZ22dtnbZ22DUal/D + KifNQ+A5rMWkW8TR2+xCosvrErNnaGDfrZGhxexGkWSXGCUEuBZLGl0XLP8AvEwJTVQ1HD1lHS7jTbi0 + 5ZYJqtfW/S/B8KbQl5JW4r46Tht95lWl2XXmAgWPFdIHYn98QNYv98QyxcVBSxqPVEhlwTJBa4PvGSoN + QUoC7tj/AF8zMwu42KTrUYF2ekclZWMfqPykRhdHPXiVBbWAHoNSuE5P3gW+bz4hhdl4hAVDqWBVv9qK + bSvtNEKep2z8QkDSZuJe2+8RDaYKeJ/T5ltIMf3UToJHywLzDhJOf7X/AIAFVbcw5AUzCBtbzn/cwoAn + MubY4hOwMxEQUagU1EwEeUW+vwSFovMJBUKzLY2vDq4AYA8QYjLunEWbFv8ARv4J9RESnDiB/wCkPPax + m9BcDXU6ykGNK1Ml/bmXSh53GbcBcDu68x5LqustAJ2iiyzfSAFdvqXE+PuLzffidl7igXzqF5Es6arr + DheHU6vwVbCusF0H4x6q6ln0A9ijhqC8tBuniXIYvRzMcB56kEuV3nEH2VXNMNWHa4bjA0+YpNHA1+0y + qKump1iBcogWVbDklnSpfsjcsQtl2pF0cx2FQvcEnz1iDeV8XHoxOkB3a9doGrIbeGbiOv8AqOAGjApq + WsogXdZIdkL0NSm21NQDop/mWkmNYjDvZUfTxncPrt+fx4NkhZZ1gIYK/eAyF8QrC9QyzaxCLfmdbOXz + csKKvVmCL6iGN8C4FcqgY4JRaDeupE928YeIBblm5kM8T95+80+CHZmHEUq7YOhCrW3bX3jBsQAA9bJe + lluEIhSF4YRTOqrzA52P8z+twFIUdJW0B0XeYBBQSvi5tQ9IGLBOTmKdqCbmuFjFi1iprK+ZjiURAKVx + W4llToFS3ZH3A2Uc1uWYQAKDcoBQesvb41TWcTULqJSmUVjmC4VUqE7K95bhQLCRCTRoiW2niMpYTmGh + gFNcxC2XvKusJzKk9O8CAEikIN7IN8WB7LNfF/KAIq6qDeSogVEqCLTiECt1EIUx+1iLgjmoZlUKgl3H + qGjuQ1Q4vZKIPbBbxMyAqNf7goBRBuNIgt3jpMRDlqIAsVjsyvxMcwKfhM2RqAkOUGFHOYmJGmdh4hyo + 4z5gPU/GZf0KiMXuU6AjeCYUUbK/3B0KbK3MgTBVVBUEs14jJI3K/OivMPFwGfMqarDeeYMmFuoMQSqq + GmzHMwNOV/ESSj09zKUmA9kaQSzmXVUUbDtBChSHsh8pYVFLrXd6ZaLddPxFZBvrHBsaK5hsTGI3QR6i + Ulf2qhkNH1rutF6iCnH5mRbBFkHUow5g7lCoylsdpW2S+0EyNXWogW9HRm73faXHAalfi4+oKbjuS/EG + JwynNjWoiyo2sBFoLmJlfjjrFqXqJYVvxLFiNXqA2i6hYqhxCtb12mariWrp7zXncdRZN/f6MW8b73G1 + bvPRIGNcld6YvQMnqE0f4qFJqhb4wTMCgcdyPgYQrPPeCK06sMaUre43FNYLm14ZzHLBneeO0tobtbXo + S0Tdeo2T0puUmvVuG3nv2nJAVV8xEWUhSo2FXf8AcTeC2/x1jBTF4hulYqFiwqv8RQBdPWA5GdRCuSq8 + wAR5mJTIvPEUhV1+PosVz4lFZ3FiYNy3EDvM+J/yD4EZmpGdQrlz2zCIaYAKq4nc4hSjghcDSOAyYp16 + v7R4nJ8IRbASghR7jBKCLUNxCjnwwbJzWo2iqu0AtDHQdXL02QwTjqzTCvEICrH6UuVGR88RIo2bvrcc + Kt/xKwFbjLg7xmFQVTy9o5WZ8f5gZS/v3ii81s7xELQZ79JSUyXniXYnY8Qp1WD7wjBd39ukUmjluOvz + VV2/zGNjbC0AuDpvPeAwytlXM2OPMVpTGNNFdOWDBdjfXtF9dtpZ+I1U0ZZcrMVvvCaVBIzEr0qoq9jW + VcRXev72iguP/DX/AJchAAcMSf5J3Padz2nc9p3Padz2nc9p3Paf9Cdz2nc9p3Padz2nc9p3Padz2nf9 + p3/ad/2iBEnCzv8A2xwFP3ZULoF2v4hLRZeVl5zatwrSUXVsyht82kREvChT2uVXes8wSl/bO59sK9/f + x+KfNfqUymVKlT9n8MIdMBV1t8VAGLzdv8wHFu73FYg43B16ecFeYhjzZ0cVLKCFN8XKWpvPwcfH4p/5 + P2sHLEuh55lYTlv8SwBVXplGTlqWWQ1NqCUpQGFyi+Yb83UHGlvFMYAivSJduPhRxaLljI/adhnaZ2md + pnaZ2mdpnaZ2mdpnaZ2mdpnaZ2mdpnaZ22J+31hChgv7wJjw/a5iQFV3fxAhopb/ANwpg5xxUoRwTMRe + AG77MpNCPTHuICGVIlJABO8cG6YKn4/HIv8A4/xT5QyIjHVLyHuMRW7alQtrWZmJ1rvOK6xeotraqWxc + r5Pwz/yfikGLBiASr8Qqhglq2ySlDnEfoykQQcgmUMqgChk7ipK+YPoYD8MayIGC4utHhURLT0g5Yek7 + PpKS09ILo9J2/SVlp6QUsPSdv0n/ADJ/zJwVbxP+JP8AmT/iTqnpP+JP+ZEopeUlTbrpMt761EFq7Ew8 + Siyw24lM3w9HvMrc9mZK40UxUB4OnmANNvs95aU8o6jcu11F27+vhqItjjXJcrh/1LtMjvF13jtsTDb+ + 0x1bZvPiJRm+Q6d4zjW+/SXdVffVdI00S+TTH0M1y9T7RGBdNoau8TErXLxL32B/eCHKjgdYjCXQLuWD + a6QC9IwljN6ibGwNY32qOUW95vrE4xyXRCypqq+9yg4LW97hoo1jtCC3i7rEYjI7xrpLugN3BctY2xIb + UcDdYhkHLLly/gBTBJKQqAi0ygDEsVFLlcal0Fr+YEinun7RQK2uPcQ8G8+oHNA39nv5ilpVCXXWLQDi + /UbAMhdRdau/NniKEc9eCEqA7nMBAANX/Mr6CtdZonTlisjQ0wOCH4i9DAmfO4BsYHD3Y27vO/8AkLAw + S0Q3FlpC0BTlibZAnoKP0MjlMMPN3+8LBr+YiLV54ZUIDWuKjOCM1xHq4f6RI9rdwrApOsGtVBxB6BtF + egcEWtBiosvZVX1gARRteKOKlRmjbHoNroiymHcVkAVR3YyJ22x8mUL7RwBY83/H0P1f/8QAKBEBAAIC + AgEDBQEAAwEAAAAAAQARITFBYVEQcZEgMIGhsUBQwdHh/9oACAECAQE/EI7oZgmHPiPUM+lS2pdRYo7P + 81fUaElwih/JnwDCZBZKNgFOIDSiFU9wEjl/sRLqPIGoJYgN4I91UG5aTR5hi9j2iDEJUlZBykuFKzUO + 412xNI0cwpMudQvhAPMqy35nUiptRQtw1iO0tfaP06eJQhbUl4K6L+hQSJyGU4jYYa8Q0VVLlDUwDaKb + CHioJZ87jXqR4mJnljKVwgsyYKic25YFickbymcaiAcHxLTcsuMDUIYBcAyhrzFwJcMLG7/ENbafmOuQ + 94BDDjZLlQPNxFzBeIzqu5cqFbWWQryTb2/QQCohi1SpiqCMLTMHKrLWi33BAijbBKNnMdvJBbSxzEqp + cvHCtSvYD4nEwrLKmF2EGvBTyyzLi9zLAtJc0MEqgcLLG0RMS6ngeSYNxuINUVOImtXBKmB+YUIKPUvC + YXL1FC2KheQtPvkK5iHaRxWbxLJK26XqL4sJRo9alTP+UezU9mNfh1HNrIhgxRsF81OSl+xMFBBXXFNp + U7yd5LgSvsAupeJX3P6+p9nZD6KAtamiLl+BHShTFW7ZRvxwR36IqIocq3BCrULOx5mMJgsYBpamq3g6 + itGf1+5t9yHqESpolniNceg0w/OIlPpYGVQLlFNY8cwBtIKKNETYY/dwQAwTci266iVaz+v3NvufQrXq + GbV5946LZ9DCJRoc+tjZLC6xKVoijctV1iDZUE8Tb7/c3+/0VDymQdB+4iLn0Np1qEuo9FZX0Ii4gK6q + vzKQ1sr8x4TergwedTh7rHcIkzdVCCmjcpEwM2+/3N/v9BtE0Q6tH79WQYAlh5MEAmJ4HrZx6Wu/W27u + OfT+33N/v9Cacyw7jSCYYYF6jlQ+IFyW3j2lxbuVAAeYnyxCRfxLKXg3N0SvF5gB/wDcwRbENb4jgE/v + 9sn9/oQFaYxYsljDLOoOFV8EoAp4vdS1s3MBE2oxGJGyCCgMJqsQQ4ZjO0Ip5IJRFLQpiwtTb7/bPXEE + gOD+SIaLmMYuLeaPbmUxEbjBhdYazLIa1uKCAMHm4p8L/Uo9CXEmkZoGCP0f1+5vjETC4W2AgDoNwaHJ + eOorFrbOpZd/5BfJnzMlMeWZlgBe4Nn1w5VgDy8EfQROGFMW4wLvn1/r9zf6JCyYIY8wSjfmAKOQhMZX + DAi0qh5iA0vg8xgBMyu1lRQSjx6OA2tRq4tj7QrxGh0mvNkQfuIpPD6/1+5u9DEKQ3Lh7iXpKgEXJGIV + Cq+leiBnzCFXSYZnbJNaDkI8oQdRZa16/wB/ubvx9FYuDKw2/aXpKtidxbfoRCRpDbqpQ4FeY9nTl/8A + IjLK7gijfPr/AF+5s9SIaHEsypEFNlnMRcmI4fpyX8MvAMe0O3CXiCUzEPJ66lfpe2e2e2e2e2e2e2e2 + e2e2XdPov3HXBnFRM4FgcHAD6RlFsXbqdZOSi5jqioE3T4nSfE6z4nWfE6T4nSfE6T4nWfE6z4nSfE6T + 4nSfE6T4nSfE6T4nWfE6T4nSfEQgNeJbzOydkt8zslvmW+Yzh9TLQExYi6uJZVCsb3BTLERaXMAFdxIJ + ww52p4WJIOokg6gaxmGxxMYrhmFb1CbUWobmGGZquUm4pSwLqfpegDTK+JjKG5WWTb1KXmQd0QxiKYNE + ouHeoMSW2VEYGBv3jt+9eIEUWjNRQBt27qYLWsY57g1bvswx7s2fuAZvLUAKDagV4l5AbHMp3Tr8ysi3 + WJdwQrEOCsBzLWll+I+y3eMcRCiqf5NpXzP1PQ2IKc6iDYEDYMGbiszNvXOrxK9K/wAn60uYmJiYmJib + PqNQ4nbO2ds7Z2zt9Pvnf6/3/qd/6nf+p2/qdv6nb+p2/qdv6nb+p2/qdv6hKmHqV+uqoBR6kv6SoWpc + tBFFx7jhViUoYYjf8QLWRAh5ellQtiihUFHlO03QvFw7XyeJYbV6W2RHAG1/wHTdNYilm5z5i87z4jWC + /wAwF2pOYipIpZUFDJKu1TMG4zXIDZaqJMbDmNEvVehfDqWyxiEXTCBdv+BkBKFDGwd7mAsYXCNLnEVL + SZIaIMF7jk8E96A+LviANKviUBSu4bkqhbKwaYcpmOZQ/wCBJ28S8ahiGgl2DawZrmJWYgUi5lwOVg03 + GAPHj0BqlvEBb0wuAUeZQaVuLbcIE01Ab4fZr0Zg2wZUyTrgtFEJDbHQZUR1AtB+eIxVX7RQBliVVftK + /F34i1QphpaYgOj06WJY/wAQ8iFKcTSSpsu/EvganROiKrGZXsSdcxwqV9CnSFeYw1hfHMpq58vEvUlP + 0xFMCMQoPaIiHxLd7YzOybhQ5ARG4DiCytN0Tihp8yqMOII0MEwxZy8QCagsa1OHiWGD71EBSopxoz3D + ZaodEDK06gts7c4YhQbFdXGMLW3MQPCJU7g9vcC01iY535gDNPXR7kVgLf5EReYgAuuY6qUxqgh0aqPA + OiHsS6sh4f8AqOoa3NmDbnllFizz4jE1VdRVlahNCz+SbveOGn5msgqAqj5mVQsjBGqlooniVbTjSzEi + hyROqm7uHdjMtCWy2+Zigr5CKSsv0oKXLHIJ4lTRgJQXBet3NoBGy0QlRdwNY7jVQuKwx4uAvJd3cvuw + RgLSqW3S5WShuOVACKaBPYlKkTBBfmEKC/MA5yRZclb9oZTEb8niXU6YMi4YKtB941IAiAafoGIVMBGz + 5TVncUBZmIiykuyUIkDUTER2mfmqihC8sFi+aiwu44szAKmoeqgjUzIpiN2Rq5cQUzHFqRAPmCliXFS7 + lmkxBrBLJlqyIBZmM6fWyY9QCeajddXipVTThuPC3huVRKc5uX2I07lcCVBtjC3Aa8riDbLOMSoiLiVG + TkYIlNSohwEuC7lKSnLLSo5qAGy9QRFM3cCpHcEUKDVRFPdQRSP4lwU5bhlacxPBBCxsbiK369LB6CZa + rMQDW4JaRMuvStrnuLuqxEGq73EUE2zdEWt8wZYxEApQw24WaZJ7pEAgloiJeIkDUFLqDl91HVMsaQwW + fuNV1Ky0hlxqIAv0Zk866gaNVXcLhvzcTFrZ+49F8TKOv3EMV+YcW5H9Rxt34m9d4rUu1p5n5ocQ2l1r + EBtvFUHmUBA9vxBXbwczLdQIOH9QAp0xSBKu6qfDX4uAgXmswpDOY0h0EFL1L0WtwUAc3FIPxMrbhDjm + CAOPoSUMTpiwRlg1QXEdkp2MwLWoeGJtNGuW0GYJBJSZNxAVMEvXhqCAhKuIaBMekV0LZyComtMe8RMM + VcEENyyRhKjUVoVKcGYFkiI0n0iF78QQ2mYQsUQauSjOIIClrePEorpLByQADEuKeZUbceIZpNRcN6Zl + W1qJEPE5vu+4QLYTNdZgbXiFasUkIVgXlv8AUMiGteIEW4ohZWXBEMrzDUeagZEA87h8wvBDmcwLD/hs + AAVazDxnxOo+J1HxOo+J1HxOo+J1HxOo+J0nxOs+J1nxOsnWTrPidB8TqPidB8ToPidB8S5GU+CdD4ix + APcWzF3VV+5YKNOw3KtBS9QOA5rUCwBXFRrKZBydxExxUKNHxOh8Toemvvf8n7kIKLmMugV1dw25WNET + k1VahoEGzEfMs48wRDQD5mGhS9S1bKwYj66+9/yfuStCNefaWiBoqUQruoTtYLmJaLjuFBgpSJZFLURN + eCXrp5xDZCB5jD6KXlXADZK8idpO0naTtJ2k7SdpO0naTtJ2k7SdpO0naTtJ2kBHKNaGll7ByfqZQrY3 + wRzFthT/AGpZRcU9y0K2MzAbdVLVdZmn/qCD0oG4BA2pqAoNkxqcemnvf8z0XBWlEEqHENgKxczRL6jS + BvfUDovNQqUblZ9DT3v+VrKUiiBcbo35gwB+0uVcU+0aK0ePMWIsLFqPKKAuBpgAiuIltJRz6FTYEbzB + lqfM8NfM7SdpBWrJ3nzO8naTtJ3k7ydpO0naTtJ2nzBdV8ztJ2kRBUdw12N3uHmFXdDLgJVIwrZMlEyL + DZ5miJgBnmPdpl3cSNBXd3EIWMFbngOg3COx6EWlxEErijBuEPM7hvF5leHtDdDBz3PZSgzjjzDZXNcQ + l/OYEwqXpgFvxBgDzKMIWbJeULVmrUERGmYE+I1MUrvqYuEh2VvcRAKuxmRyrxqCivnPc1tc1XMrBwnc + vgblK1/IAeCzKQWWpr6KGLFnm4qEil8pgyt1gIHodRBpbYItqJhXxEW6/wDUtQbviKguswFpdOJmr/8A + PzGGxjx5hcFWKLZV4qCmiibjZGWBoJfEzC2wRE5Zbq73FERixVincFNMRq3UNZikTz9it+EVzXGpkG4d + L+IkRavcop3VXCobgQGtVFNjcuku1gULKMdwLCQDSm4lrW8eYguctQgKUEvN6jiLbcYVWaqGlTB+4QVp + OPQPsf/EACwQAQEAAgECBAYDAQEBAQEAAAERACExQVFhcfDxEIGRocHRIECxMOFQYHD/2gAIAQEAAT8Q + /wDwzsRkDrdiQe2EVohOBiVOcFT3CgreI+GFeAIVUXlfDHuYp/AAdKK2BZcApPBgwkvFEo76J/8AYFWo + hPHR+cIpSn1R0PMphAgk+YoAXwCYzdD1AfK564/OBgCoxQ+WFRg0AR7h49c2ewBixvZmr1X0z1l+MvQm + I+JkSfDjL8fSfrDEc2JCgiEvP/M09qCwznYTHoxyhFLscO+Qxj6Z7z/WHzI2iivEMeTwgqCdEnbJ/sfr + NW3iA+qfD3H9s98/bPfP2wQecqivdHXwJQWXLZJQKoCoa8M1Xf4f8YRPFLo2ckUc9ifvGGQXkKX4LHhS + kKwNddOTyyQR4Vdnhn1z5fCe56GiUQt4zYJHBUK7WcGer+7C4SVj0fvl7zsBsCzjGBCgA2qsAz3z+s1N + IFVvkJvFJ8BQg+GRdBIfFZjTzmA1As+3813NDjUTSNvccYP1DBYIK9UmSxDd6yK9BrV2+GQ2YIgiOmeG + e28J81sTsJ0zk9G8rwdR2IyBgAFCECBdm+merfxnq38fCksQ5Qho3Ydsgys0oVaEOHD7BpZgCDZzzxgD + 3ygD5CM+uPTloCL2oJ9HGvlM5EYkxkmgTUOyuv1yr4oQfMA/3BTFhYDOQdHAVGMVAGVG+mjNDRLVE7ix + +e866gKcI7PJG+GJCDVHD0jzVypZG7r28M5oLIGQrlO+aqioAQQZF7421BACCdGpvCaaKGAdVF11hOJo + EuivKY6wgSGgvC9vhAs6MQ5uqdxS8eGAWyVRqsvGBgIoeyfBr/qpSB2etyBIyuzStM0CmoDQQ101gzMe + UAB+fPzwwGASkKKE1x985UV/NX+JjpS1Q0Fp54+OgoCAs2c5eRGBFILpdUzwvQ8c8D1PHJrB4LwWI98B + WJQAgKFL2mIiLRYCs12XAN9VFCLdC9M9vwYfwMCxoKAlMLboDQoBn2yk6IBCC8Hlh6BwIKoDnzwD0HlA + BBerXCknZAx653fzGm0KASJfpPnlY0KPFKNny8nBUgJKWvXXXtj389QXpe2sj5S1pLuXneDesCANA4+a + /LngJNeWCn+2CGYAZJx2pc3oQrupQkcrtwEEQkOlVsO+b6u4/PISVoe1UWjvRiUygUEGV8VwqgERKXTx + 4zKUBeoFQu+1uXKakKCjXHGOh4D5iP2yrLWOSGvzhZdFNh5ac5whdo0qz5s+Tm0CSjyzR8h+r4fCkoR2 + +mOnqhFKgQXu4s7woMdijpiGUtXMYm8JG9tQpeMFC3QAqMGd4/BPZnUxvKhVcrV5wyGoDWkadcG4eHr4 + fB7qqFbvGtuAGFFOpHjCevRLzEuCEAinSHE1gCaUm+WBTwDD1XXcAYD8jARDDLQcwe7/AO4GBE9gD/Jj + 1EbQV3VN5S+VQsFZrsODKSCVaCMNjcC0kRoR5GYpbh6iH5I40OIOQLS9cJVzaAO+wYXWc4p6vZN+WHAd + A9VIfdMY6ApokegYKGxQqDhagdccwlBDYXWgrvwxNDTDZdKIfCr1fu/n9gB4vGSxxCO0NrvCQsooKgCl + dGNiAUHEmgnXEFw2goO0wAJuDQV45tM9B7/ABPwCDXkXCAPq/HIaEnTtM1egUBTpy4xfUfPGtigERHiJ + 0xxgwvYCpZ025UihFcD0tyzALNoSj16Gehds+z/zz1Xvz0PxxTykRexR98qN0hBy0rIDxlfAB6XAfNdv + zxEltuw1k3Lgb7SFQ6ohwdT4MAiVa7SxtPGYm8sCrEQrrHeYAshTgR56YqjXAChYR3pz0ruZHqoVCxdJ + 0zdvf09cejsaCBYiuDWVk6oK6cTaC8IqfVx8MtKg0RZvZmvUDCDd6O/i4fr0K2Dt1iQBMCLtFGUbirVq + 8aIX7ZVAiPAxPnRwYEVZOdF+mL0ARrU29ubveEAk6Ogbz1p+MBwlG4IJUDhvyz0/jhCs8Z/64xgoqzXA + b8hwZ0y3FJDz1fDywXu1Ekmy4FGhkgpoHqH++XwRYIsIlwPi8vywOsoHiuGKOGOUQX5E+Weg9mer938y + ECW/ZV++sNuXYaKDMMnDFO1R8m4BujEFXK+OsKS3wkFQW91zZhJCReePhnrvfN7WKPF4sNcYEAGdPYz1 + HfbGAIEiRGGSUFdMFGhNJ98LaTU6XDxx38MCdyXQHVs4wGt15U55+uHT+kYZUamFPVZoIZu5YGrEU844 + oBKVco5HLT8hIHSgB0ymxwcwBl7VfhoWoT0HKeafbN9wJ0SH0s81yaayq6NNvScYSxQEaIG+f5zlvZ/j + 8CtOJRy11MRBX56aCfbPRuzPSu5nrXfHw5VlQOrMvdz+ZmnpEYaIoSi6eL8DBAylOgMIGjWHEhCpNzc4 + xpJ8QFIjxz8LEN3Ig0Mhee7CohxDou0fkYZaqqK14ZRexTmBWZ08DceOC0It7LnqfHHhmvBEPBdP0xCr + FagCg3KdMPDFNVRsQ+25jVPYIB62bT5GGkdSsp9nfBcDhgIaLeImNRU9JiSnibcEQQ5KKDnBPQQpoKNW + Y+pLWsBm3p9v5rWAFUHiHV39MkQ5GoKV2HS5yR2Z4bFRioIWKjvwTFVakUJnyx3eNUAF2mrijEcElg2a + 8c94zufW/wDM99f1lNtPN/We8f8AmDamAtVGHGJzQSiE7Jh0j+bEZ3lEfM6/AQddED8jWMup5sWozVFP + irtxIbAMVC7QOXECqzECEKpJiBVFK7VavncFGyCW80EfpgJCot4psq8/5h9SVOAoriXcBdsKzXhnu795 + aVSAGhKnnhyy9mIOsNuUjxxFLVnQ1MEKCUXm7qZVFp00Z98dfCDKiGzxYgs0RdgHfA/1P3jkwAA0Tivf + EkDkC1R6pqGVd/RfvGDPof3l3toiJEuDRW0FJQHrcSitW1crh7nx0ACr8sdjAclRnTPwmNuQCICch4Y5 + kJNgWqWV1ljqGBVDwHeYXNrQAyGrovhg+TRKDvF1ntz957e/eexP3gEhSCMeKXNqXfAVh9VxFBAjUAvT + sZVcN6YKQHOw8MnnWBASVUOj/dH4Kr13oA6uXDvBSOkXjPo6aWa198SrTCTSXzRuM94ToG134Y3XhMZH + aTw/yY1obRwIC66rryzp+Z1w3jx1iG3QdQdZeM3neOoicidH/wC0LGIA8CH+47x1OydR7mEmCjbD3O54 + 4d/YyTjxD/cjYJ5aWhXgx2VVUNg6AQ5n+4KZCto0aI+JhtWZf6L85dSdBwOgeBjLNCR4tH/7F3tbcXnN + HzwGEEGxOyOzOJOP8jPH4RNlg8s32MaJ6HGuHY0uu+UCY8CdquNkY9AH0mV59LyxqABQloKdW4IGsoJE + iapAdLgJpikCgDUThx67yn0wJbzQB6VjvrJjwJfCEbEYdv6kyfG+GUymE7/1gy0VqGggj1/j+5fli+vy + IASzYYU77nGcKVHgnZHk88iGGQSNNFEZqYixqWqArDsYpFZsRbSHfAmAQKhORzrH309M/WbzlTESg213 + XDK4lyBCw8cimwXjQq08MCSALSRHZzpkdoZ9IBsgRfHEkpK5VauOgaDpQKIKqdyP80yZMmTJrbSBdAKC + ryv8J/wuRkZGFwjAPLiThwFgdWKh/q8mEfwkM4tXZOz2TZioAniGLdrx06p1u8Jck8CIBg/4LleMAdIj + kxfsihomeYXffDusAIAGgMD+Xovb/wAiwW9wSkHhd4AvZRj7GM/ncv1iDFROg/6MCD7RQv00YKv2k+rp + mpLul/0xFQiUF56xDxUZuoWY9efn/V5MI/r9c9F7ceX+bgCZQ9HYcB3XoYlGczcfN5ftnJF3AL5vOK8z + 5Y4mEnIg3GChUEFcei3u2nyyFXR0xXc4OpXTIequ1O7hg/ihsgLYOpepz8XALIoSikY0ddfg8N8Ax8Kk + NERiJ8NF6WCobXWKRFFRsT+fJ/ZGD91/x+M6/wA5MBhhtyDfntgcwNqqruvXGZA1JgSp/POZp3OP4ipA + 9snUrqB33mEnfOENfwAuvtmg6r4GP63rxkaHPGnq4cN8bX6rlr7dcUVwooYO0BK+dMRuAoQgoii7m3Xb + LlhowgKlAB5xXlGoU0oPoA3dwImzSiuktfGr+sqUhoIoNDXbiK5rZiqwB388IgWXKQIX5uJ9SAVRHU7g + 4EsQpAZtvO+kx/6jbPHCNrfHAFBrwKiB04+HJ/ZGa96P5/4QVW9MG+dt3X9GHhl8b5mHcHzxSiTx/lpw + HsOOh/eUoHgryenDBHT/AAGDEYFZuKmzuOsvQGWKiqagCeOHfKIgBQM5JgiECII83Y4ObBpjNkRd9O2L + TwqhCIiPPNwS5FMitmz6nEBhDVRtNaOdn+4HCNwd3xTWauD1mTShzDq+OPG7yBuRDoP0xIwkmXezXTf2 + ynZ0qMIRen+mIgNgA6EoXHd8INCJz55PD1XscAGg+HF/ZL1Pt/mosQ7sBfI2/wCZRUYpyO4eM+uDfg8f + zIKBB/uXU0jOtc4R73PfPlHxrnRVKOzHeAbcABQs3yc9MVVVq8vway96is6rtgw8Pg6hlpuKKDybM4lj + sinDF+Gg9AIUODblBCqJTxUHGW0FRfNdv8uL/wCAQSkZqkRm+Kw+1wRahAVRkDrcRFoNoUEEqOnClGhC + FFFPDX8ASCKdLv6fw64JE0k8yY3TRemr0yx5n9Tj/wDgFFAmNdxE8gn+3HFgtdolQeQaeOKMQhXlG+Lg + k9Y85X73+BQ6VyBN2cRyIDepMfIcerFwkrxfj/kf7nYQivif+ZYfG0m6Cr14MkSFQkDqjuYoljJoZY5r + fqoFToV5xYnRAGEUePExU4OQieY4k9YD4F6YolAOhfhKEYCoV6YYGOilIoxm9mIcDvQuvlnRYlgX5nx+ + 7Mf4zhCOyPDaTOP++UTln04+n5HipX/ce1ec8Wf4YadDHovQf6/LA/hX65TgrtHYN4qcxzUiMA4vGOGO + p7Ltfpj8PKX4zj8Bfp/CIfDWpzxFu+NGBcFgagtqaV5fA4mTWYjqydF4NnHybG2co4FNXtD546jmXRAU + m3c2HyxupSITQAceBhhXhJaRx0OD7OX0obhK1MkiA9+mDE4iCJZpOechrwpM0htb354nfUHEIThE1reC + d847A3FKefMMqMLU1YNmdjrXniAsehqgK2ybuQZCK2CoU6mFDTgJibB6pDbHnE+xSso3hZnF/ZD0b0fy + U0xIdhfo3haTwONXuZXWqhKTXZhbUs/CczwDR/GWJAidF2v0mI2VOXMJOnddn2nwQi9C4prynGhUOrw1 + +MgPD4ksolMUSDxV+lxGaWCooVKD06G7k43mkygQ1SdOMlY10gQm9Bdb8dY4ANU0qt0tavF+21BwhR5j + tZPnkhoRjRBAOY1emNcPXRUoHFt6mNW70Ai8CnOT+9jCLFlvQGp1wCfhVEPG9TkF4+1ngIIwgy9lwuJ3 + YIuqu7d4ndBdNNavbHV0w5KR+zhY750VClJK73cWuuOn/wAEPaIHOAO+UMHAi6g6o3A4x/jIHX7ITE9b + jzQdq/4YTQFA4A+FIdj5YfXx9XRl27Vb5WGFE6fwjnGoFnTqmLXA+ECJwEjyr/E6/eEV9TEPKhVWE2vO + UAYUciOneMIVKq7V5V+CyCERRlHkZ0+KXT+wJuGvB8v8hVjq0i3z4+5hEtAceJzgYSBJl7v4x+BGSIdx + yWdN8QdfwGPiXQCjgqml7BlAqQChtQmw3WNCIHAKNOakJRiKagNp48ZqguRZTmm8bPk2dnL7f1Eun9pK + /wAHaxVGoo9nplNbI9k/ZvKkUD1TrPliTGWbgPGnDgTxKfEiPVHnAB6KtRcLiy8khePAxH5oKBzROnOW + 6CFu6aT5YZa0ykVCnezywIkYCIDRJzODnISgIqF+zHOSRGho/H2zY9dfAI8dUvoYMjgB8xSXmzp2xutn + NITpO788so6KgPNWZvR8IUoxaag87z/byyjoMoWVlwbqEBtQePgYQwA0eHbxmtOcyJbojx3ydK4VNs6z + J3GmDaoDdcn3Ma2hPDJ+8NEE0uAWVwm7IFlAOll8ZhWqxGO5sD85wei/2rq/wmTDQSmRsroNH4k6YVse + uyPUTo4CAK0gtxl7kL9prOgB2BhGgx5gOMT0sozR4GGdJBHmmF3Q7Ip32514YgKg2gIAjr64DxW1GCTz + wLm7BPUu67uLqgoDQ45a/HngFtWr45sHZ+Fo2iiTu8O+VUDajg1N8c/NziJZ6grUTo9M2G4A5hpr0nNH + KrYiRVLU0qvcPDpiE3BXUU5Tq9ZjzvWSiFYdx0cHXAwqyYkrtYbxNf4PCvDTPMT/ABcrQpdSixp2fM2Y + 5kmQw6gHFh88UjophNoGJ546UhXAkom2V66wsqKECECHHGDawkqEEBaHj3wZpikTG1U7aDfJxiKJMBIF + DrAfnlf2e976/n/CGK4cPFluC2sU2rk7CdzJU+PoPk/vKYg9UJ9snjk8c64Vyr2DKyeIAnbUlcC+VSCj + rVavi5YZvqAt5DV38sLfPRESE/V9MUe+JKNRBQfS40jNaI0IBFvTIXKSuCvWzOF5E/XwMQ0RGBwW6L25 + 64igQR+dm6Hh98a73AkaOVjL3wyaSOacIBeeq78Mp+BZEDONsi/N3xkgYNiKRMKS8orOWlDpzgb8mNoB + QVzkFti220wdMw0sCLIhGA6w0itNFkgFoy74zUCqCWAtXjrorgFv6UdULup1Z4GHcxUa0STwd6yRAPDB + wkdzoT54k/BlLOFIVLoCHfjE5ceLdqNTa7P7KvTCH4b52+HzhgqsEXyLh2dQBTk1mjz2FPqZaUfnmjTn + VL3xmEOjg+rrBjwKnee65Gda0UDVQ79MLshUUc1MNHOuiJ3vGVfRm/65a1cCLCpDrknMoCNkLTu98d0Z + 4SnYF++CddQFTwCV+2a3RqywDg8sK3aDxuAFeOOByia5KAFetXpfHHSccEBGP3uB118K/wDytXr7H6fP + DOB45WkrWu+nA/C14PUfHBAN+HPmYlA5Ko/TPlNlNvyMBE3xb/3LswcxPvlIRYBzWVUQZYpoeQXXlhkW + gGp5Y5TjqEh3wWwGkAJYTwwdzEQcigngzjAs0BO8nHgYa+gvklMoPQQUqbs8cRIDAAgEXu4kmdQTjRx4 + ucX186lfxhEptd93v98H86hyh5swDwj5I/8AxI08S/Jr/vwEV74aXdH2ym/yJSO44RLEKV9RMDHxig+Q + Ztd6j6HBCBkAo3XJ5mMrVDl4DOAK62y8t9jImSxxAAB8qffGRB1Yy+FNMp5Q6H+44jrDOntJ+1/GCqGl + HHCJ9TFM0QzxT+GSLGhfmj+c7nDTnlfkwVPzTVxAKpAmoeLAUlO0AOtY6MLKh32b7fyIIAdQdSZICttt + 71udE8gqh8x3jYC2k6OkB/uL1GrwU+jgWG6oD6yZSdxK/wDwNdV5P0fChdtZQeL7GMxqqoPTXreI2jBw + fvOT54chBEADuO/1mQhXAEP/AHCx1iDmXuGap6EVON1mUIoQCQyqTlrMYUqwKgA7aRcrHxKIDBi0roym + WHlY2V512w1PiZb00l7UTp55tbtevEXHyw6rQ4dhR/OecwfNH74qO30hx+5ATlYQDzcMIJdDc34n+YKG + 1eD/ACYv6GS7un8mLAcrxgs7aGS8wenbCQSzlW51z0CGc2TsNrgcroHR4pz88aASFGhuAf34Vo7/AObD + jPu/3klpueCjvBjR9uhmkOr2xLvisrweKcvTJf8A1l8VduIdJS8MqmRqunlhxeQfK5Jso6HY02nfBDWw + QVcCTiHHbC36wIbUTjrlzHbCl2vSBowXDxIv6YDnCbsUCa34OuQB8LDjp8TCWC6lXew+2C0KphVQgHVw + 5QaOhSa7sPlhwDwsC/U1nMdmqP3Ljk/y8v8AP4uXA2rQBlzoo+QjlcaioSnnqdc5mWwq51pwUI+VD8uj + lQlQ65+c45b517BMdthk9BKD9MOP7y5bLx/m+H1P954zH1DlpcPARCJDOIGgqFokO2WwBU78B2MEiG7t + eXAhp5ds5spU8EhvxyI3Y0Xrm4X5ww3z+Z8J/WX5GWTqj6mCWCceAQ/P1xdxARChAvEGGMxUoCdTR3xv + xwIkG3kSavXphD0p1yHXCJmCdDAHX6H8Vj4QqF0pwerjZN9zU6LU8WP1CENASqHBvHJVDYeau8nIehsI + XnT3ZDRORAdgA48cRmL7cIc6wPRZLQNJwiOLi9KnQcf70I3dh+zK5ycFRLTDVbbaV8hxa09zz9XDCEmG + BjEzZ7gPIK4q5x5nTNVb2OeCzsHwoPhhbUXzNYkR2pleohdCNE++EfGzHRAUHO7uhXx5yjm2rr0mvXOH + cUDU6YYmB/Exw0OisuG+BUOZgHzecEOwKCE58AcHdxLqAheRXB9P8IWgE51hRAQTwnKHmbMIBBxzKB8B + c3KOR3HWHLUjPItEwZERdm6A7PlhuqA/3tfSe3H+IHwSLNRG6Xzf/MeXAUa3cifAmwV4ZpMbpEaDp8JH + paf7lDkmOkdz66wz5BRsOEddZGyG6v0mOCKbV74MgmB/KYkRucgpz4mFmWFeK1SYlkKJ3T7OTCQE8Rsw + 2VeAnLUaxxQBXZyabg0iWXTVGb6zKOeN5wzi/iFT54dLD83kZu4iDjQ7DX97X0vs/nHm4gN5wQaSfjFW + vJPrrOucBkgeAA/GSi2G/lrGlboR75EdKT545Gu98Hf4cYXUdnzwoaPgQ/nxeReI4Q2dploP4wyhCO4B + R2g5EyXcGjydPnxgqx2FaHSdMXGYTdDgTq+2GwGhICQhtcDARAsGGrvfGJDsU1OW9SuSoAcuxp45yZZX + cNf3tfV+z+TgaXA0uMgsDaOuBi3TnnDjPJTPu3LH6M+pfxgIJSHLxE7A244JU9wmw+2Mc04+Rx9sMI/8 + Qa2FeTlmQgN06Dt3O+NyEERd/UzSwdkWc0HKowbKU8VufPBrMxBSireq4eo0gurVGh3jKWKw6kEY6RFJ + zxWc4msdXmaV+MA/Ah/Hg/sj6v2fyPDs5N0F6B1cHDPQv2sxrRdhV9nCivU4zuJz884d5Jb2vNa/nIF3 + PoKYE7cBsA6ut51Fo3e8Az5YMB+W8naG2tHZ74BWg0j0zzj/AIkkLc710Adf8wGR9FwQ1d7cKX2PU9K5 + LNUHYvVJ+cPZQu2epV53m9I8CTXFw+jtiYvju4uHApoJ8xwxKquwnjnP8eD+yPq/Z/J7Hh+MoXVbeU3P + En0zxn2w90vTtlre7lV+M0c4hC8n2Rw1i10e2BQfY4zqzgPgAhC/laP+rhnyf8AMUCgG16GMqFAORqdG + iYhSEBZt77OMeYJRudFJvm4ZIKqcR2scRdIam6F75M44jW9w4wAkcYVBQ8d5yun6IzVHRyQb3BwHg8OV + tTqOkeydH+KTxq2wGWG3RiJ/XeHDhw4cOHDhw4cOHDhw4cOHDh19zWDN0qQ0xAlNP8hw0PRQieQJiqAJ + 0Rcemvy4O/7nOYPUAH+mI59SVc64vmhNTFwKdFOeJ9PLOfpYtAjsH3G8EGVbV64Yf8EbYgrKGh9sLO81 + g5UlHWN8wU2XqPniKi9LXQBTwwFp7jCeAYYCAggU8BhqB1FczW8mWuGU6iYLYYgI2KvDOMp4xoTq9ZkH + GKrzOH6Z4DI7mfPPnkd8jvke7I92R7sj3ZHuyPdke7I92R7sj3ZHuyPdke7I92R7sj3ZHuyPdke7I92R + iMRimKYp3ynfKd8p3yj1MRszwcv0zwfgENGIeTFeCPhh431zz/hgNGH87wLAOewZqAehT5rgvQBgkaTq + Tthe0ZxTwzsHfAibnwmE5q8udeMXTcyNck9UcKZDJkAjMhGKopnHOGh2QQwqNXY018Ce1PjWvtTPamey + M9kZ7Iz2RnsjPZGeyM9kZ7Iz2RnsjPZGeyM9kZ7Iz2RnsjPZGeyM9kZ7Iz2RnsjPZGeyM9kZ7Iz2LnsL + CSEOTJH8f/ZznOc5znOc5SqzmhzeydMKqp2CfwE9yJ8bMC5wf8A/+KfpYXN5vN5vN5vN5vN5vN5vN5vJ + skV58fw+3f8AXwHn/GfHj+R/CfA/mE+B/C/xecDnDjDl/h9vhwfFJEOQrMogyVWi5o78o8EzmAVCgq9C + 4SUDBUriAKEeE+FBKg5cGRglqzKZcuaPt+b+H2D/AKwi0GgOVeDNH8cvDz75Wkp5QTkyg9q4VckmkKM1 + vvhDZjIA+jkIaXZo6AmB9BbGnBHhdYE0UeauLHYYpIcsDFkHVCVewBbnTPCijViPHzyKhVhQMiXq8TNl + xwUs+WICVkgU52GBw1bh4Fc73OXvs0lxQ9C3F8VCGNUVpHUlg9+2bOcG4hy85IiZGIrCzRjQJBVKg806 + OV6Q8VB1Jk/QMIGl3XFxGogIizBiFkayPMiOdOaN/kUxE35GPKvnjeFoYSSD53E7QL0QFgTJRKrAUOZg + nEaiBLTDnlS2IF1gt92NNO5hsA1IIiMaZYCEJAe9PbBMxdFWeBhAOsd6dsbK0wCvBcS4BWa264gaQBgC + 13gd1EAVRYcGPtlFFEls2xQEYDyXjJ6yomxPMfh9vhwfAwlXuDTvNNIp1l4ccKeXKV++8dMAaSGnpvjL + Hi0AByHdy2Lo5n1WYaq6Qkmud8YtJcgaKh/zCiALFv55s7UaUd9DJGoOLO9w4+Q/U+HL5f8Af4fZP+sV + EnCbA7DIinJL0cTLaq6wOLn2z/mWkQium5o66xAekurSQecOlIbNJSngmTIL10CUj0TLWghSaHgdGCvw + HbxSzKAEhJoh48cCkjIrU2J11kZjpgQ8FxfHJYILeOFTqdnIoIVxNLZciciZyHVs6YPwUpb2105+eDKT + vG0Ag4FDh0qIlA5sMTpRl4EQDwvXtlAw4QKQo7l4xWyuWkAqHiS43hpsUVgr4GCaQ0ISgXRQ1lgywuwr + C/XAkhFmwzY5xHdgQ0RaTmYcstgQD188M9YEN4z0xWd9AiFNeNdcCGgHAPNHKTppks3rzxBYbbOFZ4Yt + sRN5hpfnjRkVMLW1xx5bQLa8uDFoJCtTx1hYp90ViIde5im7VGiWfPeNVdqNo8PhciuX1qDPlgIkU83i + H1xSURpkHU83FkWzkrKh6Z4+YtDy+L8PtcOD4bD1orl1cPyJo6g3DrcNh+VeNOcUZkEpt4HbNQPAMF4s + 74BCJEApzUxUAWSB6ceGFArYFLU4/wBMQLb0DCWs3mDx7ZYr0cvlMfhy+X/f4fbP+sAIlxIurY3fjiP7 + VPFwV1xBQU5TNPDHQV5R67yA0bKIaa4wfY5nghYdXG5BDeHUJ5ZOBpANBw3HjaMqjuI6xvxpKbuVvfEN + qCGqhrXBmqMSJuFs27rgoSZI6O72rglrRpRTWBvHA0qsKtkd43WkWbW88y9Mi8CkYk6mtds6tpO6pEHa + f7kdI5E3N7PDE2CzI0Ig77N4VzWPdVaXL546IshlkdTgvTDIywYxI06cYXwwPshxj8osde/jjalGtXVP + l0w+lYnsRaJtxDLMDbpGR1i4PA0FIt6zAbwrRQ6BjnDfhBqefXGnTIuGLEr4Yt8hGkeA8j1wRxmbk2qd + HLojU4k2dtOXSEEqh6PfOfGmphE2aBxbRMpR3X4w4dERWGleRxeLh2FeWd5kIJH5Jahelw35QpgInWZv + 7VaglcMjTaT5Hw+1w4+EEJ5m+uNQZ0G4WuzfOXRPKIOpX5Y4FIF6tawrb4CHUp8sHl4IKhxPLD4iATQu + IMNjgg982oVmt3Dyu2PMOOHFYSHnEinw5PRv+H2D/r/5/wBv/Q5/Rv8AgPQvR13Uf/n/AG//AH5Y7lEP + cnP8AyabNg7JjD4ooPlUc94w99w99w99w98w98w98w98w98w98w98w98w98w98w98w98w98w98w98w98 + w98w98w98w98w98w98w9J+2ek/bPdMPdMPdMPdMPdMPdMPfMPfMPdMPdMPdMPdMPdMPdMPdMPdMPdMDY + DwV/bPfT957mfvPcz957mfvPcz957mfvPeT957yfvPeT957yfvPeT957yfvPeT957yfvLDCi2y9po/u3 + 4X1cvq565z1z/wA9/wDCP/wA4QEKI7GhiGUSI8iMRHhzaAEOonJFHG4gktlkuhe/8y48AOko7cSrQ0UC + dxGf9N92b7vivVhQG+1WZvIhe0fP+RZQ4FV+RvPVH4xEgQMR5E/vu6qW+Gk+zM31Kcx2MO59zIXN2e5r + 93GC28Sbl/z4wkTWhfsKAjLamCzmrTdtt8s9UfrPVH6xX5JQCgQ4xC1YQqPRpnpT9ZrwjSxB+mRiXNOH + xP4GSr1Q5k894Mo9CKnnSa+O3ocOIlABVTONwqkDvBwWuQQZQRepvIvggtIPExMmgR0gXoYD5r4KHW6y + teqZ6G/GKk07N+McIRyv6s0xxARnmY8mCgNVmgDnEV7Rebv+/ERJadOkHRxEgYVCyxWJcIUKpNU52Zut + VRodOXPS/RjyWCUQFg07+GT7X88T4ICCiB0j0c9mfrH/AMf+s9mfrGA0rLGvtiY7G8+xf4/gA/hHsFD8 + 5d1BHxSF8j/fjD21ToET/UMJgJLzkMsV7v8AcC9KBVhsM30MBlId89O7Z9yz/TE/gFBKJTlzx/o8cQmx + dFQR4cLegUCtz1h+cF6/R45WsaNMepr+/sMft1AEfoz5Y86K0e3RzZH5ZsEoyNaFknlcaoaoSnkjvDKB + CCgXZrlmQTaKIu8/L4AGjdEQg9Zkq0mxGe18IjVNg+ThKr0oVOZcP/D44+mZ9HiNxSkNUVXxXCwgwaLe + lM9sfrD/AMd+sNCMgAAHkYpIclV56xk+k+WEGIDn1wgryFCBBz/hlTyFqlhrV47YtkZzUl5vhkYGl2r/ + AJhqkCl2Eu/G56N2z7pn+2AHeJrQBzxMWjlC0NS6y2PECs8MAbfgcqrVQjtuz++l0EWI0LUTt2wmAWUQ + DBDwyHP1X7xZWWSMc5ZGIKKbPDBiHkxbwXnj4NHE9xIANpzc9tfvAZBIiLtePnggANUraeJOMEX/AAfv + D5xBpiTst5+CdQKC2vg4ubAdr/eHlBQhIurt7YfQxQsLv6meA+v95o/Z+8ZNqie8Zmqizfu4LrBJEIDk + HnlwvASh6kiZs15UwASkpBQuendjPvv+OHFY0CrZ1z2Iz2swvWSSEhOmLKpnkFuH/gme2mNIyYAJFuvL + ++64rUel0PtcFHoO50v4w3r2wugKhpTxwa6GWrpadN/wkcAO5QU7u5GA5iwkY4DU19MDpIFWCFInfOtF + bEs1ZwxoYQCbUG1e2GNXAhUkyvLHceCuFQaF3iBVBSKwX6XPduafz8tZyo825RGbHALtYOSIQWQdgr9+ + ueVTWzXXeRhtA0HPLyc+OPno2qYHVz7/AP4Z99/xwCQaY0t4TuZ6C/Ges/xhhQCAQS9DBiU0BOezh6E/ + zN3pPpg6QwFQJaHj/fs0hN5BNfIffJLyzuQn5wP/AGlKOrpF+GlTThvY7OMgAuqpUuET4GHCIGFaN7c9 + lfvPYX7wBEdQi7Xj54IEqpA2zu+GPFAUSoczAaZACihLz2wioGBLTsfALFBTyQdm/DBIEJtqGgH8YmVc + nurX+A+tzF30rweGEdTQhQUjtjq2fqcj0wJETTS5F64EmsEJxvfljM/hKeL/AJn3H/MQFnwM8O0NEURn + ljAQAlJBOvnn3P8A0/8Ag6HahsQ2J1wAAgOn/pgNUUgQAV793FuV74PKB6AsJXBrCEnOMkaEpHFXplac + 6VbJqJ8Ynz3/AIDwnv8AwGcl4XIPVhShAhy/8DEyDOgOxjLYJAdk64BzWGmlHDo7fXD80K9hJzMPQfrC + mgppAm4Q3l+DiWwsSmzRnuD9YIulBVGyr0s//MvhXaApyc61lJVsBDyXfXD3yompFO/hnuD957g/ee+P + 3h5gUDREOr4/AA0JbGBrfm4Iizs5XR93+IaiVBEqGp2wxWgEVhdeePSSBFXqqZLVak64gCeefMFIvy3j + zUKRGNImC6li5AF/2GRskcBTd67DgRDoUZO+sKKl2ki/jFjTWkWZVK8BBeynD8Iw1UIEsNfLKa66t401 + 88q/DtRohzPHCBQdS78eR8EAVIGDcem8c9KfnAi2XRIHHFwbUDYMdQ2mervzkAfbwD55YaonMYcYWWaJ + QUusCOosVQ50ZwNiDgu+mLabPE01SYmo1OfYwuKqLE8BMORCCbdvPK/vfvPdX7z3V+893fvHCmLEdpY8 + mcrkEEWz/M9hfvIHfdsqFE55z1b956F+8sFB3Czob5/5EWjDdAOm/JxafbTY8jx3MbnUAAWrtLy5wTHk + K4KF7udJEucJA58XPE+vwwbpbZIKLoN8YTX6n9YM9YBofMswzXBR63TAe2FkPUUP2yeWliE7xwTaVsGo + hud84o8Pm5bYFFdaD/zDKqB2rk22DwaKKi2ubduIR7CVXLS5AgEGMD/M4hKz88kQ4Tzu6fQMFzVcFgB/ + rnAXxJBAgI9PDL1dGUHUpp54VGXYgCEFfnrB3UUfTjKDVKijTTgWhq0NBAK4Km5TVruxZgaa3OiJqfPF + ry3GidnwcDW+G2jMreyCcDuXrhTfgKmwvfCl+0wspBZQZuYFAAhxVl1TKMxzuB3g3CmgI80uu+S7yDhC + JRO+UoEsaYiMcVZGgWuiaxLZEJvk9nD12LSgZOcp0gDRKk4uUNLAVbyRwiqcStJCpvHjN0/1g/Gb2VBd + AHUMDLokR2dZjvXatwFNhec+Un/TPvP8YaTWnYCkOkxwproYhevlkPULJKDMWC1IqN4b1rPF0Z0oZQeb + gxrMeTcB4085baA4fBpjZEoNhF1eif5/JDHMYpqD8pgApUFCbNnjjyUU7TuvQyNigF2AX7ZXKAim0BTt + UxGAFFAnUd/9xBQIkRMQI+rwo4DrO7nTtg68AxaFSr08A8A1kBe//WdNcCPjgtRNluFi+eKetzlOitR5 + dM78dRBXnguAr0loK88jhI3I7Fk3rwwGq6hpBs7uskOOO73XxcOqIqQCucpCEboj04MYcy6g6Q465qos + LII0WnfOWx01gfxnrPZz0fuZ6Z2YsXaVRdyG0XyyBoGKol3XvhMCUP0zPRO7G1qo0FmhyyUfLKYnqlIB + Vg1ySCkjpsFxBgPABgN8rIB07Y+PKfVY8YcbAUEbWO+TAtAUKCtd4PWlEcicKYirsCDPBMA6JCyix1kh + qgWIElyqj/FB4DeLsDIBQUEz7v8A7gGbQQOkjpwFIICU56F6Z9//AIx6x3ZKetHH3AQDWwmsdT5UmtlQ + e2QkgCCqIFcJsORImOdYNUOiU1i3EVu52ztr64U7zo7AIXzX7fyd6UGfUH+OPuTvYoM8q+WIcTSerUe7 + /M9b4cLJtAEHH0YdyYICpVOzisUKQhIR+vTPQeDNM/Gx2AOUSkpSaFOPMzYHnVpFQ35mLeKu3oc7wgAX + MHb1NGdoAC9hQXIhcRqx8AIOcFP2Afgp8zC6YKJZaku9debgSMMYU9YGzDFvgLT08ciWoEAAYGsauWng + irxctw3tFuqvJnnipHlcF6Bf9zQIoKA7Jdn3xeIEVk+SDrPWezjU5MNXQxmucLNAPAmnDc6C40gX63AA + E1zbo2fM+EL0/tnrHZyuIYtiaY854J5frwyNEPhj2dcPzv8ABnpnfA1qoihNJWZWha5zAVwdiEkoWl7c + YRBwgShdWTNfQooDrGZ5D5n6xX+iUQ2A6887QOgfqOIHUZUJ4PX54gb0oJs3krLikNj0z2hxIv3mUnkG + Om9CzoFHLuDrWBn5P6z3R+sK60hToHqHfFMcFfJjC3ho6IvGsPOMBo6AeGNtZV6B0HY/lWxhXKAKr4YY + wu+u7MDs3CqeEeMKIOTx14IBrxovwqm0j0cvr7/1x6rwfD7r/rPTu+HPSeDn2P8A0xrfiA0s2Bxvq8ZR + H1VYPYESH1xMsoiW+GxPHECjQLa6r2M55zoPU4vhUglUeV4NYn+aC200vfzxs+fUA3h45NqigQJ2rZnK + W5raWr5a1noPZz0HuZJ5L/Mfh4PMSYoep8rxxRYFaHBl6f2z1js41xqaiko9M9q/rFs80g1NDDjL7rb5 + wuekd8IgGBWCi64zhX2XFYpU0h4GCxSFQ1pR3fPIPNtVNUpZDwx3NQBhm0zpcOPZUgRoPlnhPR4Z3DQg + AeKkMAClQAHgAGsd/PrKnGifMzvCUXPiB9+MVJ6nyxn8qL4pg3ipbumyYOkbhyqEYeTnsz957M/eJFVI + KKKJ5593/wBxFSowyW9bhBBC1UEdRv8APQYkBEF6LquNQ0SkuCdHyw+iBdeHhsXAyQfIfnAPM+Jfzngf + S/eOfZ7LI8x4uc3p3jcr8IaLcPcn7wcsQADr3w0PgArBUOfF+udkh8z64tnb8XEcpZ/0yOUyAVdyq4OG + UBQXc66yy8AXDuUdn1x1obAB2I8a6ZodbQaR88YVfcxEt31GnDfhnTpWB0EQlze5aVUPGsvyweiO412R + 5xs4INTco+GGHElVBvOOCSiNl5yFwABA1A5yULSdhW32w60/M/eGASwACtfzjYWxTLILvgzetU6Op1cI + tCiSJE5z3d+80z7794HegBAAh1ygvkd1Wt5753q7FQIy5wCkclRgTDmqywgDV564+sYdlXwpe2GAvUWK + eAcffCrhLEFeg8OJHZINHlOnXJsjHWvhC/jJpsIQn1QM2ZfNVni9PlgV49eROydTLQOAA29S8jgLH4Ef + w3p+2X70cjEvbzw9zyFFtqrPF+BSgEdSill7Yja1AtZLziwZLHDSseswuVEoG0O2RbzQBaO4/wDZioPd + TF9LHkVxb/AUakThHFzZ8Kc3T3Kp4OuHf4Iqke45SRiUYOxeMFAc4BEwTJ2QLc4u940bfPOnw6r4jFKP + Jpy3/vWSs7fwoiqoANdBxP8A80fJifNmFuvTQtNdDmxPIxVDTo0wrKwrEWc84FJWwFsPgT7Y5IrQMMr9 + OmP32TUjovXwuGaYphDkE0act4IYCjAdejfHAkkSoKoQ3SmMSvQ9mD13T6ZBJWogNqU0sx2M2vdOQHOb + nC7aIdmvnvJgRoZQxGuEwgBGTESgdDX3yOyCRyTh5d/Hk2msjGKjb1+uNBG2QIK6tXjNjDSYAcDy7mSI + oIiHWPXGqg3kjbgZRMc0EaIdQcTqBU1MF2d8ACKnYNlFxnhFNEcgeOXKQRoCpTtxo5yExEdZoFdFKmAp + GQVSOw1At+WASqiLQAbfHpxkd6GXI2q+W7k9A4lrI3nBywdA3igPfnLtZYEhBAtmsFCumlWayZdAh2nS + hw1n8hI21KJ1ZXqEQJFsExu2SyRpdfLHEqgHJV4AyAH2FaIHu1w60waEAMhxoawNcvCoBRTww7dSFEZZ + ZMD3KqhLQ5IYedHeXO87+OCbim7Kop5OmOjLzRiwvjrDI46rcUN+JghDjauh045yV1SQj0Heb1gMVYQd + svTFSRGZQejOv/W2fc+zD8SXRG3mnOMyOmZFh6dM2KAEr0IDUN4P0tlI0AvHXNXetAqVACGNGFg3iJJ5 + sbnwaAysE1rXTIroWwSI1XbXHJJbebb8lc5zPGEAGg+KmFwiHjDRUNXpgk34pDrYK1+cEA2AOEECSng5 + AvFYN2rNpXX3wkYwtgzgMw57ZWqKseHf+4eiemojx0+GovCDZARyy4o21UtREDjiZSZFKrIb4nQwPUKI + ILo6dc5ycgaaAcvmmFTBIqKoAESBbxmnjBE1C9Sbyt+EipqKV6u8Vl4KIDQC99OSNShIUEenbFmq5Ag8 + 61oznfCiiDQ9m7yqIikisDbwxbKrA0AjOGOTFFvLRCHevnlzFFla9IX55RGqe2AqHVtyh0rB0NGH1xsW + R2QpQVdbMXIqMg0SNp9XYzbnBAqBIuw73C5vI0okO6HTzwWVtHpbE6ReuEBXSWaAD4m3J18MDVPJpklk + EmAoJHhyQLBVAEUC6GTWP8RmbiTS+fGGIwkZQWinS7bhnsCghF2GjX+YN2uIhJUZva4T4A9Cg0++ag7D + RoBSXtjRQSghSgdmUpETQTRsXV3jnqmrNRga1oJ/1EhUCI9kw6vy3+8S3YaxrjnFcMSFkVUdW9d5pBso + yrysecOP7j94LAhBbApTfiGMngkIq1Z54qnREJrjBBREmDOKHPOBFppITtBxGDVj1eZvWOd1gtEe+8uT + ueqkYXjjIVcsisdVcT2ui2vdx06NEkAgAfA1CBBGIdjfGe8f3gMwnIozlfLGBZoaqtb88kGFAYp2U8sK + pDQOH3zkhwKjG7F7mILUsPgbb9XBJrdk08z64FO0EgHOgcWRqild2O+cBeSNWHuvllABzBVwBTiCkQkd + 9aY6UJQ0hUGebgpqikHrw4TPI6AfDFpwaULed5qg4tFmiuVQGRa2bn+5s/Ns1NaXnpni4NkEsxLdnyyJ + WFwdHH0MdFIpTYPKYEBIsHwGjng6ZJw04oeXONEERFSfXOOMNc/3ixoRpsKim+d4jE21YRan1cU1wRHs + SJz2za1xvkUGheLjVzKaqvjl/oz/AO+yssUEFi71rCPAogeUY8hiBGBvAdecVcvBXkNiBLmrweSHjrGa + JJgLqApulyqsG5UYF6uG85ABqrSgpB6XNzpCIgO7tz8pilRgzCWLVmrl+hqQUNxR5H1xCGyyjdXvrj4r + yKyAU4FfPLV32IhBNo7cHVFTwWq76mGJaSFVFoAprr0xL4ahhvNNzrMGRQbs3h5PRSgFdr4Yn5LzQ8C9 + XIOTBRTvomC0w2WV2RMUF3TNGSjvjflMFQ74Ohtdw6B7GE1tAtpYx8MA7jBBYNhPDAlRVGmGI4OfeoBC + Qb03j4+HTWgIjuuRiZAGzrddZ2QA6OFE7aw0TbZIkIHOSEQUKhtDbp1l4tUCjWlTCb6Krg6M64FmNFH5 + YglCihGM2+OJDJMBDY01JhgXalVBrwBcTKKBN9kmtpiTX+cPuZNh24QIB6nkwYwAVRHxM5Piah00ON98 + RTRRiBSQ5+uWVD5IUKavxLdTVMN9b4Zy0CFiQqvY8c3s2mCiNl1rOPowAlYrGiZKhoJLQKwdBeuPuwAA + sU5K8Yj5LfBYavfAJFUgwQA31w1C3QHRZGzl30y3wQbUBITy/mcyiOBZE8cJwAGBRsrt2ccYVO5LJHZk + oRcqoolElYp169Mv3ESGIaX2euDOIDKBDekAxY2v2QTQnT94lvBuQEKIG63iCa9sA0uqDx3isZpuTN0F + Nb1l2GRATejaa54cE3WJKo6Hk2YM7EeQr1Qh8LYlAFpA32jk9ZejR0DsXD0j0wFRKPeXuazTw6soKR6H + P0yTKADuWVGvnMMQiWaPEDOWJ88SKXboP2xtoTq3Bi7deOOqESE2UhyQvfET0ma9EtuumBuAgdSKPBq+ + nD5ecoV3eyXeBBDoakFI75N+DhGnxWHWO3TTCogplkKd/wD3Np6X5rXFzTqtJVU4/wDcHlqk0RQTydec + 0O2cRIAUPHTjDhI3NsjBOusDXdkCVaPMrhmw3RKqLK88bwPoUANWKNXbcckwhOhEpzw6xiyor/cd6vIN + Ivy2YfFfYD0DqvOFKQKxhRTqH+eOU0qgKYKVubSvXGoTYCdlIuPHmZsrkcILNnMdsUtNxAhUrpepyYvq + 4AqkJeqdTnBK9CTZcBzPhjtSACEnRBPgi5IgsVkecdUisVhsg6wqmX2kQq+K5LOqeAQsOC3NmSu6pbWN + GH3xc0xCld8oNwRQAigu1dpxMBnAaLjtyuuOtUQlk2BqUmCc8SoFAC+Lrn+ZP04pI4WdnEb8IlCAALCH + XBzVDJTYx0LxM03GoQkDJPDK0hJQ00p4Y8hjdkIiQN85THE8oIwDyxEKzBQsqb5gGbjwWlEHRLswwpiK + sJpv1wnWSSB1S3vAh9gJ8Ib56uVK0dgNsO78Lioj2nwPPERHrxp5Wd8EYooWpZS723Eom7KNcyNOcsbW + oUBm9vhrAu3TVamly8+NQU1byYv1fQlREFuzAoVu1akX6OCFw0uxJtX6YEh50fAqu/nkVEjphSQOpTKi + OCIiTQdu+HJM05fJrnHUIgQs3w9OfhW+GXnzA+WS1QDXm1V0XpMPuirQ3QDuvXOiGeBGmjnA8uYLclE3 + gGbcyHNK2rd4KCt4oO28XeUsEU0jyBdGM5ylfNwiWCC4nVPGayBo5Lo4VHCELraE7aucRpg67XieOQP6 + NiwSonMcWQFA0Lzb54sQQDRA4B6TDSphdEoqq2Mwg6UUaoAIpHZhuUgcze54uMZha1ZVfq/DWrMloRfD + auJERt5RU12SMSQegwFatm65RHMMN+IYsESnoVsyogwU0umjE7XCKq0lXxzWWksSIyHgTEUtEwo4TWUq + EDSy3jeuf+sP4a/pTDj+vz/3MuORsFoPRPvjqqViJRSZs+UqZitl47MdpGeA40MYiZtkbIjRhp8cie2m + tkTxS8ZsO21SxSz5ZVa3IMUdKPJgkmxvu6Rs+9y4iqMQ52MPm/DhABgmxLwK9MXAiicaVTZQ3g4VHRDg + DtHw4wmZW6my9RafPOhITQtiCQo60pjQ5ipR0OlDv8XkG5zt2tL5YKcECWAzdMcpz1xLriXXfENZ0mEL + up4dp44w1MWJjWMD7exrJo73Gxw0GJF456ZMwRRFFuusmaIpqIAqb5xhS0giyC/jAQuKTag8Xxze+C9S + SIx48cV3ZpvjSbwIHS5IMVhp3lf+fX2x0PG6LNszqa1oo9CMxaiXmwdZNZxnfgO+IdfgYFoiUqAbTe85 + fJLgoBDNtxRSotLJRRCXpnV4RUB3U44wIGUvXfTecQixwdMfrjFpLRbSlxaJKkGAN58cioSo6DvpynDS + 8I9TzPg4AqQG1XgDCujSkrSirLvN54PAm2kWus4KbXmVC4QIQ9wpxfDB+RA6cuOXwxidkCBw6rveFgi0 + TsEvD45oHk7NP/HV/ZRUyQzhnjjLCABJsonJ2c4zP1lDChAUd2YfgiSWxUJ5dD8RyCDR04dhZxj6pEt0 + AGL88NpNhsjtAzxyY0kqwFOXfTK+GAGdIwUQ+bmjhKAVEUFeBBTKk85nRrl1/jnHIrHCgCJuTeuXtgLg + jAJvDx8MFbH1xKWSvB8HcB6kIfnnOrUASRHoa4wa/LAEII7szoNi0YYg1LyzZLhUXYgumvVlYFrOvCQz + nHqVYI3RXbI/LNfUxNmoovPeRXUoz2UELvzwagkp5Nqm1l4xmkugAogX53IE6nsoAl8i4GdYSqeFPDGB + UiEAUdMez2wZYORUUqtedJii91Qgo3zwIRnEDJCP8yn1xFV6w6PNxSdeBVGgNsOuMEFVKC7kPp8Nk5Aw + WXQQushzaVbCuh0d98BlcHsipVvOF8bWIsSPITyweClQAkFF/wA/eI/ganQCPQ1ziEegiCQTfLrid8Yr + EuG5thRMHnpbm6Ko2vOOl18nGy5QisaBfHHkD6wUAdxjkqMlEEKqdezwwgaun3EYHLAISrq3jGcfBCZC + B4K+eeM5yiQQs8s05gjApoD4GPPs6CMtZr/jUvbCMlLHljTxMXObRG3bnKvrnFugQ5Ejbq9fVdIINJ9S + AZNFzTgyvSSALDri9NUgKicAPXGiAR1lrKYqNJwNNAnKnLr/ADH2fsbpToULjlKrEAqWdXOeuPzgQS0g + oC8hYdTBqBs00HHG72chcFGyUkWcYs+YpQRDzFnfWIcCUxTfDR1MWHYSoE8rvI6QT2CmffEM0llJ2HLl + 2DqAjFZQB+pwDh107YTPAgBjAFShrJXpI4IRhTZrrivWKZyRr05y5QqTaNVfNZjygj6U0GaxNDJS8yJD + WjJHhOsjaGiHRkly2cjO7rjlddweK6OIlr4pUsiPMcs1nQQY7I0cSEQJgWaFHRMGXuaRBv5YJEJSLyq0 + c3vnOHgQMtE8898Y78GKwE7JDeS8T4J218FfqEUAciHhlpWW0RI6Xvvww6QAkAWwuTq+dCIDd88CxViG + lLsPlksOFs76hyyZTFcC1JsbNYnKKCCNlTqYDuEN60CfbEFJ0EScIV7YbMmVyC0NfBxAkkuG4OXtm+n6 + Yp6xx5ZWCtU0psiZqmhRmjg0eOJYEHqEi1PDFmDanbrv0cXL0LYyX75s8i4V7/8A8NDhVBFhZc2yyLV2 + jLj2tj2l/CoUKO75l/DHuB+89jY7S8I/GPcj957gY9wMe4GPan7z38x78fvPejHvmPaPwRPa2Pez957+ + fvPfz957ex69+89e/ee9H7z3s/eezv3nuRg/9Ix7kY9yx7kY9yMe6mPdTHuZglt1Egh2LdGeLxeLxeLx + c+Qg8uujm7p+f75vCyqyNnXwwJpQIJehziN1cGkSCXee8OQxIqpgHrwA0ISAVm7iqAOoIqc+TPX/AHZv + NrS1xm93Fu9GnXoVcXKbMk3G9GGCkxWPrAZiAE3Y8Xk8V6PHPFejxxOhY38QzdxD5wcO0ubWyKrfLFc/ + TvsOe4P3nqT856k/OepPznqT857x/eepPznqT856k/OepPznur957q/ee6v3nur957q/ee4v3nob8573 + /ee9/wB573/ee9/3nvf9573/AHnvf9573/ee9/3nu/8Aee4/3noz857j/ee4/wB57x/ee8f3nvH956y/ + OesvznrL84H64Bp4XNyFFp2vw9Y5NgjTJIb4cp0rxQW7HiGWkk3EJKlTtnfo8gMLyYNZw+jebVfSo8tG + JBVhQdhOPHLFYLaFADfTCtkTwtdKrvF0S6Dyt0YiqqxBngc5qaGSqCDOscXkWhprsN625MMCA4YoPV8O + M3rkdJry/h5M/F+Ppnb4EMOuPZcrK/7AALl/5AC+WXLly5cuXLlzZvg47/CtV2JsjpoYLp6TjchkHRZQ + RDx4wFuordAaTzxRVVs83WbHZ/7GOsLfpgS6Y65MdKVO2s3DXzg7t+GOiBLQA6O9ZDikKWXnbhbRyu6M + Fykp0O5Vlt1vNyFrNGMbvvgnEkHE9jOnxh6vD8fTO2PATk55M8n/AG//AN5f/L/z2ye2T2++eX755fvn + l++eX755fvnl++eT746Xg/5nM7/EzBj6EvyyTFTRxWSpcuegOqNL88pCVGALBXW8ERLpWhGUc3pQYGw9 + zFUotG7fFwVVzkm63NdsjXSUFDbK7wMABGBBvU8c0jh4YuhHkzXiGgU82OTXOxGwdcXDWtnaGcb8MD6A + lLFpaaa9MkalCtcNHx9L4Px9e7Z6kSYh0wMh2yHbIdsh2yHbIdsh2yHbIdsh2yHbIdsh2yHbIdsh2yHb + Idsh2yHbIdsh2yHbIdsh2yHbIdsh2yHbIdsh2yHbIdsh2yHbIds/B+EI6mfPLlf4XOfhrCfx755fxc9H + h+Pr3bOldRnBrDHlldsrs55MhkMhkMhkMhkMhkMhkMhkMhkMhkMhkMhkMhkMhkMhkMhkMhkMhkM/B+AK + 9YbFEDDW++D3fuHg3rz74M/SXIM2DvNWeghA5Lp5wk0yobe3/rI+CiHA2ncwSy7tkLrbAfnkkBlEeA2L + 23hRBmMx4Ius3vsFszgvKuWDfRBXpaZxRYIgY03pyC+1qDTZMXjmoKda98koKKSOXcySLld7lGO8ME30 + Wg2h1mh+KWtd08eeCXcEAXq1cUA/ha9jeXtjEBOgBvGSKaFJQdYQ3wDuj8fVu2TncnknCPfEFYOoa/Uz + 3F+890fvPc37z1h+c9YfnPWH5z1h+c9YfnPWH5z1h+c9YfnPWH5z1h+c9YfnPWH5z1h+c9YfnPWH5z1h + +c9YfnPWH5z1h+c9YfnPWH5z1h+c9YfnPWH5z1h+c9YfnPWH5z1h+c9YfnPWH5z1h+c9YfnPWH5z1h+c + OQ/AErprlzR+GTwwns5qMBjIudNO/rn37/coKVqWw2POVYIKkMD2b5wTaI3TSGguDRjKhSdPDF0rgDKL + vxuAyCBMsOpffIABIqDtOMZDXlxvLDprjIy+xKCBBmueMLKERZQkjzcFEV1mrdvTHUjamnbvNXSnlzQp + MeumRR6bfGZZEKJBw16QuMUUkV30wdwQI8PB1gQJABAxzhdAbWI54eDnw+Pp3bObolJyM+2W4Hwi/e52 + vnj+89v/AGz2/wDbPf37z0h+c9IfnPSH5z0h+c9IfnPSH5z0h+c9IfnPSH5z0h+c9IfnPSH5z0h+c9If + nPSH5z0h+c9IfnPSH5z0h+c9IfnPSH5z0h+c9IfnPSH5z0h+c9IfnPSH5z0h+c9IfnPSH5z0h+c9s/bP + fH7wX3nZPMVyVN5yUXlUdJ6Kym29kXQHlrvjbmAWS1Y3eI6dfRaPE3ow/HGg2fGZo3bGwpCExe8i1CZT + 2RNKCbTIVDC2gSknhhjIASut3tnM+SihOkGZUhY5qeEmBo1bg6m9vg4EAOxGt7MoE6CuCaoUILNzWWbw + mrLqXXGadqHoA1kMfFVI1Q65u7dKdg1hOc4MkHh6hGvUyb0heSO3T8fUu3w4Ma0OD45fHKd8p3ynfKd8 + p3ynfKd8p3ynfKd8p3ynfKd8p3ynfKd8p3ynfKd8p3ynfKd8p3ynfKd8p3ynfKd8p3ynfKd8p3ynfKd8 + W/k5v/FohpPk/AE0jepiOrh1B8ASCU5jcQcswQEb5Zs6f6wbo+uQIU3074dcjfGDeP4et8H4+pdvhQl0 + OAOuR3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R3yO+R + 3yO+R3yO+R3yO+ND5P8Amb/wiIGQgAZ9cfIBpFooHor8s1QQ0CXetc4K80ZrsNGpcN80YJBaURk8c6E6 + smdQdteeJ3pAUIp1RXNtBct0KKfPDBYKoomxjMfMJxGxFVjpwsiiy10qAPJeeuPUHIUq6oug+jgFfSiC + pAKB13rjvdM+LO45PPCIgVUcvRNZyL+N0m6pr+Hq/B+O3oNfCjWazWTNZrNZrNZrNZrNZrNZrNZrNZrN + ZrNZrNZrNZrNZrNZrNZrNZrNZrOryf8APg2cm/D4dI7NuL0uHNbB7j2p03gWFBRqqW5TgthpRGp0DJg4 + EKEU1O44PXRlICcnljifczVbNgeL3xLDyKg9B1r15zZ4h1eRFemIPcmnQB7pkkD4S964nK1HQsXCoq77 + XhHA4MIhA86LqO/lkRxsUoNujq4A8xNwHp/D1fg/H0btnqvD4EyZMnlk8snlk8snlk8snlk8snlk8snl + k8snlk8snlk8snlk8snlk8snlk8snlk8snlk8v8AiAJBPBxZczcoBUHh0Zea9BL22Zp3wrAXoyt+WVsw + uwTzQM7uEaIRW0Yyc5MUrqVWE/XOajESTTiBgIQ7kfVDEDG9WBxV00eMVLgsRKHTSlel6YuRaAAs6K6v + Tvi3PNOfJDeK9SirPMyIfS9Clgn5xqYywRA5s198a9EQHGdtbzYDhQB7SXEIXJZiVhtZ98ULZ0D0Clj5 + 4yVgw2Uu5xrD+FikTSX4+h9sRIJqLBf3hwBXVCffee1n7z2s/ee1n7z2s/ee1n7z2s/ee1n7z2o/ee1n + 7z2s/ee1n7z2s/ee1n7z2s/ee1n7z2s/ee1n7z2U/eeyn7z2U/eeyn7z2U/eeyn7z2U/eeyn7z2U/eey + n7z0p+89KfvPRn7z0Z+89GfvPRn7z0Z+89GfvPRn7z2M/eFF35rY7a4wzuGnyE/3AjK4/Qqz5ZQMgN0d + uW84IAmnQDVaeXIrZOUEcxec4uDmx2hyW+GDZUR2Cqhy5YHg2A0heG9cZ9FUUA1XtZ558hOT9DLAUIYI + GguKkumEihrtdZLHgQGtqcCZy5MEUnWa+WPnXkFzSp49Mk4qotryQ8axiKCloc3T0ckmtSxGcKb8nXNA + QsqAoadCdAxwC1WgLoZp7GIxa52aJVHo7YJp12JJrl+PJgGhspLO2C5w1cjQBFC0O8MdVnAcZVOsDFgr + z2GIUZEJE0iP8QQIEIR840qHWGEoF+EGIQAWLSeXxFMjpWAFFxpRshp5j/wDNmzZs2bDvHhM9dBWLlBQ + ETSI49y49y/yAAAABkmMGoCetO8C7EP4iYUKRDhlNESJw64A5gJYh00ZRGSMh7xMhDNmseQDGe8IeR3H + GjJO/BBAtshrnG4OglHTWXL5TiUVyutuABWB1DgExAEgAMN2u28B0PACT5KPqYElCu0qtVZgRDgAXzcM + T5lkW2G2IR0kKO7D74HRSoqJGCf5k8/ORcZqHbGaBqAPUU5wF06VBVqutuEKdJIDdDp5Y1UtU6l6GtYY + iRO5LVLz/D1M7TmlEroYxpqeeMOs3VBygc3mYpJIGIkROiOE1EpdmkZBp54wuIxKkIWFOmq+eEBihMoI + ophuMQujFXakeCGClBCCQKC0Kv2ygriGLDqzODU0APDYrp198niKGU5icld/DeOEiAqKB6cZX+skVaoD + hOvTy4+E6p8aHK5sjW++Xf5KdAA3hdcYIfOAVfkZojUoJa94zuYQ1QI1rkLNF6dfnmgFIBIqci9sGHUS + 35CtAp0MRDYKUFUTQ1yZoALWLCvBcqjWgBEqtEvS41z7Aulun71loowJDJQg73kGn2vAViuwF2xofHXh + EAJUryucrVZWidFedfFgEFAKgb7roxxWEoJCFFipgFEmVKsDQBvxyyWwCPVEeGZU05Io4FBEXo84+CZ5 + EV3AswNphQoh2TyxYBCiADtI8ujAngJ1wOjdcJjd9wKdbIjy6+9yRKDgShS2b4+mRJhyNHBWnB1xhSYA + Igu/Hp9MshlwRYqA7Q5HfBk0NApKIaaPXIfKQQBe1WYlFs4jdIu/vrHPww0XiImIopAODrk0mPggAgpA + WUr17YmdtFVYGtA344w6ERAvalcOUBToA2roi+NxOO2QNd7c6465ta8/5/yZAA1FvuFj88Fa5W0gvbXb + pxmu8ACoGxJKusFAqggBxoMFHCAdOhim3riarQMHiiqusnfSAaIwNdH5YYzE2JENlia0nTCCgUkYAj1F + 6Yn5IA7vQxkNU1UiCbB+/wA4pSMCCwozpPvkGvs1l6WDTw1cGGkBido446uGKSowpojCeH1zSG05ErYQ + bd0wp7tXjgEHcKcdMfI3khdhsrpelxQdWkvRLzzMUxDbZCIDqgVXAWSjEtQgsOLrFR8gR2HIl0uaGmNa + EENjHUOHBKIGjKWngjxlwBagbVsgYzoAWBBNETfNT/zIqd1CCwQhp48MBNRQRYiMvnhYLAkldNW7M2g6 + goe4DX2zVastCqdW0n3ysEIFScWJ8ANUqkCFyBULGsBROCQ10zY9BJsFEdLTpiM7QjjWAfL6Y4kOAAkV + tXe55YibXMoQCof5rw5zXgGAFQqzxc6A/CJtAxr0j4+HgTRCiCs5xtkTbxaFmQnHeoWQCTTMJEHhEiK5 + 8cQIigZBtb4YCzxFrpsSq2vATtigBzg4noaUF1z55DnSGiHkR4m1embnzB0DbBurq9LjJF4VqgngOswa + yVFSA1HfNwiyA+qaYTl8c31wBhV2IG9Y3H4rZZorgLENQk2AnLan/lSCWIEKiBDSa8MZAFVgHXHBeKDp + O+z/AIlqm90Wau+Lg2vGw0NAIwHDpAgDYTgGb3jjdSlEINEKHJscZ4S4HoXX2xri0BQZYprjphx+1FGk + 1WEv1y/kodFWo89fnjMF0AgeQRT5THRZRqug1FoevGOM7Wotacd/pmrut505tVuc57kZ4ubl5mCT3RYZ + 3cD8Q2dQIqc8BjUZVcLb1m7fhQKhKDuxHF6vL3w76AQCAKtr2cBlA1A8kZTTHFbAr7pWgN538s5asoBX + gy8JjQEXlKafHnBJpKOpTaVL98VGZDCzsTXlhPmVHCrbt18sKMlRUROGmXE5Sq/cuPxCQ4ltAd/DCBs6 + umOWdK4EaW5AjmLzhJ9SCsEP9ygZBK0CRR2bzU8mkM2aX4iqoHGgNEUUTHvlN0jbrFCEVUqrtVcN/wC6 + hU5QOkxWkYAYLxXGEREomke5kT1FcliV8h+eOBXQOykY+TisVZd4eXfD4/8AuJNMBqIAN1uHOAhHQ6Ev + IvUccTQnoXxPgx0mnVThyiTO8t2Tm3jNGVoUtasfmfTWQbAQgikpTXnzkobaq3W0TL44qSVQIJ1CQNcc + YiNqQRUbGwOxgvEMOj5WdB1r+g0ECO0Jt2TfGNxES0ggbrhzV2iqGIx2YWsa0BECfMr4ZTp3gi9SDj8d + MsdqAVXwDNhZUQUqNOfXXEYTMSgQGIDbXjhhv55RYYaVGwd9sHRyoGNtW3XEw7GFpUIrDezeNXfYCBtV + bnjMcqkKCk6bfhqEX16CfRxj82BIHJUujFLetkB4rlp9PUkAeuHTVIKsiplj2mDSsIAiVbOSF+2Td0NU + YgOjtsm6OsFMbKASEWI8PTpjwIIAq5uc8wKxgCugPnlKqh6tIrQVMVIxq4pzytmsTMhSlVjavLmwm1jF + AjbsenXCGiFkBAItDbrBiPolsqDUj0xugQhpQ50sXywgwV01YC8UeefliDfsGgKXXXXOVJDUWsU3wF88 + sQtRQhAFaPd7sMmCEgKgEDsO721iTQuBaYEXflqsyQniOJvQrN2c4HK5NwaNi7d/24ogB3VmUgrYVIKt + Tq9bN6xKQliqowAxddXrnW9cYF4pMiAnJeTWvLBI5EFLSEIBLPLDTpQyAQo3XONq0ysLQAu3yevGUxOm + QASIGle3Tyx5za3TAZlaTkmuSQOPHjtgleTYwpT7kxNlhKOAlE6Pyy16nB2ht35YtDUctZb34xvJMhTS + dcRwnLQqIpAjziMK4J06J3yi9I9xkEOYX84iGSIRVHYtK4YkqI0I1Lda64rZZvQAgk6nQ3rNYFsoqgr1 + PoYxAFojaVZOtch+hONNr49tOUBKEIWrZOOgYxY3KK/V+FPNUYgCLw2ow64G5tAgQRV0l1deGA4e1yoQ + irv7eOExU2ooiO08cLrol0nda3lzqDrfVZtdROogxNvLNW4dF64YaoSfReviAsTQIIKXbviXLnRhqgDY + qPN4zi+RwliXjJ0dbxECKpVQ6Czf9tdvaAEOsXhcIRtIWJYgide2J2grRImgJxjaO4gNIPyw/pShZSIL + wa6Y+XkC1K13123OPKDIPmq549HSOu85w0hCAT5prNN1oEDyCvzxUA4OglRQ8XKushqWOJeA6Y/XzE11 + rl+I9JEEBo8iJExNBt1P+DHYfq35xCsQJOnqLkCCdDVpA0fLHRAAAgsitecCl/Ap9EyCn6BLxVCvzuRC + pF7RwFGJkT6iKgAAb8DEi9pKBI9ed68c0o0qosry9jq5SAwWhpGztjjMgSsAbDtiI23IdpLOLM1fOk0s + i3pr4TCTLCNQYhfJyXlcOKqv+/BtMRN4A4AMENHQLUgHPyyw/UgZ4FCvlZiJN2nTk2dHxyqdqBQvUk3/ + AEv/2Q== +</value> + </data> +</root> \ No newline at end of file diff --git a/应用/UserFission/MainForm.Designer.cs b/应用/UserFission/MainForm.Designer.cs new file mode 100644 index 0000000..8bfdb12 --- /dev/null +++ b/应用/UserFission/MainForm.Designer.cs @@ -0,0 +1,1396 @@ +namespace UserFission +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.text_userinfo = new DevExpress.XtraEditors.TextEdit(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage5 = new DevExpress.XtraTab.XtraTabPage(); + this.label3 = new System.Windows.Forms.Label(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl4 = new DevExpress.XtraGrid.GridControl(); + this.gridView4 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.radioButton2 = new System.Windows.Forms.RadioButton(); + this.radioButton1 = new System.Windows.Forms.RadioButton(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemComboBox1 = new DevExpress.XtraEditors.Repository.RepositoryItemComboBox(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage6 = new DevExpress.XtraTab.XtraTabPage(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.gridControl5 = new DevExpress.XtraGrid.GridControl(); + this.gridView5 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemComboBox2 = new DevExpress.XtraEditors.Repository.RepositoryItemComboBox(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit2 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.gridControl6 = new DevExpress.XtraGrid.GridControl(); + this.gridView6 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn24 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage7 = new DevExpress.XtraTab.XtraTabPage(); + this.label9 = new System.Windows.Forms.Label(); + this.gridControl7 = new DevExpress.XtraGrid.GridControl(); + this.contex_1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView7 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn25 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn27 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage8 = new DevExpress.XtraTab.XtraTabPage(); + this.gridControl8 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem6 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView8 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn32 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn30 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn26 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn28 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn29 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl3 = new UI.Framework.Controls.PageControl(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.text_userinfo.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemComboBox1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl5)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView5)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemComboBox2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl6)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView6)).BeginInit(); + this.xtraTabPage7.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl7)).BeginInit(); + this.contex_1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView7)).BeginInit(); + this.xtraTabPage8.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl8)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView8)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage2; + this.xtraTabControl1.Size = new System.Drawing.Size(1141, 654); + this.xtraTabControl1.TabIndex = 8; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage5, + this.xtraTabPage3, + this.xtraTabPage4, + this.xtraTabPage6, + this.xtraTabPage2, + this.xtraTabPage7, + this.xtraTabPage8}); + this.xtraTabControl1.SelectedPageChanged += new DevExpress.XtraTab.TabPageChangedEventHandler(this.xtraTabControl1_SelectedPageChanged); + // + // xtraTabPage2 + // + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(1139, 628); + this.xtraTabPage2.Text = " 海 报 设 计 "; + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.labelControl10); + this.xtraTabPage1.Controls.Add(this.simpleButton2); + this.xtraTabPage1.Controls.Add(this.text_userinfo); + this.xtraTabPage1.Controls.Add(this.labelControl9); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(1139, 628); + this.xtraTabPage1.Text = "用 户 邀 请 码"; + // + // labelControl10 + // + this.labelControl10.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl10.Appearance.Options.UseForeColor = true; + this.labelControl10.Location = new System.Drawing.Point(916, 62); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(208, 14); + this.labelControl10.TabIndex = 11; + this.labelControl10.Text = "修改邀请码请点击单元格,即可直接修改"; + // + // simpleButton2 + // + this.simpleButton2.Appearance.Font = new System.Drawing.Font("Tahoma", 12F); + this.simpleButton2.Appearance.Options.UseFont = true; + this.simpleButton2.Location = new System.Drawing.Point(723, 29); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(120, 29); + this.simpleButton2.TabIndex = 10; + this.simpleButton2.Text = "搜索"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // text_userinfo + // + this.text_userinfo.Location = new System.Drawing.Point(238, 31); + this.text_userinfo.Name = "text_userinfo"; + this.text_userinfo.Properties.Appearance.Font = new System.Drawing.Font("Tahoma", 12F); + this.text_userinfo.Properties.Appearance.Options.UseFont = true; + this.text_userinfo.Size = new System.Drawing.Size(459, 26); + this.text_userinfo.TabIndex = 9; + // + // labelControl9 + // + this.labelControl9.Appearance.Font = new System.Drawing.Font("Tahoma", 12F); + this.labelControl9.Appearance.Options.UseFont = true; + this.labelControl9.Location = new System.Drawing.Point(152, 34); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(80, 19); + this.labelControl9.TabIndex = 8; + this.labelControl9.Text = "用户信息:"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 591); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(1139, 37); + this.pageControl1.TabIndex = 7; + // + // gridControl1 + // + this.gridControl1.Location = new System.Drawing.Point(0, 84); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(1135, 501); + this.gridControl1.TabIndex = 6; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsPrint.PrintVertLines = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CellValueChanged += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(this.gridView1_CellValueChanged); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 50; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 148; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 125; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "生成时间"; + this.gridColumn4.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn4.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn4.FieldName = "crt_time"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + this.gridColumn4.Width = 115; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224))))); + this.gridColumn9.AppearanceCell.BackColor2 = System.Drawing.Color.LightGray; + this.gridColumn9.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn9.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn9.AppearanceCell.Options.UseBackColor = true; + this.gridColumn9.AppearanceCell.Options.UseFont = true; + this.gridColumn9.AppearanceCell.Options.UseForeColor = true; + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "邀请码"; + this.gridColumn9.FieldName = "code"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 4; + this.gridColumn9.Width = 113; + // + // xtraTabPage5 + // + this.xtraTabPage5.Controls.Add(this.label3); + this.xtraTabPage5.Controls.Add(this.pageControl2); + this.xtraTabPage5.Controls.Add(this.gridControl4); + this.xtraTabPage5.Name = "xtraTabPage5"; + this.xtraTabPage5.Size = new System.Drawing.Size(1139, 628); + this.xtraTabPage5.Text = "机 器 人 好 友 申 请 开 关"; + // + // label3 + // + this.label3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label3.AutoSize = true; + this.label3.BackColor = System.Drawing.Color.White; + this.label3.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.Location = new System.Drawing.Point(299, 259); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(537, 35); + this.label3.TabIndex = 18; + this.label3.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 592); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(1139, 36); + this.pageControl2.TabIndex = 16; + // + // gridControl4 + // + this.gridControl4.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl4.Location = new System.Drawing.Point(0, 0); + this.gridControl4.MainView = this.gridView4; + this.gridControl4.Name = "gridControl4"; + this.gridControl4.Size = new System.Drawing.Size(1139, 584); + this.gridControl4.TabIndex = 15; + this.gridControl4.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView4}); + // + // gridView4 + // + this.gridView4.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView4.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView4.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn13, + this.gridColumn15, + this.gridColumn16, + this.gridColumn18}); + this.gridView4.GridControl = this.gridControl4; + this.gridView4.Name = "gridView4"; + this.gridView4.OptionsView.ShowGroupPanel = false; + this.gridView4.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView4_RowCellClick); + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "ID"; + this.gridColumn13.FieldName = "rid"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 0; + this.gridColumn13.Width = 143; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "账号"; + this.gridColumn15.FieldName = "name"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.OptionsColumn.AllowFocus = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 1; + this.gridColumn15.Width = 148; + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "账号昵称"; + this.gridColumn16.FieldName = "nick"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.OptionsColumn.AllowEdit = false; + this.gridColumn16.OptionsColumn.AllowFocus = false; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 2; + this.gridColumn16.Width = 125; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "勾选禁止自动通过好友申请"; + this.gridColumn18.FieldName = "onoff"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.OptionsColumn.AllowEdit = false; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 3; + this.gridColumn18.Width = 223; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.settingControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(1139, 628); + this.xtraTabPage3.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(1139, 628); + this.settingControl1.TabIndex = 0; + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.groupControl1); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(1139, 628); + this.xtraTabPage4.Text = "拉 群 设 置"; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.groupControl2); + this.groupControl1.Controls.Add(this.label2); + this.groupControl1.Controls.Add(this.label1); + this.groupControl1.Controls.Add(this.gridControl3); + this.groupControl1.Controls.Add(this.gridControl2); + this.groupControl1.Location = new System.Drawing.Point(27, 27); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(1077, 577); + this.groupControl1.TabIndex = 0; + this.groupControl1.Text = "邀请入群基础设置"; + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.numericUpDown1); + this.groupControl2.Controls.Add(this.radioButton2); + this.groupControl2.Controls.Add(this.radioButton1); + this.groupControl2.Location = new System.Drawing.Point(232, 39); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(576, 67); + this.groupControl2.TabIndex = 22; + this.groupControl2.Text = "入群条件"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(128, 32); + this.numericUpDown1.Maximum = new decimal(new int[] { + 9999, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(51, 22); + this.numericUpDown1.TabIndex = 24; + this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.numericUpDown1.Value = new decimal(new int[] { + 3, + 0, + 0, + 0}); + this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged); + // + // radioButton2 + // + this.radioButton2.AutoSize = true; + this.radioButton2.Location = new System.Drawing.Point(379, 34); + this.radioButton2.Name = "radioButton2"; + this.radioButton2.Size = new System.Drawing.Size(140, 18); + this.radioButton2.TabIndex = 23; + this.radioButton2.TabStop = true; + this.radioButton2.Text = "2、邀请新加用户入群"; + this.radioButton2.UseVisualStyleBackColor = true; + this.radioButton2.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // radioButton1 + // + this.radioButton1.AutoSize = true; + this.radioButton1.Checked = true; + this.radioButton1.Location = new System.Drawing.Point(59, 34); + this.radioButton1.Name = "radioButton1"; + this.radioButton1.Size = new System.Drawing.Size(256, 18); + this.radioButton1.TabIndex = 22; + this.radioButton1.TabStop = true; + this.radioButton1.Text = "1、完成 笔订单邀请用户入群"; + this.radioButton1.UseVisualStyleBackColor = true; + this.radioButton1.CheckedChanged += new System.EventHandler(this.radioButton_CheckedChanged); + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(689, 303); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(267, 35); + this.label2.TabIndex = 21; + this.label2.Text = "击左添加群信息"; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(5, 303); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 20; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // gridControl3 + // + this.gridControl3.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl3.Location = new System.Drawing.Point(564, 131); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemPictureEdit1, + this.repositoryItemComboBox1}); + this.gridControl3.Size = new System.Drawing.Size(513, 446); + this.gridControl3.TabIndex = 15; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1, + this.toolStripMenuItem2, + this.toolStripMenuItem3}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(101, 70); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem1.Text = "增加"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click); + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem2.Text = "修改"; + this.toolStripMenuItem2.Click += new System.EventHandler(this.toolStripMenuItem2_Click); + // + // toolStripMenuItem3 + // + this.toolStripMenuItem3.Name = "toolStripMenuItem3"; + this.toolStripMenuItem3.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem3.Text = "删除"; + this.toolStripMenuItem3.Click += new System.EventHandler(this.toolStripMenuItem3_Click); + // + // gridView3 + // + this.gridView3.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView3.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn7, + this.gridColumn12}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsBehavior.ReadOnly = true; + this.gridView3.OptionsSelection.MultiSelect = true; + this.gridView3.OptionsSelection.ResetSelectionClickOutsideCheckboxSelector = true; + this.gridView3.OptionsView.ColumnAutoWidth = false; + this.gridView3.OptionsView.ShowGroupPanel = false; + this.gridView3.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView3_RowCellClick); + this.gridView3.SelectionChanged += new DevExpress.Data.SelectionChangedEventHandler(this.gridView3_SelectionChanged); + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "群ID"; + this.gridColumn7.ColumnEdit = this.repositoryItemComboBox1; + this.gridColumn7.FieldName = "group_id"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 0; + this.gridColumn7.Width = 264; + // + // repositoryItemComboBox1 + // + this.repositoryItemComboBox1.AutoHeight = false; + this.repositoryItemComboBox1.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemComboBox1.Name = "repositoryItemComboBox1"; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "群昵称"; + this.gridColumn12.FieldName = "group_name"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + this.gridColumn12.Width = 168; + // + // repositoryItemPictureEdit1 + // + this.repositoryItemPictureEdit1.Name = "repositoryItemPictureEdit1"; + // + // gridControl2 + // + this.gridControl2.Location = new System.Drawing.Point(0, 131); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(547, 446); + this.gridControl2.TabIndex = 14; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn5, + this.gridColumn6, + this.gridColumn8}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView2_RowClick); + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick_1); + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "平台"; + this.gridColumn1.FieldName = "chatname"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "账号"; + this.gridColumn5.FieldName = "name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 1; + this.gridColumn5.Width = 188; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "账号昵称"; + this.gridColumn6.FieldName = "nick"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 2; + this.gridColumn6.Width = 172; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "禁止使用"; + this.gridColumn8.FieldName = "onoff"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 3; + this.gridColumn8.Width = 90; + // + // xtraTabPage6 + // + this.xtraTabPage6.Controls.Add(this.groupControl3); + this.xtraTabPage6.Name = "xtraTabPage6"; + this.xtraTabPage6.Size = new System.Drawing.Size(1139, 628); + this.xtraTabPage6.Text = " 进 群 通 知 开 关 "; + // + // groupControl3 + // + this.groupControl3.AutoSize = true; + this.groupControl3.Controls.Add(this.labelControl2); + this.groupControl3.Controls.Add(this.labelControl1); + this.groupControl3.Controls.Add(this.label4); + this.groupControl3.Controls.Add(this.label5); + this.groupControl3.Controls.Add(this.gridControl5); + this.groupControl3.Controls.Add(this.gridControl6); + this.groupControl3.Location = new System.Drawing.Point(29, 25); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(1080, 582); + this.groupControl3.TabIndex = 1; + this.groupControl3.Text = "新人入群通知开关设置"; + // + // labelControl2 + // + this.labelControl2.Appearance.BackColor = System.Drawing.Color.Black; + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.White; + this.labelControl2.Appearance.Options.UseBackColor = true; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(681, 3); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(216, 14); + this.labelControl2.TabIndex = 26; + this.labelControl2.Text = "右侧列表勾选为允许回复新人进群提示语"; + // + // labelControl1 + // + this.labelControl1.Appearance.BackColor = System.Drawing.Color.Black; + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.White; + this.labelControl1.Appearance.Options.UseBackColor = true; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(208, 3); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(364, 14); + this.labelControl1.TabIndex = 25; + this.labelControl1.Text = "注:列表中没有您要设置的群时,请给群发条信息,即可获取该群信息"; + // + // label4 + // + this.label4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label4.AutoSize = true; + this.label4.BackColor = System.Drawing.Color.White; + this.label4.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label4.Location = new System.Drawing.Point(641, 303); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(375, 35); + this.label4.TabIndex = 21; + this.label4.Text = "请点击左侧选中机器人"; + // + // label5 + // + this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label5.AutoSize = true; + this.label5.BackColor = System.Drawing.Color.White; + this.label5.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label5.Location = new System.Drawing.Point(5, 303); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(537, 35); + this.label5.TabIndex = 20; + this.label5.Text = "尚未登录机器人,请先登录机器人"; + // + // gridControl5 + // + this.gridControl5.Location = new System.Drawing.Point(564, 20); + this.gridControl5.MainView = this.gridView5; + this.gridControl5.Name = "gridControl5"; + this.gridControl5.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemPictureEdit2, + this.repositoryItemComboBox2}); + this.gridControl5.Size = new System.Drawing.Size(513, 559); + this.gridControl5.TabIndex = 15; + this.gridControl5.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView5}); + // + // gridView5 + // + this.gridView5.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView5.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView5.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn14, + this.gridColumn17, + this.gridColumn20}); + this.gridView5.GridControl = this.gridControl5; + this.gridView5.Name = "gridView5"; + this.gridView5.OptionsSelection.MultiSelect = true; + this.gridView5.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView5.OptionsView.ColumnAutoWidth = false; + this.gridView5.OptionsView.ShowGroupPanel = false; + this.gridView5.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView5_RowCellClick); + this.gridView5.SelectionChanged += new DevExpress.Data.SelectionChangedEventHandler(this.gridView5_SelectionChanged); + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "群ID"; + this.gridColumn14.ColumnEdit = this.repositoryItemComboBox2; + this.gridColumn14.FieldName = "group_id"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 1; + this.gridColumn14.Width = 176; + // + // repositoryItemComboBox2 + // + this.repositoryItemComboBox2.AutoHeight = false; + this.repositoryItemComboBox2.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.repositoryItemComboBox2.Name = "repositoryItemComboBox2"; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "群昵称"; + this.gridColumn17.FieldName = "group_nick"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.OptionsColumn.AllowFocus = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 2; + this.gridColumn17.Width = 161; + // + // gridColumn20 + // + this.gridColumn20.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn20.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn20.Caption = "群成员数"; + this.gridColumn20.FieldName = "member_num"; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.OptionsColumn.AllowFocus = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 3; + this.gridColumn20.Width = 82; + // + // repositoryItemPictureEdit2 + // + this.repositoryItemPictureEdit2.Name = "repositoryItemPictureEdit2"; + // + // gridControl6 + // + this.gridControl6.Location = new System.Drawing.Point(0, 20); + this.gridControl6.MainView = this.gridView6; + this.gridControl6.Name = "gridControl6"; + this.gridControl6.Size = new System.Drawing.Size(547, 559); + this.gridControl6.TabIndex = 14; + this.gridControl6.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView6}); + // + // gridView6 + // + this.gridView6.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView6.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView6.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn21, + this.gridColumn22, + this.gridColumn23, + this.gridColumn24}); + this.gridView6.GridControl = this.gridControl6; + this.gridView6.Name = "gridView6"; + this.gridView6.OptionsView.ShowGroupPanel = false; + this.gridView6.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView6_RowClick); + this.gridView6.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView6_RowCellClick); + // + // gridColumn21 + // + this.gridColumn21.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn21.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn21.Caption = "平台"; + this.gridColumn21.FieldName = "chatname"; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.OptionsColumn.AllowFocus = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 0; + // + // gridColumn22 + // + this.gridColumn22.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn22.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn22.Caption = "账号"; + this.gridColumn22.FieldName = "name"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.OptionsColumn.AllowEdit = false; + this.gridColumn22.OptionsColumn.AllowFocus = false; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 1; + this.gridColumn22.Width = 188; + // + // gridColumn23 + // + this.gridColumn23.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn23.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn23.Caption = "账号昵称"; + this.gridColumn23.FieldName = "nick"; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.OptionsColumn.AllowEdit = false; + this.gridColumn23.OptionsColumn.AllowFocus = false; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 2; + this.gridColumn23.Width = 172; + // + // gridColumn24 + // + this.gridColumn24.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn24.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn24.Caption = "禁止使用"; + this.gridColumn24.FieldName = "onoff"; + this.gridColumn24.Name = "gridColumn24"; + this.gridColumn24.OptionsColumn.AllowEdit = false; + this.gridColumn24.Visible = true; + this.gridColumn24.VisibleIndex = 3; + this.gridColumn24.Width = 90; + // + // xtraTabPage7 + // + this.xtraTabPage7.Controls.Add(this.label9); + this.xtraTabPage7.Controls.Add(this.gridControl7); + this.xtraTabPage7.Name = "xtraTabPage7"; + this.xtraTabPage7.Size = new System.Drawing.Size(1139, 628); + this.xtraTabPage7.Text = " 上 级 分 红 奖 励 设 置 "; + // + // label9 + // + this.label9.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label9.AutoSize = true; + this.label9.BackColor = System.Drawing.Color.White; + this.label9.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label9.Location = new System.Drawing.Point(317, 179); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(501, 35); + this.label9.TabIndex = 22; + this.label9.Text = "当前没有数据信息,请右击添加"; + // + // gridControl7 + // + this.gridControl7.ContextMenuStrip = this.contex_1; + this.gridControl7.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl7.Location = new System.Drawing.Point(0, 0); + this.gridControl7.MainView = this.gridView7; + this.gridControl7.Name = "gridControl7"; + this.gridControl7.Size = new System.Drawing.Size(1139, 628); + this.gridControl7.TabIndex = 2; + this.gridControl7.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView7}); + // + // contex_1 + // + this.contex_1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加ToolStripMenuItem, + this.修改ToolStripMenuItem, + this.删除ToolStripMenuItem}); + this.contex_1.Name = "contextMenuStrip1"; + this.contex_1.Size = new System.Drawing.Size(101, 70); + this.contex_1.Opening += new System.ComponentModel.CancelEventHandler(this.contex_1_Opening); + // + // 增加ToolStripMenuItem + // + this.增加ToolStripMenuItem.Name = "增加ToolStripMenuItem"; + this.增加ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.增加ToolStripMenuItem.Text = "增加"; + this.增加ToolStripMenuItem.Click += new System.EventHandler(this.增加ToolStripMenuItem_Click); + // + // 修改ToolStripMenuItem + // + this.修改ToolStripMenuItem.Name = "修改ToolStripMenuItem"; + this.修改ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.修改ToolStripMenuItem.Text = "修改"; + this.修改ToolStripMenuItem.Click += new System.EventHandler(this.修改ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // gridView7 + // + this.gridView7.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView7.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView7.Appearance.Row.Options.UseTextOptions = true; + this.gridView7.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView7.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn25, + this.gridColumn27}); + this.gridView7.GridControl = this.gridControl7; + this.gridView7.Name = "gridView7"; + this.gridView7.OptionsBehavior.ReadOnly = true; + this.gridView7.OptionsView.ShowGroupPanel = false; + // + // gridColumn25 + // + this.gridColumn25.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn25.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn25.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn25.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn25.Caption = "下级订单总数等于"; + this.gridColumn25.FieldName = "subordinate_order_totle"; + this.gridColumn25.Name = "gridColumn25"; + this.gridColumn25.OptionsColumn.AllowEdit = false; + this.gridColumn25.OptionsColumn.AllowFocus = false; + this.gridColumn25.Visible = true; + this.gridColumn25.VisibleIndex = 0; + this.gridColumn25.Width = 230; + // + // gridColumn27 + // + this.gridColumn27.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn27.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn27.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn27.Caption = "上级奖励金额"; + this.gridColumn27.FieldName = "superior_point_reward"; + this.gridColumn27.Name = "gridColumn27"; + this.gridColumn27.OptionsColumn.AllowEdit = false; + this.gridColumn27.OptionsColumn.AllowFocus = false; + this.gridColumn27.Visible = true; + this.gridColumn27.VisibleIndex = 1; + this.gridColumn27.Width = 225; + // + // xtraTabPage8 + // + this.xtraTabPage8.Controls.Add(this.gridControl8); + this.xtraTabPage8.Controls.Add(this.pageControl3); + this.xtraTabPage8.Name = "xtraTabPage8"; + this.xtraTabPage8.PageVisible = false; + this.xtraTabPage8.Size = new System.Drawing.Size(1139, 628); + this.xtraTabPage8.Text = " 微 信 关 键 词 拉 群 "; + // + // gridControl8 + // + this.gridControl8.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl8.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl8.Location = new System.Drawing.Point(0, 0); + this.gridControl8.MainView = this.gridView8; + this.gridControl8.Name = "gridControl8"; + this.gridControl8.Size = new System.Drawing.Size(1139, 596); + this.gridControl8.TabIndex = 6; + this.gridControl8.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView8}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem4, + this.toolStripMenuItem5, + this.toolStripMenuItem6}); + this.contextMenuStrip2.Name = "contextMenuStrip1"; + this.contextMenuStrip2.Size = new System.Drawing.Size(101, 70); + // + // toolStripMenuItem4 + // + this.toolStripMenuItem4.Name = "toolStripMenuItem4"; + this.toolStripMenuItem4.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem4.Text = "增加"; + this.toolStripMenuItem4.Click += new System.EventHandler(this.toolStripMenuItem4_Click); + // + // toolStripMenuItem5 + // + this.toolStripMenuItem5.Name = "toolStripMenuItem5"; + this.toolStripMenuItem5.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem5.Text = "修改"; + // + // toolStripMenuItem6 + // + this.toolStripMenuItem6.Name = "toolStripMenuItem6"; + this.toolStripMenuItem6.Size = new System.Drawing.Size(100, 22); + this.toolStripMenuItem6.Text = "删除"; + // + // gridView8 + // + this.gridView8.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn32, + this.gridColumn30, + this.gridColumn26, + this.gridColumn28, + this.gridColumn29}); + this.gridView8.GridControl = this.gridControl8; + this.gridView8.Name = "gridView8"; + this.gridView8.OptionsView.ShowGroupPanel = false; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn11.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "ID"; + this.gridColumn11.FieldName = "id"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.OptionsColumn.AllowFocus = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + this.gridColumn11.Width = 48; + // + // gridColumn32 + // + this.gridColumn32.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn32.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn32.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn32.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn32.Caption = "微信号"; + this.gridColumn32.FieldName = "robot_name"; + this.gridColumn32.Name = "gridColumn32"; + this.gridColumn32.Visible = true; + this.gridColumn32.VisibleIndex = 1; + // + // gridColumn30 + // + this.gridColumn30.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn30.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn30.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn30.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn30.Caption = "微信昵称"; + this.gridColumn30.FieldName = "robot_nice"; + this.gridColumn30.Name = "gridColumn30"; + this.gridColumn30.Visible = true; + this.gridColumn30.VisibleIndex = 2; + // + // gridColumn26 + // + this.gridColumn26.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn26.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn26.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn26.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn26.Caption = "匹配模式"; + this.gridColumn26.FieldName = "match_pattern"; + this.gridColumn26.Name = "gridColumn26"; + this.gridColumn26.OptionsColumn.AllowEdit = false; + this.gridColumn26.OptionsColumn.AllowFocus = false; + this.gridColumn26.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn26.Visible = true; + this.gridColumn26.VisibleIndex = 3; + this.gridColumn26.Width = 66; + // + // gridColumn28 + // + this.gridColumn28.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn28.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn28.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn28.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn28.Caption = "关键词"; + this.gridColumn28.FieldName = "antistop"; + this.gridColumn28.Name = "gridColumn28"; + this.gridColumn28.OptionsColumn.AllowEdit = false; + this.gridColumn28.OptionsColumn.AllowFocus = false; + this.gridColumn28.Visible = true; + this.gridColumn28.VisibleIndex = 4; + this.gridColumn28.Width = 118; + // + // gridColumn29 + // + this.gridColumn29.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn29.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn29.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn29.Caption = "推送群"; + this.gridColumn29.FieldName = "content"; + this.gridColumn29.Name = "gridColumn29"; + this.gridColumn29.OptionsColumn.AllowEdit = false; + this.gridColumn29.OptionsColumn.AllowFocus = false; + this.gridColumn29.Visible = true; + this.gridColumn29.VisibleIndex = 5; + this.gridColumn29.Width = 208; + // + // pageControl3 + // + this.pageControl3.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl3.Location = new System.Drawing.Point(0, 596); + this.pageControl3.Name = "pageControl3"; + this.pageControl3.Size = new System.Drawing.Size(1139, 32); + this.pageControl3.TabIndex = 5; + // + // gridColumn19 + // + this.gridColumn19.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn19.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn19.Caption = "数据来源"; + this.gridColumn19.FieldName = "goods_source"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.OptionsColumn.AllowFocus = false; + this.gridColumn19.Width = 83; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1141, 654); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.text_userinfo.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage5.ResumeLayout(false); + this.xtraTabPage5.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraTabPage4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemComboBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage6.ResumeLayout(false); + this.xtraTabPage6.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + this.groupControl3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl5)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView5)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemComboBox2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl6)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView6)).EndInit(); + this.xtraTabPage7.ResumeLayout(false); + this.xtraTabPage7.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl7)).EndInit(); + this.contex_1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView7)).EndInit(); + this.xtraTabPage8.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl8)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView8)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.TextEdit text_userinfo; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraEditors.LabelControl labelControl10; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit1; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraEditors.Repository.RepositoryItemComboBox repositoryItemComboBox1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage5; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl4; + private DevExpress.XtraGrid.Views.Grid.GridView gridView4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.GroupControl groupControl2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.RadioButton radioButton2; + private System.Windows.Forms.RadioButton radioButton1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage6; + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private DevExpress.XtraGrid.GridControl gridControl5; + private DevExpress.XtraGrid.Views.Grid.GridView gridView5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraEditors.Repository.RepositoryItemComboBox repositoryItemComboBox2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit2; + private DevExpress.XtraGrid.GridControl gridControl6; + private DevExpress.XtraGrid.Views.Grid.GridView gridView6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn24; + private DevExpress.XtraTab.XtraTabPage xtraTabPage7; + private DevExpress.XtraGrid.GridControl gridControl7; + private DevExpress.XtraGrid.Views.Grid.GridView gridView7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn25; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn27; + private System.Windows.Forms.ContextMenuStrip contex_1; + private System.Windows.Forms.ToolStripMenuItem 增加ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage8; + private DevExpress.XtraGrid.GridControl gridControl8; + private DevExpress.XtraGrid.Views.Grid.GridView gridView8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn32; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn30; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn26; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn28; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn29; + private UI.Framework.Controls.PageControl pageControl3; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem4; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem5; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem6; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + } +} \ No newline at end of file diff --git a/应用/UserFission/MainForm.cs b/应用/UserFission/MainForm.cs new file mode 100644 index 0000000..07f5267 --- /dev/null +++ b/应用/UserFission/MainForm.cs @@ -0,0 +1,966 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using UserFission.Entitys; +using UserFission.Properties; + +namespace UserFission +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void RefreshRewards() + { + var result = Tools.FindRewards(true); + label9.Visible = result.Count == 0; + gridControl7.DataSource = result; + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + if (Class1.Config.InviteGroupInfo2 == null) + { + if (Class1.Config.InviteGroupInfo != null && Class1.Config.InviteGroupInfo.Count != 0) + { + Class1.Config.InviteGroupInfo2 = new Dictionary<string, wxinfo>(); + + foreach (var item in Class1.Config.InviteGroupInfo) + { + var wx = new wxinfo(); + wx.onoff = item.Value.onoff; + var groupIds = item.Value.groupIds; + foreach (var _item in groupIds) + { + if (!wx.groupInfos.ContainsKey(_item)) + wx.groupInfos.Add(_item, string.Empty); + } + Class1.Config.InviteGroupInfo2.Add(item.Key, wx); + } + } + } + + settingControl1.Bind(Class1.Config, 130); + + #region 加载账号邀请码信息数据 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var where = string.IsNullOrWhiteSpace(text_userinfo.Text) ? "" : $"where m.username like '%{text_userinfo.Text.Replace("'", "''").Trim()}%' OR m.usernick like '%{text_userinfo.Text.Replace("'", "''").Trim()}%' OR ic.code like '%{text_userinfo.Text.Replace("'", "''").Trim()}%'"; + var result = session.FindPage<user_invitation_code_temp>($"select m.id,m.robot_type as chattype,m.username as name,m.usernick as nick,ic.crt_time as crt_time,ic.code as code from fl_plugin_userfission_user_invitation_code ic LEFT JOIN fl_member_info m on ic.member_info_id = m.id {where}", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + var f = new ImageDesignForm(); + f.TopLevel = false; + f.Parent = this.xtraTabPage2; + f.Show(); + + #endregion + + #region 加载所有的账号 + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<automatic_approval_setting_temp>("select r.id as rid,r.name as name,r.nick as nick,a.onoff as onoff from fl_robot_info r left join fl_plugin_userfission_automatic_approval_setting a on r.id = a.rid", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl4, 40, true, true); + + label3.Visible = gridView4.RowCount == 0; + + #endregion + + RefreshRewards(); + + numericUpDown1.Value = Class1.Config.FinishOrder_Rule; + if (Class1.Config.InvitegroupWay) + radioButton1.Checked = true; + else + radioButton2.Checked = true; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 窗体关闭 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + //比较最大值和最小值是否合法 + if (Class1.Config.SuperiorSum1 > Class1.Config.SuperiorSum2)//推荐人奖励不符合 + { + ShowError("推荐人奖励设置不合法:最大值不能小于最小值"); + e.Cancel = true; + } + else if (Class1.Config.SubordinateSum1 > Class1.Config.SubordinateSum2)//新人奖励不符合 + { + ShowError("新人奖励设置不合法:最大值不能小于最小值"); + e.Cancel = true; + } + if (!e.Cancel) + { + Util.Save(Class1.Config); + OrderHelper.RefreshConfig(true); + //TimerTask.Close<ApplyFriendThread>(); + //TimerTask.NewTimer<ApplyFriendThread>(Class1.Config.Retardation); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e) + { + try + { + if (e.Column.Caption == "邀请码") + { + if (string.IsNullOrWhiteSpace(e.Value.ToString())) + throw new Exception("邀请码不能为空"); + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取ID列的数据 + if (!Tools.CheckInvitationCode(e.Value.ToString())) + throw new Exception("邀请码已经存在,请换一组!"); + else + { + var session = ApiClient.GetSession(); + var invitation_code = session.Find<fl_plugin_userfission_user_invitation_code>("select * from fl_plugin_userfission_user_invitation_code where member_info_id = @id", new { id = id }); + session.ExcuteSQL("update fl_plugin_userfission_user_invitation_code set code = @code where member_info_id = @id", new { code = e.Value.ToString(), id = id }); + ShowSuccess("修改成功"); + pageControl1.GotoPage(1); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 搜索用户信息 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + pageControl1.GotoPage(1); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// tab标签改变的时候,将改变 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void xtraTabControl1_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e) + { + try + { + if (xtraTabControl1.SelectedTabPageIndex == 3) + { + //&& f.WeixinType == WeixinType.Grpc微信 + var wxBases = Chat.Framework.ChatClient.WXClient.Values.ToList().ToList().Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线).ToList(); + if (wxBases != null) + { + label1.Visible = wxBases.Count == 0; + label2.Visible = gridView3.RowCount == 0; + + List<object> objList = new List<object>(); + if (Class1.Config.InviteGroupInfo2 == null) + Class1.Config.InviteGroupInfo2 = new Dictionary<string, wxinfo>(); + foreach (var item in wxBases) + { + var key = Class1.Config.InviteGroupInfo2.Keys.FirstOrDefault(f => f == item.WeixinHao); + if (!string.IsNullOrEmpty(key)) + { + var result = Class1.Config.InviteGroupInfo2[key]; + objList.Add(new { chatname = (item.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信), name = key, nick = item.User.Nick, onoff = result.onoff }); + } + else + { + objList.Add(new { chatname = (item.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信), name = item.WeixinHao, nick = item.User.Nick, onoff = false }); + //Class1.Config.InviteGroupInfo.Add(item.WeixinHao, new wx_info() { onoff = false, groupIds = new List<string>() });//字典中不存在,添加一条 + Class1.Config.InviteGroupInfo2.Add(item.WeixinHao, new wxinfo() { onoff = false, groupInfos = new Dictionary<string, string>() });//字典中不存在,添加一条 + } + } + gridControl2.DataSource = objList; + } + } + else if (xtraTabControl1.SelectedTabPageIndex == 4) + { + List<object> objList = new List<object>(); + // && f.WeixinType == WeixinType.Grpc微信 + var wxBases = Chat.Framework.ChatClient.WXClient.Values.ToList().Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线).ToList(); + if (wxBases != null) + { + //label5.Visible = qqBases.Count == 0; + //label4.Visible = gridView5.RowCount == 0; + + //List<wx_info> wxkey = new List<wx_info>(); + foreach (var item in wxBases) + { + var key = Class1.Config.NewComerGroupInfo.Keys.FirstOrDefault(f => f == item.WeixinHao); + if (!string.IsNullOrEmpty(key)) + { + var result = Class1.Config.NewComerGroupInfo[key]; + objList.Add(new { chatname = ChatType.微信, name = key, nick = item.User.Nick, onoff = result.onoff }); + } + else + { + objList.Add(new { chatname = ChatType.微信, name = item.WeixinHao, nick = item.User.Nick, onoff = false }); + Class1.Config.NewComerGroupInfo.Add(item.WeixinHao, new wx_info() { onoff = false, groupIds = new List<string>() });//字典中不存在,添加一条 + } + } + } + + label5.Visible = objList.Count == 0; + label4.Visible = gridView5.RowCount == 0; + + gridControl6.DataSource = objList; + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + private void RefreshGroupView() + { + #region 通过手动添加群信息 + if (!string.IsNullOrWhiteSpace(weixinhao)) + { + if (Class1.Config.InviteGroupInfo2.ContainsKey(weixinhao)) + { + List<int> checkedIndexs = new List<int>(); + var wx = Class1.Config.InviteGroupInfo2[weixinhao]; + //wx.onoff + List<object> objList = new List<object>(); + foreach (var item in wx.groupInfos) + { + objList.Add(new { group_id = item.Key, group_name = item.Value }); + //if (item.Count != 0) + //{ + // if (item.Contains(item.UserName)) + // checkedIndexs.Add(i); + //} + //i++; + } + gridControl3.DataSource = objList; + if (checkedIndexs.Count != 0) + { + int[] indexs = checkedIndexs.ToArray(); + foreach (var index in checkedIndexs) + { + gridView3.SelectRow(index); + } + } + label2.Visible = gridView3.RowCount == 0; + } + } + #endregion + } + + /// <summary> + /// 左边的列表点击后保存下来的微信号 + /// </summary> + string weixinhao = string.Empty; + + //点击机器人,获取右边的机器人对应的配置 + private void gridView2_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + try + { + if (e.Clicks == 1) + { + var rows = gridView2.GetSelectedRows(); + if (rows != null && rows.Length != 0) + { + weixinhao = this.gridView2.GetRowCellValue(rows[0], "name").ToString(); + RefreshGroupView(); + + //if (!string.IsNullOrEmpty(weixinhao)) + //{ + #region 之前读取通讯录 xxx + //var wxBase = Chat.Framework.ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == weixinhao && f.Status == Chat.Framework.WXSdk.WxStatus.在线 && f.WeixinType == WeixinType.Grpc微信); + //if (wxBase != null) + //{ + // var ipad = wxBase as WXClientImpl_IPAD; + // if (ipad == null) return; + // if (ipad.Friends.Count == 0) + // { + // Loding.ShowWaitForm(); + // xtraTabControl1.Enabled = false; + // ipad.RefreshContact(); + // int executionTime = 700; + // while (ipad.IsRefreshContact) + // { + // this.Sleep(1000); + // executionTime--; + // if (executionTime <= 0) + // { + // Loding.CloseWaitForm(); + // throw new Exception("获取好友超时"); + // } + // } + // xtraTabControl1.Enabled = true; + // Loding.CloseWaitForm(); + // } + // var groups = ipad.Friends.Values.Where(f => !string.IsNullOrEmpty(f.ChatRoomOwner)); + // List<string> groupInfo = new List<string>(); + // if (Class1.Config.InviteGroupInfo.ContainsKey(weixinhao)) + // { + // groupInfo = Class1.Config.InviteGroupInfo[weixinhao].groupIds; + // } + // List<object> objList = new List<object>(); + // List<int> checkedIndexs = new List<int>(); + // int i = 0; + // foreach (var item in groups) + // { + // var memberNum = item.ExtInfo.Replace(",", ",").Split(',').Length;//人员数量 + // objList.Add(new { group_id = item.UserName, group_nick = item.NickName, member_num = memberNum }); + // if (groupInfo.Count != 0) + // { + // if (groupInfo.Contains(item.UserName)) + // checkedIndexs.Add(i); + // } + // i++; + // } + // gridControl3.DataSource = objList; + // if (checkedIndexs.Count != 0) + // { + // int[] indexs = checkedIndexs.ToArray(); + // foreach (var index in checkedIndexs) + // { + // gridView3.SelectRow(index); + // } + // } + //} + //label2.Visible = gridView3.RowCount == 0; + #endregion + //} + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + xtraTabControl1.Enabled = true; + } + } + + private void gridView3_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + //try + //{ + // if (string.IsNullOrEmpty(weixinhao)) throw new Exception("请点击左侧列表选择机器人账号"); + // if (e.Column.AbsoluteIndex == -1) + // { + // var flag = e.CellValue.ToString().ToLower() != "true"; + // var groupIds = Class1.Config.InviteGroupInfo2[weixinhao].groupInfos;//获取配置文件中的群号集合 + // var group_id = gridView3.GetRowCellDisplayText(gridView3.FocusedRowHandle, gridView3.Columns["group_id"]);//获取群号 + // if (flag)//增加到集合中 + // { + // if (!groupIds.ContainsKey(group_id)) + // { + // var group_name = gridView3.GetRowCellDisplayText(gridView3.FocusedRowHandle, gridView3.Columns["group_name"]);//获取群号 + // groupIds.Add(group_id, group_name); + // } + // } + // else + // { + // if (groupIds.ContainsKey(group_id)) + // groupIds.Remove(group_id); + // } + // Util.Save(Class1.Config); + // } + //} + //catch (Exception ex) + //{ + // ShowError(ex); + //} + } + + private void gridView3_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e) + { + //try + //{ + // if (e.ControllerRow < 0) + // { + // if (string.IsNullOrEmpty(weixinhao)) throw new Exception("请点击左侧列表选择机器人账号"); + // var groupIds = Class1.Config.InviteGroupInfo2[weixinhao].groupInfos;//获取配置文件中的群号集合 + // groupIds.Clear(); + // if (gridView3.SelectedRowsCount != 0) + // { + // for (int i = 0; i < gridView3.SelectedRowsCount; i++) + // { + // var group_id = gridView3.GetRowCellDisplayText(i, gridView3.Columns["group_id"]);//获取群号 + // if (!groupIds.ContainsKey(group_id))//增加到集合中 + // { + // var group_name = gridView3.GetRowCellDisplayText(i, gridView3.Columns["group_name"]);//获取群号 + // groupIds.Add(group_id, group_name); + // } + // } + // } + // Util.Save(Class1.Config); + // } + //} + //catch (Exception ex) + //{ + // ShowError(ex); + //} + } + + private void gridView2_RowCellClick_1(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 开关单元格单击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + label2.Visible = gridView3.RowCount == 0; + + if (!(bool)e.CellValue && MessageBox.Show("该微信确定禁用使用拉群功能吗?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var name = gridView2.GetRowCellDisplayText(gridView2.FocusedRowHandle, gridView2.Columns["name"]);//获取群号 + + var inviteGroupInfo2 = Class1.Config.InviteGroupInfo2[name]; + inviteGroupInfo2.onoff = !inviteGroupInfo2.onoff; + Util.Save(Class1.Config); + xtraTabControl1.SelectedTabPageIndex = 1; + xtraTabControl1.SelectedTabPageIndex = 3; + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void radioButton_CheckedChanged(object sender, EventArgs e) + { + try + { + Class1.Config.InvitegroupWay = radioButton1.Checked; + Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void numericUpDown1_ValueChanged(object sender, EventArgs e) + { + try + { + Class1.Config.FinishOrder_Rule = (int)numericUpDown1.Value; + Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView4_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + var selectRow = gridView4.GetSelectedRows()[0]; + var id = this.gridView4.GetRowCellValue(selectRow, "rid").ToString();//获取列的数据 + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("自动通过好友申请开关开启时,确定禁用该微信功能?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var aas = session.Find<fl_plugin_userfission_automatic_approval_setting>("select * from fl_plugin_userfission_automatic_approval_setting where rid = @id", new { id = id }).FirstOrDefault(); + if (aas != null)//数据库中存在 + { + aas.onoff = !aas.onoff; + session.Updateable(aas).ExecuteCommand(); + } + else + { + aas = new fl_plugin_userfission_automatic_approval_setting() { onoff = true, rid = int.Parse(id) }; + session.Insertable<fl_plugin_userfission_automatic_approval_setting>(aas).ExecuteCommand(); + } + pageControl2.GotoPage(1); + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView6_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 开关单元格单击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + label4.Visible = gridView5.RowCount == 0; + + if (!(bool)e.CellValue && MessageBox.Show("该微信确定禁用使用拉群功能吗?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var name = gridView6.GetRowCellDisplayText(gridView6.FocusedRowHandle, gridView6.Columns["name"]);//获取群号 + + var NewComerGroupInfo = Class1.Config.NewComerGroupInfo[name]; + NewComerGroupInfo.onoff = !NewComerGroupInfo.onoff; + Util.Save(Class1.Config); + xtraTabControl1.SelectedTabPageIndex = 1; + xtraTabControl1.SelectedTabPageIndex = 4; + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + //点击机器人,获取右边的机器人对应的配置 + private void gridView6_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + try + { + if (e.Clicks == 1) + { + var rows = gridView6.GetSelectedRows(); + if (rows != null && rows.Length != 0) + { + weixinhao = this.gridView6.GetRowCellValue(rows[0], "name").ToString(); + if (!string.IsNullOrEmpty(weixinhao)) + { + var wxBase = Chat.Framework.ChatClient.WXClient.Values.ToList().FirstOrDefault(f => f.WeixinHao == weixinhao && f.Status == Chat.Framework.WXSdk.WxStatus.在线);//&& f.WeixinType == WeixinType.Grpc微信 + if (wxBase != null) + { + List<object> objList = new List<object>(); + List<int> checkedIndexs = new List<int>(); + List<string> groupInfo = new List<string>(); + + if (wxBase.GetType() == typeof(WXClientImpl_IPAD)) + { + var ipad = wxBase as WXClientImpl_IPAD; + if (ipad == null) return; + if (ipad.Friends.Count == 0) + { + Loding.ShowWaitForm(); + xtraTabControl1.Enabled = false; + ipad.RefreshContact(); + int executionTime = 700; + while (ipad.IsRefreshContact) + { + this.Sleep(1000); + executionTime--; + if (executionTime <= 0) + { + Loding.CloseWaitForm(); + throw new Exception("获取好友超时"); + } + } + xtraTabControl1.Enabled = true; + Loding.CloseWaitForm(); + } + var groups = ipad.Friends.Values.Where(f => !string.IsNullOrEmpty(f.ChatRoomOwner)); + + if (Class1.Config.NewComerGroupInfo.ContainsKey(weixinhao)) + { + groupInfo = Class1.Config.NewComerGroupInfo[weixinhao].groupIds; + } + + int i = 0; + foreach (var item in groups) + { + var memberNum = item.ExtInfo.Replace(",", ",").Split(',').Length;//人员数量 + objList.Add(new { group_id = item.UserName, group_nick = item.NickName, member_num = memberNum }); + if (groupInfo.Count != 0) + { + if (groupInfo.Contains(item.UserName)) + checkedIndexs.Add(i); + } + i++; + } + } + else if (wxBase.GetType() == typeof(WXClientImpl_HOOK)) + { + var hook = wxBase as WXClientImpl_HOOK; + if (hook == null) return; + if (hook.GroupMembers != null) + { + if (Class1.Config.NewComerGroupInfo.ContainsKey(weixinhao)) + groupInfo = Class1.Config.NewComerGroupInfo[weixinhao].groupIds; + + int i = 0; + foreach (var item in hook.GroupMembers) + { + var memberNum = item.Value.ToList();//人员数量 + objList.Add(new { group_id = item.Key, group_nick = (hook.Friends == null ? "无" : hook.Friends.ContainsKey(item.Key) ? hook.Friends[item.Key].NickName : "无"), member_num = memberNum }); + if (groupInfo.Count != 0) + { + if (groupInfo.Contains(item.Key)) + checkedIndexs.Add(i); + } + i++; + } + } + } + + gridControl5.DataSource = objList; + if (checkedIndexs.Count != 0) + { + int[] indexs = checkedIndexs.ToArray(); + foreach (var index in checkedIndexs) + { + gridView5.SelectRow(index); + } + } + } + label4.Visible = gridView5.RowCount == 0; + } + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + xtraTabControl1.Enabled = true; + } + } + + private void gridView5_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + if (string.IsNullOrEmpty(weixinhao)) throw new Exception("请点击左侧列表选择机器人账号"); + if (e.Column.AbsoluteIndex == -1) + { + var flag = e.CellValue.ToString().ToLower() != "true"; + var groupIds = Class1.Config.NewComerGroupInfo[weixinhao].groupIds;//获取配置文件中的群号集合 + var group_id = gridView5.GetRowCellDisplayText(gridView5.FocusedRowHandle, gridView5.Columns["group_id"]);//获取群号 + if (flag)//增加到集合中 + { + if (!groupIds.Contains(group_id)) + groupIds.Add(group_id); + } + else + { + if (groupIds.Contains(group_id)) + groupIds.Remove(group_id); + } + Util.Save(Class1.Config); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView5_SelectionChanged(object sender, DevExpress.Data.SelectionChangedEventArgs e) + { + try + { + if (e.ControllerRow < 0) + { + if (string.IsNullOrEmpty(weixinhao)) throw new Exception("请点击左侧列表选择机器人账号"); + var groupIds = Class1.Config.NewComerGroupInfo[weixinhao].groupIds;//获取配置文件中的群号集合 + groupIds.Clear(); + if (gridView5.SelectedRowsCount != 0) + { + for (int i = 0; i < gridView5.SelectedRowsCount; i++) + { + var group_id = gridView5.GetRowCellDisplayText(i, gridView5.Columns["group_id"]);//获取群号 + if (!groupIds.Contains(group_id))//增加到集合中 + groupIds.Add(group_id); + } + } + Util.Save(Class1.Config); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 增加ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + try + { + var entity = new fl_plugin_userfission_superior_reward(); + SettingForm form = new SettingForm(entity); + form.Text = "增加奖励条件"; + form.ShowDialog(); + if (entity.subordinate_order_totle == 0) + { + if (!this.IsDisposed) BaseForm.ShowError("下级订单数不能为零"); + return; + } + var session = ApiClient.GetSession(); + session.Saveable(entity).ExecuteCommand(); + } + catch + { + if (!this.IsDisposed) BaseForm.ShowError("数据违反唯一性,请勿重复增加"); + } + RefreshRewards(); + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void 修改ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView7.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView7.GetRow(rows[0]) as fl_plugin_userfission_superior_reward; + SettingForm form = new SettingForm(row); + form.ShowDialog(); + + var session = ApiClient.GetSession(); + session.Saveable(row).ExecuteCommand(); + RefreshRewards(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView7.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = gridView7.GetRow(rows[0]) as base_model; + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_userfission_superior_reward where id = @id", new { id = row.id }); + RefreshRewards(); + } + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void contex_1_Opening(object sender, System.ComponentModel.CancelEventArgs e) + { + try + { + var rows = gridView7.GetSelectedRows(); + 修改ToolStripMenuItem.Enabled = 删除ToolStripMenuItem.Enabled = (rows != null && rows.Length > 0); + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(weixinhao)) throw new Exception("请先选择左侧列表机器人"); + var groupForm = new EditGroupForm(weixinhao); + groupForm.ShowDialog(); + RefreshGroupView(); + } + catch (Exception ex) + { + if (!this.IsDisposed) BaseForm.ShowError(ex); + } + } + + private void toolStripMenuItem2_Click(object sender, EventArgs e) + { + try + { + var rows = gridView3.GetSelectedRows(); + if (rows != null && rows.Length != 0) + { + if (string.IsNullOrEmpty(weixinhao)) throw new Exception("请先选择左侧列表机器人"); + + var group_id = this.gridView3.GetRowCellValue(rows[0], "group_id").ToString(); + var group_nameObj = this.gridView3.GetRowCellValue(rows[0], "group_name"); + var group_name = (group_nameObj == null ? string.Empty : group_nameObj.ToString()); + var groupForm = new EditGroupForm(weixinhao, group_id, group_name); + groupForm.ShowDialog(); + RefreshGroupView(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void toolStripMenuItem3_Click(object sender, EventArgs e) + { + try + { + var rows = gridView3.GetSelectedRows(); + if (rows.Length != 0) + { + if (string.IsNullOrEmpty(weixinhao)) throw new Exception("请先选择左侧列表机器人"); + for (int i = rows.Length - 1; i >= 0; i--) + { + var group_id = this.gridView3.GetRowCellValue(rows[i], "group_id").ToString(); + if (Class1.Config.InviteGroupInfo2.ContainsKey(weixinhao) && Class1.Config.InviteGroupInfo2[weixinhao].groupInfos.ContainsKey(group_id)) + { + + Class1.Config.InviteGroupInfo2[weixinhao].groupInfos.Remove(group_id); + } + } + RefreshGroupView(); + ShowSuccessAutoClose("删除成功"); + } + } + catch (Exception ex) + { + + } + } + + private void toolStripMenuItem4_Click(object sender, EventArgs e) + { + //try + //{ + // var selectRows = gridView1.GetSelectedRows(); + // if (toolStripMenuItem4.Text.Contains("增")) + // { + // var editUserDefined = new EditUserDefinedForm(string.Empty); + // editUserDefined.ShowDialog(); + // } + // else if (selectRows.Length > 0) + // { + // if (toolStripMenuItem4.Text.Contains("修")) + // { + // var editUserDefined = new EditUserDefinedForm(gridView1.GetRowCellValue(selectRows[0], "id").ToString()); + // editUserDefined.ShowDialog(); + // } + // else if (e.Item.Caption == "删除所有项") + // { + // var session = ApiClient.GetSession(); + // session.Deleteable<fl_plugin_autoanswer_userdefinedlibrary>().ExecuteCommand(); + // } + // else if (toolStripMenuItem4.Text.Contains("删")) + // { + // var session = ApiClient.GetSession(); + // try + // { + // for (int i = selectRows.Length - 1; i >= 0; i--) + // { + // var pram = session.NewParamMap(); + // var id = gridView1.GetRowCellValue(selectRows[i], "id").ToString(); + // session.ExcuteSQL($"DELETE FROM fl_plugin_autoanswer_userdefinedlibrary where id = @id", new { id = id }); + // } + // } + // catch (Exception ex) + // { + // throw ex; + // } + // } + // } + //} + //catch (Exception ex) + //{ + // ShowError(ex); + //} + //finally + //{ + // Tools.RefreshWordbanck(); + // this.pageControl1.GotoPage(1); + // label6.Visible = gridView1.RowCount == 0; + //} + } + } +} \ No newline at end of file diff --git a/应用/UserFission/MainForm.resx b/应用/UserFission/MainForm.resx new file mode 100644 index 0000000..94002c4 --- /dev/null +++ b/应用/UserFission/MainForm.resx @@ -0,0 +1,135 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>213, 17</value> + </metadata> + <metadata name="contex_1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <metadata name="contextMenuStrip2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>378, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>46</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/UserFission/Properties/AssemblyInfo.cs b/应用/UserFission/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..865c652 --- /dev/null +++ b/应用/UserFission/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("UserFission")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("UserFission")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("ba23ebcb-6efa-4779-be34-58f4ffec0aaa")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.1")] +[assembly: AssemblyFileVersion("1.0.0.1")] diff --git a/应用/UserFission/Properties/Resources.Designer.cs b/应用/UserFission/Properties/Resources.Designer.cs new file mode 100644 index 0000000..c1f650c --- /dev/null +++ b/应用/UserFission/Properties/Resources.Designer.cs @@ -0,0 +1,179 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace UserFission.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UserFission.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 客户裂变 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 裂变海报 的本地化字符串。 + /// </summary> + internal static string PluginBillTitle { + get { + return ResourceManager.GetString("PluginBillTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 客户裂变 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 客户裂变插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 分组 { + get { + object obj = ResourceManager.GetObject("分组", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 列表 { + get { + object obj = ResourceManager.GetObject("列表", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 开关 { + get { + object obj = ResourceManager.GetObject("开关", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 海报 { + get { + object obj = ResourceManager.GetObject("海报", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 用户分裂 { + get { + object obj = ResourceManager.GetObject("用户分裂", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 背景 { + get { + object obj = ResourceManager.GetObject("背景", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 通知 { + get { + object obj = ResourceManager.GetObject("通知", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/UserFission/Properties/Resources.resx b/应用/UserFission/Properties/Resources.resx new file mode 100644 index 0000000..062bff8 --- /dev/null +++ b/应用/UserFission/Properties/Resources.resx @@ -0,0 +1,161 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="MainFormTitle" xml:space="preserve"> + <value>客户裂变</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>客户裂变</value> + <comment>插件名</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>客户裂变插件</value> + <comment>插件介绍</comment> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="基础管理" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="开关" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\开关.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="背景" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\背景.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="用户分裂" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\用户分裂.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="PluginBillTitle" xml:space="preserve"> + <value>裂变海报</value> + <comment>裂变海报标题</comment> + </data> + <data name="分组" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\分组.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="列表" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\列表.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="海报" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\海报.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="通知" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\通知.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/UserFission/Properties/licenses.licx b/应用/UserFission/Properties/licenses.licx new file mode 100644 index 0000000..3efd544 --- /dev/null +++ b/应用/UserFission/Properties/licenses.licx @@ -0,0 +1,4 @@ +DevExpress.XtraEditors.Repository.RepositoryItemComboBox, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/UserFission/QRCodeForm.Designer.cs b/应用/UserFission/QRCodeForm.Designer.cs new file mode 100644 index 0000000..b30e466 --- /dev/null +++ b/应用/UserFission/QRCodeForm.Designer.cs @@ -0,0 +1,249 @@ +namespace UserFission +{ + partial class QRCodeForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.groupBox_ImageType = new System.Windows.Forms.GroupBox(); + this.button1 = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.label7 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.tBox_QRCode = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.btn_QRCode = new System.Windows.Forms.Button(); + this.groupBox_ImageType.SuspendLayout(); + this.contextMenuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox_ImageType + // + this.groupBox_ImageType.Controls.Add(this.button1); + this.groupBox_ImageType.Controls.Add(this.label3); + this.groupBox_ImageType.Controls.Add(this.comboBox1); + this.groupBox_ImageType.Controls.Add(this.listView1); + this.groupBox_ImageType.Controls.Add(this.label7); + this.groupBox_ImageType.Controls.Add(this.label5); + this.groupBox_ImageType.Controls.Add(this.tBox_QRCode); + this.groupBox_ImageType.Controls.Add(this.label1); + this.groupBox_ImageType.Controls.Add(this.label2); + this.groupBox_ImageType.Controls.Add(this.btn_QRCode); + this.groupBox_ImageType.Location = new System.Drawing.Point(13, 13); + this.groupBox_ImageType.Margin = new System.Windows.Forms.Padding(4); + this.groupBox_ImageType.Name = "groupBox_ImageType"; + this.groupBox_ImageType.Padding = new System.Windows.Forms.Padding(4); + this.groupBox_ImageType.Size = new System.Drawing.Size(869, 409); + this.groupBox_ImageType.TabIndex = 12; + this.groupBox_ImageType.TabStop = false; + this.groupBox_ImageType.Text = " 二维码内容 "; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(164, 284); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(123, 44); + this.button1.TabIndex = 12; + this.button1.Text = "添加数据"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(38, 77); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(98, 14); + this.label3.TabIndex = 11; + this.label3.Text = "1、机器人列表:"; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(144, 74); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(240, 22); + this.comboBox1.TabIndex = 10; + // + // listView1 + // + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.listView1.ContextMenuStrip = this.contextMenuStrip1; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HideSelection = false; + this.listView1.Location = new System.Drawing.Point(441, 19); + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(421, 381); + this.listView1.TabIndex = 9; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged); + // + // columnHeader1 + // + this.columnHeader1.Text = "机器人账号"; + this.columnHeader1.Width = 91; + // + // columnHeader2 + // + this.columnHeader2.Text = "机器人昵称"; + this.columnHeader2.Width = 151; + // + // columnHeader3 + // + this.columnHeader3.Text = "二维码内容"; + this.columnHeader3.Width = 173; + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(101, 26); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.ForeColor = System.Drawing.Color.DimGray; + this.label7.Location = new System.Drawing.Point(31, 202); + this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(403, 14); + this.label7.TabIndex = 8; + this.label7.Text = "注:二维码内容可以手动填写二维码地址,也可以通过上传二维码自动解析"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(38, 169); + this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(103, 14); + this.label5.TabIndex = 6; + this.label5.Text = "上传图片二维码:"; + // + // tBox_QRCode + // + this.tBox_QRCode.Location = new System.Drawing.Point(144, 132); + this.tBox_QRCode.Margin = new System.Windows.Forms.Padding(4); + this.tBox_QRCode.Name = "tBox_QRCode"; + this.tBox_QRCode.Size = new System.Drawing.Size(240, 22); + this.tBox_QRCode.TabIndex = 0; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(38, 136); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(98, 14); + this.label1.TabIndex = 2; + this.label1.Text = "2、二维码内容:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.ForeColor = System.Drawing.Color.DimGray; + this.label2.Location = new System.Drawing.Point(282, 169); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(115, 14); + this.label2.TabIndex = 5; + this.label2.Text = "(图片识别二维码)"; + // + // btn_QRCode + // + this.btn_QRCode.Location = new System.Drawing.Point(164, 165); + this.btn_QRCode.Margin = new System.Windows.Forms.Padding(4); + this.btn_QRCode.Name = "btn_QRCode"; + this.btn_QRCode.Size = new System.Drawing.Size(99, 23); + this.btn_QRCode.TabIndex = 1; + this.btn_QRCode.Text = "上传并解析"; + this.btn_QRCode.UseVisualStyleBackColor = true; + this.btn_QRCode.Click += new System.EventHandler(this.btn_QRCode_Click); + // + // QRCodeForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(895, 435); + this.Controls.Add(this.groupBox_ImageType); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; + this.IconOptions.ShowIcon = false; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "QRCodeForm"; + this.Text = "机器人二维码设置"; + this.Load += new System.EventHandler(this.QRCodeForm_Load); + this.groupBox_ImageType.ResumeLayout(false); + this.groupBox_ImageType.PerformLayout(); + this.contextMenuStrip1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox_ImageType; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox tBox_QRCode; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button btn_QRCode; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/应用/UserFission/QRCodeForm.cs b/应用/UserFission/QRCodeForm.cs new file mode 100644 index 0000000..23a4b1c --- /dev/null +++ b/应用/UserFission/QRCodeForm.cs @@ -0,0 +1,177 @@ +using Api.Framework.Tools; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace UserFission +{ + public partial class QRCodeForm : BaseForm + { + public QRCodeForm() + { + InitializeComponent(); + } + + private void listView1_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + if (listView1.SelectedItems.Count == 0) return; + var name = listView1.SelectedItems[0].SubItems[0].Text; + var nick = listView1.SelectedItems[0].SubItems[1].Text; + var url = listView1.SelectedItems[0].SubItems[2].Text; + + var data = comboBox1.DataSource as List<ItemObj>; + if (data != null) + { + var entry = data.FirstOrDefault(f => f.value == name); + if (entry != null) + { + var index = data.IndexOf(entry); + comboBox1.SelectedIndex = index; + return; + } + } + ShowError($"选中的账号未存在机器人列表中,({name}机器人未登录无法修改)"); + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + private void QRCodeForm_Load(object sender, EventArgs e) + { + try + { + var mylist = new List<ItemObj>(); + mylist.Add(new ItemObj("请选择机器人", "请选择机器人")); + var results = Chat.Framework.ChatClient.WXClient.Values; + foreach (var item in results) + { + mylist.Add(new ItemObj(item.WeixinHao, $"{item.WeixinHao}({item.User.Nick})")); + } + comboBox1.DataSource = mylist; + comboBox1.DisplayMember = "text"; + comboBox1.ValueMember = "value"; + + ShowQrCodeList(); + } + catch (Exception ex) + { } + } + + private void btn_QRCode_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog openDialog = new OpenFileDialog(); + openDialog.Filter = "图片文件|*.jpg;*.png;*.gif|All files(*.*)|*.*"; + if (openDialog.ShowDialog() == DialogResult.OK) + { + if (string.IsNullOrEmpty(openDialog.FileName)) + throw new Exception("请先打开一张二维码图片!"); + else + tBox_QRCode.Text = Util.DecodeQRCode(openDialog.FileName, Util.DecodeQRCodeType.Caoliao); + if(string.IsNullOrWhiteSpace(tBox_QRCode.Text)) throw new Exception("Invalid number of Finder Pattern detected"); + } + } + catch (Exception ex) + { + if (ex.Message == "Invalid number of Finder Pattern detected") + ShowError("二维码无法解析,请换一个重试"); + else + ShowError(ex); + } + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (comboBox1.SelectedIndex == 0) throw new Exception("请选择对应的机器人"); + if (string.IsNullOrWhiteSpace(tBox_QRCode.Text)) throw new Exception("请填写二维码地址"); + + var nick = string.Empty; + var itemObj = (ItemObj)comboBox1.SelectedItem; + var name = itemObj.value; + var rinfo = itemObj.text; + var reg = Regex.Match(rinfo, @"" + name + @"\((?<昵称>.*?)\)"); + if (reg.Success) + nick = reg.Groups["昵称"].Value; + + var item = Class1.Config.QrCodes.FirstOrDefault(f => f.rname == name); + if (item != null) + { + item.rnick = nick; + item.url = tBox_QRCode.Text.Trim(); + } + else + { + Class1.Config.QrCodes.Add(new Entitys.QrCode() { rname = name, rnick = nick, url = tBox_QRCode.Text }); + } + + ShowQrCodeList(); + } + catch (Exception ex) + { + ShowError(ex.Message); + } + } + + private void ShowQrCodeList() + { + try + { + listView1.Items.Clear(); + foreach (var item in Class1.Config.QrCodes) + { + ListViewItem _item = new ListViewItem(item.rname); + _item.SubItems.Add(item.rnick); + _item.SubItems.Add(item.url); + listView1.Items.Add(_item); + } + } + catch (Exception ex) + { } + } + + private class ItemObj + { + public ItemObj(string value, string text) + { + this.text = text; + this.value = value; + } + + public string text { get; set; } + public string value { get; set; } + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + if (listView1.SelectedItems.Count != 0) + { + var name = listView1.SelectedItems[0].SubItems[0].Text; + var item = Class1.Config.QrCodes.FirstOrDefault(f => f.rname == name); + if (item != null) + Class1.Config.QrCodes.Remove(item); + ShowQrCodeList(); + } + } + catch (Exception ex) + { } + } + } +} diff --git a/应用/UserFission/QRCodeForm.resx b/应用/UserFission/QRCodeForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/UserFission/QRCodeForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/UserFission/Resources/分组.png b/应用/UserFission/Resources/分组.png new file mode 100644 index 0000000..3ac7bc0 Binary files /dev/null and b/应用/UserFission/Resources/分组.png differ diff --git a/应用/UserFission/Resources/列表.png b/应用/UserFission/Resources/列表.png new file mode 100644 index 0000000..e9a6575 Binary files /dev/null and b/应用/UserFission/Resources/列表.png differ diff --git a/应用/UserFission/Resources/基础管理.png b/应用/UserFission/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/UserFission/Resources/基础管理.png differ diff --git a/应用/UserFission/Resources/开关.png b/应用/UserFission/Resources/开关.png new file mode 100644 index 0000000..8f64998 Binary files /dev/null and b/应用/UserFission/Resources/开关.png differ diff --git a/应用/UserFission/Resources/海报.png b/应用/UserFission/Resources/海报.png new file mode 100644 index 0000000..ddd06af Binary files /dev/null and b/应用/UserFission/Resources/海报.png differ diff --git a/应用/UserFission/Resources/用户分裂.png b/应用/UserFission/Resources/用户分裂.png new file mode 100644 index 0000000..bbd8133 Binary files /dev/null and b/应用/UserFission/Resources/用户分裂.png differ diff --git a/应用/UserFission/Resources/背景.jpg b/应用/UserFission/Resources/背景.jpg new file mode 100644 index 0000000..e92c6d5 Binary files /dev/null and b/应用/UserFission/Resources/背景.jpg differ diff --git a/应用/UserFission/Resources/通知.png b/应用/UserFission/Resources/通知.png new file mode 100644 index 0000000..090c604 Binary files /dev/null and b/应用/UserFission/Resources/通知.png differ diff --git a/应用/UserFission/Tools.cs b/应用/UserFission/Tools.cs new file mode 100644 index 0000000..d431d9c --- /dev/null +++ b/应用/UserFission/Tools.cs @@ -0,0 +1,247 @@ +using Api.Framework; +using Api.Framework.Tools; +using Chat.Framework; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using ThoughtWorks.QRCode.Codec; +using UserFission.Entitys; +using UserFission.Properties; + +namespace UserFission +{ + public static class Tools + { + /// <summary> + /// 背景图片地址 + /// </summary> + public static string PosterPathImgUrl { get; private set; } + + public const string Rex_Code = @"^([A-Za-z0-9]{6})$"; + + static Tools() + { + PosterPathImgUrl = Util.MapFile("背景.jpg", "File\\Image"); + } + + #region 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// <summary> + /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// </summary> + /// <param name="path"></param> + /// <returns></returns> + public static Bitmap ReadImageFile(string path) + { + FileStream fs = File.OpenRead(path); //OpenRead + int filelength = 0; + filelength = (int)fs.Length; //获得文件长度 + Byte[] image = new Byte[filelength]; //建立一个字节数组 + fs.Read(image, 0, filelength); //按字节流读取 + Image result = Image.FromStream(fs); + fs.Close(); + Bitmap bit = new Bitmap(result); + return bit; + } + #endregion + + #region 获取底图的地址 + /// <summary> + /// 获取底图的地址 + /// </summary> + /// <param name="path"></param> + /// <returns></returns> + public static void GetBaseIco() + { + if (!File.Exists(PosterPathImgUrl)) + { + Bitmap bit = Resources.背景; + bit.Save(PosterPathImgUrl); + } + } + #endregion + + #region 生成二维码,如果有Logo,则在二维码中添加Logo + /// <summary> + /// 生成二维码,如果有Logo,则在二维码中添加Logo + /// </summary> + /// <param name="content">生成二维码的内容</param> + /// <param name="logoImagepath">logo</param> + /// <param name="logoSize">Logo的尺寸</param> + /// <param name="version">二维码版本</param> + /// <returns></returns> + public static Bitmap CreateQRCode(string content, string logoImagepath = "", int logoSize = 35, int version = 7) + { + string _image = string.Empty; + try + { + QRCodeEncoder qrEncoder = new QRCodeEncoder(); + qrEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE; + qrEncoder.QRCodeScale = 4; + qrEncoder.QRCodeVersion = Convert.ToInt32(version); + qrEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M; + Bitmap qrcode = qrEncoder.Encode(content, Encoding.UTF8); + if (!string.IsNullOrEmpty(logoImagepath)) + { + using (Graphics g = Graphics.FromImage(qrcode)) + { + if (logoImagepath.IndexOf("http") != -1) + { + _image = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + FileTools.DownloadImage(logoImagepath, _image); + } + else + { + _image = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + File.Copy(logoImagepath, _image, true); + } + + var bitmapLogo = new Bitmap(ReadImageFile(_image), new Size(logoSize, logoSize)); + var point = new PointF(qrcode.Width / 2.00f - logoSize / 2.00f, qrcode.Height / 2.00f - logoSize / 2.00f); + g.DrawImage(bitmapLogo, point); + } + } + return qrcode; + } + catch (IndexOutOfRangeException ex) + { + throw new Exception("超出当前二维码版本的容量上限,请选择更高的二维码版本!" + ex.Message); + } + catch (Exception ex) + { + throw new Exception("生成二维码出错!" + ex.Message); + } + finally + { + if (!string.IsNullOrEmpty(_image) && File.Exists(_image)) + File.Delete(_image); + } + } + #endregion + + /// <summary> + /// 判断用户数据库中,是否存在邀请码.不存在生成并返回.存在直接返回 + /// </summary> + /// <param name="member_info_id"></param> + /// <returns></returns> + public static string FindInvitationCode(long member_info_id) + { + var session = ApiClient.GetSession(); + var invitation_code = session.Find<fl_plugin_userfission_user_invitation_code>($"select * from fl_plugin_userfission_user_invitation_code where member_info_id = @id", new { id = member_info_id }).FirstOrDefault(); + if (invitation_code != null) + return invitation_code.code; + else + { + string invitationCode = string.Empty; + do + { + //invitationCode = Util.InvitationCode(long.Parse(CsharpHttpHelper.HttpExtend.GetTimeStamp())); + invitationCode = new Random().Next(100000, 999999).ToString(); + var num = long.Parse(session.FindTable($"select count(*) as num from fl_plugin_userfission_user_invitation_code where code = @code", new { code = invitationCode }).Rows[0]["num"].ToString()); + if (num == 0) + { + session.Insertable(new fl_plugin_userfission_user_invitation_code() { member_info_id = member_info_id, code = invitationCode, crt_time = DateTime.Now }).ExecuteCommand(); + return invitationCode; + } + } + while (true); + } + } + + /// <summary> + /// 检测邀请码是否存在,返回true邀请码没使用过,false邀请码已存在 + /// </summary> + /// <param name="code"></param> + /// <returns></returns> + public static bool CheckInvitationCode(string code) + { + var session = ApiClient.GetSession(); + var num = long.Parse(session.FindTable($"select count(*) as num from fl_plugin_userfission_user_invitation_code where code = @code", new { code = code }).Rows[0]["num"].ToString()); + if (num != 0) + return false; + else + return true; + } + + /// <summary> + /// 获得下级满足条件,上级奖励列表 + /// </summary> + /// <param name="session"></param> + /// <param name="type"></param> + /// <param name="refresh">是否刷新缓存</param> + /// <returns></returns> + public static List<fl_plugin_userfission_superior_reward> FindRewards(bool refresh = false) + { + var key = $"fl_plugin_userfission_superior_reward"; + var fl_plugin_userfission_superior_rewards = ApiClient.Cache.Get<List<fl_plugin_userfission_superior_reward>>(key); + var session = ApiClient.GetSession(); + if (!refresh && fl_plugin_userfission_superior_rewards != null) return fl_plugin_userfission_superior_rewards; + fl_plugin_userfission_superior_rewards = session.Find<fl_plugin_userfission_superior_reward>("select * from fl_plugin_userfission_superior_reward order by subordinate_order_totle asc"); + ApiClient.Cache.Set(key, fl_plugin_userfission_superior_rewards, 60); + return fl_plugin_userfission_superior_rewards; + } + + } + + /// <summary> + /// 充值方式 + /// </summary> + public enum RechargeType + { + 增加余额 = 1, + 发送红包 = 2, + 商户付款 = 3, + 微信转账 = 4 + } + + /// <summary> + /// 发送红包方式 + /// </summary> + public enum TransferType + { + 转账 = 0, + 红包 = 1 + } + + + /// <summary> + /// 推荐下线奖励方式 + /// </summary> + public enum ReferralJackpotType + { + 推荐新人立马奖励 = 1, + 新人完成首单奖励 = 2, + 新人首单满足付款金额奖励 = 3 + } + + /// <summary> + /// 推荐下线奖励方式 + /// </summary> + public enum NewcomerAwardType + { + 通过立即奖励 = 1, + 首次查券奖励 = 2 + } + + /// <summary> + /// 新用户首单奖励方式 + /// </summary> + public enum NewcomerInitialAwardType + { + 订单付款后奖励 = 1, + 订单结算后奖励 = 2 + } + + /// <summary> + /// 首单奖励新用户类型 + /// </summary> + public enum InitialAwardNewcomerType + { + 所有新用户 = 1, + 被邀请用户 = 2, + 非邀请用户 = 3 + } + +} diff --git a/应用/UserFission/UserFission.csproj b/应用/UserFission/UserFission.csproj new file mode 100644 index 0000000..d754b67 --- /dev/null +++ b/应用/UserFission/UserFission.csproj @@ -0,0 +1,211 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{BA23EBCB-6EFA-4779-BE34-58F4FFEC0AAA}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>UserFission</RootNamespace> + <AssemblyName>UserFission</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\Newtonsoft.Json.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="ThoughtWorks.QRCode"> + <HintPath>..\..\Debug\ThoughtWorks.QRCode.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Control_\CategoryControl.cs" /> + <Compile Include="Control_\Enums.cs" /> + <Compile Include="EditGroupForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="EditGroupForm.Designer.cs"> + <DependentUpon>EditGroupForm.cs</DependentUpon> + </Compile> + <Compile Include="Entitys\automatic_approval_setting_temp.cs" /> + <Compile Include="Entitys\Controls.cs" /> + <Compile Include="Entitys\fl_plugin_userfission_applyfriend_info.cs" /> + <Compile Include="Entitys\fl_plugin_userfission_automatic_approval_setting.cs" /> + <Compile Include="Entitys\fl_plugin_userfission_extra.cs" /> + <Compile Include="Entitys\fl_plugin_userfission_fan_notify.cs" /> + <Compile Include="Entitys\fl_plugin_userfission_invite_record.cs" /> + <Compile Include="Entitys\fl_plugin_userfission_leadgroup_info.cs" /> + <Compile Include="Entitys\fl_plugin_userfission_superior_reward.cs" /> + <Compile Include="Entitys\fl_plugin_userfission_user_invitation_code.cs" /> + <Compile Include="Entitys\leadgroup_temp.cs" /> + <Compile Include="Entitys\QrCode.cs" /> + <Compile Include="Entitys\Subordinate.cs" /> + <Compile Include="Entitys\user_invitation_code_temp.cs" /> + <Compile Include="Entitys\wxinfo.cs" /> + <Compile Include="Entitys\wx_info.cs" /> + <Compile Include="ImageDesignForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="ImageDesignForm.Designer.cs"> + <DependentUpon>ImageDesignForm.cs</DependentUpon> + </Compile> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="QRCodeForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="QRCodeForm.Designer.cs"> + <DependentUpon>QRCodeForm.cs</DependentUpon> + </Compile> + <Compile Include="Tools.cs" /> + <Compile Include="XtraForm1.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="XtraForm1.Designer.cs"> + <DependentUpon>XtraForm1.cs</DependentUpon> + </Compile> + <Compile Include="重绘\MyPanel.cs"> + <SubType>Component</SubType> + </Compile> + <Compile Include="重绘\MyPictureBox.cs"> + <SubType>Component</SubType> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="EditGroupForm.resx"> + <DependentUpon>EditGroupForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="ImageDesignForm.resx"> + <DependentUpon>ImageDesignForm.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="QRCodeForm.resx"> + <DependentUpon>QRCodeForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="XtraForm1.resx"> + <DependentUpon>XtraForm1.cs</DependentUpon> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\用户分裂.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\背景.jpg" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\基础管理.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\列表.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\海报.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\分组.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\开关.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\通知.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/UserFission/XtraForm1.Designer.cs b/应用/UserFission/XtraForm1.Designer.cs new file mode 100644 index 0000000..e162e7e --- /dev/null +++ b/应用/UserFission/XtraForm1.Designer.cs @@ -0,0 +1,129 @@ +namespace UserFission +{ + partial class XtraForm1 + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.checkedComboBoxEdit_ChatType = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.tBox_antistop = new DevExpress.XtraEditors.TextEdit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.tBox_antistop.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(68, 119); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(48, 14); + this.labelControl3.TabIndex = 12; + this.labelControl3.Text = "机器人:"; + // + // checkedComboBoxEdit_ChatType + // + this.checkedComboBoxEdit_ChatType.EditValue = ""; + this.checkedComboBoxEdit_ChatType.Location = new System.Drawing.Point(138, 116); + this.checkedComboBoxEdit_ChatType.Name = "checkedComboBoxEdit_ChatType"; + this.checkedComboBoxEdit_ChatType.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit_ChatType.Size = new System.Drawing.Size(346, 20); + this.checkedComboBoxEdit_ChatType.TabIndex = 11; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(72, 77); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(48, 14); + this.labelControl2.TabIndex = 10; + this.labelControl2.Text = "关键词:"; + // + // radioGroup1 + // + this.radioGroup1.Location = new System.Drawing.Point(138, 70); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.Columns = 2; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "全部匹配"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "模糊匹配(支持正则表达式)")}); + this.radioGroup1.Size = new System.Drawing.Size(346, 29); + this.radioGroup1.TabIndex = 9; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(72, 35); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(48, 14); + this.labelControl1.TabIndex = 8; + this.labelControl1.Text = "关键词:"; + // + // tBox_antistop + // + this.tBox_antistop.Location = new System.Drawing.Point(138, 32); + this.tBox_antistop.Name = "tBox_antistop"; + this.tBox_antistop.Size = new System.Drawing.Size(346, 20); + this.tBox_antistop.TabIndex = 7; + // + // XtraForm1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(553, 522); + this.Controls.Add(this.labelControl3); + this.Controls.Add(this.checkedComboBoxEdit_ChatType); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.radioGroup1); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.tBox_antistop); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "XtraForm1"; + this.Text = "XtraForm1"; + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.tBox_antistop.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit_ChatType; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.TextEdit tBox_antistop; + } +} \ No newline at end of file diff --git a/应用/UserFission/XtraForm1.cs b/应用/UserFission/XtraForm1.cs new file mode 100644 index 0000000..00ac2a2 --- /dev/null +++ b/应用/UserFission/XtraForm1.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace UserFission +{ + public partial class XtraForm1 : BaseForm + { + public XtraForm1() + { + InitializeComponent(); + } + + + + } +} \ No newline at end of file diff --git a/应用/UserFission/XtraForm1.resx b/应用/UserFission/XtraForm1.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/UserFission/XtraForm1.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/UserFission/重绘/MyPanel.cs b/应用/UserFission/重绘/MyPanel.cs new file mode 100644 index 0000000..b3ac754 --- /dev/null +++ b/应用/UserFission/重绘/MyPanel.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace UserFission.重绘 +{ + class MyPanel : Panel + { + protected override CreateParams CreateParams + { + get + { + CreateParams cp = base.CreateParams; + cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED + return cp; + } + } + } +} diff --git a/应用/UserFission/重绘/MyPictureBox.cs b/应用/UserFission/重绘/MyPictureBox.cs new file mode 100644 index 0000000..ee5f0a9 --- /dev/null +++ b/应用/UserFission/重绘/MyPictureBox.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace UserFission.重绘 +{ + class MyPictureBox : PictureBox + { + protected override CreateParams CreateParams + { + get + { + var parms = base.CreateParams; + parms.Style &= ~0x02000000; // Turn off WS_CLIPCHILDREN + return parms; + } + } + } +} diff --git a/应用/VideoFission/Class1.cs b/应用/VideoFission/Class1.cs new file mode 100644 index 0000000..a53e45c --- /dev/null +++ b/应用/VideoFission/Class1.cs @@ -0,0 +1,516 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using VideoFission.Entitys; +using VideoFission.Properties; + +namespace VideoFission +{ + + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.视频裂变; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<fl_plugin_videofission_recorded_info>()) + session.CreateTable<fl_plugin_videofission_recorded_info>(); + else + { + if (!session.ColumnExist("fl_plugin_videofission_recorded_info", "record")) + session.AddColumn("fl_plugin_videofission_recorded_info", "record", "varchar(255)"); + } + if (!session.TableExist<fl_plugin_videofission_rule_info>()) + { + session.CreateTable<fl_plugin_videofission_rule_info>(); + session.AddUnique<fl_plugin_videofission_rule_info>("ruletype", "amount"); + + session.Insertable(new List<fl_plugin_videofission_rule_info>(){ + new fl_plugin_videofission_rule_info() { ruletype = RuleType.好友天数,amount = 5,num = 5}, + new fl_plugin_videofission_rule_info() { ruletype = RuleType.好友天数,amount = 15,num = 20}, + new fl_plugin_videofission_rule_info() { ruletype = RuleType.好友天数,amount = 99999,num = 30}, + new fl_plugin_videofission_rule_info() { ruletype = RuleType.推荐人数,amount = 5,num = 5}, + new fl_plugin_videofission_rule_info() { ruletype = RuleType.推荐人数,amount = 15,num = 20}, + new fl_plugin_videofission_rule_info() { ruletype = RuleType.推荐人数,amount = 99999,num =30}, + new fl_plugin_videofission_rule_info() { ruletype = RuleType.订单总数,amount = 5,num = 5}, + new fl_plugin_videofission_rule_info() { ruletype = RuleType.订单总数,amount = 50,num = 20}, + new fl_plugin_videofission_rule_info() { ruletype = RuleType.订单总数,amount = 99999,num = 30}, + }).ExecuteCommand(); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig<Config>(); + SDK.WXNewFriendEvent += SDK_WXNewFriendEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// <summary> + /// 订单通知接口 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void SDK_OrderNoticeEvent(object sender, Api.Framework.Events.OrderNoticeEvent e) + { + try + { + if (e.Customer == null && e.Member != null) + { + if (Config.OnOff) + { + var session = ApiClient.GetSession(); + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == e.Member.robot_name).Value; + if (wx != null /*&& wx.WeixinType == WeixinType.Grpc微信*/ && wx.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad == null) return; + + var systemOrderStatus = -1; + if (e.Order is fl_order_alimama) + systemOrderStatus = (int)(e.Order as fl_order_alimama).db_status; + if (e.Order is fl_order_pinduoduo) + systemOrderStatus = (int)(e.Order as fl_order_pinduoduo).db_status; + if (e.Order is fl_order_jingdong) + systemOrderStatus = (int)(e.Order as fl_order_jingdong).db_status; + if (systemOrderStatus == 1002 || systemOrderStatus == 998 || systemOrderStatus == 999 || systemOrderStatus == 1003) + { + _ProcessStr(username: e.Member.username); + } + } + } + } + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} - {ex.StackTrace}"); + } + } + + /// <summary> + /// 新加好友 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void SDK_WXNewFriendEvent(object sender, Chat.Framework.WXSdk.Events.WXNewFriend e) + { + try + { + if (Config.OnOff) + _ProcessStr(username: e.Friend.UserName); + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} . {ex.StackTrace}"); + } + } + + /// <summary> + /// + /// </summary> + /// <param name="username">用户wxid</param> + /// <returns></returns> + private void _ProcessStr(string username = "", long uid = 0) + { + try + { + var session = ApiClient.GetSession(); + fl_member_info member = null; + if (!string.IsNullOrWhiteSpace(username)) + member = session.Find<fl_member_info>("select * from fl_member_info where username = @username", new { username = username }).FirstOrDefault(); + else if (uid != 0) + member = session.Find<fl_member_info>("select * from fl_member_info where id = @id", new { id = uid }).FirstOrDefault(); + if (member == null) + return; + var days = (DateTime.Now.Date - member.crt_time.Date).Days; + + #region 查询次数/推荐人数/完成订单数(3)/退款数量(3) + + decimal invite_amount = 0m;//推荐人数 + decimal order_amount = 0m;//完成订单数 + + var incomeResult = session.FindTable(@"select count(id) as num from fl_member_info where inviter_id = @userid +UNION ALL +select COALESCE(sum(item_num),0) as num from fl_order_alimama where db_userid = @userid and db_status not in (1006,1004) +UNION ALL +select COALESCE(sum(skuNum),0) as num from fl_order_jingdong where db_userid = @userid and db_status not in (1006,1004) +UNION ALL +select COALESCE(sum(goods_quantity),0) as num from fl_order_pinduoduo where db_userid = @userid and db_status not in (1006,1004) ", new { userid = member.id }); + if (incomeResult.Rows.Count != 0) + { + invite_amount = decimal.Parse(incomeResult.Rows[0]["num"].ToString()); + + order_amount = decimal.Parse(incomeResult.Rows[1]["num"].ToString()) + decimal.Parse(incomeResult.Rows[2]["num"].ToString()) + decimal.Parse(incomeResult.Rows[3]["num"].ToString()); + } + #endregion + + //查询次数/推荐人数/完成订单数/退款数量 + var ruleInvite = session.FindSignInfo(RuleType.推荐人数, (long)invite_amount); + var ruleOrder = session.FindSignInfo(RuleType.订单总数, (long)order_amount); + var ruleDays = session.FindSignInfo(RuleType.好友天数, days); + + var recorded_info = session.Find<fl_plugin_videofission_recorded_info>("select * from fl_plugin_videofission_recorded_info where uid = @uid", new { uid = member.id }).FirstOrDefault(); + if (recorded_info != null) + { + int num = 0; + AwardItem item = null; + if (recorded_info.record == null) + item = new AwardItem(); + else + item = HttpExtend.JsonToDictionary(recorded_info.record).ConvertToObj<AwardItem>(); + + if (ruleInvite != null) + { + if (item.ruleInviteId != ruleInvite.id) + { + item.ruleInviteId = ruleInvite.id; + num += (int)ruleInvite.num; + } + } + if (ruleOrder != null) + { + if (item.ruleOrderId != ruleOrder.id) + { + item.ruleOrderId = ruleOrder.id; + num += (int)ruleOrder.num; + } + } + if (ruleDays != null) + { + if (item.ruleDaysId != ruleDays.id) + { + item.ruleDaysId = ruleDays.id; + num += (int)ruleDays.num; + } + } + if (num != 0) + { + recorded_info.surplus += num; + recorded_info.record = HttpHelper.ObjectToJson(item); + session.Saveable(recorded_info).ExecuteCommand(); + var robot = session.FindRobotInfo(member.robot_name, member.robot_type); + if (robot == null) return; + ApiClient.SendMessage(robot, member.username, Config.ParsingTimesIncreaseSuccess.Replace("[剩余次数]", recorded_info.surplus.ToString()).Replace("[增加次数]", num.ToString())); + } + } + } + catch (Exception ex) + { } + } + + /// <summary> + /// 通用解析 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + #region 自定义电影 + if (Config.Custom_OnOff && !string.IsNullOrWhiteSpace(Config.Custom_SearchCMD) && !string.IsNullOrWhiteSpace(Config.Custom_SearchUrl) && !string.IsNullOrWhiteSpace(Config.Custom_SearchMess)) + { + var reg = Regex.Match(e.Message.Trim(), Config.Custom_SearchCMD); + if (reg.Success) + { + var vname = reg.Groups[1].Value.Trim(); + if (!string.IsNullOrWhiteSpace(vname)) + { + var vmess = Config.Custom_SearchMess.Replace("[电影名]", vname).Replace("[电影网址]", + ApiClient.ShortURL(Config.Custom_SearchUrl.Replace("[电影名]", HttpExtend.UrlEncode(vname)), Config.Custom_SearchShortLinkWay).Result + ); + e.SendMessage(vmess); + return; + } + } + } + #endregion + + #region 系统内置电影 + var url = e.Message; + if (e.Message.Contains("<appmsg appid=")) + { + var regex = Regex.Match(e.Message, "<url>(?<链接>.*?)</url>"); + if (regex.Success) + { + url = regex.Groups["链接"].Value; + } + } + + fl_plugin_videofission_recorded_info recorded_info = null; + + var urlTmp = HttpExtend.RegexMatchUrl(url); + if (!string.IsNullOrWhiteSpace(urlTmp)) + { + var _url = Regex.Match(urlTmp, @"(?<url>(http[s]?://m.v.qq.com)|(http[s]?://m.iqiyi.com)|(http[s]?://v.qq.com/x/page)|(http[s]?://v.qq.com/x/cover)|(http[s]?://www.iqiyi.com/(.*?).html)|(http[s]?://www.le.com/ptv/vplay/(.*?).html)|(http[s]?://www.fun.tv/vplay)|(http[s]?://v.youku.com/v_show/id_)|(http[s]?://www.mgtv.com/(.+?).html)|(mgtv.com/(.+?).html)|(http[s]?://tv.sohu.com/)|(http[s]?://film.sohu.com/album)|(http[s]?://v.pptv.com/show/)|(http[s]?://www.wasu.cn/Play/show/id/)|(http[s]?://new-play.tu dou.com/v/)|(www.youku.com\?sharekey))", RegexOptions.IgnoreCase); + if (_url.Success) + { + if (Config._Unlimited == Api.Framework.Enums.SwitchType.关闭)//没有开启无限制 + { + //查询用户的信息 + var session = ApiClient.GetSession(); + recorded_info = session.Find<fl_plugin_videofission_recorded_info>($"select * from fl_plugin_videofission_recorded_info where uid = '{e.GetMemberinfo().id}'").FirstOrDefault(); + if (recorded_info == null && Config._Experience == Api.Framework.Enums.SwitchType.开启)//用户为新用户,并且新用户免费多少次开着 + { + recorded_info = new fl_plugin_videofission_recorded_info() { uid = e.GetMemberinfo().id, surplus = Config.ExperienceCount }; + session.Insertable<fl_plugin_videofission_recorded_info>(recorded_info).ExecuteReturnEntity(); + } + if (recorded_info.surplus > 0) + { + recorded_info.surplus = recorded_info.surplus - 1; + e.SendMessage(Config.LinkResolvedSuccessfully.Replace("[剩余次数]", recorded_info.surplus.ToString()).Replace("[播放链接]", ApiClient.ShortURL(Tools.FindAnalysisUrlFulfill(urlTmp), Config.ShortLinkWay).Result)); + session.Updateable(recorded_info).ExecuteCommand(); + } + else//播放次数不足够时 + e.SendMessage(Config.PromptOfInsufficientBalance.Replace("[剩余次数]", recorded_info.surplus.ToString())); + } + else + e.SendMessage(Config.LinkResolvedSuccessfully_Unlimited.Replace("[播放链接]", ApiClient.ShortURL(Tools.FindAnalysisUrlFulfill(urlTmp), Config.ShortLinkWay).Result)); + } + } + + if (!string.IsNullOrWhiteSpace(Config._SearchCMD)) + { + var reg = Regex.Match(e.Message.Trim(), Config._SearchCMD); + if (reg.Success) + { + var num = reg.Groups["集数"].ToString(); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "http://www.okzyw.com/index.php?m=vod-search", + Method = "post", + Referer = "http://www.okzyw.com/?m=vod-type-id-1.html", + Postdata = $"wd={HttpExtend.UrlEncode(reg.Groups["电影名"].ToString())}&submit=search", + ContentType = "application/x-www-form-urlencoded" + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + if (html.Contains("共0条数据")) + { + e.SendMessage(Config.SearchResolvedUnSuccessfully.Replace("[电影名]", reg.Groups["电影名"].ToString())); + return; + } + + var regs = Regex.Matches(html, @"<li><span class=\""tt\""></span><span class=\""xing_vb4\""><a href=\""(?<跳转地址>.+?)\"" target=\""_blank\"">(?<节目名称>.+?)</a></span> <span class=\""xing_vb5\"">(?<节目类型>.+?)</span> <span class=\""xing_vb6\"">(?<时间>.+?)</span></li>"); + //var regs = Regex.Matches(html, @"<td class=\""l\""><a href=\""(?<跳转地址>.+?)\"" target=\""_blank\"">(?<节目名称>.+?)<font color=\""red\"">(?:[^<]+?)</font>\s*<td><a href=\""(?:[^""]+?)\"" target=\""_blank\"">(?<节目类型>.+?)</a></td>(?:.+?)(?:[\w\W]+?)<font color=\""(?:[^""]+?)\"">(?<时间>.+?)</font></td>"); + foreach (Match reg_ in regs) + { + var skipUrl = reg_.Groups["跳转地址"].ToString(); + var name = reg_.Groups["节目名称"].ToString(); + var type = reg_.Groups["节目类型"].ToString(); + var dateTime = reg_.Groups["时间"].ToString(); + + http = new HttpHelper(); + item = new HttpItem() + { + URL = "http://www.okzyw.com" + skipUrl, + Method = "get", + Cookie = "", + Referer = "", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0", + ContentType = "text/html", + Allowautoredirect = false, + ProxyIp = "", + Host = "www.okzyw.com", + }; + + result = http.GetHtml(item); + html = result.Html; + + + string movieImage = string.Empty; + reg = Regex.Match(html, @"<img class=""lazy"" src=""(?<电影图片>.+?)"" alt="".+?"" />"); + //reg = Regex.Match(html, @"<div class=\""videoPic\"">(?:.*?)<img src=\""(?<电影图片>.+?)\""/>"); + if (reg.Success) + { + movieImage = reg.Groups["电影图片"].ToString(); + } + + reg = Regex.Match(html, @"<h3>播放类型:<span class=""suf"">kuyun</span></h3> (?<所有链接地址>[\w\W]+?)</ul>"); + //reg = Regex.Match(html, @"<div class=\""movievod\""><ul>\s*(?<所有链接地址>[\w\W]+?)</ul>"); + if (reg.Success) + { + var session = ApiClient.GetSession(); + if (recorded_info == null) + { + recorded_info = session.Find<fl_plugin_videofission_recorded_info>($"select * from fl_plugin_videofission_recorded_info where uid = '{e.GetMemberinfo().id}'").FirstOrDefault(); + if (recorded_info == null && Config._Experience == Api.Framework.Enums.SwitchType.开启)//用户为新用户,并且新用户免费多少次开着 + { + recorded_info = new fl_plugin_videofission_recorded_info() { uid = e.GetMemberinfo().id, surplus = Config.ExperienceCount }; + session.Insertable<fl_plugin_videofission_recorded_info>(recorded_info).ExecuteReturnEntity(); + } + } + if (Config._Unlimited == Api.Framework.Enums.SwitchType.关闭 && recorded_info == null) return;//没有开启无限制 + var urls = reg.Groups["所有链接地址"].ToString(); + regs = Regex.Matches(urls, @"<li><input type=""checkbox"" name=""copy_sel"" value=""(?<播放链接>.+?)"" checked="""" />(?<集>.+?)\$(?:.+?)</li>"); + //regs = Regex.Matches(urls, @"<li><input type=\""checkbox\"" name=\""copy_sel\"" value=\""(?<集>.+?)\$(?<播放链接>.+?)\"" checked=\""\"">"); + var list = new Dictionary<string, string>(); + foreach (Match reg1_ in regs) + { + var broadcast_address = reg1_.Groups["播放链接"].ToString(); + var ji = reg1_.Groups["集"].ToString(); + if (!type.EndsWith("剧")) + { + list.Add(ji, broadcast_address); + break; + } + if (!list.ContainsKey(ji.Replace("第", "").Replace("集", ""))) + list.Add(ji.Replace("第", "").Replace("集", ""), broadcast_address); + } + + string mess = string.Empty; + if (list.Count != 0) + { + if (Config._Unlimited == Api.Framework.Enums.SwitchType.关闭)//没有开启无限制 + { + if (recorded_info.surplus <= 0)//播放次数不足够时 + { + e.SendMessage(Config.PromptOfInsufficientBalance.Replace("[剩余次数]", recorded_info.surplus.ToString())); + return; + } + } + + if (list.Count == 1) + { + if (Config._Unlimited == Api.Framework.Enums.SwitchType.关闭)//没有开启无限制 + { + recorded_info.surplus = recorded_info.surplus - 1; + } + if (recorded_info == null)//用户为新用户,并且新用户免费多少次开着 + { + recorded_info = new fl_plugin_videofission_recorded_info() { uid = e.GetMemberinfo().id, surplus = Config.ExperienceCount }; + session.Insertable<fl_plugin_videofission_recorded_info>(recorded_info).ExecuteReturnEntity(); + } + else + { + if (Config._Unlimited == Api.Framework.Enums.SwitchType.关闭) + { + recorded_info.surplus--; + session.Updateable(recorded_info).ExecuteCommand(); + } + } + //[电影图片]、[电影名]、[集数]、[播放链接]、[剩余次数] + mess = Config.SearchResolvedSuccessfully.Replace("[电影名]", name).Replace("[集数]", string.IsNullOrWhiteSpace(num) ? list.Keys.First() : num).Replace("[播放链接]", ApiClient.ShortURL(list.Values.First(), Config.ShortLinkWay).Result).Replace("[剩余次数]", recorded_info.surplus.ToString()).Replace("[电影图片]", $"[图片={movieImage}]"); ; + } + else + { + if (!string.IsNullOrWhiteSpace(num)) + { + num = num.Length == 1 ? "0" + num : num;//单数需要显示 0X 格式 + if (list.ContainsKey(num)) + { + if (Config._Unlimited == Api.Framework.Enums.SwitchType.关闭)//没有开启无限制 + { + recorded_info.surplus = recorded_info.surplus - 1; + } + //[电影图片]、[电影名]、[集数]、[播放链接]、[剩余次数] + mess = Config.SearchResolvedSuccessfully.Replace("[电影名]", name).Replace("[集数]", num).Replace("[播放链接]", ApiClient.ShortURL(list[num], Config.ShortLinkWay).Result).Replace("[剩余次数]", recorded_info.surplus.ToString()).Replace("[电影图片]", $"[图片={movieImage}]"); + } + else + mess = Config.SearchteleplayResolvedUnSuccessfully.Replace("[电影名]", name).Replace("[集数]", num); + } + else//用户没有输入集数,返回第一个 + { + if (Config._Unlimited == Api.Framework.Enums.SwitchType.关闭)//没有开启无限制 + { + recorded_info.surplus = recorded_info.surplus - 1; + } + //[电影图片]、[电影名]、[集数]、[播放链接]、[剩余次数] + mess = Config.SearchResolvedSuccessfully.Replace("[电影名]", name).Replace("[集数]", string.IsNullOrWhiteSpace(num) ? list.Keys.First() : num).Replace("[播放链接]", ApiClient.ShortURL(list.Values.First(), Config.ShortLinkWay).Result).Replace("[剩余次数]", recorded_info.surplus.ToString()).Replace("[电影图片]", $"[图片={movieImage}]"); + } + } + if (Config._Unlimited == Api.Framework.Enums.SwitchType.关闭)//没有开启无限制 + { + session.Updateable(recorded_info).ExecuteCommand(); + } + } + else + { + mess = Config.SearchResolvedUnSuccessfully.Replace("[电影名]", name); + } + if (!string.IsNullOrWhiteSpace(mess)) + e.SendMessage(mess); + } + break; + } + } + } + #endregion + + } + catch (Exception ex) + { + this.OnLog(ex.Message + ex.StackTrace); + } + } + + } +} diff --git a/应用/VideoFission/Config.cs b/应用/VideoFission/Config.cs new file mode 100644 index 0000000..607b862 --- /dev/null +++ b/应用/VideoFission/Config.cs @@ -0,0 +1,192 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace VideoFission +{ + [Config(Name = "插件-视频裂变-配置")] + public class Config + { + [Browsable(false)] + public bool OnOff { get; set; } + + #region 自定义电影 + [Browsable(false)] + public bool Custom_OnOff { get; set; } + + [Browsable(false)] + public string Custom_SearchCMD { get; set; } + + [Browsable(false)] + public string Custom_SearchUrl { get; set; } + + [Browsable(false)] + public string Custom_SearchMess { get; set; } + + [Browsable(false)] + public DwzType Custom_SearchShortLinkWay { get; set; } + + #endregion + + + /// <summary> + /// 解析链接 + /// </summary> + [Category("1)、解析链接设置"), DisplayName("01.解析链接"), DefaultValue(@"https://api.653520.top/vip/?url= +https://vip.mpos.ren/v/?url= +https://jx.000180.top/jx/?url= +https://660e.com/?url= +https://cdn.yangju.vip/k/?url="), Description(@"每一行一个视频解析地址,解析时随机获取"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string AnalysisLink { get; set; } + + /// <summary> + /// 无限制开关 + /// </summary> + [Category("2)、无限制设置"), DisplayName("01.无限制开关"), DefaultValue(SwitchType.开启), Description(@"用户无限制使用视频解析")] + public SwitchType _Unlimited { get; set; } + /// <summary> + /// 新用户开关 + /// </summary> + [Category("3)、新用户试用设置"), DisplayName("02.新用户试用开关"), DefaultValue(SwitchType.关闭), Description(@"开启本功能,新用户将能获得试用次数")] + public SwitchType _Experience { get; set; } + /// <summary> + /// 新用户试用次数 + /// </summary> + [Category("3)、新用户试用设置"), DisplayName("03.新用户试用次数"), DefaultValue(10), Description(@"新用户将能获得的试用次数")] + public int ExperienceCount { get; set; } + + /// <summary> + /// 搜索设置 + /// </summary> + [Category("4)、搜索设置"), DisplayName("01.搜索指令"), DefaultValue(@"^看(?<电影名>.+?)(?:(?:\s+?)(?<集数>\d+?)?)?$"), Description(@"搜索电影名 +支持正则变量 电影名 与 集数 +指令:看电影名 集数 +注:集数为非必写值")] + public string _SearchCMD { get; set; } + + #region 提示语 + [Category("5)、其他设置"), DisplayName("01.短连接方式"), DefaultValue(DwzType.快站短网址)] + public DwzType ShortLinkWay { get; set; } + + /// <summary> + /// 视频解析成功 + /// </summary> + [Category("6)、提示语设置"), DisplayName("01.视频解析成功提示语(无限制)"), DefaultValue(@"播放链接:[播放链接]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[播放链接]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string LinkResolvedSuccessfully_Unlimited { get; set; } + + /// <summary> + /// 视频解析成功 + /// </summary> + [Category("6)、提示语设置"), DisplayName("02.视频解析成功提示语"), DefaultValue(@"[昵称] +播放链接:[播放链接] +剩余次数:[剩余次数]次"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[播放链接]、[剩余次数]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string LinkResolvedSuccessfully { get; set; } + + /// <summary> + /// 视频搜索成功提示语 + /// </summary> + [Category("6)、提示语设置"), DisplayName("03.视频搜索成功提示语"), DefaultValue(@"[电影图片] +[昵称] +电影名:[电影名] +电影集数:[集数] +播放链接:[播放链接] +剩余次数:[剩余次数]次"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[电影图片]、[电影名]、[集数]、[播放链接]、[剩余次数]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SearchResolvedSuccessfully { get; set; } + + /// <summary> + /// 视频搜索失败提示语 + /// </summary> + [Category("6)、提示语设置"), DisplayName("04.视频搜索失败提示语"), DefaultValue(@"[昵称] +电影名:[电影名] 没有搜索到"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[电影名]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SearchResolvedUnSuccessfully { get; set; } + + /// <summary> + /// 搜索电视剧集数不存在提示语 + /// </summary> + [Category("6)、提示语设置"), DisplayName("05.搜索电视剧集数不存在提示语"), DefaultValue(@"[昵称] +电影名:[电影名] +集数:[集数] +没有搜索到"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[电影名]、[集数]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SearchteleplayResolvedUnSuccessfully { get; set; } + + /// <summary> + /// 解析次数不足 + /// </summary> + [Category("6)、提示语设置"), DisplayName("06.解析次数不足提示语"), DefaultValue(@"[昵称] +剩余次数:[剩余次数]次"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余次数]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string PromptOfInsufficientBalance { get; set; } + /// <summary> + /// 解析次数增加成功 + /// </summary> + [Category("6)、提示语设置"), DisplayName("07.解析次数增加成功提示语"), DefaultValue(@"[昵称] +增加解析次数 +剩余次数:[剩余次数]次 +增加次数:[增加次数]次"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余次数]、[增加次数]"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ParsingTimesIncreaseSuccess { get; set; } + + #endregion + + public Config() + { + this.Custom_OnOff = false; + this.Custom_SearchCMD = @"^搜\s*?(?<电影名>.+?)$"; + this.Custom_SearchUrl = @"http://wtw.wwwuxsajccom.cn/so.php?wd=[电影名]"; + this.Custom_SearchMess = @"电影名:[电影名] +点击链接查看:[电影网址]"; + this.Custom_SearchShortLinkWay = DwzType.快站短网址; + + this.AnalysisLink = @"https://api.653520.top/vip/?url= +https://vip.mpos.ren/v/?url= +https://jx.000180.top/jx/?url= +https://660e.com/?url= +https://cdn.yangju.vip/k/?url="; + this.ParsingTimesIncreaseSuccess = @"[昵称] +增加解析次数 +剩余次数:[剩余次数]次 +增加次数:[增加次数]次"; + this._SearchCMD = @"^看(?<电影名>.+?)(?:\s+?)?(?<集数>\d+?)?$"; + this._Unlimited = SwitchType.开启; + this._Experience = SwitchType.关闭; + this.ExperienceCount = 10; + + this.ShortLinkWay = DwzType.快站短网址; + + this.LinkResolvedSuccessfully_Unlimited = @"播放链接:[播放链接]"; + this.LinkResolvedSuccessfully = @"[昵称] +播放链接:[播放链接] +剩余次数:[剩余次数]次"; + + this.SearchResolvedSuccessfully = @"[电影图片] +[昵称] +电影名:[电影名] +电影集数:[集数] +播放链接:[播放链接] +剩余次数:[剩余次数]次"; + + this.SearchResolvedUnSuccessfully = @"[昵称] +电影名:[电影名] 没有搜索到"; + + this.SearchteleplayResolvedUnSuccessfully = @"[昵称] +电影名:[电影名] +集数:[集数] +没有搜索到"; + + this.PromptOfInsufficientBalance = @"[昵称] +剩余次数:[剩余次数]次"; + } + + } +} diff --git a/应用/VideoFission/Entitys/AwardItem.cs b/应用/VideoFission/Entitys/AwardItem.cs new file mode 100644 index 0000000..962ef02 --- /dev/null +++ b/应用/VideoFission/Entitys/AwardItem.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VideoFission.Entitys +{ + public class AwardItem + { + public long ruleInviteId { get; set; } + public long ruleOrderId { get; set; } + public long ruleDaysId { get; set; } + } +} diff --git a/应用/VideoFission/Entitys/Enums.cs b/应用/VideoFission/Entitys/Enums.cs new file mode 100644 index 0000000..2d73d5d --- /dev/null +++ b/应用/VideoFission/Entitys/Enums.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VideoFission.Entitys +{ + /// <summary> + /// 奖励条件 + /// </summary> + public enum RuleType + { + 好友天数 = 0, + 订单总数 = 1, + 推荐人数 = 2 + } + +} diff --git a/应用/VideoFission/Entitys/fl_plugin_videofission_recorded_info.cs b/应用/VideoFission/Entitys/fl_plugin_videofission_recorded_info.cs new file mode 100644 index 0000000..e680a05 --- /dev/null +++ b/应用/VideoFission/Entitys/fl_plugin_videofission_recorded_info.cs @@ -0,0 +1,26 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VideoFission.Entitys +{ + public class fl_plugin_videofission_recorded_info : base_model + { + /// <summary> + /// uid + /// </summary> + public long uid { get; set; } + /// <summary> + /// 剩余次数 + /// </summary> + public int surplus { get; set; } + /// <summary> + /// 记录奖励的id (json) + /// </summary> + public string record { get;set;} + + } +} diff --git a/应用/VideoFission/Entitys/fl_plugin_videofission_rule_info.cs b/应用/VideoFission/Entitys/fl_plugin_videofission_rule_info.cs new file mode 100644 index 0000000..b91102f --- /dev/null +++ b/应用/VideoFission/Entitys/fl_plugin_videofission_rule_info.cs @@ -0,0 +1,19 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VideoFission.Entitys +{ + public class fl_plugin_videofission_rule_info : base_model + { + public RuleType ruletype { get; set; } + + public long amount { get; set; } + + public long num { get; set; } + + } +} diff --git a/应用/VideoFission/MainForm.Designer.cs b/应用/VideoFission/MainForm.Designer.cs new file mode 100644 index 0000000..a6bc868 --- /dev/null +++ b/应用/VideoFission/MainForm.Designer.cs @@ -0,0 +1,614 @@ +namespace VideoFission +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.xtraTabControl3 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit5 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.xtraTabControl2 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage5 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage7 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage6 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl3)).BeginInit(); + this.xtraTabControl3.SuspendLayout(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl2)).BeginInit(); + this.xtraTabControl2.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + this.xtraTabPage6.SuspendLayout(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl3 + // + this.xtraTabControl3.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl3.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl3.Name = "xtraTabControl3"; + this.xtraTabControl3.SelectedTabPage = this.xtraTabPage4; + this.xtraTabControl3.Size = new System.Drawing.Size(762, 511); + this.xtraTabControl3.TabIndex = 11; + this.xtraTabControl3.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage4, + this.xtraTabPage6}); + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.xtraTabControl1); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(760, 487); + this.xtraTabPage4.Text = " 系 统 自 带 电 影 解 析 "; + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(760, 487); + this.xtraTabControl1.TabIndex = 11; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.groupBox1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(758, 463); + this.xtraTabPage1.Text = " 奖 励 规 则 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.buttonCheck1); + this.groupBox1.Controls.Add(this.groupControl4); + this.groupBox1.Controls.Add(this.groupControl3); + this.groupBox1.Controls.Add(this.xtraTabControl2); + this.groupBox1.Location = new System.Drawing.Point(36, 20); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(691, 422); + this.groupBox1.TabIndex = 4; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 奖 励 规 则 设 置 "; + // + // labelControl1 + // + this.labelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 11F); + this.labelControl1.Appearance.Options.UseFont = true; + this.labelControl1.Location = new System.Drawing.Point(94, 34); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(75, 18); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "奖励开关:"; + // + // buttonCheck1 + // + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = false; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style4; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(185, 31); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(66, 24); + this.buttonCheck1.TabIndex = 5; + this.buttonCheck1.Click += new System.EventHandler(this.buttonCheck1_Click); + // + // groupControl4 + // + this.groupControl4.Controls.Add(this.numericUpDown1); + this.groupControl4.Controls.Add(this.radioGroup1); + this.groupControl4.Controls.Add(this.labelControl9); + this.groupControl4.Controls.Add(this.textEdit5); + this.groupControl4.Controls.Add(this.labelControl7); + this.groupControl4.Controls.Add(this.simpleButton3); + this.groupControl4.Controls.Add(this.simpleButton2); + this.groupControl4.Controls.Add(this.simpleButton1); + this.groupControl4.Controls.Add(this.labelControl6); + this.groupControl4.Controls.Add(this.labelControl5); + this.groupControl4.Controls.Add(this.textEdit4); + this.groupControl4.Controls.Add(this.labelControl4); + this.groupControl4.Controls.Add(this.labelControl3); + this.groupControl4.Location = new System.Drawing.Point(321, 80); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(337, 317); + this.groupControl4.TabIndex = 4; + this.groupControl4.Text = "代号编辑"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(99, 160); + this.numericUpDown1.Maximum = new decimal(new int[] { + 1410065407, + 2, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(94, 22); + this.numericUpDown1.TabIndex = 15; + // + // radioGroup1 + // + this.radioGroup1.Location = new System.Drawing.Point(92, 63); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "天数", true, 0), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "订单", true, 2), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "推荐", true, 4)}); + this.radioGroup1.Size = new System.Drawing.Size(203, 29); + this.radioGroup1.TabIndex = 14; + this.radioGroup1.SelectedIndexChanged += new System.EventHandler(this.radioGroup1_SelectedIndexChanged); + // + // labelControl9 + // + this.labelControl9.Location = new System.Drawing.Point(42, 70); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(36, 14); + this.labelControl9.TabIndex = 13; + this.labelControl9.Text = "类型:"; + // + // textEdit5 + // + this.textEdit5.Location = new System.Drawing.Point(99, 122); + this.textEdit5.Name = "textEdit5"; + this.textEdit5.Properties.ReadOnly = true; + this.textEdit5.Size = new System.Drawing.Size(94, 20); + this.textEdit5.TabIndex = 11; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(42, 125); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(36, 14); + this.labelControl7.TabIndex = 10; + this.labelControl7.Text = "条件:"; + // + // simpleButton3 + // + this.simpleButton3.Enabled = false; + this.simpleButton3.Location = new System.Drawing.Point(223, 261); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(78, 23); + this.simpleButton3.TabIndex = 9; + this.simpleButton3.Text = "删除"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.Enabled = false; + this.simpleButton2.Location = new System.Drawing.Point(134, 261); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(78, 23); + this.simpleButton2.TabIndex = 8; + this.simpleButton2.Text = "修改"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(47, 261); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(78, 23); + this.simpleButton1.TabIndex = 7; + this.simpleButton1.Text = "新增"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl6 + // + this.labelControl6.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl6.Appearance.Options.UseForeColor = true; + this.labelControl6.Location = new System.Drawing.Point(213, 205); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(82, 14); + this.labelControl6.TabIndex = 6; + this.labelControl6.Text = "(增加观影次数)"; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(213, 164); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(94, 14); + this.labelControl5.TabIndex = 5; + this.labelControl5.Text = "(需要满足的条件)"; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(99, 202); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(94, 20); + this.textEdit4.TabIndex = 4; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(33, 205); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(60, 14); + this.labelControl4.TabIndex = 3; + this.labelControl4.Text = "增加次数:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(42, 164); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(36, 14); + this.labelControl3.TabIndex = 1; + this.labelControl3.Text = "数量:"; + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.listView1); + this.groupControl3.Location = new System.Drawing.Point(27, 112); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(287, 285); + this.groupControl3.TabIndex = 3; + this.groupControl3.Text = "规则展示"; + // + // listView1 + // + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HideSelection = false; + this.listView1.Location = new System.Drawing.Point(2, 23); + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(283, 260); + this.listView1.TabIndex = 0; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + this.listView1.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.listView1_ItemSelectionChanged); + // + // columnHeader1 + // + this.columnHeader1.Text = "序号"; + // + // columnHeader2 + // + this.columnHeader2.Text = "等于数量"; + this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader2.Width = 100; + // + // columnHeader3 + // + this.columnHeader3.Text = "增加次数"; + this.columnHeader3.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.columnHeader3.Width = 100; + // + // xtraTabControl2 + // + this.xtraTabControl2.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.xtraTabControl2.BorderStylePage = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.xtraTabControl2.Location = new System.Drawing.Point(28, 77); + this.xtraTabControl2.Name = "xtraTabControl2"; + this.xtraTabControl2.PaintStyleName = "Skin"; + this.xtraTabControl2.SelectedTabPage = this.xtraTabPage3; + this.xtraTabControl2.Size = new System.Drawing.Size(287, 29); + this.xtraTabControl2.TabIndex = 2; + this.xtraTabControl2.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage3, + this.xtraTabPage5, + this.xtraTabPage7}); + this.xtraTabControl2.SelectedPageChanging += new DevExpress.XtraTab.TabPageChangingEventHandler(this.xtraTabControl2_SelectedPageChanging); + // + // xtraTabPage3 + // + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(285, 5); + this.xtraTabPage3.Tag = "0"; + this.xtraTabPage3.Text = " 天 数 "; + // + // xtraTabPage5 + // + this.xtraTabPage5.Name = "xtraTabPage5"; + this.xtraTabPage5.Size = new System.Drawing.Size(285, 5); + this.xtraTabPage5.Tag = "2"; + this.xtraTabPage5.Text = " 订 单 "; + // + // xtraTabPage7 + // + this.xtraTabPage7.Name = "xtraTabPage7"; + this.xtraTabPage7.Size = new System.Drawing.Size(285, 5); + this.xtraTabPage7.Tag = "4"; + this.xtraTabPage7.Text = " 推 荐 "; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(758, 463); + this.xtraTabPage2.Text = " 基 础 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(758, 463); + this.settingControl1.TabIndex = 10; + // + // xtraTabPage6 + // + this.xtraTabPage6.Controls.Add(this.groupBox2); + this.xtraTabPage6.Name = "xtraTabPage6"; + this.xtraTabPage6.Size = new System.Drawing.Size(760, 487); + this.xtraTabPage6.Text = " 自 定 义 电 影 接 口 "; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.comboBoxEdit1); + this.groupBox2.Controls.Add(this.labelControl11); + this.groupBox2.Controls.Add(this.buttonCheck2); + this.groupBox2.Controls.Add(this.memoEdit1); + this.groupBox2.Controls.Add(this.labelControl10); + this.groupBox2.Controls.Add(this.labelControl12); + this.groupBox2.Controls.Add(this.labelControl8); + this.groupBox2.Controls.Add(this.labelControl2); + this.groupBox2.Controls.Add(this.textEdit2); + this.groupBox2.Controls.Add(this.textEdit1); + this.groupBox2.Location = new System.Drawing.Point(66, 47); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(628, 393); + this.groupBox2.TabIndex = 2; + this.groupBox2.TabStop = false; + this.groupBox2.Text = " 基 础 信 息 "; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(150, 163); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Size = new System.Drawing.Size(398, 20); + this.comboBoxEdit1.TabIndex = 9; + // + // labelControl11 + // + this.labelControl11.Appearance.Font = new System.Drawing.Font("Tahoma", 11F); + this.labelControl11.Appearance.Options.UseFont = true; + this.labelControl11.Location = new System.Drawing.Point(60, 51); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(75, 18); + this.labelControl11.TabIndex = 8; + this.labelControl11.Text = "功能开关:"; + // + // buttonCheck2 + // + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = false; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style4; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(150, 46); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(77, 28); + this.buttonCheck2.TabIndex = 7; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(150, 196); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(398, 143); + this.memoEdit1.TabIndex = 2; + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(39, 198); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(96, 14); + this.labelControl10.TabIndex = 1; + this.labelControl10.Text = "响应用户提示语:"; + // + // labelControl12 + // + this.labelControl12.Location = new System.Drawing.Point(51, 166); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(84, 14); + this.labelControl12.TabIndex = 1; + this.labelControl12.Text = "电影网址缩短:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(51, 133); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(84, 14); + this.labelControl8.TabIndex = 1; + this.labelControl8.Text = "搜索电影网址:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(51, 101); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(84, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "搜索电影指令:"; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(150, 130); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(398, 20); + this.textEdit2.TabIndex = 0; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(150, 98); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(398, 20); + this.textEdit1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(762, 511); + this.Controls.Add(this.xtraTabControl3); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl3)).EndInit(); + this.xtraTabControl3.ResumeLayout(false); + this.xtraTabPage4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + this.groupControl4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl2)).EndInit(); + this.xtraTabControl2.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage6.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private DevExpress.XtraEditors.GroupControl groupControl4; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraEditors.TextEdit textEdit5; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private DevExpress.XtraTab.XtraTabControl xtraTabControl2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage5; + private DevExpress.XtraTab.XtraTabPage xtraTabPage7; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage6; + private System.Windows.Forms.GroupBox groupBox2; + private DevExpress.XtraEditors.LabelControl labelControl11; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl10; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl12; + } +} \ No newline at end of file diff --git a/应用/VideoFission/MainForm.cs b/应用/VideoFission/MainForm.cs new file mode 100644 index 0000000..c87577e --- /dev/null +++ b/应用/VideoFission/MainForm.cs @@ -0,0 +1,292 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; +using VideoFission.Entitys; +using VideoFission.Properties; + +namespace VideoFission +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + this.settingControl1.Bind(Class1.Config); + buttonCheck1.Checked = Class1.Config.OnOff; + _RefreshData(); + + buttonCheck2.Checked = Class1.Config.Custom_OnOff; + textEdit1.Text = Class1.Config.Custom_SearchCMD; + textEdit2.Text = Class1.Config.Custom_SearchUrl; + memoEdit1.Text = Class1.Config.Custom_SearchMess; + + #region 增加缩短类型 + this.comboBoxEdit1.Properties.Items.Clear(); + var objqqList = Enum.GetNames(typeof(DwzType)).ToList<string>(); + this.comboBoxEdit1.Properties.Items.AddRange(objqqList); + if (comboBoxEdit1.Properties.Items.Count != 0) + comboBoxEdit1.SelectedIndex = objqqList.IndexOf(Class1.Config.Custom_SearchShortLinkWay.ToString()); + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Class1.Config.Custom_OnOff = buttonCheck2.Checked; + Class1.Config.Custom_SearchCMD = textEdit1.Text; + Class1.Config.Custom_SearchUrl = textEdit2.Text; + Class1.Config.Custom_SearchMess = memoEdit1.Text; + + Class1.Config.Custom_SearchShortLinkWay = (DwzType)Enum.Parse(typeof(DwzType), comboBoxEdit1.Text); + + Util.Save(Class1.Config); + } + + /// <summary> + /// 按钮状态 + /// </summary> + /// <param name="flag"></param> + private void _ButtonEnabled(bool flag) + { + simpleButton2.Enabled = simpleButton3.Enabled = flag; + } + + private void xtraTabControl2_SelectedPageChanging(object sender, DevExpress.XtraTab.TabPageChangingEventArgs e) + { + _RefreshData(e.Page.TabIndex); + } + + /// <summary> + /// 数显数据 + /// </summary> + private void _RefreshData(int index = 0) + { + try + { + listView1.Tag = null; + if (groupControl4.Tag == null) + _ButtonEnabled(false); + var session = ApiClient.GetSession(); + var ruleInfoS = session.Find<fl_plugin_videofission_rule_info>("select * from fl_plugin_videofission_rule_info where ruletype = @ruletype order by amount asc", new { ruletype = index }); + listView1.Items.Clear(); + foreach (var rule in ruleInfoS) + { + var item = new ListViewItem(); + item.Text = rule.id.ToString(); + item.SubItems.Add(rule.amount.ToString()); + item.SubItems.Add(rule.num.ToString()); + listView1.Items.Add(item); + } + listView1.Tag = ruleInfoS; + session.FindSignInfos((RuleType)index, true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) + { + try + { + if (listView1.SelectedItems.Count == 0) + { + _ButtonEnabled(false); + return; + } + else + { + var id = long.Parse(listView1.SelectedItems[0].SubItems[0].Text); + var session = ApiClient.GetSession(); + List<fl_plugin_videofission_rule_info> signInfoS = null; + + if (listView1.Tag != null) + signInfoS = listView1.Tag as List<fl_plugin_videofission_rule_info>; + else + signInfoS = session.Find<fl_plugin_videofission_rule_info>("select * from fl_plugin_videofission_rule_info where ruletype = @ruletype order by amount asc", new { signtype = xtraTabControl1.TabIndex }); + if (signInfoS != null && signInfoS.Count != 0) + { + var signInfo = signInfoS.FirstOrDefault(f => f.id == id); + if (signInfo == null) return; + _FillDate(signInfo); + _ButtonEnabled(true); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 填充数据到控件中 + /// </summary> + private void _FillDate(fl_plugin_videofission_rule_info fuleInfo) + { + radioGroup1.SelectedIndex = (int)fuleInfo.ruletype; + textEdit5.Text = xtraTabControl2.SelectedTabPage.Text; + numericUpDown1.Value = (decimal)fuleInfo.amount; + textEdit4.Text = fuleInfo.num.ToString(); + + groupControl4.Tag = fuleInfo; + } + + /// <summary> + /// 增加 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + List<fl_plugin_videofission_rule_info> signInfoS = null; + if (listView1.Tag != null) + signInfoS = listView1.Tag as List<fl_plugin_videofission_rule_info>; + else + signInfoS = session.Find<fl_plugin_videofission_rule_info>("select * from fl_plugin_videofission_rule_info where ruletype = @ruletype order by amount asc", new { ruletype = xtraTabControl1.TabIndex }); + + var signInfo = new fl_plugin_videofission_rule_info(); + + signInfo.id = 0; + signInfo.ruletype = (RuleType)radioGroup1.SelectedIndex; + signInfo.amount = (long)numericUpDown1.Value; + + if (signInfoS != null && signInfoS.Count != 0) + { + var _signInfo = signInfoS.FirstOrDefault(f => f.ruletype == signInfo.ruletype && f.amount == signInfo.amount); + if (_signInfo != null) throw new Exception("该条件已经存在,无法增加"); + } + signInfo.num = long.Parse(textEdit4.Text.Trim()); + session.Insertable(signInfo).ExecuteCommand(); + _RefreshData((int)signInfo.ruletype); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 修改 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + fl_plugin_videofission_rule_info signInfo = null; + if (groupControl4.Tag != null) + { + signInfo = groupControl4.Tag as fl_plugin_videofission_rule_info; + signInfo.ruletype = (RuleType)radioGroup1.SelectedIndex; + signInfo.amount = (long)numericUpDown1.Value; + signInfo.num = long.Parse(textEdit4.Text.Trim()); + var session = ApiClient.GetSession(); + List<fl_plugin_videofission_rule_info> signInfoS = null; + if (listView1.Tag != null) + signInfoS = listView1.Tag as List<fl_plugin_videofission_rule_info>; + else + signInfoS = session.Find<fl_plugin_videofission_rule_info>("select * from fl_plugin_videofission_rule_info where ruletype = @ruletype order by amount asc", new { ruletype = xtraTabControl1.TabIndex }); + if (signInfoS != null && signInfoS.Count != 0) + { + var _signInfo = signInfoS.FirstOrDefault(f => f.ruletype == signInfo.ruletype && f.amount == signInfo.amount); + //if (_signInfo != null) throw new Exception("该条件已经存在,无法增加"); + } + + session.Updateable(signInfo).ExecuteCommand(); + _RefreshData((int)signInfo.ruletype); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 删除 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void simpleButton3_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + fl_plugin_videofission_rule_info signInfo = null; + if (groupControl4.Tag != null) + { + signInfo = groupControl4.Tag as fl_plugin_videofission_rule_info; + session.Deleteable(signInfo).ExecuteCommand(); + _RefreshData((int)signInfo.ruletype); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void buttonCheck1_Click(object sender, EventArgs e) + { + Class1.Config.OnOff = buttonCheck1.Checked; + } + + private void radioGroup1_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + xtraTabControl2.SelectedTabPageIndex = radioGroup1.SelectedIndex; + textEdit5.Text = xtraTabControl2.SelectedTabPage.Text; + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} \ No newline at end of file diff --git a/应用/VideoFission/MainForm.resx b/应用/VideoFission/MainForm.resx new file mode 100644 index 0000000..587796c --- /dev/null +++ b/应用/VideoFission/MainForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>64</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/VideoFission/Properties/AssemblyInfo.cs b/应用/VideoFission/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9e91314 --- /dev/null +++ b/应用/VideoFission/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("VideoFission")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("VideoFission")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("bfedb9c9-bdda-4d73-b528-c958c1b2a8a3")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2019.01.09.2")] +[assembly: AssemblyFileVersion("2019.01.09.2")] diff --git a/应用/VideoFission/Properties/Resources.Designer.cs b/应用/VideoFission/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7105acd --- /dev/null +++ b/应用/VideoFission/Properties/Resources.Designer.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace VideoFission.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VideoFission.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 视频裂变 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 视频裂变 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 视频裂变插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 视频裂变 { + get { + object obj = ResourceManager.GetObject("视频裂变", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 设置 { + get { + object obj = ResourceManager.GetObject("设置", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/VideoFission/Properties/Resources.resx b/应用/VideoFission/Properties/Resources.resx new file mode 100644 index 0000000..62ed68a --- /dev/null +++ b/应用/VideoFission/Properties/Resources.resx @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="视频裂变" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\视频裂变.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="MainFormTitle" xml:space="preserve"> + <value>视频裂变</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>视频裂变插件</value> + <comment>插件介绍</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>视频裂变</value> + <comment>插件名</comment> + </data> + <data name="设置" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\设置.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/VideoFission/Properties/licenses.licx b/应用/VideoFission/Properties/licenses.licx new file mode 100644 index 0000000..a93a180 --- /dev/null +++ b/应用/VideoFission/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/VideoFission/Resources/视频裂变.png b/应用/VideoFission/Resources/视频裂变.png new file mode 100644 index 0000000..80778e8 Binary files /dev/null and b/应用/VideoFission/Resources/视频裂变.png differ diff --git a/应用/VideoFission/Resources/设置.png b/应用/VideoFission/Resources/设置.png new file mode 100644 index 0000000..3e7cb03 Binary files /dev/null and b/应用/VideoFission/Resources/设置.png differ diff --git a/应用/VideoFission/RuleInfoEx.cs b/应用/VideoFission/RuleInfoEx.cs new file mode 100644 index 0000000..1d9d932 --- /dev/null +++ b/应用/VideoFission/RuleInfoEx.cs @@ -0,0 +1,43 @@ +using Api.Framework; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VideoFission.Entitys; + +namespace VideoFission +{ + public static class RuleInfoEx + { + public static fl_plugin_videofission_rule_info FindSignInfo(this SqlSugarClient session, RuleType type, long amount) + { + var list = session.FindSignInfos(type); + if (list != null && list.Count > 0) + { + return list.FirstOrDefault(f=>f.amount == amount); + } + return null; + } + + /// <summary> + /// 获得延迟冻结信息 + /// </summary> + /// <param name="session"></param> + /// <param name="refresh">是否刷新缓存</param> + /// <returns></returns> + public static List<fl_plugin_videofission_rule_info> FindSignInfos(this SqlSugarClient session, RuleType type, bool refresh = false) + { + var key = $"fl_plugin_videofission_rule_info_tables_{type}"; + var list = ApiClient.Cache.Get<List<fl_plugin_videofission_rule_info>>(key); + if (list != null && !refresh) return list; + list = session.Find<fl_plugin_videofission_rule_info>("select * from fl_plugin_videofission_rule_info where ruletype = @ruletype order by amount asc", new { ruletype = (int)type }); + if (list == null) list = new List<fl_plugin_videofission_rule_info>(); + ApiClient.Cache.Set(key, list, 60); + return list; + } + + } +} diff --git a/应用/VideoFission/Tools.cs b/应用/VideoFission/Tools.cs new file mode 100644 index 0000000..abf6039 --- /dev/null +++ b/应用/VideoFission/Tools.cs @@ -0,0 +1,33 @@ +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VideoFission +{ + public static class Tools + { + /// <summary> + /// 返回一个随机解析完成的短链接 + /// </summary> + /// <param name="url">要解析的链接</param> + /// <returns></returns> + public static string FindAnalysisUrlFulfill(string url) + { + try + { + if (string.IsNullOrWhiteSpace(Class1.Config.AnalysisLink)) return string.Empty; + var rows = Class1.Config.AnalysisLink.Split(new string[] { @" +" }, StringSplitOptions.RemoveEmptyEntries); + if (rows != null && rows.Length != 0) + return Api.Framework.ApiClient.ShortURL(rows[new Random().Next(0, rows.Length)] + url).Result; + } + catch + { } + return string.Empty; + } + + } +} diff --git a/应用/VideoFission/VideoFission.csproj b/应用/VideoFission/VideoFission.csproj new file mode 100644 index 0000000..20a440a --- /dev/null +++ b/应用/VideoFission/VideoFission.csproj @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{BFEDB9C9-BDDA-4D73-B528-C958C1B2A8A3}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>VideoFission</RootNamespace> + <AssemblyName>VideoFission</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Entitys\AwardItem.cs" /> + <Compile Include="Entitys\fl_plugin_videofission_recorded_info.cs" /> + <Compile Include="Entitys\fl_plugin_videofission_rule_info.cs" /> + <Compile Include="Entitys\Enums.cs" /> + <Compile Include="RuleInfoEx.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="Tools.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\视频裂变.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\设置.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/WPHRebate/Class1.cs b/应用/WPHRebate/Class1.cs new file mode 100644 index 0000000..52ff37f --- /dev/null +++ b/应用/WPHRebate/Class1.cs @@ -0,0 +1,915 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using WPHRebate.Entitys; +using WPHRebate.Properties; + +namespace WPHRebate +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.唯品会; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (session.TableExist<fl_plugin_wphrebate_wphtgw>()) + { + var wphtgws = session.Find<fl_plugin_wphrebate_wphtgw>("select * from fl_plugin_wphrebate_wphtgw").ToList(); + if (wphtgws != null) + { + foreach (var item in wphtgws) + { + //插入主推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_chief_name, //推广位名称 + adzone_pid = item.pid_chief, //推广位pid + adzone_pid_cps_name = item.pid_chief_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.唯品联盟, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "chief" + }).ExecuteCommand(); + //插入副推广位数据 + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_deputy_name, //推广位名称 + adzone_pid = item.pid_deputy, //推广位pid + adzone_pid_cps_name = item.pid_deputy_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.唯品联盟, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType, //自定义类型 + extend = "deputy" + }).ExecuteCommand(); + } + } + session.DropTable<fl_plugin_wphrebate_wphtgw>(); + } + #endregion + + //创建配置文件 + Config = this.ReadConfig<Config>(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + #region 订单事件处理 + private void SDK_OrderNoticeEvent(object sender, OrderNoticeEvent e) + { + try + { + if (e.Member != null && e.ChatType == CpsType.唯品联盟) + { + //this.OnLog("拼多多订单:" + HttpHelper.ObjectToJson(e)); + + var session = ApiClient.GetSession(); + var order = e.Order as fl_order_weipinhui; + if (order == null) return; + var robot_info = session.FindRobotInfo(e.Member.robot_name, e.Member.robot_type); + + if (robot_info != null) + { + var mess = string.Empty; + var point = HttpHelper.JsonToObject<ItemPoint>(order.db_point) as ItemPoint; + + #region 下单用户订单检测(防撸) + if (e.Customer == null) + { + var prevent_theft_cache = session.FindSingle<fl_prevent_theft_cache>("select * from fl_prevent_theft_cache where order_id = @order_id", new { order_id = order.orderSn });//防止上级多次触发 + if (prevent_theft_cache == null) + { + var isHint = false; + if (!string.IsNullOrWhiteSpace(order.mallId) && e.Member.status != MemberType.白名单) + { + #region 同一店铺多次购买(同一商品) + if (Class1.Config.AShop_SameCommodity_Switch) + { + var frequency = session.Find<fl_order_weipinhui>("select * from fl_order_weipinhui where db_userid = @db_userid and goodsId = @goodsId", new { db_userid = order.db_userid, goodsId = order.goodsId }).Count; + if (Class1.Config.AShop_SameCommodity_Number <= frequency) + { + if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order, e.Member, point), order.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 + ———— + 事件类型:订单检测 + 微信账号:{robot_info.name} + 微信昵称:{robot_info.nick} + 客户账号:{e.Member.username} + 客户昵称:{e.Member.usernick} + 拉黑原因:用户购买同一商品{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_SameCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order.goodsId; + prevent_theft_cache.mall_id = order.mallId; + prevent_theft_cache.order_id = order.orderSn; + prevent_theft_cache.cps_type = CpsType.唯品联盟; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_SameCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_SameCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 + ———— + 事件类型:订单检测 + 微信账号:{robot_info.name} + 微信昵称:{robot_info.nick} + 客户账号:{e.Member.username} + 客户昵称:{e.Member.usernick} + 警告原因:用户购买同一商品{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + + #region 同一店铺多次购买(不同商品) + if (!isHint && Class1.Config.AShop_DifferentCommodity_Switch) + { + var frequency = session.Find<fl_order_weipinhui>("select * from fl_order_weipinhui where db_userid = @db_userid and mallId = @mallId", new { db_userid = order.db_userid, mallId = order.mallId }).Count; + if (Class1.Config.AShop_DifferentCommodity_Number <= frequency) + { + if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order, e.Member, point), order.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 + ———— + 事件类型:订单检测 + 微信账号:{robot_info.name} + 微信昵称:{robot_info.nick} + 客户账号:{e.Member.username} + 客户昵称:{e.Member.usernick} + 拉黑原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.AShop_DifferentCommodity_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order.goodsId; + prevent_theft_cache.mall_id = order.mallId; + prevent_theft_cache.order_id = order.orderSn; + prevent_theft_cache.cps_type = CpsType.唯品联盟; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.AShop_DifferentCommodity_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信*/); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else if (Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.通知钉钉群) + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 + ———— + 事件类型:订单检测 + 微信账号:{robot_info.name} + 微信昵称:{robot_info.nick} + 客户账号:{e.Member.username} + 客户昵称:{e.Member.usernick} + 警告原因:用户在同家店铺购买{frequency}次", Config.notice_robotname); + isHint = true; + } + } + } + #endregion + } + + #region 收货时间验证时长 + if (!isHint && Class1.Config.ReceivingTimeCheck_Switch && order.orderSubStatusName == WeipinhuiOrderSubStatusName.已签收 && e.Member.status != MemberType.白名单) + { + if (DateTime.Now != DateTime.MinValue) + { + var timeLag = (int)Math.Floor((DateTime.Now - Util.GetDateTime(order.orderTime)).TotalHours); + if (timeLag <= Class1.Config.ReceivingTimeCheck_Hour) + { + if (Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单) + { + if (!session.TemporaryBypassedBlack(e.Member)) + { + e.Member.status = MemberType.黑名单; //拉入黑名单 + session.SaveOrUpdate(e.Member); + session.FindBlacklistMemberInfos(true);//刷新黑名单缓存 + + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(Config.Blocked_RestrictTip, order, e.Member, point), order.msg_groupid); + + ApiClient.SendNoticeMessage($@"嫌疑用户拉黑 + ———— + 事件类型:订单检测 + 微信账号:{robot_info.name} + 微信昵称:{robot_info.nick} + 客户账号:{e.Member.username} + 客户昵称:{e.Member.usernick} + 拉黑原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + e.Cancel = true; + + { + prevent_theft_cache = new fl_prevent_theft_cache(); + prevent_theft_cache.operate_type = Class1.Config.ReceivingTimeCheck_OperateType; + prevent_theft_cache.member_id = e.Member.id; + prevent_theft_cache.item_id = order.goodsId; + prevent_theft_cache.mall_id = order.mallId; + prevent_theft_cache.order_id = order.orderSn; + prevent_theft_cache.cps_type = CpsType.唯品联盟; + session.Insertable(prevent_theft_cache).ExecuteCommand(); + } + + if (Config.ReceivingTimeCheck_UserTop) + { + if (robot_info.type == ChatType.微信) + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinHao == robot_info.name /*&& f.WeixinType == WeixinType.Grpc微信 */); + if (wx != null) + { + //var ipad = wx as WXClientImpl_IPAD; + //if (ipad != null) + // ipad.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + wx.EditContacts(e.Member.username, EditContactsType.置顶, e.Member.usernick); + } + } + } + + return; + } + } + else + { + ApiClient.SendNoticeMessage($@"嫌疑用户警告 + ———— + 事件类型:订单检测 + 微信账号:{robot_info.name} + 微信昵称:{robot_info.nick} + 客户账号:{e.Member.username} + 客户昵称:{e.Member.usernick} + 警告原因:订单收货时间间隔{timeLag}小时", Config.notice_robotname); + } + } + } + } + #endregion + + } + } + #endregion + + switch (e.OrderNoticeType) + { + case OrderNoticeType.客户订单: + if (Config.UserOrderChangeSwitch == SwitchType.开启 && !ApiClient.Setting.SystemConfig.message_warning_switch) + { + mess = _GetOrderStateMess(order.db_status, order, e.Member, point); + if (!string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrEmpty(mess)) + ApiClient.SendMessage(robot_info, e.Member.username, mess, order.msg_groupid); + } + return; + case OrderNoticeType.一级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null && point.AwardOne != 0) + { + if (order.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_OneLevelTip; + if (order.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_OneLevelTip; + else if (order.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_OneLevelTip; + else if (order.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_OneLevelTip; + } + } + break; + case OrderNoticeType.二级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_TwoLevelTip; + if (order.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_TwoLevelTip; + else if (order.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_TwoLevelTip; + else if (order.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_TwoLevelTip; + } + } + break; + case OrderNoticeType.三级提成: + if (Config.AgentReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_ThreeLevelTip; + if (order.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_ThreeLevelTip; + else if (order.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_ThreeLevelTip; + else if (order.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_ThreeLevelTip; + } + } + break; + case OrderNoticeType.群主分成: + if (Config.PrincipalReceivedCommissionSwitch == SwitchType.开启) + { + if (e.Customer != null) + { + if (order.db_status == SystemOrderStatus.订单维权中) + mess = Config.ClientOrderRefund_LeaderTip; + if (order.db_status == SystemOrderStatus.订单付款) + mess = Config.OrderPaymentInform_LeaderTip; + else if (order.db_status == SystemOrderStatus.订单失效) + mess = Config.OrderCountermandInform_LeaderTip; + else if (order.db_status == SystemOrderStatus.订单结算) + mess = Config.OrderSettlement_LeaderTip; + } + } + break; + default: + break; + } + + if (!ApiClient.Setting.SystemConfig.message_warning_switch && !string.IsNullOrEmpty(e.Member.username) && !string.IsNullOrWhiteSpace(mess)) + { + ApiClient.SendMessage(robot_info, e.Member.username, new VariateReplace().CommonReplace(mess, order, e.Member, point).Replace("[下级昵称]", e.Customer.realnick ?? "")); + } + } + } + } + catch (Exception ex) + { + this.OnLog($"唯品会订单通知异常:{ex.Message},{ex.StackTrace}"); + } + } + #endregion + + #region 消息事件处理 + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + Compute compute = null; + var goodsName = string.Empty; + try + { + //过滤表情xml和卡片xml + if (((e.Message.Contains(@"<appmsg appid=") && !e.Message.Contains("唯品")) || e.Message.StartsWith("[声音=") || e.Message.Contains(@"<msg><emoji")) && !e.Message.Contains(@"点击链接,再选择浏览器咑閞")) return; + if (!OrderHelper.IsCurrentCpsMess(e.Message, CpsType.唯品联盟)) return; + + string message = e.Message; + + var session = ApiClient.GetSession(); + var member = e.GetMemberinfo(); + #region 唯品会订单绑定 + var messTmp = e.Message.Trim(); + if (Regex.IsMatch(e.Message.Trim(), @"^\d{14}$")) + { + int i = 0; + Next: + var orderid = e.Message.Trim(); + + //通过宝贝的id 和 订单号 进行查询 查看是否存在 + var orders = session.Find<fl_order_weipinhui>("select * from fl_order_weipinhui where orderSn = @orderSn", new { orderSn = orderid }); + if (orders != null && orders.Count != 0) + { + var notices = new List<OrderNoticeEvent>(); + var downWeipinhuiTimer = new DownWeipinhuiTimer(); + foreach (var order in orders) + { + if (order.db_userid != 0 && order.db_userid != member.id) + { + e.SendMessage(Config.OccupyOrderErrorTip.Replace("[订单号]", orderid)); + return; + } + + if (order.db_userid != 0) + { + var point = HttpHelper.JsonToObject<ItemPoint>(order.db_point) as ItemPoint; + member = e.GetMemberinfo(true); + if (order.db_status == SystemOrderStatus.订单付款) + e.SendMessage(new VariateReplace().CommonReplace(Config.OrderRepetBindTip, order, member, point)); + else + e.SendMessage(_GetOrderStateMess(order.db_status, order, member, point)); + } + else + { + if (Util.GetDateTime(order.orderTime) < ApiClient.Setting.SystemConfig.allow_bind_create_order_time) + { + e.SendMessage($"订单:{orderid},已经过了有效绑定时间!"); + return; + } + + if (order.db_status == SystemOrderStatus.订单结算) + order.db_endtime = DateTime.Now.AddMinutes(-5);//重新结算的话,需要将订单的冻结时间重新赋值,让后台处理 + //用户绑定订单 + order.db_robotname = e.RobotName; + order.db_robottype = e.ChatType; + order.msg_groupid = e.Groupid; + order.db_userid = member.id; + session.SaveOrUpdate(order); + + if (member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + + #region 首次付款时间 + var record = session.FindStatisticsRecord(member.id); + if (record == null) + { + record = new fl_statistics_record() { uid = member.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable<fl_statistics_record>(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + { + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable<fl_statistics_record>(record).ExecuteCommand(); + } + } + #endregion + + downWeipinhuiTimer.UpdateOrder(order, session, notices, isFrontData: true); + } + } + #region 触发通知上级获得下级的提成奖励 + if (!ApiClient.Setting.SystemConfig.message_warning_switch && notices.Count != 0) + { + var tasks = TimerTask.GetTimer<Update_NoticeQueue>() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.IsRewards) + tasks.Add(item); + //else + //SDK_OrderNoticeEvent(this, item); + } + } + #endregion + + e.Cancel = true; + } + else + { + if (i < 1) + { + CpsClient.UpdateOrder(CpsType.唯品联盟, DateTime.Now.AddMinutes(-30), DateTime.Now, orderid); + i++; + goto Next; + } + e.SendMessage(Config.NotFoundOrderErrorTip.Replace("[订单号]", orderid)); + e.Cancel = true; + return; + } + } + + if (OrderHelper.IsOrderId(e.Message.Trim())) + return; + #endregion + + #region 关键词解析、链接解析、标题查找 临时注释 + var wphinfoTemps = session.FindWphInfoTempGroups(); + var wphInfoTemp = wphinfoTemps.FirstOrDefault(f => f.name == e.RobotInfo.name && f.onoff == false); + if (wphInfoTemp == null) return; + + var item_id = WPHHelper.GetWphGoodsID(message); + if (string.IsNullOrWhiteSpace(item_id)) + return; + + fl_cps_member wph_cps = null; + var pid = string.Empty;//使用的推广位 + + var isDefault = true; + if (!string.IsNullOrWhiteSpace(e.Groupid))//群pid + { + var groupAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == PrivateAdzoneCustomType.群pid.ToString() && f.group_id == e.Groupid); + if (groupAdzone != null && !string.IsNullOrWhiteSpace(groupAdzone.adzone_pid)) + { + string username = groupAdzone.adzone_pid_cps_name; + pid = groupAdzone.adzone_pid; + wph_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.唯品联盟 && f.username == username); + isDefault = false; + } + } + + if (isDefault)//私人pid + { + var memberAdzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == PrivateAdzoneCustomType.用户私人pid.ToString() && f.member_id == member.id); + if (memberAdzone != null && !string.IsNullOrWhiteSpace(memberAdzone.adzone_pid))//私人推广位 + { + string username = memberAdzone.adzone_pid_cps_name; + wph_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.唯品联盟 && f.username == username); + pid = memberAdzone.adzone_pid; + isDefault = false; + } + } + + if (isDefault)//默认推广位 + { + wph_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.唯品联盟 && f.username == ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? wphInfoTemp.pid_chief_cps_name : wphInfoTemp.pid_deputy_cps_name));//通过判断用户的购物积分,来判断用户使用哪个推广位 + pid = ((member.buy_point >= Config.Point && member.finish_order >= Config.OrderNum) ? wphInfoTemp.pid_chief : wphInfoTemp.pid_deputy); + } + + if (wph_cps == null) throw new Exception("@唯品联盟推广位异常,请检测后重试!"); + if (string.IsNullOrWhiteSpace(pid)) throw new Exception("@唯品联盟推广位为空,请检测后重试!"); + + if (!wph_cps.is_valid) + return; + + var api = CpsClient.CreateWeipinhuiRequest(wph_cps); + if (api == null) throw new Exception("@创建唯品联盟API请求失败"); + + + #region 判断商品Id是否为屏蔽的商品 + if (Class1.Config.ItemIDRestrictList.Contains(item_id)) + { + e.SendMessage(Config.ItemIDRestrictTip.Replace("[商品ID]", item_id)); + return; + } + #endregion + + if (!ApiClient.Setting.SystemConfig.message_warning_switch) + e.SendMessage(Config.SearchingTip);//正在搜索提示 + + try + { + //Dictionary<string, object> privilege = null; + + //var chanTag = Util.EncryptDES($"r={e.RobotInfo.id} t={(int)e.ChatType} u={e.GetMemberinfo().id} p={pid}"); + var chanTag = Util.EncryptDES($"r={e.RobotInfo.id} t={(int)e.ChatType} un={e.GetMemberinfo().username} p={pid}"); + + var wphGInfo = api.SendWeipinhui<WphGoodsInfo>("com.vip.adp.api.open.service.UnionGoodsService-1.0.0#getByGoodsIdsWithOauth", new { goodsIdList = new List<string> { item_id }, requestId = Util.GetUUID(), chanTag = chanTag }); + + if (wphGInfo == null || wphGInfo.result == null || wphGInfo.returnCode == null || wphGInfo.returnCode != "0") + throw new Exception("@.."); + + foreach (var item in wphGInfo.result) + { + if (item.commissionRate == "0") + { + throw new Exception("@商品佣金为0"); + } + + #region 判断店铺ID是否为屏蔽的店铺 + if (item.storeInfo != null) + { + if (Config.SellerIDRestrictlist.Contains(item.storeInfo.storeId)) + { + e.SendMessage(Config.SellerIDRestrictTip.Replace("[店铺ID]", item.storeInfo.storeId).Replace("[店铺名称]", item.storeInfo.storeName)); + return; + } + } + #endregion + + //优惠券金额 + var coupon_price = 0.00d; + + bool isHideCoupon = false;//是否为隐藏优惠券 + var hideUrl = string.Empty;//隐藏优惠券的地址 + //优惠券地址 + //var coupon_click_url = string.Empty; + if (Config.NoCouponModeSwitch != SwitchType.开启) + { + if (item.exclusiveCoupon != null)//隐藏优惠券 + { + var nowTime = Util.GetTimeSpan(DateTime.Now, true); + if (item.exclusiveCoupon.activateBeginTime <= nowTime && nowTime < item.exclusiveCoupon.activateEndTime) + { + var buy = double.Parse(item.exclusiveCoupon.buy);//使用门槛 + if (double.Parse(item.vipPrice) >= buy) + { + coupon_price = double.Parse(item.exclusiveCoupon.fav);//优惠金额 + isHideCoupon = true; + hideUrl = item.exclusiveCoupon.receiveUrl; + } + } + } + + if (!isHideCoupon && item.couponInfo != null)//有券 + { + //优惠券没有过期 + if (item.couponInfo.useEndTime >= Util.GetTimeSpan(DateTime.Now, true)) + { + coupon_price = double.Parse(item.couponInfo.fav); + //coupon_click_url = item.couponInfo.receiveUrl; + } + } + } + //商品标题//< >&"© <,>,&,",©; + goodsName = item.goodsName.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); + + var vipPrice = double.Parse(item.vipPrice); + + var endPrice = vipPrice; + if (coupon_price != 0) + endPrice = (double)((decimal)vipPrice - (decimal)coupon_price); + + //佣金比例 + var commissionRate = double.Parse(item.commissionRate); + + //券后 总佣金 + var useCoupon_totalCommFee = Math.Round(endPrice * (commissionRate / 100.00), 2); + //用券后 给用户的佣金 + var useCoupon_commFee = session.FindItemPoint(member, useCoupon_totalCommFee, 1, CpsType.唯品联盟, out compute); + + Compute compute1 = null; + + //不用券 佣金 + var unuseCoupon_totalCommFee = Math.Round(vipPrice * (commissionRate / 100.00), 2); + //不用券 给用户的佣金 + var unuseCoupon_commFee = session.FindItemPoint(member, unuseCoupon_totalCommFee, 1, CpsType.唯品联盟, out compute1); + + if (compute == null) + compute = compute1; + + var storeName = item.storeInfo == null ? string.Empty : item.storeInfo.storeName; + + WPHCpsUrl result = null; + if (isHideCoupon && !string.IsNullOrWhiteSpace(hideUrl))//这里隐藏优惠券 + { + result = new WPHHelper().GetCpsUrl_Hide(api, new { urlList = new List<string>() { hideUrl }, chanTag = pid, requestId = Util.GetUUID(), statParam = chanTag }); + } + else + { + result = new WPHHelper().GetCpsUrl(api, new { goodsIdList = new List<string>() { item_id }, chanTag = pid, requestId = Util.GetUUID(), statParam = chanTag }); + } + if (result == null || result.returnCode == null || result.returnCode != "0") + throw new Exception($"唯品会转链异常,是否隐藏券:{(isHideCoupon ? "是" : "否")}," + HttpHelper.ObjectToJson(result)); + + var couponUrl = (result.result != null && result.result.urlInfoList.Count != 0) ? result.result.urlInfoList[0].url : string.Empty; + + #region 正常订单 + //有券的情况 + if (coupon_price != 0) + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithCouponTip))) + mess = Config.SearchSuccessWithCouponTip; + else + mess = Config.QQSearchSuccessWithCouponTip; + + e.SendMessage(mess + .Replace("劵", "券") + .Replace("[商品标题]", mess.Contains("<appmsg") ? goodsName.Replace("<", "").Replace(">", "") : goodsName) + .Replace("[商品原价]", string.Format("{0:F}", vipPrice)) + .Replace("[商品主图]", $"[图片={item.goodsMainPicture}]") + .Replace("[图片地址]", item.goodsMainPicture) + .Replace("[店铺名称]", storeName) + .Replace("[券后返利]", string.Format("{0:F}", useCoupon_commFee.UserPoint)) + .Replace("[弃券返利]", string.Format("{0:F}", unuseCoupon_commFee.UserPoint)) + .Replace("[券后价]", string.Format("{0:F}", endPrice)) + .Replace("[优惠券金额]", string.Format("{0:F}", coupon_price)) + .Replace("[购买地址]", couponUrl) + .Replace("[共节省]", ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint).ToString()) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goodsName, string.Format("{0:F}", vipPrice), string.Format("{0:F}", coupon_price), string.Format("{0:F}", endPrice), item.goodsMainPicture, couponUrl, ApiClient.QrImageType.模板B, CpsType.唯品联盟) + "]" : string.Empty) + ); + } + else//没有券的情况 + { + var mess = string.Empty; + if (e.ChatType == ChatType.微信 || e.ChatType == ChatType.企业微信 || (e.ChatType == ChatType.QQ && string.IsNullOrWhiteSpace(Config.QQSearchSuccessWithoutCouponTip))) + mess = Config.SearchSuccessWithoutCouponTip; + else + mess = Config.QQSearchSuccessWithoutCouponTip; + + e.SendMessage(mess + .Replace("[商品标题]", mess.Contains("<appmsg") ? goodsName.Replace("<", "").Replace(">", "") : goodsName) + .Replace("[商品原价]", string.Format("{0:F}", vipPrice)) + .Replace("[商品主图]", $"[图片={item.goodsMainPicture}]") + .Replace("[图片地址]", item.goodsMainPicture) + .Replace("[店铺名称]", storeName) + .Replace("[返利积分]", string.Format("{0:F}", unuseCoupon_commFee.UserPoint)) + .Replace("[购买地址]", couponUrl) + .Replace("[共节省]", string.Format("{0:F}", useCoupon_commFee.UserPoint)) + .Replace("[商品图片]", mess.Contains("[商品图片]") ? "[图片=" + ApiClient.GetQRImage(goodsName, string.Format("{0:F}", vipPrice), "0", string.Format("{0:F}", vipPrice), item.goodsMainPicture, couponUrl, ApiClient.QrImageType.模板B, CpsType.唯品联盟) + "]" : string.Empty) + ); + } + #endregion + + #region 记录用户信息,宝贝信息,平台信息,查询时间等 + session.Insertable(new fl_query_hist() + { + crt_time = DateTime.Now, + type = CpsType.唯品联盟, + itemid = item_id, + groupid = e.Groupid, + robot_name = e.RobotName, + robot_type = e.ChatType, + userid = member.id, + title = goodsName, + adzoneid = pid, + mallid = item.storeInfo == null ? string.Empty : item.storeInfo.storeId, + compute_configdic = compute == null ? string.Empty : JsonConvert.SerializeObject(compute) + }).ExecuteCommand(); + session.UpdateRecord(member.id); + + var shared = new Dictionary<string, object>(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.唯品联盟; + shared["msg_username"] = member.username; + shared["price"] = string.Format("{0:F}", vipPrice); + shared["title"] = goodsName; + shared["coupon_price"] = string.Format("{0:F}", (coupon_price != 0 ? coupon_price : 0)); + shared["user_point"] = coupon_price != 0 ? string.Format("{0:F}", useCoupon_commFee.UserPoint) : string.Format("{0:F}", unuseCoupon_commFee.UserPoint); + shared["economize"] = string.Format("{0:F}", (coupon_price != 0 ? ((decimal)coupon_price + (decimal)useCoupon_commFee.UserPoint) : (decimal)useCoupon_commFee.UserPoint)); + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + #endregion + + } + } + catch (Exception ex) + { + e.SendMessage(Config.SearchNoCommissionTip.Replace("[关键词]", goodsName).Replace("[商品标题]", goodsName));//未搜索到提示语 + + var db = ApiClient.GetSession(); + db.UpdateRecord(e.GetMemberinfo().id); + var shared = new Dictionary<string, object>(); + shared["msg_type"] = "查询宝贝"; + shared["cps_type"] = CpsType.唯品联盟; + shared["msg_username"] = e.GetMemberinfo().username; + shared["price"] = "未知"; + shared["title"] = goodsName; + shared["coupon_price"] = "未知"; + shared["user_point"] = "未知"; + shared["economize"] = "未知"; + + var sharedEvent = new SharedEvents(shared); + EventClient.OnEvent(sender, sharedEvent); + throw ex; + } + #endregion + } + catch (Exception ex) + { + if (ex.Message.StartsWith("@")) + this.OnLog($"W :({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message.Replace("@", "")}"); + else + this.OnLog($"W:({e.RobotInfo.nick}【{e.RobotInfo.name}】){ex.Message} - {ex.StackTrace}"); + this.OnLog(ApiClient.Setting.SystemConfig.msg_error); + } + } + #endregion + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + #region 变量替换 + /// <summary> + /// 订单状态 提示语替换 + /// </summary> + /// <param name="order"></param> + /// <param name="objs"></param> + /// <returns></returns> + private string _GetOrderStateMess(SystemOrderStatus order, params object[] objs) + { + + var mess = string.Empty; + switch (order) + { + case SystemOrderStatus.订单付款: + mess = new VariateReplace().CommonReplace(Config.OrderPaymentTip, objs); + break; + case SystemOrderStatus.订单失效: + mess = new VariateReplace().CommonReplace(Config.OrderFailureTip, objs); + break; + case SystemOrderStatus.全额退款: + case SystemOrderStatus.部分退款: + case SystemOrderStatus.订单维权中: + mess = new VariateReplace().CommonReplace(Config.OrderRefundTip, objs); + break; + case SystemOrderStatus.订单结算: + mess = new VariateReplace().CommonReplace(Config.OrderSettlementTip, objs); + break; + case SystemOrderStatus.订单冻结: + mess = new VariateReplace().CommonReplace(Config.OrderFreezeTip, objs); + break; + } + return mess; + } + #endregion + + } +} \ No newline at end of file diff --git a/应用/WPHRebate/Config.cs b/应用/WPHRebate/Config.cs new file mode 100644 index 0000000..aad3531 --- /dev/null +++ b/应用/WPHRebate/Config.cs @@ -0,0 +1,909 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace WPHRebate +{ + [Config(Name = "插件-唯品会返利-配置")] + public class Config + { + #region 消费积分设置 + /// <summary> + /// 消费积分设置 + /// </summary> + [ + Category("1)、基础设置"), DisplayName("01.主推广位使用条件 - 购物积分"), DefaultValue(20), + Description(@"用户消费积分≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int Point { get; set; } + + /// <summary> + /// 消费积分设置 + /// </summary> + [ + Category("1)、基础设置"), DisplayName("02.主推广位使用条件 - 订单笔数"), DefaultValue(20), + Description(@"用户交易订单数≥主推广位使用条件,才会使用主推广位,否则均使用副推广位(可以理解为:小号推广位) +注:01、02条件为并且关系,两个都要满足") + ] + public int OrderNum { get; set; } + #endregion + + #region 提示语 + /// <summary> + /// 无券模式 + /// </summary> + [ + Category("2)、商品查询"), DisplayName(@"01.无券模式"), DefaultValue(SwitchType.关闭), Description(@"为开启时,有券的商品将以无券的形式返回") + ] + public SwitchType NoCouponModeSwitch { get; set; } + + /// <summary> + /// 正在搜索宝贝提示语 + /// </summary> + [ + Category("2)、商品查询"), DisplayName("02.正在搜索宝贝"), DefaultValue(@"优惠信息查询中....."), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchingTip { get; set; } + + /// <summary> + /// 搜索宝贝无佣金 + /// </summary> + [ + Category("2)、商品查询"), DisplayName("03.无佣金时提示"), DefaultValue(@"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[关键词]、链接无返利变量:[商品标题]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchNoCommissionTip { get; set; } + + /// <summary> + /// 无优惠券时提示 + /// </summary> + [ + Category("2)、商品查询"), DisplayName("04.无优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[店铺名称]、[返利积分]、[购买地址]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithoutCouponTip { get; set; } + + /// <summary> + /// 有优惠券提示语 + /// </summary> + [ + Category("2)、商品查询"), DisplayName("05.有优惠券时提示"), DefaultValue(@"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[共节省]、[商品图片]、XML:[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string SearchSuccessWithCouponTip { get; set; } + + /// <summary> + /// 无优惠券时提示(QQ) + /// </summary> + [ + Category("2)、商品查询"), DisplayName("06.无优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""无优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[商品原价]、[商品主图]、[积分名称]、[店铺名称]、[返利积分]、[购买地址]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithoutCouponTip { get; set; } + + /// <summary> + /// 有优惠券提示语(QQ) + /// </summary> + [ + Category("2)、商品查询"), DisplayName("07.有优惠券时提示(QQ)"), DefaultValue(@""), + Description(@"当该提示语不为空,将回复QQ平台; +当该提示语为空,将使用""有优惠券时提示""的提示语; +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[积分名称]、[商品标题]、[商品原价]、[商品主图]、[店铺名称]、[优惠券金额]、[券后返利]、[弃券返利]、[券后价]、[购买地址]、[共节省]、[商品图片]、[图片地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string QQSearchSuccessWithCouponTip { get; set; } + + + #endregion + + #region 订单通知 + + /// <summary> + /// 用户订单变化通知 + /// </summary> + [ + Category("3)、订单通知"), DisplayName(@"01.用户订单变化通知"), DefaultValue(SwitchType.开启), Description(@"开启用户订单变化通知功能时,用户的订单发生变化时,将通知用户订单的情况") + ] + public SwitchType UserOrderChangeSwitch { get; set; } + /// <summary> + /// 代理获得提成通知 + /// </summary> + [ + Category("3)、订单通知"), DisplayName(@"02.代理获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启代理获得提成通知功能时,用户的订单发生变化时,将通知代理获得提成信息") + ] + public SwitchType AgentReceivedCommissionSwitch { get; set; } + /// <summary> + /// 群负责人获得提成通知 + /// </summary> + [ + Category("3)、订单通知"), DisplayName(@"03.群负责人获得提成通知"), DefaultValue(SwitchType.关闭), Description(@"开启群负责人获得提成通知功能时,用户的订单发生变化时,将通知群负责人获得提成信息") + ] + public SwitchType PrincipalReceivedCommissionSwitch { get; set; } + + /// <summary> + /// 绑定订单号非本人提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("04.已被其他用户绑定"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OccupyOrderErrorTip { get; set; } + + /// <summary> + /// 订单号未找到提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("05.未找到订单号"), DefaultValue(@"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string NotFoundOrderErrorTip { get; set; } + + /// <summary> + /// 重复绑定订单号 + /// </summary> + [Category("3)、订单通知"), DisplayName("06.重复绑定订单号"), DefaultValue(@"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRepetBindTip { get; set; } + + /// <summary> + /// 订单付款提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("07.订单付款"), DefaultValue(@"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentTip { get; set; } + + /// <summary> + /// 订单付款通知一级提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("08.订单付款通知一级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_OneLevelTip { get; set; } + + /// <summary> + /// 订单付款通知二级 + /// </summary> + [Category("3)、订单通知"), DisplayName("09.订单付款通知二级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_TwoLevelTip { get; set; } + + /// <summary> + /// 订单付款通知三级 + /// </summary> + [Category("3)、订单通知"), DisplayName("10.订单付款通知三级"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_ThreeLevelTip { get; set; } + + /// <summary> + /// 订单付款通知群负责人 + /// </summary> + [Category("3)、订单通知"), DisplayName("11.订单付款通知群负责人"), DefaultValue(@"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderPaymentInform_LeaderTip { get; set; } + + /// <summary> + /// 订单冻结提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("12.订单冻结"), DefaultValue(@"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFreezeTip { get; set; } + + /// <summary> + /// 订单结算提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("13.订单结算"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlementTip { get; set; } + + /// <summary> + /// 订单冻结提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("14.订单结算 - 全额退款"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【维权金额】[维权金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"), + Description(@"订单维权成功提示,维权类型为全额退款 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[维权金额]、[结算时间]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFrozen_AllTip { get; set; } + + /// <summary> + /// 订单冻结提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("15.订单结算 - 部分退款"), DefaultValue(@"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【原始返利积分】[原始返利积分] [积分名称] +【维权返利积分】[维权返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,部分退款,返利将相应减少 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"订单维权成功提示,维权类型为部分退款 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[原始返利积分]、[维权返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFrozen_PartTip { get; set; } + + /// <summary> + /// 一级代理获得提成 + /// </summary> + [Category("3)、订单通知"), DisplayName("16.一级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_OneLevelTip { get; set; } + + /// <summary> + /// 二级代理获得提成 + /// </summary> + [Category("3)、订单通知"), DisplayName("17.二级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_TwoLevelTip { get; set; } + + /// <summary> + /// 三级代理获得提成 + /// </summary> + [Category("3)、订单通知"), DisplayName("18.三级代理获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_ThreeLevelTip { get; set; } + + /// <summary> + /// 群负责人获得提成 + /// </summary> + [Category("3)、订单通知"), DisplayName("19.群负责人获得提成"), DefaultValue(@"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderSettlement_LeaderTip { get; set; } + + /// <summary> + /// 订单退款提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("20.订单申请维权"), DefaultValue(@"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"用户申请退款通知改提示 +支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderRefundTip { get; set; } + + /// <summary> + /// 客户维权一级代理 + /// </summary> + [Category("3)、订单通知"), DisplayName("21.客户维权一级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[一级提成积分]、[返利积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_OneLevelTip { get; set; } + + /// <summary> + /// 客户维权二级代理 + /// </summary> + [Category("3)、订单通知"), DisplayName("22.客户维权二级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[二级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_TwoLevelTip { get; set; } + + /// <summary> + /// 客户维权三级代理 + /// </summary> + [Category("3)、订单通知"), DisplayName("23.客户维权三级代理"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[三级提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_ThreeLevelTip { get; set; } + + /// <summary> + /// 客户维权群负责人 + /// </summary> + [Category("3)、订单通知"), DisplayName("24.客户维权群负责人"), DefaultValue(@"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[群负责人提成积分]、[剩余积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ClientOrderRefund_LeaderTip { get; set; } + + /// <summary> + /// 订单失效提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("25.订单失效"), DefaultValue(@"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[订单号]、[付款金额]、[返利积分]、[可兑换积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderFailureTip { get; set; } + + + /// <summary> + /// 订单失效通知一级提示语 + /// </summary> + [Category("3)、订单通知"), DisplayName("26.订单失效通知一级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[一级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_OneLevelTip { get; set; } + + /// <summary> + /// 订单失效通知二级 + /// </summary> + [Category("3)、订单通知"), DisplayName("27.订单失效通知二级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[二级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_TwoLevelTip { get; set; } + + /// <summary> + /// 订单失效通知三级 + /// </summary> + [Category("3)、订单通知"), DisplayName("28.订单失效通知三级"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[三级提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_ThreeLevelTip { get; set; } + + /// <summary> + /// 订单失效通知群负责人 + /// </summary> + [Category("3)、订单通知"), DisplayName("29.订单失效通知群负责人"), DefaultValue(@"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品标题]、[下级昵称]、[下级订单状态]、[群负责人提成积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string OrderCountermandInform_LeaderTip { get; set; } + + #endregion + + #region 查询限制设置 + /// <summary> + /// 店铺ID限制提示 + /// </summary> + [Category("4)、限制通知"), DisplayName("01.店铺ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[店铺ID]、[店铺名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string SellerIDRestrictTip { get; set; } + + /// <summary> + /// 商品ID限制提示 + /// </summary> + [Category("4)、限制通知"), DisplayName("02.商品ID限制提示"), DefaultValue(@"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[商品ID]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string ItemIDRestrictTip { get; set; } + + /// <summary> + /// 拉黑提示 + /// </summary> + [Category("4)、限制通知"), DisplayName("03.用户被拉黑"), DefaultValue(@"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[订单号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor))] + public string Blocked_RestrictTip { get; set; } + + #endregion + + #region 防撸设置 + /// <summary> + /// 同一店铺多次购买(同一商品)开关 + /// </summary> + [Browsable(false)] + public bool AShop_SameCommodity_Switch { get; set; } + + /// <summary> + /// 同一店铺多次购买(同一商品)数量 + /// </summary> + [Browsable(false)] + public int AShop_SameCommodity_Number { get; set; } + + /// <summary> + /// 同一店铺多次购买(同一商品)处理方式 + /// </summary> + [Browsable(false)] + public OperateType AShop_SameCommodity_OperateType { get; set; } + + /// <summary> + /// 同一店铺多次购买(同一商品)置顶 + /// </summary> + [Browsable(false)] + public bool AShop_SameCommodity_UserTop { get; set; } + + /// <summary> + /// 同一店铺多次购买(不同商品)开关 + /// </summary> + [Browsable(false)] + public bool AShop_DifferentCommodity_Switch { get; set; } + + /// <summary> + /// 同一店铺多次购买(不同商品)数量 + /// </summary> + [Browsable(false)] + public int AShop_DifferentCommodity_Number { get; set; } + + /// <summary> + /// 同一店铺多次购买(不同商品)置顶 + /// </summary> + [Browsable(false)] + public bool AShop_DifferentCommodity_UserTop { get; set; } + + /// <summary> + /// 同一店铺多次购买(不同商品)处理方式 + /// </summary> + [Browsable(false)] + public OperateType AShop_DifferentCommodity_OperateType { get; set; } + + /// <summary> + /// 收货时间验证开关 + /// </summary> + [Browsable(false)] + public bool ReceivingTimeCheck_Switch { get; set; } + + /// <summary> + /// 收货时间验证时长(小时) + /// </summary> + [Browsable(false)] + public int ReceivingTimeCheck_Hour { get; set; } + + /// <summary> + /// 收货时间验证处理方式 + /// </summary> + [Browsable(false)] + public OperateType ReceivingTimeCheck_OperateType { get; set; } + + /// <summary> + /// 收货时间验证置顶 + /// </summary> + [Browsable(false)] + public bool ReceivingTimeCheck_UserTop { get; set; } + + /// <summary> + /// 收货时间验证订单冻结时间 + /// </summary> + [Browsable(false)] + public int ReceivingTimeCheck_FreezeTime { get; set; } + + /// <summary> + /// 屏蔽的商品ID集合 + /// </summary> + [Browsable(false)] + public List<string> ItemIDRestrictList { get; set; } + + /// <summary> + /// 屏蔽的卖家ID集合 + /// </summary> + [Browsable(false)] + public List<string> SellerIDRestrictlist { get; set; } + + ///// <summary> + ///// 钉钉Api + ///// </summary> + //[Browsable(false)] + //public string Abnormal_DingDingApi { get; set; } + + ///// <summary> + ///// 钉钉token值 + ///// </summary> + //[Browsable(false)] + //public string Abnormal_DingDingApiToken { get; set; } + + [Browsable(false)] + public string notice_robotname { get; set; } + + #endregion + + public Config() + { + this.SellerIDRestrictTip = @"一一一一查 询 失 败一一一一 +该店铺违规,如有疑问请联系管理员"; + this.ItemIDRestrictTip = @"一一一一查 询 失 败一一一一 +该商品违规,如有疑问请联系管理员"; + this.Blocked_RestrictTip = @"一一一一查 询 失 败一一一一 +[昵称] +订单编号:[订单号] +系统测到账号购物可能存在异常 +您已经被拉入黑名单 +如有异议请联系管理员"; + + this.AShop_SameCommodity_Switch = false; + this.AShop_SameCommodity_Number = 10; + this.AShop_SameCommodity_OperateType = OperateType.通知钉钉群; + this.AShop_SameCommodity_UserTop = false; + this.AShop_DifferentCommodity_Switch = false; + this.AShop_DifferentCommodity_Number = 10; + this.AShop_DifferentCommodity_UserTop = false; + this.AShop_DifferentCommodity_OperateType = OperateType.通知钉钉群; + this.ReceivingTimeCheck_Switch = false; + this.ReceivingTimeCheck_Hour = 24; + this.ReceivingTimeCheck_OperateType = OperateType.订单冻结; + this.ReceivingTimeCheck_FreezeTime = 24; + this.ReceivingTimeCheck_UserTop = false; + this.notice_robotname = string.Empty; + + this.ItemIDRestrictList = new List<string>(); + this.SellerIDRestrictlist = new List<string>(); + + this.Point = 20; + this.OrderNum = 20; + this.NoCouponModeSwitch = SwitchType.关闭; + this.UserOrderChangeSwitch = SwitchType.开启; + this.PrincipalReceivedCommissionSwitch = SwitchType.关闭; + this.AgentReceivedCommissionSwitch = SwitchType.关闭; + this.QQSearchSuccessWithoutCouponTip = string.Empty; + this.QQSearchSuccessWithCouponTip = string.Empty; + this.SearchingTip = @"优惠信息查询中....."; + this.SearchSuccessWithCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【立即减免】[优惠券金额] [积分名称] +【返利金额】[券后返利] [积分名称] +【为您节约】[共节省]元 + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦! +下单2分钟后会收到【绑定成功】提示,没有请复制订单编号给我"; + this.SearchSuccessWithoutCouponTip = @"一一一一返 利 消 息一一一一 +[商品标题] +【宝贝原价】[商品原价] [积分名称] +【返利红包】[返利积分] [积分名称] + +打开网址复制优惠口令: +[购买地址] +━┉┉┉┉∞┉┉┉┉━ +勿用红包付款,否则无法拿返利哦!"; + this.SearchNoCommissionTip = @"一一一一优 惠 结 束一一一一 +活动已结束,暂无其他优惠! +建议您换个宝贝继续查询哦!"; + this.OrderRepetBindTip = @"一一一一重 复 绑 定一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentTip = @"一一一一绑 定 成 功一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] [积分名称] +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +收货后,就可以领取返利红包! +发送关键词:账单 (可查详细信息)"; + this.OrderPaymentInform_OneLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_TwoLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_ThreeLevelTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + + this.OrderPaymentInform_LeaderTip = @"一一一一下 级 付 款一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderFailureTip = @"一一一一订 单 失 效一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +退款或未支付,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderCountermandInform_OneLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【一级提成积分】[一级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_TwoLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【二级提成积分】[二级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_ThreeLevelTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【三级提成积分】[三级提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderCountermandInform_LeaderTip = @"一一一一下 级 订 单 失 效一一一一 +【下级昵称】[下级昵称] +【订单状态】[下级订单状态] +【群负责人提成积分】[群负责人提成积分] [积分名称] +一一一一一一一一一一一一一"; + this.OrderRefundTip = @"一一一一维 权 退 款一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于维权退款,已经撤销返利! +发送关键词:账单 (可查详细信息)"; + this.OrderFreezeTip = @"一一一一订 单 冻 结一一一一 +[昵称] +[订单号] +[商品标题] +已确认收货,系统将“[结算时间]”,奖励您[返利积分][积分名称]"; + this.OrderSettlementTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【返利积分】[返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OccupyOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,这个订单号已被其他用户绑定! +Ps:如是您的订单,请联系我们处理!"; + this.NotFoundOrderErrorTip = @"一一一一绑 定 失 败一一一一 +抱歉,找不到这个订单! + +已经记录该订单号 +5分钟内无绑定信息,请重新发送 + +可能失败的原因: +①没有通过优惠口令下单! +②使用了节日红包,如:双11 +③可能系统延迟,5分钟后重试!"; + this.OrderFrozen_AllTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【维权金额】[维权金额] 元 +【返利积分】[返利积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,全额退款,佣金为0 +发送关键词:账单 (可查详细信息)"; + this.OrderFrozen_PartTip = @"一一一一订 单 结 算一一一一 +[商品标题] +【订单编号】[订单号] +【付款金额】[付款金额] 元 +【原始返利积分】[原始返利积分] [积分名称] +【维权返利积分】[维权返利积分] [积分名称] +【可兑换积分】[可兑换积分] [积分名称] +一一一一一一一一一一一一一 +由于订单维权,部分退款,返利将相应减少 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_OneLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_TwoLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_ThreeLevelTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.OrderSettlement_LeaderTip = @"一一一一获 得 提 成一一一一 +【下级昵称】[下级昵称] +【佣金金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_OneLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[一级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_TwoLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[二级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_ThreeLevelTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[三级提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + this.ClientOrderRefund_LeaderTip = @"一一一一客 户 维 权一一一一 +【下级昵称】[下级昵称] +【维权金额】[群负责人提成积分] [积分名称] +【剩余积分】[剩余积分] [积分名称] +一一一一一一一一一一一一一 +发送关键词:兑换 (可兑换现金哦) +发送关键词:账单 (可查详细信息)"; + } + + } +} diff --git a/应用/WPHRebate/Entitys/WphGoodsInfo.cs b/应用/WPHRebate/Entitys/WphGoodsInfo.cs new file mode 100644 index 0000000..320b95a --- /dev/null +++ b/应用/WPHRebate/Entitys/WphGoodsInfo.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WPHRebate.Entitys +{ + + +} diff --git a/应用/WPHRebate/Entitys/fl_plugin_wphrebate_wphtgw.cs b/应用/WPHRebate/Entitys/fl_plugin_wphrebate_wphtgw.cs new file mode 100644 index 0000000..882d3d2 --- /dev/null +++ b/应用/WPHRebate/Entitys/fl_plugin_wphrebate_wphtgw.cs @@ -0,0 +1,45 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WPHRebate.Entitys +{ + public class fl_plugin_wphrebate_wphtgw : base_model + { + /// <summary> + /// 左连接主表 fl_robot_info 的主键 + /// </summary> + public int robot_id { get; set; } + /// <summary> + /// 主推广位CPS名称 + /// </summary> + public string pid_chief_cps_name { get; set; } + /// <summary> + /// 主推广位id + /// </summary> + public string pid_chief { get; set; } + /// <summary> + /// 主推广位昵称 + /// </summary> + public string pid_chief_name { get; set; } + /// <summary> + /// 副推广位CPS名称 + /// </summary> + public string pid_deputy_cps_name { get; set; } + /// <summary> + /// 副推广位id + /// </summary> + public string pid_deputy { get; set; } + /// <summary> + /// 副推广位名称 + /// </summary> + public string pid_deputy_name { get; set; } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/WPHRebate/Entitys/wphinfo_temp.cs b/应用/WPHRebate/Entitys/wphinfo_temp.cs new file mode 100644 index 0000000..9b753be --- /dev/null +++ b/应用/WPHRebate/Entitys/wphinfo_temp.cs @@ -0,0 +1,94 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WPHRebate.Entitys +{ + /// <summary> + /// 临时的表 (用于数据显示) + /// </summary> + public class wphinfo_temp + { + public long ID { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _pid_chief_cps_name { get; set; } + public string pid_chief_cps_name + { + get { return _pid_chief_cps_name; } + set { _pid_chief_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_chief; + /// <summary> + /// 主推广位id + /// </summary> + public string pid_chief + { + get { return _pid_chief; } + set { _pid_chief = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _pid_chief_name; + + public string pid_chief_name + { + get { return _pid_chief_name; } + set { _pid_chief_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// <summary> + /// 副推广位cps名称 + /// </summary> + private string _pid_deputy_cps_name { get; set; } + public string pid_deputy_cps_name + { + get { return _pid_deputy_cps_name; } + set { _pid_deputy_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pid_deputy; + + /// <summary> + /// 副推广位id + /// </summary> + public string pid_deputy + { + get { return _pid_deputy; } + set { _pid_deputy = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 副推广位名称 + /// </summary> + private string _pid_deputy_name; + + public string pid_deputy_name + { + get { return _pid_deputy_name; } + set { _pid_deputy_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/WPHRebate/MainForm.Designer.cs b/应用/WPHRebate/MainForm.Designer.cs new file mode 100644 index 0000000..760ab42 --- /dev/null +++ b/应用/WPHRebate/MainForm.Designer.cs @@ -0,0 +1,782 @@ +namespace WPHRebate +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl19 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox4 = new System.Windows.Forms.ComboBox(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.checkBox3 = new System.Windows.Forms.CheckBox(); + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.buttonCheck = new UI.Framework.Controls.ButtonCheck(); + this.memoEdit6 = new DevExpress.XtraEditors.MemoEdit(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.numericUpDown4 = new System.Windows.Forms.NumericUpDown(); + this.comboBox3 = new System.Windows.Forms.ComboBox(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl32 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl31 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.xtraTabPage3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(991, 577); + this.xtraTabControl1.TabIndex = 8; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage1.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(224, 189); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 7; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 514); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(989, 37); + this.pageControl1.TabIndex = 5; + // + // gridControl1 + // + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(989, 508); + this.gridControl1.TabIndex = 4; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "ID"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 55; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "平台类型"; + this.gridColumn1.FieldName = "chattype"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 1; + this.gridColumn1.Width = 110; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "账号"; + this.gridColumn2.FieldName = "name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 2; + this.gridColumn2.Width = 164; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "账号昵称"; + this.gridColumn3.FieldName = "nick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 138; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn5.AppearanceCell.Options.UseFont = true; + this.gridColumn5.AppearanceCell.Options.UseForeColor = true; + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "主推广位"; + this.gridColumn5.FieldName = "pid_chief_name"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 148; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn7.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn7.AppearanceCell.Options.UseFont = true; + this.gridColumn7.AppearanceCell.Options.UseForeColor = true; + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "副推广位"; + this.gridColumn7.FieldName = "pid_deputy_name"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 5; + this.gridColumn7.Width = 130; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "禁止使用"; + this.gridColumn9.FieldName = "onoff"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 6; + this.gridColumn9.Width = 109; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(989, 551); + this.settingControl1.TabIndex = 0; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupBox1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(989, 551); + this.xtraTabPage3.Text = " 防 撸 设 置 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.labelControl19); + this.groupBox1.Controls.Add(this.comboBox4); + this.groupBox1.Controls.Add(this.labelControl20); + this.groupBox1.Controls.Add(this.separatorControl2); + this.groupBox1.Controls.Add(this.separatorControl1); + this.groupBox1.Controls.Add(this.checkBox3); + this.groupBox1.Controls.Add(this.checkBox2); + this.groupBox1.Controls.Add(this.checkBox1); + this.groupBox1.Controls.Add(this.buttonCheck2); + this.groupBox1.Controls.Add(this.buttonCheck1); + this.groupBox1.Controls.Add(this.buttonCheck); + this.groupBox1.Controls.Add(this.memoEdit6); + this.groupBox1.Controls.Add(this.memoEdit5); + this.groupBox1.Controls.Add(this.numericUpDown2); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.numericUpDown4); + this.groupBox1.Controls.Add(this.comboBox3); + this.groupBox1.Controls.Add(this.comboBox2); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Controls.Add(this.labelControl30); + this.groupBox1.Controls.Add(this.labelControl32); + this.groupBox1.Controls.Add(this.numericUpDown3); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl31); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl29); + this.groupBox1.Controls.Add(this.labelControl28); + this.groupBox1.Controls.Add(this.labelControl27); + this.groupBox1.Location = new System.Drawing.Point(38, 25); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(916, 498); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础设置 "; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(651, 188); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(215, 14); + this.labelControl5.TabIndex = 60; + this.labelControl5.Text = "(在【系统管理->群通知机器人】中添加)"; + // + // labelControl19 + // + this.labelControl19.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl19.Appearance.Options.UseForeColor = true; + this.labelControl19.Location = new System.Drawing.Point(505, 188); + this.labelControl19.Name = "labelControl19"; + this.labelControl19.Size = new System.Drawing.Size(130, 14); + this.labelControl19.TabIndex = 59; + this.labelControl19.Text = "(未选择时使用系统设置)"; + // + // comboBox4 + // + this.comboBox4.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox4.FormattingEnabled = true; + this.comboBox4.Location = new System.Drawing.Point(170, 185); + this.comboBox4.Name = "comboBox4"; + this.comboBox4.Size = new System.Drawing.Size(308, 22); + this.comboBox4.TabIndex = 58; + // + // labelControl20 + // + this.labelControl20.Location = new System.Drawing.Point(73, 188); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(91, 14); + this.labelControl20.TabIndex = 57; + this.labelControl20.Text = "群通知API接口:"; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(44, 103); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(823, 23); + this.separatorControl2.TabIndex = 32; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(44, 50); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(823, 23); + this.separatorControl1.TabIndex = 32; + // + // checkBox3 + // + this.checkBox3.AutoSize = true; + this.checkBox3.Location = new System.Drawing.Point(651, 133); + this.checkBox3.Name = "checkBox3"; + this.checkBox3.Size = new System.Drawing.Size(108, 18); + this.checkBox3.TabIndex = 31; + this.checkBox3.Text = "置顶用户(微信)"; + this.checkBox3.UseVisualStyleBackColor = true; + this.checkBox3.Visible = false; + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(651, 81); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(108, 18); + this.checkBox2.TabIndex = 31; + this.checkBox2.Text = "置顶用户(微信)"; + this.checkBox2.UseVisualStyleBackColor = true; + this.checkBox2.Visible = false; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(651, 28); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(108, 18); + this.checkBox1.TabIndex = 31; + this.checkBox1.Text = "置顶用户(微信)"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.Visible = false; + // + // buttonCheck2 + // + this.buttonCheck2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = true; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(89, 132); + this.buttonCheck2.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(57, 22); + this.buttonCheck2.TabIndex = 28; + // + // buttonCheck1 + // + this.buttonCheck1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = true; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(89, 79); + this.buttonCheck1.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(57, 22); + this.buttonCheck1.TabIndex = 28; + // + // buttonCheck + // + this.buttonCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck.Checked = true; + this.buttonCheck.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck.Location = new System.Drawing.Point(89, 26); + this.buttonCheck.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck.Name = "buttonCheck"; + this.buttonCheck.Size = new System.Drawing.Size(57, 22); + this.buttonCheck.TabIndex = 28; + // + // memoEdit6 + // + this.memoEdit6.Location = new System.Drawing.Point(50, 389); + this.memoEdit6.Name = "memoEdit6"; + this.memoEdit6.Size = new System.Drawing.Size(817, 96); + this.memoEdit6.TabIndex = 26; + // + // memoEdit5 + // + this.memoEdit5.Location = new System.Drawing.Point(50, 263); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Size = new System.Drawing.Size(817, 96); + this.memoEdit5.TabIndex = 27; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(708, 131); + this.numericUpDown2.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(75, 22); + this.numericUpDown2.TabIndex = 22; + this.numericUpDown2.Value = new decimal(new int[] { + 24, + 0, + 0, + 0}); + this.numericUpDown2.Visible = false; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(264, 132); + this.numericUpDown1.Maximum = new decimal(new int[] { + 999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(91, 22); + this.numericUpDown1.TabIndex = 22; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // numericUpDown4 + // + this.numericUpDown4.Location = new System.Drawing.Point(370, 79); + this.numericUpDown4.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown4.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown4.Name = "numericUpDown4"; + this.numericUpDown4.Size = new System.Drawing.Size(93, 22); + this.numericUpDown4.TabIndex = 22; + this.numericUpDown4.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // comboBox3 + // + this.comboBox3.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox3.FormattingEnabled = true; + this.comboBox3.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群", + "订单冻结"}); + this.comboBox3.Location = new System.Drawing.Point(507, 131); + this.comboBox3.Name = "comboBox3"; + this.comboBox3.Size = new System.Drawing.Size(121, 22); + this.comboBox3.TabIndex = 25; + this.comboBox3.SelectedIndexChanged += new System.EventHandler(this.comboBox3_SelectedIndexChanged); + // + // comboBox2 + // + this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox2.Location = new System.Drawing.Point(507, 79); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(121, 22); + this.comboBox2.TabIndex = 25; + this.comboBox2.SelectedIndexChanged += new System.EventHandler(this.comboBox2_SelectedIndexChanged); + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "拉入黑名单", + "通知钉钉群"}); + this.comboBox1.Location = new System.Drawing.Point(507, 26); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(121, 22); + this.comboBox1.TabIndex = 25; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // labelControl30 + // + this.labelControl30.Location = new System.Drawing.Point(471, 83); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(16, 14); + this.labelControl30.TabIndex = 16; + this.labelControl30.Text = "次."; + // + // labelControl32 + // + this.labelControl32.Location = new System.Drawing.Point(50, 369); + this.labelControl32.Name = "labelControl32"; + this.labelControl32.Size = new System.Drawing.Size(72, 14); + this.labelControl32.TabIndex = 17; + this.labelControl32.Text = "屏蔽店铺ID:"; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(370, 26); + this.numericUpDown3.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.numericUpDown3.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(93, 22); + this.numericUpDown3.TabIndex = 23; + this.numericUpDown3.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(128, 369); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(132, 14); + this.labelControl2.TabIndex = 18; + this.labelControl2.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl1 + // + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(128, 243); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(132, 14); + this.labelControl1.TabIndex = 18; + this.labelControl1.Text = "(多个编码用逗号\",\"分隔)"; + // + // labelControl31 + // + this.labelControl31.Location = new System.Drawing.Point(50, 243); + this.labelControl31.Name = "labelControl31"; + this.labelControl31.Size = new System.Drawing.Size(72, 14); + this.labelControl31.TabIndex = 18; + this.labelControl31.Text = "屏蔽商品ID:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(653, 135); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(48, 14); + this.labelControl8.TabIndex = 19; + this.labelControl8.Text = "订单冻结"; + this.labelControl8.Visible = false; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(789, 135); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(28, 14); + this.labelControl7.TabIndex = 19; + this.labelControl7.Text = "小时."; + this.labelControl7.Visible = false; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(373, 136); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(64, 14); + this.labelControl4.TabIndex = 19; + this.labelControl4.Text = "小时内收货."; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(170, 136); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 19; + this.labelControl3.Text = "用户购买的商品"; + // + // labelControl29 + // + this.labelControl29.Location = new System.Drawing.Point(170, 83); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(190, 14); + this.labelControl29.TabIndex = 19; + this.labelControl29.Text = "用户在同家店铺多次购物(不同商品)"; + // + // labelControl28 + // + this.labelControl28.Location = new System.Drawing.Point(471, 30); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(16, 14); + this.labelControl28.TabIndex = 20; + this.labelControl28.Text = "次."; + // + // labelControl27 + // + this.labelControl27.Location = new System.Drawing.Point(170, 30); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(190, 14); + this.labelControl27.TabIndex = 21; + this.labelControl27.Text = "用户在同家店铺多次购买(同一商品)"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(991, 577); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl19; + private System.Windows.Forms.ComboBox comboBox4; + private DevExpress.XtraEditors.LabelControl labelControl20; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private System.Windows.Forms.CheckBox checkBox3; + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.CheckBox checkBox1; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private UI.Framework.Controls.ButtonCheck buttonCheck; + private DevExpress.XtraEditors.MemoEdit memoEdit6; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.NumericUpDown numericUpDown4; + private System.Windows.Forms.ComboBox comboBox3; + private System.Windows.Forms.ComboBox comboBox2; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.LabelControl labelControl30; + private DevExpress.XtraEditors.LabelControl labelControl32; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl31; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl29; + private DevExpress.XtraEditors.LabelControl labelControl28; + private DevExpress.XtraEditors.LabelControl labelControl27; + } +} \ No newline at end of file diff --git a/应用/WPHRebate/MainForm.cs b/应用/WPHRebate/MainForm.cs new file mode 100644 index 0000000..ea52ef9 --- /dev/null +++ b/应用/WPHRebate/MainForm.cs @@ -0,0 +1,308 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using WPHRebate.Entitys; +using WPHRebate.Properties; + +namespace WPHRebate +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + var apis = ApiClient.GetSession().FindNoticeapiRobots().ToArray(); + var rst = new List<string>(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + comboBox4.DataSource = rst; + + this.settingControl1.Bind(Class1.Config, 110); + + this.buttonCheck.Checked = Class1.Config.AShop_SameCommodity_Switch; + this.numericUpDown3.Value = Class1.Config.AShop_SameCommodity_Number; + this.comboBox1.SelectedIndex = Class1.Config.AShop_SameCommodity_OperateType == OperateType.拉入黑名单 ? 0 : 1; + + this.buttonCheck1.Checked = Class1.Config.AShop_DifferentCommodity_Switch; + this.numericUpDown4.Value = Class1.Config.AShop_DifferentCommodity_Number; + this.comboBox2.SelectedIndex = Class1.Config.AShop_DifferentCommodity_OperateType == OperateType.拉入黑名单 ? 0 : 1; + + this.buttonCheck2.Checked = Class1.Config.ReceivingTimeCheck_Switch; + this.numericUpDown1.Value = Class1.Config.ReceivingTimeCheck_Hour; + this.comboBox3.SelectedIndex = Class1.Config.ReceivingTimeCheck_OperateType == OperateType.拉入黑名单 ? 0 : Class1.Config.ReceivingTimeCheck_OperateType == OperateType.通知钉钉群 ? 1 : 2; + this.numericUpDown2.Value = Class1.Config.ReceivingTimeCheck_FreezeTime; + + this.comboBox4.SelectedIndex = rst.IndexOf(Class1.Config.notice_robotname) == -1 ? 0 : rst.IndexOf(Class1.Config.notice_robotname); + + this.memoEdit5.Text = string.Join(",", Class1.Config.ItemIDRestrictList); + this.memoEdit6.Text = string.Join(",", Class1.Config.SellerIDRestrictlist); + + #region 加载所有的账号 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<wphinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.唯品联盟}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.唯品联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label1.Visible = gridView1.RowCount == 0; + + #endregion + } + + /// <summary> + /// 修改显示内容的事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name" || e.Column.FieldName == "adzone_activity_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView1.GetSelectedRows()[0]; + var id = this.gridView1.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "pid_chief_name" || e.Column.FieldName == "pid_deputy_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.唯品联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + var pidName = e.Column.FieldName == "pid_chief_name" ? "chief" : "deputy"; + var adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzone == null) + { + adzones = new List<fl_adzone_info>(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzone.extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + #region 有出现两个重复无法修复的情况,删除一个 + var repetAdzone = adzones.Where(f => f.extend == pidName).ToList(); + if (repetAdzone.Count > 1) + { + for (int i = 1; i <= repetAdzone.Count - 1; i++) + { + session.Deleteable(repetAdzone[i]).ExecuteCommand(); + } + adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + } + #endregion + + adzone = adzones.FirstOrDefault(f => f.extend == pidName); + + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindWphInfoTempGroups(true); + session.FindAdzoneInfos(true); + session.FindWeipinhuiAutoBindPid(true);//刷新推广位 + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos(true).Where(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)).ToList(); + #region 这里判断存在两个推广位(主/副),不存在的(主副数据将创建对象) + if (adzones != null && adzones.Count < 2) + { + var pidNames = new string[] { "chief", "deputy" }; + if (adzones.Count == 0) + { + adzones = new List<fl_adzone_info>(); + foreach (var item in pidNames) + { + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, item, false); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + else + { + var unCreate = pidNames.FirstOrDefault(f => f != adzones[0].extend);//获取数据库中不存在的(主/副)推广位数据,下方添加不存在的对象 + var adzoneInfo = CreateAdzoneInfo(string.Empty, string.Empty, string.Empty, id, unCreate, adzones[0].onoff); + session.SaveOrUpdate(adzoneInfo); + adzones.Add(adzoneInfo); + } + } + #endregion + + if (adzones != null)//数据库中存在 + session.ExcuteSQL("update fl_adzone_info set onoff = @onoff where robot_id = @robot_id and alliance_id = @alliance_id and custom_type = @custom_type", new { onoff = !adzones[0].onoff, robot_id = id, alliance_id = (int)CpsType.唯品联盟, custom_type = Resources.SoftwareType }); + session.FindWphInfoTempGroups(true); + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + session.FindWeipinhuiAutoBindPid(true);//刷新推广位 + } + } + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 创建fl_adzone_info对象 + /// </summary> + /// <param name="adzone_name"></param> + /// <param name="adzone_pid"></param> + /// <param name="adzone_pid_cps_name"></param> + /// <param name="rid"></param> + /// <param name="item"></param> + /// <returns></returns> + private fl_adzone_info CreateAdzoneInfo(string adzone_name, string adzone_pid, string adzone_pid_cps_name, string rid, string item, bool onoff = false) + { + return new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = adzone_name, //推广位名称 + adzone_pid = adzone_pid, //推广位pid + adzone_pid_cps_name = adzone_pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.唯品联盟, //联盟id + robot_id = int.Parse(rid), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = onoff, //不禁用 + extend = item + }; + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Class1.Config.AShop_SameCommodity_Switch = buttonCheck.Checked; + Class1.Config.AShop_SameCommodity_Number = (int)numericUpDown3.Value; + Class1.Config.AShop_SameCommodity_OperateType = comboBox1.SelectedIndex == 0 ? OperateType.拉入黑名单 : OperateType.通知钉钉群; + + Class1.Config.AShop_DifferentCommodity_Switch = buttonCheck1.Checked; + Class1.Config.AShop_DifferentCommodity_Number = (int)numericUpDown4.Value; + Class1.Config.AShop_DifferentCommodity_OperateType = comboBox2.SelectedIndex == 0 ? OperateType.拉入黑名单 : OperateType.通知钉钉群; + + Class1.Config.ReceivingTimeCheck_Switch = buttonCheck2.Checked; + Class1.Config.ReceivingTimeCheck_Hour = (int)numericUpDown1.Value; + Class1.Config.ReceivingTimeCheck_OperateType = comboBox3.SelectedIndex == 0 ? OperateType.拉入黑名单 : comboBox3.SelectedIndex == 1 ? OperateType.通知钉钉群 : OperateType.订单冻结; + Class1.Config.ReceivingTimeCheck_FreezeTime = (int)numericUpDown2.Value; + + Class1.Config.notice_robotname = comboBox4.SelectedValue.ToString(); + + Class1.Config.ItemIDRestrictList = memoEdit5.Text.Trim().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + Class1.Config.SellerIDRestrictlist = memoEdit6.Text.Trim().Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + Util.Save(Class1.Config); + + OrderHelper.RefreshPddConfig(true); + } + + private void comboBox3_SelectedIndexChanged(object sender, EventArgs e) + { + labelControl7.Visible = labelControl8.Visible = numericUpDown2.Visible = comboBox3.SelectedIndex == 2; + checkBox3.Visible = comboBox3.SelectedIndex == 0; + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + checkBox1.Visible = comboBox1.SelectedIndex == 0; + } + + private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) + { + checkBox2.Visible = comboBox2.SelectedIndex == 0; + } + + } +} diff --git a/应用/WPHRebate/MainForm.resx b/应用/WPHRebate/MainForm.resx new file mode 100644 index 0000000..a490856 --- /dev/null +++ b/应用/WPHRebate/MainForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>51</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/WPHRebate/Properties/AssemblyInfo.cs b/应用/WPHRebate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f683e08 --- /dev/null +++ b/应用/WPHRebate/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("WPHRebate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WPHRebate")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("2cb069fc-d25a-417e-837f-fafdcee639b2")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/WPHRebate/Properties/Resources.Designer.cs b/应用/WPHRebate/Properties/Resources.Designer.cs new file mode 100644 index 0000000..ebf6fe8 --- /dev/null +++ b/应用/WPHRebate/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace WPHRebate.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WPHRebate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 唯品会返利 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 唯品会返利 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 唯品会返利插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找类似 唯品会返利 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 唯品会 { + get { + object obj = ResourceManager.GetObject("唯品会", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/WPHRebate/Properties/Resources.resx b/应用/WPHRebate/Properties/Resources.resx new file mode 100644 index 0000000..761a9d7 --- /dev/null +++ b/应用/WPHRebate/Properties/Resources.resx @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="MainFormTitle" xml:space="preserve"> + <value>唯品会返利</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>唯品会返利</value> + <comment>插件名</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>唯品会返利插件</value> + <comment>插件介绍</comment> + </data> + <data name="SoftwareType" xml:space="preserve"> + <value>唯品会返利</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="唯品会" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\唯品会.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/WPHRebate/Properties/licenses.licx b/应用/WPHRebate/Properties/licenses.licx new file mode 100644 index 0000000..301e7e3 --- /dev/null +++ b/应用/WPHRebate/Properties/licenses.licx @@ -0,0 +1,3 @@ +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/WPHRebate/Resources/唯品会.png b/应用/WPHRebate/Resources/唯品会.png new file mode 100644 index 0000000..c42f74c Binary files /dev/null and b/应用/WPHRebate/Resources/唯品会.png differ diff --git a/应用/WPHRebate/SessionExt.cs b/应用/WPHRebate/SessionExt.cs new file mode 100644 index 0000000..80cbba5 --- /dev/null +++ b/应用/WPHRebate/SessionExt.cs @@ -0,0 +1,43 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WPHRebate.Entitys; +using WPHRebate.Properties; + +namespace WPHRebate +{ + public static class SessionExt + { + const string wphinfo_temp_list_wphrebate = "wphinfo_temp_list_wphrebate"; + + /// <summary> + /// 获取fl_adzone_info表的数据集合缓存 + /// </summary> + /// <param name="session"></param> + /// <param name="refresh">刷新</param> + /// <returns></returns> + public static List<wphinfo_temp> FindWphInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + + var wphinfo_temp_groups = ApiClient.Cache.Get<List<wphinfo_temp>>(wphinfo_temp_list_wphrebate);//根据KEY、获得缓存 + if (refresh || wphinfo_temp_groups == null) + { + wphinfo_temp_groups = session.Find<wphinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.* from fl_robot_info ri left join (select ai1_temp.robot_id as id,ai1_temp.onoff as onoff,ai1_temp.adzone_pid_cps_name as pid_chief_cps_name,ai1_temp.adzone_pid as pid_chief,ai1_temp.adzone_name as pid_chief_name,ai2_temp.adzone_pid_cps_name as pid_deputy_cps_name,ai2_temp.adzone_pid as pid_deputy,ai2_temp.adzone_name as pid_deputy_name from (select * from fl_adzone_info ai1 where ai1.alliance_id = '{(int)CpsType.唯品联盟}' and ai1.custom_type = '{Resources.SoftwareType}' and ai1.extend = 'chief') ai1_temp INNER JOIN (select * from fl_adzone_info ai2 where ai2.alliance_id = '{(int)CpsType.唯品联盟}' and ai2.custom_type = '{Resources.SoftwareType}' and ai2.extend='deputy') ai2_temp on ai1_temp.robot_id = ai2_temp.robot_id) flag on ri.id = flag.id"); + ApiClient.Cache.Set(wphinfo_temp_list_wphrebate, wphinfo_temp_groups, 60); + } + return wphinfo_temp_groups; + } + + public static void Clear() + { + ApiClient.Cache.Remove(wphinfo_temp_list_wphrebate); + } + } +} diff --git a/应用/WPHRebate/WPHRebate.csproj b/应用/WPHRebate/WPHRebate.csproj new file mode 100644 index 0000000..e6f12a2 --- /dev/null +++ b/应用/WPHRebate/WPHRebate.csproj @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{2CB069FC-D25A-417E-837F-FAFDCEE639B2}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>WPHRebate</RootNamespace> + <AssemblyName>WPHRebate</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\Newtonsoft.Json.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar"> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Entitys\fl_plugin_wphrebate_wphtgw.cs" /> + <Compile Include="Entitys\WphGoodsInfo.cs" /> + <Compile Include="Entitys\wphinfo_temp.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="SessionExt.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\唯品会.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/WacheCheckUrl/Class1.cs b/应用/WacheCheckUrl/Class1.cs new file mode 100644 index 0000000..ef33e8e --- /dev/null +++ b/应用/WacheCheckUrl/Class1.cs @@ -0,0 +1,129 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WacheCheckUrl.Properties; +using Chat.Framework; + +namespace WacheCheckUrl +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.检测; + this.Name = "链接有效性"; + this.Note = "检测链接有效性"; + } + + public override void Start() + { + SDK.WebRequestEvent += SDK_WebRequestEvent; + } + + private Dictionary<string, int> dic = new Dictionary<string, int>(); + + private void SDK_WebRequestEvent(object sender, Api.Framework.Events.WebRequestEvents e) + { + try + { + if (e.Param.ContainsKey("url")) + { + var url = e.Param["url"]; + if (string.IsNullOrWhiteSpace(url)) throw new Exception("url不能为空"); + + var wxList = ChatClient.WXClient.Values.Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线 && f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信).ToList(); + if (wxList.Count > 0) + { + Random rd = new Random(Guid.NewGuid().GetHashCode()); + int index = rd.Next(wxList.Count); + + var wx = wxList[index]; + + if (dic.ContainsKey(wx.WeixinHao)) + { + var sb = new StringBuilder(); + sb.Append("重新获取开始->"); + if (dic[wx.WeixinHao] > 6) + { + dic[wx.WeixinHao] = 0; + } + rd = new Random(Guid.NewGuid().GetHashCode()); + + if (wxList.Count > 1) + { + dic[wx.WeixinHao]++; + while (true) + { + var indexTmp = rd.Next(wxList.Count); + if (index != indexTmp) + { + index = indexTmp; + sb.Append("重新获取成功A"); + break; + } + } + + if (dic[wx.WeixinHao] > 4) + { + dic.Remove(wx.WeixinHao); + } + } + else + { + sb.Append("重新获取成功B"); + index = rd.Next(wxList.Count); + } + + sb.Append("->结束"); + this.OnLog($"{sb}"); + wx = wxList[index]; + } + + var strb = new StringBuilder(); + var startTime = DateTime.Now; + var status = wx.CheckUrl(url); + var endTime = DateTime.Now; + + strb.AppendLine($"微信:{wx.User.Nick}({wx.User.Username})"); + strb.AppendLine($"开始:{startTime}"); + strb.AppendLine($"结束:{endTime}"); + strb.AppendLine(); + + var totalSeconds = (endTime - startTime).TotalSeconds; + + strb.AppendLine($"间隔:{totalSeconds}"); + strb.AppendLine($"{url} = {status}"); + + if (totalSeconds > 10) + { + if (!dic.ContainsKey(wx.WeixinHao)) + { + dic[wx.WeixinHao] = 0; + } + } + + this.OnLog($"{strb}"); + e.Send("", status ? 1 : 0); + } + else + throw new Exception("当前没有可用pc协议微信"); + } + } + catch (Exception ex) + { + e.Send(ex.Message, -1); + this.OnLog($"检测链接异常:{ex.Message} - {ex.StackTrace}"); + } + } + + public override void Stop() + { + SDK.WebRequestEvent -= SDK_WebRequestEvent; + } + + + } +} diff --git a/应用/WacheCheckUrl/Properties/AssemblyInfo.cs b/应用/WacheCheckUrl/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..3619e74 --- /dev/null +++ b/应用/WacheCheckUrl/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("WacheCheckUrl")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WacheCheckUrl")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("cdd49c07-90a3-4244-b3d7-d6a590d0e5c1")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/WacheCheckUrl/Properties/Resources.Designer.cs b/应用/WacheCheckUrl/Properties/Resources.Designer.cs new file mode 100644 index 0000000..8613b55 --- /dev/null +++ b/应用/WacheCheckUrl/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace WacheCheckUrl.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WacheCheckUrl.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 检测 { + get { + object obj = ResourceManager.GetObject("检测", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/WacheCheckUrl/Properties/Resources.resx b/应用/WacheCheckUrl/Properties/Resources.resx new file mode 100644 index 0000000..425d13b --- /dev/null +++ b/应用/WacheCheckUrl/Properties/Resources.resx @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="检测" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\检测.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/WacheCheckUrl/Resources/检测.png b/应用/WacheCheckUrl/Resources/检测.png new file mode 100644 index 0000000..bfacc57 Binary files /dev/null and b/应用/WacheCheckUrl/Resources/检测.png differ diff --git a/应用/WacheCheckUrl/WacheCheckUrl.csproj b/应用/WacheCheckUrl/WacheCheckUrl.csproj new file mode 100644 index 0000000..36b652a --- /dev/null +++ b/应用/WacheCheckUrl/WacheCheckUrl.csproj @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{CDD49C07-90A3-4244-B3D7-D6A590D0E5C1}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>WacheCheckUrl</RootNamespace> + <AssemblyName>WacheCheckUrl</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar"> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System"> + <Private>False</Private> + </Reference> + <Reference Include="System.Core"> + <Private>False</Private> + </Reference> + <Reference Include="System.Drawing"> + <Private>False</Private> + </Reference> + <Reference Include="System.Xml.Linq"> + <Private>False</Private> + </Reference> + <Reference Include="System.Data.DataSetExtensions"> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CSharp"> + <Private>False</Private> + </Reference> + <Reference Include="System.Data"> + <Private>False</Private> + </Reference> + <Reference Include="System.Net.Http"> + <Private>False</Private> + </Reference> + <Reference Include="System.Xml"> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\类库\Api.Framework\Api.Framework.csproj"> + <Project>{DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}</Project> + <Name>Api.Framework</Name> + <Private>False</Private> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\检测.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/WeChatCollectMoney/Class1.cs b/应用/WeChatCollectMoney/Class1.cs new file mode 100644 index 0000000..68256db --- /dev/null +++ b/应用/WeChatCollectMoney/Class1.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.SDK; +using WeChatCollectMoney.Properties; +using WeChatCollectMoney.Forms; +using Api.Framework; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Events; +using Api.Framework.Model; +using Chat.Framework.WXSdk.Implement; + +namespace WeChatCollectMoney +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.微信收款; + } + + #region 自定义变量 + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + if (!session.TableExist<fl_plugin_wechatcollectmoney_log>()) session.CreateTable<fl_plugin_wechatcollectmoney_log>(); + SDK.WXReicevePay += SDK_WXReicevePay; + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + SDK.WXNewMemerEvent += SDK_WXNewMemerEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + + if (e.Message == "邀请统计" && !string.IsNullOrEmpty(e.Groupid) && e.ChatType == ChatType.微信) + { + try + { + var client = e.Sender as WXClientImpl_IPAD; + var ms = client.GetMembers(e.Groupid); + if (ms == null) return; + var members = ms.Where(f => f.InviterUserName == e.Username).ToList(); + StringBuilder sb = new StringBuilder("一一邀 请 统 计一一\r\n"); + sb.Append("\r\n"); + if (members.Count != 0) + { + foreach (var item in members) + { + sb.Append(item.NickName); + sb.Append(","); + } + sb.Append("\r\n"); + sb.Append("【邀请人数】" + members.Count + " 人"); + } + else sb.Append("暂无记录!"); + + e.SendMessage(sb.ToString()); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + } + + private void SDK_WXNewMemerEvent(object sender, Chat.Framework.WXSdk.Events.WXNewMemer e) + { + refresh_members_relationship(e); + } + + /// <summary> + /// 刷新群成员关系 + /// </summary> + /// <param name="e"></param> + private void refresh_members_relationship(WXNewMemer e) + { + //刷新群成员 + e.Client.GetMembers(e.GroupId, true); + } + /// <summary> + /// 收到转账 + /// </summary> + private void SDK_WXReicevePay(object sender, Chat.Framework.WXSdk.Events.WXReicevePay e) + { + try + { + var money = e.Client.TenPayTransferConfirm(e.Invalidtime, e.Transferid, e.Friend.UserName); + if (money != -1) + { + var session = ApiClient.GetSession(); + var member = session.FindRow("select id from fl_member_info where username = @username and robot_type = @robotType and robot_name = @robotName", new { username = e.Friend.UserName, robotType = (int)ChatType.微信, robotName = e.Client.WeixinHao }); + var robot = session.FindRow("select id from fl_robot_info where name = @name and type = @robotType", new { name = e.Client.WeixinHao, robotType = (int)ChatType.微信 }); + if (member != null && robot != null) + { + session.Insertable(new fl_plugin_wechatcollectmoney_log() + { + invalidtime = DateTime.Now, + member_id = long.Parse(member["id"].ToString()), + money = (double)((decimal)money / 100), + robot_id = long.Parse(robot["id"].ToString()), + transferid = e.Transferid + }).ExecuteCommand(); + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/WeChatCollectMoney/Forms/MainForm.Designer.cs b/应用/WeChatCollectMoney/Forms/MainForm.Designer.cs new file mode 100644 index 0000000..99871c1 --- /dev/null +++ b/应用/WeChatCollectMoney/Forms/MainForm.Designer.cs @@ -0,0 +1,347 @@ +namespace WeChatCollectMoney.Forms +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(470, 27); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(62, 18); + this.checkBox1.TabIndex = 19; + this.checkBox1.Text = "时间:"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // dateTimePicker2 + // + this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker2.Location = new System.Drawing.Point(709, 25); + this.dateTimePicker2.Name = "dateTimePicker2"; + this.dateTimePicker2.Size = new System.Drawing.Size(161, 22); + this.dateTimePicker2.TabIndex = 18; + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(532, 25); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.Size = new System.Drawing.Size(161, 22); + this.dateTimePicker1.TabIndex = 14; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(143, 29); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 16; + this.labelControl1.Text = "内容:"; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(911, 23); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(76, 27); + this.simpleButton1.TabIndex = 15; + this.simpleButton1.Text = "搜索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click_1); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.EditValue = "全部数据"; + this.comboBoxEdit1.Location = new System.Drawing.Point(351, 26); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部数据", + "转账编号", + "客户编号", + "客户账号", + "客户昵称", + "机器人号", + "机器人昵称"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(100, 20); + this.comboBoxEdit1.TabIndex = 12; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // textEdit1 + // + this.textEdit1.Enabled = false; + this.textEdit1.Location = new System.Drawing.Point(179, 26); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(166, 20); + this.textEdit1.TabIndex = 10; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(0, 452); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(1143, 33); + this.pageControl1.TabIndex = 13; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(0, 67); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(1143, 379); + this.gridControl1.TabIndex = 20; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn11, + this.gridColumn8, + this.gridColumn7, + this.gridColumn6, + this.gridColumn4, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "ID"; + this.gridColumn10.FieldName = "id"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 0; + this.gridColumn10.Width = 45; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn11.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "机器人号"; + this.gridColumn11.FieldName = "name"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.OptionsColumn.AllowFocus = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 1; + this.gridColumn11.Width = 94; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn8.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "机器人昵称"; + this.gridColumn8.FieldName = "nick"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 2; + this.gridColumn8.Width = 145; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "用户编码"; + this.gridColumn7.FieldName = "member_id"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 3; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn6.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "用户账号"; + this.gridColumn6.FieldName = "username"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 4; + this.gridColumn6.Width = 152; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "用户昵称"; + this.gridColumn4.FieldName = "usernick"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 5; + this.gridColumn4.Width = 133; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "转账金额"; + this.gridColumn2.FieldName = "money"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 6; + this.gridColumn2.Width = 82; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "转账时间"; + this.gridColumn3.FieldName = "invalidtime"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 7; + this.gridColumn3.Width = 179; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "转账编码"; + this.gridColumn5.FieldName = "transferid"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 8; + this.gridColumn5.Width = 225; + // + // MainForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1143, 485); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.checkBox1); + this.Controls.Add(this.dateTimePicker2); + this.Controls.Add(this.dateTimePicker1); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.comboBoxEdit1); + this.Controls.Add(this.textEdit1); + this.Controls.Add(this.pageControl1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.DateTimePicker dateTimePicker2; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + } +} \ No newline at end of file diff --git a/应用/WeChatCollectMoney/Forms/MainForm.cs b/应用/WeChatCollectMoney/Forms/MainForm.cs new file mode 100644 index 0000000..5dd18c3 --- /dev/null +++ b/应用/WeChatCollectMoney/Forms/MainForm.cs @@ -0,0 +1,198 @@ +using Api.Framework; +using Api.Framework.Tools; +using System; +using UI.Framework.Forms; +using WeChatCollectMoney.Properties; + +namespace WeChatCollectMoney.Forms +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + dateTimePicker1.Enabled = dateTimePicker2.Enabled = false; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton1_Click_1(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void MainForm_Load(object sender, EventArgs e) + { + this.comboBoxEdit1.SelectedIndex = 0; + this.dateTimePicker1.Value = DateTime.Parse(DateTime.Today.AddDays(-30).ToString("yyyy-MM-01")); + this.dateTimePicker2.Value = DateTime.Parse(DateTime.Now.AddDays(30).ToString("yyyy-MM-dd HH:mm:ss")); + this.checkBox1.Checked = false; + this.pageControl1.Bind(delegate (int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var map = session.NewParamMap(); + if (this.checkBox1.Checked) + { + map.setParameter("start_time", this.dateTimePicker1.Value.ToString("yyyy-MM-dd HH:mm:ss")); + map.setParameter("end_time", this.dateTimePicker2.Value.ToString("yyyy-MM-dd HH:mm:ss")); + } + map.setPageParamters(index, pagesize); + map.setOrderFields("wc.invalidtime", true); + + string where = string.Empty; + if (!string.IsNullOrEmpty(this.textEdit1.Text)) + { + + switch (this.comboBoxEdit1.Text) + { + case "转账编号": + where = "wc.transferid = @transferid"; + map.setParameter("transferid", this.textEdit1.Text.Trim()); + break; + case "客户编号": + where = "m.id = @member_id"; + map.setParameter("member_id", this.textEdit1.Text.Trim()); + break; + case "客户账号": + where = "u.username like @username"; + map.setParameter("username", "%" + this.textEdit1.Text.Trim() + "%"); + break; + case "客户昵称": + where = "u.usernick like (@usernick)"; + map.setParameter("usernick", $"%{this.textEdit1.Text.Trim()}%"); + break; + case "机器人号": + where = "r.name = @name"; + map.setParameter("name", this.textEdit1.Text.Trim()); + break; + case "机器人昵称": + where = "r.nick = @nicke"; + map.setParameter("nicke", this.textEdit1.Text.Trim()); + break; + } + } + + Api.Framework.Tools.PageResult<wechatcollectmoney_temp> result = null; + if (map.ContainsKey("start_time")) + result = session.FindPage<wechatcollectmoney_temp>("select wc.money as money,wc.invalidtime as invalidtime,wc.transferid as transferid,wc.id as id,r.type as chattype,m.id as member_id,m.username as username,m.usernick as usernick,r.name as name,r.nick as nick from fl_plugin_wechatcollectmoney_log wc INNER JOIN fl_member_info m ON wc.member_id = m.id INNER JOIN fl_robot_info r on wc.robot_id = r.id where wc.invalidtime>=@start_time and wc.invalidtime<=@end_time " + (string.IsNullOrEmpty(where) ? string.Empty : " and " + where), map); + else + result = session.FindPage<wechatcollectmoney_temp>("select wc.money as money,wc.invalidtime as invalidtime,wc.transferid as transferid,wc.id as id,r.type as chattype,m.id as member_id,m.username as username,m.usernick as usernick,r.name as name,r.nick as nick from fl_plugin_wechatcollectmoney_log wc INNER JOIN fl_member_info m ON wc.member_id = m.id INNER JOIN fl_robot_info r on wc.robot_id = r.id " + (string.IsNullOrEmpty(where) ? string.Empty : " where " + where), map); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + return null; + }, this.gridControl1, 100, true, true); + + } + + public class wechatcollectmoney_temp + { + /// <summary> + /// id + /// </summary> + public long id { get; set; } + /// <summary> + /// 金额 + /// </summary> + public decimal money { get; set; } + /// <summary> + /// 转账时间 + /// </summary> + public DateTime invalidtime { get; set; } + /// <summary> + /// 用户id + /// </summary> + public long member_id { get; set; } + /// <summary> + /// 转账编码 + /// </summary> + public string transferid { get; set; } + /// <summary> + /// 机器人昵称 + /// </summary> + private string _nick { get; set; } + /// <summary> + /// 机器人昵称 + /// </summary> + public string nick + { + get { return _nick; } + set { if (string.IsNullOrEmpty(value)) _nick = string.Empty; else _nick = value; } + } + + /// <summary> + /// 机器人号 + /// </summary> + private string _name { get; set; } + /// <summary> + /// 机器人号 + /// </summary> + public string name + { + get { return _name; } + set { if (string.IsNullOrEmpty(value)) _name = string.Empty; else _name = value; } + } + + private string _username; + /// <summary> + /// 用户账号 + /// </summary> + public string username + { + get { return _username; } + set { if (string.IsNullOrEmpty(value)) _username = string.Empty; else _username = value; } + } + + private string _usernick; + /// <summary> + /// 用户昵称 + /// </summary> + public string usernick + { + get { return _usernick; } + set { if (string.IsNullOrEmpty(value)) _usernick = string.Empty; else _usernick = value; } + } + + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit1.SelectedIndex == 0) + { + this.textEdit1.Enabled = false; + this.textEdit1.Text = ""; + } + else this.textEdit1.Enabled = true; + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + dateTimePicker1.Enabled = dateTimePicker2.Enabled = checkBox1.Checked; + } + + } +} \ No newline at end of file diff --git a/应用/WeChatCollectMoney/Forms/MainForm.resx b/应用/WeChatCollectMoney/Forms/MainForm.resx new file mode 100644 index 0000000..bc5d4fb --- /dev/null +++ b/应用/WeChatCollectMoney/Forms/MainForm.resx @@ -0,0 +1,145 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> +</root> \ No newline at end of file diff --git a/应用/WeChatCollectMoney/Properties/AssemblyInfo.cs b/应用/WeChatCollectMoney/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a6e4edc --- /dev/null +++ b/应用/WeChatCollectMoney/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("WeChatCollectMoney")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WeChatCollectMoney")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("1e721fbd-b9a3-4d52-92aa-428a8acd726a")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/WeChatCollectMoney/Properties/Resources.Designer.cs b/应用/WeChatCollectMoney/Properties/Resources.Designer.cs new file mode 100644 index 0000000..77e093e --- /dev/null +++ b/应用/WeChatCollectMoney/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace WeChatCollectMoney.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WeChatCollectMoney.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 微信收款 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 微信收款 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 微信收款 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 微信收款 { + get { + object obj = ResourceManager.GetObject("微信收款", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/WeChatCollectMoney/Properties/Resources.resx b/应用/WeChatCollectMoney/Properties/Resources.resx new file mode 100644 index 0000000..3fe77ce --- /dev/null +++ b/应用/WeChatCollectMoney/Properties/Resources.resx @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="MainFormTitle" xml:space="preserve"> + <value>微信收款</value> + </data> + <data name="PluginName" xml:space="preserve"> + <value>微信收款</value> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>微信收款</value> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="微信收款" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\微信收款.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/WeChatCollectMoney/Properties/licenses.licx b/应用/WeChatCollectMoney/Properties/licenses.licx new file mode 100644 index 0000000..e69de29 diff --git a/应用/WeChatCollectMoney/Resources/微信收款.png b/应用/WeChatCollectMoney/Resources/微信收款.png new file mode 100644 index 0000000..74bdeae Binary files /dev/null and b/应用/WeChatCollectMoney/Resources/微信收款.png differ diff --git a/应用/WeChatCollectMoney/WeChatCollectMoney.csproj b/应用/WeChatCollectMoney/WeChatCollectMoney.csproj new file mode 100644 index 0000000..e7e0eec --- /dev/null +++ b/应用/WeChatCollectMoney/WeChatCollectMoney.csproj @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{1E721FBD-B9A3-4D52-92AA-428A8ACD726A}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>WeChatCollectMoney</RootNamespace> + <AssemblyName>WeChatCollectMoney</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="fl_plugin_wechatcollectmoney_log.cs" /> + <Compile Include="Forms\MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Forms\MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Forms\MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\微信收款.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/WeChatCollectMoney/fl_plugin_wechatcollectmoney_log.cs b/应用/WeChatCollectMoney/fl_plugin_wechatcollectmoney_log.cs new file mode 100644 index 0000000..b598715 --- /dev/null +++ b/应用/WeChatCollectMoney/fl_plugin_wechatcollectmoney_log.cs @@ -0,0 +1,34 @@ + +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WeChatCollectMoney +{ + public class fl_plugin_wechatcollectmoney_log : base_model + { + /// <summary> + /// 转款用户 + /// </summary> + public long member_id { get; set; } + /// <summary> + /// 收钱机器人 + /// </summary> + public long robot_id { get; set; } + /// <summary> + /// 转账金额 + /// </summary> + public double money { get; set; } + /// <summary> + /// 收款时间 + /// </summary> + public DateTime invalidtime { get; set; } + /// <summary> + /// 订单id + /// </summary> + public string transferid { get; set; } + } +} diff --git a/应用/WebAPi/Class1.cs b/应用/WebAPi/Class1.cs new file mode 100644 index 0000000..e6e229b --- /dev/null +++ b/应用/WebAPi/Class1.cs @@ -0,0 +1,85 @@ +using Api.Framework; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WebAPi.Pack; +using WebAPi.Properties; + +namespace WebAPi +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.WebApi; + } + + #region 自定义变量 + //public static Config Config; + #endregion + + public override void Start() + { + try + { + SDK.WebRequestEvent += SDK_WebRequestEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_WebRequestEvent(object sender, WebRequestEvents e) + { + try + { + #region + if (e.Param.ContainsKey("method"))//方法名称 + { + var method = e.Param["method"].ToLower(); + switch (method) + { + case "cvr"://转化率数据 + { + var resultJson = string.Empty; + try + { + if (!e.Param.ContainsKey("state_time")) throw new Exception("缺少参数state_time"); + if (!e.Param.ContainsKey("end_time")) throw new Exception("缺少参数end_time"); + DateTime stateTime; + if (!DateTime.TryParse(e.Param["state_time"].ToLower(), out stateTime)) throw new Exception($"state_time格式不正确"); + DateTime endTime; + if (!DateTime.TryParse(e.Param["end_time"].ToLower(), out endTime)) throw new Exception($"end_time格式不正确"); + + endTime = endTime.AddDays(1); + Qyery q = new Qyery(); + resultJson = q.FindCVR(stateTime, endTime).Result; + } + catch (Exception ex) + { + resultJson = Common.ErrorJson(ex.Message); + } + e.Send(resultJson, 200); + } + break; + } + } + #endregion + + } + catch (Exception ex) + { + + } + } + } +} diff --git a/应用/WebAPi/Pack/Common.cs b/应用/WebAPi/Pack/Common.cs new file mode 100644 index 0000000..bb48a5c --- /dev/null +++ b/应用/WebAPi/Pack/Common.cs @@ -0,0 +1,32 @@ +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WebAPi.Pack +{ + + public class BaseMsg + { + public int Code { get; set; } + + public string Msg { get; set; } + + } + + public class DataJson + { + public string Data { get; set; } + } + + public class Common + { + public static string ErrorJson(string msg, int code = -1) + { + return HttpHelper.ObjectToJson(new DataJson() { Data = HttpHelper.ObjectToJson(new BaseMsg() { Code = code, Msg = msg }) }); + } + } + +} diff --git a/应用/WebAPi/Pack/Entitys/Cvr.cs b/应用/WebAPi/Pack/Entitys/Cvr.cs new file mode 100644 index 0000000..3722dfd --- /dev/null +++ b/应用/WebAPi/Pack/Entitys/Cvr.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WebAPi.Pack.Entitys +{ + /// <summary> + /// 转化率 + /// </summary> + public class Cvr + { + public string robotname { get; set; } + + public string robtonick { get; set; } + + + + } +} diff --git a/应用/WebAPi/Properties/AssemblyInfo.cs b/应用/WebAPi/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a4871f7 --- /dev/null +++ b/应用/WebAPi/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("WebAPi")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WebAPi")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("edc2ac83-d4e3-4aff-9690-9f631f224d21")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/WebAPi/Properties/Resources.Designer.cs b/应用/WebAPi/Properties/Resources.Designer.cs new file mode 100644 index 0000000..dcc1b2b --- /dev/null +++ b/应用/WebAPi/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace WebAPi.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WebAPi.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 WebApi 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 WebApi 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 WebApi插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap WebApi { + get { + object obj = ResourceManager.GetObject("WebApi", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/WebAPi/Properties/Resources.resx b/应用/WebAPi/Properties/Resources.resx new file mode 100644 index 0000000..3101333 --- /dev/null +++ b/应用/WebAPi/Properties/Resources.resx @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="MainFormTitle" xml:space="preserve"> + <value>WebApi</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>WebApi</value> + <comment>插件名</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>WebApi插件</value> + <comment>插件介绍</comment> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="WebApi" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\WebApi.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/WebAPi/Qyery.cs b/应用/WebAPi/Qyery.cs new file mode 100644 index 0000000..a1c2747 --- /dev/null +++ b/应用/WebAPi/Qyery.cs @@ -0,0 +1,284 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WebAPi +{ + public class Qyery + { + private static string[] not_Friends = new string[] { "fmessage", "floatbottle", "qmessage", "medianote", "qqmail", "weixin" }; + + /// <summary> + /// 获取转换率等信息(返回Json) + /// </summary> + /// <param name="stateTime">获取的开始时间</param> + /// <param name="endTime">获取的截止时间</param> + /// <returns>返回Json</returns> + public async Task<string> FindCVR(DateTime _stateTime, DateTime _endTime) + { + + var begin_time = _stateTime; + var end_time = _endTime; + if (begin_time >= end_time) throw new Exception("begin_time时间不能大于end_time时间"); + + + return await Task.Run(() => + { + try + { + var _session = ApiClient.GetSession(); + List<object> resultList = new List<object>(); + object lock_result = new object(); + //List<Action> actions = new List<Action>(); + var robots = new List<fl_robot_info>(_session.FindRobots()); + + //总提现 + var pointHists = _session.Find<fl_point_hist>("@begin_time <= crt_time and crt_time < @end_time and type = @type ", new { begin_time = begin_time, end_time = end_time, type = "提现扣除" }); + //绑定用户的订单 + var orderAlimamas = _session.Find<OrderTemp>("select db_userid,db_status,db_robotname,db_robottype,pub_share_pre_fee as fee,db_point,item_num as num from fl_order_alimama where @begin_time <= create_time and create_time < @end_time and db_userid != 0 and db_status in (1005,1002,1001,998)", new { begin_time = begin_time, end_time = end_time }); + //绑定用户的订单 + var orderJingdongs = _session.Find<OrderTemp>("select db_userid,db_status,db_robotname,db_robottype,estimateFee as fee,db_point,skuNum as num from fl_order_jingdong where @begin_time <= orderTime and orderTime < @end_time and db_userid != 0 and db_status in (1005,1002,1001,998)", new { begin_time = begin_time, end_time = end_time }); + //绑定用户的订单 + var orderPinduoduos = _session.Find<OrderTemp>("select db_userid,db_status,db_robotname,db_robottype,promotion_amount as fee,db_point,goods_quantity as num from fl_order_pinduoduo where @begin_time <= order_create_time and order_create_time < @end_time and db_userid != 0 and db_status in (1005,1002,1001,998)", new { begin_time = begin_time, end_time = end_time }); + + //时间段创建的用户集合 + var newMemberInfos = _session.Find<fl_member_info>("@begin_time <= crt_time and crt_time < @end_time", new { begin_time = begin_time, end_time = end_time }); + + //最近沟通的用户集合 + var activeMemberInfos = _session.Find<fl_member_info>("@begin_time <= upd_time and upd_time < @end_time", new { begin_time = begin_time, end_time = end_time }); + + var statisticsRecords = _session.Find<fl_statistics_record>("select * from fl_statistics_record"); + + foreach (var _item in robots) + { + var item = _item; + //actions.Add(new Action(delegate + //{ + try + { + var session = ApiClient.GetSession(); + + #region 合计总佣金 第一个阿里妈妈。第二个京东。第三个拼多多 + var tb_income = (decimal)orderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//淘宝总佣金 + var jd_income = (decimal)orderJingdongs.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//京东总佣金 + var pdd_income = (decimal)orderPinduoduos.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.fee);//京东总佣金 + #endregion + + //付款总金额 + decimal totalIncome = tb_income + jd_income + pdd_income; + + #region 毛利合计 第一个阿里妈妈。第二个京东。第三个拼多多 + var tb_point = orderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//淘宝分出佣金 + var jd_point = orderJingdongs.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//京东分出佣金 + var pdd_point = orderPinduoduos.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Select(f => f.db_point).ToList();//拼多多分出佣金 + + List<string> temps = new List<string>(); + temps.AddRange(tb_point); + temps.AddRange(jd_point); + temps.AddRange(pdd_point); + + decimal amount_ceded = 0m;//给客户的部分(约等于) + for (int i = 0; i < temps.Count; i++) + { + var point = HttpHelper.JsonToObject<ItemPoint>(temps[i]) as ItemPoint; + if (point != null) + { + amount_ceded += ((decimal)point.UserPoint + (decimal)point.AwardOne + (decimal)point.AwardTwo + (decimal)point.AwardThree + (decimal)point.AwardCreate); + } + } + #endregion + + //毛利(约等于) + decimal totalMargin = totalIncome - amount_ceded; + + #region 订单数量合计 第一个阿里妈妈。第二个京东。第三个拼多多 + int tb_order_count = orderAlimamas.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//淘宝总订单数 + int jd_order_count = (int)orderJingdongs.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//京东总订单数 + int pdd_order_count = orderPinduoduos.Where(f => f.db_robotname == item.name && f.db_robottype == item.type).Sum(f => f.num);//拼多多总订单数 + #endregion + + //总订单数 + var orderCount = tb_order_count + jd_order_count + pdd_order_count; + + //提现金额 + var exchangeMoney = (decimal)(pointHists.Where(f => f.rid == item.id).Sum(f => f.point) * -1); + + //var gross_margin = (totalIncome == 0 ? "0%" : Math.Round(totalMargin / totalIncome * 100m, 4).ToString() + "%");//毛利率 + + //统计新人人数 + var newMembers = newMemberInfos.Count(f => f.robot_name == item.name); + + #region 新人 + + //已经下单的人,就不验证是否查询过 + var bindNewMembers = newMemberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order != 0).Count(); + + var verifyMembers = newMemberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order == 0).ToList(); + var bindNewMembers2 = 0; + for (int i = 0; i < verifyMembers.Count; i++) + { + var temp = statisticsRecords.FirstOrDefault(f => f.uid == verifyMembers[i].id); + if (null != temp) + { + if (temp.querynum != 0) + bindNewMembers2++; + } + } + var activeNewMembers = bindNewMembers2 + bindNewMembers; + //新人转化率 + var newMemberCvr = activeNewMembers == 0 ? 0 : Decimal.Round((bindNewMembers / activeNewMembers), 2); + + //当天新人首单数量 + //var pay_order_count = memberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && f.bind_order != 0).Count(); + #endregion + + #region 新老用户 + //互动人数 + var activeMembers = activeMemberInfos.Count(f => f.robot_name == item.name); + + //单粉产出 + var eachValue = activeMemberInfos.Count == 0 ? 0 : Decimal.Round((totalMargin / activeMemberInfos.Count), 2); + + //新用户下单的人数 + var _bindNewMembers = activeMemberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && begin_time <= f.crt_time && f.crt_time < end_time && f.bind_order != 0).Count(); + + #region 老用户 + //验证的人数.检查是否下单 + var _verifyMembers1 = activeMemberInfos.Where(f => f.robot_name == item.name && f.robot_type == item.type && begin_time > f.crt_time && f.crt_time >= end_time).ToList(); + int bindMembers = 0;//下单人数 + foreach (var member in _verifyMembers1) + { + var count = 0; + count += orderAlimamas.Count(f => f.db_userid == member.id); + if (count == 0) + { + count += orderJingdongs.Count(f => f.db_userid == member.id); ; + if (count == 0) + count += orderPinduoduos.Count(f => f.db_userid == member.id); ; + } + if (count != 0) + bindMembers++; + } + + #endregion + + //互动下单人数 + var activeBindMembers = bindMembers + _bindNewMembers; + + var activeMemberCvr = activeMemberInfos.Count == 0 ? 0 : Decimal.Round((activeBindMembers / activeMemberInfos.Count), 2); + + #endregion + + int totalFriend = 0; + if (Chat.Framework.ChatClient.WXClient.ContainsKey(_item.name)) + { + var wxBase = Chat.Framework.ChatClient.WXClient.FirstOrDefault(f => f.Key == item.name).Value; + if (wxBase == null) totalFriend = 0; + else + { + if (wxBase.GetType() == typeof(WXClientImpl_HOOK)) + { + var wx = wxBase as WXClientImpl_HOOK; + if (wx != null) + totalFriend = wx.Friends.Values.ToList().Where(f => !f.Alias.Contains("@") && f.MsgType == 0 && !not_Friends.ToList().Contains(f.Alias)).ToList().Count; + } + else if (wxBase.GetType() == typeof(WXClientImpl_IPAD)) + { + var wx = wxBase as WXClientImpl_IPAD; + if (wx != null) + totalFriend = wx.Friends.Values.ToList().Where(f => !f.Alias.Contains("@") && f.MsgType == 0 && !not_Friends.ToList().Contains(f.Alias)).ToList().Count; + } + } + } + + lock (lock_result) resultList.Add(new + { + robotName = item.name, + robotNick = item.nick, + robotType = item.type.ToString(), + newMembers = newMembers, + bindNewMembers = bindNewMembers, + newMemberCvr = newMemberCvr, + activeMembers = activeMembers, + activeBindMembers = activeBindMembers, + activeMemberCvr = activeMemberCvr, + eachValue = eachValue, + orderCount = orderCount, + totalFriend = totalFriend, + exchangeMoney = exchangeMoney, + totalIncome = totalIncome, + totalMargin = totalMargin + }); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"{item.name} - {ex.Message} - {ex.StackTrace}"); + } + //})); + } + + //Parallel.ForEach(actions, action => + //{ + // action.Invoke(); + //}); + //Task.WaitAll(actions.ToArray()); + return Task.FromResult(HttpHelper.ObjectToJson(resultList)); + } + catch (Exception ex) + { } + return Task.FromResult<string>(string.Empty); + }); + } + + + #region + private class OrderTemp + { + /// <summary> + /// 绑定的用户 + /// </summary> + public int db_userid { get; set; } + + /// <summary> + /// 订单状态 + /// </summary> + public SystemOrderStatus db_status { get; set; } + + /// <summary> + /// 机器人名称 + /// </summary> + public string db_robotname { get; set; } + + /// <summary> + /// 机器人类型 + /// </summary> + public ChatType db_robottype { get; set; } + + /// <summary> + /// 总佣金 + /// </summary> + public double fee { get; set; } + + /// <summary> + /// 积分json + /// </summary> + public string db_point { get; set; } + + /// <summary> + /// 购买数量 + /// </summary> + public int num { get; set; } + } + #endregion + + } +} diff --git a/应用/WebAPi/Resources/WebApi.jpg b/应用/WebAPi/Resources/WebApi.jpg new file mode 100644 index 0000000..60a60b1 Binary files /dev/null and b/应用/WebAPi/Resources/WebApi.jpg differ diff --git a/应用/WebAPi/WebAPi.csproj b/应用/WebAPi/WebAPi.csproj new file mode 100644 index 0000000..d3344b9 --- /dev/null +++ b/应用/WebAPi/WebAPi.csproj @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{EDC2AC83-D4E3-4AFF-9690-9F631F224D21}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>WebAPi</RootNamespace> + <AssemblyName>WebAPi</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Pack\Common.cs" /> + <Compile Include="Pack\Entitys\Cvr.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="Qyery.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\WebApi.jpg" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/WebTools/Class1.cs b/应用/WebTools/Class1.cs new file mode 100644 index 0000000..6ed4a44 --- /dev/null +++ b/应用/WebTools/Class1.cs @@ -0,0 +1,339 @@ +using Api.Framework; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Chat.Framework; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; +using WebTools.Properties; +using Plugin = Api.Framework.SDK.Plugin; + +namespace WebTools +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.web工具; + } + + #region 自定义变量 + public static Config Config; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + + //创建配置文件 + Config = this.ReadConfig<Config>(); + SDK.WebRequestEvent += SDK_WebRequestEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + //Clipboard.SetDataObject("https://docs.qq.com/doc/DWkNod0luR29acExG"); + Clipboard.SetDataObject("https://docs.qq.com/doc/DWlRVYWxTY1dHc01B"); + BaseForm.ShowSuccessAutoClose("已经复制使用说明地址,请到本机浏览器粘贴查看!"); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + /// <summary> + /// 字符串转换成平台类型(ChatType) + /// </summary> + /// <param name="chattype"></param> + /// <returns></returns> + private ChatType ConvertChatType(string chattype) + { + //wechat|QQ|wempchat + //微信,QQ,微信公众号 + chattype = chattype.Trim().ToLower(); + if ("wechat" == chattype) + return ChatType.微信; + //if ("workwechat" == chattype) + // return ChatType.企业微信; + else if ("qq" == chattype) + return ChatType.QQ; + //else if ("wempchat" == chattype) + // return ChatType.微信公众号; + new Exception("账号类型不存在.类型包含(wechat)"); + return ChatType.未知来源; + } + + private void SDK_WebRequestEvent(object sender, WebRequestEvents e) + { + try + { + #region + if (e.Param.ContainsKey("method"))//方法名称 + { + var method = e.Param["method"].ToLower(); + switch (method) + { + case "getrobots"://获取机器人状态 + { + var session = ApiClient.GetSession(); + var robots = session.FindRobots(true); + var wxBases = ChatClient.WXClient.Values.Where(f => f.Status == WxStatus.在线); + //var qqBases = Chat.Framework.ChatClient.QQPool.QQClients.Values; + List<Object> _robots = new List<object>(); + foreach (var robot in robots) + { + if (robot.type == ChatType.微信 || robot.type == ChatType.企业微信) + { + var _robot = wxBases.FirstOrDefault(f => f.WeixinHao == robot.name); + _robots.Add(new { name = robot.name, nick = robot.nick, type = robot.type.ToString(), status = _robot == null ? "未登录" : _robot.Status.ToString() }); + } + } + e.Send(CsharpHttpHelper.HttpHelper.ObjectToJson(_robots), 200); + } + break; + case "getgroupinfo"://获取群信息 + { + try + { + if (!e.Param.ContainsKey("robotname") || string.IsNullOrWhiteSpace(e.Param["robotname"])) throw new Exception("缺少参数robotname或者参数robotname值为空"); + //if (!e.Param.ContainsKey("chattype") || string.IsNullOrWhiteSpace(e.Param["chattype"])) throw new Exception("缺少参数chattype或者参数chattype值为空.类型包含(wechat)"); + if (!e.Param.ContainsKey("groupid") || string.IsNullOrWhiteSpace(e.Param["groupid"])) throw new Exception("缺少参数groupid或者参数groupid值为空"); + //var type = e.Param["chattype"]; //机器人类型 + + var chatType = ChatType.微信;//ConvertChatType(type); + var robotname = e.Param["robotname"]; //机器人账号 + var groupid = e.Param["groupid"]; //群id + var session = ApiClient.GetSession(); + + switch (chatType) + { + case ChatType.微信: + { + var wxBase = Chat.Framework.ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 && f.WeixinHao.Trim() == robotname.Trim() && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + if (wxBase == null) throw new Exception($"{robotname}机器人不存在或为离线状态"); + var groupinfo = wxBase.GetContact(groupid, true); + if (groupinfo == null || string.IsNullOrWhiteSpace(groupinfo.ExtInfo)) throw new Exception($"没有获取到{robotname}机器人{groupid}群信息"); + + var result = new { groupname = groupinfo.NickName, groupid = groupinfo.UserName, creator = groupinfo.ChatRoomOwner, membercount = groupinfo.ExtInfo.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Length, memberlist = groupinfo.ExtInfo }; + + e.Send(result, 200); + } + break; + case ChatType.微信公众号: + { + throw new Exception("开发中..."); + } + case ChatType.未知来源: + default: + throw new Exception("未知错误"); + //break; + } + } + catch (Exception ex) + { + e.Send(ex.Message); + } + } + break; + case "sendmsg"://发送消息 + { + try + { + if (!e.Param.ContainsKey("robotname") || string.IsNullOrWhiteSpace(e.Param["robotname"])) throw new Exception("缺少参数robotname或者参数robotname值为空"); + //if (!e.Param.ContainsKey("chattype") || string.IsNullOrWhiteSpace(e.Param["chattype"])) throw new Exception("缺少参数chattype或者参数chattype值为空.类型包含(wechat)"); + if (!e.Param.ContainsKey("touser") || string.IsNullOrWhiteSpace(e.Param["touser"])) throw new Exception("缺少参数touser或者参数touser值为空"); + //if (!e.Param.ContainsKey("msgtype") || string.IsNullOrWhiteSpace(e.Param["msgtype"])) throw new Exception("缺少参数msgtype或者参数msgtype值为空.类型包含(q|s)"); + if (!e.Param.ContainsKey("msg") || string.IsNullOrWhiteSpace(e.Param["msg"])) throw new Exception("缺少参数msg或者参数msg值为空"); + + //var type = e.Param["chattype"]; //机器人类型 + + var chatType = ChatType.微信;// ConvertChatType(type); + //var msgtype = e.Param["msgtype"]; + //if (msgtype != "q" && msgtype != "s") throw new Exception("msgtype值有误.类型包含(q|s)"); + + var robotname = e.Param["robotname"]; //机器人账号 + var touser = e.Param["touser"]; //发送给谁 + var msg = e.Param["msg"]; //发送内容 + + var session = ApiClient.GetSession(); + switch (chatType) + { + case ChatType.微信: + { + var wxBase = ChatClient.WXClient.Values.FirstOrDefault(f => /*f.WeixinType == WeixinType.Grpc微信 &&*/ f.WeixinHao.Trim() == robotname.Trim() && f.Status == WxStatus.在线); + if (wxBase == null) throw new Exception($"{robotname}机器人不存在或为离线状态"); + wxBase.SendMessage(touser, msg); + e.Send("执行成功", 200); + } + break; + case ChatType.微信公众号: + throw new Exception("开发中..."); + case ChatType.未知来源: + default: + throw new Exception("未知错误"); + } + } + catch (Exception ex) + { + e.Send(ex.Message); + } + } + break; + case "groupinvitemember"://邀请入群 + { + try + { + if (!e.Param.ContainsKey("robotname") || string.IsNullOrWhiteSpace(e.Param["robotname"])) throw new Exception("缺少参数robotname或者参数robotname值为空"); + //if (!e.Param.ContainsKey("chattype") || string.IsNullOrWhiteSpace(e.Param["chattype"])) throw new Exception("缺少参数chattype或者参数chattype值为空.类型包含(wechat|workwechat)"); + if (!e.Param.ContainsKey("username") || string.IsNullOrWhiteSpace(e.Param["username"])) throw new Exception("缺少参数username或者参数username值为空"); + if (!e.Param.ContainsKey("groupid") || string.IsNullOrWhiteSpace(e.Param["groupid"])) throw new Exception("缺少参数groupid或者参数groupid值为空"); + + //var type = e.Param["chattype"]; //机器人类型 + + var chatType = ChatType.微信;//ConvertChatType(type); + var robotname = e.Param["robotname"]; //机器人账号 + var username = e.Param["username"]; //入群用户账号 + var groupid = e.Param["groupid"]; //群id + + var session = ApiClient.GetSession(); + switch (chatType) + { + case ChatType.微信: + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == robotname).Value; + if (wx != null && wx.Status == WxStatus.在线) + { + var ipad = wx; + var result = ipad.InviteIntoGroup(username, groupid); + e.Send($"执行成功", 200); + } + else throw new Exception($"{robotname}机器人不存在或为离线状态"); + } + break; + case ChatType.微信公众号: + throw new Exception("开发中..."); + //break; + case ChatType.未知来源: + default: + throw new Exception("未知错误"); + //break; + } + } + catch (Exception ex) + { + e.Send(ex.Message); + } + } + break; + case "groupexit"://退出群 + { + try + { + if (!e.Param.ContainsKey("robotname") || string.IsNullOrWhiteSpace(e.Param["robotname"])) throw new Exception("缺少参数robotname或者参数robotname值为空"); + //if (!e.Param.ContainsKey("chattype") || string.IsNullOrWhiteSpace(e.Param["chattype"])) throw new Exception("缺少参数chattype或者参数chattype值为空.类型包含(wechat|workwechat)"); + if (!e.Param.ContainsKey("groupid") || string.IsNullOrWhiteSpace(e.Param["groupid"])) throw new Exception("缺少参数groupid或者参数groupid值为空"); + + //var type = e.Param["chattype"]; //机器人类型 + var chatType = ChatType.微信;//ConvertChatType(type); + var robotname = e.Param["robotname"]; //机器人账号 + var groupid = e.Param["groupid"]; //群id + + var session = ApiClient.GetSession(); + switch (chatType) + { + case ChatType.微信: + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == robotname).Value; + if (wx != null && wx.WeixinType == WeixinType.Grpc微信 && wx.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + var ipad = wx as WXClientImpl_IPAD; + e.Send($"执行成功", 200); + } + else throw new Exception($"{robotname}机器人不存在或为离线状态"); + } + break; + case ChatType.微信公众号: + throw new Exception("开发中..."); + case ChatType.未知来源: + default: + throw new Exception("未知错误"); + } + } + catch (Exception ex) + { + e.Send(ex.Message); + } + } + break; + case "refreshcontact"://更新联系人 + { + try + { + if (!e.Param.ContainsKey("robotname") || string.IsNullOrWhiteSpace(e.Param["robotname"])) throw new Exception("缺少参数robotname或者参数robotname值为空"); + //if (!e.Param.ContainsKey("chattype") || string.IsNullOrWhiteSpace(e.Param["chattype"])) throw new Exception("缺少参数chattype或者参数chattype值为空.类型包含(wechat|workwechat)"); + + //var type = e.Param["chattype"]; //机器人类型 + + var chatType = ChatType.微信;//ConvertChatType(type); + var robotname = e.Param["robotname"]; //机器人账号 + + var session = ApiClient.GetSession(); + switch (chatType) + { + case ChatType.微信: + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == robotname).Value; + if (wx != null && wx.WeixinType == WeixinType.Grpc微信 && wx.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + var ipad = wx as WXClientImpl_IPAD; + ipad.Initialization(); + ipad.RefreshContact(); + e.Send($"执行成功", 200); + } + else throw new Exception($"{robotname}机器人不存在或为离线状态"); + } + break; + case ChatType.微信公众号: + throw new Exception("开发中..."); + case ChatType.未知来源: + default: + throw new Exception("未知错误"); + } + } + catch (Exception ex) + { + e.Send(ex.Message); + } + } + break; + default: + break; + } + } + #endregion + + } + catch (Exception ex) + { + + } + } + } +} diff --git a/应用/WebTools/Config.cs b/应用/WebTools/Config.cs new file mode 100644 index 0000000..8203df4 --- /dev/null +++ b/应用/WebTools/Config.cs @@ -0,0 +1,21 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WebTools +{ + [Config(Name = "插件-Web工具-配置")] + public class Config + { + + public Config() + { + + } + + } +} \ No newline at end of file diff --git a/应用/WebTools/Properties/AssemblyInfo.cs b/应用/WebTools/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..13d5b4f --- /dev/null +++ b/应用/WebTools/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("WebTools")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WebTools")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("823e5afa-4a55-4338-8ce5-7fbafac103d0")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/WebTools/Properties/Resources.Designer.cs b/应用/WebTools/Properties/Resources.Designer.cs new file mode 100644 index 0000000..922887e --- /dev/null +++ b/应用/WebTools/Properties/Resources.Designer.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace WebTools.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WebTools.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 Web工具 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 Web工具 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 Web工具 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap web工具 { + get { + object obj = ResourceManager.GetObject("web工具", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/WebTools/Properties/Resources.resx b/应用/WebTools/Properties/Resources.resx new file mode 100644 index 0000000..adb2eaa --- /dev/null +++ b/应用/WebTools/Properties/Resources.resx @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="MainFormTitle" xml:space="preserve"> + <value>Web工具</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>Web工具</value> + <comment>插件名</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>Web工具</value> + <comment>插件介绍</comment> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="web工具" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\web工具.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/WebTools/Resources/web工具.png b/应用/WebTools/Resources/web工具.png new file mode 100644 index 0000000..5aace22 Binary files /dev/null and b/应用/WebTools/Resources/web工具.png differ diff --git a/应用/WebTools/WebTools.csproj b/应用/WebTools/WebTools.csproj new file mode 100644 index 0000000..9175a01 --- /dev/null +++ b/应用/WebTools/WebTools.csproj @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{823E5AFA-4A55-4338-8CE5-7FBAFAC103D0}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>WebTools</RootNamespace> + <AssemblyName>WebTools</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="WeiQ.Framework"> + <HintPath>..\..\Debug\WeiQ.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\web工具.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/Weixin.AccurateCircle/Class1.cs b/应用/Weixin.AccurateCircle/Class1.cs new file mode 100644 index 0000000..6fe6fd1 --- /dev/null +++ b/应用/Weixin.AccurateCircle/Class1.cs @@ -0,0 +1,84 @@ +using Api.Framework; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.AccurateCircle.Entitys; +using Weixin.AccurateCircle.Properties; + +namespace Weixin.AccurateCircle +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.精准朋友圈; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<fl_plugin_accuratecircle_dataInfos>()) session.CreateTable<fl_plugin_accuratecircle_dataInfos>(); + #endregion + + //创建配置文件 + Config = this.ReadConfig<Config>(); + + TimerTask.NewTimer<MonitorThread>(60); //创建线程 - 10秒 + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close<MonitorThread>(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/Weixin.AccurateCircle/Config.cs b/应用/Weixin.AccurateCircle/Config.cs new file mode 100644 index 0000000..71258c2 --- /dev/null +++ b/应用/Weixin.AccurateCircle/Config.cs @@ -0,0 +1,127 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.AccurateCircle +{ + [Config(Name = "插件-精准朋友圈-配置")] + public class Config + { + + #region 发单功能 + + #region 采集 + /// <summary> + /// 采集开关 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("01.采集开关"), DefaultValue(SwitchType.开启) + ] + public SwitchType Switch { get; set; } + + private int _downInterval; + /// <summary> + /// 采集间隔 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("02.采集间隔"), DefaultValue(5), + Description(@"定时采集间隔时间(单位/分)") + ] + public int DownInterval + { + get { return _downInterval; } + set + { + try + { + if (value < 5) throw new Exception(""); + else _downInterval = value; + } + catch (Exception) + { + _downInterval = 5; + throw new Exception($"采集间隔不能小于5分钟"); + } + _downInterval = value; + } + } + + /// <summary> + /// 采集开关 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("03.采集地址"), DefaultValue("") + ] + public string DownUrl { get; set; } + #endregion + + /// <summary> + /// 记录采集的任务ID + /// </summary> + [Browsable(false)] + public long DownID { get; set; } + + /// <summary> + /// 记录上一次的时间 + /// </summary> + [Browsable(false)] + public DateTime DownTime { get; set; } + + /// <summary> + /// 自动清理 + /// </summary> + [ + Category("2)、定时清理"), DisplayName("01.定时清理"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将在设置的时间进行采集数据的清空操作") + ] + public SwitchType Auto_IsClear { get; set; } + + private string _autoClearTaskTimes; + /// <summary> + /// 定时清理 + /// </summary> + [ + Category("2)、定时清理"), DisplayName("02.定时清理时间"), + Description(@"定时清理时间 +格式:HH:mm +例:23:59 +注:时间为24小时制") + ] + public string AutoClearTaskTimes //{ get; set; } + { + get { return _autoClearTaskTimes; } + set + { + try + { + var time = value as string; + var _time = DateTime.Parse(time); + } + catch (Exception) + { + throw new Exception($"时间格式不正确"); + } + _autoClearTaskTimes = value; + } + } + #endregion + + public Config() + { + this.Auto_IsClear = SwitchType.开启; + this.Switch = SwitchType.开启; + this._downInterval = 5; + this._autoClearTaskTimes = "23:59"; + this.DownTime = DateTime.MinValue; + this.DownID = 0; + this.DownUrl = string.Empty; + } + + } +} + diff --git a/应用/Weixin.AccurateCircle/Entitys/BaseInfo.cs b/应用/Weixin.AccurateCircle/Entitys/BaseInfo.cs new file mode 100644 index 0000000..981e831 --- /dev/null +++ b/应用/Weixin.AccurateCircle/Entitys/BaseInfo.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.AccurateCircle.Entitys +{ + public class BaseInfo + { + /// <summary> + /// 联盟类型 + /// </summary> + public string Cps { get; set; } + /// <summary> + /// 宝贝ID + /// </summary> + public string ItemId { get; set; } + /// <summary> + /// 月销量 + /// </summary> + public string SellCount { get; set; } + /// <summary> + /// 价格 + /// </summary> + public double Price { get; set; } + /// <summary> + /// 商品标题 + /// </summary> + public string ItemTitle { get; set; } + /// <summary> + /// 图片 + /// </summary> + public List<string> Images { get; set; } + /// <summary> + /// 优惠券地址 + /// </summary> + public string conupon_url { get; set; } + /// <summary> + /// 优惠券面额 + /// </summary> + public double conupon_price { get; set; } + /// <summary> + /// 商品介绍 + /// </summary> + public string Notice { get; set; } + + } +} diff --git a/应用/Weixin.AccurateCircle/Entitys/Enums.cs b/应用/Weixin.AccurateCircle/Entitys/Enums.cs new file mode 100644 index 0000000..79abea8 --- /dev/null +++ b/应用/Weixin.AccurateCircle/Entitys/Enums.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.AccurateCircle.Entitys +{ + public enum StateType + { + 已推广 = 0, + 未推广 = 1 + } + +} diff --git a/应用/Weixin.AccurateCircle/Entitys/fl_plugin_accuratecircle_dataInfos.cs b/应用/Weixin.AccurateCircle/Entitys/fl_plugin_accuratecircle_dataInfos.cs new file mode 100644 index 0000000..b79abeb --- /dev/null +++ b/应用/Weixin.AccurateCircle/Entitys/fl_plugin_accuratecircle_dataInfos.cs @@ -0,0 +1,31 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.AccurateCircle.Entitys +{ + public class fl_plugin_accuratecircle_dataInfos : base_model + { + public DateTime Sendtime { get; set; } + public string Content { get; set; } + public string Comment { get; set; } + public string AdditionalPic { get; set; } + + [SugarColumn(ColumnDataType = "Text")] + public string Data { get; set; } + + /// <summary> + /// 发送状态,是否发送过 + /// </summary> + public StateType state { get; set; } + + /// <summary> + /// 采集的日期 + /// </summary> + public DateTime cur_time { get; set; } + } +} diff --git a/应用/Weixin.AccurateCircle/Entitys/info_temp.cs b/应用/Weixin.AccurateCircle/Entitys/info_temp.cs new file mode 100644 index 0000000..6def9db --- /dev/null +++ b/应用/Weixin.AccurateCircle/Entitys/info_temp.cs @@ -0,0 +1,124 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.AccurateCircle.Entitys +{ + public class info_temp + { + public long ID { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _tb_adzone_pid_cps_name { get; set; } + public string tb_adzone_pid_cps_name + { + get { return _tb_adzone_pid_cps_name; } + set { _tb_adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _tb_adzone_pid; + /// <summary> + /// 主推广位id + /// </summary> + public string tb_adzone_pid + { + get { return _tb_adzone_pid; } + set { _tb_adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _tb_adzone_name; + + public string tb_adzone_name + { + get { return _tb_adzone_name; } + set { _tb_adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + //-- + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _jd_adzone_pid_cps_name { get; set; } + public string jd_adzone_pid_cps_name + { + get { return _jd_adzone_pid_cps_name; } + set { _jd_adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _jd_adzone_pid; + /// <summary> + /// 主推广位id + /// </summary> + public string jd_adzone_pid + { + get { return _jd_adzone_pid; } + set { _jd_adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _jd_adzone_name; + + public string jd_adzone_name + { + get { return _jd_adzone_name; } + set { _jd_adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + //== + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _pdd_adzone_pid_cps_name { get; set; } + public string pdd_adzone_pid_cps_name + { + get { return _pdd_adzone_pid_cps_name; } + set { _pdd_adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _pdd_adzone_pid; + /// <summary> + /// 主推广位id + /// </summary> + public string pdd_adzone_pid + { + get { return _pdd_adzone_pid; } + set { _pdd_adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _pdd_adzone_name; + + public string pdd_adzone_name + { + get { return _pdd_adzone_name; } + set { _pdd_adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/Weixin.AccurateCircle/MainForm.Designer.cs b/应用/Weixin.AccurateCircle/MainForm.Designer.cs new file mode 100644 index 0000000..c55f261 --- /dev/null +++ b/应用/Weixin.AccurateCircle/MainForm.Designer.cs @@ -0,0 +1,514 @@ +namespace Weixin.AccurateCircle +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label2 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有已发ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(966, 540); + this.xtraTabControl1.TabIndex = 1; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage3, + this.xtraTabPage2}); + this.xtraTabControl1.SelectedPageChanged += new DevExpress.XtraTab.TabPageChangedEventHandler(this.xtraTabControl1_SelectedPageChanged); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label2); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(960, 511); + this.xtraTabPage1.Text = " 数 据 采 集 列 表 "; + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.Transparent; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(327, 187); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(303, 35); + this.label2.TabIndex = 14; + this.label2.Text = "数据采集列表为空"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 475); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(960, 36); + this.pageControl1.TabIndex = 13; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemPictureEdit1}); + this.gridControl1.Size = new System.Drawing.Size(960, 472); + this.gridControl1.TabIndex = 12; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中项ToolStripMenuItem, + this.删除所有已发ToolStripMenuItem, + this.删除所有数据ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(149, 70); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有已发ToolStripMenuItem + // + this.删除所有已发ToolStripMenuItem.Name = "删除所有已发ToolStripMenuItem"; + this.删除所有已发ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有已发ToolStripMenuItem.Text = "删除所有已发"; + this.删除所有已发ToolStripMenuItem.Click += new System.EventHandler(this.删除所有已发ToolStripMenuItem_Click); + // + // 删除所有数据ToolStripMenuItem + // + this.删除所有数据ToolStripMenuItem.Name = "删除所有数据ToolStripMenuItem"; + this.删除所有数据ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有数据ToolStripMenuItem.Text = "删除所有数据"; + this.删除所有数据ToolStripMenuItem.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn6, + this.gridColumn10, + this.gridColumn1, + this.gridColumn3, + this.gridColumn2, + this.gridColumn5}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "编码"; + this.gridColumn6.FieldName = "id"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 1; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "发送时间"; + this.gridColumn10.DisplayFormat.FormatString = "HH:mm:ss"; + this.gridColumn10.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn10.FieldName = "Sendtime"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 2; + this.gridColumn10.Width = 86; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "正文"; + this.gridColumn1.FieldName = "Content"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 3; + this.gridColumn1.Width = 162; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "评语"; + this.gridColumn3.FieldName = "Comment"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 4; + this.gridColumn3.Width = 282; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "发送状态"; + this.gridColumn2.FieldName = "state"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 5; + this.gridColumn2.Width = 181; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "采集时间"; + this.gridColumn5.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn5.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn5.FieldName = "cur_time"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 6; + this.gridColumn5.Width = 154; + // + // repositoryItemPictureEdit1 + // + this.repositoryItemPictureEdit1.Name = "repositoryItemPictureEdit1"; + this.repositoryItemPictureEdit1.SizeMode = DevExpress.XtraEditors.Controls.PictureSizeMode.Stretch; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.label1); + this.xtraTabPage3.Controls.Add(this.pageControl2); + this.xtraTabPage3.Controls.Add(this.gridControl2); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(960, 511); + this.xtraTabPage3.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(207, 183); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 14; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 475); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(960, 36); + this.pageControl2.TabIndex = 9; + // + // gridControl2 + // + this.gridControl2.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(960, 471); + this.gridControl2.TabIndex = 8; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn4, + this.gridColumn16, + this.gridColumn17}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "ID"; + this.gridColumn11.FieldName = "ID"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + this.gridColumn11.Width = 50; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "平台类型"; + this.gridColumn12.FieldName = "chattype"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + this.gridColumn12.Width = 99; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "账号"; + this.gridColumn13.FieldName = "name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 2; + this.gridColumn13.Width = 148; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "账号昵称"; + this.gridColumn14.FieldName = "nick"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + this.gridColumn14.Width = 125; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn15.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn15.AppearanceCell.Options.UseFont = true; + this.gridColumn15.AppearanceCell.Options.UseForeColor = true; + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "淘宝推广位"; + this.gridColumn15.FieldName = "tb_adzone_name"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 4; + this.gridColumn15.Width = 121; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn4.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn4.AppearanceCell.Options.UseFont = true; + this.gridColumn4.AppearanceCell.Options.UseForeColor = true; + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "京东推广位"; + this.gridColumn4.FieldName = "jd_adzone_name"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 5; + this.gridColumn4.Width = 107; + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn16.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn16.AppearanceCell.Options.UseFont = true; + this.gridColumn16.AppearanceCell.Options.UseForeColor = true; + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "拼多多推广位"; + this.gridColumn16.FieldName = "pdd_adzone_name"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.OptionsColumn.AllowEdit = false; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 6; + this.gridColumn16.Width = 109; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "禁止使用"; + this.gridColumn17.FieldName = "onoff"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 7; + this.gridColumn17.Width = 66; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.settingControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(960, 530); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(960, 530); + this.settingControl1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(966, 540); + this.Controls.Add(this.xtraTabControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraTabPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.Label label2; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有已发ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有数据ToolStripMenuItem; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + } +} \ No newline at end of file diff --git a/应用/Weixin.AccurateCircle/MainForm.cs b/应用/Weixin.AccurateCircle/MainForm.cs new file mode 100644 index 0000000..a5ff03d --- /dev/null +++ b/应用/Weixin.AccurateCircle/MainForm.cs @@ -0,0 +1,399 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Weixin.AccurateCircle.Properties; +using Api.Framework.Enums; +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Model; +using Api.Framework.Tools; +using Weixin.AccurateCircle.Entitys; +using UI.Framework.Controls; + +namespace Weixin.AccurateCircle +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + try + { + settingControl1.Bind(Class1.Config, 120); //绑定控件 + + #region 加载所有采集到的商品 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<fl_plugin_accuratecircle_dataInfos>("select * from fl_plugin_accuratecircle_dataInfos order by state desc", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label2.Visible = gridView1.RowCount == 0; + #endregion + + #region 加载所有的账号 + + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + int total = 0; + + var result = session.Queryable<fl_robot_info>().Select<info_temp>(f => new info_temp() + { + ID = f.id, + chattype = f.type, + name = f.name, + nick = f.nick + }).ToPageList(1, 50, ref total); + + if (result != null && result.Count != 0) + { + foreach (var robot in result) + { + var adzones = session.FindAdzoneInfos().Where(f => f.custom_type == Resources.SoftwareType && f.robot_id == robot.ID).ToList(); + if (adzones != null && adzones.Count != 0) + { + robot.onoff = adzones[0].onoff; + foreach (var item in adzones) + { + if (item.alliance_id == (int)CpsType.阿里妈妈) + { + robot.tb_adzone_name = item.adzone_name; + robot.tb_adzone_pid = item.adzone_pid; + robot.tb_adzone_pid_cps_name = item.adzone_pid_cps_name; + } + else if (item.alliance_id == (int)CpsType.京东联盟) + { + robot.jd_adzone_name = item.adzone_name; + robot.jd_adzone_pid = item.adzone_pid; + robot.jd_adzone_pid_cps_name = item.adzone_pid_cps_name; + } + else if (item.alliance_id == (int)CpsType.多多进宝) + { + robot.pdd_adzone_name = item.adzone_name; + robot.pdd_adzone_pid = item.adzone_pid; + robot.pdd_adzone_pid_cps_name = item.adzone_pid_cps_name; + } + } + } + } + } + + return new PageControl.SerchResult() { Result = result, Total = total }; + + }, gridControl2, 40, true, true); + + label1.Visible = gridView2.RowCount == 0; + + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView2_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + + #region 双击单元格设置推广位 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "tb_adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == int.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + session.SaveOrUpdate(adzone); + } + else + { + try + { + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.Insertable(adzone).ExecuteReturnEntity(); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + pageControl2.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + else if (e.Column.FieldName == "jd_adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.京东联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == int.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + session.SaveOrUpdate(adzone); + } + else + { + try + { + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.京东联盟, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.Insertable(adzone).ExecuteReturnEntity(); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + pageControl2.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + else if (e.Column.FieldName == "pdd_adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.多多进宝); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.SoftwareType && f.robot_id == int.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + session.SaveOrUpdate(adzone); + } + else + { + try + { + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.Insertable(adzone).ExecuteReturnEntity(); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + pageControl2.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos().Where(f => f.custom_type == Resources.SoftwareType && f.robot_id == int.Parse(id)).ToList(); + if (adzones != null && adzones.Count != 0)//数据库中存在 + { + var onoff = adzones[0].onoff; + foreach (var item in adzones) + { + item.onoff = !onoff; + } + } + session.Saveable(adzones).ExecuteCommand(); + pageControl2.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "tb_adzone_name" || e.Column.FieldName == "jd_adzone_name" || e.Column.FieldName == "pdd_adzone_name") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView1.GetSelectedRows().ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + List<string> ids = new List<string>(); + foreach (var item in rownumber) + { + ids.Add("'" + gridView1.GetRowCellValue(item, "id").ToString() + "'");//根据行号获取相应行的数据 + } + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_accuratecircle_dataInfos where id in (" + string.Join(",", ids) + ")"); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除所有已发ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_accuratecircle_dataInfos where state = 0"); + } + + private void 删除所有数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_accuratecircle_dataInfos"); + } + + private void RemoveGoodsInfos(string sql) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL(sql); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Util.Save(Class1.Config); + } + + private void xtraTabControl1_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e) + { + try + { + if (xtraTabControl1.SelectedTabPageIndex == 0) + pageControl1.GotoPage(); + } + catch (Exception) + { } + } + } +} \ No newline at end of file diff --git a/应用/Weixin.AccurateCircle/MainForm.resx b/应用/Weixin.AccurateCircle/MainForm.resx new file mode 100644 index 0000000..c6e3372 --- /dev/null +++ b/应用/Weixin.AccurateCircle/MainForm.resx @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>43</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.AccurateCircle/MonitorThread.cs b/应用/Weixin.AccurateCircle/MonitorThread.cs new file mode 100644 index 0000000..efbb00c --- /dev/null +++ b/应用/Weixin.AccurateCircle/MonitorThread.cs @@ -0,0 +1,483 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Weixin.AccurateCircle.Entitys; +using Weixin.AccurateCircle.Properties; + +namespace Weixin.AccurateCircle +{ + public class MonitorThread : TimerTask + { + + private string cache_key = "weixin_accurateCircle_cache_key"; + + public override void Run(object state, bool timedOut) + { + + #region 定时清空采集的数据 + if (!string.IsNullOrWhiteSpace(Class1.Config.AutoClearTaskTimes)) + { + if (Class1.Config.Auto_IsClear == SwitchType.开启) + { + try + { + if (DateTime.Now.AddSeconds(-3).ToString("HHmm") == DateTime.Parse(Class1.Config.AutoClearTaskTimes).ToString("HHmm")) + { + var session = ApiClient.GetSession(); + session.Deleteable<fl_plugin_accuratecircle_dataInfos>().ExecuteCommand(); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, "定时清理异常" + ex.Message + "-" + ex.StackTrace); + } + } + } + #endregion + + #region + try + { + #region 采集 + if (Class1.Config.DownTime.AddMinutes(Class1.Config.DownInterval) < DateTime.Now) + { + Task.Run(() => + { + try + { + var url = string.IsNullOrWhiteSpace(Class1.Config.DownUrl) ? string.Empty : System.IO.Path.Combine(Class1.Config.DownUrl, "api", "circle", "gettask").Replace(@"\", "/"); + if (string.IsNullOrWhiteSpace(url)) return; + var html = string.Empty; + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = "post", + Postdata = $"taskid={Class1.Config.DownID}", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = false + }; + var result = http.GetHtml(item); + html = result.Html; + + if (!string.IsNullOrWhiteSpace(html)) + { + var dic = HttpExtend.JsonToDictionary(html); + if (dic == null) throw new Exception($"请求采集失败! {html}"); + + if (dic.ContainsKey("Data")) + { + var data = dic["Data"] as Dictionary<string, object>; + if (data.ContainsKey("data")) + { + long maxId = 0;//获取最大的id + var list = new List<fl_plugin_accuratecircle_dataInfos>(); + var _data = data["data"] as ArrayList; + foreach (Dictionary<string, object> temp in _data) + { + var datainfo = temp.ConvertToObj<fl_plugin_accuratecircle_dataInfos>(); + if (datainfo != null) + { + datainfo.state = StateType.未推广; + datainfo.cur_time = DateTime.Now; + list.Add(datainfo); + if (maxId < datainfo.id) maxId = datainfo.id; + } + } + var _session = ApiClient.GetSession(); + _session.Saveable(list).ExecuteCommand(); + Class1.Config.DownID = maxId; + Class1.Config.DownTime = DateTime.Now; + Util.Save(Class1.Config); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"精准朋友圈采集异常:{ex.Message} - {ex.StackTrace}"); + } + }); + } + #endregion + + #region 发送 + var session = ApiClient.GetSession(); + var datainfos = session.Queryable<fl_plugin_accuratecircle_dataInfos>().OrderBy(f => f.Sendtime, SqlSugar.OrderByType.Asc).Where(f => f.state == StateType.未推广).ToList(); + + datainfos = datainfos.Where(f => f.Sendtime.ToString("HHmm") == DateTime.Now.ToString("HHmm")).ToList(); + + foreach (var datainfo1 in datainfos) + { + if (datainfo1 != null) + { + var result = ApiClient.Cache.Get<List<long>>(cache_key); + if (result != null && result.Contains(datainfo1.id)) return; + var task_time = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd") + datainfo1.Sendtime.ToString(" HH:mm:ss")); + var now = DateTime.Now; + var dValue = (now - task_time).TotalMinutes; + if (0 < dValue && dValue < 5) + { + if (result == null) result = new List<long>(); + result.Add(datainfo1.id); + ApiClient.Cache.Set(cache_key, result, 5); + var clients = Chat.Framework.ChatClient.WXClient; + + var tbAnalysis = new TBHelper.TbAnalysis(); + + var jsonData = "{\"data\":" + datainfo1.AdditionalPic + "}"; + + #region 用户设置的附加图片 + StringBuilder strbImage = new StringBuilder(); + var dicData = HttpExtend.JsonToDictionary(jsonData); + if (dicData != null && dicData.ContainsKey("data")) + { + var arrFileName = dicData["data"] as ArrayList; + HttpHelper http = new HttpHelper(); + foreach (string fileName in arrFileName) + { + try + { + var image = Util.MapFile(fileName, @"Cache\image"); + var url = string.IsNullOrWhiteSpace(Class1.Config.DownUrl) ? string.Empty : Path.Combine(Class1.Config.DownUrl, fileName).Replace(@"\", "/"); + if (!string.IsNullOrWhiteSpace(url)) + { + HttpItem item = new HttpItem() + { + URL = url, + Method = "get", + IsToLower = false, + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "text/html", + Allowautoredirect = false, + ResultType = ResultType.Byte + }; + var resule_ = http.GetHtml(item); + var bytes = resule_.ResultByte; + var flag = byteArrayToImage(bytes, image); + strbImage.Append($"[图片={image}]"); + } + } + catch (Exception ex) + { } + } + } + #endregion + + foreach (var client in clients.Values) + { + try + { + if (client.WeixinType == WeixinType.Grpc微信 && client.Status == WxStatus.在线) + { + if (!string.IsNullOrWhiteSpace(datainfo1.Data)) + { + StringBuilder strb = new StringBuilder(); + strb.Append(datainfo1.Content); + + jsonData = "{\"data\":" + datainfo1.Data + "}"; + dicData = HttpExtend.JsonToDictionary(jsonData); + if (dicData != null && dicData.ContainsKey("data")) + { + var arr = dicData["data"] as ArrayList; + foreach (Dictionary<string, object> item in arr) + { + var baseInfo = new BaseInfo(); + if (item.ContainsKey("Cps")) baseInfo.Cps = item["Cps"].ToString(); + if (item.ContainsKey("ItemId")) baseInfo.ItemId = item["ItemId"].ToString(); + if (item.ContainsKey("Price")) baseInfo.Price = double.Parse(item["Price"].ToString()); + if (item.ContainsKey("ItemTitle")) baseInfo.ItemTitle = item["ItemTitle"].ToString(); + if (item.ContainsKey("conupon_url")) baseInfo.conupon_url = item["conupon_url"].ToString(); + if (item.ContainsKey("Notice")) baseInfo.Notice = item["Notice"].ToString(); + if (item.ContainsKey("conupon_price")) baseInfo.conupon_price = double.Parse(item["conupon_price"].ToString()); + if (item.ContainsKey("Images")) + { + var _images = new List<string>(); + var images = item["Images"] as ArrayList; + foreach (string image in images) + { + _images.Add(image); + } + baseInfo.Images = _images; + } + + if (baseInfo != null) + { + var robot = session.FindRobots().FirstOrDefault(f => f.name == client.WeixinHao && f.type == ChatType.微信); + if (robot == null) continue; + var adzones = session.FindAdzoneInfos().Where(f => !f.onoff && f.custom_type == Resources.SoftwareType && f.robot_id == robot.id); + if (baseInfo.Cps == "淘宝") + { + #region 淘宝 + try + { + var adzone = adzones.FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈); + if (adzone == null) continue; + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + if (member != null) + { + var api = CpsClient.CreateAlimamaRequest(member); + if (api == null) continue; + + var pict_url = (baseInfo.Images != null && baseInfo.Images.Count != 0) ? baseInfo.Images[0] : string.Empty; + #region 获取淘口令 tkl + var tkl = string.Empty; + try + { + var _title = baseInfo.ItemTitle; + var _pict_url = pict_url; + tkl = tbAnalysis.FindTKL(baseInfo.conupon_url, _title, _pict_url, api); + if (string.IsNullOrEmpty(tkl)) + { + for (int i = 0; i <= 3; i++) + { + tkl = tbAnalysis.FindTKL(baseInfo.conupon_url, _title, _pict_url, api); + if (!string.IsNullOrEmpty(tkl)) break; + Thread.Sleep(200); + } + } + if (string.IsNullOrEmpty(tkl)) + continue; + } + catch (Exception ex) + { } + #endregion + var short_url = api.ComposeTbClick(baseInfo.ItemId, pict_url, tkl, baseInfo.conupon_url, true, (int)DwzType.官方短网址);//短连接 + + var image = ApiClient.GetQRImage(baseInfo.ItemTitle, baseInfo.Price.ToString(), baseInfo.conupon_price.ToString(), ((decimal)baseInfo.Price - (decimal)baseInfo.conupon_price).ToString(), pict_url, short_url, ApiClient.QrImageType.模板A, CpsType.阿里妈妈, baseInfo.Notice); //合成附带二维码等信息的宝贝图片 + strb.Append($"[图片={image}]"); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"精确朋友圈淘宝商品解析失败:{ex.Message} - {ex.StackTrace}"); + } + #endregion + } + else if (baseInfo.Cps == "京东") + { + #region 京东 + try + { + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == robot.id); + if (adzone != null) + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟 && f.username == adzone.adzone_pid_cps_name); + if (member != null) + { + var api = CpsClient.CreateJingdongRequest(member); + if (api == null) { return; } + + var buyshorturl = string.Empty; //转连后的地址 + Dictionary<string, object> conversionlinkresult = null; //查询到的转换链接对象 + var positionId = adzone.adzone_pid.Substring(adzone.adzone_pid.LastIndexOf("_") + 1); + if (string.IsNullOrWhiteSpace(baseInfo.conupon_url)) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{baseInfo.ItemId}.html", positionId = positionId, unionId = member.usernick } });//宝贝id 和 用户的目标推客的联盟id + } + else + { + try + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{baseInfo.ItemId}.html", positionId = positionId, unionId = member.usernick, couponUrl = baseInfo.conupon_url } }); + } + catch (Exception) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{baseInfo.ItemId}.html", positionId = positionId, unionId = member.usernick } });//宝贝id 和 用户的目标推客的联盟id + } + } + if (conversionlinkresult != null) + { + if (conversionlinkresult["code"].ToString() != "200") throw new Exception($"京东查询接口调用失败:{conversionlinkresult["message"].ToString()}");//抛出错误信息 + if (conversionlinkresult.ContainsKey("data")) + { + var data = conversionlinkresult["data"] as Dictionary<string, object>; + if (data.ContainsKey("shortURL")) + buyshorturl = data["shortURL"].ToString();//购买短连接 + } + if (string.IsNullOrWhiteSpace(buyshorturl)) continue;//京东转链失败,请稍后重试 + } + + var goods_desc = string.IsNullOrWhiteSpace(baseInfo.Notice) ? string.Empty : baseInfo.Notice; + + var image = ApiClient.GetQRImage(baseInfo.ItemTitle, baseInfo.Price.ToString(), baseInfo.conupon_price.ToString(), ((decimal)baseInfo.Price - (decimal)baseInfo.conupon_price).ToString(), baseInfo.Images[0], buyshorturl, ApiClient.QrImageType.模板A, CpsType.京东联盟, baseInfo.Notice); //合成附带二维码等信息的宝贝图片 + strb.Append($"[图片={image}]"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"精确朋友圈京东商品解析失败:{ex.Message} - {ex.StackTrace}"); + } + #endregion + } + else if (baseInfo.Cps == "拼多多") + { + #region 拼多多 + try + { + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.SoftwareType && f.robot_id == robot.id); + if (adzone != null) + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == adzone.adzone_pid_cps_name); + if (member != null) + { + string param = $"fl_{robot.name}_{(int)ChatType.微信}_精准朋友圈推广"; + var api = CpsClient.CreatePinduoduoRequest(member); + if (api == null) { return; } + try + { + var data = new { goods_id_list = $"[{baseInfo.ItemId}]" }; + var obj = api.SendPinduoduo("pdd.ddk.goods.detail", data); + if (obj == null) throw new Exception("创建拼多多API请求失败"); + //解析商品,获取商品的信息 + var goods_detail_response = obj["goods_detail_response"] as Dictionary<string, object>; + var goods_details = goods_detail_response["goods_details"] as ArrayList; + //有查到返利提示 + if (goods_details.Count != 0) + { + foreach (var _details in goods_details) + { + var details = _details as Dictionary<string, object>; + var _coupon_discount = double.Parse((details["coupon_discount"] ?? 0).ToString()); + var coupon_discount = _coupon_discount == 0 ? 0 : Math.Round(_coupon_discount / 100.00, 2); //优惠券面额,单位为分 + var pddHelper = new PDDHelper(); + string _temp_param = $"fl_{robot.name}_{(int)ChatType.微信}_精准朋友圈推广"; + //搜索成功有券的情况下 + //if (_coupon_discount != 0) + //{ + var manyShoppingUrl = pddHelper.GetShoppingUrl(api, new { p_id = adzone.adzone_pid, custom_parameters = _temp_param, goods_id_list = $"[{baseInfo.ItemId}]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, force_duo_id = true }); + + strb.Append($"[图片={ApiClient.GetQRImage(baseInfo.ItemTitle, baseInfo.Price.ToString(), coupon_discount.ToString(), ((decimal)baseInfo.Price - (decimal)coupon_discount).ToString(), baseInfo.Images[0], manyShoppingUrl, ApiClient.QrImageType.模板A, CpsType.多多进宝, baseInfo.Notice)}]"); + //} + } + } + } + catch + { } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"精确朋友圈拼多多商品解析失败:{ex.Message} - {ex.StackTrace}"); + } + #endregion + } + } + } + } + + strb.Append(strbImage.ToString()); + EventClient.OnEvent(this, "定时任务:" + client.WeixinHao + ":准备发了"); + var json = client.SendCircle(strb.ToString());//发送朋友圈的主内容 + if (string.IsNullOrWhiteSpace(json)) + EventClient.OnEvent(this, "定时任务:" + client.WeixinHao + ":发送失败"); + else + EventClient.OnEvent(this, "定时任务:" + client.WeixinHao + ":已经发了"); + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + { + var id = reg.Groups["id"].Value; + if (!string.IsNullOrWhiteSpace(datainfo1.Comment)) + client.SendCircleComment(client.User.Username, id, datainfo1.Comment); + } + datainfo1.state = StateType.已推广; + session.Saveable(datainfo1).ExecuteCommand(); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - 定时发送任务:{ex.Message},{ex.StackTrace}"); + } + } + } + } + } + #endregion + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"{ex.Message} - {ex.StackTrace}"); + } + #endregion + + } + + /// <summary> + /// 字节数组生成图片 + /// </summary> + /// <param name="Bytes">字节数组</param> + /// <returns>图片</returns> + private bool byteArrayToImage(byte[] Bytes, string fileName) + { + Stream ms = null; + try + { + ms = new MemoryStream(Bytes); + return StreamToFile(ms, fileName); + } + catch (Exception ex) + { + return false; + } + finally + { + if (ms != null) + { + ms.Close(); + ms.Dispose(); + } + } + } + + /// <summary> + /// 将Stream写入文件 + /// </summary> + /// <param name="stream"></param> + /// <param name="path"></param> + public bool StreamToFile(Stream stream, string path) + { + try + { + byte[] bytes = new byte[stream.Length]; // 把Stream转换成byte[] + stream.Read(bytes, 0, bytes.Length); + stream.Seek(0, SeekOrigin.Begin); // 设置当前流的位置为流的开始 + FileStream fs = new FileStream(path, FileMode.Create); // 把byte[]写入文件 + BinaryWriter bw = new BinaryWriter(fs); + bw.Write(bytes); + bw.Close(); + fs.Close(); + } + catch (Exception) + { + return false; + } + return true; + } + + } +} diff --git a/应用/Weixin.AccurateCircle/Properties/AssemblyInfo.cs b/应用/Weixin.AccurateCircle/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9066f5c --- /dev/null +++ b/应用/Weixin.AccurateCircle/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Weixin.AccurateCircle")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Weixin.AccurateCircle")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("a9b42891-505b-4bae-9ee8-af62c92bc4da")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/Weixin.AccurateCircle/Properties/Resources.Designer.cs b/应用/Weixin.AccurateCircle/Properties/Resources.Designer.cs new file mode 100644 index 0000000..2703917 --- /dev/null +++ b/应用/Weixin.AccurateCircle/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Weixin.AccurateCircle.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Weixin.AccurateCircle.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 精准朋友圈 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 精准朋友圈 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 精准朋友圈 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找类似 精准朋友圈 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 精准朋友圈 { + get { + object obj = ResourceManager.GetObject("精准朋友圈", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Weixin.AccurateCircle/Properties/Resources.resx b/应用/Weixin.AccurateCircle/Properties/Resources.resx new file mode 100644 index 0000000..6787a41 --- /dev/null +++ b/应用/Weixin.AccurateCircle/Properties/Resources.resx @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="MainFormTitle" xml:space="preserve"> + <value>精准朋友圈</value> + </data> + <data name="PluginName" xml:space="preserve"> + <value>精准朋友圈</value> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>精准朋友圈</value> + </data> + <data name="SoftwareType" xml:space="preserve"> + <value>精准朋友圈</value> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="精准朋友圈" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\精准朋友圈.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/Weixin.AccurateCircle/Properties/licenses.licx b/应用/Weixin.AccurateCircle/Properties/licenses.licx new file mode 100644 index 0000000..3fd7997 --- /dev/null +++ b/应用/Weixin.AccurateCircle/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/Weixin.AccurateCircle/Resources/精准朋友圈.png b/应用/Weixin.AccurateCircle/Resources/精准朋友圈.png new file mode 100644 index 0000000..4c3ff9e Binary files /dev/null and b/应用/Weixin.AccurateCircle/Resources/精准朋友圈.png differ diff --git a/应用/Weixin.AccurateCircle/Weixin.AccurateCircle.csproj b/应用/Weixin.AccurateCircle/Weixin.AccurateCircle.csproj new file mode 100644 index 0000000..9c927da --- /dev/null +++ b/应用/Weixin.AccurateCircle/Weixin.AccurateCircle.csproj @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{A9B42891-505B-4BAE-9EE8-AF62C92BC4DA}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Weixin.AccurateCircle</RootNamespace> + <AssemblyName>Weixin.AccurateCircle</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Entitys\BaseInfo.cs" /> + <Compile Include="Entitys\Enums.cs" /> + <Compile Include="Entitys\fl_plugin_accuratecircle_dataInfos.cs" /> + <Compile Include="Entitys\info_temp.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="MonitorThread.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\tb02.jpg" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\精准朋友圈.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/AddAutoSendForm.Designer.cs b/应用/Weixin.CircleTools/AddAutoSendForm.Designer.cs new file mode 100644 index 0000000..00d33e4 --- /dev/null +++ b/应用/Weixin.CircleTools/AddAutoSendForm.Designer.cs @@ -0,0 +1,242 @@ +namespace Weixin.CircleTools +{ + partial class AddAutoSendForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label9 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.checkEdit1 = new DevExpress.XtraEditors.CheckEdit(); + this.label5 = new System.Windows.Forms.Label(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.label3 = new System.Windows.Forms.Label(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.checkedComboBoxEdit1 = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.label9); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.checkEdit1); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.dateTimePicker1); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.checkedComboBoxEdit1); + this.groupBox1.Location = new System.Drawing.Point(23, 28); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(524, 233); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 设置定时信息 "; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(305, 180); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(89, 35); + this.simpleButton2.TabIndex = 26; + this.simpleButton2.Text = "取 消"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(133, 180); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(89, 35); + this.simpleButton1.TabIndex = 26; + this.simpleButton1.Text = "添 加"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.ForeColor = System.Drawing.Color.Red; + this.label9.Location = new System.Drawing.Point(475, 105); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(14, 14); + this.label9.TabIndex = 25; + this.label9.Text = "*"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.ForeColor = System.Drawing.Color.Red; + this.label8.Location = new System.Drawing.Point(475, 75); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(14, 14); + this.label8.TabIndex = 24; + this.label8.Text = "*"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.ForeColor = System.Drawing.Color.Red; + this.label7.Location = new System.Drawing.Point(475, 49); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(14, 14); + this.label7.TabIndex = 23; + this.label7.Text = "*"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.ForeColor = System.Drawing.Color.Gray; + this.label6.Location = new System.Drawing.Point(236, 135); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(127, 14); + this.label6.TabIndex = 22; + this.label6.Text = "(不勾选则执行一次)"; + // + // checkEdit1 + // + this.checkEdit1.Location = new System.Drawing.Point(155, 133); + this.checkEdit1.Name = "checkEdit1"; + this.checkEdit1.Properties.Caption = "是否循环"; + this.checkEdit1.Size = new System.Drawing.Size(75, 19); + this.checkEdit1.TabIndex = 21; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(68, 135); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(67, 14); + this.label5.TabIndex = 20; + this.label5.Text = "任务类型:"; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(155, 46); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(311, 20); + this.textEdit1.TabIndex = 19; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(56, 105); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(79, 14); + this.label3.TabIndex = 18; + this.label3.Text = "发送时间点:"; + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(155, 99); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.ShowUpDown = true; + this.dateTimePicker1.Size = new System.Drawing.Size(311, 22); + this.dateTimePicker1.TabIndex = 17; + this.dateTimePicker1.Value = new System.DateTime(2018, 11, 16, 15, 56, 0, 0); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(68, 49); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 16; + this.label2.Text = "任务名称:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(56, 75); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(79, 14); + this.label1.TabIndex = 15; + this.label1.Text = "发送工作日:"; + // + // checkedComboBoxEdit1 + // + this.checkedComboBoxEdit1.Location = new System.Drawing.Point(155, 72); + this.checkedComboBoxEdit1.Name = "checkedComboBoxEdit1"; + this.checkedComboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit1.Size = new System.Drawing.Size(311, 20); + this.checkedComboBoxEdit1.TabIndex = 14; + // + // AddAutoSendForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(570, 282); + this.Controls.Add(this.groupBox1); + this.Name = "AddAutoSendForm"; + this.Text = "添加至定时推送"; + this.Load += new System.EventHandler(this.AddAutoSendForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.ComponentModel.BackgroundWorker backgroundWorker1; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; + private DevExpress.XtraEditors.CheckEdit checkEdit1; + private System.Windows.Forms.Label label5; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/AddAutoSendForm.cs b/应用/Weixin.CircleTools/AddAutoSendForm.cs new file mode 100644 index 0000000..d32df65 --- /dev/null +++ b/应用/Weixin.CircleTools/AddAutoSendForm.cs @@ -0,0 +1,60 @@ +using Api.Framework; +using System; +using UI.Framework.Forms; +using Weixin.CircleTools.Entitys; +using static CircleFriendsTools.Enums; + +namespace Weixin.CircleTools +{ + public partial class AddAutoSendForm : BaseForm + { + + fl_plugin_circletools_taskinfos taskinfo; + + public AddAutoSendForm(fl_plugin_circletools_taskinfos taskinfo) + { + InitializeComponent(); + this.taskinfo = taskinfo; + } + + private void AddAutoSendForm_Load(object sender, EventArgs e) + { + foreach (WorkingDayType item in Enum.GetValues(typeof(WorkingDayType))) + { + checkedComboBoxEdit1.Properties.Items.Add(item.ToString()); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("请填写任务名称!"); + else if (string.IsNullOrWhiteSpace(checkedComboBoxEdit1.Text)) throw new Exception("请勾选工作日!"); + else if (string.IsNullOrWhiteSpace(dateTimePicker1.Text)) throw new Exception("请设置发送时间点!"); + + var session = ApiClient.GetSession(); + if (taskinfo != null) + { + taskinfo.task_name = textEdit1.Text.Trim(); + taskinfo.task_working_day = checkedComboBoxEdit1.Text.Trim(); + taskinfo.task_time = dateTimePicker1.Value.ToString("HH:mm"); + taskinfo.is_circulate = checkEdit1.Checked ? ChooseType.是 : ChooseType.否; + + session.Saveable(taskinfo).ExecuteCommand(); + ShowSuccess("添加成功!"); + } + this.Close(); + } + catch (Exception ex) + { + ShowError("添加失败:错误" + ex.Message); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.Close(); + } + } +} diff --git a/应用/Weixin.CircleTools/AddAutoSendForm.resx b/应用/Weixin.CircleTools/AddAutoSendForm.resx new file mode 100644 index 0000000..b966dfd --- /dev/null +++ b/应用/Weixin.CircleTools/AddAutoSendForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/AnalyzeGoods.cs b/应用/Weixin.CircleTools/AnalyzeGoods.cs new file mode 100644 index 0000000..daa25ff --- /dev/null +++ b/应用/Weixin.CircleTools/AnalyzeGoods.cs @@ -0,0 +1,193 @@ +using Api.Framework; +using Api.Framework.Enums; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework.Tools; +using Weixin.CircleTools.Entitys; + +namespace Weixin.CircleTools +{ + /// <summary> + /// 解析商品 + /// </summary> + class AnalyzeGoods + { + /// <summary> + /// 通过商品的id查询返回获取到自己返利商品信息 + /// </summary> + /// <param name="goods_id"></param> + /// <returns></returns> + public goodsinfos FindGoodsInfoToItemId(string goods_id, string pid_cps_name = "", string pid = "", string biz_scene_id = "2") + { + var session = ApiClient.GetSession(); + try + { + if (!string.IsNullOrEmpty(goods_id))//符合搜索宝贝id的条件 + { + var member = (string.IsNullOrEmpty(pid_cps_name) ? CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈) : CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == pid_cps_name)); + if (member == null) { return null; } + var api = CpsClient.CreateAlimamaRequest(member); + var itemInfo = api.GetItemInfo(goods_id, "2"); + if (itemInfo != null && itemInfo.n_tbk_item != null && itemInfo.n_tbk_item.Count > 0) + { + var tbk_item = itemInfo.n_tbk_item[0]; + //店铺名称 + var nick = tbk_item.nick; + //商品主图 + var pict_url = tbk_item.pict_url; + //商品id + goods_id = tbk_item.num_iid; + //商品标题 + var title = tbk_item.title; + //商品折扣价格(当前售价) + var zk_final_price = double.Parse(tbk_item.zk_final_price); + //30天销量 + var volume = tbk_item.volume; + var goods_desc = string.Empty; + + var coupon_remain_quantity = string.Empty; + + biz_scene_id = TBHelper.TbAnalysis.BizSceneId(goods_id); + + var pids = pid.Split('_'); + var privilege = api.SendTaobao("taobao.tbk.privilege.get", new { item_id = goods_id, site_id = pids[2], adzone_id = pids[3], biz_scene_id = biz_scene_id }); + var privilege_data = privilege["data"] as Dictionary<string, object>; + //最高佣金率 + var max_commission_rate = double.Parse(privilege_data["max_commission_rate"].ToString()); + //优惠券地址 + var coupon_click_url = string.Empty; + var coupon_price = 0.00d; + if (privilege_data.ContainsKey("coupon_info")) + { + var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满\d+元减(\d+)元"); + if (quan_reg.Success) coupon_price = double.Parse(quan_reg.Groups[1].Value); + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + else + { + coupon_price = 0.00d; + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + + return new goodsinfos() { cur_time = DateTime.Today, goods_id = goods_id, goods_name = title, mall_name = nick, goods_thumbnail_url = pict_url, sold_quantity = volume, normal_price = zk_final_price, coupon_discount = coupon_price, promotion_rate = max_commission_rate, shopping_url = coupon_click_url, goods_desc = goods_desc, coupon_remain_quantity = coupon_remain_quantity }; + } + } + } + catch (Exception) + { } + return null; + } + + public void AnalysisText(string message, goodsinfos goodsinfo) + { + try + { + var list = new string[] { @"(?<短标题>[\w\W]+)\s?(优惠\s?券|领券|抢券)[::]\s?(?<优惠券>[\w\W]+)\s+(下单链接|下单|抢购|秒杀)[::]\s?(?<商品>[\w\W]+)\s+(?<长文案>[\w\W]+)", @"\[image=(?<图片地址>[\w\W]+)\]\s+(?<短标题>[\w\W]+)\s+(优惠券|领券|抢券)[::]\s?(?<优惠券>[\w\W]+)\s+(下单|抢购|秒杀)[::]\s?(?<商品>[\w\W]+)\s+(?<长文案>[\w\W]+)" }; + + foreach (string item in list) + { + var reg = Regex.Match(message, item); + if (reg.Success) + { + goodsinfo.goods_desc = reg.Groups["长文案"].ToString().Trim(); + } + } + } + catch (Exception ex) + { } + } + + //public object FindResult(string method, object param = null) + //{ + // string msd = method; + + // int page = 0; + //Next: + // page++; + // string sign = string.Empty; + // string str = string.Empty; + // System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0)); + // long t = (DateTime.Now.Ticks - startTime.Ticks) / 10000; //除10000调整为13位 + // if (param != null) + // { + // StringBuilder sb = new StringBuilder("now=" + t + "&"); + + // Type type = param.GetType(); + // System.Reflection.PropertyInfo[] ps = type.GetProperties(); + + + + // foreach (PropertyInfo i in ps) + // { + // string name = i.Name; + // object value = i.GetValue(param, null); + // sb.Append(name + "=" + HttpHelper.URLEncode(value.ToString(), Encoding.UTF8)); + // sb.Append("&"); + // } + + // str = sb.ToString(); + // sign = HttpHelper.URLDecode((str.Substring(0, str.Length - 1) + "cps-api"), Encoding.UTF8); + // sign = sign.GetHashCode().ToString(); + + // } + // str += "sign=" + sign; + // HttpHelper http = new HttpHelper(); + + // HttpItem item = new HttpItem() + // { + // URL = _host + "/api/alimama.asmx/" + method + "?v=1.0.0.1",//URL 必需项 + // Method = "post",//URL 可选项 默认为Get + // Timeout = 1000 * 30,//连接超时时间 可选项默认为100000 + // ReadWriteTimeout = 1000 * 30,//写入Post数据超时时间 可选项默认为30000 + // IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + // Cookie = "",//字符串Cookie 可选项 + // UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统 可选项有默认值 + // Accept = "text/html, application/xhtml+xml, */*",// 可选项有默认值 + // ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + // Referer = "http://license.52cmg.cn",//来源URL 可选项 + // Postdata = str,//Post数据 可选项GET时不需要写 + // }; + + // string html = string.Empty; + // try + // { + // html = http.GetHtml(item).Html; + // } + // catch (Exception) + // { + // if (page < 5) + // { + // page++; + // Thread.Sleep(500); + // goto Next; + // } + // } + + // var dic = HttpExtend.JsonToDictionary(html); + // if (dic == null) throw new Exception(html); + + // if (dic["ok"].ToString().ToUpper() == "FALSE") + // { + // string msg = dic["message"].ToString(); + // if (page < 5 && string.IsNullOrEmpty(dic["message"].ToString()) && !msg.Contains("未授权") && !msg.Contains("Invalid session")) + // { + // Console.WriteLine("异常:" + msg); + // Thread.Sleep(500); + // goto Next; + // } + + + // throw new Exception(dic["message"].ToString()); + // } + // return dic["message"]; + //} + } +} diff --git a/应用/Weixin.CircleTools/Class1.cs b/应用/Weixin.CircleTools/Class1.cs new file mode 100644 index 0000000..acd7de1 --- /dev/null +++ b/应用/Weixin.CircleTools/Class1.cs @@ -0,0 +1,130 @@ +using Api.Framework; +using Api.Framework.SDK; +using Weixin.CircleTools.Properties; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.CircleTools.Entitys; +using Weixin.CircleTools; +using Api.Framework.Enums; +using Api.Framework.Model; + +namespace CircleFriendsTools +{ + public class Class1 : Plugin + { + + public Class1() + { + this.Logo = Resources.朋友圈工具; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config = null; + private MainForm mainForm = null; + public static StringBuilder strb = new StringBuilder(); + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + if (!session.TableExist<fl_plugin_circletools_taskinfos>()) session.CreateTable<fl_plugin_circletools_taskinfos>(); + else + { + if (!session.ColumnExist("fl_plugin_circletools_taskinfos", "task_comment")) + { + session.AddColumn("fl_plugin_circletools_taskinfos", "task_comment", "text"); + } + + if (!session.ColumnExist("fl_plugin_circletools_taskinfos", "robotnames")) + { + session.AddColumn("fl_plugin_circletools_taskinfos", "robotnames", "text"); + session.ExcuteSQL("update fl_plugin_circletools_taskinfos set robotnames = '" + string.Join(",", session.FindRobots().Select(f => f.name)) + "'"); + } + } + if (session.TableExist<fl_plugin_circletools_tgw>()) + { + var tbtgws = session.Find<fl_plugin_circletools_tgw>("select * from fl_plugin_circletools_tgw").ToList(); + if (tbtgws != null) + { + foreach (var item in tbtgws) + { + session.Insertable(new fl_adzone_info() + { + adzone_name = item.pid_name, //推广位名称 + adzone_pid = item.pid, //推广位pid + adzone_pid_cps_name = item.pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType //自定义类型 + }).ExecuteCommand(); + } + } + session.DropTable<fl_plugin_circletools_tgw>(); + } + + Config = this.ReadConfig<Config>(); + var thread = TimerTask.NewTimer<MonitorThread>(1) as MonitorThread; //创建线程 - 监听好友朋友圈和接口的线程 1秒 + thread.plugin = this; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (Config.transpond_send_usernames == null) + { + Config.transpond_send_usernames = new List<string>(); + Config.transpond_send_usernames = Chat.Framework.ChatClient.WXClient.Values.ToList().Select(f => f.WeixinHao.Trim()).ToList(); + } + + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close<MonitorThread>(); + SessionExt.Clear(); + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/Weixin.CircleTools/Config.cs b/应用/Weixin.CircleTools/Config.cs new file mode 100644 index 0000000..02c405f --- /dev/null +++ b/应用/Weixin.CircleTools/Config.cs @@ -0,0 +1,215 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static Api.Framework.ApiClient; +using static CircleFriendsTools.Enums; + +namespace CircleFriendsTools +{ + /// <summary> + /// 微信内容模板 + /// </summary> + public class ContentModel + { + /// <summary> + /// 模板名称 + /// </summary> + public string ModelName { get; set; } + /// <summary> + /// 内容 + /// </summary> + public string Content { get; set; } + } + + + [Config(Name = "插件-朋友圈工具-配置")] + public class Config + { + #region 转发功能 + /// <summary> + /// 朋友圈监听账号 + /// </summary> + public string MonitorCrowd { get; set; } + + /// <summary> + /// 转发发送机器人集合 + /// </summary> + public List<string> transpond_send_usernames { get; set; } + + /// <summary> + /// 转发类型 + /// </summary> + public TransmitStyleType TransmitStyle { get; set; } + + /// <summary> + /// 朋友圈地址内容 + /// </summary> + public string LocationContent { get; set; } + + /// <summary> + /// 朋友圈poi采集用户账号 + /// </summary> + public string GatherPoiCrowd { get; set; } + + /// <summary> + /// 自定义web接口 + /// </summary> + public string CustomWebApi { get; set; } + + /// <summary> + /// 监听触发时长 分钟 + /// </summary> + public int MonitorIntervalTime { get; set; } + + ///// <summary> + ///// 自定义定时任务采集接口 + ///// </summary> + //public string CustomTimedTaskAcquisitionApi { get; set; } + + ///// <summary> + ///// 监听触发时长 分钟 + ///// </summary> + //public int CustomTimedTaskAcquisitionMonitorIntervalTime { get; set; } + + ///// <summary> + ///// 自定义定时任务采集发送机器人账号 + ///// </summary> + //public List<string> CustomTimedTaskAcquisitionSendRobotNames { get; set; } + + /// <summary> + /// 自动转连 + /// </summary> + public bool AutoTurn { get; set; } + + /// <summary> + /// 执着转连(转发朋友圈内容以及评语,用户淘口令转连失败,该值为True时,依然追加评论内容) + /// </summary> + public bool Turn_Obstinate { get; set; } + + /// <summary> + /// 转链自定义标题 + /// </summary> + public string TurnTitle { get; set; } + + /// <summary> + /// 二维码模板 + /// </summary> + public QrImageType qrImage { get; set; } + + /// <summary> + /// 监听所发送的朋友圈消息创建时间戳(记录) + /// </summary> + public string MonitorInfoHistoryTime { get; set; } + + /// <summary> + /// 自定义web接口.返回文本的MD5(用于记录是个上次发送的内容一致) + /// </summary> + public string CustomWebApiTextMD5 { get; set; } + + /// <summary> + /// 接口访问时间 分 + /// </summary> + public int CustomWebApiIntervalTime { get; set; } + + /// <summary> + /// 网络图片的链接 + /// </summary> + public string NetworkUrl { get; set; } + + /// <summary> + /// 自动点赞 + /// </summary> + public bool AutoPraise { get; set; } + + /// <summary> + /// 自动点赞时间间隔 分钟 + /// </summary> + public int AutoPraiseInterval { get; set; } + + #endregion + + #region 一键发送 + /// <summary> + /// 推广位pid + /// </summary> + public string adzone_pid { get; set; } + /// <summary> + /// 推广位pid名称 + /// </summary> + public string adzone_pid_cps_name { get; set; } + /// <summary> + /// 推广位名称 + /// </summary> + public string adzone_name { get; set; } + /// <summary> + /// 发送人员集合 + /// </summary> + public List<string> send_usernames { get; set; } + /// <summary> + /// 手动发送人员集合 + /// </summary> + public List<string> manually_send_usernames { get; set; } + /// <summary> + /// 发送模板 + /// </summary> + public List<ContentModel> send_templates { get; set; } + + /// <summary> + /// 记录当天发送过的商品 + /// </summary> + public Dictionary<string, List<string>> recordSendGoods { get; set; } + + /// <summary> + /// 转发朋友圈自定义追加评语内容 + /// </summary> + public string AppendComment { get; set; } + + #endregion + + public Config() + { + this.GatherPoiCrowd = string.Empty; + this.MonitorCrowd = string.Empty; + this.qrImage = QrImageType.模板B; + + #region 转发功能 + this.TransmitStyle = TransmitStyleType.原文及评论; + //this.transpond_send_usernames = new List<string>(); + this.LocationContent = string.Empty; + this.AutoPraise = true; + this.AutoTurn = false; + this.Turn_Obstinate = false; + //this.TurnTitle = string.Empty; + this.AutoPraiseInterval = 30; + this.MonitorIntervalTime = 20; + //this.CustomTimedTaskAcquisitionMonitorIntervalTime = 5; + this.CustomWebApiIntervalTime = 10; + //this.CustomTimedTaskAcquisitionSendRobotNames = new List<string>(); + this.AppendComment = string.Empty; + #endregion + + #region 一键发送 + this.adzone_pid = string.Empty; + this.adzone_pid_cps_name = string.Empty; + this.adzone_name = string.Empty; + this.send_usernames = new List<string>(); + this.manually_send_usernames = new List<string>(); + this.send_templates = new List<ContentModel>() { new ContentModel() { ModelName = "默认模板", Content = @"╭┈┈┈┄┈┈┈┈┈╮ +爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +识别二维码复制口令下单,手慢无[茶] [茶] +喜爱不在等待,全网最优惠价格! +好产品多多看上的速度下手!" } }; + #endregion + + recordSendGoods = new Dictionary<string, List<string>>(); + + } + + } +} diff --git a/应用/Weixin.CircleTools/Entitys/fl_plugin_circletools_taskinfos.cs b/应用/Weixin.CircleTools/Entitys/fl_plugin_circletools_taskinfos.cs new file mode 100644 index 0000000..4d5274a --- /dev/null +++ b/应用/Weixin.CircleTools/Entitys/fl_plugin_circletools_taskinfos.cs @@ -0,0 +1,48 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static CircleFriendsTools.Enums; + +namespace Weixin.CircleTools.Entitys +{ + /// <summary> + /// 发送任务 + /// </summary> + public class fl_plugin_circletools_taskinfos : base_model + { + /// <summary> + /// 任务名称 + /// </summary> + public string task_name { get; set; } + + /// <summary> + /// 机器人robotnames,多个逗号分割 + /// </summary> + public string robotnames { get; set; } + + /// <summary> + /// 发送的工作日 + /// </summary> + public string task_working_day{get;set;} + /// <summary> + /// 发送的是时间 + /// </summary> + public string task_time { get; set; } + /// <summary> + /// 发送的内容 + /// </summary> + public string task_sendtext { get; set; } + /// <summary> + /// 追加的评语 + /// </summary> + public string task_comment { get; set; } + /// <summary> + /// 是否循环 + /// </summary> + public ChooseType is_circulate { get; set; } + + } +} diff --git a/应用/Weixin.CircleTools/Entitys/fl_plugin_circletools_tgw.cs b/应用/Weixin.CircleTools/Entitys/fl_plugin_circletools_tgw.cs new file mode 100644 index 0000000..2efc621 --- /dev/null +++ b/应用/Weixin.CircleTools/Entitys/fl_plugin_circletools_tgw.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.CircleTools.Entitys +{ + public class fl_plugin_circletools_tgw + { + /// <summary> + /// 左连接主表 fl_robot_info 的主键 + /// </summary> + public int robot_id { get; set; } + /// <summary> + /// 主推广位CPS名称 + /// </summary> + public string pid_cps_name { get; set; } + /// <summary> + /// 主推广位id + /// </summary> + public string pid { get; set; } + /// <summary> + /// 主推广位昵称 + /// </summary> + public string pid_name { get; set; } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/Weixin.CircleTools/Entitys/goodsinfos.cs b/应用/Weixin.CircleTools/Entitys/goodsinfos.cs new file mode 100644 index 0000000..59213b0 --- /dev/null +++ b/应用/Weixin.CircleTools/Entitys/goodsinfos.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.CircleTools.Entitys +{ + /// <summary> + /// 采集到的商品信息 + /// </summary> + public class goodsinfos + { + /// <summary> + /// 商品id + /// </summary> + public string goods_id { get; set; } + /// <summary> + /// 商品连接 + /// </summary> + public string goods_url { get; set; } + /// <summary> + /// 商品标题 + /// </summary> + public string goods_name { get; set; } + /// <summary> + /// 商品描述 + /// </summary> + public string goods_desc { get; set; } + /// <summary> + /// 商品图片链接 + /// </summary> + public string goods_thumbnail_url { get; set; } + /// <summary> + /// 已售卖件数 + /// </summary> + public int sold_quantity { get; set; } + /// <summary> + /// 商品单价,单位为元 + /// </summary> + public double normal_price { get; set; } + /// <summary> + /// 店铺名 + /// </summary> + public string mall_name { get; set; } + /// <summary> + /// 优惠券面额,单位为元 + /// </summary> + public double coupon_discount { get; set; } + /// <summary> + /// 优惠券剩余数量 + /// </summary> + public string coupon_remain_quantity { get; set; } + /// <summary> + /// 优惠券连接 + /// </summary> + public string coupon_url { get; set; } + /// <summary> + /// 佣金比例,百分比 + /// </summary> + public double promotion_rate { get; set; } + /// <summary> + /// 购买链接 转连之后 + /// </summary> + public string shopping_url { get; set; } + /// <summary> + /// 采集的日期 + /// </summary> + public DateTime cur_time { get; set; } + } +} diff --git a/应用/Weixin.CircleTools/Entitys/tbinfo_temp.cs b/应用/Weixin.CircleTools/Entitys/tbinfo_temp.cs new file mode 100644 index 0000000..d913994 --- /dev/null +++ b/应用/Weixin.CircleTools/Entitys/tbinfo_temp.cs @@ -0,0 +1,97 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.CircleTools.Entitys +{ + /// <summary> + /// 临时的表 (用于数据显示) + /// </summary> + public class tbinfo_temp + { + public long ID { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + + /// <summary> + /// 淘宝主推广位cps名称 + /// </summary> + private string _adzone_pid_cps_name { get; set; } + public string adzone_pid_cps_name + { + get { return _adzone_pid_cps_name; } + set { _adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _adzone_pid; + /// <summary> + /// taobao主推广位id + /// </summary> + public string adzone_pid + { + get { return _adzone_pid; } + set { _adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 淘宝主推广位昵称 + /// </summary> + private string _adzone_name; + + public string adzone_name + { + get { return _adzone_name; } + set { _adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + + //======= + + /// <summary> + /// 京东主推广位cps名称 + /// </summary> + private string _adzone_pid_cps_name_jd { get; set; } + public string adzone_pid_cps_name_jd + { + get { return _adzone_pid_cps_name_jd; } + set { _adzone_pid_cps_name_jd = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _adzone_pid_jd; + /// <summary> + /// 京东主推广位id + /// </summary> + public string adzone_pid_jd + { + get { return _adzone_pid_jd; } + set { _adzone_pid_jd = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 京东主推广位昵称 + /// </summary> + private string _adzone_name_jd; + + public string adzone_name_jd + { + get { return _adzone_name_jd; } + set { _adzone_name_jd = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/Enums.cs b/应用/Weixin.CircleTools/Enums.cs new file mode 100644 index 0000000..a51a4c8 --- /dev/null +++ b/应用/Weixin.CircleTools/Enums.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CircleFriendsTools +{ + public class Enums + { + public enum TransmitStyleType + { + 仅转发原文 = 0, + 原文及评论 = 1 + } + + public enum WorkingDayType + { + 周末 = 0, + 周一 = 1, + 周二 = 2, + 周三 = 3, + 周四 = 4, + 周五 = 5, + 周六 = 6 + } + + /// <summary> + /// 抉择类型 + /// </summary> + public enum ChooseType + { + 否 = 0, + 是 = 1 + } + + } +} diff --git a/应用/Weixin.CircleTools/ImageForm.Designer.cs b/应用/Weixin.CircleTools/ImageForm.Designer.cs new file mode 100644 index 0000000..ac295a2 --- /dev/null +++ b/应用/Weixin.CircleTools/ImageForm.Designer.cs @@ -0,0 +1,88 @@ +namespace Weixin.CircleTools +{ + partial class ImageForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(31, 22); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(84, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "网络图片地址:"; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(31, 42); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(486, 188); + this.memoEdit1.TabIndex = 1; + // + // labelControl2 + // + this.labelControl2.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl2.Appearance.Options.UseForeColor = true; + this.labelControl2.Location = new System.Drawing.Point(153, 22); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(106, 14); + this.labelControl2.TabIndex = 2; + this.labelControl2.Text = "(一行一个图片链接)"; + // + // ImageForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(548, 256); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.memoEdit1); + this.Controls.Add(this.labelControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ImageForm"; + this.Text = "ImageForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImageForm_FormClosing); + this.Load += new System.EventHandler(this.ImageForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/ImageForm.cs b/应用/Weixin.CircleTools/ImageForm.cs new file mode 100644 index 0000000..aecdb00 --- /dev/null +++ b/应用/Weixin.CircleTools/ImageForm.cs @@ -0,0 +1,41 @@ +using CircleFriendsTools; +using System; +using System.Windows.Forms; +using UI.Framework.Forms; +using Weixin.CircleTools.Properties; + +namespace Weixin.CircleTools +{ + public partial class ImageForm : BaseForm + { + public ImageForm() + { + InitializeComponent(); + this.Text = Resources.ImageForm; + } + + private void ImageForm_Load(object sender, EventArgs e) + { + try + { + memoEdit1.Text = Class1.Config.NetworkUrl; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void ImageForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.NetworkUrl = memoEdit1.Text; + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/ImageForm.resx b/应用/Weixin.CircleTools/ImageForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/Weixin.CircleTools/ImageForm.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/MainForm.Designer.cs b/应用/Weixin.CircleTools/MainForm.Designer.cs new file mode 100644 index 0000000..04e1ff6 --- /dev/null +++ b/应用/Weixin.CircleTools/MainForm.Designer.cs @@ -0,0 +1,1704 @@ +namespace CircleFriendsTools +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.memoEdit6 = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl26 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton4 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.linkLabel3 = new System.Windows.Forms.LinkLabel(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl21 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl17 = new DevExpress.XtraEditors.LabelControl(); + this.separatorControl2 = new DevExpress.XtraEditors.SeparatorControl(); + this.labelControl24 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl16 = new DevExpress.XtraEditors.LabelControl(); + this.buttonCheck1 = new UI.Framework.Controls.ButtonCheck(); + this.labelControl15 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl23 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.labelControl22 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit5 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.checkedComboBoxEdit2 = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.label12 = new System.Windows.Forms.Label(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraScrollableControl1 = new DevExpress.XtraEditors.XtraScrollableControl(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.buttonCheck2 = new UI.Framework.Controls.ButtonCheck(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl13 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl14 = new DevExpress.XtraEditors.LabelControl(); + this.numericUpDown3 = new System.Windows.Forms.NumericUpDown(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.labelControl25 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.hyperlinkLabelControl2 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.checkedComboBoxEdit1 = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.memoEdit2 = new DevExpress.XtraEditors.MemoEdit(); + this.label7 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.增加任务ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.修改选中ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.groupControl8 = new DevExpress.XtraEditors.GroupControl(); + this.memoEdit5 = new DevExpress.XtraEditors.MemoEdit(); + this.groupControl7 = new DevExpress.XtraEditors.GroupControl(); + this.button3 = new System.Windows.Forms.Button(); + this.button4 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.memoEdit4 = new DevExpress.XtraEditors.MemoEdit(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl6 = new DevExpress.XtraEditors.GroupControl(); + this.label_num = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除选中ToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl5 = new DevExpress.XtraEditors.GroupControl(); + this.linkLabel6 = new System.Windows.Forms.LinkLabel(); + this.linkLabel4 = new System.Windows.Forms.LinkLabel(); + this.button1 = new System.Windows.Forms.Button(); + this.memoEdit3 = new DevExpress.XtraEditors.MemoEdit(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.checkedComboBoxEdit_UsernameType = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.linkLabel5 = new System.Windows.Forms.LinkLabel(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); + this.toolTip_Pic = new System.Windows.Forms.ToolTip(this.components); + this.toolTip_Text = new System.Windows.Forms.ToolTip(this.components); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.xtraScrollableControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl8)).BeginInit(); + this.groupControl8.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl7)).BeginInit(); + this.groupControl7.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl6)).BeginInit(); + this.groupControl6.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl5)).BeginInit(); + this.groupControl5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_UsernameType.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.memoEdit6); + this.groupControl1.Controls.Add(this.labelControl26); + this.groupControl1.Controls.Add(this.simpleButton4); + this.groupControl1.Controls.Add(this.simpleButton3); + this.groupControl1.Controls.Add(this.linkLabel3); + this.groupControl1.Controls.Add(this.checkBox1); + this.groupControl1.Controls.Add(this.labelControl20); + this.groupControl1.Controls.Add(this.labelControl29); + this.groupControl1.Controls.Add(this.labelControl28); + this.groupControl1.Controls.Add(this.labelControl27); + this.groupControl1.Controls.Add(this.labelControl21); + this.groupControl1.Controls.Add(this.textEdit4); + this.groupControl1.Controls.Add(this.labelControl17); + this.groupControl1.Controls.Add(this.separatorControl2); + this.groupControl1.Controls.Add(this.labelControl24); + this.groupControl1.Controls.Add(this.labelControl16); + this.groupControl1.Controls.Add(this.buttonCheck1); + this.groupControl1.Controls.Add(this.labelControl15); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.labelControl23); + this.groupControl1.Controls.Add(this.labelControl6); + this.groupControl1.Controls.Add(this.labelControl5); + this.groupControl1.Controls.Add(this.labelControl3); + this.groupControl1.Controls.Add(this.numericUpDown1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Controls.Add(this.labelControl22); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.textEdit5); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Location = new System.Drawing.Point(30, 60); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(895, 366); + this.groupControl1.TabIndex = 0; + this.groupControl1.Text = " 朋友圈转发 "; + // + // memoEdit6 + // + this.memoEdit6.Location = new System.Drawing.Point(162, 203); + this.memoEdit6.Name = "memoEdit6"; + this.memoEdit6.Size = new System.Drawing.Size(447, 54); + this.memoEdit6.TabIndex = 45; + // + // labelControl26 + // + this.labelControl26.Location = new System.Drawing.Point(71, 204); + this.labelControl26.Name = "labelControl26"; + this.labelControl26.Size = new System.Drawing.Size(84, 14); + this.labelControl26.TabIndex = 44; + this.labelControl26.Text = "口令评语替换:"; + // + // simpleButton4 + // + this.simpleButton4.Location = new System.Drawing.Point(623, 316); + this.simpleButton4.Name = "simpleButton4"; + this.simpleButton4.Size = new System.Drawing.Size(96, 23); + this.simpleButton4.TabIndex = 43; + this.simpleButton4.Text = "立即获取"; + this.simpleButton4.Click += new System.EventHandler(this.simpleButton4_Click); + // + // simpleButton3 + // + this.simpleButton3.Location = new System.Drawing.Point(623, 79); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(96, 23); + this.simpleButton3.TabIndex = 43; + this.simpleButton3.Text = "立即检测朋友圈"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click_1); + // + // linkLabel3 + // + this.linkLabel3.AutoSize = true; + this.linkLabel3.Location = new System.Drawing.Point(388, 154); + this.linkLabel3.Name = "linkLabel3"; + this.linkLabel3.Size = new System.Drawing.Size(67, 14); + this.linkLabel3.TabIndex = 42; + this.linkLabel3.TabStop = true; + this.linkLabel3.Text = "设置推广位"; + this.linkLabel3.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel3_LinkClicked); + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.ForeColor = System.Drawing.Color.Blue; + this.checkBox1.Location = new System.Drawing.Point(162, 116); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(350, 18); + this.checkBox1.TabIndex = 41; + this.checkBox1.Text = "如果朋友圈内容中,评语区不包含自评信息,仍然继续转发!"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // labelControl20 + // + this.labelControl20.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl20.Appearance.Options.UseForeColor = true; + this.labelControl20.Location = new System.Drawing.Point(262, 292); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(46, 14); + this.labelControl20.TabIndex = 40; + this.labelControl20.Text = "(可为空)"; + // + // labelControl29 + // + this.labelControl29.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl29.Appearance.Options.UseForeColor = true; + this.labelControl29.Location = new System.Drawing.Point(656, 237); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(58, 14); + this.labelControl29.TabIndex = 40; + this.labelControl29.Text = "[转链口令]"; + this.labelControl29.Click += new System.EventHandler(this.labelControl29_Click); + // + // labelControl28 + // + this.labelControl28.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl28.Appearance.Options.UseForeColor = true; + this.labelControl28.Location = new System.Drawing.Point(621, 237); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(36, 14); + this.labelControl28.TabIndex = 40; + this.labelControl28.Text = "变量:"; + // + // labelControl27 + // + this.labelControl27.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl27.Appearance.Options.UseForeColor = true; + this.labelControl27.Location = new System.Drawing.Point(613, 204); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(259, 28); + this.labelControl27.TabIndex = 40; + this.labelControl27.Text = "(可为空,为空时转发原评语;\r\n 不为空,可添加[分段]变量实现多条自定义评语)"; + // + // labelControl21 + // + this.labelControl21.Location = new System.Drawing.Point(103, 292); + this.labelControl21.Name = "labelControl21"; + this.labelControl21.Size = new System.Drawing.Size(52, 14); + this.labelControl21.TabIndex = 39; + this.labelControl21.Text = "地址poi:"; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(162, 289); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(96, 20); + this.textEdit4.TabIndex = 38; + // + // labelControl17 + // + this.labelControl17.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl17.Appearance.Options.UseForeColor = true; + this.labelControl17.Location = new System.Drawing.Point(240, 154); + this.labelControl17.Name = "labelControl17"; + this.labelControl17.Size = new System.Drawing.Size(135, 14); + this.labelControl17.TabIndex = 37; + this.labelControl17.Text = "(评语中的淘/喵口令转连)"; + // + // separatorControl2 + // + this.separatorControl2.Location = new System.Drawing.Point(3, 265); + this.separatorControl2.Name = "separatorControl2"; + this.separatorControl2.Size = new System.Drawing.Size(888, 23); + this.separatorControl2.TabIndex = 36; + // + // labelControl24 + // + this.labelControl24.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl24.Appearance.Options.UseForeColor = true; + this.labelControl24.Location = new System.Drawing.Point(162, 344); + this.labelControl24.Name = "labelControl24"; + this.labelControl24.Size = new System.Drawing.Size(460, 14); + this.labelControl24.TabIndex = 34; + this.labelControl24.Text = "使用方法:该功能为发圈地址(内容可自定义)转发朋友圈的内容将有自己特有的标志!"; + // + // labelControl16 + // + this.labelControl16.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl16.Appearance.Options.UseForeColor = true; + this.labelControl16.Location = new System.Drawing.Point(473, 154); + this.labelControl16.Name = "labelControl16"; + this.labelControl16.Size = new System.Drawing.Size(396, 14); + this.labelControl16.TabIndex = 34; + this.labelControl16.Text = "使用方法:该功能启用时,机器人将会自动把评语区的自评淘口令转为自己的!"; + // + // buttonCheck1 + // + this.buttonCheck1.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck1.Checked = false; + this.buttonCheck1.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck1.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck1.Location = new System.Drawing.Point(163, 150); + this.buttonCheck1.Name = "buttonCheck1"; + this.buttonCheck1.Size = new System.Drawing.Size(59, 22); + this.buttonCheck1.TabIndex = 33; + this.buttonCheck1.Click += new System.EventHandler(this.buttonCheck1_Click); + // + // labelControl15 + // + this.labelControl15.Location = new System.Drawing.Point(95, 154); + this.labelControl15.Name = "labelControl15"; + this.labelControl15.Size = new System.Drawing.Size(60, 14); + this.labelControl15.TabIndex = 32; + this.labelControl15.Text = "自动转连:"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(622, 39); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(96, 23); + this.simpleButton1.TabIndex = 7; + this.simpleButton1.Text = "检测是否为好友"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl23 + // + this.labelControl23.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl23.Appearance.Options.UseForeColor = true; + this.labelControl23.Location = new System.Drawing.Point(447, 320); + this.labelControl23.Name = "labelControl23"; + this.labelControl23.Size = new System.Drawing.Size(154, 14); + this.labelControl23.TabIndex = 6; + this.labelControl23.Text = "(好友的微信id [日志中的id] )"; + // + // labelControl6 + // + this.labelControl6.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl6.Appearance.Options.UseForeColor = true; + this.labelControl6.Location = new System.Drawing.Point(446, 43); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(154, 14); + this.labelControl6.TabIndex = 6; + this.labelControl6.Text = "(好友的微信id [日志中的id] )"; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(518, 83); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(62, 14); + this.labelControl5.TabIndex = 5; + this.labelControl5.Text = "(单位,分钟)"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(376, 83); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 3; + this.labelControl3.Text = "检测间隔:"; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(438, 79); + this.numericUpDown1.Maximum = new decimal(new int[] { + 1440, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(68, 22); + this.numericUpDown1.TabIndex = 4; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(95, 83); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 3; + this.labelControl2.Text = "转发类型:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(162, 80); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(103, 20); + this.comboBoxEdit1.TabIndex = 2; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // labelControl22 + // + this.labelControl22.Location = new System.Drawing.Point(110, 320); + this.labelControl22.Name = "labelControl22"; + this.labelControl22.Size = new System.Drawing.Size(45, 14); + this.labelControl22.TabIndex = 1; + this.labelControl22.Text = "微信id:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(95, 43); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 1; + this.labelControl1.Text = "转发账号:"; + // + // textEdit5 + // + this.textEdit5.Location = new System.Drawing.Point(162, 317); + this.textEdit5.Name = "textEdit5"; + this.textEdit5.Size = new System.Drawing.Size(266, 20); + this.textEdit5.TabIndex = 0; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(161, 40); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(266, 20); + this.textEdit1.TabIndex = 0; + // + // checkedComboBoxEdit2 + // + this.checkedComboBoxEdit2.EditValue = ""; + this.checkedComboBoxEdit2.Location = new System.Drawing.Point(193, 19); + this.checkedComboBoxEdit2.Name = "checkedComboBoxEdit2"; + this.checkedComboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit2.Size = new System.Drawing.Size(447, 20); + this.checkedComboBoxEdit2.TabIndex = 45; + // + // label12 + // + this.label12.AutoSize = true; + this.label12.Location = new System.Drawing.Point(90, 22); + this.label12.Name = "label12"; + this.label12.Size = new System.Drawing.Size(91, 14); + this.label12.TabIndex = 44; + this.label12.Text = "选择转发微信:"; + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(959, 687); + this.xtraTabControl1.TabIndex = 2; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3, + this.xtraTabPage4}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.xtraScrollableControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(957, 663); + this.xtraTabPage1.Text = " 应 用 设 置 "; + // + // xtraScrollableControl1 + // + this.xtraScrollableControl1.Controls.Add(this.label12); + this.xtraScrollableControl1.Controls.Add(this.groupControl1); + this.xtraScrollableControl1.Controls.Add(this.checkedComboBoxEdit2); + this.xtraScrollableControl1.Controls.Add(this.groupControl3); + this.xtraScrollableControl1.Controls.Add(this.groupControl2); + this.xtraScrollableControl1.Controls.Add(this.labelControl30); + this.xtraScrollableControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraScrollableControl1.Location = new System.Drawing.Point(0, 0); + this.xtraScrollableControl1.Name = "xtraScrollableControl1"; + this.xtraScrollableControl1.Size = new System.Drawing.Size(957, 663); + this.xtraScrollableControl1.TabIndex = 4; + // + // groupControl3 + // + this.groupControl3.Controls.Add(this.labelControl12); + this.groupControl3.Controls.Add(this.numericUpDown2); + this.groupControl3.Controls.Add(this.labelControl11); + this.groupControl3.Controls.Add(this.buttonCheck2); + this.groupControl3.Controls.Add(this.labelControl10); + this.groupControl3.Location = new System.Drawing.Point(30, 553); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(895, 85); + this.groupControl3.TabIndex = 3; + this.groupControl3.Text = " 朋友圈点赞 "; + // + // labelControl12 + // + this.labelControl12.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl12.Appearance.Options.UseForeColor = true; + this.labelControl12.Location = new System.Drawing.Point(592, 44); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(62, 14); + this.labelControl12.TabIndex = 34; + this.labelControl12.Text = "(单位,分钟)"; + // + // numericUpDown2 + // + this.numericUpDown2.Location = new System.Drawing.Point(518, 40); + this.numericUpDown2.Maximum = new decimal(new int[] { + 14400, + 0, + 0, + 0}); + this.numericUpDown2.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(68, 22); + this.numericUpDown2.TabIndex = 33; + this.numericUpDown2.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl11 + // + this.labelControl11.Location = new System.Drawing.Point(405, 44); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(108, 14); + this.labelControl11.TabIndex = 32; + this.labelControl11.Text = "刷新首页间隔时间:"; + // + // buttonCheck2 + // + this.buttonCheck2.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck2.Checked = false; + this.buttonCheck2.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck2.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck2.Location = new System.Drawing.Point(163, 38); + this.buttonCheck2.Name = "buttonCheck2"; + this.buttonCheck2.Size = new System.Drawing.Size(59, 22); + this.buttonCheck2.TabIndex = 31; + // + // labelControl10 + // + this.labelControl10.Location = new System.Drawing.Point(95, 42); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(60, 14); + this.labelControl10.TabIndex = 2; + this.labelControl10.Text = "自动点赞:"; + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.labelControl13); + this.groupControl2.Controls.Add(this.labelControl14); + this.groupControl2.Controls.Add(this.numericUpDown3); + this.groupControl2.Controls.Add(this.labelControl9); + this.groupControl2.Controls.Add(this.labelControl4); + this.groupControl2.Controls.Add(this.textEdit2); + this.groupControl2.Location = new System.Drawing.Point(30, 437); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(895, 103); + this.groupControl2.TabIndex = 2; + this.groupControl2.Text = " 接口转发 "; + // + // labelControl13 + // + this.labelControl13.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl13.Appearance.Options.UseForeColor = true; + this.labelControl13.Location = new System.Drawing.Point(770, 40); + this.labelControl13.Name = "labelControl13"; + this.labelControl13.Size = new System.Drawing.Size(50, 14); + this.labelControl13.TabIndex = 9; + this.labelControl13.Text = "(单位,分)"; + // + // labelControl14 + // + this.labelControl14.Location = new System.Drawing.Point(631, 40); + this.labelControl14.Name = "labelControl14"; + this.labelControl14.Size = new System.Drawing.Size(60, 14); + this.labelControl14.TabIndex = 7; + this.labelControl14.Text = "检测间隔:"; + // + // numericUpDown3 + // + this.numericUpDown3.Location = new System.Drawing.Point(696, 36); + this.numericUpDown3.Maximum = new decimal(new int[] { + 60, + 0, + 0, + 0}); + this.numericUpDown3.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown3.Name = "numericUpDown3"; + this.numericUpDown3.Size = new System.Drawing.Size(68, 22); + this.numericUpDown3.TabIndex = 8; + this.numericUpDown3.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // labelControl9 + // + this.labelControl9.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl9.Appearance.Options.UseForeColor = true; + this.labelControl9.Location = new System.Drawing.Point(162, 64); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(628, 14); + this.labelControl9.TabIndex = 6; + this.labelControl9.Text = "使用方法:此接口自行开发,返回什么数据,机器人就发送什么,一定要带图片! 评语区内容用[评语]分割,多个评语用[分段]"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(95, 40); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(60, 14); + this.labelControl4.TabIndex = 5; + this.labelControl4.Text = "接口地址:"; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(162, 37); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(447, 20); + this.textEdit2.TabIndex = 2; + // + // labelControl30 + // + this.labelControl30.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl30.Appearance.Options.UseForeColor = true; + this.labelControl30.Location = new System.Drawing.Point(666, 22); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(134, 14); + this.labelControl30.TabIndex = 6; + this.labelControl30.Text = "(未选择,所有微信都转发)"; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.groupBox1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(957, 663); + this.xtraTabPage2.Text = " 手 动 发 送 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl25); + this.groupBox1.Controls.Add(this.memoEdit1); + this.groupBox1.Controls.Add(this.hyperlinkLabelControl2); + this.groupBox1.Controls.Add(this.hyperlinkLabelControl1); + this.groupBox1.Controls.Add(this.checkedComboBoxEdit1); + this.groupBox1.Controls.Add(this.labelControl7); + this.groupBox1.Controls.Add(this.labelControl8); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.memoEdit2); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.label10); + this.groupBox1.Controls.Add(this.label11); + this.groupBox1.Location = new System.Drawing.Point(72, 41); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(813, 575); + this.groupBox1.TabIndex = 34; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // labelControl25 + // + this.labelControl25.Location = new System.Drawing.Point(116, 50); + this.labelControl25.Name = "labelControl25"; + this.labelControl25.Size = new System.Drawing.Size(84, 14); + this.labelControl25.TabIndex = 34; + this.labelControl25.Text = "选择转发微信:"; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(76, 117); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(672, 213); + this.memoEdit1.TabIndex = 27; + // + // hyperlinkLabelControl2 + // + this.hyperlinkLabelControl2.Location = new System.Drawing.Point(544, 97); + this.hyperlinkLabelControl2.Name = "hyperlinkLabelControl2"; + this.hyperlinkLabelControl2.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl2.TabIndex = 31; + this.hyperlinkLabelControl2.Text = "[插入网络图]"; + this.hyperlinkLabelControl2.Click += new System.EventHandler(this.hyperlinkLabelControl2_Click); + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(451, 97); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(70, 14); + this.hyperlinkLabelControl1.TabIndex = 31; + this.hyperlinkLabelControl1.Text = "[插入本地图]"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // checkedComboBoxEdit1 + // + this.checkedComboBoxEdit1.EditValue = ""; + this.checkedComboBoxEdit1.Location = new System.Drawing.Point(217, 47); + this.checkedComboBoxEdit1.Name = "checkedComboBoxEdit1"; + this.checkedComboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit1.Size = new System.Drawing.Size(458, 20); + this.checkedComboBoxEdit1.TabIndex = 33; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(87, 97); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(60, 14); + this.labelControl7.TabIndex = 22; + this.labelControl7.Text = "推送内容:"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(87, 346); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(60, 14); + this.labelControl8.TabIndex = 23; + this.labelControl8.Text = "追加评论:"; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(291, 492); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(242, 48); + this.simpleButton2.TabIndex = 24; + this.simpleButton2.Text = " 立 即 推 送 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // memoEdit2 + // + this.memoEdit2.Location = new System.Drawing.Point(76, 366); + this.memoEdit2.Name = "memoEdit2"; + this.memoEdit2.Size = new System.Drawing.Size(672, 111); + this.memoEdit2.TabIndex = 28; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(155, 346); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(269, 14); + this.label7.TabIndex = 30; + this.label7.Text = "注:多条评语 [分段] 分割 "; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.ForeColor = System.Drawing.Color.Red; + this.label10.Location = new System.Drawing.Point(153, 97); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(14, 14); + this.label10.TabIndex = 29; + this.label10.Text = "*"; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(173, 97); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(239, 14); + this.label11.TabIndex = 30; + this.label11.Text = "注:发送内容中必须要添加一张图片 "; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.label1); + this.xtraTabPage3.Controls.Add(this.gridControl1); + this.xtraTabPage3.Controls.Add(this.pageControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(957, 663); + this.xtraTabPage3.Text = " 定 时 推 送 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(262, 202); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(429, 35); + this.label1.TabIndex = 15; + this.label1.Text = "尚未有任务,右击进行增加"; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(957, 626); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.增加任务ToolStripMenuItem, + this.修改选中ToolStripMenuItem, + this.删除选中ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 70); + // + // 增加任务ToolStripMenuItem + // + this.增加任务ToolStripMenuItem.Name = "增加任务ToolStripMenuItem"; + this.增加任务ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.增加任务ToolStripMenuItem.Text = "增加任务"; + this.增加任务ToolStripMenuItem.Click += new System.EventHandler(this.增加任务ToolStripMenuItem_Click); + // + // 修改选中ToolStripMenuItem + // + this.修改选中ToolStripMenuItem.Name = "修改选中ToolStripMenuItem"; + this.修改选中ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.修改选中ToolStripMenuItem.Text = "修改选中"; + this.修改选中ToolStripMenuItem.Click += new System.EventHandler(this.修改选中ToolStripMenuItem_Click); + // + // 删除选中ToolStripMenuItem + // + this.删除选中ToolStripMenuItem.Name = "删除选中ToolStripMenuItem"; + this.删除选中ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.删除选中ToolStripMenuItem.Text = "删除选中"; + this.删除选中ToolStripMenuItem.Click += new System.EventHandler(this.删除选中ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4, + this.gridColumn6, + this.gridColumn13, + this.gridColumn5, + this.gridColumn14}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "任务ID"; + this.gridColumn1.FieldName = "id"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Width = 46; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "任务名称"; + this.gridColumn2.FieldName = "task_name"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 0; + this.gridColumn2.Width = 85; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "任务工作日"; + this.gridColumn3.FieldName = "task_working_day"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 1; + this.gridColumn3.Width = 134; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn4.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "发送时间点"; + this.gridColumn4.FieldName = "task_time"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 2; + this.gridColumn4.Width = 80; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn6.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "发送内容"; + this.gridColumn6.FieldName = "task_sendtext"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 3; + this.gridColumn6.Width = 186; + // + // gridColumn13 + // + this.gridColumn13.Caption = "评语内容"; + this.gridColumn13.FieldName = "task_comment"; + this.gridColumn13.Name = "gridColumn13"; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn5.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "是否循环"; + this.gridColumn5.FieldName = "is_circulate"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + this.gridColumn5.Width = 56; + // + // gridColumn14 + // + this.gridColumn14.Caption = "发送账号"; + this.gridColumn14.FieldName = "robotnames"; + this.gridColumn14.Name = "gridColumn14"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 630); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(957, 33); + this.pageControl1.TabIndex = 0; + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.panelControl1); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(957, 663); + this.xtraTabPage4.Text = "一 键 发 送"; + // + // panelControl1 + // + this.panelControl1.Controls.Add(this.groupControl8); + this.panelControl1.Controls.Add(this.groupControl7); + this.panelControl1.Controls.Add(this.groupControl6); + this.panelControl1.Controls.Add(this.groupControl5); + this.panelControl1.Controls.Add(this.groupControl4); + this.panelControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panelControl1.Location = new System.Drawing.Point(0, 0); + this.panelControl1.Name = "panelControl1"; + this.panelControl1.Size = new System.Drawing.Size(957, 663); + this.panelControl1.TabIndex = 0; + // + // groupControl8 + // + this.groupControl8.Controls.Add(this.memoEdit5); + this.groupControl8.Location = new System.Drawing.Point(18, 427); + this.groupControl8.Name = "groupControl8"; + this.groupControl8.Size = new System.Drawing.Size(919, 80); + this.groupControl8.TabIndex = 17; + this.groupControl8.Text = "第四步、追加评论: 变量:[分段]"; + // + // memoEdit5 + // + this.memoEdit5.Dock = System.Windows.Forms.DockStyle.Fill; + this.memoEdit5.Location = new System.Drawing.Point(2, 23); + this.memoEdit5.Name = "memoEdit5"; + this.memoEdit5.Size = new System.Drawing.Size(915, 55); + this.memoEdit5.TabIndex = 10; + // + // groupControl7 + // + this.groupControl7.Controls.Add(this.button3); + this.groupControl7.Controls.Add(this.button4); + this.groupControl7.Controls.Add(this.button2); + this.groupControl7.Controls.Add(this.memoEdit4); + this.groupControl7.Controls.Add(this.gridControl3); + this.groupControl7.Location = new System.Drawing.Point(18, 513); + this.groupControl7.Name = "groupControl7"; + this.groupControl7.Size = new System.Drawing.Size(919, 126); + this.groupControl7.TabIndex = 16; + this.groupControl7.Text = "第五步、确认模板:"; + // + // button3 + // + this.button3.Location = new System.Drawing.Point(756, 89); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(140, 31); + this.button3.TabIndex = 20; + this.button3.Text = "添加至自动推送"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // button4 + // + this.button4.Location = new System.Drawing.Point(756, 55); + this.button4.Name = "button4"; + this.button4.Size = new System.Drawing.Size(140, 31); + this.button4.TabIndex = 20; + this.button4.Text = "编辑文本"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(756, 21); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(140, 31); + this.button2.TabIndex = 18; + this.button2.Text = "立即发布"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // memoEdit4 + // + this.memoEdit4.Location = new System.Drawing.Point(332, 21); + this.memoEdit4.Name = "memoEdit4"; + this.memoEdit4.Properties.ReadOnly = true; + this.memoEdit4.Size = new System.Drawing.Size(403, 99); + this.memoEdit4.TabIndex = 17; + // + // gridControl3 + // + this.gridControl3.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl3.Dock = System.Windows.Forms.DockStyle.Left; + this.gridControl3.Location = new System.Drawing.Point(2, 23); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.Size = new System.Drawing.Size(324, 101); + this.gridControl3.TabIndex = 16; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // gridView3 + // + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn12}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsView.ShowGroupPanel = false; + this.gridView3.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView3_RowCellClick); + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn12.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "名称"; + this.gridColumn12.FieldName = "ModelName"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 0; + this.gridColumn12.Width = 335; + // + // groupControl6 + // + this.groupControl6.Controls.Add(this.label_num); + this.groupControl6.Controls.Add(this.label6); + this.groupControl6.Controls.Add(this.gridControl2); + this.groupControl6.Location = new System.Drawing.Point(18, 264); + this.groupControl6.Name = "groupControl6"; + this.groupControl6.Size = new System.Drawing.Size(919, 157); + this.groupControl6.TabIndex = 15; + this.groupControl6.Text = "第三步、确认商品:"; + // + // label_num + // + this.label_num.AutoSize = true; + this.label_num.Location = new System.Drawing.Point(508, 4); + this.label_num.Name = "label_num"; + this.label_num.Size = new System.Drawing.Size(14, 14); + this.label_num.TabIndex = 18; + this.label_num.Text = "0"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.ForeColor = System.Drawing.Color.Maroon; + this.label6.Location = new System.Drawing.Point(384, 4); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(127, 14); + this.label6.TabIndex = 17; + this.label6.Text = "当前已添加文案数量:"; + // + // gridControl2 + // + this.gridControl2.ContextMenuStrip = this.contextMenuStrip; + this.gridControl2.Dock = System.Windows.Forms.DockStyle.Fill; + this.gridControl2.Location = new System.Drawing.Point(2, 23); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(915, 132); + this.gridControl2.TabIndex = 16; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip + // + this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中ToolStripMenuItem1}); + this.contextMenuStrip.Name = "contextMenuStrip"; + this.contextMenuStrip.Size = new System.Drawing.Size(125, 26); + // + // 删除选中ToolStripMenuItem1 + // + this.删除选中ToolStripMenuItem1.Name = "删除选中ToolStripMenuItem1"; + this.删除选中ToolStripMenuItem1.Size = new System.Drawing.Size(124, 22); + this.删除选中ToolStripMenuItem1.Text = "删除选中"; + this.删除选中ToolStripMenuItem1.Click += new System.EventHandler(this.删除选中ToolStripMenuItem1_Click); + // + // gridView2 + // + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn7, + this.gridColumn8, + this.gridColumn9, + this.gridColumn10, + this.gridColumn11}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn7.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "宝贝标题"; + this.gridColumn7.FieldName = "goods_name"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 0; + this.gridColumn7.Width = 335; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn8.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "原价"; + this.gridColumn8.FieldName = "price"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 1; + this.gridColumn8.Width = 52; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn9.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "券后价"; + this.gridColumn9.FieldName = "final_price"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.OptionsColumn.AllowFocus = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 2; + this.gridColumn9.Width = 57; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn10.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "返利"; + this.gridColumn10.FieldName = "rebate"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 3; + this.gridColumn10.Width = 46; + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn11.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "比例"; + this.gridColumn11.FieldName = "rate"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.OptionsColumn.AllowEdit = false; + this.gridColumn11.OptionsColumn.AllowFocus = false; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 4; + this.gridColumn11.Width = 57; + // + // groupControl5 + // + this.groupControl5.Controls.Add(this.linkLabel6); + this.groupControl5.Controls.Add(this.linkLabel4); + this.groupControl5.Controls.Add(this.button1); + this.groupControl5.Controls.Add(this.memoEdit3); + this.groupControl5.Controls.Add(this.textBox3); + this.groupControl5.Controls.Add(this.label4); + this.groupControl5.Controls.Add(this.label5); + this.groupControl5.Location = new System.Drawing.Point(18, 141); + this.groupControl5.Name = "groupControl5"; + this.groupControl5.Size = new System.Drawing.Size(919, 116); + this.groupControl5.TabIndex = 14; + this.groupControl5.Text = "第二步、商品转换:"; + // + // linkLabel6 + // + this.linkLabel6.AutoSize = true; + this.linkLabel6.Font = new System.Drawing.Font("Tahoma", 12F); + this.linkLabel6.Location = new System.Drawing.Point(657, 83); + this.linkLabel6.Name = "linkLabel6"; + this.linkLabel6.Size = new System.Drawing.Size(25, 19); + this.linkLabel6.TabIndex = 14; + this.linkLabel6.TabStop = true; + this.linkLabel6.Text = "?"; + this.linkLabel6.MouseHover += new System.EventHandler(this.linkLabel6_MouseHover); + // + // linkLabel4 + // + this.linkLabel4.AutoSize = true; + this.linkLabel4.Font = new System.Drawing.Font("Tahoma", 12F); + this.linkLabel4.Location = new System.Drawing.Point(657, 43); + this.linkLabel4.Name = "linkLabel4"; + this.linkLabel4.Size = new System.Drawing.Size(25, 19); + this.linkLabel4.TabIndex = 13; + this.linkLabel4.TabStop = true; + this.linkLabel4.Text = "?"; + this.linkLabel4.MouseHover += new System.EventHandler(this.linkLabel4_MouseHover); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(704, 36); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(107, 67); + this.button1.TabIndex = 11; + this.button1.Text = "添加列表\r\n"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // memoEdit3 + // + this.memoEdit3.Location = new System.Drawing.Point(199, 35); + this.memoEdit3.Name = "memoEdit3"; + this.memoEdit3.Size = new System.Drawing.Size(452, 34); + this.memoEdit3.TabIndex = 10; + this.memoEdit3.Click += new System.EventHandler(this.memoEdit3_Click); + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(199, 81); + this.textBox3.Name = "textBox3"; + this.textBox3.Size = new System.Drawing.Size(452, 22); + this.textBox3.TabIndex = 8; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(136, 84); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 14); + this.label4.TabIndex = 6; + this.label4.Text = "指定图片:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(136, 45); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(67, 14); + this.label5.TabIndex = 5; + this.label5.Text = "粘贴文案:"; + // + // groupControl4 + // + this.groupControl4.Controls.Add(this.comboBox1); + this.groupControl4.Controls.Add(this.checkedComboBoxEdit_UsernameType); + this.groupControl4.Controls.Add(this.linkLabel5); + this.groupControl4.Controls.Add(this.textBox1); + this.groupControl4.Controls.Add(this.label8); + this.groupControl4.Controls.Add(this.label3); + this.groupControl4.Controls.Add(this.label2); + this.groupControl4.Location = new System.Drawing.Point(18, 17); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(919, 117); + this.groupControl4.TabIndex = 13; + this.groupControl4.Text = "第一步、PID设置:"; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "模板A", + "模板B"}); + this.comboBox1.Location = new System.Drawing.Point(233, 84); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(167, 22); + this.comboBox1.TabIndex = 11; + // + // checkedComboBoxEdit_UsernameType + // + this.checkedComboBoxEdit_UsernameType.EditValue = ""; + this.checkedComboBoxEdit_UsernameType.Location = new System.Drawing.Point(233, 60); + this.checkedComboBoxEdit_UsernameType.Name = "checkedComboBoxEdit_UsernameType"; + this.checkedComboBoxEdit_UsernameType.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit_UsernameType.Size = new System.Drawing.Size(418, 20); + this.checkedComboBoxEdit_UsernameType.TabIndex = 10; + this.checkedComboBoxEdit_UsernameType.EditValueChanged += new System.EventHandler(this.checkedComboBoxEdit_UsernameType_EditValueChanged); + // + // linkLabel5 + // + this.linkLabel5.AutoSize = true; + this.linkLabel5.Location = new System.Drawing.Point(683, 38); + this.linkLabel5.Name = "linkLabel5"; + this.linkLabel5.Size = new System.Drawing.Size(67, 14); + this.linkLabel5.TabIndex = 9; + this.linkLabel5.TabStop = true; + this.linkLabel5.Text = "设置推广位"; + this.linkLabel5.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel5_LinkClicked); + // + // textBox1 + // + this.textBox1.Enabled = false; + this.textBox1.Location = new System.Drawing.Point(233, 34); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(418, 22); + this.textBox1.TabIndex = 7; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(124, 87); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(103, 14); + this.label8.TabIndex = 6; + this.label8.Text = "选择二维码模板:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(136, 63); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(91, 14); + this.label3.TabIndex = 6; + this.label3.Text = "选择转发微信:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(136, 38); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(91, 14); + this.label2.TabIndex = 5; + this.label2.Text = "朋友圈推广位:"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(959, 687); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit6.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraScrollableControl1.ResumeLayout(false); + this.xtraScrollableControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + this.groupControl3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit2.Properties)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraTabPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl8)).EndInit(); + this.groupControl8.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl7)).EndInit(); + this.groupControl7.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl6)).EndInit(); + this.groupControl6.ResumeLayout(false); + this.groupControl6.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl5)).EndInit(); + this.groupControl5.ResumeLayout(false); + this.groupControl5.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + this.groupControl4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_UsernameType.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraEditors.MemoEdit memoEdit2; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.GroupControl groupControl3; + private DevExpress.XtraEditors.LabelControl labelControl9; + private DevExpress.XtraEditors.LabelControl labelControl10; + private UI.Framework.Controls.ButtonCheck buttonCheck2; + private DevExpress.XtraEditors.LabelControl labelControl11; + private DevExpress.XtraEditors.LabelControl labelControl12; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private DevExpress.XtraEditors.LabelControl labelControl13; + private DevExpress.XtraEditors.LabelControl labelControl14; + private System.Windows.Forms.NumericUpDown numericUpDown3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 增加任务ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 修改选中ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中ToolStripMenuItem; + private UI.Framework.Controls.ButtonCheck buttonCheck1; + private DevExpress.XtraEditors.LabelControl labelControl15; + private DevExpress.XtraEditors.LabelControl labelControl16; + private DevExpress.XtraEditors.LabelControl labelControl17; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.LinkLabel linkLabel3; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private System.ComponentModel.BackgroundWorker backgroundWorker1; + private System.Windows.Forms.ToolTip toolTip_Pic; + private System.Windows.Forms.ToolTip toolTip_Text; + private DevExpress.XtraEditors.PanelControl panelControl1; + private DevExpress.XtraEditors.GroupControl groupControl5; + private System.Windows.Forms.LinkLabel linkLabel6; + private System.Windows.Forms.LinkLabel linkLabel4; + private System.Windows.Forms.Button button1; + private DevExpress.XtraEditors.MemoEdit memoEdit3; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private DevExpress.XtraEditors.GroupControl groupControl4; + private System.Windows.Forms.LinkLabel linkLabel5; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.GroupControl groupControl6; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraEditors.GroupControl groupControl7; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private System.Windows.Forms.Button button2; + private DevExpress.XtraEditors.MemoEdit memoEdit4; + private System.Windows.Forms.Button button4; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit_UsernameType; + private System.Windows.Forms.ToolStripMenuItem 删除选中ToolStripMenuItem1; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label_num; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private System.Windows.Forms.Label label7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraEditors.LabelControl labelControl20; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.SeparatorControl separatorControl2; + private DevExpress.XtraEditors.LabelControl labelControl21; + private DevExpress.XtraEditors.SimpleButton simpleButton4; + private DevExpress.XtraEditors.LabelControl labelControl22; + private DevExpress.XtraEditors.TextEdit textEdit5; + private DevExpress.XtraEditors.LabelControl labelControl24; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label10; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.GroupControl groupControl8; + private DevExpress.XtraEditors.MemoEdit memoEdit5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private System.Windows.Forms.Button button3; + private DevExpress.XtraEditors.XtraScrollableControl xtraScrollableControl1; + private DevExpress.XtraEditors.LabelControl labelControl23; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit2; + private System.Windows.Forms.Label label12; + private DevExpress.XtraEditors.LabelControl labelControl25; + private DevExpress.XtraEditors.LabelControl labelControl26; + private DevExpress.XtraEditors.MemoEdit memoEdit6; + private DevExpress.XtraEditors.LabelControl labelControl27; + private DevExpress.XtraEditors.LabelControl labelControl28; + private DevExpress.XtraEditors.LabelControl labelControl29; + private DevExpress.XtraEditors.LabelControl labelControl30; + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/MainForm.cs b/应用/Weixin.CircleTools/MainForm.cs new file mode 100644 index 0000000..d7c6b7c --- /dev/null +++ b/应用/Weixin.CircleTools/MainForm.cs @@ -0,0 +1,948 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.Utils; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using Weixin.CircleTools; +using Weixin.CircleTools.Entitys; +using Weixin.CircleTools.Properties; +using static Api.Framework.ApiClient; +using static CircleFriendsTools.Enums; +using ChooseType = CircleFriendsTools.Enums.ChooseType; + +namespace CircleFriendsTools +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + #region 任务列表展示 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<fl_plugin_circletools_taskinfos>("select * from fl_plugin_circletools_taskinfos", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label1.Visible = gridView1.RowCount == 0; + + #endregion + + #region 控件赋值 + foreach (TransmitStyleType item in Enum.GetValues(typeof(TransmitStyleType))) + { + this.comboBoxEdit1.Properties.Items.Add(item.ToString()); + } + this.comboBoxEdit1.SelectedIndex = (int)Class1.Config.TransmitStyle; + this.textEdit4.Text = Class1.Config.LocationContent; + this.textEdit5.Text = Class1.Config.GatherPoiCrowd; + this.textEdit1.Text = Class1.Config.MonitorCrowd; + this.numericUpDown1.Value = Class1.Config.MonitorIntervalTime; + this.textEdit2.Text = Class1.Config.CustomWebApi; + this.buttonCheck2.Checked = Class1.Config.AutoPraise; + this.numericUpDown2.Value = Class1.Config.AutoPraiseInterval; + this.numericUpDown3.Value = Class1.Config.CustomWebApiIntervalTime; + this.buttonCheck1.Checked = linkLabel3.Enabled = Class1.Config.AutoTurn; + this.checkBox1.Checked = Class1.Config.Turn_Obstinate; + this.memoEdit6.Text = Class1.Config.AppendComment; + + var adzone = ApiClient.GetSession().FindAdzoneInfos().FirstOrDefault(f => f.custom_type == Resources.NonautomaticSoftwareType && f.alliance_id == (int)CpsType.阿里妈妈); + if (adzone != null) + textBox1.Text = adzone.adzone_name; + #endregion + + #region 将enum的值加载到列表中 修改的将勾选 + var clients = Chat.Framework.ChatClient.WXClient; + foreach (var client in clients.Values) + { + if ((client.WeixinType == WeixinType.Grpc微信 || client.WeixinType == WeixinType.Hook微信) && client.Status == WxStatus.在线) + { + if (Class1.Config.send_usernames.Select(f => f.Trim()).Contains(client.WeixinHao.Trim())) + checkedComboBoxEdit_UsernameType.Properties.Items.Add(client.WeixinHao, client.User.Nick.ToString(), CheckState.Checked, true); + else + checkedComboBoxEdit_UsernameType.Properties.Items.Add(client.WeixinHao, client.User.Nick.ToString(), CheckState.Unchecked, true); + + if (Class1.Config.manually_send_usernames.Contains(client.WeixinHao.Trim())) + checkedComboBoxEdit1.Properties.Items.Add(client.WeixinHao, client.User.Nick.ToString(), CheckState.Checked, true); + else + checkedComboBoxEdit1.Properties.Items.Add(client.WeixinHao, client.User.Nick.ToString(), CheckState.Unchecked, true); + + if (Class1.Config.transpond_send_usernames.Contains(client.WeixinHao.Trim())) + checkedComboBoxEdit2.Properties.Items.Add(client.WeixinHao, client.User.Nick.ToString(), CheckState.Checked, true); + else + checkedComboBoxEdit2.Properties.Items.Add(client.WeixinHao, client.User.Nick.ToString(), CheckState.Unchecked, true); + + } + } + #endregion + + comboBox1.SelectedIndex = (int)Class1.Config.qrImage; + + ShowContentModel(); + } + catch (Exception ex) + { + ShowError(ex); + } + + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (!string.IsNullOrWhiteSpace(textEdit2.Text) && !Regex.IsMatch(textEdit2.Text.Replace("&", "&"), CsharpHttpHelper.HttpExtend.REGEX_GETURL, RegexOptions.IgnoreCase)) + { + if (MessageBox.Show("系统监听的链接不合法,是否继续保存?", "系统提示", MessageBoxButtons.YesNo) == DialogResult.No) + e.Cancel = true; + else + textEdit2.Text = string.Empty; + } + + Class1.Config.send_usernames = checkedComboBoxEdit_UsernameType.Properties.GetCheckedItems().ToString().Replace(", ", ",").Replace(" ,", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + Class1.Config.manually_send_usernames = checkedComboBoxEdit1.Properties.GetCheckedItems().ToString().Replace(", ", ",").Replace(" ,", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + Class1.Config.transpond_send_usernames = checkedComboBoxEdit2.Properties.GetCheckedItems().ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + if (!e.Cancel) + { + tokenSource.Cancel(); + Class1.Config.TransmitStyle = (TransmitStyleType)Enum.ToObject(typeof(TransmitStyleType), comboBoxEdit1.SelectedIndex); + Class1.Config.LocationContent = textEdit4.Text; + Class1.Config.GatherPoiCrowd = textEdit5.Text; + Class1.Config.MonitorCrowd = textEdit1.Text.Trim(); + Class1.Config.MonitorIntervalTime = (int)numericUpDown1.Value; + Class1.Config.CustomWebApi = textEdit2.Text.Trim(); + Class1.Config.AutoPraise = buttonCheck2.Checked; + Class1.Config.AutoPraiseInterval = (int)numericUpDown2.Value; + Class1.Config.CustomWebApiIntervalTime = (int)numericUpDown3.Value; + Class1.Config.AutoTurn = buttonCheck1.Checked; + Class1.Config.Turn_Obstinate = checkBox1.Checked; + Class1.Config.qrImage = (QrImageType)comboBox1.SelectedIndex; + Class1.Config.AppendComment = memoEdit6.Text; + + Api.Framework.Tools.Util.Save(Class1.Config); //保存配置文件 + } + } + catch (Exception ex) + { + ShowError(ex); + e.Cancel = true; + } + } + + /// <summary> + /// 检测新账号 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (!string.IsNullOrWhiteSpace(textEdit1.Text)) + { + var form = new XtraForm1(textEdit1.Text.Trim()); + form.ShowDialog(); + } + else ShowError("用户账号为空,不支持检测"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.simpleButton2.Enabled = false; + try + { + if (string.IsNullOrWhiteSpace(checkedComboBoxEdit1.Text)) throw new Exception("选择要发送的微信"); + if (!string.IsNullOrWhiteSpace(memoEdit1.Text)) + { + if (!Regex.IsMatch(memoEdit1.Text, @"\[图片=([^]]*)\]")) + { + ShowError($"推送内容中至少添加一张图片."); + return; + } + var clients = Chat.Framework.ChatClient.WXClient; + var usernames = checkedComboBoxEdit1.Properties.GetCheckedItems().ToString().Replace(", ", ",").Replace(" ,", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + var t1 = Task.Run(() => + { + Parallel.ForEach(clients.Values, item => + { + try + { + if ((item.WeixinType == WeixinType.Grpc微信 || item.WeixinType == WeixinType.Hook微信) && item.Status == WxStatus.在线 && usernames.Contains(item.WeixinHao.Trim())) + { + var json = item.SendCircle(memoEdit1.Text); + if (!string.IsNullOrWhiteSpace(memoEdit2.Text)) + { + var reg = Regex.Match(json, @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, memoEdit2.Text.Trim()); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"{ex.Message}"); + } + }); + }, tokenSource.Token); + t1.ContinueWith(f => + { + this.Invoke(new Action(() => + { + this.simpleButton2.Enabled = true; + if (!this.IsDisposed) ShowSuccess("推送发送成功"); + })); + }, tokenSource.Token); + } + else + if (!this.IsDisposed) ShowError($"推送内容不能为空."); + } + catch (Exception ex) + { + this.simpleButton2.Enabled = true; + if (!this.IsDisposed) ShowError(ex); + } + } + + private void 增加任务ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var sendTask = new SendTaskForm(); + if (sendTask.ShowDialog() == DialogResult.OK) + { + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + ApiClient.GetSession().FindTaskInfosTempGroups(true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 修改选中ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var selectRows = gridView1.GetSelectedRows(); + + if (selectRows.Length > 0) + { + var id = int.Parse(gridView1.GetRowCellValue(selectRows[0], "id").ToString()); + var task_name = gridView1.GetRowCellValue(selectRows[0], "task_name").ToString(); + var task_working_day = gridView1.GetRowCellValue(selectRows[0], "task_working_day").ToString(); + var task_time = gridView1.GetRowCellValue(selectRows[0], "task_time").ToString(); + var task_sendtext = gridView1.GetRowCellValue(selectRows[0], "task_sendtext").ToString(); + var task_comment = string.Empty; + if (gridView1.GetRowCellValue(selectRows[0], "task_comment") != null) + task_comment = (gridView1.GetRowCellValue(selectRows[0], "task_comment").ToString()); + var is_circulate = (gridView1.GetRowCellValue(selectRows[0], "is_circulate").ToString()); + var robotnames = (gridView1.GetRowCellValue(selectRows[0], "robotnames").ToString()); + + var sendTask = new SendTaskForm(new fl_plugin_circletools_taskinfos() { id = id, task_name = task_name, task_working_day = task_working_day, task_time = task_time, task_sendtext = task_sendtext, is_circulate = is_circulate == "是" ? ChooseType.是 : ChooseType.否, task_comment = task_comment, robotnames = robotnames }); + if (sendTask.ShowDialog() == DialogResult.OK) + { + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + ApiClient.GetSession().FindTaskInfosTempGroups(true); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var selectRows = gridView1.GetSelectedRows(); + + if (selectRows.Length > 0) + { + var id = long.Parse(gridView1.GetRowCellValue(selectRows[0], "id").ToString()); + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_circletools_taskinfos where id = @id", new { id = id }); + pageControl1.GotoPage(1); + label1.Visible = gridView1.RowCount == 0; + ApiClient.GetSession().FindTaskInfosTempGroups(true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + try + { + var tgwForm = new SetTGWForm(); + tgwForm.ShowDialog(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void buttonCheck1_Click(object sender, EventArgs e) + { + this.linkLabel3.Enabled = buttonCheck1.Checked; + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + if (comboBoxEdit1.SelectedIndex == 1) + labelControl15.Enabled = buttonCheck1.Checked = linkLabel3.Enabled = buttonCheck1.Enabled = true; + else + labelControl15.Enabled = buttonCheck1.Checked = linkLabel3.Enabled = buttonCheck1.Enabled = false; + } + + private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + var tgwForm = new SetTGWForm(); + tgwForm.ShowDialog(); + var session = ApiClient.GetSession(); + session.FindAdzoneInfos(true); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void linkLabel4_MouseHover(object sender, EventArgs e) + { + toolTip_Text.AutoPopDelay = 10000; + toolTip_Text.InitialDelay = 500; + toolTip_Text.ReshowDelay = 500; + toolTip_Text.ShowAlways = true; + toolTip_Text.SetToolTip(this.linkLabel4, @"您可以从""发单群""、""选品网站"" +直接复制推广文案到此处即可"); + } + + private void linkLabel6_MouseHover(object sender, EventArgs e) + { + toolTip_Pic.AutoPopDelay = 10000; + toolTip_Pic.InitialDelay = 500; + toolTip_Pic.ReshowDelay = 500; + toolTip_Pic.ShowAlways = true; + toolTip_Pic.SetToolTip(this.linkLabel6, @"不填写图片, 程序会自动检测默认图片。 +填写图片后,程序会以提供的图片为准。"); + } + + private void linkLabel5_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.NonautomaticSoftwareType); + if (adzone != null)//数据库中存在的情况 + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + + session.SaveOrUpdate(adzone); + } + else + { + //session.BeginTransaction(); + try + { + adzone = new fl_adzone_info() + { + custom_type = Resources.NonautomaticSoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = 0, //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + //else session.Commit(); + } + catch (Exception ex) + { + //session.Rollback(); + ShowError(ex); + } + } + textBox1.Text = adzone.adzone_name; + session.FindAdzoneInfos(true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 保存一键发送的产品数据 + /// </summary> + Dictionary<string, object> goodsDic = new Dictionary<string, object>(); + + /// <summary> + /// 加入产品待发送区 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void button1_Click(object sender, EventArgs e) + { + try + { + if (gridView2.RowCount >= 9) throw new Exception("最多添加9个产品"); + if (string.IsNullOrWhiteSpace(memoEdit3.Text.Trim())) throw new Exception("请添加文案"); + var adzone = ApiClient.GetSession().FindAdzoneInfos().FirstOrDefault(f => f.custom_type == Resources.NonautomaticSoftwareType && f.alliance_id == (int)CpsType.阿里妈妈); + if (adzone == null) throw new Exception("请先设置推广位"); + var tbAnalysis = new TBHelper.TbAnalysis(); + + var itemId = tbAnalysis.FindTbItemIdByStr(memoEdit3.Text); + if (string.IsNullOrWhiteSpace(itemId)) throw new Exception("您发送的链接中未带宝贝信息!"); + var date = DateTime.Now.ToString("yyyyMMdd"); + if (Class1.Config.recordSendGoods.ContainsKey(date)) + { + if (Class1.Config.recordSendGoods[date].Contains(itemId)) + throw new Exception("今天已经发送过该商品,以防重复系统予以提示!"); + } + + var tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + var api = CpsClient.CreateAlimamaRequest(tb_cps); + if (api == null) throw new Exception("创建阿里妈妈API请求失败"); + + var activityId = string.Empty; + var urls = CsharpHttpHelper.HttpExtend.RegexMatchesUrl(memoEdit3.Text); + if (urls != null && urls.Count != 0) + { + foreach (var item in urls) + { + if (item.ToLower().Contains("uland.taobao")) + { + var reg = Regex.Match(item, @"activityId=(?<活动ID>[A-Za-z0-9]+)", RegexOptions.IgnoreCase); + if (reg.Success) + activityId = reg.Groups["活动ID"].Value; + break; + } + } + } + + AnalyzeGoods analyze = new AnalyzeGoods(); + //goodsinfo.goods_id = itemId; + var goodsinfo = analyze.FindGoodsInfoToItemId(itemId, adzone.adzone_pid_cps_name, adzone.adzone_pid); + analyze.AnalysisText(memoEdit3.Text, goodsinfo); + if (goodsinfo != null) + { + var coupon_url = goodsinfo.shopping_url + "&activityId=" + activityId; + //检测优惠券的有效性 + var coupon = api.CheckCoupon(coupon_url); + //查到宝贝返利存在异常,直接提示没有返利 + if (coupon == null || coupon.retStatus != 0) throw new Exception("该产品优惠券已经过期,请重新获取。"); + + var lastIndex = memoEdit3.Text.Trim().LastIndexOf(@" +"); + var describe = memoEdit3.Text.Substring(lastIndex + 4).Trim(); + + decimal final_price = 0; + if (double.Parse(coupon.startFee) > goodsinfo.normal_price) + final_price = (decimal)goodsinfo.normal_price; + else + final_price = ((decimal)goodsinfo.normal_price - decimal.Parse(coupon.amount)); + var good = new { goods_name = goodsinfo.goods_name, price = goodsinfo.normal_price, final_price = final_price, rebate = final_price * ((decimal)goodsinfo.promotion_rate / 100m), rate = goodsinfo.promotion_rate + "%", pic = string.IsNullOrEmpty(textBox3.Text.Trim()) ? goodsinfo.goods_thumbnail_url : textBox3.Text.Trim(), coupon_discount = decimal.Parse(coupon.amount), itemid = goodsinfo.goods_id, describe = goodsinfo.goods_desc, coupon_url = coupon_url }; + if (goodsDic.ContainsKey(goodsinfo.goods_name)) throw new Exception("对不起,该商品已存在"); + goodsDic.Add(goodsinfo.goods_name, good); + gridControl2.DataSource = goodsDic.Values.ToList(); + label_num.Text = (int.Parse(label_num.Text) + 1).ToString(); + memoEdit3.Text = textBox3.Text = string.Empty; + } + else + throw new Exception("该商品无返利"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 一键发单删除选中项 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void 删除选中ToolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + var selectRows = gridView2.GetSelectedRows(); + + if (selectRows.Length > 0) + { + var title = gridView2.GetRowCellValue(selectRows[0], "goods_name").ToString(); + goodsDic.Remove(title); + gridControl2.DataSource = goodsDic.Values.ToList(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private StringBuilder strb = new StringBuilder(); + + private void gridView3_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + var selectRow = gridView3.GetSelectedRows()[0]; + var modelName = this.gridView3.GetRowCellValue(selectRow, "ModelName").ToString();//获取列的数据 + var sendModel = Class1.Config.send_templates.FirstOrDefault(f => f.ModelName == modelName); + if (sendModel != null) + memoEdit4.Text = sendModel.Content; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 显示一键发送模板(刷新) + /// </summary> + private void ShowContentModel() + { + try + { + //var modelName = Class1.Config.send_templates.Select(f => f.ModelName).ToList(); + //gridControl3.DataSource = modelName; + List<object> obj = new List<object>(); + foreach (var item in Class1.Config.send_templates) + { + obj.Add(new { ModelName = item.ModelName }); + } + gridControl3.DataSource = obj; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button4_Click(object sender, EventArgs e) + { + try + { + var form = new SetSendModelForm(); + form.ShowDialog(); + ShowContentModel(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private async void simpleButton3_Click_1(object sender, EventArgs e) + { + simpleButton3.Enabled = false; + + Class1.Config.TransmitStyle = (TransmitStyleType)Enum.ToObject(typeof(TransmitStyleType), comboBoxEdit1.SelectedIndex); + Class1.Config.LocationContent = textEdit4.Text; + Class1.Config.GatherPoiCrowd = textEdit5.Text; + Class1.Config.MonitorCrowd = textEdit1.Text.Trim(); + Class1.Config.MonitorIntervalTime = (int)numericUpDown1.Value; + Class1.Config.CustomWebApi = textEdit2.Text.Trim(); + Class1.Config.AutoPraise = buttonCheck2.Checked; + Class1.Config.AutoPraiseInterval = (int)numericUpDown2.Value; + Class1.Config.CustomWebApiIntervalTime = (int)numericUpDown3.Value; + Class1.Config.AutoTurn = buttonCheck1.Checked; + Class1.Config.Turn_Obstinate = checkBox1.Checked; + Class1.Config.transpond_send_usernames = checkedComboBoxEdit2.Properties.GetCheckedItems().ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + Util.Save(Class1.Config); //保存配置文件 + + var t1 = Task.Run(delegate + { + var timer = TimerTask.GetTimer<MonitorThread>() as MonitorThread; + timer.Run("立即检测", false); + }, tokenSource.Token); + + try + { + await t1; + if (!this.IsDisposed) ShowSuccess("立即执行定时检测完成!"); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + simpleButton3.Enabled = true; + } + + private async void simpleButton4_Click(object sender, EventArgs e) + { + try + { + await Task.Run(delegate + { + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList(); //获取机器人集合 + var monitorCrowd = string.Empty; //用户的集合中的id + List<Dictionary<string, object>> news = null; //获取朋友圈的动态 + foreach (var item in clients) + { + try + { + if ((item.WeixinType == WeixinType.Grpc微信 || item.WeixinType == WeixinType.Hook微信) && item.Status == WxStatus.在线) + { + monitorCrowd = textEdit5.Text.Trim();//undone 获取用户真正的微信id + news = item.FindCircle(monitorCrowd); + + //EventClient.OnEvent(this, $"采集账号:{item.WeixinHao} 采集量 = {news.Count}"); + + if (news != null && news.Count != 0) + { + if (news[0].ContainsKey("ObjectDesc")) + { + var objectDesc = news[0]["ObjectDesc"].ToString(); //新动态的内容部分 + + var reg = Regex.Match(objectDesc, @"(?<地址信息>\<location.*?\</location\>)"); + if (reg.Success) + { + var location = reg.Groups["地址信息"].Value; + reg = Regex.Match(location, @"poiClassifyId=""(?<poi>[^""]+?)"""); + if (reg.Success) + { + textEdit4.Text = reg.Groups["poi"].ToString(); + if (!this.IsDisposed) ShowSuccess("获取poi信息成功"); + return; + } + else + if (!this.IsDisposed) ShowError("获取poi信息失败"); + } + else + if (!this.IsDisposed) ShowError("该用户第一条朋友圈不存在poi信息"); + } + } + else + if (!this.IsDisposed) ShowError("该用户朋友圈无动态"); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - 朋友圈获取poi异常:{ex.Message}"); + } + } + }, tokenSource.Token); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + } + + private void checkedComboBoxEdit_UsernameType_EditValueChanged(object sender, EventArgs e) + { + if (checkedComboBoxEdit_UsernameType.EditValue != null) + Class1.Config.send_usernames = checkedComboBoxEdit_UsernameType.EditValue.ToString().Split(',').Select(f => f.Trim()).ToList(); + else + Class1.Config.send_usernames = new List<string>(); + } + + private void hyperlinkLabelControl2_Click(object sender, EventArgs e) + { + try + { + var image = new ImageForm(); + image.ShowDialog(); + if (!string.IsNullOrWhiteSpace(Class1.Config.NetworkUrl)) + { + var strb = new StringBuilder(); + var images = Class1.Config.NetworkUrl.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < images.Length; i++) + { + strb.AppendLine($"[图片={images[i]}]"); + } + memoEdit1.Text += strb.ToString(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + Stream mystream; + OpenFileDialog openfiledialog1 = new OpenFileDialog(); + openfiledialog1.Multiselect = true;//允许同时选择多个文件 + openfiledialog1.InitialDirectory = "c:\\"; + openfiledialog1.Filter = "All Image Files|*.bmp;*.ico;*.gif;*.jpeg;*.jpg;*.png;*.tif;*.tiff|(*.bmp)|*.bmp|(*.ico)|*.ico|(*.gif)|(*.gif)|(*.jpg)|*.jpg;*.jpeg|(*.png)|*.png"; + openfiledialog1.FilterIndex = 1; + openfiledialog1.RestoreDirectory = true; + var dialog = openfiledialog1.ShowDialog(); + if (dialog == DialogResult.OK) + { + if ((mystream = openfiledialog1.OpenFile()) != null) + { + for (int fi = 0; fi < openfiledialog1.FileNames.Length; fi++) + { + memoEdit1.Text += $"[图片={openfiledialog1.FileNames[fi].ToString()}]\r\n"; //保存图片路径 + } + mystream.Close(); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private async void button3_Click(object sender, EventArgs e) + { + try + { + button3.Enabled = false; + fl_plugin_circletools_taskinfos t1 = await Task.Run(() => + { + try + { + if (goodsDic.Count == 0) throw new Exception("请添加要发布的产品文案"); + if (string.IsNullOrWhiteSpace(memoEdit4.Text)) throw new Exception("请选择模板"); + var adzone = ApiClient.GetSession().FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.NonautomaticSoftwareType); + if (adzone == null) throw new Exception("请先设置推广位"); + if (string.IsNullOrWhiteSpace(checkedComboBoxEdit_UsernameType.Text)) throw new Exception("请选择要发送的机器人"); + QrImageType qrImage = QrImageType.模板A; + this.Invoke(new Action(() => + { + qrImage = (comboBox1.Text == "模板A" ? ApiClient.QrImageType.模板A : ApiClient.QrImageType.模板B); + })); + strb.Length = 0; + var tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + var api = CpsClient.CreateAlimamaRequest(tb_cps); + var pid_split = adzone.adzone_pid.Split('_'); + var tbAnalysis = new TBHelper.TbAnalysis(); + strb.Append(memoEdit4.Text); + foreach (var item in goodsDic.Values) + { + var pic = item.GetType().GetProperty("pic").GetValue(item).ToString(); + var item_id = item.GetType().GetProperty("itemid").GetValue(item).ToString(); + var title = item.GetType().GetProperty("goods_name").GetValue(item).ToString(); + var coupon_click_url = item.GetType().GetProperty("coupon_url").GetValue(item).ToString();//优惠券地址 + var describe = item.GetType().GetProperty("describe").GetValue(item).ToString();//商品介绍 + + //获取淘口令 + var tklInfo = tbAnalysis.FindTKL(coupon_click_url, api); + if (tklInfo == null) continue; + var shortUrl = tbAnalysis.FindShortUrlBySrcUrl(coupon_click_url, api); + var temp_url = api.ComposeTbClick(item_id, pic, tklInfo.tkl, tklInfo.isoUrl, true, adzone.adzone_pid, Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品, (int)DwzType.快站短网址, isCircleZjy: true); + + //var temp_url = ApiClient.ShortURL(api.ComposeTbClick(item_id, pic, tkl, coupon_click_url)).Result;//中间页地址 + + strb.Append("[图片=" + ApiClient.GetQRImage(title, item.GetType().GetProperty("price").GetValue(item).ToString(), item.GetType().GetProperty("coupon_discount").GetValue(item).ToString(), item.GetType().GetProperty("final_price").GetValue(item).ToString(), pic, temp_url, qrImage, CpsType.阿里妈妈, describe) + "]"); + } + + var taskinfo = new fl_plugin_circletools_taskinfos(); + taskinfo.task_sendtext = strb.ToString(); + taskinfo.task_comment = memoEdit5.Text; + taskinfo.robotnames = checkedComboBoxEdit_UsernameType.EditValue.ToString(); + return Task.FromResult(taskinfo); + } + catch (Exception) + { + } + return null; + }, tokenSource.Token); + + button3.Enabled = true; + AddAutoSendForm sendForm = new AddAutoSendForm(t1); + sendForm.ShowDialog(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 一键发单 发布按钮 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private async void button2_Click(object sender, EventArgs e) + { + try + { + button2.Enabled = false; + if (goodsDic.Count == 0) throw new Exception("请添加要发布的产品文案"); + if (string.IsNullOrWhiteSpace(memoEdit4.Text)) throw new Exception("请选择模板"); + var adzone = ApiClient.GetSession().FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.NonautomaticSoftwareType); + if (adzone == null) throw new Exception("请先设置推广位"); + if (string.IsNullOrWhiteSpace(checkedComboBoxEdit_UsernameType.Text)) throw new Exception("请选择要发送的机器人"); + var qrImage = (comboBox1.Text == "模板A" ? ApiClient.QrImageType.模板A : ApiClient.QrImageType.模板B); + strb.Length = 0; + var t3 = Task.Factory.StartNew(() => + { + var tb_cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + var api = CpsClient.CreateAlimamaRequest(tb_cps); + //var pid_split = adzone.adzone_pid.Split('_'); + var tbAnalysis = new TBHelper.TbAnalysis(); + strb.Append(memoEdit4.Text); + foreach (var item in goodsDic.Values) + { + var pic = item.GetType().GetProperty("pic").GetValue(item).ToString(); + var item_id = item.GetType().GetProperty("itemid").GetValue(item).ToString(); + var title = item.GetType().GetProperty("goods_name").GetValue(item).ToString(); + var coupon_click_url = item.GetType().GetProperty("coupon_url").GetValue(item).ToString();//优惠券地址 + var describe = item.GetType().GetProperty("describe").GetValue(item).ToString();//商品介绍 + + var date = DateTime.Now.ToString("yyyyMMdd"); + + if (!Class1.Config.recordSendGoods.ContainsKey(date)) + { + Class1.Config.recordSendGoods.Clear(); + Class1.Config.recordSendGoods.Add(date, new List<string>() { item_id }); + } + else + Class1.Config.recordSendGoods[date].Add(item_id); + + //获取淘口令 + var tklInfo = tbAnalysis.FindTKL(coupon_click_url, api); + if (tklInfo == null) continue; + + var shortUrl = tbAnalysis.FindShortUrlBySrcUrl(coupon_click_url, api); + + var temp_url = api.ComposeTbClick(item_id, pic, tklInfo.tkl, tklInfo.isoUrl, true, adzone.adzone_pid, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品, (int)DwzType.快站短网址, isCircleZjy: true); + //var temp_url = ApiClient.ShortURL(api.ComposeTbClick(item_id, pic, tkl, coupon_click_url)).Result;//中间页地址 + + strb.Append("[图片=" + GetQRImage(title, item.GetType().GetProperty("price").GetValue(item).ToString(), item.GetType().GetProperty("coupon_discount").GetValue(item).ToString(), item.GetType().GetProperty("final_price").GetValue(item).ToString(), pic, temp_url, qrImage, CpsType.阿里妈妈, describe) + "]"); + } + + var usernames = checkedComboBoxEdit_UsernameType.EditValue.ToString().Split(',').Select(f => f.Trim()).ToList(); + var clients = Chat.Framework.ChatClient.WXClient; + foreach (var item in clients.Values) + { + try + { + if ((item.WeixinType == WeixinType.Grpc微信 || item.WeixinType == WeixinType.Hook微信) && usernames.Contains(item.WeixinHao.Trim()) && item.Status == WxStatus.在线) + { + var json = item.SendCircle(strb.ToString()); + if (!string.IsNullOrWhiteSpace(memoEdit5.Text)) + { + var reg = Regex.Match(json, @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, memoEdit5.Text.Trim()); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"一键发送异常:{item.User.Nick} - {ex.Message}"); + } + } + }, tokenSource.Token); + + try + { + await t3; + if (!this.IsDisposed) + { + button2.Enabled = true; + label_num.Text = "0"; + gridControl2.DataSource = null; + ShowSuccess("发送成功"); + goodsDic.Clear(); + } + } + catch (Exception ex) + { } + } + catch (Exception ex) + { + button2.Enabled = true; + ShowError(ex); + } + } + + private void memoEdit3_Click(object sender, EventArgs e) + { + memoEdit3.SelectAll(); + } + + private void labelControl29_Click(object sender, EventArgs e) + { + memoEdit6.Text += labelControl29.Text; + } + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/MainForm.resx b/应用/Weixin.CircleTools/MainForm.resx new file mode 100644 index 0000000..a13fcfe --- /dev/null +++ b/应用/Weixin.CircleTools/MainForm.resx @@ -0,0 +1,141 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <metadata name="contextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>688, 17</value> + </metadata> + <metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>274, 17</value> + </metadata> + <metadata name="toolTip_Pic.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>448, 17</value> + </metadata> + <metadata name="toolTip_Text.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>564, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>58</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/MethodExt.cs b/应用/Weixin.CircleTools/MethodExt.cs new file mode 100644 index 0000000..71fe587 --- /dev/null +++ b/应用/Weixin.CircleTools/MethodExt.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CircleFriendsTools +{ + public static class MethodExt + { + /// <summary> + /// 文本控件方法扩展 + /// </summary> + /// <param name="rtBox"></param> + /// <param name="text">控件内容</param> + /// <param name="color">显示的颜色</param> + /// <param name="addNewLine">是否换行</param> + public static void AppendTextColorful(this RichTextBox rtBox, string text, Color color, bool addNewLine = true) + { + if (addNewLine) + { + text += Environment.NewLine; + } + rtBox.SelectionStart = rtBox.TextLength; + rtBox.SelectionLength = 0; + rtBox.SelectionColor = color; + rtBox.AppendText(text); + rtBox.SelectionColor = rtBox.ForeColor; + } + + } +} diff --git a/应用/Weixin.CircleTools/MonitorThread.cs b/应用/Weixin.CircleTools/MonitorThread.cs new file mode 100644 index 0000000..c18c8ec --- /dev/null +++ b/应用/Weixin.CircleTools/MonitorThread.cs @@ -0,0 +1,625 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Weixin.CircleTools; +using Weixin.CircleTools.Entitys; +using static CircleFriendsTools.Enums; +using System.Text; +using Chat.Framework.Utils; + +namespace CircleFriendsTools +{ + /// <summary> + /// 评语 + /// </summary> + class Comment + { + public long CreateTime { get; set; } + + public string Content { get; set; } + } + + /// <summary> + /// 监听朋友圈列表转发内容 + /// </summary> + class MonitorThread : TimerTask + { + private string[] Day = new string[] { "周末", "周一", "周二", "周三", "周四", "周五", "周六" }; + + private long count; + //private bool isSend = false;//是否进入发送状态,成没成功和这个没关系 + private string cache_key = "cache_key"; + private TbApi tbApi = new TbApi(); + private bool IsRun = false; + + public MonitorThread() { } + internal Class1 plugin; + private static readonly Object ObjLock = new Object(); + + // static List<string> weixinhaos = new List<string>() { "liu454097", "zhengbaolingshipu520", "Cmeiliy", "WY1164314651", "L13291035216", "z15982388678" }; + public override async void Run(object state, bool timedOut) + { + try + { + count++; + //朋友圈检测 + if (!string.IsNullOrWhiteSpace(Class1.Config.MonitorCrowd) && ((state != null && state.ToString() == "立即检测") || (count % (Class1.Config.MonitorIntervalTime * 60) == 0))) + { + EventClient.OnEvent(this, $"【朋友圈工具】 => 定时执行朋友圈跟发,状态:{(IsRun ? "历史任务还在执行中" : "历史任务未执行")}"); + if (!IsRun) + { + IsRun = true; + var session = ApiClient.GetSession(); + var clients = GetRandomList<WeixinBase>(Chat.Framework.ChatClient.WXClient.Values.ToList()); //获取机器人集合 + try + { + string objectDesc = string.Empty; //要转发的朋友圈内容 + List<Comment> comments = new List<Comment>(); //评论内容 + var isNews = false; //判断是否有新的动态 + + #region 这里主要是检索所有在线的机器人列表中,监听用户的朋友圈内容以及评论数据 + lock (ObjLock) + { + string newestTime = string.Empty; + int ii = 1; + foreach (var item in clients) + { + try + { + if ((item.WeixinType == WeixinType.Grpc微信 || item.WeixinType == WeixinType.Hook微信) && item.Status == WxStatus.在线) + { + //if (!weixinhaos.Contains(item.WeixinHao)) continue; + var monitorCrowd = Class1.Config.MonitorCrowd.Trim(); //undone 获取用户真正的微信id + var news = item.FindCircle(monitorCrowd); //获取朋友圈的动态 + + if (news != null && news.Count == 0 && (state != null && state.ToString() == "立即检测")) + EventClient.OnEvent(this, $"【朋友圈工具】 => 朋友圈检测({item.WeixinHao}):{Class1.Config.MonitorInfoHistoryTime} - {news.Count}"); + + if (news != null && news.Count != 0) + { + if (news[0].ContainsKey("CreateTime")) + newestTime = news[0]["CreateTime"].ToString(); //监听的微信id最新动态发送时间 + //StringBuilder strb = new StringBuilder(); + + //if ((state != null && state.ToString() == "立即检测")) + //{ + // strb.AppendLine($"{item.WeixinHao} - {Class1.Config.MonitorInfoHistoryTime} - {newestTime}"); + // if (news[0].ContainsKey("ObjectDesc")) + // objectDesc = news[0]["ObjectDesc"].ToString(); //新动态的内容部分 + // strb.AppendLine($"objectDesc = {objectDesc}"); + // ArrayList _commentUserList = null; + // if (news[0].ContainsKey("CommentUserList")) + // _commentUserList = news[0]["CommentUserList"] as ArrayList; //评论用户列表 + // strb.AppendLine(); + // strb.AppendLine($"commentUserList = {_commentUserList}"); + // ApiClient.SendNewDingdingMessage(strb.ToString(), "https://oapi.dingtalk.com/robot/send?access_token=3d1e19c2965752d07ade14cf99abb940d6bd0ddcf1b7aaebd831b95d339a0a78"); + //} + + + + if (!string.IsNullOrEmpty(Class1.Config.MonitorInfoHistoryTime) && long.Parse(Class1.Config.MonitorInfoHistoryTime) >= long.Parse(newestTime)) //没有最新的动态 + { + if ((state != null && state.ToString() == "立即检测")) + EventClient.OnEvent(this, $"【朋友圈工具】 => 朋友圈检测({item.WeixinHao}):没有新动态({newestTime})"); + if (ii > 3) + break; + else + { + Thread.Sleep(500); + ii++; + continue; + } + } + + if (news[0].ContainsKey("ObjectDesc")) + objectDesc = news[0]["ObjectDesc"].ToString(); //新动态的内容部分 + + var reg = Regex.Match(objectDesc, @"(?<地址信息>\<location.*?\</location\>)"); + if (reg.Success) + { + var location = reg.Groups["地址信息"].Value; + var locationContent = string.Empty; + if (!string.IsNullOrWhiteSpace(Class1.Config.LocationContent)) + { + //<location poiAddress="" poiScale="0" city="成都" poiName="成都 · 88888888888888888888888" latitude="30.791265" poiClickableStatus="0" poiClassifyId="UgcPoiEx_4900258511" poiClassifyType="2" longitude="103.89912" poiAddressName="88888888888888888888888" country="中国"></location> + //Regex.Replace(“<img>abc</img>”,@“<img>(?<str>.*?)</img>”,"[图片]${str}"); + locationContent = @"<location poiAddress="""" poiScale=""0"" city="""" poiName ="""" latitude =""0"" poiClickableStatus =""1"" poiClassifyId =""" + Class1.Config.LocationContent + @""" poiClassifyType =""2"" longitude =""0"" poiAddressName ="""" country =""中国"" ></location>"""; + } + objectDesc = objectDesc.Replace(location, locationContent); + } + + if (Class1.Config.TransmitStyle == TransmitStyleType.仅转发原文) + { + isNews = true; + break; //设置为仅转发原文 + } + + ArrayList commentUserList = null; + if (news[0].ContainsKey("CommentUserList")) + commentUserList = news[0]["CommentUserList"] as ArrayList; //评论用户列表 + else + { + if (Class1.Config.TransmitStyle == TransmitStyleType.原文及评论) + { + isNews = false; + continue; + } + } + + if (commentUserList != null && commentUserList.Count != 0) + { + for (int i = 0; i < commentUserList.Count; i++) + { + try + { + var user = commentUserList[i] as Dictionary<string, object>; + if (user != null && user.Count != 0) + { + var username = string.Empty; + if (user.ContainsKey("Username")) + username = user["Username"].ToString(); + if (monitorCrowd == username || Class1.Config.MonitorCrowd == username)//发送者给自己评论时. + { + if (user.ContainsKey("Content")) + comments.Add(new Comment { Content = user["Content"].ToString(), CreateTime = long.Parse(user["CreateTime"].ToString()) }); + } + } + } + catch (Exception ex) + { + throw ex; + } + } + //评论不为空 + if (comments.Count != 0) + { + comments.Sort((Comment c1, Comment c2) => + { + return c1.CreateTime.CompareTo(c2.CreateTime); + }); + isNews = true; + break; + } + } + + if (Class1.Config.Turn_Obstinate && !string.IsNullOrEmpty(objectDesc)) + { + isNews = true; + break; + } + + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - 朋友圈检测 - 采集:{ex.Message} - {ex.StackTrace}"); + } + } + + if (isNews) + { + if (!string.IsNullOrWhiteSpace(newestTime)) + { + Class1.Config.MonitorInfoHistoryTime = newestTime; + Util.Save(Class1.Config); //更新记录时间 + } + } + } + #endregion + + #region 这里主要是让在线的机器人都转发上面获取到的最新动态 + if (isNews) + { + foreach (var _item in clients) + { + var item = _item; + + if (Class1.Config.transpond_send_usernames.Count != 0 && !Class1.Config.transpond_send_usernames.Contains(item.WeixinHao)) + continue; + + await Task.Run(() => + { + try + { + if ((item.WeixinType == WeixinType.Grpc微信 || item.WeixinType == WeixinType.Hook微信) && item.Status == WxStatus.在线) + { + EventClient.OnEvent("", $"【朋友圈工具】 => {item.User.Nick}({item.WeixinHao}),准备开始发送朋友圈~"); + List<tbinfo_temp> tbInfoTempGroups = ApiClient.GetSession().FindTbInfoTempGroups();//获取tb数据数据集合缓存 + var infoTemp = tbInfoTempGroups.FirstOrDefault(f => f.name.Trim() == item.WeixinHao.Trim() && !f.onoff); + if (infoTemp == null) return; + if (Class1.Config.TransmitStyle == TransmitStyleType.仅转发原文) + item.SendCircle(objectDesc);//发送朋友圈的主内容 + else + { + var _comment = new List<string>(); + if (Class1.Config.AutoTurn) + { + #region + var tb = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == infoTemp.adzone_pid_cps_name);//用户设置的推广位 + if (tb == null) throw new Exception("阿里妈妈推广位异常,请检测后重试!"); + + #region 淘宝转链 + if (tb != null) + { + var api = CpsClient.CreateAlimamaRequest(tb); + foreach (var comment in comments) + { + var regs = Regex.Matches(comment.Content, "(?<口令符号_前缀>[^A-Za-z0-9]?(?<淘口令>[A-Za-z0-9]{11})(?<口令符号_后缀>)[^A-Za-z0-9]?)"); + if (regs.Count > 0) + { + foreach (Match temp in regs) + { + try + { + if (temp.Success) + { + var first_fuhao = temp.Groups["口令符号_前缀"].Value;//口令符号 + var tklInfo = tbApi.TKLToOwnTKL(temp.Groups["淘口令"].Value, infoTemp.adzone_pid, api);//获取新的淘口令信息 + + if (tklInfo != null) + { + //淘口令的前/后符号有没有设置.有设置将替换掉 + var tkl = new TBHelper.TbAnalysis().ReplaceTklModifier(tklInfo.tkl); + + if (!string.IsNullOrWhiteSpace(Class1.Config.AppendComment)) + _comment.Add(Class1.Config.AppendComment.Replace("[转链口令]", tkl)); + else + _comment.Add(tkl); + //_comment.Add(comment.Content.Replace(first_fuhao, tkl)); + break; + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"机器人:{item.WeixinHao},评语转换淘口令失败 - {comment.Content},{ex.Message},{ex.StackTrace}"); + } + } + } + else + _comment.Add(comment.Content); + } + } + #endregion + + #endregion + } + else + _comment = comments.Select(f => f.Content).ToList(); + + var json = item.SendCircle(objectDesc);//发送朋友圈的主内容 + if (string.IsNullOrWhiteSpace(json)) + EventClient.OnEvent(this, $"【朋友圈工具】 => {item.WeixinHao},转发失败"); + else + EventClient.OnEvent(this, $"【朋友圈工具】 => {item.WeixinHao},转发成功"); + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + { + var id = reg.Groups["id"].Value; + //EventClient.OnEvent(this, $"【朋友圈工具】 => {item.WeixinHao}_{id}"); + var commentStr = string.Join("[分段]", _comment); + + if (!string.IsNullOrWhiteSpace(commentStr)) + { + EventClient.OnEvent(this, $"【朋友圈工具】 => {item.WeixinHao},{commentStr}"); + item.SendCircleComment(item.User.Username, id, commentStr); + } + } + else + { + //EventClient.OnEvent(this, $"【朋友圈工具】 => {item.WeixinHao},{json}"); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - 朋友圈检测 - 转发:{item.User.Nick}({item.WeixinHao}){ex.Message},{ex.StackTrace}"); + } + }); + } + //}); + EventClient.OnEvent(this, $"【朋友圈工具】 => 转发完毕"); + } + #endregion + } + catch (Exception) + { } + finally + { + IsRun = false; + } + } + } + + #region web接口检测 + if (count % (Class1.Config.CustomWebApiIntervalTime * 60) == 0) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.CustomWebApi)) + { + try + { + var http = new HttpHelper(); + var text = http.GetHtml(HttpExtend.GetItem(http, Class1.Config.CustomWebApi.Replace(".txt", ".php"))).Html; + + if (!string.IsNullOrWhiteSpace(text)) + { + var text_MD5 = Api.Framework.Tools.Util.GetMd5_32byte(text); + if (Class1.Config.CustomWebApiTextMD5 != text_MD5) + { + Class1.Config.CustomWebApiTextMD5 = text_MD5; + Util.Save(Class1.Config); + + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList(); + + var values = text.Split(new string[] { "[评语]" }, StringSplitOptions.RemoveEmptyEntries); + if (values.Length != 0) + { + var decided_tkl = string.Empty; + foreach (WeixinBase item in clients) + { + try + { + if ((item.WeixinType == WeixinType.Grpc微信 || item.WeixinType == WeixinType.Hook微信) && item.Status == WxStatus.在线) + { + var jsonObject = item.SendCircle(values[0]); + if (jsonObject == null) throw new Exception("请检测是否包含图片地址"); + if (values.Length == 2) + { + var reg = Regex.Match(jsonObject.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + { + var id = reg.Groups["id"].Value; + if (!string.IsNullOrWhiteSpace(values[1])) + { + var session = ApiClient.GetSession(); + var tbInfoTempGroups = session.FindTbInfoTempGroups();//获取tb数据数据集合缓存 + var infoTemp = tbInfoTempGroups.FirstOrDefault(f => f.name.Trim() == item.WeixinHao.Trim() && !f.onoff); + var tb = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == infoTemp.adzone_pid_cps_name);//用户设置的推广位 + if (tb == null) throw new Exception("阿里妈妈推广位异常,请检测后重试!"); + + #region 淘宝转链 + if (tb != null) + { + var finally_comment = values[1]; ; + if (Class1.Config.AutoTurn) + { + var api = CpsClient.CreateAlimamaRequest(tb); + var tempstr = string.IsNullOrWhiteSpace(decided_tkl) ? values[1] : decided_tkl; + + var regs = Regex.Matches(tempstr, "(?<口令符号_前缀>[^A-Za-z0-9]?(?<淘口令>[A-Za-z0-9]{11})(?<口令符号_后缀>)[^A-Za-z0-9]?)"); + if (regs.Count > 0) + { + foreach (Match temp in regs) + { + try + { + if (temp.Success) + { + var first_fuhao = temp.Groups["口令符号_前缀"].Value;//口令符号 + var suspicious_tkl = temp.Groups["淘口令"].Value; + var tklInfo = tbApi.TKLToOwnTKL(suspicious_tkl, infoTemp.adzone_pid, api);//获取新的淘口令信息 + + if (tklInfo != null) + { + decided_tkl = first_fuhao; + + //淘口令的前/后符号有没有设置.有设置将替换掉 + var tkl = new TBHelper.TbAnalysis().ReplaceTklModifier(tklInfo.tkl); + + finally_comment = values[1].Replace(first_fuhao, tkl); + break; + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"机器人:{item.WeixinHao},评语转换淘口令失败 - {values[1]},{ex.Message},{ex.StackTrace}"); + } + } + } + } + item.SendCircleComment(item.User.Username, id, finally_comment); + #endregion + } + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - web接口:({item.WeixinHao}) => {ex.Message}"); + } + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - web接口:{ex.Message}"); + } + } + } + #endregion + + #region 自动点赞 + if (Class1.Config.AutoPraise && count % (Class1.Config.AutoPraiseInterval * 60) == 0) + { + var robots = Chat.Framework.ChatClient.WXClient.Where(item => (item.Value.WeixinType == WeixinType.Grpc微信 || item.Value.WeixinType == WeixinType.Hook微信) && item.Value.Status == WxStatus.在线); + Parallel.ForEach(robots, item => + { + var robot = item.Value; + try + { + var circles = robot.FindCircles(); + foreach (var temp in circles) + { + try + { + var likeUserList = temp["LikeUserList"] as ArrayList; + if (likeUserList != null && likeUserList.Count != 0) + { + var query = from Dictionary<string, object> likeUser in likeUserList + where likeUser["Username"].ToString() == robot.User.Username + select likeUser; + if (query != null) + robot.SendCirclePraise(temp["Username"].ToString(), temp["Id"].ToString()); + } + else + robot.SendCirclePraise(temp["Username"].ToString(), temp["Id"].ToString()); + Thread.Sleep(1521); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - 自动点赞:{ex.Message}"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - 自动点赞:{ex.Message}"); + } + }); + } + #endregion + + #region 定时发送任务 + if (count % 60 == 0) + { + var session = ApiClient.GetSession(); + var pddinfo_temp_groups = session.FindTaskInfosTempGroups(); //读取缓存中的数据 + if (pddinfo_temp_groups != null && pddinfo_temp_groups.Count != 0) + { + string week = Day[Convert.ToInt32(DateTime.Now.DayOfWeek.ToString("d"))].ToString(); //获取到今天是星期几 + var isSend = false;//还原 + foreach (var item in pddinfo_temp_groups) + { + try + { + if (item.task_working_day.Contains(week)) + { + var result = ApiClient.Cache.Get<List<long>>(cache_key); + if (result != null && result.Contains(item.id)) continue; + var task_time = DateTime.Parse(item.task_time); + var now = DateTime.Now; + var dValue = (now - task_time).TotalMinutes; + if (0 < dValue && dValue < 5) + { + if (result == null) result = new List<long>(); + result.Add(item.id); + ApiClient.Cache.Set(cache_key, result, 5); + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList().Where(f => (f.WeixinType == WeixinType.Grpc微信 || f.WeixinType == WeixinType.Hook微信) && f.Status == WxStatus.在线); + + var robotnames = item.robotnames.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + foreach (var client in clients) + { + try + { + if (!robotnames.Contains(client.WeixinHao.Trim())) continue; + isSend = true; + EventClient.OnEvent(this, "定时任务:" + client.WeixinHao + ":准备发了"); + var json = client.SendCircle(item.task_sendtext);//发送朋友圈的主内容 + if (string.IsNullOrWhiteSpace(json)) + EventClient.OnEvent(this, "定时任务:" + client.WeixinHao + ":发送失败"); + else + EventClient.OnEvent(this, "定时任务:" + client.WeixinHao + ":已经发了"); + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + { + var id = reg.Groups["id"].Value; + if (!string.IsNullOrWhiteSpace(item.task_comment)) + client.SendCircleComment(client.User.Username, id, item.task_comment); //替换淘口令 + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - 定时发送任务:{ex.Message},{ex.StackTrace}"); + } + } + if (isSend && item.is_circulate == Enums.ChooseType.否)//不是循环发送的任务,将本次发送的工作日给删除了. + { + var workingDays = item.task_working_day.Replace(" ", "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).ToList(); + workingDays.Remove(week); + if (workingDays.Count == 0)//任务中的所有工作日都已经执行完成,删除该任务 + session.Deleteable(item).ExecuteCommand(); + else//任务中的工作还存在,将本次工作日删除后进行更新 + { + var task_working_day = string.Join(",", workingDays); + item.task_working_day = task_working_day; + + //session.Updateable(item).ExecuteCommand(); + session.ExcuteSQL("update fl_plugin_circletools_taskinfos set task_working_day = @task_working_day where id = @id", new { task_working_day = task_working_day, id = item.id }); + } + session.FindTaskInfosTempGroups(true); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"朋友圈工具 - 定时发送任务:{ex.Message}"); + } + } + } + } + #endregion + } + catch (Exception ex) + { + SessionExt.Clear(); + EventClient.OnEvent(this, $"朋友圈工具:{ex.Message}\r\n{ex.StackTrace}"); + } + } + + private static List<T> GetRandomList<T>(List<T> inputList) + { + try + { + //Copy to a array + T[] copyArray = new T[inputList.Count]; + inputList.CopyTo(copyArray); + + //Add range + List<T> copyList = new List<T>(); + copyList.AddRange(copyArray); + + //Set outputList and random + List<T> outputList = new List<T>(); + Random rd = new Random(DateTime.Now.Millisecond); + + while (copyList.Count > 0) + { + //Select an index and item + int rdIndex = rd.Next(0, copyList.Count - 1); + T remove = copyList[rdIndex]; + + //remove it from copyList and add it to output + copyList.Remove(remove); + outputList.Add(remove); + } + return outputList; + } + catch (Exception ex) + { } + return inputList; + } + + } +} diff --git a/应用/Weixin.CircleTools/Properties/AssemblyInfo.cs b/应用/Weixin.CircleTools/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..656308f --- /dev/null +++ b/应用/Weixin.CircleTools/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Weixin.CircleTools")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CircleFriendsTools")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("00191980-d031-4c7d-99aa-69b26c43d2c6")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2019.04.17.1")] +[assembly: AssemblyFileVersion("2019.04.17.1")] diff --git a/应用/Weixin.CircleTools/Properties/Resources.Designer.cs b/应用/Weixin.CircleTools/Properties/Resources.Designer.cs new file mode 100644 index 0000000..64511fe --- /dev/null +++ b/应用/Weixin.CircleTools/Properties/Resources.Designer.cs @@ -0,0 +1,163 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Weixin.CircleTools.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Weixin.CircleTools.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 设置自动转连推广位 的本地化字符串。 + /// </summary> + internal static string AutoTurnTGWFormTitle { + get { + return ResourceManager.GetString("AutoTurnTGWFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 朋友圈检测 的本地化字符串。 + /// </summary> + internal static string CheckFormTitle { + get { + return ResourceManager.GetString("CheckFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 图片选择 的本地化字符串。 + /// </summary> + internal static string ImageForm { + get { + return ResourceManager.GetString("ImageForm", resourceCulture); + } + } + + /// <summary> + /// 查找类似 朋友圈工具 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 一键发送朋友圈工具 的本地化字符串。 + /// </summary> + internal static string NonautomaticSoftwareType { + get { + return ResourceManager.GetString("NonautomaticSoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找类似 增加发送任务 的本地化字符串。 + /// </summary> + internal static string PluginFormAddSendTask { + get { + return ResourceManager.GetString("PluginFormAddSendTask", resourceCulture); + } + } + + /// <summary> + /// 查找类似 修改发送任务 的本地化字符串。 + /// </summary> + internal static string PluginFormUpdateSendTask { + get { + return ResourceManager.GetString("PluginFormUpdateSendTask", resourceCulture); + } + } + + /// <summary> + /// 查找类似 朋友圈工具 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 朋友圈工具.监听转发,发送任务 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找类似 朋友圈工具 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 朋友圈工具 { + get { + object obj = ResourceManager.GetObject("朋友圈工具", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Weixin.CircleTools/Properties/Resources.resx b/应用/Weixin.CircleTools/Properties/Resources.resx new file mode 100644 index 0000000..6ce3bdd --- /dev/null +++ b/应用/Weixin.CircleTools/Properties/Resources.resx @@ -0,0 +1,164 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="AutoTurnTGWFormTitle" xml:space="preserve"> + <value>设置自动转连推广位</value> + <comment>自动转连推广位标题</comment> + </data> + <data name="CheckFormTitle" xml:space="preserve"> + <value>朋友圈检测</value> + <comment>检测结果窗体标题</comment> + </data> + <data name="ImageForm" xml:space="preserve"> + <value>图片选择</value> + <comment>图片选择标题</comment> + </data> + <data name="MainFormTitle" xml:space="preserve"> + <value>朋友圈工具</value> + <comment>窗体标题</comment> + </data> + <data name="NonautomaticSoftwareType" xml:space="preserve"> + <value>一键发送朋友圈工具</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <data name="PluginFormAddSendTask" xml:space="preserve"> + <value>增加发送任务</value> + <comment>增加发送任务</comment> + </data> + <data name="PluginFormUpdateSendTask" xml:space="preserve"> + <value>修改发送任务</value> + <comment>修改发送任务</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>朋友圈工具</value> + <comment>插件名称</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>朋友圈工具.监听转发,发送任务</value> + <comment>插件介绍</comment> + </data> + <data name="SoftwareType" xml:space="preserve"> + <value>朋友圈工具</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="朋友圈工具" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\朋友圈工具.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/Properties/licenses.licx b/应用/Weixin.CircleTools/Properties/licenses.licx new file mode 100644 index 0000000..60e5b98 --- /dev/null +++ b/应用/Weixin.CircleTools/Properties/licenses.licx @@ -0,0 +1,4 @@ +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/Weixin.CircleTools/Resources/朋友圈工具.png b/应用/Weixin.CircleTools/Resources/朋友圈工具.png new file mode 100644 index 0000000..fd0595b Binary files /dev/null and b/应用/Weixin.CircleTools/Resources/朋友圈工具.png differ diff --git a/应用/Weixin.CircleTools/SendTaskForm.Designer.cs b/应用/Weixin.CircleTools/SendTaskForm.Designer.cs new file mode 100644 index 0000000..3d9d378 --- /dev/null +++ b/应用/Weixin.CircleTools/SendTaskForm.Designer.cs @@ -0,0 +1,337 @@ +namespace Weixin.CircleTools +{ + partial class SendTaskForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.checkedComboBoxEdit_ChatType = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.label4 = new System.Windows.Forms.Label(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.label10 = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.label8 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.checkEdit1 = new DevExpress.XtraEditors.CheckEdit(); + this.label5 = new System.Windows.Forms.Label(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.label3 = new System.Windows.Forms.Label(); + this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.checkedComboBoxEdit1 = new DevExpress.XtraEditors.CheckedComboBoxEdit(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.textBox2); + this.groupControl1.Controls.Add(this.textBox1); + this.groupControl1.Controls.Add(this.checkedComboBoxEdit_ChatType); + this.groupControl1.Controls.Add(this.label4); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl3); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.labelControl8); + this.groupControl1.Controls.Add(this.label10); + this.groupControl1.Controls.Add(this.label9); + this.groupControl1.Controls.Add(this.label11); + this.groupControl1.Controls.Add(this.label8); + this.groupControl1.Controls.Add(this.label7); + this.groupControl1.Controls.Add(this.label6); + this.groupControl1.Controls.Add(this.checkEdit1); + this.groupControl1.Controls.Add(this.label5); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Controls.Add(this.label3); + this.groupControl1.Controls.Add(this.dateTimePicker1); + this.groupControl1.Controls.Add(this.label2); + this.groupControl1.Controls.Add(this.label1); + this.groupControl1.Controls.Add(this.checkedComboBoxEdit1); + this.groupControl1.Location = new System.Drawing.Point(20, 19); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(562, 531); + this.groupControl1.TabIndex = 0; + this.groupControl1.Text = "任务信息"; + // + // checkedComboBoxEdit_ChatType + // + this.checkedComboBoxEdit_ChatType.EditValue = ""; + this.checkedComboBoxEdit_ChatType.Location = new System.Drawing.Point(141, 72); + this.checkedComboBoxEdit_ChatType.Name = "checkedComboBoxEdit_ChatType"; + this.checkedComboBoxEdit_ChatType.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit_ChatType.Size = new System.Drawing.Size(311, 20); + this.checkedComboBoxEdit_ChatType.TabIndex = 36; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(42, 75); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(79, 14); + this.label4.TabIndex = 35; + this.label4.Text = "活动机器人:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(141, 382); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(138, 14); + this.labelControl2.TabIndex = 34; + this.labelControl2.Text = "注:多条评语 [分段] 分割"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(57, 199); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 34; + this.labelControl3.Text = "发送内容:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(141, 199); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(315, 14); + this.labelControl1.TabIndex = 34; + this.labelControl1.Text = "注:发送内容中必须添加一张图片 格式:[图片=图片地址]"; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(61, 382); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(60, 14); + this.labelControl8.TabIndex = 31; + this.labelControl8.Text = "追加评论:"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.ForeColor = System.Drawing.Color.Red; + this.label10.Location = new System.Drawing.Point(114, 199); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(14, 14); + this.label10.TabIndex = 14; + this.label10.Text = "*"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.ForeColor = System.Drawing.Color.Red; + this.label9.Location = new System.Drawing.Point(461, 135); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(14, 14); + this.label9.TabIndex = 13; + this.label9.Text = "*"; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.ForeColor = System.Drawing.Color.Red; + this.label11.Location = new System.Drawing.Point(461, 75); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(14, 14); + this.label11.TabIndex = 12; + this.label11.Text = "*"; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.ForeColor = System.Drawing.Color.Red; + this.label8.Location = new System.Drawing.Point(461, 105); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(14, 14); + this.label8.TabIndex = 12; + this.label8.Text = "*"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.ForeColor = System.Drawing.Color.Red; + this.label7.Location = new System.Drawing.Point(461, 45); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(14, 14); + this.label7.TabIndex = 11; + this.label7.Text = "*"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.ForeColor = System.Drawing.Color.Gray; + this.label6.Location = new System.Drawing.Point(222, 165); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(127, 14); + this.label6.TabIndex = 10; + this.label6.Text = "(不勾选则执行一次)"; + // + // checkEdit1 + // + this.checkEdit1.Location = new System.Drawing.Point(141, 163); + this.checkEdit1.Name = "checkEdit1"; + this.checkEdit1.Properties.Caption = "是否循环"; + this.checkEdit1.Size = new System.Drawing.Size(75, 20); + this.checkEdit1.TabIndex = 9; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(54, 165); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(67, 14); + this.label5.TabIndex = 8; + this.label5.Text = "任务类型:"; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(141, 42); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(311, 20); + this.textEdit1.TabIndex = 5; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(42, 135); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(79, 14); + this.label3.TabIndex = 4; + this.label3.Text = "发送时间点:"; + // + // dateTimePicker1 + // + this.dateTimePicker1.CustomFormat = "HH:mm:ss"; + this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dateTimePicker1.Location = new System.Drawing.Point(141, 129); + this.dateTimePicker1.Name = "dateTimePicker1"; + this.dateTimePicker1.ShowUpDown = true; + this.dateTimePicker1.Size = new System.Drawing.Size(311, 22); + this.dateTimePicker1.TabIndex = 3; + this.dateTimePicker1.Value = new System.DateTime(2018, 11, 16, 15, 56, 0, 0); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(54, 45); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 2; + this.label2.Text = "任务名称:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(42, 105); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(79, 14); + this.label1.TabIndex = 1; + this.label1.Text = "发送工作日:"; + // + // checkedComboBoxEdit1 + // + this.checkedComboBoxEdit1.Location = new System.Drawing.Point(141, 102); + this.checkedComboBoxEdit1.Name = "checkedComboBoxEdit1"; + this.checkedComboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.checkedComboBoxEdit1.Size = new System.Drawing.Size(311, 20); + this.checkedComboBoxEdit1.TabIndex = 0; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(45, 228); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(471, 148); + this.textBox1.TabIndex = 39; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(45, 402); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(471, 113); + this.textBox2.TabIndex = 40; + // + // SendTaskForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(603, 572); + this.Controls.Add(this.groupControl1); + this.Name = "SendTaskForm"; + this.Text = "SendTaskForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SendTaskForm_FormClosing); + this.Load += new System.EventHandler(this.SendTaskForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit_ChatType.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkedComboBoxEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.CheckEdit checkEdit1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.DateTimePicker dateTimePicker1; + private DevExpress.XtraEditors.LabelControl labelControl8; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.CheckedComboBoxEdit checkedComboBoxEdit_ChatType; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/SendTaskForm.cs b/应用/Weixin.CircleTools/SendTaskForm.cs new file mode 100644 index 0000000..812f933 --- /dev/null +++ b/应用/Weixin.CircleTools/SendTaskForm.cs @@ -0,0 +1,150 @@ +using Api.Framework; +using Api.Framework.Tools; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; +using Weixin.CircleTools.Entitys; +using Weixin.CircleTools.Properties; +using static CircleFriendsTools.Enums; + +namespace Weixin.CircleTools +{ + public partial class SendTaskForm : BaseForm + { + public SendTaskForm() + { + InitializeComponent(); + this.Text = Resources.PluginFormAddSendTask; + taskinfo = null; + } + + private fl_plugin_circletools_taskinfos taskinfo = null; + + public SendTaskForm(fl_plugin_circletools_taskinfos taskinfo) + { + InitializeComponent(); + this.Text = Resources.PluginFormUpdateSendTask; + this.taskinfo = taskinfo; + + #region 将要修改的对象复制到控件中 + textEdit1.Text = taskinfo.task_name; + dateTimePicker1.Value = DateTime.Parse(taskinfo.task_time); + textBox1.Text = taskinfo.task_sendtext; + checkEdit1.Checked = (taskinfo.is_circulate == ChooseType.是); + textBox2.Text = taskinfo.task_comment; + #endregion + + } + + private void SendTaskForm_Load(object sender, EventArgs e) + { + foreach (WorkingDayType item in Enum.GetValues(typeof(WorkingDayType))) + { + checkedComboBoxEdit1.Properties.Items.Add(item.ToString()); + } + if (taskinfo != null) + checkedComboBoxEdit1.Text = taskinfo.task_working_day;//赋值 + + _RefreshRobotList(taskinfo == null ? null : taskinfo.robotnames.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList()); + } + + private void _RefreshRobotList(List<string> data = null) + { + try + { + checkedComboBoxEdit_ChatType.Properties.Items.Clear(); + var clients = Chat.Framework.ChatClient.WXClient; + foreach (var item in clients.Values) + { + if (item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 || item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信) + { + if (data != null && data.FirstOrDefault(f => f == item.WeixinHao) != null) + checkedComboBoxEdit_ChatType.Properties.Items.Add(item.WeixinHao, item.User.Nick, CheckState.Checked, true); + else + checkedComboBoxEdit_ChatType.Properties.Items.Add(item.WeixinHao, item.User.Nick, CheckState.Unchecked, true); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void SendTaskForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) + { + e.Cancel = true; + throw new Exception("请填写任务名称!"); + } + else if (string.IsNullOrWhiteSpace(checkedComboBoxEdit1.Text)) + { + e.Cancel = true; + throw new Exception("请勾选工作日!"); + } + else if (string.IsNullOrWhiteSpace(dateTimePicker1.Text)) + { + e.Cancel = true; + throw new Exception("请设置发送时间点!"); + } + else if (string.IsNullOrWhiteSpace(textBox1.Text)) + { + e.Cancel = true; + throw new Exception("请填写发送的内容!"); + } + if (!e.Cancel) + { + var session = ApiClient.GetSession(); + if (taskinfo == null) + taskinfo = new fl_plugin_circletools_taskinfos(); + + //taskinfo.task_name = textEdit1.Text.Trim(); + //taskinfo.task_working_day = checkedComboBoxEdit1.Text.Trim(); + //taskinfo.task_time = dateTimePicker1.Value.ToString("HH:mm"); + //taskinfo.task_sendtext = richTextBox1.Text.Trim(); + //taskinfo.task_comment = richTextBox2.Text; + //taskinfo.is_circulate = checkEdit1.Checked ? ChooseType.是 : ChooseType.否; + + //session.Saveable(taskinfo).ExecuteCommand(); //使用这个会出现转换失败 + + taskinfo.is_circulate = checkEdit1.Checked ? ChooseType.是 : ChooseType.否; + taskinfo.task_name = textEdit1.Text.Trim(); + taskinfo.task_working_day = checkedComboBoxEdit1.Text.Trim(); + taskinfo.task_time = dateTimePicker1.Value.ToString("HH:mm"); + taskinfo.task_sendtext = textBox1.Text; + taskinfo.task_comment = textBox2.Text; + taskinfo.robotnames = checkedComboBoxEdit_ChatType.EditValue.ToString(); + + + var sql = string.Empty; + if (taskinfo.id == 0) + { + //sql = "insert into fl_plugin_circletools_taskinfos (task_name,task_working_day,task_time,task_sendtext,is_circulate,task_comment,robotnames) values('" + textEdit1.Text.Trim() + "','" + checkedComboBoxEdit1.Text.Trim() + "','" + dateTimePicker1.Value.ToString("HH:mm") + "','" + content + "','" + (checkEdit1.Checked ? 1 : 0) + "','" + comment + "','" + checkedComboBoxEdit_ChatType.EditValue + "')"; + session.Insertable(taskinfo).ExecuteCommand(); + } + else + { + //sql = "update fl_plugin_circletools_taskinfos set task_name = '" + textEdit1.Text.Trim() + "',task_working_day = '" + checkedComboBoxEdit1.Text.Trim() + "',task_time = '" + dateTimePicker1.Value.ToString("HH:mm") + "',task_sendtext = '" + content + "',is_circulate = '" + (checkEdit1.Checked ? 1 : 0) + "',task_comment = '" + comment + "',robotnames = '" + checkedComboBoxEdit_ChatType.EditValue + "' where id = " + taskinfo.id; + + session.Updateable(taskinfo).ExecuteCommand(); + } + + //session.ExcuteSQL(sql, new { }); + this.DialogResult = DialogResult.OK; + } + } + catch (Exception ex) + { + if (XtraMessageBox.Show(ex.Message + " 是否继续?", "系统提示", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1) == DialogResult.No) + e.Cancel = false; + } + } + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/SendTaskForm.resx b/应用/Weixin.CircleTools/SendTaskForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/Weixin.CircleTools/SendTaskForm.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/SessionExt.cs b/应用/Weixin.CircleTools/SessionExt.cs new file mode 100644 index 0000000..e707281 --- /dev/null +++ b/应用/Weixin.CircleTools/SessionExt.cs @@ -0,0 +1,79 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System.Collections.Generic; +using Weixin.CircleTools.Entitys; +using Weixin.CircleTools.Properties; + +namespace Weixin.CircleTools +{ + public static class SessionExt + { + const string taskinfos_temp_list = "taskinfos_temp_list"; + public static List<fl_plugin_circletools_taskinfos> FindTaskInfosTempGroups(this SqlSugarClient session, bool refresh = false) + { + for (int i = 0; i < 2; i++) + { + try + { + var pddinfo_temp_groups = ApiClient.Cache.Get<List<fl_plugin_circletools_taskinfos>>(taskinfos_temp_list);//根据KEY、获得缓存 + if (refresh || pddinfo_temp_groups == null) + { + pddinfo_temp_groups = session.Find<fl_plugin_circletools_taskinfos>("select * from fl_plugin_circletools_taskinfos"); + ApiClient.Cache.Set(taskinfos_temp_list, pddinfo_temp_groups, 60); + } + return pddinfo_temp_groups; + } + catch (System.Exception) + { + ApiClient.Cache.Remove(taskinfos_temp_list); + continue; + } + } + return new List<fl_plugin_circletools_taskinfos>(); + } + + + //------------------------------------------------------------------------------- + + + const string tbinfo_temp_list_adzones = "tbinfo_temp_list_adzones"; + + /// <summary> + /// 获取fl_plugin_tbrebate_tbtgw表的数据集合缓存 + /// </summary> + /// <param name="session"></param> + /// <param name="refresh">刷新</param> + /// <returns></returns> + public static List<tbinfo_temp> FindTbInfoTempGroups(this SqlSugarClient session, bool refresh = false) + { + for (int i = 0; i < 2; i++) + { + try + { + var tbinfo_temp_groups = ApiClient.Cache.Get<List<tbinfo_temp>>(tbinfo_temp_list_adzones);//根据KEY、获得缓存 + if (refresh || tbinfo_temp_groups == null) + { + tbinfo_temp_groups = session.Find<tbinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = @allianceId and custom_type = @customType) flag on ri.id = flag.ID", new { allianceId = (int)CpsType.阿里妈妈, customType = Resources.SoftwareType }); + ApiClient.Cache.Set(tbinfo_temp_list_adzones, tbinfo_temp_groups, 60); + } + return tbinfo_temp_groups; + } + catch (System.Exception) + { + ApiClient.Cache.Remove(tbinfo_temp_list_adzones); + continue; + } + } + return new List<tbinfo_temp>(); + } + + public static void Clear() + { + ApiClient.Cache.Remove(taskinfos_temp_list); + ApiClient.Cache.Remove(tbinfo_temp_list_adzones); + } + + } +} diff --git a/应用/Weixin.CircleTools/SetSendModelForm.Designer.cs b/应用/Weixin.CircleTools/SetSendModelForm.Designer.cs new file mode 100644 index 0000000..cae1ef8 --- /dev/null +++ b/应用/Weixin.CircleTools/SetSendModelForm.Designer.cs @@ -0,0 +1,211 @@ +namespace Weixin.CircleTools +{ + partial class SetSendModelForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.button3 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + this.SuspendLayout(); + // + // panelControl1 + // + this.panelControl1.Controls.Add(this.groupControl1); + this.panelControl1.Controls.Add(this.gridControl3); + this.panelControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panelControl1.Location = new System.Drawing.Point(0, 0); + this.panelControl1.Name = "panelControl1"; + this.panelControl1.Size = new System.Drawing.Size(649, 387); + this.panelControl1.TabIndex = 0; + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.button3); + this.groupControl1.Controls.Add(this.button2); + this.groupControl1.Controls.Add(this.button1); + this.groupControl1.Controls.Add(this.memoEdit1); + this.groupControl1.Controls.Add(this.label2); + this.groupControl1.Controls.Add(this.label1); + this.groupControl1.Controls.Add(this.textBox1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Right; + this.groupControl1.Location = new System.Drawing.Point(269, 2); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(378, 383); + this.groupControl1.TabIndex = 18; + this.groupControl1.Text = "编辑区"; + // + // button3 + // + this.button3.Location = new System.Drawing.Point(252, 340); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(75, 23); + this.button3.TabIndex = 5; + this.button3.Text = "删除"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(150, 340); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 23); + this.button2.TabIndex = 5; + this.button2.Text = "添加"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(39, 340); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 4; + this.button1.Text = "更新"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(29, 117); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(317, 207); + this.memoEdit1.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(26, 100); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 2; + this.label2.Text = "文案内容:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(26, 45); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 14); + this.label1.TabIndex = 1; + this.label1.Text = "名称:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(29, 62); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(317, 22); + this.textBox1.TabIndex = 0; + // + // gridControl3 + // + this.gridControl3.Dock = System.Windows.Forms.DockStyle.Left; + this.gridControl3.Location = new System.Drawing.Point(2, 2); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.Size = new System.Drawing.Size(261, 383); + this.gridControl3.TabIndex = 17; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // gridView3 + // + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn12}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsView.ShowGroupPanel = false; + this.gridView3.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView3_RowCellClick); + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn12.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "名称"; + this.gridColumn12.FieldName = "ModelName"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 0; + this.gridColumn12.Width = 335; + // + // SetSendModelForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(649, 387); + this.Controls.Add(this.panelControl1); + this.Name = "SetSendModelForm"; + this.Text = "编辑模板"; + this.Load += new System.EventHandler(this.SetSendModelForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.PanelControl panelControl1; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraEditors.GroupControl groupControl1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/SetSendModelForm.cs b/应用/Weixin.CircleTools/SetSendModelForm.cs new file mode 100644 index 0000000..ea0b6f6 --- /dev/null +++ b/应用/Weixin.CircleTools/SetSendModelForm.cs @@ -0,0 +1,135 @@ +using CircleFriendsTools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Weixin.CircleTools +{ + public partial class SetSendModelForm : BaseForm + { + public SetSendModelForm() + { + InitializeComponent(); + } + + /// <summary> + /// 更新 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void button1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("名称不能为空"); + if (string.IsNullOrWhiteSpace(memoEdit1.Text)) throw new Exception("文案不能为空"); + var result = Class1.Config.send_templates.FirstOrDefault(f => f.ModelName.Trim() == textBox1.Text.Trim()); + if (result == null) throw new Exception("该模板找不到"); + result.Content = memoEdit1.Text; + Api.Framework.Tools.Util.Save(Class1.Config); + ShowSuccess("更新成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + ShowContentModel(); + } + } + + private void SetSendModelForm_Load(object sender, EventArgs e) + { + ShowContentModel(); + } + + /// <summary> + /// 显示一键发送模板(刷新) + /// </summary> + private void ShowContentModel() + { + try + { + List<object> obj = new List<object>(); + foreach (var item in Class1.Config.send_templates) + { + obj.Add(new { ModelName = item.ModelName }); + } + gridControl3.DataSource = obj; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView3_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + var selectRow = gridView3.GetSelectedRows()[0]; + var modelName = this.gridView3.GetRowCellValue(selectRow, "ModelName").ToString();//获取列的数据 + textBox1.Text = modelName; + var sendModel = Class1.Config.send_templates.FirstOrDefault(f => f.ModelName == modelName); + if (sendModel != null) + memoEdit1.Text = sendModel.Content; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button2_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("名称不能为空"); + if (string.IsNullOrWhiteSpace(memoEdit1.Text)) throw new Exception("文案不能为空"); + var result = Class1.Config.send_templates.FirstOrDefault(f => f.ModelName.Trim() == textBox1.Text.Trim()); + if (result != null) throw new Exception("已存在该名称"); + Class1.Config.send_templates.Add(new ContentModel { ModelName = textBox1.Text.Trim(), Content = memoEdit1.Text.Trim() }); + Api.Framework.Tools.Util.Save(Class1.Config); + ShowSuccess("添加成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + ShowContentModel(); + } + } + + private void button3_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("请选择要删除的模板"); + var result = Class1.Config.send_templates.FirstOrDefault(f => f.ModelName.Trim() == textBox1.Text.Trim()); + if (result == null) throw new Exception("模板不存在"); + Class1.Config.send_templates.Remove(result); + Api.Framework.Tools.Util.Save(Class1.Config); + ShowSuccess("删除成功!"); + } + catch (Exception ex) + { + ShowError(ex); + } + finally + { + ShowContentModel(); + } + } + + } +} diff --git a/应用/Weixin.CircleTools/SetSendModelForm.resx b/应用/Weixin.CircleTools/SetSendModelForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/Weixin.CircleTools/SetSendModelForm.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/SetTGWForm.Designer.cs b/应用/Weixin.CircleTools/SetTGWForm.Designer.cs new file mode 100644 index 0000000..93dd8e0 --- /dev/null +++ b/应用/Weixin.CircleTools/SetTGWForm.Designer.cs @@ -0,0 +1,269 @@ +namespace Weixin.CircleTools +{ + partial class SetTGWForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(); + this.删除选中阿里妈妈推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除选中京东推广位ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.label1 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.SuspendLayout(); + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 408); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(858, 36); + this.pageControl1.TabIndex = 15; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(1, 1); + this.gridControl1.MainView = this.gridView2; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(857, 407); + this.gridControl1.TabIndex = 16; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中阿里妈妈推广位ToolStripMenuItem, + this.删除选中京东推广位ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(185, 48); + // + // 删除选中阿里妈妈推广位ToolStripMenuItem + // + this.删除选中阿里妈妈推广位ToolStripMenuItem.Name = "删除选中阿里妈妈推广位ToolStripMenuItem"; + this.删除选中阿里妈妈推广位ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除选中阿里妈妈推广位ToolStripMenuItem.Text = "删除选中淘宝推广位"; + this.删除选中阿里妈妈推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除选中阿里妈妈推广位ToolStripMenuItem_Click); + // + // 删除选中京东推广位ToolStripMenuItem + // + this.删除选中京东推广位ToolStripMenuItem.Name = "删除选中京东推广位ToolStripMenuItem"; + this.删除选中京东推广位ToolStripMenuItem.Size = new System.Drawing.Size(184, 22); + this.删除选中京东推广位ToolStripMenuItem.Text = "删除选中京东推广位"; + this.删除选中京东推广位ToolStripMenuItem.Visible = false; + this.删除选中京东推广位ToolStripMenuItem.Click += new System.EventHandler(this.删除选中京东推广位ToolStripMenuItem_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn2, + this.gridColumn1, + this.gridColumn17}); + this.gridView2.GridControl = this.gridControl1; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "ID"; + this.gridColumn11.FieldName = "ID"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + this.gridColumn11.Width = 50; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "平台类型"; + this.gridColumn12.FieldName = "chattype"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + this.gridColumn12.Width = 99; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "账号"; + this.gridColumn13.FieldName = "name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 2; + this.gridColumn13.Width = 148; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "账号昵称"; + this.gridColumn14.FieldName = "nick"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + this.gridColumn14.Width = 125; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn15.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn15.AppearanceCell.Options.UseFont = true; + this.gridColumn15.AppearanceCell.Options.UseForeColor = true; + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "淘宝推广位"; + this.gridColumn15.FieldName = "adzone_name"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 4; + this.gridColumn15.Width = 135; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn2.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn2.AppearanceCell.Options.UseFont = true; + this.gridColumn2.AppearanceCell.Options.UseForeColor = true; + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn2.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "京东推广位"; + this.gridColumn2.FieldName = "adzone_name_jd"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.Width = 130; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn1.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn1.AppearanceCell.Options.UseFont = true; + this.gridColumn1.AppearanceCell.Options.UseForeColor = true; + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn1.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "拼多多推广位"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "禁止使用"; + this.gridColumn17.FieldName = "onoff"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + this.gridColumn17.Width = 66; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(170, 159); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 17; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // SetTGWForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(858, 444); + this.Controls.Add(this.label1); + this.Controls.Add(this.gridControl1); + this.Controls.Add(this.pageControl1); + this.Name = "SetTGWForm"; + this.Text = "SetTGWForm"; + this.Load += new System.EventHandler(this.SetTGWForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private System.Windows.Forms.Label label1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中阿里妈妈推广位ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除选中京东推广位ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/SetTGWForm.cs b/应用/Weixin.CircleTools/SetTGWForm.cs new file mode 100644 index 0000000..1eafcb3 --- /dev/null +++ b/应用/Weixin.CircleTools/SetTGWForm.cs @@ -0,0 +1,261 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using Weixin.CircleTools.Entitys; +using Weixin.CircleTools.Properties; + +namespace Weixin.CircleTools +{ + public partial class SetTGWForm : BaseForm + { + public SetTGWForm() + { + InitializeComponent(); + this.Text = Resources.AutoTurnTGWFormTitle; + } + + private void SetTGWForm_Load(object sender, EventArgs e) + { + try + { + #region 加载所有的账号 + + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<tbinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.adzone_pid_cps_name as adzone_pid_cps_name,flag2.adzone_pid as adzone_pid_jd,flag2.adzone_name as adzone_name_jd,flag2.adzone_pid_cps_name as adzone_pid_cps_name_jd ,flag.onoff as onoff from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.阿里妈妈}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.京东联盟}' and custom_type = '{Resources.SoftwareType}') flag2 on ri.id = flag2.ID", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label1.Visible = gridView2.RowCount == 0; + + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView2_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + var session = ApiClient.GetSession(); + if (e.Column.FieldName == "adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + #region 淘宝推广位 + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + if (e.Column.FieldName == "adzone_name") + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + } + session.SaveOrUpdate(adzone); + } + else + { + //session.BeginTransaction(); + try + { + if (e.Column.FieldName == "adzone_name") + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + #endregion + } + } + + //if (e.Column.FieldName == "adzone_name_jd") + //{ + // var tgw = CpsClient.SelectTuiguangwei(CpsType.京东联盟); + // if (tgw != null) + // { + // #region 京东推广位 + // var adzone_jd = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + // if (adzone_jd != null)//数据库中存在的情况 + // { + // if (e.Column.FieldName == "adzone_name_jd") + // { + // adzone_jd.adzone_pid_cps_name = tgw.Member.username; + // adzone_jd.adzone_pid = tgw.Pid; + // adzone_jd.adzone_name = tgw.Name; + // } + // session.SaveOrUpdate(adzone_jd); + // } + // else + // { + // //session.BeginTransaction(); + // try + // { + // if (e.Column.FieldName == "adzone_name_jd") + // adzone_jd = new fl_adzone_info() + // { + // custom_type = Resources.SoftwareType, //自定义类型 + // adzone_name = tgw.Name, //推广位名称 + // adzone_pid = tgw.Pid, //推广位pid + // adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + // alliance_id = (int)CpsType.京东联盟, //联盟id + // robot_id = int.Parse(id), //机器人id + // group_id = string.Empty, //群id + // member_id = 0, //私人id + // is_download = false, //不下载 + // onoff = false //不禁用 + // }; + // session.SaveOrUpdate(adzone_jd); + // if (0 == adzone_jd.id) + // throw new Exception("对不起,推广位设置异常,请稍后重试!"); + // } + // catch (Exception ex) + // { + // ShowError(ex); + // } + // } + // #endregion + // } + //} + pageControl1.GotoPage(1); + session.FindTbInfoTempGroups(true); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况,并且推广位设置了 + adzone.onoff = !adzone.onoff; + else + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = string.Empty, //推广位名称 + adzone_pid = string.Empty, //推广位pid + adzone_pid_cps_name = string.Empty, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = true //不禁用 + }; + session.SaveOrUpdate(adzone); + + pageControl1.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindTbInfoTempGroups(true); + session.FindAdzoneInfos(true); + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if ((e.Column.FieldName == "adzone_name" || e.Column.FieldName == "adzone_name_jd") && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中阿里妈妈推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + session.Deleteable(adzone).ExecuteCommand(); + pageControl1.GotoPage(1); + session.FindTbInfoTempGroups(true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中京东推广位ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + var session = ApiClient.GetSession(); + var adzone_jd = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone_jd != null)//数据库中存在的情况 + { + session.Deleteable(adzone_jd).ExecuteCommand(); + pageControl1.GotoPage(1); + session.FindTbInfoTempGroups(true); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/SetTGWForm.resx b/应用/Weixin.CircleTools/SetTGWForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Weixin.CircleTools/SetTGWForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/TbApi.cs b/应用/Weixin.CircleTools/TbApi.cs new file mode 100644 index 0000000..cb8867d --- /dev/null +++ b/应用/Weixin.CircleTools/TbApi.cs @@ -0,0 +1,221 @@ +using Api.Framework.Cps; +using Api.Framework.Tools; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using static Api.Framework.Tools.TBHelper.TbAnalysis; + +namespace Weixin.CircleTools +{ + public class TbApi + { + /// <summary> + /// 将别人的淘口令转成自己推广位的淘口令 + /// </summary> + /// <param name="tkl">别人的淘口令</param> + /// <param name="api">淘宝cps对象</param> + /// <returns></returns> + public TklInfo TKLToOwnTKL(string _tkl, string pid, AlimamaApi api, string biz_scene_id = "2") + { + try + { + int num = 0; + var pids = pid.Split('_'); + Next: + var tbAnalysis = new TBHelper.TbAnalysis(); + var itemId = string.Empty; + try + { + itemId = tbAnalysis.FindItemIdByUrlAndTklAndMkl(_tkl, api, pids); + } + catch (Exception ex) + { } + + if (!string.IsNullOrWhiteSpace(itemId)) + { + var activityIdStr = tbAnalysis.activityId; + + if (string.IsNullOrWhiteSpace(activityIdStr)) + { + //activityIdStr = TBHelper.FindGoodsActivityIdAll(itemId, out sellerId, out payPrice); + var exCoupon = TBHelper.FindGoodsCouponInfo(itemId); + if (exCoupon != null) + activityIdStr = exCoupon.activityId; + } + + biz_scene_id = TBHelper.TbAnalysis.BizSceneId(itemId); + + var privilege = api.SendTaobao("taobao.tbk.privilege.get", new { item_id = itemId, site_id = pids[2], adzone_id = pids[3], biz_scene_id = biz_scene_id }); + if (privilege == null) + return null; + var privilege_data = privilege["data"] as Dictionary<string, object>; + + #region 生成自己的淘口令 + + return tbAnalysis.FindTKL(privilege_data["coupon_click_url"].ToString() + (string.IsNullOrWhiteSpace(activityIdStr) ? string.Empty : "&activityId=" + activityIdStr), api); + #endregion + } + else + { + if (num <= 2) + { + num++; + goto Next; + } + } + } + catch (Exception) + { } + return null; + } + + /// <summary> + /// 通过优惠券链接获取淘宝宝贝的id + /// </summary> + /// <param name="url"></param> + private string CouponByItemId(string url, AlimamaApi api) + { + try + { + var tbAnalysis = new Api.Framework.Tools.TBHelper.TbAnalysis(); + var itemId = tbAnalysis.FindTbItemIdByStr(url); + if (!string.IsNullOrEmpty(itemId)) return itemId; + + if (url.Contains(@"uland.taobao.com/coupon"))//这是针对淘宝联盟有优惠券的接口.//https://uland.taobao.com/coupon/edetail + { + var coupon = api.CheckCoupon(url);//将返利接口转成淘宝宝贝接口 + if (coupon != null) return coupon.itemId; + } + else if (url.Contains(@"s.click.taobao.com"))//这是针对淘宝联盟没有全的接口.//https://s.click.taobao.com/t?e=m + { + var html = string.Empty; + //获得首次Location 地址 + bool first = false; + Next: + string location = GetLocation(url); + if (location.StartsWith("https://s.click.taobao.com/t?e=")) + { + var _location = GetLocation(location); + if (!string.IsNullOrEmpty(_location)) location = _location; + } + if (!string.IsNullOrEmpty(location))//跳转地址存在 + { + if (location.Contains("uland.taobao.com/coupon/edetail?e=")) + { + string tempHtml = GetHTML(location); + tempHtml = HttpHelper.URLDecode(tempHtml); + var uland = Regex.Match(tempHtml, "&req_url=([^\"]+)"); + if (uland.Success) + { + var param_e = Regex.Match(uland.Groups[1].Value, "e=([^&]+)"); + if (!param_e.Success) return string.Empty; + + //var param_result = h5Top.mtop_alimama_union_hsf_coupon_get(uland.Groups[1].Value); + + //// Dictionary<string, object> param_result = Client.ClientPro.GetOpenResult("GetCoupon", "api/alimama.ashx", new { e = param_e.Groups[1].Value, dx = "1", src = "tblm_lmapp", scm = "20140618.1.01010001.s101c6", pid = "mm_33231688_7050284_23466709" }, true) as Dictionary<string, object>; + //if (param_result != null && param_result.ContainsKey("item")) + //{ + // var _item = param_result["item"] as Dictionary<string, object>; + // return "https://item.taobao.com/item.htm?id=" + _item["itemId"]; + //} + + var coupon = api.CheckCoupon(uland.Groups[1].Value); + if (coupon != null) + return coupon.itemId; + } + else + { + //"系统日志,分析地址失败:" + url;} + } + } + else if (location.Contains("uland.taobao.com")) + { + var _reg = Regex.Match(location, "itemId=(\\d+)", RegexOptions.IgnoreCase); + if (_reg.Success) + return _reg.Groups[1].Value; + } + else if (location.Contains("tu=")) + { + //获得二次访问地址 + string next = HttpHelper.URLDecode(location.Replace("http://s.click.taobao.com/t_js?tu=", "").Replace("https://s.click.taobao.com/t_js?tu=", "")); + html = HttpHelper.URLDecode(GetHTML(next, location)); + var reg = Regex.Match(html, "&itemId=(\\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups[1].Value; + } + else + return tbAnalysis.FindTbItemIdByStr(GetHTML(location)); + } + else if (!string.IsNullOrEmpty(location) && !first) + { + url = location; + first = true; + goto Next; + } + } + } + catch (Exception) + { + } + return string.Empty; + } + + private string GetLocation(string url) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = "get", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = "", + Timeout = 5000, + ReadWriteTimeout = 15000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = false, + ProxyIp = "" + }; + HttpResult result = http.GetHtml(item); + return result.Header.Get("Location"); + } + catch (Exception) + { + } + return string.Empty; + } + + private string GetHTML(string url, string rf = "", string postData = "") + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = (postData == "" ? "get" : "post"), + Postdata = (postData == "" ? "" : postData), + IsToLower = false, + Referer = rf, + Timeout = 5000, + ReadWriteTimeout = 15000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = true + }; + HttpResult result = http.GetHtml(item); + return result.Html; + } + catch (Exception) + { } + return string.Empty; + } + + } +} diff --git a/应用/Weixin.CircleTools/Weixin.CircleTools.csproj b/应用/Weixin.CircleTools/Weixin.CircleTools.csproj new file mode 100644 index 0000000..63b3d4e --- /dev/null +++ b/应用/Weixin.CircleTools/Weixin.CircleTools.csproj @@ -0,0 +1,197 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{00191980-D031-4C7D-99AA-69B26C43D2C6}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Weixin.CircleTools</RootNamespace> + <AssemblyName>Weixin.CircleTools</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraScheduler.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraScheduler.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\Newtonsoft.Json.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="AddAutoSendForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="AddAutoSendForm.Designer.cs"> + <DependentUpon>AddAutoSendForm.cs</DependentUpon> + </Compile> + <Compile Include="AnalyzeGoods.cs" /> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Entitys\fl_plugin_circletools_taskinfos.cs" /> + <Compile Include="Entitys\fl_plugin_circletools_tgw.cs" /> + <Compile Include="Entitys\goodsinfos.cs" /> + <Compile Include="Entitys\tbinfo_temp.cs" /> + <Compile Include="Enums.cs" /> + <Compile Include="ImageForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="ImageForm.Designer.cs"> + <DependentUpon>ImageForm.cs</DependentUpon> + </Compile> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="MethodExt.cs" /> + <Compile Include="MonitorThread.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="SendTaskForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="SendTaskForm.Designer.cs"> + <DependentUpon>SendTaskForm.cs</DependentUpon> + </Compile> + <Compile Include="SessionExt.cs" /> + <Compile Include="SetSendModelForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="SetSendModelForm.Designer.cs"> + <DependentUpon>SetSendModelForm.cs</DependentUpon> + </Compile> + <Compile Include="SetTGWForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="SetTGWForm.Designer.cs"> + <DependentUpon>SetTGWForm.cs</DependentUpon> + </Compile> + <Compile Include="TbApi.cs" /> + <Compile Include="XtraForm1.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="XtraForm1.Designer.cs"> + <DependentUpon>XtraForm1.cs</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="AddAutoSendForm.resx"> + <DependentUpon>AddAutoSendForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="ImageForm.resx"> + <DependentUpon>ImageForm.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="SendTaskForm.resx"> + <DependentUpon>SendTaskForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="SetSendModelForm.resx"> + <DependentUpon>SetSendModelForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="SetTGWForm.resx"> + <DependentUpon>SetTGWForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="XtraForm1.resx"> + <DependentUpon>XtraForm1.cs</DependentUpon> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\朋友圈工具.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/Weixin.CircleTools/XtraForm1.Designer.cs b/应用/Weixin.CircleTools/XtraForm1.Designer.cs new file mode 100644 index 0000000..b21b066 --- /dev/null +++ b/应用/Weixin.CircleTools/XtraForm1.Designer.cs @@ -0,0 +1,63 @@ +namespace CircleFriendsTools +{ + partial class XtraForm1 + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.SuspendLayout(); + // + // richTextBox1 + // + this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.richTextBox1.Location = new System.Drawing.Point(0, 0); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.Size = new System.Drawing.Size(462, 402); + this.richTextBox1.TabIndex = 0; + this.richTextBox1.Text = ""; + // + // XtraForm1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(462, 402); + this.Controls.Add(this.richTextBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "XtraForm1"; + this.Text = "XtraForm1"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.XtraForm1_FormClosing); + this.Load += new System.EventHandler(this.XtraForm1_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.RichTextBox richTextBox1; + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/XtraForm1.cs b/应用/Weixin.CircleTools/XtraForm1.cs new file mode 100644 index 0000000..f08c422 --- /dev/null +++ b/应用/Weixin.CircleTools/XtraForm1.cs @@ -0,0 +1,88 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Drawing; +using System.Threading; +using System.Threading.Tasks; +using UI.Framework.Forms; +using Weixin.CircleTools.Properties; + +namespace CircleFriendsTools +{ + public partial class XtraForm1 : BaseForm + { + private string name; //要检测的账号 + + public XtraForm1(string name) + { + InitializeComponent(); + this.Text = Resources.CheckFormTitle; + this.name = name; + } + private void AddText(string text, Color color) + { + if (!this.IsDisposed) + { + this.richTextBox1.Invoke(new Action(delegate + { + richTextBox1.AppendTextColorful(text, color); + + })); + } + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private void XtraForm1_Load(object sender, EventArgs e) + { + richTextBox1.AppendTextColorful($"正在检测....", Color.Black); + Task.Factory.StartNew(delegate + { + try + { + var clients = Chat.Framework.ChatClient.WXClient; + var flag = false;//判断朋友集合中(key值)是否存在,查询的wxId + foreach (WeixinBase item in clients.Values) + { + try + { + if (item.WeixinType == WeixinType.Grpc微信 && item.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + if (!string.IsNullOrWhiteSpace(name)) + { + flag = false; + var ipad = item as WXClientImpl_IPAD; + if (ipad == null) continue; + flag = ipad.GetContact(name) != null ? true : false; + var friends = ipad.Friends; + + if (flag) AddText($"{item.User.Nick}({item.WeixinHao}) 正常", Color.Green); + else AddText($"{item.User.Nick}({item.WeixinHao}) 异常", Color.Red); + } + } + } + catch (Exception ex) + { + AddText($"检测异常:{ex.Message}", Color.Yellow); + } + } + AddText($"检测完毕....", Color.Black); + } + catch (Exception ex) + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + if(!this.IsDisposed)ShowError(ex); + })); + } + } + }, tokenSource.Token); + } + + private void XtraForm1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e) + { + tokenSource.Cancel(); + } + } +} \ No newline at end of file diff --git a/应用/Weixin.CircleTools/XtraForm1.resx b/应用/Weixin.CircleTools/XtraForm1.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/应用/Weixin.CircleTools/XtraForm1.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.JDCirclePromotion/AnalyzeGoods.cs b/应用/Weixin.JDCirclePromotion/AnalyzeGoods.cs new file mode 100644 index 0000000..c117dd7 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/AnalyzeGoods.cs @@ -0,0 +1,237 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.JDCirclePromotion.Entitys; +using static Weixin.JDCirclePromotion.Enums; + +namespace Weixin.JDCirclePromotion +{ + public class AnalyzeGoods + { + /// <summary> + /// 采集数据 + /// </summary> + public void GatherFactory() + { + var session = ApiClient.GetSession(); + try + { + var api = new JingdongApi(CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟)); + + var dic = api.SendJingdong("jd.union.open.goods.jingfen.query", new { goodsReq = new { eliteId = (int)Class1.Config.Category, pageIndex = 1, pageSize = 50, sortName = ((_OrderFieldType)((int)Class1.Config.OrderField)).ToString(), sort = ((int)Class1.Config.Sort == 1 ? "asc" : "desc") } }); + + if (dic != null && dic.ContainsKey("code") && dic["code"].ToString() == "200") + { + if (dic.ContainsKey("data")) + { + var data = dic["data"] as ArrayList; + List<fl_plugin_jdcirclepromotion_goodsinfos> goodsinfos = new List<fl_plugin_jdcirclepromotion_goodsinfos>(); + foreach (Dictionary<string, object> item in data) + { + var goodsinfo = new fl_plugin_jdcirclepromotion_goodsinfos(); + if (item.ContainsKey("commissionInfo")) + { + var commissionInfo = item["commissionInfo"] as Dictionary<string, object>; + if (commissionInfo.ContainsKey("commission")) + goodsinfo.commission = double.Parse(commissionInfo["commission"].ToString());//佣金 + if (commissionInfo.ContainsKey("commissionShare")) + goodsinfo.commissionShare = double.Parse(commissionInfo["commissionShare"].ToString());//佣金比例 + } + + if (item.ContainsKey("couponInfo")) + { + var couponInfo = item["couponInfo"] as Dictionary<string, object>; + if (couponInfo != null) + { + foreach (ArrayList arrays in couponInfo.Values) + { + foreach (Dictionary<string, object> coupon in arrays) + { + if (coupon.ContainsKey("bindType")) + { + var bindType = int.Parse(coupon["bindType"].ToString());//券种类 (优惠券种类:0 - 全品类,1 - 限品类(自营商品),2 - 限店铺,3 - 店铺限商品券) + } + if (coupon.ContainsKey("discount")) + goodsinfo.discount = double.Parse(coupon["discount"].ToString());//券面额 + if (coupon.ContainsKey("link")) + goodsinfo.link = coupon["link"].ToString();//券链接 + if (coupon.ContainsKey("platformType")) + goodsinfo.platformType = int.Parse(coupon["platformType"].ToString());//券使用平台 (平台类型:0 - 全平台券,1 - 限平台券) + if (coupon.ContainsKey("quota")) + goodsinfo.quota = double.Parse(coupon["quota"].ToString());//券消费限额 + if (coupon.ContainsKey("getStartTime")) + goodsinfo.getStartTime = long.Parse(coupon["getStartTime"].ToString());//领取开始时间(时间戳,毫秒) + if (coupon.ContainsKey("getEndTime")) + goodsinfo.getEndTime = long.Parse(coupon["getEndTime"].ToString());//券领取结束时间(时间戳,毫秒) + if (coupon.ContainsKey("useStartTime")) + goodsinfo.useStartTime = long.Parse(coupon["useStartTime"].ToString());//券有效使用开始时间(时间戳,毫秒) + if (coupon.ContainsKey("useEndTime")) + goodsinfo.useEndTime = long.Parse(coupon["useEndTime"].ToString());//券有效使用结束时间(时间戳,毫秒) + break; + } + } + } + } + + if (item.ContainsKey("imageInfo")) + { + var imageInfo = item["imageInfo"] as Dictionary<string, object>; + if (imageInfo != null && imageInfo.Count != 0) + { + if (imageInfo.ContainsKey("imageList")) + { + var imgs = imageInfo["imageList"] as ArrayList; + if (imgs != null && imgs.Count != 0) + { + var tmp = imgs[0] as Dictionary<string,object>; + if (tmp != null && tmp.ContainsKey("url")) + { + goodsinfo.imageurl = tmp["url"].ToString(); + } + } + } + //foreach (ArrayList arrays in imageInfo.Values) + //{ + // foreach (Dictionary<string, object> image in arrays) + // { + // if (image.ContainsKey("url")) + // { + // goodsinfo.imageurl = image["url"].ToString();//图片url + // break; + // } + // } + //} + } + } + + if (item.ContainsKey("inOrderCount30Days")) + goodsinfo.inOrderCount30Days = int.Parse(item["inOrderCount30Days"].ToString());//30天引单数量(月销量) + + if (item.ContainsKey("materialUrl")) + goodsinfo.materialUrl = item["materialUrl"].ToString();//商品落地页 + + if (item.ContainsKey("owner")) + goodsinfo.owner = item["owner"].ToString();//g=自营,p=pop + + if (item.ContainsKey("pinGouInfo"))//拼购信息 + { + var pinGouInfo = item["pinGouInfo"] as Dictionary<string, object>; + if (pinGouInfo != null && pinGouInfo.Count != 0) + { + //这里不清楚什么情况,等遇到在分析 + if (pinGouInfo.ContainsKey("pingouPrice")) + goodsinfo.pingouPrice = double.Parse(pinGouInfo["pingouPrice"].ToString());//拼团价格 + if (pinGouInfo.ContainsKey("pingouTmCount")) + goodsinfo.pingouTmCount = long.Parse(pinGouInfo["pingouTmCount"].ToString());//拼购成团所需人数 + if (pinGouInfo.ContainsKey("pingouUrl")) + goodsinfo.pingouUrl = pinGouInfo["pingouUrl"].ToString(); //拼购落地页url + } + } + + if (item.ContainsKey("priceInfo")) + { + var priceInfo = item["priceInfo"] as Dictionary<string, object>; + if (priceInfo.ContainsKey("price")) + { + goodsinfo.price = double.Parse(priceInfo["price"].ToString());//无线价格 + } + } + + if (item.ContainsKey("skuId")) + goodsinfo.skuId = long.Parse(item["skuId"].ToString());//商品ID + if (item.ContainsKey("skuName")) + goodsinfo.skuName = item["skuName"].ToString();//商品名称 + + goodsinfos.Add(goodsinfo); + } + try + { + session.BeginTransaction(); + session.Insertable<fl_plugin_jdcirclepromotion_goodsinfos>(goodsinfos).ExecuteCommand(); + session.Commit(); + } + catch (Exception) + { + session.Rollback(); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"京东采集:{ex.Message}{ex.StackTrace}"); + } + } + + /// <summary> + /// 通过商品的id查询返回获取到自己返利商品信息 + /// </summary> + /// <param name="goods_id"></param> + /// <returns></returns> + public string FindGoodsInfoToGoodsId(fl_plugin_jdcirclepromotion_goodsinfos goodsinfo, fl_cps_member member = null, string pid = "") + { + try + { + member = (member == null ? CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟) : member); + if (member != null) + { + var api = CpsClient.CreateJingdongRequest(member); + var obj = api.SendJingdong("jd.union.open.goods.query", new { goodsReqDTO = new { skuIds = new string[] { goodsinfo.skuId.ToString() } } }); + + //解析商品,获取商品的信息 + var goodData = obj.ConvertToObj<goodInfo_temp>(); + if (goodData.data != null) + { + foreach (Dictionary<string, object> _goodinfo in goodData.data) + { + var buyshorturl = string.Empty; //转连后的地址 + Dictionary<string, object> conversionlinkresult = null; //查询到的转换链接对象 + var positionId = pid.Substring(pid.LastIndexOf("_") + 1); + if (string.IsNullOrWhiteSpace(goodsinfo.link)) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{goodsinfo.skuId}.html", positionId = positionId, unionId = member.usernick } });//宝贝id 和 用户的目标推客的联盟id + } + else + { + try + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{goodsinfo.skuId}.html", positionId = positionId, unionId = member.usernick, couponUrl = goodsinfo.link } }); + } + catch (Exception) + { + conversionlinkresult = api.SendJingdong("jd.union.open.promotion.byunionid.get", new { promotionCodeReq = new { materialId = $@"https://item.m.jd.com/product/{goodsinfo.skuId}.html", positionId = positionId, unionId = member.usernick } });//宝贝id 和 用户的目标推客的联盟id + goodsinfo.discount = 0; + goodsinfo.link = string.Empty; + } + } + if (conversionlinkresult != null) + { + if (conversionlinkresult["code"].ToString() != "200") throw new Exception($"京东查询接口调用失败:{conversionlinkresult["message"].ToString()}");//抛出错误信息 + if (conversionlinkresult.ContainsKey("data")) + { + var data = conversionlinkresult["data"] as Dictionary<string, object>; + if (data.ContainsKey("shortURL")) + return buyshorturl = data["shortURL"].ToString();//购买短连接 + } + if (string.IsNullOrWhiteSpace(buyshorturl)) throw new Exception("京东转链失败,请稍后重试"); + } + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + } +} diff --git a/应用/Weixin.JDCirclePromotion/Class1.cs b/应用/Weixin.JDCirclePromotion/Class1.cs new file mode 100644 index 0000000..29bdd98 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Class1.cs @@ -0,0 +1,91 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.JDCirclePromotion.Entitys; +using Weixin.JDCirclePromotion.Properties; + +namespace Weixin.JDCirclePromotion +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + this.Logo = Resources.京东发单; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<fl_plugin_jdcirclepromotion_goodsinfos>()) session.CreateTable<fl_plugin_jdcirclepromotion_goodsinfos>(); + #endregion + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + + Config = this.ReadConfig<Config>(); //创建配置文件 + TimerTask.NewTimer<SendCircleFriendThread>(60); //创建线程 - 发送朋友圈的线程 60秒 + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + {} + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close<SendCircleFriendThread>(); //关闭线程 + if (mainForm != null) + { + mainForm.CloseForm(); //关闭窗体 + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } + +} diff --git a/应用/Weixin.JDCirclePromotion/Config.cs b/应用/Weixin.JDCirclePromotion/Config.cs new file mode 100644 index 0000000..3c9fe1b --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Config.cs @@ -0,0 +1,267 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using UI.Framework.Entitys; +using static Api.Framework.ApiClient; +using static Weixin.JDCirclePromotion.Enums; + +namespace Weixin.JDCirclePromotion +{ + [Config(Name = "插件-京东发单-配置")] + public class Config + { + #region 发单功能 + + #region 采集 + /// <summary> + /// 发单条件 - 商品最低售价 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("01.采集开关"), DefaultValue(SwitchType.开启) + ] + public SwitchType Switch { get; set; } + + /// <summary> + /// 采集数据触发数量 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("02.采集触发量"), DefaultValue(10), + Description(@"当采集开关为开启时,该值为一个采集点,当采集剩余的商品数量少于等于采集触发量,将自动进行采集操作") + ] + public int GatherTouchNum { get; set; } + + private CategoryType _Category; + /// <summary> + /// 发单条件 - 类目 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("03.类目"), DefaultValue(CategoryType.为你推荐), + Description(@"筛选类目:好券商品、精选卖场、9.9包邮、京东配送、实时热销榜、为你推荐、数码家电、超市、母婴玩具、家具日用、美妆穿搭、图书文具、今日必推、京东好物、京东秒杀、拼购商品、高收益榜、自营热卖榜、新品首发、自营、京东爆品、首购商品、高佣榜单、视频商品、历史最低价商品榜") + ] + public CategoryType Category + { + get + { + try + { + return _Category; + } + catch (Exception) + { + return CategoryType.为你推荐; + } + + } + set + { + _Category = value; + } + } + + /// <summary> + /// 发单条件 - 排序字段 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("04.排序字段"), DefaultValue(OrderFieldType.月销量), + Description(@"筛选类目:单价、佣金比例、佣金、月销量、评论数、好评数") + ] + public OrderFieldType OrderField { get; set; } + + /// <summary> + /// 发单条件 - 排序 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("05.排序方式"), DefaultValue(SortType.降序), + Description(@"排序方式:升序、降序") + ] + public SortType Sort { get; set; } + #endregion + + #region 开始时间 + + /// <summary> + /// 朋友圈发单二维码模板 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("01.发单二维码模板"), DefaultValue(QrImageType.模板B), + Description(@"朋友圈发单二维码模板") + ] + public QrImageType Model { get; set; } + + private string[] _sendTaskTimes; + /// <summary> + /// 发送任务时间段 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("02.发送任务时间段"), + Description(@"每一行为一个发送时间段 +格式:时间1-时间2 +注:时间1 必须大于 时间2") + ] + public string[] SendTaskTimes //{ get; set; } + { + get { return _sendTaskTimes; } + set + { + var sendTaskTimes = value as string[]; + if (sendTaskTimes != null && sendTaskTimes.Length != 0) + { + for (int i = 0; i < sendTaskTimes.Length; i++) + { + var times = sendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0]); + var end = DateTime.Parse(times[1]); + if (begin >= end) + throw new Exception($"开始时间必须小于结束时间:[{sendTaskTimes[i]}]"); + } + } + } + _sendTaskTimes = value; + } + } + + private int _sendGoodsImageNum; + /// <summary> + /// 发送商品图片数量 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("03.发送推广图片数量"), DefaultValue(9), + Description(@"发送朋友圈推广图片数量,最多9张图片") + ] + public int SendGoodsImageNum + { + get { return _sendGoodsImageNum; } + set + { + if (9 < value || value < 1) throw new Exception("发送推广图片数量应该大于等于1,小于等于9"); + _sendGoodsImageNum = value; + } + } + + /// <summary> + /// 朋友圈发送间隔,单位 分 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("04.朋友圈发送间隔"), DefaultValue(120), + Description(@"朋友圈推广商品间隔,单位 分") + ] + public double Interval_Circle { get; set; } + + /// <summary> + /// 发送的文字内容 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("05.发送的文字内容"), DefaultValue(@"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +补贴奖励和帮助渠道 + +手机京东分享宝贝给我 +可以查询优惠券款下单 + +还有网购红包领哦"), + Description(@"发送朋友圈时的文本内容"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Content_Circle { get; set; } + + /// <summary> + /// 宝贝描述语 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("06.宝贝描述语"), DefaultValue(@""), + Description(@"图片中宝贝描述信息,为空时以采集到的数据为准. +支持变量:[商品标题]、[商品描述]、[已售数量]、[店铺名称]、[优惠券门槛金额]、[优惠券金额]、[优惠券数量]、[商品单买价]、[券后单买价]、[单买地址]、[商品拼团价]、[券后拼团价]、[拼团地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Goods_Desc { get; set; } + /// <summary> + /// 朋友圈追加评语 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("07.朋友圈追加评语"), DefaultValue(@""), + Description(@"朋友圈商品推广之后,追加评语"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AdditionalComment { get; set; } + /// <summary> + /// 记录发送的时间 + /// </summary> + [Browsable(false)] + public DateTime RecordSendTime { get; set; } + + #endregion + + /// <summary> + /// 自动清理 + /// </summary> + [ + Category("3)、定时清理"), DisplayName("01.定时清理"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将在设置的时间进行采集数据的清空操作") + ] + public SwitchType Auto_IsClear { get; set; } + + private string _autoClearTaskTimes; + [ + Category("3)、定时清理"), DisplayName("02.定时清理时间"), + Description(@"定时清理时间 +格式:HH:mm +例:23:59 +注:时间为24小时制") + ] + public string AutoClearTaskTimes //{ get; set; } + { + get { return _autoClearTaskTimes; } + set + { + try + { + var time = value as string; + var _time = DateTime.Parse(time); + } + catch (Exception) + { + throw new Exception($"时间格式不正确"); + } + _autoClearTaskTimes = value; + } + } + + #endregion + + public Config() + { + this.Auto_IsClear = SwitchType.开启; + this.Switch = SwitchType.开启; + this.GatherTouchNum = 10; + this.Category = CategoryType.为你推荐; + this.OrderField = OrderFieldType.月销量; + this.Sort = SortType.降序; + this.Content_Circle = @"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +补贴奖励和帮助渠道 + +手机京东分享宝贝给我 +可以查询优惠券款下单 + +还有网购红包领哦"; + this.SendGoodsImageNum = 9; + this._sendGoodsImageNum = 9; + this.Interval_Circle = 120; + this.SendTaskTimes = new string[] { }; + this._sendTaskTimes = new string[] { "09:00-22:00" }; + this._autoClearTaskTimes = "23:59"; + this.Model = QrImageType.模板B; + this.AdditionalComment = string.Empty; + this.Goods_Desc = string.Empty; + } + + } +} diff --git a/应用/Weixin.JDCirclePromotion/Entitys/fl_plugin_jdcirclepromotion_goodsinfos.cs b/应用/Weixin.JDCirclePromotion/Entitys/fl_plugin_jdcirclepromotion_goodsinfos.cs new file mode 100644 index 0000000..3519842 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Entitys/fl_plugin_jdcirclepromotion_goodsinfos.cs @@ -0,0 +1,118 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Weixin.JDCirclePromotion.Enums; + +namespace Weixin.JDCirclePromotion.Entitys +{ + public class fl_plugin_jdcirclepromotion_goodsinfos : base_model + { + /// <summary> + /// 佣金 + /// </summary> + public double commission { get; set; } + /// <summary> + /// 佣金比例 + /// </summary> + public double commissionShare { get; set; } + /// <summary> + /// 券种类 (优惠券种类:0 - 全品类,1 - 限品类(自营商品),2 - 限店铺,3 - 店铺限商品券) + /// </summary> + public int bindType { get; set; } + /// <summary> + /// 券面额 + /// </summary> + public double discount { get; set; } + /// <summary> + /// 券链接 + /// </summary> + public string link { get; set; } + /// <summary> + /// 券使用平台 (平台类型:0 - 全平台券,1 - 限平台券) + /// </summary> + public int platformType { get; set; } + /// <summary> + /// 券消费限额 + /// </summary> + public double quota { get; set; } + /// <summary> + /// 领取开始时间(时间戳,毫秒) + /// </summary> + public long getStartTime { get; set; } + /// <summary> + /// 券领取结束时间(时间戳,毫秒) + /// </summary> + public long getEndTime { get; set; } + /// <summary> + /// 券有效使用开始时间(时间戳,毫秒) + /// </summary> + public long useStartTime { get; set; } + /// <summary> + /// 券有效使用结束时间(时间戳,毫秒) + /// </summary> + public long useEndTime { get; set; } + /// <summary> + /// 图片url + /// </summary> + public string imageurl { get; set; } + /// <summary> + /// 30天引单数量(月销量) + /// </summary> + public int inOrderCount30Days { get; set; } + /// <summary> + /// 商品落地页 + /// </summary> + public string materialUrl { get; set; } + /// <summary> + /// g=自营,p=pop + /// </summary> + public string owner { get; set; } + /// <summary> + /// 拼团价格 + /// </summary> + public double pingouPrice { get; set; } + /// <summary> + /// 拼购成团所需人数 + /// </summary> + public long pingouTmCount { get; set; } + /// <summary> + /// 拼购落地页url + /// </summary> + public string pingouUrl { get; set; } + /// <summary> + /// 无线价格 + /// </summary> + public double price { get; set; } + /// <summary> + /// 商品ID + /// </summary> + public long skuId { get; set; } + /// <summary> + /// 商品名称 + /// </summary> + public string skuName { get; set; } + /// <summary> + /// 发送状态,是否发送过 + /// </summary> + public StateType state { get; set; } + /// <summary> + /// 采集的日期 + /// </summary> + public DateTime cur_time { get; set; } + /// <summary> + /// 产品数据的来源 GoodsSourceType枚举 + /// </summary> + public GoodsSourceType goods_source { get; set; } + + public fl_plugin_jdcirclepromotion_goodsinfos() + { + cur_time = DateTime.Now; + goods_source = GoodsSourceType.接口采集; + state = StateType.未推广; + } + + } +} diff --git a/应用/Weixin.JDCirclePromotion/Entitys/goodInfo_temp.cs b/应用/Weixin.JDCirclePromotion/Entitys/goodInfo_temp.cs new file mode 100644 index 0000000..1ddd6c7 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Entitys/goodInfo_temp.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.JDCirclePromotion.Entitys +{ + public class goodInfo_temp + { + /// <summary> + /// 返回码 + /// </summary> + public int code { get; set; } + /// <summary> + /// 数据明细 + /// </summary> + //public List<GoodsResp> data { get; set; } + public ArrayList data { get; set; } + /// <summary> + /// 返回消息 + /// </summary> + public string message { get; set; } + /// <summary> + /// + /// </summary> + public string requestId { get; set; } + /// <summary> + /// 有效商品总数量,上限10w + /// </summary> + public long totalCount { get; set; } + } +} diff --git a/应用/Weixin.JDCirclePromotion/Entitys/jdinfo_temp.cs b/应用/Weixin.JDCirclePromotion/Entitys/jdinfo_temp.cs new file mode 100644 index 0000000..18bdd2e --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Entitys/jdinfo_temp.cs @@ -0,0 +1,63 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.JDCirclePromotion.Entitys +{ + /// <summary> + /// 临时的表 (用于数据显示) + /// </summary> + public class jdinfo_temp + { + public long ID { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _adzone_pid_cps_name { get; set; } + public string adzone_pid_cps_name + { + get { return _adzone_pid_cps_name; } + set { _adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _adzone_pid; + /// <summary> + /// 主推广位id + /// </summary> + public string adzone_pid + { + get { return _adzone_pid; } + set { _adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _adzone_name; + + public string adzone_name + { + get { return _adzone_name; } + set { _adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/Weixin.JDCirclePromotion/Enums.cs b/应用/Weixin.JDCirclePromotion/Enums.cs new file mode 100644 index 0000000..1bc2b47 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Enums.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.JDCirclePromotion +{ + public class Enums + { + /// <summary> + /// 京东类目枚举 + /// </summary> + public enum CategoryType + { + /* + 频道ID:1-好券商品,2-精选卖场,10-9.9包邮,15-京东配送,22-实时热销榜,23-为你推荐,24-数码家电,25-超市,26-母婴玩具,27-家具日用,28-美妆穿搭,30-图书文具,31-今日必推,32-京东好物,33-京东秒杀,34-拼购商品,40-高收益榜,41-自营热卖榜,109-新品首发,110-自营,112-京东爆品,125-首购商品,129-高佣榜单,130-视频商品,153-历史最低价商品榜 + */ + + //--------新的 + 好券商品 = 1, + 精选卖场 = 2, + 九块九专区 = 10, + 京东配送 = 15, + 实时热销榜 = 22, + 为你推荐 = 23, + 数码家电 = 24, + 超市 = 25, + 母婴玩具 = 26, + 家具日用 = 27, + 美妆穿搭 = 28, + 图书文具 = 30, + 今日必推 = 31, + 京东好物 = 32, + 京东秒杀 = 33, + 拼购商品 = 34, + 高收益榜 = 40, + 自营热卖榜 = 41, + 新品首发 = 109, + 自营 = 110, + 京东爆品 = 112, + 首购商品 = 125, + 高佣榜单 = 129, + 视频商品 = 130, + 历史最低价商品榜 = 153 + } + + /// <summary> + /// 排序字段 + /// </summary> + public enum OrderFieldType + { + //price:单价, commissionShare:佣金比例, commission:佣金, inOrderCount30DaysSku:sku维度30天引单量,comments:评论数,goodComments:好评数 + 单价 = 1, + 佣金比例 = 2, + 佣金 = 3, + 月销量 = 4, + 评论数 = 5, + 好评数 = 6 + } + + /// <summary> + /// 排序字段 + /// </summary> + public enum _OrderFieldType + { + //price:单价, commissionShare:佣金比例, commission:佣金, inOrderCount30DaysSku:sku维度30天引单量,comments:评论数,goodComments:好评数 + price = 1, + commissionShare = 2, + commission = 3, + inOrderCount30DaysSku = 4, + comments = 5, + goodComments = 6 + } + + /// <summary> + /// 排序 + /// </summary> + public enum SortType + { + //asc,desc升降序,默认降序 + 升序 = 1, + 降序 = 2 + } + + public enum GoodsSourceType + { + 文件导入 = 0, + 接口采集 = 1, + 对象 = 2 + } + + public enum StateType + { + 已推广 = 0, + 未推广 = 1 + } + } +} diff --git a/应用/Weixin.JDCirclePromotion/MainForm.Designer.cs b/应用/Weixin.JDCirclePromotion/MainForm.Designer.cs new file mode 100644 index 0000000..bbffb76 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/MainForm.Designer.cs @@ -0,0 +1,577 @@ +namespace Weixin.JDCirclePromotion +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label2 = new System.Windows.Forms.Label(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有已发ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(892, 536); + this.xtraTabControl1.TabIndex = 10; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + this.xtraTabControl1.Selected += new DevExpress.XtraTab.TabPageEventHandler(this.xtraTabControl1_Selected); + this.xtraTabControl1.TabIndexChanged += new System.EventHandler(this.xtraTabControl1_TabIndexChanged); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label2); + this.xtraTabPage1.Controls.Add(this.simpleButton1); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(886, 507); + this.xtraTabPage1.Text = " 数 据 采 集 列 表 "; + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(290, 205); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(303, 35); + this.label2.TabIndex = 13; + this.label2.Text = "数据采集列表为空"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.simpleButton1.Location = new System.Drawing.Point(751, 473); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(99, 27); + this.simpleButton1.TabIndex = 10; + this.simpleButton1.Text = "Excel数据导入"; + this.simpleButton1.Visible = false; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 471); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(886, 36); + this.pageControl1.TabIndex = 9; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(886, 468); + this.gridControl1.TabIndex = 8; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中项ToolStripMenuItem, + this.删除所有已发ToolStripMenuItem, + this.删除所有数据ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(149, 70); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有已发ToolStripMenuItem + // + this.删除所有已发ToolStripMenuItem.Name = "删除所有已发ToolStripMenuItem"; + this.删除所有已发ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有已发ToolStripMenuItem.Text = "删除所有已发"; + this.删除所有已发ToolStripMenuItem.Click += new System.EventHandler(this.删除所有已发ToolStripMenuItem_Click); + // + // 删除所有数据ToolStripMenuItem + // + this.删除所有数据ToolStripMenuItem.Name = "删除所有数据ToolStripMenuItem"; + this.删除所有数据ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有数据ToolStripMenuItem.Text = "删除所有数据"; + this.删除所有数据ToolStripMenuItem.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn16, + this.gridColumn4, + this.gridColumn3, + this.gridColumn18, + this.gridColumn5, + this.gridColumn6, + this.gridColumn19, + this.gridColumn2, + this.gridColumn7, + this.gridColumn8, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "商品ID"; + this.gridColumn10.FieldName = "skuId"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 1; + this.gridColumn10.Width = 85; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "skuName"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 2; + this.gridColumn1.Width = 108; + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "价格"; + this.gridColumn16.FieldName = "price"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 3; + this.gridColumn16.Width = 116; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "拼团价格"; + this.gridColumn4.FieldName = "pingouPrice"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 4; + this.gridColumn4.Width = 79; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "所有者"; + this.gridColumn3.FieldName = "owner"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 5; + this.gridColumn3.Width = 79; + // + // gridColumn18 + // + this.gridColumn18.Caption = "商品主图"; + this.gridColumn18.FieldName = "imageurl"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 6; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "佣金"; + this.gridColumn5.FieldName = "commission"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 7; + this.gridColumn5.Width = 81; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "佣金比例"; + this.gridColumn6.FieldName = "commissionShare"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 8; + this.gridColumn6.Width = 66; + // + // gridColumn19 + // + this.gridColumn19.Caption = "券面额"; + this.gridColumn19.FieldName = "discount"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 9; + // + // gridColumn2 + // + this.gridColumn2.Caption = "券链接"; + this.gridColumn2.FieldName = "link"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 10; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "发送状态"; + this.gridColumn7.FieldName = "state"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 11; + this.gridColumn7.Width = 54; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "采集日期"; + this.gridColumn8.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn8.FieldName = "cur_time"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 12; + this.gridColumn8.Width = 100; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "数据来源"; + this.gridColumn9.FieldName = "goods_source"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.OptionsColumn.AllowFocus = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 13; + this.gridColumn9.Width = 83; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.label1); + this.xtraTabPage2.Controls.Add(this.pageControl2); + this.xtraTabPage2.Controls.Add(this.gridControl2); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(886, 507); + this.xtraTabPage2.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(175, 205); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 13; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 471); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(886, 36); + this.pageControl2.TabIndex = 7; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(886, 467); + this.gridControl2.TabIndex = 6; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn17}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "ID"; + this.gridColumn11.FieldName = "ID"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + this.gridColumn11.Width = 50; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "平台类型"; + this.gridColumn12.FieldName = "chattype"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + this.gridColumn12.Width = 99; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "账号"; + this.gridColumn13.FieldName = "name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 2; + this.gridColumn13.Width = 148; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "账号昵称"; + this.gridColumn14.FieldName = "nick"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + this.gridColumn14.Width = 125; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn15.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn15.AppearanceCell.Options.UseFont = true; + this.gridColumn15.AppearanceCell.Options.UseForeColor = true; + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "推广位"; + this.gridColumn15.FieldName = "adzone_name"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 4; + this.gridColumn15.Width = 149; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "禁止使用"; + this.gridColumn17.FieldName = "onoff"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + this.gridColumn17.Width = 66; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.settingControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(886, 526); + this.xtraTabPage3.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(886, 526); + this.settingControl1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(892, 536); + this.Controls.Add(this.xtraTabControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有已发ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有数据ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/应用/Weixin.JDCirclePromotion/MainForm.cs b/应用/Weixin.JDCirclePromotion/MainForm.cs new file mode 100644 index 0000000..c7f7a58 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/MainForm.cs @@ -0,0 +1,327 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using Weixin.JDCirclePromotion.Entitys; +using Weixin.JDCirclePromotion.Properties; + +namespace Weixin.JDCirclePromotion +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + this.Text = Resources.MainFormTitle; + + settingControl1.Bind(Class1.Config, 120); + + #region 加载所有采集到的商品 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<fl_plugin_jdcirclepromotion_goodsinfos>("select * from fl_plugin_jdcirclepromotion_goodsinfos order by state desc", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label2.Visible = gridView1.RowCount == 0; + + #endregion + + #region 加载所有的账号 + + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<jdinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.京东联盟}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID where ri.type = 2", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl2, 40, true, true); + + label1.Visible = gridView2.RowCount == 0; + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 行单元格单击事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.京东联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + if (e.Column.FieldName == "adzone_name") + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + } + + session.SaveOrUpdate(adzone); + } + else + { + try + { + if (e.Column.FieldName == "adzone_name") + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.京东联盟, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + pageControl2.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况,并且推广位设置了 + adzone.onoff = !adzone.onoff; + else + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = string.Empty, //推广位名称 + adzone_pid = string.Empty, //推广位pid + adzone_pid_cps_name = string.Empty, //推广位cps名称 + alliance_id = (int)CpsType.京东联盟, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = true //不禁用 + }; + session.SaveOrUpdate(adzone); + pageControl2.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 修改显示内容的事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "adzone_name" && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Util.Save(Class1.Config); + } + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.Caption == "数据来源") + { + var value = e.Value.ToString().ToLower(); + if (value == "0") + e.DisplayText = "文件导入"; + else if (value == "1") + e.DisplayText = "接口采集"; + } + if (e.Column.Caption == "发送状态") + { + var value = e.Value.ToString().ToLower(); + if (value == "true") + e.DisplayText = "未推广"; + else if (value == "false") + e.DisplayText = "已推广"; + } + if (e.Column.Caption == "佣金比例") + e.DisplayText = e.Value.ToString() + "%"; + if (e.Column.Caption == "所有者") + e.DisplayText = (e.Value.ToString() == "g" ? "自营" : "第三方"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void xtraTabControl1_TabIndexChanged(object sender, EventArgs e) + { + try + { + pageControl1.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + } + catch (Exception) + { } + } + + private void xtraTabControl1_Selected(object sender, DevExpress.XtraTab.TabPageEventArgs e) + { + try + { + if (e.PageIndex == 0) + { + pageControl1.GotoPage(); + label2.Visible = gridView1.RowCount == 0; + } + else if (e.PageIndex == 1) + { + pageControl2.GotoPage(); + label1.Visible = gridView2.RowCount == 0; + } + } + catch (Exception) + { } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView1.GetSelectedRows().ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + List<string> goodsids = new List<string>(); + foreach (var item in rownumber) + { + goodsids.Add("'" + gridView1.GetRowCellValue(item, "skuId").ToString() + "'");//根据行号获取相应行的数据 + } + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_jdcirclepromotion_goodsinfos where skuId in (" + string.Join(",", goodsids) + ")"); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除所有已发ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_jdcirclepromotion_goodsinfos where state = 0"); + } + + private void 删除所有数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_jdcirclepromotion_goodsinfos"); + } + + private void RemoveGoodsInfos(string sql) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL(sql); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} diff --git a/应用/Weixin.JDCirclePromotion/MainForm.resx b/应用/Weixin.JDCirclePromotion/MainForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/MainForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.JDCirclePromotion/Properties/AssemblyInfo.cs b/应用/Weixin.JDCirclePromotion/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b8cefc1 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Weixin.JDCirclePromotion")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Weixin.JDCirclePromotion")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("89e7bcc7-cdf2-433c-9848-327da30fb281")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/Weixin.JDCirclePromotion/Properties/Resources.Designer.cs b/应用/Weixin.JDCirclePromotion/Properties/Resources.Designer.cs new file mode 100644 index 0000000..9775278 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Properties/Resources.Designer.cs @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Weixin.JDCirclePromotion.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Weixin.JDCirclePromotion.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 京东朋友圈发单 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 京东发单 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 朋友圈京东商品发单插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找类似 京东发单 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 京东发单 { + get { + object obj = ResourceManager.GetObject("京东发单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 活动推广 { + get { + object obj = ResourceManager.GetObject("活动推广", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Weixin.JDCirclePromotion/Properties/Resources.resx b/应用/Weixin.JDCirclePromotion/Properties/Resources.resx new file mode 100644 index 0000000..eab33b9 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Properties/Resources.resx @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="SoftwareType" xml:space="preserve"> + <value>京东发单</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="京东发单" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\京东发单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="MainFormTitle" xml:space="preserve"> + <value>京东朋友圈发单</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>朋友圈京东商品发单插件</value> + <comment>插件介绍</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>京东发单</value> + <comment>插件名</comment> + </data> + <data name="活动推广" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\活动推广.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="基础管理" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/Weixin.JDCirclePromotion/Properties/licenses.licx b/应用/Weixin.JDCirclePromotion/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/Weixin.JDCirclePromotion/Resources/京东发单.png b/应用/Weixin.JDCirclePromotion/Resources/京东发单.png new file mode 100644 index 0000000..518f8e8 Binary files /dev/null and b/应用/Weixin.JDCirclePromotion/Resources/京东发单.png differ diff --git a/应用/Weixin.JDCirclePromotion/Resources/基础管理.png b/应用/Weixin.JDCirclePromotion/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/Weixin.JDCirclePromotion/Resources/基础管理.png differ diff --git a/应用/Weixin.JDCirclePromotion/Resources/活动推广.png b/应用/Weixin.JDCirclePromotion/Resources/活动推广.png new file mode 100644 index 0000000..727aa42 Binary files /dev/null and b/应用/Weixin.JDCirclePromotion/Resources/活动推广.png differ diff --git a/应用/Weixin.JDCirclePromotion/SendCircleFriendThread.cs b/应用/Weixin.JDCirclePromotion/SendCircleFriendThread.cs new file mode 100644 index 0000000..3030a21 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/SendCircleFriendThread.cs @@ -0,0 +1,182 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.Utils; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Weixin.JDCirclePromotion.Entitys; +using Weixin.JDCirclePromotion.Properties; +using static Weixin.JDCirclePromotion.Enums; + +namespace Weixin.JDCirclePromotion +{ + public class SendCircleFriendThread : TimerTask + { + AnalyzeGoods analyzeGoods = new AnalyzeGoods(); + StringBuilder strb = new StringBuilder(); + bool isSend = false; + bool isSendTime = false;//这里是用来判断是否在任务时间段里面,如果满足这会赋值为true + SqlSugarClient session = ApiClient.GetSession(); + private static object objLock = new object(); + + public override void Run(object state, bool timedOut) + { + #region 定时清空采集的数据 + if (!string.IsNullOrWhiteSpace(Class1.Config.AutoClearTaskTimes)) + { + if (Class1.Config.Auto_IsClear == SwitchType.开启) + { + try + { + if (DateTime.Now.AddSeconds(-3).ToString("HHmm") == DateTime.Parse(Class1.Config.AutoClearTaskTimes).ToString("HHmm")) + { + session.ExcuteSQL("Delete from fl_plugin_jdcirclepromotion_goodsinfos", new { }); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, "定时清理异常" + ex.Message + "-" + ex.StackTrace); + } + } + } + #endregion + + isSendTime = false; + var now = DateTime.Now; + for (int i = 0; i < Class1.Config.SendTaskTimes.Length; i++) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.SendTaskTimes[i])) + { + var times = Class1.Config.SendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0].Trim()); + var end = DateTime.Parse(times[1].Trim()); + if (begin <= now && now <= end) + { + isSendTime = true; + break; + } + } + } + } + if (!isSendTime) return; + + if ((DateTime.Now - Class1.Config.RecordSendTime).TotalMinutes < Class1.Config.Interval_Circle) return; + try + { + lock (objLock) + { + session.ExcuteSQL("Delete from fl_plugin_jdcirclepromotion_goodsinfos where cur_time <= @time", new { time = DateTime.Today.AddDays(-15) }); + isSend = false; + + #region 采集数据 + if (Class1.Config.Switch == SwitchType.开启) + { + var num = session.Queryable<fl_plugin_jdcirclepromotion_goodsinfos>().Count(f => f.state == StateType.未推广); + if (num <= Class1.Config.GatherTouchNum) analyzeGoods.GatherFactory(); + } + #endregion + + var goods_infos_temp = new List<fl_plugin_jdcirclepromotion_goodsinfos>(); + + var goods_infos = session.Queryable<fl_plugin_jdcirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).ToPageList(1, (Class1.Config.SendGoodsImageNum <= 0 ? 1 : Class1.Config.SendGoodsImageNum)); + + if (goods_infos != null && goods_infos.Count != 0) + { + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList(); + foreach (var item in clients) + { + try + { + if ((item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 || item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信) && item.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + var robot_info = session.FindRobotInfo(item.WeixinHao, ChatType.微信); + if (robot_info != null) + { + var pd_circle_promotion_temp = session.FindJdCirclePromotions().Where(f => f.onoff); + if (pd_circle_promotion_temp != null) + { + if (pd_circle_promotion_temp.FirstOrDefault(f => f.name == robot_info.name) != null) continue; + } + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == robot_info.id); + if (adzone != null) + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟 && f.username == adzone.adzone_pid_cps_name); + if (member != null) + { + var api = CpsClient.CreateJingdongRequest(member); + if (api == null) { return; } + strb.Length = 0; + strb.AppendLine(Class1.Config.Content_Circle); + + for (int i = 0; i < goods_infos.Count; i++) + { + try + { + goods_infos_temp.Add(goods_infos[i]); + var goodsinfo = goods_infos[i]; + var shoppingUrl = analyzeGoods.FindGoodsInfoToGoodsId(goods_infos[i], member, adzone.adzone_pid);//获取到自己返利链接等信息 + + var goods_desc = string.IsNullOrWhiteSpace(Class1.Config.Goods_Desc) ? string.Empty : Class1.Config.Goods_Desc + .Replace("[商品标题]", goods_infos[i].skuName) + .Replace("[已售数量]", goods_infos[i].inOrderCount30Days.ToString()) + .Replace("[店铺名称]", goods_infos[i].skuName) + .Replace("[优惠券门槛金额]", goods_infos[i].quota.ToString()) + .Replace("[优惠券金额]", goods_infos[i].discount.ToString()) + .Replace("[商品单价]", goods_infos[i].price.ToString()) + .Replace("[购买地址]", shoppingUrl); + + var image = ApiClient.GetQRImage(goods_infos[i].skuName, goods_infos[i].price.ToString(), goods_infos[i].discount.ToString(), ((decimal)goods_infos[i].price - (decimal)goods_infos[i].discount).ToString(), goods_infos[i].imageurl, shoppingUrl, Class1.Config.Model, CpsType.京东联盟, goods_desc); //合成附带二维码等信息的宝贝图片 + strb.Append($"[图片={image}]"); + } + catch + { } + } + var json = item.SendCircle(strb.ToString()); + if (!string.IsNullOrWhiteSpace(Class1.Config.AdditionalComment)) + { + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, Class1.Config.AdditionalComment); + } + isSend = true;//认定发送过了... + } + } + } + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"拼多多推广:{item.WeixinHao},朋友圈推广失败,{ex.Message}"); + } + } + if (isSend) + { + //RecordSendTime = DateTime.Now; + for (int i = 0; i < goods_infos_temp.Count; i++) + { + session.ExcuteSQL("update fl_plugin_jdcirclepromotion_goodsinfos set state = @state where id = @id", new { state = Enums.StateType.已推广, id = goods_infos_temp[i].id }); + } + Class1.Config.RecordSendTime = DateTime.Now; + Util.Save(Class1.Config); + } + } + + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"京东推广:{ex.Message},{ex.StackTrace}"); + } + } + } +} diff --git a/应用/Weixin.JDCirclePromotion/SessionEx.cs b/应用/Weixin.JDCirclePromotion/SessionEx.cs new file mode 100644 index 0000000..567053e --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/SessionEx.cs @@ -0,0 +1,31 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.JDCirclePromotion.Entitys; +using Weixin.JDCirclePromotion.Properties; + +namespace Weixin.JDCirclePromotion +{ + public static class SessionEx + { + const string jd_circle_promotion_temp_list = "jd_circle_promotion_temp_list"; + + /// <summary> + /// + /// </summary> + /// <param name="session"></param> + /// <param name="refresh"></param> + /// <returns></returns> + public static List<jdinfo_temp> FindJdCirclePromotions(this SqlSugarClient session, bool refresh = false) + { + return session.Find<jdinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.京东联盟}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID"); + } + + } +} diff --git a/应用/Weixin.JDCirclePromotion/Weixin.JDCirclePromotion.csproj b/应用/Weixin.JDCirclePromotion/Weixin.JDCirclePromotion.csproj new file mode 100644 index 0000000..170d8c2 --- /dev/null +++ b/应用/Weixin.JDCirclePromotion/Weixin.JDCirclePromotion.csproj @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{89E7BCC7-CDF2-433C-9848-327DA30FB281}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Weixin.JDCirclePromotion</RootNamespace> + <AssemblyName>Weixin.JDCirclePromotion</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="AnalyzeGoods.cs" /> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Entitys\fl_plugin_jdcirclepromotion_goodsinfos.cs" /> + <Compile Include="Entitys\goodInfo_temp.cs" /> + <Compile Include="Entitys\jdinfo_temp.cs" /> + <Compile Include="Enums.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="SendCircleFriendThread.cs" /> + <Compile Include="SessionEx.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\活动推广.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\基础管理.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\京东发单.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/Weixin.PDDCirclePromotion/AnalyzeGoods.cs b/应用/Weixin.PDDCirclePromotion/AnalyzeGoods.cs new file mode 100644 index 0000000..59884c2 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/AnalyzeGoods.cs @@ -0,0 +1,239 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using PDDCircleFriends.Entitys; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static PDDCircleFriends.Enums; + +namespace PDDCircleFriends +{ + /// <summary> + /// 解析商品 + /// </summary> + public class AnalyzeGoods + { + /// <summary> + /// 通过商品的id查询返回获取到自己返利商品信息 + /// </summary> + /// <param name="goods_id"></param> + /// <returns></returns> + public fl_plugin_pddcirclepromotion_goodsinfos FindGoodsInfoToGoodsId(PinduoduoApi api, string pid, string goods_id, GoodsSourceType goods_source) + { + try + { + fl_plugin_pddcirclepromotion_goodsinfos goodsinfo = null; + + ArrayList goods_details = null; + + goods_details = PDDHelper.FindSendGuideGoodsInfo(api, pid, goods_id); + + //没有查到返利提示 + if (goods_details == null || goods_details.Count == 0) + throw new Exception("商品不存在"); + + if (goods_details != null && goods_details.Count != 0) + { + foreach (var goods_detail in goods_details) + { + var goods = goods_detail as Dictionary<string, object>; + var goods_name = (goods["goods_name"] ?? string.Empty).ToString(); //商品标题 + var goods_desc = (goods["goods_desc"] ?? string.Empty).ToString(); //商品描述 + var goods_thumbnail_url = (goods["goods_thumbnail_url"] ?? string.Empty).ToString(); //商品图片链接 + //var sold_quantity = goods["sold_quantity"] == null ? 0 : int.Parse(goods["sold_quantity"].ToString()); + var goods_sign = goods["goods_sign"].ToString(); + + var sold_quantity = 0;//已售卖件数 + try + { + if (goods.ContainsKey("sales_tip")) + { + var _sales_tip = goods["sales_tip"].ToString(); + _sales_tip = _sales_tip.Replace("+", ""); + if (_sales_tip.Contains("万")) + { + _sales_tip = _sales_tip.Replace("万", ""); + var temp = decimal.Parse(_sales_tip); + sold_quantity = (int)(temp * 10000m); + } + else + sold_quantity = int.Parse(_sales_tip); + } + } + catch (Exception) + { sold_quantity = 0; } + + + var min_group_price = Math.Round(goods["min_group_price"] == null ? 0 : (double.Parse(goods["min_group_price"].ToString()) / 100.00), 2); //最小拼团价格,单位为元 + var min_normal_price = Math.Round(goods["min_normal_price"] == null ? 0 : (double.Parse(goods["min_normal_price"].ToString()) / 100.00), 2); //最小单买价格,单位为元 + var mall_name = (goods["mall_name"] ?? string.Empty).ToString(); //店铺名称 + var category_id = (goods["category_id"] ?? string.Empty).ToString(); //类目id + var coupon_min_order_amount = Math.Round(goods["coupon_min_order_amount"] == null ? 0 : (double.Parse(goods["coupon_min_order_amount"].ToString()) / 100.00), 2); //优惠券门槛价格,单位为元 + var coupon_discount = Math.Round(goods["coupon_discount"] == null ? 0 : (double.Parse(goods["coupon_discount"].ToString()) / 100.00), 2); //优惠券面额,单位为元 + + if (coupon_discount == 0) return null;//直接不要没有优惠券的商品(拼多多上面好像有点问题.前面采集到的数据,已经添加了优惠券的条件,有时候数据中存在没有优惠券的数据) + + var coupon_remain_quantity = goods["coupon_remain_quantity"] == null ? 0 : int.Parse(goods["coupon_remain_quantity"].ToString()); //优惠券剩余数量 + var promotion_rate = Math.Round(goods["promotion_rate"] == null ? 0 : (double.Parse(goods["promotion_rate"].ToString()) / 10.00), 2); //佣金比例,百分比 + goodsinfo = new fl_plugin_pddcirclepromotion_goodsinfos() { goods_id = goods_sign, goods_name = goods_name, goods_desc = goods_desc, goods_thumbnail_url = goods_thumbnail_url, sold_quantity = sold_quantity, min_group_price = min_group_price, min_normal_price = min_normal_price, mall_name = mall_name, category_id = category_id, coupon_min_order_amount = coupon_min_order_amount, coupon_discount = coupon_discount, coupon_remain_quantity = coupon_remain_quantity, promotion_rate = promotion_rate, cur_time = DateTime.Today, state = StateType.未推广, goods_source = goods_source }; + } + } + return goodsinfo; + } + catch (Exception ex) + { + return null; + } + } + + private static int DownPage = 1; + + #region 采集数据 + /// <summary> + /// 数据采集 + /// </summary> + public void GatherFactory() + { + for (int i = 0; i < 2; i++) + { + var session = ApiClient.GetSession(); + try + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝);//随机获取一个拼多多的cps + if (member != null) + { + var shopScore = Tools.FindShopScoreVlaue(Class1.Config.ShopScore); //店铺评分 + var rate = (Class1.Config.PromotionRate ?? 0) * 10; //返佣比例 + string priceStr = string.Empty; + if ((!(Class1.Config.FloorPrice == null && Class1.Config.CeilingPrice == null))) + { + var floor_price = Class1.Config.FloorPrice == null ? @"""""" : (Math.Round((double)Class1.Config.FloorPrice, 2) * 100).ToString(); + var ceiling_price = Class1.Config.CeilingPrice == null ? @"""""" : (Math.Round((double)Class1.Config.CeilingPrice, 2) * 100).ToString(); + priceStr = @",{""range_id"":0,""range_from"":" + floor_price + @",""range_to"":" + ceiling_price + @"}"; + } + var range_list = @"[{""range_id"":7,""range_from"":" + shopScore + @",""range_to"":500},{""range_id"":2,""range_from"":" + rate + @",""range_to"":1000}" + priceStr + @"]"; + + object data = null; + if (string.IsNullOrEmpty(Class1.Config.Category)) + { + data = new { page = DownPage, page_size = 100, sort_type = 0, with_coupon = true, range_list = range_list, custom_parameters = "{\"new\":1}" }; + GatherAction(member, data); + } + else + { + var opt_ids = Class1.Config.Category.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + foreach (var item in opt_ids) + { + if (item == "精选") + data = new { page = DownPage, page_size = 100, sort_type = 0, with_coupon = true, range_list = range_list }; + else + data = new { page = DownPage, page_size = 100, opt_id = Tools.FindCategoryNum(item), sort_type = 0, with_coupon = true, range_list = range_list, custom_parameters = "{\"new\":1}" }; + GatherAction(member, data); + } + } + } + } + catch (Exception ex) + { + if (ex.Message.Contains("只支持查询前10000个商品") || ex.Message.Contains("被禁止商品搜索深翻页请求")) + { + DownPage = 1; + continue; + } + EventClient.OnEvent(this, $"拼多多采集A:{ex.Message} - {ex.StackTrace}"); + } + return; + } + } + #endregion + + /// <summary> + /// 拼多多商品采集 + /// </summary> + /// <param name="member">cps对象</param> + /// <param name="data">参数</param> + private void GatherAction(fl_cps_member member, object data) + { + DownPage++; + var session = ApiClient.GetSession(); + try + { + PinduoduoApi api = CpsClient.CreatePinduoduoRequest(member); + var goods_list = PDDHelper.FindSendGuideGoodsInfo(api, data); + if (goods_list != null && goods_list.Count != 0) + { + session.BeginTransaction(); + List<fl_plugin_pddcirclepromotion_goodsinfos> goodsinfos = new List<fl_plugin_pddcirclepromotion_goodsinfos>(); + foreach (var item in goods_list) + { + try + { + var goods = item as Dictionary<string, object>; + //var goods_id = (goods["goods_id"] ?? string.Empty).ToString(); //商品id + var goods_sign = (goods["goods_sign"] ?? string.Empty).ToString(); //商品id + + if (session.FindSingle<fl_plugin_pddcirclepromotion_goodsinfos>("select * from fl_plugin_pddcirclepromotion_goodsinfos where goods_id = @goods_id", new { goods_id = goods_sign }) != null) + continue; + + var goods_name = (goods["goods_name"] ?? string.Empty).ToString(); //商品标题 + var goods_desc = (goods["goods_desc"] ?? string.Empty).ToString(); //商品描述 + var goods_thumbnail_url = (goods["goods_thumbnail_url"] ?? string.Empty).ToString(); //商品图片链接 + + //已售卖件数 + var sold_quantity = 0; + try + { + if (goods.ContainsKey("sales_tip")) + { + var _sales_tip = goods["sales_tip"].ToString(); + _sales_tip = _sales_tip.Replace("+", ""); + if (_sales_tip.Contains("万")) + { + _sales_tip = _sales_tip.Replace("万", ""); + var temp = decimal.Parse(_sales_tip); + sold_quantity = (int)(temp * 10000m); + } + else + sold_quantity = int.Parse(_sales_tip); + } + } + catch (Exception) + { sold_quantity = 0; } + + var min_group_price = Math.Round(goods["min_group_price"] == null ? 0 : (double.Parse(goods["min_group_price"].ToString()) / 100), 2); //最小拼团价格,单位为元 + var min_normal_price = Math.Round(goods["min_normal_price"] == null ? 0 : (double.Parse(goods["min_normal_price"].ToString()) / 100), 2); //最小单买价格,单位为元 + var mall_name = (goods["mall_name"] ?? string.Empty).ToString(); //店铺名称 + var category_id = (goods["category_id"] ?? string.Empty).ToString(); //类目id + var coupon_min_order_amount = Math.Round(goods["coupon_min_order_amount"] == null ? 0 : (double.Parse(goods["coupon_min_order_amount"].ToString()) / 100), 2); //优惠券门槛价格,单位为元 + var coupon_discount = Math.Round(goods["coupon_discount"] == null ? 0 : (double.Parse(goods["coupon_discount"].ToString()) / 100), 2); //优惠券面额,单位为元 + var coupon_remain_quantity = goods["coupon_remain_quantity"] == null ? 0 : int.Parse(goods["coupon_remain_quantity"].ToString()); //优惠券剩余数量 + var promotion_rate = Math.Round(goods["promotion_rate"] == null ? 0 : (double.Parse(goods["promotion_rate"].ToString()) / 10), 2); //佣金比例,百分比 + + var ss = new fl_plugin_pddcirclepromotion_goodsinfos() { goods_id = goods_sign, goods_name = goods_name, goods_desc = goods_desc.Substring(0, goods_desc.Length < 200 ? goods_desc.Length : 200), goods_thumbnail_url = goods_thumbnail_url, sold_quantity = sold_quantity, min_group_price = min_group_price, min_normal_price = min_normal_price, mall_name = mall_name, category_id = category_id, coupon_min_order_amount = coupon_min_order_amount, coupon_discount = coupon_discount, coupon_remain_quantity = coupon_remain_quantity, promotion_rate = promotion_rate, cur_time = DateTime.Today, state = StateType.未推广, goods_source = GoodsSourceType.接口采集 }; + goodsinfos.Add(ss); + } + catch (Exception ex) + { } + } + + if (goodsinfos.Count != 0) + session.Insertable(goodsinfos).ExecuteCommand(); + session.Commit(); + } + else + DownPage = 1; + } + catch (Exception ex) + { + session.Rollback(); + throw ex; + } + } + } +} diff --git a/应用/Weixin.PDDCirclePromotion/Class1.cs b/应用/Weixin.PDDCirclePromotion/Class1.cs new file mode 100644 index 0000000..c4b109b --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Class1.cs @@ -0,0 +1,117 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.SDK; +using Api.Framework.Tools; +using PDDCircleFriends.Entitys; +using Weixin.PDDCirclePromotion.Properties; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static PDDCircleFriends.Enums; +using Api.Framework.Model; +using Api.Framework.Enums; + +namespace PDDCircleFriends +{ + public class Class1 : Plugin + { + public Class1() + { + + this.Logo = Resources.拼多多发单; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<fl_plugin_pddcirclepromotion_goodsinfos>()) session.CreateTable<fl_plugin_pddcirclepromotion_goodsinfos>(); + + //如果存在原来的表将来的数据导入到新的表中,在原来的表给删除 + if (session.TableExist<fl_plugin_pddcirclepromotion_pddtgw>()) + { + var pddtgws = session.Find<fl_plugin_pddcirclepromotion_pddtgw>("select * from fl_plugin_pddcirclepromotion_pddtgw").ToList(); + if (pddtgws != null) + { + foreach (var item in pddtgws) + { + session.Insertable<fl_adzone_info>(new fl_adzone_info() + { + adzone_name = item.pid_name, //推广位名称 + adzone_pid = item.pid, //推广位pid + adzone_pid_cps_name = item.pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType //自定义类型 + }).ExecuteCommand(); + } + } + session.DropTable<fl_plugin_pddcirclepromotion_pddtgw>(); + } + + #endregion + + Config = this.ReadConfig<Config>(); //创建配置文件 + TimerTask.NewTimer<SendCircleFriendThread>(60); //创建线程 - 发送朋友圈的线程 60秒 + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close<SendCircleFriendThread>(); //关闭线程 + if (mainForm != null) + { + mainForm.CloseForm(); //关闭窗体 + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } + +} diff --git a/应用/Weixin.PDDCirclePromotion/Config.cs b/应用/Weixin.PDDCirclePromotion/Config.cs new file mode 100644 index 0000000..0ff665d --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Config.cs @@ -0,0 +1,273 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using PDDCircleFriends.Controls; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static Api.Framework.ApiClient; +using static PDDCircleFriends.Enums; + +namespace PDDCircleFriends +{ + [Config(Name = "插件-拼多多发单-配置")] + public class Config + { + + #region 发单功能 + + #region 采集 + /// <summary> + /// 发单条件 - 商品最低售价 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("01.采集开关"), DefaultValue(SwitchType.开启) + ] + public SwitchType Switch { get; set; } + + /// <summary> + /// 采集数据触发数量 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("02.采集触发量"), DefaultValue(10), + Description(@"当采集开关为开启时,该值为一个采集点,当采集剩余的商品数量少于等于采集触发量,将自动进行采集操作") + ] + public int GatherTouchNum { get; set; } + + /// <summary> + /// 发单条件 - 商品最低售价 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("03.商品最低售价"), DefaultValue(null), + Description(@"采集的产品最低价格,不填写表示不限制最低价!") + ] + public double? FloorPrice { get; set; } + + /// <summary> + /// 发单条件 - 商品最高售价 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("04.商品最高售价"), DefaultValue(null), + Description(@"采集的产品最高价格,不填写表示不限制最高价!") + ] + public double? CeilingPrice { get; set; } + + /// <summary> + /// 发单条件 - 佣金比例 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("05.佣金比例"), DefaultValue(null), + Description(@"采集的产品佣金比例条件,选中的比例包含选中的值.不填写表示不限制佣金比例!") + ] + public double? PromotionRate { get; set; } + + /// <summary> + /// 发单条件 - 类目 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("06.类目"), DefaultValue(@"精选"), + Description(@"筛选类目:精选、百货、母婴、服饰、美食、美妆、内衣、鞋包、男装、手机、文具、电器、家纺、运动、家装、汽车、水果"), + Editor(typeof(CategoryControl), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Category { get; set; } + + /// <summary> + /// 发单条件 - 店铺评分 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("07.店铺评分"), DefaultValue(ShopScoreType.不限), + Description(@"采集的产品对店铺的条件,选中的评分包含高于选中评分") + ] + public ShopScoreType ShopScore { get; set; } + + #endregion + + #region 开始时间 + + /// <summary> + /// 朋友圈发单二维码模板 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("01.发单二维码模板"), DefaultValue(QrImageType.模板B), + Description(@"朋友圈发单二维码模板") + ] + public QrImageType Model { get; set; } + + private string[] _sendTaskTimes; + /// <summary> + /// 发送任务时间段 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("02.发送任务时间段"), + Description(@"每一行为一个发送时间段 +格式:时间1-时间2 +注:时间1 必须大于 时间2") + ] + public string[] SendTaskTimes //{ get; set; } + { + get { return _sendTaskTimes; } + set + { + var sendTaskTimes = value as string[]; + if (sendTaskTimes != null && sendTaskTimes.Length != 0) + { + for (int i = 0; i < sendTaskTimes.Length; i++) + { + var times = sendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0]); + var end = DateTime.Parse(times[1]); + if (begin >= end) + throw new Exception($"开始时间必须小于结束时间:[{sendTaskTimes[i]}]"); + } + } + } + _sendTaskTimes = value; + } + } + + private int _sendGoodsImageNum; + /// <summary> + /// 发送商品图片数量 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("03.发送推广图片数量"), DefaultValue(9), + Description(@"发送朋友圈推广图片数量,最多9张图片") + ] + public int SendGoodsImageNum + { + get { return _sendGoodsImageNum; } + set + { + if (9 < value || value < 1) throw new Exception("发送推广图片数量应该大于等于1,小于等于9"); + _sendGoodsImageNum = value; + } + } + + /// <summary> + /// 朋友圈发送间隔,单位 分 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("04.朋友圈发送间隔"), DefaultValue(120), + Description(@"朋友圈推广商品间隔,单位 分") + ] + public double Interval_Circle { get; set; } + + /// <summary> + /// 发送的文字内容 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("05.发送的文字内容"), DefaultValue(@"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +补贴奖励和帮助渠道 + +手机拼多多分享宝贝给我 +可以查询优惠券款下单 + +还有网购红包领哦"), + Description(@"发送朋友圈时的文本内容"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Content_Circle { get; set; } + + /// <summary> + /// 宝贝描述语 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("06.宝贝描述语"), DefaultValue(@""), + Description(@"图片中宝贝描述信息,为空时以采集到的数据为准. +支持变量:[商品标题]、[商品描述]、[已售数量]、[店铺名称]、[优惠券门槛金额]、[优惠券金额]、[优惠券数量]、[商品单买价]、[券后单买价]、[单买地址]、[商品拼团价]、[券后拼团价]、[拼团地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Goods_Desc { get; set; } + /// <summary> + /// 朋友圈追加评语 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("07.朋友圈追加评语"), DefaultValue(@""), + Description(@"朋友圈商品推广之后,追加评语"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AdditionalComment { get; set; } + /// <summary> + /// 记录发送的时间 + /// </summary> + [Browsable(false)] + public DateTime RecordSendTime { get; set; } + + #endregion + + /// <summary> + /// 自动清理 + /// </summary> + [ + Category("3)、定时清理"), DisplayName("01.定时清理"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将在设置的时间进行采集数据的清空操作") + ] + public SwitchType Auto_IsClear { get; set; } + + private string _autoClearTaskTimes; + [ + Category("3)、定时清理"), DisplayName("02.定时清理时间"), DefaultValue(@"23:59"), + Description(@"定时清理时间 +格式:HH:mm +例:23:59 +注:时间为24小时制") + ] + public string AutoClearTaskTimes //{ get; set; } + { + get { return _autoClearTaskTimes; } + set + { + try + { + var time = value as string; + var _time = DateTime.Parse(time); + } + catch (Exception) + { + throw new Exception($"时间格式不正确"); + } + _autoClearTaskTimes = value; + } + } + + #endregion + + public Config() + { + this.Auto_IsClear = SwitchType.开启; + this.Switch = SwitchType.开启; + this.GatherTouchNum = 10; + this.FloorPrice = null; + this.CeilingPrice = null; + this.PromotionRate = null; + this.Category = @"精选"; + this.ShopScore = ShopScoreType.不限; + this.Content_Circle = @"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +补贴奖励和帮助渠道 + +手机拼多多分享宝贝给我 +可以查询优惠券款下单 + +还有网购红包领哦"; + this.SendGoodsImageNum = 9; + this._sendGoodsImageNum = 9; + this.Interval_Circle = 120; + this.SendTaskTimes = new string[] { }; + this._sendTaskTimes = new string[] { "09:00-22:00" }; + this._autoClearTaskTimes = "23:59"; + this.Model = QrImageType.模板B; + this.AdditionalComment = string.Empty; + this.Goods_Desc = string.Empty; + } + + } +} diff --git a/应用/Weixin.PDDCirclePromotion/Controls/CategoryControl.cs b/应用/Weixin.PDDCirclePromotion/Controls/CategoryControl.cs new file mode 100644 index 0000000..778dddd --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Controls/CategoryControl.cs @@ -0,0 +1,51 @@ +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static PDDCircleFriends.Enums; + +namespace PDDCircleFriends.Controls +{ + class CategoryControl : PropertyGridEditStyle + { + public CategoryControl() + { + var listBox = new CheckedListBoxControl(); + foreach (CategoryType item in Enum.GetValues(typeof(CategoryType))) + { + listBox.Items.Add(new CheckedListBoxItem(null, item.ToString())); + } + Control = listBox; + } + + public override string GetValue() + { + var listBox = Control as CheckedListBoxControl; + string[] strs = new string[listBox.CheckedItems.Count]; + int i = 0; + foreach (var item in listBox.CheckedItems) + { + strs[i] = item.ToString(); + i++; + } + return string.Join(",", strs); + } + + public override void SetValue(object value) + { + var listBox = Control as CheckedListBoxControl; + var strs = value.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + foreach (var item in listBox.Items) + { + listBox.SetItemChecked(i, !string.IsNullOrEmpty(strs.FirstOrDefault(f => f == item.ToString()))); + i++; + } + } + + } +} \ No newline at end of file diff --git a/应用/Weixin.PDDCirclePromotion/Entitys/fl_plugin_PDDCirclePromotion_goodsinfos.cs b/应用/Weixin.PDDCirclePromotion/Entitys/fl_plugin_PDDCirclePromotion_goodsinfos.cs new file mode 100644 index 0000000..8e350fa --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Entitys/fl_plugin_PDDCirclePromotion_goodsinfos.cs @@ -0,0 +1,78 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static PDDCircleFriends.Enums; + +namespace PDDCircleFriends.Entitys +{ + public class fl_plugin_pddcirclepromotion_goodsinfos : base_model + { + /// <summary> + /// 商品id + /// </summary> + public string goods_id { get; set; } + /// <summary> + /// 商品标题 + /// </summary> + public string goods_name { get; set; } + /// <summary> + /// 商品描述 + /// </summary> + public string goods_desc { get;set; } + /// <summary> + /// 商品图片链接 + /// </summary> + public string goods_thumbnail_url { get; set; } + /// <summary> + /// 已售卖件数 + /// </summary> + public int sold_quantity { get; set; } + /// <summary> + /// 最小拼团价格,单位为元 + /// </summary> + public double min_group_price { get; set; } + /// <summary> + /// 最小单买价格,单位为元 + /// </summary> + public double min_normal_price { get; set; } + /// <summary> + /// 店铺名 + /// </summary> + public string mall_name { get; set; } + /// <summary> + /// 类目id + /// </summary> + public string category_id { get; set; } + /// <summary> + /// 优惠券门槛价格,单位为元 + /// </summary> + public double coupon_min_order_amount { get; set; } + /// <summary> + /// 优惠券面额,单位为元 + /// </summary> + public double coupon_discount { get; set; } + /// <summary> + /// 优惠券剩余数量 + /// </summary> + public int coupon_remain_quantity { get; set; } + /// <summary> + /// 佣金比例,百分比 + /// </summary> + public double promotion_rate { get; set; } + /// <summary> + /// 发送状态,是否发送过 + /// </summary> + public StateType state { get; set; } + /// <summary> + /// 采集的日期 + /// </summary> + public DateTime cur_time { get; set; } + /// <summary> + /// 产品数据的来源 GoodsSourceType枚举 + /// </summary> + public GoodsSourceType goods_source { get; set; } + } +} diff --git a/应用/Weixin.PDDCirclePromotion/Entitys/fl_plugin_pddcirclepromotion_pddtgw.cs b/应用/Weixin.PDDCirclePromotion/Entitys/fl_plugin_pddcirclepromotion_pddtgw.cs new file mode 100644 index 0000000..dcd7dc5 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Entitys/fl_plugin_pddcirclepromotion_pddtgw.cs @@ -0,0 +1,37 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PDDCircleFriends.Entitys +{ + /// <summary> + /// 平台推广位设置类 (数据库表) + /// </summary> + public class fl_plugin_pddcirclepromotion_pddtgw : base_model + { + /// <summary> + /// 左连接主表 fl_robot_info 的主键 + /// </summary> + public int robot_id { get; set; } + /// <summary> + /// 主推广位CPS名称 + /// </summary> + public string pid_cps_name { get; set; } + /// <summary> + /// 主推广位id + /// </summary> + public string pid { get; set; } + /// <summary> + /// 主推广位昵称 + /// </summary> + public string pid_name { get; set; } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + + } +} diff --git a/应用/Weixin.PDDCirclePromotion/Entitys/pddinfo_temp.cs b/应用/Weixin.PDDCirclePromotion/Entitys/pddinfo_temp.cs new file mode 100644 index 0000000..25c61ee --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Entitys/pddinfo_temp.cs @@ -0,0 +1,63 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PDDCircleFriends.Entitys +{ + /// <summary> + /// 临时的表 (用于数据显示) + /// </summary> + public class pddinfo_temp + { + public long ID { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _adzone_pid_cps_name { get; set; } + public string adzone_pid_cps_name + { + get { return _adzone_pid_cps_name; } + set { _adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _adzone_pid; + /// <summary> + /// 主推广位id + /// </summary> + public string adzone_pid + { + get { return _adzone_pid; } + set { _adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _adzone_name; + + public string adzone_name + { + get { return _adzone_name; } + set { _adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/Weixin.PDDCirclePromotion/Enums.cs b/应用/Weixin.PDDCirclePromotion/Enums.cs new file mode 100644 index 0000000..c515216 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Enums.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace PDDCircleFriends +{ + public class Enums + { + /// <summary> + /// 拼多多类目枚举 + /// </summary> + public enum CategoryType + { + 精选 = 0, + 百货 = 15, + 母婴 = 4, + 服饰 = 14, + 美食 = 1, + 美妆 = 16, + 内衣 = 1282, + 鞋包 = 1281, + 男装 = 743, + 手机 = 1543, + 文具 = 2478, + 电器 = 18, + 家纺 = 818, + 运动 = 1451, + 家装 = 1917, + 汽车 = 2048, + 水果 = 13 + } + + public enum ShopScoreType + { + 不限 = 0, + 五点零 = 1, + 四点九 = 2, + 四点八 = 3, + 四点七 = 4, + 四点六 = 5 + } + + public enum GoodsSourceType + { + 文件导入 = 0, + 接口采集 = 1, + 对象 = 2 + } + + public enum StateType + { + 已推广 = 0, + 未推广 = 1 + } + + public enum TransmitStyleType + { + 仅转发原文 = 1, + 原文及评论 = 2 + } + + } +} diff --git a/应用/Weixin.PDDCirclePromotion/MainForm.Designer.cs b/应用/Weixin.PDDCirclePromotion/MainForm.Designer.cs new file mode 100644 index 0000000..59376c4 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/MainForm.Designer.cs @@ -0,0 +1,542 @@ +namespace PDDCircleFriends +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label2 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有已发ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(892, 537); + this.xtraTabControl1.TabIndex = 9; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + this.xtraTabControl1.Selected += new DevExpress.XtraTab.TabPageEventHandler(this.xtraTabControl1_Selected); + this.xtraTabControl1.TabIndexChanged += new System.EventHandler(this.xtraTabControl1_TabIndexChanged); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label2); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(886, 508); + this.xtraTabPage1.Text = " 数 据 采 集 列 表 "; + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(290, 205); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(303, 35); + this.label2.TabIndex = 13; + this.label2.Text = "数据采集列表为空"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 472); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(886, 36); + this.pageControl1.TabIndex = 9; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(886, 468); + this.gridControl1.TabIndex = 8; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中项ToolStripMenuItem, + this.删除所有已发ToolStripMenuItem, + this.删除所有数据ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(149, 70); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有已发ToolStripMenuItem + // + this.删除所有已发ToolStripMenuItem.Name = "删除所有已发ToolStripMenuItem"; + this.删除所有已发ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有已发ToolStripMenuItem.Text = "删除所有已发"; + this.删除所有已发ToolStripMenuItem.Click += new System.EventHandler(this.删除所有已发ToolStripMenuItem_Click); + // + // 删除所有数据ToolStripMenuItem + // + this.删除所有数据ToolStripMenuItem.Name = "删除所有数据ToolStripMenuItem"; + this.删除所有数据ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有数据ToolStripMenuItem.Text = "删除所有数据"; + this.删除所有数据ToolStripMenuItem.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn16, + this.gridColumn10, + this.gridColumn1, + this.gridColumn3, + this.gridColumn4, + this.gridColumn18, + this.gridColumn5, + this.gridColumn6, + this.gridColumn7, + this.gridColumn8, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "店铺名"; + this.gridColumn16.FieldName = "mall_name"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 1; + this.gridColumn16.Width = 116; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "商品ID"; + this.gridColumn10.FieldName = "goods_id"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 2; + this.gridColumn10.Width = 85; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "goods_name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 3; + this.gridColumn1.Width = 108; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "单买价"; + this.gridColumn3.FieldName = "min_normal_price"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 4; + this.gridColumn3.Width = 79; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "拼团价"; + this.gridColumn4.FieldName = "min_group_price"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 5; + this.gridColumn4.Width = 79; + // + // gridColumn18 + // + this.gridColumn18.Caption = "优惠券金额"; + this.gridColumn18.FieldName = "coupon_discount"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 6; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "优惠券数量"; + this.gridColumn5.FieldName = "coupon_remain_quantity"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 7; + this.gridColumn5.Width = 81; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "佣金比例"; + this.gridColumn6.FieldName = "promotion_rate"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 8; + this.gridColumn6.Width = 66; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "发送状态"; + this.gridColumn7.FieldName = "state"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 9; + this.gridColumn7.Width = 54; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "采集日期"; + this.gridColumn8.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn8.FieldName = "cur_time"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 10; + this.gridColumn8.Width = 100; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "数据来源"; + this.gridColumn9.FieldName = "goods_source"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.OptionsColumn.AllowFocus = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 11; + this.gridColumn9.Width = 83; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.label1); + this.xtraTabPage2.Controls.Add(this.pageControl2); + this.xtraTabPage2.Controls.Add(this.gridControl2); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(886, 508); + this.xtraTabPage2.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(175, 205); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 13; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 472); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(886, 36); + this.pageControl2.TabIndex = 7; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(886, 468); + this.gridControl2.TabIndex = 6; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn17}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "ID"; + this.gridColumn11.FieldName = "ID"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + this.gridColumn11.Width = 50; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "平台类型"; + this.gridColumn12.FieldName = "chattype"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + this.gridColumn12.Width = 99; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "账号"; + this.gridColumn13.FieldName = "name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 2; + this.gridColumn13.Width = 148; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "账号昵称"; + this.gridColumn14.FieldName = "nick"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + this.gridColumn14.Width = 125; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn15.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn15.AppearanceCell.Options.UseFont = true; + this.gridColumn15.AppearanceCell.Options.UseForeColor = true; + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "推广位"; + this.gridColumn15.FieldName = "adzone_name"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 4; + this.gridColumn15.Width = 149; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "禁止使用"; + this.gridColumn17.FieldName = "onoff"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + this.gridColumn17.Width = 66; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.settingControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(886, 526); + this.xtraTabPage3.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(886, 526); + this.settingControl1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(892, 537); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.SettingControl settingControl1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有已发ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有数据ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/应用/Weixin.PDDCirclePromotion/MainForm.cs b/应用/Weixin.PDDCirclePromotion/MainForm.cs new file mode 100644 index 0000000..a645837 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/MainForm.cs @@ -0,0 +1,333 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using PDDCircleFriends.Entitys; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using Weixin.PDDCirclePromotion.Properties; + +namespace PDDCircleFriends +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + /// <summary> + /// 窗体关闭 + /// </summary> + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + settingControl1.Bind(Class1.Config, 120); + + #region 加载所有采集到的商品 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<fl_plugin_pddcirclepromotion_goodsinfos>("select * from fl_plugin_pddcirclepromotion_goodsinfos order by state desc", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label2.Visible = gridView1.RowCount == 0; + + #endregion + + #region 加载所有的账号 + + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<pddinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.多多进宝}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID where ri.type = 2", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl2, 40, true, true); + + label1.Visible = gridView2.RowCount == 0; + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 行单元格单击事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.多多进宝); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + if (e.Column.FieldName == "adzone_name") + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + } + + session.SaveOrUpdate(adzone); + } + else + { + //session.BeginTransaction(); + try + { + if (e.Column.FieldName == "adzone_name") + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + //else session.Commit(); + } + catch (Exception ex) + { + //session.Rollback(); + ShowError(ex); + } + } + pageControl2.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况,并且推广位设置了 + adzone.onoff = !adzone.onoff; + else + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = string.Empty, //推广位名称 + adzone_pid = string.Empty, //推广位pid + adzone_pid_cps_name = string.Empty, //推广位cps名称 + alliance_id = (int)CpsType.多多进宝, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = true //不禁用 + }; + session.SaveOrUpdate(adzone); + pageControl2.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + //session.FindPddCirclePromotions(true); + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 修改显示内容的事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "adzone_name" && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Util.Save(Class1.Config); + } + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.Caption == "数据来源") + { + var value = e.Value.ToString().ToLower(); + if (value == "0") + e.DisplayText = "文件导入"; + else if (value == "1") + e.DisplayText = "接口采集"; + } + if (e.Column.Caption == "发送状态") + { + var value = e.Value.ToString().ToLower(); + if (value == "true") + e.DisplayText = "未推广"; + else if (value == "false") + e.DisplayText = "已推广"; + } + if (e.Column.Caption == "佣金比例") + e.DisplayText = e.Value.ToString() + "%"; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void xtraTabControl1_TabIndexChanged(object sender, EventArgs e) + { + try + { + pageControl1.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + } + catch (Exception) + { } + } + + private void xtraTabControl1_Selected(object sender, DevExpress.XtraTab.TabPageEventArgs e) + { + try + { + if (e.PageIndex == 0) + { + pageControl1.GotoPage(); + label2.Visible = gridView1.RowCount == 0; + } + else if (e.PageIndex == 1) + { + pageControl2.GotoPage(); + label1.Visible = gridView2.RowCount == 0; + } + } + catch (Exception) + { + } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView1.GetSelectedRows().ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + List<string> goodsids = new List<string>(); + foreach (var item in rownumber) + { + goodsids.Add("'" + gridView1.GetRowCellValue(item, "goods_id").ToString() + "'");//根据行号获取相应行的数据 + } + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_pddcirclepromotion_goodsinfos where goods_id in (" + string.Join(",", goodsids) + ")"); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除所有已发ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_pddcirclepromotion_goodsinfos where state = 0"); + } + + private void 删除所有数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_pddcirclepromotion_goodsinfos"); + } + + private void RemoveGoodsInfos(string sql) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL(sql); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} diff --git a/应用/Weixin.PDDCirclePromotion/MainForm.resx b/应用/Weixin.PDDCirclePromotion/MainForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/MainForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.PDDCirclePromotion/Properties/AssemblyInfo.cs b/应用/Weixin.PDDCirclePromotion/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fd859d0 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("PDDCircleFriends")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PDDCircleFriends")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("e10d2202-d6d2-429b-8aa5-7586df9605c1")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2019.01.09.1")] +[assembly: AssemblyFileVersion("2019.01.09.1")] diff --git a/应用/Weixin.PDDCirclePromotion/Properties/Resources.Designer.cs b/应用/Weixin.PDDCirclePromotion/Properties/Resources.Designer.cs new file mode 100644 index 0000000..2a36b63 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Properties/Resources.Designer.cs @@ -0,0 +1,139 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Weixin.PDDCirclePromotion.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Weixin.PDDCirclePromotion.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 拼多多朋友圈发单 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 拼多多发单 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 拼多多发单朋友圈商品发单插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找类似 拼多多发单 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 基础管理 { + get { + object obj = ResourceManager.GetObject("基础管理", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 拼多多发单 { + get { + object obj = ResourceManager.GetObject("拼多多发单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 活动推广 { + get { + object obj = ResourceManager.GetObject("活动推广", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 系统 { + get { + object obj = ResourceManager.GetObject("系统", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Weixin.PDDCirclePromotion/Properties/Resources.resx b/应用/Weixin.PDDCirclePromotion/Properties/Resources.resx new file mode 100644 index 0000000..d0e1edd --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Properties/Resources.resx @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="基础管理" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\基础管理.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="系统" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\系统.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="活动推广" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\活动推广.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="MainFormTitle" xml:space="preserve"> + <value>拼多多朋友圈发单</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>拼多多发单</value> + <comment>插件名</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>拼多多发单朋友圈商品发单插件</value> + <comment>插件介绍</comment> + </data> + <data name="拼多多发单" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\拼多多发单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="SoftwareType" xml:space="preserve"> + <value>拼多多发单</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> +</root> \ No newline at end of file diff --git a/应用/Weixin.PDDCirclePromotion/Properties/licenses.licx b/应用/Weixin.PDDCirclePromotion/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/Weixin.PDDCirclePromotion/Resources/基础管理.png b/应用/Weixin.PDDCirclePromotion/Resources/基础管理.png new file mode 100644 index 0000000..a16e59c Binary files /dev/null and b/应用/Weixin.PDDCirclePromotion/Resources/基础管理.png differ diff --git a/应用/Weixin.PDDCirclePromotion/Resources/拼多多发单.png b/应用/Weixin.PDDCirclePromotion/Resources/拼多多发单.png new file mode 100644 index 0000000..8da874a Binary files /dev/null and b/应用/Weixin.PDDCirclePromotion/Resources/拼多多发单.png differ diff --git a/应用/Weixin.PDDCirclePromotion/Resources/活动推广.png b/应用/Weixin.PDDCirclePromotion/Resources/活动推广.png new file mode 100644 index 0000000..727aa42 Binary files /dev/null and b/应用/Weixin.PDDCirclePromotion/Resources/活动推广.png differ diff --git a/应用/Weixin.PDDCirclePromotion/Resources/系统.png b/应用/Weixin.PDDCirclePromotion/Resources/系统.png new file mode 100644 index 0000000..bc64b4a Binary files /dev/null and b/应用/Weixin.PDDCirclePromotion/Resources/系统.png differ diff --git a/应用/Weixin.PDDCirclePromotion/SendCircleFriendThread.cs b/应用/Weixin.PDDCirclePromotion/SendCircleFriendThread.cs new file mode 100644 index 0000000..a3965f6 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/SendCircleFriendThread.cs @@ -0,0 +1,225 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using PDDCircleFriends.Entitys; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Weixin.PDDCirclePromotion; +using Weixin.PDDCirclePromotion.Properties; +using static PDDCircleFriends.Enums; + +namespace PDDCircleFriends +{ + public class SendCircleFriendThread : TimerTask + { + PDDHelper pddHelper = new PDDHelper(); + AnalyzeGoods analyzeGoods = new AnalyzeGoods(); + StringBuilder strb = new StringBuilder(); + bool isSend = false; + bool isSendTime = false;//这里是用来判断是否在任务时间段里面,如果满足这会赋值为true + SqlSugarClient session = ApiClient.GetSession(); + private static object objLock = new object(); + + public override void Run(object state, bool timedOut) + { + #region 定时清空采集的数据 + if (!string.IsNullOrWhiteSpace(Class1.Config.AutoClearTaskTimes)) + { + if (Class1.Config.Auto_IsClear == SwitchType.开启) + { + try + { + if (DateTime.Now.AddSeconds(-3).ToString("HHmm") == DateTime.Parse(Class1.Config.AutoClearTaskTimes).ToString("HHmm")) + { + session.ExcuteSQL("Delete from fl_plugin_pddcirclepromotion_goodsinfos", new { }); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, "定时清理异常" + ex.Message + "-" + ex.StackTrace); + } + } + } + #endregion + + isSendTime = false; + var now = DateTime.Now; + + for (int i = 0; i < Class1.Config.SendTaskTimes.Length; i++) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.SendTaskTimes[i])) + { + var times = Class1.Config.SendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0].Trim()); + var end = DateTime.Parse(times[1].Trim()); + if (begin <= now && now <= end) + { + isSendTime = true; + break; + } + } + } + } + if (!isSendTime) return; + + if ((DateTime.Now - Class1.Config.RecordSendTime).TotalMinutes < Class1.Config.Interval_Circle) return; + + try + { + lock (objLock) + { + session.ExcuteSQL("Delete from fl_plugin_pddcirclepromotion_goodsinfos where cur_time <= @time", new { time = DateTime.Today.AddDays(-15) }); + isSend = false; + + #region 采集数据 + if (Class1.Config.Switch == SwitchType.开启) + { + var num = session.Queryable<fl_plugin_pddcirclepromotion_goodsinfos>().Count(f => f.state == StateType.未推广); + if (num <= Class1.Config.GatherTouchNum) + analyzeGoods.GatherFactory(); + } + #endregion + + var goods_infos_temp = new List<fl_plugin_pddcirclepromotion_goodsinfos>(); + + var goods_infos = session.Queryable<fl_plugin_pddcirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).ToPageList(1, (Class1.Config.SendGoodsImageNum <= 0 ? 1 : Class1.Config.SendGoodsImageNum)); + + if (goods_infos != null && goods_infos.Count != 0) + { + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList(); + foreach (var item in clients) + { + try + { + if ((item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 || item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信) && item.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + var robot_info = session.FindRobotInfo(item.WeixinHao, ChatType.微信); + if (robot_info != null) + { + var pd_circle_promotion_temp = session.FindPddCirclePromotions().Where(f => f.onoff); + if (pd_circle_promotion_temp != null) + { + if (pd_circle_promotion_temp.FirstOrDefault(f => f.name == robot_info.name) != null) continue; + } + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.SoftwareType && f.robot_id == robot_info.id); + if (adzone != null) + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.多多进宝 && f.username == adzone.adzone_pid_cps_name); + if (member != null) + { + //string param = $"fl_{item.WeixinHao}_{(int)ChatType.微信}_朋友圈推广"; + + var api = CpsClient.CreatePinduoduoRequest(member); + if (api == null) { return; } + strb.Length = 0; + strb.AppendLine(Class1.Config.Content_Circle); + int count = 0; + + + var isBind = false; + var resultQuery = api.SendPinduoduo("pdd.ddk.oauth.member.authority.query", new { pid = adzone.adzone_pid }); + if (resultQuery.ContainsKey("authority_query_response")) + { + var authority_query_response = resultQuery["authority_query_response"] as Dictionary<string, object>; + if (authority_query_response != null && authority_query_response.Count != 0) + isBind = int.Parse(authority_query_response["bind"].ToString()) == 1;//1-已绑定;0-未绑定 + } + + for (int i = 0; i < goods_infos.Count; i++) + { + try + { + goods_infos_temp.Add(goods_infos[i]); + var goodsinfo = goods_infos[i]; + count = 0; + Next: + var result = analyzeGoods.FindGoodsInfoToGoodsId(api, adzone.adzone_pid, goods_infos[i].goods_id, GoodsSourceType.对象);//获取到自己返利链接等信息 + if (result == null) + { + count++; + if (count <= 5) + { + goodsinfo = session.Queryable<fl_plugin_pddcirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).First(); + goods_infos_temp.Add(goodsinfo); + goto Next; + } + else + continue; + } + else + { + var cprice = (result.min_normal_price - result.coupon_discount).ToString(); + var shoppingUrl = pddHelper.GetShoppingUrl(api, new { p_id = adzone.adzone_pid, goods_sign_list = $"[\"{goods_infos[i].goods_id}\"]", multi_group = false, generate_short_url = true, generate_weapp_webview = true, force_duo_id = true, generate_authority_url = !isBind, generate_schema_url = true }); + + var shoppingUrl2 = pddHelper.GetShoppingUrl(api, new { p_id = adzone.adzone_pid, goods_sign_list = $"[\"{result.goods_id}\"]", multi_group = true, generate_short_url = true, generate_weapp_webview = true, force_duo_id = true, generate_authority_url = !isBind, generate_schema_url = true }); + + var goods_desc = string.IsNullOrWhiteSpace(Class1.Config.Goods_Desc) ? result.goods_desc : Class1.Config.Goods_Desc + .Replace("[商品标题]", result.goods_name) + .Replace("[商品描述]", result.goods_desc) + .Replace("[已售数量]", result.sold_quantity.ToString()) + .Replace("[店铺名称]", result.mall_name) + .Replace("[优惠券门槛金额]", result.coupon_min_order_amount.ToString()) + .Replace("[优惠券金额]", result.coupon_discount.ToString()) + .Replace("[优惠券数量]", result.coupon_remain_quantity.ToString()) + .Replace("[商品单买价]", result.min_normal_price.ToString()) + .Replace("[劵后单买价]", cprice) + .Replace("[券后单买价]", cprice) + .Replace("[单买地址]", shoppingUrl) + .Replace("[商品拼团价]", result.min_group_price.ToString()) + .Replace("[劵后拼团价]", ((decimal)result.min_group_price - (decimal)result.coupon_discount).ToString()) + .Replace("[券后拼团价]", ((decimal)result.min_group_price - (decimal)result.coupon_discount).ToString()) + .Replace("[拼团地址]", shoppingUrl2); + + var image = ApiClient.GetQRImage(result.goods_name, result.min_normal_price.ToString(), result.coupon_discount.ToString(), cprice, result.goods_thumbnail_url, shoppingUrl2, Class1.Config.Model, CpsType.多多进宝, result.goods_desc); //合成附带二维码等信息的宝贝图片 + strb.Append($"[图片={image}]"); + } + } + catch + { } + } + var json = item.SendCircle(strb.ToString()); + if (!string.IsNullOrWhiteSpace(Class1.Config.AdditionalComment)) + { + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, Class1.Config.AdditionalComment); + } + isSend = true;//认定发送过了... + } + } + } + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"拼多多推广:{item.WeixinHao},朋友圈推广失败,{ex.Message}"); + } + } + if (isSend) + { + for (int i = 0; i < goods_infos_temp.Count; i++) + { + session.ExcuteSQL("update fl_plugin_pddcirclepromotion_goodsinfos set state = @state where id = @id", new { state = Enums.StateType.已推广, id = goods_infos_temp[i].id }); + } + Class1.Config.RecordSendTime = DateTime.Now; + Util.Save(Class1.Config); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"拼多多推广:{ex.Message},{ex.StackTrace}"); + } + } + } +} diff --git a/应用/Weixin.PDDCirclePromotion/SessionEx.cs b/应用/Weixin.PDDCirclePromotion/SessionEx.cs new file mode 100644 index 0000000..97addbd --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/SessionEx.cs @@ -0,0 +1,31 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using PDDCircleFriends.Entitys; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.PDDCirclePromotion.Properties; + +namespace Weixin.PDDCirclePromotion +{ + public static class SessionEx + { + const string pdd_circle_promotion_temp_list = "pdd_circle_promotion_temp_list"; + + /// <summary> + /// + /// </summary> + /// <param name="session"></param> + /// <param name="refresh"></param> + /// <returns></returns> + public static List<pddinfo_temp> FindPddCirclePromotions(this SqlSugarClient session, bool refresh = false) + { + return session.Find<pddinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.多多进宝}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID"); + } + + } +} diff --git a/应用/Weixin.PDDCirclePromotion/Tools.cs b/应用/Weixin.PDDCirclePromotion/Tools.cs new file mode 100644 index 0000000..6289eb7 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Tools.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.OleDb; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static PDDCircleFriends.Enums; + +namespace PDDCircleFriends +{ + public class Tools + { + + /// <summary> + /// 将枚举中的string转int + /// </summary> + /// <param name="data"></param> + /// <returns></returns> + public static int FindCategoryNum(string data) + { + return (int)((CategoryType)Enum.Parse(typeof(CategoryType), data)); + } + + /// <summary> + /// 获取中文店铺枚举对应的数值值 + /// </summary> + /// <param name="shopScore"></param> + /// <returns></returns> + public static int FindShopScoreVlaue(ShopScoreType shopScore) + { + int value = -1; + switch (shopScore) + { + case ShopScoreType.不限: + case ShopScoreType.四点六: + value = 460; + break; + case ShopScoreType.五点零: + value = 500; + break; + case ShopScoreType.四点九: + value = 490; + break; + case ShopScoreType.四点八: + value = 480; + break; + case ShopScoreType.四点七: + value = 470; + break; + } + return value; + } + + + } +} diff --git a/应用/Weixin.PDDCirclePromotion/Weixin.PDDCirclePromotion.csproj b/应用/Weixin.PDDCirclePromotion/Weixin.PDDCirclePromotion.csproj new file mode 100644 index 0000000..2545a02 --- /dev/null +++ b/应用/Weixin.PDDCirclePromotion/Weixin.PDDCirclePromotion.csproj @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{E10D2202-D6D2-429B-8AA5-7586DF9605C1}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Weixin.PDDCirclePromotion</RootNamespace> + <AssemblyName>Weixin.PDDCirclePromotion</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Sparkline.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Core" /> + <Reference Include="System.Data.Linq" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="AnalyzeGoods.cs" /> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Controls\CategoryControl.cs" /> + <Compile Include="Entitys\fl_plugin_pddcirclepromotion_goodsinfos.cs" /> + <Compile Include="Entitys\fl_plugin_pddcirclepromotion_pddtgw.cs" /> + <Compile Include="Entitys\pddinfo_temp.cs" /> + <Compile Include="Enums.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="SendCircleFriendThread.cs" /> + <Compile Include="SessionEx.cs" /> + <Compile Include="Tools.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\系统.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\基础管理.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\活动推广.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\拼多多发单.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/Weixin.SNCirclePromotion/AnalyzeGoods.cs b/应用/Weixin.SNCirclePromotion/AnalyzeGoods.cs new file mode 100644 index 0000000..87d2661 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/AnalyzeGoods.cs @@ -0,0 +1,271 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.EntityTmp.SuNing; +using Api.Framework.EntityTmp.SuNing4; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.SNCirclePromotion.Entitys; + +namespace Weixin.SNCirclePromotion +{ + /// <summary> + /// 解析商品 + /// </summary> + public class AnalyzeGoods + { + /// <summary> + /// 通过商品的id查询返回获取到自己返利商品信息 + /// </summary> + /// <param name="api"></param> + /// <param name="goodinfo"></param> + /// <param name="goods_source"></param> + /// <returns></returns> + public fl_plugin_sncirclepromotion_goodsinfos FindGoodsInfoToGoodsId(SuNingApi api, string goodinfo, GoodsSourceType goods_source) + { + try + { + + fl_plugin_sncirclepromotion_goodsinfos goodsinfo = null; + + var snGInfo = api.QueryGoodInfo(goodinfo); + if (snGInfo.sn_responseContent.sn_error != null) + throw new Exception(snGInfo.sn_responseContent.sn_error.error_msg);//查询没结果 + else if (snGInfo.sn_responseContent.sn_body == null || snGInfo.sn_responseContent.sn_body.queryCommoditydetail == null || snGInfo.sn_responseContent.sn_body.queryCommoditydetail.Count == 0) + throw new Exception("查询没结果2"); + + foreach (var goods in snGInfo.sn_responseContent.sn_body.queryCommoditydetail) + { + var goodsname = (goods.commodityInfo.commodityName ?? string.Empty).ToString(); //商品标题 + var goodsdesc = (goods.commodityInfo.sellingPoint ?? string.Empty).ToString(); //商品描述 + var picurl = (goods.commodityInfo.pictureUrl != null && goods.commodityInfo.pictureUrl.Count != 0) ? goods.commodityInfo.pictureUrl[0].picUrl : string.Empty; //商品图片链接 + + var goodsid = (goods.commodityInfo.commodityCode ?? string.Empty).ToString(); //商品id + + //已售卖件数 + var sold_quantity = goods.commodityInfo.monthSales; + + var vipPrice = -1d; + if (!string.IsNullOrWhiteSpace(goods.commodityInfo.snPrice)) + vipPrice = double.Parse(goods.commodityInfo.snPrice); + if (vipPrice == -1 && !string.IsNullOrWhiteSpace(goods.commodityInfo.commodityPrice)) + vipPrice = double.Parse(goods.commodityInfo.commodityPrice); + + var buyUrl = goods.commodityInfo.productUrl; + + if (goods.pgInfo != null) + { + if (!string.IsNullOrWhiteSpace(goods.pgInfo.pgUrl)) + { + buyUrl = goods.pgInfo.pgUrl; + if (!string.IsNullOrWhiteSpace(goods.pgInfo.pgUrl)) + { + vipPrice = double.Parse(goods.pgInfo.pgPrice); + } + } + } + + if (vipPrice == -1) + throw new Exception("当前价格不明"); + + //优惠券金额 + var coupon_price = 0.00d; + + //怕两个地址都没有链接.用自己拼的 + if (string.IsNullOrWhiteSpace(buyUrl)) + buyUrl = $@"https://product.suning.com/{goods.commodityInfo.supplierCode}/{goodsid}.html"; + + //优惠券地址 + var couponUrl = (goods.couponInfo != null && !string.IsNullOrWhiteSpace(goods.couponInfo.couponUrl)) ? goods.couponInfo.couponUrl : string.Empty; + + //优惠券地址 + //var coupon_click_url = string.Empty; + if (!string.IsNullOrWhiteSpace(couponUrl))//有券 + { + //优惠券没有过期 + if (goods.couponInfo.couponEndTime >= DateTime.Now && ((!string.IsNullOrWhiteSpace(goods.couponInfo.bounsLimit) && double.Parse(goods.couponInfo.bounsLimit) <= vipPrice) || (string.IsNullOrWhiteSpace(goods.couponInfo.bounsLimit)))) + coupon_price = double.Parse(goods.couponInfo.couponValue); + } + //商品标题//< >&"© <,>,&,",©; + var goodsName = goods.commodityInfo.commodityName.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); + + var endPrice = vipPrice; + if (coupon_price != 0) + endPrice = (double)((decimal)vipPrice - (decimal)coupon_price); + + //佣金比例 + var commissionRate = double.Parse(goods.commodityInfo.rate); + var supplierName = goods.commodityInfo.supplierName; //店铺名称 + + var coupon_min_order_amount = Math.Round(string.IsNullOrWhiteSpace(goods.couponInfo.bounsLimit) ? 0 : double.Parse(goods.couponInfo.bounsLimit), 2); //优惠券门槛价格,单位为元 + var coupon_discount = Math.Round(goods.couponInfo.couponValue == null ? 0 : double.Parse(goods.couponInfo.couponValue), 2); //优惠券面额,单位为元 + + + goodsinfo = new fl_plugin_sncirclepromotion_goodsinfos() { couponUrl = couponUrl, buyUrl = buyUrl, goodsid = goodsid, supplierCode = goods.commodityInfo.supplierCode, goodsname = goodsname, goodsdesc = goodsdesc.Substring(0, goodsdesc.Length < 200 ? goodsdesc.Length : 200), picurl = picurl, sold_quantity = sold_quantity, vipPrice = vipPrice, supplierName = supplierName, coupon_min_order_amount = coupon_min_order_amount, coupon_discount = coupon_discount, commissionRate = commissionRate, cur_time = DateTime.Today, state = StateType.未推广, goods_source = goods_source }; + } + + return goodsinfo; + } + catch (Exception ex) + { + return null; + } + } + + private static int DownPage = 1; + + #region 采集数据 + /// <summary> + /// 数据采集 + /// </summary> + public void GatherFactory() + { + for (int i = 0; i < 2; i++) + { + var session = ApiClient.GetSession(); + try + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.苏宁易购);//随机获取一个苏宁的cps + if (member != null) + { + var api = CpsClient.CreateSuNingRequest(member); + + object data = null; + var opt_ids = Class1.Config.Category.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + foreach (var item in opt_ids) + { + var result = api.QueryGuideGoodsInfo(Util.ConvertEnum<CategoryType>(item), DownPage); + GatherAction(result); + } + } + } + catch (Exception ex) + { + DownPage = 1; + EventClient.OnEvent(this, $"苏宁采集A:{ex.Message} - {ex.StackTrace}"); + } + return; + } + } + #endregion + + /// <summary> + /// 苏宁商品采集 + /// </summary> + /// <param name="snGInfo">SN_GoodInfo对象</param> + private void GatherAction(SN_Recommend_Commodity snGInfo) + { + DownPage++; + var session = ApiClient.GetSession(); + try + { + if (snGInfo.sn_responseContent.sn_error != null) + throw new Exception(snGInfo.sn_responseContent.sn_error.error_msg);//查询没结果 + else if (snGInfo.sn_responseContent.sn_body == null || snGInfo.sn_responseContent.sn_body.querySelectrecommendcommodity == null || snGInfo.sn_responseContent.sn_body.querySelectrecommendcommodity == null && snGInfo.sn_responseContent.sn_body.querySelectrecommendcommodity.commodityList == null && snGInfo.sn_responseContent.sn_body.querySelectrecommendcommodity.commodityList.Count == 0) + throw new Exception("查询没结果2"); + + session.BeginTransaction(); + List<fl_plugin_sncirclepromotion_goodsinfos> goodsinfos = new List<fl_plugin_sncirclepromotion_goodsinfos>(); + + foreach (var goods in snGInfo.sn_responseContent.sn_body.querySelectrecommendcommodity.commodityList) + { + try + { + var goodsid = (goods.commodityInfo.commodityCode ?? string.Empty).ToString(); //商品id + + if (session.FindSingle<fl_plugin_sncirclepromotion_goodsinfos>("select * from fl_plugin_sncirclepromotion_goodsinfos where goodsid = @goodsid", new { goodsid = goodsid }) != null) + continue; + + var goodsname = (goods.commodityInfo.commodityName ?? string.Empty).ToString(); //商品标题 + var goodsdesc = (goods.commodityInfo.sellingPoint ?? string.Empty).ToString(); //商品描述 + var picurl = (goods.commodityInfo.pictureUrl != null && goods.commodityInfo.pictureUrl.Count != 0) ? goods.commodityInfo.pictureUrl[0].picUrl : string.Empty; //商品图片链接 + + //已售卖件数 + var sold_quantity = goods.commodityInfo.monthSales; + + var vipPrice = -1d; + if (!string.IsNullOrWhiteSpace(goods.commodityInfo.snPrice)) + vipPrice = double.Parse(goods.commodityInfo.snPrice); + if (vipPrice == -1 && !string.IsNullOrWhiteSpace(goods.commodityInfo.commodityPrice)) + vipPrice = double.Parse(goods.commodityInfo.commodityPrice); + + var buyUrl = goods.commodityInfo.productUrl; + + if (goods.pgInfo != null) + { + if (!string.IsNullOrWhiteSpace(goods.pgInfo.pgUrl)) + { + buyUrl = goods.pgInfo.pgUrl; + if (!string.IsNullOrWhiteSpace(goods.pgInfo.pgUrl)) + { + vipPrice = double.Parse(goods.pgInfo.pgPrice); + } + } + } + + if (vipPrice == -1) + throw new Exception("当前价格不明"); + + //优惠券金额 + var coupon_price = 0.00d; + + //怕两个地址都没有链接.用自己拼的 + if (string.IsNullOrWhiteSpace(buyUrl)) + buyUrl = $@"https://product.suning.com/{goods.commodityInfo.supplierCode}/{goodsid}.html"; + + + //优惠券地址 + var couponUrl = (goods.couponInfo != null && !string.IsNullOrWhiteSpace(goods.couponInfo.couponUrl)) ? goods.couponInfo.couponUrl : string.Empty; + + //优惠券地址 + //var coupon_click_url = string.Empty; + if (!string.IsNullOrWhiteSpace(couponUrl))//有券 + { + //优惠券没有过期 + if (goods.couponInfo.couponEndTime >= DateTime.Now && ((!string.IsNullOrWhiteSpace(goods.couponInfo.bounsLimit) && double.Parse(goods.couponInfo.bounsLimit) <= vipPrice) || (string.IsNullOrWhiteSpace(goods.couponInfo.bounsLimit)))) + coupon_price = double.Parse(goods.couponInfo.couponValue); + } + //商品标题//< >&"© <,>,&,",©; + var goodsName = goods.commodityInfo.commodityName.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); + + + + //var vipPrice = double.Parse(item.commodityInfo.snPrice); + + var endPrice = vipPrice; + if (coupon_price != 0) + endPrice = (double)((decimal)vipPrice - (decimal)coupon_price); + + //佣金比例 + var commissionRate = double.Parse(goods.commodityInfo.rate); + var supplierName = goods.commodityInfo.supplierName; //店铺名称 + + var coupon_min_order_amount = Math.Round(string.IsNullOrWhiteSpace(goods.couponInfo.bounsLimit) ? 0 : double.Parse(goods.couponInfo.bounsLimit), 2); //优惠券门槛价格,单位为元 + var coupon_discount = Math.Round(goods.couponInfo.couponValue == null ? 0 : double.Parse(goods.couponInfo.couponValue), 2); //优惠券面额,单位为元 + + var ss = new fl_plugin_sncirclepromotion_goodsinfos() { couponUrl = couponUrl, buyUrl = buyUrl, goodsid = goodsid, supplierCode = goods.commodityInfo.supplierCode, goodsname = goodsName, goodsdesc = goodsdesc.Substring(0, goodsdesc.Length < 200 ? goodsdesc.Length : 200), picurl = picurl, sold_quantity = sold_quantity, vipPrice = vipPrice, supplierName = supplierName, coupon_min_order_amount = coupon_min_order_amount, coupon_discount = coupon_discount, commissionRate = commissionRate, cur_time = DateTime.Today, state = StateType.未推广, goods_source = GoodsSourceType.接口采集 }; + goodsinfos.Add(ss); + } + catch (Exception ex) + { } + } + + if (goodsinfos.Count != 0) + session.Insertable(goodsinfos).ExecuteCommand(); + session.Commit(); + } + catch (Exception ex) + { + DownPage = 1; + session.Rollback(); + throw ex; + } + } + } +} diff --git a/应用/Weixin.SNCirclePromotion/Class1.cs b/应用/Weixin.SNCirclePromotion/Class1.cs new file mode 100644 index 0000000..5139157 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Class1.cs @@ -0,0 +1,111 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.SNCirclePromotion.Entitys; +using Weixin.SNCirclePromotion.Properties; + +namespace Weixin.SNCirclePromotion +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.苏宁发单; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<fl_plugin_sncirclepromotion_goodsinfos>()) session.CreateTable<fl_plugin_sncirclepromotion_goodsinfos>(); + + //如果存在原来的表将来的数据导入到新的表中,在原来的表给删除 + if (session.TableExist<fl_plugin_sncirclepromotion_sntgw>()) + { + var pddtgws = session.Find<fl_plugin_sncirclepromotion_sntgw>("select * from fl_plugin_sncirclepromotion_sntgw").ToList(); + if (pddtgws != null) + { + foreach (var item in pddtgws) + { + session.Insertable<fl_adzone_info>(new fl_adzone_info() + { + adzone_name = item.pid_name, //推广位名称 + adzone_pid = item.pid, //推广位pid + adzone_pid_cps_name = item.pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.苏宁易购, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType //自定义类型 + }).ExecuteCommand(); + } + } + session.DropTable<fl_plugin_sncirclepromotion_sntgw>(); + } + + #endregion + + Config = this.ReadConfig<Config>(); //创建配置文件 + TimerTask.NewTimer<SendCircleFriendThread>(60); //创建线程 - 发送朋友圈的线程 60秒 + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close<SendCircleFriendThread>(); //关闭线程 + if (mainForm != null) + { + mainForm.CloseForm(); //关闭窗体 + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/Weixin.SNCirclePromotion/Config.cs b/应用/Weixin.SNCirclePromotion/Config.cs new file mode 100644 index 0000000..5184270 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Config.cs @@ -0,0 +1,259 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using Weixin.SNCirclePromotion.Controls; +using static Api.Framework.ApiClient; + +namespace Weixin.SNCirclePromotion +{ + [Config(Name = "插件-苏宁易购发单-配置")] + public class Config + { + + #region 发单功能 + + #region 采集 + /// <summary> + /// 发单条件 - 商品最低售价 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("01.采集开关"), DefaultValue(SwitchType.开启) + ] + public SwitchType Switch { get; set; } + + /// <summary> + /// 采集数据触发数量 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("02.采集触发量"), DefaultValue(10), + Description(@"当采集开关为开启时,该值为一个采集点,当采集剩余的商品数量少于等于采集触发量,将自动进行采集操作") + ] + public int GatherTouchNum { get; set; } + + ///// <summary> + ///// 发单条件 - 商品最低售价 + ///// </summary> + //[ + // Category("1)、自动采集"), DisplayName("03.商品最低售价"), DefaultValue(null), + // Description(@"采集的产品最低价格,不填写表示不限制最低价!") + //] + //public double? FloorPrice { get; set; } + + ///// <summary> + ///// 发单条件 - 商品最高售价 + ///// </summary> + //[ + // Category("1)、自动采集"), DisplayName("04.商品最高售价"), DefaultValue(null), + // Description(@"采集的产品最高价格,不填写表示不限制最高价!") + //] + //public double? CeilingPrice { get; set; } + + ///// <summary> + ///// 发单条件 - 佣金比例 + ///// </summary> + //[ + // Category("1)、自动采集"), DisplayName("05.佣金比例"), DefaultValue(null), + // Description(@"采集的产品佣金比例条件,选中的比例包含选中的值.不填写表示不限制佣金比例!") + //] + //public double? PromotionRate { get; set; } + + /// <summary> + /// 发单条件 - 类目 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("03.类目"), DefaultValue(@"小编推荐"), + Description(@"筛选平台:小编推荐、实时热销榜、当日热推榜、高佣爆款榜、团长招商榜、九块九专区"), + Editor(typeof(CategoryControl), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Category { get; set; } + + #endregion + + #region 开始时间 + + /// <summary> + /// 朋友圈发单二维码模板 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("01.发单二维码模板"), DefaultValue(QrImageType.模板B), + Description(@"朋友圈发单二维码模板") + ] + public QrImageType Model { get; set; } + + private string[] _sendTaskTimes; + /// <summary> + /// 发送任务时间段 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("02.发送任务时间段"), + Description(@"每一行为一个发送时间段 +格式:时间1-时间2 +注:时间1 必须大于 时间2") + ] + public string[] SendTaskTimes //{ get; set; } + { + get { return _sendTaskTimes; } + set + { + var sendTaskTimes = value as string[]; + if (sendTaskTimes != null && sendTaskTimes.Length != 0) + { + for (int i = 0; i < sendTaskTimes.Length; i++) + { + var times = sendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0]); + var end = DateTime.Parse(times[1]); + if (begin >= end) + throw new Exception($"开始时间必须小于结束时间:[{sendTaskTimes[i]}]"); + } + } + } + _sendTaskTimes = value; + } + } + + private int _sendGoodsImageNum; + /// <summary> + /// 发送商品图片数量 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("03.发送推广图片数量"), DefaultValue(9), + Description(@"发送朋友圈推广图片数量,最多9张图片") + ] + public int SendGoodsImageNum + { + get { return _sendGoodsImageNum; } + set + { + if (9 < value || value < 1) throw new Exception("发送推广图片数量应该大于等于1,小于等于9"); + _sendGoodsImageNum = value; + } + } + + /// <summary> + /// 朋友圈发送间隔,单位 分 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("04.朋友圈发送间隔"), DefaultValue(120), + Description(@"朋友圈推广商品间隔,单位 分") + ] + public double Interval_Circle { get; set; } + + /// <summary> + /// 发送的文字内容 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("05.发送的文字内容"), DefaultValue(@"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +补贴奖励和帮助渠道 + +手机苏宁分享宝贝给我 +可以查询优惠券款下单 + +还有网购红包领哦"), + Description(@"发送朋友圈时的文本内容"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Content_Circle { get; set; } + + /// <summary> + /// 宝贝描述语 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("06.宝贝描述语"), DefaultValue(@""), + Description(@"图片中宝贝描述信息,为空时以采集到的数据为准. +支持变量:[商品标题]、[商品描述]、[已售数量]、[店铺名称]、[优惠券门槛金额]、[优惠券金额]、[券后价]、[购买地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Goods_Desc { get; set; } + /// <summary> + /// 朋友圈追加评语 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("07.朋友圈追加评语"), DefaultValue(@""), + Description(@"朋友圈商品推广之后,追加评语"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AdditionalComment { get; set; } + /// <summary> + /// 记录发送的时间 + /// </summary> + [Browsable(false)] + public DateTime RecordSendTime { get; set; } + + #endregion + + /// <summary> + /// 自动清理 + /// </summary> + [ + Category("3)、定时清理"), DisplayName("01.定时清理"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将在设置的时间进行采集数据的清空操作") + ] + public SwitchType Auto_IsClear { get; set; } + + private string _autoClearTaskTimes; + [ + Category("3)、定时清理"), DisplayName("02.定时清理时间"), DefaultValue(@"23:59"), + Description(@"定时清理时间 +格式:HH:mm +例:23:59 +注:时间为24小时制") + ] + public string AutoClearTaskTimes //{ get; set; } + { + get { return _autoClearTaskTimes; } + set + { + try + { + var time = value as string; + var _time = DateTime.Parse(time); + } + catch (Exception) + { + throw new Exception($"时间格式不正确"); + } + _autoClearTaskTimes = value; + } + } + + #endregion + + public Config() + { + this.Auto_IsClear = SwitchType.开启; + this.Switch = SwitchType.开启; + this.GatherTouchNum = 10; + this.Category = @"小编推荐"; + this.Content_Circle = @"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +补贴奖励和帮助渠道 + +手机苏宁分享宝贝给我 +可以查询优惠券款下单 + +还有网购红包领哦"; + this.SendGoodsImageNum = 9; + this._sendGoodsImageNum = 9; + this.Interval_Circle = 120; + this.SendTaskTimes = new string[] { }; + this._sendTaskTimes = new string[] { "09:00-22:00" }; + this._autoClearTaskTimes = "23:59"; + this.Model = QrImageType.模板B; + this.AdditionalComment = string.Empty; + this.Goods_Desc = string.Empty; + } + + } +} diff --git a/应用/Weixin.SNCirclePromotion/Controls/CategoryControl.cs b/应用/Weixin.SNCirclePromotion/Controls/CategoryControl.cs new file mode 100644 index 0000000..e42a0fc --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Controls/CategoryControl.cs @@ -0,0 +1,48 @@ +using Api.Framework.EntityTmp.SuNing; +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; +using System; +using System.Linq; +using UI.Framework.Entitys; + +namespace Weixin.SNCirclePromotion.Controls +{ + class CategoryControl : PropertyGridEditStyle + { + public CategoryControl() + { + var listBox = new CheckedListBoxControl(); + foreach (CategoryType item in Enum.GetValues(typeof(CategoryType))) + { + listBox.Items.Add(new CheckedListBoxItem(null, item.ToString())); + } + Control = listBox; + } + + public override string GetValue() + { + var listBox = Control as CheckedListBoxControl; + string[] strs = new string[listBox.CheckedItems.Count]; + int i = 0; + foreach (var item in listBox.CheckedItems) + { + strs[i] = item.ToString(); + i++; + } + return string.Join(",", strs); + } + + public override void SetValue(object value) + { + var listBox = Control as CheckedListBoxControl; + var strs = value.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + foreach (var item in listBox.Items) + { + listBox.SetItemChecked(i, !string.IsNullOrEmpty(strs.FirstOrDefault(f => f == item.ToString()))); + i++; + } + } + + } +} diff --git a/应用/Weixin.SNCirclePromotion/Entitys/fl_plugin_sncirclepromotion_goodsinfos.cs b/应用/Weixin.SNCirclePromotion/Entitys/fl_plugin_sncirclepromotion_goodsinfos.cs new file mode 100644 index 0000000..5fdc5ff --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Entitys/fl_plugin_sncirclepromotion_goodsinfos.cs @@ -0,0 +1,90 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.SNCirclePromotion.Entitys +{ + public class fl_plugin_sncirclepromotion_goodsinfos : base_model + { + /// <summary> + /// 商品编码 + /// </summary> + public string goodsid { get; set; } + + /// <summary> + /// 供应编码 + /// </summary> + public string supplierCode { get; set; } + + /// <summary> + /// 价格 + /// </summary> + public double vipPrice { get; set; } + /// <summary> + /// 店铺名称 + /// </summary> + public string supplierName { get; set; } + /// <summary> + /// 佣金比例 + /// </summary> + public double commissionRate { get; set; } + + /// <summary> + /// 商品标题 + /// </summary> + public string goodsname { get; set; } + + /// <summary> + /// 商品介绍 + /// </summary> + public string goodsdesc { get; set; } + + /// <summary> + /// 商品图片 + /// </summary> + public string picurl { get; set; } + + /// <summary> + /// 购买地址 + /// </summary> + public string buyUrl { get; set; } + + /// <summary> + /// 已售 + /// </summary> + public int sold_quantity { get; set; } + + /// <summary> + /// 优惠券基数 + /// </summary> + public double coupon_min_order_amount { get; set; } + + /// <summary> + /// 优惠券面额 + /// </summary> + public double coupon_discount { get; set; } + + /// <summary> + /// 优惠券地址 + /// </summary> + public string couponUrl { get; set; } + + /// <summary> + /// 采集日期 + /// </summary> + public DateTime cur_time { get; set; } + + /// <summary> + /// 当前状态 + /// </summary> + public StateType state { get; set; } + + /// <summary> + /// 商品来源 + /// </summary> + public GoodsSourceType goods_source { get; set; } + } +} diff --git a/应用/Weixin.SNCirclePromotion/Entitys/fl_plugin_sncirclepromotion_sntgw.cs b/应用/Weixin.SNCirclePromotion/Entitys/fl_plugin_sncirclepromotion_sntgw.cs new file mode 100644 index 0000000..b0f851e --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Entitys/fl_plugin_sncirclepromotion_sntgw.cs @@ -0,0 +1,33 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.SNCirclePromotion.Entitys +{ + public class fl_plugin_sncirclepromotion_sntgw : base_model + { + /// <summary> + /// 左连接主表 fl_robot_info 的主键 + /// </summary> + public int robot_id { get; set; } + /// <summary> + /// 主推广位CPS名称 + /// </summary> + public string pid_cps_name { get; set; } + /// <summary> + /// 主推广位id + /// </summary> + public string pid { get; set; } + /// <summary> + /// 主推广位昵称 + /// </summary> + public string pid_name { get; set; } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/Weixin.SNCirclePromotion/Entitys/sninfo_temp.cs b/应用/Weixin.SNCirclePromotion/Entitys/sninfo_temp.cs new file mode 100644 index 0000000..62bcb93 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Entitys/sninfo_temp.cs @@ -0,0 +1,63 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.SNCirclePromotion.Entitys +{ + /// <summary> + /// 临时的表 (用于数据显示) + /// </summary> + public class sninfo_temp + { + public long ID { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _adzone_pid_cps_name { get; set; } + public string adzone_pid_cps_name + { + get { return _adzone_pid_cps_name; } + set { _adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _adzone_pid; + /// <summary> + /// 主推广位id + /// </summary> + public string adzone_pid + { + get { return _adzone_pid; } + set { _adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _adzone_name; + + public string adzone_name + { + get { return _adzone_name; } + set { _adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/Weixin.SNCirclePromotion/Enums.cs b/应用/Weixin.SNCirclePromotion/Enums.cs new file mode 100644 index 0000000..fc4cb73 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Enums.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.SNCirclePromotion +{ + + + public enum StateType + { + 已推广 = 0, + 未推广 = 1 + } + + public enum GoodsSourceType + { + 文件导入 = 0, + 接口采集 = 1, + 对象 = 2 + } + +} diff --git a/应用/Weixin.SNCirclePromotion/MainForm.Designer.cs b/应用/Weixin.SNCirclePromotion/MainForm.Designer.cs new file mode 100644 index 0000000..2d59c64 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/MainForm.Designer.cs @@ -0,0 +1,509 @@ +namespace Weixin.SNCirclePromotion +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label2 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有已发ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(878, 530); + this.xtraTabControl1.TabIndex = 10; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + this.xtraTabControl1.Selected += new DevExpress.XtraTab.TabPageEventHandler(this.xtraTabControl1_Selected); + this.xtraTabControl1.TabIndexChanged += new System.EventHandler(this.xtraTabControl1_TabIndexChanged); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label2); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(876, 504); + this.xtraTabPage1.Text = " 数 据 采 集 列 表 "; + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(283, 205); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(303, 35); + this.label2.TabIndex = 13; + this.label2.Text = "数据采集列表为空"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 468); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(876, 36); + this.pageControl1.TabIndex = 9; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(876, 468); + this.gridControl1.TabIndex = 8; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中项ToolStripMenuItem, + this.删除所有已发ToolStripMenuItem, + this.删除所有数据ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(149, 70); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有已发ToolStripMenuItem + // + this.删除所有已发ToolStripMenuItem.Name = "删除所有已发ToolStripMenuItem"; + this.删除所有已发ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有已发ToolStripMenuItem.Text = "删除所有已发"; + this.删除所有已发ToolStripMenuItem.Click += new System.EventHandler(this.删除所有已发ToolStripMenuItem_Click); + // + // 删除所有数据ToolStripMenuItem + // + this.删除所有数据ToolStripMenuItem.Name = "删除所有数据ToolStripMenuItem"; + this.删除所有数据ToolStripMenuItem.Size = new System.Drawing.Size(148, 22); + this.删除所有数据ToolStripMenuItem.Text = "删除所有数据"; + this.删除所有数据ToolStripMenuItem.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn16, + this.gridColumn10, + this.gridColumn1, + this.gridColumn3, + this.gridColumn18, + this.gridColumn6, + this.gridColumn7, + this.gridColumn8, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "店铺名"; + this.gridColumn16.FieldName = "supplierName"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 1; + this.gridColumn16.Width = 116; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "商品ID"; + this.gridColumn10.FieldName = "goodsid"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 2; + this.gridColumn10.Width = 85; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "goodsname"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 3; + this.gridColumn1.Width = 108; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "价格"; + this.gridColumn3.FieldName = "vipPrice"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 4; + this.gridColumn3.Width = 79; + // + // gridColumn18 + // + this.gridColumn18.Caption = "优惠券金额"; + this.gridColumn18.FieldName = "coupon_discount"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 5; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "佣金比例"; + this.gridColumn6.FieldName = "commissionRate"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 6; + this.gridColumn6.Width = 66; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "发送状态"; + this.gridColumn7.FieldName = "state"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 7; + this.gridColumn7.Width = 54; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "采集日期"; + this.gridColumn8.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn8.FieldName = "cur_time"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 8; + this.gridColumn8.Width = 100; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "数据来源"; + this.gridColumn9.FieldName = "goods_source"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.OptionsColumn.AllowFocus = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 9; + this.gridColumn9.Width = 83; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.label1); + this.xtraTabPage2.Controls.Add(this.pageControl2); + this.xtraTabPage2.Controls.Add(this.gridControl2); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(876, 504); + this.xtraTabPage2.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(168, 205); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 13; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 468); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(876, 36); + this.pageControl2.TabIndex = 7; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(872, 461); + this.gridControl2.TabIndex = 6; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn17}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "ID"; + this.gridColumn11.FieldName = "ID"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + this.gridColumn11.Width = 50; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "平台类型"; + this.gridColumn12.FieldName = "chattype"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + this.gridColumn12.Width = 99; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "账号"; + this.gridColumn13.FieldName = "name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 2; + this.gridColumn13.Width = 148; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "账号昵称"; + this.gridColumn14.FieldName = "nick"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + this.gridColumn14.Width = 125; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn15.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn15.AppearanceCell.Options.UseFont = true; + this.gridColumn15.AppearanceCell.Options.UseForeColor = true; + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "推广位"; + this.gridColumn15.FieldName = "adzone_name"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 4; + this.gridColumn15.Width = 149; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "禁止使用"; + this.gridColumn17.FieldName = "onoff"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + this.gridColumn17.Width = 66; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.settingControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(876, 504); + this.xtraTabPage3.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(876, 504); + this.settingControl1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(878, 530); + this.Controls.Add(this.xtraTabControl1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.Label label2; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.SettingControl settingControl1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有已发ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有数据ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/应用/Weixin.SNCirclePromotion/MainForm.cs b/应用/Weixin.SNCirclePromotion/MainForm.cs new file mode 100644 index 0000000..0c61865 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/MainForm.cs @@ -0,0 +1,337 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using Weixin.SNCirclePromotion.Entitys; +using Weixin.SNCirclePromotion.Properties; + +namespace Weixin.SNCirclePromotion +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + /// <summary> + /// 窗体关闭 + /// </summary> + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + settingControl1.Bind(Class1.Config, 120); + + #region 加载所有采集到的商品 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<fl_plugin_sncirclepromotion_goodsinfos>("select * from fl_plugin_sncirclepromotion_goodsinfos order by state desc", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label2.Visible = gridView1.RowCount == 0; + + #endregion + + #region 加载所有的账号 + + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<sninfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.苏宁易购}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID where ri.type = 2", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl2, 40, true, true); + + label1.Visible = gridView2.RowCount == 0; + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 行单元格单击事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.苏宁易购); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + if (e.Column.FieldName == "adzone_name") + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + } + + session.SaveOrUpdate(adzone); + } + else + { + //session.BeginTransaction(); + try + { + if (e.Column.FieldName == "adzone_name") + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.苏宁易购, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + //else session.Commit(); + } + catch (Exception ex) + { + //session.Rollback(); + ShowError(ex); + } + } + pageControl2.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况,并且推广位设置了 + adzone.onoff = !adzone.onoff; + else + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = string.Empty, //推广位名称 + adzone_pid = string.Empty, //推广位pid + adzone_pid_cps_name = string.Empty, //推广位cps名称 + alliance_id = (int)CpsType.苏宁易购, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = true //不禁用 + }; + session.SaveOrUpdate(adzone); + pageControl2.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 修改显示内容的事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "adzone_name" && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Util.Save(Class1.Config); + } + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.Caption == "数据来源") + { + var value = e.Value.ToString().ToLower(); + if (value == "0") + e.DisplayText = "文件导入"; + else if (value == "1") + e.DisplayText = "接口采集"; + } + if (e.Column.Caption == "发送状态") + { + var value = e.Value.ToString().ToLower(); + if (value == "true") + e.DisplayText = "未推广"; + else if (value == "false") + e.DisplayText = "已推广"; + } + if (e.Column.Caption == "佣金比例") + e.DisplayText = e.Value.ToString() + "%"; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void xtraTabControl1_TabIndexChanged(object sender, EventArgs e) + { + try + { + pageControl1.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + } + catch (Exception) + { } + } + + private void xtraTabControl1_Selected(object sender, DevExpress.XtraTab.TabPageEventArgs e) + { + try + { + if (e.PageIndex == 0) + { + pageControl1.GotoPage(); + label2.Visible = gridView1.RowCount == 0; + } + else if (e.PageIndex == 1) + { + pageControl2.GotoPage(); + label1.Visible = gridView2.RowCount == 0; + } + } + catch (Exception) + { + } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView1.GetSelectedRows().ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + List<string> goodsids = new List<string>(); + foreach (var item in rownumber) + { + goodsids.Add("'" + gridView1.GetRowCellValue(item, "goodsid").ToString() + "'");//根据行号获取相应行的数据 + } + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_sncirclepromotion_goodsinfos where goodsid in (" + string.Join(",", goodsids) + ")"); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除所有已发ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_sncirclepromotion_goodsinfos where state = 0"); + } + + private void 删除所有数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_sncirclepromotion_goodsinfos"); + } + + private void RemoveGoodsInfos(string sql) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL(sql); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + } +} diff --git a/应用/Weixin.SNCirclePromotion/MainForm.resx b/应用/Weixin.SNCirclePromotion/MainForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/MainForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.SNCirclePromotion/Properties/AssemblyInfo.cs b/应用/Weixin.SNCirclePromotion/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9c4df56 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Weixin.SNCirclePromotion")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Weixin.SNCirclePromotion")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("7d4f373b-0fda-4736-bca4-629f00f6a8fb")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/Weixin.SNCirclePromotion/Properties/Resources.Designer.cs b/应用/Weixin.SNCirclePromotion/Properties/Resources.Designer.cs new file mode 100644 index 0000000..0aba1c8 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Weixin.SNCirclePromotion.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Weixin.SNCirclePromotion.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 苏宁朋友圈发单 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 苏宁发单 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 苏宁发单朋友圈商品发单插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找类似 苏宁发单 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 苏宁发单 { + get { + object obj = ResourceManager.GetObject("苏宁发单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Weixin.SNCirclePromotion/Properties/Resources.resx b/应用/Weixin.SNCirclePromotion/Properties/Resources.resx new file mode 100644 index 0000000..f758734 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Properties/Resources.resx @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="MainFormTitle" xml:space="preserve"> + <value>苏宁朋友圈发单</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>苏宁发单</value> + <comment>插件名</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>苏宁发单朋友圈商品发单插件</value> + <comment>插件介绍</comment> + </data> + <data name="SoftwareType" xml:space="preserve"> + <value>苏宁发单</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="苏宁发单" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\苏宁发单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/Weixin.SNCirclePromotion/Properties/licenses.licx b/应用/Weixin.SNCirclePromotion/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/Weixin.SNCirclePromotion/Resources/苏宁发单.png b/应用/Weixin.SNCirclePromotion/Resources/苏宁发单.png new file mode 100644 index 0000000..86d2e76 Binary files /dev/null and b/应用/Weixin.SNCirclePromotion/Resources/苏宁发单.png differ diff --git a/应用/Weixin.SNCirclePromotion/SendCircleFriendThread.cs b/应用/Weixin.SNCirclePromotion/SendCircleFriendThread.cs new file mode 100644 index 0000000..0667f15 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/SendCircleFriendThread.cs @@ -0,0 +1,211 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Weixin.SNCirclePromotion.Entitys; +using Weixin.SNCirclePromotion.Properties; + +namespace Weixin.SNCirclePromotion +{ + public class SendCircleFriendThread : TimerTask + { + SNHelper snHelper = new SNHelper(); + AnalyzeGoods analyzeGoods = new AnalyzeGoods(); + StringBuilder strb = new StringBuilder(); + bool isSend = false; + bool isSendTime = false;//这里是用来判断是否在任务时间段里面,如果满足这会赋值为true + SqlSugarClient session = ApiClient.GetSession(); + private static object objLock = new object(); + + public override void Run(object state, bool timedOut) + { + #region 定时清空采集的数据 + if (!string.IsNullOrWhiteSpace(Class1.Config.AutoClearTaskTimes)) + { + if (Class1.Config.Auto_IsClear == SwitchType.开启) + { + try + { + if (DateTime.Now.AddSeconds(-3).ToString("HHmm") == DateTime.Parse(Class1.Config.AutoClearTaskTimes).ToString("HHmm")) + { + session.ExcuteSQL("Delete from fl_plugin_sncirclepromotion_goodsinfos", new { }); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, "定时清理异常" + ex.Message + "-" + ex.StackTrace); + } + } + } + #endregion + + isSendTime = false; + var now = DateTime.Now; + + for (int i = 0; i < Class1.Config.SendTaskTimes.Length; i++) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.SendTaskTimes[i])) + { + var times = Class1.Config.SendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0].Trim()); + var end = DateTime.Parse(times[1].Trim()); + if (begin <= now && now <= end) + { + isSendTime = true; + break; + } + } + } + } + if (!isSendTime) return; + + if ((DateTime.Now - Class1.Config.RecordSendTime).TotalMinutes < Class1.Config.Interval_Circle) return; + + try + { + lock (objLock) + { + session.ExcuteSQL("Delete from fl_plugin_sncirclepromotion_goodsinfos where cur_time <= @time", new { time = DateTime.Today.AddDays(-15) }); + isSend = false; + + #region 采集数据 + if (Class1.Config.Switch == SwitchType.开启) + { + var num = session.Queryable<fl_plugin_sncirclepromotion_goodsinfos>().Count(f => f.state == StateType.未推广); + if (num <= Class1.Config.GatherTouchNum) + analyzeGoods.GatherFactory(); + } + #endregion + + var goods_infos_temp = new List<fl_plugin_sncirclepromotion_goodsinfos>(); + + var goods_infos = session.Queryable<fl_plugin_sncirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).ToPageList(1, (Class1.Config.SendGoodsImageNum <= 0 ? 1 : Class1.Config.SendGoodsImageNum)); + + if (goods_infos != null && goods_infos.Count != 0) + { + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList(); + foreach (var item in clients) + { + try + { + if ((item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 || item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信) && item.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + var robot_info = session.FindRobotInfo(item.WeixinHao, ChatType.微信); + if (robot_info != null) + { + var sn_circle_promotion_temp = session.FindSnCirclePromotions().Where(f => f.onoff); + if (sn_circle_promotion_temp != null) + { + if (sn_circle_promotion_temp.FirstOrDefault(f => f.name == robot_info.name) != null) continue; + } + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == Resources.SoftwareType && f.robot_id == robot_info.id); + if (adzone != null) + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.苏宁易购 && f.username == adzone.adzone_pid_cps_name); + if (member != null) + { + //string param = $"fl_{item.WeixinHao}_{(int)ChatType.微信}_朋友圈推广"; + + var api = CpsClient.CreateSuNingRequest(member); + if (api == null) { return; } + strb.Length = 0; + strb.AppendLine(Class1.Config.Content_Circle); + int count = 0; + + for (int i = 0; i < goods_infos.Count; i++) + { + try + { + goods_infos_temp.Add(goods_infos[i]); + var goodsinfo = goods_infos[i]; + count = 0; + Next: + var result = analyzeGoods.FindGoodsInfoToGoodsId(api, goods_infos[i].goodsid + "-" + goods_infos[i].supplierCode, GoodsSourceType.对象);//获取到自己返利链接等信息 + if (result == null) + { + count++; + if (count <= 5) + { + goodsinfo = session.Queryable<fl_plugin_sncirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).First(); + goods_infos_temp.Add(goodsinfo); + goto Next; + } + else + continue; + } + else + { + var cprice = (result.vipPrice - result.coupon_discount).ToString(); + #region 转链 + //pid=(?<pid>.+?)\sr=(?<机器人名>.*?)\st=(?<类型>\d+)\su=(?<会员名>.+?)\smid=(?<店铺ID>\d+)\sgid=(?<商品ID>\d+) + var custom = Util.EncryptDES($"pid={adzone.adzone_pid}"); + var extension = api.GetExtensionUrl(custom, result.buyUrl, result.couponUrl); + if (extension.sn_responseContent.sn_body == null) + throw new Exception(); + #endregion + + var goods_desc = string.IsNullOrWhiteSpace(Class1.Config.Goods_Desc) ? result.goodsdesc : Class1.Config.Goods_Desc + .Replace("[商品标题]", result.goodsname) + .Replace("[商品描述]", result.goodsdesc) + .Replace("[已售数量]", result.sold_quantity.ToString()) + .Replace("[店铺名称]", result.supplierName) + .Replace("[优惠券门槛金额]", result.coupon_min_order_amount.ToString()) + .Replace("[优惠券金额]", result.coupon_discount.ToString()) + .Replace("[劵后价]", cprice) + .Replace("[购买地址]", extension.sn_responseContent.sn_body.getExtensionlink.shortLink); + + var image = ApiClient.GetQRImage(result.goodsname, result.vipPrice.ToString(), result.coupon_discount.ToString(), cprice, result.picurl, extension.sn_responseContent.sn_body.getExtensionlink.shortLink, Class1.Config.Model, CpsType.苏宁易购, result.goodsdesc); //合成附带二维码等信息的宝贝图片 + strb.Append($"[图片={image}]"); + } + } + catch + { } + } + var json = item.SendCircle(strb.ToString()); + if (!string.IsNullOrWhiteSpace(Class1.Config.AdditionalComment)) + { + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, Class1.Config.AdditionalComment); + } + isSend = true;//认定发送过了... + } + } + } + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"拼多多推广:{item.WeixinHao},朋友圈推广失败,{ex.Message}"); + } + } + if (isSend) + { + for (int i = 0; i < goods_infos_temp.Count; i++) + { + session.ExcuteSQL("update fl_plugin_sncirclepromotion_goodsinfos set state = @state where id = @id", new { state = StateType.已推广, id = goods_infos_temp[i].id }); + } + Class1.Config.RecordSendTime = DateTime.Now; + Util.Save(Class1.Config); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"拼多多推广:{ex.Message},{ex.StackTrace}"); + } + } + } +} diff --git a/应用/Weixin.SNCirclePromotion/SessionEx.cs b/应用/Weixin.SNCirclePromotion/SessionEx.cs new file mode 100644 index 0000000..ab424da --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/SessionEx.cs @@ -0,0 +1,30 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.SNCirclePromotion.Entitys; +using Weixin.SNCirclePromotion.Properties; + +namespace Weixin.SNCirclePromotion +{ + public static class SessionEx + { + const string pdd_circle_promotion_temp_list = "sn_circle_promotion_temp_list"; + + /// <summary> + /// + /// </summary> + /// <param name="session"></param> + /// <param name="refresh"></param> + /// <returns></returns> + public static List<sninfo_temp> FindSnCirclePromotions(this SqlSugarClient session, bool refresh = false) + { + return session.Find<sninfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.苏宁易购}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID"); + } + + } +} diff --git a/应用/Weixin.SNCirclePromotion/Weixin.SNCirclePromotion.csproj b/应用/Weixin.SNCirclePromotion/Weixin.SNCirclePromotion.csproj new file mode 100644 index 0000000..ffbe584 --- /dev/null +++ b/应用/Weixin.SNCirclePromotion/Weixin.SNCirclePromotion.csproj @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{7D4F373B-0FDA-4736-BCA4-629F00F6A8FB}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Weixin.SNCirclePromotion</RootNamespace> + <AssemblyName>Weixin.SNCirclePromotion</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar"> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="AnalyzeGoods.cs" /> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Controls\CategoryControl.cs" /> + <Compile Include="Entitys\fl_plugin_sncirclepromotion_goodsinfos.cs" /> + <Compile Include="Entitys\fl_plugin_sncirclepromotion_sntgw.cs" /> + <Compile Include="Entitys\sninfo_temp.cs" /> + <Compile Include="Enums.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="SendCircleFriendThread.cs" /> + <Compile Include="SessionEx.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\苏宁发单.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/AnalyzeGoods.cs b/应用/Weixin.TBCirclePromotion/AnalyzeGoods.cs new file mode 100644 index 0000000..43b012e --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/AnalyzeGoods.cs @@ -0,0 +1,379 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Weixin.TBCirclePromotion.Entitys; +using static Weixin.TBCirclePromotion.Enums; + +namespace Weixin.TBCirclePromotion +{ + /// <summary> + /// 解析商品 + /// </summary> + public class AnalyzeGoods + { + /// <summary> + /// 通过商品的id查询返回获取到自己返利商品信息 + /// </summary> + /// <param name="goods_id"></param> + /// <returns></returns> + public fl_plugin_tbcirclepromotion_goodsinfos FindGoodsInfoToGoodsId(string goods_id, string pid_cps_name = "", string pid = "", string quan = "", string biz_scene_id = "2") + { + var session = ApiClient.GetSession(); + try + { + if (!string.IsNullOrEmpty(goods_id))//符合搜索宝贝id的条件 + { + var member = (string.IsNullOrEmpty(pid_cps_name) ? CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈) : CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == pid_cps_name)); + if (member == null) { return null; } + + + if (string.IsNullOrWhiteSpace(pid)) + { + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.adzone_pid_cps_name == member.username); + pid = adzone.adzone_pid; + } + + var api = CpsClient.CreateAlimamaRequest(member); + var itemInfo = api.GetItemInfo(goods_id, "2"); + if (itemInfo != null && itemInfo.n_tbk_item != null && itemInfo.n_tbk_item.Count > 0) + { + var tbk_item = itemInfo.n_tbk_item[0]; + //店铺名称 + var nick = tbk_item.nick; + //商品主图 + var pict_url = tbk_item.pict_url; + //商品id + goods_id = tbk_item.num_iid; + //商品标题 + var title = tbk_item.title; + //商品折扣价格(当前售价) + var zk_final_price = double.Parse(tbk_item.zk_final_price); + //30天销量 + var volume = tbk_item.volume; + var goods_desc = string.Empty; + + var coupon_remain_quantity = string.Empty; + + biz_scene_id = TBHelper.TbAnalysis.BizSceneId(goods_id); + + var pids = pid.Split('_'); + var privilege = api.SendTaobao("taobao.tbk.privilege.get", new { item_id = goods_id, site_id = pids[2], adzone_id = pids[3], biz_scene_id = biz_scene_id }); + var privilege_data = privilege["data"] as Dictionary<string, object>; + //最高佣金率 + var max_commission_rate = double.Parse(privilege_data["max_commission_rate"].ToString()); + //优惠券地址 + var coupon_click_url = string.Empty; + var coupon_price = 0.00d; + if (privilege_data.ContainsKey("coupon_info")) + { + var quan_reg = Regex.Match(privilege_data["coupon_info"].ToString(), @"满\d+元减(\d+)元"); + if (quan_reg.Success) coupon_price = double.Parse(quan_reg.Groups[1].Value); + coupon_click_url = privilege_data["coupon_click_url"].ToString(); + } + else + { + coupon_price = 0.00d; + if (!string.IsNullOrWhiteSpace(quan)) + coupon_click_url = privilege_data["coupon_click_url"].ToString() + "&activityId=" + quan; + } + + //检查优惠券有效性 + var coupon = api.CheckCoupon(coupon_click_url); + //查到宝贝返利存在异常,直接提示没有返利 + if (coupon != null) + { + //优惠券过期 + if (coupon != null && coupon.retStatus != 0) + { + //coupon_click_url = coupon.clickUrl; + //coupon_price = 0.00d; + if (!string.IsNullOrWhiteSpace(quan)) + coupon_click_url += "&activityId=" + quan; + else + coupon_click_url = privilege_data["item_url"].ToString(); + coupon_price = 0.00d; + } + } + return new fl_plugin_tbcirclepromotion_goodsinfos() { cur_time = DateTime.Today, goods_id = goods_id, goods_name = title, mall_name = nick, goods_thumbnail_url = pict_url, sold_quantity = volume, normal_price = zk_final_price, coupon_discount = coupon_price, promotion_rate = max_commission_rate, shopping_url = coupon_click_url, goods_desc = goods_desc, coupon_remain_quantity = coupon_remain_quantity }; + } + } + return null; + } + catch (Exception) + { + return null; + } + } + + StringBuilder strb = new StringBuilder(); + + #region 采集数据 xxx + ///// <summary> + ///// 数据采集 + ///// </summary> + //public void GatherFactory() + //{ + // strb.Length = 0; + // var session = ApiClient.GetSession(); + // try + // { + // strb.Append(@"http://www.dataoke.com/qlist/?px=zx&"); + // switch (Class1.Config.Stage) + // { + // case StageType.聚划算: + // strb.Append(@"h=tqg_jhs_ju&"); + // break; + // case StageType.淘抢购: + // strb.Append(@"h=tqg_jhs&"); + // break; + // case StageType.天猫: + // strb.Append(@"t=tmall&"); + // break; + // case StageType.金牌卖家: + // strb.Append(@"t=tm_jpmj&"); + // break; + // case StageType.海淘: + // strb.Append(@"haitao=1&"); + // break; + // } + + // if (!string.IsNullOrWhiteSpace(Class1.Config.Category)) + // { + // string[] categorys = Class1.Config.Category.Split(','); + // for (int i = 0; i < categorys.Length; i++) + // { + // categorys[i] = ((int)((CategoryType)Enum.Parse(typeof(CategoryType), categorys[i]))).ToString(); + // } + // strb.Append(string.IsNullOrWhiteSpace(Class1.Config.Category) ? string.Empty : $"cid={string.Join(",", categorys)}&"); + // } + + // strb.Append(Class1.Config.Price1 == null ? string.Empty : $"price1={Class1.Config.Price1}&"); + // strb.Append(Class1.Config.Price2 == null ? string.Empty : $"price2={Class1.Config.Price2}&"); + // strb.Append(Class1.Config.CouponMoney == null ? string.Empty : $"coupon_money={Class1.Config.CouponMoney}&"); + // strb.Append(Class1.Config.Sales == null ? string.Empty : $"sales={Class1.Config.Sales}&"); + // strb.Append(Class1.Config.Rate == null ? string.Empty : $"tk_rate={Class1.Config.Rate}&"); + + // var helper = new HttpHelper(); + // var result = helper.GetHtml(helper.GetItem(strb.ToString()));//获取网页对象 + // var doc = new HtmlDocument();//加载源代码,获取文档对象 + // doc.LoadHtml(result.Html);//加载网页信息 + // var res = doc.DocumentNode.SelectSingleNode("/html/body/div[4]/div[3]/div[1]"); + // if (res == null) + // res = doc.DocumentNode.SelectSingleNode("/html/body/div[3]/div[3]/div[1]"); + // if (res != null) + // { + // var goodsDivs = res.SelectNodes("div[@class='goods-item ']"); + // session.BeginTransaction(); + // List<fl_plugin_tbcirclepromotion_goodsinfos> goodsinfos = new List<fl_plugin_tbcirclepromotion_goodsinfos>(); + // foreach (var item in goodsDivs) + // { + // //{gid:'17098881',cid:'2',price:'14.9',coupon:'25',title:'标题链接'} + // try + // { + // var reg = Regex.Match(item.InnerHtml, @"{gid:'(?<gid>\d{5,10})',cid:'(?<cid>\d+)',price:'[.\d]+',coupon:'\d+',title:'标题链接'}"); + // if (reg.Success) + // { + // var gid = reg.Groups["gid"].Value; + // var cid = reg.Groups["cid"].Value; + // string url = "http://www.dataoke.com/gettpl?gid=" + gid + "&_=" + ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000); + // result = helper.GetHtml(helper.GetItem(url)); + // if (result != null) + // { + // var content1 = result.Html; + // if (content1.Contains("元定金,再领")) continue; + + // var content2 = item.InnerText.Replace("\n", "").Replace("\t", "").Replace(" ", ""); + // //加入收藏复制文案荷仕兰成人系列中老年奶粉900g券后价¥43营销计划30.1%券¥140销量1428优惠券剩余:100000/100000店铺:放单人: + // //(?<佣金比例>[.\d]+)%券¥(?<优惠券>\d+)销量(?<销量>\d+)优惠券剩余:(?<优惠券剩余>\d+)/(\d+) + // reg = Regex.Match(content2, @"(?<佣金比例>[.\d]+)%券¥(?<优惠券>\d+)销量(?<销量>[^优]+)优惠券剩余:(?<优惠券剩余>\d+)/(\d+)"); + // if (reg.Success) + // { + // var goods = new fl_plugin_tbcirclepromotion_goodsinfos(); + + // goods.promotion_rate = double.Parse(reg.Groups["佣金比例"].Value); //佣金 + // var isWan = reg.Groups["销量"].Value.Contains("万"); //是否包含 万 字 + // var sales = reg.Groups["销量"].Value.Replace("万", "").Replace("+", ""); //把万字去掉 + // goods.sold_quantity = (int)(double.Parse(sales) * (isWan ? 10000 : 1)); //销量 + // goods.coupon_remain_quantity = reg.Groups["优惠券剩余"].Value; //优惠券剩余 + // goods.category_id = cid; + + // var values = content1.Split(new string[] { "</br>" }, StringSplitOptions.RemoveEmptyEntries); + // goods.goods_thumbnail_url = values[0].Replace(@"<img src=""", "").Replace(@""">", ""); + // goods.goods_name = values[1]; + // var final_price = double.Parse(values[2].Replace("券后【", "").Replace("元】包邮秒杀", ""));//券后价格 + // goods.coupon_discount = double.Parse(reg.Groups["优惠券"].Value); + // goods.normal_price = final_price + goods.coupon_discount; + // reg = Regex.Match(values[4], @"id=(?<id>\d{5,})"); + // goods.goods_id = reg.Success ? reg.Groups["id"].Value : "0"; + // goods.goods_desc = values[5]; + // reg = Regex.Match(values[3], @"href=""(.*?(?<activityId>activityId=.*?))"""); + + // goods.goods_quan = reg.Success ? reg.Groups["activityId"].Value : string.Empty; + + // goods.state = Enums.StateType.未推广; + // goods.goods_source = Enums.GoodsSourceType.接口采集; + // goods.cur_time = DateTime.Today; + + // //session.Insertable(goods).ExecuteCommand(); + // goodsinfos.Add(goods); + // } + // } + // } + // } + // catch { } + // } + // if (goodsinfos.Count != 0) + // session.Insertable(goodsinfos.ToArray()).ExecuteCommand(); + // session.Commit(); + // } + // } + // catch (Exception ex) + // { + // session.Rollback(); + // EventClient.OnEvent(this, $"淘宝采集:{ex.Message}{ex.StackTrace}"); + // } + //} + #endregion + + Dictionary<string, string> dics = new Dictionary<string, string>() { { "今日上新", "new_today/1/" }, { "高评分", "grade/1/" }, { "天猫", "tianmao/1/" }, { "视频单", "video/1/" }, { "聚划算", "cheap/1/" }, { "淘抢购", "rob/1/" }, { "营销返利", "rebate/1/" }, { "天猫超市", "tianmaoshop/1/" } }; + + #region 采集好单据数据 + public void GatherFactory() + { + strb.Length = 0; + var session = ApiClient.GetSession(); + try + { + //var cid = Class1.Config.HDK_Category == CategoryType.全部 ? string.Empty : $"cid/{(int)Class1.Config.HDK_Category}/"; + //var stage = Class1.Config.HDK_Stage == StageType.不限 ? string.Empty : dics[Class1.Config.HDK_Stage.ToString()]; + + //var url = $@"https://www.haodanku.com/index/index/nav/3/{cid}{stage}starttime/30/p/1.html?sale_min={Class1.Config.HDK_Sales}&tkrates_min={Class1.Config.HDK_Rate}&tkmoney_min={Class1.Config.HDK_Brokerage}&avg_min={Class1.Config.HDK_Avgmin}&coupon_min={Class1.Config.HDK_CouponMoney}&price_min={Class1.Config.HDK_Price1}&price_max={Class1.Config.HDK_Price2}"; + + var r = new Random(); + var url = string.Empty; + switch (Class1.Config.HDK_GatherType) + { + case GatherType.实时销量榜: + { + var p = r.Next(1, 6); + url = $"https://www.haodanku.com/index/index/nav/1/p/{p}.html"; + } + break; + case GatherType.今日爆单榜: + { + var p = r.Next(1, 6); + url = $"https://www.haodanku.com/index/index/nav/7/p/{p}.html"; + } + break; + case GatherType.昨日爆单榜: + url = "https://www.haodanku.com/index/index/nav/7/status/1.html"; + break; + case GatherType.出单指数榜: + url = "https://www.haodanku.com/index/teamsale/nav/7/status/2.html"; + break; + case GatherType.自定义条件: + default: + { + var cid = Class1.Config.HDK_Category == CategoryType.全部 ? string.Empty : $"cid/{(int)Class1.Config.HDK_Category}/"; + var stage = Class1.Config.HDK_Stage == StageType.不限 ? string.Empty : dics[Class1.Config.HDK_Stage.ToString()]; + + url = $@"https://www.haodanku.com/index/index/nav/3/{cid}{stage}starttime/30/p/1.html?sale_min={Class1.Config.HDK_Sales}&tkrates_min={Class1.Config.HDK_Rate}&tkmoney_min={Class1.Config.HDK_Brokerage}&avg_min={Class1.Config.HDK_Avgmin}&coupon_min={Class1.Config.HDK_CouponMoney}&price_min={Class1.Config.HDK_Price1}&price_max={Class1.Config.HDK_Price2}"; + } + break; + } + + //HttpHelper http = new HttpHelper(); + //HttpItem item = new HttpItem(); + //item.URL = url; + //var result = http.GetHtml(item); + //var html = result.Html; + ////var reg = Regex.Matches(html, @"领券:(?<优惠券地址>.*?)<br>下单:(?<商品链接>.*?)<br>(?<介绍>[^"""">]+)"); + //var reg = Regex.Matches(html, @"<img class=""public-img-loadend"" [\w\W]*?(?:(?:src)|(?:data-echo))=""(?<图片地址>[^""]+?jpg[^""]*?)""[\w\W]*?<br/>(?<标题>([^<]+?))<br>[\w\W]*?领券:(?<优惠券地址>[^\<]*?)<br>下单:(?<商品链接>.*?)<br>(?<介绍>[^""]+)[\w\W]+?<strong class=""color-light-orange "">[\w\W]*?(?<券后价>[^\<]+)[\w\W]*?<strong class=""color-light-orange "">(?<佣金比>[^\<]+)[\w\W]*?<strong class=""color-light-orange "">(?<佣金>[^\<]+)</strong>[\w\W]*?</span><span class=""fq-ticket-num"">¥(?<优惠券面额>[^\<]+)"); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem(); + item.URL = url; + var result = http.GetHtml(item); + var html = result.Html; + //var reg = Regex.Matches(html, @"领券:(?<优惠券地址>.*?)<br>下单:(?<商品链接>.*?)<br>(?<介绍>[^"""">]+)"); + + + var regStr = @"<span class=""am-block public-copy fq-copy"" id=""public-copy.*?"" data-tips=""<img class='' src='(?<图片地址>[\w\W]+?)' style='width:50px;'><br/>(?<标题>.+?)<br>.+?<br/>\s+?领券:(?<优惠券地址>[\w\W]+?)<br>下单:(?<商品链接>[\w\W]+?)<br>(?<介绍>[^""""]*?)"">[\w\W]+?</span>[\w\W]+?<span class="".+?"">券后</span>\s+?<strong class="".+?"">(?<券后价>.+?)</strong>[\w\W]+?<span class=""am-text-xs"">营销</span>\s+?<strong class="".+?"">(?<佣金比>.+?)<span class=""am-text-sm"">%</span></strong>\s+?</li>\s+?<li>\s+?<span class=""am-text-xs"">佣金</span>\s+?<strong class="".+?"">(?<佣金>.+?)</strong>\s+?</li>\s+?</ul>\s+?</div>\s+?<div class=""commodity-content-bottom"">\s+?<div class=""fq-goods-sale am-text-xs am-padding-bottom-xs"">\s+?<a rel=""nofollow"" href="".+?"" target=""_blank"" class=""am-inline-block"">\s+?<span class=""fq-ticket"">券</span><span class=""fq-ticket-num"">¥(?<优惠券面额>.+?)</span>"; + + MatchCollection regs = null; + + //排行 + if (Regex.IsMatch(html, regStr)) + { + regs = Regex.Matches(html, regStr); + }//条件搜索 + else + { + regStr = @"<img class=""public-img-loadend"" [\w\W]*?(?:(?:src)|(?:data-echo))=""(?<图片地址>[^""]+?jpg[^""]*?)""[\w\W]*?<br/>(?<标题>([^<]+?))<br>[\w\W]*?领券:(?<优惠券地址>[^\<]*?)<br>下单:(?<商品链接>.*?)<br>(?<介绍>[^""]+)[\w\W]+?<strong class=""color-light-orange "">[\w\W]*?(?<券后价>[^\<]+)[\w\W]*?<strong class=""color-light-orange "">(?<佣金比>[^\<]+)[\w\W]*?<strong class=""color-light-orange "">(?<佣金>[^\<]+)</strong>[\w\W]*?</span><span class=""fq-ticket-num"">¥(?<优惠券面额>[^\<]+)"; + if (Regex.IsMatch(html, regStr)) + regs = Regex.Matches(html, regStr); + } + + if (regs == null) + return; + + var existGoods = session.Find<fl_plugin_tbcirclepromotion_goodsinfos>("select * from fl_plugin_tbcirclepromotion_goodsinfos"); + + var goodsinfos = new List<fl_plugin_tbcirclepromotion_goodsinfos>(); + foreach (Match _item in regs) + { + try + { + var goods = new fl_plugin_tbcirclepromotion_goodsinfos(); + var _reg = Regex.Match(_item.Groups["优惠券地址"].Value, @"(http.*?(?<activityId>activityId=[^&]+))"); + goods.goods_quan = _reg.Success ? _reg.Groups["activityId"].Value : string.Empty; + + _reg = Regex.Match(_item.Groups["商品链接"].Value, @"id=(?<id>\d{5,})"); + goods.goods_id = _reg.Success ? _reg.Groups["id"].Value : "0"; + + var gTemp = existGoods.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + gTemp = goodsinfos.FirstOrDefault(f => f.goods_id == goods.goods_id); + if (gTemp != null) + continue; + + goods.goods_desc = _item.Groups["介绍"].Value; + goods.coupon_discount = double.Parse(_item.Groups["优惠券面额"].Value); + double final_price = double.Parse(_item.Groups["券后价"].Value); + goods.normal_price = final_price + goods.coupon_discount; + goods.goods_thumbnail_url = _item.Groups["图片地址"].Value; + goods.goods_name = _item.Groups["标题"].Value; + goods.promotion_rate = double.Parse(_item.Groups["佣金比"].Value); + + //goods.sold_quantity = + //goods.category_id = + + goods.state = Enums.StateType.未推广; + goods.goods_source = Enums.GoodsSourceType.接口采集; + goods.cur_time = DateTime.Now; + goodsinfos.Add(goods); + } + catch (Exception ex) + { } + } + if (goodsinfos.Count != 0) + session.Insertable(goodsinfos.ToArray()).ExecuteCommand(); + } + catch (Exception ex) + { + //session.Rollback(); + EventClient.OnEvent(this, $"淘宝采集:{ex.Message}{ex.StackTrace}"); + } + } + #endregion + + } +} diff --git a/应用/Weixin.TBCirclePromotion/Class1.cs b/应用/Weixin.TBCirclePromotion/Class1.cs new file mode 100644 index 0000000..2c04bb0 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Class1.cs @@ -0,0 +1,119 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Linq; +using Weixin.TBCirclePromotion.Entitys; +using Weixin.TBCirclePromotion.Properties; + +namespace Weixin.TBCirclePromotion +{ + public class Class1 : Plugin + { + + public Class1() + { + this.Logo = Resources.淘宝发单; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + /// <summary> + /// + /// </summary> + public override void Start() + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<fl_plugin_tbcirclepromotion_goodsinfos>()) session.CreateTable<fl_plugin_tbcirclepromotion_goodsinfos>(); + else + { + if (!session.ColumnExist("fl_plugin_tbcirclepromotion_goodsinfos", "goods_quan")) + session.AddColumn("fl_plugin_tbcirclepromotion_goodsinfos", "goods_quan", "varchar(255) default ''"); + } + + //如果存在原来的表将来的数据导入到新的表中,在原来的表给删除 + if (session.TableExist<fl_plugin_tbcirclepromotion_tbtgw>()) + { + var tbtgws = session.Find<fl_plugin_tbcirclepromotion_tbtgw>("select * from fl_plugin_tbcirclepromotion_tbtgw").ToList(); + if (tbtgws != null) + { + foreach (var item in tbtgws) + { + session.Insertable<fl_adzone_info>(new fl_adzone_info() + { + adzone_name = item.pid_name, //推广位名称 + adzone_pid = item.pid, //推广位pid + adzone_pid_cps_name = item.pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType //自定义类型 + }).ExecuteCommand(); + } + } + session.DropTable<fl_plugin_tbcirclepromotion_tbtgw>(); + } + #endregion + + //创建配置文件 + try + { + Config = this.ReadConfig<Config>(); + Tools.GetBaseIco();//检测优惠券底图 + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + //创建线程 + TimerTask.NewTimer<SendCircleFriendThread>(60); //创建线程 - 发送朋友圈的线程 60秒 + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close<SendCircleFriendThread>(); //关闭线程 + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/Weixin.TBCirclePromotion/Config.cs b/应用/Weixin.TBCirclePromotion/Config.cs new file mode 100644 index 0000000..46c6000 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Config.cs @@ -0,0 +1,823 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using CircleFriends.Control; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using Weixin.TBCirclePromotion.Control; +using static Api.Framework.ApiClient; +using static Weixin.TBCirclePromotion.Enums; + +namespace Weixin.TBCirclePromotion +{ + [Config(Name = "插件-淘宝发单-配置")] + public class Config + { + + #region 大淘客xxx + // #region 发单功能 + + // #region 采集 + // /// <summary> + // /// 发单条件 - 商品最低售价 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("01.采集开关"), DefaultValue(SwitchType.开启) + // ] + // public SwitchType Switch { get; set; } + + // /// <summary> + // /// 采集数据触发数量 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("02.采集触发量"), DefaultValue(10), + // Description(@"当采集开关为开启时,该值为一个采集点,当采集剩余的商品数量少于等于采集触发量,将自动进行采集操作") + // ] + // public int GatherTouchNum { get; set; } + + // /// <summary> + // /// 发单条件 - 类目 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("03.类目"), DefaultValue(@""), + // Description(@"筛选类目:居家日用、美食、母婴、美妆、女装、数码家电、文娱车品、内衣、家装家纺、鞋品、男装、配饰、户外运动、箱包"), + // Editor(typeof(CategoryControl), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public string Category { get; set; } + + // /// <summary> + // /// 发单条件 - 平台 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("04.平台"), DefaultValue(StageType.不限), + // Description(@"筛选拼台:聚划算、淘抢购、天猫、金牌卖家、海淘") + // ] + // public StageType Stage { get; set; } + + // /// <summary> + // /// 发单条件 - 商品最低售价 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("05.商品最低售价"), + // Description(@"采集的产品最低价格,不填写表示不限制最价!") + // ] + // public double? Price1 { get; set; } + + // /// <summary> + // /// 发单条件 - 商品最高售价 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("06.商品最高售价"), + // Description(@"采集的产品最高价格,不填写表示不限制最高价!") + // ] + // public double? Price2 { get; set; } + + // /// <summary> + // /// 发单条件 - 佣金比例 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("07.佣金比例"), + // Description(@"采集的产品佣金比例条件,选中的比例包含选中的值.不填写表示不限制佣金比例!") + // ] + // public double? Rate { get; set; } + + // /// <summary> + // /// 发单条件 - 优惠券面额 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("08.发单条件 - 优惠券面额"), DefaultValue(@""), + // Description(@"商品对应的优惠券面额大于等于预设的值"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public double? CouponMoney { get; set; } + + // /// <summary> + // /// 发单条件 - 月销量 + // /// </summary> + // [ + // Category("1)、自动采集"), DisplayName("09.发单条件 - 月销量"), DefaultValue(@""), + // Description(@"商品月销量大于等于预设的值"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public int? Sales { get; set; } + + // #endregion + + // #region 开始时间 + + // /// <summary> + // /// 朋友圈发单二维码模板 + // /// </summary> + // [ + // Category("2)、朋友圈基础设置"), DisplayName("01.发单二维码模板"), DefaultValue(QrImageType.模板B), + // Description(@"朋友圈发单二维码模板") + // ] + // public QrImageType Model { get; set; } + + // /// <summary> + // /// 朋友圈发单方式 + // /// </summary> + // [ + // Category("2)、朋友圈基础设置"), DisplayName("02.发单方式"), DefaultValue(SendModeType.多产品), + // Description(@"朋友圈发单方式 + //第一种多产品发送,一条朋友圈信息中一个图片包含一个宝贝信息 + //第二种单产品发送,一条朋友圈信息中包含多张该宝贝的图片信息") + // ] + // public SendModeType SendMode { get; set; } + + // private string[] _sendTaskTimes; + // [ + // Category("2)、朋友圈基础设置"), DisplayName("03.发送任务时间段"), + // Description(@"每一行为一个发送时间段 + //格式:时间1-时间2 + //注:时间1 必须大于 时间2") + // ] + // public string[] SendTaskTimes //{ get; set; } + // { + // get { return _sendTaskTimes; } + // set + // { + // var sendTaskTimes = value as string[]; + // if (sendTaskTimes != null && sendTaskTimes.Length != 0) + // { + // for (int i = 0; i < sendTaskTimes.Length; i++) + // { + // var times = sendTaskTimes[i].Trim().Split('-'); + // if (times.Length == 2) + // { + // var begin = DateTime.Parse(times[0]); + // var end = DateTime.Parse(times[1]); + // if (begin >= end) + // throw new Exception($"开始时间必须小于结束时间:[{sendTaskTimes[i]}]"); + // } + // } + // } + // _sendTaskTimes = value; + // } + // } + + // /// <summary> + // /// 朋友圈发送间隔,单位 分 + // /// </summary> + // [ + // Category("2)、朋友圈基础设置"), DisplayName("04.朋友圈发送间隔"), DefaultValue(120), + // Description(@"朋友圈推广商品间隔,单位 分") + // ] + // public double Interval_Circle { get; set; } + + // #endregion + + // #region 发送设置 + + // /// <summary> + // /// 发送商品图片数量 + // /// </summary> + // [ + // Category("3)、多产品发单设置"), DisplayName("01.发送推广图片数量"), DefaultValue(9), + // Description(@"发送朋友圈推广图片数量,最多9张图片") + // ] + // public int Multi_SendGoodsImageNum { get; set; } + + // /// <summary> + // /// 宝贝描述语 + // /// </summary> + // [ + // Category("3)、多产品发单设置"), DisplayName("02.发送的文字内容"), DefaultValue(@"╭┈┈┈┄┈┈┈┈┈╮ + // 爆款榜单 + //╰┈┈┈┈┈┈┈┈┈╯ + //补贴奖励和帮助渠道 + + //手机淘宝分享宝贝给我 + //可以查询优惠券款下单 + + //还有网购红包领哦"), + // Description(@"发送朋友圈时的文本内容"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public string Multi_ContentCircle { get; set; } + + // /// <summary> + // /// 宝贝描述语 + // /// </summary> + // [ + // Category("3)、多产品发单设置"), DisplayName("03.宝贝描述语"), DefaultValue(@""), + // Description(@"图片中宝贝描述信息,为空时以采集到的数据为准. + //支持变量:[商品标题]、[商品描述]、[已售数量]、[店铺名称]、[优惠券金额]、[优惠券数量]、[商品单价]、[券后价]、[购买地址]"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public string Multi_GoodsDesc { get; set; } + + // /// <summary> + // /// 朋友圈追加评语 - 多个商品 + // /// </summary> + // [ + // Category("3)、多产品发单设置"), DisplayName("04.朋友圈追加评语"), DefaultValue(@""), + // Description(@"朋友圈商品推广之后,追加评语"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public string Multi_AdditionalComment { get; set; } + + // /// <summary> + // /// 是否合成宝贝优惠券 + // /// </summary> + // [ + // Category("4)、单产品发单设置"), DisplayName("01.是否合成优惠券"), DefaultValue(SwitchType.开启), + // Description(@"功能开启时,将自动合成优惠券图片") + // ] + // public SwitchType Single_IsSynthCoupon { get; set; } + + // /// <summary> + // /// 是否合成宝贝二维码图片 + // /// </summary> + // [ + // Category("4)、单产品发单设置"), DisplayName("02.是否合成二维码"), DefaultValue(SwitchType.开启), + // Description(@"功能开启时,将自动将其中一张图片合成二维码图片") + // ] + // public SwitchType Single_IsQRCodePic { get; set; } + + // /// <summary> + // /// 二维码宝贝描述语 + // /// </summary> + // [ + // Category("4)、单产品发单设置"), DisplayName("03.二维码图片底栏描述语"), DefaultValue(@""), + // Description(@"合成二维码功能开启时,合成二维码图片下方的空白栏内容。可以用于放广告内容"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public string Single_GoodsQRCodePicDesc { get; set; } + + // /// <summary> + // /// 宝贝描述语 + // /// </summary> + // [ + // Category("4)、单产品发单设置"), DisplayName("04.发送的文字内容"), DefaultValue(@"[商品标题] + //领[优惠券金额]元券,券后【[券后价]元】包邮秒杀! + //【推荐理由】[商品描述]"), + // Description(@"发送朋友圈时的文本内容 + //支持变量:[商品标题]、[商品单价]、[优惠券金额]、[券后价]、[商品描述]、[已售数量]、[店铺名称]"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public string Single_ContentCircle { get; set; } + + // /// <summary> + // /// 朋友圈追加评语 - 单个商品 + // /// </summary> + // [ + // Category("4)、单产品发单设置"), DisplayName("05.朋友圈追加评语"), DefaultValue(@"[商品标题] + //商品单价:[商品单价]元 + //优惠券金额:[优惠券金额]元 + //券后价:[券后价]元 + //购买地址:[购买地址] + //淘口令:[淘口令]"), + // Description(@"朋友圈商品推广之后,追加评语 + //支持变量:[商品标题]、[已售数量]、[店铺名称]、[优惠券金额]、[优惠券数量]、[商品单价]、[券后价]、[购买地址]、[淘口令]"), + // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // ] + // public string Single_AdditionalComment { get; set; } + + // /// <summary> + // /// 自动清理 + // /// </summary> + // [ + // Category("5)、定时清理"), DisplayName("01.定时清理"), DefaultValue(SwitchType.开启), + // Description(@"功能开启时,将在设置的时间进行采集数据的清空操作") + // ] + // public SwitchType Auto_IsClear { get; set; } + + // private string _autoClearTaskTimes; + // [ + // Category("5)、定时清理"), DisplayName("02.定时清理时间"), + // Description(@"定时清理时间 + //格式:HH:mm + //例:23:59 + //注:时间为24小时制") + // ] + // public string AutoClearTaskTimes //{ get; set; } + // { + // get { return _autoClearTaskTimes; } + // set + // { + // try + // { + // var time = value as string; + // var _time = DateTime.Parse(time); + // } + // catch (Exception) + // { + // throw new Exception($"时间格式不正确"); + // } + // _autoClearTaskTimes = value; + // } + // } + + // ///// <summary> + // ///// 朋友圈追加评语 + // ///// </summary> + // //[ + // // Category("4)、单产品发单设置"), DisplayName("04."), DefaultValue(@""), + // // Description(@"朋友圈商品推广之后,追加评语"), + // // Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + // //] + // //public string AdditionalComment { get; set; } + + + + + // /// <summary> + // /// 记录发送的时间 + // /// </summary> + // [Browsable(false)] + // public DateTime RecordSendTime { get; set; } + + // #endregion + + // #endregion + + // public Config() + // { + // this.Auto_IsClear = SwitchType.开启; + // this.Switch = SwitchType.开启; + // this.GatherTouchNum = 10; + // this.Stage = StageType.不限; + // this.SendMode = SendModeType.多产品; + // this.Model = QrImageType.模板B; + // this.Price1 = null; + // this.Price1 = null; + // this.CouponMoney = null; + // this.Rate = null; + // this.Category = string.Empty; + // this.Sales = null; + // this.Multi_ContentCircle = @"╭┈┈┈┄┈┈┈┈┈╮ + // 爆款榜单 + //╰┈┈┈┈┈┈┈┈┈╯ + //补贴奖励和帮助渠道 + + //手机淘宝分享宝贝给我 + //可以查询优惠券款下单 + + //还有网购红包领哦"; + // this.Multi_SendGoodsImageNum = 9; + // this.Interval_Circle = 120; + // this.SendTaskTimes = new string[] { }; + // this._sendTaskTimes = new string[] { "09:00-22:00" }; + // this._autoClearTaskTimes = "23:59"; + + // this.Single_IsSynthCoupon = SwitchType.开启; + // this.Single_IsQRCodePic = SwitchType.开启; + // this.Single_ContentCircle = @"[商品标题] + //领[优惠券金额]元券,券后【[券后价]元】包邮秒杀! + //【推荐理由】[商品描述]"; + // this.Single_AdditionalComment = @"[商品标题] + //商品单价:[商品单价]元 + //优惠券金额:[优惠券金额]元 + //券后价:[券后价]元 + //购买地址:[购买地址] + //淘口令:[淘口令]"; + // this.Single_GoodsQRCodePicDesc = string.Empty; + // } + #endregion + + #region 采集 + /// <summary> + /// 采集开关 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("01.采集开关"), DefaultValue(SwitchType.开启) + ] + public SwitchType HDK_Switch { get; set; } + + /// <summary> + /// 采集数据触发数量 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("02.采集触发量"), DefaultValue(10), + Description(@"当采集开关为开启时,该值为一个采集点,当采集剩余的商品数量少于等于采集触发量,将自动进行采集操作") + ] + public int HDK_GatherTouchNum { get; set; } + + /// <summary> + /// 采集 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("03.采集导航"), DefaultValue(GatherType.今日爆单榜), + Description(@"采集导航,设置为自定义条件将会以以下设置条件采集商品") + ] + public GatherType HDK_GatherType { get; set; } + + /// <summary> + /// 发单条件 - 类目 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("04.类目"), DefaultValue(CategoryType.全部), + Description(@"筛选类目:全部、女装、男装、内衣、美妆、配饰、鞋品、箱包、儿童、母婴、居家、美食、数码、家电、车品、文体、宠物、其他") + //,Editor(typeof(CategoryControl), typeof(System.Drawing.Design.UITypeEditor)) + ] + public CategoryType HDK_Category { get; set; } + + /// <summary> + /// 发单条件 - 平台 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("05.采集源"), DefaultValue(StageType.不限), + Description(@"筛选平台:今日上新、高评分、天猫、视频单、聚划算、淘抢购、营销返利、天猫超市") + ] + public StageType HDK_Stage { get; set; } + + private double? _HDK_Price1; + /// <summary> + /// 发单条件 - 商品最低售价 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("06.商品最低售价"), + Description(@"采集的产品最低价格,不填写表示不限制最价!") + ] + public double? HDK_Price1 + { + get { return _HDK_Price1; } + set + { + if (value != null && 0 > value) + throw new Exception($"最低售价不能低于0"); + _HDK_Price1 = value; + } + } + + private double? _HDK_Price2; + /// <summary> + /// 发单条件 - 商品最高售价 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("07.商品最高售价"), + Description(@"采集的产品最高价格,不填写表示不限制最高价!") + ] + public double? HDK_Price2 + { + get { return _HDK_Price2; } + set + { + if (value != null && 0 > value) + throw new Exception($"最高售价不能低于0"); + _HDK_Price2 = value; + } + } + + private double? _HDK_Rate; + /// <summary> + /// 发单条件 - 佣金比例 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("08.佣金比例"), DefaultValue(null), + Description(@"采集的产品佣金比例条件,选中的比例包含选中的值.不填写表示不限制佣金比例!") + ] + public double? HDK_Rate + { + get { return _HDK_Rate; } + set + { + if (value != null && (0 > value || value > 100)) + throw new Exception($"最低佣金比例不能低于0并且不能高于100"); + _HDK_Rate = value; + } + } + + private double? _HDK_Brokerage; + /// <summary> + /// 发单条件 - 佣金 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("09.佣金"), DefaultValue(null), + Description(@"采集的产品佣金比例条件,选中的比例包含选中的值.不填写表示不限制佣金比例!") + ] + public double? HDK_Brokerage + { + get { return _HDK_Brokerage; } + set + { + if (value != null && 0 > value) + throw new Exception($"最低佣金不能低于0"); + _HDK_Brokerage = value; + } + } + + private double? _HDK_CouponMoney; + /// <summary> + /// 发单条件 - 优惠券面额 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("10.优惠券面额"), DefaultValue(null), + Description(@"商品对应的优惠券面额大于等于预设的值"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public double? HDK_CouponMoney + { + get { return _HDK_CouponMoney; } + set + { + if (value != null && 0 > value) + throw new Exception($"最低优惠券面额不能低于0"); + _HDK_CouponMoney = value; + } + } + + private int? _HDK_Sales; + /// <summary> + /// 发单条件 - 月销量 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("11.月销量"), DefaultValue(null), + Description(@"商品月销量大于等于预设的值"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public int? HDK_Sales + { + get { return _HDK_Sales; } + set + { + if (value != null && 0 > value) + throw new Exception($"最低月销量不能低于0"); + _HDK_Sales = value; + } + } + + private double? _HDK_Avgmin; + /// <summary> + /// 发单条件 - 月销量 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("12.单品评分"), DefaultValue(null), + Description(@"商品单品评分大于等于预设的值,值:0-5"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public double? HDK_Avgmin + { + get { return _HDK_Avgmin; } + set + { + if (value != null && (0 > value || value > 5)) + throw new Exception($"最低单品评分不能低于0并且不能高于5"); + _HDK_Avgmin = value; + } + } + + #endregion + + /// <summary> + /// 朋友圈发单二维码模板 + /// </summary> + [ + Category("2)、朋友圈基础设置"), DisplayName("01.发单二维码模板"), DefaultValue(QrImageType.模板B), + Description(@"朋友圈发单二维码模板") + ] + public QrImageType HDK_Model { get; set; } + + /// <summary> + /// 朋友圈发单方式 + /// </summary> + [ + Category("2)、朋友圈基础设置"), DisplayName("02.发单方式"), DefaultValue(SendModeType.多产品), + Description(@"朋友圈发单方式 + 第一种多产品发送,一条朋友圈信息中一个图片包含一个宝贝信息 + 第二种单产品发送,一条朋友圈信息中包含多张该宝贝的图片信息") + ] + public SendModeType HDK_SendMode { get; set; } + + private string[] _HDK_SendTaskTimes; + [ + Category("2)、朋友圈基础设置"), DisplayName("03.发送任务时间段"), + Description(@"每一行为一个发送时间段 + 格式:时间1-时间2 + 注:时间1 必须大于 时间2") + ] + public string[] HDK_SendTaskTimes //{ get; set; } + { + get { return _HDK_SendTaskTimes; } + set + { + var sendTaskTimes = value as string[]; + if (sendTaskTimes != null && sendTaskTimes.Length != 0) + { + for (int i = 0; i < sendTaskTimes.Length; i++) + { + var times = sendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0]); + var end = DateTime.Parse(times[1]); + if (begin >= end) + throw new Exception($"开始时间必须小于结束时间:[{sendTaskTimes[i]}]"); + } + } + } + _HDK_SendTaskTimes = value; + } + } + + /// <summary> + /// 朋友圈发送间隔,单位 分 + /// </summary> + [ + Category("2)、朋友圈基础设置"), DisplayName("04.朋友圈发送间隔"), DefaultValue(120), + Description(@"朋友圈推广商品间隔,单位 分") + ] + public double HDK_Interval_Circle { get; set; } + + //#endregion + + //#region 发送设置 + + /// <summary> + /// 发送商品图片数量 + /// </summary> + [ + Category("3)、多产品发单设置"), DisplayName("01.发送推广图片数量"), DefaultValue(9), + Description(@"发送朋友圈推广图片数量,最多9张图片") + ] + public int HDK_Multi_SendGoodsImageNum { get; set; } + + /// <summary> + /// 宝贝描述语 + /// </summary> + [ + Category("3)、多产品发单设置"), DisplayName("02.发送的文字内容"), DefaultValue(@"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 + ╰┈┈┈┈┈┈┈┈┈╯ + 补贴奖励和帮助渠道 + + 手机淘宝分享宝贝给我 + 可以查询优惠券款下单 + + 还有网购红包领哦"), + Description(@"发送朋友圈时的文本内容"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string HDK_Multi_ContentCircle { get; set; } + + /// <summary> + /// 宝贝描述语 + /// </summary> + [ + Category("3)、多产品发单设置"), DisplayName("03.宝贝描述语"), DefaultValue(@""), + Description(@"图片中宝贝描述信息,为空时以采集到的数据为准. + 支持变量:[商品标题]、[商品描述]、[已售数量]、[店铺名称]、[优惠券金额]、[优惠券数量]、[商品单价]、[券后价]、[购买地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string HDK_Multi_GoodsDesc { get; set; } + + /// <summary> + /// 朋友圈追加评语 - 多个商品 + /// </summary> + [ + Category("3)、多产品发单设置"), DisplayName("04.朋友圈追加评语"), DefaultValue(@""), + Description(@"朋友圈商品推广之后,追加评语"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string HDK_Multi_AdditionalComment { get; set; } + + /// <summary> + /// 是否合成宝贝优惠券 + /// </summary> + [ + Category("4)、单产品发单设置"), DisplayName("01.是否合成优惠券"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将自动合成优惠券图片") + ] + public SwitchType HDK_Single_IsSynthCoupon { get; set; } + + /// <summary> + /// 是否合成宝贝二维码图片 + /// </summary> + [ + Category("4)、单产品发单设置"), DisplayName("02.是否合成二维码"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将自动将其中一张图片合成二维码图片") + ] + public SwitchType HDK_Single_IsQRCodePic { get; set; } + + /// <summary> + /// 二维码宝贝描述语 + /// </summary> + [ + Category("4)、单产品发单设置"), DisplayName("03.二维码图片底栏描述语"), DefaultValue(@""), + Description(@"合成二维码功能开启时,合成二维码图片下方的空白栏内容。可以用于放广告内容"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string HDK_Single_GoodsQRCodePicDesc { get; set; } + + /// <summary> + /// 宝贝描述语 + /// </summary> + [ + Category("4)、单产品发单设置"), DisplayName("04.发送的文字内容"), DefaultValue(@"[商品标题] + 领[优惠券金额]元券,券后【[券后价]元】包邮秒杀! + 【推荐理由】[商品描述]"), + Description(@"发送朋友圈时的文本内容 + 支持变量:[商品标题]、[商品单价]、[优惠券金额]、[券后价]、[商品描述]、[已售数量]、[店铺名称]、[购买地址]、[淘口令]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string HDK_Single_ContentCircle { get; set; } + + /// <summary> + /// 朋友圈追加评语 - 单个商品 + /// </summary> + [ + Category("4)、单产品发单设置"), DisplayName("05.朋友圈追加评语"), DefaultValue(@"[商品标题] + 商品单价:[商品单价]元 + 优惠券金额:[优惠券金额]元 + 券后价:[券后价]元 + 购买地址:[购买地址] + 淘口令:[淘口令]"), + Description(@"朋友圈商品推广之后,追加评语 + 支持变量:[商品标题]、[已售数量]、[店铺名称]、[优惠券金额]、[优惠券数量]、[商品单价]、[券后价]、[购买地址]、[淘口令]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string HDK_Single_AdditionalComment { get; set; } + + /// <summary> + /// 自动清理 + /// </summary> + [ + Category("5)、定时清理"), DisplayName("01.定时清理"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将在设置的时间进行采集数据的清空操作") + ] + public SwitchType HDK_Auto_IsClear { get; set; } + + private string _HDK_AutoClearTaskTimes; + [ + Category("5)、定时清理"), DisplayName("02.定时清理时间"), DefaultValue("23:59"), + Description(@"定时清理时间 + 格式:HH:mm + 例:23:59 + 注:时间为24小时制") + ] + public string HDK_AutoClearTaskTimes + { + get { return _HDK_AutoClearTaskTimes; } + set + { + try + { + var time = value as string; + var _time = DateTime.Parse(time); + } + catch (Exception) + { + throw new Exception($"时间格式不正确"); + } + _HDK_AutoClearTaskTimes = value; + } + } + + /// <summary> + /// 记录发送的时间 + /// </summary> + [Browsable(false)] + public DateTime HDK_RecordSendTime { get; set; } + + + public Config() + { + this.HDK_Auto_IsClear = SwitchType.开启; + this.HDK_Switch = SwitchType.开启; + this.HDK_GatherTouchNum = 10; + this.HDK_Stage = StageType.不限; + this.HDK_SendMode = SendModeType.多产品; + this.HDK_Model = QrImageType.模板B; + this.HDK_GatherType = GatherType.实时销量榜; + this.HDK_Price1 = null; + this.HDK_Price1 = null; + this.HDK_CouponMoney = null; + this.HDK_Rate = null; + this.HDK_Category = CategoryType.全部; + this.HDK_Sales = null; + this.HDK_Multi_AdditionalComment = string.Empty; + this.HDK_Multi_ContentCircle = @"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 + ╰┈┈┈┈┈┈┈┈┈╯ + 补贴奖励和帮助渠道 + + 手机淘宝分享宝贝给我 + 可以查询优惠券款下单 + + 还有网购红包领哦"; + this.HDK_Multi_SendGoodsImageNum = 9; + this.HDK_Interval_Circle = 120; + this._HDK_SendTaskTimes = new string[] { "09:00-22:00" }; + this._HDK_AutoClearTaskTimes = "23:59"; + + this.HDK_Single_IsSynthCoupon = SwitchType.开启; + this.HDK_Single_IsQRCodePic = SwitchType.开启; + this.HDK_Single_ContentCircle = @"[商品标题] + 领[优惠券金额]元券,券后【[券后价]元】包邮秒杀! + 【推荐理由】[商品描述]"; + this.HDK_Single_AdditionalComment = @"[商品标题] + 商品单价:[商品单价]元 + 优惠券金额:[优惠券金额]元 + 券后价:[券后价]元 + 购买地址:[购买地址] + 淘口令:[淘口令]"; + this.HDK_Single_GoodsQRCodePicDesc = string.Empty; + } + + } +} diff --git a/应用/Weixin.TBCirclePromotion/Control/ArrayControl.cs b/应用/Weixin.TBCirclePromotion/Control/ArrayControl.cs new file mode 100644 index 0000000..558bb14 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Control/ArrayControl.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace Weixin.TBCirclePromotion.Control +{ + class ArrayControl : PropertyGridEditStyle + { + + public ArrayControl() + { + UITypeEditorEditStyle = System.Drawing.Design.UITypeEditorEditStyle.Modal; + } + public override string GetValue() + { + return "点击"; + } + + public override void SetValue(object value) + { + // var userMemo = value as UserMemoControl; + Class1.Config.HDK_SendTaskTimes = value.ToString().Split(new string[] { @"\r\n" }, StringSplitOptions.RemoveEmptyEntries); + } + } +} diff --git a/应用/Weixin.TBCirclePromotion/Control/CategoryControl.cs b/应用/Weixin.TBCirclePromotion/Control/CategoryControl.cs new file mode 100644 index 0000000..fccbd2c --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Control/CategoryControl.cs @@ -0,0 +1,59 @@ +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static Weixin.TBCirclePromotion.Enums; + +namespace CircleFriends.Control +{ + class CategoryControl : PropertyGridEditStyle + { + public CategoryControl() + { + var listBox = new CheckedListBoxControl(); + foreach (CategoryType item in Enum.GetValues(typeof(CategoryType))) + { + listBox.Items.Add(new CheckedListBoxItem(null, item.ToString())); + } + Control = listBox; + } + + /// <summary> + /// 将选着的数据进行展示 + /// </summary> + /// <returns></returns> + public override string GetValue() + { + var listBox = Control as CheckedListBoxControl; + string[] strs = new string[listBox.CheckedItems.Count]; + int i = 0; + foreach (var item in listBox.CheckedItems) + { + strs[i] = item.ToString(); + i++; + } + return string.Join(",", strs); + } + + /// <summary> + /// 将内容在控件里面勾选 + /// </summary> + /// <param name="value"></param> + public override void SetValue(object value) + { + var listBox = Control as CheckedListBoxControl; + var strs = value == null ? new string[] { } : value.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + foreach (var item in listBox.Items) + { + listBox.SetItemChecked(i, !string.IsNullOrEmpty(strs.FirstOrDefault(f => f == item.ToString()))); + i++; + } + } + + } +} \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/Entitys/fl_plugin_tbcirclepromotion_goodsinfos.cs b/应用/Weixin.TBCirclePromotion/Entitys/fl_plugin_tbcirclepromotion_goodsinfos.cs new file mode 100644 index 0000000..222fa4c --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Entitys/fl_plugin_tbcirclepromotion_goodsinfos.cs @@ -0,0 +1,81 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Weixin.TBCirclePromotion.Enums; + +namespace Weixin.TBCirclePromotion.Entitys +{ + /// <summary> + /// 采集到的商品信息 + /// </summary> + public class fl_plugin_tbcirclepromotion_goodsinfos : base_model + { + /// <summary> + /// 商品id + /// </summary> + public string goods_id { get; set; } + /// <summary> + /// 商品标题 + /// </summary> + public string goods_name { get; set; } + /// <summary> + /// 商品描述 + /// </summary> + public string goods_desc { get; set; } + /// <summary> + /// 商品图片链接 + /// </summary> + public string goods_thumbnail_url { get; set; } + /// <summary> + /// 已售卖件数 + /// </summary> + public int sold_quantity { get; set; } + /// <summary> + /// 商品单价,单位为元 + /// </summary> + public double normal_price { get; set; } + /// <summary> + /// 店铺名 + /// </summary> + public string mall_name { get; set; } + /// <summary> + /// 类目id + /// </summary> + public string category_id { get; set; } + /// <summary> + /// 优惠券面额,单位为元 + /// </summary> + public double coupon_discount { get; set; } + /// <summary> + /// 优惠券剩余数量 + /// </summary> + public string coupon_remain_quantity { get; set; } + /// <summary> + /// 优惠券活动ID + /// </summary> + public string goods_quan { get; set; } + /// <summary> + /// 佣金比例,百分比 + /// </summary> + public double promotion_rate { get; set; } + /// <summary> + /// 购买链接 转连之后 + /// </summary> + public string shopping_url { get; set; } + /// <summary> + /// 发送状态,是否发送过 + /// </summary> + public StateType state { get; set; } + /// <summary> + /// 采集的日期 + /// </summary> + public DateTime cur_time { get; set; } + /// <summary> + /// 产品数据的来源 GoodsSourceType枚举 + /// </summary> + public GoodsSourceType goods_source { get; set; } + } +} diff --git a/应用/Weixin.TBCirclePromotion/Entitys/fl_plugin_tbcirclepromotion_tbtgw.cs b/应用/Weixin.TBCirclePromotion/Entitys/fl_plugin_tbcirclepromotion_tbtgw.cs new file mode 100644 index 0000000..37a6ced --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Entitys/fl_plugin_tbcirclepromotion_tbtgw.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.TBCirclePromotion.Entitys +{ + public class fl_plugin_tbcirclepromotion_tbtgw + { + /// <summary> + /// 左连接主表 fl_robot_info 的主键 + /// </summary> + public int robot_id { get; set; } + /// <summary> + /// 主推广位CPS名称 + /// </summary> + public string pid_cps_name { get; set; } + /// <summary> + /// 主推广位id + /// </summary> + public string pid { get; set; } + /// <summary> + /// 主推广位昵称 + /// </summary> + public string pid_name { get; set; } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} diff --git a/应用/Weixin.TBCirclePromotion/Entitys/tbinfo_temp.cs b/应用/Weixin.TBCirclePromotion/Entitys/tbinfo_temp.cs new file mode 100644 index 0000000..f770be5 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Entitys/tbinfo_temp.cs @@ -0,0 +1,63 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.TBCirclePromotion.Entitys +{ + /// <summary> + /// 临时的表 (用于数据显示) + /// </summary> + public class tbinfo_temp + { + public long ID { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _adzone_pid_cps_name { get; set; } + public string adzone_pid_cps_name + { + get { return _adzone_pid_cps_name; } + set { _adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _adzone_pid; + /// <summary> + /// 主推广位id + /// </summary> + public string adzone_pid + { + get { return _adzone_pid; } + set { _adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _adzone_name; + + public string adzone_name + { + get { return _adzone_name; } + set { _adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/Enums.cs b/应用/Weixin.TBCirclePromotion/Enums.cs new file mode 100644 index 0000000..68df4f6 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Enums.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.TBCirclePromotion +{ + public class Enums + { + #region 大淘客 xxx + ///// <summary> + ///// 大淘客类目枚举 + ///// </summary> + //public enum CategoryType + //{ + // 女装 = 1, + // 母婴 = 2, + // 美妆 = 3, + // 居家日用 = 4, + // 鞋品 = 5, + // 美食 = 6, + // 文娱车品 = 7, + // 数码家电 = 8, + // 男装 = 9, + // 内衣 = 10, + // 箱包 = 11, + // 配饰 = 12, + // 户外运动 = 13, + // 家装家纺 = 14 + //} + + ///// <summary> + ///// 大淘客搜宝贝平台 + ///// </summary> + //public enum StageType + //{ + // 不限 = 0, + // 聚划算 = 1, + // 淘抢购 = 2, + // 天猫 = 3, + // 金牌卖家 = 4, + // 海淘 = 5 + //} + + #endregion + + public enum GoodsSourceType + { + 文件导入 = 0, + 接口采集 = 1, + 对象 = 2 + } + + public enum StateType + { + 已推广 = 0, + 未推广 = 1 + } + + public enum SendModeType + { + 多产品 = 0, + 单产品 = 1 + } + + #region 好单库 + /// <summary> + /// 好单库类目枚举 + /// </summary> + public enum CategoryType + { + 全部 = 0, + 女装 = 1, + 男装 = 2, + 内衣 = 3, + 美妆 = 4, + 配饰 = 5, + 鞋品 = 6, + 箱包 = 7, + 儿童 = 8, + 母婴 = 9, + 居家 = 10, + 美食 = 11, + 数码 = 12, + 家电 = 13, + 其他 = 14, + 车品 = 15, + 文体 = 16, + 宠物 = 17 + } + + /// <summary> + /// 好单库搜宝贝平台 + /// </summary> + public enum StageType + { + 不限 = -1, + 今日上新 = 0, + 高评分 = 1, + 天猫 = 2, + 视频单 = 3, + 聚划算 = 4, + 淘抢购 = 5, + 营销返利 = 6, + 天猫超市 = 7 + } + + /// <summary> + /// 采集类型 + /// </summary> + public enum GatherType + { + 自定义条件 = 0, + 实时销量榜 = 1, + 今日爆单榜 = 2, + 昨日爆单榜 = 3, + 出单指数榜 = 4, + } + + #endregion + + } +} diff --git a/应用/Weixin.TBCirclePromotion/ImportDataForm.Designer.cs b/应用/Weixin.TBCirclePromotion/ImportDataForm.Designer.cs new file mode 100644 index 0000000..a56a803 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/ImportDataForm.Designer.cs @@ -0,0 +1,126 @@ +namespace Weixin.TBCirclePromotion +{ + partial class ImportDataForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImportDataForm)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label31 = new System.Windows.Forms.Label(); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label1 = new System.Windows.Forms.Label(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.label31); + this.groupBox1.Controls.Add(this.progressBar1); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.richTextBox1); + this.groupBox1.Location = new System.Drawing.Point(28, 28); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(493, 498); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 导入数据 "; + // + // label31 + // + this.label31.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(235)))), ((int)(((byte)(236)))), ((int)(((byte)(239))))); + this.label31.ForeColor = System.Drawing.Color.Blue; + this.label31.Location = new System.Drawing.Point(6, 441); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(353, 18); + this.label31.TabIndex = 24; + this.label31.Text = "状态"; + this.label31.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // progressBar1 + // + this.progressBar1.Location = new System.Drawing.Point(6, 462); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(353, 22); + this.progressBar1.TabIndex = 23; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(374, 441); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(104, 40); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "导 入"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.ForeColor = System.Drawing.Color.Gray; + this.label1.Location = new System.Drawing.Point(73, 29); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(135, 12); + this.label1.TabIndex = 1; + this.label1.Text = "注:一行一个宝贝链接"; + // + // richTextBox1 + // + this.richTextBox1.Location = new System.Drawing.Point(6, 53); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.Size = new System.Drawing.Size(482, 369); + this.richTextBox1.TabIndex = 0; + this.richTextBox1.Text = ""; + // + // ImportDataForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(556, 555); + this.Controls.Add(this.groupBox1); + this.Name = "ImportDataForm"; + this.Text = "导入淘宝数据"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImportDataForm_FormClosing); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.RichTextBox richTextBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.Label label31; + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/ImportDataForm.cs b/应用/Weixin.TBCirclePromotion/ImportDataForm.cs new file mode 100644 index 0000000..71c90eb --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/ImportDataForm.cs @@ -0,0 +1,135 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; +using Weixin.TBCirclePromotion.Entitys; + +namespace Weixin.TBCirclePromotion +{ + public partial class ImportDataForm : BaseForm + { + public ImportDataForm() + { + InitializeComponent(); + } + + private CancellationTokenSource tokenSource = new CancellationTokenSource(); + + private async void simpleButton1_Click(object sender, EventArgs e) + { + + simpleButton1.Enabled = false; + try + { + if (string.IsNullOrWhiteSpace(richTextBox1.Text)) throw new Exception("请填写要导入的内容!"); + + var cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈); + if (cps == null) throw new Exception("没有可用的阿里妈妈推广位!"); + + await Task.Run(() => + { + try + { + var api = CpsClient.CreateAlimamaRequest(cps); + if (api == null) throw new Exception("创建阿里妈妈API请求失败"); + var tbAnalysis = new TBHelper.TbAnalysis(); + + AddJindu("正在分析数据..."); + var goodsinfos = new List<fl_plugin_tbcirclepromotion_goodsinfos>(); + var content = string.Empty; + UpdateUI(() => { content = richTextBox1.Text; }); + + var urls = CsharpHttpHelper.HttpExtend.RegexMatchesUrl(content); + if (urls != null && urls.Count != 0) + { + var session = ApiClient.GetSession(); + AddJindu("准备导入数据", urls.Count); + AnalyzeGoods analyzeGoods = new AnalyzeGoods(); + foreach (var item in urls) + { + var item_id = string.Empty; + try + { + item_id = tbAnalysis.FindItemIdByUrlAndTklAndMkl(item, api, null); + } + catch (Exception) + { } + //标题搜索和商品id搜索 + if (!string.IsNullOrEmpty(item_id)) + { + var goods = analyzeGoods.FindGoodsInfoToGoodsId(item_id); + if (goods != null) + { + goods.state = Enums.StateType.未推广; + goods.goods_source = Enums.GoodsSourceType.文件导入; + goodsinfos.Add(goods); + } + } + AddJindu(); + } + session.Saveable(goodsinfos).ExecuteCommand(); + } + else + { + AddJindu($"导入数据无效,请检测是否为商品链接!"); + return; + } + AddJindu($"成功导入{goodsinfos.Count}条 - 失败{(urls.Count - goodsinfos.Count)}条"); + } + catch (Exception ex) + { + if (!this.IsDisposed) ShowError(ex); + } + }, tokenSource.Token); + } + catch (Exception) + { } + simpleButton1.Enabled = true; + } + + private object lock_obj = new object(); + private void AddJindu(string text = "", int max = 0) + { + base.UpdateUI(() => + { + try + { + lock (lock_obj) + { + if (!string.IsNullOrEmpty(text) && max == 0) + { + label31.Text = text; + } + else if (!string.IsNullOrEmpty(text) && max != 0) + { + label31.Text = text; + this.progressBar1.Value = 0; + this.progressBar1.Maximum = max; + } + else + { + if (this.progressBar1.Value < this.progressBar1.Maximum) this.progressBar1.Value++; + label31.Text = $"{this.progressBar1.Value}/{this.progressBar1.Maximum}"; + } + } + + Application.DoEvents(); + } + catch (Exception) + { } + }); + } + + private void ImportDataForm_FormClosing(object sender, FormClosingEventArgs e) + { + tokenSource.Cancel(); + } + } +} diff --git a/应用/Weixin.TBCirclePromotion/ImportDataForm.resx b/应用/Weixin.TBCirclePromotion/ImportDataForm.resx new file mode 100644 index 0000000..8ddaa51 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/ImportDataForm.resx @@ -0,0 +1,174 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAARdEVYdFRpdGxlAEluYm94O01haWw7oGuCjAAACV5J + REFUWEe1lwlQldcVx7VtalxikraZzKTjFnGNS6xp09S6IoKyC7K5IC64YcAianAJccGYRo2CCAEePJbH + KsoOooiobBI0ooiCSoAHPHYBFXkP/j3nvkVcJp3pTO/M793vfe+79/8/5557+RgA4DW07bsoUx3UBhJv + HY4wzjkiM8G3BPfiOtIEh4lDUuMcfoaf9Q43HqBmCY8V7Y1ab7ypad9GmAxoeZYpoPYbYhBNCPr+Rg6G + LeHBg/lZ+i7GHQg14rGivVHrjTc17VDY4v4GfksMPiA1EmI36r1RUsccwk91B/CgVYJvQgx58FDNswN5 + nFfwIrpUt1/TEo1uzHjlJqedI+cJObXDvIINhYFi+X5cr/0GRbVeKKr5GhUtQdgXaMCDhxO/14zhsQzP + oxWdwde6VhtvK6DGD2nhwb8jBhEc0TvEu8QHewMMhIHCmn3Ir95L7EbeL5641xwAz9P6bOBD4n3N88MI + XhI2rzUkNCrDLKmjVhNrw51WlB9k928TQ3f6zE/w9NeHwG8BvtLABq5V7cKVqp248mgHch964G7jaezw + nYcdPsTJefCg3oN6t+9nJ9FcHAAb4YC02WFN0YT4zUCzhZURVsVVUdZ4JLNGZfhSFAeawGX/53igiBWi + /bn8wB05D/6FS5XbcLHCFXcUvoSP7vdKRQw2es7ENR8jlAWZ4p7ETFAWaFp85ZgBFwZnWJjgj7ceRlo1 + PK05i77umwLV02I8bS9A7jU/7PE1Rf4jL8TdtEHWPRcheKHiS2Td30rftyDz3mZklG9Eyp21iLpuiUv3 + PeD63Rxk5xzHk+YcqDrz0PeE6MpD1wMZ7gSYNJAmZ4OXRHwMehhhib5nJejrSEZvewx626LxvEmGDnko + vve3hizLHWl3NkBGAgk/OyD59hqk3d2A1DJnJJY6IrbEBuFFpkgqXYNTCQ444mOJtqpAPKuXQtUUjt7m + CPS2xqOv8wpun36xXbUG3q6UWqCPombhdI8ZyNj+KdLdZyB523REb5mKVS6TkFvmjZiSZUIorMgEYYXG + xBJIidCCxZAVL0XSdTfYO+shfP1kJGyegiSXqYJElylQNUrR23EZt3yN2MAQgmtBGBh8P8SM0lRELmVI + c5uOS3s/Q/aembhI65i2cwb8t07Blv3zcO3h1wgrUAuGFhghJN8IkjxD0V8od8fq3TPhu2Eikl2nIcN9 + Os5vJ6g/t+kTqBSh6H2cjRsnFr1uoJwKpa8rHypKVRKJZZEok0nZSHf/FOdowu1rx+FUjDOSS9chmESD + 8xYh+JqB4OzPTjggMcc2x7E4Q5GnuE6lQKYh3W0q0uk6Yf0kqBqCaXmzUHJsIRvQHljCwJCyAGNRJKqm + MOE2g1KfLpiGVJqI0xi9YTKWOY5BRrEXIgrNEXhVHz9e0Uc4XctyNsJ65WhErpskxidvmYJkNiL4BHFO + E6CqD6QMZ+L6vxe8ZIA/hpT6LUZv51X00jqdoUlSKQsptG4Cmixp02TEk4GTjuPh4PoZcu/vIwMLEEgG + 0kvdYLV5Mn5YrofYtRNxznkSEp0nI0n0BEUfs2o8lHUBULWkoeDwXDbAh5TOwNBbPoaiQFQNIYhbPQGJ + JKaGJiB40niaPNJxAlxtRuNQwHIk3lqHszed4HF8IVyXjULEynGIp0gT1kzE2TUTiIl0Td/pXhSZU9ae + hrI5CXkHZ7MBPpxeGLjxg4EoEFV9MKJXjEMUoe71BDKaQOagh+iV4xFipwcLyz8j4bInJOlOMLP4CBLb + sWJMpN3HiLQfC5k99XytxfZjKKtP0U44h1yvWa8ZGFZ8VB8qKhBl3Y9QEdwr5WpU8gDq/ZHq+heamLYY + TXhs6SiYOU3EklV6OGo5CmEkEGk3Fhm7ZqOHhJTVvv3wQc8vPlASKkU8cvZ88bqBoiPzycAVSpO/EFPK + KV2cMqbGj3o/VETSGbDsY0SQmMR6NPwtRgkkVqMRYTOGfhsD+YXtOrGeqpM6lFUnqD8BpSIR2bs+ZwP8 + V5OPY2HgnXzvueh9LgftQ/QpG0FPCvqUDejrqQd65HRdi6KjdAYsHU2MQojlaEEoZYC/lwTYAc8rge77 + 6HtOdN+jvpx65i5xB71dJcja/lc2wH8tXxjgAntSJkF7rhvaL7uiLedLtF3aSrigLXsLsRk9zQV49jAS + FTI7Oin/hiiH8VRc45G5cxaqkjbiebUUPYpsNKeuIlaiKWUFmpKXEw5oTLJHY6Id2vO8RY28amB4LFVq + V6m/RnAzWi9uUnNhI1qznNGStR6PCw/STilFR6EnHl91QUf+NnRe90DXDU88KztEv/2E9qtfkSCJJdmR + oC1hg8azy6BgEqzQdnW/WELSfE9rgD+Gx9L+7rzhS0LOaD2/Hi2CdWjOXIvmjDWEE5rTHClLwXRkl1Pv + i87i3egq2YfuikC6V4rOUj80nrOB4twLQUXCUjScsYQi3gL1ceZozdmNCKqVVw28G0Pbq6P4OFoyWJDE + 0lcLwea0VWjidKauQGMKp9OeotiN7pp0+jNbChVlpLs6Fa2XdwjBhjMkGG9JmKMhzowwRX0MY4L6aHqh + veiBcCpg0uS3phcG+KBoLzwi1q8phQT7rV2TNp0cnUintU5MIcQsSMgc9bEkGEtiTIyxEKyLWkwYoU5m + iLrIRWg674Yw2jWvGniPD5m2vIPqYtEJalOpFlRwKgm1oJkQ1IkRdVEaQRkJRhpCToJ1kQaoizCAPHwh + asP10ZS2GVLaMaT5B4JfATUG6BBpzd2niZCiE2unTScJspgQJcFobXT9BVlsEeQsFrGQBPWJBagNI6Tz + ibmoDZ2LxuT1kNLZQZp/7G/gfT4qWy7t0qVTCIroeO0oupfSaaSOTogx+iI6eRgLMfM0gnNQG8LMRo3k + n4KGRCeEmo983QCfZC3ZO3SCuvUTa6deP7WgJjqKTNBPsIYiFGJaweBZguqgfxBfoCbo72g464gQ8xFa + A7oaGC61GlNfHraatpAtPaRe+wYuNE2x1fNSxKm3Un2suuC01V0nMqTNEiFbDDkbJ+QyWhaGaoG57WeB + INMR/FKq24bindDb4CNbOlYbpVShAioUqeaIFT0htRiJUFo/JsSce/5OUEpDtJiNIEZCIvoRkJiqryWm + aoJMRjR6zfnQnjR1L6Xaf0r4Bh+PXJ1/+h/54L/Az3Dk/D7I0b/0zwm74ZtcGP9PWIO1SHPAwP8A2uuS + V5iWFYAAAAAASUVORK5CYII= +</value> + </data> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>51</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/MainForm.Designer.cs b/应用/Weixin.TBCirclePromotion/MainForm.Designer.cs new file mode 100644 index 0000000..67773ed --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/MainForm.Designer.cs @@ -0,0 +1,1591 @@ +namespace Weixin.TBCirclePromotion +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.label2 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有已发ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.panelControl1 = new DevExpress.XtraEditors.PanelControl(); + this.xtraScrollableControl1 = new DevExpress.XtraEditors.XtraScrollableControl(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.dt_AutoClearTaskTimes = new System.Windows.Forms.DateTimePicker(); + this.labelControl30 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl29 = new DevExpress.XtraEditors.LabelControl(); + this.bc_AutoClearTask = new UI.Framework.Controls.ButtonCheck(); + this.panel3 = new System.Windows.Forms.Panel(); + this.me_SingleAdditionalComment = new DevExpress.XtraEditors.MemoEdit(); + this.me_SingleGoodsQRCodePicDesc = new DevExpress.XtraEditors.MemoEdit(); + this.me_SingleContentCircle = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl32 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl31 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl26 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl27 = new DevExpress.XtraEditors.LabelControl(); + this.bc_SingleIsQRCodePic = new UI.Framework.Controls.ButtonCheck(); + this.labelControl25 = new DevExpress.XtraEditors.LabelControl(); + this.bc_SingleIsSynthCoupon = new UI.Framework.Controls.ButtonCheck(); + this.labelControl19 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl34 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl33 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl28 = new DevExpress.XtraEditors.LabelControl(); + this.panel2 = new System.Windows.Forms.Panel(); + this.me_MultiAdditionalComment = new DevExpress.XtraEditors.MemoEdit(); + this.me_MultiGoodsDesc = new DevExpress.XtraEditors.MemoEdit(); + this.me_MultiContentCircle = new DevExpress.XtraEditors.MemoEdit(); + this.labelControl21 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl22 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl36 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl35 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl23 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl24 = new DevExpress.XtraEditors.LabelControl(); + this.nud_SendGoodsImageNum = new System.Windows.Forms.NumericUpDown(); + this.rb_shao = new System.Windows.Forms.RadioButton(); + this.rb_duo = new System.Windows.Forms.RadioButton(); + this.label4 = new System.Windows.Forms.Label(); + this.dt_SendTaskTimes2 = new System.Windows.Forms.DateTimePicker(); + this.dt_SendTaskTimes1 = new System.Windows.Forms.DateTimePicker(); + this.labelControl18 = new DevExpress.XtraEditors.LabelControl(); + this.cb_Model = new System.Windows.Forms.ComboBox(); + this.nud_IntervalCircle = new System.Windows.Forms.NumericUpDown(); + this.labelControl17 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl20 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label3 = new System.Windows.Forms.Label(); + this.nud_Price2 = new System.Windows.Forms.NumericUpDown(); + this.nud_Brokerage = new System.Windows.Forms.NumericUpDown(); + this.nud_Avgmin = new System.Windows.Forms.NumericUpDown(); + this.nud_Sales = new System.Windows.Forms.NumericUpDown(); + this.nud_CouponMoney = new System.Windows.Forms.NumericUpDown(); + this.nud_Rate = new System.Windows.Forms.NumericUpDown(); + this.nud_Price1 = new System.Windows.Forms.NumericUpDown(); + this.labelControl12 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl16 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl14 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl9 = new DevExpress.XtraEditors.LabelControl(); + this.cb_Stage = new System.Windows.Forms.ComboBox(); + this.labelControl8 = new DevExpress.XtraEditors.LabelControl(); + this.cb_Category = new System.Windows.Forms.ComboBox(); + this.labelControl7 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl15 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl11 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl13 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl10 = new DevExpress.XtraEditors.LabelControl(); + this.cb_GatherType = new System.Windows.Forms.ComboBox(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.nud_GatherTouchNum = new System.Windows.Forms.NumericUpDown(); + this.bc_CJSwitch = new UI.Framework.Controls.ButtonCheck(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit(); + this.panelControl1.SuspendLayout(); + this.xtraScrollableControl1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.panel3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.me_SingleAdditionalComment.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_SingleGoodsQRCodePicDesc.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_SingleContentCircle.Properties)).BeginInit(); + this.panel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.me_MultiAdditionalComment.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_MultiGoodsDesc.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_MultiContentCircle.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_SendGoodsImageNum)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_IntervalCircle)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Price2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Brokerage)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Avgmin)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Sales)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_CouponMoney)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Rate)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Price1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_GatherTouchNum)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(955, 539); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage3, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.simpleButton2); + this.xtraTabPage1.Controls.Add(this.label2); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(953, 513); + this.xtraTabPage1.Text = " 数 据 采 集 列 表 "; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(770, 479); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(104, 23); + this.simpleButton2.TabIndex = 15; + this.simpleButton2.Text = "导入数据"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.Transparent; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(321, 187); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(303, 35); + this.label2.TabIndex = 14; + this.label2.Text = "数据采集列表为空"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 477); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(953, 36); + this.pageControl1.TabIndex = 13; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemPictureEdit1}); + this.gridControl1.Size = new System.Drawing.Size(953, 472); + this.gridControl1.TabIndex = 12; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.删除选中项ToolStripMenuItem, + this.删除所有已发ToolStripMenuItem, + this.删除所有数据ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(181, 92); + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有已发ToolStripMenuItem + // + this.删除所有已发ToolStripMenuItem.Name = "删除所有已发ToolStripMenuItem"; + this.删除所有已发ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除所有已发ToolStripMenuItem.Text = "删除所有已发"; + this.删除所有已发ToolStripMenuItem.Click += new System.EventHandler(this.删除所有已发ToolStripMenuItem_Click); + // + // 删除所有数据ToolStripMenuItem + // + this.删除所有数据ToolStripMenuItem.Name = "删除所有数据ToolStripMenuItem"; + this.删除所有数据ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.删除所有数据ToolStripMenuItem.Text = "删除所有数据"; + this.删除所有数据ToolStripMenuItem.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn10, + this.gridColumn1, + this.gridColumn3, + this.gridColumn18, + this.gridColumn5, + this.gridColumn6, + this.gridColumn2, + this.gridColumn7, + this.gridColumn8, + this.gridColumn9}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "商品ID"; + this.gridColumn10.FieldName = "goods_id"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 1; + this.gridColumn10.Width = 86; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "goods_name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 2; + this.gridColumn1.Width = 162; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "商品单价"; + this.gridColumn3.FieldName = "normal_price"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 3; + this.gridColumn3.Width = 68; + // + // gridColumn18 + // + this.gridColumn18.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn18.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn18.Caption = "优惠券金额"; + this.gridColumn18.FieldName = "coupon_discount"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 4; + this.gridColumn18.Width = 89; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "优惠券数量"; + this.gridColumn5.FieldName = "coupon_remain_quantity"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 5; + this.gridColumn5.Width = 73; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "佣金比例"; + this.gridColumn6.FieldName = "promotion_rate"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 6; + this.gridColumn6.Width = 66; + // + // gridColumn2 + // + this.gridColumn2.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn2.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn2.Caption = "月销量"; + this.gridColumn2.FieldName = "sold_quantity"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 10; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "发送状态"; + this.gridColumn7.FieldName = "state"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 7; + this.gridColumn7.Width = 63; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "采集日期"; + this.gridColumn8.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn8.FieldName = "cur_time"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 8; + this.gridColumn8.Width = 100; + // + // gridColumn9 + // + this.gridColumn9.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn9.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn9.Caption = "数据来源"; + this.gridColumn9.FieldName = "goods_source"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.OptionsColumn.AllowEdit = false; + this.gridColumn9.OptionsColumn.AllowFocus = false; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 9; + this.gridColumn9.Width = 83; + // + // repositoryItemPictureEdit1 + // + this.repositoryItemPictureEdit1.Name = "repositoryItemPictureEdit1"; + this.repositoryItemPictureEdit1.SizeMode = DevExpress.XtraEditors.Controls.PictureSizeMode.Stretch; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.simpleButton1); + this.xtraTabPage3.Controls.Add(this.label1); + this.xtraTabPage3.Controls.Add(this.pageControl2); + this.xtraTabPage3.Controls.Add(this.gridControl2); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(953, 513); + this.xtraTabPage3.Text = " 设 置 推 广 位 "; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(741, 477); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(194, 29); + this.simpleButton1.TabIndex = 3; + this.simpleButton1.Text = "检测淘宝返利推广位重复项"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(201, 183); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 14; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 477); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(953, 36); + this.pageControl2.TabIndex = 9; + // + // gridControl2 + // + this.gridControl2.Dock = System.Windows.Forms.DockStyle.Top; + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(953, 471); + this.gridControl2.TabIndex = 8; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn17}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "ID"; + this.gridColumn11.FieldName = "ID"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + this.gridColumn11.Width = 50; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "平台类型"; + this.gridColumn12.FieldName = "chattype"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + this.gridColumn12.Width = 99; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "账号"; + this.gridColumn13.FieldName = "name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 2; + this.gridColumn13.Width = 148; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "账号昵称"; + this.gridColumn14.FieldName = "nick"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + this.gridColumn14.Width = 125; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn15.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn15.AppearanceCell.Options.UseFont = true; + this.gridColumn15.AppearanceCell.Options.UseForeColor = true; + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "推广位"; + this.gridColumn15.FieldName = "adzone_name"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 4; + this.gridColumn15.Width = 149; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "禁止使用"; + this.gridColumn17.FieldName = "onoff"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + this.gridColumn17.Width = 66; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.panelControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(953, 513); + this.xtraTabPage2.Text = " 应 用 设 置 "; + // + // panelControl1 + // + this.panelControl1.Controls.Add(this.xtraScrollableControl1); + this.panelControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panelControl1.Location = new System.Drawing.Point(0, 0); + this.panelControl1.Name = "panelControl1"; + this.panelControl1.Size = new System.Drawing.Size(953, 513); + this.panelControl1.TabIndex = 0; + // + // xtraScrollableControl1 + // + this.xtraScrollableControl1.Controls.Add(this.groupBox2); + this.xtraScrollableControl1.Controls.Add(this.groupBox1); + this.xtraScrollableControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraScrollableControl1.Location = new System.Drawing.Point(2, 2); + this.xtraScrollableControl1.Name = "xtraScrollableControl1"; + this.xtraScrollableControl1.Size = new System.Drawing.Size(949, 509); + this.xtraScrollableControl1.TabIndex = 0; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.groupBox3); + this.groupBox2.Controls.Add(this.label4); + this.groupBox2.Controls.Add(this.dt_SendTaskTimes2); + this.groupBox2.Controls.Add(this.dt_SendTaskTimes1); + this.groupBox2.Controls.Add(this.labelControl18); + this.groupBox2.Controls.Add(this.cb_Model); + this.groupBox2.Controls.Add(this.nud_IntervalCircle); + this.groupBox2.Controls.Add(this.labelControl17); + this.groupBox2.Controls.Add(this.labelControl20); + this.groupBox2.Location = new System.Drawing.Point(28, 290); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(889, 609); + this.groupBox2.TabIndex = 42; + this.groupBox2.TabStop = false; + this.groupBox2.Text = " 朋 友 圈 基 础 设 置 "; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.groupBox4); + this.groupBox3.Controls.Add(this.panel3); + this.groupBox3.Controls.Add(this.panel2); + this.groupBox3.Controls.Add(this.rb_shao); + this.groupBox3.Controls.Add(this.rb_duo); + this.groupBox3.Location = new System.Drawing.Point(6, 64); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(877, 536); + this.groupBox3.TabIndex = 68; + this.groupBox3.TabStop = false; + this.groupBox3.Text = " 发 单 方 式 "; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.dt_AutoClearTaskTimes); + this.groupBox4.Controls.Add(this.labelControl30); + this.groupBox4.Controls.Add(this.labelControl29); + this.groupBox4.Controls.Add(this.bc_AutoClearTask); + this.groupBox4.Location = new System.Drawing.Point(27, 446); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(812, 74); + this.groupBox4.TabIndex = 69; + this.groupBox4.TabStop = false; + this.groupBox4.Text = " 清 理 设 置 "; + // + // dt_AutoClearTaskTimes + // + this.dt_AutoClearTaskTimes.CustomFormat = "HH:mm"; + this.dt_AutoClearTaskTimes.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dt_AutoClearTaskTimes.Location = new System.Drawing.Point(518, 31); + this.dt_AutoClearTaskTimes.Name = "dt_AutoClearTaskTimes"; + this.dt_AutoClearTaskTimes.ShowUpDown = true; + this.dt_AutoClearTaskTimes.Size = new System.Drawing.Size(74, 22); + this.dt_AutoClearTaskTimes.TabIndex = 44; + this.dt_AutoClearTaskTimes.Value = new System.DateTime(2020, 9, 14, 9, 0, 0, 0); + // + // labelControl30 + // + this.labelControl30.Location = new System.Drawing.Point(427, 35); + this.labelControl30.Name = "labelControl30"; + this.labelControl30.Size = new System.Drawing.Size(84, 14); + this.labelControl30.TabIndex = 43; + this.labelControl30.Text = "定时清理时间:"; + // + // labelControl29 + // + this.labelControl29.Location = new System.Drawing.Point(150, 35); + this.labelControl29.Name = "labelControl29"; + this.labelControl29.Size = new System.Drawing.Size(60, 14); + this.labelControl29.TabIndex = 36; + this.labelControl29.Text = "定时清理:"; + // + // bc_AutoClearTask + // + this.bc_AutoClearTask.BackColor = System.Drawing.Color.Transparent; + this.bc_AutoClearTask.Checked = false; + this.bc_AutoClearTask.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.bc_AutoClearTask.Cursor = System.Windows.Forms.Cursors.Hand; + this.bc_AutoClearTask.Location = new System.Drawing.Point(216, 31); + this.bc_AutoClearTask.Name = "bc_AutoClearTask"; + this.bc_AutoClearTask.Size = new System.Drawing.Size(59, 22); + this.bc_AutoClearTask.TabIndex = 37; + // + // panel3 + // + this.panel3.Controls.Add(this.me_SingleAdditionalComment); + this.panel3.Controls.Add(this.me_SingleGoodsQRCodePicDesc); + this.panel3.Controls.Add(this.me_SingleContentCircle); + this.panel3.Controls.Add(this.labelControl32); + this.panel3.Controls.Add(this.labelControl31); + this.panel3.Controls.Add(this.labelControl26); + this.panel3.Controls.Add(this.labelControl27); + this.panel3.Controls.Add(this.bc_SingleIsQRCodePic); + this.panel3.Controls.Add(this.labelControl25); + this.panel3.Controls.Add(this.bc_SingleIsSynthCoupon); + this.panel3.Controls.Add(this.labelControl19); + this.panel3.Controls.Add(this.labelControl34); + this.panel3.Controls.Add(this.labelControl33); + this.panel3.Controls.Add(this.labelControl28); + this.panel3.Enabled = false; + this.panel3.Location = new System.Drawing.Point(451, 66); + this.panel3.Name = "panel3"; + this.panel3.Size = new System.Drawing.Size(420, 359); + this.panel3.TabIndex = 68; + // + // me_SingleAdditionalComment + // + this.me_SingleAdditionalComment.Location = new System.Drawing.Point(10, 220); + this.me_SingleAdditionalComment.Name = "me_SingleAdditionalComment"; + this.me_SingleAdditionalComment.Size = new System.Drawing.Size(399, 60); + this.me_SingleAdditionalComment.TabIndex = 59; + // + // me_SingleGoodsQRCodePicDesc + // + this.me_SingleGoodsQRCodePicDesc.Location = new System.Drawing.Point(10, 303); + this.me_SingleGoodsQRCodePicDesc.Name = "me_SingleGoodsQRCodePicDesc"; + this.me_SingleGoodsQRCodePicDesc.Size = new System.Drawing.Size(399, 49); + this.me_SingleGoodsQRCodePicDesc.TabIndex = 59; + // + // me_SingleContentCircle + // + this.me_SingleContentCircle.Location = new System.Drawing.Point(10, 92); + this.me_SingleContentCircle.Name = "me_SingleContentCircle"; + this.me_SingleContentCircle.Size = new System.Drawing.Size(399, 85); + this.me_SingleContentCircle.TabIndex = 59; + // + // labelControl32 + // + this.labelControl32.Location = new System.Drawing.Point(10, 76); + this.labelControl32.Name = "labelControl32"; + this.labelControl32.Size = new System.Drawing.Size(384, 14); + this.labelControl32.TabIndex = 38; + this.labelControl32.Text = "[券后价]、[商品描述]、[已售数量]、[店铺名称]、[购买地址]、[淘口令]"; + this.labelControl32.Click += new System.EventHandler(this.labelControl31_Click); + // + // labelControl31 + // + this.labelControl31.Location = new System.Drawing.Point(132, 55); + this.labelControl31.Name = "labelControl31"; + this.labelControl31.Size = new System.Drawing.Size(282, 14); + this.labelControl31.TabIndex = 38; + this.labelControl31.Text = "支持变量:[商品标题]、[商品单价]、[优惠券金额]、"; + this.labelControl31.Click += new System.EventHandler(this.labelControl31_Click); + // + // labelControl26 + // + this.labelControl26.Location = new System.Drawing.Point(10, 54); + this.labelControl26.Name = "labelControl26"; + this.labelControl26.Size = new System.Drawing.Size(96, 14); + this.labelControl26.TabIndex = 38; + this.labelControl26.Text = "朋友圈正文内容:"; + // + // labelControl27 + // + this.labelControl27.Location = new System.Drawing.Point(10, 283); + this.labelControl27.Name = "labelControl27"; + this.labelControl27.Size = new System.Drawing.Size(132, 14); + this.labelControl27.TabIndex = 38; + this.labelControl27.Text = "二维码图片底栏描述语:"; + // + // bc_SingleIsQRCodePic + // + this.bc_SingleIsQRCodePic.BackColor = System.Drawing.Color.Transparent; + this.bc_SingleIsQRCodePic.Checked = false; + this.bc_SingleIsQRCodePic.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.bc_SingleIsQRCodePic.Cursor = System.Windows.Forms.Cursors.Hand; + this.bc_SingleIsQRCodePic.Location = new System.Drawing.Point(255, 18); + this.bc_SingleIsQRCodePic.Name = "bc_SingleIsQRCodePic"; + this.bc_SingleIsQRCodePic.Size = new System.Drawing.Size(59, 22); + this.bc_SingleIsQRCodePic.TabIndex = 37; + // + // labelControl25 + // + this.labelControl25.Location = new System.Drawing.Point(181, 22); + this.labelControl25.Name = "labelControl25"; + this.labelControl25.Size = new System.Drawing.Size(72, 14); + this.labelControl25.TabIndex = 36; + this.labelControl25.Text = "合成二维码:"; + // + // bc_SingleIsSynthCoupon + // + this.bc_SingleIsSynthCoupon.BackColor = System.Drawing.Color.Transparent; + this.bc_SingleIsSynthCoupon.Checked = false; + this.bc_SingleIsSynthCoupon.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.bc_SingleIsSynthCoupon.Cursor = System.Windows.Forms.Cursors.Hand; + this.bc_SingleIsSynthCoupon.Location = new System.Drawing.Point(105, 18); + this.bc_SingleIsSynthCoupon.Name = "bc_SingleIsSynthCoupon"; + this.bc_SingleIsSynthCoupon.Size = new System.Drawing.Size(59, 22); + this.bc_SingleIsSynthCoupon.TabIndex = 37; + // + // labelControl19 + // + this.labelControl19.Location = new System.Drawing.Point(31, 22); + this.labelControl19.Name = "labelControl19"; + this.labelControl19.Size = new System.Drawing.Size(72, 14); + this.labelControl19.TabIndex = 36; + this.labelControl19.Text = "合成优惠券:"; + // + // labelControl34 + // + this.labelControl34.Location = new System.Drawing.Point(10, 200); + this.labelControl34.Name = "labelControl34"; + this.labelControl34.Size = new System.Drawing.Size(408, 14); + this.labelControl34.TabIndex = 38; + this.labelControl34.Text = "[优惠券金额]、[优惠券数量]、[商品单价]、[券后价]、[购买地址]、[淘口令]"; + // + // labelControl33 + // + this.labelControl33.Location = new System.Drawing.Point(132, 183); + this.labelControl33.Name = "labelControl33"; + this.labelControl33.Size = new System.Drawing.Size(270, 14); + this.labelControl33.TabIndex = 38; + this.labelControl33.Text = "支持变量:[商品标题]、[已售数量]、[店铺名称]、"; + // + // labelControl28 + // + this.labelControl28.Location = new System.Drawing.Point(10, 183); + this.labelControl28.Name = "labelControl28"; + this.labelControl28.Size = new System.Drawing.Size(96, 14); + this.labelControl28.TabIndex = 38; + this.labelControl28.Text = "朋友圈追加评语:"; + // + // panel2 + // + this.panel2.Controls.Add(this.me_MultiAdditionalComment); + this.panel2.Controls.Add(this.me_MultiGoodsDesc); + this.panel2.Controls.Add(this.me_MultiContentCircle); + this.panel2.Controls.Add(this.labelControl21); + this.panel2.Controls.Add(this.labelControl22); + this.panel2.Controls.Add(this.labelControl36); + this.panel2.Controls.Add(this.labelControl35); + this.panel2.Controls.Add(this.labelControl23); + this.panel2.Controls.Add(this.labelControl24); + this.panel2.Controls.Add(this.nud_SendGoodsImageNum); + this.panel2.Location = new System.Drawing.Point(20, 66); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(420, 359); + this.panel2.TabIndex = 68; + // + // me_MultiAdditionalComment + // + this.me_MultiAdditionalComment.Location = new System.Drawing.Point(10, 199); + this.me_MultiAdditionalComment.Name = "me_MultiAdditionalComment"; + this.me_MultiAdditionalComment.Size = new System.Drawing.Size(399, 60); + this.me_MultiAdditionalComment.TabIndex = 59; + // + // me_MultiGoodsDesc + // + this.me_MultiGoodsDesc.Location = new System.Drawing.Point(10, 303); + this.me_MultiGoodsDesc.Name = "me_MultiGoodsDesc"; + this.me_MultiGoodsDesc.Size = new System.Drawing.Size(399, 49); + this.me_MultiGoodsDesc.TabIndex = 59; + // + // me_MultiContentCircle + // + this.me_MultiContentCircle.Location = new System.Drawing.Point(10, 74); + this.me_MultiContentCircle.Name = "me_MultiContentCircle"; + this.me_MultiContentCircle.Size = new System.Drawing.Size(399, 103); + this.me_MultiContentCircle.TabIndex = 59; + // + // labelControl21 + // + this.labelControl21.Location = new System.Drawing.Point(23, 24); + this.labelControl21.Name = "labelControl21"; + this.labelControl21.Size = new System.Drawing.Size(84, 14); + this.labelControl21.TabIndex = 47; + this.labelControl21.Text = "发送推广图片:"; + // + // labelControl22 + // + this.labelControl22.Location = new System.Drawing.Point(10, 54); + this.labelControl22.Name = "labelControl22"; + this.labelControl22.Size = new System.Drawing.Size(96, 14); + this.labelControl22.TabIndex = 38; + this.labelControl22.Text = "朋友圈正文内容:"; + // + // labelControl36 + // + this.labelControl36.Location = new System.Drawing.Point(11, 285); + this.labelControl36.Name = "labelControl36"; + this.labelControl36.Size = new System.Drawing.Size(350, 14); + this.labelControl36.TabIndex = 38; + this.labelControl36.Text = "[优惠券金额]、[优惠券数量]、[商品单价]、[券后价]、[购买地址]"; + // + // labelControl35 + // + this.labelControl35.Location = new System.Drawing.Point(78, 266); + this.labelControl35.Name = "labelControl35"; + this.labelControl35.Size = new System.Drawing.Size(340, 14); + this.labelControl35.TabIndex = 38; + this.labelControl35.Text = "支持变量:[商品标题]、[商品描述]、[已售数量]、[店铺名称]、"; + // + // labelControl23 + // + this.labelControl23.Location = new System.Drawing.Point(8, 266); + this.labelControl23.Name = "labelControl23"; + this.labelControl23.Size = new System.Drawing.Size(72, 14); + this.labelControl23.TabIndex = 38; + this.labelControl23.Text = "宝贝描述语:"; + // + // labelControl24 + // + this.labelControl24.Location = new System.Drawing.Point(10, 179); + this.labelControl24.Name = "labelControl24"; + this.labelControl24.Size = new System.Drawing.Size(96, 14); + this.labelControl24.TabIndex = 38; + this.labelControl24.Text = "朋友圈追加评语:"; + // + // nud_SendGoodsImageNum + // + this.nud_SendGoodsImageNum.Location = new System.Drawing.Point(110, 20); + this.nud_SendGoodsImageNum.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_SendGoodsImageNum.Name = "nud_SendGoodsImageNum"; + this.nud_SendGoodsImageNum.Size = new System.Drawing.Size(70, 22); + this.nud_SendGoodsImageNum.TabIndex = 58; + this.nud_SendGoodsImageNum.Value = new decimal(new int[] { + 9, + 0, + 0, + 0}); + // + // rb_shao + // + this.rb_shao.AutoSize = true; + this.rb_shao.Location = new System.Drawing.Point(476, 34); + this.rb_shao.Name = "rb_shao"; + this.rb_shao.Size = new System.Drawing.Size(61, 18); + this.rb_shao.TabIndex = 67; + this.rb_shao.Text = "单产品"; + this.rb_shao.UseVisualStyleBackColor = true; + this.rb_shao.CheckedChanged += new System.EventHandler(this.rb_shao_CheckedChanged); + // + // rb_duo + // + this.rb_duo.AutoSize = true; + this.rb_duo.Checked = true; + this.rb_duo.Location = new System.Drawing.Point(62, 34); + this.rb_duo.Name = "rb_duo"; + this.rb_duo.Size = new System.Drawing.Size(61, 18); + this.rb_duo.TabIndex = 67; + this.rb_duo.TabStop = true; + this.rb_duo.Text = "多产品"; + this.rb_duo.UseVisualStyleBackColor = true; + this.rb_duo.CheckedChanged += new System.EventHandler(this.rb_duo_CheckedChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(523, 35); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(11, 14); + this.label4.TabIndex = 65; + this.label4.Text = "-"; + // + // dt_SendTaskTimes2 + // + this.dt_SendTaskTimes2.CustomFormat = "HH:mm"; + this.dt_SendTaskTimes2.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dt_SendTaskTimes2.Location = new System.Drawing.Point(540, 31); + this.dt_SendTaskTimes2.Name = "dt_SendTaskTimes2"; + this.dt_SendTaskTimes2.ShowUpDown = true; + this.dt_SendTaskTimes2.Size = new System.Drawing.Size(74, 22); + this.dt_SendTaskTimes2.TabIndex = 42; + this.dt_SendTaskTimes2.Value = new System.DateTime(2020, 9, 14, 22, 0, 0, 0); + // + // dt_SendTaskTimes1 + // + this.dt_SendTaskTimes1.CustomFormat = "HH:mm"; + this.dt_SendTaskTimes1.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dt_SendTaskTimes1.Location = new System.Drawing.Point(443, 31); + this.dt_SendTaskTimes1.Name = "dt_SendTaskTimes1"; + this.dt_SendTaskTimes1.ShowUpDown = true; + this.dt_SendTaskTimes1.Size = new System.Drawing.Size(74, 22); + this.dt_SendTaskTimes1.TabIndex = 42; + this.dt_SendTaskTimes1.Value = new System.DateTime(2020, 9, 14, 9, 0, 0, 0); + // + // labelControl18 + // + this.labelControl18.Location = new System.Drawing.Point(341, 35); + this.labelControl18.Name = "labelControl18"; + this.labelControl18.Size = new System.Drawing.Size(96, 14); + this.labelControl18.TabIndex = 38; + this.labelControl18.Text = "发送任务时间段:"; + // + // cb_Model + // + this.cb_Model.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cb_Model.FormattingEnabled = true; + this.cb_Model.Items.AddRange(new object[] { + "模板A", + "模板B", + "模板C"}); + this.cb_Model.Location = new System.Drawing.Point(181, 31); + this.cb_Model.Name = "cb_Model"; + this.cb_Model.Size = new System.Drawing.Size(99, 22); + this.cb_Model.TabIndex = 41; + this.cb_Model.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // nud_IntervalCircle + // + this.nud_IntervalCircle.Location = new System.Drawing.Point(759, 31); + this.nud_IntervalCircle.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_IntervalCircle.Name = "nud_IntervalCircle"; + this.nud_IntervalCircle.Size = new System.Drawing.Size(70, 22); + this.nud_IntervalCircle.TabIndex = 58; + this.nud_IntervalCircle.Value = new decimal(new int[] { + 120, + 0, + 0, + 0}); + // + // labelControl17 + // + this.labelControl17.Location = new System.Drawing.Point(83, 35); + this.labelControl17.Name = "labelControl17"; + this.labelControl17.Size = new System.Drawing.Size(96, 14); + this.labelControl17.TabIndex = 38; + this.labelControl17.Text = "发单二维码模板:"; + // + // labelControl20 + // + this.labelControl20.Location = new System.Drawing.Point(693, 35); + this.labelControl20.Name = "labelControl20"; + this.labelControl20.Size = new System.Drawing.Size(60, 14); + this.labelControl20.TabIndex = 47; + this.labelControl20.Text = "发送间隔:"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.panel1); + this.groupBox1.Controls.Add(this.cb_GatherType); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.nud_GatherTouchNum); + this.groupBox1.Controls.Add(this.bc_CJSwitch); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Location = new System.Drawing.Point(28, 19); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(889, 254); + this.groupBox1.TabIndex = 41; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 采 集 设 置 "; + // + // panel1 + // + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.nud_Price2); + this.panel1.Controls.Add(this.nud_Brokerage); + this.panel1.Controls.Add(this.nud_Avgmin); + this.panel1.Controls.Add(this.nud_Sales); + this.panel1.Controls.Add(this.nud_CouponMoney); + this.panel1.Controls.Add(this.nud_Rate); + this.panel1.Controls.Add(this.nud_Price1); + this.panel1.Controls.Add(this.labelControl12); + this.panel1.Controls.Add(this.labelControl16); + this.panel1.Controls.Add(this.labelControl14); + this.panel1.Controls.Add(this.labelControl9); + this.panel1.Controls.Add(this.cb_Stage); + this.panel1.Controls.Add(this.labelControl8); + this.panel1.Controls.Add(this.cb_Category); + this.panel1.Controls.Add(this.labelControl7); + this.panel1.Controls.Add(this.labelControl6); + this.panel1.Controls.Add(this.labelControl2); + this.panel1.Controls.Add(this.labelControl15); + this.panel1.Controls.Add(this.labelControl11); + this.panel1.Controls.Add(this.labelControl13); + this.panel1.Controls.Add(this.labelControl10); + this.panel1.Location = new System.Drawing.Point(95, 110); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(734, 121); + this.panel1.TabIndex = 44; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(155, 56); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(11, 14); + this.label3.TabIndex = 65; + this.label3.Text = "-"; + // + // nud_Price2 + // + this.nud_Price2.DecimalPlaces = 2; + this.nud_Price2.Location = new System.Drawing.Point(169, 52); + this.nud_Price2.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_Price2.Name = "nud_Price2"; + this.nud_Price2.Size = new System.Drawing.Size(70, 22); + this.nud_Price2.TabIndex = 64; + // + // nud_Brokerage + // + this.nud_Brokerage.DecimalPlaces = 2; + this.nud_Brokerage.Location = new System.Drawing.Point(581, 52); + this.nud_Brokerage.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_Brokerage.Name = "nud_Brokerage"; + this.nud_Brokerage.Size = new System.Drawing.Size(70, 22); + this.nud_Brokerage.TabIndex = 63; + // + // nud_Avgmin + // + this.nud_Avgmin.DecimalPlaces = 2; + this.nud_Avgmin.Location = new System.Drawing.Point(581, 84); + this.nud_Avgmin.Maximum = new decimal(new int[] { + 5, + 0, + 0, + 0}); + this.nud_Avgmin.Name = "nud_Avgmin"; + this.nud_Avgmin.Size = new System.Drawing.Size(70, 22); + this.nud_Avgmin.TabIndex = 62; + // + // nud_Sales + // + this.nud_Sales.Location = new System.Drawing.Point(362, 84); + this.nud_Sales.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_Sales.Name = "nud_Sales"; + this.nud_Sales.Size = new System.Drawing.Size(70, 22); + this.nud_Sales.TabIndex = 61; + // + // nud_CouponMoney + // + this.nud_CouponMoney.DecimalPlaces = 2; + this.nud_CouponMoney.Location = new System.Drawing.Point(81, 84); + this.nud_CouponMoney.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_CouponMoney.Name = "nud_CouponMoney"; + this.nud_CouponMoney.Size = new System.Drawing.Size(70, 22); + this.nud_CouponMoney.TabIndex = 60; + // + // nud_Rate + // + this.nud_Rate.DecimalPlaces = 2; + this.nud_Rate.Location = new System.Drawing.Point(363, 52); + this.nud_Rate.Name = "nud_Rate"; + this.nud_Rate.Size = new System.Drawing.Size(70, 22); + this.nud_Rate.TabIndex = 59; + // + // nud_Price1 + // + this.nud_Price1.DecimalPlaces = 2; + this.nud_Price1.Location = new System.Drawing.Point(82, 52); + this.nud_Price1.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.nud_Price1.Name = "nud_Price1"; + this.nud_Price1.Size = new System.Drawing.Size(70, 22); + this.nud_Price1.TabIndex = 58; + // + // labelControl12 + // + this.labelControl12.Location = new System.Drawing.Point(539, 56); + this.labelControl12.Name = "labelControl12"; + this.labelControl12.Size = new System.Drawing.Size(36, 14); + this.labelControl12.TabIndex = 50; + this.labelControl12.Text = "佣金:"; + // + // labelControl16 + // + this.labelControl16.Location = new System.Drawing.Point(515, 88); + this.labelControl16.Name = "labelControl16"; + this.labelControl16.Size = new System.Drawing.Size(60, 14); + this.labelControl16.TabIndex = 51; + this.labelControl16.Text = "单品评分:"; + // + // labelControl14 + // + this.labelControl14.Location = new System.Drawing.Point(308, 88); + this.labelControl14.Name = "labelControl14"; + this.labelControl14.Size = new System.Drawing.Size(48, 14); + this.labelControl14.TabIndex = 44; + this.labelControl14.Text = "月销量:"; + // + // labelControl9 + // + this.labelControl9.Location = new System.Drawing.Point(27, 88); + this.labelControl9.Name = "labelControl9"; + this.labelControl9.Size = new System.Drawing.Size(48, 14); + this.labelControl9.TabIndex = 49; + this.labelControl9.Text = "券面额:"; + // + // cb_Stage + // + this.cb_Stage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cb_Stage.FormattingEnabled = true; + this.cb_Stage.Items.AddRange(new object[] { + "不限", + "今日上新", + "高评分", + "天猫", + "视频单", + "聚划算", + "淘抢购", + "营销返利", + "天猫超市"}); + this.cb_Stage.Location = new System.Drawing.Point(362, 14); + this.cb_Stage.Name = "cb_Stage"; + this.cb_Stage.Size = new System.Drawing.Size(102, 22); + this.cb_Stage.TabIndex = 56; + // + // labelControl8 + // + this.labelControl8.Location = new System.Drawing.Point(297, 56); + this.labelControl8.Name = "labelControl8"; + this.labelControl8.Size = new System.Drawing.Size(60, 14); + this.labelControl8.TabIndex = 48; + this.labelControl8.Text = "佣金比例:"; + // + // cb_Category + // + this.cb_Category.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cb_Category.FormattingEnabled = true; + this.cb_Category.Items.AddRange(new object[] { + "全部", + "女装", + "男装", + "内衣", + "美妆", + "配饰", + "鞋品", + "箱包", + "儿童", + "母婴", + "居家", + "美食", + "数码", + "家电", + "其他", + "车品", + "文体", + "宠物"}); + this.cb_Category.Location = new System.Drawing.Point(81, 14); + this.cb_Category.Name = "cb_Category"; + this.cb_Category.Size = new System.Drawing.Size(102, 22); + this.cb_Category.TabIndex = 57; + // + // labelControl7 + // + this.labelControl7.Location = new System.Drawing.Point(16, 56); + this.labelControl7.Name = "labelControl7"; + this.labelControl7.Size = new System.Drawing.Size(60, 14); + this.labelControl7.TabIndex = 47; + this.labelControl7.Text = "商品售价:"; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(309, 18); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(48, 14); + this.labelControl6.TabIndex = 46; + this.labelControl6.Text = "采集源:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(40, 18); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(36, 14); + this.labelControl2.TabIndex = 45; + this.labelControl2.Text = "类目:"; + // + // labelControl15 + // + this.labelControl15.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl15.Appearance.Options.UseForeColor = true; + this.labelControl15.Location = new System.Drawing.Point(657, 88); + this.labelControl15.Name = "labelControl15"; + this.labelControl15.Size = new System.Drawing.Size(24, 14); + this.labelControl15.TabIndex = 53; + this.labelControl15.Text = "以上"; + // + // labelControl11 + // + this.labelControl11.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl11.Appearance.Options.UseForeColor = true; + this.labelControl11.Location = new System.Drawing.Point(657, 56); + this.labelControl11.Name = "labelControl11"; + this.labelControl11.Size = new System.Drawing.Size(24, 14); + this.labelControl11.TabIndex = 52; + this.labelControl11.Text = "以上"; + // + // labelControl13 + // + this.labelControl13.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl13.Appearance.Options.UseForeColor = true; + this.labelControl13.Location = new System.Drawing.Point(438, 88); + this.labelControl13.Name = "labelControl13"; + this.labelControl13.Size = new System.Drawing.Size(24, 14); + this.labelControl13.TabIndex = 55; + this.labelControl13.Text = "以上"; + // + // labelControl10 + // + this.labelControl10.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl10.Appearance.Options.UseForeColor = true; + this.labelControl10.Location = new System.Drawing.Point(157, 88); + this.labelControl10.Name = "labelControl10"; + this.labelControl10.Size = new System.Drawing.Size(24, 14); + this.labelControl10.TabIndex = 54; + this.labelControl10.Text = "以上"; + // + // cb_GatherType + // + this.cb_GatherType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cb_GatherType.FormattingEnabled = true; + this.cb_GatherType.Items.AddRange(new object[] { + "自定义条件", + "实时销量榜", + "今日爆单榜", + "昨日爆单榜", + "出单指数榜"}); + this.cb_GatherType.Location = new System.Drawing.Point(176, 74); + this.cb_GatherType.Name = "cb_GatherType"; + this.cb_GatherType.Size = new System.Drawing.Size(99, 22); + this.cb_GatherType.TabIndex = 41; + this.cb_GatherType.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(111, 77); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 38; + this.labelControl1.Text = "采集导航:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(367, 33); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(84, 14); + this.labelControl4.TabIndex = 38; + this.labelControl4.Text = "采集触发数量:"; + // + // nud_GatherTouchNum + // + this.nud_GatherTouchNum.Location = new System.Drawing.Point(459, 29); + this.nud_GatherTouchNum.Maximum = new decimal(new int[] { + 99999, + 0, + 0, + 0}); + this.nud_GatherTouchNum.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nud_GatherTouchNum.Name = "nud_GatherTouchNum"; + this.nud_GatherTouchNum.Size = new System.Drawing.Size(94, 22); + this.nud_GatherTouchNum.TabIndex = 39; + this.nud_GatherTouchNum.Value = new decimal(new int[] { + 10, + 0, + 0, + 0}); + // + // bc_CJSwitch + // + this.bc_CJSwitch.BackColor = System.Drawing.Color.Transparent; + this.bc_CJSwitch.Checked = false; + this.bc_CJSwitch.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.bc_CJSwitch.Cursor = System.Windows.Forms.Cursors.Hand; + this.bc_CJSwitch.Location = new System.Drawing.Point(187, 29); + this.bc_CJSwitch.Name = "bc_CJSwitch"; + this.bc_CJSwitch.Size = new System.Drawing.Size(59, 22); + this.bc_CJSwitch.TabIndex = 37; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(95, 33); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(84, 14); + this.labelControl3.TabIndex = 36; + this.labelControl3.Text = "商品采集开关:"; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Gray; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(562, 33); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(12, 14); + this.labelControl5.TabIndex = 40; + this.labelControl5.Text = "个"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(955, 539); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraTabPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit(); + this.panelControl1.ResumeLayout(false); + this.xtraScrollableControl1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + this.panel3.ResumeLayout(false); + this.panel3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.me_SingleAdditionalComment.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_SingleGoodsQRCodePicDesc.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_SingleContentCircle.Properties)).EndInit(); + this.panel2.ResumeLayout(false); + this.panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.me_MultiAdditionalComment.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_MultiGoodsDesc.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.me_MultiContentCircle.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_SendGoodsImageNum)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_IntervalCircle)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Price2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Brokerage)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Avgmin)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Sales)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_CouponMoney)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Rate)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_Price1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nud_GatherTouchNum)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit1; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有已发ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有数据ToolStripMenuItem; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.PanelControl panelControl1; + private DevExpress.XtraEditors.XtraScrollableControl xtraScrollableControl1; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private System.Windows.Forms.NumericUpDown nud_GatherTouchNum; + private UI.Framework.Controls.ButtonCheck bc_CJSwitch; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl5; + private System.Windows.Forms.ComboBox cb_GatherType; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.NumericUpDown nud_Price2; + private System.Windows.Forms.NumericUpDown nud_Brokerage; + private System.Windows.Forms.NumericUpDown nud_Avgmin; + private System.Windows.Forms.NumericUpDown nud_Sales; + private System.Windows.Forms.NumericUpDown nud_CouponMoney; + private System.Windows.Forms.NumericUpDown nud_Rate; + private System.Windows.Forms.NumericUpDown nud_Price1; + private DevExpress.XtraEditors.LabelControl labelControl12; + private DevExpress.XtraEditors.LabelControl labelControl16; + private DevExpress.XtraEditors.LabelControl labelControl14; + private DevExpress.XtraEditors.LabelControl labelControl9; + private System.Windows.Forms.ComboBox cb_Stage; + private DevExpress.XtraEditors.LabelControl labelControl8; + private System.Windows.Forms.ComboBox cb_Category; + private DevExpress.XtraEditors.LabelControl labelControl7; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl15; + private DevExpress.XtraEditors.LabelControl labelControl11; + private DevExpress.XtraEditors.LabelControl labelControl13; + private DevExpress.XtraEditors.LabelControl labelControl10; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.ComboBox cb_Model; + private DevExpress.XtraEditors.LabelControl labelControl17; + private System.Windows.Forms.DateTimePicker dt_SendTaskTimes2; + private System.Windows.Forms.DateTimePicker dt_SendTaskTimes1; + private DevExpress.XtraEditors.LabelControl labelControl18; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.NumericUpDown nud_IntervalCircle; + private DevExpress.XtraEditors.LabelControl labelControl20; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.Panel panel3; + private DevExpress.XtraEditors.MemoEdit me_SingleAdditionalComment; + private DevExpress.XtraEditors.MemoEdit me_SingleGoodsQRCodePicDesc; + private DevExpress.XtraEditors.MemoEdit me_SingleContentCircle; + private DevExpress.XtraEditors.LabelControl labelControl26; + private DevExpress.XtraEditors.LabelControl labelControl27; + private UI.Framework.Controls.ButtonCheck bc_SingleIsQRCodePic; + private DevExpress.XtraEditors.LabelControl labelControl25; + private UI.Framework.Controls.ButtonCheck bc_SingleIsSynthCoupon; + private DevExpress.XtraEditors.LabelControl labelControl19; + private DevExpress.XtraEditors.LabelControl labelControl28; + private System.Windows.Forms.Panel panel2; + private DevExpress.XtraEditors.MemoEdit me_MultiAdditionalComment; + private DevExpress.XtraEditors.MemoEdit me_MultiGoodsDesc; + private DevExpress.XtraEditors.MemoEdit me_MultiContentCircle; + private DevExpress.XtraEditors.LabelControl labelControl21; + private DevExpress.XtraEditors.LabelControl labelControl22; + private DevExpress.XtraEditors.LabelControl labelControl23; + private DevExpress.XtraEditors.LabelControl labelControl24; + private System.Windows.Forms.NumericUpDown nud_SendGoodsImageNum; + private System.Windows.Forms.RadioButton rb_shao; + private System.Windows.Forms.RadioButton rb_duo; + private DevExpress.XtraEditors.LabelControl labelControl31; + private DevExpress.XtraEditors.LabelControl labelControl32; + private DevExpress.XtraEditors.LabelControl labelControl33; + private DevExpress.XtraEditors.LabelControl labelControl34; + private DevExpress.XtraEditors.LabelControl labelControl36; + private DevExpress.XtraEditors.LabelControl labelControl35; + private System.Windows.Forms.GroupBox groupBox4; + private System.Windows.Forms.DateTimePicker dt_AutoClearTaskTimes; + private DevExpress.XtraEditors.LabelControl labelControl30; + private DevExpress.XtraEditors.LabelControl labelControl29; + private UI.Framework.Controls.ButtonCheck bc_AutoClearTask; + } +} \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/MainForm.cs b/应用/Weixin.TBCirclePromotion/MainForm.cs new file mode 100644 index 0000000..f1d77b0 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/MainForm.cs @@ -0,0 +1,490 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using Weixin.TBCirclePromotion.Entitys; +using Weixin.TBCirclePromotion.Properties; +using static Api.Framework.ApiClient; +using static Weixin.TBCirclePromotion.Enums; + +namespace Weixin.TBCirclePromotion +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + public void CloseForm() + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + + private void Bind() + { + try + { + + bc_CJSwitch.Checked = Class1.Config.HDK_Switch == SwitchType.开启; + nud_GatherTouchNum.Value = Class1.Config.HDK_GatherTouchNum; + cb_GatherType.SelectedIndex = (int)Class1.Config.HDK_GatherType; + cb_Category.SelectedIndex = (int)Class1.Config.HDK_Category; + cb_Stage.SelectedIndex = ((int)Class1.Config.HDK_Stage) + 1; + nud_Price1.Value = (decimal)(Class1.Config.HDK_Price1 ?? 0); + nud_Price2.Value = (decimal)(Class1.Config.HDK_Price2 ?? 0); + nud_Rate.Value = (decimal)(Class1.Config.HDK_Rate ?? 0); + nud_Brokerage.Value = (decimal)(Class1.Config.HDK_Brokerage ?? 0); + nud_CouponMoney.Value = (decimal)(Class1.Config.HDK_CouponMoney ?? 0); + nud_Sales.Value = (decimal)(Class1.Config.HDK_Sales ?? 0); + nud_Avgmin.Value = (decimal)(Class1.Config.HDK_Avgmin ?? 0); + cb_Model.SelectedIndex = (int)Class1.Config.HDK_Model; + rb_duo.Checked = true; + if (Class1.Config.HDK_SendMode == SendModeType.多产品) + rb_duo.Checked = true; + else + rb_shao.Checked = true; + + var times = Class1.Config.HDK_SendTaskTimes[0].Split('-'); + dt_SendTaskTimes1.Value = DateTime.Parse($"2020-01-01 {times[0]}"); + dt_SendTaskTimes2.Value = DateTime.Parse($"2020-01-01 {times[1]}"); + nud_IntervalCircle.Value = (decimal)Class1.Config.HDK_Interval_Circle; + nud_SendGoodsImageNum.Value = (decimal)Class1.Config.HDK_Multi_SendGoodsImageNum; + me_MultiContentCircle.Text = Class1.Config.HDK_Multi_ContentCircle; + me_MultiGoodsDesc.Text = Class1.Config.HDK_Multi_GoodsDesc; + me_MultiAdditionalComment.Text = Class1.Config.HDK_Multi_AdditionalComment; + bc_SingleIsSynthCoupon.Checked = Class1.Config.HDK_Single_IsSynthCoupon == SwitchType.开启; + bc_SingleIsQRCodePic.Checked = Class1.Config.HDK_Single_IsQRCodePic == SwitchType.开启; + me_SingleGoodsQRCodePicDesc.Text = Class1.Config.HDK_Single_GoodsQRCodePicDesc; + me_SingleContentCircle.Text = Class1.Config.HDK_Single_ContentCircle; + me_SingleAdditionalComment.Text = Class1.Config.HDK_Single_AdditionalComment; + bc_AutoClearTask.Checked = Class1.Config.HDK_Auto_IsClear == SwitchType.开启; + dt_AutoClearTaskTimes.Value = DateTime.Parse(Class1.Config.HDK_AutoClearTaskTimes); + + } + catch (Exception ex) + { } + } + + + + private void Save(FormClosingEventArgs e) + { + try + { + if (nud_Price1.Value > nud_Price2.Value) + throw new Exception("商品售价第一个值不能大于第二个值"); + + if (dt_SendTaskTimes1.Value > dt_SendTaskTimes2.Value) + throw new Exception("发送任务时间段第一个值不能大于第二个值"); + + Class1.Config.HDK_Price1 = nud_Price1.Value == 0 ? null : (double?)nud_Price1.Value; + Class1.Config.HDK_Price2 = nud_Price2.Value == 0 ? null : (double?)nud_Price2.Value; + + + Class1.Config.HDK_Switch = bc_CJSwitch.Checked ? SwitchType.开启 : SwitchType.关闭; + Class1.Config.HDK_GatherTouchNum = (int)nud_GatherTouchNum.Value; + Class1.Config.HDK_GatherType = (GatherType)cb_GatherType.SelectedIndex; + Class1.Config.HDK_Category = (CategoryType)cb_Category.SelectedIndex; + Class1.Config.HDK_Stage = (StageType)(cb_Stage.SelectedIndex - 1); + Class1.Config.HDK_Rate = nud_Rate.Value == 0 ? null : (double?)nud_Rate.Value; + Class1.Config.HDK_Brokerage = nud_Brokerage.Value == 0 ? null : (double?)nud_Brokerage.Value; + Class1.Config.HDK_CouponMoney = nud_CouponMoney.Value == 0 ? null : (double?)nud_CouponMoney.Value; + Class1.Config.HDK_Sales = nud_Sales.Value == 0 ? null : (int?)nud_Sales.Value; + Class1.Config.HDK_Avgmin = nud_Avgmin.Value == 0 ? null : (double?)nud_Avgmin.Value; + Class1.Config.HDK_Model = (QrImageType)cb_Model.SelectedIndex; + Class1.Config.HDK_SendMode = rb_duo.Checked ? SendModeType.多产品 : SendModeType.单产品; + Class1.Config.HDK_SendTaskTimes = new string[] { (dt_SendTaskTimes1.Value.ToString("HH:mm") + "-" + dt_SendTaskTimes2.Value.ToString("HH:mm")) }; + Class1.Config.HDK_Interval_Circle = (int)nud_IntervalCircle.Value; + Class1.Config.HDK_Multi_SendGoodsImageNum = (int)nud_SendGoodsImageNum.Value; + Class1.Config.HDK_Multi_ContentCircle = me_MultiContentCircle.Text; + Class1.Config.HDK_Multi_GoodsDesc = me_MultiGoodsDesc.Text; + Class1.Config.HDK_Multi_AdditionalComment = me_MultiAdditionalComment.Text; + Class1.Config.HDK_Single_IsSynthCoupon = bc_SingleIsSynthCoupon.Checked ? SwitchType.开启 : SwitchType.关闭; + Class1.Config.HDK_Single_IsQRCodePic = bc_SingleIsQRCodePic.Checked ? SwitchType.开启 : SwitchType.关闭; + Class1.Config.HDK_Single_GoodsQRCodePicDesc = me_SingleGoodsQRCodePicDesc.Text; + Class1.Config.HDK_Single_ContentCircle = me_SingleContentCircle.Text; + Class1.Config.HDK_Single_AdditionalComment = me_SingleAdditionalComment.Text; + Class1.Config.HDK_Auto_IsClear = bc_AutoClearTask.Checked ? SwitchType.开启 : SwitchType.关闭; + Class1.Config.HDK_AutoClearTaskTimes = dt_AutoClearTaskTimes.Value.ToString("HH:mm"); + + } + catch (Exception ex) + { + e.Cancel = true; + BaseForm.ShowError(ex); + } + } + + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + //settingControl1.Bind(Class1.Config, 120); //绑定控件 + + Bind(); + + #region 加载所有采集到的商品 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<fl_plugin_tbcirclepromotion_goodsinfos>("select * from fl_plugin_tbcirclepromotion_goodsinfos order by state desc", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label2.Visible = gridView1.RowCount == 0; + + #endregion + + #region 加载所有的账号 + + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<tbinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.阿里妈妈}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID where ri.type = 2", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl2, 40, true, true); + + label1.Visible = gridView2.RowCount == 0; + + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Save(e); + Api.Framework.Tools.Util.Save(Class1.Config); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.Caption == "数据来源") + { + var value = e.Value.ToString().ToLower(); + if (value == "0") + e.DisplayText = "文件导入"; + else if (value == "1") + e.DisplayText = "接口采集"; + } + if (e.Column.Caption == "发送状态") + { + var value = e.Value.ToString().ToLower(); + if (value == "true") + e.DisplayText = "未推广"; + else if (value == "false") + e.DisplayText = "已推广"; + } + if (e.Column.Caption == "佣金比例") + e.DisplayText = e.Value.ToString() + "%"; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 修改显示内容的事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "adzone_name" && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + /// <summary> + /// 行单元格单击事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + + #region 双击单元格设置推广位 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.阿里妈妈); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + if (e.Column.FieldName == "adzone_name") + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + } + session.SaveOrUpdate(adzone); + } + else + { + //session.BeginTransaction(); + try + { + if (e.Column.FieldName == "adzone_name") + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.Insertable(adzone).ExecuteReturnEntity(); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + //else session.Commit(); + } + catch (Exception ex) + { + //session.Rollback(); + ShowError(ex); + } + } + pageControl2.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在 + adzone.onoff = !adzone.onoff; + else + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = string.Empty, //推广位名称 + adzone_pid = string.Empty, //推广位pid + adzone_pid_cps_name = string.Empty, //推广位cps名称 + alliance_id = (int)CpsType.阿里妈妈, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = true //不禁用 + }; + session.SaveOrUpdate(adzone); + pageControl2.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + session.FindAdzoneInfos(true); + //session.FindTBCirclePromotions(true); + } + } + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView1.GetSelectedRows().ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + List<string> goodsids = new List<string>(); + foreach (var item in rownumber) + { + goodsids.Add("'" + gridView1.GetRowCellValue(item, "goods_id").ToString() + "'");//根据行号获取相应行的数据 + } + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_tbcirclepromotion_goodsinfos where goods_id in (" + string.Join(",", goodsids) + ")"); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除所有已发ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_tbcirclepromotion_goodsinfos where state = 0"); + } + + private void 删除所有数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_tbcirclepromotion_goodsinfos"); + } + + private void RemoveGoodsInfos(string sql) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL(sql); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 检测是否与发单推广位有重复 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var session = ApiClient.GetSession(); + var adzones = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType).ToList();//发单推广位集合 + var circleToolsAdzones = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.CricleToolsSoftwareType).ToList();//朋友圈推广位集合 + + var tbCricleAdzones = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.TbRebateSoftwareType).ToList();//淘宝返利 + adzones.AddRange(circleToolsAdzones); + + if (tbCricleAdzones != null && adzones != null) + { + StringBuilder strb = new StringBuilder(); + foreach (var item in tbCricleAdzones) + { + foreach (var moment in adzones) + { + if (item.adzone_pid == moment.adzone_pid) + strb.AppendLine(moment.adzone_name); + } + } + if (strb.Length != 0) + ShowSuccess(@"以下推广位和淘宝返利推广设置有冲突 +请及时处理,否则订单将无法自动绑定 +" + strb.ToString()); + else ShowSuccess("不存在冲突推广位"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + var importData = new ImportDataForm(); + importData.ShowDialog(); + pageControl1.GotoPage(1); + } + + private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) + { + + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + panel1.Enabled = cb_GatherType.SelectedIndex == 0; + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void rb_duo_CheckedChanged(object sender, EventArgs e) + { + if (rb_duo.Checked) + { + panel3.Enabled = false; + panel2.Enabled = true; + } + } + + private void rb_shao_CheckedChanged(object sender, EventArgs e) + { + if (rb_shao.Checked) + { + panel2.Enabled = false; + panel3.Enabled = true; + } + } + + private void labelControl31_Click(object sender, EventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/MainForm.resx b/应用/Weixin.TBCirclePromotion/MainForm.resx new file mode 100644 index 0000000..06d42fb --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/MainForm.resx @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>53</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/Properties/AssemblyInfo.cs b/应用/Weixin.TBCirclePromotion/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f3ffb0a --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("TBCircleFriends")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TBCircleFriends")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("5f4fc620-9101-4630-adb5-77b7dc057cf9")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("2019.02.22.1")] +[assembly: AssemblyFileVersion("2019.02.22.1")] diff --git a/应用/Weixin.TBCirclePromotion/Properties/Resources.Designer.cs b/应用/Weixin.TBCirclePromotion/Properties/Resources.Designer.cs new file mode 100644 index 0000000..00f5787 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Properties/Resources.Designer.cs @@ -0,0 +1,167 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Weixin.TBCirclePromotion.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Weixin.TBCirclePromotion.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 朋友圈工具 的本地化字符串。 + /// </summary> + internal static string CricleToolsSoftwareType { + get { + return ResourceManager.GetString("CricleToolsSoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找类似 淘宝朋友圈发单 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 淘宝发单 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 朋友圈淘宝商品发单插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找类似 淘宝发单 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找类似 淘宝返利 的本地化字符串。 + /// </summary> + internal static string TbRebateSoftwareType { + get { + return ResourceManager.GetString("TbRebateSoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 优惠券底图 { + get { + object obj = ResourceManager.GetObject("优惠券底图", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 优惠券背景图 { + get { + object obj = ResourceManager.GetObject("优惠券背景图", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 活动推广 { + get { + object obj = ResourceManager.GetObject("活动推广", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 淘宝发单 { + get { + object obj = ResourceManager.GetObject("淘宝发单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 系统 { + get { + object obj = ResourceManager.GetObject("系统", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Weixin.TBCirclePromotion/Properties/Resources.resx b/应用/Weixin.TBCirclePromotion/Properties/Resources.resx new file mode 100644 index 0000000..644dba7 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Properties/Resources.resx @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="活动推广" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\活动推广.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="MainFormTitle" xml:space="preserve"> + <value>淘宝朋友圈发单</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>朋友圈淘宝商品发单插件</value> + <comment>插件介绍</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>淘宝发单</value> + <comment>插件名</comment> + </data> + <data name="淘宝发单" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\淘宝发单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="系统" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\系统.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="优惠券底图" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\优惠券底图.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> + <data name="SoftwareType" xml:space="preserve"> + <value>淘宝发单</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <data name="TbRebateSoftwareType" xml:space="preserve"> + <value>淘宝返利</value> + <comment>fl_adzone_info自定义类型(custom_type)淘宝返利</comment> + </data> + <data name="CricleToolsSoftwareType" xml:space="preserve"> + <value>朋友圈工具</value> + <comment>fl_adzone_info自定义类型(custom_type)朋友圈发单</comment> + </data> + <data name="优惠券背景图" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\优惠券背景图.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/Weixin.TBCirclePromotion/Properties/licenses.licx b/应用/Weixin.TBCirclePromotion/Properties/licenses.licx new file mode 100644 index 0000000..3fd7997 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Properties/licenses.licx @@ -0,0 +1,2 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/Weixin.TBCirclePromotion/Resources/优惠券底图.jpg b/应用/Weixin.TBCirclePromotion/Resources/优惠券底图.jpg new file mode 100644 index 0000000..41cf755 Binary files /dev/null and b/应用/Weixin.TBCirclePromotion/Resources/优惠券底图.jpg differ diff --git a/应用/Weixin.TBCirclePromotion/Resources/优惠券背景图.jpg b/应用/Weixin.TBCirclePromotion/Resources/优惠券背景图.jpg new file mode 100644 index 0000000..1b9c2c4 Binary files /dev/null and b/应用/Weixin.TBCirclePromotion/Resources/优惠券背景图.jpg differ diff --git a/应用/Weixin.TBCirclePromotion/Resources/活动推广.png b/应用/Weixin.TBCirclePromotion/Resources/活动推广.png new file mode 100644 index 0000000..727aa42 Binary files /dev/null and b/应用/Weixin.TBCirclePromotion/Resources/活动推广.png differ diff --git a/应用/Weixin.TBCirclePromotion/Resources/淘宝发单.png b/应用/Weixin.TBCirclePromotion/Resources/淘宝发单.png new file mode 100644 index 0000000..286178d Binary files /dev/null and b/应用/Weixin.TBCirclePromotion/Resources/淘宝发单.png differ diff --git a/应用/Weixin.TBCirclePromotion/Resources/系统.png b/应用/Weixin.TBCirclePromotion/Resources/系统.png new file mode 100644 index 0000000..bc64b4a Binary files /dev/null and b/应用/Weixin.TBCirclePromotion/Resources/系统.png differ diff --git a/应用/Weixin.TBCirclePromotion/SendCircleFriendThread.cs b/应用/Weixin.TBCirclePromotion/SendCircleFriendThread.cs new file mode 100644 index 0000000..0e9b7b9 --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/SendCircleFriendThread.cs @@ -0,0 +1,830 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Api.Framework.Data.TB; +using Weixin.TBCirclePromotion.Entitys; +using Weixin.TBCirclePromotion.Properties; +using static Api.Framework.Tools.TBHelper; +using static Weixin.TBCirclePromotion.Enums; + +namespace Weixin.TBCirclePromotion +{ + public class SendCircleFriendThread : TimerTask + { + AnalyzeGoods analyzegoods = new AnalyzeGoods(); + TbAnalysis tbAnalysis = new TbAnalysis(); + AnalyzeGoods analyzeGoods = new AnalyzeGoods(); + StringBuilder strb = new StringBuilder(); + bool isSend = false; + bool isSendTime = false;//这里是用来判断是否在任务时间段里面,如果满足这会赋值为true + //private static DateTime RecordSendTime = DateTime.MinValue; + SqlSugarClient session = ApiClient.GetSession(); + private static object objLock = new object(); + + public override void Run(object state, bool timedOut) + { + #region 好单库 + + #region 定时清空采集的数据 + if (!string.IsNullOrWhiteSpace(Class1.Config.HDK_AutoClearTaskTimes)) + { + if (Class1.Config.HDK_Auto_IsClear == SwitchType.开启) + { + try + { + if (DateTime.Now.AddSeconds(-3).ToString("HHmm") == DateTime.Parse(Class1.Config.HDK_AutoClearTaskTimes).ToString("HHmm")) + { + session.ExcuteSQL("Delete from fl_plugin_tbcirclepromotion_goodsinfos", new { }); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, "定时清理异常" + ex.Message + "-" + ex.StackTrace); + } + } + } + #endregion + isSendTime = false; + var now = DateTime.Now; + for (int i = 0; i < Class1.Config.HDK_SendTaskTimes.Length; i++) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.HDK_SendTaskTimes[i])) + { + var times = Class1.Config.HDK_SendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0].Trim()); + var end = DateTime.Parse(times[1].Trim()); + if (begin <= now && now <= end) + { + isSendTime = true; + break; + } + } + } + } + if (!isSendTime) return; + if ((DateTime.Now - Class1.Config.HDK_RecordSendTime).TotalMinutes < Class1.Config.HDK_Interval_Circle) return; + var sb = new StringBuilder(); + try + { + lock (objLock) + { + //删除N天前的数据 + session.ExcuteSQL("Delete from fl_plugin_tbcirclepromotion_goodsinfos where cur_time <= @time", new { time = DateTime.Today.AddDays(-3) }); + isSend = false; + #region 采集数据 + if (Class1.Config.HDK_Switch == SwitchType.开启) + { + var num = session.Find<fl_plugin_tbcirclepromotion_goodsinfos>("select * from fl_plugin_tbcirclepromotion_goodsinfos where state = @state", new { state = StateType.未推广 }).Count(); + if (num <= Class1.Config.HDK_GatherTouchNum) analyzeGoods.GatherFactory(); + } + #endregion + var goods_infos_temp = new List<fl_plugin_tbcirclepromotion_goodsinfos>(); + #region 发送多产品模式 + if (Class1.Config.HDK_SendMode == SendModeType.多产品) + { + //EventClient.OnEvent(this, $"【淘宝发单】5555"); + var goods_infos = session.Find<fl_plugin_tbcirclepromotion_goodsinfos>($"select * from fl_plugin_tbcirclepromotion_goodsinfos where state = 1 order by cur_time desc limit {(Class1.Config.HDK_Multi_SendGoodsImageNum <= 0 ? 1 : Class1.Config.HDK_Multi_SendGoodsImageNum)}"); + + if (goods_infos != null && goods_infos.Count != 0) + { + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList().Where(f => (f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 || f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信) && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + foreach (var item in clients) + { + try + { + var robot_info = session.FindRobots().FirstOrDefault(f => f.name == item.WeixinHao && f.type == ChatType.微信); + if (robot_info != null) + { + var tb_circle_promotion_temp = session.FindTBCirclePromotions().Where(f => f.onoff).ToList(); + if (tb_circle_promotion_temp != null) + { + if (tb_circle_promotion_temp.FirstOrDefault(f => f.name == robot_info.name) != null) continue; + } + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == robot_info.id); + if (adzone != null) + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + if (member != null) + { + var api = CpsClient.CreateAlimamaRequest(member); + if (api == null) { continue; } + strb.Length = 0; + + strb.AppendLine(Class1.Config.HDK_Multi_ContentCircle); + int count = 0; + int _count = goods_infos.Count; + for (int i = 0; i < _count; i++) + { + try + { + goods_infos_temp.Add(goods_infos[i]); + var goodsinfo = goods_infos[i]; + count = 0; + Next: + var result = analyzegoods.FindGoodsInfoToGoodsId(goodsinfo.goods_id, adzone.adzone_pid_cps_name, adzone.adzone_pid, goodsinfo.goods_quan);//获取到自己返利链接等信息 + if (result == null) + { + count++; + if (count <= 7 && goods_infos_temp.Count < goods_infos.Count) + { + goodsinfo = session.FindSingle<fl_plugin_tbcirclepromotion_goodsinfos>("select * from fl_plugin_tbcirclepromotion_goodsinfos where state = @state order by cur_time desc", new { state = StateType.未推广 }); + goods_infos_temp.Add(goodsinfo); + goto Next; + } + else + continue; + } + else + { + var tklInfo = tbAnalysis.FindTKL(result.shopping_url, api); + if (tklInfo == null) + continue; //生成淘口令失败 + + //var shortUrl = tbAnalysis.FindShortUrlBySrcUrl(result.shopping_url, api); + + var short_url = api.ComposeTbClick(result.goods_id, result.goods_thumbnail_url, tklInfo.tkl, tklInfo.isoUrl, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品, (int)DwzType.快站短网址, isCircleZjy: true);//短连接 + var cprice = ((decimal)result.normal_price - (decimal)result.coupon_discount).ToString();//券后价 + var goods_desc = string.IsNullOrWhiteSpace(Class1.Config.HDK_Multi_GoodsDesc) ? result.goods_desc : Class1.Config.HDK_Multi_GoodsDesc + .Replace("[商品标题]", result.goods_name) + .Replace("[商品描述]", goodsinfo.goods_desc) + .Replace("[已售数量]", result.sold_quantity.ToString()) + .Replace("[店铺名称]", result.mall_name) + .Replace("[优惠券金额]", result.coupon_discount.ToString()) + .Replace("[优惠券数量]", result.coupon_remain_quantity.ToString()) + .Replace("[商品单价]", result.normal_price.ToString()) + .Replace("[券后价]", cprice) + .Replace("[劵后价]", cprice) + .Replace("[购买地址]", short_url);// result.shopping_url); + var image = ApiClient.GetQRImage(result.goods_name, result.normal_price.ToString(), result.coupon_discount.ToString(), cprice, result.goods_thumbnail_url, short_url, Class1.Config.HDK_Model, CpsType.阿里妈妈, string.IsNullOrWhiteSpace(Class1.Config.HDK_Single_GoodsQRCodePicDesc) ? goodsinfo.goods_desc : Class1.Config.HDK_Single_GoodsQRCodePicDesc); //合成附带二维码等信息的宝贝图片 + strb.Append($"[图片={image}]"); + } + } + catch + { } + } + var json = item.SendCircle(strb.ToString()); + if (!string.IsNullOrWhiteSpace(Class1.Config.HDK_Multi_AdditionalComment)) + { + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, Class1.Config.HDK_Multi_AdditionalComment); + } + if (string.IsNullOrWhiteSpace(json)) + EventClient.OnEvent(this, $"【淘宝发单】多({clients.Count()}):{item.WeixinHao},发单失败"); + else + EventClient.OnEvent(this, $"【淘宝发单】多({clients.Count()}):{item.WeixinHao},发单成功"); + isSend = true;//认定发送过了... + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"淘宝推广 - 多产品:{item.WeixinHao},朋友圈推广失败,{ex.Message}"); + } + } + } + } + #endregion + + #region 发送单品【多图】模式 + else + { + //获取一个宝贝 + var goods_info = session.FindSingle<fl_plugin_tbcirclepromotion_goodsinfos>("select * from fl_plugin_tbcirclepromotion_goodsinfos where state = @state order by id desc", new { state = StateType.未推广 }); + //.Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).First(); + if (goods_info != null) + { + var html = string.Empty; + var shopIcon = string.Empty; + var QRCodeUrl = string.Empty;//获取其中一张图片用于合成二维码 + var Content = string.Empty;//内容 + sb.AppendLine($"a"); + + #region 获取商品图片 + var memberTmp = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈); + if (memberTmp != null) + { + var api = CpsClient.CreateAlimamaRequest(memberTmp); + if (api == null) { return; } + + GetItemInfosData itemInfo = null; + try + { + sb.AppendLine($"b = " + goods_info.goods_id); + //objData = api.SendTaobao("taobao.tbk.item.info.get", new { num_iids = goods_info.goods_id }); + itemInfo = api.GetItemInfo(goods_info.goods_id, "2"); + } + catch + { } + + if (itemInfo != null && itemInfo.n_tbk_item != null && itemInfo.n_tbk_item.Count > 0) + { + var tbk_item = itemInfo.n_tbk_item[0]; + if (tbk_item.small_images != null && tbk_item.small_images.@string.Count > 0) + { + foreach (string _small_image in tbk_item.small_images.@string) + { + string small_image = _small_image; + if (string.IsNullOrEmpty(shopIcon)) shopIcon = small_image; + if (Class1.Config.HDK_Single_IsQRCodePic == SwitchType.开启 && string.IsNullOrWhiteSpace(QRCodeUrl)) + QRCodeUrl = small_image; + + Content += $"[图片={small_image}]"; + } + } + } + } + #endregion + + sb.AppendLine($"d"); + if (string.IsNullOrWhiteSpace(Content)) + { + session.Deleteable(goods_info).ExecuteCommand(); + return; + } + sb.AppendLine($"e"); + var clients = ChatClient.WXClient.Values.ToList().Where(f => (f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 || f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信) && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + foreach (var item in clients) + { + sb.AppendLine($"{item.WeixinHao}"); + try + { + var robot_info = session.FindRobots().FirstOrDefault(f => f.name == item.WeixinHao && f.type == ChatType.微信); + if (robot_info != null) + { + var tb_circle_promotion_temp = session.FindTBCirclePromotions().Where(f => f.onoff); + if (tb_circle_promotion_temp != null) + { + sb.AppendLine($"A"); + if (tb_circle_promotion_temp.FirstOrDefault(f => f.name == robot_info.name) != null) continue; + } + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == robot_info.id); + if (adzone != null) + { + sb.AppendLine($"B"); + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + + if (member != null) + { + sb.AppendLine($"C"); + var api = CpsClient.CreateAlimamaRequest(member); + if (api == null) { continue; } + strb.Length = 0; + strb.Append(Content); + //获取的预览图不为空 + if (strb.Length != 0) + { + sb.AppendLine($"D"); + //朋友圈评语 + var goodsInfo = analyzegoods.FindGoodsInfoToGoodsId(goods_info.goods_id, adzone.adzone_pid_cps_name, adzone.adzone_pid, goods_info.goods_quan);//获取到自己返利链接等信息 + if (goodsInfo != null) + { + sb.AppendLine($"E"); + var tklInfo = tbAnalysis.FindTKL(goodsInfo.shopping_url, api); + if (tklInfo == null) + continue; //生成淘口令失败 + + //var shortUrl = tbAnalysis.FindShortUrlBySrcUrl(goodsInfo.shopping_url, api); + var short_url = api.ComposeTbClick(goodsInfo.goods_id, goodsInfo.goods_thumbnail_url, tklInfo.tkl, tklInfo.isoUrl, ApiClient.Setting.SystemConfig.ZjyComposeType == ComposeType.有推荐商品, (int)DwzType.快站短网址, isCircleZjy: true);//短连接 + var cprice = ((decimal)goodsInfo.normal_price - (decimal)goodsInfo.coupon_discount).ToString();//券后价 + + strb.Append(Class1.Config.HDK_Single_ContentCircle + .Replace("[商品标题]", goods_info.goods_name) + .Replace("[优惠券金额]", goods_info.coupon_discount.ToString()) + .Replace("[券后价]", ((decimal)goods_info.normal_price - (decimal)goods_info.coupon_discount).ToString()) + .Replace("[劵后价]", ((decimal)goods_info.normal_price - (decimal)goods_info.coupon_discount).ToString()) + .Replace("[商品描述]", goods_info.goods_desc) + .Replace("[已售数量]", goods_info.sold_quantity.ToString()) + .Replace("[店铺名称]", goods_info.mall_name) + .Replace("[商品单价]", goods_info.normal_price.ToString()) + .Replace("[购买地址]", short_url) + .Replace("[淘口令]", tklInfo.tkl) + ); + ////朋友圈评语 + //var goodsInfo = analyzegoods.FindGoodsInfoToGoodsId(goods_info.goods_id, adzone.adzone_pid_cps_name, adzone.adzone_pid, goods_info.goods_quan);//获取到自己返利链接等信息 + //if (goodsInfo != null) + //{ + // var tkl = tbAnalysis.FindTKL(goodsInfo.shopping_url, goodsInfo.goods_name, goodsInfo.goods_thumbnail_url, api); + // if (string.IsNullOrEmpty(tkl)) { continue; }//生成淘口令失败 + + // var shortUrl = tbAnalysis.FindShortUrlBySrcUrl(goodsInfo.shopping_url, api); + // var short_url = api.ComposeTbClick(goodsInfo.goods_id, goodsInfo.goods_thumbnail_url, tkl, shortUrl, true, (int)DwzType.快站短网址);//短连接 + // var cprice = ((decimal)goodsInfo.normal_price - (decimal)goodsInfo.coupon_discount).ToString();//券后价 + + //合成二维码图片 + if (!string.IsNullOrEmpty(QRCodeUrl)) + { + sb.AppendLine($"F"); + var QRCodeimage = ApiClient.GetQRImage(goodsInfo.goods_name, goodsInfo.normal_price.ToString(), goodsInfo.coupon_discount.ToString(), cprice, QRCodeUrl, short_url, Class1.Config.HDK_Model, CpsType.阿里妈妈, string.IsNullOrWhiteSpace(Class1.Config.HDK_Single_GoodsQRCodePicDesc) ? goods_info.goods_desc : Class1.Config.HDK_Single_GoodsQRCodePicDesc); //合成附带二维码等信息的宝贝图片 + strb.Append($"[图片={QRCodeimage}]"); + } + if (Class1.Config.HDK_Single_IsSynthCoupon == SwitchType.开启) + { + sb.AppendLine($"G"); + #region 获取头像 + if (string.IsNullOrEmpty(shopIcon) || goodsInfo.mall_name == "天猫超市") + shopIcon = "https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg"; + #endregion + + if (!File.Exists(Tools.PosterPathImgUrl)) + Tools.GetBaseIco(); + //合成优惠券图片 + var shopimage_temp = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + try + { + FileTools.DownloadImage(shopIcon, shopimage_temp); + } + catch (Exception ex) + { + FileTools.DownloadImage("https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg", shopimage_temp); + } + + var shopimage = Tools.ReadImageFile(shopimage_temp); + shopimage = Tools.getnew(shopimage, 150, 150); + + var goodsImage_temp = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + FileTools.DownloadImage(goodsInfo.goods_thumbnail_url, goodsImage_temp); + var goodsImage = Tools.ReadImageFile(goodsImage_temp); + goodsImage = Tools.getnew(goodsImage, 150, 150); + + strb.Append($"[图片={ApiClient.GetCouponImage2(Tools.PosterPathImgUrl2, goodsInfo.mall_name, shopimage, goodsInfo.goods_name, goodsInfo.normal_price.ToString(), goodsInfo.coupon_discount.ToString(), goodsImage, $"{DateTime.Today.ToString("yyyy.MM.dd")} - {DateTime.Today.AddMonths(1).ToString("yyyy.MM.dd")}", goodsInfo.sold_quantity.ToString())}]"); + } + sb.AppendLine($"H"); + //淘口令的前/后符号有没有设置.有设置将替换掉 + var tkl = new TBHelper.TbAnalysis().ReplaceTklModifier(tklInfo.tkl); + var comment = Class1.Config.HDK_Single_AdditionalComment + .Replace("[商品标题]", goodsInfo.goods_name) + //.Replace("[商品描述]", goodsInfo.goods_desc) + .Replace("[已售数量]", goodsInfo.sold_quantity.ToString()) + .Replace("[店铺名称]", goodsInfo.mall_name) + .Replace("[优惠券金额]", goodsInfo.coupon_discount.ToString()) + .Replace("[优惠券数量]", goodsInfo.coupon_remain_quantity.ToString()) + .Replace("[商品单价]", goodsInfo.normal_price.ToString()) + .Replace("[券后价]", cprice) + .Replace("[劵后价]", cprice) + .Replace("[购买地址]", short_url) + .Replace("[淘口令]", tkl);//评语内容 + goods_infos_temp.Add(goods_info); + var json = item.SendCircle(strb.ToString().Replace("[购买地址]", short_url)); + if (!string.IsNullOrWhiteSpace(Class1.Config.HDK_Single_AdditionalComment)) + { + sb.AppendLine($"I"); + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, comment); + } + if (string.IsNullOrWhiteSpace(json)) + EventClient.OnEvent(this, $"【淘宝发单】单({clients.Count()}):{item.WeixinHao},发单失败"); + else + EventClient.OnEvent(this, $"【淘宝发单】单({clients.Count()}):{item.WeixinHao},发单成功"); + + isSend = true;//认定发送过了... + } + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"淘宝推广 - 单产品:{item.WeixinHao},朋友圈推广失败,{ex.Message} - {ex.StackTrace}"); + } + } + } + } + #endregion + + if (isSend) + { + //RecordSendTime = DateTime.Now; + for (int i = 0; i < goods_infos_temp.Count; i++) + { + session.ExcuteSQL("update fl_plugin_tbcirclepromotion_goodsinfos set state = @state where id = @id", new { state = Enums.StateType.已推广, id = goods_infos_temp[i].id }); + } + Class1.Config.HDK_RecordSendTime = DateTime.Now; + + Util.Save(Class1.Config); + } + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"淘宝推广:{ex.Message},{ex.StackTrace}"); + } + finally + { + //EventClient.OnEvent(this, $"【淘宝发单】({sb.ToString()})"); + } + #endregion + + #region 大淘客 xxx + + //#region 定时清空采集的数据 + //if (!string.IsNullOrWhiteSpace(Class1.Config.AutoClearTaskTimes)) + //{ + // if (Class1.Config.Auto_IsClear == SwitchType.开启) + // { + // try + // { + // if (DateTime.Now.AddSeconds(-3).ToString("HHmm") == DateTime.Parse(Class1.Config.AutoClearTaskTimes).ToString("HHmm")) + // { + // session.ExcuteSQL("Delete from fl_plugin_tbcirclepromotion_goodsinfos", new { }); + // } + // } + // catch (Exception ex) + // { + // EventClient.OnEvent(this, "定时清理异常" + ex.Message + "-" + ex.StackTrace); + // } + // } + //} + //#endregion + + //isSendTime = false; + //var now = DateTime.Now; + //for (int i = 0; i < Class1.Config.SendTaskTimes.Length; i++) + //{ + // if (!string.IsNullOrWhiteSpace(Class1.Config.SendTaskTimes[i])) + // { + // var times = Class1.Config.SendTaskTimes[i].Trim().Split('-'); + // if (times.Length == 2) + // { + // var begin = DateTime.Parse(times[0].Trim()); + // var end = DateTime.Parse(times[1].Trim()); + // if (begin <= now && now <= end) + // { + // isSendTime = true; + // break; + // } + // } + // } + //} + //if (!isSendTime) return; + + //if ((DateTime.Now - Class1.Config.RecordSendTime).TotalMinutes < Class1.Config.Interval_Circle) return; + + //try + //{ + + // lock (objLock) + // { + // //删除N天前的数据 + // session.ExcuteSQL("Delete from fl_plugin_tbcirclepromotion_goodsinfos where cur_time <= @time", new { time = DateTime.Today.AddDays(-3) }); + // isSend = false; + + // #region 采集数据 + // if (Class1.Config.Switch == SwitchType.开启) + // { + // var num = session.Queryable<fl_plugin_tbcirclepromotion_goodsinfos>().Count(f => f.state == StateType.未推广); + // if (num <= Class1.Config.GatherTouchNum) analyzeGoods.GatherFactory(); + // } + // #endregion + + // var goods_infos_temp = new List<fl_plugin_tbcirclepromotion_goodsinfos>(); + // #region 发送多产品模式 + // if (Class1.Config.SendMode == SendModeType.多产品) + // { + // //var goods_infos = session.Find<fl_plugin_tbcirclepromotion_goodsinfos>($"select * from fl_plugin_tbcirclepromotion_goodsinfos where state = 1 order by cur_time desc limit {(Class1.Config.Multi_SendGoodsImageNum <= 0 ? 1 : Class1.Config.Multi_SendGoodsImageNum)}"); + + // var goods_infos = session.Queryable<fl_plugin_tbcirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).ToPageList(1, (Class1.Config.Multi_SendGoodsImageNum <= 0 ? 1 : Class1.Config.Multi_SendGoodsImageNum)); + + // if (goods_infos != null && goods_infos.Count != 0) + // { + // var clients = Chat.Framework.ChatClient.WXClient.Values; + // foreach (var item in clients) + // { + // try + // { + // if (item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 && item.Status == Chat.Framework.WXSdk.WxStatus.在线) + // { + // var robot_info = session.FindRobotInfo(item.WeixinHao, ChatType.微信); + // if (robot_info != null) + // { + // var tb_circle_promotion_temp = session.FindTBCirclePromotions().Where(f => f.onoff).ToList(); + // if (tb_circle_promotion_temp != null) + // { + // if (tb_circle_promotion_temp.FirstOrDefault(f => f.name == robot_info.name) != null) continue; + // } + + // var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == robot_info.id); + // if (adzone != null) + // { + // var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + // if (member != null) + // { + // var api = CpsClient.CreateAlimamaRequest(member); + // if (api == null) { continue; } + // strb.Length = 0; + + // strb.AppendLine(Class1.Config.Multi_ContentCircle); + // int count = 0; + // for (int i = 0; i < goods_infos.Count; i++) + // { + // try + // { + // goods_infos_temp.Add(goods_infos[i]); + // var goodsinfo = goods_infos[i]; + // count = 0; + // Next: + // //var result = analyzegoods.FindGoodsInfoToGoodsId(goodsinfo.goods_id, GoodsSourceType.对象, adzone.adzone_pid_cps_name, adzone.adzone_pid);//获取到自己返利链接等信息 + // var result = analyzegoods.FindGoodsInfoToGoodsId(goodsinfo.goods_id, adzone.adzone_pid_cps_name, adzone.adzone_pid, goodsinfo.goods_quan);//获取到自己返利链接等信息 + // if (result == null) + // { + // count++; + // if (count <= 7 && goods_infos_temp.Count < goods_infos.Count) + // { + // goodsinfo = session.Queryable<fl_plugin_tbcirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).First(); + // goods_infos_temp.Add(goodsinfo); + // goto Next; + // } + // else + // continue; + // } + // else + // { + // var shortUrl = tbAnalysis.FindShortUrlBySrcUrl(result.shopping_url, api); + // if (string.IsNullOrEmpty(shortUrl)) { continue; }//生成短连接失败 + // var tkl = tbAnalysis.FindTKL(shortUrl, result.goods_name, result.goods_thumbnail_url, api); + // if (string.IsNullOrEmpty(tkl)) { continue; }//生成淘口令失败 + // var short_url = ApiClient.ShortURL(api.ComposeTbClick(result.goods_id, result.goods_thumbnail_url, tkl, result.shopping_url), DwzType.新浪短网址).Result;//短连接 + // var cprice = ((decimal)result.normal_price - (decimal)result.coupon_discount).ToString();//券后价 + // var goods_desc = string.IsNullOrWhiteSpace(Class1.Config.Multi_GoodsDesc) ? result.goods_desc : Class1.Config.Multi_GoodsDesc + // .Replace("[商品标题]", result.goods_name) + // .Replace("[商品描述]", result.goods_desc) + // .Replace("[已售数量]", result.sold_quantity.ToString()) + // .Replace("[店铺名称]", result.mall_name) + // .Replace("[优惠券金额]", result.coupon_discount.ToString()) + // .Replace("[优惠券数量]", result.coupon_remain_quantity.ToString()) + // .Replace("[商品单价]", result.normal_price.ToString()) + // .Replace("[券后价]", cprice) + // .Replace("[劵后价]", cprice) + // .Replace("[购买地址]", short_url);// result.shopping_url); + // var image = ApiClient.GetQRImage(result.goods_name, result.normal_price.ToString(), result.coupon_discount.ToString(), cprice, result.goods_thumbnail_url, short_url, Class1.Config.Model, CpsType.阿里妈妈, Class1.Config.Single_GoodsQRCodePicDesc); //合成附带二维码等信息的宝贝图片 + // strb.Append($"[图片={image}]"); + // } + // } + // catch + // { } + // } + // var json = item.SendCircle(strb.ToString()); + // if (!string.IsNullOrWhiteSpace(Class1.Config.Multi_AdditionalComment)) + // { + // var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + // if (reg.Success) + // item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, Class1.Config.Multi_AdditionalComment); + // } + // isSend = true;//认定发送过了... + // } + // } + // } + // } + // } + // catch (Exception ex) + // { + // EventClient.OnEvent(this, $"淘宝推广 - 多产品:{item.WeixinHao},朋友圈推广失败,{ex.Message}"); + // } + // } + // } + // } + // #endregion + + // #region 发送单品【多图】模式 + // else + // { + // //获取一个宝贝 + // var goods_info = session.Queryable<fl_plugin_tbcirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).First(); + // if (goods_info != null) + // { + // var clients = Chat.Framework.ChatClient.WXClient.Values; + // foreach (var item in clients) + // { + // try + // { + // if (item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 && item.Status == Chat.Framework.WXSdk.WxStatus.在线) + // { + // var robot_info = session.FindRobotInfo(item.WeixinHao, ChatType.微信); + // if (robot_info != null) + // { + // var tb_circle_promotion_temp = session.FindTBCirclePromotions().Where(f => f.onoff); + // if (tb_circle_promotion_temp != null) + // { + // if (tb_circle_promotion_temp.FirstOrDefault(f => f.name == robot_info.name) != null) continue; + // } + + // var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.SoftwareType && f.robot_id == robot_info.id); + // if (adzone != null) + // { + // var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == adzone.adzone_pid_cps_name); + + // if (member != null) + // { + // var api = CpsClient.CreateAlimamaRequest(member); + // if (api == null) { continue; } + // int num = 0; + // Next: + // HttpItem httpItem = new HttpItem() + // { + // URL = @"https://item.taobao.com/item.htm?id=" + goods_info.goods_id,//宝贝的链接 + // Method = "get", + // IsToLower = false, + // Timeout = 10000, + // ReadWriteTimeout = 10000, + // Allowautoredirect = true, + // UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + // ContentType = "application/x-www-form-urlencoded" + // }; + // HttpHelper http = new HttpHelper(); + // var result = http.GetHtml(httpItem); + + // if (result != null && result.Html == "操作超时" && num <= 3) + // { + // num++; + // goto Next; + // } + // var regs = Regex.Matches(result.Html, @"<a href=""#""><img ([^=]+?)=""(?<商品预览图>.+?.jpg)_([^""]*?)"""); + + // if (regs.Count != 0) + // { + // strb.Length = 0; + // //var previewPicUrls = new List<string>();//保存商品预览图 + // var shopIcon = string.Empty; + // var QRCodeUrl = string.Empty;//获取其中一张图片用于合成二维码 + // for (int i = 0; i < regs.Count; i++) + // { + // var previewPic = regs[i].Groups["商品预览图"].Value; + // if (!previewPic.StartsWith("http")) + // { + // previewPic = $"http:{previewPic}"; + // if (string.IsNullOrEmpty(shopIcon)) shopIcon = previewPic; + // } + // if (Class1.Config.Single_IsQRCodePic == SwitchType.开启 && i == (regs.Count - 1)) + // QRCodeUrl = previewPic; + // else + // strb.Append($"[图片={previewPic}]"); + // } + // //获取的预览图不为空 + // if (strb.Length != 0) + // { + // strb.Append(Class1.Config.Single_ContentCircle + // .Replace("[商品标题]", goods_info.goods_name) + // .Replace("[优惠券金额]", goods_info.coupon_discount.ToString()) + // .Replace("[券后价]", ((decimal)goods_info.normal_price - (decimal)goods_info.coupon_discount).ToString()) + // .Replace("[劵后价]", ((decimal)goods_info.normal_price - (decimal)goods_info.coupon_discount).ToString()) + // .Replace("[商品描述]", goods_info.goods_desc) + // .Replace("[已售数量]", goods_info.sold_quantity.ToString()) + // .Replace("[店铺名称]", goods_info.mall_name) + // .Replace("[商品单价]", goods_info.normal_price.ToString())); + // //朋友圈评语 + // //var goodsInfo = analyzegoods.FindGoodsInfoToGoodsId(goods_info.goods_id, GoodsSourceType.对象, adzone.adzone_pid_cps_name, adzone.adzone_pid);//获取到自己返利链接等信息 + // var goodsInfo = analyzegoods.FindGoodsInfoToGoodsId(goods_info.goods_id, adzone.adzone_pid_cps_name, adzone.adzone_pid, goods_info.goods_quan);//获取到自己返利链接等信息 + // if (goodsInfo != null) + // { + // var shortUrl = tbAnalysis.FindShortUrlBySrcUrl(goodsInfo.shopping_url, api); + // if (string.IsNullOrEmpty(shortUrl)) { continue; }//生成短连接失败 + // var tkl = tbAnalysis.FindTKL(shortUrl, goodsInfo.goods_name, goodsInfo.goods_thumbnail_url, api); + // if (string.IsNullOrEmpty(tkl)) { continue; }//生成淘口令失败 + // var short_url = ApiClient.ShortURL(api.ComposeTbClick(goodsInfo.goods_id, goodsInfo.goods_thumbnail_url, tkl, goodsInfo.shopping_url), DwzType.新浪短网址).Result;//短连接 + // var cprice = ((decimal)goodsInfo.normal_price - (decimal)goodsInfo.coupon_discount).ToString();//券后价 + // //合成二维码图片 + // if (!string.IsNullOrEmpty(QRCodeUrl)) + // { + // var QRCodeimage = ApiClient.GetQRImage(goodsInfo.goods_name, goodsInfo.normal_price.ToString(), goodsInfo.coupon_discount.ToString(), cprice, QRCodeUrl, short_url, Class1.Config.Model, CpsType.阿里妈妈, Class1.Config.Single_GoodsQRCodePicDesc); //合成附带二维码等信息的宝贝图片 + // strb.Append($"[图片={QRCodeimage}]"); + // } + // if (Class1.Config.Single_IsSynthCoupon == SwitchType.开启) + // { + // #region 获取头像 + // // B + // //var shopIcon = string.Empty; + // //var objDate = api.SendTaobao("taobao.tbk.item.info.get", new { num_iids = goods_info.goods_id }); + // //if (objDate != null && objDate.Count != 0) + // //{ + // // var tbk_temp_info = ((objDate["n_tbk_item"]) as ArrayList)[0]; + // // var tbk_item = tbk_temp_info as Dictionary<string, object>; + // // //商品主图 + // // shopIcon = tbk_item["pict_url"].ToString(); + // //} + // if (string.IsNullOrEmpty(shopIcon) || goodsInfo.mall_name == "天猫超市") + // shopIcon = "https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg"; + // #endregion + + // if (!File.Exists(Tools.PosterPathImgUrl)) + // Tools.GetBaseIco(); + // //strb.Append($"[图片={ApiClient.GetCouponImage(Tools.PosterPathImgUrl, goodsInfo.mall_name, shopIcon, goodsInfo.coupon_discount.ToString(), $"{DateTime.Today.ToString("yyyy.MM.dd")} - {DateTime.Today.AddMonths(1).ToString("yyyy.MM.dd")}")}]"); + // //合成优惠券图片 + // var shopimage_temp = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + // try + // { + // Tools.DownloadImage(shopIcon, shopimage_temp); + // } + // catch (Exception ex) + // { + // Tools.DownloadImage("https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg", shopimage_temp); + // } + + // var shopimage = Tools.ReadImageFile(shopimage_temp); + // shopimage = Tools.getnew(shopimage, 150, 150); + + // var goodsImage_temp = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + // Tools.DownloadImage(goodsInfo.goods_thumbnail_url, goodsImage_temp); + // var goodsImage = Tools.ReadImageFile(goodsImage_temp); + // goodsImage = Tools.getnew(goodsImage, 150, 150); + + // strb.Append($"[图片={ApiClient.GetCouponImage2(Tools.PosterPathImgUrl2, goodsInfo.mall_name, shopimage, goodsInfo.goods_name, goodsInfo.normal_price.ToString(), goodsInfo.coupon_discount.ToString(), goodsImage, $"{DateTime.Today.ToString("yyyy.MM.dd")} - {DateTime.Today.AddMonths(1).ToString("yyyy.MM.dd")}", goodsInfo.sold_quantity.ToString())}]"); + // } + + // Random rd = new Random(); + // if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.TklStr_First)) + // { + // var fh = ApiClient.Setting.SystemConfig.TklStr_First.Split('|');//符号 + // tkl = fh[rd.Next(0, fh.Length)] + tkl.Substring(1, tkl.Length - 1); + // } + + // if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.TKLStr_End)) + // { + // var fh = ApiClient.Setting.SystemConfig.TKLStr_End.Split('|');//符号 + // tkl = tkl.Substring(0, tkl.Length - 1) + fh[rd.Next(0, fh.Length)]; + // } + + // var comment = Class1.Config.Single_AdditionalComment + // .Replace("[商品标题]", goodsInfo.goods_name) + // //.Replace("[商品描述]", goodsInfo.goods_desc) + // .Replace("[已售数量]", goodsInfo.sold_quantity.ToString()) + // .Replace("[店铺名称]", goodsInfo.mall_name) + // .Replace("[优惠券金额]", goodsInfo.coupon_discount.ToString()) + // .Replace("[优惠券数量]", goodsInfo.coupon_remain_quantity.ToString()) + // .Replace("[商品单价]", goodsInfo.normal_price.ToString()) + // .Replace("[券后价]", cprice) + // .Replace("[劵后价]", cprice) + // .Replace("[购买地址]", short_url) + // .Replace("[淘口令]", tkl);//评语内容 + + // goods_infos_temp.Add(goods_info); + + // var json = item.SendCircle(strb.ToString().Replace("[购买地址]", short_url)); + // //EventClient.OnEvent(this,$"发送成功:{json}"); + // if (!string.IsNullOrWhiteSpace(Class1.Config.Single_AdditionalComment)) + // { + // var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + // if (reg.Success) + // item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, comment); + // } + // isSend = true;//认定发送过了... + // } + // } + // } + + // } + // } + // } + // } + // } + // catch (Exception ex) + // { + // EventClient.OnEvent(this, $"淘宝推广 - 单产品:{item.WeixinHao},朋友圈推广失败,{ex.Message} - {ex.StackTrace}"); + // } + // } + // } + // } + // #endregion + + // if (isSend) + // { + // //RecordSendTime = DateTime.Now; + // for (int i = 0; i < goods_infos_temp.Count; i++) + // { + // //goods_infos_temp[i].state = Enums.StateType.已推广; + // //session.Updateable(goods_infos_temp[i]).ExecuteCommand(); + // session.ExcuteSQL("update fl_plugin_tbcirclepromotion_goodsinfos set state = @state where id = @id", new { state = Enums.StateType.已推广, id = goods_infos_temp[i].id }); + // } + // Class1.Config.RecordSendTime = DateTime.Now; + + // Api.Framework.Tools.Util.Save(Class1.Config); + // } + + // } + + //} + //catch (Exception ex) + //{ + // EventClient.OnEvent(this, $"淘宝推广:{ex.Message},{ex.StackTrace}"); + //} + #endregion + + } + } +} diff --git a/应用/Weixin.TBCirclePromotion/SessionEx.cs b/应用/Weixin.TBCirclePromotion/SessionEx.cs new file mode 100644 index 0000000..9f790fe --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/SessionEx.cs @@ -0,0 +1,59 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.TBCirclePromotion.Entitys; +using Weixin.TBCirclePromotion.Properties; + +namespace Weixin.TBCirclePromotion +{ + public static class SessionEx + { + const string tb_circle_promotion_temp_list = "tb_circle_promotion_temp_list"; + + /// <summary> + /// + /// </summary> + /// <param name="session"></param> + /// <param name="refresh"></param> + /// <returns></returns> + public static List<tbinfo_temp> FindTBCirclePromotions(this SqlSugarClient session, bool refresh = false) + { + return session.Find<tbinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.阿里妈妈}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID"); + + //var tb_circle_promotion_temp = ApiClient.Cache.Get<string>(tb_circle_promotion_temp_list);//根据KEY、获得缓存 + //List<tbinfo_temp> list = null; + //if (refresh || tb_circle_promotion_temp == null) + //{ + // list = session.Find<tbinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.阿里妈妈}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID"); + + // Dictionary<string, object> pair = new Dictionary<string, object>() { { "data", list } }; + // tb_circle_promotion_temp = CsharpHttpHelper.HttpHelper.ObjectToJson(pair); + // ApiClient.Cache.Set(tb_circle_promotion_temp_list, tb_circle_promotion_temp, 60); + //} + //if (list == null && !string.IsNullOrWhiteSpace(tb_circle_promotion_temp)) + //{ + // var pair = CsharpHttpHelper.HttpExtend.JsonToDictionary(tb_circle_promotion_temp); + // if (pair != null && pair.ContainsKey("data")) + // { + // var result = pair["data"] as ArrayList; + // list = new List<tbinfo_temp>(); + // foreach (tbinfo_temp item in result) + // { + // list.Add(item); + // } + // } + //} + //if (list == null) + // list = new List<tbinfo_temp>(); + //return list; + } + + } +} diff --git a/应用/Weixin.TBCirclePromotion/Tools.cs b/应用/Weixin.TBCirclePromotion/Tools.cs new file mode 100644 index 0000000..a2f983b --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Tools.cs @@ -0,0 +1,197 @@ +using Api.Framework.Tools; +using System; +using System.Drawing; +using System.IO; +using Weixin.TBCirclePromotion.Properties; + +namespace Weixin.TBCirclePromotion +{ + public static class Tools + { + /// <summary> + /// 背景图片地址 + /// </summary> + public static string PosterPathImgUrl { get; private set; } + public static string PosterPathImgUrl2 { get; private set; } + + static Tools() + { + PosterPathImgUrl = Util.MapFile("优惠券底图.jpg", "File\\Image"); + PosterPathImgUrl2 = Util.MapFile("优惠券背景图.jpg", "File\\Image"); + } + + #region 获取底图的地址 + /// <summary> + /// 获取底图的地址 + /// </summary> + /// <param name="path"></param> + /// <returns></returns> + public static void GetBaseIco() + { + if (!File.Exists(PosterPathImgUrl)) + { + Bitmap bit = Resources.优惠券底图; + bit.Save(PosterPathImgUrl); + } + + if (!File.Exists(PosterPathImgUrl2)) + { + Bitmap bit = Resources.优惠券背景图; + bit.Save(PosterPathImgUrl2); + } + } + #endregion + + #region h5Top xxx + + //private static string _cookies = string.Empty; + + //private static string Cookies + //{ + // get + // { + // if (string.IsNullOrEmpty(_cookies)) + // { + // HttpHelper http = new HttpHelper(); + // string cookies = http.GetHtml(new HttpItem() { URL = "http://api.m.taobao.com/h5/mtop.alimama.union.hsf.coupon.get/1.0/?v=1.0&api=mtop.alimama.union.hsf.coupon.get&appKey=12574478&t=1521082116428&callback=mtopjsonp1&type=jsonp&sign=e102e09c3da2505790412f4b5904cfec&data=%7B%22e%22%3A%22kKwRS8jKFeIGQASttHIRqX4ccS%252BmEB0fPkvI%252B9vDGidk3qypIGt1zv02HjWWzK8QrVVJXxMdEXoJP%252FpVy45HN79fwBwwUiqlbZt%252F%252F9VQxkYKu2xm%252BXzUVW7PVn13QcLNcISolD8QJ4rvZt%252BicRrQwg%253D%253D%22%2C%22pid%22%3A%22mm_96747532_17602904_63786428%22%7D", Timeout = 5000, ReadWriteTimeout = 5000 }).Cookie; + // _cookies = HttpHelper.GetSmallCookie(cookies); + // } + // return _cookies; + // } + // set { _cookies = value; } + //} + + //const string appKey = "12574478"; + + //public static Dictionary<string, object> GetH5Result(string api, object data, string version = "6.0") + //{ + // bool next = false; + // int number = 0; + //Next: + // string time = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString(); + // string mh5Tk = HttpExtend.GetCookiesValue("_m_h5_tk", Cookies); + // mh5Tk = string.IsNullOrEmpty(mh5Tk) ? "f64aa152f943661f750e6212ebc98804_1481170439770" : mh5Tk; + // string json = (data.GetType() == typeof(string)) ? data.ToString() : HttpHelper.ObjectToJson(data).Replace("\\u0026", "&").Replace("_params", "param"); + // string temp_ = mh5Tk + "&" + time + "&" + appKey + "&" + json; + // string sign = HttpExtend.GetMD5String(temp_); + // string send = HttpExtend.UrlEncode(json); + // string temp = string.Format("http://h5api.m.taobao.com/h5/{5}/{4}/?jsv=2.4.11&v={4}&api={5}&appKey={0}&t={1}&callback=mtopjsonp1&type=jsonp&sign={2}&data={3}", appKey, time, sign, send, version, api); + // var html = M_GET_HTML(temp).Trim(); + // if (html.Contains("令牌过期") || html.Contains("令牌为空") || html.Contains("失效")) + // { + // if (!next && number <= 10) + // { + // number++; + // next = true; + // goto Next; + // } + // } + // if (html.Contains("挤爆") && number <= 10) + // { + // Dictionary<string, object> _json = HttpExtend.JsonToDictionary(html); + + // string _url = (_json["data"] as Dictionary<string, object>)["url"].ToString(); + // next = false; + // number++; + // goto Next;//?? + // } + + // var reg = Regex.Match(html, @"^mtopjsonp1\((.*?)\)$", RegexOptions.IgnoreCase); + // if (reg.Success) + // { + // var dic = HttpExtend.JsonToDictionary(reg.Groups[1].Value); + // if (dic.ContainsKey("data") && html.Contains("SUCCESS::调用成功")) + // return dic["data"] as Dictionary<string, object>; + // throw new Exception(reg.Groups[1].Value); + // } + // throw new Exception(html); + //} + + //internal const string _key = "<RSAKeyValue><Modulus>wmUZgme6iOPOaMTZtPu5DKQ8Dph9fSgy6abFyQv25MD8xOMPBBo0wsLUOVt8r9sk+li11mIg1fs1HPJ75UmIle+w9xhIx/nsXWejuQhXlQV0VyJtzI+id8G+FcyYaog91MfPndJoO3m30fSjE/0KDLDmv1EeQcP24RAzeA29p7c=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"; + //internal const int _appid = 10004; + //internal const string _host = "https://cps.api.52cmg.cn"; + + //private static string M_GET_HTML(string tempUrl) + //{ + // try + // { + // HttpItem item = new HttpItem() + // { + // URL = tempUrl,//URL 必需项 + // Method = "get",//URL 可选项 默认为Get + // IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + // Cookie = Cookies + ";random=" + new Random().Next(),//字符串Cookie 可选项 + // Referer = "http://m.taobao.com",//来源URL 可选项 + // Timeout = 5000,//连接超时时间 可选项默认为100000 + // ReadWriteTimeout = 5000,//写入Post数据超时时间 可选项默认为30000 + // UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 + // ContentType = "text/html",//返回类型 可选项有默认值 + // Allowautoredirect = false,//是否根据301跳转 可选项 + // }; + // HttpHelper http = new HttpHelper(); + // int i = 0; + // Next: + // HttpResult result = http.GetHtml(item); + // string html = result.Html; + // if (Regex.IsMatch(html, "亲,小二正忙,滑动一下马上回来|挤爆|rgv587_flag")) + // { + // var r = item.SetProxyIP(http, new AuthEndpoint() + // { + // Host = _host + "/api/webtool.asmx/send_data", + // Appid = _appid, + // Enckey = _key, + // Method = "find_proxy" + // }); + // i++; + // if (r && i < 3) goto Next; + // } + // if (!string.IsNullOrEmpty(result.Cookie)) + // { + // Cookies = HttpExtend.UpdateCookies(Cookies, result.Cookie); + // } + // return html; + // } + // catch (Exception) + // { + // return string.Empty; + // } + //} + #endregion + + #region 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// <summary> + /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// </summary> + /// <param name="path"></param> + /// <returns></returns> + public static Bitmap ReadImageFile(string path) + { + FileStream fs = File.OpenRead(path); //OpenRead + int filelength = 0; + filelength = (int)fs.Length; //获得文件长度 + Byte[] image = new Byte[filelength]; //建立一个字节数组 + fs.Read(image, 0, filelength); //按字节流读取 + Image result = Image.FromStream(fs); + fs.Close(); + Bitmap bit = new Bitmap(result); + return bit; + } + #endregion + + public static Bitmap getnew(Image bit, int width, int height)//beishu参数为放大的倍数。放大缩小都可以,0.8即为缩小至原来的0.8倍 + { + Bitmap destBitmap = new Bitmap(width, height); + using (Graphics g = Graphics.FromImage(destBitmap)) + { + g.Clear(Color.Transparent); + //设置画布的描绘质量 + g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + g.DrawImage(bit, new Rectangle(0, 0, destBitmap.Width, destBitmap.Height), 0, 0, bit.Width, bit.Height, GraphicsUnit.Pixel); + } + return destBitmap; + } + + } +} diff --git a/应用/Weixin.TBCirclePromotion/Weixin.TBCirclePromotion.csproj b/应用/Weixin.TBCirclePromotion/Weixin.TBCirclePromotion.csproj new file mode 100644 index 0000000..144ea3f --- /dev/null +++ b/应用/Weixin.TBCirclePromotion/Weixin.TBCirclePromotion.csproj @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{5F4FC620-9101-4630-ADB5-77B7DC057CF9}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Weixin.TBCirclePromotion</RootNamespace> + <AssemblyName>Weixin.TBCirclePromotion</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraVerticalGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="HtmlAgilityPack"> + <HintPath>..\..\Debug\HtmlAgilityPack.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System"> + <Private>False</Private> + </Reference> + <Reference Include="System.Core"> + <Private>False</Private> + </Reference> + <Reference Include="System.Drawing"> + <Private>False</Private> + </Reference> + <Reference Include="System.Windows.Forms"> + <Private>False</Private> + </Reference> + <Reference Include="System.Xml.Linq"> + <Private>False</Private> + </Reference> + <Reference Include="System.Data.DataSetExtensions"> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CSharp"> + <Private>False</Private> + </Reference> + <Reference Include="System.Data"> + <Private>False</Private> + </Reference> + <Reference Include="System.Net.Http"> + <Private>False</Private> + </Reference> + <Reference Include="System.Xml"> + <Private>False</Private> + </Reference> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="AnalyzeGoods.cs" /> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Control\ArrayControl.cs" /> + <Compile Include="Control\CategoryControl.cs" /> + <Compile Include="Entitys\fl_plugin_tbcirclepromotion_goodsinfos.cs" /> + <Compile Include="Entitys\fl_plugin_tbcirclepromotion_tbtgw.cs" /> + <Compile Include="Entitys\tbinfo_temp.cs" /> + <Compile Include="Enums.cs" /> + <Compile Include="ImportDataForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="ImportDataForm.Designer.cs"> + <DependentUpon>ImportDataForm.cs</DependentUpon> + </Compile> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="SendCircleFriendThread.cs" /> + <Compile Include="SessionEx.cs" /> + <Compile Include="Tools.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="ImportDataForm.resx"> + <DependentUpon>ImportDataForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\活动推广.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\系统.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\优惠券底图.jpg" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\优惠券背景图.jpg" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\淘宝发单.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/Weixin.WPHCirclePromotion/AnalyzeGoods.cs b/应用/Weixin.WPHCirclePromotion/AnalyzeGoods.cs new file mode 100644 index 0000000..27e64fc --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/AnalyzeGoods.cs @@ -0,0 +1,247 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.WPHCirclePromotion.Entitys; +using static Weixin.WPHCirclePromotion.Enums; + +namespace Weixin.WPHCirclePromotion +{ + /// <summary> + /// 解析商品 + /// </summary> + public class AnalyzeGoods + { + private static int DownPage = 1; + + #region 采集数据 + /// <summary> + /// 数据采集 + /// </summary> + public void GatherFactory() + { + for (int i = 0; i < 2; i++) + { + var session = ApiClient.GetSession(); + try + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.唯品联盟);//随机获取一个唯品会的cps + if (member != null) + { + var data = new { request = new { channelType = (int)Class1.Config.ChannelType, page = DownPage, pageSize = 100, requestId = Util.GetUUID() } }; + GatherAction(member, data); + } + } + catch (Exception ex) + { + if (ex.Message.Contains("只支持查询前10000个商品") || ex.Message.Contains("被禁止商品搜索深翻页请求")) + { + DownPage = 1; + continue; + } + EventClient.OnEvent(this, $"唯品会采集A:{ex.Message} - {ex.StackTrace}"); + } + return; + } + } + + #endregion + + private void GatherAction(fl_cps_member member, object data) + { + DownPage++; + var session = ApiClient.GetSession(); + try + { + WeipinhuiApi api = CpsClient.CreateWeipinhuiRequest(member); + var gInfosResult = api.SendWeipinhui<GoodsInfoResponseResult>("com.vip.adp.api.open.service.UnionGoodsService-1.0.0#goodsListWithOauth", data); + if (gInfosResult == null || gInfosResult.returnCode == null || gInfosResult.returnCode != "0" || gInfosResult.result == null) + throw new Exception("唯品会采集异常"); + if (gInfosResult.result.goodsInfoList == null || gInfosResult.result.goodsInfoList.Count == 0) return; + + List<fl_plugin_wphcirclepromotion_goodsinfos> goodsinfos = new List<fl_plugin_wphcirclepromotion_goodsinfos>(); + foreach (var item in gInfosResult.result.goodsInfoList) + { + try + { + if (session.FindSingle<fl_plugin_wphcirclepromotion_goodsinfos>("select * from fl_plugin_wphcirclepromotion_goodsinfos where goodsId = @goodsId", new { goodsId = item.goodsId }) != null) + continue; + + var ss = new fl_plugin_wphcirclepromotion_goodsinfos() + { + goodsId = item.goodsId, + goodsName = item.goodsName, + goodsDesc = item.goodsDesc == null ? string.Empty : item.goodsDesc.Substring(0, item.goodsDesc.Length < 200 ? item.goodsDesc.Length : 200), + goodsMainPicture = item.goodsMainPicture, + buy = item.couponInfo == null ? 0d : double.Parse(item.couponInfo.buy), + fav = item.couponInfo == null ? 0d : double.Parse(item.couponInfo.fav), + commission = double.Parse(item.commission), + commissionRate = double.Parse(item.commissionRate), + marketPrice = double.Parse(item.marketPrice), + storeName = item.storeInfo == null ? string.Empty : item.storeInfo.storeName, + totalAmount = item.couponInfo == null ? 0 : item.couponInfo.totalAmount, + vipPrice = double.Parse(item.vipPrice), + cur_time = DateTime.Today, + state = StateType.未推广, + //goods_source = GoodsSourceType.接口采集 + }; + goodsinfos.Add(ss); + } + catch (Exception ex) + { } + + } + if (goodsinfos.Count != 0) + session.Insertable(goodsinfos).ExecuteCommand(); + + //解析商品,获取商品的信息 + //var goods_search_response = obj["goods_search_response"] as Dictionary<string, object>; + //var goods_list = goods_search_response["goods_list"] as ArrayList; + //if (goods_list != null && goods_list.Count != 0) + //{ + // session.BeginTransaction(); + // List<fl_plugin_wphcirclepromotion_goodsinfos> goodsinfos = new List<fl_plugin_wphcirclepromotion_goodsinfos>(); + // foreach (var item in goods_list) + // { + // try + // { + // var goods = item as Dictionary<string, object>; + // var goods_id = (goods["goods_id"] ?? string.Empty).ToString(); //商品id + + // if (session.FindSingle<fl_plugin_wphcirclepromotion_goodsinfos>("select * from fl_plugin_wphcirclepromotion_goodsinfos where goods_id = @goods_id", new { goods_id = goods_id }) != null) + // continue; + + // var goods_name = (goods["goods_name"] ?? string.Empty).ToString(); //商品标题 + // var goods_desc = (goods["goods_desc"] ?? string.Empty).ToString(); //商品描述 + // var goods_thumbnail_url = (goods["goods_thumbnail_url"] ?? string.Empty).ToString(); //商品图片链接 + + // //已售卖件数 + // var sold_quantity = 0; + // try + // { + // if (goods.ContainsKey("sales_tip")) + // { + // var _sales_tip = goods["sales_tip"].ToString(); + // _sales_tip = _sales_tip.Replace("+", ""); + // if (_sales_tip.Contains("万")) + // { + // _sales_tip = _sales_tip.Replace("万", ""); + // var temp = decimal.Parse(_sales_tip); + // sold_quantity = (int)(temp * 10000m); + // } + // else + // sold_quantity = int.Parse(_sales_tip); + // } + // } + // catch (Exception) + // { sold_quantity = 0; } + + // var min_group_price = Math.Round(goods["min_group_price"] == null ? 0 : (double.Parse(goods["min_group_price"].ToString()) / 100), 2); //最小拼团价格,单位为元 + // var min_normal_price = Math.Round(goods["min_normal_price"] == null ? 0 : (double.Parse(goods["min_normal_price"].ToString()) / 100), 2); //最小单买价格,单位为元 + // var mall_name = (goods["mall_name"] ?? string.Empty).ToString(); //店铺名称 + // var category_id = (goods["category_id"] ?? string.Empty).ToString(); //类目id + // var coupon_min_order_amount = Math.Round(goods["coupon_min_order_amount"] == null ? 0 : (double.Parse(goods["coupon_min_order_amount"].ToString()) / 100), 2); //优惠券门槛价格,单位为元 + // var coupon_discount = Math.Round(goods["coupon_discount"] == null ? 0 : (double.Parse(goods["coupon_discount"].ToString()) / 100), 2); //优惠券面额,单位为元 + // var coupon_remain_quantity = goods["coupon_remain_quantity"] == null ? 0 : int.Parse(goods["coupon_remain_quantity"].ToString()); //优惠券剩余数量 + // var promotion_rate = Math.Round(goods["promotion_rate"] == null ? 0 : (double.Parse(goods["promotion_rate"].ToString()) / 10), 2); //佣金比例,百分比 + + // var ss = new fl_plugin_wphcirclepromotion_goodsinfos() { goods_id = goods_id, goods_name = goods_name, goods_desc = goods_desc.Substring(0, goods_desc.Length < 200 ? goods_desc.Length : 200), goods_thumbnail_url = goods_thumbnail_url, sold_quantity = sold_quantity, min_group_price = min_group_price, min_normal_price = min_normal_price, mall_name = mall_name, category_id = category_id, coupon_min_order_amount = coupon_min_order_amount, coupon_discount = coupon_discount, coupon_remain_quantity = coupon_remain_quantity, promotion_rate = promotion_rate, cur_time = DateTime.Today, state = StateType.未推广, goods_source = GoodsSourceType.接口采集 }; + // goodsinfos.Add(ss); + // } + // catch (Exception ex) + // { } + // } + + // if (goodsinfos.Count != 0) + // session.Insertable(goodsinfos).ExecuteCommand(); + // session.Commit(); + //} + //else + // DownPage = 1; + } + catch (Exception ex) + { + //session.Rollback(); + throw ex; + } + } + + internal fl_plugin_wphcirclepromotion_goodsinfos FindGoodsInfoToGoodsId(string goods_id, fl_cps_member member) + { + try + { + fl_plugin_wphcirclepromotion_goodsinfos goodsinfo = null; + + member = (member == null ? CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.唯品联盟) : member); + if (member != null) + { + var api = CpsClient.CreateWeipinhuiRequest(member); + var wphGInfo = api.SendWeipinhui<WphGoodsInfo>("com.vip.adp.api.open.service.UnionGoodsService-1.0.0#getByGoodsIdsWithOauth", new { goodsIdList = new List<string> { goods_id }, requestId = Util.GetUUID() /*,chanTag = chanTag*/ }); + + if (wphGInfo == null || wphGInfo.result == null || wphGInfo.returnCode == null || wphGInfo.returnCode != "0") + return null; + + foreach (var item in wphGInfo.result) + { + //优惠券金额 + var coupon_price = 0.00d; + //优惠券地址 + var coupon_click_url = string.Empty; + + //优惠券没有过期 + if (item.exclusiveCoupon != null && item.exclusiveCoupon.useEndTime > Util.GetTimeSpan(DateTime.Now, true)) + { + coupon_price = double.Parse(item.exclusiveCoupon.fav); + coupon_click_url = item.exclusiveCoupon.receiveUrl; + } + + //商品标题//< >&"© <,>,&,",©; + var goodsName = item.goodsName.Replace("‮", "").Replace("<", "<").Replace(">", ">").Replace("&", "&").Replace(""", "\"").Replace(" ©", "©"); + + var vipPrice = double.Parse(item.vipPrice); + + var endPrice = vipPrice; + if (coupon_price != 0) + endPrice = (double)((decimal)vipPrice - (decimal)coupon_price); + + //佣金比例 + var commissionRate = double.Parse(item.commissionRate); + + goodsinfo = new fl_plugin_wphcirclepromotion_goodsinfos() + { + goodsId = goods_id, + goodsName = item.goodsName, + goodsDesc = item.goodsDesc, + goodsMainPicture = item.goodsMainPicture, + marketPrice = double.Parse(item.marketPrice), + vipPrice = double.Parse(item.vipPrice), + buy = item.couponInfo == null ? 0 : double.Parse(item.couponInfo.buy), + commission = double.Parse(item.commission), + commissionRate = double.Parse(item.commissionRate), + fav = item.couponInfo == null ? 0 : double.Parse(item.couponInfo.fav), + storeName = item.storeInfo == null ? string.Empty : item.storeInfo.storeName, + totalAmount = item.couponInfo == null ? 0 : item.couponInfo.totalAmount, + cur_time = DateTime.Today, + state = StateType.未推广, + //goods_source = goods_source + }; + + } + return goodsinfo; + } + } + catch (Exception ex) + { } + return null; + } + + + } +} \ No newline at end of file diff --git a/应用/Weixin.WPHCirclePromotion/Class1.cs b/应用/Weixin.WPHCirclePromotion/Class1.cs new file mode 100644 index 0000000..59294a7 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Class1.cs @@ -0,0 +1,111 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.WPHCirclePromotion.Entitys; +using Weixin.WPHCirclePromotion.Properties; + +namespace Weixin.WPHCirclePromotion +{ + public class Class1 : Plugin + { + public Class1() + { + + this.Logo = Resources.唯品会发单; + this.Name = Resources.PluginName; + this.Note = Resources.PluginNote; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<fl_plugin_wphcirclepromotion_goodsinfos>()) session.CreateTable<fl_plugin_wphcirclepromotion_goodsinfos>(); + + //如果存在原来的表将来的数据导入到新的表中,在原来的表给删除 + if (session.TableExist<fl_plugin_wphcirclepromotion_wphtgw>()) + { + var pddtgws = session.Find<fl_plugin_wphcirclepromotion_wphtgw>("select * from fl_plugin_wphcirclepromotion_wphtgw").ToList(); + if (pddtgws != null) + { + foreach (var item in pddtgws) + { + session.Insertable<fl_adzone_info>(new fl_adzone_info() + { + adzone_name = item.pid_name, //推广位名称 + adzone_pid = item.pid, //推广位pid + adzone_pid_cps_name = item.pid_cps_name, //推广位cps名称 + alliance_id = (int)CpsType.唯品联盟, //联盟id + robot_id = item.robot_id, //机器人id + group_id = string.Empty, //群id + is_download = false, //不下载 + member_id = 0, //私人id + onoff = item.onoff, //不禁用 + custom_type = Resources.SoftwareType //自定义类型 + }).ExecuteCommand(); + } + } + session.DropTable<fl_plugin_wphcirclepromotion_wphtgw>(); + } + + #endregion + + Config = this.ReadConfig<Config>(); //创建配置文件 + TimerTask.NewTimer<SendCircleFriendThread>(60); //创建线程 - 发送朋友圈的线程 60秒 + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + TimerTask.Close<SendCircleFriendThread>(); //关闭线程 + if (mainForm != null) + { + mainForm.CloseForm(); //关闭窗体 + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + } +} diff --git a/应用/Weixin.WPHCirclePromotion/Config.cs b/应用/Weixin.WPHCirclePromotion/Config.cs new file mode 100644 index 0000000..e87e95b --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Config.cs @@ -0,0 +1,230 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; +using static Api.Framework.ApiClient; +using static Weixin.WPHCirclePromotion.Enums; + +namespace Weixin.WPHCirclePromotion +{ + [Config(Name = "插件-唯品会发单-配置")] + public class Config + { + + #region 发单功能 + + #region 采集 + /// <summary> + /// 发单条件 - 商品最低售价 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("01.采集开关"), DefaultValue(SwitchType.开启) + ] + public SwitchType Switch { get; set; } + + /// <summary> + /// 采集数据触发数量 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("02.采集触发量"), DefaultValue(10), + Description(@"当采集开关为开启时,该值为一个采集点,当采集剩余的商品数量少于等于采集触发量,将自动进行采集操作") + ] + public int GatherTouchNum { get; set; } + + /// <summary> + /// 发单条件 - 店铺评分 + /// </summary> + [ + Category("1)、自动采集"), DisplayName("03.频道类型"), DefaultValue(ChannelType.出单爆款), + Description(@"采集的产品频道类型") + ] + public ChannelType ChannelType { get; set; } + + #endregion + + #region 开始时间 + + /// <summary> + /// 朋友圈发单二维码模板 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("01.发单二维码模板"), DefaultValue(QrImageType.模板B), + Description(@"朋友圈发单二维码模板") + ] + public QrImageType Model { get; set; } + + private string[] _sendTaskTimes; + /// <summary> + /// 发送任务时间段 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("02.发送任务时间段"), + Description(@"每一行为一个发送时间段 +格式:时间1-时间2 +注:时间1 必须大于 时间2") + ] + public string[] SendTaskTimes //{ get; set; } + { + get { return _sendTaskTimes; } + set + { + var sendTaskTimes = value as string[]; + if (sendTaskTimes != null && sendTaskTimes.Length != 0) + { + for (int i = 0; i < sendTaskTimes.Length; i++) + { + var times = sendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0]); + var end = DateTime.Parse(times[1]); + if (begin >= end) + throw new Exception($"开始时间必须小于结束时间:[{sendTaskTimes[i]}]"); + } + } + } + _sendTaskTimes = value; + } + } + + private int _sendGoodsImageNum; + /// <summary> + /// 发送商品图片数量 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("03.发送推广图片数量"), DefaultValue(9), + Description(@"发送朋友圈推广图片数量,最多9张图片") + ] + public int SendGoodsImageNum + { + get { return _sendGoodsImageNum; } + set + { + if (9 < value || value < 1) throw new Exception("发送推广图片数量应该大于等于1,小于等于9"); + _sendGoodsImageNum = value; + } + } + + /// <summary> + /// 朋友圈发送间隔,单位 分 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("04.朋友圈发送间隔"), DefaultValue(120), + Description(@"朋友圈推广商品间隔,单位 分") + ] + public double Interval_Circle { get; set; } + + /// <summary> + /// 发送的文字内容 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("05.发送的文字内容"), DefaultValue(@"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +补贴奖励和帮助渠道 + +手机唯品会分享宝贝给我 +可以查询优惠券款下单 + +还有网购红包领哦"), + Description(@"发送朋友圈时的文本内容"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Content_Circle { get; set; } + + /// <summary> + /// 宝贝描述语 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("06.宝贝描述语"), DefaultValue(@""), + Description(@"图片中宝贝描述信息,为空时以采集到的数据为准. +支持变量:[商品标题]、[商品描述]、[已售数量]、[店铺名称]、[优惠券门槛金额]、[优惠券金额]、[优惠券数量]、[商品原价]、[商品唯品价]、[券后唯品价]、[购买地址]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Goods_Desc { get; set; } + /// <summary> + /// 朋友圈追加评语 + /// </summary> + [ + Category("2)、朋友圈设置"), DisplayName("07.朋友圈追加评语"), DefaultValue(@""), + Description(@"朋友圈商品推广之后,追加评语"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AdditionalComment { get; set; } + /// <summary> + /// 记录发送的时间 + /// </summary> + [Browsable(false)] + public DateTime RecordSendTime { get; set; } + + #endregion + + /// <summary> + /// 自动清理 + /// </summary> + [ + Category("3)、定时清理"), DisplayName("01.定时清理"), DefaultValue(SwitchType.开启), + Description(@"功能开启时,将在设置的时间进行采集数据的清空操作") + ] + public SwitchType Auto_IsClear { get; set; } + + private string _autoClearTaskTimes; + [ + Category("3)、定时清理"), DisplayName("02.定时清理时间"), DefaultValue(@"23:59"), + Description(@"定时清理时间 +格式:HH:mm +例:23:59 +注:时间为24小时制") + ] + public string AutoClearTaskTimes //{ get; set; } + { + get { return _autoClearTaskTimes; } + set + { + try + { + var time = value as string; + var _time = DateTime.Parse(time); + } + catch (Exception) + { + throw new Exception($"时间格式不正确"); + } + _autoClearTaskTimes = value; + } + } + + #endregion + + public Config() + { + this.Auto_IsClear = SwitchType.开启; + this.Switch = SwitchType.开启; + this.ChannelType = ChannelType.出单爆款; + this.Content_Circle = @"╭┈┈┈┄┈┈┈┈┈╮ + 爆款榜单 +╰┈┈┈┈┈┈┈┈┈╯ +补贴奖励和帮助渠道 + +手机唯品会分享宝贝给我 +可以查询优惠券款下单 + +还有网购红包领哦"; + this.SendGoodsImageNum = 9; + this._sendGoodsImageNum = 9; + this.Interval_Circle = 120; + this.SendTaskTimes = new string[] { }; + this._sendTaskTimes = new string[] { "09:00-22:00" }; + this._autoClearTaskTimes = "23:59"; + this.Model = QrImageType.模板B; + this.AdditionalComment = string.Empty; + this.Goods_Desc = string.Empty; + } + + } +} \ No newline at end of file diff --git a/应用/Weixin.WPHCirclePromotion/Entitys/fl_plugin_wphcirclepromotion_goodsinfos.cs b/应用/Weixin.WPHCirclePromotion/Entitys/fl_plugin_wphcirclepromotion_goodsinfos.cs new file mode 100644 index 0000000..8427ef3 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Entitys/fl_plugin_wphcirclepromotion_goodsinfos.cs @@ -0,0 +1,74 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Weixin.WPHCirclePromotion.Enums; + +namespace Weixin.WPHCirclePromotion.Entitys +{ + class fl_plugin_wphcirclepromotion_goodsinfos : base_model + { + /// <summary> + /// 商品id + /// </summary> + public string goodsId { get; set; } + /// <summary> + /// 商品标题 + /// </summary> + public string goodsName { get; set; } + /// <summary> + /// 商品描述 + /// </summary> + public string goodsDesc { get; set; } + /// <summary> + /// 商品图片链接 + /// </summary> + public string goodsMainPicture { get; set; } + /// <summary> + /// 市场价(元) + /// </summary> + public double marketPrice { get; set; } + /// <summary> + /// 唯品价(元) + /// </summary> + public double vipPrice { get; set; } + /// <summary> + /// 佣金比例(%) + /// </summary> + public double commissionRate { get; set; } + /// <summary> + /// 佣金金额(元) + /// </summary> + public double commission { get; set; } + /// <summary> + /// 店铺名称 + /// </summary> + public string storeName { get; set; } + /// <summary> + /// 优惠券门槛价格,单位为元 + /// </summary> + public double buy { get; set; } + /// <summary> + /// 优惠金额 + /// </summary> + public double fav { get; set; } + /// <summary> + /// 生成劵的总量 + /// </summary> + public long totalAmount { get; set; } + /// <summary> + /// 发送状态,是否发送过 + /// </summary> + public StateType state { get; set; } + /// <summary> + /// 采集的日期 + /// </summary> + public DateTime cur_time { get; set; } + ///// <summary> + ///// 产品数据的来源 GoodsSourceType枚举 + ///// </summary> + //public GoodsSourceType goods_source { get; set; } + } +} diff --git a/应用/Weixin.WPHCirclePromotion/Entitys/fl_plugin_wphcirclepromotion_wphtgw.cs b/应用/Weixin.WPHCirclePromotion/Entitys/fl_plugin_wphcirclepromotion_wphtgw.cs new file mode 100644 index 0000000..13a8abd --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Entitys/fl_plugin_wphcirclepromotion_wphtgw.cs @@ -0,0 +1,37 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.WPHCirclePromotion.Entitys +{ + /// <summary> + /// 平台推广位设置类 (数据库表) + /// </summary> + class fl_plugin_wphcirclepromotion_wphtgw : base_model + { + /// <summary> + /// 左连接主表 fl_robot_info 的主键 + /// </summary> + public int robot_id { get; set; } + /// <summary> + /// 主推广位CPS名称 + /// </summary> + public string pid_cps_name { get; set; } + /// <summary> + /// 主推广位id + /// </summary> + public string pid { get; set; } + /// <summary> + /// 主推广位昵称 + /// </summary> + public string pid_name { get; set; } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + + } +} \ No newline at end of file diff --git a/应用/Weixin.WPHCirclePromotion/Entitys/wphinfo_temp.cs b/应用/Weixin.WPHCirclePromotion/Entitys/wphinfo_temp.cs new file mode 100644 index 0000000..341506c --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Entitys/wphinfo_temp.cs @@ -0,0 +1,61 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.WPHCirclePromotion.Entitys +{ + public class wphinfo_temp + { + public long ID { get; set; } + /// <summary> + /// 平台类型 + /// </summary> + public ChatType chattype { get; set; } + /// <summary> + /// 用户账号 + /// </summary> + public string name { get; set; } + /// <summary> + /// [昵称] + /// </summary> + public string nick { get; set; } + + /// <summary> + /// 主推广位cps名称 + /// </summary> + private string _adzone_pid_cps_name { get; set; } + public string adzone_pid_cps_name + { + get { return _adzone_pid_cps_name; } + set { _adzone_pid_cps_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + + private string _adzone_pid; + /// <summary> + /// 主推广位id + /// </summary> + public string adzone_pid + { + get { return _adzone_pid; } + set { _adzone_pid = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 主推广位昵称 + /// </summary> + private string _adzone_name; + + public string adzone_name + { + get { return _adzone_name; } + set { _adzone_name = string.IsNullOrEmpty(value) ? string.Empty : value; } + } + /// <summary> + /// 是否禁用 + /// </summary> + public bool onoff { get; set; } + } +} + diff --git a/应用/Weixin.WPHCirclePromotion/Enums.cs b/应用/Weixin.WPHCirclePromotion/Enums.cs new file mode 100644 index 0000000..4fc2692 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Enums.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Weixin.WPHCirclePromotion +{ + public class Enums + { + + public enum StateType + { + 已推广 = 0, + 未推广 = 1 + } + + /// <summary> + /// 频道类型 + /// </summary> + public enum ChannelType + { + 超高佣 = 0, + 出单爆款 = 1 + } + + } +} diff --git a/应用/Weixin.WPHCirclePromotion/MainForm.Designer.cs b/应用/Weixin.WPHCirclePromotion/MainForm.Designer.cs new file mode 100644 index 0000000..4afb9ef --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/MainForm.Designer.cs @@ -0,0 +1,555 @@ +namespace Weixin.WPHCirclePromotion +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.label2 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.settingControl1 = new UI.Framework.Controls.SettingControl(); + this.删除选中项ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有已发ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除所有数据ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.contextMenuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(876, 530); + this.xtraTabControl1.TabIndex = 10; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + this.xtraTabControl1.Selected += new DevExpress.XtraTab.TabPageEventHandler(this.xtraTabControl1_Selected); + this.xtraTabControl1.TabIndexChanged += new System.EventHandler(this.xtraTabControl1_TabIndexChanged); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.label2); + this.xtraTabPage1.Controls.Add(this.pageControl1); + this.xtraTabPage1.Controls.Add(this.gridControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(874, 506); + this.xtraTabPage1.Text = " 数 据 采 集 列 表 "; + // + // label2 + // + this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label2.AutoSize = true; + this.label2.BackColor = System.Drawing.Color.White; + this.label2.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(282, 205); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(303, 35); + this.label2.TabIndex = 13; + this.label2.Text = "数据采集列表为空"; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 470); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(874, 36); + this.pageControl1.TabIndex = 9; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(0, 0); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(874, 468); + this.gridControl1.TabIndex = 8; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn16, + this.gridColumn10, + this.gridColumn1, + this.gridColumn3, + this.gridColumn4, + this.gridColumn18, + this.gridColumn5, + this.gridColumn6, + this.gridColumn7, + this.gridColumn8}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsSelection.MultiSelect = true; + this.gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn16 + // + this.gridColumn16.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn16.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn16.Caption = "店铺名"; + this.gridColumn16.FieldName = "storeName"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 1; + this.gridColumn16.Width = 116; + // + // gridColumn10 + // + this.gridColumn10.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn10.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn10.Caption = "商品ID"; + this.gridColumn10.FieldName = "goodsId"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.OptionsColumn.AllowEdit = false; + this.gridColumn10.OptionsColumn.AllowFocus = false; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 2; + this.gridColumn10.Width = 85; + // + // gridColumn1 + // + this.gridColumn1.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn1.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn1.Caption = "商品标题"; + this.gridColumn1.FieldName = "goodsName"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 3; + this.gridColumn1.Width = 108; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "市场价"; + this.gridColumn3.FieldName = "marketPrice"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 4; + this.gridColumn3.Width = 79; + // + // gridColumn4 + // + this.gridColumn4.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn4.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn4.Caption = "唯品价"; + this.gridColumn4.FieldName = "vipPrice"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 5; + this.gridColumn4.Width = 79; + // + // gridColumn18 + // + this.gridColumn18.Caption = "优惠券金额"; + this.gridColumn18.FieldName = "fav"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 6; + // + // gridColumn5 + // + this.gridColumn5.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn5.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn5.Caption = "优惠券数量"; + this.gridColumn5.FieldName = "totalAmount"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 7; + this.gridColumn5.Width = 81; + // + // gridColumn6 + // + this.gridColumn6.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn6.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn6.Caption = "佣金比例"; + this.gridColumn6.FieldName = "commissionRate"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 8; + this.gridColumn6.Width = 66; + // + // gridColumn7 + // + this.gridColumn7.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn7.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn7.Caption = "发送状态"; + this.gridColumn7.FieldName = "state"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 9; + this.gridColumn7.Width = 54; + // + // gridColumn8 + // + this.gridColumn8.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn8.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn8.Caption = "采集日期"; + this.gridColumn8.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn8.FieldName = "cur_time"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 10; + this.gridColumn8.Width = 100; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.label1); + this.xtraTabPage2.Controls.Add(this.pageControl2); + this.xtraTabPage2.Controls.Add(this.gridControl2); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(874, 506); + this.xtraTabPage2.Text = " 设 置 推 广 位 "; + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("黑体", 26.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(167, 205); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(537, 35); + this.label1.TabIndex = 13; + this.label1.Text = "尚未登录机器人,请先登录机器人"; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 470); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(874, 36); + this.pageControl2.TabIndex = 7; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.Location = new System.Drawing.Point(0, 0); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(870, 461); + this.gridControl2.TabIndex = 6; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn11, + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn17}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView2_RowCellClick); + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn11 + // + this.gridColumn11.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn11.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn11.Caption = "ID"; + this.gridColumn11.FieldName = "ID"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 0; + this.gridColumn11.Width = 50; + // + // gridColumn12 + // + this.gridColumn12.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn12.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn12.Caption = "平台类型"; + this.gridColumn12.FieldName = "chattype"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.OptionsColumn.AllowEdit = false; + this.gridColumn12.OptionsColumn.AllowFocus = false; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 1; + this.gridColumn12.Width = 99; + // + // gridColumn13 + // + this.gridColumn13.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn13.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn13.Caption = "账号"; + this.gridColumn13.FieldName = "name"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.OptionsColumn.AllowFocus = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 2; + this.gridColumn13.Width = 148; + // + // gridColumn14 + // + this.gridColumn14.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn14.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn14.Caption = "账号昵称"; + this.gridColumn14.FieldName = "nick"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.OptionsColumn.AllowFocus = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 3; + this.gridColumn14.Width = 125; + // + // gridColumn15 + // + this.gridColumn15.AppearanceCell.Font = new System.Drawing.Font("Tahoma", 9F, System.Drawing.FontStyle.Underline); + this.gridColumn15.AppearanceCell.ForeColor = System.Drawing.Color.Blue; + this.gridColumn15.AppearanceCell.Options.UseFont = true; + this.gridColumn15.AppearanceCell.Options.UseForeColor = true; + this.gridColumn15.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn15.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn15.Caption = "推广位"; + this.gridColumn15.FieldName = "adzone_name"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 4; + this.gridColumn15.Width = 149; + // + // gridColumn17 + // + this.gridColumn17.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn17.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn17.Caption = "禁止使用"; + this.gridColumn17.FieldName = "onoff"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.OptionsColumn.AllowEdit = false; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 5; + this.gridColumn17.Width = 66; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.settingControl1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(874, 506); + this.xtraTabPage3.Text = " 应 用 设 置 "; + // + // settingControl1 + // + this.settingControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.settingControl1.Location = new System.Drawing.Point(0, 0); + this.settingControl1.Name = "settingControl1"; + this.settingControl1.Size = new System.Drawing.Size(874, 506); + this.settingControl1.TabIndex = 0; + // + // 删除选中项ToolStripMenuItem + // + this.删除选中项ToolStripMenuItem.Name = "删除选中项ToolStripMenuItem"; + this.删除选中项ToolStripMenuItem.Size = new System.Drawing.Size(210, 24); + this.删除选中项ToolStripMenuItem.Text = "删除选中项"; + this.删除选中项ToolStripMenuItem.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // 删除所有已发ToolStripMenuItem + // + this.删除所有已发ToolStripMenuItem.Name = "删除所有已发ToolStripMenuItem"; + this.删除所有已发ToolStripMenuItem.Size = new System.Drawing.Size(210, 24); + this.删除所有已发ToolStripMenuItem.Text = "删除所有已发"; + this.删除所有已发ToolStripMenuItem.Click += new System.EventHandler(this.删除所有已发ToolStripMenuItem_Click); + // + // 删除所有数据ToolStripMenuItem + // + this.删除所有数据ToolStripMenuItem.Name = "删除所有数据ToolStripMenuItem"; + this.删除所有数据ToolStripMenuItem.Size = new System.Drawing.Size(210, 24); + this.删除所有数据ToolStripMenuItem.Text = "删除所有数据"; + this.删除所有数据ToolStripMenuItem.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1, + this.toolStripMenuItem2, + this.toolStripMenuItem3}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(149, 70); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(148, 22); + this.toolStripMenuItem1.Text = "删除选中项"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.删除选中项ToolStripMenuItem_Click); + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + this.toolStripMenuItem2.Size = new System.Drawing.Size(148, 22); + this.toolStripMenuItem2.Text = "删除所有已发"; + this.toolStripMenuItem2.Click += new System.EventHandler(this.删除所有已发ToolStripMenuItem_Click); + // + // toolStripMenuItem3 + // + this.toolStripMenuItem3.Name = "toolStripMenuItem3"; + this.toolStripMenuItem3.Size = new System.Drawing.Size(148, 22); + this.toolStripMenuItem3.Text = "删除所有数据"; + this.toolStripMenuItem3.Click += new System.EventHandler(this.删除所有数据ToolStripMenuItem_Click); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(876, 530); + this.Controls.Add(this.xtraTabControl1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.contextMenuStrip1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.Label label2; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private UI.Framework.Controls.SettingControl settingControl1; + private System.Windows.Forms.ToolStripMenuItem 删除选中项ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有已发ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除所有数据ToolStripMenuItem; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem3; + } +} \ No newline at end of file diff --git a/应用/Weixin.WPHCirclePromotion/MainForm.cs b/应用/Weixin.WPHCirclePromotion/MainForm.cs new file mode 100644 index 0000000..0f2ae00 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/MainForm.cs @@ -0,0 +1,338 @@ +using Api.Framework; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Controls; +using UI.Framework.Forms; +using Weixin.WPHCirclePromotion.Entitys; +using Weixin.WPHCirclePromotion.Properties; + +namespace Weixin.WPHCirclePromotion +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + this.Text = Resources.MainFormTitle; + } + + /// <summary> + /// 窗体关闭 + /// </summary> + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + settingControl1.Bind(Class1.Config, 120); + + #region 加载所有采集到的商品 + pageControl1.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<fl_plugin_wphcirclepromotion_goodsinfos>("select * from fl_plugin_wphcirclepromotion_goodsinfos order by state desc", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl1, 40, true, true); + + label2.Visible = gridView1.RowCount == 0; + + #endregion + + #region 加载所有的账号 + + pageControl2.Bind((page, size) => + { + var session = ApiClient.GetSession(); + var parm = session.NewParamMap(); + parm.setPageParamters(page, size); + var result = session.FindPage<wphinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.唯品联盟}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID where ri.type = 2", parm); + return new PageControl.SerchResult() { Result = result.DataList, Total = result.Total }; + }, gridControl2, 40, true, true); + + label1.Visible = gridView2.RowCount == 0; + #endregion + + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 行单元格单击事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + try + { + #region 双击单元格设置推广位 + var selectRow = gridView2.GetSelectedRows()[0]; + var id = this.gridView2.GetRowCellValue(selectRow, "ID").ToString();//获取列的数据 + //点击数大于2弹出窗体进行推广位的选择 + if (e.Clicks >= 2) + { + if (e.Column.FieldName == "adzone_name") + { + var tgwObj = CpsClient.SelectTuiguangwei(CpsType.唯品联盟); + if (tgwObj != null) + { + var tgw = tgwObj as Tuiguangwei; + var session = ApiClient.GetSession(); + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况 + { + if (e.Column.FieldName == "adzone_name") + { + adzone.adzone_pid_cps_name = tgw.Member.username; + adzone.adzone_pid = tgw.Pid; + adzone.adzone_name = tgw.Name; + } + + session.SaveOrUpdate(adzone); + } + else + { + //session.BeginTransaction(); + try + { + if (e.Column.FieldName == "adzone_name") + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = tgw.Name, //推广位名称 + adzone_pid = tgw.Pid, //推广位pid + adzone_pid_cps_name = tgw.Member.username, //推广位cps名称 + alliance_id = (int)CpsType.唯品联盟, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = false //不禁用 + }; + session.SaveOrUpdate(adzone); + if (0 == adzone.id) + throw new Exception("对不起,推广位设置异常,请稍后重试!"); + //else session.Commit(); + } + catch (Exception ex) + { + //session.Rollback(); + ShowError(ex); + } + } + pageControl2.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + } + } + } + #endregion + + #region 开关单元格双击修改状态 + if (e.Column.FieldName == "onoff") + { + if (e.Clicks == 1) + { + if (!(bool)e.CellValue && MessageBox.Show("该微信推广位确定禁用?", "系统提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) + return; + var session = ApiClient.GetSession(); + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == long.Parse(id)); + if (adzone != null)//数据库中存在的情况,并且推广位设置了 + adzone.onoff = !adzone.onoff; + else + adzone = new fl_adzone_info() + { + custom_type = Resources.SoftwareType, //自定义类型 + adzone_name = string.Empty, //推广位名称 + adzone_pid = string.Empty, //推广位pid + adzone_pid_cps_name = string.Empty, //推广位cps名称 + alliance_id = (int)CpsType.唯品联盟, //联盟id + robot_id = int.Parse(id), //机器人id + group_id = string.Empty, //群id + member_id = 0, //私人id + is_download = false, //不下载 + onoff = true //不禁用 + }; + session.SaveOrUpdate(adzone); + pageControl2.GotoPage(1); + label1.Visible = gridView2.RowCount == 0; + session.FindAdzoneInfos(true); + //session.FindPddCirclePromotions(true); + } + } + #endregion + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// <summary> + /// 修改显示内容的事件 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "adzone_name" && (e.Value == null || string.IsNullOrEmpty(e.Value.ToString()))) e.DisplayText = "双击设置"; + } + catch (Exception ex) + { + ShowError(ex); + return; + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + Util.Save(Class1.Config); + } + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.Caption == "数据来源") + { + var value = e.Value.ToString().ToLower(); + if (value == "0") + e.DisplayText = "文件导入"; + else if (value == "1") + e.DisplayText = "接口采集"; + } + if (e.Column.Caption == "发送状态") + { + var value = e.Value.ToString().ToLower(); + if (value == "true") + e.DisplayText = "未推广"; + else if (value == "false") + e.DisplayText = "已推广"; + } + if (e.Column.Caption == "佣金比例") + e.DisplayText = e.Value.ToString() + "%"; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void xtraTabControl1_TabIndexChanged(object sender, EventArgs e) + { + try + { + pageControl1.GotoPage(1); + label2.Visible = gridView1.RowCount == 0; + } + catch (Exception) + { } + } + + private void xtraTabControl1_Selected(object sender, DevExpress.XtraTab.TabPageEventArgs e) + { + try + { + if (e.PageIndex == 0) + { + pageControl1.GotoPage(); + label2.Visible = gridView1.RowCount == 0; + } + else if (e.PageIndex == 1) + { + pageControl2.GotoPage(); + label1.Visible = gridView2.RowCount == 0; + } + } + catch (Exception) + { + } + } + + private void 删除选中项ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rownumber = gridView1.GetSelectedRows().ToList();//获取选中行号; + if (rownumber != null & rownumber.Count != 0) + { + List<string> goodsids = new List<string>(); + foreach (var item in rownumber) + { + goodsids.Add("'" + gridView1.GetRowCellValue(item, "goodsId").ToString() + "'");//根据行号获取相应行的数据 + } + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from fl_plugin_wphcirclepromotion_goodsinfos where goodsId in (" + string.Join(",", goodsids) + ")"); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 删除所有已发ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_wphcirclepromotion_goodsinfos where state = 0"); + } + + private void 删除所有数据ToolStripMenuItem_Click(object sender, EventArgs e) + { + RemoveGoodsInfos("delete from fl_plugin_wphcirclepromotion_goodsinfos"); + } + + private void RemoveGoodsInfos(string sql) + { + try + { + var session = ApiClient.GetSession(); + session.ExcuteSQL(sql); + pageControl1.GotoPage(1); + ShowSuccess("删除成功"); + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} diff --git a/应用/Weixin.WPHCirclePromotion/MainForm.resx b/应用/Weixin.WPHCirclePromotion/MainForm.resx new file mode 100644 index 0000000..57fb7e1 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/MainForm.resx @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/Weixin.WPHCirclePromotion/Properties/AssemblyInfo.cs b/应用/Weixin.WPHCirclePromotion/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f291df9 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Weixin.WPHCirclePromotion")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Weixin.WPHCirclePromotion")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("1e56f851-0341-4f86-8401-a8b3452f94eb")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/Weixin.WPHCirclePromotion/Properties/Resources.Designer.cs b/应用/Weixin.WPHCirclePromotion/Properties/Resources.Designer.cs new file mode 100644 index 0000000..68331ab --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Weixin.WPHCirclePromotion.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Weixin.WPHCirclePromotion.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找类似 唯品会朋友圈发单 的本地化字符串。 + /// </summary> + internal static string MainFormTitle { + get { + return ResourceManager.GetString("MainFormTitle", resourceCulture); + } + } + + /// <summary> + /// 查找类似 唯品会发单 的本地化字符串。 + /// </summary> + internal static string PluginName { + get { + return ResourceManager.GetString("PluginName", resourceCulture); + } + } + + /// <summary> + /// 查找类似 唯品会发单朋友圈商品发单插件 的本地化字符串。 + /// </summary> + internal static string PluginNote { + get { + return ResourceManager.GetString("PluginNote", resourceCulture); + } + } + + /// <summary> + /// 查找类似 唯品会发单 的本地化字符串。 + /// </summary> + internal static string SoftwareType { + get { + return ResourceManager.GetString("SoftwareType", resourceCulture); + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 唯品会发单 { + get { + object obj = ResourceManager.GetObject("唯品会发单", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/Weixin.WPHCirclePromotion/Properties/Resources.resx b/应用/Weixin.WPHCirclePromotion/Properties/Resources.resx new file mode 100644 index 0000000..7716f62 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Properties/Resources.resx @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="MainFormTitle" xml:space="preserve"> + <value>唯品会朋友圈发单</value> + <comment>设置主窗体标题</comment> + </data> + <data name="PluginName" xml:space="preserve"> + <value>唯品会发单</value> + <comment>插件名</comment> + </data> + <data name="PluginNote" xml:space="preserve"> + <value>唯品会发单朋友圈商品发单插件</value> + <comment>插件介绍</comment> + </data> + <data name="SoftwareType" xml:space="preserve"> + <value>唯品会发单</value> + <comment>fl_adzone_info自定义类型(custom_type)</comment> + </data> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="唯品会发单" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\唯品会发单.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/Weixin.WPHCirclePromotion/Properties/licenses.licx b/应用/Weixin.WPHCirclePromotion/Properties/licenses.licx new file mode 100644 index 0000000..fb06462 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Properties/licenses.licx @@ -0,0 +1 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/Weixin.WPHCirclePromotion/Resources/唯品会发单.png b/应用/Weixin.WPHCirclePromotion/Resources/唯品会发单.png new file mode 100644 index 0000000..fd99f12 Binary files /dev/null and b/应用/Weixin.WPHCirclePromotion/Resources/唯品会发单.png differ diff --git a/应用/Weixin.WPHCirclePromotion/SendCircleFriendThread.cs b/应用/Weixin.WPHCirclePromotion/SendCircleFriendThread.cs new file mode 100644 index 0000000..f70e5bf --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/SendCircleFriendThread.cs @@ -0,0 +1,223 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.Utils; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Weixin.WphCirclePromotion; +using Weixin.WPHCirclePromotion; +using Weixin.WPHCirclePromotion.Entitys; +using Weixin.WPHCirclePromotion.Properties; +using static Weixin.WPHCirclePromotion.Enums; + +namespace Weixin.WPHCirclePromotion +{ + public class SendCircleFriendThread : TimerTask + { + WPHHelper wphHelper = new WPHHelper(); + AnalyzeGoods analyzeGoods = new AnalyzeGoods(); + StringBuilder strb = new StringBuilder(); + bool isSend = false; + bool isSendTime = false;//这里是用来判断是否在任务时间段里面,如果满足这会赋值为true + SqlSugarClient session = ApiClient.GetSession(); + private static object objLock = new object(); + + public override void Run(object state, bool timedOut) + { + #region 定时清空采集的数据 + if (!string.IsNullOrWhiteSpace(Class1.Config.AutoClearTaskTimes)) + { + if (Class1.Config.Auto_IsClear == SwitchType.开启) + { + try + { + if (DateTime.Now.AddSeconds(-3).ToString("HHmm") == DateTime.Parse(Class1.Config.AutoClearTaskTimes).ToString("HHmm")) + { + session.ExcuteSQL("Delete from fl_plugin_wphcirclepromotion_goodsinfos", new { }); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, "定时清理异常" + ex.Message + "-" + ex.StackTrace); + } + } + } + #endregion + + isSendTime = false; + var now = DateTime.Now; + + for (int i = 0; i < Class1.Config.SendTaskTimes.Length; i++) + { + if (!string.IsNullOrWhiteSpace(Class1.Config.SendTaskTimes[i])) + { + var times = Class1.Config.SendTaskTimes[i].Trim().Split('-'); + if (times.Length == 2) + { + var begin = DateTime.Parse(times[0].Trim()); + var end = DateTime.Parse(times[1].Trim()); + if (begin <= now && now <= end) + { + isSendTime = true; + break; + } + } + } + } + if (!isSendTime) return; + + if ((DateTime.Now - Class1.Config.RecordSendTime).TotalMinutes < Class1.Config.Interval_Circle) return; + + try + { + lock (objLock) + { + session.ExcuteSQL("Delete from fl_plugin_wphcirclepromotion_goodsinfos where cur_time <= @time", new { time = DateTime.Today.AddDays(-15) }); + isSend = false; + + #region 采集数据 + if (Class1.Config.Switch == SwitchType.开启) + { + var num = session.Queryable<fl_plugin_wphcirclepromotion_goodsinfos>().Count(f => f.state == StateType.未推广); + if (num <= Class1.Config.GatherTouchNum) + analyzeGoods.GatherFactory(); + } + #endregion + + var goods_infos_temp = new List<fl_plugin_wphcirclepromotion_goodsinfos>(); + + var goods_infos = session.Queryable<fl_plugin_wphcirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).ToPageList(1, (Class1.Config.SendGoodsImageNum <= 0 ? 1 : Class1.Config.SendGoodsImageNum)); + + if (goods_infos != null && goods_infos.Count != 0) + { + var clients = Chat.Framework.ChatClient.WXClient.Values.ToList(); + foreach (var item in clients) + { + try + { + if ((item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信 || item.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信) && item.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + var robot_info = session.FindRobotInfo(item.WeixinHao, ChatType.微信); + if (robot_info != null) + { + var pd_circle_promotion_temp = session.FindWphCirclePromotions().Where(f => f.onoff); + if (pd_circle_promotion_temp != null) + { + if (pd_circle_promotion_temp.FirstOrDefault(f => f.name == robot_info.name) != null) continue; + } + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.SoftwareType && f.robot_id == robot_info.id); + if (adzone != null) + { + var member = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.唯品联盟 && f.username == adzone.adzone_pid_cps_name); + if (member != null) + { + string param = Util.EncryptDES($"fl_{item.WeixinHao}_{(int)ChatType.微信}_CircleF"); + + var api = CpsClient.CreateWeipinhuiRequest(member); + if (api == null) { return; } + strb.Length = 0; + strb.AppendLine(Class1.Config.Content_Circle); + int count = 0; + + for (int i = 0; i < goods_infos.Count; i++) + { + try + { + goods_infos_temp.Add(goods_infos[i]); + var goodsinfo = goods_infos[i]; + count = 0; + Next: + //var result = analyzeGoods.FindGoodsInfoToGoodsId(goods_infos[i].goods_id, GoodsSourceType.对象, member);//获取到自己返利链接等信息 + var result = analyzeGoods.FindGoodsInfoToGoodsId(goods_infos[i].goodsId, member);//获取到自己返利链接等信息 + if (result == null) + { + count++; + if (count <= 5) + { + goodsinfo = session.Queryable<fl_plugin_wphcirclepromotion_goodsinfos>().Where(f => f.state == StateType.未推广).OrderBy(f => f.cur_time, OrderByType.Desc).First(); + goods_infos_temp.Add(goodsinfo); + goto Next; + } + else + continue; + } + else + { + var cprice = (result.vipPrice - result.fav).ToString(); + + var resultTmp = new WPHHelper().GetCpsUrl(api, new { goodsIdList = new List<string>() { goods_infos[i].goodsId }, chanTag = adzone.adzone_pid, requestId = Util.GetUUID(), statParam = param }); + if (resultTmp == null || resultTmp.returnCode == null || resultTmp.returnCode != "0") + throw new Exception("唯品会转链异常"); + + var pict_url = string.IsNullOrWhiteSpace(result.goodsMainPicture) ? string.Empty : $"[图片={result.goodsMainPicture}]"; + + var couponUrl = (resultTmp.result != null && resultTmp.result.urlInfoList.Count != 0) ? resultTmp.result.urlInfoList[0].url : string.Empty; + + if (string.IsNullOrWhiteSpace(couponUrl)) + return; + + var goods_desc = string.IsNullOrWhiteSpace(Class1.Config.Goods_Desc) ? result.goodsDesc : Class1.Config.Goods_Desc + .Replace("劵", "券") + //[商品原价]、[商品唯品价]、[券后唯品价] + .Replace("[商品标题]", result.goodsName) + .Replace("[商品描述]", result.goodsDesc) + .Replace("[店铺名称]", result.storeName) + .Replace("[优惠券门槛金额]", result.buy.ToString("0.00")) + .Replace("[优惠券金额]", result.fav.ToString("0.00")) + .Replace("[优惠券数量]", result.totalAmount.ToString()) + .Replace("[商品原价]", result.marketPrice.ToString("0.00")) + .Replace("[券后唯品价]", cprice) + .Replace("[购买地址地址]", couponUrl) + .Replace("[商品唯品价]", result.vipPrice.ToString("0.00")); + + var image = ApiClient.GetQRImage(result.goodsName, result.vipPrice.ToString("0.00"), result.fav.ToString("0.00"), cprice, result.goodsMainPicture, couponUrl, Class1.Config.Model, CpsType.唯品联盟, result.goodsDesc); //合成附带二维码等信息的宝贝图片 + strb.Append($"[图片={image}]"); + } + } + catch + { } + } + var json = item.SendCircle(strb.ToString()); + if (!string.IsNullOrWhiteSpace(Class1.Config.AdditionalComment)) + { + var reg = Regex.Match(json.Replace("<![CDATA[", "").Replace("]]>", ""), @"<id>(?<id>\d{15,})</id>");//获取返回的朋友圈id + if (reg.Success) + item.SendCircleComment(item.User.Username, reg.Groups["id"].Value, Class1.Config.AdditionalComment); + } + isSend = true;//认定发送过了... + } + } + } + } + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"唯品会推广:{item.WeixinHao},朋友圈推广失败,{ex.Message}"); + } + } + if (isSend) + { + for (int i = 0; i < goods_infos_temp.Count; i++) + { + session.ExcuteSQL("update fl_plugin_wphcirclepromotion_goodsinfos set state = @state where id = @id", new { state = Enums.StateType.已推广, id = goods_infos_temp[i].id }); + } + Class1.Config.RecordSendTime = DateTime.Now; + Util.Save(Class1.Config); + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"唯品会推广:{ex.Message},{ex.StackTrace}"); + } + } + } +} diff --git a/应用/Weixin.WPHCirclePromotion/SessionEx.cs b/应用/Weixin.WPHCirclePromotion/SessionEx.cs new file mode 100644 index 0000000..e963f84 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/SessionEx.cs @@ -0,0 +1,31 @@ +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Weixin.WPHCirclePromotion.Entitys; +using Weixin.WPHCirclePromotion.Properties; + +namespace Weixin.WphCirclePromotion +{ + public static class SessionEx + { + const string pdd_circle_promotion_temp_list = "wph_circle_promotion_temp_list"; + + /// <summary> + /// + /// </summary> + /// <param name="session"></param> + /// <param name="refresh"></param> + /// <returns></returns> + public static List<wphinfo_temp> FindWphCirclePromotions(this SqlSugarClient session, bool refresh = false) + { + return session.Find<wphinfo_temp>($"select ri.id as ID,ri.type as chattype,ri.name as name,ri.nick as nick,flag.adzone_pid as adzone_pid,flag.adzone_name as adzone_name,flag.onoff as onoff,flag.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info ri left join (select r.id as ID,r.type as chattype,r.name as name,r.nick as nick,a.adzone_pid as adzone_pid,a.adzone_name as adzone_name,a.onoff as onoff,a.adzone_pid_cps_name as adzone_pid_cps_name from fl_robot_info r left join fl_adzone_info a on r.id = a.robot_id where alliance_id = '{(int)CpsType.唯品联盟}' and custom_type = '{Resources.SoftwareType}') flag on ri.id = flag.ID"); + } + + } +} diff --git a/应用/Weixin.WPHCirclePromotion/Weixin.WPHCirclePromotion.csproj b/应用/Weixin.WPHCirclePromotion/Weixin.WPHCirclePromotion.csproj new file mode 100644 index 0000000..4eed1b5 --- /dev/null +++ b/应用/Weixin.WPHCirclePromotion/Weixin.WPHCirclePromotion.csproj @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{1E56F851-0341-4F86-8401-A8B3452F94EB}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Weixin.WPHCirclePromotion</RootNamespace> + <AssemblyName>Weixin.WPHCirclePromotion</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Sparkline.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar"> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Core" /> + <Reference Include="System.Data.Linq" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="AnalyzeGoods.cs" /> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Entitys\fl_plugin_wphcirclepromotion_goodsinfos.cs" /> + <Compile Include="Entitys\fl_plugin_wphcirclepromotion_wphtgw.cs" /> + <Compile Include="Entitys\wphinfo_temp.cs" /> + <Compile Include="Enums.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="SendCircleFriendThread.cs" /> + <Compile Include="SessionEx.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\唯品会发单.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/同步老妖联盟上下级关系/Class1.cs b/应用/同步老妖联盟上下级关系/Class1.cs new file mode 100644 index 0000000..808fb88 --- /dev/null +++ b/应用/同步老妖联盟上下级关系/Class1.cs @@ -0,0 +1,77 @@ +using Api.Framework; +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using 同步老妖联盟上下级关系.Properties; + +namespace 同步老妖联盟上下级关系 +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.兔子头像; + this.Name = "同步老妖联盟上下级关系"; + this.Note = "__ __"; + } + + #region 自定义变量 + private MainForm mainForm = null; + #endregion + + public override void Start() + { + //try + //{ + //var session = ApiClient.GetSession(); + //创建配置文件 + //Config = this.ReadConfig<Config>(); + //SDK.WXNewFriendEvent += SDK_WXNewFriendEvent; + //SDK.OrderNoticeEvent += SDK_OrderNoticeEvent; + //SDK.ReciveIMEvent += SDK_ReciveIMEvent; + //} + //catch (Exception ex) + //{ + // this.OnLog(ex.Message); + //} + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/同步老妖联盟上下级关系/Entitys/MemberInfo.cs b/应用/同步老妖联盟上下级关系/Entitys/MemberInfo.cs new file mode 100644 index 0000000..3ea691a --- /dev/null +++ b/应用/同步老妖联盟上下级关系/Entitys/MemberInfo.cs @@ -0,0 +1,107 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 同步老妖联盟上下级关系.Entitys +{ + public class MemberInfo + { + [SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)] + public int id { get; set; } + + /// <summary> + /// 群id + /// </summary> + public string groupid { get; set; } + + /// <summary> + /// 群昵称 + /// </summary> + [SugarColumn(IsNullable = true)] + public string groupnick { get; set; } + + /// <summary> + /// 用户微信id + /// </summary> + public string username { get; set; } + + /// <summary> + /// 微信上看到的微信号 + /// </summary> + [SugarColumn(IsNullable = true)] + public string account { get; set; } = string.Empty; + + /// <summary> + /// 用户昵称 + /// </summary> + [SugarColumn(IsNullable = true)] + public string usernick { get; set; } = string.Empty; + + /// <summary> + /// 性别 (0未知,1男,2女) + /// </summary> + public int sex { get; set; } = -1; + + /// <summary> + /// 头像 + /// </summary> + [SugarColumn(IsNullable = true)] + public string avatar { get; set; } + + /// <summary> + /// 头像md5 + /// </summary> + //[SugarColumn(IsNullable = true)] + //public string avatarMd5 { get; set; } + + /// <summary> + /// 邀请者 + /// </summary> + public int inviter { get; set; } + + /// <summary> + /// 邀请数量 + /// </summary> + public int invited_num { get; set; } + + /// <summary> + /// 发送已拍次数 + /// </summary> + public long yp_count { get; set; } + + /// <summary> + /// 发送已拍时间 + /// </summary> + public long yp_time { get; set; } + + /// <summary> + /// 最后发言时间 + /// </summary> + public long last_speak_time { get; set; } + + /// <summary> + /// 进群时间 + /// </summary> + public long join_time { get; set; } = 0; + + /// <summary> + /// 退群时间 + /// </summary> + public long quit_time { get; set; } + + /// <summary> + /// 机器人账号 + /// </summary> + public string robotname { get; set; } = string.Empty; + + /// <summary> + /// 头像哈希值 + /// </summary> + [SugarColumn(IsNullable = true)] + public string hashid { get; set; } + + } +} diff --git a/应用/同步老妖联盟上下级关系/MainForm.Designer.cs b/应用/同步老妖联盟上下级关系/MainForm.Designer.cs new file mode 100644 index 0000000..b7e6cad --- /dev/null +++ b/应用/同步老妖联盟上下级关系/MainForm.Designer.cs @@ -0,0 +1,187 @@ +namespace 同步老妖联盟上下级关系 +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.button2 = new System.Windows.Forms.Button(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(140, 33); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(270, 21); + this.textBox1.TabIndex = 0; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(423, 32); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 1; + this.button1.Text = "选择"; + this.button1.UseVisualStyleBackColor = true; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(61, 37); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(77, 12); + this.label1.TabIndex = 2; + this.label1.Text = "数据库路径:"; + // + // comboBox1 + // + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(140, 76); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(270, 20); + this.comboBox1.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(85, 79); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(53, 12); + this.label2.TabIndex = 2; + this.label2.Text = "机器人:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(85, 105); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(53, 12); + this.label3.TabIndex = 2; + this.label3.Text = "同步群:"; + // + // comboBox2 + // + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Location = new System.Drawing.Point(140, 102); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(270, 20); + this.comboBox2.TabIndex = 3; + // + // button2 + // + this.button2.Location = new System.Drawing.Point(334, 140); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(91, 34); + this.button2.TabIndex = 1; + this.button2.Text = "同步"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(421, 79); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(29, 12); + this.linkLabel1.TabIndex = 4; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "刷新"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(421, 105); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(29, 12); + this.linkLabel2.TabIndex = 4; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "刷新"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked); + // + // memoEdit1 + // + this.memoEdit1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.memoEdit1.Location = new System.Drawing.Point(0, 198); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(520, 236); + this.memoEdit1.TabIndex = 5; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(520, 434); + this.Controls.Add(this.memoEdit1); + this.Controls.Add(this.linkLabel2); + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.comboBox2); + this.Controls.Add(this.label3); + this.Controls.Add(this.comboBox1); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.MainForm_FormClosed); + this.Load += new System.EventHandler(this.MainForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox comboBox2; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.LinkLabel linkLabel2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + } +} \ No newline at end of file diff --git a/应用/同步老妖联盟上下级关系/MainForm.cs b/应用/同步老妖联盟上下级关系/MainForm.cs new file mode 100644 index 0000000..1dd6446 --- /dev/null +++ b/应用/同步老妖联盟上下级关系/MainForm.cs @@ -0,0 +1,353 @@ +using Api.Framework; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using 同步老妖联盟上下级关系.Entitys; +using 同步老妖联盟上下级关系.Utils; + +namespace 同步老妖联盟上下级关系 +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + try + { + EventLog.LogEvent += EventLog_LogEvent1; + + if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) + { + var path = folderBrowserDialog1.SelectedPath; + if (Directory.Exists(path)) + { + var dataPath = Path.Combine(path, "数据.db"); + if (!File.Exists(dataPath)) throw new Exception("数据库不存在"); + + DBClient.ConnPath = textBox1.Text = dataPath; + + + } + else + throw new Exception("选择的目录路径存在异常"); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + /// <summary> + /// 刷新机器人列表 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + comboBox1.DataSource = null; + + var clients = Chat.Framework.ChatClient.WXClient.Values.Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线 && f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Grpc微信).ToList(); + + var result = new ArrayList(); + result.Add(new TextAndValue("请选择机器人", "请选择机器人")); + foreach (var item in clients) + { + result.Add(new TextAndValue(item.User.Nick, item.WeixinHao)); + } + + comboBox1.DataSource = result; + comboBox1.DisplayMember = "DisplayText"; + comboBox1.ValueMember = "RealValue"; + + comboBox1.SelectedIndex = 0; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message + " - " + ex.StackTrace); + } + } + + /// <summary> + /// 刷新群列表 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + if (comboBox1.SelectedIndex == 0) throw new Exception("请选择机器人"); + + comboBox2.DataSource = null; + + var result = new ArrayList(); + var groupids = DBClient.DbBase.Queryable<MemberInfo>().GroupBy(f => f.groupid).Select(f => f.groupid).ToList(); + + result.Add(new TextAndValue("请选择同步群", "请选择同步群")); + foreach (var groupid in groupids) + { + var temp = DBClient.DbBase.Queryable<MemberInfo>().First(f => f.groupnick != string.Empty && f.groupid == groupid); + if (temp != null) + result.Add(new TextAndValue(temp.groupnick, groupid)); + } + + comboBox2.DataSource = result; + comboBox2.DisplayMember = "DisplayText"; + comboBox2.ValueMember = "RealValue"; + + comboBox2.SelectedIndex = 0; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message + " - " + ex.StackTrace); + } + } + + class TextAndValue + { + private string _RealValue = ""; + private string _DisplayText = ""; + + public string DisplayText + { + get + { + return _DisplayText; + } + } + + public string RealValue + { + get + { + return _RealValue; + } + } + + public TextAndValue(string ShowText, string RealVal) + { + _DisplayText = ShowText; + _RealValue = RealVal; + } + + public override string ToString() + { + return _RealValue.ToString(); + } + + } + + private void button2_Click(object sender, EventArgs e) + { + try + { + if (comboBox1.SelectedIndex == 0) throw new Exception("请选择机器人"); + if (comboBox1.SelectedIndex == 0) throw new Exception("请选择同步群"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + return; + } + + var robotid = comboBox1.SelectedValue.ToString(); + var groupid = comboBox2.SelectedValue.ToString(); + var groupNick = comboBox2.Text.ToString(); + + Task.Run(() => + { + try + { + var t = Task.Run(() => + { + this.Invoke(new Action(() => + { + button2.Enabled = false; + })); + try + { + EventLog.OnEvent(this, $"开始获取机器人..."); + var client = Chat.Framework.ChatClient.WXClient.Values.Where(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线 && f.WeixinType == WeixinType.Grpc微信).FirstOrDefault(f => f.WeixinHao == robotid); + if (client == null) throw new Exception("数据异常"); + + var wx = client as WXClientImpl_IPAD; + if (wx == null) + throw new Exception("异常1"); + EventLog.OnEvent(this, $"获取群{groupid}用户..."); + var members = wx.GetMembers(groupid, true); + EventLog.OnEvent(this, $"获取群用户数量:{(members == null ? 0 : members.Length)}"); + var mInfos = DBClient.DbBase.Queryable<MemberInfo>().Where(f => f.groupid == groupid).ToList(); + EventLog.OnEvent(this, $"获取数据库群{groupid}用户..."); + if (mInfos == null) throw new Exception("获取用户数据为空"); + EventLog.OnEvent(this, $"获取数据库用户数量:{(mInfos == null ? 0 : mInfos.Count)}"); + var mInfosTemp = DBClient.DbBase.Queryable<MemberInfo>().Where(f => f.groupid == groupid).ToList(); + + var invDic = new Dictionary<string, int>(); + EventLog.OnEvent(this, $"开始规整上下级数据...数量:{members.Length}"); + for (int z = 0; z < members.Length; z++) + { + var item = members[z]; + + var tmp = mInfosTemp.FirstOrDefault(f => f.username == item.Username); + if (tmp != null) + mInfosTemp.Remove(tmp); + + var member = mInfos.FirstOrDefault(f => f.groupid == groupid && f.username == item.Username); + if (member == null) + { + member = new MemberInfo() { username = item.Username, groupid = groupid, groupnick = groupNick, avatar = item.SmallHeadImgUrl, join_time = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds, sex = -1 }; + mInfos.Add(member); + } + member.usernick = item.NickName; + member.avatar = item.SmallHeadImgUrl; + member.invited_num = 0; + member.quit_time = 0; + member.inviter = 0; + + if (!string.IsNullOrWhiteSpace(item.InviterUserName)) + { + var iMember = mInfos.FirstOrDefault(f => f.groupid == groupid && f.username == item.InviterUserName); + if (iMember == null) + { + iMember = new MemberInfo() { username = item.InviterUserName, usernick = string.Empty, avatar = string.Empty, join_time = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds, invited_num = 0, sex = -1 }; + var isExist = members.FirstOrDefault(f => f.Username == item.InviterUserName); + if (isExist == null) + iMember.quit_time = iMember.join_time; + + iMember.groupid = groupid; + iMember.groupnick = groupNick; + + iMember = DBClient.DbBase.Insertable(iMember).ExecuteReturnEntity(); + mInfos.Add(iMember); + } + + + if (!invDic.ContainsKey(item.InviterUserName)) + invDic.Add(item.InviterUserName, 1); + else + { + var num = invDic[item.InviterUserName]; + num++; + invDic[item.InviterUserName] = num; + } + + member.inviter = iMember.id; + //result.Add(member); + } + member = DBClient.DbBase.Saveable(member).ExecuteReturnEntity(); + } + EventLog.OnEvent(this, $"保存上下级数据完毕"); + + EventLog.OnEvent(this, $"开始重新计算邀请人数..."); + foreach (KeyValuePair<string, int> item in invDic) + { + var m = DBClient.DbBase.Queryable<MemberInfo>().First(f => f.groupid == groupid && f.username == item.Key); + if (m != null) + { + m.invited_num = item.Value; + DBClient.DbBase.Saveable(m).ExecuteCommand(); + } + else + { + } + } + EventLog.OnEvent(this, $"重新统计邀请人数完毕"); + + foreach (var item in mInfosTemp) + { + item.quit_time = (long)(DateTime.Now - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalMilliseconds; + item.groupnick = groupNick; + item.robotname = client.User.Username; + } + DBClient.DbBase.Saveable(mInfosTemp).ExecuteCommand(); + } + catch (Exception ex) + { + EventClient.OnEvent("异常_", ex.Message + "_" + ex.StackTrace); + } + finally + { + this.Invoke(new Action(() => + { + button2.Enabled = true; + })); + } + }); + Task.WaitAll(t); + EventLog.OnEvent(this, $"同步用户完毕"); + } + catch (Exception ex) + { + EventLog.OnEvent(this, ex.Message + " - " + ex.StackTrace); + } + }); + } + + + private void EventLog_LogEvent1(object sender, LogEvent e) + { + this.Invoke(new Action(() => + { + try + { + if (memoEdit1.Text.Length >= 1000) + { + memoEdit1.Text = memoEdit1.Text.Remove(300); + } + memoEdit1.Text = $@"{e.Message.Trim()} +{memoEdit1.Text}"; + //memoEdit3.SelectionStart = memoEdit3.Text.Length; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message + "__ " + ex.StackTrace); + } + })); + } + + private void MainForm_FormClosed(object sender, FormClosedEventArgs e) + { + + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + EventLog.LogEvent -= EventLog_LogEvent1; + } + } +} diff --git a/应用/同步老妖联盟上下级关系/MainForm.resx b/应用/同步老妖联盟上下级关系/MainForm.resx new file mode 100644 index 0000000..69f943d --- /dev/null +++ b/应用/同步老妖联盟上下级关系/MainForm.resx @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="folderBrowserDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/同步老妖联盟上下级关系/Properties/AssemblyInfo.cs b/应用/同步老妖联盟上下级关系/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0115caa --- /dev/null +++ b/应用/同步老妖联盟上下级关系/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("同步老妖联盟上下级关系")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("同步老妖联盟上下级关系")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("534131c2-ba76-43f6-be09-1ddeafe4ac5c")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/同步老妖联盟上下级关系/Properties/Resources.Designer.cs b/应用/同步老妖联盟上下级关系/Properties/Resources.Designer.cs new file mode 100644 index 0000000..c0c8eb2 --- /dev/null +++ b/应用/同步老妖联盟上下级关系/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace 同步老妖联盟上下级关系.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("同步老妖联盟上下级关系.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap 兔子头像 { + get { + object obj = ResourceManager.GetObject("兔子头像", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/同步老妖联盟上下级关系/Properties/Resources.resx b/应用/同步老妖联盟上下级关系/Properties/Resources.resx new file mode 100644 index 0000000..9686465 --- /dev/null +++ b/应用/同步老妖联盟上下级关系/Properties/Resources.resx @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="兔子头像" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\兔子头像.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/同步老妖联盟上下级关系/Resources/兔子头像.jpg b/应用/同步老妖联盟上下级关系/Resources/兔子头像.jpg new file mode 100644 index 0000000..395b383 Binary files /dev/null and b/应用/同步老妖联盟上下级关系/Resources/兔子头像.jpg differ diff --git a/应用/同步老妖联盟上下级关系/Utils/DBClient.cs b/应用/同步老妖联盟上下级关系/Utils/DBClient.cs new file mode 100644 index 0000000..8935696 --- /dev/null +++ b/应用/同步老妖联盟上下级关系/Utils/DBClient.cs @@ -0,0 +1,32 @@ +using CsharpHttpHelper; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 同步老妖联盟上下级关系.Utils +{ + public class DBClient + { + public static string ConnPath; + public static SqlSugarClient DbBase + { + get + { + return new SqlSugarClient(new ConnectionConfig() + { + ConnectionString = $"Data Source={ConnPath};Version=3;", + DbType = DbType.Sqlite, + IsAutoCloseConnection = true, + InitKeyType = InitKeyType.Attribute + }); + } + } + + + + + } +} diff --git a/应用/同步老妖联盟上下级关系/Utils/EventLog.cs b/应用/同步老妖联盟上下级关系/Utils/EventLog.cs new file mode 100644 index 0000000..4a3bc9c --- /dev/null +++ b/应用/同步老妖联盟上下级关系/Utils/EventLog.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 同步老妖联盟上下级关系.Utils +{ + public class EventLog + { + /// <summary> + /// 日志事件 + /// </summary> + public static event EventHandler<LogEvent> LogEvent; + + public static void OnEvent(object sender, string log) + { + OnEvent(sender, new LogEvent(log)); + } + /// <summary> + /// 输出日志 + /// </summary> + internal static void OnEvent(object sender, LogEvent e) + { + if (LogEvent != null) + { + LogEvent.Invoke(sender, e); + } + } + } + + public class LogEvent : EventArgs + { + public Exception Exception { get; internal set; } + public string Message { get; set; } + public DateTime CrtTime { get; private set; } + public LogEvent(string message) + { + this.Message = message; + this.CrtTime = DateTime.Now; + } + } + +} diff --git a/应用/同步老妖联盟上下级关系/同步老妖联盟上下级关系.csproj b/应用/同步老妖联盟上下级关系/同步老妖联盟上下级关系.csproj new file mode 100644 index 0000000..7813be4 --- /dev/null +++ b/应用/同步老妖联盟上下级关系/同步老妖联盟上下级关系.csproj @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{534131C2-BA76-43F6-BE09-1DDEAFE4AC5C}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>同步老妖联盟上下级关系</RootNamespace> + <AssemblyName>同步老妖联盟上下级关系</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.Sparkline.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" /> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Core" /> + <Reference Include="System.Data.Linq" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Entitys\MemberInfo.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="Utils\DBClient.cs" /> + <Compile Include="Utils\EventLog.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\兔子头像.jpg" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/循环的发消息/Class1.cs b/应用/循环的发消息/Class1.cs new file mode 100644 index 0000000..8d4afe0 --- /dev/null +++ b/应用/循环的发消息/Class1.cs @@ -0,0 +1,136 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using 循环的发消息.Properties; + +namespace 循环的发消息 +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources._1; + this.Name = "循环发送"; + this.Note = ""; + } + + #region 自定义变量 + public static Config Config; + private Form1 mainForm = null; + #endregion + + public override void Start() + { + try + { + //创建配置文件 + Config = this.ReadConfig<Config>(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + static bool state = false; + static bool stop = false; + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + if (e.Message == "b") + stop = true; + if (e.Message == "a") + { + this.OnLog("开始发送..."); + if (!state) + { + var t1 = new Task(() => + { + try + { + state = true; + if (string.IsNullOrWhiteSpace(Config.Users)) throw new Exception("用户不能为空"); + + var users = Config.Users.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + var messs = Config.Content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + for (int i = 0; i < Class1.Config.Num; i++) + { + foreach (var mess in messs) + { + foreach (var m in users) + { + ApiClient.SendMessage(e.RobotInfo, m, mess); + Thread.Sleep(Config.Sleep); + if (stop) + return; + } + } + } + } + catch (Exception) + { } + finally + { + stop = false; + state = false; + } + }, TaskCreationOptions.LongRunning); + + t1.Start(); + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new Form1(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/循环的发消息/Config.cs b/应用/循环的发消息/Config.cs new file mode 100644 index 0000000..6e25857 --- /dev/null +++ b/应用/循环的发消息/Config.cs @@ -0,0 +1,26 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 循环的发消息 +{ + [Config(Name = "插件-循环发送-配置")] + public class Config + { + public string Users { get; set; } = string.Empty; + + public string Content { get; set; } = string.Empty; + + public int Num { get; set; } = 100; + + public int Sleep { get; set; } = 500; + + public Config() + { + + } + } +} diff --git a/应用/循环的发消息/Form1.Designer.cs b/应用/循环的发消息/Form1.Designer.cs new file mode 100644 index 0000000..4f79a6d --- /dev/null +++ b/应用/循环的发消息/Form1.Designer.cs @@ -0,0 +1,186 @@ +namespace 循环的发消息 +{ + partial class Form1 + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.richTextBox2 = new System.Windows.Forms.RichTextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.button1 = new System.Windows.Forms.Button(); + this.numericUpDown2 = new System.Windows.Forms.NumericUpDown(); + this.label4 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit(); + this.SuspendLayout(); + // + // richTextBox2 + // + this.richTextBox2.Location = new System.Drawing.Point(12, 143); + this.richTextBox2.Name = "richTextBox2"; + this.richTextBox2.Size = new System.Drawing.Size(563, 269); + this.richTextBox2.TabIndex = 7; + this.richTextBox2.Text = ""; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 128); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(77, 12); + this.label2.TabIndex = 6; + this.label2.Text = "发送的内容:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 16); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(77, 12); + this.label1.TabIndex = 5; + this.label1.Text = "发送的用户:"; + // + // richTextBox1 + // + this.richTextBox1.Location = new System.Drawing.Point(12, 35); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.Size = new System.Drawing.Size(563, 77); + this.richTextBox1.TabIndex = 4; + this.richTextBox1.Text = ""; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(212, 16); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(77, 12); + this.label3.TabIndex = 8; + this.label3.Text = "发送的次数:"; + // + // numericUpDown1 + // + this.numericUpDown1.Increment = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.numericUpDown1.Location = new System.Drawing.Point(295, 12); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(88, 21); + this.numericUpDown1.TabIndex = 9; + this.numericUpDown1.Value = new decimal(new int[] { + 100, + 0, + 0, + 0}); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(251, 418); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 10; + this.button1.Text = "保存"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // numericUpDown2 + // + this.numericUpDown2.Increment = new decimal(new int[] { + 10, + 0, + 0, + 0}); + this.numericUpDown2.Location = new System.Drawing.Point(486, 12); + this.numericUpDown2.Maximum = new decimal(new int[] { + 1000000000, + 0, + 0, + 0}); + this.numericUpDown2.Name = "numericUpDown2"; + this.numericUpDown2.Size = new System.Drawing.Size(89, 21); + this.numericUpDown2.TabIndex = 12; + this.numericUpDown2.Value = new decimal(new int[] { + 1000, + 0, + 0, + 0}); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(403, 16); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(77, 12); + this.label4.TabIndex = 11; + this.label4.Text = "休眠的时间:"; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(587, 447); + this.Controls.Add(this.numericUpDown2); + this.Controls.Add(this.label4); + this.Controls.Add(this.button1); + this.Controls.Add(this.numericUpDown1); + this.Controls.Add(this.label3); + this.Controls.Add(this.richTextBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.richTextBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "Form1"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Form1"; + this.Load += new System.EventHandler(this.Form1_Load); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.RichTextBox richTextBox2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.NumericUpDown numericUpDown2; + private System.Windows.Forms.Label label4; + } +} \ No newline at end of file diff --git a/应用/循环的发消息/Form1.cs b/应用/循环的发消息/Form1.cs new file mode 100644 index 0000000..7a0dc09 --- /dev/null +++ b/应用/循环的发消息/Form1.cs @@ -0,0 +1,56 @@ +using Api.Framework; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace 循环的发消息 +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + private void Form1_Load(object sender, EventArgs e) + { + this.numericUpDown1.Value = Class1.Config.Num; + this.numericUpDown2.Value = Class1.Config.Sleep; + this.richTextBox1.Text = Class1.Config.Users; + this.richTextBox2.Text = Class1.Config.Content; + } + + private void button1_Click(object sender, EventArgs e) + { + Class1.Config.Num = (int)numericUpDown1.Value; + Class1.Config.Sleep = (int)numericUpDown2.Value; + Class1.Config.Users = richTextBox1.Text; + Class1.Config.Content = richTextBox2.Text; + + Api.Framework.Tools.Util.Save(Class1.Config); + } + } +} diff --git a/应用/循环的发消息/Form1.resx b/应用/循环的发消息/Form1.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/应用/循环的发消息/Form1.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/应用/循环的发消息/Properties/AssemblyInfo.cs b/应用/循环的发消息/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6ed98eb --- /dev/null +++ b/应用/循环的发消息/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("循环的发消息")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("循环的发消息")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("5bd19ccb-7d4e-4207-852d-3b630c57df49")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/循环的发消息/Properties/Resources.Designer.cs b/应用/循环的发消息/Properties/Resources.Designer.cs new file mode 100644 index 0000000..85938cd --- /dev/null +++ b/应用/循环的发消息/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace 循环的发消息.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("循环的发消息.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap _1 { + get { + object obj = ResourceManager.GetObject("_1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/循环的发消息/Properties/Resources.resx b/应用/循环的发消息/Properties/Resources.resx new file mode 100644 index 0000000..4911e8f --- /dev/null +++ b/应用/循环的发消息/Properties/Resources.resx @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="_1" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/循环的发消息/Resources/1.png b/应用/循环的发消息/Resources/1.png new file mode 100644 index 0000000..b3bf2d6 Binary files /dev/null and b/应用/循环的发消息/Resources/1.png differ diff --git a/应用/循环的发消息/循环的发消息.csproj b/应用/循环的发消息/循环的发消息.csproj new file mode 100644 index 0000000..4b4f410 --- /dev/null +++ b/应用/循环的发消息/循环的发消息.csproj @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{5BD19CCB-7D4E-4207-852D-3B630C57DF49}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>循环的发消息</RootNamespace> + <AssemblyName>循环的发消息</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + <TargetFrameworkProfile /> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar"> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Form1.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Form1.Designer.cs"> + <DependentUpon>Form1.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Form1.resx"> + <DependentUpon>Form1.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\1.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/提取xml连接/Class1.cs b/应用/提取xml连接/Class1.cs new file mode 100644 index 0000000..e45cd96 --- /dev/null +++ b/应用/提取xml连接/Class1.cs @@ -0,0 +1,100 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using 提取xml连接.Properties; + +namespace 提取xml连接 +{ + public class Class1 : Plugin + { + public Class1() + { + this.Logo = Resources.Lark20210414_110119; + this.Name = "xml提取地址"; + this.Note = "xml提取地址"; + } + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + Config = this.ReadConfig<Config>(); + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + + + #region 消息事件处理 + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + try + { + + if (e.Message.Trim().Contains("<appmsg")) + { + var url = string.Empty; + var reg = Regex.Match(e.Message, @"((?:<pagepath>(?<链接>[\w\W]+?)</pagepath>)|(?:<url>(?<链接>[\w\W]+?)</url>))", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + var strb = new StringBuilder(); + strb.AppendLine($"用户:{e.NickName}({e.Username})"); + strb.AppendLine($"提取:{reg.Groups["链接"].Value.Replace("<![CDATA[", "").Replace("]]>", "")}"); + strb.AppendLine($"时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); + if (Config.usernames.Contains(e.Username)) + { + e.SendMessage(strb.ToString()); + } + else + this.OnLog(strb.ToString()); + } + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + #endregion + + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + } +} diff --git a/应用/提取xml连接/Config.cs b/应用/提取xml连接/Config.cs new file mode 100644 index 0000000..662ef5e --- /dev/null +++ b/应用/提取xml连接/Config.cs @@ -0,0 +1,15 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 提取xml连接 +{ + [Config(Name = "插件-xml地址提取-配置")] + public class Config + { + public string usernames { get; set; } = string.Empty; + } +} diff --git a/应用/提取xml连接/MainForm.Designer.cs b/应用/提取xml连接/MainForm.Designer.cs new file mode 100644 index 0000000..bb7ae10 --- /dev/null +++ b/应用/提取xml连接/MainForm.Designer.cs @@ -0,0 +1,85 @@ +namespace 提取xml连接 +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(87, 245); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(309, 63); + this.button1.TabIndex = 0; + this.button1.Text = "保存"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(29, 22); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(215, 12); + this.label1.TabIndex = 1; + this.label1.Text = "回复用不wxid: 多账号之间用逗号分隔"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(12, 44); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(465, 182); + this.textBox1.TabIndex = 2; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(505, 335); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.Controls.Add(this.button1); + this.Name = "MainForm"; + this.Text = "MainForm"; + this.Load += new System.EventHandler(this.MainForm_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + } +} \ No newline at end of file diff --git a/应用/提取xml连接/MainForm.cs b/应用/提取xml连接/MainForm.cs new file mode 100644 index 0000000..bc3d92f --- /dev/null +++ b/应用/提取xml连接/MainForm.cs @@ -0,0 +1,60 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace 提取xml连接 +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + textBox1.Text = Class1.Config.usernames; + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + Class1.Config.usernames = textBox1.Text; + + Util.Save(Class1.Config); + + MessageBox.Show($"成功"); + } + catch (Exception ex) + { + MessageBox.Show($"异常:{ex.Message}"); + } + } + } +} diff --git a/应用/提取xml连接/MainForm.resx b/应用/提取xml连接/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/应用/提取xml连接/MainForm.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/应用/提取xml连接/Properties/AssemblyInfo.cs b/应用/提取xml连接/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6f40298 --- /dev/null +++ b/应用/提取xml连接/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("提取xml连接")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("提取xml连接")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("0e394bb3-7552-4048-b344-0d6d7f22236c")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/提取xml连接/Properties/Resources.Designer.cs b/应用/提取xml连接/Properties/Resources.Designer.cs new file mode 100644 index 0000000..4c814de --- /dev/null +++ b/应用/提取xml连接/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace 提取xml连接.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("提取xml连接.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap Lark20210414_110119 { + get { + object obj = ResourceManager.GetObject("Lark20210414_110119", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/提取xml连接/Properties/Resources.resx b/应用/提取xml连接/Properties/Resources.resx new file mode 100644 index 0000000..298f139 --- /dev/null +++ b/应用/提取xml连接/Properties/Resources.resx @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="Lark20210414_110119" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\Lark20210414-110119.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/提取xml连接/Resources/Lark20210414-110119.png b/应用/提取xml连接/Resources/Lark20210414-110119.png new file mode 100644 index 0000000..9d44e60 Binary files /dev/null and b/应用/提取xml连接/Resources/Lark20210414-110119.png differ diff --git a/应用/提取xml连接/提取xml连接.csproj b/应用/提取xml连接/提取xml连接.csproj new file mode 100644 index 0000000..6ce7823 --- /dev/null +++ b/应用/提取xml连接/提取xml连接.csproj @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{0E394BB3-7552-4048-B344-0D6D7F22236C}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>提取xml连接</RootNamespace> + <AssemblyName>提取xml连接</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\Lark20210414-110119.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/监听违规/AddForm.Designer.cs b/应用/监听违规/AddForm.Designer.cs new file mode 100644 index 0000000..230e790 --- /dev/null +++ b/应用/监听违规/AddForm.Designer.cs @@ -0,0 +1,161 @@ +namespace 监听违规 +{ + partial class AddForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.panel1 = new System.Windows.Forms.Panel(); + this.label1 = new System.Windows.Forms.Label(); + this.cb_usertype = new DevExpress.XtraEditors.ComboBoxEdit(); + this.label2 = new System.Windows.Forms.Label(); + this.tb_username = new DevExpress.XtraEditors.TextEdit(); + this.label3 = new System.Windows.Forms.Label(); + this.tb_nick = new DevExpress.XtraEditors.TextEdit(); + this.button1 = new System.Windows.Forms.Button(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.cb_usertype.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.tb_username.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.tb_nick.Properties)).BeginInit(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.button1); + this.panel1.Controls.Add(this.tb_nick); + this.panel1.Controls.Add(this.tb_username); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.cb_usertype); + this.panel1.Controls.Add(this.label2); + this.panel1.Controls.Add(this.label1); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(472, 247); + this.panel1.TabIndex = 0; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(100, 60); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(65, 12); + this.label1.TabIndex = 0; + this.label1.Text = "用户类型:"; + // + // cb_usertype + // + this.cb_usertype.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom))); + this.cb_usertype.EditValue = "黑名单"; + this.cb_usertype.Location = new System.Drawing.Point(172, 55); + this.cb_usertype.Name = "cb_usertype"; + this.cb_usertype.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.cb_usertype.Properties.Items.AddRange(new object[] { + "黑名单", + "白名单"}); + this.cb_usertype.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.cb_usertype.Size = new System.Drawing.Size(176, 20); + this.cb_usertype.TabIndex = 8; + this.cb_usertype.Tag = "comboboxedit"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(100, 95); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(65, 12); + this.label2.TabIndex = 0; + this.label2.Text = "用户账号:"; + // + // tb_username + // + this.tb_username.EditValue = ""; + this.tb_username.Location = new System.Drawing.Point(172, 91); + this.tb_username.Name = "tb_username"; + this.tb_username.Size = new System.Drawing.Size(176, 20); + this.tb_username.TabIndex = 9; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(100, 130); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(65, 12); + this.label3.TabIndex = 0; + this.label3.Text = "用户昵称:"; + // + // tb_nick + // + this.tb_nick.EditValue = ""; + this.tb_nick.Location = new System.Drawing.Point(172, 127); + this.tb_nick.Name = "tb_nick"; + this.tb_nick.Size = new System.Drawing.Size(176, 20); + this.tb_nick.TabIndex = 9; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(141, 171); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(176, 38); + this.button1.TabIndex = 10; + this.button1.Text = " 保 存 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // AddForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(472, 247); + this.Controls.Add(this.panel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AddForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "添加"; + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.cb_usertype.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.tb_username.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.tb_nick.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.ComboBoxEdit cb_usertype; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.TextEdit tb_username; + private DevExpress.XtraEditors.TextEdit tb_nick; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/应用/监听违规/AddForm.cs b/应用/监听违规/AddForm.cs new file mode 100644 index 0000000..e2929bf --- /dev/null +++ b/应用/监听违规/AddForm.cs @@ -0,0 +1,48 @@ +using Api.Framework; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using 监听违规.Entitys; + +namespace 监听违规 +{ + public partial class AddForm : Form + { + public AddForm() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + var username = tb_username.Text; + if (string.IsNullOrWhiteSpace(username)) throw new Exception("用户账号不能为空"); + + var session = ApiClient.GetSession(); + var user = session.FindSingle<UserLists_db>("wxid = @wxid", new { wxid = username }); + if (user != null) throw new Exception("已经存在该用户,无需重复添加"); + + var utype = (UserType)Enum.Parse(typeof(UserType), cb_usertype.Text); + var nick = tb_nick.Text; + + user = new UserLists_db() { wxid = username, user_type = utype, nick_name = nick }; + session.Insertable(user).ExecuteCommand(); + Common.FlushWhiteUserListsCache(true); + MessageBox.Show("添加成功"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + } +} diff --git a/应用/监听违规/AddForm.resx b/应用/监听违规/AddForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/应用/监听违规/AddForm.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root> \ No newline at end of file diff --git a/应用/监听违规/Class1.cs b/应用/监听违规/Class1.cs new file mode 100644 index 0000000..0906630 --- /dev/null +++ b/应用/监听违规/Class1.cs @@ -0,0 +1,339 @@ +using Api.Framework; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using 监听违规.Entitys; +using 监听违规.Properties; + +namespace 监听违规 +{ + public class Class1 : Plugin + { + public Class1() + { + this.Name = "维护工具"; + this.Note = "维护工具"; + this.Logo = Resources._3; + } + + + #region 自定义变量 + public static Config Config; + private MainForm mainForm = null; + #endregion + + public override void Start() + { + try + { + var session = ApiClient.GetSession(); + + #region 判断表是否存在,不存在创建表 + if (!session.TableExist<UserLists_db>()) + { + session.CreateTable<UserLists_db>(); + session.AddIndex<UserLists_db>("wxid");//增加索引.以后数据多了.查询速度会比较快 + session.AddUnique<UserLists_db>("wxid");//增加唯一约束 + } + #endregion + + //创建配置文件 + Config = this.ReadConfig<Config>(); + + SDK.ReciveIMEvent += SDK_ReciveIMEvent; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + private List<string> GetSplit(string str) + { + if (string.IsNullOrWhiteSpace(str)) return null; + try + { + return str.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + return null; + } + + + + + private string Reg_CheckIsUrl = @"(?<链接>((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?)"; + + private void SDK_ReciveIMEvent(object sender, ReciveIMEvent e) + { + if (!string.IsNullOrWhiteSpace(e.Groupid)) + { + if (Regex.IsMatch(e.Message.Trim(), @"<msg>(\s*)?<emoji(.+)</msg>") || (e.Message.Trim().StartsWith(@"<?xml version=") && Regex.IsMatch(e.Message.Trim(), @"<emoticonmd5>(.*?)</emoticonmd5>"))) return; + + var session = ApiClient.GetSession(); + //var white = session.FindSingle<UserLists_db>("wxid = @wxid and user_type", new { wxid = e.Username, user_type = UserType.白名单 }); + if (Common.IsWhite(e.Username)) + return; + + Task.Run(() => + { + var db = ApiClient.GetSession(); + try + { + var client = e.Sender as WeixinBase; + if (client == null) return; + + var black = db.FindSingle<UserLists_db>("wxid = @wxid and user_type", new { wxid = e.Username, user_type = UserType.黑名单 }); + if (black != null) + { + Action(e, client, false); + this.OnLog($"{e.NickName}({e.Username}) 发送消息的用户为黑名单,踢出"); + var member = e.GetMemberinfo(); + if (member != null) + { + member.status = Api.Framework.Enums.MemberType.黑名单; + //e.SendMessage(new VariateReplace().CommonReplace(Config.expelmess, e.GetMemberinfo(), e.RobotInfo)); + db.SaveOrUpdate(member); + + var user = db.FindSingle<UserLists_db>("wxid = @wxid", new { wxid = e.Username }); + if (user == null) + db.Insertable(new UserLists_db() { user_type = UserType.黑名单, wxid = e.Username, nick_name = e.NickName }).ExecuteCommand(); + } + return; + } + + #region 关键词昵称踢人 + if (Config.is_nickkey) + { + var list = GetSplit(Config.nickkey); + if (list != null && list.FirstOrDefault(f => e.NickName.Contains(f)) != null) + { + Action(e, client, false); + //e.SendMessage(new VariateReplace().CommonReplace(Config.expelmess, e.GetMemberinfo(), e.RobotInfo)); + return; + } + } + #endregion + + #region 关键词消息踢人 + if (Config.is_messkey && !e.Message.StartsWith(@"<?xml version=") && !e.Message.StartsWith("[图片=") && !e.Message.StartsWith("[视频=")) + { + var list = GetSplit(Config.messkey); + if (list != null && list.FirstOrDefault(f => e.Message.Contains(f)) != null) + { + Action(e, client); + this.OnLog($"{e.NickName}({e.Username}) 发送的消息包含关键词,踢出"); + return; + } + } + #endregion + + if (!e.Message.Trim().StartsWith(@"<?xml version=", StringComparison.OrdinalIgnoreCase) && !e.Message.Trim().StartsWith("[图片=") && !e.Message.StartsWith("[视频=") && !e.Message.Trim().StartsWith("<msg>", StringComparison.OrdinalIgnoreCase) && !e.Message.Trim().EndsWith("</msg>", StringComparison.OrdinalIgnoreCase)) + { + #region 消息大于多少行踢人 + var rows = e.Message.Split('\n').Length; + if (Config.is_messrows && rows >= Config.messrows) + { + Action(e, client); + this.OnLog($"{e.NickName}({e.Username}) 发送的消息行数大于{Config.messrows},踢出"); + return; + } + #endregion + + #region 消息大于多少字踢人 + if (Config.is_messwords && e.Message.Trim().Length >= Config.messwords) + { + Action(e, client); + this.OnLog($"{e.NickName}({e.Username}) 发送的消息字数大于{Config.messwords},踢出"); + return; + } + #endregion + } + + + #region 发链接、小程序踢人 + if (Config.is_link && ((e.Message.Contains(@"<appmsg appid=") && e.Message.StartsWith(@"<?xml version=")) || Regex.IsMatch(e.Message.Replace("&", "&"), @"(?<链接>((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?)"))) + { + Action(e, client); + this.OnLog($"{e.NickName}({e.Username}) 发送连接或小程序,踢出"); + return; + } + #endregion + + #region 发名片踢人 + if (Config.is_card) + { + if (Regex.IsMatch(e.Message, @"^<\?xml version=.+antispamticket=(.+) />$")) + { + Action(e, client); + this.OnLog($"{e.NickName}({e.Username}) 发送名片,踢出"); + return; + } + } + #endregion + + #region 图片二维码踢人 + if (Config.is_qrcord) + { + //var regs = Regex.Matches(e.Message, Reg_CheckIsUrl); + //if (regs.Count != 0) + //{ + // foreach (Match reg in regs) + // { + // var link = reg.Groups["链接"].Value; + // Bitmap img = null; + // Image mainpic = null; + // try + // { + // string imagePath = string.Empty; + // try + // { + // mainpic = null; + // imagePath = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + // if (!link.StartsWith("http")) link = "http:" + link; + // mainpic = FileTools.DownloadImage(link, imagePath); + // img = new Bitmap(mainpic); + // var QRCodeData = Util.DecodeQRCode(img);//解析机器人二维码,获取到二维码的链接 + // if (!string.IsNullOrWhiteSpace(QRCodeData)) + // { + // client.DeleteGroupMember(e.Username, e.Groupid); + // return; + // } + // } + // catch (Exception ex) + // { + // throw new Exception($"读取文件异常:图片路径 = {imagePath} .{ex.Message} - {ex.StackTrace}"); + // } + // if (mainpic == null) throw new Exception($"下载失败:url = {link}"); + // } + // catch (Exception) + // { + // if (img != null) img.Dispose(); + // if (mainpic != null) mainpic.Dispose(); + // } + // } + //} + + var reg = Regex.Match(e.Message, @"\[图片=(.+?)\]"); + if (reg.Success) + { + var file = reg.Groups[1].Value; + if (!File.Exists(file)) return; + + Bitmap img = null; + //Image mainpic = null; + try + { + string imagePath = string.Empty; + try + { + //mainpic = null; + //imagePath = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + //if (!link.StartsWith("http")) link = "http:" + link; + //mainpic = FileTools.DownloadImage(link, imagePath); + //img = new Bitmap(mainpic); + + img = Util.ReadImageFile(file); + var QRCodeData = Util.DecodeQRCode(img);//解析机器人二维码,获取到二维码的链接 + if (!string.IsNullOrWhiteSpace(QRCodeData)) + { + //client.DeleteGroupMember(e.Username, e.Groupid); + //e.SendMessage(new VariateReplace().CommonReplace(Config.expelmess, e.GetMemberinfo(), e.RobotInfo)); + Action(e, client); + this.OnLog($"{e.NickName}({e.Username}) 发送的图片中带有二维码,踢出"); + return; + } + } + catch (Exception ex) + { + throw new Exception($"读取文件异常:图片路径 = {imagePath} .{ex.Message} - {ex.StackTrace}"); + } + //if (mainpic == null) throw new Exception($"下载失败:url = {link}"); + } + catch (Exception) + { + if (img != null) img.Dispose(); + //if (mainpic != null) mainpic.Dispose(); + } + //} + } + } + #endregion + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + }); + } + } + + public void Action(ReciveIMEvent e, WeixinBase client, bool isSend = true) + { + try + { + string key = "fl_jianting_key_" + e.Username; + var falg = ApiClient.Cache.Get<string>(key); + if (!string.IsNullOrWhiteSpace(falg)) return; + client.DeleteGroupMember(e.Username, e.Groupid); + if (isSend) + e.SendMessage(new VariateReplace().CommonReplace(Config.expelmess, e.GetMemberinfo(), e.RobotInfo)); + ApiClient.Cache.Set(key, "1", 2); + } + catch (Exception ex) + { + this.OnLog("缓存异常:" + ex.Message); + } + } + + + + public override void ShowForm() + { + try + { + if (mainForm == null || mainForm.IsDisposed) + { + mainForm = new MainForm(); + mainForm.Show(); + } + mainForm.TopMost = true; + mainForm.TopMost = false; + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + public override void Stop() + { + try + { + if (mainForm != null) + { + mainForm.CloseForm(); + mainForm = null; + } + } + catch (Exception ex) + { + this.OnLog(ex.Message); + } + } + + } +} diff --git a/应用/监听违规/Common.cs b/应用/监听违规/Common.cs new file mode 100644 index 0000000..6f22cc4 --- /dev/null +++ b/应用/监听违规/Common.cs @@ -0,0 +1,44 @@ +using Api.Framework; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using 监听违规.Entitys; + +namespace 监听违规 +{ + public class Common + { + private static List<UserLists_db> WhiteUserListsCache = null; + + public static void FlushWhiteUserListsCache(bool flush = false) + { + if (flush || WhiteUserListsCache == null) + { + var db = ApiClient.GetSession(); + WhiteUserListsCache = db.Queryable<UserLists_db>().Where(f => f.user_type == UserType.白名单).ToList(); + } + } + + /// <summary> + /// 判断是否是白名单 + /// </summary> + /// <param name="username"></param> + /// <returns></returns> + public static bool IsWhite(string username) + { + try + { + if (WhiteUserListsCache == null) FlushWhiteUserListsCache(); + var user = WhiteUserListsCache.FirstOrDefault(f => f.wxid == username); + return user != null; + } + catch (Exception ex) + { } + return false; + } + + } +} diff --git a/应用/监听违规/Config.cs b/应用/监听违规/Config.cs new file mode 100644 index 0000000..adb2c7d --- /dev/null +++ b/应用/监听违规/Config.cs @@ -0,0 +1,73 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 监听违规 +{ + [Config(Name = "插件-淘宝返利-配置")] + public class Config + { + /// <summary> + /// 是否开启昵称关键词 + /// </summary> + public bool is_nickkey { get; set; } = false; + /// <summary> + /// 昵称关键词 + /// </summary> + public string nickkey { get; set; } = string.Empty; + /// <summary> + /// 是否开启消息关键词 + /// </summary> + public bool is_messkey { get; set; } = false; + /// <summary> + /// 消息关键词 + /// </summary> + public string messkey { get; set; } = string.Empty; + /// <summary> + /// 发送的是否为二维码 + /// </summary> + public bool is_qrcord { get; set; } = false; + /// <summary> + /// 是否发送的卡片 + /// </summary> + public bool is_card { get; set; } = false; + /// <summary> + /// 是否发送的连接 + /// </summary> + public bool is_link { get; set; } = false; + /// <summary> + /// 是否消息行数 + /// </summary> + public bool is_messrows { get; set; } = false; + + /// <summary> + /// 消息行数 + /// </summary> + public int messrows { get; set; } = 5; + + /// <summary> + /// 是否消息字数 + /// </summary> + public bool is_messwords { get; set; } = false; + + /// <summary> + /// 消息字数 + /// </summary> + public int messwords { get; set; } = 60; + + /// <summary> + /// 是否踢出用户提示语 + /// </summary> + public bool is_expelmess { get; set; } + + /// <summary> + /// 踢出用户提示语 + /// </summary> + public string expelmess { get; set; } + + } +} diff --git a/应用/监听违规/Entitys/InviteInfo.cs b/应用/监听违规/Entitys/InviteInfo.cs new file mode 100644 index 0000000..0cacf64 --- /dev/null +++ b/应用/监听违规/Entitys/InviteInfo.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 监听违规.Entitys +{ + public class InviteInfo + { + public int id { get; set; } + + /// <summary> + /// 账号 + /// </summary> + public string Username { get; set; } + /// <summary> + /// 昵称 + /// </summary> + public string Usernick { get; set; } + /// <summary> + /// 头像 + /// </summary> + public string ImgUrl { get; set; } + + /// <summary> + /// 邀请者账号 + /// </summary> + public string InviterUserName { get; set; } + /// <summary> + /// 邀请人昵称 + /// </summary> + public string InviterUsernick { get; set; } + /// <summary> + /// 邀请者头像 + /// </summary> + public string InviterImgUrl { get; set; } + + /// <summary> + /// 自己邀请人数 + /// </summary> + public int InviterNum { get; set; } + + /// <summary> + /// 用户状态 + /// </summary> + public UserType UserType { get; set; } + + /// <summary> + /// 更新时间 + /// </summary> + public DateTime upd_tiem { get; set; } = DateTime.MinValue; + + } +} diff --git a/应用/监听违规/Entitys/UserLists_db.cs b/应用/监听违规/Entitys/UserLists_db.cs new file mode 100644 index 0000000..41e9503 --- /dev/null +++ b/应用/监听违规/Entitys/UserLists_db.cs @@ -0,0 +1,27 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 监听违规.Entitys +{ + public class UserLists_db : base_model + { + /// <summary> + /// 昵称 + /// </summary> + public string nick_name { get; set; } + + /// <summary> + /// 微信id + /// </summary> + public string wxid { get; set; } + + /// <summary> + /// 用户状态 + /// </summary> + public UserType user_type { get; set; } + } +} diff --git a/应用/监听违规/Enums.cs b/应用/监听违规/Enums.cs new file mode 100644 index 0000000..5913467 --- /dev/null +++ b/应用/监听违规/Enums.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace 监听违规 +{ + /// <summary> + /// 用户状态 + /// </summary> + public enum UserType + { + 全部状态 = 0, + 黑名单 = 1, + 白名单 = 2, + } + + +} diff --git a/应用/监听违规/MainForm.Designer.cs b/应用/监听违规/MainForm.Designer.cs new file mode 100644 index 0000000..0b663a4 --- /dev/null +++ b/应用/监听违规/MainForm.Designer.cs @@ -0,0 +1,829 @@ +namespace 监听违规 +{ + partial class MainForm + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.separatorControl1 = new DevExpress.XtraEditors.SeparatorControl(); + this.cb_nickkey = new System.Windows.Forms.CheckBox(); + this.cb_expelmess = new System.Windows.Forms.CheckBox(); + this.cb_messkey = new System.Windows.Forms.CheckBox(); + this.nd_messwords = new System.Windows.Forms.NumericUpDown(); + this.nd_messrows = new System.Windows.Forms.NumericUpDown(); + this.cb_messwords = new System.Windows.Forms.CheckBox(); + this.cb_messrows = new System.Windows.Forms.CheckBox(); + this.cb_link = new System.Windows.Forms.CheckBox(); + this.cb_card = new System.Windows.Forms.CheckBox(); + this.cb_qrcode = new System.Windows.Forms.CheckBox(); + this.tb_expelmess = new System.Windows.Forms.RichTextBox(); + this.tb_messkey = new System.Windows.Forms.RichTextBox(); + this.tb_nickkey = new System.Windows.Forms.RichTextBox(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.添加ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.删除ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn33 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.button1 = new System.Windows.Forms.Button(); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.label3 = new System.Windows.Forms.Label(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit2 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit3 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.repositoryItemPictureEdit1 = new DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.tb_groupid = new DevExpress.XtraEditors.TextEdit(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nd_messwords)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.nd_messrows)).BeginInit(); + this.tabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.tabPage3.SuspendLayout(); + this.tabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.tb_groupid.Properties)).BeginInit(); + this.SuspendLayout(); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Controls.Add(this.tabPage4); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(870, 608); + this.tabControl1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.panel1); + this.tabPage1.Location = new System.Drawing.Point(4, 23); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(862, 581); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = " 踢 人 设 置 "; + this.tabPage1.UseVisualStyleBackColor = true; + // + // panel1 + // + this.panel1.AutoScroll = true; + this.panel1.Controls.Add(this.label2); + this.panel1.Controls.Add(this.label1); + this.panel1.Controls.Add(this.separatorControl1); + this.panel1.Controls.Add(this.cb_nickkey); + this.panel1.Controls.Add(this.cb_expelmess); + this.panel1.Controls.Add(this.cb_messkey); + this.panel1.Controls.Add(this.nd_messwords); + this.panel1.Controls.Add(this.nd_messrows); + this.panel1.Controls.Add(this.cb_messwords); + this.panel1.Controls.Add(this.cb_messrows); + this.panel1.Controls.Add(this.cb_link); + this.panel1.Controls.Add(this.cb_card); + this.panel1.Controls.Add(this.cb_qrcode); + this.panel1.Controls.Add(this.tb_expelmess); + this.panel1.Controls.Add(this.tb_messkey); + this.panel1.Controls.Add(this.tb_nickkey); + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(3, 3); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(856, 575); + this.panel1.TabIndex = 0; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(176, 273); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(55, 14); + this.label2.TabIndex = 8; + this.label2.Text = "逗号分隔"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(176, 110); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 8; + this.label1.Text = "逗号分隔"; + // + // separatorControl1 + // + this.separatorControl1.Location = new System.Drawing.Point(4, 83); + this.separatorControl1.Name = "separatorControl1"; + this.separatorControl1.Size = new System.Drawing.Size(723, 23); + this.separatorControl1.TabIndex = 7; + // + // cb_nickkey + // + this.cb_nickkey.AutoSize = true; + this.cb_nickkey.Location = new System.Drawing.Point(46, 108); + this.cb_nickkey.Name = "cb_nickkey"; + this.cb_nickkey.Size = new System.Drawing.Size(86, 18); + this.cb_nickkey.TabIndex = 6; + this.cb_nickkey.Text = "昵称关键词"; + this.cb_nickkey.UseVisualStyleBackColor = true; + this.cb_nickkey.CheckedChanged += new System.EventHandler(this.cb_nickkey_CheckedChanged); + // + // cb_expelmess + // + this.cb_expelmess.AutoSize = true; + this.cb_expelmess.Location = new System.Drawing.Point(46, 491); + this.cb_expelmess.Name = "cb_expelmess"; + this.cb_expelmess.Size = new System.Drawing.Size(132, 18); + this.cb_expelmess.TabIndex = 6; + this.cb_expelmess.Text = "踢人提示语(可为空)"; + this.cb_expelmess.UseVisualStyleBackColor = true; + this.cb_expelmess.CheckedChanged += new System.EventHandler(this.cb_messkey_CheckedChanged); + // + // cb_messkey + // + this.cb_messkey.AutoSize = true; + this.cb_messkey.Location = new System.Drawing.Point(46, 271); + this.cb_messkey.Name = "cb_messkey"; + this.cb_messkey.Size = new System.Drawing.Size(86, 18); + this.cb_messkey.TabIndex = 6; + this.cb_messkey.Text = "消息关键词"; + this.cb_messkey.UseVisualStyleBackColor = true; + this.cb_messkey.CheckedChanged += new System.EventHandler(this.cb_messkey_CheckedChanged); + // + // nd_messwords + // + this.nd_messwords.Location = new System.Drawing.Point(511, 57); + this.nd_messwords.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.nd_messwords.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nd_messwords.Name = "nd_messwords"; + this.nd_messwords.Size = new System.Drawing.Size(125, 22); + this.nd_messwords.TabIndex = 5; + this.nd_messwords.Value = new decimal(new int[] { + 60, + 0, + 0, + 0}); + // + // nd_messrows + // + this.nd_messrows.Location = new System.Drawing.Point(511, 28); + this.nd_messrows.Maximum = new decimal(new int[] { + 9999999, + 0, + 0, + 0}); + this.nd_messrows.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nd_messrows.Name = "nd_messrows"; + this.nd_messrows.Size = new System.Drawing.Size(125, 22); + this.nd_messrows.TabIndex = 5; + this.nd_messrows.Value = new decimal(new int[] { + 5, + 0, + 0, + 0}); + // + // cb_messwords + // + this.cb_messwords.AutoSize = true; + this.cb_messwords.Location = new System.Drawing.Point(376, 59); + this.cb_messwords.Name = "cb_messwords"; + this.cb_messwords.Size = new System.Drawing.Size(134, 18); + this.cb_messwords.TabIndex = 4; + this.cb_messwords.Text = "消息大于等于多少字"; + this.cb_messwords.UseVisualStyleBackColor = true; + // + // cb_messrows + // + this.cb_messrows.AutoSize = true; + this.cb_messrows.Location = new System.Drawing.Point(376, 30); + this.cb_messrows.Name = "cb_messrows"; + this.cb_messrows.Size = new System.Drawing.Size(134, 18); + this.cb_messrows.TabIndex = 4; + this.cb_messrows.Text = "消息大于等于多少行"; + this.cb_messrows.UseVisualStyleBackColor = true; + // + // cb_link + // + this.cb_link.AutoSize = true; + this.cb_link.Location = new System.Drawing.Point(211, 30); + this.cb_link.Name = "cb_link"; + this.cb_link.Size = new System.Drawing.Size(122, 18); + this.cb_link.TabIndex = 4; + this.cb_link.Text = "发送链接、小程序"; + this.cb_link.UseVisualStyleBackColor = true; + // + // cb_card + // + this.cb_card.AutoSize = true; + this.cb_card.Location = new System.Drawing.Point(46, 59); + this.cb_card.Name = "cb_card"; + this.cb_card.Size = new System.Drawing.Size(62, 18); + this.cb_card.TabIndex = 4; + this.cb_card.Text = "发名片"; + this.cb_card.UseVisualStyleBackColor = true; + // + // cb_qrcode + // + this.cb_qrcode.AutoSize = true; + this.cb_qrcode.Location = new System.Drawing.Point(46, 30); + this.cb_qrcode.Name = "cb_qrcode"; + this.cb_qrcode.Size = new System.Drawing.Size(110, 18); + this.cb_qrcode.TabIndex = 4; + this.cb_qrcode.Text = "图片包含二维码"; + this.cb_qrcode.UseVisualStyleBackColor = true; + // + // tb_expelmess + // + this.tb_expelmess.Location = new System.Drawing.Point(46, 515); + this.tb_expelmess.Name = "tb_expelmess"; + this.tb_expelmess.Size = new System.Drawing.Size(652, 185); + this.tb_expelmess.TabIndex = 3; + this.tb_expelmess.Text = ""; + // + // tb_messkey + // + this.tb_messkey.Location = new System.Drawing.Point(46, 295); + this.tb_messkey.Name = "tb_messkey"; + this.tb_messkey.Size = new System.Drawing.Size(652, 185); + this.tb_messkey.TabIndex = 3; + this.tb_messkey.Text = ""; + // + // tb_nickkey + // + this.tb_nickkey.Location = new System.Drawing.Point(46, 133); + this.tb_nickkey.Name = "tb_nickkey"; + this.tb_nickkey.Size = new System.Drawing.Size(652, 127); + this.tb_nickkey.TabIndex = 2; + this.tb_nickkey.Text = ""; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.pageControl2); + this.tabPage2.Controls.Add(this.gridControl1); + this.tabPage2.Controls.Add(this.simpleButton1); + this.tabPage2.Controls.Add(this.comboBoxEdit1); + this.tabPage2.Controls.Add(this.textEdit1); + this.tabPage2.Location = new System.Drawing.Point(4, 23); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(862, 581); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = " 黑 白 名 单 列 表 "; + this.tabPage2.UseVisualStyleBackColor = true; + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(3, 545); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(856, 33); + this.pageControl2.TabIndex = 10; + // + // gridControl1 + // + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(5, 75); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(728, 402); + this.gridControl1.TabIndex = 9; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.添加ToolStripMenuItem, + this.删除ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(101, 48); + // + // 添加ToolStripMenuItem + // + this.添加ToolStripMenuItem.Name = "添加ToolStripMenuItem"; + this.添加ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.添加ToolStripMenuItem.Text = "添加"; + this.添加ToolStripMenuItem.Click += new System.EventHandler(this.添加ToolStripMenuItem_Click); + // + // 删除ToolStripMenuItem + // + this.删除ToolStripMenuItem.Name = "删除ToolStripMenuItem"; + this.删除ToolStripMenuItem.Size = new System.Drawing.Size(100, 22); + this.删除ToolStripMenuItem.Text = "删除"; + this.删除ToolStripMenuItem.Click += new System.EventHandler(this.删除ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn14, + this.gridColumn21, + this.gridColumn33}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ColumnAutoWidth = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView1_CustomUnboundColumnData); + // + // gridColumn14 + // + this.gridColumn14.Caption = "微信ID"; + this.gridColumn14.FieldName = "wxid"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 0; + this.gridColumn14.Width = 194; + // + // gridColumn21 + // + this.gridColumn21.Caption = "微信昵称"; + this.gridColumn21.FieldName = "nick_name"; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 1; + this.gridColumn21.Width = 198; + // + // gridColumn33 + // + this.gridColumn33.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn33.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn33.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn33.Caption = "用户状态"; + this.gridColumn33.DisplayFormat.FormatString = "{0}"; + this.gridColumn33.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Custom; + this.gridColumn33.FieldName = "ssss"; + this.gridColumn33.Name = "gridColumn33"; + this.gridColumn33.OptionsColumn.AllowEdit = false; + this.gridColumn33.OptionsColumn.AllowFocus = false; + this.gridColumn33.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn33.Visible = true; + this.gridColumn33.VisibleIndex = 2; + this.gridColumn33.Width = 199; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(452, 27); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(96, 31); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "搜 索"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // comboBoxEdit1 + // + this.comboBoxEdit1.EditValue = "全部状态"; + this.comboBoxEdit1.Location = new System.Drawing.Point(336, 32); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "全部状态", + "黑名单", + "白名单"}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(92, 20); + this.comboBoxEdit1.TabIndex = 7; + this.comboBoxEdit1.Tag = "comboboxedit"; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(138, 32); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(182, 20); + this.textEdit1.TabIndex = 6; + this.textEdit1.Tag = "textedit"; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.button1); + this.tabPage3.Location = new System.Drawing.Point(4, 23); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Padding = new System.Windows.Forms.Padding(3); + this.tabPage3.Size = new System.Drawing.Size(862, 581); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = " 临 时 导 入 "; + this.tabPage3.UseVisualStyleBackColor = true; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(173, 111); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(403, 118); + this.button1.TabIndex = 0; + this.button1.Text = " 导 入 外 部 数 据 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // tabPage4 + // + this.tabPage4.Controls.Add(this.linkLabel1); + this.tabPage4.Controls.Add(this.label3); + this.tabPage4.Controls.Add(this.gridControl2); + this.tabPage4.Controls.Add(this.simpleButton2); + this.tabPage4.Controls.Add(this.comboBoxEdit2); + this.tabPage4.Controls.Add(this.tb_groupid); + this.tabPage4.Location = new System.Drawing.Point(4, 23); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Padding = new System.Windows.Forms.Padding(3); + this.tabPage4.Size = new System.Drawing.Size(862, 581); + this.tabPage4.TabIndex = 3; + this.tabPage4.Text = " 数 据 统 计 "; + this.tabPage4.UseVisualStyleBackColor = true; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(506, 31); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(91, 14); + this.linkLabel1.TabIndex = 15; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "刷新机器人列表"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(77, 31); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(40, 14); + this.label3.TabIndex = 14; + this.label3.Text = "群id:"; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl2.Location = new System.Drawing.Point(2, 73); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.RepositoryItems.AddRange(new DevExpress.XtraEditors.Repository.RepositoryItem[] { + this.repositoryItemPictureEdit1, + this.repositoryItemPictureEdit2, + this.repositoryItemPictureEdit3}); + this.gridControl2.Size = new System.Drawing.Size(807, 408); + this.gridControl2.TabIndex = 13; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem1}); + this.contextMenuStrip2.Name = "contextMenuStrip1"; + this.contextMenuStrip2.Size = new System.Drawing.Size(149, 26); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(148, 22); + this.toolStripMenuItem1.Text = "踢出选中用户"; + this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn6, + this.gridColumn4, + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn5, + this.gridColumn7, + this.gridColumn8}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsSelection.MultiSelect = true; + this.gridView2.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.CheckBoxRowSelect; + this.gridView2.OptionsView.ColumnAutoWidth = false; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.CustomUnboundColumnData += new DevExpress.XtraGrid.Views.Base.CustomColumnDataEventHandler(this.gridView2_CustomUnboundColumnData); + // + // gridColumn6 + // + this.gridColumn6.Caption = "序号"; + this.gridColumn6.FieldName = "id"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 1; + this.gridColumn6.Width = 50; + // + // gridColumn4 + // + this.gridColumn4.Caption = "_"; + this.gridColumn4.ColumnEdit = this.repositoryItemPictureEdit2; + this.gridColumn4.FieldName = "ddd"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.UnboundType = DevExpress.Data.UnboundColumnType.Object; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 2; + this.gridColumn4.Width = 25; + // + // repositoryItemPictureEdit2 + // + this.repositoryItemPictureEdit2.CustomHeight = 100; + this.repositoryItemPictureEdit2.Name = "repositoryItemPictureEdit2"; + this.repositoryItemPictureEdit2.SizeMode = DevExpress.XtraEditors.Controls.PictureSizeMode.Stretch; + // + // gridColumn1 + // + this.gridColumn1.Caption = "用户信息"; + this.gridColumn1.FieldName = "gridColumn1"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 3; + this.gridColumn1.Width = 163; + // + // gridColumn2 + // + this.gridColumn2.Caption = "邀请人数"; + this.gridColumn2.FieldName = "InviterNum"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 4; + this.gridColumn2.Width = 82; + // + // gridColumn3 + // + this.gridColumn3.AppearanceCell.Options.UseTextOptions = true; + this.gridColumn3.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.AppearanceHeader.Options.UseTextOptions = true; + this.gridColumn3.AppearanceHeader.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridColumn3.Caption = "__"; + this.gridColumn3.ColumnEdit = this.repositoryItemPictureEdit3; + this.gridColumn3.FieldName = "ffff"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.UnboundType = DevExpress.Data.UnboundColumnType.Object; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 5; + this.gridColumn3.Width = 25; + // + // repositoryItemPictureEdit3 + // + this.repositoryItemPictureEdit3.CustomHeight = 100; + this.repositoryItemPictureEdit3.Name = "repositoryItemPictureEdit3"; + this.repositoryItemPictureEdit3.SizeMode = DevExpress.XtraEditors.Controls.PictureSizeMode.Stretch; + // + // gridColumn5 + // + this.gridColumn5.Caption = "被谁拉进的群"; + this.gridColumn5.FieldName = "gridColumn5"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.UnboundType = DevExpress.Data.UnboundColumnType.String; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 6; + this.gridColumn5.Width = 192; + // + // gridColumn7 + // + this.gridColumn7.Caption = "状态"; + this.gridColumn7.FieldName = "sss"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.UnboundType = DevExpress.Data.UnboundColumnType.Object; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 7; + this.gridColumn7.Width = 56; + // + // gridColumn8 + // + this.gridColumn8.Caption = "最后发言时间"; + this.gridColumn8.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn8.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn8.FieldName = "upd_tiem"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 8; + this.gridColumn8.Width = 148; + // + // repositoryItemPictureEdit1 + // + this.repositoryItemPictureEdit1.CustomHeight = 100; + this.repositoryItemPictureEdit1.Name = "repositoryItemPictureEdit1"; + this.repositoryItemPictureEdit1.SizeMode = DevExpress.XtraEditors.Controls.PictureSizeMode.Stretch; + // + // simpleButton2 + // + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(687, 23); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(96, 31); + this.simpleButton2.TabIndex = 12; + this.simpleButton2.Text = "搜 索"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // comboBoxEdit2 + // + this.comboBoxEdit2.EditValue = "请选择对应机器人"; + this.comboBoxEdit2.Location = new System.Drawing.Point(335, 28); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.Items.AddRange(new object[] { + "请选择对应机器人"}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(169, 20); + this.comboBoxEdit2.TabIndex = 11; + this.comboBoxEdit2.Tag = "comboboxedit"; + // + // tb_groupid + // + this.tb_groupid.Location = new System.Drawing.Point(123, 28); + this.tb_groupid.Name = "tb_groupid"; + this.tb_groupid.Size = new System.Drawing.Size(196, 20); + this.tb_groupid.TabIndex = 10; + this.tb_groupid.Tag = "textedit"; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(870, 608); + this.Controls.Add(this.tabControl1); + this.Name = "MainForm"; + this.Text = "主程序"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Load += new System.EventHandler(this.MainForm_Load); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.separatorControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nd_messwords)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.nd_messrows)).EndInit(); + this.tabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.tabPage3.ResumeLayout(false); + this.tabPage4.ResumeLayout(false); + this.tabPage4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.repositoryItemPictureEdit1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.tb_groupid.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.CheckBox cb_link; + private System.Windows.Forms.CheckBox cb_card; + private System.Windows.Forms.CheckBox cb_qrcode; + private System.Windows.Forms.RichTextBox tb_messkey; + private System.Windows.Forms.RichTextBox tb_nickkey; + private System.Windows.Forms.CheckBox cb_messkey; + private System.Windows.Forms.NumericUpDown nd_messwords; + private System.Windows.Forms.NumericUpDown nd_messrows; + private System.Windows.Forms.CheckBox cb_messwords; + private System.Windows.Forms.CheckBox cb_messrows; + private System.Windows.Forms.CheckBox cb_nickkey; + private DevExpress.XtraEditors.SeparatorControl separatorControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn33; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 添加ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 删除ToolStripMenuItem; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.RichTextBox tb_expelmess; + private System.Windows.Forms.CheckBox cb_expelmess; + private System.Windows.Forms.TabPage tabPage4; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private DevExpress.XtraEditors.TextEdit tb_groupid; + private System.Windows.Forms.Label label3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit2; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit repositoryItemPictureEdit1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private System.Windows.Forms.LinkLabel linkLabel1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + } +} \ No newline at end of file diff --git a/应用/监听违规/MainForm.cs b/应用/监听违规/MainForm.cs new file mode 100644 index 0000000..a652b70 --- /dev/null +++ b/应用/监听违规/MainForm.cs @@ -0,0 +1,479 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Api.Framework.Tools; +using Api.Framework; +using 监听违规.Entitys; +using SqlSugar; +using System.IO; +using CsharpHttpHelper; +using Newtonsoft.Json.Linq; +using Chat.Framework.WXSdk.Implement; +using Chat.Framework; +using Api.Framework.Model; +using Api.Framework.SDK; +using DevExpress.Utils; +using System.Threading; + +namespace 监听违规 +{ + public partial class MainForm : BaseForm + { + public MainForm() + { + InitializeComponent(); + } + + public void CloseForm() + { + try + { + if (!this.IsDisposed) + { + this.Invoke(new Action(delegate + { + this.Close(); + this.Dispose(); + })); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void MainForm_Load(object sender, EventArgs e) + { + cb_qrcode.Checked = Class1.Config.is_qrcord; + cb_card.Checked = Class1.Config.is_card; + cb_link.Checked = Class1.Config.is_link; + cb_messrows.Checked = Class1.Config.is_messrows; + nd_messrows.Value = Class1.Config.messrows; + cb_messwords.Checked = Class1.Config.is_messwords; + nd_messwords.Value = Class1.Config.messwords; + cb_nickkey.Checked = Class1.Config.is_nickkey; + tb_nickkey.Text = Class1.Config.nickkey; + cb_messkey.Checked = Class1.Config.is_messkey; + tb_messkey.Text = Class1.Config.messkey; + cb_expelmess.Checked = Class1.Config.is_expelmess; + tb_expelmess.Text = Class1.Config.expelmess; + + linkLabel1_LinkClicked(null, null); + + pageControl2.Bind(SerchData, this.gridControl1, 1000, false, true); + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + Class1.Config.is_qrcord = cb_qrcode.Checked; + Class1.Config.is_card = cb_card.Checked; + Class1.Config.is_link = cb_link.Checked; + Class1.Config.is_messrows = cb_messrows.Checked; + Class1.Config.messrows = (int)nd_messrows.Value; + Class1.Config.is_messwords = cb_messwords.Checked; + Class1.Config.messwords = (int)nd_messwords.Value; + Class1.Config.is_nickkey = cb_nickkey.Checked; + Class1.Config.nickkey = tb_nickkey.Text; + Class1.Config.is_messkey = cb_messkey.Checked; + Class1.Config.messkey = tb_messkey.Text; + Class1.Config.is_expelmess = cb_expelmess.Checked; + Class1.Config.expelmess = tb_expelmess.Text; + + Util.Save(Class1.Config); + } + catch (Exception ex) + { } + } + + private void cb_nickkey_CheckedChanged(object sender, EventArgs e) + { + + } + + private void cb_messkey_CheckedChanged(object sender, EventArgs e) + { + + } + + private UI.Framework.Controls.PageControl.SerchResult SerchData(int index, int pagesize) + { + try + { + var session = ApiClient.GetSession(); + var conModels = new List<IConditionalModel>(); + + var utype = (UserType)Enum.Parse(typeof(UserType), comboBoxEdit1.Text); + if (utype != UserType.全部状态) + conModels.Add(new ConditionalModel() { FieldName = "user_type", ConditionalType = ConditionalType.Equal, FieldValue = ((int)utype).ToString() }); + + string where = string.Empty; + string keyword = this.textEdit1.Text.Trim(); + if (!string.IsNullOrEmpty(keyword)) + conModels.Add(new ConditionalModel() { FieldName = "wxid", ConditionalType = ConditionalType.Equal, FieldValue = keyword }); + + //总记录数 + int totalNumber = 0; + var result = session.Queryable<UserLists_db>().Where(conModels).ToPageList(index, pagesize, ref totalNumber); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = totalNumber }; + } + catch (Exception ex) + { + if (!this.IsDisposed) + this.UpdateUI(() => + { + BaseForm.ShowError(ex); + }); + } + return null; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.pageControl2.Go(sender, e); + } + + private void 删除ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = this.gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var info = this.gridView1.GetRow(rows[0]) as UserLists_db; + if (XtraMessageBox.Show("您确定要删除选中数据嘛?\r\n" + info.wxid, "友情提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var session = ApiClient.GetSession(); + session.ExcuteSQL("delete from UserLists_db where id=" + info.id); + Common.FlushWhiteUserListsCache(true); + } + this.pageControl2.GotoPage(1); + + } + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void 添加ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + new AddForm().ShowDialog(); + this.pageControl2.GotoPage(1); + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void button1_Click(object sender, EventArgs e) + { + button1.Enabled = false; + + OpenFileDialog dialog = new OpenFileDialog(); + dialog.Multiselect = false; + dialog.Title = "请选择文件"; + dialog.Filter = "所有文件(*.json)|*.json"; + if (dialog.ShowDialog() == DialogResult.OK) + { + var t = Task.Run(() => + { + var db = ApiClient.GetSession(); + try + { + db.BeginTransaction(); + var json = File.ReadAllText(dialog.FileName); + var jArr = JArray.Parse(json); + + var list = new List<UserLists_db>(); + foreach (var item in jArr) + { + var data = (JObject)item; + //var wxid = data["wxid"].ToString().Trim(); + //if (string.IsNullOrWhiteSpace(wxid)) continue; + //if (list.FirstOrDefault(f => f.wxid == wxid) != null) continue; + var nick = data["nick_name"].ToString(); + list.Add(new UserLists_db() { nick_name = Util.RemoveEmoji(nick), user_type = UserType.黑名单, wxid = data["wxid"].ToString() }); + } + EventClient.OnEvent(null, "读取完成,正在插入"); + var _num1 = (int)Math.Ceiling((decimal)list.Count / 100m); + for (int o = 1; o <= _num1; o++) + { + var _list = list.Skip((o - 1) * 100).Take(100).ToList(); + try + { + db.Insertable(_list).ExecuteCommand(); + } + catch (Exception ex) + { + EventClient.OnEvent(null, "插入失败,插入 " + o * 100); + } + } + db.Commit(); + ShowSuccessAutoClose("导入成功"); + + } + catch (Exception ex) + { + db.Rollback(); + ShowError(ex); + } + finally + { + this.Invoke(new Action(() => + { + button1.Enabled = true; + })); + } + }); + //Task.WaitAll(t); + } + } + + private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + try + { + var row = e.Row as UserLists_db; + if (e.Column.Caption == "用户状态") + e.Value = row.user_type.ToString(); + } + catch (Exception ex) + { + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + if (comboBoxEdit2.SelectedIndex == 0) + { + MessageBox.Show("请选择机器人"); + return; + } + + if (string.IsNullOrWhiteSpace(tb_groupid.Text)) + { + MessageBox.Show("请填写群id"); + return; + } + var robotInfo = comboBoxEdit2.Text; + simpleButton2.Enabled = false; + Task.Run(() => + { + try + { + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinType == WeixinType.Grpc微信 && f.Status == Chat.Framework.WXSdk.WxStatus.在线 && robotInfo.Contains("(" + f.WeixinHao + ")")); + if (wx == null) throw new Exception("机器人已经离线或一会再试"); + var members = wx.GetMembers(tb_groupid.Text, true); + if (members == null) throw new Exception($"获取群({robotInfo})用户失败"); + + var session = ApiClient.GetSession(); + + var inviteInfos = new List<InviteInfo>(); + + for (int z = 0; z < members.Length; z++) + { + var item = members[z]; + + UserType userType = UserType.全部状态; + #region 判断数据中是否存在这个用户 + var member = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = item.Username }); + if (member == null) + { + member = new fl_member_info() { crt_time = DateTime.Now, usernick = item.NickName, robot_name = wx.WeixinHao, robot_type = wx.WeixinType == WeixinType.QYHook微信 ? ChatType.企业微信 : ChatType.微信, username = item.Username, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + session.SaveOrUpdate(member); + } + + if (member.is_cloud_black || member.status == Api.Framework.Enums.MemberType.黑名单) + userType = UserType.黑名单; + else if (member.status == Api.Framework.Enums.MemberType.白名单) + userType = UserType.白名单; + if (userType == UserType.全部状态) + { + var black = session.FindSingle<UserLists_db>("wxid = @wxid and user_type", new { wxid = item.Username }); + if (black != null) + userType = black.user_type; + } + #endregion + + inviteInfos.Add(new InviteInfo() { ImgUrl = item.SmallHeadImgUrl, Username = item.Username, Usernick = item.NickName, InviterUserName = item.InviterUserName, InviterNum = 0, UserType = userType, upd_tiem = member.upd_time }); + } + + int o = 1; + foreach (var user in inviteInfos) + { + user.id = o; + o++; + var inviterNum = inviteInfos.Count(f => f.InviterUserName == user.Username); + + user.InviterNum = inviterNum; + + if (!string.IsNullOrWhiteSpace(user.ImgUrl)) + { + var fileName = Util.MapFile(user.Username + ".jpg", "Cache\\image"); + if (!File.Exists(fileName)) + FileTools.DownloadImage(user.ImgUrl, fileName); + user.ImgUrl = fileName; + } + + if (!string.IsNullOrWhiteSpace(user.InviterUserName)) + { + var iUser = inviteInfos.FirstOrDefault(f => f.Username == user.InviterUserName); + if (iUser == null) continue; + user.InviterUsernick = iUser.Usernick; + user.InviterImgUrl = iUser.ImgUrl; + + if (!string.IsNullOrWhiteSpace(user.InviterImgUrl)) + { + var fileName = Util.MapFile(user.InviterUserName + ".jpg", "Cache\\image"); + if (!File.Exists(fileName)) + FileTools.DownloadImage(user.InviterImgUrl, fileName); + user.InviterImgUrl = fileName; + } + } + } + + //inviteInfos = inviteInfos.OrderByDescending(f => f.InviterNum).ToList(); + //int o = 1; + //foreach (var item in inviteInfos) + //{ + // item.id = o; + // o++; + //} + + this.Invoke(new Action(() => + { + gridControl2.DataSource = inviteInfos; + })); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + finally + { + this.Invoke(new Action(() => + { + simpleButton2.Enabled = true; + })); + } + }); + } + + private void gridView2_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) + { + try + { + var row = e.Row as InviteInfo; + if (e.Column.Caption == "用户信息") + e.Value = $"{row.Usernick}({row.Username})"; + else if (e.Column.Caption == "被谁拉进的群") + { + if (string.IsNullOrWhiteSpace(row.InviterUserName)) return; + e.Value = $"{row.InviterUsernick}({row.InviterUserName})"; + } + else if (e.Column.Caption == "_") + { + Image img = null; + try + { + if (!string.IsNullOrWhiteSpace(row.ImgUrl)) + img = Image.FromFile(row.ImgUrl); + } + catch (Exception ee) + { + //MessageBox.Show(ee.Message); + } + + e.Value = img; + } + else if (e.Column.Caption == "__") + { + Image img = null; + try + { + if (!string.IsNullOrWhiteSpace(row.InviterImgUrl)) + img = Image.FromFile(row.InviterImgUrl); + } + catch (Exception ee) + { + //MessageBox.Show(ee.Message); + } + + e.Value = img; + } + else if (e.Column.Caption == "状态") + { + if (row.UserType == UserType.全部状态) + e.Value = string.Empty; + else + e.Value = row.UserType.ToString(); + } + } + catch (Exception ex) + { + } + } + + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + comboBoxEdit2.Properties.Items.Clear(); + comboBoxEdit2.Properties.Items.Add("请选择对应机器人"); + var clients = ChatClient.WXClient.Values.Where(f => f.WeixinType == WeixinType.Grpc微信 && f.Status == Chat.Framework.WXSdk.WxStatus.在线); + foreach (var client in clients) + comboBoxEdit2.Properties.Items.Add($"{client.User.Nick.ToString()}({client.WeixinHao})"); + } + + private void toolStripMenuItem1_Click(object sender, EventArgs e) + { + try + { + int[] rows = this.gridView2.GetSelectedRows();//获取选中行号 + if (rows != null && rows.Length > 0) + { + if (MessageBox.Show("确定要踢出选中的用户吗?", "问题提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1) != DialogResult.OK) + return; + var groupid = tb_groupid.Text.Trim(); + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.WeixinType == WeixinType.Grpc微信 && f.Status == Chat.Framework.WXSdk.WxStatus.在线 && comboBoxEdit2.Text.Contains("(" + f.WeixinHao + ")")); + if (wx == null) throw new Exception("机器人已经离线或一会再试"); + + for (int i = 0; i < rows.Length; i++) + { + try + { + var row = this.gridView2.GetRow(rows[i]) as InviteInfo; + if (row == null) continue; + wx.DeleteGroupMember(row.Username, groupid); + Thread.Sleep(50); + } + catch (Exception ex) + { } + } + simpleButton2_Click(null, null); + MessageBox.Show("选中用户已全部踢出"); + } + else throw new Exception("没有选中的用户"); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + } +} \ No newline at end of file diff --git a/应用/监听违规/MainForm.resx b/应用/监听违规/MainForm.resx new file mode 100644 index 0000000..6bd63c2 --- /dev/null +++ b/应用/监听违规/MainForm.resx @@ -0,0 +1,175 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <metadata name="Loding.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>17, 17</value> + </metadata> + <metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>109, 17</value> + </metadata> + <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> + <data name="simpleButton1.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <metadata name="contextMenuStrip2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> + <value>274, 17</value> + </metadata> + <data name="simpleButton2.ImageOptions.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAt0RVh0VGl0 + bGUAWm9vbTvPCf68AAADeklEQVQ4T3WTX0yTVxjGD2iGJgreLNmNGnfhonHuhg0yFYOCZGzRgk7T4CBE + lAWYJtTYiKWIBfotaAWGgiJqsQUGpaOFydwI6R/4aIuFroAbDmRxCHRYKwwQiuTZ+xVNdrM3+eV87znn + eb73/GMAAlCsunzdEH67nm9S6xzj6qaHuNvo8FRprcb8Ym0Ujb9DBL2dL/+2SdCwQBIbfyzkhsaSr7vv + 9v8+8jdm5xapG4H2t2EPNHrH6wKVviQ8MnYDSYIFzdl87YoBxarKe+aCny1D8C8t4yf+KeQVPTiRb0Iu + ta2df2Ju3o+6ZjukCk0dzV9LBGVIqwNidqWi9ZOGFpf/1cISuDt9yFZ1g3d68GO3F+fvjOAkZ0NBdS+m + fHNQftcC8YlLiSRbnXr6+opBhdraPDA0gTb6c3aJDTM+P8YmFtE/Mg+jbRrcD1PIUtnR8Msw2kz9SMks + bSfZWvEp1YrBNbVlXFjr2XIeVuckxiYX4X4yD8vAPzD2vISqbQplbc+QXdqFodEpJKWXvCDZ+oRkjhlP + RjBWcsuE18vLSFF24EGfF+7ROZgfzaC1bxoa3osq83PU2nxILzZhdHwaR1KLhSML+0KsYPez9jLGlT/w + zMwuQFLZDWnjEzQ6fTC4XkJt9+Im/xzf9/mgsXsgrbKh99E4SDgtGMQdyWOtGXsYu6DU6+y9o6g304ZV + 2qHomARn9aDC4UVdvw/NQzNQGgZR2/EHanRd2C+SmslgXUyCjBnSdzOWdqYsXsbpqTwfZLVOZNY4cdny + F2oGvbjtnMAlQz84vQuOwQkcTuEQvic5jQxC9otymD5tF31S8lVmeS1X1gLXYw/UpsfIqe/BqapOyBse + QmsZBu9+hoxzNyHNkID7fHshaUKJ4MbUTwMGQe9/ELHhoFhRmpx1bVmt48H/Ogb3iBddrqe4oTVBdLwQ + 8szTWBioRI8qCYVx2wpIt14wefsOgok1kTHpB6i09tjEvIWYxDxab64/Kl5i/ijymFi2d4vSUnQUcHHo + LkqAPHorR5qw/z6mIGI1IVxVwT3sDeuIECJUErGxqF0WD3RKYJUdgCJuRyHbJ7rIokV5LPpQLiFj0Qcv + vCGH8hy279D5ABRClaFf73yPM36zG4uGJFR/GT4rDPxvaJM+ZsqozUyxaxO7GLlJ6AqYJG99V3E1dvsS + 99mH2n8BS6wgHnYivPsAAAAASUVORK5CYII= +</value> + </data> + <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> + <value>59</value> + </metadata> +</root> \ No newline at end of file diff --git a/应用/监听违规/Properties/AssemblyInfo.cs b/应用/监听违规/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..2e7a5fc --- /dev/null +++ b/应用/监听违规/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("监听违规")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("监听违规")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("242e7fa6-3518-4e73-9899-0a309bf8410c")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/监听违规/Properties/Resources.Designer.cs b/应用/监听违规/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7261072 --- /dev/null +++ b/应用/监听违规/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace 监听违规.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("监听违规.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// </summary> + internal static System.Drawing.Bitmap _3 { + get { + object obj = ResourceManager.GetObject("_3", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/应用/监听违规/Properties/Resources.resx b/应用/监听违规/Properties/Resources.resx new file mode 100644 index 0000000..40c318d --- /dev/null +++ b/应用/监听违规/Properties/Resources.resx @@ -0,0 +1,124 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="_3" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root> \ No newline at end of file diff --git a/应用/监听违规/Properties/licenses.licx b/应用/监听违规/Properties/licenses.licx new file mode 100644 index 0000000..71688f5 --- /dev/null +++ b/应用/监听违规/Properties/licenses.licx @@ -0,0 +1,4 @@ +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.Repository.RepositoryItemPictureEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/应用/监听违规/Resources/3.png b/应用/监听违规/Resources/3.png new file mode 100644 index 0000000..24b01db Binary files /dev/null and b/应用/监听违规/Resources/3.png differ diff --git a/应用/监听违规/监听违规.csproj b/应用/监听违规/监听违规.csproj new file mode 100644 index 0000000..c54a1e2 --- /dev/null +++ b/应用/监听违规/监听违规.csproj @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{242E7FA6-3518-4E73-9899-0A309BF8410C}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>监听违规</RootNamespace> + <AssemblyName>监听违规</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar"> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="UI.Framework"> + <HintPath>..\..\Debug\UI.Framework.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="AddForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="AddForm.Designer.cs"> + <DependentUpon>AddForm.cs</DependentUpon> + </Compile> + <Compile Include="Class1.cs" /> + <Compile Include="Common.cs" /> + <Compile Include="Config.cs" /> + <Compile Include="Entitys\InviteInfo.cs" /> + <Compile Include="Entitys\UserLists_db.cs" /> + <Compile Include="Enums.cs" /> + <Compile Include="MainForm.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="MainForm.Designer.cs"> + <DependentUpon>MainForm.cs</DependentUpon> + </Compile> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="AddForm.resx"> + <DependentUpon>AddForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="MainForm.resx"> + <DependentUpon>MainForm.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Resources\3.png" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/应用/群成员监控/Class1.cs b/应用/群成员监控/Class1.cs new file mode 100644 index 0000000..c8defbe --- /dev/null +++ b/应用/群成员监控/Class1.cs @@ -0,0 +1,68 @@ +using Api.Framework.SDK; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CsharpHttpHelper; +namespace 群成员监控 +{ + public class Class1:Plugin + { + public Class1() + { + this.Name = "群成员监控"; + } + public override void Start() + { + SDK.WXNewMemerEvent += SDK_WXNewMemerEvent; + SDK.WXReceiveGroupMsgEvent += SDK_WXReceiveGroupMsgEvent; + base.Start(); + } + + private void SDK_WXReceiveGroupMsgEvent(object sender, Chat.Framework.WXSdk.Events.WXReceiveGroupMsg e) + { + if (e.Message.Contains("邀请朋友进群")) + { + Upload(e.Group.UserName, e.Client); + } + } + + private void SDK_WXNewMemerEvent(object sender, Chat.Framework.WXSdk.Events.WXNewMemer e) + { + Upload(e.GroupId,e.Client); + } + + private void Upload(string groupid, WeixinBase client) + { + Task.Run(()=> { + try + { + System.Threading.Thread.Sleep(5000); + GroupMember[] Members = client.GetMembers(groupid, true); + if (Members != null && Members.Length != 0) + { + var members = new List<object>(); + foreach (var item in Members) members.Add(new { username = item.Username, nickname = item.NickName, logo = item.SmallHeadImgUrl, invitername = item.InviterUserName }); + var obj = new { groupid = groupid, members = members }; + var http = new CsharpHttpHelper.HttpHelper(); + + var data = Convert.ToBase64String(Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(obj))); + var x = http.GetItem("http://www.xindaogou.net/Create/UploadGroups", "", System.Web.HttpUtility.UrlEncode(data)); + x.Timeout = 1000 * 20; + + this.OnLog("上传结果:" + http.GetHtml(x).Html); + } + else throw new Exception("没有提取到,群成员数据!"); + } + catch (Exception ex) + { + this.OnLog("上传失败:" + ex.Message); + } + + }); + } + } +} diff --git a/应用/群成员监控/Properties/AssemblyInfo.cs b/应用/群成员监控/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7f2a69f --- /dev/null +++ b/应用/群成员监控/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("群成员监控")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("群成员监控")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("3eb20a81-87c6-4bfa-a66c-dddb57806e09")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/应用/群成员监控/群成员监控.csproj b/应用/群成员监控/群成员监控.csproj new file mode 100644 index 0000000..5d14912 --- /dev/null +++ b/应用/群成员监控/群成员监控.csproj @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{3EB20A81-87C6-4BFA-A66C-DDDB57806E09}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>群成员监控</RootNamespace> + <AssemblyName>群成员监控</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <Deterministic>true</Deterministic> + <TargetFrameworkProfile /> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\Plugin\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Api.Framework"> + <HintPath>..\..\Debug\Api.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Chat.Framework"> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="HttpHelper"> + <HintPath>..\..\Debug\HttpHelper.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Web" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Class1.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/易转发自修复/App.config b/易转发自修复/App.config new file mode 100644 index 0000000..74ade9d --- /dev/null +++ b/易转发自修复/App.config @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> + </startup> +</configuration> diff --git a/易转发自修复/Program.cs b/易转发自修复/Program.cs new file mode 100644 index 0000000..9fafd67 --- /dev/null +++ b/易转发自修复/Program.cs @@ -0,0 +1,335 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; +using 易转发自修复.Properties; + +namespace 易转发自修复 +{ + class Program + { + static void Main(string[] args) + { + try + { + Console.ForegroundColor = ConsoleColor.Green; + Console.WriteLine("正在检测软件运行环境..."); + var path = Environment.CurrentDirectory; + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("正在检测是否有运行的软件"); + + #region 关闭运行的程序 + Process[] MyProcesses = Process.GetProcesses(); + var proNames = new List<string>() { "PCRobot".ToLower(), "VersionUpdate".ToLower() }; + string selfName = Process.GetCurrentProcess().MainModule.ModuleName.ToLower(); + + var di = new DirectoryInfo(path); + foreach (var file in di.GetFiles()) + { + if (file.Name.ToLower().StartsWith(selfName)) + continue; + var reg = Regex.Match(file.Name, @"(.+).exe.config", RegexOptions.IgnoreCase); + if (reg.Success) + { + proNames.Add(reg.Groups[1].Value.ToLower()); + } + } + + foreach (Process MyProcess in MyProcesses) + { + try + { + var name = MyProcess.ProcessName.ToLower(); + foreach (var proName in proNames) + { + if (name == proName && MyProcess.MainModule.FileName.StartsWith(path)) + { + try + { + Console.WriteLine($"关闭运行中的软件:{MyProcess.Id},路径:{MyProcess.MainModule.FileName},进程名称:{name}"); + MyProcess.Kill(); + } + catch (Exception) + { } + } + } + } + catch (Exception ex) + { + Console.WriteLine($"未知异常:{ex.Message} - {ex.StackTrace}"); + } + } + #endregion + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine($"正在检测更新配置文件状态"); + #region 检查配置文件 + var vuName = "VersionUpdate"; + var xml = path + $@"\{vuName}.xml"; + + for (int i = 0; i < 3; i++) + { + try + { + if (File.Exists(xml)) + try { File.Delete(xml); } catch { } + FileStream fs = new FileStream(xml, FileMode.OpenOrCreate, FileAccess.ReadWrite); + StreamWriter sw = new StreamWriter(fs); + sw.Write(Resources.VersionUpdate1); + sw.Flush(); + sw.Close(); + if (File.Exists(xml)) + break; + } + catch (Exception) + { } + } + #endregion + + var exe = path + $@"\{vuName}.exe"; + if (File.Exists(exe)) + try { File.Delete(exe); } catch { } + + Console.WriteLine($"正在检测更新程序"); + WriteResource(exe, Resources.VersionUpdate); + + try + { + MapPath(@"Cache\VersionUpdate"); + var versions = GetVersions(xml); + if (versions.Count > 0) + { + Console.ForegroundColor = ConsoleColor.White; + foreach (var item in versions) + { + Console.WriteLine("下载文件:" + $@"{path}\Cache\VersionUpdate\{item.Name}_{item.Version}.zip"); + DownloadFile(item.Url, $@"{path}\Cache\VersionUpdate\{item.Name}_{item.Version}.zip"); + } + } + } + catch (Exception ex) + { } + Console.ForegroundColor = ConsoleColor.Black; + Console.WriteLine("修复完毕!!!!"); + StartProcess("VersionUpdate.exe", "易转发.exe"); + for (int i = 5; i < 1; i++) + { + Console.WriteLine($"{i}秒后自动退出"); + Thread.Sleep(1000); + } + } + catch (Exception) + { } + } + + public static void WriteResource(string fileName, byte[] writeData) + { + var writeDataStr = BitConverter.ToString(writeData); + if (File.Exists(fileName)) + { + var oldFile = File.ReadAllBytes(fileName); + var oldFileStr = BitConverter.ToString(oldFile);//将字节数组装换为字符串 + if (writeDataStr != oldFileStr) + { + File.WriteAllBytes(fileName, writeData); + } + } + else File.WriteAllBytes(fileName, writeData); + } + + public static string MapPath(string path = "", bool CreateDirectory = true) + { + if (string.IsNullOrWhiteSpace(path)) + { + return Environment.CurrentDirectory + "\\"; + } + path = Path.Combine(Environment.CurrentDirectory + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + return path; + } + + public static List<UpdateClass> GetVersions(string XMLPath) + { + List<UpdateClass> msgs = new List<UpdateClass>(); + try + { + XmlDocument XmlDoc = new XmlDocument(); + + if (!File.Exists(XMLPath)) throw new Exception("找不到VersionUpdate.xml必备文件!"); + //使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件. + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + XmlNode xn = XmlDoc.SelectSingleNode("Files"); + // 得到根节点的所有子节点 + XmlNodeList xnl = xn.ChildNodes; + foreach (XmlNode node in xnl) + { + try + { + var Name = node.Attributes["Name"].Value; + var Url = node.Attributes["Url"].Value; + var CurVersion = Version.Parse(node.Attributes["Version"].Value); + + XmlDocument temp_xml = new XmlDocument(); + temp_xml.Load(Url); + var temp_node = temp_xml.SelectSingleNode("History"); + + var temp_datas = temp_node.SelectNodes("Data"); + //更新内容 + List<XmlNode> temp_update = new List<XmlNode>(); + foreach (XmlNode item in temp_datas) + { + var ver = Version.Parse(item.Attributes["Ver"].Value); + if (ver > CurVersion) + { + //发现有更新 + temp_update.Add(item); + } + } + + if (temp_update.Count > 0) + { + var MSG = new UpdateClass() { Name = Name, Url = temp_update[0].Attributes["Url"].Value, Message = new List<string>(), Version = temp_update[0].Attributes["Ver"].Value }; + msgs.Add(MSG); + foreach (var item in temp_update) + { + var temps = item.Attributes["Msg"].Value.Split(new string[] { "[br]" }, StringSplitOptions.None); + foreach (var temp in temps) MSG.Message.Add(temp); + } + } + } + catch (Exception) + { + + } + } + } + } + catch (Exception) + { } + return msgs; + } + + public static bool DownloadFile(string URL, string filename) + { + try + { + float percent = 0; + if (File.Exists(filename)) File.Delete(filename); + + Stream st = null; + Stream so = null; + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + + totalDownloadedByte = osize + totalDownloadedByte; + //Application.DoEvents(); + so.Write(by, 0, osize); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + //Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + return true; + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + catch (Exception ex) + { + } + return false; + } + + public class UpdateClass + { + public string Name { get; set; } + public string Url { get; set; } + public string Version { get; set; } + public List<string> Message { get; set; } + } + + public static bool StartProcess(string filename, string param = null) + { + try + { + if (!File.Exists(filename)) + return false; + + try + { + if (!System.IO.File.Exists(filename)) + return false; + + if (param != null) + System.Diagnostics.Process.Start(filename, param); + else + System.Diagnostics.Process.Start(filename); + System.Threading.Thread.Sleep(100); + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + } + } +} diff --git a/易转发自修复/Properties/AssemblyInfo.cs b/易转发自修复/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..bbfabb6 --- /dev/null +++ b/易转发自修复/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("易转发自修复")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("易转发自修复")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("58ff110b-fdbc-4b53-b714-c3b171915616")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/易转发自修复/Properties/Resources.Designer.cs b/易转发自修复/Properties/Resources.Designer.cs new file mode 100644 index 0000000..3386a64 --- /dev/null +++ b/易转发自修复/Properties/Resources.Designer.cs @@ -0,0 +1,86 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace 易转发自修复.Properties { + using System; + + + /// <summary> + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// </summary> + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("易转发自修复.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// 查找 System.Byte[] 类型的本地化资源。 + /// </summary> + internal static byte[] VersionUpdate { + get { + object obj = ResourceManager.GetObject("VersionUpdate", resourceCulture); + return ((byte[])(obj)); + } + } + + /// <summary> + /// 查找类似 <?xml version="1.0" encoding="utf-8"?> + ///<Files> + /// <File Name="PCWechat" Version="2020.03.17.1" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=PCWechatUpdate" /> + /// <File Name="PCRobot" Version="2021.10.02.1008" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=PCRobotUpdate" /> + ///</Files> 的本地化字符串。 + /// </summary> + internal static string VersionUpdate1 { + get { + return ResourceManager.GetString("VersionUpdate1", resourceCulture); + } + } + } +} diff --git a/易转发自修复/Properties/Resources.resx b/易转发自修复/Properties/Resources.resx new file mode 100644 index 0000000..b5e4be5 --- /dev/null +++ b/易转发自修复/Properties/Resources.resx @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="VersionUpdate" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\VersionUpdate.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </data> + <data name="VersionUpdate1" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\VersionUpdate.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value> + </data> +</root> \ No newline at end of file diff --git a/易转发自修复/Resources/VersionUpdate.exe b/易转发自修复/Resources/VersionUpdate.exe new file mode 100644 index 0000000..a02a963 Binary files /dev/null and b/易转发自修复/Resources/VersionUpdate.exe differ diff --git a/易转发自修复/Resources/VersionUpdate.xml b/易转发自修复/Resources/VersionUpdate.xml new file mode 100644 index 0000000..5124d2e --- /dev/null +++ b/易转发自修复/Resources/VersionUpdate.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<Files> + <File Name="PCWechat" Version="2020.03.17.1" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=PCWechatUpdate" /> + <File Name="PCRobot" Version="2021.10.02.1008" Url="http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=PCRobotUpdate" /> +</Files> \ No newline at end of file diff --git a/易转发自修复/app.manifest b/易转发自修复/app.manifest new file mode 100644 index 0000000..60a45a2 --- /dev/null +++ b/易转发自修复/app.manifest @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8"?> +<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> + <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> + <security> + <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> + <!-- UAC 清单选项 + 如果想要更改 Windows 用户帐户控制级别,请使用 + 以下节点之一替换 requestedExecutionLevel 节点。n + <requestedExecutionLevel level="asInvoker" uiAccess="false" /> + <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> + <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> + + 指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。 + 如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此 + 元素。 + --> + <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> + </requestedPrivileges> + </security> + </trustInfo> + + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的 + Windows 版本的列表。取消评论适当的元素, + Windows 将自动选择最兼容的环境。 --> + + <!-- Windows Vista --> + <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />--> + + <!-- Windows 7 --> + <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />--> + + <!-- Windows 8 --> + <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />--> + + <!-- Windows 8.1 --> + <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />--> + + <!-- Windows 10 --> + <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />--> + + </application> + </compatibility> + + <!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行 + 自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需 + 选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应 + 在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。--> + <!-- + <application xmlns="urn:schemas-microsoft-com:asm.v3"> + <windowsSettings> + <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> + </windowsSettings> + </application> + --> + + <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) --> + <!-- + <dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="*" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> + </dependency> + --> + +</assembly> diff --git a/易转发自修复/修复620.ico b/易转发自修复/修复620.ico new file mode 100644 index 0000000..9add55c Binary files /dev/null and b/易转发自修复/修复620.ico differ diff --git a/易转发自修复/易转发自修复.csproj b/易转发自修复/易转发自修复.csproj new file mode 100644 index 0000000..90a6e61 --- /dev/null +++ b/易转发自修复/易转发自修复.csproj @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{58FF110B-FDBC-4B53-B714-C3B171915616}</ProjectGuid> + <OutputType>Exe</OutputType> + <RootNamespace>易转发自修复</RootNamespace> + <AssemblyName>软件异常点我修复</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> + <Deterministic>true</Deterministic> + <TargetFrameworkProfile /> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\PCRobot\bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup> + <ApplicationIcon>修复620.ico</ApplicationIcon> + </PropertyGroup> + <PropertyGroup> + <ApplicationManifest>app.manifest</ApplicationManifest> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="app.manifest" /> + <None Include="Resources\VersionUpdate.xml" /> + <None Include="Resources\VersionUpdate.exe" /> + <Content Include="修复620.ico" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/类库/Api.Framework/Api.Framework.csproj b/类库/Api.Framework/Api.Framework.csproj new file mode 100644 index 0000000..fdef88f --- /dev/null +++ b/类库/Api.Framework/Api.Framework.csproj @@ -0,0 +1,744 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{DFC8CD58-A475-4EBB-8A0E-0F1EE71EDA07}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Api.Framework</RootNamespace> + <AssemblyName>Api.Framework</AssemblyName> + <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <NuGetPackageImportStamp> + </NuGetPackageImportStamp> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>0</WarningLevel> + <PlatformTarget>x86</PlatformTarget> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <DocumentationFile>..\..\Debug\Api.Framework.xml</DocumentationFile> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup> + <StartupObject /> + </PropertyGroup> + <ItemGroup> + <Reference Include="AdvancedStringBuilder"> + <HintPath>..\..\DLL\AdvancedStringBuilder.dll</HintPath> + </Reference> + <Reference Include="BouncyCastle.Crypto, Version=1.8.3.0, Culture=neutral, PublicKeyToken=0e99375e54769942"> + <HintPath>..\..\packages\BouncyCastle.1.8.3.1\lib\BouncyCastle.Crypto.dll</HintPath> + </Reference> + <Reference Include="Chat.Framework, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\Chat.Framework.dll</HintPath> + <Private>True</Private> + </Reference> + <Reference Include="ClearScript.Core"> + <HintPath>..\..\DLL\ClearScript.Core.dll</HintPath> + </Reference> + <Reference Include="ClearScript.V8"> + <HintPath>..\..\DLL\ClearScript.V8.dll</HintPath> + </Reference> + <Reference Include="DevExpress.Data.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.Printing.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.Sparkline.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.Utils.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL"> + <Private>False</Private> + </Reference> + <Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" /> + <Reference Include="DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" /> + <Reference Include="DevExpress.XtraLayout.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.XtraPrinting.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="DevExpress.XtraScheduler.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" /> + <Reference Include="DevExpress.XtraScheduler.v19.2.Core, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" /> + <Reference Include="EO.Base, Version=21.3.18.0, Culture=neutral, PublicKeyToken=e92353a6bf73fffc, processorArchitecture=MSIL"> + <HintPath>..\..\packages\EO.WebBrowser.21.3.18\lib\EO.Base.dll</HintPath> + </Reference> + <Reference Include="EO.WebBrowser, Version=21.3.18.0, Culture=neutral, PublicKeyToken=e92353a6bf73fffc, processorArchitecture=MSIL"> + <HintPath>..\..\packages\EO.WebBrowser.21.3.18\lib\EO.WebBrowser.dll</HintPath> + </Reference> + <Reference Include="EO.WebBrowser.WinForm, Version=21.3.18.0, Culture=neutral, PublicKeyToken=e92353a6bf73fffc, processorArchitecture=MSIL"> + <HintPath>..\..\packages\EO.WebBrowser.WinForm.21.3.18\lib\EO.WebBrowser.WinForm.dll</HintPath> + </Reference> + <Reference Include="EO.WebEngine, Version=21.3.18.0, Culture=neutral, PublicKeyToken=e92353a6bf73fffc, processorArchitecture=MSIL"> + <HintPath>..\..\packages\EO.WebBrowser.21.3.18\lib\EO.WebEngine.dll</HintPath> + </Reference> + <Reference Include="Google.Protobuf, Version=3.7.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Google.Protobuf.3.7.0\lib\net45\Google.Protobuf.dll</HintPath> + </Reference> + <Reference Include="Grant.Framework"> + <HintPath>..\Debug\Grant.Framework.dll</HintPath> + </Reference> + <Reference Include="HtmlAgilityPack, Version=1.8.9.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\HtmlAgilityPack.dll</HintPath> + </Reference> + <Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\ICSharpCode.SharpZipLib.dll</HintPath> + </Reference> + <Reference Include="Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\Ionic.Zip.dll</HintPath> + </Reference> + <Reference Include="JavaScriptEngineSwitcher.Core"> + <HintPath>..\..\DLL\JavaScriptEngineSwitcher.Core.dll</HintPath> + </Reference> + <Reference Include="K4os.Compression.LZ4, Version=1.1.11.0, Culture=neutral, PublicKeyToken=2186fa9121ef231d, processorArchitecture=MSIL"> + <HintPath>..\..\packages\K4os.Compression.LZ4.1.1.11\lib\net46\K4os.Compression.LZ4.dll</HintPath> + </Reference> + <Reference Include="K4os.Compression.LZ4.Streams, Version=1.1.11.0, Culture=neutral, PublicKeyToken=2186fa9121ef231d, processorArchitecture=MSIL"> + <HintPath>..\..\packages\K4os.Compression.LZ4.Streams.1.1.11\lib\net46\K4os.Compression.LZ4.Streams.dll</HintPath> + </Reference> + <Reference Include="K4os.Hash.xxHash, Version=1.0.6.0, Culture=neutral, PublicKeyToken=32cd54395057cec3, processorArchitecture=MSIL"> + <HintPath>..\..\packages\K4os.Hash.xxHash.1.0.6\lib\net46\K4os.Hash.xxHash.dll</HintPath> + </Reference> + <Reference Include="log4net"> + <HintPath>..\..\DLL\log4net.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.Owin"> + <HintPath>..\..\DLL\Microsoft.Owin.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Owin.Cors"> + <HintPath>..\..\DLL\Microsoft.Owin.Cors.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Owin.FileSystems"> + <HintPath>..\..\DLL\Microsoft.Owin.FileSystems.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Owin.Host.HttpListener"> + <HintPath>..\..\DLL\Microsoft.Owin.Host.HttpListener.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Owin.Host.SystemWeb"> + <HintPath>..\..\DLL\Microsoft.Owin.Host.SystemWeb.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Owin.Hosting"> + <HintPath>..\..\DLL\Microsoft.Owin.Hosting.dll</HintPath> + <Private>True</Private> + </Reference> + <Reference Include="Microsoft.Owin.StaticFiles"> + <HintPath>..\..\DLL\Microsoft.Owin.StaticFiles.dll</HintPath> + </Reference> + <Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\Newtonsoft.Json.dll</HintPath> + </Reference> + <Reference Include="NPOI, Version=2.1.3.1, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\NPOI.dll</HintPath> + </Reference> + <Reference Include="NPOI.OOXML, Version=2.1.3.1, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\NPOI.OOXML.dll</HintPath> + </Reference> + <Reference Include="NPOI.OpenXml4Net, Version=2.1.3.1, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\NPOI.OpenXml4Net.dll</HintPath> + </Reference> + <Reference Include="NPOI.OpenXmlFormats, Version=2.1.3.1, Culture=neutral, PublicKeyToken=0df73ec7942b34e1, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\NPOI.OpenXmlFormats.dll</HintPath> + </Reference> + <Reference Include="Owin"> + <HintPath>..\..\DLL\Owin.dll</HintPath> + </Reference> + <Reference Include="Owin.Compression"> + <HintPath>..\..\DLL\Owin.Compression.dll</HintPath> + </Reference> + <Reference Include="PCRobot.Pack, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\PCRobot.Pack\bin\Debug\PCRobot.Pack.dll</HintPath> + </Reference> + <Reference Include="protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\protobuf-net.dll</HintPath> + </Reference> + <Reference Include="QRCoder, Version=1.4.1.0, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\QRCoder.dll</HintPath> + </Reference> + <Reference Include="Renci.SshNet, Version=2016.1.0.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106, processorArchitecture=MSIL"> + <HintPath>..\..\packages\SSH.NET.2016.1.0\lib\net40\Renci.SshNet.dll</HintPath> + </Reference> + <Reference Include="Robot.Framework, Version=4.5.2101.7, Culture=neutral, processorArchitecture=x86"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\Robot.Framework.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="SqlSugar, Version=4.9.9.3, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\SqlSugar.dll</HintPath> + </Reference> + <Reference Include="SuperSocket.Common, Version=1.6.6.1, Culture=neutral, PublicKeyToken=6c80000676988ebb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\SuperSocket.1.6.6.1\lib\net45\SuperSocket.Common.dll</HintPath> + </Reference> + <Reference Include="SuperSocket.Facility, Version=1.6.6.1, Culture=neutral, PublicKeyToken=6c80000676988ebb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\SuperSocket.1.6.6.1\lib\net45\SuperSocket.Facility.dll</HintPath> + </Reference> + <Reference Include="SuperSocket.ProtoBase, Version=1.7.0.17, Culture=neutral, PublicKeyToken=6c80000676988ebb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\SuperSocket.ProtoBase.1.7.0.17\lib\net45\SuperSocket.ProtoBase.dll</HintPath> + </Reference> + <Reference Include="SuperSocket.SocketBase, Version=1.6.6.1, Culture=neutral, PublicKeyToken=6c80000676988ebb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\SuperSocket.1.6.6.1\lib\net45\SuperSocket.SocketBase.dll</HintPath> + </Reference> + <Reference Include="SuperSocket.SocketEngine, Version=1.6.6.1, Culture=neutral, PublicKeyToken=6c80000676988ebb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\SuperSocket.Engine.1.6.6.1\lib\net45\SuperSocket.SocketEngine.dll</HintPath> + </Reference> + <Reference Include="SuperSocket.SocketService, Version=1.6.6.1, Culture=neutral, PublicKeyToken=6c80000676988ebb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\SuperSocket.Engine.1.6.6.1\lib\net45\SuperSocket.SocketService.exe</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath> + </Reference> + <Reference Include="System.Collections.Specialized, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll</HintPath> + </Reference> + <Reference Include="System.ComponentModel, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> + <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Configuration" /> + <Reference Include="System.Configuration.Install" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Drawing.Design" /> + <Reference Include="System.Management" /> + <Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll</HintPath> + </Reference> + <Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\System.Net.Http.Extensions.dll</HintPath> + </Reference> + <Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\System.Net.Http.Primitives.dll</HintPath> + </Reference> + <Reference Include="System.Net.NameResolution, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Net.NameResolution.4.3.0\lib\net46\System.Net.NameResolution.dll</HintPath> + </Reference> + <Reference Include="System.Net.Security, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Net.Security.4.3.0\lib\net46\System.Net.Security.dll</HintPath> + </Reference> + <Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath> + </Reference> + <Reference Include="System.Numerics" /> + <Reference Include="System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll</HintPath> + </Reference> + <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath> + </Reference> + <Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\DLL\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath> + </Reference> + <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath> + </Reference> + <Reference Include="System.Transactions" /> + <Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\Debug\System.ValueTuple.dll</HintPath> + </Reference> + <Reference Include="System.Web" /> + <Reference Include="System.Web.Extensions" /> + <Reference Include="System.Web.Http"> + <HintPath>..\..\DLL\System.Web.Http.dll</HintPath> + <Private>True</Private> + </Reference> + <Reference Include="System.Web.Http.Owin"> + <HintPath>..\..\DLL\System.Web.Http.Owin.dll</HintPath> + </Reference> + <Reference Include="System.Windows.Controls.Ribbon" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp"> + <Private>False</Private> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + <Reference Include="ThoughtWorks.QRCode"> + <HintPath>..\..\DLL\ThoughtWorks.QRCode.dll</HintPath> + </Reference> + <Reference Include="UI.Framework, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\..\..\.NET Lib\UI.Framework\bin\Debug\UI.Framework.dll</HintPath> + </Reference> + <Reference Include="websocket-sharp, Version=1.0.2.59611, Culture=neutral, PublicKeyToken=5660b08a1845a91e, processorArchitecture=MSIL"> + <HintPath>..\..\packages\WebSocketSharp.1.0.3-rc11\lib\websocket-sharp.dll</HintPath> + </Reference> + <Reference Include="zxing"> + <HintPath>..\..\DLL\zxing.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="ApiClient.cs" /> + <Compile Include="Config\OtherConfig.cs" /> + <Compile Include="Config\ServerConfig.cs" /> + <Compile Include="Config\SystemConfig.cs" /> + <Compile Include="Cps\DouyinApi.cs" /> + <Compile Include="Cps\douyin_form_login.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\douyin_form_login.Designer.cs"> + <DependentUpon>douyin_form_login.cs</DependentUpon> + </Compile> + <Compile Include="Cps\douyin_form_select_tgw.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\douyin_form_select_tgw.Designer.cs"> + <DependentUpon>douyin_form_select_tgw.cs</DependentUpon> + </Compile> + <Compile Include="Cps\douyin_verify.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\douyin_verify.Designer.cs"> + <DependentUpon>douyin_verify.cs</DependentUpon> + </Compile> + <Compile Include="Cps\DtkApi.cs" /> + <Compile Include="Cps\JingdongApi.cs" /> + <Compile Include="Cps\jingdong_form_login.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\jingdong_form_login.Designer.cs"> + <DependentUpon>jingdong_form_login.cs</DependentUpon> + </Compile> + <Compile Include="Cps\jingdong_form_select_tgw.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\jingdong_form_select_tgw.Designer.cs"> + <DependentUpon>jingdong_form_select_tgw.cs</DependentUpon> + </Compile> + <Compile Include="Cps\KuaiShouApi.cs" /> + <Compile Include="Cps\kuaishou_form_login.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\kuaishou_form_login.Designer.cs"> + <DependentUpon>kuaishou_form_login.cs</DependentUpon> + </Compile> + <Compile Include="Cps\kuaishou_form_select_tgw.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\kuaishou_form_select_tgw.Designer.cs"> + <DependentUpon>kuaishou_form_select_tgw.cs</DependentUpon> + </Compile> + <Compile Include="Cps\kuaishou_form_usernick.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\kuaishou_form_usernick.Designer.cs"> + <DependentUpon>kuaishou_form_usernick.cs</DependentUpon> + </Compile> + <Compile Include="Cps\SuNingApi.cs" /> + <Compile Include="Cps\suning_form_login.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\suning_form_login.Designer.cs"> + <DependentUpon>suning_form_login.cs</DependentUpon> + </Compile> + <Compile Include="Cps\suning_form_login1.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\suning_form_login1.Designer.cs"> + <DependentUpon>suning_form_login1.cs</DependentUpon> + </Compile> + <Compile Include="Cps\suning_form_select_tgw.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\suning_form_select_tgw.Designer.cs"> + <DependentUpon>suning_form_select_tgw.cs</DependentUpon> + </Compile> + <Compile Include="Cps\WeipinhuiApi.cs" /> + <Compile Include="Cps\weipinhui_form_login.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\weipinhui_form_login.Designer.cs"> + <DependentUpon>weipinhui_form_login.cs</DependentUpon> + </Compile> + <Compile Include="Cps\weipinhui_form_select_tgw.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\weipinhui_form_select_tgw.Designer.cs"> + <DependentUpon>weipinhui_form_select_tgw.cs</DependentUpon> + </Compile> + <Compile Include="Cps\weipinhui_form_usernick.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\weipinhui_form_usernick.Designer.cs"> + <DependentUpon>weipinhui_form_usernick.cs</DependentUpon> + </Compile> + <Compile Include="Data\TB\AnalysisTkUrlData.cs" /> + <Compile Include="Data\TB\CouponData.cs" /> + <Compile Include="Data\TB\GetItemInfoData.cs" /> + <Compile Include="Data\TB\TBGoodParsingData.cs" /> + <Compile Include="Data\TB\TBItemInfoData.cs" /> + <Compile Include="Data\TB\TBPassInfoData.cs" /> + <Compile Include="EntityTmp\Douyin\DyItemInfo.cs" /> + <Compile Include="EntityTmp\Douyin\DyOrderInfo.cs" /> + <Compile Include="EntityTmp\Douyin\KolPidList.cs" /> + <Compile Include="EntityTmp\Douyin\ShareInfo.cs" /> + <Compile Include="EntityTmp\KuaiShou\KS_ItemInfo.cs" /> + <Compile Include="EntityTmp\KuaiShou\KS_OrderInfo.cs" /> + <Compile Include="EntityTmp\KuaiShou\KS_TuiGuangWeiInfo.cs" /> + <Compile Include="EntityTmp\KuaiShou\KS_TurnUrlInfo.cs" /> + <Compile Include="EntityTmp\SuNing\Enums.cs" /> + <Compile Include="EntityTmp\SuNing\SN_GoodInfo.cs" /> + <Compile Include="EntityTmp\SuNing\SN_OrderInfo.cs" /> + <Compile Include="EntityTmp\SuNing\SN_QueryCommoditydetail.cs" /> + <Compile Include="EntityTmp\SuNing\SN_Recommend_Commodity.cs" /> + <Compile Include="EntityTmp\SuNing\ToolsRelation.cs" /> + <Compile Include="EntityTmp\SuNing\SN_TuiGuangWeiInfo.cs" /> + <Compile Include="EntityTmp\TkUrlClass.cs" /> + <Compile Include="EntityTmp\WeiPinHui\QueryPids.cs" /> + <Compile Include="Enums\ComposeType.cs" /> + <Compile Include="Enums\DwzType.cs" /> + <Compile Include="Enums\OperateType.cs" /> + <Compile Include="Enums\PrivateAdzoneType.cs" /> + <Compile Include="Events\SharedEvents.cs" /> + <Compile Include="Events\WebRequestEvents.cs" /> + <Compile Include="Extents\ValuesEx.cs" /> + <Compile Include="GlobalSuppressions.cs" /> + <Compile Include="Model\fl_alimama_tlj_create_log.cs" /> + <Compile Include="Model\fl_alimama_tlj_get_record.cs" /> + <Compile Include="Model\fl_alimama_tlj_info.cs" /> + <Compile Include="Model\fl_blackuser.cs" /> + <Compile Include="Model\fl_douyin_record.cs" /> + <Compile Include="Model\fl_dy_ck.cs" /> + <Compile Include="Model\fl_itempoint1_hist.cs" /> + <Compile Include="Model\fl_noticeapi_info.cs" /> + <Compile Include="Model\fl_operation_log.cs" /> + <Compile Include="Model\fl_order_douyin.cs" /> + <Compile Include="Model\fl_order_kuaishou.cs" /> + <Compile Include="Model\fl_order_suning.cs" /> + <Compile Include="Model\fl_order_weipinhui.cs" /> + <Compile Include="Model\fl_prevent_theft_cache.cs" /> + <Compile Include="Model\fl_adzone_group.cs" /> + <Compile Include="Model\fl_adzone_info.cs" /> + <Compile Include="Model\fl_alimama_activity_pid.cs" /> + <Compile Include="Model\fl_cloud_black.cs" /> + <Compile Include="Model\fl_debug_log.cs" /> + <Compile Include="Model\fl_exchange_info.cs" /> + <Compile Include="Model\fl_plugin_allrebatesactivity_info.cs" /> + <Compile Include="Model\fl_plugin_allrebatesactivity_orderlist.cs" /> + <Compile Include="Model\fl_query_ratio_info.cs" /> + <Compile Include="Model\fl_ratio_info_custom.cs" /> + <Compile Include="Model\fl_refund_hist_point.cs" /> + <Compile Include="Model\fl_shpay_hist.cs" /> + <Compile Include="Model\fl_statistics_record.cs" /> + <Compile Include="Model\fl_dictionary_item.cs" /> + <Compile Include="Config\LoginUser.cs" /> + <Compile Include="Config\Setting.cs" /> + <Compile Include="CpsClient.cs" /> + <Compile Include="Cps\alimama_form_select_tgw.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\alimama_form_select_tgw.Designer.cs"> + <DependentUpon>alimama_form_select_tgw.cs</DependentUpon> + </Compile> + <Compile Include="Cps\BaseCpsApi.cs" /> + <Compile Include="Cps\CpsToken.cs" /> + <Compile Include="Cps\pinduoduo_form_login.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\pinduoduo_form_login.Designer.cs"> + <DependentUpon>pinduoduo_form_login.cs</DependentUpon> + </Compile> + <Compile Include="Cps\PinduoduoApi.cs" /> + <Compile Include="Cps\AlimamaApi.cs" /> + <Compile Include="Cps\alimama_form_login.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\alimama_form_login.Designer.cs"> + <DependentUpon>alimama_form_login.cs</DependentUpon> + </Compile> + <Compile Include="Cps\pinduoduo_form_select_tgw.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="Cps\pinduoduo_form_select_tgw.Designer.cs"> + <DependentUpon>pinduoduo_form_select_tgw.cs</DependentUpon> + </Compile> + <Compile Include="Cps\Tuiguangwei.cs" /> + <Compile Include="Enums\AwardDepotType.cs" /> + <Compile Include="Enums\CpsType.cs" /> + <Compile Include="Enums\MemberType.cs" /> + <Compile Include="Enums\OrderNoticeType.cs" /> + <Compile Include="Enums\OrderStatus.cs" /> + <Compile Include="Enums\PointType.cs" /> + <Compile Include="Enums\SubsidyType.cs" /> + <Compile Include="Enums\SwitchType.cs" /> + <Compile Include="Events\BaseEvents.cs" /> + <Compile Include="Events\DebugEvent.cs" /> + <Compile Include="Events\LogEvents.cs" /> + <Compile Include="Events\MethodType.cs" /> + <Compile Include="Events\OrderNoticeEvent.cs" /> + <Compile Include="Model\base_model.cs" /> + <Compile Include="Model\fl_group_person.cs" /> + <Compile Include="Model\fl_order_alimama.cs" /> + <Compile Include="Model\fl_alimama_order_lastnum.cs" /> + <Compile Include="Model\fl_bind_cache.cs" /> + <Compile Include="Model\fl_cps_member.cs" /> + <Compile Include="Model\fl_create_info.cs" /> + <Compile Include="Model\fl_member_group.cs" /> + <Compile Include="Model\fl_order_jingdong.cs" /> + <Compile Include="Model\fl_order_refund_alimama.cs" /> + <Compile Include="Model\fl_order_sleep.cs" /> + <Compile Include="Model\fl_order_pinduoduo.cs" /> + <Compile Include="Model\fl_point_hist.cs" /> + <Compile Include="Model\fl_private_pid.cs" /> + <Compile Include="Model\fl_query_hist.cs" /> + <Compile Include="Model\fl_ratio_info.cs" /> + <Compile Include="Model\fl_suning_tgw.cs" /> + <Compile Include="Model\fl_tb_relation.cs" /> + <Compile Include="Model\fl_uservariate_info.cs" /> + <Compile Include="Model\fl_wechat_contacts.cs" /> + <Compile Include="Model\fl_wechat_device.cs" /> + <Compile Include="Model\fl_weixin_password.cs" /> + <Compile Include="Model\ModelExtend.cs" /> + <Compile Include="Model\temp_send_data.cs" /> + <Compile Include="NoticeSocketClient.cs" /> + <Compile Include="SDK\MemberPointChangeEvent.cs" /> + <Compile Include="SDK\PluginExtend.cs" /> + <Compile Include="SDK\ReciveIMEvent.cs" /> + <Compile Include="Model\fl_member_level.cs" /> + <Compile Include="Model\fl_member_info.cs" /> + <Compile Include="Model\fl_plugin_info.cs" /> + <Compile Include="Model\fl_robot_info.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="SDK\Plugin.cs" /> + <Compile Include="PluginClient.cs" /> + <Compile Include="EventClient.cs" /> + <Compile Include="SDK\SDKEvent.cs" /> + <Compile Include="Timers\ClearGarbageTimer.cs" /> + <Compile Include="SDK\TimerTask.cs" /> + <Compile Include="Timers\DownAlimamaTimer.cs" /> + <Compile Include="Timers\DownDouyinTimer.cs" /> + <Compile Include="Timers\DownJingdongTimer.cs" /> + <Compile Include="Timers\DownKuaiShouTimer.cs" /> + <Compile Include="Timers\DownPinduoduoTimer.cs" /> + <Compile Include="Timers\DownSuningTimer.cs" /> + <Compile Include="Timers\DownWeipinhuiTimer.cs" /> + <Compile Include="Tools\AesHelper.cs" /> + <Compile Include="Tools\ChatTypeControl.cs" /> + <Compile Include="Tools\CloudApiHelper.cs" /> + <Compile Include="Tools\CloudBlack.cs" /> + <Compile Include="Tools\DouyinGoodsInfo.cs" /> + <Compile Include="Tools\KSHelper.cs" /> + <Compile Include="Tools\PointManageConfig.cs" /> + <Compile Include="Tools\SNHelper.cs" /> + <Compile Include="Tools\DYHelper.cs" /> + <Compile Include="Tools\h5Top.cs" /> + <Compile Include="Tools\KuaiZhanShort.cs" /> + <Compile Include="Tools\OrderHelper.cs" /> + <Compile Include="Tools\SynchronizedDictionary.cs" /> + <Compile Include="Tools\ExcelHelper.cs" /> + <Compile Include="Tools\IniHelper.cs" /> + <Compile Include="Tools\JDHelper.cs" /> + <Compile Include="Tools\LogHelper.cs" /> + <Compile Include="Tools\Nopi\Assistant.cs" /> + <Compile Include="Tools\Nopi\ExcelFileExport.cs" /> + <Compile Include="Tools\Nopi\ExcelHelper.cs" /> + <Compile Include="Tools\Nopi\ExcelStream.cs" /> + <Compile Include="Tools\Nopi\ExcelStreamExport.cs" /> + <Compile Include="Tools\Nopi\ExtensiveHelper.cs" /> + <Compile Include="Tools\PDDHelper.cs" /> + <Compile Include="Tools\SqlSugarEx.cs" /> + <Compile Include="Tools\TaskTool.cs" /> + <Compile Include="Timers\Update_CpsStatus.cs" /> + <Compile Include="Timers\Update_NoticeQueue.cs" /> + <Compile Include="Tools\CacheTool.cs" /> + <Compile Include="Tools\Encryption.cs" /> + <Compile Include="Tools\HTTPClass.cs" /> + <Compile Include="Tools\TBHelper.cs" /> + <Compile Include="Tools\UpdateClient.cs" /> + <Compile Include="Tools\Util.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Tools\VariateReplace.cs" /> + <Compile Include="Tools\WechatPay.cs" /> + <Compile Include="Tools\WPHHelper.cs" /> + <Compile Include="Tools\Zip.cs" /> + <Compile Include="Tools\ZipHelper.cs" /> + <Compile Include="UIForm\AliQrCordControl.cs"> + <SubType>UserControl</SubType> + </Compile> + <Compile Include="UIForm\AliQrCordControl.Designer.cs"> + <DependentUpon>AliQrCordControl.cs</DependentUpon> + </Compile> + <Compile Include="UIForm\SetConnectionConfig.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="UIForm\SetConnectionConfig.Designer.cs"> + <DependentUpon>SetConnectionConfig.cs</DependentUpon> + </Compile> + <Compile Include="SDK\Config.cs" /> + <Compile Include="UIForm\smsCode.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="UIForm\smsCode.Designer.cs"> + <DependentUpon>smsCode.cs</DependentUpon> + </Compile> + <Compile Include="WebClient.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Cps\alimama_form_select_tgw.resx"> + <DependentUpon>alimama_form_select_tgw.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="Cps\douyin_form_login.resx"> + <DependentUpon>douyin_form_login.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\douyin_form_select_tgw.resx"> + <DependentUpon>douyin_form_select_tgw.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\douyin_verify.resx"> + <DependentUpon>douyin_verify.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\jingdong_form_login.resx"> + <DependentUpon>jingdong_form_login.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\jingdong_form_select_tgw.resx"> + <DependentUpon>jingdong_form_select_tgw.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="Cps\kuaishou_form_login.resx"> + <DependentUpon>kuaishou_form_login.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\kuaishou_form_select_tgw.resx"> + <DependentUpon>kuaishou_form_select_tgw.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\kuaishou_form_usernick.resx"> + <DependentUpon>kuaishou_form_usernick.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\pinduoduo_form_login.resx"> + <DependentUpon>pinduoduo_form_login.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\alimama_form_login.resx"> + <DependentUpon>alimama_form_login.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="Cps\pinduoduo_form_select_tgw.resx"> + <DependentUpon>pinduoduo_form_select_tgw.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="Cps\suning_form_login.resx"> + <DependentUpon>suning_form_login.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\suning_form_login1.resx"> + <DependentUpon>suning_form_login1.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\suning_form_select_tgw.resx"> + <DependentUpon>suning_form_select_tgw.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\weipinhui_form_login.resx"> + <DependentUpon>weipinhui_form_login.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\weipinhui_form_select_tgw.resx"> + <DependentUpon>weipinhui_form_select_tgw.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Cps\weipinhui_form_usernick.resx"> + <DependentUpon>weipinhui_form_usernick.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="UIForm\AliQrCordControl.resx"> + <DependentUpon>AliQrCordControl.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="UIForm\smsCode.resx"> + <DependentUpon>smsCode.cs</DependentUpon> + </EmbeddedResource> + <None Include="app.config"> + <SubType>Designer</SubType> + </None> + <None Include="Config\log4net.config" /> + <None Include="Config\log4net.unix.config" /> + <None Include="packages.config"> + <SubType>Designer</SubType> + </None> + <None Include="Properties\licenses.licx" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="UIForm\SetConnectionConfig.resx"> + <DependentUpon>SetConnectionConfig.cs</DependentUpon> + <SubType>Designer</SubType> + </EmbeddedResource> + <None Include="Resources\返利机器人.rar" /> + <None Include="supersocket.cmd" /> + <None Include="supersocket.sh" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\sxds.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\bitbug_favicon-2.ico" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\favicon-20180629034329926.ico" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\foot.png" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\模板B.jpg" /> + </ItemGroup> + <ItemGroup> + <None Include="Resources\优惠券C.jpg" /> + </ItemGroup> + <ItemGroup> + <WCFMetadata Include="Connected Services\" /> + </ItemGroup> + <ItemGroup> + <COMReference Include="SHDocVw"> + <Guid>{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}</Guid> + <VersionMajor>1</VersionMajor> + <VersionMinor>1</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>tlbimp</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>True</EmbedInteropTypes> + </COMReference> + </ItemGroup> + <ItemGroup> + <None Include="Resources\VersionUpdate.xml" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\HttpHelper2.1\HttpHelper.csproj"> + <Project>{b54ae050-dd6c-4f73-95e8-9d8c1cf38ffe}</Project> + <Name>HttpHelper</Name> + <Private>False</Private> + </ProjectReference> + </ItemGroup> + <ItemGroup /> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project> \ No newline at end of file diff --git a/类库/Api.Framework/ApiClient - 复制.cs b/类库/Api.Framework/ApiClient - 复制.cs new file mode 100644 index 0000000..b4cc30c --- /dev/null +++ b/类库/Api.Framework/ApiClient - 复制.cs @@ -0,0 +1,3272 @@ +using Api.Framework.Config; +using Api.Framework.Config; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Api.Framework.UIForm; +using Chat.Framework; +using CsharpHttpHelper; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; +using ZXing; +using ZXing.Common; +using System.Reflection; +using Chat.Framework.WXSdk; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using SuperSocket.SocketBase; +using System.Text.RegularExpressions; +using System.Security.Cryptography; +using Chat.Framework.PCRobotSDK.WechatEvents; +using PCRobot.Pack; +using SuperSocket.SocketEngine; +using Chat.Framework.PCRobotSDK; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.Implement; +using Chat.Framework.PCRobotSDK.WorkWechatEvents; +using Grant.Framework; +using Newtonsoft.Json.Linq; +using System.Web.Configuration; +using System.Web.Security; +using static Api.Framework.Cps.AlimamaApi; +using Robot.Framework.Entities; +using Chat.Framework.QQSdk.QPlus; + +namespace Api.Framework +{ + + public class ApiClient + { + + private static Version _version; + /// <summary> + /// 当前版本 + /// </summary> + public static Version CurVersion + { + get + { + if (_version == null) + { + string file = Util.MapFile("VersionUpdate.xml"); + if (!File.Exists(file)) file = Util.MapFile("OnlineUpdate.xml"); + if (!File.Exists(file)) throw new Exception("文件丢失[VersionUpdate.xml],不存在!"); + var xml = File.ReadAllText(file).Trim(); + if (!string.IsNullOrWhiteSpace(xml)) + { + var reg = Regex.Match(xml, @"File\s+?Name=""核心组件""\s+?Version=""(?<版本号>([^""]*?))"""); + if (reg.Success) + { + var version = reg.Groups["版本号"].Value.Trim(); + _version = Version.Parse(version); + } + } + } + return _version; + } + } + + public static SoperSocketServer Server { get; private set; } + public static void StopSocketServer() + { + try + { + if (Server != null) + { + Server.Stop(); + Server.NewSessionConnected -= appServer_NewSessionConnected; + Server.SessionClosed -= appServer_NewSessionClosed; + } + } + catch (Exception) + { } + } + public static bool StartSocketServer(int port, string password) + { + try + { + StopSocketServer(); + Server = new SoperSocketServer(); + + var serconfig = new SuperSocket.SocketBase.Config.ServerConfig(); + serconfig.TextEncoding = "UTF-8"; + serconfig.Ip = "Any"; + serconfig.Port = port; + serconfig.SendBufferSize = 1024 * 40; + serconfig.ReceiveBufferSize = 10240 * 40; + serconfig.MaxRequestLength = 10240 * 40; + serconfig.SendingQueueSize = 50; + Console.WriteLine(serconfig.MaxConnectionNumber); + + // serconfig.MaxConnectionNumber = 5000; + //SuperSocket.SocketBase. appServer = new AppServer(); + if (!Server.Setup(serconfig)) throw new Exception("监听端口失败,请检查是否关闭防火墙或端口被占用!"); + + //var cfg = new SuperSocket.SocketBase.Config.ServerConfig(); + //cfg.ReceiveBufferSize = int.MaxValue; + //var rfg = new SuperSocket.SocketBase.Config.RootConfig(); + ////Try to start the appServer + if (!Server.Start()) throw new Exception("初始化端口失败,请检查是否关闭防火墙或端口被占用!"); + + ApiClient.Setting.ServerConfig.SocketPassword = password; + ApiClient.Setting.ServerConfig.SocketPort = port; + ApiClient.Setting.ServerConfig.SocketIsOpen = true; + //var cfg = Server.Config; + ////var rfg = Server.RootConfig; + //Server.Config.ReceiveBufferSize = int.MaxValue; + + ChatClient.SocketPassword = password; + + Server.NewSessionConnected += appServer_NewSessionConnected; + Server.SessionClosed += appServer_NewSessionClosed; + + ////SocketCMD 是KEY + Server.NewRequestReceived += Server_NewRequestReceived; + + //Server.r + Util.Save(Setting.ServerConfig); + return true; + //return true; + } + catch (Exception ex) + { + ApiClient.Setting.ServerConfig.SocketIsOpen = false; + Util.Save(Setting.ServerConfig); + throw ex; + } + + return false; + } + + /// <summary> + /// HOOK机器人消息事件 + /// </summary> + /// <param name="session"></param> + /// <param name="requestInfo"></param> + private static void Server_NewRequestReceived(SupperSocketSession _session, SuperSocket.SocketBase.Protocol.StringRequestInfo _requestInfo) + { + var session = _session; + var requestInfo = _requestInfo; + var action = new Action(delegate () + { + try + { + int key; + //var cmd = (PCRobot.Pack.PCRobotCMD)Enum.Parse(typeof(PCRobot.Pack.PCRobotCMD), requestInfo.Key); + PCRobot.Pack.PCRobotCMD cmd; + if (!Enum.TryParse<PCRobot.Pack.PCRobotCMD>(requestInfo.Key, out cmd)) return; + var data = PackTool.DecompressString(requestInfo.Body); + var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(data); + if (dic.ContainsKey("Key") && dic["Key"].ToString() != Setting.ServerConfig.SocketPassword) + { + var RobotUsernick = string.Empty; + if (dic.ContainsKey("RobotUsernick")) + RobotUsernick = dic["RobotUsernick"].ToString(); + var RobotUsername = string.Empty; + if (dic.ContainsKey("RobotUsername")) + RobotUsername = dic["RobotUsername"].ToString(); + + RobotType robotType; + if (dic.ContainsKey("RobotType")) + { + var type = dic["RobotType"].ToString(); + if (Enum.TryParse<RobotType>(type, out robotType)) + throw new Exception($"{(robotType == RobotType.客户端微信 ? ChatType.微信 : robotType == RobotType.客户端企业微信 ? ChatType.企业微信 : robotType == RobotType.客户端扣扣 ? ChatType.QQ : ChatType.微信公众号)}:{RobotUsernick}({RobotUsername}) 易转发与软件秘钥不匹配,无法通讯!"); + } + } + var cmd_int = (int)cmd; + var events = ChatClient.Events; + + //心跳包处理 + //if (cmd == PCRobotCMD.heartBreak) + //{ + // var json = HttpHelper.JsonToObject<WechatStatus>(data) as WechatStatus; + // var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatStatusEvents(json); + // if (evt == null) return; + // if (evt.Key != Setting.ServerConfig.SocketPassword) throw new Exception("秘钥不匹配,无法连接!"); + + // //var robot = GetRobotInfo(evt.RobotUsername, evt.RobotUsernick, evt.RobotType == RobotType.客户端企业微信 ? ChatType.企业微信 : ChatType.微信, evt.Uin); + + // //Chat.Framework.ChatClient.PCRobotPool.Update(evt.RobotUsername, session); + // //var hook = FindHookRobot(robot, evt.RobotType); + // //if (hook != null) + // //{ + // // hook.Receive(evt); + // //} + // //EventClient.OnEvent(null,$"收到{robot.name}({robot.nick})的心跳包!"); + // session.Send("heartBreak $"); + //} + if (cmd.ToString().StartsWith("offline")) + { + var json = HttpHelper.JsonToObject<WechatStatus>(data) as WechatStatus; + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatStatusEvents(json); + if (evt == null) + { + EventClient.OnEvent(null, $"{json.RobotUsername}({json.Uin})心跳发送失败"); + return; + } + + if (evt.Key == Setting.ServerConfig.SocketPassword) + session.TrySend(data); + else + EventClient.OnEvent(null, $"{json.RobotUsername}({json.Uin})心跳发送失败,秘钥不一致"); + } + + //个人微信消息 + if (cmd_int >= 2000 && cmd_int <= 2999) + { + switch (cmd) + { + case PCRobot.Pack.PCRobotCMD.rcvTxt: + case PCRobot.Pack.PCRobotCMD.rcvFile: + case PCRobot.Pack.PCRobotCMD.rcvImg: + { + var json = HttpHelper.JsonToObject<WechatReceiveMsg>(data) as WechatReceiveMsg; + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatReceiveMsgEvents(json); + if (evt == null) return; + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + //EventClient.OnEvent(evt, evt); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + { + hook.Receive(evt); + } + } + break; + case PCRobotCMD.applyFriend: + { + var json = HttpHelper.JsonToObject<WechatApplyFriend>(data) as WechatApplyFriend; + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatApplyFriendEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobot.Pack.PCRobotCMD.receivePay: + { + var json = HttpHelper.JsonToObject<WechatReicevePay>(data) as WechatReicevePay; + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatReicevePayEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobotCMD.applyGroup: + { } + break; + case PCRobotCMD.newfriend: + { + var json = HttpHelper.JsonToObject<WechatNewFriend>(data) as WechatNewFriend; + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatNewFriendEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobotCMD.offline: + { + var json = HttpHelper.JsonToObject<WechatStatus>(data) as WechatStatus; + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatStatusEvents(json); + if (evt == null) + { + EventClient.OnEvent(null, $"{json.RobotUsername}({json.Uin})心跳发送失败,秘钥不一致"); + return; + } + + var robot = GetRobotInfo(evt.RobotUsername, evt.RobotUsernick, ChatType.微信, json.Uin); + + robot.is_login = evt.Status == Status.在线; + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.RobotType); + if (hook != null) + { + hook.Receive(evt); + + if (string.IsNullOrWhiteSpace(robot.end_time)) + { + var softId = (robot.type == Api.Framework.SDK.ChatType.QQ) ? 1002 : 1001; + var custm = GrantClient.Get().Refresh(robot.uin.ToString(), softId); + if (custm != null) + { + robot.end_time = custm.endTime; + ApiClient.GetSession().SaveOrUpdate(robot); + ApiClient.GetSession().FindRobots(true); + } + } + } + } + break; + case PCRobotCMD.newMember: + { + var json = HttpHelper.JsonToObject<WechatNewMemer>(data) as WechatNewMemer; + var evt = new WechatNewMemerEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobotCMD.rcvContactList: + { + var json = HttpHelper.JsonToObject<WechatContact>(data) as WechatContact; + var evt = new WechatContactListEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobotCMD.rcvContact: + { + var json = HttpHelper.JsonToObject<WechatContact>(data) as WechatContact; + var evt = new WechatContactListEvents(json); + if (evt == null) return; + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + } + break; + case PCRobotCMD.rcvCheckUrl: + { + var json = HttpHelper.JsonToObject<CheckUrl>(data) as CheckUrl; + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + } + break; + case PCRobotCMD.rcvCreateRoom: + { + var json = HttpHelper.JsonToObject<CreateRoom>(data) as CreateRoom; + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + } + break; + case PCRobotCMD.rcvGroupMember: + { + var json = HttpHelper.JsonToObject<WechatGroupMember>(data) as WechatGroupMember; + var evt = new WechatGroupMemberEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + } + } + + //企业微信消息处理 + else if (cmd_int >= 3000 && cmd_int <= 3999) + { + switch (cmd) + { + case PCRobotCMD.rcvTxt_workWeChat: + case PCRobotCMD.rcvFile_workWeChat: + case PCRobotCMD.rcvImg_workWeChat: + { + var json = HttpHelper.JsonToObject<WorkWechatReceiveMsg>(data) as WorkWechatReceiveMsg; + var evt = new Chat.Framework.PCRobotSDK.WorkWechatEvents.WorkWechatReceiveMsgEvents(json); + if (evt == null) return; + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + //EventClient.OnEvent(evt, evt); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.applyFriend_workWeChat: + { + var json = HttpHelper.JsonToObject<WorkWechatApplyFriend>(data) as WorkWechatApplyFriend; + var evt = new Chat.Framework.PCRobotSDK.WorkWechatEvents.WorkWechatApplyFriendEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.receivePay_workWeChat: + { + var json = HttpHelper.JsonToObject<WorkWechatReicevePay>(data) as WorkWechatReicevePay; + var evt = new Chat.Framework.PCRobotSDK.WorkWechatEvents.WorkWechatReicevePayEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.applyGroup_workWeChat: + { } + break; + case PCRobotCMD.newfriend_workWeChat: + { + var json = HttpHelper.JsonToObject<WorkWechatNewFriend>(data) as WorkWechatNewFriend; + var evt = new Chat.Framework.PCRobotSDK.WorkWechatEvents.WorkWechatNewFriendEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.offline_workWeChat: + { + var json = HttpHelper.JsonToObject<WechatStatus>(data) as WechatStatus; + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatStatusEvents(json); + if (evt == null) + { + EventClient.OnEvent(null, $"{json.RobotUsername}({json.Uin})心跳发送失败,秘钥不一致"); + return; + } + + var robot = GetRobotInfo(evt.RobotUsername, evt.RobotUsernick, ChatType.企业微信, json.Uin); + + robot.is_login = evt.Status == Status.在线; + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.RobotType); + if (hook != null) + { + hook.Receive(evt); + + if (string.IsNullOrWhiteSpace(robot.end_time)) + { + var softId = (robot.type == Api.Framework.SDK.ChatType.QQ) ? 1002 : 1001; + var custm = GrantClient.Get().Refresh(robot.uin.ToString(), softId); + if (custm != null) + { + robot.end_time = custm.endTime; + ApiClient.GetSession().SaveOrUpdate(robot); + ApiClient.GetSession().FindRobots(true); + } + } + } + else + { } + } + break; + case PCRobotCMD.newMember_workWeChat: + { + var json = HttpHelper.JsonToObject<WorkWechatNewMemer>(data) as WorkWechatNewMemer; + var evt = new WorkWechatNewMemerEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.rcvContact_workWeChat: + { + var json = HttpHelper.JsonToObject<WorkWechatContact>(data) as WorkWechatContact; + var evt = new WorkWechatContactListEvents(json); + if (evt == null) return; + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + } + break; + case PCRobotCMD.rcvContactList_workWeChat: + { + var json = HttpHelper.JsonToObject<WorkWechatContact>(data) as WorkWechatContact; + var evt = new WorkWechatContactListEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.rcvGroupMember_workWeChat: + { + var json = HttpHelper.JsonToObject<WorkWechatGroupMember>(data) as WorkWechatGroupMember; + var evt = new WorkWechatGroupMemberEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(null, $"{ex.Message}."); + } + }); + action.BeginInvoke(null, null); + } + + /// <summary> + /// 锁获取机器人对象,确保唯一 + /// </summary> + private static readonly object GetRobotLock = new object(); + /// <summary> + /// 获取机器人对象 + /// </summary> + /// <param name="weixinhao"></param> + /// <returns></returns> + private static WeixinBase FindHookRobot(fl_robot_info robot, RobotType robotType) + { + lock (GetRobotLock) + { + var v = ChatClient.WXClient.FirstOrDefault(f => f.Key == robot.name).Value; + if (!robot.is_login && v == null) + return null; + switch (robotType) + { + case RobotType.客户端系统: + break; + case RobotType.客户端微信: + if (v == null) + v = new WXClientImpl_HOOK(robot.name, robot.nick, long.Parse(robot.uin)); + break; + case RobotType.客户端企业微信: + if (v == null) + v = new WXClientImpl_QYHOOK(robot.name, robot.nick, long.Parse(robot.uin)); + break; + case RobotType.客户端扣扣: + break; + } + return v; + } + } + + /// <summary> + /// 获取机器人对象 + /// </summary> + /// <param name="username"></param> + /// <param name="usernick"></param> + /// <param name="robotType"></param> + /// <returns></returns> + [Obsolete("这个函数已经过时了", true)] + private static WeixinBase FindHookRobot(string username, string usernick, RobotType robotType) + { + lock (GetRobotLock) + { + var v = ChatClient.WXClient.FirstOrDefault(f => f.Key == username).Value; + switch (robotType) + { + case RobotType.客户端系统: + break; + case RobotType.客户端微信: + if (v == null) + v = new WXClientImpl_HOOK(username, usernick); + break; + case RobotType.客户端企业微信: + if (v == null) + v = new WXClientImpl_QYHOOK(username, usernick); + break; + case RobotType.客户端扣扣: + break; + } + return v; + } + } + + /// <summary> + /// 删除机器人对象 + /// </summary> + /// <param name="weixinhao"></param> + //private static void RemoveHookRobot(string weixinhao) + //{ + // lock (GetRobotLock) + // { + // if (ChatClient.WXClient.ContainsKey(weixinhao)) + // ChatClient.WXClient.Remove(weixinhao); + // } + //} + + private readonly static object robot_lock = new object(); + + private static fl_robot_info GetRobotInfo(string robotUsername, string robotUsernick, ChatType chatType, string uin = "") + { + var s = ApiClient.GetSession(); + fl_robot_info robot = null; + if (string.IsNullOrWhiteSpace(robotUsername)) + return null; + lock (robot_lock) + { + robot = s.FindRobotInfo(robotUsername, chatType); + if (robot == null) + { + robot = new fl_robot_info() + { + name = robotUsername, + nick = Util.RemoveEmoji(robotUsernick), + uin = uin, + type = chatType, + remark = "PCWechat HOOK" + }; + s.Insertable<fl_robot_info>(robot).ExecuteCommandIdentityIntoEntity(); + s.FindRobots(true); + } + else + { + if (!string.IsNullOrWhiteSpace(uin)) + { + robot.nick = Util.RemoveEmoji(robotUsernick); + robot.uin = uin; + robot.remark = "PCWechat HOOK"; + s.Updateable<fl_robot_info>(robot).ExecuteCommand(); + s.FindRobots(true); + } + else + { } + } + + robot.is_login = true; + } + return robot; + } + + private static void appServer_NewSessionClosed(SupperSocketSession session, SuperSocket.SocketBase.CloseReason value) + { + try + { + EventClient.OnEvent(session, $"{session.RemoteEndPoint.Address}-{session.RemoteEndPoint.Port}--> 已关闭!"); + var con = ApiClient.GetSession(); + var name = Chat.Framework.ChatClient.PCRobotPool.Remove(session); + var r = con.FindRobots().FirstOrDefault(f => f.name == name); + if (r != null) + { + r.is_login = false; + con.Updateable<fl_robot_info>(r).ExecuteCommand(); + } + + + } + catch (Exception) + { + } + } + + private static void appServer_NewSessionConnected(SupperSocketSession session) + { + EventClient.OnEvent(session, $"{session.RemoteEndPoint.Address}-{session.RemoteEndPoint.Port} --> 连接成功!"); + } + + public static Setting Setting { get; set; } + + /// <summary> + /// 清理垃圾 + /// </summary> + private static ClearGarbageTimer _ClearGarbage; + + public static bool SelectDbbase() + { + Setting = new Setting(); + //选择数据库 + if (string.IsNullOrEmpty(Setting.DbConfig.ConnectionString)) + { + SetConnectionConfig connection = new SetConnectionConfig(); + connection.ShowDialog(); + if (!connection.IsOk) return false; + return true; + } + return true; + } + + /// <summary> + /// 初始化 + /// </summary> + public static bool Initialization() + { + + try + { + Cache = CacheTool.GetSingleObj(); + //初始化 + var session = GetSession(); + try + { + bool first = CreateTables(session); + Setting.Iniconfig(); + Setting.SystemConfig.cps_server_api = "http://cps.api.52cmg.cn/"; + if (first) + { + Setting.Plugins.Add("PointManage.Class1"); + Setting.Plugins.Add("TBRebate.Class1"); + Setting.Plugins.Add("PDDRebate.Class1"); + Setting.Plugins.Add("UserFission.Class1"); + Setting.Plugins.Add("AutoAnswer.Class1"); + } + string key = "<RSAKeyValue><Modulus>2lThVzrziUuYbxfzgQ9CpivZANcSOVzUaV9Uacw8gCaudDjT6Vn6Mv+HyMKUnZB4zCwBOYkFuMjS8gfoog3Dk26TkHxAp7izE3RK8ptL7vzqozaMioqak05binUrZxLiy4X/5D9+Ny+lueuQjCIjn6eXL0D595NbAlTw/uOHodE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"; + CpsClient.SetEnckey(10003, ApiClient.Setting.SystemConfig.cps_server_api, key); + //var ip = (CpsClient.SendServer("find_config", "webtool.asmx", new { name = "Grpc微信服务器" }) as string).Split(','); + ChatClient.GetServerDataMethod = GetServerConfig; + // var ip = "193.112.217.56:81".Split(','); ; + //var ip = "193.112.217.56:81".Split(','); ; + // ip = new string[] { "118.25.53.240:9888" }; + + ChatClient.SetWeixinCore(null, new string[] { "1001", "13101A4D25A0C46B97BB58799C0D5CC7" }); + ChatClient.Events.WXGetDeviceEvent += Events_WXGetDeviceEvent; + ChatClient.GetDBWechatFriend = GetDBWechatFriend; + + PluginClient.LodingPlugin();//加载插件 + ResetTimer(); + + if (Setting.ServerConfig.IsOpen) + { + WebClient.Start(Setting.ServerConfig.Host, ApiClient.Setting.ServerConfig.Port, false); + } + + if (Setting.ServerConfig.SocketIsOpen) + { + StartSocketServer(Setting.ServerConfig.SocketPort, Setting.ServerConfig.SocketPassword); + } + + return true; + } + catch (Exception ex) + { + throw ex; + return false; + // session.Rollback(); + } + } + catch (Exception ex) + { + throw ex; + //MessageBox.Show(ex.Message + ex.StackTrace != null ? "\r\n" + ex.StackTrace : "", "初始化失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + } + private static Chat.Framework.WXSdk.Friend GetDBWechatFriend(string username) + { + try + { + var session = GetSession(); + var member = session.FindSingle<fl_member_info>("select * from fl_member_info where (robot_type = @robot_type1 or robot_type = @robot_type2) and username = @username", new { username = username, robot_type1 = ChatType.微信, robot_type2 = ChatType.企业微信 }); + if (member != null) + return new Chat.Framework.WXSdk.Friend() { UserName = member.username, NickName = member.usernick, Alias = member.wechatid }; + } + catch (Exception) + { } + return new Chat.Framework.WXSdk.Friend() { UserName = username }; + } + private static void Events_WXGetDeviceEvent(object sender, Chat.Framework.WXSdk.Events.WXGetDevice e) + { + try + { + var session = GetSession(); + //var device = session.Queryable<fl_wechat_device>().Where(f => f.weixinhao == e.Client.WeixinHao).Single(); + var device = session.FindSingle<fl_wechat_device>("select * from fl_wechat_device where weixinhao = @weixinhao", new { weixinhao = e.Client.WeixinHao }); + if (device != null) + { + e.DeviceInfo = string.IsNullOrEmpty(device.device_info) ? string.Empty : device.device_info; + } + } + catch (Exception) + { } + } + + public static string GetServerConfig(string key) + { + return CpsClient.SendServer("find_config", "webtool.asmx", new { name = key }) as string; + } + + + + #region 临时用的,返回false不用管,返回true表示已经删除了(删除了,重新新建索引) + private static bool checkIndex(SqlSugarClient session, string tableName, params object[] values) + { + try + { + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + if (session.IndexExist(tableName, values[0].ToString())) + return session.DeleteIndex(tableName, values[0].ToString()); + } + else if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + if (session.IndexExist(tableName, tableName + "_" + string.Join("_", values))) + return session.DeleteIndex(tableName, tableName + "_" + string.Join("_", values)); + } + } + catch (Exception) + { } + return false; + } + #endregion + + /// <summary> + /// 创建表,没有表则创建 + /// </summary> + /// <param name="session"></param> + /// <returns></returns> + public static bool CreateTables(SqlSugarClient session) + { + try + { + //全额免单 + if (!session.TableExist<fl_plugin_allrebatesactivity_info>()) + { + session.CreateTable<fl_plugin_allrebatesactivity_info>(); + session.AddIndex<fl_plugin_allrebatesactivity_info>("name");//增加索引.以后数据多了.查询速度会比较快 + session.AddUnique<fl_plugin_allrebatesactivity_info>("name");//增加唯一约束 + } + //全额免单订单 + if (!session.TableExist<fl_plugin_allrebatesactivity_orderlist>()) + { + session.CreateTable<fl_plugin_allrebatesactivity_orderlist>(); + } + + if (!session.TableExist<fl_prevent_theft_cache>()) + { + session.CreateTable<fl_prevent_theft_cache>(); + session.AddIndex<fl_prevent_theft_cache>("order_id"); + session.AddUnique<fl_prevent_theft_cache>("order_id"); + } + + //推广位组 + if (!session.TableExist<fl_adzone_group>()) + { + session.CreateTable<fl_adzone_group>(); + session.AddIndex<fl_adzone_group>("cps_type"); + session.AddUnique<fl_adzone_group>("name"); + } + else + { + if (!session.ColumnExist("fl_adzone_group", "remark")) + { + session.AddColumn("fl_adzone_group", "remark", "varchar(255) default ''"); + } + } + + //推广位 + if (!session.TableExist<fl_adzone_info>()) + { + session.CreateTable<fl_adzone_info>(); + } + else + { + if (!session.ColumnExist("fl_adzone_info", "is_auto_bind")) + { + session.AddColumn("fl_adzone_info", "is_auto_bind", "boolean default 0"); + } + + if (!session.ColumnExist("fl_adzone_info", "adzone_group")) + { + session.AddColumn("fl_adzone_info", "adzone_group", "integer default 0"); + } + } + + //用户自定义变量 + if (!session.TableExist<fl_uservariate_info>()) + { + session.CreateTable<fl_uservariate_info>(); + session.AddUnique<fl_uservariate_info>("variate"); + } + + if (!session.TableExist<fl_wechat_contacts>()) + { + session.CreateTable<fl_wechat_contacts>(); + session.AddUnique<fl_wechat_contacts>("user_name"); + } + + if (!session.TableExist<fl_noticeapi_info>()) + { + session.CreateTable<fl_noticeapi_info>(); + session.AddUnique<fl_noticeapi_info>("name"); + } + + //dubug日志 + if (!session.TableExist<fl_debug_log>()) + { + session.CreateTable<fl_debug_log>(); + } + + //群负责人 + if (!session.TableExist<fl_group_person>()) + { + session.CreateTable<fl_group_person>(); + session.AddIndex<fl_group_person>("groupid"); + } + + //私人pid + if (!session.TableExist<fl_private_pid>()) + { + session.CreateTable<fl_private_pid>(); + } + + //阿里妈妈维权表 + if (!session.TableExist<fl_order_refund_alimama>()) + { + session.CreateTable<fl_order_refund_alimama>(); + session.AddIndex<fl_order_refund_alimama>("tbtradeparentid", "tbtradeid"); + } + else + { + #region 以后可以删除 + try + { + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + session.ExcuteSQL("drop index fl_order_refund_alimama_tbTradeParentId_", new { }); + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + session.ExcuteSQL("ALTER TABLE fl_order_refund_alimama DROP INDEX tbTradeParentId", new { }); + } + } + catch (Exception ex) + { + } + #endregion + } + + //微信设备信息 + if (!session.TableExist<fl_wechat_device>()) + { + session.CreateTable<fl_wechat_device>(); + session.AddUnique("fl_wechat_device", "weixinhao"); + } + else + { + #region 修改mysql中varchar类型,类中text的类型 以后可以删除 + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + try + { + PropertyInfo[] Propertys = typeof(fl_wechat_device).GetProperties(); + foreach (var item in Propertys) + { + string _name = item.Name; + + if (_name.ToLower() == "device_info".ToLower()) + { + if (item.PropertyType.FullName == typeof(string).ToString()) + session.ExcuteSQL("ALTER TABLE fl_wechat_device MODIFY COLUMN " + _name + " Text", new { }); + } + } + } + catch (Exception ex) + { } + } + #endregion + } + + //用户信息表 + if (!session.TableExist<fl_member_info>()) + { + session.CreateTable<fl_member_info>(); + session.AddUnique<fl_member_info>("robot_type", "username"); + //session.AddIndex<fl_member_info>("inviter_id", "robot_type", "username"); + //session.AddIndex<fl_member_info>("status", "robot_name"); + session.AddIndex<fl_member_info>("robot_type", "username"); + session.AddIndex<fl_member_info>("crt_time", "robot_name"); + session.AddIndex<fl_member_info>("status"); + session.AddIndex<fl_member_info>("inviter_id"); + session.AddIndex<fl_member_info>("usernick"); + } + else + { + //if (!session.IndexExist<fl_member_info>("inviter_id")) + //{ + // session.AddIndex<fl_member_info>("inviter_id", "status", "robot_name"); + //} + var flag1 = checkIndex(session, "fl_member_info", "inviter_id", "robot_type", "username"); + var flag2 = checkIndex(session, "fl_member_info", "status", "robot_name"); + var flag3 = checkIndex(session, "fl_member_info", "inviter_id", "status", "robot_name"); + if (flag1 || flag2 || flag3) + { + session.AddIndex<fl_member_info>("robot_type", "username"); + session.AddIndex<fl_member_info>("crt_time", "robot_name"); + session.AddIndex<fl_member_info>("status"); + session.AddIndex<fl_member_info>("inviter_id"); + session.AddIndex<fl_member_info>("usernick"); + } + + if (!session.ColumnExist("fl_member_info", "ignore_group_update")) + { + session.AddColumn("fl_member_info", "ignore_group_update", "integer default 0"); + } + + if (!session.ColumnExist("fl_member_info", "chat_count")) + { + session.AddColumn("fl_member_info", "chat_count", "integer default 0"); + session.AddColumn("fl_member_info", "blackout_time", "datetime default '2000-01-01 00:00:00'"); + } + + if (!session.ColumnExist("fl_member_info", "identity_card")) + { + session.AddColumn("fl_member_info", "identity_card", "varchar(255)"); + } + + if (!session.ColumnExist("fl_member_info", "identity_name")) + { + session.AddColumn("fl_member_info", "identity_name", "varchar(255)"); + } + + if (!session.ColumnExist("fl_member_info", "ban_exchange_time")) + { + session.AddColumn("fl_member_info", "ban_exchange_time", "datetime default '2000-01-01 00:00:00'"); + } + + if (!session.ColumnExist("fl_member_info", "private_ratio")) + { + session.AddColumn("fl_member_info", "private_ratio", "double default 0"); + } + + if (!session.ColumnExist("fl_member_info", "realnick")) + { + session.AddColumn("fl_member_info", "realnick", "varchar(255) default ''"); + session.AddColumn("fl_member_info", "wechatid", "varchar(255) default ''"); + } + + if (!session.ColumnExist("fl_member_info", "check_cloud_black_time")) + { + session.AddColumn("fl_member_info", "check_cloud_black_time", "datetime default '2000-01-01 00:00:00'"); + session.AddColumn("fl_member_info", "is_cloud_black", "boolean default 0"); + } + + if (!session.ColumnExist("fl_member_info", "bind_order")) + { + session.AddColumn("fl_member_info", "bind_order", "integer default 0"); + + var members = session.Find<fl_member_info>("select * from fl_member_info").Where(f => f.finish_order != 0).ToList(); + for (int i = 0; i < members.Count; i++) + { + members[i].bind_order = members[i].finish_order; + } + var _num = (int)Math.Ceiling((decimal)members.Count / 500m); + for (int o = 1; o <= _num; o++) + { + var _list = members.Skip((o - 1) * 500).Take(500).ToList(); + session.Updateable(_list.ToArray()).ExecuteCommand(); + } + } + } + + //云黑名单 + if (!session.TableExist<fl_cloud_black>()) + { + session.CreateTable<fl_cloud_black>(); + session.AddUnique<fl_cloud_black>("memberid"); + } + + //用户其他信息记录表 + if (!session.TableExist<fl_statistics_record>()) + { + session.CreateTable<fl_statistics_record>(); + session.AddIndex<fl_statistics_record>("uid"); + session.AddUnique<fl_statistics_record>("uid"); + } + else + { + try + { + var result = session.FindTable("select uid from fl_statistics_record group by uid having count(uid) > 1 order by uid"); + + if (result.Rows.Count != 0) + { + for (int i = 0; i < result.Rows.Count; i++) + { + var uid = result.Rows[i]["uid"].ToString(); + var records = session.Find<fl_statistics_record>("uid = @uid", new { uid = uid }); + fl_statistics_record _record = null; + foreach (var record in records) + { + if (_record == null) + _record = record; + else + { + if (_record.ex1 == 0) + _record.ex1 += record.ex1; + if (_record.ex2 == 0) + _record.ex2 += record.ex2; + _record.ex3 += record.ex3; + _record.ex4 += record.ex4; + _record.ex5 += record.ex5; + _record.ex6 += record.ex6; + _record.ex7 += record.ex7; + _record.ex8 += record.ex8; + _record.ex9 += record.ex9; + _record.ex10 += record.ex10; + _record.ex11 += record.ex11; + _record.ex12 += record.ex12; + _record.querynum += record.querynum; + session.Deleteable<fl_statistics_record>().In(record.id).ExecuteCommand(); + } + } + if (_record != null) + session.Updateable(_record).ExecuteCommand(); + } + } + + if (!session.ExistUnique("fl_statistics_record", "uid")) + session.AddUnique<fl_statistics_record>("uid"); + } + catch (Exception ex) + { } + } + + + if (!session.TableExist<fl_member_level>()) + { + session.CreateTable<fl_member_level>(); + } + + if (!session.TableExist<fl_alimama_tlj_create_record>()) + { + session.CreateTable<fl_alimama_tlj_create_record>(); + session.AddUnique<fl_alimama_tlj_create_record>("cpsname"); + } + + if (!session.TableExist<fl_alimama_tlj_get_record>()) + { + session.CreateTable<fl_alimama_tlj_get_record>(); + session.AddUnique<fl_alimama_tlj_get_record>("itemid"); + session.AddIndex<fl_alimama_tlj_get_record>("itemid", "expiredate"); + } + + if (!session.TableExist<fl_plugin_info>()) + { + session.CreateTable<fl_plugin_info>(); + } + if (!session.TableExist<fl_robot_info>()) + { + session.CreateTable<fl_robot_info>(); + session.AddUnique<fl_robot_info>("name", "type"); + } + else + { + if (!session.ColumnExist("fl_robot_info", "is_receives")) + { + session.AddColumn("fl_robot_info", "is_receives", "integer default 1"); + } + + if (!session.ColumnExist("fl_robot_info", "off_line_tip")) + { + session.AddColumn("fl_robot_info", "off_line_tip", "integer default 1"); + } + + if (!session.ColumnExist("fl_robot_info", "off_line_auto_login")) + { + session.AddColumn("fl_robot_info", "off_line_auto_login", "integer default 1"); + } + + } + + if (session.TableExist("fl_member_private_config")) + { + session.DropTable("fl_member_private_config"); + } + if (!session.TableExist<fl_weixin_password>()) + { + session.CreateTable<fl_weixin_password>(); + session.AddUnique<fl_weixin_password>("robot_id"); + } + else + { + //这个字段没有什么用,最早之前不知道为什么要给fl_weixin_password继承base_model + if (!session.ColumnExist("fl_weixin_password", "db_status_time")) + { + session.AddColumn("fl_weixin_password", "db_status_time", "varchar(25)"); + } + } + + if (!session.TableExist<fl_cps_member>()) + { + session.CreateTable<fl_cps_member>(); + session.AddUnique<fl_cps_member>("username", "cpstype"); + } + else + { + if (!session.ColumnExist("fl_cps_member", "abnormal_tip")) + { + session.AddColumn("fl_cps_member", "abnormal_tip", "integer default 1"); + } + + if (!session.ColumnExist("fl_cps_member", "is_download")) + { + session.AddColumn("fl_cps_member", "is_download", "integer default 1"); + } + + if (!session.ColumnExist("fl_cps_member", "is_valid")) + { + session.AddColumn("fl_cps_member", "is_valid", "boolean default 1"); + } + } + + try + { + session.UpdateColumnType("fl_cps_member", "cookies", "longText"); + } + catch (Exception) + { } + + + + if (!session.TableExist<fl_point_hist>()) + { + session.CreateTable<fl_point_hist>(); + session.AddIndex<fl_point_hist>("crt_time", "type", "rid", "uid"); + session.AddIndex<fl_point_hist>("uid", "type"); + } + else + { + if (!session.ColumnExist("fl_point_hist", "after_point")) + { + session.AddColumn("fl_point_hist", "after_point", "double default 0"); + session.AddColumn("fl_point_hist", "before_point", "double default 0"); + } + + if (!session.ColumnExist("fl_point_hist", "rid")) + { + session.AddColumn("fl_point_hist", "rid", "integer default 0"); + } + + //if (!session.IndexExist<fl_point_hist>("crt_time")) + //{ + // session.AddIndex<fl_point_hist>("crt_time", "type", "rid", "uid"); + //} + } + + if (!session.TableExist<fl_create_info>()) + { + session.CreateTable<fl_create_info>(); + session.AddUnique<fl_create_info>("groupid", "chat_type"); + } + if (!session.TableExist<fl_alimama_order_lastnum>()) + { + session.CreateTable<fl_alimama_order_lastnum>(); + session.AddUnique<fl_alimama_order_lastnum>("lastnumber", "userid"); + session.AddIndex<fl_alimama_order_lastnum>("lastnumber"); + } + + if (!session.TableExist<fl_alimama_tlj_info>()) + { + session.CreateTable<fl_alimama_tlj_info>(); + session.AddUnique<fl_alimama_tlj_info>("username"); + } + + //添加淘宝比例 + if (!session.TableExist<fl_ratio_info>()) + { + session.CreateTable<fl_ratio_info>(); + session.AddUnique<fl_ratio_info>("comm", "cps_type"); + + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.阿里妈妈, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.阿里妈妈, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.阿里妈妈, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.京东联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.京东联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.京东联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.多多进宝, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.多多进宝, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.多多进宝, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + else + { + try + { + var tmps = session.Queryable<fl_ratio_info>().Where(f => f.cps_type == CpsType.唯品联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + } + catch (Exception) + { } + + try + { + var tmps = session.Queryable<fl_ratio_info>().Where(f => f.cps_type == CpsType.抖音联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + } + catch (Exception) + { } + } + + + if (!session.TableExist<fl_member_group>()) + { + session.CreateTable<fl_member_group>(); + session.AddUnique<fl_member_group>("name"); + session.AddUnique<fl_member_group>("terms", "terms_ordersum"); + session.Insertable<fl_member_group>(new fl_member_group() { name = "大众会员", terms = 0, terms_ordersum = 0, subsidy = 0.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_member_group>(new fl_member_group() { name = "黄金会员", terms = 20, terms_ordersum = 5, subsidy = 0.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_member_group>(new fl_member_group() { name = "铂金会员", terms = 100, terms_ordersum = 15, subsidy = 0.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_member_group>(new fl_member_group() { name = "钻石会员", terms = 500, terms_ordersum = 50, subsidy = 0.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + else + { + if (!session.ColumnExist("fl_member_group", "terms_ordersum")) + { + session.AddColumn("fl_member_group", "terms_ordersum", "integer default 0"); + try + { + session.AddUnique<fl_member_group>("terms", "terms_ordersum"); + + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + session.ExcuteSQL("drop INDEX fl_member_group_terms_", new { }); + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + session.ExcuteSQL("ALTER TABLE fl_member_group DROP INDEX terms", new { }); + } + } + catch (Exception ex) + { + } + } + } + + if (!session.TableExist<fl_order_sleep>()) + { + session.CreateTable<fl_order_sleep>(); + session.AddUnique<fl_order_sleep>("money", "cps_type"); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.阿里妈妈 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.阿里妈妈 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.京东联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.京东联盟 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.多多进宝 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.多多进宝 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.唯品联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.唯品联盟 }).ExecuteCommand(); + } + else + { + try + { + var tmps = session.Queryable<fl_order_sleep>().Where(f => f.cps_type == CpsType.唯品联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.唯品联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.唯品联盟 }).ExecuteCommand(); + } + } + catch (Exception) + { } + } + + if (!session.TableExist<fl_query_hist>()) + { + session.CreateTable<fl_query_hist>(); + session.AddIndex<fl_query_hist>("userid", "itemid", "adzoneid", "crt_time"); + } + else + { + if (!session.ColumnExist("fl_query_hist", "adzoneid")) + { + session.AddColumn("fl_query_hist", "adzoneid", "varchar(255)"); + } + + if (!session.ColumnExist("fl_query_hist", "mallid")) + { + session.Deleteable<fl_query_hist>().Where(f => f.crt_time < DateTime.Now.AddMonths(-2)).ExecuteCommand(); + session.AddColumn("fl_query_hist", "mallid", "varchar(30)"); + } + //if (!session.IndexExist<fl_query_hist>("userid")) + //{ + // session.AddIndex<fl_query_hist>("userid", "itemid", "adzoneid", "crt_time"); + //} + } + + if (!session.TableExist<fl_order_alimama>()) + { + session.CreateTable<fl_order_alimama>(); + session.AddUnique<fl_order_alimama>("trade_id", "trade_parent_id"); + session.AddIndex<fl_order_alimama>("create_time", "db_status"); + session.AddIndex<fl_order_alimama>("db_userid", "db_status"); + session.AddIndex<fl_order_alimama>("create_time", "db_userid"); + session.AddIndex<fl_order_alimama>("trade_parent_id"); + session.AddIndex<fl_order_alimama>("paid_time", "db_status"); + session.AddIndex<fl_order_alimama>("db_robotname", "db_robottype"); + session.AddIndex<fl_order_alimama>("earning_time", "db_status"); + //session.AddIndex<fl_order_alimama>("trade_parent_id", "db_userid", "adzone_id", "create_time"); + //session.AddIndex<fl_order_alimama>("num_iid", "item_title", "db_cpsnick", "db_cpsname"); + //session.AddIndex<fl_order_alimama>("db_status", "db_userid"); + } + else + { + //if (!session.IndexExist<fl_order_alimama>("db_status")) + //{ + // session.AddIndex<fl_order_alimama>("db_status", "db_userid"); + //} + + if (!session.IndexExist<fl_order_alimama>("db_status", "db_endtime")) + { + session.AddIndex<fl_order_alimama>("db_status", "db_endtime"); + } + if (!session.IndexExist<fl_order_alimama>("db_status", "create_time")) + { + session.AddIndex<fl_order_alimama>("db_status", "create_time"); + } + + var flag1 = checkIndex(session, "fl_order_alimama", "db_status", "db_userid"); + var flag2 = checkIndex(session, "fl_order_alimama", "item_title", "db_cpsnick", "db_cpsname"); + var flag3 = checkIndex(session, "fl_order_alimama", "trade_parent_id", "db_userid", "adzone_id", "create_time"); + var flag4 = checkIndex(session, "fl_order_alimama", "num_iid", "item_title", "db_cpsnick", "db_cpsname"); + var flag5 = checkIndex(session, "fl_order_alimama", "db_status", "db_userid"); + var flag6 = checkIndex(session, "fl_order_alimama", "db_userid", "adzone_id", "num_iid", "create_time"); + + if (flag1 || flag2 || flag3 || flag4 || flag5 || flag6) + { + session.AddIndex<fl_order_alimama>("create_time", "db_status"); + session.AddIndex<fl_order_alimama>("db_userid", "db_status"); + session.AddIndex<fl_order_alimama>("create_time", "db_userid"); + session.AddIndex<fl_order_alimama>("trade_parent_id"); + session.AddIndex<fl_order_alimama>("paid_time", "db_status"); + session.AddIndex<fl_order_alimama>("db_robotname", "db_robottype"); + session.AddIndex<fl_order_alimama>("earning_time", "db_status"); + } + + if (!session.ColumnExist("fl_order_alimama", "seller_id")) + { + session.AddColumn("fl_order_alimama", "seller_id", "varchar(30)"); + } + if (!session.ColumnExist("fl_order_alimama", "paid_time")) + { + session.AddColumn("fl_order_alimama", "paid_time", "datetime"); + } + if (!session.ColumnExist("fl_order_alimama", "deposit_price")) + { + session.AddColumn("fl_order_alimama", "deposit_price", "varchar(30)"); + } + if (!session.ColumnExist("fl_order_alimama", "tb_deposit_time")) + { + session.AddColumn("fl_order_alimama", "tb_deposit_time", "varchar(25)"); + } + if (!session.ColumnExist("fl_order_alimama", "db_status_time")) + { + session.AddColumn("fl_order_alimama", "db_status_time", "varchar(25)"); + } + if (!session.ColumnExist("fl_order_alimama", "alimama_rate")) + { + session.AddColumn("fl_order_alimama", "alimama_rate", "double default 0"); + } + if (!session.ColumnExist("fl_order_alimama", "alimama_share_fee")) + { + session.AddColumn("fl_order_alimama", "alimama_share_fee", "double default 0"); + } + } + + if (!session.TableExist<fl_order_pinduoduo>()) + { + session.CreateTable<fl_order_pinduoduo>(); + session.AddUnique<fl_order_pinduoduo>("order_sn"); + //session.AddIndex<fl_order_pinduoduo>("order_sn", "db_userid", "db_cpsnick", "order_create_time"); + //session.AddIndex<fl_order_pinduoduo>("db_cpsname", "p_id", "goods_name", "goods_id"); + //session.AddIndex<fl_order_pinduoduo>("db_status", "db_userid"); + + session.AddIndex<fl_order_pinduoduo>("db_userid", "db_status"); + session.AddIndex<fl_order_pinduoduo>("order_create_time", "db_status"); + session.AddIndex<fl_order_pinduoduo>("order_create_time", "db_userid"); + session.AddIndex<fl_order_pinduoduo>("db_status", "db_endtime"); + session.AddIndex<fl_order_pinduoduo>("db_robotname", "db_robottype"); + } + else + { + //if (!session.IndexExist<fl_order_pinduoduo>("db_status")) + //{ + // session.AddIndex<fl_order_pinduoduo>("db_status", "db_userid"); + //} + + //if (!session.IndexExist<fl_order_pinduoduo>("db_userid")) + //{ + // session.AddIndex<fl_order_pinduoduo>("db_userid", "db_cpsnick", "db_cpsname"); + // session.AddIndex<fl_order_pinduoduo>("p_id", "goods_name", "goods_id", "order_create_time"); + //} + + var flag1 = checkIndex(session, "fl_order_pinduoduo", "order_sn", "db_userid", "db_cpsnick", "order_create_time"); + var flag2 = checkIndex(session, "fl_order_pinduoduo", "db_cpsname", "p_id", "goods_name", "goods_id"); + var flag3 = checkIndex(session, "fl_order_pinduoduo", "db_status", "db_userid"); + var flag4 = checkIndex(session, "fl_order_pinduoduo", "db_userid", "db_cpsnick", "db_cpsname"); + var flag5 = checkIndex(session, "fl_order_pinduoduo", "p_id", "goods_name", "goods_id", "order_create_time"); + if (flag1 || flag2 || flag3 || flag4 || flag5) + { + session.AddIndex<fl_order_pinduoduo>("db_userid", "db_status"); + session.AddIndex<fl_order_pinduoduo>("order_create_time", "db_status"); + session.AddIndex<fl_order_pinduoduo>("order_create_time", "db_userid"); + session.AddIndex<fl_order_pinduoduo>("db_status", "db_endtime"); + session.AddIndex<fl_order_pinduoduo>("db_robotname", "db_robottype"); + } + + if (!session.ColumnExist("fl_order_pinduoduo", "mall_id")) + { + session.AddColumn("fl_order_pinduoduo", "mall_id", "varchar(30)"); + } + + if (!session.ColumnExist("fl_order_pinduoduo", "db_status_time")) + { + session.AddColumn("fl_order_pinduoduo", "db_status_time", "varchar(25)"); + } + + if (!session.ColumnExist("fl_order_pinduoduo", "price_compare_status")) + { + session.AddColumn("fl_order_pinduoduo", "price_compare_status", "integer"); + } + } + + if (!session.TableExist<fl_order_jingdong>()) + { + session.CreateTable<fl_order_jingdong>(); + session.AddUnique<fl_order_jingdong>("orderId", "skuId"); + //session.AddIndex<fl_order_jingdong>("orderId", "db_userid", "db_cpsnick", "orderTime"); + //session.AddIndex<fl_order_jingdong>("db_cpsname", "positionId", "skuId", "skuName"); + session.AddIndex<fl_order_jingdong>("db_userid", "db_status"); + session.AddIndex<fl_order_jingdong>("orderTime", "db_status"); + session.AddIndex<fl_order_jingdong>("orderTime", "db_userid"); + session.AddIndex<fl_order_jingdong>("db_status", "finishTime"); + session.AddIndex<fl_order_jingdong>("db_robotname", "db_robottype"); + } + else + { + //if (!session.IndexExist<fl_order_jingdong>("db_status")) + //{ + // session.AddIndex<fl_order_jingdong>("db_status", "db_userid"); + //} + + //if (!session.IndexExist<fl_order_jingdong>("db_userid")) + //{ + // session.AddIndex<fl_order_jingdong>("db_userid", "db_cpsnick", "db_cpsname"); + // session.AddIndex<fl_order_jingdong>("positionId", "skuId", "skuName", "orderTime"); + //} + + var flag1 = checkIndex(session, "fl_order_jingdong", "orderId", "db_userid", "db_cpsnick", "orderTime"); + var flag2 = checkIndex(session, "fl_order_jingdong", "db_cpsname", "positionId", "skuId", "skuName"); + var flag3 = checkIndex(session, "fl_order_jingdong", "db_status", "db_userid"); + var flag4 = checkIndex(session, "fl_order_jingdong", "db_userid", "db_cpsnick", "db_cpsname"); + var flag5 = checkIndex(session, "fl_order_jingdong", "positionId", "skuId", "skuName", "orderTime"); + if (flag1 || flag2 || flag3 || flag4 || flag5) + { + session.AddIndex<fl_order_jingdong>("db_userid", "db_status"); + session.AddIndex<fl_order_jingdong>("orderTime", "db_status"); + session.AddIndex<fl_order_jingdong>("orderTime", "db_userid"); + session.AddIndex<fl_order_jingdong>("db_status", "finishTime"); + session.AddIndex<fl_order_jingdong>("db_robotname", "db_robottype"); + } + + #region 增加一个字段 plus + + if (!session.ColumnExist("fl_order_jingdong", "plus")) + { + session.AddColumn("fl_order_jingdong", "plus", "integer default 0"); + } + + if (!session.ColumnExist("fl_order_jingdong", "db_status_time")) + { + session.AddColumn("fl_order_jingdong", "db_status_time", "varchar(25)"); + } + + #endregion + + #region 修改mysql中int类型,类中long的类型 以后可以删除 + //获取公共属性 + //if (session.CurrentConnectionConfig.DbType == DbType.MySql) + //{ + // PropertyInfo[] Propertys = typeof(fl_order_jingdong).GetProperties(); + // foreach (var item in Propertys) + // { + // string _name = item.Name; + // string _type = string.Empty; + // bool _primary = false; + // var _attribute = item.GetCustomAttributes().FirstOrDefault(f => f.GetType() == typeof(SugarColumn)) as SugarColumn; + // if (_attribute != null) + // { } + // if (item.Name.ToLower() == "id" || _primary) + // { } + // else if (!string.IsNullOrEmpty(_type)) + // { } + // else + // { + // if (item.PropertyType.FullName == typeof(Int64).ToString()) + // { + // session.ExcuteSQL("ALTER TABLE fl_order_jingdong MODIFY COLUMN " + _name + " bigint(11) DEFAULT 0", new { }); + // } + // } + // } + //} + #endregion + + #region 修改订单状态,最开始导致的,完成的订单变成了 部分退款 + //session.ExcuteSQL("update fl_order_jingdong set db_status = 1002 where db_status = 998"); + #endregion + + if (!session.ColumnExist("fl_order_jingdong", "refundcreatetime")) + { + session.AddColumn("fl_order_jingdong", "refundcreatetime", "datetime"); + } + } + + //000000 + if (!session.TableExist<fl_order_weipinhui>()) + { + session.CreateTable<fl_order_weipinhui>(); + session.AddUnique<fl_order_weipinhui>("orderSn", "goodsId", "sizeId"); + //session.AddUnique<fl_order_weipinhui>("orderSn"); + + session.AddIndex<fl_order_weipinhui>("db_userid", "db_status"); + session.AddIndex<fl_order_weipinhui>("orderTime", "db_status"); + session.AddIndex<fl_order_weipinhui>("orderTime", "db_userid"); + session.AddIndex<fl_order_weipinhui>("db_status", "db_endtime"); + session.AddIndex<fl_order_weipinhui>("db_robotname", "db_robottype"); + } + else + { + //if (session.CurrentConnectionConfig.DbType == DbType.Sqlite || (session.CurrentConnectionConfig.DbType == DbType.MySql && session.ExistUnique("fl_order_weipinhui", "orderSn"))) + //{ + // if (session.DeleteUnique("fl_order_weipinhui", "orderSn")) + // { + // try + // { + // session.AddUnique<fl_order_weipinhui>("orderSn", "goodsId"); + // } + // catch (Exception ex) + // { } + // } + //} + + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite || (session.CurrentConnectionConfig.DbType == DbType.MySql && session.ExistUnique("fl_order_weipinhui", "orderSn", "goodsId"))) + { + if (session.DeleteUnique("fl_order_weipinhui", "orderSn", "goodsId")) + { + try + { + session.AddUnique<fl_order_weipinhui>("orderSn", "goodsId", "sizeId"); + } + catch (Exception ex) + { } + } + } + } + + //000000 + if (!session.TableExist<fl_order_douyin>()) + { + session.CreateTable<fl_order_douyin>(); + session.AddUnique<fl_order_douyin>("order_id", "product_id"); + + session.AddIndex<fl_order_douyin>("db_userid", "db_status"); + session.AddIndex<fl_order_douyin>("pay_time", "db_status"); + session.AddIndex<fl_order_douyin>("pay_time", "db_userid"); + session.AddIndex<fl_order_douyin>("db_status", "db_endtime"); + session.AddIndex<fl_order_douyin>("db_robotname", "db_robottype"); + } + + if (!session.TableExist<fl_bind_cache>()) + { + session.CreateTable<fl_bind_cache>(); + session.AddIndex<fl_bind_cache>("orderid"); + } + + //try + //{ + // if (session.TableExist("fl_alimama_activity_pid")) + // session.DropTable("fl_alimama_activity_pid"); + // session.DropTable("fl_alimama_pid_activity"); + //} + //catch (Exception) + //{ } + + bool first = false; + if (!session.TableExist<fl_dictionary_item>()) + { + session.CreateTable<fl_dictionary_item>(); + session.AddUnique<fl_dictionary_item>("dickey"); + first = true; + } + + if (!session.TableExist<fl_exchange_info>()) + { + session.CreateTable<fl_exchange_info>(); + session.AddIndex<fl_exchange_info>("uid", "state"); + if (session.TableExist("fl_plugin_pointmanage_exchange_list")) + { + var queryable = session.Queryable("fl_plugin_pointmanage_exchange_list", "pel").AddJoinInfo("fl_robot_info", "r", "r.name = pel.robot_name").Select<fl_exchange_info>("r.id as rid,pel.*").ToList(); + session.Insertable(queryable).ExecuteCommand(); + } + } + else + { + if (!session.IndexExist<fl_exchange_info>("uid", "state")) + { + session.AddIndex<fl_exchange_info>("uid", "state"); + } + + if (!session.ColumnExist("fl_exchange_info", "groupid")) + { + session.AddColumn("fl_exchange_info", "groupid", "varchar(255)"); + } + + if (!session.ColumnExist("fl_exchange_info", "check_time")) + { + session.AddColumn("fl_exchange_info", "check_time", "datetime default '2000-01-01 00:00:00'"); + } + } + // session.Commit(); + return first; + } + catch (Exception ex) + { + throw ex; + } + return false; + } + + /// <summary> + /// 重置定时器 + /// </summary> + public static void ResetTimer() + { + //关闭以前的线程 + TimerTask.Close<ClearGarbageTimer>(); + TimerTask.Close<DownPinduoduoTimer>(); + TimerTask.Close<DownAlimamaTimer>(); + TimerTask.Close<DownJingdongTimer>(); + TimerTask.Close<DownWeipinhuiTimer>(); + TimerTask.Close<DownDouyinTimer>(); + TimerTask.Close<Update_NoticeQueue>(); + TimerTask.Close<Update_CpsStatus>(); + + //启动新的线程 + TimerTask.NewTimer<Update_NoticeQueue>(1);//处理队列消息 + TimerTask.NewTimer<Update_CpsStatus>(360);//更新联盟状态 + TimerTask.NewTimer<ClearGarbageTimer>(Setting.SystemConfig.timer_clear_memory); //注册清理垃圾线程 + TimerTask.NewTimer<DownPinduoduoTimer>(Setting.SystemConfig.time_down_pinduoduo); //下载拼多多订单线程 + TimerTask.NewTimer<DownAlimamaTimer>(Setting.SystemConfig.timer_down_alimama); //下载阿里妈妈订单线程 + TimerTask.NewTimer<DownJingdongTimer>(Setting.SystemConfig.time_down_jingdong); //下载京东订单线程 + TimerTask.NewTimer<DownWeipinhuiTimer>(Setting.SystemConfig.time_down_weipinhui); //下载唯品会订单线程 + TimerTask.NewTimer<DownDouyinTimer>(Setting.SystemConfig.time_down_douyin); //下载抖音订单线程 + } + /// <summary> + /// 缓存 + /// </summary> + public static CacheTool Cache { get; private set; } + + private static object getsession_lock = new object(); + public static SqlSugarClient GetSession(Api.Framework.Tools.ConnectionConfig config = null, bool iscache = true) + { + if (config == null) config = Setting.DbConfig; + + DbType type = DbType.MySql; + if (config.DatabaseType == DatabaseType.SQLITE) type = DbType.Sqlite; + else if (config.DatabaseType == DatabaseType.MYSQL) type = DbType.MySql; + else return null; + SqlSugarClient session = new SqlSugarClient(new SqlSugar.ConnectionConfig() + { + MoreSettings = new ConnMoreSettings() { IsAutoRemoveDataCache = true }, + ConnectionString = config.ConnectionString, //必填 + DbType = type, //必填 + IsAutoCloseConnection = true, + InitKeyType = InitKeyType.Attribute + }); + + return session; + } + + /// <summary> + /// 发送信息 + /// </summary> + /// <param name="message">消息内容</param> + /// <param name="robot">通过哪个机器人发送</param> + public static void SendAdminMessage(string message, fl_robot_info robot, string title = "系统消息") + { + //邮件通知管理员 + if (!string.IsNullOrEmpty(Setting.SystemConfig.account_admin_email)) + { + //邮箱通知 + var emails = Setting.SystemConfig.account_admin_email.Split(','); + foreach (var item in emails) + { + SendAdminEmail(item, title, title + "<br>" + message, true); + } + } + } + + /// <summary> + /// 发送邮件 + /// </summary> + /// <param name="toemail">收件人</param> + /// <param name="title">标题</param> + /// <param name="content">内容</param> + /// <param name="tryException">捕获</param> + /// <param name="begin">异步</param>//ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "机器人即将到期通知", msg, true); + public static void SendAdminEmail(string toemail, string title, string content, bool tryException = false, bool begin = true) + { + try + { + var config = Setting.SystemConfig; + Util.SendEmail(config.SMTP_Host, config.SMTP_Port, config.SMTP_User, config.SMTP_Pass, config.SMTP_SSL == SwitchType.开启 ? true : false, toemail, title, content, begin); + } + catch (Exception ex) + { + if (tryException) return; + else EventClient.OnEvent(null, "发送邮件:" + ex.Message); + } + } + + /// <summary> + /// 发送邮件 + /// </summary> + /// <param name="toemail">收件人</param> + /// <param name="title">标题</param> + /// <param name="content">内容</param> + /// <param name="file"></param> + /// <param name="tryException">捕获</param> + /// <param name="begin">异步</param>//ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "机器人即将到期通知", msg, true); + public static void SendAdminEmail(string toemail, string title, string content, string file, bool tryException = false, bool begin = true) + { + try + { + var config = Setting.SystemConfig; + Util.SendEmail(config.SMTP_Host, config.SMTP_Port, config.SMTP_User, config.SMTP_Pass, config.SMTP_SSL == SwitchType.开启, toemail, title, content, begin, file); + } + catch (Exception ex) + { + if (tryException) return; + else EventClient.OnEvent(null, "发送邮件:" + ex.Message); + } + } + + /// <summary> + /// 商户支付 + /// </summary> + /// <param name="remark"></param> + /// <param name="describe"></param> + /// <param name="money"></param> + /// <returns>返回 连接为点击领取 + /// 返回 "已转账"为自动转账 + /// 返回 空为异常</returns> + [Obsolete("改方法已过时")] + public static string SendWechatPay(object remark, string describe, double money) + { + try + { + var pay = new WechatPay(); + var result = string.Empty; + if (!string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_hostSign)) + { + result = pay.Create(Setting.SystemConfig.pay_wechat_hostSign, remark, describe, money); + Console.WriteLine(result); + } + else + { + result = pay.Create(Setting.SystemConfig.pay_wechat_gzh_appid, Setting.SystemConfig.pay_wechat_sh_appid, Setting.SystemConfig.pay_wechat_gzh_appsecret, Setting.SystemConfig.pay_wechat_sh_appsecret, money, HttpHelper.ObjectToJson(remark), describe); + } + //if (string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_host)) throw new Exception("您没有填写服务器信息!"); + if (!string.IsNullOrEmpty(result)) + { + if (result == "操作超时") + { + EventClient.OnEvent(null, $"【{money}积分】商户连接:{result}"); + result = string.Empty; + } + else if (result == "已转账") + { + //返回为空,获取商户异常 + return result; + } + } + return result; + } + catch (Exception ex) + { + EventClient.OnEvent(null, ex.Message); + } + return string.Empty; + } + + public static string SendWechatPay(object remark, string describe, double money, out bool ispaid) + { + ispaid = false; + try + { + var pay = new WechatPay(); + var result = string.Empty; + if (!string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_hostSign)) + { + result = pay.Create(Setting.SystemConfig.pay_wechat_hostSign, remark, describe, money, out ispaid); + Console.WriteLine(result); + } + else + { + result = pay.Create(Setting.SystemConfig.pay_wechat_gzh_appid, Setting.SystemConfig.pay_wechat_sh_appid, Setting.SystemConfig.pay_wechat_gzh_appsecret, Setting.SystemConfig.pay_wechat_sh_appsecret, money, HttpHelper.ObjectToJson(remark), describe); + } + //if (string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_host)) throw new Exception("您没有填写服务器信息!"); + if (!string.IsNullOrEmpty(result)) + { + if (result == "操作超时") + { + EventClient.OnEvent(null, $"【{money}积分】商户连接:{result}"); + ispaid = false; + return string.Empty; + } + //else if (result == "已转账") + //{ + // //返回为空,获取商户异常 + // return result; + //} + } + return result; + } + catch (Exception ex) + { + EventClient.OnEvent(null, ex.Message); + } + return string.Empty; + } + + /// <summary> + /// 发送钉钉消息 + /// </summary> + /// <param name="message">消息内容 </param> + /// <param name="api">默认选择系统自带接口、也可以自定义</param> + //public static void SendDingdingMessage(string _message, string api = "") + //{ + // if (!string.IsNullOrEmpty(api) && ApiClient.Setting.SystemConfig.notice_robotname != "请选择(钉钉/微信群机器人API名称)") + // { + // SendNoticeMessage(ApiClient.Setting.SystemConfig.notice_robotname, _message); + // return; + // } + // var _api = string.IsNullOrEmpty(api) ? ApiClient.Setting.SystemConfig.notice_dingding_robotapi : api; + // if (!string.IsNullOrEmpty(_api)) SendNoticeMessage(new fl_noticeapi_info() { name = "旧接口钉钉API地址", api_location = _api, notice_apitype = NoticeApiType.企业钉钉机器人API }, _message); + //} + + + public static void SendNewDingdingMessage(string _message, string api = "", string secret = "") + { + if (!string.IsNullOrEmpty(api) && ApiClient.Setting.SystemConfig.notice_robotname != "请选择(钉钉/微信群机器人API名称)") + { + SendNoticeMessage(_message); + return; + } + var _api = string.IsNullOrEmpty(api) ? ApiClient.Setting.SystemConfig.notice_dingding_robotapi : api; + var _api_token = string.IsNullOrEmpty(api) ? ApiClient.Setting.SystemConfig.notice_dingding_robotSecret : secret; + if (!string.IsNullOrEmpty(_api)) SendNoticeMessage(new fl_noticeapi_info() { name = "旧接口钉钉API地址", token = _api_token, api_location = _api, notice_apitype = NoticeApiType.企业钉钉机器人API }, _message); + + } + + /// <summary> + /// 发送通知【钉钉/微信群机器人】消息 + /// </summary> + /// <param name="name">名称,为空为系统设置</param> + /// <param name="message">消息内容</param> + public static void SendNoticeMessage(string message, string name = "") + { + if (string.IsNullOrWhiteSpace(name) || name == "请选择(钉钉/微信群机器人API名称)") + name = ApiClient.Setting.SystemConfig.notice_robotname; + var session = ApiClient.GetSession(); + var api = session.FindNoticeapiRobots().FirstOrDefault(f => f.name == name); + if (api != null) SendNoticeMessage(api, message); + } + + public static void SendNoticeMessage(fl_noticeapi_info api_entity, string message, bool is_begin = true) + { + if (api_entity == null || api_entity.name == "请选择(钉钉/微信群机器人API名称)") return; + var _info = api_entity; + var _message = message.Replace("\r\n", "\n"); ; + Exception exception = null; + var action = new Action(delegate + { + for (int i = 0; i < 10; i++) + { + try + { + var http = new HttpHelper(); + var item = http.GetItem(_info.api_location); + item.Method = "post"; + item.ContentType = "application/json;";//返回类型 可选项有默认值 + switch (_info.notice_apitype) + { + case NoticeApiType.企业钉钉机器人API: + { + if (!string.IsNullOrEmpty(_info.token)) + { + long dingTimestamp = (DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, 0).Ticks) / 10000; + string canonicalString = $"{dingTimestamp}\n{_info.token}"; + string signature = Convert.ToBase64String(Sign(Encoding.UTF8.GetBytes(canonicalString), Encoding.UTF8.GetBytes(_info.token))); + item.URL = item.URL + $"×tamp={dingTimestamp}&sign={signature}"; + } + item.PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte; + item.PostdataByte = Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { msgtype = "text", text = new { content = _message } })); + } + break; + case NoticeApiType.企业微信机器人API: + { + item.PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte; + item.PostdataByte = Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { msgtype = "text", text = new { content = _message } })); + } + break; + case NoticeApiType.飞书机器人API: + { + item.PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte; + if (_info.api_location.Contains("bot/v2/hook")) + item.PostdataByte = Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { msg_type = "text", content = new { text = _message } })); + else + item.PostdataByte = Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { title = "", text = _message })); + } + break; + default: throw new Exception("无法识别的API类型!" + _info.notice_apitype.ToString()); + } + + var html = http.GetHtml(item).Html; + Console.WriteLine(html); + if (html.Contains("ok") || html.Contains("success")) + return; + throw new Exception(html); + } + catch (Exception ex) + { + if (ex.Message.Contains("sign not match")) + { + Thread.Sleep(370); + continue; + } + exception = ex; + EventClient.OnEvent(null, $"{_info.name}提醒失败:" + ex.Message); + } + } + }); + if (is_begin) action.BeginInvoke(null, null); + else + { + action.Invoke(); + + //抛出异常信息 + if (exception != null) throw exception; + } + } + + private static byte[] Sign(byte[] key, byte[] data) + { + HMACSHA256 sha256 = new HMACSHA256(data); + return sha256.ComputeHash(key); + } + + static ConcurrentDictionary<string, ConcurrentQueue<temp_send_data>> MessageQueue = new ConcurrentDictionary<string, ConcurrentQueue<temp_send_data>>(); + + /// <summary> + /// 发送消息2 + /// </summary> + /// <param name="robot">机器人</param> + /// <param name="tousername">发送给谁</param> + /// <param name="message">发送的消息SendNewDingdingMessage</param> + /// <param name="groupid">发送的群(空位私聊)</param> + /// <param name="TempMsgID">QQ的临时会话ID</param> + /// <param name="token">临时会话的token</param> + /// <returns></returns> + //public static Task SendWQMessage(fl_robot_info robot, string tousername, string message, string groupid = "", uint TempMsgID = 0, byte[] token = null) + //{ + // return SendMessage(new temp_send_data() { Groupid = groupid, Message = message, TouserName = tousername, Robot = robot, TempMsgID = TempMsgID, token = token }); + //} + + /// <summary> + /// 发送消息1 + /// </summary> + /// <param name="robot">机器人</param> + /// <param name="tousername">发送给谁</param> + /// <param name="message"></param> + /// <param name="groupid"></param> + public static Task SendMessage(fl_robot_info robot, string tousername, string message, string groupid = "") + { + return SendMessage(new temp_send_data() { Groupid = groupid, Message = message, TouserName = tousername, Robot = robot }); + } + public static Task SendMessage(fl_robot_info robot, string tousername, string message, bool isTemp) + { + return SendMessage(new temp_send_data() { IsTemp = isTemp, Message = message, TouserName = tousername, Robot = robot }); + } + + public static Task SendMessage(params temp_send_data[] data) + { + var _data = data; + return Task.Run(() => + { + try + { + for (int i = 0; i < _data.Length; i++) + { + var item = _data[i]; + if (i > 0) Thread.Sleep(650); + try + { + #region 不处理不接受的机器人 + var session = ApiClient.GetSession(); + var robots = session.FindRobots(); + if (null != robots.FirstOrDefault(f => f.is_receives == Enums.SwitchType.关闭 && item.Robot.name == f.name)) + continue; + #endregion + + var groupid = item.Groupid; + var tousername = item.TouserName; + var robot = item.Robot; + var message = item.Message.Replace("[积分名称]", Setting.SystemConfig.PointName).Replace("[机器人账号]", robot.name).Replace("[机器人昵称]", robot.nick).Trim(); + + if (message.Contains("[编号]")) + { + string id = string.Empty; + var member = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = item.TouserName }); + if (member != null) + id = member.id.ToString(); + message = message.Replace("[编号]", id); + } + + switch (item.Robot.type) + { + case ChatType.QQ: + { + var qBase = ChatClient.QQClients.FirstOrDefault(f => f.Key.ToString() == robot.name).Value; + + if (qBase is QQClientImpl_QQPlus) + { + var tmp = (qBase as QQClientImpl_QQPlus); + var qq = tmp.QQClient; + if (qq != null && qq.User != null && qq.User.LoginStatus == LoginStatus.Login) + { + if (!string.IsNullOrWhiteSpace(tousername)) + { + var member = session.FindBlacklistMemberInfos().FirstOrDefault(f => f.username == tousername); + if (member != null) break; + + if (message.Contains("[昵称]")) + { + member = session.FindSingle<fl_member_info>("select * from fl_member_info where robot_type = @robot_type and username = @username", new { username = tousername, robot_type = ChatType.QQ }); + if (member != null) + message = message.Replace("[账号]", tousername).Replace("[昵称]", member.usernick); + else + message = message.Replace("[账号]", tousername).Replace("[昵称]", string.Empty); + } + } + message = new VariateReplace().ReplaceUserVariate(message).Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + + uint target = 1; + var isGroup = false; + uint toUsernaem = 0; + if (string.IsNullOrEmpty(groupid)) + uint.TryParse(tousername, out target); + else + { + uint.TryParse(groupid, out target); + isGroup = true; + } + tmp.SendMessage(target, message, isGroup, item.IsTemp); + } + } + } + break; + case ChatType.微信: + case ChatType.企业微信: + { + if (!string.IsNullOrWhiteSpace(tousername)) + { + var member = session.FindBlacklistMemberInfos().FirstOrDefault(f => f.username == tousername); + if (member != null) break; + if (message.Contains("[昵称]")) + { + member = session.FindSingle<fl_member_info>("select * from fl_member_info where robot_type = @robot_type and username = @username", new { username = tousername, robot_type = item.Robot.type }); + message = message.Replace("[昵称]", member == null ? string.Empty : member.usernick); + } + message = message.Replace("[账号]", tousername); + } + message = new VariateReplace().ReplaceUserVariate(message).Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + + + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == robot.name).Value; + + if (wx != null && wx.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + message.Replace("[机器人微信]", wx.User.Username); + wx.SendMessage(string.IsNullOrWhiteSpace(groupid) ? tousername : groupid, message); + //EventClient.OnEvent(item, $"协议:{wx.WeixinHao} 给 {tousername} 发送 -> {message}"); + } + else + { + //EventClient.OnEvent(item, $"pc {robot.name} 发送:{message}"); + + var client = ChatClient.PCRobotPool.GetSession(robot.name); + if (client != null) + { + WechatMsgType messageType = WechatMsgType.文本; + PCRobotCMD robotCMD = PCRobotCMD.sendTxt; + + message.Replace("[机器人微信]", robot.name); + + #region 发送图片 + var match = Regex.Match(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Success) + { + var image = match.Groups[1].Value; + + //if (!image.StartsWith("http")) + //{ + // if (File.Exists(image)) + // { + // var bitmap = Util.PercentImage(Util.ReadImageFile(image), 280); + // var _image = image + Path.GetExtension(image);//压缩图片的地址 + // if (Util.YaSuo(bitmap, _image, 70)) + // { + // image = Util.FileToBase64(_image); + // } + // } + //} + message = image; + + messageType = WechatMsgType.图片; + robotCMD = PCRobotCMD.sendImg; + } + #endregion + + #region 发送视频 + match = Regex.Match(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Success) + { + //var video = Util.StrToHex(match.Groups[1].Value); + //if (video != null) + //{ + // var video_json = Encoding.UTF8.GetString(video); + // var video_data = CsharpHttpHelper.HttpExtend.JsonToDictionary(video_json); + // if (video_data != null) + // { + // //(username, video_data["cdnurl"].ToString(), video_data["aeskey"].ToString(), CDNType.发送视频); + + // } + //} + + message = match.Groups[1].Value; + + messageType = WechatMsgType.视频; + robotCMD = PCRobotCMD.sendFile; + } + #endregion + + #region 发送语音 + match = Regex.Match(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Success) + { + throw new Exception("PC协议不支持语音发送"); + } + #endregion + + if (string.IsNullOrWhiteSpace(message)) return; + + var msg = new ServerWechatMsg() + { + Cmd = robotCMD, + RobotType = item.Robot.type == ChatType.企业微信 ? RobotType.客户端企业微信 : RobotType.客户端微信, + RobotUsername = robot.name, + RobotUsernick = string.Empty, + ToMessage = message, + ToMessageType = messageType, + ToUsername = string.IsNullOrWhiteSpace(groupid) ? tousername : groupid, + Key = Setting.ServerConfig.SocketPassword + }; + //Console.WriteLine(groupid); + var json = HttpHelper.ObjectToJson(msg); + var text = PackTool.CompressString(json); + //AESCryption aes = new AESCryption(); + //json = aes.AesEncrypt(json,Setting.ServerConfig.SocketPassword.Substring(0,16)); + //Console.WriteLine(json); + var need_send = $"{msg.Cmd} {text}\r\n"; + //var need_send_data = Encoding.UTF8.GetBytes(need_send); + client.TrySend(need_send); + + } + } + } + break; + case ChatType.微信公众号: + break; + case ChatType.未知来源: + break; + default: + break; + } + } + catch (Exception ex) + { + EventClient.OnEvent(item, $"发送通知消息失败:{item.Robot.name}->{item.TouserName}->{item.Message},{ex.Message} - {ex.StackTrace}"); + } + } + } + catch (Exception) + { } + }); + } + + /// <summary> + /// 发送消息 + /// </summary> + /// <param name="robot_name">机器人账号</param> + /// <param name="robot_type">机器人类型</param> + /// <param name="tousername">发送给谁</param> + /// <param name="message">发送消息内容</param> + /// <param name="groupid">发送的群号</param> + public static void SendMessage(string robot_name, ChatType robot_type, string tousername, string message, string groupid = "") + { + var session = GetSession(); + var robot = session.FindRobots().FirstOrDefault(f => f.name == robot_name && f.type == robot_type); + if (robot != null) SendMessage(robot, tousername, message, groupid); + } + + /// <summary> + /// 缩短网址 - 根据配置的短网址类型 + /// </summary> + /// <param name="url">目标URL</param> + /// <returns></returns> + public static Task<string> ShortURL(string url) + { + return ShortURL(url, Setting.SystemConfig.dwz_type); + } + + /// <summary> + /// 缩短网址 - 自定义短网址类型 + /// </summary> + /// <param name="url">目标网址</param> + /// <param name="type">缩短类型</param> + /// <returns></returns> + public static Task<string> ShortURL(string url, DwzType type) + { + return Task.Factory.StartNew<string>(() => + { + var http = new HttpHelper(); + int num = 0; + var html = string.Empty; + Next: + try + { + num++; + + if (EventClient.ReplaceURL != null) + { + var temp = EventClient.ReplaceURL(0, url); + if (!string.IsNullOrEmpty(temp)) return temp; + } + + switch (type) + { + #region xxx + //case DwzType.新浪短网址: + //{ + // #region 老的新浪 xx + // //html = http.GetHtml("http://api.t.sina.com.cn/short_url/shorten.json?source=3271760578&url_long=" + HttpHelper.URLEncode(url)).Html; + // //if (!string.IsNullOrWhiteSpace(html) && html.ToLower().Contains("url_short")) + // //{ + // // var array = CsharpHttpHelper.HttpHelper.JsonToObject<ArrayList>(html) as ArrayList; + // // if (array != null && array.Count > 0) + // // { + // // var dic = array[0] as Dictionary<string, object>; + // // return dic["url_short"].ToString().Replace("http://", "https://"); + // // } + // //} + // //break; + // #endregion + + // #region 新浪 + // var _url = $"https://service.weibo.com/share/share.php?url={HttpHelper.URLEncode(url)}&title=%e4%b8%ad%e9%97%b4%e9%a1%b5"; + // html = http.GetHtml(_url).Html; + // if (!string.IsNullOrWhiteSpace(html)) + // { + // var reg = Regex.Match(html, @"href=""(?<短连接>https?://t.cn/(?:[^""]+?))"""); + // if (reg.Success) + // { + // var shorturl = reg.Groups["短连接"].Value; + // return shorturl.Replace("http://", "https://"); + // } + // } + // break; + // #endregion + //} + //case DwzType.新新浪短网址: + //{ + // var _url = $"https://service.weibo.com/share/share.php?url={HttpHelper.URLEncode(url)}&title=%e4%b8%ad%e9%97%b4%e9%a1%b5"; + // html = http.GetHtml(_url).Html; + // if (!string.IsNullOrWhiteSpace(html)) + // { + // var reg = Regex.Match(html, @"href=""(?<短连接>https?://t.cn/(?:[^""]+?))"""); + // if (reg.Success) + // { + // var shorturl = reg.Groups["短连接"].Value; + // return shorturl.Replace("http://", "https://").Replace("t.cn/", "sinaurl.cn/"); + // } + // } + // break; + //} + //case DwzType.腾讯短网址: + //{ + // var data = CsharpHttpHelper.HttpHelper.URLEncode(url); + // html = http.GetHtml($"http://sa.sogou.com/gettiny?url={data}").Html; + // if (!string.IsNullOrWhiteSpace(html) && html.ToLower().Contains("url.cn")) + // return html; + // break; + //} + //case DwzType.百度短网址://收费 + //{ + //if (!string.IsNullOrWhiteSpace(Setting.SystemConfig.DwzToken)) + //{ + // try + // { + // var data = HttpHelper.ObjectToJson(new { Url = url, TermOfValidity = "1-year" }); + // var item = new HttpItem() + // { + // URL = "https://dwz.cn/admin/v2/create", + // Method = "post", + // Encoding = Encoding.UTF8, + // UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统 可选项有默认值 + // ContentType = "application/json;",//返回类型 可选项有默认值 + // PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte, + // PostdataByte = Encoding.UTF8.GetBytes(data),//HttpUtility.UrlEncode(data), + // Timeout = 5000, + // ReadWriteTimeout = 5000 + // }; + // item.Header.Add("token", Setting.SystemConfig.DwzToken); + // html = http.GetHtml(item).Html; + // if (!string.IsNullOrWhiteSpace(html)) + // { + // //{"Code":0,"ShortUrl":"https://dwz.cn/kiJerp0h","LongUrl":"https://www.hifige.com/collection-album/yuanzhua","ErrMsg":""} + // var json = HttpExtend.JsonToDictionary(html); + // if (json != null && json.ContainsKey("Code")) + // { + // var code = json["Code"].ToString(); + // if (code == "0" && json.ContainsKey("ShortUrl")) + // { + // var shortUrl = json["ShortUrl"].ToString(); + // return shortUrl; + // } + // EventClient.OnEvent(null, $"百度短连接获取失败:{html}"); + // } + // } + // } + // catch (Exception ex) + // { + // EventClient.OnEvent(null, "百度短连接生成失败:" + ex.Message); + // } + //} + //else + //{ + // EventClient.OnEvent(null, $"转链失败:百度短网址Token值为空【系统设置 => 6.百度短网址设置 中设置】"); + //} + //return url; + //break; + //} + //case DwzType.UC浏览器短网址: + //{ + // // var url = "http://www.qq.com"; + // byte[] sign_password = new byte[38]; + // sign_password[0] = 48; + // sign_password[1] = 0; + // sign_password[2] = 57; + // sign_password[3] = 0; + // sign_password[4] = 58; + // sign_password[5] = 0; + // sign_password[6] = 49; + // sign_password[7] = 0; + // sign_password[8] = 53; + // sign_password[9] = 0; + // sign_password[10] = 89; + // sign_password[11] = 0; + // sign_password[12] = 103; + // sign_password[13] = 0; + // sign_password[14] = 125; + // sign_password[15] = 0; + // sign_password[16] = 78; + // sign_password[17] = 0; + // sign_password[18] = 74; + // sign_password[19] = 0; + // sign_password[20] = 112; + // sign_password[21] = 0; + // sign_password[22] = 125; + // sign_password[23] = 0; + // sign_password[24] = 85; + // sign_password[25] = 0; + // sign_password[26] = 67; + // sign_password[27] = 0; + // sign_password[28] = 83; + // sign_password[29] = 0; + // sign_password[30] = 104; + // sign_password[31] = 0; + // sign_password[32] = 97; + // sign_password[33] = 0; + // sign_password[34] = 114; + // sign_password[35] = 0; + // sign_password[36] = 101; + // sign_password[37] = 0; + // var sign = HttpHelper.ToMD5(System.Text.Encoding.Unicode.GetString(sign_password) + url).ToUpper(); + // var item = http.GetItem("http://t.uc.cn/short_url/shorten", "", $"app_key=UCShare&url_long={HttpHelper.URLEncode(url)}&sign={sign}"); + // html = http.GetHtml(item).Html; + // var success_reg = System.Text.RegularExpressions.Regex.Match(html, @"""url_short"":""http://fxt.ucdesk.cn/(.*?)"""); + // if (success_reg.Success) return "http://t.uc.cn/" + success_reg.Groups[1].Value; + //} + //break; + #endregion + case DwzType.百度短网址://收费 + { + if (!string.IsNullOrWhiteSpace(Setting.SystemConfig.DwzToken)) + { + try + { + var data = HttpHelper.ObjectToJson(new { Url = url, TermOfValidity = "1-year" }); + var item = new HttpItem() + { + URL = "https://dwz.cn/admin/v2/create", + //URL = "https://dwz.cn/api/v3/short-urls", + Method = "post", + Encoding = Encoding.UTF8, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "application/json;",//返回类型 可选项有默认值 + PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte, + PostdataByte = Encoding.UTF8.GetBytes(data),//HttpUtility.UrlEncode(data), + Timeout = 5000, + ReadWriteTimeout = 5000 + }; + item.Header.Add("token", Setting.SystemConfig.DwzToken); + html = http.GetHtml(item).Html; + if (!string.IsNullOrWhiteSpace(html)) + { + //{"Code":0,"ShortUrl":"https://dwz.cn/kiJerp0h","LongUrl":"https://www.hifige.com/collection-album/yuanzhua","ErrMsg":""} + var json = HttpExtend.JsonToDictionary(html); + if (json != null && json.ContainsKey("Code")) + { + var code = json["Code"].ToString(); + if (code == "0" && json.ContainsKey("ShortUrl")) + { + var shortUrl = json["ShortUrl"].ToString(); + return shortUrl; + } + EventClient.OnEvent(null, $"百度短连接获取失败:{html}"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(null, "百度短连接生成失败:" + ex.Message); + } + } + else + { + EventClient.OnEvent(null, $"转链失败:百度短网址Token值为空【系统设置 => 6.百度短网址设置 中设置】"); + } + return url; + break; + } + case DwzType.UC浏览器短网址: + case DwzType.新浪短网址: + case DwzType.新新浪短网址: + case DwzType.腾讯短网址: + //case DwzType.百度短网址: + case DwzType.官方短网址: + { + //for (int i = 0; i < 3; i++) + //{ + // var xx = HttpHelper.URLEncode(url); + // var sign = HttpHelper.ToMD5("23658" + url + "pMr7E2oPjvXI5ME1tZ0etTcenA7xgCzh"); + // var _url = $"https://url.api.52cmg.cn/generate?url={xx}&sign={sign}&appid=23658"; + // html = http.GetHtml(_url).Html; + // if (!string.IsNullOrWhiteSpace(html)) + // { + // if (html.Contains("ok")) + // { + // JObject json = JObject.Parse(html); + // if (!(bool)json["ok"]) return url; + // return json["url"].ToString(); + // } + // } + // Thread.Sleep(10); + // Console.WriteLine("html = " + html); + // Console.WriteLine("url = " + url); + //} + + HttpHelper helper = new HttpHelper(); + HttpItem item = new HttpItem();//https://url.api.52cmg.cn/generate?url=http://www.baidu.com&sign=E086A45084D1B490C411DEBD71E9DA4A&appid=23658 + + //var ccTLD = "https://url.api.52cmg.cn/generate"; + //if (!string.IsNullOrWhiteSpace(ccTLD)) + // ccTLD = ApiClient.Setting.SystemConfig.URLDwz; + + item.URL = "https://url.api.52cmg.cn/generate?url=" + System.Web.HttpUtility.UrlEncode(url) + $"&sign={GetSign(url, "23658")}&appid=23658"; + //item.URL = $"{ccTLD}?url={System.Web.HttpUtility.UrlEncode(url)}&sign={GetSign(url, "23658")}&appid=23658"; + for (int z = 0; z < 5; z++) + { + html = helper.GetHtml(item).Html; + if (html.Contains("\"ok\":true")) + { + Newtonsoft.Json.Linq.JObject j = Newtonsoft.Json.Linq.JObject.Parse(html); + var result = j["url"].ToString(); + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.URLDwz)) + { + var reg = Regex.Match(result, "id=([a-zA-Z0-9]+)"); + if (reg.Success) + { + if (ApiClient.Setting.SystemConfig.URLDwz.Contains("[序号]")) + { + result = ApiClient.Setting.SystemConfig.URLDwz.Replace("[序号]", reg.Groups[1].Value); + } + else if (ApiClient.Setting.SystemConfig.URLDwz.EndsWith("/")) + { + result = ApiClient.Setting.SystemConfig.URLDwz + "?id=" + reg.Groups[1].Value; + } + else + { + result = ApiClient.Setting.SystemConfig.URLDwz + "/?id=" + reg.Groups[1].Value; + } + + if (!result.StartsWith("http")) result = "http://" + result; + } + } + return result; + } + Thread.Sleep(10); + Console.WriteLine("html = " + html); + Console.WriteLine("url = " + url); + Console.WriteLine("item.URL = " + item.URL); + } + return url; + } + break; + case DwzType.缩我短网址: + { + for (int i = 0; i < 3; i++) + { + var data = CsharpHttpHelper.HttpHelper.URLEncode(url); + var date = DateTime.Today.AddMonths(6).ToString("yyyy-MM-dd"); + html = http.GetHtml($"http://suo.im/api.htm?url={data}&key=5dba8ad5b1a9c71e1cd3a570@731360bd06f09592d5843dd6bed51c2f&expireDate={date}").Html; + if (!string.IsNullOrWhiteSpace(html) && !html.Contains("未能解析此远程名称") && html.ToLower().Contains("suo.im")) + return html; + Thread.Sleep(100); + } + + break; + } + case DwzType.快站短网址: + { + return KuaiZhanShort.GetShort(url); + } + break; + case DwzType.不缩短域名: + return url; + } + } + catch (Exception ex) + { + EventClient.OnEvent(null, $"短连接异常:html => {html} - { ex.Message} - {ex.Source}"); + } + if (num <= 3) + { + if (type == DwzType.缩我短网址) type = DwzType.腾讯短网址; + else if (type == DwzType.腾讯短网址) type = DwzType.新浪短网址; + else if (type == DwzType.官方短网址) type = DwzType.缩我短网址; + else type = DwzType.快站短网址; + goto Next; + } + return url; + }); + } + + #region 关芳端连街 + public static string GetSign(string url, string appid) + { + var appSecret = "pMr7E2oPjvXI5ME1tZ0etTcenA7xgCzh"; + if (!string.IsNullOrEmpty(appSecret)) + { + string md5 = MD5Encrypt32(appid + url + appSecret); + return md5; + } + return ""; + } + + /// <summary> + /// 32位MD5加密 + /// </summary> + /// <param name="password"></param> + /// <returns></returns> + public static string MD5Encrypt32(string password) + { + string passwordFormat = FormsAuthPasswordFormat.MD5.ToString(); + return FormsAuthentication.HashPasswordForStoringInConfigFile(password, passwordFormat); + } + #endregion + + /// <summary> + /// 生成二维码图片 + /// </summary> + /// <param name="text">二维码内容</param> + /// <returns></returns> + private static Bitmap Generate3(string text) + { + MultiFormatWriter writer = new MultiFormatWriter(); + BitMatrix bm = writer.encode(text, BarcodeFormat.QR_CODE, 200, 200); + BarcodeWriter barcodeWriter = new BarcodeWriter(); + Bitmap map = barcodeWriter.Write(bm); + int[] rectangle = bm.getEnclosingRectangle(); + Bitmap bmpimg = new Bitmap(rectangle[2], rectangle[3], PixelFormat.Format32bppArgb); + using (Graphics g = Graphics.FromImage(bmpimg)) + { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + g.DrawImage(map, 0 - rectangle[0], 0 - rectangle[1]); + } + return bmpimg; + } + + public enum QrImageType + { + 模板A = 0, + 模板B = 1, + 模板C = 2, + } + + /// <summary> + /// 合成二维码 + /// </summary> + /// <param name="title">标题</param> + /// <param name="price">价格</param> + /// <param name="cprice">券价格</param> + /// <param name="nprice">券后价格</param> + /// <param name="image">图片地址</param> + /// <param name="link">生成二维码的链接</param> + /// <param name="type">使用的模板</param> + /// <param name="cps">联盟类型,自动填写内容</param> + /// <param name="content">底栏内容</param> + /// <param name="basePath">保存路径</param> + /// <returns></returns> + public static string GetQRImage(string title, string price, string cprice, string nprice, string image, string link, QrImageType type = QrImageType.模板B, CpsType cps = CpsType.阿里妈妈, string content = "", string basePath = "") + { + if (string.IsNullOrWhiteSpace(content)) + { + switch (cps) + { + case CpsType.阿里妈妈: + { + if (type == QrImageType.模板A) + content = " 长按识别二维码 > 复制淘口令 > 打开手机淘宝 > 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按识别二维码 >> 复制淘口令 >> 打开手机淘宝 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + case CpsType.多多进宝: + { + if (type == QrImageType.模板A) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + case CpsType.京东联盟: + { + if (type == QrImageType.模板A) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + case CpsType.唯品联盟: + { + if (type == QrImageType.模板A) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + } + } + int number = 0; + Next: + Bitmap img = null; + Image mainpic = null; + try + { + string imagePath = string.Empty; + try + { + mainpic = null; + imagePath = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + if (!image.StartsWith("http")) image = "http:" + image; + mainpic = FileTools.DownloadImage(image, imagePath); + } + catch (Exception ex) + { + throw new Exception($"读取图片异常:图片路径 = {imagePath} .{ex.Message} - {ex.StackTrace}"); + } + if (mainpic == null) throw new Exception($"下载图片失败:图片url = {image}"); + + switch (type) + { + case QrImageType.模板A: + { + double rate = mainpic.Width / 800.00; + double height = mainpic.Height / rate; + img = new Bitmap(800, int.Parse((height + 424).ToString("0"))); + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.High; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.DrawImage(mainpic, 0, 0, 800, int.Parse((height).ToString("0"))); + graphics.DrawImage(Properties.Resources.foot, 0, int.Parse((height).ToString("0")), 800, 424); + graphics.DrawImage(Generate3(link), 510, int.Parse((height + 50).ToString("0")), 225, 220); + var font = new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular); + RectangleF rec = new RectangleF(20, int.Parse((height + 50).ToString("0")), 450, 150); + Brush brush = new SolidBrush(Color.FromArgb(53, 53, 53)); + graphics.DrawString(" " + title, font, brush, rec); + graphics.DrawString("¥", new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(148, 148, 148)), 90, int.Parse((height + 204).ToString("0"))); + graphics.DrawString(price, new Font("微软雅黑", 20, System.Drawing.FontStyle.Strikeout), new SolidBrush(Color.FromArgb(148, 148, 148)), 115, int.Parse((height + 204).ToString("0"))); + graphics.DrawString(nprice, new Font("微软雅黑", 28, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(243, 119, 7)), 265, int.Parse((height + 247).ToString("0"))); + graphics.DrawString(cprice.Split('.')[0] + "元", new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(243, 119, 7)), 65, int.Parse((height + 255).ToString("0"))); + RectangleF rec2 = new RectangleF(10, int.Parse((height + 337).ToString("0")), 780, 70); + Brush brush2 = new SolidBrush(Color.FromArgb(243, 119, 7)); + graphics.DrawString(content, font, brush2, rec2); + } + } + break; + case QrImageType.模板B: + { + var foot = Properties.Resources.模板B; + var width = (int)foot.Width; + var height = (int)foot.Height; + img = new Bitmap(width, height); + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.High; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.DrawImage(foot, 0, 0, width, height); + graphics.DrawImage(mainpic, 0, 0, width, (int)(height * 0.56)); + graphics.DrawImage(Generate3(link), 296, 1050, 165, 165); + RectangleF rec = new RectangleF(20, 760, 700, 150); + Brush brush = new SolidBrush(Color.FromArgb(53, 53, 53)); + graphics.DrawString(" " + title, new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular), brush, rec); + graphics.DrawString(nprice, new Font("微软雅黑", 25, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(178, 34, 34)), 45, 895); + graphics.DrawString(price, new Font("微软雅黑", 25, System.Drawing.FontStyle.Strikeout), new SolidBrush(Color.FromArgb(148, 148, 148)), 335, 895); + graphics.DrawString(cprice, new Font("微软雅黑", 28, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(70, 130, 180)), 595, 892); + RectangleF rec2 = new RectangleF(10, 1298, width - 40, 42); + Brush brush2 = new SolidBrush(Color.FromArgb(250, 250, 210)); + graphics.DrawString(content, new Font("微软雅黑", 16, System.Drawing.FontStyle.Bold), brush2, rec2); + } + } + break; + case QrImageType.模板C: + { + var foot = Properties.Resources.模板C; + var width = foot.Width; + var height = foot.Height; + img = new Bitmap(width, height); + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.High; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.DrawImage(foot, 0, 0, width, height);//填充背景图片 + + //添加标题 + RectangleF rec = new RectangleF(40, 17, 728, 110); + Brush brush = new SolidBrush(Color.FromArgb(53, 53, 53)); + graphics.DrawString(title, new Font("微软雅黑", 30, System.Drawing.FontStyle.Regular), brush, rec); + + graphics.DrawImage(mainpic, 45, 131, 413, 388);//填充商品图片 + graphics.DrawImage(Generate3(link), 557, 277, 152, 152); + //graphics.DrawImage(Image.FromFile(@"D:\A.png"), 557, 277, 152, 152); + + graphics.DrawString($"券后【{nprice}元】包邮秒杀", new Font("微软雅黑", 40, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(178, 34, 34)), 44, 565); + //graphics.DrawString(price, new Font("微软雅黑", 25, FontStyle.Strikeout), new SolidBrush(Color.FromArgb(148, 148, 148)), 335, 895); + graphics.DrawString($"减{cprice}元", new Font("微软雅黑", 28, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(70, 130, 180)), 600, 182); + RectangleF rec2 = new RectangleF(40, 667, 745, 122); + graphics.DrawString(content, new Font("微软雅黑", 18, System.Drawing.FontStyle.Bold), brush, rec2); + } + } + break; + } + + string path = string.Empty; + if (img != null) + { + if (!string.IsNullOrEmpty(basePath)) + path = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", basePath); + else path = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + img.Save(path, ImageFormat.Jpeg); + } + return path; + } + catch (Exception ex) + { + number++; + if (number <= 3) + { + Thread.Sleep(300); + goto Next; + } + EventClient.OnEvent(null, $"合成二维码图片:{ex.Message} - {ex.StackTrace}"); + return string.Empty; + } + finally + { + if (img != null) img.Dispose(); + if (mainpic != null) mainpic.Dispose(); + } + } + + /// <summary> + /// 将方形图片变成雏形 + /// </summary> + /// <param name="img">要转变的图片</param> + /// <param name="rec">大小和位置</param> + /// <param name="size"></param> + /// <returns></returns> + private static Image CutEllipse(Image img, Rectangle rec, Size size) + { + Bitmap bitmap = new Bitmap(size.Width, size.Height); + using (Graphics g = Graphics.FromImage(bitmap)) + { + using (TextureBrush br = new TextureBrush(img, System.Drawing.Drawing2D.WrapMode.Clamp, rec)) + { + br.ScaleTransform(bitmap.Width / (float)rec.Width, bitmap.Height / (float)rec.Height); + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + g.FillEllipse(br, new Rectangle(Point.Empty, size)); + } + } + return bitmap; + } + + /// <summary> + /// 合成优惠券图(新版) + /// </summary> + /// <param name="image">优惠券底图</param> + /// <param name="shopname">店铺名称</param> + /// <param name="shopimage">店铺头像</param> + /// <param name="title">宝贝标题</param> + /// <param name="price">宝贝原价</param> + /// <param name="couponprice">优惠券金额</param> + /// <param name="itemimage">宝贝图片</param> + /// <param name="indate">优惠券有效期区间(2018.02.12 - 2018.03.12)</param> + /// <param name="sellcount">月销量</param> + /// <param name="basePath">图片保存路径</param> + /// <returns></returns> + public static string GetCouponImage2(string image, string shopname, Image shopimage, string title, string price, string couponprice, Image itemimage, string indate, string sellcount, string basePath = "") + { + int number = 0; + Image mainpic = null; + Image shoppic = null; + Next: + try + { + HttpHelper http = new HttpHelper(); + if (image.StartsWith("http")) + mainpic = http.GetImage(http.GetItem(image)); + else + mainpic = ReadImageFile(image); + //店铺头像 + shoppic = CutEllipse(shopimage, new Rectangle(0, 0, 150, 150), new Size(150, 150)); + + var width = (int)mainpic.Width; + var height = (int)mainpic.Height; + string path = string.Empty; + using (Bitmap img = new Bitmap(width, height)) + { + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + + graphics.DrawImage(mainpic, 0, 0, width, height);//将优惠券底图放置画板中 + graphics.DrawImage(shoppic, (width - 135) / 2, 154, 135, 135);//画板中绘画店铺头像 + + #region 店铺名 + var couponTitleFont = new Font("微软雅黑", 26, System.Drawing.FontStyle.Regular); + var wid = graphics.MeasureString(shopname, couponTitleFont); + RectangleF rec = new RectangleF((width - wid.Width) / 2, 294, wid.Width, wid.Height);//优惠券标题 + graphics.DrawString(shopname, couponTitleFont, new SolidBrush(Color.White), rec); + #endregion + + #region 绘画优惠券金额 + var couponFont = new Font("微软雅黑", 70, System.Drawing.FontStyle.Regular);//优惠券金额字体 + var couponpriceWid = graphics.MeasureString(couponprice, couponFont);//优惠券金额字体大小 + graphics.DrawString(couponprice, couponFont, new SolidBrush(Color.FromArgb(0xCD, 0x00, 0x00)), 210, 346);//画板中绘画优惠券金额 + #endregion + + #region 绘画优惠券有效期 + var couponIndateFont = new Font("微软雅黑", 19, System.Drawing.FontStyle.Regular);//优惠券有效期字体 + graphics.DrawString(indate, couponIndateFont, new SolidBrush(Color.FromArgb(0xc0, 0xc0, 0xc0)), 108, 511);//画板中绘画优惠券有效期 + #endregion + + #region 绘画宝贝图 + //店铺头像 + graphics.DrawImage(itemimage, 23, 607, 250, 268);//画板中绘画店铺头像 + + #endregion + + #region 绘画商品原价 + var priceFont = new Font("微软雅黑", 27, System.Drawing.FontStyle.Strikeout); + graphics.DrawString(price, priceFont, new SolidBrush(Color.Black), 385, 740); + #endregion + + #region 绘画商品最终价 + var finalPriceFont = new Font("微软雅黑", 45, System.Drawing.FontStyle.Regular); + wid = graphics.MeasureString(price, finalPriceFont); + graphics.DrawString((decimal.Parse(price) - decimal.Parse(couponprice)).ToString(), finalPriceFont, new SolidBrush(Color.Red), 438, 774); + #endregion + + #region 绘画商品标题 + var titleFont = new Font("微软雅黑", 18, System.Drawing.FontStyle.Regular); + int num = 18; + int rows = (int)Math.Floor(((decimal)title.Length / (decimal)num)); + for (int i = 1; i <= rows; i++) + { + var index = (num * i) + ((i - 1) * 2); + title = title.Insert(index, @" +"); + } + graphics.DrawString(title, titleFont, new SolidBrush(Color.Black), 298, 595); + #endregion + + #region 绘画月销量 + var sellcountFont = new Font("微软雅黑", 22, System.Drawing.FontStyle.Regular);//优惠券有效期字体 + graphics.DrawString(sellcount + "笔成交", sellcountFont, new SolidBrush(Color.FromArgb(0xc0, 0xc0, 0xc0)), 563, 692);//画板中绘画优惠券有效期 + #endregion + + } + path = !string.IsNullOrEmpty(basePath) ? Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", basePath) : Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + + img.Save(path, ImageFormat.Jpeg); + } + return path; + } + catch (Exception ex) + { + number++; + if (number <= 3) goto Next; + throw ex; + } + } + + + /// <summary> + /// 合成优惠券图 + /// </summary> + /// <param name="image">优惠券底图</param> + /// <param name="shopname">店铺名称</param> + /// <param name="shoppic">店铺头像</param> + /// <param name="couponprice">优惠券金额</param> + /// <param name="indate">优惠券有效期区间(2018.02.12 - 2018.03.12)</param> + /// <param name="basePath">图片保存路径</param> + /// <returns></returns> + public static string GetCouponImage(string image, string shopname, string shopimage, string couponprice, string indate, string basePath = "") + { + int number = 0; + Image mainpic = null; + Image shoppic = null; + Next: + try + { + HttpHelper http = new HttpHelper(); + if (image.StartsWith("http")) + mainpic = http.GetImage(http.GetItem(image)); + else + mainpic = ReadImageFile(image); + + shoppic = http.GetImage(http.GetItem(shopimage)); + var width = (int)mainpic.Width; + var height = (int)mainpic.Height; + string path = string.Empty; + using (Bitmap img = new Bitmap(width, height)) + { + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.High; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.DrawImage(mainpic, 0, 0, width, height);//将优惠券底图放置画板中 + //graphics.DrawImage(Properties.Resources.foot, 0, int.Parse((height).ToString("0")), 800, 424); + //graphics.DrawImage(Generate3(link), 510, int.Parse((height + 50).ToString("0")), 225, 220); + + graphics.DrawImage(shoppic, 38, 417, 60, 60);//画板中绘画店铺头像 + + #region 绘画优惠券标题 + var _shopname = shopname + "优惠券"; + var couponTitleFont = new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular); + var wid = graphics.MeasureString(_shopname, couponTitleFont); + RectangleF rec = new RectangleF((width - wid.Width) / 2, (91 - wid.Height) / 2, wid.Width, wid.Height);//优惠券标题 + Brush brush = new SolidBrush(Color.FromArgb(53, 53, 53)); + graphics.DrawString(_shopname, couponTitleFont, brush, rec); + #endregion + + #region 绘画优惠券金额 + var couponFont = new Font("微软雅黑", 28, System.Drawing.FontStyle.Bold);//优惠券金额字体 + var couponpriceWid = graphics.MeasureString(couponprice, couponFont);//优惠券金额字体大小 + graphics.DrawString(couponprice, couponFont, new SolidBrush(Color.FromArgb(255, 99, 71)), (width - couponpriceWid.Width) / 2, 197);//画板中绘画优惠券金额 + #endregion + + #region 绘画优惠券有效期 + indate = "使用期限 " + indate; + var couponIndateFont = new Font("微软雅黑", 15, System.Drawing.FontStyle.Regular);//优惠券有效期字体 + var couponindateWid = graphics.MeasureString(indate, couponIndateFont);//优惠券有效期字体大小 + graphics.DrawString(indate, couponIndateFont, new SolidBrush(Color.FromArgb(169, 169, 169)), (width - couponindateWid.Width) / 2, 115);//画板中绘画优惠券有效期 + #endregion + + #region 绘画店铺名称 + var shopNameFont = new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular); + wid = graphics.MeasureString(shopname, shopNameFont); + //RectangleF rec = new RectangleF((width - wid.Width) / 2, 50, 50, wid.Height);//优惠券标题 + graphics.DrawString(shopname, shopNameFont, new SolidBrush(Color.Black), 103, 402 + (90 - wid.Height) / 2); + #endregion + } + + if (!string.IsNullOrEmpty(basePath)) + path = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", basePath); + else path = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + img.Save(path, ImageFormat.Jpeg); + } + return path; + } + catch (Exception ex) + { + number++; + if (number <= 3) goto Next; + throw ex; + } + } + + /// <summary> + /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// </summary> + /// <param name="path"></param> + /// <returns></returns> + private static Bitmap ReadImageFile(string path) + { + FileStream fs = File.OpenRead(path); //OpenRead + int filelength = 0; + filelength = (int)fs.Length; //获得文件长度 + Byte[] image = new Byte[filelength]; //建立一个字节数组 + fs.Read(image, 0, filelength); //按字节流读取 + Image result = Image.FromStream(fs); + fs.Close(); + Bitmap bit = new Bitmap(result); + return bit; + } + + } +} diff --git a/类库/Api.Framework/ApiClient.cs b/类库/Api.Framework/ApiClient.cs new file mode 100644 index 0000000..d31cec2 --- /dev/null +++ b/类库/Api.Framework/ApiClient.cs @@ -0,0 +1,4131 @@ +using Api.Framework.Config; +using Api.Framework.Config; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Timers; +using Api.Framework.Tools; +using Api.Framework.UIForm; +using Chat.Framework; +using CsharpHttpHelper; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; +using ZXing; +using ZXing.Common; +using System.Reflection; +using Chat.Framework.WXSdk; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using SuperSocket.SocketBase; +using System.Text.RegularExpressions; +using System.Security.Cryptography; +using Chat.Framework.PCRobotSDK.WechatEvents; +using PCRobot.Pack; +using SuperSocket.SocketEngine; +using Chat.Framework.PCRobotSDK; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.Implement; +using Chat.Framework.PCRobotSDK.WorkWechatEvents; +using Grant.Framework; +using Newtonsoft.Json.Linq; +using System.Web.Configuration; +using System.Web.Security; +using static Api.Framework.Cps.AlimamaApi; +using Robot.Framework.Entities; +using Chat.Framework.QQSdk.QPlus; +using SuperSocket.SocketBase.Protocol; +using AppServer = SuperSocket.SocketBase.AppServer; +using Api.Framework.Properties; +using Api.Framework.Utils; +using Newtonsoft.Json; + +namespace Api.Framework +{ + /// <summary> + /// Api端功能集合 + /// </summary> + public class ApiClient + { + /// <summary> + /// 插件列表显示的插件 + /// </summary> + public static List<string> ShowPluginList { get; set; } + + private static PointManageConfig pointManageConfig = null; + /// <summary> + /// 获取积分管理插件配置 + /// </summary> + /// <param name="flush">是否刷新</param> + /// <returns></returns> + public static PointManageConfig GetPointManageConfig(bool flush = false) + { + if (pointManageConfig == null || flush) + pointManageConfig = PluginExtend.ReadConfig<PointManageConfig>(null); + return pointManageConfig; + } + + + private static Version _version; + /// <summary> + /// 当前版本 + /// </summary> + public static Version CurVersion + { + get + { + if (_version == null) + { + try + { + _version = new Version(UpdateClient.GetVersionName()); + } + catch (Exception ex) + { + _version = new Version("0.0.0.0"); + } + } + return _version; + } + } + + #region superSocket 2.0 + /// <summary> + /// Socket服务 + /// </summary> + public static AppServer Server { get; private set; } + /// <summary> + /// 关闭Socket服务 + /// </summary> + public static void StopSocketServer() + { + try + { + if (Server != null) + { + Server.Stop(); + Server.NewSessionConnected -= appServer_NewSessionConnected; + Server.SessionClosed -= appServer_NewSessionClosed; + } + } + catch (Exception) + { } + } + + /// <summary> + /// 有新的Socket连接 + /// </summary> + /// <param name="session">连接端的信息</param> + private static void appServer_NewSessionConnected(AppSession session) + { + var ip = session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port; + if (!ChatClient.PCRobotPool.ClientSessions.ContainsKey(ip)) + ChatClient.PCRobotPool.ClientSessions.Add(ip, new PCRobotPool.AppSessionInfo() { appSession = session, device = string.Empty }); + + EventClient.OnEvent(session, $"{session.RemoteEndPoint.Address}-{session.RemoteEndPoint.Port} --> 连接成功!"); + } + + /// <summary> + /// 有连接的Socket关闭 + /// </summary> + /// <param name="session">断开端的信息</param> + /// <param name="value">关闭的原因</param> + private static void appServer_NewSessionClosed(AppSession session, SuperSocket.SocketBase.CloseReason value) + { + try + { + var ip = session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port; + if (ChatClient.PCRobotPool.ClientSessions.ContainsKey(ip)) + ChatClient.PCRobotPool.ClientSessions.Remove(ip); + else + { } + + EventClient.OnEvent(session, $"{session.RemoteEndPoint.Address}-{session.RemoteEndPoint.Port}--> 已关闭!"); + var con = ApiClient.GetSession(); + var name = Chat.Framework.ChatClient.PCRobotPool.Remove(session); + var r = con.FindRobots().FirstOrDefault(f => f.name == name); + if (r != null) + { + r.is_login = false; + con.Updateable<fl_robot_info>(r).ExecuteCommand(); + } + } + catch (Exception ex) + { + EventClient.OnEvent(session, $"{session.RemoteEndPoint.Address}-{session.RemoteEndPoint.Port},{value},{ex.Message}-{ex.StackTrace}--> 已关闭!"); + } + } + + /// <summary> + /// 启动Socket服务 + /// </summary> + /// <param name="port">端口</param> + /// <param name="password">通讯秘钥</param> + /// <returns></returns> + public static bool StartSocketServer(int port, string password) + { + try + { + StopSocketServer(); + Server = new AppServer(); + var bufSize = 1024 * 256; + var serconfig = new SuperSocket.SocketBase.Config.ServerConfig + { + Ip = "Any", + Mode = SuperSocket.SocketBase.SocketMode.Tcp, + TextEncoding = "UTF-8", + Port = port, + MaxConnectionNumber = 100 * 5, + ReceiveBufferSize = bufSize, + MaxRequestLength = Int32.MaxValue, + SendingQueueSize = 300, + }; + + + //var serconfig = new SuperSocket.SocketBase.Config.ServerConfig + //{ + // Ip = "Any", + // Mode = SuperSocket.SocketBase.SocketMode.Tcp, + // TextEncoding = "UTF-8", + // Port = port, + // //MaxConnectionNumber = 350, + // ReceiveBufferSize = 1024 * 1024 * 3, + // MaxRequestLength = 1024 * 1024, + // SendingQueueSize = 300 + //}; + + //----------- + + //var size = 1024 * 1024 * 8; + //var serconfig = new SuperSocket.SocketBase.Config.ServerConfig(); + //serconfig.TextEncoding = "UTF-8"; + //serconfig.Ip = "Any"; + //serconfig.Port = port; + //serconfig.SendBufferSize = size; + //serconfig.ReceiveBufferSize = size; + //serconfig.MaxRequestLength = size; + //serconfig.SendingQueueSize = 50; + //serconfig.MaxConnectionNumber = 500; + //serconfig.LogAllSocketException = true; + //serconfig.LogFactory = "SuperSocket.SocketBase.Logging.ConsoleLogFactory, SuperSocket.SocketBase"; + //Console.WriteLine(serconfig.MaxConnectionNumber); + + if (!Server.Setup(serconfig)) throw new Exception("监听端口失败,请检查是否关闭防火墙或端口被占用!"); + + ////Try to start the appServer + if (!Server.Start()) throw new Exception("初始化端口失败,请检查是否关闭防火墙或端口被占用!"); + + ApiClient.Setting.ServerConfig.SocketPassword = password; + ApiClient.Setting.ServerConfig.SocketPort = port; + ApiClient.Setting.ServerConfig.SocketIsOpen = true; + + Util.Save(Setting.ServerConfig); + + ChatClient.SocketPassword = password; + + Server.NewSessionConnected += appServer_NewSessionConnected; + Server.SessionClosed += appServer_NewSessionClosed; + + ////SocketCMD 是KEY + Server.NewRequestReceived += Server_NewRequestReceived; + + return true; + } + catch (Exception ex) + { + EventClient.OnEvent("Socket服务端口", $"开启失败,原因:{ex.Message}"); + ApiClient.Setting.ServerConfig.SocketIsOpen = false; + Util.Save(Setting.ServerConfig); + throw ex; + } + + return false; + } + private static void Server_NewRequestReceived2(AppSession _session, StringRequestInfo _requestInfo) + { + new Thread(delegate () + { + + }).Start(); + Task.Factory.StartNew(delegate () + { + Thread.Sleep(10000); + //记录 msg 日志,并做逻辑处理 + }); + + + } + + /// <summary> + /// 收到Socket消息 + /// </summary> + /// <param name="_session">发送端的信息</param> + /// <param name="_requestInfo">收到的信息</param> + private static void Server_NewRequestReceived(AppSession _session, StringRequestInfo _requestInfo) + { + var session = _session; + var requestInfo = _requestInfo; + + //var action = new Action(delegate () + Task.Factory.StartNew(delegate () + { + var data = string.Empty; + try + { + if (string.IsNullOrWhiteSpace(requestInfo.Key) || string.IsNullOrWhiteSpace(requestInfo.Body)) + { + LogHelper.GetSingleObj().Debug("", $"收到客户端消息__:{requestInfo.Key} - {requestInfo.Body}"); + return; + } + //EventClient.OnEvent(null,$"收到数据包:{requestInfo.Key} - {requestInfo.Body.Length}"); + int key; + //var cmd = (PCRobot.Pack.PCRobotCMD)Enum.Parse(typeof(PCRobot.Pack.PCRobotCMD), requestInfo.Key); + try + { + data = PackTool.DecompressString(requestInfo.Body); + } + catch (Exception) + { + LogHelper.GetSingleObj().Debug("", $"收到客户端消息转换Body异常:{requestInfo.Key} - {requestInfo.Body}"); + return; + } + PCRobot.Pack.PCRobotCMD cmd; + if (!Enum.TryParse<PCRobot.Pack.PCRobotCMD>(requestInfo.Key, out cmd)) + { + LogHelper.GetSingleObj().Debug("", $"收到客户端消息CMD转换异常:{requestInfo.Key} - {data} - {data.Length}"); + return; + } + + #region 客户端软件之间,获取连接端设备信息 + var ip = session.RemoteEndPoint.Address + ":" + session.RemoteEndPoint.Port; + LogHelper.GetSingleObj().Debug("", $"心跳?:{ip}"); + if (cmd == PCRobotCMD.heartBreak) + { + if (Chat.Framework.ChatClient.PCRobotPool.ClientSessions.ContainsKey(ip)) + { + var json = JsonConvert.DeserializeObject<CommonResult>(data); + if (json == null) return; + if (json.Cmd == PCRobotCMD.heartBreak) + { + var appSession = Chat.Framework.ChatClient.PCRobotPool.ClientSessions[ip]; + appSession.device = json.Data; + return; + } + } + else + { + } + } + #endregion + + + //EventClient.OnEvent(null, $"收到客户端消息:{requestInfo.Key} - {data}"); + LogHelper.GetSingleObj().Debug("", $"收到客户端消息:{requestInfo.Key} - {data} - {data.Length}"); + + var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(data); + if (dic.ContainsKey("Key") && dic["Key"].ToString() != Setting.ServerConfig.SocketPassword) + { + var RobotUsernick = string.Empty; + if (dic.ContainsKey("RobotUsernick")) + RobotUsernick = dic["RobotUsernick"].ToString(); + var RobotUsername = string.Empty; + if (dic.ContainsKey("RobotUsername")) + RobotUsername = dic["RobotUsername"].ToString(); + + RobotType robotType; + if (dic.ContainsKey("RobotType")) + { + var type = dic["RobotType"].ToString(); + if (Enum.TryParse<RobotType>(type, out robotType)) + throw new Exception($"{(robotType == RobotType.客户端微信 ? ChatType.微信 : robotType == RobotType.客户端企业微信 ? ChatType.企业微信 : robotType == RobotType.客户端扣扣 ? ChatType.QQ : ChatType.微信公众号)}:{RobotUsernick}({RobotUsername}) 易转发与软件秘钥不匹配,无法通讯!"); + } + } + var cmd_int = (int)cmd; + var events = ChatClient.Events; + + if (cmd.ToString().ToLower().StartsWith("offline".ToLower())) + { + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd = {data})"); + var json = JsonConvert.DeserializeObject<WechatStatus>(data); + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd A = {data} # json = {(json == null ? string.Empty : JsonConvert.SerializeObject(json))}"); + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatStatusEvents(json); + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd B = {data} # evt = {(evt == null ? string.Empty : JsonConvert.SerializeObject(evt))}"); + if (evt == null) + { + EventClient.OnEvent(null, $"{json.RobotUsername}({json.Uin})心跳发送失败"); + return; + } + if (evt.Key != Setting.ServerConfig.SocketPassword) + { + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd RRR = {data}"); + EventClient.OnEvent(null, $"{json.RobotUsername}({json.Uin})心跳发送失败,秘钥不一致"); + } + + try + { + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd CCCC = {data}"); + var robot = GetRobotInfo(evt.RobotUsername, evt.RobotUsernick, evt.RobotType == RobotType.客户端微信 ? ChatType.微信 : ChatType.企业微信, json.Uin, json.Device); + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd C = {data} # robot = {(robot == null ? string.Empty : JsonConvert.SerializeObject(robot))}"); + + robot.is_login = evt.Status == Status.在线; + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.RobotUsername, session); + + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd D = {data}"); + + var hook = FindHookRobot(robot, evt.RobotType); + + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd E = {data} # hook = {(hook == null ? string.Empty : hook.GetType().Name)}"); + if (hook != null) + { + hook.Receive(evt); + //LogHelper.GetSingleObj().Debug("", $"收到的消息cmd F = {data}"); + if (string.IsNullOrWhiteSpace(robot.end_time)) + { + var softId = (robot.type == Api.Framework.SDK.ChatType.QQ) ? 1002 : 1001; + var custm = GrantClient.Get().Refresh(robot.uin.ToString(), softId); + if (custm != null) + { + robot.end_time = custm.endTime; + ApiClient.GetSession().SaveOrUpdate(robot); + ApiClient.GetSession().FindRobots(true); + } + } + } + else + { + LogHelper.GetSingleObj().Debug("", $"客户端消息1:{requestInfo.Key} - Uin:{evt.Uin},{evt.RobotUsernick}({evt.RobotUsername}) - hook为空"); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Debug("", $"客户端消息2:{requestInfo.Key} - Uin:{evt.Uin},{evt.RobotUsernick}({evt.RobotUsername}) - 异常:{ex.Message} - {ex.StackTrace}"); + } + finally + { + var isSend = session.TrySend($"{cmd} {(HttpHelper.ObjectToJson(new { RobotUsername = json.RobotUsername }))}\r\n"); + + + //LogHelper.GetSingleObj().Debug("", $"客户端消息3:{requestInfo.Key} - {data} - 响应心跳:{isSend}"); + } + } + else + { + //LogHelper.GetSingleObj().Debug("", $"收到的消息___cmd = {cmd} {data})"); + } + + //个人微信消息 + if (cmd_int >= 2000 && cmd_int <= 2999) + { + switch (cmd) + { + case PCRobot.Pack.PCRobotCMD.rcvTxt: + case PCRobot.Pack.PCRobotCMD.rcvFile: + case PCRobot.Pack.PCRobotCMD.rcvImg: + { + var json = JsonConvert.DeserializeObject<WechatReceiveMsg>(data); + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatReceiveMsgEvents(json); + if (evt == null) return; + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + //EventClient.OnEvent(evt, evt); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + { + hook.Receive(evt); + } + } + break; + case PCRobotCMD.applyFriend: + { + var json = JsonConvert.DeserializeObject<WechatApplyFriend>(data); + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatApplyFriendEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobot.Pack.PCRobotCMD.receivePay: + { + var json = JsonConvert.DeserializeObject<WechatReicevePay>(data); + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatReicevePayEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobotCMD.applyGroup: + { } + break; + case PCRobotCMD.newfriend: + { + var json = JsonConvert.DeserializeObject<WechatNewFriend>(data); + var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatNewFriendEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobotCMD.offline: + { + //var json = JsonConvert.DeserializeObject<WechatStatus>(data); + //var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatStatusEvents(json); + //if (evt == null) + //{ + // EventClient.OnEvent(null, $"{json.RobotUsername}({json.Uin})心跳发送失败,秘钥不一致"); + // return; + //} + + //var robot = GetRobotInfo(evt.RobotUsername, evt.RobotUsernick, ChatType.微信, json.Uin); + + //robot.is_login = evt.Status == Status.在线; + + //Chat.Framework.ChatClient.PCRobotPool.Update(evt.RobotUsername, session); + + //var hook = FindHookRobot(robot, evt.RobotType); + //if (hook != null) + //{ + // hook.Receive(evt); + + // if (string.IsNullOrWhiteSpace(robot.end_time)) + // { + // var softId = (robot.type == Api.Framework.SDK.ChatType.QQ) ? 1002 : 1001; + // var custm = GrantClient.Get().Refresh(robot.uin.ToString(), softId); + // if (custm != null) + // { + // robot.end_time = custm.endTime; + // ApiClient.GetSession().SaveOrUpdate(robot); + // ApiClient.GetSession().FindRobots(true); + // } + // } + //} + } + break; + case PCRobotCMD.newMember: + { + var json = JsonConvert.DeserializeObject<WechatNewMemer>(data); + var evt = new WechatNewMemerEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobotCMD.rcvContactList: + { + var json = JsonConvert.DeserializeObject<WechatContact>(data); + var evt = new WechatContactListEvents(json); + //if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + case PCRobotCMD.rcvCircleData://朋友圈json数据 + case PCRobotCMD.rcvMiniAppCode://朋友圈json数据 + case PCRobotCMD.rcvCircleReturnId://成功发送朋友圈返回id + case PCRobotCMD.rcvCircleUploadImageUrl://朋友圈上传图片返回网络地址 + case PCRobotCMD.rcvLoginCode://登录二维码 + case PCRobotCMD.rcvFriendList://好友列表 + { + var json = JsonConvert.DeserializeObject<CommonResult>(data); + //var evt = new WechatContactListEvents(json); + if (json == null) return; + if (!string.IsNullOrWhiteSpace(json.RobotUsername)) + { + var robot = GetRobotInfo(json.RobotUsername, json.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(json.RobotUsername, session); + } + else + { } + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + + //var hook = FindHookRobot(robot, json.RobotType); + //if (hook != null) + // hook.Receive(json); + } + break; + case PCRobotCMD.rcvContact: + { + var json = JsonConvert.DeserializeObject<WechatContact>(data); + var evt = new WechatContactListEvents(json); + if (evt == null) return; + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + } + break; + case PCRobotCMD.rcvCheckUrl: + { + var json = JsonConvert.DeserializeObject<CheckUrl>(data); + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + } + break; + case PCRobotCMD.rcvCreateRoom: + { + var json = JsonConvert.DeserializeObject<CreateRoom>(data); + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + } + break; + case PCRobotCMD.rcvGroupMember: + { + var json = JsonConvert.DeserializeObject<WechatGroupMember>(data); + var evt = new WechatGroupMemberEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + } + break; + } + } + + //企业微信消息处理 + else if (cmd_int >= 3000 && cmd_int <= 3999) + { + switch (cmd) + { + case PCRobotCMD.rcvLoginCode_workWeChat://登录二维码 + case PCRobotCMD.rcvFriendList_workWeChat://获取好友列表 + { + var json = JsonConvert.DeserializeObject<CommonResult>(data); + if (json == null) return; + + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + + //var hook = FindHookRobot(robot, json.RobotType); + //if (hook != null) + // hook.Receive(json); + } + break; + case PCRobotCMD.rcvTxt_workWeChat: + case PCRobotCMD.rcvFile_workWeChat: + case PCRobotCMD.rcvImg_workWeChat: + { + var json = JsonConvert.DeserializeObject<WorkWechatReceiveMsg>(data); + var evt = new Chat.Framework.PCRobotSDK.WorkWechatEvents.WorkWechatReceiveMsgEvents(json); + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + //EventClient.OnEvent(evt, evt); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.applyFriend_workWeChat: + { + var json = JsonConvert.DeserializeObject<WorkWechatApplyFriend>(data); + var evt = new Chat.Framework.PCRobotSDK.WorkWechatEvents.WorkWechatApplyFriendEvents(json); + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.receivePay_workWeChat: + { + var json = JsonConvert.DeserializeObject<WorkWechatReicevePay>(data); + var evt = new Chat.Framework.PCRobotSDK.WorkWechatEvents.WorkWechatReicevePayEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.applyGroup_workWeChat: + { } + break; + case PCRobotCMD.newfriend_workWeChat: + { + var json = JsonConvert.DeserializeObject<WorkWechatNewFriend>(data); + var evt = new Chat.Framework.PCRobotSDK.WorkWechatEvents.WorkWechatNewFriendEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.offline_workWeChat: + { + //var json = JsonConvert.DeserializeObject<WechatStatus>(data); + //var evt = new Chat.Framework.PCRobotSDK.WechatEvents.WechatStatusEvents(json); + //if (evt == null) + //{ + // EventClient.OnEvent(null, $"{json.RobotUsername}({json.Uin})心跳发送失败,秘钥不一致"); + // return; + //} + + //var robot = GetRobotInfo(evt.RobotUsername, evt.RobotUsernick, ChatType.企业微信, json.Uin); + + //robot.is_login = evt.Status == Status.在线; + + //Chat.Framework.ChatClient.PCRobotPool.Update(evt.RobotUsername, session); + + //var hook = FindHookRobot(robot, evt.RobotType); + //if (hook != null) + //{ + // hook.Receive(evt); + + // if (string.IsNullOrWhiteSpace(robot.end_time)) + // { + // var softId = (robot.type == Api.Framework.SDK.ChatType.QQ) ? 1002 : 1001; + // var custm = GrantClient.Get().Refresh(robot.uin.ToString(), softId); + // if (custm != null) + // { + // robot.end_time = custm.endTime; + // ApiClient.GetSession().SaveOrUpdate(robot); + // ApiClient.GetSession().FindRobots(true); + // } + // } + //} + } + break; + case PCRobotCMD.newMember_workWeChat: + { + var json = JsonConvert.DeserializeObject<WorkWechatNewMemer>(data); + var evt = new WorkWechatNewMemerEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.rcvContact_workWeChat: + { + var json = JsonConvert.DeserializeObject<WorkWechatContact>(data); + var evt = new WorkWechatContactListEvents(json); + if (evt == null) return; + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + Chat.Framework.ChatClient.PCRobotPool.PackHist.SetResult(json); + } + break; + case PCRobotCMD.rcvContactList_workWeChat: + { + var json = JsonConvert.DeserializeObject<WorkWechatContact>(data); + var evt = new WorkWechatContactListEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + case PCRobotCMD.rcvGroupMember_workWeChat: + { + var json = JsonConvert.DeserializeObject<WorkWechatGroupMember>(data); + var evt = new WorkWechatGroupMemberEvents(json); + if (evt == null) return; + + var robot = GetRobotInfo(evt.Data.RobotUsername, evt.Data.RobotUsernick, ChatType.企业微信); + + Chat.Framework.ChatClient.PCRobotPool.Update(evt.Data.RobotUsername, session); + + var hook = FindHookRobot(robot, evt.Data.RobotType); + if (hook != null) + hook.Receive(evt); + else + { } + } + break; + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Debug("", $"收到的消息cmd ERROR = {data}"); + EventClient.OnEvent(null, $"{ex.Message}."); + } + }); + //action.BeginInvoke(null, null); + } + + #endregion + + /// <summary> + /// 锁获取机器人对象,确保唯一 + /// </summary> + private static readonly object GetRobotLock = new object(); + /// <summary> + /// 获取机器人对象 + /// </summary> + /// <param name="weixinhao"></param> + /// <returns></returns> + private static WeixinBase FindHookRobot(fl_robot_info robot, RobotType robotType) + { + lock (GetRobotLock) + { + try + { + var strb = new StringBuilder(); + var clients = ChatClient.WXClient; + foreach (KeyValuePair<string, WeixinBase> item in clients) + { + strb.AppendLine($"key:{item.Key},Uin:{item.Value.User.Uin},{item.Value.User.Nick}({item.Value.User.Username})"); + } + strb.AppendLine(); + strb.AppendLine($"状态:{robot.is_login},微信-{robotType}:{robot.nick}({robot.name})"); + //LogHelper.GetSingleObj().Info("", $"客户端微信集合 = {strb.ToString()}"); + } + catch (Exception) + { } + + var v = ChatClient.WXClient.FirstOrDefault(f => f.Key == robot.name).Value; + if (!robot.is_login && v == null) + return null; + switch (robotType) + { + case RobotType.客户端系统: + break; + case RobotType.客户端微信: + if (v == null) + { + v = new WXClientImpl_HOOK(robot.name, robot.nick, long.Parse(robot.uin)); + //LogHelper.GetSingleObj().Info("", $"初始化客户端微信 = {robot.uin},{robot.nick}({robot.name})"); + } + break; + case RobotType.客户端企业微信: + if (v == null) + { + v = new WXClientImpl_QYHOOK(robot.name, robot.nick, long.Parse(robot.uin)); + //LogHelper.GetSingleObj().Info("", $"初始化客户端企业微信 = {robot.uin},{robot.nick}({robot.name})"); + } + break; + case RobotType.客户端扣扣: + break; + } + return v; + } + } + + /// <summary> + /// 获取机器人对象 + /// </summary> + /// <param name="username">机器人账号</param> + /// <param name="usernick">机器人昵称</param> + /// <param name="robotType">机器人所属hook类型</param> + /// <returns></returns> + [Obsolete("这个函数已经过时了", true)] + private static WeixinBase FindHookRobot(string username, string usernick, RobotType robotType) + { + lock (GetRobotLock) + { + var v = ChatClient.WXClient.FirstOrDefault(f => f.Key == username).Value; + switch (robotType) + { + case RobotType.客户端系统: + break; + case RobotType.客户端微信: + if (v == null) + v = new WXClientImpl_HOOK(username, usernick); + break; + case RobotType.客户端企业微信: + if (v == null) + v = new WXClientImpl_QYHOOK(username, usernick); + break; + case RobotType.客户端扣扣: + break; + } + return v; + } + } + + /// <summary> + /// 锁 - 获取机器人 + /// </summary> + private readonly static object robot_lock = new object(); + + /// <summary> + /// 获取机器人数据库对象 + /// </summary> + /// <param name="robotUsername">要查询的机器人账号</param> + /// <param name="robotUsernick">机器人昵称</param> + /// <param name="chatType">平台类型</param> + /// <param name="uin">机器人的uin,企业微信/QQ的为自己的账号</param> + /// <returns></returns> + private static fl_robot_info GetRobotInfo(string robotUsername, string robotUsernick, ChatType chatType, string uin = "", string device = "") + { + var s = ApiClient.GetSession(); + fl_robot_info robot = null; + if (string.IsNullOrWhiteSpace(robotUsername)) + return null; + lock (robot_lock) + { + robot = s.FindRobotInfo(robotUsername, chatType); + if (robot == null) + { + robot = new fl_robot_info() + { + name = robotUsername, + nick = Util.RemoveEmoji(robotUsernick), + uin = uin, + type = chatType, + token = device, + remark = "PCWechat HOOK" + }; + s.Insertable<fl_robot_info>(robot).ExecuteCommandIdentityIntoEntity(); + s.FindRobots(true); + } + else + { + if (!string.IsNullOrWhiteSpace(robotUsernick) && (string.IsNullOrWhiteSpace(robot.nick) || robot.nick != robotUsernick)) + { + robot.nick = Util.RemoveEmoji(robotUsernick); + s.Saveable<fl_robot_info>(robot).ExecuteCommand(); + s.FindRobots(true); + } + + if ((!string.IsNullOrWhiteSpace(uin) && uin != robot.uin) || (!string.IsNullOrWhiteSpace(device) && device != robot.token)) + { + robot.uin = uin; + robot.token = device; + robot.remark = "PCWechat HOOK"; + s.Saveable<fl_robot_info>(robot).ExecuteCommand(); + s.FindRobots(true); + } + else + { } + } + + robot.is_login = true; + } + return robot; + } + + /// <summary> + /// 配置 + /// </summary> + public static Setting Setting { get; set; } + + /// <summary> + /// 清理垃圾 + /// </summary> + private static ClearGarbageTimer _ClearGarbage; + + /// <summary> + /// 判断是否已经配置数据库 + /// </summary> + /// <returns></returns> + public static bool SelectDbbase() + { + Setting = new Setting(); + //选择数据库 + if (string.IsNullOrEmpty(Setting.DbConfig.ConnectionString)) + { + SetConnectionConfig connection = new SetConnectionConfig(); + connection.ShowDialog(); + if (!connection.IsOk) return false; + return true; + } + return true; + } + + /// <summary> + /// 初始化 + /// </summary> + public static bool Initialization() + { + try + { + Cache = CacheTool.GetSingleObj(); + //初始化 + var session = GetSession(); + try + { + bool first = CreateTables(session); + Setting.Iniconfig(); + if (string.IsNullOrWhiteSpace(Setting.SystemConfig.cps_server_api)) + { + Setting.SystemConfig.cps_server_api = "http://cps.api.52cmg.cn/"; + } + + if (first) + { + Setting.Plugins.Add("PointManage.Class1"); + Setting.Plugins.Add("TBRebate.Class1"); + Setting.Plugins.Add("PDDRebate.Class1"); + Setting.Plugins.Add("UserFission.Class1"); + Setting.Plugins.Add("AutoAnswer.Class1"); + } + string key = "<RSAKeyValue><Modulus>2lThVzrziUuYbxfzgQ9CpivZANcSOVzUaV9Uacw8gCaudDjT6Vn6Mv+HyMKUnZB4zCwBOYkFuMjS8gfoog3Dk26TkHxAp7izE3RK8ptL7vzqozaMioqak05binUrZxLiy4X/5D9+Ny+lueuQjCIjn6eXL0D595NbAlTw/uOHodE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"; + CpsClient.SetEnckey(10003, ApiClient.Setting.SystemConfig.cps_server_api, key); + //var ip = (CpsClient.SendServer("find_config", "webtool.asmx", new { name = "Grpc微信服务器" }) as string).Split(','); + ChatClient.GetServerDataMethod = GetServerConfig; + // var ip = "193.112.217.56:81".Split(','); ; + //var ip = "193.112.217.56:81".Split(','); ; + // ip = new string[] { "118.25.53.240:9888" }; + + ChatClient.SetWeixinCore(null, new string[] { "1001", "13101A4D25A0C46B97BB58799C0D5CC7" }); + ChatClient.Events.WXGetDeviceEvent += Events_WXGetDeviceEvent; + ChatClient.GetDBWechatFriend = GetDBWechatFriend; + + PluginClient.LodingPlugin();//加载插件 + ResetTimer(); + + return true; + } + catch (Exception ex) + { + throw ex; + return false; + // session.Rollback(); + } + } + catch (Exception ex) + { + throw ex; + //MessageBox.Show(ex.Message + ex.StackTrace != null ? "\r\n" + ex.StackTrace : "", "初始化失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + } + + /// <summary> + /// 服务端Socket启动 + /// </summary> + public static void SocketInitialization() + { + if (Setting.ServerConfig.IsOpen) + { + WebClient.Start(Setting.ServerConfig.Host, ApiClient.Setting.ServerConfig.Port, false); + } + + if (Setting.ServerConfig.SocketIsOpen) + { + StartSocketServer(Setting.ServerConfig.SocketPort, Setting.ServerConfig.SocketPassword); + } + } + + /// <summary> + /// 通过用户id查库获取Friend用户对象 + /// </summary> + /// <param name="username"></param> + /// <returns></returns> + private static Chat.Framework.WXSdk.Friend GetDBWechatFriend(string username) + { + try + { + var session = GetSession(); + var member = session.FindSingle<fl_member_info>("select * from fl_member_info where (robot_type = @robot_type1 or robot_type = @robot_type2) and username = @username", new { username = username, robot_type1 = ChatType.微信, robot_type2 = ChatType.企业微信 }); + if (member != null) + return new Chat.Framework.WXSdk.Friend() { UserName = member.username, NickName = member.usernick, Alias = member.wechatid }; + } + catch (Exception) + { } + return new Chat.Framework.WXSdk.Friend() { UserName = username }; + } + + /// <summary> + /// 协议微信设备信息更新 + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private static void Events_WXGetDeviceEvent(object sender, Chat.Framework.WXSdk.Events.WXGetDevice e) + { + try + { + var session = GetSession(); + //var device = session.Queryable<fl_wechat_device>().Where(f => f.weixinhao == e.Client.WeixinHao).Single(); + var device = session.FindSingle<fl_wechat_device>("select * from fl_wechat_device where weixinhao = @weixinhao", new { weixinhao = e.Client.WeixinHao }); + if (device != null) + { + e.DeviceInfo = string.IsNullOrEmpty(device.device_info) ? string.Empty : device.device_info; + } + } + catch (Exception) + { } + } + + public static string GetServerConfig(string key) + { + return CpsClient.SendServer("find_config", "webtool.asmx", new { name = key }) as string; + } + + #region 临时用的,返回false不用管,返回true表示已经删除了(删除了,重新新建索引) + private static bool checkIndex(SqlSugarClient session, string tableName, params object[] values) + { + try + { + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + if (session.IndexExist(tableName, values[0].ToString())) + return session.DeleteIndex(tableName, values[0].ToString()); + } + else if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + if (session.IndexExist(tableName, tableName + "_" + string.Join("_", values))) + return session.DeleteIndex(tableName, tableName + "_" + string.Join("_", values)); + } + } + catch (Exception) + { } + return false; + } + #endregion + + /// <summary> + /// 创建表,没有表则创建 + /// </summary> + /// <param name="session"></param> + /// <returns></returns> + public static bool CreateTables(SqlSugarClient session) + { + var strb = new StringBuilder(); + try + { + if (!session.TableExist<fl_ratio_info_custom_group>()) + { + strb.AppendLine("fl_ratio_info_custom_group"); + session.CreateTable<fl_ratio_info_custom_group>(); + session.AddUnique<fl_ratio_info_custom_group>("cps_type", "name"); + } + + if (!session.TableExist<fl_ratio_info_custom>()) + { + strb.AppendLine("fl_ratio_info_custom"); + session.CreateTable<fl_ratio_info_custom>(); + session.AddUnique<fl_ratio_info_custom>("cps_type", "cgid", "comm"); + } + + //全额免单 + if (!session.TableExist<fl_plugin_allrebatesactivity_info>()) + { + strb.AppendLine("fl_plugin_allrebatesactivity_info"); + session.CreateTable<fl_plugin_allrebatesactivity_info>(); + session.AddIndex<fl_plugin_allrebatesactivity_info>("name");//增加索引.以后数据多了.查询速度会比较快 + session.AddUnique<fl_plugin_allrebatesactivity_info>("name");//增加唯一约束 + } + //全额免单订单 + if (!session.TableExist<fl_plugin_allrebatesactivity_orderlist>()) + { + strb.AppendLine("fl_plugin_allrebatesactivity_orderlist"); + session.CreateTable<fl_plugin_allrebatesactivity_orderlist>(); + } + + if (!session.TableExist<fl_prevent_theft_cache>()) + { + strb.AppendLine("fl_prevent_theft_cache"); + session.CreateTable<fl_prevent_theft_cache>(); + session.AddIndex<fl_prevent_theft_cache>("order_id"); + session.AddUnique<fl_prevent_theft_cache>("order_id"); + } + + //推广位组 + if (!session.TableExist<fl_adzone_group>()) + { + strb.AppendLine("fl_adzone_group"); + session.CreateTable<fl_adzone_group>(); + session.AddIndex<fl_adzone_group>("cps_type"); + session.AddUnique<fl_adzone_group>("name"); + } + else + { + strb.AppendLine("fl_adzone_group 2"); + if (!session.ColumnExist("fl_adzone_group", "remark")) + { + session.AddColumn("fl_adzone_group", "remark", "varchar(255) default ''"); + } + } + + //推广位 + if (!session.TableExist<fl_adzone_info>()) + { + strb.AppendLine("fl_adzone_info"); + session.CreateTable<fl_adzone_info>(); + } + else + { + if (!session.ColumnExist("fl_adzone_info", "is_auto_bind")) + { + strb.AppendLine("fl_adzone_info 2"); + session.AddColumn("fl_adzone_info", "is_auto_bind", "boolean default 0"); + } + + if (!session.ColumnExist("fl_adzone_info", "adzone_group")) + { + strb.AppendLine("fl_adzone_info 3"); + session.AddColumn("fl_adzone_info", "adzone_group", "integer default 0"); + } + } + + //用户自定义变量 + if (!session.TableExist<fl_uservariate_info>()) + { + strb.AppendLine("fl_uservariate_info"); + session.CreateTable<fl_uservariate_info>(); + session.AddUnique<fl_uservariate_info>("variate"); + } + + if (!session.TableExist<fl_dy_ck>()) + { + try + { + strb.AppendLine("fl_dy_ck"); + session.CreateTable<fl_dy_ck>(); + session.AddUnique<fl_dy_ck>("cpsname", "chname"); + } + catch (Exception ex) + { + } + } + + if (!session.TableExist<fl_wechat_contacts>()) + { + strb.AppendLine("fl_wechat_contacts"); + session.CreateTable<fl_wechat_contacts>(); + session.AddUnique<fl_wechat_contacts>("user_name"); + } + + if (!session.TableExist<fl_noticeapi_info>()) + { + strb.AppendLine("fl_noticeapi_info"); + session.CreateTable<fl_noticeapi_info>(); + session.AddUnique<fl_noticeapi_info>("name"); + } + + //dubug日志 + if (!session.TableExist<fl_debug_log>()) + { + strb.AppendLine("fl_debug_log"); + session.CreateTable<fl_debug_log>(); + } + + //群负责人 + if (!session.TableExist<fl_group_person>()) + { + strb.AppendLine("fl_group_person"); + session.CreateTable<fl_group_person>(); + session.AddIndex<fl_group_person>("groupid"); + } + + //私人pid + if (!session.TableExist<fl_private_pid>()) + { + strb.AppendLine("fl_private_pid"); + session.CreateTable<fl_private_pid>(); + } + + if (!session.TableExist<fl_refund_hist_point>()) + { + strb.AppendLine("fl_refund_hist_point"); + session.CreateTable<fl_refund_hist_point>(); + session.AddUnique<fl_refund_hist_point>("orderid", "orderid2"); + session.AddIndex<fl_refund_hist_point>("cpstype", "orderid", "orderid2"); + } + + //阿里妈妈维权表 + if (!session.TableExist<fl_order_refund_alimama>()) + { + strb.AppendLine("fl_order_refund_alimama"); + session.CreateTable<fl_order_refund_alimama>(); + session.AddIndex<fl_order_refund_alimama>("tbtradeparentid", "tbtradeid"); + } + else + { + #region 以后可以删除 + try + { + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + strb.AppendLine("fl_order_refund_alimama 2"); + session.ExcuteSQL("drop index fl_order_refund_alimama_tbTradeParentId_", new { }); + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + strb.AppendLine("fl_order_refund_alimama 3"); + session.ExcuteSQL("ALTER TABLE fl_order_refund_alimama DROP INDEX tbTradeParentId", new { }); + } + } + catch (Exception ex) + { + } + #endregion + } + + //微信设备信息 + if (!session.TableExist<fl_wechat_device>()) + { + strb.AppendLine("fl_wechat_device"); + session.CreateTable<fl_wechat_device>(); + session.AddUnique("fl_wechat_device", "weixinhao"); + } + else + { + #region 修改mysql中varchar类型,类中text的类型 以后可以删除 + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + try + { + PropertyInfo[] Propertys = typeof(fl_wechat_device).GetProperties(); + foreach (var item in Propertys) + { + string _name = item.Name; + + if (_name.ToLower() == "device_info".ToLower()) + { + if (item.PropertyType.FullName == typeof(string).ToString()) + session.ExcuteSQL("ALTER TABLE fl_wechat_device MODIFY COLUMN " + _name + " Text", new { }); + } + } + } + catch (Exception ex) + { } + } + #endregion + } + + //用户信息表 + if (!session.TableExist<fl_member_info>()) + { + strb.AppendLine("fl_member_info"); + session.CreateTable<fl_member_info>(); + session.AddUnique<fl_member_info>("robot_type", "username"); + //session.AddIndex<fl_member_info>("inviter_id", "robot_type", "username"); + //session.AddIndex<fl_member_info>("status", "robot_name"); + session.AddIndex<fl_member_info>("robot_type", "username"); + session.AddIndex<fl_member_info>("crt_time", "robot_name"); + session.AddIndex<fl_member_info>("status"); + session.AddIndex<fl_member_info>("inviter_id"); + session.AddIndex<fl_member_info>("usernick"); + } + else + { + //if (!session.IndexExist<fl_member_info>("inviter_id")) + //{ + // session.AddIndex<fl_member_info>("inviter_id", "status", "robot_name"); + //} + var flag1 = checkIndex(session, "fl_member_info", "inviter_id", "robot_type", "username"); + var flag2 = checkIndex(session, "fl_member_info", "status", "robot_name"); + var flag3 = checkIndex(session, "fl_member_info", "inviter_id", "status", "robot_name"); + if (flag1 || flag2 || flag3) + { + strb.AppendLine("fl_member_info 1"); + session.AddIndex<fl_member_info>("robot_type", "username"); + session.AddIndex<fl_member_info>("crt_time", "robot_name"); + session.AddIndex<fl_member_info>("status"); + session.AddIndex<fl_member_info>("inviter_id"); + session.AddIndex<fl_member_info>("usernick"); + } + + if (!session.ColumnExist("fl_member_info", "ignore_group_update")) + { + strb.AppendLine("fl_member_info 2"); + session.AddColumn("fl_member_info", "ignore_group_update", "integer default 0"); + } + + if (!session.ColumnExist("fl_member_info", "chat_count")) + { + strb.AppendLine("fl_member_info 3"); + session.AddColumn("fl_member_info", "chat_count", "integer default 0"); + session.AddColumn("fl_member_info", "blackout_time", "datetime default '2000-01-01 00:00:00'"); + } + + if (!session.ColumnExist("fl_member_info", "identity_card")) + { + strb.AppendLine("fl_member_info 4"); + session.AddColumn("fl_member_info", "identity_card", "varchar(255)"); + } + + if (!session.ColumnExist("fl_member_info", "headurl")) + { + strb.AppendLine("fl_member_info 4.1"); + session.AddColumn("fl_member_info", "headurl", "varchar(255) default ''"); + } + + if (!session.ColumnExist("fl_member_info", "identity_name")) + { + strb.AppendLine("fl_member_info 5"); + session.AddColumn("fl_member_info", "identity_name", "varchar(255)"); + } + + if (!session.ColumnExist("fl_member_info", "ban_exchange_time")) + { + strb.AppendLine("fl_member_info 6"); + session.AddColumn("fl_member_info", "ban_exchange_time", "datetime default '2000-01-01 00:00:00'"); + } + + if (!session.ColumnExist("fl_member_info", "private_ratio")) + { + strb.AppendLine("fl_member_info 7"); + session.AddColumn("fl_member_info", "private_ratio", "double default 0"); + } + + if (!session.ColumnExist("fl_member_info", "exchange_type")) + { + strb.AppendLine("fl_member_info 7-1"); + session.AddColumn("fl_member_info", "exchange_type", "integer default 0"); + } + + if (!session.ColumnExist("fl_member_info", "realnick")) + { + strb.AppendLine("fl_member_info 8"); + session.AddColumn("fl_member_info", "realnick", "varchar(255) default ''"); + session.AddColumn("fl_member_info", "wechatid", "varchar(255) default ''"); + } + + if (!session.ColumnExist("fl_member_info", "check_cloud_black_time")) + { + strb.AppendLine("fl_member_info 9"); + session.AddColumn("fl_member_info", "check_cloud_black_time", "datetime default '2000-01-01 00:00:00'"); + session.AddColumn("fl_member_info", "is_cloud_black", "boolean default 0"); + } + + if (!session.ColumnExist("fl_member_info", "bind_order")) + { + strb.AppendLine("fl_member_info 0"); + session.AddColumn("fl_member_info", "bind_order", "integer default 0"); + + var members = session.Find<fl_member_info>("select * from fl_member_info").Where(f => f.finish_order != 0).ToList(); + for (int i = 0; i < members.Count; i++) + { + members[i].bind_order = members[i].finish_order; + } + var _num = (int)Math.Ceiling((decimal)members.Count / 500m); + for (int o = 1; o <= _num; o++) + { + var _list = members.Skip((o - 1) * 500).Take(500).ToList(); + session.Updateable(_list.ToArray()).ExecuteCommand(); + } + } + } + + //云黑名单 + if (!session.TableExist<fl_cloud_black>()) + { + strb.AppendLine("fl_cloud_black"); + session.CreateTable<fl_cloud_black>(); + session.AddUnique<fl_cloud_black>("memberid"); + } + + if (!session.TableExist<fl_blackuser>()) + { + strb.AppendLine("fl_blackuser"); + session.CreateTable<fl_blackuser>(); + session.AddUnique<fl_blackuser>("username", "usertype"); + } + + if (!session.TableExist<fl_douyin_record>()) + { + strb.AppendLine("fl_douyin_record"); + session.CreateTable<fl_douyin_record>(); + session.AddUnique<fl_douyin_record>("product_id", "promotion_id"); + session.AddIndex<fl_statistics_record>("product_id"); + session.AddIndex<fl_statistics_record>("promotion_id"); + } + + if (!session.TableExist<fl_itempoint1_hist>()) + { + strb.AppendLine("fl_itempoint1_hist"); + session.CreateTable<fl_itempoint1_hist>(); + session.AddUnique<fl_itempoint1_hist>("guidkey"); + session.AddIndex<fl_itempoint1_hist>("guidkey"); + } + + //用户其他信息记录表 + if (!session.TableExist<fl_statistics_record>()) + { + strb.AppendLine("fl_statistics_record"); + session.CreateTable<fl_statistics_record>(); + session.AddIndex<fl_statistics_record>("uid"); + session.AddUnique<fl_statistics_record>("uid"); + } + else + { + strb.AppendLine("fl_statistics_record 2"); + try + { + var result = session.FindTable("select uid from fl_statistics_record group by uid having count(uid) > 1 order by uid"); + + if (result.Rows.Count != 0) + { + for (int i = 0; i < result.Rows.Count; i++) + { + var uid = result.Rows[i]["uid"].ToString(); + var records = session.Find<fl_statistics_record>("uid = @uid", new { uid = uid }); + fl_statistics_record _record = null; + foreach (var record in records) + { + if (_record == null) + _record = record; + else + { + if (_record.ex1 == 0) + _record.ex1 += record.ex1; + if (_record.ex2 == 0) + _record.ex2 += record.ex2; + _record.ex3 += record.ex3; + _record.ex4 += record.ex4; + _record.ex5 += record.ex5; + _record.ex6 += record.ex6; + _record.ex7 += record.ex7; + _record.ex8 += record.ex8; + _record.ex9 += record.ex9; + _record.ex10 += record.ex10; + _record.ex11 += record.ex11; + _record.ex12 += record.ex12; + _record.querynum += record.querynum; + session.Deleteable<fl_statistics_record>().In(record.id).ExecuteCommand(); + } + } + if (_record != null) + session.Updateable(_record).ExecuteCommand(); + } + } + + if (!session.ExistUnique("fl_statistics_record", "uid")) + session.AddUnique<fl_statistics_record>("uid"); + } + catch (Exception ex) + { } + } + + + if (!session.TableExist<fl_member_level>()) + { + strb.AppendLine("fl_member_level"); + session.CreateTable<fl_member_level>(); + } + + if (!session.TableExist<fl_alimama_tlj_create_record>()) + { + strb.AppendLine("fl_alimama_tlj_create_record"); + session.CreateTable<fl_alimama_tlj_create_record>(); + session.AddUnique<fl_alimama_tlj_create_record>("cpsname"); + } + + if (!session.TableExist<fl_alimama_tlj_get_record>()) + { + strb.AppendLine("fl_alimama_tlj_get_record"); + session.CreateTable<fl_alimama_tlj_get_record>(); + session.AddUnique<fl_alimama_tlj_get_record>("itemid"); + session.AddIndex<fl_alimama_tlj_get_record>("itemid", "expiredate"); + } + + if (!session.TableExist<fl_plugin_info>()) + { + strb.AppendLine("fl_plugin_info"); + session.CreateTable<fl_plugin_info>(); + } + if (!session.TableExist<fl_robot_info>()) + { + strb.AppendLine("fl_robot_info"); + session.CreateTable<fl_robot_info>(); + session.AddUnique<fl_robot_info>("name", "type"); + } + else + { + strb.AppendLine("fl_robot_info 2"); + if (!session.ColumnExist("fl_robot_info", "is_receives")) + { + session.AddColumn("fl_robot_info", "is_receives", "integer default 1"); + } + + if (!session.ColumnExist("fl_robot_info", "off_line_tip")) + { + session.AddColumn("fl_robot_info", "off_line_tip", "integer default 1"); + } + + if (!session.ColumnExist("fl_robot_info", "off_line_auto_login")) + { + session.AddColumn("fl_robot_info", "off_line_auto_login", "integer default 1"); + } + + } + + if (session.TableExist("fl_member_private_config")) + { + strb.AppendLine("fl_member_private_config"); + session.DropTable("fl_member_private_config"); + } + if (!session.TableExist<fl_weixin_password>()) + { + strb.AppendLine("fl_weixin_password"); + session.CreateTable<fl_weixin_password>(); + session.AddUnique<fl_weixin_password>("robot_id"); + } + else + { + strb.AppendLine("fl_weixin_password 2"); + //这个字段没有什么用,最早之前不知道为什么要给fl_weixin_password继承base_model + if (!session.ColumnExist("fl_weixin_password", "db_status_time")) + { + session.AddColumn("fl_weixin_password", "db_status_time", "varchar(25)"); + } + } + + if (!session.TableExist<fl_cps_member>()) + { + strb.AppendLine("fl_cps_member"); + session.CreateTable<fl_cps_member>(); + session.AddUnique<fl_cps_member>("username", "cpstype"); + } + else + { + strb.AppendLine("fl_cps_member 2"); + if (!session.ColumnExist("fl_cps_member", "abnormal_tip")) + { + session.AddColumn("fl_cps_member", "abnormal_tip", "integer default 1"); + } + + if (!session.ColumnExist("fl_cps_member", "is_download")) + { + session.AddColumn("fl_cps_member", "is_download", "integer default 1"); + } + + if (!session.ColumnExist("fl_cps_member", "is_valid")) + { + session.AddColumn("fl_cps_member", "is_valid", "boolean default 1"); + } + + if (!session.ColumnExist("fl_cps_member", "other")) + { + session.AddColumn("fl_cps_member", "other", "text"); + } + } + + try + { + session.UpdateColumnType("fl_cps_member", "cookies", "longText"); + } + catch (Exception) + { } + + + + if (!session.TableExist<fl_point_hist>()) + { + strb.AppendLine("fl_point_hist"); + session.CreateTable<fl_point_hist>(); + session.AddIndex<fl_point_hist>("crt_time", "type", "rid", "uid"); + session.AddIndex<fl_point_hist>("uid", "type"); + session.AddIndex<fl_point_hist>("uid", "type", "message"); + } + else + { + strb.AppendLine("fl_point_hist 2"); + if (!session.ColumnExist("fl_point_hist", "after_point")) + { + session.AddColumn("fl_point_hist", "after_point", "double default 0"); + session.AddColumn("fl_point_hist", "before_point", "double default 0"); + } + + if (!session.ColumnExist("fl_point_hist", "rid")) + { + session.AddColumn("fl_point_hist", "rid", "integer default 0"); + } + + if (!session.IndexExist<fl_point_hist>("uid", "type", "message")) + { + session.AddIndex<fl_point_hist>("uid", "type", "message"); + } + } + + if (!session.TableExist<fl_create_info>()) + { + strb.AppendLine("fl_create_info"); + session.CreateTable<fl_create_info>(); + session.AddUnique<fl_create_info>("groupid", "chat_type"); + } + if (!session.TableExist<fl_alimama_order_lastnum>()) + { + strb.AppendLine("fl_alimama_order_lastnum"); + session.CreateTable<fl_alimama_order_lastnum>(); + session.AddUnique<fl_alimama_order_lastnum>("lastnumber", "userid"); + session.AddIndex<fl_alimama_order_lastnum>("lastnumber"); + } + + if (!session.TableExist<fl_alimama_tlj_info>()) + { + strb.AppendLine("fl_alimama_tlj_info"); + session.CreateTable<fl_alimama_tlj_info>(); + session.AddUnique<fl_alimama_tlj_info>("username"); + } + + if (!session.TableExist<fl_tb_relation>()) + { + strb.AppendLine("fl_tb_relation"); + session.CreateTable<fl_tb_relation>(); + session.AddUnique<fl_tb_relation>("cps_memberid", "special_id"); + } + + //添加淘宝比例 + if (!session.TableExist<fl_ratio_info>()) + { + strb.AppendLine("fl_ratio_info"); + session.CreateTable<fl_ratio_info>(); + session.AddUnique<fl_ratio_info>("comm", "cps_type"); + + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.阿里妈妈, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.阿里妈妈, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.阿里妈妈, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.京东联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.京东联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.京东联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.多多进宝, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.多多进宝, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.多多进宝, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.苏宁易购, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.苏宁易购, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.苏宁易购, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.快手联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.快手联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.快手联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + else + { + strb.AppendLine("fl_ratio_info 2"); + try + { + var tmps = session.Queryable<fl_ratio_info>().Where(f => f.cps_type == CpsType.唯品联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.唯品联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + } + catch (Exception) + { } + + try + { + var tmps = session.Queryable<fl_ratio_info>().Where(f => f.cps_type == CpsType.抖音联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.抖音联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + } + catch (Exception) + { } + + try + { + var tmps = session.Queryable<fl_ratio_info>().Where(f => f.cps_type == CpsType.苏宁易购).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.苏宁易购, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.苏宁易购, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.苏宁易购, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + } + catch (Exception) + { } + + try + { + var tmps = session.Queryable<fl_ratio_info>().Where(f => f.cps_type == CpsType.快手联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.快手联盟, comm = 10.00, subsidy_num = 50.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.快手联盟, comm = 30.00, subsidy_num = 40.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_ratio_info>(new fl_ratio_info() { cps_type = CpsType.快手联盟, comm = 99999.00, subsidy_num = 30.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + } + catch (Exception) + { } + } + + + if (!session.TableExist<fl_member_group>()) + { + strb.AppendLine("fl_member_group"); + session.CreateTable<fl_member_group>(); + session.AddUnique<fl_member_group>("name"); + session.AddUnique<fl_member_group>("terms", "terms_ordersum"); + session.Insertable<fl_member_group>(new fl_member_group() { name = "大众会员", terms = 0, terms_ordersum = 0, subsidy = 0.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_member_group>(new fl_member_group() { name = "黄金会员", terms = 20, terms_ordersum = 5, subsidy = 0.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_member_group>(new fl_member_group() { name = "铂金会员", terms = 100, terms_ordersum = 15, subsidy = 0.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + session.Insertable<fl_member_group>(new fl_member_group() { name = "钻石会员", terms = 500, terms_ordersum = 50, subsidy = 0.00, subsidy_type = SubsidyType.百分比 }).ExecuteCommand(); + } + else + { + strb.AppendLine("fl_member_group 2"); + if (!session.ColumnExist("fl_member_group", "terms_ordersum")) + { + session.AddColumn("fl_member_group", "terms_ordersum", "integer default 0"); + try + { + session.AddUnique<fl_member_group>("terms", "terms_ordersum"); + + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + session.ExcuteSQL("drop INDEX fl_member_group_terms_", new { }); + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + session.ExcuteSQL("ALTER TABLE fl_member_group DROP INDEX terms", new { }); + } + } + catch (Exception ex) + { + } + } + if (!session.ColumnExist("fl_member_group", "ratio_custom_tb")) + { + session.AddColumn("fl_member_group", "ratio_custom_tb", "integer default 0"); + session.AddColumn("fl_member_group", "ratio_custom_pdd", "integer default 0"); + session.AddColumn("fl_member_group", "ratio_custom_jd", "integer default 0"); + session.AddColumn("fl_member_group", "ratio_custom_wph", "integer default 0"); + session.AddColumn("fl_member_group", "ratio_custom_dy", "integer default 0"); + } + + if (!session.ColumnExist("fl_member_group", "ratio_custom_sn")) + { + session.AddColumn("fl_member_group", "ratio_custom_sn", "integer default 0"); + } + if (!session.ColumnExist("fl_member_group", "ratio_custom_ks")) + { + session.AddColumn("fl_member_group", "ratio_custom_ks", "integer default 0"); + } + } + + if (!session.TableExist<fl_order_sleep>()) + { + strb.AppendLine("fl_order_sleep"); + session.CreateTable<fl_order_sleep>(); + session.AddUnique<fl_order_sleep>("money", "cps_type"); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.阿里妈妈 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.阿里妈妈 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.京东联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.京东联盟 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.多多进宝 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.多多进宝 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.唯品联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.唯品联盟 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.抖音联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.抖音联盟 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.苏宁易购 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.苏宁易购 }).ExecuteCommand(); + + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.快手联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.快手联盟 }).ExecuteCommand(); + + } + else + { + strb.AppendLine("fl_order_sleep 2"); + try + { + var tmps = session.Queryable<fl_order_sleep>().Where(f => f.cps_type == CpsType.唯品联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.唯品联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.唯品联盟 }).ExecuteCommand(); + } + } + catch (Exception) + { } + try + { + var tmps = session.Queryable<fl_order_sleep>().Where(f => f.cps_type == CpsType.抖音联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.抖音联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.抖音联盟 }).ExecuteCommand(); + } + } + catch (Exception) + { } + try + { + var tmps = session.Queryable<fl_order_sleep>().Where(f => f.cps_type == CpsType.苏宁易购).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.苏宁易购 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.苏宁易购 }).ExecuteCommand(); + } + } + catch (Exception) + { } + + try + { + var tmps = session.Queryable<fl_order_sleep>().Where(f => f.cps_type == CpsType.快手联盟).ToList(); + if (tmps == null || tmps.Count == 0) + { + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 30.00, sleep = 24, cps_type = CpsType.快手联盟 }).ExecuteCommand(); + session.Insertable<fl_order_sleep>(new fl_order_sleep() { money = 999999.00, sleep = 48, cps_type = CpsType.快手联盟 }).ExecuteCommand(); + } + } + catch (Exception) + { } + } + + if (!session.TableExist<fl_query_ratio_hist>()) + { + strb.AppendLine("fl_query_ratio_hist"); + session.CreateTable<fl_query_ratio_hist>(); + session.AddUnique<fl_query_ratio_hist>("cpstype", "db_orderid"); + } + + if (!session.TableExist<fl_operation_log>()) + { + strb.AppendLine("fl_operation_log"); + session.CreateTable<fl_operation_log>(); + session.AddIndex<fl_operation_log>("otype", "datetime"); + session.AddIndex<fl_operation_log>("datetime"); + } + + if (!session.TableExist<fl_query_hist>()) + { + strb.AppendLine("fl_query_hist"); + session.CreateTable<fl_query_hist>(); + session.AddIndex<fl_query_hist>("userid", "itemid", "adzoneid", "crt_time"); + } + else + { + strb.AppendLine("fl_query_hist 2"); + if (!session.ColumnExist("fl_query_hist", "adzoneid")) + { + session.AddColumn("fl_query_hist", "adzoneid", "varchar(255)"); + } + + if (!session.ColumnExist("fl_query_hist", "is_multiple")) + { + session.AddColumn("fl_query_hist", "is_multiple", "boolean default 0"); + } + + if (!session.ColumnExist("fl_query_hist", "mallid")) + { + session.Deleteable<fl_query_hist>().Where(f => f.crt_time < DateTime.Now.AddMonths(-2)).ExecuteCommand(); + session.AddColumn("fl_query_hist", "mallid", "varchar(30)"); + } + + if (!session.IndexExist<fl_query_hist>("compute_configdic")) + { + session.AddColumn("fl_query_hist", "compute_configdic", "text"); + } + } + + if (!session.TableExist<fl_order_alimama>()) + { + strb.AppendLine("fl_order_alimama"); + session.CreateTable<fl_order_alimama>(); + session.AddUnique<fl_order_alimama>("trade_id", "trade_parent_id"); + session.AddIndex<fl_order_alimama>("create_time", "db_status"); + session.AddIndex<fl_order_alimama>("db_userid", "db_status", "db_endtime", "alipay_total_price"); + session.AddIndex<fl_order_alimama>("create_time", "db_userid"); + session.AddIndex<fl_order_alimama>("trade_parent_id"); + session.AddIndex<fl_order_alimama>("paid_time", "db_status"); + session.AddIndex<fl_order_alimama>("db_robotname", "db_robottype"); + session.AddIndex<fl_order_alimama>("earning_time", "db_status"); + //session.AddIndex<fl_order_alimama>("trade_parent_id", "db_userid", "adzone_id", "create_time"); + //session.AddIndex<fl_order_alimama>("num_iid", "item_title", "db_cpsnick", "db_cpsname"); + //session.AddIndex<fl_order_alimama>("db_status", "db_userid"); + } + else + { + strb.AppendLine("fl_order_alimama 2"); + //if (!session.IndexExist<fl_order_alimama>("db_status")) + //{ + // session.AddIndex<fl_order_alimama>("db_status", "db_userid"); + //} + + if (!session.IndexExist<fl_order_alimama>("db_userid", "db_status", "db_endtime", "alipay_total_price")) + { + session.AddIndex<fl_order_alimama>("db_userid", "db_status", "db_endtime", "alipay_total_price"); + } + + if (!session.IndexExist<fl_order_alimama>("db_status", "db_endtime")) + { + session.AddIndex<fl_order_alimama>("db_status", "db_endtime"); + } + if (!session.IndexExist<fl_order_alimama>("db_status", "create_time")) + { + session.AddIndex<fl_order_alimama>("db_status", "create_time"); + } + + var flag1 = checkIndex(session, "fl_order_alimama", "db_status", "db_userid"); + var flag2 = checkIndex(session, "fl_order_alimama", "item_title", "db_cpsnick", "db_cpsname"); + var flag3 = checkIndex(session, "fl_order_alimama", "trade_parent_id", "db_userid", "adzone_id", "create_time"); + var flag4 = checkIndex(session, "fl_order_alimama", "num_iid", "item_title", "db_cpsnick", "db_cpsname"); + var flag5 = checkIndex(session, "fl_order_alimama", "db_status", "db_userid"); + var flag6 = checkIndex(session, "fl_order_alimama", "db_userid", "adzone_id", "num_iid", "create_time"); + + if (flag1 || flag2 || flag3 || flag4 || flag5 || flag6) + { + session.AddIndex<fl_order_alimama>("create_time", "db_status"); + session.AddIndex<fl_order_alimama>("db_userid", "db_status"); + session.AddIndex<fl_order_alimama>("create_time", "db_userid"); + session.AddIndex<fl_order_alimama>("trade_parent_id"); + session.AddIndex<fl_order_alimama>("paid_time", "db_status"); + session.AddIndex<fl_order_alimama>("db_robotname", "db_robottype"); + session.AddIndex<fl_order_alimama>("earning_time", "db_status"); + } + + if (!session.ColumnExist("fl_order_alimama", "seller_id")) + { + session.AddColumn("fl_order_alimama", "seller_id", "varchar(30)"); + } + if (!session.ColumnExist("fl_order_alimama", "paid_time")) + { + session.AddColumn("fl_order_alimama", "paid_time", "datetime"); + } + if (!session.ColumnExist("fl_order_alimama", "deposit_price")) + { + session.AddColumn("fl_order_alimama", "deposit_price", "varchar(30)"); + } + if (!session.ColumnExist("fl_order_alimama", "tb_deposit_time")) + { + session.AddColumn("fl_order_alimama", "tb_deposit_time", "varchar(25)"); + } + if (!session.ColumnExist("fl_order_alimama", "db_status_time")) + { + session.AddColumn("fl_order_alimama", "db_status_time", "varchar(25)"); + } + if (!session.ColumnExist("fl_order_alimama", "alimama_rate")) + { + session.AddColumn("fl_order_alimama", "alimama_rate", "double default 0"); + } + if (!session.ColumnExist("fl_order_alimama", "alimama_share_fee")) + { + session.AddColumn("fl_order_alimama", "alimama_share_fee", "double default 0"); + } + if (!session.ColumnExist("fl_order_alimama", "special_id")) + { + session.AddColumn("fl_order_alimama", "special_id", "integer default 0"); + } + if (!session.ColumnExist("fl_order_alimama", "relation_id")) + { + session.AddColumn("fl_order_alimama", "relation_id", "integer default 0"); + } + } + + if (!session.TableExist<fl_order_pinduoduo>()) + { + strb.AppendLine("fl_order_pinduoduo"); + session.CreateTable<fl_order_pinduoduo>(); + session.AddUnique<fl_order_pinduoduo>("order_sn"); + //session.AddIndex<fl_order_pinduoduo>("order_sn", "db_userid", "db_cpsnick", "order_create_time"); + //session.AddIndex<fl_order_pinduoduo>("db_cpsname", "p_id", "goods_name", "goods_id"); + //session.AddIndex<fl_order_pinduoduo>("db_status", "db_userid"); + + session.AddIndex<fl_order_pinduoduo>("db_userid", "db_status"); + session.AddIndex<fl_order_pinduoduo>("order_create_time", "db_status"); + session.AddIndex<fl_order_pinduoduo>("order_create_time", "db_userid"); + session.AddIndex<fl_order_pinduoduo>("db_status", "db_endtime"); + session.AddIndex<fl_order_pinduoduo>("db_robotname", "db_robottype"); + //session.AddIndex<fl_order_pinduoduo>("goods_id", "order_create_time"); + } + else + { + strb.AppendLine("fl_order_pinduoduo 2"); + //if (!session.IndexExist<fl_order_pinduoduo>("goods_id", "order_create_time")) + //{ + // session.AddIndex<fl_order_pinduoduo>("goods_id", "order_create_time"); + //} + + //if (!session.IndexExist<fl_order_pinduoduo>("db_status")) + //{ + // session.AddIndex<fl_order_pinduoduo>("db_status", "db_userid"); + //} + + //if (!session.IndexExist<fl_order_pinduoduo>("db_userid")) + //{ + // session.AddIndex<fl_order_pinduoduo>("db_userid", "db_cpsnick", "db_cpsname"); + // session.AddIndex<fl_order_pinduoduo>("p_id", "goods_name", "goods_id", "order_create_time"); + //} + + var flag1 = checkIndex(session, "fl_order_pinduoduo", "order_sn", "db_userid", "db_cpsnick", "order_create_time"); + var flag2 = checkIndex(session, "fl_order_pinduoduo", "db_cpsname", "p_id", "goods_name", "goods_id"); + var flag3 = checkIndex(session, "fl_order_pinduoduo", "db_status", "db_userid"); + var flag4 = checkIndex(session, "fl_order_pinduoduo", "db_userid", "db_cpsnick", "db_cpsname"); + var flag5 = checkIndex(session, "fl_order_pinduoduo", "p_id", "goods_name", "goods_id", "order_create_time"); + if (flag1 || flag2 || flag3 || flag4 || flag5) + { + session.AddIndex<fl_order_pinduoduo>("db_userid", "db_status"); + session.AddIndex<fl_order_pinduoduo>("order_create_time", "db_status"); + session.AddIndex<fl_order_pinduoduo>("order_create_time", "db_userid"); + session.AddIndex<fl_order_pinduoduo>("db_status", "db_endtime"); + session.AddIndex<fl_order_pinduoduo>("db_robotname", "db_robottype"); + } + + if (!session.ColumnExist("fl_order_pinduoduo", "mall_id")) + { + session.AddColumn("fl_order_pinduoduo", "mall_id", "varchar(30)"); + } + + if (!session.ColumnExist("fl_order_pinduoduo", "db_status_time")) + { + session.AddColumn("fl_order_pinduoduo", "db_status_time", "varchar(25)"); + } + + if (!session.ColumnExist("fl_order_pinduoduo", "price_compare_status")) + { + session.AddColumn("fl_order_pinduoduo", "price_compare_status", "integer"); + } + } + + if (!session.TableExist<fl_order_jingdong>()) + { + strb.AppendLine("fl_order_jingdong"); + session.CreateTable<fl_order_jingdong>(); + session.AddUnique<fl_order_jingdong>("orderId", "skuId"); + //session.AddIndex<fl_order_jingdong>("orderId", "db_userid", "db_cpsnick", "orderTime"); + //session.AddIndex<fl_order_jingdong>("db_cpsname", "positionId", "skuId", "skuName"); + session.AddIndex<fl_order_jingdong>("orderId"); + session.AddIndex<fl_order_jingdong>("db_userid", "db_status", "db_endtime", "estimateCosPrice"); + session.AddIndex<fl_order_jingdong>("orderTime", "db_status"); + session.AddIndex<fl_order_jingdong>("orderTime", "db_userid"); + session.AddIndex<fl_order_jingdong>("db_status", "finishTime"); + session.AddIndex<fl_order_jingdong>("db_robotname", "db_robottype"); + } + else + { + strb.AppendLine("fl_order_jingdong 2"); + if (!session.IndexExist<fl_order_jingdong>("db_userid", "db_status", "db_endtime", "estimateCosPrice")) + { + session.AddIndex<fl_order_jingdong>("db_userid", "db_status", "db_endtime", "estimateCosPrice"); + } + + try + { + if (!session.IndexExist<fl_order_jingdong>("orderId")) + { + session.AddIndex<fl_order_jingdong>("orderId"); + } + } + catch (Exception ex) + { } + + //if (!session.IndexExist<fl_order_jingdong>("db_status")) + //{ + // session.AddIndex<fl_order_jingdong>("db_status", "db_userid"); + //} + + //if (!session.IndexExist<fl_order_jingdong>("db_userid")) + //{ + // session.AddIndex<fl_order_jingdong>("db_userid", "db_cpsnick", "db_cpsname"); + // session.AddIndex<fl_order_jingdong>("positionId", "skuId", "skuName", "orderTime"); + //} + + var flag1 = checkIndex(session, "fl_order_jingdong", "orderId", "db_userid", "db_cpsnick", "orderTime"); + var flag2 = checkIndex(session, "fl_order_jingdong", "db_cpsname", "positionId", "skuId", "skuName"); + var flag3 = checkIndex(session, "fl_order_jingdong", "db_status", "db_userid"); + var flag4 = checkIndex(session, "fl_order_jingdong", "db_userid", "db_cpsnick", "db_cpsname"); + var flag5 = checkIndex(session, "fl_order_jingdong", "positionId", "skuId", "skuName", "orderTime"); + if (flag1 || flag2 || flag3 || flag4 || flag5) + { + session.AddIndex<fl_order_jingdong>("db_userid", "db_status"); + session.AddIndex<fl_order_jingdong>("orderTime", "db_status"); + session.AddIndex<fl_order_jingdong>("orderTime", "db_userid"); + session.AddIndex<fl_order_jingdong>("db_status", "finishTime"); + session.AddIndex<fl_order_jingdong>("db_robotname", "db_robottype"); + } + + #region 增加一个字段 plus + + if (!session.ColumnExist("fl_order_jingdong", "plus")) + { + session.AddColumn("fl_order_jingdong", "plus", "integer default 0"); + } + + if (!session.ColumnExist("fl_order_jingdong", "db_status_time")) + { + session.AddColumn("fl_order_jingdong", "db_status_time", "varchar(25)"); + } + + if (!session.ColumnExist("fl_order_jingdong", "proPriceAmount")) + { + session.AddColumn("fl_order_jingdong", "proPriceAmount", "double default 0"); + } + + #endregion + + #region 修改mysql中int类型,类中long的类型 以后可以删除 + //获取公共属性 + //if (session.CurrentConnectionConfig.DbType == DbType.MySql) + //{ + // PropertyInfo[] Propertys = typeof(fl_order_jingdong).GetProperties(); + // foreach (var item in Propertys) + // { + // string _name = item.Name; + // string _type = string.Empty; + // bool _primary = false; + // var _attribute = item.GetCustomAttributes().FirstOrDefault(f => f.GetType() == typeof(SugarColumn)) as SugarColumn; + // if (_attribute != null) + // { } + // if (item.Name.ToLower() == "id" || _primary) + // { } + // else if (!string.IsNullOrEmpty(_type)) + // { } + // else + // { + // if (item.PropertyType.FullName == typeof(Int64).ToString()) + // { + // session.ExcuteSQL("ALTER TABLE fl_order_jingdong MODIFY COLUMN " + _name + " bigint(11) DEFAULT 0", new { }); + // } + // } + // } + //} + #endregion + + #region 修改订单状态,最开始导致的,完成的订单变成了 部分退款 + //session.ExcuteSQL("update fl_order_jingdong set db_status = 1002 where db_status = 998"); + #endregion + + if (!session.ColumnExist("fl_order_jingdong", "refundcreatetime")) + { + session.AddColumn("fl_order_jingdong", "refundcreatetime", "datetime"); + } + } + + //000000 + if (!session.TableExist<fl_order_weipinhui>()) + { + strb.AppendLine("fl_order_weipinhui"); + session.CreateTable<fl_order_weipinhui>(); + session.AddUnique<fl_order_weipinhui>("orderSn", "goodsId", "sizeId"); + //session.AddUnique<fl_order_weipinhui>("orderSn"); + + session.AddIndex<fl_order_weipinhui>("db_userid", "db_status", "db_endtime", "commissionTotalCost"); + session.AddIndex<fl_order_weipinhui>("orderTime", "db_status"); + session.AddIndex<fl_order_weipinhui>("orderTime", "db_userid"); + session.AddIndex<fl_order_weipinhui>("db_status", "db_endtime"); + session.AddIndex<fl_order_weipinhui>("db_robotname", "db_robottype"); + } + else + { + strb.AppendLine("fl_order_weipinhui 2"); + //if (session.CurrentConnectionConfig.DbType == DbType.Sqlite || (session.CurrentConnectionConfig.DbType == DbType.MySql && session.ExistUnique("fl_order_weipinhui", "orderSn"))) + //{ + // if (session.DeleteUnique("fl_order_weipinhui", "orderSn")) + // { + // try + // { + // session.AddUnique<fl_order_weipinhui>("orderSn", "goodsId"); + // } + // catch (Exception ex) + // { } + // } + //} + + if (!session.IndexExist<fl_order_weipinhui>("db_userid", "db_status", "db_endtime", "commissionTotalCost")) + { + session.AddIndex<fl_order_weipinhui>("db_userid", "db_status", "db_endtime", "commissionTotalCost"); + } + + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite || (session.CurrentConnectionConfig.DbType == DbType.MySql && session.ExistUnique("fl_order_weipinhui", "orderSn", "goodsId"))) + { + if (session.DeleteUnique("fl_order_weipinhui", "orderSn", "goodsId")) + { + try + { + session.AddUnique<fl_order_weipinhui>("orderSn", "goodsId", "sizeId"); + } + catch (Exception ex) + { } + } + } + } + + //000000 + if (!session.TableExist<fl_order_douyin>()) + { + strb.AppendLine("fl_order_douyin"); + session.CreateTable<fl_order_douyin>(); + session.AddUnique<fl_order_douyin>("order_id", "product_id"); + session.AddIndex<fl_order_douyin>("db_userid", "db_status", "db_endtime", "total_pay_amount"); + session.AddIndex<fl_order_douyin>("pay_time", "db_status"); + session.AddIndex<fl_order_douyin>("pay_time", "db_userid"); + session.AddIndex<fl_order_douyin>("db_status", "db_endtime"); + session.AddIndex<fl_order_douyin>("db_robotname", "db_robottype"); + } + else + { + strb.AppendLine("fl_order_douyin 2"); + if (!session.IndexExist<fl_order_douyin>("db_userid", "db_status", "db_endtime", "total_pay_amount")) + { + session.AddIndex<fl_order_douyin>("db_userid", "db_status", "db_endtime", "total_pay_amount"); + } + } + + if (!session.TableExist<fl_order_suning>()) + { + strb.AppendLine("fl_order_suning"); + session.CreateTable<fl_order_suning>(); + session.AddUnique<fl_order_suning>("orderCode", "orderLineNumber"); + session.AddIndex<fl_order_suning>("db_userid", "db_status", "db_endtime", "payAmount"); + session.AddIndex<fl_order_suning>("payTime", "db_status"); + session.AddIndex<fl_order_suning>("payTime", "db_userid"); + session.AddIndex<fl_order_suning>("payTime", "pid"); + session.AddIndex<fl_order_suning>("db_status", "db_endtime"); + session.AddIndex<fl_order_suning>("db_robotname", "db_robottype"); + } + else + { + strb.AppendLine("fl_order_suning 2"); + if (!session.IndexExist<fl_order_suning>("db_userid", "db_status", "db_endtime", "payAmount")) + { + session.AddIndex<fl_order_suning>("db_userid", "db_status", "db_endtime", "payAmount"); + } + } + + if (!session.TableExist<fl_order_kuaishou>()) + { + strb.AppendLine("fl_order_kuaishou"); + session.CreateTable<fl_order_kuaishou>(); + session.AddUnique<fl_order_kuaishou>("oid", "oid2"); + session.AddIndex<fl_order_kuaishou>("db_userid", "db_status", "db_endtime", "itemPrice"); + session.AddIndex<fl_order_kuaishou>("payTime", "db_status"); + session.AddIndex<fl_order_kuaishou>("payTime", "db_userid"); + session.AddIndex<fl_order_kuaishou>("payTime", "pid"); + session.AddIndex<fl_order_kuaishou>("db_status", "db_endtime"); + session.AddIndex<fl_order_kuaishou>("db_robotname", "db_robottype"); + } + + + if (!session.TableExist<fl_suning_tgw>()) + { + strb.AppendLine("fl_suning_tgw"); + session.CreateTable<fl_suning_tgw>(); + session.AddUnique<fl_suning_tgw>("username", "toolpid"); + session.AddIndex<fl_suning_tgw>("username", "toolpid"); + } + + if (!session.TableExist<fl_bind_cache>()) + { + strb.AppendLine("fl_bind_cache"); + session.CreateTable<fl_bind_cache>(); + session.AddIndex<fl_bind_cache>("orderid"); + } + + if (!session.TableExist<fl_shpay_hist>()) + { + strb.AppendLine("fl_shpay_hist"); + session.CreateTable<fl_shpay_hist>(); + session.AddUnique<fl_shpay_hist>("orderid"); + session.AddIndex<fl_shpay_hist>("rid", "ctime"); + session.AddIndex<fl_shpay_hist>("paytype", "chattype"); + } + + //try + //{ + // if (session.TableExist("fl_alimama_activity_pid")) + // session.DropTable("fl_alimama_activity_pid"); + // session.DropTable("fl_alimama_pid_activity"); + //} + //catch (Exception) + //{ } + + bool first = false; + if (!session.TableExist<fl_dictionary_item>()) + { + strb.AppendLine("fl_dictionary_item"); + session.CreateTable<fl_dictionary_item>(); + session.AddUnique<fl_dictionary_item>("dickey"); + first = true; + } + + if (!session.TableExist<fl_exchange_info>()) + { + strb.AppendLine("fl_exchange_info"); + session.CreateTable<fl_exchange_info>(); + session.AddIndex<fl_exchange_info>("uid", "state"); + if (session.TableExist("fl_plugin_pointmanage_exchange_list")) + { + var queryable = session.Queryable("fl_plugin_pointmanage_exchange_list", "pel").AddJoinInfo("fl_robot_info", "r", "r.name = pel.robot_name").Select<fl_exchange_info>("r.id as rid,pel.*").ToList(); + session.Insertable(queryable).ExecuteCommand(); + } + } + else + { + strb.AppendLine("fl_exchange_info 2"); + if (!session.IndexExist<fl_exchange_info>("uid", "state")) + { + session.AddIndex<fl_exchange_info>("uid", "state"); + } + + if (!session.ColumnExist("fl_exchange_info", "groupid")) + { + session.AddColumn("fl_exchange_info", "groupid", "varchar(255)"); + } + + if (!session.ColumnExist("fl_exchange_info", "check_time")) + { + session.AddColumn("fl_exchange_info", "check_time", "datetime default '2000-01-01 00:00:00'"); + } + } + // session.Commit(); + return first; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Debug("表异常", strb.ToString()); + throw ex; + } + return false; + } + + /// <summary> + /// 重置定时器 + /// </summary> + internal static void ResetTimer() + { + //关闭以前的线程 + TimerTask.Close<ClearGarbageTimer>(); + TimerTask.Close<DownPinduoduoTimer>(); + TimerTask.Close<DownAlimamaTimer>(); + TimerTask.Close<DownJingdongTimer>(); + TimerTask.Close<DownWeipinhuiTimer>(); + TimerTask.Close<DownDouyinTimer>(); + TimerTask.Close<DownSuningTimer>(); + TimerTask.Close<Update_NoticeQueue>(); + TimerTask.Close<Update_CpsStatus>(); + + //启动新的线程 + TimerTask.NewTimer<Update_NoticeQueue>(1);//处理队列消息 + TimerTask.NewTimer<Update_CpsStatus>(360);//更新联盟状态 + TimerTask.NewTimer<ClearGarbageTimer>(Setting.SystemConfig.timer_clear_memory); //注册清理垃圾线程 + TimerTask.NewTimer<DownPinduoduoTimer>(Setting.SystemConfig.time_down_pinduoduo); //下载拼多多订单线程 + TimerTask.NewTimer<DownAlimamaTimer>(Setting.SystemConfig.timer_down_alimama); //下载阿里妈妈订单线程 + TimerTask.NewTimer<DownJingdongTimer>(Setting.SystemConfig.time_down_jingdong); //下载京东订单线程 + TimerTask.NewTimer<DownWeipinhuiTimer>(Setting.SystemConfig.time_down_weipinhui); //下载唯品会订单线程 + TimerTask.NewTimer<DownDouyinTimer>(Setting.SystemConfig.time_down_douyin); //下载抖音订单线程 + TimerTask.NewTimer<DownSuningTimer>(Setting.SystemConfig.time_down_suning); //下载苏宁订单线程 + TimerTask.NewTimer<DownKuaiShouTimer>(Setting.SystemConfig.time_down_kuaishou); //下载快手订单线程 + } + /// <summary> + /// 缓存 + /// </summary> + public static CacheTool Cache { get; private set; } + + private static object getsession_lock = new object(); + + /// <summary> + /// 获取数据库操作对象 + /// </summary> + /// <param name="config">数据库连接配置,如果是软件的数据库该值不需要传</param> + /// <param name="iscache"></param> + /// <returns></returns> + public static SqlSugarClient GetSession(Api.Framework.Tools.ConnectionConfig config = null, bool iscache = true) + { + if (config == null) config = Setting.DbConfig; + + DbType type = DbType.MySql; + if (config.DatabaseType == DatabaseType.SQLITE) type = DbType.Sqlite; + else if (config.DatabaseType == DatabaseType.MYSQL) type = DbType.MySql; + else return null; + SqlSugarClient session = new SqlSugarClient(new SqlSugar.ConnectionConfig() + { + MoreSettings = new ConnMoreSettings() { IsAutoRemoveDataCache = true }, + ConnectionString = config.ConnectionString, //必填 + DbType = type, //必填 + IsAutoCloseConnection = true, + InitKeyType = InitKeyType.Attribute + }); + + session.Aop.OnLogExecuted = (sql, pars) => + { + var timeOut = session.Ado.SqlExecutionTime.TotalSeconds; + if (timeOut >= 2) + { + //慢查询SQL + var temp = sql; + foreach (var item in pars) + { + temp = temp.Replace($"{item.ParameterName}", "'" + item.Value.ToString() + "'"); + } + LogHelper.GetSingleObj().SqlMan("sql慢日志:", $"慢查询日志({timeOut}秒):{temp}"); + } + + //执行完了可以输出SQL执行时间 (OnLogExecutedDelegate) + }; + return session; + } + + /// <summary> + /// 发送信息 + /// </summary> + /// <param name="message">消息内容</param> + /// <param name="robot">通过哪个机器人发送</param> + public static void SendAdminMessage(string message, fl_robot_info robot, string title = "系统消息") + { + //邮件通知管理员 + if (!string.IsNullOrEmpty(Setting.SystemConfig.account_admin_email)) + { + //邮箱通知 + var emails = Setting.SystemConfig.account_admin_email.Split(','); + foreach (var item in emails) + { + SendAdminEmail(item, title, title + "<br>" + message, true); + } + } + } + + /// <summary> + /// 发送邮件 + /// </summary> + /// <param name="toemail">收件人</param> + /// <param name="title">标题</param> + /// <param name="content">内容</param> + /// <param name="tryException">捕获</param> + /// <param name="begin">异步</param>//ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "机器人即将到期通知", msg, true); + public static void SendAdminEmail(string toemail, string title, string content, bool tryException = false, bool begin = true) + { + try + { + var config = Setting.SystemConfig; + Util.SendEmail(config.SMTP_Host, config.SMTP_Port, config.SMTP_User, config.SMTP_Pass, config.SMTP_SSL == SwitchType.开启 ? true : false, toemail, title, content, begin); + } + catch (Exception ex) + { + if (tryException) return; + else EventClient.OnEvent(null, "发送邮件:" + ex.Message); + } + } + + /// <summary> + /// 发送邮件 + /// </summary> + /// <param name="toemail">收件人</param> + /// <param name="title">标题</param> + /// <param name="content">内容</param> + /// <param name="file"></param> + /// <param name="tryException">捕获</param> + /// <param name="begin">异步</param>//ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "机器人即将到期通知", msg, true); + public static void SendAdminEmail(string toemail, string title, string content, string file, bool tryException = false, bool begin = true) + { + try + { + var config = Setting.SystemConfig; + Util.SendEmail(config.SMTP_Host, config.SMTP_Port, config.SMTP_User, config.SMTP_Pass, config.SMTP_SSL == SwitchType.开启, toemail, title, content, begin, file); + } + catch (Exception ex) + { + if (tryException) return; + else EventClient.OnEvent(null, "发送邮件:" + ex.Message); + } + } + + /// <summary> + /// 商户支付 + /// </summary> + /// <param name="remark"></param> + /// <param name="describe"></param> + /// <param name="money"></param> + /// <returns>返回 连接为点击领取 + /// 返回 "已转账"为自动转账 + /// 返回 空为异常</returns> + [Obsolete("改方法已过时")] + public static string SendWechatPay(object remark, string describe, double money) + { + try + { + var pay = new WechatPay(); + var result = string.Empty; + if (!string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_hostSign)) + { + result = pay.Create(Setting.SystemConfig.pay_wechat_hostSign, remark, describe, money); + //Console.WriteLine(result); + } + else + { + result = pay.Create(Setting.SystemConfig.pay_wechat_gzh_appid, Setting.SystemConfig.pay_wechat_sh_appid, Setting.SystemConfig.pay_wechat_gzh_appsecret, Setting.SystemConfig.pay_wechat_sh_appsecret, money, HttpHelper.ObjectToJson(remark), describe); + } + //if (string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_host)) throw new Exception("您没有填写服务器信息!"); + if (!string.IsNullOrEmpty(result)) + { + if (result == "操作超时") + { + EventClient.OnEvent(null, $"【{money}积分】商户连接:{result}"); + return string.Empty; + } + else if (result == "已转账") + { + RecordShPay(result, remark, money, PayGetType.已领取); + //返回为空,获取商户异常 + return result; + } + RecordShPay(result, remark, money, PayGetType.未领取); + } + return result; + } + catch (Exception ex) + { + EventClient.OnEvent(null, ex.Message); + } + return string.Empty; + } + + /// <summary> + /// 发视商户支付 + /// </summary> + /// <param name="remark"></param> + /// <param name="describe"></param> + /// <param name="money"></param> + /// <param name="ispaid"></param> + /// <returns></returns> + public static string SendWechatPay(object remark, string describe, double money, out bool ispaid) + { + ispaid = false; + try + { + var pay = new WechatPay(); + var result = string.Empty; + if (!string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_hostSign)) + { + result = pay.Create(Setting.SystemConfig.pay_wechat_hostSign, remark, describe, money, out ispaid); + //Console.WriteLine(result); + } + else + { + result = pay.Create(Setting.SystemConfig.pay_wechat_gzh_appid, Setting.SystemConfig.pay_wechat_sh_appid, Setting.SystemConfig.pay_wechat_gzh_appsecret, Setting.SystemConfig.pay_wechat_sh_appsecret, money, HttpHelper.ObjectToJson(remark), describe); + } + //if (string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_host)) throw new Exception("您没有填写服务器信息!"); + if (!string.IsNullOrEmpty(result)) + { + if (result == "操作超时") + { + EventClient.OnEvent(null, $"【{money}积分】商户连接:{result}"); + ispaid = false; + return string.Empty; + } + //else if (result == "已转账") + //{ + // //返回为空,获取商户异常 + // return result; + //} + RecordShPay(result, remark, money, ispaid ? PayGetType.已领取 : PayGetType.未领取); + } + return result; + } + catch (Exception ex) + { + EventClient.OnEvent(null, ex.Message); + } + return string.Empty; + } + + /// <summary> + /// 发送商户支付 + /// </summary> + /// <param name="remark">备注</param> + /// <param name="describe">描述</param> + /// <param name="money">金额</param> + /// <param name="ispaid">是否直接到账</param> + /// <param name="appinfo">小程序信息,微信可以用户发送小程序;不支持小程序返回null</param> + /// <returns></returns> + public static string SendWechatPay(object remark, string describe, double money, out bool ispaid, out object appinfo) + { + ispaid = false; + appinfo = null; + try + { + var pay = new WechatPay(); + var result = string.Empty; + if (!string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_hostSign)) + { + //念初 https://service-dbej45c6-1301483065.nj.apigw.tencentcs.com/api/624d64fe8805a?money=100&key=624d66df08ba5949556281&remark=付乐天 + if (Setting.SystemConfig.pay_wechat_hostSign.ToLower().Contains("nj.apigw.tencentcs.com")) + result = pay.Create2(Setting.SystemConfig.pay_wechat_hostSign, remark, describe, money); + else + result = pay.Create(Setting.SystemConfig.pay_wechat_hostSign, remark, describe, money, out ispaid, out appinfo); + //Console.WriteLine(result); + } + else + { + result = pay.Create(Setting.SystemConfig.pay_wechat_gzh_appid, Setting.SystemConfig.pay_wechat_sh_appid, Setting.SystemConfig.pay_wechat_gzh_appsecret, Setting.SystemConfig.pay_wechat_sh_appsecret, money, HttpHelper.ObjectToJson(remark), describe); + } + //if (string.IsNullOrEmpty(Setting.SystemConfig.pay_wechat_host)) throw new Exception("您没有填写服务器信息!"); + if (!string.IsNullOrEmpty(result)) + { + if (result == "操作超时") + { + EventClient.OnEvent(null, $"【{money}积分】商户连接:{result}"); + ispaid = false; + return string.Empty; + } + //else if (result == "已转账") + //{ + // //返回为空,获取商户异常 + // return result; + //} + RecordShPay(result, remark, money, ispaid ? PayGetType.已领取 : PayGetType.未领取); + } + return result; + } + catch (Exception ex) + { + EventClient.OnEvent(null, ex.Message); + } + return string.Empty; + } + + /// <summary> + /// 记录商户生成信息 + /// </summary> + /// <param name="url">连接</param> + /// <param name="remark">备注</param> + /// <param name="money">金额</param> + /// <param name="paytype">领取状态</param> + private static void RecordShPay(string url, object remark, double money, PayGetType paytype) + { + if (remark != null) + { + try + { + var db = ApiClient.GetSession(); + //robot_name = robot.name, robot_nick = robot.nick, username = member.username, usernick = member.usernick + var json = HttpHelper.ObjectToJson(remark); + if (!string.IsNullOrWhiteSpace(json)) + { + //var reg = Regex.Match(url, "orderid=(?<商户id>[^&]+)", RegexOptions.IgnoreCase); + var reg = Regex.Match(url, "orderid=(?<商户id>[^&]+)", RegexOptions.IgnoreCase); + if (reg.Success) + { + //reg = Regex.Match(url, "^(?<商户id>[a-zA-Z0-9]+)$", RegexOptions.IgnoreCase); + var jObj = JObject.Parse(json); + var time = DateTime.Now; + var shpay = new fl_shpay_hist() { payurl = url, ctime = CsharpHttpHelper.HttpExtend.GetTimeStamp(time), ctimedate = CsharpHttpHelper.HttpExtend.GetTimeStamp(time.Date), point = money, paytype = paytype, orderid = (reg.Success ? reg.Groups["商户id"].Value : string.Empty) }; + if (paytype == PayGetType.已领取) + shpay.paytime = CsharpHttpHelper.HttpExtend.GetTimeStamp(time); + + if (jObj["robot_name"] != null && jObj["username"] != null) + { + var r = db.FindRobots().FirstOrDefault(f => f.name == jObj["robot_name"].ToString()); + if (r != null) + { + shpay.chattype = r.type; + shpay.rid = r.id; + } + + var m = db.FindMemberInfoByUsername(jObj["username"].ToString()); + if (m != null) + { + shpay.uid = m.id; + shpay.usernick = m.realnick; + } + shpay.username = jObj["username"].ToString(); + shpay.robotname = jObj["robot_name"].ToString(); + shpay.robotnick = jObj["robot_nick"].ToString(); + + db.Insertable(shpay).ExecuteCommand(); + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("", $"记录商户生成连接异常:{ex.Message}"); + } + } + } + + /// <summary> + /// 通知钉钉机器人 + /// </summary> + /// <param name="_message">发送消息</param> + /// <param name="api">通知机器人名称</param> + /// <param name="secret">secret字符串</param> + public static void SendNewDingdingMessage(string _message, string api = "", string secret = "") + { + if (!string.IsNullOrEmpty(api) && ApiClient.Setting.SystemConfig.notice_robotname != "请选择(钉钉/微信群机器人API名称)") + { + SendNoticeMessage(_message); + return; + } + var _api = string.IsNullOrEmpty(api) ? ApiClient.Setting.SystemConfig.notice_dingding_robotapi : api; + var _api_token = string.IsNullOrEmpty(api) ? ApiClient.Setting.SystemConfig.notice_dingding_robotSecret : secret; + if (!string.IsNullOrEmpty(_api)) SendNoticeMessage(new fl_noticeapi_info() { name = "旧接口钉钉API地址", token = _api_token, api_location = _api, notice_apitype = NoticeApiType.企业钉钉机器人API }, _message); + + } + + /// <summary> + /// 发送通知【钉钉/微信群机器人】消息 + /// </summary> + /// <param name="message">消息内容</param> + /// <param name="name">名称,为空为系统设置</param> + public static void SendNoticeMessage(string message, string name = "") + { + if (string.IsNullOrWhiteSpace(name) || name == "请选择(钉钉/微信群机器人API名称)") + name = ApiClient.Setting.SystemConfig.notice_robotname; + var session = ApiClient.GetSession(); + var api = session.FindNoticeapiRobots().FirstOrDefault(f => f.name == name); + if (api != null) SendNoticeMessage(api, message); + } + + private static string LocalIp = ""; + /// <summary> + /// 获取本机外网IP + /// </summary> + /// <returns></returns> + public static string QueryInternetIP() + { + try + { + if (string.IsNullOrWhiteSpace(LocalIp)) + { + HttpHelper http = new HttpHelper(); + string html = http.GetHtml("https://ip.tool.lu").Html; + Match match = Regex.Match(html, "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})"); + if (match.Success) + LocalIp = match.Groups[1].Value; + } + } + catch (Exception ex) + { } + return LocalIp; + } + + /// <summary> + /// 通知机器人发送消息 + /// </summary> + /// <param name="api_entity">通知机器人对象</param> + /// <param name="message">发送消息</param> + /// <param name="is_begin">异步发送</param> + public static void SendNoticeMessage(fl_noticeapi_info api_entity, string message, bool is_begin = true) + { + if (api_entity == null || api_entity.name == "请选择(钉钉/微信群机器人API名称)") return; + + var _info = api_entity; + var _message = message.Replace("\r\n", "\n"); + if (string.IsNullOrWhiteSpace(_message)) return; + var appendIp = QueryInternetIP(); + if (!string.IsNullOrWhiteSpace(appendIp)) + _message += $@" +------------ +本消息来自IP:{appendIp}"; + Exception exception = null; + var action = new Action(delegate + { + for (int i = 0; i < 5; i++) + { + LogHelper.GetSingleObj().Error("", $@"【通知机器人】 => 发送消息:{_message})"); + try + { + var http = new HttpHelper(); + var item = http.GetItem(_info.api_location); + item.Method = "post"; + item.ContentType = "application/json;";//返回类型 可选项有默认值 + switch (_info.notice_apitype) + { + case NoticeApiType.企业钉钉机器人API: + { + if (!string.IsNullOrEmpty(_info.token)) + { + long dingTimestamp = (DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, 0).Ticks) / 10000; + string canonicalString = $"{dingTimestamp}\n{_info.token}"; + string signature = Convert.ToBase64String(Sign(Encoding.UTF8.GetBytes(canonicalString), Encoding.UTF8.GetBytes(_info.token))); + item.URL = item.URL + $"×tamp={dingTimestamp}&sign={signature}"; + } + item.PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte; + item.PostdataByte = Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { msgtype = "text", text = new { content = _message } })); + } + break; + case NoticeApiType.企业微信机器人API: + { + item.PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte; + item.PostdataByte = Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { msgtype = "text", text = new { content = _message } })); + } + break; + case NoticeApiType.飞书机器人API: + { + item.PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte; + if (_info.api_location.Contains("bot/v2/hook")) + item.PostdataByte = Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { msg_type = "text", content = new { text = _message } })); + else + item.PostdataByte = Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { title = "", text = _message })); + } + break; + default: throw new Exception("无法识别的API类型!" + _info.notice_apitype.ToString()); + } + + var html = http.GetHtml(item).Html; + //Console.WriteLine(html); + if (html.Contains("ok") || html.Contains("success")) + return; + throw new Exception(html); + } + catch (Exception ex) + { + if (ex.Message.Contains("sign not match")) + { + Thread.Sleep(370); + continue; + } + exception = ex; + EventClient.OnEvent(null, $"{_info.name}提醒失败:" + ex.Message); + } + } + }); + if (is_begin) action.BeginInvoke(null, null); + else + { + action.Invoke(); + + //抛出异常信息 + if (exception != null) throw exception; + } + } + + private static byte[] Sign(byte[] key, byte[] data) + { + HMACSHA256 sha256 = new HMACSHA256(data); + return sha256.ComputeHash(key); + } + + static ConcurrentDictionary<string, ConcurrentQueue<temp_send_data>> MessageQueue = new ConcurrentDictionary<string, ConcurrentQueue<temp_send_data>>(); + + ///// <summary> + ///// 发送消息2 + ///// </summary> + ///// <param name="robot">机器人</param> + ///// <param name="tousername">发送给谁</param> + ///// <param name="message">发送的消息SendNewDingdingMessage</param> + ///// <param name="groupid">发送的群(空位私聊)</param> + ///// <param name="TempMsgID">QQ的临时会话ID</param> + ///// <param name="token">临时会话的token</param> + ///// <returns></returns> + //public static Task SendWQMessage(fl_robot_info robot, string tousername, string message, string groupid = "", uint TempMsgID = 0, byte[] token = null) + //{ + // return SendMessage(new temp_send_data() { Groupid = groupid, Message = message, TouserName = tousername, Robot = robot, TempMsgID = TempMsgID, token = token }); + //} + + /// <summary> + /// 发送消息1 + /// </summary> + /// <param name="robot">机器人</param> + /// <param name="tousername">发送给谁</param> + /// <param name="message"></param> + /// <param name="groupid"></param> + public static Task SendMessage(fl_robot_info robot, string tousername, string message, string groupid = "") + { + return SendMessage(new temp_send_data() { Groupid = groupid, Message = message, TouserName = tousername, Robot = robot }); + } + + /// <summary> + /// 发送消息 + /// </summary> + /// <param name="robot">机器人对象</param> + /// <param name="tousername">接收者账号</param> + /// <param name="message">消息</param> + /// <param name="isTemp">机器人为QQ时,临时聊天需要复制为true</param> + /// <returns></returns> + public static Task SendMessage(fl_robot_info robot, string tousername, string message, bool isTemp) + { + return SendMessage(new temp_send_data() { IsTemp = isTemp, Message = message, TouserName = tousername, Robot = robot }); + } + + /// <summary> + /// 发送消息 + /// </summary> + /// <param name="data">temp_send_data对象集合</param> + /// <returns></returns> + public static Task SendMessage(params temp_send_data[] data) + { + var _data = data; + return Task.Run(() => + { + try + { + for (int i = 0; i < _data.Length; i++) + { + var item = _data[i]; + if (i > 0) Thread.Sleep(650); + try + { + #region 不处理不接受的机器人 + var session = ApiClient.GetSession(); + var robots = session.FindRobots(); + if (null != robots.FirstOrDefault(f => f.is_receives == Enums.SwitchType.关闭 && item.Robot.name == f.name)) + continue; + #endregion + + var groupid = item.Groupid; + var tousername = item.TouserName; + var robot = item.Robot; + var message = item.Message.Replace("[积分名称]", Setting.SystemConfig.PointName).Replace("[机器人账号]", robot.name).Replace("[机器人昵称]", robot.nick).Trim(); + + if (message.Contains("[编号]")) + { + string id = string.Empty; + var member = session.FindSingle<fl_member_info>("select * from fl_member_info where username = @username", new { username = item.TouserName }); + if (member != null) + id = member.id.ToString(); + message = message.Replace("[编号]", id); + } + + switch (item.Robot.type) + { + case ChatType.QQ: + { + var qBase = ChatClient.QQClients.FirstOrDefault(f => f.Key.ToString() == robot.name).Value; + + if (qBase is QQClientImpl_QQPlus) + { + var tmp = (qBase as QQClientImpl_QQPlus); + var qq = tmp.QQClient; + if (qq != null && qq.User != null && qq.User.LoginStatus == LoginStatus.Login) + { + if (!string.IsNullOrWhiteSpace(tousername)) + { + var member = session.FindBlacklistMemberInfos().FirstOrDefault(f => f.username == tousername); + if (member != null) break; + + var m = session.FindMemberInfoByUsername(tousername); + if (m.status != MemberType.白名单) + { + CloudBlack cloud = new CloudBlack(); + if (cloud.QueryBlack(tousername, item.Robot.type) != null) + break; + } + + if (message.Contains("[昵称]")) + { + member = session.FindSingle<fl_member_info>("select * from fl_member_info where robot_type = @robot_type and username = @username", new { username = tousername, robot_type = ChatType.QQ }); + if (member != null) + message = message.Replace("[账号]", tousername).Replace("[昵称]", member.usernick); + else + message = message.Replace("[账号]", tousername).Replace("[昵称]", string.Empty); + } + } + message = new VariateReplace().ReplaceUserVariate(message).Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + + uint target = 1; + var isGroup = false; + uint toUsernaem = 0; + if (string.IsNullOrEmpty(groupid)) + uint.TryParse(tousername, out target); + else + { + uint.TryParse(groupid, out target); + isGroup = true; + } + tmp.SendMessage(target, message, isGroup, item.IsTemp); + } + } + } + break; + case ChatType.微信: + case ChatType.企业微信: + { + if (!string.IsNullOrWhiteSpace(tousername)) + { + var member = session.FindBlacklistMemberInfos().FirstOrDefault(f => f.username == tousername); + if (member != null) break; + + var m = session.FindMemberInfoByUsername(tousername); + if (m.status != MemberType.白名单) + { + CloudBlack cloud = new CloudBlack(); + if (cloud.QueryBlack(tousername, item.Robot.type) != null) + break; + } + + if (message.Contains("[昵称]")) + { + member = session.FindSingle<fl_member_info>("select * from fl_member_info where robot_type = @robot_type and username = @username", new { username = tousername, robot_type = item.Robot.type }); + message = message.Replace("[昵称]", member == null ? string.Empty : member.usernick); + } + message = message.Replace("[账号]", tousername); + } + message = new VariateReplace().ReplaceUserVariate(message).Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == robot.name).Value; + if (wx != null && wx.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + message.Replace("[机器人微信]", wx.User.Username); + wx.SendMessage(string.IsNullOrWhiteSpace(groupid) ? tousername : groupid, message); + //EventClient.OnEvent(item, $"协议:{wx.WeixinHao} 给 {tousername} 发送 -> {message}"); + } + else + { + //EventClient.OnEvent(item, $"pc {robot.name} 发送:{message}"); + + var client = ChatClient.PCRobotPool.GetSession(robot.name); + if (client != null) + { + WechatMsgType messageType = WechatMsgType.文本; + PCRobotCMD robotCMD = PCRobotCMD.sendTxt; + message.Replace("[机器人微信]", robot.name); + #region 发送图片 + var match = Regex.Match(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Success) + { + var image = match.Groups[1].Value; + + //if (!image.StartsWith("http")) + //{ + // if (File.Exists(image)) + // { + // var bitmap = Util.PercentImage(Util.ReadImageFile(image), 280); + // var _image = image + Path.GetExtension(image);//压缩图片的地址 + // if (Util.YaSuo(bitmap, _image, 70)) + // { + // image = Util.FileToBase64(_image); + // } + // } + //} + message = image; + + messageType = WechatMsgType.图片; + robotCMD = PCRobotCMD.sendImg; + } + #endregion + + #region 发送视频 + match = Regex.Match(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Success) + { + //var video = Util.StrToHex(match.Groups[1].Value); + //if (video != null) + //{ + // var video_json = Encoding.UTF8.GetString(video); + // var video_data = CsharpHttpHelper.HttpExtend.JsonToDictionary(video_json); + // if (video_data != null) + // { + // //(username, video_data["cdnurl"].ToString(), video_data["aeskey"].ToString(), CDNType.发送视频); + + // } + //} + + message = match.Groups[1].Value; + + messageType = WechatMsgType.视频; + robotCMD = PCRobotCMD.sendFile; + } + #endregion + + #region 发送语音 + match = Regex.Match(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Success) + { + throw new Exception("PC协议不支持语音发送"); + } + #endregion + if (string.IsNullOrWhiteSpace(message)) return; + var msg = new ServerWechatMsg() + { + Cmd = robotCMD, + RobotType = item.Robot.type == ChatType.企业微信 ? RobotType.客户端企业微信 : RobotType.客户端微信, + RobotUsername = robot.name, + RobotUsernick = string.Empty, + ToMessage = message, + ToMessageType = messageType, + ToUsername = string.IsNullOrWhiteSpace(groupid) ? tousername : groupid, + Key = Setting.ServerConfig.SocketPassword + }; + //Console.WriteLine(groupid); + var json = HttpHelper.ObjectToJson(msg); + var text = PackTool.CompressString(json); + //AESCryption aes = new AESCryption(); + //json = aes.AesEncrypt(json,Setting.ServerConfig.SocketPassword.Substring(0,16)); + //Console.WriteLine(json); + var need_send = $"{msg.Cmd} {text}\r\n"; + //var need_send_data = Encoding.UTF8.GetBytes(need_send); + LogHelper.GetSingleObj().Debug("", $"给客户端发送消息:{msg.Cmd} - {text.Length}"); + client.TrySend(need_send); + } + } + } + break; + case ChatType.微信公众号: + break; + case ChatType.未知来源: + break; + default: + break; + } + } + catch (Exception ex) + { + EventClient.OnEvent(item, $"发送通知消息失败:{item.Robot.name}->{item.TouserName}->{item.Message},{ex.Message} - {ex.StackTrace}"); + } + } + } + catch (Exception) + { } + }); + } + + /// <summary> + /// 发送消息 + /// </summary> + /// <param name="robot_name">机器人账号</param> + /// <param name="robot_type">机器人类型</param> + /// <param name="tousername">发送给谁</param> + /// <param name="message">发送消息内容</param> + /// <param name="groupid">发送的群号</param> + public static void SendMessage(string robot_name, ChatType robot_type, string tousername, string message, string groupid = "") + { + var session = GetSession(); + var robot = session.FindRobots().FirstOrDefault(f => f.name == robot_name && f.type == robot_type); + if (robot != null) SendMessage(robot, tousername, message, groupid); + } + + /// <summary> + /// 缩短网址 - 根据配置的短网址类型 + /// </summary> + /// <param name="url">目标URL</param> + /// <returns></returns> + public static Task<string> ShortURL(string url) + { + return ShortURL(url, Setting.SystemConfig.dwz_type); + } + + /// <summary> + /// 缩短网址 - 自定义短网址类型 + /// </summary> + /// <param name="url">目标网址</param> + /// <param name="type">缩短类型</param> + /// <returns></returns> + public static Task<string> ShortURL(string url, DwzType type) + { + return Task.Factory.StartNew<string>(() => + { + var http = new HttpHelper(); + int num = 0; + var html = string.Empty; + Next: + try + { + num++; + + if (EventClient.ReplaceURL != null) + { + var temp = EventClient.ReplaceURL(0, url); + if (!string.IsNullOrEmpty(temp)) return temp; + } + + switch (type) + { + #region xxx + //case DwzType.新浪短网址: + //{ + // #region 老的新浪 xx + // //html = http.GetHtml("http://api.t.sina.com.cn/short_url/shorten.json?source=3271760578&url_long=" + HttpHelper.URLEncode(url)).Html; + // //if (!string.IsNullOrWhiteSpace(html) && html.ToLower().Contains("url_short")) + // //{ + // // var array = JsonConvert.DeserializeObject<ArrayList>(html); + // // if (array != null && array.Count > 0) + // // { + // // var dic = array[0] as Dictionary<string, object>; + // // return dic["url_short"].ToString().Replace("http://", "https://"); + // // } + // //} + // //break; + // #endregion + + // #region 新浪 + // var _url = $"https://service.weibo.com/share/share.php?url={HttpHelper.URLEncode(url)}&title=%e4%b8%ad%e9%97%b4%e9%a1%b5"; + // html = http.GetHtml(_url).Html; + // if (!string.IsNullOrWhiteSpace(html)) + // { + // var reg = Regex.Match(html, @"href=""(?<短连接>https?://t.cn/(?:[^""]+?))"""); + // if (reg.Success) + // { + // var shorturl = reg.Groups["短连接"].Value; + // return shorturl.Replace("http://", "https://"); + // } + // } + // break; + // #endregion + //} + //case DwzType.新新浪短网址: + //{ + // var _url = $"https://service.weibo.com/share/share.php?url={HttpHelper.URLEncode(url)}&title=%e4%b8%ad%e9%97%b4%e9%a1%b5"; + // html = http.GetHtml(_url).Html; + // if (!string.IsNullOrWhiteSpace(html)) + // { + // var reg = Regex.Match(html, @"href=""(?<短连接>https?://t.cn/(?:[^""]+?))"""); + // if (reg.Success) + // { + // var shorturl = reg.Groups["短连接"].Value; + // return shorturl.Replace("http://", "https://").Replace("t.cn/", "sinaurl.cn/"); + // } + // } + // break; + //} + //case DwzType.腾讯短网址: + //{ + // var data = CsharpHttpHelper.HttpHelper.URLEncode(url); + // html = http.GetHtml($"http://sa.sogou.com/gettiny?url={data}").Html; + // if (!string.IsNullOrWhiteSpace(html) && html.ToLower().Contains("url.cn")) + // return html; + // break; + //} + //case DwzType.百度短网址://收费 + //{ + //if (!string.IsNullOrWhiteSpace(Setting.SystemConfig.DwzToken)) + //{ + // try + // { + // var data = HttpHelper.ObjectToJson(new { Url = url, TermOfValidity = "1-year" }); + // var item = new HttpItem() + // { + // URL = "https://dwz.cn/admin/v2/create", + // Method = "post", + // Encoding = Encoding.UTF8, + // UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统 可选项有默认值 + // ContentType = "application/json;",//返回类型 可选项有默认值 + // PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte, + // PostdataByte = Encoding.UTF8.GetBytes(data),//HttpUtility.UrlEncode(data), + // Timeout = 5000, + // ReadWriteTimeout = 5000 + // }; + // item.Header.Add("token", Setting.SystemConfig.DwzToken); + // html = http.GetHtml(item).Html; + // if (!string.IsNullOrWhiteSpace(html)) + // { + // //{"Code":0,"ShortUrl":"https://dwz.cn/kiJerp0h","LongUrl":"https://www.hifige.com/collection-album/yuanzhua","ErrMsg":""} + // var json = HttpExtend.JsonToDictionary(html); + // if (json != null && json.ContainsKey("Code")) + // { + // var code = json["Code"].ToString(); + // if (code == "0" && json.ContainsKey("ShortUrl")) + // { + // var shortUrl = json["ShortUrl"].ToString(); + // return shortUrl; + // } + // EventClient.OnEvent(null, $"百度短连接获取失败:{html}"); + // } + // } + // } + // catch (Exception ex) + // { + // EventClient.OnEvent(null, "百度短连接生成失败:" + ex.Message); + // } + //} + //else + //{ + // EventClient.OnEvent(null, $"转链失败:百度短网址Token值为空【系统设置 => 6.百度短网址设置 中设置】"); + //} + //return url; + //break; + //} + //case DwzType.UC浏览器短网址: + //{ + // // var url = "http://www.qq.com"; + // byte[] sign_password = new byte[38]; + // sign_password[0] = 48; + // sign_password[1] = 0; + // sign_password[2] = 57; + // sign_password[3] = 0; + // sign_password[4] = 58; + // sign_password[5] = 0; + // sign_password[6] = 49; + // sign_password[7] = 0; + // sign_password[8] = 53; + // sign_password[9] = 0; + // sign_password[10] = 89; + // sign_password[11] = 0; + // sign_password[12] = 103; + // sign_password[13] = 0; + // sign_password[14] = 125; + // sign_password[15] = 0; + // sign_password[16] = 78; + // sign_password[17] = 0; + // sign_password[18] = 74; + // sign_password[19] = 0; + // sign_password[20] = 112; + // sign_password[21] = 0; + // sign_password[22] = 125; + // sign_password[23] = 0; + // sign_password[24] = 85; + // sign_password[25] = 0; + // sign_password[26] = 67; + // sign_password[27] = 0; + // sign_password[28] = 83; + // sign_password[29] = 0; + // sign_password[30] = 104; + // sign_password[31] = 0; + // sign_password[32] = 97; + // sign_password[33] = 0; + // sign_password[34] = 114; + // sign_password[35] = 0; + // sign_password[36] = 101; + // sign_password[37] = 0; + // var sign = HttpHelper.ToMD5(System.Text.Encoding.Unicode.GetString(sign_password) + url).ToUpper(); + // var item = http.GetItem("http://t.uc.cn/short_url/shorten", "", $"app_key=UCShare&url_long={HttpHelper.URLEncode(url)}&sign={sign}"); + // html = http.GetHtml(item).Html; + // var success_reg = System.Text.RegularExpressions.Regex.Match(html, @"""url_short"":""http://fxt.ucdesk.cn/(.*?)"""); + // if (success_reg.Success) return "http://t.uc.cn/" + success_reg.Groups[1].Value; + //} + //break; + #endregion + case DwzType.百度短网址://收费 + { + if (!string.IsNullOrWhiteSpace(Setting.SystemConfig.DwzToken)) + { + try + { + var data = HttpHelper.ObjectToJson(new { Url = url, TermOfValidity = "1-year" }); + var item = new HttpItem() + { + URL = "https://dwz.cn/admin/v2/create", + //URL = "https://dwz.cn/api/v3/short-urls", + Method = "post", + Encoding = Encoding.UTF8, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "application/json;",//返回类型 可选项有默认值 + PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte, + PostdataByte = Encoding.UTF8.GetBytes(data),//HttpUtility.UrlEncode(data), + Timeout = 5000, + ReadWriteTimeout = 5000 + }; + item.Header.Add("token", Setting.SystemConfig.DwzToken); + html = http.GetHtml(item).Html; + if (!string.IsNullOrWhiteSpace(html)) + { + //{"Code":0,"ShortUrl":"https://dwz.cn/kiJerp0h","LongUrl":"https://www.hifige.com/collection-album/yuanzhua","ErrMsg":""} + var json = HttpExtend.JsonToDictionary(html); + if (json != null && json.ContainsKey("Code")) + { + var code = json["Code"].ToString(); + if (code == "0" && json.ContainsKey("ShortUrl")) + { + var shortUrl = json["ShortUrl"].ToString(); + return shortUrl; + } + EventClient.OnEvent(null, $"百度短连接获取失败:{html}"); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(null, "百度短连接生成失败:" + ex.Message); + } + } + else + { + EventClient.OnEvent(null, $"转链失败:百度短网址Token值为空【系统设置 => 6.百度短网址设置 中设置】"); + } + return url; + break; + } + case DwzType.UC浏览器短网址: + case DwzType.新浪短网址: + case DwzType.新新浪短网址: + case DwzType.腾讯短网址: + //case DwzType.百度短网址: + case DwzType.官方短网址: + { + //for (int i = 0; i < 3; i++) + //{ + // var xx = HttpHelper.URLEncode(url); + // var sign = HttpHelper.ToMD5("23658" + url + "pMr7E2oPjvXI5ME1tZ0etTcenA7xgCzh"); + // var _url = $"https://url.api.52cmg.cn/generate?url={xx}&sign={sign}&appid=23658"; + // html = http.GetHtml(_url).Html; + // if (!string.IsNullOrWhiteSpace(html)) + // { + // if (html.Contains("ok")) + // { + // JObject json = JObject.Parse(html); + // if (!(bool)json["ok"]) return url; + // return json["url"].ToString(); + // } + // } + // Thread.Sleep(10); + // Console.WriteLine("html = " + html); + // Console.WriteLine("url = " + url); + //} + + HttpHelper helper = new HttpHelper(); + HttpItem item = new HttpItem();//https://url.api.52cmg.cn/generate?url=http://www.baidu.com&sign=E086A45084D1B490C411DEBD71E9DA4A&appid=23658 + + //var ccTLD = "https://url.api.52cmg.cn/generate"; + //if (!string.IsNullOrWhiteSpace(ccTLD)) + // ccTLD = ApiClient.Setting.SystemConfig.URLDwz; + + item.URL = "https://url.api.52cmg.cn/generate?url=" + System.Web.HttpUtility.UrlEncode(url) + $"&sign={GetSign(url, "23658")}&appid=23658"; + //item.URL = $"{ccTLD}?url={System.Web.HttpUtility.UrlEncode(url)}&sign={GetSign(url, "23658")}&appid=23658"; + for (int z = 0; z < 5; z++) + { + html = helper.GetHtml(item).Html; + if (html.Contains("\"ok\":true")) + { + Newtonsoft.Json.Linq.JObject j = Newtonsoft.Json.Linq.JObject.Parse(html); + var result = j["url"].ToString(); + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.URLDwz)) + { + var reg = Regex.Match(result, "id=([a-zA-Z0-9]+)"); + if (reg.Success) + { + if (ApiClient.Setting.SystemConfig.URLDwz.Contains("[序号]")) + { + result = ApiClient.Setting.SystemConfig.URLDwz.Replace("[序号]", reg.Groups[1].Value); + } + else if (ApiClient.Setting.SystemConfig.URLDwz.EndsWith("/")) + { + result = ApiClient.Setting.SystemConfig.URLDwz + "?id=" + reg.Groups[1].Value; + } + else + { + result = ApiClient.Setting.SystemConfig.URLDwz + "/?id=" + reg.Groups[1].Value; + } + + if (!result.StartsWith("http")) result = "http://" + result; + } + } + return result; + } + Thread.Sleep(10); + //Console.WriteLine("html = " + html); + //Console.WriteLine("url = " + url); + //Console.WriteLine("item.URL = " + item.URL); + } + return url; + } + break; + case DwzType.缩我短网址: + //{ + // for (int i = 0; i < 3; i++) + // { + // var data = CsharpHttpHelper.HttpHelper.URLEncode(url); + // var date = DateTime.Today.AddMonths(6).ToString("yyyy-MM-dd"); + // html = http.GetHtml($"http://suo.im/api.htm?url={data}&key=5dba8ad5b1a9c71e1cd3a570@731360bd06f09592d5843dd6bed51c2f&expireDate={date}").Html; + // if (!string.IsNullOrWhiteSpace(html) && !html.Contains("未能解析此远程名称") && html.ToLower().Contains("suo.im")) + // return html; + // Thread.Sleep(100); + // } + // break; + //} + case DwzType.快站短网址: + { + var urlTmp = KuaiZhanShort.GetShort(url); + if (urlTmp == url) + { + type = DwzType.官方短网址; + goto Next; + } + return urlTmp; + } + break; + case DwzType.不缩短域名: + return url; + } + } + catch (Exception ex) + { + EventClient.OnEvent(null, $"短连接异常:html => {html} - { ex.Message} - {ex.Source}"); + } + if (num <= 3) + { + if (type == DwzType.缩我短网址) type = DwzType.官方短网址; + else if (type == DwzType.腾讯短网址) type = DwzType.官方短网址; + //else if (type == DwzType.官方短网址) type = DwzType.官方短网址; + else if (type == DwzType.快站短网址) type = DwzType.官方短网址; + else type = DwzType.官方短网址; + goto Next; + } + return url; + }); + } + + #region 关芳端连街 + internal static string GetSign(string url, string appid) + { + var appSecret = "pMr7E2oPjvXI5ME1tZ0etTcenA7xgCzh"; + if (!string.IsNullOrEmpty(appSecret)) + { + string md5 = MD5Encrypt32(appid + url + appSecret); + return md5; + } + return ""; + } + + /// <summary> + /// 32位MD5加密 + /// </summary> + /// <param name="password"></param> + /// <returns></returns> + private static string MD5Encrypt32(string password) + { + string passwordFormat = FormsAuthPasswordFormat.MD5.ToString(); + return FormsAuthentication.HashPasswordForStoringInConfigFile(password, passwordFormat); + } + #endregion + + /// <summary> + /// 生成二维码图片 + /// </summary> + /// <param name="text">二维码内容</param> + /// <returns></returns> + private static Bitmap Generate3(string text) + { + MultiFormatWriter writer = new MultiFormatWriter(); + BitMatrix bm = writer.encode(text, BarcodeFormat.QR_CODE, 200, 200); + BarcodeWriter barcodeWriter = new BarcodeWriter(); + Bitmap map = barcodeWriter.Write(bm); + int[] rectangle = bm.getEnclosingRectangle(); + Bitmap bmpimg = new Bitmap(rectangle[2], rectangle[3], PixelFormat.Format32bppArgb); + using (Graphics g = Graphics.FromImage(bmpimg)) + { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + g.DrawImage(map, 0 - rectangle[0], 0 - rectangle[1]); + } + return bmpimg; + } + + /// <summary> + /// 合成海报模板 + /// </summary> + public enum QrImageType + { + 模板A = 0, + 模板B = 1, + 模板C = 2, + } + + /// <summary> + /// 合成二维码 + /// </summary> + /// <param name="title">标题</param> + /// <param name="price">价格</param> + /// <param name="cprice">券价格</param> + /// <param name="nprice">券后价格</param> + /// <param name="image">图片地址</param> + /// <param name="link">生成二维码的链接</param> + /// <param name="type">使用的模板</param> + /// <param name="cps">联盟类型,自动填写内容</param> + /// <param name="content">底栏内容</param> + /// <param name="basePath">保存路径</param> + /// <returns></returns> + public static string GetQRImage(string title, string price, string cprice, string nprice, string image, string link, QrImageType type = QrImageType.模板B, CpsType cps = CpsType.阿里妈妈, string content = "", string basePath = "") + { + if (string.IsNullOrWhiteSpace(content)) + { + switch (cps) + { + case CpsType.阿里妈妈: + { + if (type == QrImageType.模板A) + content = " 长按识别二维码 > 复制淘口令 > 打开手机淘宝 > 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按识别二维码 >> 复制淘口令 >> 打开手机淘宝 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + case CpsType.多多进宝: + { + if (type == QrImageType.模板A) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + case CpsType.京东联盟: + { + if (type == QrImageType.模板A) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + case CpsType.唯品联盟: + { + if (type == QrImageType.模板A) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + default: + { + if (type == QrImageType.模板A) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板B) + content = " 长按二维码 >> 识别图中二维码 >> 下单购买"; + else if (type == QrImageType.模板C) + content = ""; + } + break; + } + } + int number = 0; + Next: + Bitmap img = null; + Image mainpic = null; + try + { + string imagePath = string.Empty; + try + { + mainpic = null; + imagePath = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + if (!image.StartsWith("http")) image = "http:" + image; + mainpic = FileTools.DownloadImage(image, imagePath); + } + catch (Exception ex) + { + throw new Exception($"读取图片异常:图片路径 = {imagePath} .{ex.Message} - {ex.StackTrace}"); + } + if (mainpic == null) throw new Exception($"下载图片失败:图片url = {image}"); + + switch (type) + { + case QrImageType.模板A: + { + double rate = mainpic.Width / 800.00; + double height = mainpic.Height / rate; + img = new Bitmap(800, int.Parse((height + 424).ToString("0"))); + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.High; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.DrawImage(mainpic, 0, 0, 800, int.Parse((height).ToString("0"))); + graphics.DrawImage(Properties.Resources.foot, 0, int.Parse((height).ToString("0")), 800, 424); + graphics.DrawImage(Generate3(link), 510, int.Parse((height + 50).ToString("0")), 225, 220); + var font = new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular); + RectangleF rec = new RectangleF(20, int.Parse((height + 50).ToString("0")), 450, 150); + Brush brush = new SolidBrush(Color.FromArgb(53, 53, 53)); + graphics.DrawString(" " + title, font, brush, rec); + graphics.DrawString("¥", new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(148, 148, 148)), 90, int.Parse((height + 204).ToString("0"))); + graphics.DrawString(price, new Font("微软雅黑", 20, System.Drawing.FontStyle.Strikeout), new SolidBrush(Color.FromArgb(148, 148, 148)), 115, int.Parse((height + 204).ToString("0"))); + graphics.DrawString(nprice, new Font("微软雅黑", 28, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(243, 119, 7)), 265, int.Parse((height + 247).ToString("0"))); + graphics.DrawString(cprice.Split('.')[0] + "元", new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(243, 119, 7)), 65, int.Parse((height + 255).ToString("0"))); + RectangleF rec2 = new RectangleF(10, int.Parse((height + 337).ToString("0")), 780, 70); + Brush brush2 = new SolidBrush(Color.FromArgb(243, 119, 7)); + graphics.DrawString(content, font, brush2, rec2); + } + } + break; + case QrImageType.模板B: + { + var foot = Properties.Resources.模板B; + var width = (int)foot.Width; + var height = (int)foot.Height; + img = new Bitmap(width, height); + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.High; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.DrawImage(foot, 0, 0, width, height); + graphics.DrawImage(mainpic, 0, 0, width, (int)(height * 0.56)); + graphics.DrawImage(Generate3(link), 296, 1050, 165, 165); + RectangleF rec = new RectangleF(20, 760, 700, 150); + Brush brush = new SolidBrush(Color.FromArgb(53, 53, 53)); + graphics.DrawString(" " + title, new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular), brush, rec); + graphics.DrawString(nprice, new Font("微软雅黑", 25, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(178, 34, 34)), 45, 895); + graphics.DrawString(price, new Font("微软雅黑", 25, System.Drawing.FontStyle.Strikeout), new SolidBrush(Color.FromArgb(148, 148, 148)), 335, 895); + graphics.DrawString(cprice, new Font("微软雅黑", 28, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(70, 130, 180)), 595, 892); + RectangleF rec2 = new RectangleF(10, 1298, width - 40, 42); + Brush brush2 = new SolidBrush(Color.FromArgb(250, 250, 210)); + graphics.DrawString(content, new Font("微软雅黑", 16, System.Drawing.FontStyle.Bold), brush2, rec2); + } + } + break; + case QrImageType.模板C: + { + var foot = Properties.Resources.模板C; + var width = foot.Width; + var height = foot.Height; + img = new Bitmap(width, height); + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.High; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.DrawImage(foot, 0, 0, width, height);//填充背景图片 + + //添加标题 + RectangleF rec = new RectangleF(40, 17, 728, 110); + Brush brush = new SolidBrush(Color.FromArgb(53, 53, 53)); + graphics.DrawString(title, new Font("微软雅黑", 30, System.Drawing.FontStyle.Regular), brush, rec); + + graphics.DrawImage(mainpic, 45, 131, 413, 388);//填充商品图片 + graphics.DrawImage(Generate3(link), 557, 277, 152, 152); + //graphics.DrawImage(Image.FromFile(@"D:\A.png"), 557, 277, 152, 152); + + graphics.DrawString($"券后【{nprice}元】包邮秒杀", new Font("微软雅黑", 40, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(178, 34, 34)), 44, 565); + //graphics.DrawString(price, new Font("微软雅黑", 25, FontStyle.Strikeout), new SolidBrush(Color.FromArgb(148, 148, 148)), 335, 895); + graphics.DrawString($"减{cprice}元", new Font("微软雅黑", 28, System.Drawing.FontStyle.Regular), new SolidBrush(Color.FromArgb(70, 130, 180)), 600, 182); + RectangleF rec2 = new RectangleF(40, 667, 745, 122); + graphics.DrawString(content, new Font("微软雅黑", 18, System.Drawing.FontStyle.Bold), brush, rec2); + } + } + break; + } + + string path = string.Empty; + if (img != null) + { + if (!string.IsNullOrEmpty(basePath)) + path = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", basePath); + else path = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + img.Save(path, ImageFormat.Jpeg); + } + return path; + } + catch (Exception ex) + { + number++; + if (number <= 3) + { + Thread.Sleep(300); + goto Next; + } + EventClient.OnEvent(null, $"合成二维码图片:{ex.Message} - {ex.StackTrace}"); + return string.Empty; + } + finally + { + if (img != null) img.Dispose(); + if (mainpic != null) mainpic.Dispose(); + } + } + + /// <summary> + /// 将方形图片变成雏形 + /// </summary> + /// <param name="img">要转变的图片</param> + /// <param name="rec">大小和位置</param> + /// <param name="size">尺寸大小</param> + /// <returns></returns> + private static Image CutEllipse(Image img, Rectangle rec, Size size) + { + Bitmap bitmap = new Bitmap(size.Width, size.Height); + using (Graphics g = Graphics.FromImage(bitmap)) + { + using (TextureBrush br = new TextureBrush(img, System.Drawing.Drawing2D.WrapMode.Clamp, rec)) + { + br.ScaleTransform(bitmap.Width / (float)rec.Width, bitmap.Height / (float)rec.Height); + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; + g.FillEllipse(br, new Rectangle(Point.Empty, size)); + } + } + return bitmap; + } + + /// <summary> + /// 合成优惠券图(新版) + /// </summary> + /// <param name="image">优惠券底图</param> + /// <param name="shopname">店铺名称</param> + /// <param name="shopimage">店铺头像</param> + /// <param name="title">宝贝标题</param> + /// <param name="price">宝贝原价</param> + /// <param name="couponprice">优惠券金额</param> + /// <param name="itemimage">宝贝图片</param> + /// <param name="indate">优惠券有效期区间(2018.02.12 - 2018.03.12)</param> + /// <param name="sellcount">月销量</param> + /// <param name="basePath">图片保存路径</param> + /// <returns></returns> + public static string GetCouponImage2(string image, string shopname, Image shopimage, string title, string price, string couponprice, Image itemimage, string indate, string sellcount, string basePath = "") + { + int number = 0; + Image mainpic = null; + Image shoppic = null; + Next: + try + { + HttpHelper http = new HttpHelper(); + if (image.StartsWith("http")) + mainpic = http.GetImage(http.GetItem(image)); + else + mainpic = ReadImageFile(image); + //店铺头像 + shoppic = CutEllipse(shopimage, new Rectangle(0, 0, 150, 150), new Size(150, 150)); + + var width = (int)mainpic.Width; + var height = (int)mainpic.Height; + string path = string.Empty; + using (Bitmap img = new Bitmap(width, height)) + { + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + + graphics.DrawImage(mainpic, 0, 0, width, height);//将优惠券底图放置画板中 + graphics.DrawImage(shoppic, (width - 135) / 2, 154, 135, 135);//画板中绘画店铺头像 + + #region 店铺名 + var couponTitleFont = new Font("微软雅黑", 26, System.Drawing.FontStyle.Regular); + var wid = graphics.MeasureString(shopname, couponTitleFont); + RectangleF rec = new RectangleF((width - wid.Width) / 2, 294, wid.Width, wid.Height);//优惠券标题 + graphics.DrawString(shopname, couponTitleFont, new SolidBrush(Color.White), rec); + #endregion + + #region 绘画优惠券金额 + var couponFont = new Font("微软雅黑", 70, System.Drawing.FontStyle.Regular);//优惠券金额字体 + var couponpriceWid = graphics.MeasureString(couponprice, couponFont);//优惠券金额字体大小 + graphics.DrawString(couponprice, couponFont, new SolidBrush(Color.FromArgb(0xCD, 0x00, 0x00)), 210, 346);//画板中绘画优惠券金额 + #endregion + + #region 绘画优惠券有效期 + var couponIndateFont = new Font("微软雅黑", 19, System.Drawing.FontStyle.Regular);//优惠券有效期字体 + graphics.DrawString(indate, couponIndateFont, new SolidBrush(Color.FromArgb(0xc0, 0xc0, 0xc0)), 108, 511);//画板中绘画优惠券有效期 + #endregion + + #region 绘画宝贝图 + //店铺头像 + graphics.DrawImage(itemimage, 23, 607, 250, 268);//画板中绘画店铺头像 + + #endregion + + #region 绘画商品原价 + var priceFont = new Font("微软雅黑", 27, System.Drawing.FontStyle.Strikeout); + graphics.DrawString(price, priceFont, new SolidBrush(Color.Black), 385, 740); + #endregion + + #region 绘画商品最终价 + var finalPriceFont = new Font("微软雅黑", 45, System.Drawing.FontStyle.Regular); + wid = graphics.MeasureString(price, finalPriceFont); + graphics.DrawString((decimal.Parse(price) - decimal.Parse(couponprice)).ToString(), finalPriceFont, new SolidBrush(Color.Red), 438, 774); + #endregion + + #region 绘画商品标题 + var titleFont = new Font("微软雅黑", 18, System.Drawing.FontStyle.Regular); + int num = 18; + int rows = (int)Math.Floor(((decimal)title.Length / (decimal)num)); + for (int i = 1; i <= rows; i++) + { + var index = (num * i) + ((i - 1) * 2); + title = title.Insert(index, @" +"); + } + graphics.DrawString(title, titleFont, new SolidBrush(Color.Black), 298, 595); + #endregion + + #region 绘画月销量 + var sellcountFont = new Font("微软雅黑", 22, System.Drawing.FontStyle.Regular);//优惠券有效期字体 + graphics.DrawString(sellcount + "笔成交", sellcountFont, new SolidBrush(Color.FromArgb(0xc0, 0xc0, 0xc0)), 563, 692);//画板中绘画优惠券有效期 + #endregion + + } + path = !string.IsNullOrEmpty(basePath) ? Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", basePath) : Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + + img.Save(path, ImageFormat.Jpeg); + } + return path; + } + catch (Exception ex) + { + number++; + if (number <= 3) goto Next; + throw ex; + } + } + + + /// <summary> + /// 合成优惠券图 + /// </summary> + /// <param name="image">优惠券底图</param> + /// <param name="shopname">店铺名称</param> + /// <param name="shoppic">店铺头像</param> + /// <param name="couponprice">优惠券金额</param> + /// <param name="indate">优惠券有效期区间(2018.02.12 - 2018.03.12)</param> + /// <param name="basePath">图片保存路径</param> + /// <returns></returns> + public static string GetCouponImage(string image, string shopname, string shopimage, string couponprice, string indate, string basePath = "") + { + int number = 0; + Image mainpic = null; + Image shoppic = null; + Next: + try + { + HttpHelper http = new HttpHelper(); + if (image.StartsWith("http")) + mainpic = http.GetImage(http.GetItem(image)); + else + mainpic = ReadImageFile(image); + + shoppic = http.GetImage(http.GetItem(shopimage)); + var width = (int)mainpic.Width; + var height = (int)mainpic.Height; + string path = string.Empty; + using (Bitmap img = new Bitmap(width, height)) + { + using (Graphics graphics = Graphics.FromImage(img)) + { + graphics.Clear(Color.White); + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.InterpolationMode = InterpolationMode.High; + graphics.SmoothingMode = SmoothingMode.AntiAlias; + graphics.DrawImage(mainpic, 0, 0, width, height);//将优惠券底图放置画板中 + //graphics.DrawImage(Properties.Resources.foot, 0, int.Parse((height).ToString("0")), 800, 424); + //graphics.DrawImage(Generate3(link), 510, int.Parse((height + 50).ToString("0")), 225, 220); + + graphics.DrawImage(shoppic, 38, 417, 60, 60);//画板中绘画店铺头像 + + #region 绘画优惠券标题 + var _shopname = shopname + "优惠券"; + var couponTitleFont = new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular); + var wid = graphics.MeasureString(_shopname, couponTitleFont); + RectangleF rec = new RectangleF((width - wid.Width) / 2, (91 - wid.Height) / 2, wid.Width, wid.Height);//优惠券标题 + Brush brush = new SolidBrush(Color.FromArgb(53, 53, 53)); + graphics.DrawString(_shopname, couponTitleFont, brush, rec); + #endregion + + #region 绘画优惠券金额 + var couponFont = new Font("微软雅黑", 28, System.Drawing.FontStyle.Bold);//优惠券金额字体 + var couponpriceWid = graphics.MeasureString(couponprice, couponFont);//优惠券金额字体大小 + graphics.DrawString(couponprice, couponFont, new SolidBrush(Color.FromArgb(255, 99, 71)), (width - couponpriceWid.Width) / 2, 197);//画板中绘画优惠券金额 + #endregion + + #region 绘画优惠券有效期 + indate = "使用期限 " + indate; + var couponIndateFont = new Font("微软雅黑", 15, System.Drawing.FontStyle.Regular);//优惠券有效期字体 + var couponindateWid = graphics.MeasureString(indate, couponIndateFont);//优惠券有效期字体大小 + graphics.DrawString(indate, couponIndateFont, new SolidBrush(Color.FromArgb(169, 169, 169)), (width - couponindateWid.Width) / 2, 115);//画板中绘画优惠券有效期 + #endregion + + #region 绘画店铺名称 + var shopNameFont = new Font("微软雅黑", 20, System.Drawing.FontStyle.Regular); + wid = graphics.MeasureString(shopname, shopNameFont); + //RectangleF rec = new RectangleF((width - wid.Width) / 2, 50, 50, wid.Height);//优惠券标题 + graphics.DrawString(shopname, shopNameFont, new SolidBrush(Color.Black), 103, 402 + (90 - wid.Height) / 2); + #endregion + } + + if (!string.IsNullOrEmpty(basePath)) + path = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", basePath); + else path = Util.MapFile(DateTime.Now.Ticks.ToString() + ".jpg", "Cache\\image"); + img.Save(path, ImageFormat.Jpeg); + } + return path; + } + catch (Exception ex) + { + number++; + if (number <= 3) goto Next; + throw ex; + } + } + + /// <summary> + /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// </summary> + /// <param name="path">路径</param> + /// <returns></returns> + private static Bitmap ReadImageFile(string path) + { + FileStream fs = File.OpenRead(path); //OpenRead + int filelength = 0; + filelength = (int)fs.Length; //获得文件长度 + Byte[] image = new Byte[filelength]; //建立一个字节数组 + fs.Read(image, 0, filelength); //按字节流读取 + Image result = Image.FromStream(fs); + fs.Close(); + Bitmap bit = new Bitmap(result); + return bit; + } + + } +} diff --git a/类库/Api.Framework/Config/LoginUser.cs b/类库/Api.Framework/Config/LoginUser.cs new file mode 100644 index 0000000..b256bee --- /dev/null +++ b/类库/Api.Framework/Config/LoginUser.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Config +{ + public class LoginUser + { + public string Name { get; set; } + public string Pass { get; set; } + } +} diff --git a/类库/Api.Framework/Config/OthercONFIG.cs b/类库/Api.Framework/Config/OthercONFIG.cs new file mode 100644 index 0000000..b5b7d0c --- /dev/null +++ b/类库/Api.Framework/Config/OthercONFIG.cs @@ -0,0 +1,41 @@ +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Config +{ + /// <summary> + /// 系统其他配置 + /// </summary> + [Config(Name = "系统.其他设置")] + public class OtherConfig + { + + private List<string> _plugin; + /// <summary> + /// 插件顺序 + /// </summary> + public List<string> Plugins + { + get + { + _plugin = _plugin.Distinct().ToList(); + return _plugin; + } + set + { + _plugin = value; + } + } + + public OtherConfig() + { + this.Plugins = Util.Read<List<String>>("系统.插件配置"); + } + + } +} diff --git a/类库/Api.Framework/Config/ServerConfig.cs b/类库/Api.Framework/Config/ServerConfig.cs new file mode 100644 index 0000000..1d6e287 --- /dev/null +++ b/类库/Api.Framework/Config/ServerConfig.cs @@ -0,0 +1,69 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Config +{ + /// <summary> + /// 系统接口配置 + /// </summary> + [Config(Name = "系统.接口配置")] + public class ServerConfig + { + /// <summary> + /// 域名 + /// </summary> + public string Domain { get; set; } + + /// <summary> + /// 服务器IP + /// </summary> + public string Host { get; set; } + + /// <summary> + /// 端口号 + /// </summary> + public int Port { get; set; } + + /// <summary> + /// Web服务器是否开启 + /// </summary> + public bool IsOpen { get; set; } + + /// <summary> + /// Socket端口 + /// </summary> + [Browsable(false)] + public int SocketPort { get; set; } + + /// <summary> + /// 通信秘钥 + /// </summary> + [Browsable(false)] + public string SocketPassword { get; set; } + + /// <summary> + /// Socket服务器是否打开 + /// </summary> + [Browsable(false)] + public bool SocketIsOpen { get; set; } + + + public ServerConfig() + { + this.SocketPort = 443; + this.SocketPassword = "123456789123456789"; + this.SocketIsOpen = false; + + this.Domain = string.Empty; + this.IsOpen = false; + this.Host = "*"; + this.Port = 80; + } + } + +} diff --git a/类库/Api.Framework/Config/Setting.cs b/类库/Api.Framework/Config/Setting.cs new file mode 100644 index 0000000..486ffc1 --- /dev/null +++ b/类库/Api.Framework/Config/Setting.cs @@ -0,0 +1,115 @@ +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework.WXSdk.IPAD; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.Timers; +using Chat.Framework; +using Api.Framework.Enums; +using Newtonsoft.Json; + +namespace Api.Framework.Config +{ + /// <summary> + /// 配置 + /// </summary> + public class Setting + { + private ConnectionConfig _DbConfig; + /// <summary> + /// 数据库配置 + /// </summary> + public ConnectionConfig DbConfig + { + get + { + if (_DbConfig == null) + { + IniHelper ini = new IniHelper(Util.MapFile("系统配置.ini", "Config")); + _DbConfig = new ConnectionConfig(); + _DbConfig.ConnectionString = ini.GetValue("数据库", "链接"); + var text = ini.GetValue("数据库", "类型"); + if (!string.IsNullOrEmpty(text)) + _DbConfig.DatabaseType = Util.ConvertEnum<DatabaseType>(int.Parse(ini.GetValue("数据库", "类型"))); + } + _DbConfig.ConnectionString = _DbConfig.ConnectionString.Replace("Max Pool Size = 30", "Max Pool Size = 99999"); + return _DbConfig; + } + set + { + _DbConfig = value; + IniHelper ini = new IniHelper(Util.MapFile("系统配置.ini", "Config")); + ini.SetValue("数据库", "链接", value.ConnectionString); + ini.SetValue("数据库", "类型", ((int)_DbConfig.DatabaseType).ToString()); + } + } + + /// <summary> + /// 系统接口配置 + /// </summary> + public ServerConfig ServerConfig { get; set; } + + /// <summary> + /// 系统基础配置 + /// </summary> + public SystemConfig SystemConfig { get; set; } + + /// <summary> + /// 系统其他配置 + /// </summary> + public OtherConfig OtherConfig { get; set; } + + /// <summary> + /// 获取插件顺序 + /// </summary> + public List<string> Plugins + { + get + { + return OtherConfig.Plugins; + } + } + + public Setting() + { + //if (this.DbConfig.DatabaseType == DatabaseType.SQLITE) this.DbConfig.ConnectionString = string.Format("Data Source={0};Version=3;password={1};Journal Mode=WAL;", Util.MapFile("数据库.db", "Config"), ""); + if (this.DbConfig.DatabaseType == DatabaseType.SQLITE) + this.DbConfig.ConnectionString = string.Format("Data Source={0};PRAGMA journal_mode=WAL;Version=3;Pooling=True;Max Pool Size=99999;", Util.MapFile("数据库.db", "Config")); + } + + /// <summary> + /// 初始化配置 + /// </summary> + public void Iniconfig() + { + this.SystemConfig = Util.Read<SystemConfig>(); + this.OtherConfig = Util.Read<OtherConfig>(); + + + this.ServerConfig = Util.Read<ServerConfig>(); + } + + /// <summary> + /// 保存配置 + /// </summary> + public void Save() + { + Util.Save(this.OtherConfig); + Util.Save(this.ServerConfig); + Util.Save(this.SystemConfig); + + ChatClient.WXSdkConfig.MsgConvertToFriend = SystemConfig.msg_wx_convertswich == SwitchType.开启 ? true : false; + ChatClient.MessFrequentSleepTime = SystemConfig.mess_frequent_sleep_time; + + #region 重新加载更新订单定时器 + ApiClient.ResetTimer(); + #endregion + } + + } +} diff --git a/类库/Api.Framework/Config/SystemConfig.cs b/类库/Api.Framework/Config/SystemConfig.cs new file mode 100644 index 0000000..f6e2bdf --- /dev/null +++ b/类库/Api.Framework/Config/SystemConfig.cs @@ -0,0 +1,1195 @@ +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing.Design; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms.Design; +using UI.Framework.Entitys; + +namespace Api.Framework.Config +{ + /// <summary> + /// 系统基础设置 + /// </summary> + [Config(Name = "系统.基础配置")] + public class SystemConfig + { + #region 一.积分设置 + /// <summary> + /// 换算比例 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("01.换算比例"), DefaultValue(1), ReadOnly(true), + Description("一元人民币等于多少积分,例如:设置100,表示1元人民币等于100积分。") + ] + public int PointRitio { get; set; } + + /// <summary> + /// 积分名称 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("02.积分名称"), DefaultValue("元"), + Description("单位名称,一般取名为:元、金币、积分 等。") + ] + public string PointName { get; set; } + + /// <summary> + /// 提成类型 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("03.提成类型"), DefaultValue(AwardDepotType.不扣分出佣金), + Description("例如:100元商品,分出佣金为50元,扣除分出佣金->代理根据比例从50里抽取,剩余的金额归客户. 不扣除分出佣金->客户拿50元,代理在从50里面再次抽取自己的百分比.") + ] + public AwardDepotType AwardDepot { get; set; } + + /// <summary> + /// 一级提成 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("04.一级提成"), DefaultValue(20), + Description("A推荐B加机器人,B网购,A可以获得多少佣金!") + ] + public int AwardOne { get; set; } + + /// <summary> + /// 二级提成 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("05.二级提成"), DefaultValue(10), + Description("A推荐B加机器人,B又推荐C加机器人,C网购,A可以获得多少佣金!") + ] + public int AwardTwo { get; set; } + + /// <summary> + /// 三级提成 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("05.三级提成"), DefaultValue(10), + Description("A推荐B加机器人,B又推荐C加机器人,C再推荐D加机器人,D网购,A可以获得多少佣金!") + ] + public int AwardThree { get; set; } + + /// <summary> + /// 群主奖励 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("06.负责人提成"), DefaultValue(5), + Description("一般指做群的用户,会为群分配一个负责人,该群内所有产出佣金. 负责人都可以从“分出佣金”内,拿指定比例!") + ] + public int AwardCreator { get; set; } + + /// <summary> + /// 淘宝0元补助 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("07.用户所得佣金为0补助 - 淘宝"), DefaultValue(SwitchType.开启), + Description("商品计算用户所得佣金为0时,开启改功能将补助0.01给用户!") + ] + public SwitchType SubsidyTb { get; set; } + + /// <summary> + /// 拼多多0元补助 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("08.用户所得佣金为0补助 - 拼多多"), DefaultValue(SwitchType.开启), + Description("商品计算用户所得佣金为0时,开启改功能将补助0.01给用户!") + ] + public SwitchType SubsidyPdd { get; set; } + + /// <summary> + /// 京东0元补助 + /// </summary> + [ + Category("1)、积分设置"), DisplayName("09.用户所得佣金为0补助 - 京东"), DefaultValue(SwitchType.开启), + Description("商品计算用户所得佣金为0时,开启改功能将补助0.01给用户!") + ] + public SwitchType SubsidyJd { get; set; } + + #endregion + + #region 二.防封设置 + /// <summary> + /// 淘口令开始符号 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("01.淘口令前符号"), DefaultValue("《"), + Description("¥xxxxx¥,一般淘口令为这种格式,我们会把第一个¥替换,用竖线可以分割多个符号,随机选用!") + ] + public string TklStr_First { get; set; } + + /// <summary> + /// 淘口令末尾符号 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("02.淘口令后符号"), DefaultValue("《"), + Description("¥xxxxx¥,一般淘口令为这种格式,我们会把第二个¥替换,用竖线可以分割多个符号,随机选用!") + ] + public string TKLStr_End { get; set; } + + + private int _TGWRandomCount; + /// <summary> + /// 淘宝随机推广位切换频率 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("03.淘宝随机推广位切换频率"), DefaultValue(50), + Description("单位:次,推广位每使用N次以后切换下一个,防止推广位被举报.") + ] + public int TGWRandomCount + { + get { return _TGWRandomCount; } + set + { + if (value < 1) + { + _TGWRandomCount = 1; + //throw new Exception("定时时间应大于等于10"); + } + else + _TGWRandomCount = value; + } + } + + /// <summary> + /// 精准查询链接过期时间 - 分钟 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("04.精准查询链接有效期"), DefaultValue(30), + Description("单位:分钟,防止链接被举报.") + ] + public int QueryItemExpireTime { get; set; } + + /// <summary> + /// 自定义域名-淘口令 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("05.自定义域名-淘口令"), DefaultValue(""), + Description("不填写调用默认,由于微信封域名,这里是打开淘口令的中转页,便于复制淘口令!变量:[淘口令]、[图片]、[地址]、[图片地址]\r\n例如:http://xxxxx.xxx/item.html?taowords=[淘口令]&pic=[图片]&url=[地址]") + ] + public string URLTbTkl { get; set; } + + /// <summary> + /// 自定义域名中间页屏蔽通知 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("06.自定义域名中间页屏蔽通知"), DefaultValue(SwitchType.开启), + Description("自定义中间页域名被微信屏蔽通知开关") + ] + public SwitchType CheckUrlSwitch { get; set; } + + /// <summary> + /// 自定义域名-产品库 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("07.自定义域名-产品库"), DefaultValue(""), + Description("不填写调用默认,由于微信封域名,这里是查找商品的网站! 变量:[关键词]、[推广位]\r\n例如:http://xxxx.com/serch.html?key=[关键词]&pid=[推广位]") + ] + public string URLTbCms { get; set; } + + /// <summary> + /// 自定义域名-订单详情 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("08.自定义域名-订单详情"), DefaultValue(""), + Description("不填写调用默认,由于微信封域名,这里是订单详情页的网站! 变量:[key]\r\n例如:http://xxxx/aliorder.html?key=[key]") + ] + public string URLTbDdxq { get; set; } + + /// <summary> + /// 自定义域名-短网址 + /// </summary> + [ + Category("2)、防封设置"), DisplayName("09.自定义域名-短网址"), DefaultValue(""), + Description("请解析域名到 119.28.55.17 (免备案),然后填写网址,例如:http://www.baidu.com,也可以联系客服获取代码!自己放自己服务器,或块站") + ] + public string URLDwz { get; set; } + + #endregion + + /// <summary> + /// 官方中间页模式 + /// </summary> + [ + Category("3)、官方中间页模式设置"), DisplayName("01.官方中间页模式"), DefaultValue(ComposeType.有推荐商品), + Description("官方中间页模式选择") + ] + public ComposeType ZjyComposeType { get; set; } = ComposeType.有推荐商品; + + #region 四.邮件设置 + /// <summary> + /// 邮件服务器 + /// </summary> + [ + Category("4)、邮件设置"), DisplayName("01.服务器"), DefaultValue("smtp.qq.com"), + Description("常用邮件:腾讯(smtp.qq.com)、新浪(smtp.sina.com)、搜狐(smtp.sohu.com)....") + ] + public string SMTP_Host { get; set; } + + /// <summary> + /// 邮件端口号 + /// </summary> + [ + Category("4)、邮件设置"), DisplayName("02.端口号"), DefaultValue(587), + Description("常用端口:25(大部分采用)、由于25很多服务器封禁了该端口,可以尝试:465、587,仍无效请检查防火墙是否未允许使用此端口!") + ] + public int SMTP_Port { get; set; } + + /// <summary> + /// 邮件用户名 + /// </summary> + [ + Category("4)、邮件设置"), DisplayName("03.用户名"), DefaultValue(""), + Description("用于发信的邮箱名,例如:xxxx@qq.com") + ] + public string SMTP_User { get; set; } + + /// <summary> + /// 邮件授权密码 + /// </summary> + [ + Category("4)、邮件设置"), DisplayName("04.授权密码"), DefaultValue(""), + Description("登录密码或授权码,为了安全考虑很多邮箱已经采用了授权码!") + ] + public string SMTP_Pass { get; set; } + + /// <summary> + /// SSL加密传输 + /// </summary> + [ + Category("4)、邮件设置"), DisplayName("05.SSL加密传输"), DefaultValue(SwitchType.开启), + Description("加密传输防止泄露信息,部分邮件服务器必须强制SSL通信,建议开启!") + ] + public SwitchType SMTP_SSL { get; set; } + #endregion + + #region 五、系统设置 + + /// <summary> + /// 消息防止频繁休眠间隔 + /// </summary> + private int _mess_frequent_sleep_time { get; set; } + /// <summary> + /// 消息发送间隔 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("01.消息防止频繁休眠间隔"), DefaultValue(5), + Description("机器人消息队列10秒内推送10条消息的休眠时间. 例如:十秒内发送的消息量超过10条,休眠5(设置值)秒后继续发送未发送的信息.值为0时,该功能无效 单位:秒") + ] + public int mess_frequent_sleep_time + { + get { return _mess_frequent_sleep_time; } + set + { + if (value < 0) + _mess_frequent_sleep_time = 5; + else + _mess_frequent_sleep_time = value; + } + } + + /// <summary> + /// 订单冻结依据 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("02.订单冻结依据"), DefaultValue(FreezingConditionType.商品总佣金), + Description("例如:100元商品,总佣金为10元,客户所得是5元.商品总佣金->冻结时间将以10为条件进行计算冻结时间. 客户所得佣金->冻结时间将以5为条件进行计算冻结时间.") + ] + public FreezingConditionType FreezingCondition { get; set; } + + private int _timer_clear_memory { get; set; } + /// <summary> + /// 定时-清理内存 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("03.定时-清理内存"), DefaultValue(120), + Description("单位:秒、定时清理系统内存(非硬盘)无引用对象,通过Win32API,GC回收,大幅度降低占用内存!") + ] + public int timer_clear_memory + { + get { return _timer_clear_memory; } + set + { + if (value < 10) + { + _timer_clear_memory = 10; + //throw new Exception("定时时间应大于等于10"); + } + else + _timer_clear_memory = value; + } + } + + private int _timer_down_alimama { get; set; } + /// <summary> + /// 定时-下载淘宝订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("04.定时-下载淘宝订单"), DefaultValue(40), + Description("单位:秒、定时同步循环下载阿里妈妈订单,取值范围:10-1200") + ] + public int timer_down_alimama + { + get { return _timer_down_alimama; } + set + { + if (value < 10) + { + _timer_down_alimama = 10; + //throw new Exception("定时时间应在10-1200之间"); + } + else if (value > 1200) + _timer_down_alimama = 1200; + else + _timer_down_alimama = value; + } + } + + private int _time_down_pinduoduo { get; set; } + /// <summary> + /// 定时-下载拼多多订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("05.定时-下载拼多多订单"), DefaultValue(40), + Description("单位:秒、定时循环下载拼多多订单,取值范围:10-1200") + ] + public int time_down_pinduoduo + { + get { return _time_down_pinduoduo; } + set + { + if (value < 10) + { + _time_down_pinduoduo = 10; + //throw new Exception("定时时间应在10-1200之间"); + } + else if (value > 1200) + _time_down_pinduoduo = 1200; + else + _time_down_pinduoduo = value; + } + } + + private int _time_down_jingdong { get; set; } + /// <summary> + /// 定时-下载京东订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("06.定时-下载京东订单"), DefaultValue(600), + Description("单位:秒、定时循环下载京东订单,取值范围:60-1200") + ] + public int time_down_jingdong + { + get { return _time_down_jingdong; } + set + { + if (value < 30) + { + _time_down_jingdong = 30; + //throw new Exception("定时时间应在20-1200之间"); + } + else if (value > 1200) + _time_down_jingdong = 1200; + else + _time_down_jingdong = value; + //_time_down_jingdong = 600; + } + } + + private int _time_down_weipinhui { get; set; } + /// <summary> + /// 定时-下载唯品会订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("07.定时-下载唯品会订单"), DefaultValue(60), + Description("单位:秒、定时循环下载唯品会订单,取值范围:10-1200") + ] + public int time_down_weipinhui + { + get { return _time_down_weipinhui; } + set + { + if (value < 10) + { + _time_down_weipinhui = 10; + //throw new Exception("定时时间应在10-1200之间"); + } + else if (value > 1200) + _time_down_weipinhui = 1200; + else + _time_down_weipinhui = value; + } + } + + private int _time_down_douyin { get; set; } + /// <summary> + /// 定时-下载抖音订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("08.定时-下载抖音订单"), DefaultValue(60), + Description("单位:秒、定时循环下载抖音订单,取值范围:60-1200") + ] + public int time_down_douyin + { + get { return _time_down_douyin; } + set + { + if (value < 60) + { + _time_down_douyin = 60; + //throw new Exception("定时时间应在30-1200之间"); + } + else if (value > 1200) + _time_down_douyin = 1200; + else + _time_down_douyin = value; + } + } + + + private int _time_down_suning { get; set; } + /// <summary> + /// 定时-下载苏宁订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("08.定时-下载苏宁订单"), DefaultValue(60), + Description("单位:秒、定时循环下载苏宁订单,取值范围:60-1200") + ] + public int time_down_suning + { + get { return _time_down_suning; } + set + { + if (value < 60) + { + _time_down_suning = 60; + //throw new Exception("定时时间应在30-1200之间"); + } + else if (value > 1200) + _time_down_suning = 1200; + else + _time_down_suning = value; + } + } + + private int _time_down_kuaishou { get; set; } + /// <summary> + /// 定时-下载快手订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("09.定时-下载快手订单"), DefaultValue(300), + Description("单位:秒、定时循环下载快手订单,取值范围:60-1200") + ] + public int time_down_kuaishou + { + get { return _time_down_kuaishou; } + set + { + if (value < 60) + { + _time_down_kuaishou = 60; + //throw new Exception("定时时间应在30-1200之间"); + } + else if (value > 1200) + _time_down_kuaishou = 1200; + else + _time_down_kuaishou = value; + //_time_down_jingdong = 300; + } + } + + + /// <summary> + /// 管理员邮箱 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("10.管理员邮箱"), DefaultValue(""), + Description("系统有紧急事件,会通知管理员!") + ] + public string account_admin_email { get; set; } + + /// <summary> + /// 自定义短网址 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("11.自定义短网址"), DefaultValue(DwzType.快站短网址), + Description("如果网址过长,会被自动缩短!") + ] + public DwzType dwz_type { get; set; } + + /// <summary> + /// 自定义短网址(百度付费Token) + /// </summary> + [ + Category("5)、系统设置"), DisplayName("12.自定义短网址(百度付费Token)"), PasswordPropertyText(true), DefaultValue(""), + Description("百度短网址是付费接口,需要用户自行充值,百度短网址官网:https://dwz.cn ,把Token填写到此处!") + ] + public string DwzToken { get; set; } + + /// <summary> + /// 系统异常提示语 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("13.系统异常提示语"), DefaultValue("对不起查询失败,当前是使用高峰期,请稍后重试! 给您造成不便敬请谅解!"), + Description("应用在处理过程中,如果出现错误,将对客户提示展示这段话!") + ] + public string msg_error { get; set; } + + /// <summary> + /// 微信辅助客户输入 + /// </summary> + /// <summary> + /// 短网址 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("14.微信辅助客户输入"), DefaultValue(SwitchType.开启), + Description("来源替换,例如:自己用手机给客户发消息,机器人会自动转换为客户发过来的消息,方便替客户查余额、辅助客户使用!") + ] + public SwitchType msg_wx_convertswich { get; set; } + + /// <summary> + /// 淘宝订单自动绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("15.淘宝订单自动绑定"), DefaultValue(SwitchType.开启), + Description("系统会根据最近客户和您的聊天记录自动判断,如果多人查询同一个宝贝将不会绑定!") + ] + public SwitchType order_alimama_bind { get; set; } + + /// <summary> + /// 淘宝订单下载依据 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("16.淘宝订单下载依据"), DefaultValue(DownAdzoneType.不下载推广位), + Description(@"系统淘宝订单下载依据! +不下载推广位:以17设置项为准,将不下载设置的推广位对应的订单! +只下载推广位:以17设置项为准,将只下载设置的推广位对应的订单! + +注:17设置项为空时,将下载全部") + ] + public DownAdzoneType order_alimama_down_type { get; set; } + + /// <summary> + /// 淘宝订单[不]下载推广位 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("17.淘宝订单[不]下载推广位"), DefaultValue(""), + Description(@"此处设置的推广位,受制于16设置项的设置. +16设置项的设置,将决定[不]下载对应的订单,用英文逗号"",""分隔!") + ] + public string order_alimama_not_download_pid { get; set; } + + /// <summary> + /// 只下载使用中推广位淘宝订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("18.只下载使用中推广位淘宝订单"), DefaultValue(SwitchType.关闭), + Description("开启状态,系统将通过插件中设置的推广位进行订单下载,联盟其他推广位订单将不下载,5-16设置项将无效") + ] + public SwitchType order_alimama_download_set_pids { get; set; } = SwitchType.关闭; + + /// <summary> + /// 淘宝订单尾号自动采集 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("19.淘宝订单尾号自动采集"), DefaultValue(SwitchType.关闭), + Description("订单自动绑定与尾号自动采集同时开启后,才会自动采集用户的订单尾号") + ] + public SwitchType order_alimama_last_auto_capture { get; set; } + + /// <summary> + /// 淘宝订单尾号识别绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("20.淘宝订单尾号识别绑定"), DefaultValue(SwitchType.关闭), + Description("") + ] + public SwitchType order_alimama_last_auto_bind { get; set; } + + /// <summary> + /// 淘宝同店订单绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("21.淘宝同店订单绑定"), DefaultValue(SwitchType.关闭), + Description("") + ] + public SwitchType order_alimama_same_shop_bind { get; set; } = SwitchType.关闭; + + /// <summary> + /// 拼多多订单自动绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("22.拼多多订单自动绑定"), DefaultValue(SwitchType.开启), + Description("精准绑定、内置黑科技参数,可以完美实现精准客户识别!") + ] + public SwitchType order_pinduoduo_bind { get; set; } + + /// <summary> + /// 拼多多订单下载依据 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("23.拼多多订单下载依据"), DefaultValue(DownAdzoneType.不下载推广位), + Description(@"系统拼多多订单下载依据! +不下载推广位:以24设置项为准,将不下载设置的推广位对应的订单! +只下载推广位:以24设置项为准,将只下载设置的推广位对应的订单! + +注:23设置项为空时,将下载全部") + ] + public DownAdzoneType order_pinduoduo_down_type { get; set; } + + /// <summary> + /// 拼多多订单[不]下载推广位 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("24.拼多多订单[不]下载推广位"), DefaultValue(""), + Description(@"此处设置的推广位,受制于23设置项的设置. +23设置项的设置, 将决定[不]下载对应的订单, 用英文逗号"", ""分隔!") + ] + public string order_pinduoduo_not_download_pid { get; set; } + + /// <summary> + /// 只下载使用中推广位拼多多订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("25.只下载使用中推广位拼多多订单"), DefaultValue(SwitchType.关闭), + Description("开启状态,系统将通过插件中设置的推广位进行订单下载,联盟其他推广位订单将不下载,5-23设置项将无效") +] + public SwitchType order_pinduoduo_download_set_pids { get; set; } = SwitchType.关闭; + + /// <summary> + /// 京东订单自动绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("26.京东订单自动绑定"), DefaultValue(SwitchType.开启), + Description("精准绑定、内置黑科技参数,可以完美实现精准客户识别!") + ] + public SwitchType order_jingdong_bind { get; set; } + + /// <summary> + /// 京东订单下载依据 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("27.京东订单下载依据"), DefaultValue(DownAdzoneType.不下载推广位), + Description(@"系统京东订单下载依据! +不下载推广位:以28设置项为准,将不下载设置的推广位对应的订单! +只下载推广位:以28设置项为准,将只下载设置的推广位对应的订单! + +注:27设置项为空时,将下载全部") + ] + public DownAdzoneType order_jingdong_down_type { get; set; } + + /// <summary> + /// 京东订单[不]下载推广位 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("28.京东订单[不]下载推广位"), DefaultValue(""), + Description(@"此处设置的推广位,受制于27设置项的设置. +27设置项的设置, 将决定[不]下载对应的订单, 用英文逗号"", ""分隔!") + ] + public string order_jingdong_not_download_pid { get; set; } + + /// <summary> + /// 只下载使用中推广位京东订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("29.只下载使用中推广位京东订单"), DefaultValue(SwitchType.关闭), + Description("开启状态,系统将通过插件中设置的推广位进行订单下载,联盟其他推广位订单将不下载,5-27设置项将无效") +] + public SwitchType order_jingdong_download_set_pids { get; set; } = SwitchType.关闭; + + /// <summary> + /// 唯品会订单自动绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("30.唯品会订单自动绑定"), DefaultValue(SwitchType.开启), + Description("精准绑定、内置黑科技参数,可以完美实现精准客户识别!") + ] + public SwitchType order_weipinhui_bind { get; set; } + + /// <summary> + /// 唯品会订单下载依据 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("31.唯品会订单下载依据"), DefaultValue(DownAdzoneType.不下载推广位), + Description(@"系统唯品会订单下载依据! +不下载推广位:以32设置项为准,将不下载设置的推广位对应的订单! +只下载推广位:以32设置项为准,将只下载设置的推广位对应的订单! + +注:31设置项为空时,将下载全部") + ] + public DownAdzoneType order_weipinhui_down_type { get; set; } + + /// <summary> + /// 唯品会订单[不]下载推广位 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("32.唯品会订单[不]下载推广位"), DefaultValue(""), + Description(@"此处设置的推广位,受制于31设置项的设置. +31设置项的设置, 将决定[不]下载对应的订单, 用英文逗号"", ""分隔!") + ] + public string order_weipinhui_not_download_pid { get; set; } + + /// <summary> + /// 只下载使用中推广位唯品会订单 + /// </summary> + [ +Category("5)、系统设置"), DisplayName("33.只下载使用中推广位唯品会订单"), DefaultValue(SwitchType.关闭), +Description("开启状态,系统将通过插件中设置的推广位进行订单下载,联盟其他推广位订单将不下载,5-31设置项将无效") +] + public SwitchType order_weipinhui_download_set_pids { get; set; } = SwitchType.关闭; + + /// <summary> + /// 抖音订单自动绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("34.抖音订单自动绑定"), DefaultValue(SwitchType.开启), + Description("系统会根据最近客户和您的聊天记录自动判断,如果多人查询同一个宝贝将不会绑定!") + ] + public SwitchType order_douyin_bind { get; set; } = SwitchType.开启; + + // /// <summary> + // /// 抖音订单下载依据 + // /// </summary> + // [ + // Category("5)、系统设置"), DisplayName("34.抖音订单下载依据"), DefaultValue(DownAdzoneType.不下载推广位), + // Description(@"系统抖音订单下载依据! + //不下载推广位:以35设置项为准,将不下载设置的推广位对应的订单! + //只下载推广位:以35设置项为准,将只下载设置的推广位对应的订单! + + //注:35设置项为空时,将下载全部") + // ] + // public DownAdzoneType order_douyin_down_type { get; set; } = DownAdzoneType.不下载推广位; + + // /// <summary> + // /// 抖音订单[不]下载推广位 + // /// </summary> + // [ + // Category("5)、系统设置"), DisplayName("35.抖音订单[不]下载推广位"), DefaultValue(""), + // Description(@"此处设置的推广位,受制于34设置项的设置. + //34设置项的设置, 将决定[不]下载对应的订单, 用英文逗号"", ""分隔!") + // ] + // public string order_douyin_not_download_pid { get; set; } = string.Empty; + + // /// <summary> + // /// 只下载使用中推广位抖音订单 + // /// </summary> + // [ + //Category("5)、系统设置"), DisplayName("36.只下载使用中推广位抖音订单"), DefaultValue(SwitchType.关闭), + //Description("开启状态,系统将通过插件中设置的推广位进行订单下载,联盟其他推广位订单将不下载,5-34设置项将无效") + //] + // public SwitchType order_douyin_download_set_pids { get; set; } = SwitchType.关闭; + + //----------------------- + + /// <summary> + /// 苏宁订单自动绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("37.苏宁订单自动绑定"), DefaultValue(SwitchType.开启), + Description("精准绑定、内置黑科技参数,可以完美实现精准客户识别!") + ] + public SwitchType order_suning_bind { get; set; } = SwitchType.开启; + + /// <summary> + /// 苏宁订单下载依据 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("38.苏宁订单下载依据"), DefaultValue(DownAdzoneType.不下载推广位), + Description(@"系统苏宁订单下载依据! +不下载推广位:以39设置项为准,将不下载设置的推广位对应的订单! +只下载推广位:以39设置项为准,将只下载设置的推广位对应的订单! + +注:39设置项为空时,将下载全部") + ] + public DownAdzoneType order_suning_down_type { get; set; } = DownAdzoneType.不下载推广位; + + /// <summary> + /// 苏宁订单[不]下载推广位 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("39.苏宁订单[不]下载推广位"), DefaultValue(""), + Description(@"此处设置的推广位,受制于38设置项的设置. +38设置项的设置, 将决定[不]下载对应的订单, 用英文逗号"", ""分隔!") + ] + public string order_suning_not_download_pid { get; set; } = string.Empty; + + /// <summary> + /// 只下载使用中推广位苏宁订单 + /// </summary> + [ +Category("5)、系统设置"), DisplayName("40.只下载使用中推广位苏宁订单"), DefaultValue(SwitchType.关闭), +Description("开启状态,系统将通过插件中设置的推广位进行订单下载,联盟其他推广位订单将不下载,5-38设置项将无效") +] + public SwitchType order_suning_download_set_pids { get; set; } = SwitchType.关闭; + + + + + + + /// <summary> + /// 快手订单自动绑定 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("41.快手订单自动绑定"), DefaultValue(SwitchType.开启), + Description("精准绑定、内置黑科技参数,可以完美实现精准客户识别!") + ] + public SwitchType order_kuaishou_bind { get; set; } = SwitchType.开启; + + /// <summary> + /// 快手订单下载依据 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("42.快手订单下载依据"), DefaultValue(DownAdzoneType.不下载推广位), + Description(@"系统快手订单下载依据! +不下载推广位:以43设置项为准,将不下载设置的推广位对应的订单! +只下载推广位:以43设置项为准,将只下载设置的推广位对应的订单! + +注:43设置项为空时,将下载全部") + ] + public DownAdzoneType order_kuaishou_down_type { get; set; } = DownAdzoneType.不下载推广位; + + /// <summary> + /// 快手订单[不]下载推广位 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("43.快手订单[不]下载推广位"), DefaultValue(""), + Description(@"此处设置的推广位,受制于42设置项的设置. +42设置项的设置, 将决定[不]下载对应的订单, 用英文逗号"", ""分隔!") + ] + public string order_kuaishou_not_download_pid { get; set; } = string.Empty; + + /// <summary> + /// 只下载使用中推广位快手订单 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("44.只下载使用中推广位快手订单"), DefaultValue(SwitchType.关闭), + Description("开启状态,系统将通过插件中设置的推广位进行订单下载,联盟其他推广位订单将不下载,5-42设置项将无效") + ] + public SwitchType order_kuaishou_download_set_pids { get; set; } = SwitchType.关闭; + + + + private string _notice_dingding_robotapi; + /// <summary> + /// 钉钉群接口 + /// </summary> + [ + Browsable(false) + ] + public string notice_dingding_robotapi + { + //get;set; + get + { + if (string.IsNullOrWhiteSpace(_notice_dingding_robotapi)) + { + if (notice_robotname != "请选择(钉钉/微信群机器人API名称)") + { + var session = ApiClient.GetSession(); + var item = session.FindSingle<fl_noticeapi_info>("select * from fl_noticeapi_info where name = @name", new { name = notice_robotname }); + if (item != null) + { + notice_dingding_robotSecret = item.token; + _notice_dingding_robotapi = item.api_location; + } + } + else + { + notice_dingding_robotSecret = string.Empty; + _notice_dingding_robotapi = string.Empty; + } + } + return _notice_dingding_robotapi; + } + } + + /// <summary> + /// 钉钉群秘钥 + /// </summary> + [ + Browsable(false) + ] + public string notice_dingding_robotSecret { get; set; } + + private string _notice_robotname; + + /// <summary> + /// 钉钉/微信群机器人 + /// </summary> + [Category("5)、系统设置"), DisplayName("45.钉钉/微信群机器人"), DefaultValue("请选择(钉钉/微信群机器人API名称)"), Description("请选择已存在的机器人名称,如果还没有添加,在【系统管理->群通知机器人】中添加机器人!"), TypeConverter(typeof(notice_robotname_item))] + public string notice_robotname + { + get { return _notice_robotname; } + set + { + if (_notice_robotname != value) + { + _notice_dingding_robotapi = string.Empty; + notice_dingding_robotSecret = string.Empty; + } + _notice_robotname = value; + } + } + + public class notice_robotname_item : MyTypeConverter + { + public override string[] GetValues() + { + var session = ApiClient.GetSession(); + var apis = session.FindNoticeapiRobots().ToArray(); + var rst = new List<string>(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + return rst.ToArray(); + } + } + + /// <summary> + /// 联盟API通信平台 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("46.联盟API通信平台"), ReadOnly(false),//Description("不懂请勿乱修改!不懂请勿乱修改!默认即可!"), + ] + public string cps_server_api { get; set; } + + /// <summary> + /// 允许手动绑定的订单时间 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("47.允许手动绑定的订单时间"), //DefaultValue(), + Description("手动发送订单号,该订单的创建时间小于设置的时间将无法绑定") + ] + public DateTime allow_bind_create_order_time { get; set; } + + /// <summary> + /// 锁定界面开关 + /// </summary> + [ + Category("5)、系统设置"), DisplayName("48.锁定界面开关"), DefaultValue(SwitchType.关闭), + Description("锁定界面开启,5分钟不操作软件自动锁定") + ] + public SwitchType is_lock_main { get; set; } + #endregion + + #region 六、微信商户付款 + /// <summary> + /// 易提现 - API接口 + /// </summary> + [ + Category("6)、微信商户付款 - 【新接口】"), DisplayName("01.易提现 - API接口"), PasswordPropertyText(true),// DefaultValue(""), + Description("请用谷歌浏览器(Chrome)、在网站:Pay.52cmg.cn 中添加商户(或用系统默认商户)、获取API接口!") + ] + public string pay_wechat_hostSign { get; set; } + + /// <summary> + /// 支付平台地址 + /// </summary> + [ + Category("6)、微信商户付款【已过时、不建议使用】"), DisplayName("01.支付平台地址"), DefaultValue(""), + Description("自定义独立支付系统,需要付费搭建!") + ] + public string pay_wechat_host { get; set; } + + /// <summary> + /// 公众号AppId + /// </summary> + [ + Category("6)、微信商户付款【已过时、不建议使用】"), DisplayName("02.公众号AppId"), DefaultValue(""), + Description("要求:1、服务号 2、已认证 3、开通了支付功能\r\n登录网址:mp.weixin.qq.com") + ] + public string pay_wechat_gzh_appid { get; set; } + + /// <summary> + /// 公众号AppSecret + /// </summary> + [ + Category("6)、微信商户付款【已过时、不建议使用】"), DisplayName("03.公众号AppSecret"), DefaultValue(""), PasswordPropertyText(true), + Description("要求:1、服务号 2、已认证 3、开通了支付功能\r\n登录网址:mp.weixin.qq.com") + ] + public string pay_wechat_gzh_appsecret { get; set; } + + /// <summary> + /// 商户号AppId + /// </summary> + [ + Category("6)、微信商户付款【已过时、不建议使用】"), DisplayName("04.商户号AppId"), DefaultValue(""), + Description("要求:登录微信商户平台->产品中心->开通企业付款到零钱\r\n登录网址:pay.weixin.qq.com") + ] + public string pay_wechat_sh_appid { get; set; } + + /// <summary> + /// 商户号AppSecret + /// </summary> + [ + Category("6)、微信商户付款【已过时、不建议使用】"), DisplayName("05.商户号AppSecret"), DefaultValue(""), PasswordPropertyText(true), + Description("要求:登录微信商户平台->产品中心->开通企业付款到零钱\r\n登录网址:pay.weixin.qq.com") + ] + public string pay_wechat_sh_appsecret { get; set; } + + /// <summary> + /// 商户号证书路径 + /// </summary> + [ + Category("6)、微信商户付款【已过时、不建议使用】"), DisplayName("06.商户号证书路径"), DefaultValue(""), + Description("通过商户平台,再本机安装证书,安装完成后,请填写路径!\r\n例如:C:\\Windows\\WechatCerpath\\apiclient_cert.p12") + ] + public string pay_wechat_sh_cerpath { get; set; } + + /// <summary> + /// 著作授权信息 + /// </summary> + [ + Category("6)、微信商户付款【已过时、不建议使用】"), DisplayName("07.著作授权信息"), DefaultValue("©Copyright 2019-2020 FLSystem"), + Description("网站底部的著作授权信息,例如:©Copyright 2019-2020 FLSystem") + ] + public string pay_wechat_web_footer { get; set; } + + #endregion + + /// <summary> + /// 消息预警方案 + /// </summary> + [Browsable(false)] + public bool message_warning_switch { get; set; } + + /// <summary> + /// 需要输入密码的应用 + /// </summary> + [Browsable(false)] + public List<string> admin_verify_control_name { get; set; } + + /// <summary> + /// 显示debug日志 + /// </summary> + [Browsable(false)] + public bool show_debug_log { get; set; } + + /// <summary> + /// 商户未领取提示语 + /// </summary> + [Browsable(false)] + public string send_shpay_msg { get; set; } = @"一一一一未 领 取 红 包一一一一 + +[领取地址] + +点击链接,领取[兑换金额]元到微信钱包!"; + + /// <summary> + /// 24小时发送未领取商户开关 + /// </summary> + [Browsable(false)] + public bool send_shpay_switch { get; set; } = false; + + /// <summary> + /// 商户未领取提示语是否以小程序的形式发送 + /// </summary> + [Browsable(false)] + public bool send_shpay_minixml { get; set; } = false; + + /// <summary> + /// 系统配置 + /// </summary> + public SystemConfig() + { + this.allow_bind_create_order_time = DateTime.MinValue; + this.message_warning_switch = false; + + this.pay_wechat_hostSign = string.Empty; + this._mess_frequent_sleep_time = 5; + this.show_debug_log = true; + this.pay_wechat_host = string.Empty; + this.admin_verify_control_name = new List<string>() { "应用功能", "系统设置" }; + + this.pay_wechat_web_footer = "©Copyright 2019-2020 FLSystem"; + this.pay_wechat_gzh_appid = string.Empty; + this.pay_wechat_gzh_appsecret = string.Empty; + this.pay_wechat_sh_appid = string.Empty; + this.pay_wechat_sh_appsecret = string.Empty; + this.pay_wechat_sh_cerpath = string.Empty; + + this.cps_server_api = "http://cps.api.52cmg.cn/"; + //this.notice_dingding_robotapi = string.Empty; + //this.notice_dingding_robotSecret = string.Empty; + this.notice_robotname = "请选择(钉钉/微信群机器人API名称)"; + this.order_alimama_bind = SwitchType.开启; + this.order_pinduoduo_bind = SwitchType.开启; + this.order_suning_bind = SwitchType.开启; + this.order_jingdong_bind = SwitchType.开启; + this.order_weipinhui_bind = SwitchType.开启; + this.order_douyin_bind = SwitchType.开启; + this.order_alimama_last_auto_bind = SwitchType.关闭; + this.order_alimama_last_auto_capture = SwitchType.关闭; + + this.is_lock_main = SwitchType.关闭; + + this.FreezingCondition = FreezingConditionType.商品总佣金; + + msg_error = "对不起查询失败,当前是使用高峰期,请稍后重试! 给您造成不便敬请谅解!"; + URLTbTkl = string.Empty; + URLTbCms = string.Empty; + URLTbDdxq = string.Empty; + dwz_type = DwzType.快站短网址; + account_admin_email = string.Empty; + msg_wx_convertswich = SwitchType.开启; + _timer_clear_memory = 120; + _timer_down_alimama = 40; + _time_down_pinduoduo = 40; + _time_down_jingdong = 600; + _time_down_weipinhui = 60; + _time_down_douyin = 60; + _time_down_suning = 60; + _time_down_kuaishou = 300; + + SMTP_SSL = SwitchType.开启; + SMTP_Pass = string.Empty; + SMTP_Host = "smtp.qq.com"; + SMTP_Port = 587; + SMTP_User = string.Empty; + + PointRitio = 1; + PointName = "元"; + AwardDepot = AwardDepotType.不扣分出佣金; + AwardOne = 0; + AwardTwo = 0; + AwardThree = 0; + AwardCreator = 0; + TklStr_First = "《"; + TKLStr_End = "《"; + QueryItemExpireTime = 30; + _TGWRandomCount = 50; + + order_alimama_down_type = DownAdzoneType.不下载推广位; + order_alimama_not_download_pid = string.Empty; + + order_pinduoduo_down_type = DownAdzoneType.不下载推广位; + order_pinduoduo_not_download_pid = string.Empty; + + order_jingdong_down_type = DownAdzoneType.不下载推广位; + order_jingdong_not_download_pid = string.Empty; + + order_weipinhui_down_type = DownAdzoneType.不下载推广位; + order_weipinhui_not_download_pid = string.Empty; + + + order_kuaishou_bind = SwitchType.开启; + order_kuaishou_down_type = DownAdzoneType.不下载推广位; + order_kuaishou_not_download_pid = string.Empty; + order_kuaishou_download_set_pids = SwitchType.关闭; + + + DwzToken = string.Empty; + CheckUrlSwitch = SwitchType.开启; + + SubsidyTb = SwitchType.开启; + SubsidyPdd = SwitchType.开启; + SubsidyJd = SwitchType.开启; + } + + } +} diff --git a/类库/Api.Framework/Config/log4net.config b/类库/Api.Framework/Config/log4net.config new file mode 100644 index 0000000..c1ebe95 --- /dev/null +++ b/类库/Api.Framework/Config/log4net.config @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8" ?> +<log4net> + <appender name="errorAppender" type="log4net.Appender.RollingFileAppender"> + <filter type="log4net.Filter.LevelMatchFilter"> + <levelToMatch value="ERROR" /> + </filter> + <filter type="log4net.Filter.DenyAllFilter" /> + <file value="Logs\err.log" /> + <encoding value="utf-8"/> + <preserveLogFileNameExtension value="true" /> + <appendToFile value="true" /> + <rollingStyle value="Date" /> + <datePattern value="yyyyMMdd" /> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> + </layout> + </appender> + <appender name="infoAppender" type="log4net.Appender.RollingFileAppender"> + <filter type="log4net.Filter.LevelMatchFilter"> + <levelToMatch value="INFO" /> + </filter> + <filter type="log4net.Filter.DenyAllFilter" /> + <file value="Logs\info.log" /> + <encoding value="utf-8"/> + <preserveLogFileNameExtension value="true" /> + <appendToFile value="true" /> + <rollingStyle value="Date" /> + <datePattern value="yyyyMMdd" /> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> + </layout> + </appender> + <appender name="debugAppender" type="log4net.Appender.RollingFileAppender"> + <filter type="log4net.Filter.LevelMatchFilter"> + <levelToMatch value="DEBUG" /> + </filter> + <filter type="log4net.Filter.DenyAllFilter" /> + <file value="Logs\debug.log" /> + <encoding value="utf-8"/> + <preserveLogFileNameExtension value="true" /> + <appendToFile value="true" /> + <rollingStyle value="Date" /> + <datePattern value="yyyyMMdd" /> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> + </layout> + </appender> + <appender name="perfAppender" type="log4net.Appender.RollingFileAppender"> + <filter type="log4net.Filter.LevelMatchFilter"> + <levelToMatch value="INFO" /> + </filter> + <filter type="log4net.Filter.DenyAllFilter" /> + <file value="Logs\perf.log" /> + <encoding value="utf-8"/> + <preserveLogFileNameExtension value="true" /> + <appendToFile value="true" /> + <rollingStyle value="Date" /> + <datePattern value="yyyyMMdd" /> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date %logger - %message%newline" /> + </layout> + </appender> + <root> + <level value="ALL" /> + <appender-ref ref="errorAppender" /> + <appender-ref ref="infoAppender" /> + <appender-ref ref="debugAppender" /> + </root> + <logger name="Performance" additivity="false"> + <level value="ALL" /> + <appender-ref ref="perfAppender" /> + </logger> +</log4net> \ No newline at end of file diff --git a/类库/Api.Framework/Config/log4net.unix.config b/类库/Api.Framework/Config/log4net.unix.config new file mode 100644 index 0000000..3b07772 --- /dev/null +++ b/类库/Api.Framework/Config/log4net.unix.config @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8" ?> +<log4net> + <appender name="errorAppender" type="log4net.Appender.RollingFileAppender"> + <filter type="log4net.Filter.LevelMatchFilter"> + <levelToMatch value="ERROR" /> + </filter> + <filter type="log4net.Filter.DenyAllFilter" /> + <File value="Logs/err.log" /> + <encoding value="utf-8"/> + <preserveLogFileNameExtension value="true" /> + <appendToFile value="true" /> + <rollingStyle value="Date" /> + <datePattern value="yyyyMMdd" /> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> + </layout> + </appender> + <appender name="infoAppender" type="log4net.Appender.RollingFileAppender"> + <filter type="log4net.Filter.LevelMatchFilter"> + <levelToMatch value="INFO" /> + </filter> + <filter type="log4net.Filter.DenyAllFilter" /> + <file value="Logs/info.log" /> + <encoding value="utf-8"/> + <preserveLogFileNameExtension value="true" /> + <appendToFile value="true" /> + <rollingStyle value="Date" /> + <datePattern value="yyyyMMdd" /> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> + </layout> + </appender> + <appender name="debugAppender" type="log4net.Appender.RollingFileAppender"> + <filter type="log4net.Filter.LevelMatchFilter"> + <levelToMatch value="DEBUG" /> + </filter> + <filter type="log4net.Filter.DenyAllFilter" /> + <file value="Logs/debug.log" /> + <encoding value="utf-8"/> + <preserveLogFileNameExtension value="true" /> + <appendToFile value="true" /> + <rollingStyle value="Date" /> + <datePattern value="yyyyMMdd" /> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> + </layout> + </appender> + <appender name="perfAppender" type="log4net.Appender.RollingFileAppender"> + <filter type="log4net.Filter.LevelMatchFilter"> + <levelToMatch value="INFO" /> + </filter> + <filter type="log4net.Filter.DenyAllFilter" /> + <file value="Logs/perf.log" /> + <encoding value="utf-8"/> + <preserveLogFileNameExtension value="true" /> + <appendToFile value="true" /> + <rollingStyle value="Date" /> + <datePattern value="yyyyMMdd" /> + <layout type="log4net.Layout.PatternLayout"> + <conversionPattern value="%date %logger - %message%newline" /> + </layout> + </appender> + <root> + <level value="ALL" /> + <appender-ref ref="errorAppender" /> + <appender-ref ref="infoAppender" /> + <appender-ref ref="debugAppender" /> + </root> + <logger name="Performance" additivity="false"> + <level value="ALL" /> + <appender-ref ref="perfAppender" /> + </logger> +</log4net> \ No newline at end of file diff --git a/类库/Api.Framework/Cps/AlimamaApi.cs b/类库/Api.Framework/Cps/AlimamaApi.cs new file mode 100644 index 0000000..48be361 --- /dev/null +++ b/类库/Api.Framework/Cps/AlimamaApi.cs @@ -0,0 +1,2313 @@ +//============================================================= +// 创建人:千年老妖 +// 本页代码,均为原创。对未经许可擅自使用者,本人保留追究其法律责任的权利。 +//============================================================== +using Api.Framework.Events; +using Api.Framework.Model; +using CsharpHttpHelper; +using Api.Framework.Tools; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Threading; +using Api.Framework.Utils; +using Api.Framework.Enums; +using System.Net; +using System.Web; +using System.Web.Caching; +using Api.Framework.Timers; +using System.Windows.Forms; +using Api.Framework.Data.TB; +using Api.Framework.EntityTmp; +using Api.Framework.Extents; +using Microsoft.ClearScript.Util.Web; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Api.Framework.Cps +{ + /// <summary> + /// 阿里妈妈操作Api + /// </summary> + public class AlimamaApi : BaseCpsApi + { + #region 静态功能 + + /// <summary> + /// url请求方法 + /// </summary> + /// <param name="tempUrl"></param> + /// <returns></returns> + private static string M_GET_HTML(string tempUrl) + { + try + { + HttpItem item = new HttpItem() + { + URL = tempUrl, //URL 必需项 + Method = "get", //URL 可选项 默认为Get + IsToLower = false, //得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = Cookies + ";random=" + new Random().Next(), //字符串Cookie 可选项 + Referer = "http://m.taobao.com", //来源URL 可选项 + Timeout = 100000, //连接超时时间 可选项默认为100000 + ReadWriteTimeout = 30000, //写入Post数据超时时间 可选项默认为30000 + UserAgent = + "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", //用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "text/html", //返回类型 可选项有默认值 + Allowautoredirect = false, //是否根据301跳转 可选项 + }; + HttpHelper http = new HttpHelper(); + //HttpResult result = http.GetHtml(item); + + var result = http.GetHtml(item); + if (!string.IsNullOrEmpty(result.Cookie)) + { + Cookies = result.UpdateCookies(Cookies); + } + + return result.Html; + } + catch (Exception ex) + { + //Console.WriteLine(ex.Message); + return string.Empty; + } + } + + private static string appKey = "12574478"; + private static string Cookies = string.Empty; + + private static Dictionary<string, object> M_GET(string api, object data, string version = "1.0") + { + //_cookies = string.Empty; + int number = 1; + Next: + string time = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString(); + string mh5Tk = HttpExtend.GetCookiesValue("_m_h5_tk", Cookies); + mh5Tk = string.IsNullOrEmpty(mh5Tk) ? "f64aa152f943661f750e6212ebc98804_1481170439770" : mh5Tk; + string json = (data.GetType() == typeof(string)) + ? data.ToString() + : HttpHelper.ObjectToJson(data).Replace("\\u0026", "&"); + string temp_ = mh5Tk + "&" + time + "&" + appKey + "&" + json; + + string sign = HttpHelper.ToMD5(temp_).ToLower(); + ; + string send = HttpHelper.URLEncode(json); + string temp = + string.Format( + "http://acs.m.taobao.com/h5/{5}/{4}/?v={4}&api={5}&appKey={0}&t={1}&callback=mtopjsonp1&type=jsonp&sign={2}&data={3}", + appKey, time, sign, send, version, api); + string html = M_GET_HTML(temp).Trim(); + if ((html.Contains("令牌过期") || html.Contains("令牌为空") || html.Contains("失效") || + html.Contains("login.m.taobao.com"))) + { + if (number < 5) + { + number++; + goto Next; + } + } + + var reg = System.Text.RegularExpressions.Regex.Match(html, @"^mtopjsonp1\((.*?)\)$", + System.Text.RegularExpressions.RegexOptions.IgnoreCase); + if (reg.Success) + { + var dic = HttpExtend.JsonToDictionary(reg.Groups[1].Value); + if (dic.ContainsKey("data") && html.Contains("SUCCESS::调用成功")) + return dic["data"] as Dictionary<string, object>; + throw new Exception(reg.Groups[1].Value); + } + + throw new Exception(html); + } + + private static Dictionary<string, DateTime> error_next = new Dictionary<string, DateTime>(); + + /// <summary> + /// 解析优惠券信息 + /// </summary> + /// <param name="sellerId">商家id</param> + /// <param name="activityId">优惠券id</param> + /// <param name="pid"></param> + /// <returns></returns> + public static Dictionary<string, object> mtop_alimama_union_hsf_coupon_get(string sellerId, string activityId, + string pid = "") + { + try + { + //222097624044 7b66a82d352a4af481bc85452fcf3344 + + if (string.IsNullOrEmpty(pid)) pid = "mm_33231688_7050284_23466709"; + string api = "mtop.alimama.union.hsf.mama.coupon.get"; + string version = "1.0"; + var data = new + { + sellerId = sellerId, + activityId = activityId, + pid = pid + + }; + if (!error_next.ContainsKey(api) || error_next[api] > DateTime.Now) + { + try + { + var result = M_GET(api, data, version); + return result; + } + catch (Exception ex) + { + if (ex.Message.Contains("访问受限")) + { + error_next[api] = DateTime.Now.AddMinutes(10); + } + else throw new Exception("mauhcg:" + ex.Message); + } + } + } + catch (Exception ex) + { + // Client.OnLog("error:mtop_alimama_union_hsf_coupon_get->" + ex.Message); + } + + return null; + + } + + #endregion + + /// <summary> + /// 优惠券结构类 + /// </summary> + public class Coupon + { + /// <summary> + /// 优惠券状态,!=0表示优惠券失效或没有优惠券 + /// </summary> + public int retStatus { get; set; } + + /// <summary> + /// 使用条件 + /// </summary> + public string startFee { get; set; } + + /// <summary> + /// 使用金额 + /// </summary> + public string amount { get; set; } + + /// <summary> + /// 店铺Logo + /// </summary> + public string shopLogo { get; set; } + + /// <summary> + /// 店铺名称 + /// </summary> + public string shopName { get; set; } + + /// <summary> + /// 使用时间 + /// </summary> + public DateTime effectiveStartTime { get; set; } + + /// <summary> + /// 活动截止时间 + /// </summary> + public DateTime effectiveEndTime { get; set; } + + /// <summary> + /// 点击下单 + /// </summary> + public string clickUrl { get; set; } + + /// <summary> + /// 分享地址 + /// </summary> + public string shareUrl { get; set; } + + /// <summary> + /// 软件标题 + /// </summary> + public string title { get; set; } + + /// <summary> + /// 原价 + /// </summary> + public string reservePrice { get; set; } + + /// <summary> + /// 折扣价格 + /// </summary> + public string discountPrice { get; set; } + + /// <summary> + /// 30天销量 + /// </summary> + public int biz30Day { get; set; } + + /// <summary> + /// 是否是天猫 ,1(是) + /// </summary> + public string tmall { get; set; } + + /// <summary> + /// 未知参数 + /// </summary> + public int postFree { get; set; } + + /// <summary> + /// 宝贝ID + /// </summary> + public string itemId { get; set; } + + /// <summary> + /// 未知参数 + /// </summary> + public string couponFlowLimit { get; set; } + } + + #region 私域数据异步绑定 + + /// <summary> + /// 淘宝eid绑定缓存 + /// </summary> + public class TBEidExid + { + /// <summary> + /// 淘宝客外部用户标记,如自身系统账户ID;微信ID等 + /// </summary> + public string special_id { get; set; } + + /// <summary> + /// 失效时间 + /// </summary> + public int dietime { get; set; } + + /// <summary> + /// eid + /// </summary> + public string external_id { get; set; } + } + + /// <summary> + /// 缓存 + /// </summary> + private static Dictionary<string, List<TBEidExid>> TBEidExidList = new Dictionary<string, List<TBEidExid>>(); + + /// <summary> + /// 添加Eid缓存 + /// </summary> + /// <param name="external_id">eid</param> + public void AddTBEid(string external_id) + { + try + { + if (!TBEidExidList.ContainsKey(Member.username)) + TBEidExidList.Add(Member.username, new List<TBEidExid>()); + var ext = TBEidExidList[Member.username].FirstOrDefault(f => f.external_id == external_id); + if (ext != null && ext.dietime < HttpExtend.GetTimeStamp(DateTime.Now)) + { + TBEidExidList[Member.username].Remove(ext); + ext = null; + } + + if (ext == null) + { + TBEidExidList[Member.username].Add(new TBEidExid() + { external_id = external_id, dietime = HttpExtend.GetTimeStamp(DateTime.Now.AddMinutes(10)) }); + } + } + catch (Exception ex) + { + } + } + + private static Dictionary<string, string> RunEidSyncDic = new Dictionary<string, string>(); + + /// <summary> + /// 同步私域数据 + /// </summary> + private static System.Threading.Timer timer = + new System.Threading.Timer(new TimerCallback(EidSync), null, 0, 1000 * 60 * 2); + + private static TBHelper.TbAnalysis tbAnalysis = new TBHelper.TbAnalysis(); + + private static int runNum = 1; + + /// <summary> + /// 同步私域数据 + /// </summary> + /// <param name="state"></param> + private static void EidSync(object state) + { + try + { + if (!tbAnalysis.IsRunTBSiYu()) + return; + runNum++; + + if (TBEidExidList.Count == 0) return; + + var cpsMembers = CpsClient.Members + .Where(f => f.cpstype == CpsType.阿里妈妈 && f.is_download == SwitchType.开启).ToList(); + + Task[] _task = new Task[cpsMembers.Count]; + for (int i = 0; i < cpsMembers.Count; i++) + { + var cps = cpsMembers[i]; + _task[i] = new Task(delegate + { + if (RunEidSyncDic.ContainsKey(cps.username)) + return; + try + { + RunEidSyncDic.Add(cps.username, cps.username); + var api = CpsClient.CreateAlimamaRequest(cps); + if (!TBEidExidList.ContainsKey(cps.username) || TBEidExidList[cps.username].Count == 0) + return; + + #region 删除过期的数据 + + if (runNum % 10 == 0) + { + try + { + var dieEidList = TBEidExidList[cps.username] + .Where(f => f.dietime < HttpExtend.GetTimeStamp(DateTime.Now)).ToList(); + for (int q = 0; q < dieEidList.Count; q++) + { + TBEidExidList[cps.username].Remove(dieEidList[q]); + } + } + catch (Exception ex) + { + } + } + + #endregion + + TBEidExidList[cps.username] = TBEidExidList[cps.username] + .Where(f => f.dietime >= HttpExtend.GetTimeStamp(DateTime.Now)).ToList(); + + var arrList = tbAnalysis.FindTbPublisherInfoAll(api); + List<Dictionary<string, object>> dicList = new List<Dictionary<string, object>>(); + foreach (Dictionary<string, object> item in arrList) + { + if (item.ContainsKey("external_id")) + dicList.Add(item); + } + + var db = ApiClient.GetSession(); + + bool isUpdate = false; + for (int e = 0; e < TBEidExidList[cps.username].Count; e++) + { + try + { + var result = dicList.Where(z => + z["external_id"].ToString() == TBEidExidList[cps.username][e].external_id) + .ToList(); + if (result != null && result.Count != 0) + { + var count = result.Count; + if (count == 1) + { + var special_id = long.Parse(result[0]["special_id"].ToString()); + var external_id = TBEidExidList[cps.username][e].external_id; + + var relation = db.FindTbRelations().FirstOrDefault(f => + f.special_id == special_id && f.cps_memberid == cps.username); + if (relation == null) + relation = new fl_tb_relation() + { cps_memberid = cps.username, special_id = special_id }; + if (relation.username != external_id) + { + isUpdate = true; + relation.username = external_id; + relation = db.Saveable(relation).ExecuteReturnEntity(); + } + + TBEidExidList[cps.username].Remove(TBEidExidList[cps.username][e]); + } + //else if (count > 1) + //{ + // for (int w = 0; w < result.Count; w++) + // { + // dicList.Remove(result[w]); + // } + //} + } + } + catch (Exception ex) + { + } + } + + if (isUpdate) + db.FindTbRelations(true); + } + catch (Exception ex) + { + EventClient.OnEvent("私域异步绑定", ex.Message); + } + finally + { + if (RunEidSyncDic.ContainsKey(cps.username)) + RunEidSyncDic.Remove(cps.username); + } + }); + _task[i].Start(); + Thread.Sleep(1); + } + + Task.WaitAll(_task); + } + catch (Exception ex) + { + EventClient.OnEvent("", $"私域异步绑定异常:{ex.Message} - {ex.StackTrace}"); + } + } + + #endregion + + private const string SIGN_METHOD_MD5 = "md5"; + private const string SIGN_METHOD_HMAC = "hmac"; + + private string SignTopRequest(Dictionary<string, string> parameters, string secret, string signMethod = "hmac") + { + // 第一步:把字典按Key的字母顺序排序 + IDictionary<string, string> sortedParams = + new SortedDictionary<string, string>(parameters, StringComparer.Ordinal); + + // 第二步:把所有参数名和参数值串在一起 + StringBuilder query = new StringBuilder(); + if (SIGN_METHOD_MD5.Equals(signMethod)) + { + query.Append(secret); + } + + foreach (KeyValuePair<string, string> kv in sortedParams) + { + if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value) && kv.Key != "sign") + { + query.Append(kv.Key).Append(kv.Value); + } + } + + //// 第三步:把请求主体拼接在参数后面 + //if (!string.IsNullOrEmpty(body)) + //{ + // query.Append(body); + //} + + // 第四步:使用MD5/HMAC加密 + byte[] bytes; + if (SIGN_METHOD_HMAC.Equals(signMethod)) + { + HMACMD5 hmac = new HMACMD5(Encoding.UTF8.GetBytes(secret)); + bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString())); + } + else + { + query.Append(secret); + MD5 md5 = MD5.Create(); + bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString())); + } + + // 第五步:把二进制转化为大写的十六进制 + StringBuilder result = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + result.Append(bytes[i].ToString("X2")); + } + + return result.ToString(); + } + + private static DateTime servertime = DateTime.MinValue; + + #region 老道重新修改 + + private static string tlj = "taobao.tbk.dg.vegas.tlj.create"; + private static string[] not_session = new string[] { "taobao.tbk.item.info.get", tlj }; + private static int[] server_port = new[] { 30001, 30002, 30003, 30004, 30005 }; + + /// <summary> + /// 计算签名,返回请求阿里妈妈服务器的参数 + /// </summary> + /// <param name="_api">api名称</param> + /// <param name="_data">参数</param> + /// <param name="appkey">appkey</param> + /// <param name="appsecret">appsecret</param> + /// <returns></returns> + private string GetAlimamaRequestData(string _api, object _data, string appkey = "", string appsecret = "") + { + try + { + var data = _data; + var api = _api; + Dictionary<string, string> param = new Dictionary<string, string>(); + var type = data.GetType().GetProperties(); + + foreach (var item in type) + { + var _value = item.GetValue(data).ToString(); + param[item.Name] = _value; + } + + var app_id = Token.appid; + var app_key = Token.appkey; + var accessToken = Token.access_token; + + //#if DEBUG + // app_id = "33951412"; + // app_key = "ab478e5a7332acee4ee3e4f56f70a6cb"; + // accessToken = "6100412e139f270d8430132973d2e7cefbbb26be53653b12200733453642"; + //#endif + + + //淘礼金接口 + if (tlj == api) + { + if (string.IsNullOrWhiteSpace(appkey)) throw new Exception("淘礼金appkey不能为空,终止淘礼金生成操作"); + if (string.IsNullOrWhiteSpace(appsecret)) throw new Exception("淘礼金appsecret不能为空,终止淘礼金生成操作"); + app_id = appkey; + app_key = appsecret; + } + + param["method"] = api; + param["app_key"] = app_id; + if (!not_session.Contains(api)) + param["session"] = accessToken; + + //param["session"] = "7000010023374d0168aa5c8b8404a7d1de45cfb11ad3114891fccad8b7384c4d05d4e3c862677733"; + param["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + param["format"] = "json"; + param["v"] = "2.0"; + param["sign_method"] = "md5"; + + //计算签名 + string sign = SignTopRequest(param, app_key, param["sign_method"]); + param["sign"] = sign; + return HttpExtend.BuildQuery(param); + } + catch (Exception ex) + { + } + + return string.Empty; + } + + /// <summary> + /// 请求淘宝服务器端 + /// </summary> + /// <param name="_api">api名称</param> + /// <param name="_data">参数</param> + /// <param name="appkey">appkey</param> + /// <param name="appsecret">appsecret</param> + /// <returns></returns> + private Dictionary<string, object> SendTaobaoServer(string _api, object _data, string _appkey = "", + string _appsecret = "") + { + var data = _data; + var api = _api; + var appkey = _appkey; + var appsecret = _appsecret; + int number = 0; + Next: + + number++; + + if (!Member.is_valid && !this.RefToken()) throw new Exception("授权状态已过期,请重新登陆阿里妈妈!"); + var query = GetAlimamaRequestData(api, data, appkey, appsecret); + + var html = string.Empty; + string _url = string.Empty; + try + { + HttpHelper http = new HttpHelper(); + + _url = "http://gw.api.taobao.com/router/rest?" + query; + + if (servertime > DateTime.Now || (number > 2 && api == "taobao.tbk.item.info.get")) + { + try + { + var _item = http.GetItem( + $"http://jushita.api.52cmg.cn:{server_port[new Random().Next(0, server_port.Length)]}/api/http/gethtml", + "", $"url={HttpHelper.URLEncode(_url)}"); + var _html = http.GetHtml(_item).Html; + //if (api == "taobao.tbk.sc.tpwd.convert") EventClient.OnEvent("解析日志", _html); + var _dic = HttpExtend.JsonToDictionary(_html); + if (_dic != null && _dic["Code"].ToString() == "0") html = _dic["Data"].ToString(); + } + catch (Exception) + { + } + } + + if (string.IsNullOrEmpty(html)) + { + HttpItem item = new HttpItem() + { + URL = _url, //URL 必需项 + Method = "GET", //URL 可选项 默认为Get + Timeout = 5000, //连接超时时间 可选项默认为100000 + ReadWriteTimeout = 5000, //写入Post数据超时时间 + Accept = "text/html, application/xhtml+xml, */*", // 可选项有默认值 + ContentType = "application/json", //返回类型 可选项有默认值 + }; + var result = http.GetHtml(item); + //{"tbk_dg_vegas_tlj_create_response":{"result":{"model":{"rights_id":"XvLXNwkX8HBQ8VZ2WS4DlNtN7m9cS4TU","send_url":"https:\/\/uland.taobao.com\/taolijin\/edetail?eh=5L6pfx5vldOZuQF0XRz0iAXoB%2BDaBK5LQS0Flu%2FfbSp4QsdWMikAalrisGmre1Id0BFAqRODu1004PvI5lqUzYTPq7zN5TtBXU4J7X2wljh7PW2ShemY2x1IRRpXndAncj8tXpgtxXzbOKxKSviYxsuv0da8KKt7WubOUkoI2Oa3HR2hP0JFSmjppH3xlrrJg8pBHJnzzOjd2vZvO6fEydXbwx4naJ6dk%2FBu2lJxZtMc7BMk%2FDH7wY2fDQKPuN9qcxwaWpDoQwfi%2B9ZUBfurmaewy3GJqMoK4342DlvX1ZVNOJlvqrE2h6J7%2BkHL3AEW&union_lens=lensId%3A0b14fbf4_0b3d_16f65a622fd_31b4%3Btraffic_flag%3Dlm","vegas_code":"N4HHV6HV"},"success":true},"request_id":"no8k8bbwsct2"}} + html = result.Html; + if (result != null && result.StatusCode != System.Net.HttpStatusCode.OK) + throw new Exception(html); + } + + //Console.WriteLine($"html = {html}"); + var dic = HttpExtend.JsonToDictionary(html); + if (dic == null) throw new Exception(html); + if (dic.ContainsKey("error_response")) + throw new Exception(html); + + var key = api.Replace("taobao.", "").Replace(".", "_") + "_response"; + if (!dic.ContainsKey(key)) throw new Exception($"key = {key},html = {html}"); + dic = dic[key] as Dictionary<String, object>; + if (dic.ContainsKey("result")) return dic["result"] as Dictionary<string, object>; + if (dic.ContainsKey("results")) return dic["results"] as Dictionary<string, object>; + return dic; + } + catch (Exception ex) + { + var appId = Token.appid; + +#if DEBUG + appId = "33951412"; +#endif + + LogHelper.GetSingleObj().Error("AlimamaApi", $"api{api},appid={appId},url={_url}"); + if (ex.Message.Contains("invalid-sessionkey")) + { + Thread.Sleep(1000); + if (this.Member != null && RefToken() && this.Member.is_valid) goto Next; + else throw new Exception($"{this.Member.username}({this.Member.usernick})授权状态已过期,请重新登陆阿里妈妈!"); + } + else if (ex.Message.Contains("Platform System blacklist")) + { + servertime = DateTime.Now.AddMonths(5); + if (number > 3) + { + throw ex; + } + + goto Next; + } + else if (number < 3 && (ex.Message.Contains("sub_msg\":\"无结果") || + ex.Message.Contains("Invalid signature") || + ex.Message.Contains("请求阿里妈妈API异常") || ex.Message.Contains("未将对象引用设置到对象的实例") || + ex.Message.Contains("操作超时") || + (!ex.Message.Contains("SessionKey非法") && + !ex.Message.Contains("App Call Limited")) || Regex.Match(ex.Message, + @"(""error_response"":{""code"":15,""msg"":""Remote service error"",""sub_code"":)|(操作超时)|(基础连接已经关闭)|(远程服务调用超时)|(淘宝客API服务不可用)|(HSF执行错误)") + .Success)) + { + if ((ex.Message.Contains("该item_id对应宝贝已下架或非淘客宝贝") || ex.Message.Contains("sub_msg\":\"无结果")) && + number > 1) //重试两次就直接抛出 + throw ex; + Thread.Sleep(100); + goto Next; + } + else if (ex.Message.Contains("sub_msg\":\"无结果") || ex.Message.Contains("sub_msg\":\"淘口令解析结果为空") || + ex.Message.Contains("sub_msg\":\"口令跳转url不支持口令转换")) + throw ex; + else + { + //EventClient.OnEvent(this,$@"cce:{_api.Replace("taobao.tbk.", "").Replace(".", "")} => {ex.Message} - {ex.StackTrace} + //html => {html}"); + if (ex.Message.Contains("Invalid signature")) + throw new Exception($"{this.Member.username}({this.Member.usernick})Invalid signature,请求异常"); + else + { + if (ex.Message.Contains("Insufficient isv permissions")) + throw new Exception( + $"{this.Member.username}({this.Member.usernick}) isv权限不足~!处理方法:1.请检测阿里妈妈权限 2.重新登陆阿里妈妈重试"); + throw new Exception($"{this.Member.username}({this.Member.usernick})请求阿里妈妈接口:" + ex.Message + + " - " + ex.StackTrace); + } + } + } + } + + /// <summary> + /// 请求淘宝服务器端 + /// </summary> + /// <param name="_api">api名称</param> + /// <param name="_data">参数</param> + /// <param name="appkey">appkey</param> + /// <param name="appsecret">appsecret</param> + /// <returns></returns> + private JToken SendTaobaoServerJToken(string _api, object _data, string _appkey = "", string _appsecret = "") + { + var data = _data; + var api = _api; + var appkey = _appkey; + var appsecret = _appsecret; + int number = 0; + Next: + + number++; + + if (!Member.is_valid && !this.RefToken()) throw new Exception("授权状态已过期,请重新登陆阿里妈妈!"); + var query = GetAlimamaRequestData(api, data, appkey, appsecret); + + var html = string.Empty; + string _url = string.Empty; + try + { + HttpHelper http = new HttpHelper(); + + _url = "http://gw.api.taobao.com/router/rest?" + query; + + if (servertime > DateTime.Now || (number > 2 && api == "taobao.tbk.item.info.get")) + { + try + { + var _item = http.GetItem( + $"http://jushita.api.52cmg.cn:{server_port[new Random().Next(0, server_port.Length)]}/api/http/gethtml", + "", $"url={HttpHelper.URLEncode(_url)}"); + var _html = http.GetHtml(_item).Html; + //if (api == "taobao.tbk.sc.tpwd.convert") EventClient.OnEvent("解析日志", _html); + var _dic = HttpExtend.JsonToDictionary(_html); + if (_dic != null && _dic["Code"].ToString() == "0") html = _dic["Data"].ToString(); + } + catch (Exception) + { + } + } + + if (string.IsNullOrEmpty(html)) + { + HttpItem item = new HttpItem() + { + URL = _url, //URL 必需项 + Method = "GET", //URL 可选项 默认为Get + Timeout = 5000, //连接超时时间 可选项默认为100000 + ReadWriteTimeout = 5000, //写入Post数据超时时间 + Accept = "text/html, application/xhtml+xml, */*", // 可选项有默认值 + ContentType = "application/json", //返回类型 可选项有默认值 + }; + var result = http.GetHtml(item); + //{"tbk_dg_vegas_tlj_create_response":{"result":{"model":{"rights_id":"XvLXNwkX8HBQ8VZ2WS4DlNtN7m9cS4TU","send_url":"https:\/\/uland.taobao.com\/taolijin\/edetail?eh=5L6pfx5vldOZuQF0XRz0iAXoB%2BDaBK5LQS0Flu%2FfbSp4QsdWMikAalrisGmre1Id0BFAqRODu1004PvI5lqUzYTPq7zN5TtBXU4J7X2wljh7PW2ShemY2x1IRRpXndAncj8tXpgtxXzbOKxKSviYxsuv0da8KKt7WubOUkoI2Oa3HR2hP0JFSmjppH3xlrrJg8pBHJnzzOjd2vZvO6fEydXbwx4naJ6dk%2FBu2lJxZtMc7BMk%2FDH7wY2fDQKPuN9qcxwaWpDoQwfi%2B9ZUBfurmaewy3GJqMoK4342DlvX1ZVNOJlvqrE2h6J7%2BkHL3AEW&union_lens=lensId%3A0b14fbf4_0b3d_16f65a622fd_31b4%3Btraffic_flag%3Dlm","vegas_code":"N4HHV6HV"},"success":true},"request_id":"no8k8bbwsct2"}} + html = result.Html; + if (result != null && result.StatusCode != System.Net.HttpStatusCode.OK) + throw new Exception(html); + } + + var jsonResult = JObject.Parse(html); + if (jsonResult == null) + throw new Exception(html); + + var jToken = jsonResult.First?.First; + if (jToken != null) + { + if (jToken["code"] != null) + throw new Exception(jToken.ToString()); + if (jToken["results"] != null) + return jToken["results"]; + if (jToken["result"] != null) + { + var jTokenResult = jToken["result"]; + return (jTokenResult["data"] ?? jTokenResult); + } + if (jToken["data"] != null) + return jToken["data"]; + } + return jToken; + } + catch (Exception ex) + { + var appId = Token.appid; + + LogHelper.GetSingleObj().Error("AlimamaApi", $"api{api},appid={appId},url={_url}"); + if (ex.Message.Contains("invalid-sessionkey")) + { + Thread.Sleep(1000); + if (this.Member != null && RefToken() && this.Member.is_valid) goto Next; + else throw new Exception($"{this.Member.username}({this.Member.usernick})授权状态已过期,请重新登陆阿里妈妈!"); + } + else if (ex.Message.Contains("Platform System blacklist")) + { + servertime = DateTime.Now.AddMonths(5); + if (number > 3) + { + throw ex; + } + + goto Next; + } + else if (number < 3 && (ex.Message.Contains("sub_msg\":\"无结果") || + ex.Message.Contains("Invalid signature") || + ex.Message.Contains("请求阿里妈妈API异常") || ex.Message.Contains("未将对象引用设置到对象的实例") || + ex.Message.Contains("操作超时") || + (!ex.Message.Contains("SessionKey非法") && + !ex.Message.Contains("App Call Limited")) || Regex.Match(ex.Message, + @"(""error_response"":{""code"":15,""msg"":""Remote service error"",""sub_code"":)|(操作超时)|(基础连接已经关闭)|(远程服务调用超时)|(淘宝客API服务不可用)|(HSF执行错误)") + .Success)) + { + if ((ex.Message.Contains("该item_id对应宝贝已下架或非淘客宝贝") || ex.Message.Contains("sub_msg\":\"无结果")) && + number > 1) //重试两次就直接抛出 + throw ex; + Thread.Sleep(100); + goto Next; + } + else if (ex.Message.Contains("sub_msg\":\"无结果") || ex.Message.Contains("sub_msg\":\"淘口令解析结果为空") || + ex.Message.Contains("sub_msg\":\"口令跳转url不支持口令转换")) + throw ex; + else + { + //EventClient.OnEvent(this,$@"cce:{_api.Replace("taobao.tbk.", "").Replace(".", "")} => {ex.Message} - {ex.StackTrace} + //html => {html}"); + if (ex.Message.Contains("Invalid signature")) + throw new Exception($"{this.Member.username}({this.Member.usernick})Invalid signature,请求异常"); + else + { + if (ex.Message.Contains("Insufficient isv permissions")) + throw new Exception( + $"{this.Member.username}({this.Member.usernick}) isv权限不足~!处理方法:1.请检测阿里妈妈权限 2.重新登陆阿里妈妈重试"); + throw new Exception($"{this.Member.username}({this.Member.usernick})请求阿里妈妈接口:" + ex.Message + + " - " + ex.StackTrace); + } + } + } + } + + /// <summary> + /// 淘礼金调用 + /// </summary> + /// <param name="_api">api名称</param> + /// <param name="_data">参数</param> + /// <param name="_appkey">appkey</param> + /// <param name="_appsecret">appsecret</param> + /// <returns></returns> + public Dictionary<string, object> SendTaobao(string _api, object _data, string _appkey = "", + string _appsecret = "") + { + var data = _data; + var api = _api; + var appkey = _appkey; + var appsecret = _appsecret; + + return SendTaobaoServer(api, data, appkey, appsecret); + } + + /// <summary> + /// 发送阿里妈妈报文 + /// </summary> + /// <param name="_api">api名称</param> + /// <param name="_data">参数</param> + /// <returns></returns> + public Dictionary<string, object> SendTaobao(string _api, object _data) + { + var data = _data; + var api = _api; + + return SendTaobaoServer(api, data); + } + + /// <summary> + /// 发送阿里妈妈报文 + /// </summary> + /// <param name="_api">api名称</param> + /// <param name="_data">参数</param> + /// <returns></returns> + public T SendTaobao<T>(string _api, object _data) + { + var data = _data; + var api = _api; + + return SendTaobaoServerJToken(api, data).ToObject<T>(); + } + + #endregion + + /// <summary> + /// 解析淘口令 + /// </summary> + /// <param name="password"></param> + /// <param name="adzoneId"></param> + /// <param name="siteId"></param> + /// <returns></returns> + public TBPassInfoData AnalysisTkPassword(string password, string adzoneId, string siteId) + { + var data = SendTaobao<TBPassInfoData>("taobao.tbk.sc.tpwd.convert", + new { password_content = password, adzone_id = adzoneId, site_id = siteId }); + return data; + } + + /// <summary> + /// 解析链接 (长短链接 s.click.taobao) + /// </summary> + /// <param name="url"></param> + /// <returns></returns> + public AnalysisTkUrlData AnalysisTkUrl(string url, string bizSceneId) + { + var result = SendTaobao<AnalysisTkUrlData>("taobao.tbk.item.click.extract", new { click_url = url, biz_scene_id = bizSceneId }); + + return result; + } + + + public TBItemInfoData TurnItemId(string itemId, string activityId, string adzoneId, string siteId, + string bizSceneId, string specialId = "", bool isCircle = false) + { + try + { + bizSceneId = TBHelper.TbAnalysis.BizSceneId(itemId); + + object transportData; + if (!string.IsNullOrWhiteSpace(specialId)) + transportData = new { adzone_id = adzoneId, site_id = siteId, item_id = itemId, special_id = specialId, biz_scene_id = bizSceneId }; + else + transportData = new { adzone_id = adzoneId, site_id = siteId, item_id = itemId, biz_scene_id = bizSceneId }; + + var queryItemDataResult = GetItemInfo(itemId, bizSceneId); + + if (queryItemDataResult == null) + { + throw new Exception("商品基础信息查询失败"); + } + + if (queryItemDataResult.n_tbk_item == null || queryItemDataResult.n_tbk_item.Count <= 0) + { + throw new Exception("商品基础信息查询失败"); + } + + var queryItemData = queryItemDataResult.n_tbk_item[0]; + + if (queryItemData == null) + { + throw new Exception("商品基础信息查询失败"); + } + + var jToken = SendTaobaoServerJToken("taobao.tbk.privilege.get", transportData); + if (jToken != null) + { + var item = new TBItemInfoData() + { + ItemId = queryItemData.num_iid, + //BuyPass = string.Empty, + BuyUrl = jToken["coupon_click_url"]?.Value<string>() ?? jToken["item_url"]?.Value<string>(), + CommissionRatio = (jToken["max_commission_rate"]?.Value<decimal>() ?? 0).ExecDivision(100, 4), + //CouponUrl = jToken["coupon_click_url"]?.ToString(), + ImageUrl = queryItemData.pict_url, + ItemTitle = queryItemData.title, + ItemUrl = queryItemData.item_url, + Price = decimal.Parse(queryItemData.zk_final_price), + Sales = queryItemData.volume, + ShopId = queryItemData.seller_id.ToString(), + ShopNick = queryItemData.nick, + IsTip = true, + ActivityId = activityId + }; + + GetCouponInfo(jToken, item); + + var tklResult = SendTaobaoServerJToken("taobao.tbk.tpwd.create", new { url = item.BuyUrl }); + var regResult = HttpExtend.RegexMatchUrl(tklResult["model"]?.Value<string>()); + if (!string.IsNullOrWhiteSpace(regResult)) + { + item.BuyUrl = regResult.Replace("m.tb", "s.tb"); + } + + item.BuyPass = tklResult["password_simple"]?.Value<string>(); + + //朋友圈中间页 + var zjyResult = ComposeTbClick(itemId, item.ImageUrl, item.BuyPass, item.BuyUrl, adzoneId, true, isCircleZjy: isCircle); + if (zjyResult != null) + { + item.ZJYUrl = zjyResult; + } + + return item; + } + throw new Exception("商品链接失败"); + } + catch (Exception ex) + { + throw new Exception($"转连商品信息异常:{ex.Message}"); + } + } + + /// <summary> + /// 获取商品信息 + /// </summary> + /// <param name="itemId"></param> + /// <param name="bizSceneId"></param> + /// <returns></returns> + public GetItemInfosData GetItemInfo(string itemId, string bizSceneId) + { + bizSceneId = TBHelper.TbAnalysis.BizSceneId(itemId); + + var result = SendTaobao<GetItemInfosData>("taobao.tbk.item.info.get", new { num_iids = itemId, biz_scene_id = bizSceneId }); + return result; + } + + + /// <summary> + /// 获取优惠券信息 + /// </summary> + /// <param name="data"></param> + /// <param name="infoData"></param> + private void GetCouponInfo(JToken data, TBItemInfoData infoData) + { + //优惠券地址 + var couponUrl = data["item_url"]?.ToString(); + + //妈妈券 + var mmCouponInfo = data["mm_coupon_info"]; + //普通券 + var couponInfo = data["coupon_info"]; + + List<CouponData> couponList = new List<CouponData>(); + + //普通优惠券 + if (couponInfo != null) + { + var coupon = new CouponData(); + + var quanReg = Regex.Match(data["coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (quanReg.Success) + { + coupon.CouponPrice = decimal.Parse(quanReg.Groups["减"].Value); + coupon.ConditionPrice = decimal.Parse(quanReg.Groups["满"].Value); + couponUrl = coupon.CouponUrl = data["coupon_click_url"].ToString(); + + couponList.Add(coupon); + } + } + + //妈妈优惠券 + if (mmCouponInfo != null) + { + var coupon = new CouponData(); + + var mmQuanReg = Regex.Match(data["mm_coupon_info"].ToString(), @"满(?<满>\d+)元减(?<减>\d+)元"); + if (mmQuanReg.Success) + { + coupon.CouponPrice = decimal.Parse(mmQuanReg.Groups["减"].Value); + coupon.ConditionPrice = decimal.Parse(mmQuanReg.Groups["满"].Value); + couponUrl = coupon.CouponUrl = data["mm_coupon_click_url"].ToString(); + + couponList.Add(coupon); + } + } + + //获取其他优惠券Id信息 + if (string.IsNullOrWhiteSpace(infoData.ActivityId) == false) + { + var activityData = GetActivityInfo(infoData.ItemId, infoData.ActivityId); + if (activityData != null) + { + couponList.Add(activityData); + } + } + //将优惠券排序 + couponList.Sort(new CouponDataComparer()); + + //获取一个符合的优惠券 + var couponData = couponList.FirstOrDefault(f => f.ConditionPrice <= infoData.Price); + if (couponData != null) + { + if (!string.IsNullOrWhiteSpace(couponData.ActivityId)) + { + couponUrl = couponData.CouponUrl = $"{couponUrl}&activityId={couponData.ActivityId}"; + } + infoData.CouponPrice = couponData.CouponPrice; + infoData.UseCouponPrice = infoData.Price - infoData.CouponPrice; + } + else//没有优惠券 + { + infoData.CouponPrice = 0m; + infoData.UseCouponPrice = infoData.Price; + } + + infoData.CouponUrl = couponUrl; + } + + /// <summary> + /// 获取优惠券Id的信息 + /// </summary> + /// <param name="itemId">商品Id</param> + /// <param name="activityId">优惠券活动Id</param> + public CouponData GetActivityInfo(string itemId, string activityId) + { + try + { + var jToken = SendTaobaoServerJToken("taobao.tbk.coupon.get", new { activity_id = activityId, item_id = itemId }); + + if ((jToken["coupon_remain_count"]?.Value<int>() ?? 0) == 0) + { + throw new Exception("优惠券已经无效"); + } + + var coupon = new CouponData(); + coupon.ConditionPrice = jToken["coupon_start_fee"]?.Value<decimal>() ?? 0; + coupon.CouponPrice = jToken["coupon_amount"]?.Value<decimal>() ?? 0; + coupon.ActivityId = jToken["coupon_activity_id"]?.ToString(); + + return coupon; + } + catch (Exception ex) + { + + } + + return null; + } + + /// <summary> + /// 校验阿里妈妈cookiecs是否有效 + /// </summary> + /// <param name="cookies">cookies</param> + /// <returns></returns> + public static Dictionary<string, object> GetUnionPubContextInfo(string cookies) + { + var http = new HttpHelper(); + var item = http.GetItem("https://www.alimama.com/getLogInfo.htm?callback=__jp0", cookies); + var html = http.GetHtml(item).Html; + html = html.Replace("__jp0(", "").Replace(")", ""); + var result = + HttpHelper.JsonToObject<Dictionary<string, object>>(html.Replace("__jp0", "").Replace(")", "")) as + Dictionary<string, object>; + if (result != null && result.ContainsKey("result")) + { + return result["result"] as Dictionary<string, object>; + } + + return result; + } + + /// <summary> + /// 订单类型 + /// </summary> + public enum OrderType + { + 淘客订单明细 = 1, + 第三方订单明细 = 2, + 维权退款明细 = 3 + } + + /// <summary> + /// 判断是否是天猫商品 + /// </summary> + /// <param name="itemid">商品id</param> + /// <returns></returns> + public bool IsTianmao(string itemid) + { + var html = GetAlimamaHtml("https://detail.tmall.com/item.htm?id=" + itemid); + if (html.Contains("天猫Tmall.com") || html.Contains("tmallBuySupport=true")) return true; + return false; + } + + /// <summary> + /// 爬虫 - 从阿里妈妈官网提取订单 + /// </summary> + /// <param name="type">爬取的订单类型</param> + /// <param name="queryType">写0吧</param> + /// <param name="payStatus">写空吧</param> + /// <param name="maxSize">最大1000</param> + /// <param name="day">不能操作90天最好少于90天</param> + /// <param name="toPage">第几页</param> + /// <returns></returns> + public List<Dictionary<string, object>> SerchOrder(OrderType type, int queryType, string payStatus, int maxSize, + DateTime day, int toPage) + { + List<Dictionary<string, object>> rst = new List<Dictionary<string, object>>(); + //string url = "http://pub.alimama.com/report/getTbkPaymentDetails.json?startTime=" + start.ToString("yyyy-MM-dd") + "&endTime=" + end.ToString("yyyy-MM-dd") + "&payStatus="+(all?"":"3")+"&queryType=" + (all ? "1" : "3") + "&toPage=1&perPageSize=" + maxSize + "&total=&t=" + Tools.ConvertDateTimeInt(DateTime.Now).ToString() + "&_tb_token_=" + this.GetKey("tb_token") + "&_input_charset=utf-8"; + //pub.alimama.com/report/getTbkThirdPaymentDetails + try + { + + string url = string.Empty; + if (type == OrderType.淘客订单明细) //淘客订单明细 + //url = "https://pub.alimama.com/report/getTbkPaymentDetails.json?startTime=" + day.ToString("yyyy-MM-dd") + "&endTime=" + DateTime.Now.ToString("yyyy-MM-dd") + "&payStatus=" + payStatus + "&queryType=" + queryType + "&toPage=" + toPage + "&perPageSize=" + maxSize + "&total=&_input_charset=utf-8"; + url = "https://pub.alimama.com/report/getTbkPaymentDetails.json?startTime=" + + day.ToString("yyyy-MM-dd") + "&endTime=" + DateTime.Now.ToString("yyyy-MM-dd") + + "&payStatus=" + payStatus + "&queryType=" + queryType + "&toPage=" + toPage + + "&perPageSize=" + maxSize + "&total=&_input_charset=utf-8"; + else if (type == OrderType.第三方订单明细) //第三方订单明细 + //url = "https://pub.alimama.com/report/getTbkThirdPaymentDetails.json?startTime=" + day.ToString("yyyy-MM-dd") + "&endTime=" + DateTime.Now.ToString("yyyy-MM-dd") + "&payStatus=" + payStatus + "&queryType=" + queryType + "&toPage=" + toPage + "&perPageSize=" + maxSize + "&total=&_input_charset=utf-8"; + url = "https://pub.alimama.com/report/getTbkThirdPaymentDetails.json?startTime=" + + day.ToString("yyyy-MM-dd") + "&endTime=" + DateTime.Now.ToString("yyyy-MM-dd") + + "&payStatus=" + payStatus + "&queryType=" + queryType + "&toPage=" + toPage + + "&perPageSize=" + maxSize + "&total=&_input_charset=utf-8"; + else if (type == OrderType.维权退款明细) + //url = "https://pub.alimama.com/report/getNewTbkRefundPaymentDetails.json?startTime=" + day.ToString("yyyy-MM-dd") + "&endTime=" + DateTime.Now.ToString("yyyy-MM-dd") + "&refundType=1&searchType=1&toPage=1&perPageSize=" + maxSize + "&_input_charset=utf-8"; + url = + $"https://pub.alimama.com/openapi/param2/1/gateway.unionpub/report.getTbkRefundOrderDetails.json?pageNo={toPage}&startTime={day.ToString("yyyy-MM-dd")}&endTime={DateTime.Now.ToString("yyyy-MM-dd")}&queryType=1&isFullRefund=0&memberType=1&pageSize={maxSize}"; + //"https://pub.alimama.com/report/getNewTbkRefundPaymentDetails.json?startTime=" + day.ToString("yyyy-MM-dd") + "&endTime=" + DateTime.Now.ToString("yyyy-MM-dd") + "&refundType=1&searchType=1&toPage=" + toPage + "&perPageSize=" + maxSize + "&_input_charset=utf-8"; + + string html = GetAlimamaHtml(url); + if (html.Contains("<title>阿里妈妈")) + { + Member.online = false; + var session = ApiClient.GetSession(); + session.SaveOrUpdate(Member); + } + + Dictionary dic = HttpExtend.JsonToDictionary(html); + if (dic != null && dic.ContainsKey("data")) + { + dic = dic["data"] as Dictionary; + if (dic != null && dic.ContainsKey("result")) + { + var list = dic["result"] as ArrayList; + var _rst = new List>(); + foreach (Dictionary item in list) _rst.Add(item); + + _rst = _rst.OrderByDescending(a => DateTime.Parse(a["refundCreateTime"].ToString())) + .ToList(); //降序 + foreach (var item in _rst) + { + var _item = rst.FirstOrDefault(f => + f["tbTradeId"].ToString() == item["tbTradeId"].ToString() && + f["tbTradeParentId"].ToString() == item["tbTradeParentId"].ToString()); + if (_item == null) + rst.Add(item); + } + + } + } + } + catch (Exception wz) + { + // client.SendLogEvent("AliSerchOrder异常:" + ex.Message); + } + + return rst; + } + + private string create_scorder_url(Dictionary infos, string start_time, int page, int tk_status, + string order_query_type, string fields = "") + { + var parameters = new Dictionary(); + parameters["fields"] = string.IsNullOrEmpty(fields) + ? "tb_trade_parent_id,tb_trade_id,num_iid,item_title,item_num,price,pay_price,seller_nick,seller_shop_title,commission,commission_rate,unid,create_time,earning_time,tk3rd_pub_id,tk3rd_site_id,tk3rd_adzone_id,relation_id,tk_status,earning_time" + : fields; + parameters["method"] = "taobao.tbk.sc.order.get"; + parameters["start_time"] = start_time; + parameters["span"] = "1200"; + parameters["page_no"] = page.ToString(); + parameters["page_size"] = "100"; + parameters["tk_status"] = tk_status.ToString(); + parameters["order_query_type"] = order_query_type; + parameters["app_key"] = infos["key"].ToString(); + parameters["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + parameters["format"] = "json"; + parameters["v"] = "2.0"; + parameters["sign_method"] = "md5"; + //计算签名 + string sign = SignTopRequest(parameters, infos["secret"].ToString(), parameters["sign_method"]); + parameters["sign"] = sign; + string query = HttpExtend.BuildQuery(parameters); + return "http://gw.api.taobao.com/router/rest?" + query; + } + + /// + /// 下载订单,带状态(有多页,获取所有) + /// + /// 开始时间 + /// 第几页 + /// 页大小 + /// 同步的订单状态 + /// 阿里妈妈同步的订单类型 + /// 场景订单场景类型,1:常规订单,2:渠道订单,3:会员运营订单,默认为1 + /// + internal ArrayList DownOrder(DateTime start_time, int _page_index, int page_size, AlimamaOrderStatus tk_status, + AlimamaOrderType type, int order_scene) + { + #region 2021-08-04之后 新接口 第三版(按照订单更新时间) + + var interval = DownAlimamaTimer.GetIntervalCache(); //这个是三个小时的间隔 如果报错就用19分钟的间隔,默认179 + ArrayList array = new ArrayList(); + try + { + object obj = null; + var page_index = _page_index; + Dictionary _rst = null; + for (int i = 0; i < 2; i++) + { + try + { + obj = new + { + query_type = 4, //查询时间类型,1:按照订单淘客创建时间查询,2:按照订单淘客付款时间查询,3:按照订单淘客结算时间查询,4:按照订单更新时间; + page_size = page_size, //页大小 + start_time = start_time.ToString("yyyy-MM-dd HH:mm:ss"), + end_time = start_time.AddMinutes(interval) + .ToString( + "yyyy-MM-dd HH:mm:ss"), //这里是对应前面同步间隔的19分钟 //【订单查询结束时间,订单开始时间至订单结束时间,中间时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!】 + page_no = page_index, + order_count_type = (int)type, + order_scene = order_scene + }; + _rst = this.SendTaobao("taobao.tbk.sc.order.details.get", obj); + DownAlimamaTimer.SetIntervalCache(interval); + break; + } + catch (Exception ex) + { + //29453481(魏娜晓辉)请求阿里妈妈接口:{"error_response":{"code":15,"msg":"Remote service error","sub_code":"2007","sub_msg":"亲,订单开始时间至订单结束时间的时间段是60分钟,时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!","request_id":"3ppg3w1tkhay"}} - 在 Api.Framework.Cps.AlimamaApi.SendTaobaoServer(String _api, Object _data, String _appkey, String _appsecret) 位置 D:\秒单客项目\返利机器人\fl_system\类库\Api.Framework\Cps\AlimamaApi.cs:行号 569 + if (ex.Message.Contains("年货节等大促期间预估时间段不可超过")) + interval = 19; + else + throw ex; + } + } + + var isWhile = false; + do + { + //Console.WriteLine($"{this.Member.usernick} - {tk_status} - {start_time} - {page_index}/{page_size}"); + try + { + if (_rst != null && _rst.ContainsKey("data")) + { + var data = _rst["data"] as Dictionary; + //查看是否还有下一页 + if (data.ContainsKey("has_next") && data["has_next"].ToString().ToLower() != "false") + { + isWhile = true; + + #region 获取下一页数据 + + array.AddRange(GetResult(data)); + if (data.ContainsKey("position_index")) + { + var position_index = data["position_index"].ToString(); + page_index++; + if (tk_status != AlimamaOrderStatus.全部订单) + obj = new + { + query_type = 4, //查询时间类型,1:按照订单淘客创建时间查询,2:按照订单淘客付款时间查询,3:按照订单淘客结算时间查询 + page_size = page_size, //页大小 + tk_status = (int)tk_status, + start_time = start_time.ToString("yyyy-MM-dd HH:mm:ss"), + end_time = start_time.AddMinutes(interval) + .ToString( + "yyyy-MM-dd HH:mm:ss"), //这里是对应前面同步间隔的19分钟 //【订单查询结束时间,订单开始时间至订单结束时间,中间时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!】 + page_no = page_index, + position_index = position_index, + order_count_type = (int)type + }; + else + obj = new + { + query_type = 4, //查询时间类型,1:按照订单淘客创建时间查询,2:按照订单淘客付款时间查询,3:按照订单淘客结算时间查询 + page_size = page_size, //页大小 + start_time = start_time.ToString("yyyy-MM-dd HH:mm:ss"), + end_time = start_time.AddMinutes(interval) + .ToString( + "yyyy-MM-dd HH:mm:ss"), //这里是对应前面同步间隔的19分钟 //【订单查询结束时间,订单开始时间至订单结束时间,中间时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!】 + page_no = page_index, + position_index = position_index, + order_count_type = (int)type + }; + //continue; + } + + #endregion + } + else + { + //isWhile = false; + _rst.Clear(); + _rst = null; + array.AddRange(GetResult(data)); + return array; + } + + _rst = this.SendTaobao("taobao.tbk.sc.order.details.get", obj); + } + } + catch (Exception _ex) + { + throw _ex; + } + } while (isWhile); + } + catch (Exception ex) + { + throw ex; + } + + return array; + + #endregion + + } + + /// + /// 下载订单,不带状态(有多页,获取所有) + /// + /// 开始时间 + /// 第几页 + /// 页大小 + /// 阿里妈妈同步的订单类型 + /// 场景订单场景类型,1:常规订单,2:渠道订单,3:会员运营订单,默认为1 + /// + internal ArrayList DownOrder(DateTime start_time, int _page_index, int page_size, AlimamaOrderType type, + int order_scene) + { + #region 2021-08-04之后 新接口 第三版(按照订单更新时间) + + var interval = DownAlimamaTimer.GetIntervalCache(); //这个是三个小时的间隔 如果报错就用19分钟的间隔,默认179 + ArrayList array = new ArrayList(); + try + { + object obj = null; + var page_index = _page_index; + Dictionary _rst = null; + for (int i = 0; i < 2; i++) + { + try + { + obj = new + { + query_type = 4, //查询时间类型,1:按照订单淘客创建时间查询,2:按照订单淘客付款时间查询,3:按照订单淘客结算时间查询,4:按照订单更新时间; + page_size = page_size, //页大小 + start_time = start_time.ToString("yyyy-MM-dd HH:mm:ss"), + end_time = start_time.AddMinutes(interval) + .ToString( + "yyyy-MM-dd HH:mm:ss"), //这里是对应前面同步间隔的19分钟 //【订单查询结束时间,订单开始时间至订单结束时间,中间时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!】 + page_no = page_index, + order_count_type = (int)type, + order_scene = order_scene + }; + _rst = this.SendTaobao("taobao.tbk.sc.order.details.get", obj); + DownAlimamaTimer.SetIntervalCache(interval); + break; + } + catch (Exception ex) + { + //1029080089(秒单客036)请求阿里妈妈接口:{"error_response":{"code":15,"msg":"Remote service error","sub_code":"2007","sub_msg":"亲,订单开始时间至订单结束时间的时间段是60分钟,时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!","request_id":"5zjxw7z7laai"}} - 在 Api.Framework.Cps.AlimamaApi.SendTaobaoServer(String _api, Object _data, String _appkey, String _appsecret) 位置 D:\秒单客项目\返利机器人\fl_system\类库\Api.Framework\Cps\AlimamaApi.cs:行号 614 + + //29453481(魏娜晓辉)请求阿里妈妈接口:{"error_response":{"code":15,"msg":"Remote service error","sub_code":"2007","sub_msg":"亲,订单开始时间至订单结束时间的时间段是60分钟,时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!","request_id":"3ppg3w1tkhay"}} - 在 Api.Framework.Cps.AlimamaApi.SendTaobaoServer(String _api, Object _data, String _appkey, String _appsecret) 位置 D:\秒单客项目\返利机器人\fl_system\类库\Api.Framework\Cps\AlimamaApi.cs:行号 569 + + //28592081(永远圆不了)请求阿里妈妈接口:{"error_response":{"code":15,"msg":"Remote service error","sub_code":"2007","sub_msg":"亲,订单开始时间至订单结束时间的时间段是60分钟,时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!","request_id":"f87pm4x24dn2"}} - 在 Api.Framework.Cps.AlimamaApi.SendTaobaoServer(String _api, Object _data, String _appkey, String _appsecret) 位置 D:\秒单客项目\返利机器人\fl_system\类库\Api.Framework\Cps\AlimamaApi.cs:行号 614 + if (ex.Message.Contains("年货节等大促期间预估时间段不可超过")) + interval = 19; + else + throw ex; + } + } + + var isWhile = false; + do + { + //Console.WriteLine($".{this.Member.usernick} - {start_time} - {page_index}/{page_size}"); + try + { + if (_rst != null && _rst.ContainsKey("data")) + { + var data = _rst["data"] as Dictionary; + //查看是否还有下一页 + if (data.ContainsKey("has_next") && data["has_next"].ToString().ToLower() != "false") + { + isWhile = true; + + #region 获取下一页数据 + + array.AddRange(GetResult(data)); + if (data.ContainsKey("position_index")) + { + var position_index = data["position_index"].ToString(); + page_index++; + obj = new + { + query_type = 4, //查询时间类型,1:按照订单淘客创建时间查询,2:按照订单淘客付款时间查询,3:按照订单淘客结算时间查询 + page_size = page_size, //页大小 + start_time = start_time.ToString("yyyy-MM-dd HH:mm:ss"), + end_time = start_time.AddMinutes(interval) + .ToString( + "yyyy-MM-dd HH:mm:ss"), //这里是对应前面同步间隔的19分钟 //【订单查询结束时间,订单开始时间至订单结束时间,中间时间段日常要求不超过3个小时,但如618、双11、年货节等大促期间预估时间段不可超过20分钟,超过会提示错误,调用时请务必注意时间段的选择,以保证亲能正常调用!】 + page_no = page_index, + position_index = position_index, + order_count_type = (int)type + }; + //continue; + } + + #endregion + } + else + { + //isWhile = false; + _rst.Clear(); + _rst = null; + array.AddRange(GetResult(data)); + return array; + } + + _rst = this.SendTaobao("taobao.tbk.sc.order.details.get", obj); + } + } + catch (Exception _ex) + { + throw _ex; + } + } while (isWhile); + } + catch (Exception ex) + { + throw ex; + } + + return array; + + #endregion + } + + /// + /// 解析请求到的订单 + /// + /// 获取到的订单数据 + /// + private ArrayList GetResult(Dictionary data) + { + if (data != null && data.ContainsKey("results")) + { + var results = data["results"] as Dictionary; + if (results != null && results.ContainsKey("publisher_order_dto")) + return results["publisher_order_dto"] as ArrayList; + } + + return new ArrayList(); + } + + /// + /// 淘宝防屏蔽地址(不带缩短) + /// + /// 淘宝ID + /// 图片地址 + /// 淘口令 + /// 下单地址 + /// 推荐商品转链pid + /// 是否有推荐商品 + /// 自定义的目标地址 + /// + private string ComposeTbClick(string itemId, string img, string tkl, string url, string pid, bool isTuiguang, + string target = "", bool isCircleZjy = false) + { + if (!string.IsNullOrWhiteSpace(tkl)) + { + var reg = Regex.Match(tkl, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?"); + if (reg.Success) + tkl = "¥" + reg.Groups[1].Value + "¥"; + } + + if (string.IsNullOrWhiteSpace(target)) + target = string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.URLTbTkl) + ? FindTransferAddress(isCircleZjy ? TargetType.朋友圈中间页 : TargetType.淘口令) + : ApiClient.Setting.SystemConfig.URLTbTkl.Trim(); + target = target + .Replace("[关键词]", System.Web.HttpUtility.UrlEncode(tkl)) + .Replace("[口令]", "[淘口令]") + .Replace("[淘口令]", System.Web.HttpUtility.UrlEncode(tkl)) + .Replace("[宝贝ID]", itemId) + .Replace("[图片]", System.Web.HttpUtility.UrlEncode(HttpExtend.StringToBase64String(img))) + .Replace("[图片地址]", System.Web.HttpUtility.UrlEncode(img)) + .Replace("[宝贝地址]", "[地址]") + .Replace("&url=[返利链接]", "") + .Replace("[地址]", System.Web.HttpUtility.UrlEncode(url)) + .Replace("[pid]", pid) + .Replace("[tj]", isTuiguang.ToString()); + + if (target.StartsWith("https://hkl.api.52cmg.cn")) + { + var html = string.Empty; + for (int i = 0; i < 3; i++) + { + var http = new HttpHelper(); + var item = http.GetItem(target); + html = http.GetHtml(item).Html; + var json = HttpExtend.JsonToDictionary(html); + if (json != null && json["ok"].ToString().ToLower() == "true") + { + return json["message"].ToString(); + } + + continue; + } + + throw new Exception($@"gethkl:{html} +t = {target}"); + } + + return target; + } + + /// + /// 淘宝防屏蔽地址带缩短 + /// + /// 淘宝ID + /// 图片地址 + /// 淘口令 + /// 下单地址 + /// 是否缩短 + /// 缩短的枚举类型数值(-1为系统基础设置) + /// 自定义的目标地址 + /// + public string ComposeTbClick(string itemId, string img, string tkl, string url, bool isShortUrl, + int DwzType = -1, string target = "", bool isCircleZjy = false) + { + try + { + if (string.IsNullOrWhiteSpace(img)) + img = "https://img.alicdn.com/tfs/TB1MaLKRXXXXXaWXFXXXXXXXXXX-480-260.png"; + + var compose = ComposeTbClick(itemId, img, tkl, url, "", false, target, isCircleZjy); + + return GetComposeUrl(compose, isShortUrl, DwzType, target); // + } + catch (Exception ex) + { + EventClient.OnEvent(this, $@"CTC:{ex.Message} @ {ex.StackTrace}"); + } + + return string.Empty; + } + + /// + /// 淘宝防屏蔽地址(带推荐) + /// + /// 淘宝ID + /// 图片地址 + /// 淘口令 + /// 下单地址 + /// 是否缩短 + /// 推广商品转链用的推广位信息 + /// 是否推广 + /// 缩短的枚举类型数值(-1为系统基础设置) + /// 自定义的目标地址 + /// + public string ComposeTbClick(string itemId, string img, string tkl, string url, bool isShortUrl, string pid, + bool isTuiGuang, int DwzType = -1, string target = "", bool isCircleZjy = false) + { + var compose = string.Empty; + if (string.IsNullOrWhiteSpace(pid)) + compose = ComposeTbClick(itemId, img, tkl, url, isShortUrl, DwzType, target, isCircleZjy); + else + compose = ComposeTbClick(itemId, img, tkl, url, pid, isTuiGuang, target, isCircleZjy); + + return GetComposeUrl(compose, isShortUrl, DwzType, target); + } + + /// + /// 获取中间页地址 + /// + /// + /// + /// + /// + /// + private string GetComposeUrl(string compose, bool isShortUrl, int DwzType = -1, string target = "", bool isCircleZjy = false) + { + if (string.IsNullOrWhiteSpace(target)) + { + //target = + if (string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.URLTbTkl)) + { + target = FindTransferAddress(isCircleZjy ? TargetType.朋友圈中间页 : TargetType.淘口令); + } + else + { + target = ApiClient.Setting.SystemConfig.URLTbTkl.Trim(); + } + + } + + if (target.StartsWith("https://hkl.api.52cmg.cn")) + { + return compose; + } + + var dtype = Api.Framework.ApiClient.Setting.SystemConfig.dwz_type; + if (isShortUrl && DwzType != -1) + { + //Util.CheckUrlDomain(compose); + //return ApiClient.ShortURL(compose, (DwzType)DwzType).Result; + dtype = (DwzType)DwzType; + } + + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.URLTbTkl)) Util.CheckUrlDomain(compose); + return ApiClient.ShortURL(compose, dtype).Result; + } + + + /// + /// 拼接淘宝Cms地址.关键词:[推广位]、[关键词](注:小写的url编码)、[关键词U](注:大写的url编码)、 + /// + /// 推广位id + /// 搜索的关键词 + /// 拼接好的url + public string ComposeTbCms(string pid, string keyword) + { + var target = string.Empty; + if (string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.URLTbCms)) + { + target = FindTransferAddress(TargetType.产品库); + } + else + { + target = ApiClient.Setting.SystemConfig.URLTbCms.Trim(); + } + + var result = target + .Replace("[推广位]", pid) + .Replace("[关键词]", "[关键词L]") + .Replace("[关键词L]", System.Web.HttpUtility.UrlEncode(keyword)) + .Replace("[关键词U]", HttpExtend.UrlEncode(keyword)); + + return result; + } + + /// + /// 淘宝防屏蔽地址缓存 + /// + /// 请求目标类型(产品库/淘口令/订单页) + /// false获取缓存,true重新获取 + /// + public static string FindTransferAddress2(TargetType type, bool refresh = false) + { + string key = $"key_alimamaapi_composetbclick_{(int)type}"; + string target = ApiClient.Cache.Get(key); + //Console.WriteLine(type.ToString() + ",target = " + target); + if (refresh || string.IsNullOrWhiteSpace(target)) + { + for (int i = 0; i < 5; i++) + { + try + { + var ali = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈); + if (ali == null) return target; + var cps = CpsClient.CreateAlimamaRequest(ali); + if (cps == null) + { + //Console.WriteLine("cps = " + cps == null + " , " + type.ToString() + ",target = " + target); + return target; + } + target = cps.SendServer("find_wangzhi", "webTool.asmx", new { name = type.ToString() }).message.ToString(); + ApiClient.Cache.Set(key, target, 10); + break; + } + catch (Exception ex) + { + Thread.Sleep(200); + } + } + } + //Console.WriteLine(type.ToString() + ",target = " + target); + return target; + } + + internal AlimamaApi(fl_cps_member member) : base(member) + { + } + + + + #region MyRegion + + private static NoticeSocketClient _noticeSocket; + + + public static void Init() + { + _noticeSocket = new NoticeSocketClient("event.api.52cmg.cn", "tksoft"); + _noticeSocket.OnMessageEvent += NoticeSocket_OnMessageEvent; + _noticeSocket.OnConnectedEvent += NoticeSocket_OnConnectedEvent; + _noticeSocket.Connect(); + } + + //收到服务端通知 + private static void NoticeSocket_OnMessageEvent(object sender, NoticeSocketClient.AckNoticeData e) + { + try + { + LogHelper.GetSingleObj().Info("", "域名相关通知 => " + e.Data); + var data = JObject.Parse(e.Data); + if (e.CommonId == "change_tkurl") + { + var newUrl = (data["new"] ?? string.Empty).Value(); + var oldUrl = (data["old"] ?? string.Empty).Value(); + if (string.IsNullOrEmpty(newUrl) || string.IsNullOrEmpty(oldUrl)) return; + //替换查询中间页 + for (int i = 0; i < TkUrl.UrlQuery.Length; i++) + { + if (TkUrl.UrlQuery[i].IndexOf(oldUrl, StringComparison.Ordinal) != -1) + TkUrl.UrlQuery[i] = TkUrl.UrlQuery[i].Replace(oldUrl, newUrl); + } + + //替换cms网站 + for (int i = 0; i < TkUrl.UrlCms.Length; i++) + { + if (TkUrl.UrlCms[i].IndexOf(oldUrl, StringComparison.Ordinal) != -1) + TkUrl.UrlCms[i] = TkUrl.UrlCms[i].Replace(oldUrl, newUrl); + } + + ////替换提现页面 + //for (int i = 0; i < TkUrl.UrlCash.Length; i++) + //{ + // if (TkUrl.UrlCash[i].IndexOf(oldUrl, StringComparison.Ordinal) != -1) + // TkUrl.UrlCash[i] = TkUrl.UrlCash[i].Replace(oldUrl, newUrl); + //} + + //替换朋友圈中间页 + for (int i = 0; i < TkUrl.UrlCircle.Length; i++) + { + if (TkUrl.UrlCircle[i].IndexOf(oldUrl, StringComparison.Ordinal) != -1) + TkUrl.UrlCircle[i] = TkUrl.UrlCircle[i].Replace(oldUrl, newUrl); + } + } + else if (e.CommonId == "refreshTkurl") + { + RefreshTkUrl(); + } + } + catch (Exception exception) + { + EventClient.OnEvent("收到域名变化通知", $"数据:{e.Data};异常:{exception.Message}"); + } + } + + /// + /// 淘客的地址 + /// + public static TkUrlClass TkUrl { get; private set; } + + //建议连接成功后,主动再去拉一次配置(防止有时候客户端崩溃,但这个时候服务器有更新,没有收到) + private static void NoticeSocket_OnConnectedEvent(object sender, EventArgs e) + { + RefreshTkUrl(); + } + + /// + /// 刷新淘客中间页 + /// + public static void RefreshTkUrl() + { + try + { + var data = _noticeSocket.GetData("tkurl"); + LogHelper.GetSingleObj().Info("", "域名重新获取 => " + data); + if (string.IsNullOrWhiteSpace(data)) + { + throw new Exception("请求域名为空"); + } + + var rst = JsonConvert.DeserializeObject(data); + if (rst != null) TkUrl = rst; + } + catch (Exception exception) + { + EventClient.OnEvent($"获取淘客域名失败", $"{exception.Message}"); + } + } + + /// + /// 获取新的域名 + /// + /// + /// + /// + public static string FindTransferAddress(TargetType targetType, bool refresh = false) + { + if (TkUrl == null) + { + RefreshTkUrl(); + } + + switch (targetType) + { + case TargetType.产品库: + { + var _url = GetRandomUrl(TkUrl.UrlCms); + return $"{_url}/?keyword=[关键词]&pid=[推广位]"; + } + break; + case TargetType.淘口令: + { + var _url = GetRandomUrl(TkUrl.UrlQuery); + return $"{_url}/?taowords=[淘口令]&pic=[图片]&url=[地址]&pid=[pid]&tj=[tj]&item_id=[宝贝ID]"; + } + break; + case TargetType.订单页: + { + //var _url = GetRandomUrl(TkUrl.UrlCms); + //return $"{_url}/aliorder.html?key=[key]"; + + var _url = FindTransferAddress2(targetType); + return _url; + } + break; + case TargetType.朋友圈中间页: + { + var _url = GetRandomUrl(TkUrl.UrlCircle); + return $"{_url}/?taowords=[淘口令]&pic=[图片]&url=[地址]&pid=[pid]&tj=[tj]&item_id=[宝贝ID]"; + } + break; + } + + return string.Empty; + } + + /// + /// 随机取一个 + /// + /// + /// + private static string GetRandomUrl(string[] list) + { + if (list != null && list.Length > 0) + { + var r = new Random(Guid.NewGuid().GetHashCode()); + var index = r.Next(0, list.Length); + return list[index]; + } + return string.Empty; + } + + #endregion + + /// + /// 会员推广位为列表 + /// + /// 第几页 + /// 页大小 + /// + internal Dictionary VipAdzoneManage(int topage, int pagesize) + { + var _tb_token_ = string.Empty; + var reg = Regex.Match(Member.cookies, "_tb_token_=([^;]+)"); + if (reg.Success) + _tb_token_ = reg.Groups[1].Value; + var _url = $"https://pub.alimama.com/common/adzone/adzoneList.json?type=2&t={HttpExtend.GetTimeStamp()}&_tb_token_={_tb_token_}&pvid="; + var http = new HttpHelper(); + var item = http.GetItem(_url, Member.cookies); + var html = http.GetHtml(item).Html; + if (html.Contains("没有权限")) + { + try + { + Clipboard.SetDataObject("https://survey.taobao.com/apps/zhiliao/0JpI9eizU"); + } + catch (Exception ex) + { } + throw new Exception($@"{Member.usernick},您还没有申请权限哦 +申请地址已经复制,请在网页中打开"); + } + //EventClient.OnEvent("", "html = " + html); + var _dic = HttpExtend.JsonToDictionary(html); + if (_dic == null) throw new Exception($"{Member.usernick},此接口需要访问阿里妈妈官网,登录已过期请重新登录阿里妈妈!"); + if (_dic["ok"].ToString().ToLower() == "false") throw new Exception(html); + _dic = _dic["data"] as Dictionary; + + return _dic; + } + + /// + /// 普通推广位列表 + /// + /// 第几页 + /// 页大小 + /// + public Dictionary AdzoneManage(int topage, int pagesize) + { + var _url = $"https://pub.alimama.com/common/adzone/adzoneManage.json?tab=3&toPage={topage}&perPageSize={pagesize}&gcid=8&t={HttpExtend.GetTimeStamp()}&_input_charset=utf-8"; + var http = new HttpHelper(); + var item = http.GetItem(_url, Member.cookies); + var html = http.GetHtml(item).Html; + var _dic = HttpExtend.JsonToDictionary(html); + if (_dic == null) throw new Exception($"{Member.usernick},此接口需要访问阿里妈妈官网,登录已过期请重新登录阿里妈妈!"); + if (_dic["ok"].ToString().ToLower() == "false") throw new Exception(html); + _dic = _dic["data"] as Dictionary; + + return _dic; + } + + private static DateTime NextTime = DateTime.MinValue; + + /// + /// 检测淘宝优惠券 + /// + /// 优惠券地址 + /// + public Coupon CheckCoupon(string coupon_click_url) + { + string html = string.Empty; + try + { + if (coupon_click_url.Contains("coupon/details") || coupon_click_url.Contains("coupon/edetail")) + { + Coupon c = new Coupon(); + coupon_click_url = coupon_click_url.Replace("coupon/details", "cp/coupon/").Replace("coupon/edetail", "cp/coupon/"); + var http = new HttpHelper(); + + for (int i = 0; i < 4; i++) + { + if (NextTime > DateTime.Now) + return null; + + var item = http.GetItem(coupon_click_url); + item.Timeout = 30000; + item.ReadWriteTimeout = 20000; + item.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0"; + item.ContentType = "application/x-www-form-urlencoded"; + item.SetProxyipCDN(); + html = http.GetHtml(item).Html.Replace("\\", ""); + if (html.Contains("亲,小二正忙,滑动一下马上回来") || html.Contains("操作超时") || html == @"{""success"": false}") + { + if (i == 3) + { + NextTime = DateTime.Now.AddMinutes(2); + return null; + } + Thread.Sleep(500); + continue; + } + + var _obj = HttpExtend.JsonToDictionary(html);//转成字典 + if (_obj != null) + { + _obj = _obj["result"] as Dictionary; + _obj.ConvertToObj(c); + if (c.retStatus == 1) continue; + _obj = _obj["item"] as Dictionary; + if (_obj["clickUrl"] != null) _obj["clickUrl"] = "http:" + _obj["clickUrl"].ToString(); + if (_obj["shareUrl"] != null) _obj["shareUrl"] = "http:" + _obj["shareUrl"].ToString(); + _obj.ConvertToObj(c); + if (c.retStatus == 2 || c.retStatus == 0 || c.retStatus == 4) return c; + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $@"检查优惠券异常:{ex.Message} @ {ex.StackTrace} +html => {html}"); + } + return null; + } + + /// + /// 获得HTML + /// + /// 请求的地址 + /// post数据 + /// referer的地址 + /// + private string GetAlimamaHtml(string url, string postData = "", string referer = "http://pub.alimama.com/myunion.htm") + { + try + { + //Console.WriteLine(url); + Thread.Sleep(300 + random.Next(700, 1000)); + + HttpHelper _http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = string.IsNullOrEmpty(postData) ? "get" : "post", + IsToLower = false, + Cookie = Member.cookies, + Referer = referer, + Postdata = postData, + Timeout = 3000, + ReadWriteTimeout = 3000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = true, + ProtocolVersion = System.Net.HttpVersion.Version11 + }; + //item.SetProxyipCDN(); + var result = _http.GetHtml(item); + //Console.WriteLine($"{result.Html} - {result.Cookie}"); + if (!string.IsNullOrEmpty(result.Cookie)) + { + this.Member.cookies = result.UpdateCookies(this.Member.cookies); + } + return result.Html; + } + catch (Exception) + { } + return string.Empty; + } + + /// + /// 随机数对象 + /// + private static Random random = new Random(); + + /// + /// 更新阿里妈妈Cookies + /// + internal void UpdateCookies() + { + GetAlimamaHtml("http://www.alimama.com/index.htm"); + GetAlimamaHtml("https://ssp.tanx.com/api/userinfo?callback=userInfoCallback"); + GetAlimamaHtml("http://ssp.tanx.com/api/userinfo?callback=userInfoCallback"); + GetAlimamaHtml("https://media.alimama.com/user/base_info.htm"); + GetAlimamaHtml("https://media.alimama.com/verify/risk.htm"); + GetAlimamaHtml("https://media.alimama.com/"); + GetAlimamaHtml("https://media.alimama.com/product.htm"); + + GetAlimamaHtml("https://pub.alimama.com/myunion.htm"); + GetAlimamaHtml("https://tbk.bbs.taobao.com/list.html"); + GetAlimamaHtml("https://pub.alimama.com/manage/overview/index.htm"); + + GetAlimamaHtml("https://pub.alimama.com/common/getUnionPubContextInfo.json"); + + var page = random.Next(1, 5); + var size = page * 10; + GetAlimamaHtml($"https://media.alimama.com/violationu2/violation2_page.json?r=mx_794&toPage={page}&pageSize=40"); + + if (page % 2 != 0) + { + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/adzone.htmhttps://pub.alimama.com/third/manage/record/site.htm?tab=self_web_site");//媒体备案管理 - 自有平台(网站) + if (page == 3) + GetAlimamaHtml($"https://pub.ama.com/third/manage/record/site.htm?tab=self_web_site&sencecode=self_app&pageNo=1&pageSize=50");//媒体备案管理 - 自有平台(App客户端) + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/site.htm?tab=self_web_site&sencecode=self_pc_client&pageNo=1&pageSize=50");//媒体备案管理 - 自有平台(PC客户端) + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/site.htm?tab=self_web_site&sencecode=self_offline&pageNo=1&pageSize=50");//媒体备案管理 - 自有平台(线下阵地) + } + else + { + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/adzone.htm");//推广位 + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/site.htm?tab=all");//媒体备案管理 - 全部 + if (page == 2) + { + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/site.htm?tab=self_web_site&sencecode=self_miniprogram&pageNo=1&pageSize=50");//媒体备案管理 - 自有平台(小程序/快应用) + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/site.htm?tab=self_web_site&sencecode=self_operating_system&pageNo=1&pageSize=50");//媒体备案管理 - 自有平台(操作系统) + } + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/site.htm?tab=self_web_site&sencecode=self_hardware_device&pageNo=1&pageSize=50");//媒体备案管理 - 自有平台(硬件设备) + } + GetAlimamaHtml($"https://pub.alimimama.com/third/manage/record/site.htm?tab=other_social");//媒体备案管理 - 他方平台(社交平台) + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/site.htm?tab=other_social&sencecode=other_content&pageNo=1&pageSize=50");//媒体备案管理 - 他方平台(内容平台) + + GetAlimamaHtml($"https://pub.alimama.com/third/manage/record/site.htm?tab=traffic_purchasing");//媒体备案管理 - 无自有阵地 + + GetAlimamaHtml("http://c.tanx.com/"); + + for (int i = 0; i < 2; i++) + { + GetAlimamaHtml($"https://pub.alimama.com/openapi/json2/1/gateway.unionpub/xt.entry.json", $"t={HttpExtend.GetTimeStamp()}000&_tb_token_=33183160110853659822%3A34758%2C%22variableMap%22%3A%7B%22itemId%22%3A%22{(Util.GetRandomString(12))}%22%7D%7D");//内容库查询 + } + + + GetAlimamaHtml($"https://pub.alimama.com/manage/user/new_privilege.htm"); + + for (int i = 0; i < 3; i++) + { + var punishStatus = random.Next(1, 9); + + page = random.Next(1, 5); + size = page * 10; + + GetAlimamaHtml($"https://media.alimama.com/violationu2/violation2_page.json?toPage={page}&pageSize={size}&punishStatus={punishStatus}"); + } + + GetAlimamaHtml($"https://pub.alimama.com/manage/overview/index.htm"); + + for (int i = 0; i < 3; i++) + { + var type = random.Next(1, 4); + var day = random.Next(1, 16); + var date1 = DateTime.Now.Date.AddDays(-day).ToString("yyyy-MM-dd"); + var date2 = DateTime.Now.Date.ToString("yyyy-MM-dd"); + GetAlimamaHtml($"https://pub.alimama.com/openapi/param2/1/gateway.unionpub/report.getTbkOrderDetails.json?t={HttpExtend.GetTimeStamp()}000&_tb_token_=33183d55eb1e6&jumpType=0&positionIndex=&pageNo=1&startTime={date1}&endTime={date2}&queryType={type}&tkStatus=&memberType=&pageSize=40"); + } + + CheckLoginAlimama(); + + GetAlimamaHtml("https://pub.alimama.com/common/getUnionPubContextInfo.json"); + + GetAlimamaHtml($"https://media.alimama.com/violationu2/warning_instance_page.json?r=mx_544&toPage={page}&pageSize={size}"); + + GetAlimamaHtml($"https://everyservice.cdn.taobao.com/widget/queryServiceStrategy"); + GetAlimamaHtml($"https://everyhelp.taobao.com/version/getWidgetVersion"); + GetAlimamaHtml($"https://media.alimama.com/violation/violation_list.htm"); + + CheckLoginAlimama(); + + GetAlimamaHtml("https://c.tanx.com/"); + } + + /// + /// 检测登录阿里妈妈 + /// + /// + internal bool CheckLoginAlimama() + { + try + { + var dic = GetUnionPubContextInfo(this.Member.cookies); + if (dic != null) + { + if (dic.ContainsKey("memberID")) + return true; + else return false; + } + else return true; + } + catch (Exception ex) + { + return false; + } + } + + /// + /// 阿里妈妈同步的订单类型 + /// + internal enum AlimamaOrderType : int + { + 淘客明细订单 = 1, + 第三方订单明细 = 2 + } + + /// + /// 阿里妈妈订单状态 + /// + public enum AlimamaOrderStatus : int + { + 全部订单 = 1, + 订单结算 = 3, + 订单付款 = 12, + 订单失效 = 13, + 订单成功 = 14, + 订单维权中 = 15, + } + + //public enum AlimamaOrderSort : int + //{ + // 创建时间 = 1, + // 结算时间 = 2 + //} + + /// + /// 请求目标类型 产品库/淘口令/订单页 + /// + public enum TargetType : int + { + 淘口令 = 1, + 产品库 = 2, + 订单页 = 3, + 朋友圈中间页 = 4 + } + + } +} diff --git a/类库/Api.Framework/Cps/BaseCpsApi.cs b/类库/Api.Framework/Cps/BaseCpsApi.cs new file mode 100644 index 0000000..27845f0 --- /dev/null +++ b/类库/Api.Framework/Cps/BaseCpsApi.cs @@ -0,0 +1,246 @@ +//============================================================= +// 创建人:千年老妖 +// 本页代码,均为原创。对未经许可擅自使用者,本人保留追究其法律责任的权利。 +//============================================================== +using Api.Framework.Model; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Cps +{ + /// + /// CpsApi基础类 + /// + public class BaseCpsApi + { + /// + /// cps数据对象 + /// + public fl_cps_member Member { get; protected set; } + private CpsToken _token = null; + + private static SynchronizedDictionary Tokens = new SynchronizedDictionary(); + + /// + /// 删除Token缓存 + /// + internal void ClearToken() + { + string key = $"{Member.username}_{(int)Member.cpstype}"; + if (Tokens.ContainsKey(key)) Tokens.Remove(key); + _token = null; + } + + /// + /// 获取重新获取token + /// + /// + internal CpsToken GetToken() + { + try + { + for (int i = 0; i <= 5; i++) + { + var result = SendServer("get_token", new { username = Member.username, enc_result = true }); + if (result != null) + { + if (result.ok) + { + return HttpHelper.JsonToObject(result.message.ToString()) as CpsToken; + } + else + return null; + } + Thread.Sleep(15); + } + } + catch (Exception ex) + { + throw ex; + } + return null; + } + + /// + /// 重新获取Token + /// + /// + internal bool RefToken() + { + #region 老妖xxx + //try + //{ + // int number = 0; + //Next: + // number++; + // var result = SendServer("get_token", new { username = Member.username, enc_result = true }); + // if (result == null && number <= 5) + // { + // Thread.Sleep(10); + // goto Next; + // } + // _token = HttpHelper.JsonToObject(result.message.ToString()) as CpsToken; + + // if (_token != null) + // { + // string key = $"{Member.username}_{(int)Member.cpstype}"; + // if (Tokens.ContainsKey(key)) Tokens.Add(key, _token); + // else Tokens[key] = _token; + // } + //} + //catch (Exception ex) + //{ + // throw ex; + //} + #endregion + + #region 老道 + try + { + var new_token = GetToken(); + if (new_token == null) return false; + + //本机没有值,拉取服务器Token + if (_token == null) + { + _token = new_token; + SetToken(_token); + if (Member != null) Member.is_valid = true; + return true; + } + else + { + //和本机一致,返回False 表示没有新Token + if (_token.access_token == new_token.access_token) + return false; + _token = new_token; + SetToken(_token); + if (Member != null) + Member.is_valid = true; + return true; + } + } + catch (Exception ex) + { + throw ex; + } + finally + { + LogHelper.GetSingleObj().Debug("", $"唯品会获取新的Token: username = {_token?.username},appid = {_token?.appid},access_token = {_token?.access_token}"); + } + #endregion + return false; + } + + /// + /// 设置Token + /// + /// + private void SetToken(CpsToken cpsToken) + { + if (cpsToken != null) + { + string key = $"{Member.username}_{(int)Member.cpstype}"; + if (!Tokens.ContainsKey(key)) Tokens.Add(key, cpsToken); + else Tokens[key] = cpsToken; + } + } + + /// + /// 操作Token + /// + internal CpsToken Token + { + get + { + if (_token == null) + { + string key = $"{Member.username}_{(int)Member.cpstype}"; + if (Tokens.ContainsKey(key)) _token = Tokens[key]; + else RefToken(); + } + return _token; + } + } + + internal BaseCpsApi(fl_cps_member member) + { + this.Member = member; + //if (this.Member.cpstype == Enums.CpsType.阿里妈妈) + //{ + // this.RefToken(); + //} + } + + /// + /// 请求报文 + /// + /// + /// + /// + /// + public WebResult SendServer(string method, string target = "", object param = null) + { + if (string.IsNullOrEmpty(target)) + { + var type = this.GetType(); + if (type == typeof(AlimamaApi)) target = "alimama.asmx"; + else if (type == typeof(PinduoduoApi)) target = "pinduoduo.asmx"; + else if (type == typeof(JingdongApi)) target = "jingdong.asmx"; + else if (type == typeof(WeipinhuiApi)) target = "weipinhui.asmx"; + else if (type == typeof(DouyinApi)) target = "douyin.asmx"; + else if (type == typeof(KuaiShouApi)) target = "kuaishou.asmx"; + else throw new Exception("暂时不支持类型:" + target); + } + + AuthEndpoint end = new AuthEndpoint() + { + Appid = CpsClient._appid, + Enckey = CpsClient._key, + Host = CpsClient._host + "api/" + target + "/send_data", + Method = method + }; + + if (param != null) + { + var _param = param.GetType().GetProperties(); + foreach (var item in _param) + { + end.Param[item.Name] = item.GetValue(param); + } + } + HttpHelper http = new HttpHelper(); + try + { + //var ss = http.SendData(end); + return http.SendData(end); + } + catch (Exception ex) + { + if (ex.Message == "未将对象引用设置到对象的实例。") + return null; + else + throw ex; + } + } + + /// + /// 发送API数据 + /// + /// API接口 + /// 参数 + /// + public WebResult SendServer(string method, object param = null) + { + return SendServer(method, "", param); + } + + } +} diff --git a/类库/Api.Framework/Cps/CefSharp1/BaseResult.cs b/类库/Api.Framework/Cps/CefSharp1/BaseResult.cs new file mode 100644 index 0000000..938edb9 --- /dev/null +++ b/类库/Api.Framework/Cps/CefSharp1/BaseResult.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Cps.CefSharp1 +{ + public class BaseResult + { + public BaseResult() + { + MsgId = new Random(Guid.NewGuid().GetHashCode()).Next().ToString(); + } + + public string MsgId { get; set; } + + public string Json { get; set; } + + } +} diff --git a/类库/Api.Framework/Cps/CefSharp1/BrowserAndLoginInfo.cs b/类库/Api.Framework/Cps/CefSharp1/BrowserAndLoginInfo.cs new file mode 100644 index 0000000..32880ce --- /dev/null +++ b/类库/Api.Framework/Cps/CefSharp1/BrowserAndLoginInfo.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Cps.CefSharp1 +{ + public class BrowserAndLoginInfo + { + public LoginInfo loginInfo { get; set; } + + public BrowseInfo browseInfo { get; set; } + + public string session_id { get; set; } + + public long event_index { get; set; } + } + + public class LoginInfo + { + public string user_unique_id { get; set; } + + public int user_type { get; set; } + + public string user_id { get; set; } + + public string web_id { get; set; } + + public string ssid { get; set; } + } + + public class BrowseInfo + { + public int app_id { get; set; } + public string os_name { get; set; } + public string os_version { get; set; } + public string device_model { get; set; } + public string language { get; set; } + public string platform { get; set; } + public string sdk_version { get; set; } + public string sdk_lib { get; set; } + public int timezone { get; set; } + public int tz_offset { get; set; } + public string resolution { get; set; } + public string browser { get; set; } + public string browser_version { get; set; } + public string referrer { get; set; } = string.Empty; + public string referrer_host { get; set; } = string.Empty; + public int width { get; set; } + public int height { get; set; } + public int screen_width { get; set; } + public int screen_height { get; set; } + public object custom { get; set; } = new { }; + } + +} diff --git a/类库/Api.Framework/Cps/CefSharp1/CEFRequestHandler.cs b/类库/Api.Framework/Cps/CefSharp1/CEFRequestHandler.cs new file mode 100644 index 0000000..e5f761c --- /dev/null +++ b/类库/Api.Framework/Cps/CefSharp1/CEFRequestHandler.cs @@ -0,0 +1,290 @@ +using Api.Framework.Cps.CefSharp1; +using CefSharp; +using CefSharp.WinForms; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Cps.CefSharp1 +{ + internal class CefSharpOpenPageSelf : ILifeSpanHandler + { + public bool DoClose(IWebBrowser browserControl, IBrowser browser) + { + return false; + } + public void OnAfterCreated(IWebBrowser browserControl, IBrowser browser) + { + } + public void OnBeforeClose(IWebBrowser browserControl, IBrowser browser) + { + } + public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser) + { + newBrowser = null; + var chromiumWebBrowser = (ChromiumWebBrowser)browserControl; + chromiumWebBrowser.Load(targetUrl); + return true; //Return true to cancel the popup creation copyright by codebye.com. + } + } + + /// + /// 拦截请求 + /// + public class CEFRequestHandler : IRequestHandler + { + public event Action JsonAction; + public event Action BrowserAndLoginInfoAction; + + public IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling) + { + //if (request.PostData != null) + //{ + // var bytes1 = request.PostData.Elements[0].Bytes; + // var postStr1 = System.Text.Encoding.UTF8.GetString(bytes1); + // Console.WriteLine("@@@@@@@@@@@@@@@@@@@@@@@ = " + postStr1); + //} + + //"https://buyin.jinritemai.com/api/author/order/details?author_app_id=1128&user_id=1460607342872671&start_time=1606806032&end_time=1609398032&time_type=1&page=1&pageSize=20&_signature=_02B4Z6wo00101Zp7NtAAAIDCpf2A9b4M3iGafzJAAAZ8DhdlaobXsro5mjL-ohtCATVjsCaDIQPNiWIbrQwGsR5suxHYJOJ2oQ6unSqn.loaNiMcqo.PA4VvXk0FA8ueolBWm739wlv1HXZ637" + if (request.Url.Contains("buyin.jinritemai.com/api/author/order/details")) + { + //var time1 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now.AddDays(-1)); + //var time2 = CsharpHttpHelper.HttpExtend.GetTimeStamp(); + //request.Url = $"https://buyin.jinritemai.com/api/author/order/details?author_app_id=1128&user_id=1460607342872671&start_time={time1}&end_time={time2}&time_type=1&page=1&pageSize=20&_signature=_02B4Z6wo00101Zp7NtAAAIDCpf2A9b4M3iGafzJAAAZ8DhdlaobXsro5mjL-ohtCATVjsCaDIQPNiWIbrQwGsR5suxHYJOJ2oQ6unSqn.loaNiMcqo.PA4VvXk0FA8ueolBWm739wlv1HXZ637"; + + } + + if (request.Url.Contains("https://mcs.snssdk.com/v1/list")) + { + if (request.PostData.Elements != null && request.PostData.Elements.Count != 0) + { + var bytes = request.PostData.Elements[0].Bytes; + var postStr = System.Text.Encoding.UTF8.GetString(bytes); + if (!string.IsNullOrWhiteSpace(postStr)) + { + Console.WriteLine(postStr + " &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"); + + BrowseInfo bInfo = null; + LoginInfo lInfo = null; + var session_id = string.Empty; + long event_index = -1; + + var jArrs = JArray.Parse(postStr); + var jObj = jArrs[0]; + if (jObj["user"] != null) + { + var user = jObj["user"]; + if (user != null) + { + /* + "user_unique_id": "6978842327024550185", + "user_type": 12, + "user_id": "1460607342872671", + "web_id": "6988302958481098274", + "ssid": "25c4c89c-ccce-4061-baa7-ebe593d425fc" + */ + if (user["user_unique_id"] != null && user["user_type"] != null && user["user_id"] != null && user["web_id"] != null && user["ssid"] != null) + { + var user_unique_id = user["user_unique_id"].ToString(); + var user_type = (int)user["user_type"]; + var user_id = user["user_id"].ToString(); + var web_id = user["web_id"].ToString(); + var ssid = user["ssid"].ToString(); + + lInfo = new LoginInfo() { ssid = ssid, user_id = user_id, user_type = user_type, user_unique_id = user_unique_id, web_id = web_id }; + } + } + } + if (jObj["header"] != null) + { + var header = jObj["header"]; + if (header != null) + { + /* + "app_id": 2631, + "os_name": "windows", + "os_version": "8", + "device_model": "Windows NT 6.2", + "language": "en-US", + "platform": "web", + "sdk_version": "4.1.53_2", + "sdk_lib": "js", + "timezone": 8, + "tz_offset": -28800, + "resolution": "1920x1080", + "browser": "Chrome", + "browser_version": "91.0.4472.114", + "referrer": "", + "referrer_host": "", + "width": 1920, + "height": 1080, + "screen_width": 1920, + "screen_height": 1080, + "custom": "{}" + */ + + if (header["app_id"] != null && + header["os_name"] != null && + header["os_version"] != null && + header["device_model"] != null && + header["language"] != null && + header["platform"] != null && + header["sdk_version"] != null && + header["sdk_lib"] != null && + header["timezone"] != null && + header["tz_offset"] != null && + header["browser"] != null && + header["browser_version"] != null && + header["referrer"] != null && + header["referrer_host"] != null && + header["width"] != null && + header["height"] != null && + header["screen_width"] != null && + header["height"] != null && + header["screen_height"] != null && + header["resolution"] != null) + { + var app_id = (int)header["app_id"]; + var os_name = header["os_name"].ToString(); + var os_version = header["os_version"].ToString(); + var device_model = header["device_model"].ToString(); + var language = header["language"].ToString(); + var platform = header["platform"].ToString(); + var sdk_version = header["sdk_version"].ToString(); + var sdk_lib = header["sdk_lib"].ToString(); + var timezone = (int)header["timezone"]; + var tz_offset = (int)header["tz_offset"]; + var browser1 = header["browser"].ToString(); + var browser_version = header["browser_version"].ToString(); + var referrer = header["referrer"].ToString(); + var referrer_host = header["referrer_host"].ToString(); + var width = (int)header["width"]; + var height = (int)header["height"]; + var screen_width = (int)header["screen_width"]; + var height1 = header["height"].ToString(); + var screen_height = (int)header["screen_height"]; + var resolution = header["resolution"].ToString(); + + + bInfo = new BrowseInfo() { app_id = app_id, browser = browser1, browser_version = browser_version, device_model = device_model, height = height, language = language, os_name = os_name, os_version = os_version, platform = platform, referrer = referrer, referrer_host = referrer_host, resolution = resolution, screen_height = screen_height, screen_width = screen_width, sdk_lib = sdk_lib, sdk_version = sdk_version, timezone = timezone, tz_offset = tz_offset, width = width }; + } + } + } + + if (jObj["events"] != null) + { + var events = (JArray)jObj["events"]; + if (events != null && events.Count != 0) + { + if (events[0]["session_id"] != null) + session_id = events[0]["session_id"].ToString(); + if (events[0]["params"] != null) + { + var jObjTmp = JObject.Parse(events[0]["params"].ToString()); + if (jObjTmp["event_index"] != null) + event_index = long.Parse(jObjTmp["event_index"].ToString()); + } + } + } + + if (lInfo != null && bInfo != null && !string.IsNullOrWhiteSpace(session_id) && event_index != -1) + { + var b = new BrowserAndLoginInfo() { browseInfo = bInfo, loginInfo = lInfo, session_id = session_id, event_index = event_index }; + BrowserAndLoginInfoAction?.Invoke(b); + } + } + } + } + + + return new CEFResponseHandler(JsonAction); + } + + public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) + { + //var url = new Uri(request.Url); + //if (url.AbsoluteUri.Contains("http://www.baidu.com")) + //{ + // //自定义的IResponseFilter,这里是按照官方文档的示例 + // var filter = CEFFilterManger.CreateFilter(request.Identifier.ToString()); + // return filter; + //} + return null; + } + private void Filter_VOIDFUN(string arg1, string arg2, string arg3, long arg4) + { + + } + public bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, + bool isRedirect) + { + return false; + } + public CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback) + { + return CefReturnValue.Continue; + } + public bool OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback) + { + return true; + } + public bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture) + { + return false; + } + public void OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath) + { + } + public bool OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url) + { + return false; + } + public bool OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize, IRequestCallback callback) + { + return false; + } + public void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status) + { + } + public void OnRenderViewReady(IWebBrowser browserControl, IBrowser browser) + { + } + public void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength) + { + } + public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, ref string newUrl) + { + } + public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl) + { + } + public bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response) + { + return false; ; + } + public bool OnSelectClientCertificate(IWebBrowser browserControl, IBrowser browser, bool isProxy, string host, int port, X509Certificate2Collection certificates, ISelectClientCertificateCallback callback) + { + return true; + } + + public bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect) + { + return false; + } + + public void OnDocumentAvailableInMainFrame(IWebBrowser chromiumWebBrowser, IBrowser browser) + { + } + + public bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback) + { + return false; + } + } +} diff --git a/类库/Api.Framework/Cps/CefSharp1/CEFResponseHandler.cs b/类库/Api.Framework/Cps/CefSharp1/CEFResponseHandler.cs new file mode 100644 index 0000000..81db955 --- /dev/null +++ b/类库/Api.Framework/Cps/CefSharp1/CEFResponseHandler.cs @@ -0,0 +1,55 @@ +using CefSharp; +using CefSharp.Handler; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Cps.CefSharp1 +{ + /// + /// 拦截响应数据 + /// + public class CEFResponseHandler : ResourceRequestHandler + { + Action JsonAction; + public CEFResponseHandler(Action JsonAction) + { + this.JsonAction = JsonAction; + } + + private readonly System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(); + + protected override IResponseFilter GetResourceResponseFilter(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response) + { + var sss = new CefSharp.ResponseFilter.StreamResponseFilter(memoryStream); + return sss; + } + + protected override void OnResourceLoadComplete(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength) + { + //You can now get the data from the stream + var bytes = memoryStream.ToArray(); + //var str1 = System.Text.Encoding.UTF8.GetString(bytes); + //Console.WriteLine(str1 + " = str1"); + + //if (str1.Contains("优芙")) + //{ + + //} + + //https://buyin.jinritemai.com/api/author/order/details?author_app_id=1128&user_id=1460607342872671&start_time=1625036432&end_time=1625641232&time_type=1&page=1&pageSize=20&_signature=_02B4Z6wo00101S-ErAQAAIDCEAIaIFYsB.0vgKiAACsHDhdlaobXsro5mjL-ohtCATVjsCaDIQPNiWIbrQwGsR5suxHYJOJ2oQ6unSqn.loaNiMcqo.PA4VvXk0FA8ueolBWm739wlv1HXZ64a + if (response.Charset == "utf-8" && request.Url.Contains("buyin.jinritemai.com/api/author/order/details?")) + { + var str = System.Text.Encoding.UTF8.GetString(bytes); + + JsonAction?.Invoke(request.Url, str); + } + else + { + //Deal with different encoding here + } + } + } +} diff --git a/类库/Api.Framework/Cps/CefSharp1/CookieVisitor.cs b/类库/Api.Framework/Cps/CefSharp1/CookieVisitor.cs new file mode 100644 index 0000000..134d9bc --- /dev/null +++ b/类库/Api.Framework/Cps/CefSharp1/CookieVisitor.cs @@ -0,0 +1,26 @@ +using CefSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Cps.CefSharp1 +{ + public class CookieVisitor : ICookieVisitor + { + public event Action SendCookie; + public void Dispose() + { } + + public bool Visit(Cookie cookie, int count, int total, ref bool deleteCookie) + { + deleteCookie = false; + if (SendCookie != null) + { + SendCookie(cookie); + } + return true; + } + } +} diff --git a/类库/Api.Framework/Cps/CefSharp1/DouyinSendOrder.cs b/类库/Api.Framework/Cps/CefSharp1/DouyinSendOrder.cs new file mode 100644 index 0000000..088e9e3 --- /dev/null +++ b/类库/Api.Framework/Cps/CefSharp1/DouyinSendOrder.cs @@ -0,0 +1,138 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Cps.CefSharp1 +{ + class DouyinSendOrder + { + } + + public class DouyinPackHist : IRunable + { + public DouyinPackHist() + { + ThreadExcutor.RegisterIntervalObject(this, this, 1000 * 60, false); + } + class Pack + { + public DateTime CreateTime { get; set; } + public BaseResult BaseResult { get; set; } + } + //private object mPackDicObj = new object(); + private Dictionary mPackDic = new Dictionary(); + + public bool IsRunning { get; set; } + + public RegisteredWaitHandle RegisterdHandler { get; set; } + public WaitHandle WaitHandler { get; set; } + + private BaseResult _GetResultMsg(string msgId) + { + try + { + lock (mPackDic) + { + //Thread.Sleep(10); + BaseResult buf = null; + try + { + if (mPackDic.ContainsKey(msgId)) + { + buf = mPackDic[msgId].BaseResult; + mPackDic.Remove(msgId); + return buf; + } + } + catch (Exception ee) + { } + return buf; + } + } + catch (Exception) + { + } + return null; + } + + public void Run(object state, bool timedOut) + { + if (IsRunning) return; + try + { + IsRunning = true; + var t = DateTime.Now.AddMinutes(-5); + var list = mPackDic.ToList().Where(f => f.Value.CreateTime < t);//5分钟前的包,直接忽略 + foreach (var item in list) if (mPackDic.ContainsKey(item.Key)) mPackDic.Remove(item.Key); + } + catch (Exception) + { } + finally + { + IsRunning = false; + } + } + + public void Dispose() + { + + } + /// + /// 设置接收数据包 + /// + /// + /// + public void SetResult(BaseResult msg) + { + try + { + lock (mPackDic) + { + Console.WriteLine("add" + msg.MsgId); + if (mPackDic.ContainsKey(msg.MsgId)) mPackDic.Add(msg.MsgId, new Pack() { BaseResult = msg }); + else mPackDic[msg.MsgId] = new Pack() { BaseResult = msg }; + } + } + catch (Exception) + { } + } + + /// + /// 获取接收数据包 + /// + /// msgId + /// + public Task GetResult(string _msg_id) + { + var msg_id = _msg_id; + return Task.Factory.StartNew(delegate () + { + try + { + Console.WriteLine($"get {msg_id}"); + DateTime end_time = DateTime.Now.AddSeconds(5); + while (end_time > DateTime.Now) + { + var r = _GetResultMsg(msg_id); + + if (r != null) return r; + Thread.Sleep(20); + } + } + catch (Exception) + { + + } + return null; + }); + } + } + public class DouyinPool + { + public static DouyinPackHist PackHist { get; private set; } = new DouyinPackHist(); + } +} diff --git a/类库/Api.Framework/Cps/CpsToken.cs b/类库/Api.Framework/Cps/CpsToken.cs new file mode 100644 index 0000000..bb18334 --- /dev/null +++ b/类库/Api.Framework/Cps/CpsToken.cs @@ -0,0 +1,23 @@ +//============================================================= +// 创建人:千年老妖 +// 本页代码,均为原创。对未经许可擅自使用者,本人保留追究其法律责任的权利。 +//============================================================== +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Cps +{ + /// + /// CpsToken类 + /// + internal class CpsToken + { + public string username { get; set; } + public string appid { get; set; } + public string appkey { get; set; } + public string access_token { get; set; } + } +} diff --git a/类库/Api.Framework/Cps/DouyinApi.cs b/类库/Api.Framework/Cps/DouyinApi.cs new file mode 100644 index 0000000..a3b4e61 --- /dev/null +++ b/类库/Api.Framework/Cps/DouyinApi.cs @@ -0,0 +1,2877 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using Api.Framework.EntityTmp.Douyin; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Microsoft.ClearScript.V8; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Api.Framework.Cps +{ + /// + /// 抖音订单状态 + /// + public enum DouyinOrderStatus : int + { + 全部订单 = 1, + SETTLE = 2,//结算 + PAY_SUCC = 3,//订单付款 + REFUND = 5,//退款/失效 + 订单维权中 = 6, + CONFIRM = 7,//确定收货 + } + public class DouyinApi : BaseCpsApi + { + internal DouyinApi(fl_cps_member member) : base(member) { } + + #region 接口 + /// + /// 添加商品至橱柜 + /// + private const string AddGoods_WindowUrl = @"https://buyin.jinritemai.com/pc/selection/window/pmt/add?_signature={0}"; + + /// + /// 口令解析地址 + /// + //private const string AnalysisCmdUrl = @"https://aweme.snssdk.com/aweme/v2/platform/share/command/trans/?command={0}&support_type=16&os_api=22&device_type=MI+9&ssmix=a&manifest_version_code=160201&dpi=320&uuid=863254393831028&app_name=aweme&version_name=16.2.0&ts={1}&cpu_support64=false&app_type=normal&appTheme=dark&ac=wifi&host_abi=armeabi-v7a&update_version_code=16209900&channel=tengxun_1128_0531&_rticket=1624938653257&device_platform=android&iid=3466131644356413&version_code=160200&cdid={2}&is_android_pad=0&openudid=0347cf3f47c211af&device_id=1478167560454807&resolution=900*1600&os_version=5.1.1&language=zh&device_brand=Xiaomi&aid=1128&minor_status=0&mcc_mnc=46007"; + + private const string AnalysisCmdUrl = @"https://aweme.snssdk.com/aweme/v2/platform/share/command/trans/?command={0}"; + + /// + /// 橱窗商品列表搜索地址 + /// + private const string ShopWindowUrl = @"https://buyin.jinritemai.com/api/shop/search?hide_status=0&promotion_source=0&title={0}&page=1&pageSize=20&_signature={1}"; + + /// + /// 搜索关键词 + /// + private const string SearchUrl = @"https://buyin.jinritemai.com/pc/selection/search/pmt?page=1&page_size=60&search_text="; + + public static fl_cps_member GetUserInfo(string html, string ck) + { + try + { + var jObj = JObject.Parse(html); + if (jObj != null && jObj["code"] != null) + { + var db = ApiClient.GetSession(); + var code = jObj["code"].ToString(); + if (code == "0") + { + #region 获取用户信息 + + var shop_id = jObj["data"]["shop_id"].ToString(); + if (shop_id == "0") + throw new Exception($@"该账号未开通商品分享功能,请开通后重试 + +注:开通电商权限,需要同时满足以下4个条件 +①、账号实名认证 +②、个人主页视频数(公开且审核通过)≥ 10 条 +③、账号粉丝量(绑定第三方粉丝量不计数)≥ 1000 +④、商品分享保证金 ¥500立即充值"); + + var uname = jObj["data"]["buyin_account_id"].ToString(); + + var m = db.Queryable().First(f => f.cpstype == CpsType.抖音联盟 && f.username == uname); + if (m == null) + m = new fl_cps_member(); + m.cookies = ck; + m.usernick = jObj["data"]["shop_name"].ToString(); + //LoginUserId = jObj["data"]["user_id"].ToString(); + m.username = uname; + m.logintime = DateTime.Now; + + m.online = true; + m.is_valid = true; + m.cpstype = CpsType.抖音联盟; + return m; + #endregion + } + else if (code == "401") + { + if (jObj["msg"].ToString() == "请重新登录") + { + throw new Exception("填写的Cookice无效,请填写有效的cookice"); + } + } + else + throw new Exception($"其他:{jObj["msg"].ToString()}"); + } + } + catch (Exception ex) + { + throw ex; + } + return null; + } + + /// + /// 通过推广id获取商品id + /// + /// 推广id + /// + internal string GetProductIdByPromotionid(string promotion_id) + { + try + { + if (!string.IsNullOrWhiteSpace(promotion_id)) + { + var db = ApiClient.GetSession(); + var cps = CpsClient.Members.FirstOrDefault(f => f.online && f.cpstype == CpsType.抖音联盟); + if (cps != null) + { + var goodsInfo = FindGoodsInfo(promotion_id); + if (goodsInfo != null) + { + if (goodsInfo != null && goodsInfo.msg != "用户未登录") + { + //没有查到返利提示 + //if (goodsInfo == null || goodsInfo.data == null || goodsInfo.data.promotions == null || goodsInfo.data.promotions.Count != 1)//这里goodsInfo.data.promotions.Count要是不等于1,说明这个不能查询到精确的商品 + if (goodsInfo == null || goodsInfo.data == null || goodsInfo.msg == "商品没有推广信息" || goodsInfo.code != 0) + { } + else + return goodsInfo.data.product_id; + } + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"通过推广id获取商品id: +promotion_id = {promotion_id}"); + throw ex; + } + return string.Empty; + } + + /// + /// 将抖音口令解析成商品id + /// + /// 要解析的口令 + /// + internal static string AnalysisCmdToGoodsUrl(string kl, out string promotion_id, out string title) + { + title = string.Empty; + promotion_id = string.Empty; + var html = string.Empty; + try + { + var analysisCmdUrl = string.Format(AnalysisCmdUrl, HttpHelper.URLEncode(kl), HttpExtend.GetTimeStamp(), Guid.NewGuid().ToString()) + $"&sign={HttpExtend.GetMD5String(Guid.NewGuid().ToString("N"))}"; + + for (int i = 0; i < 3; i++) + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = analysisCmdUrl, + Method = "get", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "text/html", + Allowautoredirect = false, + ProxyIp = "", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + html = result.Html; + if (html.Contains("status_code")) + { + var jobj = JObject.Parse(html); + if (jobj["status_code"].ToString() == "0") + break; + } + Thread.Sleep(200); + } + var jObj = JObject.Parse(html); + if (html.Contains("title")) + { + var reg = Regex.Match(html, @"""title"":""(?<标题>.+?)"",", RegexOptions.IgnoreCase); + if (reg.Success) + title = reg.Groups["标题"].Value; + } + if (html.Contains("schema")) + { + var schema = HttpHelper.URLDecode(jObj["schema"].ToString()); + + var reg = Regex.Match(schema, @"promotion_id=(?<推广id>\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + { + var promotion_id_tmp = reg.Groups["推广id"].Value;//临时 + reg = Regex.Match(schema, @"item_id=(?<商品id>\d+)"); + if (reg.Success) + { + var groupid = reg.Groups["商品id"].Value; + if (groupid == "0")//某种情况下该item_id为0的时候,promotion_id为商品id + { + groupid = promotion_id_tmp; + var cps = CpsClient.Members.FirstOrDefault(f => f.online && f.cpstype == CpsType.抖音联盟); + if (cps == null) return string.Empty; + string goodid = new DouyinApi(cps).GetPromotionId(groupid, out promotion_id); + if (!string.IsNullOrWhiteSpace(goodid)) + { + return goodid; + //goodid = new DouyinApi(cps).GetPromotionId(groupid, out promotion_id, out title); + } + } + } + else + { + reg = Regex.Match(schema, @"product_id=(?<商品id>\d+)"); + if (reg.Success) + { + var product_id = reg.Groups["商品id"].Value; + if (!string.IsNullOrWhiteSpace(product_id) && product_id != "0") + { + if (promotion_id_tmp == product_id) + { + promotion_id = string.Empty; + return product_id; + } + else + { + promotion_id = promotion_id_tmp; + return product_id; + } + } + } + //promotion_id = promotion_id_tmp; + } + promotion_id = promotion_id_tmp; + } + return promotion_id; + } + else + { + //{\"status_code\":4,\"status_msg\":\"啊哦,服务器打瞌睡了,再试一次吧~\",\"log_pb\":{\"impr_id\":\"202203231247040102081051452B082DD6\"}} + + LogHelper.GetSingleObj().Error("抖音返利", $@"抖音口令解析_: +kl:{kl} + +html = {html}"); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"抖音口令解析异常:{ex.Message} - {ex.StackTrace} +kl:{kl} + +html = {html}"); + throw ex; + } + finally + { + + + LogHelper.GetSingleObj().Debug("抖音返利调试", $@"抖音口令解析 +html = {html}"); + } + return string.Empty; + } + + /// + /// 获取推广id + /// + /// + /// + /// + /// + public string GetPromotionId(string goodid, out string promotion_id, out string title) + { + promotion_id = string.Empty; + title = string.Empty; + //var param = $"urls=https:{HttpExtend.UrlEncode($"//haohuo.jinritemai.com/views/product/item2?id={goodid}")}"; + var param = $"urls=https://haohuo.jinritemai.com/views/product/item2?id={goodid}"; + var sign = GetSign(param, Member.other); + if (!string.IsNullOrWhiteSpace(sign)) + param = $"{param}&_signature={sign}"; + + var xb = GetXbogus(param, Member.other); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/api/shop/batchLink?{param}&X-Bogus={xb}", + Method = "GET", + Timeout = 20000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "text/html", + Referer = "https://buyin.jinritemai.com/dashboard/shopwindow/goods-list", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String,//返回数据类型,是Byte还是String + }; + HttpResult result = http.GetHtml(item); + + string html = result.Html; + + if (!string.IsNullOrWhiteSpace(html)) + { + try + { + var jObj = JObject.Parse(html); + if (jObj["msg"].ToString() == "success") + { + if (jObj["data"] != null) + { + var batch_shop_manage_promotions = (JArray)jObj["data"]["batch_shop_manage_promotions"]; + if (batch_shop_manage_promotions != null && batch_shop_manage_promotions.Count != 0) + { + var good = batch_shop_manage_promotions[0]; + var promotionIdTmp = good["promotion_id"].ToString(); + if (!string.IsNullOrWhiteSpace(promotionIdTmp)) + { + promotion_id = good["promotion_id"].ToString(); + goodid = good["product_id"].ToString(); + title = good["title"].ToString(); + return goodid; + } + } + //这里可能商品id为推广id + promotion_id = goodid; + return string.Empty; + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"抖音解析推广id和商品id一致异常:{ex.Message} - {ex.StackTrace} +商品id: {goodid},推广id: {promotion_id} + +html = {html}"); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利调试", $@"抖音解析推广id和商品id一致 +商品id: {goodid},推广id: {promotion_id} + +html = {html}"); + } + } + return string.Empty; + } + + + public string GetPromotionId(string goodid, out string promotion_id) + { + promotion_id = string.Empty; + var title = string.Empty; + //var param = $"urls=https:{HttpExtend.UrlEncode($"//haohuo.jinritemai.com/views/product/item2?id={goodid}")}"; + var param = $"urls=https://haohuo.jinritemai.com/views/product/item2?id={goodid}"; + var sign = GetSign(param, Member.other); + if (!string.IsNullOrWhiteSpace(sign)) + param = $"{param}&_signature={sign}"; + + var xb = GetXbogus(param, Member.other); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/api/shop/batchLink?{param}&X-Bogus={xb}", + Method = "GET", + Timeout = 20000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "text/html", + Referer = "https://buyin.jinritemai.com/dashboard/shopwindow/goods-list", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + + string html = result.Html; + + if (!string.IsNullOrWhiteSpace(html)) + { + try + { + var jObj = JObject.Parse(html); + if (jObj["msg"].ToString() == "success") + { + if (jObj["data"] != null) + { + var batch_shop_manage_promotions = (JArray)jObj["data"]["batch_shop_manage_promotions"]; + if (batch_shop_manage_promotions != null && batch_shop_manage_promotions.Count != 0) + { + var good = batch_shop_manage_promotions[0]; + var promotionIdTmp = good["promotion_id"].ToString(); + if (!string.IsNullOrWhiteSpace(promotionIdTmp)) + { + promotion_id = good["promotion_id"].ToString(); + goodid = good["product_id"].ToString(); + title = good["title"].ToString(); + return goodid; + } + } + //这里可能商品id为推广id + promotion_id = goodid; + return string.Empty; + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"抖音解析推广id和商品id一致异常:{ex.Message} - {ex.StackTrace} +商品id: {goodid},推广id: {promotion_id} + +html = {html}"); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利调试", $@"抖音解析推广id和商品id一致 +商品id: {goodid},推广id: {promotion_id} + +html = {html}"); + } + } + return string.Empty; + } + + + ///// + ///// 获取抖音链接中的商品ID + ///// + ///// + ///// + ///// + ///// + //public string GetDyGoodsID(string message, out string promotion_id) + //{ + // promotion_id = string.Empty; + + // var goodid = DYHelper.GetDyGoodsID(message, out promotion_id); + + // if (!string.IsNullOrWhiteSpace(goodid) && !string.IsNullOrWhiteSpace(promotion_id)) + // goodid = GetProductIdByPromotionid(promotion_id); + // return goodid; + //} + + public string GetDyGoodsID(string mess, out string promotion_id, out string title) + { + title = string.Empty; + return GetDyGoodsID(mess, out promotion_id); + } + + #region 抖音原始信息解析 新 + + public string GetDyGoodsID(string mess, out string promotion_id) + { + promotion_id = string.Empty; + try + { + var product_id = string.Empty; + + #region + if (string.IsNullOrWhiteSpace(mess) || + Regex.IsMatch(mess, @"\[图片=(.+?)\]") || + Regex.IsMatch(mess, @"\[视频=(.+?)\]") || + Regex.IsMatch(mess, @"\[卡片=(.+?)\]") || + Regex.IsMatch(mess, @"\[公告=(.+?)\]") || + Regex.IsMatch(mess, @"\[语音=(.+?)\]") + ) + return string.Empty; + #endregion + + bool flag = false; + if (mess.ToLower().Contains("goods_id")) flag = true; + + mess = Regex.Replace(mess, "v.douyin.com", "https://v.douyin.com", RegexOptions.IgnoreCase);//抖音短链接,没有前缀 + //获取链接的正则表达式 + var _url = Regex.Match(mess.Replace("&", "&"), HttpExtend.REGEX_GETURL, RegexOptions.IgnoreCase); + + //是否需要解析 + var IsResolved = false; + + //之前的拿不到promotion_id,就先不处理 这种连接: https://haohuo.jinritemai.com/views/product/item2?id=3479881104721353508 + #region 新的 + if (!flag && _url.Success)//有链接的情况 + { + mess = _url.Groups["链接"].Value; + if (Regex.IsMatch(mess, "http[s]?://haohuo.", RegexOptions.IgnoreCase)) + { + if (mess == null || !mess.Contains("?id=")) return string.Empty; + else + { + var reg = Regex.Match(mess, @"\?id=(?\d{4,})", RegexOptions.IgnoreCase); + if (reg.Success) + { + promotion_id = product_id = reg.Groups["product_id"].Value; + IsResolved = true; + } + } + } + else if (Regex.IsMatch(mess, "http[s]?://www.iesdouyin.", RegexOptions.IgnoreCase)) + { + if (mess == null || mess.ToLower().Contains("object_id=")) + { + var reg = Regex.Match(mess, @"object_id=(?:\d+?)_(?\d+?)_(?\d+?)_(?:\d+?)", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + //https://www.iesdouyin.com/?schema_type=20&object_id=1460607342872671_3508329772335892947_3508329411592229101_0 + promotion_id = reg.Groups["promotion_id"].ToString(); + return reg.Groups["goodid"].ToString(); + } + } + else flag = true; + } + else if (Regex.IsMatch(mess, "(http[s]?://)?v.douyin.com", RegexOptions.IgnoreCase))//链接: https://v.douyin.com/LbN2pka/ + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = mess, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + }; + HttpResult result = http.GetHtml(item); + + mess = result.Html; + flag = true; + } + else + flag = true; + } + #endregion + + if (flag) + { + var regUrl = Regex.Match(mess, @"(yukhj\.com|m\.tb\.cn|m\.yeeoq\.top|m\.uqlsi|m\.rijni|m\.gkqmj|m\.mulwt|uland\.taobao\.com|sjtm\.me|aa5d\.com|d11a\.com|f61[a-z]\.com|92db\.com|yqt\.so|e22a\.com|f61b\.com|detail\.m\.tmall.hk|k\.83jie\.com|ewqcxz\.com|items\.alitrip\.com|tmqd\.me|detail\.tmall\.hk|url\.cn|taobao\.com|mashort\.cn|tmall\.com|tb\.cn|detail\.yao\.95095\.com|laiwang\.com|dwz\.cn|juhuasuan\.com|detail\.m\.tmall\.com|zmnxbc\.com|s\.click\.taobao|detail\.liangxinyao\.com|m\.tb\.cn)", RegexOptions.IgnoreCase); + if (!regUrl.Success) + { + var messTmp = HttpHelper.URLDecode(HttpHelper.URLDecode(mess)).Replace("&", "&"); + var reg = Regex.Match(messTmp, @"\?id=(?\d+)&alkey=\d+?_\d+?_\d+?_(?\d+)_\d+?", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + var product_id1 = reg.Groups["product_id1"].Value; + var product_id2 = reg.Groups["product_id2"].Value; + if (product_id1 == product_id2)//商品id准确的 + { + //获取promotion_id + product_id = GetPromotionId(product_id1, out promotion_id); + if (!string.IsNullOrWhiteSpace(product_id) && !string.IsNullOrWhiteSpace(promotion_id)) + { + if (product_id == product_id1) + return product_id; + } + } + } + + reg = Regex.Match(messTmp, @"alkey=\d+?_\d+?_\d+?_(?\d+)_\d+?", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + //promotion_id + promotion_id = product_id = reg.Groups["product_id"].Value; + IsResolved = true; + } + else + { + + } + + //这里可能还有其他的可能 + } + } + else + { + var title = string.Empty; + //var regs1 = Regex.Matches(mess, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?"); + var reg = Regex.Match(mess, "([︽#]{2}[A-Za-z0-9]{11,14}[︽#]{2})"); + if (reg.Success) + { + product_id = DouyinApi.AnalysisCmdToGoodsUrl(reg.Groups[1].Value, out promotion_id, out title); + IsResolved = true; + } + } + + if (IsResolved) + { + if (!string.IsNullOrWhiteSpace(product_id)) + { + //大概率上面的正则拿到的是商品id,先判断商品id + var promotion_idTmp = string.Empty; + var product_idTmp = GetPromotionId(product_id, out promotion_idTmp); + if (string.IsNullOrWhiteSpace(product_idTmp)) + { + var goodInfo = FindGoodsInfo(promotion_id ?? promotion_idTmp); + if (goodInfo != null && goodInfo.data.promotion_id != goodInfo.data.product_id)//返回的数据要是一致的话,就直接用推广的id查询商品 + { + promotion_id = goodInfo.data.promotion_id; + product_id = goodInfo.data.product_id; + } + else + { + return product_id; + } + } + else if (!string.IsNullOrWhiteSpace(product_idTmp) && !string.IsNullOrWhiteSpace(promotion_idTmp)) + { + promotion_id = promotion_idTmp; + product_id = product_idTmp; + } + if (product_id != promotion_id) + { + return product_id; + } + } + else + { + + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音解析", ex.Message + " - " + ex.StackTrace); + throw ex; + } + return string.Empty; + } + #endregion + + /// + /// 通过商品链接查询商品信息 + /// + /// 商品id + /// 返回商品的基础信息 + public DouyinGoodsInfo FindGoodsInfo(string goodsId) + { + if (string.IsNullOrWhiteSpace(goodsId)) return null; + var html = string.Empty; + try + { + var param = $"promotion_id={goodsId}"; + var sign = GetSign(param, Member.other); + if (!string.IsNullOrWhiteSpace(sign)) + param = $"{param}&_signature={sign}"; + + var xb = GetXbogus(param, Member.other); + + var searchUrl = $"https://buyin.jinritemai.com/pc/decision/detail?"; + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = $"{searchUrl}{param}&X-Bogus={xb}", + Method = "get", + IsToLower = false, + Cookie = Member.cookies, + Referer = "https://buyin.jinritemai.com/dashboard/shopwindow/goods-list", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = Member.other, + ContentType = "application/json", + Allowautoredirect = false, + ProxyIp = "", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + html = result.Html; + + //{"code":0,"st":0,"msg":"","data":{"promotions":[{"promotion_id":"3473786827197053067","product_id":"3473587162723782872","title":"【象牙塔】爆款 厚实桌面手机支架 随意旋转上下调节","cover":{"uri":"temai/e7ea85383a76fe7cec7390407fdfa984www1099-1015","url_list":["http://p3.pstatp.com/aweme/720x720/temai/e7ea85383a76fe7cec7390407fdfa984www1099-1015.jpeg","http://pb9.pstatp.com/aweme/720x720/temai/e7ea85383a76fe7cec7390407fdfa984www1099-1015.jpeg","http://pb3.pstatp.com/aweme/720x720/temai/e7ea85383a76fe7cec7390407fdfa984www1099-1015.jpeg"]},"detail_url":"https://haohuo.jinritemai.com/views/product/item2?id=3473587162723782872","promotion_source":4,"brand_icon":{"url_list":["http://p3.pstatp.com/origin/db00001bcc4cfde8d96a"]},"price":990,"market_price":1900,"cos_fee":495,"cos_ratio":5000,"month_sales":7020,"shop_id":14065420,"shop_name":"象牙塔","exp_score":"4.5","in_promotion":true,"in_shop":false,"sales":0}],"has_more":false,"search_id":"6979517724091285760"},"total":1,"log_id":"20210630173326010198066204044B8F51"} + var goodsInfo = JsonConvert.DeserializeObject(html); + if (goodsInfo != null && goodsInfo.msg == "用户未登录") + throw new Exception("商品不存在"); + //没有查到返利提示 + if (goodsInfo == null || goodsInfo.data == null || goodsInfo.msg == "商品没有推广信息" || goodsInfo.code != 0) + throw new Exception("商品不存在"); + return goodsInfo; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"goodsId = {goodsId} ,查询商品信息异常,{ex.Message} +st:{ex.StackTrace} + +html = {html}"); + Thread.Sleep(500 + new Random(Guid.NewGuid().GetHashCode()).Next(500, 1000)); + throw new Exception(ex.Message); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利调试", $@"goodsId = {goodsId} ,查询商品信息 +html = {html}"); + } + return null; + } + + /// + /// 绑定关系 + /// + /// + /// + public bool BindGoods(string product_id, string promotion_id) + { + var html = string.Empty; + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "https://buyin.jinritemai.com/api/shop/bind", + Method = "head", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = "Opera/9.27 (Windows NT 5.2; U; zh-cn)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "text/json", + Referer = "https://buyin.jinritemai.com/api/shop/bind", + Allowautoredirect = true, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + item.Header.Add("x-secsdk-csrf-request", "1"); + HttpResult result = http.GetHtml(item); + Member.cookies = result.UpdateCookies(Member.cookies); + + var token = string.Empty; + if (result.Header.AllKeys.Contains("x-ware-csrf-token")) + { + token = result.Header["x-ware-csrf-token"]; + //0,000100000001eaa646767f8d6256ebdfd102948baa96304b4ac337509303bc3337f980350b5416d1c078c655906c,86370000,success + token = token.Split(',')[1]; + + var postdata = @"{""pmts"":[{""promotion_id"":""" + promotion_id + @""",""bind_source"":""0"",""link_url"":""https://haohuo.jinritemai.com/views/product/item2?id=" + product_id + @"""}],""hide_status"":2}"; + + var sign = GetSign("", Member.other, postdata); + + var param = string.Empty; + if (!string.IsNullOrWhiteSpace(sign)) + param = $"_signature={sign}"; + + var xb = GetXbogus(param, Member.other, postdata); + + http = new HttpHelper(); + item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/api/shop/bind/?X-Bogus={xb}&{param}", + Method = "POST", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "https://buyin.jinritemai.com/dashboard/shopwindow/goods-list", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = postdata, + ResultType = ResultType.String,//返回数据类型,是Byte还是String + }; + item.Header.Add("x-secsdk-csrf-token", token);//设置请求头信息(Header) + result = http.GetHtml(item); + + Member.cookies = Member.cookies.SimpleCookies(); + + html = result.Html; + //{"st":0,"code":0,"msg":"成功添加1件商品至橱窗","log_id":"202202091007460101501661640711ACE3","data":{"success_count":1,"failure_count":0,"failure_list":[]}} + //{"st":0,"code":0,"msg":"成功添加0件商品至橱窗","log_id":"202202081526040101501480791706D0B6","data":{"success_count":0,"failure_count":1,"failure_list":[{"bind_status":1,"bind_msg":"绑定失败","bind_reason":"获取推广信息失败","product_id":"","title":""}]}} + if (string.IsNullOrWhiteSpace(html)) + return false; + + var jObj = JObject.Parse(html); + var success_count = (int)jObj["data"]["success_count"]; + if (success_count > 0) + { + return true; + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"商品id = {product_id}, 推广id = {promotion_id} ,添加商品到橱柜异常:{ex.Message} +st:{ex.StackTrace} + +html = {html}"); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利调试", $@"商品id = {product_id}, 推广id = {promotion_id} ,添加商品到橱柜 +html = {html}"); + } + + return false; + } + + + /// + /// 添加商品至橱柜 + /// + /// 商品id + /// + public bool AddGoodsWindowUrl(string goodsid) + { + var html = string.Empty; + for (int i = 0; i < 3; i++) + { + try + { + var sign = "";//抖音TODO 这个可以为空 + var addGoods_WindowUrl = string.Format(AddGoods_WindowUrl, sign); + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = addGoods_WindowUrl, + Method = "POST", + Timeout = 10000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "https://buyin.jinritemai.com/dashboard/merch-picking-hall", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = $"product_id={goodsid}&item_type=4&pick_first_source=%E7%99%BE%E5%BA%94&pick_second_source=%E9%80%89%E5%93%81%E5%B9%BF%E5%9C%BA&pick_third_source=search&pick_source_id=", + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + + //{"code":0,"st":0,"msg":"success","error_type":0,"data":{},"log_id":"202107011223480101980650882E822E5B"} + html = result.Html; + var jObj = JObject.Parse(html); + if (html.Contains("code")) + { + var code = (int)jObj["code"]; + if (code == 0) + { + if (jObj["msg"].ToString().ToLower() == "success") + return true; + } + /* + {"code":-3581,"st":0,"msg":"","error_type":2,"data":{"guide_info":{"title":"开通收款账户","content":"您已提交过资质认证,收款账户还未开通完成,开通完成后可添加商品,请前往移动端商品橱窗-常用服务-升级账户完成开通","confirm_text":"立即开通","cancel_text":"暂不开通","guide_link":"aweme://webview/?url=https%3A%2F%2Ffxg.jinritemai.com%2Fh5%2Fshop%2Fsettle%2Fperson%3Fstatus_bar_color%3Dffffff%26loading_bgcolor%3Dffffff\u0026status_bar_color=ffffff\u0026loading_bgcolor=ffffff"}},"log_id":"202111081303580101311300260A047903"} + */ + else + { + EventClient.OnEvent("抖音返利", $@"添加橱窗异常:{html}"); + } + } + else + { + LogHelper.GetSingleObj().Debug("抖音返利", $@"商品id = {goodsid} ,添加商品到橱柜返回:html = {html}"); + } + Thread.Sleep(500 + new Random(Guid.NewGuid().GetHashCode()).Next(500, 1000)); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"商品id = {goodsid} ,添加商品到橱柜异常:{ex.Message} +st:{ex.StackTrace} + +html = {html} +"); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利调试", $@"商品id = {goodsid} ,添加商品到橱柜 +html = {html} +"); + } + Thread.Sleep(500); + } + return false; + } + + /// + /// 删除橱柜商品 + /// + /// 推广id + /// + public bool DelGoodsWindowUrl(string promotion_id) + { + var html = string.Empty; + for (int i = 0; i < 2; i++) + { + try + { + var postdata = $"promotion_id={promotion_id}"; + var sign = GetSign("", Member.other, postdata); + + var param = string.Empty; + if (!string.IsNullOrWhiteSpace(sign)) + param = $"_signature={sign}"; + + var xb = GetXbogus(param, Member.other, postdata); + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/api/shop/unbind?X-Bogus={xb}&{param}", + Method = "POST", + Timeout = 10000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "https://buyin.jinritemai.com/dashboard/merch-picking-hall", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = postdata, + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + + //{"code":0,"st":0,"msg":"success","error_type":0,"data":{},"log_id":"202107011223480101980650882E822E5B"} + html = result.Html; + var jObj = JObject.Parse(html); + if (html.Contains("code")) + { + var code = (int)jObj["code"]; + if (code == 0) + { + if (jObj["msg"].ToString().ToLower() == "success") + return true; + } + else + { + LogHelper.GetSingleObj().Error("抖音返利", $@"删除橱窗异常:{html}"); + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"商品推广id = {promotion_id} ,删除商品到橱柜异常:{ex.Message} +st:{ex.StackTrace} + +html = {html}"); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利调试", $@"商品推广id = {promotion_id} ,删除商品到橱柜 +html = {html}"); + } + Thread.Sleep(1000); + } + return false; + } + + /// + /// 删除橱柜商品 + /// + /// 推广id + /// + public bool DelGoodsWindowUrls(List promotion_ids) + { + var html = string.Empty; + for (int i = 0; i < 2; i++) + { + try + { + var pids = string.Join("%2C", promotion_ids); + + var postdata = $"promotion_ids={pids}"; + + //var sign = GetSign("", Member.other, postdata); + //var param = string.Empty; + //if (!string.IsNullOrWhiteSpace(sign)) + // param = $"_signature={sign}"; + + //var xb = GetXbogus(param, Member.other, postdata); + + //var xb = GetXbogus("", Member.other); + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/api/shop/batchUnbind", + Method = "POST", + Timeout = 10000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "https://buyin.jinritemai.com/dashboard/merch-picking-hall", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = postdata, + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + + //{"code":0,"st":0,"msg":"success","error_type":0,"data":{},"log_id":"202107011223480101980650882E822E5B"} + html = result.Html; + var jObj = JObject.Parse(html); + if (html.Contains("code")) + { + var code = (int)jObj["code"]; + if (code == 0) + { + if (Regex.IsMatch(jObj["msg"].ToString(), @"成功删除\d+个商品")) + return true; + } + else + { + LogHelper.GetSingleObj().Error("抖音返利", $@"删除所有商品橱窗异常:{html}"); + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"删除橱窗商品列表:{string.Join(",", promotion_ids)}"); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利", $@"删除橱窗商品列表:{string.Join(",", promotion_ids)}"); + } + Thread.Sleep(1000); + } + return false; + } + + /// + /// 删除橱柜商品 + /// + /// 推广id + /// + public List FindGoodsWindowUrls(out int total) + { + total = 0; + List list = new List(); + var html = string.Empty; + for (int i = 0; i < 2; i++) + { + try + { + var param = "hide_status=0&page=1&pageSize=20&promotion_source=0"; + var sign = GetSign(param, Member.other); + //param = $"{param}&_signature={sign}"; + + if (!string.IsNullOrWhiteSpace(sign)) + param = $"{param}&_signature={sign}"; + + var xb = GetXbogus(param, Member.other); + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/api/shop/search?{param}&X-Bogus={xb}", + Method = "Get", + Timeout = 10000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "https://buyin.jinritemai.com/dashboard/shopwindow/goods-list", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + //if (!string.IsNullOrWhiteSpace(result.Cookie)) + //{ + // Member.cookies = HttpHelper.GetSmallCookie(result.UpdateCookies(Member.cookies)); + //} + //Member.cookies = result.UpdateCookies(Member.cookies); + //{"code":0,"st":0,"msg":"success","error_type":0,"data":{},"log_id":"202107011223480101980650882E822E5B"} + html = result.Html; + if (!string.IsNullOrWhiteSpace(html)) + { + var regs = Regex.Matches(html, @"promotion_id"":\s?""(?\d+)""", RegexOptions.IgnoreCase); + for (int z = 0; z < regs.Count; z++) + { + list.Add(regs[z].Groups["promotion_id"].Value); + } + var reg = Regex.Match(html, @"""total"":\s?(?\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + total = int.Parse(reg.Groups["total"].Value); + return list; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"获取橱窗商品列表异常,{ex.Message}"); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利", $@"获取橱窗商品列表:{string.Join(",", list)}"); + } + Thread.Sleep(1000); + } + return list; + } + + /// + /// 通过商品id查询橱柜中的商品,获取推广链接 + /// + /// 商品id + /// + public string GetShopWindow_PromotionUrlToGoodsId(string goodsid) + { + var html = string.Empty; + try + { + for (int i = 0; i < 10; i++) + { + var param = $@"hide_status=0&promotion_source=0&title={goodsid}&page=1&pageSize=20"; + var sign = GetSign(param, Member.other); + //var sign = string.Empty; + + if (!string.IsNullOrWhiteSpace(sign)) + param = $"{param}&_signature={sign}"; + + var xb = GetXbogus(param, Member.other); + + var searchUrl = "https://buyin.jinritemai.com/api/shop/search?"; + + var ck = Member.cookies; + + //ck = CkRelpace(ck, ""); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = $"{searchUrl}{param}&X-Bogus={xb}", + //URL = $"{searchUrl}{param}", + Method = "get", + IsToLower = false, + Cookie = ck, + Referer = "https://buyin.jinritemai.com/dashboard/shopwindow/goods-list", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*",// 可选项有默认值 + ContentType = "application/json",//返回类型 可选项有默认值 + Allowautoredirect = false, + ProxyIp = "", + ResultType = ResultType.String, + Host = "buyin.jinritemai.com" + //IsUpdateCookie = true + }; + + item.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2"); + item.Header.Add("Accept-Encoding", "deflate"); + //item.Header["Connection"] = "keep-alive"; + //item.Header.Add("Sec-Fetch-Dest", "empty"); + //item.Header.Add("Sec-Fetch-Mode", "cors"); + //item.Header.Add("Sec-Fetch-Site", "same-origin"); + //item.Header.Add("TE", "trailers"); + + HttpResult result = http.GetHtml(item); + html = result.Html; + //Console.WriteLine(); + //continue; + #region 数据结构 + //{"code":0,"data":[{"promotion_id":"3461130275701011777","product_id":"3454352531717751823","promotion_source":4,"coupon_amount":"","price":9990,"cos_fee":3996,"cos_ratio":40,"title":" 【辉腾】直播落地支架 直播支架 直播落地三脚架 户外落地支架","detail_url":"https://haohuo.jinritemai.com/views/product/item2?id=3454352531717751823\u0026origin_type=2002170010\u0026origin_id=1460607342872671_3461130275701011777\u0026alkey=1128_1460607342872671_0_3461130275701011777_011\u0026sec_author_id=MS4wLjABAAAAEnpGkVpQS-WLtu18Me9lZ-9A284xvNbstU-HGyQK3vn2Pi-WtDWPRAXLCnSRvDsF\u0026buyin_track=COgIEN-Q0K6ijcwCGgQIABAAIgAoj4iI8LXqlPgvMAE\u0026c_biz_combo=2","cover":"temai/c9a03a89407ec53f6dc06fb949a9a7bcwww800-800","images":["temai/c9a03a89407ec53f6dc06fb949a9a7bcwww800-800","temai/bd81e0f3a80b8ef97228454fcd243157www800-800","temai/7575df4d88e28769e16ebd13ec48c14awww800-800","temai/0bdd668c8dad2dd2605dc62b51b9f509www800-800","temai/b25524e60b62f6b768995a2c4910cd91www800-800"],"elastic_title":"","elastic_images":["temai/c9a03a89407ec53f6dc06fb949a9a7bcwww800-800","temai/bd81e0f3a80b8ef97228454fcd243157www800-800","temai/7575df4d88e28769e16ebd13ec48c14awww800-800","temai/0bdd668c8dad2dd2605dc62b51b9f509www800-800","temai/b25524e60b62f6b768995a2c4910cd91www800-800"],"ies_category":12,"sales":0,"pic_audit_status":null,"brand_icon":"","original_promotion_source":0,"cos_type":0,"cos_type_name":"","live_elastic_title":"","full_discount":[],"shop_label":null,"shop_id":9868340,"tax_price":0,"is_haitao":false,"hide_status":2,"pool_type":"","industry_cid":7,"industry_cname":"智能家居"}],"extra":{"log_id":"2021070109250001019806620216778C63","now":1625102701000},"msg":"success","st":0,"total":1} + #endregion + + var jObj = JObject.Parse(html); + if (html.Contains("code")) + { + var code = (int)jObj["code"]; + if (code == 0) + { + var jArr = (JArray)jObj["data"]; + if (jArr.Count != 0) + { + var jTok = jArr[0]; + return jTok["detail_url"].ToString(); + } + + } + else if (code == 9001) + { + //LogHelper.GetSingleObj().Debug("抖音下载", $"html={html},出验证码了.正在滑块"); + if (i % 3 == 0 && result.Header.AllKeys.Contains("X-Buyin-Sec-Verify-Code")) + { + var VerifyCode = result.Header["X-Buyin-Sec-Verify-Code"].ToString(); + var webId = SlidingBlock(Member.cookies, VerifyCode); + if (!string.IsNullOrWhiteSpace(webId)) + { + Member.cookies = CkRelpace(Member.cookies, webId); + ApiClient.GetSession().Saveable(Member).ExecuteCommand(); + continue; + } + } + else + throw new Exception(html); + } + } + else + { + LogHelper.GetSingleObj().Debug("抖音返利", $@"goodsid = {goodsid} ,{html}"); + } + Thread.Sleep(1000); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("抖音返利", $@"获取推广链接异常:{ex.Message} +st:{ex.StackTrace} + +html = {html}"); + } + finally + { + LogHelper.GetSingleObj().Debug("抖音返利调试", $@"获取推广链接 goodsid:{goodsid} +html = {html}"); + } + return string.Empty; + } + + private static string CkRelpace(string ck, string wVWebId) + { + ck = Regex.Replace(ck, "(;s_v_web_id=[^;]+)", ""); + ck += wVWebId; + return ck; + } + + + public static string GetLoginUserInfo(string cookies, string UserAgent) + { + try + { + //var sign = GetSign("", UserAgent); + var param = string.Empty; + + //if (!string.IsNullOrWhiteSpace(sign)) + // param = $"_signature={sign}"; + + var xb = GetXbogus(param, UserAgent); + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/index/getUser?X-Bogus={xb}", + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookies, + UserAgent = UserAgent, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "https://buyin.jinritemai.com/dashboard?new_enter_from=", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + + var json = string.Empty; + for (int i = 0; i < 5; i++) + { + var data = http.GetHtml(item); + json = data.Html; + var jObj = JObject.Parse(json); + if (jObj != null && jObj["code"] != null) + { + if ((int)jObj["code"] != 0) + { + Thread.Sleep(500); + continue; + } + break; + } + } + + if (!string.IsNullOrWhiteSpace(json)) + { + return json; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("获取抖音用户信息异常", ex.Message); + } + return string.Empty; + } + + + /// + /// 关键词搜索商品(请求有限制) + /// + /// + /// + public string SearchGoodsToKeyWord(string keyword) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = SearchUrl + keyword, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + + return html; + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 推广连接 + /// + /// + /// + /// + public string GetPromotionUrl(string goodid, string promotion_id) + { + return $"https://www.iesdouyin.com/?schema_type=20&object_id={Member.username}_{promotion_id}_{goodid}_0"; + } + + public List DownOrder(DateTime start_time, DateTime end_time, int _page_index, DouyinQueryOrderType type) + { + int num = 0; + Next: + num++; + var pageSize = 50; + #region + List list = new List(); + try + { + var page = _page_index; + JObject jObj = null; + + var param = $"time_type={(int)type}&page={page}&pageSize={pageSize}&author_app_id=1128&user_id={Member.username}&start_time={HttpExtend.GetTimeStamp(start_time)}&end_time={HttpExtend.GetTimeStamp(end_time)}"; + var sign = GetSign(param, Member.other); + + if (!string.IsNullOrWhiteSpace(sign)) + param = $"{param}&_signature={sign}"; + + var xb = GetXbogus(param, Member.other); + + try + { + Thread.Sleep(500 + new Random(Guid.NewGuid().GetHashCode()).Next(500, 1000)); + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/api/author/order/details?{param}&X-Bogus={xb}",//&X-Bogus={xb}", + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + + var html = result.Html; + + if (result.Header.AllKeys.Contains("set-cookie")) + { + var msTokenStr = result.Header["set-cookie"].ToString(); + var reg = Regex.Match(msTokenStr, @"(msToken=.+?;)", RegexOptions.IgnoreCase); + if (reg.Success) + Member.cookies = Member.cookies + ";" + reg.Groups[1].Value; + } + + var log = $@"抖音订单1请求时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss} ,订单时间:{start_time:yyyy-MM-dd HH:mm:ss} - {end_time:yyyy-MM-dd HH:mm:ss},{type.ToString()},{page}页 + +{html}"; + System.Diagnostics.Debug.WriteLine(log); + LogHelper.GetSingleObj().Debug("抖音下载", log); + + try + { + if (html.ToLower().Contains("400 Request Header".ToLower())) + { + Member.cookies = Member.cookies.SimpleCookies(); + } + + jObj = JObject.Parse(html); + + if (jObj["code"] != null) + { + var code = (int)jObj["code"]; + if (code == 0) + { + if (jObj["total"] != null && (int)jObj["total"] != 0) + list.Add(html); + } + else + { + //{"st":0,"code":9001,"msg":"操作异常","log_id":"2022010221313001020404907424DA1368","data":[]} + //{"st":401,"code":401,"msg":"请重新登录","extra":{"now":1641130324000,"log_id":"2022010221320401021213604714D95647"},"data":[]} + if (code == 401) + throw new Exception(html); + else if (code == 9001) + { + Thread.Sleep(2000); + //LogHelper.GetSingleObj().Debug("抖音下载", $"html={html},出验证码了.正在滑块"); + + if (num <= 3 && result.Header.AllKeys.Contains("X-Buyin-Sec-Verify-Code")) + { + var VerifyCode = result.Header["X-Buyin-Sec-Verify-Code"].ToString(); + var webId = SlidingBlock(Member.cookies, VerifyCode); + if (!string.IsNullOrWhiteSpace(webId)) + { + Member.cookies = CkRelpace(Member.cookies, webId); + ApiClient.GetSession().Saveable(Member).ExecuteCommand(); + goto Next; + } + } + else + throw new Exception(html); + } + jObj = null; + } + } + } + catch (Exception ex) + { + throw ex; + } + } + catch (Exception ex) + { + throw ex; + } + + if (jObj != null) + { + var total = (int)jObj["total"]; + + if (total > pageSize) + { + var value = (decimal)total / (decimal)pageSize; + var rate = (int)Math.Ceiling(value); + for (int i = 1; i < rate; i++) + { + try + { + Thread.Sleep(5000 + new Random(Guid.NewGuid().GetHashCode()).Next(1000, 2000)); + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = $"https://buyin.jinritemai.com/api/author/order/details?time_type={(int)type}&page={i}&pageSize={pageSize}&author_app_id=1128&user_id={Member.username}&start_time={HttpExtend.GetTimeStamp(start_time)}&end_time={HttpExtend.GetTimeStamp(end_time)}", + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = Member.cookies, + UserAgent = Member.other, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + + var html = result.Html; + + var log = $@"抖音订单2请求时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} ,订单时间:{start_time.ToString("yyyy-MM-dd HH:mm:ss")} - {end_time.ToString("yyyy-MM-dd HH:mm:ss")},{type.ToString()},{page}页 + +{html}"; + System.Diagnostics.Debug.WriteLine(log); + LogHelper.GetSingleObj().Debug("抖音下载2", log); + + try + { + jObj = JObject.Parse(html); + + if (jObj["code"] != null) + { + var code = (int)jObj["code"]; + if (code == 0) + { + list.Add(html); + } + else + { + Thread.Sleep(2000 + new Random(Guid.NewGuid().GetHashCode()).Next(500, 1000)); + //{"st":0,"code":9001,"msg":"操作异常","log_id":"2022010221313001020404907424DA1368","data":[]} + //{"st":401,"code":401,"msg":"请重新登录","extra":{"now":1641130324000,"log_id":"2022010221320401021213604714D95647"},"data":[]} + if (code == 401) + { + Member.online = false;//离线 + throw new Exception("重新登录"); + } + else if (code == 9001) + { + LogHelper.GetSingleObj().Debug("抖音下载", $"html={html},可能是验证码"); + } + jObj = null; + } + } + } + catch (Exception ex) + { + throw ex; + } + } + catch (Exception ex) + { + throw ex; + } + } + } + } + } + catch (Exception ex) + { + throw ex; + } + finally + { + Thread.Sleep(500); + } + return list; + #endregion + } + + ///// + ///// 计算xb + ///// + ///// + ///// + ///// + ///// + //private static string GetXbogus(string Param, string UserAgent, string PostData = "") + //{ + // var xb_obj = new + // { + // @params = Param, + // data = PostData, + // //user_agent = UserAgent + // user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36" + // }; + // var http = new HttpHelper(); + // var item = new HttpItem() + // { + // URL = "http://39.105.134.191:5510/xbogus", + // Postdata = JsonConvert.SerializeObject(xb_obj), + // Method = "post", + // ContentType = "application/json", + // Timeout = 5000 + // }; + // var html = http.GetHtml(item).Html; + // return JObject.Parse(html)["x_bogus"].ToString(); + //} + + + private static Dictionary SlidingBlockCache = new Dictionary(); + + #region 滑块 + private static string SlidingBlock(string ck, string verify_conf) + { + try + { + var reg = Regex.Match(ck, "SASID=([^;]+)", RegexOptions.IgnoreCase); + if (!reg.Success) + { + return string.Empty; + } + var dyId = reg.Groups[1].Value; + + if (SlidingBlockCache.ContainsKey(dyId)) + { + if (SlidingBlockCache[dyId] > DateTime.Now) + { + return string.Empty; + } + } + + SlidingBlockCache[dyId] = DateTime.Now.AddHours(1); + + for (int i = 0; i < 3; i++) + { + var html = RequestSlidingBlock(ck, verify_conf); + if (!string.IsNullOrWhiteSpace(html)) + { + //{"code":0,"msg":"\u6ed1\u5757\u6210\u529f\uff1averify_l0zvp97r_IBaMz2Mf_0DLB_4XuM_80gw_4AQDyhfXT50Q"} + var jObj = JObject.Parse(html); + if (jObj != null) + { + var code = (int)jObj["code"]; + if (200 == code) + { + var jObj1 = JObject.Parse(verify_conf); + var fp = jObj1["fp"]?.ToString(); + LogHelper.GetSingleObj().Debug("抖音滑块", "抖音滑块成功"); + + return $";s_v_web_id={fp}"; + } + if (-1 == code)//{"code":-1,"msg":"call: coderL"} + { + Thread.Sleep(3000); + LogHelper.GetSingleObj().Debug("抖音滑块", $"抖音滑块失败 {(i + 1)} => html = {html}"); + } + } + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("滑块异常", ex.Message + " - " + ex.StackTrace); + } + return string.Empty; + } + + /// + /// 请求滑块 + /// + /// + /// + /// + private static string RequestSlidingBlock(string ck, string verify_conf) + { + //ck = CkRelpace(ck, ";s_v_web_id=verify_l7bcxz5e_JTtVMCp0_uz88_4Cgb_9i8l_2dqOYZFURkt1"); + + ck = CkRelpace(ck, ""); + + //ck += ";s_v_web_id=verify_l7bcxz5e_JTtVMCp0_uz88_4Cgb_9i8l_2dqOYZFURkt1"; + //var verify_conf1 = verify_conf.Replace("\\", "\\\\").Replace(@"""", @"\"""); + //var postData = @"{""cookie"":""" + ck + @""",""verify_conf"":""" + verify_conf1 + @"""}"; + var postData2 = JsonConvert.SerializeObject(new { cookie = ck, verify_conf = verify_conf }); + + var sign = HttpExtend.GetMD5String("Cc" + verify_conf + "_*54R56@%"); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + //URL = "http://139.155.92.148:5511/dy_slide?sign=" + sign, + URL = "http://132.232.9.33:5511/dy_slide?sign=CF8EC9D97984579FF840FDB523F3AEA6", + Method = "POST", + Timeout = 50000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = postData2, + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + return html; + } + + #endregion + + #region 计算xb + private static string _js_xbcode = ""; + private static string Js_Xbcode + { + get + { + if (string.IsNullOrEmpty(_js_xbcode)) + { + StringBuilder builer = new StringBuilder(); + builer.Append("var key_1 = \"Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=\"").Append("\r\n"); + builer.Append("var key_2 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\"").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function _0x2b1419(_0x1a3c83) {").Append("\r\n"); + builer.Append(" var _0x408a74 = {").Append("\r\n"); + builer.Append(" 'exports': {}").Append("\r\n"); + builer.Append(" };").Append("\r\n"); + builer.Append(" return _0x1a3c83(_0x408a74, _0x408a74['exports']),").Append("\r\n"); + builer.Append(" _0x408a74['exports'];").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("var _0x522be9 = _0x2b1419(function (_0x5338f3) {").Append("\r\n"); + builer.Append(" !function () {").Append("\r\n"); + builer.Append(" var _0x10d7cc = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'").Append("\r\n"); + builer.Append(" , _0x485084 = {").Append("\r\n"); + builer.Append(" 'rotl': function (_0x399d32, _0xbcfbfb) {").Append("\r\n"); + builer.Append(" return _0x399d32 << _0xbcfbfb | _0x399d32 >>> -0x8dc + -0x8 * -0x13a + 0x6a * -0x2 - _0xbcfbfb;").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'rotr': function (_0x34bbe0, _0x39326b) {").Append("\r\n"); + builer.Append(" return _0x34bbe0 << -0x962 + 0x1ef6 + -0x1574 - _0x39326b | _0x34bbe0 >>> _0x39326b;").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'endian': function (_0x18b9a6) {").Append("\r\n"); + builer.Append(" if (_0x18b9a6['constructor'] == Number)").Append("\r\n"); + builer.Append(" return -0x6c1d8b + 0xabd * 0x102b + -0x1 * -0xbd80cb & _0x485084['rotl'](_0x18b9a6, 0x1f0c + 0x17d + 0x35 * -0x9d) | 0x123 * -0x151f537 + -0x133507d4 + 0x2925fc459 & _0x485084['rotl'](_0x18b9a6, -0x1d81 + 0x1 * -0xf8f + 0x2d28);").Append("\r\n"); + builer.Append(" for (var _0x2b9dac = -0x2b * -0xc5 + -0x1297 * -0x2 + -0x4645 * 0x1; _0x2b9dac < _0x18b9a6['length']; _0x2b9dac++)").Append("\r\n"); + builer.Append(" _0x18b9a6[_0x2b9dac] = _0x485084['endian'](_0x18b9a6[_0x2b9dac]);").Append("\r\n"); + builer.Append(" return _0x18b9a6;").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'randomBytes': function (_0x243867) {").Append("\r\n"); + builer.Append(" for (var _0x53efd7 = []; _0x243867 > 0xc32 + 0x19fe + -0x2630; _0x243867--)").Append("\r\n"); + builer.Append(" _0x53efd7['push'](Math['floor']((0x14b1 * -0x1 + -0xe80 + 0x2431) * Math['random']()));").Append("\r\n"); + builer.Append(" return _0x53efd7;").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'bytesToWords': function (_0x4b67bc) {").Append("\r\n"); + builer.Append(" for (var _0x52088d = [], _0x414454 = -0x2 * 0x67 + -0x2346 + -0x1 * -0x2414, _0x1ccc46 = -0xd * 0x2de + -0x1 * 0xcc + 0x2 * 0x1309; _0x414454 < _0x4b67bc['length']; _0x414454++,").Append("\r\n"); + builer.Append(" _0x1ccc46 += -0x1 * -0x1e4f + -0x1e1e + 0x29 * -0x1)").Append("\r\n"); + builer.Append(" _0x52088d[_0x1ccc46 >>> -0x9e * 0x35 + -0x24f * 0x1 + -0x5 * -0x702] |= _0x4b67bc[_0x414454] << 0x1f14 + 0x2500 + 0x394 * -0x13 - _0x1ccc46 % (-0x11c + 0x1a50 * 0x1 + -0x1914);").Append("\r\n"); + builer.Append(" return _0x52088d;").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'wordsToBytes': function (_0x389d89) {").Append("\r\n"); + builer.Append(" for (var _0x533c36 = [], _0x1d361a = 0x1 * -0x24fa + -0x10d1 + 0x35cb; _0x1d361a < (0x25de + -0x789 + 0xd1 * -0x25) * _0x389d89['length']; _0x1d361a += 0xf19 + 0x2321 * -0x1 + -0xc * -0x1ac)").Append("\r\n"); + builer.Append(" _0x533c36['push'](_0x389d89[_0x1d361a >>> -0x10d2 + -0x232d + 0x3404] >>> 0x1a12 + -0x74 + -0x252 * 0xb - _0x1d361a % (-0x34d + -0x19fb + 0xeb4 * 0x2) & 0x286 * 0xc + 0x2c9 + -0x2012);").Append("\r\n"); + builer.Append(" return _0x533c36;").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'bytesToHex': function (_0x563df3) {").Append("\r\n"); + builer.Append(" for (var _0x1ff846 = [], _0x1b16d2 = -0xa * 0x14b + 0x2dd * 0xd + -0x184b; _0x1b16d2 < _0x563df3['length']; _0x1b16d2++)").Append("\r\n"); + builer.Append(" _0x1ff846['push']((_0x563df3[_0x1b16d2] >>> -0x19 * 0x81 + 0x3 * -0x8a1 + 0x2680)['toString'](0x1 * -0x264c + -0x185 * -0x6 + -0x1 * -0x1d3e)),").Append("\r\n"); + builer.Append(" _0x1ff846['push']((-0xdd5 + 0x511 + 0xfb * 0x9 & _0x563df3[_0x1b16d2])['toString'](0x3d * -0x5f + -0x1ed5 + 0x3588));").Append("\r\n"); + builer.Append(" return _0x1ff846['join']('');").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'hexToBytes': function (_0x18dd40) {").Append("\r\n"); + builer.Append(" for (var _0x283d66 = [], _0x447560 = -0x23fd + -0x4 * -0x5af + 0xd41; _0x447560 < _0x18dd40['length']; _0x447560 += -0x25fc + 0xf9 * -0xc + 0x31aa)").Append("\r\n"); + builer.Append(" _0x283d66['push'](parseInt(_0x18dd40['substr'](_0x447560, -0x217e + -0x18d * -0x19 + -0x545 * 0x1), 0x71 * -0x43 + 0x1fb6 + -0x213));").Append("\r\n"); + builer.Append(" return _0x283d66;").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'bytesToBase64': function (_0x5c9156) {").Append("\r\n"); + builer.Append(" for (var _0x4571f8 = [], _0x3d51bf = 0x321 * 0x1 + 0x6df * -0x1 + 0x3be; _0x3d51bf < _0x5c9156['length']; _0x3d51bf += 0x2ce * 0x6 + -0xbf9 + -0x4d8)").Append("\r\n"); + builer.Append(" for (var _0xe1b6c2 = _0x5c9156[_0x3d51bf] << 0x218c + 0x167a + -0x37f6 | _0x5c9156[_0x3d51bf + (0x1 * -0x2db + 0x3 * 0x54d + -0x459 * 0x3)] << -0x3a * 0x39 + -0x69 * -0x36 + -0x24d * 0x4 | _0x5c9156[_0x3d51bf + (0x7b9 + 0x18bf + -0x2076 * 0x1)], _0x3aa643 = -0x18cf * -0x1 + 0x240d + 0xa * -0x616; _0x3aa643 < -0x3d * 0x11 + -0x448 + 0x859; _0x3aa643++)").Append("\r\n"); + builer.Append(" (0x1f2b + 0x1a4 + -0xaed * 0x3) * _0x3d51bf + (0x2525 + 0x1405 + -0x45 * 0xd4) * _0x3aa643 <= (-0x1de4 + 0x191b * 0x1 + -0x19b * -0x3) * _0x5c9156['length'] ? _0x4571f8['push'](_0x10d7cc['charAt'](_0xe1b6c2 >>> (-0x261c + 0x1 * -0xdc3 + 0x33e5) * (-0x15d9 + -0x10 * -0x163 + -0x3 * 0x1c - _0x3aa643) & -0x1b8 * 0x3 + -0x15fa + 0x2b * 0xa3)) : _0x4571f8['push']('=');").Append("\r\n"); + builer.Append(" return _0x4571f8['join']('');").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'base64ToBytes': function (_0x4f0ceb) {").Append("\r\n"); + builer.Append(" _0x4f0ceb = _0x4f0ceb['replace'](/[^A-Z0-9+\\/]/gi, '');").Append("\r\n"); + builer.Append(" for (var _0x953172 = [], _0x19d29a = -0x1ec5 + 0x443 * -0x2 + -0x59d * -0x7, _0x5bec73 = 0x1 * -0x1242 + -0x3f * -0x22 + 0x9e4; _0x19d29a < _0x4f0ceb['length']; _0x5bec73 = ++_0x19d29a % (-0xddc + 0x10 * -0x1de + 0x2bc0))").Append("\r\n"); + builer.Append(" -0x1bd7 + 0x1 * 0x7df + 0x13f8 != _0x5bec73 && _0x953172['push']((_0x10d7cc['indexOf'](_0x4f0ceb['charAt'](_0x19d29a - (0x260e + -0x1057 * 0x2 + -0x55f))) & Math['pow'](-0x2 * -0x10d5 + 0x1a * -0x58 + 0x388 * -0x7, -(-0x1e4 * 0x8 + 0x262b + -0x1709) * _0x5bec73 + (-0xaa7 + 0x26bf + -0x1c10)) - (-0x11c9 + -0x24ab + 0x3675)) << (0x1 * -0x551 + 0x1 * 0xdc8 + 0x1 * -0x875) * _0x5bec73 | _0x10d7cc['indexOf'](_0x4f0ceb['charAt'](_0x19d29a)) >>> 0x511 * -0x1 + -0x3d9 + 0x8f0 - (-0x2076 + 0x206e + 0xa) * _0x5bec73);").Append("\r\n"); + builer.Append(" return _0x953172;").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" };").Append("\r\n"); + builer.Append(" _0x5338f3['exports'] = _0x485084;").Append("\r\n"); + builer.Append(" }();").Append("\r\n"); + builer.Append("})").Append("\r\n"); + builer.Append(" , _0x43f7d5 = {").Append("\r\n"); + builer.Append(" 'utf8': {").Append("\r\n"); + builer.Append(" 'stringToBytes': function (_0x3ecb9e) {").Append("\r\n"); + builer.Append(" return _0x43f7d5['bin']['stringToBytes'](unescape(encodeURIComponent(_0x3ecb9e)));").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'bytesToString': function (_0x577703) {").Append("\r\n"); + builer.Append(" return decodeURIComponent(escape(_0x43f7d5['bin']['bytesToString'](_0x577703)));").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'bin': {").Append("\r\n"); + builer.Append(" 'stringToBytes': function (_0x2b796a) {").Append("\r\n"); + builer.Append(" for (var _0x83a3c1 = [], _0x2b558b = 0x1597 + -0x20a5 + 0xb0e; _0x2b558b < _0x2b796a['length']; _0x2b558b++)").Append("\r\n"); + builer.Append(" _0x83a3c1['push'](0x50f + 0x6 * -0x10 + 0xec * -0x4 & _0x2b796a['charCodeAt'](_0x2b558b));").Append("\r\n"); + builer.Append(" return _0x83a3c1;").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'bytesToString': function (_0x2f2515) {").Append("\r\n"); + builer.Append(" for (var _0x56610e = [], _0x3415a9 = -0x40d + -0x17d * -0x4 + -0x1e7 * 0x1; _0x3415a9 < _0x2f2515['length']; _0x3415a9++)").Append("\r\n"); + builer.Append(" console.log('from_CharCode_10', String['fromCharCode'](_0x2f2515[_0x3415a9]), _0x2f2515[_0x3415a9])").Append("\r\n"); + builer.Append(" _0x56610e['push'](String['fromCharCode'](_0x2f2515[_0x3415a9]));").Append("\r\n"); + builer.Append(" return _0x56610e['join']('');").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append(" , _0x15dd40 = _0x43f7d5").Append("\r\n"); + builer.Append(" , _0x34cd71 = function (_0x51f280) {").Append("\r\n"); + builer.Append(" return null != _0x51f280 && (_0x1b5b56(_0x51f280) || _0x16238e(_0x51f280) || !!_0x51f280['_isBuffer']);").Append("\r\n"); + builer.Append("};").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function _0x1b5b56(_0x1b9428) {").Append("\r\n"); + builer.Append(" return !!_0x1b9428['constructor'] && 'function' == typeof _0x1b9428['constructor']['isBuffer'] && _0x1b9428['constructor']['isBuffer'](_0x1b9428);").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function _0x16238e(_0x23735f) {").Append("\r\n"); + builer.Append(" return 'function' == typeof _0x23735f['readFloatLE'] && 'function' == typeof _0x23735f['slice'] && _0x1b5b56(_0x23735f['slice'](-0x11ba + 0x1e7e + 0x13 * -0xac, 0x12e7 * -0x1 + 0x1545 + -0x65 * 0x6));").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("var _0xf220d2 = _0x2b1419(function (_0x18e32f) {").Append("\r\n"); + builer.Append(" !function () {").Append("\r\n"); + builer.Append(" var _0x16e6ad = _0x522be9").Append("\r\n"); + builer.Append(" , _0x5e1216 = _0x15dd40['utf8']").Append("\r\n"); + builer.Append(" , _0x2fc35f = _0x34cd71").Append("\r\n"); + builer.Append(" , _0x37dba4 = _0x15dd40['bin']").Append("\r\n"); + builer.Append(" , _0x3c1bff = function (_0x3481d8, _0x53f008) {").Append("\r\n"); + builer.Append(" _0x3481d8['constructor'] == String ? _0x3481d8 = _0x53f008 && 'binary' === _0x53f008['encoding'] ? _0x37dba4['stringToBytes'](_0x3481d8) : _0x5e1216['stringToBytes'](_0x3481d8) : _0x2fc35f(_0x3481d8) ? _0x3481d8 = Array['prototype']['slice']['call'](_0x3481d8, 0x41 * 0x2 + -0x2271 * 0x1 + -0x1ff * -0x11) : Array['isArray'](_0x3481d8) || _0x3481d8['constructor'] === Uint8Array || (_0x3481d8 = _0x3481d8['toString']());").Append("\r\n"); + builer.Append(" for (var _0x14f8b4 = _0x16e6ad['bytesToWords'](_0x3481d8), _0x500746 = (-0x1 * -0x16cf + 0x6e8 + -0x1daf) * _0x3481d8['length'], _0x58fa30 = -0x1a1b8a * 0xe1 + -0x2 * 0x1f6998d9 + 0xbd0a88fd, _0x5a63d0 = -(0x157c81bf + 0x2 * 0x8984bb + -0x45aa * 0x1763), _0xfa952 = -(0xe * 0xe0dfabd + 0x1d2f084 * 0x2f + 0x2cce2ee4 * -0x4), _0x38d239 = -0x105d7743 + 0x154a5 * 0x16f5 + 0x2039bd0, _0x474622 = 0x13a0 + -0x1bf7 + -0x1 * -0x857; _0x474622 < _0x14f8b4['length']; _0x474622++)").Append("\r\n"); + builer.Append(" _0x14f8b4[_0x474622] = -0x427a7e + 0x2 * 0x61326d + -0x7f16a3 * -0x1 & (_0x14f8b4[_0x474622] << -0x2706 + 0x215e + 0x5b * 0x10 | _0x14f8b4[_0x474622] >>> -0x9 * 0xa1 + -0x1 * -0x125b + -0xc9a) | -0x1e69bded8 + -0x2 * -0xd0ed9297 + 0x143c1b8aa & (_0x14f8b4[_0x474622] << 0x1a0d + -0x7b + -0xcbd * 0x2 | _0x14f8b4[_0x474622] >>> 0x1e8a + 0x89d + -0x7d3 * 0x5);").Append("\r\n"); + builer.Append(" _0x14f8b4[_0x500746 >>> 0x152a + -0x2632 + 0x110d] |= -0x1a5e + -0x80a + 0x22e8 << _0x500746 % (-0xa5 * -0xb + -0x1dae + -0x1 * -0x16b7),").Append("\r\n"); + builer.Append(" _0x14f8b4[0x20ff + 0x3 * -0xba + -0x1ec3 + (_0x500746 + (0x84e + 0x4 * -0x251 + 0x136) >>> 0x12 * 0x137 + -0x255 + 0x9c0 * -0x2 << -0xcee * -0x2 + -0x2568 + 0xb90)] = _0x500746;").Append("\r\n"); + builer.Append(" var _0x140544 = _0x3c1bff['_ff']").Append("\r\n"); + builer.Append(" , _0x25553e = _0x3c1bff['_gg']").Append("\r\n"); + builer.Append(" , _0x236490 = _0x3c1bff['_hh']").Append("\r\n"); + builer.Append(" , _0x45bb0a = _0x3c1bff['_ii'];").Append("\r\n"); + builer.Append(" for (_0x474622 = 0x1c22 + 0xac8 + -0x26ea; _0x474622 < _0x14f8b4['length']; _0x474622 += 0x4 * 0x6d2 + 0x1985 * -0x1 + -0x1b3) {").Append("\r\n"); + builer.Append(" var _0x235199 = _0x58fa30").Append("\r\n"); + builer.Append(" , _0x365440 = _0x5a63d0").Append("\r\n"); + builer.Append(" , _0x56f863 = _0xfa952").Append("\r\n"); + builer.Append(" , _0x54bd03 = _0x38d239;").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x140544(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0xc0 * 0x34 + -0x22f8 + 0x49f8)], -0x1605 + -0x5fb * -0x6 + -0xdd6, -(-0x4f2596b * -0xc + 0x474cdc87 * 0x1 + -0x5a13b203)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x140544(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (0x11 * 0x208 + 0x1 * 0x70d + -0x3 * 0xddc)], -0xba3 + -0x13f7 + 0x1fa6, -(0x1d7 * 0x13a989 + -0x2 * -0x140bb7ac + -0xfbc63 * 0x35f)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x140544(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (0xec6 + 0xfdb + -0x367 * 0x9)], 0x1f8b + -0x3 * 0xc86 + 0x618, 0x2fa10109 + -0x451ed7dc + -0x6383 * -0x943a),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x140544(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0xc6d * 0x2 + -0x19d + -0x1 * -0x1a7a)], 0x1138 + -0x1fe4 * 0x1 + 0xec2, -(-0x2dbf0c5e + -0x279eacea + 0x808b3f * 0x126)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x140544(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0x1021 * 0x2 + 0xce * 0xc + 0x243 * 0xa)], -0x3a * -0x91 + 0x999 + -0x2a6c, -(0x884d053 + 0x5d92c26 + 0x1ed0614 * -0x2)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x140544(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (0x6df * 0x4 + -0x6ee + -0x1489)], -0x5 * 0x22a + 0x2128 + -0x76e * 0x3, -0x5bc8729f + -0x339 * 0x28e523 + -0xd9c * -0x15af13),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x140544(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0x9f1 + -0x12 * -0x118 + -0x9b9)], -0x22b7 * 0x1 + -0x2677 * -0x1 + -0x3af, -(-0x44575f2f + -0x212f4838 + 0xbd566154)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x140544(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0x1b9 + -0x2177 + 0x2337)], -0x23a3 + 0x2 * 0xeed + -0x1 * -0x5df, -(-0x3fcc1dd + -0x5205b96 * 0x1 + 0xbd68872)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x140544(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0x11b * 0x17 + 0x1 * 0x2549 + -0xbd4)], -0x2 * 0x65 + -0xcf9 + 0xdca, 0x153322f * -0x6e + 0xc6d549ce + -0x50d62a * -0xa6),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x140544(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (0xa62 + -0x14dc + 0x381 * 0x3)], 0x9ef * 0x1 + 0x1517 + -0x1efa, -(-0x9b * -0x160b8ce + -0x25fe74a8 + 0x71bb7 * -0x847)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x140544(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (0xff2 + -0xb5c + -0x48c)], -0x10e2 + 0xbf2 + 0x501, -(0xbfd + 0x406d + 0x57e5)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x140544(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (0xc26 + -0xe * -0x243 + 0x2bc5 * -0x1)], -0x1a8c * -0x1 + -0x41 + -0x1a35, -(0x815afa87 + 0xab446624 + 0xb5fc3869 * -0x1)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x140544(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (0x1fcb + 0x1cb2 + -0x1 * 0x3c71)], 0x1f8f + 0x14ee + 0x55 * -0x9e, 0x136d91b * 0x11 + -0x418a30f1 + 0x9875d748),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x140544(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (0x1 * 0xd0b + -0x1a06 + 0xd08)], -0x122 * 0x7 + -0x3f7 * 0x5 + 0x1bcd, -(-0x129fb8 + 0xb531d * -0x3b + 0x28b2aea * 0x2)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x140544(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (0x2 * 0x1d0 + 0x18cc + -0x1c5e)], -0x5f8 * -0x6 + -0x894 * -0x1 + 0x2c53 * -0x1, -(-0x3bd8480a * 0x1 + -0x9b91a191 + 0x130f0a60d)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x25553e(_0x58fa30, _0x5a63d0 = _0x140544(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (0x490 + -0x1586 + -0x1105 * -0x1)], 0xeeb + 0x1995 + -0x286a, -0xb6f * 0x13316 + -0x9064344f + -0xb * -0x1512d92e), _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0x13a1 + 0x89 * -0x14 + 0x1e56)], -0x176c + 0x17db + -0x2 * 0x35, -(0x3f1 * 0x1a470 + 0x7f16e2e + 0x193b8 * -0x2e0)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x25553e(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (0x7 * 0x1c1 + 0x1 * 0x55d + 0xa * -0x1c3)], -0x4d + 0x71d + -0x6c7, -(-0x99f9c0 + -0x3cd103bf + 0x239 * 0x385037)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x25553e(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0x1 * 0x2f5 + 0x6d * -0x31 + 0x17dd)], -0x1e + -0x10f + 0x13b, -0x40e13c7d + 0x375 * 0x10b6f7 + -0xf27b0f9 * -0x3),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x25553e(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0x15f * 0x19 + 0x23cf + -0x188)], 0x40e + 0x2a * 0xb3 + -0xc2 * 0x2c, -(-0x236e70c9 + 0xe13fa72 + 0x2ba3aead)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x25553e(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0x1 * -0x2417 + -0x275 * -0x1 + -0x2687)], 0xc6 + 0x9f2 + 0xf9 * -0xb, -(0x6d6cd * 0x369 + 0x4cd42122 + 0x5c * -0xa252a3)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x25553e(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x110a + 0x214 * -0xe + -0x2 * -0x1716)], 0x1fcd + -0x2 * 0xb1a + -0x990, 0x2 * -0x206ac6a + 0xe665f * -0x3d + -0x116 * -0x8fa4f),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x25553e(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0x1 * -0x10ed + -0x1 * 0x3fd + 0x3 * -0x44b)], -0x5f0 * -0x5 + -0x264f + -0x1 * -0x8ad, -(-0x2245d187 + -0x22da86c0 + 0xad971c7 * 0xa)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x25553e(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (0x4 * 0x267 + -0x2469 + 0x1ad1)], 0x1904 + 0x3 * 0x474 + -0x264c, -(0x1f1de099 * -0x1 + 0x1 * 0x60e3f1f + -0x2cb7 * -0x119de)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x25553e(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (0x1877 * -0x1 + 0x1613 + -0x9 * -0x45)], -0x3bb + -0x36e + 0x72e, 0xf9f176 * -0x2b + 0x33b0fae5 + -0x1 * -0x182c61d3),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x25553e(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x739 + -0x1825 + 0x1f6c)], -0x37 * 0x25 + 0xb * 0x28f + -0x1429, -(-0x2 * -0x37a04f82 + -0x20b43a75 + -0x1 * 0x11c36c65)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x25553e(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (0x1a84 + 0xda * -0xe + 0x1 * -0xe95)], 0x2 * -0x11fb + 0x1 * 0x1771 + 0x1d * 0x6f, -(-0x1a47a8d + -0xa951477 + 0x1764817d)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x25553e(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0x1c0d + 0x1d05 + -0xf0)], 0x18fc + -0x1 * 0x1d21 + -0x439 * -0x1, -0x198a4fe8 * -0x2 + 0x1e773750 + 0xc31c233 * -0x1),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x25553e(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (0xe13 + 0x227 * 0x3 + -0x147b)], 0x12fa + -0xfde * -0x2 + -0x32b1, -(0x30f6 * 0x336c9 + 0x939c46fb + -0xdadc8526)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x25553e(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (0x1b05 + -0xbb8 + -0xf4b)], 0x1623 + 0x4 * -0x5b3 + 0x59 * 0x2, -(0x2ddda05 + 0x5e33987 * -0x1 + -0x534e * -0x12b3)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x25553e(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0x20de + 0x2070 + -0xd * -0x9)], -0x467 * 0x2 + 0x1e6 + 0x6 * 0x129, -0x1 * -0x1926ea91 + -0x23908a46 + 0x71d8a28e),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x236490(_0x58fa30, _0x5a63d0 = _0x25553e(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (0x1 * 0x2308 + -0x19ef + -0x1 * 0x90d)], 0xb * -0x52 + 0x3 * 0x4f1 + -0xb39, -(0x1 * -0x8456ffce + -0x5 * -0x27503b8f + 0x329b8979)), _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (0x1 * -0x67f + -0x17 * -0x5f + 0xb * -0x2f)], 0x1af2 + -0x1bda + 0x4 * 0x3b, -(0x147 * 0x551 + -0x4e532 * 0x2 + 0x8c6ab * 0x1)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x236490(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x24fa + 0x9a4 * 0x1 + -0x3e * -0x71)], -0x149b + 0x2634 + -0x8c7 * 0x2, -(-0x9 * 0x29f6320 + 0x1d10fb93 * -0x7 + -0x56e7d9a9 * -0x4)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x236490(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (0x1 * 0x1e0d + -0xd * -0x1f3 + -0x3759)], -0x110e + -0x199c * -0x1 + 0x1 * -0x87e, -0x2 * 0x5b779ef4 + 0x4a1 * -0x2bf7c2 + 0x1f012780c),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x236490(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0x2 * -0xdd3 + -0x15f7 + 0x83 * -0xb)], -0xdae + -0xd1 * -0x7 + -0x407 * -0x2, -(0xccd739 + -0x387862c + 0x4d576e7)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x236490(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0x1f72 + -0x1d21 + 0x3c94)], 0x1f8e + -0x1138 + -0x3 * 0x4c6, -(-0x616353e3 + 0x1b873 * 0x107f + -0x17 * -0x6f7c53e)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x236490(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x3d6 * 0x1 + -0xf * -0xcd + -0x1 * 0x829)], 0x1a4d + 0x231e + -0x2 * 0x1eb0, 0x5b1a66fd + 0x1aa19916 + -0x29dd306a),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x236490(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0x2486 + -0x1ef9 + 0x4386)], -0x73e * -0x5 + 0x175e + 0x1dc2 * -0x2, -(0x1442234 + 0x43 * -0x1321ab + -0x3d * -0x3698b1)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x236490(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0x1 * 0x253d + -0x8e1 * -0x1 + 0xe33 * 0x2)], -0x35 * -0x11 + -0x255d * -0x1 + -0x28cb, -(0xd1028 * 0x1eb + -0x3bdbbf9f + 0x640e0677)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x236490(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (0x69 * 0x32 + -0x44f + -0x1026)], -0x2 * 0x12b9 + 0x60 * -0x28 + 0x3476, 0x4132d95 * -0x9 + 0xc9db7d5 + -0x766 * -0x8bd8d),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x236490(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (0xec9 + 0x21a9 * -0x1 + 0x12e0)], 0x11 * -0x34 + 0x21cc + -0x1e4d, -(-0xe95d9 * -0x11f + -0x2187d73b + 0x268cb0fa)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x236490(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0x17e9 + 0x221 + 0x15cb)], 0x202 * -0x5 + -0x1e0f + 0x45 * 0x95, -(-0x163dae24 + 0x1 * -0x391868b2 + 0x187afadd * 0x5)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x236490(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0xd38 + -0x3ca + -0x1b4 * -0xa)], 0xb39 * -0x1 + 0x17 * 0x18d + -0x185b * 0x1, 0x5006610 + -0x3 * -0x10a59b1 + -0x397561e),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x236490(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0x1e07 + 0x1 * -0x15cf + 0x33df * 0x1)], 0x2403 * -0x1 + -0x191 + 0x2598, -(0x1f4bcdce + -0x11311842 + 0x18107a3b)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x236490(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x67 * -0x7 + -0x144b + 0x2 * 0x8c3)], 0x2382 + 0x258 + -0x1 * 0x25cf, -(-0x37 * -0xad9c25 + 0x7a * -0x516f11 + 0x2 * 0xd536421)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x236490(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (0x18a9 + 0xbeb + 0x2485 * -0x1)], 0x50e + -0x1511 + 0x1013, -0x17d3161f * -0x1 + -0xf549 * 0x11fe + 0x190c9e47),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x45bb0a(_0x58fa30, _0x5a63d0 = _0x236490(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0x18aa + 0x8 * -0x475 + -0x57c * -0xb)], -0x7e9 + -0x475 + -0xc75 * -0x1, -(-0x1 * -0x63cb03d3 + -0x3fe6c634 + 0x176f6bfc)), _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (0x2 * -0x75b + 0x1 * 0x1e23 + -0xf6d)], -0x1 * -0x1994 + 0x1c * 0x9a + -0x2 * 0x1533, -(0x33d9a * 0x58a + -0x1 * 0x670901f + 0x13 * 0x46ead)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x45bb0a(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x210d + -0xd83 * 0x1 + 0x2e97)], -0x1 * 0x21b7 + 0x248c + -0x2cb, -0x20e6f140 + -0x133 * -0x3d26bf + -0xd1 * -0x20bfaa),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x45bb0a(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0xa7 * -0xd + 0x2384 + -0x7 * 0x647)], 0x19 * -0x138 + -0xc8 * -0x2 + 0x1cf7, -(0x7c2d271f * 0x1 + -0xa615d099 + 0x7e5485d3)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x45bb0a(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0xa * -0x39d + 0x2cf * -0xd + 0x1 * 0x66)], -0x3c4 + 0x1d * -0x1 + 0xd * 0x4e, -(0x3 * 0x51c3b1 + -0xb03c7d * 0x3 + 0x487ca2b)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x45bb0a(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0x24f5 + -0x1b5 * -0x7 + 0x3 * 0x85a)], -0x1 * 0x1f53 + 0x2 * 0xeef + 0x17b, -0x6d292286 + 0xd * -0x1e597a + 0xd40f077b),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x45bb0a(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x15a * 0x13 + 0x482 * 0x8 + 0x3b * -0x2d)], -0x26 * -0xd6 + 0xfba + -0x2 * 0x17ba, -(-0x2 * -0x603a0bef + -0xb8f41cb1 + 0x69733841)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x45bb0a(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0xfa9 + 0x3d * -0x1a + 0x15e5)], 0x1692 + -0x1ec4 + -0x841 * -0x1, -(0x2433 * -0x6f + 0x1a686a + 0x55536)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x45bb0a(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0x125 + -0x1 * -0x1843 + -0x171d)], 0x679 + 0x4 * 0x2e2 + 0x4 * -0x47b, -(0xfc44093 * -0x3 + -0x3 * -0x404df487 + -0x4a04b89 * 0x5)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x45bb0a(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (0xec2 + 0x54 + -0x2f * 0x52)], 0x1a2e + -0x31 * -0xa1 + -0x38f9, -0x13 * 0x10d9a53 + 0x5c155c66 + 0x1 * 0x27959612),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x45bb0a(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x25ec + -0x1 * -0x1319 + 0x12e2)], 0x12f6 + 0x25cc + -0x38b8, -(0xafdd37 * 0x5 + -0x2818c33 + 0x830b0 * 0x1c)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x45bb0a(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (0xe6 + 0xbf * -0x10 + 0x6 * 0x1d8)], -0x1b15 + -0x52 * -0x29 + -0x2 * -0x701, -(-0xb1a8b580 + 0x5e800adf + -0xb027678d * -0x1)),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x45bb0a(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (-0x2 * -0x12ef + 0x897 + -0x78 * 0x63)], -0xacb + -0x132b + 0x1e0b * 0x1, 0x879b228b + 0x40b23 * 0x17ff + -0xea30ef * 0xa9),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x45bb0a(_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239, _0x14f8b4[_0x474622 + (-0x11d4 + 0x1 * -0xe35 + -0x1 * -0x200d)], 0x2409 + 0x20 * -0x12d + 0x19d * 0x1, -(-0x5df8b1 * 0x25 + 0x7cd632d + 0xe740fe6)),").Append("\r\n"); + builer.Append(" _0x38d239 = _0x45bb0a(_0x38d239, _0x58fa30, _0x5a63d0, _0xfa952, _0x14f8b4[_0x474622 + (-0x209d + 0x1 * -0x12cb + 0x3373)], -0x1 * -0x1bbb + -0x3f * 0x5 + -0x6 * 0x469, -(0xe8 * 0x565186 + 0x2f * -0x2a8bd63 + 0xc7 * 0x920a38)),").Append("\r\n"); + builer.Append(" _0xfa952 = _0x45bb0a(_0xfa952, _0x38d239, _0x58fa30, _0x5a63d0, _0x14f8b4[_0x474622 + (-0x141 * -0x1f + 0x25 * 0x9a + -0x3d1f)], 0x4db + 0x5b + -0x1 * 0x527, -0x681c5b3 * -0x5 + 0x5e9 * 0x1b0e3 + 0x5088a1),").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x45bb0a(_0x5a63d0, _0xfa952, _0x38d239, _0x58fa30, _0x14f8b4[_0x474622 + (0x27 * -0xf + -0x36 * 0xd + 0x3 * 0x1b0)], 0xab * 0x1 + 0x1f53 + -0x1fe9, -(-0x27eed9db + -0x7c2dd5 * 0x9 + 0x40c5a2c7)),").Append("\r\n"); + builer.Append(" _0x58fa30 = _0x58fa30 + _0x235199 >>> -0x3 * -0x6b + -0x1471 * -0x1 + 0xad9 * -0x2,").Append("\r\n"); + builer.Append(" _0x5a63d0 = _0x5a63d0 + _0x365440 >>> 0x1 * 0x2702 + -0x160e + 0x1f * -0x8c,").Append("\r\n"); + builer.Append(" _0xfa952 = _0xfa952 + _0x56f863 >>> -0x14 * 0x99 + -0x1 * -0x1751 + -0xb5d * 0x1,").Append("\r\n"); + builer.Append(" _0x38d239 = _0x38d239 + _0x54bd03 >>> -0x1 * 0x22bb + 0x2a6 + 0x1 * 0x2015;").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" return _0x16e6ad['endian']([_0x58fa30, _0x5a63d0, _0xfa952, _0x38d239]);").Append("\r\n"); + builer.Append(" };").Append("\r\n"); + builer.Append(" _0x3c1bff['_ff'] = function (_0x39d6ff, _0xf44b81, _0x6e1fd8, _0x537a5d, _0x473a43, _0x1d47fe, _0x396c93) {").Append("\r\n"); + builer.Append(" var _0x20d237 = _0x39d6ff + (_0xf44b81 & _0x6e1fd8 | ~_0xf44b81 & _0x537a5d) + (_0x473a43 >>> 0x1644 + -0x5 * -0x757 + -0x3af7 * 0x1) + _0x396c93;").Append("\r\n"); + builer.Append(" return (_0x20d237 << _0x1d47fe | _0x20d237 >>> -0x1 * 0x1c51 + -0x1bb + 0x1e2c - _0x1d47fe) + _0xf44b81;").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" ,").Append("\r\n"); + builer.Append(" _0x3c1bff['_gg'] = function (_0x38be71, _0x46f056, _0xcdfe0b, _0x28f534, _0x15caff, _0x2e1b18, _0x2b54bf) {").Append("\r\n"); + builer.Append(" var _0xe03481 = _0x38be71 + (_0x46f056 & _0x28f534 | _0xcdfe0b & ~_0x28f534) + (_0x15caff >>> 0xb3f + -0x1a85 + 0xf46) + _0x2b54bf;").Append("\r\n"); + builer.Append(" return (_0xe03481 << _0x2e1b18 | _0xe03481 >>> 0x6b * 0x9 + 0x2642 + -0x29e5 - _0x2e1b18) + _0x46f056;").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" ,").Append("\r\n"); + builer.Append(" _0x3c1bff['_hh'] = function (_0x47b307, _0x45f56f, _0x277ce6, _0x483b1b, _0xd50cbf, _0x164d53, _0x459b9f) {").Append("\r\n"); + builer.Append(" var _0x9e8d61 = _0x47b307 + (_0x45f56f ^ _0x277ce6 ^ _0x483b1b) + (_0xd50cbf >>> 0x2 * -0xaf3 + 0xe * -0xb6 + 0x1fda) + _0x459b9f;").Append("\r\n"); + builer.Append(" return (_0x9e8d61 << _0x164d53 | _0x9e8d61 >>> -0x5 * -0x3d + -0xb * -0x1a1 + -0x2 * 0x97e - _0x164d53) + _0x45f56f;").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" ,").Append("\r\n"); + builer.Append(" _0x3c1bff['_ii'] = function (_0x17a9fb, _0x5a4323, _0x49d45d, _0x3cbe9a, _0x301e85, _0x19e288, _0x53cfd0) {").Append("\r\n"); + builer.Append(" var _0x5a8ab2 = _0x17a9fb + (_0x49d45d ^ (_0x5a4323 | ~_0x3cbe9a)) + (_0x301e85 >>> -0xe71 + -0x8e3 + 0x1754) + _0x53cfd0;").Append("\r\n"); + builer.Append(" return (_0x5a8ab2 << _0x19e288 | _0x5a8ab2 >>> -0x13 * -0x144 + 0x1e4e + -0x363a * 0x1 - _0x19e288) + _0x5a4323;").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" ,").Append("\r\n"); + builer.Append(" _0x3c1bff['_blocksize'] = 0x1c71 + 0x2497 + -0x207c * 0x2,").Append("\r\n"); + builer.Append(" _0x3c1bff['_digestsize'] = -0x1 * 0x1b3b + -0x1 * -0xc28 + 0xf23,").Append("\r\n"); + builer.Append(" _0x18e32f['exports'] = function (_0x369546, _0x237ff3) {").Append("\r\n"); + builer.Append(" if (null == _0x369546)").Append("\r\n"); + builer.Append(" throw new Error('Illegal\\x20argument\\x20' + _0x369546);").Append("\r\n"); + builer.Append(" var _0x1869a2 = _0x16e6ad['wordsToBytes'](_0x3c1bff(_0x369546, _0x237ff3));").Append("\r\n"); + builer.Append(" return _0x237ff3 && _0x237ff3['asBytes'] ? _0x1869a2 : _0x237ff3 && _0x237ff3['asString'] ? _0x37dba4['bytesToString'](_0x1869a2) : _0x16e6ad['bytesToHex'](_0x1869a2);").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" ;").Append("\r\n"); + builer.Append(" }();").Append("\r\n"); + builer.Append("});").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("for (var _0x5d6614 = {").Append("\r\n"); + builer.Append(" 'boe': !(0x122a + 0x4fd + 0x2 * -0xb93),").Append("\r\n"); + builer.Append(" 'aid': 0x0,").Append("\r\n"); + builer.Append(" 'dfp': !(-0x17 * -0x17f + 0x71a * -0x2 + -0x1434),").Append("\r\n"); + builer.Append(" 'sdi': !(0x57 * 0x37 + 0xb17 * 0x1 + -0x1dc7),").Append("\r\n"); + builer.Append(" 'enablePathList': [],").Append("\r\n"); + builer.Append(" '_enablePathListRegex': [],").Append("\r\n"); + builer.Append(" 'urlRewriteRules': [],").Append("\r\n"); + builer.Append(" '_urlRewriteRules': [],").Append("\r\n"); + builer.Append(" 'initialized': !(-0x13 * 0x1a1 + 0x1 * 0x963 + 0x1591 * 0x1),").Append("\r\n"); + builer.Append(" 'enableTrack': !(0x667 * 0x3 + 0x1a4f * 0x1 + -0x2d83),").Append("\r\n"); + builer.Append(" 'track': {").Append("\r\n"); + builer.Append(" 'unitTime': 0x0,").Append("\r\n"); + builer.Append(" 'unitAmount': 0x0,").Append("\r\n"); + builer.Append(" 'fre': 0x0").Append("\r\n"); + builer.Append(" },").Append("\r\n"); + builer.Append(" 'triggerUnload': !(-0x95 * -0x20 + 0x1c82 + -0x2f21),").Append("\r\n"); + builer.Append(" 'region': '',").Append("\r\n"); + builer.Append(" 'regionConf': {},").Append("\r\n"); + builer.Append(" 'umode': 0x0,").Append("\r\n"); + builer.Append(" 'v': !(0x35e * 0x5 + -0x585 + 0xb50 * -0x1),").Append("\r\n"); + builer.Append(" 'perf': !(-0x11e9 + -0x1 * -0x16a9 + -0x4bf)").Append("\r\n"); + builer.Append("}, _0x15f587 = {").Append("\r\n"); + builer.Append(" 'debug': function (_0x41ffc1, _0x5bbbc8) {").Append("\r\n"); + builer.Append(" let _0xcd8973 = !(0x1cdc + 0x154 * -0xe + 0x25 * -0x47);").Append("\r\n"); + builer.Append(" _0xcd8973 = _0x5d6614['boe'];").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append("}, _0x55fe31 = '0123456789abcdef'['split'](''), _0x3c6322 = [], _0x50ff23 = [], _0x4059b2 = 0x81 * -0x9 + 0xf * 0x281 + -0x2106; _0x4059b2 < 0x3e * -0xd + -0x96a + 0xd90; _0x4059b2++)").Append("\r\n"); + builer.Append(" _0x3c6322[_0x4059b2] = _0x55fe31[_0x4059b2 >> 0xa6 * -0xb + -0x11 * -0xef + 0x1 * -0x8b9 & -0xb * 0x227 + 0x240b + -0xc4f] + _0x55fe31[-0x506 + -0xa7d * -0x1 + -0x1 * 0x568 & _0x4059b2],").Append("\r\n"); + builer.Append(" _0x4059b2 < -0xbd2 + 0x1e5f + -0x127d && (_0x4059b2 < -0x214d + -0xf47 * 0x1 + 0x309e ? _0x50ff23[0xd7c * -0x1 + -0x574 * 0x4 + 0x2f5 * 0xc + _0x4059b2] = _0x4059b2 : _0x50ff23[-0x170b + 0x2 * -0x5cf + 0x7 * 0x500 + _0x4059b2] = _0x4059b2);").Append("\r\n"); + builer.Append("var encode = function (_0x5ac7ec) {").Append("\r\n"); + builer.Append(" for (var _0x34905b = _0x5ac7ec['length'], _0x44b5b7 = '', _0x68d4f2 = -0x3 * 0x605 + 0x1020 + 0x1ef; _0x68d4f2 < _0x34905b;)").Append("\r\n"); + builer.Append(" _0x44b5b7 += _0x3c6322[_0x5ac7ec[_0x68d4f2++]];").Append("\r\n"); + builer.Append(" return _0x44b5b7;").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("var decode = function (_0x5c3d2a) {").Append("\r\n"); + builer.Append(" for (var _0x1204d6 = _0x5c3d2a['length'] >> 0xa1e * -0x2 + 0x1937 + 0x4fa * -0x1, _0x700552 = _0x1204d6 << 0x68 + -0xa29 + 0x9c2, _0x1673dd = new Uint8Array(_0x1204d6), _0x19eb71 = 0xe9e + -0x167 + -0xd37, _0x249396 = 0x1 * 0x104a + 0xaa9 + 0x1af3 * -0x1; _0x249396 < _0x700552;)").Append("\r\n"); + builer.Append(" _0x1673dd[_0x19eb71++] = _0x50ff23[_0x5c3d2a['charCodeAt'](_0x249396++)] << -0x1938 + 0x10c4 * -0x1 + 0x2a00 | _0x50ff23[_0x5c3d2a['charCodeAt'](_0x249396++)];").Append("\r\n"); + builer.Append(" return _0x1673dd;").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function _0x238632(_0x4cdef5, _0x268c9c) {").Append("\r\n"); + builer.Append(" let _0x2b4641, _0xbb44d8 = [], _0x138ea3 = 0x140 + -0x2038 + -0x7be * -0x4, _0xc9f8ff = '';").Append("\r\n"); + builer.Append(" for (let _0x332e7e = 0x17 * -0x8 + -0x910 + 0x2 * 0x4e4; _0x332e7e < 0x24e + -0x2533 + 0xbf7 * 0x3; _0x332e7e++)").Append("\r\n"); + builer.Append(" _0xbb44d8[_0x332e7e] = _0x332e7e;").Append("\r\n"); + builer.Append(" for (let _0x369701 = 0x77a * -0x5 + -0x3 * 0x689 + -0x12ff * -0x3; _0x369701 < 0x1b3 * 0x12 + -0x1e3 + 0x3f5 * -0x7; _0x369701++)").Append("\r\n"); + builer.Append(" _0x138ea3 = (_0x138ea3 + _0xbb44d8[_0x369701] + _0x4cdef5['charCodeAt'](_0x369701 % _0x4cdef5['length'])) % (0x16d0 + 0x12 * -0xf4 + 0x254 * -0x2),").Append("\r\n"); + builer.Append(" _0x2b4641 = _0xbb44d8[_0x369701],").Append("\r\n"); + builer.Append(" _0xbb44d8[_0x369701] = _0xbb44d8[_0x138ea3],").Append("\r\n"); + builer.Append(" _0xbb44d8[_0x138ea3] = _0x2b4641;").Append("\r\n"); + builer.Append(" let _0x1a0256 = 0x1ca3 + 0x1a34 + -0x36d7;").Append("\r\n"); + builer.Append(" _0x138ea3 = 0xdc * 0x28 + -0x15d * 0x1 + 0x3ab * -0x9;").Append("\r\n"); + builer.Append(" for (let _0x1b288d = 0x9 * 0x349 + 0x1e7f + -0x3c10 * 0x1; _0x1b288d < _0x268c9c['length']; _0x1b288d++)").Append("\r\n"); + builer.Append(" _0x1a0256 = (_0x1a0256 + (0x14ef * -0x1 + -0x1752 + -0x37 * -0xce)) % (-0x312 + 0x171d + -0x130b),").Append("\r\n"); + builer.Append(" _0x138ea3 = (_0x138ea3 + _0xbb44d8[_0x1a0256]) % (0x3 * 0x66d + -0x3 * -0x13d + -0x15fe),").Append("\r\n"); + builer.Append(" _0x2b4641 = _0xbb44d8[_0x1a0256],").Append("\r\n"); + builer.Append(" _0xbb44d8[_0x1a0256] = _0xbb44d8[_0x138ea3],").Append("\r\n"); + builer.Append(" _0xbb44d8[_0x138ea3] = _0x2b4641,").Append("\r\n"); + builer.Append(" _0xc9f8ff += String['fromCharCode'](_0x268c9c['charCodeAt'](_0x1b288d) ^ _0xbb44d8[(_0xbb44d8[_0x1a0256] + _0xbb44d8[_0x138ea3]) % (-0x1db3 + 0x1 * -0x733 + -0x15 * -0x1ce)]);").Append("\r\n"); + builer.Append(" return _0xc9f8ff;").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function _0x22a2b6(_0x59d7ab, _0x151cde, _0x1e0c94, _0x54aa83, _0x76d8ab, _0x550bdb, _0xb90041, _0x44b16d, _0x28659f, _0x252c2c, _0x365218, _0x48af11, _0x25e3db, _0x34084f, _0x4f0729, _0x46a34c, _0x1f67f1, _0x5cd529, _0x53097b) {").Append("\r\n"); + builer.Append(" let _0xa0a6ac = new Uint8Array(0x21ed + 0x25dc + -0x47b6 * 0x1);").Append("\r\n"); + builer.Append(" return _0xa0a6ac[-0x1 * -0x2192 + 0x11b * 0x5 + -0x2719 * 0x1] = _0x59d7ab,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x4a * 0x3 + -0x6d * 0xb + -0x1e9 * -0x2] = _0x365218,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0x59f * -0x3 + -0x46c * -0x4 + -0x228b] = _0x151cde,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x11a1 + 0xf3d * -0x1 + 0x3 * -0xcb] = _0x48af11,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0x1 * -0xa37 + 0x13 * 0x173 + -0x25bc] = _0x1e0c94,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0x4 * -0x59f + -0x669 * 0x4 + 0x32d] = _0x25e3db,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0x1b42 + 0x10 * -0x24 + 0x1d88] = _0x54aa83,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x2245 + 0x335 * 0x6 + -0x357c] = _0x34084f,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x3fb + 0x18e1 + -0x1cd4] = _0x76d8ab,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x3 * 0x7a + 0x1 * 0x53f + 0x154 * -0x5] = _0x4f0729,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x25a * -0x9 + 0x11f6 + 0xa6 * 0x5] = _0x550bdb,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0x1b * -0x147 + -0x21e9 * -0x1 + 0x445b * -0x1] = _0x46a34c,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0x2f * 0xaf + 0x22f0 + -0x2c3] = _0xb90041,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x2f * 0x16 + 0x17 * 0x19 + -0x63c] = _0x1f67f1,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0x46a * 0x1 + 0xb * -0x97 + 0xaf5] = _0x44b16d,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x47 * 0x4f + -0x8cb * -0x4 + -0x3906] = _0x5cd529,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0x7 * 0x40e + 0xb8b + 0x10e7] = _0x28659f,").Append("\r\n"); + builer.Append(" _0xa0a6ac[0x6f9 + 0x196b + 0x5 * -0x677] = _0x53097b,").Append("\r\n"); + builer.Append(" _0xa0a6ac[-0xa78 + 0x1b89 + 0xe5 * -0x13] = _0x252c2c,").Append("\r\n"); + builer.Append(" String['fromCharCode']['apply'](null, _0xa0a6ac);").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function get_arr(arr) {").Append("\r\n"); + builer.Append(" arr.push(eval(arr.toString().replace(/,/g, \"^\")))").Append("\r\n"); + builer.Append(" let arr_1 = [], arr_2 = [];").Append("\r\n"); + builer.Append(" for (let i = 0; i < arr.length; i += 2) {").Append("\r\n"); + builer.Append(" arr_1.push(arr[i]);").Append("\r\n"); + builer.Append(" if (arr[i + 1]>=0) {").Append("\r\n"); + builer.Append(" arr_2.push(arr[i + 1])").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" arr_3 = arr_1.concat(arr_2)").Append("\r\n"); + builer.Append(" console.log(arr_3, arr_3.length)").Append("\r\n"); + builer.Append(" return arr_3").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function md5_slice_1(string) {").Append("\r\n"); + builer.Append(" md5_arr = decode(_0xf220d2(decode(_0xf220d2(string))))").Append("\r\n"); + builer.Append(" return [md5_arr[md5_arr.length - 2], md5_arr[md5_arr.length - 1]]").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function md5_slice_2(string) {").Append("\r\n"); + builer.Append(" md5_arr = decode(_0xf220d2(string))").Append("\r\n"); + builer.Append(" return [md5_arr[md5_arr.length - 2], md5_arr[md5_arr.length - 1]]").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function bytes2string(key, bytes) {").Append("\r\n"); + builer.Append(" let result = \"\"").Append("\r\n"); + builer.Append(" for (let i = 0; i < bytes.length / 3; i++) {").Append("\r\n"); + builer.Append(" if (bytes.charCodeAt(i * 3 + 1)) {").Append("\r\n"); + builer.Append(" const num = (bytes.charCodeAt(i * 3) << 16) + (bytes.charCodeAt(i * 3 + 1) << 8) + (bytes.charCodeAt(i * 3 + 2))").Append("\r\n"); + builer.Append(" result += key.charAt((num & 16515072) >> 18)").Append("\r\n"); + builer.Append(" result += key.charAt((num & 258048) >> 12)").Append("\r\n"); + builer.Append(" result += key.charAt((num & 4032) >> 6)").Append("\r\n"); + builer.Append(" result += key.charAt(num & 63)").Append("\r\n"); + builer.Append(" } else {").Append("\r\n"); + builer.Append(" const num = (bytes.charCodeAt(i * 3) << 16)").Append("\r\n"); + builer.Append(" result += key.charAt((num & 16515072) >> 18)").Append("\r\n"); + builer.Append(" result += key.charAt((num & 258048) >> 12)").Append("\r\n"); + builer.Append(" result += \"=\"").Append("\r\n"); + builer.Append(" result += \"=\"").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" return result").Append("\r\n"); + builer.Append("}").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("function get_x_bogus(params, body,user_agent) {").Append("\r\n"); + builer.Append(" time_13=new Date / 1000 ^ 0").Append("\r\n"); + builer.Append(" canvas = 2691034029").Append("\r\n"); + builer.Append(" calc_arr = [1, 1, 8]").Append("\r\n"); + builer.Append(" str_ua = bytes2string(key_2,_0x238632(String.fromCharCode.apply(String, calc_arr), user_agent))").Append("\r\n"); + builer.Append(" console.log(str_ua)").Append("\r\n"); + builer.Append(" arr_4_1 = md5_slice_1(params)").Append("\r\n"); + builer.Append(" if (body) {").Append("\r\n"); + builer.Append(" arr_4_2 = md5_slice_1(body)").Append("\r\n"); + builer.Append(" } else {").Append("\r\n"); + builer.Append(" arr_4_2 = md5_slice_1('')").Append("\r\n"); + builer.Append(" }").Append("\r\n"); + builer.Append(" arr_4_3 = md5_slice_2(str_ua)").Append("\r\n"); + builer.Append(" arr_4_4 = [time_13 >> 24 & 255, time_13 >> 16 & 255, time_13 >> 8 & 255, time_13 >> 0 & 255]").Append("\r\n"); + builer.Append(" arr_4_5 = [canvas >> 24 & 255, canvas >> 16 & 255, canvas >> 8 & 255, canvas >> 0 & 255]").Append("\r\n"); + builer.Append(" _0x30af53 = get_arr([64].concat(calc_arr).concat(arr_4_1).concat(arr_4_2).concat(arr_4_3).concat(arr_4_4).concat(arr_4_5))").Append("\r\n"); + builer.Append(" ss = String.fromCharCode.apply(null,[2,255]) + _0x238632(String.fromCharCode(255), _0x22a2b6['apply'](null, _0x30af53))").Append("\r\n"); + builer.Append(" var X_Bogus = bytes2string(key_1,ss)").Append("\r\n"); + builer.Append(" console.log(X_Bogus)").Append("\r\n"); + builer.Append(" return X_Bogus").Append("\r\n"); + builer.Append("}").Append("\r\n"); + _js_xbcode = builer.ToString(); + } + return _js_xbcode; + } + } + + private static string _js_sign = ""; + private static string Js_Sign + { + get + { + if (string.IsNullOrEmpty(_js_sign)) + { + StringBuilder builder = new StringBuilder(); + builder.Append($"function t_1(add, string) {{").AppendLine(); + builder.Append($" for (let x of string) {{").AppendLine(); + builder.Append($" add = ((add ^ x.charCodeAt()) * 65599) >>> 0").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" return add").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function t_2(num_1, num_2) {{").AppendLine(); + builder.Append($" let a = num_1 % 65521").AppendLine(); + builder.Append($" let b = a * 65521").AppendLine(); + builder.Append($" let c = num_2 ^ b").AppendLine(); + builder.Append($" let d = c >>> 0").AppendLine(); + builder.Append($" let e = d.toString(2)").AppendLine(); + builder.Append($" if (e.length < 33) {{").AppendLine(); + builder.Append($" let qq = '0'.repeat(32 - e.length)").AppendLine(); + builder.Append($" f = 10000000110000 + qq").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" let g = f + e").AppendLine(); + builder.Append($" return parseInt(g, 2).toString()").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function t_3(data_url) {{").AppendLine(); + builder.Append($" num_1 = data_url.charCodeAt()").AppendLine(); + builder.Append($" for (var i = 0; i < 31; i++) {{").AppendLine(); + builder.Append($" let a = num_1 * 65599").AppendLine(); + builder.Append($" let b = num_1 % data_url.length").AppendLine(); + builder.Append($" let c = data_url.charCodeAt(b)").AppendLine(); + builder.Append($" num_1 = a + c >>> 0").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" return num_1").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function t_4(ua) {{").AppendLine(); + builder.Append($" num_1 = ua.charCodeAt()").AppendLine(); + builder.Append($" let aa = aaaaaaaaa ^ num_1").AppendLine(); + builder.Append($" let add = ''").AppendLine(); + builder.Append($" for (var i = 1; i < ua.length + 1; i++) {{").AppendLine(); + builder.Append($" let b = aa * 65599").AppendLine(); + builder.Append($" let c = b >>> 0").AppendLine(); + builder.Append($" let d = ua.charCodeAt(i)").AppendLine(); + builder.Append($" add = c").AppendLine(); + builder.Append($" aa = c ^ d").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" return add").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function t_5(url) {{").AppendLine(); + builder.Append($" let aa = url.charCodeAt()").AppendLine(); + builder.Append($" for (var i = 1; i < url.length + 1; i++) {{").AppendLine(); + builder.Append($" let b = aa * 65599").AppendLine(); + builder.Append($" let c = b >>> 0").AppendLine(); + builder.Append($" let d = url.charCodeAt(i)").AppendLine(); + builder.Append($" aa = c ^ d").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" return aa").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function get_5(c_3) {{").AppendLine(); + builder.Append($" let a = c_3 / 4294967296").AppendLine(); + builder.Append($" return a >>> 0").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function a(num) {{").AppendLine(); + builder.Append($" if (num < 26) {{").AppendLine(); + builder.Append($" return num + 65").AppendLine(); + builder.Append($" }} else if (num < 52) {{").AppendLine(); + builder.Append($" return num + 71").AppendLine(); + builder.Append($" }} else if (num < 62) {{").AppendLine(); + builder.Append($" return num + -4").AppendLine(); + builder.Append($" }} else {{").AppendLine(); + builder.Append($" return num + -17").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function s1(str_1) {{").AppendLine(); + builder.Append($" str_2 = str_1 >> 2").AppendLine(); + builder.Append($" str_3 = str_2 >> 24").AppendLine(); + builder.Append($" str_4 = str_3 & 63").AppendLine(); + builder.Append($" str_5 = a(str_4)").AppendLine(); + builder.Append($" str_6 = String.fromCharCode(str_5)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_7 = str_2 >> 18").AppendLine(); + builder.Append($" str_8 = str_7 & 63").AppendLine(); + builder.Append($" str_9 = a(str_8)").AppendLine(); + builder.Append($" str_10 = String.fromCharCode(str_9)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_11 = str_2 >> 12").AppendLine(); + builder.Append($" str_12 = str_11 & 63").AppendLine(); + builder.Append($" str_13 = a(str_12)").AppendLine(); + builder.Append($" str_14 = String.fromCharCode(str_13)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_15 = str_2 >> 6").AppendLine(); + builder.Append($" str_16 = str_15 & 63").AppendLine(); + builder.Append($" str_17 = a(str_16)").AppendLine(); + builder.Append($" str_18 = String.fromCharCode(str_17)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_19 = str_2").AppendLine(); + builder.Append($" str_20 = str_19 & 63").AppendLine(); + builder.Append($" str_21 = a(str_20)").AppendLine(); + builder.Append($" str_22 = String.fromCharCode(str_21)").AppendLine(); + builder.Append($" return str_6 + str_10 + str_14 + str_18 + str_22").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function s2(str_1) {{").AppendLine(); + builder.Append($" str_2 = str_1 << 28").AppendLine(); + builder.Append($" str_3 = str_2 | get_5(str_1) >>> 4").AppendLine(); + builder.Append($" str_4 = str_3 >> 24").AppendLine(); + builder.Append($" str_5 = str_4 & 63").AppendLine(); + builder.Append($" str_5 = a(str_5)").AppendLine(); + builder.Append($" str_6 = String.fromCharCode(str_5)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_7 = str_3 >> 18").AppendLine(); + builder.Append($" str_8 = str_7 & 63").AppendLine(); + builder.Append($" str_9 = a(str_8)").AppendLine(); + builder.Append($" str_10 = String.fromCharCode(str_9)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_11 = str_3 >> 12").AppendLine(); + builder.Append($" str_12 = str_11 & 63").AppendLine(); + builder.Append($" str_13 = a(str_12)").AppendLine(); + builder.Append($" str_14 = String.fromCharCode(str_13)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_15 = str_3 >> 6").AppendLine(); + builder.Append($" str_16 = str_15 & 63").AppendLine(); + builder.Append($" str_17 = a(str_16)").AppendLine(); + builder.Append($" str_18 = String.fromCharCode(str_17)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_19 = str_3").AppendLine(); + builder.Append($" str_20 = str_19 & 63").AppendLine(); + builder.Append($" str_21 = a(str_20)").AppendLine(); + builder.Append($" str_22 = String.fromCharCode(str_21)").AppendLine(); + builder.Append($" return str_6 + str_10 + str_14 + str_18 + str_22").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function s3(str_1) {{").AppendLine(); + builder.Append($" aa = c_4 ^ str_1").AppendLine(); + builder.Append($" str1 = aa >>> 6").AppendLine(); + builder.Append($" str_2 = get_5(str_1) << 26").AppendLine(); + builder.Append($" str_3 = str_2 | str1").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_4 = str_3 >> 24").AppendLine(); + builder.Append($" str_5 = str_4 & 63").AppendLine(); + builder.Append($" str_5 = a(str_5)").AppendLine(); + builder.Append($" str_6 = String.fromCharCode(str_5)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_7 = str_3 >> 18").AppendLine(); + builder.Append($" str_8 = str_7 & 63").AppendLine(); + builder.Append($" str_9 = a(str_8)").AppendLine(); + builder.Append($" str_10 = String.fromCharCode(str_9)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_11 = str_3 >> 12").AppendLine(); + builder.Append($" str_12 = str_11 & 63").AppendLine(); + builder.Append($" str_13 = a(str_12)").AppendLine(); + builder.Append($" str_14 = String.fromCharCode(str_13)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_15 = str_3 >> 6").AppendLine(); + builder.Append($" str_16 = str_15 & 63").AppendLine(); + builder.Append($" str_17 = a(str_16)").AppendLine(); + builder.Append($" str_18 = String.fromCharCode(str_17)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_19 = str_3").AppendLine(); + builder.Append($" str_20 = str_19 & 63").AppendLine(); + builder.Append($" str_21 = a(str_20)").AppendLine(); + builder.Append($" str_22 = String.fromCharCode(str_21)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_23 = c_4 ^ str_1").AppendLine(); + builder.Append($" str_24 = str_23 & 63").AppendLine(); + builder.Append($" str_25 = a(str_24)").AppendLine(); + builder.Append($" str_26 = String.fromCharCode(str_25)").AppendLine(); + builder.Append($" return str_6 + str_10 + str_14 + str_18 + str_22 + str_26").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function s4(str_1) {{").AppendLine(); + builder.Append($" str_4 = str_1 >> 2").AppendLine(); + builder.Append($" str_5 = str_4 >> 24").AppendLine(); + builder.Append($" str_6 = str_5 & 63").AppendLine(); + builder.Append($" str_7 = a(str_6)").AppendLine(); + builder.Append($" str_8 = String.fromCharCode(str_7)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_9 = str_4 >> 18").AppendLine(); + builder.Append($" str_10 = str_9 & 63").AppendLine(); + builder.Append($" str_11 = a(str_10)").AppendLine(); + builder.Append($" str_12 = String.fromCharCode(str_11)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_13 = str_4 >> 12").AppendLine(); + builder.Append($" str_14 = str_13 & 63").AppendLine(); + builder.Append($" str_15 = a(str_14)").AppendLine(); + builder.Append($" str_16 = String.fromCharCode(str_15)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_17 = str_4 >> 6").AppendLine(); + builder.Append($" str_18 = str_17 & 63").AppendLine(); + builder.Append($" str_19 = a(str_18)").AppendLine(); + builder.Append($" str_20 = String.fromCharCode(str_19)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_21 = str_4").AppendLine(); + builder.Append($" str_22 = str_21 & 63").AppendLine(); + builder.Append($" str_23 = a(str_22)").AppendLine(); + builder.Append($" str_24 = String.fromCharCode(str_23)").AppendLine(); + builder.Append($" return str_8 + str_12 + str_16 + str_20 + str_24").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function s5(str_1) {{").AppendLine(); + builder.Append($" let cc = 2 << 4").AppendLine(); + builder.Append($" let bb = 1 << 8 // 65792").AppendLine(); + builder.Append($" str_q = bb | cc").AppendLine(); + builder.Append($" str_2 = b << 28").AppendLine(); + builder.Append($" let oo = str_q ^ str_1").AppendLine(); + builder.Append($" let qqq = oo >>> 4").AppendLine(); + builder.Append($" str_3 = str_2 | qqq").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_4 = str_3 >> 24").AppendLine(); + builder.Append($" str_5 = str_4 & 63").AppendLine(); + builder.Append($" str_5 = a(str_5)").AppendLine(); + builder.Append($" str_6 = String.fromCharCode(str_5)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_7 = str_3 >> 18").AppendLine(); + builder.Append($" str_8 = str_7 & 63").AppendLine(); + builder.Append($" str_9 = a(str_8)").AppendLine(); + builder.Append($" str_10 = String.fromCharCode(str_9)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_11 = str_3 >> 12").AppendLine(); + builder.Append($" str_12 = str_11 & 63").AppendLine(); + builder.Append($" str_13 = a(str_12)").AppendLine(); + builder.Append($" str_14 = String.fromCharCode(str_13)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_15 = str_3 >> 6").AppendLine(); + builder.Append($" str_16 = str_15 & 63").AppendLine(); + builder.Append($" str_17 = a(str_16)").AppendLine(); + builder.Append($" str_18 = String.fromCharCode(str_17)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_19 = str_3").AppendLine(); + builder.Append($" str_20 = str_19 & 63").AppendLine(); + builder.Append($" str_21 = a(str_20)").AppendLine(); + builder.Append($" str_22 = String.fromCharCode(str_21)").AppendLine(); + builder.Append($" return str_6 + str_10 + str_14 + str_18 + str_22").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function s6(str_1) {{").AppendLine(); + builder.Append($" str_2 = str_1 % 65521").AppendLine(); + builder.Append($" str_3 = str_2 >> 24").AppendLine(); + builder.Append($" str_4 = str_3 & 63").AppendLine(); + builder.Append($" str_5 = a(str_4)").AppendLine(); + builder.Append($" str_6 = String.fromCharCode(str_5)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_7 = str_2 >> 18").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_8 = str_7 & 63").AppendLine(); + builder.Append($" str_9 = a(str_8)").AppendLine(); + builder.Append($" str_10 = String.fromCharCode(str_9)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_11 = str_2 >> 12").AppendLine(); + builder.Append($" str_12 = str_11 & 63").AppendLine(); + builder.Append($" str_13 = a(str_12)").AppendLine(); + builder.Append($" str_14 = String.fromCharCode(str_13)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_15 = str_2 >> 6").AppendLine(); + builder.Append($" str_16 = str_15 & 63").AppendLine(); + builder.Append($" str_17 = a(str_16)").AppendLine(); + builder.Append($" str_18 = String.fromCharCode(str_17)").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" str_19 = str_2").AppendLine(); + builder.Append($" str_20 = str_19 & 63").AppendLine(); + builder.Append($" str_21 = a(str_20)").AppendLine(); + builder.Append($" str_22 = String.fromCharCode(str_21)").AppendLine(); + builder.Append($" return str_6 + str_10 + str_14 + str_18 + str_22").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function s7(sign) {{").AppendLine(); + builder.Append($" num_1 = sign.charCodeAt()").AppendLine(); + builder.Append($" for (var i = 1; i < 45; i++) {{").AppendLine(); + builder.Append($" let a = num_1 * 65599").AppendLine(); + builder.Append($" let c = sign.charCodeAt(i)").AppendLine(); + builder.Append($" num_1 = a + c >>> 0").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" return num_1.toString(16).slice(6, 8)").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function url_sort(url) {{").AppendLine(); + builder.Append($" if (url.indexOf('http')!=-1){{").AppendLine(); + builder.Append($" let a = url.split('?')").AppendLine(); + builder.Append($" let b = a[0]").AppendLine(); + builder.Append($" let c = a[1] // 参数").AppendLine(); + builder.Append($" let d = b.split('buyin.jinritemai.com')[1] // pathname=/aweme/v1/web/search/item/").AppendLine(); + builder.Append($" let f = c.split('&')").AppendLine(); + builder.Append($" let g = {{}}").AppendLine(); + builder.Append($" for (x of f) {{").AppendLine(); + builder.Append($" g[x.split('=')[0]] = x.split('=')[1]").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" let h = Object.keys(g).sort()").AppendLine(); + builder.Append($" let j = []").AppendLine(); + builder.Append($" for (x of h) {{").AppendLine(); + builder.Append($" let q = x + '=' + g[x]").AppendLine(); + builder.Append($" j.push(q)").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" j.push('pathname=' + d)").AppendLine(); + builder.Append($" j.push('tt_webid=' + '')").AppendLine(); + builder.Append($" j.push('uuid=' + '')").AppendLine(); + builder.Append($" k = j.join('&')").AppendLine(); + builder.Append($" }}else {{").AppendLine(); + builder.Append($" k=url").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" return k").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function body_hash(url) {{").AppendLine(); + builder.Append($" url = JSON.stringify(url)").AppendLine(); + builder.Append($" let aa = url.charCodeAt()").AppendLine(); + builder.Append($" for (var i = 1; i < url.length; i++) {{").AppendLine(); + builder.Append($" let b = aa * 65599").AppendLine(); + builder.Append($" let d = url.charCodeAt(i)").AppendLine(); + builder.Append($" aa = b + d >>> 0").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" return 'body_hash=' + aa + '&'").AppendLine(); + builder.Append($"}}").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($"function get_sign_url(url, body, user_agent) {{").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" canvas = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAQCAYAAABQrvyxAAACNklEQVRIS8WWP0iVYRTGf3cJcmjJrS0Ht4TWdElIdHFwCNIgcnALnKO64SQIgiB6wa0/0NDQFBIEYi4OQdDSFkHaUIuL4KI8cg4cj+/3ebncm9/y3e/9c97zPM95znsbnH2O07c+GzamOf9dWPbfhwaB2VJCnmhOOIPrJZjrwBtgLNHSAuaBQ+AcgBL7vj8nexlq3AHuAguWVFGBEuuxhCIhvVQg1+NVYBl4D0wBc7agVWI2b67yQAQ7DTw0dp4DT4AfgMZfAxpz5hRf7L0DhjyRUBolMynOzUKMcx6oU0CBSz6QtF9CIl+B28A68AB4CywGUF7fArQDOLvbVvcZgJIfMYB9yRtFBdphPLMvdj7byarTG8AB8AH4C6wEABGwKxOTlEH1OFCBjOo5wFoTC4SzHX97W41zfpDmdNAq8AIYB54C/QmAl1AElQE8AwRU4/8qGnQRgCcb3146pbmmBfe3DtXha8AtA6SDYrLa4us8wZICkenoFx+fUTlFE1e10axAJEQG3QI2bNAT+wm8shqPAH5ZN1EX2QwMVwHIQP1s983vi1phXb/X3L6VyrcAQIaOyUUAWjYB7JpSFykgNeUt+SA/itusUqBdD3wC7oXIbtDYNqsUOC0B21ungDx139pyrQL5L0RkvzT3B3gMfKwwWbeG853hcYelTFYgGzV2HZ+7Zi3S57qVaEdxSh64AhxVRJPUS3ZJvezoxC5vKgGYBB7ZBbRn98EAMAp8ty7S67JpG+YJtseqHtBfgugAAAAASUVORK5CYII='").AppendLine(); + builder.Append($" host = 'buyin.jinritemai.com/'").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" timestamp = parseInt(new Date().getTime() / 1000).toString()").AppendLine(); + builder.Append($"").AppendLine(); + builder.Append($" c_1 = t_1('', timestamp)").AppendLine(); + builder.Append($" c_2 = t_1(c_1, host)").AppendLine(); + builder.Append($" c_3 = t_2(c_2, timestamp)").AppendLine(); + builder.Append($" c_4 = t_3(canvas)").AppendLine(); + builder.Append($" aaaaaaaaa = t_5(c_3)").AppendLine(); + builder.Append($" x1 = t_4(user_agent)").AppendLine(); + builder.Append($" if (body) {{").AppendLine(); + builder.Append($" body_ = body_hash(body)").AppendLine(); + builder.Append($" }} else {{").AppendLine(); + builder.Append($" body_ = ''").AppendLine(); + builder.Append($" }}").AppendLine(); + builder.Append($" url = url_sort(url)").AppendLine(); + builder.Append($" x2 = t_4(body_ + url)").AppendLine(); + builder.Append($" s_1 = s1(c_3)").AppendLine(); + builder.Append($" s_2 = s2(c_3)").AppendLine(); + builder.Append($" s_3 = s3(c_3)").AppendLine(); + builder.Append($" str__1 = x1 % 65521").AppendLine(); + builder.Append($" str__2 = x2 % 65521").AppendLine(); + builder.Append($" str__3 = str__1 << 16").AppendLine(); + builder.Append($" b = str__3 | str__2").AppendLine(); + builder.Append($" s_4 = s4(b)").AppendLine(); + builder.Append($" s_5 = s5(c_3)").AppendLine(); + builder.Append($" s_6 = s6(c_2)").AppendLine(); + builder.Append($" sign_1 = '_02B4Z6wo00101' + s_1 + s_2 + s_3 + s_4 + s_5 + s_6").AppendLine(); + builder.Append($" sign_2 = s7(sign_1)").AppendLine(); + builder.Append($" return sign_1 + sign_2").AppendLine(); + builder.Append($"}}").AppendLine(); + _js_sign = builder.ToString(); + } + return _js_sign; + } + } + + /// + /// 使用V8引擎执行JS代码 + /// + /// JS代码 + /// 当前方法需要的参数 + /// 执行的JS方法名 + /// + private static string V8Method(string JsCode, string JsParam, string JsMethodName) + { + string result = string.Empty; + try + { + using (var engine = new V8ScriptEngine()) + { + V8Script script = engine.Compile(JsCode); + engine.Execute(script); + result = engine.ExecuteCommand(string.Format("{0}({1})", JsMethodName, JsParam)); + //其他写法 + } + } + catch (Exception ex) + { + //result = ex.Message.ToString(); + } + return result; + } + + //function get_sign_url(url, body, user_agent) + private static string GetSign(string Param, string UserAgent, string PostData = "") + { + return V8Method(Js_Sign, $"'{Param}','{PostData}','{UserAgent}'", "get_sign_url"); + } + + private static string GetXbogus(string Param, string UserAgent, string PostData = "") + { + return V8Method(Js_Xbcode, $"'{Param}','{PostData}','{UserAgent}'", "get_x_bogus"); + } + #endregion + + #endregion + + /// + /// 订单下载-官方 + /// + /// + /// + /// + /// + public List DownOrderApi(DateTime start_time, DateTime end_time, string pid) + { + var list = new List(); + var cursor = "0"; + + DyOrderInfo order = null; + do + { + var jToken = SendData("buyin.kolOrderAds", new { start_time = start_time.ToString("yyyy-MM-dd HH:mm:ss"), end_time = end_time.ToString("yyyy-MM-dd HH:mm:ss"), pid = pid, size = 20, cursor = cursor, distribution_type = "ProductDetail" }); + if (jToken == null) return list; + + var data = jToken["data"]; + if (data != null) + { + order = Util.ToObj(data); + + if (order == null || order.orders == null || order.orders.Count == 0) return list; + list.Add(order); + cursor = order.cursor; + } + else + break; + Thread.Sleep(1); + } while (order != null && !string.IsNullOrWhiteSpace(cursor)); + return list; + } + + + /// + /// 获取抖音推广位信息 + /// + /// 第一页 + /// 每页大小 + /// + public KolPidList FindPidList(int page = 1, int pageSize = 100) + { + var jToken = SendData("buyin.kolPidList", new { page = page, page_size = pageSize }); + + if (jToken == null) return null; + + var data = jToken["data"]; + if (data != null) + { + return Util.ToObj(data); + } + return null; + } + + + public KolPidList ConvertInstPickSource(string url) + { + var jToken = SendData("buyin.instPickSourceConvert", new { product_url = url }); + + if (jToken == null) return null; + + var data = jToken["data"]; + if (data != null) + { + return Util.ToObj(data); + } + return null; + } + + + /// + /// 查询商品信息 + /// + /// 商品id + /// 返回可分销状态 sharable 字段 + public DyItemInfo FindItemInfo(string itemid, bool with_share_status = true) + { + try + { + var jToken = SendData("alliance.materialsProductsDetails", new { product_ids = $"[{itemid}]", with_share_status = with_share_status }); + + if (jToken == null) return null; + + var data = jToken["data"]; + if (data != null) + { + return Util.ToObj(data); + } + } + catch (Exception ex) + { + throw ex; + } + return null; + } + + /// + /// 获取推广的商品 + /// + public void GetShareMaterial() + { + try + { + var jToken = SendData("buyin.getProductShareMaterial", new { }); + + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 转链 + /// + /// 商品连接 + /// 达人PID + /// 自定义参数 + public ShareInfo ConvertUrl(string product_url, string pid, string external_info) + { + try + { + var jToken = SendData("buyin.kolProductShare", new { product_url = product_url, pid = pid, external_info = external_info }); + + if (jToken == null) return null; + + var data = jToken["data"]; + if (data != null) + { + return Util.ToObj(data); + } + else + throw new Exception(JsonConvert.SerializeObject(jToken)); + //{"code":50002,"err_no":7,"log_id":"202202231957160101330351311C082EFF","message":"当前商品暂不支持站外分享","msg":"业务处理失败","sub_code":"isv.business-failed:276","sub_msg":"当前商品暂不支持站外分享"} + } + catch (Exception ex) + { + throw ex; + } + return null; + } + + + public bool CreateKolPid(int media_type, string site_name) + { + try + { + var media_name = "微信推广"; + var jToken = SendData("buyin.kolPidCreate", new { media_type = media_type, media_name = media_name, site_name = site_name }); + + if (jToken == null) return false; + + var pid = jToken["data"]["pid"].ToString(); + if (!string.IsNullOrWhiteSpace(pid)) + return true; + } + catch (Exception ex) + { + } + return false; + } + + + //private const string Appid = "7066380295942964749"; + //private const string Appsecret = "5723f45c-1493-46bd-a0d9-1e4bb65b77d0"; + + //private string access_token = "64706dde-57a3-4a6b-9760-bf3064610d17"; + + + //public static string LoginUrl { get { return $"https://buyin.jinritemai.com/dashboard/institution/through-power?app_id={Appid}&state=xx"; } } + + public JToken SendData(string ApiName, object Data, bool ThrowException = false) + { + int number = 0; + var html = string.Empty; + Next: + + number++; + + try + { + //var access_token = string.Empty; + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + + // 序列化参数 + var param_json = Marshal(Data); + + // 计算签名 + var signVal = Sign(Token.appid, Token.appkey, ApiName, timestamp, param_json); + //var signVal = Sign(Appid, Appsecret, ApiName, timestamp, param_json); + + var url = string.Empty; + if (ApiName == "token.create") + { + url = $"{host}/{ApiName.Replace('.', '/')}?app_key={Token.appid}&method={ApiName}¶m_json={HttpUtility.UrlEncode(param_json, Encoding.UTF8)}×tamp={HttpUtility.UrlEncode(timestamp, Encoding.UTF8)}&v={Ver}&sign={signVal}&sign_method={sign_method}"; + //url = $"{host}/{ApiName.Replace('.', '/')}?app_key={Appid}&method={ApiName}¶m_json={HttpUtility.UrlEncode(param_json, Encoding.UTF8)}×tamp={HttpUtility.UrlEncode(timestamp, Encoding.UTF8)}&v={Ver}&sign={signVal}&sign_method={sign_method}"; + } + else + url = $"{host}/{ApiName.Replace('.', '/')}?app_key={Token.appid}&method={ApiName}&access_token={Token.access_token}¶m_json={HttpUtility.UrlEncode(param_json, Encoding.UTF8)}×tamp={HttpUtility.UrlEncode(timestamp, Encoding.UTF8)}&v={Ver}&sign={signVal}&sign_method={sign_method}"; + //url = $"{host}/{ApiName.Replace('.', '/')}?app_key={Appid}&method={ApiName}&access_token={access_token}¶m_json={HttpUtility.UrlEncode(param_json, Encoding.UTF8)}×tamp={HttpUtility.UrlEncode(timestamp, Encoding.UTF8)}&v={Ver}&sign={signVal}&sign_method={sign_method}"; + + // 发起请求 + var methodPath = ApiName; + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = url, + Method = "get", + ContentType = "application/json;charset=UTF-8", + Timeout = 5000, + }; + html = http.GetHtml(item).Html; + + if (html.ToLower().Contains("access_token") || html.ToLower().Contains("invalid")) + throw new Exception("失效"); + + var jObj = JObject.Parse(html); + + if ((int)jObj["code"] != 10000) + throw new Exception(html); + return jObj; + } + catch (Exception ex) + { + //{"code":90000,"err_no":7,"log_id":"20220307142917010150154220048FFC84","message":"获取用户客户端账户信息失败","msg":"未知错误,此错误会逐步细化明确,请不要依赖sub_code或sub_msg做业务判断","sub_code":"isp.unknown-error","sub_msg":"4158:获取用户客户端账户信息失败"} + + //{"code":40003,"err_no":30005,"log_id":"2022022811520301013214610523A49FAD","message":"access_token不存在,请使用最新的access_token访问","msg":"操作权限不足","sub_code":"isv.access-token-no-existed","sub_msg":"access_token不存在,请使用最新的access_token访问"} + if (ex.Message == "失效") + { + if (number < 3 && this.Member != null && RefToken() && this.Member.is_valid) goto Next; + Member.is_valid = false; + } + LogHelper.GetSingleObj().Debug("抖音请求", ApiName + ":" + ex.Message); + throw ex; + } + finally + { + LogHelper.GetSingleObj().Info("抖音Api请求", $"Api:{ApiName},{html}"); + } + } + + #region 抖音签名算法 + private const string host = "https://openapi-fxg.jinritemai.com"; + private const int Ver = 2; + private const string sign_method = "hmac-sha256"; + + //private const string Appid = "7066380295942964749"; + //private const string Appsecret = "5723f45c-1493-46bd-a0d9-1e4bb65b77d0"; + + + // 序列化参数 + // 这一步看上去冗余,实际很重要。如果要自己实现,则必须保证这三点: + // 1、保证JSON所有层级上Key的有序性 + // 2、保证JSON的所有数值不带多余的小数点 + // 3、保证转义逻辑与这段代码一致 + public static string Marshal(object o) + { + var raw = JsonConvert.SerializeObject(o); + + // 反序列化为JObject + var dict = JsonConvert.DeserializeObject(raw); + + // 重新序列化 + var settings = new JsonSerializerSettings(); + settings.Converters = new List { new JObjectConverter(), new JValueConverter() }; + return JsonConvert.SerializeObject(dict, Formatting.None, settings); + } + + // 计算签名 + public static string Sign(string appKey, string appSecret, string method, string timestamp, string paramJson) + { + // 按给定规则拼接参数 + var paramPattern = "app_key" + appKey + "method" + method + "param_json" + paramJson + "timestamp" + + timestamp + "v" + Ver; + var signPattern = appSecret + paramPattern + appSecret; + //Console.WriteLine("sign_pattern:" + signPattern); + + return Hmac(signPattern, appSecret); + } + + // 计算hmac + public static string Hmac(string plainText, string appSecret) + { + var h = new HMACSHA256(Encoding.UTF8.GetBytes(appSecret)); + var sum = h.ComputeHash(Encoding.UTF8.GetBytes(plainText)); + + var sb = new StringBuilder(); + foreach (byte b in sum) + { + sb.Append(b.ToString("x2")); + } + return sb.ToString(); + } + + // 自定义JObject的序列化方法,确保对象的Key按字典序输出 + class JObjectConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var val = value as JObject; + var props = val.Properties().OrderBy(i => i.Name).ToList(); + writer.WriteStartObject(); + foreach (var p in props) + { + writer.WritePropertyName(p.Name); + serializer.Serialize(writer, p.Value); + } + + writer.WriteEndObject(); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, + JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(JObject); + } + } + + // 自定义JValue的序列化方法,确保浮点数输出时移除小数点后多余的零 + class JValueConverter : JsonConverter + { + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var val = value as JValue; + if (val.Type == JTokenType.Float) + { + var d = Convert.ToDouble(val.Value); + var i = (long)d; + if (Math.Abs(i - d) == 0) // 针对float,如果小数点后的零是多余的,那么按整数方式输出 + { + writer.WriteValue(i); + return; + } + } + writer.WriteValue(value); // 否则按原逻辑 + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(JValue); + } + } + + #endregion + + } +} diff --git a/类库/Api.Framework/Cps/DtkApi.cs b/类库/Api.Framework/Cps/DtkApi.cs new file mode 100644 index 0000000..f6ac5d6 --- /dev/null +++ b/类库/Api.Framework/Cps/DtkApi.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Cps +{ + /// + /// 大淘客api + /// + public class DtkApi + { + private static DtkApi DTKApi = new DtkApi(); + private DtkApi() { } + + public static DtkApi GetDtkApi() + { + return DTKApi; + } + + //老道的大淘客appkey + private string _appKey = "61a59957d79af"; + + private string _appSecret = "dce4f8ea16af4a920e4f07015cc62ecd"; + + public string SendDtk(string apiUrl, ApiParameters parameters, string version = "v1.0.0") + { + string result3; + try + { + string url = this.BuildUrl(apiUrl, version, parameters); + using (HttpClient client = new HttpClient()) + { + HttpResponseMessage response = client.GetAsync(url).Result; + if (response.IsSuccessStatusCode) + { + Stream result2 = response.Content.ReadAsStreamAsync().Result; + StreamReader streamReader = new StreamReader(result2, Encoding.GetEncoding("utf-8")); + string result = streamReader.ReadToEnd(); + streamReader.Close(); + result2.Close(); + result3 = result; + } + else + { + result3 = response.StatusCode.ToString(); + } + } + } + catch (Exception ex) + { + result3 = ex.Message; + } + return result3; + } + + private string BuildUrl(string apiUrl, string version, ApiParameters parameters) + { + int nonce; + string timer; + string sign = this.MakeSign(out nonce, out timer); + if (sign == "") + { + return ""; + } + string url = string.Concat(new string[] + { + apiUrl.Trim(), + "?appKey=", + this._appKey.Trim(), + "&nonce=", + nonce.ToString(), + "&signRan=", + sign, + "&version=", + version.Trim(), + "&timer=", + timer + }); + if (parameters.Value.Count <= 0) + { + return url; + } + for (int i = 0; i <= parameters.Value.Count - 1; i++) + { + url += string.Format("&{0}={1}", parameters.Value[i].Key, parameters.Value[i].Value); + } + return url; + } + + private string MakeSign(out int nonce, out string timer) + { + Random rd = new Random(); + nonce = rd.Next(100000, 1000000); + timer = GetTimeStamp(); + string result; + try + { + result = Md5(string.Format("appKey={0}&timer={1}&nonce={2}&key={3}", new object[] + { + this._appKey, + timer, + nonce, + this._appSecret + })).ToUpper(); + } + catch (Exception) + { + result = ""; + } + return result; + } + + private static string GetTimeStamp() + { + return Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalMilliseconds).ToString(); + } + + private static string Md5(string value) + { + string result = string.Empty; + if (string.IsNullOrEmpty(value)) + { + return result; + } + using (MD5 md5 = MD5.Create()) + { + result = GetMd5Hash(md5, value); + } + return result; + } + + private static string GetMd5Hash(MD5 md5Hash, string input) + { + byte[] array = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); + StringBuilder sBuilder = new StringBuilder(); + foreach (byte t in array) + { + sBuilder.Append(t.ToString("x2")); + } + return sBuilder.ToString(); + } + } + + public class ApiParameters + { + private List> parameters = new List>(); + + public List> Value + { + get + { + return this.parameters; + } + } + + public void Add(string key, string value) + { + this.parameters.Add(new KeyValuePair(key, value)); + } + + public bool Delete(string key) + { + bool result; + try + { + int find = this.parameters.FindIndex((KeyValuePair a) => a.Key == key); + if (find >= 0) + { + this.parameters.RemoveAt(find); + } + result = true; + } + catch + { + result = false; + } + return result; + } + + public bool EditOrAdd(string key, string value) + { + bool result; + try + { + int find = this.parameters.FindIndex((KeyValuePair a) => a.Key == key); + if (find >= 0) + { + this.parameters.RemoveAt(find); + } + this.Add(key, value); + result = true; + } + catch + { + result = false; + } + return result; + } + + public bool Edit(string key, string value) + { + bool result; + try + { + int find = this.parameters.FindIndex((KeyValuePair a) => a.Key == key); + if (find >= 0) + { + this.parameters.RemoveAt(find); + this.Add(key, value); + } + result = true; + } + catch + { + result = false; + } + return result; + } + + public void Clear() + { + this.parameters.Clear(); + } + } +} diff --git a/类库/Api.Framework/Cps/DuoyinApi - 复制.cs b/类库/Api.Framework/Cps/DuoyinApi - 复制.cs new file mode 100644 index 0000000..dd024c8 --- /dev/null +++ b/类库/Api.Framework/Cps/DuoyinApi - 复制.cs @@ -0,0 +1,769 @@ +using Api.Framework.Cps.CefSharp1; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.Tools; +using CefSharp; +using CefSharp.WinForms; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Cps +{ + public class DouyinApi : BaseCpsApi + { + #region 抖音登录部分 + + public ChromiumWebBrowser chromeBrowser; + + public static Action douyinApiAction; + + /// + /// 抖音cookie + /// + private string cookie = string.Empty; + + public string GetCookie() + { + var tmp = new List(CookieCache) { }; + return JsonConvert.SerializeObject(tmp); + } + + public void SetMember(fl_cps_member Member) + { + this.Member = Member; + Heartbeat(); + } + + #endregion + + private List CookieCache = new List(); + + /// + /// 没什么用 + /// + public bool ISVIEW { get; private set; } = false; + + /// + /// 抖音首页 + /// + //private static string DouyinUrl = "https://www.douyinec.com/"; + private static string DouyinUrl = "https://buyin.jinritemai.com/dashboard"; + + static DouyinApi() + { + //CefSettings settings = new CefSettings(); + + ////日志文件 + //settings.LogFile = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/LogData"; + //settings.PersistSessionCookies = true; + //settings.WindowlessRenderingEnabled = true; + //settings.UserDataPath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/UserData"; + //// Initialize cef with the provided settings + //Cef.Initialize(settings); + } + + public DouyinApi(fl_cps_member member) : base(member) + { + InitializeChromium(string.IsNullOrWhiteSpace(member.username) ? Guid.NewGuid().ToString("N") : member.username); + } + + //初始化浏览器并启动 + public void InitializeChromium(string accountName) + { + RequestContext context = new RequestContext(new RequestContextSettings() + { + CachePath = HttpExtend.MapPath($"Cache\\Cef\\{accountName}"), + }); + //创建一个浏览器组件 + chromeBrowser = new ChromiumWebBrowser(DouyinUrl, context); + //this.tabPage2.Controls.Add(chromeBrowser); + //chromeBrowser.Dock = DockStyle.Fill; + chromeBrowser.AddressChanged += ChromeBrowser_AddressChanged; + + chromeBrowser.FrameLoadEnd += ChromeBrowser_FrameLoadEnd; + chromeBrowser.IsBrowserInitializedChanged += ChromeBrowser_IsBrowserInitializedChanged; + //注册自定义的请求/拦截响应 + var cefRequestHandler = new CEFRequestHandler(); + chromeBrowser.RequestHandler = cefRequestHandler; + cefRequestHandler.JsonAction += CefRequestHandler_JsonAction; + } + + private static string splitStr = "●●●"; + + /// + /// 初始化完成之后将cookie还原进去 + /// + /// + /// + private void ChromeBrowser_IsBrowserInitializedChanged(object sender, EventArgs e) + { + try + { + if (!string.IsNullOrWhiteSpace(Member.cookies)) + { + var cookies = JsonConvert.DeserializeObject>(Member.cookies); + + var cookieManager = chromeBrowser.GetCookieManager(); + //var cookieManager = CefSharp.Cef.GetGlobalCookieManager(); + foreach (string c in cookies) + { + var result = c.Split(new string[] { splitStr }, StringSplitOptions.RemoveEmptyEntries); + var cookieTmp = new CefSharp.Cookie + { + Creation = DateTime.Now, + Domain = result[0], + Name = result[1], + Value = result[2], + Expires = DateTime.Now.AddDays(20) + }; + cookie += $"{result[1]}={result[2]};"; + cookie = GetSmallCookie(cookie); + + if (!string.IsNullOrWhiteSpace(result[2])) + CookieCache.Add($"{result[0]}{splitStr}{result[1]}{splitStr}{result[2]}"); + //var b = cookieManager.SetCookieAsync(DouyinUrl, cookie).Result; + cookieManager.SetCookieAsync(DouyinUrl, cookieTmp); + } + ISVIEW = true; + } + + } + catch (Exception ex) + { + } + finally + { + chromeBrowser.Load(DouyinUrl); + } + } + + /// + /// 订单响应数据 + /// + /// + /// + private void CefRequestHandler_JsonAction(string url, string json) + { + IsQueryOrderRun = false; + orderjson = json; + Console.WriteLine($"@@@@@@@@@@@@@@@ {orderjson}"); + } + + private void ChromeBrowser_AddressChanged(object sender, AddressChangedEventArgs e) + { + Console.WriteLine($"######### = " + e.Address); + + //e.Address == "https://buyin.jinritemai.com/dashboard/live/control + + //在线的离线了, + if (e.Address == "https://www.douyinec.com/" && Member.is_valid) + { + Task.Run(() => + { + //if (isCheck) return; + //isCheck = true; + try + { + var end = DateTime.Now.AddMinutes(1); + do + { + Thread.Sleep(500); + + Member.cookies = GetCookie(); + var json = GetLoginUserInfo(); + if (!string.IsNullOrWhiteSpace(json)) + { + EventClient.OnEvent("获取抖音信息", json); + var jObj = JObject.Parse(json); + if (jObj != null && (int)jObj["code"] == 0) + { + //{"code":0,"data":{"account_avatar":"https://p6.douyinpic.com/img/tos-cn-i-0813/e87c3c6a24cb47568147aef8a949c392~c5_100x100.jpeg?from=4010531038","agree_pro":2,"anchor_coupon_menu_show":1,"buyin_account_id":"6978842327024533801","center_menu_show":1,"check_status":0,"child_status":0,"compass_first_level_menu_show":1,"compass_second_level_menu_show":1,"contact_not_set":1,"daren_plaza_popup":false,"daren_plaza_status":2,"doudian_shop_id":0,"dr_auth":{"1128":{"authority_shop":1,"authority_item":1,"authority_live":1}},"has_bind_star":0,"origin_uid":"1460607342872671","plaza_status":1,"qianchuan":1,"selection_plaza":1,"shop_id":"6978842327024550185","shop_name":"四面八方","shop_type":24,"shop_type_child":2,"shops":[{"agree_protocol":2,"check_status":0,"shop_id":"6978842327024550185","shop_name":"四面八方","shop_type":24,"shop_type_child":2,"status":1,"user_name":"四面八方"}],"status":1,"user_app":1128,"user_id":"123616240602295","user_identity_type":1,"user_name":"四面八方","user_role":1},"log_id":"202106301629040101980662044544AEAC","msg":"success","st":0} + + var userid = jObj["data"]["origin_uid"].ToString(); + var Member = CpsClient.Members.FirstOrDefault(f => f.username == userid && f.cpstype == CpsType.抖音联盟); + if (Member == null) + { + Member = new fl_cps_member() { username = userid, cpstype = CpsType.抖音联盟 }; + CpsClient.Members.Add(Member); + } + + Member.online = true; + Member.cookies = GetCookie(); + Member.usernick = jObj["data"]["shop_name"].ToString(); + + Member.logintime = DateTime.Now; + Member.is_valid = true; + CpsClient.AddDouyinApi(this); + this.Member = Member; + ApiClient.GetSession().SaveOrUpdate(Member); + EventClient.OnEvent("", $"抖音激活成功:{Member.usernick}({Member.username})"); + break; + } + else + { + IsQualifiedAction?.Invoke(!flag, this) + EventClient.OnEvent("抖音登录失败", json); + } + } + } while (end < DateTime.Now); + + //isCheck = false; + //this.Invoke(new Action(() => + //{ + // this.Close(); + //})); + } + catch (Exception ex) + { + EventClient.OnEvent("抖音登录失败", ex.Message + " - " + ex.StackTrace); + } + }); + } + + } + + private string orderjson = string.Empty; + + private Task GetOrderData() + { + return Task.Run(() => + { + try + { + if (!IsQueryOrderRun) + return null; + var endTime = DateTime.Now.AddSeconds(20); + do + { + Thread.Sleep(200); + if (!IsQueryOrderRun) + break; + } while (endTime > DateTime.Now); + var orderjsonTmp = orderjson; + return orderjsonTmp; + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + finally + { + IsQueryOrderRun = false; + orderjson = string.Empty; + } + return string.Empty; + }); + } + + /// + /// 执行查询的订单 + /// + public void QueryOrderButton() + { + try + { + chromeBrowser.EvaluateScriptAsync("document.getElementsByClassName('ant-btn ant-btn-primary')[0].click()"); + } + catch (Exception ex) + { + } + } + + public void SkipOther(string url) + { + try + { + chromeBrowser.Load(url); + Thread.Sleep(1000 + new Random().Next(200, 4000)); + } + catch (Exception ex) + { } + } + + /// + /// 是否在运行 + /// + private bool IsQueryOrderRun = false; + + private static string QueryOrderUrl = "https://buyin.jinritemai.com/dashboard/dataCenter/order"; + + /// + /// 跳转请求页面,实现查询以当前时间为基础的,七天订单 ☆☆☆☆☆ + /// + public Task SkipQueryOrder() + { + if (IsQueryOrderRun) return Task.FromResult("error"); + IsQueryOrderRun = true; + SkipOther("https://buyin.jinritemai.com/dashboard/dataCenter/export-list"); + var data = GetOrderData(); + SkipOther(QueryOrderUrl); + return data; + } + + /// + /// 登录的账号是否满足条件 + /// + public Action IsQualifiedAction; + + /// + /// 网页加载完毕 + /// + /// + /// + private void ChromeBrowser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e) + { + if (!ISVIEW && e.Url.StartsWith("https://summon.bytedance.com/web/?sign_token=")) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("function tempFunction() {"); + sb.AppendLine(" return document.getElementsByTagName('button')[0].innerHTML; "); + sb.AppendLine("}"); + sb.AppendLine("tempFunction();"); + chromeBrowser.EvaluateScriptAsync(sb.ToString()).ContinueWith(x => + { + var response = x.Result; + + if (response.Success && response.Result != null) + { + //var a = CpsClient.DouyinApiCache; + var startDate = response.Result; + var flag = startDate.ToString().Contains("暂无开通权限"); + if (!flag) + ISVIEW = true; + IsQualifiedAction?.Invoke(!flag, this); + } + }); + } + + CookieVisitor visitor = new CookieVisitor(); + visitor.SendCookie += visitor_SendCookie; + + ICookieManager cookieManager = chromeBrowser.GetCookieManager(); + cookieManager.VisitAllCookies(visitor); + } + + /// + /// 访问者收到的cookie + /// + /// + private void visitor_SendCookie(Cookie obj) + { + try + { + //System.Net.Cookie ck = new System.Net.Cookie(obj.Name, obj.Value); + //ck.Domain = obj.Domain; + + cookie += $"{obj.Name}={obj.Value};"; + cookie = GetSmallCookie(cookie); + + if (!string.IsNullOrWhiteSpace(obj.Value)) + CookieCache.Add($"{obj.Domain}{splitStr}{obj.Name}{splitStr}{obj.Value}"); + } + catch (Exception ex) + { } + } + + #region 需要抖音cookie + + //{"code":-2,"log_id":"202106301727440101980662104D4B7D05","msg":"用户未登录"} + //cookie失效提示 + + /// + /// 获取登录用户的信息 + /// + /// + public string GetLoginUserInfo() + { + try + { + if (Member == null || string.IsNullOrWhiteSpace(Member.cookies)) return string.Empty; + var item = new HttpItem() + { + URL = "https://buyin.jinritemai.com/index/getUser", + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookie, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "https://buyin.jinritemai.com/dashboard", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + + var http = new HttpHelper(); + var res = http.GetHtml(item); + var html = res.Html; + //{"code":0,"data":{"account_avatar":"https://p6.douyinpic.com/img/tos-cn-i-0813/e87c3c6a24cb47568147aef8a949c392~c5_100x100.jpeg?from=4010531038","agree_pro":2,"anchor_coupon_menu_show":1,"buyin_account_id":"6978842327024533801","center_menu_show":1,"check_status":0,"child_status":0,"compass_first_level_menu_show":1,"compass_second_level_menu_show":1,"contact_not_set":1,"daren_plaza_popup":false,"daren_plaza_status":2,"doudian_shop_id":0,"dr_auth":{"1128":{"authority_shop":1,"authority_item":1,"authority_live":1}},"has_bind_star":0,"origin_uid":"1460607342872671","plaza_status":1,"qianchuan":1,"selection_plaza":1,"shop_id":"6978842327024550185","shop_name":"四面八方","shop_type":24,"shop_type_child":2,"shops":[{"agree_protocol":2,"check_status":0,"shop_id":"6978842327024550185","shop_name":"四面八方","shop_type":24,"shop_type_child":2,"status":1,"user_name":"四面八方"}],"status":1,"user_app":1128,"user_id":"123616240602295","user_identity_type":1,"user_name":"四面八方","user_role":1},"log_id":"202106301629040101980662044544AEAC","msg":"success","st":0} + + return html; + } + catch (Exception ex) + { + Console.WriteLine($"获取登录用户信息异常:{ex.Message} - {ex.StackTrace}"); + } + return string.Empty; + } + + /// + /// 获取登录用户的信息 + /// + /// + public string GetUserInfo(string cookice) + { + try + { + var item = new HttpItem() + { + URL = "https://buyin.jinritemai.com/index/getUser", + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookice, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "https://buyin.jinritemai.com/dashboard", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + + var http = new HttpHelper(); + var res = http.GetHtml(item); + var html = res.Html; + //{"code":0,"data":{"account_avatar":"https://p6.douyinpic.com/img/tos-cn-i-0813/e87c3c6a24cb47568147aef8a949c392~c5_100x100.jpeg?from=4010531038","agree_pro":2,"anchor_coupon_menu_show":1,"buyin_account_id":"6978842327024533801","center_menu_show":1,"check_status":0,"child_status":0,"compass_first_level_menu_show":1,"compass_second_level_menu_show":1,"contact_not_set":1,"daren_plaza_popup":false,"daren_plaza_status":2,"doudian_shop_id":0,"dr_auth":{"1128":{"authority_shop":1,"authority_item":1,"authority_live":1}},"has_bind_star":0,"origin_uid":"1460607342872671","plaza_status":1,"qianchuan":1,"selection_plaza":1,"shop_id":"6978842327024550185","shop_name":"四面八方","shop_type":24,"shop_type_child":2,"shops":[{"agree_protocol":2,"check_status":0,"shop_id":"6978842327024550185","shop_name":"四面八方","shop_type":24,"shop_type_child":2,"status":1,"user_name":"四面八方"}],"status":1,"user_app":1128,"user_id":"123616240602295","user_identity_type":1,"user_name":"四面八方","user_role":1},"log_id":"202106301629040101980662044544AEAC","msg":"success","st":0} + + return html; + } + catch (Exception ex) + { + Console.WriteLine($"获取登录用户信息异常:{ex.Message} - {ex.StackTrace}"); + } + return string.Empty; + } + + #endregion + + /// + /// 检测cookie是否还有效(心跳) + /// + public void Heartbeat() + { + Task.Run(() => + { + do + { + Thread.Sleep(200000 + new Random().Next(2000000, 30000000)); + var json = GetLoginUserInfo(); + if (!string.IsNullOrWhiteSpace(json)) + { + var jObj = JObject.Parse(json); + if (jObj != null && (int)jObj["code"] == 0) + { + Console.WriteLine($"账号:{Member.usernick}({Member.username})在线..."); + } + else + { + Console.WriteLine($"账号:{Member.usernick}({Member.username})离线了"); + return; + } + } + } while (true); + }); + } + + /// + /// 口令解析地址 + /// + private const string AnalysisCmdUrl = @"https://aweme.snssdk.com/aweme/v2/platform/share/command/trans/?command={0}&support_type=16&os_api=22&device_type=MI+9&ssmix=a&manifest_version_code=160201&dpi=320&uuid=863254393831028&app_name=aweme&version_name=16.2.0&ts={1}&cpu_support64=false&app_type=normal&appTheme=dark&ac=wifi&host_abi=armeabi-v7a&update_version_code=16209900&channel=tengxun_1128_0531&_rticket=1624938653257&device_platform=android&iid=3466131644356413&version_code=160200&cdid={2}&is_android_pad=0&openudid=0347cf3f47c211af&device_id=1478167560454807&resolution=900*1600&os_version=5.1.1&language=zh&device_brand=Xiaomi&aid=1128&minor_status=0&mcc_mnc=46007"; + + /// + /// 搜索商品(商品链接搜索,或标题搜索) + /// + private const string SearchUrl = @"https://buyin.jinritemai.com/pc/selection/search/pmt?page_size=60&page=1&search_text={0}&_signature={1}"; + + /// + /// 橱窗商品列表搜索地址 + /// + private const string ShopWindowUrl = @"https://buyin.jinritemai.com/api/shop/search?hide_status=0&promotion_source=0&title={0}&page=1&pageSize=20&_signature={1}"; + + /// + /// 添加商品至橱柜 + /// + private const string AddGoods_WindowUrl = @"https://buyin.jinritemai.com/pc/selection/window/pmt/add?_signature={0}"; + + /// + /// 将抖音口令解析成商品id + /// + public static string AnalysisCmdToGoodsUrl(string kl) + { + try + { + var analysisCmdUrl = string.Format(AnalysisCmdUrl, HttpHelper.URLEncode(kl), HttpExtend.GetTimeStamp(), Guid.NewGuid().ToString()); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = analysisCmdUrl, + Method = "get", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "text/html", + Allowautoredirect = false, + ProxyIp = "", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + string cookie = result.Cookie; + + var jObj = JObject.Parse(html); + if (html.Contains("schema")) + { + var schema = jObj["schema"].ToString(); + var reg = Regex.Match(schema, @"product_id=(?<商品id>\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + { + return reg.Groups["商品id"].Value; + } + } + } + catch (Exception ex) + { + Console.WriteLine($"抖音口令解析异常:{ex.Message} - {ex.StackTrace} - kl:{kl}"); + } + return string.Empty; + } + + + /// + /// 通过商品链接查询商品信息 + /// + /// + /// 返回商品的基础信息 + public DouyinGoodsInfo FindGoodsInfo(string goodsId) + { + try + { + var sign = "";//TODO 这个可以为空 + var searchUrl = string.Format(SearchUrl, HttpHelper.URLEncode($"https://haohuo.jinritemai.com/views/product/item2?id={goodsId}"), sign); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = searchUrl, + Method = "get", + IsToLower = false, + Cookie = cookie, + Referer = "", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "text/html", + Allowautoredirect = false, + ProxyIp = "", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + //string cookie = result.Cookie; + + //{"code":0,"st":0,"msg":"","data":{"promotions":[{"promotion_id":"3473786827197053067","product_id":"3473587162723782872","title":"【象牙塔】爆款 厚实桌面手机支架 随意旋转上下调节","cover":{"uri":"temai/e7ea85383a76fe7cec7390407fdfa984www1099-1015","url_list":["http://p3.pstatp.com/aweme/720x720/temai/e7ea85383a76fe7cec7390407fdfa984www1099-1015.jpeg","http://pb9.pstatp.com/aweme/720x720/temai/e7ea85383a76fe7cec7390407fdfa984www1099-1015.jpeg","http://pb3.pstatp.com/aweme/720x720/temai/e7ea85383a76fe7cec7390407fdfa984www1099-1015.jpeg"]},"detail_url":"https://haohuo.jinritemai.com/views/product/item2?id=3473587162723782872","promotion_source":4,"brand_icon":{"url_list":["http://p3.pstatp.com/origin/db00001bcc4cfde8d96a"]},"price":990,"market_price":1900,"cos_fee":495,"cos_ratio":5000,"month_sales":7020,"shop_id":14065420,"shop_name":"象牙塔","exp_score":"4.5","in_promotion":true,"in_shop":false,"sales":0}],"has_more":false,"search_id":"6979517724091285760"},"total":1,"log_id":"20210630173326010198066204044B8F51"} + var goodsInfo = JsonConvert.DeserializeObject(html); + //if (goodsInfo != null) + return goodsInfo; + } + catch (Exception ex) + { + Console.WriteLine($"查询商品信息异常,{ex.Message} - {ex.StackTrace}"); + } + return null; + } + + /// + /// 添加商品至橱柜 + /// + /// + public bool AddGoodsWindowUrl(string product_id) + { + try + { + var sign = "";//TODO 这个可以为空 + var addGoods_WindowUrl = string.Format(AddGoods_WindowUrl, sign); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = addGoods_WindowUrl, + Method = "POST", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookie, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "https://buyin.jinritemai.com/dashboard/merch-picking-hall", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = $"product_id={product_id}&item_type=4&pick_first_source=%E7%99%BE%E5%BA%94&pick_second_source=%E9%80%89%E5%93%81%E5%B9%BF%E5%9C%BA&pick_third_source=search&pick_source_id=", + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + //{"code":0,"st":0,"msg":"success","error_type":0,"data":{},"log_id":"202107011223480101980650882E822E5B"} + string html = result.Html; + //string cookie = result.Cookie; + + var jObj = JObject.Parse(html); + if (html.Contains("code") && (int)jObj["code"] == 0) + { + if (jObj["msg"].ToString().ToLower() == "success") + return true; + } + + } + catch (Exception ex) + { + Console.WriteLine($"添加商品到橱柜异常:{ex.Message} - {ex.StackTrace}"); + } + return false; + } + + /// + /// 通过商品id查询橱柜中的商品,获取推广链接 + /// + /// + /// + public string GetShopWindow_PromotionUrlToGoodsId(string goodsid) + { + try + { + var sign = "";//TODO 这个可以为空 + var searchUrl = string.Format(ShopWindowUrl, goodsid, sign); + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = searchUrl, + Method = "get", + IsToLower = false, + Cookie = cookie, + Referer = "", + Postdata = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + Accept = "text/html, application/xhtml+xml, */*",// 可选项有默认值 + ContentType = "application/json",//返回类型 可选项有默认值 + Allowautoredirect = false, + ProxyIp = "", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + //string cookie = result.Cookie; + + //{"code":0,"data":[{"promotion_id":"3461130275701011777","product_id":"3454352531717751823","promotion_source":4,"coupon_amount":"","price":9990,"cos_fee":3996,"cos_ratio":40,"title":" 【辉腾】直播落地支架 直播支架 直播落地三脚架 户外落地支架","detail_url":"https://haohuo.jinritemai.com/views/product/item2?id=3454352531717751823\u0026origin_type=2002170010\u0026origin_id=1460607342872671_3461130275701011777\u0026alkey=1128_1460607342872671_0_3461130275701011777_011\u0026sec_author_id=MS4wLjABAAAAEnpGkVpQS-WLtu18Me9lZ-9A284xvNbstU-HGyQK3vn2Pi-WtDWPRAXLCnSRvDsF\u0026buyin_track=COgIEN-Q0K6ijcwCGgQIABAAIgAoj4iI8LXqlPgvMAE\u0026c_biz_combo=2","cover":"temai/c9a03a89407ec53f6dc06fb949a9a7bcwww800-800","images":["temai/c9a03a89407ec53f6dc06fb949a9a7bcwww800-800","temai/bd81e0f3a80b8ef97228454fcd243157www800-800","temai/7575df4d88e28769e16ebd13ec48c14awww800-800","temai/0bdd668c8dad2dd2605dc62b51b9f509www800-800","temai/b25524e60b62f6b768995a2c4910cd91www800-800"],"elastic_title":"","elastic_images":["temai/c9a03a89407ec53f6dc06fb949a9a7bcwww800-800","temai/bd81e0f3a80b8ef97228454fcd243157www800-800","temai/7575df4d88e28769e16ebd13ec48c14awww800-800","temai/0bdd668c8dad2dd2605dc62b51b9f509www800-800","temai/b25524e60b62f6b768995a2c4910cd91www800-800"],"ies_category":12,"sales":0,"pic_audit_status":null,"brand_icon":"","original_promotion_source":0,"cos_type":0,"cos_type_name":"","live_elastic_title":"","full_discount":[],"shop_label":null,"shop_id":9868340,"tax_price":0,"is_haitao":false,"hide_status":2,"pool_type":"","industry_cid":7,"industry_cname":"智能家居"}],"extra":{"log_id":"2021070109250001019806620216778C63","now":1625102701000},"msg":"success","st":0,"total":1} + + var jObj = JObject.Parse(html); + if (html.Contains("code") && (int)jObj["code"] == 0) + { + var jArr = (JArray)jObj["data"]; + if (jArr.Count != 0) + { + var jTok = jArr[0]; + return jTok["detail_url"].ToString(); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"获取推广链接异常:{ex.Message} - {ex.StackTrace}"); + } + return string.Empty; + } + + + /// + /// 抖音订单状态 + /// + public enum DouyinOrderStatus : int + { + 全部订单 = 1, + 订单结算 = 2, + PAY_SUCC = 3,//订单付款 + REFUND = 5,//退款/失效 + 订单维权中 = 6, + } + + /// + /// 根据字符生成Cookie和精简串,将排除path,expires,domain以及重复项 + /// + /// Cookie字符串 + /// 精简串 + internal static string GetSmallCookie(string strcookie) + { + if (string.IsNullOrWhiteSpace(strcookie)) + { + return string.Empty; + } + + Dictionary keyValues = new Dictionary(); + string[] array = strcookie.ToString().Split(new string[2] + { + ",", + ";" + }, StringSplitOptions.RemoveEmptyEntries); + string[] array2 = array; + foreach (string text in array2) + { + var index = text.IndexOf("="); + if (index != -1) + { + var val0 = text.Substring(0, index); + var val1 = text.Substring(index + 1, text.Length - index - 1); + + var val2 = val0.ToLower().Trim(); + if (!val2.Contains("path=") && !val2.Contains("expires=") && !val2.Contains("domain=")) + { + if (!keyValues.ContainsKey(val0)) + keyValues.Add(val0, val1); + else + keyValues[val0] = val1; + } + } + } + + List list = new List(); + foreach (KeyValuePair item in keyValues) + { + list.Add($"{item.Key}={ item.Value}"); + } + return string.Join(";", list) + ";"; + } + + } +} diff --git a/类库/Api.Framework/Cps/JingdongApi.cs b/类库/Api.Framework/Cps/JingdongApi.cs new file mode 100644 index 0000000..3bea5c0 --- /dev/null +++ b/类库/Api.Framework/Cps/JingdongApi.cs @@ -0,0 +1,406 @@ +using Api.Framework.Model; +using Api.Framework.Tools; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Cps +{ + /// + /// 京东操作Api + /// + public class JingdongApi : BaseCpsApi + { + #region 固定函数 + /// + /// 构造方法 + /// + /// fl_cps_member实例 + public JingdongApi(fl_cps_member member) : base(member) { } + + /// + /// 刷新授权 + /// + public void RefreshStatus() + { + try + { + var result = SendServer("refresh_token", new { username = Member.username }); + if (!result.ok) throw new Exception(result.message.ToString()); + Member.online = true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"ERROR:{this.GetType()}-{System.Reflection.MethodBase.GetCurrentMethod().Name}->{ex.Message}"); + } + } + + #region + private static int AppKeysIndex = -1; + private static string[] AppKeys = null; + + private static List WhiteApiList = new List() { + "jd.union.open.promotion.byunionid.get"/*转链*/, + "jd.union.open.position.query"/*推广位*/, + "jd.union.open.position.create"/*创建推广位*/, + "jd.union.open.goods.jingfen.query"/*京粉精选商品*/, + "jd.union.open.goods.promotiongoodsinfo.query"/*根据skuid查询商品信息*/ }; + + + private static string[] KeyInfo = null; + private static DateTime UpdateKeyTime = DateTime.MinValue; + private string[] GetKeySecret() + { + if (UpdateKeyTime.AddDays(1) < DateTime.Now) + KeyInfo = null; + if (KeyInfo == null) + { + for (int i = 0; i < 3; i++) + { + try + { + var data = this.SendServer("find_wangzhi", "webTool.asmx", new { name = "京东APPKEY" }).message.ToString(); + if (!string.IsNullOrWhiteSpace(data)) + { + /* + appkey="4363c9848d8a43c8b7b9e957d3adcbcf"; +"474ae90f6930495988c28701b6be1d9a"; + */ + //data = "4363c9848d8a43c8b7b9e957d3adcbcf_474ae90f6930495988c28701b6be1d9a"; + KeyInfo = data.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + break; + } + continue; + } + catch (Exception) + { + KeyInfo = null; + Thread.Sleep(500); + } + } + UpdateKeyTime = DateTime.Now; + } + return KeyInfo; + } + + /// + /// 发送京东报文 + /// + /// api接口 + /// 参数 + /// + public Dictionary SendJingdong(string api, object data) + { + try + { + //执行次数 + int num = 1; + Next: + string[] appKey = null; + if (AppKeysIndex == -1) + { + //appkey = "4363c9848d8a43c8b7b9e957d3adcbcf"; + //secretkey = "474ae90f6930495988c28701b6be1d9a"; + + if (WhiteApiList.Contains(api)) + //appKey = new string[] { "dd09c846450c044cf4977357e25ef2cb", "8a610e949a0d4657b310def702728059" };//自己的目前30W + appKey = GetKeySecret();//自己的目前30W + if (appKey == null) + appKey = new string[] { "4363c9848d8a43c8b7b9e957d3adcbcf", "474ae90f6930495988c28701b6be1d9a" };//别人的,无限制 + } + //else + //{ + // //第一次 + // if (AppKeys == null || AppKeysIndex >= AppKeys.Length) + // { + // try + // { + // if (AppKeys != null && AppKeysIndex >= AppKeys.Length) AppKeysIndex = -1; + // else if (AppKeys == null && AppKeysIndex != -1) AppKeysIndex = -1; + + // var result = base.SendServer("get_appkey", ""); + // var msg = result.message.ToString(); + // msg = ZipHelper.GZipDecompressString(msg); + // AppKeys = msg.Split(','); + // } + // catch (Exception ex) + // { + // throw new Exception("获取京东授权KEY失败!" + ex.Message); + // } + // } + // appKey = AppKeys[AppKeysIndex].Split('_'); + //} + + Dictionary param = new Dictionary(); + + param["access_token"] = ""; + param["app_key"] = appKey[0]; + param["format"] = "json"; + param["method"] = api; + param["param_json"] = CsharpHttpHelper.HttpHelper.ObjectToJson(data);//param_json为空的时候需要写成 "{}" + param["sign_method"] = "md5"; + param["timestamp"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + param["v"] = "1.0"; + + //计算签名 + var sign = SignTopRequest(param, appKey[1]); + param["sign"] = sign; + + if (param.ContainsKey("param_json")) + { + param["param_json"] = HttpHelper.URLEncode(param["param_json"]); + } + + var _param = HttpHelper.URLDecode(HttpExtend.BuildQuery(param)); + HttpHelper http = new HttpHelper(); + HttpItem _item = new HttpItem() + { + URL = "https://router.jd.com/api?" + _param, + Method = "get", + Timeout = 10000, + ReadWriteTimeout = 10000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "" + }; + + Dictionary dic = null; + string html = string.Empty; + for (int i = 0; i < 4; i++) + { + html = http.GetHtml(_item).Html; + if (html.Contains("操作超时") || html.Contains("服务端异常")) + { + Thread.Sleep(200); + continue; + } + else + { + dic = HttpExtend.JsonToDictionary(html); + if (dic == null) continue; + } + break; + } + if (html.Contains("操作超时") || html.Contains("服务端异常")) return new Dictionary(); + if (dic == null) + { + EventClient.OnEvent(this, $"【京东】 => 请求失败转换异常:{html}"); + return new Dictionary(); + } + var response = api.Replace(".", "_") + "_response"; + if (dic.ContainsKey(response)) + { + var result = dic[response] as Dictionary; + if (result.ContainsKey("result")) + { + dic = HttpExtend.JsonToDictionary(result["result"].ToString()); + } + if (dic.ContainsKey("code")) + { + var code = dic["code"].ToString(); + if (code != "200" && code != "1002016") + { + if (dic["message"].ToString().ToLower() == "授权key无权限或错误") + { + if (num < 3) + { + num++; + goto Next; + } + //if (code == "1002006") throw new Exception("京东key失效"); + throw new Exception(@"授权key无权限或错误"); + } + else + { + EventClient.OnEvent(this, $"京东接口异常:{this.Member.username}({this.Member.usernick})->{api}->{dic["message"]}"); + throw new Exception(HttpHelper.ObjectToJson(dic["message"])); + } + } + } + return dic; + } + else if (dic.ContainsKey("errorResponse") || dic.ContainsKey("error_response"))//{"errorResponse":{"code":"3067","msg":"API GLOBAL LIMITER ACTIVE, REQUEST TIMES LIMITED"}} + { + if (dic.ContainsKey("errorResponse")) + { + var errorResponse = dic["errorResponse"] as Dictionary; + if (errorResponse.ContainsKey("code") && (errorResponse["code"].ToString() == "3066" || errorResponse["code"].ToString() == "67")) + { + AppKeysIndex++; + if (AppKeysIndex < AppKeys.Length) + { + goto Next; + } + else + throw new Exception($".京东调用量饱和,暂时无法为您发起请求!"); + } + else + { + throw new Exception($".京东接口异常:({this.Member.usernick})->{api}->{HttpHelper.ObjectToJson(dic["errorResponse"])}"); + } + } + else if (dic.ContainsKey("error_response")) + { + var errorResponse = dic["error_response"] as Dictionary; + //if (errorResponse.ContainsKey("code") && errorResponse["code"] == "2") + //{ + if (errorResponse.ContainsKey("zh_desc") && errorResponse["zh_desc"].ToString().Contains("1天内访问接口")) + { + AppKeysIndex++; + if (AppKeysIndex < AppKeys.Length) + { + goto Next; + } + else + throw new Exception($".京东调用量饱和,暂时无法为您发起请求!"); + } + //} + else + { + string code = string.Empty; + if (errorResponse.ContainsKey("code")) + code = errorResponse["code"].ToString(); + throw new Exception($".京东接口异常:({this.Member.usernick})->{api}-> {code}.京东调用量饱和,暂时无法为您发起请求!"); + } + } + } + return new Dictionary(); + } + catch (Exception ex) + { + throw ex; + } + } + #endregion + + #region 2021年1月25日 新接口 + /// + /// 京东下载订单 + /// + /// 开始时间 + /// 结束时间 + /// 第几页 + /// 每页数量,上限500 + /// 订单类型 + /// + internal Dictionary DownOrder(DateTime datetime, string key, int page_index, int page_size, int type = 3) + { + int i = 0; + Next: + try + { + var endTime = datetime.ToString("yyyy-MM-dd HH:mm:ss"); //每小时同步订单 + var startTime = datetime.AddHours(-1).ToString("yyyy-MM-dd HH:mm:ss"); //每小时同步订单 + var _rst = this.SendJingdong("jd.union.open.order.row.query", new + { + orderReq = new + { + key = key, + pageIndex = page_index, + pageSize = page_size, + type = type, //订单时间查询类型(1:下单时间,2:完成时间(购买用户确认收货时间),3:更新时间 + startTime = startTime, //查询时间,建议使用分钟级查询,格式: yyyyMMddHH, yyyyMMddHHmm或yyyyMMddHHmmss,如201811031212的查询范围从12:12:00-12:12:59 + endTime = endTime, + } + }); + return _rst; + } + catch (Exception ex) + { + if (i <= 3 && ex.Message == "未将对象引用设置到对象的实例。") //调用接口是偶尔会出现为将对象实例化的错误. + { + i++; + Thread.Sleep(100); + goto Next; + } + else + throw ex; + + EventClient.OnEvent(this, $"更新京东订单异常: {ex.Message} - {ex.StackTrace}"); + return null; + } + } + #endregion + + #endregion + + #region Sign计算 + private string SignTopRequest(Dictionary parameters, string appSecret) + { + StringBuilder sb = new StringBuilder(appSecret); + //按照规则拼成字符串 + foreach (KeyValuePair entry in parameters) + { + string name = entry.Key; + string value = entry.Value; + //检测参数是否为空 + if (areNotEmpty(new string[] { name, value })) + { + sb.Append(name).Append(value); + } + } + sb.Append(appSecret); + + //MD5 + return md5(sb.ToString()); + } + + private string md5(string source) + { + MD5 md5 = MD5.Create(); + var result = md5.ComputeHash(Encoding.UTF8.GetBytes(source)); + return byte2hex(result); + } + + private string byte2hex(byte[] bytes) + { + //把二进制转化为大写的十六进制 + StringBuilder result = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + result.Append(bytes[i].ToString("X2")); + } + return result.ToString(); + } + + private bool areNotEmpty(string[] values) + { + bool result = true; + if ((values == null) || (values.Length == 0)) + result = false; + else + { + foreach (var value in values) + { + result &= !isEmpty(value); + } + } + return result; + } + + private bool isEmpty(string value) + { + int strLen; + if ((value == null) || ((strLen = value.Length) == 0)) + return true; + for (int i = 0; i < strLen; i++) + { + var ss = value[i]; + if (!string.IsNullOrWhiteSpace(value[i].ToString())) + { + return false; + } + } + return true; + } + #endregion + } +} diff --git a/类库/Api.Framework/Cps/KuaiShouApi.cs b/类库/Api.Framework/Cps/KuaiShouApi.cs new file mode 100644 index 0000000..d9d54fc --- /dev/null +++ b/类库/Api.Framework/Cps/KuaiShouApi.cs @@ -0,0 +1,347 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.EntityTmp.KuaiShou; +using Api.Framework.Model; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Api.Framework.Cps +{ + public class KuaiShouApi : BaseCpsApi + { + + internal KuaiShouApi(fl_cps_member member) : base(member) { } + + /// + /// 请求快手Api + /// + /// api接口 + /// 请求参数 + /// + public T SendData(string api, object data) + { + var jObj = SendServer(api, data); + if (jObj != null) + return jObj.ToObject(); + return default(T); + } + + /// + /// 请求快手Api + /// + /// api接口 + /// 请求参数 + /// + public JToken SendData(string api, object data) + { + try + { + var jObj = SendServer(api, data); + return jObj; + } + catch (Exception ex) + { + throw ex; + } + return null; + } + + #region 请求 + private string AppKey = "ks679199118973905155"; + //private string Token = "ChFvYXV0aC5hY2Nlc3NUb2tlbhJAq13iHqm2rYA2FPaq_m0RU87-oshvTLzbFJXSnJMC0znK7kwq29tUnRKVow6LFrdSZ8mTRmrQvIWQxVL0FKTqCBoSbRuEMdwtT-6YPlmXD2hUvaWiIiBf7afrOrF3qxUPgNXpAg_nT6OrwDx27hZpMeG8P7OimigFMAE"; + private string SignSecret = "910631f39a61e70f0b2c85a97ad4477e"; + + private JToken SendServer(string api, object data) + { + for (int i = 0; i < 2; i++) + { + + var param = GetRequestData(api, data, out string postParam); + + var url = $"https://openapi.kwaixiaodian.com/{(api.Replace(".", "/"))}?{param}"; + + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url,//URL 必需项 + Method = "get",//URL 可选项 默认为Get + Timeout = 10000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 5000,//写入Post数据超时时间 + Accept = "text/html, application/xhtml+xml, */*",// 可选项有默认值 + ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + }; + var result = http.GetHtml(item); + //{"tbk_dg_vegas_tlj_create_response":{"result":{"model":{"rights_id":"XvLXNwkX8HBQ8VZ2WS4DlNtN7m9cS4TU","send_url":"https:\/\/uland.taobao.com\/taolijin\/edetail?eh=5L6pfx5vldOZuQF0XRz0iAXoB%2BDaBK5LQS0Flu%2FfbSp4QsdWMikAalrisGmre1Id0BFAqRODu1004PvI5lqUzYTPq7zN5TtBXU4J7X2wljh7PW2ShemY2x1IRRpXndAncj8tXpgtxXzbOKxKSviYxsuv0da8KKt7WubOUkoI2Oa3HR2hP0JFSmjppH3xlrrJg8pBHJnzzOjd2vZvO6fEydXbwx4naJ6dk%2FBu2lJxZtMc7BMk%2FDH7wY2fDQKPuN9qcxwaWpDoQwfi%2B9ZUBfurmaewy3GJqMoK4342DlvX1ZVNOJlvqrE2h6J7%2BkHL3AEW&union_lens=lensId%3A0b14fbf4_0b3d_16f65a622fd_31b4%3Btraffic_flag%3Dlm","vegas_code":"N4HHV6HV"},"success":true},"request_id":"no8k8bbwsct2"}} + var html = result.Html; + + LogHelper.GetSingleObj().Debug("", $"快手Api请求:{api} => {JsonConvert.SerializeObject(data)} => 结果:" + html); + //Console.WriteLine($"快手请求: {html}"); + //Console.WriteLine(); + + //{"result":28,"code":"803000","msg":"鉴权失败","error_msg":"invalid access_token","sub_code":"28","sub_msg":"invalid access_token","request_id":"653573599408509148"} + //{"result":1017,"code":"802000","msg":"流量限制","error_msg":"[1017] exceed quota limit","sub_code":"802006","sub_msg":"APP已达到当天调用额度限制,请申请额度,[appkey:ks679199118973905155;primaryUserId:2871240599]","request_id":"653817732085832693"} + var jObj = JObject.Parse(html); + if (jObj["code"].ToString() == "803000" || jObj["sub_code"].ToString() == "28") + { + + base.RefToken(); + LogHelper.GetSingleObj().Error("", $"快手Api请求异常:{api} => {JsonConvert.SerializeObject(data)} => 结果:" + html); + continue; + } + else if (jObj["code"].ToString() == "802000" || jObj["sub_code"].ToString() == "802006") + { + LogHelper.GetSingleObj().Error("", $"快手Api请求异常:{api} => {JsonConvert.SerializeObject(data)} => 结果:" + html); + continue; + } + + return jObj; + } + + return null; + + //if (result != null && result.StatusCode != System.Net.HttpStatusCode.OK) + // throw new Exception(html); + + //var jToken = JObject.Parse(html); + //return jToken; + } + + private string GetRequestData(string api, object data, out string postParam) + { + Dictionary param = new Dictionary(); + + param["appkey"] = AppKey; + param["version"] = "1"; + param["method"] = api; + //param["signMethod"] = "HMAC_SHA256"; + param["signMethod"] = "MD5"; + param["access_token"] = base.Token.access_token; + param["timestamp"] = GetTimeStamp().ToString(); + postParam = param["param"] = JsonConvert.SerializeObject(data); + + //计算签名 + string sign = SignTopRequest(param); + param["sign"] = sign; + + return BuildQuery(param); + } + + /// + /// 同步订单 + /// + /// + /// + /// + /// + internal void DownOrder(DateTime beginTime, DateTime endTime, Action action, string pcursor = "") + { + var begin = HttpExtend.GetTimeStamp(beginTime, true); + var end = HttpExtend.GetTimeStamp(endTime, true); + var jObj = SendData("open.distribution.cps.kwaimoney.order.list", new { cpsOrderStatus = 0, pageSize = 100, sortType = 1, queryType = 2, beginTime = begin, endTime = end, pcursor = pcursor }); + + var data = jObj["data"]; + if (data != null) + { + try + { + var result = data.ToObject(); + if (result != null) + { + action(result, this.Member.username, this.Member.usernick); + + if (result.pcursor != "nomore")//继续请求 + { + DownOrder(beginTime, endTime, action, result.pcursor); + } + } + } + catch (Exception ex) + { + //Console.WriteLine(ex); + throw ex; + } + } + } + + public static string BuildQuery(IDictionary parameters) + { + if (parameters == null || parameters.Count == 0) + return (string)null; + StringBuilder stringBuilder = new StringBuilder(); + bool flag = false; + foreach (KeyValuePair parameter in (IEnumerable>)parameters) + { + string key = parameter.Key; + string str = parameter.Value; + if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(str)) + { + if (flag) + stringBuilder.Append("&"); + stringBuilder.Append(key); + stringBuilder.Append("="); + stringBuilder.Append(HttpExtend.UrlEncode(str)); + flag = true; + } + } + return stringBuilder.ToString().Replace("%2c", "%2C").Replace("%3a", "%3A"); + } + + private string SignTopRequest(Dictionary parameters) + { + // 第一步:把字典按Key的字母顺序排序 + IDictionary sortedParams = new SortedDictionary(parameters, StringComparer.Ordinal); + + // 第二步:把所有参数名和参数值串在一起 + List list = new List(); + + parameters.Clear(); + + foreach (KeyValuePair kv in sortedParams) + { + if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value)) + { + list.Add($"{kv.Key}={kv.Value}"); + parameters[kv.Key] = kv.Value; + } + } + + //parameters = sortedParams as Dictionary; + + list.Add($"signSecret={SignSecret}"); + + var query = string.Join("&", list); + + //// 第三步:使用HMACSHA256加密 + //var h = new HMACSHA256(Encoding.UTF8.GetBytes(SignSecret)); + //var bytes = h.ComputeHash(Encoding.UTF8.GetBytes(query)); + + MD5 md5 = MD5.Create(); + var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query)); + + // 第五步:把二进制转化为大写的十六进制 + StringBuilder result = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + result.Append(bytes[i].ToString("x2")); + } + + return result.ToString(); + } + + private long GetTimeStamp(bool Seconds = false) + { + TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0); + if (Seconds) return Convert.ToInt64(ts.TotalSeconds); + else return Convert.ToInt64(ts.TotalMilliseconds); + } + #endregion + + /// + /// 创建推广位 + /// + /// 推广位名称 + public void CreateMedia(string name) + { + SendData("open.distribution.cps.kwaimoney.pid.create", new { promotionBitName = name }); + } + + /// + /// 获取推广位列表 + /// + /// + /// + /// + /// + public List GetMedias(int page, int pageSize, out int total) + { + List list = null; + total = 0; + + var jToken = SendData("open.distribution.cps.kwaimoney.pid.list", new { page = page, pageSize = pageSize }); + + if (jToken != null) + { + var cpsPidData = jToken["data"]?["cpsPidData"]?.ToArray(); + if (cpsPidData != null) + { + list = new List(); + foreach (var item in cpsPidData) + { + list.Add(item.ToObject()); + } + } + ////{{"result":1,"msg":"success","error_msg":"SUCCESS","code":"1","data":{"cpsPidData":[{"cpsPid":"ks_2871240599_102_DfSm3SDi4fQ","createTime":1653447708399,"promotionBitName":"测试一下","status":1},{"cpsPid":"ks_2871240599_102_ENyeXrpQo0Y","createTime":1653447514432,"promotionBitName":"111","status":1}],"total":2},"requestId":"653449659999263660","sub_msg":"SUCCESS","sub_code":"1"}} + total = jToken["data"]["total"].Value(); + } + + return list; + } + + /// + /// 转链 + /// + /// 携带id(达人快手id或商品id) + /// 快赚客推广位cps pid + /// 备注(透传字段,拉取订单接口返回) + /// 自定义文案 + public KS_TurnUrlInfo TurnUrl(string linkCarrierId, string pid, string comments, string customContent = "") + { + var jToken = SendData("open.distribution.cps.kwaimoney.link.create", + new + { + linkType = 101, + linkCarrierId = linkCarrierId, + comments = comments, + cpsPid = pid, + customContent = customContent + }); + + if (jToken["data"] != null) + { + var result = jToken["data"]?.ToObject(); + return result; + } + + return null; + } + + /// + /// 添加商品到货架 + /// + /// + /// + public bool AddShopWindow(long itemId) + { + var jToken = SendData("open.distribution.selection.pick", new { itemIds = new List() { itemId } }); + + if (jToken["data"]?["result"].Value() == 1) + return true; + return false; + } + + /// + /// 获取商品信息 + /// + /// + /// + public KS_ItemInfo GetItemInfo(string itemId) + { + var jToken = SendData("open.distribution.cps.kwaimoney.selection.item.detail", new { itemId = new List() { long.Parse(itemId) } }); + + var jArr = jToken?["data"]?.ToArray(); + if (jArr != null && jArr.Length != 0) + { + var result = jArr[0].ToObject(); + return result; + } + return null; + } + + } +} diff --git a/类库/Api.Framework/Cps/PinduoduoApi.cs b/类库/Api.Framework/Cps/PinduoduoApi.cs new file mode 100644 index 0000000..ce5ac59 --- /dev/null +++ b/类库/Api.Framework/Cps/PinduoduoApi.cs @@ -0,0 +1,212 @@ +using Api.Framework.Model; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; +using System.Threading; + +namespace Api.Framework.Cps +{ + /// + /// 拼多多操作Api + /// + public class PinduoduoApi : BaseCpsApi + { + #region 静态 + /// + /// 拼多多接口请求地址 + /// + private const string app_host = "http://gw-api.pinduoduo.com/api/router"; + + /// + /// 计算sign + /// + /// 参数 + /// appkey + /// + private string SignTopRequest(Dictionary parameters, string appkey) + { + // 第一步:把字典按Key的字母顺序排序 + IDictionary sortedParams = new SortedDictionary(parameters, StringComparer.Ordinal); + + // 第二步:把所有参数名和参数值串在一起 + StringBuilder query = new StringBuilder(); + query.Append(appkey); + foreach (KeyValuePair kv in sortedParams) + { + if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value)) + { + query.Append(kv.Key).Append(kv.Value); + } + } + + // 第四步 + byte[] bytes; + query.Append(appkey); + MD5 md5 = MD5.Create(); + bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString())); + // 第五步:把二进制转化为大写的十六进制 + StringBuilder result = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + result.Append(bytes[i].ToString("X2")); + } + return result.ToString(); + } + #endregion + + #region 实际操作 + /// + /// 构造方法 + /// + /// + internal PinduoduoApi(fl_cps_member member) : base(member) { } + + /// + /// 刷新授权 + /// + internal void RefreshStatus() + { + for (int i = 0; i < 3; i++) + { + try + { + //if (Member.cpstype == Enums.CpsType.多多进宝) + // Console.WriteLine(); + //UpdateCookies(); + var result = SendServer("refresh_token", new { username = Member.username }); + if (!result.ok) throw new Exception(result.message.ToString()); + Member.online = true; + RefToken(); + break; + } + catch (Exception ex) + { + if (i < 2) + { + Thread.Sleep(10000); + continue; + } + else + EventClient.OnEvent(this, $"ERROR:{this.GetType()}@{System.Reflection.MethodBase.GetCurrentMethod().Name}->{ex.Message}"); + } + } + } + + /// + /// 发送拼多多报文 + /// + /// 请求的api + /// 参数 + /// + public Dictionary SendPinduoduo(string api, object data) + { + int number = 0; + string html = string.Empty; + Next: + try + { + number++; + + //throw new Exception("{\"error_msg\":\"公共参数错误: access_token\",\"sub_msg\":\"公共参数错误: access_token\",\"sub_code\":\"10019\",\"error_code\":10019,\"request_id\":\"16249438515389810\"}"); + + Dictionary param = new Dictionary(); + var type = data.GetType().GetProperties(); + foreach (var item in type) + { + var _value = item.GetValue(data).ToString(); + param[item.Name] = _value; + } + //if (api != "pdd.ddk.oauth.order.list.increment.get" && api != "pdd.ddk.oauth.goods.search") + if (api.Contains("oauth")) + param["access_token"] = Token.access_token; + param["type"] = api; + param["client_id"] = Token.appid; + //param["timestamp"] = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString();//HttpExtend.GetTimeStamp(DateTime.Now).ToString(); + param["timestamp"] = HttpExtend.GetTimeStamp(); + param["data_type"] = "JSON"; + var sign = SignTopRequest(param, Token.appkey); + param["sign"] = sign; + + HttpHelper http = new HttpHelper(); + HttpItem _item = new HttpItem() + { + URL = app_host, + Method = "Post",//URL 可选项 默认为Get + Timeout = 10000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 10000,//写入Post数据超时时间 可选项默认为30000 + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = "",//字符串Cookie 可选项 + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统 可选项有默认值 + Accept = "text/html, application/xhtml+xml, */*",// 可选项有默认值 + ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + Referer = "",//来源URL 可选项 + Postdata = HttpExtend.BuildQuery(param),//Post数据 可选项GET时不需要写 + }; + html = http.GetHtml(_item).Html; + + //if (html.Contains("access_token已过期")) Member.online = false; + //else if (api == "pdd.ddk.oauth.order.list.increment.get") Member.online = true; + var dic = HttpExtend.JsonToDictionary(html); + if (dic.ContainsKey("error_response")) + { + //EventClient.OnEvent(this, $"拼多多接口异常:{this.Member.username}({this.Member.usernick})->{api}->{html}"); + throw new Exception(HttpHelper.ObjectToJson(dic["error_response"])); + } + return dic; + } + catch (Exception ex) + { + if (ex.Message.Contains("access_token") && ((ex.Message.Contains("10019") || ex.Message.Contains("20033") || ex.Message.Contains("20032")))) + { + Thread.Sleep(1000); + if (this.Member != null && RefToken() && this.Member.is_valid && number < 3) goto Next; + else + { + //Member.online = false; + //ApiClient.GetSession().SaveOrUpdate(Member); + Member.is_valid = false; + EventClient.OnEvent(this, $@"拼多多异常:{this.Member.username}({this.Member.usernick}),{ex.Message} - {ex.StackTrace} +,注:请重新登录拼多多,{api}"); + throw new Exception($"{this.Member.username}({this.Member.usernick}),{ex.Message},注:请重新登录拼多多"); + } + } + else if (html.Contains("超时")) + { + goto Next; + } + throw ex; + } + } + + /// + /// 拼多多下载订单 + /// + /// 开始时间 + /// 结束时间 + /// 每页数量默认50安全 + /// 第几页 + /// + internal Dictionary DownOrder(DateTime start_time, DateTime end_time, int page_index, int page_size) + { + if (!Member.is_valid) + throw new Exception("需要重新登录"); + + var _rst = this.SendPinduoduo("pdd.ddk.oauth.order.list.increment.get", new + { + start_update_time = HttpExtend.GetTimeStamp(start_time), + end_update_time = HttpExtend.GetTimeStamp(end_time), + page_size = page_size, + page = page_index + }); + if (_rst.ContainsKey("order_list_get_response")) + { + return _rst["order_list_get_response"] as Dictionary; + } + return null; + } + #endregion + + } +} diff --git a/类库/Api.Framework/Cps/SuNingApi.cs b/类库/Api.Framework/Cps/SuNingApi.cs new file mode 100644 index 0000000..a554f00 --- /dev/null +++ b/类库/Api.Framework/Cps/SuNingApi.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework.EntityTmp.SuNing; +using Api.Framework.EntityTmp.SuNing1; +using Api.Framework.EntityTmp.SuNing2; +using Api.Framework.EntityTmp.SuNing3; +using Api.Framework.EntityTmp.SuNing4; +using Api.Framework.Model; +using Api.Framework.Utils; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Api.Framework.Cps +{ + /// + /// 苏宁操作Api + /// + public class SuNingApi : BaseCpsApi + { + private string cookice = string.Empty; + + internal SuNingApi(fl_cps_member member) : base(member) + { + cookice = member.cookies; + } + + private const string ChannelID = "15824"; + + #region 获取Appkey + private static string[] KeyInfo = null; + private static DateTime UpdateKeyTime = DateTime.MinValue; + private string[] GetKeySecret() + { + if (UpdateKeyTime.AddDays(1) < DateTime.Now) + KeyInfo = null; + if (KeyInfo == null) + { + for (int i = 0; i < 3; i++) + { + try + { + var data = this.SendServer("find_wangzhi", "webTool.asmx", new { name = "苏宁APPKEY" }).message.ToString(); + if (!string.IsNullOrWhiteSpace(data)) + { + //data = a683d87c23dc4e6d01020cd8fa356456_a76798b7230b886627f6e6090d3b4e48 + //data = "75b46e8fb0a3a10a534282a684c92a09_532d037c25612475fd68e09eddb873fa"; + KeyInfo = data.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries); + break; + } + continue; + } + catch (Exception) + { + KeyInfo = null; + Thread.Sleep(500); + } + } + UpdateKeyTime = DateTime.Now; + } + return KeyInfo; + } + #endregion + + + #region 获取所有推广位 + List TgwList = null; + + public List GetTuiguagnwei(bool flush = false) + { + try + { + if (flush || TgwList == null) + { + TgwList = RequestTuiguagnwei(1); + } + return TgwList; + } + catch (Exception ex) + { + throw ex; + } + return new List(); + } + + /// + /// 请求苏宁获取聊天推广位 + /// + /// + /// + /// + private List RequestTuiguagnwei(int pageNumber, int countNumber = -1) + { + var list = new List(); + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "http://sums.suning.com/union/member/myPromotion/promotionPosition/list.htm", + Method = "POST", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookice, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "http://sums.suning.com/union/member/myPromotion/promotionPosition/list.htm", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "promotionSubjection=3&siteId_val=&siteId=&pageNumber=" + pageNumber, + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + if (!string.IsNullOrWhiteSpace(html)) + { + html = Regex.Replace(html, @"\s", "", RegexOptions.IgnoreCase); + + var regs = Regex.Matches(html, @"(?<推广位名称>.+?)(?\d+).+?.+?.+?.+?.+?查看报表删除

", RegexOptions.IgnoreCase | RegexOptions.Multiline); + foreach (Match reg in regs) + { + list.Add(new SN_TuiGuangWeiInfo() { adzonename = reg.Groups["推广位名称"].Value, adzonepid = reg.Groups["pid"].ToString() }); + } + + if (countNumber == -1) + { + var reg1 = Regex.Match(html, @"\(inputPageNumber-0\)<=\((?<页数>\d+)\)\)", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg1.Success) + { + countNumber = int.Parse(reg1.Groups["页数"].Value); + } + } + if (countNumber > pageNumber) + { + pageNumber++; + list.AddRange(RequestTuiguagnwei(pageNumber, countNumber)); + } + } + } + catch (Exception ex) + { + + } + return list; + } + #endregion + + /// + /// 创建工具商客户关系 + /// + /// 苏宁的手机号 + /// + public string CreateToolsRelation(string mediaCustNum) + { + try + { + var result = SendSuNing("suning.netalliance.toolseller.add", new { phone = "", channel = ChannelID, mediaCustNum = mediaCustNum }); + //{"sn_responseContent":{"sn_body":{"addToolseller":{"pid":"0c3cced96b03e0f0a06a","status":"1"}}}} + if (result == null) + throw new Exception("请求异常,请稍后重试!"); + var addToolseller = result.sn_responseContent.sn_body.addToolseller; + if (addToolseller.status != "1") + throw new Exception(addToolseller.errMsg); + else + return addToolseller.pid; + } + catch (Exception ex) + { + throw ex; + } + return string.Empty; + } + + /// + /// 查询商品xixni + /// + /// + public SN_GoodInfo QuerySearchCommodity(string mess) + { + var data = new + { + keyword = mess + }; + + return SendSuNing("suning.netalliance.searchcommodity.query", data); + } + + /// + /// 转链 二合一 + /// + /// 商品链接 + /// 优惠券链接 + /// + public SN_QueryCommoditydetail GetExtensionUrl(string pid, string url, string quanUrl) + { + var data = new + { + productUrl = url, + quanUrl = quanUrl, + //promotionId = "",//这个推广只联盟前台申请的推广位,如果没有可以不填 这个不符合我们的需求 + subUser = pid,//这个是自定义字段,传pid以及拼接的绑定信息等 + pid = Member.usernick//这个指定订单归工具商还是客户 - 工具商绑定关系pid + }; + return SendSuNing("suning.netalliance.extensionlink.get", data); + } + + /// + /// 查询商品信息 + /// + /// 商品编码1-供应商编码1_商品编码2-供应商编码2... 商品编码取有效位,供应商编码左补零至10位 最大查询10个商品 + /// + public SN_GoodInfo QueryGoodInfo(string commodityStr) + { + var data = new + { + commodityStr = commodityStr + }; + + return SendSuNing("suning.netalliance.commoditydetail.query", data); + } + + /// + /// 商品精选接口 + /// + /// 默认为1,,营销id。1-小编推荐;2-实时热销榜;3-当日热推榜;4-高佣爆款榜;5-团长招商榜;6-9块9专区 + /// + public SN_Recommend_Commodity QueryGuideGoodsInfo(CategoryType categoryType, int pageIndex = 1) + { + var data = new + { + eliteId = (int)categoryType, + pageIndex = pageIndex, + size = 40, + }; + + return SendSuNing("suning.netalliance.selectrecommendcommodity.query", data); + } + + + /// + /// 请求苏宁Api + /// + /// api接口 + /// 请求参数 + /// + public T SendSuNing(string api, object data) + { + var html = SendSuNingServer(api, data); + + return JsonConvert.DeserializeObject(html); + } + + /// + /// 请求苏宁Api + /// + /// api接口 + /// 请求参数 + /// + public JToken SendSuNing(string api, object data) + { + try + { + var html = SendSuNingServer(api, data); + var jObj = JObject.Parse(html); + if (jObj != null && jObj["sn_responseContent"] != null) + { + var sn_responseContent = jObj["sn_responseContent"]; + if (sn_responseContent != null && sn_responseContent["sn_body"] != null) + { + return sn_responseContent["sn_body"]; + } + } + } + catch (Exception ex) + { + throw ex; + } + return null; + } + + private string SendSuNingServer(string api, object data) + { + int number = 0; + var html = string.Empty; + Next: + try + { + var appname = string.Empty; + var apiSplic = api.Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries); + if (apiSplic.Length == 4) + { + var tmp = apiSplic[2].ToString(); + appname = apiSplic[3] + tmp.Substring(0, 1).ToUpper() + tmp.Substring(1); + } + var jsonData = @"{""sn_request"":{""sn_body"":{""" + appname + @""":" + JsonConvert.SerializeObject(data) + "}}}"; + + var keyInfo = GetKeySecret(); + //var jsonData = JsonConvert.SerializeObject(jsonStr); + var base64Str = HttpExtend.StringToBase64String(jsonData); + + var timeStr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + var versionNo = "v1.2"; + var sign = GetSign(api, timeStr, versionNo, base64Str); + + var http = new HttpHelper(); + var _item = new HttpItem() + { + //URL = $"https://openpre.cnsuning.com/api/http/sopRequest/{api}", + URL = $"https://open.suning.com/api/http/sopRequest/{api}", + Method = "post", + Timeout = 3000, + ReadWriteTimeout = 3000, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte, + PostdataByte = Encoding.UTF8.GetBytes(jsonData), + Referer = "" + }; + _item.Header["appMethod"] = api; + _item.Header["appRequestTime"] = timeStr; + _item.Header["appKey"] = keyInfo[0]; + _item.Header["versionNo"] = "v1.2"; + _item.Header["format"] = "json"; + _item.Header["signInfo"] = sign; + + html = http.GetHtml(_item).Html; + + if (html.Contains("操作超时") || html.Contains("服务端异常") || html.Contains("基础连接已经关闭") || html.Contains("请求被中止")) + throw new Exception(); + + return html; + } + catch (Exception ex) + { + Thread.Sleep(200); + if (number < 2 && html.Contains("操作超时") || html.Contains("服务端异常") || html.Contains("基础连接已经关闭") || html.Contains("请求被中止")) + goto Next; + else + { + EventClient.OnEvent(this, $"【苏宁易购】 => 请求异常1:{this.Member.usernick}({this.Member.username})"); + LogHelper.GetSingleObj().Error("", $@"【苏宁易购】 => 请求异常1:{this.Member.usernick}({this.Member.username}) +{api} +{html} +{ex.Message} - {ex.StackTrace}"); + } + throw ex; + } + return string.Empty; + } + + /// + /// 下载订单,不带状态(有多页,获取所有) + /// + /// 开始时间 + /// 第几页 + /// 页大小 + /// 阿里妈妈同步的订单类型 + /// 场景订单场景类型,1:常规订单,2:渠道订单,3:会员运营订单,默认为1 + /// + internal SN_OrderInfo DownOrder(DateTime start_time, DateTime end_time, int page_index, int page_size) + { + SN_OrderInfo _rst = null; + for (int i = 0; i < 2; i++) + { + try + { + var data = new + { + pageNo = page_index, + pageSize = page_size, + startTime = start_time.ToString("yyyy-MM-dd HH:mm:ss"), + endTime = end_time.ToString("yyyy-MM-dd HH:mm:ss"), + orderLineStatus = 0, + pid = Member.usernick//这个指定订单归工具商还是客户 - 工具商绑定关系pid + }; + + _rst = SendSuNing("suning.netalliance.order.query", data); + if (_rst.sn_responseContent != null && _rst.sn_responseContent.sn_body != null && _rst.sn_responseContent.sn_body.queryOrder != null && _rst.sn_responseContent.sn_body.queryOrder.Count != 0) + return _rst; + else if (_rst.sn_responseContent != null && _rst.sn_responseContent.sn_error != null && _rst.sn_responseContent.sn_error.error_code.Contains("no-result"))//没有查到数据 + break; + } + catch (Exception ex) + { + throw ex; + } + } + return null; + } + + /// + /// 计算sign + /// + /// + private string GetSign(string api, string timeStr, string versionNo, string base64Str) + { + //按照顺序依次拼接appSecret的值(appKey对应的密钥)、appMethod的值,appRequestTime的值,appkey的值,versionNo的值和第一步编码后的值 + var data = $"{KeyInfo[1]}{api}{timeStr}{KeyInfo[0]}{versionNo}{base64Str}"; + + //md5 小写 + return HttpHelper.ToMD5(data).ToLower(); + } + + } +} diff --git a/类库/Api.Framework/Cps/Tuiguangwei.cs b/类库/Api.Framework/Cps/Tuiguangwei.cs new file mode 100644 index 0000000..9f8a90d --- /dev/null +++ b/类库/Api.Framework/Cps/Tuiguangwei.cs @@ -0,0 +1,62 @@ +//============================================================= +// 创建人:千年老妖 +// 本页代码,均为原创。对未经许可擅自使用者,本人保留追究其法律责任的权利。 +//============================================================== +using Api.Framework.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Cps +{ + /// + /// 阿里妈妈推广位 + /// + public class Tuiguangwei + { + /// + /// 账号 + /// + public fl_cps_member Member { get; set; } + + /// + /// 推广位名称 + /// + public string Name { get; set; } + + /// + /// 推广位 + /// + public string Pid { get; set; } + } + + /// + /// 推广位强制返利 + /// + public class TuiguangweiActivity : Tuiguangwei + { + private string _ShortUrl; + /// + /// 短连接 + /// + public string ShortUrl + { + get + { + return _ShortUrl?.Trim(); + } + set + { + _ShortUrl = value; + } + } + + /// + /// 淘口令 + /// + public string Tkl { get; set; } + } + +} diff --git a/类库/Api.Framework/Cps/WeipinhuiApi.cs b/类库/Api.Framework/Cps/WeipinhuiApi.cs new file mode 100644 index 0000000..fb3b7c6 --- /dev/null +++ b/类库/Api.Framework/Cps/WeipinhuiApi.cs @@ -0,0 +1,328 @@ +using Api.Framework.Model; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework.EntityTmp.WeiPinHui; + +namespace Api.Framework.Cps +{ + /// + /// 唯品会操作Api + /// + public class WeipinhuiApi : BaseCpsApi + { + #region 固定函数 + /// + /// 构造方法 + /// + /// + internal WeipinhuiApi(fl_cps_member member) : base(member) { } + + /// + /// 刷新授权 + /// + public void RefreshStatus() + { + try + { + var result = SendServer("refresh_token", new { username = Member.username }); + if (!result.ok) throw new Exception(result.message.ToString()); + Member.online = true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"ERROR:{this.GetType()}-{System.Reflection.MethodBase.GetCurrentMethod().Name}->{ex.Message}"); + } + } + + //private string AppKey = "0c85e6c0"; + //private string AppSecret = "F921D8D3EFEAEA5B0387158512AEF909"; + + #region + + /// + /// 发送唯品会报文 + /// + /// api接口 + /// 参数 + /// + public T SendWeipinhui(string api, object data) + { + if (!Member.is_valid) return default(T); + + var isRefToken = false; + + var html = string.Empty; + for (int i = 0; i < 3; i++) + { + try + { + var query = GetRequestData(api, data); + var postData = JsonConvert.SerializeObject(data); + var http = new HttpHelper(); + var httpItem = new HttpItem() + { + URL = $"https://vop.vipapis.com/?{query}", + Method = "POST", + Timeout = 5000, + ReadWriteTimeout = 5000, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json;", + Postdata = postData, + }; + + var result = http.GetHtml(httpItem); + + if (result.StatusCode == HttpStatusCode.OK) + { + html = result.Html; + if (!string.IsNullOrWhiteSpace(html)) + { + var jObj = JObject.Parse(html); + var resultCode = jObj["returnCode"]?.ToString(); + if (resultCode == "0") + { + T t = JsonConvert.DeserializeObject(html); + return t; + } + else + { + //请求太快了 + if (resultCode == "1008") + { + Thread.Sleep(5000); + continue; + } + } + } + } + + throw new Exception(html); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("", $@"唯品会请求异常A.,{Member.usernick}({Member.username}),登录时间:{Member.logintime.ToString("yyyy-MM-dd HH:mm:ss")} +{api} +{html} +{ex.Message} - {ex.StackTrace}"); + + //token失效的错误数据 + //{"returnCode":"vipapis.oauth-invalidate-failure","returnMessage":"oauth-error-code[30111]description[access token invalid]"} + + if (ex.Message.Contains("invalid") || html.Contains("invalid") || html.Contains("token") || html.ToLower().Contains("does not exist")) + { + //没有刷新过token + if (isRefToken == false) + { + isRefToken = true; + if (RefToken()) + continue; + } + + EventClient.OnEvent(this, $@"【唯品会】 => 请求异常1:{this.Member.usernick}({this.Member.username}),注:请重新登录唯品会!!!"); + Member.is_valid = false; + return default(T); + } + Thread.Sleep(500); + } + } + return default(T); + } + #endregion + + /// + /// 唯品会下载订单 + /// + /// 开始时间 + /// 结束时间 + /// 第几页 + /// 每页数量 + /// + internal OrderResponseResult DownOrder(DateTime _startTime, DateTime _endTime, int page_index, int page_size) + { + if (!Member.is_valid) + { + //Api.Framework.Utils.LogHelper.GetSingleObj().Error("唯品会订单下载异常.过期?", $"需要重新登录,{this.Member.usernick}({this.Member.username})"); + throw new Exception("vipapis.oauth-invalidate-failure"); + } + + var startTime = Util.GetTimeSpan(_startTime, true); //每小时同步订单 + var endTime = Util.GetTimeSpan(_endTime, true); //每小时同步订单 + //time = "2019042216"; + //TODO 订单下载接口 + var result = this.SendWeipinhui("com.vip.adp.api.open.service.UnionOrderService-1.0.0#orderListWithOauth", new + { + queryModel = new + { + //status = key,//订单状态:0-不合格,1-待定,2-已完结,该参数不设置默认代表全部状态 + //orderTimeStart = page_index,//订单时间起始 时间戳 单位毫秒 + //orderTimeEnd = page_size,//订单时间结束 时间戳 单位毫秒 + page = page_index,//页码:从1开始 + pageSize = page_size,//页面大小:默认20 + requestId = Util.GetUUID(),//请求id:调用方自行定义,用于追踪请求,单次请求唯一,建议使用UUID + updateTimeStart = startTime,//更新时间-起始 时间戳 单位毫秒 + updateTimeEnd = endTime,//更新时间-结束 时间戳 单位毫秒 + //orderSnList = ,//订单号列表:当传入订单号列表时,订单时间和更新时间区间可不传入 + //vendorCode = ,//vendorCode,工具商方式下会传入 + //chanTag = ,//渠道标识,即推广位PID + } + }); + //if (_rst == null || _rst.result == null || _rst.returnCode == null || _rst.returnCode != "0") + // throw new Exception(JsonConvert.SerializeObject(_rst)); + return result; + } + + #endregion + + #region Sign计算 + + /// + /// 计算签名,返回请求阿里妈妈服务器的参数 + /// + /// api + /// 参数 + /// + private string GetRequestData(string api, object data) + { + //try + //{ + var reg = Regex.Match(api, "(?.+?)-(?.+?)#(?.+)"); + if (!reg.Success) throw new Exception($"无法识别“{api}”API请求!"); + + var param = new Dictionary(); + if (Token == null) + { + throw new Exception("invalid .."); + } + + param["accessToken"] = Token.access_token; + param["appKey"] = "9f7a9b3d";//Token.appid; + param["format"] = "JSON"; + param["language"] = "zh"; + param["method"] = reg.Groups["method"].Value; + param["service"] = reg.Groups["service"].Value; + param["version"] = reg.Groups["version"].Value; + param["timestamp"] = Util.GetTimeSpan(DateTime.Now, false).ToString(); + + //计算签名 + string sign = GetSign(param, "074B0E1FFB94334FDEC993913884EC7F"/*Token.appkey*/, data); + param["sign"] = sign; + + return HttpExtend.BuildQuery(param); + //} + //catch (Exception ex) + //{ + + //} + return string.Empty; + } + + + /// + /// 计算sign + /// + /// 计算的参数 + /// appkey + /// 请求的参数 + /// + private string GetSign(Dictionary parameters, string secret, object bizParam = null) + { + // 第一步:把字典按Key的字母顺序排序 + IDictionary sortedParams = new SortedDictionary(parameters, StringComparer.Ordinal); + + //// 第二步:把所有参数名和参数值串在一起 + StringBuilder query = new StringBuilder(); + foreach (KeyValuePair kv in sortedParams) + { + if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value)) + query.Append(kv.Key).Append(kv.Value); + } + + // 第三步:把请求主体拼接在参数后面 + var boby = string.Empty; + if (bizParam != null) + boby = JsonConvert.SerializeObject(bizParam); + if (!string.IsNullOrEmpty(boby)) + { + query.Append(boby); + } + + var sss = query.ToString(); + // 第四步: 使用HMAC加密 + HMACMD5 hmac = new HMACMD5(Encoding.UTF8.GetBytes(secret)); + var bytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(query.ToString())); + + // 第五步:把二进制转化为大写的十六进制 + StringBuilder result = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + result.Append(bytes[i].ToString("X2")); + } + + return result.ToString(); + } + #endregion + + /// + /// 获取唯品会推广位 + /// + /// WeipinhuiApi对象 + /// 第几页 + /// 每页的数量 + /// + public static QueryPid GetWphTgw(WeipinhuiApi api, int page = 1, int pageSize = 20) + { + var res = api.SendWeipinhui("com.vip.adp.api.open.service.UnionPidService-1.0.0#queryPidWithOauth", new { pidQueryRequest = new { requestId = Util.GetUUID(), page = page, pageSize = pageSize } }); + if (res != null && res.returnCode == "0") + { + return res.result; + } + return null; + } + + ///// + ///// 获取唯品会推广位 + ///// + ///// WeipinhuiApi对象 + ///// 第几页 + ///// 每页的数量 + ///// + //public static ArrayList GetWphTgw(WeipinhuiApi api, out int total, int page = 1, int pageSize = 20) + //{ + // total = 0; + // var res = api.SendWeipinhui("com.vip.adp.api.open.service.UnionPidService-1.0.0#queryPidWithOauth", new { pidQueryRequest = new { requestId = Util.GetUUID(), page = page, pageSize = pageSize } }); + // if (res.ContainsKey("returnCode") && res["returnCode"].ToString() == "0") + // { + // res = res["result"] as Dictionary; + // total = int.Parse(res["total"].ToString()); + // return res["pidInfoList"] as ArrayList; + // } + // return null; + //} + + /// + /// 创建推广位 + /// + /// WeipinhuiApi对象 + /// 要创建的推广位名称 + public static void CreateWphTgw(WeipinhuiApi api, List pidList = null) + { + if (pidList == null) + pidList = new List() { "WphDefault" }; + api.SendWeipinhui("com.vip.adp.api.open.service.UnionPidService-1.0.0#genPidWithOauth", new { pidGenRequest = new { requestId = Util.GetUUID(), pidNameList = pidList } }); + } + + } +} diff --git a/类库/Api.Framework/Cps/alimama_form_login.Designer.cs b/类库/Api.Framework/Cps/alimama_form_login.Designer.cs new file mode 100644 index 0000000..c984b7a --- /dev/null +++ b/类库/Api.Framework/Cps/alimama_form_login.Designer.cs @@ -0,0 +1,262 @@ +namespace Api.Framework.Cps +{ + partial class alimama_form_login + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(alimama_form_login)); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.webControl1 = new EO.WinForm.WebControl(); + this.webView1 = new EO.WebBrowser.WebView(); + this.tabControl1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.tabPage4.SuspendLayout(); + this.SuspendLayout(); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage4); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(388, 392); + this.tabControl1.TabIndex = 15; + this.tabControl1.SelectedIndexChanged += new System.EventHandler(this.tabControl1_SelectedIndexChanged); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.groupBox2); + this.tabPage2.Controls.Add(this.groupBox1); + this.tabPage2.Location = new System.Drawing.Point(4, 23); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(380, 365); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Cookies登录"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.simpleButton2); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Controls.Add(this.linkLabel2); + this.groupBox2.Controls.Add(this.textBox2); + this.groupBox2.Enabled = false; + this.groupBox2.Location = new System.Drawing.Point(3, 201); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(374, 161); + this.groupBox2.TabIndex = 1; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "第二步 填写高佣授权结果"; + // + // simpleButton2 + // + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(100, 100); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(194, 31); + this.simpleButton2.TabIndex = 3; + this.simpleButton2.Text = "同步Session网络数据"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.ForeColor = System.Drawing.Color.Red; + this.label2.Location = new System.Drawing.Point(33, 65); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(283, 19); + this.label2.TabIndex = 4; + this.label2.Text = "请填写登录成功后的,浏览器地址栏URL"; + this.label2.Click += new System.EventHandler(this.label2_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ForeColor = System.Drawing.Color.Silver; + this.label1.Location = new System.Drawing.Point(22, 139); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(323, 14); + this.label1.TabIndex = 3; + this.label1.Text = "注意:如果多套软件,不用重复授权,只需要任意一套同步即可!"; + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(215, 0); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(79, 14); + this.linkLabel2.TabIndex = 2; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "复制登录地址"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked); + // + // textBox2 + // + this.textBox2.Dock = System.Windows.Forms.DockStyle.Top; + this.textBox2.Location = new System.Drawing.Point(3, 18); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox2.Size = new System.Drawing.Size(368, 76); + this.textBox2.TabIndex = 0; + this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.linkLabel1); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupBox1.Location = new System.Drawing.Point(3, 3); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(374, 178); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "第一步 请输入阿里妈妈Cookies"; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(215, 0); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(79, 14); + this.linkLabel1.TabIndex = 1; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "复制登录地址"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // textBox1 + // + this.textBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.textBox1.Location = new System.Drawing.Point(3, 18); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox1.Size = new System.Drawing.Size(368, 110); + this.textBox1.TabIndex = 0; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(100, 135); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(194, 31); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "验证Cookies有效性"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton2_Click); + // + // tabPage4 + // + this.tabPage4.Controls.Add(this.webControl1); + this.tabPage4.Location = new System.Drawing.Point(4, 23); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Padding = new System.Windows.Forms.Padding(3); + this.tabPage4.Size = new System.Drawing.Size(380, 365); + this.tabPage4.TabIndex = 3; + this.tabPage4.Text = "浏览器登录"; + this.tabPage4.UseVisualStyleBackColor = true; + // + // webControl1 + // + this.webControl1.BackColor = System.Drawing.Color.White; + this.webControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webControl1.Location = new System.Drawing.Point(3, 3); + this.webControl1.Name = "webControl1"; + this.webControl1.Size = new System.Drawing.Size(374, 359); + this.webControl1.TabIndex = 0; + this.webControl1.Text = "webControl1"; + this.webControl1.WebView = this.webView1; + // + // webView1 + // + this.webView1.InputMsgFilter = null; + this.webView1.ObjectForScripting = null; + this.webView1.Title = null; + this.webView1.Url = ""; + // + // alimama_form_login + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(388, 392); + this.Controls.Add(this.tabControl1); + this.Name = "alimama_form_login"; + this.Text = "登录淘宝联盟"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.alimama_form_login_FormClosing); + this.Load += new System.EventHandler(this.alimama_form_login_Load); + this.SizeChanged += new System.EventHandler(this.alimama_form_login_SizeChanged); + this.tabControl1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.tabPage4.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TabPage tabPage4; + private EO.WinForm.WebControl webControl1; + private EO.WebBrowser.WebView webView1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/alimama_form_login.cs b/类库/Api.Framework/Cps/alimama_form_login.cs new file mode 100644 index 0000000..2351b20 --- /dev/null +++ b/类库/Api.Framework/Cps/alimama_form_login.cs @@ -0,0 +1,376 @@ +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using CsharpHttpHelper; +using EO.Base; +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using Api.Framework.Config; +using Newtonsoft.Json; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + /// + /// 阿里妈妈登录 + /// + internal partial class alimama_form_login : BaseForm + { + //private const string apiurl = "http://cps.api.52cmg.cn/api/alimama.asmx/login"; + + private static string apiurl => $"{ApiClient.Setting.SystemConfig.cps_server_api}api/alimama.asmx/login"; + + private const string alimama = "https://login.taobao.com/member/login.jhtml?style=mini&newMini2=true&css_style=alimama&from=alimama&redirectURL=http%3A%2F%2Fwww.alimama.com&full_redirect=true&disableQuickLogin=true&qq-pf-to=pcqq.c2c"; + internal alimama_form_login() + { + InitializeComponent(); + } + + private Wininet wininet = new Wininet(); + private Dictionary _Login; + internal fl_cps_member Member { get; private set; } + internal bool IsLogin { get; private set; } + + private static void WebBrowserVersionEmulation() + { + try + { + const string BROWSER_EMULATION_KEY = + @"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"; + // app.exe and app.vshost.exe + String appname = Process.GetCurrentProcess().ProcessName + ".exe"; + // Webpages are displayed in IE9 Standards mode, regardless of the !DOCTYPE directive. + const int browserEmulationMode = 9999; + + RegistryKey browserEmulationKey = + Registry.CurrentUser.OpenSubKey(BROWSER_EMULATION_KEY, RegistryKeyPermissionCheck.ReadWriteSubTree) ?? + Registry.CurrentUser.CreateSubKey(BROWSER_EMULATION_KEY); + + browserEmulationKey.SetValue(appname, browserEmulationMode, RegistryValueKind.DWord); + browserEmulationKey.Close(); + } + catch { } + } + + //private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) + //{ + // if (e.Url != null) + // { + // try + // { + // string url = this.webBrowser1.Url.ToString(); + // //Console.WriteLine(url); + // if (url.Contains("oauth.taobao.com")) + // { + // var reg = Regex.Match(url, "access_token=([^&]+).*?refresh_token=([^&]+)"); + // if (reg.Success) + // { + // Member = CpsClient.Members.FirstOrDefault(f => f.username == _Login["memberID"].ToString() && f.cpstype == CpsType.阿里妈妈); + // if (Member == null) + // { + // Member = new fl_cps_member() { username = _Login["memberID"].ToString(), cpstype = CpsType.阿里妈妈 }; + // CpsClient.Members.Add(Member); + // } + + // Member.online = true; + // Member.cookies = wininet.GetCookies("http://www.alimama.com"); + // Member.usernick = HttpExtend.Unicode2String(_Login["nickName"].ToString()); + // Member.logintime = DateTime.Now; + // Member.is_valid = true; + // var api = CpsClient.CreateAlimamaRequest(Member); + // api.SendServer("taobao.tbk.update.token", new { mid = Member.username, url = url }); + // api.RefToken(); + // this.Close(); + // } + // else + // { + // var input = this.webBrowser1.Document.GetElementById("sub"); + // if (input != null) + // { + // input.InvokeMember("click"); + // return; + // } + // } + // } + // if (url.Contains("openssp.tanx.com/ssp.html") || url.Contains("www.alimama.com")) + // { + // Wininet wininet = new Wininet(); + // string cookieString = wininet.GetCookies("http://www.alimama.com"); + // var result = AlimamaApi.GetUnionPubContextInfo(cookieString); + // if (result.ContainsKey("memberID")) + // { + // _Login = result; + // this.webBrowser1.Navigate(apiurl); + // this.WindowState = FormWindowState.Maximized; + // } + // } + // } + // catch (Exception ex) + // { + // BaseForm.ShowError(ex); + // } + // } + //} + + private void alimama_form_login_FormClosing(object sender, FormClosingEventArgs e) + { + DeleteCookies(); + if (Member != null) + { + //Tools.Util.ClearCookies(); + } + EventClient.OnEvent(this, MethodType.刷新联盟); + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + this._Login = AlimamaApi.GetUnionPubContextInfo(this.textBox1.Text); + if (_Login == null || _Login.Count == 0 || !_Login.ContainsKey("memberID")) + throw new Exception($@"填写的Cookies数据错误: +原因: +①错误复制cookies +②联盟账号未登录 +③等"); + Member = CpsClient.Members.FirstOrDefault(f => f.username == _Login["memberID"].ToString() && f.cpstype == CpsType.阿里妈妈); + if (Member == null) + { + Member = new fl_cps_member() { username = _Login["memberID"].ToString(), cpstype = CpsType.阿里妈妈 }; + CpsClient.Members.Add(Member); + } + + Member.online = true; + Member.cookies = this.textBox1.Text; + if (_Login.ContainsKey("nickName")) + Member.usernick = HttpExtend.Unicode2String(_Login["nickName"].ToString()); + + this.groupBox2.Enabled = true; + ShowSuccess("验证成功,您可以继续授权高佣Api"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) + { + try + { + if (this.tabControl1.SelectedIndex == 0) + { + this.WindowState = FormWindowState.Normal; + this.Size = new Size(404, 431); + return; + } + else if (this.tabControl1.SelectedIndex == 1) + { + this.webView1.LoadUrl("about:blank"); + } + } + catch (Exception exception) + { + BaseForm.ShowError(exception); + } + } + + private void alimama_form_login_SizeChanged(object sender, EventArgs e) + { + if (this.tabControl1.SelectedIndex == 1) + { + this.Size = new Size(404, 431); + } + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + Clipboard.SetDataObject(alimama); + BaseForm.ShowSuccess("复制成功,请到本机电脑粘贴登录!\r\n登录成功后,请填写Cookies验证!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + Clipboard.SetDataObject(apiurl); + BaseForm.ShowSuccess("复制成功,请到本机电脑粘贴登录!\r\n登录成功后,请填写页面字符串同步!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var reg = Regex.Match(this.textBox2.Text, "access_token=([^&]+).*?refresh_token=([^&]+)"); + Member.logintime = DateTime.Now; + Member.is_valid = true; + var api = CpsClient.CreateAlimamaRequest(Member); + api.SendServer("taobao.tbk.update.token", new { mid = Member.username, url = this.textBox2.Text }); + api.RefToken(); + this.Close(); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void textBox2_TextChanged(object sender, EventArgs e) + { + label2.Visible = false; + } + + private void label2_Click(object sender, EventArgs e) + { + this.label2.Visible = false; + } + + private void alimama_form_login_Load(object sender, EventArgs e) + { + try + { + EO.Base.Runtime.EnableEOWP = true; + EO.Base.Runtime.Exception += Runtime_Exception; + this.webView1.LoadCompleted += WebView1_LoadCompleted; + this.webView1.NewWindow += WebView1_NewWindow; + this.webView1.CertificateError += WebView1_CertificateError; + + tabControl1.SelectedIndex = 1; + } + catch (Exception ex) + { + + } + } + + + + private void Runtime_Exception(object sender, ExceptionEventArgs e) + { + e.ShowExceptionDialog = false; + } + + private void WebView1_CertificateError(object sender, EO.WebBrowser.CertificateErrorEventArgs e) + { + } + + private void WebView1_NewWindow(object sender, EO.WebBrowser.NewWindowEventArgs e) + { + try + { + this.webView1.LoadUrl(e.TargetUrl); + } + catch (Exception ex) + { + BaseForm.ShowError(ex.Message + " = 22"); + } + } + + private void DeleteCookies() + { + try + { + this.webView1.Engine.CookieManager.DeleteCookies(); + } + catch (Exception e) + { } + } + + private void WebView1_LoadCompleted(object sender, EO.WebBrowser.LoadCompletedEventArgs e) + { + try + { + var url = e.Url; + + Console.WriteLine(url + @" +"); + if (url == "about:blank") + { + DeleteCookies(); + this.webView1.LoadUrl(alimama); + return; + } + if (url.Contains("oauth.taobao.com")) + { + var reg = Regex.Match(url, "access_token=([^&]+).*?refresh_token=([^&]+)"); + if (reg.Success) + { + Member = CpsClient.Members.FirstOrDefault(f => f.username == _Login["memberID"].ToString() && f.cpstype == CpsType.阿里妈妈); + if (Member == null) + { + Member = new fl_cps_member() { username = _Login["memberID"].ToString(), cpstype = CpsType.阿里妈妈 }; + CpsClient.Members.Add(Member); + } + + Member.online = true; + Member.cookies = GetCookies("https://www.alimama.com/index.htm"); + Member.usernick = HttpExtend.Unicode2String(_Login["nickName"].ToString()); + Member.logintime = DateTime.Now; + Member.is_valid = true; + var api = CpsClient.CreateAlimamaRequest(Member); + api.SendServer("taobao.tbk.update.token", new { mid = Member.username, url = url }); + api.RefToken(); + this.Close(); + } + else + { + this.webView1.EvalScript("document.getElementById('sub').click()", false); + } + } + + if (url.Contains("openssp.tanx.com/ssp.html") || url.Contains("//www.alimama.com")) + { + string cookieString = GetCookies(url); + var result = AlimamaApi.GetUnionPubContextInfo(cookieString); + if (result.ContainsKey("memberID")) + { + _Login = result; + this.webView1.LoadUrl(apiurl); + + this.WindowState = FormWindowState.Maximized; + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex.Message); + } + } + + /// + /// 获取指定页面COOKIE + /// + /// + /// + public string GetCookies(string url) + { + var cks = this.webView1.Engine.CookieManager.GetCookies(url); + StringBuilder sb = new StringBuilder(); + foreach (var item in cks.AllKeys) + { + sb.Append(item + "=" + cks[item].Value + ";"); + } + return sb.ToString(); + } + + } +} diff --git a/类库/Api.Framework/Cps/alimama_form_login.resx b/类库/Api.Framework/Cps/alimama_form_login.resx new file mode 100644 index 0000000..855d62e --- /dev/null +++ b/类库/Api.Framework/Cps/alimama_form_login.resx @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + 109, 17 + + + 57 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/alimama_form_select_tgw.Designer.cs b/类库/Api.Framework/Cps/alimama_form_select_tgw.Designer.cs new file mode 100644 index 0000000..e52abdd --- /dev/null +++ b/类库/Api.Framework/Cps/alimama_form_select_tgw.Designer.cs @@ -0,0 +1,602 @@ +namespace Api.Framework.Cps +{ + partial class alimama_form_select_tgw + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(alimama_form_select_tgw)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.label4 = new System.Windows.Forms.Label(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.groupControl3 = new DevExpress.XtraEditors.GroupControl(); + this.label1 = new System.Windows.Forms.Label(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupControl4 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit2 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.label2 = new System.Windows.Forms.Label(); + this.groupControl5 = new DevExpress.XtraEditors.GroupControl(); + this.label3 = new System.Windows.Forms.Label(); + this.pageControl3 = new UI.Framework.Controls.PageControl(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).BeginInit(); + this.groupControl3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).BeginInit(); + this.groupControl4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl5)).BeginInit(); + this.groupControl5.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.label6); + this.groupControl1.Controls.Add(this.pageControl1); + this.groupControl1.Controls.Add(this.gridControl1); + this.groupControl1.Location = new System.Drawing.Point(9, 101); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(753, 417); + this.groupControl1.TabIndex = 43; + this.groupControl1.Text = "推广位列表"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(2, 118); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(748, 33); + this.label6.TabIndex = 2; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(5, 379); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(743, 36); + this.pageControl1.TabIndex = 1; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(0, 21); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(753, 352); + this.gridControl1.TabIndex = 0; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.RowClick += new DevExpress.XtraGrid.Views.Grid.RowClickEventHandler(this.gridView1_RowClick); + this.gridView1.RowCellClick += new DevExpress.XtraGrid.Views.Grid.RowCellClickEventHandler(this.gridView1_RowCellClick); + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.AllowEdit = false; + this.gridColumn1.OptionsColumn.AllowFocus = false; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + this.gridColumn1.Width = 200; + // + // gridColumn2 + // + this.gridColumn2.Caption = "PID"; + this.gridColumn2.FieldName = "pid"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.OptionsColumn.AllowFocus = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + this.gridColumn2.Width = 271; + // + // gridColumn3 + // + this.gridColumn3.Caption = "联盟昵称"; + this.gridColumn3.FieldName = "membernick"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.OptionsColumn.AllowFocus = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + this.gridColumn3.Width = 218; + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.labelControl1); + this.groupControl2.Controls.Add(this.comboBoxEdit1); + this.groupControl2.Controls.Add(this.label4); + this.groupControl2.Location = new System.Drawing.Point(9, 7); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(753, 88); + this.groupControl2.TabIndex = 44; + this.groupControl2.Text = "账号选择"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(418, 43); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(246, 14); + this.labelControl1.TabIndex = 56; + this.labelControl1.Text = "(注意:推广位信息获取,需要先登录好淘宝账号)"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(132, 40); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(254, 20); + this.comboBoxEdit1.TabIndex = 55; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(59, 43); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(67, 14); + this.label4.TabIndex = 47; + this.label4.Text = "操作账号:"; + // + // simpleButton1 + // + this.simpleButton1.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(201, 590); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(152, 32); + this.simpleButton1.TabIndex = 53; + this.simpleButton1.Text = "确认选择"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(408, 589); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(137, 35); + this.simpleButton3.TabIndex = 54; + this.simpleButton3.Text = "放弃修改"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Top; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(779, 572); + this.xtraTabControl1.TabIndex = 55; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.groupControl2); + this.xtraTabPage1.Controls.Add(this.groupControl1); + this.xtraTabPage1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("xtraTabPage1.ImageOptions.Image"))); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(777, 528); + this.xtraTabPage1.Text = " 单 推 广 位 "; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.groupControl3); + this.xtraTabPage2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("xtraTabPage2.ImageOptions.Image"))); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(777, 528); + this.xtraTabPage2.Text = " 组 推 广 位 "; + // + // groupControl3 + // + this.groupControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl3.Controls.Add(this.label1); + this.groupControl3.Controls.Add(this.pageControl2); + this.groupControl3.Controls.Add(this.gridControl2); + this.groupControl3.Location = new System.Drawing.Point(12, 14); + this.groupControl3.Name = "groupControl3"; + this.groupControl3.Size = new System.Drawing.Size(753, 500); + this.groupControl3.TabIndex = 44; + this.groupControl3.Text = "推广位列表"; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.White; + this.label1.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.ForeColor = System.Drawing.Color.Red; + this.label1.Location = new System.Drawing.Point(1, 150); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(749, 56); + this.label1.TabIndex = 2; + this.label1.Text = "推广位组为空\r\n系统管理 -> 其他设置 -> 推广位组(右击增加)"; + this.label1.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label1.Visible = false; + // + // pageControl2 + // + this.pageControl2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl2.Location = new System.Drawing.Point(5, 462); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(743, 36); + this.pageControl2.TabIndex = 1; + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.Location = new System.Drawing.Point(0, 21); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(753, 435); + this.gridControl2.TabIndex = 0; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView2.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Appearance.Row.Options.UseTextOptions = true; + this.gridView2.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn4, + this.gridColumn5}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.IndicatorWidth = 50; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsView.ShowGroupPanel = false; + this.gridView2.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView2_CustomColumnDisplayText); + // + // gridColumn4 + // + this.gridColumn4.Caption = "组名称"; + this.gridColumn4.FieldName = "name"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.OptionsColumn.AllowFocus = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 0; + this.gridColumn4.Width = 261; + // + // gridColumn5 + // + this.gridColumn5.Caption = "推广位"; + this.gridColumn5.FieldName = "adzones"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.OptionsColumn.AllowEdit = false; + this.gridColumn5.OptionsColumn.AllowFocus = false; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 1; + this.gridColumn5.Width = 437; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupControl4); + this.xtraTabPage3.Controls.Add(this.groupControl5); + this.xtraTabPage3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("xtraTabPage3.ImageOptions.Image"))); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(777, 528); + this.xtraTabPage3.Text = "会 员 专 属 推 广 位"; + // + // groupControl4 + // + this.groupControl4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl4.Controls.Add(this.labelControl2); + this.groupControl4.Controls.Add(this.comboBoxEdit2); + this.groupControl4.Controls.Add(this.label2); + this.groupControl4.Location = new System.Drawing.Point(12, 10); + this.groupControl4.Name = "groupControl4"; + this.groupControl4.Size = new System.Drawing.Size(753, 88); + this.groupControl4.TabIndex = 46; + this.groupControl4.Text = "账号选择"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(418, 43); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(246, 14); + this.labelControl2.TabIndex = 56; + this.labelControl2.Text = "(注意:推广位信息获取,需要先登录好淘宝账号)"; + // + // comboBoxEdit2 + // + this.comboBoxEdit2.Location = new System.Drawing.Point(132, 40); + this.comboBoxEdit2.Name = "comboBoxEdit2"; + this.comboBoxEdit2.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit2.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit2.Size = new System.Drawing.Size(254, 20); + this.comboBoxEdit2.TabIndex = 55; + this.comboBoxEdit2.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit2_SelectedIndexChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(59, 43); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 47; + this.label2.Text = "操作账号:"; + // + // groupControl5 + // + this.groupControl5.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl5.Controls.Add(this.label3); + this.groupControl5.Controls.Add(this.pageControl3); + this.groupControl5.Controls.Add(this.gridControl3); + this.groupControl5.Location = new System.Drawing.Point(12, 104); + this.groupControl5.Name = "groupControl5"; + this.groupControl5.Size = new System.Drawing.Size(753, 417); + this.groupControl5.TabIndex = 45; + this.groupControl5.Text = "推广位列表"; + // + // label3 + // + this.label3.BackColor = System.Drawing.Color.White; + this.label3.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.ForeColor = System.Drawing.Color.Red; + this.label3.Location = new System.Drawing.Point(2, 89); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(748, 140); + this.label3.TabIndex = 2; + this.label3.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label3.Visible = false; + // + // pageControl3 + // + this.pageControl3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl3.Location = new System.Drawing.Point(5, 379); + this.pageControl3.Name = "pageControl3"; + this.pageControl3.Size = new System.Drawing.Size(743, 36); + this.pageControl3.TabIndex = 1; + // + // gridControl3 + // + this.gridControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl3.Location = new System.Drawing.Point(0, 21); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.Size = new System.Drawing.Size(753, 352); + this.gridControl3.TabIndex = 0; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // gridView3 + // + this.gridView3.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView3.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Appearance.Row.Options.UseTextOptions = true; + this.gridView3.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn6, + this.gridColumn7, + this.gridColumn8}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.IndicatorWidth = 50; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsBehavior.ReadOnly = true; + this.gridView3.OptionsView.ShowGroupPanel = false; + // + // gridColumn6 + // + this.gridColumn6.Caption = "名称"; + this.gridColumn6.FieldName = "name"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.OptionsColumn.AllowEdit = false; + this.gridColumn6.OptionsColumn.AllowFocus = false; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 0; + this.gridColumn6.Width = 200; + // + // gridColumn7 + // + this.gridColumn7.Caption = "PID"; + this.gridColumn7.FieldName = "pid"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.OptionsColumn.AllowFocus = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 1; + this.gridColumn7.Width = 271; + // + // gridColumn8 + // + this.gridColumn8.Caption = "联盟昵称"; + this.gridColumn8.FieldName = "membernick"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.OptionsColumn.AllowFocus = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 2; + this.gridColumn8.Width = 218; + // + // alimama_form_select_tgw + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(779, 636); + this.Controls.Add(this.xtraTabControl1); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.simpleButton1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "alimama_form_select_tgw"; + this.Text = "阿里妈妈推广位设置"; + this.Load += new System.EventHandler(this.alimama_form_select_tgw_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl3)).EndInit(); + this.groupControl3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.groupControl4)).EndInit(); + this.groupControl4.ResumeLayout(false); + this.groupControl4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl5)).EndInit(); + this.groupControl5.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.Label label4; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private System.Windows.Forms.Label label6; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraEditors.GroupControl groupControl3; + private System.Windows.Forms.Label label1; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraEditors.GroupControl groupControl4; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit2; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.GroupControl groupControl5; + private System.Windows.Forms.Label label3; + private UI.Framework.Controls.PageControl pageControl3; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/alimama_form_select_tgw.cs b/类库/Api.Framework/Cps/alimama_form_select_tgw.cs new file mode 100644 index 0000000..4a6bcb8 --- /dev/null +++ b/类库/Api.Framework/Cps/alimama_form_select_tgw.cs @@ -0,0 +1,283 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Api.Framework.Enums; +using System.Text.RegularExpressions; +using System.Collections; +using Api.Framework.Model; +using Api.Framework.Tools; + +namespace Api.Framework.Cps +{ + internal partial class alimama_form_select_tgw : BaseForm + { + internal class view_alimama_form_select_tgw + { + public string name { get; set; } + public string pid { get; set; } + public string membernick { get; set; } + } + /// + /// 单个推广位 + /// + internal Tuiguangwei Tuiguangwei { get; private set; } + /// + /// 推广位组 + /// + internal fl_adzone_group AdzoneGroup { get; private set; } + + /// + /// 是否为强制推广位组 + /// + private bool isactivity = false; + + internal alimama_form_select_tgw(bool isalone = true, bool isgroup = false, bool isactivity = false) + { + InitializeComponent(); + xtraTabPage1.PageEnabled = isalone; + xtraTabPage2.PageEnabled = isgroup; + if (!isalone && isgroup) + xtraTabControl1.SelectedTabPageIndex = 1; + this.isactivity = isactivity; + } + + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void gridView3_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (xtraTabControl1.SelectedTabPageIndex == 0) + { + var select = this.gridView1.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView1.GetRow(select[0]) as view_alimama_form_select_tgw; + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + Tuiguangwei = new Tuiguangwei() + { + Member = member, + Name = row.name, + Pid = row.pid + }; + AdzoneGroup = null; + this.Close(); + } + } + else if (xtraTabControl1.SelectedTabPageIndex == 1) + { + var select = this.gridView2.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView2.GetRow(select[0]) as fl_adzone_group; + AdzoneGroup = row; + Tuiguangwei = null; + this.Close(); + } + } + else if (xtraTabControl1.SelectedTabPageIndex == 2) + { + var select = this.gridView3.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView3.GetRow(select[0]) as view_alimama_form_select_tgw; + var member = this.comboBoxEdit2.SelectedItem as fl_cps_member; + Tuiguangwei = new Tuiguangwei() + { + Member = member, + Name = row.name, + Pid = row.pid + }; + AdzoneGroup = null; + this.Close(); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView1_RowClick(object sender, DevExpress.XtraGrid.Views.Grid.RowClickEventArgs e) + { + change_tuiguangwei(); + } + + private void change_tuiguangwei() + { + var rows = this.gridView1.GetSelectedRows(); + if (rows != null && rows.Length > 0) + { + var row = this.gridView1.GetRow(rows[0]) as view_alimama_form_select_tgw; + } + } + + private void gridView1_RowCellClick(object sender, DevExpress.XtraGrid.Views.Grid.RowCellClickEventArgs e) + { + change_tuiguangwei(); + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + AdzoneGroup = null; + Tuiguangwei = null; + this.Close(); + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void alimama_form_select_tgw_Load(object sender, EventArgs e) + { + if (!isactivity) + xtraTabPage2.PageVisible = Util.ShowTgwz(); + + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈).ToList(); + if (members == null || members.Count == 0) + { + ShowError("请先登录阿里妈妈后重试!"); + this.Close(); + return; + } + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + + this.pageControl1.Bind(delegate (int page, int pagesize) + { + try + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateAlimamaRequest(member); + var result = api.AdzoneManage(page, pagesize); + this.Invoke(new Action(() => + { + label6.Visible = false; + })); + + ArrayList _list = new ArrayList(); + var paginator = result["paginator"] as Dictionary; + + var list = result["pagelist"] as ArrayList; + if (list != null) + { + foreach (Dictionary item in list) + { + _list.Add(new view_alimama_form_select_tgw() { pid = item["adzonePid"].ToString(), membernick = member.usernick, name = item["name"].ToString() }); + } + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = paginator == null ? 0 : int.Parse(paginator["items"].ToString()) }; + } + catch (Exception ex) + { + this.UpdateUI(() => + { + label6.Visible = true; + label6.Text = ex.Message; + }); + } + return null; + + }, this.gridControl1, 40, true, true); + + this.pageControl2.Bind(delegate (int page, int pagesize) + { + var session = ApiClient.GetSession(); + var result = session.FindAdzoneGroups(CpsType.阿里妈妈, true); + result = result.Where(f => (isactivity ? f.remark == fl_alimama_activity_type.天猫精选.ToString() : string.IsNullOrWhiteSpace(f.remark))).ToList(); + var total = result.Count; + result = result.Skip((page - 1) * pagesize).Take(pagesize).ToList(); + + label1.Visible = result.Count == 0; + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = result, Total = total }; + }, this.gridControl2, 40, true, true); + + this.gridView3.CustomDrawRowIndicator += gridView3_CustomDrawRowIndicator; + + //会员推广位组 + this.pageControl3.Bind(delegate (int page, int pagesize) + { + try + { + var member = this.comboBoxEdit2.SelectedItem as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateAlimamaRequest(member); + var result = api.VipAdzoneManage(page, pagesize); + this.Invoke(new Action(() => + { + label3.Visible = false; + })); + + ArrayList _list = new ArrayList(); + var totalNum = result["totalNum"]; + + var list = result["adzoneList"] as ArrayList; + if (list != null) + { + foreach (Dictionary item in list) + { + _list.Add(new view_alimama_form_select_tgw() { pid = item["adzonePid"].ToString(), membernick = member.usernick, name = item["name"] == null ? string.Empty : item["name"].ToString() }); + } + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = totalNum == null ? 0 : int.Parse(totalNum.ToString()) }; + } + catch (Exception ex) + { + this.UpdateUI(() => + { + label3.Visible = true; + label3.Text = ex.Message; + }); + } + return null; + + }, this.gridControl3, 40, true, true); + + this.comboBoxEdit1.Properties.Items.AddRange(members); + this.comboBoxEdit1.SelectedIndex = 0; + + this.comboBoxEdit2.Properties.Items.AddRange(members); + this.comboBoxEdit2.SelectedIndex = 0; + } + + private void gridView2_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "adzones") + { + e.DisplayText = string.Join(",", ((CsharpHttpHelper.HttpHelper.JsonToObject>(e.Value.ToString())) as List).Select(z => z.Pid)); + } + } + catch (Exception ex) + { } + } + + private void comboBoxEdit2_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl3.GotoPage(1); + } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/alimama_form_select_tgw.resx b/类库/Api.Framework/Cps/alimama_form_select_tgw.resx new file mode 100644 index 0000000..91a8d69 --- /dev/null +++ b/类库/Api.Framework/Cps/alimama_form_select_tgw.resx @@ -0,0 +1,359 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAOdEVYdFRpdGxlAFByb2R1Y3Q7kT0mKAAACOdJREFU + WEfFlnlcjfkexx+urjuWOp1Oi73lImYsWYe54c4SCa9MliSFRAttwhWRpDKWsaTGJTMZM15TUhgd6qC0 + nBaV0CoV6bSJNuvMfX3u9/c85xylzPjr3t/r9ZHzdHren8/39/0tHID/q7p9+L9Utw/fpz8ZPbpRl9Hl + nR0/5H03h8uNsOBuHfuSywn7nMs+MovLOjSTkx/4B5e+bzqXGvopl7JnKnc9cDLn+olWj6O2xjpn3UZ5 + xqwflRvrMboy2n1U2Jm1w6332gwTE+svpJ5KqU0FWRjQj7fcTgZyI2ZzbY8T/1AE7nneZ8zUWK9PohJD + Zr66E+eO8uRvURH3NZpSHVB+3hq/+pnhpL3RzbDFhoEhCwb/k3gaSqlM8dXpYuBWuEW30NZHCdzFzeO1 + pNsmuF3cMi4//+flqLy+CTXZQahICURefAjkh2fgQcxcPL5sjfqkRaiXLUFF/EKkHpyBo7ZG7bs+15dt + Ndf1d58sHqk0IkwR70I5WOk7glmZrwVMnZQYMOnkzQNfPr8vdYcicyca8kNQmeKPzJ9ckHxiHRLDPXBx + 5yxknVqKnO8Xo+CsLYpi7FAUvQTl8ctQccEWVZdWoOayDXbOMmDA3iRWic4GcsK+4MHSHVO0koOnucgC + p+QVnLVH5Y2NaMjdjcbbwajPC0a1PITg3nhRdxnt1TFoe3ASzcX78TQ/AI1yT9SnrEWtzAGKK0tRI7VB + zaX5qL60FHJ/Y/h9psuAfUisCp1Gj7SDMyekH5hxPPuYZdvDlO2ovx2Olqp4tJLaqhPQXCVFQ3Ec7qdF + QnbCh+Dn8OzebjTl+qIhYy3qkgmatISgC1Hz63w8vmQFhdQOhQdMkeenh+vrdbHlUx1moB+pkwE2Hz2p + 41FfGIUn9xNQk3kQD69tRsUVT9y/uBKlcY64c3o+so6Y46q/GaTfLEJr5fdoytuMxixXgjsSnCUW4LWy + VSiNMMPtXQbI36aP3E26uOZCBqaImYH+pF4MrBrMQK9MMvBcEYqWR5FobyxAe0MR2kvC0Z7liNYMWzTJ + bFAdOxc5R6ZDfmoNmksOEdyNSr5SDa9PdsGD09Nxb+9gFOwegPwAA+Ru1UO2rwQyMrBxkogZ0GI8BlYN + ZkAj89sZeNOwF2/q9pCC6P/h+M+Lu8BvzfhdEYu2TGfUJSxAfoQ5Ci9sxNPbuwi+CrUEb0jzxKM4KxQe + Gop7oUNwN3ggnz7PTx85lD7Lmwys04HXBN4A2yfYslQP1pG9acPBm/pQHv5asQuvagLw8tE2vKzeg99a + U4HfW/G6JgllMStQdTOQGs4L9Wm+qEmyQ8m/TVB8dBgKDw4hA8r0Oyi9ny6fPtNLB0nOOvAw02IGdEjM + gLAUaTADH2Xsn443tUF4pdithr+o2ornD3xpKrzRVuqLV/XxeFZXiobbxwlO/RE1EmUn/o7iCEOCC+kL + ggd1SC9BthcZ2CDG1VVirB/HG9Aj/ZWkNsA6sm/6N9MpOcEVDL5DCd+E9lKCl3iipcgdLQXr8LopAw/O + fYzyn01R9sMIlHxngqIwlp4MhAzqlD6H0md56EDuJhhwG8sbYPtxFwP900KnkQGCVzO4nwC/70XJPdGq + hDfnrMbrhusEH82nL30n/V0ywKffpsenZ3PP0qev08YVRzFcx/AGBpLYZqQ2wDpSKzVkqgB/6IcXFZsJ + 7oO2Yi8Bfpfgt6jzs1fipUKK8tOUPnK4kP5wN3O/hTqfSp/lIeHT8wYctEG7KzMwmNTFgHbKnsl4SfDn + lUo4JW+5t15InkfwW45oyrAng7Eo65he2fkFIdT5OwlO6/7t3FP5XbSRtkYE6QptrP2YNzCU9DeS2gDr + SJ0bgZPwonIL2stY07HkBL/jIsBzVuJp5nI8SV2G9vIfUXaqw9zvf5s+bwdtOur0wtyz9DedyIC9CM6j + eQPDSGoD7B/WEPrXAybSy2mLLfOihtsglD1fCZfb40naMjTcWELGjgvpw42EuWebTpCQnu981njKzk93 + ESPZicq/XBvxS0RYM0qzyxSoDAyQ7TCjjlcmZ/A8Zyr7KkruwCdvJHh9og1NySFl+qFC+mDV3LP0ynVP + pc9wFUPmJKbSixBpJWIN2DJ3aN9NxGL7gHonZAaYm0GJ28ejtZAld0NL/loe/kxO8DQ7PEleSvBFqL1i + jac5wSg+1qHzKT3bctmBk63s/FQqfeJqHVxcLkaQuQh2w/unmWhqmBNHn/QRqafqJFZX4Oq2caimfb05 + n5LnCvCmdDs0ptBWm2SDOqk1FHS0NqX7o4g13gFh2RUEvE2ftVGCZBcJkpx08MNCbWwYr9U6e2gff3q/ + CYltwaq7QI+OVwF+FYTYGm2I3zz2SW6kBRrT7emKtUxITocQg9demA9FnCUak307pRfmXg9yHwmuueoi + gZIHzxJhhWn/DCNNDXYlG0RSnYAsMA/nDShdqKZBMsGw3+QwB+P4BL/xKIu2QoNsEequfg3FhQUEt0JN + 9Gz67M6ve9Wmk+tvgDRv4bg9s1gMn4mUelifXfS+ESQ236zj+WvY6pGaPPNdA2ywsrCpEJEMnWboOZ9y + NK65FjQFD8/RxSJ2Hh7/MgfVZ78iM2vU6XMInuKtBynB932ljVWj+8sptQW9YwhJk6Q6dHpI7URctwbU + H4QvsjKxK5O+pF8vs+2WA85EOQ3/PefQZ3j0owWqor7A41gHOm4HIdPPADd99PGLvQS+U0RtloZ9gujv + RpF0SazR+NQMrNIfGjjvYUrf5010rIaxhammXZDlwNJod1MUHTOnC8diZPgNhMzbAIfnSeA0VivbSEtj + Dn2XbTDsstEp9QcbiHEfyZVGz+NKzs6lv+1UDXZ6jV09WTti3/yBrxP+NQ2xzvrYbi5utzLpG0q/G0Ni + R+zb1PadwR9kINp1BPfTGhMuaqUxF2lvSO/pUg2TMfq9rb2masvdJ4rkxiINS3pmrPydOjXt9xzteJwT + wRjwXXVkdvrwPilfzJKxarD5ZaVmkiifqZbXn44u7373wftEg09HYjC2ZJnU65r0QaPze8H9FyTi9z+I + F2gqAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAXdEVYdFRpdGxlAFByb2R1Y3Q7UHJvZHVjdHM7c0vM + pAAACNJJREFUWEfFV3lcT+kePsLYyoSmaeEqtO9psRUjkmUywhQyolSKaRCNFkmWiKGUTK4xKbkVVwta + SXW1WiptSpvSooWiLHe6z3zfU5mRX/+Mz2fu9/N5Tuf3vud9n+/2PufEAfi/QuDgYCAbQhBifwXN/xXw + l1z/eVzOSUMu6ycDLvPobC7jyAwu7ZA+l7pfl0vxnN5PPJwg7LtmymJV6dESdD+mb2xIsKUsF2Q+mfNf + OYk7YSrNHV0i+RHRYOAvOX5zufZHIR+BjEX72WSxkeMDN8ltSzlmUled7oPQzfLdp9bKxjkbS1nTvDhB + hD1HGNL1+DjnYyLxEdFg4C/ZJwz/TMqiHUoYaWc8UT7sB03/jMAV3VW39qD5/iHQM8gJt0NFvB0yTi7E + aQuZ9r2LpaIsp49fS2ukCGMJvDMDyQSBv2T/NIee54mHEcb42SguinbVS8wLseypy/REfeY+lEY7ofBf + W1ASvRfRHibIPmuF/Ev2KL1ij+wAU0Q4qMN7vni7o974SybThL+mfUYPJBMEZnx95aTGiIZu13BK9Dao + LKBNG3K9+YgZGHnn4yh0lJ7H84eBaLt/FK25nmjJ3I3mjO/RdNsWjTet0Ji8DnXxFjhno8R2niiIcCCY + fRbjruOTFWjaWZ3hw6d4IFjUHWUX8DR+xaBoSFyFtpztqI22gIfBF2znaYIIB4KZcPrhGXjVdA2tldGo + e/AzavL8UZ5+FPmxrrgT4oAol0V4URQkkJihJXMbGpJsUBSgjQJfFbjOFmM7ywkiHAhmoumH9fGmwRvv + 2sLQ87oAPa/u4PWzy2h7FIzqTB+kBWxAe/6xj4gbU23QlL4DZb/MQpG/OgqPqyLfRwkuMyewnRUEEQ4E + s/G3D+ridb0nup+4o6t2H962RZMjpehujkdzgR/yLzuhNc/rD+KUDWjOdMPjcCOU/qyN4kANPDyhhoKj + yrh3UAG79MeznVUITCfYiRr0RDATS92vg64aN3RV78HLyt3orHDGy8d7yZEkvHv5CC3FIWjJ+hENyZZo + yduPmmgzVJzXQ9nZ6Sg5rYkiPyI/poK7BxVxx10OBxdJIMRW9kGo7ZQsT1NJU+J4rxMBq6Q5v+VS3LGl + vVrBTPzmPm0i3sUTdz7ajs4yJ3QUb6WOd6Tf3uh58wyt9w6hIcUaVRdnoCJEH4/+qYPSM1pEroF8qnu2 + lxKSXeQRu0OejqcDuhrTUB1vjQy/JQiwmHTf3kBsDXGJEUYShHyX/OGARIqnFk/cUfo9XjDiQgc8L7BH + +/3NaL1rjTetWaiOmo3KS7PwOFQf5ed1UEKpL/TXQJ6PCm65KSLeRRGFkY5EnE6On8azO84oj5yPtw0X + 0F5wAClHjHFomUSRhaYoU08mWKMJTGk5qSQPTTwvciTiLdRstmi7R8R5m9Cas4FSvx7djcmojpiFyrAZ + KP9Vj6KfTuSaSPNWQZK7MkqubP2AmOHpTSfk+umgKtkDVYnuqEpwRVG4DSIcdeA6U7TWVFHEnriZanIT + 49000P6AiCna1txNaMnegGeZ60lk1lCXm+NV7VVUhs9ExQVK/bne1Of5quGmlyraS3zxpu0u6m87oSrm + G1ReXYqKy8ZErjuoeJVHrUeA2WQojOI0mAP/uOGiRpNWFO135L1lL3GaORpvraKON0Nn+YW+1OuiLJga + L1AT2YdVkOKpiu7avdS81LCt1/Fb10O8a72Cd00XKXLPj8SrIXE1BTKPAtDG/vm8WLGTwslc26WK5v8Q + cboFyeq3RLySOp4WJS1H/Y1lfATlIbp86kuCqPHozGcfUEaShwpeVbriZYUL9RA1cZk73rak4beObN6B + fvGqv2GGmiuL+fXs2JYEacJrHu+AGnNgcuxOFTSlUrQ3+4gTiPj6MtTFLUFdjAn1w2GU86mnMx/Qe+az + qOsT3ZTxsmwXOkp2kpNOeJ6/lfqHGvihJ57kxKHtgS+exC4n5/VRdo7Ig3vJ2R775vJqqc4cmHDSckpC + 0l4tVEQtIuKlqI9dzBPX/nsBai4bUUlc35/5hyfV+TOfuU8BCa5KeNFH3H7fgcpoS2W0oTJuxKsn11AV + YURNS2Vjzp9l5JQ9JlqUQU9D3gFN5gBTK6l1M8V+CLaa2pJ+RJeOHBFHGaEm4itUU80ak7ehtC/1/XKb + 6jIN1+notVPEPHG2NZVxI/XOd1TCteisjOwt2y865Lw237hMMYtOqVMQanCfw8u1Vr8YsPMoIiY8TMt5 + oURMuJ1cz4MAfVSFGaAy1AD1cVaUNoq+T27jtsnCSW/c22u7FPiIe4nXE/E6PE02R338KjwvPtdLzvqG + 1Z0at5+cBeE2m3dAk3cgYos8VxP5FXOEz8Y8ORFrLxPJuugdiuS9PmVjJSmeOnIPKeHMamlYqYwtkxwz + dG3MDgU8TVmLBor4abIF6hNWoe76CjyJMSXlPNmrlsFafOn43qE9Co+rINJeBnban9cQlyzvQLjtNK76 + oiFH0TInWDbYB6eypZZo+PHlkv9NPzwTCbvl4DH3izcLZccE0ZwiYcKB1RN/vOqs1F0cZoK6aytQG2uK + GtKB6ssmaLrjhTL2oqKmKyJy9r5gkZ/5VhrmyiLpw4WGsK/dUbwDYZumcuc3yHJn18nQ1+0k7pSZNM3x + n2cSyuIjzB10xxXZTRctkvl8+Dc0xj5C2RxftmUaokaBlpNLbh3UQWWkCTWeMUm2EWVmO990LPIifzWS + bGUcWfzl/xbIjg6kdVMJI/jys8tgIGOfa0yzJxKYV+z+/auV3RNGEGR2LhAPCbeX68kPmoWKUEPUxm2i + ujNydSTvkYeroVi3ktiIzfTsl4Rhu/XG9e7Rv9mngIy988WNFUWsfZZLPkt0V0VV5EoUE/lFGxk46o2r + EP5MiDUZ036hD9b++cengIxlQ1hy7DC9LbMmpP66cSr8VkjCTFkkYqgQp0pzIwWuEzT4V8E+Nsj4knyt + JOI8Y9Io9r8CGxzuNmeCwDUCBz8VZKwkowjMmQ9SPhACB/9OCBz8+wDud0IUucB3M2m1AAAAAElFTkSu + QmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAALdEVYdFRpdGxlAFNhbGU76FnfrwAACeVJREFUWEfF + lwdUlFcWx8e2bmJBKQISFVEEEhVRseCCJipSRDEYCyJqbPQZLBBHBAUETMQ2CLFgS+EIIlgCioigwFBk + AJUuRZEuShMbOf+975uRDB6yuzm75+w75zIz3zfzfv//vfe998ED8H+N/9Xo00v829FDgORHM15OmCnv + /vEFvOyQr3hZx+bxMo/M5YmD/8FL+8GIdy9oFi9l/0xekq8hz3GiQh/RKi2lCCc9fpSLXk602+eVkc56 + IT9v0bY+YDNGkabrR9FXFt2i/E3V6OWP0UNATtgiXvuzhH8ZBO57edukmdGCiecTAue+eRDjjMfJh1ER + 8zWa79nj8WVrXBca4LTd2Lsh32j6Bi757EuaeoAsPojqzk4PAfdDTXuFtj2N4131mKIQv3uq01VP/dzc + X9egMmknarL8UZHiC0lsIMRHTVAeZYFnv1mj4dZyNCSuQEXsMtw7ZALRqrEd+75STdxlrLLH2VBRh1BM + CCeipwBKvTyYpfn23pnTE/ZOP303eMGrsnhn1Gb4oDE3EJUpe5DxiwOST21FQqgbrvrMQ+aZlcg++w3y + I1ahMMoWhZEr8Dh2NSqurELVtbWo+c0GPvPUGHEgBctETwHZIfM5cLz3DIXkgNkOib4zJPkRdqi8sx2N + OX5oygtAgyQA1eJAgrujs/43dFRHob38NFqKDuJF7l40ifloSNmCukR71N5YiZp4G9Rcs0L1tZUQ79GC + cI4KI35KwbLQQ0Cf1ENzp6YFm5zIOm7e/iTFCw15oWitikUbRXt1HFqq4tFYFIOy1HAkntpG8Et4+cgP + zTk70Ji+BfXJBL21gqDLUHPdCs+uWaI23hYFwbqQCEcgyUUFnrOUGHEwRQ8BrB59qePRUHAez8viUJNx + CE9ue6DiBh9lV9ejJGYdHlywQuYxY9zcY4D475ejrfIsmiUeaMp0JPg6gjPHUnhd4gaUhBkgb58acner + ImenCm47kIAZiow4hKI/A8sL6J9BAl7VBqH1aTg6mvLR0ViIjuJQdGSuQ1v6KjQn2qA62gLZx4wgPrMJ + LcVHCO5EKV/fDW9IdkD5BSM8OvAZ8v3UkbtXDTm7RiBrhzISScD26cOw20L3vpeF7kX3BeNZKbhmZH8G + ZBw2wbvGA3hXv5/Cn96H4vfOh8D7FnTVRqM9YzPq45YgN8wYBVe240XePoJvQB3BG1P5eBpjiYIjo/Eo + aBQeBozk3EuEqsgm95nuJGCrEgRTh2GnqXaw56IJjkILnXOMywSwjhxIGw7eNQRx8Le1+/CmZi9eP92N + 19X78b7tHtDVhrc1t1AatRZVd32p4QRoSN2Bmlu2KD45DkWiMSg4NIoEyNx7k3uhCuc+Q6CEW5uV4Gag + gLWzRn9pPlFtzB5L3ZfEZf3ACfgk/aAR3tX5402tXze8s2oXXpXvoFK4o71kB940xOJlfQka804QnPrj + vA5KT41HUZgmwaXu8wM05NwrI0tAAlwVcXODIlz0FTDk7/015oxX0vSy0Gsj7nAmgHXkoLTvjcg5wWsZ + 3FsG34mOEoIX89Fa6IzW/K1425yO8ktf4PGvuig9NwHFP45DYQhzTwICNXq4zyb3mW5KEDtJBThNVmBd + p0FZWOZhpiORFzAkNWg2CSB4NYMLpfAyATnno00Gb8n+Fm8bkwj+Oee+5CP3D0kA5373CM49qz1zn7Z1 + OOLXKcJhEidAWzB//KVNxpo+9H4QE8CWhMK9wJlS+BMhOis8CL4N7UUCKfwhwe9T52etx+vaeDy+QO7D + taXuj/ZSe0/qfEr9MSdTzN4QAkN7EabaHoK+TSAMjBaLhBa6DcqDB2oTl9sPmIDhKfsN8ZrgryplcHLe + +shF6lxC8Pvr0JxuRwKjUSrvXtb5+YHU+T4Ep3XP3IucTWH1XSzczpSDf7YCruEl2HhYjC3Ll2LpXKN4 + YiozOBtsKSjd8Z2OzkpPdJSypmPOCf7AQQrPXo8XGWvw/N5qdDz+CaVn5Gp/8A/3Em/adMi9PPzbsDLM + c7+Cacv9YLV6G/h2K6A11wVD1CeNIi63D/yNQjVp7zSanLbYUgE1nKs07bkyuNgOz1NXo/HOChJ2Quo+ + dKy09mzT8Ze6Z51/zNUUiz1j4XKqBPZHH8HS7z4MVh6E+yJ9eK61hoVrOLTmuWOw+sTx8gLUE70NqONl + zhlcspnSvoGc23POmwjekGBDJTkicz9a6j7gQ+1VIeIv4uAOYQVwFGXA+0wW3ENSscwjCvpLvWG5ORhr + /OKhacLHIBVddjRzAtjxqJHgNQVtBcy5E1pzt3Dwl2KCp9riefJKgi9H3Q1rvMgOQNFxuc4n9xJyLxIs + 4tLufLIEDkczkF9Wjyd1L9HV9TuEoXexxCsB9oFJsNp1HaONnPGp8oRuAVwGbu7WRzXt6y255DxHCm9O + s0VTCm21t2xQH2+NWjpam9P2oJA1XrBs2fmoQ7TNjJzHYGvYI6wIFOPALzl4WteCaWtPorXjNc5dz4Ox + WyzFZehZ+UFJ1+owMYd+EMCtgsBVY11jPSY/zwk3RVOaHT1irZY6p0OIweuuWKE2xhxNyTu63T/wGwnR + djPOueOPhQiKyENRVTMWCi7j7bsuOH4fh8t3imDkEAFjl0scXFnX8hjxVCj6yZ+GrAzKUzUHG4bYa8XG + CaegNNISjYnLUX/za9ReWUJwS9RELqLPzty6Z+4ldNpZbtqPraEPYXc4Dz/dKOCcG64/i9ziGogiM2Hk + dBHGrgRfTHAdCxFxRlD0U/5idY8HEnYesFIMo9DcaDJi85l1WjW3/WfgySV6sIhejGcXzVAdsZDEbOqu + fZaXGn510sHCTYdg4ZMOr1NivHvfxdW+/Fkz7H2vYY5LlDTtOuYhNLcqRb+1+67yPhbABssEKwc7p1WV + B/c38DJX//n8Ru2u7CNz8PQnU1Sdn49n0fZ03GogQ6iGu9tUEbFGGRtnju2cvvJAp63/bfCPJGFXaDIW + 8iMxx/GiFD7B4jibk4KD9yrgspsue2Ei5LOhZao71NbffGRJpLMuCo8b0wPHN0gXjkSiuxqOLib4ZIWs + MUMHWCqONbLRX+b3cp7gCkz41HAu0QT3Zc5DaR72D0E3vFcBUc46vJLIxbziCAv2UT4b7MeTvzUcHvaD + 1ci3cd/NRvRmVXgZK3ZYjhsURPcmUTB3w5TGmyzQM9vVYkx117Pyh5K2eRhdV6foAe9VQKTjBN4vm8bx + zq/X4oXbabJLH2dj3CTVgdaCmcPFztOGibWGDTCna1qye2w7Z98dpDB6hpmG4cZmpQnmLO0cnMF6i497 + 4M8GE8JOLZYNtnzGyIIdJuwayxT7Dhvs9RMK1ulMGLv3p+M/FcAGm5gFm5AtWRYfwB/gf3n8FQHy47+C + yg8AvH8CqUB0J/cNlPoAAAAASUVORK5CYII= + + + + 50 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_login.Designer.cs b/类库/Api.Framework/Cps/douyin_form_login.Designer.cs new file mode 100644 index 0000000..9946aec --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login.Designer.cs @@ -0,0 +1,303 @@ +namespace Api.Framework.Cps +{ + partial class douyin_form_login + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(douyin_form_login)); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.button1 = new System.Windows.Forms.Button(); + this.webControl1 = new EO.WinForm.WebControl(); + this.webView1 = new EO.WebBrowser.WebView(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.label1 = new System.Windows.Forms.Label(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.label2 = new System.Windows.Forms.Label(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.textBox2 = new System.Windows.Forms.TextBox(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(911, 492); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage3, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.button1); + this.xtraTabPage1.Controls.Add(this.webControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(909, 466); + this.xtraTabPage1.Text = " 扫 码 登 录 "; + // + // button1 + // + this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.button1.Location = new System.Drawing.Point(767, 14); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(116, 23); + this.button1.TabIndex = 1; + this.button1.Text = "授权无效时点击"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click_1); + // + // webControl1 + // + this.webControl1.BackColor = System.Drawing.Color.White; + this.webControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webControl1.Location = new System.Drawing.Point(0, 0); + this.webControl1.Name = "webControl1"; + this.webControl1.Size = new System.Drawing.Size(909, 466); + this.webControl1.TabIndex = 0; + this.webControl1.Text = "webControl1"; + this.webControl1.WebView = this.webView1; + // + // webView1 + // + this.webView1.InputMsgFilter = null; + this.webView1.ObjectForScripting = null; + this.webView1.Title = null; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.label1); + this.xtraTabPage2.Controls.Add(this.simpleButton1); + this.xtraTabPage2.Controls.Add(this.memoEdit1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(909, 466); + this.xtraTabPage2.Text = " 同软件登录码 "; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ForeColor = System.Drawing.Color.Blue; + this.label1.Location = new System.Drawing.Point(247, 373); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(403, 14); + this.label1.TabIndex = 4; + this.label1.Text = "注:抖音登录码为相同返利软件联盟列表中选中要复制的抖音右击复制所得"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(351, 402); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(194, 41); + this.simpleButton1.TabIndex = 3; + this.simpleButton1.Text = "验证登录码有效性"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // memoEdit1 + // + this.memoEdit1.Dock = System.Windows.Forms.DockStyle.Top; + this.memoEdit1.Location = new System.Drawing.Point(0, 0); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(909, 355); + this.memoEdit1.TabIndex = 0; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.groupBox2); + this.xtraTabPage3.Controls.Add(this.groupBox1); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(909, 466); + this.xtraTabPage3.Text = " Cookie登录 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.linkLabel1); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.groupBox1.Location = new System.Drawing.Point(0, 0); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(909, 222); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "第一步 请输入抖音Cookies"; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(215, 0); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(79, 14); + this.linkLabel1.TabIndex = 1; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "复制登录地址"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // textBox1 + // + this.textBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.textBox1.Location = new System.Drawing.Point(3, 18); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox1.Size = new System.Drawing.Size(903, 152); + this.textBox1.TabIndex = 0; + // + // simpleButton2 + // + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(358, 176); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(194, 31); + this.simpleButton2.TabIndex = 2; + this.simpleButton2.Text = "验证Cookies有效性"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click_1); + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.Controls.Add(this.simpleButton3); + this.groupBox2.Controls.Add(this.label2); + this.groupBox2.Controls.Add(this.linkLabel2); + this.groupBox2.Controls.Add(this.textBox2); + this.groupBox2.Enabled = false; + this.groupBox2.Location = new System.Drawing.Point(3, 228); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(903, 235); + this.groupBox2.TabIndex = 2; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "第二步 填写授权结果"; + // + // simpleButton3 + // + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(355, 196); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(194, 31); + this.simpleButton3.TabIndex = 3; + this.simpleButton3.Text = "同步Session网络数据"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.ForeColor = System.Drawing.Color.Red; + this.label2.Location = new System.Drawing.Point(313, 162); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(286, 19); + this.label2.TabIndex = 4; + this.label2.Text = "请填写登录成功后的,页面中所有的内容"; + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(215, 0); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(79, 14); + this.linkLabel2.TabIndex = 2; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "复制登录地址"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked); + // + // textBox2 + // + this.textBox2.Dock = System.Windows.Forms.DockStyle.Top; + this.textBox2.Location = new System.Drawing.Point(3, 18); + this.textBox2.Multiline = true; + this.textBox2.Name = "textBox2"; + this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox2.Size = new System.Drawing.Size(897, 172); + this.textBox2.TabIndex = 0; + // + // douyin_form_login + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(911, 492); + this.Controls.Add(this.xtraTabControl1); + this.Name = "douyin_form_login"; + this.Text = "抖音登录 - (请勿手动关闭窗口,授权成功会自动关闭)"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.douyin_form_login_FormClosing); + this.Load += new System.EventHandler(this.douyin_form_login_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private EO.WinForm.WebControl webControl1; + private EO.WebBrowser.WebView webView1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private System.Windows.Forms.GroupBox groupBox2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.TextBox textBox2; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_login.cs b/类库/Api.Framework/Cps/douyin_form_login.cs new file mode 100644 index 0000000..345b37e --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login.cs @@ -0,0 +1,519 @@ +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using DevExpress.XtraEditors; +using EO.Base; +using EO.WebBrowser; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + public partial class douyin_form_login : BaseForm + { + public douyin_form_login() + { + InitializeComponent(); + } + + internal fl_cps_member Member { get; private set; } + + /// + /// 是否已经授权 + /// + private bool IsAuthorization = false; + + private void douyin_form_login_Load(object sender, EventArgs e) + { + try + { + InitializeChromium(); + } + catch (Exception ex) + { + ShowErrorAutoClose(ex); + } + } + + //private const string loginUrl = "https://open.douyin.com/platform/oauth/connect?client_key=aw7tduvjdk1a0x3r&state=douyin_sso&response_type=code&scope=mobile%2Cuser_info%2Cvideo.create%2Cvideo.data&redirect_uri=https%3A%2F%2Fbuyin.jinritemai.com%2Faccount%2Fpage%2Fservice%2Flogin%3F"; + private const string loginUrl = "https://buyin.jinritemai.com/mpa/account/login?log_out=1&type=24&target_url=/dashboard/dataCenter/order"; + + private void InitializeChromium() + { + var accountName = Guid.NewGuid().ToString("N"); + EO.WebEngine.Engine engine = EO.WebEngine.Engine.Create(accountName); + engine.Options.CachePath = HttpExtend.MapPath($"Cache\\Cookies\\{accountName}"); + webControl1.WebView.Engine = engine; + + EO.Base.Runtime.Exception += Runtime_Exception; + + webControl1.WebView.LoadUrl(loginUrl); + //webControl1.WebView.TitleChanged += WebView_TitleChanged; + webControl1.WebView.LoadCompleted += WebView_LoadCompleted; + webControl1.WebView.NewWindow += WebView_NewWindow; + var sHandler = new SampleHandler(); + sHandler.JsonAction += SHandler_JsonAction; + webControl1.WebView.RegisterResourceHandler(sHandler);//注册自定义资源处理程序 + } + + /// + /// 是否跳转到授权页面 + /// + private bool IsJumpAuthorizationUrl = false; + + private void WebView_LoadCompleted(object sender, LoadCompletedEventArgs e) + { + try + { + Debug.WriteLine("####### " + e.Url); + + LogHelper.GetSingleObj().Debug("抖音授权地址", e.Url); + + if (e.Url.StartsWith("https://buyin.jinritemai.com/account/page/service/login")) + { + webControl1.WebView.EvalScript("document.getElementsByClassName('platform-logo')[0].click()", false); + } + if (e.Url.Contains("buyin.jinritemai.com/dashboard/institution/through-power"))//新账号需要点击确定授权? + { + webControl1.WebView.EvalScript( + "document.getElementsByClassName('auxo-btn auxo-btn-primary auxo-btn-lg')[0].click()", false); + } + //else if (e.Url.ToLower().Contains("cps.api.52cmg.cn/api/douyin.asmx"))//授权成功页面 + else if (e.Url.ToLower().Contains($"{ApiClient.Setting.SystemConfig.cps_server_api}api/douyin.asmx"))//授权成功页面 + { + IsJumpAuthorizationUrl = true; + + var flag = false; + var json = webControl1.WebView.GetText(); + if (!string.IsNullOrWhiteSpace(json)) + { + var jObj = JObject.Parse(json); + if (jObj != null) + { + if (Member != null) + { + if ((bool)jObj["ok"]) + { + IsAuthorization = true; + EventClient.OnEvent("抖音登录", "抖音授权登录成功!"); + flag = true; + } + } + } + } + if (!flag) + EventClient.OnEvent("抖音登录", "抖音授权登录失败!"); + this.DialogResult = DialogResult.OK; + } + else if (e.Url.ToLower() == "https://buyin.jinritemai.com/dashboard/dataCenter/order".ToLower()) + { + webControl1.WebView.Engine.CookieManager.GetCookies("http://buyin.jinritemai.com", true).ToString(); + webControl1.WebView.EvalScript("function getck() {return document.cookie}", false); + var ck = string.Empty; + if (string.IsNullOrWhiteSpace(CK)) + { + ck = webControl1.WebView.InvokeFunction("getck")?.ToString(); + LogHelper.GetSingleObj().Info("抖音登录获取到ck", ck?.ToString()); + } + var json = DouyinApi.GetLoginUserInfo(CK ?? ck, UserAgent); + LogHelper.GetSingleObj().Info("抖音登录获取到用户数据", json); + CheckLoginCk(json, CK ?? ck, UserAgent); + //EventClient.OnEvent("抖音登录", "抖音登录授权跳转2"); + //webControl1.WebView.LoadUrl(AuthorizeLoginUrl); + + if (!IsJumpAuthorizationUrl) + { + //EventClient.OnEvent("抖音登录", "抖音登录授权跳转1"); + Task.Run(() => + { + int num = 0; + do + { + num++; + + EventClient.OnEvent("抖音登录", $"请求跳转授权页面,第{num}次"); + webControl1.WebView.LoadUrl(AuthorizeLoginUrl); + + Thread.Sleep(10000); + } while (num < 13 && !IsJumpAuthorizationUrl); + }); + } + } + } + catch (Exception) + { } + } + + private static string AuthorizeLoginUrl => $"{ApiClient.Setting.SystemConfig.cps_server_api}api/douyin.asmx/login"; + + private string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"; + + private string CK = string.Empty; + + /// + /// 订单响应数据 + /// + /// 拦截的url + /// 拦截的数据 + private void SHandler_JsonAction(string url, string cookice, string json, string ua) + { + try + { + if (url.ToLower().Contains("buyin.jinritemai.com/index/getUser".ToLower()) || url.ToLower() + .Contains("buyin.jinritemai.com/dashboard/dataCenter/order".ToLower())) + { + //EventClient.OnEvent("抖音登录", "抖音登录授权跳转3"); + //webControl1.WebView.LoadUrl(AuthorizeLoginUrl); + CK = cookice; + //if (url.ToLower().Contains("buyin.jinritemai.com/index/getUser".ToLower())) + //{ + // CheckLoginCk(json, CK, UserAgent); + //} + } + } + catch (Exception ex) + { + ShowErrorAutoClose(ex); + } + } + + private void WebView_NewWindow(object sender, NewWindowEventArgs e) + { + webControl1.WebView.LoadUrl(e.TargetUrl); + } + + private void Runtime_Exception(object sender, ExceptionEventArgs e) + { + e.ShowExceptionDialog = false; + } + + /// + /// CK验证(ck登录方式) + /// + /// + /// + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var tmp = memoEdit1.Text.Trim(); + if (string.IsNullOrWhiteSpace(tmp)) + throw new Exception("请填写登录码"); + + var json = Util.DecryptDES(tmp); + + fl_cps_member cps = null; + try + { + cps = JsonConvert.DeserializeObject(json); + } + catch (Exception) + { throw new Exception("登录码解析异常"); } + if (cps == null) + throw new Exception("登录码解析异常."); + + Member = CpsClient.Members.FirstOrDefault(f => f.username == cps.username && f.cpstype == CpsType.抖音联盟); + if (Member == null) + { + Member = cps; + CpsClient.Members.Add(Member); + } + Member.usernick = cps.usernick; + Member.logintime = DateTime.Now; + Member.cookies = cps.cookies; + Member.online = true; + Member.is_valid = true; + Member.other = cps.other; + IsAuthorization = true; + } + catch (Exception ex) + { + ShowErrorAutoClose(ex, 15000); + } + finally + { + this.DialogResult = DialogResult.OK; + } + } + + private bool CheckLoginCk(string html, string ck, string userAgent) + { + try + { + var cps = DouyinApi.GetUserInfo(html, ck); + + if (cps != null) + { + Member = CpsClient.Members.FirstOrDefault(f => f.username == cps.username && f.cpstype == CpsType.抖音联盟); + if (Member == null) + { + Member = cps; + CpsClient.Members.Add(Member); + } + Member.usernick = cps.usernick; + Member.logintime = DateTime.Now; + Member.cookies = ck; + Member.online = true; + Member.is_valid = true; + Member.other = userAgent; + EventClient.OnEvent("抖音登录", "抖音信息获取成功"); + return true; + } + } + catch (Exception ex) + { + ShowErrorAutoClose(ex, 15000); + } + return false; + } + + #region 自定义响应Response 20210321 + + internal class SampleHandler : ResourceHandler + { + private static int num = 1; + private static bool IsRun = false; + + public event Action JsonAction; + + //如果使用此方式,将完全转移嫁接,包括真实请求,需要自己模拟请求, + public const string SampleUrlPrefix = "sample://"; + + public const string EmbeddedPageUrl = "sample://embedded_page"; + + //此方法判断是否自定义处理响应 + public override bool Match(Request request) + { + var cookies = Regex.Replace(request.Cookies.ToString(), "path=/", "").Replace("\r\n", ""); + //Debug.WriteLine("!!!!!!!!!!! = " + request.Url); + + if (request.Url.Contains("buyin.jinritemai.com/index/getUser") || request.Url.Contains("buyin.jinritemai.com/dashboard/dataCenter/order")) + { + //if (!IsRun) + //num++; + JsonAction?.Invoke(request.Url, cookies, "", ""); + //return true; + } + return false; + } + + //如果自定义响应,则在这里处理请求,并返回要显示的信息 + public override void ProcessRequest(Request request, EO.WebBrowser.Response response) + { + try + { + EventClient.OnEvent("抖音登录", "抖音获取登录信息中..."); + IsRun = true; + var UserAgent = string.Empty; + var cookies = Regex.Replace(request.Cookies.ToString(), "path=/", "").Replace("\r\n", ""); + //if (request.Url.Contains("buyin.jinritemai.com/index/getUser") || request.Url.Contains("buyin.jinritemai.com/dashboard/dataCenter/order")) + //{ + //Console.WriteLine(request.Headers[1]); + if (request.Headers.AllKeys.Contains("User-Agent")) + UserAgent = request.Headers["User-Agent"]; + //} + //else + //{ + + + //} + + //var http = new HttpHelper(); + //var data = http.GetHtml(request.Url, cookies, ""); + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = request.Url, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookies, + UserAgent = UserAgent, + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "https://buyin.jinritemai.com/dashboard", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + var data = http.GetHtml(item); + + var json = data.Html; + if (!string.IsNullOrWhiteSpace(json)) + { + if (cookies.Contains("buyin_app_id=1128;") || cookies.Contains("buyin_shop_type=24;")) + JsonAction?.Invoke(request.Url, cookies, json, UserAgent); + + response.ContentType = "application/json";//必须设置,否则会弹出对话框并无法显示在EO.Web控件上 + response.ContentEncoding = "UTF-8";//必须设置,否则中文显示乱码 + byte[] be = Encoding.UTF8.GetBytes(json); + response.OutputStream.Write(be, 0, be.Length); + response.OutputStream.Close(); + return; + } + } + catch (Exception ex) + { } + base.ProcessRequest(request, response); + } + } + #endregion + + private void douyin_form_login_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (!IsAuthorization) + if (XtraMessageBox.Show("当前未授权完成,是否取消登录?", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.No) + e.Cancel = true; + } + catch (Exception ex) + { } + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + webControl1.WebView.Reload(); + } + catch (Exception ex) + { } + } + + private void button1_Click_1(object sender, EventArgs e) + { + IsAuthorization = false; + webControl1.WebView.Reload(); + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + //try + //{ + // var ck = memoEdit2.Text.Trim(); + + // if (string.IsNullOrWhiteSpace(ck)) + // throw new Exception("请填写cookie"); + + // LogHelper.GetSingleObj().Info("抖音登录获取到ck", ck?.ToString()); + // var json = DouyinApi.GetLoginUserInfo(ck.ToString(), UserAgent); + // LogHelper.GetSingleObj().Info("抖音登录获取到用户数据", json); + // CheckLoginCk(json, ck.ToString(), UserAgent); + // if (Member != null) + // { + // AuthorizeLoginUrl + // } + //} + //catch (Exception ex) + //{ + // ShowErrorAutoClose(ex); + //} + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + Clipboard.SetDataObject("https://buyin.jinritemai.com/mpa/account/login?log_out=1&type=24"); + BaseForm.ShowSuccess("复制成功,请到本机电脑粘贴登录!\r\n登录成功后,请填写Cookies验证!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton2_Click_1(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(this.textBox1.Text)) + throw new Exception("请填写Cookie"); + var json = DouyinApi.GetLoginUserInfo(this.textBox1.Text, UserAgent); + LogHelper.GetSingleObj().Info("抖音登录获取到用户数据", json); + if (CheckLoginCk(json, this.textBox1.Text, UserAgent)) + { + this.groupBox2.Enabled = true; + BaseForm.ShowSuccessAutoClose("验证成功,您可以继续授权Api"); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + Clipboard.SetDataObject(AuthorizeLoginUrl); + BaseForm.ShowSuccess("复制成功,请到本机电脑粘贴登录!\r\n登录成功后,请填写页面字符串同步!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + try + { + var flag = false; + var json = this.textBox2.Text; + if (!string.IsNullOrWhiteSpace(json)) + { + var jObj = JObject.Parse(json); + if (jObj != null) + { + if (Member != null) + { + if ((bool)jObj["ok"]) + { + IsAuthorization = true; + EventClient.OnEvent("抖音登录", "抖音授权登录成功!"); + flag = true; + + this.DialogResult = DialogResult.OK; + } + } + } + } + + if (!flag) + throw new Exception("抖音授权登录失败!"); + } + catch (Exception ex) + { + if (ex.Message.Contains("Unexpected")) + { + BaseForm.ShowError("数据格式不正确,请检查是否复制错误"); + return; + } + + BaseForm.ShowError(ex); + } + } + } +} diff --git a/类库/Api.Framework/Cps/douyin_form_login.resx b/类库/Api.Framework/Cps/douyin_form_login.resx new file mode 100644 index 0000000..5b8ff6f --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login.resx @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + 60 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_login1.Designer.cs b/类库/Api.Framework/Cps/douyin_form_login1.Designer.cs new file mode 100644 index 0000000..b3f3001 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login1.Designer.cs @@ -0,0 +1,57 @@ +namespace Api.Framework.Cps +{ + partial class douyin_form_login1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.webView1 = new EO.WebBrowser.WebView(); + this.SuspendLayout(); + // + // webView1 + // + this.webView1.InputMsgFilter = null; + this.webView1.ObjectForScripting = null; + this.webView1.Title = null; + // + // douyin_form_login1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1180, 797); + this.Name = "douyin_form_login1"; + this.Text = "抖音登录"; + this.WindowState = System.Windows.Forms.FormWindowState.Maximized; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.douyin_form_login1_FormClosing); + this.Load += new System.EventHandler(this.douyin_form_login1_Load); + this.ResumeLayout(false); + + } + + #endregion + private EO.WebBrowser.WebView webView1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_login1.cs b/类库/Api.Framework/Cps/douyin_form_login1.cs new file mode 100644 index 0000000..ef0f339 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login1.cs @@ -0,0 +1,143 @@ +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + /// + /// 抖音登录 + /// + public partial class douyin_form_login1 : BaseForm + { + DouyinApi api = null; + public douyin_form_login1() + { + InitializeComponent(); + DouyinApi.douyinApiAction = DouyinApiAction; + } + + private void DouyinApiAction(DouyinApi api) + { + try + { + api.IsQualifiedAction = IsQualifiedAction; + this.api = api; + api.webControl.Dock = DockStyle.None; + api.webControl.Location = new Point(0, 0); + api.webControl.Size = new Size(1920, 1080); + + this.Controls.Add(api.webControl);//添加要增加的控件 + } + catch (Exception ex) + { + } + } + + /// + /// 是否满足账号权限 + /// + /// + private void IsQualifiedAction(DouyinLoginType type, DouyinApi api) + { + try + { + switch (type) + { + case DouyinLoginType.权限不足: + { + EventClient.OnEvent("", $"{api.Member.username}({api.Member.usernick}) 权限未开通,请开通后重试!"); + CpsClient.Members.Remove(api.Member); + + + BaseForm.ShowErrorAutoClose($@"该账号未开通商品分享功能,请开通后重试 + +注:开通电商权限,需要同时满足以下4个条件 +①、账号实名认证 +②、个人主页视频数(公开且审核通过)≥ 10 条 +③、账号粉丝量(绑定第三方粉丝量不计数)≥ 1000 +④、商品分享保证金 ¥500立即充值", 120000); + } + SelfClose(true); + break; + case DouyinLoginType.登录过期: + { + EventClient.OnEvent("", $"抖音离线:{api.Member.username}({api.Member.usernick})"); + CpsClient.Members.Remove(api.Member); + SelfClose(true); + } + break; + case DouyinLoginType.登录成功: + case DouyinLoginType.新号登录成功: + { + SelfClose(false); + } + break; + case DouyinLoginType.删除登录账号: + { + EventClient.OnEvent("", $"手动删除抖音账号:{api.Member.username}({api.Member.usernick})"); + SelfClose(true); + } + break; + case DouyinLoginType.移除登录窗口: + { + SelfClose(true); + } + break; + default: + break; + } + this.Invoke(new Action(() => + { + CpsClient.RefreshCps(); + EventClient.OnEvent(null, MethodType.刷新联盟); + })); + } + catch (Exception ex) + { + + } + } + + /// + /// 是否关闭窗体 + /// + bool IsClose = false; + + private void SelfClose(bool isClose = false) + { + this.Invoke(new Action(() => + { + IsClose = isClose; + this.Close(); + })); + } + + private void douyin_form_login1_FormClosing(object sender, FormClosingEventArgs e) + { + if (api.isLoad && !IsClose) + { + //抖音隐藏 + if (ApiClient.Setting.SystemConfig.hidedy) + this.Hide(); + e.Cancel = true; + } + } + + private void douyin_form_login1_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/类库/Api.Framework/Cps/douyin_form_login1.resx b/类库/Api.Framework/Cps/douyin_form_login1.resx new file mode 100644 index 0000000..85f21e4 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login1.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_login_.Designer.cs b/类库/Api.Framework/Cps/douyin_form_login_.Designer.cs new file mode 100644 index 0000000..c11f306 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login_.Designer.cs @@ -0,0 +1,70 @@ +namespace Api.Framework.Cps +{ + partial class douyin_form_login_ + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.webControl1 = new EO.WinForm.WebControl(); + this.webView1 = new EO.WebBrowser.WebView(); + this.SuspendLayout(); + // + // webControl1 + // + this.webControl1.BackColor = System.Drawing.Color.White; + this.webControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webControl1.Location = new System.Drawing.Point(0, 0); + this.webControl1.Name = "webControl1"; + this.webControl1.Size = new System.Drawing.Size(601, 445); + this.webControl1.TabIndex = 1; + this.webControl1.Text = "webControl1"; + this.webControl1.WebView = this.webView1; + // + // webView1 + // + this.webView1.InputMsgFilter = null; + this.webView1.ObjectForScripting = null; + this.webView1.Title = null; + // + // douyin_form_login_ + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(601, 445); + this.Controls.Add(this.webControl1); + this.Name = "douyin_form_login_"; + this.Text = "登录抖音"; + this.Load += new System.EventHandler(this.douyin_form_login__Load); + this.ResumeLayout(false); + + } + + #endregion + + private EO.WinForm.WebControl webControl1; + private EO.WebBrowser.WebView webView1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_login_.cs b/类库/Api.Framework/Cps/douyin_form_login_.cs new file mode 100644 index 0000000..ceebd1b --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login_.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using EO.Base; +using EO.WebBrowser; +using Api.Framework.Model; +using Api.Framework.Enums; +using CsharpHttpHelper; + +namespace Api.Framework.Cps +{ + public partial class douyin_form_login_ : BaseForm + { + public douyin_form_login_() + { + InitializeComponent(); + } + + private const string loginUrl = "http://cps.api.52cmg.cn/api/douyin.asmx/login"; + + private void douyin_form_login__Load(object sender, EventArgs e) + { + try + { + var accountName = Guid.NewGuid().ToString("N"); + EO.WebEngine.Engine engine = EO.WebEngine.Engine.Create(accountName); + engine.Options.CachePath = HttpExtend.MapPath($"Cache\\Cookies\\{accountName}"); + webControl1.WebView.Engine = engine; + EO.Base.Runtime.Exception += Runtime_Exception; + + webControl1.WebView.LoadUrl(loginUrl); + //webControl1.WebView.TitleChanged += WebView_TitleChanged; + webControl1.WebView.LoadCompleted += WebView_LoadCompleted; + webControl1.WebView.NewWindow += WebView_NewWindow; + } + catch (Exception ex) + { + ShowErrorAutoClose(ex); + } + } + + private void WebView_NewWindow(object sender, NewWindowEventArgs e) + { + webControl1.WebView.LoadUrl(e.TargetUrl); + } + + internal fl_cps_member member { get; private set; } + + + private string GuidToken = Guid.NewGuid().ToString(); + + private void WebView_LoadCompleted(object sender, LoadCompletedEventArgs e) + { + Console.WriteLine(e.Url); + if (e.Url.StartsWith("http://cps.api.52cmg.cn/api/douyin.asmx/login_result")) + { + /* + { + "ok": true, + "message": { + "id": 1, + "access_token": "c9d55a33-f110-4e22-9c48-356fbc3eff15", + "expires_in": 592775, + "refresh_token": "53e3c143-758a-47f9-9c7b-088ccee6ada3", + "app_id": "7066380295942964749", + "scope": null, + "shop_id": "0", + "shop_name": "" + }, + "time": 458, + "method": "login_result", + "req": "20220223155239743" + } + */ + var html = webControl1.WebView.GetText(); + + var json = CsharpHttpHelper.HttpExtend.JsonToDictionary(html); + + if (json == null) + { + EventClient.OnEvent(this, "登陆抖音失败:" + html); + ShowError("登录失败,请查看页面具体错误!"); + } + else if (json["ok"].ToString().ToLower() == "false") ShowError(json["message"].ToString()); + else + { + json = json["message"] as Dictionary; + member = CpsClient.Members.FirstOrDefault(f => f.username == json["app_id"].ToString() && f.cpstype == CpsType.抖音联盟); + if (member == null) + { + member = new fl_cps_member() { username = json["app_id"].ToString(), cpstype = CpsType.抖音联盟 }; + CpsClient.Members.Add(member); + } + + member.logintime = DateTime.Now; + member.is_valid = true; + this.Close(); + } + } + } + + private void Runtime_Exception(object sender, ExceptionEventArgs e) + { + e.ShowExceptionDialog = false; + } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_login_.resx b/类库/Api.Framework/Cps/douyin_form_login_.resx new file mode 100644 index 0000000..cb4cc33 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_login_.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_select_tgw.Designer.cs b/类库/Api.Framework/Cps/douyin_form_select_tgw.Designer.cs new file mode 100644 index 0000000..97b9ad8 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_select_tgw.Designer.cs @@ -0,0 +1,275 @@ +namespace Api.Framework.Cps +{ + partial class douyin_form_select_tgw + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(douyin_form_select_tgw)); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(414, 510); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(137, 35); + this.simpleButton3.TabIndex = 12; + this.simpleButton3.Text = "放弃修改"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(221, 508); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(137, 35); + this.simpleButton2.TabIndex = 11; + this.simpleButton2.Text = "确认选中行"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.label6); + this.groupControl2.Controls.Add(this.pageControl1); + this.groupControl2.Controls.Add(this.gridControl1); + this.groupControl2.Location = new System.Drawing.Point(7, 113); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(758, 389); + this.groupControl2.TabIndex = 10; + this.groupControl2.Text = "推广位选择"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(17, 124); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(716, 33); + this.label6.TabIndex = 3; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(5, 348); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(748, 36); + this.pageControl1.TabIndex = 2; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(5, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(748, 318); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.Caption = "Pid"; + this.gridColumn2.FieldName = "p_id"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // gridColumn3 + // + this.gridColumn3.Caption = "创建时间"; + this.gridColumn3.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn3.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn3.FieldName = "create_time"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.ReadOnly = true; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Location = new System.Drawing.Point(7, 9); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(758, 86); + this.groupControl1.TabIndex = 9; + this.groupControl1.Text = "账号选择"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(605, 39); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(94, 23); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "创建推广位"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(406, 41); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(174, 20); + this.textEdit1.TabIndex = 7; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(348, 43); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 6; + this.labelControl2.Text = "新建名称:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(52, 44); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 5; + this.labelControl1.Text = "操作账号:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(110, 41); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(202, 20); + this.comboBoxEdit1.TabIndex = 4; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // douyin_form_select_tgw + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(773, 555); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.groupControl1); + this.Name = "douyin_form_select_tgw"; + this.Text = "选择抖音联盟"; + this.Load += new System.EventHandler(this.douyin_form_select_tgw_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.GroupControl groupControl2; + private System.Windows.Forms.Label label6; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_select_tgw.cs b/类库/Api.Framework/Cps/douyin_form_select_tgw.cs new file mode 100644 index 0000000..5b43d1c --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_select_tgw.cs @@ -0,0 +1,164 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Api.Framework.Enums; +using Api.Framework.Model; +using System.Collections; + +namespace Api.Framework.Cps +{ + /// + /// 抖音账号选择(别的平台是cps) + /// + internal partial class douyin_form_select_tgw : BaseForm + { + internal class view_douyin_form_select_tgw + { + public string name { get; set; } + public string p_id { get; set; } + public DateTime create_time { get; set; } + } + + internal douyin_form_select_tgw() + { + InitializeComponent(); + } + + private void douyin_form_select_tgw_Load(object sender, EventArgs e) + { + ShowView(); + } + + private void ShowView() + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.抖音联盟).ToList(); + if (members == null || members.Count == 0) + { + ShowError("对不起,当前未检测到您登录的抖音账号!"); + this.Close(); + return; + } + this.comboBoxEdit1.Properties.Items.AddRange(members); + + this.pageControl1.Bind(delegate (int index, int page) + { + try + { + var member = this.comboBoxEdit1.EditValue as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateDouyinRequest(member); + var result = api.FindPidList(index, page); + + this.label6.Visible = false; + ArrayList _list = new ArrayList(); + + if (result != null) + { + if (result.pids != null) + { + foreach (var item in result.pids) + { + _list.Add(new view_douyin_form_select_tgw { name = item.site_name, p_id = item.pid, create_time = CsharpHttpHelper.HttpExtend.GetDateTime(item.create_time.ToString()) }); + } + } + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = int.Parse(result.total.ToString()) }; + } + catch (Exception ex) + { + this.UpdateUI(() => + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + }); + } + return null; + }, this.gridControl1, 100, true, true); + + this.comboBoxEdit1.SelectedIndex = 0; + + } + catch (Exception ex) + { + this.UpdateUI(() => + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + }); + ShowError(ex); + } + } + + /// + /// 单个推广位 + /// + internal Tuiguangwei Tuiguangwei { get; private set; } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + var select = this.gridView1.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView1.GetRow(select[0]) as view_douyin_form_select_tgw; + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + Tuiguangwei = new Tuiguangwei() + { + Member = member, + Name = row.name, + Pid = row.p_id + }; + this.Close(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + Tuiguangwei = null; + this.Close(); + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(this.textEdit1.Text)) throw new Exception("推广位名称不能留空!"); + if (XtraMessageBox.Show($"您确定要创建名为【{this.textEdit1.Text}】的推广位吗?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var member = this.comboBoxEdit1.EditValue as fl_cps_member; + //var member = CpsClient.Members.FirstOrDefault(f => f.username == Regex.Match(this.comboBoxEdit1.Text, @"(\d+)").Groups[1].Value); + var api = CpsClient.CreateDouyinRequest(member); + var flag = api.CreateKolPid(1, this.textEdit1.Text); + + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_form_select_tgw.resx b/类库/Api.Framework/Cps/douyin_form_select_tgw.resx new file mode 100644 index 0000000..f71e8f3 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_form_select_tgw.resx @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_verify.Designer.cs b/类库/Api.Framework/Cps/douyin_verify.Designer.cs new file mode 100644 index 0000000..98d070a --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_verify.Designer.cs @@ -0,0 +1,72 @@ +namespace Api.Framework.Cps +{ + partial class douyin_verify + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.webControl1 = new EO.WinForm.WebControl(); + this.webView1 = new EO.WebBrowser.WebView(); + this.SuspendLayout(); + // + // webControl1 + // + this.webControl1.BackColor = System.Drawing.Color.White; + this.webControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webControl1.Location = new System.Drawing.Point(0, 0); + this.webControl1.Name = "webControl1"; + this.webControl1.Size = new System.Drawing.Size(800, 450); + this.webControl1.TabIndex = 0; + this.webControl1.Text = "webControl1"; + this.webControl1.WebView = this.webView1; + // + // webView1 + // + this.webView1.InputMsgFilter = null; + this.webView1.ObjectForScripting = null; + this.webView1.Title = null; + this.webView1.Url = "https://www.baidu.com"; + // + // douyin_verify + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.webControl1); + this.Name = "douyin_verify"; + this.Text = "抖音验证码 - (请勿手动关闭窗口,验证成功会自动关闭)"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.douyin_verify_FormClosing); + this.Load += new System.EventHandler(this.douyin_verify_Load); + this.ResumeLayout(false); + + } + + #endregion + + private EO.WinForm.WebControl webControl1; + private EO.WebBrowser.WebView webView1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/douyin_verify.cs b/类库/Api.Framework/Cps/douyin_verify.cs new file mode 100644 index 0000000..5ca2af6 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_verify.cs @@ -0,0 +1,218 @@ +using Api.Framework.Model; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using EO.Base; +using EO.WebBrowser; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + public partial class douyin_verify : BaseForm + { + private string username; + private fl_cps_member cps; + public douyin_verify(string username) + { + InitializeComponent(); + this.username = username; + } + + private void douyin_verify_Load(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(username)) + this.Close(); + + cps = CpsClient.Members.FirstOrDefault(f => f.username == username && f.cpstype == Enums.CpsType.抖音联盟); + if (cps == null) + this.Close(); + + var accountName = Guid.NewGuid().ToString("N"); + EO.WebEngine.Engine engine = EO.WebEngine.Engine.Create(accountName); + engine.Options.CachePath = HttpExtend.MapPath($"Cache\\Cookies\\{accountName}"); + webView1.Engine = engine; + EO.Base.Runtime.Exception += Runtime_Exception; + //webControl1.WebView.TitleChanged += WebView_TitleChanged; + webView1.LoadCompleted += WebView_LoadCompleted; + webView1.NewWindow += WebView_NewWindow; + + var sHandler = new SampleHandler(); + sHandler.JsonAction += SHandler_JsonAction; + webControl1.WebView.RegisterResourceHandler(sHandler);//注册自定义资源处理程序 + } + catch (Exception ex) + { + + } + } + + private void SHandler_JsonAction(string cookies, string arg2, string arg3, string arg4) + { + try + { + if (!string.IsNullOrWhiteSpace(cookies)) + { + cps.cookies = cookies; + + var api = CpsClient.CreateDouyinRequest(cps); + + var end_time = DateTime.Now; + var start_time = end_time.AddHours(-1); + try + { + var order = api.DownOrder(start_time, end_time, 1, Enums.DouyinQueryOrderType.付款订单); + + cps.online = true; + ApiClient.GetSession().SaveOrUpdate(cps); + + EventClient.OnEvent("", "抖音验证成功"); + //this.Invoke(new System.Action(() => + //{ + this.DialogResult = DialogResult.OK; + //})); + } + catch (Exception ex) + { + } + } + } + catch (Exception ex) + { + } + } + + private void WebView_LoadCompleted(object sender, LoadCompletedEventArgs e) + { + try + { + var ck = webControl1.WebView.Engine.CookieManager.GetCookies().ToString(); + var ck1 = Regex.Replace(ck, "path=/", "").Replace("\r\n", ""); + //Console.WriteLine("------- " + e.Url); + if (e.Url.Contains("www.baidu.com")) + { + var cookice = cps.cookies; + + var keyValue = cookice.Split(';'); + + for (int i = 0; i < keyValue.Length; i++) + { + var data = keyValue[i].Split('='); + if (data.Length == 2) + { + webControl1.WebView.Engine.CookieManager.SetCookie("https://buyin.jinritemai.com/dashboard/dataCenter/order", new EO.WebEngine.Cookie(data[0].Trim(), data[1].Trim())); + } + } + + webView1.LoadUrl("https://buyin.jinritemai.com/dashboard"); + } + else if (e.Url == "https://buyin.jinritemai.com/dashboard") + { + webView1.LoadUrl("https://buyin.jinritemai.com/dashboard/dataCenter/order"); + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + + private void Runtime_Exception(object sender, ExceptionEventArgs e) + { + e.ShowExceptionDialog = false; + } + + private void WebView_NewWindow(object sender, NewWindowEventArgs e) + { + webView1.LoadUrl(e.TargetUrl); + } + + #region 自定义响应Response 20210321 + + internal class SampleHandler : ResourceHandler + { + private static int num = 1; + private static bool IsRun = false; + + public event Action JsonAction; + + //如果使用此方式,将完全转移嫁接,包括真实请求,需要自己模拟请求, + public const string SampleUrlPrefix = "sample://"; + + public const string EmbeddedPageUrl = "sample://embedded_page"; + + //此方法判断是否自定义处理响应 + public override bool Match(Request request) + { + var cookies = Regex.Replace(request.Cookies.ToString(), "path=/", "").Replace("\r\n", ""); + Debug.WriteLine("*** " + request.Url); + + //https://verify.snssdk.com/captcha/get?lang=zh&app_name=&h5_sdk_version=2.26.2&sdk_version=3.5.2&iid=0&did=0&device_id=0&ch=web_text&aid=2631&os_type=2&mode=&tmp=1646209585986&platform=pc&webdriver=undefined&fp=verify_l09aojjx_ZYrkkHpy_VjiQ_4DtQ_BP9J_prQIB7hNThGm&type=verify&detail=329dZ9*0HUUTxcZ*3PeYAZmmzO31ayBNAH2aY4YrPAzwG9HvIR0aEkUBjvCZYcIs1rPMjWv57a9yuKWP4Iq*dMdU6pKa8ddOK4hwQKsgI675G7Z0gr2bfMX4jmFVgvn05uvQSOBIXZxI3F7C3kht4ftX5SSQfaCapLMMM4-ToqtjEuBiYTM31yZefCcUxaoxur*eXATelW0noYZvMt7n-J8q2i-Uw3b8gtwHo4Y0EydfCX-IcJ8yqfqCsVdh50Xvcgs-jn15g-obBVNda3Z7x6n5olZlO3pV0yXHdp5B2IZxofobV-fIC9P*x0HG6WVXrsJns3YY33tG12irfIAXOWpmBbs96LmUAuLueEsB60ocppfLzbPz3iBktHFIKT4xcTogaL6TV9CDF2kDE0vO1Gg6*3f7ViuSiV10vySAsjXBfpI.&server_sdk_env=%7B%22idc%22:%22lf%22,%22region%22:%22CN%22,%22server_type%22:%22business%22%7D&subtype=slide&challenge_code=1105&os_name=windows&h5_check_version=3.5.2 + + if (request.Url.Contains("buyin.jinritemai.com/api/author/order/details")) + { + if (num >= 2) + { + JsonAction.Invoke(cookies, "", "", ""); + } + num++; + } + else if (request.Url.Contains("verify.snssdk.com/captcha/get?")) + { + //return true; + } + else + { + + } + return false; + } + + //如果自定义响应,则在这里处理请求,并返回要显示的信息 + public override void ProcessRequest(Request request, EO.WebBrowser.Response response) + { + var cookies = Regex.Replace(request.Cookies.ToString(), "path=/", "").Replace("\r\n", ""); + + + /* + {"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":17,"host":"","id":"f2f49d6eb42ff02d7542bcec6044104fcd2ef111","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7118a15982b44c6c8e6d1980bf948dcf~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b4895857a8004988a814223f0fa42d70~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7118a15982b44c6c8e6d1980bf948dcf~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7118a15982b44c6c8e6d1980bf948dcf~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b4895857a8004988a814223f0fa42d70~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b4895857a8004988a814223f0fa42d70~tplv-188rlo5p4y-1.png"],"tip_y":41},"region":"","version":2},"message":"验证通过"} + */ + var http = new HttpHelper(); + var item = http.GetItem(request.Url, cookies); + var result = http.GetHtml(item); + + + base.ProcessRequest(request, response); + } + } + #endregion + + private void douyin_verify_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (!cps.online) + { + if (XtraMessageBox.Show("当前未完成验证,是否取消验证?", "温馨提示", MessageBoxButtons.YesNo) == DialogResult.No) + e.Cancel = true; + else + EventClient.OnEvent("", "放弃抖音手动验证"); + } + } + catch (Exception ex) + { } + } + } +} diff --git a/类库/Api.Framework/Cps/douyin_verify.resx b/类库/Api.Framework/Cps/douyin_verify.resx new file mode 100644 index 0000000..3882fa5 --- /dev/null +++ b/类库/Api.Framework/Cps/douyin_verify.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 52 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/jingdong_form_login.Designer.cs b/类库/Api.Framework/Cps/jingdong_form_login.Designer.cs new file mode 100644 index 0000000..cc8de7c --- /dev/null +++ b/类库/Api.Framework/Cps/jingdong_form_login.Designer.cs @@ -0,0 +1,112 @@ +namespace Api.Framework.Cps +{ + partial class jingdong_form_login + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(jingdong_form_login)); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit_UnionId = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit_Key = new DevExpress.XtraEditors.MemoEdit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit_UnionId.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit_Key.Properties)).BeginInit(); + this.SuspendLayout(); + // + // simpleButton2 + // + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(161, 173); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(118, 41); + this.simpleButton2.TabIndex = 2; + this.simpleButton2.Text = "验证结果"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // textEdit_UnionId + // + this.textEdit_UnionId.EditValue = ""; + this.textEdit_UnionId.Location = new System.Drawing.Point(114, 47); + this.textEdit_UnionId.Name = "textEdit_UnionId"; + this.textEdit_UnionId.Size = new System.Drawing.Size(272, 20); + this.textEdit_UnionId.TabIndex = 9; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(60, 50); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(48, 14); + this.labelControl2.TabIndex = 8; + this.labelControl2.Text = "联盟ID:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(56, 87); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(56, 14); + this.labelControl1.TabIndex = 10; + this.labelControl1.Text = "授权Key:"; + // + // memoEdit_Key + // + this.memoEdit_Key.EditValue = ""; + this.memoEdit_Key.Location = new System.Drawing.Point(114, 86); + this.memoEdit_Key.Name = "memoEdit_Key"; + this.memoEdit_Key.Size = new System.Drawing.Size(272, 71); + this.memoEdit_Key.TabIndex = 11; + // + // jingdong_form_login + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(444, 244); + this.Controls.Add(this.memoEdit_Key); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.textEdit_UnionId); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.simpleButton2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "jingdong_form_login"; + this.Text = "登录京东联盟"; + ((System.ComponentModel.ISupportInitialize)(this.textEdit_UnionId.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit_Key.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.TextEdit textEdit_UnionId; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.MemoEdit memoEdit_Key; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/jingdong_form_login.cs b/类库/Api.Framework/Cps/jingdong_form_login.cs new file mode 100644 index 0000000..23fe285 --- /dev/null +++ b/类库/Api.Framework/Cps/jingdong_form_login.cs @@ -0,0 +1,72 @@ +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + /// + /// 京东登录 + /// + internal partial class jingdong_form_login : BaseForm + { + internal jingdong_form_login() + { + InitializeComponent(); + } + + internal fl_cps_member member { get; private set; } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + var cps = new fl_cps_member() { cpstype = CpsType.京东联盟, logintime = DateTime.Now, online = true, usernick = textEdit_UnionId.Text.Trim(), username = memoEdit_Key.Text.Trim() }; + var api = new JingdongApi(cps); + //这里请求推广位来测试是否与京东联盟相通 + var result = api.SendJingdong("jd.union.open.position.query", new { positionReq = new { unionType = 1, pageSize = 1, pageIndex = 1, unionId = textEdit_UnionId.Text.Trim(), key = memoEdit_Key.Text.Trim() } }); + + if (result.ContainsKey("code") && result["code"].ToString() == "200") + { + member = CpsClient.Members.FirstOrDefault(f => f.usernick == textEdit_UnionId.Text.Trim() && f.cpstype == CpsType.京东联盟); + if (member != null) + { + member.online = true; + member.username = memoEdit_Key.Text.Trim(); + member.logintime = DateTime.Now; + var session = ApiClient.GetSession(); + session.ExcuteSQL($"update fl_adzone_info set adzone_pid_cps_name = @username where adzone_pid like '{textEdit_UnionId.Text.Trim()}%'", new { username = member.username }); + } + else + { + CpsClient.Members.Add(cps); + member = cps; + } + EventClient.OnEvent(this, MethodType.刷新联盟); + this.Close(); + } + else + ShowError($"登录失败,{result["message"].ToString()}"); + } + catch (Exception ex) + { + ShowError($@"登录失败 +可能原因如下: +1、授权key或联盟ID错误 +2、授权key新生成,请10分钟后重试(因京东有延迟,请耐心等待) +3、本地时间和服务器时间不一致,可尝试同步时间以后重试"); + } + } + + } +} diff --git a/类库/Api.Framework/Cps/jingdong_form_login.resx b/类库/Api.Framework/Cps/jingdong_form_login.resx new file mode 100644 index 0000000..c0dbac8 --- /dev/null +++ b/类库/Api.Framework/Cps/jingdong_form_login.resx @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/jingdong_form_select_tgw.Designer.cs b/类库/Api.Framework/Cps/jingdong_form_select_tgw.Designer.cs new file mode 100644 index 0000000..098d439 --- /dev/null +++ b/类库/Api.Framework/Cps/jingdong_form_select_tgw.Designer.cs @@ -0,0 +1,261 @@ +namespace Api.Framework.Cps +{ + partial class jingdong_form_select_tgw + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(jingdong_form_select_tgw)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Location = new System.Drawing.Point(12, 12); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(755, 88); + this.groupControl1.TabIndex = 6; + this.groupControl1.Text = "账号选择"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(605, 39); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(94, 23); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "创建推广位"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(406, 41); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(174, 20); + this.textEdit1.TabIndex = 7; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(348, 43); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 6; + this.labelControl2.Text = "新建名称:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(52, 44); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 5; + this.labelControl1.Text = "操作账号:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(110, 41); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(202, 20); + this.comboBoxEdit1.TabIndex = 4; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.label6); + this.groupControl2.Controls.Add(this.pageControl1); + this.groupControl2.Controls.Add(this.gridControl1); + this.groupControl2.Location = new System.Drawing.Point(12, 106); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(755, 460); + this.groupControl2.TabIndex = 7; + this.groupControl2.Text = "推广位选择"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(17, 124); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(716, 33); + this.label6.TabIndex = 3; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(5, 419); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(745, 36); + this.pageControl1.TabIndex = 2; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(5, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(745, 389); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.Caption = "Pid"; + this.gridColumn2.FieldName = "p_id"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(408, 589); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(137, 35); + this.simpleButton3.TabIndex = 10; + this.simpleButton3.Text = "放弃修改"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // simpleButton2 + // + this.simpleButton2.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(201, 590); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(152, 32); + this.simpleButton2.TabIndex = 9; + this.simpleButton2.Text = "确认选中行"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // jingdong_form_select_tgw + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(779, 636); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.simpleButton3); + this.Name = "jingdong_form_select_tgw"; + this.Text = "设置京东推广位"; + this.Load += new System.EventHandler(this.jingdong_form_select_tgw_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private System.Windows.Forms.Label label6; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/jingdong_form_select_tgw.cs b/类库/Api.Framework/Cps/jingdong_form_select_tgw.cs new file mode 100644 index 0000000..45ec451 --- /dev/null +++ b/类库/Api.Framework/Cps/jingdong_form_select_tgw.cs @@ -0,0 +1,200 @@ +using Api.Framework.Enums; +using Api.Framework.Model; +using CsharpHttpHelper; +using DevExpress.XtraEditors; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + /// + /// 京东推广位选择 + /// + public partial class jingdong_form_select_tgw : BaseForm + { + internal class view_jingdong_form_select_tgw + { + public string name { get; set; } + public string p_id { get; set; } + public DateTime create_time { get; set; } + } + + internal jingdong_form_select_tgw() + { + InitializeComponent(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(this.textEdit1.Text)) throw new Exception("推广位名称不能留空!"); + string pattern = "[\u4e00-\u9fbb]"; + if (Regex.IsMatch(this.textEdit1.Text, pattern)) throw new Exception("推广位名称不能包含中文!"); + + if (XtraMessageBox.Show($"您确定要创建名为【{this.textEdit1.Text}】的推广位吗?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + //var member = CpsClient.Members.FirstOrDefault(f => f.username == Regex.Match(this.comboBoxEdit1.Text, @"(\d+)").Groups[1].Value); + var api = CpsClient.CreateJingdongRequest(member); + api.SendJingdong("jd.union.open.position.create", new + { + positionReq = new + { + spaceNameList = new string[] { this.textEdit1.Text }, + unionType = 1, + type = 4, + unionId = member.usernick, + key = member.username + } + }); + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void jingdong_form_select_tgw_Load(object sender, EventArgs e) + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.京东联盟).ToList(); + if (members == null || members.Count == 0) + { + ShowError("对不起,当前未检测到您登录的京东账号!"); + this.Close(); + return; + } + + this.comboBoxEdit1.Properties.Items.AddRange(members); + + this.pageControl1.Bind(delegate (int index, int page) + { + try + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateJingdongRequest(member); + var list = new List(); + FindTGW(api, 1, 1, member.usernick, member.username, list);//以前的推广位(现在已经无法创建) + FindTGW(api, 3, 1, member.usernick, member.username, list);//开放推广位 + var _list = list.Skip((index - 1) * page).Take(page).ToList(); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = list.Count }; + + } + catch (Exception ex) + { + this.UpdateUI(() => + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + }); + } + return null; + }, this.gridControl1, 100, true, true); + + this.comboBoxEdit1.SelectedIndex = 0; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 单个推广位 + /// + internal Tuiguangwei Tuiguangwei { get; private set; } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + var select = this.gridView1.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView1.GetRow(select[0]) as view_jingdong_form_select_tgw; + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + Tuiguangwei = new Tuiguangwei() + { + Member = member, + Name = row.name, + Pid = row.p_id + }; + this.Close(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 获取所有的推广位 + /// + /// + /// + /// + /// + /// + private void FindTGW(JingdongApi api, int unionType, int page, string usernick, string username, List list) + { + try + { + var result = api.SendJingdong("jd.union.open.position.query", new { positionReq = new { unionType = unionType, pageSize = 100, pageIndex = page, unionId = usernick, key = username } }); + if (result.ContainsKey("data")) + { + var data = result["data"] as Dictionary; + if (data.ContainsKey("result")) + { + var result2 = data["result"] as ArrayList; + this.label6.Visible = false; + foreach (Dictionary item in result2) + { + list.Add(new view_jingdong_form_select_tgw { name = item["spaceName"].ToString(), p_id = $"{usernick}_{(item.ContainsKey("siteId") ? item["siteId"].ToString() : "0")}_{item["id"].ToString()}" }); + } + } + if (data.ContainsKey("total")) + { + var total = long.Parse(data["total"].ToString()); + var pageNo = int.Parse(data["pageNo"].ToString()); + var pageSize = int.Parse(data["pageSize"].ToString()); + if (total > (pageNo * pageSize)) + { + page++; + FindTGW(api, unionType, page, usernick, username, list); + } + } + } + } + catch (Exception ex) + { } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + Tuiguangwei = null; + this.Close(); + } + } +} diff --git a/类库/Api.Framework/Cps/jingdong_form_select_tgw.resx b/类库/Api.Framework/Cps/jingdong_form_select_tgw.resx new file mode 100644 index 0000000..05c9965 --- /dev/null +++ b/类库/Api.Framework/Cps/jingdong_form_select_tgw.resx @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + 56 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/kuaishou_form_login.Designer.cs b/类库/Api.Framework/Cps/kuaishou_form_login.Designer.cs new file mode 100644 index 0000000..498249b --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_login.Designer.cs @@ -0,0 +1,170 @@ +namespace Api.Framework.Cps +{ + partial class kuaishou_form_login + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(kuaishou_form_login)); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.webControl1 = new EO.WinForm.WebControl(); + this.webView1 = new EO.WebBrowser.WebView(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(1245, 589); + this.xtraTabControl1.TabIndex = 1; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.webControl1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(1243, 563); + this.xtraTabPage1.Text = " 扫 码 登 录 "; + // + // webControl1 + // + this.webControl1.BackColor = System.Drawing.Color.White; + this.webControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webControl1.Location = new System.Drawing.Point(0, 0); + this.webControl1.Name = "webControl1"; + this.webControl1.Size = new System.Drawing.Size(1243, 563); + this.webControl1.TabIndex = 0; + this.webControl1.Text = "webControl1"; + this.webControl1.WebView = this.webView1; + // + // webView1 + // + this.webView1.InputMsgFilter = null; + this.webView1.ObjectForScripting = null; + this.webView1.Title = null; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.groupBox1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(1243, 563); + this.xtraTabPage2.Text = " 网页登录授权 "; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.hyperlinkLabelControl1); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBox1.Location = new System.Drawing.Point(0, 0); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(1243, 563); + this.groupBox1.TabIndex = 2; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "请粘贴登录结果"; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.hyperlinkLabelControl1.Appearance.Options.UseFont = true; + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(317, 417); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(560, 17); + this.hyperlinkLabelControl1.TabIndex = 2; + this.hyperlinkLabelControl1.Text = "还未登录,请点击【复制登录地址】,粘贴到浏览器登录,登录成功后将数据复制到本框中"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // textBox1 + // + this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox1.Location = new System.Drawing.Point(3, 18); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox1.Size = new System.Drawing.Size(1237, 455); + this.textBox1.TabIndex = 0; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(234, 497); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(755, 41); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "验证Json有效性"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // kuaishou_form_login + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1245, 589); + this.Controls.Add(this.xtraTabControl1); + this.Name = "kuaishou_form_login"; + this.Text = "快手授权登录"; + this.Load += new System.EventHandler(this.kuaishou_form_login_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private EO.WinForm.WebControl webControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private EO.WebBrowser.WebView webView1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/kuaishou_form_login.cs b/类库/Api.Framework/Cps/kuaishou_form_login.cs new file mode 100644 index 0000000..7191dc5 --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_login.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework.Enums; +using Api.Framework.Model; +using CsharpHttpHelper; +using EO.WebBrowser; +using Newtonsoft.Json.Linq; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + public partial class kuaishou_form_login : BaseForm + { + public kuaishou_form_login() + { + InitializeComponent(); + } + + internal fl_cps_member member { get; private set; } + + //private string url = "https://cps.api.52cmg.cn/api/kuaishou.asmx/login"; + private string url => $"{ApiClient.Setting.SystemConfig.cps_server_api}api/kuaishou.asmx/login"; + + private void kuaishou_form_login_Load(object sender, EventArgs e) + { + var accountName = Guid.NewGuid().ToString("N"); + EO.WebEngine.Engine engine = EO.WebEngine.Engine.Create(accountName); + engine.Options.CachePath = HttpExtend.MapPath($"Cache\\Cookies\\{accountName}"); + + webControl1.WebView.Engine = engine; + + EO.Base.Runtime.Exception += Runtime_Exception; + + //加载url + webControl1.WebView.LoadUrl(url); + webControl1.WebView.LoadCompleted += WebView_LoadCompleted; + webControl1.WebView.NewWindow += WebView_NewWindow; + //webControl.WebView.UrlChanged += WebView_UrlChanged; + //webControl.WebView.AfterReceiveHeaders += WebView_AfterReceiveHeaders; + //var sHandler = new SNResourceHandler(); + //sHandler.JsonAction += SHandler_JsonAction; + //webControl1.WebView.RegisterResourceHandler(sHandler);//注册自定义资源处理程序 + + } + + private void Runtime_Exception(object sender, EO.Base.ExceptionEventArgs e) + { + e.ShowExceptionDialog = false; ; + } + + private void WebView_NewWindow(object sender, NewWindowEventArgs e) + { + webControl1.WebView.LoadUrl(e.TargetUrl); + } + + private void WebView_LoadCompleted(object sender, LoadCompletedEventArgs e) + { + //Console.WriteLine($"### {e.Url}"); + if (Regex.IsMatch(e.Url, @"https://login\.kwaixiaodian\.com/\?redirect_url=", RegexOptions.IgnoreCase)) + { + webControl1.WebView.EvalScript("document.getElementsByClassName('account-type__item')[0].click()", false); + } + //else if (e.Url.StartsWith("http://cps.api.52cmg.cn/api/kuaishou.asmx/login_result")) + else if (e.Url.StartsWith($"{ApiClient.Setting.SystemConfig.cps_server_api}api/kuaishou.asmx/login_result")) + { + var text = webControl1.WebView.GetText(); + CheckJson(text); + } + } + + + private void CheckJson(string html, string cookie = "") + { + try + { + var json = JObject.Parse(html); + + if (json == null) + { + EventClient.OnEvent(this, "登陆快手失败:" + html); + ShowError("登录失败,请查看页面具体错误!"); + } + else if (json["ok"].ToString().ToLower() == "false") + ShowError(json["message"].ToString()); + else + { + var open_id = json["message"]?["open_id"]?.ToString(); + member = CpsClient.Members.FirstOrDefault(f => f.username == open_id && f.cpstype == CpsType.快手联盟); + if (member == null) + { + member = new fl_cps_member() { username = open_id, cpstype = CpsType.快手联盟 }; + CpsClient.Members.Add(member); + } + //member.usernick = "";//TODO 这里获取用户页面上输入的账号,这里开发者写固定了,发布的时候修改 + if (string.IsNullOrWhiteSpace(member.usernick)) + { + var wphUserNickForm = new kuaishou_form_usernick(); + if (wphUserNickForm.ShowDialog() == DialogResult.OK) + member.usernick = wphUserNickForm.usernick; + else + { + ShowError("未设置快手授权账号昵称,登录终止"); + return; + } + } + member.logintime = DateTime.Now; + member.cookies = cookie; + member.is_valid = true; + this.Close(); + } + } + catch (Exception ex) + { + throw ex; + } + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + Clipboard.SetDataObject(url); + BaseForm.ShowSuccessAutoClose("复制成功,请粘贴到任意电脑的浏览器!\r\n注意:如果页面显示空白,请换个浏览器,不要用系统自带的IE浏览器!!!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("Json数据不能为空"); + CheckJson(textBox1.Text); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + } +} diff --git a/类库/Api.Framework/Cps/kuaishou_form_login.resx b/类库/Api.Framework/Cps/kuaishou_form_login.resx new file mode 100644 index 0000000..592da5b --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_login.resx @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + 59 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/kuaishou_form_select_tgw.Designer.cs b/类库/Api.Framework/Cps/kuaishou_form_select_tgw.Designer.cs new file mode 100644 index 0000000..bee85d9 --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_select_tgw.Designer.cs @@ -0,0 +1,261 @@ +namespace Api.Framework.Cps +{ + partial class kuaishou_form_select_tgw + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(kuaishou_form_select_tgw)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Location = new System.Drawing.Point(12, 12); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(755, 88); + this.groupControl1.TabIndex = 11; + this.groupControl1.Text = "账号选择"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(605, 39); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(94, 23); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "创建推广位"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(406, 41); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(174, 20); + this.textEdit1.TabIndex = 7; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(348, 43); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 6; + this.labelControl2.Text = "新建名称:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(52, 44); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 5; + this.labelControl1.Text = "操作账号:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(110, 41); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(202, 20); + this.comboBoxEdit1.TabIndex = 4; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.label6); + this.groupControl2.Controls.Add(this.pageControl1); + this.groupControl2.Controls.Add(this.gridControl1); + this.groupControl2.Location = new System.Drawing.Point(12, 106); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(755, 460); + this.groupControl2.TabIndex = 12; + this.groupControl2.Text = "推广位选择"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(17, 124); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(716, 33); + this.label6.TabIndex = 3; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(5, 419); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(745, 36); + this.pageControl1.TabIndex = 2; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(5, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(745, 389); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.Caption = "Pid"; + this.gridColumn2.FieldName = "p_id"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // simpleButton2 + // + this.simpleButton2.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(201, 590); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(152, 32); + this.simpleButton2.TabIndex = 13; + this.simpleButton2.Text = "确认选中行"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(408, 589); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(137, 35); + this.simpleButton3.TabIndex = 14; + this.simpleButton3.Text = "放弃修改"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // kuaishou_form_select_tgw + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(779, 636); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.simpleButton3); + this.Name = "kuaishou_form_select_tgw"; + this.Text = "设置快手推广位"; + this.Load += new System.EventHandler(this.kuaishou_form_select_tgw_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private System.Windows.Forms.Label label6; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/kuaishou_form_select_tgw.cs b/类库/Api.Framework/Cps/kuaishou_form_select_tgw.cs new file mode 100644 index 0000000..36dea5e --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_select_tgw.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using Api.Framework.Enums; +using Api.Framework.Model; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + public partial class kuaishou_form_select_tgw : BaseForm + { + internal class view_kuaishou_form_select_tgw + { + public string name { get; set; } + public string p_id { get; set; } + public DateTime create_time { get; set; } + } + + public kuaishou_form_select_tgw() + { + InitializeComponent(); + } + + /// + /// 单个推广位 + /// + internal Tuiguangwei Tuiguangwei { get; private set; } + + private void kuaishou_form_select_tgw_Load(object sender, EventArgs e) + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.快手联盟).ToList(); + if (members == null || members.Count == 0) + { + ShowError("对不起,当前未检测到您登录的快手账号!"); + this.Close(); + return; + } + + this.comboBoxEdit1.Properties.Items.AddRange(members); + + this.pageControl1.Bind(delegate (int index, int page) + { + try + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateKuaiShouRequest(member); + var list = new List(); + + FindTGW(api, 1, 30, list); + var _list = list.Skip((index - 1) * page).Take(page).ToList(); + + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = list.Count }; + + } + catch (Exception ex) + { + this.UpdateUI(() => + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + }); + } + return null; + }, this.gridControl1, 100, true, true); + + this.comboBoxEdit1.SelectedIndex = 0; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void FindTGW(KuaiShouApi api, int page, int pageSize, List list) + { + + var tgws = api.GetMedias(page, pageSize, out int total); + if (total != 0) + { + this.label6.Visible = false; + foreach (var item in tgws) + { + list.Add(new view_kuaishou_form_select_tgw { name = item.promotionBitName, p_id = item.cpsPid }); + } + + if (total > (page * pageSize)) + { + page++; + FindTGW(api, page, pageSize, list); + } + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(this.textEdit1.Text)) throw new Exception("推广位名称不能留空!"); + //string pattern = "[\u4e00-\u9fbb]"; + //if (Regex.IsMatch(this.textEdit1.Text, pattern)) throw new Exception("推广位名称不能包含中文!"); + + if (XtraMessageBox.Show($"您确定要创建名为【{this.textEdit1.Text}】的推广位吗?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + var api = CpsClient.CreateKuaiShouRequest(member); + api.CreateMedia(this.textEdit1.Text); + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + var select = this.gridView1.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView1.GetRow(select[0]) as view_kuaishou_form_select_tgw; + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + Tuiguangwei = new Tuiguangwei() + { + Member = member, + Name = row.name, + Pid = row.p_id + }; + this.Close(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + Tuiguangwei = null; + this.Close(); + } + } +} diff --git a/类库/Api.Framework/Cps/kuaishou_form_select_tgw.resx b/类库/Api.Framework/Cps/kuaishou_form_select_tgw.resx new file mode 100644 index 0000000..62ec3f7 --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_select_tgw.resx @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC + + + + 59 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/kuaishou_form_usernick.Designer.cs b/类库/Api.Framework/Cps/kuaishou_form_usernick.Designer.cs new file mode 100644 index 0000000..4cb88b0 --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_usernick.Designer.cs @@ -0,0 +1,89 @@ +namespace Api.Framework.Cps +{ + partial class kuaishou_form_usernick + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ForeColor = System.Drawing.Color.Blue; + this.label1.Location = new System.Drawing.Point(70, 87); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(283, 14); + this.label1.TabIndex = 5; + this.label1.Text = "注:该昵称用于备注快手登录账号(方便用户记忆)"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(53, 38); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(234, 22); + this.textBox1.TabIndex = 4; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(304, 39); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 3; + this.button1.Text = "确定"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // kuaishou_form_usernick + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(423, 129); + this.Controls.Add(this.label1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.button1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "kuaishou_form_usernick"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "设置快手账号昵称"; + this.Load += new System.EventHandler(this.kuaishou_form_usernick_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/kuaishou_form_usernick.cs b/类库/Api.Framework/Cps/kuaishou_form_usernick.cs new file mode 100644 index 0000000..c0c859c --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_usernick.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + public partial class kuaishou_form_usernick : BaseForm + { + internal string usernick = string.Empty; + + internal kuaishou_form_usernick() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) + throw new Exception("昵称不能为空"); + else + { + usernick = textBox1.Text.Trim(); + this.DialogResult = DialogResult.OK; + } + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex); + } + } + + private void kuaishou_form_usernick_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/类库/Api.Framework/Cps/kuaishou_form_usernick.resx b/类库/Api.Framework/Cps/kuaishou_form_usernick.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Api.Framework/Cps/kuaishou_form_usernick.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/pinduoduo_form_login.Designer.cs b/类库/Api.Framework/Cps/pinduoduo_form_login.Designer.cs new file mode 100644 index 0000000..2497c6b --- /dev/null +++ b/类库/Api.Framework/Cps/pinduoduo_form_login.Designer.cs @@ -0,0 +1,212 @@ +namespace Api.Framework.Cps +{ + partial class pinduoduo_form_login + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(pinduoduo_form_login)); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(676, 462); + this.xtraTabControl1.TabIndex = 1; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.groupBox2); + this.xtraTabPage1.Controls.Add(this.button2); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(674, 436); + this.xtraTabPage1.Text = "本机浏览器登录"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Controls.Add(this.button1); + this.groupBox2.Location = new System.Drawing.Point(11, 152); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(652, 273); + this.groupBox2.TabIndex = 4; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "登录失败 - 解决方案如下(IE无法登录)"; + // + // label1 + // + this.label1.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.ForeColor = System.Drawing.Color.Red; + this.label1.Location = new System.Drawing.Point(113, 58); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(520, 95); + this.label1.TabIndex = 4; + this.label1.Text = "情况1:没有看到打开的网页!!\r\n\r\n情况2:打开后显示空白页面!!\r\n\r\n请点击下方按钮,粘贴到任意电脑的其他浏览器登录!\r\n"; + // + // button1 + // + this.button1.Font = new System.Drawing.Font("Tahoma", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.button1.Location = new System.Drawing.Point(117, 191); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(384, 43); + this.button1.TabIndex = 3; + this.button1.Text = "复制登录地址 --- ( 我要去别的浏览器登录 )"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.linkLabel1_LinkClicked); + // + // button2 + // + this.button2.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.button2.Location = new System.Drawing.Point(108, 52); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(425, 43); + this.button2.TabIndex = 3; + this.button2.Text = "打开本机【默认浏览器】登录"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.groupBox1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(674, 436); + this.xtraTabPage2.Text = "我在其他电脑登录了"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.hyperlinkLabelControl1); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBox1.Location = new System.Drawing.Point(0, 0); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(674, 436); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "请粘贴登录结果"; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.hyperlinkLabelControl1.Appearance.Options.UseFont = true; + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(165, 340); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(350, 17); + this.hyperlinkLabelControl1.TabIndex = 2; + this.hyperlinkLabelControl1.Text = "还未登录,请点击【复制登录地址】,粘贴到浏览器登录"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.linkLabel1_LinkClicked); + // + // textBox1 + // + this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox1.Location = new System.Drawing.Point(3, 18); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox1.Size = new System.Drawing.Size(668, 298); + this.textBox1.TabIndex = 0; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(266, 373); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(146, 41); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "验证Json有效性"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 2000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // pinduoduo_form_login + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(676, 462); + this.Controls.Add(this.xtraTabControl1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "pinduoduo_form_login"; + this.Text = "登录多多进宝"; + this.Load += new System.EventHandler(this.LoginPinduoduo_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private System.Windows.Forms.Timer timer1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/pinduoduo_form_login.cs b/类库/Api.Framework/Cps/pinduoduo_form_login.cs new file mode 100644 index 0000000..90a845e --- /dev/null +++ b/类库/Api.Framework/Cps/pinduoduo_form_login.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Api.Framework.Model; +using Api.Framework.Enums; +using System.Text.RegularExpressions; +using System.Runtime.InteropServices; +using Microsoft.Win32; +using CsharpHttpHelper; + +namespace Api.Framework.Cps +{ + /// + /// 拼多多登录 + /// + internal partial class pinduoduo_form_login : BaseForm + { + internal pinduoduo_form_login() + { + InitializeComponent(); + } + + private string LoginUrl = string.Empty; + private string GuidToken = Guid.NewGuid().ToString(); + private void LoginPinduoduo_Load(object sender, EventArgs e) + { + //通过系统默认浏览器登录 + try + { + var http = new HttpHelper(); + var item = new HttpItem() + { + //URL = "https://cps.api.52cmg.cn/api/pinduoduo.asmx/login", + URL = $"{ApiClient.Setting.SystemConfig.cps_server_api}api/pinduoduo.asmx/login", + Timeout = 5000, + ReadWriteTimeout = 5000, + Allowautoredirect = false + }; + var url = http.GetHtml(item).Header["Location"].ToString(); + var reg = Regex.Match(url, "state=([^&]+)"); + if (reg.Success) + { + GuidToken = reg.Groups[1].Value; + this.LoginUrl = url; + } + else throw new Exception("无法正常获取登录地址!"); + + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "加载失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + internal fl_cps_member member { get; private set; } + + private void CheckJson(string html, string cookie = "") + { + try + { + var json = CsharpHttpHelper.HttpExtend.JsonToDictionary(html); + + if (json == null) + { + EventClient.OnEvent(this, "登陆多多进宝失败:" + html); + ShowError("登录失败,请查看页面具体错误!"); + } + else if (json["ok"].ToString().ToLower() == "false") ShowError(json["message"].ToString()); + else + { + json = json["message"] as Dictionary; + member = CpsClient.Members.FirstOrDefault(f => f.username == json["owner_id"].ToString() && f.cpstype == CpsType.多多进宝); + if (member == null) + { + member = new fl_cps_member() { username = json["owner_id"].ToString(), cookies = cookie, cpstype = CpsType.多多进宝 }; + CpsClient.Members.Add(member); + } + + member.logintime = DateTime.Now; + member.cookies = cookie; + member.is_valid = true; + this.Close(); + } + } + catch (Exception ex) + { + throw ex; + } + } + + #region cookie + + private const int INTERNET_COOKIE_HTTPONLY = 0x00002000; + + + [DllImport("wininet.dll", SetLastError = true)] + static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, StringBuilder pchCookieData, ref System.UInt32 pcchCookieData, int dwFlags, IntPtr lpReserved); + private static string GetCookie(string url) + { + uint datasize = 1024; + StringBuilder cookieData = new StringBuilder((int)datasize); + if (!InternetGetCookieEx(url, null, cookieData, ref datasize, 0x2000, IntPtr.Zero)) + { + if (datasize < 0) + return null; + + cookieData = new StringBuilder((int)datasize); + if (!InternetGetCookieEx(url, null, cookieData, ref datasize, 0x00002000, IntPtr.Zero)) + return null; + } + return cookieData.ToString(); + } + #endregion + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("Json数据不能为空"); + CheckJson(textBox1.Text); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void linkLabel1_LinkClicked(object sender, EventArgs e) + { + try + { + Clipboard.SetDataObject(LoginUrl); + BaseForm.ShowSuccessAutoClose("复制成功,请粘贴到任意电脑的浏览器!\r\n注意:如果页面显示空白,请换个浏览器,不要用系统自带的IE浏览器!!!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void button1_Click(object sender, EventArgs e) + { + linkLabel1_LinkClicked(null, null); + } + + private void timer1_Tick(object sender, EventArgs e) + { + try + { + HttpHelper http = new HttpHelper(); + + //var html = http.GetHtml("http://cps.api.52cmg.cn/api/pinduoduo.asmx/login_callback?id=" + GuidToken).Html; + var html = http.GetHtml($"{ApiClient.Setting.SystemConfig.cps_server_api}api/pinduoduo.asmx/login_callback?id=" + GuidToken).Html; + var dic = HttpExtend.JsonToDictionary(html); + if (dic["ok"].ToString().ToLower() == "true") + { + this.timer1.Stop(); + CheckJson(html); + + //Console.WriteLine("拼多多登录结果:" + html); + } + + + } + catch (Exception ex) + { + + } + } + + private void button2_Click(object sender, EventArgs e) + { + try + { + //从注册表中读取默认浏览器可执行文件路径 + RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"http\shell\open\command\"); + string s = key.GetValue("").ToString(); + + + System.Diagnostics.Process.Start(s.Substring(0, s.Length - 8), LoginUrl); + } + catch (Exception) + { + try + { + System.Diagnostics.Process.Start(LoginUrl); + } + catch (Exception) + { + MessageBox.Show("抱歉,无法启动【默认浏览器】,请点击下方按钮自行登录!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/pinduoduo_form_login.resx b/类库/Api.Framework/Cps/pinduoduo_form_login.resx new file mode 100644 index 0000000..744624b --- /dev/null +++ b/类库/Api.Framework/Cps/pinduoduo_form_login.resx @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + 109, 17 + + + 50 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.Designer.cs b/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.Designer.cs new file mode 100644 index 0000000..1f697e6 --- /dev/null +++ b/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.Designer.cs @@ -0,0 +1,274 @@ +namespace Api.Framework.Cps +{ + partial class pinduoduo_form_select_tgw + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(pinduoduo_form_select_tgw)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Location = new System.Drawing.Point(8, 9); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(758, 86); + this.groupControl1.TabIndex = 5; + this.groupControl1.Text = "账号选择"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(605, 39); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(94, 23); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "创建推广位"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(406, 41); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(174, 20); + this.textEdit1.TabIndex = 7; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(348, 43); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 6; + this.labelControl2.Text = "新建名称:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(52, 44); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 5; + this.labelControl1.Text = "操作账号:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(110, 41); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(202, 20); + this.comboBoxEdit1.TabIndex = 4; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.label6); + this.groupControl2.Controls.Add(this.pageControl1); + this.groupControl2.Controls.Add(this.gridControl1); + this.groupControl2.Location = new System.Drawing.Point(8, 113); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(758, 389); + this.groupControl2.TabIndex = 6; + this.groupControl2.Text = "推广位选择"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(17, 124); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(716, 33); + this.label6.TabIndex = 3; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(5, 348); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(748, 36); + this.pageControl1.TabIndex = 2; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(5, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(748, 318); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.Caption = "Pid"; + this.gridColumn2.FieldName = "p_id"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // gridColumn3 + // + this.gridColumn3.Caption = "创建时间"; + this.gridColumn3.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn3.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn3.FieldName = "create_time"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.ReadOnly = true; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + // + // simpleButton2 + // + this.simpleButton2.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(222, 508); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(137, 35); + this.simpleButton2.TabIndex = 7; + this.simpleButton2.Text = "确认选中行"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(415, 510); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(137, 35); + this.simpleButton3.TabIndex = 8; + this.simpleButton3.Text = "放弃修改"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // pinduoduo_form_select_tgw + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(773, 555); + this.Controls.Add(this.simpleButton3); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.groupControl1); + this.Name = "pinduoduo_form_select_tgw"; + this.Text = "设置拼多多推广位"; + this.Load += new System.EventHandler(this.pinduoduo_form_selec_tgw_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private System.Windows.Forms.Label label6; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.cs b/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.cs new file mode 100644 index 0000000..8309bd9 --- /dev/null +++ b/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using Api.Framework.Enums; +using System.Text.RegularExpressions; +using System.Collections; +using Api.Framework.Model; + +namespace Api.Framework.Cps +{ + /// + /// 拼多多推广位选择 + /// + internal partial class pinduoduo_form_select_tgw : BaseForm + { + internal class view_pinduoduo_form_select_tgw + { + public string name { get; set; } + public string p_id { get; set; } + public DateTime create_time { get; set; } + } + internal pinduoduo_form_select_tgw() + { + InitializeComponent(); + this.gridView1.CustomDrawRowIndicator += gridView1_CustomDrawRowIndicator; + } + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + private void pinduoduo_form_selec_tgw_Load(object sender, EventArgs e) + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.多多进宝).ToList(); + if (members == null || members.Count == 0) + { + ShowError("对不起,当前未检测到您登陆了拼多多!"); + this.Close(); + return; + } + + this.comboBoxEdit1.Properties.Items.AddRange(members); + + this.pageControl1.Bind(delegate (int index, int page) + { + try + { + var member = this.comboBoxEdit1.EditValue as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreatePinduoduoRequest(member); + var result = api.SendPinduoduo("pdd.ddk.oauth.goods.pid.query", new { page = index, page_size = page }); + result = result["p_id_query_response"] as Dictionary; + var list = result["p_id_list"] as ArrayList; + this.label6.Visible = false; + ArrayList _list = new ArrayList(); + foreach (Dictionary item in list) + { + _list.Add(new view_pinduoduo_form_select_tgw { name = item["pid_name"].ToString(), p_id = item["p_id"].ToString(), create_time = CsharpHttpHelper.HttpExtend.GetDateTime(item["create_time"].ToString()) }); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = int.Parse(result["total_count"].ToString()) }; + } + catch (Exception ex) + { + this.UpdateUI(() => + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + }); + } + return null; + }, this.gridControl1, 100, true, true); + + this.comboBoxEdit1.SelectedIndex = 0; + + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + internal Tuiguangwei Tuiguangwei { get; private set; } + private void simpleButton2_Click(object sender, EventArgs e) + { + var select = this.gridView1.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView1.GetRow(select[0]) as view_pinduoduo_form_select_tgw; + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + Tuiguangwei = new Tuiguangwei() + { + Member = member, + Name = row.name, + Pid = row.p_id + }; + this.Close(); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + Tuiguangwei = null; + this.Close(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrEmpty(this.textEdit1.Text)) throw new Exception("推广位名称不能留空!"); + if (XtraMessageBox.Show($"您确定要创建名为【{this.textEdit1.Text}】的推广位吗?\r\n友情提示:创建后,暂时无法删除推广位!", "谨慎选择", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var member = this.comboBoxEdit1.EditValue as fl_cps_member; + //var member = CpsClient.Members.FirstOrDefault(f => f.username == Regex.Match(this.comboBoxEdit1.Text, @"(\d+)").Groups[1].Value); + var api = CpsClient.CreatePinduoduoRequest(member); + api.SendPinduoduo("pdd.ddk.oauth.goods.pid.generate", new + { + number = 1, + p_id_name_list = $"[\"{this.textEdit1.Text}\"]" + }); + this.pageControl1.GotoPage(1); + } + + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.resx b/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.resx new file mode 100644 index 0000000..06a0574 --- /dev/null +++ b/类库/Api.Framework/Cps/pinduoduo_form_select_tgw.resx @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC + + + + 25 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/suning_form_login.Designer.cs b/类库/Api.Framework/Cps/suning_form_login.Designer.cs new file mode 100644 index 0000000..c08602e --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_login.Designer.cs @@ -0,0 +1,48 @@ +namespace Api.Framework.Cps +{ + partial class suning_form_login + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // suning_form_login + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1133, 590); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Name = "suning_form_login"; + this.Text = "苏宁易购登录"; + this.Load += new System.EventHandler(this.suning_form_login_Load); + this.ResumeLayout(false); + + } + + #endregion + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/suning_form_login.cs b/类库/Api.Framework/Cps/suning_form_login.cs new file mode 100644 index 0000000..3b4e660 --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_login.cs @@ -0,0 +1,293 @@ +using Api.Framework.EntityTmp.SuNing; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.Tools; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using EO.Base; +using EO.WebBrowser; +using EO.WinForm; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + public partial class suning_form_login : BaseForm + { + public suning_form_login() + { + InitializeComponent(); + } + + internal fl_cps_member member { get; private set; } + + private void button1_Click(object sender, EventArgs e) + { + try + { + //var phone = textEdit1.Text.Trim(); + //if (string.IsNullOrWhiteSpace(textEdit1.Text)) + // throw new Exception("请填写苏宁联盟的手机号"); + //else if (!Regex.IsMatch(phone, @"\d{11}")) + // throw new Exception("填写的手机号码非法"); + + //var cps = new fl_cps_member() { cpstype = CpsType.苏宁易购, logintime = DateTime.Now, online = true, usernick = phone, username = string.Empty }; + //var api = new SuNingApi(cps); + //var toolPid = api.CreateToolsRelation(phone); + //if (string.IsNullOrWhiteSpace(toolPid)) + // throw new Exception("请求异常,请稍后重试"); + //cps.username = toolPid; + //member = CpsClient.Members.FirstOrDefault(f => f.usernick == phone && f.cpstype == CpsType.苏宁易购); + //if (member != null) + //{ + // member.online = true; + // member.username = toolPid; + // member.logintime = DateTime.Now; + //} + //else + //{ + // CpsClient.Members.Add(cps); + // member = cps; + //} + + //EventClient.OnEvent(this, MethodType.刷新联盟); + //this.Close(); + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex, 10000); + } + } + + private const string loginUrl = "https://passport.suning.com/ids/login?service=https%3A%2F%2Faq.suning.com%2Fasc%2Fauth%3FtargetUrl%3Dhttp%253A%252F%252Fsums.suning.com%252Funion%252Flogin.htm&loginTheme=b2c&multipleActive=false"; + + public WebControl webControl; + + private void suning_form_login_Load(object sender, EventArgs e) + { + //初始化控件对象 + webControl = new WebControl(); + //实例化视图 + webControl.WebView = new EO.WebBrowser.WebView(); + + var accountName = Guid.NewGuid().ToString("N"); + EO.WebEngine.Engine engine = EO.WebEngine.Engine.Create(accountName); + engine.Options.CachePath = HttpExtend.MapPath($"Cache\\Cookies\\{accountName}"); + + webControl.WebView.Engine = engine; + + EO.Base.Runtime.Exception += Runtime_Exception; + + //加载url + webControl.WebView.LoadUrl(loginUrl); + webControl.WebView.LoadCompleted += WebView_LoadCompleted; + webControl.WebView.NewWindow += WebView_NewWindow; + //webControl.WebView.UrlChanged += WebView_UrlChanged; + //webControl.WebView.AfterReceiveHeaders += WebView_AfterReceiveHeaders; + var sHandler = new SNResourceHandler(); + sHandler.JsonAction += SHandler_JsonAction; + webControl.WebView.RegisterResourceHandler(sHandler);//注册自定义资源处理程序 + + webControl.Dock = DockStyle.Fill; + this.Controls.Add(webControl); + } + + private void Runtime_Exception(object sender, ExceptionEventArgs e) + { + e.ShowExceptionDialog = false; + } + + private void SHandler_JsonAction(string url, string arg2, string cookice) + { + try + { + if (url.Contains("sums.suning.com/union/home.htm")) + this.cookice = cookice; + } + catch (Exception ex) + { + } + } + + private string cookice = string.Empty; + + private void WebView_LoadCompleted(object sender, LoadCompletedEventArgs e) + { + try + { + if (e.Url.Contains("sums.suning.com/union/home.htm")) + { + var html = webControl.WebView.GetHtml(); + if (!string.IsNullOrWhiteSpace(html) && (html.Contains(@"class=""logout"">退出登录</a>") || html.Contains(@">进入联盟</a>"))) + { + GetMemberId(); + + if (member != null) + { + var api = CpsClient.CreateSuNingRequest(member); + + int total = 0; + var list = api.GetTuiguagnwei(); + if (list != null && list.Count != 0) + { + var db = ApiClient.GetSession(); + var tgw = db.FindSingle("select * from fl_suning_tgw where username = @username and toolpid = @toolpid", new { username = member.username, toolpid = member.usernick }); + if (tgw == null) + tgw = new fl_suning_tgw() { username = member.username, toolpid = member.usernick }; + tgw.piddic = JsonConvert.SerializeObject(list); + db.SaveOrUpdate(tgw); + } + } + + this.Close(); + } + throw new Exception("登录失败"); + } + } + catch (Exception ex) + { + ShowErrorAutoClose(ex); + } + } + + private void GetMemberId() + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "http://sums.suning.com/union/myUnion/account/info.htm", + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookice, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "text/html", + Referer = "http://sums.suning.com/union/myUnion/account/info.htm", + Allowautoredirect = true, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + if (!string.IsNullOrWhiteSpace(html)) + { + html = Regex.Replace(html, @"\s", "", RegexOptions.IgnoreCase); + var reg = Regex.Match(html, @"用户名:(?<会员名>.+?)[\w\W]+会员编码:(?<会员编码>\d+)", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + + //var memberNikc = reg.Groups["会员名"].Value; + var memberId = reg.Groups["会员编码"].Value; + + var api = new SuNingApi(new fl_cps_member()); + var relationId = api.CreateToolsRelation(memberId); + + member = CpsClient.Members.FirstOrDefault(f => f.username == memberId && f.cpstype == CpsType.苏宁易购); + if (member == null) + { + member = new fl_cps_member() { username = memberId, usernick = relationId, cookies = cookice, cpstype = CpsType.苏宁易购 }; + CpsClient.Members.Add(member); + } + member.usernick = relationId; + member.logintime = DateTime.Now; + member.cookies = cookice; + member.is_valid = true; + } + } + } + catch (Exception ex) + { + } + } + + private void WebView_NewWindow(object sender, NewWindowEventArgs e) + { + webControl.WebView.LoadUrl(e.TargetUrl); + } + + } + + + #region 自定义响应Response 20212123 + + internal class SNResourceHandler : ResourceHandler + { + public event Action JsonAction; + + //如果使用此方式,将完全转移嫁接,包括真实请求,需要自己模拟请求, + public const string SampleUrlPrefix = "sample://"; + + public const string EmbeddedPageUrl = "sample://embedded_page"; + + //此方法判断是否自定义处理响应 + public override bool Match(Request request) + { + var cookies = Regex.Replace(request.Cookies.ToString(), "path=/", "").Replace("\r\n", ""); + //Console.WriteLine(request.Url); + + if (request.Url.Contains("sums.suning.com/union/home.htm")) + return true; + return false; + } + + //如果自定义响应,则在这里处理请求,并返回要显示的信息 + public override void ProcessRequest(Request request, EO.WebBrowser.Response response) + { + try + { + var cookies = Regex.Replace(request.Cookies.ToString(), "path=/", "").Replace("\r\n", ""); + + //Console.WriteLine("@ = " + request.Url); + var http = new HttpHelper(); + var data = http.GetHtml(request.Url, cookies, ""); + + var html = data.Html; + if (!string.IsNullOrWhiteSpace(html)) + { + /* + + */ + if (html.Contains(@"class=""logout"">退出登录") || html.Contains(@">进入联盟")) + JsonAction?.Invoke(request.Url, "", cookies); + + response.ContentType = "application/json";//必须设置,否则会弹出对话框并无法显示在EO.Web控件上 + response.ContentEncoding = "UTF-8";//必须设置,否则中文显示乱码 + byte[] be = Encoding.UTF8.GetBytes(html); + response.OutputStream.Write(be, 0, be.Length); + response.OutputStream.Close(); + return; + } + } + catch (Exception ex) + { } + base.ProcessRequest(request, response); + } + } + #endregion + +} diff --git a/类库/Api.Framework/Cps/suning_form_login.resx b/类库/Api.Framework/Cps/suning_form_login.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_login.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/suning_form_login1.Designer.cs b/类库/Api.Framework/Cps/suning_form_login1.Designer.cs new file mode 100644 index 0000000..47ed54b --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_login1.Designer.cs @@ -0,0 +1,93 @@ +namespace Api.Framework.Cps +{ + partial class suning_form_login1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.status = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(202, 276); + this.linkLabel1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(31, 14); + this.linkLabel1.TabIndex = 9; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "刷新"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // status + // + this.status.AutoSize = true; + this.status.Location = new System.Drawing.Point(50, 276); + this.status.Name = "status"; + this.status.Size = new System.Drawing.Size(38, 14); + this.status.TabIndex = 8; + this.status.Text = "label1"; + // + // pictureBox1 + // + this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.pictureBox1.Location = new System.Drawing.Point(0, 0); + this.pictureBox1.Margin = new System.Windows.Forms.Padding(5); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Padding = new System.Windows.Forms.Padding(5); + this.pictureBox1.Size = new System.Drawing.Size(268, 256); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureBox1.TabIndex = 7; + this.pictureBox1.TabStop = false; + // + // suning_form_login1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(268, 304); + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.status); + this.Controls.Add(this.pictureBox1); + this.Name = "suning_form_login1"; + this.Text = "苏宁授权登录"; + this.Load += new System.EventHandler(this.suning_form_login1_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Label status; + private System.Windows.Forms.PictureBox pictureBox1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/suning_form_login1.cs b/类库/Api.Framework/Cps/suning_form_login1.cs new file mode 100644 index 0000000..069906f --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_login1.cs @@ -0,0 +1,229 @@ +using Api.Framework.Enums; +using Api.Framework.Model; +using CsharpHttpHelper; +using Newtonsoft.Json.Linq; +using QRCoder; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + public partial class suning_form_login1 : BaseForm + { + public suning_form_login1() + { + InitializeComponent(); + } + + internal fl_cps_member member { get; private set; } + + private void suning_form_login1_Load(object sender, EventArgs e) + { + View(); + } + + public void View() + { + cancellation.Cancel(); + //cancellation = new CancellationTokenSource(); + + var code = GetQRCodeUrl(); + + var qrGenerator = new QRCoder.QRCodeGenerator(); + var qrCodeData = qrGenerator.CreateQrCode(code, QRCodeGenerator.ECCLevel.Q); + var qrcode = new QRCode(qrCodeData); + + Bitmap qrCodeImage = qrcode.GetGraphic(5, Color.Black, Color.White, null, 15, 6, false); + var ms = new MemoryStream(); + qrCodeImage.Save(ms, ImageFormat.Jpeg); + this.Invoke(new Action(() => + { + pictureBox1.Image = qrCodeImage; + status.Text = "请使用手机苏宁二维码..."; + })); + } + + public string QRCodeUrl; + public string ErrorMsg; + public LoginQRCodeStatus QRCodeStatus; + + private string uuid; + private string Cookies; + + public string GetQRCodeUrl() + { + try + { + var login_url = $"https://passport.suning.com/ids/qrLoginUuidGenerate.htm?image=false&yys={HttpExtend.GetTimeStamp(DateTime.Now)}000"; + var http = new HttpHelper(); + var result = http.GetHtml(login_url); + var json = JObject.Parse(result.Html); + + if (json != null && json["res_code"]?.ToString() == "0") + { + this.QRCodeUrl = json["url"].ToString(); + this.uuid = json["qrToken"].ToString(); + this.Cookies = HttpHelper.GetSmallCookie(result.Cookie); + QRCodeStatus = LoginQRCodeStatus.等待扫码; + StarCheck(); + return this.QRCodeUrl; + } + else throw new Exception(result.Html); + } + catch (Exception ex) + { + ErrorMsg = ex.Message; + QRCodeStatus = LoginQRCodeStatus.获取二维码失败; + } + return string.Empty; + } + + CancellationTokenSource cancellation = new CancellationTokenSource(); + + private void StarCheck() + { + cancellation = new CancellationTokenSource(); + ThreadPool.QueueUserWorkItem(x => + { + var timeout = DateTime.Now.AddMinutes(5); + while (DateTime.Now < timeout) + { + if (cancellation.IsCancellationRequested) + return; + + Thread.Sleep(1000); + try + { + var http = new HttpHelper(); + var result = http.GetHtml("https://passport.suning.com/ids/qrLoginStateProbe?r=" + Guid.NewGuid().ToString(), this.Cookies, $"uuid={uuid}&service=&terminal=PC", "https://passport.suning.com/ids/login"); + var json = JObject.Parse(result.Html); + var code = json["state"].ToString(); + + if (!string.IsNullOrEmpty(result.Cookie)) this.Cookies = result.UpdateCookies(this.Cookies); + if (code == "0") + { + QRCodeStatus = LoginQRCodeStatus.等待扫码; + this.Invoke(new Action(() => + { + status.Text = QRCodeStatus.ToString(); + })); + } + else if (code == "1") + { + QRCodeStatus = LoginQRCodeStatus.等待确认登录; + this.Invoke(new Action(() => + { + status.Text = QRCodeStatus.ToString(); + })); + } + else if (code == "2") + { + var vid = HttpExtend.GetTimeStamp(DateTime.Now).ToString() + (long)(new Random().NextDouble() * 100000000); + this.Cookies += $";_snma=" + HttpHelper.URLEncode("1|{vid}|{vid.Substring(0,13)}|{HttpExtend.GetTimeStamp(DateTime.Now,true)}|{HttpExtend.GetTimeStamp(DateTime.Now, true)}|27|2"); + var item = http.GetItem($"https://passport.suning.com/ids/login?service=https%3A%2F%2Floginst.suning.com%2Fauth%3FtargetUrl%3Dhttps%253A%252F%252Floginst.suning.com%252FauthStatus%253Fcallback%253DjQuery172004949899331832408_1647605568465%2526_%253D{HttpExtend.GetTimeStamp(DateTime.Now, true)}&gateway=true&loginTheme=b2c&multipleActive=false", this.Cookies); + item.Allowautoredirect = false; + result = http.GetHtml(item); + + this.Cookies = result.UpdateCookies(this.Cookies); + item = http.GetItem("http://sums.suning.com/union/myUnion/account/info.htm", this.Cookies); + item.Timeout = 10000; + item.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0"; + item.Accept = "text/html, application/xhtml+xml, */*"; + item.ContentType = "text/html"; + item.Referer = "http://sums.suning.com/union/myUnion/account/info.htm"; + + var html = http.GetHtml(item).Html; + html = Regex.Replace(html, @"\s", "", RegexOptions.IgnoreCase); + var reg = Regex.Match(html, @"用户名:(?<会员名>.+?)[\w\W]+会员编码:(?<会员编码>\d+)", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + var memberId = reg.Groups["会员编码"].Value; + + var api = new SuNingApi(new fl_cps_member()); + var relationId = api.CreateToolsRelation(memberId); + + member = CpsClient.Members.FirstOrDefault(f => f.username == memberId && f.cpstype == CpsType.苏宁易购); + if (member == null) + { + member = new fl_cps_member() { username = memberId, usernick = relationId, cookies = Cookies, cpstype = CpsType.苏宁易购 }; + CpsClient.Members.Add(member); + } + member.usernick = relationId; + member.logintime = DateTime.Now; + member.cookies = Cookies; + member.is_valid = true; + + QRCodeStatus = LoginQRCodeStatus.登录并授权成功; + this.Invoke(new Action(() => + { + status.Text = QRCodeStatus.ToString(); + this.Close(); + })); + + + return; + } + else + { + + QRCodeStatus = LoginQRCodeStatus.登录失败; + this.Invoke(new Action(() => + { + status.Text = QRCodeStatus.ToString(); + })); + ErrorMsg = "已确认登录,但获取关键信息失败!"; + break; + } + } + else + { + QRCodeStatus = LoginQRCodeStatus.二维码已过期; + this.Invoke(new Action(() => + { + status.Text = QRCodeStatus.ToString(); + })); + break; + } + } + catch (Exception ex) + { + EventClient.OnEvent("苏宁授权过程异常", ex.Message); + } + } + }, cancellation.Token); + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + View(); + } + } + + + public enum LoginQRCodeStatus : int + { + 正在获取二维码 = 1, + 获取二维码失败 = 2, + 二维码已过期 = 3, + 等待扫码 = 4, + 等待确认登录 = 5, + 正在授权 = 6, + 登录并授权成功 = 7, + + 登录失败 = 97, + 操作超时 = 99 + } + +} diff --git a/类库/Api.Framework/Cps/suning_form_login1.resx b/类库/Api.Framework/Cps/suning_form_login1.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_login1.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/suning_form_select_tgw.Designer.cs b/类库/Api.Framework/Cps/suning_form_select_tgw.Designer.cs new file mode 100644 index 0000000..83f6ba5 --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_select_tgw.Designer.cs @@ -0,0 +1,263 @@ +namespace Api.Framework.Cps +{ + partial class suning_form_select_tgw + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(suning_form_select_tgw)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Location = new System.Drawing.Point(5, 8); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(755, 88); + this.groupControl1.TabIndex = 15; + this.groupControl1.Text = "账号选择"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(605, 39); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(94, 23); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "创建推广位"; + this.simpleButton1.Visible = false; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(406, 41); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(174, 20); + this.textEdit1.TabIndex = 7; + this.textEdit1.Visible = false; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(348, 43); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(52, 14); + this.labelControl2.TabIndex = 6; + this.labelControl2.Text = "新建名称:"; + this.labelControl2.Visible = false; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(52, 44); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(52, 14); + this.labelControl1.TabIndex = 5; + this.labelControl1.Text = "操作账号:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(110, 41); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(202, 20); + this.comboBoxEdit1.TabIndex = 4; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.label6); + this.groupControl2.Controls.Add(this.pageControl1); + this.groupControl2.Controls.Add(this.gridControl1); + this.groupControl2.Location = new System.Drawing.Point(5, 102); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(755, 460); + this.groupControl2.TabIndex = 16; + this.groupControl2.Text = "推广位选择"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(17, 124); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(716, 33); + this.label6.TabIndex = 3; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(5, 419); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(745, 36); + this.pageControl1.TabIndex = 2; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(5, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(745, 389); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.Caption = "Pid"; + this.gridColumn2.FieldName = "p_id"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // simpleButton2 + // + this.simpleButton2.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(194, 586); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(152, 32); + this.simpleButton2.TabIndex = 17; + this.simpleButton2.Text = "确认选中行"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(401, 585); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(137, 35); + this.simpleButton3.TabIndex = 18; + this.simpleButton3.Text = "放弃修改"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // suning_form_select_tgw + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(765, 629); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.simpleButton3); + this.Name = "suning_form_select_tgw"; + this.Text = "选择推广位"; + this.Load += new System.EventHandler(this.suning_form_select_tgw_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private System.Windows.Forms.Label label6; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/suning_form_select_tgw.cs b/类库/Api.Framework/Cps/suning_form_select_tgw.cs new file mode 100644 index 0000000..45474dd --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_select_tgw.cs @@ -0,0 +1,150 @@ +using Api.Framework.EntityTmp.SuNing; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + public partial class suning_form_select_tgw : BaseForm + { + /// + /// 单个推广位 + /// + internal Tuiguangwei Tuiguangwei { get; private set; } + + public suning_form_select_tgw() + { + InitializeComponent(); + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + var select = this.gridView1.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView1.GetRow(select[0]) as view_suning_form_select_tgw; + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + Tuiguangwei = new Tuiguangwei() + { + Member = member, + Name = row.name, + Pid = row.p_id + }; + this.Close(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + Tuiguangwei = null; + this.Close(); + } + + private void suning_form_select_tgw_Load(object sender, EventArgs e) + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.苏宁易购).ToList(); + if (members == null || members.Count == 0) + { + ShowError("对不起,当前未检测到您登录的苏宁账号!"); + this.Close(); + return; + } + + this.pageControl1.Bind(delegate (int index, int page) + { + try + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateSuNingRequest(member); + + int total = 0; + + var db = ApiClient.GetSession(); + var tgw = db.FindSingle("select * from fl_suning_tgw where username = @username and toolpid = @toolpid", new { username = member.username, toolpid = member.usernick }); + + var list = api.GetTuiguagnwei(); + if (tgw != null && (list == null || list.Count == 0)) + { + list = JsonConvert.DeserializeObject>(tgw.piddic); + } + + if (list != null && list.Count != 0) + { + if (tgw == null) + tgw = new fl_suning_tgw() { username = member.username, toolpid = member.usernick }; + tgw.piddic = JsonConvert.SerializeObject(list); + db.SaveOrUpdate(tgw); + + this.label6.Visible = false; + var _list = new ArrayList(); + foreach (SN_TuiGuangWeiInfo item in list) + { + _list.Add(new view_suning_form_select_tgw { name = item.adzonename, p_id = item.adzonepid, create_time = DateTime.Now }); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = total }; + } + else + { + throw new Exception("获取推广位异常,请重新登录苏宁!"); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = new ArrayList(), Total = 0 }; + } + catch (Exception ex) + { + this.UpdateUI(() => + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + }); + } + return null; + }, this.gridControl1, 100, true, true); + + this.comboBoxEdit1.Properties.Items.AddRange(members); + this.comboBoxEdit1.SelectedIndex = 0; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 临时类 + /// + internal class view_suning_form_select_tgw + { + public string name { get; set; } + public string p_id { get; set; } + public DateTime create_time { get; set; } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + } +} diff --git a/类库/Api.Framework/Cps/suning_form_select_tgw.resx b/类库/Api.Framework/Cps/suning_form_select_tgw.resx new file mode 100644 index 0000000..3d9504c --- /dev/null +++ b/类库/Api.Framework/Cps/suning_form_select_tgw.resx @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC + + + + 52 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/weipinhui_form_login.Designer.cs b/类库/Api.Framework/Cps/weipinhui_form_login.Designer.cs new file mode 100644 index 0000000..401ace2 --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_login.Designer.cs @@ -0,0 +1,214 @@ +namespace Api.Framework.Cps +{ + partial class weipinhui_form_login + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(weipinhui_form_login)); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.xtraTabPage2.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(712, 453); + this.xtraTabControl1.TabIndex = 2; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.groupBox2); + this.xtraTabPage1.Controls.Add(this.button2); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(710, 427); + this.xtraTabPage1.Text = "本机浏览器登录"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Controls.Add(this.button1); + this.groupBox2.Location = new System.Drawing.Point(11, 152); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(652, 273); + this.groupBox2.TabIndex = 4; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "登录失败 - 解决方案如下(IE无法登录)"; + // + // label1 + // + this.label1.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.ForeColor = System.Drawing.Color.Red; + this.label1.Location = new System.Drawing.Point(113, 58); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(520, 95); + this.label1.TabIndex = 4; + this.label1.Text = "情况1:没有看到打开的网页!!\r\n\r\n情况2:打开后显示空白页面!!\r\n\r\n请点击下方按钮,粘贴到任意电脑的其他浏览器登录!\r\n"; + // + // button1 + // + this.button1.Font = new System.Drawing.Font("Tahoma", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.button1.Location = new System.Drawing.Point(117, 191); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(384, 43); + this.button1.TabIndex = 3; + this.button1.Text = "复制登录地址 --- ( 我要去别的浏览器登录 )"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.button2.Location = new System.Drawing.Point(108, 52); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(425, 43); + this.button2.TabIndex = 3; + this.button2.Text = "打开本机【默认浏览器】登录"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.groupBox1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(710, 427); + this.xtraTabPage2.Text = "我在其他电脑登录了"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.hyperlinkLabelControl1); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupBox1.Location = new System.Drawing.Point(0, 0); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(710, 427); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "请粘贴登录结果"; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.hyperlinkLabelControl1.Appearance.Options.UseFont = true; + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(168, 328); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(350, 17); + this.hyperlinkLabelControl1.TabIndex = 2; + this.hyperlinkLabelControl1.Text = "还未登录,请点击【复制登录地址】,粘贴到浏览器登录"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.hyperlinkLabelControl1_Click); + // + // textBox1 + // + this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox1.Location = new System.Drawing.Point(3, 18); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox1.Size = new System.Drawing.Size(704, 289); + this.textBox1.TabIndex = 0; + // + // simpleButton1 + // + this.simpleButton1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(236, 361); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(182, 41); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "验证Json有效性"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 2000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // weipinhui_form_login + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(712, 453); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "weipinhui_form_login"; + this.Text = "唯品会登录"; + this.Load += new System.EventHandler(this.weipinhui_form_login_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.xtraTabPage2.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.Timer timer1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/weipinhui_form_login.cs b/类库/Api.Framework/Cps/weipinhui_form_login.cs new file mode 100644 index 0000000..3a4a2b4 --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_login.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using Api.Framework.Tools; +using Api.Framework.Model; +using System.Text.RegularExpressions; +using UI.Framework.Forms; +using Api.Framework.Enums; +using SHDocVw; +using Microsoft.Win32; +using System.Runtime.InteropServices; +using CsharpHttpHelper; + +namespace Api.Framework.Cps +{ + /// + /// 唯品会登录 + /// + public partial class weipinhui_form_login : BaseForm + { + internal weipinhui_form_login() + { + InitializeComponent(); + } + + internal fl_cps_member member { get; private set; } + + private void weipinhui_form_login_Load(object sender, EventArgs e) + { + //this.LoginUrl = $"http://cps.api.52cmg.cn/api/weipinhui.asmx/login?guid={GuidToken}"; + this.LoginUrl = $"{ApiClient.Setting.SystemConfig.cps_server_api}api/weipinhui.asmx/login?guid={GuidToken}"; + } + + private string LoginUrl = string.Empty; + private string GuidToken = Guid.NewGuid().ToString(); + + private string UserName = string.Empty; + private string UserId = string.Empty; + + private void button2_Click(object sender, EventArgs e) + { + try + { + //从注册表中读取默认浏览器可执行文件路径 + RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"http\shell\open\command\"); + string s = key.GetValue("").ToString(); + + System.Diagnostics.Process.Start(s.Substring(0, s.Length - 8), LoginUrl); + } + catch (Exception) + { + try + { + System.Diagnostics.Process.Start(LoginUrl); + } + catch (Exception) + { + MessageBox.Show("抱歉,无法启动【默认浏览器】,请点击下方按钮自行登录!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + } + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + Clipboard.SetDataObject(LoginUrl); + BaseForm.ShowSuccessAutoClose("复制成功,请粘贴到任意电脑的浏览器!\r\n注意:如果页面显示空白,请换个浏览器,不要用系统自带的IE浏览器!!!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void hyperlinkLabelControl1_Click(object sender, EventArgs e) + { + try + { + Clipboard.SetDataObject(LoginUrl); + BaseForm.ShowSuccessAutoClose("复制成功,请粘贴到任意电脑的浏览器!\r\n注意:如果页面显示空白,请换个浏览器,不要用系统自带的IE浏览器!!!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("Json数据不能为空"); + CheckJson(textBox1.Text); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void timer1_Tick(object sender, EventArgs e) + { + try + { + var http = new HttpHelper(); + + //var html = http.GetHtml("http://cps.api.52cmg.cn/api/weipinhui.asmx/query_callback?guid=" + GuidToken).Html; + var html = http.GetHtml($"{ApiClient.Setting.SystemConfig.cps_server_api}api/weipinhui.asmx/query_callback?guid=" + GuidToken).Html; + var dic = HttpExtend.JsonToDictionary(html); + if (dic["ok"].ToString().ToLower() == "true") + { + this.timer1.Stop(); + CheckJson(html); + + //Console.WriteLine("拼多多登录结果:" + html); + } + } + catch (Exception ex) + { } + } + + private void CheckJson(string html, string cookie = "") + { + try + { + var json = CsharpHttpHelper.HttpExtend.JsonToDictionary(html); + + if (json == null) + { + EventClient.OnEvent(this, "登陆唯品会失败:" + html); + ShowError("登录失败,请查看页面具体错误!"); + } + else if (json["ok"].ToString().ToLower() == "false") ShowError(json["message"].ToString()); + else + { + json = json["message"] as Dictionary; + member = CpsClient.Members.FirstOrDefault(f => f.username == json["open_id"].ToString() && f.cpstype == CpsType.唯品联盟); + if (member == null) + { + member = new fl_cps_member() { username = json["open_id"].ToString(), cpstype = CpsType.唯品联盟 }; + CpsClient.Members.Add(member); + } + //member.usernick = "";//TODO 这里获取用户页面上输入的账号,这里开发者写固定了,发布的时候修改 + if (string.IsNullOrWhiteSpace(member.usernick)) + { + var wphUserNickForm = new weipinhui_form_usernick(); + if (wphUserNickForm.ShowDialog() == DialogResult.OK) + member.usernick = wphUserNickForm.usernick; + else + { + ShowError("未设置唯品会授权账号昵称,登录终止"); + return; + } + } + member.logintime = DateTime.Now; + member.cookies = cookie; + member.is_valid = true; + this.Close(); + } + } + catch (Exception ex) + { + throw ex; + } + } + + #region cookie + private const int INTERNET_COOKIE_HTTPONLY = 0x00002000; + + [DllImport("wininet.dll", SetLastError = true)] + static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, StringBuilder pchCookieData, ref System.UInt32 pcchCookieData, int dwFlags, IntPtr lpReserved); + private static string GetCookie(string url) + { + uint datasize = 1024; + StringBuilder cookieData = new StringBuilder((int)datasize); + if (!InternetGetCookieEx(url, null, cookieData, ref datasize, 0x2000, IntPtr.Zero)) + { + if (datasize < 0) + return null; + + cookieData = new StringBuilder((int)datasize); + if (!InternetGetCookieEx(url, null, cookieData, ref datasize, 0x00002000, IntPtr.Zero)) + return null; + } + return cookieData.ToString(); + } + #endregion + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/weipinhui_form_login.resx b/类库/Api.Framework/Cps/weipinhui_form_login.resx new file mode 100644 index 0000000..d2a1966 --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_login.resx @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + 109, 17 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/weipinhui_form_select_tgw.Designer.cs b/类库/Api.Framework/Cps/weipinhui_form_select_tgw.Designer.cs new file mode 100644 index 0000000..66f7b26 --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_select_tgw.Designer.cs @@ -0,0 +1,261 @@ +namespace Api.Framework.Cps +{ + partial class weipinhui_form_select_tgw + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(weipinhui_form_select_tgw)); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.label6 = new System.Windows.Forms.Label(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // groupControl1 + // + this.groupControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl1.Controls.Add(this.simpleButton1); + this.groupControl1.Controls.Add(this.textEdit1); + this.groupControl1.Controls.Add(this.labelControl2); + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.comboBoxEdit1); + this.groupControl1.Location = new System.Drawing.Point(12, 12); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(755, 88); + this.groupControl1.TabIndex = 11; + this.groupControl1.Text = "账号选择"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(605, 39); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(94, 23); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "创建推广位"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(406, 41); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(174, 24); + this.textEdit1.TabIndex = 7; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(348, 43); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(65, 18); + this.labelControl2.TabIndex = 6; + this.labelControl2.Text = "新建名称:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(52, 44); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(65, 18); + this.labelControl1.TabIndex = 5; + this.labelControl1.Text = "操作账号:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.Location = new System.Drawing.Point(110, 41); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.TextEditStyle = DevExpress.XtraEditors.Controls.TextEditStyles.DisableTextEditor; + this.comboBoxEdit1.Size = new System.Drawing.Size(202, 24); + this.comboBoxEdit1.TabIndex = 4; + this.comboBoxEdit1.SelectedIndexChanged += new System.EventHandler(this.comboBoxEdit1_SelectedIndexChanged); + // + // groupControl2 + // + this.groupControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupControl2.Controls.Add(this.label6); + this.groupControl2.Controls.Add(this.pageControl1); + this.groupControl2.Controls.Add(this.gridControl1); + this.groupControl2.Location = new System.Drawing.Point(12, 106); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(755, 460); + this.groupControl2.TabIndex = 12; + this.groupControl2.Text = "推广位选择"; + // + // label6 + // + this.label6.BackColor = System.Drawing.Color.White; + this.label6.Font = new System.Drawing.Font("Tahoma", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(17, 124); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(716, 33); + this.label6.TabIndex = 3; + this.label6.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.label6.Visible = false; + // + // pageControl1 + // + this.pageControl1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.pageControl1.Location = new System.Drawing.Point(5, 419); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(745, 36); + this.pageControl1.TabIndex = 2; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.Location = new System.Drawing.Point(5, 24); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(745, 389); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + // + // gridColumn1 + // + this.gridColumn1.Caption = "名称"; + this.gridColumn1.FieldName = "name"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.OptionsColumn.ReadOnly = true; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.Caption = "Pid"; + this.gridColumn2.FieldName = "p_id"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.ReadOnly = true; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // simpleButton2 + // + this.simpleButton2.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(201, 590); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(152, 32); + this.simpleButton2.TabIndex = 13; + this.simpleButton2.Text = "确认选中行"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton3 + // + this.simpleButton3.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.simpleButton3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton3.ImageOptions.Image"))); + this.simpleButton3.Location = new System.Drawing.Point(408, 589); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(137, 35); + this.simpleButton3.TabIndex = 14; + this.simpleButton3.Text = "放弃修改"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // weipinhui_form_select_tgw + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 18F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(779, 636); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.simpleButton3); + this.Name = "weipinhui_form_select_tgw"; + this.Text = "设置唯品会推广位"; + this.Load += new System.EventHandler(this.weipinhui_form_select_tgw_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private System.Windows.Forms.Label label6; + private UI.Framework.Controls.PageControl pageControl1; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/weipinhui_form_select_tgw.cs b/类库/Api.Framework/Cps/weipinhui_form_select_tgw.cs new file mode 100644 index 0000000..a38e7d7 --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_select_tgw.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using System.Text.RegularExpressions; +using Api.Framework.Model; +using Api.Framework.Enums; +using System.Collections; +using Api.Framework.Tools; +using Newtonsoft.Json; + +namespace Api.Framework.Cps +{ + /// + /// 唯品会推广位选择 + /// + public partial class weipinhui_form_select_tgw : BaseForm + { + internal class view_weipinhui_form_select_tgw + { + public string name { get; set; } + public string p_id { get; set; } + public DateTime create_time { get; set; } + } + internal weipinhui_form_select_tgw() + { + InitializeComponent(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var newName = this.textEdit1.Text.Trim(); + if (string.IsNullOrWhiteSpace(newName)) throw new Exception("推广位名称不能留空!"); + string pattern = "[\u4e00-\u9fbb]"; + if (Regex.IsMatch(this.textEdit1.Text, pattern)) throw new Exception("推广位名称不能包含中文!"); + if (this.textEdit1.Text.Trim().Length > 50) throw new Exception("推广位名称长度过长,最多50个字符!"); + + if (XtraMessageBox.Show($"您确定要创建名为【{newName}】的推广位吗?", "温馨提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + //var member = CpsClient.Members.FirstOrDefault(f => f.username == Regex.Match(this.comboBoxEdit1.Text, @"(\d+)").Groups[1].Value); + var api = CpsClient.CreateWeipinhuiRequest(member); + //api.SendWeipinhui("com.vip.adp.api.open.service.UnionPidService-1.0.0#genPidWithOauth", new { pidGenRequest = new { requestId = Util.GetUUID(), pidNameList = new List() { newName } } }); + WeipinhuiApi.CreateWphTgw(api, new List() { newName }); + this.pageControl1.GotoPage(1); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void comboBoxEdit1_SelectedIndexChanged(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void weipinhui_form_select_tgw_Load(object sender, EventArgs e) + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.唯品联盟).ToList(); + if (members == null || members.Count == 0) + { + ShowError("对不起,当前未检测到您登录的唯品会账号!"); + this.Close(); + return; + } + + this.pageControl1.Bind(delegate (int index, int page) + { + try + { + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + if (member == null) throw new Exception("找不到,您选择的账号!"); + var api = CpsClient.CreateWeipinhuiRequest(member); + + var result = WeipinhuiApi.GetWphTgw(api, index, page); + if (result != null) + { + var total = result.total; + var list = result.pidInfoList; + this.label6.Visible = false; + ArrayList _list = new ArrayList(); + foreach (var item in list) + { + _list.Add(new view_weipinhui_form_select_tgw { name = item.pidName, p_id = item.pid, create_time = CsharpHttpHelper.HttpExtend.GetDateTime(item.createTime.ToString()) }); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = _list, Total = total }; + } + else + { + throw new Exception("获取推广位异常,稍后再试!"); + } + return new UI.Framework.Controls.PageControl.SerchResult() { Result = new ArrayList(), Total = 0 }; + } + catch (Exception ex) + { + this.UpdateUI(() => + { + this.label6.Visible = true; + this.label6.Text = ex.Message; + }); + } + return null; + }, this.gridControl1, 100, true, true); + + this.comboBoxEdit1.Properties.Items.AddRange(members); + this.comboBoxEdit1.SelectedIndex = 0; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + /// + /// 单个推广位 + /// + internal Tuiguangwei Tuiguangwei { get; private set; } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + var select = this.gridView1.GetSelectedRows(); + if (select.Length == 0) ShowError("您当前没有选中任何一行!"); + else + { + var row = this.gridView1.GetRow(select[0]) as view_weipinhui_form_select_tgw; + var member = this.comboBoxEdit1.SelectedItem as fl_cps_member; + Tuiguangwei = new Tuiguangwei() + { + Member = member, + Name = row.name, + Pid = row.p_id + }; + this.Close(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + Tuiguangwei = null; + this.Close(); + } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/weipinhui_form_select_tgw.resx b/类库/Api.Framework/Cps/weipinhui_form_select_tgw.resx new file mode 100644 index 0000000..a93c809 --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_select_tgw.resx @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFp0RVh0VGl0 + bGUARGVsZXRlO0RlbGV0ZUl0ZW07UmVtb3ZlO1JlbW92ZUl0ZW07RGVsZXRlTGlzdDtMaXN0O1JlbW92 + ZUxpc3Q7SXRlbTtMaXN0O0NsZWFyO0VyYXNlWOIXCwAAB81JREFUWEell3tM1ecZx9FavBVFra5pV2ma + dZlduiVbsi3dP+tfa8yWuizruk7nEm2NK65qnTqLIBxuIjfhIKhcvaBy1dQK9QbIRahUq5BSi7agFSe3 + A5zDuXD77vs8v3PggECa9E0+PO/vct7v93lvvxcfAD5eZUZWwWeXs4uuI7vwOrI8USj4DNkFRhQyC+qR + mV+PjLx6pDOm511T4g6XhbGdWWSmtJeYVe2TmFnpk0C8i+iqtpeBGWSmCH6X4nINwmZ3oafXjkedfWi5 + 343rjQ9QVd+CqJRSE9t6UtqTdvnMJ+ZgGatjhU1MauAJyVbK0NAIhobdDA0zDmOQ94QBXjuchgFLnwP/ + 67Ti7r0uJB+pwcgIcL6yGSFxZ8PZni9RE+FJFxjGiuiqtv4xihiYJd0rZUzUQESVwRG4BocVh3MA1n4X + Orv7aaATsekVasBqH0RJxW3sjCyKYJuzyRPu9keL6Kq2/jGKvPBkBsdTipEpoeAgxQxxQ9g1MAznwBDj + EPodA+jiMNxhD0SYL6oBu2tYTZy9+AW2hJyMZLtzyDgToqva+scohgFOJCkiJhw8VT+ekxM4UY+4jCo0 + t3Rid9w5NSCmHWpiCKfPN+JfO488ZkJ0VVv/GEUe+B4+5WWAmUr22gNsdFwvuHEODnEuDOBOSxe2R57R + 34oJvqo96HANoajkJtZ/kCEmPHNiUgPyYPbBk4YB6WbhQO41N5+O1Y+zTlLc7D10Ba0PexCeVIr3Qwqw + KTgfm3bnIzBIyENx6U320hURmkekF6Y0MCctt070dXxlnCfLWO473fNAVoOdtFvs+Pq+BbduP8S1hnuo + vdHKJfkNymrv4ErdHcQeqhAhPzK9gdTjtaJvNE7MR+uQrNQa8YjEWiQdqSO12E+ScoSrrBPW97MecaAM + 33xr0blxt7UTMWllIrSAyCY1pYG5KccMA3aOnZ2bjVOy1ozHcPC+jK2g77EH+t09IdHmGEQfl2e7pR9t + 7Va0d1kRnXZJhBaSaQ3MM8tmIgacXGJsLJHZJGZfRQJJzK5BYlYNErJ47SFTrmsQL7DuITTpErq4ScnQ + yGYVaVYD/mRKAzI285NyqtRAP7MQA07NVDI2MvRk+Rh838Yo2du4B8g+YLFyk+p1wGpzcYJeEKFFZFoD + TyVm0QAdaIMkLqMasVznsemM6Yxar8I+D4eFSoPR6yqEJJ5Hd59Tkc3KlPSJCC0m0xpYEOe1nfZxfT+W + pRt5bmTK7Vje7R94jK5eJ3vAqb0XEl8iQk8T+UjNmMyAOFuw72A5DYxoA70k5lClrnNP3HuQUdA6SRMq + Ec16FInmtfBh/Cfo7HGgo8epw7Y79mMRWkqmNbBQlosYEPFejp1m60Ezdmer0ajru4pLf9NrM6473Aak + 93bFfDcD/tGpFzFMAz2cQBY2FpVWgahUg0iN5RqVAwKvPej9Kxp3xZSgvcdOHJrEh/vUwDIi2/GUBhZF + mC8YBigus1gz9cp2YsY9zFbelW52DnCVOFwarTwrPOrmWaHbrs9uNX0rQj8ksh3Lkp/UwOLw/YaBbqsx + g8NTyhEhmMtZL9NrEwnntclcps8+utTEj1EHvjx6As0fbMbNE4W8bh9dBQ6aasgrxu2N73TX/HON58uo + veBtQMZmSVhCKYZ5CpIfyiwenzGzFaR3PNCoHEzu5Z1Ce3YKXA3laNqzE18VFfOw4kCf1Y77paVoS97H + ZxV4lGlG9Zq3o0Rv1IDbhBh4eg+XixjwLKGw5MujhEpMMmIoo9RNKZfR+FUbbm54F/aaYtgK4+Gsysfn + 29/HrWO5aD59Bq3xkXDVfwxbQRxspTn4/B9rLNSa690DehghS4Njz+k5UHawDmKM8YDOB4vNqRlL3TNE + gox7U14+bgSug7U4Gb05JjjKcvHppg24GxUM59Vi9B016f2qt1Yh4aUVW6nlO5mBZUGcrWJAlk+7Rfby + MR4JnFQysTw87LLThNHV13OOoXr1X2DJiUBX6k7YzqWjvyQD3an/RdeBHbi48jWEPhuwgzrzRdPbgMxK + WR7P7Ij6SM+DKqSibjEKiZiHtk5+6bqIRCI9Zum1ojr1EC6vWomOpG14aFpH1ms897vfINB/aTQ1lpDR + M4F3D6iB7RFn9BQ8MUsVHRW04wHjgw4isdOmBrp7+lCXkYOr69bggWkD7m376yg1q99E0IqfxVBDNqMp + DSzbZjqtZ7/Rrx43EWP/N/Z8z06oq0J2PK4EedbbZ1XxitVvoS3uP2hevxLN77hh/b5pI8rf/DPCfvxK + EHXkZDRzogHdiAKDciu2hBVja2gRtpDNe4RCbA4p1PPev4O9znxkS1gRbjS24uzeZJx/449oCX4XX7z9 + GprIiR8F4OSKl7QufL317yhd+Tp2B/xkF7XGrQIpeiQj8s1+hjxHZOd6fhKWexFAXjYvf9n6ZeDf0PCn + 3+LWG68i98XlWDtrftzaWfPic198AQ2rXlUa1/4B5oCf9vI3/hMNSC+ICekJGQ75j2YiYnAy/HctCUgp + /uUvUP/6r3B8+fN4z9cvmPd/IGycvXDP8RcCUP/7X6Po569gx+KAFN6fP2rg+8Iixhdu83suKdI/wLLJ + 10+6WA6gcl+fvTdnURCf9Wz2e9bMazmYjM2B74u7iJB8aOTcN9d97SmeZyL8FHGvAvj8H0dnIylwnHcG + AAAAAElFTkSuQmCC + + + + 53 + + \ No newline at end of file diff --git a/类库/Api.Framework/Cps/weipinhui_form_usernick.Designer.cs b/类库/Api.Framework/Cps/weipinhui_form_usernick.Designer.cs new file mode 100644 index 0000000..87034f2 --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_usernick.Designer.cs @@ -0,0 +1,89 @@ +namespace Api.Framework.Cps +{ + partial class weipinhui_form_usernick + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.button1 = new System.Windows.Forms.Button(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(317, 36); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 0; + this.button1.Text = "确定"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(66, 35); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(234, 22); + this.textBox1.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.ForeColor = System.Drawing.Color.Blue; + this.label1.Location = new System.Drawing.Point(44, 85); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(295, 14); + this.label1.TabIndex = 2; + this.label1.Text = "注:该昵称用于备注唯品会登录账号(方便用户记忆)"; + // + // weipinhui_form_usernick + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(423, 129); + this.Controls.Add(this.label1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.button1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "weipinhui_form_usernick"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "设置唯品会账号昵称"; + this.Load += new System.EventHandler(this.weipinhui_form_usernick_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Cps/weipinhui_form_usernick.cs b/类库/Api.Framework/Cps/weipinhui_form_usernick.cs new file mode 100644 index 0000000..4ec664a --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_usernick.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.Cps +{ + /// + /// 唯品会名称设置 + /// + public partial class weipinhui_form_usernick : BaseForm + { + internal string usernick = string.Empty; + internal weipinhui_form_usernick() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) + throw new Exception("昵称不能为空"); + else + { + usernick = textBox1.Text.Trim(); + this.DialogResult = DialogResult.OK; + } + } + catch (Exception ex) + { + BaseForm.ShowErrorAutoClose(ex); + } + } + + private void weipinhui_form_usernick_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/类库/Api.Framework/Cps/weipinhui_form_usernick.resx b/类库/Api.Framework/Cps/weipinhui_form_usernick.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Api.Framework/Cps/weipinhui_form_usernick.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Api.Framework/CpsClient.cs b/类库/Api.Framework/CpsClient.cs new file mode 100644 index 0000000..dd2dfd1 --- /dev/null +++ b/类库/Api.Framework/CpsClient.cs @@ -0,0 +1,417 @@ +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CsharpHttpHelper; +using System.IO; +using Api.Framework.SDK; +using Api.Framework.Timers; +using System.Threading; + +namespace Api.Framework +{ + /// + /// Cps管理端 + /// + public class CpsClient + { + static CpsClient() + { + RefreshCps(); + GuideMembers = new List(); + GuideMembers.Add(new fl_cps_member() { abnormal_tip = SwitchType.关闭, cpstype = CpsType.多多进宝, is_download = SwitchType.关闭, is_valid = true, logintime = DateTime.Now, online = true, username = "1929015", usernick = "w", cookies = "1929015_24223399" });//吴嘉华 + GuideMembers.Add(new fl_cps_member() { abnormal_tip = SwitchType.关闭, cpstype = CpsType.多多进宝, is_download = SwitchType.关闭, is_valid = true, logintime = DateTime.Now, online = true, username = "8701005", usernick = "zyy", cookies = "8701005_194371009" });//张谊玉 + GuideMembers.Add(new fl_cps_member() { abnormal_tip = SwitchType.关闭, cpstype = CpsType.多多进宝, is_download = SwitchType.关闭, is_valid = true, logintime = DateTime.Now, online = true, username = "15528847", usernick = "zl", cookies = "15528847_194372142" });//周雷 + GuideMembers.Add(new fl_cps_member() { abnormal_tip = SwitchType.关闭, cpstype = CpsType.多多进宝, is_download = SwitchType.关闭, is_valid = true, logintime = DateTime.Now, online = true, username = "8364424", usernick = "zcg", cookies = "8364424_194372426" });//钟成刚 + GuideMembers.Add(new fl_cps_member() { abnormal_tip = SwitchType.关闭, cpstype = CpsType.多多进宝, is_download = SwitchType.关闭, is_valid = true, logintime = DateTime.Now, online = true, username = "15529092", usernick = "lcr", cookies = "15529092_194372782" });//廖春容 + GuideMembers.Add(new fl_cps_member() { abnormal_tip = SwitchType.关闭, cpstype = CpsType.多多进宝, is_download = SwitchType.关闭, is_valid = true, logintime = DateTime.Now, online = true, username = "15529109", usernick = "yc", cookies = "15529109_194373136" });//杨灿 + GuideMembers.Add(new fl_cps_member() { abnormal_tip = SwitchType.关闭, cpstype = CpsType.多多进宝, is_download = SwitchType.关闭, is_valid = true, logintime = DateTime.Now, online = true, username = "15531182", usernick = "lxy", cookies = "15531182_194378363" });//李馨雨 + } + + /// + /// 软件登录的cps集合 + /// + public static List Members { get; private set; } + + /// + /// 公共的Cps集合 + /// + internal static List GuideMembers { get; private set; } + + /// + /// 刷新cps缓存 + /// + public static void RefreshCps() + { + Members = ApiClient.GetSession().Find("select * from fl_cps_member"); + } + + /// + /// 创建拼多多API请求 + /// + /// cps对象 + /// + public static PinduoduoApi CreatePinduoduoRequest(fl_cps_member member) + { + if (member != null && member.cpstype != CpsType.多多进宝) throw new Exception("CreatePinduoduoRequest 失败,您当前账号类型为:" + member.cpstype); + return new PinduoduoApi(member); + } + + /// + /// 创建一个阿里妈妈API请求 + /// + /// cps对象 + /// + public static AlimamaApi CreateAlimamaRequest(fl_cps_member member) + { + if (member.cpstype != CpsType.阿里妈妈) throw new Exception("CreateAlimamaRequest 失败,您当前账号类型为:" + member.cpstype); + return new AlimamaApi(member); + } + + /// + /// 创建一个京东联盟API请求 + /// + /// cps对象 + /// + public static JingdongApi CreateJingdongRequest(fl_cps_member member) + { + if (member.cpstype != CpsType.京东联盟) throw new Exception("CreateJingdongRequest 失败,您当前账号类型为:" + member.cpstype); + return new JingdongApi(member); + } + + /// + /// 创建一个唯品联盟API请求 + /// + /// cps对象 + /// + public static WeipinhuiApi CreateWeipinhuiRequest(fl_cps_member member) + { + if (member.cpstype != CpsType.唯品联盟) throw new Exception("CreateWeipinhuiRequest 失败,您当前账号类型为:" + member.cpstype); + return new WeipinhuiApi(member); + } + + /// + /// 创建一个苏宁易购API请求 + /// + /// cps对象 + /// + public static SuNingApi CreateSuNingRequest(fl_cps_member member) + { + if (member.cpstype != CpsType.苏宁易购) throw new Exception("CreateSuNingRequest 失败,您当前账号类型为:" + member.cpstype); + return new SuNingApi(member); + } + + /// + /// 创建一个抖音联盟API请求 + /// + /// cps对象 + /// + public static DouyinApi CreateDouyinRequest(fl_cps_member member) + { + if (member != null && member.cpstype != CpsType.抖音联盟) throw new Exception("CreateDouyinRequest 失败,您当前账号类型为:" + member.cpstype); + return new DouyinApi(member); + } + + public static KuaiShouApi CreateKuaiShouRequest(fl_cps_member member) + { + if (member.cpstype != CpsType.快手联盟) throw new Exception("CreateDouyinRequest 失败,您当前账号类型为:" + member.cpstype); + return new KuaiShouApi(member); + } + + /// + /// cps登录 + /// + /// 需要登录cps类型 + /// + public static fl_cps_member Login(CpsType type) + { + // MiniblinkNet.WebView.PerformCookieCommand( MiniblinkNet.wkeCookieCommand.ClearAllCookies); + + fl_cps_member member = null; + + switch (type) + { + case CpsType.唯品联盟: + { + var form = new weipinhui_form_login(); + form.ShowDialog(); + member = form.member; + break; + } + //登录拼多多 + case CpsType.多多进宝: + { + var form = new pinduoduo_form_login(); + form.ShowDialog(); + member = form.member; + break; + } + case CpsType.阿里妈妈: + { + //清理Cookies + Tools.Util.SuppressWininetBehavior(); + try + { + var CookiesFile = HttpExtend.MapFile("cookies.dat"); + if (File.Exists(CookiesFile)) File.Delete(CookiesFile); + } + catch (Exception) + { + } + //开始登陆 + var login = new alimama_form_login(); + login.ShowDialog(); + member = login.Member; + break; + } + case CpsType.京东联盟: + { + var form = new jingdong_form_login(); + form.ShowDialog(); + member = form.member; + break; + } + case CpsType.抖音联盟: + { + var form = new douyin_form_login(); + form.ShowDialog(); + member = form.Member; + break; + } + case CpsType.苏宁易购: + { + var form = new suning_form_login1(); + form.ShowDialog(); + member = form.member; + break; + } + case CpsType.快手联盟: + { + var form = new kuaishou_form_login(); + form.ShowDialog(); + member = form.member; + break; + } + } + + if (member != null) + { + try + { + switch (type) + { + case CpsType.阿里妈妈: + new AlimamaApi(member).RefToken(); + break; + case CpsType.多多进宝: + new PinduoduoApi(member).RefToken(); + break; + case CpsType.唯品联盟: + new WeipinhuiApi(member).RefToken(); + break; + case CpsType.快手联盟: + new KuaiShouApi(member).RefToken(); + break; + case CpsType.京东联盟: + //new JingdongApi(member).RefToken(); + break; + default: + break; + } + } + catch (Exception) + { } + + var session = ApiClient.GetSession(); + session.SaveOrUpdate(member); + return member; + } + return null; + } + + /// + /// cps选择推广位 + /// + /// cps类型 + /// + /// + /// + /// + public static object SelectTuiguangwei(CpsType type, bool isalone = true, bool isgroup = false, bool isactivity = false) + { + switch (type) + { + case CpsType.阿里妈妈: + { + var f = new alimama_form_select_tgw(isalone, isgroup, isactivity); + f.ShowDialog(); + if (f.Tuiguangwei != null) + return f.Tuiguangwei; + else + return f.AdzoneGroup; + } + case CpsType.多多进宝: + { + var f = new pinduoduo_form_select_tgw(); + f.ShowDialog(); + return f.Tuiguangwei; + } + case CpsType.京东联盟: + { + var f = new jingdong_form_select_tgw(); + f.ShowDialog(); + return f.Tuiguangwei; + } + case CpsType.唯品联盟: + { + var f = new weipinhui_form_select_tgw(); + f.ShowDialog(); + return f.Tuiguangwei; + } + case CpsType.抖音联盟: + { + var f = new douyin_form_select_tgw(); + f.ShowDialog(); + return f.Tuiguangwei; + } + case CpsType.苏宁易购: + { + var f = new suning_form_select_tgw(); + f.ShowDialog(); + return f.Tuiguangwei; + } + case CpsType.快手联盟: + { + var f = new kuaishou_form_select_tgw(); + f.ShowDialog(); + return f.Tuiguangwei; + } + //case CpsType.考拉联盟: + // { + // var f = new laola_form_select_tgw(); + // f.ShowDialog(); + // return f.Tuiguangwei; + // } + default: + + break; + } + return null; + } + + /// + /// 更新订单 + /// + /// cps类型 + /// 开始时间 + /// 结束时间 + /// 订单id + public static void UpdateOrder(CpsType type, DateTime startTime, DateTime endTime, string order_id) + { + try + { + switch (type) + { + case CpsType.阿里妈妈: + { + var timer = TimerTask.GetTimer() as DownAlimamaTimer; + timer.UpdateOrder(startTime, endTime, order_id); + break; + } + case CpsType.多多进宝: + { + var timer = TimerTask.GetTimer() as DownPinduoduoTimer; + timer.UpdateOrder(startTime, endTime, order_id); + break; + } + case CpsType.京东联盟: + { + var timer = TimerTask.GetTimer() as DownJingdongTimer; + timer.UpdateOrder(startTime, order_id); + break; + } + case CpsType.唯品联盟: + { + var timer = TimerTask.GetTimer() as DownWeipinhuiTimer; + timer.UpdateOrder(startTime, endTime, order_id); + break; + } + //case CpsType.抖音联盟: + // { + // var timer = TimerTask.GetTimer() as DownDouyinTimer; + // timer.UpdateOrder(startTime, endTime, order_id); + // break; + // } + case CpsType.苏宁易购: + { + var timer = TimerTask.GetTimer() as DownSuningTimer; + timer.UpdateOrder(startTime, endTime, order_id); + break; + } + case CpsType.快手联盟: + { + var timer = TimerTask.GetTimer() as DownKuaiShouTimer; + timer.UpdateOrder(startTime, endTime); + break; + } + default: + break; + } + } + catch { } + } + + internal static string _key { get; set; } + internal static int _appid { get; set; } + internal static string _host { get; set; } + internal static void SetEnckey(int appid, string host, string key) + { + _host = host; + _appid = appid; + _key = key; + } + + /// + /// 像服务器发送数据包 + /// + /// + /// + /// + /// + internal static object SendServer(string method, string target, object param) + { + AuthEndpoint end = new AuthEndpoint() + { + Appid = CpsClient._appid, + Enckey = CpsClient._key, + Host = CpsClient._host + "/api/" + target + "/send_data", + Method = method + }; + if (param != null) + { + var _param = param.GetType().GetProperties(); + foreach (var item in _param) + { + end.Param[item.Name] = item.GetValue(param); + } + } + HttpHelper http = new HttpHelper(); + for (int i = 0; i < 3; i++) + { + var result = http.SendData(end); + if (result != null) + { + if (!result.ok) throw new Exception(result.message.ToString()); + return result.message; + } + Thread.Sleep(50); + } + return null; + } + } +} diff --git a/类库/Api.Framework/Data/TB/AnalysisTkUrlData.cs b/类库/Api.Framework/Data/TB/AnalysisTkUrlData.cs new file mode 100644 index 0000000..ca2264c --- /dev/null +++ b/类库/Api.Framework/Data/TB/AnalysisTkUrlData.cs @@ -0,0 +1,23 @@ +namespace Api.Framework.Data.TB +{ + /// + /// 解析链接 (长短链接 s.click.taobao) + /// + public class AnalysisTkUrlData + { + /// + /// 商品id + /// + public string item_id { get; set; } + + /// + /// 商品混淆id + /// + public string open_iid { get; set; } + + /// + /// 1-动态ID转链场景,2-消费者比价场景,3-商品库导购场景(不填默认为1) + /// + public string biz_scene_id { get; set; } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Data/TB/CouponData.cs b/类库/Api.Framework/Data/TB/CouponData.cs new file mode 100644 index 0000000..10c9dcc --- /dev/null +++ b/类库/Api.Framework/Data/TB/CouponData.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; + +namespace Api.Framework.Data.TB +{ + /// + /// 优惠券信息数据 + /// + public class CouponData + { + /// + /// 优惠券金额 + /// + public decimal CouponPrice { get; set; } + + /// + /// 优惠券条件金额 + /// + public decimal ConditionPrice { get; set; } + + /// + /// 优惠券地址 + /// + public string CouponUrl { get; set; } + + /// + /// 优惠券ID + /// + public string ActivityId { get; set; } + + + } + public class CouponDataComparer : IComparer + { + public int Compare(CouponData x, CouponData y) + { + if (x == null || y == null) + { + return 0; + } + if (x.ConditionPrice == y.ConditionPrice) + { + var result = x.CouponPrice - y.CouponPrice; + if (result == 0) + { + return 0; + } + + if (result > 0) + { + return -1; + } + else + { + return 1; + } + } + else if (x.ConditionPrice > y.ConditionPrice) + { + return -1; + } + else if (x.ConditionPrice < y.ConditionPrice) + { + return 1; + } + return -1; + } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Data/TB/GetItemInfoData.cs b/类库/Api.Framework/Data/TB/GetItemInfoData.cs new file mode 100644 index 0000000..56a2285 --- /dev/null +++ b/类库/Api.Framework/Data/TB/GetItemInfoData.cs @@ -0,0 +1,195 @@ +using System.Collections.Generic; + +namespace Api.Framework.Data.TB +{ + public class GetItemInfosData + { + /// + /// + /// + public List n_tbk_item { get; set; } + + } + + public class Small_images + { + /// + /// 图片 + /// + public List @string { get; set; } + } + + public class N_tbk_item + { + /// + /// 女装 + /// + public string cat_name { get; set; } + /// + /// + /// + public string num_iid { get; set; } + /// + /// 连衣裙 + /// + public string title { get; set; } + /// + /// + /// + public string pict_url { get; set; } + /// + /// + /// + public Small_images small_images { get; set; } + /// + /// + /// + public string reserve_price { get; set; } + /// + /// + /// + public string zk_final_price { get; set; } + /// + /// + /// + public long user_type { get; set; } + /// + /// 杭州 + /// + public string provcity { get; set; } + /// + /// + /// + public string item_url { get; set; } + /// + /// + /// + public long seller_id { get; set; } + /// + /// + /// + public int volume { get; set; } + /// + /// xx旗舰店 + /// + public string nick { get; set; } + /// + /// 情趣内衣 + /// + public string cat_leaf_name { get; set; } + /// + /// + /// + public bool is_prepay { get; set; } + /// + /// + /// + public long shop_dsr { get; set; } + /// + /// + /// + public long ratesum { get; set; } + /// + /// + /// + public bool i_rfd_rate { get; set; } + /// + /// + /// + public bool h_good_rate { get; set; } + /// + /// + /// + public bool h_pay_rate30 { get; set; } + /// + /// + /// + public bool free_shipment { get; set; } + /// + /// + /// + public string material_lib_type { get; set; } + /// + /// 付定金立减20元 + /// + public string presale_discount_fee_text { get; set; } + /// + /// + /// + public long presale_tail_end_time { get; set; } + /// + /// + /// + public long presale_tail_start_time { get; set; } + /// + /// + /// + public long presale_end_time { get; set; } + /// + /// + /// + public long presale_start_time { get; set; } + /// + /// + /// + public string presale_deposit { get; set; } + /// + /// + /// + public long ju_play_end_time { get; set; } + /// + /// + /// + public long ju_play_start_time { get; set; } + /// + /// 玩法 + /// + public string play_info { get; set; } + /// + /// + /// + public long tmall_play_activity_end_time { get; set; } + /// + /// + /// + public long tmall_play_activity_start_time { get; set; } + /// + /// + /// + public string ju_online_start_time { get; set; } + /// + /// + /// + public string ju_online_end_time { get; set; } + /// + /// + /// + public string ju_pre_show_start_time { get; set; } + /// + /// + /// + public string ju_pre_show_end_time { get; set; } + /// + /// + /// + public string sale_price { get; set; } + /// + /// ["每100减20","每200减50"] + /// + public string kuadian_promotion_info { get; set; } + /// + /// + /// + public string superior_brand { get; set; } + /// + /// + /// + public string hot_flag { get; set; } + /// + /// + /// + public string input_num_iid { get; set; } + } + + +} \ No newline at end of file diff --git a/类库/Api.Framework/Data/TB/TBGoodParsingData.cs b/类库/Api.Framework/Data/TB/TBGoodParsingData.cs new file mode 100644 index 0000000..1b057d0 --- /dev/null +++ b/类库/Api.Framework/Data/TB/TBGoodParsingData.cs @@ -0,0 +1,30 @@ +namespace Api.Framework.Data.TB +{ + public class TBGoodParsingData + { + /// + /// 商品ID + /// + public string ItemId { get; set; } + + /// + /// 原始消息中包含商品ID的关键词 + /// + public string OriginalKeyWord { get; set; } + + /// + /// 是否是解析口令 + /// + public bool IsParsingPass { get; set; } = false; + + /// + /// 淘宝场景ID 【1-动态ID转链场景(支持新商品ID转换),2-消费者比价场景(支持原始商品ID转新商品ID),3-商品库导购场景(支持库内B段新商品ID转换)(不填默认为1)】 + /// + public string BizSceneId { get; set; } = "2"; + + /// + /// 指定的优惠券信息 + /// + public string ActivityId { get; set; } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Data/TB/TBItemInfoData.cs b/类库/Api.Framework/Data/TB/TBItemInfoData.cs new file mode 100644 index 0000000..3dee4eb --- /dev/null +++ b/类库/Api.Framework/Data/TB/TBItemInfoData.cs @@ -0,0 +1,111 @@ +using System; + +namespace Api.Framework.Data.TB +{ + /// + /// 商品信息 + /// + public class TBItemInfoData + { + /// + /// 购买口令 + /// + public string BuyPass { get; set; } + + /// + /// 中间页地址 + /// + public string ZJYUrl { get; set; } + + /// + /// 优惠券ID + /// + public string ActivityId { get; set; } + + /// + /// 优惠券地址 + /// + public string CouponUrl { get; set; } + + /// + /// 宝贝ID + /// + public string ItemId { get; set; } + + /// + /// 商品地址 + /// + public string ItemUrl { get; set; } + + /// + /// 商品名称 + /// + public string ItemTitle { get; set; } + + /// + /// 宝贝价格 + /// + public decimal Price { get; set; } + + /// + /// 佣金比例 + /// + public decimal CommissionRatio { get; set; } + + /// + /// 是否需要技术费 + /// + public bool IsTip { get; set; } = false; + + /// + /// 佣金金额(根据付款金额及佣金比例自动计算) + /// + public decimal CommissionMoney => Math.Round(Price * (IsTip ? 0.9m : 1m) * CommissionRatio, 2); + + /// + /// 优惠券金额 + /// + public decimal CouponPrice { get; set; } + + /// + /// 使用券后价 + /// + public decimal UseCouponPrice { get; set; } + + /// + /// 券后佣金 + /// + public decimal CommissionUseCouponMoney => Math.Round((UseCouponPrice <= 0 ? Price : UseCouponPrice) * (IsTip ? 0.9m : 1m) * CommissionRatio, 2); + + /// + /// 不使用券佣金 + /// + public decimal CommissionUnUseCouponMoney => Math.Round(Price * (IsTip ? 0.9m : 1m) * CommissionRatio, 2); + + /// + /// 宝贝图片 + /// + public string ImageUrl { get; set; } + + /// + /// 月销量 + /// + public int Sales { get; set; } + + /// + /// 店铺ID + /// + public string ShopId { get; set; } + + /// + /// 店铺昵称 + /// + public string ShopNick { get; set; } + + /// + /// 购买地址 + /// + public string BuyUrl { get; set; } + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Data/TB/TBPassInfoData.cs b/类库/Api.Framework/Data/TB/TBPassInfoData.cs new file mode 100644 index 0000000..ac28b94 --- /dev/null +++ b/类库/Api.Framework/Data/TB/TBPassInfoData.cs @@ -0,0 +1,59 @@ +using System.Text.RegularExpressions; + +namespace Api.Framework.Data.TB +{ + /// + /// 解析后的淘宝口令信息 + /// + public class TBPassInfoData + { + /// + /// 商品Id + /// + public string num_iid { get; set; } + + /// + /// 优惠券Id + /// + public string activityId + { + get + { + string activityIdTmp = string.Empty; + if (string.IsNullOrWhiteSpace(origin_url) == false) + { + var reg = Regex.Match(origin_url, @"activityId=(?<活动ID>[A-Za-z0-9]+)", RegexOptions.IgnoreCase); + if (reg.Success) + activityIdTmp = reg.Groups["活动ID"].Value; + } + return activityIdTmp; + } + } + + /// + /// 商品淘客转连连接 + /// + public string click_url { get; set; } + + /// + /// 店铺卖家ID + /// + public string seller_id { get; set; } + + /// + /// 入参淘口令对应原始链接 + /// + public string origin_url { get; set; } + + /// + /// 入参淘口令推广链接中的pid,如果不属于当前调用的推广者则展示“0” + /// + public string origin_pid { get; set; } + + /// + /// 1-动态ID转链场景,2-消费者比价场景,3-商品库导购场景 + /// + public string biz_scene_id { get; set; } + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Easy4/Common/ColumnInfo.cs b/类库/Api.Framework/Easy4/Common/ColumnInfo.cs new file mode 100644 index 0000000..8e550c7 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/ColumnInfo.cs @@ -0,0 +1,12 @@ +using System; + +namespace Easy4net.Common +{ + /// + /// 数据库字段名跟值键值对试题类 + /// + public class ColumnInfo : Map + { + + } +} diff --git a/类库/Api.Framework/Easy4/Common/CommonUtils.cs b/类库/Api.Framework/Easy4/Common/CommonUtils.cs new file mode 100644 index 0000000..5f7957d --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/CommonUtils.cs @@ -0,0 +1,53 @@ +using System; +using System.Configuration; + +namespace Easy4net.Common +{ + /// + /// 通用实用工具 + /// + public class CommonUtils + { + /// + /// 用于字符串和枚举类型的转换 + /// + /// + /// + /// + public static T EnumParse(string value) + { + try + { + return (T)Enum.Parse(typeof(T), value); + } + catch + { + throw new Exception("传入的值与枚举值不匹配。"); + } + } + + /// + /// 根据传入的Key获取配置文件中的Value值 + /// + /// + /// + public static string GetConfigValueByKey(string Key) + { + return ConfigurationManager.AppSettings[Key]; + } + + /// + /// 检测输入值是否为空 + /// + /// + /// + public static Boolean IsNullOrEmpty(Object value) + { + if (value == null) + return true; + if (String.IsNullOrEmpty(value.ToString())) + return true; + return false; + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/DbCondition.cs b/类库/Api.Framework/Easy4/Common/DbCondition.cs new file mode 100644 index 0000000..c3a7e33 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/DbCondition.cs @@ -0,0 +1,520 @@ +using System; +using System.Text; +using Easy4net.DBUtility; +using Easy4net.Context; + +namespace Easy4net.Common +{ + /// + /// 数据库条件语句生成器 + /// + public class DbCondition : Map + { + private static string WHERE = " WHERE "; + private static string EQUAL = " {0} = {1} "; + + private static string AND_EQ = " AND {0} = {1} "; + private static string OR_EQ = " OR {0} = {1} "; + + private static string GT = " {0} > {1} "; + private static string GT_EQ = " {0} >= {1} "; + + private static string AND_GT = " AND {0} > {1} "; + private static string AND_GT_EQ = " AND {0} >= {1} "; + + private static string OR_GT = " OR {0} > {1} "; + private static string OR_GT_EQ = " OR {0} >= {1} "; + + private static string LT = " {0} < {1} "; + private static string LT_EQ = " {0} <= {1} "; + + private static string AND_LT = " AND {0} < {1} "; + private static string AND_LT_EQ = " AND {0} <= {1} "; + + private static string OR_LT = " OR {0} < {1} "; + private static string OR_LT_EQ = " OR {0} <= {1} "; + + private static string ORDER_BY_ASC = " ORDER BY {0} ASC "; + private static string ORDER_BY_DESC = " ORDER BY {0} DESC "; + + /// + /// 参数字符前缀 + /// + private static string paramChar = string.Empty; + /// + /// SQL语句创建对象 + /// + private StringBuilder sbSQL = new StringBuilder(); + /// + /// 查询SQL语句 + /// + public string queryString = String.Empty; + /// + /// 字段信息 + /// + public ColumnInfo Columns = new ColumnInfo(); + + /// + /// 根据配置文件创建一个默认的条件语句生成器 + /// + public DbCondition() + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + paramChar = dbFactory.DbParmChar; + } + + /// + /// 根据配置文件创建一个默认的条件语句生成器 + /// + /// 查询语句 + public DbCondition(string query) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + paramChar = dbFactory.DbParmChar; + + this.queryString = query; + sbSQL.Append(query); + } + + /// + /// 传入查询语句 + /// + /// 查询语句 + /// + public DbCondition Query(string query) + { + this.queryString = query; + sbSQL.Append(query); + return this; + } + + /// + /// 增加Where关键字 + /// + /// + public DbCondition Where() + { + sbSQL.Append(WHERE); + return this; + } + + /// + /// 增加Where等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition Where(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(WHERE + EQUAL, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition Equal(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(EQUAL, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加And等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition AndEqual(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(AND_EQ, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加Or等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition OrEqual(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(OR_EQ, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加大于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition GreaterThan(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(GT, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加大于等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition GreaterThanEqual(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(GT_EQ, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加And大于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition AndGreaterThan(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(AND_GT, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加And大于等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition AndGreaterThanEqual(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(AND_GT_EQ, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加Or大于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition OrGreaterThan(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(OR_GT, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加Or大于等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition OrGreaterThanEqual(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(OR_GT_EQ, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加小于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition LessThan(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(LT, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加小于等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition LessThanEqual(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(LT_EQ, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加And小于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition AndLessThan(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(AND_LT, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加And小于等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition AndLessThanEqual(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(AND_LT_EQ, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加Or小于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition OrLessThan(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(OR_LT, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加Or小于等于语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition OrLessThanEqual(string fieldName, object fieldValue) + { + string formatName = formatKey(fieldName); + sbSQL.AppendFormat(OR_LT_EQ, fieldName, paramChar + formatName); + Columns[formatName] = fieldValue; + + return this; + } + + /// + /// 增加And等于语句,相当于AndEqual方法 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition And(string fieldName, object fieldValue) + { + return this.AndEqual(fieldName, fieldValue); + } + + /// + /// 增加Or等于语句,相当于OrEqual方法 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition Or(string fieldName, object fieldValue) + { + return this.OrEqual(fieldName, fieldValue); + } + + /// + /// 增加Order By Asc递增排序语句 + /// + /// 排序的字段名 + /// + public DbCondition OrderByASC(string fieldName) + { + sbSQL.AppendFormat(ORDER_BY_ASC, fieldName); + + return this; + } + + /// + /// 增加Order By Desc递减排序语句 + /// + /// 排序的字段名 + /// + public DbCondition OrderByDESC(string fieldName) + { + sbSQL.AppendFormat(ORDER_BY_DESC, fieldName); + + return this; + } + + /// + /// 增加Like %XX%语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition Like(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" {0} LIKE '%{1}%' ", fieldName, fieldValue); + return this; + } + + /// + /// 增加And Like %XX%语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition AndLike(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" AND {0} LIKE '%{1}%' ", fieldName, fieldValue); + return this; + } + + /// + /// 增加Or Like %XX%语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition OrLike(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" OR {0} LIKE '%{1}%' ", fieldName, fieldValue); + return this; + } + + /// + /// 增加Like %XX语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition LeftLike(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" {0} LIKE '%{1}' ", fieldName, fieldValue); + return this; + } + + /// + /// 增加And Like %XX语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition AndLeftLike(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" AND {0} LIKE '%{1}' ", fieldName, fieldValue); + return this; + } + + /// + /// 增加Or Like %XX语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition OrLeftLike(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" OR {0} LIKE '%{1}' ", fieldName, fieldValue); + return this; + } + + /// + /// 增加Like XX%语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition RightLike(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" {0} LIKE '{1}%' ", fieldName, fieldValue); + return this; + } + + /// + /// 增加And Like XX%语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition AndRightLike(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" AND {0} LIKE '{1}%' ", fieldName, fieldValue); + return this; + } + + /// + /// 增加Or Like XX%语句 + /// + /// 字段名 + /// 字段值 + /// + public DbCondition OrRightLike(string fieldName, object fieldValue) + { + sbSQL.AppendFormat(" OR {0} LIKE '{1}%' ", fieldName, fieldValue); + return this; + } + + /// + /// 输出本条件对象的字符串描述 + /// + /// + public override string ToString() + { + return sbSQL.ToString(); + } + + /// + /// 对关键字进行格式化输出 + /// + /// 要格式化的关键字 + /// + private string formatKey(string key) + { + int index = key.IndexOf('.'); + if (index >= 0) + { + key = key.Substring(index + 1, key.Length-(index+1)); + } + + return key; + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/DbKeywords.cs b/类库/Api.Framework/Easy4/Common/DbKeywords.cs new file mode 100644 index 0000000..feeea50 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/DbKeywords.cs @@ -0,0 +1,82 @@ +using Easy4net.DBUtility; +using System; +using System.Collections.Generic; + +namespace Easy4net.Common +{ + /// + /// 数据库关键字检查帮助类 + /// + public static class DbKeywords + { + /// + /// MySQL中关键字集合 + /// + private static Dictionary m_MySQL = new Dictionary(); + /// + /// MSSQL中关键字集合 + /// + private static Dictionary m_MSSQL = new Dictionary(); + + /// + /// 初始化MySQL中关键字集合 + /// + private static void InitMySQL() + { + if (m_MySQL.Count == 0) + { + m_MySQL.Add("order", "`order`"); + m_MySQL.Add("desc", "`desc`"); + m_MySQL.Add("key", "`key`"); + } + } + + /// + /// 初始化MSSQL中关键字集合 + /// + private static void InitMSSQL() + { + if (m_MSSQL.Count == 0) + { + m_MSSQL.Add("order", "[order]"); + m_MSSQL.Add("desc", "[desc]"); + m_MSSQL.Add("key", "[key]"); + m_MSSQL.Add("text", "[text]"); + m_MSSQL.Add("limit", "[limit]"); + m_MSSQL.Add("offset", "[offset]"); + m_MSSQL.Add("password", "[password]"); + } + } + + /// + /// 格式化列名,对列名与数据库关键字相同的进行格式化处理 + /// + /// + /// + /// + public static string FormatColumnName(string columnName, DatabaseType dbType) + { + InitMySQL(); + InitMSSQL(); + + string colName = columnName.ToLower(); + if ((dbType == DatabaseType.SQLITE || dbType == DatabaseType.MYSQL) && m_MySQL.ContainsKey(colName)) + { + return m_MySQL[colName]; + } + + if (dbType == DatabaseType.SQLSERVER && m_MSSQL.ContainsKey(colName)) + { + return m_MSSQL[colName]; + } + + if (dbType == DatabaseType.ACCESS && m_MSSQL.ContainsKey(colName)) + { + return m_MSSQL[colName]; + } + + return columnName; + } + + } +} diff --git a/类库/Api.Framework/Easy4/Common/DynamicCalls.cs b/类库/Api.Framework/Easy4/Common/DynamicCalls.cs new file mode 100644 index 0000000..7ff0fd1 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/DynamicCalls.cs @@ -0,0 +1,343 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; + +namespace Easy4net.Common +{ + /// Delegate for calling a method that is not known at runtime. + /// the object to be called or null if the call is to a static method. + /// the parameters to the method. + /// the return value for the method or null if it doesn't return anything. + public delegate object FastInvokeHandler(object target, object[] parameters); + + /// Delegate for creating and object at runtime using the default constructor. + /// the newly created object. + public delegate object FastCreateInstanceHandler(); + + /// Delegate to get an arbitraty property at runtime. + /// the object instance whose property will be obtained. + /// the property value. + public delegate object FastPropertyGetHandler(object target); + + /// Delegate to set an arbitrary property at runtime. + /// the object instance whose property will be modified. + /// + public delegate void FastPropertySetHandler(object target, object parameter); + + /// Class with helper methods for dynamic invocation generating IL on the fly. + public static class DynamicCalls + { + /// + /// 用于存放GetMethodInvoker的Dictionary + /// + private static Dictionary dictInvoker = new Dictionary(); + + /// + /// 快速执行指定方法 + /// + /// + /// + public static FastInvokeHandler GetMethodInvoker(MethodInfo methodInfo) + { + lock (dictInvoker) + { + if (dictInvoker.ContainsKey(methodInfo)) return dictInvoker[methodInfo]; + + // generates a dynamic method to generate a FastInvokeHandler delegate + DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object), typeof(object[]) }, methodInfo.DeclaringType.Module); + + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + ParameterInfo[] parameters = methodInfo.GetParameters(); + + Type[] paramTypes = new Type[parameters.Length]; + + // copies the parameter types to an array + for (int i = 0; i < paramTypes.Length; i++) + { + if (parameters[i].ParameterType.IsByRef) + paramTypes[i] = parameters[i].ParameterType.GetElementType(); + else + paramTypes[i] = parameters[i].ParameterType; + } + + LocalBuilder[] locals = new LocalBuilder[paramTypes.Length]; + + // generates a local variable for each parameter + for (int i = 0; i < paramTypes.Length; i++) + { + locals[i] = ilGenerator.DeclareLocal(paramTypes[i], true); + } + + // creates code to copy the parameters to the local variables + for (int i = 0; i < paramTypes.Length; i++) + { + ilGenerator.Emit(OpCodes.Ldarg_1); + EmitFastInt(ilGenerator, i); + ilGenerator.Emit(OpCodes.Ldelem_Ref); + EmitCastToReference(ilGenerator, paramTypes[i]); + ilGenerator.Emit(OpCodes.Stloc, locals[i]); + } + + if (!methodInfo.IsStatic) + { + // loads the object into the stack + ilGenerator.Emit(OpCodes.Ldarg_0); + } + + // loads the parameters copied to the local variables into the stack + for (int i = 0; i < paramTypes.Length; i++) + { + if (parameters[i].ParameterType.IsByRef) + ilGenerator.Emit(OpCodes.Ldloca_S, locals[i]); + else + ilGenerator.Emit(OpCodes.Ldloc, locals[i]); + } + + // calls the method + if (!methodInfo.IsStatic) + { + ilGenerator.EmitCall(OpCodes.Callvirt, methodInfo, null); + } + else + { + ilGenerator.EmitCall(OpCodes.Call, methodInfo, null); + } + + // creates code for handling the return value + if (methodInfo.ReturnType == typeof(void)) + { + ilGenerator.Emit(OpCodes.Ldnull); + } + else + { + EmitBoxIfNeeded(ilGenerator, methodInfo.ReturnType); + } + + // iterates through the parameters updating the parameters passed by ref + for (int i = 0; i < paramTypes.Length; i++) + { + if (parameters[i].ParameterType.IsByRef) + { + ilGenerator.Emit(OpCodes.Ldarg_1); + EmitFastInt(ilGenerator, i); + ilGenerator.Emit(OpCodes.Ldloc, locals[i]); + if (locals[i].LocalType.IsValueType) + ilGenerator.Emit(OpCodes.Box, locals[i].LocalType); + ilGenerator.Emit(OpCodes.Stelem_Ref); + } + } + + // returns the value to the caller + ilGenerator.Emit(OpCodes.Ret); + + // converts the DynamicMethod to a FastInvokeHandler delegate to call to the method + FastInvokeHandler invoker = (FastInvokeHandler)dynamicMethod.CreateDelegate(typeof(FastInvokeHandler)); + + dictInvoker.Add(methodInfo, invoker); + + return invoker; + } + } + + /// + /// 用于存放GetInstanceCreator的Dictionary + /// + private static Dictionary dictCreator = new Dictionary(); + + /// Gets the instance creator delegate that can be use to create instances of the specified type. + /// The type of the objects we want to create. + /// A delegate that can be used to create the objects. + public static FastCreateInstanceHandler GetInstanceCreator(Type type) + { + lock (dictCreator) + { + if (dictCreator.ContainsKey(type)) return dictCreator[type]; + + // generates a dynamic method to generate a FastCreateInstanceHandler delegate + DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, type, new Type[0], typeof(DynamicCalls).Module); + + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + // generates code to create a new object of the specified type using the default constructor + ilGenerator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes)); + + // returns the value to the caller + ilGenerator.Emit(OpCodes.Ret); + + // converts the DynamicMethod to a FastCreateInstanceHandler delegate to create the object + FastCreateInstanceHandler creator = (FastCreateInstanceHandler)dynamicMethod.CreateDelegate(typeof(FastCreateInstanceHandler)); + + dictCreator.Add(type, creator); + + return creator; + } + } + + /// + /// 用于存放GetPropertyGetter的Dictionary + /// + private static Dictionary dictGetter = new Dictionary(); + + /// + /// 快速获取成员属性 + /// + /// + /// + public static FastPropertyGetHandler GetPropertyGetter(PropertyInfo propInfo) + { + lock (dictGetter) + { + if (dictGetter.ContainsKey(propInfo)) return dictGetter[propInfo]; + + // generates a dynamic method to generate a FastPropertyGetHandler delegate + DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) }, propInfo.DeclaringType.Module); + + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + // loads the object into the stack + ilGenerator.Emit(OpCodes.Ldarg_0); + + // calls the getter + ilGenerator.EmitCall(OpCodes.Callvirt, propInfo.GetGetMethod(), null); + + // creates code for handling the return value + EmitBoxIfNeeded(ilGenerator, propInfo.PropertyType); + + // returns the value to the caller + ilGenerator.Emit(OpCodes.Ret); + + // converts the DynamicMethod to a FastPropertyGetHandler delegate to get the property + FastPropertyGetHandler getter = (FastPropertyGetHandler)dynamicMethod.CreateDelegate(typeof(FastPropertyGetHandler)); + + dictGetter.Add(propInfo, getter); + + return getter; + } + } + + /// + /// 用于存放SetPropertySetter的Dictionary + /// + private static Dictionary dictSetter = new Dictionary(); + + /// + /// 快速设置成员属性 + /// + /// + /// + public static FastPropertySetHandler GetPropertySetter(PropertyInfo propInfo) + { + lock (dictSetter) + { + if (dictSetter.ContainsKey(propInfo)) return dictSetter[propInfo]; + + // generates a dynamic method to generate a FastPropertySetHandler delegate + DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, null, new Type[] { typeof(object), typeof(object) }, propInfo.DeclaringType.Module); + + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + // loads the object into the stack + ilGenerator.Emit(OpCodes.Ldarg_0); + + // loads the parameter from the stack + ilGenerator.Emit(OpCodes.Ldarg_1); + + // cast to the proper type (unboxing if needed) + EmitCastToReference(ilGenerator, propInfo.PropertyType); + + // calls the setter + ilGenerator.EmitCall(OpCodes.Callvirt, propInfo.GetSetMethod(), null); + + // terminates the call + ilGenerator.Emit(OpCodes.Ret); + + // converts the DynamicMethod to a FastPropertyGetHandler delegate to get the property + FastPropertySetHandler setter = (FastPropertySetHandler)dynamicMethod.CreateDelegate(typeof(FastPropertySetHandler)); + + dictSetter.Add(propInfo, setter); + + return setter; + } + } + + /// Emits the cast to a reference, unboxing if needed. + /// The MSIL generator. + /// The type to cast. + private static void EmitCastToReference(ILGenerator ilGenerator, System.Type type) + { + if (type.IsValueType) + { + ilGenerator.Emit(OpCodes.Unbox_Any, type); + } + else + { + ilGenerator.Emit(OpCodes.Castclass, type); + } + } + + /// Boxes a type if needed. + /// The MSIL generator. + /// The type. + private static void EmitBoxIfNeeded(ILGenerator ilGenerator, System.Type type) + { + if (type.IsValueType) + { + ilGenerator.Emit(OpCodes.Box, type); + } + } + + /// Emits code to save an integer to the evaluation stack. + /// The MSIL generator. + /// The value to push. + private static void EmitFastInt(ILGenerator ilGenerator, int value) + { + // for small integers, emit the proper opcode + switch (value) + { + case -1: + ilGenerator.Emit(OpCodes.Ldc_I4_M1); + return; + case 0: + ilGenerator.Emit(OpCodes.Ldc_I4_0); + return; + case 1: + ilGenerator.Emit(OpCodes.Ldc_I4_1); + return; + case 2: + ilGenerator.Emit(OpCodes.Ldc_I4_2); + return; + case 3: + ilGenerator.Emit(OpCodes.Ldc_I4_3); + return; + case 4: + ilGenerator.Emit(OpCodes.Ldc_I4_4); + return; + case 5: + ilGenerator.Emit(OpCodes.Ldc_I4_5); + return; + case 6: + ilGenerator.Emit(OpCodes.Ldc_I4_6); + return; + case 7: + ilGenerator.Emit(OpCodes.Ldc_I4_7); + return; + case 8: + ilGenerator.Emit(OpCodes.Ldc_I4_8); + return; + } + + // for bigger values emit the short or long opcode + if (value > -129 && value < 128) + { + ilGenerator.Emit(OpCodes.Ldc_I4_S, (SByte)value); + } + else + { + ilGenerator.Emit(OpCodes.Ldc_I4, value); + } + } + } +} + diff --git a/类库/Api.Framework/Easy4/Common/EntityHelper.cs b/类库/Api.Framework/Easy4/Common/EntityHelper.cs new file mode 100644 index 0000000..cdf663d --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/EntityHelper.cs @@ -0,0 +1,694 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Easy4net.CustomAttributes; +using Easy4net.DBUtility; +using System.Reflection; +using System.Data; +using Easy4net.Context; + +namespace Easy4net.Common +{ + /// + /// 实体帮助类 + /// + public static class EntityHelper + { + //public static string GetTableName(Type classType, DbOperateType type) + //{ + // //string strTableName = string.Empty; + // //string strEntityName = string.Empty; + + // //strEntityName = classType.FullName; + + // //object[] attr = classType.GetCustomAttributes(false); + // //if (attr.Length == 0) return strTableName; + + // //foreach (object classAttr in attr) + // //{ + // // if (classAttr is TableAttribute) + // // { + // // TableAttribute tableAttr = classAttr as TableAttribute; + // // strTableName = tableAttr.Name; + // // } + // //} + + // TableAttribute tableAttr = GetTableAttribute(classType, type); + + // //if (string.IsNullOrEmpty(strTableName) && (type == DbOperateType.INSERT || type == DbOperateType.UPDATE || type == DbOperateType.DELETE)) + // //{ + // // throw new Exception("实体类:" + strEntityName + "的属性配置[Table(name=\"tablename\")]错误或未配置"); + // //} + + // return tableAttr.Name; + //} + + /// + /// 根据实体类类型和数据操作类型获取数据库表特性 + /// + /// 数据库表实例类型 + /// 数据操作类型 + /// 数据库表特性 + public static TableAttribute GetTableAttribute(Type classType, DbOperateType type) + { + TableAttribute tableAttr = null; + //string strTableName = string.Empty; + string strEntityName = string.Empty; + + strEntityName = classType.FullName; + + object[] attr = classType.GetCustomAttributes(false); + if (attr.Length == 0) return null; + + foreach (object classAttr in attr) + { + if (classAttr is TableAttribute) + { + tableAttr = classAttr as TableAttribute; + //atrTableName = tableAttr.Name; + } + } + + if (tableAttr == null && (type == DbOperateType.INSERT || type == DbOperateType.UPDATE || type == DbOperateType.DELETE)) + { + throw new Exception("实体类:" + strEntityName + "的属性配置[Table(name=\"tablename\")]错误或未配置"); + } + + return tableAttr; + } + + /// + /// 根据主键特性跟数据操作类型获取主键名 + /// + /// IdAttribute主键特性 + /// 数据操作类型 + /// 主键名 + public static string GetPrimaryKey(object attribute, DbOperateType type) + { + string strPrimary = string.Empty; + IdAttribute attr = attribute as IdAttribute; + if (type == DbOperateType.INSERT) + { + switch (attr.Strategy) + { + case GenerationType.INDENTITY: + break; + case GenerationType.GUID: + strPrimary = System.Guid.NewGuid().ToString(); + break; + } + } + else { + strPrimary = attr.Name; + } + + return strPrimary; + } + + /// + /// 根据字段特性或主键特性获取对应字段名 + /// + /// 字段特性或主键特性 + /// 字段名 + public static string GetColumnName(object attribute) + { + string columnName = string.Empty; + if (attribute is ColumnAttribute) + { + ColumnAttribute columnAttr = attribute as ColumnAttribute; + columnName = columnAttr.Name; + } + if (attribute is IdAttribute) + { + IdAttribute idAttr = attribute as IdAttribute; + columnName = idAttr.Name; + } + + return columnName; + } + + /// + /// 根据数据库表对象及数据操作类型获取表信息 + /// + /// 数据库表对象 + /// 操作类型 + /// 数据库表对象属性集合 + /// 数据库表信息 + public static TableInfo GetTableInfo(object entity, DbOperateType dbOpType, PropertyInfo[] properties) + { + bool breakForeach = false; + string strPrimaryKey = string.Empty; + TableInfo tableInfo = new TableInfo(); + Type type = entity.GetType(); + + TableAttribute tableAttr = GetTableAttribute(type, dbOpType); + if (tableAttr != null) + { + tableInfo.TableName = tableAttr.Name; + tableInfo.NoAutomaticKey = tableAttr.NoAutomaticKey; + } + else + { + tableInfo.TableName = type.Name; + } + + //tableInfo.TableName = GetTableName(type, dbOpType); + + if (dbOpType == DbOperateType.COUNT) + { + return tableInfo; + } + + foreach (PropertyInfo property in properties) + { + object propvalue = null; + string columnName = string.Empty; + string propName = columnName = property.Name; + + propvalue = ReflectionHelper.GetPropertyValue(entity, property); + + object[] propertyAttrs = property.GetCustomAttributes(false); + for (int i = 0; i < propertyAttrs.Length; i++) + { + object propertyAttr = propertyAttrs[i]; + if (!(propertyAttr is ColumnAttribute) && !(propertyAttr is IdAttribute)) + { + continue; + } + + if (EntityHelper.IsCaseColumn(propertyAttr, dbOpType)) + { + breakForeach = true;break; + } + + string tempVal = GetColumnName(propertyAttr); + columnName = tempVal == string.Empty ? propName : tempVal; + + if (propertyAttr is IdAttribute) + { + IdAttribute idAttr = propertyAttr as IdAttribute; + tableInfo.Strategy = idAttr.Strategy; + + if (dbOpType == DbOperateType.INSERT || dbOpType == DbOperateType.DELETE) + { + if (CommonUtils.IsNullOrEmpty(propvalue)) + { + strPrimaryKey = EntityHelper.GetPrimaryKey(propertyAttr, dbOpType); + if (!string.IsNullOrEmpty(strPrimaryKey)) + propvalue = strPrimaryKey; + } + } + + tableInfo.Id.Key = columnName; + tableInfo.Id.Value = propvalue; + tableInfo.PropToColumn.Put(propName, columnName); + tableInfo.ColumnToProp.Put(columnName, propName); + breakForeach = true; + } + } + + if (breakForeach && dbOpType == DbOperateType.DELETE) break; + if (breakForeach) { breakForeach = false; continue; } + tableInfo.Columns.Put(columnName, propvalue); + tableInfo.PropToColumn.Put(propName, columnName); + tableInfo.ColumnToProp.Put(columnName, propName); + } + + if (tableInfo.Strategy != GenerationType.INDENTITY && tableInfo.Id.Key != null) + { + tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value); + } + + /*if (dbOpType == DbOperateType.UPDATE) + { + tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value); + }*/ + + return tableInfo; + } + + /// + /// 根据数据库表对象获取该对象中主键成员的属性 + /// + /// 数据库表对象 + /// 该对象的属性集合 + /// 主键成员属性 + public static PropertyInfo GetPrimaryKeyPropertyInfo(object entity, PropertyInfo[] properties) + { + bool breakForeach = false; + Type type = entity.GetType(); + PropertyInfo properyInfo = null; + + foreach (PropertyInfo property in properties) + { + string columnName = string.Empty; + string propName = columnName = property.Name; + + object[] propertyAttrs = property.GetCustomAttributes(false); + for (int i = 0; i < propertyAttrs.Length; i++) + { + object propertyAttr = propertyAttrs[i]; + + if (propertyAttr is IdAttribute) + { + properyInfo = property; + breakForeach = true; + break; + } + } + if (breakForeach) break; + } + + return properyInfo; + } + + /// + /// 根据数据库表信息从DataReader中读取对应实体类的数据集合 + /// + /// 数据库表实体类 + /// DataReader + /// 数据库表信息 + /// 实体类属性集合 + /// + public static List toList(IDataReader sdr, TableInfo tableInfo, PropertyInfo[] properties) where T : new() + { + List list = new List(); + + while (sdr.Read()) + { + T entity = new T(); + foreach (PropertyInfo property in properties) + { + if (EntityHelper.IsCaseColumn(property, DbOperateType.SELECT)) continue; + + String name = tableInfo.PropToColumn[property.Name].ToString(); + ReflectionHelper.SetPropertyValue(entity, property, sdr[name]); + } + list.Add(entity); + } + + return list; + } + + /// + /// 从DataReader中读取指定数据库表类型的数据集合 + /// + /// 数据库表实体类 + /// DataReader + /// + public static List toList(IDataReader sdr) where T : new() + { + List list = new List(); + PropertyInfo[] properties = ReflectionHelper.GetProperties(new T().GetType()); + + while (sdr.Read()) + { + T entity = new T(); + foreach (PropertyInfo property in properties) + { + String name = property.Name; + ReflectionHelper.SetPropertyValue(entity, property, sdr[name]); + } + list.Add(entity); + } + + return list; + } + + /// + /// 根据数据库表信息及条件生成器获取Select语句 + /// + /// 数据库表信息 + /// 条件生成器 + /// + public static string GetFindSql(TableInfo tableInfo, DbCondition condition) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + string dbParmChar = dbFactory.DbParmChar; + + StringBuilder sbColumns = new StringBuilder(); + + tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value); + foreach (String key in tableInfo.Columns.Keys) + { + string nKey = DbKeywords.FormatColumnName(key.Trim(), dbFactory.DbType); + sbColumns.Append(nKey).Append(","); + } + + if (sbColumns.Length > 0) sbColumns.Remove(sbColumns.ToString().Length - 1, 1); + + string strSql = String.Empty; + if (String.IsNullOrEmpty(condition.queryString)) { + strSql = "SELECT {0} FROM {1}"; + strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName); + strSql += condition.ToString(); + } + else { + strSql = condition.ToString(); + } + + strSql = strSql.ToUpper(); + + return strSql; + } + + /// + /// 根据数据库表信息获取Selet All语句 + /// + /// 数据库表信息 + /// + public static string GetFindAllSql(TableInfo tableInfo) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + string dbParmChar = dbFactory.DbParmChar; + + StringBuilder sbColumns = new StringBuilder(); + + tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value); + foreach (String key in tableInfo.Columns.Keys) + { + string nKey = DbKeywords.FormatColumnName(key.Trim(), dbFactory.DbType); + sbColumns.Append(nKey).Append(","); + } + + if (sbColumns.Length > 0) sbColumns.Remove(sbColumns.ToString().Length - 1, 1); + + string strSql = "SELECT {0} FROM {1}"; + strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName); + + return strSql; + } + + /// + /// 根据数据库表信息获取根据主键值进行查询的SQL语句 + /// + /// 数据库表信息 + /// + public static string GetFindByIdSql(TableInfo tableInfo) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + string dbParmChar = dbFactory.DbParmChar; + + StringBuilder sbColumns = new StringBuilder(); + + if (tableInfo.Columns.ContainsKey(tableInfo.Id.Key)) + tableInfo.Columns[tableInfo.Id.Key] = tableInfo.Id.Value; + else + tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value); + + foreach (String key in tableInfo.Columns.Keys) + { + string nKey = DbKeywords.FormatColumnName(key.Trim(), dbFactory.DbType); + sbColumns.Append(nKey).Append(","); + } + + if (sbColumns.Length > 0) sbColumns.Remove(sbColumns.ToString().Length - 1, 1); + + string strSql = "SELECT {0} FROM {1} WHERE {2} = " + dbParmChar + "{2}"; + strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName, tableInfo.Id.Key); + + return strSql; + } + + /// + /// 根据数据库表信息获取查询记录条数的SQL语句 + /// + /// 数据库表信息 + /// + public static string GetFindCountSql(TableInfo tableInfo) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + string dbParmChar = dbFactory.DbParmChar; + + StringBuilder sbColumns = new StringBuilder(); + + string strSql = "SELECT COUNT(0) FROM {1} "; + strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName); + + foreach (String key in tableInfo.Columns.Keys) + { + string nKey = DbKeywords.FormatColumnName(key.Trim(), dbFactory.DbType); + sbColumns.Append(nKey).Append("=").Append(dbParmChar).Append(key); + } + + if (sbColumns.Length > 0) + { + strSql += " WHERE " + sbColumns.ToString(); + } + + return strSql; + } + + /// + /// 根据数据库表信息及条件生成器获取查询记录条数的SQL语句 + /// + /// 数据库表信息 + /// 条件生成器 + /// + public static string GetFindCountSql(TableInfo tableInfo, DbCondition condition) + { + string strSql = "SELECT COUNT(0) FROM {0}"; + strSql = string.Format(strSql, tableInfo.TableName); + strSql += condition.ToString(); + + return strSql; + } + + /// + /// 根据数据库表信息获取根据主键值进行查询的SQL语句 + /// 同方法GetFindByIdSql + /// + /// + /// + public static string GetFindByPropertySql(TableInfo tableInfo) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + string dbParmChar = dbFactory.DbParmChar; + + StringBuilder sbColumns = new StringBuilder(); + + tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value); + foreach (String key in tableInfo.Columns.Keys) + { + string nKey = DbKeywords.FormatColumnName(key.Trim(), dbFactory.DbType); + sbColumns.Append(nKey).Append(","); + } + + if (sbColumns.Length > 0) sbColumns.Remove(sbColumns.ToString().Length - 1, 1); + + string strSql = "SELECT {0} FROM {1} WHERE {2} = " + dbParmChar + "{2}"; + strSql = string.Format(strSql, sbColumns.ToString(), tableInfo.TableName, tableInfo.Id.Key); + + return strSql; + } + + /// + /// 根据数据库类型获取对应的获取在插入操作后自增长型主键字段的SQL语句 + /// + /// 数据库类型 + /// + public static string GetAutoSql(DatabaseType dbType) + { + string autoSQL = ""; + if (dbType == DatabaseType.SQLSERVER) + { + autoSQL = " select scope_identity() as AutoId "; + } + else if (dbType == DatabaseType.ACCESS) + { + autoSQL = " select @@IDENTITY as AutoId "; + } + + else if (dbType == DatabaseType.MYSQL) + { + autoSQL = " ;select @@identity "; + } + + else if (dbType == DatabaseType.SQLITE) + { + autoSQL = " ;select last_insert_rowid() as AutoId "; + } + + return autoSQL; + } + + /// + /// 根据数据库表信息获取Insert插入操作语句 + /// + /// + /// + public static string GetInsertSql(TableInfo tableInfo) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + string dbParmChar = dbFactory.DbParmChar; + + StringBuilder sbColumns = new StringBuilder(); + StringBuilder sbValues = new StringBuilder(); + + if(tableInfo.Strategy != GenerationType.INDENTITY) + { + if (tableInfo.Strategy == GenerationType.GUID && tableInfo.Id.Value == null) + { + tableInfo.Id.Value = Guid.NewGuid().ToString(); + } + + if (tableInfo.Id.Value != null) + { + tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value); + } + } + + foreach (String key in tableInfo.Columns.Keys) + { + Object value = tableInfo.Columns[key]; + if (!string.IsNullOrEmpty(key.Trim()) && value != null) + { + string nKey = DbKeywords.FormatColumnName(key.Trim(), dbFactory.DbType); + sbColumns.Append(nKey).Append(","); + sbValues.Append(dbParmChar).Append(key).Append(","); + } + } + + if (sbColumns.Length > 0 && sbValues.Length > 0) + { + sbColumns.Remove(sbColumns.ToString().Length - 1, 1); + sbValues.Remove(sbValues.ToString().Length - 1, 1); + } + + string strSql = "INSERT INTO {0}({1}) VALUES({2})"; + strSql = string.Format(strSql, tableInfo.TableName, sbColumns.ToString(), sbValues.ToString()); + + + if (!tableInfo.NoAutomaticKey) + { + if (dbFactory.DbType == DatabaseType.SQLSERVER || dbFactory.DbType == DatabaseType.MYSQL || dbFactory.DbType == DatabaseType.SQLITE) + { + string autoSql = EntityHelper.GetAutoSql(dbFactory.DbType); + strSql = strSql + autoSql; + } + } + + return strSql; + } + + /// + /// 根据数据库表信息获取Update更新操作语句 + /// + /// + /// + public static string GetUpdateSql(TableInfo tableInfo) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + string dbParmChar = dbFactory.DbParmChar; + + StringBuilder sbBody = new StringBuilder(); + + foreach (String key in tableInfo.Columns.Keys) + { + Object value = tableInfo.Columns[key]; + if (!string.IsNullOrEmpty(key.Trim()) && value != null) + { + string nKey = DbKeywords.FormatColumnName(key.Trim(), dbFactory.DbType); + sbBody.Append(nKey).Append("=").Append(dbParmChar).Append(key).Append(","); + } + } + + if (sbBody.Length > 0) sbBody.Remove(sbBody.ToString().Length - 1, 1); + + //tableInfo.Columns.Put(tableInfo.Id.Key, tableInfo.Id.Value); + + string strSql = "update {0} set {1} where {2} =" + dbParmChar + tableInfo.Id.Key; + strSql = string.Format(strSql, tableInfo.TableName, sbBody.ToString(), tableInfo.Id.Key); + + return strSql; + } + + /// + /// 根据数据库表信息获取根据主键进行Delete删除操作语句 + /// + /// + /// + public static string GetDeleteByIdSql(TableInfo tableInfo) + { + DbFactory dbFactory = SessionThreadLocal.Get().DbFactory; + string dbParmChar = dbFactory.DbParmChar; + + string strSql = "delete from {0} where {1} =" + dbParmChar + tableInfo.Id.Key; + strSql = string.Format(strSql, tableInfo.TableName, tableInfo.Id.Key); + + return strSql; + } + + /// + /// 将字段信息集合设置到参数数组中 + /// + /// 字段信息集合 + /// [输出] 参数值集合 + public static void SetParameters(ColumnInfo columns, params IDbDataParameter[] parms) + { + int i = 0; + foreach (string key in columns.Keys) + { + if (!string.IsNullOrEmpty(key.Trim())) + { + object value = columns[key]; + if (value != null) + { + parms[i].ParameterName = key; + parms[i].Value = value; + i++; + } + } + } + } + + /// + /// 根据操作类型判断输入的字段特性中指定的字段是否进行忽略 + /// + /// 字段特性ColumnAttribute,如果不为此特性则不进行忽略检测 + /// 操作类型 + /// true忽略此字段 + public static bool IsCaseColumn(object attribute, DbOperateType dbOperateType) + { + if (attribute is ColumnAttribute) + { + ColumnAttribute columnAttr = attribute as ColumnAttribute; + if (columnAttr.Ignore) + { + return true; + } + if (!columnAttr.IsInsert && dbOperateType == DbOperateType.INSERT) + { + return true; + } + if (!columnAttr.IsUpdate && dbOperateType == DbOperateType.UPDATE) + { + return true; + } + } + + return false; + } + + /// + /// 根据操作类型判断输入的成员属性中指定的成员是否进行忽略 + /// + /// 成员属性 + /// 数据操作 + /// true忽略此属性中的成员 + public static bool IsCaseColumn(PropertyInfo property, DbOperateType dbOperateType) + { + bool isBreak = false; + object[] propertyAttrs = property.GetCustomAttributes(false); + foreach (object propertyAttr in propertyAttrs) + { + if (EntityHelper.IsCaseColumn(propertyAttr, DbOperateType.SELECT)) + { + isBreak = true; break; + } + } + + return isBreak; + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/Field.cs b/类库/Api.Framework/Easy4/Common/Field.cs new file mode 100644 index 0000000..8055c6c --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/Field.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Easy4net.Common +{ + public class Field + { + private String fieldName; + + //不允许不传参数的构造函数 + private Field() { } + public Field(String name) + { + fieldName = name; + } + + public static WhereExpression operator ==(Field field, Object value) + { + return null; + } + + public static WhereExpression operator !=(Field field, Object value) + { + return null; + } + + public static WhereExpression operator >(Field field, Object value) + { + return null; + } + + public static WhereExpression operator >=(Field field, Object value) + { + return null; + } + + public static WhereExpression operator <(Field field, Object value) + { + return null; + } + + public static WhereExpression operator <=(Field field, Object value) + { + return null; + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/IdInfo.cs b/类库/Api.Framework/Easy4/Common/IdInfo.cs new file mode 100644 index 0000000..ece2531 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/IdInfo.cs @@ -0,0 +1,37 @@ +using System; + +namespace Easy4net.Common +{ + /// + /// 主键字段信息 + /// + public class IdInfo + { + /// + /// 主键字段名 + /// + private String key; + /// + /// 主键字段值 + /// + private Object value; + + /// + /// 主键字段名 + /// + public String Key + { + get { return key; } + set { key = value; } + } + + /// + /// 主键字段值 + /// + public Object Value + { + get { return this.value; } + set { this.value = value; } + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/Map.cs b/类库/Api.Framework/Easy4/Common/Map.cs new file mode 100644 index 0000000..442ca3f --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/Map.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; + +namespace Easy4net.Common +{ + /// + /// 键值对映射类 + /// + public class Map : Hashtable + { + /// + /// 设置/添加键值对 + /// + /// + /// + public void Put(object key,object value) + { + if (this.ContainsKey(key)) this.Remove(key); + base.Add(key, value); + } + + /// + /// 设置/添加参数 + /// + /// + /// + public void setParameter(string key, object value) + { + if (this.ContainsKey(key)) this.Remove(key); + base.Add(key, value); + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/PageResult.cs b/类库/Api.Framework/Easy4/Common/PageResult.cs new file mode 100644 index 0000000..e5497b1 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/PageResult.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +namespace Easy4net.Common +{ + /// + /// 分页查询结果 + /// + /// 数据库表实体类 + public class PageResult + { + /// + /// 分页查询中总记录数 + /// + public int Total {get; set;} + + /// + /// 分页查询中结果集合 + /// + public List DataList {get; set;} + } +} diff --git a/类库/Api.Framework/Easy4/Common/ParamMap.cs b/类库/Api.Framework/Easy4/Common/ParamMap.cs new file mode 100644 index 0000000..9d08d1f --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/ParamMap.cs @@ -0,0 +1,337 @@ +using System; +using System.Collections.Generic; +using System.Data; +using Easy4net.DBUtility; +using Easy4net.Context; + +namespace Easy4net.Common +{ + /// + /// 参数映射集合类 + /// + public class ParamMap : Map + { + /// + /// 是否分页 + /// + private bool isPage; + /// + /// 页面偏移量 + /// + private int pageOffset; + /// + /// 每页限制记录数 + /// + private int pageLimit; + /// + /// 排序字段 + /// + private string orderFields; + /// + /// 是否递减排序 + /// + private bool isDesc = true; + + /// + /// 数据库参数集合 + /// + private List m_ParamList = new List(); + + /// + /// 创建一个参数映射集合 + /// + private ParamMap() { } + + /// + /// 排序的字段 + /// + public string OrderFields + { + get { return orderFields; } + set { orderFields = value; } + } + + /// + /// 是否递减排序 + /// + public bool IsDesc + { + get { return isDesc; } + set { isDesc = value; } + } + + /// + /// 创建一个参数映射集合 + /// + /// + public static ParamMap NewMap() + { + ParamMap paramMap = new ParamMap(); + return paramMap; + } + + /// + /// 是否进行分页 + /// + public bool IsPage + { + get + { + return isPage; + } + } + + /// + /// 每页的偏移量 + /// + public int PageOffset + { + get + { + if (this.ContainsKey("pageIndex") && this.ContainsKey("pageSize")) + { + int pageIndex = this.getInt("pageIndex"); + int pageSize = this.getInt("pageSize"); + if (pageIndex <= 0) pageIndex = 1; + if (pageSize <= 0) pageSize = 1; + + return (pageIndex - 1) * pageSize; + } + + return 0; + } + } + + /// + /// 每页的记录条数限制 + /// + public int PageLimit + { + get + { + if (this.ContainsKey("pageSize")) + { + return this.getInt("pageSize"); + } + + return 0; + } + } + + /// + /// 根据键值获取整型数据 + /// + /// + /// + public int getInt(string key) + { + var value = this[key]; + return Convert.ToInt32(value); + } + + /// + /// 根据键值获取字符串数据 + /// + /// + /// + public String getString(string key) + { + var value = this[key]; + return Convert.ToString(value); + } + + /// + /// 根据键值获取Double型数据 + /// + /// + /// + public Double toDouble(string key) + { + var value = this[key]; + return Convert.ToDouble(value); + } + + /// + /// 根据键值获取Long型数据 + /// + /// + /// + public Int64 toLong(string key) + { + var value = this[key]; + return Convert.ToInt64(value); + } + + /// + /// 根据键值获取Decimal型数据 + /// + /// + /// + public Decimal toDecimal(string key) + { + var value = this[key]; + return Convert.ToDecimal(value); + } + + /// + /// 根据键值获取DateTime型数据 + /// + /// + /// + public DateTime toDateTime(string key) + { + var value = this[key]; + return Convert.ToDateTime(value); + } + + /// + /// 设置排序字段及排序方式 + /// + /// 排序字段 + /// 是否为递减排序 + public void setOrderFields(string orderFields, bool isDesc) + { + this.orderFields = orderFields; + this.isDesc = isDesc; + } + + /// + /// 此方法已过时,请使用 setPageParamters方法分页 + /// + /// + [Obsolete("此方法已过时,请使用 setPageParamters方法分页")] + private void setPageIndex(int pageIndex) + { + this["pageIndex"] = pageIndex; + setPages(); + } + + /// + /// 此方法已过时,请使用 setPageParamters方法分页 + /// + /// + [Obsolete("此方法已过时,请使用 setPageParamters方法分页")] + private void setPageSize(int pageSize) + { + this["pageSize"] = pageSize; + setPages(); + } + + /// + /// 分页参数设置 + /// + /// 第几页,从0开始 + /// 每页最多显示几条数据 + public void setPageParamters(int page, int limit) + { + this["pageIndex"] = page; + this["pageSize"] = limit; + setPages(); + } + + /// + /// 设置分页参数 + /// + private void setPages() + { + Session session = SessionThreadLocal.Get(); + + if (this.ContainsKey("pageIndex") && this.ContainsKey("pageSize")) + { + this.isPage = true; + if (session.DbFactory.DbType == DatabaseType.MYSQL || session.DbFactory.DbType == DatabaseType.SQLITE) + { + this["offset"] = this.PageOffset; + this["limit"] = this.PageLimit; + + this.Remove("pageIndex"); + this.Remove("pageSize"); + + this.Add("offset", this.getInt("offset")); + this.Add("limit", this.getInt("limit")); + } + + if (session.DbFactory.DbType == DatabaseType.SQLSERVER) + { + int pageIndex = this.getInt("pageIndex"); + int pageSize = this.getInt("pageSize"); + if (pageIndex <= 0) pageIndex = 1; + if (pageSize <= 0) pageSize = 1; + + this["pageStart"] = (pageIndex - 1) * pageSize + 1; + this["pageEnd"] = pageIndex * pageSize; + + this.Remove("pageIndex"); + this.Remove("pageSize"); + + this.Add("pageStart", this.getInt("pageStart")); + this.Add("pageEnd", this.getInt("pageEnd")); + } + + if (session.DbFactory.DbType == DatabaseType.ACCESS) + { + int pageIndex = this.getInt("pageIndex"); + int pageSize = this.getInt("pageSize"); + + this["page_offset"] = pageIndex * pageSize; + this["page_limit"] = pageSize; + + this.Remove("pageIndex"); + this.Remove("pageSize"); + } + } + } + + /// + /// 添加键值对映射 + /// + /// + /// + public override void Add(object key, object value) + { + base.Put(key, value); + + Session session = SessionThreadLocal.Get(); + + IDbDataParameter param = session.DbFactory.CreateDbParameter(key.ToString(), value); + m_ParamList.Add(param); + } + + /// + /// 添加键值对映射 + /// + /// + /// + public new void Put(object key, object value) + { + this.Add(key, value); + } + + /// + /// 添加键值对映射 + /// + /// + /// + public new void setParameter(string key, object value) + { + this.Add(key, value); + } + + /// + /// 输出参数集合 + /// + /// + public IDbDataParameter[] toDbParameters() + { + int i = 0; + IDbDataParameter[] paramArr = new IDbDataParameter[m_ParamList.Count]; + foreach (IDbDataParameter dbParameter in m_ParamList) + { + paramArr[i] = dbParameter; + i++; + } + + return paramArr; + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/ReflectionHelper.cs b/类库/Api.Framework/Easy4/Common/ReflectionHelper.cs new file mode 100644 index 0000000..586516e --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/ReflectionHelper.cs @@ -0,0 +1,218 @@ +using System; +using System.Reflection; + +namespace Easy4net.Common +{ + /// + /// 实体类反射帮助类 + /// + public static class ReflectionHelper + { + /// + /// 根据输入类型获取对应的成员属性集合 + /// + /// + /// + public static PropertyInfo[] GetProperties(Type type) + { + return type.GetProperties(BindingFlags.Public | BindingFlags.Instance); + } + + /// + /// 根据输入类型获取对应的字段属性集合 + /// + /// + /// + public static FieldInfo[] GetFields(Type type) + { + return type.GetFields(BindingFlags.Public | BindingFlags.Instance); + } + + #region 快速执行方法 + /// + /// 快速执行Method + /// + /// + /// + /// + /// + public static object FastMethodInvoke(object obj, MethodInfo method, params object[] parameters) + { + return DynamicCalls.GetMethodInvoker(method)(obj, parameters); + } + + /// + /// 快速实例化一个T + /// + /// + /// + public static T Create() + { + return (T)Create(typeof(T))(); + } + + /// + /// 快速实例化一个FastCreateInstanceHandler + /// + /// + /// + public static FastCreateInstanceHandler Create(Type type) + { + return DynamicCalls.GetInstanceCreator(type); + } + #endregion + + #region 设置属性值 + /// + /// 设置属性值 + /// + /// + /// + /// + public static void SetPropertyValue(object obj, PropertyInfo property, object value) + { + if (property.CanWrite) + { + var propertySetter = DynamicCalls.GetPropertySetter(property); + value = TypeUtils.ConvertForType(value, property.PropertyType); + if (value != null) + { + propertySetter(obj, value); + } + } + } + + /// + /// 设置属性值 + /// + /// + /// + /// + public static void SetPropertyValue(object obj, string propertyName, object value) + { + SetPropertyValue(obj.GetType(), obj, propertyName, value); + } + + /// + /// 设置属性值 + /// + /// + /// + /// + /// + public static void SetPropertyValue(Type type, object obj, string propertyName, object value) + { + PropertyInfo property = type.GetProperty(propertyName); + if (property != null) + { + SetPropertyValue(obj, property, value); + } + } + + /// + /// 获取属性值 + /// + /// + /// + /// + /// + public static object GetPropertyValue(T entity, string propertyName) + { + PropertyInfo property = entity.GetType().GetProperty(propertyName); + if (property != null) + { + return property.GetValue(entity, null); + } + + return null; + } + + /// + /// 获取属性值 + /// + /// + /// + /// + /// + public static object GetPropertyValue(T entity, PropertyInfo property) + { + if (property != null) + { + return property.GetValue(entity, null); + } + + return null; + } + + /// + /// 获取属性类型 + /// + /// + /// + /// + public static Type GetPropertyType(Type classType, string propertyName) + { + PropertyInfo property = classType.GetProperty(propertyName); + if (property != null) + { + return property.PropertyType; + } + + return null; + } + + + + #endregion + + /*public static void SetPropertyValue(Object obj, PropertyInfo property, Object value) + { + + //创建Set委托 + SetHandler setter = DynamicMethodCompiler.CreateSetHandler(obj.GetType(),property); + + //先获取该私有成员的数据类型 + Type type = property.PropertyType; + + //通过数据类型转换 + value = TypeUtils.ConvertForType(value, type); + + //将值设置到对象中 + setter(obj, value); + } + + public static Object GetPropertyValue(Object obj, PropertyInfo property) + { + //创建Set委托 + GetHandler getter = DynamicMethodCompiler.CreateGetHandler(obj.GetType(), property); + + //获取属性值 + return getter(obj); + + } + + public static void SetFieldValue(Object obj, FieldInfo field, Object value) + { + //创建Set委托 + SetHandler setter = DynamicMethodCompiler.CreateSetHandler(obj.GetType(), field); + + //先获取该私有成员的数据类型 + Type type = field.FieldType; + + //通过数据类型转换 + value = TypeUtils.ConvertForType(value, type); + + //将值设置到对象中 + setter(obj, value); + } + + public static Object GetFieldValue(Object obj, FieldInfo field) + { + //创建Set委托 + GetHandler getter = DynamicMethodCompiler.CreateGetHandler(obj.GetType(), field); + + //获取字段值 + return getter(obj); + }*/ + } +} diff --git a/类库/Api.Framework/Easy4/Common/SQLBuilderHelper.cs b/类库/Api.Framework/Easy4/Common/SQLBuilderHelper.cs new file mode 100644 index 0000000..cdc5e93 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/SQLBuilderHelper.cs @@ -0,0 +1,318 @@ +using System; +using Easy4net.DBUtility; +using System.Data; +using Easy4net.Context; + +namespace Easy4net.Common +{ + /// + /// SQL语句创建帮助类 + /// + public static class SQLBuilderHelper + { + /// + /// MSSQL分页语句模版 + /// + private static string mssqlPageTemplate = "select * from (select ROW_NUMBER() OVER(order by {0}) AS RowNumber, {1}) as tmp_tbl where RowNumber BETWEEN @pageStart and @pageEnd "; + /// + /// MySQL排序分页语句模版 + /// + private static string mysqlOrderPageTemplate = "{0} order by {1} limit ?offset,?limit"; + /// + /// MySQL分页语句模板 + /// + private static string mysqlPageTemplate = "{0} limit ?offset,?limit"; + /// + /// SQLite排序分页语句模板 + /// + private static string sqliteOrderPageTemplate = "{0} order by {1} limit @offset,@limit"; + /// + /// SQLite分页语句模板 + /// + private static string sqlitePageTemplate = "{0} limit @offset,@limit"; + /// + /// ACCESS分页语句模板 + /// + private static string accessPageTemplate = "select * from (select top @page_limit * from (select top @page_offset {0} order by id desc) order by id) order by {1}"; + + /// + /// 从SQL语句中获取查询的列名集合 + /// Select 与 From中间的部分 + /// + /// + /// + public static string fetchColumns(string strSQL) + { + string lowerSQL = strSQL.ToLower(); + String columns = lowerSQL.Substring(6, lowerSQL.IndexOf("from") - 6); + return columns; + } + + /// + /// 从SQL语句中获取分页语句 + /// + /// + /// + public static string fetchPageBody(string strSQL) + { + string body = strSQL.Substring(6, strSQL.Length - 6); + return body; + } + + /// + /// 从SQL语句中获取查询语句 + /// + /// + /// + public static string fetchWhere(string strSQL) + { + int index = strSQL.LastIndexOf("where"); + if (index == -1) return ""; + + String where = strSQL.Substring(index, strSQL.Length - index); + return where; + } + + /// + /// 根据SQL语句判断是否为分页语句 + /// + /// + /// + public static bool isPage(string strSQL) + { + string strSql = strSQL.ToLower(); + Session session = SessionThreadLocal.Get(); + + if (session.DbFactory.DbType == DatabaseType.ACCESS && strSql.IndexOf("top") == -1) + { + return false; + } + + if (session.DbFactory.DbType == DatabaseType.SQLSERVER && strSql.IndexOf("row_number()") == -1) + { + return false; + } + + if (session.DbFactory.DbType == DatabaseType.MYSQL && strSql.IndexOf("limit") == -1) + { + return false; + } + + if (session.DbFactory.DbType == DatabaseType.SQLITE && strSql.IndexOf("limit") == -1) + { + return false; + } + + if (session.DbFactory.DbType == DatabaseType.ORACLE && strSql.IndexOf("rowid") == -1) + { + return false; + } + + return true; + } + + /// + /// 根据SQL语句及排序条件创建分页语句 + /// + /// SQL语句 + /// 排序字段 + /// 是否为递减排序 + /// + public static string builderPageSQL(string strSql, string order, bool desc) + { + Session session = SessionThreadLocal.Get(); + + string columns = fetchColumns(strSql); + string orderBy = order + (desc ? " desc " : " asc "); + + + if (session.DbFactory.DbType == DatabaseType.SQLSERVER && strSql.IndexOf("row_number()") == -1) + { + if (string.IsNullOrEmpty(order)) + { + throw new Exception(" SqlException: order field is null, you must support the order field for sqlserver page. "); + } + + string pageBody = fetchPageBody(strSql); + strSql = string.Format(mssqlPageTemplate, orderBy, pageBody); + } + + if (session.DbFactory.DbType == DatabaseType.ACCESS && strSql.IndexOf("top") == -1) + { + if (string.IsNullOrEmpty(order)) + { + throw new Exception(" SqlException: order field is null, you must support the order field for sqlserver page. "); + } + + //select {0} from (select top @pageSize {1} from (select top @pageSize*@pageIndex {2} from {3} order by {4}) order by id) order by {5} + string pageBody = fetchPageBody(strSql); + strSql = string.Format(accessPageTemplate, pageBody, orderBy); + } + + if (session.DbFactory.DbType == DatabaseType.MYSQL) + { + if (!string.IsNullOrEmpty(order)) + { + strSql = string.Format(mysqlOrderPageTemplate, strSql, orderBy); + } + else + { + strSql = string.Format(mysqlPageTemplate, strSql); + } + } + + if (session.DbFactory.DbType == DatabaseType.SQLITE) + { + if (!string.IsNullOrEmpty(order)) + { + strSql = string.Format(sqliteOrderPageTemplate, strSql, orderBy); + } + else + { + strSql = string.Format(sqlitePageTemplate, strSql); + } + } + + return strSql; + } + + /// + /// 根据SQL语句创建一个获取记录数的SQL语句 + /// + /// + /// + public static string builderCountSQL(string strSQL) + { + int index = strSQL.IndexOf("from"); + string strFooter = strSQL.Substring(index, strSQL.Length - index); + string strText = "select count(*) " + strFooter; + + return strText; + } + + /// + /// 创建ACCESS数据库的分页SQL语句 + /// + /// + /// 参数集合 + /// + public static string builderAccessPageSQL(string strSql, ParamMap param) + { + return builderAccessPageSQL(strSql, param, -1); + } + + /// + /// 创建ACCESS的分页SQL语句 + /// + /// + /// 参数集合 + /// 每页记录数 + /// + public static string builderAccessPageSQL(string strSql, ParamMap param, int limit) + { + Session session = SessionThreadLocal.Get(); + + if (session.DbFactory.DbType != DatabaseType.ACCESS) + { + return strSql; + } + + if (param.ContainsKey("page_limit")) + { + if (limit != -1) + { + strSql = strSql.Replace("@" + "page_limit", limit.ToString()); + } + else + { + strSql = strSql.Replace("@" + "page_limit", param.getString("page_limit")); + } + param.Remove("page_limit"); + } + + if (param.ContainsKey("page_offset")) + { + strSql = strSql.Replace("@" + "page_offset", param.getString("page_offset")); + param.Remove("page_offset"); + } + + return strSql; + } + + /// + /// 创建ACCESS的SQL语句 + /// + /// 数据库表实体对象类型 + /// 表信息 + /// SQL语句 + /// 参数集合 + /// + public static string builderAccessSQL(Type classType, TableInfo tableInfo, string strSql, IDbDataParameter[] parameters) + { + Session session = SessionThreadLocal.Get(); + + if (session.DbFactory.DbType != DatabaseType.ACCESS) + { + return strSql; + } + + foreach (IDbDataParameter param in parameters) + { + if (param.Value == null) continue; + + string paramName = param.ParameterName; + string paramValue = param.Value.ToString(); + + float i = 0; + if (tableInfo.ColumnToProp.ContainsKey(paramName)) + { + string propertyName = tableInfo.ColumnToProp[paramName].ToString(); + Type type = ReflectionHelper.GetPropertyType(classType, propertyName); + + string typeName = TypeUtils.GetTypeName(type); + if (typeName == "System.String" || typeName == "System.DateTime") + { + paramValue = "'" + paramValue + "'"; + } + } + else if (!float.TryParse(paramValue, out i)) { + paramValue = "'" + paramValue + "'"; + } + + //paramName = paramName.ToLower(); + strSql = strSql.Replace("@"+paramName, paramValue); + } + + return strSql; + } + + /// + /// 创建ACCESS SQL语句 + /// + /// + /// 参数集合 + /// + public static string builderAccessSQL(string strSql, IDbDataParameter[] parameters) + { + Session session = SessionThreadLocal.Get(); + + if (session.DbFactory.DbType != DatabaseType.ACCESS) + { + return strSql; + } + + foreach (IDbDataParameter param in parameters) + { + if (param.Value == null) continue; + + string paramName = param.ParameterName; + string paramValue = param.Value.ToString(); + + paramValue = "'" + paramValue + "'"; + strSql = strSql.Replace("@" + paramName, paramValue); + } + + return strSql; + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/TableInfo.cs b/类库/Api.Framework/Easy4/Common/TableInfo.cs new file mode 100644 index 0000000..e4f2826 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/TableInfo.cs @@ -0,0 +1,190 @@ +using System; +using System.Collections.Generic; +using System.Data; +using Easy4net.Context; + +namespace Easy4net.Common +{ + /// + /// 数据库表信息实体类 + /// + public class TableInfo + { + /// + /// 数据库表名 + /// + private string tableName; + /// + /// 主键生成方式 + /// + private int strategy; + + /// + /// 主键信息 + /// + private IdInfo id = new IdInfo(); + /// + /// 普通字段信息集合 + /// + private ColumnInfo columns = new ColumnInfo(); + /// + /// 属性到字段信息的映射集合 + /// + private Map propToColumn = new Map(); + /// + /// 字段信息到属性的映射集合 + /// + private Map columnToProp = new Map(); + + /// + /// 是否不具备自增长键 + /// + public bool NoAutomaticKey + { + get; + set; + } + + /// + /// 数据库表名 + /// + public string TableName + { + get { return tableName; } + set { tableName = value; } + } + + /// + /// 主键生成方式,参考GenerationType定义 + /// + public int Strategy + { + get { return strategy; } + set { strategy = value; } + } + + /// + /// 主键字段信息 + /// + public IdInfo Id + { + get { return id; } + set { id = value; } + } + + /// + /// 普通字段信息集合 + /// + public ColumnInfo Columns + { + get { return columns; } + set { columns = value; } + } + + /// + /// 实体类属性对应字段信息映射集合 + /// + public Map PropToColumn + { + get { return propToColumn; } + set { propToColumn = value; } + } + + /// + /// 字段信息对应实体类属性映射集合 + /// + public Map ColumnToProp + { + get { return columnToProp; } + set { columnToProp = value; } + } + + /// + /// 获取本数据库表信息中的参数键值集合 + /// + /// + public List GetParameterList() + { + if (this.Columns == null || this.Columns.Count == 0) return new List(); + + Session session = SessionThreadLocal.Get(); + + List paramList = new List(); + foreach (string key in this.Columns.Keys) + { + if (!string.IsNullOrEmpty(key.Trim())) + { + object value = this.Columns[key]; + if (value != null) + { + IDbDataParameter param = session.DbFactory.CreateDbParameter(); + param.ParameterName = key; + param.Value = value; + + paramList.Add(param); + } + } + } + + return paramList; + } + + /// + /// 将参数集合转为参数数组 + /// + /// 参数集合 + /// + public IDbDataParameter[] GetParameters(List paramList) + { + Session session = SessionThreadLocal.Get(); + + int i = 0; + IDbDataParameter[] parameters = session.DbFactory.CreateDbParameters(paramList.Count); + foreach (IDbDataParameter dbParameter in paramList) + { + parameters[i] = dbParameter; + i++; + } + + return parameters; + } + + /// + /// 获取本数据库表信息中的参数键值数组 + /// + /// + public IDbDataParameter[] GetParameters() + { + Session session = SessionThreadLocal.Get(); + + if (this.Columns == null || this.Columns.Count == 0) return session.DbFactory.CreateDbParameters(1); + + List paramList = new List(); + foreach (string key in this.Columns.Keys) + { + if (!string.IsNullOrEmpty(key.Trim())) + { + object value = this.Columns[key]; + if (value != null) + { + IDbDataParameter param = session.DbFactory.CreateDbParameter(); + param.ParameterName = key; + param.Value = value; + + paramList.Add(param); + } + } + } + + int i = 0; + IDbDataParameter[] parameters = session.DbFactory.CreateDbParameters(paramList.Count); + foreach (IDbDataParameter dbParameter in paramList) + { + parameters[i] = dbParameter; + i++; + } + + return parameters; + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/TypeUtils.cs b/类库/Api.Framework/Easy4/Common/TypeUtils.cs new file mode 100644 index 0000000..a72b17f --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/TypeUtils.cs @@ -0,0 +1,151 @@ +using System; + +namespace Easy4net.Common +{ + /// + /// 类型单元帮助类 + /// + public class TypeUtils + { + /// + /// 根据数据类型将指定数据进行相应转换 + /// + /// + /// + /// + public static object ConvertForType(object value,Type type) + { + if (Convert.IsDBNull(value) || (value == null)) + { + return null; + } + + string typeName = type.FullName.ToString(); + + if (type == typeof(System.Nullable)) + { + value = Convert.ToUInt16(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToUInt32(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToUInt64(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToInt32(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToInt64(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToDateTime(value); + } + + switch (typeName) + { + case "System.String": + if (!isNullOrEmpty(value)) + value = value.ToString(); + break; + case "System.Boolean": + if (!isNullOrEmpty(value)) + value = Convert.ToBoolean(value); + break; + case "System.Int16": + if (!isNullOrEmpty(value)) + value = Convert.ToInt16(value); + break; + case "System.Int32": + if (!isNullOrEmpty(value)) + value = Convert.ToInt32(value); + break; + case "System.Int64": + if (!isNullOrEmpty(value)) + value = Convert.ToInt64(value); + break; + case "System.Double": + if (!isNullOrEmpty(value)) + value = Convert.ToDouble(value); + break; + case "System.Float": + if (!isNullOrEmpty(value)) + value = Convert.ToDouble(value); + break; + case "System.Single": + if (!isNullOrEmpty(value)) + value = Convert.ToSingle(value); + break; + case "System.Decimal": + if (!isNullOrEmpty(value)) + value = Convert.ToDecimal(value); + break; + case "System.DateTime": + if (!isNullOrEmpty(value)) + value = Convert.ToDateTime(value); + break; + } + + return value; + } + + /// + /// 获取类型名 + /// + /// + /// + public static string GetTypeName(Type type) + { + if (type == null) return "System.Int32"; + string typeName = type.FullName.ToString(); + + if (type == typeof(System.Nullable)) + { + typeName = "System.UInt16"; + } + else if (type == typeof(System.Nullable)) + { + typeName = "System.UInt32"; + } + else if (type == typeof(System.Nullable)) + { + typeName = "System.UInt64"; + } + else if (type == typeof(System.Nullable)) + { + typeName = "System.Int16"; + } + else if (type == typeof(System.Nullable)) + { + typeName = "System.Int32"; + } + else if (type == typeof(System.Nullable)) + { + typeName = "System.Int64"; + } + else if (type == typeof(System.Nullable)) + { + typeName = "System.DateTime"; + } + + return typeName; + } + + /// + /// 检查输入值是否为空 + /// + /// + /// + static bool isNullOrEmpty(object val) + { + if (val == null) return true; + if (val.ToString() == "") return true; + return false; + } + } +} diff --git a/类库/Api.Framework/Easy4/Common/WhereExpression.cs b/类库/Api.Framework/Easy4/Common/WhereExpression.cs new file mode 100644 index 0000000..cfc5951 --- /dev/null +++ b/类库/Api.Framework/Easy4/Common/WhereExpression.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Easy4net.Common +{ + + public class WhereExpression + { + + //左边表达式 + public WhereExpression Left { get; set; } + + //右边表示式 + public WhereExpression Right { get; set; } + + //左边的字段 + public String LeftField { get; set; } + + //右边的字段 + public object RightField { get; set; } + + + /// + /// 值 + /// + public object Value { get; set; } + + /// + /// 是否检索全部数据 1=1 + /// + internal bool? IsAll { get; set; } + + /// + /// 是否为单独的查询 + /// + /// + public bool IsSingle + { + get + { + if ((Left as object) == null && (Right as object) == null) + return true; + return + false; + } + } + + public static bool IsNullOrEmpty(WhereExpression exp) + { + if ((exp as object) == null) return true; + if ((exp.Left as object) == null && + (exp.Right as object) == null && + (exp.LeftField as object) == null && + (exp.RightField as object) == null) + return true; + return false; + } + + + public static WhereExpression ALL + { + get + { + return new WhereExpression() + { + IsAll = true + }; + } + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + public override int GetHashCode() + { + return base.GetHashCode(); + } + + + #region 运算符重载 + + + + #region 两个条件表达式的组合 + + /// + /// And + /// + /// + /// + /// + public static WhereExpression operator &(WhereExpression left, WhereExpression right) + { + return null;//WhereExpression.Create(left, right, QueryOperator.And); + } + + + /// + /// Or + /// + /// + /// + /// + public static WhereExpression operator |(WhereExpression left, WhereExpression right) + { + return null;//WhereExpression.Create(left, right, QueryOperator.Or); + } + #endregion + + public WhereExpression Like(string value) + { + return null; + } + + + #endregion + + public static bool operator true(WhereExpression exp) + { + return false; + } + + public static bool operator false(WhereExpression exp) + { + return false; + } + } +} + diff --git a/类库/Api.Framework/Easy4/Context/ConnectionConfig.cs b/类库/Api.Framework/Easy4/Context/ConnectionConfig.cs new file mode 100644 index 0000000..4becb7a --- /dev/null +++ b/类库/Api.Framework/Easy4/Context/ConnectionConfig.cs @@ -0,0 +1,21 @@ +using Easy4net.DBUtility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Easy4net.Context +{ + + public class ConnectionConfig + { + /// + /// 数据库连接信息 + /// + public string ConnectionString { get; set; } + /// + /// 数据库类型 + /// + public DatabaseType DatabaseType { get; set; } + } +} diff --git a/类库/Api.Framework/Easy4/Context/Session.cs b/类库/Api.Framework/Easy4/Context/Session.cs new file mode 100644 index 0000000..cb16e74 --- /dev/null +++ b/类库/Api.Framework/Easy4/Context/Session.cs @@ -0,0 +1,1423 @@ +using Easy4net.Common; +using Easy4net.DBUtility; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Reflection; +using Easy4net.CustomAttributes; +using System.Text; +using System.Data.Common; +using System.Text.RegularExpressions; + +namespace Easy4net.Context +{ + /// + /// 持久层实体类 + /// + public class Session + { + + /// + /// 数据库连接字符串 + /// + private string connectionString = string.Empty; + + /// + /// 数据库事物对象 + /// + private IDbTransaction m_Transaction = null; + /// + /// 数据库类型 + /// + private DatabaseType dataBaseType = DatabaseType.SQLSERVER; + + /// + /// 数据库工厂对象,生成相应的数据库操作对象 + /// + private DbFactory dbFactory; + + /// + /// /数据库工厂对象,生成相应的数据库操作对象 + /// + public DbFactory DbFactory + { + get { return dbFactory; } + set { value = dbFactory; } + } + + private Session() { } + + /// + /// 根据数据库类型名创建一个持久层对象 + /// + /// + /// + public static Session NewInstance(ConnectionConfig config) + { + Session session = new Session(); + session.ConnectDB(config); + return session; + } + + /// + /// 获取当前的持久层对象 + /// + /// + public static Session GetCurrentSession() + { + Session session = SessionThreadLocal.Get(); + return session; + } + + + /// + /// 根据连接类型名进行连接配置 + /// + /// + public void ConnectDB(ConnectionConfig config) + { + + connectionString = config.ConnectionString; + + dataBaseType = config.DatabaseType; + dbFactory = DbFactory.NewInstance(connectionString, dataBaseType); + } + + /// + /// 开启事物处理功能 + /// + public void BeginTransaction() + { + m_Transaction = dbFactory.CreateDbTransaction(); + } + + /// + /// 根据事物锁定行为开启事物 + /// + /// + public void BeginTransaction(System.Data.IsolationLevel level) + { + m_Transaction = dbFactory.CreateDbTransaction(level); + } + + /// + /// 提交事物 + /// + public void Commit() + { + if (m_Transaction != null && m_Transaction.Connection != null) + { + if (m_Transaction.Connection.State != ConnectionState.Closed) + { + m_Transaction.Commit(); + m_Transaction = null; + } + } + } + + /// + /// 事物回滚 + /// + public void Rollback() + { + if (m_Transaction != null && m_Transaction.Connection != null) + { + if (m_Transaction.Connection.State != ConnectionState.Closed) + { + m_Transaction.Rollback(); + m_Transaction = null; + } + } + } + + /// + /// 获取当前的事物 + /// + /// + private IDbTransaction GetTransaction() + { + return m_Transaction; + } + + #region 将实体数据保存到数据库 + /// + /// Insert插入操作 + /// + /// + /// 数据库表实体对象 + /// + public int Insert(Object entity) + { + if (entity == null) return 0; + + object val = 0; + + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + Type classType = entity.GetType(); + //从实体对象的属性配置上获取对应的表信息 + PropertyInfo[] properties = ReflectionHelper.GetProperties(classType); + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.INSERT, properties); + + //获取SQL语句 + String strSql = EntityHelper.GetInsertSql(tableInfo); + + //获取参数 + IDbDataParameter[] parms = tableInfo.GetParameters(); + //执行Insert命令 + val = AdoHelper.ExecuteScalar(dbFactory, connection, transaction, CommandType.Text, strSql, parms); + + //把自动生成的主键ID赋值给返回的对象 + if (!tableInfo.NoAutomaticKey + && tableInfo.Strategy == GenerationType.INDENTITY) + { + if (dataBaseType == DatabaseType.SQLSERVER || dataBaseType == DatabaseType.MYSQL || dataBaseType == DatabaseType.SQLITE) + { + PropertyInfo propertyInfo = EntityHelper.GetPrimaryKeyPropertyInfo(entity, properties); + ReflectionHelper.SetPropertyValue(entity, propertyInfo, val); + } + } + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + + #endregion + + #region 批量保存 + /// + /// 批量进行Insert插入操作 + /// + /// + /// 数据库表实体对象集合 + /// + public int Insert(List entityList) + { + if (entityList == null || entityList.Count == 0) return 0; + + object val = 0; + + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + //从实体对象的属性配置上获取对应的表信息 + T firstEntity = entityList[0]; + Type classType = firstEntity.GetType(); + + PropertyInfo[] properties = ReflectionHelper.GetProperties(classType); + TableInfo tableInfo = EntityHelper.GetTableInfo(firstEntity, DbOperateType.INSERT, properties); + + //获取SQL语句 + String strSQL = EntityHelper.GetInsertSql(tableInfo); + foreach (T entity in entityList) + { + //从实体对象的属性配置上获取对应的表信息 + tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.INSERT, properties); + + //获取参数 + IDbDataParameter[] parms = tableInfo.GetParameters(); + //执行Insert命令 + val = AdoHelper.ExecuteScalar(dbFactory, connection, transaction, CommandType.Text, strSQL, parms); + + //Access数据库执行不需要命名参数 + if (dataBaseType == DatabaseType.ACCESS) + { + //如果是Access数据库,另外执行获取自动生成的ID + String autoSql = EntityHelper.GetAutoSql(dbFactory.DbType); + val = AdoHelper.ExecuteScalar(dbFactory, connection, transaction, CommandType.Text, autoSql); + } + + //把自动生成的主键ID赋值给返回的对象 + if (!tableInfo.NoAutomaticKey + && tableInfo.Strategy == GenerationType.INDENTITY) + { + //把自动生成的主键ID赋值给返回的对象 + if (dataBaseType == DatabaseType.SQLSERVER || dataBaseType == DatabaseType.MYSQL || dataBaseType == DatabaseType.ACCESS || dataBaseType == DatabaseType.SQLITE) + { + PropertyInfo propertyInfo = EntityHelper.GetPrimaryKeyPropertyInfo(entity, properties); + ReflectionHelper.SetPropertyValue(entity, propertyInfo, val); + } + } + } + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + #endregion + + #region 将实体数据修改到数据库 + /// + /// Update更新操作 + /// + /// + /// 数据库表实体对象 + /// + public int Update(Object entity) + { + if (entity == null) return 0; + + object val = 0; + + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + Type classType = entity.GetType(); + PropertyInfo[] properties = ReflectionHelper.GetProperties(classType); + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.UPDATE, properties); + + String strSQL = EntityHelper.GetUpdateSql(tableInfo); + + List paramsList = tableInfo.GetParameterList(); + IDbDataParameter dbParameter = dbFactory.CreateDbParameter(tableInfo.Id.Key, tableInfo.Id.Value); + paramsList.Add(dbParameter); + + IDbDataParameter[] parms = tableInfo.GetParameters(paramsList); + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL, parms); + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + + + #endregion + + #region 批量更新 + /// + /// 批量进行Update更新操作 + /// + /// + /// 数据库表实体对象集合 + /// + public int Update(List entityList) + { + if (entityList == null || entityList.Count == 0) return 0; + + object val = 0; + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + T firstEntity = entityList[0]; + Type classType = firstEntity.GetType(); + + PropertyInfo[] properties = ReflectionHelper.GetProperties(firstEntity.GetType()); + TableInfo tableInfo = EntityHelper.GetTableInfo(firstEntity, DbOperateType.UPDATE, properties); + + String strSQL = EntityHelper.GetUpdateSql(tableInfo); + + /*tableInfo.Columns.Add(tableInfo.Id.Key, tableInfo.Id.Value); + IDbDataParameter[] parms = tableInfo.GetParameters();*/ + + foreach (T entity in entityList) + { + tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.UPDATE, properties); + + List paramsList = tableInfo.GetParameterList(); + IDbDataParameter dbParameter = dbFactory.CreateDbParameter(tableInfo.Id.Key, tableInfo.Id.Value); + paramsList.Add(dbParameter); + + IDbDataParameter[] parms = tableInfo.GetParameters(paramsList); + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL, parms); + } + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + #endregion + + #region 执行SQL语句 + /// + /// 执行一条带有参数集合的SQL语句 + /// + /// SQL语句 + /// 参数集合 + /// + public int ExcuteSQL(string strSQL, ParamMap param) + { + object val = 0; + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + IDbDataParameter[] parms = param.toDbParameters(); + + if (dataBaseType == DatabaseType.ACCESS) + { + strSQL = SQLBuilderHelper.builderAccessSQL(strSQL, parms); + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL); + } + else + { + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL, parms); + } + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + #endregion + + #region 执行SQL语句 + /// + /// 执行一条SQL语句 + /// + /// + /// + public int ExcuteSQL(string strSQL) + { + + object val = 0; + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL); + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + #endregion + + #region 删除实体对应数据库中的数据 + /// + /// 进行Delete删除操作 + /// + /// + /// 数据库表实体对象 + /// + public int Delete(T entity) + { + if (entity == null) return 0; + + object val = 0; + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + Type classType = entity.GetType(); + PropertyInfo[] properties = ReflectionHelper.GetProperties(classType); + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.DELETE, properties); + + IDbDataParameter[] parms = dbFactory.CreateDbParameters(1); + parms[0].ParameterName = tableInfo.Id.Key; + parms[0].Value = tableInfo.Id.Value; + + String strSQL = EntityHelper.GetDeleteByIdSql(tableInfo); + + if (dataBaseType == DatabaseType.ACCESS) + { + strSQL = SQLBuilderHelper.builderAccessSQL(classType, tableInfo, strSQL, parms); + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL); + } + else + { + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL, parms); + } + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + #endregion + + #region 批量删除 + /// + /// 批量进行Delete删除操作 + /// + /// + /// 数据库表实体对象集合 + /// + public int Delete(List entityList) + { + if (entityList == null || entityList.Count == 0) return 0; + + object val = 0; + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + T firstEntity = entityList[0]; + Type classType = firstEntity.GetType(); + + PropertyInfo[] properties = ReflectionHelper.GetProperties(firstEntity.GetType()); + TableInfo tableInfo = EntityHelper.GetTableInfo(firstEntity, DbOperateType.DELETE, properties); + + String strSQL = EntityHelper.GetDeleteByIdSql(tableInfo); + + foreach (T entity in entityList) + { + tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.DELETE, properties); + + IDbDataParameter[] parms = dbFactory.CreateDbParameters(1); + parms[0].ParameterName = tableInfo.Id.Key; + parms[0].Value = tableInfo.Id.Value; + + if (dataBaseType == DatabaseType.ACCESS) + { + strSQL = SQLBuilderHelper.builderAccessSQL(classType, tableInfo, strSQL, parms); + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL); + } + else + { + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL, parms); + } + + //val = AdoHelper.ExecuteNonQuery(connection, transaction, CommandType.Text, strSQL, parms); + } + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + #endregion + + #region 根据主键id删除实体对应数据库中的数据 + /// + /// 根据主键值删除实体类对应数据库中的数据 + /// + /// + /// 主键值 + /// + public int Delete(object id) where T : new() + { + object val = 0; + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + T entity = new T(); + Type classType = entity.GetType(); + + PropertyInfo[] properties = ReflectionHelper.GetProperties(entity.GetType()); + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.DELETE, properties); + + String strSQL = EntityHelper.GetDeleteByIdSql(tableInfo); + + IDbDataParameter[] parms = dbFactory.CreateDbParameters(1); + parms[0].ParameterName = tableInfo.Id.Key; + parms[0].Value = id; + + if (dataBaseType == DatabaseType.ACCESS) + { + strSQL = SQLBuilderHelper.builderAccessSQL(classType, tableInfo, strSQL, parms); + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL); + } + else + { + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL, parms); + } + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + #endregion + + #region 批量根据主键id删除数据 + /// + /// 根据主键ID集合进行删除操作 + /// + /// + /// + /// + public int Delete(object[] ids) where T : new() + { + if (ids == null || ids.Length == 0) return 0; + + object val = 0; + IDbTransaction transaction = null; + IDbConnection connection = null; + try + { + //获取数据库连接,如果开启了事务,从事务中获取 + connection = GetConnection(); + transaction = GetTransaction(); + + T entity = new T(); + Type classType = entity.GetType(); + + PropertyInfo[] properties = ReflectionHelper.GetProperties(entity.GetType()); + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.DELETE, properties); + + String strSQL = EntityHelper.GetDeleteByIdSql(tableInfo); + + foreach (object id in ids) + { + tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.DELETE, properties); + + IDbDataParameter[] parms = dbFactory.CreateDbParameters(1); + parms[0].ParameterName = tableInfo.Id.Key; + parms[0].Value = id; + + val = AdoHelper.ExecuteNonQuery(dbFactory, connection, transaction, CommandType.Text, strSQL, parms); + } + } + catch (Exception e) + { + throw e; + } + finally + { + if (m_Transaction == null) + { + connection.Close(); + } + } + + return Convert.ToInt32(val); + } + #endregion + + #region 通过自定义SQL语句查询记录数 + /// + /// 根据SQL语句获取记录数 + /// + /// + /// + public int Count(string strSQL) + { + int count = 0; + IDbConnection connection = null; + bool closeConnection = GetWillConnectionState(); + try + { + connection = GetConnection(); + count = Convert.ToInt32(AdoHelper.ExecuteScalar(dbFactory, connection, CommandType.Text, strSQL)); + } + catch (Exception ex) + { + throw ex; + } + finally + { + if (closeConnection) + { + connection.Close(); + } + } + + return count; + } + #endregion + + #region 通过自定义SQL语句查询记录数 + /// + /// 通过自定义SQL语句查询记录数 + /// + /// + /// 参数集合 + /// + public int Count(string strSql, ParamMap param) + { + int count = 0; + IDbConnection connection = null; + bool closeConnection = GetWillConnectionState(); + try + { + connection = GetConnection(); + + strSql = strSql.ToLower(); + String columns = SQLBuilderHelper.fetchColumns(strSql); + + if (dataBaseType == DatabaseType.ACCESS) + { + strSql = SQLBuilderHelper.builderAccessSQL(strSql, param.toDbParameters()); + count = Convert.ToInt32(AdoHelper.ExecuteScalar(dbFactory, connection, CommandType.Text, strSql)); + } + else + { + count = Convert.ToInt32(AdoHelper.ExecuteScalar(dbFactory, connection, CommandType.Text, strSql, param.toDbParameters())); + } + } + catch (Exception ex) + { + throw ex; + } + finally + { + if (closeConnection) + { + connection.Close(); + } + } + + return count; + } + #endregion + + #region 通过自定义SQL语句查询数据 + /// + /// 通过自定义SQL语句查询数据 + /// + /// + /// + /// + public List Find(string strSql) where T : new() + { + List list = new List(); + IDataReader sdr = null; + IDbConnection connection = null; + try + { + connection = GetConnection(); + bool closeConnection = GetWillConnectionState(); + + strSql = strSql.ToLower(); + String columns = SQLBuilderHelper.fetchColumns(strSql); + + T entity = new T(); + PropertyInfo[] properties = ReflectionHelper.GetProperties(entity.GetType()); + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.SELECT, properties); + + sdr = AdoHelper.ExecuteReader(dbFactory, closeConnection, connection, CommandType.Text, strSql, null); + list = EntityHelper.toList(sdr, tableInfo, properties); + } + catch (Exception ex) + { + throw ex; + } + finally + { + if (sdr != null) sdr.Close(); + } + + return list; + } + #endregion + + #region 通过自定义SQL语句查询数据 + /// + /// 通过自定义SQL语句查询数据 + /// + /// + /// + /// + /// + public List Find(string strSQL, ParamMap param) where T : new() + { + List list = new List(); + IDataReader sdr = null; + IDbConnection connection = null; + try + { + connection = GetConnection(); + bool closeConnection = GetWillConnectionState(); + + string lowerSQL = strSQL.ToLower(); + String columns = SQLBuilderHelper.fetchColumns(lowerSQL); + + T entity = new T(); + Type classType = entity.GetType(); + PropertyInfo[] properties = ReflectionHelper.GetProperties(classType); + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.SELECT, properties); + + if (param.IsPage && !SQLBuilderHelper.isPage(lowerSQL)) + { + strSQL = SQLBuilderHelper.builderPageSQL(strSQL, param.OrderFields, param.IsDesc); + } + + if (dataBaseType == DatabaseType.ACCESS) + { + strSQL = SQLBuilderHelper.builderAccessPageSQL(strSQL, param); + } + + sdr = AdoHelper.ExecuteReader(dbFactory, closeConnection, connection, CommandType.Text, strSQL, param.toDbParameters()); + + list = EntityHelper.toList(sdr, tableInfo, properties); + } + catch (Exception ex) + { + throw ex; + } + finally + { + if (sdr != null) sdr.Close(); + } + + return list; + } + + public DataRow FindRow(string strSQL, ParamMap param) + { + var table = FindTable(strSQL,param); + if (table != null && table.Rows.Count > 0) return table.Rows[0]; + else return null; + } + + public DataTable FindTable(string strSQL, ParamMap param) + { + + IDataReader sdr = null; + IDbConnection connection = null; + try + { + connection = GetConnection(); + bool closeConnection = GetWillConnectionState(); + + string lowerSQL = strSQL.ToLower(); + String columns = SQLBuilderHelper.fetchColumns(lowerSQL); + + + + if (param.IsPage && !SQLBuilderHelper.isPage(lowerSQL)) + { + strSQL = SQLBuilderHelper.builderPageSQL(strSQL, param.OrderFields, param.IsDesc); + } + + if (dataBaseType == DatabaseType.ACCESS) + { + strSQL = SQLBuilderHelper.builderAccessPageSQL(strSQL, param); + } + + sdr = AdoHelper.ExecuteReader(dbFactory, closeConnection, connection, CommandType.Text, strSQL, param.toDbParameters()); + + return GetDataTableFromIDataReader(sdr); + } + catch (Exception ex) + { + throw ex; + } + finally + { + if (sdr != null) sdr.Close(); + } + + + } + + public List Find(string strSQL, Object obj) where T : new() + { + if (dataBaseType == DatabaseType.MYSQL) + { + strSQL = strSQL.Replace("[随机排序]", " order by rand() "); + } + else + { + strSQL = strSQL.Replace("[随机排序]", " order by RANDOM() "); + } + + //获取公共属性 + PropertyInfo[] propertys = obj.GetType().GetProperties(); + ParamMap map = ParamMap.NewMap(); + foreach (System.Reflection.PropertyInfo p in propertys) + { + map.Add(p.Name,p.GetValue(obj)); + } + return Find(strSQL,map); + } + public DataRow FindRow(string strSQL, Object obj) + { + if (dataBaseType == DatabaseType.MYSQL) + { + strSQL = strSQL.Replace("[随机排序]", " order by rand() "); + } + else + { + strSQL = strSQL.Replace("[随机排序]", " order by RANDOM() "); + } + //获取公共属性 + PropertyInfo[] propertys = obj.GetType().GetProperties(); + ParamMap map = ParamMap.NewMap(); + foreach (System.Reflection.PropertyInfo p in propertys) + { + map.Add(p.Name, p.GetValue(obj)); + } + return FindRow(strSQL, map); + } + public DataTable FindTable(string strSQL, Object obj) + { + if (dataBaseType == DatabaseType.MYSQL) + { + strSQL = strSQL.Replace("[随机排序]", " order by rand() "); + } + else + { + strSQL = strSQL.Replace("[随机排序]", " order by RANDOM() "); + } + //获取公共属性 + PropertyInfo[] propertys = obj.GetType().GetProperties(); + ParamMap map = ParamMap.NewMap(); + foreach (System.Reflection.PropertyInfo p in propertys) + { + map.Add(p.Name, p.GetValue(obj)); + } + return FindTable(strSQL, map); + } + + + + private DataTable GetDataTableFromIDataReader(IDataReader reader) + { + DataTable dt = new DataTable(); + bool init = false; + dt.BeginLoadData(); + object[] vals = new object[0]; + while (reader.Read()) + { + if (!init) + { + init = true; + int fieldCount = reader.FieldCount; + for (int i = 0; i < fieldCount; i++) + { + dt.Columns.Add(reader.GetName(i), reader.GetFieldType(i)); + } + vals = new object[fieldCount]; + } + reader.GetValues(vals); + dt.LoadDataRow(vals, true); + } + reader.Close(); + dt.EndLoadData(); + return dt; + } + #endregion + + #region 分页查询返回分页结果 + /// + /// 分页查询返回分页结果 + /// + /// + /// + /// + /// + public PageResult FindPage(string strSQL, ParamMap param) where T : new() + { + PageResult pageResult = new PageResult(); + List list = new List(); + IDataReader sdr = null; + IDbConnection connection = null; + try + { + connection = GetConnection(); + bool closeConnection = GetWillConnectionState(); + + strSQL = strSQL.ToLower(); + String countSQL = SQLBuilderHelper.builderCountSQL(strSQL); + String columns = SQLBuilderHelper.fetchColumns(strSQL); + + int count = this.Count(countSQL, param); + + T entity = new T(); + Type classType = entity.GetType(); + + PropertyInfo[] properties = ReflectionHelper.GetProperties(classType); + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.SELECT, properties); + + if (param.IsPage && !SQLBuilderHelper.isPage(strSQL)) + { + strSQL = SQLBuilderHelper.builderPageSQL(strSQL, param.OrderFields, param.IsDesc); + } + + if (dataBaseType == DatabaseType.ACCESS) + { + if (param.getInt("page_offset") > count) + { + int limit = param.getInt("page_limit") + count - param.getInt("page_offset"); + if (limit > 0) + { + strSQL = SQLBuilderHelper.builderAccessPageSQL(strSQL, param, limit); + sdr = AdoHelper.ExecuteReader(dbFactory, closeConnection, connection, CommandType.Text, strSQL, param.toDbParameters()); + list = EntityHelper.toList(sdr, tableInfo, properties); + } + } + else + { + strSQL = SQLBuilderHelper.builderAccessPageSQL(strSQL, param); + sdr = AdoHelper.ExecuteReader(dbFactory, closeConnection, connection, CommandType.Text, strSQL, param.toDbParameters()); + list = EntityHelper.toList(sdr, tableInfo, properties); + } + } + else + { + sdr = AdoHelper.ExecuteReader(dbFactory, closeConnection, connection, CommandType.Text, strSQL, param.toDbParameters()); + list = EntityHelper.toList(sdr, tableInfo, properties); + } + pageResult.Total = count; + pageResult.DataList = list; + + } + catch (Exception ex) + { + throw ex; + } + finally + { + if (sdr != null) sdr.Close(); + } + + return pageResult; + } + #endregion + + #region 通过主键ID查询数据 + /// + /// 通过主键ID查询数据 + /// + /// + /// + /// + public T Get(object id) where T : new() + { + List list = new List(); + + IDataReader sdr = null; + IDbConnection connection = null; + try + { + connection = GetConnection(); + bool closeConnection = GetWillConnectionState(); + + T entity = new T(); + Type classType = entity.GetType(); + PropertyInfo[] properties = ReflectionHelper.GetProperties(classType); + + TableInfo tableInfo = EntityHelper.GetTableInfo(entity, DbOperateType.SELECT, properties); + + IDbDataParameter[] parms = dbFactory.CreateDbParameters(1); + parms[0].ParameterName = tableInfo.Id.Key; + parms[0].Value = id; + + String strSQL = EntityHelper.GetFindByIdSql(tableInfo); + sdr = AdoHelper.ExecuteReader(dbFactory, closeConnection, connection, CommandType.Text, strSQL, parms); + + list = EntityHelper.toList(sdr, tableInfo, properties); + } + catch (Exception ex) + { + throw ex; + } + finally + { + if (sdr != null) sdr.Close(); + } + + return list.FirstOrDefault(); + } + #endregion + + /// + /// 获取数据库连接 + /// + /// + private IDbConnection GetConnection() + { + //获取数据库连接,如果开启了事务,从事务中获取 + IDbConnection connection = null; + if (m_Transaction != null) + { + connection = m_Transaction.Connection; + } + else + { + connection = dbFactory.CreateDbConnection(); + } + + return connection; + } + + /// + /// 获取当前事物是否为空 + /// + /// + private bool GetWillConnectionState() + { + return m_Transaction == null; + } + + + /// + /// 创建表 + /// + /// + public void CreateTable() + { + CreateTable(typeof(T)); + } + + /// + /// 创建表 + /// + /// + public void CreateTable(Type type) + { + + //获取公共属性 + PropertyInfo[] Propertys = type.GetProperties(); + + if (Propertys.Length == 1) throw new Exception("字段最少需要2个。"); + StringBuilder sb = new StringBuilder(); + sb.Append("CREATE TABLE "); + sb.Append(type.Name); + sb.Append("("); + int number = 0; + foreach (var item in Propertys) + { + string _name = item.Name; + string _type = string.Empty; + bool _primary = false; + var _unique = " "; + var _attribute = item.GetCustomAttributes().FirstOrDefault(f=>f.GetType()== typeof(ColumnAttribute)) as ColumnAttribute; + if (_attribute != null) + { + _name = _attribute.Name; + _type = _attribute.TypeInfo; + _primary = _attribute.PrimaryKey; + _unique = _attribute.IsUnique? " unique " : " "; + } + if (string.IsNullOrEmpty(_name)) _name = item.Name; + number++; + sb.Append(_name); + if (item.Name.ToLower() == "id" || _primary) + { + sb.Append(" integer primary key 自增 not null "); + } + else if (!string.IsNullOrEmpty(_type)) + { + sb.Append(" "+_type+ _unique); + } + else + { + sb.Append(" "); + if (item.PropertyType.FullName == typeof(Int32).ToString() || item.PropertyType.FullName == typeof(Int16).ToString() || item.PropertyType.FullName == typeof(UInt16).ToString() || item.PropertyType.FullName == typeof(Int64).ToString()) + sb.Append(" integer default 0 " + _unique); + else if (typeof(DateTime).ToString() == item.PropertyType.FullName) + sb.Append(" datetime " + _unique); + else if (typeof(String).ToString() == item.PropertyType.FullName) + { + if (_name.ToUpper() == "message".ToUpper() || _name.ToUpper() == "answer".ToUpper() || _name.ToUpper() == "token".ToUpper()) + { + sb.Append(" text " + _unique); + } + else + sb.Append(" varchar(255) default ''" + _unique); + } + + else if (item.PropertyType.FullName == typeof(Char).ToString()) + sb.Append(" varchar(2) default ''" + _unique); + else if (item.PropertyType.FullName == typeof(Boolean).ToString()) + sb.Append(" boolean " + _unique); + else if (item.PropertyType.FullName == typeof(Double).ToString()) + sb.Append(" double default 0.00" + _unique); + else + { + + throw new Exception("不支持" + item.PropertyType.FullName + "字段,请联系框架设计师处理。"); + } + + + } + if (number != Propertys.Length) + { + sb.Append(","); + } + } + sb.Append(");"); + string sql = sb.ToString(); + if (sql.Contains("自增")) { + if (dataBaseType == DatabaseType.SQLITE) + { + sql = sql.Replace("自增", "AUTOINCREMENT").Replace("AUTO_INCREMENT", "AUTOINCREMENT"); + } + else if(dataBaseType == DatabaseType.MYSQL) + { + sql = sql.Replace("自增", "AUTO_INCREMENT").Replace("AUTOINCREMENT", "AUTO_INCREMENT"); + } + } + + ExcuteSQL(sql); + } + + + /// + /// 添加唯一约束 + /// + public void AddUnique(params object[] values) + { + AddUnique(typeof(T).Name, values); + } + /// + /// 添加唯一约束 + /// + public void AddUnique(string tableName, params object[] values) + { + if (values == null) throw new Exception("Unique 不能为空。"); + + StringBuilder sb = new StringBuilder(); + if (dataBaseType == DatabaseType.SQLITE) + { + sb.Append(" CREATE UNIQUE INDEX "); + sb.Append(tableName); + foreach (var item in values) + { + sb.Append("_"); + sb.Append(item); + sb.Append("_"); + } + sb.Append(" ON "); + sb.Append(tableName); + sb.Append("("); + for (int i = 0; i < values.Length; i++) + { + sb.Append(values[i]); + if ((i + 1) != values.Length) + { + sb.Append(","); + } + } + sb.Append(");"); + } + else if (dataBaseType == DatabaseType.MYSQL) + { + sb.Append("ALTER TABLE "); + sb.Append(tableName); + sb.Append(" ADD UNIQUE KEY("); + for (int i = 0; i < values.Length; i++) + { + sb.Append(values[i]); + if ((i + 1) != values.Length) + { + sb.Append(","); + } + } + sb.Append(");"); + } + else throw new Exception("暂时不支持"+dataBaseType+"数据库!"); + + ExcuteSQL(sb.ToString()); + + + } + + /// + /// 添加索引 + /// + public bool AddIndex(string indexName, params object[] values) + { + try + { + string tableName = typeof(T).Name; + StringBuilder sb = new StringBuilder(); + if (dataBaseType == DatabaseType.SQLITE) + { + sb.Append(" CREATE INDEX "); + sb.Append(indexName); + foreach (var item in values) + { + sb.Append("_"); + sb.Append(item); + sb.Append("_"); + } + sb.Append(" ON "); + sb.Append(tableName); + sb.Append("("); + for (int i = 0; i < values.Length; i++) + { + sb.Append(values[i]); + if ((i + 1) != values.Length) + { + sb.Append(","); + } + } + sb.Append(");"); + } + else if (dataBaseType == DatabaseType.MYSQL) + { + sb.Append("ALTER TABLE "); + sb.Append(tableName); + sb.Append(" ADD INDEX " + indexName + "("); + for (int i = 0; i < values.Length; i++) + { + sb.Append(values[i]); + if ((i + 1) != values.Length) + { + sb.Append(","); + } + } + sb.Append(");"); + } + else throw new Exception("暂时不支持" + dataBaseType + "数据库!"); + + ExcuteSQL(sb.ToString()); + return true; + } + catch (Exception ex) + { + Console.WriteLine("创建索引失败:" + ex.Message); + } + return false; + } + + /// + /// 判断表是否存在 + /// + /// + /// + public bool TableExist() + { + return TableExist(typeof(T).Name); + } + /// + /// 判断表是否存在 + /// + public bool TableExist(string tableName) + { + ParamMap param = ParamMap.NewMap(); + param.setParameter("tableName", tableName); + if (dataBaseType== DatabaseType.SQLITE) + { + var result =FindRow("SELECT * FROM sqlite_master where type='table' and name=@tableName;", param); + if (result == null) return false; + } + else if (dataBaseType == DatabaseType.MYSQL) + { + param.setParameter("dbName", Regex.Match(connectionString,"Initial Catalog=(.*?);").Groups[1].Value); + var result = FindRow("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=@dbName and TABLE_NAME=@tableName ;",param); + if (result == null) return false; + } + else return false; + + return true; + } + + } + + +} diff --git a/类库/Api.Framework/Easy4/Context/SessionFactory.cs b/类库/Api.Framework/Easy4/Context/SessionFactory.cs new file mode 100644 index 0000000..f912ec1 --- /dev/null +++ b/类库/Api.Framework/Easy4/Context/SessionFactory.cs @@ -0,0 +1,48 @@ +using System; +using System.Linq; + +namespace Easy4net.Context +{ + /// + /// 持久层对象获取帮助 + /// + public class SessionFactory + { + /// + /// 根据数据库类型名获取对应的持久层对象 + /// + /// + /// + public static Session GetSession(ConnectionConfig config) + { + Session session = SessionThreadLocal.Get(); + if (session == null) + { + session = Session.NewInstance(config); + SessionThreadLocal.Set(session); + } + else + { + session.ConnectDB(config); + } + + return session; + } + + /// + /// 获取MSSQL持久层对象 + /// + /// + public static Session GetSession() + { + Session session = SessionThreadLocal.Get(); + if (session == null) + { + session = Session.NewInstance(null); + SessionThreadLocal.Set(session); + } + + return session; + } + } +} diff --git a/类库/Api.Framework/Easy4/Context/SessionThreadLocal.cs b/类库/Api.Framework/Easy4/Context/SessionThreadLocal.cs new file mode 100644 index 0000000..537e0f9 --- /dev/null +++ b/类库/Api.Framework/Easy4/Context/SessionThreadLocal.cs @@ -0,0 +1,39 @@ +using System; +using System.Threading; + +namespace Easy4net.Context +{ + /// + /// 持久层线程池 + /// + public class SessionThreadLocal + { + private static ThreadLocal m_SessionLocal = new ThreadLocal(); + + /// + /// 设置持久层到线程池 + /// + /// + public static void Set(Session session) + { + m_SessionLocal.Value = session; + } + + /// + /// 从线程池获取持久层 + /// + /// + public static Session Get() + { + return m_SessionLocal.Value; + } + + /// + /// 清空线程池 + /// + public static void Clear() + { + m_SessionLocal.Value = null; + } + } +} diff --git a/类库/Api.Framework/Easy4/CustomAttributes/ColumnAttribute.cs b/类库/Api.Framework/Easy4/CustomAttributes/ColumnAttribute.cs new file mode 100644 index 0000000..697baa5 --- /dev/null +++ b/类库/Api.Framework/Easy4/CustomAttributes/ColumnAttribute.cs @@ -0,0 +1,144 @@ +using System; + +namespace Easy4net.CustomAttributes +{ + /// + /// 数据库表字段特性 + /// + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, + AllowMultiple = false, Inherited = false)] + public class ColumnAttribute : Attribute + { + /// + /// 字段信息 例如:varchar(255) default '' + /// + public string TypeInfo { get; set; } + + /// + /// 是否为主键 + /// + public bool PrimaryKey { get; set; } + + /// + /// 字段名 + /// + private string _Name = string.Empty; + /// + /// 是否唯一 + /// + private bool _IsUnique = false; + /// + /// 是否允许为空 + /// + private bool _IsNull = true; + /// + /// 是否插入到表中 + /// + private bool _IsInsert = true; + /// + /// 是否修改到表中 + /// + private bool _IsUpdate = true; + /// + /// 在所有操作中是否忽略此字段 + /// + private bool _Ignore = false; + + + /// + /// 表字段名 + /// + public string Name + { + get { return _Name; } + set { _Name = value; } + } + + /// + /// 是否是唯一的,默认为否 + /// + public bool IsUnique + { + get { return _IsUnique; } + set { _IsUnique = value; } + } + + /// + /// 此字段是否允许为空,默认允许为空 + /// + public bool IsNull + { + get { return _IsNull; } + set { _IsNull = value; } + } + + /// + /// 在执行插入操作时此是否插入此字段值,默认为插入 + /// + public bool IsInsert + { + get { return _IsInsert; } + set { _IsInsert = value; } + } + + /// + /// 在执行更新操作时是否更新此字段值,默认为更新 + /// + public bool IsUpdate + { + get { return _IsUpdate; } + set { _IsUpdate = value; } + } + + /// + /// 在执行所有操作时是否忽略此字段,默认不忽略 + /// + public bool Ignore + { + get { return _Ignore; } + set { _Ignore = value; } + } + + /// + /// 创建一个空的字段特性 + /// + public ColumnAttribute() + { + + } + + /// + /// 创建一个指定字段名的字段特性 + /// + /// 字段名 + public ColumnAttribute(string aName) + : this() + { + this.Name = aName; + } + + /// + /// 创建一个制定字段名的字段特性 + /// + /// 字段名 + /// 在执行数据操作时是否忽略此字段 + public ColumnAttribute(string aName, bool aIgnore) + : this(aName) + { + this.Ignore = aIgnore; + } + + /// + /// 创建一个制定字段名的字段特性 + /// + /// 字段名 + /// 此字段是否参与插入操作 + /// 此字段是否参与更新操作 + public ColumnAttribute(string aName, bool aInsert, bool aUpdate) + : this(aName) + { + this.IsInsert = aInsert; + this.IsUpdate = aUpdate; + } + } +} diff --git a/类库/Api.Framework/Easy4/CustomAttributes/GenerationType.cs b/类库/Api.Framework/Easy4/CustomAttributes/GenerationType.cs new file mode 100644 index 0000000..b8c563c --- /dev/null +++ b/类库/Api.Framework/Easy4/CustomAttributes/GenerationType.cs @@ -0,0 +1,25 @@ +using System; + +namespace Easy4net.CustomAttributes +{ + /// + /// 数据库表主键生成类型定义 + /// + public class GenerationType + { + /// + /// 自动增长型 + /// + public const int INDENTITY = 1; + /// + /// GUID型 + /// + public const int GUID = 2; + /// + /// 提前生成并填充 + /// + public const int FILL = 3; + + private GenerationType() { }//私有构造函数,不可被实例化对象 + } +} diff --git a/类库/Api.Framework/Easy4/CustomAttributes/IdAttribute.cs b/类库/Api.Framework/Easy4/CustomAttributes/IdAttribute.cs new file mode 100644 index 0000000..7b1a1eb --- /dev/null +++ b/类库/Api.Framework/Easy4/CustomAttributes/IdAttribute.cs @@ -0,0 +1,48 @@ +using System; + +namespace Easy4net.CustomAttributes +{ + /// + /// 数据库主键字段特性 + /// + [AttributeUsage(AttributeTargets.Field|AttributeTargets.Property, + AllowMultiple = false, Inherited = false)] + public class IdAttribute : Attribute + { + /// + /// 主键字段名 + /// + private string _Name = string.Empty; + /// + /// 主键字段名 + /// + public string Name + { + get { return this._Name; } + set { this._Name = value; } + } + + /// + /// 主键字段生成方式,参考GenerationType定义 + /// + public int Strategy { get; set; } + + /// + /// 创建一个默认的主键特性,字段生成方式为自动增长型 + /// + public IdAttribute() + { + this.Strategy = GenerationType.INDENTITY; + } + + /// + /// 创建一个制定字段名的主键特性,字段生成方式为自动增长型 + /// + /// 主键字段名 + public IdAttribute(string aName) + : this() + { + this.Name = aName; + } + } +} diff --git a/类库/Api.Framework/Easy4/CustomAttributes/TableAttribute.cs b/类库/Api.Framework/Easy4/CustomAttributes/TableAttribute.cs new file mode 100644 index 0000000..6ff6545 --- /dev/null +++ b/类库/Api.Framework/Easy4/CustomAttributes/TableAttribute.cs @@ -0,0 +1,48 @@ +using System; + +namespace Easy4net.CustomAttributes +{ + /// + /// 数据库表特性 + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] + public class TableAttribute : Attribute + { + /// + /// 数据库名 + /// + private string _Name = string.Empty; + + /// + /// 创建一个空的数据库表特性,默认具备自增长键 + /// + public TableAttribute() + { + NoAutomaticKey = false; + } + + /// + /// 创建一个制定表明的数据库表特性,默认具备自增长键 + /// + /// 数据库表名 + public TableAttribute(string aName) + : this() + { + this.Name = aName; + } + + /// + /// 数据库名 + /// + public string Name + { + get { return _Name; } + set { _Name = value; } + } + + /// + /// 不具备自增长键的表 + /// + public bool NoAutomaticKey { get; set; } + } +} diff --git a/类库/Api.Framework/Easy4/DBUtility/AdoHelper.cs b/类库/Api.Framework/Easy4/DBUtility/AdoHelper.cs new file mode 100644 index 0000000..8703be1 --- /dev/null +++ b/类库/Api.Framework/Easy4/DBUtility/AdoHelper.cs @@ -0,0 +1,770 @@ +using System; +using System.Collections; +using System.Data; +using Easy4net.Common; + +namespace Easy4net.DBUtility +{ + /// + /// 数据库操作帮助类 + /// + public class AdoHelper + { + //获取数据库类型 + //private static string strDbType = CommonUtils.GetConfigValueByKey("dbType").ToUpper(); + + //将数据库类型转换成枚举类型 + //public static DatabaseType DbType = DatabaseTypeEnumParse(strDbType); + + //获取数据库连接字符串 + //public static string ConnectionString = GetConnectionString("connectionString"); + + //获取数据库命名参数符号,比如@(SQLSERVER)、:(ORACLE) + //public static string DbParmChar = DbFactory.CreateDbParmCharacter(); + + private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable()); + + /// + ///通过提供的参数,执行无结果集的数据库操作命令 + /// 并返回执行数据库操作所影响的行数。 + /// + /// 数据库配置对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回通过执行命令所影响的行数 + public static int ExecuteNonQuery(DbFactory dbFactory, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + using (IDbConnection conn = dbFactory.CreateDbConnection()) + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, commandParameters); + int val = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + return val; + } + } + /// + ///通过提供的参数,执行无结果集的数据库操作命令 + /// 并返回执行数据库操作所影响的行数。 + /// + /// 数据库配置对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回通过执行命令所影响的行数 + public static int ExecuteNonQuery(DbFactory dbFactory, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + using (IDbConnection conn = dbFactory.CreateDbConnection()) + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, null); + int val = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + return val; + } + } + + /// + ///通过提供的参数,执行无结果集返回的数据库操作命令 + ///并返回执行数据库操作所影响的行数。 + /// + /// + /// e.g.: + /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库连接对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回通过执行命令所影响的行数 + public static int ExecuteNonQuery(DbFactory dbFactory, IDbConnection connection, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, connection, null, cmdType, cmdText, commandParameters); + int val = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + return val; + } + + /// + ///通过提供的参数,执行无结果集返回的数据库操作命令 + ///并返回执行数据库操作所影响的行数。 + /// + /// + /// e.g.: + /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库连接对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回通过执行命令所影响的行数 + public static int ExecuteNonQuery(DbFactory dbFactory, IDbConnection connection, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, connection, null, cmdType, cmdText, null); + int val = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + return val; + } + + /// + ///通过提供的参数,执行无结果集返回的数据库操作命令 + ///并返回执行数据库操作所影响的行数。 + /// + /// + /// e.g.: + /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库连接对象 + /// + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回通过执行命令所影响的行数 + public static int ExecuteNonQuery(DbFactory dbFactory, IDbConnection connection, IDbTransaction transaction, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, connection, transaction, cmdType, cmdText, null); + int val = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + return val; + } + /// + ///通过提供的参数,执行无结果集返回的数据库操作命令 + ///并返回执行数据库操作所影响的行数。 + /// + /// + /// e.g.: + /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库连接对象 + /// + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// + /// 返回通过执行命令所影响的行数 + public static int ExecuteNonQuery(DbFactory dbFactory, IDbConnection connection, IDbTransaction transaction, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, connection, transaction, cmdType, cmdText, commandParameters); + int val = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + return val; + } + + + /// + ///通过提供的参数,执行无结果集返回的数据库操作命令 + ///并返回执行数据库操作所影响的行数。 + /// + /// + /// e.g.: + /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// sql事务对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回通过执行命令所影响的行数 + public static int ExecuteNonQuery(DbFactory dbFactory, IDbTransaction trans, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + int val = 0; + IDbCommand cmd = dbFactory.CreateDbCommand(); + + if (trans == null || trans.Connection == null) + { + using (IDbConnection conn = dbFactory.CreateDbConnection()) + { + PrepareCommand(dbFactory, cmd, conn, trans, cmdType, cmdText, commandParameters); + val = cmd.ExecuteNonQuery(); + } + } + else + { + PrepareCommand(dbFactory, cmd, trans.Connection, trans, cmdType, cmdText, commandParameters); + val = cmd.ExecuteNonQuery(); + } + + cmd.Parameters.Clear(); + return val; + } + /// + ///通过提供的参数,执行无结果集返回的数据库操作命令 + ///并返回执行数据库操作所影响的行数。 + /// + /// + /// e.g.: + /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// sql事务对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回通过执行命令所影响的行数 + public static int ExecuteNonQuery(DbFactory dbFactory, IDbTransaction trans, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + PrepareCommand(dbFactory, cmd, trans.Connection, trans, cmdType, cmdText, null); + int val = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + return val; + } + + /// + /// 使用提供的参数,执行有结果集返回的数据库操作命令 + /// 并返回SqlDataReader对象 + /// + /// + /// e.g.: + /// SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回SqlDataReader对象 + public static IDataReader ExecuteReader(DbFactory dbFactory, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + IDbConnection conn = dbFactory.CreateDbConnection(); + + //我们在这里使用一个 try/catch,因为如果PrepareCommand方法抛出一个异常,我们想在捕获代码里面关闭 + //connection连接对象,因为异常发生datareader将不会存在,所以commandBehaviour.CloseConnection + //将不会执行。 + try + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, commandParameters); + IDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection); + cmd.Parameters.Clear(); + return rdr; + } + catch + { + conn.Close(); + cmd.Dispose(); + throw; + } + } + + /// + /// 使用提供的参数,执行有结果集返回的数据库操作命令 + /// 并返回SqlDataReader对象 + /// + /// + /// e.g.: + /// SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回SqlDataReader对象 + public static IDataReader ExecuteReader(DbFactory dbFactory, IDbTransaction trans, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + IDbConnection conn = trans.Connection; + + //我们在这里使用一个 try/catch,因为如果PrepareCommand方法抛出一个异常,我们想在捕获代码里面关闭 + //connection连接对象,因为异常发生datareader将不会存在,所以commandBehaviour.CloseConnection + //将不会执行。 + try + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, commandParameters); + IDataReader rdr = cmd.ExecuteReader(); + cmd.Parameters.Clear(); + return rdr; + } + catch + { + conn.Close(); + cmd.Dispose(); + throw; + } + } + + /// + /// 使用提供的参数,执行有结果集返回的数据库操作命令 + /// 并返回SqlDataReader对象 + /// + /// + /// e.g.: + /// SqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 读取完关闭Reader是否同时也关闭数据库连接 + /// 数据库链接 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回SqlDataReader对象 + public static IDataReader ExecuteReader(DbFactory dbFactory, bool closeConnection, IDbConnection connection, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + IDbConnection conn = connection; + + //我们在这里使用一个 try/catch,因为如果PrepareCommand方法抛出一个异常,我们想在捕获代码里面关闭 + //connection连接对象,因为异常发生datareader将不会存在,所以commandBehaviour.CloseConnection + //将不会执行。 + try + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, commandParameters); + IDataReader rdr = closeConnection ? cmd.ExecuteReader(CommandBehavior.CloseConnection) : cmd.ExecuteReader(); + cmd.Parameters.Clear(); + return rdr; + } + catch + { + conn.Close(); + cmd.Dispose(); + throw; + } + } + + /// + ///使用提供的参数,执行有结果集返回的数据库操作命令 + /// 并返回SqlDataReader对象 + /// + /// 数据库配置对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回SqlDataReader对象 + public static IDataReader ExecuteReader(DbFactory dbFactory, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + IDbConnection conn = dbFactory.CreateDbConnection(); + + //我们在这里使用一个 try/catch,因为如果PrepareCommand方法抛出一个异常,我们想在捕获代码里面关闭 + //connection连接对象,因为异常发生datareader将不会存在,所以commandBehaviour.CloseConnection + //将不会执行。 + try + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, null); + IDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection); + cmd.Parameters.Clear(); + return rdr; + } + catch (Exception ex) + { + conn.Close(); + cmd.Dispose(); + throw ex; + } + } + + /// + ///使用提供的参数,执行有结果集返回的数据库操作命令 + /// 并返回SqlDataReader对象 + /// + /// 数据库配置对象 + /// + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回SqlDataReader对象 + public static IDataReader ExecuteReader(DbFactory dbFactory, IDbTransaction trans, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + IDbConnection conn = trans.Connection; + + //我们在这里使用一个 try/catch,因为如果PrepareCommand方法抛出一个异常,我们想在捕获代码里面关闭 + //connection连接对象,因为异常发生datareader将不会存在,所以commandBehaviour.CloseConnection + //将不会执行。 + try + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, null); + IDataReader rdr = cmd.ExecuteReader(); + cmd.Parameters.Clear(); + return rdr; + } + catch (Exception ex) + { + conn.Close(); + cmd.Dispose(); + throw ex; + } + } + + /// + ///使用提供的参数,执行有结果集返回的数据库操作命令 + /// 并返回SqlDataReader对象 + /// + /// 数据库配置对象 + /// 读取完关闭Reader是否同时也关闭数据库连接 + /// 数据库链接 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回SqlDataReader对象 + public static IDataReader ExecuteReader(DbFactory dbFactory, bool closeConnection, IDbConnection connection, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + IDbConnection conn = connection; + + //我们在这里使用一个 try/catch,因为如果PrepareCommand方法抛出一个异常,我们想在捕获代码里面关闭 + //connection连接对象,因为异常发生datareader将不会存在,所以commandBehaviour.CloseConnection + //将不会执行。 + try + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, null); + IDataReader rdr = closeConnection ? cmd.ExecuteReader(CommandBehavior.CloseConnection) : cmd.ExecuteReader(); + cmd.Parameters.Clear(); + return rdr; + } + catch (Exception ex) + { + conn.Close(); + cmd.Dispose(); + throw ex; + } + } + + + /// + /// 查询数据填充到数据集DataSet中 + /// + /// 数据库配置对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 命令文本 + /// 参数数组 + /// 数据集DataSet对象 + public static DataSet dataSet(DbFactory dbFactory, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + DataSet ds = new DataSet(); + IDbCommand cmd = dbFactory.CreateDbCommand(); + IDbConnection conn = dbFactory.CreateDbConnection(); + try + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, commandParameters); + IDbDataAdapter sda = dbFactory.CreateDataAdapter(cmd); + sda.Fill(ds); + return ds; + } + catch + { + conn.Close(); + cmd.Dispose(); + throw; + } + finally + { + conn.Close(); + cmd.Dispose(); + } + } + + /// + /// 查询数据填充到数据集DataSet中 + /// + /// 数据库配置对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 命令文本 + /// 数据集DataSet对象 + public static DataSet dataSet(DbFactory dbFactory, CommandType cmdType, string cmdText) + { + DataSet ds = new DataSet(); + IDbCommand cmd = dbFactory.CreateDbCommand(); + IDbConnection conn = dbFactory.CreateDbConnection(); + try + { + PrepareCommand(dbFactory, cmd, conn, null, cmdType, cmdText, null); + IDbDataAdapter sda = dbFactory.CreateDataAdapter(cmd); + sda.Fill(ds); + return ds; + } + catch + { + conn.Close(); + cmd.Dispose(); + throw; + } + finally + { + conn.Close(); + cmd.Dispose(); + } + } + + /// + /// 依靠数据库连接字符串connectionString, + /// 使用所提供参数,执行返回首行首列命令 + /// + /// + /// e.g.: + /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + public static object ExecuteScalar(DbFactory dbFactory, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + using (IDbConnection connection = dbFactory.CreateDbConnection()) + { + PrepareCommand(dbFactory, cmd, connection, null, cmdType, cmdText, commandParameters); + object val = cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + return val; + } + } + /// + /// 依靠数据库连接字符串connectionString, + /// 使用所提供参数,执行返回首行首列命令 + /// + /// + /// e.g.: + /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + public static object ExecuteScalar(DbFactory dbFactory, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + using (IDbConnection connection = dbFactory.CreateDbConnection()) + { + PrepareCommand(dbFactory, cmd, connection, null, cmdType, cmdText, null); + object val = cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + return val; + } + } + /// + ///依靠数据库连接字符串connectionString, + /// 使用所提供参数,执行返回首行首列命令 + /// + /// + /// e.g.: + /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库连接对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + public static object ExecuteScalar(DbFactory dbFactory, IDbConnection connection, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, connection, null, cmdType, cmdText, commandParameters); + object val = cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + return val; + } + + /// + ///依靠数据库连接字符串connectionString, + /// 使用所提供参数,执行返回首行首列命令 + /// + /// + /// e.g.: + /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库连接对象 + /// + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + public static object ExecuteScalar(DbFactory dbFactory, IDbConnection connection, IDbTransaction transaction, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, connection, transaction, cmdType, cmdText, commandParameters); + object val = cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + return val; + } + + /// + ///依靠数据库连接字符串connectionString, + /// 使用所提供参数,执行返回首行首列命令 + /// + /// + /// e.g.: + /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库连接对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + public static object ExecuteScalar(DbFactory dbFactory, IDbConnection connection, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, connection, null, cmdType, cmdText, null); + object val = cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + return val; + } + + /// + ///依靠数据库连接字符串connectionString, + /// 使用所提供参数,执行返回首行首列命令 + /// + /// + /// e.g.: + /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库连接对象 + /// + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + public static object ExecuteScalar(DbFactory dbFactory, IDbConnection conn, IDbTransaction trans, CommandType cmdType, string cmdText) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, conn, trans, cmdType, cmdText, null); + object val = cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + return val; + } + + /// + ///依靠数据库连接字符串connectionString, + /// 使用所提供参数,执行返回首行首列命令 + /// + /// + /// e.g.: + /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new SqlParameter("@prodid", 24)); + /// + /// 数据库配置对象 + /// 数据库事物对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行 + /// 执行命令所需的参数数组 + /// 返回一个对象,使用Convert.To{Type}将该对象转换成想要的数据类型。 + public static object ExecuteScalar(DbFactory dbFactory, IDbTransaction trans, CommandType cmdType, string cmdText, params IDbDataParameter[] commandParameters) + { + IDbCommand cmd = dbFactory.CreateDbCommand(); + + PrepareCommand(dbFactory, cmd, trans.Connection, trans, cmdType, cmdText, commandParameters); + object val = cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + return val; + } + + /// + /// add parameter array to the cache + /// + /// Key to the parameter cache + /// an array of SqlParamters to be cached + public static void CacheParameters(string cacheKey, params IDbDataParameter[] commandParameters) + { + parmCache[cacheKey] = commandParameters; + } + + /// + /// 查询缓存参数 + /// + /// 使用缓存名称查找值 + /// 缓存参数数组 + public static IDbDataParameter[] GetCachedParameters(string cacheKey) + { + IDbDataParameter[] cachedParms = (IDbDataParameter[])parmCache[cacheKey]; + + if (cachedParms == null) + return null; + + IDbDataParameter[] clonedParms = new IDbDataParameter[cachedParms.Length]; + + for (int i = 0, j = cachedParms.Length; i < j; i++) + clonedParms[i] = (IDbDataParameter)((ICloneable)cachedParms[i]).Clone(); + + return clonedParms; + } + + /// + /// 为即将执行准备一个命令 + /// + /// 数据库配置对象 + /// SqlCommand对象 + /// SqlConnection对象 + /// IDbTransaction对象 + /// 执行命令的类型(存储过程或T-SQL,等等) + /// 存储过程名称或者T-SQL命令行, e.g. Select * from Products + /// SqlParameters to use in the command + private static void PrepareCommand(DbFactory dbFactory, IDbCommand cmd, IDbConnection conn, IDbTransaction trans, CommandType cmdType, string cmdText, IDbDataParameter[] cmdParms) + { + if (conn.State != ConnectionState.Open) + conn.Open(); + + cmd.Connection = conn; + cmd.CommandText = cmdText; + + if (trans != null) + cmd.Transaction = trans; + + cmd.CommandType = cmdType; + + if (cmdParms != null) + { + foreach (IDbDataParameter parm in cmdParms) + { + if (dbFactory.DbType == DatabaseType.ACCESS && parm.DbType == System.Data.DbType.DateTime) + { + parm.DbType = System.Data.DbType.Object; + } + cmd.Parameters.Add(parm); + } + } + } + + /// + /// 根据传入的Key获取配置文件中 + /// 相应Key的数据库连接字符串 + /// + /// + /// + public static string GetConnectionString(string Key) + { + try + { + string connectionString = CommonUtils.GetConfigValueByKey(Key); + return connectionString; + } + catch + { + throw new Exception("web.config文件appSettings中数据库连接字符串未配置或配置错误,必须为Key=\"connectionString\""); + } + } + + + + /// + /// 用于数据库类型的字符串枚举转换 + /// + /// + /// + /// + public static T DatabaseTypeEnumParse(string value) + { + try + { + return CommonUtils.EnumParse(value); + } + catch + { + throw new Exception("数据库类型\"" + value + "\"错误,请检查!"); + } + } + } +} diff --git a/类库/Api.Framework/Easy4/DBUtility/DatabaseType.cs b/类库/Api.Framework/Easy4/DBUtility/DatabaseType.cs new file mode 100644 index 0000000..d93402e --- /dev/null +++ b/类库/Api.Framework/Easy4/DBUtility/DatabaseType.cs @@ -0,0 +1,37 @@ +using System; +using System.ComponentModel; + +namespace Easy4net.DBUtility +{ + /// + /// 数据库类型枚举,需要扩展类型可在此添加 + /// + public enum DatabaseType + { + /// + /// MSSQL数据库 + /// + [Description("MSSQL数据库")] + SQLSERVER, + /// + /// ORACLE数据库 + /// + [Description("ORACLE数据库")] + ORACLE, + /// + /// ACCESS数据库 + /// + [Description("ACCESS数据库")] + ACCESS, + /// + /// MYSQL数据库 + /// + [Description("MYSQL数据库")] + MYSQL, + /// + /// SQLITE数据库 + /// + [Description("SQLITE数据库")] + SQLITE + } +} diff --git a/类库/Api.Framework/Easy4/DBUtility/DbFactory.cs b/类库/Api.Framework/Easy4/DBUtility/DbFactory.cs new file mode 100644 index 0000000..6988216 --- /dev/null +++ b/类库/Api.Framework/Easy4/DBUtility/DbFactory.cs @@ -0,0 +1,456 @@ +using System; +using System.Data; +using System.Data.SqlClient; +using System.Data.OracleClient; +using System.Data.OleDb; +using MySql.Data.MySqlClient; +using System.Data.SQLite; + +namespace Easy4net.DBUtility +{ + /// + /// ɹ + /// + public class DbFactory + { + + private DbFactory() + { + + } + + /// + /// ݿַԼݿʹһݿ⹤ + /// + /// ݿַ + /// ݿ + /// + public static DbFactory NewInstance(string connectionString, DatabaseType dbType) + { + DbFactory factory = new DbFactory(); + factory.connectionString = connectionString; + factory.dbType = dbType; + factory.DbParmChar = factory.CreateDbParmCharacter(); + + return factory; + } + + private string connectionString; + private DatabaseType dbType; + private string dbParmChar; + + /// + /// ݿ + /// + public DatabaseType DbType + { + get { return dbType; } + set { value = dbType; } + } + + /// + /// ַ + /// + public string ConnectionString + { + get { return connectionString; } + set { value = connectionString; } + } + + /// + /// ǰ׺ַ + /// + public string DbParmChar + { + get { return dbParmChar; } + set { dbParmChar = value; } + } + + /// + /// ļõݿ + /// ȡеIJoracleΪ":",sqlserverΪ"@" + /// + /// + public string CreateDbParmCharacter() + { + string character = string.Empty; + + switch (dbType) + { + case DatabaseType.SQLSERVER: + character = "@"; + break; + case DatabaseType.ORACLE: + character = ":"; + break; + case DatabaseType.MYSQL: + character = "?"; + break; + case DatabaseType.ACCESS: + character = "@"; + break; + case DatabaseType.SQLITE: + character = "@"; + break; + default: + throw new Exception("ݿĿǰ֧֣"); + } + + return character; + } + + /// + /// ļõݿͺʹ + /// ݿַӦݿӶ + /// + /// + public IDbConnection CreateDbConnection() + { + IDbConnection conn = null; + switch (dbType) + { + case DatabaseType.SQLSERVER: + conn = new SqlConnection(connectionString); + break; + case DatabaseType.ORACLE: + conn = new OracleConnection(connectionString); + break; + case DatabaseType.MYSQL: + conn = new MySqlConnection(connectionString); + break; + case DatabaseType.ACCESS: + conn = new OleDbConnection(connectionString); + break; + case DatabaseType.SQLITE: + conn = new SQLiteConnection(connectionString); + break; + default: + throw new Exception("ݿĿǰ֧֣"); + } + + return conn; + } + + /// + /// ļõݿ + /// Ӧݿ + /// + /// + public IDbCommand CreateDbCommand() + { + IDbCommand cmd = null; + switch (dbType) + { + case DatabaseType.SQLSERVER: + cmd = new SqlCommand(); + break; + case DatabaseType.ORACLE: + cmd = new OracleCommand(); + break; + case DatabaseType.MYSQL: + cmd = new MySqlCommand(); + break; + case DatabaseType.ACCESS: + cmd = new OleDbCommand(); + break; + case DatabaseType.SQLITE: + cmd = new SQLiteCommand(); + break; + default: + throw new Exception("ݿĿǰ֧֣"); + } + + return cmd; + } + + /// + /// ļõݿ + /// Ӧݿ + /// + /// + public IDbDataAdapter CreateDataAdapter() + { + IDbDataAdapter adapter = null; + switch (dbType) + { + case DatabaseType.SQLSERVER: + adapter = new SqlDataAdapter(); + break; + case DatabaseType.ORACLE: + adapter = new OracleDataAdapter(); + break; + case DatabaseType.MYSQL: + adapter = new MySqlDataAdapter(); + break; + case DatabaseType.ACCESS: + adapter = new OleDbDataAdapter(); + break; + case DatabaseType.SQLITE: + adapter = new SQLiteDataAdapter(); + break; + default: + throw new Exception("ݿĿǰ֧֣"); + } + + return adapter; + } + + /// + /// ļõݿ + /// ʹӦݿ + /// + /// + public IDbDataAdapter CreateDataAdapter(IDbCommand cmd) + { + IDbDataAdapter adapter = null; + switch (dbType) + { + case DatabaseType.SQLSERVER: + adapter = new SqlDataAdapter((SqlCommand)cmd); + break; + case DatabaseType.ORACLE: + adapter = new OracleDataAdapter((OracleCommand)cmd); + break; + case DatabaseType.MYSQL: + adapter = new MySqlDataAdapter((MySqlCommand)cmd); + break; + case DatabaseType.ACCESS: + adapter = new OleDbDataAdapter((OleDbCommand)cmd); + break; + case DatabaseType.SQLITE: + adapter = new SQLiteDataAdapter((SQLiteCommand)cmd); + break; + default: throw new Exception("ݿĿǰ֧֣"); + } + + return adapter; + } + + /// + /// ļõݿ + /// ӦݿIJ + /// + /// + public IDbDataParameter CreateDbParameter() + { + IDbDataParameter param = null; + switch (dbType) + { + case DatabaseType.SQLSERVER: + param = new SqlParameter(); + break; + case DatabaseType.ORACLE: + param = new OracleParameter(); + break; + case DatabaseType.MYSQL: + param = new MySqlParameter(); + break; + case DatabaseType.ACCESS: + param = new OleDbParameter(); + break; + case DatabaseType.SQLITE: + param = new SQLiteParameter(); + break; + default: + throw new Exception("ݿĿǰ֧֣"); + } + + return param; + } + + /// + /// ļõݿ + /// ӦݿIJ + /// + /// + public IDbDataParameter CreateDbParameter(string paramName, object value) + { + if (dbType == DatabaseType.ACCESS || dbType == DatabaseType.SQLITE) + { + paramName = "@" + paramName; + } + + IDbDataParameter param = CreateDbParameter(); + param.ParameterName = paramName; + param.Value = value; + + return param; + } + + /// + /// ļõݿ + /// ӦݿIJ + /// + /// + public IDbDataParameter CreateDbParameter(string paramName, object value, DbType _dataType) + { + if (dbType == DatabaseType.ACCESS || dbType == DatabaseType.SQLITE) + { + paramName = "@" + paramName; + } + + IDbDataParameter param = CreateDbParameter(); + param.DbType = _dataType; + param.ParameterName = paramName; + param.Value = value; + + return param; + } + + /// + /// ļõݿ + /// ӦݿIJ + /// + /// + public IDbDataParameter CreateDbParameter(string paramName, object value, ParameterDirection direction) + { + if (dbType == DatabaseType.ACCESS || dbType == DatabaseType.SQLITE) + { + paramName = "@" + paramName; + } + + IDbDataParameter param = CreateDbParameter(); + param.Direction = direction; + param.ParameterName = paramName; + param.Value = value; + + return param; + } + + /// + /// ļõݿ + /// ӦݿIJ + /// + /// + public IDbDataParameter CreateDbParameter(string paramName, object value, int size, ParameterDirection direction) + { + if (dbType == DatabaseType.ACCESS || dbType == DatabaseType.SQLITE) + { + paramName = "@" + paramName; + } + + IDbDataParameter param = CreateDbParameter(); + param.Direction = direction; + param.ParameterName = paramName; + param.Value = value; + param.Size = size; + + return param; + } + + /// + /// ļõݿ + /// ӦݿIJ + /// + /// + public IDbDataParameter CreateDbOutParameter(string paramName, int size) + { + if (dbType == DatabaseType.ACCESS || dbType == DatabaseType.SQLITE) + { + paramName = "@" + paramName; + } + + IDbDataParameter param = CreateDbParameter(); + param.Direction = ParameterDirection.Output; + param.ParameterName = paramName; + param.Size = size; + + return param; + } + + /// + /// ļõݿ + /// ӦݿIJ + /// + /// + public IDbDataParameter CreateDbParameter(string paramName, object value, DbType _dataType, ParameterDirection direction) + { + if (dbType == DatabaseType.ACCESS || dbType == DatabaseType.SQLITE) + { + paramName = "@" + paramName; + } + + IDbDataParameter param = CreateDbParameter(); + param.Direction = direction; + param.DbType = _dataType; + param.ParameterName = paramName; + param.Value = value; + + return param; + } + + /// + /// ļõݿ + /// ʹIJӦݿIJ + /// + /// + public IDbDataParameter[] CreateDbParameters(int size) + { + int i = 0; + IDbDataParameter[] param = null; + switch (dbType) + { + case DatabaseType.SQLSERVER: + param = new SqlParameter[size]; + while (i < size) { param[i] = new SqlParameter(); i++; } + break; + case DatabaseType.ORACLE: + param = new OracleParameter[size]; + while (i < size) { param[i] = new OracleParameter(); i++; } + break; + case DatabaseType.MYSQL: + param = new MySqlParameter[size]; + while (i < size) { param[i] = new MySqlParameter(); i++; } + break; + case DatabaseType.ACCESS: + param = new OleDbParameter[size]; + while (i < size) { param[i] = new OleDbParameter(); i++; } + break; + case DatabaseType.SQLITE: + param = new SQLiteParameter[size]; + while (i < size) { param[i] = new SQLiteParameter(); i++; } + break; + default: + throw new Exception("ݿĿǰ֧֣"); + + } + + return param; + } + + /// + /// ļõݿ + /// Ӧݿ + /// + /// + public IDbTransaction CreateDbTransaction() + { + IDbConnection conn = CreateDbConnection(); + + if (conn.State == ConnectionState.Closed) + { + conn.Open(); + } + + return conn.BeginTransaction(); + } + + + /// + /// ݿ + /// + /// + /// + public IDbTransaction CreateDbTransaction(System.Data.IsolationLevel level) + { + IDbConnection conn = CreateDbConnection(); + + if (conn.State == ConnectionState.Closed) + { + conn.Open(); + } + + return conn.BeginTransaction(level); + } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Easy4/DBUtility/DbHelper.cs b/类库/Api.Framework/Easy4/DBUtility/DbHelper.cs new file mode 100644 index 0000000..fe9bdbf --- /dev/null +++ b/类库/Api.Framework/Easy4/DBUtility/DbHelper.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Easy4net.Common; +using Easy4net.Context; + +namespace Easy4net.DBUtility +{ + /// + /// 数据库帮助类 + /// + public class DBHelper + { + Session session; + + /// + /// 根据数据库连接类型名创建一个数据库帮助类 + /// + /// + public DBHelper(ConnectionConfig config) + { + session = Session.NewInstance(config); + } + + /// + /// 根据数据库连接类型名创建一个数据库帮助类 + /// + /// + /// + public static DBHelper getInstance(ConnectionConfig config) + { + return new DBHelper(config); + } + + /// + /// 根据主键ID获取对象 + /// + /// 对象类型 + /// 主键ID + /// + public T Get(object id) where T : new() + { + return session.Get(id); + } + + /// + /// 插入对象数据 + /// + + /// 需要插入的数据对象 + /// + public int Save(object entity) + { + return session.Insert(entity); + } + + /// + /// 批量插入对象数据 + /// + /// 数据对象类型 + /// 需要插入的数据对象集合 + /// + public int Save(List entityList) + { + return session.Insert(entityList); + } + + /// + /// 更新对象数据 + /// + /// 数据对象类型 + /// 需要更新的数据对象集合 + /// + public int Update(Object entity) + { + return session.Update(entity); + } + + /// + /// 批量更新对象数据 + /// + /// 数据对象类型 + /// 需要更新的数据对象集合 + /// + public int Update(List entityList) + { + return session.Update(entityList); + } + + /// + /// 删除对象数据 + /// + /// 数据对象类型 + /// 需要删除的数据对象 + /// + public int Remove(T entity) + { + return session.Delete(entity); + } + + /// + /// 批量删除对象数据 + /// + /// 数据对象类型 + /// 需要删除的数据对象集合 + /// + public int Remove(List entityList) + { + return session.Delete(entityList); + } + + /// + /// 根据主键ID删除数据 + /// + /// 数据对象类型 + /// 主键ID + /// + public int Remove(object id) where T : new() + { + return session.Delete(id); + } + + /// + /// 执行SQL语句 + /// + /// SQL命令 + /// 参数 + /// + public int ExcuteSQL(string strSQL, ParamMap param) + { + return session.ExcuteSQL(strSQL, param); + } + + /// + /// 执行SQL语句 + /// + /// SQL命令 + /// + public int ExcuteSQL(string strSQL) + { + return session.ExcuteSQL(strSQL); + } + + /// + /// 根据SQL查询数量 + /// + /// SQL命令 + /// + public int Count(string strSQL) + { + return session.Count(strSQL); + } + + /// + /// 根据SQL查询记录数 + /// + /// SQL命令 + /// 参数 + /// + public int Count(string strSQL, ParamMap param) + { + return session.Count(strSQL, param); + } + + /// + /// 根据SQL查询数据 + /// + /// 对象类型 + /// SQL命令 + /// + public List FindBySql(string strSQL) where T : new() + { + return session.Find(strSQL); + } + + /// + /// 根据SQL查询数据 + /// + /// 对象类型 + /// SQL命令 + /// 参数 + /// + public List FindBySql(string strSQL, ParamMap param) where T : new() + { + return session.Find(strSQL, param); + } + + /// + /// 分页查询返回分页对象 + /// + /// 对象类型 + /// SQL命令 + /// 参数 + /// + public PageResult FindPage(string strSQL, ParamMap param) where T : new() + { + return session.FindPage(strSQL, param); + } + + /// + /// 查询一条数据 + /// + /// 对象类型 + /// SQL命令 + /// + public T FindOne(string strSQL) where T : new() + { + return session.Find(strSQL).FirstOrDefault(); + } + + /// + /// 查询一条数据 + /// + /// 对象类型 + /// SQL命令 + /// 参数 + /// + public T FindOne(string strSQL, ParamMap param) where T : new() + { + return session.Find(strSQL, param).FirstOrDefault(); + } + + /// + /// 开启事务 + /// + public void BeginTransaction() + { + session.BeginTransaction(); + } + + /// + /// 根据锁定行为开启事物 + /// + /// + public void BeginTransaction(System.Data.IsolationLevel level) + { + session.BeginTransaction(level); + } + + /// + /// 提交事务 + /// + public void CommitTransaction() + { + session.Commit(); + } + + /// + /// 回滚事务 + /// + public void RollbackTransaction() + { + session.Rollback(); + } + } +} + diff --git a/类库/Api.Framework/Easy4/DBUtility/DbOperateType.cs b/类库/Api.Framework/Easy4/DBUtility/DbOperateType.cs new file mode 100644 index 0000000..2b32651 --- /dev/null +++ b/类库/Api.Framework/Easy4/DBUtility/DbOperateType.cs @@ -0,0 +1,37 @@ +using System; +using System.ComponentModel; + +namespace Easy4net.DBUtility +{ + /// + /// 数据库表操作类型定义 + /// + public enum DbOperateType + { + /// + /// 插入操作 + /// + [Description("插入操作")] + INSERT, + /// + /// 更新操作 + /// + [Description("更新操作")] + UPDATE, + /// + /// 删除操作 + /// + [Description("删除操作")] + DELETE, + /// + /// 查询操作 + /// + [Description("查询操作")] + SELECT, + /// + /// 获取记录数操作 + /// + [Description("获取记录数操作")] + COUNT + } +} diff --git a/类库/Api.Framework/Easy4/DBUtility/DbTypeConvert.cs b/类库/Api.Framework/Easy4/DBUtility/DbTypeConvert.cs new file mode 100644 index 0000000..f0df377 --- /dev/null +++ b/类库/Api.Framework/Easy4/DBUtility/DbTypeConvert.cs @@ -0,0 +1,20 @@ +using System; + +namespace Easy4net.DBUtility +{ + /// + /// 数据类型转换帮助类 + /// + public class DbTypeConvert + { + /// + /// 转为Decimal类型 + /// + /// + /// + static decimal ToDecimal(int value) + { + return Convert.ToDecimal(value); + } + } +} diff --git a/类库/Api.Framework/Easy4/TransactionManager/TransactionManager.cs b/类库/Api.Framework/Easy4/TransactionManager/TransactionManager.cs new file mode 100644 index 0000000..e8e3086 --- /dev/null +++ b/类库/Api.Framework/Easy4/TransactionManager/TransactionManager.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Data; +using System.Configuration; +using System.Data.SqlClient; +using System.Data.OracleClient; +using System.Data.Common; +using Orm.DBUtility; + +namespace Orm.DBTransaction +{ + public class TransactionManager + { + public static IDbTransaction CreateTransaction() + { + return DbFactory.CreateDbTransaction(); + } + } +} diff --git a/类库/Api.Framework/Easy4/Variety/MSSQL/OrmMSSQLConfig.cs b/类库/Api.Framework/Easy4/Variety/MSSQL/OrmMSSQLConfig.cs new file mode 100644 index 0000000..a9bfe82 --- /dev/null +++ b/类库/Api.Framework/Easy4/Variety/MSSQL/OrmMSSQLConfig.cs @@ -0,0 +1,137 @@ +using System; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using Easy4net.DBUtility; + +namespace Easy4net.Variety.MSSQL +{ + /// + /// MSSQL数据库配置类 + /// + public class OrmMSSQLConfig : OrmConfig + { + /// + /// MSSQL关键字集合 + /// + private readonly static string[] _keyMSSQL = { "order", "desc", "key", "text", "limit", "offset", "password" }; + + /// + /// 获取当前支持的数据库类型 + /// + public override DatabaseType DbType + { + get + { + return DatabaseType.SQLSERVER; + } + } + /// + /// 获取对应的数据库参数字符前缀 + /// + public override string DbParamChar + { + get + { + return "@"; + } + } + + /// + /// 创建一个数据库参数对象 + /// + /// + public OrmMSSQLConfig(string aConn) + { + this.ConnectionString = aConn; + } + + /// + /// 根据MSSQL数据库参数获取一个MSSQL的数据库参数对象 + /// + /// + public OrmMSSQLConfig(SqlConnectionParam aPrm) + { + this.ConnectionString = SqlConnectionParam.GetConnectionString(aPrm); + } + + /// + /// 根据当前的全局配置获取一个MSSQL的数据库参数对象 + /// + public OrmMSSQLConfig() + { + this.ConnectionString = SqlConnectionParam.ConnectionString; + } + + /// + /// 创建一个数据库链接对象 + /// + /// + internal override IDbConnection CreateDbConnection() + { + return new SqlConnection(ConnectionString); + } + + /// + /// 创建一个数据库命令对象 + /// + /// + internal override IDbCommand CreateDbCommand() + { + return new SqlCommand(); + } + + /// + /// 创建数据库适配器对象 + /// + /// + internal override IDbDataAdapter CreateDataAdapter() + { + return new SqlDataAdapter(); + } + + /// + /// 根据传入的命令对象创建适配器对象 + /// + /// + /// + internal override IDbDataAdapter CreateDataAdapter(IDbCommand aCmd) + { + return new SqlDataAdapter((SqlCommand)aCmd); + } + + /// + /// 创建数据库参数对象 + /// + /// + public override IDbDataParameter CreateDbParameter() + { + return new SqlParameter(); + } + + /// + /// 检查MSSQL列名是否为数据库的关键字,是则进行格式化,否则返回原列名 + /// + /// + /// + internal override string FormatColumnName(string aColounName) + { + string tmp_str = aColounName.ToLower(); + if (_keyMSSQL.Contains(tmp_str)) + { + return string.Format("[{0}]", tmp_str); + } + + return aColounName; + } + + /// + /// 生成获取自增长列的新添加值的SQL语句 + /// + /// + internal override string GetAutoSql() + { + return " SELECT scope_identity() as AutoId "; + } + } +} diff --git a/类库/Api.Framework/Easy4/Variety/MSSQL/SqlConnectionParam.cs b/类库/Api.Framework/Easy4/Variety/MSSQL/SqlConnectionParam.cs new file mode 100644 index 0000000..fc109f9 --- /dev/null +++ b/类库/Api.Framework/Easy4/Variety/MSSQL/SqlConnectionParam.cs @@ -0,0 +1,181 @@ +using System; +using System.Linq; +using System.Text; + +namespace Easy4net.Variety.MSSQL +{ + /// + /// SQL数据库连接参数配置类 + /// + public class SqlConnectionParam + { + /// + /// 数据库连接字符串 + /// + internal static string ConnectionString { get; private set; } + + /// + /// 数据库主机地址 + /// + public string DbHost { get; private set; } + /// + /// 数据库端口 + /// + public string DbPort { get; private set; } + /// + /// 数据库名 + /// + public string DbName { get; private set; } + /// + /// 数据库用户名 + /// + public string DbUser { get; private set; } + /// + /// 数据库密码 + /// + public string DbPassword { get; private set; } + + /// + /// 最小缓存池大小,空则未配置 + /// + public string DbMinPoolSize { get; private set; } + /// + /// 最大缓存池大小,空则未配置 + /// + public string DbMaxPoolSize { get; private set; } + + /// + /// 字符集设置,空则未配置 + /// + public string DbCharset { get; private set; } + + /// + /// 新建一个MSSQL链接参数对象 + /// + /// 数据库主机地址 + /// 端口号 + /// 数据库名 + /// 用户名 + /// 密码 + public SqlConnectionParam(string aHost, string aPort, string aName, + string aUser, string aPassword) + { + this.DbHost = aHost; + this.DbPort = aPort; + this.DbName = aName; + this.DbUser = aUser; + this.DbPassword = aPassword; + } + + /// + /// 新建一个MSSQL链接参数对象 + /// + /// 数据库主机地址 + /// 端口号 + /// 数据库名 + /// 用户名 + /// 密码 + /// 字符集 + public SqlConnectionParam(string aHost, string aPort, string aName, + string aUser, string aPassword, string aCharset) + : this(aHost, aPort, aName, aUser, aPassword) + { + this.DbCharset = aCharset; + } + + /// + /// 新建一个MSSQL链接参数对象 + /// + /// 数据库主机地址 + /// 端口号 + /// 数据库名 + /// 用户名 + /// 密码 + /// 最小缓存池大小 + /// 最大缓存池大小 + public SqlConnectionParam(string aHost, string aPort, string aName, + string aUser, string aPassword, + string aMinPool, string aMaxPool) + : this(aHost, aPort, aName, aUser, aPassword) + { + this.DbMinPoolSize = aMinPool; + this.DbMaxPoolSize = aMaxPool; + } + + /// + /// 新建一个MSSQL链接参数对象 + /// + /// 数据库主机地址 + /// 端口号 + /// 数据库名 + /// 用户名 + /// 密码 + /// 最小缓存池大小 + /// 最大缓存池大小 + /// 字符集 + public SqlConnectionParam(string aHost, string aPort, string aName, + string aUser, string aPassword, + string aMinPool, string aMaxPool, string aCharset) + : this(aHost, aPort, aName, aUser, aPassword, aMinPool, aMaxPool) + { + this.DbCharset = aCharset; + } + + /// + /// 将当前参数设置为全局连接参数 + /// + public void SetGlobal() + { + // 更新连接字符串 + ConnectionString = GetConnectionString(this); + } + + /// + /// 输出当前连接参数字符串 + /// + /// + public override string ToString() + { + return GetConnectionString(this); + } + + /// + /// 根据当前的变量生成链接字符串 + /// + /// 数据库连接参数 + /// 连接字符串 + internal static string GetConnectionString(SqlConnectionParam aParam) + { + StringBuilder tmp_sb = new StringBuilder(); + tmp_sb.Append("Data Source=").Append(aParam.DbHost); + + if (!String.IsNullOrEmpty(aParam.DbPort)) + { + tmp_sb.Append(",").Append(aParam.DbPort); + } + + tmp_sb.Append(";"); + tmp_sb.AppendFormat("User ID={0};", aParam.DbUser); + // 解密密码 + tmp_sb.AppendFormat("Password={0};", aParam.DbPassword); + tmp_sb.AppendFormat("DataBase={0};", aParam.DbName); + + if (!String.IsNullOrEmpty(aParam.DbMinPoolSize)) + { + tmp_sb.AppendFormat("Min Pool Size={0};", aParam.DbMinPoolSize); + } + + if (!String.IsNullOrEmpty(aParam.DbMaxPoolSize)) + { + tmp_sb.AppendFormat("Max Pool Size={0};", aParam.DbMaxPoolSize); + } + + if (!String.IsNullOrEmpty(aParam.DbCharset)) + { + tmp_sb.AppendFormat("charset={0};", aParam.DbCharset); + } + + return tmp_sb.ToString(); + } + } +} diff --git a/类库/Api.Framework/Easy4/Variety/OrmConfig.cs b/类库/Api.Framework/Easy4/Variety/OrmConfig.cs new file mode 100644 index 0000000..8d30664 --- /dev/null +++ b/类库/Api.Framework/Easy4/Variety/OrmConfig.cs @@ -0,0 +1,159 @@ +using System; +using System.Data; +using System.Linq; +using Easy4net.DBUtility; + +namespace Easy4net.Variety +{ + /// + /// ORM配置基类 + /// + public abstract class OrmConfig + { + /// + /// 获取当前支持的数据库类型 + /// + public abstract DatabaseType DbType { get; } + /// + /// 获取对应的数据库参数字符前缀 + /// + public abstract string DbParamChar { get; } + /// + /// 获取数据库连接字符串 + /// + public string ConnectionString { get; protected set; } + + /// + /// 创建一个数据库链接对象 + /// + /// + internal abstract IDbConnection CreateDbConnection(); + /// + /// 创建一个数据库命令对象 + /// + /// + internal abstract IDbCommand CreateDbCommand(); + /// + /// 创建数据库适配器对象 + /// + /// + internal abstract IDbDataAdapter CreateDataAdapter(); + /// + /// 根据传入的命令对象创建适配器对象 + /// + /// + /// + internal abstract IDbDataAdapter CreateDataAdapter(IDbCommand aCmd); + /// + /// 打开数据库连接并创建事物对象 + /// + /// + internal virtual IDbTransaction CreateDbTransaction() + { + IDbConnection conn = CreateDbConnection(); + if (conn.State == ConnectionState.Closed) + { + conn.Open(); + } + + return conn.BeginTransaction(); + } + + /// + /// 打开数据库连接并创建指定连接行为的事物对象 + /// + /// + /// + internal virtual IDbTransaction CreateDbTransaction(IsolationLevel aLevel) + { + IDbConnection conn = CreateDbConnection(); + if (conn.State == ConnectionState.Closed) + { + conn.Open(); + } + + return conn.BeginTransaction(aLevel); + } + + /// + /// 创建数据库参数对象 + /// + /// + public abstract IDbDataParameter CreateDbParameter(); + + /// + /// 根据参数名与值创建数据库参数对象 + /// + /// + /// + /// + public virtual IDbDataParameter CreateDbParameter(string aPrmName, object aValue) + { + IDbDataParameter param = CreateDbParameter(); + param.ParameterName = aPrmName; + param.Value = aValue; + + return param; + } + + /// + /// 根据参数名与值及参数值类型创建一个数据库参数对象 + /// + /// + /// + /// 参数值的数据类型 + /// + public virtual IDbDataParameter CreateDbParameter(string aPrmName, object aValue, DbType aDbType) + { + IDbDataParameter param = CreateDbParameter(aPrmName, aValue); + param.DbType = aDbType; + + return param; + } + + /// + /// 根据参数名与值及参数输入输出类型创建一个数据库参数对象 + /// + /// + /// + /// + /// + public virtual IDbDataParameter CreateDbParameter(string aPrmName, object aValue, ParameterDirection aDirection) + { + IDbDataParameter param = CreateDbParameter(aPrmName, aValue); + param.Direction = aDirection; + + return param; + } + + /// + /// 根据参数名,值,参数大小,参数方向类型创建一个参数对象 + /// + /// + /// + /// + /// + /// + /// + public virtual IDbDataParameter CreateDbParameter(string aPrmName, object aValue, DbType aDbType, int aSize, ParameterDirection aDirection) + { + IDbDataParameter param = CreateDbParameter(aPrmName, aValue, aDbType); + param.Size = aSize; + param.Direction = aDirection; + + return param; + } + + /// + /// 格式化字段名 + /// + /// + /// + internal abstract string FormatColumnName(string aColumnName); + /// + /// 生成获取自增长列的新添加值的SQL语句 + /// + /// + internal abstract string GetAutoSql(); + } +} diff --git a/类库/Api.Framework/Easy4/Variety/SQLite/OrmSQLiteConfig.cs b/类库/Api.Framework/Easy4/Variety/SQLite/OrmSQLiteConfig.cs new file mode 100644 index 0000000..ce2077f --- /dev/null +++ b/类库/Api.Framework/Easy4/Variety/SQLite/OrmSQLiteConfig.cs @@ -0,0 +1,154 @@ +using System; +using System.Data; +using System.Data.SQLite; +using System.Linq; +using Easy4net.DBUtility; + +namespace Easy4net.Variety.SQLite +{ + /// + /// SQLite数据库配置类 + /// + public class OrmSQLiteConfig : OrmConfig + { + /// + /// SQLite关键字集合 + /// + private readonly static string[] _keySQLite = { "order", "desc", "key" }; + + /// + /// 获取当前支持的数据库类型 + /// + public override DatabaseType DbType + { + get + { + return DatabaseType.SQLITE; + } + } + + /// + /// 获取对应的数据库参数字符前缀 + /// + public override string DbParamChar + { + get + { + return "@"; + } + } + + /// + /// 创建一个数据库参数对象 + /// + /// + public OrmSQLiteConfig(string aConn) + { + this.ConnectionString = aConn; + } + + /// + /// 根据SQLite数据库参数获取一个MSSQL的数据库参数对象 + /// + /// + public OrmSQLiteConfig(SQLiteConnectionParam aPrm) + { + this.ConnectionString = SQLiteConnectionParam.GetConnectionString(aPrm); + } + + /// + /// 根据当前的全局配置获取一个SQLite的数据库参数对象 + /// + public OrmSQLiteConfig() + { + this.ConnectionString = SQLiteConnectionParam.ConnectionString; + } + + + /// + /// 创建一个数据库链接对象 + /// + /// + internal override IDbConnection CreateDbConnection() + { + return new SQLiteConnection(ConnectionString); + } + + /// + /// 创建一个数据库命令对象 + /// + /// + internal override IDbCommand CreateDbCommand() + { + return new SQLiteCommand(); + } + + /// + /// 创建数据库适配器对象 + /// + /// + internal override IDbDataAdapter CreateDataAdapter() + { + return new SQLiteDataAdapter(); + } + + /// + /// 根据传入的命令对象创建适配器对象 + /// + /// + /// + internal override IDbDataAdapter CreateDataAdapter(IDbCommand aCmd) + { + return new SQLiteDataAdapter((SQLiteCommand)aCmd); + } + + /// + /// 创建数据库参数对象 + /// + /// + public override IDbDataParameter CreateDbParameter() + { + return new SQLiteParameter(); + } + + /// + /// 根据参数名与值创建数据库参数对象 + /// + /// + /// + /// + public override IDbDataParameter CreateDbParameter(string aPrmName, object aValue) + { + IDbDataParameter param = CreateDbParameter(); + param.ParameterName = "@" + aPrmName; + param.Value = aValue; + + return param; + } + + /// + /// 检查SQLite列名是否为数据库的关键字,是则进行格式化,否则返回原列名 + /// + /// + /// + internal override string FormatColumnName(string aColounName) + { + string tmp_str = aColounName.ToLower(); + if (_keySQLite.Contains(tmp_str)) + { + return string.Format("`{0}`", tmp_str); + } + + return aColounName; + } + + /// + /// 生成获取自增长列的新添加值的SQL语句 + /// + /// + internal override string GetAutoSql() + { + return " ;select last_insert_rowid() as AutoId "; + } + } +} diff --git a/类库/Api.Framework/Easy4/Variety/SQLite/SQLiteConnectionParam.cs b/类库/Api.Framework/Easy4/Variety/SQLite/SQLiteConnectionParam.cs new file mode 100644 index 0000000..0160bb0 --- /dev/null +++ b/类库/Api.Framework/Easy4/Variety/SQLite/SQLiteConnectionParam.cs @@ -0,0 +1,82 @@ +using System; +using System.Linq; +using System.Text; + +namespace Easy4net.Variety.SQLite +{ + /// + /// SQLite数据库连接参数 + /// + public class SQLiteConnectionParam + { + /// + /// 数据库连接字符串 + /// + internal static string ConnectionString { get; private set; } + + /// + /// SQLite数据库路径 + /// + public string FileName { get; private set; } + /// + /// SQLite数据库密码 + /// + public string Password { get; private set; } + + /// + /// 创建一个无密码的SQLite数据库参数 + /// + /// 数据库文件路径 + public SQLiteConnectionParam(string aFile) + { + this.FileName = aFile; + } + + /// + /// 创建一个带密码的SQLite数据库参数 + /// + /// + /// + public SQLiteConnectionParam(string aFile, string aPwd) + : this(aFile) + { + this.Password = aPwd; + } + + /// + /// 将当前参数设置为全局连接参数 + /// + public void SetGlobal() + { + // 更新连接字符串 + ConnectionString = GetConnectionString(this); + } + + /// + /// 输出当前连接参数字符串 + /// + /// + public override string ToString() + { + return GetConnectionString(this); + } + + /// + /// 根据当前的变量生成链接字符串 + /// + /// 数据库连接参数 + /// 连接字符串 + internal static string GetConnectionString(SQLiteConnectionParam aParam) + { + StringBuilder tmp_sb = new StringBuilder(); + tmp_sb.AppendFormat("Data Source='{0}';", aParam.FileName); + + if (!String.IsNullOrEmpty(aParam.Password)) + { + tmp_sb.AppendFormat("password={0}", aParam.Password); + } + + return tmp_sb.ToString(); + } + } +} diff --git a/类库/Api.Framework/EntityTmp/Douyin/DyItemInfo.cs b/类库/Api.Framework/EntityTmp/Douyin/DyItemInfo.cs new file mode 100644 index 0000000..4d8c48d --- /dev/null +++ b/类库/Api.Framework/EntityTmp/Douyin/DyItemInfo.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.Douyin +{ + /// + /// 抖音商品信息 + /// + public class DyItemInfo + { + /// + /// 数量 + /// + public long total { get; set; } + /// + /// 商品信息 + /// + public List products { get; set; } + + } + public class Products + { + public List daily_statistics { get; set; } + + public Shoptotalscore shop_total_score { get; set; } + /// + /// 商品id + /// + public long product_id { get; set; } + /// + /// 商品标题 + /// + public string title { get; set; } + /// + /// 商品售价(单位为分) + /// + public long price { get; set; } + /// + /// 普通佣金比例(乘100,例如10%为10) + /// + public double cos_ratio { get; set; } + /// + /// 普通佣金金额(单位为分) + /// + public long cos_fee { get; set; } + /// + /// 商品一级类目 + /// + public long? first_cid { get; set; } + /// + /// 商品二级类目 + /// + public long? second_cid { get; set; } + /// + /// 商品三级类目 + /// + public long? third_cid { get; set; } + /// + /// 是否有库存 + /// + public bool in_stock { get; set; } + /// + /// 销量 + /// + public long? sales { get; set; } + /// + /// 商品主图 + /// + public string cover { get; set; } + /// + /// 商品轮播图 + /// + public List imgs { get; set; } + /// + /// 商品链接(普通计划链接) + /// + public string detail_url { get; set; } + /// + /// 店铺ID + /// + public long shop_id { get; set; } + /// + /// 店铺名称 + /// + public string shop_name { get; set; } + /// + /// 商品活动审核状态 + /// + public long? status { get; set; } + /// + /// 活动审核原因 + /// + public string reason { get; set; } + /// + /// 达人佣金比例 + /// + public double? kol_cos_ratio { get; set; } + /// + /// 达人佣金金额(单位为分) + /// + public long? kol_cos_fee { get; set; } + /// + /// 商品评分(5分制,保留一位) + /// + public double? comment_score { get; set; } + /// + /// 商品评价数目 + /// + public long? comment_num { get; set; } + /// + /// 近30天商品总订单量 + /// + public long? order_num { get; set; } + /// + /// 近30天商品总浏览量 + /// + public long? view_num { get; set; } + /// + /// 近30天推广总达人数 + /// + public long? kol_num { get; set; } + /// + /// 专属团长功能活动对应的限制类目名称 + /// + public string category_name { get; set; } + /// + /// 专属团长功能活动对应的限制类目名称id + /// + public long? category_id { get; set; } + /// + /// 商品物流说明 + /// + public string logistics_info { get; set; } + /// + /// 是否具有短视频随心推资质 + /// + public bool has_sxt { get; set; } + /// + /// 券后价 + /// + public double? coupon_price { get; set; } + /// + /// 是否可分销 + /// + public string sharable { get; set; } + } + public class Daily_statistics + { + /// + /// 日期 + /// + public string date { get; set; } + /// + /// 当日商品订单量明细 + /// + public long? order_num { get; set; } + /// + /// 当日商品浏览量明细 + /// + public long? view_num { get; set; } + /// + /// 当日推广达人数明细 + /// + public long? kol_num { get; set; } + } + public class Shoptotalscore + { + public Shopinfo shop_score { get; set; } + public Shopinfo product_Score { get; set; } + public Shopinfo logistics_score { get; set; } + public Shopinfo service_score { get; set; } + } + public class Shopinfo + { + /// + /// 文本 + /// + public string text { get; set; } + /// + /// 得分 + /// + public string score { get; set; } + /// + /// 等级 + /// + public long? level { get; set; } + } +} diff --git a/类库/Api.Framework/EntityTmp/Douyin/DyOrderInfo.cs b/类库/Api.Framework/EntityTmp/Douyin/DyOrderInfo.cs new file mode 100644 index 0000000..fb32d8b --- /dev/null +++ b/类库/Api.Framework/EntityTmp/Douyin/DyOrderInfo.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.Douyin +{ + public class DyOrderInfo + { + public List orders { get; set; } + /// + /// 下一页索引 + /// + public string cursor { get; set; } + } + public class Orders + { + public Pidinfo pid_info { get; set; } + /// + /// 订单号 + /// + public string order_id { get; set; } + /// + /// 商品id + /// + public string product_id { get; set; } + /// + /// 商品名称 + /// + public string product_name { get; set; } + /// + /// 商品图片URL + /// + public string product_img { get; set; } + /// + /// 作者账号昵称(抖音/火山作者) + /// + public string author_account { get; set; } + /// + /// 作者抖店open_id + /// + public string author_openid { get; set; } + /// + /// 商家名称 + /// + public string shop_name { get; set; } + /// + /// 订单支付金额,单位分 + /// + public double total_pay_amount { get; set; } + /// + /// 达人佣金率,此处保存为真实数据x1万之后,如真实是0.35,这里是3500 + /// + public double commission_rate { get; set; } + /// + /// 达人预估佣金收入,单位分 (已经扣除了技术费) + /// + public int estimated_commission { get; set; } + /// + /// 达人实际佣金收入,单位分 + /// + public double real_commission { get; set; } + /// + /// 订单状态(PAY_SUCC:支付完成 REFUND:退款 SETTLE:结算 CONFIRM: 确认收货) + /// + public string flow_point { get; set; } + /// + /// App名称(抖音,火山) + /// + public string app { get; set; } + /// + /// 下单用户抖店open_id + /// + public string buyer_openid { get; set; } + /// + /// 更新时间 [联盟侧订单更新时间] + /// + public string update_time { get; set; } + /// + /// 付款时间 + /// + public string pay_success_time { get; set; } + /// + /// 结算时间,结算前为空字符串 + /// + public string settle_time { get; set; } + /// + /// 预估参与结算金额 + /// + public int pay_goods_amount { get; set; } + /// + /// 实际参与结算金额 + /// + public double settled_goods_amount { get; set; } + /// + /// 店铺ID + /// + public long shop_id { get; set; } + /// + /// 预估平台技术服务费 + /// + public double shop_estimated_commission { get; set; } + /// + /// 实际参与结算金额 + /// + public double shop_real_commission { get; set; } + /// + /// 预估平台技术服务费 + /// + public double estimated_tech_service_fee { get; set; } + /// + /// 实际参与结算金额 + /// + public double settled_tech_service_fee { get; set; } + /// + /// 商品数目 + /// + public long item_num { get; set; } + /// + /// 退款订单退款时间 + /// + public string refund_time { get; set; } + /// + /// 总佣金(预估),对应百应订单明细中的总佣金 + /// + public double estimated_total_commission { get; set; } + /// + /// 选品App client_key + /// + public string pick_source_client_key { get; set; } + /// + /// 达人/自播商家给直播间分销渠道设置的分成比 + /// + public double ads_split_rate { get; set; } + /// + /// 直播间分销渠道预估佣金收入,单位分 + /// + public double ads_estimated_commission { get; set; } + /// + /// 直播间分销渠道实际佣金收入,单位分 + /// + public double ads_real_commission { get; set; } + /// + /// 达人抖音号 + /// + public string author_short_id { get; set; } + /// + /// 达人/自播商家给直播间分销渠道设置的推广费率 + /// + public double ads_promotion_rate { get; set; } + /// + /// 达人百应ID + /// + public string author_buyin_id { get; set; } + /// + /// 带货体裁。shop_list:橱窗;video:视频;live:直播;others:其他 + /// + public string media_type { get; set; } + } + public class Pidinfo + { + /// + /// PID + /// + public string pid { get; set; } + /// + /// 外部参数 + /// + public string external_info { get; set; } + /// + /// 分销类型,直播:Live,商品:ProductDetail + /// + public string media_type_name { get; set; } + } +} diff --git a/类库/Api.Framework/EntityTmp/Douyin/KolPidList.cs b/类库/Api.Framework/EntityTmp/Douyin/KolPidList.cs new file mode 100644 index 0000000..e912065 --- /dev/null +++ b/类库/Api.Framework/EntityTmp/Douyin/KolPidList.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.Douyin +{ + /// + /// 抖音推广位 + /// + public class KolPidList + { + /// + /// 总数 + /// + public int total { get; set; } + + public List pids { get; set; } + + } + + /// + /// pid信息 + /// + public class PidInfo + { + /// + /// pid + /// + public string pid { get; set; } + /// + /// 推广媒体类型 + /// + public int media_type { get; set; } + /// + /// 渠道ID + /// + public long media_id { get; set; } + /// + /// 渠道名称 + /// + public string media_name { get; set; } + /// + /// 推广位名称 + /// + public string site_name { get; set; } + /// + /// 创建时间 + /// + public long create_time { get; set; } + /// + /// 创建时间 + /// + public long update_time { get; set; } + + } +} diff --git a/类库/Api.Framework/EntityTmp/Douyin/ShareInfo.cs b/类库/Api.Framework/EntityTmp/Douyin/ShareInfo.cs new file mode 100644 index 0000000..4b25d0d --- /dev/null +++ b/类库/Api.Framework/EntityTmp/Douyin/ShareInfo.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.Douyin +{ + /// + /// 转链信息 + /// + public class ShareInfo + { + /// + /// 抖口令 + /// + public string dy_password { get; set; } + + /// + /// deeplink + /// + public string dy_deeplink { get; set; } + + /// + /// 二维码信息 + /// + public DyQrCode qr_code { get; set; } + + } + + public class DyQrCode + { + /// + /// 图片地址 + /// + public string url { get; set; } + /// + /// 宽度 + /// + public int width { get; set; } + /// + /// 高度 + /// + public int height { get; set; } + } + +} diff --git a/类库/Api.Framework/EntityTmp/KuaiShou/KS_ItemInfo.cs b/类库/Api.Framework/EntityTmp/KuaiShou/KS_ItemInfo.cs new file mode 100644 index 0000000..86f3bd9 --- /dev/null +++ b/类库/Api.Framework/EntityTmp/KuaiShou/KS_ItemInfo.cs @@ -0,0 +1,80 @@ +using System.Collections.Generic; + +namespace Api.Framework.EntityTmp.KuaiShou +{ + /// + /// 商品信息 + /// + public class KS_ItemInfo + { + /// + /// 频道id列表 + /// + public List channelIds { get; set; } + /// + /// 商品id + /// + public long goodsId { get; set; } + /// + /// 商品价格(分) + /// + public long goodsPrice { get; set; } + /// + /// 折扣价 + /// + public long zkGoodsPrice { get; set; } + /// + /// 标题 + /// + public string goodsTitle { get; set; } + /// + /// 商品描述 + /// + public string goodsDesc { get; set; } + /// + /// 卖家id + /// + public long mallId { get; set; } + /// + /// 店铺名称 + /// + public string mallName { get; set; } + /// + /// 店铺类型(列表接口下无数据):0-未知,1-旗舰店,2-专门店,3-专营店,4-卖场旗舰店,5-普通企业店,6-个人店,7-个体工商户 + /// + public int mallType { get; set; } + /// + /// 商品图片链接 + /// + public string goodsImageUrl { get; set; } + /// + /// 类目id + /// + public int categoryId { get; set; } + /// + /// 佣金率(千分比) + /// + public int promotionRate { get; set; } + /// + /// 30销量 + /// + public long salesTip { get; set; } + /// + /// 轮播图列表,仅在获取详情接口时返回 + /// + public List goodsGalleryUrls { get; set; } + /// + /// 推广预估佣金(分) + /// + public long promotionAmount { get; set; } + /// + /// 商品详情图,仅在获取详情接口时返回 + /// + public List itemDescUrls { get; set; } + /// + /// 运费模版id,-1时为全国包邮模版,0时表示状态不正确。其他值可以使用开放平台获取运费模版接口获取具体运费信息 + /// + public long expressId { get; set; } + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/EntityTmp/KuaiShou/KS_OrderInfo.cs b/类库/Api.Framework/EntityTmp/KuaiShou/KS_OrderInfo.cs new file mode 100644 index 0000000..ceeb76e --- /dev/null +++ b/类库/Api.Framework/EntityTmp/KuaiShou/KS_OrderInfo.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.KuaiShou +{ + /// + /// 订单数据 + /// + public class KS_OrderInfo + { + /// + /// 订单集合 + /// + public List orderList { get; set; } + + /// + /// 下次请求需要传的游标参数 + /// + public string pcursor { get; set; } + } + + + public class OrderList + { + /// + /// 订单号 + /// + public long oid { get; set; } + + /// + /// 订单状态 [0:全部订单] [30:已付款] [50:已收货] [60:已结算] [80:已失效] + /// + public int cpsOrderStatus { get; set; } + + /// + /// 订单创建时间 + /// + public long orderCreateTime { get; set; } + + /// + /// 支付时间 + /// + public long payTime { get; set; } + + /// + /// 订单金额,单位分 + /// + public int orderTradeAmount { get; set; } + + /// + /// 分销订单生成时间 + /// + public long createTime { get; set; } + + /// + /// 分销订单更新时间 + /// + public long updateTime { get; set; } + + /// + /// 结算成功时间 + /// + public long settlementSuccessTime { get; set; } + + /// + /// 结算金额,单位分 + /// + public int settlementAmount { get; set; } + + + /// + /// 所属快手账号ID + /// + public long kwaimoneyUserId { get; set; } + + /// + /// 快赚客商品列表 + /// + public List cpsKwaimoneyOrderProductView { get; set; } + + /// + /// 商品列表 + /// + public List cpsOrderProductView { get; set; } + + } + + //public class CpsKwaimoneyOrderProductView + public class CpsOrderProductView + { + /// + /// 子订单号 + /// + public long oid { get; set; } + + /// + /// 商品ID + /// + public long itemId { get; set; } + + /// + /// 商品标题 + /// + public string itemTitle { get; set; } + + /// + /// 商品头图 + /// + public string itemPicUrl { get; set; } + + /// + /// 商品金额快照,单位分 + /// + public int itemPrice { get; set; } + + /// + /// 规格描述 + /// + public string skuDesc { get; set; } + + /// + /// 预估收入,单位分 + /// + public int estimatedIncome { get; set; } + + /// + /// 佣金率,单位千分之一 + /// + public int commissionRate { get; set; } + + /// + /// 推广位pid + /// + public string cpsPid { get; set; } + + /// + /// 卖家id + /// + public long sellerId { get; set; } + + /// + /// 卖家昵称 + /// + public string sellerNickname { get; set; } + + /// + /// 购买数量 + /// + public int num { get; set; } + + /// + /// 分销订单类型:3-达人直播间分销 + /// + public int cpsType { get; set; } + + /// + /// 达人id + /// + public long distributorId { get; set; } + + /// + /// 达人昵称 + /// + public string distributorNickname { get; set; } + + /// + /// 备注(创建商品时的自定义参数) + /// + public string comments { get; set; } + + /// + /// pid名称 + /// + public string pidName { get; set; } + + /// + /// 实付金额(分) + /// + public int paymentFee { get; set; } + } + + //public class CpsOrderProductView + //{ + // /// + // /// + // /// + // public int oid { get; set; } + // /// + // /// + // /// + // public int itemId { get; set; } + // /// + // /// 罗马仕安卓数据线快充加长蓝牙耳机充电线器闪充micro usb + // /// + // public string itemTitle { get; set; } + // /// + // /// + // /// + // public int itemPrice { get; set; } + // /// + // /// + // /// + // public int estimatedIncome { get; set; } + // /// + // /// + // /// + // public int commissionRate { get; set; } + // /// + // /// + // /// + // public string cpsPid { get; set; } + // /// + // /// + // /// + // public int sellerId { get; set; } + // /// + // /// ROMOSS罗马仕旗舰店 + // /// + // public string sellerNickname { get; set; } + // /// + // /// + // /// + // public int num { get; set; } + // /// + // /// + // /// + // public int cpsType { get; set; } + // /// + // /// + // /// + // public int distributorId { get; set; } + // /// + // /// ROMOSS罗马仕旗舰店 + // /// + // public string distributorNickname { get; set; } + // /// + // /// + // /// + // public string comments { get; set; } + // /// + // /// + // /// + // public string pidName { get; set; } + // /// + // /// 高雅黑【3A快充单条装】,1m + // /// + // public string skuDesc { get; set; } + // /// + // /// + // /// + // public string itemPicUrl { get; set; } + // /// + // /// + // /// + // public int paymentFee { get; set; } + //} +} diff --git a/类库/Api.Framework/EntityTmp/KuaiShou/KS_TuiGuangWeiInfo.cs b/类库/Api.Framework/EntityTmp/KuaiShou/KS_TuiGuangWeiInfo.cs new file mode 100644 index 0000000..c28cbd6 --- /dev/null +++ b/类库/Api.Framework/EntityTmp/KuaiShou/KS_TuiGuangWeiInfo.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.KuaiShou +{ + /// + /// 快手推广位信息 + /// + public class KS_TuiGuangWeiInfo + { + /// + /// 推广位名称 + /// + public string promotionBitName { get; set; } + /// + /// 创建时间 + /// + public long createTime { get; set; } + /// + /// 推广位cps pid + /// + public string cpsPid { get; set; } + /// + /// 状态 + /// + public int status { get; set; } + } +} diff --git a/类库/Api.Framework/EntityTmp/KuaiShou/KS_TurnUrlInfo.cs b/类库/Api.Framework/EntityTmp/KuaiShou/KS_TurnUrlInfo.cs new file mode 100644 index 0000000..989a791 --- /dev/null +++ b/类库/Api.Framework/EntityTmp/KuaiShou/KS_TurnUrlInfo.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.KuaiShou +{ + /// + /// 快手转链信息 + /// + public class KS_TurnUrlInfo + { + /// + /// 口令 + /// + public string linkCode { get; set; } + /// + /// 转链链接 + /// + public string linkUrl { get; set; } + /// + /// kwai url + /// + public string kwaiUrl { get; set; } + /// + /// 快赚客推广位cps pid + /// + public string cpsPid { get; set; } + /// + /// 极速版kwai url + /// + public string nebulaKwaiUrl { get; set; } + /// + /// 短链文案 + /// + public string shortContent { get; set; } + /// + /// 长链文案 + /// + public string longContent { get; set; } + /// + /// 口令文案 + /// + public string commandContent { get; set; } + /// + /// 分享token + /// + public string shareToken { get; set; } + /// + /// 小程序短链 + /// + public string minaShortLink { get; set; } + } +} diff --git a/类库/Api.Framework/EntityTmp/SuNing/Enums.cs b/类库/Api.Framework/EntityTmp/SuNing/Enums.cs new file mode 100644 index 0000000..24238dd --- /dev/null +++ b/类库/Api.Framework/EntityTmp/SuNing/Enums.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.SuNing +{ + /// + /// 苏宁类目枚举 + /// + public enum CategoryType + { + 小编推荐 = 1, + 实时热销榜 = 2, + 当日热推榜 = 3, + 高佣爆款榜 = 4, + 团长招商榜 = 5, + 九块九专区 = 6 + } +} diff --git a/类库/Api.Framework/EntityTmp/SuNing/SN_GoodInfo.cs b/类库/Api.Framework/EntityTmp/SuNing/SN_GoodInfo.cs new file mode 100644 index 0000000..b4f81e3 --- /dev/null +++ b/类库/Api.Framework/EntityTmp/SuNing/SN_GoodInfo.cs @@ -0,0 +1,580 @@ +using Api.Framework.EntityTmp.SuNing2; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.SuNing +{ + /// + /// 商品信息 + /// + public class SN_GoodInfo + { + /// + /// 响应体 + /// + public Sn_responseContent sn_responseContent { get; set; } + } + + public class Sn_responseContent + { + /// + /// 数据体 + /// + public Sn_body sn_body { get; set; } + + + public Sn_error sn_error { get; set; } + } + + public class Sn_body + { + /// + /// 查询商品的细节集合 + /// + public List queryCommoditydetail { get; set; } + /// + /// 搜索商品的细节集合 + /// + public List querySearchcommodity { get; set; } + } + + public class OrderActivity + { + /// + /// + /// + public List activityRuleList { get; set; } + /// + /// 99元任选4件 + /// + public string activityDescription { get; set; } + } + + public class ActivityRuleList + { + /// + /// + /// + public string couponAmount { get; set; } + /// + /// + /// + public string singleMaxRewardAmount { get; set; } + /// + /// + /// + public string baseAddUpType { get; set; } + /// + /// + /// + public string rewardQuantifierType { get; set; } + /// + /// + /// + public string scopeType { get; set; } + /// + /// + /// + public string baseQuantifierType { get; set; } + /// + /// + /// + public string rewardAmount { get; set; } + /// + /// + /// + public string floor { get; set; } + /// + /// + /// + public string baseAmount { get; set; } + } + + /// + /// 查询商品的细节 + /// + public class QueryCommoditydetail + { + /// + /// 订单活动 + /// + public OrderActivity orderActivity { get; set; } + /// + /// + /// + public CommodityInfo commodityInfo { get; set; } + /// + /// + /// + public PgInfo pgInfo { get; set; } + /// + /// + /// + public CategoryInfo categoryInfo { get; set; } + /// + /// + /// + public CouponInfo couponInfo { get; set; } + /// + /// + /// + public List couponInfoList { get; set; } + /// + /// + /// + public List actList { get; set; } + /// + /// + /// + public double? arrivalPrice { get; set; } + /// + /// + /// + public AdvanceSale advanceSale { get; set; } + /// + /// + /// + public List parametersList { get; set; } + /// + /// subCode + /// + public List subCodeList { get; set; } + /// + /// + /// + public CmmdtyReviewInfo cmmdtyReviewInfo { get; set; } + + } + + public class SubCodeList + { + /// + /// + /// + public string subCode { get; set; } + } + + public class CmmdtyReviewInfo + { + /// + /// 好评率 + /// + public string goodRate { get; set; } + /// + /// 好评数量 + /// + public int goodReviewCount { get; set; } + /// + /// 评价总数 + /// + public int totalReviewCount { get; set; } + } + + public class CouponInfoList + { + /// + /// + /// + public string bounsLimit { get; set; } + /// + /// + /// + public string activitySecretKey { get; set; } + /// + /// + /// + public DateTime? couponEndTime { get; set; } + /// + /// + /// + public string activityId { get; set; } + /// + /// + /// + public DateTime? couponStartTime { get; set; } + /// + /// + /// + public string couponUrl { get; set; } + /// + /// + /// + public string couponCount { get; set; } + /// + /// + /// + public DateTime? startTime { get; set; } + /// + /// 店铺易券(4元) + /// + public string activityDescription { get; set; } + /// + /// + /// + public DateTime? endTime { get; set; } + /// + /// + /// + public string couponValue { get; set; } + } + + public class ActRoleList + { + /// + /// + /// + public string couponAmount { get; set; } + /// + /// + /// + public string singleMaxRewardAmount { get; set; } + /// + /// + /// + public string baseAddUpType { get; set; } + /// + /// + /// + public string rewardQuantifierType { get; set; } + /// + /// + /// + public string scopeType { get; set; } + /// + /// + /// + public string baseQuantifierType { get; set; } + /// + /// + /// + public string rewardAmount { get; set; } + /// + /// + /// + public string floor { get; set; } + /// + /// + /// + public string baseAmount { get; set; } + } + + public class ActList + { + /// + /// + /// + public string activityId { get; set; } + /// + /// + /// + public List actRoleList { get; set; } + /// + /// 店铺易券(4元) + /// + public string activityDescription { get; set; } + /// + /// + /// + public string activityTypeId { get; set; } + } + + public class AdvanceSale + { + /// + /// 是否预售 + /// + public string isReserveCommodity { get; set; } + /// + /// 定金 + /// + public string depositAmount { get; set; } + /// + /// 付定金结束时间 + /// + public string depositEndTime { get; set; } + } + + public class ParametersList + { + /// + /// 参数说明文 + /// + public string explain { get; set; } + /// + /// 参数组描述 + /// + public string parameterDesc { get; set; } + /// + /// 参数组排序 + /// + public string sequence { get; set; } + /// + /// 参数描述值 + /// + public string parameterVal { get; set; } + /// + /// parameterCode + /// + public string parametersCode { get; set; } + /// + /// 参数排序码 + /// + public string parameterSequence { get; set; } + /// + /// 参数组描述 + /// + public string parametersDesc { get; set; } + /// + /// 核心参数 + /// + public string coreFlag { get; set; } + /// + /// 参数代码 + /// + public string parameterCode { get; set; } + } + + public class PictureUrl + { + /// + /// 图片Url + /// + public string picUrl { get; set; } + /// + /// 图片位置 + /// + public int locationId { get; set; } + } + + public class CommodityInfo + { + /// + /// 0不是 1是 + /// + public string isAct { get; set; } + /// + /// 商品名称 + /// + public string commodityName { get; set; } + /// + /// 商品编码 + /// + public string commodityCode { get; set; } + /// + /// 供应商编码(店铺id) + /// + public string supplierCode { get; set; } + /// + /// 供应商名称(店铺名) + /// + public string supplierName { get; set; } + /// + /// 图片信息 + /// + public List pictureUrl { get; set; } + /// + /// 商品卖点 + /// + public string sellingPoint { get; set; } + /// + /// 月销量 + /// + public int monthSales { get; set; } + /// + /// 原价 + /// + public string snPrice { get; set; } + /// + /// 当前价 + /// + public string commodityPrice { get; set; } + /// + /// 商品类型 1:自营 2:C店 3:海外购自营 4:海外购 5:特卖 6:极物 + /// + public int commodityType { get; set; } + /// + /// 价格类型 + /// + public string priceType { get; set; } + /// + /// 价格类型编码 0:正常价格,1:大聚惠 , 2:抢购, 3:渠道专享, 4:限时促销 ,5:爆款抢购,6:掌上抢,7:特卖,99:乐拼购 + /// + public int priceTypeCode { get; set; } + /// + /// 是否包邮 0:不包邮 1:包邮 + /// + public int baoyou { get; set; } + /// + /// 佣金比例 (数值为百分比数据) + /// + public string rate { get; set; } + /// + /// 是否可售 0:可售,1:无货,2:本地暂不销售 + /// + public int saleStatus { get; set; } + /// + /// 四级页地址 + /// + public string productUrl { get; set; } + /// + /// 1:禁售 0:非禁售 + /// + public string forbiddenMark { get; set; } + } + + public class PgInfo + { + /// + /// 成团人数 + /// + public string pgNum { get; set; } + /// + /// 拼购价 + /// + public string pgPrice { get; set; } + /// + /// 拼购四级页地址 + /// + public string pgUrl { get; set; } + /// + /// 拼购活动ID + /// + public string pgActionId { get; set; } + /// + /// 拼购商品起售数量 + /// + public string minOrderQuantity { get; set; } + } + + public class CategoryInfo + { + /// + /// 一级销售目录ID + /// + public string firstSaleCategoryId { get; set; } + /// + /// 一级销售目录名称 + /// + public string firstSaleCategoryName { get; set; } + /// + /// 二级销售目录ID + /// + public string secondSaleCategoryId { get; set; } + /// + /// 厨二级销售目录名称 + /// + public string secondSaleCategoryName { get; set; } + /// + /// 三级销售目录ID + /// + public string thirdSaleCategoryId { get; set; } + /// + /// 三级销售目录名称 + /// + public string thirdSaleCategoryName { get; set; } + /// + /// 一级采购目录ID + /// + public string firstPurchaseCategoryId { get; set; } + /// + /// 一级采购目录名称 + /// + public string firstPurchaseCategoryName { get; set; } + /// + /// 二级采购目录ID + /// + public string secondPurchaseCategoryId { get; set; } + /// + /// 二级采购目录名称 + /// + public string secondPurchaseCategoryName { get; set; } + /// + /// 三级采购目录ID + /// + public string thirdPurchaseCategoryId { get; set; } + /// + /// 三级采购目录名称 + /// + public string thirdPurchaseCategoryName { get; set; } + /// + /// 商品组目录ID + /// + public string goodsGroupCategoryId { get; set; } + /// + /// 商品组目录名称 + /// + public string goodsGroupCategoryName { get; set; } + } + + public class CouponInfo + { + /// + /// 券链接URL + /// + public string couponUrl { get; set; } + /// + /// 券活动编码 + /// + public string activityId { get; set; } + /// + /// 券秘钥 + /// + public string activitySecretKey { get; set; } + /// + /// 满30用4 + /// + public string preferentialDistinct { get; set; } + /// + /// + /// + public string couponShowType { get; set; } + /// + /// 4元 + /// + public string descriptionForList { get; set; } + /// + /// + /// + public string bounsAmount { get; set; } + /// + /// 券面额 + /// + public string couponValue { get; set; } + /// + /// 券总数 + /// + public string couponCount { get; set; } + /// + /// 券领取开始时间 + /// + public DateTime? couponStartTime { get; set; } + /// + /// 券领取结束时间 + /// + public DateTime? couponEndTime { get; set; } + /// + /// 券使用开始时间 + /// + public string startTime { get; set; } + /// + /// 券使用结束时间 + /// + public string endTime { get; set; } + /// + /// 基数数值 + /// + public string bounsLimit { get; set; } + /// + /// 活动描述 + /// + public string activityDescription { get; set; } + /// + /// 券后价 + /// + public string afterCouponPrice { get; set; } + } + +} diff --git a/类库/Api.Framework/EntityTmp/SuNing/SN_OrderInfo.cs b/类库/Api.Framework/EntityTmp/SuNing/SN_OrderInfo.cs new file mode 100644 index 0000000..cd8cd6c --- /dev/null +++ b/类库/Api.Framework/EntityTmp/SuNing/SN_OrderInfo.cs @@ -0,0 +1,195 @@ +using Api.Framework.EntityTmp.SuNing2; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.SuNing3 +{ + public class Sn_head + { + /// + /// + /// + public int totalSize { get; set; } + /// + /// + /// + public int pageTotal { get; set; } + /// + /// + /// + public int pageNo { get; set; } + /// + /// + /// + public string returnMessage { get; set; } + } + + public class OrderDetail + { + /// + /// 商品组目录编码 - R9001872 + /// + public string goodsGroupCatalog { get; set; } + /// + /// 商品归属 - 自营 + /// + public string orderType { get; set; } + /// + /// 支付时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime payTime { get; set; } + /// + /// 推广类型 - 链接推广 + /// + public string saleType { get; set; } + /// + /// 二级目录 + /// + public string productSecondCatalog { get; set; } + /// + /// 订单行项目状态 - 支付完成 + /// + public string orderLineStatusDesc { get; set; } + /// + /// 商品名称 + /// + public string productName { get; set; } + /// + /// 订单行标记 - 大聚惠 + /// + public string orderLineFlag { get; set; } + /// + /// 统计参数 + /// + public string statParam { get; set; } + /// + /// 商户编码 + /// + public string sellerCode { get; set; } + /// + /// 实付金额 + /// + public string payAmount { get; set; } + /// + /// 订单行来源(PC端、无线端) + /// + public string orderLineOrigin { get; set; } + /// + /// 一级目录 + /// + public string productFirstCatalog { get; set; } + /// + /// 商品编码 + /// + public string goodsNum { get; set; } + /// + /// 推广会员编码 + /// + public string custNo { get; set; } + /// + /// 商户名称 + /// + public string sellName { get; set; } + /// + /// 商品主图 + /// + public string pictureUrl { get; set; } + /// + /// 三级目录 + /// + public string productThirdCatalog { get; set; } + /// + /// 商品数量 + /// + public string saleNum { get; set; } + /// + /// 佣金比例 + /// + public string commissionRatio { get; set; } + /// + /// 是否返佣,0:否;1:是 + /// + public int returnCommission { get; set; } + /// + /// 预估佣金 + /// + public string prePayCommission { get; set; } + /// + /// 推广位ID + /// + public string positionId { get; set; } + /// + /// 是否违规,0:否;1:是 + /// + public int violation { get; set; } + /// + /// 下单时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime orderSubmitTime { get; set; } + /// + /// 订单行项目号 + /// + public string orderLineNumber { get; set; } + /// + /// 行项目状态更新时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime orderLineStatusChangeTime { get; set; } + /// + /// 1.风控订单 + /// + public int promotion { get; set; } + /// + /// 子推广账号ID(对应sub_user) + /// + public string childAccountId { get; set; } + } + + public class QueryOrder + { + /// + /// 订单号 + /// + public string orderCode { get; set; } + /// + /// 订单详情 + /// + public List orderDetail { get; set; } + } + + public class Sn_body + { + /// + /// 订单集合 + /// + public List queryOrder { get; set; } + + public Sn_error sn_error { get; set; } + } + + public class Sn_responseContent + { + /// + /// + /// + public Sn_head sn_head { get; set; } + /// + /// 数据体 + /// + public Sn_body sn_body { get; set; } + /// + /// 错误体 + /// + public Sn_error sn_error { get; set; } + } + + public class SN_OrderInfo + { + /// + /// 响应体 + /// + public Sn_responseContent sn_responseContent { get; set; } + } +} diff --git a/类库/Api.Framework/EntityTmp/SuNing/SN_QueryCommoditydetail.cs b/类库/Api.Framework/EntityTmp/SuNing/SN_QueryCommoditydetail.cs new file mode 100644 index 0000000..dea28d6 --- /dev/null +++ b/类库/Api.Framework/EntityTmp/SuNing/SN_QueryCommoditydetail.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.SuNing2 +{ + /// + /// 获取到的转链后的结构 + /// + public class SN_QueryCommoditydetail + { + public Sn_responseContent sn_responseContent { get; set; } + } + + public class Sn_responseContent + { + /// + /// + /// + public Sn_error sn_error { get; set; } + + public Sn_body sn_body { get; set; } + } + + public class Sn_error + { + /// + /// pid与推广位id冲突,不能同时存在 + /// + public string error_msg { get; set; } + /// + /// + /// + public string error_code { get; set; } + } + + public class GetExtensionlink + { + /// + /// + /// + public string shortLink { get; set; } + } + + public class Sn_body + { + /// + /// 转链后的链接 + /// + public GetExtensionlink getExtensionlink { get; set; } + } + +} diff --git a/类库/Api.Framework/EntityTmp/SuNing/SN_Recommend_Commodity.cs b/类库/Api.Framework/EntityTmp/SuNing/SN_Recommend_Commodity.cs new file mode 100644 index 0000000..0cac394 --- /dev/null +++ b/类库/Api.Framework/EntityTmp/SuNing/SN_Recommend_Commodity.cs @@ -0,0 +1,565 @@ +using Api.Framework.EntityTmp.SuNing2; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.SuNing4 +{ + public class CouponInfoList + { + /// + /// + /// + public string bounsLimit { get; set; } + /// + /// + /// + public string activitySecretKey { get; set; } + /// + /// + /// + public DateTime? couponEndTime { get; set; } + /// + /// + /// + public string activityId { get; set; } + /// + /// + /// + public DateTime? couponStartTime { get; set; } + /// + /// + /// + public string couponUrl { get; set; } + /// + /// + /// + public string couponCount { get; set; } + /// + /// + /// + public DateTime? startTime { get; set; } + /// + /// 店铺易券(100元) + /// + public string activityDescription { get; set; } + /// + /// + /// + public DateTime? endTime { get; set; } + /// + /// + /// + public string couponValue { get; set; } + } + + public class ActRoleList + { + /// + /// + /// + public string couponAmount { get; set; } + /// + /// + /// + public string singleMaxRewardAmount { get; set; } + /// + /// + /// + public string baseAddUpType { get; set; } + /// + /// + /// + public string rewardQuantifierType { get; set; } + /// + /// + /// + public string scopeType { get; set; } + /// + /// + /// + public string baseQuantifierType { get; set; } + /// + /// + /// + public string rewardAmount { get; set; } + /// + /// + /// + public string floor { get; set; } + /// + /// + /// + public string baseAmount { get; set; } + } + + public class ActList + { + /// + /// + /// + public string activityId { get; set; } + /// + /// + /// + public List actRoleList { get; set; } + /// + /// 店铺易券(100元) + /// + public string activityDescription { get; set; } + /// + /// + /// + public string activityTypeId { get; set; } + } + + public class PictureUrl + { + /// + /// + /// + public string picUrl { get; set; } + /// + /// + /// + public int locationId { get; set; } + } + + public class CommodityInfo + { + /// + /// + /// + public string isAct { get; set; } + /// + /// 新疆长绒棉花被冬被手工纯棉花被子有网全棉被芯1.8m/2.0m加厚保暖棉絮床垫被褥子秋冬被胎床上用品 + /// + public string commodityName { get; set; } + /// + /// + /// + public string commodityCode { get; set; } + /// + /// + /// + public string supplierCode { get; set; } + /// + /// 最羽家纺拼购专营店 + /// + public string supplierName { get; set; } + /// + /// + /// + public List pictureUrl { get; set; } + /// + /// 精选新疆长绒棉/保暖蓄热/包边工艺 + /// + public string sellingPoint { get; set; } + /// + /// + /// + public int monthSales { get; set; } + /// + /// + /// + public string snPrice { get; set; } + /// + /// + /// + public string commodityPrice { get; set; } + /// + /// + /// + public int commodityType { get; set; } + /// + /// 乐拼购 + /// + public string priceType { get; set; } + /// + /// + /// + public int priceTypeCode { get; set; } + /// + /// + /// + public int baoyou { get; set; } + /// + /// + /// + public string rate { get; set; } + /// + /// + /// + public int saleStatus { get; set; } + /// + /// + /// + public string productUrl { get; set; } + /// + /// + /// + public string forbiddenMark { get; set; } + } + + public class PgInfo + { + /// + /// + /// + public string pgNum { get; set; } + /// + /// + /// + public string pgPrice { get; set; } + /// + /// + /// + public string minOrderQuantity { get; set; } + /// + /// + /// + public string pgUrl { get; set; } + /// + /// + /// + public string pgActionId { get; set; } + } + + public class CategoryInfo + { + /// + /// + /// + public string firstSaleCategoryId { get; set; } + /// + /// 家居/日用/厨具 + /// + public string firstSaleCategoryName { get; set; } + /// + /// + /// + public string secondSaleCategoryId { get; set; } + /// + /// 家纺 + /// + public string secondSaleCategoryName { get; set; } + /// + /// + /// + public string thirdSaleCategoryId { get; set; } + /// + /// 被子 + /// + public string thirdSaleCategoryName { get; set; } + /// + /// + /// + public string firstPurchaseCategoryId { get; set; } + /// + /// 家用纺织品 + /// + public string firstPurchaseCategoryName { get; set; } + /// + /// + /// + public string secondPurchaseCategoryId { get; set; } + /// + /// 床上用品 + /// + public string secondPurchaseCategoryName { get; set; } + /// + /// + /// + public string thirdPurchaseCategoryId { get; set; } + /// + /// 被子 + /// + public string thirdPurchaseCategoryName { get; set; } + /// + /// + /// + public string goodsGroupCategoryId { get; set; } + /// + /// 被子 + /// + public string goodsGroupCategoryName { get; set; } + } + + public class CouponInfo + { + /// + /// + /// + public string couponUrl { get; set; } + /// + /// + /// + public string activityId { get; set; } + /// + /// 满189用100 + /// + public string preferentialDistinct { get; set; } + /// + /// + /// + public string couponShowType { get; set; } + /// + /// 100元 + /// + public string descriptionForList { get; set; } + /// + /// + /// + public string bounsAmount { get; set; } + /// + /// + /// + public string activitySecretKey { get; set; } + /// + /// + /// + public string couponValue { get; set; } + /// + /// + /// + public string couponCount { get; set; } + /// + /// + /// + public DateTime? couponStartTime { get; set; } + /// + /// + /// + public DateTime? couponEndTime { get; set; } + /// + /// + /// + public DateTime? startTime { get; set; } + /// + /// + /// + public DateTime? endTime { get; set; } + /// + /// + /// + public string bounsLimit { get; set; } + /// + /// 店铺易券(100元) + /// + public string activityDescription { get; set; } + /// + /// + /// + public string afterCouponPrice { get; set; } + } + + public class AdvanceSale + { + /// + /// + /// + public string isReserveCommodity { get; set; } + /// + /// + /// + public string depositAmount { get; set; } + /// + /// + /// + public string depositEndTime { get; set; } + } + + public class SubCodeList + { + /// + /// + /// + public string subCode { get; set; } + } + + public class ParametersList + { + /// + /// + /// + public string explain { get; set; } + /// + /// 品牌 + /// + public string parameterDesc { get; set; } + /// + /// + /// + public string sequence { get; set; } + /// + /// 最羽 + /// + public string parameterVal { get; set; } + /// + /// + /// + public string parametersCode { get; set; } + /// + /// + /// + public string parameterSequence { get; set; } + /// + /// 主体参数 + /// + public string parametersDesc { get; set; } + /// + /// + /// + public string coreFlag { get; set; } + /// + /// + /// + public string parameterCode { get; set; } + } + + public class OrderActivity + { + /// + /// + /// + public List activityRuleList { get; set; } + /// + /// 满1件打9折 + /// + public string activityDescription { get; set; } + } + + public class ActivityRuleList + { + /// + /// + /// + public string couponAmount { get; set; } + /// + /// + /// + public string singleMaxRewardAmount { get; set; } + /// + /// + /// + public string baseAddUpType { get; set; } + /// + /// + /// + public string rewardQuantifierType { get; set; } + /// + /// + /// + public string scopeType { get; set; } + /// + /// + /// + public string baseQuantifierType { get; set; } + /// + /// + /// + public string rewardAmount { get; set; } + /// + /// + /// + public string floor { get; set; } + /// + /// + /// + public string baseAmount { get; set; } + } + + public class CommodityList + { + /// + /// 活动 + /// + public OrderActivity orderActivity { get; set; } + /// + /// 优惠券信息集合 + /// + public List couponInfoList { get; set; } + /// + /// + /// + public List actList { get; set; } + /// + /// 到手价 + /// + public double arrivalPrice { get; set; } + /// + /// 商品信息 + /// + public CommodityInfo commodityInfo { get; set; } + /// + /// 拼购信息 + /// + public PgInfo pgInfo { get; set; } + /// + /// 类别信息 + /// + public CategoryInfo categoryInfo { get; set; } + /// + /// 优惠券信息 + /// + public CouponInfo couponInfo { get; set; } + /// + /// 预售信息 + /// + public AdvanceSale advanceSale { get; set; } + /// + /// 子代码集合 + /// + public List subCodeList { get; set; } + /// + /// 参数列表 + /// + public List parametersList { get; set; } + /// + /// 1:下一页有值 0:下一页无值 + /// + public string isHaveData { get; set; } + } + + public class QuerySelectrecommendcommodity + { + /// + /// 1:下一页有值 0:下一页无值 + /// + public string isHaveData { get; set; } + /// + /// + /// + public List commodityList { get; set; } + } + + public class Sn_body + { + /// + /// + /// + public QuerySelectrecommendcommodity querySelectrecommendcommodity { get; set; } + } + + public class Sn_responseContent + { + /// + /// + /// + public Sn_body sn_body { get; set; } + + + public Sn_error sn_error { get; set; } + } + + public class SN_Recommend_Commodity + { + /// + /// + /// + public Sn_responseContent sn_responseContent { get; set; } + } + +} diff --git a/类库/Api.Framework/EntityTmp/SuNing/SN_TuiGuangWeiInfo.cs b/类库/Api.Framework/EntityTmp/SuNing/SN_TuiGuangWeiInfo.cs new file mode 100644 index 0000000..642f2ac --- /dev/null +++ b/类库/Api.Framework/EntityTmp/SuNing/SN_TuiGuangWeiInfo.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.SuNing +{ + public class SN_TuiGuangWeiInfo + { + /// + /// 推广位昵称 + /// + public string adzonename { get; set; } + /// + /// 推广位pid + /// + public string adzonepid { get; set; } + + } +} diff --git a/类库/Api.Framework/EntityTmp/SuNing/ToolsRelation.cs b/类库/Api.Framework/EntityTmp/SuNing/ToolsRelation.cs new file mode 100644 index 0000000..353d106 --- /dev/null +++ b/类库/Api.Framework/EntityTmp/SuNing/ToolsRelation.cs @@ -0,0 +1,56 @@ +using Api.Framework.EntityTmp.SuNing2; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.SuNing1 +{ + public class AddToolseller + { + /// + /// 关系pid + /// + public string pid { get; set; } + /// + /// 1 成功,其他 异常 + /// + public string status { get; set; } + + /// + /// 错误提示 + /// + public string errMsg { get; set; } + } + + public class Sn_body + { + /// + /// + /// + public AddToolseller addToolseller { get; set; } + + public Sn_error sn_error { get; set; } + } + + public class Sn_responseContent + { + /// + /// + /// + public Sn_body sn_body { get; set; } + } + + /// + /// 工具商关系 + /// + public class ToolsRelation + { + /// + /// + /// + public Sn_responseContent sn_responseContent { get; set; } + } + +} diff --git a/类库/Api.Framework/EntityTmp/TkUrlClass.cs b/类库/Api.Framework/EntityTmp/TkUrlClass.cs new file mode 100644 index 0000000..91ceafd --- /dev/null +++ b/类库/Api.Framework/EntityTmp/TkUrlClass.cs @@ -0,0 +1,34 @@ +using Newtonsoft.Json; + +namespace Api.Framework.EntityTmp +{ + /// + /// 淘客的URL地址 + /// + public class TkUrlClass + { + /// + /// CMS网址 + /// + [JsonProperty(PropertyName = "url_cms")] + public string[] UrlCms { get; set; } + + /// + /// 中间页 + /// + [JsonProperty(PropertyName = "url_querys")] + public string[] UrlQuery { get; set; } + + ///// + ///// 提现网址 + ///// + //[JsonProperty(PropertyName = "url_cashs")] + //public string[] UrlCash { get; set; } + + /// + /// 朋友圈中间页 + /// + [JsonProperty(PropertyName = "url_circles")] + public string[] UrlCircle { get; set; } + } +} \ No newline at end of file diff --git a/类库/Api.Framework/EntityTmp/WeiPinHui/QueryPids.cs b/类库/Api.Framework/EntityTmp/WeiPinHui/QueryPids.cs new file mode 100644 index 0000000..37db6cc --- /dev/null +++ b/类库/Api.Framework/EntityTmp/WeiPinHui/QueryPids.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.EntityTmp.WeiPinHui +{ + /// + /// 查询推广位 + /// + public class QueryPids + { + /// + /// 返回代码 + /// + public string returnCode { get; set; } + /// + /// 返回数据 + /// + public QueryPid result { get; set; } + } + + public class QueryPid + { + public List pidInfoList { get; set; } + + public int total { get; set; } + + } + + public class PidInfo + { + public string pid { get; set; } + public string pidName { get; set; } + public long createTime { get; set; } + public string ucode { get; set; } + public string b2cUserId { get; set; } + public int status { get; set; } + public bool hasValidOrder { get; set; } + } + +} diff --git a/类库/Api.Framework/Enums/AwardDepotType.cs b/类库/Api.Framework/Enums/AwardDepotType.cs new file mode 100644 index 0000000..d20935a --- /dev/null +++ b/类库/Api.Framework/Enums/AwardDepotType.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + public enum AwardDepotType : ushort + { + 扣除分出佣金 = 1, + 不扣分出佣金 = 2 + } + + /// + /// 冻结佣金条件 + /// + public enum FreezingConditionType : ushort + { + 商品总佣金 = 1, + 客户所得佣金 = 2 + } + + /// + /// 订单推广位下载条件 + /// + public enum DownAdzoneType : ushort + { + 不下载推广位 = 1, + 只下载推广位 = 2, + } + +} diff --git a/类库/Api.Framework/Enums/ComposeType.cs b/类库/Api.Framework/Enums/ComposeType.cs new file mode 100644 index 0000000..fa62e29 --- /dev/null +++ b/类库/Api.Framework/Enums/ComposeType.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 中间页模式 + /// + public enum ComposeType + { + 无推荐商品 = 1, + 有推荐商品 = 2, + } +} diff --git a/类库/Api.Framework/Enums/CpsType.cs b/类库/Api.Framework/Enums/CpsType.cs new file mode 100644 index 0000000..6b749f6 --- /dev/null +++ b/类库/Api.Framework/Enums/CpsType.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// Cps平台类型 + /// + public enum CpsType : int + { + 阿里妈妈 = 1, + 多多进宝 = 2, + 京东联盟 = 3, + 唯品联盟 = 4, + 抖音联盟 = 5, + 苏宁易购 = 6, + 快手联盟 = 7, + //考拉联盟 = 8 + } + + /// + /// 阿里妈妈同步订单类型 + /// + public enum TBDownType : int + { + //1:常规订单,2:渠道订单,3:会员运营订单 + 常规订单 = 1, + 渠道订单 = 2, + 会员运营订单 = 3 + } +} diff --git a/类库/Api.Framework/Enums/DwzType.cs b/类库/Api.Framework/Enums/DwzType.cs new file mode 100644 index 0000000..257f4ca --- /dev/null +++ b/类库/Api.Framework/Enums/DwzType.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 缩短类型 + /// + public enum DwzType : int + { + 不缩短域名 = 0, + 新浪短网址 = 1, + 腾讯短网址 = 2, + 缩我短网址 = 3, + 百度短网址 = 4, + UC浏览器短网址 = 5, + 新新浪短网址 = 6, + 官方短网址 = 7, + 快站短网址 = 8, + } +} diff --git a/类库/Api.Framework/Enums/MemberType.cs b/类库/Api.Framework/Enums/MemberType.cs new file mode 100644 index 0000000..cc71bda --- /dev/null +++ b/类库/Api.Framework/Enums/MemberType.cs @@ -0,0 +1,32 @@ +//============================================================= +// 创建人:千年老妖 +// 本页代码,均为原创。对未经许可擅自使用者,本人保留追究其法律责任的权利。 +//============================================================== +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 用户类型 + /// + public enum MemberType : int + { + 正常 = 0, + 黑名单 = 1, + 白名单 = 2 + } + + /// + /// 用户兑换方式 + /// + public enum ExchangeType : int + { + 随系统设置 = 0, + 人工审核 = 1, + } + +} diff --git a/类库/Api.Framework/Enums/OperateType.cs b/类库/Api.Framework/Enums/OperateType.cs new file mode 100644 index 0000000..a4fa251 --- /dev/null +++ b/类库/Api.Framework/Enums/OperateType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 防撸处理类型 + /// + public enum OperateType : ushort + { + 拉入黑名单 = 1, + 通知钉钉群 = 2, + 订单冻结 = 3 + } + +} diff --git a/类库/Api.Framework/Enums/OrderNoticeType.cs b/类库/Api.Framework/Enums/OrderNoticeType.cs new file mode 100644 index 0000000..d25c34c --- /dev/null +++ b/类库/Api.Framework/Enums/OrderNoticeType.cs @@ -0,0 +1,24 @@ +//============================================================= +// 创建人:千年老妖 +// 本页代码,均为原创。对未经许可擅自使用者,本人保留追究其法律责任的权利。 +//============================================================== +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 订单通知类型 + /// + public enum OrderNoticeType : int + { + 客户订单 = 1, + 一级提成 = 2, + 二级提成 = 3, + 三级提成 = 5, + 群主分成 = 4 + } +} diff --git a/类库/Api.Framework/Enums/OrderStatus.cs b/类库/Api.Framework/Enums/OrderStatus.cs new file mode 100644 index 0000000..f96318b --- /dev/null +++ b/类库/Api.Framework/Enums/OrderStatus.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 系统订单状态 + /// + public enum SystemOrderStatus : int + { + 订单创建 = 1006, + 订单付款 = 1005, + 订单失效 = 1004, + 订单退款 = 1003, + 订单结算 = 1002, + 订单冻结 = 1001, + 订单维权中 = 1000, + 全额退款 = 999, + 部分退款 = 998, + 订单未知 = -99 + } + + /// + /// 阿里订单维权状态 + /// + public enum OrderRefundStatus : int + { + 维权创建 = 1000, + 维权成功 = 1001, + 维权失败 = 1002, + 等待处理 = 1003, + 维权成功_等待补扣佣金 = 1004, + 维权成功_佣金补扣成功 = 1005, + 维权失败_等待卖家返还佣金 = 1006, + 维权失败_卖家佣金返还成功 = 1007, + } + + /// + /// 阿里订单归属平台 + /// + public enum AlimamaOrderSubsidyType + { + 其他 = -1, + 天猫 = 1, + 聚划算 = 2, + 航旅 = 3, + 阿里云 = 4 + } + + /// + /// 成交平台 + /// + public enum AlimamaOrderTerminalType + { + 其他 = -1, + PC = 1, + 无线 = 2 + } + + /// + /// 拼多多订单状态 + /// + public enum PinduoduoOrderStatus : int + { + 等待付款 = -1, + 已经付款 = 0, + 已经成团 = 1, + 确认收货 = 2, + 审核成功 = 3, + 审核失败 = 4, + 已经结算 = 5, + 没有佣金 = 8, + 违规订单 = 10, + 未知状态 = -99 + } + + /// + /// 拼多多比价类型 + /// + public enum PinduoduoBiJiaType + { + 非比价 = 0, + 比价 = 1, + } + + /// + /// 京东订单男状态 + /// + public enum JingdongOrderStatus : int + { + 未知 = -1, + 无效_拆单 = 2, + 无效_取消 = 3, + 无效_京东帮帮主订单 = 4, + 无效_账号异常 = 5, + 无效_赠品类目不返佣 = 6, + 无效_校园订单 = 7, + 无效_企业订单 = 8, + 无效_团购订单 = 9, + 无效_开增值税专用发票订单 = 10, + 无效_乡村推广员下单 = 11, + 无效_自己推广自己下单 = 12, + 无效_违规订单 = 13, + 无效_来源与备案网址不符 = 14, + 待付款 = 15, + 已付款 = 16, + 已完成 = 17, + 已结算 = 18, + 售后中 = 19, + 结算后失效 = 20, + 已付定金 = 24, + 违规订单流量劫持 = 25, + 违规订单流量异常 = 26, + 违规订单违反京东平台规则 = 27, + 违规订单多笔交易异常 = 28 + } + + /// + /// 唯品会订单状态 + /// + public enum WeipinhuiOrderStatus + { + 不合格 = 0, + 待定 = 1, + 已完结 = 2 + } + + /// + /// 唯品会新老客:0-待定,1-新客,2-老客 + /// + public enum WeipinhuiNewCustomer + { + 待定 = 0, + 新客 = 1, + 老客 = 2 + } + + /// + /// 唯品会订单结算状态 + /// + public enum WeipinhuiOrderSettled + { + 未结算 = 0, + 已结算 = 1 + } + + /// + /// 唯品会状态 是否 + /// + public enum WeipinhuiShiFou + { + 否 = 0, + 是 = 1 + } + + /// + /// 订单归因方式 + /// + public enum WeipinhuiGuiYin + { + 常规推广 = 0, + 惊喜红包 = 1, + 锁粉 = 2, + 超级红包 = 3 + } + + /// + /// 售后类型:1-退货,2-换货,无售后时为空 + /// + public enum WeipinhuiSfterSaleType + { + 无 = 0, + 退货 = 1, + 换货 = 2 + } + + /// + /// 商品售后状态:1-售后中,2-售后完成,3-售后取消,无售后时为空 + /// + public enum WeipinhuiAfterSaleStatus + { + 无 = 0, + 售后中 = 1, + 售后完成 = 2, + 售后取消 = 3 + } + + /// + /// 唯品会订单子状态 流转状态-支持状态 + /// + public enum WeipinhuiOrderSubStatusName + { + 已下单 = 1001, + 已付款 = 1002, + 已签收 = 1003, + 待结算 = 1004, + 已结算 = 1005, + 已失效 = 1006, + 维权中 = 1007, + 维权完成 = 1008, + 手动失效 = 1009 + } + + /// + /// 苏宁订单自身状态 + /// + public enum SuNingSubOrderStatus + { + 支付完成 = 0, + 退款 = 1, + 订单已取消 = 2, + 确认收货 = 3, + 等待支付 = 4, + + + } +} diff --git a/类库/Api.Framework/Enums/PointType.cs b/类库/Api.Framework/Enums/PointType.cs new file mode 100644 index 0000000..2764475 --- /dev/null +++ b/类库/Api.Framework/Enums/PointType.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 积分操作类型 + /// + public enum PointType : int + { + 维权扣除 = -2, + 提现扣除 = -1, + 消费补贴 = 1, + 提成奖励 = 2, + 退回积分 = 3, + 其他奖励 = 99, + 人为修改 = 0 + } + + /// + /// 系统修改操作类型 + /// + public enum OperationType + { + + } + +} diff --git a/类库/Api.Framework/Enums/PrivateAdzoneType.cs b/类库/Api.Framework/Enums/PrivateAdzoneType.cs new file mode 100644 index 0000000..0f5b881 --- /dev/null +++ b/类库/Api.Framework/Enums/PrivateAdzoneType.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 私人推广位 + /// + public enum PrivateAdzoneType + { + 淘宝私人pid = 1, + 拼多多私人pid = 2, + 京东私人pid = 3, + 唯品会私人pid = 4, + 抖音私人pid = 5, + } + + /// + /// 私人推广位类型 + /// + public enum PrivateAdzoneCustomType + { + 用户私人pid = 1, + 群pid = 2, + } + +} diff --git a/类库/Api.Framework/Enums/SubsidyType.cs b/类库/Api.Framework/Enums/SubsidyType.cs new file mode 100644 index 0000000..8cb272c --- /dev/null +++ b/类库/Api.Framework/Enums/SubsidyType.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 补贴类型 + /// + public enum SubsidyType:int + { + 百分比 = 1, + 固定积分 = 2 + } +} diff --git a/类库/Api.Framework/Enums/SwitchType.cs b/类库/Api.Framework/Enums/SwitchType.cs new file mode 100644 index 0000000..2504f39 --- /dev/null +++ b/类库/Api.Framework/Enums/SwitchType.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Enums +{ + /// + /// 打开关闭类型 + /// + public enum SwitchType : int + { + 开启 = 1, + 关闭 = 0 + } + + /// + /// 抖音查询订单按钮类型 + /// + public enum DouyinQueryButtonType : int + { + 查询 = 0, + 重置 = 1 + } + + /// + /// 同步订单类型 + /// + public enum DouyinQueryOrderType : int + { + 付款订单 = 1, + 订单收货 = 2, + //结算订单 = 3, + } + + /// + /// 商户领取状态 + /// + public enum PayGetType + { + 未领取 = 0, + 已领取 = 1 + } + + public enum PointPayType : ushort + { + 关闭 = 0, + 红包 = 1, + 转账 = 2, + 商户 = 3 + } + +} diff --git a/类库/Api.Framework/EventClient.cs b/类库/Api.Framework/EventClient.cs new file mode 100644 index 0000000..a46405a --- /dev/null +++ b/类库/Api.Framework/EventClient.cs @@ -0,0 +1,231 @@ +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Chat.Framework; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework +{ + /// + /// 事件管理 + /// + public class EventClient + { + static EventClient() + { + ChatClient.Events.WXApplyFriendEvent += OnEvent; + ChatClient.Events.WXApplyGroupEvent += OnEvent; + ChatClient.Events.WXChangeStatusEvent += OnEvent; + ChatClient.Events.WXNewFriendEvent += OnEvent; + ChatClient.Events.WXNewMemerEvent += OnEvent; + ChatClient.Events.WXReceiveGroupMsgEvent += OnEvent; + ChatClient.Events.WXReiceveFriendMsgEvent += OnEvent; + ChatClient.Events.WXSendMessageEvent += OnEvent; + ChatClient.Events.WXWXReicevePayEvent += OnEvent; + ChatClient.Events.WXRefreshContactSuccessEvent += OnEvent; + ChatClient.Events.WXOpenWindowEvent += OnEvent; + + + ChatClient.QQEvents.QQReceiveFriendMsgEvents += OnEvent; + ChatClient.QQEvents.QQReceiveGroupMsgEvents += OnEvent; + ChatClient.QQEvents.QQAddMeNeedAuthEvents += OnEvent; + ChatClient.QQEvents.QQNewFriendEvents += OnEvent; + ChatClient.QQEvents.QQNewGroupMemberEvents += OnEvent; + ChatClient.QQEvents.QQAddToClusterNeedAuthEvents += OnEvent; + //ChatClient.QQEvents.QQVerifyCodeEvents += QQPool_QQVerifyCodeEvents; + + ChatClient.QQEvents.QQLogEvents += QQPool_QQLogEvents; + } + + private static void QQPool_QQLogEvents(object sender, Chat.Framework.QQSdk.Events.QQLogEvents e) + { + LogEvent(sender, new LogEvents(e.Message)); + } + + /// + /// 是否传递插件 + /// + public static bool StopParsing { get; set; } + + /// + /// 给插件传递消息 + /// + /// + /// + public static void OnEvent(object _sender, object _e) + { + if (StopParsing) return; + + object sender = _sender; + object e = _e; + var method = new Action(delegate () + //Task.Factory.StartNew(delegate () + { + var msgId = Guid.NewGuid().ToString(); + try + { + var plugins = new List(PluginClient.Plugins); + var type = e.GetType(); + if (e is Chat.Framework.ChatEvent) + { + //通用消息解析 + var b = e as Chat.Framework.ChatEvent; + if (b.IsToString) + EventClient.OnEvent(sender, e.ToString()); + if (type == typeof(Chat.Framework.PCRobotSDK.WechatEvents.WechatReceiveMsgEvents) || type == typeof(Chat.Framework.QQSdk.Events.QQReceiveGroupMsgEvents) || type == typeof(Chat.Framework.QQSdk.Events.QQReceiveFriendMsgEvents) || type == typeof(Chat.Framework.WXSdk.Events.WXReceiveGroupMsg) || type == typeof(Chat.Framework.WXSdk.Events.WXReiceveFriendMsg) || type == typeof(DebugEvent)) + { + var _time = DateTime.Now; + var c = new ReciveIMEvent(sender, e); + + #region 不处理不接受的机器人 + + var session = ApiClient.GetSession(); + var robots = session.FindRobots(); + if (null != robots.FirstOrDefault(f => f.is_receives == Enums.SwitchType.关闭 && c.RobotInfo.name == f.name)) + return; + #endregion + + #region 企业微信这里判断用户是否存在,如果存在创建事件 + if (c.Sender.GetType() == typeof(WXClientImpl_QYHOOK)) + { + var qyhook = c.Sender as WXClientImpl_QYHOOK; + var member = session.FindSingle("select * from fl_member_info where robot_type = @robot_type and username = @username", new { username = c.Username, robot_type = c.ChatType }); + if (member == null) + { + c.GetMemberinfo(); + Friend friend = null; + friend = qyhook.GetContact(c.Username);//这里很大概率获取不到用户的昵称,新用户 + if (friend == null) + { + return; + } + friend.NickName = Util.RemoveEmoji(friend.NickName); + EventClient.OnEvent(qyhook, new WXNewFriend(qyhook, friend)); + //return; + } + } + #endregion + var m = c.GetMemberinfo(); + Dictionary time = new Dictionary(); + foreach (var plugin in plugins) + { + if (!plugin.IsRun) continue;//未运行 + var _t = DateTime.Now; + plugin.SDK.OnEvent(sender, c); + time[plugin.Name] = (DateTime.Now - _t).TotalSeconds; + if (c.Cancel) + { + break; + //return;//取消传递 + } + } + ApiClient.GetSession().Insertable(new fl_debug_log() + { + crt_time = DateTime.Now, + message = b.ToString(), + token = CsharpHttpHelper.HttpHelper.ObjectToJson(time), + time = (DateTime.Now - _time).TotalSeconds, + userid = m.id + }).ExecuteCommandAsync(); + return; + } + + + //正常事件解析 + foreach (var plugin in plugins) + { + if (!plugin.IsRun) continue;//未运行 + if (b.Cancel) return;//已取消传递 + plugin.SDK.OnEvent(sender, e); + } + } + else if (e is BaseEvents) + { + var b = e as BaseEvents; + //解析API事件 + foreach (var plugin in plugins) + { + if (!plugin.IsRun) continue;//未运行 + if (b.Cancel) return;//已取消传递 + plugin.SDK.OnEvent(sender, e); + } + } + } + catch (Exception ex) + { + //OnEvent(null, $"{msgId} - 异常:"+ex.Message); + } + }); + method.BeginInvoke(null, null); + } + + /// + /// 日志事件 + /// + public static event EventHandler LogEvent; + + /// + /// 输出日志触发 + /// + /// + /// + public static void OnEvent(object sender, string log) + { + OnEvent(sender, new LogEvents(log)); + } + + /// + /// 输出日志触发 + /// + /// + /// + internal static void OnEvent(object sender, LogEvents e) + { + if (LogEvent != null) + { + LogEvent.Invoke(sender, e); + } + } + + public static event EventHandler SharedEvent; + + /// + /// 触发通用事件 + /// + internal static void OnSharedEvent(object sender, SharedEvents e) + { + if (LogEvent != null) + { + SharedEvent.Invoke(sender, e); + } + } + + /// + /// 刷新刷新传递事件(刷新某些数据或者页面数据) + /// + public static event EventHandler MethodEvent; + /// + /// 刷新事件触发 + /// + public static void OnEvent(object sender, MethodType e) + { + if (MethodEvent != null) + { + MethodEvent.Invoke(sender, e); + } + } + + /// + /// 替换短网址链接 + /// + public static Func ReplaceURL; + } +} diff --git a/类库/Api.Framework/Events/BaseEvents.cs b/类库/Api.Framework/Events/BaseEvents.cs new file mode 100644 index 0000000..c0f53d7 --- /dev/null +++ b/类库/Api.Framework/Events/BaseEvents.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Events +{ + /// + /// 事件基类 + /// + public class BaseEvents : EventArgs + { + /// + /// 是否取消传递 true:消息将不往后传,false:继续传递 + /// + public bool Cancel { get; set; } + } +} diff --git a/类库/Api.Framework/Events/DebugEvent.cs b/类库/Api.Framework/Events/DebugEvent.cs new file mode 100644 index 0000000..5689bea --- /dev/null +++ b/类库/Api.Framework/Events/DebugEvent.cs @@ -0,0 +1,59 @@ +using Api.Framework.SDK; +using Chat.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Events +{ + /// + /// 调试事件 + /// + public class DebugEvent: ChatEvent + { + /// + /// 定义发送调试委托 + /// + /// 接收者账号 + /// 发送的消息 + public delegate void SendDebugMsgs(string username,string message); + /// + /// 发送调试委托 + /// + public SendDebugMsgs SendDebugMsg; + /// + /// 机器人平台类型 + /// + public ChatType chatType { get; private set; } + /// + /// 接收者账号 + /// + public string username { get; private set; } + /// + /// 接收者昵称 + /// + public string usernick { get;private set; } + /// + /// 发送的消息 + /// + public string content { get; private set; } + /// + /// 构造方法 + /// + /// 委托 + /// 接收者账号 + /// 接收者昵称 + /// 发送的消息 + /// 机器人平台类型 + public DebugEvent(SendDebugMsgs sendmsg,string username,string usernick,string content,ChatType type) + { + this.SendDebugMsg = sendmsg; + this.username = username; + this.usernick = usernick; + this.content = content; + this.chatType = type; + } + } +} diff --git a/类库/Api.Framework/Events/LogEvents.cs b/类库/Api.Framework/Events/LogEvents.cs new file mode 100644 index 0000000..d79a454 --- /dev/null +++ b/类库/Api.Framework/Events/LogEvents.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Events +{ + /// + /// 日志事件 + /// + public class LogEvents : BaseEvents + { + /// + /// 异常对象 + /// + public Exception Exception { get; internal set; } + /// + /// 日志内容 + /// + public string Message { get; set; } + /// + /// 触发时间 + /// + public DateTime CrtTime { get; private set; } + /// + /// 构造方法 + /// + /// 日志内容 + public LogEvents(string message) + { + this.Message = message; + this.CrtTime = DateTime.Now; + } + } +} diff --git a/类库/Api.Framework/Events/MethodType.cs b/类库/Api.Framework/Events/MethodType.cs new file mode 100644 index 0000000..2b03607 --- /dev/null +++ b/类库/Api.Framework/Events/MethodType.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Events +{ + /// + /// 界面常用操作类型 + /// + public enum MethodType : ushort + { + 刷新应用 = 1, + 删除机器人 = 2, + 刷新联盟 = 3, + 刷新机器人 = 4, + 刷新数据报表 = 5, + 刷新配置文件 = 6, + } +} diff --git a/类库/Api.Framework/Events/OrderNoticeEvent.cs b/类库/Api.Framework/Events/OrderNoticeEvent.cs new file mode 100644 index 0000000..ac602d9 --- /dev/null +++ b/类库/Api.Framework/Events/OrderNoticeEvent.cs @@ -0,0 +1,63 @@ +using Api.Framework.Enums; +using Api.Framework.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Events +{ + + /// + /// 订单通知事件 + /// + public class OrderNoticeEvent : BaseEvents + { + /// + /// 订单 父类(base_model_order): 强转为原始的订单类型,如阿里妈妈 fl_order_alimama ... + /// + public object Order { get; private set; } + + /// + /// 联盟类型 + /// + public CpsType ChatType { get; private set; } + + /// + /// 事件触发人 + /// + public fl_member_info Member { get; private set; } + + /// + /// 消费者 - 客户信息 注:通知类型(OrderNoticeType)为客户订单时,改对象为空;为其他类型,该值为订单所属者 + /// + public fl_member_info Customer { get; internal set; } + + /// + /// 【Customer为null,IsRewards为true(订单拥有者完成首单奖励规则);Customer不为null,IsRewards为true(上级完成首单并且符合推荐奖励规则)】 + /// + public bool IsRewards { get; internal set; } + + /// + /// 通知类型 + /// + public OrderNoticeType OrderNoticeType { get; set; } + + /// + /// 构造方法 + /// + /// cps类型 + /// 用户对象 + /// 订单对象 + /// 订单所属 + public OrderNoticeEvent(CpsType chatType, fl_member_info member, object order, OrderNoticeType noticeType = OrderNoticeType.客户订单) + { + this.Order = order; + this.ChatType = chatType; + this.OrderNoticeType = noticeType; + this.Member = member; + this.IsRewards = false; + } + } +} diff --git a/类库/Api.Framework/Events/SendMessageEvent.cs b/类库/Api.Framework/Events/SendMessageEvent.cs new file mode 100644 index 0000000..d8aa98a --- /dev/null +++ b/类库/Api.Framework/Events/SendMessageEvent.cs @@ -0,0 +1,39 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Events +{ + + + /// + /// 发送消息 + /// + public class SendMessageEvent + { + /// + /// 机器人类型 + /// + public ChatType ChatType { get;internal set; } + + /// + /// 消息正文 + /// + public string Message { get; internal set; } + + /// + /// 发送者 + /// + public object Sender { get; internal set; } + + /// + /// 接收者 + /// + public object Receive { get; internal set; } + } + + +} diff --git a/类库/Api.Framework/Events/SharedEvents.cs b/类库/Api.Framework/Events/SharedEvents.cs new file mode 100644 index 0000000..0d753fd --- /dev/null +++ b/类库/Api.Framework/Events/SharedEvents.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Events +{ + /// + /// 通用事件,可实现插件之间的数据传输,自己定义规则 + /// + public class SharedEvents : BaseEvents + { + /// + /// 参数 + /// + public Dictionary Shareds { get; private set; } + + /// + /// 构造方法 + /// + /// 参数 + public SharedEvents(Dictionary Shareds) + { + this.Shareds = Shareds; + } + + /// + /// 构造方法 + /// + public SharedEvents() + { + } + } +} diff --git a/类库/Api.Framework/Events/WebRequestEvents.cs b/类库/Api.Framework/Events/WebRequestEvents.cs new file mode 100644 index 0000000..0b5638f --- /dev/null +++ b/类库/Api.Framework/Events/WebRequestEvents.cs @@ -0,0 +1,71 @@ +using Microsoft.Owin; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Events +{ + /// + /// web请求事件 + /// + public class WebRequestEvents : BaseEvents + { + /// + /// 响应结果 + /// + private WebClient.Result Respose { get; set; } + + /// + /// 发送错误请求 + /// + /// 异常 + /// 错误代码 + public void Send(Exception e, int code = -1) + { + Send(e.Message, code); + } + + /// + /// 发送正确请求 + /// + /// 请求内容 + /// 正确代码 + public void Send(object message, int code = 0) + { + Respose.Message = message; + Respose.Code = code; + this.Cancel = true; + } + + /// + /// 提交的参数 包含:GET POST 合集 + /// + public Dictionary Param { get; private set; } + /// + /// 上下文 + /// + public IOwinContext Context { get; private set; } + /// + /// cookies + /// + public NameValueCollection Cookies { get; private set; } + + /// + /// 构造方法 + /// + /// 上下文 + /// 提交的参数 包含:GET POST 合集 + /// 响应的对象 + public WebRequestEvents(IOwinContext context, Dictionary Param, WebClient.Result Respose) + { + this.Context = context; + this.Param = Param; + this.Respose = Respose; + } + + } +} diff --git a/类库/Api.Framework/Extents/ValuesEx.cs b/类库/Api.Framework/Extents/ValuesEx.cs new file mode 100644 index 0000000..73b4aa1 --- /dev/null +++ b/类库/Api.Framework/Extents/ValuesEx.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CsharpHttpHelper; + +namespace Api.Framework.Extents +{ + /// + /// 数值相关扩展类 + /// + public static class ValueEx + { + + /// + /// 执行除法 + /// + /// + public static double ExecDivision(this int value, double divisor = 100d, int decimals = 2) + { + if (value == 0) return 0; + + return (double)((decimal)value / (decimal)divisor).ToDecimal(decimals); + } + + /// + /// 执行除法 + /// + /// + public static double ExecDivision(this double value, double divisor = 100d, int decimals = 2) + { + if (value == 0) return 0; + + return (double)((decimal)value / (decimal)divisor).ToDecimal(decimals); + } + + /// + /// 执行除法 + /// + /// + public static decimal ExecDivision(this decimal value, decimal divisor = 100m, int decimals = 2) + { + if (value == 0) return 0; + + return (value / divisor).ToDecimal(decimals); + } + + /// + /// 转为指定的小数位 + /// + /// + /// + /// + public static decimal ToDecimal(this decimal value, int decimals = 2) + { + return Math.Round(value, decimals); + } + + /// + /// 时间戳转时间 + /// + /// + /// + public static DateTime ToDateTime(this long value) + { + try + { + return HttpExtend.GetDateTime(value.ToString()); + } + catch (Exception e) + { + return DateTime.MinValue; + } + } + + + } +} diff --git a/类库/Api.Framework/GlobalSuppressions.cs b/类库/Api.Framework/GlobalSuppressions.cs new file mode 100644 index 0000000..9cf77bb Binary files /dev/null and b/类库/Api.Framework/GlobalSuppressions.cs differ diff --git a/类库/Api.Framework/MB/MB_API.cs b/类库/Api.Framework/MB/MB_API.cs new file mode 100644 index 0000000..9b10ef3 --- /dev/null +++ b/类库/Api.Framework/MB/MB_API.cs @@ -0,0 +1,1273 @@ +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace MB +{ + #region 定义委托 + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeTitleChangedCallback(IntPtr webView, IntPtr param, IntPtr title); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeMouseOverUrlChangedCallback(IntPtr webView, IntPtr param, IntPtr url); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeURLChangedCallback2(IntPtr webView, IntPtr param, IntPtr frame, IntPtr url); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkePaintUpdatedCallback(IntPtr webView, IntPtr param, IntPtr buffer, int x, int y, int cx, int cy); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkePaintBitUpdatedCallback(IntPtr webView, IntPtr param, IntPtr hdc, ref wkeRect r, int width, int height); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeAlertBoxCallback(IntPtr webView, IntPtr param, IntPtr msg); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate byte wkeConfirmBoxCallback(IntPtr webView, IntPtr param, IntPtr msg); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate byte wkePromptBoxCallback(IntPtr webView, IntPtr param, IntPtr msg, IntPtr defaultResult, IntPtr result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate byte wkeNavigationCallback(IntPtr webView, IntPtr param, wkeNavigationType navigationType, IntPtr url); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate IntPtr wkeCreateViewCallback(IntPtr webView, IntPtr param, wkeNavigationType navigationType, IntPtr url, IntPtr windowFeatures); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeDocumentReadyCallback(IntPtr webView, IntPtr param); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeDocumentReady2Callback(IntPtr webView, IntPtr param, IntPtr frame); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeLoadingFinishCallback(IntPtr webView, IntPtr param, IntPtr url, wkeLoadingResult result, IntPtr failedReason); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate byte wkeDownloadCallback(IntPtr webView, IntPtr param, IntPtr url); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate byte wkeDownload2Callback(IntPtr webView, IntPtr param, uint expectedContentLength, IntPtr url, IntPtr mime, IntPtr disposition, IntPtr job, IntPtr dataBind); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeConsoleCallback(IntPtr webView, IntPtr param, wkeConsoleLevel level, IntPtr message, IntPtr sourceName, uint sourceLine, IntPtr stackTrace); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate byte wkeLoadUrlBeginCallback(IntPtr webView, IntPtr param, IntPtr url, IntPtr job); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeLoadUrlEndCallback(IntPtr webView, IntPtr param, IntPtr url, IntPtr job, IntPtr buf, int len); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeLoadUrlFailCallback(IntPtr webView, IntPtr param, IntPtr url, IntPtr job); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeDidCreateScriptContextCallback(IntPtr webView, IntPtr param, IntPtr frame, IntPtr context, int extensionGroup, int worldId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeWillReleaseScriptContextCallback(IntPtr webView, IntPtr param, IntPtr frame, IntPtr context, int worldId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate byte wkeNetResponseCallback(IntPtr webView, IntPtr param, IntPtr url, IntPtr job); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeWillMediaLoadCallback(IntPtr webView, IntPtr param, IntPtr url, IntPtr info); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeOnOtherLoadCallback(IntPtr webView, IntPtr param, wkeOtherLoadType type, IntPtr info); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long wkeJsNativeFunction(IntPtr jsExecState, IntPtr param); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeOnShowDevtoolsCallback(IntPtr webView, IntPtr param); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeOnNetGetFaviconCallback(IntPtr webView, IntPtr param, IntPtr utf8Url, ref wkeMemBuf buf); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeNetJobDataRecvCallback(IntPtr ptr, IntPtr job, IntPtr data, int length); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeNetJobDataFinishCallback(IntPtr ptr, IntPtr job, wkeLoadingResult result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public delegate long jsGetPropertyCallback(IntPtr es, long obj, string propertyName); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public delegate byte jsSetPropertyCallback(IntPtr es, long obj, string propertyName, long value); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate long jsCallAsFunctionCallback(IntPtr es, long obj, IntPtr args, int argCount); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void jsFinalizeCallback(IntPtr data); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeOnUrlRequestWillRedirectCallback(IntPtr webView, IntPtr param, IntPtr oldRequest, IntPtr request, IntPtr redirectResponse); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeOnUrlRequestDidReceiveResponseCallback(IntPtr webView, IntPtr param, IntPtr request, IntPtr response); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeOnUrlRequestDidReceiveDataCallback(IntPtr webView, IntPtr param, IntPtr request, IntPtr data, int dataLength); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeOnUrlRequestDidFailCallback(IntPtr webView, IntPtr param, IntPtr request, IntPtr error); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void wkeOnUrlRequestDidFinishLoadingCallback(IntPtr webView, IntPtr param, IntPtr request, long finishTime); + + /// + /// 访问Cookie回调 + /// + /// 用户数据 + /// + /// + /// 域名 + /// 路径 + /// 安全,如果非0则仅发送到https请求 + /// 如果非0则仅发送到http请求 + /// 过期时间 The cookie expiration date is only valid if |has_expires| is true. + /// 返回true 则应用程序自己处理miniblink不处理 + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool wkeCookieVisitor(IntPtr userData, [MarshalAs(UnmanagedType.LPStr)]string name, [MarshalAs(UnmanagedType.LPStr)]string value, [MarshalAs(UnmanagedType.LPStr)]string domain, [MarshalAs(UnmanagedType.LPStr)]string path, int secure, int httpOnly, ref int expires); + + #endregion + + #region 枚举 + + public enum wkeMouseFlags + { + WKE_LBUTTON = 0x01, + WKE_RBUTTON = 0x02, + WKE_SHIFT = 0x04, + WKE_CONTROL = 0x08, + WKE_MBUTTON = 0x10, + } + + public enum wkeKeyFlags + { + WKE_EXTENDED = 0x0100, + WKE_REPEAT = 0x4000, + } + + public enum jsType + { + NUMBER, + STRING, + BOOLEAN, + OBJECT, + FUNCTION, + UNDEFINED, + ARRAY, + NULL + } + + [StructLayout(LayoutKind.Sequential)] + public struct jsKeys + { + public int length; + public IntPtr keys; + } + + public enum wkeConsoleLevel + { + Debug = 4, + Log = 1, + Info = 5, + Warning = 2, + Error = 3, + RevokedError = 6, + } + + public enum wkeLoadingResult + { + Succeeded, + Failed, + Canceled + } + + public enum wkeNavigationType + { + LinkClick, + FormSubmit, + BackForward, + ReLoad, + FormReSubmit, + Other + } + + public enum wkeCursorStyle + { + Pointer, + Cross, + Hand, + IBeam, + Wait, + Help, + EastResize, + NorthResize, + NorthEastResize, + NorthWestResize, + SouthResize, + SouthEastResize, + SouthWestResize, + WestResize, + NorthSouthResize, + EastWestResize, + NorthEastSouthWestResize, + NorthWestSouthEastResize, + ColumnResize, + RowResize, + MiddlePanning, + EastPanning, + NorthPanning, + NorthEastPanning, + NorthWestPanning, + SouthPanning, + SouthEastPanning, + SouthWestPanning, + WestPanning, + Move, + VerticalText, + Cell, + ContextMenu, + Alias, + Progress, + NoDrop, + Copy, + None, + NotAllowed, + ZoomIn, + ZoomOut, + Grab, + Grabbing, + Custom + } + + public enum wkeCookieCommand + { + ClearAllCookies, + ClearSessionCookies, + FlushCookiesToFile, + ReloadCookiesFromFile + } + + public enum wkeProxyType + { + NONE, + HTTP, + SOCKS4, + SOCKS4A, + SOCKS5, + SOCKS5HOSTNAME + } + + public enum wkeSettingMask + { + PROXY = 1, + PAINTCALLBACK_IN_OTHER_THREAD = 4, + } + + public enum wkeOtherLoadType + { + WKE_DID_START_LOADING, + WKE_DID_STOP_LOADING, + WKE_DID_NAVIGATE, + WKE_DID_NAVIGATE_IN_PAGE, + WKE_DID_GET_RESPONSE_DETAILS, + WKE_DID_GET_REDIRECT_REQUEST + } + + public enum wkeResourceType + { + MAIN_FRAME = 0, // top level page + SUB_FRAME = 1, // frame or iframe + STYLESHEET = 2, // a CSS stylesheet + SCRIPT = 3, // an external script + IMAGE = 4, // an image (jpg/gif/png/etc) + FONT_RESOURCE = 5, // a font + SUB_RESOURCE = 6, // an "other" subresource. + OBJECT = 7, // an object (or embed) tag for a plugin, or a resource that a plugin requested. + MEDIA = 8, // a media resource. + WORKER = 9, // the main resource of a dedicated worker. + SHARED_WORKER = 10, // the main resource of a shared worker. + PREFETCH = 11, // an explicitly requested prefetch + FAVICON = 12, // a favicon + XHR = 13, // a XMLHttpRequest + PING = 14, // a ping request for + SERVICE_WORKER = 15, // the main resource of a service worker. + } + + public enum wkeMenuItemId + { + kWkeMenuSelectedAllId = 1 << 1, + kWkeMenuSelectedTextId = 1 << 2, + kWkeMenuUndoId = 1 << 3, + kWkeMenuCopyImageId = 1 << 4, + kWkeMenuInspectElementAtId = 1 << 5, + kWkeMenuCutId = 1 << 6, + kWkeMenuPasteId = 1 << 7, + kWkeMenuPrintId = 1 << 8, + kWkeMenuGoForwardId = 1 << 9, + kWkeMenuGoBackId = 1 << 10, + kWkeMenuReloadId = 1 << 11, + } + + public enum wkeRequestType + { + Invalidation, + Get, + Post, + Put, + } + + public enum wkeHttBodyElementType + { + wkeHttBodyElementTypeData, + wkeHttBodyElementTypeFile + } + + #endregion + + #region 结构体 + + public struct jsData + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] + public string typeName; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public jsGetPropertyCallback propertyGet; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public jsSetPropertyCallback propertySet; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public jsFinalizeCallback finalize; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public jsCallAsFunctionCallback callAsFunction; + } + + public struct wkeNetJobDataBind + { + IntPtr param; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public wkeNetJobDataRecvCallback recvCallback; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public wkeNetJobDataFinishCallback finishCallback; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkeRect + { + public int x; + public int y; + public int w; + public int h; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct wkeProxy + { + public wkeProxyType Type; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)] + public string HostName; + + public ushort Port; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string UserName; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string Password; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkeSettings + { + public wkeProxy Proxy; + public wkeSettingMask Mask; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkeWindowFeatures + { + public int x; + public int y; + public int width; + public int height; + + [MarshalAs(UnmanagedType.I1)] + public bool menuBarVisible; + + [MarshalAs(UnmanagedType.I1)] + public bool statusBarVisible; + + [MarshalAs(UnmanagedType.I1)] + public bool toolBarVisible; + + [MarshalAs(UnmanagedType.I1)] + public bool locationBarVisible; + + [MarshalAs(UnmanagedType.I1)] + public bool scrollbarsVisible; + + [MarshalAs(UnmanagedType.I1)] + public bool resizable; + + [MarshalAs(UnmanagedType.I1)] + public bool fullscreen; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkeMediaLoadInfo + { + public int size; + public int width; + public int height; + public double duration; + } + + public struct wkeWillSendRequestInfo + { + public bool isHolded; + public string url; + public string newUrl; + public wkeResourceType resourceType; + public int httpResponseCode; + public string method; + public string referrer; + public IntPtr headers; + } + + public struct wkeTempCallbackInfo + { + public int size; + public IntPtr frame; + public IntPtr willSendRequestInfo; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkeMemBuf + { + public int size; + public IntPtr data; + public int length; + } + + public struct jsExceptionInfo + { + public string Message; + public string SourceLine; + public string ScriptResourceName; + public int LineNumber; + public int StartPosition; + public int EndPosition; + public int StartColumn; + public int EndColoumn; + public string CallStackString; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkeViewSettings + { + public int size; + public uint bgColor; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkeSlist + { + public IntPtr str; + public IntPtr next; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkePostBodyElement + { + public int size; + public wkeHttBodyElementType type; + public IntPtr data; + public string filePath; + public long fileStart; + public long fileLength; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkePostBodyElements + { + public int size; + public IntPtr element; + public int elementSize; + public bool isDirty; + } + + [StructLayout(LayoutKind.Sequential)] + public struct wkeUrlRequestCallbacks + { + wkeOnUrlRequestWillRedirectCallback willRedirectCallback; + wkeOnUrlRequestDidReceiveResponseCallback didReceiveResponseCallback; + wkeOnUrlRequestDidReceiveDataCallback didReceiveDataCallback; + wkeOnUrlRequestDidFailCallback didFailCallback; + wkeOnUrlRequestDidFinishLoadingCallback didFinishLoadingCallback; + } + + #endregion + + public class MBApi + { + private const string m_strDll = "Assembly\\library\\node.dll"; // 编译64位的话,换成"miniblink_x64.dll",或者把"miniblink_x64.dll"文件改名成"node.dll"也行 + + [DllImport(m_strDll, EntryPoint = "wkeIsInitialize", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsInitialize(); + + [DllImport(m_strDll, EntryPoint = "wkeInitialize", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeInitialize(); + + [DllImport(m_strDll, EntryPoint = "wkeInitializeEx", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeInitializeEx(wkeSettings settings); + + [DllImport(m_strDll, EntryPoint = "wkeSetViewSettings", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetViewSettings(IntPtr webView, wkeViewSettings settings); + + [DllImport(m_strDll, EntryPoint = "wkeConfigure", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeConfigure(wkeSettings settings); + + [DllImport(m_strDll, EntryPoint = "wkeSetDebugConfig", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeSetDebugConfig(IntPtr webView, string debugString, [MarshalAs(UnmanagedType.LPArray)]byte[] param); + + [DllImport(m_strDll, EntryPoint = "wkeGetDebugConfig", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr wkeGetDebugConfig(IntPtr webView, string debugString); + + [DllImport(m_strDll, EntryPoint = "wkeGetVersion", CallingConvention = CallingConvention.Cdecl)] + public static extern uint wkeGetVersion(); + + [DllImport(m_strDll, EntryPoint = "wkeGetVersionString", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetVersionString(); + + [DllImport(m_strDll, EntryPoint = "wkeGC", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeGC(IntPtr webView, int delayMs); + + [DllImport(m_strDll, EntryPoint = "wkeCreateWebView", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeCreateWebView(); + + [DllImport(m_strDll, EntryPoint = "wkeGetWebView", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr wkeGetWebView(string name); + + [DllImport(m_strDll, EntryPoint = "wkeDestroyWebView", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeDestroyWebView(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSetMemoryCacheEnable", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetMemoryCacheEnable(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetTouchEnabled", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetTouchEnabled(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetNavigationToNewWindowEnable", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetNavigationToNewWindowEnable(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetCspCheckEnable", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetCspCheckEnable(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetNpapiPluginsEnabled", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetNpapiPluginsEnabled(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetHeadlessEnabled", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetHeadlessEnabled(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetMouseEnabled", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetMouseEnabled(IntPtr webView, [MarshalAs(UnmanagedType.I1)] bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetDragEnable", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetDragEnable(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetDragDropEnable", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetDragDropEnable(IntPtr WebView, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetContextMenuItemShow", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetContextMenuItemShow(IntPtr WebView, wkeMenuItemId item, [MarshalAs(UnmanagedType.I1)]bool b); + + [DllImport(m_strDll, EntryPoint = "wkeSetLanguage", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeSetLanguage(IntPtr WebView, string language); + + [DllImport(m_strDll, EntryPoint = "wkeSetViewNetInterface", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr wkeSetViewNetInterface(IntPtr webView, string netInterface); + + [DllImport(m_strDll, EntryPoint = "wkeSetProxy", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetProxy(ref wkeProxy proxy); + + [DllImport(m_strDll, EntryPoint = "wkeSetViewProxy", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetViewProxy(IntPtr webView, ref wkeProxy proxy); + + [DllImport(m_strDll, EntryPoint = "wkeGetName", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetName(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSetName", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeSetName(IntPtr webView, string name); + + [DllImport(m_strDll, EntryPoint = "wkeSetHandle", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetHandle(IntPtr webView, IntPtr wndHandle); + + [DllImport(m_strDll, EntryPoint = "wkeSetHandleOffset", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetHandleOffset(IntPtr webView, int x, int y); + + [DllImport(m_strDll, EntryPoint = "wkeIsTransparent", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsTransparent(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSetTransparent", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetTransparent(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool transparent); + + [DllImport(m_strDll, EntryPoint = "wkeSetUserAgentW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeSetUserAgentW(IntPtr webView, string userAgent); + + [DllImport(m_strDll, EntryPoint = "wkeLoadW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeLoadW(IntPtr webView, string url); + + [DllImport(m_strDll, EntryPoint = "wkeLoadURLW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeLoadURLW(IntPtr webView, string url); + + [DllImport(m_strDll, EntryPoint = "wkePostURLW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkePostURLW(IntPtr webView, string url, [MarshalAs(UnmanagedType.LPArray)]byte[] postData, int postLen); + + [DllImport(m_strDll, EntryPoint = "wkeLoadHTMLW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeLoadHTMLW(IntPtr webView, string html); + + [DllImport(m_strDll, EntryPoint = "wkeLoadFileW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeLoadFileW(IntPtr webView, string fileName); + + [DllImport(m_strDll, EntryPoint = "wkeGetURL", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetURL(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeIsLoading", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsLoading(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeIsLoadingFailed", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsLoadingFailed(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeIsLoadingCompleted", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsLoadingCompleted(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeIsDocumentReady", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsDocumentReady(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeStopLoading", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeStopLoading(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeReload", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeReload(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGoToOffset", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeGoToOffset(IntPtr webView, int offset); + + [DllImport(m_strDll, EntryPoint = "wkeGoToIndex", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeGoToIndex(IntPtr webView, int index); + + [DllImport(m_strDll, EntryPoint = "wkeGetWebviewId", CallingConvention = CallingConvention.Cdecl)] + public static extern int wkeGetWebviewId(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeIsWebviewAlive", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsWebviewAlive(IntPtr webView, int id); + + [DllImport(m_strDll, EntryPoint = "wkeGetDocumentCompleteURL", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetDocumentCompleteURL(IntPtr webView, IntPtr frameId, [MarshalAs(UnmanagedType.LPArray)]byte[] partialURL); + + [DllImport(m_strDll, EntryPoint = "wkeCreateMemBuf", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeCreateMemBuf(IntPtr webView, [MarshalAs(UnmanagedType.LPArray)]byte[] buff, int length); + + [DllImport(m_strDll, EntryPoint = "wkeFreeMemBuf", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeFreeMemBuf(IntPtr buf); + + [DllImport(m_strDll, EntryPoint = "wkeGetTitleW", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetTitleW(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeResize", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeResize(IntPtr webView, int w, int h); + + [DllImport(m_strDll, EntryPoint = "wkeGetWidth", CallingConvention = CallingConvention.Cdecl)] + public static extern int wkeGetWidth(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGetHeight", CallingConvention = CallingConvention.Cdecl)] + public static extern int wkeGetHeight(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGetContentWidth", CallingConvention = CallingConvention.Cdecl)] + public static extern int wkeGetContentWidth(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGetContentHeight", CallingConvention = CallingConvention.Cdecl)] + public static extern int wkeGetContentHeight(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkePaint2", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkePaint2(IntPtr webView, IntPtr bits, int bufWid, int bufHei, int xDst, int yDst, int w, int h, int xSrc, int ySrc, [MarshalAs(UnmanagedType.I1)]bool bCopyAlpha); + + [DllImport(m_strDll, EntryPoint = "wkePaint", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkePaint(IntPtr webView, IntPtr bits, int pitch); + + [DllImport(m_strDll, EntryPoint = "wkeGetViewDC", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetViewDC(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGetHostHWND", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetHostHWND(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeCanGoBack", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeCanGoBack(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGoBack", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeGoBack(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeCanGoForward", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeCanGoForward(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGoForward", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeGoForward(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeEditorSelectAll", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeEditorSelectAll(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeEditorUnSelect", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeEditorUnSelect(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeEditorCopy", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeEditorCopy(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeEditorCut", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeEditorCut(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeEditorPaste", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeEditorPaste(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeEditorDelete", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeEditorDelete(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeEditorUndo", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeEditorUndo(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeEditorRedo", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeEditorRedo(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGetCookieW", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetCookieW(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSetCookie", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetCookie(IntPtr webView, [MarshalAs(UnmanagedType.LPArray)]byte[] url, [MarshalAs(UnmanagedType.LPArray)]byte[] cookie); + + [DllImport(m_strDll, EntryPoint = "wkeVisitAllCookie", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeVisitAllCookie(IntPtr webView, IntPtr usetData, wkeCookieVisitor visitor); + + [DllImport(m_strDll, EntryPoint = "wkePerformCookieCommand", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkePerformCookieCommand(wkeCookieCommand command); + + [DllImport(m_strDll, EntryPoint = "wkeSetCookieEnabled", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetCookieEnabled(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool enable); + + [DllImport(m_strDll, EntryPoint = "wkeIsCookieEnabled", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsCookieEnabled(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSetCookieJarPath", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeSetCookieJarPath(IntPtr webView, string path); + + [DllImport(m_strDll, EntryPoint = "wkeSetCookieJarFullPath", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeSetCookieJarFullPath(IntPtr webView, string path); + + [DllImport(m_strDll, EntryPoint = "wkeSetLocalStorageFullPath", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeSetLocalStorageFullPath(IntPtr webView, string path); + + [DllImport(m_strDll, EntryPoint = "wkeSetMediaVolume", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetMediaVolume(IntPtr webView, float volume); + + [DllImport(m_strDll, EntryPoint = "wkeGetMediaVolume", CallingConvention = CallingConvention.Cdecl)] + public static extern float wkeGetMediaVolume(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeFireMouseEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeFireMouseEvent(IntPtr webView, uint message, int x, int y, uint flags); + + [DllImport(m_strDll, EntryPoint = "wkeFireContextMenuEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeFireContextMenuEvent(IntPtr webView, int x, int y, uint flags); + + [DllImport(m_strDll, EntryPoint = "wkeFireMouseWheelEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeFireMouseWheelEvent(IntPtr webView, int x, int y, int delta, uint flags); + + [DllImport(m_strDll, EntryPoint = "wkeFireKeyUpEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeFireKeyUpEvent(IntPtr webView, int virtualKeyCode, uint flags, [MarshalAs(UnmanagedType.I1)]bool systemKey); + + [DllImport(m_strDll, EntryPoint = "wkeFireKeyDownEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeFireKeyDownEvent(IntPtr webView, int virtualKeyCode, uint flags, [MarshalAs(UnmanagedType.I1)]bool systemKey); + + [DllImport(m_strDll, EntryPoint = "wkeFireKeyPressEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeFireKeyPressEvent(IntPtr webView, int charCode, uint flags, [MarshalAs(UnmanagedType.I1)]bool systemKey); + + [DllImport(m_strDll, EntryPoint = "wkeFireWindowsMessage", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeFireWindowsMessage(IntPtr webView, IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam, IntPtr result); + + [DllImport(m_strDll, EntryPoint = "wkeSetFocus", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeSetFocus(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeKillFocus", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeKillFocus(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGetCaretRect", CallingConvention = CallingConvention.Cdecl)] + public static extern wkeRect wkeGetCaretRect(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeRunJSW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern long wkeRunJSW(IntPtr webView, string script); + + [DllImport(m_strDll, EntryPoint = "wkeGlobalExec", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGlobalExec(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSleep", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSleep(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeWake", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeWake(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeIsAwake", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsAwake(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSetZoomFactor", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetZoomFactor(IntPtr webView, float factor); + + [DllImport(m_strDll, EntryPoint = "wkeGetZoomFactor", CallingConvention = CallingConvention.Cdecl)] + public static extern float wkeGetZoomFactor(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSetEditable", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetEditable(IntPtr webView, [MarshalAs(UnmanagedType.I1)]bool editable); + + [DllImport(m_strDll, EntryPoint = "wkeGetStringW", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetStringW(IntPtr wkeString); + + [DllImport(m_strDll, EntryPoint = "wkeSetStringW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeSetStringW(IntPtr wkeString, string str, int len); + + [DllImport(m_strDll, EntryPoint = "wkeCreateStringW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern IntPtr wkeCreateStringW(string str, int len); + + [DllImport(m_strDll, EntryPoint = "wkeDeleteString", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeDeleteString(IntPtr wkeString); + + [DllImport(m_strDll, EntryPoint = "wkeGetWebViewForCurrentContext", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetWebViewForCurrentContext(); + + [DllImport(m_strDll, EntryPoint = "wkeSetUserKeyValue", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeSetUserKeyValue(IntPtr webView, string key, IntPtr value); + + [DllImport(m_strDll, EntryPoint = "wkeGetUserKeyValue", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr wkeGetUserKeyValue(IntPtr webView, string key); + + [DllImport(m_strDll, EntryPoint = "wkeGetCursorInfoType", CallingConvention = CallingConvention.Cdecl)] + public static extern wkeCursorStyle wkeGetCursorInfoType(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeSetCursorInfoType", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetCursorInfoType(IntPtr webView, wkeCursorStyle type); + + [DllImport(m_strDll, EntryPoint = "wkeSetDragFiles", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetDragFiles(IntPtr webView, IntPtr clintPos, IntPtr screenPos, [MarshalAs(UnmanagedType.LPArray)]IntPtr[] files, int filesCount); + + [DllImport(m_strDll, EntryPoint = "wkeOnMouseOverUrlChanged", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnMouseOverUrlChanged(IntPtr webView, wkeMouseOverUrlChangedCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnTitleChanged", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnTitleChanged(IntPtr webView, wkeTitleChangedCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnURLChanged2", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnURLChanged2(IntPtr webView, wkeURLChangedCallback2 callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnPaintUpdated", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnPaintUpdated(IntPtr webView, wkePaintUpdatedCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnPaintBitUpdated", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnPaintBitUpdated(IntPtr webView, wkePaintBitUpdatedCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnAlertBox", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnAlertBox(IntPtr webView, wkeAlertBoxCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnConfirmBox", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnConfirmBox(IntPtr webView, wkeConfirmBoxCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnPromptBox", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnPromptBox(IntPtr webView, wkePromptBoxCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnNavigation", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnNavigation(IntPtr webView, wkeNavigationCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnCreateView", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnCreateView(IntPtr webView, wkeCreateViewCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnDocumentReady", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnDocumentReady(IntPtr webView, wkeDocumentReadyCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnDocumentReady2", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnDocumentReady2(IntPtr webView, wkeDocumentReady2Callback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnLoadingFinish", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnLoadingFinish(IntPtr webView, wkeLoadingFinishCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnDownload", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnDownload(IntPtr webView, wkeDownloadCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnDownload2", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnDownload2(IntPtr webView, wkeDownload2Callback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnConsole", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnConsole(IntPtr webView, wkeConsoleCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnDidCreateScriptContext", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnDidCreateScriptContext(IntPtr webView, wkeDidCreateScriptContextCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnWillReleaseScriptContext", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnWillReleaseScriptContext(IntPtr webView, wkeWillReleaseScriptContextCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnLoadUrlBegin", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnLoadUrlBegin(IntPtr webView, wkeLoadUrlBeginCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnLoadUrlEnd", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnLoadUrlEnd(IntPtr webView, wkeLoadUrlEndCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeOnLoadUrlFail", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnLoadUrlFail(IntPtr webView, wkeLoadUrlFailCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeNetOnResponse", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeNetOnResponse(IntPtr webView, wkeNetResponseCallback callback, IntPtr callbackParam); + + [DllImport(m_strDll, EntryPoint = "wkeNetSetMIMEType", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeNetSetMIMEType(IntPtr job, string type); + + [DllImport(m_strDll, EntryPoint = "wkeNetSetHTTPHeaderField", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeNetSetHTTPHeaderField(IntPtr job, string key, string value, [MarshalAs(UnmanagedType.I1)]bool response); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetHTTPHeaderField", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr wkeNetGetHTTPHeaderField(IntPtr job, string key); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetHTTPHeaderFieldFromResponse", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern IntPtr wkeNetGetHTTPHeaderFieldFromResponse(IntPtr job, string key); + + [DllImport(m_strDll, EntryPoint = "wkeNetSetData", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeNetSetData(IntPtr job, [MarshalAs(UnmanagedType.LPArray)]byte[] buf, int len); + + [DllImport(m_strDll, EntryPoint = "wkeNetHookRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeNetHookRequest(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetRequestMethod", CallingConvention = CallingConvention.Cdecl)] + public static extern wkeRequestType wkeNetGetRequestMethod(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetMIMEType", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetGetMIMEType(IntPtr job, IntPtr mime); + + [DllImport(m_strDll, EntryPoint = "wkeNetContinueJob", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeNetContinueJob(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetUrlByJob", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetGetUrlByJob(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetRawHttpHead", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetGetRawHttpHead(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetRawResponseHead", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetGetRawResponseHead(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetCancelRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeNetCancelRequest(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetHoldJobToAsynCommit", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeNetHoldJobToAsynCommit(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetChangeRequestUrl", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern byte wkeNetChangeRequestUrl(IntPtr job, string url); + + [DllImport(m_strDll, EntryPoint = "wkeNetCreateWebUrlRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetCreateWebUrlRequest(IntPtr url, IntPtr method, IntPtr mime); + + [DllImport(m_strDll, EntryPoint = "wkeNetCreateWebUrlRequest2", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetCreateWebUrlRequest2(IntPtr request); + + [DllImport(m_strDll, EntryPoint = "wkeNetCopyWebUrlRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetCopyWebUrlRequest(IntPtr job, [MarshalAs(UnmanagedType.I1)]bool needExtraData); + + [DllImport(m_strDll, EntryPoint = "wkeNetDeleteBlinkWebURLRequestPtr", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeNetDeleteBlinkWebURLRequestPtr(IntPtr request); + + [DllImport(m_strDll, EntryPoint = "wkeNetAddHTTPHeaderFieldToUrlRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeNetAddHTTPHeaderFieldToUrlRequest(IntPtr request, IntPtr name, IntPtr value); + + [DllImport(m_strDll, EntryPoint = "wkeNetStartUrlRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern int wkeNetStartUrlRequest(IntPtr webView, IntPtr request, IntPtr param, wkeUrlRequestCallbacks callback); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetHttpStatusCode", CallingConvention = CallingConvention.Cdecl)] + public static extern int wkeNetGetHttpStatusCode(IntPtr response); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetExpectedContentLength", CallingConvention = CallingConvention.Cdecl)] + public static extern long wkeNetGetExpectedContentLength(IntPtr response); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetResponseUrl", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetGetResponseUrl(IntPtr response); + + [DllImport(m_strDll, EntryPoint = "wkeNetCancelWebUrlRequest", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeNetCancelWebUrlRequest(int requestId); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetPostBody", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetGetPostBody(IntPtr job); + + [DllImport(m_strDll, EntryPoint = "wkeNetCreatePostBodyElements", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetCreatePostBodyElements(IntPtr webView, long length); + + [DllImport(m_strDll, EntryPoint = "wkeNetFreePostBodyElements", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetFreePostBodyElements(IntPtr elements); + + [DllImport(m_strDll, EntryPoint = "wkeNetCreatePostBodyElement", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeNetCreatePostBodyElement(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeNetFreePostBodyElement", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeNetFreePostBodyElement(IntPtr element); + + [DllImport(m_strDll, EntryPoint = "wkeIsMainFrame", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsMainFrame(IntPtr webFrame); + + [DllImport(m_strDll, EntryPoint = "wkeIsWebRemoteFrame", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsWebRemoteFrame(IntPtr webFrame); + + [DllImport(m_strDll, EntryPoint = "wkeWebFrameGetMainFrame", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeWebFrameGetMainFrame(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeWebFrameGetMainWorldScriptContext", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeWebFrameGetMainWorldScriptContext(IntPtr webFrame, ref IntPtr contextOut); + + [DllImport(m_strDll, EntryPoint = "wkeGetBlinkMainThreadIsolate", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetBlinkMainThreadIsolate(); + + [DllImport(m_strDll, EntryPoint = "wkeRunJsByFrame", CallingConvention = CallingConvention.Cdecl)] + public static extern long wkeRunJsByFrame(IntPtr webView, IntPtr frameId, [MarshalAs(UnmanagedType.LPArray)]byte[] script, [MarshalAs(UnmanagedType.I1)]bool isInClosure); + + [DllImport(m_strDll, EntryPoint = "wkeGetWindowHandle", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetWindowHandle(IntPtr WebView); + + [DllImport(m_strDll, EntryPoint = "wkeOnWillMediaLoad", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnWillMediaLoad(IntPtr WebView, wkeWillMediaLoadCallback callback, IntPtr param); + + [DllImport(m_strDll, EntryPoint = "wkeDeleteWillSendRequestInfo", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeDeleteWillSendRequestInfo(IntPtr WebView, IntPtr info); + + [DllImport(m_strDll, EntryPoint = "wkeOnOtherLoad", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeOnOtherLoad(IntPtr WebView, wkeOnOtherLoadCallback callback, IntPtr param); + + [DllImport(m_strDll, EntryPoint = "wkeSetDeviceParameter", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeSetDeviceParameter(IntPtr WebView, string device, string paramStr, int paramInt, float paramFloat); + + [DllImport(m_strDll, EntryPoint = "wkeAddPluginDirectory", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeAddPluginDirectory(IntPtr WebView, string path); + + [DllImport(m_strDll, EntryPoint = "wkeGetGlobalExecByFrame", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetGlobalExecByFrame(IntPtr WebView, IntPtr frameId); + + [DllImport(m_strDll, EntryPoint = "wkeShowDevtools", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern void wkeShowDevtools(IntPtr WebView, string path, wkeOnShowDevtoolsCallback callback, IntPtr param); + + [DllImport(m_strDll, EntryPoint = "wkeInsertCSSByFrame", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeInsertCSSByFrame(IntPtr WebView, IntPtr frameId, [MarshalAs(UnmanagedType.LPArray)]byte[] utf8css); + + [DllImport(m_strDll, EntryPoint = "wkeSetResourceGc", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeSetResourceGc(IntPtr WebView, int intervalSec); + + [DllImport(m_strDll, EntryPoint = "wkeLoadHtmlWithBaseUrl", CallingConvention = CallingConvention.Cdecl)] + public static extern void wkeLoadHtmlWithBaseUrl(IntPtr WebView, [MarshalAs(UnmanagedType.LPArray)]byte[] utf8html, [MarshalAs(UnmanagedType.LPArray)]byte[] baseUrl); + + [DllImport(m_strDll, EntryPoint = "wkeGetUserAgent", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetUserAgent(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGetFrameUrl", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetFrameUrl(IntPtr webView, IntPtr frameId); + + [DllImport(m_strDll, EntryPoint = "wkeNetGetFavicon", CallingConvention = CallingConvention.Cdecl)] + public static extern int wkeNetGetFavicon(IntPtr webView, wkeNetResponseCallback callback, IntPtr param); + + [DllImport(m_strDll, EntryPoint = "wkeIsProcessingUserGesture", CallingConvention = CallingConvention.Cdecl)] + public static extern byte wkeIsProcessingUserGesture(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeUtilSerializeToMHTML", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeUtilSerializeToMHTML(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeGetSource", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr wkeGetSource(IntPtr webView); + + [DllImport(m_strDll, EntryPoint = "wkeJsBindFunction", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeJsBindFunction(string name, wkeJsNativeFunction fn, IntPtr param, uint argCount); + + [DllImport(m_strDll, EntryPoint = "wkeJsBindGetter", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeJsBindGetter(string name, wkeJsNativeFunction fn, IntPtr param); + + [DllImport(m_strDll, EntryPoint = "wkeJsBindSetter", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void wkeJsBindSetter(string name, wkeJsNativeFunction fn, IntPtr param); + + [DllImport(m_strDll, EntryPoint = "jsArgCount", CallingConvention = CallingConvention.Cdecl)] + public static extern int jsArgCount(IntPtr es); + + [DllImport(m_strDll, EntryPoint = "jsArgType", CallingConvention = CallingConvention.Cdecl)] + public static extern jsType jsArgType(IntPtr es, int argIdx); + + [DllImport(m_strDll, EntryPoint = "jsArg", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsArg(IntPtr es, int argIdx); + + [DllImport(m_strDll, EntryPoint = "jsTypeOf", CallingConvention = CallingConvention.Cdecl)] + public static extern jsType jsTypeOf(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsNumber", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsNumber(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsString", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsString(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsBoolean", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsBoolean(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsObject", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsObject(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsFunction", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsFunction(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsUndefined", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsUndefined(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsNull", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsNull(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsArray", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsArray(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsTrue", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsTrue(long v); + + [DllImport(m_strDll, EntryPoint = "jsIsFalse", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsFalse(long v); + + [DllImport(m_strDll, EntryPoint = "jsToInt", CallingConvention = CallingConvention.Cdecl)] + public static extern int jsToInt(IntPtr es, long v); + + [DllImport(m_strDll, EntryPoint = "jsToFloat", CallingConvention = CallingConvention.Cdecl)] + public static extern float jsToFloat(IntPtr es, long v); + + [DllImport(m_strDll, EntryPoint = "jsToDouble", CallingConvention = CallingConvention.Cdecl)] + public static extern double jsToDouble(IntPtr es, long v); + + [DllImport(m_strDll, EntryPoint = "jsToBoolean", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsToBoolean(IntPtr es, long v); + + [DllImport(m_strDll, EntryPoint = "jsToTempStringW", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr jsToTempStringW(IntPtr es, long v); + + [DllImport(m_strDll, EntryPoint = "jsInt", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsInt(int n); + + [DllImport(m_strDll, EntryPoint = "jsFloat", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsFloat(float f); + + [DllImport(m_strDll, EntryPoint = "jsDouble", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsDouble(double d); + + [DllImport(m_strDll, EntryPoint = "jsBoolean", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsBoolean(bool b); + + [DllImport(m_strDll, EntryPoint = "jsUndefined", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsUndefined(); + + [DllImport(m_strDll, EntryPoint = "jsNull", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsNull(); + + [DllImport(m_strDll, EntryPoint = "jsTrue", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsTrue(); + + [DllImport(m_strDll, EntryPoint = "jsFalse", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsFalse(); + + [DllImport(m_strDll, EntryPoint = "jsStringW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern long jsStringW(IntPtr es, string str); + + [DllImport(m_strDll, EntryPoint = "jsEmptyObject", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsEmptyObject(IntPtr es); + + [DllImport(m_strDll, EntryPoint = "jsEmptyArray", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsEmptyArray(IntPtr es); + + [DllImport(m_strDll, EntryPoint = "jsArrayBuffer", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern long jsArrayBuffer(IntPtr es, StringBuilder buffer, int size); + + [DllImport(m_strDll, EntryPoint = "jsObject", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsObject(IntPtr es, IntPtr obj); + + [DllImport(m_strDll, EntryPoint = "jsFunction", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsFunction(IntPtr es, IntPtr obj); + + [DllImport(m_strDll, EntryPoint = "jsGetData", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr jsGetData(IntPtr es, long jsValue); + + [DllImport(m_strDll, EntryPoint = "jsGet", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern long jsGet(IntPtr es, long jsValue, string prop); + + [DllImport(m_strDll, EntryPoint = "jsSet", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void jsSet(IntPtr es, long jsValue, string prop, long v); + + [DllImport(m_strDll, EntryPoint = "jsGetAt", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsGetAt(IntPtr es, long jsValue, int index); + + [DllImport(m_strDll, EntryPoint = "jsSetAt", CallingConvention = CallingConvention.Cdecl)] + public static extern void jsSetAt(IntPtr es, long jsValue, int index, long v); + + [DllImport(m_strDll, EntryPoint = "jsGetLength", CallingConvention = CallingConvention.Cdecl)] + public static extern int jsGetLength(IntPtr es, long jsValue); + + [DllImport(m_strDll, EntryPoint = "jsSetLength", CallingConvention = CallingConvention.Cdecl)] + public static extern void jsSetLength(IntPtr es, long jsValue, int length); + + [DllImport(m_strDll, EntryPoint = "jsGlobalObject", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsGlobalObject(IntPtr es); + + [DllImport(m_strDll, EntryPoint = "jsGetWebView", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr jsGetWebView(IntPtr es); + + [DllImport(m_strDll, EntryPoint = "jsEvalW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern long jsEvalW(IntPtr es, string str); + + [DllImport(m_strDll, EntryPoint = "jsEvalExW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] + public static extern long jsEvalExW(IntPtr es, string str, [MarshalAs(UnmanagedType.I1)]bool isInClosure); + + [DllImport(m_strDll, EntryPoint = "jsCall", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsCall(IntPtr es, long func, long thisObject, [MarshalAs(UnmanagedType.LPArray)]Int64[] args, int argCount); + + [DllImport(m_strDll, EntryPoint = "jsCallGlobal", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsCallGlobal(IntPtr es, long func, [MarshalAs(UnmanagedType.LPArray)]Int64[] args, int argCount); + + [DllImport(m_strDll, EntryPoint = "jsGetGlobal", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern long jsGetGlobal(IntPtr es, string prop); + + [DllImport(m_strDll, EntryPoint = "jsSetGlobal", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void jsSetGlobal(IntPtr es, string prop, long jsValue); + + [DllImport(m_strDll, EntryPoint = "jsGC", CallingConvention = CallingConvention.Cdecl)] + public static extern void jsGC(); + + [DllImport(m_strDll, EntryPoint = "jsIsJsValueValid", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsJsValueValid(IntPtr es, long jsValue); + + [DllImport(m_strDll, EntryPoint = "jsIsValidExecState", CallingConvention = CallingConvention.Cdecl)] + public static extern byte jsIsValidExecState(IntPtr es); + + [DllImport(m_strDll, EntryPoint = "jsDeleteObjectProp", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + public static extern void jsDeleteObjectProp(IntPtr es, long jsValue, string prop); + + [DllImport(m_strDll, EntryPoint = "jsGetArrayBuffer", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr jsGetArrayBuffer(IntPtr es, long jsValue); + + [DllImport(m_strDll, EntryPoint = "jsGetLastErrorIfException", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr jsGetLastErrorIfException(IntPtr es); + + [DllImport(m_strDll, EntryPoint = "jsThrowException", CallingConvention = CallingConvention.Cdecl)] + public static extern long jsThrowException(IntPtr es, [MarshalAs(UnmanagedType.LPArray)]byte[] utf8exception); + + [DllImport(m_strDll, EntryPoint = "jsGetKeys", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr jsGetKeys(IntPtr es, long jsValue); + } +} diff --git a/类库/Api.Framework/MB/MB_Common.cs b/类库/Api.Framework/MB/MB_Common.cs new file mode 100644 index 0000000..629fcc2 --- /dev/null +++ b/类库/Api.Framework/MB/MB_Common.cs @@ -0,0 +1,453 @@ +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace MB +{ + public delegate IntPtr WndProcCallback(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + + public RECT(int left, int top, int right, int bottom) + { + Left = left; + Top = top; + Right = right; + Bottom = bottom; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct SIZE + { + public int cx; + public int cy; + public SIZE(int x, int y) + { + cx = x; + cy = y; + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct PAINTSTRUCT + { + public int hdc; + public int fErase; + public RECT rcPaint; + public int fRestore; + public int fIncUpdate; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] rgbReserved; + } + + [StructLayout(LayoutKind.Sequential)] + public struct POINT + { + public int x; + public int y; + } + + [StructLayout(LayoutKind.Sequential)] + public struct COMPOSITIONFORM + { + public int dwStyle; + public POINT ptCurrentPos; + public RECT rcArea; + } + + [StructLayout(LayoutKind.Sequential)] + public struct BITMAP + { + public int bmType; + public int bmWidth; + public int bmHeight; + public int bmWidthBytes; + public short bmPlanes; + public short bmBitsPixel; + public int bmBits; + } + + [StructLayout(LayoutKind.Explicit, Size = 4)] + public struct BLENDFUNCTION + { + [FieldOffset(0)] + public byte BlendOp; + + [FieldOffset(1)] + public byte BlendFlags; + + [FieldOffset(2)] + public byte SourceConstantAlpha; + + [FieldOffset(3)] + public byte AlphaFormat; + } + + public enum WinConst : int + { + GWL_EXSTYLE = -20, + GWL_WNDPROC = -4, + WS_EX_LAYERED = 524288, + WM_PAINT = 15, + WM_ERASEBKGND = 20, + WM_SIZE = 5, + WM_KEYDOWN = 256, + WM_KEYUP = 257, + WM_CHAR = 258, + WM_LBUTTONDOWN = 513, + WM_LBUTTONUP = 514, + WM_MBUTTONDOWN = 519, + WM_RBUTTONDOWN = 516, + WM_LBUTTONDBLCLK = 515, + WM_MBUTTONDBLCLK = 521, + WM_RBUTTONDBLCLK = 518, + WM_MBUTTONUP = 520, + WM_RBUTTONUP = 517, + WM_MOUSEMOVE = 512, + WM_CONTEXTMENU = 123, + WM_MOUSEWHEEL = 522, + WM_SETFOCUS = 7, + WM_KILLFOCUS = 8, + WM_IME_STARTCOMPOSITION = 269, + WM_NCHITTEST = 132, + WM_GETMINMAXINFO = 36, + WM_DESTROY = 2, + WM_SETCURSOR = 32, + MK_CONTROL = 8, + MK_SHIFT = 4, + MK_LBUTTON = 1, + MK_MBUTTON = 16, + MK_RBUTTON = 2, + KF_REPEAT = 16384, + KF_EXTENDED = 256, + SRCCOPY = 13369376, + CAPTUREBLT = 1073741824, + CFS_POINT = 2, + CFS_FORCE_POSITION = 32, + OBJ_BITMAP = 7, + AC_SRC_OVER = 0, + AC_SRC_ALPHA = 1, + ULW_ALPHA = 2, + WM_INPUTLANGCHANGE = 81, + WM_NCDESTROY = 130, + WM_SYSCOMMAND = 274, + CS_DROPSHADOW = 0x00020000, + } + + + public static class MB_Common + { + [DllImport("user32.dll", EntryPoint = "GetWindowLongW")] + public static extern int GetWindowLong32(IntPtr hwnd, int nIndex); + + [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")] + public static extern int GetWindowLong64(IntPtr hwnd, int nIndex); + + public static int GetWindowLong(IntPtr hwnd, int nIndex) + { + return IntPtr.Size == 8 ? GetWindowLong64(hwnd, nIndex) : GetWindowLong32(hwnd, nIndex); + } + + [DllImport("user32.dll", EntryPoint = "SetWindowLongW")] + public static extern int SetWindowLong32(IntPtr hwnd, int nIndex, int dwNewLong); + + [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")] + public static extern int SetWindowLong64(IntPtr hwnd, int nIndex, int dwNewLong); + + public static int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong) + { + return IntPtr.Size == 8 ? SetWindowLong64(hwnd, nIndex, dwNewLong) : SetWindowLong32(hwnd, nIndex, dwNewLong); + } + + [DllImport("user32.dll", EntryPoint = "CallWindowProcW")] + public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", EntryPoint = "DefWindowProcA")] + public static extern IntPtr DefWindowProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", EntryPoint = "GetClientRect")] + public static extern int GetClientRect(IntPtr hwnd, ref RECT lpRect); + + [DllImport("user32.dll", EntryPoint = "BeginPaint")] + public static extern IntPtr BeginPaint(IntPtr hwnd, ref PAINTSTRUCT lpPaint); + + [DllImport("user32.dll", EntryPoint = "IntersectRect")] + public static extern int IntersectRect(ref RECT lpDestRect, ref RECT lpSrc1Rect, ref RECT lpSrc2Rect); + + [DllImport("gdi32.dll", EntryPoint = "BitBlt")] + public static extern int BitBlt(IntPtr hDestDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop); + + [DllImport("user32.dll", EntryPoint = "EndPaint")] + public static extern int EndPaint(IntPtr hwnd, ref PAINTSTRUCT lpPaint); + + [DllImport("user32.dll", EntryPoint = "GetFocus")] + public static extern IntPtr GetFocus(); + + [DllImport("user32.dll", EntryPoint = "SetFocus")] + public static extern IntPtr SetFocus(IntPtr hwnd); + + [DllImport("user32.dll", EntryPoint = "SetCapture")] + public static extern int SetCapture(IntPtr hwnd); + + [DllImport("user32.dll", EntryPoint = "ReleaseCapture")] + public static extern int ReleaseCapture(); + + [DllImport("user32.dll", EntryPoint = "ScreenToClient")] + public static extern int ScreenToClient(IntPtr hwnd, ref POINT lpPoint); + + [DllImport("imm32.dll", EntryPoint = "ImmGetContext")] + public static extern IntPtr ImmGetContext(IntPtr hwnd); + + [DllImport("imm32.dll", EntryPoint = "ImmSetCompositionWindow")] + public static extern int ImmSetCompositionWindow(IntPtr himc, ref COMPOSITIONFORM lpCompositionForm); + + [DllImport("imm32.dll", EntryPoint = "ImmReleaseContext")] + public static extern int ImmReleaseContext(IntPtr hwnd, IntPtr himc); + + [DllImport("user32.dll", EntryPoint = "GetWindowRect")] + public static extern int GetWindowRect(IntPtr hwnd, ref RECT lpRect); + + [DllImport("user32.dll", EntryPoint = "OffsetRect")] + public static extern int OffsetRect(ref RECT lpRect, int x, int y); + + [DllImport("gdi32.dll", EntryPoint = "GetCurrentObject")] + public static extern IntPtr GetCurrentObject(IntPtr hdc, int uObjectType); + + [DllImport("gdi32.dll", EntryPoint = "GetObjectW")] + public static extern int GetObject(IntPtr hObject, int nCount, ref BITMAP lpObject); + + [DllImport("user32.dll", EntryPoint = "GetDC")] + public static extern IntPtr GetDC(IntPtr hwnd); + + [DllImport("user32.dll", EntryPoint = "UpdateLayeredWindow")] + public static extern int UpdateLayeredWindow(IntPtr hWnd, IntPtr hdcDst, IntPtr pptDst, ref SIZE psize, IntPtr hdcSrc, ref POINT pptSrc, int crKey, ref BLENDFUNCTION pblend, int dwFlags); + + [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")] + public static extern IntPtr CreateCompatibleDC(IntPtr hdc); + + [DllImport("gdi32.dll", EntryPoint = "CreateCompatibleBitmap")] + public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); + + [DllImport("gdi32.dll", EntryPoint = "SelectObject")] + public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject); + + [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] + public static extern int DeleteObject(IntPtr hObject); + + [DllImport("gdi32.dll", EntryPoint = "DeleteDC")] + public static extern int DeleteDC(IntPtr hdc); + + [DllImport("user32.dll", EntryPoint = "ReleaseDC")] + public static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc); + + [DllImport("user32.dll", EntryPoint = "InvalidateRect")] + public static extern int InvalidateRect(IntPtr hwnd, ref RECT lpRect, bool bErase); + + [DllImport("kernel32.dll", EntryPoint = "lstrlenA")] + public static extern int lstrlen(IntPtr lpString); + + [DllImport("kernel32.dll", EntryPoint = "lstrlenA")] + public static extern int lstrlenA(IntPtr lpString); + + [DllImport("kernel32.dll", EntryPoint = "lstrlenW")] + public static extern int lstrlenW(IntPtr lpString); + + [DllImport("user32.dll ", EntryPoint = "SendMessage")] + public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + public static ulong LOWORD(this IntPtr dword) + { + return IntPtr.Size == 4 ? (ulong)dword & 65535 : (ulong)dword & 4294967295; + } + + public static ulong HIWORD(this IntPtr dword) + { + return IntPtr.Size == 4 ? (ulong)dword >> 16 : (ulong)dword >> 32; + } + + public static int LOWORD(this int dword) + { + return dword & 65535; + } + + public static int HIWORD(this int dword) + { + return dword >> 16; + } + + public static int To32(this IntPtr dword) + { + return IntPtr.Size == 8 ? (int)(dword.ToInt64() << 32 >> 32) : dword.ToInt32(); + } + + public static string UTF8PtrToStr(this IntPtr utf8) + { + if (utf8 == IntPtr.Zero) + { + return string.Empty; + } + + int iLen = lstrlenA(utf8); + byte[] bytes = new byte[iLen]; + Marshal.Copy(utf8, bytes, 0, iLen); + + return Encoding.UTF8.GetString(bytes); + } + + public static IntPtr StrToUtf8Ptr(this string str) + { + IntPtr ptr = IntPtr.Zero; + + if (str != null) + { + byte[] bytes = Encoding.UTF8.GetBytes(str); + ptr = Marshal.AllocHGlobal(bytes.Length + 1); + Marshal.Copy(bytes, 0, ptr, bytes.Length); + Marshal.WriteByte(ptr, bytes.Length, 0); + } + + return ptr; + } + + public static string UnicodePtrToStr(this IntPtr unicode) + { + /*if (unicode == IntPtr.Zero) + { + return string.Empty; + } + + int iLen = lstrlenW(unicode); + char[] ch = new char[iLen]; + Marshal.Copy(unicode, ch, 0, iLen); + + return new string(ch);*/ + + return Marshal.PtrToStringUni(unicode); + } + + public static IntPtr StrToUnicodePtr(this string str) + { + IntPtr ptr = IntPtr.Zero; + + if (str != null) + { + byte[] bytes = Encoding.Unicode.GetBytes(str); + ptr = Marshal.AllocHGlobal(bytes.Length + 1); + Marshal.Copy(bytes, 0, ptr, bytes.Length); + Marshal.WriteByte(ptr, bytes.Length, 0); + } + + return ptr; + } + + public static byte[] StructToBytes(this object structObj) + { + int iSize = Marshal.SizeOf(structObj); + byte[] bytes = new byte[iSize]; + IntPtr structPtr = Marshal.AllocHGlobal(iSize); + Marshal.StructureToPtr(structObj, structPtr, false); + Marshal.Copy(structPtr, bytes, 0, iSize); + Marshal.FreeHGlobal(structPtr); + + return bytes; + } + + public static object BytesToStuct(this byte[] bytes, Type type) + { + object objRet = null; + + int iSize = Marshal.SizeOf(type); + if (iSize <= bytes.Length) + { + IntPtr structPtr = Marshal.AllocHGlobal(iSize); + Marshal.Copy(bytes, 0, structPtr, iSize); + objRet = Marshal.PtrToStructure(structPtr, type); + Marshal.FreeHGlobal(structPtr); + } + + return objRet; + } + + public static IntPtr StructToUTF8Ptr(this object structObj) + { + int iSize = Marshal.SizeOf(structObj); + byte[] bytes = new byte[iSize]; + IntPtr structPtr = Marshal.AllocHGlobal(iSize); + Marshal.StructureToPtr(structObj, structPtr, false); + Marshal.Copy(structPtr, bytes, 0, iSize); + + return structPtr; + } + + public static object UTF8PtrToStruct(this IntPtr structPtr, Type type) + { + return Marshal.PtrToStructure(structPtr, type); + } + + public static byte[] UTF8PtrToByte(this IntPtr utf8) + { + if (utf8 == IntPtr.Zero) + { + return new byte[0]; + } + + int iLen = lstrlenA(utf8); + byte[] bytes = new byte[iLen]; + Marshal.Copy(utf8, bytes, 0, iLen); + + return bytes; + } + + public static IntPtr ByteToUtf8Ptr(this byte[] data) + { + IntPtr ptr = IntPtr.Zero; + + if (data != null) + { + ptr = Marshal.AllocHGlobal(data.Length + 1); + Marshal.Copy(data, 0, ptr, data.Length); + Marshal.WriteByte(ptr, data.Length, 0); + } + + return ptr; + } + + public static string[] PtrToStringArray(this IntPtr ptr, int iLength) + { + string[] data = new string[iLength]; + + for (int i = 0; i < iLength; i++) + { + IntPtr str = (IntPtr)Marshal.PtrToStructure(ptr, typeof(IntPtr)); + data[i] = Marshal.PtrToStringAnsi(str); + ptr = new IntPtr(ptr.ToInt64() + IntPtr.Size); + } + + return data; + } + + public static long ToLong(this DateTime time) + { + DateTime now = time.ToUniversalTime(); + DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + return (now.Ticks - start.Ticks) / 10000; + } + + public static DateTime ToDT(this long time) + { + DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + time = start.Ticks + time * 10000; + + return new DateTime(time, DateTimeKind.Utc).ToLocalTime(); + } + } +} diff --git a/类库/Api.Framework/MB/MB_WebView.cs b/类库/Api.Framework/MB/MB_WebView.cs new file mode 100644 index 0000000..86b525f --- /dev/null +++ b/类库/Api.Framework/MB/MB_WebView.cs @@ -0,0 +1,3454 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.Dynamic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; + +namespace MB +{ + public class WebView : IDisposable + { + private IntPtr m_hWnd; + private IntPtr m_OldProc; + private wkePaintUpdatedCallback m_wkePaintUpdatedCallback; + private WndProcCallback m_WndProcCallback; + private bool m_bMouseEnabled; + private bool m_bTransparent; + + #region 设置回调事件 + + private wkeTitleChangedCallback m_wkeTitleChangedCallback; + private wkeMouseOverUrlChangedCallback m_wkeMouseOverUrlChangedCallback; + private wkeURLChangedCallback2 m_wkeURLChangedCallback2; + private wkeAlertBoxCallback m_wkeAlertBoxCallback; + private wkeConfirmBoxCallback m_wkeConfirmBoxCallback; + private wkePromptBoxCallback m_wkePromptBoxCallback; + private wkeNavigationCallback m_wkeNavigationCallback; + private wkeCreateViewCallback m_wkeCreateViewCallback; + private wkeDocumentReady2Callback m_wkeDocumentReadyCallback; + private wkeLoadingFinishCallback m_wkeLoadingFinishCallback; + private wkeDownloadCallback m_wkeDownloadCallback; + private wkeDownload2Callback m_wkeDownloadCallback2; + private wkeConsoleCallback m_wkeConsoleCallback; + private wkeLoadUrlBeginCallback m_wkeLoadUrlBeginCallback; + private wkeLoadUrlEndCallback m_wkeLoadUrlEndCallback; + private wkeLoadUrlFailCallback m_wkeLoadUrlFailCallback; + private wkeDidCreateScriptContextCallback m_wkeDidCreateScriptContextCallback; + private wkeWillReleaseScriptContextCallback m_wkeWillReleaseScriptContextCallback; + private wkeNetResponseCallback m_wkeNetResponseCallback; + private wkeWillMediaLoadCallback m_wkeWillMediaLoadCallback; + private wkeOnOtherLoadCallback m_wkeOnOtherLoadCallback; + + private event EventHandler m_titleChangeHandler = null; + private event EventHandler m_mouseOverUrlChangedHandler = null; + private event EventHandler m_urlChangeHandler = null; + private event EventHandler m_alertBoxHandler = null; + private event EventHandler m_confirmBoxHandler = null; + private event EventHandler m_promptBoxHandler = null; + private event EventHandler m_navigateHandler = null; + private event EventHandler m_createViewHandler = null; + private event EventHandler m_documentReadyHandler = null; + private event EventHandler m_loadingFinishHandler = null; + private event EventHandler m_downloadHandler = null; + private event EventHandler m_downloadHandler2 = null; + private event EventHandler m_consoleHandler = null; + private event EventHandler m_loadUrlBeginHandler = null; + private event EventHandler m_loadUrlEndHandler = null; + private event EventHandler m_loadUrlFailHandler = null; + private event EventHandler m_didCreateScriptContextHandler = null; + private event EventHandler m_willReleaseScriptContextHandler = null; + private event EventHandler m_netResponseHandler = null; + private event EventHandler m_willMediaLoadHandler = null; + private event EventHandler m_OtherLoadHandler = null; + + private void SetCallback() + { + m_wkeTitleChangedCallback = new wkeTitleChangedCallback((IntPtr WebView, IntPtr param, IntPtr title) => + { + m_titleChangeHandler?.Invoke(this, new TitleChangeEventArgs(WebView, title)); + + }); + + m_wkeMouseOverUrlChangedCallback = new wkeMouseOverUrlChangedCallback((IntPtr WebView, IntPtr param, IntPtr url) => + { + m_titleChangeHandler?.Invoke(this, new TitleChangeEventArgs(WebView, url)); + + }); + + m_wkeURLChangedCallback2 = new wkeURLChangedCallback2((IntPtr WebView, IntPtr param, IntPtr frame, IntPtr url) => + { + m_urlChangeHandler?.Invoke(this, new UrlChangeEventArgs(WebView, url, frame)); + + }); + + m_wkeAlertBoxCallback = new wkeAlertBoxCallback((IntPtr WebView, IntPtr param, IntPtr msg) => + { + m_alertBoxHandler?.Invoke(this, new AlertBoxEventArgs(WebView, msg)); + }); + + m_wkeConfirmBoxCallback = new wkeConfirmBoxCallback((IntPtr WebView, IntPtr param, IntPtr msg) => + { + if (m_confirmBoxHandler != null) + { + ConfirmBoxEventArgs e = new ConfirmBoxEventArgs(WebView, msg); + m_confirmBoxHandler(this, e); + return Convert.ToByte(e.Result); + } + return 0; + }); + + m_wkePromptBoxCallback = new wkePromptBoxCallback((IntPtr webView, IntPtr param, IntPtr msg, IntPtr defaultResult, IntPtr result) => + { + if (m_promptBoxHandler != null) + { + PromptBoxEventArgs e = new PromptBoxEventArgs(webView, msg, defaultResult, result); + m_promptBoxHandler(this, e); + return Convert.ToByte(e.Result); + } + return 0; + }); + + m_wkeNavigationCallback = new wkeNavigationCallback((IntPtr webView, IntPtr param, wkeNavigationType navigationType, IntPtr url) => + { + if (m_navigateHandler != null) + { + NavigateEventArgs e = new NavigateEventArgs(webView, navigationType, url); + m_navigateHandler(this, e); + + return (byte)(e.Cancel ? 0 : 1); + } + return 1; + }); + + m_wkeCreateViewCallback = new wkeCreateViewCallback((IntPtr webView, IntPtr param, wkeNavigationType navigationType, IntPtr url, IntPtr windowFeatures) => + { + if (m_createViewHandler != null) + { + CreateViewEventArgs e = new CreateViewEventArgs(webView, navigationType, url, windowFeatures); + m_createViewHandler(this, e); + + return e.NewWebViewHandle; + } + return webView; + }); + + m_wkeDocumentReadyCallback = new wkeDocumentReady2Callback((IntPtr webView, IntPtr param, IntPtr frame) => + { + m_documentReadyHandler?.Invoke(this, new DocumentReadyEventArgs(webView, frame)); + }); + + m_wkeLoadingFinishCallback = new wkeLoadingFinishCallback((IntPtr webView, IntPtr param, IntPtr url, wkeLoadingResult result, IntPtr failedReason) => + { + m_loadingFinishHandler?.Invoke(this, new LoadingFinishEventArgs(webView, url, result, failedReason)); + }); + + m_wkeDownloadCallback = new wkeDownloadCallback((IntPtr webView, IntPtr param, IntPtr url) => + { + if (m_downloadHandler != null) + { + DownloadEventArgs e = new DownloadEventArgs(webView, url); + m_downloadHandler(this, e); + return (byte)(e.Cancel ? 1 : 0); + } + return 1; + }); + + m_wkeDownloadCallback2 = new wkeDownload2Callback((IntPtr webView, IntPtr param, uint expectedContentLength, IntPtr url, IntPtr mime, IntPtr disposition, IntPtr job, IntPtr dataBind) => + { + if (m_downloadHandler2 != null) + { + DownloadEventArgs2 e = new DownloadEventArgs2(webView, param, expectedContentLength, url, mime, disposition, job, dataBind); + m_downloadHandler2(this, e); + return (byte)(e.Cancel ? 1 : 0); + } + return 1; + }); + + m_wkeConsoleCallback = new wkeConsoleCallback((IntPtr webView, IntPtr param, wkeConsoleLevel level, IntPtr message, IntPtr sourceName, uint sourceLine, IntPtr stackTrace) => + { + m_consoleHandler?.Invoke(this, new ConsoleEventArgs(webView, level, message, sourceName, sourceLine, stackTrace)); + }); + + m_wkeLoadUrlBeginCallback = new wkeLoadUrlBeginCallback((IntPtr webView, IntPtr param, IntPtr url, IntPtr job) => + { + if (m_loadUrlBeginHandler != null) + { + LoadUrlBeginEventArgs e = new LoadUrlBeginEventArgs(webView, url, job); + m_loadUrlBeginHandler(this, e); + return (byte)(e.Cancel ? 1 : 0); + } + return 0; + }); + + m_wkeLoadUrlEndCallback = new wkeLoadUrlEndCallback((IntPtr webView, IntPtr param, IntPtr url, IntPtr job, IntPtr buf, int len) => + { + m_loadUrlEndHandler?.Invoke(this, new LoadUrlEndEventArgs(webView, url, job, buf, len)); + }); + + m_wkeDidCreateScriptContextCallback = new wkeDidCreateScriptContextCallback((IntPtr webView, IntPtr param, IntPtr frame, IntPtr context, int extensionGroup, int worldId) => + { + m_didCreateScriptContextHandler?.Invoke(this, new DidCreateScriptContextEventArgs(webView, frame, context, extensionGroup, worldId)); + }); + + m_wkeWillReleaseScriptContextCallback = new wkeWillReleaseScriptContextCallback((IntPtr webView, IntPtr param, IntPtr frame, IntPtr context, int worldId) => + { + m_willReleaseScriptContextHandler?.Invoke(this, new WillReleaseScriptContextEventArgs(webView, frame, context, worldId)); + }); + + m_wkeNetResponseCallback = new wkeNetResponseCallback((IntPtr WebView, IntPtr param, IntPtr url, IntPtr job) => { + if (m_netResponseHandler != null) + { + NetResponseEventArgs e = new NetResponseEventArgs(WebView, url, job); + m_netResponseHandler(this, e); + return (byte)(e.Cancel ? 1 : 0); + } + return 0; + }); + + m_wkeWillMediaLoadCallback = new wkeWillMediaLoadCallback((IntPtr webView, IntPtr param, IntPtr url, IntPtr info) => + { + m_willMediaLoadHandler?.Invoke(this, new WillMediaLoadEventArgs(webView, url, info)); + }); + + m_wkeOnOtherLoadCallback = new wkeOnOtherLoadCallback((IntPtr webView, IntPtr param, wkeOtherLoadType type, IntPtr info) => + { + m_OtherLoadHandler?.Invoke(this, new OtherLoadEventArgs(webView, type, info)); + }); + } + + /// + /// 窗口过程事件 + /// + public event EventHandler OnWindowProc; + + /// + /// 鼠标经过URL改变事件 + /// + public event EventHandler OnMouseoverUrlChange + { + add + { + if (m_mouseOverUrlChangedHandler == null) + { + MBApi.wkeOnMouseOverUrlChanged(Handle, m_wkeMouseOverUrlChangedCallback, IntPtr.Zero); + } + m_mouseOverUrlChangedHandler += value; + } + remove + { + m_mouseOverUrlChangedHandler -= value; + if (m_mouseOverUrlChangedHandler == null) + { + MBApi.wkeOnMouseOverUrlChanged(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 标题被改变事件 + /// + public event EventHandler OnTitleChange + { + add + { + if (m_titleChangeHandler == null) + { + MBApi.wkeOnTitleChanged(Handle, m_wkeTitleChangedCallback, IntPtr.Zero); + } + m_titleChangeHandler += value; + } + remove + { + m_titleChangeHandler -= value; + if (m_titleChangeHandler == null) + { + MBApi.wkeOnTitleChanged(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// URL被改变事件 + /// + public event EventHandler OnURLChange + { + add + { + if (m_urlChangeHandler == null) + { + MBApi.wkeOnURLChanged2(Handle, m_wkeURLChangedCallback2, IntPtr.Zero); + } + m_urlChangeHandler += value; + } + remove + { + m_urlChangeHandler -= value; + if (m_urlChangeHandler == null) + { + MBApi.wkeOnURLChanged2(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// alert被调用事件 + /// + public event EventHandler OnAlertBox + { + add + { + if (m_alertBoxHandler == null) + { + MBApi.wkeOnAlertBox(Handle, m_wkeAlertBoxCallback, IntPtr.Zero); + } + m_alertBoxHandler += value; + } + remove + { + m_alertBoxHandler -= value; + if (m_alertBoxHandler == null) + { + MBApi.wkeOnAlertBox(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// confirm被调用事件 + /// + public event EventHandler OnConfirmBox + { + add + { + if (m_confirmBoxHandler == null) + { + MBApi.wkeOnConfirmBox(Handle, m_wkeConfirmBoxCallback, IntPtr.Zero); + } + m_confirmBoxHandler += value; + } + remove + { + m_confirmBoxHandler -= value; + if (m_confirmBoxHandler == null) + { + MBApi.wkeOnConfirmBox(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// prompt被调用事件 + /// + public event EventHandler OnPromptBox + { + add + { + if (m_promptBoxHandler == null) + { + MBApi.wkeOnPromptBox(Handle, m_wkePromptBoxCallback, IntPtr.Zero); + } + m_promptBoxHandler += value; + } + remove + { + m_promptBoxHandler -= value; + if (m_promptBoxHandler == null) + { + MBApi.wkeOnPromptBox(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 导航事件 + /// + public event EventHandler OnNavigate + { + add + { + if (m_navigateHandler == null) + { + MBApi.wkeOnNavigation(Handle, m_wkeNavigationCallback, IntPtr.Zero); + } + m_navigateHandler += value; + } + remove + { + m_navigateHandler -= value; + if (m_navigateHandler == null) + { + MBApi.wkeOnNavigation(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 将创建新窗口 + /// + public event EventHandler OnCreateView + { + add + { + if (m_createViewHandler == null) + { + MBApi.wkeOnCreateView(Handle, m_wkeCreateViewCallback, IntPtr.Zero); + } + m_createViewHandler += value; + } + remove + { + m_createViewHandler -= value; + if (m_createViewHandler == null) + { + MBApi.wkeOnCreateView(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 文档就绪 + /// + public event EventHandler OnDocumentReady + { + add + { + if (m_documentReadyHandler == null) + { + MBApi.wkeOnDocumentReady2(Handle, m_wkeDocumentReadyCallback, IntPtr.Zero); + } + m_documentReadyHandler += value; + } + remove + { + m_documentReadyHandler -= value; + if (m_documentReadyHandler == null) + { + MBApi.wkeOnDocumentReady2(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 载入完成 + /// + public event EventHandler OnLoadingFinish + { + add + { + if (m_loadingFinishHandler == null) + { + MBApi.wkeOnLoadingFinish(Handle, m_wkeLoadingFinishCallback, IntPtr.Zero); + } + m_loadingFinishHandler += value; + } + remove + { + m_loadingFinishHandler -= value; + if (m_loadingFinishHandler == null) + { + MBApi.wkeOnLoadingFinish(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 下载 + /// + public event EventHandler OnDownload + { + add + { + if (m_downloadHandler == null) + { + MBApi.wkeOnDownload(Handle, m_wkeDownloadCallback, IntPtr.Zero); + } + m_downloadHandler += value; + } + remove + { + m_downloadHandler -= value; + if (m_downloadHandler == null) + { + MBApi.wkeOnDownload(Handle, null, IntPtr.Zero); + } + } + } + + public event EventHandler OnDownload2 + { + add + { + if (m_downloadHandler2 == null) + { + MBApi.wkeOnDownload2(Handle, m_wkeDownloadCallback2, IntPtr.Zero); + } + m_downloadHandler2 += value; + } + remove + { + m_downloadHandler2 -= value; + if (m_downloadHandler2 == null) + { + MBApi.wkeOnDownload2(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 控制台 + /// + public event EventHandler OnConsole + { + add + { + if (m_consoleHandler == null) + { + MBApi.wkeOnConsole(Handle, m_wkeConsoleCallback, IntPtr.Zero); + } + m_consoleHandler += value; + } + remove + { + m_consoleHandler -= value; + if (m_consoleHandler == null) + { + MBApi.wkeOnConsole(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 开始载入URL + /// + public event EventHandler OnLoadUrlBegin + { + add + { + if (m_loadUrlBeginHandler == null) + { + MBApi.wkeOnLoadUrlBegin(Handle, m_wkeLoadUrlBeginCallback, IntPtr.Zero); + } + m_loadUrlBeginHandler += value; + } + remove + { + m_loadUrlBeginHandler -= value; + if (m_loadUrlBeginHandler == null) + { + MBApi.wkeOnLoadUrlBegin(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 结束载入URL + /// + public event EventHandler OnLoadUrlEnd + { + add + { + if (m_loadUrlEndHandler == null) + { + MBApi.wkeOnLoadUrlEnd(Handle, m_wkeLoadUrlEndCallback, IntPtr.Zero); + } + m_loadUrlEndHandler += value; + } + remove + { + m_loadUrlEndHandler -= value; + if (m_loadUrlEndHandler == null) + { + MBApi.wkeOnLoadUrlEnd(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 载入URL失败 + /// + public event EventHandler OnLoadUrlFail + { + add + { + if (m_loadUrlFailHandler == null) + { + MBApi.wkeOnLoadUrlFail(Handle, m_wkeLoadUrlFailCallback, IntPtr.Zero); + } + m_loadUrlFailHandler += value; + } + remove + { + m_loadUrlFailHandler -= value; + if (m_loadUrlFailHandler == null) + { + MBApi.wkeOnLoadUrlFail(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 脚本上下文已创建 + /// + public event EventHandler OnDidCreateScriptContext + { + add + { + if (m_didCreateScriptContextHandler == null) + { + MBApi.wkeOnDidCreateScriptContext(Handle, m_wkeDidCreateScriptContextCallback, IntPtr.Zero); + } + m_didCreateScriptContextHandler += value; + } + remove + { + m_didCreateScriptContextHandler -= value; + if (m_didCreateScriptContextHandler == null) + { + MBApi.wkeOnDidCreateScriptContext(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 脚本上下文将释放 + /// + public event EventHandler OnWillReleaseScriptContext + { + add + { + if (m_willReleaseScriptContextHandler == null) + { + MBApi.wkeOnWillReleaseScriptContext(Handle, m_wkeWillReleaseScriptContextCallback, IntPtr.Zero); + } + m_willReleaseScriptContextHandler += value; + } + remove + { + m_willReleaseScriptContextHandler -= value; + if (m_willReleaseScriptContextHandler == null) + { + MBApi.wkeOnWillReleaseScriptContext(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 网络响应事件 + /// + public event EventHandler OnNetResponse + { + add + { + if (m_netResponseHandler == null) + { + MBApi.wkeNetOnResponse(Handle, m_wkeNetResponseCallback, IntPtr.Zero); + } + m_netResponseHandler += value; + } + remove + { + m_netResponseHandler -= value; + if (m_netResponseHandler == null) + { + MBApi.wkeNetOnResponse(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 媒体将被载入事件 + /// + public event EventHandler OnWillMediaLoad + { + add + { + if (m_willMediaLoadHandler == null) + { + MBApi.wkeOnWillMediaLoad(Handle, m_wkeWillMediaLoadCallback, IntPtr.Zero); + } + m_willMediaLoadHandler += value; + } + remove + { + m_willMediaLoadHandler -= value; + if (m_willMediaLoadHandler == null) + { + MBApi.wkeOnWillMediaLoad(Handle, null, IntPtr.Zero); + } + } + } + + /// + /// 其他载入事件 + /// + public event EventHandler OnOtherLoad + { + add + { + if (m_OtherLoadHandler == null) + { + MBApi.wkeOnOtherLoad(Handle, m_wkeOnOtherLoadCallback, IntPtr.Zero); + } + m_OtherLoadHandler += value; + } + remove + { + m_OtherLoadHandler -= value; + if (m_OtherLoadHandler == null) + { + MBApi.wkeOnOtherLoad(Handle, null, IntPtr.Zero); + } + } + } + + #endregion + + /// + /// 构造函数 + /// + public WebView() + { + /*if (!File.Exists($"{Environment.CurrentDirectory}\\node.dll")) + { + MessageBox.Show("请在程序同目录下放置node.dll文件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + Process.GetCurrentProcess().Kill(); + }*/ + + if (MBApi.wkeIsInitialize() == 0) + { + MBApi.wkeInitialize(); + } + m_wkePaintUpdatedCallback = new wkePaintUpdatedCallback(wkeOnPaintUpdated); + m_WndProcCallback = new WndProcCallback(OnWndProc); + SetCallback(); + Handle = MBApi.wkeCreateWebView(); + } + + + + /// + /// 构造函数 + /// + /// 窗口 + /// true 表示为分层窗口,窗口必须是顶层 + public WebView(IWin32Window window, bool isTransparent = false) + { + /*if (!File.Exists($"{Environment.CurrentDirectory}\\node.dll")) + { + MessageBox.Show("请在程序同目录下放置node.dll文件", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + Process.GetCurrentProcess().Kill(); + }*/ + + if (MBApi.wkeIsInitialize() == 0) + { + MBApi.wkeInitialize(); + } + m_wkePaintUpdatedCallback = new wkePaintUpdatedCallback(wkeOnPaintUpdated); + m_WndProcCallback = new WndProcCallback(OnWndProc); + SetCallback(); + Bind(window, isTransparent); + } + + /// + /// 销毁 WebView + /// + public void Dispose() + { + if (Handle != IntPtr.Zero) + { + if (m_OldProc != IntPtr.Zero) + { + MB_Common.SetWindowLong(m_hWnd, (int)WinConst.GWL_WNDPROC, m_OldProc.To32()); + m_OldProc = IntPtr.Zero; + } + + MBApi.wkeSetHandle(Handle, IntPtr.Zero); + MBApi.wkeDestroyWebView(Handle); + Handle = IntPtr.Zero; + m_hWnd = IntPtr.Zero; + } + } + + protected void wkeOnPaintUpdated(IntPtr webView, IntPtr param, IntPtr hdc, int x, int y, int cx, int cy) + { + IntPtr hWnd = param; + + if ((int)WinConst.WS_EX_LAYERED == ((int)WinConst.WS_EX_LAYERED & MB_Common.GetWindowLong(m_hWnd, (int)WinConst.GWL_EXSTYLE))) + { + RECT rectDest = new RECT(); + MB_Common.GetWindowRect(m_hWnd, ref rectDest); + MB_Common.OffsetRect(ref rectDest, -rectDest.Left, -rectDest.Top); + + SIZE sizeDest = new SIZE(rectDest.Right - rectDest.Left, rectDest.Bottom - rectDest.Top); + POINT pointSource = new POINT(); + + BITMAP bmp = new BITMAP(); + IntPtr hBmp = MB_Common.GetCurrentObject(hdc, (int)WinConst.OBJ_BITMAP); + MB_Common.GetObject(hBmp, Marshal.SizeOf(typeof(BITMAP)), ref bmp); + + sizeDest.cx = bmp.bmWidth; + sizeDest.cy = bmp.bmHeight; + + IntPtr hdcScreen = MB_Common.GetDC(hWnd); + + BLENDFUNCTION blend = new BLENDFUNCTION(); + blend.BlendOp = (byte)WinConst.AC_SRC_OVER; + blend.SourceConstantAlpha = 255; + blend.AlphaFormat = (byte)WinConst.AC_SRC_ALPHA; + + if (MB_Common.UpdateLayeredWindow(m_hWnd, hdcScreen, IntPtr.Zero, ref sizeDest, hdc, ref pointSource, 0, ref blend, (int)WinConst.ULW_ALPHA) == 0) + { + IntPtr hdcMemory = MB_Common.CreateCompatibleDC(hdcScreen); + IntPtr hbmpMemory = MB_Common.CreateCompatibleBitmap(hdcScreen, sizeDest.cx, sizeDest.cy); + IntPtr hbmpOld = MB_Common.SelectObject(hdcMemory, hbmpMemory); + + MB_Common.BitBlt(hdcMemory, 0, 0, sizeDest.cx, sizeDest.cy, hdc, 0, 0, (int)WinConst.SRCCOPY | (int)WinConst.CAPTUREBLT); + MB_Common.BitBlt(hdc, 0, 0, sizeDest.cx, sizeDest.cy, hdcMemory, 0, 0, (int)WinConst.SRCCOPY | (int)WinConst.CAPTUREBLT); + MB_Common.UpdateLayeredWindow(m_hWnd, hdcScreen, IntPtr.Zero, ref sizeDest, hdcMemory, ref pointSource, 0, ref blend, (int)WinConst.ULW_ALPHA); + MB_Common.SelectObject(hdcMemory, hbmpOld); + MB_Common.DeleteObject(hbmpMemory); + MB_Common.DeleteDC(hdcMemory); + } + + MB_Common.ReleaseDC(m_hWnd, hdcScreen); + } + else + { + RECT rc = new RECT(x, y, x + cx, y + cy); + MB_Common.InvalidateRect(m_hWnd, ref rc, true); + } + } + + protected IntPtr OnWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + { + if (OnWindowProc != null) + { + WindowProcEventArgs e = new WindowProcEventArgs(hWnd, (int)msg, wParam, lParam); + OnWindowProc(this, e); + if (e.bHand) + { + return e.Result; + } + } + + switch (msg) + { + case (uint)WinConst.WM_PAINT: // 当窗口显示区域的一部分显示内容或者全部变为“无效”,以致于必须“更新画面”时 + { + if ((int)WinConst.WS_EX_LAYERED != ((int)WinConst.WS_EX_LAYERED & MB_Common.GetWindowLong(hWnd, (int)WinConst.GWL_EXSTYLE))) + { + PAINTSTRUCT ps = new PAINTSTRUCT(); + IntPtr hdc = MB_Common.BeginPaint(hWnd, ref ps); + + RECT rcClip = ps.rcPaint; + RECT rcClient = new RECT(); + MB_Common.GetClientRect(hWnd, ref rcClient); + RECT rcInvalid = rcClient; + + if (rcClip.Right != rcClip.Left && rcClip.Bottom != rcClip.Top) + { + MB_Common.IntersectRect(ref rcInvalid, ref rcClip, ref rcClient); + } + + int srcX = rcInvalid.Left - rcClient.Left; + int srcY = rcInvalid.Top - rcClient.Top; + int destX = rcInvalid.Left; + int destY = rcInvalid.Top; + int width = rcInvalid.Right - rcInvalid.Left; + int height = rcInvalid.Bottom - rcInvalid.Top; + + if (width != 0 && height != 0) + { + MB_Common.BitBlt(hdc, destX, destY, width, height, MBApi.wkeGetViewDC(Handle), srcX, srcY, (int)WinConst.SRCCOPY); + } + + MB_Common.EndPaint(hWnd, ref ps); + return IntPtr.Zero; + } + + break; + } + + case (uint)WinConst.WM_ERASEBKGND: // 窗口背景被擦除时 + { + return new IntPtr(1); + } + + case (uint)WinConst.WM_SIZE: // 窗口尺寸改变时 + { + MBApi.wkeResize(Handle, lParam.To32().LOWORD(), lParam.To32().HIWORD()); + break; + } + + case (uint)WinConst.WM_KEYDOWN: // 非系统键被按下时 + { + uint flags = 0; + if ((lParam.To32().HIWORD() & (int)WinConst.KF_REPEAT) != 0) + { + flags |= (uint)wkeKeyFlags.WKE_REPEAT; + } + + if ((lParam.To32().HIWORD() & (int)WinConst.KF_EXTENDED) != 0) + { + flags |= (uint)wkeKeyFlags.WKE_EXTENDED; + } + + if (MBApi.wkeFireKeyDownEvent(Handle, wParam.To32(), flags, false) != 0) + { + return IntPtr.Zero; + } + + break; + } + + case (uint)WinConst.WM_KEYUP: // 非系统键被抬起时 + { + uint flags = 0; + if ((lParam.To32().HIWORD() & (int)WinConst.KF_REPEAT) != 0) + { + flags |= (uint)wkeKeyFlags.WKE_REPEAT; + } + + if ((lParam.To32().HIWORD() & (int)WinConst.KF_EXTENDED) != 0) + { + flags |= (uint)wkeKeyFlags.WKE_EXTENDED; + } + + if (MBApi.wkeFireKeyUpEvent(Handle, wParam.To32(), flags, false) != 0) + { + return IntPtr.Zero; + } + + break; + } + + case (uint)WinConst.WM_CHAR: // ASCII码为0-127之间的按键被按下时 + { + uint flags = 0; + if ((lParam.To32().HIWORD() & (int)WinConst.KF_REPEAT) != 0) + { + flags |= (uint)wkeKeyFlags.WKE_REPEAT; + } + + if ((lParam.To32().HIWORD() & (int)WinConst.KF_EXTENDED) != 0) + { + flags |= (uint)wkeKeyFlags.WKE_EXTENDED; + } + + if (MBApi.wkeFireKeyPressEvent(Handle, wParam.To32(), flags, false) != 0) + { + return IntPtr.Zero; + } + + break; + } + + case (uint)WinConst.WM_LBUTTONDOWN: + case (uint)WinConst.WM_MBUTTONDOWN: + case (uint)WinConst.WM_RBUTTONDOWN: + case (uint)WinConst.WM_LBUTTONDBLCLK: + case (uint)WinConst.WM_MBUTTONDBLCLK: + case (uint)WinConst.WM_RBUTTONDBLCLK: + case (uint)WinConst.WM_LBUTTONUP: + case (uint)WinConst.WM_MBUTTONUP: + case (uint)WinConst.WM_RBUTTONUP: + case (uint)WinConst.WM_MOUSEMOVE: + { + if (msg == (uint)WinConst.WM_LBUTTONDOWN || msg == (uint)WinConst.WM_MBUTTONDOWN || msg == (uint)WinConst.WM_RBUTTONDOWN) + { + if (MB_Common.GetFocus() != hWnd) + { + MB_Common.SetFocus(hWnd); + } + MB_Common.SetCapture(hWnd); + } + else if (msg == (uint)WinConst.WM_LBUTTONUP || msg == (uint)WinConst.WM_MBUTTONUP || msg == (uint)WinConst.WM_RBUTTONUP) + { + MB_Common.ReleaseCapture(); + } + + uint flags = 0; + if ((wParam.To32() & (int)WinConst.MK_CONTROL) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_CONTROL; + } + + if ((wParam.To32() & (int)WinConst.MK_SHIFT) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_SHIFT; + } + + if ((wParam.To32() & (int)WinConst.MK_LBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_LBUTTON; + } + + if ((wParam.To32() & (int)WinConst.MK_MBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_MBUTTON; + } + + if ((wParam.To32() & (int)WinConst.MK_RBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_RBUTTON; + } + + if (MBApi.wkeFireMouseEvent(Handle, msg, lParam.To32().LOWORD(), lParam.To32().HIWORD(), flags) != 0) + { + return IntPtr.Zero; + } + + break; + } + + case (uint)WinConst.WM_CONTEXTMENU: + { + POINT pt; + pt.x = lParam.To32().LOWORD(); + pt.y = lParam.To32().HIWORD(); + + if (pt.x != -1 && pt.y != -1) + { + MB_Common.ScreenToClient(hWnd, ref pt); + } + + uint flags = 0; + + if ((wParam.To32() & (int)WinConst.MK_CONTROL) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_CONTROL; + } + + if ((wParam.To32() & (int)WinConst.MK_SHIFT) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_SHIFT; + } + + if ((wParam.To32() & (int)WinConst.MK_LBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_LBUTTON; + } + + if ((wParam.To32() & (int)WinConst.MK_MBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_MBUTTON; + } + + if ((wParam.To32() & (int)WinConst.MK_RBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_RBUTTON; + } + + if (MBApi.wkeFireContextMenuEvent(Handle, pt.x, pt.y, flags) != 0) + { + return IntPtr.Zero; + } + + break; + } + + case (uint)WinConst.WM_MOUSEWHEEL: + { + POINT pt; + pt.x = lParam.To32().LOWORD(); + pt.y = lParam.To32().HIWORD(); + MB_Common.ScreenToClient(hWnd, ref pt); + + uint flags = 0; + + if ((wParam.To32() & (int)WinConst.MK_CONTROL) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_CONTROL; + } + + if ((wParam.To32() & (int)WinConst.MK_SHIFT) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_SHIFT; + } + + if ((wParam.To32() & (int)WinConst.MK_LBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_LBUTTON; + } + + if ((wParam.To32() & (int)WinConst.MK_MBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_MBUTTON; + } + + if ((wParam.To32() & (int)WinConst.MK_RBUTTON) != 0) + { + flags |= (uint)wkeMouseFlags.WKE_RBUTTON; + } + + if (MBApi.wkeFireMouseWheelEvent(Handle, pt.x, pt.y, wParam.To32().HIWORD(), flags) != 0) + { + return IntPtr.Zero; + } + + break; + } + case (uint)WinConst.WM_SETFOCUS: + { + MBApi.wkeSetFocus(Handle); + return IntPtr.Zero; + } + + case (uint)WinConst.WM_KILLFOCUS: + { + MBApi.wkeKillFocus(Handle); + return IntPtr.Zero; + } + + case (uint)WinConst.WM_SETCURSOR: + { + if (MBApi.wkeFireWindowsMessage(Handle, hWnd, (uint)WinConst.WM_SETCURSOR, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) != 0) + { + return IntPtr.Zero; + } + + break; + } + + case (uint)WinConst.WM_IME_STARTCOMPOSITION: + { + wkeRect caret = MBApi.wkeGetCaretRect(Handle); + + COMPOSITIONFORM COMPOSITIONFORM = new COMPOSITIONFORM(); + COMPOSITIONFORM.dwStyle = (int)WinConst.CFS_POINT | (int)WinConst.CFS_FORCE_POSITION; + COMPOSITIONFORM.ptCurrentPos.x = caret.x; + COMPOSITIONFORM.ptCurrentPos.y = caret.y; + + IntPtr hIMC = MB_Common.ImmGetContext(hWnd); + MB_Common.ImmSetCompositionWindow(hIMC, ref COMPOSITIONFORM); + MB_Common.ImmReleaseContext(hWnd, hIMC); + + return IntPtr.Zero; + } + + case (uint)WinConst.WM_INPUTLANGCHANGE: + { + return MB_Common.DefWindowProc(hWnd, msg, wParam, lParam); + } + } + + return MB_Common.CallWindowProc(m_OldProc, hWnd, msg, wParam, lParam); + } + + #region 基本方法 + + /// + /// 初始化miniblink,如果没有调用,则在 new WebView 时会自己初始化 + /// + public void wkeInitialize() + { + if (MBApi.wkeIsInitialize() == 0) + { + MBApi.wkeInitialize(); + } + } + + /// + /// 初始化miniblink,并可以设置一些参数,如果没有调用,则在 new WebView 时会自己初始化 + /// + /// + public void wkeInitialize(wkeSettings settings) + { + if (MBApi.wkeIsInitialize() == 0) + { + MBApi.wkeInitializeEx(settings); + } + } + + /// + /// 获取版本 + /// + public uint Version + { + get { return MBApi.wkeGetVersion(); } + } + + /// + /// 获取版本信息 + /// + public string VersionString + { + get + { + IntPtr utf8 = MBApi.wkeGetVersionString(); + if (utf8 != IntPtr.Zero) + { + return Marshal.PtrToStringAnsi(utf8); + } + return null; + } + } + + /// + /// 设置代理 + /// + /// + public void SetProxy(wkeProxy proxy) + { + MBApi.wkeSetProxy(ref proxy); + } + + /// + /// 判断是否主框架 + /// + /// 框架句柄 + /// + public bool FrameIsMainFrame(IntPtr WebFrame) + { + return MBApi.wkeIsMainFrame(WebFrame) != 0; + } + + /// + /// 判断是否远程框架 + /// + /// + /// + public bool FrameIsRemoteFrame(IntPtr WebFrame) + { + return MBApi.wkeIsWebRemoteFrame(WebFrame) != 0; + } + + /// + /// 获取v8Context + /// + /// 框架句柄 + /// + public IntPtr FrameGetMainWorldScriptContext(IntPtr WebFrame) + { + IntPtr v8ContextPtr = IntPtr.Zero; + MBApi.wkeWebFrameGetMainWorldScriptContext(WebFrame, ref v8ContextPtr); + return v8ContextPtr; + } + + /// + /// 获取v8Isolate + /// + /// + public IntPtr GetBlinkMainThreadIsolate() + { + return MBApi.wkeGetBlinkMainThreadIsolate(); + } + + /// + /// 设置mimeType。此方法应该在 OnLoadUrlBegin 事件中使用 + /// + /// + /// MIMEType + public void NetSetMIMEType(IntPtr job, string MIMEType) + { + MBApi.wkeNetSetMIMEType(job, MIMEType); + } + + /// + /// 获取mimeType。此方法应该在 OnNetResponse 事件中使用 + /// + /// + /// + public string NetGetMIMEType(IntPtr job) + { + //IntPtr ptr = MBApi.wkeNetGetMIMEType(job, IntPtr.Zero); + //return ptr.UTF8PtrToStr(); + + IntPtr mime = MBApi.wkeCreateStringW(null, 0); + if (mime == IntPtr.Zero) + { + return string.Empty; + } + + MBApi.wkeNetGetMIMEType(job, mime); + string mimeType = MBApi.wkeGetStringW(mime).UTF8PtrToStr(); + MBApi.wkeDeleteString(mime); + + return mimeType; + } + + /// + /// 继续执行中断的网络任务,参看wkeNetHoldJobToAsynCommit接口。 + /// + /// + public void NetContinueJob(IntPtr job) + { + MBApi.wkeNetContinueJob(job); + } + + /// + /// 通过jobPtr获取当前请求的url。 + /// + /// + public string NetGetUrlByJob(IntPtr job) + { + IntPtr ptr = MBApi.wkeNetGetUrlByJob(job); + return ptr.UTF8PtrToStr(); + } + + /// + /// 获取Raw格式的HTTP请求数据,wkeSlist是个保存了网络数据的链表结构,请参看wke.h文件。 + /// + /// + public wkeSlist NetGetRawHttpHead(IntPtr job) + { + IntPtr ptr = MBApi.wkeNetGetRawHttpHead(job); + return (wkeSlist)ptr.UTF8PtrToStruct(typeof(wkeSlist)); + } + + /// + /// 获取Raw格式的HTTP响应数据,wkeSlist是个保存了网络数据的链表结构,请参看wke.h文件。 + /// + /// + /// + public wkeSlist NetGetRawResponseHead(IntPtr job) + { + IntPtr ptr = MBApi.wkeNetGetRawResponseHead(job); + return (wkeSlist)ptr.UTF8PtrToStruct(typeof(wkeSlist)); + } + + /// + /// 取消本次网络请求,需要在wkeOnLoadUrlBegin里调用。 + /// + /// + public void NetCancelRequest(IntPtr job) + { + MBApi.wkeNetCancelRequest(job); + } + + /// + /// 网络访问经常存在异步操作,当wkeOnLoadUrlBegin里拦截到一个请求后如不能马上判断出结果,此时可以调用本接口,处理完成后需调用wkeNetContinueJob来让此请求继续。 + /// + /// + /// + public bool NetHoldJobToAsynCommit(IntPtr job) + { + return MBApi.wkeNetHoldJobToAsynCommit(job) == 1 ? true : false; + } + + /// + /// 修改当前请求的url。 + /// + /// + /// + /// + public bool NetChangeRequestUrl(IntPtr job, string url) + { + return MBApi.wkeNetChangeRequestUrl(job, url) == 1 ? true : false; + } + + /// + /// 创建一个网络请求 + /// + /// + /// + /// + /// + public IntPtr NetCreateWebUrlRequest(IntPtr url, IntPtr method, IntPtr mime) + { + return MBApi.wkeNetCreateWebUrlRequest(url, method, mime); + } + + /// + /// 创建一个网络请求 + /// + /// + /// + public IntPtr NetCreateWebUrlRequest2(IntPtr request) + { + return MBApi.wkeNetCreateWebUrlRequest2(request); + } + + /// + /// 复制一个网络请求 + /// + /// + /// + /// + public IntPtr NetCopyWebUrlRequest(IntPtr job, bool needExtraData) + { + return MBApi.wkeNetCopyWebUrlRequest(job, needExtraData); + } + + /// + /// 取消网络请求。 + /// + /// + public void NetDeleteBlinkWebURLRequestPtr(IntPtr request) + { + MBApi.wkeNetDeleteBlinkWebURLRequestPtr(request); + } + + /// + /// 在指定网络请求中插入一个请求头。 + /// + /// + /// + /// + public void NetAddHTTPHeaderFieldToUrlRequest(IntPtr request, IntPtr name, IntPtr value) + { + MBApi.wkeNetAddHTTPHeaderFieldToUrlRequest(request, name, value); + } + + /// + /// 开始网络请求。 + /// + /// + /// + /// + /// + /// + public int NetStartUrlRequest(IntPtr webView, IntPtr request, IntPtr param, wkeUrlRequestCallbacks callback) + { + return MBApi.wkeNetStartUrlRequest(webView, request, param, callback); + } + + /// + /// 获取HTTP响应状态码。 + /// + /// + /// + public int NetGetHttpStatusCode(IntPtr response) + { + return MBApi.wkeNetGetHttpStatusCode(response); + } + + /// + /// 获取响应数据大小。 + /// + /// + /// + public long NetGetExpectedContentLength(IntPtr response) + { + return MBApi.wkeNetGetExpectedContentLength(response); + } + + /// + /// 获取响应url。 + /// + /// + /// + public string NetGetResponseUrl(IntPtr response) + { + IntPtr ptr = MBApi.wkeNetGetResponseUrl(response); + return ptr.UTF8PtrToStr(); + } + + /// + /// 取消网络请求。 + /// + /// + public void NetCancelWebUrlRequest(int requestId) + { + MBApi.wkeNetCancelWebUrlRequest(requestId); + } + + /// + /// 获取此请求中的post数据,注意:只有当请求是post时才可获取到,get请求直接从url上取就好了。 + /// + /// + /// + public wkePostBodyElements NetGetPostBody(IntPtr job) + { + IntPtr ptr = MBApi.wkeNetGetPostBody(job); + return (wkePostBodyElements)ptr.UTF8PtrToStruct(typeof(wkePostBodyElements)); + } + + /// + /// 创建一组post数据内容 + /// + /// + /// + /// + public wkePostBodyElements NetCreatePostBodyElements(long length) + { + IntPtr ptr = MBApi.wkeNetCreatePostBodyElements(Handle, length); + return (wkePostBodyElements)ptr.UTF8PtrToStruct(typeof(wkePostBodyElements)); + } + + /// + /// 干掉指定的post数据内容组,释放内存。 + /// + /// + /// + public void NetFreePostBodyElements(IntPtr elements) + { + MBApi.wkeNetFreePostBodyElements(elements); + } + + /// + /// 创建一个post数据内容。 + /// + /// + /// + public wkePostBodyElement NetCreatePostBodyElement() + { + IntPtr ptr = MBApi.wkeNetCreatePostBodyElement(Handle); + return (wkePostBodyElement)ptr.UTF8PtrToStruct(typeof(wkePostBodyElement)); + } + + /// + /// 干掉指定的post数据内容,释放内存。 + /// + /// + public void NetFreePostBodyElement(IntPtr element) + { + MBApi.wkeNetFreePostBodyElement(element); + } + + /// + /// 设置HTTP头字段。此方法应该在 OnLoadUrlBegin 事件中使用 + /// + /// + /// + /// + /// + public void NetSetHTTPHeaderField(IntPtr job, string key, string value, bool response) + { + MBApi.wkeNetSetHTTPHeaderField(job, key, value, response); + } + + /// + /// 获取HTTP请求头 + /// + /// + /// + public string NetGetHTTPHeaderField(IntPtr job, string key) + { + return MBApi.wkeNetGetHTTPHeaderField(job, key).UTF8PtrToStr(); + } + + /// + /// 获取HTTP响应头 + /// + /// + /// + public string NetGetHTTPHeaderFieldFromResponse(IntPtr job, string key) + { + return MBApi.wkeNetGetHTTPHeaderFieldFromResponse(job, key).UTF8PtrToStr(); + } + + /// + /// 设置网络数据。此方法应该在 OnLoadUrlBegin 事件中使用 + /// + /// + /// + public void NetSetData(IntPtr job, byte[] data) + { + MBApi.wkeNetSetData(job, data, data.Length); + } + + /// + /// 设置网络数据。此方法应该在 OnLoadUrlBegin 事件中使用 + /// + /// + /// string数据 + public void NetSetData(IntPtr job, string str) + { + byte[] data = Encoding.UTF8.GetBytes(str); + MBApi.wkeNetSetData(job, data, data.Length); + } + + /// + /// 设置网络数据。此方法应该在 OnLoadUrlBegin 事件中使用 + /// + /// + /// PNG图片数据 + public void NetSetData(IntPtr job, Image png) + { + byte[] data = null; + using (MemoryStream ms = new MemoryStream()) + { + png.Save(ms, ImageFormat.Png); + data = ms.GetBuffer(); + } + MBApi.wkeNetSetData(job, data, data.Length); + } + + /// + /// 设置网络数据。此方法应该在 OnLoadUrlBegin 事件中使用 + /// + /// + /// 图片数据 + /// 图片格式 + public void NetSetData(IntPtr job, Image img, ImageFormat fmt) + { + byte[] data = null; + using (MemoryStream ms = new MemoryStream()) + { + img.Save(ms, fmt); + data = ms.GetBuffer(); + } + MBApi.wkeNetSetData(job, data, data.Length); + } + + /// + /// 此方法应该在 OnLoadUrlBegin 事件中使用,调用此函数后,网络层收到数据会存储在一buf内,接收数据完成后响应OnLoadUrlEnd事件.#此调用严重影响性能,慎用, + /// 此函数和WebView.NetSetData的区别是,WebView.NetHookRequest会在接受到真正网络数据后再调用回调,并允许回调修改网络数据。 + /// 而WebView.NetSetData是在网络数据还没发送的时候修改 + /// + /// + public void NetHookRequest(IntPtr job) + { + MBApi.wkeNetHookRequest(job); + } + + /// + /// 获取请求方法 + /// + /// + /// + public wkeRequestType GetRequestMethod(IntPtr job) + { + return MBApi.wkeNetGetRequestMethod(job); + } + + /// + /// 获取图标,结果再Callback中取 + /// + /// + /// + /// + /// + public int NetGetFavicon(IntPtr WebView, wkeNetResponseCallback Callback, IntPtr param) + { + return MBApi.wkeNetGetFavicon(WebView, Callback, param); + } + + /// + /// 指定一个回调函数,访问所有Cookie + /// + /// wkeCookieVisitor 委托 + /// 用户数据 + public void VisitAllCookie(wkeCookieVisitor visitor, IntPtr userData) + { + MBApi.wkeVisitAllCookie(Handle, userData, visitor); + } + + /// + /// 执行cookie命令,清空等操作 + /// + /// + public void PerformCookieCommand(wkeCookieCommand command) + { + MBApi.wkePerformCookieCommand(command); + } + + /// + /// 绑定指定窗口 + /// + /// 窗口 + /// 是否透明模式,必须是顶层窗口才有效 + /// + public bool Bind(IWin32Window window, bool isTransparent = false) + { + if (m_hWnd == window.Handle) + { + return true; + } + + if (Handle == IntPtr.Zero) + { + Handle = MBApi.wkeCreateWebView(); + if (Handle == IntPtr.Zero) + { + return false; + } + } + m_hWnd = window.Handle; + + MBApi.wkeSetHandle(Handle, m_hWnd); + MBApi.wkeOnPaintUpdated(Handle, m_wkePaintUpdatedCallback, m_hWnd); + + if (isTransparent) + { + MBApi.wkeSetTransparent(Handle, true); + int exStyle = MB_Common.GetWindowLong(m_hWnd, (int)WinConst.GWL_EXSTYLE); + MB_Common.SetWindowLong(m_hWnd, (int)WinConst.GWL_EXSTYLE, exStyle | (int)WinConst.WS_EX_LAYERED); + } + else + { + MBApi.wkeSetTransparent(Handle, false); + } + + m_OldProc = (IntPtr)MB_Common.GetWindowLong(m_hWnd, (int)WinConst.GWL_WNDPROC); + IntPtr ptrProcCallback = Marshal.GetFunctionPointerForDelegate(m_WndProcCallback); + if (m_OldProc != ptrProcCallback) + { + m_OldProc = (IntPtr)MB_Common.SetWindowLong(m_hWnd, (int)WinConst.GWL_WNDPROC, (int)ptrProcCallback); + } + + RECT rc = new RECT(); + MB_Common.GetClientRect(m_hWnd, ref rc); + MBApi.wkeResize(Handle, rc.Right - rc.Left, rc.Bottom - rc.Top); + + return true; + } + + /// + /// 载入URL + /// + /// + public void Load(string URL) + { + MBApi.wkeLoadW(Handle, URL); + } + + /// + /// 载入URL + /// + /// + public void LoadURL(string URL) + { + MBApi.wkeLoadURLW(Handle, URL); + } + + /// + /// 载入本地文件 + /// + /// 文件名 + public void LoadFile(string FileName) + { + MBApi.wkeLoadFileW(Handle, FileName); + } + + /// + /// 载入内存HTML文本 + /// + /// HTML文本 + public void LoadHTML(string Html) + { + MBApi.wkeLoadHTMLW(Handle, Html); + } + + /// + /// POST方式载入URL + /// + /// + /// 提交的POST数据 + public void PostURL(string URL, byte[] PostData) + { + MBApi.wkePostURLW(Handle, URL, PostData, PostData.Length); + } + + /// + /// 载入内存HTML文本,并指定 BaseURL + /// + /// HTML文本 + /// + public void LoadHtmlWithBaseUrl(string Html, string BaseURL) + { + MBApi.wkeLoadHtmlWithBaseUrl(Handle, Encoding.UTF8.GetBytes(Html), Encoding.UTF8.GetBytes(BaseURL)); + } + + /// + /// 停止载入 + /// + public void StopLoading() + { + MBApi.wkeStopLoading(Handle); + } + + /// + /// 重新载入 + /// + public void Reload() + { + MBApi.wkeReload(Handle); + } + + /// + /// 跳转到指定偏移的浏览历史 + /// + /// + public void GoToOffset(int offset) + { + MBApi.wkeGoToOffset(Handle, offset); + } + + /// + /// 跳转到指定索引的浏览历史 + /// + /// + public void GoToIndex(int index) + { + MBApi.wkeGoToIndex(Handle, index); + } + + /// + /// 获取Webview的ID + /// + /// + public int GetId() + { + return MBApi.wkeGetWebviewId(Handle); + } + + /// + /// 根据Webview的ID判断是否活动Webview + /// + /// + /// + public bool IsWebviewAlive(int webViewId) + { + return MBApi.wkeIsWebviewAlive(Handle, webViewId) != 0; + } + + /// + /// 获取文档完成URL + /// + /// 框架ID + /// + /// + public string GetDocumentCompleteURL(IntPtr frameId, string partialURL) + { + byte[] utf8 = Encoding.UTF8.GetBytes(partialURL); + return MBApi.wkeGetDocumentCompleteURL(Handle, frameId, utf8).UTF8PtrToStr(); + } + + /// + /// 获取当前URL + /// + public string GetURL() + { + IntPtr pUrl = MBApi.wkeGetURL(Handle); + if (pUrl != IntPtr.Zero) + return pUrl.UTF8PtrToStr(); + return string.Empty; + } + + /// + /// 获取指定框架的URL + /// + /// 框架ID + /// + public string GetFrameURL(IntPtr FrameId) + { + IntPtr pUrl = MBApi.wkeGetFrameUrl(Handle, FrameId); + if (pUrl != IntPtr.Zero) + return pUrl.UTF8PtrToStr(); + return string.Empty; + } + + /// + /// 垃圾回收 + /// + /// 延迟的毫秒数 + public void GC(int delayMs) + { + MBApi.wkeGC(Handle, delayMs); + } + + /// + /// 设置当前WebView的代理 + /// + /// + public void SetViewProxy(wkeProxy proxy) + { + MBApi.wkeSetViewProxy(Handle, ref proxy); + } + + /// + /// 休眠 + /// + public void Sleep() + { + MBApi.wkeSleep(Handle); + } + + /// + /// 唤醒 + /// + public void Wake() + { + MBApi.wkeWake(Handle); + } + + /// + /// 设置UserAgent + /// + /// + public void SetUserAgent(string UserAgent) + { + MBApi.wkeSetUserAgentW(Handle, UserAgent); + } + + /// + /// 获取UserAgent + /// + /// + public string GetUserAgent() + { + IntPtr pstr = MBApi.wkeGetUserAgent(Handle); + if (pstr != IntPtr.Zero) + { + return pstr.UTF8PtrToStr(); + } + return string.Empty; + } + + /// + /// 后退 + /// + public bool GoBack() + { + return MBApi.wkeGoBack(Handle) != 0; + } + + /// + /// 前进 + /// + public bool GoForward() + { + return MBApi.wkeGoForward(Handle) != 0; + } + + /// + /// 全选 + /// + public void EditorSelectAll() + { + MBApi.wkeEditorSelectAll(Handle); + } + + /// + /// 取消选择 + /// + public void EditorUnSelect() + { + MBApi.wkeEditorUnSelect(Handle); + } + + /// + /// 复制 + /// + public void EditorCopy() + { + MBApi.wkeEditorCopy(Handle); + } + + /// + /// 剪切 + /// + public void EditorCut() + { + MBApi.wkeEditorCut(Handle); + } + + /// + /// 粘贴 + /// + public void EditorPaste() + { + MBApi.wkeEditorPaste(Handle); + } + + /// + /// 删除 + /// + public void EditorDelete() + { + MBApi.wkeEditorDelete(Handle); + } + + /// + /// 撤销 + /// + public void EditorUndo() + { + MBApi.wkeEditorUndo(Handle); + } + + /// + /// 重做 + /// + public void EditorRedo() + { + MBApi.wkeEditorRedo(Handle); + } + + /// + /// 获取Cookie + /// + /// + public string GetCookie() + { + IntPtr pStr = MBApi.wkeGetCookieW(Handle); + if (pStr != IntPtr.Zero) + { + return Marshal.PtrToStringUni(pStr); + } + return string.Empty; + } + + /// + /// 设置Cookie + /// + /// + /// cookie格式必须是:Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure + public void SetCookie(string Url, string Cookie) + { + byte[] url = Encoding.UTF8.GetBytes(Url); + byte[] cookie = Encoding.UTF8.GetBytes(Cookie); + MBApi.wkeSetCookie(Handle, url, cookie); + } + + /// + /// 设置Cookie目录 + /// + /// + public void SetCookieJarPath(string Path) + { + MBApi.wkeSetCookieJarPath(Handle, Path); + } + + /// + /// 设置Cookie全路径,包含文件名 + /// + /// + public void SetCookieJarFullPath(string FileName) + { + MBApi.wkeSetCookieJarFullPath(Handle, FileName); + } + + /// + /// 设置 LocalStorage 目录 + /// + /// + public void SetLocalStorageFullPath(string Path) + { + MBApi.wkeSetLocalStorageFullPath(Handle, Path); + } + + /// + /// 添加插件目录 + /// + /// + public void AddPluginDirectory(string Path) + { + MBApi.wkeAddPluginDirectory(Handle, Path); + } + + /// + /// 获得焦点 + /// + public void SetFocus() + { + MBApi.wkeSetFocus(Handle); + } + + /// + /// 失去焦点 + /// + public void KillFocus() + { + MBApi.wkeKillFocus(Handle); + } + + /// + /// 运行JS + /// + /// 脚本,如果需要返回值,则需要 return + /// + public object RunJS(string JavaScript) + { + long jsValue = MBApi.wkeRunJSW(Handle, JavaScript); + return ToNetValue(jsValue); + } + + /// + /// 执行页面中的js函数 + /// + /// + /// + /// + public object CallJsFunc(string strFuncName, params object[] param) + { + IntPtr es = MBApi.wkeGlobalExec(Handle); + var args = param.Select(arg => ToJsValue(arg)).ToArray(); + long jsValue = MBApi.jsCall(es, MBApi.jsGetGlobal(es, strFuncName), MBApi.jsUndefined(), args, args.Length); + + return ToNetValue(jsValue); + } + + /// + /// 将js中的函数绑定到c#的函数,用于实现js调用c# + /// + /// + /// + /// + public void BindFunction(string name, wkeJsNativeFunction fn, uint argCount = 0) + { + MBApi.wkeJsBindFunction(name, fn, IntPtr.Zero, argCount); + } + + /// + /// 在指定框架运行JS + /// + /// 框架ID + /// 脚本 + /// 是否闭包 + /// + public object RunJsByFrame(IntPtr FrameId, string JavaScript, bool IsInClosure = false) + { + byte[] utf8 = Encoding.UTF8.GetBytes(JavaScript); + return MBApi.wkeRunJsByFrame(Handle, FrameId, utf8, IsInClosure); + } + + /// + /// 全局执行 + /// + /// 返回全局 jsExecState + public IntPtr GlobalExec() + { + return MBApi.wkeGlobalExec(Handle); + } + + /// + /// 获取指定框架jsExecState + /// + /// 框架ID + /// 返回 jsExecState + public IntPtr GetGlobalExecByFrame(IntPtr FrameId) + { + return MBApi.wkeGetGlobalExecByFrame(Handle, FrameId); + } + + /// + /// 在c#中封装一个js函数,用于下面的类型转换 + /// + public class JsFunc + { + private string m_strName = null; + private WebView m_webView; + + public JsFunc(WebView webView, long jsValue) + { + m_webView = webView; + IntPtr es = MBApi.wkeGlobalExec(m_webView.Handle); + m_strName = "func" + Guid.NewGuid().ToString().Replace("-", ""); + + MBApi.jsSetGlobal(es, m_strName, jsValue); + } + + public object Invoke(params object[] param) + { + IntPtr es = MBApi.wkeGlobalExec(m_webView.Handle); + long value = MBApi.jsGetGlobal(es, m_strName); + + long[] jsps = param.Select(i => m_webView.ToJsValue(i)).ToArray(); + object result = m_webView.ToNetValue(MBApi.jsCall(es, value, MBApi.jsUndefined(), jsps, jsps.Length)); + + MBApi.jsSetGlobal(es, m_strName, MBApi.jsUndefined()); + + return result; + } + } + + + /// + /// 将js值转成c#值,参考凹大神的 https://gitee.com/aochulai/NetMiniblink + /// + /// + /// 指定如果是函数是否执行该函数,如果执行,则返回函数执行的结果而不是函数本身 + /// + public object ToNetValue(long value, bool bFunExecute = false) + { + jsType type = MBApi.jsTypeOf(value); + IntPtr es = MBApi.wkeGlobalExec(Handle); + + switch (type) + { + case jsType.NULL: + case jsType.UNDEFINED: + { + return null; + } + + case jsType.NUMBER: + { + return MBApi.jsToDouble(es, value); + } + + case jsType.BOOLEAN: + { + return MBApi.jsToBoolean(es, value); + } + + case jsType.STRING: + { + return MBApi.jsToTempStringW(es, value).UnicodePtrToStr(); + } + + case jsType.FUNCTION: + { + JsFunc function = new JsFunc(this, value); + if (bFunExecute) + { + return function.Invoke(); // 如果有参数一般是从另一个jsType传过来,具体情况具体分析 + } + + return function; + } + + case jsType.ARRAY: + { + int len = MBApi.jsGetLength(es, value); + object[] array = new object[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = ToNetValue(MBApi.jsGetAt(es, value, i)); + } + + return array; + } + + case jsType.OBJECT: + { + IntPtr ptr = MBApi.jsGetKeys(es, value); + jsKeys keys = (jsKeys)Marshal.PtrToStructure(ptr, typeof(jsKeys)); + string[] strKeyArr = keys.keys.PtrToStringArray(keys.length); + + ExpandoObject exp = new ExpandoObject(); + IDictionary map = (IDictionary)exp; + foreach (string key in strKeyArr) + { + map.Add(key, ToNetValue(MBApi.jsGet(es, value, key))); + } + + return map; + } + + default: + { + throw new NotSupportedException(); + } + } + } + + // 定义一个通用的函数形式 + public delegate object CommonFuncType(object[] param); + + /// + /// 将c#值转成js值 + /// + /// + /// 指定如果是函数是否执行该函数,如果执行则返回函数执行的结果,如果不执行则返回的是函数的参数, + /// 注意不是函数本身,这个和ToNetValue不一样,这是由于jsData结构定义导致的 + /// + public long ToJsValue(object obj, bool bFunExecute = false) + { + IntPtr es = MBApi.wkeGlobalExec(Handle); + + if (obj == null) + { + return MBApi.jsUndefined(); + } + else if (obj is int) + { + return MBApi.jsInt((int)obj); + } + else if (obj is bool) + { + return MBApi.jsBoolean((bool)obj); + } + else if (obj is double) + { + return MBApi.jsDouble((double)obj); + } + else if (obj is long) + { + return ToJsValue(obj.ToString()); + } + else if (obj is float) + { + return MBApi.jsFloat((float)obj); + } + else if (obj is DateTime) + { + return MBApi.jsDouble(((DateTime)obj).ToLong()); + } + else if (obj is string) + { + return MBApi.jsStringW(es, obj.ToString()); + } + else if (obj is decimal) + { + var dec = (decimal)obj; + if (dec.ToString().Contains(".")) + { + return ToJsValue(Convert.ToDouble(dec.ToString())); + } + else + { + return ToJsValue(Convert.ToInt32(dec.ToString())); + } + } + else if (obj is IEnumerable) + { + List list = new List(); + foreach (object item in (IEnumerable)obj) + { + list.Add(item); + } + + long array = MBApi.jsEmptyArray(es); + MBApi.jsSetLength(es, array, list.Count); + + for (int i = 0; i < list.Count; i++) + { + MBApi.jsSetAt(es, array, i, ToJsValue(list[i])); + } + + return array; + } + else if (obj is Delegate) + { + Delegate func = (Delegate)obj; + IntPtr funcptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(jsData))); + + jsData funcdata = new jsData + { + typeName = "function", + + finalize = (ptr) => + { + Marshal.FreeHGlobal(ptr); + }, + + callAsFunction = (fes, fobj, fargs, fcount) => + { + if (func is CommonFuncType) + { + var fps = new List(); + for (var i = 0; i < fcount; i++) + { + fps.Add(ToNetValue(MBApi.jsArg(fes, i))); + } + + if (bFunExecute) + { + return ToJsValue(((CommonFuncType)func)(fps.ToArray())); + } + + return ToJsValue(fps.ToArray()); + } + else // 如果传过来的不是动态参数,而是具体的参数 + { + object[] fps = new object[func.Method.GetParameters().Length]; + for (int i = 0; i < fcount && i < fps.Length; i++) + { + fps[i] = ToNetValue(MBApi.jsArg(fes, i)); + } + + if (bFunExecute) + { + return ToJsValue(func.Method.Invoke(func.Target, fps)); + } + + return ToJsValue(fps); + } + }, + }; + + Marshal.StructureToPtr(funcdata, funcptr, false); + + return MBApi.jsFunction(es, funcptr); + } + else + { + long jsobj = MBApi.jsEmptyObject(es); + + PropertyInfo[] PropertyArr = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); + foreach (var ps in PropertyArr) + { + object oValue = ps.GetValue(obj, null); + if (oValue != null) + { + MBApi.jsSet(es, jsobj, ps.Name, ToJsValue(oValue)); + } + } + + return jsobj; + } + } + + /// + /// 启用或禁用编辑模式 + /// + /// + public void SetEditable(bool editable) + { + MBApi.wkeSetEditable(Handle, editable); + } + + /// + /// 启用或禁用跨域检查 + /// + /// + public void SetCspCheckEnable(bool enable) + { + MBApi.wkeSetCspCheckEnable(Handle, enable); + } + + /// + /// 设置网络接口 + /// + /// + public void SetNetInterface(string NetInterface) + { + MBApi.wkeSetViewNetInterface(Handle, NetInterface); + } + + /// + /// 截图 + /// + /// + public Bitmap PrintToBitmap() + { + if (Handle == IntPtr.Zero) + { + return null; + } + + MBApi.wkeRunJSW(Handle, @"document.body.style.overflow='hidden'"); + int w = MBApi.wkeGetContentWidth(Handle); + int h = MBApi.wkeGetContentHeight(Handle); + + int oldwidth = MBApi.wkeGetWidth(Handle); + int oldheight = MBApi.wkeGetHeight(Handle); + + MBApi.wkeResize(Handle, w, h); + + Bitmap bmp = new Bitmap(w, h); + Rectangle rc = new Rectangle(0, 0, w, h); + System.Drawing.Imaging.BitmapData data = bmp.LockBits(rc, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + MBApi.wkePaint(Handle, data.Scan0, 0); + bmp.UnlockBits(data); + + MBApi.wkeResize(Handle, oldwidth, oldheight); + MBApi.wkeRunJSW(Handle, @"document.body.style.overflow='visible'"); + + return bmp; + } + + /// + /// 设置调试配置 + /// + /// "showDevTools" 是开启devtools功能,参数为:front_end/inspector.html(utf8编码) + /// + public void SetDebugConfig(string debugString, string param) + { + MBApi.wkeSetDebugConfig(Handle, debugString, Encoding.UTF8.GetBytes(param)); + } + + /// + /// 获取调试配置 + /// + /// + /// + public string GetDebugConfig(string debugString) + { + return MBApi.wkeGetDebugConfig(Handle, debugString).UTF8PtrToStr(); + } + + /// + /// 设置上下文菜单项目是否显示 + /// + /// + /// + public void SetContextMenuItemShow(wkeMenuItemId item, bool isShow) + { + MBApi.wkeSetContextMenuItemShow(Handle, item, isShow); + } + + /// + /// 设置语言 + /// + /// + public void SetLanguage(string language) + { + MBApi.wkeSetLanguage(Handle, language); + } + + /// + /// 设置设备参数 + /// + /// 如:“navigator.platform” + /// + /// + /// + public void SetDeviceParameter(string device, string paramStr, int paramInt = 0, float paramFloat = 0) + { + MBApi.wkeSetDeviceParameter(Handle, device, paramStr, paramInt, paramFloat); + } + + /// + /// 显示DevTools窗口 + /// + /// 路径 + /// + public void ShowDevtools(string Path, wkeOnShowDevtoolsCallback Callback, IntPtr Param) + { + MBApi.wkeShowDevtools(Handle, Path, Callback, Param); + } + + /// + /// 删除将发送请求的信息 + /// + /// + public void DeleteWillSendRequestInfo(IntPtr WillSendRequestInfoPtr) + { + MBApi.wkeDeleteWillSendRequestInfo(Handle, WillSendRequestInfoPtr); + } + + /// + /// 在指定框架插入CSS + /// + /// 框架ID + /// + public void InsertCSSByFrame(IntPtr FrameId, string cssText) + { + byte[] utf8 = Encoding.UTF8.GetBytes(cssText); + MBApi.wkeInsertCSSByFrame(Handle, FrameId, utf8); + } + + /// + /// 序列化到MHTML + /// + /// + public string SerializeToMHTML() + { + return MBApi.wkeUtilSerializeToMHTML(Handle).UTF8PtrToStr(); + } + + /// + /// 获取网页HTML + /// + /// + public string GetSource() + { + return MBApi.wkeGetSource(Handle).UTF8PtrToStr(); + } + + /// + /// 设置视图配置,可设置尺寸和背景色 + /// + /// + public void SetViewSettings(wkeViewSettings settings) + { + MBApi.wkeSetViewSettings(Handle, settings); + } + + #endregion + + #region 属性 + + /// + /// 获取 WebView 句柄 + /// + public IntPtr Handle { get; private set; } + + /// + /// 获取宿主窗口句柄 + /// + public IntPtr HostHandle + { + get { return MBApi.wkeGetHostHWND(Handle); } + } + + /// + /// 获取是否处于唤醒状态 + /// + public bool IsWake + { + get { return MBApi.wkeIsAwake(Handle) != 0; } + } + + /// + /// 获取是否正在载入 + /// + public bool IsLoading + { + get { return MBApi.wkeIsLoading(Handle) != 0; } + } + + /// + /// 获取是否载入失败 + /// + public bool IsLoadingFailed + { + get { return MBApi.wkeIsLoadingFailed(Handle) != 0; } + } + + /// + /// 获取是否载入完成 + /// + public bool IsLoadingCompleted + { + get { return MBApi.wkeIsLoadingCompleted(Handle) != 0; } + } + + /// + /// 获取文档是否就绪 + /// + public bool IsDocumentReady + { + get { return MBApi.wkeIsDocumentReady(Handle) != 0; } + } + + /// + /// 获取标题 + /// + public string Title + { + get + { + IntPtr pTitle = MBApi.wkeGetTitleW(Handle); + if (pTitle != IntPtr.Zero) + { + return Marshal.PtrToStringUni(pTitle); + } + return string.Empty; + } + } + + /// + /// 获取宽度 + /// + public int Width + { + get { return MBApi.wkeGetWidth(Handle); } + } + + /// + /// 获取高度 + /// + public int Height + { + get { return MBApi.wkeGetHeight(Handle); } + } + + /// + /// 获取内容宽度 + /// + public int ContentWidth + { + get { return MBApi.wkeGetContentWidth(Handle); } + } + + /// + /// 获取内容高度 + /// + public int ContentHeight + { + get { return MBApi.wkeGetContentHeight(Handle); } + } + + /// + /// 是否透明 + /// + public bool Transparent + { + get { return m_bTransparent; } + set + { + m_bTransparent = value; + MBApi.wkeSetTransparent(Handle, value); + } + } + + /// + /// 获取是否能后退操作 + /// + public bool CanGoBack + { + get { return MBApi.wkeCanGoBack(Handle) != 0; } + } + + /// + /// 获取是否能前进操作 + /// + public bool CanGoForward + { + get { return MBApi.wkeCanGoForward(Handle) != 0; } + } + + /// + /// 获取或设置Cookie引擎是否启用 + /// + public bool CookieEnabled + { + get { return MBApi.wkeIsCookieEnabled(Handle) != 0; } + set { MBApi.wkeSetCookieEnabled(Handle, value); } + } + + /// + /// 获取或设置媒体音量 + /// + public float MediaVolume + { + get { return MBApi.wkeGetMediaVolume(Handle); } + set { MBApi.wkeSetMediaVolume(Handle, value); } + } + + /// + /// 获取或设置缩放因子 + /// + public float ZoomFactor + { + get { return MBApi.wkeGetZoomFactor(Handle); } + set { MBApi.wkeSetZoomFactor(Handle, value); } + } + + /// + /// 获取主框架句柄 + /// + public IntPtr MainFrame + { + get { return MBApi.wkeWebFrameGetMainFrame(Handle); } + } + + /// + /// 获取或设置光标类型 + /// + public wkeCursorStyle CursorInfoType + { + get { return MBApi.wkeGetCursorInfoType(Handle); } + set { MBApi.wkeSetCursorInfoType(Handle, value); } + } + + /// + /// 设置是否启用内存缓存 + /// + /// + public bool MemoryCacheEnable + { + set { MBApi.wkeSetMemoryCacheEnable(Handle, value); } + } + + /// + /// 设置是否导航到新窗口 + /// + /// 如果为false 则不会弹出新窗口 + public bool NavigationToNewWindowEnable + { + set { MBApi.wkeSetNavigationToNewWindowEnable(Handle, value); } + } + + /// + /// 设置是否启用触摸 + /// + public bool TouchEnable + { + set { MBApi.wkeSetTouchEnabled(Handle, value); } + } + + /// + /// 设置是否启用 NPAPI 插件 + /// + public bool NpapiPluginsEnabled + { + set { MBApi.wkeSetNpapiPluginsEnabled(Handle, value); } + } + + /// + /// 设置是否启用无头模式,可以关闭渲染 + /// + public bool HeadlessEnabled + { + set { MBApi.wkeSetHeadlessEnabled(Handle, value); } + } + + /// + /// 设置是否启用拖拽,可关闭拖拽文件加载网页 + /// + public bool DragEnable + { + set { MBApi.wkeSetDragEnable(Handle, value); } + } + + /// + /// 设置或获取是否禁用鼠标 + /// + public bool MouseEnabled + { + get { return m_bMouseEnabled; } + set { MBApi.wkeSetMouseEnabled(Handle, value); } + } + + /// + /// 可关闭拖拽到其他进程 + /// + public bool DragDropEnable + { + set { MBApi.wkeSetDragDropEnable(Handle, value); } + } + + /// + /// 设置资源回收间隔 + /// + public int ResourceGc + { + set { MBApi.wkeSetResourceGc(Handle, value); } + } + + /// + /// 获取是否真正处理手势 + /// + public bool IsProcessingUserGesture + { + get { return MBApi.wkeIsProcessingUserGesture(Handle) != 0; } + } + + #endregion + } + + #region 事件参数 + public class MiniblinkEventArgs : EventArgs + { + public IntPtr Handle { get; } + + public MiniblinkEventArgs(IntPtr webView) + { + Handle = webView; + } + } + + /// + /// OnMouseOverUrlChanged 事件参数 + /// + public class MouseOverUrlChangedEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + + public MouseOverUrlChangedEventArgs(IntPtr webView, IntPtr url) : base(webView) + { + m_url = url; + } + + public string URL + { + get { return MBApi.wkeGetStringW(m_url).UnicodePtrToStr(); } + } + } + + /// + /// OnTitleChange 事件参数 + /// + public class TitleChangeEventArgs : MiniblinkEventArgs + { + private IntPtr m_title; + + public TitleChangeEventArgs(IntPtr webView, IntPtr title) : base(webView) + { + m_title = title; + } + + public string Title + { + get { return MBApi.wkeGetStringW(m_title).UnicodePtrToStr(); } + } + } + + /// + /// OnUrlChange 事件参数 + /// + public class UrlChangeEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + + public UrlChangeEventArgs(IntPtr webView, IntPtr url, IntPtr webFrame) : base(webView) + { + m_url = url; + WebFrame = webFrame; + } + + public string URL + { + get { return MBApi.wkeGetStringW(m_url).UnicodePtrToStr(); } + } + + public IntPtr WebFrame { get; } + } + + /// + /// OnAlertBox事件参数 + /// + public class AlertBoxEventArgs : MiniblinkEventArgs + { + private IntPtr m_msg; + + public AlertBoxEventArgs(IntPtr webView, IntPtr msg) : base(webView) + { + m_msg = msg; + } + + public string Msg + { + get { return MBApi.wkeGetStringW(m_msg).UnicodePtrToStr(); } + } + } + + /// + /// OnConfirmBox事件参数 + /// + public class ConfirmBoxEventArgs : MiniblinkEventArgs + { + private IntPtr m_msg; + public bool Result { get; set; } + + public ConfirmBoxEventArgs(IntPtr webView, IntPtr msg) : base(webView) + { + m_msg = msg; + } + + public string Msg + { + get { return MBApi.wkeGetStringW(m_msg).UnicodePtrToStr(); } + } + } + + /// + /// OnPromptBox事件参数 + /// + public class PromptBoxEventArgs : MiniblinkEventArgs + { + private IntPtr m_msg; + private IntPtr m_defaultStr; + private IntPtr m_resultStr; + + public PromptBoxEventArgs(IntPtr webView, IntPtr msg, IntPtr defaultResult, IntPtr result) : base(webView) + { + m_msg = msg; + m_defaultStr = defaultResult; + m_resultStr = result; + } + + public bool Result { get; set; } + + public string Msg + { + get { return MBApi.wkeGetStringW(m_msg).UnicodePtrToStr(); } + } + + public string DefaultResultString + { + get { return MBApi.wkeGetStringW(m_defaultStr).UnicodePtrToStr(); } + } + + public string ResultString + { + set { MBApi.wkeSetStringW(m_resultStr, value, value.Length); } + } + } + + /// + /// OnNavigate事件参数 + /// + public class NavigateEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + + public NavigateEventArgs(IntPtr webView, wkeNavigationType navigationType, IntPtr url) : base(webView) + { + NavigationType = navigationType; + m_url = url; + } + + public wkeNavigationType NavigationType { get; } + + public bool Cancel { get; set; } + + public string URL + { + get { return MBApi.wkeGetStringW(m_url).UnicodePtrToStr(); } + } + } + + /// + /// OnCreateView事件参数 + /// + public class CreateViewEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + private IntPtr m_windowFeatures; + + public CreateViewEventArgs(IntPtr webView, wkeNavigationType navigationType, IntPtr url, IntPtr windowFeatures) : base(webView) + { + NavigationType = navigationType; + m_url = url; + m_windowFeatures = windowFeatures; + NewWebViewHandle = webView; + } + + public wkeNavigationType NavigationType { get; } + + public IntPtr NewWebViewHandle { get; set; } + + public string URL + { + get { return MBApi.wkeGetStringW(m_url).UnicodePtrToStr(); } + } + + public wkeWindowFeatures WindowFeatures + { + get { return (wkeWindowFeatures)m_windowFeatures.UTF8PtrToStruct(typeof(wkeWindowFeatures)); } + } + } + + /// + /// OnDocumentReady + /// + public class DocumentReadyEventArgs : MiniblinkEventArgs + { + public DocumentReadyEventArgs(IntPtr webView, IntPtr frame) : base(webView) + { + Frame = frame; + } + + public IntPtr Frame { get; } + } + + /// + /// OnLoadingFinish事件参数 + /// + public class LoadingFinishEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + private IntPtr m_failedReason; + + public LoadingFinishEventArgs(IntPtr webView, IntPtr url, wkeLoadingResult result, IntPtr failedReason) : base(webView) + { + m_url = url; + LoadingResult = result; + m_failedReason = failedReason; + } + + public wkeLoadingResult LoadingResult { get; } + + public string URL + { + get { return MBApi.wkeGetStringW(m_url).UnicodePtrToStr(); } + } + + public string FailedReason + { + get { return MBApi.wkeGetStringW(m_failedReason).UnicodePtrToStr(); } + } + } + + /// + /// OnDownload事件参数 + /// + public class DownloadEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + + public DownloadEventArgs(IntPtr webView, IntPtr url) : base(webView) + { + m_url = url; + } + + public string SaveFilePath { get; set; } + + public bool Cancel { get; set; } + + public long ContentLength { get; set; } + + public string URL + { + get { return m_url.UTF8PtrToStr(); } + } + + public event EventHandler Progress; + + public void OnProgress(DownloadProgressEventArgs e) + { + Progress?.Invoke(this, e); + } + + public event EventHandler Finish; + + public void OnFinish(DownloadFinishEventArgs e) + { + Finish?.Invoke(this, e); + } + } + + /// + /// OnDownload2事件参数,貌似有问题,经常报“c#尝试读取或写入受保护的内存。这通常指示其他内存已损坏” + /// + public class DownloadEventArgs2 : MiniblinkEventArgs + { + private IntPtr m_url; + private IntPtr m_mime; + private IntPtr m_disposition; + private IntPtr m_dataBind; + + public DownloadEventArgs2(IntPtr webView, IntPtr param, uint expectedContentLength, IntPtr url, IntPtr mime, IntPtr disposition, IntPtr job, IntPtr dataBind) : base(webView) + { + m_url = url; + m_mime = mime; + m_disposition = disposition; + m_dataBind = dataBind; + + ContentLength = expectedContentLength; + Job = job; + } + + public string SaveFilePath { get; set; } + + public bool Cancel { get; set; } + + public long ContentLength { get; set; } + + public IntPtr Job { get; } + + public string URL + { + get { return m_url.UTF8PtrToStr(); } + } + + public string Mime + { + get { return m_mime.UTF8PtrToStr(); } + } + + public string Disposition + { + get { return m_disposition.UTF8PtrToStr(); } + } + + public string DataBind + { + get { return m_dataBind.UTF8PtrToStr(); } + } + + public event EventHandler Progress; + + public void OnProgress(DownloadProgressEventArgs e) + { + Progress?.Invoke(this, e); + } + + public event EventHandler Finish; + + public void OnFinish(DownloadFinishEventArgs e) + { + Finish?.Invoke(this, e); + } + } + + /// + /// 下载过程事件参数 + /// + public class DownloadProgressEventArgs : EventArgs + { + public long Total { get; set; } + public long Received { get; set; } + public byte[] Data { get; set; } + public bool Cancel { get; set; } + } + + /// + /// 下载完成事件参数 + /// + public class DownloadFinishEventArgs : EventArgs + { + public Exception Error { get; set; } + public bool IsCompleted { get; set; } + } + + /// + /// OnConsole事件参数 + /// + public class ConsoleEventArgs : MiniblinkEventArgs + { + private IntPtr m_message; + private IntPtr m_sourceName; + private IntPtr m_stackTrace; + + public ConsoleEventArgs(IntPtr webView, wkeConsoleLevel level, IntPtr message, IntPtr sourceName, uint sourceLine, IntPtr stackTrace) : base(webView) + { + Level = level; + m_message = message; + m_sourceName = sourceName; + SourceLine = sourceLine; + m_stackTrace = stackTrace; + } + + public wkeConsoleLevel Level { get; } + + public uint SourceLine { get; } + + public string Message + { + get { return MBApi.wkeGetStringW(m_message).UTF8PtrToStr(); } + } + + public string SourceName + { + get { return MBApi.wkeGetStringW(m_sourceName).UTF8PtrToStr(); } + } + + public string StackTrace + { + get { return MBApi.wkeGetStringW(m_stackTrace).UTF8PtrToStr(); } + } + } + + /// + /// OnLoadUrlBegin事件参数 + /// + public class LoadUrlBeginEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + + public LoadUrlBeginEventArgs(IntPtr webView, IntPtr url, IntPtr job) : base(webView) + { + m_url = url; + Job = job; + } + + public string URL + { + get { return m_url.UTF8PtrToStr(); } + } + + public IntPtr Job { get; } + public bool Cancel { get; set; } + } + + /// + /// OnLoadUrlEnd事件参数 + /// + public class LoadUrlEndEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + private IntPtr m_buf; + + public LoadUrlEndEventArgs(IntPtr webView, IntPtr url, IntPtr job, IntPtr buf, int len) : base(webView) + { + m_url = url; + Job = job; + m_buf = buf; + Len = len; + } + + public IntPtr Job { get; } + + public int Len { get; } + + public string URL + { + get { return m_url.UTF8PtrToStr(); } + } + + public byte[] Data + { + get { return m_buf.StructToBytes(); } + set { m_buf = Data.ByteToUtf8Ptr(); } + } + } + + /// + /// OnLoadUrlFail事件参数 + /// + public class LoadUrlFailEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + + public LoadUrlFailEventArgs(IntPtr webView, IntPtr url, IntPtr job) : base(webView) + { + m_url = url; + Job = job; + } + + public IntPtr Job { get; } + + public string URL + { + get { return m_url.UTF8PtrToStr(); } + } + } + + /// + /// OnDidCreateScriptContext + /// + public class DidCreateScriptContextEventArgs : MiniblinkEventArgs + { + public DidCreateScriptContextEventArgs(IntPtr webView, IntPtr frame, IntPtr context, int extensionGroup, int worldId) : base(webView) + { + Frame = frame; + Context = context; + ExtensionGroup = extensionGroup; + WorldId = worldId; + } + + public IntPtr Frame { get; } + public IntPtr Context { get; } + public int ExtensionGroup { get; } + public int WorldId { get; } + } + + /// + /// OnWillReleaseScriptContext 事件参数 + /// + public class WillReleaseScriptContextEventArgs : MiniblinkEventArgs + { + public WillReleaseScriptContextEventArgs(IntPtr webView, IntPtr frame, IntPtr context, int worldId) : base(webView) + { + Frame = frame; + Context = context; + WorldId = worldId; + } + + public IntPtr Frame { get; } + public IntPtr Context { get; } + public int WorldId { get; } + } + + /// + /// OnNetResponse 事件参数 + /// + public class NetResponseEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + + public NetResponseEventArgs(IntPtr webView, IntPtr url, IntPtr job) : base(webView) + { + m_url = url; + Job = job; + } + + public string URL + { + get { return m_url.UTF8PtrToStr(); } + } + + public IntPtr Job { get; } + public bool Cancel { get; set; } + } + + /// + /// OnWillMediaLoad 事件参数 + /// + public class WillMediaLoadEventArgs : MiniblinkEventArgs + { + private IntPtr m_url; + private wkeMediaLoadInfo m_info; + + public WillMediaLoadEventArgs(IntPtr webView, IntPtr url, IntPtr info) : base(webView) + { + m_url = url; + m_info = (wkeMediaLoadInfo)Marshal.PtrToStructure(info, typeof(wkeMediaLoadInfo)); + } + + public string URL + { + get { return m_url.UTF8PtrToStr(); } + } + + public wkeMediaLoadInfo Info + { + get { return m_info; } + } + } + + /// + /// OnOtherLoad 事件参数 + /// + public class OtherLoadEventArgs : MiniblinkEventArgs + { + private wkeTempCallbackInfo m_info; + + public OtherLoadEventArgs(IntPtr webView, wkeOtherLoadType type, IntPtr info) : base(webView) + { + LoadType = type; + m_info = (wkeTempCallbackInfo)Marshal.PtrToStructure(info, typeof(wkeTempCallbackInfo)); + } + + public wkeOtherLoadType LoadType { get; } + + public int Size + { + get { return m_info.size; } + } + + public IntPtr Frame + { + get { return m_info.frame; } + } + + public wkeWillSendRequestInfo WillSendRequestInfo + { + get + { + wkeWillSendRequestInfo srInfo = new wkeWillSendRequestInfo(); + if (m_info.willSendRequestInfo != IntPtr.Zero) + { + srInfo.isHolded = Marshal.ReadInt32(m_info.willSendRequestInfo) != 0; + + IntPtr ptr = Marshal.ReadIntPtr(m_info.willSendRequestInfo, 4); + srInfo.url = MBApi.wkeGetStringW(ptr).UTF8PtrToStr(); + + ptr = Marshal.ReadIntPtr(m_info.willSendRequestInfo, 8); + srInfo.newUrl = MBApi.wkeGetStringW(ptr).UTF8PtrToStr(); + + srInfo.resourceType = (wkeResourceType)Marshal.ReadInt32(m_info.willSendRequestInfo, 12); + srInfo.httpResponseCode = Marshal.ReadInt32(m_info.willSendRequestInfo, 16); + ptr = Marshal.ReadIntPtr(m_info.willSendRequestInfo, 20); + srInfo.method = MBApi.wkeGetStringW(ptr).UTF8PtrToStr(); + + ptr = Marshal.ReadIntPtr(m_info.willSendRequestInfo, 24); + srInfo.referrer = MBApi.wkeGetStringW(ptr).UTF8PtrToStr(); + + srInfo.headers = Marshal.ReadIntPtr(m_info.willSendRequestInfo, 28); + } + + return srInfo; + } + } + + public IntPtr WillSendRequestInfoPtr + { + get { return m_info.willSendRequestInfo; } + } + } + + /// + /// 窗口过程事件参数 + /// + public class WindowProcEventArgs : EventArgs + { + public WindowProcEventArgs(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam) + { + Handle = hWnd; + Msg = msg; + this.wParam = wParam; + this.lParam = lParam; + } + + public IntPtr Handle { get; } + public int Msg { get; } + public IntPtr wParam { get; } + public IntPtr lParam { get; } + public IntPtr Result { get; set; } + + /// + /// 如果为 true 则会返回 Result ,false 则返回默认值 + /// + public bool bHand { get; set; } + } + + #endregion +} diff --git a/类库/Api.Framework/Model/ModelExtend.cs b/类库/Api.Framework/Model/ModelExtend.cs new file mode 100644 index 0000000..9a2ea05 --- /dev/null +++ b/类库/Api.Framework/Model/ModelExtend.cs @@ -0,0 +1,1989 @@ +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Properties; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 扩展方法 + /// + public static class ModelExtend + { + + private static readonly object lock_point = new object(); + + /// + /// 改变积分 + /// + /// 数据库操作对象 + /// 类型 + /// 金额(单位:元) + /// 用户id + /// 备注 + /// 自定义积分类型(为空即可) + public static fl_member_info ChangePoint(this SqlSugarClient session, PointType type, double money, long memberid, string message, string pointType_name = "") + { + //session.BeginTransaction(); + try + { + lock (lock_point) + { + var member = session.FindMemberInfoById(memberid); + if (member == null) return null; + + if (type < 0 && money > 0) money = -money; + + if (string.IsNullOrEmpty(pointType_name)) pointType_name = Enum.GetName(type.GetType(), type); + + var robot = session.FindRobotInfo(member.robot_name, member.robot_type); + + var point_hist = new fl_point_hist() { message = message, point = money, type = pointType_name, rid = (robot == null ? 0 : robot.id), uid = member.id, before_point = member.cur_point }; + + if (type != PointType.人为修改) + { + if (money > 0) + { + switch (type) + { + case PointType.消费补贴: + { + member.buy_point = (double)decimal.Round((decimal)money + (decimal)member.buy_point, 2); + member.finish_order++; + } + break; + case PointType.提成奖励: + member.ext_point = (double)decimal.Round((decimal)member.ext_point + (decimal)money, 2); + break; + case PointType.其他奖励: + member.rew_point = (double)decimal.Round((decimal)member.rew_point + (decimal)money, 2); + break; + } + if (type != PointType.退回积分) + member.sum_point = (double)decimal.Round((decimal)member.sum_point + (decimal)money, 2); + } + else + { + if (type == PointType.维权扣除) + { + if (message.Contains("提成")) + { + member.ext_point = (double)decimal.Round((decimal)member.ext_point + (decimal)money, 2); + } + else + { + member.buy_point = (double)decimal.Round((decimal)member.buy_point + (decimal)money, 2); + member.finish_order -= 1; + } + } + } + } + member.cur_point = (double)decimal.Round((decimal)member.cur_point + (decimal)money, 2); + + //#region 无视积分影响分组升级 + //if (member.ignore_group_update == SwitchType.关闭) + //{ + // //判断是否需要升级会员组 + // var groups = session.FindGroups(); + // var _oldGroup = session.FindGroup(member); + // var _newGroup = session.FindGroup(member.sum_point, member.bind_order); + // long group_id = member.group_id; + // if (_oldGroup != null && _newGroup != null && _oldGroup.id != _newGroup.id) + // { + // group_id = _newGroup.id; + // } + // member.group_id = group_id; + //} + //#endregion + + session.SaveOrUpdate(member, true); + member = session.UpdateMemberGroup(member); + + point_hist.after_point = member.cur_point; + point_hist = session.Insertable(point_hist).ExecuteReturnEntity(); + //session.Commit(); + EventClient.OnEvent(null, new MemberPointChangeEvent(point_hist)); + return member; + } + } + catch (Exception ex) + { + //session.Rollback(); + if (ex.Message.Contains("database disk image is malformed")) + throw new Exception("本地数据库已经损坏,请及时联系相关人员修复!"); + throw ex; + } + return null; + } + + public static void InsertRefundHistPoint(this SqlSugarClient session, string orderid, string orderid2, CpsType cpsType, string db_point, long uid = 0) + { + var rhPoint = FindRefundHistPoint(session, orderid, orderid2, cpsType); + if (rhPoint == null) + { + rhPoint = new fl_refund_hist_point() { cpstype = cpsType, orderid = orderid, orderid2 = orderid2, db_point = db_point, time = DateTime.Now, userid = uid }; + session.Insertable(rhPoint).ExecuteCommand(); + } + } + + public static fl_refund_hist_point FindRefundHistPoint(this SqlSugarClient session, string orderid, string orderid2, CpsType cpsType) + { + try + { + return session.FindSingle("select * from fl_refund_hist_point where cpsType = @cpsType and orderid = @orderid and orderid2 = @orderid2", new { cpsType = (int)cpsType, orderid = orderid, orderid2 = orderid2 }); + } + catch (Exception) + { } + return null; + } + + /// + /// 微信支付密码集合 + /// + /// + /// + /// + public static List FindWeixinpasswords(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_weixin_password_table"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.Find("select * from fl_weixin_password", new { }); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 查询微信密码信息 + /// + /// + /// + /// + /// + public static fl_weixin_password FindWeixinpassword(this SqlSugarClient session, long robot_id, bool refresh = false) + { + return session.FindWeixinpasswords(refresh).FirstOrDefault(f => f.robot_id == robot_id); + } + + /// + /// 查询淘宝自动绑定PID集合 + /// + /// + /// true刷新 + /// + public static List FindAlimamaAutoBindPid(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_alimama_auto_bind_adzone_info"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.FindAdzoneInfos().Where(f => f.custom_type == Resources.TbSoftwareType && f.alliance_id == (int)CpsType.阿里妈妈).ToList(); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 尾号绑定.非订单查询绑定(朋友圈等其他推广) + /// + /// + /// + /// + public static List FindAlimamaTailBindPid(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_alimama_tail_bind_adzone_info"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.FindAdzoneInfos().Where(f => (f.custom_type == "群发优惠券" || f.custom_type == "朋友圈代运营" || f.custom_type == "精准朋友圈" || f.custom_type == "朋友圈工具" || f.custom_type == "淘宝发单") && f.alliance_id == (int)CpsType.阿里妈妈).ToList(); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 阿里私人推广位 + /// + /// + /// 私人pid + /// + public static List FindAlimamaPrivatePid(this SqlSugarClient session, string adzone_id) + { + var list = session.FindAdzoneInfos().Where(f => f.adzone_pid.EndsWith("_" + adzone_id) && f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == "用户私人pid" && f.extend == "淘宝私人pid").ToList(); + return list; + } + + /// + /// 抖音私人推广位 + /// + /// + /// 私人pid + /// + public static List FindDouyinPrivatePid(this SqlSugarClient session, string adzone_id) + { + var list = session.FindAdzoneInfos().Where(f => f.adzone_pid == adzone_id && f.alliance_id == (int)CpsType.抖音联盟 && f.custom_type == "用户私人pid" && f.extend == "抖音私人pid").ToList(); + return list; + } + + /// + /// 京东私人推广位 + /// + /// + /// 私人pid + /// + public static List FindJingdongPrivatePid(this SqlSugarClient session, string adzone_id) + { + var list = session.FindAdzoneInfos().Where(f => f.adzone_pid.EndsWith("_" + adzone_id) && f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == "用户私人pid" && f.extend == "京东私人pid").ToList(); + return list; + } + + /// + /// 苏宁私人推广位 + /// + /// + /// 私人pid + /// + public static List FindSuningPrivatePid(this SqlSugarClient session, string adzone_id) + { + var list = session.FindAdzoneInfos().Where(f => f.adzone_pid == adzone_id && f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == "用户私人pid" && f.extend == "苏宁私人pid").ToList(); + return list; + } + + /// + /// 拼多多推广位自动绑定推广位 + /// + /// + /// 刷新 + /// + public static List FindSuningAutoBindPid(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_suning_auto_bind_adzone_info"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.苏宁易购 && f.custom_type == Resources.SNSoftwareType).Select(f => f.adzone_pid).ToList(); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 拼多多私人推广位 + /// + /// + /// 私人pid + /// + public static List FindPinduoduoPrivatePid(this SqlSugarClient session, string adzone_id) + { + var list = session.FindAdzoneInfos().Where(f => f.adzone_pid == adzone_id && f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == "用户私人pid" && f.extend == "拼多多私人pid").ToList(); + return list; + } + + public static List FindKuaishouPrivatePid(this SqlSugarClient session, string adzone_id) + { + var list = session.FindAdzoneInfos().Where(f => f.adzone_pid == adzone_id && f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == "用户私人pid" && f.extend == "快手私人pid").ToList(); + return list; + } + + /// + /// 拼多多推广位自动绑定推广位 + /// + /// + /// 刷新 + /// + public static List FindPinduoduoAutoBindPid(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_pinduoduo_auto_bind_adzone_info"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.多多进宝 && f.custom_type == Resources.PddSoftwareType).Select(f => f.adzone_pid).ToList(); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 快手推广位自动绑定推广位 + /// + /// + /// 刷新 + /// + public static List FindKuaishouAutoBindPid(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_kuaishou_auto_bind_adzone_info"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.快手联盟 && f.custom_type == Resources.KsSoftwareType).Select(f => f.adzone_pid).ToList(); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 抖音推广位自动绑定推广位 + /// + /// + /// 刷新 + /// + public static List FindDouyinAutoBindPid(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_douyin_auto_bind_adzone_info"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.抖音联盟 && f.custom_type == Resources.PddSoftwareType).Select(f => f.adzone_pid).ToList(); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 唯品会推广位自动绑定推广位 + /// + /// + /// 刷新 + /// + public static List FindWeipinhuiAutoBindPid(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_weipinhui_auto_bind_adzone_info"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == Resources.WphSoftwareType).Select(f => f.adzone_pid).ToList(); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 唯品会私人推广位 + /// + /// + /// 私人pid + /// + public static List FindWeipinhuiPrivatePid(this SqlSugarClient session, string adzone_id) + { + var list = session.FindAdzoneInfos().Where(f => f.adzone_pid == adzone_id && f.alliance_id == (int)CpsType.唯品联盟 && f.custom_type == "用户私人pid" && f.extend == "唯品会私人pid").ToList(); + return list; + } + + /// + /// 获取通知Robots + /// + /// + /// 刷新 + /// + public static List FindNoticeapiRobots(this SqlSugarClient session, bool refresh = false) + { + string key = "FindNoticeapiRobots"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.Queryable().ToList(); + ApiClient.Cache.Set(key, list, 60 * 24); + } + return list; + } + + /// + /// 京东推广位自动绑定推广位 + /// + /// + /// 刷新 + /// + public static List FindJingdongAutoBindPid(this SqlSugarClient session, bool refresh = false) + { + string key = "fl_jingdong_auto_bind_adzone_info"; + var list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.FindAdzoneInfos().Where(f => f.alliance_id == (int)CpsType.京东联盟 && f.custom_type == Resources.JdSoftwareType).Select(f => f.adzone_pid).ToList(); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + private readonly static object loc_obj = new object(); + + /// + /// 获得会员数据 + /// + /// + /// 通用IM消息 + /// + public static fl_member_info FindMemberinfo(this SqlSugarClient session, ReciveIMEvent e) + { + + var m = session.FindSingle("select * from fl_member_info where robot_type = @robot_type and username = @username", new { username = e.Username, robot_type = e.ChatType }); + if (m == null) + { + m = new fl_member_info() { crt_time = DateTime.Now, usernick = e.NickName, realnick = e.RealNick, robot_name = e.RobotName, robot_type = e.ChatType, username = e.Username, upd_time = DateTime.Now, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + var groups = session.FindGroups(); + if (groups.Count == 0) throw new Exception("会员组未设置,请先设置会员组!"); + if (!string.IsNullOrEmpty(e.RealNick)) m.realnick = e.RealNick; + if (!string.IsNullOrEmpty(e.Wechatid)) m.wechatid = e.Wechatid; + m.group_id = groups[0].id; + session.Insertable(m).ExecuteReturnEntity(); + } + else + { + m.upd_time = DateTime.Now; + m.robot_name = e.RobotName; + if (string.IsNullOrWhiteSpace(m.usernick)) m.usernick = e.NickName; + if (!string.IsNullOrEmpty(e.RealNick)) m.realnick = e.RealNick; + if (!string.IsNullOrEmpty(e.Wechatid)) m.wechatid = e.Wechatid; + } + return m; + + //try + //{ + // lock (loc_obj) + // { + // Console.WriteLine(e.ChatType); + + // } + //} + //catch (Exception ex) + //{ } + //return null; + } + + /// + /// 通过用户账号查询用户对象 + /// + /// + /// 用户账号 + /// + public static fl_member_info FindMemberInfoByUsername(this SqlSugarClient session, string username) + { + try + { + return session.FindSingle("select * from fl_member_info where username = @username", new { username = username }); + } + catch (Exception ex) + { } + return null; + } + + /// + /// 通过用户id查询用户对象 + /// + /// + /// 用户id + /// + public static fl_member_info FindMemberInfoById(this SqlSugarClient session, long uid) + { + try + { + return session.FindSingle("select * from fl_member_info where id = @id", new { id = uid }); + } + catch (Exception ex) + { } + return null; + } + + /// + /// 获取机器人集合 + /// + /// + /// 刷新 + /// + public static List FindRobots(this SqlSugarClient session, bool refresh = false) + { + var key = $"find_robot_info_table"; + List list = null; + list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.Find("select * from fl_robot_info order by id desc"); + ApiClient.Cache.Set(key, list, 60 * 24); + } + return list; + } + + /// + /// 获取软件与插件的Config的配置 + /// + /// + /// 刷新 + /// + public static List FindDictionaryItems(this SqlSugarClient session, bool refresh = false) + { + var key = $"find_fl_dictionary_item_table"; + List list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.Find("select * from fl_dictionary_item"); + ApiClient.Cache.Set(key, list, 60 * 24); + } + return list; + } + + private static readonly object tljLock = new object(); + /// + /// 累加淘礼金创建次数 + /// + /// + /// cps账号 + public static void AddTljCreateNum(this SqlSugarClient session, string cpsname) + { + lock (tljLock) + { + var tljRecord = session.FindSingle("select * from fl_alimama_tlj_create_record where cpsname = @cpsname", new { cpsname = cpsname }); + if (tljRecord != null) + { + var date = DateTime.Now.ToString("yyyyMMdd"); + if (tljRecord.date == date) + tljRecord.number++; + else + { + tljRecord.number = 1; + tljRecord.date = date; + } + } + else + { + tljRecord = new fl_alimama_tlj_create_record() { cpsname = cpsname, date = DateTime.Now.ToString("yyyyMMdd"), number = 1 }; + } + + session.Saveable(tljRecord).ExecuteCommand(); + } + } + + /// + /// 检测淘宝账号是否符合创建淘礼金(淘礼金每天创建30个) + /// + /// + /// cps账号 + /// 返回true + public static bool FindTljCreateNum(this SqlSugarClient session, string cpsname) + { + lock (tljLock) + { + var tljRecord = session.FindSingle("select * from fl_alimama_tlj_create_record where cpsname = @cpsname", new { cpsname = cpsname }); + if (tljRecord != null) + { + var date = DateTime.Now.ToString("yyyyMMdd"); + return !(tljRecord.date == date && tljRecord.number >= 30); + } + return true; + } + } + + /// + /// 获取推广位集合 + /// + /// + /// 刷新 + /// + public static List FindAdzoneInfos(this SqlSugarClient session, bool refresh = false) + { + var key = $"find_fl_adzone_info_table"; + List list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + //list = session.Queryable().ToList(); + list = session.Find("select * from fl_adzone_info"); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 获取所有的淘宝淘礼金信息 + /// + /// + /// 刷新 + /// + public static List FindTljInfos(this SqlSugarClient session, bool refresh = false) + { + var key = $"find_fl_alimama_tlj_info_table"; + List list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.Find("select * from fl_alimama_tlj_info"); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 通过推广位id判断是否为淘礼金订单 + /// + /// + /// 推广位id + /// + public static bool CheckIsTljOrder(this SqlSugarClient session, string adzone_id) + { + var tljInfos = session.FindTljInfos(); + if (tljInfos.Count != 0) + { + tljInfos = tljInfos.Where(f => !string.IsNullOrWhiteSpace(f.adzone_pid)).ToList(); + if (tljInfos.Count != 0) + { + var _tlj = tljInfos.FirstOrDefault(f => f.adzone_pid.EndsWith("_" + adzone_id)); + return _tlj != null; + } + } + return false; + } + + /// + /// 15天内被拉黑过的用户不拉黑 + /// + /// + /// 用户对象 + /// 返回true不需要拉黑 + public static bool TemporaryBypassedBlack(this SqlSugarClient session, fl_member_info member) + { + var time = DateTime.Now - member.blackout_time; + + //15天内自动跳过 + if (time.TotalDays <= 15) + { + EventClient.OnEvent(null, $"由于{member.usernick}({member.username})用户,最近被管理员人为去除黑名单,15天内将不会自动拉黑!"); + return true; + } + return false; + } + + /// + /// 获取黑名单用户信息 + /// + /// + /// + /// + public static List FindBlacklistMemberInfos(this SqlSugarClient session, bool refresh = false) + { + var key = $"find_fl_blacklist_member_info_table"; + List list = ApiClient.Cache.Get>(key); + if (refresh || list == null) + { + list = session.Find("select * from fl_member_info where status = @status", new { status = MemberType.黑名单 }); + ApiClient.Cache.Set(key, list, 60); + } + return list; + } + + /// + /// 通过文件key,获取配置文件 + /// + /// + /// 配置文件的名称 + /// 刷新 + /// + public static fl_dictionary_item FindDictionaryItem(this SqlSugarClient session, string key, bool refresh = false) + { + var table = session.FindDictionaryItems(refresh); + return table.FirstOrDefault(f => f.dickey == key); + } + + /// + /// 获得机器人信息 + /// + /// + /// 机器人账号 + /// 机器人平台类型 + /// 刷新 + /// + public static fl_robot_info FindRobotInfo(this SqlSugarClient session, string robot_name, ChatType robot_type, bool refresh = false) + { + var robots = session.FindRobots(refresh); + var member = robots.FirstOrDefault(f => f.name.Trim() == robot_name.Trim() && f.type == robot_type); + return member; + } + + /// + /// 获取eid(关系)集合 + /// + /// + /// 刷新 + /// + public static List FindTbRelations(this SqlSugarClient session, bool refresh = false) + { + var key = $"find_tb_relation_table"; + var flTBRelationCache = ApiClient.Cache.Get>(key); + if (refresh || flTBRelationCache == null) + { + flTBRelationCache = session.Find("select * from fl_tb_relation"); + } + return flTBRelationCache; + } + + /// + /// 公共分出比例列表 + /// + /// + /// cps类型 + /// 刷新 + /// + public static List FindRatios(this SqlSugarClient session, CpsType type, bool refresh = false) + { + var key = $"fl_ratio_info_tables_" + type; + var fl_ratio_infos = ApiClient.Cache.Get>(key); + if (!refresh && fl_ratio_infos != null) return fl_ratio_infos; + fl_ratio_infos = session.Find("select * from fl_ratio_info where cps_type = @cps_type order by comm asc", new { cps_type = type }); + ApiClient.Cache.Set(key, fl_ratio_infos, 60); + return fl_ratio_infos; + } + + /// + /// 独立分出比例列表 + /// + /// + /// + /// + /// + public static List FindCustomRatios(this SqlSugarClient session, long cgid, bool refresh = false) + { + var key = $"fl_ratio_info_tables_" + cgid; + var fl_ratio_infos = ApiClient.Cache.Get>(key); + if (!refresh && fl_ratio_infos != null) return fl_ratio_infos; + fl_ratio_infos = session.Find("select * from fl_ratio_info_custom where cgid = @cgid order by comm asc", new { cgid = cgid }); + ApiClient.Cache.Set(key, fl_ratio_infos, 60); + return fl_ratio_infos; + } + + /// + /// 根据金额获得佣金比例 + /// + /// + /// cps类型 + /// 佣金 + /// + public static fl_ratio_info FindRatio(this SqlSugarClient session, CpsType type, double commission) + { + var ratios = session.FindRatios(type); + int index = -1; + for (int i = 0; i < ratios.Count; i++) + { + double cur = ratios[i].comm; + if (i == (ratios.Count - 1)) cur = double.MaxValue; + if (commission <= cur) + { + index = i; + break; + } + } + if (index == -1) return null; + return ratios[index]; + } + + /// + /// 根据金额获得独立佣金比例 + /// + /// + /// + /// + /// + public static fl_ratio_info_custom FindCustomRatio(this SqlSugarClient session, long cgid, double commission) + { + var ratios = session.FindCustomRatios(cgid); + int index = -1; + for (int i = 0; i < ratios.Count; i++) + { + double cur = ratios[i].comm; + if (i == (ratios.Count - 1)) cur = double.MaxValue; + if (commission <= cur) + { + index = i; + break; + } + } + if (index == -1) return null; + return ratios[index]; + } + + + /// + /// 扩展方法订单尾号集合缓存 + /// + /// + /// + /// + public static List FindAlimamaOrderLastnums(this SqlSugarClient session, bool refresh = false) + { + var key = "fl_alimama_order_lastnum_tables"; + var fl_alimama_order_lastnums = ApiClient.Cache.Get>(key); + if (refresh || fl_alimama_order_lastnums == null) + { + fl_alimama_order_lastnums = session.Find("select * from fl_alimama_order_lastnum"); + ApiClient.Cache.Set(key, fl_alimama_order_lastnums, 60); + } + return fl_alimama_order_lastnums; + } + + + /// + /// 获取会员组列表 + /// + /// + /// 刷新 + /// + public static List FindGroups(this SqlSugarClient session, bool refresh = false) + { + var key = "fl_member_group_tables"; + var fl_member_groups = ApiClient.Cache.Get>(key);//根据KEY、获得缓存 + if (refresh || fl_member_groups == null) + { + fl_member_groups = session.Find("select * from fl_member_group order by terms asc"); + for (int i = 0; i < fl_member_groups.Count; i++) + { + fl_member_groups[i].SetLevel(i + 1); + } + + ApiClient.Cache.Set(key, fl_member_groups, 60); + } + return fl_member_groups; + } + + /// + /// 获得会员组 + /// + /// + /// 根据组名称 + /// + public static fl_member_group FindGroup(this SqlSugarClient session, string group_name) + { + var groups = session.FindGroups(); + return groups.FirstOrDefault(f => f.name == group_name); + } + + /// + /// 获得会员组 + /// + /// 会员组id + public static fl_member_group FindGroup(this SqlSugarClient session, long id) + { + var groups = session.FindGroups(); + return groups.FirstOrDefault(f => f.id == id); + } + + /// + /// 获得用户组 + /// + /// + /// 根据会员表 + /// + public static fl_member_group FindGroup(this SqlSugarClient session, fl_member_info member) + { + var group = session.FindGroup(member.group_id); + if (group == null) group = session.FindGroup(member.sum_point, member.bind_order); + if (group != null && member.group_id != group.id) + { + member.group_id = group.id; + if (member.id != 0) + session.SaveOrUpdate(member); + } + return group; + } + + /// + /// 根据消费总积分获得会员组 + /// + /// + /// 消费总积分 + /// 绑定订单数 + /// + public static fl_member_group FindGroup(this SqlSugarClient session, double sum_point, long bind_order) + { + var groups = session.FindGroups().OrderByDescending(f => f.terms).ThenByDescending(f => f.terms_ordersum).ToList(); + var index = -1; + for (int i = 0; i < groups.Count; i++) + { + if (sum_point >= groups[i].terms && bind_order >= groups[i].terms_ordersum) + { + index = i; + break; + } + } + if (index == -1) return null; + return groups[index]; + } + + /// + /// 获得推广位组信息 + /// + /// + /// cps类型 + /// 刷新 + /// + public static List FindAdzoneGroups(this SqlSugarClient session, CpsType type, bool refresh = false) + { + var key = $"fl_adzone_group_tables_{type}"; + var list = ApiClient.Cache.Get>(key); + if (!refresh && list != null) return list; + list = session.Find("select * from fl_adzone_group where cps_type = @cps_type order by id Desc", new { cps_type = type }); + if (list == null) list = new List(); + ApiClient.Cache.Set(key, list, 60); + return list; + } + + /// + /// 获得延迟冻结信息 + /// + /// + /// cps类型 + /// 刷新 + /// + public static List FindSleeps(this SqlSugarClient session, CpsType type, bool refresh = false) + { + var key = $"fl_order_sleep_tables_{type}"; + var list = ApiClient.Cache.Get>(key); + if (!refresh && list != null) return list; + list = session.Find("select * from fl_order_sleep where cps_type = @cps_type Order By money asc", new { cps_type = type }); + if (list == null) list = new List(); + ApiClient.Cache.Set(key, list, 60); + return list; + } + + /// + /// 获得延迟冻结时间 + /// + /// + /// cps类型 + /// 佣金 + /// + public static fl_order_sleep FindSleep(this SqlSugarClient session, CpsType type, double commission) + { + var list = session.FindSleeps(type); + if (list != null && list.Count > 0) + { + for (int i = 0; i < list.Count; i++) + { + if (commission <= list[i].money) return list[i]; + } + return list[list.Count - 1]; + } + return null; + } + + /// + /// 获得用户自定义变量信息 + /// + /// + /// 刷新 + /// + public static List FindUserVariates(this SqlSugarClient session, bool refresh = false) + { + var key = $"fl_uservariate_info_tables"; + var list = ApiClient.Cache.Get>(key); + if (!refresh && list != null) return list; + list = session.Find("select * from fl_uservariate_info"); + if (list == null) list = new List(); + ApiClient.Cache.Set(key, list, 60); + return list; + } + + /// + /// 获取查询阿里比价佣金的扣除后的计算佣金 + /// + /// 阿里订单 + /// + public static double GetTbComparisonFeeRate(this SqlSugarClient session, fl_order_alimama order) + { + var commission = (order.commission == 0 ? order.pub_share_pre_fee : order.commission); + + if (order.alimama_rate != 0) + { + var tbConfig = OrderHelper.RefreshTbConfig(); + if (tbConfig != null && tbConfig.ContainsKey("QueryComparisonSwitch") && tbConfig.ContainsKey("ComparisonFeeRate")) + { + var QueryComparisonSwitch = tbConfig["QueryComparisonSwitch"].ToString(); + var ComparisonFeeRate = int.Parse(tbConfig["ComparisonFeeRate"].ToString()); + if (QueryComparisonSwitch == "1" && ComparisonFeeRate > 0)//查询使用实时佣金 = 0,查询使用比价佣金 = 1,查询使用正常佣金 = 2 + commission = Math.Round(commission * (1d - ((double)ComparisonFeeRate / 100d)), 2); + } + } + return commission; + } + + /// + /// 获取查询拼多多比价佣金的扣除后的计算佣金 + /// + /// 正常佣金 + /// + public static double GetPddComparisonFeeRate(this SqlSugarClient session, double commission) + { + //if (order.price_compare_status != PinduoduoBiJiaType.非比价) + { + var pddConfig = OrderHelper.RefreshPddConfig(); + if (pddConfig != null && pddConfig.ContainsKey("ComparisonFeeRate")) + { + var ComparisonFeeRate = int.Parse(pddConfig["ComparisonFeeRate"].ToString()); + if (ComparisonFeeRate > 0)//查询使用实时佣金 = 0,查询使用比价佣金 = 1,查询使用正常佣金 = 2 + commission = Math.Round(commission * (1d - ((double)ComparisonFeeRate / 100d)), 2); + } + } + return commission; + } + + /// + /// 获得商品积分 + /// + /// + /// 用户对象 + /// 佣金 + /// 购买数量 + /// cps类型 + /// + public static ItemPoint FindItemPoint(this SqlSugarClient session, fl_member_info member, double _commission, int buy_count, CpsType type) + { + if (_commission == 0) return new ItemPoint(); + var commission = (decimal)_commission / (decimal)buy_count; + + member = session.UpdateMemberGroup(member); + + //得到佣金 + decimal _fl1 = 0; + #region 比例 + if (member == null || member.private_ratio == 0) + { + var flag = true; + #region 是否使用独立分出比例分组 + if (member != null) + { + fl_ratio_info_custom customR = null; + var ratioCustomId = -1l; + var g = session.FindGroup(member); + switch (type) + { + case CpsType.阿里妈妈: + ratioCustomId = g.ratio_custom_tb; + break; + case CpsType.多多进宝: + ratioCustomId = g.ratio_custom_pdd; + break; + case CpsType.京东联盟: + ratioCustomId = g.ratio_custom_jd; + break; + case CpsType.唯品联盟: + ratioCustomId = g.ratio_custom_wph; + break; + case CpsType.抖音联盟: + ratioCustomId = g.ratio_custom_dy; + break; + case CpsType.苏宁易购: + ratioCustomId = g.ratio_custom_sn; + break; + case CpsType.快手联盟: + ratioCustomId = g.ratio_custom_ks; + break; + default: + break; + } + + if (ratioCustomId != -1) + { + var customRs = session.FindCustomRatios(ratioCustomId); + if (customRs != null && customRs.Count != 0) + { + customR = session.FindCustomRatio(ratioCustomId, (double)commission); + if (customR == null) throw new Exception($"独立佣金:{commission},没有满足该佣金的比例!"); + _fl1 = (customR.subsidy_type == SubsidyType.固定积分 ? (decimal)customR.subsidy_num : ((decimal)customR.subsidy_num / 100m) * commission) * (decimal)buy_count; + + LogHelper.GetSingleObj().Debug("", $"使用独立佣金计算:平台:{type.ToString()},独立分组:{ratioCustomId},补贴类型:{customR.subsidy_type},返点数:{customR.subsidy_num},单品佣金:{commission},品数:{buy_count}"); + flag = false; + } + } + } + #endregion + + if (flag)//公共分出比例 + { + var ratio = session.FindRatio(type, (double)commission); + if (ratio == null) throw new Exception($"佣金:{commission},没有满足该佣金的比例!"); + _fl1 = (ratio.subsidy_type == SubsidyType.固定积分 ? (decimal)ratio.subsidy_num : ((decimal)ratio.subsidy_num / 100m) * commission) * (decimal)buy_count; + LogHelper.GetSingleObj().Debug("", $"使用公共佣金计算:平台:{type.ToString()},佣金条件:{ratio.id},补贴类型:{ratio.subsidy_type},返点数:{ratio.subsidy_num},单品佣金:{commission},品数:{buy_count}"); + } + } + else//私人比例 + { + _fl1 = ((decimal)member.private_ratio / 100m) * commission * (decimal)buy_count; + } + + #endregion + + fl_member_group group = null; + if (member != null) + { + group = session.FindGroup(member.group_id); + if (group == null)//(这里锁定的用户对应的会员组不存在了,那么给用户设置一个默认值) + { + group = session.FindGroups().FirstOrDefault(); + if (group != null) + { + member.group_id = group.id; + session.SaveOrUpdate(member); + } + } + } + else + group = session.FindGroups().FirstOrDefault(); + if (group == null && member != null) throw new Exception($"积分:{member.sum_point},没有满足该积分的会员组!"); + + //补贴佣金 + decimal _fl2 = (group.subsidy == 0 ? 0 : (group.subsidy_type == SubsidyType.固定积分 ? (decimal)group.subsidy : (decimal)group.subsidy / 100m * (decimal)_commission)); + + ItemPoint point = new ItemPoint(); + + //分出总额 + decimal rst = Math.Round(_fl1 + _fl2, 2); + if (ApiClient.Setting.SystemConfig.AwardDepot == AwardDepotType.不扣分出佣金) + { + point.AwardOne = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardOne / 100m) * (decimal)rst), 2); + point.AwardTwo = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardTwo / 100m) * (decimal)rst), 2); + point.AwardThree = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardThree / 100m) * (decimal)rst), 2); + point.AwardCreate = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardCreator / 100m) * (decimal)rst), 2); + point.UserPoint = (double)rst; + } + else + { + point.AwardOne = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardOne / 100m) * (decimal)rst), 2); + point.AwardTwo = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardTwo / 100m) * (decimal)rst), 2); + point.AwardThree = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardThree / 100m) * (decimal)rst), 2); + point.AwardCreate = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardCreator / 100m) * (decimal)rst), 2); + point.UserPoint = Math.Round((double)((decimal)rst - (decimal)point.AwardOne - (decimal)point.AwardTwo - (decimal)point.AwardThree - (decimal)point.AwardCreate), 2); + } + point.UserPoint = point.UserPoint == 0 ? 0.01 : point.UserPoint; + return point; + } + + /// + /// 获得商品积分 + /// + /// + /// 用户对象 + /// 佣金 + /// 购买数量 + /// cps + /// 计算公式信息 + /// + public static ItemPoint FindItemPoint(this SqlSugarClient session, fl_member_info member, double _commission, int buy_count, CpsType type, out Compute compute) + { + compute = null; + if (_commission == 0) return new ItemPoint(); + var commission = (decimal)_commission / (decimal)buy_count; + + compute = new Compute(); + + member = session.UpdateMemberGroup(member); + + //得到佣金 + decimal _fl1 = 0; + #region 比例 + if (member == null || member.private_ratio == 0) + { + var flag = true; + #region 是否使用独立分出比例分组 + if (member != null) + { + fl_ratio_info_custom customR = null; + var ratioCustomId = -1l; + var g = session.FindGroup(member); + switch (type) + { + case CpsType.阿里妈妈: + ratioCustomId = g.ratio_custom_tb; + break; + case CpsType.多多进宝: + ratioCustomId = g.ratio_custom_pdd; + break; + case CpsType.京东联盟: + ratioCustomId = g.ratio_custom_jd; + break; + case CpsType.唯品联盟: + ratioCustomId = g.ratio_custom_wph; + break; + case CpsType.抖音联盟: + ratioCustomId = g.ratio_custom_dy; + break; + case CpsType.苏宁易购: + ratioCustomId = g.ratio_custom_sn; + break; + case CpsType.快手联盟: + ratioCustomId = g.ratio_custom_ks; + break; + default: + break; + } + + if (ratioCustomId != -1) + { + var customRs = session.FindCustomRatios(ratioCustomId); + if (customRs != null && customRs.Count != 0) + { + customR = session.FindCustomRatio(ratioCustomId, (double)commission); + if (customR == null) throw new Exception($"独立佣金:{commission},没有满足该佣金的比例!"); + _fl1 = (customR.subsidy_type == SubsidyType.固定积分 ? (decimal)customR.subsidy_num : ((decimal)customR.subsidy_num / 100m) * commission) * (decimal)buy_count; + + compute.SubsidyType = customR.subsidy_type; + compute.IsPrivateRatio = false; + compute.Subsidy = customR.subsidy_num; + + LogHelper.GetSingleObj().Debug("", $"使用独立佣金计算:平台:{type.ToString()},独立分组:{ratioCustomId},补贴类型:{customR.subsidy_type},返点数:{customR.subsidy_num},单品佣金:{commission},品数:{buy_count}"); + flag = false; + } + } + } + #endregion + + if (flag)//公共分出比例 + { + var ratio = session.FindRatio(type, (double)commission); + if (ratio == null) throw new Exception($"佣金:{commission},没有满足该佣金的比例!"); + _fl1 = (ratio.subsidy_type == SubsidyType.固定积分 ? (decimal)ratio.subsidy_num : ((decimal)ratio.subsidy_num / 100m) * commission) * (decimal)buy_count; + + compute.SubsidyType = ratio.subsidy_type; + compute.IsPrivateRatio = false; + compute.Subsidy = ratio.subsidy_num; + + LogHelper.GetSingleObj().Debug("", $"使用公共佣金计算:平台:{type.ToString()},佣金条件:{ratio.id},补贴类型:{ratio.subsidy_type},返点数:{ratio.subsidy_num},单品佣金:{commission},品数:{buy_count}"); + } + } + else//私人比例 + { + _fl1 = ((decimal)member.private_ratio / 100m) * commission * (decimal)buy_count; + + compute.IsPrivateRatio = true; + compute.Subsidy = member.private_ratio; + } + + #endregion + + fl_member_group group = null; + if (member != null) + { + group = session.FindGroup(member.group_id); + if (group == null)//(这里锁定的用户对应的会员组不存在了,那么给用户设置一个默认值) + { + group = session.FindGroups().FirstOrDefault(); + if (group != null) + { + member.group_id = group.id; + session.SaveOrUpdate(member); + } + } + } + else + group = session.FindGroups().FirstOrDefault(); + if (group == null && member != null) throw new Exception($"积分:{member.sum_point},没有满足该积分的会员组!"); + + //补贴佣金 + decimal _fl2 = (group.subsidy == 0 ? 0 : (group.subsidy_type == SubsidyType.固定积分 ? (decimal)group.subsidy : (decimal)group.subsidy / 100m * (decimal)_commission)); + + compute.GroupSubsidyType = group.subsidy_type; + compute.GroupSubsidy = group.subsidy; + + ItemPoint point = new ItemPoint(); + + //分出总额 + decimal rst = Math.Round(_fl1 + _fl2, 2); + if (ApiClient.Setting.SystemConfig.AwardDepot == AwardDepotType.不扣分出佣金) + { + point.AwardOne = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardOne / 100m) * (decimal)rst), 2); + point.AwardTwo = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardTwo / 100m) * (decimal)rst), 2); + point.AwardThree = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardThree / 100m) * (decimal)rst), 2); + point.AwardCreate = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardCreator / 100m) * (decimal)rst), 2); + point.UserPoint = (double)rst; + } + else + { + point.AwardOne = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardOne / 100m) * (decimal)rst), 2); + point.AwardTwo = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardTwo / 100m) * (decimal)rst), 2); + point.AwardThree = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardThree / 100m) * (decimal)rst), 2); + point.AwardCreate = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardCreator / 100m) * (decimal)rst), 2); + point.UserPoint = Math.Round((double)((decimal)rst - (decimal)point.AwardOne - (decimal)point.AwardTwo - (decimal)point.AwardThree - (decimal)point.AwardCreate), 2); + } + + compute.AwardDepot = ApiClient.Setting.SystemConfig.AwardDepot; + compute.AwardOne = ApiClient.Setting.SystemConfig.AwardOne; + compute.AwardTwo = ApiClient.Setting.SystemConfig.AwardTwo; + compute.AwardThree = ApiClient.Setting.SystemConfig.AwardThree; + compute.AwardCreator = ApiClient.Setting.SystemConfig.AwardCreator; + + point.UserPoint = point.UserPoint == 0 ? 0.01 : point.UserPoint; + return point; + } + + /// + /// 获得商品积分 + /// + /// + /// 计算公式信息 + /// 佣金 + /// 购买数量 + /// cps + /// + public static ItemPoint FindItemPoint(this SqlSugarClient session, CpsType type, Compute compute, double _commission, int buy_count) + { + if (_commission == 0) return new ItemPoint(); + var commission = (decimal)_commission / (decimal)buy_count; + + //得到佣金 + decimal _fl1 = 0; + #region 比例 + if (!compute.IsPrivateRatio) + { + _fl1 = (compute.SubsidyType == SubsidyType.固定积分 ? (decimal)compute.Subsidy : ((decimal)compute.Subsidy / 100m) * commission) * (decimal)buy_count; + + LogHelper.GetSingleObj().Debug("", $"使用历史佣金计算:平台:{type.ToString()},补贴类型:{compute.SubsidyType},返点数:{compute.Subsidy},单品佣金:{commission},品数:{buy_count}"); + } + else + { + _fl1 = ((decimal)compute.Subsidy / 100m) * commission * (decimal)buy_count; + } + #endregion + + //补贴佣金 + decimal _fl2 = (compute.GroupSubsidy == 0 ? 0 : (compute.GroupSubsidyType == SubsidyType.固定积分 ? (decimal)compute.GroupSubsidy : (decimal)compute.GroupSubsidy / 100m * (decimal)_commission)); + + ItemPoint point = new ItemPoint(); + + //分出总额 + decimal rst = Math.Round(_fl1 + _fl2, 2); + if (compute.AwardDepot == AwardDepotType.不扣分出佣金) + { + point.AwardOne = Math.Round((double)(((decimal)compute.AwardOne / 100m) * (decimal)rst), 2); + point.AwardTwo = Math.Round((double)(((decimal)compute.AwardTwo / 100m) * (decimal)rst), 2); + point.AwardThree = Math.Round((double)(((decimal)compute.AwardThree / 100m) * (decimal)rst), 2); + point.AwardCreate = Math.Round((double)(((decimal)compute.AwardCreator / 100m) * (decimal)rst), 2); + point.UserPoint = (double)rst; + } + else + { + point.AwardOne = Math.Round((double)(((decimal)compute.AwardOne / 100m) * (decimal)rst), 2); + point.AwardTwo = Math.Round((double)(((decimal)compute.AwardTwo / 100m) * (decimal)rst), 2); + point.AwardThree = Math.Round((double)(((decimal)compute.AwardThree / 100m) * (decimal)rst), 2); + point.AwardCreate = Math.Round((double)(((decimal)compute.AwardCreator / 100m) * (decimal)rst), 2); + point.UserPoint = Math.Round((double)((decimal)rst - (decimal)point.AwardOne - (decimal)point.AwardTwo - (decimal)point.AwardThree - (decimal)point.AwardCreate), 2); + } + + point.UserPoint = point.UserPoint == 0 ? 0.01 : point.UserPoint; + return point; + } + + #region 老版本的积分计算 + //public static ItemPoint FindItemPoint(this SqlSugarClient session, fl_member_info member, double _commission, int buy_count, CpsType type) + //{ + // if (_commission == 0) return new ItemPoint(); + // var commission = (decimal)_commission / (decimal)buy_count; + + // member = session.UpdateMemberGroup(member); + + // //得到佣金 + // decimal _fl1 = 0; + // #region 比例 + // if (member == null || member.private_ratio == 0) + // { + // var ratio = session.FindRatio(type, (double)commission); + // if (ratio == null) throw new Exception($"佣金:{commission},没有满足该佣金的比例!"); + // _fl1 = (ratio.subsidy_type == SubsidyType.固定积分 ? (decimal)ratio.subsidy_num : ((decimal)ratio.subsidy_num / 100m) * commission) * (decimal)buy_count; + // } + // else//私人比例 + // { + // _fl1 = ((decimal)member.private_ratio / 100m) * commission * (decimal)buy_count; + // } + + // #endregion + + // fl_member_group group = null; + // if (member != null) + // { + // group = session.FindGroup(member.group_id); + // if (group == null)//(这里锁定的用户对应的会员组不存在了,那么给用户设置一个默认值) + // { + // group = session.FindGroups().FirstOrDefault(); + // if (group != null) + // { + // member.group_id = group.id; + // session.SaveOrUpdate(member); + // } + // } + // } + // else + // group = session.FindGroups().FirstOrDefault(); + // if (group == null && member != null) throw new Exception($"积分:{member.sum_point},没有满足该积分的会员组!"); + + // //补贴佣金 + // //decimal _fl2 = (group.subsidy <= 0 ? 0 : (group.subsidy_type == SubsidyType.固定积分 ? (decimal)group.subsidy : (decimal)group.subsidy / 100m * commission)) * (decimal)buy_count; + // decimal _fl2 = (group.subsidy == 0 ? 0 : (group.subsidy_type == SubsidyType.固定积分 ? (decimal)group.subsidy : (decimal)group.subsidy / 100m * (decimal)_commission)); + + // ItemPoint point = new ItemPoint(); + + // //分出总额 + // decimal rst = Math.Round(_fl1 + _fl2, 2); + // if (ApiClient.Setting.SystemConfig.AwardDepot == AwardDepotType.不扣分出佣金) + // { + // point.AwardOne = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardOne / 100m) * (decimal)rst), 2); + // point.AwardTwo = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardTwo / 100m) * (decimal)rst), 2); + // point.AwardThree = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardThree / 100m) * (decimal)rst), 2); + // point.AwardCreate = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardCreator / 100m) * (decimal)rst), 2); + // point.UserPoint = (double)rst; + // } + // else + // { + // point.AwardOne = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardOne / 100m) * (decimal)rst), 2); + // point.AwardTwo = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardTwo / 100m) * (decimal)rst), 2); + // point.AwardThree = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardThree / 100m) * (decimal)rst), 2); + // point.AwardCreate = Math.Round((double)(((decimal)ApiClient.Setting.SystemConfig.AwardCreator / 100m) * (decimal)rst), 2); + // point.UserPoint = Math.Round((double)((decimal)rst - (decimal)point.AwardOne - (decimal)point.AwardTwo - (decimal)point.AwardThree - (decimal)point.AwardCreate), 2); + // } + // point.UserPoint = point.UserPoint == 0 ? 0.01 : point.UserPoint; + // return point; + //} + #endregion + + /// + /// 读取绑定记录 + /// + /// + /// 订单编号 + /// 刷新 + /// + public static fl_bind_cache FindBindCache(this SqlSugarClient session, string orderid, bool refresh = false) + { + var key = $"fl_bind_cache_{orderid}"; + var bind = ApiClient.Cache.Get(key); + if (!refresh && bind != null) return bind; + bind = session.FindSingle("orderid = @orderid", new { orderid = orderid }); + if (bind != null) ApiClient.Cache.Set(key, bind, 30); + return bind; + } + + /// + /// 获得创建者信息 + /// + /// + /// 群号 + /// 类型 + /// 刷新 + /// + public static fl_group_person FindCreateInfo(this SqlSugarClient session, string groupid, ChatType type, bool refresh = false) + { + try + { + var key = $"find_fl_group_person_{groupid}_{type}"; + var item = ApiClient.Cache.Get(key); + if (!refresh && item != null) return item; + item = session.FindSingle("select * from fl_group_person where groupid = @groupid", new { groupid = groupid }); + if (item != null) ApiClient.Cache.Set(key, item, 10); + return item; + } + catch { } + return null; + } + + /// + /// 更新用户所在分组 + /// + /// + /// 用户对象 + /// + public static fl_member_info UpdateMemberGroup(this SqlSugarClient session, fl_member_info member) + { + try + { + if (member == null) return null; + + #region 无视积分影响分组升级 + if (member.ignore_group_update == SwitchType.关闭) + { + //判断是否需要升级会员组 + var _oldGroup = session.FindGroup(member); + var _newGroup = session.FindGroup(member.sum_point, member.bind_order); + if (_oldGroup != null && _newGroup != null && _oldGroup.id != _newGroup.id) + { + member.group_id = _newGroup.id; + } + } + session.SaveOrUpdate(member); + #endregion + } + catch (Exception) + { } + return member; + } + + /// + /// 删除cps对象 + /// + /// + /// cps对象 + public static void Delete(this SqlSugarClient session, fl_cps_member obj) + { + session.Deleteable(obj).ExecuteCommand(); + } + + /// + /// 删除会员分组 + /// + /// + /// 会员分组 + public static void Delete(this SqlSugarClient session, fl_member_group obj) + { + session.Deleteable(obj).ExecuteCommand(); + } + + /// + /// 添加/修改微信支付信息 + /// + /// + /// 微信支付信息对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_weixin_password model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 苏宁推广位记录表 + /// + /// + /// + public static void SaveOrUpdate(this SqlSugarClient session, fl_suning_tgw model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + public static void SaveOrUpdate(this SqlSugarClient session, fl_ratio_info_custom model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 独立分出比例分组 + /// + /// + /// + public static void SaveOrUpdate(this SqlSugarClient session, fl_ratio_info_custom_group model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + public static fl_dy_ck FindDyCk(this SqlSugarClient session, string cpsname, string chname) + { + return session.FindSingle("select * from fl_dy_ck where cpsname = @cpsname and chname = @chname", new { cpsname = cpsname, chname = chname }); + } + + public static void SaveOrUpdate(this SqlSugarClient session, fl_dy_ck model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改群管理 + /// + /// + /// 群管理对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_group_person model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改订单维权 + /// + /// + /// + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_refund_alimama model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改推广位信息 + /// + /// + /// 推广位对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_adzone_info model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改订单冻结规则 + /// + /// + /// 订单冻结规则对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_sleep model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改会员分组 + /// + /// + /// 会员分组对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_member_group model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改机器人对象 + /// + /// + /// 机器人对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_robot_info model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改用户对象 + /// + /// + /// 用户对象 + /// false:只修改关键信息 + public static void SaveOrUpdate(this SqlSugarClient session, fl_member_info model, bool all = false) + { + if (model.id == 0) + model.id = session.Insertable(model).ExecuteReturnIdentity(); + else + { + if (all) + session.Updateable(model).With(SqlWith.UpdLock).ExecuteCommand(); + else + { + //session.Update(model). + session.Updateable(model) + .UpdateColumns(f => + new + { + f.usernick, + f.robot_type, + f.robot_name, + f.status, + f.remark, + f.finish_order, + f.inviter_id, + f.group_id, + f.ignore_group_update, + f.alipay_name, + f.alipay_num, + f.identity_name, + f.identity_card, + f.upd_time, + f.blackout_time, + f.chat_count, + f.ban_exchange_time, + f.private_ratio, + f.realnick, + f.bind_order, + f.exchange_type, + f.wechatid, + f.is_cloud_black, + f.check_cloud_black_time, + f.headurl + } + ).ExecuteCommand(); + //session.Updateable(new + //{ + // usernick = model.usernick, + // robot_type = model.robot_type, + // robot_name = model.robot_name, + // status = model.status, + // remark = model.remark, + // finish_order = model.finish_order, + // inviter_id = model.inviter_id, + // group_id = model.group_id, + // ignore_group_update = model.ignore_group_update, + // alipay_name = model.alipay_name, + // alipay_num = model.alipay_num, + // identity_name = model.identity_name, + // identity_card = model.identity_card, + // upd_time = DateTime.Now, + // blackout_time = model.blackout_time, + // chat_count = model.chat_count, + // ban_exchange_time = model.ban_exchange_time, + // private_ratio = model.private_ratio, + // realnick = model.realnick, + // bind_order = model.bind_order, + // wechatid = model.wechatid, + // is_cloud_black = model.is_cloud_black, + // check_cloud_black_time = model.check_cloud_black_time + //}).Where(f => f.id == model.id).ExecuteCommand(); + } + } + } + + /// + /// 添加/修改cps对象 + /// + /// + /// + public static void SaveOrUpdate(this SqlSugarClient session, fl_cps_member model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改拼多多订单 + /// + /// + /// 拼多多订单对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_pinduoduo model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改唯品会订单 + /// + /// + /// 唯品会订单对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_weipinhui model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改快手订单 + /// + /// + /// 快手订单对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_kuaishou model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改京东订单 + /// + /// + /// 京东订单对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_jingdong model) + { + //if (model.id == 0) + // model.id = session.Insertable(model).ExecuteReturnBigIdentity(); + //else + // session.Updateable(model).ExecuteCommand(); + model = session.Saveable(model).ExecuteReturnEntity(); + } + + public static void SaveOrUpdate(this SqlSugarClient session, fl_query_ratio_hist model) + { + try + { + if (model == null) return; + var modelTmp = session.GetQueryRatioHist(model.cpstype, model.db_orderid); + if (modelTmp != null) + model.id = modelTmp.id; + model = session.Saveable(model).ExecuteReturnEntity(); + } + catch (Exception) + { } + } + + private static fl_query_ratio_hist GetQueryRatioHist(this SqlSugarClient session, CpsType cpsTyp, long id) + { + return session.FindSingle("select * from fl_query_ratio_hist where cpstype = @cpstype and db_orderid = @db_orderid", new { cpstype = cpsTyp, db_orderid = id }); + } + + /// + /// 添加/修改抖音订单 + /// + /// + /// 抖音订单对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_douyin model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改苏宁订单 + /// + /// + /// 抖音订单对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_suning model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改阿里订单 + /// + /// + /// 阿里订单对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_order_alimama model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改分出比例 + /// + /// + /// 分出比例对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_ratio_info model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 添加/修改配置 + /// + /// + /// 配置对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_dictionary_item model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + + /// + /// 记录用户基础记录(商品查询次数) + /// + /// + /// 用户id + public static void UpdateRecord(this SqlSugarClient session, long uid) + { + var key = "fl_statistics_record_key"; + var list = ApiClient.Cache.Get>(key); + if (list == null) + { + list = session.Find("select * from fl_statistics_record"); + if (list == null) list = new List(); + ApiClient.Cache.Set(key, list, 60); + } + if (list.FirstOrDefault(f => f.uid == uid) == null) + { + var record = new fl_statistics_record() { uid = uid, querynum = 1, ex3 = HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Insertable(record).ExecuteCommand(); + list.Add(record); + } + else + session.ExcuteSQL("update fl_statistics_record set querynum = querynum + 1 where uid = @uid", new { uid = uid }); + } + + /// + /// 查询用户基础记录 + /// + /// + /// 用户id + /// + public static fl_statistics_record FindStatisticsRecord(this SqlSugarClient session, long uid) + { + return session.FindSingle("select * from fl_statistics_record where uid = @uid", new { uid = uid }); + } + + /// + /// 查询历史查询比例 + /// + /// + /// 平台类型 + /// 订单id + /// + public static Compute FindQueryRatioHist(this SqlSugarClient session, CpsType cpstype, long db_orderid) + { + if (db_orderid == 0) + return null; + Compute compute = null; + #region 查询历史查询比例 + var queryRatioHist = session.FindSingle("select * from fl_query_ratio_hist where cpstype = @cpstype and db_orderid = @db_orderid", new { cpstype = cpstype, db_orderid = db_orderid }); + if (queryRatioHist != null && !string.IsNullOrWhiteSpace(queryRatioHist.compute_config)) + { + compute = JsonConvert.DeserializeObject(queryRatioHist.compute_config); + } + #endregion + return compute; + } + + /// + /// 通过阿里商品id获取已经创建的淘礼金 + /// + /// + /// 商品id + public static fl_alimama_tlj_get_record FindTljByItemid(this SqlSugarClient session, string itemid) + { + var tlj = session.FindSingle("select * from fl_alimama_tlj_get_record where itemid = @itemid", new { itemid = itemid }); + if (tlj != null) + { + if (tlj.expiredate <= DateTime.Now || tlj.number <= 0) + { + session.Deleteable(tlj).ExecuteCommand(); + return null; + } + return tlj; + } + return null; + } + + /// + /// 添加/修改阿里淘礼金记录 + /// + /// + /// 阿里淘礼金记录对象 + public static void SaveOrUpdate(this SqlSugarClient session, fl_alimama_tlj_get_record model) + { + model = session.Saveable(model).ExecuteReturnEntity(); + } + } + +} + +/// +/// 积分分配类 +/// +public class ItemPoint +{ + /// + /// 类型 + /// + public CpsType Type { get; set; } + + /// + /// 总佣金 + /// + public double Commission { get; set; } + + /// + /// 总积分 + /// + public double SumPoint + { + get { return (double)((decimal)UserPoint + (decimal)AwardOne + (decimal)AwardTwo + (decimal)AwardThree + (decimal)AwardCreate); } + } + + /// + /// 用户积分 + /// + public double UserPoint { get; set; } + + /// + /// 一级提成 + /// + public double AwardOne { get; set; } + + /// + /// 二级提成 + /// + public double AwardTwo { get; set; } + + /// + /// 三级提成 + /// + public double AwardThree { get; set; } + + /// + /// 创建者提成 + /// + public double AwardCreate { get; set; } + +} diff --git a/类库/Api.Framework/Model/base_model.cs b/类库/Api.Framework/Model/base_model.cs new file mode 100644 index 0000000..b9f5da0 --- /dev/null +++ b/类库/Api.Framework/Model/base_model.cs @@ -0,0 +1,99 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 基础订单类 + /// + public class base_model_order : base_model + { + /// + /// 构造方法 + /// + public base_model_order() + { + this.db_point = ""; + this.msg_groupid = ""; + this.db_cpsname = string.Empty; + this.db_cpsnick = string.Empty; + this.db_robotname = string.Empty; + } + + /// + /// 订单是否完成 + /// + /// + public bool IsFinish() + { + //if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status==SystemOrderStatus.订1单退款 || db_status == SystemOrderStatus.订单维权中) + if (db_status == SystemOrderStatus.订单失效 || db_status == SystemOrderStatus.订单结算 || db_status == SystemOrderStatus.订单退款 || db_status == SystemOrderStatus.全额退款 || db_status == SystemOrderStatus.部分退款 || db_status == SystemOrderStatus.订单维权中) + { + return true; + } + return false; + } + + /// + /// 订单状态修改时间戳 + /// + public string db_status_time { get; set; } + + /// + /// 完结状态:-2、未支付、-1、已退款 0、订单付款 1、冻结中 99、已结算 + /// + public SystemOrderStatus db_status { get; set; } + + /// + /// 用户标识 + /// + public long db_userid { get; set; } + + /// + /// 机器人ID + /// + public string db_robotname { get; set; } + + /// + /// 机器人类型 + /// + public ChatType db_robottype { get; set; } + + /// + /// 积分信息 + /// + public string db_point { get; set; } + + /// + /// 用户积分 - 临时记录 + /// + public double db_userpoint { get; set; } + + /// + /// 订单来源群 + /// + public string msg_groupid { get; set; } + + /// + /// 完结时间 + /// + public DateTime db_endtime { get; set; } + + /// + /// 联盟账号 + /// + public string db_cpsname { get; set; } + + /// + /// 联盟昵称 + /// + public string db_cpsnick { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_adzone_group.cs b/类库/Api.Framework/Model/fl_adzone_group.cs new file mode 100644 index 0000000..a4d1f60 --- /dev/null +++ b/类库/Api.Framework/Model/fl_adzone_group.cs @@ -0,0 +1,41 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 推广位组 + /// + public class fl_adzone_group : base_model + { + /// + /// 组名称 + /// + public string name { get; set; } + + /// + /// 推广位集合 + /// + [SugarColumn(ColumnDataType = "TEXT")]//设置字段为长文本 + public string adzones { get; set; } + + /// + /// 联盟类型 + /// + public CpsType cps_type { get; set; } + + /// + /// 备注 + /// + public string remark { get; set; } + + } + +} diff --git a/类库/Api.Framework/Model/fl_adzone_info.cs b/类库/Api.Framework/Model/fl_adzone_info.cs new file mode 100644 index 0000000..be2f4e7 --- /dev/null +++ b/类库/Api.Framework/Model/fl_adzone_info.cs @@ -0,0 +1,71 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 推广位 + /// + public class fl_adzone_info : base_model + { + /// + /// 机器人id + /// + public long robot_id { get; set; } + /// + /// 联盟id + /// + public long alliance_id { get; set; } + /// + /// 推广位组 + /// + public long adzone_group { get; set; } + /// + /// 推广位名称 + /// + public string adzone_name { get; set; } + /// + /// 推广位pid + /// + public string adzone_pid { get; set; } + /// + /// 推广位CPS名称 + /// + public string adzone_pid_cps_name { get; set; } + /// + /// 用户id(用于私人pid) + /// + public long member_id { get; set; } + /// + /// 群id(用于群pid) + /// + public string group_id { get; set; } + /// + /// 自定义类型(用处) + /// + public string custom_type { get; set; } + /// + /// 是否下载报表 + /// + public bool is_download { get; set; } + /// + /// 是否禁用(true为禁用) + /// + public bool onoff { get; set; } + /// + /// 扩展属性 + /// + public string extend { get; set; } + + /// + /// 是否强制绑定 + /// + public bool is_auto_bind { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_alimama_activity_pid.cs b/类库/Api.Framework/Model/fl_alimama_activity_pid.cs new file mode 100644 index 0000000..97cf601 --- /dev/null +++ b/类库/Api.Framework/Model/fl_alimama_activity_pid.cs @@ -0,0 +1,19 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 天猫推广位类型 + /// + public enum fl_alimama_activity_type : long + { + 天猫精选 = 2015012602 + } + +} diff --git a/类库/Api.Framework/Model/fl_alimama_order_lastnum.cs b/类库/Api.Framework/Model/fl_alimama_order_lastnum.cs new file mode 100644 index 0000000..dabe524 --- /dev/null +++ b/类库/Api.Framework/Model/fl_alimama_order_lastnum.cs @@ -0,0 +1,25 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 阿里订单尾号 + /// + public class fl_alimama_order_lastnum : base_model + { + /// + /// 尾号 + /// + public string lastnumber { get; set; } + /// + /// 所属用户 + /// + public long userid { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_alimama_tlj_create_log.cs b/类库/Api.Framework/Model/fl_alimama_tlj_create_log.cs new file mode 100644 index 0000000..1fb9d63 --- /dev/null +++ b/类库/Api.Framework/Model/fl_alimama_tlj_create_log.cs @@ -0,0 +1,29 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 阿里淘礼金创建记录 + /// + public class fl_alimama_tlj_create_record : base_model + { + /// + /// cps名称 + /// + public string cpsname { get; set; } + /// + /// 创建的数量 + /// + public int number { get; set; } + /// + /// 创建的日期 + /// + public string date { get; set; } + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Model/fl_alimama_tlj_get_record.cs b/类库/Api.Framework/Model/fl_alimama_tlj_get_record.cs new file mode 100644 index 0000000..593abb5 --- /dev/null +++ b/类库/Api.Framework/Model/fl_alimama_tlj_get_record.cs @@ -0,0 +1,50 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 阿里淘礼金获取记录 + /// + public class fl_alimama_tlj_get_record : base_model + { + /// + /// 商品id + /// + public string itemid { get; set; } + + /// + /// 阿里id + /// + public string cpsname { get; set; } + + /// + /// tlj使用的pid + /// + public string adzoneid { get; set; } + + /// + /// 数量 + /// + public int number { get; set; } + + /// + /// 淘礼金有效期 + /// + public DateTime expiredate { get; set; } + + /// + /// 淘礼金链接 + /// + public string url { get; set; } + + /// + /// 是否有效 + /// + //public bool isvalid { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_alimama_tlj_info.cs b/类库/Api.Framework/Model/fl_alimama_tlj_info.cs new file mode 100644 index 0000000..164a2cc --- /dev/null +++ b/类库/Api.Framework/Model/fl_alimama_tlj_info.cs @@ -0,0 +1,36 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 阿里淘礼金信息 + /// + public class fl_alimama_tlj_info : base_model + { + /// + /// 淘宝username + /// + public string username { get; set; } + /// + /// 淘礼金appkey + /// + public string appkey { get; set; } + /// + /// 淘礼金appsecret + /// + public string appsecret { get; set; } + /// + /// 推广位名称 + /// + public string adzone_name { get; set; } + /// + /// 推广位pid + /// + public string adzone_pid { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_bind_cache.cs b/类库/Api.Framework/Model/fl_bind_cache.cs new file mode 100644 index 0000000..d045f85 --- /dev/null +++ b/类库/Api.Framework/Model/fl_bind_cache.cs @@ -0,0 +1,45 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 订单绑定记录表 + /// + public class fl_bind_cache: base_model + { + /// + /// fl绑定缓存 + /// + public fl_bind_cache() { groupid = string.Empty; } + + /// + /// 群号 + /// + public string groupid { get; set; } + + /// + /// 机器人ID + /// + public long db_robotid { get; set; } + + /// + /// 用户ID + /// + public long db_userid { get; set; } + + /// + /// 绑定的订单号 + /// + public string orderid { get; set; } + + /// + /// 创建时间 + /// + public DateTime crt_time { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_blackuser.cs b/类库/Api.Framework/Model/fl_blackuser.cs new file mode 100644 index 0000000..c6bb014 --- /dev/null +++ b/类库/Api.Framework/Model/fl_blackuser.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.SDK; +using Api.Framework.Tools; + +namespace Api.Framework.Model +{ + /// + /// 云黑名单 + /// + public class fl_blackuser : base_model + { + /// + /// 用户ID + /// + public string username { get; set; } + + /// + /// 0微信 1QQ + /// + public ChatType usertype { get; set; } + + /// + /// 昵称 + /// + public string nickname { get; set; } = string.Empty; + /// + /// 头像 + /// + public string avatar { get; set; } + ///// + ///// 拉黑类型 + ///// + //public BlackType BlackType { get; set; } + /// + /// 拉黑备注 + /// + public string remark { get; set; } = string.Empty; + /// + /// 是否已删除 + /// + public bool isdel { get; set; } + /// + /// 更新时间 + /// + public DateTime updatetime { get; set; } + /// + /// 是否云端 + /// + public bool iscloud { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_cloud_black.cs b/类库/Api.Framework/Model/fl_cloud_black.cs new file mode 100644 index 0000000..652be56 --- /dev/null +++ b/类库/Api.Framework/Model/fl_cloud_black.cs @@ -0,0 +1,36 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 云黑名单 + /// + public class fl_cloud_black : base_model + { + /// + /// 用户id + /// + public long memberid { get; set; } + + /// + /// 最后一次检测时间 + /// + public DateTime last_check_time { get; set; } + + /// + /// 是否是黑名单 + /// + public bool is_black { get; set; } + + /// + /// 被拉黑的原因 + /// + public string remark { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_cps_member.cs b/类库/Api.Framework/Model/fl_cps_member.cs new file mode 100644 index 0000000..f672996 --- /dev/null +++ b/类库/Api.Framework/Model/fl_cps_member.cs @@ -0,0 +1,97 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 平台账号对象(拼多多|阿里妈妈|京东联盟) + /// + public class fl_cps_member : base_model + { + public override string ToString() + { + switch (cpstype) + { + case CpsType.阿里妈妈: + case CpsType.多多进宝: + case CpsType.唯品联盟: + case CpsType.抖音联盟: + case CpsType.苏宁易购: + case CpsType.快手联盟: + return $"{usernick}({username})"; + case CpsType.京东联盟: + return $"{username}({usernick})"; + default: + return $"{usernick}({username})"; + } + } + + /// + /// 登录名(京东联盟:key) + /// + public string username { get; set; } + + /// + /// 用户昵称(京东联盟:unionId) + /// + public string usernick { get; set; } + + /// + /// Cookies + /// + [SugarColumn(ColumnDataType = "text")] + public string cookies { get; set; } + + /// + /// 登录时间 + /// + public DateTime logintime { get; set; } + + /// + /// 账号类型 + /// + public CpsType cpstype { get; set; } + + /// + /// 异常通知 + /// + public SwitchType abnormal_tip { get; set; } + + /// + /// 是否下载 + /// + public SwitchType is_download { get; set; } + + private bool _online; + /// + /// 在线 + /// + public bool online { get { return (cpstype == CpsType.阿里妈妈 || cpstype == CpsType.京东联盟 || cpstype == CpsType.抖音联盟) ? _online : true; } set { _online = value; } } + + /// + /// 高佣是否有效(淘宝有效) + /// + public bool is_valid { get; set; } + + /// + /// 其他 + /// + [SugarColumn(ColumnDataType = "text")] + public string other { get; set; } + + public fl_cps_member() + { + this.online = false; + this.cookies = string.Empty; + this.abnormal_tip = SwitchType.开启; + this.is_download = SwitchType.开启; + this.is_valid = true; + } + } +} diff --git a/类库/Api.Framework/Model/fl_create_info.cs b/类库/Api.Framework/Model/fl_create_info.cs new file mode 100644 index 0000000..dc26a0f --- /dev/null +++ b/类库/Api.Framework/Model/fl_create_info.cs @@ -0,0 +1,35 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 無用 + /// + public class fl_create_info : base_model + { + /// + /// 用户ID + /// + public long userid { get; set; } + + /// + /// 群名 + /// + public string groupname { get; set; } + + /// + /// 群号 + /// + public string groupid { get; set; } + + /// + /// 类型 + /// + public int chat_type { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_debug_log.cs b/类库/Api.Framework/Model/fl_debug_log.cs new file mode 100644 index 0000000..5b5f9c0 --- /dev/null +++ b/类库/Api.Framework/Model/fl_debug_log.cs @@ -0,0 +1,36 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// debug日志 + /// + public class fl_debug_log:base_model + { + /// + /// 用户ID + /// + public long userid { get; set; } + /// + /// 消息 + /// + public string message { get; set; } + /// + /// 时间 + /// + public double time { get; set; } + /// + /// token + /// + public string token { get; set; } + /// + /// 创建时间 + /// + public DateTime crt_time { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_dictionary_item.cs b/类库/Api.Framework/Model/fl_dictionary_item.cs new file mode 100644 index 0000000..ff2473d --- /dev/null +++ b/类库/Api.Framework/Model/fl_dictionary_item.cs @@ -0,0 +1,26 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 配置 + /// + public class fl_dictionary_item : base_model + { + /// + /// 配置的名称 + /// + public string dickey { get; set; } + /// + /// 配置的数据 + /// + public string dicvalue { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_douyin_record.cs b/类库/Api.Framework/Model/fl_douyin_record.cs new file mode 100644 index 0000000..06f9262 --- /dev/null +++ b/类库/Api.Framework/Model/fl_douyin_record.cs @@ -0,0 +1,37 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 商品历史推广信息记录 + /// + public class fl_douyin_record : base_model + { + /// + /// 商品ID + /// + public string product_id { get; set; } + + /// + /// 推广ID + /// + public string promotion_id { get; set; } + + /// + /// 商品推广信息 + /// + public string url { get; set; } + + /// + /// 商品信息json + /// + [SugarColumn(ColumnDataType = "text")] + public string gooddic { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_dy_ck.cs b/类库/Api.Framework/Model/fl_dy_ck.cs new file mode 100644 index 0000000..37ce4e7 --- /dev/null +++ b/类库/Api.Framework/Model/fl_dy_ck.cs @@ -0,0 +1,29 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 抖音ck + /// + public class fl_dy_ck : base_model + { + //[SugarColumn(Length = 1000)] + public string cpsname { get; set; } + /// + /// + /// + //[SugarColumn(Length = 1000)] + public string chname { get; set; } + /// + /// + /// + [SugarColumn(ColumnDataType = "text")] + public string ckdic { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_exchange_info.cs b/类库/Api.Framework/Model/fl_exchange_info.cs new file mode 100644 index 0000000..644f2f2 --- /dev/null +++ b/类库/Api.Framework/Model/fl_exchange_info.cs @@ -0,0 +1,53 @@ +using Api.Framework.Tools; +using Chat.Framework.WXSdk.IPAD; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 兑换记录 + /// + public class fl_exchange_info : base_model + { + /// + /// 用户fl_member_info的id + /// + public long uid { get; set; } + /// + /// 机器人的id fl_robot_info表 + /// + public long rid { get; set; } + /// + /// 积分 + /// + public double point { get; set; } + /// + /// 兑换时间 + /// + public DateTime time { get; set; } + /// + /// 审核时间 + /// + public DateTime check_time { get; set; } + /// + /// 备注 + /// + public string remark { get; set; } + /// + /// 申请状态 + /// + public ApplyType state { get; set; } + /// + /// 是否为自动转账(之后用于计算当天自动转账金额总数) + /// + public bool IsTransmatic { get; set; } + /// + /// 群id + /// + public string groupid { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_group_person.cs b/类库/Api.Framework/Model/fl_group_person.cs new file mode 100644 index 0000000..c188267 --- /dev/null +++ b/类库/Api.Framework/Model/fl_group_person.cs @@ -0,0 +1,32 @@ +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 群管理 + /// + public class fl_group_person:base_model + { + /// + /// 用户ID + /// + public long mid { get; set; } + + /// + /// 群号 + /// + public string groupid { get; set; } + + /// + /// 群名 + /// + public string groupname { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_itempoint1_hist.cs b/类库/Api.Framework/Model/fl_itempoint1_hist.cs new file mode 100644 index 0000000..f84f6c3 --- /dev/null +++ b/类库/Api.Framework/Model/fl_itempoint1_hist.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; + +namespace Api.Framework.Model +{ + /// + /// 佣金计算记录表 + /// + public class fl_itempoint1_hist : base_model + { + /// + /// guid + /// + public string guidkey { get; set; } + + /// + /// 用户id + /// + public long uid { get; set; } + + /// + /// 机器人账号 + /// + public string robotname { get; set; } + + /// + /// 机器人类型 + /// + public ChatType cpstype { get; set; } + + /// + /// 群账号 + /// + public string gid { get; set; } + + /// + /// 分出佣金itempoint - json + /// + public string text { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_member_group.cs b/类库/Api.Framework/Model/fl_member_group.cs new file mode 100644 index 0000000..e7550cd --- /dev/null +++ b/类库/Api.Framework/Model/fl_member_group.cs @@ -0,0 +1,94 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 会员分组表 + /// + public class fl_member_group : base_model + { + public override string ToString() + { + return name; + } + + private string _name; + /// + /// 名称 + /// + [Category("属性编辑"), DisplayName("1.会员组名称"), Description("可以在提示语中使用“[会员等级]”变量!")] + public string name { get; set; } + + /// + /// 条件 - 订单数 + /// + [Category("属性编辑"), DisplayName("2.升级条件 - 订单数"), Description("累计积分到达多少时,自动升级会员等级")] + public long terms_ordersum { get; set; } + + /// + /// 条件 - 积分数 + /// + [Category("属性编辑"), DisplayName("3.升级条件 - 积分数"), Description("累计积分到达多少时,自动升级会员等级")] + public double terms { get; set; } + + /// + /// 补贴 + /// + [Category("属性编辑"), DisplayName("4.额外补贴值"), Description("获得基础返利后,该等级客户额外补贴!")] + public double subsidy { get; set; } + + /// + /// 补贴类型 + /// + [Category("属性编辑"), TypeConverter(typeof(SubsidyType)), DisplayName("5.补贴类型"), DefaultValue(SubsidyType.固定积分), Description("额外补贴类型,目前为百分比或固定值!")] + public SubsidyType subsidy_type { get; set; } + + /// + /// 会员组等级 + /// + private int level { get; set; } + + /// + /// 获取会员组等级 + /// + /// + public int GetLevel() + { + return level; + } + + /// + /// 设置会员组等级 + /// + /// + public void SetLevel(int level) + { + this.level = level; + } + + /// + /// 自定义佣金比例淘宝 + /// + [Browsable(false)] + public long ratio_custom_tb { get; set; } + [Browsable(false)] + public long ratio_custom_pdd { get; set; } + [Browsable(false)] + public long ratio_custom_jd { get; set; } + [Browsable(false)] + public long ratio_custom_wph { get; set; } + [Browsable(false)] + public long ratio_custom_dy { get; set; } + [Browsable(false)] + public long ratio_custom_sn { get; set; } + [Browsable(false)] + public long ratio_custom_ks { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_member_info.cs b/类库/Api.Framework/Model/fl_member_info.cs new file mode 100644 index 0000000..0484cd8 --- /dev/null +++ b/类库/Api.Framework/Model/fl_member_info.cs @@ -0,0 +1,227 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 用户信息表 + /// + public class fl_member_info : base_model + { + /// + /// 构造方法 + /// + public fl_member_info() + { + upd_time = DateTime.Now; + crt_time = DateTime.Now; + status = MemberType.正常; + ignore_group_update = SwitchType.关闭; + ban_exchange_time = DateTime.Parse("2000-01-01 00:00:00"); + is_cloud_black = false; + check_cloud_black_time = DateTime.Parse("2000-01-01 00:00:00"); + } + + /// + /// 微信号 + /// + [Category("属性编辑"), DisplayName("01.用户名"), Description("在聊天工具里面的,唯一标识,非软件生成!")] + public string wechatid { get; set; } + + /// + /// 用户名 + /// + [Category("属性编辑"), DisplayName("02.用户名别名"), Description("在聊天工具里面的,唯一标识,非软件生成!"), ReadOnly(true)] + public string username { get; set; } + + /// + /// 真实昵称 + /// + [Category("属性编辑"), DisplayName("03.真实昵称"), Description("一般表示网名,昵称")] + public string realnick { get; set; } + + private string _usernick; + /// + /// 用户昵称 + /// + [Category("属性编辑"), DisplayName("04.昵称"), Description("一般表示备注")] + public string usernick + { + get + { + return Util.RemoveEmoji(_usernick); + } + set + { + _usernick = value; + } + } + + /// + /// 机器人类型 + /// + [Category("属性编辑"), DisplayName("05.类型"), Description("例如:QQ,微信,公众号等")] + public ChatType robot_type { get; set; } + + /// + /// 用户状态 + /// + [Category("属性编辑"), DisplayName("06.状态"), Description("获得用户状态,黑名单用户将不予理睬!")] + public MemberType status { get; set; } + + /// + /// 私人返利比例 + /// + [Browsable(false)] + public double private_ratio { get; set; } + + /// + /// 用户兑换方式 + /// + [Browsable(false)] + public ExchangeType exchange_type { get; set; } = ExchangeType.随系统设置; + + /// + /// 当前积分 + /// + [Category("属性编辑"), DisplayName("07.剩余积分"), Description("剩余积分,可以提现的积分")] + public double cur_point { get; set; } + + /// + /// 购物积分 + /// + [Browsable(false)] + public double buy_point { get; set; } + + /// + /// 累计积分 + /// + [Browsable(false)] + public double sum_point { get; set; } + + /// + /// 提成奖励 + /// + [Browsable(false)] + public double ext_point { get; set; } + + /// + /// 其他奖励 + /// + [Browsable(false)] + public double rew_point { get; set; } + + /// + /// 已完成订单 + /// + [Browsable(false)] + public long finish_order { get; set; } + + /// + /// 绑定订单数 + /// + [Browsable(false)] + public long bind_order { get; set; } + + /// + /// 备注信息 + /// + [Category("属性编辑"), DisplayName("08.备注信息"), Description("防止用户修改昵称后,无法确认用户!")] + public string remark { get; set; } + + /// + /// 机器人名称 + /// + [Category("属性编辑"), DisplayName("09.机器人名称"), ReadOnly(true), Description("不可编辑,目前客户正在使用哪个机器人!")] + public string robot_name { get; set; } + + /// + /// 邀请人ID + /// + [Category("属性编辑"), DisplayName("10.推荐人ID"), Description("用户的唯一编号,此编号由系统生成!")] + public long inviter_id { get; set; } + + /// + /// 分组ID + /// + [Category("属性编辑"), DisplayName("11.分组ID"), Description("分组ID,由系统生成!")] + public long group_id { get; set; } + + /// + /// 无视分组升级 + /// + [Category("属性编辑"), DisplayName("12.无视分组升级"), Description("无视分组等级由积分变化而改变")] + public SwitchType ignore_group_update { get; set; } + + /// + /// 支付宝账号 + /// + [Category("属性编辑"), DisplayName("13.支付宝账号"), Description("支付宝账号,便于通过支付宝提现!")] + public string alipay_num { get; set; } + + /// + /// 支付宝姓名 + /// + [Category("属性编辑"), DisplayName("14.支付宝姓名"), Description("支付宝姓名,便于通过支付宝提现!")] + public string alipay_name { get; set; } + + /// + /// 身份证姓名 + /// + [Category("属性编辑"), DisplayName("15.身份证姓名"), Description("身份证姓名")] + public string identity_name { get; set; } + + /// + /// 身份证号码 + /// + [Category("属性编辑"), DisplayName("16.身份证号码"), Description("身份证号码")] + public string identity_card { get; set; } + + /// + /// 创建时间 + /// + [Category("属性编辑"), DisplayName("17.注册时间"), Description("客户首次使用软件的时间")] + public DateTime crt_time { get; set; } + + /// + /// 最后更新时间 + /// + [Category("属性编辑"), DisplayName("18.最后交谈时间"), Description("一般表示,客户最后与我们聊天的时间!"), ReadOnly(true)] + public DateTime upd_time { get; set; } + + [Category("属性编辑"), DisplayName("19.给自己发消息次数"), Description("给自己发过多少次消息"), ReadOnly(true)] + public int chat_count { get; set; } + + [Category("属性编辑"), DisplayName("20.上一次拉黑时间"), Description("如果用户被拉黑,会记录拉黑的时间"), ReadOnly(true)] + public DateTime blackout_time { get; set; } + + [Category("属性编辑"), DisplayName("21.限制兑换时间"), Description("当前时间小于限制兑换时间时,改用户将不能进行兑换操作"), ReadOnly(true)] + public DateTime ban_exchange_time { get; set; } + + /// + /// 是否为云黑名单人员 + /// + [Browsable(false)] + public bool is_cloud_black { get; set; } + + /// + /// 云黑名单上次检测时间 + /// + [Browsable(false)] + public DateTime check_cloud_black_time { get; set; } + + /// + /// 头像地址 + /// + [Browsable(false)] + public string headurl { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_member_level.cs b/类库/Api.Framework/Model/fl_member_level.cs new file mode 100644 index 0000000..f018ea1 --- /dev/null +++ b/类库/Api.Framework/Model/fl_member_level.cs @@ -0,0 +1,28 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace Api.Framework.Model +{ + /// + /// 分组 + /// + public class fl_member_level : base_model + { + /// + /// 分组名称 + /// + [DataViewAtrribute(Name = "分组名称")] + public string name { get; set; } + + /// + /// 所需积分 + /// + [DataViewAtrribute(Name = "所需积分")] + public double point { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_member_private_config.cs b/类库/Api.Framework/Model/fl_member_private_config.cs new file mode 100644 index 0000000..b214459 --- /dev/null +++ b/类库/Api.Framework/Model/fl_member_private_config.cs @@ -0,0 +1,61 @@ +using Easy4net.Context; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 客户私人配置*(私人pid,积分比例等) + /// + public class fl_member_private_config : base_model + { + /// + /// 用户id (fl_membe_info 表id) + /// + public long uid { get; set; } + /// + /// 淘宝cps名称 + /// + public string tb_cps_name { get; set; } + /// + /// 淘宝pid + /// + public string tb_pid { get; set; } + /// + /// 淘宝推广位名称 + /// + public string tb_pid_name { get; set; } + /// + /// 京东cps名称 + /// + public string jd_cps_name { get;set; } + /// + /// 京东pid + /// + public string jd_pid { get; set; } + /// + /// 京东推广位名称 + /// + public string jd_pid_name { get; set; } + /// + /// 淘宝cps名称 + /// + public string pdd_cps_name { get; set; } + /// + /// 拼多多pid + /// + public string pdd_pid { get; set; } + /// + /// 拼多多推广位名称 + /// + public string pdd_pid_name { get; set; } + /// + /// 个人的积分比例 + /// + public string point_ratio { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_noticeapi_info.cs b/类库/Api.Framework/Model/fl_noticeapi_info.cs new file mode 100644 index 0000000..c6d1c6a --- /dev/null +++ b/类库/Api.Framework/Model/fl_noticeapi_info.cs @@ -0,0 +1,48 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 通知Api类型 + /// + public enum NoticeApiType + { + 企业钉钉机器人API, + 企业微信机器人API, + 飞书机器人API + } + + /// + /// 通知机器人信息 + /// + public class fl_noticeapi_info : base_model + { + /// + /// 名称 + /// + public string name { get; set; } + + /// + /// API位置 + /// + public string api_location { get; set; } + + /// + /// 备注 + /// + public string remark { get; set; } + + public NoticeApiType notice_apitype { get; set; } + + /// + /// Token等,验证字段 + /// + public string token { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_operation_log.cs b/类库/Api.Framework/Model/fl_operation_log.cs new file mode 100644 index 0000000..c2f46a7 --- /dev/null +++ b/类库/Api.Framework/Model/fl_operation_log.cs @@ -0,0 +1,33 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 操作日志 + /// + public class fl_operation_log : base_model + { + /// + /// 操作类型 + /// + public OperationType otype { get; set; } + /// + /// 旧数据 + /// + public string old_text { get; set; } + /// + /// 新数据 + /// + public string new_text { get; set; } + /// + /// 修改日志 + /// + public DateTime datetime { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_order_alimama.cs b/类库/Api.Framework/Model/fl_order_alimama.cs new file mode 100644 index 0000000..d72eb39 --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_alimama.cs @@ -0,0 +1,173 @@ + +using Api.Framework.Enums; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 阿里订单 + /// + public class fl_order_alimama : base_model_order + { + /// + /// PID-第三段-ID + /// + public string adzone_id { get; set; } + /// + /// PID-第三段-名称 + /// + public string adzone_name { get; set; } + /// + /// 付款金额 + /// + public double alipay_total_price { get; set; } + /// + /// 类目名称,(这个用来判断维权中订单手动结算状态 - 值:手动处理) + /// + public string auction_category { get; set; } + /// + /// 结算预估总佣金 + /// + public double commission { get; set; } + /// + /// 佣金比例 + /// + public double commission_rate { get; set; } + /// + /// 创建时间 + /// + public DateTime create_time { get; set; } + /// + /// 付款时间 + /// + public DateTime paid_time { get; set; } + /// + /// 结算时间 + /// + public DateTime earning_time { get; set; } + /// + /// 补贴比例 + /// + public double income_rate { get; set; } + /// + /// 商品数量 + /// + public int item_num { get; set; } + /// + /// 商品标题 + /// + public string item_title { get; set; } + /// + /// 商品ID + /// + public string num_iid { get; set; } + /// + /// 订单类型 例如: 天猫、淘宝 + /// + public string order_type { get; set; } + /// + /// 实际付款 + /// + public double pay_price { get; set; } + /// + /// 宝贝原价 + /// + public double price { get; set; } + /// + /// 预估佣金 + /// + public double pub_share_pre_fee { get; set; } + /// + /// 店铺昵称 + /// + public string seller_nick { get; set; } + /// + /// 店铺标题 + /// + public string seller_shop_title { get; set; } + /// + /// PID-第二段 + /// + public string site_id { get; set; } + /// + /// PID-第二段名称 + /// + public string site_name { get; set; } + /// + /// 补贴佣金 + /// + public double subsidy_fee { get; set; } + /// + /// 补贴比例 + /// + public double subsidy_rate { get; set; } + /// + /// 补贴类型 + /// + public int subsidy_type { get; set; } + /// + /// 终端类型 + /// + public int terminal_type { get; set; } + /// + /// 订单状态 + /// + public int tk_status { get; set; } + /// + /// 佣金金额 + /// + public double total_commission_fee { get; set; } + /// + /// 总共比例 + /// + public double total_commission_rate { get; set; } + /// + /// 子订单号 + /// + public string trade_id { get; set; } + /// + /// 父订单号 + /// + public string trade_parent_id { get; set; } + /// + /// 店铺ID + /// + public string seller_id { get; set; } + + /// + /// 预付款金额 + /// + public string deposit_price { get; set; } + + /// + /// 预售时期,用户对预售商品支付定金的付款时间 + /// + public string tb_deposit_time { get; set; } + + /// + /// 技术服务费比率 + /// + public double alimama_rate { get; set; } + + /// + /// 技术服务费金额 + /// + public double alimama_share_fee { get; set; } + + /// + /// 会员运营id + /// + public long special_id { get; set; } + + /// + /// 渠道关系id + /// + public long relation_id { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_order_douyin.cs b/类库/Api.Framework/Model/fl_order_douyin.cs new file mode 100644 index 0000000..9158658 --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_douyin.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 抖音订单响应 + /// + public class DouYinOrder + { + /// + /// 响应值 + /// + public long code { get; set; } + /// + /// 数据 + /// + public List data { get; set; } + /// + /// 其他信息 + /// + public Extra extra { get; set; } + /// + /// 响应状态内容 + /// + public string msg { get; set; } + /// + /// 不知道是什么 + /// + public long st { get; set; } + /// + /// 查询出来的数据量 + /// + public long total { get; set; } + } + + /// + /// 抖音订单 + /// + public class fl_order_douyin : base_model_order + { + /// + /// 订单号 + /// + public string order_id { get; set; } + /// + /// 商品id + /// + public string product_id { get; set; } + /// + /// 商品标题 + /// + public string product_name { get; set; } + /// + /// 商品详情页 + /// + public string product_detail { get; set; } + /// + /// 用户名称 + /// + public string user_name { get; set; } + /// + /// 支付金额 + /// + public int total_pay_amount { get; set; } + /// + /// 佣金率 + /// + public int commission_rate { get; set; } + /// + /// 预估佣金(已经扣除了技术费) + /// + public int estimated_comission { get; set; } + /// + /// 实际佣金 (应该是结算有才有值,已付款为0) + /// + public int real_comission { get; set; } + /// + /// 订单的状态 “PAY_SUCC” + /// + public string order_status { get; set; } + /// + /// 付款时间 + /// + public int pay_time { get; set; } + /// + /// 确定收货时间(已付款时值为1) + /// + public int confirm_time { get; set; } + /// + /// 建立时间?(已付款时值为1) + /// + public int settle_time { get; set; } + /// + /// 推销来源(推销类型) + /// + public int promotion_source { get; set; } + /// + /// 用户利润比例 + /// + public int user_profit_ratio { get; set; } + /// + /// 平台服务费(百分之10) + /// + public int platform_service_fee { get; set; } + /// + /// 账户类型(值:正式账户) + /// + public string account_type { get; set; } + /// + /// 全部佣金 + /// + public int total_commission { get; set; } + /// + /// 估计用户佣金 + /// + public int estimated_user_comission { get; set; } + /// + /// 预计本月佣金 + /// + public int estimated_inst_comission { get; set; } + /// + /// 确定的用户佣金 + /// + public int settle_user_comission { get; set; } + /// + /// 本月结算佣金 + /// + public int settle_inst_comission { get; set; } + /// + /// 是否为海淘 + /// + public bool is_haitao { get; set; } + /// + /// 阶段顺序 + /// + public bool stage_order { get; set; } + /// + /// 第一阶段支付时间 + /// + public string stage_one_pay_time { get; set; } + /// + /// 第二阶段支付时间 + /// + public string stage_two_pay_time { get; set; } + /// + /// 第一阶段支付付款 + /// + public int stage_one_pay_money { get; set; } + } + + /// + /// 其他 + /// + public class Extra + { + /// + /// 日志id + /// + public string log_id { get; set; } + /// + /// 时间戳毫秒 + /// + public long now { get; set; } + } + +} diff --git a/类库/Api.Framework/Model/fl_order_jingdong.cs b/类库/Api.Framework/Model/fl_order_jingdong.cs new file mode 100644 index 0000000..1ab66fe --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_jingdong.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 京东订单 + /// + public class fl_order_jingdong : base_model_order + { + /// + /// 下单时间 + /// + public DateTime orderTime { get; set; } + /// + /// 完成时间 + /// + public DateTime finishTime { get; set; } + /// + /// 订单号 + /// + public long orderId { get; set; } + /// + /// 商品ID + /// + public long skuId { get; set; } + /// + /// 商品名称 + /// + public string skuName { get; set; } + /// + /// 商品数量 + /// + public long skuNum { get; set; } + /// + /// 商品已退货数量 + /// + public long skuReturnNum { get; set; } + /// + /// 商品售后中数量 + /// + public long frozenSkuNum { get; set; } + /// + /// 分成比例 + /// + public double subSideRate { get; set; } + /// + /// 补贴比例 + /// + public double subsidyRate { get; set; } + /// + /// 实际计算佣金的金额。订单完成后,会将误扣除的运费券金额更正。如订单完成后发生退款,此金额会更新。 + /// + public double actualCosPrice { get; set; } + /// + /// (商品总佣金)推客获得的实际佣金(实际计佣金额*佣金比例*最终比例)。如订单完成后发生退款,此金额会更新。 + /// + public double actualFee { get; set; } + /// + /// 佣金比例 + /// + public double commissionRate { get; set; } + + /// + /// 预估计佣金额,即用户下单的金额(已扣除优惠券、白条、支付优惠、进口税,未扣除红包和京豆),有时会误扣除运费券金额,完成结算时会在实际计佣金额中更正。如订单完成前发生退款,此金额也会更新。 + /// + public double estimateCosPrice { get; set; } + /// + /// 推客的预估佣金(预估计佣金额*佣金比例*最终比例),如订单完成前发生退款,此金额也会更新。 + /// + public double estimateFee { get; set; } + /// + /// 最终比例(分成比例+补贴比例) + /// + public double finalRate { get; set; } + /// + /// 京东结算时间(格式:yyyyMMdd),0:未结算 + /// + public String payMonth { get; set; } + /// + /// 联盟子站长身份标识,格式:子站长ID_子站长网站ID_子站长推广位ID + /// + public string pid { get; set; } + /// + /// 商家ID。(订单行维度); + /// + public long popId { get; set; } + /// + /// 推广位ID,0代表无推广位 + /// + public long positionId { get; set; } + /// + /// 是否是会员 + /// + public int plus { get; set; } + /// + /// 商品单价 + /// + public double price { get; set; } + + /// + /// 2:同店;3:跨店 + /// + public int traceType { get; set; } + /// + /// 子联盟ID(需要联系运营开放白名单才能拿到数据) + /// + public string subUnionId { get; set; } + /// + /// PID所属母账号平台名称(原第三方服务商来源) + /// + public string unionAlias { get; set; } + /// + /// 联盟标签数据(整型的二进制字符串(32位),目前只返回8位:00000001。数据从右向左进行,每一位为1表示符合联盟的标签特征,第1位:优惠券,第2位:组合推广订单,第3位:拼购订单,第5位:有效首次购订单(00011XXX表示有效首购,最终奖励活动结算金额会结合订单状态判断,以联盟后台对应活动效果数据报表https://union.jd.com/active为准)。例如:00000001:优惠券,00000010:组合推广订单,00000100:拼购订单,00011000:有效首购,00000111:优惠券+组合推广+拼购等) + /// + public string unionTag { get; set; } + /// + /// 渠道组 1:1号店,其他:京东 + /// + public int unionTrafficGroup { get; set; } + /// + /// sku维度的有效码(-1:未知,2.无效-拆单,3.无效-取消,4.无效-京东帮帮主订单,5.无效-账号异常,6.无效-赠品类目不返佣,7.无效-校园订单,8.无效-企业订单,9.无效-团购订单,10.无效-开增值税专用发票订单,11.无效-乡村推广员下单,12.无效-自己推广自己下单,13.无效-违规订单,14.无效-来源与备案网址不符,15.待付款,16.已付款,17.已完成,18.已结算)注:自2018/7/13起,自己推广自己下单已经允许返佣,故12无效码仅针对历史数据有效 + /// + public int validCode { get; set; } + /// + /// 应用id(网站id、appid、社交媒体id) + /// + public long siteId { get; set; } + + /// + /// 推客生成推广链接时传入的扩展字段(需要联系运营开放白名单才能拿到数据)。(订单行维度); + /// + public string ext1 { get; set; } + ///// + ///// 一级类目ID + ///// + public long cid1 { get; set; } + ///// + ///// 二级类目ID + ///// + public long cid2 { get; set; } + ///// + ///// 三级类目ID + ///// + public long cid3 { get; set; } + /// + /// 维权时间 + /// + public DateTime refundcreatetime { get; set; } + + /// + /// 价保赔付金额,非为0时,给客户结算的金额为0 + /// + public double proPriceAmount { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_order_kuaishou.cs b/类库/Api.Framework/Model/fl_order_kuaishou.cs new file mode 100644 index 0000000..7426d2c --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_kuaishou.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 快手订单 + /// + public class fl_order_kuaishou : base_model_order + { + /// + /// 订单号 + /// + public long oid { get; set; } + + /// + /// 订单状态 [0:全部订单] [30:已付款] [50:已收货] [60:已结算] [80:已失效] + /// + public CpsOrderStatus cpsOrderStatus { get; set; } + + /// + /// 订单创建时间 + /// + public DateTime orderCreateTime { get; set; } + + /// + /// 支付时间 + /// + public DateTime payTime { get; set; } + + /// + /// 订单金额 + /// + public double orderTradeAmount { get; set; } + + /// + /// 分销订单生成时间 + /// + public DateTime createTime { get; set; } + + /// + /// 分销订单更新时间 + /// + public DateTime updateTime { get; set; } + + /// + /// 结算成功时间 + /// + public DateTime settlementSuccessTime { get; set; } + + /// + /// 结算金额 + /// + public double settlementAmount { get; set; } + + /// + /// 所属快手账号ID + /// + public long kwaimoneyUserId { get; set; } + + //------------------------------------------------- + /// + /// 子订单号 + /// + public long oid2 { get; set; } + + /// + /// 商品ID + /// + public long itemId { get; set; } + + /// + /// 商品标题 + /// + public string itemTitle { get; set; } + + /// + /// 商品头图 + /// + public string itemPicUrl { get; set; } + + /// + /// 商品金额快照 + /// + public double itemPrice { get; set; } + + /// + /// 规格描述 + /// + public string skuDesc { get; set; } + + /// + /// 预估收入(佣金) + /// + public double estimatedIncome { get; set; } + + /// + /// 佣金率,单位千分之一 + /// + public double commissionRate { get; set; } + + /// + /// 推广位pid + /// + public string cpsPid { get; set; } + + /// + /// 卖家id + /// + public long sellerId { get; set; } + + /// + /// 卖家昵称 + /// + public string sellerNickname { get; set; } + + /// + /// 购买数量 + /// + public int num { get; set; } + + /// + /// 分销订单类型:3-达人直播间分销 + /// + public int cpsType { get; set; } + + /// + /// 达人id + /// + public long distributorId { get; set; } + + /// + /// 达人昵称 + /// + public string distributorNickname { get; set; } + + /// + /// 备注(创建商品时的自定义参数) + /// + public string comments { get; set; } + + /// + /// pid名称 + /// + public string pidName { get; set; } + + /// + /// 实付金额 + /// + public double paymentFee { get; set; } + + } + + + public enum CpsOrderStatus + { + 全部订单 = 0, + 已付款 = 30, + 已收货 = 50, + 已结算 = 60, + 已失效 = 80, + } + +} diff --git a/类库/Api.Framework/Model/fl_order_pinduoduo.cs b/类库/Api.Framework/Model/fl_order_pinduoduo.cs new file mode 100644 index 0000000..9635935 --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_pinduoduo.cs @@ -0,0 +1,129 @@ +//============================================================= +// 创建人:千年老妖 +// 本页代码,均为原创。对未经许可擅自使用者,本人保留追究其法律责任的权利。 +//============================================================== +using Api.Framework.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 拼多多订单 + /// + public class fl_order_pinduoduo : base_model_order + { + /// + /// 0非比价,1比价 + /// + public PinduoduoBiJiaType price_compare_status { get; set; } + + /// + /// 自定义参数 + /// + public string custom_parameters { get; set; } + + /// + /// 拼多多结算时间 + /// + public DateTime order_receive_time { get; set; } + + /// + /// 订单类型 + /// + public int type { get; set; } + + /// + /// 审核时间 + /// + public DateTime order_verify_time { get; set; } + + /// + /// 支付时间 + /// + public DateTime order_pay_time { get; set; } + + /// + /// 成团时间 + /// + public DateTime order_group_success_time { get; set; } + + /// + /// 最后更新时间 + /// + public DateTime order_modify_at { get; set; } + + /// + /// 状态描述 + /// + public string order_status_desc { get; set; } + + /// + /// 推广位ID + /// + public string p_id { get; set; } + + /// + /// 订单状态 + /// + public int order_status { get; set; } + + /// + /// 佣金金额 + /// + public double promotion_amount { get; set; } + + /// + /// 佣金比例 + /// + public int promotion_rate { get; set; } + + /// + /// 订单生成时间 + /// + public DateTime order_create_time { get; set; } + + /// + /// 支付金额 + /// + public double order_amount { get; set; } + + /// + /// 订单单价 + /// + public double goods_price { get; set; } + + /// + /// 订单数量 + /// + public int goods_quantity { get; set; } + + /// + /// 缩率图 + /// + public string goods_thumbnail_url { get; set; } + + /// + /// 商品名称 + /// + public string goods_name { get; set; } + + /// + /// 商品id + /// + public string goods_id { get; set; } + + /// + /// 订单号 + /// + public string order_sn { get; set; } + + /// + /// 店铺ID + /// + public string mall_id { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_order_refund_alimama.cs b/类库/Api.Framework/Model/fl_order_refund_alimama.cs new file mode 100644 index 0000000..de5b3c4 --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_refund_alimama.cs @@ -0,0 +1,108 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 阿里订单维权 + /// + public class fl_order_refund_alimama : base_model + { + /// + /// 手续费 + /// + public double tkcommissionfee { get; set; } + /// + /// 补贴费用 + /// + public string tksubsidyfee { get; set; } + /// + /// 退款手续费 + /// + public double refundfee { get; set; } + /// + /// 淘宝交易id + /// + public string tbtradeid { get; set; } + /// + /// 邀请者id + /// + public string inviterid { get; set; } + + /// + /// 父订单号 + /// + public string tbtradeparentid { get; set; } + + /// + /// tbauctionnum + /// + public string tbauctionnum { get; set; } + + /// + /// 订单标题 + /// + public string tbauctiontitle { get; set; } + /// + /// 淘宝卖家商店标题 + /// + public string tbsellershoptitle { get; set; } + /// + /// 订单结算时间 + /// + public string earningtime { get; set; } + /// + /// 显示返回的费用 + /// + public double showreturnfee { get; set; } + + /// + /// 显示退款原因 + /// + public string showrefundreason { get; set; } + /// + /// 退款创建时间 + /// + public string refundcreatetime { get; set; } + /// + /// 退款完成时间 + /// + public string refundfinishtime { get; set; } + /// + /// 退还服务费用 + /// + public double refundservicefee { get; set; } + /// + /// 关系app + /// + public string relationapp { get; set; } + /// + /// 邀请人帐户名称 + /// + public string inviteraccountname { get; set; } + /// + /// 关系app名称 + /// + public string relationappname { get; set; } + /// + /// 关系id + /// + public string relationid { get; set; } + + /// + /// TB贸易成品价格 + /// + public string tbtradefinishprice { get; set; } + + /// + /// 维权状态 + /// + public string showrefundstatus { get; set; } + + + } +} diff --git a/类库/Api.Framework/Model/fl_order_sleep.cs b/类库/Api.Framework/Model/fl_order_sleep.cs new file mode 100644 index 0000000..4b2e22e --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_sleep.cs @@ -0,0 +1,50 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 订单冻结规则 + /// + public class fl_order_sleep : base_model + { + /// + /// 金额满足 + /// + [Category("属性编辑"), DisplayName("1.佣金条件"), Description("总佣金小于等于多少")] + public double money { get; set; } + + /// + /// 结算后延迟返佣金(单位:小时) + /// + [Category("属性编辑"), DisplayName("2.延迟结算"), Description("延迟多少小时结算")] + public int sleep { get; set; } + + /// + /// 联盟类型 + /// + [Category("属性编辑"), DisplayName("3.联盟类型"), Description("针对哪个联盟生效")] + public CpsType cps_type { get; set; } + + /// + /// 不受限的会员组 + /// + [Category("属性编辑"), DisplayName("4.不受限会员组"), Description("填写会员分组ID,多个分组,用英文逗号分隔")] + public string white_groups { get; set; } + + /// + /// 无参构造函数 + /// + public fl_order_sleep() + { + this.white_groups = string.Empty; + } + + } +} diff --git a/类库/Api.Framework/Model/fl_order_suning.cs b/类库/Api.Framework/Model/fl_order_suning.cs new file mode 100644 index 0000000..91c8bcd --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_suning.cs @@ -0,0 +1,144 @@ +using Api.Framework.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + public class fl_order_suning : base_model_order + { + /// + /// 订单号 + /// + public string orderCode { get; set; } + /// + /// 支付时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime payTime { get; set; } + /// + /// 下单时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime orderSubmitTime { get; set; } + /// + /// 订单行项目号 + /// + public string orderLineNumber { get; set; } + /// + /// 订单行项目状态 - 支付完成 + /// + public string orderLineStatusDesc { get; set; } + /// + /// 行项目状态更新时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime orderLineStatusChangeTime { get; set; } + /// + /// 订单行来源(PC端、无线端) + /// + public string orderLineOrigin { get; set; } + /// + /// 商品名称 + /// + public string productName { get; set; } + /// + /// 商品数量 + /// + public string saleNum { get; set; } + /// + /// 实付金额 + /// + public string payAmount { get; set; } + /// + /// 订单行标记 + /// + public string orderLineFlag { get; set; } + /// + /// 自定义编码 - 子推广账号ID(对应sub_user) + /// + public string childAccountId { get; set; } + /// + /// 商户名称 + /// + public string sellName { get; set; } + /// + /// 商户编码 + /// + public string sellerCode { get; set; } + /// + /// 商品编码 + /// + public string goodsNum { get; set; } + /// + /// 佣金比例 + /// + public string commissionRatio { get; set; } + /// + /// 预估佣金 + /// + public string prePayCommission { get; set; } + /// + /// 一级目录 + /// + public string productFirstCatalog { get; set; } + /// + /// 二级目录 + /// + public string productSecondCatalog { get; set; } + /// + /// 三级目录 + /// + public string productThirdCatalog { get; set; } + /// + /// 商品归属 - 自营 + /// + public string orderType { get; set; } + /// + /// 推广位ID + /// + public string positionId { get; set; } + /// + /// 商品组目录编码 + /// + public string goodsGroupCatalog { get; set; } + /// + /// 推广类型 - 链接推广 + /// + public string saleType { get; set; } + /// + /// 商品主图 + /// + public string pictureUrl { get; set; } + /// + /// 1.风控订单 + /// + public int promotion { get; set; } + /// + /// 是否违规,0:否;1:是 + /// + public int violation { get; set; } + /// + /// 是否返佣,0:否;1:是 + /// + public int returnCommission { get; set; } + /// + /// 推广会员编码 + /// + public string custNo { get; set; } + /// + /// + /// + public string statParam { get; set; } + + /// + /// 店铺id + /// + public string mallId { get; set; } + + /// + /// 推广位,此推广位非彼推广位 + /// + public string pid { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_order_weipinhui.cs b/类库/Api.Framework/Model/fl_order_weipinhui.cs new file mode 100644 index 0000000..ec22bb5 --- /dev/null +++ b/类库/Api.Framework/Model/fl_order_weipinhui.cs @@ -0,0 +1,201 @@ +using Api.Framework.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 唯品会订单 + /// + public class fl_order_weipinhui : base_model_order + { + /// + /// 订单号 + /// + public string orderSn { get; set; } + ///// + ///// 订单状态:0-不合格,1-待定,2-已完结 + ///// + //public WeipinhuiOrderStatus status { get; set; } + /// + /// 新老客:0-待定,1-新客,2-老客 + /// + public WeipinhuiNewCustomer newCustomer { get; set; } + /// + /// 渠道商模式下表示自定义渠道标识;工具商模式下表示pid + /// + public string channelTag { get; set; } + /// + /// 下单时间 时间戳 单位毫秒 + /// + public long orderTime { get; set; } + /// + /// 签收时间 时间戳 单位毫秒 + /// + public long signTime { get; set; } + /// + /// 结算时间 时间戳 单位毫秒 + /// + public long settledTime { get; set; } + /// + /// 订单上次更新时间 时间戳 单位毫秒 + /// + public long lastUpdateTime { get; set; } + /// + /// 订单结算状态 0-未结算,1-已结算 + /// + public WeipinhuiOrderSettled settled { get; set; } + /// + /// 是否自推自买 0-否,1-是 + /// + public WeipinhuiShiFou selfBuy { get; set; } + /// + /// 订单子状态:流转状态-支持状态:(已下单、已付款、已签收、待结算、已结算、已失效) + /// + public WeipinhuiOrderSubStatusName orderSubStatusName { get; set; } + + /// + /// 售后订单佣金变动:仅在订单完结之后发生售后行为时返回 + /// + public string afterSaleChangeCommission { get; set; } + /// + /// 售后订单总商品数量变动:仅在订单完结之后发生售后行为时返回 + /// + public string afterSaleChangeGoodsCount { get; set; } + /// + /// 入账时间,时间戳,单位毫秒 + /// + public long commissionEnterTime { get; set; } + ///// + ///// 订单来源 + ///// + //public string orderSource { get; set; } + /// + /// 推广PID:目前等同于channelTag + /// + public string pid { get; set; } + /// + /// 店铺ID + /// + public string mallId { get; set; } + /// + /// 是否预付订单:0-否,1-是 + /// + public WeipinhuiShiFou isPrepay { get; set; } + /// + /// 自定义统计参数 + /// + public string statParam { get; set; } + /// + /// 订单拆单标识: 0-否,1-是 + /// + public WeipinhuiShiFou isSplit { get; set; } + /// + /// 订单母单号:订单为拆单子单时返回 + /// + public string parentSn { get; set; } + /// + /// 订单归因方式:0-常规推广,1-惊喜红包,2-锁粉,3-超级红包 + /// + public WeipinhuiGuiYin orderTrackReason { get; set; } + + #region 商品明细 + /// + /// 商品id + /// + public string goodsId { get; set; } + /// + /// 商品名称 + /// + public string goodsName { get; set; } + /// + /// 商品缩略图 + /// + public string goodsThumb { get; set; } + /// + /// 商品数量 + /// + public int goodsCount { get; set; } + /// + /// 商品计佣金额(元,保留两位小数) + /// + public double commissionTotalCost { get; set; } + /// + /// 商品佣金比例(%) + /// + public double commissionRate { get; set; } + /// + /// 商品佣金金额(元,保留两位小数) + /// + public double commission { get; set; } + /// + /// 佣金编码:对应商品二级分类 + /// + public string commCode { get; set; } + /// + /// 佣金方案名称 + /// + public string commName { get; set; } + /// + /// 订单来源 + /// + public string orderSource { get; set; } + /// + /// 商品尺码:2019.01.01之后可用 + /// + public string sizeId { get; set; } + /// + /// 商品状态:0-不合格,1-待定,2-已完结 + /// + public WeipinhuiOrderStatus status { get; set; } + /// + /// 品牌编号 + /// + public string brandStoreSn { get; set; } + /// + /// 品牌名称 + /// + public string brandStoreName { get; set; } + /// + /// 商品spuId + /// + public string spuId { get; set; } + /// + /// 商品成交价(元,保留两位小数,商品成交价上线之后的订单才有该值) + /// + public double goodsFinalPrice { get; set; } + + #endregion + + #region 售后信息 无售后为空 + /// + /// 商品佣金售后变动:仅在订单完结之后发生售后时返回,无售后时为空 + /// + public double afterSaleChangedCommission { get; set; } + /// + /// 商品数量售后变动:仅在订单完结之后发生售后时返回,无售后时为空 + /// + public int afterSaleChangedGoodsCount { get; set; } + /// + /// 商品售后单号,无售后时为空 + /// + public string afterSaleSn { get; set; } + /// + /// 商品售后状态:1-售后中,2-售后完成,3-售后取消,无售后时为空 + /// + public WeipinhuiAfterSaleStatus afterSaleStatus { get; set; } + /// + /// 售后类型:1-退货,2-换货,无售后时为空 + /// + public WeipinhuiSfterSaleType afterSaleType { get; set; } + /// + /// 售后完成时间,时间戳,单位:毫秒,无售后时为空 + /// + public long afterSaleFinishTime { get; set; } + #endregion + + } +} diff --git a/类库/Api.Framework/Model/fl_plugin_allrebatesactivity_info.cs b/类库/Api.Framework/Model/fl_plugin_allrebatesactivity_info.cs new file mode 100644 index 0000000..e39ff99 --- /dev/null +++ b/类库/Api.Framework/Model/fl_plugin_allrebatesactivity_info.cs @@ -0,0 +1,81 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 全额免单 + /// + public class fl_plugin_allrebatesactivity_info : base_model + { + /// + /// 活动名称 + /// + public string name { get; set; } + + /// + /// 活动开始时间 + /// + public DateTime time_begin { get; set; } + + /// + /// 活动结束时间 + /// + public DateTime time_end { get; set; } + + /// + /// 机器人列表 (机器人name) + /// + public string robots { get; set; } + + /// + /// 参加活动的用户组(-1未所有用户) + /// + public string groups { get; set; } + + /// + /// 限制购买数量 + /// + public int limit_quantity_number { get;set;} + + /// + /// 活动宝贝 + /// + public string goods_id { get; set; } + + /// + /// 宝贝标题 + /// + public string title { get; set; } + + /// + /// 单价 + /// + public double price { get; set; } + + /// + /// 优惠券面额 + /// + public double coupon { get; set; } + + /// + /// 返利比例 + /// + public int brokerage_ratio { get; set; } + + /// + /// 返利金额 + /// + public double brokerage_money { get; set; } + + /// + /// 返回客户金额比例.用户付款金额为基数 + /// + public double return_money { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_plugin_allrebatesactivity_orderlist.cs b/类库/Api.Framework/Model/fl_plugin_allrebatesactivity_orderlist.cs new file mode 100644 index 0000000..387afc8 --- /dev/null +++ b/类库/Api.Framework/Model/fl_plugin_allrebatesactivity_orderlist.cs @@ -0,0 +1,38 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 全额免单订单 + /// + public class fl_plugin_allrebatesactivity_orderlist : base_model + { + /// + /// 任务ID + /// + public long activity_id { get; set; } + + /// + /// 机器人ID + /// + public long rid { get; set; } + + /// + /// 用户ID + /// + public long mid { get; set; } + + /// + /// 订单ID + /// + public long oid { get; set; } + + } + +} diff --git a/类库/Api.Framework/Model/fl_plugin_info.cs b/类库/Api.Framework/Model/fl_plugin_info.cs new file mode 100644 index 0000000..968d87a --- /dev/null +++ b/类库/Api.Framework/Model/fl_plugin_info.cs @@ -0,0 +1,30 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 插件基础信息 + /// + public class fl_plugin_info:base_model + { + /// + /// 程序集 + /// + public string assembly { get; set; } + + /// + /// 顺序 + /// + public int level { get; set; } + + /// + /// 文件 + /// + public string file { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_point_hist.cs b/类库/Api.Framework/Model/fl_point_hist.cs new file mode 100644 index 0000000..ecb66f1 --- /dev/null +++ b/类库/Api.Framework/Model/fl_point_hist.cs @@ -0,0 +1,60 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 积分改变记录 + /// + public class fl_point_hist : base_model + { + /// + /// 用户ID + /// + public long uid { get; set; } + + /// + /// 机器人id + /// + public long rid { get; set; } + + /// + /// 改变的值 + /// + public double point { get; set; } + + /// + /// 类型 + /// + public string type { get; set; } + + /// + /// 内容 + /// + public string message { get; set; } + + /// + /// 修改前积分 + /// + public double before_point { get; set; } + + /// + /// 修改后积分 + /// + public double after_point { get; set; } + + /// + /// 创建时间 + /// + public DateTime crt_time { get; set; } + public fl_point_hist() + { + this.message = string.Empty; + this.crt_time = DateTime.Now; + } + } +} diff --git a/类库/Api.Framework/Model/fl_prevent_theft_cache.cs b/类库/Api.Framework/Model/fl_prevent_theft_cache.cs new file mode 100644 index 0000000..52547b0 --- /dev/null +++ b/类库/Api.Framework/Model/fl_prevent_theft_cache.cs @@ -0,0 +1,43 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 防撸处理 + /// + public class fl_prevent_theft_cache : base_model + { + /// + /// 用户id + /// + public long member_id { get; set; } + /// + /// 商品ID + /// + public string item_id { get; set; } + /// + /// 店铺ID + /// + public string mall_id { get; set; } + /// + /// 订单编码 + /// + public string order_id { get; set; } + /// + /// 处理类型 + /// + public OperateType operate_type { get;set;} + /// + /// 订单平台类型 + /// + public CpsType cps_type { get; set; } + + public string extend { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_private_pid.cs b/类库/Api.Framework/Model/fl_private_pid.cs new file mode 100644 index 0000000..750c24e --- /dev/null +++ b/类库/Api.Framework/Model/fl_private_pid.cs @@ -0,0 +1,52 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 私人PID绑定 + /// + public class fl_private_pid:base_model + { + /// + /// 用户编号 + /// + public long uid { get; set; } + + /// + /// 推广位ID + /// + public string pid_id { get; set; } + + /// + /// 推广位名称 + /// + public string pid_name { get; set; } + + /// + /// 联盟账号 + /// + public string cps_name { get; set; } + + /// + /// cps类型 + /// + public CpsType cps_type { get; set; } + + /// + /// 订单绑定 + /// + public bool bind_order { get; set; } + + /// + /// 查询绑定 + /// + public bool bind_query { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_query_hist.cs b/类库/Api.Framework/Model/fl_query_hist.cs new file mode 100644 index 0000000..0494322 --- /dev/null +++ b/类库/Api.Framework/Model/fl_query_hist.cs @@ -0,0 +1,130 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 查询记录 + /// + public class fl_query_hist : base_model + { + /// + /// cps类型 + /// + public CpsType type { get; set; } + /// + /// 商品ID + /// + public string itemid { get; set; } + /// + /// 标题 + /// + public string title { get; set; } + /// + /// 机器人ID + /// + public string robot_name { get; set; } + + /// + /// 机器人类型 + /// + public ChatType robot_type { get; set; } + /// + /// 用户ID + /// + public long userid { get; set; } + + /// + /// 群号 + /// + public string groupid { get; set; } + + /// + /// 推广位ID + /// + public string adzoneid { get; set; } + + /// + /// 创建时间 + /// + public DateTime crt_time { get; set; } + + /// + /// 店铺ID + /// + public string mallid { get; set; } + + /// + /// 计算配置 + /// + public string compute_configdic { get; set; } + + /// + /// 是否通知多人 + /// + public bool is_multiple { get; set; } + } + + /// + /// 查询时的计算配置 + /// + public class Compute + { + /// + /// 返利类型 + /// + public SubsidyType SubsidyType { get; set; } + + /// + /// 是否为独立比例 + /// + public bool IsPrivateRatio { get; set; } + + /// + /// 补贴值 [为私人比例时:直接为比例,其他以系统设置补贴为准] + /// + public double Subsidy { get; set; } + + /// + /// 用户分组补贴类型 + /// + public SubsidyType GroupSubsidyType { get; set; } + + /// + /// 用户分组补贴值() + /// + public double GroupSubsidy { get; set; } + + /// + /// 系统设置的扣除类型 + /// + public AwardDepotType AwardDepot { get; set; } + + /// + /// 系统设置的一级提成 + /// + public int AwardOne { get; set; } + + /// + /// 系统设置的二级提成 + /// + public int AwardTwo { get; set; } + + /// + /// 系统设置的三级提成 + /// + public int AwardThree { get; set; } + + /// + /// 系统设置的群主提成 + /// + public int AwardCreator { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_query_ratio_info.cs b/类库/Api.Framework/Model/fl_query_ratio_info.cs new file mode 100644 index 0000000..37939f3 --- /dev/null +++ b/类库/Api.Framework/Model/fl_query_ratio_info.cs @@ -0,0 +1,37 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 查询历史比例 + /// + public class fl_query_ratio_hist : base_model + { + /// + /// 平台类型 + /// + public CpsType cpstype { get; set; } + + /// + /// 订单id + /// + public long db_orderid { get; set; } + + /// + /// 历史的计算比例 + /// + public string compute_config { get; set; } + + /// + /// 创建时间 + /// + public DateTime createtime { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_ratio_info.cs b/类库/Api.Framework/Model/fl_ratio_info.cs new file mode 100644 index 0000000..d83afd1 --- /dev/null +++ b/类库/Api.Framework/Model/fl_ratio_info.cs @@ -0,0 +1,41 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 分出比例 + /// + public class fl_ratio_info : base_model + { + /// + /// 佣金 + /// + [Category("属性编辑"), DisplayName("1.佣金条件"), Description("总佣金小于等于这个值,会采用该比例!")] + public double comm { get; set; } + + /// + /// 返点数值 + /// + [Category("属性编辑"), DisplayName("2.返利数值"), Description("满足条件的佣金,返利多少!")] + public double subsidy_num { get; set; } + + /// + /// 补贴类型 + /// + [Category("属性编辑"), DisplayName("3.返利类型"), DefaultValue(SubsidyType.百分比), Description("通过百分比,还是固定值返利!")] + public SubsidyType subsidy_type { get; set; } + + /// + /// CPS类型 + /// + [Category("属性编辑"), DisplayName("4.联盟类型"), Description("针对哪个联盟平台生效")] + public CpsType cps_type { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_ratio_info_custom.cs b/类库/Api.Framework/Model/fl_ratio_info_custom.cs new file mode 100644 index 0000000..c290725 --- /dev/null +++ b/类库/Api.Framework/Model/fl_ratio_info_custom.cs @@ -0,0 +1,76 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + public class fl_ratio_info_custom_group : base_model + { + [Browsable(false)] + private string _name = " "; + /// + /// 分组名称 + /// + [Category("独立分组编辑"), DisplayName("1.分组名称"), DefaultValue(""), Description("独立分组名称,自己用于区分独立分组")] + public string name + { + get { return _name; } + set + { + if (string.IsNullOrWhiteSpace(value)) + throw new Exception("请填写分组名"); + else + _name = value; + } + } + + /// + /// CPS类型 + /// + [Category("独立分组编辑"), DisplayName("2.联盟类型"), Description("针对哪个联盟平台生效"), ReadOnly(true)] + public CpsType cps_type { get; set; } + } + + + /// + /// 自定义分出比例 + /// + public class fl_ratio_info_custom : base_model + { + /// + /// 独立分组id + /// + [Browsable(false)] + public long cgid { get; set; } + /// + /// 佣金条件 + /// + [Category("属性编辑"), DisplayName("1.佣金条件"), Description("总佣金小于等于这个值,会采用该比例!")] + public double comm { get; set; } + + /// + /// 返点数值 + /// + [Category("属性编辑"), DisplayName("2.返利数值"), Description("满足条件的佣金,返利多少!")] + public double subsidy_num { get; set; } + + /// + /// 补贴类型 + /// + [Category("属性编辑"), DisplayName("3.返利类型"), DefaultValue(SubsidyType.百分比), Description("通过百分比,还是固定值返利!")] + public SubsidyType subsidy_type { get; set; } + + /// + /// CPS类型 + /// + //[Category("属性编辑"), DisplayName("4.联盟类型"), Description("针对哪个联盟平台生效"), ReadOnly(true)] + [Browsable(false)] + public CpsType cps_type { get; set; } + } + +} diff --git a/类库/Api.Framework/Model/fl_refund_hist_point.cs b/类库/Api.Framework/Model/fl_refund_hist_point.cs new file mode 100644 index 0000000..f11d04c --- /dev/null +++ b/类库/Api.Framework/Model/fl_refund_hist_point.cs @@ -0,0 +1,48 @@ +using Api.Framework.Enums; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 维权退款前的积分情况 + /// + public class fl_refund_hist_point : base_model + { + /// + /// 维权前积分情况 + /// + [SugarColumn(ColumnDataType = "text")] + public string db_point { get; set; } + + /// + /// 发生时间 + /// + public DateTime time { get; set; } + + /// + /// 订单号 + /// + public string orderid { get; set; } + + /// + /// 子订单号 + /// + public string orderid2 { get; set; } + + /// + /// 用户id + /// + public long userid { get; set; } + + /// + /// 账号类型 + /// + public CpsType cpstype { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_robot_info.cs b/类库/Api.Framework/Model/fl_robot_info.cs new file mode 100644 index 0000000..2a4bacf --- /dev/null +++ b/类库/Api.Framework/Model/fl_robot_info.cs @@ -0,0 +1,113 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 机器人信息 + /// + public class fl_robot_info : base_model + { + public override string ToString() + { + return $"{nick}({name})"; + } + + /// + /// 平台类型 + /// + public ChatType type { get; set; } + + /// + /// 机器人账号 + /// + public string name { get; set; } + + private string _nick; + /// + /// 机器人昵称 + /// + [SugarColumn(IsNullable = true)] + public string nick + { + get + { + return Util.RemoveEmoji(_nick); + } + set + { + _nick = value; + } + } + /// + /// 授权编号 + /// + public string uin { get; set; } + [SugarColumn(IsNullable = true, ColumnDataType = "text")] + public string remark { get; set; } + /// + /// token + /// + [SugarColumn(IsNullable = true, ColumnDataType = "text")] + public string token { get; set; } + /// + /// 是否登录 + /// + public bool is_login { get; set; } + /// + /// 创建时间 + /// + public DateTime crt_time { get; set; } + /// + /// 到期时间 + /// + public string end_time { get; set; } + /// + /// 是否接收消息 + /// + public SwitchType is_receives { get; set; } + /// + /// 离线通知 + /// + public SwitchType off_line_tip { get; set; } + + /// + /// 离线自动重登 + /// + public SwitchType off_line_auto_login { get; set; } + + public fl_robot_info() + { + this.uin = string.Empty; + this.crt_time = DateTime.Now; + this.end_time = string.Empty; + this.token = string.Empty; + this.name = string.Empty; + this.remark = string.Empty; + this.is_receives = SwitchType.开启; + this.off_line_tip = SwitchType.开启; + this.off_line_auto_login = SwitchType.开启; + } + + /// + /// 获取token + /// + /// + public object GetToken() + { + if (!string.IsNullOrEmpty(token)) + { + return CsharpHttpHelper.HttpExtend.JsonToDictionary(token); + } + return null; + } + } +} diff --git a/类库/Api.Framework/Model/fl_shpay_hist.cs b/类库/Api.Framework/Model/fl_shpay_hist.cs new file mode 100644 index 0000000..0659973 --- /dev/null +++ b/类库/Api.Framework/Model/fl_shpay_hist.cs @@ -0,0 +1,78 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 商户支付记录 + /// + public class fl_shpay_hist : base_model + { + /// + /// 机器人id + /// + public long rid { get; set; } + /// + /// 机器人账号 + /// + public string robotname { get; set; } + /// + /// 机器人昵称 + /// + public string robotnick { get; set; } + /// + /// 用户id + /// + public long uid { get; set; } + /// + /// 用户账号 + /// + public string username { get; set; } + /// + /// 用户昵称 + /// + public string usernick { get; set; } + /// + /// 平台 + /// + public ChatType chattype { get; set; } + /// + /// 提现金额 + /// + public double point { get; set; } + /// + /// 商户连接 + /// + public string payurl { get; set; } + /// + /// 商户orderid + /// + public string orderid { get; set; } + /// + /// 生成连接时间 + /// + public long ctime { get; set; } + /// + /// 生成日期 + /// + public long ctimedate { get; set; } + /// + /// 领取状态 + /// + public PayGetType paytype { get; set; } = PayGetType.未领取; + /// + /// 用户领取时间 + /// + public long paytime { get; set; } + /// + /// 通知发送时间 + /// + public long sendtime { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_statistics_record.cs b/类库/Api.Framework/Model/fl_statistics_record.cs new file mode 100644 index 0000000..ae218ba --- /dev/null +++ b/类库/Api.Framework/Model/fl_statistics_record.cs @@ -0,0 +1,86 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 用户基础记录 + /// + public class fl_statistics_record : base_model + { + /// + /// 用户id + /// + public long uid { get; set; } + + /// + /// 查询次数 + /// + public long querynum { get; set; } + + /// + /// 下级首单付款金额满足奖励上级(上级推荐) + /// + public long ex1 { get; set; } + + /// + /// 订单付款后奖励 + /// + public long ex2 { get; set; } + + /// + /// 首次查询时间 + /// + public long ex3 { get; set; } + + /// + /// 首次付款时间 + /// + public long ex4 { get; set; } + + /// + /// 最后付款时间 + /// + public long ex5 { get; set; } + + /// + /// + /// + public long ex6 { get; set; } + + /// + /// + /// + public long ex7 { get; set; } + + /// + /// + /// + public long ex8 { get; set; } + + /// + /// + /// + public long ex9 { get; set; } + + /// + /// + /// + public long ex10 { get; set; } + + /// + /// + /// + public long ex11 { get; set; } + + /// + /// + /// + public long ex12 { get; set; } + + } +} diff --git a/类库/Api.Framework/Model/fl_suning_tgw.cs b/类库/Api.Framework/Model/fl_suning_tgw.cs new file mode 100644 index 0000000..61cb514 --- /dev/null +++ b/类库/Api.Framework/Model/fl_suning_tgw.cs @@ -0,0 +1,32 @@ +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 苏宁推广位 + /// + public class fl_suning_tgw : base_model + { + /// + /// 会员名 + /// + public string username { get; set; } + + /// + /// 工具商关系pid + /// + public string toolpid { get; set; } + + /// + /// pid数据 + /// + [SugarColumn(ColumnDataType = "text")] + public string piddic { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_tb_relation.cs b/类库/Api.Framework/Model/fl_tb_relation.cs new file mode 100644 index 0000000..8e7f22f --- /dev/null +++ b/类库/Api.Framework/Model/fl_tb_relation.cs @@ -0,0 +1,30 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 淘宝关系类 + /// + public class fl_tb_relation : base_model + { + /// + /// cps账号 + /// + public string cps_memberid { get; set; } + + /// + /// 特别的id + /// + public long special_id { get; set; } + + /// + /// 用户对应的账号 + /// + public string username { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_uservariate_info.cs b/类库/Api.Framework/Model/fl_uservariate_info.cs new file mode 100644 index 0000000..b5f5e70 --- /dev/null +++ b/类库/Api.Framework/Model/fl_uservariate_info.cs @@ -0,0 +1,24 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 用户自定义全局变量 + /// + public class fl_uservariate_info : base_model + { + /// + /// 变量 + /// + public string variate { get; set; } + /// + /// 替换的数据 + /// + public string data { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_wechat_contacts.cs b/类库/Api.Framework/Model/fl_wechat_contacts.cs new file mode 100644 index 0000000..bd636c2 --- /dev/null +++ b/类库/Api.Framework/Model/fl_wechat_contacts.cs @@ -0,0 +1,69 @@ +using Api.Framework.Tools; +using Chat.Framework.WXSdk; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 联系人 + /// + public class fl_wechat_contacts : base_model + { + public int msg_type { get; set; } + /// + /// 账号 + /// + public string user_name { get; set; } + /// + /// 昵称 + /// + public string nick_name { get; set; } + /// + /// 签名 + /// + public string signature { get; set; } + /// + /// 小头像 + /// + public string smallheadimgurl { get; set; } + /// + /// 大头像 + /// + public string bigheadimgurl { get; set; } + /// + /// 省份 + /// + public string province { get; set; } + /// + /// 城市 + /// + public string city { get; set; } + /// + /// 备注 + /// + public string remark { get; set; } + /// + /// 微信号 + /// + public string alias { get; set; } + /// + /// 性别 + /// + public int sex { get; set; } + public int contacttype { get; set; } + public string chatroomowner { get; set; } + public string extinfo { get; set; } + /// + /// 是否为相互好友,值为空时为好友 + /// + public string ticket { get; set; } + /// + /// 版本 + /// + public string chatroomversion { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_wechat_device.cs b/类库/Api.Framework/Model/fl_wechat_device.cs new file mode 100644 index 0000000..883b361 --- /dev/null +++ b/类库/Api.Framework/Model/fl_wechat_device.cs @@ -0,0 +1,25 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 微信协议设备信息 + /// + public class fl_wechat_device:base_model + { + /// + /// 微信号 + /// + public string weixinhao { get; set; } + + /// + /// 设备信息 + /// + public string device_info { get; set; } + } +} diff --git a/类库/Api.Framework/Model/fl_weixin_password.cs b/类库/Api.Framework/Model/fl_weixin_password.cs new file mode 100644 index 0000000..ba9efb9 --- /dev/null +++ b/类库/Api.Framework/Model/fl_weixin_password.cs @@ -0,0 +1,77 @@ +using Chat.Framework.WXSdk; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 协议微信支付信息 + /// + public class fl_weixin_password : base_model_order + { + /// + /// 机器人编号 + /// + public long robot_id { get; set; } + + /// + /// 支付密码 + /// + public string password { get; set; } + + /// + /// 银行名称 + /// + public string bank_name { get; set; } + + /// + /// 银行序列号 + /// + public string bank_serial { get; set; } + + /// + /// 银行卡尾号 + /// + public string bank_tail { get; set; } + + /// + /// 银行卡类型 + /// + public string bank_type { get; set; } + + /// + /// 设置银行卡信息 + /// + /// + public void SetBank(BankCar bank) + { + if (bank != null) + { + bank_name = bank.bank_name; + bank_serial = bank.bind_serial; + bank_tail = bank.bind_tail; + bank_type = bank.bank_type; + } + else + { + bank_name = string.Empty; + bank_serial = string.Empty; + bank_tail = string.Empty; + bank_type = string.Empty; + } + } + + /// + /// 获得银行卡信息 + /// + /// + public BankCar GetBank() + { + if (string.IsNullOrEmpty(bank_name)) return null; + return new BankCar() { bank_name = bank_name, bank_type = bank_type, bind_serial = bank_serial, bind_tail = bank_tail }; + } + } +} diff --git a/类库/Api.Framework/Model/temp_send_data.cs b/类库/Api.Framework/Model/temp_send_data.cs new file mode 100644 index 0000000..b14c61e --- /dev/null +++ b/类库/Api.Framework/Model/temp_send_data.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Model +{ + /// + /// 发送消息临时类 + /// + public class temp_send_data + { + /// + /// 机器人ID + /// + public fl_robot_info Robot { get; set; } + + /// + /// 接收者账号 + /// + public string TouserName { get; set; } + + /// + /// 消息内容 + /// + public string Message { get; set; } + + /// + /// 接收群账号 + /// + public string Groupid { get; set; } + + /// + /// 如果为QQ这个值一定要赋值,为临时会话时,一定要传true + /// + public bool IsTemp { get; set; } + } +} diff --git a/类库/Api.Framework/NoticeSocketClient.cs b/类库/Api.Framework/NoticeSocketClient.cs new file mode 100644 index 0000000..9fa26e8 --- /dev/null +++ b/类库/Api.Framework/NoticeSocketClient.cs @@ -0,0 +1,199 @@ +using System; +using System.Linq; +using System.Text; +using System.Threading; +using System.Xml; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using WebSocket = WebSocketSharp.WebSocket; +using CsharpHttpHelper; + +namespace Api.Framework +{ + + /// + /// 通知客户端 + /// + public class NoticeSocketClient + { + /// + /// 发送Ack模式通知数据 + /// + public class AckNoticeData : EventArgs + { + /// + /// ID + /// + public string Id { get; set; } + /// + /// 命令ID + /// + public string CommonId { get; set; } + /// + /// 信号道 + /// + public string Channel { get; set; } + /// + /// 数据 + /// + public string Data { get; set; } + /// + /// 生成时间 + /// + public DateTime CreateDateTime { get; set; } + /// + /// 标记被删除 + /// + public bool IsRemove { get; set; } + /// + /// 重试 + /// + public bool IsRetry { get; set; } + } + + + /// + /// 构造函数 + /// + /// + /// + public NoticeSocketClient(string host, params string[] channel) + { + this._host = host; + this._channels = channel.ToArray(); + } + + private readonly string[] _channels; + private readonly string _host; + /// + /// 连接对象 + /// + private WebSocket _websocket; + + /// + /// 连接状态 + /// + public bool IsConnected => (_websocket != null && _websocket.IsAlive); + + /// + /// 连接 + /// + public void Connect() + { + if (IsConnected) + { + _websocket.OnOpen -= _websocket_OnOpen; + _websocket.OnMessage -= _websocket_OnMessage; + _websocket?.Close(); + } + + _websocket = new WebSocket($"ws://{this._host}/api/push?id={DateTime.Now.Ticks}"); + _websocket.OnOpen += _websocket_OnOpen; + _websocket.OnMessage += _websocket_OnMessage; + _websocket.Connect(); + + if (_thread == null) + { + _thread = new Thread(Ping) + { + IsBackground = true + }; + _thread.Start(); + } + } + + /// + /// 收到消息事件 + /// + public event EventHandler OnMessageEvent; + + /// + /// 连接成功事件 + /// + public event EventHandler OnConnectedEvent; + + private void _websocket_OnMessage(object sender, WebSocketSharp.MessageEventArgs e) + { + try + { + var index = e.Data.IndexOf("\u0000", StringComparison.Ordinal); + + if (index <= -1) + { + return; + } + + var commonId = e.Data.Substring(0, index); + if (commonId != "notice") return; + var body = e.Data.Substring(index + 1); + var data = JsonConvert.DeserializeObject(body); + if (data == null || string.IsNullOrEmpty(data.Id)) return; + this._websocket.Send("notice_ack\u0000" + data.Id); + OnMessageEvent?.Invoke(this, data); + } + catch (Exception ex) + { + Console.WriteLine($"即时通讯API接收异常:{ex.Message}"); + } + } + + private Thread _thread; + private void _websocket_OnOpen(object sender, System.EventArgs e) + { + try + { + foreach (var v in this._channels) + { + this._websocket.Send($"subchannel\u0000{v}");//订阅通道 + } + this.OnConnectedEvent?.Invoke(this, EventArgs.Empty); + } + catch (Exception ex) + { + Console.WriteLine($"即时通讯API连接异常:{ex.Message}"); + } + } + private void Ping() + { + while (true) + { + Thread.Sleep(1000 * 10); + try + { + //测试ping是否正常 + if (this._websocket.Ping()) continue; + + //断开自动重连 + this.Connect(); + } + catch (Exception e) + { + Console.WriteLine($"即时通讯API Ping异常:{e.Message}"); + } + } + // ReSharper disable once FunctionNeverReturns + } + + /// + /// 获取数据 + /// + /// + /// + public string GetData(string key) + { + var http = new HttpHelper(); + var html = http.GetHtml($"http://{this._host}/api/TransferData/Get?key={key}&rd={DateTime.Now.Ticks}").Html; + var rest = JObject.Parse(html); + //if (!(rest["Ok"] ?? false).Value() throw new Exception(html); + //return (rest["Data"] ?? string.Empty).Value(); + + //EventClient.OnEvent($"获取淘客域名数据", $"{html}"); + + if (!(rest["Ok"] ?? false).Value()) + throw new Exception(html); + return (rest["Data"] ?? string.Empty).Value(); + + } + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/PluginClient.cs b/类库/Api.Framework/PluginClient.cs new file mode 100644 index 0000000..96b43c5 --- /dev/null +++ b/类库/Api.Framework/PluginClient.cs @@ -0,0 +1,619 @@ +using Api.Framework.Events; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; +using static System.Net.Mime.MediaTypeNames; +using System.Windows.Forms; +namespace Api.Framework +{ + /// + /// 插件管理 + /// + public class PluginClient + { + /// + /// 插件集合 + /// + public static List Plugins { get; private set; } + /// + /// 插件AES加密 + /// + private static byte[] Iv, Key; + + static PluginClient() + { + Plugins = new List(); + Key = new byte[] { 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 }; + Iv = new byte[] { 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }; + } + + /// + /// 获取插件新版本 + /// + /// 需要获取的插件 + public static List FindVersion(Plugin plugin) + { + if (string.IsNullOrEmpty(plugin.VersionXML)) return null; + List versions = new List(); + + Util util = new Util(); + var doc = new XmlDocument(); + doc.Load(plugin.VersionXML); + var nodes = doc.SelectNodes("Version"); + foreach (XmlNode item in nodes) + { + var v = new PluginVersion() + { + CurMessage = item["CurMessage"].ToString(), + CurVersion = Version.Parse(item["CurVersion"].ToString()), + SoftVersion = Version.Parse(item["SoftVersion"].ToString()), + DownURL = item["DownURL"].ToString() + }; + versions.Add(v); + } + versions.OrderByDescending(p => p.CurVersion); + return versions; + } + + /// + /// 将指定文件的转换成插件,并保存 + /// + /// 文件路径 + /// + public static Plugin FileConvertPlugin(string filePath) + { + if (!File.Exists(filePath)) throw new Exception("文件不存在,请查证。"); + if (filePath.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase)) + { + Util util = new Util(); + string fileName = Path.GetFileName(filePath); + string path = filePath.Substring(0, filePath.Length - 4); + byte[] inputBuffer = util.ReadFile(filePath);// File.ReadAllBytes(filePath); + Assembly al = ConvertAssembly(inputBuffer); + Plugin p = null; + if (al != null) + { + p = ConvertPlugin(al); + if (p == null) + throw new Exception("该文件不能不符合插件接口标准!"); + // string filep = Path.Combine(Util.MapPath("Plugin"), fileName.Substring(0, fileName.Length - 4) + ".plugin"); + string savePath = path + ".plugin"; + byte[] bytes = Aes.Create().CreateEncryptor(Key, Iv).TransformFinalBlock(inputBuffer, 0, inputBuffer.Length); + File.WriteAllBytes(savePath, bytes); + p.CurVersion = al.GetName().Version; + p.FilePath = savePath; + return p; + } + else + throw new Exception("该文件不能不符合插件接口标准。"); + } + else if (filePath.EndsWith(".plugin", StringComparison.CurrentCultureIgnoreCase)) + { + var plugin = GetPlugin(filePath); + if (plugin == null) throw new Exception("该文件不能不符合插件接口标准。"); + return plugin; + } + else + throw new Exception("该文件不能不符合插件接口标准。"); + } + + /// + /// 加载插件 + /// + /// 重新加载 + public static void LodingPlugin(bool reload = false) + { + EventClient.StopParsing = true; + ApiClient.GetSession().Context.Utilities.RemoveCacheAll(); + Task.Factory.StartNew(delegate + { + try + { + if (reload) + { + ApiClient.Cache.Cleaner(); + lock (Plugins) + { + foreach (var item in Plugins) + { + try + { + item.Stop(); + item.Dispose(); + } + catch (Exception ex) + { + EventClient.OnEvent(item, $"停止失败{item.Name}:{ex.Message}"); + } + } + + Plugins.Clear(); + } + } + string[] plugin_files = Directory.GetFiles(Util.MapPath("Plugin", true), "*.plugin", SearchOption.TopDirectoryOnly); + string[] dll_files = Directory.GetFiles(Util.MapPath("Plugin", true), "*.dll", SearchOption.TopDirectoryOnly); + List pluginFiles = new List(); + pluginFiles.AddRange(plugin_files); + pluginFiles.AddRange(dll_files); + lock (Plugins) + { + foreach (var item in pluginFiles) + { + try + { + var p = GetPlugin(item); + if (p == null) + continue; + else + { + #region 显示的插件,不显示的continue了 + if (ApiClient.ShowPluginList != null) + { + if (!p.FilePath.ToLower().Contains("\\main.dll")) + { + var flag = ApiClient.ShowPluginList.FirstOrDefault(f => p.FilePath.Contains(f)); + if (string.IsNullOrWhiteSpace(flag)) + { + p?.Stop(); + continue; + } + } + } + #endregion + + + Plugin oldPlugin = Plugins.FirstOrDefault(f => f.GetType().ToString() == p.GetType().ToString()); + if (oldPlugin != null)//发现旧插件 + { + if (oldPlugin.FilePath != item)//可是路径不相同 + { + EventClient.OnEvent("插件系统", new Events.LogEvents("文件:" + oldPlugin.FilePath + "与" + p.FilePath + "冲突!") { }); + } + else + { + if (oldPlugin.Md5 != p.Md5) + { + Plugins.Remove(oldPlugin); + Plugins.Add(p); + bool isStart = (oldPlugin.IsRun ? true : false); + + if (isStart) + { + oldPlugin.Stop(); + oldPlugin.Dispose(); + p.Start(); + p.IsRun = true; + } + } + //else + //{ + // if (!p.IsNet) + // { + // DynnamicDLL dll = p as DynnamicDLL; + // if (dll != null) + // { + + // dll.Dispose(); + // } + // } + //} + // p.Level = oldPlugin.Level; + } + } + else + { + p.Level = int.MaxValue; + Plugins.Add(p); + } + } + } + catch (Exception e) + { + EventClient.OnEvent(null, new Events.LogEvents("处理文件:" + item + ",发生异常:" + e.Message) { Exception = e }); + } + } + + var _plugins = ApiClient.Setting.Plugins; + for (int i = 1; i <= _plugins.Count; i++) + { + Plugin plugin = Plugins.FirstOrDefault(f => f.GetType().ToString() == _plugins[i - 1].ToString()); + if (plugin != null) + { + try + { + plugin.Level = i; + if (!plugin.IsRun) + { + plugin.Level = i; + plugin.Start(); + plugin.IsRun = true; + } + } + catch (Exception e) + { + EventClient.OnEvent(null, new Events.LogEvents(string.Format("启动“{0}”插件失败:{1}", plugin.Name, e.Message)) { Exception = e }); + plugin.IsRun = false; + } + } + } + Plugins.Sort(); + } + EventClient.OnEvent(null, MethodType.刷新应用); + } + catch (Exception ex) + { + //Console.WriteLine(); + } + finally + { + EventClient.StopParsing = false; + } + }); + } + + /// + /// 更新插件 + /// + /// 版本 + /// + public static bool UpdatePlugin(PluginVersion version) + { + return false; + } + + /// + /// 添加插件 + /// + /// 插件路径 + /// + public static Plugin AddPlugin(string filePath) + { + try + { + Plugin p = FileConvertPlugin(filePath); + Plugin o = Plugins.FirstOrDefault(f => f.GetType().ToString() == p.GetType().ToString()); + if (o != null) + { + lock (Plugins) + { + try + { + if (o.IsRun) + { + o.Stop(); + // o.UnInstall(); + o.Dispose(); + } + p.Level = o.Level; + Plugins.Remove(o); + Plugins.Add(p); + if (o.IsRun) + { + // p.Install(); + p.Start(); + p.IsRun = true; + } + + return p; + } + catch (Exception e) + { + throw new Exception(string.Format("更新插件“{0}”出错:{1}", p.FilePath, e.Message)); + } + } + } + else + { + lock (Plugins) + { + Plugins.Add(p); + } + EventClient.OnEvent(null, MethodType.刷新应用); + return p; + } + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 插件安装 + /// + /// 要安装的插件对象 + public static void Install(Plugin plugin) + { + string type = plugin.GetType().ToString(); + plugin.Start(); + plugin.IsRun = true; + int level = ApiClient.Setting.Plugins.IndexOf(type); + plugin.Level = (level == -1 ? ApiClient.Setting.Plugins.Count : level); + + if (!ApiClient.Setting.Plugins.Contains(plugin.GetType().ToString())) + ApiClient.Setting.Plugins.Add(type); + SavePlugin(); + } + + /// + /// 插件卸载 + /// + /// 要卸载的插件对象 + public static void UnInstall(Plugin plugin) + { + if (plugin.IsRun) + { + try + { + plugin.IsRun = false; + plugin.Level = 1000; + plugin.Stop(); + plugin.Dispose(); + plugin._SDK = null; + } + catch { } + string type = plugin.GetType().ToString(); + if (ApiClient.Setting.Plugins.Contains(type)) + { + ApiClient.Setting.Plugins.Remove(type); + SavePlugin(); + } + } + } + + /// + /// 删除插件 + /// + /// 要删除的插件对象 + public static void Delete(Plugin plugin) + { + try + { + string type = plugin.GetType().ToString(); + lock (Plugins) + { + UnInstall(plugin); + if (Plugins.Contains(plugin)) + { + Plugins.Remove(plugin); + } + plugin.Dispose(); + if (ApiClient.Setting.Plugins.Contains(type)) + { + ApiClient.Setting.Plugins.Remove(type); + SavePlugin(); + } + if (File.Exists(plugin.FilePath)) + File.Delete(plugin.FilePath); + + } + EventClient.OnEvent(null, MethodType.刷新应用); + } + catch (Exception) + { } + } + + /// + /// 保存修通配置 + /// + private static void SavePlugin() + { + Util.Save(ApiClient.Setting.Plugins, "系统.插件配置"); + } + + /// + /// 调换插件顺序 + /// + /// 被调换的插件下标 + /// 需要调换的插件下标 + public static void MovePlugin(int plugin1, int plugin2) + { + try + { + var plugin = Plugins[plugin1]; + + Plugins.Remove(plugin); + if (plugin2 > Plugins.Count) + Plugins.Insert(Plugins.Count, plugin); + else if (plugin2 < 0) + Plugins.Insert(0, plugin); + else + Plugins.Insert(plugin2, plugin); + + ApiClient.Setting.Plugins.Clear(); + int i = 0; + foreach (var item in Plugins) + { + i++; + if (item.IsRun) + ApiClient.Setting.Plugins.Add(item.GetType().ToString()); + } + SavePlugin(); + } + catch (Exception) + { } + } + public static string MovePlugin(Plugin plugin1, Plugin plugin2) + { + try + { + if (plugin1 == plugin2) + return "插件不能相同!"; + if (!Plugins.Contains(plugin1) || !Plugins.Contains(plugin2)) + return "插件不存在!"; + int level = plugin1.Level; + plugin1.Level = plugin2.Level; + plugin2.Level = level; + + int p1 = -1; + int p2 = -1; + for (int i = 0; i < Plugins.Count; i++) + { + if (Plugins[i] == plugin1) + p1 = i; + else if (Plugins[i] == plugin2) + p2 = i; + if (p1 != -1 && p2 != -1) + break; + } + if (p1 != -1 && p2 != -1) + { + var temp = Plugins[p1]; + Plugins[p1] = Plugins[p2]; + Plugins[p2] = temp; + Plugins.Sort(); + + ApiClient.Setting.Plugins.Clear(); + foreach (Plugin item in Plugins) + { + if (item.IsRun) + ApiClient.Setting.Plugins.Add(item.GetType().ToString()); + } + SavePlugin(); + return null; + } + else + return "没有找到元素位置!"; + } + catch (Exception) + { } + return null; + } + + #region 私有函数 + /// + /// 寻找一个程序集 + /// + /// 文件路径 + /// + private static Assembly FindAssembly(string path) + { + Util util = new Util(); + Assembly assembly = null; + try + { + if (string.IsNullOrWhiteSpace(path) || !System.IO.File.Exists(path)) + { + return assembly; + } + + if (path.EndsWith(".plugin", StringComparison.CurrentCultureIgnoreCase)) + { + byte[] inputBuffer = util.ReadFile(path); + byte[] mingwen = Aes.Create().CreateDecryptor(Key, Iv).TransformFinalBlock(inputBuffer, 0, inputBuffer.Length); + assembly = Assembly.Load(mingwen); + } + else if (path.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase)) + { + assembly = Assembly.Load(util.ReadFile(path)); + } + } + catch { } + return assembly; + } + + /// + /// 通过文件路径获取插件对象 + /// + /// 文件路径 + /// + private static Plugin GetPlugin(string filePath) + { + try + { + var al = FindAssembly(filePath); + if (al != null) + { + var plugin = ConvertPlugin(al); + if (plugin != null) + { + plugin.FilePath = filePath; + plugin.Md5 = (Util.GetFileMd5Code(filePath)); + return plugin; + } + } + else + { + //try + //{ + // DynnamicDLL dll = ConvertDynnamicDLL(fileName); + // if (dll == null) + // { + // throw new Exception("无法识别动态连DLL!"); + // } + // if (dll.CheckDLL()) + // { + // return dll; + // } + // else + // { + // throw new Exception("无法正确识别插件信息!"); + // } + + //} + //catch (Exception ex) + //{ + // Client.ClientPro.OnLog("插件系统","转换插件异常:" + ex.Message + "," + fileName); + //} + } + } + catch (Exception) + { } + return null; + } + + /// + /// 将字节集转换成 程序集 + /// + /// + /// + private static Assembly ConvertAssembly(byte[] body) + { + try + { + return Assembly.Load(body); + } + catch (Exception) + { } + return null; + } + + /// + /// 将程序集转换成Plugin + /// + /// + /// + private static Plugin ConvertPlugin(Assembly assembly) + { + try + { + if (assembly != null) + { + foreach (System.Type type in assembly.GetTypes()) + { + if (type.IsSubclassOf(typeof(Plugin))) + { + Plugin plugin = (Activator.CreateInstance(type) as Plugin); + plugin.CurVersion = assembly.GetName().Version; + return plugin; + } + } + } + } + catch (Exception e) + { } + return null; + } + #endregion + + } +} diff --git a/类库/Api.Framework/Properties/AssemblyInfo.cs b/类库/Api.Framework/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a96697c --- /dev/null +++ b/类库/Api.Framework/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Api.Framework")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Api.Framework")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("dfc8cd58-a475-4ebb-8a0e-0f1ee71eda07")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/类库/Api.Framework/Properties/Resources.Designer.cs b/类库/Api.Framework/Properties/Resources.Designer.cs new file mode 100644 index 0000000..043a3b5 --- /dev/null +++ b/类库/Api.Framework/Properties/Resources.Designer.cs @@ -0,0 +1,156 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Api.Framework.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Api.Framework.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap foot { + get { + object obj = ResourceManager.GetObject("foot", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找类似 京东返利 的本地化字符串。 + /// + internal static string JdSoftwareType { + get { + return ResourceManager.GetString("JdSoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 快手返利 的本地化字符串。 + /// + internal static string KsSoftwareType { + get { + return ResourceManager.GetString("KsSoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 拼多多返利 的本地化字符串。 + /// + internal static string PddSoftwareType { + get { + return ResourceManager.GetString("PddSoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 苏宁返利 的本地化字符串。 + /// + internal static string SNSoftwareType { + get { + return ResourceManager.GetString("SNSoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 全额免单 的本地化字符串。 + /// + internal static string TbAllRebatesSoftwareType { + get { + return ResourceManager.GetString("TbAllRebatesSoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 淘宝返利 的本地化字符串。 + /// + internal static string TbSoftwareType { + get { + return ResourceManager.GetString("TbSoftwareType", resourceCulture); + } + } + + /// + /// 查找类似 唯品会返利 的本地化字符串。 + /// + internal static string WphSoftwareType { + get { + return ResourceManager.GetString("WphSoftwareType", resourceCulture); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 模板B { + get { + object obj = ResourceManager.GetObject("模板B", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 模板C { + get { + object obj = ResourceManager.GetObject("模板C", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/类库/Api.Framework/Properties/Resources.resx b/类库/Api.Framework/Properties/Resources.resx new file mode 100644 index 0000000..8f35676 --- /dev/null +++ b/类库/Api.Framework/Properties/Resources.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\foot.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 淘宝返利 + fl_adzone_info自定义类型(custom_type)淘宝返利 + + + 拼多多返利 + fl_adzone_info自定义类型(custom_type)拼多多返利 + + + 京东返利 + fl_adzone_info自定义类型(custom_type)京东返利 + + + ..\Resources\模板B.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 全额免单 + fl_adzone_info自定义类型(custom_type)淘宝全额返利 + + + ..\Resources\优惠券C.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + 唯品会返利 + fl_adzone_info自定义类型(custom_type)唯品会返利 + + + 苏宁返利 + fl_adzone_info自定义类型(custom_type)苏宁返利 + + + 快手返利 + fl_adzone_info自定义类型(custom_type)快手返利 + + \ No newline at end of file diff --git a/类库/Api.Framework/Properties/licenses.licx b/类库/Api.Framework/Properties/licenses.licx new file mode 100644 index 0000000..81c8e65 --- /dev/null +++ b/类库/Api.Framework/Properties/licenses.licx @@ -0,0 +1,3 @@ +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/类库/Api.Framework/Resources/VersionUpdate.xml b/类库/Api.Framework/Resources/VersionUpdate.xml new file mode 100644 index 0000000..1b886fb --- /dev/null +++ b/类库/Api.Framework/Resources/VersionUpdate.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/类库/Api.Framework/Resources/bitbug_favicon-2.ico b/类库/Api.Framework/Resources/bitbug_favicon-2.ico new file mode 100644 index 0000000..234a014 Binary files /dev/null and b/类库/Api.Framework/Resources/bitbug_favicon-2.ico differ diff --git a/类库/Api.Framework/Resources/favicon-20180629034329926.ico b/类库/Api.Framework/Resources/favicon-20180629034329926.ico new file mode 100644 index 0000000..76829b1 Binary files /dev/null and b/类库/Api.Framework/Resources/favicon-20180629034329926.ico differ diff --git a/类库/Api.Framework/Resources/foot.png b/类库/Api.Framework/Resources/foot.png new file mode 100644 index 0000000..1df2d61 Binary files /dev/null and b/类库/Api.Framework/Resources/foot.png differ diff --git a/类库/Api.Framework/Resources/sxds.png b/类库/Api.Framework/Resources/sxds.png new file mode 100644 index 0000000..2307337 Binary files /dev/null and b/类库/Api.Framework/Resources/sxds.png differ diff --git a/类库/Api.Framework/Resources/优惠券C.jpg b/类库/Api.Framework/Resources/优惠券C.jpg new file mode 100644 index 0000000..4e5e0bd Binary files /dev/null and b/类库/Api.Framework/Resources/优惠券C.jpg differ diff --git a/类库/Api.Framework/Resources/模板B.jpg b/类库/Api.Framework/Resources/模板B.jpg new file mode 100644 index 0000000..1bdb314 Binary files /dev/null and b/类库/Api.Framework/Resources/模板B.jpg differ diff --git a/类库/Api.Framework/SDK/Config.cs b/类库/Api.Framework/SDK/Config.cs new file mode 100644 index 0000000..c2b70ce --- /dev/null +++ b/类库/Api.Framework/SDK/Config.cs @@ -0,0 +1,76 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; +using System.Web.Script.Serialization; +using System.Windows.Forms; + +namespace Api.Framework.SDK +{ + /// + /// 配置文件属性 + /// + public class ConfigAttribute : Attribute + { + /// + /// 保存的文件名 + /// + public string Name { get; set; } + + /// + /// 是否存档到数据库 + /// + public bool IsSaveDB { get; set; } + + + private byte[] _encKey; + /// + /// 16位密钥 - 不填写则使用系统秘钥 + /// + public byte[] EncKey + { + get { return _encKey; } + set + { + if (value != null) + { + if (value.Length != 16) throw new Exception("长度必须等于16字节!"); + _encKey = value; + } + } + } + + /// + /// 是否加密数据信息 默认为False + /// + public bool IsEncryption { get; set; } + public ConfigAttribute() + { + this.IsSaveDB = true; + this._encKey = new byte[16]; + } + + } + + /// + /// 配置属性 + /// + public class ParamAttribute : Attribute + { + /// + /// 标签信息 - 一般表示变量 + /// + public string[] Tags { get; set; } + + /// + /// 描述信息 + /// + public string Describe { get; set; } + + } +} diff --git a/类库/Api.Framework/SDK/MemberPointChangeEvent.cs b/类库/Api.Framework/SDK/MemberPointChangeEvent.cs new file mode 100644 index 0000000..65f0de3 --- /dev/null +++ b/类库/Api.Framework/SDK/MemberPointChangeEvent.cs @@ -0,0 +1,26 @@ +using Api.Framework.Events; +using Api.Framework.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.SDK +{ + /// + /// 用户积分变动事件 + /// + public class MemberPointChangeEvent : BaseEvents + { + /// + /// 修改积分信息 + /// + public fl_point_hist Point { get; private set; } + + public MemberPointChangeEvent(fl_point_hist point) + { + this.Point = point; + } + } +} diff --git a/类库/Api.Framework/SDK/Plugin.cs b/类库/Api.Framework/SDK/Plugin.cs new file mode 100644 index 0000000..7910f8e --- /dev/null +++ b/类库/Api.Framework/SDK/Plugin.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Api.Framework.SDK +{ + /// + /// 插件版本 + /// + public class PluginVersion + { + /// + /// 软件最低版本 + /// + public Version SoftVersion { get; set; } + + /// + /// 当前版本号 + /// + public Version CurVersion { get; set; } + + /// + /// 当前版本更新内容 + /// + public string CurMessage { get; set; } + + /// + /// 下载地址 + /// + public string DownURL { get; set; } + } + + /// + /// 插件基础类 - 插件开发继承后重写 + /// + public class Plugin : IDisposable, IComparable + { + internal SDKEvent _SDK { get; set; } + /// + /// 事件 + /// + public SDKEvent SDK + { + get + { + if (_SDK == null) + { + _SDK = new SDKEvent(this); + } + return _SDK; + } + } + + //public bool IsNet { get; internal set; } + + /// + /// 插件名称 + /// + public string Name { get; set; } + + /// + /// 插件简介 + /// + public string Note { get; set; } + + /// + /// XML版本信息 + /// + public string VersionXML { get; set; } + + /// + /// 当前版本号 + /// + public Version CurVersion { get; internal set; } + /// + /// 文件路径 + /// + public string FilePath { get; internal set; } + + /// + /// 插件MD5信息 + /// + public string Md5 { get; internal set; } + + /// + /// 插件顺序 + /// + public int Level { get; internal set; } + + public bool IsRun { get; internal set; } + + /// + /// 插件图标 + /// + public Image Logo { get; set; } + + + public void Dispose() + { + + } + + ///// + ///// 安装s + ///// + //public virtual void Install() { } + ///// + ///// 卸载 + ///// + //public virtual void UnInstall() { } + + /// + /// 启动 + /// + public virtual void Start() { } + + /// + /// 窗体 + /// + public virtual void ShowForm() + { + MessageBox.Show("这个插件没有设置窗口!", "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + /// + /// 停用 + /// + public virtual void Stop() { } + + public int CompareTo(object obj) + { + try + { + Plugin info = obj as Plugin; + string str = obj.GetType().ToString(); + //Console.WriteLine(); + if (str == "AutoAnswer.Class1") return -1; + else if (this.GetType().ToString() == "AutoAnswer.Class1") return 1; + + + if (str == "MessageSupervises.Class1") return 1; + else if (this.GetType().ToString() == "MessageSupervises.Class1") return -1; + + if (this.Level < info.Level) + return -1; + if (this.Level == info.Level) + return 0; + else + return 1; + + } + catch (Exception) { return 0; } + + } + + } +} diff --git a/类库/Api.Framework/SDK/PluginExtend.cs b/类库/Api.Framework/SDK/PluginExtend.cs new file mode 100644 index 0000000..71214e0 --- /dev/null +++ b/类库/Api.Framework/SDK/PluginExtend.cs @@ -0,0 +1,84 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.SDK +{ + /// + /// 插件扩展类 + /// + public static class PluginExtend + { + /// + /// 输出日志 + /// + /// + /// 日志内容 + public static void OnLog(this Plugin plugin, string message) + { + EventClient.OnEvent(plugin, new Framework.Events.LogEvents("【" + plugin.Name + "】" + message)); + } + + /// + /// 读入配置 + /// + /// + /// + /// + public static T ReadConfig(this Plugin plugin) + { + var t = Util.Read(); + //System.Drawing.Color c = new System.Drawing.Color(); + return t; + } + + /// + /// 保存配置 + /// + /// + /// 保存的对象 + public static void SaveConfig(this Plugin plugin, Object obj) + { + Util.Save(obj); + } + + + /// + /// 反射获取某个对象属性的值 + /// + /// 对象 + /// 对象中的属性 + /// + public static object FindPropertyValue(this Object obj, string name) + { + var _type = obj.GetType(); + var _prot = _type.GetProperties(); + foreach (System.Reflection.PropertyInfo p in _prot) + { + if (name == p.Name) return p.GetValue(obj); + } + return null; + } + + /// + /// 反射获取某个对象属性信息 + /// + /// 对象 + /// 对象中的属性 + /// + public static System.Reflection.PropertyInfo FindPropertyInfo(this Object obj, string name) + { + var _type = obj.GetType(); + var _prot = _type.GetProperties(); + foreach (System.Reflection.PropertyInfo p in _prot) + { + if (name == p.Name) return p; + } + return null; + } + + } +} diff --git a/类库/Api.Framework/SDK/ReciveIMEvent.cs b/类库/Api.Framework/SDK/ReciveIMEvent.cs new file mode 100644 index 0000000..fe4850f --- /dev/null +++ b/类库/Api.Framework/SDK/ReciveIMEvent.cs @@ -0,0 +1,501 @@ +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.Tools; +using Chat.Framework.QQSdk.QPlus; +using Chat.Framework.Utils; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Implement; +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.SDK +{ + /// + /// 平台类型 + /// + public enum ChatType : int + { + 未知来源 = 0, + QQ = 1, + 微信 = 2, + 微信公众号 = 3, + 企业微信 = 4 + } + + /// + /// 通用消息事件 + /// + public class ReciveIMEvent : BaseEvents + { + /// + /// 事件来源(机器人),强转即可 (注:机器人基类为:WeixinBase) + /// + public object Sender { get; private set; } + /// + /// 事件原形 + /// + public object Event { get; private set; } + /// + /// 消息 + /// + public string Message { get; private set; } + /// + /// 发送者昵称 + /// + public string NickName { get; private set; } + /// + /// 发送者原始昵称 + /// + public string RealNick { get; set; } + /// + /// 微信号 + /// + public string Wechatid { get; set; } + /// + /// 发送者账号 + /// + public string Username { get; private set; } + + /// + /// 用户头像地址 + /// + public string HeadUrl { get; private set; } + + /// + /// 群号,私聊为空 + /// + public string Groupid { get; private set; } + /// + /// 机器人类型 + /// + public ChatType ChatType { get; private set; } + /// + /// 机器人账号 + /// + public string RobotName { get; private set; } + /// + /// 机器人账号 + /// + public string RobotNick { get; private set; } + + private fl_robot_info _robotinfo; + /// + /// 机器人对象 + /// + public fl_robot_info RobotInfo + { + get + { + if (_robotinfo == null) + { + var session = ApiClient.GetSession(); + _robotinfo = session.FindRobotInfo(RobotName, ChatType); + } + return _robotinfo; + } + } + + private fl_member_info fl_member_info; + + /// + /// 获取用户对象方法 + /// + /// 刷新 + /// + public fl_member_info GetMemberinfo(bool refresh = false) + { + bool is_first = fl_member_info == null ? true : false; + if (refresh || fl_member_info == null || string.IsNullOrWhiteSpace(fl_member_info.headurl)) + { + var session = ApiClient.GetSession(); + this.fl_member_info = session.FindMemberinfo(this); + if (this.fl_member_info != null) + { + if (is_first || string.IsNullOrWhiteSpace(fl_member_info.headurl)) + { + if (is_first) + this.fl_member_info.chat_count++; + if (string.IsNullOrWhiteSpace(fl_member_info.headurl)) + fl_member_info.headurl = HeadUrl; + session.SaveOrUpdate(this.fl_member_info); + } + } + } + return this.fl_member_info; + } + + /// + /// 事件Type + /// + public Type EventType { get; private set; } + + /// + /// 通用解析 + /// + /// + /// + public ReciveIMEvent(object Sender, object Event) + { + if (Sender.GetType() == typeof(Chat.Framework.WXSdk.Implement.WXClientImpl_IPAD)) + { + var client = Sender as Chat.Framework.WXSdk.Implement.WXClientImpl_IPAD; + + this.RobotName = client.WeixinHao; + this.RobotNick = client.User.Nick; + this.ChatType = ChatType.微信; + } + else if (Sender.GetType() == typeof(QQClientImpl_QQPlus)) + { + var client = Sender as QQClientImpl_QQPlus; + this.RobotName = client.QQClient.User.QQ.ToString(); + this.RobotNick = Util.RemoveEmoji(client.QQClient.User.NickName); + this.ChatType = ChatType.QQ; + } + else if (Sender.GetType() == typeof(Chat.Framework.WXSdk.Implement.WXClientImpl_HOOK)) + { + var client = Sender as Chat.Framework.WXSdk.Implement.WXClientImpl_HOOK; + this.RobotName = client.WeixinHao; + this.RobotNick = Util.RemoveEmoji(client.User.Nick); + this.ChatType = ChatType.微信; + } + else if (Sender.GetType() == typeof(Chat.Framework.WXSdk.Implement.WXClientImpl_QYHOOK)) + { + var client = Sender as Chat.Framework.WXSdk.Implement.WXClientImpl_QYHOOK; + this.RobotName = client.WeixinHao; + this.RobotNick = Util.RemoveEmoji(client.User.Nick); + this.ChatType = ChatType.企业微信; + } + + this.Groupid = string.Empty; + this.Sender = Sender; + this.Event = Event; + //Console.WriteLine(Event.GetType().ToString()); + this.EventType = Event.GetType(); + if (EventType == typeof(Chat.Framework.QQSdk.Events.QQReceiveFriendMsgEvents)) + { + this.ChatType = ChatType.QQ; + var e = Event as Chat.Framework.QQSdk.Events.QQReceiveFriendMsgEvents; + this.NickName = Util.RemoveEmoji(e.Nickname); + this.Message = e.Message; + this.RealNick = Util.RemoveEmoji(e.Nickname); + this.Username = e.QQ.ToString(); + this.Wechatid = string.Empty; + this.HeadUrl = this.HeadUrl = $"http://q1.qlogo.cn/g?b=qq&nk={e.QQ}&s=640"; + } + //else if (EventType == typeof(Chat.Framework.PCRobotSDK.WechatEvents.WechatReceiveMsgEvents)) + //{ + // ChatType = ChatType.微信; + // var evt = Event as Chat.Framework.PCRobotSDK.WechatEvents.WechatReceiveMsgEvents; + // this.RobotName = evt.Data.RobotUsername; + // this.RobotNick = Util.RemoveEmoji(evt.Data.RobotUsernick); + // this.NickName = Util.RemoveEmoji(evt.Data.FromUsernick == null ? string.Empty : evt.Data.FromUsernick); //evt.Data.FromUsernick; + // this.Username = evt.Data.FromUsername; + // this.Message = evt.Data.FromMessage; + // this.Groupid = evt.Data.FromGroupid; + //} + else if (EventType == typeof(Chat.Framework.QQSdk.Events.QQReceiveGroupMsgEvents)) + { + this.ChatType = ChatType.QQ; + var e = Event as Chat.Framework.QQSdk.Events.QQReceiveGroupMsgEvents; + this.NickName = Util.RemoveEmoji(e.Nickname == null ? string.Empty : e.Nickname); + this.Message = e.Message; + this.RealNick = Util.RemoveEmoji(e.Nickname == null ? string.Empty : e.Nickname); + this.Groupid = e.GroupId.ToString(); + this.Username = e.QQ.ToString(); + this.Wechatid = string.Empty; + this.HeadUrl = $"http://q1.qlogo.cn/g?b=qq&nk={e.QQ}&s=640"; + } + else if (EventType == typeof(Chat.Framework.WXSdk.Events.WXReceiveGroupMsg)) + { + var e = Event as Chat.Framework.WXSdk.Events.WXReceiveGroupMsg; + this.RobotName = e.Client.WeixinHao; + this.Message = e.Message; + + var realNick = e.Member.NickName; + var nick = e.Member.GetName(); + if (string.IsNullOrWhiteSpace(Util.RemoveEmoji(nick))) + { + Friend friend = null; + if (Sender.GetType() == typeof(WXClientImpl_HOOK)) + { + var wx = Sender as WXClientImpl_HOOK; + friend = wx.Friends.FirstOrDefault(f => f.Key == e.Member.Username).Value; + } + else if (Sender.GetType() == typeof(WXClientImpl_QYHOOK)) + { + var wx = Sender as WXClientImpl_QYHOOK; + friend = wx.Friends.FirstOrDefault(f => f.Key == e.Member.Username).Value; + } + else if (Sender.GetType() == typeof(WXClientImpl_IPAD)) + { + var wx = Sender as WXClientImpl_IPAD; + friend = wx.Friends.FirstOrDefault(f => f.Key == e.Member.Username).Value; + } + if (friend != null) + { + nick = friend.GetName(); + realNick = friend.NickName; + } + } + + this.RealNick = Util.RemoveEmoji(realNick); + this.NickName = Util.RemoveEmoji(nick); + this.Username = e.Member.Username; + this.Groupid = e.Group.UserName; + this.HeadUrl = e.Member.BigHeadImgUrl; + } + else if (EventType == typeof(Chat.Framework.WXSdk.Events.WXReiceveFriendMsg)) + { + //this.ChatType = ChatType.微信; + var e = Event as Chat.Framework.WXSdk.Events.WXReiceveFriendMsg; + this.RobotName = e.Client.WeixinHao; + this.Message = e.Message; + + var realNick = e.Friend.NickName; + var nick = e.Friend.GetName(); + if (string.IsNullOrWhiteSpace(Util.RemoveEmoji(nick))) + { + Friend friend = null; + if (Sender.GetType() == typeof(WXClientImpl_HOOK)) + { + var wx = Sender as WXClientImpl_HOOK; + friend = wx.Friends.FirstOrDefault(f => f.Key == e.Friend.UserName).Value; + } + else if (Sender.GetType() == typeof(WXClientImpl_QYHOOK)) + { + var wx = Sender as WXClientImpl_QYHOOK; + friend = wx.Friends.FirstOrDefault(f => f.Key == e.Friend.UserName).Value; + } + else if (Sender.GetType() == typeof(WXClientImpl_IPAD)) + { + var wx = Sender as WXClientImpl_IPAD; + friend = wx.Friends.FirstOrDefault(f => f.Key == e.Friend.UserName).Value; + } + if (friend != null) + { + nick = friend.GetName(); + realNick = friend.NickName; + } + } + this.RealNick = Util.RemoveEmoji(realNick); + this.NickName = Util.RemoveEmoji(nick); + this.Username = e.Friend.UserName; + this.Wechatid = e.Friend.Alias; + this.HeadUrl = e.Friend.BigHeadImgUrl; + } + + else if (EventType == typeof(DebugEvent)) + { + this.RobotName = "系统调试"; + this.RobotNick = "系统调试"; + var e = Event as DebugEvent; + this.ChatType = e.chatType; + this.Message = e.content; + this.RealNick = "系统调试"; + this.NickName = e.usernick; + this.Username = e.username; + } + else + { + } + } + + /// + /// 发送消息 + /// + /// 发送的消息 + /// 是否取消传递消息给后续插件 + public void SendMessage(string Message, bool SetCancel = true) + { + if (string.IsNullOrWhiteSpace(Message)) return; + if (Message.Contains("[会员等级]")) + { + var session = ApiClient.GetSession(); + var member = session.FindMemberinfo(this); + var group = session.FindGroup(member); + Message = Message.Replace("[会员等级]", group.name); + } + + if (Message.Contains("[编号]")) + { + var session = ApiClient.GetSession(); + var member = session.FindMemberinfo(this); + Message = Message.Replace("[编号]", member.id.ToString()); + } + + var msgTmp = Message + .Replace("[账号]", Username) + .Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName) + .Replace("[昵称]", string.IsNullOrWhiteSpace(Groupid) ? (string.IsNullOrEmpty(RealNick) ? NickName : RealNick) : (string.IsNullOrEmpty(RealNick) ? NickName : RealNick)) + .Replace("[机器人账号]", RobotName) + .Replace("[机器人昵称]", RobotNick) + .Trim(); + + msgTmp = new VariateReplace().ReplaceUserVariate(msgTmp); + + var msgs = msgTmp.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var item in msgs) + { + var m = item; + + var msg = m.RandomMess(); + + if (EventType == typeof(DebugEvent)) + { + var e = Event as DebugEvent; + msg = msg.Replace("[@发送者账号]", e.username).Trim(); + e.SendDebugMsg.Invoke(e.username, msg); + } + else if (EventType == typeof(Chat.Framework.WXSdk.Events.WXReceiveGroupMsg)) + { + var e = Event as Chat.Framework.WXSdk.Events.WXReceiveGroupMsg; + string at = msg.Contains("[@发送者账号]") ? e.Member.Username : ""; + msg = msg.Replace("[@发送者账号]", e.Member.GetName()).Trim(); + e.Client.SendMessage(e.Group.UserName, msg, at); + } + else if (EventType == typeof(Chat.Framework.WXSdk.Events.WXReiceveFriendMsg)) + { + var e = Event as Chat.Framework.WXSdk.Events.WXReiceveFriendMsg; + msg = msg.Replace("[@发送者账号]", "").Trim(); + e.Client.SendMessage(e.Friend.UserName, msg); + } + else if (EventType == typeof(Chat.Framework.QQSdk.Events.QQReceiveFriendMsgEvents)) + { + var e = Event as Chat.Framework.QQSdk.Events.QQReceiveFriendMsgEvents; + + var session = ApiClient.GetSession(); + var robot = session.FindRobotInfo(e.QQBase.QQ.ToString(), ChatType.QQ); + if (robot == null) return; + + msg = msg.Replace("[@发送者账号]", "").Trim(); + //if (e.TempMsgID == 0) + // e.QQBase.SendFriendMessage(e.QQ, msg); + //else + // e.QQBase.SendTempMessage(e.QQ, msg); + ApiClient.SendMessage(robot, e.QQ.ToString(), msg, e.IsTemp); + } + else if (EventType == typeof(Chat.Framework.QQSdk.Events.QQReceiveGroupMsgEvents)) + { + var e = Event as Chat.Framework.QQSdk.Events.QQReceiveGroupMsgEvents; + + var session = ApiClient.GetSession(); + var robot = session.FindRobotInfo(e.QQBase.QQ.ToString(), ChatType.QQ); + if (robot == null) return; + + msg = msg.Replace("[@发送者账号]", $"[@{e.QQ}]").Trim(); + //e.QQBase.SendGroupMessage(e.GroupId, msg); + ApiClient.SendMessage(robot, e.QQ.ToString(), msg, e.GroupId.ToString()); + } + else if (EventType == typeof(Chat.Framework.PCRobotSDK.WechatEvents.WechatReceiveMsgEvents)) + { + var e = Event as Chat.Framework.PCRobotSDK.WechatEvents.WechatReceiveMsgEvents; + var session = ApiClient.GetSession(); + var robot = session.FindRobotInfo(e.Data.RobotUsername, e.Data.RobotType == PCRobot.Pack.RobotType.客户端微信 ? ChatType.微信 : ChatType.企业微信); + if (robot == null) return; + //Console.WriteLine(e.Data.FromGroupid); + + msg = msg.Replace("\r\n", "\n").Trim().Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + + try + { + msg = msg.Contains("[随机表情]") ? msg.Replace("[随机表情]", WXClientImpl_IPAD.FindRandomExpression()) : msg; + + //if (message.StartsWith("[延迟=")) + //{ + // var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + // if (reg.Success) + // { + // message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + // Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + // } + //} + msg = DelayMess(msg); + + //发送XML消息 + if (msg.ToLower().Trim().StartsWith("")) + { + msg = $@"{Util.RemoveEmoji(e.Data.RobotUsernick)}0{msg.Trim().Replace("&", "&")}1Window wechat"; + + ApiClient.SendMessage(robot, e.Data.FromUsername, msg, e.Data.FromGroupid); + } + + //发送图片消息 + var matchs = Regex.Matches(msg, @"(\[图片\=[^\]]+\])", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + ApiClient.SendMessage(robot, e.Data.FromUsername, match.Groups[1].Value, e.Data.FromGroupid); + } + msg = Regex.Replace(msg, @"\[图片\=([^\]]+)\]", ""); + msg = DelayMess(msg); + //发送语音消息 + matchs = Regex.Matches(msg, @"(\[语音\=[^\]]+\])", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + ApiClient.SendMessage(robot, e.Data.FromUsername, match.Groups[1].Value, e.Data.FromGroupid); + } + msg = Regex.Replace(msg, @"\[语音\=([^\]]+)\]", ""); + msg = DelayMess(msg); + matchs = Regex.Matches(msg, @"(\[视频\=[^\]]+\])", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + ApiClient.SendMessage(robot, e.Data.FromUsername, match.Groups[1].Value, e.Data.FromGroupid); + } + msg = Regex.Replace(msg, @"\[视频\=([^\]]+)\]", ""); + msg = DelayMess(msg); + //ToDo 卡片还没完成 + //matchs = Regex.Matches(msg, @"\[卡片\=([^\]]+)\]", RegexOptions.IgnoreCase); + //foreach (Match match in matchs) + //{ + // SendCard(username, match.Groups[1].Value == "自己" ? robot.name : match.Groups[1].Value); + //} + //msg = Regex.Replace(msg, @"\[卡片\=([^\]]+)\]", ""); + msg = DelayMess(msg); + if (string.IsNullOrWhiteSpace(msg)) continue; + if (msg.StartsWith("\r\n")) msg = msg.Substring("\r\n".Length); + if (msg.StartsWith("\n")) msg = msg.Substring("\n".Length); + } + catch (Exception ex) + { + //("SendMessage ERROR:" + ex.Message); + } + ApiClient.SendMessage(robot, e.Data.FromUsername, msg, e.Data.FromGroupid); + } + } + Cancel = SetCancel; + } + + /// + /// 消息延迟 + /// + /// 消息 + private string DelayMess(string message) + { + try + { + message = message.Trim(); + if (message.StartsWith("[延迟=")) + { + var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + } + } + } + catch (Exception ex) + { } + return message; + } + + } +} diff --git a/类库/Api.Framework/SDK/SDKEvent.cs b/类库/Api.Framework/SDK/SDKEvent.cs new file mode 100644 index 0000000..3b4bf9e --- /dev/null +++ b/类库/Api.Framework/SDK/SDKEvent.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework.Events; +using Chat.Framework.QQSdk.Events; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Events; + +namespace Api.Framework.SDK +{ + /// + /// SDK事件管理 + /// + public class SDKEvent + { + public SDKEvent(Plugin plugin) + { + this.plugin = plugin; + } + Plugin plugin; + internal void OnEvent(object sender, object e) + { + try + { + var type = e.GetType(); + if (type == typeof(ReciveIMEvent)) + { + var item = e as ReciveIMEvent; + var robot = item.RobotInfo; + if (ReciveIMEvent != null) + ReciveIMEvent.Invoke(sender, e as ReciveIMEvent); + } + else if (type == typeof(MemberPointChangeEvent)) + { + if (MemberPointChangeEvent != null) + MemberPointChangeEvent.Invoke(sender, e as MemberPointChangeEvent); + } + else if (type == typeof(WXReiceveFriendMsg)) + { + if (WXReiceveFriendMsgEvent != null) + WXReiceveFriendMsgEvent.Invoke(sender, e as WXReiceveFriendMsg); + } + else if (type == typeof(WXApplyGroup)) + { + if (WXApplyGroupEvent != null) + WXApplyGroupEvent.Invoke(sender, e as WXApplyGroup); + } + else if (type == typeof(WXChangeStatus)) + { + if (WXChangeStatusEvent != null) + WXChangeStatusEvent.Invoke(sender, e as WXChangeStatus); + } + else if (type == typeof(WXNewFriend)) + { + if (WXNewFriendEvent != null) + WXNewFriendEvent.Invoke(sender, e as WXNewFriend); + } + else if (type == typeof(WXNewMemer)) + { + if (WXNewMemerEvent != null) + WXNewMemerEvent.Invoke(sender, e as WXNewMemer); + } + else if (type == typeof(WXApplyFriend)) + { + if (WXApplyFriendEvent != null) WXApplyFriendEvent.Invoke(sender, e as WXApplyFriend); + } + else if (type == typeof(WXReceiveGroupMsg)) + { + if (WXReceiveGroupMsgEvent != null) + WXReceiveGroupMsgEvent.Invoke(sender, e as WXReceiveGroupMsg); + } + else if (type == typeof(OrderNoticeEvent)) + { + if (OrderNoticeEvent != null) OrderNoticeEvent.Invoke(sender, e as OrderNoticeEvent); + } + + else if (type == typeof(WXSendMessage)) + { + if (WXSendMessage != null) WXSendMessage.Invoke(sender, e as WXSendMessage); + } + else if (type == typeof(WXRefreshContactSuccess)) + { + if (WXRefreshContactSuccess != null) WXRefreshContactSuccess.Invoke(sender, e as WXRefreshContactSuccess); + } + else if (type == typeof(WXReicevePay)) + { + if (WXReicevePay != null) WXReicevePay.Invoke(sender, e as WXReicevePay); + } + else if (type == typeof(SharedEvents)) + { + if (SharedEvent != null) SharedEvent.Invoke(sender, e as SharedEvents); + } + else if (type == typeof(WebRequestEvents)) + { + if (WebRequestEvent != null) WebRequestEvent.Invoke(sender, e as WebRequestEvents); + } + else if (type == typeof(WXOpenWindow)) + { + if (WXOpenWindowEvent != null) WXOpenWindowEvent.Invoke(sender, e as WXOpenWindow); + } + else if (type == typeof(QQReceiveFriendMsgEvents)) + { + if (QQReceiveFriendMsgEvents != null) QQReceiveFriendMsgEvents.Invoke(sender, e as QQReceiveFriendMsgEvents); + } + else if (type == typeof(QQAddMeNeedAuthEvents)) + { + if (QQAddMeNeedAuthEvents != null) QQAddMeNeedAuthEvents.Invoke(sender, e as QQAddMeNeedAuthEvents); + } + else if (type == typeof(QQNewFriendEvents)) + { + if (QQNewFriendEvents != null) QQNewFriendEvents.Invoke(sender, e as QQNewFriendEvents); + } + else if (type == typeof(QQNewGroupMemberEvents)) + { + if (QQNewGroupMemberEvents != null) QQNewGroupMemberEvents.Invoke(sender, e as QQNewGroupMemberEvents); + } + else if (type == typeof(QQAddToClusterNeedAuthEvents)) + { + if (QQAddToClusterNeedAuthEvents != null) QQAddToClusterNeedAuthEvents.Invoke(sender, e as QQAddToClusterNeedAuthEvents); + } + else + { + plugin.OnLog("不支持事件:" + type); + } + } + catch (Exception ex) + { + plugin.OnLog(ex.Message); + } + } + /// + /// 打开窗口事件 + /// + + public event EventHandler WXOpenWindowEvent; + + /// + /// web请求事件 + /// + public event EventHandler WebRequestEvent; + + /// + /// 微信收到支付 + /// + public event EventHandler WXReicevePay; + + /// + /// 通用解析事件 + /// + public event EventHandler ReciveIMEvent; + + /// + /// 用户积分变动通知事件 + /// + public event EventHandler MemberPointChangeEvent; + + /// + /// 收到微信群消息 + /// + public event EventHandler WXReceiveGroupMsgEvent; + /// + /// 微信 - 收到微信好友消息 + /// + public event EventHandler WXReiceveFriendMsgEvent; + /// + /// 微信 - 申请添加我为好友,需要审核 + /// + public event EventHandler WXApplyFriendEvent; + /// + /// 微信 - 申请进入群,需要审核 + /// + public event EventHandler WXApplyGroupEvent; + /// + /// 微信 - 在线状态发生改变 + /// + public event EventHandler WXChangeStatusEvent; + /// + /// 微信 - 新增微信好友 + /// + public event EventHandler WXNewFriendEvent; + /// + /// 微信 - 新增群成员 + /// + public event EventHandler WXNewMemerEvent; + + /// + /// 订单通知接口 + /// + public event EventHandler OrderNoticeEvent; + + /// + /// 微信发送消息成功 + /// + public event EventHandler WXSendMessage; + + /// + /// 微信刷新好友成功 + /// + public event EventHandler WXRefreshContactSuccess; + + /// + /// 共享自定义事件 + /// + public event EventHandler SharedEvent; + + /// + /// 收到QQ消息 + /// + + public event EventHandler QQReceiveFriendMsgEvents; + + /// + /// 有人添加我为好友,需要审核 + /// + + public event EventHandler QQAddMeNeedAuthEvents; + + /// + /// 有人添加我为好友 + /// + public event EventHandler QQNewFriendEvents; + + /// + /// QQ群新增成员 + /// + public event EventHandler QQNewGroupMemberEvents; + + /// + /// 有人申请进群,需要审核 + /// + public event EventHandler QQAddToClusterNeedAuthEvents; + + } +} diff --git a/类库/Api.Framework/SDK/TimerTask.cs b/类库/Api.Framework/SDK/TimerTask.cs new file mode 100644 index 0000000..008bd78 --- /dev/null +++ b/类库/Api.Framework/SDK/TimerTask.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.SDK +{ + /// + /// 定时器 + /// + public abstract class TimerTask : IDisposable + { + /// + /// 是否在运行 + /// + public new bool IsRunning { get; protected set; } + /// + /// 运行的数量 + /// + public new long RunningCount { get; set; } + /// + /// 执行任务 + /// + public new void ExecutionTask(object state, bool timedOut) + { + if (IsRunning) return; + try + { + IsRunning = true; + RunningCount++; + this.Run(state, timedOut); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"ERROR.:{this.GetType()}-{System.Reflection.MethodBase.GetCurrentMethod().Name}-->{ex.Message},{ex.StackTrace}"); + } + finally + { + IsRunning = false; + } + } + + /// + /// 运行主体 - 需要重写 + /// + public abstract void Run(object state, bool timedOut); + + /// + /// 销毁方法 - 可以被重写 + /// + public new virtual void Dispose() { this.IsRunning = false; } + + /// + /// RegisterdHandler + /// + public new RegisteredWaitHandle RegisterdHandler { get; private set; } + + /// + /// WaitHandler + /// + public new WaitHandle WaitHandler { get; private set; } + + static TimerTask() { Timers = new Dictionary(); } + + private static Dictionary Timers { get; set; } + + /// + /// 获得定时器 + /// + public static TimerTask GetTimer() + { + var type = typeof(T); + if (Timers.ContainsKey(type)) return Timers[type]; + return null; + } + + public static T NewTimer(T task, int second, object state = null) + { + var _t = task as TimerTask; + if (_t == null) throw new Exception($"不支持{typeof(T)}类型,请继承[Api.Framework.TimerClient]!"); + Close(); + var type = task.GetType(); + _t.WaitHandler = new AutoResetEvent(false); + _t.RegisterdHandler = ThreadPool.RegisterWaitForSingleObject(_t.WaitHandler, new WaitOrTimerCallback(_t.ExecutionTask), state, second * 1000, false); + Timers[type] = _t; + return task; + } + /// + /// 创建一个定时器 + /// + /// + public static T NewTimer(int second, object state = null) + { + if (second == 0) second = 1; + var time = System.Activator.CreateInstance(); + var _t = time as TimerTask; + if (_t == null) throw new Exception($"不支持{typeof(T)}类型,请继承[Api.Framework.TimerClient]!"); + Close(); + var type = time.GetType(); + _t.WaitHandler = new AutoResetEvent(false); + _t.RegisterdHandler = ThreadPool.RegisterWaitForSingleObject(_t.WaitHandler, new WaitOrTimerCallback(_t.ExecutionTask), state, second * 1000, false); + Timers[type] = _t; + return time; + } + + /// + /// 关闭一个定时器 + /// + public static new void Close() + { + var type = typeof(T); + if (Timers.ContainsKey(type)) + { + var t = Timers[type]; + Timers.Remove(type); + if (t != null && t.WaitHandler != null && t.RegisterdHandler != null) + { + t.RegisterdHandler.Unregister(t.WaitHandler); + t.Dispose(); + } + } + } + + protected bool IsStart + { + get + { + if (this.WaitHandler != null && this.RegisterdHandler != null) return true; + return false; + } + } + + } +} diff --git a/类库/Api.Framework/Timers/ClearGarbageTimer.cs b/类库/Api.Framework/Timers/ClearGarbageTimer.cs new file mode 100644 index 0000000..567d78d --- /dev/null +++ b/类库/Api.Framework/Timers/ClearGarbageTimer.cs @@ -0,0 +1,38 @@ +using Api.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Timers +{ + /// + /// 清理垃圾线程 + /// + public class ClearGarbageTimer : TimerTask + { + [DllImport("psapi.dll")] + private static extern int EmptyWorkingSet(IntPtr hwProc); + + public override void Run(object time, bool timeout) + { + try + { + //Win32清理内存 + Process currentProcess = Process.GetCurrentProcess(); + EmptyWorkingSet(currentProcess.Handle); + + //强制清理GC回收站 + GC.Collect(); + } + catch (Exception ) + {} + } + + } +} diff --git a/类库/Api.Framework/Timers/DownAlimamaTimer.cs b/类库/Api.Framework/Timers/DownAlimamaTimer.cs new file mode 100644 index 0000000..80c2161 --- /dev/null +++ b/类库/Api.Framework/Timers/DownAlimamaTimer.cs @@ -0,0 +1,2442 @@ +//============================================================= +// 创建人:千年老妖 +// 本页代码,均为原创。对未经许可擅自使用者,本人保留追究其法律责任的权利。 +//============================================================== +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.Properties; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Timers; +using System.Web; +using System.Web.Caching; +using static Api.Framework.Cps.AlimamaApi; + +namespace Api.Framework.Timers +{ + /// + /// 阿里订单下载定时器 + /// + public class DownAlimamaTimer : TimerTask + { + /// + /// 是否在运行 + /// + private static bool isRun = false; + /// + /// 记录三个月中最早付款的时间 + /// + private static DateTime recordTime = DateTime.MinValue; + + private static object rights = null;//维权让只执行一次 + private static readonly object objLock = new object();//锁 + public DownAlimamaTimer() + { + if (rights == null) + { + lock (objLock) + { + if (rights == null) + { + rights = new object(); + + //维权订单下载 + ThreadPool.QueueUserWorkItem(delegate + { + while (this.IsStart) + { + try + { + Thread.Sleep(1000 * 60 * 30); + if (!this.IsStart) return; + var list = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈 && f.online == true && f.is_download == SwitchType.开启).ToList(); + TaskTool task = new TaskTool(); + foreach (var item in list) + { + var api = new AlimamaApi(item); + task.AddTask(delegate + { + UpdateOrder(api, DateTime.Now.AddDays(-50)); + }); + } + task.Start(10, null); + } + catch (Exception) + { } + } + }); + + //同步长时间没有同步的付款订单 + ThreadPool.QueueUserWorkItem(delegate + { + do + { + if (isRun) return; + isRun = true; + try + { + Thread.Sleep(30000); + var session = ApiClient.GetSession(); + var date = DateTime.Now; + + var start_time = recordTime == DateTime.MinValue ? date.AddDays(-90).AddHours(2) : recordTime; + + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈 && f.is_download == SwitchType.开启 && f.logintime.AddDays(30).AddHours(-5) >= DateTime.Now).ToArray(); + if (members != null && members.Length != 0) + { + var _recordTime = recordTime; + fl_order_alimama order = null; + for (int i = 0; i < 2; i++) + { + var cpsnames = "'" + string.Join("','", members.Select(f => f.username)) + "'"; + //order = session.FindSingle("db_status = @db_status and db_endtime = @min and @start_time < create_time and create_time <= @end_time and db_cpsname in (" + cpsnames + ") order by create_time asc", new { db_status = (int)SystemOrderStatus.订单付款, min = DateTime.MinValue.ToString("yyyy-MM-dd HH:mm:ss"), start_time = start_time.ToString("yyyy-MM-dd HH:mm:ss"), end_time = date.ToString("yyyy-MM-dd HH:mm:ss") }); + order = session.FindSingle("db_status = @db_status and @start_time < create_time and create_time <= @end_time and db_cpsname in (" + cpsnames + ") order by create_time asc", new { db_status = (int)SystemOrderStatus.订单付款, start_time = start_time.ToString("yyyy-MM-dd HH:mm:ss"), end_time = date.ToString("yyyy-MM-dd HH:mm:ss") }); + if (order != null) + { + if (order.create_time != DateTime.MinValue && order.create_time != recordTime) + { + recordTime = order.create_time; + break; + } + else + start_time = recordTime; + } + } + if (order != null) + { + if (recordTime == DateTime.MinValue) recordTime = order.create_time; + + if (_recordTime == recordTime) return; + + var staetTime = order.create_time;//最后 + if (date > staetTime.AddDays(20)) + { + //var notices = DownOrderByOrderStatus(members, staetTime, staetTime.AddDays(1), new AlimamaOrderStatus[] { /*AlimamaOrderStatus.订单付款,*/AlimamaOrderStatus.全部订单, /* AlimamaOrderStatus.订单结算,*/ AlimamaOrderStatus.订单失效 }); + var notices = DownOrderByOrderStatus(members, staetTime, staetTime.AddDays(1)); + if (notices != null && notices.Count != 0) + OrderNotices(notices); + } + } + } + } + catch (Exception) + { } + finally + { + isRun = false; + } + Thread.Sleep(1700000);//半个小时执行一次 + } while (true); + }); + + //离线通知 + ThreadPool.QueueUserWorkItem(delegate + { + do + { + try + { + Thread.Sleep(60000); + var cpss = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈 && f.abnormal_tip == SwitchType.开启 && f.online).ToList(); + if (cpss != null && cpss.Count != 0) + { + foreach (var cps in cpss) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "https://media.alimama.com/violationu2/violation2_page.json?r=mx_162&toPage=1&pageSize=40&punishStatus=1&csrfID=8383fb1b95de", + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cps.cookies, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "text/html", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + ResultType = ResultType.String, + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + if (string.IsNullOrWhiteSpace(html)) continue; + var temp = JObject.Parse(html); + if (temp == null) continue; + //{"data":{"result":[],"totalCount":0},"resultCode":1,"success":true} + var successTemp = temp["success"]; + if (successTemp == null || !(bool)successTemp) continue; + var data = temp["data"]; + if (data == null) continue; + var totalCountTemp = data["totalCount"]; + if (totalCountTemp == null) continue; + int totalCount = (int)totalCountTemp; + if (totalCount == 0) continue; + StringBuilder strb = new StringBuilder(); + strb.AppendLine("淘宝违规处罚通知"); + strb.AppendLine("---------------------"); + strb.AppendLine("淘宝昵称:" + cps.usernick); + strb.AppendLine("淘宝账号:" + cps.username); + strb.AppendLine("存在违规:" + totalCount + "条"); + strb.AppendLine(); + strb.AppendLine("尽快去后台进行违规申诉"); + ApiClient.SendNoticeMessage(strb.ToString()); + } + catch (Exception ex) + { } + finally + { + Thread.Sleep(1000); + } + } + } + } + catch (Exception ex) + { } + Thread.Sleep(12 * 60 * 60 * 1000);//8小时执行一次 + } while (true); + }); + } + } + } + } + /// + /// .... + /// + private Dictionary OrderDataIdDic = new Dictionary(); + private DateTime update_time = DateTime.Now.AddMinutes(-60); + private int number; + public override void Run(object state, bool timedOut) + { + try + { + OrderDataIdDic = new Dictionary(); + //return; + number++; + + DateTime start = DateTime.Now; + if (number == 1) + { + start = DateTime.Now.AddHours(-5); + } + else + { + start = update_time; + if (number % 10 == 0) start = DateTime.Now.AddHours(-1); + if (number % 60 == 0) start = DateTime.Now.AddHours(-5); + else if (number % 120 == 0) start = DateTime.Now.AddHours(-24); + } + + var end = DateTime.Now; + update_time = DateTime.Now.AddMinutes(-30); + + #region 需要重新登录的联盟账号通知钉钉 + var cps_expires = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈 && f.abnormal_tip == SwitchType.开启 && f.logintime.AddDays(29) <= DateTime.Now).ToList(); + if (cps_expires != null && cps_expires.Count != 0) + { + foreach (var cps in cps_expires) + { + var key = $"alimama_cps_expire_{cps.username}"; + var value = ApiClient.Cache.Get(key); + if (string.IsNullOrWhiteSpace(value)) + { + var session = ApiClient.GetSession(); + var robot = session.FindRobots().FirstOrDefault(); + + StringBuilder strb = new StringBuilder(); + strb.AppendLine("淘宝状态异常"); + strb.AppendLine("---------------------"); + if (robot != null) + strb.AppendLine("所在机器人:" + $"({robot.nick}){robot.name}"); + + strb.AppendLine("昵称:" + cps.usernick); + strb.AppendLine("账号:" + cps.username); + strb.AppendLine(); + strb.AppendLine("解决方法:重新登录"); + ApiClient.SendNoticeMessage(strb.ToString()); + ApiClient.Cache.Set(key, ".", 300); + Thread.Sleep(50); + } + } + } + #endregion + + var _members = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈 && f.is_download == SwitchType.开启 && f.logintime.AddDays(30).AddHours(-5) >= DateTime.Now).ToArray(); + + UnValidCpsMember(_members); + + UpdateOrder(_members, start, end); + + #region 同步失效订单 + if (number % 2000 == 0) + { + //var notices = DownOrderByOrderStatus(_members, DateTime.Now.AddDays(-5), end, new AlimamaOrderStatus[] { AlimamaOrderStatus.订单失效 }); + var notices = DownOrderByOrderStatus(_members, DateTime.Now.AddDays(-5), end); + + OrderNotices(notices); + } + #endregion + + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"Alimama - > Run:{ex.Message},{ex.StackTrace}"); + } + finally + { + OrderDataIdDic = new Dictionary(); + } + } + + /// + /// 通过cps获取AlimamaApi + /// + /// cps对象 + /// + public AlimamaApi GetAlimamaApi(fl_cps_member cps) + { + try + { + return new AlimamaApi(cps); + } + catch (Exception) + { } + return null; + } + + #region 下载维权退款订单 + + private bool IsRun = false; + /// + /// 爬虫更新阿里妈妈订单 - 下载维权退款订单 + /// + /// AlimamaApi对象 + /// 开始时间 + /// 最大的页数 + public void UpdateOrder(AlimamaApi api, DateTime startTime, int maxPage = 999999) + { + #region + if (IsRun) return; + try + { + IsRun = true; + int toPage = 1; + List> result = null; + var pageSize = 1000; + List notices = new List(); + do + { + result = api.SerchOrder(OrderType.维权退款明细, 0, "", pageSize, startTime, toPage);//获取淘宝联盟的订单 + + var session = ApiClient.GetSession(); + foreach (Dictionary item in result) + { + var order = session.FindSingle("select * from fl_order_alimama where trade_id = @trade_id and trade_parent_id = @trade_parent_id", new { trade_id = item["tbTradeId"].ToString(), trade_parent_id = item["tbTradeParentId"].ToString() }); + + string _showRefundStatus = string.Empty; + if (order != null) + { + if (order.auction_category == "手动处理") + continue; + + bool IsRefundOrderExist = false;//是否是新创建 + var refund_order = session.FindSingle("select * from fl_order_refund_alimama where tbtradeparentid = @tbtradeparentid and tbtradeid = @tbtradeid", new { tbtradeparentid = item["tbTradeParentId"].ToString(), tbtradeid = item["tbTradeId"].ToString() }); + if (refund_order == null) + { + _showRefundStatus = (item["showRefundStatus"] == null ? string.Empty : item["showRefundStatus"].ToString()).Replace(",", ",").Replace(",", "_"); //维权状态 + if (_showRefundStatus.Contains("维权成功")) + _showRefundStatus = "维权成功"; + else if (_showRefundStatus.Contains("维权失败")) + _showRefundStatus = "维权失败"; + IsRefundOrderExist = true; + refund_order = new fl_order_refund_alimama() + { + earningtime = !item.ContainsKey("earningTime") || item["earningTime"] == null ? string.Empty : item["earningTime"].ToString(), + inviteraccountname = string.Empty, //item["inviterAccountName"] == null ? string.Empty : item["inviterAccountName"].ToString(), + inviterid = string.Empty, //item["inviterId"] == null ? string.Empty : item["inviterId"].ToString(), + refundcreatetime = !item.ContainsKey("refundCreateTime") || item["refundCreateTime"] == null ? string.Empty : item["refundCreateTime"].ToString(), + refundfee = !item.ContainsKey("refundFee") || item["refundFee"] == null ? 0d : double.Parse(item["refundFee"].ToString()), + + refundservicefee = !item.ContainsKey("refundServiceFee") || item["refundServiceFee"] == null ? 0d : double.Parse(item["refundServiceFee"].ToString()), + relationapp = string.Empty, //item["relationApp"] == null ? string.Empty : item["relationApp"].ToString(), + relationappname = string.Empty, //item["relationAppName"] == null ? string.Empty : item["relationAppName"].ToString(), + relationid = string.Empty,// item["relationId"] == null ? string.Empty : item["relationId"].ToString(), + showrefundreason = string.Empty,// item["showRefundReason"] == null ? string.Empty : item["showRefundReason"].ToString(), + showrefundstatus = _showRefundStatus, + showreturnfee = !item.ContainsKey("showReturnFee") || item["showReturnFee"] == null ? 0d : double.Parse(item["showReturnFee"].ToString()), + tbauctionnum = string.Empty,//item["tbAuctionNum"] == null ? string.Empty : item["tbAuctionNum"].ToString(), + tbauctiontitle = item.ContainsKey("itemTitle") ? item["itemTitle"].ToString() : string.Empty,//item["tbAuctionTitle"] == null ? string.Empty : item["tbAuctionTitle"].ToString(), + tbsellershoptitle = !item.ContainsKey("sellerShopTitle") || item["sellerShopTitle"] == null ? string.Empty : item["sellerShopTitle"].ToString(), + tbtradefinishprice = string.Empty,//item["tbTradeFinishPrice"] == null ? string.Empty : item["tbTradeFinishPrice"].ToString(), + tbtradeid = !item.ContainsKey("tbTradeId") || item["tbTradeId"] == null ? string.Empty : item["tbTradeId"].ToString(), + tbtradeparentid = !item.ContainsKey("tbTradeParentId") || item["tbTradeParentId"] == null ? string.Empty : item["tbTradeParentId"].ToString(), + tkcommissionfee = !item.ContainsKey("finalPubShareFee") || item["finalPubShareFee"] == null ? 0d : double.Parse(item["finalPubShareFee"].ToString()), + tksubsidyfee = string.Empty, //item["tkSubsidyFee"] == null ? string.Empty : item["tkSubsidyFee"].ToString() + }; + if (item.ContainsKey("refundFinishTime")) refund_order.refundfinishtime = item["refundFinishTime"] == null ? string.Empty : item["refundFinishTime"].ToString(); + } + else + { + IsRefundOrderExist = false; + _showRefundStatus = (item["showRefundStatus"] == null ? string.Empty : item["showRefundStatus"].ToString()).Replace(",", ",").Replace(",", "_"); //维权状态 + if (_showRefundStatus.Contains("维权成功")) + _showRefundStatus = "维权成功"; + else if (_showRefundStatus.Contains("维权失败")) + _showRefundStatus = "维权失败"; + + if (refund_order.showrefundstatus != _showRefundStatus) + { + if (refund_order.showrefundstatus == "维权失败" && _showRefundStatus == "维权成功") + { + IsRefundOrderExist = true; + } + refund_order.showrefundstatus = _showRefundStatus; + refund_order.refundfee = item["refundFee"] == null ? 0d : double.Parse(item["refundFee"].ToString()); //维权金额 + refund_order.refundcreatetime = item["refundCreateTime"] == null ? string.Empty : item["refundCreateTime"].ToString(); + if (item.ContainsKey("refundFinishTime")) + refund_order.refundfinishtime = item["refundFinishTime"] == null ? string.Empty : item["refundFinishTime"].ToString(); //退款完成时间 + if (item.ContainsKey("refundServiceFee")) + refund_order.refundservicefee = item["refundServiceFee"] == null ? 0d : double.Parse(item["refundServiceFee"].ToString()); //退还服务费用 + if (item.ContainsKey("showReturnFee")) + refund_order.showreturnfee = item["showReturnFee"] == null ? 0d : double.Parse(item["showReturnFee"].ToString()); //退款金额 + if (string.IsNullOrWhiteSpace(refund_order.tbauctiontitle) && item.ContainsKey("itemTitle")) + refund_order.tbauctiontitle = item["itemTitle"].ToString(); + } + else + { + var flag = false; + if (_showRefundStatus == "维权失败" && (order.db_status == SystemOrderStatus.订单维权中 || !order.IsFinish())) + { + flag = true; + } + + if (string.IsNullOrWhiteSpace(refund_order.tbauctiontitle) && item.ContainsKey("itemTitle")) + { + refund_order.tbauctiontitle = item["itemTitle"].ToString(); + if (!flag) + session.SaveOrUpdate(refund_order); + } + if (!flag) + continue; + } + } + session.SaveOrUpdate(refund_order); + + //非维权失败 + if (!_showRefundStatus.Contains("维权失败")) + { + //如果订单结算、直接扣除 + if (order.db_status == SystemOrderStatus.订单结算 || order.db_status == SystemOrderStatus.部分退款) + { + order.tk_status = (int)AlimamaOrderStatus.订单维权中; //后加 + order.db_endtime = DateTime.MinValue; //后加 + order.db_status = SystemOrderStatus.订单维权中; + + if (order.db_userid > 0) + { + var pointHists = session.Find("select * from fl_point_hist where uid = @uid and type = @pointType_name and message = @message", new { uid = order.db_userid, pointType_name = PointType.维权扣除.ToString(), message = $"退款:{order.item_title}({order.trade_parent_id})({order.trade_id})" }); + if (pointHists != null && pointHists.Count != 0) + { + continue; + } + } + + //扣除用户订单,结算的积分 + new OrderHelper().DeductAliOrderPoint(notices, order); + + if (IsRefundOrderExist && _showRefundStatus.Contains("维权成功"))//如果上面的阿里妈妈维权订单有一段时间没有下载到(维权订单),新new的对象,以前没有记录 + { + var order2 = session.FindSingle("trade_id=@trade_id and trade_parent_id=@trade_parent_id", new + { + trade_id = item["tbTradeId"].ToString(), + trade_parent_id = item["tbTradeParentId"].ToString() + }); + session.SaveOrUpdate(order); + order2.db_status = SystemOrderStatus.订单结算; + order2.tk_status = (int)AlimamaOrderStatus.订单结算; + order2.db_endtime = DateTime.Now; + + //var strb = new StringBuilder(); + //try + //{ + // strb.Append($@"维权A 数据1:{HttpHelper.ObjectToJson(order2)}"); + //} + //catch (Exception) + //{ } + + UpdateOrder(order2, notices, session, refund_order); + + //try + //{ + // strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(order2)}"); + // LogHelper.GetSingleObj().Debug("淘宝订单_: ", strb.ToString()); + //} + //catch (Exception) + //{ } + + session.SaveOrUpdate(order2); + continue; + } + if (IsRefundOrderExist && _showRefundStatus.Contains("维权成功"))//如果上面的阿里妈妈维权订单有一段时间没有下载到(维权订单),新new的对象,以前没有记录 + { + continue; + } + } + + if (_showRefundStatus.Contains("维权成功")) + { + if (order.tk_status == (int)AlimamaOrderStatus.订单维权中)//这个是出里别的软件导过来,还会结算一次 + { + order.db_status = SystemOrderStatus.订单结算; + order.tk_status = (int)AlimamaOrderStatus.订单结算; + order.db_endtime = DateTime.Now; + + //var strb = new StringBuilder(); + //try + //{ + // strb.Append($@"维权B 数据1:{HttpHelper.ObjectToJson(order)}"); + //} + //catch (Exception) + //{ } + UpdateOrder(order, notices, session, refund_order); + //try + //{ + // strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(order)}"); + // LogHelper.GetSingleObj().Debug("淘宝订单_: ", strb.ToString()); + //} + //catch (Exception) + //{ } + + } + } + else + { + order.tk_status = (int)AlimamaOrderStatus.订单维权中; //后加 + order.db_endtime = DateTime.MinValue; //后加 + order.db_status = SystemOrderStatus.订单维权中; + session.SaveOrUpdate(order); + } + } + else + { + if (order.db_status == SystemOrderStatus.订单维权中 || !order.IsFinish()) + { + if (IsRefundOrderExist && (order.db_status == SystemOrderStatus.订单冻结 || order.db_status == SystemOrderStatus.订单付款)) + { + continue; + } + + //维权失败 、 正常结算给客户 + order.tk_status = (int)AlimamaOrderStatus.订单结算; + order.db_status = SystemOrderStatus.订单冻结; + order.db_endtime = DateTime.Now; + + //var strb = new StringBuilder(); + //try + //{ + // strb.Append($@"维权B 数据2: {HttpHelper.ObjectToJson(order)}"); + //} + //catch (Exception) + //{ } + UpdateOrder(order, notices, session, refund_order); + //try + //{ + // strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(order)}"); + // LogHelper.GetSingleObj().Debug("淘宝订单_: ", strb.ToString()); + //} + //catch (Exception) + //{ } + } + } + } + } + toPage++; + } while (result != null && result.Count == pageSize && toPage < maxPage); + + OrderNotices(notices); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "下载维权退款订单异常:" + ex.Message); + } + finally + { + IsRun = false; + } + #endregion + } + #endregion + + /// + /// 同步订单 + /// + /// 同步账号时间 + /// 同步开始 + /// 同步结束时间 + private void UpdateOrder(fl_cps_member[] _members, DateTime start_time, DateTime end_time) + { + if (end_time.Hour == 3 && 0 <= end_time.Minute && end_time.Minute <= 7) return; + + _members = _members.Where(f => f.is_download == SwitchType.开启).ToArray(); + if (_members == null || _members.Length == 0) + return; + + List notices = null; + + try + { + UnValidCpsMember(_members); + + if (!string.IsNullOrWhiteSpace(order_id)) + //notices = DownOrderByOrderStatus(_members, start_time, end_time, new AlimamaOrderStatus[] { AlimamaOrderStatus.订单付款 }); + notices = DownOrderByOrderStatus(_members, start_time, end_time); + else + { + //notices = DownOrderByOrderStatus(_members, start_time, end_time, new AlimamaOrderStatus[] { AlimamaOrderStatus.订单付款, AlimamaOrderStatus.全部订单, AlimamaOrderStatus.订单结算, AlimamaOrderStatus.订单失效 }); + notices = DownOrderByOrderStatus(_members, start_time, end_time); + + #region 检查冻结状态的订单是否可以结算 + var session = ApiClient.GetSession(); + var end_orders = session.Find("db_status = @db_status and db_endtime != @min and db_endtime < @now", new { db_status = (int)SystemOrderStatus.订单冻结, min = DateTime.MinValue.ToString("yyyy-MM-dd HH:mm:ss"), now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); + //var strb = new StringBuilder(); + //strb.AppendLine("检查冻结订单是否可以结算..."); + //int index = 1; + foreach (var db_order in end_orders) + { + //strb.Append($@"订单{index}:{HttpHelper.ObjectToJson(db_order)}"); + UpdateOrder(db_order, notices, session); + //strb.AppendLine($@"返回: {HttpHelper.ObjectToJson(db_order)}"); + //index++; + //strb.AppendLine(); + } + //try + //{ + // LogHelper.GetSingleObj().Debug("淘宝订单_: ", strb.ToString()); + //} + //catch (Exception) + //{ } + #endregion + } + } + catch (Exception ex) + { + var err = ""; + if (ex.Message.Contains("未将对象引用设置到对象的实例")) + err = ",请重新登录淘宝"; + EventClient.OnEvent(this, $"更新阿里妈妈订单异常:{ex.Message} - {ex.StackTrace} {err}"); + } + + OrderNotices(notices); + } + + + /// + /// 手动同步指定阿里妈妈订单状态 + /// + /// 要同步的阿里妈妈 + /// 同步的时间 + /// 同步结束的时间 + /// 订单的状态 + public void UpdateOrder(fl_cps_member[] _members, DateTime start_time, DateTime end_time, AlimamaOrderStatus status) + { + if (_members == null || _members.Length == 0) + return; + + //if (status == AlimamaOrderStatus.全部订单 || status == AlimamaOrderStatus.订单成功 || status == AlimamaOrderStatus.订单维权中) + //return; + + List notices = null; + + try + { + UnValidCpsMember(_members); + + notices = DownOrderByOrderStatus(_members, start_time, end_time, new AlimamaOrderStatus[] { status }); + //notices = DownOrderByOrderStatus(_members, start_time, end_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"更新阿里妈妈订单({status.ToString()}):" + ex.Message); + } + + + OrderNotices(notices); + + } + + /// + /// 创建阿里妈妈订单同步任务 + /// 阿里妈妈联盟 + /// 订单同步起始时间 + /// 订单同步结束时间 + public void UpdateOrder(List members, DateTime start_time, DateTime end_time) + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + UpdateOrder(members.ToArray(), start_time, end_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新阿里妈妈订单异常4:" + ex.Message); + } + finally + { + IsRunning = false; + } + } + + //private static readonly int row_count = 19;//阿里妈妈更新间隔间隔 + #region 同步间隔时间缓存 + /// + /// 设置同步的时间间隔 + /// + /// + internal static void SetIntervalCache(int interval) + { + try + { + var cacheName = DateTime.Now.ToString("yyyyMMdd"); + Cache cache = HttpRuntime.Cache; + //时间间隔缓存,不存在则返回null + object item = cache[cacheName]; + if (item == null) + { + var date = DateTime.Now.Date.AddDays(1).AddMilliseconds(-1); + cache.Insert(cacheName, interval, null, date, System.Web.Caching.Cache.NoSlidingExpiration); + } + } + catch (Exception ex) + { } + } + /// + /// 获取同步的时间间隔 + /// + /// + internal static int GetIntervalCache() + { + try + { + var cacheName = DateTime.Now.ToString("yyyyMMdd"); + Cache cache = HttpRuntime.Cache; + object item = cache[cacheName]; + if (item != null) + return Convert.ToInt32(item); + } + catch (Exception) + { } + return interval; + } + + /// + /// 判断缓存是否存在 + /// + /// + internal static bool IsExitCache() + { + try + { + var cacheName = DateTime.Now.ToString("yyyyMMdd"); + Cache cache = HttpRuntime.Cache; + return cache[cacheName] != null; + } + catch (Exception ex) + { } + return false; + } + #endregion + + #region 老道 通过阿里妈妈订单状态下载订单 + + private const int interval = 60; + + private List DownOrderByOrderStatus(fl_cps_member[] _members, DateTime _start_time, DateTime _end_time, AlimamaOrderStatus[] _orderStatus = null) + { + var orderStatus = _orderStatus; + var members = _members; + DateTime start_time = _start_time; + DateTime end_time = _end_time; + + //start_time = DateTime.Parse("2020-05-26 07:00:00"); + //end_time = DateTime.Parse("2020-05-31 01:00:00"); + List notices = new List(); + + //if (orderStatus == null || orderStatus.Length == 0) return notices; + + members = members.Where(f => f.is_valid).ToArray(); + + if (members.Length != 0) + { + try + { + var isState = (orderStatus == null || orderStatus.Length == 0); + var row_count = 19; + if (!IsExitCache())//如果缓存时间不存在那么先请求一次下载订单 + { + var _member = members.FirstOrDefault(f => f.logintime > DateTime.Now.AddDays(-29)); + if (_member != null) + { + var api = CpsClient.CreateAlimamaRequest(_member); + var time = end_time.AddMinutes(-interval); + //UpdateOrder(AlimamaOrderType.淘客明细订单, time, api, notices, _member, orderStatus[0]); + if (isState) + api.DownOrder(time, 1, 100, AlimamaOrderType.淘客明细订单, 1); + else + api.DownOrder(time, 1, 100, orderStatus[0], AlimamaOrderType.淘客明细订单, 1); + } + } + if (IsExitCache()) + { + row_count = GetIntervalCache(); + } + var spa_time = end_time - start_time;//计算时间差 + //int count = (int)spa_time.TotalMinutes / row_count; + //if (spa_time.TotalMinutes % row_count != 0) count++; + var count = Math.Ceiling(spa_time.TotalMinutes / row_count); + + if (!isState)//带订单状态 + { + for (int s = 0; s < orderStatus.Length; s++)//更新的订单状态 + { + var status = orderStatus[s]; + Task[] _task = new Task[members.Length]; + for (int i = 0; i < members.Length; i++) + { + var _status = status; + var _member = members[i]; + var _api = CpsClient.CreateAlimamaRequest(_member); + + _task[i] = new Task(delegate + { + var api = _api; + var member = _member; + try + { + for (int j = 1; j <= count; j++) + { + //临时时间 + var _time = end_time.AddMinutes(-(j * row_count)); + UpdateOrder(AlimamaOrderType.淘客明细订单, _time, api, notices, member, _status); + UpdateOrder(AlimamaOrderType.第三方订单明细, _time, api, notices, member, _status); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"阿里妈妈Api更新订单状态异常:{member.usernick} ~ {status} # {ex.Message} - {ex.StackTrace}"); + } + }); + _task[i].Start(); + Thread.Sleep(100); + } + Task.WaitAll(_task); + Thread.Sleep(10); + } + } + else//没有订单状态 + { + Task[] _task = new Task[members.Length]; + for (int i = 0; i < members.Length; i++) + { + var _member = members[i]; + var _api = CpsClient.CreateAlimamaRequest(_member); + + _task[i] = new Task(delegate + { + var api = _api; + var member = _member; + try + { + for (int j = 1; j <= count; j++) + { + //临时时间 + var _time = end_time.AddMinutes(-(j * row_count)); + UpdateOrder(AlimamaOrderType.淘客明细订单, _time, api, notices, member); + UpdateOrder(AlimamaOrderType.第三方订单明细, _time, api, notices, member); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"阿里妈妈Api更新订单状态异常:{member.usernick} ~ ## {ex.Message} - {ex.StackTrace}"); + } + }); + _task[i].Start(); + Thread.Sleep(100); + } + Task.WaitAll(_task); + } + } + catch (Exception ex) + { + throw ex; + } + } + return notices; + } + #endregion + + /// + /// 事件通知 + /// + /// + private void OrderNotices(List _notices) + { + var notices = _notices; + if (notices != null && notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + var order = item.Order as fl_order_alimama; + if (order.trade_parent_id == order_id) continue; + Thread.Sleep(5); + tasks.Add(item); + } + notices.Clear(); + notices = null; + } + } + + #region 下载订单 + + #region 下载阿里妈妈订单 + /// + /// 下载阿里订单 + /// + /// + /// + /// + /// + /// + /// + internal void UpdateOrder(AlimamaOrderType _order_type, DateTime _start_time, AlimamaApi _api, List notices, fl_cps_member _ItemMember, AlimamaOrderStatus _tk_status = AlimamaOrderStatus.全部订单) + { + var order_type = _order_type; + var start_time = _start_time; + var ItemMember = _ItemMember; + var tk_status = _tk_status; + var api = _api; + + var downTypeList = new List() { 3, 1 }; + //foreach (int order_scene in Enum.GetValues(typeof(TBDownType))) + foreach (var order_scene in downTypeList) + { + try + { + ArrayList list = null; + if (tk_status != AlimamaOrderStatus.全部订单) + list = api.DownOrder(start_time, 1, 100, tk_status, order_type, order_scene); + else + list = api.DownOrder(start_time, 1, 100, order_type, order_scene); + if (list == null || list.Count == 0) + { + Thread.Sleep(300); + continue; + } + + //var _pids = ApiClient.Setting.SystemConfig.order_alimama_not_download_pid.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + int count = 0; + foreach (Dictionary order in list) + { + count++; + var session = ApiClient.GetSession(); + + try + { + if (!string.IsNullOrEmpty(order_id) && order["trade_parent_id"].ToString() != order_id) continue; + + //订单号搜索 + //if (order["trade_parent_id"].ToString() == "2104466653925439514" && order["trade_id"].ToString() == "2104466653926439514") + //{ + + //} + + //if (order["trade_parent_id"].ToString() == "8536347047390809379") + //{ + + //} + + if (order.ContainsKey("alipay_total_price") && double.Parse(order["alipay_total_price"].ToString()) == 0d)//不处理赠品商品,直接跳过 + continue; + + #region 处理的PID + if (ApiClient.Setting.SystemConfig.order_alimama_download_set_pids == SwitchType.关闭) + { + var _pids = ApiClient.Setting.SystemConfig.order_alimama_not_download_pid.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + if (_pids.Count != 0 && order.ContainsKey("adzone_id")) + { + var isExist = _pids.FirstOrDefault(f => f.EndsWith("_" + order["adzone_id"].ToString())) != null;//是否包含 + if (ApiClient.Setting.SystemConfig.order_alimama_down_type == DownAdzoneType.不下载推广位 && isExist) + continue; + else if (ApiClient.Setting.SystemConfig.order_alimama_down_type == DownAdzoneType.只下载推广位 && !isExist) + continue; + } + } + else + { + if (order.ContainsKey("adzone_id")) + { + var adzoneList = new List(); + var adzones = session.FindAdzoneInfos(); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "淘宝返利" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.EndsWith("_" + order["adzone_id"].ToString()))); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "用户私人pid" && f.extend == "淘宝私人pid" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.EndsWith("_" + order["adzone_id"].ToString()))); + if (adzoneList == null || adzoneList.Count() == 0) + { + if (null == session.FindAdzoneGroups(CpsType.阿里妈妈).FirstOrDefault(f => Regex.IsMatch(f.adzones, "_" + order["adzone_id"].ToString()))) + continue; + continue; + } + } + } + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(150); + #endregion + + var status = int.Parse(order["tk_status"].ToString()); + + //var db_order = session.Queryable().Where(f => f.trade_id == order["trade_id"].ToString() && f.trade_parent_id == order["trade_parent_id"].ToString()).First(); + var db_order = session.FindSingle("select * from fl_order_alimama where trade_id = @trade_id and trade_parent_id = @trade_parent_id", new { trade_id = order["trade_id"].ToString(), trade_parent_id = order["trade_parent_id"].ToString() }); + + if (db_order != null) //跳过相同状态 + { + if (db_order.total_commission_rate == 0) continue; + if (db_order.IsFinish()) continue;//是否完成 + + #region 预付定金处理 + if (order.ContainsKey("tb_deposit_time") && order["tb_deposit_time"].ToString() != "--") + { + if (order.ContainsKey("alipay_total_price") && double.Parse(order["alipay_total_price"].ToString()) != db_order.alipay_total_price) + { + var alipay_total_price = double.Parse(order["alipay_total_price"].ToString()); + db_order.alipay_total_price = alipay_total_price; + + if (order.ContainsKey("pub_share_pre_fee")) + db_order.pub_share_pre_fee = double.Parse(order["pub_share_pre_fee"].ToString()); + + fl_member_info member = null; + if (db_order.db_userid != 0) + { + //member = session.FindSingle("select * from fl_member_info where id = @id", new { id = db_order.db_userid }); + member = session.FindMemberInfoById(db_order.db_userid); + } + + //计算的佣金 - 判断使用设置模式,符合将扣除用户自定义预扣佣金 + var commission = session.GetTbComparisonFeeRate(db_order); + + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.阿里妈妈, db_order.id); + + ItemPoint itempoint = null; + if (compute != null) + itempoint = session.FindItemPoint(CpsType.阿里妈妈, compute, commission, db_order.item_num); + else + itempoint = session.FindItemPoint(member, commission, db_order.item_num, CpsType.阿里妈妈); + db_order.db_userpoint = itempoint.UserPoint; + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + session.SaveOrUpdate(db_order); + } + + #region 以后直接删除 + if (order.ContainsKey("deposit_price") && string.IsNullOrWhiteSpace(db_order.deposit_price)) + { + db_order.deposit_price = order["deposit_price"].ToString(); + db_order.tb_deposit_time = order["tb_deposit_time"].ToString(); + session.SaveOrUpdate(db_order); + } + #endregion + } + #endregion + + if (db_order.db_status == SystemOrderStatus.订单冻结 && db_order.db_endtime > DateTime.Now) continue;//跳过系统冻结 + if ((int)db_order.tk_status == status) continue;//跳过相同状态? + + #region 更新以下的值 + #region 老接口 09-20 + //if (order.ContainsKey("commission")) + // db_order.commission = double.Parse(order["commission"].ToString()); + //if (order.ContainsKey("pay_price")) + // db_order.pay_price = double.Parse(order["pay_price"].ToString()); + //if (order.ContainsKey("earning_time")) + // db_order.earning_time = DateTime.Parse(order["earning_time"].ToString()); + #endregion + + #region 新接口 09-20 + //if (order.ContainsKey("commission")) + // db_order.commission = double.Parse(order["commission"].ToString()); + if (order.ContainsKey("tk_paid_time")) + db_order.paid_time = DateTime.Parse(order["tk_paid_time"].ToString()); + if (order.ContainsKey("pub_share_fee")) + db_order.commission = double.Parse(order["pub_share_fee"].ToString()); + if (order.ContainsKey("pay_price")) + db_order.pay_price = double.Parse(order["pay_price"].ToString()); + //if (order.ContainsKey("earning_time")) + // db_order.earning_time = DateTime.Parse(order["earning_time"].ToString()); + if (order.ContainsKey("tk_earning_time")) + db_order.earning_time = DateTime.Parse(order["tk_earning_time"].ToString()); + if (order.ContainsKey("total_commission_fee")) + db_order.total_commission_fee = double.Parse(order["total_commission_fee"].ToString()); + #endregion + + #endregion + } + + //自动填充实例 + if (db_order == null) + { + db_order = order.ConvertToObj(); + if (db_order.total_commission_rate == 0 && db_order.order_type != "饿了么") continue; + if (order.ContainsKey("subsidy_type")) + { + AlimamaOrderSubsidyType subsidyType; + + if (!Enum.TryParse(order["subsidy_type"].ToString(), out subsidyType)) + subsidyType = AlimamaOrderSubsidyType.其他; + db_order.subsidy_type = (int)subsidyType; + } + if (order.ContainsKey("terminal_type")) + { + AlimamaOrderTerminalType terminalType; + + if (!Enum.TryParse(order["terminal_type"].ToString(), out terminalType)) + terminalType = AlimamaOrderTerminalType.其他; + db_order.terminal_type = (int)terminalType; + } + + db_order.income_rate = (double)((decimal)db_order.income_rate / 100m); + db_order.total_commission_rate = (double)((decimal)db_order.total_commission_rate / 100m); + db_order.subsidy_rate = (double)((decimal)db_order.subsidy_rate / 100m); + + #region 新接口 + if (order.ContainsKey("tk_paid_time")) + db_order.paid_time = DateTime.Parse(order["tk_paid_time"].ToString()); + if (order.ContainsKey("tk_earning_time")) + db_order.earning_time = DateTime.Parse(order["tk_earning_time"].ToString()); + if (order.ContainsKey("pub_share_fee")) + db_order.commission = double.Parse(order["pub_share_fee"].ToString()); + if (order.ContainsKey("item_category_name")) + db_order.auction_category = order["item_category_name"].ToString(); + if (order.ContainsKey("tk_create_time")) + db_order.create_time = DateTime.Parse(order["tk_create_time"].ToString()); + if (order.ContainsKey("item_id")) + db_order.num_iid = order["item_id"].ToString(); + if (order.ContainsKey("item_price")) + db_order.price = double.Parse(order["item_price"].ToString()); + #endregion + + db_order.db_cpsname = ItemMember.username; + db_order.db_cpsnick = ItemMember.usernick; + + #region 预付定金处理 + if (order.ContainsKey("tb_deposit_time") && order["tb_deposit_time"].ToString() != "--") + { + if (order.ContainsKey("deposit_price") && double.Parse(order["deposit_price"].ToString()) != 0d) + { + var alipay_total_price = double.Parse(order["alipay_total_price"].ToString()); + db_order.alipay_total_price = alipay_total_price; + + if (order.ContainsKey("pub_share_pre_fee")) + db_order.pub_share_pre_fee = double.Parse(order["pub_share_pre_fee"].ToString()); + + fl_member_info member = null; + if (db_order.db_userid != 0) + member = session.FindMemberInfoById(db_order.db_userid); + + //计算的佣金 - 判断使用设置模式,符合将扣除用户自定义预扣佣金 + var commission = session.GetTbComparisonFeeRate(db_order); + //var itempoint = session.FindItemPoint(member, (db_order.commission == 0 ? db_order.pub_share_pre_fee : db_order.commission), db_order.item_num, CpsType.阿里妈妈); + + if (db_order.id == 0) + session.Saveable(db_order); + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.阿里妈妈, db_order.id); + + ItemPoint itempoint = null; + if (compute != null) + itempoint = session.FindItemPoint(CpsType.阿里妈妈, compute, commission, db_order.item_num); + else + itempoint = session.FindItemPoint(member, commission, db_order.item_num, CpsType.阿里妈妈); + db_order.db_userpoint = itempoint.UserPoint; + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + + session.SaveOrUpdate(db_order); + } + } + #endregion + } + db_order.tk_status = status; + + if (string.IsNullOrWhiteSpace(db_order.seller_id)) + { + if (order.ContainsKey("item_img")) + { + var reg = Regex.Match(order["item_img"].ToString(), @"i\d+?/(?<店铺Id>\d+?)/"); + if (reg.Success) + db_order.seller_id = reg.Groups["店铺Id"].Value; + } + } + + if (ItemMember != null) + { + //var strb = new StringBuilder(); + //try + //{ + // strb.Append($@"数据:{HttpHelper.ObjectToJson(db_order)} + + //原始:{HttpHelper.ObjectToJson(order)}"); + //} + //catch (Exception) + //{ } + + //System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); + //watch.Start();//开始监视代码运行时间 + + if (db_order.tk_status == (int)AlimamaOrderStatus.订单成功) + { + if (order.ContainsKey("modified_time")) + { + if (!string.IsNullOrWhiteSpace(order["modified_time"]?.ToString())) + { + DateTime time; + if (DateTime.TryParse(order["modified_time"]?.ToString(), out time)) + { + db_order.earning_time = time; + //session.SaveOrUpdate(db_order); + } + } + } + //db_order.tk_status = (int)AlimamaOrderStatus.订单结算; + } + + UpdateOrder(db_order, notices, session);//.. + + //watch.Stop();//停止监视 + //try + //{ + //strb.AppendLine($@" + //耗时:{watch.Elapsed.TotalSeconds} 秒"); + //LogHelper.GetSingleObj().Debug("淘宝订单: ", strb.ToString()); + //} + //catch (Exception) + //{ } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"同步阿里妈妈订单出错:{ItemMember.username} - {ex.Message} - {ex.StackTrace}"); + } + finally + { + //session.Close(); + } + } + list.Clear(); + list = null; + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"更新阿里妈妈订单异常3:{ItemMember.username} - {ex.Message} - {ex.StackTrace}"); + if (ex.Message.Contains("已过期")) + { + ItemMember.logintime = DateTime.Now.AddDays(-30);//设置登录时间为过期,后面通知客户 + throw ex; + } + } + } + } + #endregion + + #endregion + private readonly object LockObj = new object(); + /// + /// 订单绑定逻辑 + /// + /// 阿里订单对象 + /// 事件集合 + /// 数据库操作对象 + /// 阿里订单维权对象 + /// + public void UpdateOrder(fl_order_alimama db_order, List notice, SqlSugarClient session, fl_order_refund_alimama order_refund = null, bool isFrontData = false) + { + //维权中的订单,直接跳出 + if (db_order.db_status == SystemOrderStatus.订单维权中) + return; + else + { + } + try + { + if (db_order.id != 0) + { + lock (LockObj) + { + if (!OrderDataIdDic.ContainsKey(db_order.id)) + { + OrderDataIdDic[db_order.id] = db_order.id; + } + else + { + LogHelper.GetSingleObj().Error("订单重复进入", $"订单ID:{db_order.id}"); + return; + } + } + } + + fl_plugin_allrebatesactivity_orderlist allrebatesactivity_orderlist = null; + var old_status = db_order.db_status; + var status = Util.ConvertEnum(db_order.tk_status); + bool islotUserQuery = false;//订单是否为多人查询 + // string old_md5 = Util.GetMd5_32byte(HttpHelper.ObjectToJson(db_order)); + var isRewards = false;//是否获得推荐新人奖励 + var isFirstOrder = false;//是否获得用户首单奖励 + + #region 私域绑定 + if (db_order.db_userid == 0 && status == AlimamaOrderStatus.订单付款 && db_order.special_id != 0) + { + var tbAnalysis = new TBHelper.TbAnalysis(); + var cps_member = CpsClient.Members.FirstOrDefault(f => f.username == db_order.db_cpsname && f.cpstype == CpsType.阿里妈妈); + if (cps_member != null) + { + //var api = CpsClient.CreateAlimamaRequest(cps_member); + //var external_id = tbAnalysis.FindTbPublisherInfoFirst(api, new { info_type = 2, relation_app = "common", special_id = db_order.special_id, external_type = 0 }, TBHelper.TbAnalysis.PublisherType.ExternalId); + //if (!string.IsNullOrWhiteSpace(external_id)) + //{ + // var memberInfo = session.FindMemberInfoByUsername(external_id); + // if (memberInfo != null) + // { + // db_order.db_robotname = memberInfo.robot_name; + // db_order.db_robottype = memberInfo.robot_type; + // db_order.db_userid = memberInfo.id; + + // var relation = session.Queryable().First(f => f.cps_memberid == db_order.db_cpsname && f.special_id == db_order.special_id); + // if (relation == null) + // relation = new fl_tb_relation() { cps_memberid = db_order.db_cpsname, special_id = db_order.special_id }; + // if (relation.username != external_id) + // { + // relation.username = external_id; + // session.Saveable(relation).ExecuteCommand(); + // } + // } + //} + + var relation = ApiClient.GetSession().FindTbRelations().FirstOrDefault(f => f.cps_memberid == db_order.db_cpsname && f.special_id == db_order.special_id); + if (relation != null && !string.IsNullOrWhiteSpace(relation.username)) + { + var memberInfo = session.FindMemberInfoByUsername(relation.username); + if (memberInfo != null) + { + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + db_order.db_userid = memberInfo.id; + + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time order by id", new { userid = db_order.db_userid, itemid = db_order.num_iid, adzoneid = db_order.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + #region 绑定群号 + if (string.IsNullOrWhiteSpace(db_order.msg_groupid)) + db_order.msg_groupid = query_item.groupid; + #endregion + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + } + } + } + } + } + #endregion + + #region 自动识别绑定 + #region 缓存绑定 + if (db_order.db_userid == 0 && status == AlimamaOrderStatus.订单付款) + { + var bind = session.FindBindCache(db_order.trade_parent_id); + if (bind != null) + { + var memberInfo = session.FindMemberInfoById(bind.db_userid); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + db_order.msg_groupid = bind.groupid; + session.SaveOrUpdate(memberInfo); + //session.SaveOrUpdate(db_order); + } + } + } + #endregion + + if (db_order.db_userid == 0 && status == AlimamaOrderStatus.订单付款) + { + #region 淘宝返利推广位自动绑定 + + #region 私人推广位 + var privateAdzonePids = session.FindAlimamaPrivatePid(db_order.adzone_id);//私人推广位对象 + if (privateAdzonePids.Count == 1 && privateAdzonePids[0].is_auto_bind)//无条件设置开启中,直接自动绑定 + { + var memberInfo = session.FindSingle("select * from fl_member_info where id = @id", new { id = privateAdzonePids[0].member_id }); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + //session.SaveOrUpdate(db_order); + } + } + #endregion + else + { + var flag = false; + var ali_pid_list = session.FindAlimamaAutoBindPid();//淘宝返利设置的推广位集合 + if (ali_pid_list != null) + { + flag = ali_pid_list.FirstOrDefault(f => f.adzone_pid.EndsWith("_" + db_order.adzone_id)) != null ? true : false; + if (!flag) + { + var groupList = session.FindAdzoneGroups(CpsType.阿里妈妈); + #region 淘宝推广位组 + var groups = groupList.Where(f => string.IsNullOrWhiteSpace(f.remark)); + ali_pid_list = ali_pid_list.Where(f => f.adzone_group != 0).ToList(); + foreach (var item in ali_pid_list) + { + var group = groups.FirstOrDefault(f => f.id == item.adzone_group); + if (group != null) + { + List tuiguangweis = null; + try + { + tuiguangweis = HttpHelper.JsonToObject>(group.adzones) as List; + } + catch (Exception) + { + tuiguangweis = new List(); + } + if (tuiguangweis != null) + flag = (null != tuiguangweis.FirstOrDefault(f => f.Pid.EndsWith("_" + db_order.adzone_id))) ? true : false; + if (flag) break; + } + } + #endregion + + #region 强制推广位组 + if (!flag) + { + groups = groupList.Where(f => f.remark == fl_alimama_activity_type.天猫精选.ToString()); + ali_pid_list = ali_pid_list.Where(f => f.adzone_group != 0).ToList(); + foreach (var item in ali_pid_list) + { + var group = groups.FirstOrDefault(f => f.id == item.adzone_group); + if (group != null) + { + List tuiguangweis = null; + try + { + tuiguangweis = HttpHelper.JsonToObject>(group.adzones) as List; + } + catch (Exception) + { + tuiguangweis = new List(); + } + if (tuiguangweis != null) + flag = (null != tuiguangweis.FirstOrDefault(f => f.Pid.EndsWith("_" + db_order.adzone_id))) ? true : false; + if (flag) break; + } + } + } + #endregion + + #region 全额返利推广位 + var all_rebates_adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.TbAllRebatesSoftwareType && f.adzone_pid.EndsWith("_" + db_order.adzone_id)); + if (all_rebates_adzone != null) + { + flag = (null != all_rebates_adzone.adzone_pid.EndsWith("_" + db_order.adzone_id)) ? true : false; + } + #endregion + } + } + + if (!flag) + flag = privateAdzonePids.Select(f => f.adzone_pid).ToList().FirstOrDefault(f => f.EndsWith("_" + db_order.adzone_id)) != null ? true : false;//私人推广位 + + if (!flag) + flag = session.CheckIsTljOrder(db_order.adzone_id);//淘礼金推广位 + #endregion + + if (flag) + { + #region 新字符串绑定 + + if (ApiClient.Setting.SystemConfig.order_alimama_bind == SwitchType.开启) + { + if (db_order.num_iid.Contains("-")) + { + var split = db_order.num_iid.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries); + var itemIdB = split[1]; + var query = session.FindTable("select userid,count(*) as count from fl_query_hist where userid != 0 and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time group by userid ", new { itemid = itemIdB, adzoneid = db_order.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query != null && query.Rows.Count > 0) + { + if (query.Rows.Count == 1) + { + var query_item = session.FindSingle("select * from fl_query_hist where itemid = @itemid and crt_time > @time order by id desc", new { itemid = itemIdB, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.db_robotname = query_item.robot_name; + db_order.db_robottype = query_item.robot_type; + db_order.msg_groupid = query_item.groupid; + db_order.db_userid = query_item.userid; + //session.SaveOrUpdate(db_order); + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + } + } + } + } + } + #endregion + + //订单尾号自动绑定用户 + if (db_order.db_userid == 0) + { + if (ApiClient.Setting.SystemConfig.order_alimama_last_auto_bind == SwitchType.开启) + { + var lasts = session.FindAlimamaOrderLastnums().Where(f => db_order.trade_parent_id.EndsWith(f.lastnumber)).ToList();//通过订单尾号查询对应的用户 + if (lasts != null && lasts.Count == 1)//订单尾号只对应一个用户,多个不处理 + { + var memberInfo = session.FindMemberInfoById(lasts[0].userid); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + //session.SaveOrUpdate(db_order); + } + } + } + } + //订单没有绑定用户 查询订单记录 + if (db_order.db_userid == 0) + { + var query = session.FindTable("select userid,count(*) as count from fl_query_hist where userid != 0 and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time group by userid ", new { itemid = db_order.num_iid, adzoneid = db_order.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query != null && query.Rows.Count > 0) + { + if (query.Rows.Count == 1) + { + if (ApiClient.Setting.SystemConfig.order_alimama_bind == SwitchType.开启) + { + var userid = int.Parse(query.Rows[0]["userid"].ToString());//要是查询记录已经标记为通知过的记录(userid 为 负数),将不通过查询记录进行绑定 + if (userid > 0) + { + db_order.db_userid = userid;//根据查询记录认领 + + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.num_iid, adzoneid = db_order.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + #region 淘宝订单尾号自动采集 + if (ApiClient.Setting.SystemConfig.order_alimama_last_auto_capture == SwitchType.开启) + { + //订单尾号和用户进行绑定 + if (session.FindAlimamaOrderLastnums().FirstOrDefault(f => f.userid == db_order.db_userid) == null) + { + session.Insertable(new fl_alimama_order_lastnum() { userid = db_order.db_userid, lastnumber = db_order.trade_parent_id.Substring(db_order.trade_parent_id.Length - 6, 6) }).ExecuteCommand(); + session.FindAlimamaOrderLastnums(true); + } + } + #endregion + } + } + } + } + else + { + if (ApiClient.Setting.SystemConfig.order_alimama_last_auto_bind == SwitchType.开启) + { + var end_number = db_order.trade_parent_id.Substring(db_order.trade_parent_id.Length - 6); + var lasts = session.FindAlimamaOrderLastnums().Where(f => end_number == f.lastnumber).ToList(); + + if (lasts.Count > 0) + { + //是否存在、尾号相同,并且查询过宝贝(优先识别) + Dictionary last_num = new Dictionary(); + for (int i = 0; i < query.Rows.Count; i++) + { + var info = lasts.FirstOrDefault(f => f.userid == long.Parse(query.Rows[i]["userid"].ToString())); + if (info != null) last_num[info.userid] = info; + } + + if (last_num.Count == 1) + { + var last_item = last_num.FirstOrDefault().Value; + db_order.db_userid = last_item.userid; + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.num_iid, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.db_robotname = query_item.robot_name; + db_order.db_robottype = query_item.robot_type; + db_order.msg_groupid = query_item.groupid; + //session.SaveOrUpdate(db_order); + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + } + } + else + { + //尾号相同、并且均查询过该宝贝 + } + } + else + { + //未找到尾号相同订单 + } + } + + //订单多人查询,并且订单还未绑定 + if (db_order.db_userid == 0) + islotUserQuery = true; + } + } + } + } + } + + #region 绑定群号 + if (string.IsNullOrWhiteSpace(db_order.msg_groupid)) + { + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.num_iid, adzoneid = db_order.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + } + } + #endregion + } + + #region 店铺绑定,最后的绑定判断(如果上面的绑定都没有成功,使用店铺绑定的方式进行绑定,如果多人在该店查询过其他商品将不进行绑定.只针对一个用户在该店铺查询过,将该商品的订单给绑定给用户) + if (db_order.db_userid == 0 && status == AlimamaOrderStatus.订单付款 && ApiClient.Setting.SystemConfig.order_alimama_same_shop_bind == SwitchType.开启 && !string.IsNullOrWhiteSpace(db_order.seller_id)) + { + var query = session.FindTable("select userid,count(*) as count from fl_query_hist where userid != 0 and mallid = @mallid and adzoneid = @adzoneid and crt_time > @time group by userid ", new { mallid = db_order.seller_id, adzoneid = db_order.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query != null && query.Rows.Count > 0) + { + if (query.Rows.Count == 1) + { + if (ApiClient.Setting.SystemConfig.order_alimama_bind == SwitchType.开启) + { + var userid = int.Parse(query.Rows[0]["userid"].ToString());//要是查询记录已经标记为通知过的记录(userid 为 负数),将不通过查询记录进行绑定 + if (userid > 0) + { + db_order.db_userid = userid;//根据查询记录认领 + + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and mallid = @mallid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, mallid = db_order.seller_id, adzoneid = db_order.adzone_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + //#region 淘宝订单尾号自动采集 + //if (ApiClient.Setting.SystemConfig.order_alimama_last_auto_capture == SwitchType.开启) + //{ + // //订单尾号和用户进行绑定 + // if (session.FindAlimamaOrderLastnums().FirstOrDefault(f => f.userid == db_order.db_userid) == null) + // { + // session.Insertable(new fl_alimama_order_lastnum() { userid = db_order.db_userid, lastnumber = db_order.trade_parent_id.Substring(db_order.trade_parent_id.Length - 6, 6) }).ExecuteCommand(); + // session.FindAlimamaOrderLastnums(true); + // } + //} + //#endregion + } + } + } + } + } + else + { + query = session.FindTable("select userid,count(*) as count from fl_query_hist where userid != 0 and mallid = @mallid and crt_time > @time group by userid ", new { mallid = db_order.seller_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query != null && query.Rows.Count > 0) + { + if (query.Rows.Count == 1) + { + if (ApiClient.Setting.SystemConfig.order_alimama_bind == SwitchType.开启) + { + var userid = int.Parse(query.Rows[0]["userid"].ToString());//要是查询记录已经标记为通知过的记录(userid 为 负数),将不通过查询记录进行绑定 + if (userid > 0) + { + db_order.db_userid = userid;//根据查询记录认领 + + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and mallid = @mallid and crt_time > @time order by id desc", new { userid = db_order.db_userid, mallid = db_order.seller_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.阿里妈妈 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + //#region 淘宝订单尾号自动采集 + //if (ApiClient.Setting.SystemConfig.order_alimama_last_auto_capture == SwitchType.开启) + //{ + // //订单尾号和用户进行绑定 + // if (session.FindAlimamaOrderLastnums().FirstOrDefault(f => f.userid == db_order.db_userid) == null) + // { + // session.Insertable(new fl_alimama_order_lastnum() { userid = db_order.db_userid, lastnumber = db_order.trade_parent_id.Substring(db_order.trade_parent_id.Length - 6, 6) }).ExecuteCommand(); + // session.FindAlimamaOrderLastnums(true); + // } + //} + //#endregion + } + } + } + } + } + } + } + #endregion + + #endregion + + if (db_order.tk_status == 12 && db_order.db_userid != 0) + { + try + { + var record = session.FindStatisticsRecord(db_order.db_userid); + if (record == null) + record = new fl_statistics_record() { uid = db_order.db_userid }; + record.ex5 = HttpExtend.GetTimeStamp(db_order.paid_time); + session.Saveable(record).ExecuteCommand(); + } + catch (Exception) + { } + } + + //查询积分比例 + var member = db_order.db_userid != 0 ? session.FindMemberInfoById(db_order.db_userid) : null; + + if (string.IsNullOrEmpty(db_order.db_robotname) && member != null) + { + db_order.db_robotname = member.robot_name; + db_order.db_robottype = member.robot_type; + } + + #region 全额返利绑定 并且 将返利积分进行固定 + + var adzone = session.FindAdzoneInfos().FirstOrDefault(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.custom_type == Resources.TbAllRebatesSoftwareType && f.adzone_pid.EndsWith("_" + db_order.adzone_id)); + if (adzone != null) + { + var allrebatesactivity_infos = session.Find("select * from fl_plugin_allrebatesactivity_info where goods_id = @goods_id", new { goods_id = db_order.num_iid }); + if (allrebatesactivity_infos != null && allrebatesactivity_infos.Count != 0) + { + if (member != null) + { + var allrebatesactivity_info = allrebatesactivity_infos.FirstOrDefault(f => f.time_begin <= db_order.create_time && db_order.create_time <= f.time_end && f.groups.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(z => Convert.ToInt64(z.Trim())).ToList().Contains(member.group_id) && f.robots.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(z => z.Trim()).ToList().Contains(db_order.db_robotname)); + if (allrebatesactivity_info != null) + { + //TODO这里还要判断已经成交的列表中是否存在订单数量 + var allrebatesactivity_orderlists = session.Find("select * from fl_plugin_allrebatesactivity_orderlist where activity_id = @activity_id and mid = @mid", new { activity_id = allrebatesactivity_info.id, mid = member.id }); + int purchased_quantity = 0;//已经购买的数量 + if (allrebatesactivity_orderlists != null && allrebatesactivity_orderlists.Count != 0) + { + foreach (var item in allrebatesactivity_orderlists) + { + var order_alimama = session.FindSingle("select * from fl_order_alimama where id = @id", new { id = item.oid }); + if (order_alimama != null) + { + if (order_alimama.db_status == SystemOrderStatus.订单结算 || order_alimama.db_status == SystemOrderStatus.全额退款 || order_alimama.db_status == SystemOrderStatus.部分退款 || order_alimama.db_status == SystemOrderStatus.订单付款 || order_alimama.db_status == SystemOrderStatus.订单冻结 || order_alimama.db_status == SystemOrderStatus.订单退款 || order_alimama.db_status == SystemOrderStatus.订单维权中) + { + purchased_quantity += order_alimama.item_num; + } + } + } + } + + if (allrebatesactivity_info.limit_quantity_number >= (db_order.item_num + purchased_quantity)) + { + if (string.IsNullOrEmpty(db_order.db_point)) + { + var return_money = (double)((decimal)allrebatesactivity_info.return_money * (decimal)db_order.item_num); + var point = @"{""Type"":0,""Commission"":0,""SumPoint"":" + db_order.pub_share_pre_fee + @",""UserPoint"":" + return_money + @",""AwardOne"":0,""AwardTwo"":0,""AwardThree"":0,""AwardCreate"":0}"; + db_order.db_point = point; + db_order.db_userpoint = return_money; + } + + var robot = session.FindRobots().FirstOrDefault(f => db_order.db_robottype == f.type && f.name == db_order.db_robotname); + if (robot != null) + { + allrebatesactivity_orderlist = new fl_plugin_allrebatesactivity_orderlist() + { + activity_id = allrebatesactivity_info.id, + mid = member.id, + rid = robot.id, + oid = db_order.id + }; + } + } + } + } + } + } + #endregion + + if (string.IsNullOrEmpty(db_order.db_point)) + { + #region 判断是否为淘礼金订单,如果是淘礼金订单将不给这个订单返利 + var isTljOrder = session.CheckIsTljOrder(db_order.adzone_id); + #endregion + + //计算的佣金 - 判断使用设置模式,符合将扣除用户自定义预扣佣金 + var commission = session.GetTbComparisonFeeRate(db_order); + + if (db_order.id == 0) + session.Saveable(db_order); + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.阿里妈妈, db_order.id); + + ItemPoint itempoint = null; + if (compute != null) + itempoint = session.FindItemPoint(CpsType.阿里妈妈, compute, isTljOrder ? 0 : commission, db_order.item_num); + else + itempoint = session.FindItemPoint(member, isTljOrder ? 0 : commission, db_order.item_num, CpsType.阿里妈妈); + if (itempoint != null) + { + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + db_order.db_userpoint = itempoint.UserPoint; + } + if (member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + } + + switch (status) + { + case AlimamaOrderStatus.订单成功: + case AlimamaOrderStatus.订单结算: + { + if (status == AlimamaOrderStatus.订单成功) + db_order.tk_status = (int)AlimamaOrderStatus.订单结算; + + //进入冻结逻辑 + if (db_order.db_endtime == DateTime.MinValue) + { + db_order.db_status = SystemOrderStatus.订单冻结; + if (db_order.alipay_total_price != db_order.pay_price) + { + //计算的佣金 - 判断使用设置模式,符合将扣除用户自定义预扣佣金 + var commission = session.GetTbComparisonFeeRate(db_order); + + if (db_order.id == 0) + session.Saveable(db_order); + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.阿里妈妈, db_order.id); + + ItemPoint itempointTemp = null; + if (compute != null) + itempointTemp = session.FindItemPoint(CpsType.阿里妈妈, compute, commission, db_order.item_num); + else + itempointTemp = session.FindItemPoint(member, commission, db_order.item_num, CpsType.阿里妈妈); + db_order.db_point = HttpHelper.ObjectToJson(itempointTemp); + db_order.db_userpoint = itempointTemp.UserPoint; + } + + var sleep = session.FindSleep(CpsType.阿里妈妈, ApiClient.Setting.SystemConfig.FreezingCondition == FreezingConditionType.商品总佣金 ? (db_order.commission == 0 ? db_order.pub_share_pre_fee : db_order.commission) : db_order.db_userpoint);//通过返佣获取订单冻结规则 + if (sleep != null) + { + if (!string.IsNullOrEmpty(sleep.white_groups)) + { + if (member != null && sleep.white_groups.Split(',').Contains(member.group_id.ToString())) + db_order.db_endtime = DateTime.Now;//该会员组不受限制 + else + db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else db_order.db_endtime = DateTime.Now; + + #region 验证订单是否为24小时 + if (db_order.earning_time != DateTime.MinValue) + { + var config = Util.Read>("插件-淘宝返利-配置"); + if (config != null) + { + if (config.ContainsKey("ReceivingTimeCheck_Switch")) + { + var ReceivingTimeCheck_Switch = (bool)config["ReceivingTimeCheck_Switch"]; + if (ReceivingTimeCheck_Switch) + { + if (config.ContainsKey("ReceivingTimeCheck_Hour")) + { + //var ss = config["ReceivingTimeCheck_Hour"]; + var ReceivingTimeCheck_Hour = int.Parse(config["ReceivingTimeCheck_Hour"].ToString()); + if ((db_order.earning_time - db_order.create_time).TotalHours <= ReceivingTimeCheck_Hour)//判断订单收货时间差 + { + if (config.ContainsKey("ReceivingTimeCheck_OperateType")) + { + var ReceivingTimeCheck_OperateType = (OperateType)int.Parse(config["ReceivingTimeCheck_OperateType"].ToString()); + if (ReceivingTimeCheck_OperateType == OperateType.订单冻结) + { + if (config.ContainsKey("ReceivingTimeCheck_FreezeTime")) + { + var ReceivingTimeCheck_FreezeTime = int.Parse(config["ReceivingTimeCheck_FreezeTime"].ToString()); + db_order.db_endtime = db_order.db_endtime.AddHours(ReceivingTimeCheck_FreezeTime);//延迟多少小时 + } + } + } + } + } + } + } + } + } + #endregion + + } + + //已经传递了参数~ 这里就不要强制读数据库 + if (db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.订单结算; + + if (db_order.auction_category != "手动处理") + { + if (order_refund == null) + order_refund = session.FindSingle("select * from fl_order_refund_alimama where tbtradeparentid = @tbtradeparentid and tbtradeid = @tbtradeid", new { tbtradeparentid = db_order.trade_parent_id, tbtradeid = db_order.trade_id }); + + if (order_refund != null) + { + var showRefundStatus = (OrderRefundStatus)Enum.Parse(typeof(OrderRefundStatus), order_refund.showrefundstatus); //将阿里返回的订单状态转成枚举 + switch (showRefundStatus) + { + case OrderRefundStatus.维权成功_佣金补扣成功: + case OrderRefundStatus.维权成功_等待补扣佣金: + case OrderRefundStatus.维权成功: + { + //维权成功,更新退款金额 + if (order_refund.refundfee == db_order.alipay_total_price) + { + db_order.db_status = SystemOrderStatus.全额退款; + db_order.db_endtime = DateTime.Now; + } + else + { + //var commission = db_order.commission;//临时的佣金额度 + //if (db_order.commission == 0) + // commission = db_order.pub_share_pre_fee; + + //计算的佣金 - 判断使用设置模式,符合将扣除用户自定义预扣佣金 + var commission = session.GetTbComparisonFeeRate(db_order); + + db_order.commission = (double)((decimal)commission - (decimal)order_refund.showreturnfee);//付款金额与退款金额一致 说明退了全额;不一致那么只退了一部分,佣金需要重新计算 + + //上面重新计算了一下佣金 + commission = session.GetTbComparisonFeeRate(db_order); + + if (db_order.id == 0) + session.Saveable(db_order); + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.阿里妈妈, db_order.id); + + ItemPoint itempoint = null; + if (compute != null) + itempoint = session.FindItemPoint(CpsType.阿里妈妈, compute, commission, db_order.item_num); + else + itempoint = session.FindItemPoint(member, db_order.commission, db_order.item_num, CpsType.阿里妈妈); + if (itempoint != null) + { + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + db_order.db_userpoint = itempoint.UserPoint; + } + + db_order.db_status = SystemOrderStatus.部分退款; + db_order.db_endtime = DateTime.Now; + } + } + break; + case OrderRefundStatus.维权失败_卖家佣金返还成功: + case OrderRefundStatus.维权失败_等待卖家返还佣金: + case OrderRefundStatus.维权失败: + //维权失败,继续结算 + break; + case OrderRefundStatus.等待处理: + break; + default: + return;//维权未结束不予结算 + } + } + } + + if (member != null && db_order.db_status != SystemOrderStatus.全额退款) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + if (point.UserPoint == 0) + { + point.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(point); + db_order.db_userpoint = point.UserPoint; + } + + #region 获取是否已经结算给客户 + var pointHists = session.Find("select * from fl_point_hist where uid = @uid and type = @pointType_name and message = @message", new { uid = member.id, pointType_name = PointType.消费补贴.ToString(), message = $"淘宝购买:{db_order.item_title} - ({db_order.trade_parent_id}) - ({db_order.trade_id})" }); + if (pointHists != null && pointHists.Count != 0) + { + pointHists = session.Find("select * from fl_point_hist where uid = @uid and type = @pointType_name and message = @message", new { uid = member.id, pointType_name = PointType.维权扣除.ToString(), message = $"退款:{db_order.item_title}({db_order.trade_parent_id})({db_order.trade_id})" }); + if (pointHists != null && pointHists.Count != 0) + { + LogHelper.GetSingleObj().Debug("维权扣除过的订单", $@"{JsonConvert.SerializeObject(db_order)} + +维权?:{(order_refund != null ? JsonConvert.SerializeObject(order_refund) : string.Empty)} + +维权扣除积分的次数:{pointHists.Count}"); + } + else + { + session.SaveOrUpdate(db_order); + return; + } + } + #endregion + + ///fl_order_alimama db_order, List notice, SqlSugarClient session, fl_order_refund_alimama order_refund = null, bool isFrontData = false + //LogHelper.GetSingleObj().Debug("订单AAAAAAA结算", $"阿里订单 ___ {JsonConvert.SerializeObject(db_order)} , notice = {notice.Count} , order_refund = null ? {order_refund = null} , isFrontData = {isFrontData}"); + //用户自身加积分 + member = session.ChangePoint(PointType.消费补贴, point.UserPoint, member.id, $"淘宝购买:{db_order.item_title} - ({db_order.trade_parent_id}) - ({db_order.trade_id})"); + + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + + List ids = new List(); + ids.Add(member.id); + //多级提成计算..用户自己的上级不能为自己 + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.alipay_total_price); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + } + } + else if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardOne, member.inviter_id, $"{member.usernick},淘宝购物1级提成!{db_order.item_title} - ({db_order.trade_parent_id}) - ({db_order.trade_id})"); + if (flag != null) + { + ids.Add(flag.id); + if (notice != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.alipay_total_price); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.提成奖励, point.AwardTwo, flag.inviter_id, $"{member.usernick},淘宝购物2级提成!{db_order.item_title} - ({db_order.trade_parent_id}) - ({db_order.trade_id})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (notice != null && flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.提成奖励, point.AwardThree, flag2.inviter_id, $"{member.usernick},淘宝购物3级提成!{db_order.item_title} - ({db_order.trade_parent_id}) - ({db_order.trade_id})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (notice != null && flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardCreate, create.mid, $"{member.usernick},淘宝维护提成!{db_order.item_title} - ({db_order.trade_parent_id}) - ({db_order.trade_id})"); + if (notice != null && flag != null) notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + Thread.Sleep(40); + } + else + { + //提示查询该宝贝的人所有人 + if (islotUserQuery) + { + notice.Add(new Events.OrderNoticeEvent(CpsType.阿里妈妈, null, db_order)); + } + } + } + else + { + db_order.db_status = SystemOrderStatus.订单冻结; + } + } + break; + case AlimamaOrderStatus.订单维权中: + db_order.db_status = SystemOrderStatus.订单维权中; + break; + case AlimamaOrderStatus.订单付款: + { + db_order.db_status = SystemOrderStatus.订单付款; + } + break; + case AlimamaOrderStatus.订单失效: + db_order.db_status = SystemOrderStatus.订单失效; + break; + default: + break; + } + + #region 通知客户订单付款/失效 提示上级 + if (member != null && (db_order.db_status == SystemOrderStatus.订单付款 || db_order.db_status == SystemOrderStatus.订单失效)) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + + if (point.UserPoint == 0 && ApiClient.Setting.SystemConfig.SubsidyTb == SwitchType.开启) + { + point.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(point); + db_order.db_userpoint = point.UserPoint; + } + + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + //一级用户对象 + var member_one = session.FindMemberInfoById(member.inviter_id); + if (member_one != null) + { + ids.Add(member_one.id); + if (notice != null) + notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, member_one, db_order, OrderNoticeType.一级提成) { Customer = member }); + if (point.AwardTwo > 0 && member_one.inviter_id != 0 && !ids.Contains(member_one.inviter_id)) + { + //二级用户对象 + var member_two = session.FindMemberInfoById(member_one.inviter_id); + if (member_two != null) + { + ids.Add(member_two.id); + if (member_two != null) + { + notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, member_two, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && member_two.inviter_id != 0 && !ids.Contains(member_two.inviter_id)) + { + //三级用户对象 + var member_three = session.FindMemberInfoById(member_two.inviter_id); + if (member_three != null) + { + ids.Add(member_three.id); + if (member_three != null) + notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, member_three, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var member_create = session.FindMemberInfoById(create.mid); + if (notice != null && member_create != null) notice.Add(new OrderNoticeEvent(CpsType.阿里妈妈, member_create, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + #endregion + + //string new_md5 = Util.GetMd5_32byte(HttpHelper.ObjectToJson(db_order)); + if (old_status != db_order.db_status) + db_order.db_status_time = HttpExtend.GetTimeStamp(); + session.SaveOrUpdate(db_order); + + if (db_order.db_status == SystemOrderStatus.订单付款) + { + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + } + + if (allrebatesactivity_orderlist != null) + { + allrebatesactivity_orderlist.oid = db_order.id; + session.Saveable(allrebatesactivity_orderlist).ExecuteCommand(); + } + + //if ((notice != null && old_status != db_order.db_status && order_id != db_order.trade_parent_id && member != null) || (notice != null && old_status != db_order.db_status && order_id != db_order.trade_parent_id && islotUserQuery && member == null)) + if (notice != null && (isFrontData || old_status != db_order.db_status) && order_id != db_order.trade_parent_id && ((islotUserQuery && member == null) || member != null)) + { + notice.Add(new Events.OrderNoticeEvent(CpsType.阿里妈妈, member, db_order) { IsRewards = isFirstOrder }); + } + + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新阿里妈妈订单异常1:" + db_order.db_cpsname + " - " + db_order.trade_parent_id + "," + ex.Message + "," + ex.StackTrace); + } + } + + #region 手动发送订单号,只更新短时间的付款订单 + /// + /// 如果该订单后为空时,只同步付款订单 + /// + private string order_id = string.Empty; + + /// + /// 通过订单号更新订单状态 + /// + /// 开始时间 + /// 结束时间 + /// 订单号 + /// + internal bool UpdateOrder(DateTime start_time, DateTime end_time, string order_id = "") + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + this.order_id = order_id; + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈 && f.is_download == SwitchType.开启 && f.logintime.AddDays(30).AddHours(-5) >= DateTime.Now).ToArray(); + UpdateOrder(members, start_time, end_time); + return true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新阿里妈妈订单异常5:" + ex.Message); + return false; + } + finally + { + this.order_id = string.Empty; + IsRunning = false; + } + + } + #endregion + + /// + /// 通过订单ID查询该订单是否维权 + /// + /// 数据库操作对象 + /// 父订单号 + /// 子订单号 + /// + private int FindRefundAlimamaCount(SqlSugarClient session, string tbtradeparentid, string tbtradeid) + { + try + { + var value = session.FindRow(@"select count(*) as num from fl_order_alimama ali inner join fl_order_refund_alimama rali on ali.trade_id = rali.tbtradeid and ali.trade_parent_id = rali.tbtradeparentid where rali.tbtradeid = @tbtradeid and rali.tbtradeparentid = @tbtradeparentid", new { tbtradeid = tbtradeid, tbtradeparentid = tbtradeparentid }); + return int.Parse(value["num"].ToString()); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新阿里妈妈订单异常6:" + ex.Message); + } + return 0; + } + + private static DateTime invalidnotice_time = DateTime.MinValue;//阿里妈妈账号无效通知时间 + private static DateTime invalidnotice_time2 = DateTime.MinValue;//阿里妈妈账号日志无效时间 + + /// + /// 无效的阿里妈妈账号通知 + /// + /// 阿里妈妈集合(为筛选的集合) + private void UnValidCpsMember(fl_cps_member[] _members) + { + try + { + var invalid_members = _members.Where(f => !f.is_valid).ToArray(); + if (invalid_members.Length != 0) + { + var strb = new StringBuilder(); + strb.AppendLine($"淘宝更新订单异常"); + strb.AppendLine(); + + for (int i = 0; i < invalid_members.Length; i++) + { + strb.AppendLine($"{invalid_members[i].usernick} ({invalid_members[i].username})"); + } + strb.AppendLine(); + strb.AppendLine($"以上账号授权状态已过期"); + strb.AppendLine($"跳过以上账号下载操作"); + strb.AppendLine($"请重新登录淘宝账号"); + + var timelag2 = (DateTime.Now - invalidnotice_time2).TotalMinutes; + + if (timelag2 > 5) + { + invalidnotice_time2 = DateTime.Now; + EventClient.OnEvent(this, strb.ToString()); + } + + var timelag = (DateTime.Now - invalidnotice_time).TotalMinutes; + + if (timelag > 30) + { + strb.AppendLine($"系统时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); + invalidnotice_time = DateTime.Now; + ApiClient.SendNoticeMessage(strb.ToString()); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "淘宝账号授权失效通知", strb.ToString(), true); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"更新阿里妈妈订单异常7:{ex.Message},{ex.StackTrace}"); + } + } + } +} diff --git a/类库/Api.Framework/Timers/DownDouyinTimer.cs b/类库/Api.Framework/Timers/DownDouyinTimer.cs new file mode 100644 index 0000000..f0a053c --- /dev/null +++ b/类库/Api.Framework/Timers/DownDouyinTimer.cs @@ -0,0 +1,1014 @@ +using Api.Framework.Cps; +using Api.Framework.EntityTmp.Douyin; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.Properties; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using static Api.Framework.Cps.AlimamaApi; + +namespace Api.Framework.Timers +{ + /// + /// 抖音订单下载定时器 + /// + public class DownDouyinTimer : TimerTask + { + private static object rights = null; + private static readonly object objLock = new object(); + + //public DownDouyinTimer() + //{ + // if (rights == null) + // { + // lock (objLock) + // { + + // } + // } + //} + + public override void Run(object state, bool timedOut) + { + //TODO 这里的时间还没有用,因为抖音巨量那边还搞不定(通过时间查询) + var update_time = DateTime.Now.AddDays(-1); + var end_time = DateTime.Now; + UpdateOrder(CpsClient.Members.Where(f => f.cpstype == CpsType.抖音联盟 && f.is_download == SwitchType.开启).ToArray(), update_time, end_time); + + #region 更新冻结的订单 + + List notices = new List(); + + var session = ApiClient.GetSession(); + var result = session.Find("db_status=@db_status and db_endtime<@db_endtime", new { db_status = (int)SystemOrderStatus.订单冻结, db_endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ToList();//所有完成冻结,但是还没改状态的订单 + foreach (var db_order in result) + { + UpdateOrder(db_order, notices, session); + } + + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_douyin; + tasks.Add(item); + } + } + #endregion + } + + /// + /// 手动下载订单 + /// + /// 抖音cps对象集合 + /// 订单同步开始时间 + /// 订单同步结束时间 + public void UpdateOrder(List members, DateTime start_time, DateTime end_time) + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + + UpdateOrder(members.ToArray(), start_time, end_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新抖音订单异常:" + ex.Message); + } + finally + { + IsRunning = false; + } + } + + /// + /// 订单下载时间间隔 + /// + private const int IntervalHour = 12; + + /// + /// 下载订单 + /// + /// 抖音cps对象集合 + /// 订单同步开始时间 + /// 订单同步结束时间 + private void UpdateOrder(fl_cps_member[] members, DateTime start_time, DateTime end_time) + { + if (members == null || members.Length == 0) return; + + //var memberList = members.Where(f => f.online).ToList(); + var memberList = members.ToList(); + + var timespan = end_time - start_time; + + TaskTool task = new TaskTool(); + List notices = new List(); + + foreach (var item in memberList) + { + var _item = item; + var api = CpsClient.CreateDouyinRequest(_item); + task.AddTask(delegate + { + try + { + var _star = timespan.TotalHours > 12 ? end_time : start_time;//倒叙12小时一个间断 + var _end = end_time; + do + { + try + { + if (timespan.TotalHours > 12) + { + _end = _star; + _star = _star.AddHours(-11.99); + } + + var session = ApiClient.GetSession(); + + List orderList = new List(); + + //官方接口已经同步了订单,防止非官方接口再次同步 + List orderidCache = new List(); + + //if (1 != 2) + { + var pids = session.Find("select * from fl_adzone_info").Where(f => f.adzone_pid_cps_name == _item.username).Where(f => !string.IsNullOrWhiteSpace(f.adzone_pid)).Select(f => f.adzone_pid).Distinct().ToList(); + if (pids != null & pids.Count != 0) + { + foreach (var pid in pids) + { + var tmp = api.DownOrderApi(_star, _end, pid); + if (tmp != null) + orderList.AddRange(tmp); + } + + Exception _exception = null; + + for (int i = 0; i < orderList.Count; i++) + { + var orderInfo = orderList[i]; + if (_exception != null) continue; + foreach (var order in orderInfo.orders) + { + try + { + try + { + //if (order.order_id == "4886104544279610848") + //{ + + //} + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE) + Thread.Sleep(100); + + var status = order.flow_point; + + var db_order = session.FindSingle("order_id=@order_id and product_id=@product_id", new { order_id = order.order_id, product_id = order.product_id }); + if (db_order != null) //跳过相同状态 + { + if (db_order.order_status == DouyinOrderStatus.REFUND.ToString() || db_order.product_detail == "手动处理") + { + continue; + } + if (status == db_order.order_status || status != DouyinOrderStatus.PAY_SUCC.ToString()) + { + if (db_order.IsFinish()) continue;//是否已经完成 + if (db_order.db_status == SystemOrderStatus.订单冻结 && db_order.db_endtime > DateTime.Now) continue;//跳过系统冻结 + //if (db_order.order_status != WeipinhuiOrderSubStatusName.已签收 && db_order.order_status == status) continue;//跳过相同状态 + if (db_order.order_status == status) continue;//跳过相同状态 + } + db_order.order_status = status; + } + else + { + var orderTmp = new fl_order_douyin() + { + order_id = order.order_id, + product_id = order.product_id, + product_name = order.product_name, + total_pay_amount = order.pay_goods_amount, + estimated_comission = order.estimated_commission, + order_status = order.flow_point, + pay_time = HttpExtend.GetTimeStamp(DateTime.Parse(order.pay_success_time)) + //... + }; + + db_order = orderTmp; + db_order.db_cpsname = _item.username; + db_order.db_cpsnick = _item.usernick; + } + try + { + LogHelper.GetSingleObj().Debug("抖音订单: ", $@"抖音Api原始:{JsonConvert.SerializeObject(order)} + +order = {JsonConvert.SerializeObject(db_order)}"); + } + catch (Exception) + { } + + orderidCache.Add(db_order.order_id); + + UpdateOrder(db_order, notices, session); + + try + { + LogHelper.GetSingleObj().Debug("抖音订单: ", $@"处理完成的 ,需要通知的用户 -> {notices.Count} +order = {JsonConvert.SerializeObject(db_order)}"); + } + catch (Exception) + { } + } + catch (Exception ex) + { + throw ex; + } + finally + { + //session.Close(); + } + } + catch (Exception ex) + { + _exception = ex; + break; + } + } + } + } + //Console.WriteLine(); + + } + //return; + + //int queryCount = 1; + + if (api.Member.online)//在为检测是未失效的时候进行同步 + { + #region 非官方接口获取订单 + foreach (DouyinQueryOrderType type in Enum.GetValues(typeof(DouyinQueryOrderType))) + { + try + { + Stopwatch stop = new Stopwatch(); + stop.Start(); + var json = api.DownOrder(_star, _end, 1, type); + stop.Stop(); + //Console.WriteLine($"_star={_star},_end={_end},type={type},用时:{stop.Elapsed.TotalSeconds}"); + + if (api.Member.online) + { + if (json == null || json.Count == 0 || json[0] == "error") + continue; + var orderObj = JsonConvert.DeserializeObject(json[0]); + if (orderObj.code != 0) continue; + Exception _exception = null; + var data = orderObj.data; + if (data == null) continue; + for (int i = 0; i < data.Count; i++) + { + var order = data[i]; + if (_exception != null) continue; + try + { + try + { + //if (order.order_id == "4933900340490065113") + //{ + //} + //else + //if (order.order_id == "4934209762824039641") + //{ + //} + //else + //if (order.order_id == "4934212125058641113") + //{ + //} + //else + //if (order.order_id == "4934295228379604185") + //{ + //} + //else + //if (order.order_id == "4936102872734510874") + //{ + //} + //else + //{ + // continue; + //} + + if (orderidCache.Contains(order.order_id)) + continue; + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE) + Thread.Sleep(100); + + var status = order.order_status; + + var db_order = session.FindSingle("order_id=@order_id and product_id=@product_id", new { order_id = order.order_id, product_id = order.product_id }); + if (db_order != null) //跳过相同状态 + { + if (db_order.order_status == DouyinOrderStatus.REFUND.ToString() || db_order.product_detail == "手动处理") + { + continue; + } + if (status == db_order.order_status || status != DouyinOrderStatus.PAY_SUCC.ToString()) + { + var isFinish = db_order.IsFinish(); + if (isFinish && status == db_order.order_status) continue;//是否已经完成 + + if (db_order.db_status == SystemOrderStatus.订单冻结 && db_order.db_endtime > DateTime.Now) continue;//跳过系统冻结 + //if (db_order.order_status != WeipinhuiOrderSubStatusName.已签收 && db_order.order_status == status) continue;//跳过相同状态 + if (db_order.order_status == status) continue;//跳过相同状态 + } + db_order.order_status = status; + } + else + { + db_order = order; + db_order.db_cpsname = _item.username; + db_order.db_cpsnick = _item.usernick; + } + try + { + LogHelper.GetSingleObj().Debug("抖音订单: ", $@"抖音原始:{JsonConvert.SerializeObject(order)} + +order = {JsonConvert.SerializeObject(db_order)}"); + } + catch (Exception) + { } + + UpdateOrder(db_order, notices, session); + + try + { + LogHelper.GetSingleObj().Debug("抖音订单: ", $@"处理完成的 ,需要通知的用不 -> {notices.Count} +order = {JsonConvert.SerializeObject(db_order)}"); + } + catch (Exception) + { } + } + catch (Exception ex) + { + throw ex; + } + finally + { + //session.Close(); + } + } + catch (Exception ex) + { + _exception = ex; + break; + } + } + } + else + { + EventClient.OnEvent("", $"抖音账号:{api.Member.usernick}({api.Member.username}),请重新登录"); + break; + } + } + catch (Exception ex) + { + /* + {"st":0,"code":9001,"msg":"操作异常","log_id":"2022010221313001020404907424DA1368","data":[]} + */ + //if (ex.Message.Contains("操作异常") || ex.Message.Contains("请重新登录")) + // queryCount++; + //if (queryCount >= 2) + //{ + // EventClient.OnEvent("", $"链接订单无法同步,请重新登录抖音:{api.Member.usernick}({api.Member.username})"); + // api.Member.online = false; + // ApiClient.GetSession().SaveOrUpdate(api.Member); + + // var shared = new Dictionary(); + // shared["msg_type"] = "抖音验证码"; + // shared["cps_type"] = CpsType.抖音联盟; + // shared["msg_username"] = api.Member.username; + // shared["msg_usernick"] = api.Member.usernick; + + // var sharedEvent = new SharedEvents(shared); + // EventClient.OnSharedEvent(null, sharedEvent); + // return; + //} + } + } + } + #endregion + } + catch (Exception ex) + { + //The underlying frame is no longer valid - please check the IsValid property before calling! + if (ex.Message.Contains("is no longer valid - please check the IsValid")) + { + api.Member.is_valid = false; + } + } + } while (_star > start_time); + } + catch (Exception ex) + { + //throw ex; + } + + }); + } + task.Start(1, null); + + var db = ApiClient.GetSession(); + var end_orders = db.Find("select * from fl_order_douyin where db_status=@db_status and db_endtime<@db_endtime", new { db_status = (int)SystemOrderStatus.订单冻结, db_endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ToList(); + foreach (var db_order in end_orders) + { + UpdateOrder(db_order, notices, db); + } + + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_weipinhui; + tasks.Add(item); + } + } + + } + + /// + /// 订单 修改状态/用户绑定等操作通知用户 + /// + /// 抖音订单对象 + /// 事件集合 + /// 数据库操作对象 + /// + public void UpdateOrder(fl_order_douyin db_order, List notice, SqlSugarClient session, bool isFrontData = false) + { + //维权中的订单,直接跳出 + if (db_order.db_status == SystemOrderStatus.订单维权中) + return; + try + { + fl_plugin_allrebatesactivity_orderlist allrebatesactivity_orderlist = null; + var old_status = db_order.db_status; + var status = Util.ConvertEnum(db_order.order_status.ToUpper()); + bool islotUserQuery = false;//订单是否为多人查询 + // string old_md5 = Util.GetMd5_32byte(HttpHelper.ObjectToJson(db_order)); + var isRewards = false;//是否获得推荐新人奖励 + var isFirstOrder = false;//是否获得用户首单奖励 + + #region 自动识别绑定 + #region 缓存绑定 + if (db_order.db_userid == 0 && status == DouyinOrderStatus.PAY_SUCC) + { + var bind = session.FindBindCache(db_order.order_id); + if (bind != null) + { + var memberInfo = session.FindMemberInfoById(bind.db_userid); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + db_order.msg_groupid = bind.groupid; + session.SaveOrUpdate(memberInfo); + //session.SaveOrUpdate(db_order); + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.product_id, adzoneid = db_order.db_cpsname, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.抖音联盟 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + } + } + #endregion + + if (db_order.db_userid == 0 && status == DouyinOrderStatus.PAY_SUCC) + { + #region 抖音返利推广位自动绑定 + + #region 私人推广位 + var privateAdzonePids = session.FindAlimamaPrivatePid(db_order.db_cpsname);//私人推广位对象 + if (privateAdzonePids.Count == 1 && privateAdzonePids[0].is_auto_bind)//无条件设置开启中,直接自动绑定 + { + var memberInfo = session.FindSingle("select * from fl_member_info where id = @id", new { id = privateAdzonePids[0].member_id }); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + //session.SaveOrUpdate(db_order); + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.product_id, adzoneid = db_order.db_cpsname, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.抖音联盟 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + } + } + #endregion + else + { + //var flag = false; + + //if (!flag) + //{ + //查询订单记录 + if (db_order.db_userid == 0) + { + var query = session.FindTable("select userid,count(*) as count from fl_query_hist where userid != 0 and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time group by userid ", new { itemid = db_order.product_id, adzoneid = db_order.db_cpsname, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query != null && query.Rows.Count > 0) + { + if (query.Rows.Count == 1) + { + if (ApiClient.Setting.SystemConfig.order_douyin_bind == SwitchType.开启) + { + var userid = int.Parse(query.Rows[0]["userid"].ToString());//要是查询记录已经标记为通知过的记录(userid 为 负数),将不通过查询记录进行绑定 + if (userid > 0) + { + db_order.db_userid = userid;//根据查询记录认领 + + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.product_id, adzoneid = db_order.db_cpsname, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.抖音联盟 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + db_order.msg_groupid = query_item.groupid; + } + } + } + } + else + { + //订单多人查询,并且订单还未绑定 + if (db_order.db_userid == 0) + islotUserQuery = true; + } + } + } + //} + } + #endregion + + #region 绑定群号 + if (string.IsNullOrWhiteSpace(db_order.msg_groupid)) + { + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.product_id, adzoneid = db_order.db_cpsname, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.抖音联盟 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + } + #endregion + } + #endregion + + if (db_order.order_status == DouyinOrderStatus.PAY_SUCC.ToString() && db_order.db_userid != 0) + { + try + { + var record = session.FindStatisticsRecord(db_order.db_userid); + if (record == null) + record = new fl_statistics_record() { uid = db_order.db_userid }; + record.ex5 = db_order.pay_time; + session.Saveable(record).ExecuteCommand(); + } + catch (Exception) + { } + } + + //查询积分比例 + var member = db_order.db_userid != 0 ? session.FindMemberInfoById(db_order.db_userid) : null; + + if (string.IsNullOrEmpty(db_order.db_robotname) && member != null) + { + db_order.db_robotname = member.robot_name; + db_order.db_robottype = member.robot_type; + } + + if (string.IsNullOrEmpty(db_order.db_point)) + { + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.抖音联盟, db_order.id); + + ItemPoint itempoint = null; + + //计算的佣金 + if (compute != null) + itempoint = session.FindItemPoint(CpsType.抖音联盟, compute, Util.ConvertDouble_FenToYuan(db_order.estimated_comission), 1); + else + itempoint = session.FindItemPoint(member, Util.ConvertDouble_FenToYuan(db_order.estimated_comission), 1, CpsType.抖音联盟); + if (itempoint != null) + { + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + db_order.db_userpoint = itempoint.UserPoint; + } + if (member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + } + + switch (status) + { + case DouyinOrderStatus.CONFIRM: + case DouyinOrderStatus.SETTLE: + { + //进入冻结逻辑 + if (db_order.db_endtime == DateTime.MinValue) + { + var sleep = session.FindSleep(CpsType.抖音联盟, ApiClient.Setting.SystemConfig.FreezingCondition == FreezingConditionType.商品总佣金 ? Util.ConvertDouble_FenToYuan(db_order.estimated_comission) : db_order.db_userpoint);//通过返佣获取订单冻结规则 + if (sleep != null) + { + if (!string.IsNullOrEmpty(sleep.white_groups)) + { + if (member != null && sleep.white_groups.Split(',').Contains(member.group_id.ToString())) + db_order.db_endtime = DateTime.Now;//该会员组不受限制 + else + db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else db_order.db_endtime = DateTime.Now; + + + + #region 验证订单是否为24小时 + var config = Util.Read>("插件-抖音返利-配置"); + if (config != null) + { + if (config.ContainsKey("ReceivingTimeCheck_Switch")) + { + var ReceivingTimeCheck_Switch = bool.Parse(config["ReceivingTimeCheck_Switch"].ToString()); + if (ReceivingTimeCheck_Switch) + { + if (config.ContainsKey("ReceivingTimeCheck_Hour")) + { + var ReceivingTimeCheck_Hour = int.Parse(config["ReceivingTimeCheck_Hour"].ToString()); + + var payTime = HttpExtend.GetDateTime(db_order.pay_time.ToString()); + + if ((DateTime.Now - payTime).TotalHours <= ReceivingTimeCheck_Hour)//判断订单收货时间差 + { + if (config.ContainsKey("ReceivingTimeCheck_OperateType")) + { + var ReceivingTimeCheck_OperateType = (OperateType)int.Parse(config["ReceivingTimeCheck_OperateType"].ToString()); + if (ReceivingTimeCheck_OperateType == OperateType.订单冻结) + { + if (config.ContainsKey("ReceivingTimeCheck_FreezeTime")) + { + var ReceivingTimeCheck_FreezeTime = int.Parse(config["ReceivingTimeCheck_FreezeTime"].ToString()); + db_order.db_endtime = db_order.db_endtime.AddHours(ReceivingTimeCheck_FreezeTime);//延迟多少小时 + } + } + } + } + } + } + } + } + #endregion + + } + + //已经传递了参数~ 这里就不要强制读数据库 + if (db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.订单结算; + + if (member != null && db_order.db_status != SystemOrderStatus.全额退款) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + if (point.UserPoint == 0) + { + point.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(point); + db_order.db_userpoint = point.UserPoint; + } + + #region 获取是否已经结算给客户 + var pointHists = session.Find("select * from fl_point_hist where uid = @uid and type = @pointType_name and message = @message", new { uid = member.id, pointType_name = PointType.消费补贴.ToString(), message = $"抖音购买:{db_order.product_name} - ({db_order.order_id})" }); + if (pointHists != null && pointHists.Count != 0) + { + session.SaveOrUpdate(db_order); + return; + } + #endregion + + //用户自身加积分 + member = session.ChangePoint(PointType.消费补贴, point.UserPoint, member.id, $"抖音购买:{db_order.product_name} - ({db_order.order_id})"); + + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + + List ids = new List(); + ids.Add(member.id); + //多级提成计算..用户自己的上级不能为自己 + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, Util.ConvertDouble_FenToYuan(db_order.total_pay_amount)); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + } + } + else if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardOne, member.inviter_id, $"{member.usernick},抖音购物1级提成!{db_order.product_name} - ({db_order.order_id})"); + if (flag != null) + { + ids.Add(flag.id); + if (notice != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, Util.ConvertDouble_FenToYuan(db_order.total_pay_amount)); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.提成奖励, point.AwardTwo, flag.inviter_id, $"{member.usernick},抖音购物2级提成!{db_order.product_name} - ({db_order.order_id})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (notice != null && flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.提成奖励, point.AwardThree, flag2.inviter_id, $"{member.usernick},抖音购物3级提成!{db_order.product_name} - ({db_order.order_id})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (notice != null && flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardCreate, create.mid, $"{member.usernick},抖音维护提成!{db_order.product_name} - ({db_order.order_id})"); + if (notice != null && flag != null) notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + Thread.Sleep(40); + } + else + { + //提示查询该宝贝的人所有人 + if (islotUserQuery) + { + notice.Add(new Events.OrderNoticeEvent(CpsType.抖音联盟, null, db_order)); + } + } + } + else + { + db_order.db_status = SystemOrderStatus.订单冻结; + } + } + break; + case DouyinOrderStatus.订单维权中: + db_order.db_status = SystemOrderStatus.订单维权中; + break; + case DouyinOrderStatus.PAY_SUCC: + { + db_order.db_status = SystemOrderStatus.订单付款; + } + break; + case DouyinOrderStatus.REFUND: + db_order.db_status = SystemOrderStatus.订单失效; + if (member != null)//订单还没有绑定用户 + { + if (db_order.db_endtime != DateTime.MinValue) //客户已经在冻结中 + { + if (db_order.db_endtime <= DateTime.Now) //佣金已经解冻 - 已经把佣金给客户(需要扣除佣金) + { + ItemPoint itempointTmp = null; + + var compute = session.FindQueryRatioHist(CpsType.抖音联盟, db_order.id); + + if (compute != null) + itempointTmp = session.FindItemPoint(CpsType.抖音联盟, compute, Util.ConvertDouble_FenToYuan(db_order.estimated_comission), 1); + else + //判断用户的订单是否已经结算,如果已经结算通过实际佣金进行退款,如果没有结算通过预计佣进行计算 + itempointTmp = session.FindItemPoint(member, Util.ConvertDouble_FenToYuan(db_order.estimated_comission), 1, CpsType.抖音联盟); + + + new OrderHelper().DeductDouYinOrderPoint(notice, db_order, itempointTmp); + + db_order.db_status = SystemOrderStatus.全额退款; + } + else + { + //if (itempoint != null) + //{ + // //用户自身加积分 + // //member = session.ChangePoint(PointType.维权扣除, itempoint.UserPoint, member.id, $"抖音购买:{db_order.skuName}({db_order.orderId}) - 售后中(扣除) - 订单还未结算(冻结中)"); + //} + } + } + db_order.db_endtime = DateTime.MinValue; + } + break; + default: + break; + } + + #region 通知客户订单付款/失效 提示上级 + if (member != null && (db_order.db_status == SystemOrderStatus.订单付款 || db_order.db_status == SystemOrderStatus.订单失效)) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + + if (point.UserPoint == 0 && ApiClient.Setting.SystemConfig.SubsidyTb == SwitchType.开启) + { + point.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(point); + db_order.db_userpoint = point.UserPoint; + } + + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + //一级用户对象 + var member_one = session.FindMemberInfoById(member.inviter_id); + if (member_one != null) + { + ids.Add(member_one.id); + if (notice != null) + notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, member_one, db_order, OrderNoticeType.一级提成) { Customer = member }); + if (point.AwardTwo > 0 && member_one.inviter_id != 0 && !ids.Contains(member_one.inviter_id)) + { + //二级用户对象 + var member_two = session.FindMemberInfoById(member_one.inviter_id); + if (member_two != null) + { + ids.Add(member_two.id); + if (member_two != null) + { + notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, member_two, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && member_two.inviter_id != 0 && !ids.Contains(member_two.inviter_id)) + { + //三级用户对象 + var member_three = session.FindMemberInfoById(member_two.inviter_id); + if (member_three != null) + { + ids.Add(member_three.id); + if (member_three != null) + notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, member_three, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var member_create = session.FindMemberInfoById(create.mid); + if (notice != null && member_create != null) notice.Add(new OrderNoticeEvent(CpsType.抖音联盟, member_create, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + #endregion + + //string new_md5 = Util.GetMd5_32byte(HttpHelper.ObjectToJson(db_order)); + if (old_status != db_order.db_status) + db_order.db_status_time = HttpExtend.GetTimeStamp(); + + session.SaveOrUpdate(db_order); + + if (db_order.db_status == SystemOrderStatus.订单付款) + { + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + } + + if (allrebatesactivity_orderlist != null) + { + allrebatesactivity_orderlist.oid = db_order.id; + session.Saveable(allrebatesactivity_orderlist).ExecuteCommand(); + } + + //if ((notice != null && old_status != db_order.db_status && order_id != db_order.trade_parent_id && member != null) || (notice != null && old_status != db_order.db_status && order_id != db_order.trade_parent_id && islotUserQuery && member == null)) + if (notice != null && (isFrontData || old_status != db_order.db_status) && ((islotUserQuery && member == null) || member != null)) + { + notice.Add(new Events.OrderNoticeEvent(CpsType.抖音联盟, member, db_order) { IsRewards = isFirstOrder }); + } + + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新抖音联盟订单异常1:" + db_order.db_cpsname + " - " + db_order.order_id + "," + ex.Message + "," + ex.StackTrace); + } + } + + } +} diff --git a/类库/Api.Framework/Timers/DownJingdongTimer.cs b/类库/Api.Framework/Timers/DownJingdongTimer.cs new file mode 100644 index 0000000..0fb1d1f --- /dev/null +++ b/类库/Api.Framework/Timers/DownJingdongTimer.cs @@ -0,0 +1,1121 @@ +using Api.Framework.Config; +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Timers +{ + /// + /// 京东订单下载定时器 + /// + public class DownJingdongTimer : TimerTask + { + + private static long number = 0; + private DateTime update_time = DateTime.Now.AddHours(-2); + public override void Run(object state, bool timedOut) + { + try + { + number++; + if (number % 30 == 0) update_time = DateTime.Now.AddHours(-12); + else if (number % 100 == 0) update_time = DateTime.Now.AddHours(-24); + else update_time = DateTime.Now.AddHours(-2); + + var not_onlines = CpsClient.Members.Where(f => f.cpstype == CpsType.京东联盟 && f.abnormal_tip == SwitchType.开启 && !f.online).ToList(); + if (not_onlines != null && not_onlines.Count != 0) + { + foreach (var cps in not_onlines) + { + var key = $"jingdong_not_online_{cps.usernick}"; + var value = ApiClient.Cache.Get(key); + if (string.IsNullOrWhiteSpace(value)) + { + var _session = ApiClient.GetSession(); + var robot = _session.FindRobots().FirstOrDefault(); + + StringBuilder strb = new StringBuilder(); + strb.AppendLine("京东状态异常"); + strb.AppendLine("---------------------"); + if (robot != null) + strb.AppendLine("所在机器人:" + robot.name); + + strb.AppendLine("京东ID:" + cps.usernick); + strb.AppendLine(); + strb.AppendLine("解决方法:重新授权Key后,重新登录"); + //ApiClient.SendNewDingdingMessage(strb.ToString()); + ApiClient.SendNoticeMessage(strb.ToString()); + ApiClient.Cache.Set(key, ".", 300); + Thread.Sleep(50); + } + } + } + + UpdateOrder(CpsClient.Members.Where(f => f.cpstype == CpsType.京东联盟 && f.online && f.is_download == SwitchType.开启).ToArray(), update_time); + + #region 更新冻结的订单 + var session = ApiClient.GetSession(); + var result = session.Find("db_status = @db_status and finishTime != @min and finishTime <= @now and db_endtime <= @endtime", new { db_status = 1001, min = DateTime.MinValue.ToString("yyyy-MM-dd HH:mm:ss"), now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") });//所有完成冻结,但是还没改状态的订单, + //var cpsnicks = result.Select(f => f.db_cpsnick).GroupBy(f => f).Select(f => f.Key).ToList(); + //TaskTool task = new TaskTool(); + + List notices = new List(); + + foreach (var order in result) + { + UpdateOrder(order, session, notices); + } + + //foreach (var _cpsnick in cpsnicks) + //{ + //var cpsnick = _cpsnick; + //var cps = CpsClient.Members.Where(f => f.cpstype == CpsType.京东联盟 && f.is_download == SwitchType.开启).ToList().FirstOrDefault(f => f.usernick == cpsnick); + //if (cps == null) continue; + //var client = new JingdongApi(cps); + + //task.AddTask(delegate + //{ + // try + // { + // var orderTimes = result.Where(f => f.db_cpsnick == cpsnick).Select(f => f.finishTime).OrderBy(f => f).ToList(); + // if (orderTimes.Count == 0) return; + + // if (orderTimes != null && orderTimes.Count != 0) + // { + // var time = orderTimes[0]; + // List times = new List() { time }; + // do + // { + // time = time.AddHours(1); + // var _time = orderTimes.FirstOrDefault(f => f > time); + // if (_time != DateTime.MinValue) + // { + // time = _time; + // times.Add(_time); + // } + // else + // break; + // } while (true); + + // if (times.Count > 0) + // { + // foreach (var _time in times) + // { + // ProcessOrder(_time, client, notices); + // } + // } + // } + + // if (notices.Count != 0) + // { + // var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + // foreach (var item in notices) + // { + // if (item.Member == null) continue; + // var order = item.Order as fl_order_jingdong; + // if (order.orderId.ToString() == order_id) continue; + // tasks.Add(item); + // } + // } + + // } + // catch (Exception ex) + // { + // EventClient.OnEvent(this, "更新阿里妈妈异常:" + ex.Message); + // } + //}); + //} + //task.Start(1, null); + + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_jingdong; + if (order.orderId.ToString() == order_id) continue; + tasks.Add(item); + } + } + #endregion + + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"更新京东异常:{ex.Message},{ex.StackTrace}"); + } + } + + /// + /// 手动同步订单 + /// + /// 京东cps对象集合 + /// 开始同步的时间 + public void UpdateOrder(List members, DateTime start_time) + { + foreach (var member in members) + { + if (!member.online) + EventClient.OnEvent(this, $"【{member.usernick}】该账号失效,请重新生成京东联盟Key"); + } + members = members.Where(f => f.online).ToList(); + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + //start_time = DateTime.Now.AddDays(-1);//TODO 由于调用量有限京东只能同步1天,以后要删除的 + UpdateOrder(members.ToArray(), start_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新京东订单异常:" + ex.Message); + } + finally + { + IsRunning = false; + } + } + + /// + /// 京东下载订单执行 + /// + /// 京东cps对象集合 + /// 开始同步的时间 + private void UpdateOrder(fl_cps_member[] members, DateTime start_time) + { + if (members == null || members.Length == 0) return; + int pageCount = 100;//下载每页的数量 + //var session = ApiClient.GetSession(); + TaskTool task = new TaskTool(); + List notices = new List(); + + foreach (var item in members) + { + var _item = item; + var client = new JingdongApi(_item); + + task.AddTask(delegate + { + var end_time = DateTime.Now; + try + { + do + { + if (!ProcessOrder(end_time, client, notices).Result) + { + break; + } + + //就近原则,先更新最近的 + end_time = end_time.AddHours(-1); + + //多账号,多线程处理的时候,肯定有问题 + // start_time = start_time.AddHours(1); //增加一小时 + } + while (end_time > start_time);//当前结束时间,必须大于启动时间,否则退出 + } + catch (Exception ex) + { + if (ex.Message == "京东繁忙,请稍后再试") + EventClient.OnEvent(this, "更新京东联盟订单异常:" + ex.Message + ",已终止操作"); + else + EventClient.OnEvent(this, "更新京东联盟订单异常:" + ex.Message); + } + }); + } + task.Start(1, null); + + + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_jingdong; + if (order.orderId.ToString() == order_id) continue; + tasks.Add(item); + } + } + + } + + /// + /// 无效的订单类型 + /// + private static List InvalidValidCodes = new List() { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 25, 26, 27, 28 }; + + /// + /// 处理下载到的订单 + /// + /// + /// + /// + /// + /// + private Task ProcessOrder(DateTime time, JingdongApi client, List notices) + { + Thread.Sleep(10); + return Task.Run(() => + { + try + { + var cps = client.Member; + #region 处理每一个小时的订单 + bool hasMore = false; //是否还有更多数据【true:还有数据;false:已查询完毕,没有数据】 + int page_index = 1; //当前查询的页数 + Dictionary result = null; + do + { + try + { + //订单时间查询类型(1:下单时间, 2:完成时间, 3:更新时间) + #region 更新时间 + //2019-08-19 12:15:01 + result = client.DownOrder(time, cps.username, page_index, 500, 3); + if (result == null) break; + if (result["code"].ToString() != "200") throw new Exception($"京东订单下载失败 - 下单时间:{time.ToString("yyyy-MM-dd HH:mm:ss")} - {result["message"]}"); + if (result.ContainsKey("data")) + { + var orders = result["data"] as ArrayList; + if (orders != null && orders.Count > 0) + { + int count = 1; + foreach (Dictionary order in orders) + { + count++; + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(200); + var session = ApiClient.GetSession(); + try + { + if (order["orderId"].ToString() == "250364082656") + { + } + + var db_orders = session.Find("orderId = @orderId", new { orderId = order["orderId"].ToString() }).ToList(); + + //var orderTime = long.Parse(order["orderTime"].ToString());//下单时间 + //var finishTime = long.Parse(order["finishTime"].ToString());//完成时间 + var orderTime = string.IsNullOrWhiteSpace(order["orderTime"].ToString()) ? DateTime.MinValue : DateTime.Parse(order["orderTime"].ToString());//下单时间 + var finishTime = string.IsNullOrWhiteSpace(order["finishTime"].ToString()) ? DateTime.MinValue : DateTime.Parse(order["finishTime"].ToString());//完成时间 + var modifyTime = string.IsNullOrWhiteSpace(order["modifyTime"].ToString()) ? DateTime.MinValue : DateTime.Parse(order["modifyTime"].ToString());//更新时间,格式yyyy-MM-dd HH:mm:ss + + //if (order["parentId"].ToString() != "0")//存在拆单数据 + //{ //父类ID非等于0的不处理 + //if (order.ContainsKey("skuList")) + //if (order.ContainsKey("orderRowResp")) + //{ + #region 是否是plus会员下单 plus + int plus = 0; + if (order.ContainsKey("plus")) plus = int.Parse(order["plus"].ToString()); + #endregion + + //var skuList = order["orderRowResp"] as ArrayList; + //foreach (Dictionary sku in skuList) + //{ + if (order.ContainsKey("estimateCosPrice") && double.Parse(order["estimateCosPrice"].ToString()) == 0) continue; + if (order.ContainsKey("positionId")) + { + var positionId = order["positionId"].ToString(); + + if (ApiClient.Setting.SystemConfig.order_jingdong_download_set_pids == SwitchType.关闭) + { + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.order_jingdong_not_download_pid)) + { + var pids = ApiClient.Setting.SystemConfig.order_jingdong_not_download_pid.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + var isExist = (pids.FirstOrDefault(f => f.EndsWith(positionId)) != null); + if (ApiClient.Setting.SystemConfig.order_jingdong_down_type == DownAdzoneType.不下载推广位 && isExist) + continue; + else if (ApiClient.Setting.SystemConfig.order_jingdong_down_type == DownAdzoneType.只下载推广位 && !isExist) + continue; + } + } + else + { + //var adzone = session.FindAdzoneInfos().Where(f => f.custom_type == "京东返利" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.EndsWith(positionId)); + + var adzoneList = new List(); + var adzones = session.FindAdzoneInfos(); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "京东返利" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.EndsWith(positionId))); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "用户私人pid" && f.extend == "京东私人pid" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.EndsWith(positionId))); + if (adzoneList == null || adzoneList.Count() == 0) + { + continue; + } + } + } + + //2021年1月26日 之前老版 + //sku维度的有效码(-1:未知,2.无效-拆单,3.无效-取消,4.无效-京东帮帮主订单,5.无效-账号异常,6.无效-赠品类目不返佣,7.无效-校园订单,8.无效-企业订单,9.无效-团购订单,10.无效-开增值税专用发票订单,11.无效-乡村推广员下单,13.无效-违规订单,14.无效-来源与备案网址不符,15.待付款,16.已付款,17.已完成,18.已结算(5.9号不再支持结算状态回写展示)) + + //-1:未知,2.无效-拆单,3.无效-取消,4.无效-京东帮帮主订单,5.无效-账号异常,6.无效-赠品类目不返佣,7.无效-校园订单,8.无效-企业订单,9.无效-团购订单,10.无效-开增值税专用发票订单,11.无效-乡村推广员下单,12.无效-自己推广自己下单,13.无效-违规订单,14.无效-来源与备案网址不符,15.待付款,16.已付款,17.已完成,18.已结算 //自定义 19.售后中 //自定义 20.结算后失效 + + //2021年1月26日 之后新版 + //sku维度的有效码(-1:未知,2.无效-拆单,3.无效-取消,4.无效-京东帮帮主订单,5.无效-账号异常,6.无效-赠品类目不返佣,7.无效-校园订单,8.无效-企业订单,9.无效-团购订单,11.无效-乡村推广员下单,13.无效-违规订单,14.无效-来源与备案网址不符,15.待付款,16.已付款,17.已完成(购买用户确认收货),20.无效-此复购订单对应的首购订单无效,21.无效-云店订单,22. 无效-PLUS会员佣金比例为0 19.售后中 //自定义 + + //2021年10月21日 之后新版 + //sku维度的有效码(-1:未知,2.无效 - 拆单,3.无效 - 取消,4.无效 - 京东帮帮主订单,5.无效 - 账号异常,6.无效 - 赠品类目不返佣,7.无效 - 校园订单,8.无效 - 企业订单,9.无效 - 团购订单,11.无效 - 乡村推广员下单,13.无效 - 违规订单,14.无效 - 来源与备案网址不符,15.待付款,16.已付款,17.已完成(购买用户确认收货),20.无效 - 此复购订单对应的首购订单无效,21.无效 - 云店订单,22.无效 - PLUS会员佣金比例为0,23.无效 - 支付有礼,24.已付定金,25. 违规订单-流量劫持,26. 违规订单-流量异常,27. 违规订单-违反京东平台规则,28. 违规订单-多笔交易异常 19.售后中 //自定义 + + var validCode = int.Parse(order["validCode"].ToString()); + var proPriceAmount = double.Parse(order["proPriceAmount"].ToString()); + + if (decimal.Parse(order["commissionRate"].ToString()) == 0m) continue; //无佣金的订单不下载(订单状态:已完成/已结算) + + if (validCode != 2)//不处理拆单 - 无效 + { + var jingdong_order = db_orders.FirstOrDefault(f => f.orderId == long.Parse(order["orderId"].ToString()) && f.skuId == long.Parse(order["skuId"].ToString())); + if (jingdong_order != null) //订单存在 - 判断订单状态是否一样,一样不处理 + { + var validCode_temp = jingdong_order.validCode; + #region 存在售后订单 + //var _validCode = validCode; + var frozenSkuNum = long.Parse(order["skuFrozenNum"].ToString());//商品售后中数量 + + var skuReturnNum = long.Parse(order["skuReturnNum"].ToString());//商品退货数量 + + if (frozenSkuNum != 0)//订单信息中存在维权的情况 + { + if (jingdong_order.db_status != SystemOrderStatus.订单维权中) + { + //if (frozenSkuNum != 0)//这里判断是否为售后状态,数量为0时没有售后订单 + //{ + jingdong_order.frozenSkuNum = frozenSkuNum;//售后中的数量,这个变量不为空,实际佣金和实际计算佣金的金额会变成0 + jingdong_order.refundcreatetime = DateTime.Now; + validCode = 19; + //} + } + else + { + if (jingdong_order.frozenSkuNum == frozenSkuNum)//维权数量一致时,跳过 + continue; + } + } + else if (jingdong_order.skuReturnNum != skuReturnNum && validCode == 17 && jingdong_order.db_status != SystemOrderStatus.全额退款 && jingdong_order.db_status != SystemOrderStatus.部分退款) + { + jingdong_order.skuReturnNum = skuReturnNum; + if (jingdong_order.db_status == SystemOrderStatus.订单结算) + validCode = 20; + } + else//订单信息中不存在维权的情况,判断订单是已经结算 + { + //if (jingdong_order.db_status != SystemOrderStatus.订单维权中) + // if (jingdong_order.IsFinish()) continue;//是否已经完成 + + + if (jingdong_order.db_status != SystemOrderStatus.订单维权中) + { + if (jingdong_order.db_status == SystemOrderStatus.订单结算 && InvalidValidCodes.Contains(validCode) && validCode_temp != validCode) + { + validCode = 20; + } + else if (jingdong_order.IsFinish())//是否已经完成 + { + continue; + } + } + } + #endregion + + if (validCode_temp == validCode && jingdong_order.db_status != SystemOrderStatus.订单冻结) + continue; + + jingdong_order.validCode = validCode;//更新状态 + jingdong_order.finishTime = finishTime; + jingdong_order.skuReturnNum = long.Parse(order["skuReturnNum"].ToString());//商品已退货数量 + jingdong_order.frozenSkuNum = long.Parse(order["skuFrozenNum"].ToString());//商品售后中数量 + + + #region 这里重新赋值实际的佣金和计算佣金的金额( + //1、售后中两个金额将为0 + //2、订单收货后两个金额将有实际的佣金值) + jingdong_order.actualFee = double.Parse(order["actualFee"].ToString());//实际佣金 + jingdong_order.actualCosPrice = double.Parse(order["actualCosPrice"].ToString());//实际计算佣金的金额 + #endregion + + if (jingdong_order.db_status == SystemOrderStatus.订单维权中 && (jingdong_order.validCode == 17 || jingdong_order.validCode == 18)) + { + jingdong_order.db_status = SystemOrderStatus.订单退款; + } + } + else + { + if (order.ContainsKey("id")) + order.Remove("id"); + + //订单不存在 - 增加 + jingdong_order = order.ConvertToObj(); + jingdong_order.frozenSkuNum = long.Parse(order["skuFrozenNum"].ToString()); + //不保存,赠送商品 + if (jingdong_order.price == 0d) continue; + + jingdong_order.orderId = long.Parse(order["orderId"].ToString()); + jingdong_order.db_cpsname = cps.username; + jingdong_order.db_cpsnick = cps.usernick; + jingdong_order.orderTime = orderTime; + jingdong_order.finishTime = finishTime; + //if (validCode == 16 || validCode == 24) + // jingdong_order.db_status = SystemOrderStatus.订单付款; + + #region 佣金比例京东联盟 + //var estimateFee = decimal.Round((decimal)jingdong_order.estimateCosPrice * (decimal)jingdong_order.commissionRate * (decimal)jingdong_order.finalRate, 2, MidpointRounding.AwayFromZero); ;//预计佣金 + //var actualFee = decimal.Round((decimal)jingdong_order.actualCosPrice * (decimal)jingdong_order.commissionRate * (decimal)jingdong_order.finalRate, 2, MidpointRounding.AwayFromZero);//实际佣金 + #endregion + if (jingdong_order.frozenSkuNum != 0) + { + jingdong_order.refundcreatetime = DateTime.Now; + jingdong_order.validCode = 19; + } + } + jingdong_order.proPriceAmount = proPriceAmount; + jingdong_order.plus = plus; + UpdateOrder(jingdong_order, session, notices); + } + else //拆单订单变成无效 + { + var jingdong_order = db_orders.FirstOrDefault(f => f.orderId == long.Parse(order["orderId"].ToString()) && f.skuId == long.Parse(order["skuId"].ToString())); + if (jingdong_order != null) + { + if (jingdong_order.IsFinish()) continue;//是否已经完成 + jingdong_order.validCode = 2; + jingdong_order.db_status = SystemOrderStatus.订单失效; + session.SaveOrUpdate(jingdong_order); + } + } + // } + //} + } + catch (Exception ex) + { + throw ex; + } + } + } + } + #endregion + } + catch (Exception ex) + { + if (ex.Message == "京东key失效" || ex.Message == "授权key无权限或错误") + { + EventClient.OnEvent(this, $"更新京东联盟订单异常:{ex.Message} - {ex.StackTrace}"); + var _cps = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.京东联盟 && f.username == cps.username && f.usernick == cps.usernick); + _cps.online = false; + var session = ApiClient.GetSession(); + session.Updateable(_cps).ExecuteCommand(); + return false; + } + if (ex.Message == "京东繁忙,请稍后再试") + throw ex; + EventClient.OnEvent(this, $"同步京东订单列表出错:{ex.Message} - {ex.StackTrace}"); + } + page_index++; + Thread.Sleep(50); //请求接口太快,用于减速 + } while (result != null && result.Count != 0 && result.ContainsKey("hasMore") && result["hasMore"].ToString().ToLower() == "true");//是否存在更多的数据,存在去加载下一页数据 + #endregion + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"同步京东出错:{ex.Message} - {ex.StackTrace}"); + return false; + } + return true; + }); + } + + /// + /// 订单 修改状态/用户绑定等操作通知用户 + /// + /// 京东订单对象 + /// 数据库操作对象 + /// 事件集合 + /// + public void UpdateOrder(fl_order_jingdong db_order, SqlSugarClient session, List notices, bool isFrontData = false) + { + try + { + //维权中的订单,直接跳出 + if (db_order.db_status == SystemOrderStatus.订单维权中) + return; + + var old_status = db_order.db_status; + fl_member_info member = null; + var isRewards = false;//是否获得推荐新人奖励 + var isFirstOrder = false;//是否获得用户首单奖励 + #region 缓存绑定 + if (db_order.db_userid == 0 && (db_order.validCode == 16 || db_order.validCode == 24)) + { + var bind = session.FindBindCache(db_order.orderId.ToString()); + if (bind != null) + { + var memberInfo = session.FindMemberInfoById(bind.db_userid); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + db_order.msg_groupid = bind.groupid; + session.SaveOrUpdate(memberInfo); + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.skuId, adzoneid = db_order.positionId, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.京东联盟 + }; + LogHelper.GetSingleObj().Error("历史查询记录1", JsonConvert.SerializeObject(queryRatioHist)); + session.SaveOrUpdate(queryRatioHist); + } + #endregion + } + } + } + #endregion + + //订单自动绑定 + if (db_order.db_userid == 0 && (db_order.validCode == 16 || db_order.validCode == 24) && ApiClient.Setting.SystemConfig.order_jingdong_bind == SwitchType.开启) + { + #region 京东返利进行自动绑定 + + #region 私人推广位 + var privateAdzonePids = session.FindJingdongPrivatePid(db_order.positionId.ToString());//私人推广位对象 + //var privatePids = privateAdzonePids.Select(f => f.adzone_pid).ToList(); + if (privateAdzonePids.Count == 1 && privateAdzonePids[0].is_auto_bind)//无条件设置开启中,直接自动绑定 + { + var memberInfo = session.Find("id=@id", new { id = privateAdzonePids[0].member_id }).FirstOrDefault(); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + + #region 绑定群号 + if (string.IsNullOrWhiteSpace(db_order.msg_groupid)) + { + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.skuId, adzoneid = db_order.positionId, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.京东联盟 + }; + LogHelper.GetSingleObj().Error("历史查询记录2", JsonConvert.SerializeObject(queryRatioHist)); + session.SaveOrUpdate(queryRatioHist); + } + db_order.msg_groupid = query_item.groupid; + } + } + #endregion + } + } + #endregion + else + { + var bind_pids = session.FindJingdongAutoBindPid(); + bind_pids.AddRange(privateAdzonePids.Select(f => f.adzone_pid)); + bool support = bind_pids.FirstOrDefault(f => f.EndsWith("_" + db_order.positionId)) != null ? true : false;//TODO 这里的站长ID还是完整的 xxx_x_xxx + //bool support = bind_pids.FirstOrDefault(f => db_order.pid.StartsWith(f + "_")) != null ? true : false;//这里的站长ID还是完整的 xxx_x_xxx + + if (support) + { + #region 通过查询记录找用户 + var query = session.FindTable("select userid,count(*) as count from fl_query_hist where itemid=@itemid and adzoneid = @adzoneid and crt_time>@time group by userid ", new { itemid = db_order.skuId, adzoneid = db_order.positionId, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query.Rows.Count == 1) + { + db_order.db_userid = int.Parse(query.Rows[0]["userid"].ToString()); //根据查询记录认领 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.skuId, adzoneid = db_order.positionId, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.京东联盟 + }; + LogHelper.GetSingleObj().Error("历史查询记录3", JsonConvert.SerializeObject(queryRatioHist)); + session.SaveOrUpdate(queryRatioHist); + } + + db_order.msg_groupid = query_item.groupid; //订单查询群号 + } + } + #endregion + } + } + #endregion + } + + if ((db_order.validCode == 16 || db_order.validCode == 24) && db_order.db_userid != 0) + { + try + { + var record = session.FindStatisticsRecord(db_order.db_userid); + if (record == null) + record = new fl_statistics_record() { uid = db_order.db_userid }; + record.ex5 = HttpExtend.GetTimeStamp(db_order.orderTime); + session.Saveable(record).ExecuteCommand(); + } + catch (Exception) + { } + } + + member = db_order.db_userid != 0 ? session.FindSingle("select * from fl_member_info where id=@id", new { id = db_order.db_userid }) : null; + if (string.IsNullOrEmpty(db_order.db_robotname) && member != null) //订单没有绑定机器人账号 & 用户存在 (进行机器人账号和机器人类型绑定) + { + member.username = member.username; + db_order.db_robotname = member.robot_name; + db_order.db_robottype = member.robot_type; + } + + var status = Util.ConvertEnum(db_order.validCode); + + //if (string.IsNullOrEmpty(db_order.db_point)) //进行用户所得佣金计算 + //{ + + #region 积分随着订单状态的改变而改变 + double fee = 0d; //实际佣金和预计佣金 + switch (status) + { + case JingdongOrderStatus.未知: + case JingdongOrderStatus.无效_拆单: + case JingdongOrderStatus.无效_取消: + case JingdongOrderStatus.无效_京东帮帮主订单: + case JingdongOrderStatus.无效_账号异常: + case JingdongOrderStatus.无效_赠品类目不返佣: + case JingdongOrderStatus.无效_校园订单: + case JingdongOrderStatus.无效_企业订单: + case JingdongOrderStatus.无效_团购订单: + case JingdongOrderStatus.无效_开增值税专用发票订单: + case JingdongOrderStatus.无效_乡村推广员下单: + case JingdongOrderStatus.无效_自己推广自己下单: + case JingdongOrderStatus.无效_违规订单: + case JingdongOrderStatus.无效_来源与备案网址不符: + fee = db_order.estimateFee;//订单取消这里使用 预估佣金 + break; + case JingdongOrderStatus.结算后失效: + case JingdongOrderStatus.已完成: + case JingdongOrderStatus.已结算: + //if (db_order.proPriceAmount == 0) + fee = (db_order.actualFee != 0 ? db_order.actualFee : db_order.estimateFee); //实际佣金 + //else + // fee = 0;//价保赔付金额不为空,将佣金设置为0;...搞不清楚这个是什么完样 + break; + case JingdongOrderStatus.待付款: + case JingdongOrderStatus.已付款: + case JingdongOrderStatus.售后中: + case JingdongOrderStatus.已付定金: + fee = db_order.estimateFee; //预计佣金 + break; + default: + break; + } + + ItemPoint itempoint = null; + + if (db_order.db_status != SystemOrderStatus.订单冻结) + { + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.京东联盟, db_order.id); + + if (compute != null) + itempoint = session.FindItemPoint(CpsType.京东联盟, compute, fee, (int)db_order.skuNum); + else + itempoint = session.FindItemPoint(member, fee, (int)db_order.skuNum, CpsType.京东联盟); + if (itempoint != null) + { + if (itempoint.UserPoint == 0 && ApiClient.Setting.SystemConfig.SubsidyJd == SwitchType.开启) + itempoint.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + db_order.db_userpoint = itempoint.UserPoint; + } + if (db_order.db_status == SystemOrderStatus.订单付款 && member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + } + else + itempoint = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + #endregion + + //} + + switch (status) + { + case JingdongOrderStatus.已完成: + case JingdongOrderStatus.已结算: + { + if (db_order.actualCosPrice == 0d && db_order.skuNum == db_order.skuReturnNum) + { + db_order.db_status = SystemOrderStatus.全额退款; + db_order.db_endtime = DateTime.Now.AddMinutes(-1); + //old_status = SystemOrderStatus.全额退款; //不处理,不通知用户 + } + if (db_order.db_status != SystemOrderStatus.全额退款) + { + if (db_order.db_endtime == DateTime.MinValue) //客户还没有结算 + { + var sleep = session.FindSleep(CpsType.京东联盟, ApiClient.Setting.SystemConfig.FreezingCondition == FreezingConditionType.商品总佣金 ? db_order.actualFee : db_order.db_userpoint); //计算延迟冻结时间 + if (sleep != null) + { + if (!string.IsNullOrEmpty(sleep.white_groups)) + { + if (member != null && sleep.white_groups.Split(',').Contains(member.group_id.ToString())) + { + db_order.db_endtime = DateTime.Now; //该会员组不受限制 + } + else + { + db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep); //延迟多少小时 + } + } + else db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep); //延迟多少小时 + } + else db_order.db_endtime = DateTime.Now; + } + + if (db_order.db_endtime > DateTime.Now) //佣金解冻 + { + db_order.db_status = SystemOrderStatus.订单冻结; + //if (db_order.actualCosPrice == 0d) + //{ + // db_order.db_status = SystemOrderStatus.全额退款; + // db_order.db_endtime = DateTime.Now.AddMinutes(-1); + // //old_status = SystemOrderStatus.全额退款; //不处理,不通知用户 + //} + } + else + { + db_order.db_status = SystemOrderStatus.订单结算; + + //if (db_order.skuReturnNum == db_order.skuNum && db_order.actualCosPrice == 0d) + // db_order.db_status = SystemOrderStatus.全额退款; + ////else if (db_order.skuReturnNum != db_order.skuNum) + //// db_order.db_status = SystemOrderStatus.部分退款; + + session.SaveOrUpdate(db_order); + if (member != null) + { + if (itempoint != null) + { + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.消费补贴, itempoint.UserPoint, member.id, $"京东购买:{db_order.skuName}({db_order.orderId})"); + + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + + //多级提成计算 + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (itempoint.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notices != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.estimateCosPrice); + #endregion + + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + } + } + else if (itempoint.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.提成奖励, itempoint.AwardOne, member.inviter_id, $"{member.usernick},京东购物1级提成! - {db_order.skuName}({db_order.orderId})"); + if (flag != null) + { + ids.Add(flag.id); + + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.estimateCosPrice); + #endregion + + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + + if (itempoint.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.提成奖励, itempoint.AwardTwo, flag.inviter_id, $"{member.usernick},京东购物2级提成! - {db_order.skuName}({db_order.orderId})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (itempoint.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.提成奖励, itempoint.AwardThree, flag2.inviter_id, $"{member.usernick},京东购物3级提成! - {db_order.skuName}({db_order.orderId})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notices.Add(new OrderNoticeEvent(CpsType.京东联盟, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (itempoint.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.提成奖励, itempoint.AwardCreate, create.mid, $"{member.usernick},京东维护提成! - {db_order.skuName}({db_order.orderId})"); + if (flag != null) notices.Add(new OrderNoticeEvent(CpsType.京东联盟, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + } + } + } + break; + } + case JingdongOrderStatus.售后中: + case JingdongOrderStatus.结算后失效: + { + if (status == JingdongOrderStatus.结算后失效) + { + if (db_order.actualCosPrice == 0d && db_order.skuNum == db_order.skuReturnNum) + { + db_order.db_status = SystemOrderStatus.全额退款; + db_order.db_endtime = DateTime.Now.AddMinutes(-1); + //old_status = SystemOrderStatus.全额退款; //不处理,不通知用户 + } + else + { + db_order.db_status = SystemOrderStatus.订单失效; + db_order.validCode = 2; + } + } + else + db_order.db_status = SystemOrderStatus.订单维权中; + + if (member != null)//订单还没有绑定用户 + { + if (db_order.db_endtime != DateTime.MinValue) //客户已经在冻结中 + { + if (db_order.db_endtime <= DateTime.Now) //佣金已经解冻 - 已经把佣金给客户(需要扣除佣金) + { + ItemPoint itempointTmp = null; + + var compute = session.FindQueryRatioHist(CpsType.京东联盟, db_order.id); + + if (compute != null) + itempointTmp = session.FindItemPoint(CpsType.京东联盟, compute, (db_order.actualFee != 0 ? db_order.actualFee : db_order.estimateFee), (int)db_order.skuNum); + else + //判断用户的订单是否已经结算,如果已经结算通过实际佣金进行退款,如果没有结算通过预计佣进行计算 + itempointTmp = session.FindItemPoint(member, (db_order.actualFee != 0 ? db_order.actualFee : db_order.estimateFee), (int)db_order.skuNum, CpsType.京东联盟); + new OrderHelper().DeductJingDongOrderPoint(notices, db_order, itempointTmp); + } + else + { + //if (itempoint != null) + //{ + // //用户自身加积分 + // //member = session.ChangePoint(PointType.维权扣除, itempoint.UserPoint, member.id, $"京东购买:{db_order.skuName}({db_order.orderId}) - 售后中(扣除) - 订单还未结算(冻结中)"); + //} + } + } + db_order.db_endtime = DateTime.MinValue; + } + } + break; + case JingdongOrderStatus.已付款: + case JingdongOrderStatus.已付定金: + { + db_order.db_status = SystemOrderStatus.订单付款; + } + break; + case JingdongOrderStatus.无效_乡村推广员下单: + case JingdongOrderStatus.无效_京东帮帮主订单: + case JingdongOrderStatus.无效_企业订单: + case JingdongOrderStatus.无效_取消: + case JingdongOrderStatus.无效_团购订单: + case JingdongOrderStatus.无效_开增值税专用发票订单: + case JingdongOrderStatus.无效_拆单: + case JingdongOrderStatus.无效_来源与备案网址不符: + case JingdongOrderStatus.无效_校园订单: + case JingdongOrderStatus.无效_自己推广自己下单: + case JingdongOrderStatus.无效_账号异常: + case JingdongOrderStatus.无效_赠品类目不返佣: + case JingdongOrderStatus.无效_违规订单: + case JingdongOrderStatus.违规订单流量劫持: + case JingdongOrderStatus.违规订单流量异常: + case JingdongOrderStatus.违规订单违反京东平台规则: + case JingdongOrderStatus.违规订单多笔交易异常: + db_order.db_status = SystemOrderStatus.订单失效; + break; + case JingdongOrderStatus.待付款: + db_order.db_status = SystemOrderStatus.订单创建; + break; + //case JingdongOrderStatus.已完成: + // break; + default: + db_order.db_status = SystemOrderStatus.订单未知; + break; + } + + #region 通知客户订单付款/失效 提示上级 + if (member != null && (db_order.db_status == SystemOrderStatus.订单付款 || db_order.db_status == SystemOrderStatus.订单失效)) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + //一级用户对象 + var member_one = session.FindMemberInfoById(member.inviter_id); + if (member_one != null) + { + ids.Add(member_one.id); + if (notices != null) + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, member_one, db_order, OrderNoticeType.一级提成) { Customer = member }); + if (point.AwardTwo > 0 && member_one.inviter_id != 0 && !ids.Contains(member_one.inviter_id)) + { + //二级用户对象 + var member_two = session.FindMemberInfoById(member_one.inviter_id); + if (member_two != null) + { + ids.Add(member_two.id); + if (notices != null && member_two != null) + { + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, member_two, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && member_two.inviter_id != 0 && !ids.Contains(member_two.inviter_id)) + { + //三级用户对象 + var member_three = session.FindMemberInfoById(member_two.inviter_id); + if (member_three != null) + { + ids.Add(member_three.id); + if (notices != null && member_three != null) + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, member_three, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var member_create = session.FindMemberInfoById(create.mid); + if (notices != null && member_create != null) notices.Add(new OrderNoticeEvent(CpsType.京东联盟, member_create, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + #endregion + + if (old_status != db_order.db_status) + db_order.db_status_time = HttpExtend.GetTimeStamp(); + session.SaveOrUpdate(db_order); + + if (db_order.db_status == SystemOrderStatus.订单付款) + { + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + } + + //if (notices != null && old_status != db_order.db_status) + // notices.Add(new Events.OrderNoticeEvent(CpsType.京东联盟, member, db_order, OrderNoticeType.客户订单)); + if (notices != null && member != null && (isFrontData || old_status != db_order.db_status)) + notices.Add(new Events.OrderNoticeEvent(CpsType.京东联盟, member, db_order) { IsRewards = isFirstOrder }); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新京东订单错误 - 更新状态/订单绑定:" + db_order.orderId + "," + ex.Message + "," + ex.StackTrace); + } + } + + /// + /// 订单id + /// + private string order_id = string.Empty; + + /// + /// 更新订单 + /// + /// 开始时间 + /// 订单id + /// + internal bool UpdateOrder(DateTime start_time, string order_id = "") + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + this.order_id = order_id; + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.京东联盟 && f.is_download == SwitchType.开启 && f.online).ToArray(); + UpdateOrder(members, start_time); + return true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新京东联盟异常:" + ex.Message + "," + ex.StackTrace); + return false; + } + finally + { + this.order_id = string.Empty; + IsRunning = false; + } + } + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Timers/DownKuaiShouTimer.cs b/类库/Api.Framework/Timers/DownKuaiShouTimer.cs new file mode 100644 index 0000000..9e36509 --- /dev/null +++ b/类库/Api.Framework/Timers/DownKuaiShouTimer.cs @@ -0,0 +1,773 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Api.Framework.Cps; +using Api.Framework.EntityTmp.KuaiShou; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Extents; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using SqlSugar; + +namespace Api.Framework.Timers +{ + public class DownKuaiShouTimer : TimerTask + { + private DateTime update_time = DateTime.Now.AddMinutes(-60); + public override void Run(object state, bool timedOut) + { + var endTime = DateTime.Now; + UpdateOrder(CpsClient.Members.Where(f => f.cpstype == CpsType.快手联盟 && f.is_download == SwitchType.开启).ToArray(), update_time, endTime); + update_time = DateTime.Now.AddMinutes(-20); + } + + /// + /// 手动同步订单 + /// + /// 快手cps对象集合 + /// 开始时间 + /// 结束时间 + public void UpdateOrder(List members, DateTime start_time, DateTime end_time) + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + + UpdateOrder(members.ToArray(), start_time, end_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"更新快手订单异常:{ex.Message} - {ex.StackTrace}"); + } + finally + { + IsRunning = false; + } + } + + /// + /// 同步订单 + /// + /// 快手cps对象集合 + /// 开始时间 + /// 结束时间 + private void UpdateOrder(fl_cps_member[] members, DateTime start_time, DateTime end_time) + { + if (members == null || members.Length == 0) return; + + UnValidCpsMember(members); + + int row_count = 50; //间隔 + var timespan = end_time - start_time; + TaskTool task = new TaskTool(); + List notices = new List(); + var not_download_pids = ApiClient.Setting.SystemConfig.order_kuaishou_not_download_pid.Replace(",", ",") + .Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + members = members.Where(f => f.is_valid).ToArray(); + + foreach (var item in members) + { + var _item = item; + var client = new KuaiShouApi(_item); + task.AddTask(delegate + { + try + { + var _star = timespan.TotalHours > 24 ? end_time : start_time; //倒叙24小时一个间断 + var _end = end_time; + do + { + if (timespan.TotalHours > 24) + { + _end = _star; + _star = _star.AddHours(-23.99); + } + client.DownOrder(_star, _end, OrderHandle, ""); + } while (_star > start_time); + + #region 处理完成冻结订单 + var session = ApiClient.GetSession(); + var end_orders = session.Find("select * from fl_order_kuaishou where db_status=@db_status and db_endtime<@db_endtime", new { db_status = (int)SystemOrderStatus.订单冻结, db_endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ToList(); + foreach (var db_order in end_orders) + { + UpdateOrder(db_order, session, notices); + } + #endregion + } + catch (Exception ex) + { + //throw ex; + } + }); + } + + task.Start(1, null); + + //if (string.IsNullOrEmpty(order_id)) + //{ + // var session = ApiClient.GetSession(); + // var end_orders = session.Find("select * from fl_order_kuaishou where db_status=@db_status and db_endtime<@db_endtime", new { db_status = (int)SystemOrderStatus.订单冻结, db_endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ToList(); + // foreach (var db_order in end_orders) + // { + // UpdateOrder(db_order, session, notices); + // } + //} + + //if (notices.Count != 0) + //{ + // var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + // foreach (var item in notices) + // { + // //if (item.Member == null) continue; + // var order = item.Order as fl_order_kuaishou; + // if (order.order_sn == order_id) continue; + // tasks.Add(item); + // } + //} + } + + private void OrderHandle(KS_OrderInfo orderInfo, string username, string usernick) + { + try + { + if (orderInfo?.orderList != null && orderInfo.orderList.Count != 0) + { + List notices = new List(); + var notDownloadPids = ApiClient.Setting.SystemConfig.order_kuaishou_not_download_pid.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + int count = 1; + foreach (var item in orderInfo.orderList) + { + try + { + if (item.cpsKwaimoneyOrderProductView == null || item.cpsKwaimoneyOrderProductView.Count == 0) + continue; + + var db = ApiClient.GetSession(); + + foreach (var orderItem in item.cpsKwaimoneyOrderProductView) + { + count++; + + #region 不处理的PID + if (ApiClient.Setting.SystemConfig.order_kuaishou_download_set_pids == SwitchType.关闭) + { + if (notDownloadPids.Count != 0) + { + var isExist = notDownloadPids.Contains(orderItem.cpsPid);//是否包含 + //continue; + if (ApiClient.Setting.SystemConfig.order_kuaishou_down_type == DownAdzoneType.不下载推广位 && isExist) + continue; + else if (ApiClient.Setting.SystemConfig.order_kuaishou_down_type == DownAdzoneType.只下载推广位 && !isExist) + continue; + } + } + else + { + var adzoneList = new List(); + var adzones = db.FindAdzoneInfos(); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "快手返利" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.Contains(orderItem.cpsPid))); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "用户私人pid" && f.extend == "快手私人pid" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.Contains(orderItem.cpsPid))); + if (adzoneList.Count() == 0) + continue; + } + #endregion + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && count % 10 == 0) + Thread.Sleep(150); + + var dbOrder = db.FindSingle("oid=@oid and oid2=@oid2", new { oid = item.oid, oid2 = orderItem.oid }); + if (dbOrder != null) + { + var updateTime = item.updateTime.ToDateTime(); + if (dbOrder.updateTime == updateTime) + continue; + + if (dbOrder.IsFinish())//是否已经完成 + continue; + if (dbOrder.db_status == SystemOrderStatus.订单冻结 && dbOrder.db_endtime > DateTime.Now)//跳过冻结 + continue; + + dbOrder.updateTime = updateTime; + dbOrder.cpsOrderStatus = (CpsOrderStatus)item.cpsOrderStatus; + dbOrder.settlementSuccessTime = item.settlementSuccessTime.ToDateTime(); + dbOrder.settlementAmount = item.settlementAmount.ExecDivision(); + } + else + { + dbOrder = ToDbKusishou(item, orderItem); + + dbOrder.db_cpsname = username; + dbOrder.db_cpsnick = usernick; + } + + UpdateOrder(dbOrder, db, notices); + } + } + catch (Exception ex) + { + //Console.WriteLine($"处理订单异常1:{ex.Message} - {ex.StackTrace}"); + } + } + + //通知 + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + var order = item.Order as fl_order_kuaishou; + tasks.Add(item); + } + } + + } + } + catch (Exception ex) + { + //Console.WriteLine($"处理订单异常2:{ex.Message} - {ex.StackTrace}"); + } + } + + private fl_order_kuaishou ToDbKusishou(OrderList order, CpsOrderProductView orderItem) + { + var dbOrder = new fl_order_kuaishou(); + + dbOrder.oid = order.oid; + dbOrder.cpsOrderStatus = (CpsOrderStatus)order.cpsOrderStatus; + dbOrder.orderCreateTime = order.orderCreateTime.ToDateTime(); + dbOrder.payTime = order.payTime.ToDateTime(); + dbOrder.orderTradeAmount = order.orderTradeAmount.ExecDivision(); + dbOrder.createTime = order.createTime.ToDateTime(); + dbOrder.updateTime = order.updateTime.ToDateTime(); + dbOrder.settlementSuccessTime = order.settlementSuccessTime.ToDateTime(); + dbOrder.settlementAmount = order.settlementAmount.ExecDivision(); + dbOrder.kwaimoneyUserId = order.kwaimoneyUserId; + + dbOrder.oid2 = orderItem.oid; + dbOrder.itemId = orderItem.itemId; + dbOrder.itemTitle = orderItem.itemTitle; + dbOrder.itemPicUrl = orderItem.itemPicUrl; + dbOrder.itemPrice = orderItem.itemPrice.ExecDivision(); + dbOrder.skuDesc = orderItem.skuDesc; + dbOrder.estimatedIncome = orderItem.estimatedIncome.ExecDivision(); + dbOrder.commissionRate = orderItem.commissionRate.ExecDivision(1000, 3); + dbOrder.cpsPid = orderItem.cpsPid; + dbOrder.sellerId = orderItem.sellerId; + dbOrder.sellerNickname = orderItem.sellerNickname; + dbOrder.num = orderItem.num; + dbOrder.cpsType = orderItem.cpsType; + dbOrder.distributorId = orderItem.distributorId; + dbOrder.distributorNickname = orderItem.distributorNickname; + dbOrder.comments = orderItem.comments; + dbOrder.pidName = orderItem.pidName; + dbOrder.paymentFee = orderItem.paymentFee.ExecDivision(); + + return dbOrder; + } + + internal bool UpdateOrder(DateTime start_time, DateTime end_time) + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.快手联盟 && f.is_download == SwitchType.开启).ToArray(); + + UnValidCpsMember(members); + + UpdateOrder(members, start_time, end_time); + return true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新快手异常:" + ex.Message); + return false; + } + finally + { + IsRunning = false; + } + } + + /// + /// 订单 修改状态/用户绑定等操作通知用户 + /// + /// 快手订单对象 + /// 数据库操作对象 + /// 事件集合 + /// + public void UpdateOrder(fl_order_kuaishou dbOrder, SqlSugarClient db, List notice, bool isFrontData = false) + { + try + { + var old_status = dbOrder.db_status; + fl_member_info member = null; ; + var isRewards = false;//是否获得推荐新人奖励 + var isFirstOrder = false;//是否获得用户首单奖励 + var islotUserQuery = false;//订单是否为多人查询 + + //历史佣金计算id + fl_itempoint1_hist itemPointHist = null; + + //订单自动绑定 + if (dbOrder.db_userid == 0 && ApiClient.Setting.SystemConfig.order_kuaishou_bind == SwitchType.开启) + { + var isbind = false; + #region 快手返利进行自动绑定 + //私人推广位强制绑定绑定 + var privateAdzonePids = db.FindKuaishouPrivatePid(dbOrder.cpsPid); + if (privateAdzonePids.Count == 1 && privateAdzonePids[0].is_auto_bind)//无条件设置开启中,直接自动绑定 + { + var memberInfo = db.FindMemberInfoById(privateAdzonePids[0].member_id); + if (memberInfo != null) + { + dbOrder.db_userid = memberInfo.id; + dbOrder.db_robotname = memberInfo.robot_name; + dbOrder.db_robottype = memberInfo.robot_type; + isbind = true; + } + } + + if (!isbind) + { + var bind_pids = db.FindKuaishouAutoBindPid(); + bool flag = bind_pids.FirstOrDefault(f => f == dbOrder.cpsPid) != null ? true : false; + if (flag) + { + #region 有定义参数 + if (!string.IsNullOrWhiteSpace(dbOrder.comments)) + { + itemPointHist = db.Queryable().First(f => f.guidkey == dbOrder.comments); + if (itemPointHist != null) + { + member = db.FindMemberInfoById(itemPointHist.uid); + if (member != null) + { + dbOrder.db_userid = member.id; + if (string.IsNullOrEmpty(dbOrder.db_robotname)) + { + dbOrder.db_robotname = itemPointHist.robotname; + dbOrder.db_robottype = member.robot_type; + + } + dbOrder.msg_groupid = itemPointHist.gid; + } + } + } + #endregion + } + } + #endregion + } + else + { + member = db.Find("id=@id", new { id = dbOrder.db_userid }).FirstOrDefault(); + } + + #region 更新用户的最后付款时间 + if (dbOrder.cpsOrderStatus == CpsOrderStatus.已付款 && dbOrder.db_userid != 0) + { + try + { + var record = db.FindStatisticsRecord(dbOrder.db_userid); + if (record == null) + record = new fl_statistics_record() { uid = dbOrder.db_userid }; + record.ex5 = HttpExtend.GetTimeStamp(dbOrder.payTime); + db.Saveable(record).ExecuteCommand(); + } + catch (Exception) + { } + } + #endregion + + //计算积分 + if (string.IsNullOrEmpty(dbOrder.db_point)) + { + if (member == null) + member = db.Find("id=@id", new { id = dbOrder.db_userid }).FirstOrDefault(); + + ItemPoint itempoint = null; + + Compute compute = null; + + if (itemPointHist != null) + compute = JsonConvert.DeserializeObject(itemPointHist.text); + + //计算的佣金 + if (compute != null) + itempoint = db.FindItemPoint(CpsType.快手联盟, compute, dbOrder.estimatedIncome, dbOrder.num); + else + itempoint = db.FindItemPoint(member, dbOrder.estimatedIncome, dbOrder.num, CpsType.快手联盟); + + if (itempoint != null) + { + dbOrder.db_point = HttpHelper.ObjectToJson(itempoint); + dbOrder.db_userpoint = itempoint.UserPoint; + } + if (member != null) + { + member.bind_order++; + member = db.UpdateMemberGroup(member); + } + } + + if (member != null && string.IsNullOrWhiteSpace(dbOrder.db_robotname)) + { + dbOrder.db_robotname = member.robot_name; + dbOrder.db_robottype = member.robot_type; + } + + switch (dbOrder.cpsOrderStatus) + { + case CpsOrderStatus.已结算: + case CpsOrderStatus.已收货: + { + //未发放佣金 + if (dbOrder.db_endtime == DateTime.MinValue) + { + var sleep = db.FindSleep(CpsType.快手联盟, ApiClient.Setting.SystemConfig.FreezingCondition == FreezingConditionType.商品总佣金 ? dbOrder.estimatedIncome : dbOrder.db_userpoint); + if (sleep != null) + { + if (!string.IsNullOrEmpty(sleep.white_groups)) + { + if (member != null && sleep.white_groups.Split(',').Contains(member.group_id.ToString())) + { + dbOrder.db_endtime = DateTime.Now;//该会员组不受限制 + } + else + { + dbOrder.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + } + else dbOrder.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else dbOrder.db_endtime = DateTime.Now; + + #region 验证订单是否为24小时 + var config = Util.Read>("插件-快手返利-配置"); + if (config != null) + { + if (config.ContainsKey("ReceivingTimeCheck_Switch")) + { + var ReceivingTimeCheck_Switch = bool.Parse(config["ReceivingTimeCheck_Switch"].ToString()); + if (ReceivingTimeCheck_Switch) + { + if (config.ContainsKey("ReceivingTimeCheck_Hour")) + { + var ReceivingTimeCheck_Hour = int.Parse(config["ReceivingTimeCheck_Hour"].ToString()); + if ((DateTime.Now - dbOrder.payTime).TotalHours <= ReceivingTimeCheck_Hour)//判断订单收货时间差 + { + if (config.ContainsKey("ReceivingTimeCheck_OperateType")) + { + var ReceivingTimeCheck_OperateType = (OperateType)int.Parse(config["ReceivingTimeCheck_OperateType"].ToString()); + if (ReceivingTimeCheck_OperateType == OperateType.订单冻结) + { + if (config.ContainsKey("ReceivingTimeCheck_FreezeTime")) + { + var ReceivingTimeCheck_FreezeTime = int.Parse(config["ReceivingTimeCheck_FreezeTime"].ToString()); + dbOrder.db_endtime = dbOrder.db_endtime.AddHours(ReceivingTimeCheck_FreezeTime);//延迟多少小时 + } + } + } + } + } + } + } + } + #endregion + + } + if (dbOrder.db_endtime <= DateTime.Now) + { + dbOrder.db_status = SystemOrderStatus.订单结算; + //session.ExcuteSQL("update fl_order_kuaishou set db_status=" + (int)db_order.db_status + " where id=" + db_order.id); + if (member != null) + { + var point = HttpHelper.JsonToObject(dbOrder.db_point) as ItemPoint; + if (point != null) + { + #region 获取是否已经结算给客户 + var pointHists = db.Find("select * from fl_point_hist where uid = @uid and type = @pointType_name and message = @message", new { uid = member.id, pointType_name = PointType.消费补贴.ToString(), message = $"快手购买:{dbOrder.itemTitle}({dbOrder.oid}-{dbOrder.oid2})" }); + if (pointHists != null && pointHists.Count != 0) + { + db.SaveOrUpdate(dbOrder); + return; + } + #endregion + + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = db.ChangePoint(PointType.消费补贴, point.UserPoint, member.id, $"快手购买:{dbOrder.itemTitle}({dbOrder.oid}-{dbOrder.oid2})"); + + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, dbOrder.db_status); + #endregion + + //notice.Add(new OrderNoticeEvent(CpsType.快手联盟, member, db_order)); + //多级提成计算 + + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = db.FindMemberInfoById(member.inviter_id); + if (inviter != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, dbOrder.db_endtime, dbOrder.paymentFee); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.快手联盟, inviter, dbOrder, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + } + } + else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = db.ChangePoint(PointType.提成奖励, point.AwardOne, member.inviter_id, $"{member.usernick},快手购物1级提成! - {dbOrder.itemTitle}({dbOrder.oid}-{dbOrder.oid2})"); + if (flag != null) + { + ids.Add(flag.id); + + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, dbOrder.db_endtime, dbOrder.paymentFee); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.快手联盟, flag, dbOrder, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = db.ChangePoint(PointType.提成奖励, point.AwardTwo, flag.inviter_id, $"{member.usernick},快手购物2级提成! - {dbOrder.itemTitle}({dbOrder.oid}-{dbOrder.oid2})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.快手联盟, flag2, dbOrder, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = db.ChangePoint(PointType.提成奖励, point.AwardThree, flag2.inviter_id, $"{member.usernick},快手购物3级提成! - {dbOrder.itemTitle}({dbOrder.oid}-{dbOrder.oid2})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.快手联盟, flag3, dbOrder, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(dbOrder.msg_groupid) && !string.IsNullOrEmpty(dbOrder.db_robotname)) + { + var robot = db.FindRobotInfo(dbOrder.db_robotname, dbOrder.db_robottype); + if (robot != null) + { + var create = db.FindCreateInfo(dbOrder.msg_groupid, dbOrder.db_robottype); + if (create != null && member.id != create.id) + { + var flag = db.ChangePoint(PointType.提成奖励, point.AwardCreate, create.mid, $"{member.usernick},快手维护提成! - {dbOrder.itemTitle}({dbOrder.oid}-{dbOrder.oid2})"); + if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.快手联盟, flag, dbOrder, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + } + } + else dbOrder.db_status = SystemOrderStatus.订单冻结; + break; + } + case CpsOrderStatus.已付款: + dbOrder.db_status = SystemOrderStatus.订单付款; + break; + case CpsOrderStatus.已失效: + dbOrder.db_status = SystemOrderStatus.订单失效; + + if (member != null)//订单还没有绑定用户 + { + if (dbOrder.db_endtime != DateTime.MinValue) //客户已经在冻结中 + { + if (dbOrder.db_endtime <= DateTime.Now) //佣金已经解冻 - 已经把佣金给客户(需要扣除佣金) + { + ItemPoint itempointTmp = null; + + var compute = db.FindQueryRatioHist(CpsType.快手联盟, dbOrder.id); + + if (compute != null) + itempointTmp = db.FindItemPoint(CpsType.快手联盟, compute, dbOrder.estimatedIncome, dbOrder.num); + else + //判断用户的订单是否已经结算,如果已经结算通过实际佣金进行退款,如果没有结算通过预计佣进行计算 + itempointTmp = db.FindItemPoint(member, dbOrder.estimatedIncome, dbOrder.num, CpsType.快手联盟); + new OrderHelper().DeductKuaiShouOrderPoint(notice, dbOrder, itempointTmp); + + dbOrder.db_status = SystemOrderStatus.全额退款; + } + else + { + //if (itempoint != null) + //{ + // //用户自身加积分 + // //member = session.ChangePoint(PointType.维权扣除, itempoint.UserPoint, member.id, $"抖音购买:{db_order.skuName}({db_order.orderId}) - 售后中(扣除) - 订单还未结算(冻结中)"); + //} + } + } + dbOrder.db_endtime = DateTime.MinValue; + } + + break; + default: + dbOrder.db_status = SystemOrderStatus.订单未知; + break; + } + + #region 通知客户订单付款/失效 提示上级 + if (member != null && (dbOrder.db_status == SystemOrderStatus.订单付款 || dbOrder.db_status == SystemOrderStatus.订单失效)) + { + var point = HttpHelper.JsonToObject(dbOrder.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + //一级用户对象 + var member_one = db.FindMemberInfoById(member.inviter_id); + if (member_one != null) + { + ids.Add(member_one.id); + if (notice != null) + notice.Add(new OrderNoticeEvent(CpsType.快手联盟, member_one, dbOrder, OrderNoticeType.一级提成) { Customer = member }); + if (point.AwardTwo > 0 && member_one.inviter_id != 0 && !ids.Contains(member_one.inviter_id)) + { + //二级用户对象 + var member_two = db.FindMemberInfoById(member_one.inviter_id); + if (member_two != null) + { + ids.Add(member_two.id); + if (notice != null && member_two != null) + { + notice.Add(new OrderNoticeEvent(CpsType.快手联盟, member_two, dbOrder, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && member_two.inviter_id != 0 && !ids.Contains(member_two.inviter_id)) + { + //三级用户对象 + var member_three = db.FindMemberInfoById(member_two.inviter_id); + if (member_three != null) + { + ids.Add(member_three.id); + if (notice != null && member_three != null) + notice.Add(new OrderNoticeEvent(CpsType.快手联盟, member_three, dbOrder, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(dbOrder.msg_groupid) && !string.IsNullOrEmpty(dbOrder.db_robotname)) + { + var create = db.FindCreateInfo(dbOrder.msg_groupid, dbOrder.db_robottype); + if (create != null && member.id != create.id) + { + var member_create = db.FindMemberInfoById(create.mid); + if (notice != null && member_create != null) notice.Add(new OrderNoticeEvent(CpsType.快手联盟, member_create, dbOrder, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + #endregion + if (old_status != dbOrder.db_status) + dbOrder.db_status_time = HttpExtend.GetTimeStamp(); + + db.SaveOrUpdate(dbOrder); + if (dbOrder.db_status == SystemOrderStatus.订单付款) + { + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, dbOrder.db_status); + #endregion + } + + //if (notice != null && (isFrontData || old_status != db_order.db_status)) + if (notice != null && (isFrontData || old_status != dbOrder.db_status) + && ((islotUserQuery && member == null) || member != null)) + notice.Add(new Events.OrderNoticeEvent(CpsType.快手联盟, member, dbOrder, OrderNoticeType.客户订单) { IsRewards = isFirstOrder }); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新快手订单错误:" + dbOrder.oid + "-" + dbOrder.oid2 + "," + ex.Message); + } + } + + private static DateTime invalidnotice_time = DateTime.MinValue;//阿里妈妈账号无效通知时间 + private static DateTime invalidnotice_time2 = DateTime.MinValue;//阿里妈妈账号日志无效时间 + /// + /// 无效的快手账号通知 + /// + /// 快手cps对象集合 + private void UnValidCpsMember(fl_cps_member[] _members) + { + try + { + var invalid_members = _members.Where(f => !f.is_valid).ToArray(); + if (invalid_members.Length != 0) + { + var strb = new StringBuilder(); + strb.AppendLine($"快手更新订单异常"); + strb.AppendLine(); + + for (int i = 0; i < invalid_members.Length; i++) + { + strb.AppendLine($"{invalid_members[i].usernick} ({invalid_members[i].username})"); + } + strb.AppendLine(); + strb.AppendLine($"以上账号授权状态已过期"); + strb.AppendLine($"跳过以上账号下载操作"); + strb.AppendLine($"请重新登录快手账号"); + + var timelag2 = (DateTime.Now - invalidnotice_time2).TotalMinutes; + + if (timelag2 > 5) + { + invalidnotice_time2 = DateTime.Now; + EventClient.OnEvent(this, strb.ToString()); + } + + var timelag = (DateTime.Now - invalidnotice_time).TotalMinutes; + + if (timelag > 30) + { + strb.AppendLine($"系统时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); + invalidnotice_time = DateTime.Now; + ApiClient.SendNoticeMessage(strb.ToString()); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "快手账号授权失效通知", strb.ToString(), true); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"更新快手订单异常7:{ex.Message},{ex.StackTrace}"); + } + } + + } +} diff --git a/类库/Api.Framework/Timers/DownPinduoduoTimer - 复制.cs b/类库/Api.Framework/Timers/DownPinduoduoTimer - 复制.cs new file mode 100644 index 0000000..35d842b --- /dev/null +++ b/类库/Api.Framework/Timers/DownPinduoduoTimer - 复制.cs @@ -0,0 +1,793 @@ +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Text; + +namespace Api.Framework.Timers +{ + /// + /// 下载拼多多订单,定时器 + /// + public class DownPinduoduoTimer : TimerTask + { + private DateTime update_time = DateTime.Now.AddMinutes(-60); + public override void Run(object state, bool timedOut) + { + var end_time = DateTime.Now; + UpdateOrder(CpsClient.Members.Where(f => f.cpstype == CpsType.多多进宝 && f.is_download == SwitchType.开启).ToArray(), update_time, end_time); + update_time = DateTime.Now.AddMinutes(-20); + } + + /// + /// 订单id + /// + public string order_id = string.Empty; + private object lock_obj = new object(); + /// + /// 下载订单任务下达A + /// + /// + /// + /// + public void UpdateOrder(List members, DateTime start_time, DateTime end_time) + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + + UpdateOrder(members.ToArray(), start_time, end_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新拼多多订单异常:" + ex.Message); + } + finally + { + IsRunning = false; + } + } + /// + /// 更新订单 + /// + /// 开始时间 + /// 结束时间 + /// 订单id + /// + public bool UpdateOrder(DateTime start_time, DateTime end_time, string order_id = "") + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + this.order_id = order_id; + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.多多进宝 && f.is_download == SwitchType.开启).ToArray(); + UpdateOrder(members, start_time, end_time); + return true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新拼多多异常:" + ex.Message); + return false; + } + finally + { + this.order_id = string.Empty; + IsRunning = false; + } + + } + + private static string custom_parameters_regex = @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.+?)(?:\smallid=(?<店铺ID>\d+)?)?$"; + + private static string custom_parameters_regex_new = @"^r=(?<机器人名>.*?)\st=(?<类型>\d+)\su=(?<会员名>.+?)$"; + + public void UpdateOrder(fl_order_pinduoduo db_order, SqlSugarClient session, List notice, bool isFrontData = false) + { + try + { + var old_status = db_order.db_status; + fl_member_info member = null; + var isRewards = false;//是否获得推荐新人奖励 + var isFirstOrder = false;//是否获得用户首单奖励 + + //订单自动绑定 + if (db_order.db_userid == 0 && ApiClient.Setting.SystemConfig.order_pinduoduo_bind == SwitchType.开启) + { + var isbind = false; + #region 拼多多返利进行自动绑定 + //私人推广位强制绑定绑定 + var privateAdzonePids = session.FindPinduoduoPrivatePid(db_order.p_id.ToString()); + if (privateAdzonePids.Count == 1 && privateAdzonePids[0].is_auto_bind)//无条件设置开启中,直接自动绑定 + { + var memberInfo = session.FindMemberInfoById(privateAdzonePids[0].member_id); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + isbind = true; + } + } + + if (!isbind) + { + var bind_pids = session.FindPinduoduoAutoBindPid(); + bool flag = bind_pids.FirstOrDefault(f => f == db_order.p_id) != null ? true : false; + #endregion + if (flag) + { + //var reg = Regex.Match(db_order.custom_parameters, @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.*?)$"); + //var reg = Regex.Match(db_order.custom_parameters, @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.+?)(?:\smallid=(?<店铺ID>\d+))?$"); + var reg = Regex.Match(db_order.custom_parameters, custom_parameters_regex_new); + if (!reg.Success) + reg = Regex.Match(db_order.custom_parameters, custom_parameters_regex); + if (reg.Success) + { + member = session.FindSingle("username=@username and robot_type=@robot_type", new { username = reg.Groups["会员名"].Value, robot_type = reg.Groups["类型"].Value }); + if (member == null) + { + member = new fl_member_info() { robot_type = Util.ConvertEnum(int.Parse(reg.Groups["类型"].Value)), username = reg.Groups["会员名"].Value, robot_name = reg.Groups["机器人名"].ToString(), alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + var groups = session.FindGroups(); + if (groups.Count != 0) + member.group_id = groups[0].id; + session.SaveOrUpdate(member); + } + db_order.db_userid = member.id; + if (string.IsNullOrEmpty(db_order.db_robotname)) + { + db_order.db_robotname = reg.Groups["机器人名"].Value; + db_order.db_robottype = Util.ConvertEnum(int.Parse(reg.Groups["类型"].Value)); + } + + #region 绑定群号 + if (string.IsNullOrWhiteSpace(db_order.msg_groupid)) + { + var query_item = session.Find("userid=@userid and itemid=@itemid and adzoneid = @adzoneid", new { userid = db_order.db_userid, itemid = db_order.goods_id, adzoneid = db_order.p_id }).FirstOrDefault(); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + } + } + #endregion + + } + } + } + } + else + { + member = session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault(); + } + + if ((db_order.order_status == 0 || db_order.order_status == 1) && db_order.db_userid != 0) + { + try + { + var record = session.FindStatisticsRecord(db_order.db_userid); + if (record == null) + record = new fl_statistics_record() { uid = db_order.db_userid }; + record.ex5 = HttpExtend.GetTimeStamp(db_order.order_pay_time); + session.Saveable(record).ExecuteCommand(); + } + catch (Exception) + { } + } + //计算积分 + if (string.IsNullOrEmpty(db_order.db_point)) + { + if (member == null) session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault(); + var itempoint = session.FindItemPoint(member, db_order.promotion_amount, db_order.goods_quantity, CpsType.多多进宝); + if (itempoint != null) + { + if (itempoint.UserPoint == 0 && ApiClient.Setting.SystemConfig.SubsidyPdd == SwitchType.开启) + itempoint.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + db_order.db_userpoint = itempoint.UserPoint; + } + if (member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + } + var status = Util.ConvertEnum(db_order.order_status); + switch (status) + { + case PinduoduoOrderStatus.确认收货: + case PinduoduoOrderStatus.审核成功: + case PinduoduoOrderStatus.已经结算: + { + //未发放佣金 + if (db_order.db_endtime == DateTime.MinValue) + { + var sleep = session.FindSleep(CpsType.多多进宝, ApiClient.Setting.SystemConfig.FreezingCondition == FreezingConditionType.商品总佣金 ? db_order.promotion_amount : db_order.db_userpoint); + if (sleep != null) + { + if (!string.IsNullOrEmpty(sleep.white_groups)) + { + if (member != null && sleep.white_groups.Split(',').Contains(member.group_id.ToString())) + { + db_order.db_endtime = DateTime.Now;//该会员组不受限制 + } + else + { + db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + } + else db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else db_order.db_endtime = DateTime.Now; + + #region 验证订单是否为24小时 + var config = Util.Read>("插件-拼多多返利-配置"); + if (config != null) + { + if (config.ContainsKey("ReceivingTimeCheck_Switch")) + { + var ReceivingTimeCheck_Switch = (bool)config["ReceivingTimeCheck_Switch"]; + if (ReceivingTimeCheck_Switch) + { + if (config.ContainsKey("ReceivingTimeCheck_Hour")) + { + var ReceivingTimeCheck_Hour = (int)config["ReceivingTimeCheck_Hour"]; + if ((DateTime.Now - db_order.order_pay_time).TotalHours <= ReceivingTimeCheck_Hour)//判断订单收货时间差 + { + if (config.ContainsKey("ReceivingTimeCheck_OperateType")) + { + var ReceivingTimeCheck_OperateType = (OperateType)int.Parse(config["ReceivingTimeCheck_OperateType"].ToString()); + if (ReceivingTimeCheck_OperateType == OperateType.订单冻结) + { + if (config.ContainsKey("ReceivingTimeCheck_FreezeTime")) + { + var ReceivingTimeCheck_FreezeTime = (int)config["ReceivingTimeCheck_FreezeTime"]; + db_order.db_endtime = db_order.db_endtime.AddHours(ReceivingTimeCheck_FreezeTime);//延迟多少小时 + } + } + } + } + } + } + } + } + #endregion + + } + if (db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.订单结算; + //session.ExcuteSQL("update fl_order_pinduoduo set db_status=" + (int)db_order.db_status + " where id=" + db_order.id); + if (member != null) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.消费补贴, point.UserPoint, member.id, $"拼多多购买:{db_order.goods_name}({db_order.order_sn})"); + + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + + //notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member, db_order)); + //多级提成计算 + + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.order_amount); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + } + } + else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardOne, member.inviter_id, $"{member.usernick},拼多多购物1级提成! - {db_order.goods_name}({db_order.order_sn})"); + if (flag != null) + { + ids.Add(flag.id); + + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.order_amount); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.提成奖励, point.AwardTwo, flag.inviter_id, $"{member.usernick},拼多多购物2级提成! - {db_order.goods_name}({db_order.order_sn})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.提成奖励, point.AwardThree, flag2.inviter_id, $"{member.usernick},拼多多购物3级提成! - {db_order.goods_name}({db_order.order_sn})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardCreate, create.mid, $"{member.usernick},拼多多维护提成! - {db_order.goods_name}({db_order.order_sn})"); + if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + } + } + else db_order.db_status = SystemOrderStatus.订单冻结; + break; + } + case PinduoduoOrderStatus.已经付款: + case PinduoduoOrderStatus.已经成团: + { + db_order.db_status = SystemOrderStatus.订单付款; + } + break; + case PinduoduoOrderStatus.审核失败: + //db_order.db_status = (old_status == SystemOrderStatus.订单结算) ? SystemOrderStatus.全额退款 : SystemOrderStatus.订单失效; + #region 全额维权 + //if (member != null && old_status == SystemOrderStatus.订单结算 && db_order.db_status == SystemOrderStatus.全额退款)//扣除积分 + if (db_order.db_endtime != DateTime.MinValue && db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.全额退款; + #region + //if (member != null) + //{ + // var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + // if (point != null) + // { + // List ids = new List(); + // ids.Add(member.id); + // //用户自身加积分 + // member = session.ChangePoint(PointType.维权扣除, point.UserPoint, member.id, $"拼多多购买:{db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + + // //#region 判断用户是否符合获得新人奖励 + // //isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + // //#endregion + + // //notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member, db_order)); + // //多级提成计算 + + // //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + // if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + // { + // if (notice != null) + // { + // var inviter = session.FindMemberInfoById(member.inviter_id); + // if (inviter != null) + // { + // #region 判断上级是否符合获得推荐新人奖励 + // isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.order_amount); + // #endregion + + // notice.Add(new OrderNoticeEvent(CpsType.多多进宝, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + // } + // } + // } + // else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + // { + // var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},拼多多购物1级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + // if (flag != null) + // { + // ids.Add(flag.id); + + // //#region 判断上级是否符合获得推荐新人奖励 + // //isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.order_amount); + // //#endregion + + // //notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + // notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.一级提成) { Customer = member }); + + // if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + // { + // var flag2 = session.ChangePoint(PointType.维权扣除, point.AwardTwo, flag.inviter_id, $"{member.usernick},拼多多购物2级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + // if (flag2 != null) + // { + // ids.Add(flag2.id); + // if (flag2 != null) + // { + // notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + // if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + // { + // var flag3 = session.ChangePoint(PointType.维权扣除, point.AwardThree, flag2.inviter_id, $"{member.usernick},拼多多购物3级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + // if (flag3 != null) + // { + // ids.Add(flag3.id); + // if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + // } + // } + // } + // } + // } + // } + // } + + // //创建人计算 + // if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + // { + // var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + // if (robot != null) + // { + // var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + // if (create != null && member.id != create.id) + // { + // var flag = session.ChangePoint(PointType.维权扣除, point.AwardCreate, create.mid, $"{member.usernick},拼多多维护提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + // if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + // } + // } + // } + // } + //} + #endregion + new OrderHelper().DeductPinDuoOrderPoint(notice, db_order); + } + else + { + db_order.db_status = SystemOrderStatus.订单失效; + } + #endregion + break; + case PinduoduoOrderStatus.没有佣金: + case PinduoduoOrderStatus.违规订单: + db_order.db_status = SystemOrderStatus.订单失效; + break; + case PinduoduoOrderStatus.等待付款: + db_order.db_status = SystemOrderStatus.订单创建; + break; + default: + db_order.db_status = SystemOrderStatus.订单未知; break; + } + + #region 通知客户订单付款/失效 提示上级 + if (member != null && (db_order.db_status == SystemOrderStatus.订单付款 || db_order.db_status == SystemOrderStatus.订单失效)) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + //一级用户对象 + var member_one = session.FindMemberInfoById(member.inviter_id); + if (member_one != null) + { + ids.Add(member_one.id); + if (notice != null) + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member_one, db_order, OrderNoticeType.一级提成) { Customer = member }); + if (point.AwardTwo > 0 && member_one.inviter_id != 0 && !ids.Contains(member_one.inviter_id)) + { + //二级用户对象 + var member_two = session.FindMemberInfoById(member_one.inviter_id); + if (member_two != null) + { + ids.Add(member_two.id); + if (notice != null && member_two != null) + { + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member_two, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && member_two.inviter_id != 0 && !ids.Contains(member_two.inviter_id)) + { + //三级用户对象 + var member_three = session.FindMemberInfoById(member_two.inviter_id); + if (member_three != null) + { + ids.Add(member_three.id); + if (notice != null && member_three != null) + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member_three, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var member_create = session.FindMemberInfoById(create.mid); + if (notice != null && member_create != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member_create, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + #endregion + if (old_status != db_order.db_status) + db_order.db_status_time = HttpExtend.GetTimeStamp(); + + session.SaveOrUpdate(db_order); + if (db_order.db_status == SystemOrderStatus.订单付款) + { + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + } + + if (notice != null && (isFrontData || old_status != db_order.db_status)) + notice.Add(new Events.OrderNoticeEvent(CpsType.多多进宝, member, db_order, OrderNoticeType.客户订单) { IsRewards = isFirstOrder }); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新拼多多订单错误:" + db_order.order_sn + "," + ex.Message); + } + } + + private void UpdateOrder(fl_cps_member[] members, DateTime start_time, DateTime end_time) + { + if (members == null || members.Length == 0) return; + int row_count = 50;//间隔 + //var timespan = end_time - start_time; + //var forcount = 1; + //if (timespan.TotalHours > 24.00) + //{ + // forcount = (int)(timespan.TotalHours / 24); + // if (timespan.TotalHours % 24 > 0) forcount++; + //}; + var timespan = end_time - start_time; + TaskTool task = new TaskTool(); + List notices = new List(); + var not_download_pids = ApiClient.Setting.SystemConfig.order_pinduoduo_not_download_pid.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + foreach (var item in members) + { + var _item = item; + var client = new PinduoduoApi(_item); + task.AddTask(delegate + { + try + { + var _star = timespan.TotalHours > 24 ? end_time : start_time;//倒叙24小时一个间断 + var _end = end_time; + do + { + if (timespan.TotalHours > 24) + { + _end = _star; + _star = _star.AddHours(-23.99); + } + Dictionary rst = null; + for (int i = 0; i < 3; i++) + { + try + { + rst = client.DownOrder(_star, _end, 1, row_count); + break; + } + catch (Exception ex) + { + Thread.Sleep(1000); + continue; + } + } + int total_count = int.Parse(rst["total_count"].ToString()); + if (total_count == 0) continue; + var order_list = rst["order_list"] as ArrayList; + Exception _exception = null; + int count = total_count / row_count; + if (total_count % row_count != 0) count++; + for (int i = 1; i <= count; i++) + { + var page = i; + if (_exception != null) return; + try + { + Dictionary _rst = null; + //下载 + if (page != 1) + { + for (int z = 0; z < 3; z++) + { + try + { + _rst = client.DownOrder(_star, _end, page, row_count); + break; + } + catch (Exception ex) + { + Thread.Sleep(1000); + continue; + } + } + order_list = _rst["order_list"] as ArrayList; + } + + if (order_list != null && order_list.Count > 0) + { + int _count = 1; + foreach (Dictionary _order in order_list) + { + _count++; + + var session = ApiClient.GetSession(); + try + { + //if (_order["order_sn"].ToString() == "200525-419953705981880") + //if (_order["order_sn"].ToString() == "200705-538107904903242") + //{ + //} + + #region 不处理的PID + if (not_download_pids.Count != 0) + { + var isExist = not_download_pids.Contains(_order["p_id"].ToString());//是否包含 + //continue; + if (ApiClient.Setting.SystemConfig.order_pinduoduo_down_type == DownAdzoneType.不下载推广位 && isExist) + continue; + else if (ApiClient.Setting.SystemConfig.order_pinduoduo_down_type == DownAdzoneType.只下载推广位 && !isExist) + continue; + } + #endregion + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && _count % 10 == 0) + Thread.Sleep(150); + + //计算订单信息 + var status = Util.ConvertEnum(int.Parse(_order["order_status"].ToString())); + //if (status == PinduoduoOrderStatus.等待付款) continue; + //var db_order = session.Queryable().Where(f => f.order_sn == _order["order_sn"].ToString()).First(); + var db_order = session.FindSingle("order_sn=@order_sn", new { order_sn = _order["order_sn"].ToString() }); + if (db_order != null) //跳过相同状态 + { + var statusTemp = (PinduoduoOrderStatus)db_order.order_status; + + if (status == statusTemp || + (status == PinduoduoOrderStatus.确认收货 || status == PinduoduoOrderStatus.已经结算 || status == PinduoduoOrderStatus.审核成功) && (statusTemp == PinduoduoOrderStatus.确认收货 || status == PinduoduoOrderStatus.已经结算 || status == PinduoduoOrderStatus.审核成功)) + { + if (db_order.IsFinish()) continue;//是否已经完成 + if (db_order.db_status == SystemOrderStatus.订单冻结 && db_order.db_endtime > DateTime.Now) continue;//跳过系统冻结 + if (db_order.order_status != 2 && db_order.order_status == (int)status) continue;//跳过相同状态 + } + db_order.order_status = (int)status; + if (db_order.goods_price == 0 || db_order.order_amount == 0 || db_order.promotion_amount == 0) + { + var temp = _order.ConvertToObj(); + db_order.promotion_amount = temp.promotion_amount == 0 ? 0 : Math.Round(temp.promotion_amount / 100.00, 2); + db_order.order_amount = temp.order_amount == 0 ? 0 : Math.Round(temp.order_amount / 100.00, 2); + db_order.goods_price = temp.goods_price == 0 ? 0 : Math.Round(temp.goods_price / 100.00, 2); + } + if (db_order.price_compare_status != (PinduoduoBiJiaType)db_order.price_compare_status) + db_order.price_compare_status = (PinduoduoBiJiaType)db_order.price_compare_status; + + } + else + { + db_order = _order.ConvertToObj(); + db_order.promotion_amount = db_order.promotion_amount == 0 ? 0 : Math.Round(db_order.promotion_amount / 100.00, 2); + db_order.order_amount = db_order.order_amount == 0 ? 0 : Math.Round(db_order.order_amount / 100.00, 2); + db_order.goods_price = db_order.goods_price == 0 ? 0 : Math.Round(db_order.goods_price / 100.00, 2); + db_order.db_cpsname = _item.username; + db_order.db_cpsnick = _item.usernick; + } + if (string.IsNullOrWhiteSpace(db_order.mall_id)) + { + //var reg = Regex.Match(db_order.custom_parameters, @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.+?)(?:\smallid=(?<店铺ID>\d+))?$"); + var reg = Regex.Match(db_order.custom_parameters, custom_parameters_regex); + if (reg.Success && reg.Groups["店铺ID"] != null && !string.IsNullOrWhiteSpace(reg.Groups["店铺ID"].ToString())) + db_order.mall_id = reg.Groups["店铺ID"].ToString(); + + if (string.IsNullOrWhiteSpace(db_order.mall_id)) + { + var query_item = session.FindSingle("select * from fl_query_hist where itemid = @itemid", new { itemid = db_order.goods_id }); + if (query_item != null) + db_order.mall_id = query_item.mallid; + } + } + + UpdateOrder(db_order, session, notices); + //if (!result.Result) + //{ + // _exception = result.Exception;return; + //} + } + catch (Exception ex) + { + throw ex; + } + finally + { + //session.Close(); + } + } + } + } + catch (Exception ex) + { + _exception = ex; return; + } + } + if (_exception != null) throw _exception; + + //_star = _star.AddHours(-23.99); + } while (_star > start_time); + + } + catch (Exception ex) + { + //throw ex; + } + }); + } + task.Start(1, null); + + if (string.IsNullOrEmpty(order_id)) + { + var session = ApiClient.GetSession(); + var end_orders = session.Find("select * from fl_order_pinduoduo where db_status=@db_status and db_endtime<@db_endtime", new { db_status = (int)SystemOrderStatus.订单冻结, db_endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ToList(); + foreach (var db_order in end_orders) + { + UpdateOrder(db_order, session, notices); + } + } + + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_pinduoduo; + if (order.order_sn == order_id) continue; + tasks.Add(item); + } + } + + //TaskTool task = new TaskTool(); + //task.AddTask(delegate { + + //}); + //var session = ApiClient.GetSession();//获得一个Session + //int thread_count = 6000; + + } + } +} diff --git a/类库/Api.Framework/Timers/DownPinduoduoTimer.cs b/类库/Api.Framework/Timers/DownPinduoduoTimer.cs new file mode 100644 index 0000000..d840239 --- /dev/null +++ b/类库/Api.Framework/Timers/DownPinduoduoTimer.cs @@ -0,0 +1,961 @@ +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Api.Framework.Tools; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Text; +using Newtonsoft.Json; + +namespace Api.Framework.Timers +{ + /// + /// 拼多多订单下载定时器 + /// + public class DownPinduoduoTimer : TimerTask + { + private DateTime update_time = DateTime.Now.AddMinutes(-60); + public override void Run(object state, bool timedOut) + { + var end_time = DateTime.Now; + UpdateOrder(CpsClient.Members.Where(f => f.cpstype == CpsType.多多进宝 && f.is_download == SwitchType.开启).ToArray(), update_time, end_time); + update_time = DateTime.Now.AddMinutes(-20); + } + + /// + /// 订单id + /// + private string order_id = string.Empty; + private object lock_obj = new object(); + /// + /// 手动同步订单 + /// + /// 拼多多cps对象集合 + /// 开始时间 + /// 结束时间 + public void UpdateOrder(List members, DateTime start_time, DateTime end_time) + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + + UpdateOrder(members.ToArray(), start_time, end_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新拼多多订单异常:" + ex.Message); + } + finally + { + IsRunning = false; + } + } + + /// + /// 更新订单 + /// + /// 开始时间 + /// 结束时间 + /// 订单id + /// + internal bool UpdateOrder(DateTime start_time, DateTime end_time, string order_id = "") + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + this.order_id = order_id; + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.多多进宝 && f.is_download == SwitchType.开启).ToArray(); + + UnValidCpsMember(members); + + UpdateOrder(members, start_time, end_time); + return true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新拼多多异常:" + ex.Message); + return false; + } + finally + { + this.order_id = string.Empty; + IsRunning = false; + } + + } + + private static string custom_parameters_regex = @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.+?)(?:\smallid=(?<店铺ID>\d+)?)?$"; + + private static string custom_parameters_regex_new = @"^r=(?<机器人名>.*?)\st=(?<类型>\d+)\su=(?<会员名>.+?)$"; + + /// + /// 订单 修改状态/用户绑定等操作通知用户 + /// + /// 拼多多订单对象 + /// 数据库操作对象 + /// 事件集合 + /// + public void UpdateOrder(fl_order_pinduoduo db_order, SqlSugarClient session, List notice, bool isFrontData = false) + { + try + { + var old_status = db_order.db_status; + fl_member_info member = null; + var isRewards = false;//是否获得推荐新人奖励 + var isFirstOrder = false;//是否获得用户首单奖励 + var islotUserQuery = false;//订单是否为多人查询 + + //订单自动绑定 + if (db_order.db_userid == 0 && ApiClient.Setting.SystemConfig.order_pinduoduo_bind == SwitchType.开启) + { + var isbind = false; + #region 拼多多返利进行自动绑定 + //私人推广位强制绑定绑定 + var privateAdzonePids = session.FindPinduoduoPrivatePid(db_order.p_id.ToString()); + if (privateAdzonePids.Count == 1 && privateAdzonePids[0].is_auto_bind)//无条件设置开启中,直接自动绑定 + { + var memberInfo = session.FindMemberInfoById(privateAdzonePids[0].member_id); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + isbind = true; + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.goods_id, adzoneid = db_order.p_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.多多进宝 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + } + + if (!isbind) + { + var bind_pids = session.FindPinduoduoAutoBindPid(); + bool flag = bind_pids.FirstOrDefault(f => f == db_order.p_id) != null ? true : false; + #endregion + if (flag) + { + #region 有定义custom_parameters参数 + //if (!string.IsNullOrWhiteSpace(db_order.custom_parameters)) + //{ + // //var reg = Regex.Match(db_order.custom_parameters, @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.*?)$"); + // //var reg = Regex.Match(db_order.custom_parameters, @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.+?)(?:\smallid=(?<店铺ID>\d+))?$"); + // var reg = Regex.Match(db_order.custom_parameters, custom_parameters_regex_new); + // if (!reg.Success) + // reg = Regex.Match(db_order.custom_parameters, custom_parameters_regex); + // if (reg.Success) + // { + // member = session.FindSingle("username=@username and robot_type=@robot_type", new { username = reg.Groups["会员名"].Value, robot_type = reg.Groups["类型"].Value }); + // if (member == null) + // { + // member = new fl_member_info() { robot_type = Util.ConvertEnum(int.Parse(reg.Groups["类型"].Value)), username = reg.Groups["会员名"].Value, robot_name = reg.Groups["机器人名"].ToString(), alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + // var groups = session.FindGroups(); + // if (groups.Count != 0) + // member.group_id = groups[0].id; + // session.SaveOrUpdate(member); + // } + // db_order.db_userid = member.id; + // if (string.IsNullOrEmpty(db_order.db_robotname)) + // { + // db_order.db_robotname = reg.Groups["机器人名"].Value; + // db_order.db_robottype = Util.ConvertEnum(int.Parse(reg.Groups["类型"].Value)); + // } + + // #region 绑定群号 + // if (string.IsNullOrWhiteSpace(db_order.msg_groupid)) + // { + // var query_item = session.Find("userid=@userid and itemid=@itemid and adzoneid = @adzoneid", new { userid = db_order.db_userid, itemid = db_order.goods_id, adzoneid = db_order.p_id }).FirstOrDefault(); + // if (query_item != null) + // { + // db_order.msg_groupid = query_item.groupid; + // } + // } + // #endregion + + // } + //} + #endregion + + #region 没有定义custom_parameters参数,进行逻辑绑定 + //else + { + //订单没有绑定用户 查询订单记录 + if (db_order.db_userid == 0) + { + var query = session.FindTable("select userid,count(*) as count from fl_query_hist where userid != 0 and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time group by userid ", new { itemid = db_order.goods_id, adzoneid = db_order.p_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query != null && query.Rows.Count > 0) + { + if (query.Rows.Count == 1) + { + var userid = int.Parse(query.Rows[0]["userid"].ToString());//要是查询记录已经标记为通知过的记录(userid 为 负数),将不通过查询记录进行绑定 + if (userid > 0) + { + db_order.db_userid = userid;//根据查询记录认领 + + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.goods_id, adzoneid = db_order.p_id, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.多多进宝 + }; + session.SaveOrUpdate(queryRatioHist); + } + + } + } + } + else + { + //订单多人查询,并且订单还未绑定 + if (db_order.db_userid == 0) + islotUserQuery = true; + } + } + } + } + #endregion + } + } + } + else + { + member = session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault(); + } + + if ((db_order.order_status == 0 || db_order.order_status == 1) && db_order.db_userid != 0) + { + try + { + var record = session.FindStatisticsRecord(db_order.db_userid); + if (record == null) + record = new fl_statistics_record() { uid = db_order.db_userid }; + record.ex5 = HttpExtend.GetTimeStamp(db_order.order_pay_time); + session.Saveable(record).ExecuteCommand(); + } + catch (Exception) + { } + } + //计算积分 + if (string.IsNullOrEmpty(db_order.db_point)) + { + if (member == null) member = session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault(); + + ItemPoint itempoint = null; + + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.多多进宝, db_order.id); + + //计算的佣金 + if (compute != null) + itempoint = session.FindItemPoint(CpsType.多多进宝, compute, db_order.promotion_amount, db_order.goods_quantity); + else + itempoint = session.FindItemPoint(member, db_order.promotion_amount, db_order.goods_quantity, CpsType.多多进宝); + if (itempoint != null) + { + if (itempoint.UserPoint == 0 && ApiClient.Setting.SystemConfig.SubsidyPdd == SwitchType.开启) + itempoint.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + db_order.db_userpoint = itempoint.UserPoint; + } + if (member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + } + + if (member != null && string.IsNullOrWhiteSpace(db_order.db_robotname)) + { + db_order.db_robotname = member.robot_name; + db_order.db_robottype = member.robot_type; + } + + var status = Util.ConvertEnum(db_order.order_status); + switch (status) + { + case PinduoduoOrderStatus.确认收货: + case PinduoduoOrderStatus.审核成功: + case PinduoduoOrderStatus.已经结算: + { + //未发放佣金 + if (db_order.db_endtime == DateTime.MinValue) + { + var sleep = session.FindSleep(CpsType.多多进宝, ApiClient.Setting.SystemConfig.FreezingCondition == FreezingConditionType.商品总佣金 ? db_order.promotion_amount : db_order.db_userpoint); + if (sleep != null) + { + if (!string.IsNullOrEmpty(sleep.white_groups)) + { + if (member != null && sleep.white_groups.Split(',').Contains(member.group_id.ToString())) + { + db_order.db_endtime = DateTime.Now;//该会员组不受限制 + } + else + { + db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + } + else db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else db_order.db_endtime = DateTime.Now; + + #region 验证订单是否为24小时 + var config = Util.Read>("插件-拼多多返利-配置"); + if (config != null) + { + if (config.ContainsKey("ReceivingTimeCheck_Switch")) + { + var ReceivingTimeCheck_Switch = bool.Parse(config["ReceivingTimeCheck_Switch"].ToString()); + if (ReceivingTimeCheck_Switch) + { + if (config.ContainsKey("ReceivingTimeCheck_Hour")) + { + var ReceivingTimeCheck_Hour = int.Parse(config["ReceivingTimeCheck_Hour"].ToString()); + if ((DateTime.Now - db_order.order_pay_time).TotalHours <= ReceivingTimeCheck_Hour)//判断订单收货时间差 + { + if (config.ContainsKey("ReceivingTimeCheck_OperateType")) + { + var ReceivingTimeCheck_OperateType = (OperateType)int.Parse(config["ReceivingTimeCheck_OperateType"].ToString()); + if (ReceivingTimeCheck_OperateType == OperateType.订单冻结) + { + if (config.ContainsKey("ReceivingTimeCheck_FreezeTime")) + { + var ReceivingTimeCheck_FreezeTime = int.Parse(config["ReceivingTimeCheck_FreezeTime"].ToString()); + db_order.db_endtime = db_order.db_endtime.AddHours(ReceivingTimeCheck_FreezeTime);//延迟多少小时 + } + } + } + } + } + } + } + } + #endregion + + } + if (db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.订单结算; + //session.ExcuteSQL("update fl_order_pinduoduo set db_status=" + (int)db_order.db_status + " where id=" + db_order.id); + if (member != null) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + #region 获取是否已经结算给客户 + var pointHists = session.Find("select * from fl_point_hist where uid = @uid and type = @pointType_name and message = @message", new { uid = member.id, pointType_name = PointType.消费补贴.ToString(), message = $"拼多多购买:{db_order.goods_name}({db_order.order_sn})" }); + if (pointHists != null && pointHists.Count != 0) + { + session.SaveOrUpdate(db_order); + return; + } + #endregion + + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.消费补贴, point.UserPoint, member.id, $"拼多多购买:{db_order.goods_name}({db_order.order_sn})"); + + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + + //notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member, db_order)); + //多级提成计算 + + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.order_amount); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + } + } + else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardOne, member.inviter_id, $"{member.usernick},拼多多购物1级提成! - {db_order.goods_name}({db_order.order_sn})"); + if (flag != null) + { + ids.Add(flag.id); + + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.order_amount); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.提成奖励, point.AwardTwo, flag.inviter_id, $"{member.usernick},拼多多购物2级提成! - {db_order.goods_name}({db_order.order_sn})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.提成奖励, point.AwardThree, flag2.inviter_id, $"{member.usernick},拼多多购物3级提成! - {db_order.goods_name}({db_order.order_sn})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardCreate, create.mid, $"{member.usernick},拼多多维护提成! - {db_order.goods_name}({db_order.order_sn})"); + if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + } + } + else db_order.db_status = SystemOrderStatus.订单冻结; + break; + } + case PinduoduoOrderStatus.已经付款: + case PinduoduoOrderStatus.已经成团: + { + db_order.db_status = SystemOrderStatus.订单付款; + } + break; + case PinduoduoOrderStatus.审核失败: + case PinduoduoOrderStatus.违规订单: + //db_order.db_status = (old_status == SystemOrderStatus.订单结算) ? SystemOrderStatus.全额退款 : SystemOrderStatus.订单失效; + #region 全额维权 + //if (member != null && old_status == SystemOrderStatus.订单结算 && db_order.db_status == SystemOrderStatus.全额退款)//扣除积分 + if (db_order.db_endtime != DateTime.MinValue && db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.全额退款; + #region + //if (member != null) + //{ + // var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + // if (point != null) + // { + // List ids = new List(); + // ids.Add(member.id); + // //用户自身加积分 + // member = session.ChangePoint(PointType.维权扣除, point.UserPoint, member.id, $"拼多多购买:{db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + + // //#region 判断用户是否符合获得新人奖励 + // //isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + // //#endregion + + // //notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member, db_order)); + // //多级提成计算 + + // //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + // if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + // { + // if (notice != null) + // { + // var inviter = session.FindMemberInfoById(member.inviter_id); + // if (inviter != null) + // { + // #region 判断上级是否符合获得推荐新人奖励 + // isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.order_amount); + // #endregion + + // notice.Add(new OrderNoticeEvent(CpsType.多多进宝, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + // } + // } + // } + // else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + // { + // var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},拼多多购物1级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + // if (flag != null) + // { + // ids.Add(flag.id); + + // //#region 判断上级是否符合获得推荐新人奖励 + // //isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.order_amount); + // //#endregion + + // //notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + // notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.一级提成) { Customer = member }); + + // if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + // { + // var flag2 = session.ChangePoint(PointType.维权扣除, point.AwardTwo, flag.inviter_id, $"{member.usernick},拼多多购物2级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + // if (flag2 != null) + // { + // ids.Add(flag2.id); + // if (flag2 != null) + // { + // notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + // if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + // { + // var flag3 = session.ChangePoint(PointType.维权扣除, point.AwardThree, flag2.inviter_id, $"{member.usernick},拼多多购物3级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + // if (flag3 != null) + // { + // ids.Add(flag3.id); + // if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + // } + // } + // } + // } + // } + // } + // } + + // //创建人计算 + // if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + // { + // var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + // if (robot != null) + // { + // var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + // if (create != null && member.id != create.id) + // { + // var flag = session.ChangePoint(PointType.维权扣除, point.AwardCreate, create.mid, $"{member.usernick},拼多多维护提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + // if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + // } + // } + // } + // } + //} + #endregion + new OrderHelper().DeductPinDuoOrderPoint(notice, db_order); + } + else + { + db_order.db_status = SystemOrderStatus.订单失效; + } + #endregion + break; + case PinduoduoOrderStatus.没有佣金: + db_order.db_status = SystemOrderStatus.订单失效; + break; + case PinduoduoOrderStatus.等待付款: + db_order.db_status = SystemOrderStatus.订单创建; + break; + default: + db_order.db_status = SystemOrderStatus.订单未知; break; + } + + #region 通知客户订单付款/失效 提示上级 + if (member != null && (db_order.db_status == SystemOrderStatus.订单付款 || db_order.db_status == SystemOrderStatus.订单失效)) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + //一级用户对象 + var member_one = session.FindMemberInfoById(member.inviter_id); + if (member_one != null) + { + ids.Add(member_one.id); + if (notice != null) + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member_one, db_order, OrderNoticeType.一级提成) { Customer = member }); + if (point.AwardTwo > 0 && member_one.inviter_id != 0 && !ids.Contains(member_one.inviter_id)) + { + //二级用户对象 + var member_two = session.FindMemberInfoById(member_one.inviter_id); + if (member_two != null) + { + ids.Add(member_two.id); + if (notice != null && member_two != null) + { + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member_two, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && member_two.inviter_id != 0 && !ids.Contains(member_two.inviter_id)) + { + //三级用户对象 + var member_three = session.FindMemberInfoById(member_two.inviter_id); + if (member_three != null) + { + ids.Add(member_three.id); + if (notice != null && member_three != null) + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member_three, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var member_create = session.FindMemberInfoById(create.mid); + if (notice != null && member_create != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member_create, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + #endregion + if (old_status != db_order.db_status) + db_order.db_status_time = HttpExtend.GetTimeStamp(); + + session.SaveOrUpdate(db_order); + if (db_order.db_status == SystemOrderStatus.订单付款) + { + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + } + + //if (notice != null && (isFrontData || old_status != db_order.db_status)) + if (notice != null && (isFrontData || old_status != db_order.db_status) + && ((islotUserQuery && member == null) || member != null)) + notice.Add(new Events.OrderNoticeEvent(CpsType.多多进宝, member, db_order, OrderNoticeType.客户订单) { IsRewards = isFirstOrder }); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新拼多多订单错误:" + db_order.order_sn + "," + ex.Message); + } + } + + /// + /// 同步订单 + /// + /// 拼多多cps对象集合 + /// 开始时间 + /// 结束时间 + private void UpdateOrder(fl_cps_member[] members, DateTime start_time, DateTime end_time) + { + if (members == null || members.Length == 0) return; + + UnValidCpsMember(members); + + int row_count = 50;//间隔 + //var timespan = end_time - start_time; + //var forcount = 1; + //if (timespan.TotalHours > 24.00) + //{ + // forcount = (int)(timespan.TotalHours / 24); + // if (timespan.TotalHours % 24 > 0) forcount++; + //}; + var timespan = end_time - start_time; + TaskTool task = new TaskTool(); + List notices = new List(); + var not_download_pids = ApiClient.Setting.SystemConfig.order_pinduoduo_not_download_pid.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + members = members.Where(f => f.is_valid).ToArray(); + + foreach (var item in members) + { + var _item = item; + var client = new PinduoduoApi(_item); + task.AddTask(delegate + { + try + { + var _star = timespan.TotalHours > 24 ? end_time : start_time;//倒叙24小时一个间断 + var _end = end_time; + do + { + if (timespan.TotalHours > 24) + { + _end = _star; + _star = _star.AddHours(-23.99); + } + + var rst = client.DownOrder(_star, _end, 1, row_count); + + int total_count = int.Parse(rst["total_count"].ToString()); + if (total_count == 0) continue; + var order_list = rst["order_list"] as ArrayList; + Exception _exception = null; + int count = total_count / row_count; + if (total_count % row_count != 0) count++; + + for (int i = 1; i <= count; i++) + { + var page = i; + if (_exception != null) return; + try + { + Dictionary _rst = null; + //下载 + if (page != 1) + { + _rst = client.DownOrder(_star, _end, page, row_count); + order_list = _rst["order_list"] as ArrayList; + } + + if (order_list != null && order_list.Count > 0) + { + int _count = 1; + foreach (Dictionary _order in order_list) + { + _count++; + + var session = ApiClient.GetSession(); + try + { + //if (_order["order_sn"].ToString() == "200525-419953705981880") + if (_order["order_sn"].ToString() == "220716-265625301872658") + { + } + + #region 不处理的PID + if (ApiClient.Setting.SystemConfig.order_pinduoduo_download_set_pids == SwitchType.关闭) + { + if (not_download_pids.Count != 0) + { + var isExist = not_download_pids.Contains(_order["p_id"].ToString());//是否包含 + //continue; + if (ApiClient.Setting.SystemConfig.order_pinduoduo_down_type == DownAdzoneType.不下载推广位 && isExist) + continue; + else if (ApiClient.Setting.SystemConfig.order_pinduoduo_down_type == DownAdzoneType.只下载推广位 && !isExist) + continue; + } + } + else + { + var adzoneList = new List(); + var adzones = session.FindAdzoneInfos(); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "拼多多返利" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.Contains(_order["p_id"].ToString()))); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "用户私人pid" && f.extend == "拼多多私人pid" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.Contains(_order["p_id"].ToString()))); + if (adzoneList.Count() == 0) + { + continue; + } + } + #endregion + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && _count % 10 == 0) + Thread.Sleep(150); + + //计算订单信息 + var status = Util.ConvertEnum(int.Parse(_order["order_status"].ToString())); + //if (status == PinduoduoOrderStatus.等待付款) continue; + //var db_order = session.Queryable().Where(f => f.order_sn == _order["order_sn"].ToString()).First(); + var db_order = session.FindSingle("order_sn=@order_sn", new { order_sn = _order["order_sn"].ToString() }); + if (db_order != null) //跳过相同状态 + { + var statusTemp = (PinduoduoOrderStatus)db_order.order_status; + + if (status == statusTemp || + (status == PinduoduoOrderStatus.确认收货 || status == PinduoduoOrderStatus.已经结算 || status == PinduoduoOrderStatus.审核成功) && (statusTemp == PinduoduoOrderStatus.确认收货 || status == PinduoduoOrderStatus.已经结算 || status == PinduoduoOrderStatus.审核成功)) + { + if (db_order.IsFinish()) continue;//是否已经完成 + if (db_order.db_status == SystemOrderStatus.订单冻结 && db_order.db_endtime > DateTime.Now) continue;//跳过系统冻结 + if (db_order.order_status != 2 && db_order.order_status == (int)status) continue;//跳过相同状态 + } + db_order.order_status = (int)status; + if (db_order.goods_price == 0 || db_order.order_amount == 0 || db_order.promotion_amount == 0) + { + var temp = _order.ConvertToObj(); + db_order.promotion_amount = temp.promotion_amount == 0 ? 0 : Math.Round(temp.promotion_amount / 100.00, 2); + db_order.order_amount = temp.order_amount == 0 ? 0 : Math.Round(temp.order_amount / 100.00, 2); + db_order.goods_price = temp.goods_price == 0 ? 0 : Math.Round(temp.goods_price / 100.00, 2); + } + if (db_order.price_compare_status != (PinduoduoBiJiaType)db_order.price_compare_status) + db_order.price_compare_status = (PinduoduoBiJiaType)db_order.price_compare_status; + + } + else + { + db_order = _order.ConvertToObj(); + db_order.promotion_amount = db_order.promotion_amount == 0 ? 0 : Math.Round(db_order.promotion_amount / 100.00, 2); + db_order.order_amount = db_order.order_amount == 0 ? 0 : Math.Round(db_order.order_amount / 100.00, 2); + db_order.goods_price = db_order.goods_price == 0 ? 0 : Math.Round(db_order.goods_price / 100.00, 2); + db_order.db_cpsname = _item.username; + db_order.db_cpsnick = _item.usernick; + } + if (string.IsNullOrWhiteSpace(db_order.mall_id)) + { + //var reg = Regex.Match(db_order.custom_parameters, @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.+?)(?:\smallid=(?<店铺ID>\d+))?$"); + var reg = Regex.Match(db_order.custom_parameters, custom_parameters_regex); + if (reg.Success && reg.Groups["店铺ID"] != null && !string.IsNullOrWhiteSpace(reg.Groups["店铺ID"].ToString())) + db_order.mall_id = reg.Groups["店铺ID"].ToString(); + + if (string.IsNullOrWhiteSpace(db_order.mall_id)) + { + var query_item = session.FindSingle("select * from fl_query_hist where itemid = @itemid", new { itemid = db_order.goods_id }); + if (query_item != null) + db_order.mall_id = query_item.mallid; + } + } + + UpdateOrder(db_order, session, notices); + //if (!result.Result) + //{ + // _exception = result.Exception;return; + //} + } + catch (Exception ex) + { + throw ex; + } + finally + { + //session.Close(); + } + } + } + } + catch (Exception ex) + { + _exception = ex; return; + } + } + if (_exception != null) throw _exception; + + //_star = _star.AddHours(-23.99); + } while (_star > start_time); + } + catch (Exception ex) + { + //throw ex; + } + }); + } + task.Start(1, null); + + if (string.IsNullOrEmpty(order_id)) + { + var session = ApiClient.GetSession(); + var end_orders = session.Find("select * from fl_order_pinduoduo where db_status=@db_status and db_endtime<@db_endtime", new { db_status = (int)SystemOrderStatus.订单冻结, db_endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ToList(); + foreach (var db_order in end_orders) + { + UpdateOrder(db_order, session, notices); + } + } + + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.Member == null) continue; + var order = item.Order as fl_order_pinduoduo; + if (order.order_sn == order_id) continue; + tasks.Add(item); + } + } + + //TaskTool task = new TaskTool(); + //task.AddTask(delegate { + + //}); + //var session = ApiClient.GetSession();//获得一个Session + //int thread_count = 6000; + + } + + private static DateTime invalidnotice_time = DateTime.MinValue;//阿里妈妈账号无效通知时间 + private static DateTime invalidnotice_time2 = DateTime.MinValue;//阿里妈妈账号日志无效时间 + + /// + /// 无效的拼多多账号通知 + /// + /// 拼多多cps对象集合 + private void UnValidCpsMember(fl_cps_member[] _members) + { + try + { + var invalid_members = _members.Where(f => !f.is_valid).ToArray(); + if (invalid_members.Length != 0) + { + var strb = new StringBuilder(); + strb.AppendLine($"拼多多更新订单异常"); + strb.AppendLine(); + + for (int i = 0; i < invalid_members.Length; i++) + { + strb.AppendLine($"{invalid_members[i].usernick} ({invalid_members[i].username})"); + } + strb.AppendLine(); + strb.AppendLine($"以上账号授权状态已过期"); + strb.AppendLine($"跳过以上账号下载操作"); + strb.AppendLine($"请重新登录拼多多账号"); + + var timelag2 = (DateTime.Now - invalidnotice_time2).TotalMinutes; + + if (timelag2 > 5) + { + invalidnotice_time2 = DateTime.Now; + EventClient.OnEvent(this, strb.ToString()); + } + + var timelag = (DateTime.Now - invalidnotice_time).TotalMinutes; + + if (timelag > 30) + { + strb.AppendLine($"系统时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); + invalidnotice_time = DateTime.Now; + ApiClient.SendNoticeMessage(strb.ToString()); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "拼多多账号授权失效通知", strb.ToString(), true); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"更新拼多多订单异常7:{ex.Message},{ex.StackTrace}"); + } + } + } +} diff --git a/类库/Api.Framework/Timers/DownSuningTimer.cs b/类库/Api.Framework/Timers/DownSuningTimer.cs new file mode 100644 index 0000000..9c197ce --- /dev/null +++ b/类库/Api.Framework/Timers/DownSuningTimer.cs @@ -0,0 +1,919 @@ +using Api.Framework.Cps; +using Api.Framework.EntityTmp.SuNing3; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Timers +{ + /// + /// 苏宁订单同步 + /// + public class DownSuningTimer : TimerTask + { + private DateTime update_time = DateTime.Now.AddMinutes(-120); + public override void Run(object state, bool timedOut) + { + var end_time = DateTime.Now; + UpdateOrder(CpsClient.Members.Where(f => f.cpstype == CpsType.苏宁易购 && f.is_download == SwitchType.开启).ToArray(), update_time, end_time); + update_time = DateTime.Now.AddMinutes(-70); + } + + /// + /// 订单id + /// + private string order_id = string.Empty; + private object lock_obj = new object(); + /// + /// 手动同步订单 + /// + /// 苏宁cps对象集合 + /// 开始时间 + /// 结束时间 + public void UpdateOrder(List members, DateTime start_time, DateTime end_time) + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + + UpdateOrder(members.ToArray(), start_time, end_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新苏宁订单异常:" + ex.Message); + } + finally + { + IsRunning = false; + } + } + + /// + /// 更新订单 + /// + /// 开始时间 + /// 结束时间 + /// 订单id + /// + internal bool UpdateOrder(DateTime start_time, DateTime end_time, string order_id = "") + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + this.order_id = order_id; + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.苏宁易购 && f.is_download == SwitchType.开启).ToArray(); + + UnValidCpsMember(members); + + UpdateOrder(members, start_time, end_time); + return true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新苏宁异常:" + ex.Message); + return false; + } + finally + { + this.order_id = string.Empty; + IsRunning = false; + } + + } + + //private static string custom_parameters_regex = @"^robot=(?<机器人名>.*?)\stype=(?<类型>\d+)\suser=(?<会员名>.+?)(?:\smallid=(?<店铺ID>\d+)?)?$"; + + private static string custom_parameters_regex = @"^pid=(?.+?)\sr=(?<机器人名>.*?)\st=(?<类型>\d*)\su=(?<会员名>[^\s]*)\smid=(?<店铺ID>[^\s]*)\sgid=(?<商品ID>[^\s]*)\sg=(?<群ID>.*)$"; + + /// + /// 订单 修改状态/用户绑定等操作通知用户 + /// + /// 苏宁订单对象 + /// 数据库操作对象 + /// 事件集合 + /// + public void UpdateOrder(fl_order_suning db_order, SqlSugarClient session, List notice, bool isFrontData = false) + { + try + { + var old_status = db_order.db_status; + fl_member_info member = null; + var isRewards = false;//是否获得推荐新人奖励 + var isFirstOrder = false;//是否获得用户首单奖励 + var islotUserQuery = false;//订单是否为多人查询 + + //订单自动绑定 + if (db_order.db_userid == 0 && ApiClient.Setting.SystemConfig.order_suning_bind == SwitchType.开启) + { + var isbind = false; + #region 苏宁返利进行自动绑定 + + if (!string.IsNullOrWhiteSpace(db_order.childAccountId)) + { + var custom = Util.DecryptDES(db_order.childAccountId); + var reg = Regex.Match(custom, custom_parameters_regex); + if (reg.Success) + { + var pid = reg.Groups["pid"].Value;//推广位pid + var rwxid = reg.Groups["机器人名"].Value;//机器人xiid + var rtype = reg.Groups["类型"].Value;//机器人类型 + var uwxid = reg.Groups["会员名"].Value;//用户wxid + var mallid = reg.Groups["店铺ID"].Value;//店铺id + var gid = reg.Groups["商品ID"].Value;//商品id + var groupid = reg.Groups["群ID"].Value;//商品id + + db_order.mallId = mallid; + db_order.pid = pid; + + //私人推广位强制绑定绑定 + var privateAdzonePids = session.FindSuningPrivatePid(pid); + if (privateAdzonePids.Count == 1 && privateAdzonePids[0].is_auto_bind)//无条件设置开启中,直接自动绑定 + { + var memberInfo = session.FindMemberInfoById(privateAdzonePids[0].member_id); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + isbind = true; + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = gid, adzoneid = pid, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.苏宁易购 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + } + + + if (!isbind) + { + var bind_pids = session.FindSuningAutoBindPid(); + bool flag = bind_pids.FirstOrDefault(f => f == pid) != null ? true : false; + #endregion + if (flag) + { + #region 有定义custom_parameters参数 + member = session.FindSingle("username=@username and robot_type=@robot_type", new { username = uwxid, robot_type = rtype }); + if (member == null) + { + member = new fl_member_info() { robot_type = Util.ConvertEnum(int.Parse(rtype)), username = uwxid, robot_name = rwxid, alipay_name = string.Empty, alipay_num = string.Empty, remark = string.Empty }; + var groups = session.FindGroups(); + if (groups.Count != 0) + member.group_id = groups[0].id; + session.SaveOrUpdate(member); + } + db_order.db_userid = member.id; + if (string.IsNullOrEmpty(db_order.db_robotname)) + { + db_order.db_robotname = rwxid; + db_order.db_robottype = Util.ConvertEnum(int.Parse(rtype)); + } + + //绑定群号 + db_order.msg_groupid = groupid; + + #endregion + + #region 没有定义custom_parameters参数,进行逻辑绑定 + //else + { + //订单没有绑定用户 查询订单记录 + if (db_order.db_userid == 0) + { + var query = session.FindTable("select userid,count(*) as count from fl_query_hist where userid != 0 and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time group by userid ", new { itemid = gid, adzoneid = pid, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query != null && query.Rows.Count > 0) + { + if (query.Rows.Count == 1) + { + var userid = int.Parse(query.Rows[0]["userid"].ToString());//要是查询记录已经标记为通知过的记录(userid 为 负数),将不通过查询记录进行绑定 + if (userid > 0) + { + db_order.db_userid = userid;//根据查询记录认领 + + var query_item = session.FindSingle("select * from fl_query_hist where userid = @userid and itemid = @itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = gid, adzoneid = pid, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.苏宁易购 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + } + } + else + { + //订单多人查询,并且订单还未绑定 + if (db_order.db_userid == 0) + islotUserQuery = true; + } + } + } + } + #endregion + + } + } + } + } + } + else + { + member = session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault(); + } + + if ((db_order.orderLineStatusDesc == SuNingSubOrderStatus.支付完成.ToString()) && db_order.db_userid != 0) + { + try + { + var record = session.FindStatisticsRecord(db_order.db_userid); + if (record == null) + record = new fl_statistics_record() { uid = db_order.db_userid }; + record.ex5 = HttpExtend.GetTimeStamp(db_order.payTime); + session.Saveable(record).ExecuteCommand(); + } + catch (Exception) + { } + } + //计算积分 + if (string.IsNullOrEmpty(db_order.db_point)) + { + if (member == null) member = session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault(); + + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.苏宁易购, db_order.id); + + ItemPoint itempoint = null; + if (compute != null) + itempoint = session.FindItemPoint(CpsType.苏宁易购, compute, double.Parse(db_order.prePayCommission), int.Parse(db_order.saleNum)); + else + itempoint = session.FindItemPoint(member, double.Parse(db_order.prePayCommission), int.Parse(db_order.saleNum), CpsType.苏宁易购); + if (itempoint != null) + { + if (itempoint.UserPoint == 0 && ApiClient.Setting.SystemConfig.SubsidyPdd == SwitchType.开启) + itempoint.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + db_order.db_userpoint = itempoint.UserPoint; + } + if (member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + } + + if (member != null && string.IsNullOrWhiteSpace(db_order.db_robotname)) + { + db_order.db_robotname = member.robot_name; + db_order.db_robottype = member.robot_type; + } + + var status = Util.ConvertEnum(db_order.orderLineStatusDesc); + switch (status) + { + case SuNingSubOrderStatus.确认收货: + { + //未发放佣金 + if (db_order.db_endtime == DateTime.MinValue) + { + var sleep = session.FindSleep(CpsType.苏宁易购, ApiClient.Setting.SystemConfig.FreezingCondition == FreezingConditionType.商品总佣金 ? double.Parse(db_order.prePayCommission) : db_order.db_userpoint); + if (sleep != null) + { + if (!string.IsNullOrEmpty(sleep.white_groups)) + { + if (member != null && sleep.white_groups.Split(',').Contains(member.group_id.ToString())) + { + db_order.db_endtime = DateTime.Now;//该会员组不受限制 + } + else + { + db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + } + else db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else db_order.db_endtime = DateTime.Now; + + #region 验证订单是否为24小时 + var config = Util.Read>("插件-苏宁返利-配置"); + if (config != null) + { + if (config.ContainsKey("ReceivingTimeCheck_Switch")) + { + var ReceivingTimeCheck_Switch = (bool)config["ReceivingTimeCheck_Switch"]; + if (ReceivingTimeCheck_Switch) + { + if (config.ContainsKey("ReceivingTimeCheck_Hour")) + { + var ReceivingTimeCheck_Hour = int.Parse(config["ReceivingTimeCheck_Hour"].ToString()); + if ((DateTime.Now - db_order.payTime).TotalHours <= ReceivingTimeCheck_Hour)//判断订单收货时间差 + { + if (config.ContainsKey("ReceivingTimeCheck_OperateType")) + { + var ReceivingTimeCheck_OperateType = (OperateType)int.Parse(config["ReceivingTimeCheck_OperateType"].ToString()); + if (ReceivingTimeCheck_OperateType == OperateType.订单冻结) + { + if (config.ContainsKey("ReceivingTimeCheck_FreezeTime")) + { + var ReceivingTimeCheck_FreezeTime = int.Parse(config["ReceivingTimeCheck_FreezeTime"].ToString()); + db_order.db_endtime = db_order.db_endtime.AddHours(ReceivingTimeCheck_FreezeTime);//延迟多少小时 + } + } + } + } + } + } + } + } + #endregion + + } + if (db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.订单结算; + //session.ExcuteSQL("update fl_order_suning set db_status=" + (int)db_order.db_status + " where id=" + db_order.id); + if (member != null) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.消费补贴, point.UserPoint, member.id, $"苏宁购买:{db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber})"); + + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + + //notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, member, db_order)); + //多级提成计算 + + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, double.Parse(db_order.payAmount)); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + } + } + else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardOne, member.inviter_id, $"{member.usernick},苏宁购物1级提成! - {db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber})"); + if (flag != null) + { + ids.Add(flag.id); + + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, double.Parse(db_order.payAmount)); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.提成奖励, point.AwardTwo, flag.inviter_id, $"{member.usernick},苏宁购物2级提成! - {db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.提成奖励, point.AwardThree, flag2.inviter_id, $"{member.usernick},苏宁购物3级提成! - {db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardCreate, create.mid, $"{member.usernick},苏宁维护提成! - {db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber})"); + if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + } + } + else db_order.db_status = SystemOrderStatus.订单冻结; + break; + } + case SuNingSubOrderStatus.支付完成: + { + db_order.db_status = SystemOrderStatus.订单付款; + } + break; + //case SuNingSubOrderStatus.审核失败: + // #region 全额维权 + // if (db_order.db_endtime != DateTime.MinValue && db_order.db_endtime <= DateTime.Now) + // { + // db_order.db_status = SystemOrderStatus.全额退款; + // new OrderHelper().DeductSuningOrderPoint(notice, db_order); + // } + // else + // { + // db_order.db_status = SystemOrderStatus.订单失效; + // } + // #endregion + // break; + case SuNingSubOrderStatus.订单已取消: + case SuNingSubOrderStatus.退款: + //db_order.db_status = SystemOrderStatus.订单失效; + if (db_order.db_endtime != DateTime.MinValue && db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.全额退款; + new OrderHelper().DeductSuningOrderPoint(notice, db_order); + } + else + { + db_order.db_status = SystemOrderStatus.订单失效; + } + break; + case SuNingSubOrderStatus.等待支付: + db_order.db_status = SystemOrderStatus.订单创建; + break; + default: + db_order.db_status = SystemOrderStatus.订单未知; + break; + } + + #region 通知客户订单付款/失效 提示上级 + if (member != null && (db_order.db_status == SystemOrderStatus.订单付款 || db_order.db_status == SystemOrderStatus.订单失效)) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + //一级用户对象 + var member_one = session.FindMemberInfoById(member.inviter_id); + if (member_one != null) + { + ids.Add(member_one.id); + if (notice != null) + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, member_one, db_order, OrderNoticeType.一级提成) { Customer = member }); + if (point.AwardTwo > 0 && member_one.inviter_id != 0 && !ids.Contains(member_one.inviter_id)) + { + //二级用户对象 + var member_two = session.FindMemberInfoById(member_one.inviter_id); + if (member_two != null) + { + ids.Add(member_two.id); + if (notice != null && member_two != null) + { + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, member_two, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && member_two.inviter_id != 0 && !ids.Contains(member_two.inviter_id)) + { + //三级用户对象 + var member_three = session.FindMemberInfoById(member_two.inviter_id); + if (member_three != null) + { + ids.Add(member_three.id); + if (notice != null && member_three != null) + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, member_three, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var member_create = session.FindMemberInfoById(create.mid); + if (notice != null && member_create != null) notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, member_create, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + #endregion + if (old_status != db_order.db_status) + db_order.db_status_time = HttpExtend.GetTimeStamp(); + + session.SaveOrUpdate(db_order); + if (db_order.db_status == SystemOrderStatus.订单付款) + { + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + } + + //if (notice != null && (isFrontData || old_status != db_order.db_status)) + if (notice != null && (isFrontData || old_status != db_order.db_status) + && ((islotUserQuery && member == null) || member != null)) + notice.Add(new Events.OrderNoticeEvent(CpsType.苏宁易购, member, db_order, OrderNoticeType.客户订单) { IsRewards = isFirstOrder }); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新苏宁订单错误:" + db_order.orderCode + "," + ex.Message); + } + } + + /// + /// 同步订单 + /// + /// 苏宁cps对象集合 + /// 开始时间 + /// 结束时间 + private void UpdateOrder(fl_cps_member[] members, DateTime start_time, DateTime end_time) + { + if (members == null || members.Length == 0) return; + + UnValidCpsMember(members); + + int row_count = 50;//间隔 + //var timespan = end_time - start_time; + //var forcount = 1; + //if (timespan.TotalHours > 24.00) + //{ + // forcount = (int)(timespan.TotalHours / 24); + // if (timespan.TotalHours % 24 > 0) forcount++; + //}; + var timespan = end_time - start_time; + TaskTool task = new TaskTool(); + List notices = new List(); + var not_download_pids = ApiClient.Setting.SystemConfig.order_suning_not_download_pid.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + + members = members.Where(f => f.is_valid).ToArray(); + + foreach (var item in members) + { + var _item = item; + var client = new SuNingApi(_item); + task.AddTask(delegate + { + try + { + var _star = timespan.TotalHours > 24 ? end_time : start_time;//倒叙24小时一个间断 + var _end = end_time; + do + { + if (timespan.TotalHours > 24) + { + _end = _star; + _star = _star.AddHours(-23.99); + } + + var rst = client.DownOrder(_star, _end, 1, row_count); + + if (rst != null && rst.sn_responseContent.sn_head != null) + { + int total_count = rst.sn_responseContent.sn_head.totalSize; + if (total_count == 0) continue; + if (rst.sn_responseContent.sn_body == null) continue; + var order_list = rst.sn_responseContent.sn_body.queryOrder; + Exception _exception = null; + int count = total_count / row_count; + if (total_count % row_count != 0) count++; + + for (int i = 1; i <= count; i++) + { + var page = i; + if (_exception != null) return; + try + { + rst = null; + //下载 + if (page != 1) + { + rst = client.DownOrder(_star, _end, page, row_count); + if (rst == null || rst.sn_responseContent == null || rst.sn_responseContent.sn_body == null) + continue; + order_list = rst.sn_responseContent.sn_body.queryOrder; + } + + if (order_list != null && order_list.Count > 0) + { + int _count = 1; + foreach (EntityTmp.SuNing3.QueryOrder _order in order_list) + { + _count++; + + var session = ApiClient.GetSession(); + try + { + //if (_order.orderCode == "40196344057") + //{ + //} + + foreach (var order in _order.orderDetail) + { + try + { + var custom = Util.DecryptDES(order.childAccountId); + #region 不处理的PID + if (ApiClient.Setting.SystemConfig.order_suning_download_set_pids == SwitchType.关闭) + { + if (not_download_pids.Count != 0) + { + var isExist = not_download_pids.FirstOrDefault(f => custom.StartsWith(f)) != null;//是否包含 + if (ApiClient.Setting.SystemConfig.order_suning_down_type == DownAdzoneType.不下载推广位 && isExist) + continue; + else if (ApiClient.Setting.SystemConfig.order_suning_down_type == DownAdzoneType.只下载推广位 && !isExist) + continue; + } + } + else + { + //var adzone = session.FindAdzoneInfos().Where(f => f.custom_type == "苏宁返利" && !string.IsNullOrEmpty(f.adzone_pid) && custom.StartsWith(f.adzone_pid)); + + var adzoneList = new List(); + var adzones = session.FindAdzoneInfos(); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "苏宁返利" && !string.IsNullOrEmpty(f.adzone_pid) && custom.StartsWith($"pid={f.adzone_pid}"))); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "用户私人pid" && f.extend == "苏宁私人pid" && !string.IsNullOrEmpty(f.adzone_pid) && custom.StartsWith($"pid={f.adzone_pid}"))); + if (adzoneList == null || adzoneList.Count() == 0) + { + continue; + } + } + #endregion + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && _count % 10 == 0) + Thread.Sleep(150); + + //计算订单信息 + var status = Util.ConvertEnum(order.orderLineStatusDesc); + var db_order = session.FindSingle("orderCode=@orderCode and orderLineNumber = @orderLineNumber", new { orderCode = _order.orderCode, orderLineNumber = order.orderLineNumber }); + if (db_order != null) + { + var statusTemp = Util.ConvertEnum(db_order.orderLineStatusDesc); + + if (status == statusTemp || (status == SuNingSubOrderStatus.确认收货) && (statusTemp == SuNingSubOrderStatus.确认收货 || status == SuNingSubOrderStatus.确认收货)) + { + if (db_order.IsFinish()) continue;//是否已经完成 + if (db_order.db_status == SystemOrderStatus.订单冻结 && db_order.db_endtime > DateTime.Now) continue;//跳过系统冻结 + if (db_order.orderLineStatusDesc != SuNingSubOrderStatus.确认收货.ToString() && db_order.orderLineStatusDesc == status.ToString()) continue;//跳过相同状态 + + } + db_order.orderLineStatusDesc = status.ToString(); + } + else + { + db_order = ConvertDBSuNingOrder(db_order, order, _order.orderCode); + db_order.db_cpsname = _item.username; + db_order.db_cpsnick = _item.usernick; + } + + var strb = new StringBuilder(); + try + { + strb.AppendLine($@"苏宁订单 原始: {JsonConvert.SerializeObject(db_order)} + +"); + } + catch (Exception ex) + { } + + UpdateOrder(db_order, session, notices); + + try + { + strb.AppendLine($@"处理后: {JsonConvert.SerializeObject(db_order)} +通知数:{notices.Count}"); + LogHelper.GetSingleObj().Debug("同步订单:", strb.ToString()); + } + catch (Exception ex) + { } + } + catch (Exception ex) + { + throw ex; + } + } + } + catch (Exception ex) + { + throw ex; + } + finally + { + //session.Close(); + } + } + } + } + catch (Exception ex) + { + _exception = ex; return; + } + } + if (_exception != null) throw _exception; + + //_star = _star.AddHours(-23.99); + } + } while (_star > start_time); + } + catch (Exception ex) + { + //throw ex; + } + }); + } + task.Start(1, null); + + if (string.IsNullOrEmpty(order_id)) + { + var session = ApiClient.GetSession(); + var end_orders = session.Find("select * from fl_order_suning where db_status=@db_status and db_endtime<@db_endtime", new { db_status = (int)SystemOrderStatus.订单冻结, db_endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ToList(); + foreach (var db_order in end_orders) + { + UpdateOrder(db_order, session, notices); + } + } + + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + //if (item.Member == null) continue; + var order = item.Order as fl_order_suning; + if (order.orderCode == order_id) continue; + tasks.Add(item); + } + } + + //TaskTool task = new TaskTool(); + //task.AddTask(delegate { + + //}); + //var session = ApiClient.GetSession();//获得一个Session + //int thread_count = 6000; + + } + + private fl_order_suning ConvertDBSuNingOrder(fl_order_suning suning, EntityTmp.SuNing3.OrderDetail order, string orderCode) + { + try + { + if (suning == null) + suning = new fl_order_suning(); + + suning.orderCode = orderCode; + suning.childAccountId = order.childAccountId; + suning.commissionRatio = order.commissionRatio; + suning.custNo = order.custNo; + suning.goodsGroupCatalog = order.goodsGroupCatalog; + suning.goodsNum = order.goodsNum; + suning.orderLineFlag = order.orderLineFlag; + suning.orderLineNumber = order.orderLineNumber; + suning.orderLineOrigin = order.orderLineOrigin; + suning.orderLineStatusChangeTime = order.orderLineStatusChangeTime; + suning.orderLineStatusDesc = order.orderLineStatusDesc; + suning.orderSubmitTime = order.orderSubmitTime; + suning.orderType = order.orderType; + suning.payAmount = order.payAmount; + suning.payTime = order.payTime; + suning.pictureUrl = order.pictureUrl; + suning.positionId = order.positionId; + suning.prePayCommission = order.prePayCommission; + suning.productFirstCatalog = order.productFirstCatalog; + suning.productName = order.productName; + suning.productSecondCatalog = order.productSecondCatalog; + suning.productThirdCatalog = order.productThirdCatalog; + suning.promotion = order.promotion; + suning.returnCommission = order.returnCommission; + suning.saleNum = order.saleNum; + suning.saleType = order.saleType; + suning.sellerCode = order.sellerCode; + suning.sellName = order.sellName; + suning.statParam = order.statParam; + suning.violation = order.violation; + } + catch (Exception ex) + { + throw ex; + } + return suning; + } + + + private static DateTime invalidnotice_time = DateTime.MinValue;//阿里妈妈账号无效通知时间 + private static DateTime invalidnotice_time2 = DateTime.MinValue;//阿里妈妈账号日志无效时间 + + /// + /// 无效的苏宁账号通知 + /// + /// 苏宁cps对象集合 + private void UnValidCpsMember(fl_cps_member[] _members) + { + try + { + var invalid_members = _members.Where(f => !f.is_valid).ToArray(); + if (invalid_members.Length != 0) + { + var strb = new StringBuilder(); + strb.AppendLine($"苏宁更新订单异常"); + strb.AppendLine(); + + for (int i = 0; i < invalid_members.Length; i++) + { + strb.AppendLine($"{invalid_members[i].usernick} ({invalid_members[i].username})"); + } + strb.AppendLine(); + strb.AppendLine($"以上账号授权状态已过期"); + strb.AppendLine($"跳过以上账号下载操作"); + strb.AppendLine($"请重新登录苏宁账号"); + + var timelag2 = (DateTime.Now - invalidnotice_time2).TotalMinutes; + + if (timelag2 > 5) + { + invalidnotice_time2 = DateTime.Now; + EventClient.OnEvent(this, strb.ToString()); + } + + var timelag = (DateTime.Now - invalidnotice_time).TotalMinutes; + + if (timelag > 30) + { + strb.AppendLine($"系统时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); + invalidnotice_time = DateTime.Now; + ApiClient.SendNoticeMessage(strb.ToString()); + ApiClient.SendAdminEmail(ApiClient.Setting.SystemConfig.account_admin_email, "苏宁账号授权失效通知", strb.ToString(), true); + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"更新苏宁订单异常7:{ex.Message},{ex.StackTrace}"); + } + } + } +} diff --git a/类库/Api.Framework/Timers/DownWeipinhuiTimer.cs b/类库/Api.Framework/Timers/DownWeipinhuiTimer.cs new file mode 100644 index 0000000..e4ccc7e --- /dev/null +++ b/类库/Api.Framework/Timers/DownWeipinhuiTimer.cs @@ -0,0 +1,1001 @@ +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Tools; +using Api.Framework.Utils; +using CsharpHttpHelper; +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Timers +{ + /// + /// 唯品会订单下载定时器 + /// + public class DownWeipinhuiTimer : TimerTask + { + private DateTime update_time = DateTime.Now.AddMinutes(-60); + public override void Run(object state, bool timedOut) + { + var end_time = DateTime.Now; + UpdateOrder(CpsClient.Members.Where(f => f.cpstype == CpsType.唯品联盟 && f.is_download == SwitchType.开启).ToArray(), update_time, end_time); + update_time = DateTime.Now.AddMinutes(-20); + + #region 需要重新登录的联盟账号通知钉钉 + var cps_expires = CpsClient.Members.Where(f => f.cpstype == CpsType.唯品联盟 && f.abnormal_tip == SwitchType.开启 && !f.is_valid).ToList(); + if (cps_expires != null && cps_expires.Count != 0) + { + foreach (var cps in cps_expires) + { + var key = $"weipinhui_cps_expire_{cps.username}"; + var value = ApiClient.Cache.Get(key); + if (string.IsNullOrWhiteSpace(value)) + { + var session = ApiClient.GetSession(); + var robot = session.FindRobots().FirstOrDefault(); + + StringBuilder strb = new StringBuilder(); + strb.AppendLine("唯品会状态异常"); + strb.AppendLine("---------------------"); + if (robot != null) + strb.AppendLine("所在机器人:" + robot.nick + $"({robot.name})"); + + strb.AppendLine("昵称:" + cps.usernick); + strb.AppendLine("账号:" + cps.username); + strb.AppendLine(); + strb.AppendLine("解决方法:重新授权登录"); + ApiClient.SendNoticeMessage(strb.ToString()); + ApiClient.Cache.Set(key, ".", 24 * 60 * 60 * 1000); + Thread.Sleep(50); + } + } + } + #endregion + } + + /// + /// 订单id + /// + private string order_id = string.Empty; + + /// + /// 手动同步订单 + /// + /// 唯品会cps对象集合 + /// 开始时间 + /// 结束时间 + public void UpdateOrder(List members, DateTime start_time, DateTime end_time) + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + + UpdateOrder(members.ToArray(), start_time, end_time); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新唯品会订单异常:" + ex.Message); + } + finally + { + IsRunning = false; + } + } + + /// + /// 更新订单 + /// + /// 开始时间 + /// 结束时间 + /// 订单id + /// + internal bool UpdateOrder(DateTime start_time, DateTime end_time, string order_id = "") + { + if (IsRunning) throw new Exception("任务繁忙,请稍后重试!"); + try + { + IsRunning = true; + this.order_id = order_id; + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.唯品联盟 && f.is_download == SwitchType.开启).ToArray(); + UpdateOrder(members, start_time, end_time); + return true; + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新唯品会异常:" + ex.Message); + return false; + } + finally + { + this.order_id = string.Empty; + IsRunning = false; + } + + } + + private static string custom_parameters_regex = @"^r=(?<机器人id>.*?)\st=(?<类型>\d+)\su=(?<会员id>.+?)\sp=(?<推广位>.+)$"; + private static string custom_parameters_regex2 = @"^r=(?<机器人id>.*?)\st=(?<类型>\d+)\sun=(?<会员id>.+?)\sp=(?<推广位>.+)$"; + + /// + /// 订单 修改状态/用户绑定等操作通知用户 + /// + /// 唯品会订单对象 + /// 数据库操作对象 + /// 事件集合 + /// + public void UpdateOrder(fl_order_weipinhui db_order, SqlSugarClient session, List notice, bool isFrontData = false) + { + if (db_order.orderSubStatusName == WeipinhuiOrderSubStatusName.已下单) + return; + + var IsContainYourself = false;//是否已经包含自己通知事件 + try + { + var old_status = db_order.db_status; + fl_member_info member = null; + var isRewards = false;//是否获得推荐新人奖励 + var isFirstOrder = false;//是否获得用户首单奖励 + + //订单自动绑定 + if (db_order.db_userid == 0 && ApiClient.Setting.SystemConfig.order_weipinhui_bind == SwitchType.开启) + { + var isbind = false; + #region 唯品会返利进行自动绑定 + //私人推广位强制绑定绑定 + var privateAdzonePids = session.FindWeipinhuiPrivatePid(db_order.pid.ToString()); + if (privateAdzonePids.Count == 1 && privateAdzonePids[0].is_auto_bind)//无条件设置开启中,直接自动绑定 + { + var memberInfo = session.FindMemberInfoById(privateAdzonePids[0].member_id); + if (memberInfo != null) + { + db_order.db_userid = memberInfo.id; + db_order.db_robotname = memberInfo.robot_name; + db_order.db_robottype = memberInfo.robot_type; + isbind = true; + + #region 获取查询时的比例 + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.goodsId, adzoneid = db_order.pid, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null && !string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.唯品联盟 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + } + + if (!isbind) + { + var bind_pids = session.FindWeipinhuiAutoBindPid(); + bool flag = bind_pids.FirstOrDefault(f => f == db_order.pid) != null ? true : false; + #endregion + if (flag) + { + var mid = string.Empty; + var statParam = Util.DecryptDES(db_order.statParam); + var reg = Regex.Match(statParam, custom_parameters_regex); + if (reg.Success) + member = session.FindSingle("id=@id", new { id = reg.Groups["会员id"].Value }); + else + { + reg = Regex.Match(statParam, custom_parameters_regex2); + if (reg.Success) + { + var wxid = reg.Groups["会员id"].Value; + if (!string.IsNullOrWhiteSpace(wxid)) + member = session.FindSingle("username = @username", new { username = reg.Groups["会员id"].Value }); + } + } + if (member != null) + { + db_order.db_userid = member.id; + if (string.IsNullOrEmpty(db_order.db_robotname)) + { + var rInfo = session.FindRobots().FirstOrDefault(f => f.id.ToString() == reg.Groups["机器人id"].Value); + if (rInfo != null) + { + db_order.db_robotname = rInfo.name; + db_order.db_robottype = rInfo.type; + } + } + + #region 绑定群号 + if (string.IsNullOrWhiteSpace(db_order.msg_groupid)) + { + var query_item = session.FindSingle("userid=@userid and itemid=@itemid and adzoneid = @adzoneid and crt_time > @time order by id desc", new { userid = db_order.db_userid, itemid = db_order.goodsId, adzoneid = db_order.pid, time = DateTime.Now.AddHours(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query_item != null) + { + db_order.msg_groupid = query_item.groupid; + + #region 获取查询时的比例 + if (!string.IsNullOrWhiteSpace(query_item.compute_configdic)) + { + if (db_order.id == 0) + session.SaveOrUpdate(db_order); + var queryRatioHist = new fl_query_ratio_hist() + { + compute_config = query_item.compute_configdic, + db_orderid = db_order.id, + createtime = DateTime.Now, + cpstype = CpsType.唯品联盟 + }; + session.SaveOrUpdate(queryRatioHist); + } + #endregion + + } + } + #endregion + } + } + } + } + else + { + member = session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault(); + } + + #region 更新最后下单的时间 + //if ((db_order.orderSubStatusName == WeipinhuiOrderSubStatusName.已下单 || db_order.orderSubStatusName == WeipinhuiOrderSubStatusName.已付款) && db_order.db_userid != 0) + if (db_order.orderSubStatusName == WeipinhuiOrderSubStatusName.已付款 && db_order.db_userid != 0) + { + try + { + var record = session.FindStatisticsRecord(db_order.db_userid); + if (record == null) + record = new fl_statistics_record() { uid = db_order.db_userid }; + record.ex5 = long.Parse(db_order.orderTime.ToString().Substring(0, 10)); + session.Saveable(record).ExecuteCommand(); + } + catch (Exception) + { } + } + #endregion + + //计算积分 + if (string.IsNullOrEmpty(db_order.db_point)) + { + if (member == null) session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault(); + + //查询历史查询比例 + var compute = session.FindQueryRatioHist(CpsType.唯品联盟, db_order.id); + + ItemPoint itempoint = null; + if (compute != null) + itempoint = session.FindItemPoint(CpsType.唯品联盟, compute, db_order.commission, db_order.goodsCount); + else + itempoint = session.FindItemPoint(member, db_order.commission, db_order.goodsCount, CpsType.唯品联盟); + if (itempoint != null) + { + if (itempoint.UserPoint == 0 && ApiClient.Setting.SystemConfig.SubsidyPdd == SwitchType.开启) + itempoint.UserPoint = 0.01; + db_order.db_point = HttpHelper.ObjectToJson(itempoint); + db_order.db_userpoint = itempoint.UserPoint; + } + if (member != null) + { + member.bind_order++; + member = session.UpdateMemberGroup(member); + } + } + //var status = Util.ConvertEnum(db_order.orderSubStatusName); + switch (db_order.orderSubStatusName) + { + case WeipinhuiOrderSubStatusName.维权完成: + case WeipinhuiOrderSubStatusName.已签收: + case WeipinhuiOrderSubStatusName.待结算: + case WeipinhuiOrderSubStatusName.已结算: + { + if (db_order.commission == 0) + db_order.db_status = SystemOrderStatus.订单失效; + else + { + //未发放佣金 + if (db_order.db_endtime == DateTime.MinValue) + { + var sleep = session.FindSleep(CpsType.唯品联盟, ApiClient.Setting.SystemConfig.FreezingCondition == FreezingConditionType.商品总佣金 ? db_order.commission : db_order.db_userpoint); + if (sleep != null) + { + if (!string.IsNullOrEmpty(sleep.white_groups)) + { + if (member != null && sleep.white_groups.Split(',').Contains(member.group_id.ToString())) + { + db_order.db_endtime = DateTime.Now;//该会员组不受限制 + } + else + { + db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + } + else db_order.db_endtime = DateTime.Now.AddHours(sleep.sleep);//延迟多少小时 + } + else db_order.db_endtime = DateTime.Now; + + #region 验证订单是否为24小时 + var config = Util.Read>("插件-唯品会返利-配置"); + if (config != null) + { + if (config.ContainsKey("ReceivingTimeCheck_Switch")) + { + var ReceivingTimeCheck_Switch = bool.Parse(config["ReceivingTimeCheck_Switch"].ToString()); + if (ReceivingTimeCheck_Switch) + { + if (config.ContainsKey("ReceivingTimeCheck_Hour")) + { + var ReceivingTimeCheck_Hour = int.Parse(config["ReceivingTimeCheck_Hour"].ToString()); + if ((DateTime.Now - Util.GetDateTime(db_order.orderTime)).TotalHours <= ReceivingTimeCheck_Hour)//判断订单收货时间差 + { + if (config.ContainsKey("ReceivingTimeCheck_OperateType")) + { + var ReceivingTimeCheck_OperateType = (OperateType)int.Parse(config["ReceivingTimeCheck_OperateType"].ToString()); + if (ReceivingTimeCheck_OperateType == OperateType.订单冻结) + { + if (config.ContainsKey("ReceivingTimeCheck_FreezeTime")) + { + var ReceivingTimeCheck_FreezeTime = int.Parse(config["ReceivingTimeCheck_FreezeTime"].ToString()); + db_order.db_endtime = db_order.db_endtime.AddHours(ReceivingTimeCheck_FreezeTime);//延迟多少小时 + } + } + } + } + } + } + } + } + #endregion + + } + if (db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.订单结算; + //session.ExcuteSQL("update fl_order_weipinhui set db_status=" + (int)db_order.db_status + " where id=" + db_order.id); + if (member != null) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.消费补贴, point.UserPoint, member.id, $"唯品会购买:{db_order.goodsName}({db_order.orderSn})"); + + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + + //notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, member, db_order)); + //多级提成计算 + + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + { + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.commissionTotalCost); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + } + } + } + else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardOne, member.inviter_id, $"{member.usernick},唯品会购物1级提成! - {db_order.goodsName}({db_order.orderSn})"); + if (flag != null) + { + ids.Add(flag.id); + + #region 判断上级是否符合获得推荐新人奖励 + isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.commissionTotalCost); + #endregion + + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.提成奖励, point.AwardTwo, flag.inviter_id, $"{member.usernick},唯品会购物2级提成! - {db_order.goodsName}({db_order.orderSn})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.提成奖励, point.AwardThree, flag2.inviter_id, $"{member.usernick},唯品会购物3级提成! - {db_order.goodsName}({db_order.orderSn})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardCreate, create.mid, $"{member.usernick},唯品会维护提成! - {db_order.goodsName}({db_order.orderSn})"); + if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + } + } + else db_order.db_status = SystemOrderStatus.订单冻结; + } + break; + } + case WeipinhuiOrderSubStatusName.已付款: + db_order.db_status = SystemOrderStatus.订单付款; + break; + case WeipinhuiOrderSubStatusName.已下单://TODO 这里的状态不知道什么意思,以后在判断 + db_order.db_status = SystemOrderStatus.订单创建; + break; + case WeipinhuiOrderSubStatusName.已失效: + //if (db_order.afterSaleChangedGoodsCount == 0 && db_order.afterSaleStatus == WeipinhuiAfterSaleStatus.售后完成 && db_order.afterSaleType == WeipinhuiSfterSaleType.退货) + //{ + db_order.db_status = (old_status == SystemOrderStatus.订单结算) ? SystemOrderStatus.全额退款 : SystemOrderStatus.订单失效; + #region 全额维权,扣除账户金额 + if (member != null && old_status == SystemOrderStatus.订单结算 && db_order.db_status == SystemOrderStatus.全额退款)//扣除积分 + { + if (db_order.db_endtime != DateTime.MinValue && db_order.db_endtime <= DateTime.Now) + { + db_order.db_status = SystemOrderStatus.全额退款; + #region xxx + //if (member != null) + //{ + // var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + // if (point != null) + // { + // List ids = new List(); + // ids.Add(member.id); + // //用户自身加积分 + // member = session.ChangePoint(PointType.维权扣除, point.UserPoint, member.id, $"唯品会购买:{db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + + // //#region 判断用户是否符合获得新人奖励 + // //isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + // //#endregion + + // //notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, member, db_order)); + // //多级提成计算 + + // //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + // if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + // { + // if (notice != null) + // { + // var inviter = session.FindMemberInfoById(member.inviter_id); + // if (inviter != null) + // { + // #region 判断上级是否符合获得推荐新人奖励 + // isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.commissionTotalCost); + // #endregion + + // notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, inviter, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards });//下级首单完成 + // } + // } + // } + // else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + // { + // var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},唯品会购物1级提成! - {db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + // if (flag != null) + // { + // ids.Add(flag.id); + + // //#region 判断上级是否符合获得推荐新人奖励 + // //isRewards = OrderHelper.CheckSuperiorInviteRewards(member, db_order.db_endtime, db_order.commissionTotalCost); + // //#endregion + + // //notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag, db_order, OrderNoticeType.一级提成) { Customer = member, IsRewards = isRewards }); + // notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag, db_order, OrderNoticeType.一级提成) { Customer = member }); + + // if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + // { + // var flag2 = session.ChangePoint(PointType.维权扣除, point.AwardTwo, flag.inviter_id, $"{member.usernick},唯品会购物2级提成! - {db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + // if (flag2 != null) + // { + // ids.Add(flag2.id); + // if (flag2 != null) + // { + // notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + // if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + // { + // var flag3 = session.ChangePoint(PointType.维权扣除, point.AwardThree, flag2.inviter_id, $"{member.usernick},唯品会购物3级提成! - {db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + // if (flag3 != null) + // { + // ids.Add(flag3.id); + // if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + // } + // } + // } + // } + // } + // } + // } + + // //创建人计算 + // if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + // { + // var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + // if (robot != null) + // { + // var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + // if (create != null && member.id != create.id) + // { + // var flag = session.ChangePoint(PointType.维权扣除, point.AwardCreate, create.mid, $"{member.usernick},唯品会维护提成! - {db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + // if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + // } + // } + // } + // } + //} + #endregion + IsContainYourself = new OrderHelper().DeductWeipinhuiOrderPoint(notice, db_order); + } + else + { + db_order.db_status = SystemOrderStatus.订单失效; + } + } + #endregion + //} + //else + //{ + // db_order.db_status = SystemOrderStatus.订单失效; + //} + break; + case WeipinhuiOrderSubStatusName.维权中: + { + //if (db_order.afterSaleChangedGoodsCount != 0 && db_order.afterSaleStatus == WeipinhuiAfterSaleStatus.售后中 && db_order.afterSaleType == WeipinhuiSfterSaleType.退货) + if (db_order.afterSaleStatus == WeipinhuiAfterSaleStatus.售后中 && db_order.afterSaleType == WeipinhuiSfterSaleType.退货) + { + if (db_order.afterSaleChangedGoodsCount != 0) + db_order.db_status = SystemOrderStatus.订单维权中; + else + db_order.db_status = SystemOrderStatus.订单失效; + + //db_order.db_status = (old_status == SystemOrderStatus.订单结算) ? SystemOrderStatus.全额退款 : SystemOrderStatus.订单失效; + #region 全额维权,扣除账户金额 + //if (member != null && old_status == SystemOrderStatus.订单结算 && db_order.db_status == SystemOrderStatus.全额退款)//扣除积分 + if (member != null && old_status == SystemOrderStatus.订单结算)//扣除积分 + { + if (db_order.db_endtime != DateTime.MinValue && db_order.db_endtime <= DateTime.Now) + { + IsContainYourself = new OrderHelper().DeductWeipinhuiOrderPoint(notice, db_order); + } + //else + //{ + // db_order.db_status = SystemOrderStatus.订单失效; + //} + } + #endregion + } + else if (db_order.afterSaleChangedGoodsCount == 0 && db_order.afterSaleStatus == WeipinhuiAfterSaleStatus.售后完成 && db_order.afterSaleType == WeipinhuiSfterSaleType.退货) + { + if (db_order.db_status == SystemOrderStatus.订单结算) + { + IsContainYourself = new OrderHelper().DeductWeipinhuiOrderPoint(notice, db_order); + db_order.db_status = SystemOrderStatus.全额退款; + } + else + { + db_order.db_status = SystemOrderStatus.订单失效; + } + } + } + break; + //db_order.db_status = SystemOrderStatus.订单创建; + //break; + default: + db_order.db_status = SystemOrderStatus.订单未知; + break; + } + + #region 通知客户订单付款/失效 提示上级 + if (member != null && (db_order.db_status == SystemOrderStatus.订单付款 || db_order.db_status == SystemOrderStatus.订单失效)) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + List ids = new List(); + ids.Add(member.id); + + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + //一级用户对象 + var member_one = session.FindMemberInfoById(member.inviter_id); + if (member_one != null) + { + ids.Add(member_one.id); + if (notice != null) + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, member_one, db_order, OrderNoticeType.一级提成) { Customer = member }); + if (point.AwardTwo > 0 && member_one.inviter_id != 0 && !ids.Contains(member_one.inviter_id)) + { + //二级用户对象 + var member_two = session.FindMemberInfoById(member_one.inviter_id); + if (member_two != null) + { + ids.Add(member_two.id); + if (notice != null && member_two != null) + { + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, member_two, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && member_two.inviter_id != 0 && !ids.Contains(member_two.inviter_id)) + { + //三级用户对象 + var member_three = session.FindMemberInfoById(member_two.inviter_id); + if (member_three != null) + { + ids.Add(member_three.id); + if (notice != null && member_three != null) + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, member_three, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var member_create = session.FindMemberInfoById(create.mid); + if (notice != null && member_create != null) notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, member_create, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + #endregion + if (old_status != db_order.db_status) + db_order.db_status_time = HttpExtend.GetTimeStamp(); + + session.SaveOrUpdate(db_order); + if (db_order.db_status == SystemOrderStatus.订单付款) + { + #region 判断用户是否符合获得新人奖励 + isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + #endregion + } + + if (notice != null && (isFrontData || old_status != db_order.db_status) && !IsContainYourself) + notice.Add(new Events.OrderNoticeEvent(CpsType.唯品联盟, member, db_order, OrderNoticeType.客户订单) { IsRewards = isFirstOrder }); + } + catch (Exception ex) + { + EventClient.OnEvent(this, "更新唯品会订单错误:" + db_order.orderSn + "," + ex.Message); + } + } + + /// + /// 同步订单 + /// + /// 唯品会cps对象集合 + /// 开始时间 + /// 结束时间 + private void UpdateOrder(fl_cps_member[] members, DateTime start_time, DateTime end_time) + { + if (members == null || members.Length == 0) return; + int row_count = 50;//间隔 + //var timespan = end_time - start_time; + //var forcount = 1; + //if (timespan.TotalHours > 1.00) + //{ + // forcount = (int)(timespan.TotalHours / 1); + // if (timespan.TotalHours % 1 > 0) forcount++; + //}; + var timespan = end_time - start_time; + TaskTool task = new TaskTool(); + List notices = new List(); + var not_download_pids = ApiClient.Setting.SystemConfig.order_weipinhui_not_download_pid.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + foreach (var item in members) + { + var _item = item; + if (!_item.is_valid) continue; + var client = new WeipinhuiApi(_item); + task.AddTask(delegate + { + try + { + var _star = timespan.TotalHours > 1 ? end_time : start_time;//倒叙1小时一个间断 + var _end = end_time; + do + { + if (timespan.TotalHours > 1) + { + _end = _star; + _star = _star.AddHours(-0.99); + } + + + var orr = client.DownOrder(_star, _end, 1, row_count); + + if (orr == null || orr.result.total == 0) + { + if (client.Member != null && !client.Member.is_valid) + return; + + Thread.Sleep(500); + continue; + } + + Exception _exception = null; + int count = orr.result.total / row_count; + if (orr.result.total % row_count != 0) count++; + for (int i = 1; i <= count; i++) + { + var page = i; + if (_exception != null) return; + try + { + //下载 + if (page != 1) + { + orr = client.DownOrder(_star, _end, page, row_count); + + if (orr == null) + { + if (client.Member != null && !client.Member.is_valid) + return; + } + } + + if (orr != null && orr.result.orderInfoList != null && orr.result.orderInfoList.Count > 0) + { + int _count = 1; + foreach (var order in orr.result.orderInfoList) + { + _count++; + + var session = ApiClient.GetSession(); + try + { + ////订单号搜索 + //if (order.orderSn == "22051870142932") + //{ + //} + + //if (order.orderSn == "22031844797946") + //{ + //} + + //if (order.orderSn == "22012680610572") + //{ + //} + + #region 不处理的PID + if (ApiClient.Setting.SystemConfig.order_weipinhui_download_set_pids == SwitchType.关闭) + { + if (not_download_pids.Count != 0) + { + var isExist = not_download_pids.Contains(order.pid);//是否包含 + //continue; + if (ApiClient.Setting.SystemConfig.order_weipinhui_down_type == DownAdzoneType.不下载推广位 && isExist) + continue; + else if (ApiClient.Setting.SystemConfig.order_weipinhui_down_type == DownAdzoneType.只下载推广位 && !isExist) + continue; + } + } + else + { + //var adzone = session.FindAdzoneInfos().Where(f => f.custom_type == "唯品会返利" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.Contains(order.pid)); + + var adzoneList = new List(); + var adzones = session.FindAdzoneInfos(); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "唯品会返利" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.Contains(order.pid))); + adzoneList.AddRange(adzones.Where(f => f.custom_type == "用户私人pid" && f.extend == "唯品会私人pid" && !string.IsNullOrEmpty(f.adzone_pid) && f.adzone_pid.Contains(order.pid))); + if (adzoneList == null || adzoneList.Count() == 0) + { + continue; + } + } + #endregion + + if (ApiClient.Setting.DbConfig.DatabaseType == DatabaseType.SQLITE && _count % 10 == 0) + Thread.Sleep(150); + + //计算订单信息 + //var status = Util.ConvertEnum(order.orderSubStatusName); + + #region 老的 一个订单号 多个订单无法保存 + //var db_order = session.FindSingle("orderSn=@orderSn", new { orderSn = order.orderSn, }); + //if (db_order != null) //跳过相同状态 + //{ + // //var statusTemp = (WeipinhuiOrderSubStatusName)Enum.Parse(typeof(WeipinhuiOrderSubStatusName), db_order.orderSubStatusName); + + // if (status == db_order.orderSubStatusName || + // (status == WeipinhuiOrderSubStatusName.已签收 || status == WeipinhuiOrderSubStatusName.已结算 || status == WeipinhuiOrderSubStatusName.已下单) && (db_order.orderSubStatusName == WeipinhuiOrderSubStatusName.已签收 || status == WeipinhuiOrderSubStatusName.已结算 || status == WeipinhuiOrderSubStatusName.已下单)) + // { + // if (db_order.IsFinish()) continue;//是否已经完成 + // if (db_order.db_status == SystemOrderStatus.订单冻结 && db_order.db_endtime > DateTime.Now) continue;//跳过系统冻结 + // if (db_order.orderSubStatusName != WeipinhuiOrderSubStatusName.已签收 && db_order.orderSubStatusName == status) continue;//跳过相同状态 + // } + // db_order.orderSubStatusName = status; + + // if (db_order.goodsFinalPrice == 0 || db_order.commissionTotalCost == 0 || db_order.commission == 0) + // { + // var orderTmps = new WPHHelper().OrderInfoListConvertDbWeipinhuiOrder(order, null); + // if (orderTmps == null || orderTmps.Count == 0) + // { + // EventClient.OnEvent("", ""); + // return; + // } + // else if (orderTmps.Count > 1) + // EventClient.OnEvent("下载订单多个订单明细.", $"订单号码:{order.orderSn},订单下单时间:{Util.GetDateTime(order.orderTime).ToString("yyyy-MM-dd HH:mm:ss")},唯品会联盟账号:{client.Member.usernick}({client.Member.username})"); + + // var temp = orderTmps[0]; + + // db_order.commission = temp.commission; + // db_order.commissionTotalCost = temp.commissionTotalCost; + // db_order.goodsFinalPrice = temp.goodsFinalPrice; + // } + //} + //else + //{ + // var orderTmps = new WPHHelper().OrderInfoListConvertDbWeipinhuiOrder(order, null); + // if (orderTmps == null || orderTmps.Count == 0) + // { + // EventClient.OnEvent("", ""); + // return; + // } + // else if (orderTmps.Count > 1) + // EventClient.OnEvent("下载订单多个订单明细.", $"订单号码:{order.orderSn},订单下单时间:{Util.GetDateTime(order.orderTime).ToString("yyyy-MM-dd HH:mm:ss")},唯品会联盟账号:{client.Member.usernick}({client.Member.username})"); + + // db_order = orderTmps[0]; + // db_order.db_cpsname = _item.username; + // db_order.db_cpsnick = _item.usernick; + //} + //UpdateOrder(db_order, session, notices); + #endregion + + #region 新的 + + var orderTmps = new WPHHelper().OrderInfoListConvertDbWeipinhuiOrder(order, null); + if (orderTmps == null || orderTmps.Count == 0) + return; + foreach (var orderTmp in orderTmps) + { + var status = orderTmp.orderSubStatusName; + + var db_order = session.FindSingle("orderSn=@orderSn and goodsId=@goodsId and sizeId=@sizeId", new { orderSn = order.orderSn, goodsId = orderTmp.goodsId, sizeId = orderTmp.sizeId }); + if (db_order != null) //跳过相同状态 + { + if (db_order.orderSubStatusName == WeipinhuiOrderSubStatusName.手动失效) + { + continue; + } + if (status == db_order.orderSubStatusName || (status == WeipinhuiOrderSubStatusName.已签收 || status == WeipinhuiOrderSubStatusName.待结算 || status == WeipinhuiOrderSubStatusName.已结算 || status == WeipinhuiOrderSubStatusName.维权完成) && (db_order.orderSubStatusName == WeipinhuiOrderSubStatusName.已签收 || status == WeipinhuiOrderSubStatusName.已结算 || status == WeipinhuiOrderSubStatusName.待结算 || status == WeipinhuiOrderSubStatusName.维权完成)) + { + if (db_order.IsFinish()) continue;//是否已经完成 + if (db_order.db_status == SystemOrderStatus.订单冻结 && db_order.db_endtime > DateTime.Now) continue;//跳过系统冻结 + if (db_order.orderSubStatusName != WeipinhuiOrderSubStatusName.已签收 && db_order.orderSubStatusName == status) continue;//跳过相同状态 + } + + + db_order.orderSubStatusName = status; + + db_order.afterSaleChangedCommission = orderTmp.afterSaleChangedCommission;//商品佣金售后变动:仅在订单完结之后发生售后时返回,无售后时为空 + + db_order.afterSaleChangedGoodsCount = orderTmp.afterSaleChangedGoodsCount;//商品数量售后变动:仅在订单完结之后发生售后时返回,无售后时为空 + db_order.afterSaleSn = orderTmp.afterSaleSn;//商品售后单号,无售后时为空 + db_order.afterSaleStatus = orderTmp.afterSaleStatus;//商品售后状态:1-售后中,2-售后完成,3-售后取消,无售后时为空 WeipinhuiAfterSaleStatus + db_order.afterSaleType = orderTmp.afterSaleType;//售后类型:1-退货,2-换货,无售后时为空 WeipinhuiSfterSaleType + db_order.afterSaleFinishTime = orderTmp.afterSaleFinishTime;//售后完成时间,时间戳,单位:毫秒,无售后时为空 + + if (db_order.goodsFinalPrice == 0 || db_order.commissionTotalCost == 0 || db_order.commission == 0) + { + db_order.commission = orderTmp.commission; + db_order.commissionTotalCost = orderTmp.commissionTotalCost; + db_order.goodsFinalPrice = orderTmp.goodsFinalPrice; + } + } + else + { + db_order = orderTmp; + db_order.db_cpsname = _item.username; + db_order.db_cpsnick = _item.usernick; + } + try + { + LogHelper.GetSingleObj().Debug("唯品会订单: ", $"{HttpHelper.ObjectToJson(orr)}"); + } + catch (Exception) + { } + + UpdateOrder(db_order, session, notices); + } + #endregion + } + catch (Exception ex) + { + throw ex; + } + finally + { + //session.Close(); + } + } + } + } + catch (Exception ex) + { + _exception = ex; return; + } + } + if (_exception != null) throw _exception; + + //_star = _star.AddHours(-23.99); + } while (_star > start_time); + } + catch (Exception ex) + { + return; + } + }); + } + task.Start(1, null); + + if (string.IsNullOrEmpty(order_id)) + { + var session = ApiClient.GetSession(); + var end_orders = session.Find("select * from fl_order_weipinhui where db_status=@db_status and db_endtime<@db_endtime", new { db_status = (int)SystemOrderStatus.订单冻结, db_endtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }).ToList(); + foreach (var db_order in end_orders) + { + UpdateOrder(db_order, session, notices); + } + } + + if (notices.Count != 0) + { + var tasks = TimerTask.GetTimer() as Update_NoticeQueue; + foreach (var item in notices) + { + if (item.Member == null) continue; + var order = item.Order as fl_order_weipinhui; + if (order.orderSn == order_id) continue; + tasks.Add(item); + } + } + + } + } +} diff --git a/类库/Api.Framework/Timers/UpdateTaobaoOrder.cs b/类库/Api.Framework/Timers/UpdateTaobaoOrder.cs new file mode 100644 index 0000000..5995e49 --- /dev/null +++ b/类库/Api.Framework/Timers/UpdateTaobaoOrder.cs @@ -0,0 +1,28 @@ +using Api.Framework.Enums; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Timers +{ + class UpdateTaobaoOrder + { + /// + /// 最后一次更新时间 + /// + private DateTime LastTime; + public void UpdateOrder() + { + //有效账户 + var Taobaos = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈 && f.is_download == SwitchType.开启 && f.logintime.AddDays(30).AddHours(-5) >= DateTime.Now).ToArray(); + + foreach (var item in Taobaos) + { + + } + + } + } +} diff --git a/类库/Api.Framework/Timers/Update_AlimamaOrders.cs b/类库/Api.Framework/Timers/Update_AlimamaOrders.cs new file mode 100644 index 0000000..7b6f89e --- /dev/null +++ b/类库/Api.Framework/Timers/Update_AlimamaOrders.cs @@ -0,0 +1,308 @@ +using Api.Framework.Model; +using Cps.Framework; +using Cps.Framework.Tb; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using CsharpHttpHelper; +using Easy4net.Context; +using System.Text.RegularExpressions; +using Api.Framework.Enums; +using Api.Framework.Tools; +using System.Data; +using Api.Framework.Events; +using Cps.Framework.Entitys; +using Api.Framework.Utils; + +namespace Api.Framework.Threading +{ + class Update_AlimamaOrders : IThread + { + public bool IsRunning { get; set; } + public RegisteredWaitHandle RegisterdHandler { get; set; } + public WaitHandle WaitHandler { get; set; } + + public void Dispose() + { + + } + + + + + public void Run(object time, bool timeout) + { + if (this.IsRunning) return; + + + + } + + private void UpdateOrder(fl_order_pinduoduo db_order, Session session, List notice) + { + this.IsRunning = true; + DateTime stt_time = DateTime.Now.AddDays(-30); + DateTime end_time = DateTime.Now; + var spa_time = end_time - stt_time; + int row_count = 20; + int count = (int)spa_time.TotalMinutes / row_count; if (spa_time.TotalMinutes % row_count != 0) count++; + int sum_order = 0; + TaskTool task = new TaskTool(); + //var session = ApiClient.GetSession();//获得一个Session + int thread_count = 6000; + try + { + session.BeginTransaction(); + List noticeEvents = new List(); + foreach (var item in CPSClient.AlimamaUsers) + { + if (item.IsLoginApi) + { + bool is_run = true; + for (int i = 1; i <= count; i++) + { + //临时时间 + var _time = end_time.AddMinutes(-(i * row_count)); + task.AddTask(delegate + { + try + { + HttpHelper http = new HttpHelper(); + int page = 1; + do + { + if (!is_run) return; + var url = item.GetAlimamaorderURL(_time, page, ApiDownorderType.订单结算, ApiDownorderSort.结算时间);//获得下载URL + Dictionary dic = null; + int number = 0; + Next: + try + { + number++; + var _item = http.GetItem(url); + var _html = http.GetHtml(_item).Html; + dic = HttpExtend.JsonToDictionary(_html); + if (dic == null) throw new Exception(_html); + if (dic.ContainsKey("error_response")) throw new Exception(_html); + dic = dic["tbk_sc_order_get_response"] as Dictionary; + dic = dic["results"] as Dictionary; + if (dic == null || dic.Count == 0) return; + } + catch (Exception ex) + { + if (number <= 20 && Regex.Match(ex.Message, @"(""error_response"":{""code"":15,""msg"":""Remote service error"",""sub_code"":""0"")|(无法连接)|(操作超时)|(基础连接已经关闭)|(远程服务调用超时)|(淘宝客API服务不可用)|(HSF执行错误)").Success) + { + Thread.Sleep(2000); + goto Next; + } + else + { + IsRunning = false; + Console.WriteLine("下载订单异常:" + ex.Message + ex.StackTrace); + throw ex; + } + } + + + + + var list = dic["n_tbk_order"] as ArrayList; + foreach (Dictionary order in list) + { + try + { + var status = int.Parse(order["tk_status"].ToString()); + var db_order = session.Find("trade_id=@trade_id and trade_parent_id=@trade_parent_id", new { trade_id = order["trade_id"].ToString(), trade_parent_id = order["trade_parent_id"].ToString() }).FirstOrDefault(); + if (db_order != null) //跳过相同状态 + { + if (db_order.IsFinish()) continue;//是否完成 + if (db_order.db_status == status) continue;//跳过相同状态 + } + + //自动填充实例 + if (db_order == null) db_order = order.ConvertToObj(); + else + { + db_order.tk_status = status; + } + + sum_order++; + + //查询是否绑定 + if (db_order.db_userid == 0) + { + var bind = session.FindBindCache(db_order.trade_parent_id); + if (bind != null) + { + db_order.db_userid = bind.db_userid;//根据绑定记录识别 + db_order.msg_robotid = bind.db_robotid; + db_order.msg_groupid = bind.groupid; + } + + } + + //自动识别绑定 + if (db_order.db_userid == 0) + { + var query = session.FindTable("select userid,count(*) count from fl_query_hist itemid=@itemid and crt_time>@time group userid ", new { itemid = db_order.item_num, time = DateTime.Now.AddMinutes(-24).ToString("yyyy-MM-dd HH:mm:ss") }); + if (query.Rows.Count > 0) + { + if (query.Rows.Count == 1) db_order.db_userid = long.Parse(query.Rows[0]["userid"].ToString());//根据查询记录认领 + else + { + var end_number = db_order.trade_parent_id.Substring(db_order.trade_parent_id.Length - 6); + var lasts = session.Find("number=@number", new { number = end_number }); + if (lasts.Count > 0) + { + //是否存在、尾号相同,并且查询过宝贝(优先识别) + Dictionary last_num = new Dictionary(); + foreach (DataRow q in query.Rows) + { + var info = lasts.FirstOrDefault(f => f.userid == long.Parse(q["userid"].ToString())); + if (info != null) last_num[info.userid] = info; + } + + if (last_num.Count == 1) + { + var last_item = last_num.FirstOrDefault().Value; + db_order.db_userid = last_item.userid; + var query_item = session.Find("itemid=@itemid and userid=@userid", new { itemid = db_order.item_num, userid = db_order.db_userid }).FirstOrDefault(); + if (query_item != null) + { + db_order.msg_robotid = query_item.robotid; + db_order.msg_groupid = query_item.groupid; + } + } + else + { + //尾号相同、并且均查询过该宝贝 + } + } + else + { + //未找到尾号相同订单 + } + } + } + } + + + var member = db_order.db_userid != 0 ? session.Find("id=@id", new { id = db_order.db_userid }).FirstOrDefault() : null; + if (string.IsNullOrEmpty(db_order.db_point)) + { + var itempoint = session.FindItemPoint(member, db_order.total_commission_fee, CpsType.淘宝); + if (itempoint != null) db_order.db_point = HttpHelper.ObjectToJson(itempoint); + } + + switch (status) + { + case (int)ApiDownorderType.订单结算: + { + db_order.db_status = (int)OrderStatus.订单完结; + if (!string.IsNullOrEmpty(db_order.db_point) && member != null) + { + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point != null) + { + //用户自身加积分 + session.ChangePoint(PointType.消费补贴, point.UserPoint, member.id, $"购买:{db_order.item_title}({db_order.trade_parent_id})"); + noticeEvents.Add(new OrderNoticeEvent(CpsType.淘宝, member, db_order)); + //多级提成计算 + if (point.AwardOne > 0 && member.inviter_id > 0) + { + var flag = session.ChangePoint(PointType.提成奖励, point.AwardOne, member.inviter_id, $"{member.nick_name},淘宝购物1级提成!"); + if (flag != null) + { + noticeEvents.Add(new OrderNoticeEvent(CpsType.淘宝, flag, db_order)); + + if (point.AwardTwo > 0 && flag.inviter_id != 0) + { + flag = session.ChangePoint(PointType.提成奖励, point.AwardOne, flag.inviter_id, $"{member.nick_name},淘宝购物2级提成!"); + if (flag != null) noticeEvents.Add(new OrderNoticeEvent(CpsType.淘宝, flag, db_order)); + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && string.IsNullOrEmpty(db_order.msg_groupid) && db_order.db_robotid != 0) + { + var robot = session.FindRobotInfo(db_order.db_robotid); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, robot.GetRobotType()); + if (create != null) + { + var flag = session.ChangePoint(PointType.提成奖励, create.userid, create.userid, $"{member.nick_name},维护提成!"); + if (flag != null) noticeEvents.Add(new OrderNoticeEvent(CpsType.淘宝, flag, db_order)); + } + } + + + } + + } + + + } + break; + } + case (int)ApiDownorderType.订单付款: + db_order.db_status = (int)OrderStatus.订单付款; + break; + case (int)ApiDownorderType.订单失效: + db_order.db_status = (int)OrderStatus.订单失效; + break; + case (int)ApiDownorderType.订单成功: + db_order.db_status = (int)OrderStatus.商家未结算; + break; + } + + if (db_order.id == 0) session.Insert(db_order);//订单逻辑处理 + else session.Update(db_order); + + if (member != null) ApiClient.GetThread().Add(new Events.OrderNoticeEvent(CpsType.淘宝, member, db_order)); + } + catch (Exception ex) + { + Console.WriteLine(string.Format("更新AlimamaOrder:{0}{1}异常:{2}", order["trade_parent_id"].ToString(), order["trade_id"].ToString(), ex.Message)); + } + } + + if (list == null || list.Count < 100) break; + page++; + } + while (true); + } + catch (Exception ex) + { + Console.WriteLine("下载订单异常:" + ex.Message + ex.StackTrace); + } + }); + } + + + + } + } + + task.Start(thread_count, null); + int s = (int)(DateTime.Now - end_time).TotalSeconds; + session.Commit(); + if (noticeEvents.Count > 0) ApiClient.GetThread().Add(noticeEvents); + + Console.WriteLine(string.Format("同步历史:{4}天、耗时:{0}秒、允许最大并行:{1}、任务总数:{2}、平均每秒更新:{3}/个订单", s, thread_count, task.Tasks.Count, sum_order / s, (int)spa_time.TotalDays)); + } + catch (Exception) + { + session.Rollback(); + } + Console.WriteLine(); + } + } +} diff --git a/类库/Api.Framework/Timers/Update_CpsStatus.cs b/类库/Api.Framework/Timers/Update_CpsStatus.cs new file mode 100644 index 0000000..cd22608 --- /dev/null +++ b/类库/Api.Framework/Timers/Update_CpsStatus.cs @@ -0,0 +1,74 @@ +using Api.Framework.Enums; +using Api.Framework.SDK; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Timers +{ + /// + /// 定时更新阿里和拼多多授权信息 + /// + class Update_CpsStatus : TimerTask + { + public long count = 0; + public override void Run(object state, bool timeout) + { + count++; + //更新多多进宝状态 + if (count == 0 || count % 24 == 0) + { + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.多多进宝); + foreach (var item in members) + { + var api = CpsClient.CreatePinduoduoRequest(item); + api.RefreshStatus(); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"ERROR-:{this.GetType()}-{System.Reflection.MethodBase.GetCurrentMethod().Name}->Pdd->{ex.Message}"); + } + } + + //判断阿里妈妈状态 + try + { + var members = CpsClient.Members.Where(f => f.cpstype == CpsType.阿里妈妈).ToList(); + foreach (var _item in members) + { + var item = _item; + Task.Run(() => + { + try + { + var session = ApiClient.GetSession(); + var api = CpsClient.CreateAlimamaRequest(item); + if (item.online) + { + api.UpdateCookies(); + item = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈 && f.username == item.username); + item.online = api.CheckLoginAlimama(); + } + api.RefToken(); + session.Saveable(item).ExecuteCommand(); + } + catch (Exception ex) + { } + }); + Thread.Sleep(50); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"ERROR:{this.GetType()}-{System.Reflection.MethodBase.GetCurrentMethod().Name}- >TB->{ex.Message}"); + } + } + } +} diff --git a/类库/Api.Framework/Timers/Update_NoticeQueue.cs b/类库/Api.Framework/Timers/Update_NoticeQueue.cs new file mode 100644 index 0000000..2c718a2 --- /dev/null +++ b/类库/Api.Framework/Timers/Update_NoticeQueue.cs @@ -0,0 +1,60 @@ +using Api.Framework.Events; +using Api.Framework.SDK; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Timers +{ + /// + /// 更新同时队列定时器 + /// + public class Update_NoticeQueue : TimerTask + { + + private Queue queue = Queue.Synchronized(new Queue()); + public void Add(OrderNoticeEvent e) + { + queue.Enqueue(e); + } + + public void Add(List e) + { + queue.Enqueue(e.ToArray()); + } + + private object GetData() + { + try + { + return queue.Dequeue(); + } + catch (Exception) + { + + + } + return null; + } + + public override void Run(object state, bool timeout) + { + if (queue.Count > 0) + { + var v = GetData(); + while (v!=null) + { + EventClient.OnEvent(this, v); + Thread.Sleep(10); + //Thread.Sleep(ApiClient.Setting.SystemConfig.timer_send_interval); + v = GetData(); + } + } + + } + } +} diff --git a/类库/Api.Framework/Tools/AesHelper.cs b/类库/Api.Framework/Tools/AesHelper.cs new file mode 100644 index 0000000..22ee0f4 --- /dev/null +++ b/类库/Api.Framework/Tools/AesHelper.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + public class AesHelper + { + /// + /// 有密码的AES加密 + /// + /// 加密字符 + /// 加密的密码 + /// + public static string Encrypt(string toEncrypt, string key) + { + if (key.Length > 32) + { + key = key.Substring(0, 32); + } + try + { + byte[] keyArray = Encoding.UTF8.GetBytes(key); + byte[] toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt); + RijndaelManaged rDel = new RijndaelManaged(); + rDel.Key = keyArray; + rDel.Mode = CipherMode.ECB; + rDel.Padding = PaddingMode.PKCS7; + ICryptoTransform cTransform = rDel.CreateEncryptor(); + byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); + return ByteArrayToHexString(resultArray); + } + catch (Exception) + { + return ""; + } + } + + /// + /// AES解密 + /// + /// + /// + /// + public static string Decrypt(string toDecrypt, string key) + { + if (key.Length > 32) + { + key = key.Substring(0, 32); + } + byte[] keyArray = Encoding.UTF8.GetBytes(key); + byte[] toEncryptArray = Convert.FromBase64String(toDecrypt); + RijndaelManaged rDel = new RijndaelManaged(); + rDel.Key = keyArray; + rDel.Mode = CipherMode.ECB; + rDel.Padding = PaddingMode.PKCS7; + ICryptoTransform cTransform = rDel.CreateDecryptor(); + byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); + return Encoding.UTF8.GetString(resultArray); + } + /// + /// 将一个byte数组转换成16进制字符串 + /// + /// + /// + public static string ByteArrayToHexString(byte[] data) + { + StringBuilder sb = new StringBuilder(data.Length * 3); + foreach (byte b in data) + { + sb.Append(Convert.ToString(b, 16).PadLeft(2, '0')); + } + return sb.ToString().ToUpper(); + } + /// + /// 将16进制字符串转换成byte数组 + /// + /// + /// + public static byte[] ByteArrayToHexString(string hexString) + { + //将16进制秘钥转成字节数组 + var byteArray = new byte[hexString.Length / 2]; + for (var x = 0; x < byteArray.Length; x++) + { + var i = Convert.ToInt32(hexString.Substring(x * 2, 2), 16); + byteArray[x] = (byte)i; + } + return byteArray; + } + } +} diff --git a/类库/Api.Framework/Tools/CacheTool.cs b/类库/Api.Framework/Tools/CacheTool.cs new file mode 100644 index 0000000..a45f4e7 --- /dev/null +++ b/类库/Api.Framework/Tools/CacheTool.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + + /// + /// 自定义内存缓存助手 + /// + public sealed class CacheTool + { + #region 单例模式 + //创建私有化静态obj锁 + private static readonly object _ObjLock = new object(); + //创建私有静态字段,接收类的实例化对象 + private static volatile CacheTool _CacheTool = null; + //构造函数私有化 + private CacheTool() { } + //创建单利对象资源并返回 + public static CacheTool GetSingleObj() + { + if (_CacheTool == null) + { + lock (_ObjLock) + { + if (_CacheTool == null) + _CacheTool = new CacheTool(); + } + } + return _CacheTool; + } + #endregion + + /// + /// 缓存字典 => 【key|value|time】 + /// + private static volatile ConcurrentDictionary> _CacheDictionary = new ConcurrentDictionary>(); + + + /// + /// 1.主动过期 + /// + static CacheTool() + { + Task.Run(() => + { + while (true) + { + Thread.Sleep(1000 * 60); //1分钟检查一次 + if (_CacheDictionary != null && _CacheDictionary.Keys.Count > 0) + { + var listKey = new List(); + foreach (var key in _CacheDictionary.Keys) + { + listKey.Add(key); + } + foreach (var key in listKey) + { + var valueTime = _CacheDictionary[key]; + if (valueTime.Value < DateTime.Now) + _CacheDictionary.TryRemove(key, out KeyValuePair value); + } + } + } + }); + } + + /// + /// 索引器 + /// + /// + /// + public object this[string key] + { + get => _CacheDictionary[key]; + set => _CacheDictionary[key] = new KeyValuePair(value, null); + } + + /// + /// 设置相对过期缓存 + /// + /// 键 + /// 数据包 + /// 相对过期时间 + public void Set(string key, object data, int minute = 10) + { + // var v = string.Empty; + // if (data.GetType() != typeof(String)) + // { + //v = CsharpHttpHelper.HttpHelper.ObjectToJson(); + // } + _CacheDictionary[key] = new KeyValuePair(data, DateTime.Now.AddMinutes(minute)); + } + + ///// + ///// 设置绝对过期缓存 + ///// + ///// 键< + ///// 数据包 + //public void Set(string key, object data) + //{ + // this[key] = data; //_CacheDictionary[key] = new KeyValuePair(data, null); + //} + + /// + /// 通过key获取缓存value + /// 2.被动过期 + /// + /// + /// + /// + public T Get(string key) + { + if (Exist(key)) + { + var valueTime = _CacheDictionary[key]; + return (T)valueTime.Key; //return (T)this[key]; + } + else + { + return default(T); + } + } + + /// + /// 获取缓存个数 + /// + /// + public int Count() + { + int count = 0; + if (_CacheDictionary != null) + count = _CacheDictionary.Count; + return count; + } + + /// + /// 删除指定key的value + /// + /// + public bool Remove(string key) + { + for (int i = 0; i < 5; i++) + { + var flag = _CacheDictionary.TryRemove(key, out KeyValuePair value); + if (!flag) Thread.Sleep(100); + else return true; + } + return false; + } + + /// + /// 清空所有缓存 + /// + public void Cleaner() + { + if (_CacheDictionary != null && _CacheDictionary.Count > 0) + { + foreach (var key in _CacheDictionary.Keys) + { + _CacheDictionary.TryRemove(key, out KeyValuePair value); + } + } + } + + /// + /// 检查key是否存在 + /// 2.被动过期,保证任何过期缓存都无法取值 + /// + /// + /// + public bool Exist(string key) + { + if (string.IsNullOrWhiteSpace(key)) + { + return false; + } + else if (_CacheDictionary.ContainsKey(key)) + { + var valTime = _CacheDictionary[key]; + if (valTime.Value != null && valTime.Value > DateTime.Now) + { + return true; //缓存没过期 + } + else + { + _CacheDictionary.TryRemove(key, out KeyValuePair value); //缓存过期清理 + return false; + } + } + else + { + return false; + } + } + } + +} diff --git a/类库/Api.Framework/Tools/ChatTypeControl.cs b/类库/Api.Framework/Tools/ChatTypeControl.cs new file mode 100644 index 0000000..3b5c03d --- /dev/null +++ b/类库/Api.Framework/Tools/ChatTypeControl.cs @@ -0,0 +1,59 @@ +using Api.Framework.SDK; +using DevExpress.XtraEditors; +using DevExpress.XtraEditors.Controls; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UI.Framework.Entitys; + +namespace Api.Framework.Tools +{ + public class ChatTypeControl : PropertyGridEditStyle + { + public ChatTypeControl() + { + var listBox = new CheckedListBoxControl(); + foreach (ChatType item in Enum.GetValues(typeof(ChatType))) + { + listBox.Items.Add(new CheckedListBoxItem(null, item.ToString())); + } + Control = listBox; + } + + /// + /// 将选着的数据进行展示 + /// + /// + public override string GetValue() + { + var listBox = Control as CheckedListBoxControl; + string[] strs = new string[listBox.CheckedItems.Count]; + int i = 0; + foreach (var item in listBox.CheckedItems) + { + strs[i] = item.ToString(); + i++; + } + return string.Join(",", strs); + } + + /// + /// 将内容在控件里面勾选 + /// + /// + public override void SetValue(object value) + { + var listBox = Control as CheckedListBoxControl; + var strs = value == null ? new string[] { } : value.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); + int i = 0; + foreach (var item in listBox.Items) + { + listBox.SetItemChecked(i, !string.IsNullOrEmpty(strs.FirstOrDefault(f => f == item.ToString()))); + i++; + } + } + + } +} diff --git a/类库/Api.Framework/Tools/CloudApiHelper.cs b/类库/Api.Framework/Tools/CloudApiHelper.cs new file mode 100644 index 0000000..c2bec43 --- /dev/null +++ b/类库/Api.Framework/Tools/CloudApiHelper.cs @@ -0,0 +1,893 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Api.Framework.Utils; +using CsharpHttpHelper; + +namespace Api.Framework.Tools +{ + /// + /// 后端API + /// + public class YZCloudApiHelper + { + public static string ComputerFeature { get; set; } = "WdnHwv"; + + /// + /// host + /// + public static readonly string host = "http://yzinterface.api.52cmg.cn/api/"; + public static readonly string wshost = "ws://yzinterface.api.52cmg.cn/api/"; + //public static readonly string wshost = "ws://127.0.0.1:7000/api/"; + public static readonly int appkey = 334391396; + public static readonly string appsecret = "b924f8b944694cb8891bcfc7834dedb533436a3776de472cbde99577337902b2"; + + + private static T HttpT(string api, string method, object postdata = null) where T : class + { + try + { + var result = HttpResult(api, method, postdata); + if (result.StatusCode == HttpStatusCode.OK) + { + LogHelper.GetSingleObj().Error("同步黑", result.Html); + + return Newtonsoft.Json.JsonConvert.DeserializeObject(result.Html); + } + return null; + } + catch (Exception e) + { + return null; + } + + } + /// + /// http + /// + /// + /// + /// + /// + private static HttpResult HttpResult(string api, string method, object postdata = null) + { + var data = Newtonsoft.Json.JsonConvert.SerializeObject(postdata); + var http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = host + api, + Method = method, + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Server", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = data, + PostEncoding = Encoding.UTF8 + }; + var timespan = GetTimespan(DateTime.Now); + var sign = HttpExtend.GetMD5String(AesHelper.Encrypt(data + appkey + timespan, appsecret)).ToLower(); + item.Header.Add("sign", sign); + item.Header.Add("timestamp", timespan + ""); + item.Header.Add("appkey", appkey + ""); + item.Header.Add("UserToken", ComputerFeature); + var result = http.GetHtml(item); + return result; + } + + public static Int64 GetTimespan(DateTime dateTime) + { + TimeSpan ts = dateTime - new DateTime(1970, 1, 1, 0, 0, 0, 0); + return Convert.ToInt64(ts.TotalSeconds); + } + + /// + /// 生成签名 + /// + /// + /// + /// + public static string CreateSign(string data, long timespan) + { + var sign = HttpExtend.GetMD5String(AesHelper.Encrypt(data + appkey + timespan, appsecret)); + return sign; + } + + + private static ServiceResult Http(string api, string method, object postdata = null) + { + try + { + var result = HttpResult(api, method, postdata); + if (result.StatusCode == HttpStatusCode.OK) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject>(result.Html); + } + return new ServiceResult(default(T)) + { + Ok = false, + Message = result.Html, + }; + } + catch (Exception e) + { + return new ServiceResult(default(T)) + { + Ok = false, + Message = e.ToString(), + }; + } + + } + + private static ServiceResult Http(string api, string method, object postdata = null) + { + try + { + var result = HttpResult(api, method, postdata); + if (result.StatusCode == HttpStatusCode.OK) + { + return Newtonsoft.Json.JsonConvert.DeserializeObject(result.Html); + } + return new ServiceResult() + { + Ok = false, + Data = result.Html, + }; + } + catch (Exception e) + { + return new ServiceResult() + { + Ok = false, + Data = e.ToString(), + }; + } + } + /// + /// 删除黑名单数据 + /// + /// + /// + public static ServiceResult RemoveBlacklist(List inputs) + { + inputs.ForEach(item => + { + if (string.IsNullOrWhiteSpace(item.UserToken)) + { + item.UserToken = ComputerFeature; + } + }); + return Http("UserBlacklist/Remove", "post", inputs); + } + + /// + /// 获取黑名单列表 + /// + /// + /// + public static PageResult1 GetBlacklist(BlacklistSearchPagingInput input) + { + if (string.IsNullOrWhiteSpace(input.UserToken)) + { + input.UserToken = ComputerFeature; + } + return HttpT>("UserBlacklist/GetList", "post", input); + } + /// + /// 获取商品黑名单列表 + /// + /// + /// + public static PageResult1 GetGoodsBlacklist(GoodsBlacklistSearchPagingInput input) + { + if (string.IsNullOrWhiteSpace(input.UserToken)) + { + input.UserToken = ComputerFeature; + } + return HttpT>("GoodsBlacklist/GetList", "post", input); + } + + + /// + /// 获取商店黑名单列表 + /// + /// + /// + public static PageResult1 GetStoreBlacklist(StoreBlacklistSearchPagingInput input) + { + if (string.IsNullOrWhiteSpace(input.UserToken)) + { + input.UserToken = ComputerFeature; + } + return HttpT>("StoreBlacklist/GetList", "post", input); + } + + /// + /// 删除商品黑名单数据 + /// + /// + /// + public static ServiceResult RemoveGoodsBlacklist(List inputs) + { + inputs.ForEach(item => + { + if (string.IsNullOrWhiteSpace(item.UserToken)) + { + item.UserToken = ComputerFeature; + } + }); + return Http("GoodsBlacklist/Remove", "post", inputs); + } + /// + /// 删除商品黑名单数据 + /// + /// + /// + public static ServiceResult RemoveStoreBlacklist(List inputs) + { + inputs.ForEach(item => + { + if (string.IsNullOrWhiteSpace(item.UserToken)) + { + item.UserToken = ComputerFeature; + } + }); + return Http("StoreBlacklist/Remove", "post", inputs); + } + /// + /// 新增用户黑名单 + /// + /// + /// + public static ServiceResult AddUserBlacklist(List inputs) + { + inputs.ForEach(item => + { + if (string.IsNullOrWhiteSpace(item.UserToken)) + { + item.UserToken = ComputerFeature; + } + }); + return Http("UserBlacklist/Add", "post", inputs); + } + + /// + /// 新增商品黑名单 + /// + /// + /// + public static ServiceResult AddGoodsBlacklist(List inputs) + { + inputs.ForEach(item => + { + if (string.IsNullOrWhiteSpace(item.UserToken)) + { + item.UserToken = ComputerFeature; + } + }); + return Http("GoodsBlacklist/Add", "post", inputs); + } + + /// + /// 新增商店黑名单 + /// + /// + /// + public static ServiceResult AddStoreBlacklist(List inputs) + { + inputs.ForEach(item => + { + if (string.IsNullOrWhiteSpace(item.UserToken)) + { + item.UserToken = ComputerFeature; + } + }); + return Http("StoreBlacklist/Add", "post", inputs); + } + /// + /// 设置全局配置 + /// + /// + /// + public static ServiceResult SetGlobalConfig(Dictionary dic) + { + return Http("GlobalConfig/Set", "post", dic); + } + /// + /// 获取全局配置 + /// + /// + /// + public static ServiceResult> GetGlobalConfig(params string[] keys) + { + var res = Http>("GlobalConfig/Get", "post", keys); + if (res.Ok) + { + foreach (var key in keys) + { + if (!res.Data.ContainsKey(key)) + { + res.Data[key] = ""; + } + } + } + return res; + } + } + /// + /// 设置商店 + /// + public class SetStoerBlacklistInput + { + /// + /// 平台 + /// + [Required] + [DisplayName("平台")] + public string Platform { get; set; } + /// + /// 商店名称 + /// + [DisplayName("商店名称")] + public string StoreName { get; set; } + /// + /// 商店ID + /// + public string StoreId { get; set; } + /// + /// 备注 + /// + [DisplayName("备注")] + public string Remark { get; set; } = string.Empty; + /// + /// 新增时间 + /// + [Required] + [DisplayName("新增时间")] + public DateTime AddDateTime { get; set; } + /// + /// 用户Token标示 + /// + [DisplayName("用户关联特征码")] + public string UserToken { get; set; } + } + /// + /// 设置商品 + /// + public class SetGoodsBlacklistInput + { + /// + /// 平台 + /// + [Required] + [DisplayName("平台")] + public string Platform { get; set; } + /// + /// 商品ID + /// + [Required] + [DisplayName("商品ID")] + public string GoodsId { get; set; } + /// + /// 商店名称 + /// + [DisplayName("商店名称")] + public string StoreName { get; set; } + /// + /// 备注 + /// + [DisplayName("备注")] + public string Remark { get; set; } = string.Empty; + /// + /// 新增时间 + /// + [Required] + [DisplayName("新增时间")] + public DateTime AddDateTime { get; set; } + /// + /// 用户Token标示 + /// + [DisplayName("用户关联特征码")] + public string UserToken { get; set; } + } + /// + /// 新增黑名单 + /// + public class SetBlacklistInput + { + /// + /// 0=微信 1=QQ + /// + public int Type { get; set; } + /// + /// 用户ID + /// + public string UserName { get; set; } + /// + /// 用户昵称 + /// + public string UserNick { get; set; } + /// + /// 分组类型 + /// + public BlacklistGroupType GroupType { get; set; } + /// + /// 头像 + /// + public string Avatar { get; set; } + /// + /// 备注 + /// + public string Remark { get; set; } = string.Empty; + /// + /// 新增时间 + /// + public DateTime AddDateTime { get; set; } + /// + /// 用户Token标示 + /// + public string UserToken { get; set; } + } + /// + /// 删除商店黑名单 + /// + public class RemoveStoreBlacklistInput + { + /// + /// 商店ID + /// + public string StoreId { get; set; } + /// + /// 平台 + /// + [Required] + [DisplayName("平台")] + public string Platform { get; set; } + /// + /// 用户标示 + /// + [Required] + [DisplayName("用户标示")] + public string UserToken { get; set; } + } + /// + /// 删除商品黑名单 + /// + public class RemoveGoodsBlacklistInput + { + /// + /// 商品ID + /// + [Required] + [DisplayName("商品ID")] + public string GoodsId { get; set; } + /// + /// 平台 + /// + [Required] + [DisplayName("平台")] + public string Platform { get; set; } + /// + /// 用户标示 + /// + [Required] + [DisplayName("用户标示")] + public string UserToken { get; set; } + } + /// + /// 审核状态 + /// + public enum AuditStateEmun : int + { + /// + /// 等待审核 + /// + Waiting = 0, + /// + /// 审核成功 + /// + Succee = 1, + /// + /// 审核失败 + /// + Failure = 2, + } + /// + /// 云商品黑名单返回结果 + /// + public class CloudStoreBlacklistResult + { + /// + /// ID + /// + public long Id { get; set; } + /// + /// 平台 + /// + public string Platform { get; set; } + /// + /// 商店ID + /// + public string StoreId { get; set; } + /// + /// 商店名称 + /// + public string StoreName { get; set; } + /// + /// 备注 + /// + public string Remark { get; set; } = string.Empty; + /// + /// 添加时间 + /// + public DateTime AddDateTime { get; set; } + /// + /// 用户Token标示 + /// + public string UserToken { get; set; } + /// + /// 更新时间 + /// + public DateTime UpdateDateTime { get; set; } + /// + /// 是否删除 + /// + public bool IsRemove { get; set; } + } + /// + /// 商店黑名单搜索 + /// + public class StoreBlacklistSearchPagingInput : SearchPagingInput + { + /// + /// 用户Token标示 + /// + public string UserToken { get; set; } + /// + /// 升序还是降序 + /// + public bool IsAsc { get; set; } + /// + /// 更新时间 + /// + public DateTime? UpdateDateTime { get; set; } + /// + /// 审核状态 + /// + public AuditStateEmun? AuditState { get; set; } + } + /// + /// 云商品黑名单返回结果 + /// + public class CloudGoodsBlacklistResult + { + /// + /// ID + /// + public long Id { get; set; } + + /// + /// 商品ID + /// + public string GoodsId { get; set; } + /// + /// 平台 + /// + public string Platform { get; set; } + /// + /// 商店名称 + /// + public string StoreName { get; set; } + /// + /// 备注 + /// + public string Remark { get; set; } = string.Empty; + /// + /// 添加时间 + /// + public DateTime AddDateTime { get; set; } + /// + /// 用户Token标示 + /// + public string UserToken { get; set; } + /// + /// 更新时间 + /// + public DateTime UpdateDateTime { get; set; } + /// + /// 是否删除 + /// + public bool IsRemove { get; set; } + } + /// + /// 商品黑名单搜索 + /// + public class GoodsBlacklistSearchPagingInput : SearchPagingInput + { + /// + /// 用户Token标示 + /// + public string UserToken { get; set; } + /// + /// 升序还是降序 + /// + public bool IsAsc { get; set; } + /// + /// 更新时间 + /// + public DateTime? UpdateDateTime { get; set; } + /// + /// 审核状态 + /// + public AuditStateEmun? AuditState { get; set; } + } + /// + /// 黑名单搜索 + /// + public class BlacklistSearchPagingInput : SearchPagingInput + { + /// + /// 用户Token标示 + /// + [DisplayName("用户关联特征码")] + public string UserToken { get; set; } + /// + /// 升序还是降序 + /// + public bool IsAsc { get; set; } + /// + /// 同步时间 + /// + public DateTime? UpdateDateTime { get; set; } + /// + /// 审核状态 + /// + public AuditStateEmun? AuditState { get; set; } + } + /// + /// 云黑名单返回结果 + /// + public class CloudBlacklistResult + { + /// + /// ID + /// + public long Id { get; set; } + + /// + /// 0=微信 1=QQ + /// + public int Type { get; set; } + /// + /// 用户ID + /// + public string UserName { get; set; } + /// + /// 用户昵称 + /// + public string UserNick { get; set; } + /// + /// 分组类型 + /// + public BlacklistGroupType GroupType { get; set; } + /// + /// 头像 + /// + public string Avatar { get; set; } + + /// + /// 备注 + /// + public string Remark { get; set; } = string.Empty; + /// + /// 添加时间 + /// + public DateTime AddDateTime { get; set; } + /// + /// 更新时间 + /// + public DateTime UpdateDateTime { get; set; } + + /// + /// 用户Token标示 + /// + public string UserToken { get; set; } + /// + /// 是否删除 + /// + public bool IsRemove { get; set; } + } + /// + /// 黑名单分组 + /// + public enum BlacklistGroupType : int + { + /// + /// 未分组 + /// + 未分组 = 0, + /// + /// 薅羊毛党 + /// + 薅羊毛党 = 1, + /// + /// 恶意举报 + /// + 恶意举报 = 2 + } + + /// + /// 删除黑名单 + /// + public class RemoveBlacklistInput + { + /// + /// 用户id + /// + [Required] + [DisplayName("用户id")] + public string Username { get; set; } + /// + /// 用户类型0微信 1QQ + /// + [Required] + [DisplayName("类型")] + public int Type { get; set; } + /// + /// 用户标示 + /// + [Required] + [DisplayName("用户标示")] + public string UserToken { get; set; } + } + /// + /// 统一服务返回结果 + /// + public class ServiceResult + { + /// + /// 请求是否成功 + /// + public bool Ok { get; set; } + /// + /// 数据 + /// + public object Data { get; set; } + /// + /// 错误信息 + /// + public string Message { get; set; } + } + /// + /// 统一返回结果 + /// + /// + public class ServiceResult : ServiceResult + { + /// + /// 初始化 + /// + /// + public ServiceResult(T data) + { + this.Data = data; + } + /// + /// 返回数据 + /// + public new T Data { get; set; } + + } + /// + /// 分页数据 + /// + /// + public class PageResult1 + { + /// + /// 下一页 + /// + public bool IsNext { get; set; } + + /// + /// 上一页 + /// + public bool IsBack { get; set; } + + /// + /// 数据 + /// + public List Datas { get; set; } + + /// + /// 总数量 + /// + public int TotalNumber { get; set; } + + /// + /// 每页显示条数 + /// + public int PageSize { get; set; } + + /// + /// 总页码 + /// + public int PageNumber { get; set; } + + /// + /// 当前页码 + /// + public int PageIndex { get; set; } + + /// + /// + /// + /// + /// + /// + /// + /// + public PageResult1(List Datas, int TotalNumber, int PageSize, int PageIndex) + { + if (PageIndex <= 0 || PageSize <= 0) throw new Exception("Index或PageSize 有问题,请检查"); + if (PageSize > 10000) throw new Exception("每页查询数量,不能超过100"); + + PageNumber = 1; + if (TotalNumber != 0 && PageSize > 0) + { + PageNumber = TotalNumber / PageSize; + if (TotalNumber % PageSize != 0) PageNumber++; + } + this.Datas = Datas; + this.TotalNumber = TotalNumber; + this.PageNumber = PageNumber; + this.PageSize = PageSize; + this.PageIndex = PageIndex; + this.IsBack = PageIndex > 1; + this.IsNext = PageIndex < PageNumber; + } + } + + + + /// + /// 分页输入参数 + /// + public class PagingInput + { + /// + /// 页码 + /// + + public int PageIndex { get; set; } = 1; + + /// + /// 限制条数 + /// + + public int PageSize { get; set; } = 10; + } + + + /// + /// 搜索输入 + /// + public class SearchPagingInput : PagingInput + { + /// + /// 关键字 + /// + public string Keyword { get; set; } + } +} diff --git a/类库/Api.Framework/Tools/CloudBlack.cs b/类库/Api.Framework/Tools/CloudBlack.cs new file mode 100644 index 0000000..1feb456 --- /dev/null +++ b/类库/Api.Framework/Tools/CloudBlack.cs @@ -0,0 +1,131 @@ +using Api.Framework.Model; +using Api.Framework.Utils; +using CsharpHttpHelper; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using Api.Framework.SDK; + +namespace Api.Framework.Tools +{ + /// + /// 云黑命大类 + /// + public class CloudBlack + { + /// + /// 黑名单所属平台类型 + /// + public enum BlackType : int + { + wechat = 0 + } + public class BlackResult + { + public int Code { get; set; } + public object Data { get; set; } + } + + /// + /// 查询用户是否黑名单 + /// + /// 用户对象 + /// + public fl_blackuser QueryBlack(fl_member_info member) + { + return QueryBlack(member.username, member.robot_type); + } + + /// + /// 判断用户是否为黑名单 + /// + /// 用户账号 + /// + public fl_blackuser QueryBlack(string username, ChatType robot_type) + { + if (string.IsNullOrWhiteSpace(username)) + return null; + try + { + var session = ApiClient.GetSession(); + var black = session.FindSingle("select * from fl_blackuser where username = @username and usertype = @usertype", new { username = username, usertype = robot_type }); + if (black != null && black.isdel == false && black.iscloud) + return black; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Debug("检测云黑名单", $"{username} - {robot_type},{ex.Message} - {ex.StackTrace}"); + } + return null; + } + + /// + /// 删除用户黑名单 + /// + /// 用户对象 + /// + public ServiceResult RemoveBlack(fl_member_info member) + { + var res = YZCloudApiHelper.RemoveBlacklist(new List() + { + new RemoveBlacklistInput() + { + Username = member.username, + Type = GetUserType(member.robot_type), + UserToken = HttpUtility.UrlEncode(Grant.Framework.GrantClient.Get().accounts.username, Encoding.UTF8) + } + }); + return res; + } + + /// + /// 插入黑名单 + /// + /// 用户对象 + /// 备注 + /// + public ServiceResult InsertBlack(fl_member_info member, string remark) + { + var res = YZCloudApiHelper.AddUserBlacklist(new List() + { + new SetBlacklistInput() + { + AddDateTime = DateTime.Now, + Avatar = member.headurl, + Remark = remark, + Type = GetUserType(member.robot_type), + UserToken = HttpUtility.UrlEncode(Grant.Framework.GrantClient.Get().accounts.username, Encoding.UTF8), + UserName = member.username, + UserNick =member.usernick + } + }); + if (!res.Ok) + { + //throw new Exception(res.Message); + } + return res; + } + + + private int GetUserType(ChatType userType) + { + switch (userType) + { + case ChatType.微信: + return 0; + case ChatType.企业微信: + return 2; + case ChatType.QQ: + return 1; + default: + return 0; + } + } + + } +} diff --git a/类库/Api.Framework/Tools/DYHelper.cs b/类库/Api.Framework/Tools/DYHelper.cs new file mode 100644 index 0000000..50f4c56 --- /dev/null +++ b/类库/Api.Framework/Tools/DYHelper.cs @@ -0,0 +1,551 @@ +using Api.Framework.Cps; +using Api.Framework.Utils; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; + +namespace Api.Framework.Tools +{ + /// + /// 抖音解析助手 + /// + public class DYHelper + { + /// + /// 获取抖音链接中的商品ID(有问题,用api中的GetDyGoodsID) + /// + /// 包含抖音链接的文本 + /// + public static string GetDyGoodsID(string mess, out string promotion_id, out string title) + { + title = string.Empty; + promotion_id = string.Empty; + + if (string.IsNullOrWhiteSpace(mess) || +Regex.IsMatch(mess, @"\[图片=(.+?)\]") || +Regex.IsMatch(mess, @"\[视频=(.+?)\]") || +Regex.IsMatch(mess, @"\[卡片=(.+?)\]") || +Regex.IsMatch(mess, @"\[公告=(.+?)\]") || +Regex.IsMatch(mess, @"\[语音=(.+?)\]") +) + return string.Empty; + + bool flag = false; + if (mess.Contains("goods_id")) flag = true; + //获取链接的正则表达式 + var _url = HttpExtend.RegexMatchUrl(mess); + + #region 之前的拿不到promotion_id,就先不处理 这种连接: https://haohuo.jinritemai.com/views/product/item2?id=3479881104721353508 + //if (!flag && _url.Success)//有链接的情况 + //{ + // mess = _url.Groups["链接"].Value; + // if (Regex.IsMatch(mess, "http[s]?://haohuo.")) + // { + // if (mess == null || !mess.Contains("?id=")) return string.Empty; + // else flag = true; + // } + // else + // flag = true; + //} + #region 新的 + if (!flag && !string.IsNullOrWhiteSpace(_url))//有链接的情况 + { + mess = _url; + if (Regex.IsMatch(mess, "http[s]?://haohuo.")) + { + if (mess == null || !mess.Contains("?id=")) return string.Empty; + else flag = true; + } + else if (Regex.IsMatch(mess, "http[s]?://www.iesdouyin.", RegexOptions.IgnoreCase)) + { + if (mess == null || mess.ToLower().Contains("object_id=")) + { + var reg = Regex.Match(mess, @"object_id=(?:\d+?)_(?\d+?)_(?\d+?)_(?:\d+?)", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + //https://www.iesdouyin.com/?schema_type=20&object_id=1460607342872671_3508329772335892947_3508329411592229101_0 + promotion_id = reg.Groups["promotion_id"].ToString(); + return reg.Groups["goodid"].ToString(); + } + } + else flag = true; + } + else if (Regex.IsMatch(mess, "http[s]?://v.douyin.com", RegexOptions.IgnoreCase))//链接: https://v.douyin.com/LbN2pka/ + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = mess, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + }; + HttpResult result = http.GetHtml(item); + + mess = result.Html; + flag = true; + } + else + flag = true; + } + #endregion + + #endregion + if (flag) + { + var regUrl = Regex.Match(mess, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|detail.yao.95095.com|laiwang.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com|m.tb.cn)", RegexOptions.IgnoreCase); + if (!regUrl.Success) + { + var messTmp = HttpHelper.URLDecode(HttpHelper.URLDecode(mess)).Replace("&", "&"); + var reg = Regex.Match(messTmp, @"origin_id=\d+_(?\d+)", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (!reg.Success) + reg = Regex.Match(messTmp, @"alkey=\d+?_\d+?_\d+?_(?\d+)_\d+?", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + promotion_id = reg.Groups["promotion_id"].ToString(); + + reg = Regex.Match(messTmp, @"\?id=(?<商品id>\d{4,})", RegexOptions.IgnoreCase); + if (!reg.Success) + reg = Regex.Match(messTmp, @"product_id=(?<商品id>\d+)", RegexOptions.IgnoreCase); + if (!reg.Success) + reg = Regex.Match(messTmp, @"""product_id\\\"":\\\""(?<商品id>\d+)\\\""", RegexOptions.IgnoreCase); + if (!reg.Success) + reg = Regex.Match(messTmp, @"""product_id"":(?<商品id>\d+)", RegexOptions.IgnoreCase); + if (!reg.Success) + reg = Regex.Match(messTmp, @"""product_id"":""(?<商品id>\d+)""", RegexOptions.IgnoreCase); + if (!reg.Success) + reg = Regex.Match(messTmp, @"product_id"":""(?<商品id>\d+)""", RegexOptions.IgnoreCase); + if (!reg.Success) + //reg = Regex.Match(messTmp, @"&id=(?<商品id>\d{4,})", RegexOptions.IgnoreCase); + reg = Regex.Match(messTmp, @"\\\\\\""gid\\\\\\"":(?<商品id>\d{4,}),", RegexOptions.IgnoreCase); + if (!reg.Success) + reg = Regex.Match(messTmp, @"origin_id=\d+?_\d+?_(?<商品id>\d+)", RegexOptions.IgnoreCase); + if (!reg.Success) + reg = Regex.Match(messTmp, @"""search_result_id\\+?"":\\+?""(?<商品id>\d+)", RegexOptions.IgnoreCase); + if (!reg.Success) + reg = Regex.Match(messTmp, @"""pre_product_id\\+?"":\\+?""(?<商品id>\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups["商品id"].ToString(); + + reg = Regex.Match(messTmp, @"object_id=(?:\d+)_(?<推广id>\d+)_(?<商品id>\d+)_(?:\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + { + promotion_id = reg.Groups["推广id"].ToString(); + return reg.Groups["商品id"].ToString(); + } + } + } + else + { + //var regs1 = Regex.Matches(mess, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?"); + var reg = Regex.Match(mess, "([︽#]{2}[A-Za-z0-9]{11,14}[︽#]{2})"); + if (reg.Success) + { + return DouyinApi.AnalysisCmdToGoodsUrl(reg.Groups[1].Value, out promotion_id, out title); + } + } + return string.Empty; + } + + + public static string GetDyGoodsID(string mess, out string promotion_id) + { + promotion_id = string.Empty; + + if (string.IsNullOrWhiteSpace(mess) || +Regex.IsMatch(mess, @"\[图片=(.+?)\]") || +Regex.IsMatch(mess, @"\[视频=(.+?)\]") || +Regex.IsMatch(mess, @"\[卡片=(.+?)\]") || +Regex.IsMatch(mess, @"\[公告=(.+?)\]") || +Regex.IsMatch(mess, @"\[语音=(.+?)\]") +) + return string.Empty; + + bool flag = false; + if (mess.Contains("goods_id")) flag = true; + //获取链接的正则表达式 + var _url = HttpExtend.RegexMatchUrl(mess); + + //之前的拿不到promotion_id,就先不处理 这种连接: https://haohuo.jinritemai.com/views/product/item2?id=3479881104721353508 + #region 新的 + if (!flag && !string.IsNullOrWhiteSpace(_url))//有链接的情况 + { + mess = _url; + if (Regex.IsMatch(mess, "http[s]?://haohuo.", RegexOptions.IgnoreCase)) + { + if (mess == null || !mess.Contains("?id=")) return string.Empty; + else flag = true; + } + else if (Regex.IsMatch(mess, "http[s]?://www.iesdouyin.", RegexOptions.IgnoreCase)) + { + if (mess == null || mess.ToLower().Contains("object_id=")) + { + var reg = Regex.Match(mess, @"object_id=(?:\d+?)_(?\d+?)_(?\d+?)_(?:\d+?)", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + //https://www.iesdouyin.com/?schema_type=20&object_id=1460607342872671_3508329772335892947_3508329411592229101_0 + promotion_id = reg.Groups["promotion_id"].ToString(); + return reg.Groups["goodid"].ToString(); + } + } + else flag = true; + } + else if (Regex.IsMatch(mess, "http[s]?://v.douyin.com", RegexOptions.IgnoreCase))//链接: https://v.douyin.com/LbN2pka/ + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = mess, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "", + }; + HttpResult result = http.GetHtml(item); + + mess = result.Html; + flag = true; + } + else + flag = true; + } + #endregion + + if (flag) + { + var regUrl = Regex.Match(mess, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|detail.yao.95095.com|laiwang.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com|m.tb.cn)", RegexOptions.IgnoreCase); + if (!regUrl.Success) + { + var messTmp = HttpHelper.URLDecode(HttpHelper.URLDecode(mess)).Replace("&", "&"); + var reg = Regex.Match(messTmp, @"origin_id=\d+_(?\d+)", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (!reg.Success) + reg = Regex.Match(messTmp, @"alkey=\d+?_\d+?_\d+?_(?\d+)_\d+?", RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (reg.Success) + { + promotion_id = reg.Groups["promotion_id"].ToString(); + //判断是promotion_id是推广id还是商品id + return promotion_id; + } + //这里可能还有其他的可能 + + else + { + + } + + } + } + else + { + //var regs1 = Regex.Matches(mess, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?"); + var reg = Regex.Match(mess, "([︽#]{2}[A-Za-z0-9]{11,14}[︽#]{2})"); + if (reg.Success) + { + var title = string.Empty; + return DouyinApi.AnalysisCmdToGoodsUrl(reg.Groups[1].Value, out promotion_id, out title); + } + } + return string.Empty; + } + + + + + /// + /// 唤醒app链接 + /// + /// 登录用户id + /// 推广ID + /// 商品ID + /// + public static string DyAppUrl(string uid, string promotion_id, string product_id) + { + //https://www.iesdouyin.com/?schema_type=20&object_id=” + 抖音账号原始id () + “_” + 推广商品id + “_” + 商品id + “_0 + //https://www.iesdouyin.com/?schema_type=20&object_id=1460607342872671_3507936844719500526_3507742501886900674_0 + return $"https://www.iesdouyin.com/?schema_type=20&object_id={uid}_{promotion_id}_{product_id}_0"; + } + + /// + /// 抖音短连接 + /// + /// + /// + public static string ShortDyUrl(string url) + { + for (int i = 0; i < 3; i++) + { + try + { + //{"code":0,"message":"success","now":1640269188,"data":"https://v.douyin.com/8Ntmkfp/"} + var shortUrl = "https://lf.snssdk.com/shorten/?belong=aweme&target=" + HttpHelper.URLEncode(url); + HttpHelper http = new HttpHelper(); + var html = http.GetHtml(shortUrl).Html; + if (!string.IsNullOrWhiteSpace(html)) + { + var jObj = JObject.Parse(html); + if (jObj["code"] != null && ((int)jObj["code"] == 0 || jObj["message"]?.ToString() == "success")) + { + var data = jObj["data"]?.ToString(); + if (data.ToLower().Contains("douyin")) + return data; + } + } + } + catch (Exception ex) + { } + Thread.Sleep(200); + } + return url; + } + + + + + #region 口令算法 + + private static string Md5(string str) + { + MD5 md5 = MD5.Create(); + var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); + // 第五步:把二进制转化为大写的十六进制 + StringBuilder result = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + result.Append(bytes[i].ToString("x2")); + } + return result.ToString(); + } + private static long GetTimeStamp(bool Seconds = true) + { + TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0); + if (Seconds) return Convert.ToInt64(ts.TotalSeconds); + else return Convert.ToInt64(ts.TotalMilliseconds); + } + private static string hex_string(long num) + { + var tmp_string = num.ToString("x2"); + if (tmp_string.Length < 2) + tmp_string = '0' + tmp_string; + return tmp_string; + } + private static int reverse(long num) + { + var tmp_string = hex_string(num); + return Convert.ToInt32(tmp_string.Substring(1) + tmp_string.Substring(0, 1), 16); + } + private static int RIT(long num) + { + var result = ""; + var tmp_string = Convert.ToString(num, 2); ;// bin(num)[2]; + while (tmp_string.Length < 8) + { + tmp_string = "0" + tmp_string; + } + for (int i = 0; i < 8; i++) + { + result = result + tmp_string[7 - i]; + } + return Convert.ToInt32(result, 2); + } + private static Dictionary CreateXg(string url, string data = "", string cookies = "") + { + var gorgon = string.Empty; + gorgon += Md5(url); + if (!string.IsNullOrEmpty(data)) + gorgon += Md5(data); + else + gorgon += "00000000000000000000000000000000"; + + if (!string.IsNullOrEmpty(cookies)) + gorgon += Md5(cookies); + else + gorgon += "00000000000000000000000000000000"; + + gorgon += "00000000000000000000000000000000"; + + return calc_xg(gorgon); + + } + + private static Dictionary calc_xg(string data) + { + var ts = 1646128554;// GetTimeStamp(); + var ts_x = 1646128554000;// GetTimeStamp(true); + var len = 0x14; + var key = new long[] { 0xDF, 0x77, 0xB9, 0x40, 0xb9, 0x9b, 0x84, 0x83, 0xd1, 0xb9, 0xcb, 0xd1, 0xf7, 0xc2, 0xb9, 0x85, 0xc3, 0xd0, + 0xfb, 0xc3}; + var param_list = new List(); + long H = 0; + // for i in range(0, 12, 4): + for (int i = 0; i < 12; i = i + 4) + { + var temp = data.Substring(8 * i, 8);// data[8 * i: 8 * (i + 1)]; + for (int j = 0; j < 4; j++) + { + // int(temp[j * 2:(j + 1) * 2], 16) + var V = temp.Substring(j * 2, 2); + H = Convert.ToInt32(temp.Substring(j * 2, 2), 16); + param_list.Add(H); + } + } + //param_list.extend([0x0, 0x6, 0xB, 0x1C]) + param_list.Add(0x0); + param_list.Add(0x6); + param_list.Add(0xB); + param_list.Add(0x1C); + H = Convert.ToInt32(ts.ToString("x2"), 16); + param_list.Add((H & 0xFF000000) >> 24); + param_list.Add((H & 0x00FF0000) >> 16); + param_list.Add((H & 0x0000FF00) >> 8); + param_list.Add((H & 0x000000FF) >> 0); + var eor_result_list = new List(); + for (int i = 0; i < 20; i++) + { + //eor_result_list.append(A ^ B) + eor_result_list.Add(param_list[i] ^ key[i]); + } + + for (int i = 0; i < 20; i++) + { + var C = reverse(eor_result_list[i]); + var D = eor_result_list[(i + 1) % len]; + var E = C ^ D; + var F = RIT(E); + H = (F ^ 0xFFFFFFFF ^ len) & 0xFF; + eor_result_list[i] = H; + } + + var result = ""; + foreach (var param in eor_result_list) + { + result += hex_string(param); + } + + var xgorgon = "0408b0d30000" + result; + Dictionary XgDatas = new Dictionary(); + XgDatas["X-Gorgon"] = xgorgon; + XgDatas["X-Khronos"] = ts.ToString(); + XgDatas["X-SS-REQ-TICKET"] = ts_x.ToString(); + return XgDatas; + } + private static Dictionary _device_info; + private static Dictionary device_info + { + get + { + if (_device_info == null) + { + _device_info = new Dictionary(); + + _device_info["device_id"] = "655729250010781"; + _device_info["install_id"] = "2590869714905182"; + _device_info["device_id_str"] = "655729250010781"; + _device_info["install_id_str"] = "2590869714905182"; + _device_info["new_user"] = "1"; + _device_info["device_token"] = "AAA45JXIIXBRRAL6BCSHWP2ZFWET2NU65PHNP6EREEYPF2WJ6NMY2TKTAZXV666654U44IRIACWWQKGDEJWZQS7JMB7KTT5MOQ6WEFSOPMATGN6FG2EYRZTG4YQ5A"; + + } + return _device_info; + } + } + + /// + /// 连接转口令 + /// + /// + /// + public static string CreateKouling(string url) + { + //https://haohuo.jinritemai.com/views/product/item2?id=3504966563675637147&origin_type=2002170010&origin_id=1460607342872671_3507916645882543574&alkey=1128_1460607342872671_0_3507916645882543574_011&sec_author_id=MS4wLjABAAAAEnpGkVpQS-WLtu18Me9lZ-9A284xvNbstU-HGyQK3vn2Pi-WtDWPRAXLCnSRvDsF&buyin_track=COgIEN-Q0K6ijcwCGgQIABAAIgkyB05ldmpGQ2Mom4uIjNCQidIwMAE&c_biz_combo=2 + + + var uri = new Uri(url); + + var collection = HttpUtility.ParseQueryString(uri.Query);//默认采用UTF-8编码,当然也可以传入特定编码进行解析 + //var collection= HttpUtility.ParseQueryString(uri.Query,Encoding.ASCII); + + var id = collection["id"]; + var promotion_id = collection["origin_id"]?.Split('_')[1]; + var sec_author_id = collection["sec_author_id"]; + var buyin_track = collection["buyin_track"]; + + return CreateKouling(id, promotion_id, sec_author_id, buyin_track); + } + + /// + /// + /// + /// 商品ID + /// 推广地址ID + /// 推广人信息 + private static string CreateKouling(string product_id, string promotion_id, string sec_author_id, string buyin_track) + { + try + { + var ts = GetTimeStamp(); + //var sslocal = $"sslocal%3A%2F%2Fec_goods_detail%2F%3Fsec_author_id%3D%26promotion_id%3D{promotion_id}%26product_id%3D{product_id}%26commodity_id%3D%26commodity_type%3D%26promotion_source%3D%26enter_method%3Dclick_video_tag%26meta_params%3D%7B%22is_star_atlas%22%3Afalse%2C%22is_ad_traffic%22%3Afalse%2C%22entrance_info%22%3A%22%22%7D%26source_page%3Dtoken%26ecom_share_track_params%3D%7B%22is_ec_shopping%22%3A%221%22%7D%26request_additions%3D%7B%22sec_author_id%22%3A%22{}%22%7D"; + var sslocal = "sslocal://ec_goods_detail/?sec_author_id=&promotion_id=" + promotion_id + "&product_id=" + product_id + "&commodity_id=&commodity_type=&promotion_source=&enter_method=click_video_tag&meta_params={\"is_star_atlas\":false,\"is_ad_traffic\":false,\"entrance_info\":\"\"}&source_page=token&ecom_share_track_params={\"is_ec_shopping\":\"1\"}&request_additions={\"sec_author_id\":\"" + sec_author_id + "\",\"buyin_track\":\"" + buyin_track + "\"}"; + sslocal = CsharpHttpHelper.HttpHelper.URLEncode(sslocal, Encoding.UTF8); + var otherData = $"&schema_type=20&object_id={product_id}©_type=auto&iid={device_info["install_id"]}&device_id={device_info["device_id"]}&ac=wifi&channel=douyin_juyouliang_and4&aid=1128&app_name=aweme&version_code=190200&version_name=19.2.0&device_platform=android&os=android&ssmix=a&device_type=Pixel+3&device_brand=google&language=zh&os_api=29&os_version=10&manifest_version_code=190201&resolution=1080*2028&dpi=440&update_version_code=19209900&_rticket=1646117336178&package=com.ss.android.ugc.aweme&cpu_support64=true&host_abi=armeabi-v7a&is_guest_mode=0&app_type=normal&minor_status=0&appTheme=light&need_personal_recommend=1&is_android_pad=0&ts={ts}&cdid=a090acdf-53e8-47a7-85ca-7d4f8d3d3b7c"; + + var param = $"schema={sslocal}{otherData}"; + var url = $"https://api5-normal-c-lq.amemv.com/aweme/v2/platform/share/command/gen/?{param}"; + var Headers = CreateXg(param); + var http = new CsharpHttpHelper.HttpHelper(); + var item = new CsharpHttpHelper.HttpItem() + { + URL = url, + Method = "post", + ContentType = "application/json", + Postdata = "{'body': 'null'}", + Timeout = 5000, + UserAgent = "com.ss.android.ugc.aweme/190201 (Linux; U; Android 10; zh_CN_#Hans; Pixel 3; Build/QQ3A.200805.001; Cronet/TTNetVersion:28eaf52b 2021-12-28 QuicVersion:68cae75d 2021-08-12)" + }; + foreach (var v in Headers) + { + item.Header[v.Key] = v.Value; + } + //3:/ - + var html = http.GetHtml(item).Html; + var json = JObject.Parse(html); + if (json["command_v2"] != null) + return json["command_v2"].ToString(); + else throw new Exception(html); + } + catch (Exception ex) + { + EventClient.OnEvent("", $"抖音口令转换失败:{ex.Message}"); + } + return String.Empty; + } + #endregion + + + + } +} diff --git a/类库/Api.Framework/Tools/DouyinGoodsInfo.cs b/类库/Api.Framework/Tools/DouyinGoodsInfo.cs new file mode 100644 index 0000000..03141ad --- /dev/null +++ b/类库/Api.Framework/Tools/DouyinGoodsInfo.cs @@ -0,0 +1,563 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + #region 新的接口 + public class Sale_infos + { + /// + /// 新人 + /// + public string campaign_type { get; set; } + /// + /// 30减2 + /// + public string title { get; set; } + /// + /// + /// + public int begin_time { get; set; } + /// + /// + /// + public int end_time { get; set; } + } + + public class New_goods_tag_infos + { + } + + public class Exper_score + { + /// + /// + /// + public string score { get; set; } + /// + /// 低 + /// + public string level { get; set; } + } + + public class Goods_score + { + /// + /// + /// + public string score { get; set; } + /// + /// 低 + /// + public string level { get; set; } + } + + public class Logistics_score + { + /// + /// + /// + public string score { get; set; } + /// + /// 高 + /// + public string level { get; set; } + } + + public class Service_score + { + /// + /// + /// + public string score { get; set; } + /// + /// 中 + /// + public string level { get; set; } + } + + public class Shop_exper_score + { + /// + /// + /// + public Exper_score exper_score { get; set; } + /// + /// + /// + public Goods_score goods_score { get; set; } + /// + /// + /// + public Logistics_score logistics_score { get; set; } + /// + /// + /// + public Service_score service_score { get; set; } + /// + /// + /// + public bool has_data { get; set; } + } + + public class Shop_hot_sale_products + { + /// + /// + /// + public string promotion_id { get; set; } + /// + /// + /// + public string product_id { get; set; } + /// + /// 【粉丝专属】防蓝光眼镜近视眼镜女度数网红款INS镜框男超轻 + /// + public string title { get; set; } + /// + /// + /// + public string cover { get; set; } + /// + /// + /// + public int price { get; set; } + /// + /// + /// + public string detail_url { get; set; } + /// + /// + /// + public int sales { get; set; } + /// + /// + /// + public int cos_fee { get; set; } + /// + /// + /// + public int cos_ratio { get; set; } + } + + public class Status_info + { + /// + /// + /// + public bool is_shop_button { get; set; } + /// + /// + /// + public bool is_send_cooperation_intention { get; set; } + /// + /// + /// + public int daren_lark_status { get; set; } + /// + /// + /// + public string daren_mobile { get; set; } + /// + /// + /// + public string shop_mobile { get; set; } + /// + /// + /// + public int shop_lark_status { get; set; } + /// + /// + /// + public string shop_wechat_id { get; set; } + /// + /// + /// + public bool is_trusteeship { get; set; } + } + + public class Icon + { + /// + /// + /// + public List url_list { get; set; } + } + + public class Small_icon + { + /// + /// + /// + public List url_list { get; set; } + } + + public class Privilege_info_detail + { + /// + /// + /// + public string tag_id { get; set; } + /// + /// 正品保障 + /// + public string title { get; set; } + /// + /// 100%正品,假一赔三,放心选购 + /// + public string content { get; set; } + /// + /// + /// + public Icon icon { get; set; } + /// + /// + /// + public Small_icon small_icon { get; set; } + /// + /// + /// + public bool show_small_icon { get; set; } + } + + public class Privilege_info + { + /// + /// + /// + public int privilege_id { get; set; } + /// + /// + /// + public string platform_public_url { get; set; } + /// + /// + /// + public List privilege_info_detail { get; set; } + } + + public class Data + { + /// + /// 促销id + /// + public string promotion_id { get; set; } + /// + /// 商品id + /// + public string product_id { get; set; } + /// + /// 商品标题 + /// + public string title { get; set; } + /// + /// 商品主图 + /// + public string cover { get; set; } + /// + /// 其他商品图 + /// + public List images { get; set; } + /// + /// 售价 + /// + public int price { get; set; } + /// + /// 详细连接 + /// + public string detail_url { get; set; } + /// + /// 佣金率 + /// + public int cos_ratio { get; set; } + /// + /// 佣金 + /// + public int cos_fee { get; set; } + /// + /// 月销 + /// + public int sales { get; set; } + /// + /// 商品是否在橱窗 + /// + public bool is_in_shopwindow { get; set; } + /// + /// 促销来源 + /// + public int promotion_source { get; set; } + /// + /// 原价格 + /// + public int old_price { get; set; } + /// + /// 原佣金率 + /// + public int old_cos_ratio { get; set; } + /// + /// 原佣金 + /// + public int old_cos_fee { get; set; } + /// + /// 优惠券信息 + /// + public List sale_infos { get; set; } + /// + /// 新商品标签信息 + /// + public List new_goods_tag_infos { get; set; } + /// + /// 产品亮点 + /// + public string product_highlights { get; set; } + /// + /// 店铺id + /// + public int shop_id { get; set; } + /// + /// 店铺昵称 + /// + public string shop_name { get; set; } + /// + /// 店铺头像 + /// + public string shop_image { get; set; } + /// + /// 店铺实分数信息 + /// + public Shop_exper_score shop_exper_score { get; set; } + /// + /// 商店热卖产品 + /// + public List shop_hot_sale_products { get; set; } + /// + /// 商店热卖产品 + /// + public List big_imgs { get; set; } + /// + /// + /// + public Status_info status_info { get; set; } + /// + /// + /// + public Privilege_info privilege_info { get; set; } + } + + public class DouyinGoodsInfo + { + /// + /// 返回编码 + /// + public int code { get; set; } + /// + /// + /// + public int st { get; set; } + /// + /// 错误信息 + /// + public string msg { get; set; } + /// + /// 订单数据对象 + /// + public Data data { get; set; } + /// + /// 可能是日志编码 + /// + public string log_id { get; set; } + } + + + + #endregion + + #region MyRegion + + ///// + ///// 抖音商品信息 + ///// + //public class DouyinGoodsInfo + //{ + // /// + // /// 返回编码 + // /// + // public int code { get; set; } + // /// + // /// + // /// + // public int st { get; set; } + // /// + // /// 错误信息 + // /// + // public string msg { get; set; } + // /// + // /// 订单数据对象 + // /// + // public Data data { get; set; } + // /// + // /// 订单数量 + // /// + // public int total { get; set; } + // /// + // /// 可能是日志编码 + // /// + // public string log_id { get; set; } + //} + + ///// + ///// 其他 + ///// + //public class Cover + //{ + // /// + // /// xxxxxxxx 不知道是什么 + // /// + // public string uri { get; set; } + // /// + // /// 商品图片 + // /// + // public List url_list { get; set; } + //} + + ///// + ///// 图片 + ///// + //public class Brand_icon + //{ + // /// + // /// 店铺图片 + // /// + // public List url_list { get; set; } + //} + + ///// + ///// 推广项目 + ///// + //public class PromotionsItem + //{ + // /// + // /// 推广id + // /// + // public string promotion_id { get; set; } + // /// + // /// 产品id + // /// + // public string product_id { get; set; } + // /// + // /// 产品标题 + // /// + // public string title { get; set; } + // /// + // /// 商品图片等信息 + // /// + // public Cover cover { get; set; } + // /// + // /// 细节链接 + // /// + // public string detail_url { get; set; } + // /// + // /// 推广来源编码 + // /// + // public int promotion_source { get; set; } + // /// + // /// 品牌图标 + // /// + // public Brand_icon brand_icon { get; set; } + // /// + // /// 商品现价价格 + // /// + // public int price { get; set; } + // /// + // /// 市场价 + // /// + // public int market_price { get; set; } + // /// + // /// 佣金(分) + // /// + // public int cos_fee { get; set; } + // /// + // /// 佣金率(要除以100) + // /// + // public int cos_ratio { get; set; } + // /// + // /// 月销售 + // /// + // public int month_sales { get; set; } + + // /// + // /// 优惠券信息(没有为空) + // /// + // public List sale_infos { get; set; } + // /// + // /// 商店id + // /// + // public int shop_id { get; set; } + // /// + // /// 商店名称 + // /// + // public string shop_name { get; set; } + // /// + // /// 商品评分 + // /// + // public string exp_score { get; set; } + // /// + // /// 是否在促销 + // /// + // public bool in_promotion { get; set; } + // /// + // /// 在商店 + // /// + // public bool in_shop { get; set; } + // /// + // /// 销售 + // /// + // public int sales { get; set; } + //} + + ///// + ///// 商品信息 + ///// + //public class Data + //{ + // /// + // /// 商品信息 + // /// + // public List promotions { get; set; } + // /// + // /// 是否还有更多 + // /// + // public bool has_more { get; set; } + // /// + // /// 搜索id + // /// + // public string search_id { get; set; } + //} + + ///// + ///// 销售信息(优惠券信息) + ///// + //public class Sale_infos + //{ + // /// + // /// 券 + // /// + // public string campaign_type { get; set; } + // /// + // /// 券信息(100减5) + // /// + // public string title { get; set; } + // /// + // /// 优惠券开始 + // /// + // public int begin_time { get; set; } + // /// + // /// 优惠券结束 + // /// + // public int end_time { get; set; } + //} + #endregion +} diff --git a/类库/Api.Framework/Tools/Encryption.cs b/类库/Api.Framework/Tools/Encryption.cs new file mode 100644 index 0000000..afe5951 --- /dev/null +++ b/类库/Api.Framework/Tools/Encryption.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 加密解密QQ消息包的工具类. + /// + public static class TeaEncryption + { + private static void code(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos, byte[] key) + { + if (outPos > 0) + { + for (int i = 0; i < 8; i++) + { + In[outOffset + outPos + i] = (byte)(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i - 8]); + } + } + uint[] formattedKey = FormatKey(key); + uint y = ConvertByteArrayToUInt(In, outOffset + outPos); + uint z = ConvertByteArrayToUInt(In, outOffset + outPos + 4); + uint sum = 0; + uint delta = 0x9e3779b9; + uint n = 16; + + while (n-- > 0) + { + sum += delta; + y += ((z << 4) + formattedKey[0]) ^ (z + sum) ^ ((z >> 5) + formattedKey[1]); + z += ((y << 4) + formattedKey[2]) ^ (y + sum) ^ ((y >> 5) + formattedKey[3]); + } + Array.Copy(ConvertUIntToByteArray(y), 0, Out, outOffset + outPos, 4); + Array.Copy(ConvertUIntToByteArray(z), 0, Out, outOffset + outPos + 4, 4); + if (inPos > 0) + { + for (int i = 0; i < 8; i++) + { + Out[outOffset + outPos + i] = (byte)(Out[outOffset + outPos + i] ^ In[inOffset + inPos + i - 8]); + } + } + } + + private static void decode(byte[] In, int inOffset, int inPos, byte[] Out, int outOffset, int outPos, byte[] key) + { + if (outPos > 0) + { + for (int i = 0; i < 8; i++) + { + Out[outOffset + outPos + i] = (byte)(In[inOffset + inPos + i] ^ Out[outOffset + outPos + i - 8]); + } + } + else + { + Array.Copy(In, inOffset, Out, outOffset, 8); + } + uint[] formattedKey = FormatKey(key); + uint y = ConvertByteArrayToUInt(Out, outOffset + outPos); + uint z = ConvertByteArrayToUInt(Out, outOffset + outPos + 4); + uint sum = 0xE3779B90; + uint delta = 0x9e3779b9; + uint n = 16; + + while (n-- > 0) + { + z -= ((y << 4) + formattedKey[2]) ^ (y + sum) ^ ((y >> 5) + formattedKey[3]); + y -= ((z << 4) + formattedKey[0]) ^ (z + sum) ^ ((z >> 5) + formattedKey[1]); + sum -= delta; + } + Array.Copy(ConvertUIntToByteArray(y), 0, Out, outOffset + outPos, 4); + Array.Copy(ConvertUIntToByteArray(z), 0, Out, outOffset + outPos + 4, 4); + } + + + public static byte[] Decrypt(byte[] data, byte[] key) + { + + return Decrypt(data,0,data.Length,key); + } + + public static byte[] Decrypt(byte[] In, int offset, int len, byte[] key) + { + // 因为QQ消息加密之后至少是16字节,并且肯定是8的倍数,这里检查这种情况 + //if ((len % 8 != 0) || (len < 16)) + //{ + // return null; + //} + byte[] Out = new byte[len]; + for (int i = 0; i < len; i += 8) + { + decode(In, offset, i, Out, 0, i, key); + } + for (int i = 8; i < len; i++) + { + Out[i] = (byte)(Out[i] ^ In[offset + i - 8]); + } + int pos = Out[0] & 0x07; + len = len - pos - 10; + byte[] res = new byte[len]; + Array.Copy(Out, pos + 3, res, 0, len); + return res; + } + + + public static byte[] Encrypt(byte[] data, byte[] key) + { + return Encrypt(data,0,data.Length,key); + } + public static byte[] Encrypt(byte[] In, int offset, int len, byte[] key) + { + // 计算头部填充字节数 + int pos = (len + 10) % 8; + if (pos != 0) + { + pos = 8 - pos; + } + byte[] plain = new byte[len + pos + 10]; + Random Rnd = new Random(); + plain[0] = (byte)((Rnd.Next() & 0xF8) | pos); + for (int i = 1; i < pos + 3; i++) + { + plain[i] = (byte)(Rnd.Next() & 0xFF); + } + Array.Copy(In, 0, plain, pos + 3, len); + for (int i = pos + 3 + len; i < plain.Length; i++) + { + plain[i] = 0x0; + } + // 定义输出流 + byte[] outer = new byte[len + pos + 10]; + for (int i = 0; i < outer.Length; i += 8) + { + code(plain, 0, i, outer, 0, i, key); + } + return outer; + } + + private static uint[] FormatKey(byte[] key) + { + if (key.Length == 0) + { + throw new ArgumentException("Key must be between 1 and 16 characters in length"); + } + byte[] refineKey = new byte[16]; + if (key.Length < 16) + { + Array.Copy(key, 0, refineKey, 0, key.Length); + for (int k = key.Length; k < 16; k++) + { + refineKey[k] = 0x20; + } + } + else + { + Array.Copy(key, 0, refineKey, 0, 16); + } + uint[] formattedKey = new uint[4]; + int j = 0; + for (int i = 0; i < refineKey.Length; i += 4) + { + formattedKey[j++] = ConvertByteArrayToUInt(refineKey, i); + } + return formattedKey; + } + + private static byte[] ConvertUIntToByteArray(uint v) + { + byte[] result = new byte[4]; + result[0] = (byte)((v >> 24) & 0xFF); + result[1] = (byte)((v >> 16) & 0xFF); + result[2] = (byte)((v >> 8) & 0xFF); + result[3] = (byte)((v >> 0) & 0xFF); + return result; + } + + private static uint ConvertByteArrayToUInt(byte[] v, int offset) + { + if (offset + 4 > v.Length) + { + return 0; + } + uint output; + output = (uint)(v[offset] << 24); + output |= (uint)(v[offset + 1] << 16); + output |= (uint)(v[offset + 2] << 8); + output |= (uint)(v[offset + 3] << 0); + return output; + } + } + + +} diff --git a/类库/Api.Framework/Tools/ExcelHelper.cs b/类库/Api.Framework/Tools/ExcelHelper.cs new file mode 100644 index 0000000..b083f07 --- /dev/null +++ b/类库/Api.Framework/Tools/ExcelHelper.cs @@ -0,0 +1,783 @@ +//using System; +//using System.Web.UI; +//using System.Collections.Generic; +//using System.Web.UI.WebControls; +//using System.Data; +//using System.IO; +//using System.Text; +//using System.Web; +//using NPOI; +//using NPOI.HPSF; +//using NPOI.HSSF; +//using NPOI.HSSF.UserModel; +//using NPOI.HSSF.Util; +//using NPOI.POIFS; +//using NPOI.Util; +//using System.Data.OleDb; +//using System.Threading; + +//namespace Api.Framework.Tools +//{ +// /// +// /// 功能说明:此工具主要采用NOPI组件,实现对Excel的获取数据、导出数据到Excel等功能。 +// /// +// /// +// /// 创建时间:2012年12月12日0:17:22 创建人:张晓斌 +// /// 备注信息: +// /// 注意事项:采用NOPI进行操作Excel可以在服务器上不用安装Office的情况下进行,而且性能比直接操作Office要高很多 +// /// 修改时间: +// /// +// public class ExcelHelper +// { +// #region ExportEasy:NPOI简单Demo,快速入门代码,以MemoryStream形式实现导出DataTable数据到Excel +// /// +// /// NPOI简单Demo,快速入门代码 +// /// +// /// +// /// +// /// NPOI认为Excel的第一个单元格是:(0,0) +// public static void ExportEasy(DataTable dtSource, string strFileName) +// { +// HSSFWorkbook workbook = new HSSFWorkbook(); +// HSSFSheet sheet = workbook.CreateSheet(); + +// //填充表头 +// HSSFRow dataRow = sheet.CreateRow(0); +// foreach (DataColumn column in dtSource.Columns) +// { +// dataRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); +// } + + +// //填充内容 +// for (int i = 0; i < dtSource.Rows.Count; i++) +// { +// dataRow = sheet.CreateRow(i + 1); +// for (int j = 0; j < dtSource.Columns.Count; j++) +// { +// dataRow.CreateCell(j).SetCellValue(dtSource.Rows[i][j].ToString()); +// } +// } + + +// //保存 +// using (MemoryStream ms = new MemoryStream()) +// { +// using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)) +// { +// workbook.Write(ms); +// ms.Flush(); +// ms.Position = 0; +// byte[] data = ms.ToArray(); +// fs.Write(data, 0, data.Length); +// fs.Flush(); +// } +// } +// sheet.Dispose(); +// workbook.Dispose(); +// } +// #endregion + +// #region ExportByWeb:Web形式导出DataTable数据到Excel +// /// +// /// 用于Web导出 +// /// +// /// +// /// +// /// +// public static void ExportByWeb(DataTable dtSource, string strHeaderText, string strFileName) +// { + +// HttpContext curContext = HttpContext.Current; +// if (!strFileName.Contains(".xls") || !strFileName.Contains(".xlsx")) +// strFileName += ".xls"; +// // 设置编码和附件格式 +// curContext.Response.ContentType = "application/vnd.ms-excel"; +// curContext.Response.ContentEncoding = Encoding.UTF8; +// curContext.Response.Charset = ""; +// curContext.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(strFileName, Encoding.UTF8)); + +// curContext.Response.BinaryWrite(Export(dtSource, strHeaderText).GetBuffer()); +// curContext.Response.End(); + +// } +// #endregion + +// #region Export:DataTable导出到Excel的MemoryStream +// /// +// /// DataTable导出到Excel的MemoryStream +// /// +// /// 源DataTable +// /// 表头文本 +// /// +// public static MemoryStream Export(DataTable dtSource, string strHeaderText) +// { +// HSSFWorkbook workbook = new HSSFWorkbook(); +// HSSFSheet sheet = workbook.CreateSheet(); + +// #region 右击文件 属性信息 +// { +// DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); +// dsi.Company = "";//公司 +// workbook.DocumentSummaryInformation = dsi; + +// SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); +// si.Author = ""; //填加xls文件作者信息 +// si.ApplicationName = ""; //填加xls文件创建程序信息 +// si.LastAuthor = ""; //填加xls文件最后保存者信息 +// si.Comments = ""; //填加xls文件作者信息 +// si.Title = ""; //填加xls文件标题信息 +// si.Subject = "";//填加文件主题信息 +// si.CreateDateTime = DateTime.Now; +// workbook.SummaryInformation = si; +// } +// #endregion + +// HSSFCellStyle dateStyle = workbook.CreateCellStyle(); +// HSSFDataFormat format = workbook.CreateDataFormat(); +// //dateStyle.DataFormat = format.GetFormat("yyyy-MM-dd"); + +// //取得列宽 +// int[] arrColWidth = new int[dtSource.Columns.Count]; +// foreach (DataColumn item in dtSource.Columns) +// { /*gb2312*/ +// arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length; +// } +// for (int i = 0; i < dtSource.Rows.Count; i++) +// { +// for (int j = 0; j < dtSource.Columns.Count; j++) +// { +// int intTemp = Encoding.GetEncoding(936).GetBytes(dtSource.Rows[i][j].ToString()).Length; +// if (intTemp > arrColWidth[j]) +// { +// arrColWidth[j] = intTemp; +// } +// } +// } + +// int rowIndex = 0; + +// foreach (DataRow row in dtSource.Rows) +// { +// #region 新建表,填充表头,填充列头,样式 +// if (rowIndex == 65535 || rowIndex == 0) +// { +// if (rowIndex != 0) +// { +// sheet = workbook.CreateSheet(); +// } + +// #region 表头及样式 +// { +// HSSFRow headerRow = sheet.CreateRow(0); +// headerRow.HeightInPoints = 25; +// headerRow.CreateCell(0).SetCellValue(strHeaderText); + +// HSSFCellStyle headStyle = workbook.CreateCellStyle(); +// headStyle.Alignment = CellHorizontalAlignment.CENTER; +// HSSFFont font = workbook.CreateFont(); +// font.FontHeightInPoints = 20; +// font.Boldweight = 700; +// headStyle.SetFont(font); + +// headerRow.GetCell(0).CellStyle = headStyle; + +// sheet.AddMergedRegion(new Region(0, 0, 0, dtSource.Columns.Count - 1)); +// headerRow.Dispose(); +// } +// #endregion + + +// #region 列头及样式 +// { +// HSSFRow headerRow = sheet.CreateRow(1); + + +// HSSFCellStyle headStyle = workbook.CreateCellStyle(); +// headStyle.Alignment = CellHorizontalAlignment.CENTER; +// headStyle.BorderBottom = CellBorderType.THIN; +// headStyle.BorderLeft = CellBorderType.THIN; +// headStyle.BorderRight = CellBorderType.THIN; +// headStyle.BorderTop = CellBorderType.THIN; +// HSSFFont font = workbook.CreateFont(); +// font.FontHeightInPoints = 10; +// font.Boldweight = 700; +// headStyle.SetFont(font); + + +// foreach (DataColumn column in dtSource.Columns) +// { +// headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); +// headerRow.GetCell(column.Ordinal).CellStyle = headStyle; + +// //设置列宽 +// sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); + +// } +// headerRow.Dispose(); +// } +// #endregion + +// rowIndex = 2; +// } +// #endregion + + +// #region 填充内容 +// foreach (DataColumn column in dtSource.Columns) +// { +// HSSFRow dataRow = sheet.CreateRow(rowIndex); +// HSSFCell newCell = dataRow.CreateCell(column.Ordinal); + +// newCell.CellStyle.BorderBottom = CellBorderType.THIN; +// newCell.CellStyle.BorderLeft = CellBorderType.THIN; +// newCell.CellStyle.BorderRight = CellBorderType.THIN; +// newCell.CellStyle.BorderTop = CellBorderType.THIN; + +// string drValue = row[column].ToString(); + +// switch (column.DataType.ToString()) +// { +// case "System.String"://字符串类型 +// newCell.SetCellValue(drValue); +// break; +// case "System.DateTime"://日期类型 +// DateTime dateV; +// DateTime.TryParse(drValue, out dateV); +// newCell.SetCellValue(dateV); + +// newCell.CellStyle = dateStyle;//格式化显示 +// break; +// case "System.Boolean"://布尔型 +// bool boolV = false; +// bool.TryParse(drValue, out boolV); +// newCell.SetCellValue(boolV); +// break; +// case "System.Int16"://整型 +// case "System.Int32": +// case "System.Int64": +// case "System.Byte": +// int intV = 0; +// int.TryParse(drValue, out intV); +// newCell.SetCellValue(intV); +// break; +// case "System.Decimal"://浮点型 +// case "System.Double": +// double doubV = 0; +// double.TryParse(drValue, out doubV); +// newCell.SetCellValue(doubV); +// break; +// case "System.DBNull"://空值处理 +// newCell.SetCellValue(""); +// break; +// default: +// newCell.SetCellValue(""); +// break; +// } + +// } +// #endregion + +// rowIndex++; +// } + +// using (MemoryStream ms = new MemoryStream()) +// { +// workbook.Write(ms); +// ms.Flush(); +// ms.Position = 0; + +// sheet.Dispose(); +// workbook.Dispose(); + +// return ms; +// } +// } +// #endregion + +// #region Export:以MemoryStream形式将DataTable导出到Excel文件 +// /// +// /// DataTable导出到Excel文件 +// /// +// /// 源DataTable +// /// 表头文本 +// /// 保存位置 +// public static void Export(DataTable dtSource, string strHeaderText, string strFileName) +// { +// using (MemoryStream ms = Export(dtSource, strHeaderText)) +// { +// using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)) +// { +// byte[] data = ms.ToArray(); +// fs.Write(data, 0, data.Length); +// fs.Flush(); +// } +// } +// } +// #endregion + +// public static DataTable Import(string strFileName, string SheetName, int HeaderRowIndex) +// { +// using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) +// { +// return Import(file, SheetName, HeaderRowIndex); +// } +// } +// public static DataTable Import(string strFileName, int SheetIndex, int HeaderRowIndex) +// { +// using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) +// { +// return Import(file, SheetIndex, HeaderRowIndex); +// } +// } + + +// #region Import:读取Excel默认第一行为列名 +// /// +// /// 读取Excel默认第一行为标头 +// /// +// /// excel文档路径 +// /// +// public static DataTable Import(string strFileName) +// { +// DataTable dt = new DataTable(); + +// HSSFWorkbook hssfworkbook; +// using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) +// { +// hssfworkbook = new HSSFWorkbook(file); +// } +// HSSFSheet sheet = hssfworkbook.GetSheetAt(0); +// System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); + +// HSSFRow headerRow = sheet.GetRow(0); +// int cellCount = headerRow.LastCellNum; + +// for (int j = 0; j < cellCount; j++) +// { +// HSSFCell cell = headerRow.GetCell(j); +// dt.Columns.Add(cell.ToString()); +// // dt.Columns.Add(getCellValueByType(cell)); +// } + +// for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) +// { +// HSSFRow row = sheet.GetRow(i); +// DataRow dataRow = dt.NewRow(); + +// for (int j = row.FirstCellNum; j < cellCount; j++) +// { +// if (row.GetCell(j) != null) +// //dataRow[j] = row.GetCell(j).ToString(); +// dataRow[j] = getCellValueByType(row.GetCell(j)); +// } + +// dt.Rows.Add(dataRow); +// } + +// return dt; +// } +// #endregion + +// #region Import:读取Excel数据到DataTable第一行为列名 +// /// +// /// 读取Excel数据到DataTable第一行为列名 +// /// +// /// Excel文件流 +// /// +// /// 从第几行开始读取 +// /// +// public static DataTable Import(Stream ExcelFileStream, string SheetName, int HeaderRowIndex) +// { +// HSSFWorkbook workbook = new HSSFWorkbook(ExcelFileStream); +// HSSFSheet sheet = workbook.GetSheet(SheetName); + +// DataTable table = new DataTable(); + +// HSSFRow headerRow = sheet.GetRow(HeaderRowIndex); +// int cellCount = headerRow.LastCellNum; + +// for (int i = headerRow.FirstCellNum; i < cellCount; i++) +// { +// DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue); +// table.Columns.Add(column); +// } + +// int rowCount = sheet.LastRowNum; +// int startRow = HeaderRowIndex + 1; + +// for (int i = startRow; i <= sheet.LastRowNum; i++) +// { +// HSSFRow row = sheet.GetRow(i); +// DataRow dataRow = table.NewRow(); + +// for (int j = row.FirstCellNum; j < cellCount; j++) +// { +// dataRow[j] = getCellValueByType(row.GetCell(j)); +// //dataRow[j] = row.GetCell(j).ToString(); +// } +// } + +// ExcelFileStream.Close(); +// workbook = null; +// sheet = null; +// return table; +// } +// #endregion + +// #region Import:读取Excel数据到DataTable第一行为列名 +// /// +// /// 读取Excel数据到DataTable第一行为列名 +// /// +// /// Excel文件流 +// /// +// /// 从第几行开始读取 +// /// +// public static DataTable Import(Stream ExcelFileStream, int SheetIndex, int HeaderRowIndex) +// { +// HSSFWorkbook workbook = new HSSFWorkbook(ExcelFileStream); +// HSSFSheet sheet = workbook.GetSheetAt(SheetIndex); + +// DataTable table = new DataTable(); + +// HSSFRow headerRow = sheet.GetRow(HeaderRowIndex); +// //int cellCount = headerRow.LastCellNum; +// int cellCount = headerRow.Cells.Count; + +// for (int i = headerRow.FirstCellNum; i < cellCount; i++) +// { +// if (headerRow.GetCell(i).StringCellValue != null) +// { +// DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue); +// table.Columns.Add(column); +// } +// } + +// int rowCount = sheet.LastRowNum; +// int startRow = HeaderRowIndex + 1; +// for (int i = startRow; i <= sheet.LastRowNum; i++) +// { +// HSSFRow row = sheet.GetRow(i); +// DataRow dataRow = table.NewRow(); + +// for (int j = row.FirstCellNum; j < cellCount; j++) +// { +// if (row.GetCell(j) != null) +// { +// dataRow[j] = getCellValueByType(row.GetCell(j)); +// } +// } + +// table.Rows.Add(dataRow); +// } + +// ExcelFileStream.Close(); +// workbook = null; +// sheet = null; +// return table; +// } +// #endregion + +// #region getCellValueByType:获取Excel对象单元格中的数据值 +// /// +// /// 获取Excel对象单元格中的数据值 +// /// +// /// HSSFCell:Excel单元格对象 +// /// +// public static string getCellValueByType(HSSFCell cell) +// { +// string ret = ""; +// switch (cell.CellType) +// { +// case HSSFCellType.BLANK: ret = ""; break; +// case HSSFCellType.BOOLEAN: ret = "[cell.BooleanCellValue]"; break; +// case HSSFCellType.NUMERIC: +// try +// { +// if (cell.ToString().Contains("/")) +// { +// ret = cell.DateCellValue.ToString(); +// } +// else +// { +// ret = cell.NumericCellValue.ToString(); +// } +// } +// catch (Exception e) +// { +// ret = cell.NumericCellValue.ToString(); +// } +// //This is a trick to get the correct value of the cell. NumericCellValue will return a numeric value no matter the cell value is a date or a number. +// break; +// case HSSFCellType.STRING: ret = cell.StringCellValue; break; +// case HSSFCellType.ERROR: ret = "[cell.ErrorCellValue]"; break; +// case HSSFCellType.FORMULA: ret = cell.StringCellValue; break;//如果是公式,则返回值 +// default: ret = "=" + cell.CellFormula; break; +// } +// return ret; +// } +// #endregion + +// #region ExportExcelByWeb:导出WebControl.GridView数据到Excel,隐藏的数据列不导出 +// /// +// /// 导出WebControl.GridView数据到Excel,隐藏的数据列不导出 +// /// +// /// 泛型对象 +// /// 填充数据的WebControl.GridView +// /// 需要导出的泛型对象集合列表 +// public static void ExportExcelByWeb(GridView gridView, IList listObj) +// { +// ExportExcelByWeb(gridView, listObj, "", ""); +// } + +// /// +// /// 导出WebControl.GridView数据到Excel,隐藏的数据列不导出 +// /// +// /// 泛型对象 +// /// 填充数据的WebControl.GridView +// /// 需要导出的泛型对象集合列表 +// /// 导出Excel的标题,默认为“Excel数据列表” +// /// 导出的Excel文件名称,默认为“ExportExcelFile” +// public static void ExportExcelByWeb(GridView gridView, IList listObj, string strHeaderText, string strFileName) +// { +// if (string.IsNullOrEmpty(strHeaderText)) strHeaderText = "Excel数据列表"; +// if (string.IsNullOrEmpty(strFileName)) strFileName = "ExportExcelFile"; +// DataTable dt = null;//ConvertTypeUtil.ConvertListEntityToDataTable(listObj); +// //实现将数据表中的数据填充到根据gridview的col属性解析后的DataTable中 +// DataTable dtExportData = new DataTable(); +// Dictionary cols = new Dictionary(); +// foreach (object tcol in gridView.Columns) +// { +// if (tcol is System.Web.UI.WebControls.TemplateField) +// { +// System.Web.UI.WebControls.TemplateField tempcol = tcol as System.Web.UI.WebControls.TemplateField; +// if (tempcol.Visible && tempcol.SortExpression.Length > 0) +// { +// cols.Add(tempcol.SortExpression, tempcol.HeaderText); +// dtExportData.Columns.Add(tempcol.SortExpression); +// } +// } +// else if (tcol is BoundField) +// { +// BoundField BoundFieldLogID = tcol as BoundField; +// string bb = BoundFieldLogID.DataField; +// } +// } + +// //实现根据GridView中的col属性进行数据列筛选,并且另存到筛选后的DataTable +// foreach (DataRow dr in dt.Rows) +// { +// DataRow drExportData = dtExportData.NewRow(); +// foreach (KeyValuePair keyValue in cols) +// { +// drExportData[keyValue.Key] = dr[keyValue.Key]; +// } +// dtExportData.Rows.Add(drExportData); +// } +// ExportByWeb(dtExportData, strFileName, strHeaderText); +// } +// #endregion + +// #region GenerateExcelTemplate:生成excel数据模板 +// /// +// /// 生成模版文件 +// /// +// /// 原始模版文件路径 +// /// Tabname为sheet名,namespace为表头 +// /// +// public static MemoryStream GenerateExcelTemplate(string filePath, List dtSourceArr) +// { +// HSSFWorkbook workbook = new HSSFWorkbook(); + +// using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite)) +// { +// workbook = new HSSFWorkbook(fileStream); +// } +// #region 右击文件 属性信息 +// { +// DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); +// dsi.Company = "";//公司 +// workbook.DocumentSummaryInformation = dsi; + +// SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); +// si.Author = ""; //填加xls文件作者信息 +// si.ApplicationName = ""; //填加xls文件创建程序信息 +// si.LastAuthor = ""; //填加xls文件最后保存者信息 +// si.Comments = ""; //填加xls文件作者信息 +// si.Title = ""; //填加xls文件标题信息 +// si.Subject = "";//填加文件主题信息 +// si.CreateDateTime = DateTime.Now; +// workbook.SummaryInformation = si; +// } +// #endregion + +// HSSFCellStyle dateStyle = workbook.CreateCellStyle(); +// HSSFDataFormat format = workbook.CreateDataFormat(); +// //dateStyle.DataFormat = format.GetFormat("yyyy-MM-dd"); +// for (int ti = 0; ti < dtSourceArr.Count; ti++) +// { +// var table = dtSourceArr[ti]; + +// HSSFSheet sheet = workbook.CreateSheet(table.TableName); +// workbook.SetSheetOrder(table.TableName, ti); + +// //取得列宽 +// int[] arrColWidth = new int[table.Columns.Count]; +// foreach (DataColumn item in table.Columns) +// { /*gb2312*/ +// arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length; +// } +// for (int i = 0; i < table.Rows.Count; i++) +// { +// for (int j = 0; j < table.Columns.Count; j++) +// { +// int intTemp = Encoding.GetEncoding(936).GetBytes(table.Rows[i][j].ToString()).Length; +// if (intTemp > arrColWidth[j]) +// { +// arrColWidth[j] = intTemp; +// } +// } +// } + +// int rowIndex = 0; + +// foreach (DataRow row in table.Rows) +// { +// #region 新建表,填充表头,填充列头,样式 +// if (rowIndex == 65535 || rowIndex == 0) +// { +// if (rowIndex != 0) +// { +// sheet = workbook.CreateSheet(); +// } + +// #region 表头及样式 +// { +// HSSFRow headerRow = sheet.CreateRow(0); +// headerRow.HeightInPoints = 25; +// headerRow.CreateCell(0).SetCellValue(table.Namespace); + +// HSSFCellStyle headStyle = workbook.CreateCellStyle(); +// headStyle.Alignment = CellHorizontalAlignment.CENTER; +// HSSFFont font = workbook.CreateFont(); +// font.FontHeightInPoints = 20; +// font.Boldweight = 700; +// headStyle.SetFont(font); + +// headerRow.GetCell(0).CellStyle = headStyle; + +// sheet.AddMergedRegion(new Region(0, 0, 0, table.Columns.Count - 1)); +// headerRow.Dispose(); +// } +// #endregion + + +// #region 列头及样式 +// { +// HSSFRow headerRow = sheet.CreateRow(1); + + +// HSSFCellStyle headStyle = workbook.CreateCellStyle(); +// headStyle.Alignment = CellHorizontalAlignment.CENTER; +// headStyle.BorderBottom = CellBorderType.THIN; +// headStyle.BorderLeft = CellBorderType.THIN; +// headStyle.BorderRight = CellBorderType.THIN; +// headStyle.BorderTop = CellBorderType.THIN; +// HSSFFont font = workbook.CreateFont(); +// font.FontHeightInPoints = 10; +// font.Boldweight = 700; +// headStyle.SetFont(font); + + +// foreach (DataColumn column in table.Columns) +// { +// headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); +// headerRow.GetCell(column.Ordinal).CellStyle = headStyle; + +// //设置列宽 +// sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); + +// } +// headerRow.Dispose(); +// } +// #endregion + +// rowIndex = 2; +// } +// #endregion + + +// #region 填充内容 +// foreach (DataColumn column in table.Columns) +// { +// HSSFRow dataRow = sheet.CreateRow(rowIndex); +// HSSFCell newCell = dataRow.CreateCell(column.Ordinal); + +// newCell.CellStyle.BorderBottom = CellBorderType.THIN; +// newCell.CellStyle.BorderLeft = CellBorderType.THIN; +// newCell.CellStyle.BorderRight = CellBorderType.THIN; +// newCell.CellStyle.BorderTop = CellBorderType.THIN; + +// string drValue = row[column].ToString(); + +// switch (column.DataType.ToString()) +// { +// case "System.String"://字符串类型 +// newCell.SetCellValue(drValue); +// break; +// case "System.DateTime"://日期类型 +// DateTime dateV; +// DateTime.TryParse(drValue, out dateV); +// newCell.SetCellValue(dateV); + +// newCell.CellStyle = dateStyle;//格式化显示 +// break; +// case "System.Boolean"://布尔型 +// bool boolV = false; +// bool.TryParse(drValue, out boolV); +// newCell.SetCellValue(boolV); +// break; +// case "System.Int16"://整型 +// case "System.Int32": +// case "System.Int64": +// case "System.Byte": +// int intV = 0; +// int.TryParse(drValue, out intV); +// newCell.SetCellValue(intV); +// break; +// case "System.Decimal"://浮点型 +// case "System.Double": +// double doubV = 0; +// double.TryParse(drValue, out doubV); +// newCell.SetCellValue(doubV); +// break; +// case "System.DBNull"://空值处理 +// newCell.SetCellValue(""); +// break; +// default: +// newCell.SetCellValue(""); +// break; +// } + +// } +// #endregion + +// rowIndex++; +// } +// } + + +// using (MemoryStream ms = new MemoryStream()) +// { +// workbook.Write(ms); +// ms.Flush(); +// ms.Position = 0; + +// //sheet.Dispose(); +// workbook.Dispose(); +// return ms; +// } +// } +// #endregion +// } +//} diff --git a/类库/Api.Framework/Tools/HTTPClass.cs b/类库/Api.Framework/Tools/HTTPClass.cs new file mode 100644 index 0000000..240f34f --- /dev/null +++ b/类库/Api.Framework/Tools/HTTPClass.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + + public class HTTPClass + { + + public Response HTTP(string _url, string _type, string _postdata, string _cookie, Encoding _responseEncode) + { + try + { + TcpClient clientSocket = new TcpClient(); + Uri URI = new Uri(_url); + clientSocket.Connect(URI.Host, URI.Port); + StringBuilder RequestHeaders = new StringBuilder(); + + RequestHeaders.Append(_type + " " + URI.PathAndQuery + " HTTP/1.1\r\n"); + RequestHeaders.Append("Content-Type:application/x-www-form-urlencoded\r\n"); + RequestHeaders.Append("User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11\r\n"); + RequestHeaders.Append("Cookie:" + _cookie + "\r\n"); + RequestHeaders.Append("Accept:*/*\r\n"); + RequestHeaders.Append("Host:" + URI.Host + "\r\n"); + RequestHeaders.Append("Content-Length:" + _postdata.Length + "\r\n"); + RequestHeaders.Append("Connection:close\r\n\r\n"); + + byte[] request = Encoding.UTF8.GetBytes(RequestHeaders.ToString() + _postdata); + clientSocket.Client.Send(request); + + byte[] responseByte = new byte[1024000]; + int len = clientSocket.Client.Receive(responseByte); + string result = Encoding.UTF8.GetString(responseByte, 0, len); + clientSocket.Close(); + int headerIndex = result.IndexOf("\r\n\r\n"); + string[] headerStr = result.Substring(0, headerIndex).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + Dictionary responseHeader = new Dictionary(); + for (int i = 0; i < headerStr.Length; i++) + { + string[] temp = headerStr[i].Split(new string[] { ": " }, StringSplitOptions.RemoveEmptyEntries); + if (temp.Length == 2) + { + if (responseHeader.ContainsKey(temp[0])) + { + responseHeader[temp[0]] = temp[1]; + } + else + { + responseHeader.Add(temp[0], temp[1]); + } + } + } + Response response = new Response(); + response.HTTPResponseHeader = responseHeader; + string[] httpstatus = headerStr[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); + if (httpstatus.Length > 2) + { + + response.HTTPStatusCode = httpstatus[1]; + } + else + { + + response.HTTPStatusCode = "400"; + } + response.HTTPResponseText = _responseEncode.GetString(Encoding.UTF8.GetBytes(result.Substring(headerIndex + 4))); + return response; + + } + catch + { + return null; + } + + } + + + } + + public class Response + { + + string hTTPStatusCode; + /// + /// http状态代码 + /// + public string HTTPStatusCode + { + get { return hTTPStatusCode; } + set { hTTPStatusCode = value; } + } + Dictionary hTTPResponseHeader; + /// + /// Response的header + /// + public Dictionary HTTPResponseHeader + { + get { return hTTPResponseHeader; } + set { hTTPResponseHeader = value; } + } + string hTTPResponseText; + /// + /// html代码 + /// + public string HTTPResponseText + { + get { return hTTPResponseText; } + set { hTTPResponseText = value; } + } + + + } +} diff --git a/类库/Api.Framework/Tools/IniHelper.cs b/类库/Api.Framework/Tools/IniHelper.cs new file mode 100644 index 0000000..5bf8ce1 --- /dev/null +++ b/类库/Api.Framework/Tools/IniHelper.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// ini配置文件操作类 + /// + public class IniHelper + { + [DllImport("kernel32")] + private static extern long WritePrivateProfileString(string section, string key, string val, string filepath); + [DllImport("kernel32")] + private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filePath); + + + //获取ini文件路径 + private string inifilepath; + + /// + /// ini文件完整路径 + /// + /// + public IniHelper(string fileName) + { + this.inifilepath = fileName; + } + + /// + /// 获取ini配置文件中指定key的数据 + /// + /// 头 + /// 头下面的key + /// + public string GetValue(string node, string key) + { + StringBuilder s = new StringBuilder(1024); + GetPrivateProfileString(node, key, "", s, 1024, inifilepath); + return s.ToString(); + } + + /// + /// 设置ini配置文件的字段 + /// + /// 头 + /// 键 + /// 值 + public void SetValue(string node, string key, string value) + { + try + { + WritePrivateProfileString(node, key, value, inifilepath); + } + catch (Exception ex) + { + throw ex; + } + } + } +} diff --git a/类库/Api.Framework/Tools/JDHelper.cs b/类库/Api.Framework/Tools/JDHelper.cs new file mode 100644 index 0000000..987819a --- /dev/null +++ b/类库/Api.Framework/Tools/JDHelper.cs @@ -0,0 +1,165 @@ +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 京东解析助手 + /// + public static class JDHelper + { + /// + /// 查找宝贝Id的正则表达式 + /// + private static string RegItemId = @"(?:item\.jd\.com/|item\.m\.jd\.com/product/|item\.jd\.hk/|jd(?:.*?)sku_id=|skuId=|re.jd.com/cps/item/|jd(?:.*?)[\?&]sku=|jd/dujia/item/|http(?:.*?)jd\.(?:.{0,15}?)|jd(?:.*?)wareId=|sku=|京东(?:[\w\W]*?)wareId=|wareId=)(?\d{4,})"; + + /// + /// 通过字符串获取京东商品id + /// + /// 包含京东链接的文本 + /// + public static string GetJingdongItemId(string str) + { + try + { + if (str.ToLower().Contains("taobao") || str.ToLower().Contains("detail.tmall") || str.ToLower().Contains("<![CDATA[微信红包]]>")) return string.Empty; + Match reg = null; + if (!str.ToLower().Contains("sq.jd.")) + { + reg = Regex.Match(str, RegItemId, RegexOptions.IgnoreCase); + if (reg.Success) + { + return reg.Groups["itemId"].Value;//京东宝贝ID + } + else + reg = null; + } + + if (reg == null) + { + if (!str.ToLower().Contains("sq.jd.")) + { + reg = Regex.Match(HttpHelper.URLDecode(str), RegItemId, RegexOptions.IgnoreCase); + if (reg.Success) + { + return reg.Groups["itemId"].Value;//京东宝贝ID + } + } + + str = Regex.Replace(str, "u.jd", "https://u.jd", RegexOptions.IgnoreCase); + var _url = HttpExtend.RegexMatchUrl(str); + if (string.IsNullOrWhiteSpace(_url)) + _url = HttpExtend.RegexMatch(str, @"""jumpUrl"":""(?<链接>http:[^""]+?)"""); + if (string.IsNullOrWhiteSpace(_url))//没有前缀https: + { + _url = HttpExtend.RegexMatchUrl(str); + } + if (!string.IsNullOrWhiteSpace(_url)) + { + var url = _url; + HttpHelper http = new HttpHelper(); + var item = http.GetItem(url); + var result = http.GetHtml(item); + var html = result.Html; + //reg = Regex.Match(html, @"(?:window._itemOnly\s*?=\s*?\({\s*?""item"": {""skuId"":""(?<宝贝Id>\d+?)"",)"); + if (str.Contains("taobao") || str.Contains("detail.tmall")) return string.Empty; + reg = Regex.Match(html, @"""skuId"":""(?<宝贝Id>\d+?)"""); + if (reg.Success) + { + return reg.Groups["宝贝Id"].ToString(); + } + else + { + reg = Regex.Match(html, @"hrl='(?<跳转A>.+?)';"); + if (reg.Success) + { + var skip = reg.Groups["跳转A"].ToString(); + item.URL = skip; + item.Referer = url; + item.Allowautoredirect = false; + result = http.GetHtml(item); + var header = result.Header; + var location = result.Header.Get("Location"); + if (location != null) + { + reg = Regex.Match(location, RegItemId, RegexOptions.IgnoreCase); + if (reg.Success) + { + return reg.Groups["itemId"].Value;//京东宝贝ID + } + } + } + else //http://3.cn/Vc0Avuc 这类链接 + { + var location = result.ResponseUri; + if (!string.IsNullOrWhiteSpace(location)) + { + var url1 = location.Substring(location.IndexOf("appurl=") + 7); + url1 = HttpHelper.URLDecode(url1); + item.URL = url1; + item.Referer = location; + item.Allowautoredirect = false; + result = http.GetHtml(item); + reg = Regex.Match(result.Html, @"hrl='(?.+?)';"); + if (reg.Success) + { + var hrl = reg.Groups["hrl"].Value; + item.URL = hrl; + item.Referer = hrl; + item.Allowautoredirect = false; + result = http.GetHtml(item); + + reg = Regex.Match(result.RedirectUrl, RegItemId, RegexOptions.IgnoreCase); + if (reg.Success) + { + return reg.Groups["itemId"].Value;//京东宝贝ID + } + } + } + + } + } + + http = new HttpHelper(); + item = new HttpItem() + { + URL = url, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Opera/9.27 (Windows NT 5.2; U; zh-cn)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "text/html", + Referer = "", + Postdata = "", + }; + result = http.GetHtml(item); + var _location = result.Header.Get("Location"); + if (!string.IsNullOrWhiteSpace(_location)) + { + reg = Regex.Match(_location, RegItemId, RegexOptions.IgnoreCase); + if (reg.Success) + { + return reg.Groups["itemId"].Value;//京东宝贝ID + } + } + + } + } + } + catch (Exception ex) + { + //throw ex; + } + return string.Empty; + } + + } +} diff --git a/类库/Api.Framework/Tools/KSHelper.cs b/类库/Api.Framework/Tools/KSHelper.cs new file mode 100644 index 0000000..f99e1aa --- /dev/null +++ b/类库/Api.Framework/Tools/KSHelper.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Microsoft.ClearScript.V8; +using Newtonsoft.Json.Linq; + +namespace Api.Framework.Tools +{ + /// + /// 快手解析助手 + /// + public class KSHelper + { + /// + /// 解析商品内容获取Id + /// + /// + /// + public static string GetItemId(string str, out string title) + { + #region 解析链接 + if (Regex.IsMatch(str, @"((?:https://a6chq\.ogwormb\.com)|(?:(https://ac31\.suvmothq\.com)))", RegexOptions.IgnoreCase)) + { + var url = HttpExtend.RegexMatchUrl(str); + str = CsharpHttpHelper.HttpExtend.GetLocationUrl(url); + } + + var reg = Regex.Match(str, + @"https:\/\/cps\.kwaixiaodian\.com\/page\/kwaimoney\/promotion\/goods\/detail\/(?<商品ID>\d+)", + RegexOptions.ExplicitCapture); + if (!reg.Success) + reg = Regex.Match(str, @"package-shop/pages/goods/main.*?[\?&]id=(?<商品ID>\d+)", + RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (!reg.Success) + reg = Regex.Match(str, @"page/kwaishop-buyer-goods-detail.*?[\?&]id=(?<商品ID>\d+)", + RegexOptions.IgnoreCase | RegexOptions.Multiline); + + if (reg.Success) + { + title = string.Empty; + return reg.Groups["商品ID"].Value; + } + #endregion + + #region 解析解析口令 + //##X7poMxtqkJLk21g## + + reg = Regex.Match(str, @"((?:##)|(?:[^a-zA-Z0-9-]))(?<口令>X[a-zA-Z0-9-]{13,15})((?:##)|(?:[^a-zA-Z0-9-]))", RegexOptions.IgnoreCase); + if (reg.Success) + { + var result = AnalysisKl(reg.Groups["口令"].Value); + //....解析操作 + + #region 数据结构 + + //{"result":1,"hostName":"zt-zl-rs296.idczw.hb1.kwaidc.com","cache-scope":"nocache","error_msg":null,"showDialog":{"originKpn":"KUAISHOU","originSubBiz":"GOODS_DETAILS_OF_NATIVE","kpn":"KUAISHOU","subBiz":"share","kwaiUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareToken=X7WKCOoS0M6bgoi&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","dialog":{"subTitle":"来快手看看这个商品吧","footerText":"来自好友的分享,查看他","actionButtonTargetUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","shareId":"16956809344990","footerTargetUrl":"kwai://profile/2430851481?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","shareObjectId":"4035974256190","iconUrl":"https://p3.eckwai.com/bs2/image-kwaishop-product/item-2763666190-185a99e1c95847b39e39ad59f34c94cf.jpg","iconTargetUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?fid=2430851481&cc=share_copylink&followRefer=151&shareMethod=TOKEN&kpn=KUAISHOU&subBiz=GOODS_DETAILS_OF_NATIVE&carrierType=24&shareId=16956809344990&shareMode=SYSTEM&originShareId=16956809344990&layoutType=4&shareObjectId=4035974256190&id=4035974256190&shareUrlOpened=0&carrierId=5×tamp=1653385982520","title":"1元 快乐旺哥草莓蛋糕【拼满19.9包邮发货】","actionButtonText":"去看看"},"oldShowType":0,"newShowTypes":["bigHeadDialog"],"extParams":{"kwaiUrl":"kwai://home","shareUrl":"/package-shop/pages/goods/main?id=4035974256190&layoutType=4&carrierType=24","iconUrl":"https://p3.eckwai.com/bs2/image-kwaishop-product/item-2763666190-185a99e1c95847b39e39ad59f34c94cf.jpg","title":"1元 快乐旺哥草莓蛋糕【拼满19.9包邮发货】","carrierId":"5","jumpUrl":"https://app.kwaixiaodian.com/merchant/shop/detail?id=4035974256190&layoutType=4&carrierType=24"}},"max-age":0} + + #endregion + + var jObj = JObject.Parse(result); + var jumpUrl = jObj?["showDialog"]?["dialog"]?["shareObjectId"]?.ToString(); + if (!string.IsNullOrWhiteSpace(jumpUrl)) + { + title = jObj?["showDialog"]?["dialog"]?["title"]?.ToString(); + return jumpUrl; + } + } + + + #endregion + + title = string.Empty; + return string.Empty; + } + + #region 快手口令解析 + /// + /// Post参数 + /// + static string postParam = $"kpf=ANDROID_PHONE&shareMessage=内容&kpn=KUAISHOU&sdkVersion=1.14.0.0&theme=light&sessionId=8a19a62f-fa3c-4097-aae4-cdf0ec11c59d&extTransientParams={{\"source\":\"autoDetectPasteboard\"}}&launchState=firstColdLaunchToday"; + /// + /// 参数2 + /// + static string getParam = "kpf=ANDROID_PHONE&ver=9.7&gid=&mod=HUAWEI%28HWI-AL00%29&c=OPPO&oDid=TEST_ANDROID_dd6f96475163fa32&android_os=0&os=android&appver=9.7.30.21320&boardPlatform=hi3660&ftt=&kpn=KUAISHOU&subBiz=share&androidApiLevel=28&language=zh-cn&sys=ANDROID_9&mcc=46007&userId=0&memoryTotalSize=5725&did_tag=0&countryCode=CN&rdid=&net=WIFI&did="; + + /// + /// 解析快手口令 + /// + /// + /// + public static string AnalysisKl(string content) + { + content = $"##{content}##"; + var sign = GetKlSign(content); + + var param = postParam.Replace("内容", content) + $"&sig={sign}"; + + var url = $"https://api.kuaishouzt.com/rest/zt/share/show/any?{getParam}"; + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = "post", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = param, + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = false, + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + //EventClient.OnEvent("", "口令解析:" + html); + return html; + } + + private static string GetKlSign(string content) + { + var paramC = $"{postParam.Replace("内容", content)}&{getParam}"; + + var deContent = System.Web.HttpUtility.UrlDecode(paramC); + + //var splits = deContent.Split('&').ToList(); + //splits.Sort(); + //var sortContent = string.Join("", splits); + + + byte[] deContentAAscii = Encoding.ASCII.GetBytes(deContent); + string deContentUtf8 = Encoding.UTF8.GetString(deContentAAscii); + + var sortContent = JsStrSort(deContentUtf8); + + var result = $"{sortContent}382700b563f4"; + + MD5 md5 = MD5.Create(); + var bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(result)); + + // 第五步:把二进制转化为大写的十六进制 + StringBuilder strb = new StringBuilder(); + for (int i = 0; i < bytes.Length; i++) + { + strb.Append(bytes[i].ToString("x2")); + } + + return strb.ToString(); + } + + private static string JsStrSort(string content) + { + return V8Method(JsSort, $"'{content}'", "getString"); + } + + /// + /// 使用V8引擎执行JS代码 + /// + /// JS代码 + /// 当前方法需要的参数 + /// 执行的JS方法名 + /// + private static string V8Method(string JsCode, string JsParam, string JsMethodName) + { + string result = string.Empty; + try + { + using (var engine = new V8ScriptEngine()) + { + V8Script script = engine.Compile(JsCode); + engine.Execute(script); + result = engine.ExecuteCommand(string.Format("{0}({1})", JsMethodName, JsParam)); + //其他写法 + } + } + catch (Exception ex) + { + //result = ex.Message.ToString(); + } + return result; + } + + private static string JsSort + { + get + { + return @"function getString(str){ + var array; + array = str.split('&'); + array.sort(); + return array.join(''); + }"; + } + + + } + #endregion + + + } +} diff --git a/类库/Api.Framework/Tools/KuaiZhanShort.cs b/类库/Api.Framework/Tools/KuaiZhanShort.cs new file mode 100644 index 0000000..37219b5 --- /dev/null +++ b/类库/Api.Framework/Tools/KuaiZhanShort.cs @@ -0,0 +1,125 @@ +using CsharpHttpHelper; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 快站短网址 + /// + public class KuaiZhanShort + { + /// + /// 快站缩短 + /// + /// + /// + public static string GetShort(string url) + { + try + { + var APP_KEY = "LFxURPXd0Qy3"; + var APP_SECRET = "94e50cce6317fa27360247e64e7ae48149a04b88"; + var pams = new Dictionary(); + pams.Add("url", url); + pams.Add("appKey", APP_KEY); + pams.Add("urlType", "default"); + var sign = signTopRequest(pams, APP_SECRET); + pams.Add("sign", sign); + + var Postdata = HttpExtend.BuildQuery(pams); + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = "https://cloud.kuaizhan.com/api/v1/tbk/genShortUrl", + Method = "post", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = Postdata, + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = false, + ProxyIp = "" + }; + var result = http.GetHtml(item); + + //{"code":200,"msg":"ok","data":{"shortUrl":"http://kzurl07.cn/tbKy"}} + var jobj = JObject.Parse(result.Html); + if (jobj != null) + { + if ((int)jobj["code"] == 200) + { + var data = (JObject)jobj["data"]; + return data["shortUrl"].ToString(); + } + else if ((int)jobj["code"] == 1001) + { + EventClient.OnEvent("短连接", "由于快站短连接接口请求的额度超限制,正在切换其他短连接"); + } + } + else + { + + } + } + catch (Exception ex) + { } + return url; + } + + /// + /// 计算快站的sign + /// + /// + /// + /// + private static String signTopRequest(Dictionary pams, String secret) + { + // 第一步:检查参数是否已经排序 + IDictionary sortedParams = new SortedDictionary(pams, StringComparer.Ordinal); + + // 第二步:把所有参数名和参数值串在一起 + var query = new StringBuilder(); + query.Append(secret); + + foreach (KeyValuePair kv in sortedParams) + { + if (!string.IsNullOrEmpty(kv.Key) && !string.IsNullOrEmpty(kv.Value) && "sign" != kv.Key) + query.Append(kv.Key).Append(kv.Value); + } + query.Append(secret); + var ss = query.ToString(); + // 第三步:使用MD5加密 + return GetMd5(query.ToString()); + } + + /// + /// MD5加密方法写法 + /// + /// 参数字符串 + /// + private static string GetMd5(string str) + { + MD5 md5 = MD5.Create(); + byte[] ba = Encoding.Default.GetBytes(str); + byte[] md55 = md5.ComputeHash(ba); + StringBuilder sb = new StringBuilder(); + for (int I = 0; I < md55.Length; I++) + { + sb.Append(md55[I].ToString("x2")); + } + return sb.ToString(); + } + + + } +} diff --git a/类库/Api.Framework/Tools/LogHelper.cs b/类库/Api.Framework/Tools/LogHelper.cs new file mode 100644 index 0000000..28a770f --- /dev/null +++ b/类库/Api.Framework/Tools/LogHelper.cs @@ -0,0 +1,161 @@ +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Utils +{ + /// + /// 日志参数类 + /// + internal sealed class LogParameter + { +        /// +        /// 日志等级 +        /// +        public int LogGrade { get; set; } + + /// +         /// 日志类型 +         /// + public string LogType { get; set; } + + /// +         /// 日志记录类名和方法名(className/methodName) +         /// + public string LogName { get; set; } + + /// +         /// 日志记录文本内容 +         /// + public string LogContent { get; set; } + } + + /// + /// 自定义之日助手 + /// + public sealed class LogHelper + { + #region 单利模式 + //创建私有静态字段,接收类的实例化对象 + private static readonly LogHelper _LogHelper = null; + //构造函数私有化 + internal LogHelper() { } + //静态构造函数,创建单利对象资源 + static LogHelper() + { + _LogHelper = new LogHelper(); + } + + //获取单利对象资源 + public static LogHelper GetSingleObj() + { + return _LogHelper; + } + #endregion + + /// + /// 日志等级 + /// + private enum LogType { ERROR = 1, INFO = 2, DEBUG = 3, SQLMAN = 4 }; + + /// + /// 指定日志文件夹(项目跟路劲文件夹) + /// + public string Path { get; set; } + + /// + /// 向日志文件写入调试信息 + /// + /// 类名/方法名 + /// 日志记录内容 + public void Debug(string logName, string logContent) + { + try + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.DEBUG, LogType = nameof(LogType.DEBUG), LogName = logName, LogContent = logContent }); + } + catch (Exception) + { } + } + + public void SqlMan(string logName, string logContent) + { + try + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.SQLMAN, LogType = nameof(LogType.SQLMAN), LogName = logName, LogContent = logContent }); + } + catch (Exception) + { } + } + + + /// + /// 向日志文件写入运行时信息 + /// + /// 类名/方法名 + /// 日志记录内容 + public void Info(string logName, string logContent) + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.INFO, LogType = nameof(LogType.INFO), LogName = logName, LogContent = logContent }); + } + + /// + /// 向日志文件写入出错信息 + /// + /// 类名/方法名 + /// 日志记录内容 + public void Error(string logName, string logContent) + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.ERROR, LogType = nameof(LogType.ERROR), LogName = logName, LogContent = logContent }); + } + + /// + /// 实际的写日志操作 + /// + /// 日志参数model + private void WriteLog(LogParameter _logParameter) + { + var logParameter = _logParameter; + var m = new Action(delegate () + //Task.Factory.StartNew(delegate () + { + try + { + string filename = string.Empty; + if (_logParameter.LogType == "SQLMAN") + filename = CsharpHttpHelper.HttpExtend.MapFile($"{DateTime.Now.ToString("yyyy-MM-dd HH")}.log", "Cache\\SQLMAN"); + else + filename = CsharpHttpHelper.HttpExtend.MapFile($"{DateTime.Now.ToString("yyyy-MM-dd HH")}.log", "Cache\\" + _logParameter.LogType); + #region 原始写法 + //创建或打开日志文件,向日志文件末尾追加记录 + //StreamWriter mySw = File.AppendText(filename); + + //向日志文件写入内容 + //string writeContent = time + "|" + typeGrade + ":" + type + "|" + className + ":" + content; + //mySw.WriteLine(writeContent); + + //关闭日志文件 + //mySw.Close(); + #endregion + + //(优化写法)创建或打开日志文件,向日志文件末尾追加记录,关闭日志文件 + using (StreamWriter mySw = File.AppendText(filename)) + { + string writeContent = $"{DateTime.Now.ToString("HH:mm:ss")}---{logParameter.LogGrade}|{logParameter.LogType}|{logParameter.LogName}---{logParameter.LogContent}"; + mySw.WriteLine(writeContent);//向日志文件写入内容 + mySw.Close(); //关闭日志文件 + } + } + catch (Exception) + { + } + }); + m.BeginInvoke(null, null); + } + } + +} diff --git a/类库/Api.Framework/Tools/Nopi/Assistant.cs b/类库/Api.Framework/Tools/Nopi/Assistant.cs new file mode 100644 index 0000000..28cba01 --- /dev/null +++ b/类库/Api.Framework/Tools/Nopi/Assistant.cs @@ -0,0 +1,251 @@ +using System; +using System.Text; +using System.Configuration; +using System.Web.UI.WebControls; +using System.IO; +using System.Web; +using System.Net; +using Newtonsoft.Json; +using System.Web.UI; +using System.Web.Hosting; + +namespace Eson.Utils +{ + /// + /// 文件操作帮助类 + /// + public class Assistant + { + /// + ///删除指定目录下的所有文件 + /// + /// 目录 + public static void Deletes(string srcPath) + { + try + { + string[] fileList = Directory.GetFileSystemEntries(srcPath);//获取目录下所有文件目录和文件 + + foreach (string file in fileList) + { + string pt = file; + //检查是否含有"\\"字符 + if (pt.IndexOf("\\") > -1) + { + pt = pt.Replace("\\", "/");//把"\\"替换成"/" + } + + //检查是否为目录 + if (Directory.Exists(pt)) + { + if (pt.IndexOf("App_Data") > -1) //检查目录名是否为"App_Data" 如果是不执行操作 + { } + else if (pt.IndexOf("Admin") > -1)//检查目录名是否为"Admin" 如果是不执行操作 + { } + else + { + //删除该目录及目录下所有文件 + Directory.Delete(pt, true); + } + } + else + { + //删除文件 + File.Delete(pt); + } + + } + } + catch + { + + } + } + + /// + /// 在执行完导入操作后,删除导入过程中临时存放的导入文件 + /// + /// + public static void DeleteFileOfImport(string importFilePath) + { + if (Convert.ToBoolean(ConfigurationManager.AppSettings["ImportPathDel"])) + { + //删除文件 + try + { + System.IO.File.Delete(importFilePath); + } + catch { } + } + } + + /// + /// 检查是否存在某文件,存在则删除 + /// + /// 文件路径 + public static void DeleteFile(string strFilePath) + { + if (File.Exists(strFilePath)) + { + try + { + File.Delete(strFilePath); + } + catch { } + } + } + + /// + /// 上传文件 + /// + /// 上传控件 + /// 文件路径 + /// 文件上层文件夹路径 + public static void SaveFile(FileUpload fuXls, out string strFilePath, string strPath) + { + string virtualPath = ConfigurationManager.AppSettings[strPath] + fuXls.FileName; + strFilePath = System.Web.HttpContext.Current.Server.MapPath(virtualPath); + DeleteFile(strFilePath); + fuXls.SaveAs(strFilePath); + } + + /// + /// 上传文件 + /// + /// 上传控件 + /// 文件上层文件夹路径 + /// 文件名称(默认为空) + public static string UpLoadFile(FileUpload fuXls, string strPath, string saveName = "") + { + try + { + string fileName = fuXls.FileName; + string extension = System.IO.Path.GetExtension(fileName).ToLower(); + if (string.IsNullOrEmpty(saveName)) + { + saveName = GetRandomCode(15); + } + saveName = saveName + extension; + string strFilePath = string.Empty; + string virtualPath = strPath + saveName; + strFilePath = System.Web.HttpContext.Current.Server.MapPath(virtualPath); + DeleteFile(strFilePath); + fuXls.SaveAs(strFilePath); + return strFilePath; + } + catch (Exception ex) + { + throw ex; + } + } + + #region 从字符串里随机得到,规定个数的字符串 + + /// + /// 从字符串里随机得到,规定个数的字符串. + /// + /// + /// + /// + public static string GetRandomCode(int CodeCount) + { + string allChar = "1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,i,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z"; + string[] allCharArray = allChar.Split(','); + string RandomCode = ""; + int temp = -1; + Random rand = new Random(); + for (int i = 0; i < CodeCount; i++) + { + if (temp != -1) + { + rand = new Random(temp * i * ((int)DateTime.Now.Ticks)); + } + + int t = rand.Next(allCharArray.Length - 1); + + while (temp == t) + { + t = rand.Next(allCharArray.Length - 1); + } + + temp = t; + RandomCode += allCharArray[t]; + } + return RandomCode; + } + + #endregion + + #region 记录日志 + /// + /// 根据路径创建文件 + /// + /// 文件路径 + public static void CreateLog(string realPath) + { + StreamWriter SW; + SW = File.CreateText(realPath); + //SW.WriteLine(string.Format("支付宝回调: {0}", DateTime.Now.ToString("dd-MM-yyyy hh:mm:ss"))); + SW.Close(); + } + + /// + /// 向文件写入数据 + /// + /// 内容 + /// 文件路径 + public static void WriteLog(string content, string realPath) + { + using (StreamWriter SW = File.AppendText(realPath)) + { + SW.WriteLine(content); + SW.Close(); + } + } + #endregion + + #region 获取虚拟目录根目录 + /// + /// 获取虚拟目录根目录 + /// + public static string SiteRoot + { + get + { + HttpRequest request = HttpContext.Current.Request; + string root = request.ApplicationPath; + if (root == "/") return root; + else return root + "/"; + } + } + #endregion + } + + /// + /// 文件上传操作结果返回类 + /// + public class FileUpLoadMsgInfo + { + public FileUpLoadMsgInfo() + { + IsSuccess = true; + FilePath = string.Empty; + Msg = "操作成功"; + } + + /// + /// 是否上传成功 + /// + public bool IsSuccess { get; set; } + + /// + /// 上传好的文件路径 + /// + public string FilePath { get; set; } + + /// + /// 消息 + /// + public string Msg { get; set; } + } +} diff --git a/类库/Api.Framework/Tools/Nopi/ExcelFileExport.cs b/类库/Api.Framework/Tools/Nopi/ExcelFileExport.cs new file mode 100644 index 0000000..baab46e --- /dev/null +++ b/类库/Api.Framework/Tools/Nopi/ExcelFileExport.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections.Generic; +using NPOI.XSSF.UserModel; +using NPOI.SS.UserModel; +using NPOI.HSSF.UserModel; +using System.IO; +using System.Data; +using System.Web; + +namespace Eson.Utils.ExcelHelper +{ + /// + /// 导出Excel帮助类(文件模板形式,特殊样式时,可自己设置模板) + /// + public class ExcelFileExport + { + + private static ExcelFileExport _instance; + /// + /// 实例化导出Excel帮助类 + /// + /// + public static ExcelFileExport GetInstance() + { + if (_instance == null) + _instance = new ExcelFileExport(); + return _instance; + } + + public IWorkbook workBook; + public ISheet workSheet; + + #region Excel文件基本操作 + /// + /// 初始化工作簿(Book) + /// + /// 文件名称,也作为工作簿名称 + /// 是否导出2007以上版本的Excel + public void InitializeWorkbook(string strSaveName, bool is07Excel) + { + FileStream file = new FileStream(strSaveName, FileMode.Open, FileAccess.Read); + workBook = is07Excel ? (new XSSFWorkbook(file) as IWorkbook) : (new HSSFWorkbook(file) as IWorkbook); + GetSheetByIndex(null); + } + + /// + /// 按序号打开工作表(Sheet) + /// + /// 工作表序号,为空时默认第一个工作表 + public void GetSheetByIndex(int? intSheetIndex) + { + if (intSheetIndex == null) + workSheet = workBook.GetSheetAt(0); + else + workSheet = workBook.GetSheetAt(Convert.ToInt32(intSheetIndex)); + } + + /// + /// 按名称打开工作表(Sheet) + /// + /// 工作表名称 + public void GetSheetByName(string strSheetName) + { + workSheet = workBook.GetSheet(strSheetName); + } + + /// + /// 初始化工作簿,自动打开第intSheetIndex个Sheet(intSheetIndex默认为0) + /// + /// 原Excel文件路径 + /// 第几个Sheet,默认为0 + /// 是否导出2007以上版本的Excel + public void GetSheetFromExcel(string strExcelFilePath, int? intSheetIndex, bool is07Excel) + { + InitializeWorkbook(strExcelFilePath, is07Excel); + GetSheetByIndex(intSheetIndex); + } + + /// + /// 将工作簿写入文件 + /// 如果目标文件已经存在,先删除 + /// + /// 要保存的文件地址 + public void WriteToFile(string strSaveFilePath) + { + FileInfo fi = new FileInfo(strSaveFilePath); + if (fi.Exists) + fi.Delete(); + FileStream fs = new FileStream(strSaveFilePath, FileMode.Create); + workBook.Write(fs); + fs.Close(); + } + + ///// + ///// 导出Excel文件 + ///// + ///// 文件路径 + ///// 保存名称 + ///// 是否导出2007以上版本的Excel + //public void SaveExcel(string strSaveFilePath, string strSaveName, bool is07Excel) + //{ + // WriteToFile(strSaveFilePath); + // Assistant.ToExcel(strSaveFilePath, strSaveName, is07Excel); + //} + + #endregion + + + #region 写数据到excel文件 + /// + /// 导出Excel,传入泛型数据 + /// + /// T类型 + /// 泛型 + /// 想要转换的属性名称列表[key值对应Model属性,value值对应Excel显示的列名] + /// 保存名称 + /// 是否导出2007以上版本的Excel,默认是 + /// 模板路径(默认不传入时使用默认模板,需要特殊样式时使用自己设置好样式的模板,模板统一放在EXCELFILE下,可在其下另建文件夹,注意模板名称去掉后缀再传入) + //public void WriteListDate(List lst, Dictionary dicProperties, string strSaveName, bool is07Excel = true, string deamoPath = null) + // where T : class + //{ + // #region 初始化工作簿 + // string strSaveFilePath = System.Web.HttpContext.Current.Server.MapPath("~/EXCELFILE/" + Guid.NewGuid().ToString() + (is07Excel ? ".xlsx" : ".xls")); + // File.Copy(System.Web.HttpContext.Current.Server.MapPath(string.Format("~/EXCELFILE/{0}{1}", string.IsNullOrEmpty(deamoPath) ? "demo" : deamoPath, is07Excel ? ".xlsx" : ".xls")), strSaveFilePath); + // InitializeWorkbook(strSaveFilePath, is07Excel); + + // //转换数据 + // DataTable dtbl = ExtensiveHelper.ConvertListToTable(lst, dicProperties); + + // //初始化行 + // int rowIndex = 0; + // int intColumn = 0; + // IRow rowExcel = workSheet.CreateRow(rowIndex); + // ICell cellExcel; + + // //初始化列 + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumn); + // cellExcel.SetCellValue(property.Value); + // ++intColumn; + // } + // #endregion + + // #region 写入内容 + // foreach (DataRow rowInfo in dtbl.Rows) + // { + // ++rowIndex; + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumnContent = 0; + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumnContent); + // cellExcel.SetCellValue(rowInfo[property.Value].ToString()); + // ++intColumnContent; + // } + // } + // #endregion + + // //模板流导出 + // SaveExcel(strSaveFilePath, strSaveName, is07Excel); + //} + + + /// + /// 输出Excel文件 + /// + /// MemoryStream内存流 + /// 文件保存名称 + /// 是否导出2007以上版本的Excel + //private void ExportExcel(MemoryStream ms, string strSaveName, bool is07Excel) + //{ + // ms.Flush(); + // ms.Position = 0; + // workBook.Write(ms); + // workBook = null; + // HttpContext current = HttpContext.Current; + // current.Response.ContentType = "application/ms-excel"; + // current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + UrlOper.GetToExcelName(strSaveName) + (is07Excel ? ".xlsx" : ".xls")); + // current.Response.BinaryWrite(ms.ToArray()); + // current.Response.End(); + // ms.Close(); + // ms = null; + //} + + /// + /// 导出Excel,传入DataTable内存表 + /// + /// DataTabke内存表 + /// 想要转换的属性名称列表[key值对应Model属性,value值对应Excel显示的列名] + /// 保存名称 + /// 是否导出2007以上版本的Excel,默认是 + /// 模板路径(默认不传入时使用默认模板,需要特殊样式时使用自己设置好样式的模板,模板统一放在EXCELFILE下,可在其下另建文件夹,注意模板名称去掉后缀再传入) + //public void WriteListDate(DataTable dtbl, Dictionary dicProperties, string strSaveName, bool is07Excel = true, string deamoPath = null) + //{ + // #region 初始化工作簿 + // string strSaveFilePath = System.Web.HttpContext.Current.Server.MapPath("~/EXCELFILE/" + Guid.NewGuid().ToString() + (is07Excel ? ".xlsx" : ".xls")); + // File.Copy(System.Web.HttpContext.Current.Server.MapPath(string.Format("~/EXCELFILE/{0}{1}", string.IsNullOrEmpty(deamoPath) ? "demo" : deamoPath, is07Excel ? ".xlsx" : ".xls")), strSaveFilePath); + // InitializeWorkbook(strSaveFilePath, is07Excel); + + // //初始化行 + // int rowIndex = 0; + // int intColumn = 0; + // IRow rowExcel = workSheet.CreateRow(rowIndex); + // ICell cellExcel; + + // //初始化列 + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumn); + // cellExcel.SetCellValue(property.Value); + // ++intColumn; + // } + // #endregion + + // #region 写入内容 + // foreach (DataRow rowInfo in dtbl.Rows) + // { + // ++rowIndex; + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumnContent = 0; + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumnContent); + // cellExcel.SetCellValue(GetColumValue(dtbl, rowInfo, property.Key)); + // ++intColumnContent; + // } + // } + // #endregion + + // //模板流导出 + // SaveExcel(strSaveFilePath, strSaveName, is07Excel); + //} + + /// + /// 通过提供的列名和具体行,返回DataTable中具体的某一列的值 + /// + /// 内存表 + /// 具体行 + /// 列名 + /// 具体某列的值 + public string GetColumValue(DataTable dtbl, DataRow rowInfo, string columName) + { + string clumValue = ""; + foreach (DataColumn clum in dtbl.Columns) + { + if (clum.ColumnName.Equals(columName)) + { + clumValue = rowInfo[clum].ToString(); + break; + } + } + return clumValue; + } + + /// + /// 将DataTable导出成Excel文件 + /// + /// DataTabke内存表泛型 + /// 字典泛型,想要转换的属性名称列表[key值对应Model属性,value值对应Excel显示的列名] + /// 保存名称 + /// 换行数,表之间的间距,不换行可以默认输入null,也可以输入0 + /// 是否导出2007以上版本的Excel,默认是 + /// 模板路径(默认不传入时使用默认模板,需要特殊样式时使用自己设置好样式的模板,模板统一放在EXCELFILE下,可在其下另建文件夹,注意模板名称去掉后缀再传入) + //public void WriteListDate(List lstDtbl, List> lstDicProperties, string strSaveName, int? intLineCount, bool is07Excel = true, string deamoPath = null) + //{ + // #region 初始化工作簿 + // string strSaveFilePath = System.Web.HttpContext.Current.Server.MapPath("~/EXCELFILE/" + Guid.NewGuid().ToString() + (is07Excel ? ".xlsx" : ".xls")); + // File.Copy(System.Web.HttpContext.Current.Server.MapPath(string.Format("~/EXCELFILE/{0}.{1}", string.IsNullOrEmpty(deamoPath) ? "demo" : deamoPath, is07Excel ? ".xlsx" : ".xls")), strSaveFilePath); + // InitializeWorkbook(strSaveFilePath, is07Excel); + + // //初始化行 + // int rowIndex = 0; + // IRow rowExcel; + // ICell cellExcel; + + // #endregion + + // #region 写内容 + // for (int i = 0; i < lstDicProperties.Count; i++) + // { + // //写表头 + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumn = 0; + // foreach (KeyValuePair property in lstDicProperties[i]) + // { + // cellExcel = rowExcel.CreateCell(intColumn); + // cellExcel.SetCellValue(property.Value); + // ++intColumn; + // } + + // //写入内容 + // foreach (DataRow rowInfo in lstDtbl[i].Rows) + // { + // ++rowIndex; + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumnContent = 0; + // foreach (KeyValuePair property in lstDicProperties[i]) + // { + // cellExcel = rowExcel.CreateCell(intColumnContent); + // cellExcel.SetCellValue(GetColumValue(lstDtbl[i], rowInfo, property.Key)); + // ++intColumnContent; + // } + // } + + // ++rowIndex; + + // //换行 + // rowIndex += intLineCount == null ? 0 : Convert.ToInt32(intLineCount); + // } + // #endregion + + // //模板流导出 + // SaveExcel(strSaveFilePath, strSaveName, is07Excel); + //} + #endregion + } +} diff --git a/类库/Api.Framework/Tools/Nopi/ExcelHelper.cs b/类库/Api.Framework/Tools/Nopi/ExcelHelper.cs new file mode 100644 index 0000000..66fb412 --- /dev/null +++ b/类库/Api.Framework/Tools/Nopi/ExcelHelper.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Eson.Utils.ExcelHelper +{ + /// + /// Excel导出帮助类 + /// + public class ExcelHelper + { + private static ExcelHelper _instance; + /// + /// 实例化导出Excel帮助类 + /// + /// + public static ExcelHelper GetInstance() + { + if (_instance == null) + _instance = new ExcelHelper(); + return _instance; + } + + /// + /// 调用Excel模板形式导出Excel(在需要特殊样式时可使用自己设置好样式的模板导出Excel,通常情况下建议使用内存流形式导出) + /// + /// + public ExcelFileExport ExportWithFile() + { + return new ExcelFileExport(); + } + + /// + /// 调用内存流形式导出Excel + /// + /// + public ExcelStreamExport ExportWithStream() + { + return new ExcelStreamExport(); + } + } +} diff --git a/类库/Api.Framework/Tools/Nopi/ExcelStream.cs b/类库/Api.Framework/Tools/Nopi/ExcelStream.cs new file mode 100644 index 0000000..90fb983 --- /dev/null +++ b/类库/Api.Framework/Tools/Nopi/ExcelStream.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using NPOI.XSSF.UserModel; +using NPOI.SS.UserModel; +using NPOI.HSSF.UserModel; +using System.IO; +using System.Data; +using System.Web; +namespace Eson.Utils.ExcelHelper +{ + public sealed class ExcelStream : IDisposable + { + public void Dispose() + { + workSheet = null; + workBook = null; + } + + public IWorkbook workBook; + public ISheet workSheet; + + public ExcelStream() : this(null, true) + { + + } + + public ExcelStream(string sheetname, bool is07Excel) + { + workBook = is07Excel ? (new XSSFWorkbook() as IWorkbook) : (new HSSFWorkbook() as IWorkbook); + if (!string.IsNullOrEmpty(sheetname)) + workSheet = workBook.CreateSheet(sheetname); + else + workSheet = workBook.CreateSheet(); + + //_cellStyle = GetDefaultCellStyle(); + } + + /// + /// 导出Excel,传入DataTable内存表 + /// + /// DataTabke内存表 + /// 想要转换的属性名称列表[key值对应Model属性,value值对应Excel显示的列名] + /// 保存名称 + /// 是否导出2007以上版本的Excel,默认是 + //public void WriteListDate(DataTable dtbl, Dictionary dicProperties, string strSaveName, bool is07Excel = true) + //{ + // #region 初始化工作簿 + // //InitializeWorkbook(strSaveName, is07Excel); + + // //初始化行 + // int rowIndex = 0; + // int intColumn = 0; + // IRow rowExcel = workSheet.CreateRow(rowIndex); + // ICell cellExcel; + + // //初始化列 + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumn); + // cellExcel.SetCellValue(property.Value); + // ++intColumn; + // } + // #endregion + + // #region 写入内容 + // foreach (DataRow rowInfo in dtbl.Rows) + // { + // ++rowIndex; + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumnContent = 0; + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumnContent); + // cellExcel.SetCellValue(GetColumValue(dtbl, rowInfo, property.Key)); + // ++intColumnContent; + // } + // } + // #endregion + + // //内存流导出 + // MemoryStream ms = new MemoryStream(); + // ExportExcel(ms, strSaveName, is07Excel); + //} + + /// + /// 通过提供的列名和具体行,返回DataTable中具体的某一列的值 + /// + /// 内存表 + /// 具体行 + /// 列名 + /// 具体某列的值 + public string GetColumValue(DataTable dtbl, DataRow rowInfo, string columName) + { + string clumValue = ""; + foreach (DataColumn clum in dtbl.Columns) + { + if (clum.ColumnName.Equals(columName)) + { + clumValue = rowInfo[clum].ToString(); + break; + } + } + return clumValue; + } + + /// + /// 输出Excel文件 + /// + /// MemoryStream内存流 + /// 文件保存名称 + /// 是否导出2007以上版本的Excel + //private void ExportExcel(MemoryStream ms, string strSaveName, bool is07Excel) + //{ + // try + // { + // //MemoryStream ms1 = new MemoryStream(); + // ////ms.Flush(); + // ////ms.Position = 0; + // //workBook.Write(ms1); + + // //string filename = UrlOper.GetToExcelName(strSaveName) + (is07Excel ? ".xlsx" : ".xls"); + // //Stream stream = ms1; + // //FileDownload.ExportFile(stream, filename); + + // ////ms.Close(); + // //ms = null; + // //workBook = null; + + // //ms.Flush(); + // //ms.Position = 0; + // //workBook.Write(ms); + // //workBook = null; + // //HttpContext current = HttpContext.Current; + // //current.Response.ContentEncoding = System.Text.Encoding.UTF8; + // //current.Response.ContentType = "application/ms-excel"; + // //current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + UrlOper.GetToExcelName(strSaveName) + (is07Excel ? ".xlsx" : ".xls")); + // //current.Response.BinaryWrite(ms.ToArray()); + // //ms.Close(); + // //ms = null; + // //current.Response.Flush(); + // //current.Response.Close(); + + // HttpContext current = HttpContext.Current; + // current.Response.Clear(); + // current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + // current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", UrlOper.GetToExcelName(strSaveName) + ".xlsx")); + // //System.IO.MemoryStream ms = new System.IO.MemoryStream(); + // workBook.Write(ms); + // current.Response.BinaryWrite(ms.ToArray()); + + // current.Response.Flush(); + // current.Response.End(); + // } + // catch (Exception ex) { } + //} + } +} diff --git a/类库/Api.Framework/Tools/Nopi/ExcelStreamExport.cs b/类库/Api.Framework/Tools/Nopi/ExcelStreamExport.cs new file mode 100644 index 0000000..99b7891 --- /dev/null +++ b/类库/Api.Framework/Tools/Nopi/ExcelStreamExport.cs @@ -0,0 +1,665 @@ +using System; +using System.Collections.Generic; +using NPOI.XSSF.UserModel; +using NPOI.SS.UserModel; +using NPOI.HSSF.UserModel; +using System.IO; +using System.Data; +using System.Web; + +namespace Eson.Utils.ExcelHelper +{ + /// + /// 导出Excel帮助类(内存流形式) + /// + public class ExcelStreamExport + { + private static ExcelStreamExport _instance; + /// + /// 实例化导出Excel帮助类 + /// + /// + public static ExcelStreamExport GetInstance() + { + if (_instance == null) + _instance = new ExcelStreamExport(); + return _instance; + } + + public IWorkbook workBook; + public ISheet workSheet; + public MemoryStream ms; + + #region Excel文件基本操作 + /// + /// 初始化工作簿(Book) + /// + /// 文件名称,也作为工作簿名称 + /// 是否导出2007以上版本的Excel + public void InitializeWorkbook(string strSaveName, bool is07Excel) + { + //内存流导出 + workBook = is07Excel ? (new XSSFWorkbook() as IWorkbook) : (new HSSFWorkbook() as IWorkbook); + ms = new MemoryStream(); + workSheet = workBook.CreateSheet(strSaveName); + } + + /// + /// 初始化工作簿(Book) + /// + /// 文件名称,也作为工作簿名称 + /// 是否导出2007以上版本的Excel(默认是) + /// 是否第一次创建Excel的Sheet页(默认是) + public void InitializeWorkSheet(string strSaveName, bool is07Excel = true, bool isFirstCreateSheet = true) + { + //内存流导出 + workBook = is07Excel ? (new XSSFWorkbook() as IWorkbook) : (new HSSFWorkbook() as IWorkbook); + if (isFirstCreateSheet) + { + ms = new MemoryStream(); + } + + workSheet = workBook.CreateSheet(strSaveName); + } + + /// + /// 按序号打开工作表(Sheet) + /// + /// 工作表序号,为空时默认第一个工作表 + public void GetSheetByIndex(int? intSheetIndex) + { + if (intSheetIndex == null) + workSheet = workBook.GetSheetAt(0); + else + workSheet = workBook.GetSheetAt(Convert.ToInt32(intSheetIndex)); + } + + /// + /// 按名称打开工作表(Sheet) + /// + /// 工作表名称 + public void GetSheetByName(string strSheetName) + { + workSheet = workBook.GetSheet(strSheetName); + } + + /// + /// 初始化工作簿,自动打开第intSheetIndex个Sheet(intSheetIndex默认为0) + /// + /// 原Excel文件路径 + /// 第几个Sheet,默认为0 + /// 是否导出2007以上版本的Excel + public void GetSheetFromExcel(string strExcelFilePath, int? intSheetIndex, bool is07Excel) + { + InitializeWorkbook(strExcelFilePath, is07Excel); + GetSheetByIndex(intSheetIndex); + } + + /// + /// 将工作簿写入文件 + /// 如果目标文件已经存在,先删除 + /// + /// 要保存的文件地址 + public void WriteToFile(string strSaveFilePath) + { + FileInfo fi = new FileInfo(strSaveFilePath); + if (fi.Exists) + fi.Delete(); + FileStream fs = new FileStream(strSaveFilePath, FileMode.Create); + workBook.Write(fs); + fs.Close(); + } + + #endregion + + + #region 写数据到excel文件 + /// + /// 导出Excel,传入泛型数据 + /// + /// T类型 + /// 泛型 + /// 想要转换的属性名称列表[key值对应Model属性,value值对应Excel显示的列名] + /// 保存名称 + /// 是否导出2007以上版本的Excel,默认是 + //public void WriteListDate(List lst, Dictionary dicProperties, string strSaveName, bool is07Excel = true) + // where T : class + //{ + // #region 初始化工作簿 + // InitializeWorkbook(strSaveName, is07Excel); + + // //转换数据 + // DataTable dtbl = ExtensiveHelper.ConvertListToTable(lst, dicProperties); + + // //初始化行 + // int rowIndex = 0; + // int intColumn = 0; + // IRow rowExcel = workSheet.CreateRow(rowIndex); + // ICell cellExcel; + + // //初始化列 + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumn); + // cellExcel.SetCellValue(property.Value); + // ++intColumn; + // } + // #endregion + + // #region 写入内容 + // foreach (DataRow rowInfo in dtbl.Rows) + // { + // ++rowIndex; + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumnContent = 0; + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumnContent); + // cellExcel.SetCellValue(rowInfo[property.Value].ToString()); + // ++intColumnContent; + // } + // } + // #endregion + + // //内存流导出 + // ExportExcel(ms, strSaveName, is07Excel); + //} + + + /// + /// 输出Excel文件 + /// + /// MemoryStream内存流 + /// 文件保存名称 + /// 是否导出2007以上版本的Excel + //private void ExportExcel(MemoryStream ms, string strSaveName, bool is07Excel) + //{ + // try + // { + // ms.Flush(); + // ms.Position = 0; + // workBook.Write(ms); + // workBook = null; + // HttpContext current = HttpContext.Current; + // current.Response.ContentType = "application/ms-excel"; + // current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + UrlOper.GetToExcelName(strSaveName) + (is07Excel ? ".xlsx" : ".xls")); + // current.Response.BinaryWrite(ms.ToArray()); + // ms.Close(); + // ms = null; + // current.Response.Flush(); + // current.Response.End(); + // //current.Response.Close(); + // } + // catch (Exception ex) { } + //} + + #region 导出Excel,传入DataTable内存表 + /// + /// 导出Excel,传入DataTable内存表 + /// + /// DataTabke内存表 + /// 想要转换的属性名称列表[key值对应Model属性,value值对应Excel显示的列名] + /// 保存名称 + /// 是否导出2007以上版本的Excel,默认是 + //public void WriteListDate(DataTable dtbl, Dictionary dicProperties, string strSaveName, bool is07Excel = true) + //{ + // #region 初始化工作簿 + // InitializeWorkbook(strSaveName, is07Excel); + + // //初始化行 + // int rowIndex = 0; + // int intColumn = 0; + // IRow rowExcel = workSheet.CreateRow(rowIndex); + // ICell cellExcel; + + // //初始化列 + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumn); + // cellExcel.SetCellValue(property.Value); + // ++intColumn; + // } + // #endregion + + // #region 写入内容 + // foreach (DataRow rowInfo in dtbl.Rows) + // { + // ++rowIndex; + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumnContent = 0; + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumnContent); + // cellExcel.SetCellValue(GetColumValue(dtbl, rowInfo, property.Key)); + // ++intColumnContent; + // } + // } + // #endregion + + // //内存流导出 + // ExportExcel(ms, strSaveName, is07Excel); + //} + #endregion + + #region 传入多张DataTable内存表数据,导出Excel + /// + /// 传入多张DataTable内存表数据,导出Excel + /// + /// DataTabke内存表泛型数据 + /// 保存名称 + /// 导出excel每页数据的Sheet名称(不传入则按照dtblList的序号展示) + /// 是否导出2007以上版本的Excel,默认是 + //public void WriteListDate(List dtblList, string strSaveName = null, List sheetNameList = null, bool is07Excel = true) + //{ + // #region Excel每月Sheet名称初始化 + // if (sheetNameList == null || (sheetNameList != null && dtblList.Count < sheetNameList.Count)) + // { + // sheetNameList = new List(); + // for (var i = 1; i < dtblList.Count + 1; i++) + // { + // sheetNameList.Add(string.Format("数据表_{0}", i)); + // } + // } + // if (string.IsNullOrEmpty(strSaveName)) + // { + // strSaveName = DateTime.Now.ToString("yyyyMMddHHmmss"); + // } + // #endregion + + // #region 遍历数据表源 + // var dtCount = 0; + // workBook = is07Excel ? (new XSSFWorkbook() as IWorkbook) : (new HSSFWorkbook() as IWorkbook); + // //创建流对象 + // ms = new MemoryStream(); + // foreach (var tb in dtblList) + // { + // if (tb != null && tb.Rows.Count > 0) + // { + // #region 获取表头列名称 + // Dictionary dicProperties = new Dictionary(); + // foreach (DataColumn column in tb.Columns) + // { + // dicProperties.Add(column.ColumnName, column.ColumnName); + // } + // #endregion + + // var currSheet = workBook.CreateSheet(sheetNameList[dtCount]); + + // //初始化行 + // int rowIndex = 0; + // int intColumn = 0; + // IRow rowExcel = currSheet.CreateRow(rowIndex); + // ICell cellExcel; + + // //初始化列 + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumn); + // cellExcel.SetCellValue(property.Value); + // ++intColumn; + // } + + // #region 写入内容 + // foreach (DataRow rowInfo in tb.Rows) + // { + // ++rowIndex; + // rowExcel = currSheet.CreateRow(rowIndex); + // int intColumnContent = 0; + // foreach (KeyValuePair property in dicProperties) + // { + // cellExcel = rowExcel.CreateCell(intColumnContent); + // cellExcel.SetCellValue(GetColumValue(tb, rowInfo, property.Key)); + // ++intColumnContent; + // } + // } + // #endregion + // } + + // dtCount++; + // } + // #endregion + + // //内存流导出 + // ExportExcel(ms, strSaveName, is07Excel); + //} + #endregion + + /// + /// 通过提供的列名和具体行,返回DataTable中具体的某一列的值 + /// + /// 内存表 + /// 具体行 + /// 列名 + /// 具体某列的值 + public string GetColumValue(DataTable dtbl, DataRow rowInfo, string columName) + { + string clumValue = ""; + foreach (DataColumn clum in dtbl.Columns) + { + if (clum.ColumnName.Equals(columName)) + { + clumValue = rowInfo[clum].ToString(); + break; + } + } + return clumValue; + } + + /// + /// 将DataTable导出成Excel文件 + /// + /// DataTabke内存表泛型 + /// 字典泛型,想要转换的属性名称列表[key值对应Model属性,value值对应Excel显示的列名] + /// 保存名称 + /// 换行数,表之间的间距,不换行可以默认输入null,也可以输入0 + /// 是否导出2007以上版本的Excel,默认是 + //public void WriteListDate(List lstDtbl, List> lstDicProperties, string strSaveName, int? intLineCount, bool is07Excel = true) + //{ + // #region 初始化工作簿 + // InitializeWorkbook(strSaveName, is07Excel); + + // //初始化行 + // int rowIndex = 0; + // IRow rowExcel; + // ICell cellExcel; + + // #endregion + + // #region 写内容 + // for (int i = 0; i < lstDicProperties.Count; i++) + // { + // //写表头 + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumn = 0; + // foreach (KeyValuePair property in lstDicProperties[i]) + // { + // cellExcel = rowExcel.CreateCell(intColumn); + // cellExcel.SetCellValue(property.Value); + // ++intColumn; + // } + + // //写入内容 + // foreach (DataRow rowInfo in lstDtbl[i].Rows) + // { + // ++rowIndex; + // rowExcel = workSheet.CreateRow(rowIndex); + // int intColumnContent = 0; + // foreach (KeyValuePair property in lstDicProperties[i]) + // { + // cellExcel = rowExcel.CreateCell(intColumnContent); + // cellExcel.SetCellValue(GetColumValue(lstDtbl[i], rowInfo, property.Key)); + // ++intColumnContent; + // } + // } + + // ++rowIndex; + + // //换行 + // rowIndex += intLineCount == null ? 0 : Convert.ToInt32(intLineCount); + // } + // #endregion + + // //内存流导出 + // ExportExcel(ms, strSaveName, is07Excel); + //} + #endregion + + #region 读取Excel2007数据 + /// + /// 将Excel2007以上版本文件中的数据读出到DataTable中(xlsx) + /// + /// Excel2007版本以上文件地址 + /// 需读取Sheet的Index,Sheet1的index是0,默认0 + /// + public DataTable ConvertExcelToTable(string filePath, int sheetIndex = 0) + { + DataTable dt = new DataTable(); + string extension = System.IO.Path.GetExtension(filePath).ToLower(); + using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + { + if (extension.Equals(".xls")) + { + workBook = new HSSFWorkbook(fs) as IWorkbook; + workSheet = workBook.GetSheetAt(sheetIndex); + + #region 表头 + IRow header = workSheet.GetRow(workSheet.FirstRowNum); + List columns = new List(); + for (int i = 0; i < header.LastCellNum; i++) + { + object obj = GetValueTypeForXLS(header.GetCell(i) as HSSFCell); + if (obj == null || obj.ToString() == string.Empty) + { + dt.Columns.Add(new DataColumn("Columns" + i.ToString())); + } + else + dt.Columns.Add(new DataColumn(obj.ToString())); + columns.Add(i); + } + #endregion + + #region 数据 + for (int i = workSheet.FirstRowNum + 1; i <= workSheet.LastRowNum; i++) + { + DataRow dr = dt.NewRow(); + + int count = columns.Count; ; + foreach (int j in columns) + { + object obj = GetValueTypeForXLS(workSheet.GetRow(i).GetCell(j) as HSSFCell); + if (obj == null || string.IsNullOrEmpty(obj.ToString())) + { + count--; + dr[j] = ""; + } + else + { + dr[j] = obj; + } + } + + if (count != 0) + { + dt.Rows.Add(dr); + } + } + #endregion + } + else + { + try + { + workBook = new XSSFWorkbook(fs) as IWorkbook; + workSheet = workBook.GetSheetAt(sheetIndex); + + #region 表头 + IRow header = workSheet.GetRow(workSheet.FirstRowNum); + List columns = new List(); + for (int i = 0; i < header.LastCellNum; i++) + { + object obj = GetValueTypeForXLSX(header.GetCell(i) as XSSFCell); + if (obj == null || obj.ToString() == string.Empty) + { + dt.Columns.Add(new DataColumn("Columns" + i.ToString())); + } + else + dt.Columns.Add(new DataColumn(obj.ToString())); + columns.Add(i); + } + #endregion + + #region 数据 + for (int i = workSheet.FirstRowNum + 1; i <= workSheet.LastRowNum; i++) + { + DataRow dr = dt.NewRow(); + + int count = columns.Count; + foreach (int j in columns) + { + object obj = GetValueTypeForXLSX(workSheet.GetRow(i).GetCell(j) as XSSFCell); + if (obj == null || string.IsNullOrEmpty(obj.ToString())) + { + count--; + dr[j] = ""; + } + else + { + dr[j] = obj; + } + } + + if (count != 0) + { + dt.Rows.Add(dr); + } + } + #endregion + } + catch (Exception) + { + workBook = new HSSFWorkbook(fs) as IWorkbook; + workSheet = workBook.GetSheetAt(sheetIndex); + + #region 表头 + IRow header = workSheet.GetRow(workSheet.FirstRowNum); + List columns = new List(); + for (int i = 0; i < header.LastCellNum; i++) + { + object obj = GetValueTypeForXLS(header.GetCell(i) as HSSFCell); + if (obj == null || obj.ToString() == string.Empty) + { + dt.Columns.Add(new DataColumn("Columns" + i.ToString())); + } + else + dt.Columns.Add(new DataColumn(obj.ToString())); + columns.Add(i); + } + #endregion + + #region 数据 + for (int i = workSheet.FirstRowNum + 1; i <= workSheet.LastRowNum; i++) + { + DataRow dr = dt.NewRow(); + + int count = columns.Count; ; + foreach (int j in columns) + { + object obj = GetValueTypeForXLS(workSheet.GetRow(i).GetCell(j) as HSSFCell); + if (obj == null || string.IsNullOrEmpty(obj.ToString())) + { + count--; + dr[j] = ""; + } + else + { + dr[j] = obj; + } + } + + if (count != 0) + { + dt.Rows.Add(dr); + } + } + #endregion + } + } + } + return dt; + } + #endregion + + #region 获取单元格类型 + /// + /// 获取单元格类型(xlsx) + /// + /// 单元格 + /// + private static object GetValueTypeForXLSX(XSSFCell cell) + { + if (cell == null) + return null; + + switch (cell.CellType) + { + case CellType.Blank: //BLANK: + return null; + case CellType.Boolean: //BOOLEAN: + return cell.BooleanCellValue; + case CellType.Numeric: //NUMERIC: + //short format = cell.CellStyle.DataFormat; + //if (format == 14 || format == 31 || format == 57 || format == 58 || format == 178) + //{ + // return cell.DateCellValue; + //} + //else + //{ + // return cell.NumericCellValue; + //} + //NPOI中数字和日期都是NUMERIC类型的,这里对其进行判断是否是日期类型 + if (HSSFDateUtil.IsCellDateFormatted(cell))//日期类型 + { + return cell.DateCellValue; + } + else//其他数字类型 + { + return cell.NumericCellValue; + } + case CellType.String: //STRING: + return cell.StringCellValue; + case CellType.Error: //ERROR: + return cell.ErrorCellValue; + case CellType.Formula: //FORMULA: + default: + return "=" + cell.CellFormula; + } + } + + /// + /// 获取单元格类型(xls) + /// + /// 单元格 + /// + private static object GetValueTypeForXLS(HSSFCell cell) + { + if (cell == null) + return null; + + switch (cell.CellType) + { + case CellType.Blank: //BLANK: + return null; + case CellType.Boolean: //BOOLEAN: + return cell.BooleanCellValue; + case CellType.Numeric: //NUMERIC: + //short format = cell.CellStyle.DataFormat; + //if (format == 14 || format == 31 || format == 57 || format == 58 || format == 178) + //{ + // return cell.DateCellValue; + //} + //else + //{ + // return cell.NumericCellValue; + //} + //NPOI中数字和日期都是NUMERIC类型的,这里对其进行判断是否是日期类型 + if (HSSFDateUtil.IsCellDateFormatted(cell))//日期类型 + { + return cell.DateCellValue; + } + else//其他数字类型 + { + return cell.NumericCellValue; + } + case CellType.String: //STRING: + return cell.StringCellValue; + case CellType.Error: //ERROR: + return cell.ErrorCellValue; + case CellType.Formula: //FORMULA: + default: + return "=" + cell.CellFormula; + } + } + #endregion + + } +} diff --git a/类库/Api.Framework/Tools/Nopi/ExtensiveHelper.cs b/类库/Api.Framework/Tools/Nopi/ExtensiveHelper.cs new file mode 100644 index 0000000..dceead2 --- /dev/null +++ b/类库/Api.Framework/Tools/Nopi/ExtensiveHelper.cs @@ -0,0 +1,321 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Eson.Utils +{ + /// + /// 反射帮助类 + /// + public class ExtensiveHelper + { + + public ExtensiveHelper() + { } + + /// + /// 将TSource类型的实体类对象转换为TDest类型的实体类对象 + /// + /// 要转换的实体类对象T类型 + /// 目标实体类对象T类型 + /// 要转换的实体类对象 + /// TDest目标实体类对象 + public static TDest Map(TSource s) + where TSource : class, new() + where TDest : class, new() + { + //定义TDest目标返回对象 + TDest oTarget = new TDest(); + + //获取TSource, TDest的反射类型以及其公共属性 + Type typeTSource = typeof(TSource); + Type typeTDest = typeof(TDest); + PropertyInfo[] propersTSource = typeTSource.GetProperties(); + PropertyInfo[] propersTDest = typeTDest.GetProperties(); + + #region 遍历转换 + foreach (PropertyInfo pTDest in propersTDest) + { + foreach (PropertyInfo pTSource in propersTSource) + { + //如果TSource, TDest的属性名称相同,则可进行转换 + if (pTDest.Name.Equals(pTSource.Name)) + { + //获取TSource对象该属性的值 + object objValue = pTSource.GetValue(s, null); + + if (null != objValue) + { + if (!pTDest.PropertyType.IsGenericType) + { + //已知类型 + try + { + pTDest.SetValue(oTarget, Convert.ChangeType(objValue, pTDest.PropertyType), null); + } + catch + { + continue; + } + } + else + { + //泛型Nullable<>,未知类型 + Type genericTypeDefinition = pTDest.PropertyType.GetGenericTypeDefinition(); + if (genericTypeDefinition == typeof(Nullable<>)) + { + pTDest.SetValue(oTarget, Convert.ChangeType(objValue, Nullable.GetUnderlyingType(pTDest.PropertyType)), null); + } + } + } + break; + } + + } + } + #endregion + + return oTarget; + } + + /// + /// 将TSource类型的实体类泛型List对象转换为TDest类型的泛型List对象 + /// + /// 要转换的实体类对象T类型 + /// 目标实体类对象T类型 + /// 要转换的泛型List对象 + /// TDest目标泛型List对象 + public static List Map(List sList) + where TSource : class, new() + where TDest : class, new() + { + List list = new List(); + + if (null == sList) + { + return list; + } + + foreach (TSource s in sList) + { + list.Add(Map(s)); + } + + return list; + } + + /// + /// 将TSource类型的实体类泛型List对象转换为TDest类型的泛型List对象 + /// + /// 要转换的实体类对象T类型 + /// 目标实体类对象T类型 + /// 要转换的泛型List对象 + /// TDest目标泛型List对象 + public static IList MapI(IList ISList) + where TSource : class, new() + where TDest : class, new() + { + IList Ilist = new List(); + + if (null == ISList) + { + return Ilist; + } + + foreach (TSource s in ISList) + { + Ilist.Add(Map(s)); + } + + return Ilist; + } + + + /// + /// 将DataTable数据转换为TDest类型的泛型List对象 + /// + /// 约束DataTabe的行类型T类型 + /// 目标实体类对象T类型 + /// DataTabe数据对象 + /// TDest目标泛型List对象 + public static List Map(DataTable tb) + where TSource : DataTable + where TDest : class, new() + { + List list = new List(); + + if (null == tb || tb.Rows.Count == 0) + { + return list; + } + + foreach (DataRow row in tb.Rows) + { + list.Add(Map(row, tb.Columns)); + } + + return list; + } + + /// + /// 将DataTable的行转换成TDest类型的泛型List对象 + /// + /// 约束DataTabe的行类型 + /// 目标实体类对象T类型 + /// DataTabe的行对象 + /// DataTabe的所有列数据 + /// TDest目标泛型List对象 + public static TDest Map(DataRow row, DataColumnCollection columns) + where TSource : DataRow + where TDest : class, new() + { + //定义TDest目标返回对象 + TDest oTarget = new TDest(); + + //获取TDest的反射类型以及其公共属性 + Type typeTDest = typeof(TDest); + PropertyInfo[] propersTDest = typeTDest.GetProperties(); + + #region 遍历转换 + foreach (PropertyInfo pTDest in propersTDest) + { + foreach (DataColumn cl in columns) + { + //如果DataTable的列名, TDest的属性名称相同,则可进行转换 + if (pTDest.Name.Equals(cl.ColumnName)) + { + //获取TSource对象该属性的值 + object objValue = row[cl.ColumnName]; + + if (null != objValue) + { + if (!pTDest.PropertyType.IsGenericType) + { + //已知类型 + try + { + pTDest.SetValue(oTarget, Convert.ChangeType(objValue, pTDest.PropertyType), null); + } + catch + { + continue; + } + } + else + { + //泛型Nullable<>,未知类型 + Type genericTypeDefinition = pTDest.PropertyType.GetGenericTypeDefinition(); + if (genericTypeDefinition == typeof(Nullable<>)) + { + pTDest.SetValue(oTarget, Convert.ChangeType(objValue, Nullable.GetUnderlyingType(pTDest.PropertyType)), null); + } + } + } + break; + } + + } + } + #endregion + + return oTarget; + } + + /// + /// 将T类型的List列表转换为DataTable + /// + /// T类型 + /// 列表 + /// 想要转换的属性名称列表[key值对应Model属性,value值对应Excel显示的列名] + /// 返回DataTable + public static DataTable ConvertListToTable(List list, Dictionary properties) + where T : class + { + DataTable dt = new DataTable(); + if (properties.Count > 0 && list.Count > 0) + { + Type type = typeof(T); + foreach (KeyValuePair property in properties) + { + dt.Columns.Add(new DataColumn(property.Value)); + } + foreach (T t in list) + { + DataRow dr = dt.NewRow(); + int i = 0; + foreach (KeyValuePair property in properties) + { + PropertyInfo pi = type.GetProperty(property.Key); + object obj = pi.GetValue(t, null); + dr[i] = obj == null ? "" : obj.ToString(); + i++; + } + dt.Rows.Add(dr); + } + } + return dt; + } + + /// + /// 将T类型的Dictionary字典列表转换为DataTable + /// + /// D类型 + /// S类型 + /// 字典列表 + /// 列名列表 + /// 返回DataTable + public static DataTable ConvertDictionaryToTable(Dictionary dic, List list) + { + DataTable dt = new DataTable(); + if (dic.Count > 0 && list.Count > 0) + { + foreach (string columnName in list) + { + dt.Columns.Add(new DataColumn(columnName)); + } + foreach (KeyValuePair d in dic) + { + DataRow dr = dt.NewRow(); + dr[0] = d.Key.ToString(); + dr[1] = d.Value.ToString(); + dt.Rows.Add(dr); + } + } + return dt; + } + + /// + /// 将T类型的List列表转换为DataTable + /// + /// T类型 + /// 列表 + /// 返回DataTable + public static DataTable ConvertListToTable(List list) + where T : class + { + DataTable dt = new DataTable(); + Type type = typeof(T); + PropertyInfo[] propers = type.GetProperties(); + foreach (PropertyInfo p in propers) + { + dt.Columns.Add(new DataColumn(p.Name)); + } + foreach (T t in list) + { + DataRow dr = dt.NewRow(); + for (int i = 0; i < propers.Length; i++) + { + PropertyInfo pi = type.GetProperty(propers[i].Name); + object obj = pi.GetValue(t, null); + dr[i] = obj == null ? "" : obj.ToString(); + } + dt.Rows.Add(dr); + } + return dt; + } + } +} diff --git a/类库/Api.Framework/Tools/OrderHelper.cs b/类库/Api.Framework/Tools/OrderHelper.cs new file mode 100644 index 0000000..33948bd --- /dev/null +++ b/类库/Api.Framework/Tools/OrderHelper.cs @@ -0,0 +1,1057 @@ +using Api.Framework.Enums; +using Api.Framework.Events; +using Api.Framework.Model; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Api.Framework.Tools +{ + /// + /// 订单助手 + /// + public class OrderHelper + { + /// + /// 判断是否是三个平台的订单号 + /// + /// 判断是否为已知的cps订单 + /// + public static bool IsOrderId(string mess) + { + try + { + if (Regex.IsMatch(mess, @"^(\d{4})\s(\d{4})\s(\d{4})\s(\d{4})\s(\d{3})$") || Regex.IsMatch(mess, @"^\d{18,19}$") || Regex.IsMatch(mess, @"^\d{6}-\d{15}$") || Regex.IsMatch(mess, @"^\d{11,12}$")) + return true; + } + catch (Exception) + { } + return false; + } + + #region 返利平台消息类型简单判断(较少误判断) + /// + /// 简单判断消息是否为指定cps类型 + /// + /// 消息 + /// cps类型 + /// + public static bool IsCurrentCpsMess(string mess, CpsType cpsType) + { + try + { + switch (cpsType) + { + case CpsType.阿里妈妈: + return !(isPDD(mess) || isJD(mess) || isWPH(mess)); + case CpsType.多多进宝: + return !(isTB(mess) || isJD(mess) || isWPH(mess)); + case CpsType.京东联盟: + return !(isPDD(mess) || isTB(mess) || isWPH(mess)); + case CpsType.唯品联盟: + return !(isPDD(mess) || isJD(mess) || isTB(mess)); + default: + return true; + } + } + catch (Exception ex) + { } + return true; + } + + /// + /// 是否为拼多多 + /// + /// 消息 + /// + private static bool isPDD(string mess) + { + try + { + if (mess.Trim().Contains("jinbao.pinduoduo.com") || + mess.Trim().Contains("yangkeduo.com") || + mess.Trim().Contains("pinduoduo.com") + ) + return true; + } + catch (Exception) + { } + return false; + } + + /// + /// 是否为京东 + /// + /// 消息 + /// + private static bool isJD(string mess) + { + try + { + if (mess.Trim().Contains(".jd.com")) + return true; + } + catch (Exception) + { } + return false; + } + + private static bool isWPH(string mess) + { + try + { + if (mess.Trim().Contains(".vip.com")) + return true; + } + catch (Exception) + { } + return false; + } + + /// + /// 是否为阿里 + /// + /// 消息 + /// + private static bool isTB(string mess) + { + try + { + //yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|detail.yao.95095.com|laiwang.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com|m.tb.cn + if (mess.Trim().Contains("taobao.com") || + mess.Trim().Contains("detail.tmall") || + mess.Trim().Contains(".tb.cn") || + mess.Trim().Contains("yukhj.com") || + mess.Trim().Contains("m.yeeoq.top") || + mess.Trim().Contains("m.uqlsi") || + mess.Trim().Contains("m.rijni") || + mess.Trim().Contains("m.gkqmj") || + mess.Trim().Contains("m.mulwt") || + mess.Trim().Contains("sjtm.me") || + mess.Trim().Contains("aa5d.com") || + mess.Trim().Contains("d11a.com") || + mess.Trim().Contains("92db.com") || + mess.Trim().Contains("yqt.so") || + mess.Trim().Contains("e22a.com") || + mess.Trim().Contains("f61b.com") || + mess.Trim().Contains("detail.m.tmall") || + mess.Trim().Contains("k.83jie.com") || + mess.Trim().Contains("ewqcxz.com") || + mess.Trim().Contains("items.alitrip.com") || + mess.Trim().Contains("tmqd.me") || + mess.Trim().Contains("detail.tmall.hk") || + mess.Trim().Contains("mashort.cn") || + mess.Trim().Contains("tmall.com") || + mess.Trim().Contains("detail.yao.95095.com") || + mess.Trim().Contains("laiwang.com") || + mess.Trim().Contains("juhuasuan.com") || + mess.Trim().Contains("s.click.taobao") || + mess.Trim().Contains("detail.liangxinyao.com")) + return true; + } + catch (Exception) + { } + return false; + } + + #endregion + + #region 获取淘宝配置 + private static Dictionary tbConfig; + /// + /// 获取阿里配置 + /// + /// 刷新 + public static Dictionary RefreshTbConfig(bool refresh = false) + { + if (refresh || tbConfig == null) + tbConfig = Util.ReadConfig("插件-淘宝返利-配置", true); + return tbConfig; + } + #endregion + + #region 获取拼多多配置 + private static Dictionary pddConfig; + /// + /// 获取拼多多配置 + /// + /// 刷新 + public static Dictionary RefreshPddConfig(bool refresh = false) + { + if (refresh || pddConfig == null) + pddConfig = Util.ReadConfig("插件-拼多多返利-配置", true); + return pddConfig; + } + #endregion + + #region 获取抖音配置 + private static Dictionary dyConfig; + /// + /// 获取抖音配置 + /// + /// 刷新 + public static Dictionary RefreshDyConfig(bool refresh = false) + { + if (refresh || dyConfig == null) + dyConfig = Util.ReadConfig("插件-抖音返利-配置", true); + return dyConfig; + } + #endregion + + private static Dictionary config; + + static OrderHelper() + { + RefreshConfig(); + } + + /// + /// 刷新用户裂变配置 + /// + /// 刷新 + public static void RefreshConfig(bool refresh = false) + { + if (refresh || config == null) + { + config = Util.ReadConfig("插件-用户裂变-配置", true); + } + } + + private static readonly Object lockObj_1 = new Object(); + + /// + /// 判断上级是否获得推荐奖励 + /// + /// 订单所绑定的用户对象 + /// 订单结算时间 + /// 付款金额 + /// + public static bool CheckSuperiorInviteRewards(fl_member_info _member, DateTime _endtime, double _price) + { + try + { + var member = _member; + + var session = ApiClient.GetSession(); + var record = session.FindStatisticsRecord(member.id); + if (record != null && record.ex1 == 1) + return false; + + lock (lockObj_1) + { + var price = _price; + var endtime = _endtime; + + record = session.FindStatisticsRecord(member.id); + if (record == null || record.ex1 == 0) + { + if (config != null && config.ContainsKey("SuperiorSumSwitch"))//上级奖励开关 + { + var SuperiorSumSwitch = config["SuperiorSumSwitch"].ToString(); + if (SuperiorSumSwitch == "1") + { + if (member.inviter_id != 0 && member.id != member.inviter_id) + { + if (config.ContainsKey("SuperiorRewardWay")) + { + var SuperiorRewardWay = config["SuperiorRewardWay"].ToString().Trim(); + if (SuperiorRewardWay == "2")// 新人完成首单奖励 = 2,新人首单满足付款金额奖励 = 3 + { + if (record == null) + record = new fl_statistics_record() + { + uid = member.id, + ex1 = 1 + }; + else + record.ex1 = 1; + session.Saveable(record).ExecuteCommand(); + + var flag = false; + var orderCount = 0;//历史是否存在已结算的订单 + var db_endtime = (endtime.Year == 1900 ? DateTime.Now : endtime); + orderCount += session.Find("select * from fl_order_alimama where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_jingdong where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_pinduoduo where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_weipinhui where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_douyin where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_suning where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime }).Count; + } + } + } + } + } + EventClient.OnEvent("【新人完成首单奖励】", $"(【{member.id}】{member.username},上级:【{member.inviter_id}】),结算订单数:{orderCount}"); + return orderCount == 0; + } + else if (SuperiorRewardWay == "3") + { + //Console.WriteLine("endtime.Year = " + endtime.Year); + var db_endtime = (endtime.Year == 1900 ? DateTime.Now : endtime); + if (config.ContainsKey("SuperiorReward_FirstSinglePaymentSum")) + { + var SuperiorReward_FirstSinglePaymentSum = double.Parse(config["SuperiorReward_FirstSinglePaymentSum"].ToString());//下级首单付款金额 + if (price < SuperiorReward_FirstSinglePaymentSum) return false; + + if (record == null) + record = new fl_statistics_record() { uid = member.id, ex1 = 1 }; + else + record.ex1 = 1; + session.Saveable(record).ExecuteCommand(); + + var orderCount = 0;//历史是否存在已结算的订单 + orderCount += session.Find("select * from fl_order_alimama where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime and alipay_total_price >= @alipay_total_price", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime, alipay_total_price = SuperiorReward_FirstSinglePaymentSum }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_jingdong where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime and estimateCosPrice >= @estimateCosPrice", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime, estimateCosPrice = SuperiorReward_FirstSinglePaymentSum }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_pinduoduo where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime and order_amount >= @order_amount", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime, order_amount = SuperiorReward_FirstSinglePaymentSum }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_weipinhui where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime and commissionTotalCost >= @commissionTotalCost", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime, commissionTotalCost = SuperiorReward_FirstSinglePaymentSum }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_douyin where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime and total_pay_amount >= @total_pay_amount", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime, total_pay_amount = SuperiorReward_FirstSinglePaymentSum }).Count; + if (orderCount == 0) + { + orderCount += session.Find("select * from fl_order_suning where db_userid = @db_userid and db_status = @db_status and db_endtime < @db_endtime and payAmount >= @payAmount", new { db_userid = member.id, db_status = SystemOrderStatus.订单结算, db_endtime = db_endtime, payAmount = SuperiorReward_FirstSinglePaymentSum }).Count; + } + } + } + } + } + EventClient.OnEvent("【新人首单满足付款金额奖励】", $@"(【{member.id}】{member.username},上级:【{member.inviter_id}】),结算订单数:{orderCount} - {price}~{SuperiorReward_FirstSinglePaymentSum} - {endtime} - {db_endtime}"); + return orderCount == 0; + } + } + } + } + } + } + } + return false; + } + } + catch (Exception ex) + { } + return false; + } + + private static readonly Object lockObj_2 = new Object(); + + /// + /// 判断是否用户首单奖励 + /// + /// 用户对象 + /// 系统订单类型 + /// + public static bool CheckMemberFirstOrderRewards(fl_member_info _member, SystemOrderStatus _orderStatus)//, DateTime endtime + { + try + { + lock (lockObj_2) + { + var member = _member; + var orderStatus = _orderStatus; + if (member == null) + return false; + var session = ApiClient.GetSession(); + var record = session.FindStatisticsRecord(member.id); + if (record != null && record.ex2 >= 1) + return false; + + #region 记录首次下单的时间 + if (orderStatus == SystemOrderStatus.订单付款) + { + if (record == null) + { + record = new fl_statistics_record() { uid = member.id, ex2 = 0, ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now) }; + session.Saveable(record).ExecuteCommand(); + } + else + { + if (record.ex2 == 0 && record.ex4 == 0) + record.ex4 = CsharpHttpHelper.HttpExtend.GetTimeStamp(DateTime.Now); + session.Saveable(record).ExecuteCommand(); + } + } + #endregion + + if (config.ContainsKey("FirstOrder_SumSwitch") && config["FirstOrder_SumSwitch"].ToString() == "1") + { + record = session.FindStatisticsRecord(member.id); + if (record == null || record.ex2 == 0) + { + if (config.ContainsKey("FirstOrder_InitialAwardNewcomerType"))//判断首单奖励新人类型 + { + var newcomerType = config["FirstOrder_InitialAwardNewcomerType"].ToString();//所有新用户 = 1,被邀请用户 = 2,非邀请用户 = 3 + if (newcomerType == "2" && member.inviter_id == 0) + return false; + else if (newcomerType == "3" && member.inviter_id != 0) + return false; + } + + if (config.ContainsKey("FirstOrderAwardWay"))//判断首单奖励的方式 + { + var FirstOrderAwardWay = config["FirstOrderAwardWay"].ToString();//订单付款后奖励 = 1,订单结算后奖励 = 2 + if (FirstOrderAwardWay == "1" && orderStatus == SystemOrderStatus.订单付款) + { + if (record == null) + record = new fl_statistics_record() { uid = member.id, ex2 = 1 }; + else + record.ex2 = 1; + session.Saveable(record).ExecuteCommand(); + + var orderCount = 0; + orderCount += session.Find("select * from fl_order_alimama where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0 || orderCount == 1) + { + orderCount += session.Find("select * from fl_order_jingdong where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0 || orderCount == 1) + { + orderCount += session.Find("select * from fl_order_pinduoduo where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0 || orderCount == 1) + { + orderCount += session.Find("select * from fl_order_weipinhui where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0 || orderCount == 1) + { + orderCount += session.Find("select * from fl_order_douyin where db_userid = @db_userid", new { db_userid = member.id }).Count; + if (orderCount == 0 || orderCount == 1) + { + orderCount += session.Find("select * from fl_order_suning where db_userid = @db_userid", new { db_userid = member.id }).Count; + } + } + } + } + } + return (orderCount == 1); + } + else if (FirstOrderAwardWay == "2" && orderStatus == SystemOrderStatus.订单结算) + { + if (record == null) + record = new fl_statistics_record() { uid = member.id, ex2 = 1 }; + else + record.ex2 = 1; + session.Saveable(record).ExecuteCommand(); + + return (member.finish_order == 1); + } + } + } + } + return false; + } + } + catch (Exception ex) + { } + return false; + } + + /// + /// 扣除已经阿里结算订单的用户所得 + /// + /// 通知集合 + /// 阿里订单对象 + public void DeductAliOrderPoint(List notices, fl_order_alimama order) + { + try + { + if (order.db_userid == 0) return; + var session = ApiClient.GetSession(); + + var member = session.FindSingle("id=@id", new { id = order.db_userid }); + if (member == null) return; + + session.InsertRefundHistPoint(order.trade_parent_id, order.trade_id, CpsType.阿里妈妈, order.db_point, member.id); + + //获取积分信息 + var point = HttpHelper.JsonToObject(order.db_point) as ItemPoint; + if (point == null) return; + + #region 维权扣除 - 全部 + member = session.ChangePoint(PointType.维权扣除, point.UserPoint, member.id, $"退款:{order.item_title}({order.trade_parent_id})({order.trade_id})"); + notices.Add(new OrderNoticeEvent(CpsType.阿里妈妈, member, order)); + + List ids = new List(); + ids.Add(member.id); + //多级提成计算..用户自己的上级不能为自己 + //if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id)) + if (point.AwardOne > 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},淘宝购物1级提成!{order.item_title} - ({order.trade_parent_id})({order.trade_id})"); + if (flag != null) + { + ids.Add(flag.id); + if (notices != null) + { + notices.Add(new OrderNoticeEvent(CpsType.阿里妈妈, flag, order, OrderNoticeType.一级提成) { Customer = member }); + } + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + flag = session.ChangePoint(PointType.维权扣除, point.AwardTwo, flag.inviter_id, $"{member.usernick},淘宝购物2级提成!{order.item_title} - ({order.trade_parent_id})({order.trade_id})"); + if (flag != null) + { + ids.Add(flag.id); + if (notices != null && flag != null) + { + notices.Add(new OrderNoticeEvent(CpsType.阿里妈妈, flag, order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + flag = session.ChangePoint(PointType.维权扣除, point.AwardThree, flag.inviter_id, $"{member.usernick},淘宝购物3级提成!{order.item_title} - ({order.trade_parent_id})({order.trade_id})"); + if (flag != null) + { + ids.Add(flag.id); + if (notices != null && flag != null) notices.Add(new OrderNoticeEvent(CpsType.阿里妈妈, flag, order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(order.msg_groupid) && !string.IsNullOrEmpty(order.db_robotname)) + { + var create = session.FindCreateInfo(order.msg_groupid, order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.维权扣除, point.AwardCreate, create.mid, $"{member.usernick},淘宝维护提成!{order.item_title} - ({order.trade_parent_id})({order.trade_id})"); + if (notices != null && flag != null) notices.Add(new OrderNoticeEvent(CpsType.阿里妈妈, flag, order, OrderNoticeType.群主分成) { Customer = member }); + } + } + #endregion + } + catch (Exception ex) + { } + } + + /// + /// 扣除已经京东结算订单的用户所得 + /// + /// 通知集合 + /// 京东订单对象 + /// 积分分配对象 + public void DeductJingDongOrderPoint(List notices, fl_order_jingdong order, ItemPoint itempoint) + { + try + { + if (order == null || order.db_userid == 0) return; + var session = ApiClient.GetSession(); + + if (itempoint == null) return; + + var member = session.FindSingle("id=@id", new { id = order.db_userid }); + if (member == null) return; + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.维权扣除, itempoint.UserPoint, member.id, $"京东购买:{order.skuName}({order.orderId}) - 售后中(扣除)"); + //var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},京东购物1级提成 - 售后中(扣除)!"); + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, member, order)); + //多级提成计算 + if (itempoint.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.维权扣除, itempoint.AwardOne, member.inviter_id, $"{member.usernick},京东购物1级提成 - 售后中(扣除) - {order.skuName}({order.orderId})"); + if (flag != null) + { + ids.Add(flag.id); + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, flag, order, OrderNoticeType.一级提成) { Customer = member }); + + if (itempoint.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.维权扣除, itempoint.AwardTwo, flag.inviter_id, $"{member.usernick},京东购物2级提成 - 售后中(扣除) - {order.skuName}({order.orderId})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notices.Add(new OrderNoticeEvent(CpsType.京东联盟, flag2, order, OrderNoticeType.二级提成) { Customer = member }); + + if (itempoint.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.维权扣除, itempoint.AwardThree, flag2.inviter_id, $"{member.usernick},京东购物3级提成 - 售后中(扣除) - {order.skuName}({order.orderId})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notices.Add(new OrderNoticeEvent(CpsType.京东联盟, flag3, order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (itempoint.AwardCreate > 0 && !string.IsNullOrEmpty(order.msg_groupid) && !string.IsNullOrEmpty(order.db_robotname)) + { + var robot = session.FindRobotInfo(order.db_robotname, order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(order.msg_groupid, order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.维权扣除, itempoint.AwardCreate, create.mid, $"{member.usernick},京东维护提成 - 售后中(扣除) - {order.skuName}({order.orderId})"); + if (flag != null) notices.Add(new OrderNoticeEvent(CpsType.京东联盟, flag, order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + catch (Exception ex) + { } + } + + + /// + /// 扣除已经快手结算订单的用户所得 + /// + /// 通知集合 + /// 快手订单对象 + /// 积分分配对象 + public void DeductKuaiShouOrderPoint(List notices, fl_order_kuaishou order, ItemPoint itempoint) + { + try + { + if (order == null || order.db_userid == 0) return; + var session = ApiClient.GetSession(); + + if (itempoint == null) return; + + var member = session.FindSingle("id=@id", new { id = order.db_userid }); + if (member == null) return; + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.维权扣除, itempoint.UserPoint, member.id, $"快手购买:{order.itemTitle}({order.oid}-{order.oid2}) - 售后中(扣除)"); + //var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},快手购物1级提成 - 售后中(扣除)!"); + notices.Add(new OrderNoticeEvent(CpsType.快手联盟, member, order)); + //多级提成计算 + if (itempoint.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.维权扣除, itempoint.AwardOne, member.inviter_id, $"{member.usernick},快手购物1级提成 - 售后中(扣除) - {order.itemTitle}({order.oid}-{order.oid2})"); + if (flag != null) + { + ids.Add(flag.id); + notices.Add(new OrderNoticeEvent(CpsType.快手联盟, flag, order, OrderNoticeType.一级提成) { Customer = member }); + + if (itempoint.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.维权扣除, itempoint.AwardTwo, flag.inviter_id, $"{member.usernick},快手购物2级提成 - 售后中(扣除) - {order.itemTitle}({order.oid}-{order.oid2})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notices.Add(new OrderNoticeEvent(CpsType.快手联盟, flag2, order, OrderNoticeType.二级提成) { Customer = member }); + + if (itempoint.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.维权扣除, itempoint.AwardThree, flag2.inviter_id, $"{member.usernick},快手购物3级提成 - 售后中(扣除) - {order.itemTitle}({order.oid}-{order.oid2})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notices.Add(new OrderNoticeEvent(CpsType.快手联盟, flag3, order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (itempoint.AwardCreate > 0 && !string.IsNullOrEmpty(order.msg_groupid) && !string.IsNullOrEmpty(order.db_robotname)) + { + var robot = session.FindRobotInfo(order.db_robotname, order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(order.msg_groupid, order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.维权扣除, itempoint.AwardCreate, create.mid, $"{member.usernick},快手维护提成 - 售后中(扣除) - {order.itemTitle}({order.oid}-{order.oid2})"); + if (flag != null) notices.Add(new OrderNoticeEvent(CpsType.快手联盟, flag, order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + catch (Exception ex) + { } + } + + /// + /// 扣除已经抖音结算订单的用户所得 + /// + /// 通知集合 + /// 抖音订单对象 + /// 积分分配对象 + public void DeductDouYinOrderPoint(List notices, fl_order_douyin order, ItemPoint itempoint) + { + try + { + if (order == null || order.db_userid == 0) return; + var session = ApiClient.GetSession(); + + if (itempoint == null) return; + + var member = session.FindSingle("id=@id", new { id = order.db_userid }); + if (member == null) return; + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.维权扣除, itempoint.UserPoint, member.id, $"抖音购买:{order.product_name}({order.order_id}) - 售后中(扣除)"); + //var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},抖音购物1级提成 - 售后中(扣除)!"); + notices.Add(new OrderNoticeEvent(CpsType.抖音联盟, member, order)); + //多级提成计算 + if (itempoint.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.维权扣除, itempoint.AwardOne, member.inviter_id, $"{member.usernick},抖音购物1级提成 - 售后中(扣除) - {order.product_name}({order.order_id})"); + if (flag != null) + { + ids.Add(flag.id); + notices.Add(new OrderNoticeEvent(CpsType.抖音联盟, flag, order, OrderNoticeType.一级提成) { Customer = member }); + + if (itempoint.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.维权扣除, itempoint.AwardTwo, flag.inviter_id, $"{member.usernick},抖音购物2级提成 - 售后中(扣除) - {order.product_name}({order.order_id})"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notices.Add(new OrderNoticeEvent(CpsType.抖音联盟, flag2, order, OrderNoticeType.二级提成) { Customer = member }); + + if (itempoint.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.维权扣除, itempoint.AwardThree, flag2.inviter_id, $"{member.usernick},抖音购物3级提成 - 售后中(扣除) - {order.product_name}({order.order_id})"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notices.Add(new OrderNoticeEvent(CpsType.抖音联盟, flag3, order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (itempoint.AwardCreate > 0 && !string.IsNullOrEmpty(order.msg_groupid) && !string.IsNullOrEmpty(order.db_robotname)) + { + var robot = session.FindRobotInfo(order.db_robotname, order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(order.msg_groupid, order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.维权扣除, itempoint.AwardCreate, create.mid, $"{member.usernick},抖音维护提成 - 售后中(扣除) - {order.product_name}({order.order_id})"); + if (flag != null) notices.Add(new OrderNoticeEvent(CpsType.抖音联盟, flag, order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + catch (Exception ex) + { } + } + + /// + /// 扣除已经拼多结算订单的用户所得 + /// + /// 通知集合 + /// 拼多多订单对象 + public void DeductPinDuoOrderPoint(List notice, fl_order_pinduoduo db_order) + { + try + { + if (db_order.db_userid == 0) return; + var session = ApiClient.GetSession(); + + var member = session.FindSingle("id=@id", new { id = db_order.db_userid }); + + if (member == null) return; + + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point == null) return; + + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.维权扣除, point.UserPoint, member.id, $"拼多多购买:{db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + + //#region 判断用户是否符合获得新人奖励 + //isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + //#endregion + + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, member, db_order)); + //多级提成计算 + + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, inviter, db_order, OrderNoticeType.一级提成) { Customer = member }); + } + } + else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},拼多多购物1级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + if (flag != null) + { + ids.Add(flag.id); + + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.一级提成) { Customer = member }); + + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.维权扣除, point.AwardTwo, flag.inviter_id, $"{member.usernick},拼多多购物2级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.维权扣除, point.AwardThree, flag2.inviter_id, $"{member.usernick},拼多多购物3级提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.维权扣除, point.AwardCreate, create.mid, $"{member.usernick},拼多多维护提成! - {db_order.goods_name}({db_order.order_sn}) - 售后中(扣除)"); + if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.多多进宝, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + catch (Exception ex) + { } + } + + /// + /// 扣除已经拼多结算订单的用户所得 + /// + /// 通知集合 + /// 拼多多订单对象 + public void DeductSuningOrderPoint(List notice, fl_order_suning db_order) + { + try + { + if (db_order.db_userid == 0) return; + var session = ApiClient.GetSession(); + + var member = session.FindSingle("id=@id", new { id = db_order.db_userid }); + + if (member == null) return; + + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point == null) return; + + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.维权扣除, point.UserPoint, member.id, $"苏宁易购购买:{db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber}) - 售后中(扣除)"); + + //#region 判断用户是否符合获得新人奖励 + //isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + //#endregion + + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, member, db_order)); + //多级提成计算 + + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, inviter, db_order, OrderNoticeType.一级提成) { Customer = member }); + } + } + else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},苏宁易购购物1级提成! - {db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber}) - 售后中(扣除)"); + if (flag != null) + { + ids.Add(flag.id); + + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, flag, db_order, OrderNoticeType.一级提成) { Customer = member }); + + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.维权扣除, point.AwardTwo, flag.inviter_id, $"{member.usernick},苏宁易购购物2级提成! - {db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber}) - 售后中(扣除)"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.维权扣除, point.AwardThree, flag2.inviter_id, $"{member.usernick},苏宁易购购物3级提成! - {db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber}) - 售后中(扣除)"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.维权扣除, point.AwardCreate, create.mid, $"{member.usernick},苏宁易购维护提成! - {db_order.productName}({db_order.orderCode}-{db_order.orderLineNumber}) - 售后中(扣除)"); + if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.苏宁易购, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + catch (Exception ex) + { } + } + + /// + /// 扣除已经唯品会结算订单的用户所得 + /// + /// 通知集合 + /// 唯品会订单对象 + public bool DeductWeipinhuiOrderPoint(List notice, fl_order_weipinhui db_order) + { + try + { + if (db_order.db_userid == 0) return false; + var session = ApiClient.GetSession(); + + var member = session.FindSingle("id=@id", new { id = db_order.db_userid }); + + if (member == null) return false; + + var point = HttpHelper.JsonToObject(db_order.db_point) as ItemPoint; + if (point == null) return false; + + List ids = new List(); + ids.Add(member.id); + //用户自身加积分 + member = session.ChangePoint(PointType.维权扣除, point.UserPoint, member.id, $"唯品会购买:{db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + + //#region 判断用户是否符合获得新人奖励 + //isFirstOrder = OrderHelper.CheckMemberFirstOrderRewards(member, db_order.db_status); + //#endregion + + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, member, db_order)); + + + //多级提成计算 + + //一级的提成小于等于0时,并且判断一级是否符合获得推荐新人奖励(无奖励一级提成) + if (point.AwardOne <= 0 && member.inviter_id > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + if (notice != null) + { + var inviter = session.FindMemberInfoById(member.inviter_id); + if (inviter != null) + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, inviter, db_order, OrderNoticeType.一级提成) { Customer = member }); + } + } + else if (point.AwardOne > 0 && !ids.Contains(member.inviter_id) && member.id != member.inviter_id) + { + var flag = session.ChangePoint(PointType.维权扣除, point.AwardOne, member.inviter_id, $"{member.usernick},唯品会购物1级提成! - {db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + if (flag != null) + { + ids.Add(flag.id); + + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag, db_order, OrderNoticeType.一级提成) { Customer = member }); + + if (point.AwardTwo > 0 && flag.inviter_id != 0 && !ids.Contains(flag.inviter_id)) + { + var flag2 = session.ChangePoint(PointType.维权扣除, point.AwardTwo, flag.inviter_id, $"{member.usernick},唯品会购物2级提成! - {db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + if (flag2 != null) + { + ids.Add(flag2.id); + if (flag2 != null) + { + notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag2, db_order, OrderNoticeType.二级提成) { Customer = member }); + + if (point.AwardThree > 0 && flag2.inviter_id != 0 && !ids.Contains(flag2.inviter_id)) + { + var flag3 = session.ChangePoint(PointType.维权扣除, point.AwardThree, flag2.inviter_id, $"{member.usernick},唯品会购物3级提成! - {db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + if (flag3 != null) + { + ids.Add(flag3.id); + if (flag3 != null) notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag3, db_order, OrderNoticeType.三级提成) { Customer = member }); + } + } + } + } + } + } + } + + //创建人计算 + if (point.AwardCreate > 0 && !string.IsNullOrEmpty(db_order.msg_groupid) && !string.IsNullOrEmpty(db_order.db_robotname)) + { + var robot = session.FindRobotInfo(db_order.db_robotname, db_order.db_robottype); + if (robot != null) + { + var create = session.FindCreateInfo(db_order.msg_groupid, db_order.db_robottype); + if (create != null && member.id != create.id) + { + var flag = session.ChangePoint(PointType.维权扣除, point.AwardCreate, create.mid, $"{member.usernick},唯品会维护提成! - {db_order.goodsName}({db_order.orderSn} - {db_order.goodsId}) - 售后中(扣除)"); + if (flag != null) notice.Add(new OrderNoticeEvent(CpsType.唯品联盟, flag, db_order, OrderNoticeType.群主分成) { Customer = member }); + } + } + } + } + catch (Exception ex) + { } + return true; + } + + } +} diff --git a/类库/Api.Framework/Tools/PDDHelper.cs b/类库/Api.Framework/Tools/PDDHelper.cs new file mode 100644 index 0000000..f2754af --- /dev/null +++ b/类库/Api.Framework/Tools/PDDHelper.cs @@ -0,0 +1,451 @@ +using Api.Framework.Cps; +using Api.Framework.Model; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 拼多多解析助手 + /// + public class PDDHelper + { + /// + /// 随机对象 + /// + private static Random random = new Random(Guid.NewGuid().GetHashCode()); + + /// + /// 获取随机公共拼多多查询商品信息账号 + /// + /// + public static fl_cps_member RandomGuidePddMembers() + { + try + { + //return CpsClient.GuideMembers[0]; + return CpsClient.GuideMembers[random.Next(0, CpsClient.GuideMembers.Count)]; + } + catch (Exception ex) + { } + return CpsClient.GuideMembers.FirstOrDefault(); + } + + /// + /// 多多进宝app中获取高佣商品的招商id + /// + /// 商id + /// + public static string FindGoodsSign_H5(string goodsid) + { + try + { + try + { + if (GoodsCacheDic.ContainsKey(goodsid)) + { + var GoodsCache = GoodsCacheDic[goodsid]; + if (GoodsCache.GetTime.AddHours(1) > DateTime.Now) + return GoodsCache.GoodsSign; + else + GoodsCacheDic.Remove(goodsid); + } + } + catch (Exception) + { } + + for (int i = 0; i < 3; i++) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = "https://jinbaoh5.pinduoduo.com/network_h5/weak_auth/goods/query_goodslist", + Method = "POST", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = "", + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = @"{""hasCoupon"": false,""pageNumber"": 1,""sortType"": 0,""listId"": """",""pageSize"":10,""keyword"":""" + goodsid + @"""}", + ResultType = ResultType.String + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + + var jobj = JObject.Parse(html); + if (!(bool)jobj["success"]) + continue; + else + { + var goodsList = (JArray)jobj["result"]["goodsList"]; + for (int z = 0; z < goodsList.Count; z++) + { + //var zsDuoId = (int)goodsList[0]["zsDuoId"]; + //if (zsDuoId == 0) return string.Empty; + //return zsDuoId.ToString(); + var goodsSign = goodsList[0]["goodsSign"].ToString(); + if (!string.IsNullOrWhiteSpace(goodsSign)) + { + return goodsSign; + } + } + } + } + catch (Exception ex) + { } + finally + { + Thread.Sleep(200); + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + private static Dictionary GoodsCacheDic = new Dictionary(); + + /// + /// 清理缓存时间 + /// + private static DateTime remove_cache_time = DateTime.Now; + + #region 临时类 + class GoodsCahce + { + public string GoodsSign { get; set; } + public DateTime GetTime { get; set; } + } + #endregion + + /// + /// 缓存异常Cps集合 + /// + private static Dictionary CacheErrCpsDic = new Dictionary(); + + /// + /// 获取商品高佣信息 + /// + /// PinduoduoApi对象 + /// 推广位pid + /// 商品id + /// 是否授权绑定 + /// + public static ArrayList FindSendGuideGoodsInfo(PinduoduoApi api, string pid, string goods_id, bool isBind = false) + { + #region 清理缓存 + if (remove_cache_time.AddHours(5) < DateTime.Now) + { + remove_cache_time = DateTime.Now; + Task.Run(() => + { + try + { + var tmps = GoodsCacheDic.Where(f => f.Value.GetTime.AddHours(1) < DateTime.Now).ToList(); + if (tmps == null || tmps.Count == 0) return; + for (int i = 0; i < tmps.Count; i++) + { + try + { + GoodsCacheDic.Remove(tmps[i].Key); + } + catch (Exception) + { } + } + } + catch (Exception) + { } + }); + } + #endregion + + //获取高佣H5信息 + var goodsSign = FindGoodsSign_H5(goods_id); + if (!string.IsNullOrWhiteSpace(goodsSign)) + { + try + { + if (!GoodsCacheDic.ContainsKey(goods_id)) + GoodsCacheDic[goods_id] = new GoodsCahce() { GoodsSign = goodsSign, GetTime = DateTime.Now }; + } + catch (Exception) + { } + if (!isBind)//true-已绑定;false-未绑定 + { //公用的账号 + var guideCps = RandomGuidePddMembers(); + if (guideCps == null) throw new Exception("公共账号异常"); + var guideApi = CpsClient.CreatePinduoduoRequest(guideCps); + if (guideApi == null) throw new Exception("创建公共请求对象异常"); + var fgInfo = FindGoodsInfo(guideApi, goodsSign, guideCps.cookies); + if (fgInfo != null) + return fgInfo; + } + var goodsInfo = FindGoodsInfo(api, goodsSign, pid); + return goodsInfo; + } + else + { + PinduoduoApi apiTmp = null; + var pidTmp = pid; + var cpsUsername = api.Member.username; + //无法获取高佣这里获取低佣 + for (int i = 0; i < 2; i++) + { + Dictionary obj_ = null; + //if (!isBind)//true-已绑定;false-未绑定 + if (CacheErrCpsDic.ContainsKey(cpsUsername) || !isBind)//true-已绑定;false-未绑定 + { //公用的账号 + var guideCps = RandomGuidePddMembers(); + if (guideCps == null) throw new Exception("公共账号异常"); + var guideApi = CpsClient.CreatePinduoduoRequest(guideCps); + if (guideApi == null) throw new Exception("创建公共请求对象异常"); + apiTmp = guideApi; + pidTmp = guideCps.cookies; + } + else + apiTmp = api; + if (apiTmp == null) continue; + try + { + obj_ = apiTmp.SendPinduoduo("pdd.ddk.oauth.goods.search", new + { + keyword = goods_id, + pid = pidTmp, + //custom_parameters = "{\"uid\":\"602172712\",\"sid\":\"jdds\"}" + //page = 1, + //page_size = 10, + //with_coupon = true + }); + + if (obj_ == null) throw new Exception("创建拼多多API请求失败3"); + + var goods_detail_response = obj_["goods_search_response"] as Dictionary; + var goods_list = goods_detail_response["goods_list"] as ArrayList; + + if (goods_list != null && goods_list.Count != 0) + { + var tmp = goods_list[0] as Dictionary; + if (tmp != null && tmp.Count == 2) + return FindGoodsInfo(api, tmp["goods_sign"].ToString(), pid); + } + return goods_list; + } + catch (Exception ex) + { + if (ex.Message.Contains("涉嫌爬虫或本地缓存商品信息")) + { + CacheErrCpsDic[apiTmp.Member.username] = apiTmp.Member.username; + cpsUsername = apiTmp.Member.username; + } + EventClient.OnEvent(null, $"拼多多:public -> {apiTmp.Member.username} 异常:{ex.Message} - {ex.StackTrace} - {(obj_ == null ? string.Empty : JsonConvert.SerializeObject(obj_))}"); + } + finally + { + Thread.Sleep(200); + } + } + } + return null; + } + + /// + /// 获取商品高佣信息 + /// + /// PinduoduoApi对象 + /// 参数 + /// + public static ArrayList FindSendGuideGoodsInfo(PinduoduoApi api, object data) + { + //公用的账号 + var guideCps = RandomGuidePddMembers(); + if (guideCps == null) throw new Exception("公共账号异常"); + var guideApi = CpsClient.CreatePinduoduoRequest(guideCps); + if (guideApi == null) throw new Exception("创建公共请求对象异常"); + var obj_ = guideApi.SendPinduoduo("pdd.ddk.oauth.goods.search", data); + if (obj_ == null) throw new Exception("创建拼多多API请求失败2"); + //解析商品,获取商品的信息 + var goods_detail_response = obj_["goods_search_response"] as Dictionary; + return goods_detail_response["goods_list"] as ArrayList; + } + + /// + /// 查询商品信息(自己的账号,以保佣金比例的正确性) + /// + /// PinduoduoApi对象 + /// 商品sign + /// 推广位pid + /// + public static ArrayList FindGoodsInfo(PinduoduoApi api, string goods_sign, string pid) + { + try + { + var obj_ = api.SendPinduoduo("pdd.ddk.oauth.goods.search", new { goods_sign_list = $"[\"{goods_sign}\"]", pid = pid }); + + if (obj_ == null) throw new Exception("创建拼多多API请求失败2"); + //解析商品,获取商品的信息 + var goods_detail_response = obj_["goods_search_response"] as Dictionary; + return goods_detail_response["goods_list"] as ArrayList; + + + //var obj_ = api.SendPinduoduo("pdd.ddk.goods.detail", new { goods_sign = goods_sign, pid = pid }); + + //if (obj_ == null) throw new Exception("创建拼多多API请求失败2"); + ////解析商品,获取商品的信息 + //var goods_detail_response = obj_["goods_detail_response"] as Dictionary; + //return goods_detail_response["goods_details"] as ArrayList; + + + + } + catch (Exception ex) + { } + return null; + } + + /// + /// 获取拼多多链接中的商品ID + /// + /// 拼多多商品连接 + /// + public static string GetPddGoodsID(string url) + { + bool flag = false; + if (url.Contains("goods_id")) flag = true; + + var _url = HttpExtend.RegexMatchUrl(url); + if (!flag && !string.IsNullOrWhiteSpace(_url))//有链接的情况 + { + //TODO 这里好像还有短连接 目前忘记了短连接的格式 + + url = _url; + if (Regex.IsMatch(url, "(http[s]?://url.cn|http[s]?://a.toutiaonanren.com|http[s]?://p.pinduoduo.com)", RegexOptions.IgnoreCase)) + { + //可能为短网址//跳转换成真实地址 + url = HttpHelper.URLDecode(GetLocation(url)); + if (url == null || !url.Contains("goods_id")) return string.Empty; + else flag = true; + } + else + flag = true; + } + if (flag) + { + var reg = Regex.Match(url, @"goods_id=(?\d{4,})"); + if (reg.Success) + return reg.Groups["good_id"].ToString(); + reg = Regex.Match(HttpHelper.URLDecode(url), @"goods_id=(?\d{4,})"); + if (reg.Success) + return reg.Groups["good_id"].ToString(); + reg = Regex.Match(HttpHelper.URLDecode(url), @"pinduoduo(?:.*)?goodsId=(?\d{4,})", RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups["good_id"].ToString(); + } + return string.Empty; + } + + /// + /// 获取页面的真实Location的地址(比如:获取短连接的真实地址) + /// + /// 链接 + /// + private static string GetLocation(string url) + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = "", + UserAgent = "Opera/9.27 (Windows NT 5.2; U; zh-cn)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "text/html", + Referer = "", + Postdata = "", + }; + HttpResult result = http.GetHtml(item); + return result.Header.Get("Location"); + } + + + /// + /// 获取单人团 / 多人团地址 + /// + /// PinduoduoApi对象 + /// 接口的必要参数 + /// + public string GetShoppingUrl(PinduoduoApi api, object obj) + { + for (int i = 0; i < 3; i++) + { + try + { + var goods_promotion_url_generate_response = api.SendPinduoduo("pdd.ddk.oauth.goods.prom.url.generate", obj)["goods_promotion_url_generate_response"] as Dictionary; + + var goods_promotion_url_list = goods_promotion_url_generate_response["goods_promotion_url_list"] as ArrayList; + string url = string.Empty; + foreach (var _url in goods_promotion_url_list) + { + //return (_url as Dictionary)["short_url"].ToString(); + return (_url as Dictionary)["mobile_short_url"].ToString(); + } + } + catch (Exception ex) + { } + Thread.Sleep(100); + } + return string.Empty; + } + + /// + /// + /// + /// PinduoduoApi对象 + /// 参数 + /// + public Dictionary GetShoppingUrls(PinduoduoApi api, object obj) + { + for (int i = 0; i < 2; i++) + { + try + { + var goods_promotion_url_generate_response = api.SendPinduoduo("pdd.ddk.oauth.goods.prom.url.generate", obj)["goods_promotion_url_generate_response"] as Dictionary; + + var goods_promotion_url_list = goods_promotion_url_generate_response["goods_promotion_url_list"] as ArrayList; + string url = string.Empty; + foreach (var _url in goods_promotion_url_list) + { + return (_url as Dictionary); + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"生成拼多多推广连接失败:{ex.Message},{ex.StackTrace}"); + } + Thread.Sleep(100); + } + return null; + } + + } +} diff --git a/类库/Api.Framework/Tools/PointManageConfig.cs b/类库/Api.Framework/Tools/PointManageConfig.cs new file mode 100644 index 0000000..5c8eea3 --- /dev/null +++ b/类库/Api.Framework/Tools/PointManageConfig.cs @@ -0,0 +1,1015 @@ +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Robot.Framework.Utils; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + [Config(Name = "插件-积分管理-配置")] + public class PointManageConfig + { + + #region 签到 + /// + /// 签到开关 + /// + [ + Category("1)、签到设置"), DisplayName("01.签到开关"), DefaultValue(SwitchType.开启), + Description(@"签到开关设置") + ] + public SwitchType Checkin_Switch { get; set; } + + /// + /// 签到周期 + /// + [ + Category("1)、签到设置"), DisplayName("02.签到周期"), DefaultValue(@"24"), + Description(@"签到周期,单位:小时"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public int Checkin_Period { get; set; } + + /// + /// 签到指令 + /// + [ + Category("1)、签到设置"), DisplayName("03.签到指令"), DefaultValue(@"^(签到|打卡)$"), + Description(@"签到指令,支持正则表达"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Checkin_CMD { get; set; } + /// + /// 签到最小积分奖励 + /// + [ + Category("1)、签到设置"), DisplayName("04.最小奖励"), DefaultValue(0.01), + Description(@"签到奖励积分区间最小值") + ] + public double Checkin_Reward_Min { get; set; } + /// + /// 签到最大积分奖励 + /// + [ + Category("1)、签到设置"), DisplayName("05.最大奖励"), DefaultValue(0.05), + Description(@"签到奖励积分区间最大值") + ] + public double Checkin_Reward_Max { get; set; } + + /// + /// 签到成功提示语 + /// + [ + Category("1)、签到设置"), DisplayName(@"06.签到成功"), DefaultValue(@"一一一一签 到 成 功一一一一 +【获得奖励】[签到奖励] [积分名称] +【连续签到】[连续签到次数] 次 +【签到次数】[总共签到次数] 次 +【剩余积分】[剩余积分] [积分名称] +【每日语录】[每日语录]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[签到奖励]、[连续签到次数]、[总共签到次数]、[剩余积分]、[积分名称]、[每日语录]、[连续签到次数]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckinSuccessTip { get; set; } + + /// + /// 重复签到提示语 + /// + [ + Category("1)、签到设置"), DisplayName(@"07.重复签到"), DefaultValue(@"一一一一签 到 失 败一一一一 +每日只可以签到一次哦,不要重复签到哦!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckinRepeatTip { get; set; } + /// + /// 无购物禁止签到开关 + /// + [ + Category("1)、签到设置"), DisplayName("08.无购物禁止签到开关"), DefaultValue(SwitchType.关闭), + Description(@"无购物禁止签到开关") + ] + public SwitchType Restrict_Switch { get; set; } + + private int _CheckinRestrictMonth; + /// + /// 限制签到提示语 + /// + [ + Category("1)、签到设置"), DisplayName(@"09.无购物禁止签到月数"), DefaultValue(1), + Description(@"自定义无购物禁止签到的月数,默认1个月") + ] + public int CheckinRestrictMonth + { + get + { + return _CheckinRestrictMonth; + } + set + { + if (value <= 0) + _CheckinRestrictMonth = 1; + else + _CheckinRestrictMonth = value; + } + } + + /// + /// 限制签到提示语 + /// + [ + Category("1)、签到设置"), DisplayName(@"10.无购物禁止签到提示语"), DefaultValue(@"一一一一签 到 限 制一一一一 +您的账号活跃度不足,签到已被限制!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckinRestrictTip { get; set; } + + #endregion + + #region 查看积分 + /// + /// 查看个人积分指令 + /// + [ + Category("2)、积分设置"), DisplayName("01.查询指令"), DefaultValue(@"^(余额|积分|账单|信息|明细|个人信息)$"), + Description(@"用户查看个人积分信息"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckUserPoint_CMD { get; set; } + + /// + /// 查看个人积分成功提示语 + /// + [ + Category("2)、积分设置"), DisplayName("02.查询成功"), DefaultValue(@"一一一一查 询 成 功一一一一 +【剩余积分】[剩余积分] [积分名称] +【累计获得】[累计积分] [积分名称] +一一一一订 单 相 关一一一一 +【多多待结】[拼多多待结算数量]笔/[拼多多待结算金额]元 +【淘宝待结】[淘宝待结算数量]笔/[淘宝待结算金额]元 +【京东待结】[京东待结算数量]笔/[京东待结算金额]元 +【唯品待结】[唯品会待结算数量]笔/[唯品会待结算金额]元 +【抖音待结】[抖音待结算数量]笔/[抖音待结算金额]元 +【苏宁待结】[苏宁待结算数量]笔/[苏宁待结算金额]元 +【待结汇总】[待结算总数数量]笔/[待结算总数金额]元 +【订单记录】[订单记录] +一一一一一一一一一一一一一 +收货后延迟2-5天,会自动给您结算!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[支付宝姓名]、[支付宝账号]、[剩余积分]、[提成积分]、[累计积分]、[其他积分]、[推广积分]、[消费积分]、[积分名称]、 +[拼多多冻结金额]、[拼多多冻结订单数]、[拼多多未收货金额]、[拼多多未收货订单数]、[拼多多待结算数量]、[拼多多待结算金额]、 +[淘宝冻结金额]、[淘宝冻结订单数]、[淘宝未收货金额]、[淘宝未收货订单数]、[淘宝待结算数量]、[淘宝待结算金额]、 +[京东冻结金额]、[京东冻结订单数]、[京东未收货金额]、[京东未收货订单数]、[京东待结算数量]、[京东待结算金额]、 +[抖音冻结金额]、[抖音冻结订单数]、[抖音未收货金额]、[抖音未收货订单数]、[抖音待结算数量]、[抖音待结算金额]、 +[苏宁冻结金额]、[苏宁冻结订单数]、[苏宁未收货金额]、[苏宁未收货订单数]、[苏宁待结算数量]、[苏宁待结算金额]、 +[快手冻结金额]、[快手冻结订单数]、[快手未收货金额]、[快手未收货订单数]、[快手待结算数量]、[快手待结算金额]、 +[唯品会冻结金额]、[唯品会冻结订单数]、[唯品会未收货金额]、[唯品会未收货订单数]、[唯品会待结算数量]、[唯品会待结算金额]、 +[未收货总金额]、[冻结总金额]、[未收货订单数]、[冻结订单数]、[待结算总数数量]、[待结算总数金额]、 +[淘宝售后中订单数]、[京东售后中订单数]、[唯品会售后中订单数]、[抖音售后中订单数]、[苏宁售后中订单数]、[订单总数]、[今日总订单]、[已退款订单数]、[今日总积分]、[已退款积分]、[已兑换积分]、[兑换中积分]、[下级总提成]、[推荐人数]、[订单记录]、 +[完成首单人数]、[未完成首单人数]、[三级有效人数]、[三级邀请人数]、[下级列表]"), + + //[待结算订单数]、[待收货订单数]、[待收货积分]、[待结算积分]、 + + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string CheckPointSuccessTip { get; set; } + + #endregion + + #region 绑定支付宝 + /// + /// 绑定支付宝开关 + /// + [ + Category("3)、支付宝设置"), DisplayName("01.支付宝开关"), DefaultValue(SwitchType.关闭), + Description(@"支付宝开关功能,将决定是否使用支付宝人工审核") + ] + public SwitchType AlipaySwitch { get; set; } + + /// + /// 绑定支付宝指令 + /// + [ + Category("3)、支付宝设置"), DisplayName("02.绑定指令"), DefaultValue(@"^绑定\s+(?<账号>[^\s]+?)\s+(?<名称>[^\s]+?)$"), + Description(@"用户绑定支付宝,支持正则表达式 +正则变量别名:<账号>、<名称> 【 账户:支付宝账号 ; 名称:支付宝名称 】 +作用于:绑定支付宝、修改支付宝 操作 +"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Alipay_Bind_CMD { get; set; } + + /// + /// 支付宝绑定平台 + /// + [ + Category("3)、支付宝设置"), DisplayName("03.绑定平台"), DefaultValue(@"微信"), + Description(@"需要绑定的平台:微信、QQ、微信公众号"), + Editor(typeof(ChatTypeControl), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Alipay_ChatType { get; set; } + + /// + /// 支付宝绑定成功 + /// + [ + Category("3)、支付宝设置"), DisplayName("04.绑定成功"), DefaultValue(@"一一一一绑 定 成 功一一一一 +【姓名】[支付宝姓名] +【账号】[支付宝账号] +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[支付宝姓名]、[支付宝账号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string AlipayBindSuccessTip { get; set; } + #endregion + + #region 绑定身份证 + /// + /// 绑定身份证开关 + /// + [ + Category("4)、身份证绑定"), DisplayName("01.提现绑定身份证开关"), DefaultValue(SwitchType.关闭), + Description(@"提现绑定身份证开关,关闭不用给用户绑定身份证即可提现,反之提现需要绑定身份证") + ] + public SwitchType IdentityIdSwitch { get; set; } + + /// + /// 身份证真实性AppKey + /// + [ + Category("4)、身份证绑定"), DisplayName("02.身份证真实性AppKey"), + Description(@""), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdCheckAppKey { get; set; } + + /// + /// 身份姓名匹配AppKey + /// + [ + Category("4)、身份证绑定"), DisplayName("03.身份姓名匹配AppKey"), + Description(@""), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdMatchAppKey { get; set; } + + /// + /// 身份证绑指令 + /// + [ + Category("4)、身份证绑定"), DisplayName("04.身份证绑定指令"), DefaultValue(@"^身份证\s+(?<身份证号>.+?)\s+(?<姓名>.+?)$"), + Description(@"用户绑定支付宝,支持正则表达式 +正则变量别名:<身份证号>、<姓名> 【身份证号:身份证上的证件号 ; 姓名:身份证上的姓名】 +作用于:绑定身份证、修改身份证 操作 +"), Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityId_Bind_CMD { get; set; } + + /// + /// 身份证绑定成功 + /// + [ + Category("4)、身份证绑定"), DisplayName("05.绑定成功"), DefaultValue(@"一一一一绑 定 成 功一一一一 +【姓名】[身份证姓名] +【身份证】[身份证号码] +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[身份证姓名]、[身份证号码]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdBindSuccessTip { get; set; } + + /// + /// 身份证绑定失败 + /// + [ + Category("4)、身份证绑定"), DisplayName("06.绑定失败"), DefaultValue(@"一一一一绑 定 失 败一一一一 +【姓名】[身份证姓名] +【身份证】[身份证号码] +【失败原因】姓名和身份证不匹配 +一一一一一一一一一一一一一 +以上身份证号码不合法,请核对后重试"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[身份证姓名]、[身份证号码]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdBindUSuccessTip { get; set; } + + /// + /// 身份证未绑定 - 提现操作 + /// + [ + Category("4)、身份证绑定"), DisplayName("07.身份证未绑定 - 提现操作"), DefaultValue(@"一一一一提 现 失 败一一一一 +当前无法提现 +原因: +未绑定身份证请发送 【身份证 身份证号 姓名】 +例如:身份证 123456789123456789 小明 +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[身份证姓名]、[身份证号码]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string IdentityIdUnBindExchangeTip { get; set; } + + #endregion + + #region 提现设置 + /// + /// 无购物记录禁止提现 + /// + [ + Category("5)、提现设置"), DisplayName("01.无购物记录禁止提现"), DefaultValue(SwitchType.关闭), + Description(@"开启时,禁止无购物记录的人进行提现操作") + ] + public SwitchType Unsettled_Forbid_Exchange { get; set; } + + /// + /// 兑换指令 + /// + [ + Category("5)、提现设置"), DisplayName("02.兑换指令"), DefaultValue(@"^(兑换|提现|转账)$"), + Description(@"积分提现指令"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Exchange_CMD { get; set; } + + /// + /// 开启整数提现 + /// + [ + Category("5)、提现设置"), DisplayName("03.开启整数提现"), DefaultValue(SwitchType.关闭), + Description(@"开启时,兑换的金额包含小数,小数部分将不予提现 +注:金额小于1将不生效") + ] + public SwitchType Integer_Exchange_Switch { get; set; } + + [Browsable(false)] + private double _exchange_Min_Point { get; set; } + /// + /// 兑换最低积分 + /// + [ + Category("5)、提现设置"), DisplayName("04.每次最低提现额度"), DefaultValue(1.00), + Description(@"每次最低提现额度,低于这个金额的用户无法执行提现操作") + ] + public double Exchange_Min_Point + { + get { return _exchange_Min_Point; } + set + { + if (value <= 0) + _exchange_Min_Point = 0.01; + else + _exchange_Min_Point = value; + } + } + + [Browsable(false)] + public double _exchange_Max_Point { get; set; } + /// + /// 兑换最高积分 + /// + [ + Category("5)、提现设置"), DisplayName("05.每次最高提现额度"), DefaultValue(100.00), + Description(@"每次最高提现额度") + ] + public double Exchange_Max_Point + { + get { return _exchange_Max_Point; } + set + { + if (value <= 0) + _exchange_Max_Point = 0.01; + else + _exchange_Max_Point = value; + } + } + + [Browsable(false)] + public long _exchange_Num { get; set; } + /// + /// 每日兑换次数 + /// + [ + Category("5)、提现设置"), DisplayName("06.每日最多兑换次数"), DefaultValue(1L), + Description(@"每位用户当天最多提现的次数") + ] + public long Exchange_Num + { + get { return _exchange_Num; } + set + { + if (value < 0) + _exchange_Num = 1; + else + _exchange_Num = value; + } + } + + /// + /// 新用户提现次数限制开关 + /// + [ + Category("5)、提现设置"), DisplayName("07.新用户提现限制开关"), DefaultValue(SwitchType.关闭), + Description(@"开启时,新人提现将被限制,直接进入人工审核") + ] + public SwitchType Audit_Exchange_Frequency_SwitchType { get; set; } + + /// + /// 新用户提现次数限制 + /// + [ + Category("5)、提现设置"), DisplayName("08.新用户提现限制"), DefaultValue(2), + Description(@"该值为提现次数限制值,新用户提现次数小于等于该值将人工审核") + ] + public long Audit_Exchange_Frequency_Baseline { get; set; } + + /// + /// 超过提现次数限制 + /// + [ + Category("5)、提现设置"), DisplayName("09.新用户提现限制 - 通知机器人"), DefaultValue(@"审核通知 +———— +通知事件:新用户提现 +兑换金额:[提现金额] +微信账号:[机器人账号] +微信昵称:[机器人昵称] +客户账号:[账号] +客户昵称:[昵称] +创建时间:[创建时间]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[提现金额]、[剩余积分]、[积分名称]、[支付宝姓名]、[支付宝账号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeFrequencyLimitDingdingTip { get; set; } + + [ +Category("5)、提现设置"), DisplayName("10.限制提现"), DefaultValue(@"一一一一提 现 限 制一一一一 +您的账户被冻结 +账户冻结解除:[限制兑换时间] + +如有疑问联系管理员"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[限制兑换时间]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) +] + public string Ban_Exchange_Tip { get; set; } + + [ + Category("5)、提现设置"), DisplayName("11-1.禁止提现_无结算订单"), DefaultValue(@"一一一一提 现 失 败一一一一 +您未有消费记录,系统积分不予提现操作"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Unsettled_Forbid_Exchange_Tip { get; set; } + + [ + Category("5)、提现设置"), DisplayName("11-2.禁止提现_无付款订单"), DefaultValue(@"一一一一提 现 失 败一一一一 +您未有消费记录,系统积分不予提现操作"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string NotReceiving_Forbid_Exchange_Tip { get; set; } + + /// + /// 成功提交兑换提示语 + /// + [ + Category("5)、提现设置"), DisplayName("12.申请成功"), DefaultValue(@"一一一一申 请 成 功一一一一 +【申请金额】[提现金额][积分名称] +【剩余金额】[剩余积分][积分名称] +一一一一一一一一一一一一一 +客服会在24小时内处理,节假日会有延迟!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[提现金额]、[剩余积分]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeSuccessTip { get; set; } + + /// + /// 成功提交兑换提示语 + /// + [ + Category("5)、提现设置"), DisplayName("13.申请成功 - 通知机器人"), DefaultValue(@"审核通知 +———— +兑换金额:[提现金额] +平台类型:[平台类型] +平台账号:[机器人账号] +平台昵称:[机器人昵称] +客户账号:[账号] +客户昵称:[昵称] +创建时间:[创建时间]"), + Description(@"支持变量:[平台类型]、[机器人账号]、[机器人昵称]、[账号]、[昵称]、[提现金额]、[剩余积分]、[积分名称]、[支付宝姓名]、[支付宝账号]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeSuccessDingdingTip { get; set; } + + /// + /// 申请失败-未绑定支付宝 + /// + [ + Category("5)、提现设置"), DisplayName("14.申请失败-未绑定支付宝"), DefaultValue(@"一一一一兑 换 失 败一一一一 +请告诉我们您的支付宝收款账号! + +指令:绑定 支付宝账号 姓名 +例如:绑定 18100000000 张三 +一一一一一一一一一一一一一 +绑定成功后,再重新申请提现哦"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeUnBindAlipayTip { get; set; } + + /// + /// 申请失败-重复提交 + /// + [ + Category("5)、提现设置"), DisplayName("15.申请失败-重复提交"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您有[提现金额][积分名称]正在审核,请耐心等待!"), + Description(@"上一笔未处理,不予申请二次兑换 + 支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[提现金额]、[冻结总金额]、[未收货总金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeUntreatedTip { get; set; } + + /// + /// 申请失败-积分不足 + /// + [ + Category("5)、提现设置"), DisplayName("16.申请失败-积分不足"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您当前有[剩余积分][积分名称],最低[最低提现额度][积分名称]才可以提现! +待结算积分:[冻结总金额][积分名称] +未收货积分:[未收货总金额][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余积分]、[最低提现额度]、[冻结总金额]、[未收货总金额]、[已兑换积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeErrorTip { get; set; } + + /// + /// 群内提现限制开关 + /// + [ + Category("5)、提现设置"), DisplayName("17.群内提现限制开关"), DefaultValue(SwitchType.关闭), + Description(@"开启时,群内将无法提现,需要添加好友才能进行提现操作") + ] + public SwitchType ExchangeErrorGroupBan_SwitchType { get; set; } + + /// + /// 申请失败-微信群无法提现 + /// + [ + Category("5)、提现设置"), DisplayName("18.申请失败-微信群无法提现"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您当前有[剩余积分][积分名称] +如需兑换请添加好友"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余积分]、[最低提现额度]、[冻结总金额]、[未收货总金额]、[已兑换积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeErrorGroupBanTip { get; set; } + + /// + /// 申请失败-次数不足 + /// + [ + Category("5)、提现设置"), DisplayName("19.申请失败-次数不足"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您今日已兑换[兑换次数]次,已达到上限,请明天再兑换!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换次数]、[剩余积分]、[已兑换积分]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeInsufficientNumTip { get; set; } + + /// + /// 提现失败-审核未过退回 + /// + [ + Category("5)、提现设置"), DisplayName("20.提现失败-审核未过退回"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您申请的[兑换金额][积分名称]已退回! +原因:[备注]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[积分名称]、[剩余积分]、[已兑换积分]、[备注]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeReturnTip { get; set; } + + /// + /// 提现失败-审核未过没收 + /// + [ + Category("5)、提现设置"), DisplayName("21.提现失败-审核未过没收"), DefaultValue(@"一一一一兑 换 失 败一一一一 +您申请的[兑换金额][积分名称]已没收! +原因:[备注]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[剩余积分]、[已兑换积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeConfiscateTip { get; set; } + + /// + /// 提现成功-通过审核 + /// + [ + Category("5)、提现设置"), DisplayName("22.提现成功-通过审核"), DefaultValue(@"一一一一兑 换 成 功一一一一 +您申请的[兑换金额][积分名称]已发放,请注意查收! + +Ps:如未收到,请及时给我们留言!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[剩余积分]、[已兑换积分]、[积分名称]、[领取地址](仅限商户有效)"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeAdoptTip { get; set; } + + [ + Category("5)、提现设置"), DisplayName("23.商户付款通知(优先使用小程序)"), DefaultValue(SwitchType.开启), + Description(@"如果商户支持小程序,将会优先推送小程序模板!(届时 5-22 设置的提示语,将不会推送)")] + public SwitchType ExchangeCommercialPayTip_MiniApp { get; set; } = SwitchType.开启; + + /// + /// 商户付款通知 + /// + [ + Category("5)、提现设置"), DisplayName("24.商户付款通知"), DefaultValue(@"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[领取地址]、[兑换金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeCommercialPayTip { get; set; } + + /// + /// 商户付款通知 + /// + [ + Category("5)、提现设置"), DisplayName("25.商户付款通知 - 直接到账"), DefaultValue(@"一一一一商 户 转 账 成 功一一一一 +[兑换金额]兑换成功 +已直接转入您的账户!"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeCommercialEftTip { get; set; } + + private string _notice_robotname; + [Category("5)、提现设置"), DisplayName("26.钉钉/微信群机器人"), DefaultValue("请选择(钉钉/微信群机器人API名称)"), Description(@"请选择已存在的机器人名称,如果还没有添加,在【系统管理->群通知机器人】中添加机器人! +未选择则使用默认系统设置"), TypeConverter(typeof(notice_robotname_item))] + public string notice_robotname + { + get { return _notice_robotname; } + set + { + _notice_robotname = value; + } + } + + public class notice_robotname_item : UI.Framework.Entitys.MyTypeConverter + { + public override string[] GetValues() + { + var session = ApiClient.GetSession(); + var apis = session.FindNoticeapiRobots().ToArray(); + var rst = new List(); + rst.Add("请选择(钉钉/微信群机器人API名称)"); + foreach (var item in apis) rst.Add(item.name); + return rst.ToArray(); + } + } + + #endregion + + #region 提现设置 - (微信自动转账设置) + /// + /// 支付方式 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("01.支付方式"), DefaultValue(PointPayType.关闭), + Description(@"兑换支付方式: +1)、关闭 +2)、转账 +3)、发红包") + ] + public PointPayType Exchange_PayType { get; set; } + + /// + /// 微信自动转账单笔最高上限 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("02.最高额度"), DefaultValue(40.00), + Description(@"微信自动转账,单笔最高兑换上限") + ] + /// + /// 每次自动转账最大金额 + /// + public double Exchange_Transmatic_Maxpoint { get; set; } + /// + /// 微信自动转账每日上限(总金额) + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("03.每日每个机器人最多支付"), DefaultValue(1000.00), + Description(@"微信自动转账,每日最高兑换金额 (防作弊设置,每天每个微信最多支出多少钱,防止被撸羊毛)") + ] + public double Exchange_Transmatic_SumPoint { get; set; } + + /// + /// 微信自动转账红包标题 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("04.红包标题"), DefaultValue(@"兑换成功:[兑换金额]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangePacketTitle { get; set; } + + /// + /// 微信自动转账成功提示语 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("05.转账成功"), DefaultValue(@"一一一一兑 换 成 功一一一一 +您申请的[兑换金额][积分名称]已发放,请注意查收! + +Ps:请及时查询微信红包"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[兑换金额]、[剩余积分]、[已兑换积分]、[积分名称]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string ExchangeTransmaticTip { get; set; } + + /// + /// 未设置支付密码使用商户付款 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("06.未设置支付密码使用商户付款"), DefaultValue(SwitchType.关闭), + Description(@"开启:未设置支付密码使用商户付款") + ] + public SwitchType IsEmptyPasswordUseCommercialPaySwitchType { get; set; } + + /// + /// 微信支付不成功使用商户付款 + /// + [ + Category("6)、提现设置 - 微信自动转账设置"), DisplayName("07.微信支付不成功使用商户付款"), DefaultValue(SwitchType.关闭), + Description(@"开启:微信支付失败使用商户付款") + ] + public SwitchType IsPaymentFailedUseCommercialPaySwitchType { get; set; } + #endregion + + #region + /// + /// 结算抢红包开关 + /// + [ + Category("7)、抢红包设置"), DisplayName("01.结算抢红包开关"), DefaultValue(SwitchType.关闭), + Description(@"开启时,结算一个订单可以获取一个抢红包的机会") + ] + public SwitchType Extra_Award_Switch { get; set; } + + /// + /// 结算抢红包指令 + /// + [ + Category("7)、抢红包设置"), DisplayName("02.结算抢红包指令"), DefaultValue(@"^(抢红包)$"), + Description(@"订单结算后抢红包指令"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Extra_Award_CMD { get; set; } + + [Browsable(false)] + private double _Extra_Award_Min_Point { get; set; } + /// + /// 抢红包最低金额 + /// + [ + Category("7)、抢红包设置"), DisplayName("03.抢红包最低金额"), DefaultValue(1.00), + Description(@"抢红包最低金额") + ] + public double Extra_Award_Min_Point + { + get { return _Extra_Award_Min_Point; } + set + { + if (value <= 0) + _Extra_Award_Min_Point = 0.01; + else + _Extra_Award_Min_Point = value; + } + } + + [Browsable(false)] + public double _Extra_Award_Max_Point { get; set; } + /// + /// 抢红包最高金额 + /// + [ + Category("7)、抢红包设置"), DisplayName("04.抢红包最高金额"), DefaultValue(1.50), + Description(@"抢红包最搞金额") + ] + public double Extra_Award_Max_Point + { + get { return _Extra_Award_Max_Point; } + set + { + if (value <= 0) + _Extra_Award_Max_Point = 0.01; + else + _Extra_Award_Max_Point = value; + } + } + + /// + /// 抢红包成功 + /// + [ + Category("7)、抢红包设置"), DisplayName("05.抢红包成功"), DefaultValue(@"一一一一抢 红 包 成 功一一一一 + +恭喜获得红包:[红包金额][积分名称] +当前剩余积分:[剩余积分][积分名称]"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余积分]、[剩余积分]、[冻结总金额]、[未收货总金额]、[红包金额]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Extra_AwardSuccessTip { get; set; } + + + /// + /// 抢红包失败 + /// + [ + Category("7)、抢红包设置"), DisplayName("05.抢红包失败"), DefaultValue(@"一一一一抢 红 包 失 败一一一一 + +当前无抢红包机会"), + Description(@"支持变量:[机器人账号]、[机器人昵称]、[账号]、[昵称]、[剩余积分]、[冻结总金额]、[未收货总金额]"), + Editor(typeof(PropertyGridRichText), typeof(System.Drawing.Design.UITypeEditor)) + ] + public string Extra_AwardErrorTip { get; set; } + #endregion + + public PointManageConfig() + { + + #region 签到 + this.Restrict_Switch = SwitchType.关闭; + this._CheckinRestrictMonth = 1; + this.Checkin_Period = 24; + this.Checkin_Switch = SwitchType.开启; + this.Checkin_CMD = @"^(签到|打卡)$"; + this.Checkin_Reward_Min = 0.01; + this.Checkin_Reward_Max = 0.05; + this.CheckinSuccessTip = @"一一一一签 到 成 功一一一一 +【获得奖励】[签到奖励] [积分名称] +【连续签到】[连续签到次数] 次 +【签到次数】[总共签到次数] 次 +【剩余积分】[剩余积分] [积分名称] +【每日语录】[每日语录]"; + this.CheckinRepeatTip = @"一一一一签 到 失 败一一一一 +每日只可以签到一次哦,不要重复签到哦!"; + this.CheckinRestrictTip = @"一一一一签 到 限 制一一一一 +您的账号活跃度不足,签到已被限制!"; + #endregion + + #region 支付宝绑定 + this.AlipaySwitch = SwitchType.关闭; + this.Alipay_ChatType = "微信"; + this.Alipay_Bind_CMD = @"^绑定\s+(?<账号>[^\s]+?)\s+(?<名称>[^\s]+?)$"; + this.CheckUserPoint_CMD = @"^(余额|积分|账单|信息|明细|个人信息)$"; + this.CheckPointSuccessTip = @"一一一一查 询 成 功一一一一 +【剩余积分】[剩余积分] [积分名称] +【累计获得】[累计积分] [积分名称] +一一一一订 单 相 关一一一一 +【多多待结】[拼多多待结算数量]笔/[拼多多待结算金额]元 +【淘宝待结】[淘宝待结算数量]笔/[淘宝待结算金额]元 +【京东待结】[京东待结算数量]笔/[京东待结算金额]元 +【唯品待结】[唯品会待结算数量]笔/[唯品会待结算金额]元 +【抖音待结】[抖音待结算数量]笔/[抖音待结算金额]元 +【苏宁待结】[苏宁待结算数量]笔/[苏宁待结算金额]元 +【待结汇总】[待结算总数数量]笔/[待结算总数金额]元 +【订单记录】[订单记录] +一一一一一一一一一一一一一 +收货后延迟2-5天,会自动给您结算!"; + this.AlipayBindSuccessTip = @"一一一一绑 定 成 功一一一一 +【姓名】[支付宝姓名] +【账号】[支付宝账号] +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"; + #endregion + + #region 初始化数据 + this.notice_robotname = "请选择(钉钉/微信群机器人API名称)"; + this.Integer_Exchange_Switch = SwitchType.关闭; + this.Audit_Exchange_Frequency_SwitchType = SwitchType.关闭; + this.Audit_Exchange_Frequency_Baseline = 2; + this.Unsettled_Forbid_Exchange = SwitchType.关闭; + this.Exchange_CMD = @"^(兑换|提现|转账)$"; + this._exchange_Num = 1L; + this._exchange_Min_Point = 1.00; + this._exchange_Max_Point = 100.00; + this.Exchange_PayType = PointPayType.关闭; + this.Exchange_Transmatic_Maxpoint = 40.00; + this.Exchange_Transmatic_SumPoint = 1000.00; + this.IsEmptyPasswordUseCommercialPaySwitchType = SwitchType.关闭; + this.IsPaymentFailedUseCommercialPaySwitchType = SwitchType.关闭; + this.ExchangeFrequencyLimitDingdingTip = @"审核通知 +———— +通知事件:新用户提现 +兑换金额:[提现金额] +微信账号:[机器人账号] +微信昵称:[机器人昵称] +客户账号:[账号] +客户昵称:[昵称] +创建时间:[创建时间]"; + this.IdentityIdUnBindExchangeTip = @"一一一一提 现 失 败一一一一 +当前无法提现 +原因: +未绑定身份证请发送 【身份证 身份证号 姓名】 +例如:身份证 123456789123456789 小明 +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"; + this.IdentityIdBindUSuccessTip = @"一一一一绑 定 失 败一一一一 +【姓名】[身份证姓名] +【身份证】[身份证号码] +【失败原因】姓名和身份证不匹配 +一一一一一一一一一一一一一 +以上身份证号码不合法,请核对后重试"; + this.IdentityIdBindSuccessTip = @"一一一一绑 定 成 功一一一一 +【姓名】[身份证姓名] +【身份证】[身份证号码] +一一一一一一一一一一一一一 +请核对信息,如果有误,请重新绑定!"; + this.IdentityId_Bind_CMD = @"^身份证\s+(?<身份证号>.+?)\s+(?<姓名>.+?)$"; + this.IdentityIdCheckAppKey = string.Empty; + this.IdentityIdMatchAppKey = string.Empty; + this.IdentityIdSwitch = SwitchType.关闭; + this.Ban_Exchange_Tip = @"一一一一提 现 限 制一一一一 +您的账户被冻结 +账户冻结解除:[限制兑换时间] + +如有疑问联系管理员"; + this.Unsettled_Forbid_Exchange_Tip = @"一一一一提 现 失 败一一一一 +您未有消费记录,系统积分不予提现操作"; + this.NotReceiving_Forbid_Exchange_Tip = @"一一一一提 现 失 败一一一一 +您未有消费记录,系统积分不予提现操作"; + this.ExchangeUnBindAlipayTip = @"一一一一兑 换 失 败一一一一 +请告诉我们您的支付宝收款账号! + +指令:绑定 支付宝账号 姓名 +例如:绑定 18100000000 张三 +一一一一一一一一一一一一一 +绑定成功后,再重新申请提现哦"; + this.ExchangeSuccessTip = @"一一一一申 请 成 功一一一一 +【申请金额】[提现金额][积分名称] +【剩余金额】[剩余积分][积分名称] +一一一一一一一一一一一一一 +客服会在24小时内处理,节假日会有延迟!"; + this.ExchangeSuccessDingdingTip = @"审核通知 +———— +兑换金额:[提现金额] +平台类型:[平台类型] +平台账号:[机器人账号] +平台昵称:[机器人昵称] +客户账号:[账号] +客户昵称:[昵称] +创建时间:[创建时间]"; + this.ExchangeErrorTip = @"一一一一兑 换 失 败一一一一 +您当前有[剩余积分][积分名称],最低[最低提现额度][积分名称]才可以提现! +待结算积分:[冻结总金额][积分名称] +未收货积分:[未收货总金额][积分名称]"; + this.ExchangeReturnTip = @"一一一一兑 换 失 败一一一一 +您申请的[兑换金额][积分名称]已退回! +原因:[备注]"; + this.ExchangeAdoptTip = @"一一一一兑 换 成 功一一一一 +您申请的[兑换金额][积分名称]已发放,请注意查收! + +Ps:如未收到,请及时给我们留言!"; + this.ExchangeInsufficientNumTip = @"一一一一兑 换 失 败一一一一 +您今日已兑换[兑换次数]次,已达到上限,请明天再兑换!"; + this.ExchangeErrorGroupBan_SwitchType = SwitchType.关闭; + this.ExchangeErrorGroupBanTip = @"一一一一兑 换 失 败一一一一 +您当前有[剩余积分][积分名称] +如需兑换请添加好友"; + this.ExchangeUntreatedTip = @"一一一一兑 换 失 败一一一一 +您有[提现金额][积分名称]正在审核,请耐心等待!"; + this.ExchangeTransmaticTip = @"一一一一兑 换 成 功一一一一 +您申请的[兑换金额][积分名称]已发放,请注意查收! + +Ps:请及时查询微信红包"; + this.ExchangeConfiscateTip = @"一一一一兑 换 失 败一一一一 +您申请的[兑换金额][积分名称]已没收! +原因:[备注]"; + this.ExchangePacketTitle = @"兑换成功:[兑换金额]"; + + this.ExchangeCommercialPayTip = @"一一一一等 待 领 取一一一一 + +[领取地址] + +点击链接,领取红包到您钱包!"; + this.ExchangeCommercialEftTip = @"一一一一商 户 转 账 成 功一一一一 +[兑换金额]兑换成功 +已直接转入您的账户!"; + #endregion + + #region 额外奖励设置 + this.Extra_Award_Switch = SwitchType.关闭; + this.Extra_Award_CMD = @"^(抢红包)$"; + this._Extra_Award_Min_Point = 1; + this._Extra_Award_Max_Point = 1.5; + this.Extra_AwardSuccessTip = @"一一一一抢 红 包 成 功一一一一 + +恭喜获得红包:[红包金额][积分名称] +当前剩余积分:[剩余积分][积分名称]"; + this.Extra_AwardErrorTip = @"一一一一抢 红 包 失 败一一一一 + +当前无抢红包机会"; + #endregion + + } + } +} diff --git a/类库/Api.Framework/Tools/SNHelper.cs b/类库/Api.Framework/Tools/SNHelper.cs new file mode 100644 index 0000000..cf76384 --- /dev/null +++ b/类库/Api.Framework/Tools/SNHelper.cs @@ -0,0 +1,295 @@ +using Api.Framework.Cps; +using CsharpHttpHelper; +using CsharpHttpHelper.Enum; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 苏宁助手 + /// + public class SNHelper + { + /// + /// 获取苏宁链接中的商品ID + /// + /// 包含抖音链接的文本 + /// + public static SNId GetSNGoodsID(string mess) + { + if (string.IsNullOrWhiteSpace(mess) || + Regex.IsMatch(mess, @"\[图片=(.+?)\]") || + Regex.IsMatch(mess, @"\[视频=(.+?)\]") || + Regex.IsMatch(mess, @"\[卡片=(.+?)\]") || + Regex.IsMatch(mess, @"\[公告=(.+?)\]") || + Regex.IsMatch(mess, @"\[语音=(.+?)\]") + ) + return null; + + try + { + var reg = Regex.Match(mess, @"(?:(?:midfourth.html\?productId=(?\d{10,})&shop=(?\d+))|(?:suning.com/(?\d{10})/(?\d+))|(?:m.suning.com/product/(?\d{10})/(?\d+))|(?:from=APP&productId=(?\d+)&shop=(?\d+)))|(?:shopId=(?\d{10})&storeId=(?\d+))", RegexOptions.IgnoreCase); + if (reg.Success) + { + return new SNId() { goodid = reg.Groups["goodid"].ToString(), shop = reg.Groups["shop"].ToString() }; + } + else + { + if (mess.ToLower().Contains("suning.com")) + { + var _url = HttpExtend.RegexMatchUrl(mess); + if (!string.IsNullOrWhiteSpace(_url)) + { + var cps = new SuNingApi(new Model.fl_cps_member()); + var snGInfo = cps.QuerySearchCommodity(_url); + if (snGInfo.sn_responseContent.sn_error != null) + throw new Exception(snGInfo.sn_responseContent.sn_error.error_msg);//查询没结果 + else if (snGInfo.sn_responseContent.sn_body == null || snGInfo.sn_responseContent.sn_body.querySearchcommodity == null || snGInfo.sn_responseContent.sn_body.querySearchcommodity.Count == 0) + throw new Exception("查询没结果2"); + else if (snGInfo.sn_responseContent.sn_body != null && snGInfo.sn_responseContent.sn_body.querySearchcommodity != null && snGInfo.sn_responseContent.sn_body.querySearchcommodity.Count != 0) + { + return new SNId() { goodid = snGInfo.sn_responseContent.sn_body.querySearchcommodity[0].commodityInfo.commodityCode, shop = snGInfo.sn_responseContent.sn_body.querySearchcommodity[0].commodityInfo.supplierCode }; + } + } + } + } + } + catch (Exception ex) + { + throw new Exception(ex.Message); + } + return null; + + } + + //private static SNId GetSnid(string mess) + //{ + + //} + + #region 内部类 + /// + /// 苏宁id,供应商id(自营为十个0) + /// + public class SNId + { + /// + /// 商品id + /// + public string goodid { get; set; } + /// + /// 供应商id + /// + public string shop { get; set; } + } + #endregion + + } + + #region 苏宁订单类 + /// + /// 响应头 + /// + public class Sn_head + { + /// + /// 总数量 + /// + public string totalSize { get; set; } + /// + /// 总页数 + /// + public string pageTotal { get; set; } + /// + /// 当前页 + /// + public string pageNo { get; set; } + /// + /// 返回状态内容 + /// + public string returnMessage { get; set; } + } + + /// + /// 订单明细 + /// + public class OrderDetail + { + /// + /// 支付时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime payTime { get; set; } + /// + /// 下单时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime orderSubmitTime { get; set; } + /// + /// 订单行项目号 + /// + public string orderLineNumber { get; set; } + /// + /// 订单行项目状态 - 支付完成 + /// + public string orderLineStatusDesc { get; set; } + /// + /// 行项目状态更新时间,格式:yyyy-MM-dd HH:mm:ss + /// + public DateTime orderLineStatusChangeTime { get; set; } + /// + /// 订单行来源(PC端、无线端) + /// + public string orderLineOrigin { get; set; } + /// + /// 商品名称 + /// + public string productName { get; set; } + /// + /// 商品数量 + /// + public string saleNum { get; set; } + /// + /// 实付金额 + /// + public string payAmount { get; set; } + /// + /// 订单行标记 + /// + public string orderLineFlag { get; set; } + /// + /// 子推广账号ID(对应sub_user) + /// + public string childAccountId { get; set; } + /// + /// 商户名称 + /// + public string sellName { get; set; } + /// + /// 商户编码 + /// + public string sellerCode { get; set; } + /// + /// 商品编码 + /// + public string goodsNum { get; set; } + /// + /// 佣金比例 + /// + public string commissionRatio { get; set; } + /// + /// 预估佣金 + /// + public string prePayCommission { get; set; } + /// + /// 一级目录 + /// + public string productFirstCatalog { get; set; } + /// + /// 二级目录 + /// + public string productSecondCatalog { get; set; } + /// + /// 三级目录 + /// + public string productThirdCatalog { get; set; } + /// + /// 商品归属 - 自营 + /// + public string orderType { get; set; } + /// + /// 推广位ID + /// + public string positionId { get; set; } + /// + /// 商品组目录编码 + /// + public string goodsGroupCatalog { get; set; } + /// + /// 推广类型 - 链接推广 + /// + public string saleType { get; set; } + /// + /// 商品主图 + /// + public string pictureUrl { get; set; } + /// + /// 1.风控订单 + /// + public string promotion { get; set; } + /// + /// 是否违规,0:否;1:是 + /// + public string violation { get; set; } + /// + /// 是否返佣,0:否;1:是 + /// + public string returnCommission { get; set; } + /// + /// 推广会员编码 + /// + public string custNo { get; set; } + /// + /// + /// + public string statParam { get; set; } + } + + /// + /// 订单类 + /// + public class QueryOrder + { + /// + /// 订单号 + /// + public string orderCode { get; set; } + /// + /// 订单明细集合 + /// + public List orderDetail { get; set; } + } + + /// + /// 响应体 + /// + public class Sn_body + { + /// + /// 订单集合 + /// + public List queryOrder { get; set; } + } + + /// + /// 响应结构 + /// + public class Sn_responseContent + { + /// + /// 响应头 + /// + public Sn_head sn_head { get; set; } + /// + /// 响应体 + /// + public Sn_body sn_body { get; set; } + } + + /// + /// 订单响应结果 + /// + public class SNOrderResponseResult + { + /// + /// 响应结构 + /// + public Sn_responseContent sn_responseContent { get; set; } + } + + #endregion + +} diff --git a/类库/Api.Framework/Tools/SocketUtil.cs b/类库/Api.Framework/Tools/SocketUtil.cs new file mode 100644 index 0000000..b8c1f96 --- /dev/null +++ b/类库/Api.Framework/Tools/SocketUtil.cs @@ -0,0 +1,83 @@ +using SuperSocket.SocketBase; +using SuperSocket.SocketBase.Protocol; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + public enum SocketCMD:int + { + Wechat登陆成功 = 1, + Wechat收到消息 = 2 + } + public class SuperSocketServer + { + public AppServer Server { get;private set; } + public SuperSocketServer() + { + + } + public void Stop() + { + if (this.Server != null) + { + this.Server.Stop(); + } + } + public bool Start(int port) + { + this.Stop(); + this.Server = new AppServer(); + + if (!Server.Setup(port)) return false; + + //Try to start the appServer + if (!Server.Start()) return false; + + Server.NewSessionConnected += new SessionHandler(appServer_NewSessionConnected); + + Server.SessionClosed += appServer_NewSessionClosed; + + //SocketCMD 是KEY + Server.NewRequestReceived += new RequestHandler(appServer_NewRequestReceived); + + + + return true; + + } + + private void appServer_NewRequestReceived(AppSession session, StringRequestInfo requestInfo) + { + try + { + var cmd = Util.ConvertEnum(int.Parse(requestInfo.Key)); + switch (cmd) + { + case SocketCMD.Wechat登陆成功: + break; + case SocketCMD.Wechat收到消息: + break; + default: + break; + } + } + catch (Exception) + { + } + } + + private void appServer_NewSessionClosed(AppSession session, CloseReason value) + { + + } + + private void appServer_NewSessionConnected(AppSession session) + { + + } + } +} diff --git a/类库/Api.Framework/Tools/SqlSugarEx.cs b/类库/Api.Framework/Tools/SqlSugarEx.cs new file mode 100644 index 0000000..81e754c --- /dev/null +++ b/类库/Api.Framework/Tools/SqlSugarEx.cs @@ -0,0 +1,906 @@ + +using Api.Framework.Model; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 持久层线程池 + /// + public class SessionThreadLocal + { + private static ThreadLocal m_SessionLocal = new ThreadLocal(); + + /// + /// 设置持久层到线程池 + /// + /// + public static void Set(SqlSugarClient session) + { + m_SessionLocal.Value = session; + } + + /// + /// 从线程池获取持久层 + /// + /// + public static SqlSugarClient Get() + { + return m_SessionLocal.Value; + } + + /// + /// 清空线程池 + /// + public static void Clear() + { + foreach (var item in m_SessionLocal.Values) + { + item.Close(); + item.Dispose(); + } + m_SessionLocal.Value = null; + } + } + + /// + /// 数据库链接配置 + /// + public class ConnectionConfig + { + /// + /// 数据库连接信息 + /// + public string ConnectionString { get; set; } + /// + /// 数据库类型 + /// + public DatabaseType DatabaseType { get; set; } + + } + /// + /// 数据库类型枚举,需要扩展类型可在此添加 + /// + public enum DatabaseType : int + { + /// + /// MSSQL数据库 + /// + [Description("MSSQL数据库")] + SQLSERVER = 1, + /// + /// ORACLE数据库 + /// + [Description("ORACLE数据库")] + ORACLE = 2, + /// + /// ACCESS数据库 + /// + [Description("ACCESS数据库")] + ACCESS = 3, + /// + /// MYSQL数据库 + /// + [Description("MYSQL数据库")] + MYSQL = 4, + /// + /// SQLITE数据库 + /// + [Description("SQLITE数据库")] + SQLITE = 5 + } + + /// + /// 数据库基础类 + /// + public class base_model + { + [SugarColumn(IsPrimaryKey = true, IsIdentity = true), Browsable(false), ReadOnly(false)] + public long id { get; set; } + } + + /// + /// 分页查询结果 + /// + /// 数据库表实体类 + public class PageResult + { + /// + /// 分页查询中总记录数 + /// + public int Total { get; set; } + + /// + /// 分页查询中结果集合 + /// + public List DataList { get; set; } + } + + + public class ParamMap + { + public List SugarParameters { get; private set; } + public bool ContainsKey(string name) + { + return this.SugarParameters.FirstOrDefault(f => f.ParameterName == name) != null ? true : false; + } + public ParamMap() + { + OrderBySQL = string.Empty; + SugarParameters = new List(); + } + + public void setParameter(string name, object value) + { + + SugarParameters.Add(new SqlSugar.SugarParameter(name, value)); + } + + public int Index { get; private set; } + public int PageSize { get; private set; } + + public void setPageParamters(int index, int pagesize) + { + this.Index = index; + this.PageSize = pagesize; + } + + + public string OrderBySQL { get; private set; } + /// + /// 设置排序字段及排序方式 + /// + /// 排序字段 + /// 是否为递减排序 + public void setOrderFields(string orderFields, bool isDesc) + { + OrderBySQL = $" Order by {orderFields} " + (isDesc ? "desc" : "asc") + " "; + } + } + public static class SqlSugarExtend + { + + public static PageResult FindPage(this SqlSugarClient session, string sql, ParamMap map) + { + string _temp = string.Empty; + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + _temp = $" limit {map.PageSize} offset {map.PageSize * (map.Index - 1)}"; + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + _temp = $" limit {map.PageSize * (map.Index - 1)},{map.PageSize}"; + } + + //foreach (SugarParameter item in map.SugarParameters) + //{ + // sql = sql.Replace("@"+item.ParameterName,$""); + //} + + PageResult result = new PageResult(); + + result.DataList = session.Ado.SqlQuery(sql + map.OrderBySQL + _temp, map.SugarParameters); + + + //var reg = Regex.Matches(sql, @"(select [\w\W]+ from)"); + //if (reg.Count > 0) + //{ + + //} + //var temp = Regex.Replace(sql, @"^select [\w\W]+ from", "select count(*) as count from"); + var start_index = sql.IndexOf("from"); + var temp_sql = "select count(*) as count " + sql.Substring(start_index); + + result.Total = int.Parse(session.FindRow(temp_sql, map.SugarParameters)["count"].ToString()); + + return result; + + } + public static ParamMap NewParamMap(this SqlSugarClient session) + { + return new ParamMap(); + } + + /// + /// 创建表 + /// + /// + public static void CreateTable(this SqlSugarClient session, Type type) + { + + //session.CodeFirst.BackupTable().InitTables(type); + + //获取公共属性 + PropertyInfo[] Propertys = type.GetProperties(); + + if (Propertys.Length == 1) throw new Exception("字段最少需要2个。"); + StringBuilder sb = new StringBuilder(); + sb.Append("CREATE TABLE "); + sb.Append(type.Name); + sb.Append("("); + int number = 0; + foreach (var item in Propertys) + { + string _name = $"`{item.Name}`"; + if (_name == "interval") + _name = $"`{_name}`"; + string _type = string.Empty; + bool _primary = false; + var _unique = " "; + var _attribute = item.GetCustomAttributes().FirstOrDefault(f => f.GetType() == typeof(SugarColumn)) as SugarColumn; + if (_attribute != null) + { + _name = _attribute.ColumnName; + //_type = _attribute.ty; + _primary = _attribute.IsPrimaryKey; + // _unique = _attribute.IsUnique ? " unique " : " "; + } + if (string.IsNullOrEmpty(_name)) _name = item.Name; + number++; + sb.Append(_name); + if (item.Name.ToLower() == "id" || _primary) + { + //sb.Append(" integer(11) primary key 自增 not null "); + sb.Append(" integer primary key 自增 not null "); + } + else if (!string.IsNullOrEmpty(_type)) + { + sb.Append(" " + _type + _unique); + } + else + { + sb.Append(" "); + //if (item.PropertyType.FullName == typeof(Int32).ToString() || item.PropertyType.FullName == typeof(Int16).ToString() || item.PropertyType.FullName == typeof(UInt16).ToString() || item.PropertyType.FullName == typeof(Int64).ToString()) + if (item.PropertyType.FullName == typeof(Int32).ToString() || item.PropertyType.FullName == typeof(Int16).ToString() || item.PropertyType.FullName == typeof(UInt16).ToString()) + sb.Append(" integer(11) default 0 " + _unique); + else if (item.PropertyType.FullName == typeof(Int64).ToString()) + sb.Append(" bigint(11) default 0 " + _unique); + + else if (typeof(DateTime).ToString() == item.PropertyType.FullName) + sb.Append(" datetime " + _unique); + else if (typeof(String).ToString() == item.PropertyType.FullName) + { + if (_name.ToUpper() == "message".ToUpper() || _name.ToUpper() == "answer".ToUpper() || _name.ToUpper() == "token".ToUpper() || _name.ToUpper() == "dicvalue".ToUpper() || _name.ToUpper() == "ExtInfo".ToUpper() || _name.ToUpper() == "Signature".ToUpper() || _name.ToUpper() == "adzones".ToUpper() || _name.ToUpper() == "data".ToUpper() || _name.ToUpper() == "device_info".ToUpper() || _name.ToUpper().EndsWith("_text".ToUpper()) || _name.ToUpper().EndsWith("dic".ToUpper())) + { + if (session.CurrentConnectionConfig.DbType == DbType.MySql && _name.ToUpper().EndsWith("dic".ToUpper())) + { + sb.Append(" longtext " + _unique); + } + else + sb.Append(" text " + _unique); + } + else + sb.Append(" varchar(" + (_attribute == null ? 255 : (_attribute.Length == 0 ? 255 : _attribute.Length)) + ") default ''" + _unique); + } + + else if (item.PropertyType.FullName == typeof(Char).ToString()) + sb.Append(" varchar(2) default ''" + _unique); + else if (item.PropertyType.FullName == typeof(Boolean).ToString()) + sb.Append(" boolean " + _unique); + else if (item.PropertyType.FullName == typeof(Double).ToString()) + sb.Append(" double default 0.00" + _unique); + else + { + if (item.PropertyType.BaseType.Name == "Enum") + { + sb.Append(" integer default 0 " + _unique); + } + else + { + throw new Exception("不支持" + item.PropertyType.FullName + "字段,请联系框架设计师处理。"); + } + } + } + if (number != Propertys.Length) + { + sb.Append(","); + } + } + sb.Append(");"); + string sql = sb.ToString(); + if (sql.Contains("自增")) + { + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + sql = sql.Replace("自增", "AUTOINCREMENT").Replace("AUTO_INCREMENT", "AUTOINCREMENT"); + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + sql = sql.Replace("自增", "AUTO_INCREMENT").Replace("AUTOINCREMENT", "AUTO_INCREMENT"); + } + } + + session.ExcuteSQL(sql); + } + + public static void CreateTable(this SqlSugarClient session) + { + session.CreateTable(typeof(T)); + } + + public static void Update(this SqlSugarClient session, base_model model, object param = null) + { + StringBuilder sb = new StringBuilder("update " + model.GetType().Name + " set "); + ParamMap map = session.NewParamMap(); + if (param != null) + { + PropertyInfo[] propertys = param.GetType().GetProperties(); + int number = 0; + foreach (System.Reflection.PropertyInfo p in propertys) + { + number++; + sb.Append(p.Name + "=@" + p.Name); + map.setParameter(p.Name, p.GetValue(param)); + if (propertys.Length != number) sb.Append(","); + } + map.setParameter("id", model.id); + sb.Append(" where id=@id;"); + } + } + + public static bool IndexExist(this SqlSugarClient session, params object[] values) + { + return IndexExist(session, typeof(T).Name, values); + } + + public static bool IndexExist(this SqlSugarClient session, string tableName, params object[] values) + { + var indexName = tableName + "__" + string.Join("_", values); + if (indexName.Length > 64) + indexName = indexName.Substring(0, 64); + + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + var db_name = string.Empty; + var reg = Regex.Match(session.CurrentConnectionConfig.ConnectionString, "Data Source=(?.*?);Initial Catalog=(?.*?);Persist Security Info=True;User ID=(?.*?);Password=(?.*?);Port=(?.*?);"); + if (reg.Success) + db_name = reg.Groups["db_name"].ToString(); + var row = session.FindRow("SELECT * FROM information_schema.statistics WHERE table_schema = @db_name and table_name = @tableName AND index_name = @indexName", new { db_name = db_name, tableName = tableName, indexName = indexName }); + if (row != null) return true; + } + else if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + var row = session.FindRow("SELECT * FROM sqlite_master WHERE type = 'index' and tbl_name = @tableName and name = @indexName", new { tableName = tableName, indexName = indexName }); + if (row != null) return true; + } + return false; + } + + /// + /// 索引是否存在 + /// + /// + /// + /// + /// + public static bool IndexExist(this SqlSugarClient session, string indexName) + { + return IndexExist(session, typeof(T).Name, indexName); + } + + /// + /// 索引是否存在 + /// + /// + /// + /// + /// + public static bool IndexExist(this SqlSugarClient session, string tableName, string indexName) + { + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + var db_name = string.Empty; + var reg = Regex.Match(session.CurrentConnectionConfig.ConnectionString, "Data Source=(?.*?);Initial Catalog=(?.*?);Persist Security Info=True;User ID=(?.*?);Password=(?.*?);Port=(?.*?);"); + if (reg.Success) + db_name = reg.Groups["db_name"].ToString(); + + var row = session.FindRow("SELECT * FROM information_schema.statistics WHERE table_schema = @db_name and table_name = @tableName AND index_name = @indexName", new { db_name = db_name, tableName = tableName, indexName = tableName+ "__" + indexName }); + if (row != null) return true; + } + else if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + var row = session.FindRow("SELECT * FROM sqlite_master WHERE type = 'index' and tbl_name = @tableName and name = @indexName", new { tableName = tableName, indexName = indexName }); + if (row != null) return true; + } + return false; + } + + /// + /// 添加索引 + /// + public static bool AddIndex(this SqlSugarClient session, params object[] values) + { + try + { + string tableName = typeof(T).Name; + string sql = string.Empty; + var indexName = tableName + "__" + string.Join("_", values); + if (indexName.Length > 64) + indexName = indexName.Substring(0, 64); + + + + + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + sql = $" CREATE INDEX {indexName} ON {tableName} ({string.Join(",", values)});"; + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + sql = $"ALTER TABLE {tableName} ADD INDEX {indexName}({string.Join(",", values)});"; + else throw new Exception("暂时不支持" + session.CurrentConnectionConfig.DbType + "数据库!"); + + session.ExcuteSQL(sql); + return true; + } + catch (Exception ex) + { + Console.WriteLine("创建索引失败:" + ex.Message); + } + return false; + } + + public static bool DeleteIndex(this SqlSugarClient session, string tableName, string indexName) + { + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + session.ExcuteSQL($"DROP INDEX {indexName} ON {tableName}"); + } + else if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + session.ExcuteSQL($"DROP INDEX {indexName}"); + } + return !session.IndexExist(tableName, indexName); + } + + + /// + /// 判断表是否存在 + /// + /// + /// + public static bool TableExist(this SqlSugarClient session) + { + return TableExist(session, typeof(T).Name); + } + /// + /// 判断表是否存在 + /// + public static bool TableExist(this SqlSugarClient session, string tableName) + { + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + var result = session.Ado.GetDataTable("SELECT * FROM sqlite_master where type='table' and name=@tableName;", new { tableName = tableName }); + if (result.Rows.Count == 0) return false; + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + + //var result = session.Ado.GetDataTable("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=@dbName and TABLE_NAME=@tableName ;", new { tableName = Regex.Match(session.CurrentConnectionConfig.ConnectionString, "Initial Catalog=(.*?);").Groups[1].Value }); + var result = session.Ado.GetDataTable("select * from information_schema.TABLES where TABLE_SCHEMA=(select database()) and `table_name` =@tableName", new { tableName = tableName }); + + if (result.Rows.Count == 0) return false; + else + { + //SELECT table_name FROM information_schema.TABLES WHERE table_name ='fl_plugin_pddrebate_pddtgw'; + result = session.Ado.GetDataTable("SELECT table_name FROM information_schema.TABLES WHERE table_name = @tableName", new { tableName = tableName }); + if (result.Rows.Count == 0) return false; + } + } + else return false; + + return true; + } + + /// + /// 添加唯一约束 + /// + public static void AddUnique(this SqlSugarClient session, params object[] values) + { + AddUnique(session, typeof(T).Name, values); + } + + /// + /// 执行sql + /// + /// + /// + /// + public static void ExcuteSQL(this SqlSugarClient session, string sql, object parameters = null) + { + session.Ado.ExecuteCommand(sql, parameters); + } + + public static bool ExistUnique(this SqlSugarClient session, string tableName, params object[] values) + { + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + return false; + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + //SELECT count(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE where table_name = 'fl_statistics_record' and column_name = 'uid' + + //var result = session.Ado.GetDataTable("SELECT count(*) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE where table_name = @tableName and column_name = @column_name", new { tableName = tableName, column_name = columnName }); + + StringBuilder strb = new StringBuilder($"SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE where table_name = @tableName and CONSTRAINT_NAME = '{values[0]}'"); + //List ors = new List(); + //for (int i = 0; i < values.Length; i++) + //{ + // ors.Add($"column_name = '{values[i]}'"); + //} + //strb.Append($"({string.Join(" or ", ors)});"); + + var result = session.Ado.GetDataTable(strb.ToString(), new { tableName = tableName }); + var rows = result.Rows; + if (rows.Count == 0) + return false; + List strs = new List(); + + foreach (System.Data.DataRow row in rows) + { + var item = row["column_name"]; + strs.Add(item.ToString()); + } + + string[] strs2 = new string[values.Length]; + values.CopyTo(strs2, 0); + + var notchongfu = strs.Except(strs2.ToList()).ToList(); + + return notchongfu.Count == 0; + } + return true; + } + + public static bool DeleteUnique(this SqlSugarClient session, string tableName, params object[] values) + { + try + { + if (values == null) throw new Exception("Unique 不能为空。"); + StringBuilder sb = new StringBuilder(); + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + sb.Append(" drop index "); + sb.Append(tableName); + foreach (var item in values) + { + sb.Append("_"); + sb.Append(item); + sb.Append("_"); + } + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + try + { + sb.Append("ALTER TABLE "); + sb.Append(tableName); + sb.Append(" drop index "); + for (int i = 0; i < values.Length; i++) + { + sb.Append(values[i]); + if ((i + 1) != values.Length) + { + sb.Append(","); + } + } + sb.Append(";"); + session.Ado.ExecuteCommand(sb.ToString()); + return true; + } + catch (Exception) + { + sb.Length = 0; + sb.Append("ALTER TABLE "); + sb.Append(tableName); + sb.Append(" drop index "); + if (values.Length != 0) + { + sb.Append(values[0]); + } + sb.Append(";"); + session.Ado.ExecuteCommand(sb.ToString()); + return true; + } + } + else throw new Exception("暂时不支持" + session.CurrentConnectionConfig.DbType + "数据库!"); + + session.Ado.ExecuteCommand(sb.ToString()); + return true; + } + catch (Exception ex) + { } + return false; + } + + /// + /// 添加唯一约束 + /// + public static void AddUnique(this SqlSugarClient session, string tableName, params object[] values) + { + if (values == null) throw new Exception("Unique 不能为空。"); + StringBuilder sb = new StringBuilder(); + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + sb.Append(" CREATE UNIQUE INDEX "); + sb.Append(tableName); + foreach (var item in values) + { + sb.Append("_"); + sb.Append(item); + sb.Append("_"); + } + sb.Append(" ON "); + sb.Append(tableName); + sb.Append("("); + for (int i = 0; i < values.Length; i++) + { + sb.Append(values[i]); + if ((i + 1) != values.Length) + { + sb.Append(","); + } + } + sb.Append(");"); + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + if (session.ExistUnique(tableName, values)) + return; + sb.Append("ALTER TABLE "); + sb.Append(tableName); + sb.Append(" ADD UNIQUE KEY("); + for (int i = 0; i < values.Length; i++) + { + sb.Append(values[i]); + if ((i + 1) != values.Length) + { + sb.Append(","); + } + } + sb.Append(");"); + } + else throw new Exception("暂时不支持" + session.CurrentConnectionConfig.DbType + "数据库!"); + + session.Ado.ExecuteCommand(sb.ToString()); + } + + /// + /// 检测列是否存在 + /// + /// + /// + /// + /// + public static bool ColumnExist(this SqlSugarClient session, string tableName, string columnName) + { + //IF NOT EXISTS (SELECT * FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'vrv_paw_rule' AND column_name = 'thresholdMin') THEN + //ALTER TABLE vrv_paw_rule ADD COLUMN thresholdMin BIGINT; + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + var row = session.FindRow("select * from sqlite_master where name = @tableName and sql like @colunName;", new { tableName = tableName, colunName = "%" + columnName + "%" }); + { + if (row != null) + { + string sql = row["sql"].ToString().ToLower(); + + //var reg = Regex.Match(sql, @",?'?\s{0,}\[?""?" + columnName.ToLower() + @"""?\]?'?\s{1,}", RegexOptions.IgnoreCase); + var reg = Regex.Match(sql, @",?'?\s{0,}\[?""?" + columnName.ToLower() + @"""?\]?'?\s{1,}", RegexOptions.IgnoreCase); + if (reg.Success) return true; + else return false; + + //return true; + } + } + } + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + var row = session.FindRow("select * from information_schema.columns where table_schema = DATABASE() and table_name = @tableName and column_name like @colunName;", new { tableName = tableName, colunName = "%" + columnName + "%" }); + if (row != null) return true; + } + return false; + } + + /// + /// 增加列 + /// + /// + /// + /// + /// + public static void AddColumn(this SqlSugarClient session, string tableName, string columnName, string sqlType) + { + try + { + if (session.CurrentConnectionConfig.DbType == DbType.Sqlite) session.ExcuteSQL("alter table " + tableName + " add " + columnName + " " + sqlType); + else if (session.CurrentConnectionConfig.DbType == DbType.MySql) session.ExcuteSQL("alter table " + tableName + " add column " + columnName + " " + sqlType); + } + catch (Exception ex) + { + EventClient.OnEvent("", $"增加字段异常:{ex.Message} - {tableName} - {columnName} - {sqlType}"); + } + } + + /// + /// 修改字段类型 + /// + /// + /// + /// + /// + public static void UpdateColumnType(this SqlSugarClient session, string tableName, string cloumnName, string newType) + { + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + session.ExcuteSQL("alter table " + tableName + " modify column " + cloumnName + " " + newType + ";"); + } + + /// + /// 获得第一条数据 + /// + /// + /// + /// + /// + public static System.Data.DataRow FindRow(this SqlSugarClient session, string strSQL, Object obj) + { + if (session.CurrentConnectionConfig.DbType == SqlSugar.DbType.MySql) + { + strSQL = strSQL.Replace("[随机排序]", " order by rand() "); + } + else + { + strSQL = strSQL.Replace("[随机排序]", " order by RANDOM() "); + } + //获取公共属性 + + var table = session.Ado.GetDataTable(strSQL, obj); + if (table.Rows.Count > 0) return table.Rows[0]; + + return null; + } + + + /// + /// 获得Table + /// + /// + /// SQL + /// + /// + public static System.Data.DataTable FindTable(this SqlSugarClient session, string strSQL, object param = null) + { + return session.Ado.GetDataTable(strSQL, param); + } + + /// + /// 根据ID查数据、必须有为ID的字段 + /// + /// + /// + /// + /// + public static T FindById(this SqlSugarClient session, long id) where T : new() + { + return session.Queryable().InSingle(2); + } + + public static int Insertable(this SqlSugarClient session, base_model obj) + { + var t = obj.GetType(); + + return session.Insertable(obj).ExecuteReturnIdentity(); + } + + public static List Find(this SqlSugarClient session, string strSQL, Object param = null) where T : new() + { + var tablename = typeof(T).Name; + if (!strSQL.StartsWith("select")) + { + StringBuilder sb = new StringBuilder(); + sb.Append("select * from "); + sb.Append(tablename); + sb.Append(" where "); + sb.Append(strSQL); + + strSQL = sb.ToString(); + } + + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + strSQL = strSQL.Replace("[随机排序]", " order by rand() "); + } + else + { + strSQL = strSQL.Replace("[随机排序]", " order by RANDOM() "); + } + + return session.Ado.SqlQuery(strSQL, param); + } + + public static T FindSingle(this SqlSugarClient session, string strSQL, Object param = null) where T : new() + { + for (int i = 0; i < 5; i++) + { + var tablename = typeof(T).Name; + if (!strSQL.StartsWith("select", StringComparison.OrdinalIgnoreCase)) + { + StringBuilder sb = new StringBuilder(); + sb.Append("select * from "); + sb.Append(tablename); + sb.Append(" where "); + sb.Append(strSQL); + + strSQL = sb.ToString(); + } + + if (session.CurrentConnectionConfig.DbType == DbType.MySql) + { + strSQL = strSQL.Replace("[随机排序]", " order by rand() "); + } + else + { + strSQL = strSQL.Replace("[随机排序]", " order by RANDOM() "); + } + + return session.Ado.SqlQuerySingle(strSQL, param); + } + return default(T); + } + + /// + /// 删除表 + /// + /// + /// + public static void DropTable(this SqlSugarClient session, string tableName) + { + session.ExcuteSQL("DROP TABLE " + tableName); + } + + /// + /// 删除表 + /// + /// + /// + public static void DropTable(this SqlSugarClient session) + { + string table_name = typeof(T).Name; + session.DropTable(table_name); + } + + /// + /// 开启事务 + /// + /// + public static void BeginTransaction(this SqlSugarClient session) + { + session.Ado.BeginTran(); + } + + /// + /// 回滚 + /// + /// + public static void Rollback(this SqlSugarClient session) + { + session.Ado.RollbackTran(); + } + + /// + /// 提交 + /// + /// + public static void Commit(this SqlSugarClient session) + { + session.Ado.CommitTran(); + } + } + +} diff --git a/类库/Api.Framework/Tools/SynchronizedDictionary.cs b/类库/Api.Framework/Tools/SynchronizedDictionary.cs new file mode 100644 index 0000000..2a57b82 --- /dev/null +++ b/类库/Api.Framework/Tools/SynchronizedDictionary.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 线程安全的数据字典 + /// + /// + /// + public class SynchronizedDictionary + { + private Dictionary dic = new Dictionary(); + private object obj = new object(); + +        /// +        /// 向字典中增加键值对 +        /// +        /// +        /// +        public void Add(TKey key, TValue value) + { + lock (obj) + { + if (ContainsKey(key)) + { + Remove(key); + } + dic.Add(key, value); + } + } + + +        /// +        /// 向字典中添加列表 +        /// +        /// +        /// +        public void AddRange(ICollection valueList, Func func) + { + lock (obj) + { + if (func != null) + { + TKey key = default(TKey); + + + foreach (var item in valueList) + { + key = func(item); + + if (ContainsKey(key)) + { + dic.Remove(key); + } + + + dic.Add(key, item); + + + key = default(TKey); + } + } + } + } + + +        /// +        /// 清空数据字典 +        /// +        public void Clear() + { + lock (obj) + { + dic.Clear(); + } + } + + +        /// +        /// 从字典中移除特定的键值对 +        /// +        /// +        /// +        public bool Remove(TKey key) + { + lock (obj) + { + return dic.Remove(key); + } + } + + +        /// +        /// 字典是否包含特定的键 +        /// +        /// +        /// +        public bool ContainsKey(TKey key) + { + lock (obj) + { + return dic.ContainsKey(key); + } + } + + /// +         /// 字典是否包含特定的值 +         /// +         /// +         /// + public bool ContainsValue(TValue value) + { + lock (obj) + { + return dic.ContainsValue(value); + } + } + + /// +         /// 字典中键值对的数目 +         /// + public int Count + { + get + { + lock (obj) + { + return dic.Count; + } + } + } + + +        /// +        /// 字典的键集合 +        /// +        public Dictionary.KeyCollection Keys + { + get + { + lock (obj) + { + return dic.Keys; + } + } + } + + +        /// +        /// 字典值集合 +        /// +        public Dictionary.ValueCollection Values + { + get + { + lock (obj) + { + return dic.Values; + } + } + } + + +        /// +        /// 字典键数组 +        /// +        public TKey[] KeysToArray + { + get + { + lock (obj) + { + TKey[] keys = new TKey[dic.Keys.Count]; + dic.Keys.CopyTo(keys, 0); + return keys; + } + } + } + + +        /// +        /// 字典值数组 +        /// +        public TValue[] ValuesToArray + { + get + { + lock (obj) + { + TValue[] values = new TValue[dic.Keys.Count]; + dic.Values.CopyTo(values, 0); + return values; + } + } + } + + /// +         /// 返回字典循环访问的枚举 +         /// +         /// + public Dictionary.Enumerator GetEnumerator() + { + lock (obj) + { + return dic.GetEnumerator(); + } + } + + /// +         ///  +         /// + public IEqualityComparer Comparer + { + get + { + lock (obj) + { + return dic.Comparer; + } + } + } + + +        /// +        /// 通过key获取特定的值 +        /// +        /// +        /// +        public TValue this[TKey key] + { + + + get + { + lock (obj) + { + return dic[key]; + } + } + set + { + lock (obj) + { + dic[key] = value; + } + } + } + + +        ///// +        ///// 获取字典特定位置的值 +        ///// +        ///// +        ///// +        public TValue Value(int index) + { + + + lock (obj) + { + return ValuesToArray[index]; + } + } + + +        /// +        /// 获取字典特定位置的键 +        /// +        /// +        /// +        public TKey Key(int index) + { + + + lock (obj) + { + return KeysToArray[index]; + } + } + } +} diff --git a/类库/Api.Framework/Tools/TBHelper.cs b/类库/Api.Framework/Tools/TBHelper.cs new file mode 100644 index 0000000..6bbe2a6 --- /dev/null +++ b/类库/Api.Framework/Tools/TBHelper.cs @@ -0,0 +1,2355 @@ +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.Utils; +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Text; +using System.Web; +using NPOI.POIFS.Storage; + +namespace Api.Framework.Tools +{ + /// + /// 淘宝导购帮助类 + /// + public static class TBHelper + { + #region 优惠券信息和商品字典缓存 + private static string cache_tbitemid_key = "cache_tbitemid_key"; + /// + /// 在存有优惠券的字典中查询商品编码 + /// + /// + /// + public static string FindTBCouponByItemIdCache(string url) + { + try + { + if (string.IsNullOrWhiteSpace(url)) return string.Empty; + var reg = Regex.Match(url, @"i\d+?/(?<图片字符串>(?:\d+?)[^\.]+?)\."); + if (!reg.Success) return string.Empty; + var imgStr = reg.Groups["图片字符串"].Value; + var item_id = string.Empty; + var value = ApiClient.Cache.Get>(cache_tbitemid_key); + if (value == null) + return string.Empty; + var md5 = Util.GetMd5_32byte(imgStr); + if (value.ContainsKey(md5)) + return item_id = value[md5]; + } + catch (Exception ex) + { } + return string.Empty; + } + /// + /// 将优惠券链接和商品编码保存在字典中 + /// + /// + /// + public static void SetTBCouponByItemIdCache(string url, string item_id) + { + try + { + if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(item_id)) return; + + var value = ApiClient.Cache.Get>(cache_tbitemid_key); + if (value == null) + value = new Dictionary(); + else if (value.Count > 1000) + value.Clear(); + + var reg = Regex.Match(url, @"i\d+?/(?<图片字符串>(?:\d+?)[^\.]+?)\."); + if (!reg.Success) return; + var imgStr = reg.Groups["图片字符串"].Value; + var md5 = Util.GetMd5_32byte(imgStr); + if (!value.ContainsKey(md5)) + value.Add(md5, item_id); + ApiClient.Cache.Set(cache_tbitemid_key, value, 30); + } + catch (Exception ex) + { } + } + #endregion + + #region 获取外围优惠券信息 + #region xxx + ///// + ///// 通过商品id获取优惠券信息(爬大淘客优惠券信息) + ///// + ///// + ///// + //public static string FindGoodsActivityIdAll(string itemId, out string sellerId, out double payPrice) + //{ + // var activityId = FindGoodsActivityId_DaTaoKe(itemId, out sellerId, out payPrice); + // if (string.IsNullOrWhiteSpace(activityId)) + // activityId = FindGoodsActivityId_HaoDanKu(itemId, out sellerId, out payPrice); + // if (string.IsNullOrWhiteSpace(activityId)) + // activityId = FindGoodsActivityId_XuanDan(itemId, out sellerId, out payPrice); + // return activityId; + //} + + //public static string FindGoodsActivityId_DaTaoKe(string itemId, out string sellerId, out double payPrice) + //{ + // sellerId = string.Empty; + // payPrice = -1; + // var activityid = string.Empty; + // try + // { + // HttpItem item = new HttpItem() + // { + // URL = $"http://www.dataoke.com/search/?keywords={itemId}", + // Method = "GET", + // Timeout = 5000, + // ReadWriteTimeout = 10000, + // IsToLower = false, + // UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + // Accept = "text/html, application/xhtml+xml, */*", + // ContentType = "text/html" + // }; + // HttpHelper http = new HttpHelper(); + // var result = http.GetHtml(item); + // if (result == null) + // return activityid; + // //var regs = Regex.Matches(result.Html, @"\d+)\&parts=商品库"); + // var regs = Regex.Matches(result.Html, @"goods-items_(?\d+)"); + // if (regs.Count != 1) + // return activityid; + // var gid = regs[0].Groups["gid"].Value?.Trim(); + // if (string.IsNullOrWhiteSpace(gid)) return activityid; + // item.URL = $"http://www.dataoke.com/gettpl?gid={gid}&_={HttpExtend.GetTimeStamp()}000"; + // result = http.GetHtml(item); + // if (result == null) + // return activityid; + // var html = result.Html; + // if (html.Contains($"item.htm?id={itemId}")) + // { + // var reg = Regex.Match(html, @"activityId=(?<活动ID>[A-Za-z0-9]+)"); + // if (reg.Success) + // { + // var activity = reg.Groups["活动ID"].Value?.Trim(); + // reg = Regex.Match(html, @"sellerId=(?<店铺ID>[^&]*)"); + // if (reg.Success) + // sellerId = reg.Groups["店铺ID"].Value; + + // List regStrs = new List() { @"后【(?<券后>\d+(?:[.]{1}\d+?)?)元】", @"仅(?<券后>\d+(?:[.]{1}\d+?)?)元秒杀" }; + // foreach (var regStr in regStrs) + // { + // reg = Regex.Match(html, regStr); + // if (reg.Success) + // { + // payPrice = double.Parse(reg.Groups["券后"].Value); + // break; + // } + // } + + + // //var quan = -1d; + // //reg = Regex.Match(html, @"(?<券>\d+[[.]{1}\d+?]?)元优惠券"); + // //if (reg.Success) + // // quan = double.Parse(reg.Groups["券"].Value); + // //if (price != -1 && quan != -1) + // // payPrice = quan + price; + // return activity; + // } + // } + // else + // { + // Console.WriteLine("html = " + html); + // } + // } + // catch (Exception) + // { } + // return activityid; + //} + + //public static string FindGoodsActivityId_HaoDanKu(string itemId, out string sellerId, out double payPrice) + //{ + // payPrice = -1; + // sellerId = string.Empty; + // var activityid = string.Empty; + // try + // { + // HttpItem item = new HttpItem() + // { + // URL = $"https://www.haodanku.com/indexapi/get_allitem_list?keyword={itemId}", + // Method = "GET", + // Timeout = 5000, + // ReadWriteTimeout = 10000, + // IsToLower = false, + // UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + // Accept = "text/html, application/xhtml+xml, */*", + // ContentType = "application/json" + // }; + // HttpHelper http = new HttpHelper(); + // var result = http.GetHtml(item); + // if (result == null) + // return activityid; + // var dic = HttpExtend.JsonToDictionary(result.Html); + // if (dic == null) return activityid; + // if (dic.ContainsKey("item_info")) + // { + // var item_info = dic["item_info"] as ArrayList; + // if (item_info != null && item_info.Count != 0) + // { + // var data = item_info[0] as Dictionary; + // if (data.ContainsKey("activityid")) + // { + // activityid = data["activityid"].ToString(); + // if (data.ContainsKey("userid")) + // sellerId = data["userid"].ToString(); + // var price = -1d; + // if (data.ContainsKey("itemendprice")) + // payPrice = double.Parse(data["itemendprice"].ToString()); + // //var quan = -1d; + // //if (data.ContainsKey("couponmoney")) + // // quan = double.Parse(data["couponmoney"].ToString()); + // //if (quan != -1 && price != -1) + // // oldPrice = price + quan; + // return activityid; + // } + // } + // } + // } + // catch (Exception) + // { } + // return activityid; + //} + + //public static string FindGoodsActivityId_XuanDan(string itemId, out string sellerId, out double payPrice) + //{ + // payPrice = -1; + // sellerId = string.Empty; + // var activityid = string.Empty; + // try + // { + // HttpItem item = new HttpItem() + // { + // URL = $"http://www.xuandan.com/index.html?key={itemId}", + // Method = "GET", + // Timeout = 5000, + // ReadWriteTimeout = 10000, + // IsToLower = false, + // UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + // Accept = "text/html, application/xhtml+xml, */*", + // ContentType = "application/json" + // }; + // HttpHelper http = new HttpHelper(); + // var result = http.GetHtml(item); + // if (result == null) + // return activityid; + // var html = result.Html; + // if (string.IsNullOrWhiteSpace(html)) return activityid; + // var reg = Regex.Match(html, "领券:([^<]+)"); + // if (reg.Success) + // { + // var url = reg.Groups[1].Value.Trim(); + // reg = Regex.Match(url, @"activityId=(?<活动ID>[A-Za-z0-9]+)"); + // if (reg.Success) + // { + // var activity = reg.Groups["活动ID"].Value?.Trim(); + // reg = Regex.Match(html, @"sellerId=(?<店铺ID>[^&]*)"); + // if (reg.Success) + // sellerId = reg.Groups["店铺ID"].Value; + // reg = Regex.Match(html, @"【券后(?<券后>\d+[[.]{1}\d+?]?)元】"); + // if (reg.Success) + // payPrice = double.Parse(reg.Groups["券后"].Value); + // return activity; + // } + // } + // } + // catch (Exception) + // { } + // return activityid; + //} + #endregion + + #region + /// + /// 通过商品id获取优惠券信息(爬大淘客优惠券信息) + /// + /// + /// + public static TbExCoupon FindGoodsCouponInfo(string itemId) + { + TbExCoupon result = FindGoodsActivityId_DaTaoKe(itemId); + if (result == null) + result = FindGoodsActivityId_HaoDanKu(itemId); + //if (result == null) + // result = FindGoodsActivityId_XuanDan(itemId); + return result; + } + + /// + /// 通过商品id获取大淘客的信息 + /// + /// 商品id + /// + public static TbExCoupon FindGoodsActivityId_DaTaoKe(string itemId) + { + TbExCoupon exCoupon = null; + try + { + HttpItem item = new HttpItem() + { + //http://dtkapi.ffquan.cn/go_getway/proxy/search?platform=1&page=1&sortType=4&kw=525918728400 + URL = $"http://dtkapi.ffquan.cn/go_getway/proxy/search?platform=1&page=1&sortType=4&kw={itemId}", + Method = "GET", + Timeout = 5000, + ReadWriteTimeout = 10000, + IsToLower = false, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "text/html" + }; + HttpHelper http = new HttpHelper(); + var result = http.GetHtml(item); + if (result == null) + return exCoupon; + + var tmp = JObject.Parse(result.Html); + var list = (JArray)tmp["data"]["search"]["list"]; + if (list != null && list.Count == 1) + { + var data = list[0]; + var gid = data["id"].ToString(); + var coupon_amount = data["coupon_amount"].ToString();//券金额 + var price = data["price"].ToString();//券后价 + var original_price = data["original_price"].ToString();//原价 + + if (string.IsNullOrWhiteSpace(gid)) + return exCoupon; + item.URL = $"http://www.dataoke.com/gettpl?gid={gid}&_={HttpExtend.GetTimeStamp()}000"; + result = http.GetHtml(item); + if (result == null) + return exCoupon; + var html = result.Html; + if (html.Contains($"item.htm?id={itemId}")) + { + var reg = Regex.Match(html, @"activityId=(?<活动ID>[A-Za-z0-9]+)"); + if (reg.Success) + { + exCoupon = new TbExCoupon(); + exCoupon.activityId = reg.Groups["活动ID"].Value?.Trim(); + reg = Regex.Match(html, @"sellerId=(?<店铺ID>[^&]*)"); + if (reg.Success) + exCoupon.sellerId = reg.Groups["店铺ID"].Value; + + exCoupon.endPrice = double.Parse(price); + exCoupon.salePrice = double.Parse(original_price); + exCoupon.couponAmount = double.Parse(coupon_amount); + return exCoupon; + } + } + //else + //{ + // Console.WriteLine("html = " + html); + //} + } + } + catch (Exception) + { } + return exCoupon; + } + + /// + /// 通过商品id获取好单库的信息 + /// + /// 商品id + /// + public static TbExCoupon FindGoodsActivityId_HaoDanKu(string itemId) + { + TbExCoupon exCoupon = null; + try + { + HttpItem item = new HttpItem() + { + URL = $"https://www.haodanku.com/indexapi/get_allitem_list?keyword={itemId}", + Method = "GET", + Timeout = 5000, + ReadWriteTimeout = 10000, + IsToLower = false, + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json" + }; + HttpHelper http = new HttpHelper(); + var result = http.GetHtml(item); + if (result == null) + return exCoupon; + var dic = HttpExtend.JsonToDictionary(result.Html); + if (dic == null) + return exCoupon; + if (dic.ContainsKey("item_info")) + { + var tmp = JObject.Parse(result.Html); + var list = (JArray)(tmp["item_info"]); + + if (list != null && list.Count == 1) + { + exCoupon = new TbExCoupon(); + var data = list[0]; + exCoupon.activityId = data["activityid"].ToString();//优惠券id + exCoupon.sellerId = data["userid"].ToString();//店铺id + exCoupon.endPrice = double.Parse(data["itemendprice"].ToString());//券后价 + exCoupon.couponAmount = double.Parse(data["couponmoney"].ToString());//券金额 + exCoupon.salePrice = double.Parse(data["itemprice"].ToString());//原价 + + return exCoupon; + } + } + } + catch (Exception) + { } + return exCoupon; + } + + ///// + ///// 通过商品id获取选单的信息 + ///// + ///// 商品id + ///// + //public static TbExCoupon FindGoodsActivityId_XuanDan(string itemId) + //{ + // TbExCoupon exCoupon = null; + // try + // { + // HttpItem item = new HttpItem() + // { + // URL = $"http://www.xuandan.com/index.html?key={itemId}", + // Method = "GET", + // Timeout = 5000, + // ReadWriteTimeout = 10000, + // IsToLower = false, + // UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0", + // Accept = "text/html, application/xhtml+xml, */*", + // ContentType = "application/json" + // }; + // HttpHelper http = new HttpHelper(); + // var result = http.GetHtml(item); + // if (result == null) + // return exCoupon; + // var html = result.Html; + // if (string.IsNullOrWhiteSpace(html)) + // return exCoupon; + // var reg = Regex.Match(html, "领券:([^<]+)"); + // if (reg.Success) + // { + // var url = reg.Groups[1].Value.Trim(); + // reg = Regex.Match(url, @"activityId=(?<活动ID>[A-Za-z0-9]+)"); + // if (reg.Success) + // { + // exCoupon = new TbExCoupon(); + // var activity = reg.Groups["活动ID"].Value?.Trim(); + // reg = Regex.Match(html, @"sellerId=(?<店铺ID>[^&]*)"); + // if (reg.Success) + // sellerId = reg.Groups["店铺ID"].Value; + // reg = Regex.Match(html, @"【券后(?<券后>\d+[[.]{1}\d+?]?)元】"); + // if (reg.Success) + // payPrice = double.Parse(reg.Groups["券后"].Value); + // return exCoupon; + // } + // } + // } + // catch (Exception) + // { } + // return exCoupon; + //} + #endregion + + /// + /// 外围淘宝商品信息(优惠券等信息) + /// + public class TbExCoupon + { + /// + /// 优惠券信息 + /// + public string activityId { get; set; } + /// + /// 店铺Id + /// + public string sellerId { get; set; } + /// + /// 折后价(活动价) + /// + public double salePrice { get; set; } + /// + /// 优惠券金额 + /// + public double couponAmount { get; set; } + /// + /// 折后价格减去优惠券金额 + /// + public double endPrice { get; set; } + + } + + #endregion + + /// + /// 保存淘宝基础信息的类 + /// + public class TbBaseInfo + { + /// + /// 宝贝ID + /// + public string ItemId { get; set; } + /// + /// 月销量 + /// + public string SellCount { get; set; } + /// + /// 价格 + /// + public string Price { get; set; } + /// + /// 店铺名称 + /// + public string ShopName { get; set; } + /// + /// 店铺头像 + /// + public string ShopIcon { get; set; } + /// + /// + /// + public string UserId { get; set; } + /// + /// 商品主图 + /// + public string ItemImage { get; set; } + /// + /// 商品标题 + /// + public string ItemTitle { get; set; } + /// + /// 店铺Id + /// + public string SellerId { get; set; } + + } + + /// + /// 淘宝解析方法 + /// + public class TbAnalysis + { + /// + /// 查找宝贝Id的正则表达式 + /// + private string[] Reg_Item_Ids = { @"item[Ii]d=(?\d{5,})", @"item_id=(?\d{5,})", @"\?id=(?\d{5,})", @"&id=(?\d{5,})", @"/i(?\d{5,})", @"num[Ii]id=(?\d{5,})", @"\?id=(?[a-zA-Z0-9]{5,}-[a-zA-Z0-9]{5,})" }; + + private string key = "tbanalysis_key"; + + /// + /// 通过宝贝id,查询宝贝所有的信息 + /// + /// 宝贝ID + /// 返回TbInfo对象,异常返回Null + public TbBaseInfo FindTbInfoByItemId(string itemId) + { + var html = ""; + try + { + //var item = TbTools.GetH5Result("mtop.taobao.detail.getdetail", new { itemNumId = itemId, exParams = new { id = itemId }, detail_v = "3.1.1", ttid = "2018@taobao_iphone_9.9.9", utdid = "123123123123123" }, out html); + + //var time = ApiClient.Cache.Get(key); + //if (time == null) + // ApiClient.Cache.Set(key, DateTime.Now, 10); + //else + // return null; + + var item = TbTools.GetH5Result("mtop.taobao.detail.getdetail", new { itemNumId = itemId, exParams = new { id = itemId }, ttid = "2016@taobao_h5_2.0.0", isSec = "0", ecode = "0", AntiFlood = "true", AntiCreep = "true", H5Request = "true", type = "jsonp", dataType = "jsonp" }, out html); + + if (item == null) return null; + if (item.ContainsKey("item")) + { + var _item = item["item"] as Dictionary; + var sellerId = string.Empty; + //这里可以通过图片的地址获取店铺的id + if (_item.ContainsKey("images")) + { + var images = _item["images"] as ArrayList; + if (images != null && images.Count != 0) + { + var reg = Regex.Match(images[0].ToString(), @"http://img.alicdn.com/imgextra/i\d/(?<店铺Id>\d+)/"); + if (reg.Success) + sellerId = reg.Groups["店铺Id"].Value; + } + } + + var price = string.Empty;//价格 + var sellCount = string.Empty; + if (item.ContainsKey("apiStack")) + { + var apiStack = item["apiStack"] as ArrayList; + if (apiStack != null && apiStack.Count != 0) + { + var _apiStack = apiStack[0] as Dictionary; + if (_apiStack.ContainsKey("value")) + { + var valueJsonStr = _apiStack["value"].ToString(); + var valueJson = HttpExtend.JsonToDictionary(valueJsonStr); + + #region 获取销量 sellCount + var itemTag = valueJson["item"] as Dictionary; + //if (itemTag.ContainsKey("sellCount")) + // sellCount = itemTag["sellCount"].ToString(); + if (itemTag.ContainsKey("sellCount")) + { + sellCount = itemTag["sellCount"].ToString(); + if (sellCount.Contains("万+")) + { + sellCount = ((int)(decimal.Parse(sellCount.Replace("万+", "")) * 10000m)).ToString(); + } + } + else + sellCount = "0"; + #endregion + + #region 获取价格 price + var priceTag = valueJson["price"] as Dictionary; + if (priceTag.ContainsKey("price")) + { + var priceSub = priceTag["price"] as Dictionary; + if (priceSub.ContainsKey("priceText")) + price = priceSub["priceText"].ToString(); + } + if (string.IsNullOrEmpty(price) && priceTag.ContainsKey("transmitPrice")) + { + var transmitPrice = priceTag["transmitPrice"] as Dictionary; + if (transmitPrice.ContainsKey("priceText")) + price = transmitPrice["priceText"].ToString(); + } + if (!string.IsNullOrEmpty(price) && price.Contains("-")) //??这里可能还存在带问号的价格,目前不清楚是什么情况,先空着 + price = price.Split('-')[0]; + if (string.IsNullOrEmpty(price)) + price = "0"; + #endregion + } + } + + if (item.ContainsKey("seller")) + { + var _seller = item["seller"] as Dictionary; + //店铺名称 + if (_seller.ContainsKey("shopName")) + { + var shopName = _seller["shopName"].ToString(); + //店铺图片 + if (_seller.ContainsKey("shopIcon")) + { + string shopIcon = _seller["shopIcon"].ToString(); + shopIcon = string.IsNullOrEmpty(shopIcon) ? "https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg" : shopIcon.StartsWith("http") ? _seller["shopIcon"].ToString() : "http:" + _seller["shopIcon"].ToString(); + if (string.IsNullOrEmpty(shopIcon) || shopName == "天猫超市") + shopIcon = "https://ss2.bdstatic.com/8_V1bjqh_Q23odCf/pacific/1659832877.jpg"; + + var userId = string.Empty; + if (_seller.ContainsKey("userId")) + userId = _seller["userId"].ToString(); + //主图图片 + var item_image = string.Empty; + if (_item.ContainsKey("images")) + item_image = (_item["images"] as ArrayList)[0].ToString(); + //商品标题 + var item_title = string.Empty; + if (_item.ContainsKey("title")) + item_title = _item["title"].ToString(); + return new TbBaseInfo() { ItemId = itemId, ItemImage = item_image, ItemTitle = item_title, Price = price, SellCount = sellCount, ShopIcon = shopIcon, ShopName = shopName, UserId = userId, SellerId = sellerId }; + } + } + } + } + } + return null; + } + catch (Exception ex) + { + //EventClient.OnEvent("+++++", ex.Message + " - " + ex.StackTrace + " @@@@@@@ " + html); + } + return null; + } + + /// + /// 从字符串中获取淘宝宝贝id + /// + /// 要查找的字符串 + /// 返回查找到的宝贝id,未找到返回空,异常返回异常的信息 + public string FindTbItemIdByStr(string str) + { + try + { + //获取淘宝天猫的宝贝id值 + for (int i = 0; i < Reg_Item_Ids.Length; i++) + { + var reg = Regex.Match(str, Reg_Item_Ids[i].ToString()); + if (reg.Success) + return reg.Groups["id"].Value; + } + return string.Empty; + } + catch (Exception ex) + { + return string.Empty; + } + } + + /// + /// 活动ID + /// + public string activityId = string.Empty; + + #region 在线获取口令正则表达式 + /// + /// 清空正则表达式 + /// + public static void TklRegToEmpty() + { + tklReg = string.Empty; + } + + private static string tklReg = string.Empty; + private static DateTime UpdatetklReg = DateTime.MinValue; + public static string GetTklReg() + { + if (UpdatetklReg.AddMinutes(5) < DateTime.Now) + tklReg = string.Empty; + if (string.IsNullOrWhiteSpace(tklReg)) + { + var ali = CpsClient.Members.FirstOrDefault(f => f.cpstype == CpsType.阿里妈妈); + if (ali == null) + ali = new fl_cps_member() { cpstype = CpsType.阿里妈妈, username = "28592081" }; + if (ali != null) + { + var cps = CpsClient.CreateAlimamaRequest(ali); + if (cps != null) + { + for (int i = 0; i < 3; i++) + { + try + { + var data = cps.SendServer("find_wangzhi", "webTool.asmx", new { name = "淘口令中文正则" }).message.ToString(); + if (!string.IsNullOrWhiteSpace(data)) + { + tklReg = data; + break; + } + continue; + } + catch (Exception) + { + tklReg = string.Empty; + Thread.Sleep(500); + } + } + } + } + UpdatetklReg = DateTime.Now; + } + if (string.IsNullOrWhiteSpace(tklReg)) + { + //tklReg = @"(?.*(/|!||,[^\u4e00-\u9fa5])(?[\u4e00-\u9fa5]{11,16})(十|[^\u4e00-\u9fa5]).*)"; + tklReg = @"(?.*?(?:(?:\d+:/(?:/|!|,|[^\u4e00-\u9fa5])?)|(?:[^\u4e00-\u9fa5])?)(?[\u4e00-\u9fa5]{11,16})(http:[^\u4e00-\u9fa5]+)?.*)(?:微|乐|云|品|麦|凌|十|口|广|哇|它|厂|[^\u4e00-\u9fa5])?.*"; + } + return tklReg; + } + #endregion + + /// + /// 获取宝贝Id.解析所有的各种链接/淘口令/喵口令等,先解析商品类型的链接,在去解析其他类型的链接 + /// + /// 要解析内容 + /// AlimamaApi对象 + /// 返回宝贝Id,找不到返回空,异常返回异常的信息 + public string FindItemIdByUrlAndTklAndMkl(string mess, AlimamaApi api, string[] pids = null) + { + try + { + if (mess.Length <= 8) return string.Empty; + string item_id = string.Empty; + + if (string.IsNullOrWhiteSpace(mess) || + Regex.IsMatch(mess, @"\[图片=(.+?)\]") || + Regex.IsMatch(mess, @"\[视频=(.+?)\]") || + Regex.IsMatch(mess, @"\[卡片=(.+?)\]") || + Regex.IsMatch(mess, @"\[公告=(.+?)\]") || + Regex.IsMatch(mess, @"\[语音=(.+?)\]") || + mess.Contains("抖音口令") || + mess.Contains("抖音搜索") || + mess.Contains("8##") || + mess.Contains("#小程序://京东") + ) + return item_id; + + var promotion_id = string.Empty; + var title = string.Empty; + if (!string.IsNullOrWhiteSpace(DYHelper.GetDyGoodsID(mess, out promotion_id, out title))) + return string.Empty; + + item_id = FindTbItemIdByStr(mess); + if (!string.IsNullOrEmpty(item_id)) return item_id; + + #region 2019年6月10日09:40:31 支持用户发送的语句中存在多个连接 + var regs = HttpExtend.RegexMatchesUrl(mess); + if (regs != null && regs.Count != 0) + { + foreach (var item in regs) + { + try + { + var url = item; + item_id = FindTbItemIdByStr(url);//正常的淘宝天猫链接 [ https://detail.tmall.com/item.htm?id=576795776133 && https://item.taobao.com/item.htm?id=573396652123 ] + if (!string.IsNullOrEmpty(item_id)) return item_id; + + if (mess.Contains("喵口令")) + { + try + { + var _app = api.SendServer("taobao.tbk.h5.top", + new { api = "mtop.tmall.share.initdialog", param = HttpHelper.ObjectToJson(new { data = HttpHelper.ObjectToJson(new { codes = new string[] { url }, wholeCode = HttpHelper.URLEncode(mess) }) }), v = "1.0" }); + if (_app != null && _app.ok) + { + var result = _app.message as Dictionary; + if (result != null && result.ContainsKey("dialog")) + { + result = result["dialog"] as Dictionary; + if (result.ContainsKey("rightBtnActionUrl")) + { + item_id = FindTbItemIdByStr(result["rightBtnActionUrl"].ToString()); + if (!string.IsNullOrEmpty(item_id)) return item_id; + } + } + } + + } + catch (Exception ex) + { } + } + //var regUrl = Regex.Match(url, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|jd.hk|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|t.cn|detail.yao.95095.com|laiwang.com|jd.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com)"); + //var regUrl = Regex.Match(url, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|t.cn|detail.yao.95095.com|laiwang.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com|m.tb.cn)"); + var regUrl = Regex.Match(url, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|detail.yao.95095.com|laiwang.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com|m.tb.cn)"); + if (regUrl.Success) + { + var html = string.Empty; + for (int i = 0; i < 3; i++) + { + var http = new HttpHelper(); + html = http.GetHtml(url).Html; + if (html.Contains("超时操作")) + Thread.Sleep(500); + else break; + } + var reg = Regex.Match(html, @"var url = '(?.*?)';"); + if (reg.Success) + { + var oriUrl = reg.Groups["url"].Value; + if (string.IsNullOrWhiteSpace(oriUrl)) + { + return "00000"; + } + item_id = CouponByItemId(oriUrl, api); + } + if (string.IsNullOrWhiteSpace(item_id)) + item_id = FindTbItemIdByStr(html); + if (!string.IsNullOrWhiteSpace(item_id)) return item_id; + + if (url.Contains("uland.taobao")) + { + item_id = CouponByItemId(url, api); + if (!string.IsNullOrEmpty(item_id)) return item_id; + } + + if (url.Contains("p.tb.cn"))//https://p.tb.cn/5syZScgn56Eycz3W1eRKPk + { + var locationA = TbTools.FindLocationByUrl(url); + if (!string.IsNullOrWhiteSpace(locationA)) + item_id = FindTbItemIdByStr(locationA); + if (!string.IsNullOrWhiteSpace(item_id)) + return item_id; + } + + if (url.Contains("s.click.taobao"))//https://s.click.taobao.com/aFIAbOw 这种链接 + { + var locationA = TbTools.FindLocationByUrl(url); + if (locationA != null) + { + if (!locationA.Contains("err.taobao.com")) + { + //item_id = CouponByItemId(mess, api); + item_id = CouponByItemId(url, api); + if (!string.IsNullOrEmpty(item_id)) return item_id; + var locationB = TbTools.FindLocationByUrl(locationA); + if (string.IsNullOrWhiteSpace(locationB)) { item_id = string.Empty; } + else + { + var goodsUrl = HttpHelper.URLDecode(locationB.Replace("https://s.click.taobao.com/t_js?tu=", "").Replace("http://s.click.taobao.com/t_js?tu=", "")); + var tb_url = TbTools.FindLocationByUrl(goodsUrl, locationB);//获取到的淘宝链接 + if (!string.IsNullOrEmpty(item_id)) return item_id; + } + } + } + else + { + var _html = GetHTML(url); + reg = Regex.Match(_html, "real_jump_address = '(?<真正的跳转地址>[^']+)"); + if (reg.Success) + { + var address = reg.Groups["真正的跳转地址"].Value; + //_html = GetHTML(HttpHelper.URLDecode(address).Replace("&", "&"), HttpHelper.URLDecode(url)); + for (int i = 0; i < 3; i++) + { + _html = GetHTML(address.Replace("&", "&"), url); + item_id = FindTbItemIdByStr(_html); + if (!string.IsNullOrWhiteSpace(item_id)) + return item_id; + else + { + //访问频繁,休息重试3次 + Thread.Sleep(500); + } + } + } + + } + } + } + mess = mess.Replace(url, "");//清除没用的连接,如果连接无法解析,name下面的淘口令解析将会减轻负担 + } + catch (Exception ex) + { } + } + } + #endregion + //EventClient.OnEvent("", "A0 = " + item_id); + //if (!reg.Success || string.IsNullOrEmpty(item_id))//非链接 淘口令 + if (string.IsNullOrEmpty(item_id))//非链接 淘口令 + { + if (Util.IsXML(mess)) + return string.Empty; + var _mess = Regex.Replace(mess, "Http:/[A-Za-z]", "", RegexOptions.IgnoreCase); + + //_mess = Util.RemoveEmoji(_mess); + var tklTmps = new List(); + + #region 正常口令 + var regs1 = Regex.Matches(_mess, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?"); + foreach (Match item in regs1) + { + if (item.Success) + { + var tkl = item.Groups[1].Value; + if (Regex.IsMatch(tkl, @"(\d{11})")) + continue; + tklTmps.Add(tkl); + } + } + #endregion + + var tklreg = GetTklReg(); + regs1 = Regex.Matches(_mess, tklreg, RegexOptions.IgnoreCase); + foreach (Match item in regs1) + { + if (item.Success) + { + var tkl = _mess;// item.Groups["tkl"].Value; + tklTmps.Add(tkl); + } + } + + //regs1 = Regex.Matches(_mess, @"[^A-Za-z0-9]?(?[A-Za-z0-9]{5}(?\[0x[A-Za-z0-9]{8}\]|[^A-Za-z0-9]{1,2})[A-Za-z0-9]{6})[^A-Za-z0-9]?"); + //foreach (Match item in regs1) + //{ + // if (item.Success) + // { + // var tkl = item.Groups["tkl"].Value.Replace(item.Groups["tmp"].Value, ""); + // if (Regex.IsMatch(tkl, @"(\d{11})")) + // continue; + // tklTmps.Add(tkl); + // } + //} + + + //regs1 = Regex.Matches(_mess, @"[^A-Za-z0-9]?(?[A-Za-z0-9]{5}(?\[0x[A-Za-z0-9]{8}\]|[^A-Za-z0-9])[A-Za-z0-9]{6})[^A-Za-z0-9]?"); + //foreach (Match item in regs1) + //{ + // if (item.Success) + // { + // var tkl = item.Groups["tkl"].Value.Replace(item.Groups["tmp"].Value, ""); + // if (Regex.IsMatch(tkl, @"(\d{11})")) + // continue; + // tklTmps.Add(tkl); + // } + //} + + + tklTmps = tklTmps.Distinct().ToList(); + //if (tklTmps != null && tklTmps.Count != 0) + //{ + // Dictionary tklDic = new Dictionary(); + // foreach (string tkl in tklTmps) + // { + // if (!tklDic.ContainsKey(tkl)) + // tklDic.Add(tkl, null); + // try + // { + // var h5 = new h5Top(); + // try + // { + // item_id = h5.GetItemIdByTKL(tkl, api); + // if (!string.IsNullOrWhiteSpace(h5.activityId)) + // activityId = h5.activityId; + // if (!string.IsNullOrWhiteSpace(item_id)) + // return item_id; + // } + // catch (Exception ex) + // { } + + // #region 调用淘宝接口 + // if (api != null) + // { + // #region 推广位为空时,从数据库中获取推广位数据 + // if (pids == null) + // { + // var adzoneInfo = ApiClient.GetSession().FindAdzoneInfos(); + // if (adzoneInfo != null) + // { + // var adzones = adzoneInfo.Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.adzone_pid_cps_name == api.Member.username && f.adzone_pid != "").ToList(); + + // if (adzones != null && adzones.Count != 0) + // { + // var adzone = adzones[0]; + // var pid = adzone.adzone_pid; + // pids = pid.Split('_'); + // } + // } + // } + // #endregion + + // if (pids != null) + // { + // for (int i = 0; i < 3; i++) + // { + // try + // { + // var result = api.AnalysisTkPassword(tkl, pids[3], pids[2]); + // if (result != null) + // { + + // if (string.IsNullOrWhiteSpace(result.num_iid) == false) + // { + // activityId = result.activityId; + // return result.num_iid; + // } + // else if (string.IsNullOrWhiteSpace(result.origin_url) == false) + // { + // var origin_url = result.origin_url; + // var itemId = h5.AnalysisItemidByTljUrl(origin_url); + // if (string.IsNullOrWhiteSpace(itemId)) + // { + // //https://mo.m.tmall.com/page/4575720?shop_id=467416422&tjm_src_bp=lianmeng&ali_trackid=2%3Amm_1754690195_2267550095_112115050458%3A1652094564_031_1590174982&union_lens=lensId%3ATAPI%401651496796%4021077da2_094a_18084e14332_2603%40022DmGvXUZxOvuwwSZ0LoETU&e=zrVP7yuy4rVotn5NVqnsNSD_KSPfxwxAjbefuUrtutMvRYPtLig9CvJWHexRmZcAI4Mf8vGNB9I5gQVXM_6rcSS0mLRQv4Bd_mADjKzV7vKVZ5v92btTAHsIrYMGBr2GBYPMuFXeq-4BuPt5MbeOhNcpn7YIi5VZD6mqIygp0v5Y1G4UzsUP7C8moQkRQa_XEW7UOyhDnSkfiCPkiD6Cz3R-90eN4O9vOXCP7dzEQOKfPMuLv_j__qqFFEONMR2_oHs8zUzui2caaWnKBfgFYluKPxpVF7I8PCr7uRbxpRR5dfvaanbnRU3etiyKgMVl&type=2&tk_cps_param=1754690195&tkFlag=0&tk_cps_ut=1&bxsign=tcdZEytOnK0_AhxV5fosBNu9idGZ5_8gUin4FkyHzftdv0tMZVkZO1xpC-uzCWNPNv09ZNRd_eheS4r7pSoiZhpyKVYrAm48FRABurbYVLtTmI&sourceType=other&suid=6af02016-55bc-4c67-8d07-07cfa0fb7513&ut_sk=1.XJLlO2HWVcIDABY8xNZnqB%2B8_21646297_1652094536032.TaoPassword-WeiXin.tjm_share&un=d09271ea3d8897ed2040bd82ddc2e1ea&share_crt_v=1&un_site=0&spm=a2159r.13376460.0.0&sp_abtk=common_tjm_share_commonInfo&sp_tk=5bCP5LuW5LiK6IO95pyJ5a2Q5LqG5Y676LW35a%2B55LqG&bc_fl_src=share-480627500109-1-0 + + // if (origin_url.Contains("tmall.com")) + // { + // var res = HttpExtend.GetHtml(new HttpHelper(), origin_url); + // if (!string.IsNullOrWhiteSpace(res.Html)) + // { + // var reg = Regex.Match(res.Html, @"item_id=""(\d+)""", RegexOptions.IgnoreCase); + // if (reg.Success) + // { + // return reg.Groups[1].Value; + // } + // } + // } + // } + // } + // } + // } + // catch (Exception ex) + // { + // //945122237(潜意识)请求阿里妈妈接口:{"error_response":{"code":15,"msg":"Remote service error","sub_code":"isv.parse-result-invalid","sub_msg":"淘口令解析结果无效","request_id":"z24mo2uo0obo"}} - 在 Api.Framework.Cps.AlimamaApi.SendTaobaoServer(String _api, Object _data, String _appkey, String _appsecret) 位置 C:\xxxxxxxxxxxxxxxxx + // LogHelper.GetSingleObj().Debug("tkl解析", tkl + " = " + mess + "; 异常:" + ex.Message); + // if (i >= 1) + // throw ex; + // } + // } + // } + // } + // #endregion + + // } + // catch (Exception ex) + // { + // tklDic[tkl] = ex; + // if (tklDic.Count < tklTmps.Count) + // continue; + // LogHelper.GetSingleObj().Debug("", $"Oo:{mess} tkl:{tkl} - {ex.Message} - {ex.StackTrace}"); + // throw ex; + // } + // } + + // //if (tklDic.Count >= tklTmps.Count) + // //{ + // // var ex = tklDic.Values.ToList()[0]; + // // throw ex; + // //} + //} + + mess = Util.RemoveEmoji(mess); + mess = Regex.Replace(mess, @"[]", "");//这里有两个看不见的字符,两个字符不一样,都要删除了(这个只针对Ipad协议) + + item_id = GetItemInfoByPass(mess, tklTmps, api, pids); + + } + return item_id; + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"mess={mess}{ex.Message},{ex.StackTrace}"); + //淘口令解析结果无效,当前淘口令无效 + if (ex.Message.Contains(@"""淘口令转链处理异常""") || ex.Message.Contains(@"淘口令解析结果无效") || ex.Message.Contains(@"""淘口令解析结果")) + { + throw ex; + } + return string.Empty; + } + return string.Empty; + } + + private string GetItemInfoByPass(string mess, List tklTmps, AlimamaApi api, string[] pids = null) + { + var item_id = string.Empty; + + var h5 = new h5Top(); + + foreach (string tkl in tklTmps) + { + try + { + item_id = h5.GetItemIdByTKL(tkl, api); + if (!string.IsNullOrWhiteSpace(h5.activityId)) + activityId = h5.activityId; + if (!string.IsNullOrWhiteSpace(item_id)) + return item_id; + } + catch (Exception ex) + { } + } + + try + { + #region 调用淘宝接口 + if (api != null) + { + if (string.IsNullOrWhiteSpace(mess)) + { + return string.Empty; + } + + #region 推广位为空时,从数据库中获取推广位数据 + if (pids == null) + { + var adzoneInfo = ApiClient.GetSession().FindAdzoneInfos(); + if (adzoneInfo != null) + { + var adzones = adzoneInfo.Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.adzone_pid_cps_name == api.Member.username && f.adzone_pid != "").ToList(); + + if (adzones != null && adzones.Count != 0) + { + var adzone = adzones[0]; + var pid = adzone.adzone_pid; + pids = pid.Split('_'); + } + } + } + #endregion + + if (pids != null) + { + for (int i = 0; i < 3; i++) + { + try + { + var result = api.AnalysisTkPassword(mess, pids[3], pids[2]); + if (result != null) + { + + if (string.IsNullOrWhiteSpace(result.num_iid) == false) + { + activityId = result.activityId; + return result.num_iid; + } + else if (string.IsNullOrWhiteSpace(result.origin_url) == false) + { + var origin_url = result.origin_url; + var itemId = h5.AnalysisItemidByTljUrl(origin_url); + if (string.IsNullOrWhiteSpace(itemId)) + { + //https://mo.m.tmall.com/page/4575720?shop_id=467416422&tjm_src_bp=lianmeng&ali_trackid=2%3Amm_1754690195_2267550095_112115050458%3A1652094564_031_1590174982&union_lens=lensId%3ATAPI%401651496796%4021077da2_094a_18084e14332_2603%40022DmGvXUZxOvuwwSZ0LoETU&e=zrVP7yuy4rVotn5NVqnsNSD_KSPfxwxAjbefuUrtutMvRYPtLig9CvJWHexRmZcAI4Mf8vGNB9I5gQVXM_6rcSS0mLRQv4Bd_mADjKzV7vKVZ5v92btTAHsIrYMGBr2GBYPMuFXeq-4BuPt5MbeOhNcpn7YIi5VZD6mqIygp0v5Y1G4UzsUP7C8moQkRQa_XEW7UOyhDnSkfiCPkiD6Cz3R-90eN4O9vOXCP7dzEQOKfPMuLv_j__qqFFEONMR2_oHs8zUzui2caaWnKBfgFYluKPxpVF7I8PCr7uRbxpRR5dfvaanbnRU3etiyKgMVl&type=2&tk_cps_param=1754690195&tkFlag=0&tk_cps_ut=1&bxsign=tcdZEytOnK0_AhxV5fosBNu9idGZ5_8gUin4FkyHzftdv0tMZVkZO1xpC-uzCWNPNv09ZNRd_eheS4r7pSoiZhpyKVYrAm48FRABurbYVLtTmI&sourceType=other&suid=6af02016-55bc-4c67-8d07-07cfa0fb7513&ut_sk=1.XJLlO2HWVcIDABY8xNZnqB%2B8_21646297_1652094536032.TaoPassword-WeiXin.tjm_share&un=d09271ea3d8897ed2040bd82ddc2e1ea&share_crt_v=1&un_site=0&spm=a2159r.13376460.0.0&sp_abtk=common_tjm_share_commonInfo&sp_tk=5bCP5LuW5LiK6IO95pyJ5a2Q5LqG5Y676LW35a%2B55LqG&bc_fl_src=share-480627500109-1-0 + + if (origin_url.Contains("tmall.com")) + { + var res = HttpExtend.GetHtml(new HttpHelper(), origin_url); + if (!string.IsNullOrWhiteSpace(res.Html)) + { + var reg = Regex.Match(res.Html, @"item_id=""(\d+)""", RegexOptions.IgnoreCase); + if (reg.Success) + { + return reg.Groups[1].Value; + } + } + } + } + } + } + } + catch (Exception ex) + { + //945122237(潜意识)请求阿里妈妈接口:{"error_response":{"code":15,"msg":"Remote service error","sub_code":"isv.parse-result-invalid","sub_msg":"淘口令解析结果无效","request_id":"z24mo2uo0obo"}} - 在 Api.Framework.Cps.AlimamaApi.SendTaobaoServer(String _api, Object _data, String _appkey, String _appsecret) 位置 C:\xxxxxxxxxxxxxxxxx + LogHelper.GetSingleObj().Debug("tkl解析", mess + "; 异常:" + ex.Message); + if (i >= 1) + throw ex; + } + } + } + } + #endregion + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Debug("", $"Oo:{mess} - {ex.Message} - {ex.StackTrace}"); + throw ex; + } + + return item_id; + } + + + /// + /// 获取宝贝Id.解析所有的各种链接/淘口令/喵口令等,先解析商品类型的链接,在去解析其他类型的链接 + /// + /// 要解析内容 + /// AlimamaApi对象 + /// 返回宝贝Id,找不到返回空,异常返回异常的信息 + [Obsolete("过时的")] + public string FindItemIdByUrlAndTklAndMkl(string mess, AlimamaApi api) + { + try + { + string item_id = string.Empty; + item_id = FindTbItemIdByStr(mess); + if (!string.IsNullOrEmpty(item_id)) return item_id; + + #region 2019年6月10日09:40:31 支持用户发送的语句中存在多个连接 + var regs = HttpExtend.RegexMatchesUrl(mess); + if (regs != null && regs.Count != 0) + { + foreach (var item in regs) + { + try + { + var url = item; + item_id = FindTbItemIdByStr(url);//正常的淘宝天猫链接 [ https://detail.tmall.com/item.htm?id=576795776133 && https://item.taobao.com/item.htm?id=573396652123 ] + if (!string.IsNullOrEmpty(item_id)) return item_id; + + if (mess.Contains("喵口令")) + { + try + { + var _app = api.SendServer("taobao.tbk.h5.top", + new { api = "mtop.tmall.share.initdialog", param = HttpHelper.ObjectToJson(new { data = HttpHelper.ObjectToJson(new { codes = new string[] { url }, wholeCode = HttpHelper.URLEncode(mess) }) }), v = "1.0" }); + if (_app != null && _app.ok) + { + var result = _app.message as Dictionary; + if (result != null && result.ContainsKey("dialog")) + { + result = result["dialog"] as Dictionary; + if (result.ContainsKey("rightBtnActionUrl")) + { + item_id = FindTbItemIdByStr(result["rightBtnActionUrl"].ToString()); + if (!string.IsNullOrEmpty(item_id)) return item_id; + } + } + } + + } + catch (Exception ex) + { } + } + //var regUrl = Regex.Match(url, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|jd.hk|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|t.cn|detail.yao.95095.com|laiwang.com|jd.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com)"); + //var regUrl = Regex.Match(url, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|t.cn|detail.yao.95095.com|laiwang.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com|m.tb.cn)"); + var regUrl = Regex.Match(url, @"(yukhj.com|m.tb.cn|m.yeeoq.top|m.uqlsi|m.rijni|m.gkqmj|m.mulwt|uland\\.taobao\\.com|sjtm.me|aa5d.com|d11a.com|f61[a-z].com|92db.com|yqt.so|e22a.com|f61b.com|detail.m.tmall.hk|k.83jie.com|ewqcxz.com|items.alitrip.com|tmqd.me|detail.tmall.hk|url.cn|taobao.com|mashort.cn|tmall.com|tb.cn|detail.yao.95095.com|laiwang.com|dwz.cn|juhuasuan.com|detail.m.tmall.com|zmnxbc.com|s.click.taobao|detail.liangxinyao.com|m.tb.cn)"); + if (regUrl.Success) + { + var html = string.Empty; + for (int i = 0; i < 3; i++) + { + var http = new HttpHelper(); + html = http.GetHtml(url).Html; + if (html.Contains("超时操作")) + Thread.Sleep(500); + else break; + } + var reg = Regex.Match(html, @"var url = '(?.+?)';"); + if (reg.Success) + item_id = CouponByItemId(reg.Groups["url"].Value, api); + if (string.IsNullOrWhiteSpace(item_id)) + item_id = FindTbItemIdByStr(html); + if (!string.IsNullOrWhiteSpace(item_id)) return item_id; + + if (url.Contains("uland.taobao")) + { + item_id = CouponByItemId(url, api); + if (!string.IsNullOrEmpty(item_id)) return item_id; + } + + if (url.Contains("s.click.taobao"))//https://s.click.taobao.com/aFIAbOw 这种链接 + { + #region 2022年9月5日15:28:32 + //var locationA = TbTools.FindLocationByUrl(url); + //if (locationA != null) + //{ + // if (!locationA.Contains("err.taobao.com")) + // { + // //item_id = CouponByItemId(mess, api); + // item_id = CouponByItemId(url, api); + // if (!string.IsNullOrEmpty(item_id)) return item_id; + // var locationB = TbTools.FindLocationByUrl(locationA); + // if (string.IsNullOrWhiteSpace(locationB)) { item_id = string.Empty; } + // else + // { + // var goodsUrl = HttpHelper.URLDecode(locationB.Replace("https://s.click.taobao.com/t_js?tu=", "").Replace("http://s.click.taobao.com/t_js?tu=", "")); + // var tb_url = TbTools.FindLocationByUrl(goodsUrl, locationB);//获取到的淘宝链接 + // if (!string.IsNullOrEmpty(item_id)) return item_id; + // } + // } + //} + //else + //{ + // var _html = GetHTML(url); + // reg = Regex.Match(_html, "real_jump_address = '(?<真正的跳转地址>[^']+)"); + // if (reg.Success) + // { + // var address = reg.Groups["真正的跳转地址"].Value; + // //_html = GetHTML(HttpHelper.URLDecode(address).Replace("&", "&"), HttpHelper.URLDecode(url)); + // for (int i = 0; i < 3; i++) + // { + // _html = GetHTML(address.Replace("&", "&"), url); + // item_id = FindTbItemIdByStr(_html); + // if (!string.IsNullOrWhiteSpace(item_id)) + // return item_id; + // else + // { + // //访问频繁,休息重试3次 + // Thread.Sleep(500); + // } + // } + // } + + //} + #endregion + + var result = api.AnalysisTkUrl(url, "2"); + if (result != null) + { + return result.item_id; + } + + } + } + mess = mess.Replace(url, "");//清除没用的连接,如果连接无法解析,name下面的淘口令解析将会减轻负担 + } + catch (Exception ex) + { } + } + } + #endregion + + //if (!reg.Success || string.IsNullOrEmpty(item_id))//非链接 淘口令 + if (string.IsNullOrEmpty(item_id))//非链接 淘口令 + { + if (Util.IsXML(mess)) + return string.Empty; + var _mess = Regex.Replace(mess, "Http:/[A-Za-z]", "", RegexOptions.IgnoreCase); + var regs1 = Regex.Matches(_mess, "[^A-Za-z0-9]?([A-Za-z0-9]{11})[^A-Za-z0-9]?"); + foreach (Match item in regs1) + { + try + { + if (item.Success) + { + try + { + if (api != null) + { + try + { + var adzoneInfo = ApiClient.GetSession().FindAdzoneInfos(); + if (adzoneInfo != null) + { + var adzones = adzoneInfo.Where(f => f.alliance_id == (int)CpsType.阿里妈妈 && f.adzone_pid_cps_name == api.Member.username && f.adzone_pid != "").ToList(); + + if (adzones != null) + { + foreach (var adzone in adzones) + { + try + { + var pid = adzone.adzone_pid; + var pids = pid.Split('_'); + var result = api.AnalysisTkPassword(item.Groups[1].Value, pids[3], pids[2]); + if (result != null) + { + if (string.IsNullOrWhiteSpace(result.num_iid) == false) + { + return result.num_iid; + } + } + } + catch (Exception) + { } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", ex.Message + " _ " + ex.StackTrace); + } + } + + var h5 = new h5Top(); + item_id = h5.GetItemIdByTKL(item.Groups[1].Value, api); + if (!string.IsNullOrWhiteSpace(h5.activityId)) + activityId = h5.activityId; + if (!string.IsNullOrWhiteSpace(item_id)) + return item_id; + else + { + } + //var _temp = api.SendServer("com.taobao.redbull.getpassworddetail", new { password = item.Groups[1].Value }); + //if (_temp != null && _temp.ok) + //{ + // if (_temp.message.ToString().Contains("口令不存在")) + // return string.Empty; + // var _obj = _temp.message as Dictionary; + // var _url = string.Empty; + // if (_obj.ContainsKey("url")) + // _url = _obj["url"] as string; + // if (!string.IsNullOrEmpty(_url)) return CouponByItemId(_url, api); + //} + //else return "服务器繁忙,请稍后重试!"; + } + catch (Exception ex) + { throw ex; } + } + } + catch (Exception ex) + { + EventClient.OnEvent("", "C = " + ex.Message + ex.StackTrace); + // throw ex; + } + } + } + return item_id; + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"mess={mess}{ex.Message},{ex.StackTrace}"); + return string.Empty; + } + } + + #region 私域数据相关 + /// + /// 私域查詢数据的類型 + /// + public enum PublisherType + { + SpecialId = 0, + ExternalId = 1 + } + + /// + /// 私域用户备案信息查询 + /// + /// + /// + /// special_id + public string FindTbPublisherInfoFirst(AlimamaApi api, object _data, PublisherType publisherType = PublisherType.SpecialId) + { + try + { + var result = api.SendTaobao("taobao.tbk.sc.publisher.info.get", _data); + if (result != null && result.ContainsKey("data")) + { + var data = result["data"] as Dictionary; + if (data != null && data.ContainsKey("inviter_list")) + { + var inviter_list = data["inviter_list"] as Dictionary; + if (inviter_list != null && inviter_list.ContainsKey("map_data")) + { + var map_data = inviter_list["map_data"] as ArrayList; + if (map_data != null && map_data.Count != 0) + { + if (map_data.Count == 1) + { + foreach (Dictionary item in map_data) + { + if (publisherType == PublisherType.SpecialId && item.ContainsKey("special_id")) + return item["special_id"].ToString(); + if (publisherType == PublisherType.ExternalId && item.ContainsKey("external_id")) + return item["external_id"].ToString(); + } + } + } + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"查询私域绑定关系异常:{ex.Message},{ex.StackTrace}"); + } + return string.Empty; + } + + /// + /// 私域用户备案信息查询,默认查询所有 + /// + /// AlimamaApi对象 + /// 参数 + public ArrayList FindTbPublisherInfoAll(AlimamaApi api, object _data = null) + { + try + { + if (_data == null) + _data = new { info_type = 2, relation_app = "common", page_size = 1000, external_type = 1 }; + + var result = api.SendTaobao("taobao.tbk.sc.publisher.info.get", _data); + if (result != null && result.ContainsKey("data")) + { + var data = result["data"] as Dictionary; + if (data != null && data.ContainsKey("inviter_list")) + { + var inviter_list = data["inviter_list"] as Dictionary; + if (inviter_list != null && inviter_list.ContainsKey("map_data")) + { + var map_data = inviter_list["map_data"] as ArrayList; + if (map_data != null && map_data.Count != 0) + return map_data; + } + } + } + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"查询私域绑定关系异常:{ex.Message},{ex.StackTrace}"); + } + return new ArrayList(); + } + #endregion + + /// + /// 是否运行淘宝私域功能,用于同步私域数据 + /// + /// + public bool IsRunTBSiYu() + { + try + { + for (int i = 0; i < 2; i++) + { + var config = Util.ReadConfig("插件-淘宝返利-配置", true);//刷新积分管理中的配置文件 + if (config == null) continue; + if (config.ContainsKey("QueryComparisonSwitch")) + { + var qComSwitch = config["QueryComparisonSwitch"].ToString(); + + return qComSwitch == "0"; + } + } + } + catch (Exception ex) + { } + return false; + } + + + public static string BizSceneId(string itemId) + { + var bizSceneId = "2"; + if (itemId.Contains("-")) + { + bizSceneId = "1"; + } + + return bizSceneId; + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + public Dictionary GetPrivilege(AlimamaApi api, string item_id, string[] pid_split, string biz_scene_id, string external_id = "", string special_id = "") + { + biz_scene_id = BizSceneId(item_id); + + object data = null; + if (!string.IsNullOrWhiteSpace(external_id) && !string.IsNullOrWhiteSpace(special_id)) + data = new { item_id = item_id, site_id = pid_split[2], adzone_id = pid_split[3], special_id = special_id, external_id = external_id, biz_scene_id = biz_scene_id }; + else if (!string.IsNullOrWhiteSpace(external_id)) + data = new { item_id = item_id, site_id = pid_split[2], adzone_id = pid_split[3], external_id = external_id, biz_scene_id = biz_scene_id }; + else + data = new { item_id = item_id, site_id = pid_split[2], adzone_id = pid_split[3], biz_scene_id = biz_scene_id }; + + //data = new { item_id = item_id, site_id = pid_split[2], adzone_id = pid_split[3], special_id = special_id }; + + var privilege = api.SendTaobao("taobao.tbk.privilege.get", data); + if (privilege == null) + { + for (int i = 0; i <= 1; i++) + { + privilege = api.SendTaobao("taobao.tbk.privilege.get", data); + if (privilege != null) break; + Thread.Sleep(200); + } + } + if (privilege == null) throw new Exception("@高佣金转链失败"); + return privilege; + } + + /// + /// 将淘宝url生成淘口令 + /// + /// 宝贝地址[优惠券地址|宝贝地址] + /// 标题 + /// 图片url[宝贝图片,非本地图片] + /// AlimamaApi对象 + /// 返回淘口令或空 + public string FindTKL(string _url, string title, string logo, AlimamaApi api) + { + try + { + var url = _url; + //注:转淘口令的时候 title 参数存在一些管检测,需要处理。一下转不出来的,将以“淘宝精选商品”为标题 + title = title.Replace("‮", "").Replace("总复习", ""); + //title = "123456789"; + Dictionary tkl_json = null; + for (int i = 0; i <= 4; i++) + { + if (title.Length < 5) + title = "淘宝商品:" + title; + try + { + tkl_json = api.SendTaobao("taobao.tbk.tpwd.create", new { url = url, text = title, logo = logo }); + } + catch (Exception ex) + { + if (ex.Message.Contains("sub_msg\":\"title have illegal characters")) + { + title = "内部优惠通道"; + if (i > 2) + { + var tbAnalysis = new TBHelper.TbAnalysis(); + url = tbAnalysis.FindShortUrlBySrcUrl(url, api); + } + continue; + } + } + if (tkl_json == null) + { + Thread.Sleep(200); + } + else + { + if ((tkl_json["data"] as Dictionary).Count != 0) + break; + } + title = "内部优惠通道"; + } + if (tkl_json == null) throw new Exception(); + var data = tkl_json["data"] as Dictionary; + if (data.Count == 0) throw new Exception("生成淘口令失败"); + var isoTkl = data["model"].ToString(); + + //Console.WriteLine(isoTkl); + + var tkl = data["password_simple"].ToString(); + //Console.WriteLine(tkl); + return tkl; + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"生成淘口令异常:{_url},{ex.Message},{ex.StackTrace}"); + return string.Empty; + } + } + + /// + /// 将淘宝url生成淘口令 + /// + /// + /// + /// + public TklInfo FindTKL(string url, AlimamaApi api) + { + try + { + Dictionary tkl_json = null; + for (int i = 0; i <= 4; i++) + { + try + { + tkl_json = api.SendTaobao("taobao.tbk.tpwd.create", new { url = url }); + } + catch (Exception ex) + { + if (ex.Message.Contains("sub_msg\":\"title have illegal characters")) + { + if (i > 2) + { + var tbAnalysis = new TBHelper.TbAnalysis(); + url = tbAnalysis.FindShortUrlBySrcUrl(url, api); + } + continue; + } + } + if (tkl_json == null) + { + Thread.Sleep(200); + } + else + { + if ((tkl_json["data"] as Dictionary).Count != 0) + break; + } + } + if (tkl_json == null) throw new Exception(); + var data = tkl_json["data"] as Dictionary; + if (data.Count == 0) throw new Exception("生成淘口令失败"); + var model = data["model"].ToString(); + + var isoTkl = string.Empty; + var urlTmp = HttpExtend.RegexMatchUrl(model); + if (!string.IsNullOrWhiteSpace(urlTmp)) + isoTkl = urlTmp.Replace("m.tb", "s.tb"); + + //Console.WriteLine(isoTkl); + var tkl = data["password_simple"].ToString(); + + //Console.WriteLine(tkl); + return new TklInfo() { tkl = tkl, isoUrl = isoTkl }; + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"生成淘口令异常:{url},{ex.Message},{ex.StackTrace}"); + return null; + } + } + + /// + /// 淘口令信息 + /// + public class TklInfo + { + public string isoUrl { get; set; } + public string tkl { get; set; } + } + + /// + /// 生成淘宝短连接 + /// + /// url链接 + /// AlimamaApi对象 + /// 返回缩短后的链接或原始链接 + public string FindShortUrlBySrcUrl(string url, AlimamaApi api) + { + try + { + Dictionary result = null; + for (int i = 0; i <= 2; i++) + { + result = api.SendTaobao("taobao.tbk.spread.get", new { requests = "[{\"url\":\"" + url + "\"}]" }); + if (result == null) + Thread.Sleep(200); + else + { + if (result.ContainsKey("tbk_spread")) + { + var content = ((result["tbk_spread"] as ArrayList)[0] as Dictionary)["content"].ToString(); + if (!string.IsNullOrEmpty(content)) + return content; + } + } + } + return url; + //var tbk_spread = result["tbk_spread"] as ArrayList; + //var content = (tbk_spread[0] as Dictionary)["content"].ToString(); + //return content; + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"生成短连接失败:{url},{ex.Message},{ex.StackTrace}"); + return url; + } + } + + /// + /// 替换淘口令前后符号(系统配置) + /// + /// 需要替换的淘口令 + /// + public string ReplaceTklModifier(string tkl) + { + try + { + //淘口令的前/后符号有没有设置.有设置将替换掉 + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.TklStr_First)) + { + var modifier = Util.FindTKlRandomModifier(ApiClient.Setting.SystemConfig.TklStr_First); + tkl = modifier + tkl.Substring(1, tkl.Length - 1); + } + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.TKLStr_End)) + { + var modifier = Util.FindTKlRandomModifier(ApiClient.Setting.SystemConfig.TKLStr_End); + tkl = tkl.Substring(0, tkl.Length - 1) + modifier; + } + + if (tkl.Length == 13 && (!Regex.IsMatch(tkl, @"(\d.[A-Za-z0-9]{11}.:\/)") || !Regex.IsMatch(tkl, @"(\d\s[A-Za-z0-9]+\s.[A-Za-z0-9]{11}.\/)"))) + tkl = "8 AA1111 " + tkl + "/"; + } + catch (Exception ex) + { } + return tkl; + } + + #region 通过优惠券链接获取淘宝宝贝的id + /// + /// 通过优惠券链接获取淘宝宝贝的id + /// + /// + public string CouponByItemId(string url, AlimamaApi api) + { + try + { + var itemId = FindTbItemIdByStr(url); + if (!string.IsNullOrEmpty(itemId)) + return itemId; + if (url.Contains(@"uland.taobao.com/coupon"))//这是针对淘宝联盟有优惠券的接口.//https://uland.taobao.com/coupon/edetail + { + var coupon = api.CheckCoupon(url);//将返利接口转成淘宝宝贝接口 + if (coupon != null) return coupon.itemId; + } + else if (url.Contains(@"uland.taobao.com/ccoupon")) + { + var x_reg = Regex.Match(url, "e=([^&]+)"); + if (x_reg.Success) + { + h5Top h5 = new h5Top(); + //https://h5api.m.taobao.com/h5/mtop.taobao.baichuan.smb.get/1.0/?jsv=2.4.0&appKey=12574478&t=1580101872147&sign=0d0cd5819f67b6568a77de5867f151f9&api=mtop.taobao.baichuan.smb.get&v=1.0&type=originaljson&dataType=jsonp&timeout=10000 + var rst = h5.M_GET("mtop.alimama.union.xt.biz.zhibo.api.entry", new + { + floorId = 13193, + variableMap = "{\"e\":\"" + HttpHelper.URLDecode(x_reg.Groups[1].Value) + "\",\"type\":\"nBuy\",\"buyMoreSwitch\":\"0\",\"union_lens\":\"lensId:" + HttpHelper.URLDecode(Regex.Match(url, "=lensId:([^&]+)").Groups[1].Value) + "\",\"recoveryId\":\"" + Api.Framework.Tools.Util.GetRandomString(16) + "_" + HttpExtend.GetTimeStamp() + "\"}" + }); + + if (rst != null && rst.ContainsKey("resultList")) + { + var resultList = rst["resultList"] as ArrayList; + if (resultList != null && resultList.Count != 0) + { + var result = resultList[0] as Dictionary; + if (result != null && result.ContainsKey("itemId")) + return result["itemId"].ToString(); + } + } + //Console.WriteLine(HttpHelper.ObjectToJson(rst)); + } + } + else if (url.Contains(@"s.click.taobao.com"))//这是针对淘宝联盟没有全的接口.//https://s.click.taobao.com/t?e=m + { + var html = string.Empty; + //获得首次Location 地址 + bool first = false; + Next: + string location = GetLocation(url); + + if (!string.IsNullOrWhiteSpace(location) && location.StartsWith("https://s.click.taobao.com/t?e=")) + { + var _location = GetLocation(location); + if (!string.IsNullOrEmpty(_location)) location = _location; + } + if (!string.IsNullOrEmpty(location))//跳转地址存在 + { + //if (location.Contains("uland.taobao.com/coupon/edetail?e=")) + + + + if (location.Contains("uland.taobao.com/coupon/edetail?")) + { + + var reg = Regex.Match(location, @"(?:&|\?)itemId=(\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups[1].Value; + + string tempHtml = GetHTML(location); + tempHtml = HttpHelper.URLDecode(tempHtml); + var uland = Regex.Match(tempHtml, "&req_url=([^\"]+)"); + if (uland.Success) + { + var param_e = Regex.Match(uland.Groups[1].Value, "e=([^&]+)"); + if (!param_e.Success) + return string.Empty; + var coupon = api.CheckCoupon(uland.Groups[1].Value); + if (coupon != null) + return coupon.itemId; + } + else + { + //Console.WriteLine(location); + var x_reg = Regex.Match(location, "e=([^&]+)"); + if (x_reg.Success) + { + h5Top h5 = new h5Top(); + //https://h5api.m.taobao.com/h5/mtop.taobao.baichuan.smb.get/1.0/?jsv=2.4.0&appKey=12574478&t=1580101872147&sign=0d0cd5819f67b6568a77de5867f151f9&api=mtop.taobao.baichuan.smb.get&v=1.0&type=originaljson&dataType=jsonp&timeout=10000 + var rst = h5.M_GET("mtop.alimama.union.xt.biz.quan.api.entry", new { floorId = 13193, variableMap = "{\"e\":\"" + HttpHelper.URLDecode(x_reg.Groups[1].Value) + "\",\"src\":\"" + HttpHelper.URLDecode(Regex.Match(location, "&src=([^&]+)").Groups[1].Value) + "\",\"af\":\"4\",\"type\":\"nBuy\",\"buyMoreSwitch\":\"0\",\"union_lens\":\"lensId:" + HttpHelper.URLDecode(Regex.Match(location, "=lensId:([^&]+)").Groups[1].Value) + "\",\"recoveryId\":\"" + Api.Framework.Tools.Util.GetRandomString(16) + "_" + HttpExtend.GetTimeStamp() + "\"}" }); + //Console.WriteLine(HttpHelper.ObjectToJson(rst)); + + if (rst != null && rst.ContainsKey("resultList")) + { + var resultList = rst["resultList"] as ArrayList; + for (int i = 0; i < resultList.Count; i++) + { + var dic = resultList[i] as Dictionary; + if (dic.ContainsKey("itemId")) + { + return dic["itemId"].ToString(); + } + } + } + } + + //"系统日志,分析地址失败:" + url;} + } + } + else if (location.Contains("uland.taobao.com")) + { + var _reg = Regex.Match(location, "itemId=(\\d+)", RegexOptions.IgnoreCase); + if (_reg.Success) + return _reg.Groups[1].Value; + } + else if (location.Contains("tu=")) + { + //获得二次访问地址 + string next = HttpHelper.URLDecode(location.Replace("http://s.click.taobao.com/t_js?tu=", "").Replace("https://s.click.taobao.com/t_js?tu=", "")); + html = HttpHelper.URLDecode(GetHTML(next, location)); + var reg = Regex.Match(html, @"(?:&|\?)itemId=(\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups[1].Value; + } + else + return FindTbItemIdByStr(GetHTML(location)); + } + else if (!string.IsNullOrEmpty(location) && !first) + { + url = location; + first = true; + goto Next; + } + + #region + if (string.IsNullOrWhiteSpace(location)) + { + var _html = GetHTML(url); + var reg = Regex.Match(_html, "real_jump_address = '(?<真正的跳转地址>[^']+)"); + if (reg.Success) + { + var address = reg.Groups["真正的跳转地址"].Value; + //_html = GetHTML(HttpHelper.URLDecode(address).Replace("&", "&"), HttpHelper.URLDecode(url)); + for (int i = 0; i < 3; i++) + { + _html = GetHTML(address.Replace("&", "&"), url); + itemId = FindTbItemIdByStr(_html); + if (!string.IsNullOrWhiteSpace(itemId)) + return itemId; + else + { + //访问频繁,休息重试3次 + Thread.Sleep(500); + } + } + } + } + #endregion + } + else if (url.Contains("m.tb.cn")) + { + string tempHtml = GetHTML(url); + tempHtml = HttpHelper.URLDecode(tempHtml); + var reg = Regex.Match(tempHtml, "url = '(?<链接>.*?)';"); + if (reg.Success) + { + var _url = reg.Groups["链接"].Value; + _url = HttpHelper.URLDecode(_url); + itemId = FindTbItemIdByStr(_url); + if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + } + } + else if (url.Contains("h5.m.taobao.com")) + { + var _url = HttpHelper.URLDecode(HttpHelper.URLDecode(url)); + itemId = FindTbItemIdByStr(_url); + if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + } + else if (url.Contains("mo.m.tmall.com")) + { + string tempHtml = GetHTML(url); + itemId = FindTbItemIdByStr(tempHtml); + if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + } + else if (url.Contains("uland.taobao")) + { + + } + } + catch (Exception ex) + { + //Console.WriteLine(ex.Message); + } + return string.Empty; + } + + private string GetLocation(string url) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = "get", + IsToLower = false, + Cookie = "", + Referer = "", + Postdata = "", + Timeout = 5000, + ReadWriteTimeout = 15000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = false, + ProxyIp = "" + }; + HttpResult result = http.GetHtml(item); + return result.Header.Get("Location"); + } + catch (Exception ex) + { + //EventClient.OnEvent(this, $"Location:{url},{ex.Message},{ex.StackTrace}"); + } + return string.Empty; + } + private string GetHTML(string url, string rf = "", string postData = "") + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + Method = (postData == "" ? "get" : "post"), + Postdata = (postData == "" ? "" : postData), + IsToLower = false, + Referer = rf, + Timeout = 5000, + ReadWriteTimeout = 15000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = true + }; + HttpResult result = http.GetHtml(item); + //var location = result.Header.Get("Location"); + return result.Html; + } + catch (Exception) + { } + return string.Empty; + } + #endregion + + } + + public class TbTools + { + #region H5 + + /// + /// 获取宝贝的基础信息 + /// + /// [比如: mtop.taobao.detail.getdetail] + /// 链接附带的参数 例如: new { itemNumId = itemId, exParams = new { id = itemId }, ttid = "2016@taobao_h5_2.0.0", isSec = "0", ecode = "0", AntiFlood = "true", AntiCreep = "true", H5Request = "true", type = "jsonp", dataType = "jsonp" } + /// 将获取到的内容以out的形式返回给调用 + /// 版本号默认[6.0] + /// Dictionary + public static Dictionary GetH5Result(string api, object data, out string html, string version = "6.0") + { + //bool next = false; + int maxnumber = 5; + int number = 0; + Next: + number++; + string time = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString(); + string mh5Tk = HttpExtend.GetCookiesValue("_m_h5_tk", Cookies); + mh5Tk = string.IsNullOrEmpty(mh5Tk) ? "f64aa152f943661f750e6212ebc98804_1481170439770" : mh5Tk; + string json = (data.GetType() == typeof(string)) ? data.ToString() : HttpHelper.ObjectToJson(data).Replace("\\u0026", "&").Replace("_params", "param"); + string temp_ = mh5Tk + "&" + time + "&" + appKey + "&" + json; + string sign = HttpExtend.GetMD5String(temp_); + string send = HttpExtend.UrlEncode(json); + string temp = string.Format("http://h5api.m.taobao.com/h5/{5}/{4}/?jsv=2.4.11&v={4}&api={5}&appKey={0}&t={1}&callback=mtopjsonp1&type=jsonp&sign={2}&data={3}", appKey, time, sign, send, version, api); + html = M_GET_HTML(temp).Trim(); + if (html.Contains("令牌过期") || html.Contains("令牌为空") || html.Contains("失效")) + { + if (number <= 2) goto Next; + } + if (html.Contains("挤爆") && number <= maxnumber) + { + + Dictionary _json = HttpExtend.JsonToDictionary(html); + + string _url = (_json["data"] as Dictionary)["url"].ToString(); + //next = false; + goto Next; + } + + var reg = Regex.Match(html, @"^mtopjsonp1\((.*?)\)$", RegexOptions.IgnoreCase); + if (reg.Success) + { + var dic = HttpExtend.JsonToDictionary(reg.Groups[1].Value); + if (dic.ContainsKey("data") && html.Contains("SUCCESS::调用成功")) + return dic["data"] as Dictionary; + throw new Exception(reg.Groups[1].Value); + } + throw new Exception(api + " = " + html); + } + + private const string _key = "wmUZgme6iOPOaMTZtPu5DKQ8Dph9fSgy6abFyQv25MD8xOMPBBo0wsLUOVt8r9sk+li11mIg1fs1HPJ75UmIle+w9xhIx/nsXWejuQhXlQV0VyJtzI+id8G+FcyYaog91MfPndJoO3m30fSjE/0KDLDmv1EeQcP24RAzeA29p7c=AQAB"; + private const int _appid = 10004; + //private static string _host = "https://cps.api.52cmg.cn"; + + private static string _cookies = string.Empty; + + private static string Cookies + { + get + { + if (string.IsNullOrEmpty(_cookies)) + { + HttpHelper http = new HttpHelper(); + string cookies = http.GetHtml(new HttpItem() { URL = "http://api.m.taobao.com/h5/mtop.alimama.union.hsf.coupon.get/1.0/?v=1.0&api=mtop.alimama.union.hsf.coupon.get&appKey=12574478&t=1521082116428&callback=mtopjsonp1&type=jsonp&sign=e102e09c3da2505790412f4b5904cfec&data=%7B%22e%22%3A%22kKwRS8jKFeIGQASttHIRqX4ccS%252BmEB0fPkvI%252B9vDGidk3qypIGt1zv02HjWWzK8QrVVJXxMdEXoJP%252FpVy45HN79fwBwwUiqlbZt%252F%252F9VQxkYKu2xm%252BXzUVW7PVn13QcLNcISolD8QJ4rvZt%252BicRrQwg%253D%253D%22%2C%22pid%22%3A%22mm_96747532_17602904_63786428%22%7D", Timeout = 5000, ReadWriteTimeout = 5000 }).Cookie; + _cookies = HttpHelper.GetSmallCookie(cookies); + } + return _cookies; + } + set { _cookies = value; } + } + + private const string appKey = "12574478"; + const string keyword = "亲,小二正忙,滑动一下马上回来|挤爆|rgv587_flag"; + private static string M_GET_HTML(string tempUrl) + { + try + { + HttpItem item = new HttpItem() + { + URL = tempUrl,//URL 必需项 + Method = "get",//URL 可选项 默认为Get + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = Cookies + ";random=" + new Random().Next(),//字符串Cookie 可选项 + Referer = "http://m.taobao.com",//来源URL 可选项 + Timeout = 5000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 5000,//写入Post数据超时时间 可选项默认为30000 + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "text/html",//返回类型 可选项有默认值 + Allowautoredirect = false,//是否根据301跳转 可选项 + }; + HttpHelper http = new HttpHelper(); + int i = 0; + Next: + HttpResult result = http.GetHtml(item); + string html = result.Html; + if (Regex.IsMatch(html, keyword)) + { + var r = item.SetProxyIP(http, new AuthEndpoint() + { + Host = ApiClient.Setting.SystemConfig.cps_server_api + "api/webtool.asmx/send_data", + Appid = _appid, + Enckey = _key, + Method = "find_proxy" + }); + i++; + if (r && i < 3) goto Next; + } + if (!string.IsNullOrEmpty(result.Cookie)) + { + Cookies = HttpExtend.UpdateCookies(Cookies, result.Cookie); + } + return html; + } + catch (Exception) + { + return string.Empty; + } + } + #endregion + + /// + /// 链接跳转获取Location + /// + /// 要获取Location的链接 + /// 来源 + /// 是否跳转 + /// + public static string FindLocationByUrl(string url, string referer = "", bool allowautoredirect = false) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + IsToLower = false, + Timeout = 5000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Referer = referer, + Allowautoredirect = allowautoredirect + }; + HttpResult result = http.GetHtml(item); + return result.Header.Get("Location"); + } + catch (Exception) + { } + return string.Empty; + } + + /// + /// 发送API数据 + /// + /// API接口 + /// 参数 + /// + public static WebResult SendData(string method, object param = null, bool flag = true) + { + int num = 0; + Next: + try + { + AuthEndpoint end = new AuthEndpoint() + { + Appid = _appid, + Enckey = _key, + Host = ApiClient.Setting.SystemConfig.cps_server_api + (flag ? "api/alimama.asmx/send_data" : "api/webtool.asmx/send_data"), + Method = method + }; + if (param != null) + { + if (param.GetType() == typeof(Dictionary)) + { + var _param = param as Dictionary; + foreach (var item in _param) + { + end.Param[item.Key] = item.Value; + } + } + else + { + var _param = param.GetType().GetProperties(); + foreach (var item in _param) + { + end.Param[item.Name] = item.GetValue(param); + } + } + + } + HttpHelper http = new HttpHelper(); return http.SendData(end, true); + } + catch (Exception ex) + { + if (ex.Message == "未将对象引用设置到对象的实例。" && num <= 4) + { + num++; + goto Next; + } + return new CsharpHttpHelper.WebResult() { ok = false, message = ex.Message }; + } + } + + public static string GetLocation(string url) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url + }; + HttpResult result = http.GetHtml(item); + var _url = result.Header.Get("Location"); + if (string.IsNullOrEmpty(_url)) + { + return url; + } + else + return _url; + } + catch (Exception) + { + + } + return string.Empty; + } + + public static string GetLocation(string url, string referer = "", bool allowautoredirect = false) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + IsToLower = false, + Timeout = 5000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Referer = referer, + Allowautoredirect = allowautoredirect + }; + HttpResult result = http.GetHtml(item); + return result.Header.Get("Location"); + } + catch (Exception) + { + } + return string.Empty; + } + + } + + } +} \ No newline at end of file diff --git a/类库/Api.Framework/Tools/TaskTool.cs b/类库/Api.Framework/Tools/TaskTool.cs new file mode 100644 index 0000000..91fe41e --- /dev/null +++ b/类库/Api.Framework/Tools/TaskTool.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Api.Framework.Utils +{ + public class TaskTool + { + /// + /// 最大并发 + /// + private int max_run { get; set; } + + /// + /// 任务管理器 + /// + public List Tasks { get; private set; } + + /// + /// 创建线程池 + /// + /// + public TaskTool() + { + this.Tasks = new List(); + } + + /// + /// 增加任务 + /// + /// + public void AddTask(Action method) + { + Tasks.Add(new Task(method)); + } + + /// + /// 执行线程池内所有线程 + /// + /// 最大并行线程数量 + /// 执行完成后通知 + public void Start(int max_sync, AsyncCallback callback) + { + DateTime start_Time = DateTime.Now; + Action action = delegate () + { + //循环几次 + var _count = Tasks.Count / max_sync; if (Tasks.Count % max_sync != 0) _count++; + for (int i = 0; i < _count; i++) + { + List _runs = new List(); + for (int j = i * max_sync; j < Tasks.Count && _runs.Count < max_sync; j++) + { + var task = Tasks[j]; + _runs.Add(task); + task.Start(); + } + Task.WaitAll(_runs.ToArray()); + } + + }; + if (callback == null) action.Invoke(); + else action.BeginInvoke(callback, null); + } + + + public void Clear() + { + this.Tasks.Clear(); + } + } + + public static class TaskExtend + { + + /// + /// 不卡界面休眠 + /// + /// 源 + /// 毫秒 + public static void Sleep(this object obj, int millisecondsTimeout) + { + System.Threading.Thread t = new System.Threading.Thread(o => System.Threading.Thread.Sleep(millisecondsTimeout)); + t.Start(obj); + while (t.IsAlive) + { + System.Windows.Forms.Application.DoEvents(); + } + } + } + +} diff --git a/类库/Api.Framework/Tools/UpdateClient.cs b/类库/Api.Framework/Tools/UpdateClient.cs new file mode 100644 index 0000000..53db250 --- /dev/null +++ b/类库/Api.Framework/Tools/UpdateClient.cs @@ -0,0 +1,134 @@ +using CsharpHttpHelper; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + public class UpdateClient + { + private static string ExecName = "FLSystem"; + /// + /// 获取云端的文件列表 + /// + public static string GetCloudFileHist() + { + try + { + int LastId = 1; + + try + { + var id = GetVersionId(); + LastId = int.Parse(id); + } + catch (Exception) + { + LastId = 1; + } + + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = "http://file.api.52cmg.cn/file/QueryHist?Name=" + HttpHelper.URLEncode(ExecName, Encoding.UTF8) + "&LastId=" + LastId, + Timeout = 30000 + }; + var result = http.GetHtml(item).Html; + var data = JObject.Parse(result); + if ((bool)data["Ok"] && data["Data"] != null) + { + return ShowUpdate(data["Data"]); + } + } + catch (Exception) + { } + return null; + } + + private static IniHelper Ini { get; set; } + + + public static string ShowUpdate(JToken jToken) + { + var strb = new StringBuilder(); + try + { + + + foreach (var item in jToken) + { + strb.AppendLine(((DateTime)item["CreateTime"]).ToString("yyyy.MM.dd.HHmm")); + strb.AppendLine(item["Message"].ToString()); + strb.AppendLine(); + } + } + catch (Exception ex) + { } + return strb.ToString(); + } + + /// + /// 版本数据id + /// + /// + private static string GetVersionId() + { + Ini = new IniHelper(HttpExtend.MapFile("版本信息.ini")); + return Ini.GetValue("Version", "Id"); + } + + /// + /// 版本号 + /// + /// + public static string GetVersionName() + { + Ini = new IniHelper(HttpExtend.MapFile("版本信息.ini")); + return DateTime.Parse(Ini.GetValue("Version", "CreateTime")).ToString("yyyy.MM.dd.HHmm"); + } + + /// + /// 版本信息 + /// + public class FileVersion + { + public int Id { get; set; } + public string Name { get; set; } + public bool IsEnable { get; set; } + + private string _Message; + /// + /// 更新的内容 + /// + public string Message + { + get { return ShowMessage(_Message); } + set { _Message = value; } + } + public DateTime CreateTime { get; set; } + + private string ShowMessage(string Message) + { + try + { + var strb = new StringBuilder(); + var UpdateContent = Message.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); + + strb.AppendLine($"{Name} - {CreateTime.ToString("yyyy.MM.dd.HHmmss")}"); + strb.AppendLine(); + for (int i = 0; i < UpdateContent.Length; i++) + { + strb.AppendLine(UpdateContent[i]); + } + } + catch (Exception ex) + { } + return Message; + } + } + + } +} diff --git a/类库/Api.Framework/Tools/Util.cs b/类库/Api.Framework/Tools/Util.cs new file mode 100644 index 0000000..4498405 --- /dev/null +++ b/类库/Api.Framework/Tools/Util.cs @@ -0,0 +1,2129 @@ +using Api.Framework.Model; +using Api.Framework.SDK; +using CsharpHttpHelper; +using Api.Framework.Tools; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Configuration; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.ExceptionServices; +using System.Runtime.InteropServices; +using System.Runtime.Serialization.Formatters.Binary; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using System.Web.Script.Serialization; +using System.Windows.Forms; +using ThoughtWorks.QRCode.Codec; +using ThoughtWorks.QRCode.Codec.Data; +using ZXing; +using static System.Net.Mime.MediaTypeNames; +using Image = System.Drawing.Image; +using System.Text.RegularExpressions; +using System.Net; +using System.Net.Mail; +using System.Net.Mime; +using Chat.Framework; +using System.Web.Caching; +using System.Web; +using System.Net.Http; +using Api.Framework.Utils; +using Newtonsoft.Json; +using System.ComponentModel; +using Newtonsoft.Json.Linq; + +namespace Api.Framework.Tools +{ + public class Util + { + + /// + /// 将数据转成对象 + /// + /// + /// + /// + public static T ToObj(JToken data) + { + try + { + if (data == null) + return default(T); + //return JsonConvert.DeserializeObject(JsonConvert.SerializeObject(data)); + return data.ToObject(); + } + catch (Exception ex) + { + throw ex; + } + return default(T); + } + + public static double ConvertDouble_FenToYuan(int value) + { + return (double)Math.Round((decimal.Parse(value.ToString()) / 100.0m), 2); + } + + + private static readonly object obj_Lock = new object(); + /// + /// 检测微信域名是否正常 + /// + /// + /// + public static async void CheckUrlDomain(string url, string noticeName = "") + { + if (ApiClient.Setting.SystemConfig.CheckUrlSwitch == Enums.SwitchType.关闭) return; + lock (obj_Lock) + { + try + { + if (string.IsNullOrWhiteSpace(url)) throw new Exception("url不能为空"); + + var wx = ChatClient.WXClient.Values.FirstOrDefault(f => f.Status == Chat.Framework.WXSdk.WxStatus.在线 && f.WeixinType == Chat.Framework.WXSdk.Implement.WeixinType.Hook微信); + if (wx != null) + { + if (!wx.CheckUrl(url)) + { + Uri uri = new Uri(url); + var host = uri.Host; + if (!GetCache(host.ToLower())) + { + SetCache(host.ToLower(), 600); + var strb = new StringBuilder(); + strb.AppendLine($@"域名监控通知: +中间页域名:{host},已被微信拦截,请及时更换"); + ApiClient.SendNoticeMessage(strb.ToString(), noticeName); + } + } + } + } + catch (Exception ex) + { } + } + } + + /// + /// 获取小程序xml文本 + /// + /// + /// + /// + public static string GetMiNiAppXml(object data, ChatType chatType) + { + var xml = string.Empty; + try + { + if (data != null) + { + if (data is Dictionary) + { + var dic = data as Dictionary; + if (dic.ContainsKey("appId") && dic.ContainsKey("appName") && dic.ContainsKey("target")) + { + var appid = dic["appId"].ToString().Replace("\"", ""); + var appname = dic["appName"].ToString().Replace("\"", ""); + var target = dic["target"].ToString().Replace("\"", ""); + + switch (chatType) + { + case ChatType.微信: + { + #region 新 + xml = $@" + <![CDATA[兑换成功,请注意查收]]> + + + view + 33 + 0 + + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + 308182020100047b30790201000204241402cf02032f53a102046aed7b7602046140580404546175706170706d73675f313964303238376430373335333963355f313633313630363738383235345f3737303538355f30663530663632362d316535632d343235352d613136352d6530316361333464353736300204011800030201000400 + 308ac8283026da65a796d699318d218c + 12820 + 576 + 720 + 5951804402693f81eb27633f194a6a68 + 5951804402693f81eb27633f194a6a68 + 1 + + 0 + + + 3 + https://fd-1300509451.cos.ap-chengdu.myqcloud.com/fm1.jpeg + + + + + 0 + + + + 0 + + + + 0 + null + null + + + 0 + null + null + null + + 0 + + + + + + + + + 308ac8283026da65a796d699318d218c + + + + + 2 + 0 + 0 + + 720 + 576 + 0 + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + 0 + + + + + + + + + + + + + 0 + + + + 0 + + + "; + + #region xxx + // return $@" + // <![CDATA[兑换成功,请注意查收]] + // + // + // view + // 33 + // 0 + // + // + // + // 0 + // + // + // 0 + // + // + // 0 + // + // + // + // + // + // + // + // + // + // + // + // + // 307f020100047830760201000204d6c63d1d02032f53a10204f0ed7b760204610f5d5304516175706170706d73675f323538663230643164323734356236655f313632383339363838333530365f3533335f61613163303962362d303134322d343032332d383862662d3935373136313536383462380204011800030201000400 + // 308ac8283026da65a796d699318d218c + // 12820 + // 576 + // 720 + // 0487c4db437f564f94d76fc32ca01cd5 + // 0487c4db437f564f94d76fc32ca01cd5 + // 1 + // + // 0 + // + // + // 3 + // https://fd-1300509451.cos.ap-chengdu.myqcloud.com/fm1.jpeg + // + // + // + // + // 0 + // + // + // + // 0 + // + // + // + // 0 + // null + // null + // + // + // 0 + // null + // null + // null + // + // 0 + // + // + // + // + // + // + // + // + // 308ac8283026da65a796d699318d218c + // + // + // + // + // 2 + // 0 + // 0 + // + // 720 + // 576 + // 0 + // + // + // + // + // 0 + // + // + // + // + // + // + // 0 + // + // + // + // + // + // 0 + // + // + // + // + // + // + // + // + // + // + // + // + // 0 + // + // + // + // 0 + // + // + //"; + #endregion + + #endregion + + return xml; + } + break; + case ChatType.企业微信: + { + + } + break; + case ChatType.微信公众号: + case ChatType.未知来源: + case ChatType.QQ: + break; + default: + break; + } + } + } + } + } + catch (Exception ex) + { + } + finally + { + LogHelper.GetSingleObj().Debug("", $@"获取微信小程序文本:{JsonConvert.SerializeObject(data)} +平台:{chatType.ToString()} +xml:字符长度:{(string.IsNullOrWhiteSpace(xml) ? "0" : $"{xml.Length}")}"); + } + return xml; + } + + + /// + /// 缓存是否存在 + /// + /// + /// + /// + /// + public static bool GetCache(string text) + { + try + { + var MD5 = GetMD5($"{text}"); + Cache cache = HttpRuntime.Cache; + object item = cache[MD5]; + return item != null ? true : false; + } + catch (Exception) + { + } + return false; + } + + /// + /// 设置缓存(辅助输入) + /// + /// + /// + /// + /// + public static bool SetCache(string text, int seconds = 60) + { + try + { + var MD5 = GetMD5($"{text}"); + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[MD5]; + if (item == null) + cache.Insert(MD5, 1, null, DateTime.Now.AddSeconds(seconds), System.Web.Caching.Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + + /// + /// 设置缓存(辅助输入) + /// + /// + /// + /// + /// + public static void RemoveCache(string text) + { + try + { + var MD5 = GetMD5($"{text}"); + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[MD5]; + if (item != null) + cache.Remove(MD5); + } + catch (Exception ex) + { } + } + + /// + /// MD5字符串加密 + /// + /// + /// 加密后字符串 + public static string GetMD5(string txt) + { + using (MD5 mi = MD5.Create()) + { + byte[] buffer = Encoding.Default.GetBytes(txt); + //开始加密 + byte[] newBuffer = mi.ComputeHash(buffer); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < newBuffer.Length; i++) + { + sb.Append(newBuffer[i].ToString("x2")); + } + return sb.ToString(); + } + } + + #region 读取配置文件 + + public static Dictionary ReadConfig(string name, bool refresh = false) + { + return Util.Read>(name); + } + #endregion + + #region MyRegion + [DllImport("PsyQrDcd.dll"), HandleProcessCorruptedStateExceptions] + private static extern int DecodePictureFile(string filename); + + [DllImport("PsyQrDcd.dll"), HandleProcessCorruptedStateExceptions] + private static extern int GetDecodeData(int x, ref StringBuilder sb); + + + public static object _DecodePictureFile = new object(); + + private static Dictionary DecodeQRCodeCache = new Dictionary(); + + /// + /// 二维码解析类型 + /// + public enum DecodeQRCodeType + { + 全部 = 0, + Zxing = 1, + ThoughtWorks = 2, + Caoliao = 3, + } + + /// + /// 解密二维码 + /// + /// 文件路径 + /// + [HandleProcessCorruptedStateExceptions] + public static string DecodeQRCode(string filename, DecodeQRCodeType type = DecodeQRCodeType.Zxing) + { + if (!File.Exists(filename)) return string.Empty; + if (DecodeQRCodeCache.ContainsKey(filename)) return DecodeQRCodeCache[filename]; + if (type == DecodeQRCodeType.Zxing || type == DecodeQRCodeType.全部) + { + //Zxing 解析二维码 + try + { + using (var image = new Bitmap(filename)) + { + BarcodeReader reader = new BarcodeReader(); + System.Diagnostics.Stopwatch watch = new Stopwatch(); + watch.Start(); + Result result = reader.Decode(image); //通过reader解码 + watch.Stop(); + TimeSpan timeSpan = watch.Elapsed; + if (!string.IsNullOrEmpty(result.Text)) + { + EventClient.OnEvent(null, $"Zxing 解析出二维码:" + result.Text); + DecodeQRCodeCache[filename] = result.Text; + return result.Text; + } + } + } + catch (Exception) { } + } + + if (type == DecodeQRCodeType.ThoughtWorks || type == DecodeQRCodeType.全部) + { + //ThoughtWorks 解析二维码 + try + { + using (var image = new Bitmap(filename)) + { + string decodedString = new QRCodeDecoder().decode(new QRCodeBitmapImage(new Bitmap(filename)), Encoding.UTF8); + if (!string.IsNullOrEmpty(decodedString)) + { + EventClient.OnEvent(null, $"ThoughtWorks 解析出二维码:" + decodedString); + DecodeQRCodeCache[filename] = decodedString; + return decodedString; + } + } + } + catch (Exception) + { } + } + + if (type == DecodeQRCodeType.Caoliao || type == DecodeQRCodeType.全部) + { + //草料解析 + try + { + HttpHelper http = new HttpHelper(); + string _name = filename.Substring(filename.LastIndexOf("\\") + 1); //文件名 + StringBuilder sb = new StringBuilder("------WebKitFormBoundaryti0AVKw1aHIUR6yX\r\n"); + sb.Append($"Content-Disposition: form-data; name=\"Filedata\"; filename=\"{_name}.jpg\"\r\n"); + byte[] data = File.ReadAllBytes(filename); + var image = ReturnPhoto(data); + string content_type = GetMimeType(image); + sb.Append($"Content-Type: {content_type}\r\n"); + sb.Append("\r\n"); + var str = sb.ToString(); + byte[] Header = Encoding.ASCII.GetBytes(sb.ToString()); + byte[] Body = data; + byte[] Foot = Encoding.ASCII.GetBytes("\r\n------WebKitFormBoundaryti0AVKw1aHIUR6yX--\r\n"); + var SendData = ComposeArrays(ComposeArrays(Header, Body), Foot); + var item = http.GetItem("https://upload.api.cli.im/upload.php?kid=cliim"); + item.Header["Origin"] = "https://cli.im"; + item.ContentType = "multipart/form-data; boundary=----WebKitFormBoundaryti0AVKw1aHIUR6yX"; + item.Method = "post"; + item.PostdataByte = SendData; + item.PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte; + item.Referer = "https://cli.im/deqr"; + var html = http.GetHtml(item).Html; + var json = HttpExtend.JsonToDictionary(html); + if (json["status"].ToString() == "1") + { + var json_data = json["data"] as Dictionary; + var upload_url = json_data["path"].ToString(); + html = http.GetHtml("https://cli.im/apis/up/deqrimg", "", "img=" + HttpHelper.URLEncode(upload_url)).Html; + json = HttpExtend.JsonToDictionary(html); + if (json["status"].ToString() == "1" && json.ContainsKey("info")) + { + json_data = json["info"] as Dictionary; + if (json_data.ContainsKey("data")) + { + var list_url = json_data["data"] as ArrayList; + if (list_url.Count > 0) + { + var url = list_url[0].ToString(); + EventClient.OnEvent(null, $"Api 解析出二维码:" + url); + DecodeQRCodeCache[filename] = url; + return url; + } + } + } + } + } + catch (Exception) + { } + } + DecodeQRCodeCache[filename] = string.Empty; + return string.Empty; + } + public static System.Drawing.Image ReturnPhoto(byte[] streamByte) + { + System.IO.MemoryStream ms = new System.IO.MemoryStream(streamByte); + System.Drawing.Image img = System.Drawing.Image.FromStream(ms); + return img; + } + + public static byte[] ComposeArrays(byte[] Array1, byte[] Array2) + { + byte[] Temp = new byte[Array1.Length + Array2.Length]; + Array1.CopyTo(Temp, 0); + Array2.CopyTo(Temp, Array1.Length); + return Temp; + } + + /// + /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// + /// + /// + public static Bitmap ReadImageFile(string path) + { + //OpenRead + Image result = null; + try + { + using (FileStream fs = File.OpenRead(path)) + { + int filelength = 0; + filelength = (int)fs.Length; //获得文件长度 + Byte[] image = new Byte[filelength]; //建立一个字节数组 + fs.Read(image, 0, filelength); //按字节流读取 + result = Image.FromStream(fs); + return new Bitmap(result); + } + } + catch (Exception) + { } + return null; + } + + public static string GetMimeType(string filename) + { + var mime = string.Empty; + var img = ReadImageFile(filename); + if (img != null) + { + mime = GetMimeType(img); + img.Dispose(); + } + return mime; + } + + public static string GetMimeType(Image image) + { + var ImageCodec = ImageCodecInfo.GetImageDecoders(); + foreach (var item in ImageCodec) + { + if (item.FormatID == image.RawFormat.Guid) + return item.MimeType; + } + return "image/unknown"; + } + + /// + /// 解析二维码 + /// + /// + /// + public static string DecodeQRCode(Bitmap bitmap) + { + try + { + if (bitmap == null) return string.Empty; + var file = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + bitmap.Save(file, System.Drawing.Imaging.ImageFormat.Jpeg); + return DecodeQRCode(file); + } + catch (Exception) + { } + return string.Empty; + } + #endregion + + #region AppConfig + // 选择文件: + + public static void AppConfig_AddItem(string keyName, string keyValue) + { + //添加配置文件的项,键为keyName,值为keyValue + Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + config.AppSettings.Settings.Add(keyName, keyValue); + config.Save(ConfigurationSaveMode.Modified); + ConfigurationManager.RefreshSection("appSettings"); + } + + public static bool AppConfig_ExistItem(string keyName) + { + //判断配置文件中是否存在键为keyName的项 + foreach (string key in ConfigurationManager.AppSettings) + { + if (key == keyName) + { + //存在 + return true; + } + } + return false; + } + public static string AppConfig_GetValue(string keyName) + { + //返回配置文件中键为keyName的项的值 + return ConfigurationManager.AppSettings[keyName]; + } + + public static void AppConfig_RemoveItem(string keyName) + { + //删除配置文件键为keyName的项 + Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + config.AppSettings.Settings.Remove(keyName); + config.Save(ConfigurationSaveMode.Modified); + ConfigurationManager.RefreshSection("appSettings"); + } + + public static bool AppConfig_ModifyItem(string keyName, string newKeyValue) + { + //修改配置文件中键为keyName的项的值 + try + { + Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + config.AppSettings.Settings[keyName].Value = newKeyValue; + config.AppSettings.SectionInformation.ForceSave = true; + config.Save(ConfigurationSaveMode.Modified); + ConfigurationManager.RefreshSection("appSettings"); + return true; + } + catch (Exception ex) + { + return false; + } + } + + #endregion + + /// + /// 生成指定位数的随机数 + /// + /// + /// + public static string GetRandomString(int iLength) + { + try + { + string buffer = "0123456789";// 随机字符中也可以为汉字(任何) + StringBuilder sb = new StringBuilder(); + Random r = new Random(); + int range = buffer.Length; + for (int i = 0; i < iLength; i++) + { + sb.Append(buffer.Substring(r.Next(range), 1)); + } + return sb.ToString(); + } + catch (Exception) + { } + return string.Empty; + } + + /// + /// 添加水印 + /// + /// 原图片地址 + /// 水印图片地址 + /// resMsg[0] 成功,失败 + public static byte[] AddWaterMark(byte[] data, string text) + { + try + { + var image = BytesToBitmap(data); + + Bitmap bitmap = new Bitmap(image, image.Width, image.Height); + + Graphics g = Graphics.FromImage(bitmap); + + float fontSize = 12.0f; //字体大小 + + float textWidth = text.Length * fontSize; //文本的长度 + + //下面定义一个矩形区域,以后在这个矩形里画上白底黑字 + + float rectX = 0; + + float rectY = 0; + + float rectWidth = text.Length * (fontSize + 8); + + float rectHeight = fontSize + 8; + + //声明矩形域 + + RectangleF textArea = new RectangleF(rectX, rectY, rectWidth, rectHeight); + + Font font = new Font("宋体", fontSize); //定义字体 + + Brush whiteBrush = new SolidBrush(Color.White); //白笔刷,画文字用 + + Brush blackBrush = new SolidBrush(Color.Black); //黑笔刷,画背景用 + + g.FillRectangle(blackBrush, rectX, rectY, rectWidth, rectHeight); + + g.DrawString(text, font, whiteBrush, textArea); + + MemoryStream ms = new MemoryStream(); + + //保存为Jpg类型 + + bitmap.Save(ms, ImageFormat.Jpeg); + + Image h_hovercImg = Image.FromStream(ms); + + g.Dispose(); + + bitmap.Dispose(); + + var temp_data = new byte[ms.Length]; + ms.Write(temp_data, 0, temp_data.Length); + ms.Close(); + return temp_data; + } + catch (Exception) + { + } + return data; + } + + /// + /// 给图片添加文字水印 + /// + /// 图片 + /// 文字 + /// 文本位置中心点坐标 + /// 字体 + /// 字体颜色 + /// 旋转角度(顺时针) + /// + public static Image AddText2Image(Image img, string text, Point p, Font font, Color fontColor, int angle) + { + try + { + using (var g = Graphics.FromImage(img)) + using (var brush = new SolidBrush(fontColor)) + { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + var sizeF = g.MeasureString(text, font); + g.ResetTransform(); + g.TranslateTransform(p.X, p.Y); + g.RotateTransform(angle); + g.DrawString(text, font, brush, new PointF(-sizeF.Width / 2, -sizeF.Height / 2)); + } + return img; + } + catch (Exception) + { + } + return null; + } + public static byte[] imageToByteArray(System.Drawing.Image imageIn) + { + MemoryStream ms = new MemoryStream(); + imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); + return ms.ToArray(); + } + + public static Image byteArrayToImage(byte[] byteArrayIn) + { + MemoryStream ms = new MemoryStream(byteArrayIn); + Image returnImage = Image.FromStream(ms); + return returnImage; + } + public static void SendEmail(string host, int port, string username, string userpass, bool ssl, string tousername, string title, string content, bool begin = false, string file = "") + { + if (string.IsNullOrWhiteSpace(username)) throw new Exception("请填写邮箱地址"); + System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(); + client.Host = host;//邮件服务器 + client.Port = port;//smtp主机上的端口号,默认是25. + client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;//邮件发送方式:通过网络发送到SMTP服务器 + client.Credentials = new System.Net.NetworkCredential(username, userpass);//凭证,发件人登录邮箱的用户名和密码 + client.Timeout = 5000; + //电子邮件信息类 + System.Net.Mail.MailAddress fromAddress = new System.Net.Mail.MailAddress(username, username);//发件人Email,在邮箱是这样显示的,[发件人:小明;] + System.Net.Mail.MailAddress toAddress = new System.Net.Mail.MailAddress(tousername, username);//收件人Email,在邮箱是这样显示的, [收件人:小红<43327681@163.com>;] + System.Net.Mail.MailMessage mailMessage = new System.Net.Mail.MailMessage(fromAddress, toAddress);//创建一个电子邮件类 + mailMessage.Subject = title; + // string filePath = Server.MapPath("/index.html");//邮件的内容可以是一个html文本. + //System.IO.StreamReader read = new System.IO.StreamReader(filePath, System.Text.Encoding.GetEncoding("GB2312")); + //string mailBody = read.ReadToEnd(); + //read.Close(); + mailMessage.Body = content;//可为html格式文本 + //mailMessage.Body = "邮件的内容";//可为html格式文本 + mailMessage.SubjectEncoding = System.Text.Encoding.UTF8;//邮件主题编码 + mailMessage.BodyEncoding = System.Text.Encoding.UTF8;//邮件内容编码 + mailMessage.IsBodyHtml = true;//邮件内容是否为html格式 + + mailMessage.Priority = System.Net.Mail.MailPriority.Normal;//邮件的优先级,有三个值:高(在邮件主题前有一个红色感叹号,表示紧急),低(在邮件主题前有一个蓝色向下箭头,表示缓慢),正常(无显示). + + #region + //添加附件 + if (!string.IsNullOrWhiteSpace(file)) + { + //string extName = Path.GetExtension(file).ToLower(); + ////这里仅举例说明如何判断附件类型 + //if (extName == ".rar" || extName == ".zip") + // attachment = new Attachment(file, MediaTypeNames.Application.Zip); + //else + // attachment = new Attachment(file, MediaTypeNames.Application.Octet); + //ContentDisposition cd = attachment.ContentDisposition; + //cd.CreationDate = File.GetCreationTime(file); + //cd.ModificationDate = File.GetLastWriteTime(file); + //cd.ReadDate = File.GetLastAccessTime(file); + //mailMessage.Attachments.Add(attachment); + + + //SUpFile = Server.MapPath("~/发邮件/Upfile/" + SUpFile);//获得附件在本地地址 + //将文件进行转换成Attachments + Attachment data = new Attachment(file, MediaTypeNames.Application.Octet); + // Add time stamp information for the file. + ContentDisposition disposition = data.ContentDisposition; + disposition.CreationDate = System.IO.File.GetCreationTime(file); + disposition.ModificationDate = System.IO.File.GetLastWriteTime(file); + disposition.ReadDate = System.IO.File.GetLastAccessTime(file); + + mailMessage.Attachments.Add(data); + System.Net.Mime.ContentType ctype = new System.Net.Mime.ContentType(); + } + #endregion + + client.EnableSsl = ssl; + if (begin) + client.SendAsync(mailMessage, "ojb"); + else + client.Send(mailMessage);//发送邮件 + + } + const string Seq = "s9LFkgy5RovixI1aOf8UhdY3r4DMplQZJXPqebE0WSjBn7wVzmN2Gc6THCAKut"; + /// + /// 10进制转换为62进制 + /// + /// + /// + public static string InvitationCode(long id) + { + if (id < 62) + { + return Seq[(int)id].ToString(); + } + int y = (int)(id % 62); + long x = (long)(id / 62); + + return InvitationCode(x) + Seq[y]; + } + + public static long InvitationCode(string Num) + { + long v = 0; + int Len = Num.Length; + for (int i = Len - 1; i >= 0; i--) + { + int t = Seq.IndexOf(Num[i]); + double s = (Len - i) - 1; + long m = (long)(Math.Pow(62, s) * t); + v += m; + } + return v; + } + + public static string HexToStr(byte[] bytes) + { + string returnStr = ""; + if (bytes != null) + { + for (int i = 0; i < bytes.Length; i++) + { + returnStr += bytes[i].ToString("X2"); + } + } + return returnStr; + } + + public static byte[] StrToHex(string hexString) + { + hexString = hexString.Replace(" ", ""); + if ((hexString.Length % 2) != 0) + { + hexString = hexString + " "; + } + byte[] buffer = new byte[hexString.Length / 2]; + for (int i = 0; i < buffer.Length; i++) + { + buffer[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 0x10); + } + return buffer; + } + + public static string GetMd5_32byte(string str) + { + string pwd = string.Empty; + + //实例化一个md5对像 + MD5 md5 = MD5.Create(); + + // 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择  + byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); + + // 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得 + for (int i = 0; i < s.Length; i++) + { + // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写(X)则格式后的字符是大写字符 + pwd = pwd + s[i].ToString("X"); + } + + return pwd; + } + public static string GetFileMd5Code(string filePath) + { + StringBuilder builder = new StringBuilder(); + using (var md5 = new MD5CryptoServiceProvider()) + { + File.Copy(filePath, filePath + ".bak");//复制一份,防止占用 + using (FileStream fs = new FileStream(filePath + ".bak", FileMode.Open)) + { + byte[] bt = md5.ComputeHash(fs); + for (int i = 0; i < bt.Length; i++) + { + builder.Append(bt[i].ToString("x2")); + } + } + File.Delete(filePath + ".bak");//删除复制的文件,这里没处理异常等.... + } + return builder.ToString(); + } + public static string TimeDiffer(DateTime time) + { + var c = DateTime.Now - time; + return string.Format("{0}天{1}小时{2}分", c.Days, c.Hours, c.Minutes); + } + public static T ConvertEnum(string value) + { + var v = Enum.Parse(typeof(T), value); + return (T)v; + } + public static T ConvertEnum(int value) + { + return (T)Enum.Parse(typeof(T), value.ToString()); + } + public static T ConvertEnum(ushort value) + { + return (T)Enum.Parse(typeof(T), value.ToString()); + } + /// + /// 读取配置文件 + /// + /// + public static T Read(string name = "") + { + var obj = System.Activator.CreateInstance(); + ConfigAttribute _attribute = obj.GetType().GetCustomAttributes().FirstOrDefault(f => typeof(ConfigAttribute) == f.GetType()) as ConfigAttribute; + if (_attribute == null) _attribute = new ConfigAttribute(); + + //配置文件名 + string _name = name; + if (string.IsNullOrEmpty(_name)) + { + if (string.IsNullOrEmpty(_attribute.Name)) _name = obj.GetType().ToString(); else _name = _attribute.Name; + + } + string text = string.Empty; + if (_attribute.IsSaveDB) + { + var session = ApiClient.GetSession(); + var _db_item = session.FindDictionaryItem(_name); + if (_db_item != null) + { + text = _db_item.dicvalue; + } + else return obj; + } + else + { + + string fileName = MapFile(_name + ".config", "Config"); + if (!File.Exists(fileName)) return obj; + text = File.ReadAllText(fileName, Encoding.UTF8); + } + + byte[] bytes = HexToByte(text); + if (_attribute.IsEncryption) + { + bytes = TeaEncryption.Decrypt(bytes, _attribute.EncKey); + } + string json = Encoding.UTF8.GetString(bytes); + + try + { + return ToDeserialize(json); + } + catch (Exception) + { + try + { + if (_name == "系统.其他设置") + { + json = "{\"Plugins\":[\"MessageSupervises.Class1\",\"PointManage.Class1\",\"TBRebate.Class1\",\"JDRebate.Class1\",\"PDDRebate.Class1\",\"AutoAnswer.Class1\",\"PointConvert.MyPlugin\",\"WPHRebate.Class1\",\"GroupSend2019.MyPlugin\",\"InviteGroup2020.MyPlugin\",\"UserFission.Class1\",\"ProductClient.Class1\",\"DYRebate.Class1\",\"SNRebate.Class1\"]}"; + } + return JsonConvert.DeserializeObject(json); + } + catch (Exception) + { } + } + return default(T); + } + + /// + /// 将图片转换为字节数组 + /// + /// 完整的图片路径 + /// + public static byte[] GetImageByte(string imagePath) + { + + FileStream files = new FileStream(imagePath, FileMode.Open); + + byte[] imgByte = new byte[files.Length]; + + files.Read(imgByte, 0, imgByte.Length); + + files.Close(); + + return imgByte; + + } + + /// + /// 将图片Bitmap类型转成字节数组 + /// + /// + /// + public static byte[] GetImageByte(System.Drawing.Bitmap bmp) + { + byte[] bytes = null; + try + { + MemoryStream ms = new MemoryStream(); + bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); + bytes = ms.GetBuffer(); //byte[] bytes= ms.ToArray(); 这两句都可以,至于区别么,下面有解释 + ms.Close(); + } + catch (Exception) + { } + return bytes; + } + + /// + /// 获取一个淘口令前后随机修饰符 + /// + /// 要随机的修饰符 + /// 分隔符,默认'|' + /// 返回随机的一个修饰符或传入的str值 + public static string FindTKlRandomModifier(string str, char separator = '|') + { + try + { + var modifiers = str.Split(separator); + if (modifiers != null && modifiers.Length != 0) + { + Random random = new Random(); + return modifiers[random.Next(0, modifiers.Length)]; + } + } + catch (Exception) + { } + return str; + } + + private readonly static object save_config_lock = new object(); + + /// + /// 保存配置文件 + /// + /// + public static void Save(Object obj, string name = "") + { + lock (save_config_lock) + { + try + { + var bytes = Encoding.UTF8.GetBytes(ToSerializer(obj)); + var _class = obj.GetType(); + var _attribute = _class.GetCustomAttributes().FirstOrDefault() as ConfigAttribute; + if (_attribute == null) _attribute = new ConfigAttribute(); + //配置文件名 + string _name = name; + if (string.IsNullOrEmpty(_name)) + { + if (string.IsNullOrEmpty(_attribute.Name)) _name = obj.GetType().ToString(); else _name = _attribute.Name; + } + + var _properties = _class.GetProperties(); + foreach (var property in _properties) + { + var attributes = property.GetCustomAttributes(); + } + if (_attribute.IsEncryption) + { + bytes = TeaEncryption.Decrypt(bytes, _attribute.EncKey); + } + var hex = ByteToHex(bytes); + if (_attribute.IsSaveDB) + { + var session = ApiClient.GetSession(); + var _db_item = session.FindDictionaryItem(_name); + if (_db_item == null) _db_item = new fl_dictionary_item() { dickey = _name }; + _db_item.dicvalue = hex; + session.SaveOrUpdate(_db_item); + session.FindDictionaryItem(_name, true); + } + else + { + var fileName = MapFile(_name + ".config", "Config"); + File.WriteAllText(fileName, hex, Encoding.UTF8); + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"【配置文件】保存失败,{ex.Message}"); + } + } + } + + public static string MapFile(string file, string path = "") + { + return Path.Combine(MapPath(path, true), file); + } + + public static string MapPath(string path = "", bool CreateDirectory = true) + { + if (string.IsNullOrWhiteSpace(path)) + { + return System.Windows.Forms.Application.StartupPath.ToString() + "\\"; + } + path = Path.Combine(System.Windows.Forms.Application.StartupPath.ToString() + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + return path; + } + + public static byte[] BitmapToBytes(Bitmap Bitmap) + { + MemoryStream ms = null; + try + { + ms = new MemoryStream(); + Bitmap.Save(ms, Bitmap.RawFormat); + byte[] byteImage = new Byte[ms.Length]; + byteImage = ms.ToArray(); + return byteImage; + } + catch (ArgumentNullException ex) + { } + finally + { + ms.Close(); + } + return null; + } + + public static string GetMD5Hash(byte[] bytedata) + { + try + { + System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); + byte[] retVal = md5.ComputeHash(bytedata); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < retVal.Length; i++) + { + sb.Append(retVal[i].ToString("x2")); + } + return sb.ToString(); + } + catch (Exception ex) + { + throw new Exception("GetMD5Hash() fail,error:" + ex.Message); + } + } + + public static Bitmap BytesToBitmap(byte[] Bytes) + { + MemoryStream stream = null; + try + { + stream = new MemoryStream(Bytes); + return new Bitmap(stream); + } + catch (ArgumentNullException ex) + { + throw ex; + } + catch (ArgumentException ex) + { + throw ex; + } + finally + { + stream.Close(); + } + } + /// + /// 图像灰度化 + /// + public static Bitmap ToGrey(System.Drawing.Image image) + { + Bitmap img = new Bitmap(image); + for (int i = 0; i < img.Width; i++) + { + for (int j = 0; j < img.Height; j++) + { + Color pixelColor = img.GetPixel(i, j); + int grey = (int)(0.299 * pixelColor.R + 0.587 * pixelColor.G + 0.114 * pixelColor.B); + Color newColor = Color.FromArgb(grey, grey, grey, grey); + img.SetPixel(i, j, newColor); + } + } + return img; + } + + public static T ToDeserialize(string content) + { + JavaScriptSerializer serializer = new JavaScriptSerializer(); + serializer.MaxJsonLength = Int32.MaxValue; + return serializer.Deserialize(content); + } + public static string ToSerializer(Object entity) + { + JavaScriptSerializer serializer = new JavaScriptSerializer(); + serializer.MaxJsonLength = Int32.MaxValue; + return serializer.Serialize(entity); + } + + private static string ByteToHex(byte[] bytes) + { + return BitConverter.ToString(bytes, 0).Replace("-", string.Empty).ToLower(); + } + + private static byte[] HexToByte(string hex) + { + var inputByteArray = new byte[hex.Length / 2]; + for (var x = 0; x < inputByteArray.Length; x++) + { + var i = Convert.ToInt32(hex.Substring(x * 2, 2), 16); + inputByteArray[x] = (byte)i; + } + return inputByteArray; + } + + /// + /// 下载文件 + /// + /// 下载文件地址 + /// 下载后的存放地址 + /// 用于显示的进度条 + public void DownloadFile(string url, string filename, System.Windows.Forms.ProgressBar prog = null) + { + float percent = 0; + try + { + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + if (prog != null) prog.Maximum = (int)totalBytes; + System.IO.Stream st = myrp.GetResponseStream(); + System.IO.Stream so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + totalDownloadedByte = osize + totalDownloadedByte; + System.Windows.Forms.Application.DoEvents(); + so.Write(by, 0, osize); + if (prog != null) prog.Value = (int)totalDownloadedByte; + osize = st.Read(by, 0, (int)by.Length); + + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + System.Windows.Forms.Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + so.Close(); + st.Close(); + } + catch (System.Exception) + { + throw; + } + } + + /// + /// 下载HTML + /// + /// 地址 + /// Post参数 + /// + public string DownloadHtml(string url, string data = "") + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url,//URL 必需项 + Method = string.IsNullOrEmpty(data) ? "GET" : "POST",//URL 可选项 默认为Get + Timeout = 5000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 5000,//写入Post数据超时时间 可选项默认为30000 + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = "",//字符串Cookie 可选项 + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统 可选项有默认值 + Accept = "text/html, application/xhtml+xml, */*",// 可选项有默认值 + ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + Referer = "",//来源URL 可选项 + Allowautoredirect = true,//是否根据301跳转 可选项 + + Postdata = data + }; + HttpResult result = http.GetHtml(item); + return result.Html; + + } + + /// + /// 读取数据 + /// + /// 文件路径 + public byte[] ReadFile(string path) + { + using (FileStream stream = new FileStream(path, FileMode.Open)) + { + using (MemoryStream memStream = new MemoryStream()) + { + int res; + byte[] b = new byte[stream.Length]; + while ((res = stream.Read(b, 0, b.Length)) > 0) + { + memStream.Write(b, 0, b.Length); + } + return b; + } + } + } + + #region Cookies 操作 + + /// + /// 设置IE + /// + /// hInternet + /// dwOption + /// lpBuffer + /// lpdwBufferLength + /// 处理结果 + [DllImport("wininet.dll", SetLastError = true)] + public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int lpdwBufferLength); + + [DllImport("shell32.dll")] + + static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); + + public static void ClearCookies() + { + try + { + InternetSetOption(IntPtr.Zero, 42, IntPtr.Zero, 0); + + //SuppressWininetBehavior(); + + ShellExecute(IntPtr.Zero, "open", "rundll32.exe", " InetCpl.cpl,ClearMyTracksByProcess 255", "", 0); + + CleanAll(); + } + catch (Exception ex) + { + //Console.WriteLine(ex.Message); + } + } + public static void CleanAll() + { + CleanCookie(); + CleanHistory(); + + CleanTempFiles(); + } + + + + [DllImport("wininet.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + private static extern bool InternetSetOption(int hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength); + public static unsafe void SuppressWininetBehavior() + { + try + { + int option = (int)3/* INTERNET_SUPPRESS_COOKIE_PERSIST*/; + int* optionPtr = &option; + bool success = InternetSetOption(0, 81/*INTERNET_OPTION_SUPPRESS_BEHAVIOR*/, new IntPtr(optionPtr), sizeof(int)); + + } + catch (Exception ex) { } + } + + /// + /// 拷贝oldlab的文件到newlab下面 + /// + /// lab文件所在目录(@"~\labs\oldlab") + /// 保存的目标目录(@"~\labs\newlab") + /// 返回:true-拷贝成功;false:拷贝失败 + public static bool CopyOldLabFilesToNewLab(string sourcePath, string savePath) + { + if (!Directory.Exists(savePath)) + { + Directory.CreateDirectory(savePath); + } + + #region //拷贝labs文件夹到savePath下 + try + { + string[] labDirs = Directory.GetDirectories(sourcePath);//目录 + string[] labFiles = Directory.GetFiles(sourcePath);//文件 + if (labFiles.Length > 0) + { + for (int i = 0; i < labFiles.Length; i++) + { + if (Path.GetExtension(labFiles[i]) != ".lab")//排除.lab文件 + { + File.Copy(sourcePath + "\\" + Path.GetFileName(labFiles[i]), savePath + "\\" + Path.GetFileName(labFiles[i]), true); + } + } + } + if (labDirs.Length > 0) + { + for (int j = 0; j < labDirs.Length; j++) + { + Directory.GetDirectories(sourcePath + "\\" + Path.GetFileName(labDirs[j])); + + //递归调用 + CopyOldLabFilesToNewLab(sourcePath + "\\" + Path.GetFileName(labDirs[j]), savePath + "\\" + Path.GetFileName(labDirs[j])); + } + } + } + catch (Exception) + { + return false; + } + #endregion + return true; + } + /// + /// 删除历史记录 Win7+ 需要管理员权限 + /// + public static void CleanHistory() + { + string[] theFiles = System.IO.Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.History), "*", System.IO.SearchOption.AllDirectories); + foreach (string s in theFiles) + FileDelete(s); + RunCmd("RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 1"); + } + /// + /// 调用CMD执行命令 + /// + /// + public static void RunCmd(string cmd) + { + System.Diagnostics.Process p = new System.Diagnostics.Process(); + p.StartInfo.FileName = "cmd.exe"; + // 关闭Shell的使用 + p.StartInfo.UseShellExecute = false; + // 重定向标准输入 + p.StartInfo.RedirectStandardInput = true; + // 重定向标准输出 + p.StartInfo.RedirectStandardOutput = true; + //重定向错误输出 + p.StartInfo.RedirectStandardError = true; + p.StartInfo.CreateNoWindow = true; + p.Start(); + p.StandardInput.WriteLine(cmd); + p.StandardInput.WriteLine("exit"); + } + + /// + /// 删除一个文件,System.IO.File.Delete()函数不可以删除只读文件,这个函数可以强行把只读文件删除。 + /// + /// 文件路径 + /// 成功为true + public static bool FileDelete(string path) + { + //first set the File\'s ReadOnly to 0 + //if EXP, restore its Attributes + System.IO.FileInfo file = new System.IO.FileInfo(path); + System.IO.FileAttributes att = 0; + bool attModified = false; + try + { + //### ATT_GETnSET + att = file.Attributes; + file.Attributes &= (~System.IO.FileAttributes.ReadOnly); + attModified = true; + file.Delete(); + + } + catch + { + if (attModified) + file.Attributes = att; + return false; + + } + return true; + } + /// + /// 删除文件夹 + /// + /// 文件夹路径 + public static void FolderClear(string path) + { + System.IO.DirectoryInfo diPath = new System.IO.DirectoryInfo(path); + foreach (System.IO.FileInfo fiCurrFile in diPath.GetFiles()) + { + FileDelete(fiCurrFile.FullName); + + } + foreach (System.IO.DirectoryInfo diSubFolder in diPath.GetDirectories()) + { + FolderClear(diSubFolder.FullName); // Call recursively for all subfolders + + } + + } + /// + /// 删除临时文件 Win7+ 需要管理员权限 + /// + public static void CleanTempFiles() + { + FolderClear(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache)); + RunCmd("RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 8"); + } + /// + /// 删除Cookie文件 Win7+ 需要管理员权限 + /// + public static void CleanCookie() + { + string[] theFiles = System.IO.Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Cookies), "*", System.IO.SearchOption.AllDirectories); + foreach (string s in theFiles) + FileDelete(s); + RunCmd("RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 2"); + } + #endregion + + /// + /// 是否为XML + /// + /// + /// + public static bool IsXML(string mess) + { + return mess.Contains("硬盘文件路径 + /// + public static byte[] ReadFileToByte(string fileName) + { + FileStream pFileStream = null; + byte[] pReadByte = new byte[0]; + try + { + pFileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read); + BinaryReader r = new BinaryReader(pFileStream); + r.BaseStream.Seek(0, SeekOrigin.Begin); //将文件指针设置到文件开 + pReadByte = r.ReadBytes((int)r.BaseStream.Length); + return pReadByte; + } + catch + { + return pReadByte; + } + finally + { + if (pFileStream != null) + pFileStream.Close(); + } + } + + /// + /// 写byte[]到fileName + /// + /// byte[] + /// 保存至硬盘路径 + /// + public static bool WriteByteToFile(byte[] pReadByte, string fileName) + { + FileStream pFileStream = null; + try + { + pFileStream = new FileStream(fileName, FileMode.OpenOrCreate); + pFileStream.Write(pReadByte, 0, pReadByte.Length); + } + catch + { + return false; + } + finally + { + if (pFileStream != null) + pFileStream.Close(); + } + return true; + } + + public static string RemoveEmoji(string text) + { + if (string.IsNullOrEmpty(text)) return string.Empty; + + if (!string.IsNullOrEmpty(System.Configuration.ConfigurationManager.AppSettings["RemoveWechatEmoji"]) && System.Configuration.ConfigurationManager.AppSettings["RemoveWechatEmoji"].ToUpper() == "FALSE") + { + return text; + } + text = Regex.Replace(text, @"\%uD.{3}", ""); + text = Regex.Replace(text, "[👃☺️☹️☠️✊✌️☝✋✍️♀️♂️]", ""); + foreach (var a in text) + { + byte[] bts = Encoding.UTF32.GetBytes(a.ToString()); + + if (bts[0].ToString() == "253" && bts[1].ToString() == "255") + { + text = text.Replace(a.ToString(), ""); + } + + } + return text; + + } + + public static bool ShowTgwz() + { + var session = ApiClient.GetSession(); + var count = session.Find("select * from fl_adzone_group").Count(); + if (count != 0) return true; + + var ShowTgwz = AppConfig_GetValue("ShowTgwz"); + return (ShowTgwz != null && ShowTgwz == "1"); + } + + /// + /// 文件转换成Base64字符串 + /// + /// 文件绝对路径 + /// + public static String FileToBase64(string fileName) + { + string strRet = ""; + + try + { + FileStream fs = new FileStream(fileName, FileMode.Open); + byte[] bt = new byte[fs.Length]; + fs.Read(bt, 0, bt.Length); + strRet = Convert.ToBase64String(bt); + fs.Close(); + } + catch (Exception ex) + { + strRet = null; + } + + return strRet; + } + + /// + /// Base64字符串转换成文件 + /// + /// base64字符串 + /// 保存文件的绝对路径 + /// + public static bool Base64ToFileAndSave(string strInput, string fileName) + { + bool bTrue = false; + try + { + byte[] buffer = Convert.FromBase64String(strInput); + FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate); + fs.Write(buffer, 0, buffer.Length); + fs.Close(); + bTrue = true; + } + catch (Exception ex) + { } + return bTrue; + } + + /// + /// 将图片控制在宽度为指定得像素 + /// + /// + /// + /// + public static Bitmap PercentImage(Image srcImage, int size = 200) + { + int newW = srcImage.Width < size ? srcImage.Width : size; + int newH = int.Parse(Math.Round(srcImage.Height * (double)newW / srcImage.Width).ToString()); + try + { + Bitmap b = new Bitmap(newW, newH); + Graphics g = Graphics.FromImage(b); + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default; + g.DrawImage(srcImage, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, srcImage.Width, srcImage.Height), GraphicsUnit.Pixel); + g.Dispose(); + return b; + } + catch (Exception) + { + return null; + } + } + + /// + /// 将图片按百分比压缩, + /// + /// + /// + /// flag取值1到100,越小压缩比越大 + /// + public static bool YaSuo(Image iSource, string outPath, int flag = 80) + { + ImageFormat tFormat = iSource.RawFormat; + EncoderParameters ep = new EncoderParameters(); + long[] qy = new long[1]; + qy[0] = flag; + EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy); + ep.Param[0] = eParam; + try + { + ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageDecoders(); + ImageCodecInfo jpegICIinfo = null; + for (int x = 0; x < arrayICI.Length; x++) + { + if (arrayICI[x].FormatDescription.Equals("JPEG")) + { + jpegICIinfo = arrayICI[x]; + break; + } + } + if (jpegICIinfo != null) + iSource.Save(outPath, jpegICIinfo, ep); + else + iSource.Save(outPath, tFormat); + return true; + } + catch + { + return false; + } + iSource.Dispose(); + } + + + /// + /// 日期转换成时间戳Timestamp + /// + /// + /// + public static long GetTimeSpan(DateTime time) + { + DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + + return (long)(time - dtStart).TotalMilliseconds; + } + + /// + /// 日期转换成时间戳Timestamp + /// + /// + /// + public static long GetTimeSpan(DateTime time, bool Milliseconds = false) + { + DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + + if (!Milliseconds) + return (long)(time - dtStart).TotalSeconds; + else + return (long)(time - dtStart).TotalMilliseconds; + } + + /// + /// 时间戳转时间 + /// + /// + /// + public static DateTime GetDateTime(long timeSpan) + { + DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + if (timeSpan.ToString().Length == 13) + return dtStart.AddMilliseconds(timeSpan); + else + return dtStart.AddSeconds(timeSpan); + } + + /// + /// 获取UUID + /// + /// + public static string GetUUID() + { + return System.Guid.NewGuid().ToString("N"); + } + + #region 加密 + //默认密钥向量 + private static byte[] Keys = { 0x42, 0x34, 0x56, 0x3C, 0x90, 0xAB, 0xAD, 0xEE }; + + //// + /// DES加密字符串 + /// + /// 待加密的字符串 + /// 加密密钥,要求为8位 + /// 加密成功返回加密后的字符串,失败返回源串 + public static string EncryptDES(string encryptString, string encryptKey = "2#~1*oW0") + { + try + { + byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8)); + byte[] rgbIV = Keys; + byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString); + DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider(); + MemoryStream mStream = new MemoryStream(); + CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write); + cStream.Write(inputByteArray, 0, inputByteArray.Length); + cStream.FlushFinalBlock(); + return Convert.ToBase64String(mStream.ToArray()); + } + catch + { + return encryptString; + } + } + + //// + /// DES解密字符串 + /// + /// 待解密的字符串 + /// 解密密钥,要求为8位,和加密密钥相同 + /// 解密成功返回解密后的字符串,失败返源串 + public static string DecryptDES(string decryptString, string decryptKey = "2#~1*oW0") + { + try + { + byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey); + byte[] rgbIV = Keys; + byte[] inputByteArray = Convert.FromBase64String(decryptString); + DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider(); + MemoryStream mStream = new MemoryStream(); + CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write); + cStream.Write(inputByteArray, 0, inputByteArray.Length); + cStream.FlushFinalBlock(); + return Encoding.UTF8.GetString(mStream.ToArray()); + } + catch + { + return decryptString; + } + } + #endregion + + } + + public class EnumHelper + { + /// + /// 将枚举转为集合 + /// + /// + /// + public static List EnumToList() + { + List list = new List(); + + foreach (var e in Enum.GetValues(typeof(T))) + { + EnumEntity m = new EnumEntity(); + object[] objArr = e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), true); + if (objArr != null && objArr.Length > 0) + { + DescriptionAttribute da = objArr[0] as DescriptionAttribute; + m.Desction = da.Description; + } + m.EnumValue = Convert.ToInt32(e); + m.EnumName = e.ToString(); + list.Add(m); + } + return list; + } + + /// + /// 获取枚举描述 + /// + /// + /// + /// + public static string GetEnumDesction(string EnumName) + { + foreach (var e in Enum.GetValues(typeof(T))) + { + if (e.ToString() != EnumName) + continue; + + EnumEntity m = new EnumEntity(); + object[] objArr = e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), true); + if (objArr != null && objArr.Length > 0) + { + DescriptionAttribute da = objArr[0] as DescriptionAttribute; + return da.Description; + } + } + return ""; + } + } + + /// + /// 枚举实体 + /// + public class EnumEntity + { + /// + /// 枚举的描述 + /// + public string Desction { set; get; } + + /// + /// 枚举名称 + /// + public string EnumName { set; get; } + + /// + /// 枚举对象的值 + /// + public int EnumValue { set; get; } + } +} diff --git a/类库/Api.Framework/Tools/VariateReplace.cs b/类库/Api.Framework/Tools/VariateReplace.cs new file mode 100644 index 0000000..02ec876 --- /dev/null +++ b/类库/Api.Framework/Tools/VariateReplace.cs @@ -0,0 +1,1221 @@ +using Api.Framework.Enums; +using Api.Framework.Model; +using Api.Framework.SDK; +using Api.Framework.Utils; +using CsharpHttpHelper; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using static Api.Framework.Cps.AlimamaApi; + +namespace Api.Framework.Tools +{ + /// + /// 变量替换 + /// + public class VariateReplace + { + private static List pddlist = new List() { "[拼多多待结算数量]", "[拼多多待结算金额]", "[拼多多冻结金额]", "[拼多多冻结订单数]", "[拼多多未收货金额]", "[拼多多未收货订单数]" }; + private static List tblist = new List() { "[淘宝待结算数量]", "[淘宝待结算金额]", "[淘宝冻结金额]", "[淘宝冻结订单数]", "[淘宝未收货金额]", "[淘宝未收货订单数]" }; + private static List jdlist = new List() { "[京东待结算数量]", "[京东待结算金额]", "[京东冻结金额]", "[京东冻结订单数]", "[京东未收货金额]", "[京东未收货订单数]" }; + private static List wphlist = new List() { "[唯品会待结算数量]", "[唯品会待结算金额]", "[唯品会冻结金额]", "[唯品会冻结订单数]", "[唯品会未收货金额]", "[唯品会未收货订单数]" }; + private static List dylist = new List() { "[抖音待结算数量]", "[抖音待结算金额]", "[抖音冻结金额]", "[抖音冻结订单数]", "[抖音未收货金额]", "[抖音未收货订单数]" }; + private static List snlist = new List() { "[苏宁待结算数量]", "[苏宁待结算金额]", "[苏宁冻结金额]", "[苏宁冻结订单数]", "[苏宁未收货金额]", "[苏宁未收货订单数]" }; + private static List kslist = new List() { "[快手待结算数量]", "[快手待结算金额]", "[快手冻结金额]", "[快手冻结订单数]", "[快手未收货金额]", "[快手未收货订单数]" }; + private static List list = new List() { "[待结算总数数量]", "[待结算总数金额]", "[待收货积分]", "[未收货积分]", "[未收货总金额]", "[待结算积分]", "[冻结总金额]", "[待收货订单数]", "[未收货订单数]", "[待结算订单数]", "[冻结订单数]" }; + + + StringBuilder mess = null; + private object lock_replace = new object(); + private void Replace(string key, string value) + { + if (mess != null) + { + lock (lock_replace) mess = mess.Replace(key, value); + } + } + + /// + /// 通用替换变量 + /// + /// 替换的内容 + /// 与变量有关联的对象 + /// + public string CommonReplace(string _mess, params object[] objs) + { + if (string.IsNullOrEmpty(_mess)) return string.Empty; + mess = new StringBuilder(_mess); + + try + { + Replace("[积分名称]", ApiClient.Setting.SystemConfig.PointName); + List actions = new List(); + + //List tasks = new List(); + foreach (var item in objs) + { + var type = item.GetType(); + if (type == typeof(fl_order_alimama)) + { + var order = item as fl_order_alimama; + + Replace("[订单号]", order.trade_parent_id); + Replace("[商品标题]", order.item_title); + Replace("[子订单号]", order.trade_id); + Replace("[付款金额]", order.alipay_total_price.ToString()); + Replace("[结算时间]", order.db_endtime.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[下级订单状态]", order.db_status.ToString()); + + #region [原始返利积分] [维权金额] 淘宝变量 + if (order != null) + { + var session = ApiClient.GetSession(); + if (_mess.Contains("[维权金额]")) + { + var refund_alimama = session.Find("select * from fl_order_refund_alimama where tbtradeparentid = @tbtradeparentid and tbtradeid = @tbtradeid", new { tbtradeparentid = order.trade_parent_id, tbtradeid = order.trade_id }).FirstOrDefault(); + if (refund_alimama != null) + Replace("[维权金额]", refund_alimama.refundfee.ToString()); + } + + if (_mess.Contains("[原始返利积分]")) + { + if (order.db_userid != 0) + { + var member = session.FindMemberInfoById(order.db_userid); + if (member != null) + { + ////获取历史的增加积分 + //var pointHists = session.Find("select * from fl_point_hist where uid = @uid and type = @pointType_name and message = @message", new { uid = order.db_userid, pointType_name = PointType.消费补贴, message = $"淘宝购买:{order.item_title} - ({order.trade_parent_id}) - ({order.trade_id})" }); + + //var histAddPoint = 0d; + ////if (pointHists != null && pointHists.Count == 1) + //if (pointHists != null && pointHists.Count != 0) + //{ + // pointHists = pointHists.OrderByDescending(f => f.crt_time).ToList(); + // histAddPoint = pointHists[0].point; + //} + //if (histAddPoint != 0) + //{ + // Replace("[原始返利积分]", histAddPoint.ToString("0.00")); + //} + //else + //{ + // var itempoint = session.FindItemPoint(member, (double)(Math.Round((decimal)order.alipay_total_price * (decimal)order.income_rate, 2, MidpointRounding.AwayFromZero)), order.item_num, CpsType.阿里妈妈);//重新计算阿里妈妈给的佣金 + // if (itempoint != null) + // { + // Replace("[原始返利积分]", itempoint.UserPoint.ToString()); + // } + //} + + var isReplace = false; + var rhPoint = session.FindRefundHistPoint(order.trade_parent_id, order.trade_id, CpsType.阿里妈妈); + if (rhPoint != null) + { + //获取积分信息 + var point = HttpHelper.JsonToObject(rhPoint.db_point) as ItemPoint; + if (point != null) + { + Replace("[原始返利积分]", point.UserPoint.ToString("0.00")); + isReplace = true; + } + } + + if (!isReplace) + { + #region 其他方案 + //获取历史的增加积分 + var pointHists = session.Find("select * from fl_point_hist where uid = @uid and type = @pointType_name and message = @message", new { uid = order.db_userid, pointType_name = PointType.消费补贴.ToString(), message = $"淘宝购买:{order.item_title} - ({order.trade_parent_id}) - ({order.trade_id})" }); + + var histAddPoint = 0d; + //if (pointHists != null && pointHists.Count == 1) + if (pointHists != null && pointHists.Count != 0) + { + pointHists = pointHists.OrderByDescending(f => f.crt_time).ToList(); + histAddPoint = pointHists[0].point; + } + if (histAddPoint != 0) + { + Replace("[原始返利积分]", histAddPoint.ToString("0.00")); + } + else + { + var itempoint = session.FindItemPoint(member, (double)(Math.Round((decimal)order.alipay_total_price * (decimal)order.income_rate, 2, MidpointRounding.AwayFromZero)), order.item_num, CpsType.阿里妈妈);//重新计算阿里妈妈给的佣金 + if (itempoint != null) + { + Replace("[原始返利积分]", itempoint.UserPoint.ToString()); + } + } + #endregion + } + } + } + Replace("[原始返利积分]", "0.00"); + } + } + #endregion + + } + if (type == typeof(fl_order_jingdong)) + { + var order = item as fl_order_jingdong; + Replace("[订单号]", order.orderId.ToString()); + Replace("[商品标题]", order.skuName); + Replace("[付款金额]", order.estimateCosPrice.ToString()); + Replace("[结算时间]", order.db_endtime.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[下级订单状态]", order.db_status.ToString()); + } + if (type == typeof(fl_order_pinduoduo)) + { + var order = item as fl_order_pinduoduo; + Replace("[订单号]", order.order_sn); + Replace("[商品标题]", order.goods_name); + Replace("[付款金额]", order.order_amount.ToString()); + Replace("[结算时间]", order.db_endtime.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[下级订单状态]", order.db_status.ToString()); + } + if (type == typeof(fl_order_douyin)) + { + var order = item as fl_order_douyin; + Replace("[订单号]", order.order_id); + Replace("[商品标题]", order.product_name); + Replace("[付款金额]", Util.ConvertDouble_FenToYuan(order.total_pay_amount).ToString("0.00")); + Replace("[结算时间]", order.db_endtime.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[下级订单状态]", order.db_status.ToString()); + } + if (type == typeof(fl_order_weipinhui)) + { + var order = item as fl_order_weipinhui; + Replace("[订单号]", order.orderSn); + Replace("[商品标题]", order.goodsName); + Replace("[付款金额]", order.goodsFinalPrice.ToString()); + Replace("[结算时间]", order.db_endtime.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[下级订单状态]", order.db_status.ToString()); + } + if (type == typeof(fl_order_douyin)) + { + var order = item as fl_order_douyin; + Replace("[订单号]", order.order_id); + Replace("[商品标题]", order.product_name); + Replace("[付款金额]", Util.ConvertDouble_FenToYuan(order.total_pay_amount).ToString()); + Replace("[结算时间]", order.db_endtime.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[下级订单状态]", order.db_status.ToString()); + } + if (type == typeof(fl_order_suning)) + { + var order = item as fl_order_suning; + Replace("[订单号]", order.orderCode); + Replace("[商品标题]", order.productName); + Replace("[付款金额]", Util.ConvertDouble_FenToYuan((int)(double.Parse(order.payAmount) * 100)).ToString("0.00")); + Replace("[结算时间]", order.db_endtime.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[下级订单状态]", order.db_status.ToString()); + } + if (type == typeof(fl_order_kuaishou)) + { + var order = item as fl_order_kuaishou; + Replace("[订单号]", order.oid.ToString()); + Replace("[商品标题]", order.itemTitle); + Replace("[付款金额]", order.paymentFee.ToString("0.00")); + Replace("[结算时间]", order.db_endtime.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[下级订单状态]", order.db_status.ToString()); + } + else if (type == typeof(fl_robot_info)) + { + var robot = item as fl_robot_info; + Replace("[机器人账号]", robot.name); + Replace("[机器人昵称]", robot.nick); + } + else if (type == typeof(fl_member_info)) + { + var session = ApiClient.GetSession(); + var member = item as fl_member_info; + if (_mess.Contains("[上级昵称]")) + { + var m = session.FindMemberInfoById(member.inviter_id); + if (m != null) + Replace("[上级昵称]", m.realnick); + else + Replace("[上级昵称]", "无"); + } + Replace("[消费者昵称]", member.realnick); + Replace("[限制兑换时间]", member.ban_exchange_time.ToString("yyyy-MM-dd HH:mm:ss")); + Replace("[可兑换积分]", "[剩余积分]"); + Replace("[剩余积分]", member.cur_point.ToString()); + Replace("[账号]", member.username); + Replace("[昵称]", member.realnick); + Replace("[累计积分]", member.sum_point.ToString()); + Replace("[提成积分]", member.ext_point.ToString()); + Replace("[其他积分]", member.rew_point.ToString()); + Replace("[消费积分]", member.buy_point.ToString()); + Replace("[推广积分]", ((decimal)member.rew_point + (decimal)member.ext_point).ToString()); + Replace("[支付宝账号]", member.alipay_num); + Replace("[支付宝姓名]", member.alipay_name); + Replace("[身份证号]", member.identity_card); + Replace("[身份证号码]", member.identity_card); + Replace("[姓名]", member.identity_name); + Replace("[身份证姓名]", member.identity_name); + Replace("[平台类型]", member.robot_type.ToString()); + + #region 今日订单信息/已退款订单数/今日总积分/已退款积分 + if (_mess.Contains("[订单总数]")) + { + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + + var session1 = ApiClient.GetSession(); + var data = session1.FindRow($@"select COALESCE(SUM(num),0) as num from ( +select count(*) as num from fl_order_alimama where db_userid = @userid +UNION all +select count(*) as num from fl_order_pinduoduo where db_userid = @userid +UNION all +select count(*) as num from fl_order_jingdong where db_userid = @userid +UNION all +select count(*) as num from fl_order_weipinhui where db_userid = @userid +UNION all +select count(*) as num from fl_order_suning where db_userid = @userid +UNION all +select count(*) as num from fl_order_douyin where db_userid = @userid +UNION all +select count(*) as num from fl_order_kuaishou where db_userid = @userid +) as temp", new { userid = member.id }); + Replace("[订单总数]", data["num"].ToString()); + + LogHelper.GetSingleObj().Debug("", $"订单总数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + })); + } + if (_mess.Contains("[今日总订单]")) + { + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + + var session1 = ApiClient.GetSession(); + var data = session1.FindRow($@"select COALESCE(SUM(num),0) as num from ( +select count(*) as num from fl_order_alimama where @begin_time < create_time and create_time <= @end_time and db_userid = @userid +UNION All +select count(*) as num from fl_order_pinduoduo where @begin_time < order_create_time and order_create_time <= @end_time and db_userid = @userid +UNION All +select count(*) as num from fl_order_jingdong where @begin_time < orderTime and orderTime <= @end_time and db_userid = @userid +UNION All +select count(*) as num from fl_order_suning where @begin_time < orderSubmitTime and orderSubmitTime <= @end_time and db_userid = @userid +UNION All +select count(*) as num from fl_order_weipinhui where @begin_time1 < orderTime and orderTime <= @end_time1 and db_userid = @userid +UNION All +select count(*) as num from fl_order_douyin where @begin_time2 < pay_time and pay_time <= @end_time2 and db_userid = @userid +UNION All +select count(*) as num from fl_order_kuaishou where @begin_time < payTime and payTime <= @end_time and db_userid = @userid +) as temp", new + { + begin_time = DateTime.Today.AddSeconds(-1).ToString("yyyy-MM-dd HH:mm:ss"), + end_time = DateTime.Today.AddDays(1).AddSeconds(-1).ToString("yyyy-MM-dd HH:mm:ss"), + begin_time1 = Util.GetTimeSpan(DateTime.Today.AddSeconds(-1), true), + end_time1 = Util.GetTimeSpan(DateTime.Today.AddDays(1).AddSeconds(-1), true), + begin_time2 = Util.GetTimeSpan(DateTime.Today.AddSeconds(-1), false), + end_time2 = Util.GetTimeSpan(DateTime.Today.AddDays(1).AddSeconds(-1), false), + userid = member.id + }); + + Replace("[今日总订单]", data["num"].ToString()); + + LogHelper.GetSingleObj().Debug("", $"今日总订单:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + })); + } + if (_mess.Contains("[已退款订单数]")) + { + Replace("[已退款订单数]", FindOrderInfoByState(999, member.id, OrderStateType.退款订单数)); + } + if (_mess.Contains("[今日总积分]")) + { + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + + var session1 = ApiClient.GetSession(); + var result = session1.FindRow($@"select COALESCE(SUM(num),0) as num from ( +select COALESCE(SUM(db_userpoint),0) as num from fl_order_alimama where @begin_time < create_time and create_time <= @end_time and db_userid = @userid +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_pinduoduo where @begin_time < order_create_time and order_create_time <= @end_time and db_userid = @userid +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_jingdong where @begin_time < orderTime and orderTime <= @end_time and db_userid = @userid +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_suning where @begin_time < orderSubmitTime and orderSubmitTime <= @end_time and db_userid = @userid +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_weipinhui where @begin_time1 < orderTime and orderTime <= @end_time1 and db_userid = @userid +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_douyin where @begin_time2 < pay_time and pay_time <= @end_time2 and db_userid = @userid +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_kuaishou where @begin_time < payTime and payTime <= @end_time and db_userid = @userid +) as temp", new + { + begin_time = DateTime.Today.AddSeconds(-1).ToString("yyyy-MM-dd HH:mm:ss"), + end_time = DateTime.Today.AddDays(1).AddSeconds(-1).ToString("yyyy-MM-dd HH:mm:ss"), + begin_time1 = Util.GetTimeSpan(DateTime.Today.AddSeconds(-1), true), + end_time1 = Util.GetTimeSpan(DateTime.Today.AddDays(1).AddSeconds(-1), true), + begin_time2 = Util.GetTimeSpan(DateTime.Today.AddSeconds(-1), false), + end_time2 = Util.GetTimeSpan(DateTime.Today.AddDays(1).AddSeconds(-1), false), + userid = member.id + }); + + Replace("[今日总积分]", double.Parse(result["num"].ToString()).ToString()); + + LogHelper.GetSingleObj().Debug("", $"今日总积分:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + })); + } + if (_mess.Contains("[已退款积分]")) + Replace("[已退款积分]", FindOrderInfoByState(999, member.id, OrderStateType.退款总金额)); + if (_mess.Contains("[已兑换积分]") || _mess.Contains("[已兑换总额]")) + { + Replace("[已兑换总额]", "[已兑换积分]"); + Replace("[已兑换积分]", FindAlreadyExchange(member.id)); + } + if (_mess.Contains("[兑换中积分]")) + Replace("[兑换中积分]", session.FindRow($"select COALESCE(SUM(point),0) as num from fl_exchange_info where uid = @uid and state = 1", new { uid = member.id })["num"].ToString()); + if (_mess.Contains("[下级总提成]")) + Replace("[下级总提成]", member.ext_point.ToString("0.00")); + + #endregion + + #region 各种订单金额数量查询 + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + + var session1 = ApiClient.GetSession(); + //[拼多多待结算数量]、[拼多多待结算金额]、[淘宝待结算数量]、[淘宝待结算金额]、[京东待结算数量]、[京东待结算金额]、[待结算总数数量]、[待结算总数金额]、[淘宝售后中订单数]、[京东售后中订单数] + decimal pddPendingPoint_sleep, pddPendingPoint_pay, pddPendingPoint, alimamaPendingPoint_sleep, alimamaPendingPoint_pay, alimamaPendingPoint, jdPendingPoint_sleep, jdPendingPoint_pay, jdPendingPoint, wphPendingPoint_sleep, wphPendingPoint_pay, wphPendingPoint, dyPendingPoint_sleep, dyPendingPoint_pay, dyPendingPoint, snPendingPoint_sleep, snPendingPoint_pay, snPendingPoint, ksPendingPoint_sleep, ksPendingPoint_pay, ksPendingPoint, sumPendingPoint; + + pddPendingPoint_sleep = pddPendingPoint_pay = pddPendingPoint = alimamaPendingPoint_sleep = alimamaPendingPoint_pay = alimamaPendingPoint = jdPendingPoint_sleep = jdPendingPoint_pay = jdPendingPoint = wphPendingPoint_sleep = wphPendingPoint_pay = wphPendingPoint = dyPendingPoint_sleep = dyPendingPoint_pay = dyPendingPoint = snPendingPoint_sleep = snPendingPoint_pay = snPendingPoint = ksPendingPoint_sleep = ksPendingPoint_pay = ksPendingPoint = sumPendingPoint = 0m; + + int pddPendingCount_sleep, pddPendingCount_pay, pddPendingCount, alimamaPendingCount_sleep, alimamaPendingCount_pay, alimamaPendingCount, jdPendingCount_sleep, jdPendingCount_pay, jdPendingCount, wphPendingCount_sleep, wphPendingCount_pay, wphPendingCount, dyPendingCount_sleep, dyPendingCount_pay, dyPendingCount, snPendingCount_sleep, snPendingCount_pay, snPendingCount, ksPendingCount_sleep, ksPendingCount_pay, ksPendingCount, sumPendingCount, alimamaReturnNum, jingdongReturnNum, weipinhuiReturnNum, douyinReturnNum, suningReturnNum, kuaishouReturnNum; + + pddPendingCount_sleep = pddPendingCount_pay = pddPendingCount = alimamaPendingCount_sleep = alimamaPendingCount_pay = alimamaPendingCount = jdPendingCount_sleep = jdPendingCount_pay = jdPendingCount = wphPendingCount_sleep = wphPendingCount_pay = wphPendingCount = dyPendingCount_sleep = dyPendingCount_pay = dyPendingCount = snPendingCount_sleep = snPendingCount_pay = snPendingCount = ksPendingCount_sleep = ksPendingCount_pay = ksPendingCount = sumPendingCount = alimamaReturnNum = jingdongReturnNum = weipinhuiReturnNum = douyinReturnNum = suningReturnNum = kuaishouReturnNum = 0; + + Dictionary pddDic = null; + Dictionary tbDic = null; + Dictionary jdDic = null; + Dictionary wphDic = null; + Dictionary dyDic = null; + Dictionary snDic = null; + Dictionary ksDic = null; + + if (pddlist.FirstOrDefault(f => _mess.Contains(f)) != null) + { + timeNow = DateTime.Now; + pddDic = FindOrderTotalInfo("fl_order_pinduoduo", member.id); + if (pddDic != null) + { + pddPendingPoint_sleep = pddDic["point_sleep"]; + pddPendingCount_sleep = (int)pddDic["count_sleep"]; + pddPendingPoint_pay = pddDic["point_pay"]; + pddPendingCount_pay = (int)pddDic["count_pay"]; + pddPendingPoint = pddDic["point"]; + pddPendingCount = (int)pddDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"A_pinduoduo:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + + if (tblist.FirstOrDefault(f => _mess.Contains(f)) != null) + { + timeNow = DateTime.Now; + tbDic = FindOrderTotalInfo("fl_order_alimama", member.id); + if (tbDic != null) + { + alimamaPendingPoint_sleep = tbDic["point_sleep"]; + alimamaPendingCount_sleep = (int)tbDic["count_sleep"]; + alimamaPendingPoint_pay = tbDic["point_pay"]; + alimamaPendingCount_pay = (int)tbDic["count_pay"]; + alimamaPendingPoint = tbDic["point"]; + alimamaPendingCount = (int)tbDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"A_alimama:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + + if (jdlist.FirstOrDefault(f => _mess.Contains(f)) != null) + { + timeNow = DateTime.Now; + jdDic = FindOrderTotalInfo("fl_order_jingdong", member.id); + if (jdDic != null) + { + jdPendingPoint_sleep = jdDic["point_sleep"]; + jdPendingCount_sleep = (int)jdDic["count_sleep"]; + jdPendingPoint_pay = jdDic["point_pay"]; + jdPendingCount_pay = (int)jdDic["count_pay"]; + jdPendingPoint = jdDic["point"]; + jdPendingCount = (int)jdDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"A_jingdong:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (wphlist.FirstOrDefault(f => _mess.Contains(f)) != null) + { + timeNow = DateTime.Now; + wphDic = FindOrderTotalInfo("fl_order_weipinhui", member.id); + if (wphDic != null) + { + wphPendingPoint_sleep = wphDic["point_sleep"]; + wphPendingCount_sleep = (int)wphDic["count_sleep"]; + wphPendingPoint_pay = wphDic["point_pay"]; + wphPendingCount_pay = (int)wphDic["count_pay"]; + wphPendingPoint = wphDic["point"]; + wphPendingCount = (int)wphDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"A_weipinhui:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (dylist.FirstOrDefault(f => _mess.Contains(f)) != null) + { + timeNow = DateTime.Now; + dyDic = FindOrderTotalInfo("fl_order_douyin", member.id); + if (dyDic != null) + { + dyPendingPoint_sleep = dyDic["point_sleep"]; + dyPendingCount_sleep = (int)dyDic["count_sleep"]; + dyPendingPoint_pay = dyDic["point_pay"]; + dyPendingCount_pay = (int)dyDic["count_pay"]; + dyPendingPoint = dyDic["point"]; + dyPendingCount = (int)dyDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"A_douyin:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (snlist.FirstOrDefault(f => _mess.Contains(f)) != null) + { + timeNow = DateTime.Now; + snDic = FindOrderTotalInfo("fl_order_suning", member.id); + if (snDic != null) + { + snPendingPoint_sleep = snDic["point_sleep"]; + snPendingCount_sleep = (int)snDic["count_sleep"]; + snPendingPoint_pay = snDic["point_pay"]; + snPendingCount_pay = (int)snDic["count_pay"]; + snPendingPoint = snDic["point"]; + snPendingCount = (int)snDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"A_suning:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (kslist.FirstOrDefault(f => _mess.Contains(f)) != null) + { + timeNow = DateTime.Now; + ksDic = FindOrderTotalInfo("fl_order_kuaishou", member.id); + if (ksDic != null) + { + ksPendingPoint_sleep = ksDic["point_sleep"]; + ksPendingCount_sleep = (int)ksDic["count_sleep"]; + ksPendingPoint_pay = ksDic["point_pay"]; + ksPendingCount_pay = (int)ksDic["count_pay"]; + ksPendingPoint = ksDic["point"]; + ksPendingCount = (int)ksDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"A_suning:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + + + if (list.FirstOrDefault(f => _mess.Contains(f)) != null) + { + if (pddDic == null) + { + timeNow = DateTime.Now; + pddDic = FindOrderTotalInfo("fl_order_pinduoduo", member.id); + if (pddDic != null) + { + pddPendingPoint_sleep = pddDic["point_sleep"]; + pddPendingCount_sleep = (int)pddDic["count_sleep"]; + pddPendingPoint_pay = pddDic["point_pay"]; + pddPendingCount_pay = (int)pddDic["count_pay"]; + pddPendingPoint = pddDic["point"]; + pddPendingCount = (int)pddDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"B_pinduoduo:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (tbDic == null) + { + timeNow = DateTime.Now; + tbDic = FindOrderTotalInfo("fl_order_alimama", member.id); + if (tbDic != null) + { + alimamaPendingPoint_sleep = tbDic["point_sleep"]; + alimamaPendingCount_sleep = (int)tbDic["count_sleep"]; + alimamaPendingPoint_pay = tbDic["point_pay"]; + alimamaPendingCount_pay = (int)tbDic["count_pay"]; + alimamaPendingPoint = tbDic["point"]; + alimamaPendingCount = (int)tbDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"B_alimama:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (jdDic == null) + { + timeNow = DateTime.Now; + jdDic = FindOrderTotalInfo("fl_order_jingdong", member.id); + if (jdDic != null) + { + jdPendingPoint_sleep = jdDic["point_sleep"]; + jdPendingCount_sleep = (int)jdDic["count_sleep"]; + jdPendingPoint_pay = jdDic["point_pay"]; + jdPendingCount_pay = (int)jdDic["count_pay"]; + jdPendingPoint = jdDic["point"]; + jdPendingCount = (int)jdDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"B_jingdong:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (wphDic == null) + { + timeNow = DateTime.Now; + wphDic = FindOrderTotalInfo("fl_order_weipinhui", member.id); + if (wphDic != null) + { + wphPendingPoint_sleep = wphDic["point_sleep"]; + wphPendingCount_sleep = (int)wphDic["count_sleep"]; + wphPendingPoint_pay = wphDic["point_pay"]; + wphPendingCount_pay = (int)wphDic["count_pay"]; + wphPendingPoint = wphDic["point"]; + wphPendingCount = (int)wphDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"B_weipinhui:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (dyDic == null) + { + timeNow = DateTime.Now; + dyDic = FindOrderTotalInfo("fl_order_douyin", member.id); + if (dyDic != null) + { + dyPendingPoint_sleep = dyDic["point_sleep"]; + dyPendingCount_sleep = (int)dyDic["count_sleep"]; + dyPendingPoint_pay = dyDic["point_pay"]; + dyPendingCount_pay = (int)dyDic["count_pay"]; + dyPendingPoint = dyDic["point"]; + dyPendingCount = (int)dyDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"B_douyin:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (snDic == null) + { + timeNow = DateTime.Now; + snDic = FindOrderTotalInfo("fl_order_suning", member.id); + if (snDic != null) + { + snPendingPoint_sleep = snDic["point_sleep"]; + snPendingCount_sleep = (int)snDic["count_sleep"]; + snPendingPoint_pay = snDic["point_pay"]; + snPendingCount_pay = (int)snDic["count_pay"]; + snPendingPoint = snDic["point"]; + snPendingCount = (int)snDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"B_suning:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (ksDic == null) + { + timeNow = DateTime.Now; + ksDic = FindOrderTotalInfo("fl_order_kuaishou", member.id); + if (ksDic != null) + { + ksPendingPoint_sleep = ksDic["point_sleep"]; + ksPendingCount_sleep = (int)ksDic["count_sleep"]; + ksPendingPoint_pay = ksDic["point_pay"]; + ksPendingCount_pay = (int)ksDic["count_pay"]; + ksPendingPoint = ksDic["point"]; + ksPendingCount = (int)ksDic["count"]; + } + LogHelper.GetSingleObj().Debug("", $"B_kuaishou:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + sumPendingPoint = pddPendingPoint + alimamaPendingPoint + jdPendingPoint + wphPendingPoint + dyPendingPoint + snPendingPoint + ksPendingPoint; + sumPendingCount = pddPendingCount + alimamaPendingCount + jdPendingCount + wphPendingCount + dyPendingCount + snPendingCount + ksPendingCount; + } + + if (_mess.Contains("[淘宝售后中订单数]")) + { + timeNow = DateTime.Now; + var result = session1.FindRow("select count(*) as count from fl_order_alimama where db_userid = @id and db_status = 1000", new { id = member.id }); + alimamaReturnNum = int.Parse(result["count"].ToString()); + LogHelper.GetSingleObj().Debug("", $"淘宝售后中订单数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (_mess.Contains("[京东售后中订单数]")) + { + timeNow = DateTime.Now; + var result = session1.FindRow("select count(*) as count from fl_order_jingdong where db_userid = @id and db_status = 1000", new { id = member.id }); + jingdongReturnNum = int.Parse(result["count"].ToString()); + LogHelper.GetSingleObj().Debug("", $"京东售后中订单数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (_mess.Contains("[唯品会售后中订单数]")) + { + timeNow = DateTime.Now; + var result = session1.FindRow("select count(*) as count from fl_order_weipinhui where db_userid = @id and db_status = 1000", new { id = member.id }); + weipinhuiReturnNum = int.Parse(result["count"].ToString()); + LogHelper.GetSingleObj().Debug("", $"唯品会售后中订单数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (_mess.Contains("[抖音售后中订单数]")) + { + timeNow = DateTime.Now; + var result = session1.FindRow("select count(*) as count from fl_order_douyin where db_userid = @id and db_status = 1000", new { id = member.id }); + douyinReturnNum = int.Parse(result["count"].ToString()); + LogHelper.GetSingleObj().Debug("", $"抖音售后中订单数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (_mess.Contains("[苏宁售后中订单数]")) + { + timeNow = DateTime.Now; + var result = session1.FindRow("select count(*) as count from fl_order_suning where db_userid = @id and db_status = 1000", new { id = member.id }); + suningReturnNum = int.Parse(result["count"].ToString()); + LogHelper.GetSingleObj().Debug("", $"苏宁售后中订单数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + if (_mess.Contains("[快手售后中订单数]")) + { + timeNow = DateTime.Now; + var result = session1.FindRow("select count(*) as count from fl_order_kuaishou where db_userid = @id and db_status = 1000", new { id = member.id }); + kuaishouReturnNum = int.Parse(result["count"].ToString()); + LogHelper.GetSingleObj().Debug("", $"快手售后中订单数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + + Replace("[淘宝售后中订单数]", alimamaReturnNum.ToString()); + Replace("[京东售后中订单数]", jingdongReturnNum.ToString()); + Replace("[唯品会售后中订单数]", weipinhuiReturnNum.ToString()); + Replace("[抖音售后中订单数]", douyinReturnNum.ToString()); + Replace("[苏宁售后中订单数]", suningReturnNum.ToString()); + Replace("[快手售后中订单数]", kuaishouReturnNum.ToString()); + Replace("[拼多多待结算数量]", pddPendingCount.ToString()); + Replace("[拼多多待结算金额]", pddPendingPoint.ToString("0.00")); + Replace("[淘宝待结算数量]", alimamaPendingCount.ToString()); + Replace("[淘宝待结算金额]", alimamaPendingPoint.ToString("0.00")); + Replace("[京东待结算数量]", jdPendingCount.ToString()); + Replace("[京东待结算金额]", jdPendingPoint.ToString("0.00")); + Replace("[唯品会待结算数量]", wphPendingCount.ToString()); + Replace("[唯品会待结算金额]", wphPendingPoint.ToString("0.00")); + Replace("[抖音待结算数量]", dyPendingCount.ToString()); + Replace("[抖音待结算金额]", dyPendingPoint.ToString("0.00")); + Replace("[苏宁待结算数量]", snPendingCount.ToString()); + Replace("[苏宁待结算金额]", snPendingPoint.ToString("0.00")); + Replace("[快手待结算数量]", ksPendingCount.ToString()); + Replace("[快手待结算金额]", ksPendingPoint.ToString("0.00")); + Replace("[待结算总数数量]", sumPendingCount.ToString()); + Replace("[待结算总数金额]", sumPendingPoint.ToString("0.00")); + + Replace("[淘宝冻结金额]", alimamaPendingPoint_sleep.ToString("0.00")); + Replace("[拼多多冻结金额]", pddPendingPoint_sleep.ToString("0.00")); + Replace("[京东冻结金额]", jdPendingPoint_sleep.ToString("0.00")); + Replace("[唯品会冻结金额]", wphPendingPoint_sleep.ToString("0.00")); + Replace("[抖音冻结金额]", dyPendingPoint_sleep.ToString("0.00")); + Replace("[苏宁冻结金额]", snPendingPoint_sleep.ToString("0.00")); + Replace("[快手冻结金额]", ksPendingPoint_sleep.ToString("0.00")); + Replace("[淘宝冻结订单数]", alimamaPendingCount_sleep.ToString()); + Replace("[拼多多冻结订单数]", pddPendingCount_sleep.ToString()); + Replace("[京东冻结订单数]", jdPendingCount_sleep.ToString()); + Replace("[唯品会冻结订单数]", wphPendingCount_sleep.ToString()); + Replace("[抖音冻结订单数]", dyPendingCount_sleep.ToString()); + Replace("[苏宁冻结订单数]", snPendingCount_sleep.ToString()); + Replace("[快手冻结订单数]", ksPendingCount_sleep.ToString()); + + Replace("[淘宝未收货金额]", alimamaPendingPoint_pay.ToString("0.00")); + Replace("[拼多多未收货金额]", pddPendingPoint_pay.ToString("0.00")); + Replace("[京东未收货金额]", jdPendingPoint_pay.ToString("0.00")); + Replace("[唯品会未收货金额]", wphPendingPoint_pay.ToString("0.00")); + Replace("[抖音未收货金额]", dyPendingPoint_pay.ToString("0.00")); + Replace("[苏宁未收货金额]", snPendingPoint_pay.ToString("0.00")); + Replace("[快手未收货金额]", ksPendingPoint_pay.ToString("0.00")); + Replace("[淘宝未收货订单数]", alimamaPendingCount_pay.ToString()); + Replace("[拼多多未收货订单数]", pddPendingCount_pay.ToString()); + Replace("[京东未收货订单数]", jdPendingCount_pay.ToString()); + Replace("[唯品会未收货订单数]", wphPendingCount_pay.ToString()); + Replace("[抖音未收货订单数]", dyPendingCount_pay.ToString()); + Replace("[苏宁未收货订单数]", snPendingCount_pay.ToString()); + Replace("[快手未收货订单数]", ksPendingCount_pay.ToString()); + + Replace("[未收货积分]", "[未收货总金额]"); + Replace("[待收货积分]", "[未收货总金额]"); + Replace("[未收货总金额]", (alimamaPendingPoint_pay + pddPendingPoint_pay + jdPendingPoint_pay + wphPendingPoint_pay + dyPendingPoint_pay + snPendingPoint_pay + ksPendingPoint_pay).ToString("0.00")); + Replace("[待结算积分]", "[冻结总金额]"); + Replace("[冻结总金额]", (alimamaPendingPoint_sleep + pddPendingPoint_sleep + jdPendingPoint_sleep + wphPendingPoint_sleep + dyPendingPoint_sleep + snPendingPoint_sleep + ksPendingPoint_sleep).ToString("0.00")); + Replace("[待收货订单数]", "[未收货订单数]"); + Replace("[未收货订单数]", (alimamaPendingCount_pay + pddPendingCount_pay + jdPendingCount_pay + wphPendingCount_pay + dyPendingCount_pay + snPendingCount_pay + ksPendingCount_pay).ToString()); + Replace("[待结算订单数]", "[冻结订单数]"); + Replace("[冻结订单数]", (alimamaPendingCount_sleep + pddPendingCount_sleep + jdPendingCount_sleep + wphPendingCount_sleep + dyPendingCount_sleep + snPendingCount_sleep + ksPendingCount_sleep).ToString()); + })); + #endregion + + #region 统计邀请数据 + if (_mess.Contains("[下级人数]") || _mess.Contains("[推荐人数]")) + { + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + var session1 = ApiClient.GetSession(); + var temp = session1.FindRow($"select count(id) as num from fl_member_info where inviter_id = @id", new { id = member.id })["num"].ToString(); + Replace("[下级人数]", "[推荐人数]"); + Replace("[推荐人数]", temp); + LogHelper.GetSingleObj().Debug("", $"下级人数|推荐人数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + })); + } + + if (_mess.Contains("[完成首单人数]")) + { + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + var session1 = ApiClient.GetSession(); + var temp = session1.FindRow($"select count(id) as num from fl_member_info where inviter_id = @id and finish_order != @finish_order", new { id = member.id, finish_order = 0 })["num"].ToString(); + Replace("[完成首单人数]", temp); + LogHelper.GetSingleObj().Debug("", $"完成首单人数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + })); + } + string UnfinishOrderNum = "0";//完成订单数 + if (_mess.Contains("[未完成首单人数]")) + { + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + var session1 = ApiClient.GetSession(); + var temp = session1.FindRow($"select count(id) as num from fl_member_info where inviter_id = @id and finish_order = @finish_order", new { id = member.id, finish_order = 0 })["num"].ToString(); + Replace("[未完成首单人数]", temp); + LogHelper.GetSingleObj().Debug("", $"未完成首单人数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + })); + } + if (_mess.Contains("[三级邀请人数]")) + { + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + var session1 = ApiClient.GetSession(); + var temp = session1.FindRow($@"select count(*) as num from ( +select id from fl_member_info where inviter_id = @id +UNION all +select id from fl_member_info where inviter_id in (select id from fl_member_info where inviter_id = @id ) and inviter_id != '0' +UNION all +select id from fl_member_info where inviter_id in (select id from fl_member_info where inviter_id in (select id from fl_member_info where inviter_id = @id) and inviter_id != '0') and inviter_id != '0' +) as temp", new { id = member.id })["num"].ToString(); + Replace("[三级邀请人数]", temp); + LogHelper.GetSingleObj().Debug("", $"三级邀请人数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + })); + } + + if (_mess.Contains("[三级有效人数]")) + { + actions.Add(new Action(delegate + { + var timeNow = DateTime.Now; + var session1 = ApiClient.GetSession(); + var temp = session1.FindRow($@"select count(*) as num from ( +select id from fl_member_info where inviter_id = @id and finish_order != 0 +UNION all +select id from fl_member_info where inviter_id in (select id from fl_member_info where inviter_id = @id) and inviter_id != '0' and finish_order != 0 +UNION all +select id from fl_member_info where inviter_id in (select id from fl_member_info where inviter_id in (select id from fl_member_info where inviter_id = @id) and inviter_id != '0') and inviter_id != '0' and finish_order != 0 +) as temp", new { id = member.id })["num"].ToString(); + Replace("[三级有效人数]", temp); + LogHelper.GetSingleObj().Debug("", $"三级有效人数:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + })); + } + #endregion + + #region 获取订单记录 + if (_mess.Contains("[订单记录]")) + { + var timeNow = DateTime.Now; + var _dics = new List(); + //查阿里妈妈订单 + //var list_alimama = session.Queryable().Where(f => f.db_userid == member.id).OrderBy(f => f.id, SqlSugar.OrderByType.Desc).ToPageList(1, 30); + var list_alimama = session.Find("select * from fl_order_alimama where db_userid=@uid order by id desc limit 0,30", new { uid = member.id }); + //this.OnLog("阿里妈妈数量:"+list_alimama.Count+",您的ID:"+ id); + foreach (var aimama in list_alimama) + { + _dics.Add(new + { + orderId = aimama.trade_parent_id, + title = aimama.item_title, + status = aimama.db_status.ToString(), + money = aimama.alipay_total_price.ToString("0.00"), + fanli = aimama.db_userpoint.ToString("0.00"), + nums = aimama.item_num, + crtTime = aimama.create_time.ToString("yyyy-MM-dd HH:mm:ss") + }); + } + + LogHelper.GetSingleObj().Debug("", $"AA:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + timeNow = DateTime.Now; + + //查最近拼多多订单 + var list_pinduoduo = session.Find("select * from fl_order_pinduoduo where db_userid=@uid order by id desc limit 0,30", new { uid = member.id }); + foreach (var pdd in list_pinduoduo) + { + _dics.Add(new + { + orderId = pdd.order_sn, + title = pdd.goods_name, + status = pdd.db_status.ToString(), + money = pdd.order_amount.ToString("0.00"), + fanli = pdd.db_userpoint.ToString("0.00"), + nums = pdd.goods_quantity, + crtTime = pdd.order_create_time.ToString("yyyy-MM-dd HH:mm:ss") + }); + } + + LogHelper.GetSingleObj().Debug("", $"BB:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + timeNow = DateTime.Now; + + //查最近京东订单 + var list_jingdong = session.Find("select * from fl_order_jingdong where db_userid=@uid order by id desc limit 0,30", new { uid = member.id }); + foreach (var jd in list_jingdong) + { + _dics.Add(new + { + orderId = jd.orderId, + title = jd.skuName, + status = jd.db_status.ToString(), + money = jd.estimateCosPrice.ToString("0.00"), + fanli = jd.db_userpoint.ToString("0.00"), + nums = jd.skuNum, + crtTime = jd.orderTime.ToString("yyyy-MM-dd HH:mm:ss") + }); + } + + LogHelper.GetSingleObj().Debug("", $"CC:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + timeNow = DateTime.Now; + + //查最近唯品会订单 + var list_weipinhui = session.Find("select * from fl_order_weipinhui where db_userid=@uid order by id desc limit 0,30", new { uid = member.id }); + foreach (var wph in list_weipinhui) + { + _dics.Add(new + { + orderId = wph.orderSn, + title = wph.goodsName, + status = wph.db_status.ToString(), + money = wph.commission.ToString("0.00"), + fanli = wph.db_userpoint.ToString("0.00"), + nums = wph.goodsCount, + crtTime = Util.GetDateTime(wph.orderTime).ToString("yyyy-MM-dd HH:mm:ss") + }); + } + + //查最近抖音订单 + var list_douyin = session.Find("select * from fl_order_douyin where db_userid=@uid order by id desc limit 0,30", new { uid = member.id }); + foreach (var dy in list_douyin) + { + _dics.Add(new + { + orderId = dy.order_id, + title = dy.product_name, + status = dy.db_status.ToString(), + money = Util.ConvertDouble_FenToYuan(dy.estimated_comission), + fanli = dy.db_userpoint.ToString("0.00"), + nums = 1, + crtTime = Util.GetDateTime(dy.pay_time).ToString("yyyy-MM-dd HH:mm:ss") + }); + } + + //查最近苏宁订单 + var list_suning = session.Find("select * from fl_order_suning where db_userid=@uid order by id desc limit 0,30", new { uid = member.id }); + foreach (var sn in list_suning) + { + _dics.Add(new + { + orderId = sn.orderCode, + title = sn.productName, + status = sn.db_status.ToString(), + money = double.Parse(sn.prePayCommission).ToString("0.00"), + fanli = sn.db_userpoint.ToString("0.00"), + nums = sn.saleNum, + crtTime = sn.payTime.ToString("yyyy-MM-dd HH:mm:ss") + }); + } + + //查最近苏宁订单 + var list_kuaishou = session.Find("select * from fl_order_kuaishou where db_userid=@uid order by id desc limit 0,30", new { uid = member.id }); + foreach (var ks in list_kuaishou) + { + _dics.Add(new + { + orderId = ks.oid.ToString(), + title = ks.itemTitle, + status = ks.db_status.ToString(), + money = ks.estimatedIncome.ToString("0.00"), + fanli = ks.db_userpoint.ToString("0.00"), + nums = ks.num, + crtTime = ks.payTime.ToString("yyyy-MM-dd HH:mm:ss") + }); + } + + LogHelper.GetSingleObj().Debug("", $"DD:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + timeNow = DateTime.Now; + + // var count = list_alimama.Count + list_pinduoduo.Count + list_jingdong.Count; + if (_dics.Count == 0) + Replace("[订单记录]", "暂无记录"); + else + { + string key = HttpHelper.ToMD5("aliorder_" + member.username).ToLower(); + var _url = FindTransferAddress(TargetType.订单页, true); + var url = GetOrderList(_url, key, HttpHelper.ObjectToJson(_dics)); + if (string.IsNullOrWhiteSpace(url)) + Replace("[订单记录]", "查询失败"); + else + { + var url_ = string.Empty; + if (ApiClient.Setting.SystemConfig.dwz_type != DwzType.不缩短域名) + url_ = ApiClient.ShortURL(url).Result; + else + url_ = ApiClient.ShortURL(url, DwzType.快站短网址).Result; + Replace("[订单记录]", url_); + } + } + LogHelper.GetSingleObj().Debug("", $"订单记录:{(DateTime.Now - timeNow).TotalSeconds}\r\n"); + } + #endregion + + #region 邀请列表 + + if (_mess.Contains("[下级列表]")) + { + var subordinate = new StringBuilder(); + var memberList = session.Find("select * from fl_member_info where inviter_id = @uid order by crt_time desc", new { uid = member.id }).Take(10).ToList(); + for (int i = 0; i < memberList.Count; i++) + { + subordinate.AppendLine($"{i + 1}.{memberList[i].realnick}"); + } + Replace("[下级列表]", subordinate.ToString()); + } + #endregion + + } + else if (type == typeof(ItemPoint)) + { + var point = item as ItemPoint; + Replace("[返利积分]", point.UserPoint.ToString("0.00")); + Replace("[总积分]", point.SumPoint.ToString("0.00")); + Replace("[总佣金]", point.Commission.ToString("0.00")); + Replace("[三级提成积分]", point.AwardThree.ToString("0.00")); + Replace("[二级提成积分]", point.AwardTwo.ToString("0.00")); + Replace("[一级提成积分]", point.AwardOne.ToString("0.00")); + Replace("[群负责人提成积分]", point.AwardCreate.ToString("0.00")); + Replace("[维权返利积分]", point.UserPoint.ToString("0.00")); + } + } + + int excute_num = 0; + object lock_action = new object(); + if (actions.Count > 0) + { + Parallel.ForEach(actions, action => action.Invoke()); + } + + Replace("[创建时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + } + catch (Exception ex) + { + EventClient.OnEvent(null, $"{ex.Message} - {ex.StackTrace}"); + } + return mess.ToString(); + } + + /// + /// 统计阿里妈妈,京东,拼多多,(付款状态订单合计/冻结状态订单合计/付款和冻结状态订单合计) + /// + /// 表名 + /// 用户id + /// + private Dictionary FindOrderTotalInfo(string tableName, long uid) + { + var sql = string.Empty; + try + { + var sqlwhere = string.Empty; + switch (tableName) + { + case "fl_order_pinduoduo": + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= order_create_time"; + break; + case "fl_order_alimama": + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= create_time"; + break; + case "fl_order_jingdong": + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= orderTime"; + break; + case "fl_order_weipinhui": //下单时间为 int + sqlwhere += $" and '{HttpExtend.GetTimeStamp(DateTime.Now.AddYears(-1))}' <= orderTime"; + break; + case "fl_order_douyin": //下单时间为 int + sqlwhere += $" and '{HttpExtend.GetTimeStamp(DateTime.Now.AddYears(-1))}' <= pay_time"; + break; + case "fl_order_suning": + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= payTime"; + break; + case "fl_order_kuaishou": + sqlwhere += $" and '{DateTime.Now.AddYears(-1).ToString("yyyy-MM-dd HH:mm:ss")}' <= payTime"; + break; + default: + break; + } + + var session = ApiClient.GetSession(); + + sql = $"select round(COALESCE(sum(db_userpoint),0) ,2) as sum ,count(id) as count from {tableName} where db_userid = @id and db_status = 1001 {sqlwhere} UNION ALL select round(COALESCE(sum(db_userpoint), 0), 2) as sum, count(id) as count from {tableName} where db_userid = @id and db_status = 1005 {sqlwhere}"; + var result = session.FindTable(sql, new { id = uid }); + if (result.Rows.Count != 0 && result.Rows.Count == 2) + { + var dic = new Dictionary(); + + var point_sleep = decimal.Parse(result.Rows[0]["sum"].ToString()); + var count_sleep = int.Parse(result.Rows[0]["count"].ToString()); + var point_pay = decimal.Parse(result.Rows[1]["sum"].ToString()); + var count_pay = int.Parse(result.Rows[1]["count"].ToString()); + + dic.Add("point_sleep", point_sleep); + dic.Add("count_sleep", count_sleep); + dic.Add("point_pay", point_pay); + dic.Add("count_pay", count_pay); + dic.Add("point", point_sleep + point_pay); + dic.Add("count", count_sleep + count_pay); + + return dic; + } + } + catch (Exception ex) + { + EventClient.OnEvent("", $"查询积分异常:{tableName} - {uid} - {ex.Message} - {ex.StackTrace}"); + LogHelper.GetSingleObj().Error("", $"查询积分异常:{tableName} - {uid} - {ex.Message} - {ex.StackTrace} - {sql}"); + } + return null; + } + + private enum OrderStateType + { + 退款总金额 = 0, + 退款订单数 = 1 + } + + /// + /// 已退款积分 + /// + /// + /// + /// + /// + private string FindOrderInfoByState(int status_id, long uid, OrderStateType stateType) + { + try + { + //key == "[待收货积分]" ? 1005 : key == "[已退款积分]" ? 1003 : 1001 + + var session = ApiClient.GetSession(); + var sql = string.Empty; + if (uid != 999) + { + if (stateType == OrderStateType.退款总金额) + { + sql = $@"select COALESCE(SUM(num),0) as num from (select COALESCE(SUM(db_userpoint),0) as num from fl_order_alimama where db_userid = @userid and db_status = @status +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_pinduoduo where db_userid = @userid and db_status = @status +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_jingdong where db_userid = @userid and db_status = @status) as temp"; + return double.Parse(session.FindRow(sql, new { userid = uid, status = status_id })["num"].ToString()).ToString("0.00"); + } + else + { + sql = $@"select COALESCE(SUM(num),0) as num from (select count(*) as num from fl_order_alimama where db_userid = @userid and db_status = @status +UNION all +select count(*) as num from fl_order_pinduoduo where db_userid = @userid and db_status = @status +UNION all +select count(*) as num from fl_order_jingdong where db_userid = @userid and db_status = @status) as temp"; + return session.FindRow(sql, new { userid = uid, status = status_id })["num"].ToString(); + } + } + else + { + if (stateType == OrderStateType.退款总金额) + { + sql = $@"select COALESCE(SUM(num),0) as num from (select COALESCE(SUM(db_userpoint),0) as num from fl_order_alimama where db_userid = @userid and (db_status = @status or db_status = @status2) +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_pinduoduo where db_userid = @userid and (db_status = @status or db_status = @status2) +UNION all +select COALESCE(SUM(db_userpoint),0) as num from fl_order_jingdong where db_userid = @userid and (db_status = @status or db_status = @status2)) as temp"; + return double.Parse(session.FindRow(sql, new { userid = uid, status = status_id, status2 = 1003 })["num"].ToString()).ToString("0.00"); + } + else + { + sql = $@"select COALESCE(SUM(num),0) as num from (select count(*) as num from fl_order_alimama where db_userid = @userid and (db_status = @status or db_status = @status2) +UNION all +select count(*) as num from fl_order_pinduoduo where db_userid = @userid and (db_status = @status or db_status = @status2) +UNION all +select count(*) as num from fl_order_jingdong where db_userid = @userid and (db_status = @status or db_status = @status2)) as temp"; + + return session.FindRow(sql, new { userid = uid, status = status_id, status2 = 1003 })["num"].ToString(); + } + } + } + catch (Exception ex) + { } + return "0"; + } + + #region 已兑换积分 + private string FindAlreadyExchange(long uid) + { + try + { + var session = ApiClient.GetSession(); + var sumPoint = double.Parse(session.FindRow("select COALESCE(SUM(point),0) as num from fl_point_hist where uid = @uid and type = '提现扣除'", new { uid = uid })["num"].ToString()); + var thSumPoint = double.Parse(session.FindRow("select COALESCE(SUM(point),0) as num from fl_point_hist where uid = @uid and type = '退回积分'", new { uid = uid })["num"].ToString()); + return (sumPoint + thSumPoint).ToString("0.00").Replace("-", ""); + } + catch (Exception ex) + { + EventClient.OnEvent(null, $"查询已兑换总额异常:{ex.Message} - {ex.StackTrace}"); + } + return "-1"; + } + #endregion + + /// + /// 获取订单详情 + /// + /// + /// + /// + private string GetOrderList(string _url, string key, string json) + { + try + { + var http = new HttpHelper(); + var item = http.GetItem("http://api.view.52cmg.cn/api/util.asmx/SetCache"); + item.Postdata = "key=" + key + "&json=" + HttpHelper.URLEncode(json, Encoding.UTF8); + item.Encoding = Encoding.UTF8; + item.Method = "post"; + var result = http.GetHtml(item); + if (!string.IsNullOrWhiteSpace(ApiClient.Setting.SystemConfig.URLTbDdxq)) + _url = ApiClient.Setting.SystemConfig.URLTbDdxq; + return _url.Replace("[key]", key); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"获取订单详情:{ex.Message}"); + } + return string.Empty; + } + + /// + /// 用户自定义变量替换 + /// + /// 替换的原内容 + /// 替换后的内容,报错将返回原内容 + internal string ReplaceUserVariate(string str) + { + StringBuilder strb = new StringBuilder(); + strb.Append(str); + try + { + var session = ApiClient.GetSession(); + var uservariaters = session.FindUserVariates(); + if (uservariaters != null && uservariaters.Count != 0) + { + foreach (var variater in uservariaters) + { + strb = strb.Replace(variater.variate, variater.data); + } + } + return strb.ToString(); + } + catch (Exception ex) + { } + return str; + } + + } +} diff --git a/类库/Api.Framework/Tools/WPHHelper.cs b/类库/Api.Framework/Tools/WPHHelper.cs new file mode 100644 index 0000000..6cce419 --- /dev/null +++ b/类库/Api.Framework/Tools/WPHHelper.cs @@ -0,0 +1,1302 @@ +using Api.Framework.Cps; +using Api.Framework.Enums; +using Api.Framework.Model; +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 唯品会助手类 + /// + public class WPHHelper + { + /// + /// 查找宝贝Id的正则表达式 + /// + //private static string RegItemId = @"product-\d+-(?<商品Id>\d+)"; + private static List RegItemIds = new List() { @"(?i)(?:product|detail)-\d+-(?<商品Id>\d+)", @"(?i)vip.com.+?goodsId=(?<商品Id>\d+)", @"landing_pid=(?<商品Id>\d+)" }; + + /// + /// 内容中获取唯品会商品id + /// + /// + /// + private static string CheckRegexGetGoodsId(string mess) + { + try + { + try + { + mess = HttpHelper.URLDecode(HttpHelper.URLDecode(HttpHelper.URLDecode(mess))); + foreach (var item in RegItemIds) + { + var reg = Regex.Match(mess, item, RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups["商品Id"].Value; + } + } + catch (Exception ex) + { } + + var urlTmps = HttpExtend.RegexMatchesUrl(mess); + foreach (var url in urlTmps) + { + var tmpUrl = FindLocationByUrl(url); + if (!string.IsNullOrWhiteSpace(tmpUrl)) + { + tmpUrl = HttpHelper.URLDecode(HttpHelper.URLDecode(HttpHelper.URLDecode(tmpUrl))); + foreach (var item in RegItemIds) + { + var reg = Regex.Match(tmpUrl, item, RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups["商品Id"].Value; + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 获取商品id + /// + /// 内容 + /// + public static string GetWphGoodsID(string mess) + { + try + { + var messTmp = HttpHelper.URLDecode(HttpHelper.URLDecode(HttpHelper.URLDecode(mess))); + if (messTmp.ToLower().Contains("vip.com") || messTmp.ToLower().Contains("m.vip") || messTmp.ToLower().Contains("vipglobal.hk")) + { + var itemId = CheckRegexGetGoodsId(messTmp); + if (!string.IsNullOrWhiteSpace(itemId)) + return itemId; + } + //pages/index/index.html?$route=/pages/productDetail/productDetail?goodsId=6919530373160104087&brandId=1710613367&f=share_pd&nmsns=shop_android-7.62.2-weixin&nst=product&nsbc=&nct=card&ncid=075f0b5e-f292-3b6f-a846-7aab008970f9&nabtid=121&nuid=377785401&nchl_param=share:075f0b5e-f292-3b6f-a846-7aab008970f9:1642813783344&mars_cid_a=075f0b5e-f292-3b6f-a846-7aab008970f9&chl_type=share&nmsns=shop_android-7.62.2-weixin&nst=product&nsbc=&nct=card&ncid=075f0b5e-f292-3b6f-a846-7aab008970f9&nabtid=121&nuid=377785401&nchl_param=share:075f0b5e-f292-3b6f-a846-7aab008970f9:1642813783344&mars_cid_a=075f0b5e-f292-3b6f-a846-7aab008970f9&chl_type=share&tra_from=adp:C01V4m7y4lstf247::mig_code::x214d703d4124f5fbd3f8451e99b81f7 + if (messTmp.ToLower().Contains("vipshop/") || messTmp.Contains("唯品") || messTmp.ToLower().Contains("productDetail/productDetail".ToLower())) + { + var reg = Regex.Match(messTmp, @"goodsId=(?<商品Id>\d+)", RegexOptions.IgnoreCase); + if (reg.Success) + { + return reg.Groups["商品Id"].Value; + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 转链(根据商品id生成联盟链接) 参数参考:https://vop.vip.com/home#/api/method/detail/com.vip.adp.api.open.service.UnionUrlService-1.0.0/genByGoodsIdWithOauth + /// + /// 参数 + /// + public WPHCpsUrl GetCpsUrl(WeipinhuiApi api, object data) + { + return api.SendWeipinhui("com.vip.adp.api.open.service.UnionUrlService-1.0.0#genByGoodsIdWithOauth", data); + } + + /// + /// 转链(根据唯品会链接生成联盟链接) 参数参考:https://vop.vip.com/home#/api/method/detail/com.vip.adp.api.open.service.UnionUrlService-1.0.0/genByVIPUrlWithOauth + /// + /// 参数 + /// + public WPHCpsUrl GetCpsUrl_Hide(WeipinhuiApi api, object data) + { + return api.SendWeipinhui("com.vip.adp.api.open.service.UnionUrlService-1.0.0#genByVIPUrlWithOauth", data); + } + + /// + /// 获取链接真实地址 + /// + /// 链接 + /// 开源 + /// + /// + private static string FindLocationByUrl(string url, string referer = "", bool allowautoredirect = false) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + IsToLower = false, + Timeout = 5000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Referer = referer, + Allowautoredirect = allowautoredirect + }; + HttpResult result = http.GetHtml(item); + var ss = result.Header.Get("Location"); + return ss; + } + catch (Exception) + { } + return string.Empty; + } + + /// + /// 将订单明细对象转换成数据库唯品会fl_order_weipinhui对象 + /// + /// + /// + /// + internal List OrderInfoListConvertDbWeipinhuiOrder(OrderInfoList order, List wphList) + { + try + { + if (order == null) + return wphList; + + if (wphList == null) + { + #region 商品明细 + if (order.detailList != null) + { + var wphs = new List(); + + foreach (var detail in order.detailList) + { + var wph = new fl_order_weipinhui(); + #region 公共部分 + wph.orderSn = order.orderSn; //订单号 + wph.newCustomer = order.newCustomer;//新老客:0-待定,1-新客,2-老客 WeipinhuiNewCustomer + wph.channelTag = order.channelTag;//渠道商模式下表示自定义渠道标识;工具商模式下表示pid + wph.orderTime = order.orderTime;//下单时间 时间戳 单位毫秒 + wph.signTime = order.signTime;//签收时间 时间戳 单位毫秒 + wph.settledTime = order.settledTime;//结算时间 时间戳 单位毫秒 + wph.lastUpdateTime = order.lastUpdateTime;//订单上次更新时间 时间戳 单位毫秒 + wph.settled = order.settled;//订单结算状态 0-未结算,1-已结算 WeipinhuiOrderSettled + wph.selfBuy = order.selfBuy;//是否自推自买 0-否,1-是 WeipinhuiShiFou + wph.orderSubStatusName = Util.ConvertEnum(order.orderSubStatusName);//订单子状态:流转状态-支持状态:(已下单、已付款、已签收、待结算、已结算、已失效) + wph.afterSaleChangeCommission = order.afterSaleChangeCommission;//售后订单佣金变动:仅在订单完结之后发生售后行为时返回 + wph.afterSaleChangeGoodsCount = order.afterSaleChangeGoodsCount;//售后订单总商品数量变动:仅在订单完结之后发生售后行为时返回 + wph.commissionEnterTime = order.commissionEnterTime;//入账时间,时间戳,单位毫秒 + wph.pid = order.pid;//推广PID:目前等同于channelTag + wph.isPrepay = order.isPrepay;//是否预付订单:0-否,1-是 WeipinhuiShiFou + wph.statParam = order.statParam; //自定义统计参数 + wph.isSplit = order.isSplit;//订单拆单标识: 0-否,1-是 WeipinhuiShiFou + wph.parentSn = order.parentSn;//订单母单号:订单为拆单子单时返回 + wph.orderTrackReason = order.orderTrackReason;//订单归因方式:0-常规推广,1-惊喜红包,2-锁粉,3-超级红包 WeipinhuiGuiYin + + //wph.status = ;//订单状态:0-不合格,1-待定,2-已完结 WeipinhuiOrderStatus + //wph. string orderSource ;//订单来源 + #endregion + + //if (detail.goodsId == "6918315325800001858") + //{ + + //} + + wph.goodsId = detail.goodsId;//商品id + wph.goodsName = detail.goodsName;//商品名称 + wph.goodsThumb = detail.goodsThumb;//商品缩略图 + wph.goodsCount = detail.goodsCount;//商品数量 + wph.commissionTotalCost = double.Parse(detail.commissionTotalCost);//商品计佣金额(元,保留两位小数) + wph.commissionRate = Math.Round(double.Parse(detail.commissionRate) / 100.00, 2);//商品佣金比例(%) + wph.commission = double.Parse(detail.commission);//商品佣金金额(元,保留两位小数) + wph.commCode = detail.commCode;//佣金编码:对应商品二级分类 + wph.commName = detail.commName;//佣金方案名称 + wph.orderSource = detail.orderSource;//订单来源 + wph.sizeId = detail.sizeId;//商品尺码:2019.01.01之后可用 + wph.status = detail.status;//商品状态:0-不合格,1-待定,2-已完结 + wph.brandStoreSn = detail.brandStoreSn;//品牌编号 + wph.brandStoreName = detail.brandStoreName;//品牌名称 + wph.spuId = detail.spuId;//商品spuId + wph.goodsFinalPrice = double.Parse(detail.goodsFinalPrice);//商品成交价(元,保留两位小数,商品成交价上线之后的订单才有该值) + + #region 售后信息 无售后为空 + if (detail.afterSaleInfo != null && detail.afterSaleInfo.Count != 0) + { + var afterSaleChangedCommission = string.IsNullOrWhiteSpace(detail.afterSaleInfo[0].afterSaleChangedCommission) ? 0 : double.Parse(detail.afterSaleInfo[0].afterSaleChangedCommission); + + if (afterSaleChangedCommission != 0) + { + wph.afterSaleChangedCommission = afterSaleChangedCommission;//商品佣金售后变动:仅在订单完结之后发生售后时返回,无售后时为空 + + wph.afterSaleChangedGoodsCount = detail.afterSaleInfo[0].afterSaleChangedGoodsCount;//商品数量售后变动:仅在订单完结之后发生售后时返回,无售后时为空 + wph.afterSaleSn = detail.afterSaleInfo[0].afterSaleSn;//商品售后单号,无售后时为空 + wph.afterSaleStatus = detail.afterSaleInfo[0].afterSaleStatus;//商品售后状态:1-售后中,2-售后完成,3-售后取消,无售后时为空 WeipinhuiAfterSaleStatus + wph.afterSaleType = detail.afterSaleInfo[0].afterSaleType;//售后类型:1-退货,2-换货,无售后时为空 WeipinhuiSfterSaleType + wph.afterSaleFinishTime = detail.afterSaleInfo[0].afterSaleFinishTime;//售后完成时间,时间戳,单位:毫秒,无售后时为空 + + if (wph.afterSaleChangedGoodsCount != 0) + wph.orderSubStatusName = WeipinhuiOrderSubStatusName.维权中; + else + { + var db_order = ApiClient.GetSession().FindSingle("orderSn=@orderSn and goodsId=@goodsId and sizeId = @sizeId", new { orderSn = wph.orderSn, goodsId = wph.goodsId, sizeId = wph.sizeId }); + if (db_order != null && db_order.db_status == SystemOrderStatus.订单结算) //跳过相同状态 + { + wph.orderSubStatusName = WeipinhuiOrderSubStatusName.维权中; + } + else + { + wph.orderSubStatusName = WeipinhuiOrderSubStatusName.维权完成; + } + } + } + else + { + //退货 = 1 + //换货 = 2 + if (detail.afterSaleInfo[0].afterSaleType == WeipinhuiSfterSaleType.退货 && detail.afterSaleInfo[0].afterSaleStatus == WeipinhuiAfterSaleStatus.售后完成) + { + wph.afterSaleStatus = detail.afterSaleInfo[0].afterSaleStatus; + wph.orderSubStatusName = WeipinhuiOrderSubStatusName.已失效; + wph.afterSaleType = detail.afterSaleInfo[0].afterSaleType; + } + } + } + #endregion + + wphs.Add(wph); + } + + return wphs; + } + #endregion + } + } + catch (Exception ex) + { + EventClient.OnEvent("将订单明细对象转换成数据库唯品会fl_order_weipinhui对象异常:", ex.Message + " - " + ex.StackTrace); + } + return null; + } + + } + + #region 返回的数据结构 + #region 转链后返回的数据 + /// + /// 链接数据 + /// + public class UrlInfoList + { + /// + /// 链接生成的数据源: 如果根据商品id生成链接,该值商品id, 如果根据链接生成链接,该值为唯品会链接 + /// + public string source { get; set; } + /// + /// CPS短链接 + /// + public string url { get; set; } + /// + /// CPS长连接 + /// + public string longUrl { get; set; } + /// + /// CPS通用连接 + /// + public string ulUrl { get; set; } + /// + /// CPS Deeplink链接 + /// + public string deeplinkUrl { get; set; } + /// + /// 小程序CPS参数:通用小程序跟单参数 + /// + public string traFrom { get; set; } + /// + /// CPS短链接:不唤起快应用 + /// + public string noEvokeUrl { get; set; } + /// + /// CPS长链接:不唤起快应用 + /// + public string noEvokeLongUrl { get; set; } + /// + /// 唯品会小程序链接:仅在根据商品id获取时返回 + /// + public string vipWxUrl { get; set; } + /// + /// 唯品会小程序码:仅在根据商品id获取时返回,需获取小程序码高级权限 + /// + public string vipWxCode { get; set; } + /// + /// 唯品会快应用链接 + /// + public string vipQuickAppUrl { get; set; } + } + + public class Result1 + { + /// + /// 链接数据 + /// + public List urlInfoList { get; set; } + } + + /// + /// 转链后返回的数据解构 + /// + public class WPHCpsUrl + { + public string returnCode { get; set; } + public Result1 result { get; set; } + } + #endregion + + #region 订单下载数据解构 + /// + /// 商品明细 + /// + public class DetailList + { + /// + /// 商品id + /// + public string goodsId { get; set; } + /// + /// 商品名称 + /// + public string goodsName { get; set; } + /// + /// 商品缩略图 + /// + public string goodsThumb { get; set; } + /// + /// 商品数量 + /// + public int goodsCount { get; set; } + /// + /// 商品计佣金额(元,保留两位小数) + /// + public string commissionTotalCost { get; set; } + /// + /// 商品佣金比例(%) + /// + public string commissionRate { get; set; } + /// + /// 商品佣金金额(元,保留两位小数) + /// + public string commission { get; set; } + /// + /// 佣金编码:对应商品二级分类 + /// + public string commCode { get; set; } + /// + /// 佣金方案名称 + /// + public string commName { get; set; } + /// + /// 订单来源 + /// + public string orderSource { get; set; } + /// + /// 商品售后信息 + /// + public List afterSaleInfo { get; set; } + /// + /// 商品尺码:2019.01.01之后可用 + /// + public string sizeId { get; set; } + /// + /// 商品状态:0-不合格,1-待定,2-已完结 + /// + public WeipinhuiOrderStatus status { get; set; } + /// + /// 品牌编号 + /// + public string brandStoreSn { get; set; } + /// + /// 品牌名称 + /// + public string brandStoreName { get; set; } + /// + /// 商品spuId + /// + public string spuId { get; set; } + /// + /// 商品成交价(元,保留两位小数,商品成交价上线之后的订单才有该值) + /// + public string goodsFinalPrice { get; set; } + } + + /// + /// 商品售后信息 + /// + public class AfterSaleInfo + { + /// + /// 商品佣金售后变动:仅在订单完结之后发生售后时返回,无售后时为空 + /// + public string afterSaleChangedCommission { get; set; } + /// + /// 商品数量售后变动:仅在订单完结之后发生售后时返回,无售后时为空 + /// + public int afterSaleChangedGoodsCount { get; set; } + /// + /// 商品售后单号,无售后时为空 + /// + public string afterSaleSn { get; set; } + /// + /// 商品售后状态:1-售后中,2-售后完成,3-售后取消,无售后时为空 + /// + public WeipinhuiAfterSaleStatus afterSaleStatus { get; set; } + /// + /// 售后类型:1-退货,2-换货,无售后时为空 + /// + public WeipinhuiSfterSaleType afterSaleType { get; set; } + /// + /// 售后完成时间,时间戳,单位:毫秒,无售后时为空 + /// + public long afterSaleFinishTime { get; set; } + } + + /// + /// 业绩查询响应结果 + /// + public class OrderInfoList + { + /// + /// 订单号 + /// + public string orderSn { get; set; } + /// + /// 订单状态:0-不合格,1-待定,2-已完结 + /// + public WeipinhuiOrderStatus status { get; set; } + /// + /// 新老客:0-待定,1-新客,2-老客 + /// + public WeipinhuiNewCustomer newCustomer { get; set; } + /// + /// 渠道商模式下表示自定义渠道标识;工具商模式下表示pid + /// + public string channelTag { get; set; } + /// + /// 下单时间 时间戳 单位毫秒 + /// + public long orderTime { get; set; } + /// + /// 签收时间 时间戳 单位毫秒 + /// + public long signTime { get; set; } + /// + /// 结算时间 时间戳 单位毫秒 + /// + public long settledTime { get; set; } + /// + /// 商品明细 + /// + public List detailList { get; set; } + /// + /// 订单上次更新时间 时间戳 单位毫秒 + /// + public long lastUpdateTime { get; set; } + /// + /// 订单结算状态 0-未结算,1-已结算 + /// + public WeipinhuiOrderSettled settled { get; set; } + /// + /// 是否自推自买 0-否,1-是 + /// + public WeipinhuiShiFou selfBuy { get; set; } + /// + /// 订单子状态:流转状态-支持状态:(已下单、已付款、已签收、待结算、已结算、已失效) + /// + public string orderSubStatusName { get; set; } + /// + /// 商品总佣金:单位元 + /// + public string commission { get; set; } + /// + /// 售后订单佣金变动:仅在订单完结之后发生售后行为时返回 + /// + public string afterSaleChangeCommission { get; set; } + /// + /// 售后订单总商品数量变动:仅在订单完结之后发生售后行为时返回 + /// + public string afterSaleChangeGoodsCount { get; set; } + /// + /// 入账时间,时间戳,单位毫秒 + /// + public long commissionEnterTime { get; set; } + /// + /// 订单来源 + /// + public string orderSource { get; set; } + /// + /// 推广PID:目前等同于channelTag + /// + public string pid { get; set; } + /// + /// 是否预付订单:0-否,1-是 + /// + public WeipinhuiShiFou isPrepay { get; set; } + /// + /// 自定义统计参数 + /// + public string statParam { get; set; } + /// + /// 订单拆单标识: 0-否,1-是 + /// + public WeipinhuiShiFou isSplit { get; set; } + /// + /// 订单母单号:订单为拆单子单时返回 + /// + public string parentSn { get; set; } + /// + /// 订单归因方式:0-常规推广,1-惊喜红包,2-锁粉,3-超级红包 + /// + public WeipinhuiGuiYin orderTrackReason { get; set; } + /// + /// 开发者调用的appKey:当订单是通过开发者API推广成单时返回,其余时候返回为空 + /// + public string appKey { get; set; } + /// + /// 订单支付金额:单位元 + /// + public string totalCost { get; set; } + } + + /// + /// 订单数据 + /// + public class OrderResult + { + /// + /// 业绩总条数 + /// + public int total { get; set; } + /// + /// 当前页码 + /// + public int pageSize { get; set; } + /// + /// 页面大小 + /// + public int page { get; set; } + /// + /// 业绩查询响应结果 + /// + public List orderInfoList { get; set; } + } + + /// + /// 订单响应结果 + /// + public class OrderResponseResult + { + /// + /// 返回代码 + /// + public string returnCode { get; set; } + /// + /// 返回数据 + /// + public OrderResult result { get; set; } + } + #endregion + + #region 唯品会在推商品数据结构 + ///// + ///// 店铺信息 + ///// + //public class StoreInfo + //{ + // /// + // /// 店铺名字 + // /// + // public string storeName { get; set; } + // /// + // /// 店铺Id + // /// + // public string storeId { get; set; } + //} + + /// + /// 红包信息 + /// + public class CouponInfo + { + /// + /// 优惠券批次号 + /// + public string couponNo { get; set; } + /// + /// 优惠劵名称 + /// + public string couponName { get; set; } + /// + /// 使用门槛 + /// + public string buy { get; set; } + /// + /// 优惠金额 + /// + public string fav { get; set; } + /// + /// 券激活开始时间,毫秒级时间戳 + /// + public long activateBeginTime { get; set; } + /// + /// 券激活结束时间,毫秒级时间戳 + /// + public long activateEndTime { get; set; } + /// + /// 使用开始时间,毫秒级时间戳 + /// + public long useBeginTime { get; set; } + /// + /// 使用结束时间,毫秒级时间戳 + /// + public long useEndTime { get; set; } + /// + /// 生成劵的总量 + /// + public long totalAmount { get; set; } + /// + /// 劵已激活的数量 + /// + public int activedAmount { get; set; } + } + + /// + /// 精选商品列表 + /// + public class GoodsInfoList + { + /// + /// 商品id + /// + public string goodsId { get; set; } + /// + /// 商品名称 + /// + public string goodsName { get; set; } + /// + /// 商品描述,字段暂不输出 + /// + public string goodsDesc { get; set; } + /// + /// 商品落地页 + /// + public string destUrl { get; set; } + /// + /// 商品缩略图 + /// + public string goodsThumbUrl { get; set; } + /// + /// 商品轮播图:根据商品id查询时返回,商品列表不返回 + /// + public List goodsCarouselPictures { get; set; } + /// + /// 商品主图 + /// + public string goodsMainPicture { get; set; } + /// + /// 商品三级分类id + /// + public int categoryId { get; set; } + /// + /// 商品三级分类 + /// + public string categoryName { get; set; } + /// + /// 商品类型:0-自营,1-MP + /// + public int sourceType { get; set; } + /// + /// 市场价(元) + /// + public string marketPrice { get; set; } + /// + /// 唯品价(元) + /// + public string vipPrice { get; set; } + /// + /// 佣金比例(%) + /// + public string commissionRate { get; set; } + /// + /// 佣金金额(元) + /// + public string commission { get; set; } + /// + /// 折扣:唯品价/市场价 保留两位小数字符串 + /// + public string discount { get; set; } + /// + /// 商品详情图片:根据商品id查询商品信息时返回,商品列表不返回 + /// + public List goodsDetailPictures { get; set; } + /// + /// 商品一级分类id + /// + public int cat1stId { get; set; } + /// + /// 商品一级分类名称 + /// + public string cat1stName { get; set; } + /// + /// 商品二级分类id + /// + public int cat2ndId { get; set; } + /// + /// 商品二级分类名称 + /// + public string cat2ndName { get; set; } + /// + /// 商品品牌sn + /// + public string brandStoreSn { get; set; } + /// + /// 商品品牌名称 + /// + public string brandName { get; set; } + /// + /// 商品品牌logo全路径地址 + /// + public string brandLogoFull { get; set; } + /// + /// 商品推广计划有效期预估截止时间:仅为预估时间,仅做参考;时间戳,单位:毫秒 + /// + public long schemeEndTime { get; set; } + /// + /// 商品售卖开始时间,时间戳,单位毫秒 + /// + public long sellTimeFrom { get; set; } + /// + /// 商品售卖结束时间,时间戳, 单位毫秒 + /// + public long sellTimeTo { get; set; } + /// + /// 推广权重,用于确定推广该商品的优先级,权重值越大,优先级越高 + /// + public long weight { get; set; } + /// + /// 店铺信息 + /// + public StoreInfo storeInfo { get; set; } + /// + /// 商品所属档期(专场)id + /// + public int brandId { get; set; } + /// + /// 商品所属推广方案开始时间:时间戳,单位:毫秒 + /// + public long schemeStartTime { get; set; } + /// + /// 商品状态:0-下架,1-上架 + /// + public int status { get; set; } + /// + /// 红包信息 + /// + public CouponInfo couponInfo { get; set; } + /// + /// 是否海淘商品标识:1是 0不是 + /// + public int haiTao { get; set; } + /// + /// 商品spuId + /// + public string spuId { get; set; } + + } + + /// + /// 精选商品列表 + /// + public class GoodsInfoResult + { + /// + /// 总数 + /// + public int total { get; set; } + /// + /// 精选商品列表 + /// + public List goodsInfoList { get; set; } + /// + /// 分页大小 + /// + public int pageSize { get; set; } + /// + /// 支持的排序字段,为空时仅支持默认排序 + /// + public List sortFields { get; set; } + /// + /// 当前页码 + /// + public int page { get; set; } + } + + public class GoodsInfoResponseResult + { + public string returnCode { get; set; } + public GoodsInfoResult result { get; set; } + } + #endregion + + #region 唯品会 + /// + /// 商品预付信息 + /// + public class PrepayInfo + { + /// + /// 是否预付商品:0-否,1-是 + /// + public int isPrepay { get; set; } + /// + /// 预付到手价:元 + /// + public string prepayPrice { get; set; } + /// + /// 预付首款金额:元 + /// + public string firstAmount { get; set; } + /// + /// 预付尾款金额:元 + /// + public string lastAmount { get; set; } + /// + /// 预付优惠金额: 元 + /// + public string prepayFavAmount { get; set; } + /// + /// 抵扣价格(首款+优惠金额):元 + /// + public string deductionPrice { get; set; } + /// + /// 预付折扣:(唯品价-优惠金额)/唯品价 保留两位小数的数字字符串 + /// + public string prepayDiscount { get; set; } + /// + /// 首款支付开始时间:时间戳,单位毫秒 + /// + public long prepayFirstStartTime { get; set; } + /// + /// 首款支付结束时间:时间戳,单位毫秒 + /// + public long prepayFirstEndTime { get; set; } + /// + /// 尾款支付开始时间:时间戳,单位毫秒 + /// + public long prepayLastStartTime { get; set; } + /// + /// 尾款支付结束时间:时间戳,单位毫秒 + /// + public long prepayLastEndTime { get; set; } + } + + /// + /// 商品所属店铺服务能力评价 + /// + public class StoreServiceCapability + { + /// + /// 店铺评分:保留两位小数 + /// + public string storeScore { get; set; } + /// + /// 店铺同品类排名比例:例如10表示前10% + /// + public string storeRankRate { get; set; } + } + + /// + /// 商品评价信息 + /// + public class CommentsInfo + { + /// + /// 商品评论数 + /// + public int comments { get; set; } + /// + /// 商品好评率:百分比,不带百分号 + /// + public string goodCommentsShare { get; set; } + } + + /// + /// 店铺信息 + /// + public class StoreInfo + { + /// + /// 店铺名称 + /// + public string storeName { get; set; } + /// + /// 店铺id + /// + public string storeId { get; set; } + } + + /// + /// 商品参与活动信息:未参与活动集合为空 + /// + public class JoinedActivities + { + /// + /// 活动类型:18-唯品快抢 + /// + public int actType { get; set; } + /// + /// 活动名称 + /// + public string actName { get; set; } + /// + /// 开始时间:时间戳,单位毫秒 + /// + public long beginTime { get; set; } + /// + /// 结束时间:时间戳,单位毫秒 + /// + public long endTime { get; set; } + /// + /// 预热开始时间:时间戳,单位毫秒 + /// + public long foreShowBeginTime { get; set; } + + } + + /// + /// 红包信息 + /// + public class CouponInfo1 + { + /// + /// 优惠券批次号 + /// + public string couponNo { get; set; } + /// + /// 优惠券名称 + /// + public string couponName { get; set; } + /// + /// 使用门槛 + /// + public string buy { get; set; } + /// + /// 优惠券金额 + /// + public string fav { get; set; } + /// + /// 券激活开始时间, 毫秒级时间戳 + /// + public long activateBeginTime { get; set; } + /// + /// 券激活结束时间, 毫秒级时间戳 + /// + public long activateEndTime { get; set; } + //使用开始时间,毫秒级时间戳 + public long useBeginTime { get; set; } + /// + /// 使用结束时间,毫秒级时间戳 + /// + public long useEndTime { get; set; } + /// + /// 生成劵的总量 + /// + public long totalAmount { get; set; } + /// + /// 劵已激活的数量 + /// + public long activedAmount { get; set; } + } + + /// + /// 对应sku信息 + /// + public class SkuInfos + { + /// + /// 商品尺码id(唯品会体系下和skuId等同) + /// + public string sizeId { get; set; } + /// + /// 售卖属性信息(134 - 颜色,453 - 尺码) + /// + public Dictionary saleProps { get; set; } + /// + /// 剩余库存:查询库存时返回 + /// + public int leavingStock { get; set; } + /// + /// 商品库存状态:1-已抢光,2-有库存,3-有机会 + /// + public int saleStockStatus { get; set; } + /// + /// 唯品价:单位元 + /// + public string vipPrice { get; set; } + /// + /// 市场价:单位元 + /// + public string marketPrice { get; set; } + + } + + /// + /// 渠道专属红包:目前仅开放单品券,没有则返回空 + /// + public class ExclusiveCoupon + { + /// + /// 优惠券批次号 + /// + public string couponNo { get; set; } + + /// + /// 优惠劵名称 + /// + public string couponName { get; set; } + + /// + /// 优惠金额:单位-元,查询详情时返回 + /// + public string fav { get; set; } + + /// + /// 使用门槛:单位-元,查询详情时返回 + /// + public string buy { get; set; } + + /// + /// 券激活开始时间,毫秒级时间戳 + /// + public long activateBeginTime { get; set; } + + /// + /// 券激活结束时间,毫秒级时间戳 + /// + public long activateEndTime { get; set; } + + /// + /// 使用开始时间,毫秒级时间戳 + /// + public long useBeginTime { get; set; } + + /// + /// 使用结束时间,毫秒级时间戳 + /// + public long useEndTime { get; set; } + + /// + /// 生成劵的总量:查询详情时返回 + /// + public long totalAmount { get; set; } + + /// + /// 劵已激活的数量:查询详情时返回 + /// + public long activedAmount { get; set; } + + /// + /// 专属领券页地址 + /// + public string receiveUrl { get; set; } + + } + + /// + /// 唯品会商品查询详情结果 + /// + public class WphGoodsInfoResult + { + /// + /// 商品id + /// + public string goodsId { get; set; } + /// + /// 商品名称 + /// + public string goodsName { get; set; } + /// + /// 商品描述,字段暂不输出 + /// + public string goodsDesc { get; set; } + /// + /// 商品落地页 + /// + public string destUrl { get; set; } + /// + /// 商品缩略图 + /// + public string goodsThumbUrl { get; set; } + /// + /// 商品轮播图:根据商品id查询时返回,商品列表不返回 + /// + public List goodsCarouselPictures { get; set; } + /// + /// 商品主图 + /// + public string goodsMainPicture { get; set; } + /// + /// 商品三级分类id + /// + public long categoryId { get; set; } + /// + /// 商品三级分类 + /// + public string categoryName { get; set; } + /// + /// 商品类型:0-自营,1-MP + /// + public int sourceType { get; set; } + /// + /// 市场价(元) + /// + public string marketPrice { get; set; } + /// + /// 唯品价(元) + /// + public string vipPrice { get; set; } + /// + /// 佣金比例(%) + /// + public string commissionRate { get; set; } + /// + /// 佣金金额(元) + /// + public string commission { get; set; } + /// + /// 折扣:唯品价/市场价 保留两位小数字符串 + /// + public string discount { get; set; } + /// + /// 商品详情图片:根据商品id查询商品信息时返回,商品列表不返回 + /// categoryName + public List goodsDetailPictures { get; set; } + /// + /// 商品一级分类id + /// + public long cat1stId { get; set; } + /// + /// 商品一级分类名称 + /// + public string cat1stName { get; set; } + /// + /// 商品二级分类id + /// + public long cat2ndId { get; set; } + /// + /// 商品二级分类名称 + /// + public string cat2ndName { get; set; } + /// + /// 商品品牌sn + /// + public string brandStoreSn { get; set; } + /// + /// 商品品牌名称 + /// + public string brandName { get; set; } + /// + /// 商品品牌logo全路径地址 + /// + public string brandLogoFull { get; set; } + /// + /// 商品推广计划有效期预估截止时间:仅为预估时间,仅做参考;时间戳,单位:毫秒 + /// + public long schemeEndTime { get; set; } + /// + /// 商品售卖开始时间,时间戳,单位毫秒 + /// + public long sellTimeFrom { get; set; } + /// + /// 商品售卖结束时间,时间戳, 单位毫秒 + /// + public long sellTimeTo { get; set; } + /// + /// 推广权重,用于确定推广该商品的优先级,权重值越大,优先级越高 + /// + public int weight { get; set; } + /// + /// 店铺信息 + /// + public StoreInfo storeInfo { get; set; } + /// + /// 商品评价信息 + /// + public CommentsInfo commentsInfo { get; set; } + /// + /// 商品所属店铺服务能力评价 + /// + public StoreServiceCapability storeServiceCapability { get; set; } + /// + /// 商品所属档期(专场)id + /// + public long brandId { get; set; } + /// + /// 商品所属推广方案开始时间:时间戳,单位:毫秒 + /// + public long schemeStartTime { get; set; } + /// + /// 商品库存状态:1-已抢光,2-有库存,3-有机会,当列表查询库存或者查询商品详情时返回 + /// + public int saleStockStatus { get; set; } + /// + /// 商品状态:0-下架,1-上架 + /// + public int status { get; set; } + /// + /// 商品预付信息 + /// + public PrepayInfo prepayInfo { get; set; } + /// + /// 商品参与活动信息:未参与活动集合为空 + /// + public List joinedActivities { get; set; } + /// + /// 红包信息 + /// + public CouponInfo1 couponInfo { get; set; } + /// + /// 是否海淘商品标识:1是 0不是 + /// + public int haiTao { get; set; } + /// + /// 商品spuId + /// + public string spuId { get; set; } + /// + /// 同spuId扩展商品id: 新版详情接口返回,其余接口不返回该字段 + /// + public List goodsIdsWithSameSpu { get; set; } + /// + /// 对应sku信息 + /// + public SkuInfos skuInfos { get; set; } + + /// + /// 渠道专属红包:目前仅开放单品券,没有则返回空 + /// + public ExclusiveCoupon exclusiveCoupon { get; set; } + + /// + /// cps推广信息:目前只返回小程序链接和通用追踪参数,其他链接请移步转链接口,1-通用推广参数(tra_from),2-唯品会微信小程序链接 + /// + public Dictionary cpsInfo { get; set; } + + } + + public class WphGoodsInfo + { + public string returnCode { get; set; } + public List result { get; set; } + } + #endregion + + #endregion + +} diff --git a/类库/Api.Framework/Tools/WechatPay.cs b/类库/Api.Framework/Tools/WechatPay.cs new file mode 100644 index 0000000..1a09530 --- /dev/null +++ b/类库/Api.Framework/Tools/WechatPay.cs @@ -0,0 +1,355 @@ +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + /// + /// 商户支付类 + /// + public class WechatPay + { + public WechatPay() + { + + } + private string wechat_pay_url = "http://wxpay.api.52cmg.cn"; + private const int wechat_appid = 85599; + private const string wechat_appkey = "vssNGL91TxssqPHsOek+febRdhhPDf5BwIAO2S/jr0kGsFJIrG1IbG7Y73kM14h+71q1KepvUSG6ngSvZzHxQsBNSUFWd0/kOqjTJp5az5CssPEZOE+5Y9JyOQQ6P6QijdhSxtGSrJt3RLKAeQGbEnc5lU5WB8g1zgIODrLzRQ0=AQAB"; + + /// + /// 请求服务器 + /// + /// + /// + /// + private WebResult SendServer(string method, object param = null) + { + AuthEndpoint end = new AuthEndpoint() + { + Appid = wechat_appid, + Enckey = wechat_appkey, + Host = wechat_pay_url + "/api/pay.asmx/send_data", + Method = method + }; + if (param != null) + { + var _param = param.GetType().GetProperties(); + foreach (var item in _param) + { + end.Param[item.Name] = item.GetValue(param); + } + } + HttpHelper http = new HttpHelper(); + return http.SendData(end); + } + + /// + /// 商户数据上传 + /// + /// + /// + /// + /// + /// + /// + /// + /// + public string Upload(string url, string gzh_appid, string gzh_appsecret, string sh_appid, string sh_appsecret, byte[] sh_cerdata, string footer) + { + if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(gzh_appid) || string.IsNullOrEmpty(sh_appid)) throw new Exception("商户填写的数据信息不完整!"); + var hex_data = HttpExtend.ByteToHex(sh_cerdata); + var result = SendServer("upload_shop", new { url = url, gzh_appid = gzh_appid, gzh_appsecret = gzh_appsecret, sh_appid = sh_appid, sh_appsecret = sh_appsecret, sh_cerdata = hex_data, footer = footer }); + return result.message.ToString(); + } + const string rsa_key = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgPPwyc5JAbPRjkulZcat/JAYm +/eiPRhtyod1CmqLteE1v90HCPoLwejkrmUToRsaJKKOgObKdh/t3Od/41RBc3rJw +S4uX8VXqsq/VcLWh/GiieCNYqpb/7Chp7tfW7Sp+eyA/reT9LHRg27hLYfkhmu9f +eFGAS17iICAyv3jpUwIDAQAB"; + + /// + /// 商户创建 + /// + /// 商户地址 + /// 备注 + /// 描述 + /// 金额 + /// + [Obsolete("改方法已过时")] + public string Create(string url, object remark, string describe, double money) + { + var post = string.Empty;// "amount=[金额]&describe=[描述]&remark=[备注]".Replace("[金额]", money.ToString()).Replace("[描述]", HttpHelper.URLEncode(describe)).Replace("[备注]", HttpHelper.URLEncode(HttpHelper.ObjectToJson(remark))); + + var http = new HttpHelper(); + url = url.Replace("[金额]", money.ToString()).Replace("[描述]", HttpHelper.URLEncode(describe, Encoding.UTF8)).Replace("[备注]", HttpHelper.URLEncode(HttpHelper.ObjectToJson(remark), Encoding.UTF8)); + //if (url.StartsWith("https://pay.api.52cmg.cn")) + //{ + // RSACryption rsa = new RSACryption(); + // var request_data = rsa.RsaEncrypt(HttpHelper.ObjectToJson(new + // { + // money = money, + // describe = describe, + // remark = remark + // }),rsa_key); + //} + + var item = http.GetItem(url); + item.Encoding = Encoding.UTF8; + var data = http.GetHtml(item); + var result = data.Html; + var json = HttpExtend.JsonToDictionary(result); + if (json != null && json.ContainsKey("code")) + { + var code = int.Parse(json["code"].ToString()); + if (code == 1) + { + var ispaid = false; + var msg = string.Empty; + if (json.ContainsKey("message")) + msg = json["message"].ToString(); + else if (json.ContainsKey("msg")) + msg = json["msg"].ToString(); + if (json.ContainsKey("ispaid")) + ispaid = json["ispaid"].ToString().ToUpper() == "TRUE"; + return msg; + } + //else if (code == 2) + //{ + // return "已转账"; + //} + else EventClient.OnEvent(this, $"生成兑换链接失败:{json["msg"].ToString()}"); + } + else EventClient.OnEvent(this, $"生成兑换链接失败:{result}"); + + return string.Empty; + } + + /// + /// 商户创建 + /// + /// 商户地址 + /// 备注 + /// 描述 + /// 金额 + /// 是否直接到账 + /// + public string Create(string url, object remark, string describe, double money, out bool ispaid) + { + var html = string.Empty; + try + { + var post = string.Empty;// "amount=[金额]&describe=[描述]&remark=[备注]".Replace("[金额]", money.ToString()).Replace("[描述]", HttpHelper.URLEncode(describe)).Replace("[备注]", HttpHelper.URLEncode(HttpHelper.ObjectToJson(remark))); + + var http = new HttpHelper(); + url = url.Replace("[金额]", money.ToString("0.00")).Replace("[描述]", HttpHelper.URLEncode(describe, Encoding.UTF8)).Replace("[备注]", HttpHelper.URLEncode(HttpHelper.ObjectToJson(remark), Encoding.UTF8)); + //if (url.StartsWith("https://pay.api.52cmg.cn")) + //{ + // RSACryption rsa = new RSACryption(); + // var request_data = rsa.RsaEncrypt(HttpHelper.ObjectToJson(new + // { + // money = money, + // describe = describe, + // remark = remark + // }),rsa_key); + //} + + ispaid = false; + var item = http.GetItem(url); + item.Timeout = 30000; + item.ReadWriteTimeout = 20000; + item.Encoding = Encoding.UTF8; + var data = http.GetHtml(item); + html = data.Html; + var json = HttpExtend.JsonToDictionary(html); + if (json != null && json.ContainsKey("code")) + { + var code = int.Parse(json["code"].ToString()); + if (code == 1) + { + var msg = string.Empty; + if (json.ContainsKey("message")) + msg = json["message"]?.ToString(); + else if (json.ContainsKey("msg")) + msg = json["msg"]?.ToString(); + + if (json.ContainsKey("ispaid")) + ispaid = json["ispaid"]?.ToString().ToUpper() == "TRUE"; + return msg; + } + else + { + var msg = string.Empty; + if (json.ContainsKey("msg")) + msg = json["msg"]?.ToString(); + else if (json.ContainsKey("message")) + msg = json["message"]?.ToString(); + + EventClient.OnEvent(this, $"生成商户兑换链接失败:{msg}"); + } + } + else + EventClient.OnEvent(this, $"生成商户兑换链接失败:{html}"); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"生成兑换链接失败:{html} - {ex.Message}"); + } + ispaid = false; + return string.Empty; + } + + /// + /// 商户创建 + /// + /// 商户地址 + /// 备注 + /// 描述 + /// 金额 + /// 是否直接到账 + /// 小程序信息,微信可以用来发送小程序;不支持小程序返回null + /// + public string Create(string url, object remark, string describe, double money, out bool ispaid, out object appinfo) + { + var html = string.Empty; + appinfo = null; + try + { + var post = string.Empty;// "amount=[金额]&describe=[描述]&remark=[备注]".Replace("[金额]", money.ToString()).Replace("[描述]", HttpHelper.URLEncode(describe)).Replace("[备注]", HttpHelper.URLEncode(HttpHelper.ObjectToJson(remark))); + + var http = new HttpHelper(); + url = url.Replace("[金额]", money.ToString("0.00")).Replace("[描述]", HttpHelper.URLEncode(describe, Encoding.UTF8)).Replace("[备注]", HttpHelper.URLEncode(HttpHelper.ObjectToJson(remark), Encoding.UTF8)); + //if (url.StartsWith("https://pay.api.52cmg.cn")) + //{ + // RSACryption rsa = new RSACryption(); + // var request_data = rsa.RsaEncrypt(HttpHelper.ObjectToJson(new + // { + // money = money, + // describe = describe, + // remark = remark + // }),rsa_key); + //} + + ispaid = false; + var item = http.GetItem(url); + item.Timeout = 30000; + item.ReadWriteTimeout = 20000; + item.Encoding = Encoding.UTF8; + var data = http.GetHtml(item); + html = data.Html; + + //{"code":1,"msg":"https://ygh8i.kuaizhan.com/52/52/p825791697c346b?orderid=e8255ae1e8d928555d61de464d73af75\u0026appid=wx6e0df44505ec10f5","appinfo":null,"aliUrl":"https://ulink.alipay.com/?scheme=alipays%3A%2F%2Fplatformapi%2Fstartapp%3FsaId%3D10000007%26clientVersion%3D3.7.0.0718%26qrcode%3Dhttps%3A%2F%2Fpay.api.52cmg.cn%2Falipay%3Forderid%3De8255ae1e8d928555d61de464d73af75"} + + var json = HttpExtend.JsonToDictionary(html); + if (json != null && json.ContainsKey("code")) + { + var code = int.Parse(json["code"].ToString()); + if (code == 1) + { + var msg = string.Empty; + if (json.ContainsKey("message")) + msg = json["message"]?.ToString(); + else if (json.ContainsKey("msg")) + msg = json["msg"]?.ToString(); + + if (json.ContainsKey("ispaid")) + ispaid = json["ispaid"]?.ToString().ToUpper() == "TRUE"; + + if (json.ContainsKey("appinfo")) + appinfo = json["appinfo"]; + + return msg; + } + else + { + var msg = string.Empty; + if (json.ContainsKey("msg")) + msg = json["msg"]?.ToString(); + else if (json.ContainsKey("message")) + msg = json["message"]?.ToString(); + + EventClient.OnEvent(this, $"生成商户兑换链接失败:{msg}"); + } + } + else + EventClient.OnEvent(this, $"生成商户兑换链接失败:{html}"); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"生成兑换链接失败:{html} - {ex.Message}"); + } + ispaid = false; + return string.Empty; + } + + /// + /// + /// + /// + /// + /// + /// + /// + public string Create2(string url, object remark, string describe, double money) + { + var html = string.Empty; + try + { + var http = new HttpHelper(); + url = url.Replace("[金额]", ((int)(money * 100)).ToString()).Replace("[描述]", HttpHelper.URLEncode(describe, Encoding.UTF8)).Replace("[备注]", HttpHelper.URLEncode(HttpHelper.ObjectToJson(remark), Encoding.UTF8)); + + var item = http.GetItem(url); + item.Timeout = 30000; + item.ReadWriteTimeout = 20000; + item.Encoding = Encoding.UTF8; + var data = http.GetHtml(item); + html = data.Html; + var jObj = JObject.Parse(html); + if (jObj != null && jObj["code"] != null) + { + if ((int)jObj["code"] == 1) + { + var msg = jObj["data"]["withdraw_url"]?.ToString(); + return msg; + } + else + EventClient.OnEvent(this, $"生成商户兑换链接失败1:{html}"); + } + else + EventClient.OnEvent(this, $"生成商户兑换链接失败2:{html}"); + } + catch (Exception ex) + { + EventClient.OnEvent(this, $"生成兑换链接失败3:{html} - {ex.Message}"); + } + return string.Empty; + } + + /// + /// 商户创建 + /// + /// 公众号appid + /// 商户appid + /// 公众号appkey + /// 商户appkey + /// 金额 + /// 备注 + /// 描述 + /// + public string Create(string gzh_appid, string sh_appid, string gzh_appkey, string sh_appkey, double amount, string remark, string describe) + { + if (string.IsNullOrEmpty(gzh_appid) || string.IsNullOrEmpty(sh_appid)) throw new Exception("商户填写的数据信息不完整!"); + var password = HttpExtend.GetMD5String(gzh_appkey + sh_appkey); + var result = SendServer("create_order", new { gzh_appid = gzh_appid, sh_appid = sh_appid, amount = amount.ToString("0.00"), remark = remark, describe = describe, password = password }); + return result.message.ToString(); + } + + + + + } +} diff --git a/类库/Api.Framework/Tools/Zip.cs b/类库/Api.Framework/Tools/Zip.cs new file mode 100644 index 0000000..5a59169 --- /dev/null +++ b/类库/Api.Framework/Tools/Zip.cs @@ -0,0 +1,312 @@ +using ICSharpCode.SharpZipLib.Zip; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Api.Framework.Tools +{ + public class Zip + { + + /// + /// 根据给的文件参数,自动进行压缩或解压缩操作 + /// + public static void Process(String[] files, String Password = null) + { + if (files.Length > 0) + { + if (files.Length == 1 && (files[0].ToLower().EndsWith(".zip") || files[0].ToLower().EndsWith(".rar"))) + { + unzip(files[0], null, Password, null); // 解压缩 + } + else + { + String zipPath = Tools.getPathNoExt(files[0]) + ".zip"; // 以待压缩的第一个文件命名生成的压缩文件 + String BaseDir = Tools.getParent(files[0]); // 获取第一个文件的父路径信息 + if (files.Length == 1) // 若载入的为单个目录,则已当前目录作为基础路径 + { + String file = files[0]; + if (Directory.Exists(file)) BaseDir = file + "\\"; + } + + String[] subFiles = Tools.getSubFiles(files); // 获取args对应的所有目录下的文件列表 + zip(zipPath, BaseDir, subFiles, Password, null); // 对载入的文件进行压缩操作 + } + } + } + + /// + /// 压缩所有文件files,为压缩文件zipFile, 以相对于BaseDir的路径构建压缩文件子目录,ignoreNames指定要忽略的文件或目录 + /// + public static bool zip(String zipPath, String BaseDir, String[] files, String Password = null, String[] ignoreNames = null) + { + if (files == null || files.Length == 0) return false; + if (zipPath == null || zipPath.Equals("")) zipPath = Tools.getPathNoExt(files[0]) + ".zip"; // 默认以第一个文件命名压缩文件 + if (BaseDir == null || BaseDir.Equals("")) BaseDir = Tools.getParent(files[0]); // 默认以第一个文件的父目录作为基础路径 + //Console.WriteLine("所有待压缩文件根目录:" + BaseDir); + + try + { + Tools.mkdirs(Tools.getParent(zipPath)); // 创建目标路径 + //Console.WriteLine("创建压缩文件:" + zipPath); + + FileStream input = null; + ZipOutputStream zipStream = new ZipOutputStream(File.Create(zipPath)); + if (Password != null && !Password.Equals("")) zipStream.Password = Password; + + files = Tools.getSubFiles(files); // 获取子目录下所有文件信息 + for (int i = 0; i < files.Length; i++) + { + if (ContainsIgnoreName(files[i], ignoreNames)) continue; // 跳过忽略的文件或目录 + + String entryName = Tools.relativePath(BaseDir, files[i]); + zipStream.PutNextEntry(new ZipEntry(entryName)); + //Console.WriteLine("添加压缩文件:" + entryName); + + if (File.Exists(files[i])) // 读取文件内容 + { + input = File.OpenRead(files[i]); + Random rand = new Random(); + byte[] buffer = new byte[10240]; + int read = 0; + while ((read = input.Read(buffer, 0, 10240)) > 0) + { + zipStream.Write(buffer, 0, read); + } + input.Close(); + } + } + zipStream.Close(); + //Console.WriteLine("文件压缩完成!"); + + return true; + } + catch (Exception ex) + { + //Console.WriteLine(ex.ToString()); + } + + return false; + } + + /// + /// 解压文件 到指定的路径,可通过targeFileNames指定解压特定的文件 + /// + public static bool unzip(String zipPath, String targetPath = null, String Password = null, String[] targeFileNames = null) + { + if (File.Exists(zipPath)) + { + if (targetPath == null || targetPath.Equals("")) targetPath = Tools.getPathNoExt(zipPath); + //Console.WriteLine("解压文件:" + zipPath); + //Console.WriteLine("解压至目录:" + targetPath); + + try + { + ZipInputStream zipStream = null; + FileStream bos = null; + + zipStream = new ZipInputStream(File.OpenRead(zipPath)); + if (Password != null && !Password.Equals("")) zipStream.Password = Password; + + ZipEntry entry = null; + while ((entry = zipStream.GetNextEntry()) != null) + { + if (targeFileNames != null && targeFileNames.Length > 0) // 若指定了目标解压文件 + { + if (!ContainsIgnoreName(entry.Name, targeFileNames)) continue; // 跳过非指定的文件 + } + + String target = targetPath + "\\" + entry.Name; + if (entry.IsDirectory) Tools.mkdirs(target); // 创建目标路径 + if (entry.IsFile) + { + Tools.mkdirs(Tools.getParent(target)); + + bos = File.Create(target); + //Console.WriteLine("解压生成文件:" + target); + + int read = 0; + byte[] buffer = new byte[10240]; + while ((read = zipStream.Read(buffer, 0, 10240)) > 0) + { + bos.Write(buffer, 0, read); + } + bos.Flush(); + bos.Close(); + } + } + zipStream.CloseEntry(); + + //Console.WriteLine("解压完成!"); + return true; + } + catch (Exception ex) + { + //Console.WriteLine(ex.ToString()); + } + } + return false; + } + + /// + /// 判断fileName中是否含有ignoreNames中的某一项 + /// + private static bool ContainsIgnoreName(String fileName, String[] ignoreNames) + { + if (ignoreNames != null && ignoreNames.Length > 0) + { + foreach (string name in ignoreNames) + { + if (fileName.Contains(name)) return true; + } + } + return false; + } + + } + + /// + /// 通用功能函数 + /// + public class Tools + { + /// + /// 检测目录是否存在,若不存在则创建 + /// + public static void mkdirs(string path) + { + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + } + + /// + /// 获取去除拓展名的文件路径 + /// + public static String getPathNoExt(String path) + { + if (File.Exists(path)) return Directory.GetParent(path).FullName + "\\" + Path.GetFileNameWithoutExtension(path); + else return Directory.GetParent(path).FullName + "\\" + Path.GetFileName(path); + } + + /// + /// 获取父目录的路径信息 + /// + public static String getParent(String path) + { + return System.IO.Directory.GetParent(path).FullName + "\\"; + } + + + /// + /// 获取父目录的路径信息 + /// + public static String getFileName(String path) + { + return System.IO.Path.GetFileName(path); + } + + /// + /// 获取filePath的相对于BaseDir的路径 + /// + public static String relativePath(String BaseDir, String filePath) + { + String relativePath = ""; + if (filePath.StartsWith(BaseDir)) relativePath = filePath.Substring(BaseDir.Length); + return relativePath; + } + + /// + /// 获取paths路径下所有文件信息 + /// + public static String[] getSubFiles(String[] Paths) + { + List list = new List(); // paths路径下所有文件信息 + + foreach (String path in Paths) + { + List subFiles = getSubFiles(path); // 获取路径path下所有文件列表信息 + list = ListAdd(list, subFiles); + } + + String[] A = List2Array(list); // 转化为数组形式 + + return A; + } + + /// + /// 合并list1和list2到新的list + /// + public static List ListAdd(List list1, List list2) + { + List list = new List(); + + foreach (String path in list1) if (!list.Contains(path)) list.Add(path); + foreach (String path in list2) if (!list.Contains(path)) list.Add(path); + + return list; + } + + /// + /// 获取file目录下所有文件列表 + /// + public static List getSubFiles(String file) + { + List list = new List(); + + if (File.Exists(file)) + { + if (!list.Contains(file)) list.Add(file); + } + + if (Directory.Exists(file)) + { + // 获取目录下的文件信息 + foreach (String iteam in Directory.GetFiles(file)) + { + if (!list.Contains(iteam)) list.Add(iteam); + } + + // 获取目录下的子目录信息 + foreach (String iteam in Directory.GetDirectories(file)) + { + List L = getSubFiles(iteam); // 获取子目录下所有文件列表 + foreach (String path in L) + { + if (!list.Contains(path)) list.Add(path); + } + } + + // 记录当前目录 + if (Directory.GetFiles(file).Length == 0 && Directory.GetDirectories(file).Length == 0) + { + if (!list.Contains(file)) list.Add(file + "\\"); + } + } + + return list; + } + + /// + /// 转化list为数组 + /// + public static String[] List2Array(List list) + { + int size = (list == null ? 0 : list.Count); + String[] A = new String[size]; + + int i = 0; + foreach (String S in list) + { + A[i++] = S; + } + + return A; + } + + } +} diff --git a/类库/Api.Framework/Tools/ZipHelper.cs b/类库/Api.Framework/Tools/ZipHelper.cs new file mode 100644 index 0000000..a35120d --- /dev/null +++ b/类库/Api.Framework/Tools/ZipHelper.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.IO.Compression; +using System.Data; + +namespace Api.Framework.Tools +{ + public class ZipHelper + { + /// + /// 解压 + /// + /// + /// + public static DataSet GetDatasetByString(string Value) + { + DataSet ds = new DataSet(); + string CC = GZipDecompressString(Value); + System.IO.StringReader Sr = new StringReader(CC); + ds.ReadXml(Sr); + return ds; + } + /// + /// 根据DATASET压缩字符串 + /// + /// + /// + public static string GetStringByDataset(string ds) + { + return GZipCompressString(ds); + } + /// + /// 将传入字符串以GZip算法压缩后,返回Base64编码字符 + /// + /// 需要压缩的字符串 + /// 压缩后的Base64编码的字符串 + public static string GZipCompressString(string rawString) + { + if (string.IsNullOrEmpty(rawString) || rawString.Length == 0) + { + return ""; + } + else + { + byte[] rawData = System.Text.Encoding.UTF8.GetBytes(rawString.ToString()); + byte[] zippedData = Compress(rawData); + return (string)(Convert.ToBase64String(zippedData)); + } + + } + /// + /// GZip压缩 + /// + /// + /// + public static byte[] Compress(byte[] rawData) + { + MemoryStream ms = new MemoryStream(); + GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Compress, true); + compressedzipStream.Write(rawData, 0, rawData.Length); + compressedzipStream.Close(); + return ms.ToArray(); + } + /// + /// 将传入的二进制字符串资料以GZip算法解压缩 + /// + /// 经GZip压缩后的二进制字符串 + /// 原始未压缩字符串 + public static string GZipDecompressString(string zippedString) + { + if (string.IsNullOrEmpty(zippedString) || zippedString.Length == 0) + { + return ""; + } + else + { + byte[] zippedData = Convert.FromBase64String(zippedString.ToString()); + return (string)(System.Text.Encoding.UTF8.GetString(Decompress(zippedData))); + } + } + /// + /// ZIP解压 + /// + /// + /// + public static byte[] Decompress(byte[] zippedData) + { + MemoryStream ms = new MemoryStream(zippedData); + GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Decompress); + MemoryStream outBuffer = new MemoryStream(); + byte[] block = new byte[1024 * 10]; + while (true) + { + int bytesRead = compressedzipStream.Read(block, 0, block.Length); + if (bytesRead <= 0) + break; + else + outBuffer.Write(block, 0, bytesRead); + } + compressedzipStream.Close(); + return outBuffer.ToArray(); + } + } +} diff --git a/类库/Api.Framework/Tools/h5Top - 复制.cs b/类库/Api.Framework/Tools/h5Top - 复制.cs new file mode 100644 index 0000000..e6893c1 --- /dev/null +++ b/类库/Api.Framework/Tools/h5Top - 复制.cs @@ -0,0 +1,723 @@ +using Api.Framework.Cps; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using static Api.Framework.Tools.TBHelper; + +namespace Api.Framework.Tools +{ + public class h5Top + { + #region h5Top Code + private string _cookies = string.Empty; + private string Cookies + { + get + { + if (string.IsNullOrEmpty(_cookies)) + { + //HttpHelper http = new HttpHelper(); + //string cookies = http.GetHtml(new HttpItem() { URL = "http://api.m.taobao.com/h5/mtop.alimama.union.hsf.coupon.get/1.0/?v=1.0&api=mtop.alimama.union.hsf.coupon.get&appKey=12574478&t=1521082116428&callback=mtopjsonp1&type=jsonp&sign=e102e09c3da2505790412f4b5904cfec&data=%7B%22e%22%3A%22kKwRS8jKFeIGQASttHIRqX4ccS%252BmEB0fPkvI%252B9vDGidk3qypIGt1zv02HjWWzK8QrVVJXxMdEXoJP%252FpVy45HN79fwBwwUiqlbZt%252F%252F9VQxkYKu2xm%252BXzUVW7PVn13QcLNcISolD8QJ4rvZt%252BicRrQwg%253D%253D%22%2C%22pid%22%3A%22mm_96747532_17602904_63786428%22%7D" }).Cookie; + //_cookies = HttpHelper.GetSmallCookie(cookies); + + HttpHelper http = new HttpHelper(); + //string cookies = http.GetHtml(new HttpItem() { URL = "http://api.m.taobao.com/h5/mtop.alimama.union.hsf.coupon.get/1.0/?v=1.0&api=mtop.alimama.union.hsf.coupon.get&appKey=12574478&t=1521082116428&callback=mtopjsonp1&type=jsonp&sign=e102e09c3da2505790412f4b5904cfec&data=%7B%22e%22%3A%22kKwRS8jKFeIGQASttHIRqX4ccS%252BmEB0fPkvI%252B9vDGidk3qypIGt1zv02HjWWzK8QrVVJXxMdEXoJP%252FpVy45HN79fwBwwUiqlbZt%252F%252F9VQxkYKu2xm%252BXzUVW7PVn13QcLNcISolD8QJ4rvZt%252BicRrQwg%253D%253D%22%2C%22pid%22%3A%22mm_96747532_17602904_63786428%22%7D" }).Cookie; + //_cookies = HttpHelper.GetSmallCookie(cookies); + + string _m_h5_tk, t, reCookie = ""; + var referer = "https://www.taobao.com"; + var api = "com.taobao.redbull.getpassworddetail"; + if (string.IsNullOrEmpty(_cookies)) + { + var tempUrl = $"https://api.m.taobao.com/h5/{api}/1.0/?appKey={appKey}&api={api}&v=1.0&t=&sign="; + string cookies = http.GetHtml(new HttpItem() + { + URL = tempUrl + }).Cookie; + _cookies = HttpHelper.GetSmallCookie(cookies); + //_cookies = cookies;//HttpHelper.GetSmallCookie(cookies); + } + + } + return _cookies; + } + set { _cookies = value; } + } + + const string appKey = "12574478"; + + public static string GetCookiesValue(string key, string cookies) + { + if (string.IsNullOrEmpty(cookies)) return string.Empty; + string[] tempCookies = cookies.Split(';'); + foreach (var item in tempCookies) + { + string[] tempCookie = item.Split('='); + if (tempCookie.Length == 2) + { + if (tempCookie[0].Trim() == key) + { + return tempCookie[1].Split('_')[0]; + } + } + + } + + + return string.Empty; + + } + private static string GetbyteToString(byte[] data) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < data.Length; i++) + { + sb.Append(data[i].ToString("x2")); + } + return sb.ToString(); + } + private static string GetMD5String(string str) + { + MD5 md5 = MD5.Create(); + byte[] data = Encoding.UTF8.GetBytes(str); + byte[] data2 = md5.ComputeHash(data); + + return GetbyteToString(data2); + //return BitConverter.ToString(data2).Replace("-", "").ToLower(); + } + private static string URLEncode(string str) + { + StringBuilder builder = new StringBuilder(); + foreach (char c in str) + { + if (HttpUtility.UrlEncode(c.ToString()).Length > 1) + { + builder.Append(HttpUtility.UrlEncode(c.ToString()).ToUpper()); + } + else + { + builder.Append(c); + } + } + return builder.ToString(); + } + public Dictionary M_GET(string api, object data, string version = "1.0") + { + + int number = 3; + Next: + number--; + string time = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString(); + string mh5Tk = GetCookiesValue("_m_h5_tk", Cookies); + mh5Tk = string.IsNullOrEmpty(mh5Tk) ? "f64aa152f943661f750e6212ebc98804_1481170439770" : mh5Tk; + string json = (data.GetType() == typeof(string)) ? data.ToString() : HttpHelper.ObjectToJson(data).Replace("\\u0026", "&"); + string temp_ = mh5Tk + "&" + time + "&" + appKey + "&" + json; + + string sign = GetMD5String(temp_); ; + string send = HttpHelper.URLEncode(json); + string temp = string.Format("http://api.m.taobao.com/h5/{5}/{4}/?v={4}&api={5}&appKey={0}&t={1}&callback=mtopjsonp1&type=jsonp&sign={2}&data={3}", appKey, time, sign, send, version, api); + string html = string.Empty; + //if (api == "mtop.taobao.baichuan.smb.get") + if (api.StartsWith("mtop") || api == "mtop.alimama.union.xt.biz.quan.api.entry" || api == "mtop.taobao.sharepassword.querypassword") + { + //temp = $"https://h5api.m.taobao.com/h5/{api}/{version}/?jsv=2.4.0&appKey={appKey}&t={time}&sign={sign}&api={api}&v={version}&type=originaljson&dataType=jsonp&timeout=10000"; + temp = $"https://h5api.m.taobao.com/h5/{api}/{version}/?jsv=2.4.0&appKey={appKey}&t={time}&sign={sign}&api={api}&v={version}&timeout=20000&AntiCreep=true&AntiFlood=true&type=jsonp&dataType=jsonp&callback=mtopjsonp2&data={send}"; + //html = M_POST_HTML(temp, "data=" + send); + html = M_GET_HTML(temp).Trim(); + Console.WriteLine(html); + } + else + { + html = M_GET_HTML(temp).Trim(); + } + + //https://h5api.m.taobao.com/h5/mtop.taobao.baichuan.smb.get/1.0/?jsv=2.4.0&appKey=12574478&t=1580101872147&sign=0d0cd5819f67b6568a77de5867f151f9&api=mtop.taobao.baichuan.smb.get&v=1.0&type=originaljson&dataType=jsonp&timeout=10000 + if (html.Contains("FAIL_SYS") || string.IsNullOrEmpty(html)) + { + //if(!html.Contains("非法请求")) _cookies = string.Empty; + if (number >= 0) + { + //System.Threading.Thread.Sleep(10); + goto Next; + } + } + //Console.WriteLine(html); + + if (html.Contains("SUCCESS::")) + { + Dictionary json_rst = null; + var reg = System.Text.RegularExpressions.Regex.Match(html, @"^mtopjsonp\d\((.*?)\)$", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + if (reg.Success) json_rst = HttpExtend.JsonToDictionary(reg.Groups[1].Value); + else json_rst = HttpExtend.JsonToDictionary(html); + + if (json_rst != null && json_rst.ContainsKey("data")) + return json_rst["data"] as Dictionary; + } + throw new Exception(html); + } + + private string M_POST_HTML(string tempUrl, string data) + { + try + { + HttpItem item = new HttpItem() + { + URL = tempUrl,//URL 必需项 + Method = "post",//URL 可选项 默认为Get + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = Cookies + ";random=" + new Random().Next(),//字符串Cookie 可选项 + Postdata = data, + + Referer = tempUrl,//来源URL 可选项 + Timeout = 3000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 3000,//写入Post数据超时时间 可选项默认为30000 + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + Allowautoredirect = false,//是否根据301跳转 可选项 + }; + HttpHelper http = new HttpHelper(); + HttpResult result = http.GetHtml(item); + string html = result.Html; + Console.WriteLine(html); + if (!string.IsNullOrEmpty(result.Cookie)) + { + this.Cookies = result.UpdateCookies(this.Cookies); + } + return html; + } + catch (Exception ex) + { + return string.Empty; + } + } + + private string M_GET_HTML(string tempUrl) + { + try + { + HttpItem item = new HttpItem() + { + URL = tempUrl,//URL 必需项 + Method = "get",//URL 可选项 默认为Get + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = Cookies + ";random=" + new Random().Next(),//字符串Cookie 可选项 + Referer = "http://m.taobao.com",//来源URL 可选项 + Timeout = 3000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 3000,//写入Post数据超时时间 可选项默认为30000 + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "text/html",//返回类型 可选项有默认值 + Allowautoredirect = false,//是否根据301跳转 可选项 + }; + HttpHelper http = new HttpHelper(); + HttpResult result = http.GetHtml(item); + string html = result.Html; + if (!string.IsNullOrEmpty(result.Cookie)) + { + this.Cookies = result.UpdateCookies(this.Cookies); + } + return html; + } + catch (Exception ex) + { + return string.Empty; + } + } + #endregion + + /// + /// 优惠券activityId + /// + public string activityId = string.Empty; + + public Dictionary CreateTaopass(string text, string url, string pic) + { + + return M_GET("mtop.taobao.sharepassword.genpasswordh5", new { url = url, picUrl = pic, passwordType = "tao", sourceType = "other", title = text, bizId = "windvane" }, "1.0"); + } + + public Dictionary GetMobileTaobao(string api, object data, string v, string method = "get") + { + var http = new HttpHelper(); + var json = HttpHelper.ObjectToJson(data); + + HttpItem item = null; + if (method == "get") item = http.GetItem($"https://api.m.taobao.com/gw/{api}/{v}/?data={HttpHelper.URLEncode(json, Encoding.UTF8)}"); + else item = http.GetItem($"https://api.m.taobao.com/gw/{api}/{v}/", "", $"data={HttpHelper.URLEncode(json, Encoding.UTF8)}"); + + item.Timeout = 5000; + item.ReadWriteTimeout = 5000; + item.Header["x-appkey"] = "21380790"; + item.Header["x-t"] = HttpExtend.GetTimeStamp(); + item.Header["x-pv"] = "5.1"; + item.Header["x-sign"] = HttpHelper.ToMD5(Guid.NewGuid().ToString()); + item.Header["x-freatures"] = "27"; + item.Header["x-location"] = "FE.tfaZtP%2C0p.2o9qse"; + item.Header["x-ttid"] = "8Qde5G@taobao_android_6.8.0"; + item.Header["x-utdid"] = "2848V9fDrPe03W8H3947j8d0"; + item.Header["x-devid"] = "61C70me88jvMe9m9hq2V0QK0677fp5xqEreHzh8Gjt8r"; + //if (Consumer != null && !string.IsNullOrEmpty(this.Consumer.Sid)) item.Header["x-sid"] = Consumer.Sid; + //if (Consumer != null && !string.IsNullOrEmpty(this.Consumer.Userid)) item.Header["x-uid"] = Consumer.Userid; + item.Header["x-uid"] = "0"; + var res = http.GetHtml(item); + //EventClient.OnEvent("", "h5 =" + res.Html); + return HttpExtend.JsonToDictionary(res.Html); + } + + /// + /// 解析淘礼金链接 接口H5 + /// 阿里妈妈H5接口:mtop.alimama.union.xt.en.api.entry + /// https://acs.m.taobao.com/h5/mtop.alimama.union.xt.en.api.entry/1.0/?appKey=12574478&t=1613718293861&sign=0845fffdde5f8421366dde26a971bc26&api=mtop.alimama.union.xt.en.api.entry&v=1.0&data= {"floorId":"32447","variableMap":"{\"vegasCode\":\"S5834VQF\"}"} + /// + /// + /// + public Dictionary AnalysisTljUrl(string vegasCode) + { + try + { + string cookie = ""; + + HttpItem item = new HttpItem(); + item.URL = "https://acs.m.taobao.com/h5/mtop.alimama.union.xt.en.api.entry/1.0/?jsv=2.3.16&appKey=12574478"; + item.Method = "GET"; + item.ContentType = "application/x-www-form-urlencoded"; + item.Referer = "https://acs.m.taobao.com/h5/mtop.alimama.union.xt.en.api.entry/1.0/?jsv=2.3.16&appKey=12574478"; + item.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36"; + //item.Header["HOST"] = "acs.m.taobao.com"; + item.Host = "acs.m.taobao.com"; + item.Accept = "*/*"; + item.Header["Accept-Language"] = "zh-cn"; + var http = new HttpHelper(); + var res = http.GetHtml(item);//这一步的目的是为了获取到_m_h5_tk,这东西是H5端参与sign计算的必要参数,需要跟cookie中的内容相匹配 + cookie = res.Cookie; + + if (cookie.Contains("_m_h5_tk")) + { + var dataTmp = HttpUtility.UrlDecode($"%20%7B%22floorId%22%3A%2232447%22%2C%22variableMap%22%3A%22%7B%5C%22vegasCode%5C%22%3A%5C%22{vegasCode}%5C%22%7D%22%7D"); + var t = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString(); + var cookieArr = cookie.Split(new char[] { ';' }); + + //cookie2=1cd2e5c403c5dfca032b9747d2617e5a; _m_h5_tk=e1a4e7e0ff871e6513b53a27b72ea630_1613731324324; _m_h5_tk_enc=5c2329cb962340adafb08ff57e836860 + var cookie2 = cookieArr.FirstOrDefault(f => f.Contains("cookie2=")); + var _m_h5_tk = cookieArr.FirstOrDefault(f => f.Contains("_m_h5_tk=")); + var _m_h5_tk_enc = cookieArr.FirstOrDefault(f => f.Contains("_m_h5_tk_enc=")); + cookie = $"cookie2={getValue(cookie2, "cookie2")}; _m_h5_tk={getValue(_m_h5_tk, "_m_h5_tk")}; _m_h5_tk_enc={getValue(_m_h5_tk_enc, "_m_h5_tk_enc")}"; + + + var mh5Tk = cookieArr.FirstOrDefault(p => p.Contains("_m_h5_tk") && !p.Contains("_m_h5_tk_enc")); + mh5Tk = mh5Tk.Split(new char[] { '=' })[1].Split(new char[] { '_' })[0]; + string temp_ = mh5Tk + "&" + t + "&" + "12574478" + "&" + dataTmp; + string sign = HttpHelper.ToMD5(temp_).ToLower(); + var url = $"https://acs.m.taobao.com/h5/mtop.alimama.union.xt.en.api.entry/1.0/?appKey=12574478&t={t}&sign={sign}&api=mtop.alimama.union.xt.en.api.entry&v=1.0&data=%20%7B%22floorId%22%3A%2232447%22%2C%22variableMap%22%3A%22%7B%5C%22vegasCode%5C%22%3A%5C%22{vegasCode}%5C%22%7D%22%7D"; + item.URL = url; + item.Referer = url; + item.Cookie = cookie; + var resHtml = http.GetHtml(item).Html; + if (resHtml.Contains("SUCCESS::调用成功")) + { + var json = HttpExtend.JsonToDictionary(resHtml); + return json; + } + } + } + catch (Exception ex) + { + } + return null; + } + + private static string getValue(string value, string str) + { + var reg = Regex.Match(value, str + "=([^;]+)"); + if (reg.Success) + { + return reg.Groups[1].Value; + } + return value; + } + + /// + /// 通过淘口令获取商品连接 + /// + /// + /// + public string GetItemIdByTKL(string password, AlimamaApi api = null) + { + try + { + var result = GetPasswordDetail(password); + if (result != null && result.Count != 0) + { + TbAnalysis analysis = new TbAnalysis(); + var url = string.Empty; + if (result.ContainsKey("url")) + url = result["url"].ToString(); + else if (result.ContainsKey("origin_url")) + url = result["origin_url"].ToString(); + if (!url.Contains("taolijin/")) + { + + var item_id = string.Empty; + if (url.Contains("uland.taobao")) + { + var reg = Regex.Match(result["url"].ToString(), @"activityId=(?<活动ID>[A-Za-z0-9]+)"); + if (reg.Success) + activityId = reg.Groups["活动ID"].Value; + } + else if (url.Contains("mo.m.tmall.com")) + { + var http = new HttpHelper(); + var html = http.GetHtml(url).Html; + var reg = Regex.Match(html, @"itemId: '(\d+)'"); + if (reg.Success) + { + return reg.Groups[1].Value; + } + } + if ((api != null)) + { + if (result.ContainsKey("picUrl") && !string.IsNullOrWhiteSpace(result["picUrl"]?.ToString())) + { + item_id = TBHelper.FindTBCouponByItemIdCache(result["picUrl"].ToString()); + if (string.IsNullOrWhiteSpace(item_id)) + { + item_id = analysis.CouponByItemId(result["url"].ToString(), api); + if (!string.IsNullOrWhiteSpace(item_id)) + TBHelper.SetTBCouponByItemIdCache(result["picUrl"].ToString(), item_id); + } + else + { } + } + else + { + item_id = analysis.CouponByItemId(result["url"].ToString(), api); + } + } + else + item_id = analysis.FindTbItemIdByStr(result["url"].ToString()); + return item_id; + } + else + { + return AnalysisItemidByTljUrl(url); + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + public string AnalysisItemidByTljUrl(string url) + { + if (url.Contains("taolijin/")) + { + //https://uland.taobao.com/taolijin/edetail?vegasCode=S5834VQF&type=qtz&union_lens=lensId%3ATAPI%401613722684%4021053dc7_0abe_1778b63dc58_e8c2%40015HKdubJ7xgHNR2jfxmRzMg&un=8a050443537b55c34c6e4bed9157ce66&share_crt_v=1&ut_sk=1.utdid_24551056_1613698636132.TaoPassword-Outside.taoketop&spm=a2159r.13376465.0.0&sp_tk=aHJ6TmN4aWI1Mmg=&bxsign=tcdCOtJHarTrAkacOE_s67gvWJ4eV4ohNoUxtwDdaYDGdQeOcF1Ns4VX1hadXKQHOB6mxPRxtTJhZQn-pWZBiBtZsWVVZJWNRkQHPNmMlgx3Do + var reg = Regex.Match(url, @"vegasCode=(?[^&]+)"); + if (reg.Success) + { + var vegasCode = reg.Groups["vegasCode"].Value; + var result = AnalysisTljUrl(vegasCode); + if (result != null && result.Count != 0) + { + if (result.ContainsKey("data")) + { + var data1 = result["data"] as Dictionary; + if (data1.ContainsKey("resultList")) + { + var resultList = data1["resultList"] as ArrayList; + if (resultList != null && resultList.Count != 0) + { + var item = resultList[0] as Dictionary; + activityId = item.ContainsKey("couponActivityId") ? item["couponActivityId"].ToString() : string.Empty; + return item.ContainsKey("itemId") ? item["itemId"].ToString() : string.Empty; + } + } + } + } + } + } + return string.Empty; + } + + /// + /// 通过淘宝口令获取信息(返回字典) + /// + /// + /// + /// + public Dictionary GetPasswordDetail(string password) + { + //for (int i = 0; i < 3; i++) + //{ + // try + // { + // Dictionary result = null; + // try + // { + // TbAnalysis analysis = new TbAnalysis(); + // result = M_GET("com.taobao.redbull.getpassworddetail", new { password = password }, "1.0"); + // } + // catch (Exception ex) + // { } + // if (result != null && result.Count != 0) + // return result; + // var _temp = TbTools.SendData("com.taobao.redbull.getpassworddetail", new { password = password }); + // if (_temp != null && _temp.ok) + // { + // if (_temp.message.ToString().Contains("口令不存在")) return new Dictionary(); + // return _temp.message as Dictionary; + // } + // } + // catch (Exception ex) + // { } + // Thread.Sleep(100); + //} + //return new Dictionary(); + + for (int i = 0; i < 3; i++) + { + try + { + var result = GetMobileTaobao("mtop.taobao.sharepassword.querypassword", new { passwordContent = password }, "1.0"); + if (result != null && result.Count != 0) + { + if (result.ContainsKey("data")) + { + var data = result["data"] as Dictionary; + return data; + } + } + } + catch (Exception ex) + { } + Thread.Sleep(100); + } + return new Dictionary(); + } + + private static Dictionary error_next = new Dictionary(); + + //#region 通过优惠券链接获取淘宝宝贝的id + ///// + ///// 通过优惠券链接获取淘宝宝贝的id + ///// + ///// + //private string CouponByItemId(string url, AlimamaApi api) + //{ + // try + // { + // var itemId = FindTbItemIdByStr(url); + // if (!string.IsNullOrEmpty(itemId)) return itemId; + + // if (url.Contains(@"uland.taobao.com/coupon"))//这是针对淘宝联盟有优惠券的接口.//https://uland.taobao.com/coupon/edetail + // { + // var coupon = api.CheckCoupon(url);//将返利接口转成淘宝宝贝接口 + // if (coupon != null) return coupon.itemId; + // } + // else if (url.Contains(@"s.click.taobao.com"))//这是针对淘宝联盟没有全的接口.//https://s.click.taobao.com/t?e=m + // { + // var html = string.Empty; + // //获得首次Location 地址 + // bool first = false; + // Next: + // string location = GetLocation(url); + + // if (!string.IsNullOrWhiteSpace(location) && location.StartsWith("https://s.click.taobao.com/t?e=")) + // { + // var _location = GetLocation(location); + // if (!string.IsNullOrEmpty(_location)) location = _location; + // } + // if (!string.IsNullOrEmpty(location))//跳转地址存在 + // { + // //if (location.Contains("uland.taobao.com/coupon/edetail?e=")) + // if (location.Contains("uland.taobao.com/coupon/edetail?")) + // { + // string tempHtml = GetHTML(location); + // tempHtml = HttpHelper.URLDecode(tempHtml); + // var uland = Regex.Match(tempHtml, "&req_url=([^\"]+)"); + // if (uland.Success) + // { + // var param_e = Regex.Match(uland.Groups[1].Value, "e=([^&]+)"); + // if (!param_e.Success) return string.Empty; + // var coupon = api.CheckCoupon(uland.Groups[1].Value); + // if (coupon != null) + // return coupon.itemId; + // } + // else + // { + // //"系统日志,分析地址失败:" + url;} + // } + // } + // else if (location.Contains("uland.taobao.com")) + // { + // var _reg = Regex.Match(location, "itemId=(\\d+)", RegexOptions.IgnoreCase); + // if (_reg.Success) + // return _reg.Groups[1].Value; + // } + // else if (location.Contains("tu=")) + // { + // //获得二次访问地址 + // string next = HttpHelper.URLDecode(location.Replace("http://s.click.taobao.com/t_js?tu=", "").Replace("https://s.click.taobao.com/t_js?tu=", "")); + // html = HttpHelper.URLDecode(GetHTML(next, location)); + // var reg = Regex.Match(html, @"(?:&|\?)itemId=(\d+)", RegexOptions.IgnoreCase); + // if (reg.Success) + // return reg.Groups[1].Value; + // } + // else + // return FindTbItemIdByStr(GetHTML(location)); + // } + // else if (!string.IsNullOrEmpty(location) && !first) + // { + // url = location; + // first = true; + // goto Next; + // } + + // #region + // if (string.IsNullOrWhiteSpace(location)) + // { + // var _html = GetHTML(url); + // var reg = Regex.Match(_html, "real_jump_address = '(?<真正的跳转地址>[^']+)"); + // if (reg.Success) + // { + // var address = reg.Groups["真正的跳转地址"].Value; + // //_html = GetHTML(HttpHelper.URLDecode(address).Replace("&", "&"), HttpHelper.URLDecode(url)); + // _html = GetHTML(address.Replace("&", "&"), url); + // itemId = FindTbItemIdByStr(_html); + // if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + // } + // } + // #endregion + // } + // else if (url.Contains("m.tb.cn")) + // { + // string tempHtml = GetHTML(url); + // tempHtml = HttpHelper.URLDecode(tempHtml); + // var reg = Regex.Match(tempHtml, "url = '(?<链接>.*?)';"); + // if (reg.Success) + // { + // var _url = reg.Groups["链接"].Value; + // _url = HttpHelper.URLDecode(_url); + // itemId = FindTbItemIdByStr(_url); + // if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + // } + // } + // else if (url.Contains("h5.m.taobao.com")) + // { + // var _url = HttpHelper.URLDecode(HttpHelper.URLDecode(url)); + // itemId = FindTbItemIdByStr(_url); + // if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + // } + // else if (url.Contains("mo.m.tmall.com")) + // { + // string tempHtml = GetHTML(url); + // itemId = FindTbItemIdByStr(tempHtml); + // if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + // } + // else if (url.Contains("uland.taobao")) + // { + + // } + // } + // catch (Exception ex) + // { } + // return string.Empty; + //} + + //private string GetLocation(string url) + //{ + // try + // { + // HttpHelper http = new HttpHelper(); + // HttpItem item = new HttpItem() + // { + // URL = url, + // Method = "get", + // IsToLower = false, + // Cookie = "", + // Referer = "", + // Postdata = "", + // Timeout = 5000, + // ReadWriteTimeout = 15000, + // UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + // ContentType = "application/x-www-form-urlencoded", + // Allowautoredirect = false, + // ProxyIp = "" + // }; + // HttpResult result = http.GetHtml(item); + // return result.Header.Get("Location"); + // } + // catch (Exception ex) + // { + // //EventClient.OnEvent(this, $"Location:{url},{ex.Message},{ex.StackTrace}"); + // } + // return string.Empty; + //} + //private string GetHTML(string url, string rf = "", string postData = "") + //{ + // try + // { + // HttpHelper http = new HttpHelper(); + // HttpItem item = new HttpItem() + // { + // URL = url, + // Method = (postData == "" ? "get" : "post"), + // Postdata = (postData == "" ? "" : postData), + // IsToLower = false, + // Referer = rf, + // Timeout = 5000, + // ReadWriteTimeout = 15000, + // UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + // ContentType = "application/x-www-form-urlencoded", + // Allowautoredirect = true + // }; + // HttpResult result = http.GetHtml(item); + // //var location = result.Header.Get("Location"); + // return result.Html; + // } + // catch (Exception) + // { } + // return string.Empty; + //} + + ///// + ///// 查找宝贝Id的正则表达式 + ///// + //private string[] Reg_Item_Ids = { @"item[Ii]d=(?\d{5,})", @"item_id=(?\d{5,})", @"\?id=(?\d{5,})", @"&id=(?\d{5,})", @"/i(?\d{5,})", @"num[Ii]id=(?\d{5,})" }; + + ///// + ///// 从字符串中获取淘宝宝贝id + ///// + ///// 要查找的字符串 + ///// 返回查找到的宝贝id,未找到返回空,异常返回异常的信息 + //public string FindTbItemIdByStr(string str) + //{ + // try + // { + // //获取淘宝天猫的宝贝id值 + // for (int i = 0; i < Reg_Item_Ids.Length; i++) + // { + // var reg = Regex.Match(str, Reg_Item_Ids[i].ToString()); + // if (reg.Success) + // return reg.Groups["id"].Value; + // } + // return string.Empty; + // } + // catch (Exception ex) + // { + // return string.Empty; + // } + //} + //#endregion + + } +} diff --git a/类库/Api.Framework/Tools/h5Top.cs b/类库/Api.Framework/Tools/h5Top.cs new file mode 100644 index 0000000..8a854b8 --- /dev/null +++ b/类库/Api.Framework/Tools/h5Top.cs @@ -0,0 +1,693 @@ +using Api.Framework.Cps; +using CsharpHttpHelper; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using static Api.Framework.Tools.TBHelper; + +namespace Api.Framework.Tools +{ + /// + /// h5 + /// + public class h5Top + { + #region h5Top Code + private string _cookies = string.Empty; + private string Cookies + { + get + { + if (string.IsNullOrEmpty(_cookies)) + { + HttpHelper http = new HttpHelper(); + string _m_h5_tk, t, reCookie = ""; + var referer = "https://www.taobao.com"; + var api = "com.taobao.redbull.getpassworddetail"; + if (string.IsNullOrEmpty(_cookies)) + { + var tempUrl = $"https://api.m.taobao.com/h5/{api}/1.0/?appKey={appKey}&api={api}&v=1.0&t=&sign="; + string cookies = http.GetHtml(new HttpItem() + { + URL = tempUrl + }).Cookie; + _cookies = HttpHelper.GetSmallCookie(cookies); + } + } + return _cookies; + } + set { _cookies = value; } + } + + const string appKey = "12574478"; + + public static string GetCookiesValue(string key, string cookies) + { + if (string.IsNullOrEmpty(cookies)) return string.Empty; + string[] tempCookies = cookies.Split(';'); + foreach (var item in tempCookies) + { + string[] tempCookie = item.Split('='); + if (tempCookie.Length == 2) + { + if (tempCookie[0].Trim() == key) + { + return tempCookie[1].Split('_')[0]; + } + } + } + return string.Empty; + } + + private static string GetbyteToString(byte[] data) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < data.Length; i++) + { + sb.Append(data[i].ToString("x2")); + } + return sb.ToString(); + } + + private static string GetMD5String(string str) + { + MD5 md5 = MD5.Create(); + byte[] data = Encoding.UTF8.GetBytes(str); + byte[] data2 = md5.ComputeHash(data); + + return GetbyteToString(data2); + //return BitConverter.ToString(data2).Replace("-", "").ToLower(); + } + + public Dictionary M_GET(string api, object data, string version = "1.0") + { + int number = 3; + Next: + number--; + string time = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString(); + string mh5Tk = GetCookiesValue("_m_h5_tk", Cookies); + mh5Tk = string.IsNullOrEmpty(mh5Tk) ? "f64aa152f943661f750e6212ebc98804_1481170439770" : mh5Tk; + string json = (data.GetType() == typeof(string)) ? data.ToString() : HttpHelper.ObjectToJson(data).Replace("\\u0026", "&"); + string temp_ = mh5Tk + "&" + time + "&" + appKey + "&" + json; + string sign = GetMD5String(temp_); ; + string send = HttpHelper.URLEncode(json); + string temp = string.Format("http://api.m.taobao.com/h5/{5}/{4}/?v={4}&api={5}&appKey={0}&t={1}&callback=mtopjsonp1&type=jsonp&sign={2}&data={3}", appKey, time, sign, send, version, api); + string html = string.Empty; + //if (api == "mtop.taobao.baichuan.smb.get") + if (api.StartsWith("mtop") || api == "mtop.alimama.union.xt.biz.quan.api.entry" || api == "mtop.taobao.sharepassword.querypassword") + { + //temp = $"https://h5api.m.taobao.com/h5/{api}/{version}/?jsv=2.4.0&appKey={appKey}&t={time}&sign={sign}&api={api}&v={version}&type=originaljson&dataType=jsonp&timeout=10000"; + temp = $"https://h5api.m.taobao.com/h5/{api}/{version}/?jsv=2.4.0&appKey={appKey}&t={time}&sign={sign}&api={api}&v={version}&timeout=20000&AntiCreep=true&AntiFlood=true&type=jsonp&dataType=jsonp&callback=mtopjsonp2&data={send}"; + //html = M_POST_HTML(temp, "data=" + send); + html = M_GET_HTML(temp).Trim(); + //Console.WriteLine(html); + } + else + html = M_GET_HTML(temp).Trim(); + + //https://h5api.m.taobao.com/h5/mtop.taobao.baichuan.smb.get/1.0/?jsv=2.4.0&appKey=12574478&t=1580101872147&sign=0d0cd5819f67b6568a77de5867f151f9&api=mtop.taobao.baichuan.smb.get&v=1.0&type=originaljson&dataType=jsonp&timeout=10000 + if (html.Contains("FAIL_SYS") || string.IsNullOrEmpty(html)) + { + //if(!html.Contains("非法请求")) _cookies = string.Empty; + if (number >= 0) + { + //System.Threading.Thread.Sleep(10); + goto Next; + } + } + //Console.WriteLine(html); + + if (html.Contains("SUCCESS::")) + { + Dictionary json_rst = null; + var reg = System.Text.RegularExpressions.Regex.Match(html, @"^mtopjsonp\d\((.*?)\)$", System.Text.RegularExpressions.RegexOptions.IgnoreCase); + if (reg.Success) json_rst = HttpExtend.JsonToDictionary(reg.Groups[1].Value); + else json_rst = HttpExtend.JsonToDictionary(html); + + if (json_rst != null && json_rst.ContainsKey("data")) + return json_rst["data"] as Dictionary; + } + throw new Exception(html); + } + + private string M_POST_HTML(string tempUrl, string data) + { + try + { + HttpItem item = new HttpItem() + { + URL = tempUrl,//URL 必需项 + Method = "post",//URL 可选项 默认为Get + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = Cookies + ";random=" + new Random().Next(),//字符串Cookie 可选项 + Postdata = data, + + Referer = tempUrl,//来源URL 可选项 + Timeout = 3000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 3000,//写入Post数据超时时间 可选项默认为30000 + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + Allowautoredirect = false,//是否根据301跳转 可选项 + }; + HttpHelper http = new HttpHelper(); + HttpResult result = http.GetHtml(item); + string html = result.Html; + //Console.WriteLine(html); + if (!string.IsNullOrEmpty(result.Cookie)) + { + this.Cookies = result.UpdateCookies(this.Cookies); + } + return html; + } + catch (Exception ex) + { + return string.Empty; + } + } + + private string M_GET_HTML(string tempUrl) + { + try + { + HttpItem item = new HttpItem() + { + URL = tempUrl,//URL 必需项 + Method = "get",//URL 可选项 默认为Get + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = Cookies + ";random=" + new Random().Next(),//字符串Cookie 可选项 + Referer = "http://m.taobao.com",//来源URL 可选项 + Timeout = 3000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 3000,//写入Post数据超时时间 可选项默认为30000 + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "text/html",//返回类型 可选项有默认值 + Allowautoredirect = false,//是否根据301跳转 可选项 + }; + HttpHelper http = new HttpHelper(); + HttpResult result = http.GetHtml(item); + string html = result.Html; + if (!string.IsNullOrEmpty(result.Cookie)) + { + this.Cookies = result.UpdateCookies(this.Cookies); + } + return html; + } + catch (Exception ex) + { + return string.Empty; + } + } + #endregion + + /// + /// 优惠券activityId + /// + public string activityId = string.Empty; + + public Dictionary CreateTaopass(string text, string url, string pic) + { + return M_GET("mtop.taobao.sharepassword.genpasswordh5", new { url = url, picUrl = pic, passwordType = "tao", sourceType = "other", title = text, bizId = "windvane" }, "1.0"); + } + + public Dictionary GetMobileTaobao(string api, object data, string v, string method = "get") + { + var http = new HttpHelper(); + var json = HttpHelper.ObjectToJson(data); + + HttpItem item = null; + if (method == "get") item = http.GetItem($"https://api.m.taobao.com/gw/{api}/{v}/?data={HttpHelper.URLEncode(json, Encoding.UTF8)}"); + else item = http.GetItem($"https://api.m.taobao.com/gw/{api}/{v}/", "", $"data={HttpHelper.URLEncode(json, Encoding.UTF8)}"); + + item.Timeout = 5000; + item.ReadWriteTimeout = 5000; + item.Header["x-appkey"] = "21380790"; + item.Header["x-t"] = HttpExtend.GetTimeStamp(); + item.Header["x-pv"] = "5.1"; + item.Header["x-sign"] = HttpHelper.ToMD5(Guid.NewGuid().ToString()); + item.Header["x-freatures"] = "27"; + item.Header["x-location"] = "FE.tfaZtP%2C0p.2o9qse"; + item.Header["x-ttid"] = "8Qde5G@taobao_android_6.8.0"; + item.Header["x-utdid"] = "2848V9fDrPe03W8H3947j8d0"; + item.Header["x-devid"] = "61C70me88jvMe9m9hq2V0QK0677fp5xqEreHzh8Gjt8r"; + //if (Consumer != null && !string.IsNullOrEmpty(this.Consumer.Sid)) item.Header["x-sid"] = Consumer.Sid; + //if (Consumer != null && !string.IsNullOrEmpty(this.Consumer.Userid)) item.Header["x-uid"] = Consumer.Userid; + item.Header["x-uid"] = "0"; + var res = http.GetHtml(item); + //EventClient.OnEvent("", "h5 =" + res.Html); + return HttpExtend.JsonToDictionary(res.Html); + } + + /// + /// 解析淘礼金链接 接口H5 + /// 阿里妈妈H5接口:mtop.alimama.union.xt.en.api.entry + /// https://acs.m.taobao.com/h5/mtop.alimama.union.xt.en.api.entry/1.0/?appKey=12574478&t=1613718293861&sign=0845fffdde5f8421366dde26a971bc26&api=mtop.alimama.union.xt.en.api.entry&v=1.0&data= {"floorId":"32447","variableMap":"{\"vegasCode\":\"S5834VQF\"}"} + /// + /// + /// + public Dictionary AnalysisTljUrl(string vegasCode) + { + try + { + string cookie = ""; + + HttpItem item = new HttpItem(); + item.URL = "https://acs.m.taobao.com/h5/mtop.alimama.union.xt.en.api.entry/1.0/?jsv=2.3.16&appKey=12574478"; + item.Method = "GET"; + item.ContentType = "application/x-www-form-urlencoded"; + item.Referer = "https://acs.m.taobao.com/h5/mtop.alimama.union.xt.en.api.entry/1.0/?jsv=2.3.16&appKey=12574478"; + item.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36"; + //item.Header["HOST"] = "acs.m.taobao.com"; + item.Host = "acs.m.taobao.com"; + item.Accept = "*/*"; + item.Header["Accept-Language"] = "zh-cn"; + var http = new HttpHelper(); + var res = http.GetHtml(item);//这一步的目的是为了获取到_m_h5_tk,这东西是H5端参与sign计算的必要参数,需要跟cookie中的内容相匹配 + cookie = res.Cookie; + + if (cookie.Contains("_m_h5_tk")) + { + var dataTmp = HttpUtility.UrlDecode($"%20%7B%22floorId%22%3A%2232447%22%2C%22variableMap%22%3A%22%7B%5C%22vegasCode%5C%22%3A%5C%22{vegasCode}%5C%22%7D%22%7D"); + var t = ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000).ToString(); + var cookieArr = cookie.Split(new char[] { ';' }); + + //cookie2=1cd2e5c403c5dfca032b9747d2617e5a; _m_h5_tk=e1a4e7e0ff871e6513b53a27b72ea630_1613731324324; _m_h5_tk_enc=5c2329cb962340adafb08ff57e836860 + var cookie2 = cookieArr.FirstOrDefault(f => f.Contains("cookie2=")); + var _m_h5_tk = cookieArr.FirstOrDefault(f => f.Contains("_m_h5_tk=")); + var _m_h5_tk_enc = cookieArr.FirstOrDefault(f => f.Contains("_m_h5_tk_enc=")); + cookie = $"cookie2={getValue(cookie2, "cookie2")}; _m_h5_tk={getValue(_m_h5_tk, "_m_h5_tk")}; _m_h5_tk_enc={getValue(_m_h5_tk_enc, "_m_h5_tk_enc")}"; + + + var mh5Tk = cookieArr.FirstOrDefault(p => p.Contains("_m_h5_tk") && !p.Contains("_m_h5_tk_enc")); + mh5Tk = mh5Tk.Split(new char[] { '=' })[1].Split(new char[] { '_' })[0]; + string temp_ = mh5Tk + "&" + t + "&" + "12574478" + "&" + dataTmp; + string sign = HttpHelper.ToMD5(temp_).ToLower(); + var url = $"https://acs.m.taobao.com/h5/mtop.alimama.union.xt.en.api.entry/1.0/?appKey=12574478&t={t}&sign={sign}&api=mtop.alimama.union.xt.en.api.entry&v=1.0&data=%20%7B%22floorId%22%3A%2232447%22%2C%22variableMap%22%3A%22%7B%5C%22vegasCode%5C%22%3A%5C%22{vegasCode}%5C%22%7D%22%7D"; + item.URL = url; + item.Referer = url; + item.Cookie = cookie; + var resHtml = http.GetHtml(item).Html; + if (resHtml.Contains("SUCCESS::调用成功")) + { + var json = HttpExtend.JsonToDictionary(resHtml); + return json; + } + } + } + catch (Exception ex) + { + } + return null; + } + + private static string getValue(string value, string str) + { + var reg = Regex.Match(value, str + "=([^;]+)"); + if (reg.Success) + return reg.Groups[1].Value; + return value; + } + + /// + /// 通过淘口令获取商品连接 + /// + /// + /// + public string GetItemIdByTKL(string password, AlimamaApi api = null) + { + try + { + var result = GetPasswordDetail(password); + if (result != null && result.Count != 0) + { + TbAnalysis analysis = new TbAnalysis(); + var url = string.Empty; + if (result.ContainsKey("url")) + url = result["url"].ToString(); + else if (result.ContainsKey("origin_url")) + url = result["origin_url"].ToString(); + if (!url.Contains("taolijin/")) + { + + var item_id = string.Empty; + if (url.Contains("uland.taobao")) + { + var reg = Regex.Match(result["url"].ToString(), @"activityId=(?<活动ID>[A-Za-z0-9]+)"); + if (reg.Success) + activityId = reg.Groups["活动ID"].Value; + } + else if (url.Contains("mo.m.tmall.com")) + { + var http = new HttpHelper(); + var html = http.GetHtml(url).Html; + var reg = Regex.Match(html, @"itemId: '(\d+)'"); + if (reg.Success) + { + return reg.Groups[1].Value; + } + } + if ((api != null)) + { + if (result.ContainsKey("picUrl") && !string.IsNullOrWhiteSpace(result["picUrl"]?.ToString())) + { + item_id = TBHelper.FindTBCouponByItemIdCache(result["picUrl"].ToString()); + if (string.IsNullOrWhiteSpace(item_id)) + { + item_id = analysis.CouponByItemId(result["url"].ToString(), api); + if (!string.IsNullOrWhiteSpace(item_id)) + TBHelper.SetTBCouponByItemIdCache(result["picUrl"].ToString(), item_id); + } + else + { } + } + else + { + item_id = analysis.CouponByItemId(result["url"].ToString(), api); + } + } + else + item_id = analysis.FindTbItemIdByStr(result["url"].ToString()); + return item_id; + } + else + { + return AnalysisItemidByTljUrl(url); + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + public string AnalysisItemidByTljUrl(string url) + { + if (url.Contains("taolijin/")) + { + //https://uland.taobao.com/taolijin/edetail?vegasCode=S5834VQF&type=qtz&union_lens=lensId%3ATAPI%401613722684%4021053dc7_0abe_1778b63dc58_e8c2%40015HKdubJ7xgHNR2jfxmRzMg&un=8a050443537b55c34c6e4bed9157ce66&share_crt_v=1&ut_sk=1.utdid_24551056_1613698636132.TaoPassword-Outside.taoketop&spm=a2159r.13376465.0.0&sp_tk=aHJ6TmN4aWI1Mmg=&bxsign=tcdCOtJHarTrAkacOE_s67gvWJ4eV4ohNoUxtwDdaYDGdQeOcF1Ns4VX1hadXKQHOB6mxPRxtTJhZQn-pWZBiBtZsWVVZJWNRkQHPNmMlgx3Do + var reg = Regex.Match(url, @"vegasCode=(?[^&]+)"); + if (reg.Success) + { + var vegasCode = reg.Groups["vegasCode"].Value; + var result = AnalysisTljUrl(vegasCode); + if (result != null && result.Count != 0) + { + if (result.ContainsKey("data")) + { + var data1 = result["data"] as Dictionary; + if (data1.ContainsKey("resultList")) + { + var resultList = data1["resultList"] as ArrayList; + if (resultList != null && resultList.Count != 0) + { + var item = resultList[0] as Dictionary; + activityId = item.ContainsKey("couponActivityId") ? item["couponActivityId"].ToString() : string.Empty; + return item.ContainsKey("itemId") ? item["itemId"].ToString() : string.Empty; + } + } + } + } + } + } + return string.Empty; + } + + /// + /// 通过淘宝口令获取信息(返回字典) + /// + /// + /// + /// + public Dictionary GetPasswordDetail(string password) + { + //for (int i = 0; i < 3; i++) + //{ + // try + // { + // Dictionary result = null; + // try + // { + // TbAnalysis analysis = new TbAnalysis(); + // result = M_GET("com.taobao.redbull.getpassworddetail", new { password = password }, "1.0"); + // } + // catch (Exception ex) + // { } + // if (result != null && result.Count != 0) + // return result; + // var _temp = TbTools.SendData("com.taobao.redbull.getpassworddetail", new { password = password }); + // if (_temp != null && _temp.ok) + // { + // if (_temp.message.ToString().Contains("口令不存在")) return new Dictionary(); + // return _temp.message as Dictionary; + // } + // } + // catch (Exception ex) + // { } + // Thread.Sleep(100); + //} + //return new Dictionary(); + + for (int i = 0; i < 2; i++) + { + try + { + var result = GetMobileTaobao("mtop.taobao.sharepassword.querypassword", new { passwordContent = password }, "1.0"); + if (result != null && result.Count != 0) + { + if (result.ContainsKey("data")) + { + var data = result["data"] as Dictionary; + return data; + } + } + } + catch (Exception ex) + { } + Thread.Sleep(100); + } + return new Dictionary(); + } + + private static Dictionary error_next = new Dictionary(); + + //#region 通过优惠券链接获取淘宝宝贝的id + ///// + ///// 通过优惠券链接获取淘宝宝贝的id + ///// + ///// + //private string CouponByItemId(string url, AlimamaApi api) + //{ + // try + // { + // var itemId = FindTbItemIdByStr(url); + // if (!string.IsNullOrEmpty(itemId)) return itemId; + + // if (url.Contains(@"uland.taobao.com/coupon"))//这是针对淘宝联盟有优惠券的接口.//https://uland.taobao.com/coupon/edetail + // { + // var coupon = api.CheckCoupon(url);//将返利接口转成淘宝宝贝接口 + // if (coupon != null) return coupon.itemId; + // } + // else if (url.Contains(@"s.click.taobao.com"))//这是针对淘宝联盟没有全的接口.//https://s.click.taobao.com/t?e=m + // { + // var html = string.Empty; + // //获得首次Location 地址 + // bool first = false; + // Next: + // string location = GetLocation(url); + + // if (!string.IsNullOrWhiteSpace(location) && location.StartsWith("https://s.click.taobao.com/t?e=")) + // { + // var _location = GetLocation(location); + // if (!string.IsNullOrEmpty(_location)) location = _location; + // } + // if (!string.IsNullOrEmpty(location))//跳转地址存在 + // { + // //if (location.Contains("uland.taobao.com/coupon/edetail?e=")) + // if (location.Contains("uland.taobao.com/coupon/edetail?")) + // { + // string tempHtml = GetHTML(location); + // tempHtml = HttpHelper.URLDecode(tempHtml); + // var uland = Regex.Match(tempHtml, "&req_url=([^\"]+)"); + // if (uland.Success) + // { + // var param_e = Regex.Match(uland.Groups[1].Value, "e=([^&]+)"); + // if (!param_e.Success) return string.Empty; + // var coupon = api.CheckCoupon(uland.Groups[1].Value); + // if (coupon != null) + // return coupon.itemId; + // } + // else + // { + // //"系统日志,分析地址失败:" + url;} + // } + // } + // else if (location.Contains("uland.taobao.com")) + // { + // var _reg = Regex.Match(location, "itemId=(\\d+)", RegexOptions.IgnoreCase); + // if (_reg.Success) + // return _reg.Groups[1].Value; + // } + // else if (location.Contains("tu=")) + // { + // //获得二次访问地址 + // string next = HttpHelper.URLDecode(location.Replace("http://s.click.taobao.com/t_js?tu=", "").Replace("https://s.click.taobao.com/t_js?tu=", "")); + // html = HttpHelper.URLDecode(GetHTML(next, location)); + // var reg = Regex.Match(html, @"(?:&|\?)itemId=(\d+)", RegexOptions.IgnoreCase); + // if (reg.Success) + // return reg.Groups[1].Value; + // } + // else + // return FindTbItemIdByStr(GetHTML(location)); + // } + // else if (!string.IsNullOrEmpty(location) && !first) + // { + // url = location; + // first = true; + // goto Next; + // } + + // #region + // if (string.IsNullOrWhiteSpace(location)) + // { + // var _html = GetHTML(url); + // var reg = Regex.Match(_html, "real_jump_address = '(?<真正的跳转地址>[^']+)"); + // if (reg.Success) + // { + // var address = reg.Groups["真正的跳转地址"].Value; + // //_html = GetHTML(HttpHelper.URLDecode(address).Replace("&", "&"), HttpHelper.URLDecode(url)); + // _html = GetHTML(address.Replace("&", "&"), url); + // itemId = FindTbItemIdByStr(_html); + // if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + // } + // } + // #endregion + // } + // else if (url.Contains("m.tb.cn")) + // { + // string tempHtml = GetHTML(url); + // tempHtml = HttpHelper.URLDecode(tempHtml); + // var reg = Regex.Match(tempHtml, "url = '(?<链接>.*?)';"); + // if (reg.Success) + // { + // var _url = reg.Groups["链接"].Value; + // _url = HttpHelper.URLDecode(_url); + // itemId = FindTbItemIdByStr(_url); + // if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + // } + // } + // else if (url.Contains("h5.m.taobao.com")) + // { + // var _url = HttpHelper.URLDecode(HttpHelper.URLDecode(url)); + // itemId = FindTbItemIdByStr(_url); + // if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + // } + // else if (url.Contains("mo.m.tmall.com")) + // { + // string tempHtml = GetHTML(url); + // itemId = FindTbItemIdByStr(tempHtml); + // if (!string.IsNullOrWhiteSpace(itemId)) return itemId; + // } + // else if (url.Contains("uland.taobao")) + // { + + // } + // } + // catch (Exception ex) + // { } + // return string.Empty; + //} + + //private string GetLocation(string url) + //{ + // try + // { + // HttpHelper http = new HttpHelper(); + // HttpItem item = new HttpItem() + // { + // URL = url, + // Method = "get", + // IsToLower = false, + // Cookie = "", + // Referer = "", + // Postdata = "", + // Timeout = 5000, + // ReadWriteTimeout = 15000, + // UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + // ContentType = "application/x-www-form-urlencoded", + // Allowautoredirect = false, + // ProxyIp = "" + // }; + // HttpResult result = http.GetHtml(item); + // return result.Header.Get("Location"); + // } + // catch (Exception ex) + // { + // //EventClient.OnEvent(this, $"Location:{url},{ex.Message},{ex.StackTrace}"); + // } + // return string.Empty; + //} + //private string GetHTML(string url, string rf = "", string postData = "") + //{ + // try + // { + // HttpHelper http = new HttpHelper(); + // HttpItem item = new HttpItem() + // { + // URL = url, + // Method = (postData == "" ? "get" : "post"), + // Postdata = (postData == "" ? "" : postData), + // IsToLower = false, + // Referer = rf, + // Timeout = 5000, + // ReadWriteTimeout = 15000, + // UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + // ContentType = "application/x-www-form-urlencoded", + // Allowautoredirect = true + // }; + // HttpResult result = http.GetHtml(item); + // //var location = result.Header.Get("Location"); + // return result.Html; + // } + // catch (Exception) + // { } + // return string.Empty; + //} + + ///// + ///// 查找宝贝Id的正则表达式 + ///// + //private string[] Reg_Item_Ids = { @"item[Ii]d=(?\d{5,})", @"item_id=(?\d{5,})", @"\?id=(?\d{5,})", @"&id=(?\d{5,})", @"/i(?\d{5,})", @"num[Ii]id=(?\d{5,})" }; + + ///// + ///// 从字符串中获取淘宝宝贝id + ///// + ///// 要查找的字符串 + ///// 返回查找到的宝贝id,未找到返回空,异常返回异常的信息 + //public string FindTbItemIdByStr(string str) + //{ + // try + // { + // //获取淘宝天猫的宝贝id值 + // for (int i = 0; i < Reg_Item_Ids.Length; i++) + // { + // var reg = Regex.Match(str, Reg_Item_Ids[i].ToString()); + // if (reg.Success) + // return reg.Groups["id"].Value; + // } + // return string.Empty; + // } + // catch (Exception ex) + // { + // return string.Empty; + // } + //} + //#endregion + + } +} diff --git a/类库/Api.Framework/UIForm/AliQrCordControl.Designer.cs b/类库/Api.Framework/UIForm/AliQrCordControl.Designer.cs new file mode 100644 index 0000000..fb007f8 --- /dev/null +++ b/类库/Api.Framework/UIForm/AliQrCordControl.Designer.cs @@ -0,0 +1,93 @@ + +namespace 淘宝登录 +{ + partial class AliQrCordControl + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.status = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // status + // + this.status.AutoSize = true; + this.status.Location = new System.Drawing.Point(124, 349); + this.status.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.status.Name = "status"; + this.status.Size = new System.Drawing.Size(55, 15); + this.status.TabIndex = 5; + this.status.Text = "label1"; + // + // pictureBox1 + // + this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Top; + this.pictureBox1.Location = new System.Drawing.Point(0, 0); + this.pictureBox1.Margin = new System.Windows.Forms.Padding(7, 6, 7, 6); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Padding = new System.Windows.Forms.Padding(7, 6, 7, 6); + this.pictureBox1.Size = new System.Drawing.Size(333, 320); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureBox1.TabIndex = 4; + this.pictureBox1.TabStop = false; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(263, 349); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(37, 15); + this.linkLabel1.TabIndex = 6; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "刷新"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // AliQrCordControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.status); + this.Controls.Add(this.pictureBox1); + this.Name = "AliQrCordControl"; + this.Size = new System.Drawing.Size(333, 387); + this.Load += new System.EventHandler(this.AliQrCordControl_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label status; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.LinkLabel linkLabel1; + } +} diff --git a/类库/Api.Framework/UIForm/AliQrCordControl.cs b/类库/Api.Framework/UIForm/AliQrCordControl.cs new file mode 100644 index 0000000..488b959 --- /dev/null +++ b/类库/Api.Framework/UIForm/AliQrCordControl.cs @@ -0,0 +1,1054 @@ +using HtmlAgilityPack; +using CsharpHttpHelper; +using Newtonsoft.Json.Linq; +using QRCoder; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Web; +using PcLogger; +using UI.Framework.Forms; +using Api.Framework.Cps; +using Api.Framework; +using Api.Framework.Enums; +using Api.Framework.Model; + +namespace 淘宝登录 +{ + /// + /// 阿里妈妈登录二维码 + /// + public partial class AliQrCordControl : UserControl + { + public AliQrCordControl() + { + InitializeComponent(); + } + + private void AliQrCordControl_Load(object sender, EventArgs e) + { + View(); + } + + private string logUrl = "https://login.taobao.com/member/login.jhtml?style=mini&newMini2=true&css_style=alimama&from=alimama&redirectURL=http%3A%2F%2Fwww.alimama.com&full_redirect=true&disableQuickLogin=true&qq-pf-to=pcqq.c2c"; + + private string apiurl = $"{ApiClient.Setting.SystemConfig.cps_server_api}api/alimama.asmx/login"; + + public string error = "请在浏览器端登录一次淘宝官网后,再重新回来扫码即可登录"; + + int count = 0; + + public void View() + { + Task.Run(() => + { + count++; + string cookie = string.Empty; + try + { + var http = new HttpHelper(); + var item = new HttpItem() + { + URL = logUrl, + Method = "get", + IsToLower = false, + Cookie = cookie, + Referer = "", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "text/html", + Allowautoredirect = false, + }; + var result = http.GetHtml(item); + string html = result.Html; + cookie = result.UpdateCookies(cookie); + + if (html.Contains("oginFormData")) + { + var index = html.IndexOf("loginFormData"); + var content = html.Substring(index, html.Length - index); + var endIndex = content.IndexOf(";\n"); + var msg = content.Substring(0, endIndex); + msg = msg.Replace("loginFormData\":", ""); + msg = msg.Replace("{", "").Replace("}", ""); + msg = "{" + msg + "}"; + var msgObj = JObject.Parse(msg); + + var qrItem = new HttpItem() + { + URL = $"https://login.taobao.com/newlogin/qrcode/generate.do?appName={msgObj["appName"]}&fromSite={msgObj["fromSite"]}&appName={msgObj["appName"]}&appEntrance={msgObj["appEntrance"]}&_csrf_token={msgObj["_csrf_token"]}&umidToken={msgObj["umidToken"]}&hsiz={msgObj["hsiz"]}&bizParams=&style=default&appkey={msgObj["appkey"]}&from={msgObj["from"]}&isMobile={msgObj["isMobile"]}&lang={msgObj["lang"]}&returnUrl={HttpUtility.UrlEncode("https://www.alimama.com/index.htm")}&fromSite={msgObj["fromSite"]}", + Method = "get", + IsToLower = false, + Cookie = cookie, + Referer = logUrl, + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "application/json, text/plain, */*", + Allowautoredirect = false, + }; + + var qrRes = http.GetHtml(qrItem); + var qrHtml = qrRes.Html; + cookie = qrRes.UpdateCookies(cookie); + + //var qrItem = new HttpItem(); + + //qrItem.URL = $"https://login.taobao.com/newlogin/qrcode/generate.do?appName={msgObj["appName"]}&fromSite={msgObj["fromSite"]}&appName={msgObj["appName"]}&appEntrance={msgObj["appEntrance"]}&_csrf_token={msgObj["_csrf_token"]}&umidToken={msgObj["umidToken"]}&hsiz={msgObj["hsiz"]}&bizParams=&style=default&appkey={msgObj["appkey"]}&from={msgObj["from"]}&isMobile={msgObj["isMobile"]}&lang={msgObj["lang"]}&returnUrl={HttpUtility.UrlEncode("https://www.alimama.com/index.htm")}&fromSite={msgObj["fromSite"]}"; + //qrItem.Cookie = cookice; + //qrItem.Accept = "application/json, text/plain, */*"; + //qrItem.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + //qrItem.Referer = logUrl; + //var qrRes = http.GetHtml(qrItem, ref cookie).Html; + var qrObj = JObject.Parse(qrHtml);//[JSON].content.data.t + var ck = qrObj["content"]["data"]["ck"].ToString(); + var t = qrObj["content"]["data"]["t"].ToString(); + var code = qrObj["content"]["data"]["codeContent"].ToString(); + var qrGenerator = new QRCoder.QRCodeGenerator(); + var qrCodeData = qrGenerator.CreateQrCode(code, QRCodeGenerator.ECCLevel.Q); + var qrcode = new QRCode(qrCodeData); + + Bitmap qrCodeImage = qrcode.GetGraphic(5, Color.Black, Color.White, null, 15, 6, false); + var ms = new MemoryStream(); + qrCodeImage.Save(ms, ImageFormat.Jpeg); + this.Invoke(new Action(() => + { + pictureBox1.Image = qrCodeImage; + status.Text = "请使用手机淘宝扫描二维码..."; + })); + + var start = DateTime.Now; + //string url = ""; + qrState qr = qrState.已发码; + while (DateTime.Now < start.AddMinutes(2)) + { + //qr = CheckStatus(msgObj, items.URL, cookie, t, ck, qrItem.UserAgent, ref url); + qr = CheckStatus(msgObj, logUrl, ref cookie, t, ck, qrItem.UserAgent); + if (qr == qrState.已确认) + { + break; + } + else if (qr == qrState.二维码超时) + { + //二维码超时 + break; + } + Thread.Sleep(1500); + } + if (qr == qrState.已确认) + { + //CheckLogin(url, cookie, items.URL); + //MessageBox.Show(cookie); + Shouquan(cookie); + } + } + } + catch (Exception ex) + { + if (error != ex.Message) + { + if (count < 2) + { + BaseForm.ShowErrorAutoClose($"扫码登录失败:{ex.Message},二维码已更新请扫码重试", 3000); + View(); + } + else + { + BaseForm.ShowError("多次登录账号未成功,请稍后重新"); + (this.Parent.Parent.Parent as alimama_form_login).Close(); + } + } + else + { + BaseForm.ShowErrorAutoClose(error, 5000); + } + } + }); + } + #region 授权高佣 + /// + /// 授权 + /// + /// + public void Shouquan(string cookie_) + { + #region 登录成功高佣授权 + try + { + var _Login = AlimamaApi.GetUnionPubContextInfo(cookie_); + //var _Login = GetUnionPubContextInfo(cookie_); + if (_Login == null || _Login.Count == 0 || !_Login.ContainsKey("memberID")) + throw new Exception($@"填写的Cookies数据错误: +原因: +①错误复制cookies +②联盟账号未登录 +③等"); + var Member = CpsClient.Members.FirstOrDefault(f => f.username == _Login["memberID"].ToString() && f.cpstype == CpsType.阿里妈妈); + if (Member == null) + { + Member = new fl_cps_member() { username = _Login["memberID"].ToString(), cpstype = CpsType.阿里妈妈 }; + CpsClient.Members.Add(Member); + } + + Member.online = true; + Member.cookies = cookie_; + if (_Login.ContainsKey("nickName")) + Member.usernick = HttpExtend.Unicode2String(_Login["nickName"].ToString()); + + //BaseForm.ShowSuccess("验证成功,您可以继续授权高佣Api"); + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = apiurl, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookie_, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "", + Allowautoredirect = true, + AutoRedirectCookie = false, + Postdata = "" + }; + HttpResult result = http.GetHtml(item); + string html = result.Html; + + cookie_ = result.UpdateCookies(cookie_); + var responseUri = result.ResponseUri; + //授权页面 + if (!string.IsNullOrWhiteSpace(responseUri)) + { + http = new HttpHelper(); + item = new HttpItem() + { + URL = responseUri, + Method = "GET", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookie_, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = "", + Allowautoredirect = true, + AutoRedirectCookie = false, + Postdata = "", + }; + result = http.GetHtml(item); + html = result.Html; + + cookie_ = result.UpdateCookies(cookie_); + //获取表单数据 + var postStrb = new StringBuilder(); + var regs = Regex.Matches(html, ""); + foreach (Match reg in regs) + { + var key = reg.Groups["key"].Value; + var value = reg.Groups["value"].Value; + if ("agreement" == key) + value = string.IsNullOrWhiteSpace(value) ? "true" : "false"; + postStrb.Append($"{key}={value}&"); + } + + //https://oauth.taobao.com/authorize.do + item = new HttpItem() + { + URL = "https://oauth.taobao.com/authorize.do", + Method = "POST", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookie_, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = responseUri, + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = postStrb.ToString() + }; + result = http.GetHtml(item); + html = result.Html; + + cookie_ = result.UpdateCookies(cookie_); + + var oauthUrl = result.RedirectUrl; + + if (string.IsNullOrWhiteSpace(oauthUrl)) + { + + + + throw new Exception($@"本电脑缺少淘宝的数字证书 +解决方案: +1.请使用别的方式登录试一下 +2.使用Cookies登录,复制链接到自己电脑登录"); + } + + //https://oauth.taobao.com/authorize?track_id=1694974f-aacc-4d49-a915-c864306af03e&response_type=token&client_id=27754179&state=27754179&view=web&agreement=true&agreementsign=27754179-26850731-2155887647-3A29FFF558F28BAD620FD148AAEE95D5&_tb_token_=3edb333935ef0 + + var item1 = new HttpItem() + { + URL = oauthUrl, + Method = "POST", + Timeout = 100000, + ReadWriteTimeout = 30000, + IsToLower = false, + Cookie = cookie_, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/x-www-form-urlencoded", + Referer = responseUri, + Allowautoredirect = false, + AutoRedirectCookie = false, + Postdata = "" + }; + var result1 = http.GetHtml(item1); + var html1 = result1.Html; + + var cookie_1 = result1.UpdateCookies(cookie_); + //https://oauth.taobao.com/oauth2?view=web#access_token=6100311473e8c16e6ea17fff1f17365d895a9750c9778002155887647&token_type=Bearer&expires_in=2592000&refresh_token=61002117e0f670517e5111bfb9899eea6895b4e827830912155887647&re_expires_in=2592000&r1_expires_in=2592000&r2_expires_in=86400&taobao_open_uid=AAFJsrlwAJVa5gTotY1tZwL5&taobao_user_id=2155887647&taobao_user_nick=%E6%BD%9C%E6%84%8F%E8%AF%86%E4%B8%8D%E8%88%8D&w1_expires_in=2592000&w2_expires_in=300&state=27754179&top_sign=1047B82D2B67D6610982DC4F754FC3BC + var resultUrl = result1.RedirectUrl; + try + { + var reg = Regex.Match(resultUrl, "access_token=([^&]+).*?refresh_token=([^&]+)"); + Member.logintime = DateTime.Now; + Member.is_valid = true; + var api = CpsClient.CreateAlimamaRequest(Member); + api.SendServer("taobao.tbk.update.token", new { mid = Member.username, url = resultUrl }); + api.RefToken(); + try + { + Member = ApiClient.GetSession().Saveable(Member).ExecuteReturnEntity(); + } + catch (Exception ex) + { } + BaseForm.ShowSuccessAutoClose($"{Member.usernick}({Member.username}),登录成功"); + this.Invoke(new Action(() => + { + try + { + (this.Parent.Parent.Parent as alimama_form_login).Close(); + } + catch (Exception ex) + { } + })); + } + catch (Exception ex) + { + BaseForm.ShowError(ex.Message + ex.StackTrace); + } + } + try + { + Member = ApiClient.GetSession().Saveable(Member).ExecuteReturnEntity(); + } + catch (Exception ex) + { } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + #endregion + } + #region xxx + // /// + // /// 授权 + // /// + // /// + // public void Shouquan(string cookie_) + // { + // #region 登录成功高佣授权 + // try + // { + // var _Login = AlimamaApi.GetUnionPubContextInfo(cookie_); + // if (_Login == null || _Login.Count == 0 || !_Login.ContainsKey("memberID")) + // throw new Exception($@"填写的Cookies数据错误: + //原因: + //①错误复制cookies + //②联盟账号未登录 + //③等"); + // var Member = CpsClient.Members.FirstOrDefault(f => f.username == _Login["memberID"].ToString() && f.cpstype == CpsType.阿里妈妈); + // if (Member == null) + // { + // Member = new fl_cps_member() { username = _Login["memberID"].ToString(), cpstype = CpsType.阿里妈妈 }; + // CpsClient.Members.Add(Member); + // } + + // Member.online = true; + // Member.cookies = cookie_; + // if (_Login.ContainsKey("nickName")) + // Member.usernick = HttpExtend.Unicode2String(_Login["nickName"].ToString()); + + // //BaseForm.ShowSuccess("验证成功,您可以继续授权高佣Api"); + // HttpHelper http = new HttpHelper(); + // HttpItem item = new HttpItem() + // { + // URL = apiurl, + // Method = "GET", + // Timeout = 100000, + // ReadWriteTimeout = 30000, + // IsToLower = false, + // Cookie = cookie_, + // UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + // Accept = "text/html, application/xhtml+xml, */*", + // ContentType = "application/x-www-form-urlencoded", + // Referer = "", + // Allowautoredirect = true, + // AutoRedirectCookie = false, + // Postdata = "" + // }; + // HttpResult result = http.GetHtml(item); + // string html = result.Html; + // cookie_ = result.UpdateCookies(cookie_); + // var responseUri = result.ResponseUri; + // //授权页面 + // if (!string.IsNullOrWhiteSpace(responseUri)) + // { + // http = new HttpHelper(); + // item = new HttpItem() + // { + // URL = responseUri, + // Method = "GET", + // Timeout = 100000, + // ReadWriteTimeout = 30000, + // IsToLower = false, + // Cookie = cookie_, + // UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + // Accept = "text/html, application/xhtml+xml, */*", + // ContentType = "application/x-www-form-urlencoded", + // Referer = "", + // Allowautoredirect = true, + // AutoRedirectCookie = false, + // Postdata = "", + // }; + // result = http.GetHtml(item); + // html = result.Html; + // cookie_ = result.UpdateCookies(cookie_); + // //获取表单数据 + // var postStrb = new StringBuilder(); + // var regs = Regex.Matches(html, ""); + // foreach (Match reg in regs) + // { + // var key = reg.Groups["key"].Value; + // var value = reg.Groups["value"].Value; + // if ("agreement" == key) + // value = string.IsNullOrWhiteSpace(value) ? "true" : "false"; + // postStrb.Append($"{key}={value};"); + // } + + // //https://oauth.taobao.com/authorize.do + // item = new HttpItem() + // { + // URL = "https://oauth.taobao.com/authorize.do", + // Method = "POST", + // Timeout = 100000, + // ReadWriteTimeout = 30000, + // IsToLower = false, + // Cookie = cookie_, + // UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + // Accept = "text/html, application/xhtml+xml, */*", + // ContentType = "application/x-www-form-urlencoded", + // Referer = responseUri, + // Allowautoredirect = false, + // AutoRedirectCookie = false, + // Postdata = postStrb.ToString() + // }; + // result = http.GetHtml(item); + // html = result.Html; + // cookie_ = result.UpdateCookies(cookie_); + + // var oauthUrl = result.ResponseUri; + + // //https://oauth.taobao.com/authorize?track_id=1694974f-aacc-4d49-a915-c864306af03e&response_type=token&client_id=27754179&state=27754179&view=web&agreement=true&agreementsign=27754179-26850731-2155887647-3A29FFF558F28BAD620FD148AAEE95D5&_tb_token_=3edb333935ef0 + // item.URL = oauthUrl; + // item.Referer = responseUri; + // item.Cookie = cookie_; + // item.Method = "Get"; + // item.Postdata = ""; + + // result = http.GetHtml(item); + // html = result.Html; + // cookie_ = result.UpdateCookies(cookie_); + + // } + // } + // catch (Exception ex) + // { + // BaseForm.ShowError(ex); + // } + // #endregion + // } + #endregion + #endregion + + public qrState CheckStatus(JObject msg, string refer, ref string cookie, string t, string ck, string ua) + { + //https://login.taobao.com/newlogin/qrcode/query.do?appName=taobao&fromSite=0&_bx-v=1.1.20 + + var item = new HttpItem() + { + URL = "https://login.taobao.com/newlogin/qrcode/query.do?appName=taobao&fromSite=0", + Method = "post", + IsToLower = false, + Cookie = cookie, + Referer = logUrl, + Postdata = $"t={t}&ck={ck}&ua=&appName={msg["appName"]}&appEntrance={msg["appEntrance"]}&_csrf_token={msg["_csrf_token"]}&umidToken={msg["umidToken"]}&hsiz={msg["hsiz"]}&bizParams=&style=default&appkey={msg["appkey"]}&from={msg["from"]}&isMobile=false&lang={msg["lang"]}&returnUrl={HttpUtility.UrlEncode("https://www.alimama.com/index.htm")}&fromSite={msg["fromSite"]}&navlanguage=zh-CN&navUserAgent=Mozilla%2F5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F86.0.4240.111%20Safari%2F537.36&navPlatform=Win32", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = false + }; + + var http = new HttpHelper(); + var res = http.GetHtml(item); + var html = res.Html; + cookie = res.UpdateCookies(cookie); + + if (html.Contains("NEW")) + return qrState.已发码; + else if (html.Contains("SCANED")) + return qrState.已扫码; + else if (html.Contains("CONFIRMED")) + { + try + { + JObject resObj = JObject.Parse(html); + + var url = string.Empty; + var data = (JObject)resObj["content"]["data"]; + //这里是你之前代码有差异的地方(iframeRedirectUrl 带这个值得账号需要二次确认登录,redirectUrl 带这个值得账号直接请求返回的cookice是可以直接登录淘宝联盟) + //现在就是说,iframeRedirectUrl登录 的地址 需要二次授权登录,然后返回的界面中,有 + if (html.Contains("iframeRedirectUrl")) + { + //{"content":{"data":{"qrCodeStatus":"CONFIRMED","resultCode":100,"iframeRedirect":true,"iframeRedirectUrl":"https://login.taobao.com/member/login_unusual.htm?user_num_id=691249236&from=alimama&style=default&css_style=default&is_scure=true&c_is_scure=true&tpl_redirect_url=https%3A%2F%2Fwww.alimama.com%2Findex.htm&cr=https%3A%2F%2Fwww.alimama.com%2Findex.htm&sub=false&loginsite=0&login_type=3&lang=zh_CN&appkey=00000000&new_iv_check=true&iv_check_time=1609229233221&iv_check_sign=45346d0aa50ffd805020a6314ec3540c"},"status":0,"success":true},"hasError":false} + var resJson = CheckLogin(data["iframeRedirectUrl"].ToString(), ref cookie, logUrl); + JObject resJsonObj = JObject.Parse(resJson); + // {"data":{"redirect":true,"redirectUrl":"https://login.taobao.com/member/login_agreement.htm?style=default&redirectURL=https%3A%2F%2Fwww.alimama.com%2Findex.htm","asyncUrls":["https://passport.alibaba.com/mini_apply_st.js?callback=callback&site=0&token=1kmsQ89TjdVlaH_NuC5dtWg"],"resultCode":100},"status":0,"success":true} + url = resJsonObj["data"]["redirectUrl"].ToString(); + + if (url.Contains("login_agreement.htm")) + { + //item = new HttpItem(); + //item.URL = "https://login.taobao.com/member/agreementSign.do"; + //item.Postdata = "redirectURL=https%3A%2F%2Fwww.alimama.com%2Findex.htm"; + //item.Method = "POST"; + //item.Cookie = cookie; + //item.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + //item.Referer = "https://login.taobao.com/member/login_agreement.htm?style=default&redirectURL=https%3A%2F%2Fwww.alimama.com%2Findex.htm"; + //item.Header.Add("origin", "https://login.taobao.com"); + //item.ContentType = "application/x-www-form-urlencoded"; + //http = new HttpHelper(); + //res = http.GetHtml(item); + //cookie = res.UpdateCookies(cookie); + throw new Exception(error); + } + } + else if (html.Contains("redirectUrl")) + { + //{"content":{"data":{"redirect":true,"qrCodeStatus":"CONFIRMED","redirectUrl":"https://www.alimama.com/membersvc/my.htm?domain=taobao&service=user_on_taobao&sign_account=886e9e0358b2f9b386ba2d4ad40b7b86","asyncUrls":["https://passport.alibaba.com/mini_apply_st.js?callback=callback&site=0&token=1g1LYnbdoy6n6Y5mWfW0xEw"],"resultCode":100},"status":0,"success":true},"hasError":false} + url = data["redirectUrl"].ToString(); + } + item = new HttpItem(); + item.URL = url; + item.Method = "GET"; + item.Cookie = cookie; + item.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + item.Referer = "https://login.taobao.com/"; + item.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"; + + //var nickName = GetUserNick(ref cookie); + + http = new HttpHelper(); + res = http.GetHtml(item); + cookie = res.UpdateCookies(cookie); + + if (string.IsNullOrEmpty(res.RedirectUrl)) + { + item = new HttpItem(); + item.URL = "https://pub.alimama.com/common/getUnionPubContextInfo.json"; + item.Method = "GET"; + item.Cookie = cookie; + item.Referer = "https://pub.alimama.com/third/manage/record/site.htm"; + item.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + http = new HttpHelper(); + res = http.GetHtml(item); + cookie = res.UpdateCookies(cookie); + if (res.Html.ToLower().Contains("nologin")) + { + throw new Exception("登录不成功"); + } + //MessageBox.Show(cookie); + } + else + { + item = new HttpItem(); + item.URL = res.RedirectUrl; + item.Method = "GET"; + item.Cookie = cookie; + item.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + item.Referer = "https://login.taobao.com/"; + item.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"; + item.Header.Add("sec-fetch-dest", "document"); + item.Header.Add("sec-fetch-mode", "navigate"); + item.Header.Add("sec-fetch-site", "cross-site"); + item.Header.Add("upgrade-insecure-requests", "1"); + http = new HttpHelper(); + res = http.GetHtml(item); + cookie = res.UpdateCookies(cookie); + + item = new HttpItem(); + item.URL = res.RedirectUrl; + item.Method = "GET"; + item.Cookie = cookie; + item.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + item.Referer = "https://login.taobao.com/"; + item.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"; + http = new HttpHelper(); + res = http.GetHtml(item); + cookie = res.UpdateCookies(cookie); + } + } + catch (Exception ex) + { + //if (ex.Message == error) + throw new Exception(error); + } + return qrState.已确认; + } + return qrState.未扫码; + } + + /// + /// 从url中提取对象 + /// + /// + /// + /// + public string getTarget(string url, string target) + { + var arr = url.Split(new char[] { '&' }); + var tars = arr.FirstOrDefault(p => p.Contains(target) && p.Contains("=")); + if (!string.IsNullOrEmpty(tars)) + { + return tars.Split(new char[] { '=' })[1]; + } + + return ""; + } + + /// + /// 从cookie中获取token + /// + /// + /// + public string getTbToken(string cookie) + { + var arr = cookie.Split(new char[] { ';' }); + var tars = arr.FirstOrDefault(p => p.Contains("_tb_token")); + if (!string.IsNullOrEmpty(tars)) + { + return tars.Split(new char[] { '=' })[1]; + } + return ""; + } + + + /// + /// 根据页面获取用户名称 + /// + /// + /// + public static string GetUserNick(ref string cookie) + { + try + { + var url = "https://member1.taobao.com/member/fresh/account_security.htm"; + var item = new HttpItem() + { + URL = "https://member1.taobao.com/member/fresh/account_security.htm", + Method = "get", + IsToLower = false, + Referer = "https://buyertrade.taobao.com/trade/itemlist/list_bought_items.htm?spm=a21bo.2017.1997525045.2.244011d9PuKjma", + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36", + ContentType = "application/json;charset=UTF-8", + Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", + Cookie = cookie + }; + var http = new HttpHelper(); + var result = http.GetHtml(item); + cookie = result.UpdateCookies(cookie); + + if (result.Html.Contains("\"登录页面\"改进建议") || result.RedirectUrl.Contains("login")) + { + return null; + } + else + { + HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); + doc.LoadHtml(result.Html); + HtmlNode node = doc.DocumentNode; + var uid = node.SelectNodes("//*[@id=\"main-content\"]/dl/dd[1]/ul/li[1]/span[2]"); + var st = uid[0].InnerHtml; + + return st; + } + } + catch (Exception) + { + return ""; + } + } + + /// + /// 提交验证码 + /// + /// + /// + public string verifySmsCode(verifyStruct vs) + { + string cookie = vs.cookie; + var verItem = new HttpItem(); + verItem.URL = $"https://passport.taobao.com/iv/identity_verify.htm?tag=8&htoken={vs.fmh}&appName="; + verItem.Method = "POST"; + verItem.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + verItem.Referer = vs.refer; + verItem.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"; + verItem.Cookie = vs.cookie; + verItem.Postdata = $"_tb_token_={vs._tb_token_}&action=verify_action&event_submit_do_validate=notNull&_fm.v._0.t={vs.fmt}&_fm.v._0.h={vs.fmh}&_fm.v._0.ty={vs.fmt}&_fm.v._0.c=pc&_fm.v._0.p={vs.fmp}&_fm.v._0.a={vs.fma}&_fm.v._0.ph={vs.fmph}&_fm.v._0.pho=sms&ua="; + var http = new HttpHelper(); + var verRes = http.GetHtml(verItem); + cookie = verRes.UpdateCookies(cookie); + + //verItem.URL = verRes.ResponseUrl; + verItem.URL = verRes.ResponseUri; + verItem.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"; + verItem.Method = "GET"; + verItem.Cookie = cookie; + + var nickName = GetUserNick(ref cookie); + if (!string.IsNullOrEmpty(nickName)) + { + return cookie; + } + return string.Empty; + } + + /// + /// 二次验证 + /// + /// + /// + /// + /// + //public verifyStruct CheckLogin(string url, string cookie, string refer) + public string CheckLogin(string url, ref string cookie, string refer) + { + var item = new HttpItem() + { + URL = url, + Encoding = Encoding.GetEncoding("utf-8"), + Method = "get", + IsToLower = false, + Cookie = cookie, + Referer = refer, + Timeout = 100000, + ReadWriteTimeout = 30000, + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = false + }; + var http = new HttpHelper(); + var res = http.GetHtml(item); + var html = res.Html; + cookie = res.UpdateCookies(cookie); + + HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument(); + doc.LoadHtml(html); + var iframe = doc.DocumentNode.SelectSingleNode("//iframe"); + if (iframe != null) + { + string src = iframe.Attributes["src"].Value; + + var confirm = new HttpItem() + { + URL = src, + Method = "get", + IsToLower = false, + Cookie = cookie, + Referer = url, + Timeout = 100000, + ReadWriteTimeout = 30000, + Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*", + UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "application/x-www-form-urlencoded", + Allowautoredirect = true + }; + var confirmRes = http.GetHtml(confirm); + var confirmHtml = confirmRes.Html; + cookie = confirmRes.UpdateCookies(cookie); + + if (confirmHtml.Contains("window.location.href")) + { + var location = confirmHtml.Substring(confirmHtml.IndexOf("window.location.href"), confirmHtml.Length - confirmHtml.IndexOf("window.location.href")); + location = location.Substring(0, location.IndexOf("+window._iv_umidfg")); + location = location.Replace("window.location.href = ", "").Replace("\"", ""); + + confirm.URL = location; + confirm.Cookie = cookie; + var secConfirm = http.GetHtml(confirm); + cookie = res.UpdateCookies(cookie); + //var secUrl = secConfirm.ResponseUrl; + var secUrl = secConfirm.ResponseUri; + var htoken = getTarget(secUrl, "htoken"); + //验证码流程 + if (secUrl.Contains("tag=8")) + { + doc.LoadHtml(secConfirm.Html); + var phone = doc.GetElementbyId("J_MobileVal"); + var num = phone.Attributes["value"].Value; + var area = doc.GetElementbyId("areaCode"); + var areaCode = area.Attributes["value"].Value; + + confirm.URL = $"https://passport.taobao.com/iv/phone/send_code.do?htoken={htoken}&phone={num}&type=phone&area={areaCode}&tag={areaCode}&_={GetTimeSpan(DateTime.Now)}"; + + confirm.Referer = secUrl; + var codeRes = http.GetHtml(confirm); + cookie = codeRes.UpdateCookies(cookie); + var codeHtml = codeRes.Html; + if (codeHtml.Contains("验证码发送成功")) + { + smsCode sms = new smsCode(); + if (sms.ShowDialog() == DialogResult.OK && !string.IsNullOrEmpty(sms.sms)) + { + verifyStruct vs = new verifyStruct(); + vs.fma = areaCode; + vs.fmc = "pc"; + vs.fmh = htoken; + vs.fmp = num; + vs.fmph = sms.sms; + vs._tb_token_ = getTbToken(cookie); + vs.cookie = cookie; + vs.refer = secUrl; + var result = ""; + var starter = DateTime.Now; + while (string.IsNullOrEmpty(result) && DateTime.Now < starter.AddMinutes(2)) + { + result = verifySmsCode(vs); + Thread.Sleep(2000); + } + if (!string.IsNullOrEmpty(result)) + { + MessageBox.Show(result); + } + else + { + throw new Exception("超时"); + } + } + } + } + ///自动同意流程 + else + { + var areaCode = string.Empty; + var result = ""; + var starter = DateTime.Now; + //var refere = $"https://passport.taobao.com/iv/mini/identity_verify.htm?tag={areaCode}&htoken={htoken}&appName="; + var refere = secUrl.Replace("iv/identity_verify", "iv/mini/identity_verify");//https://passport.taobao.com/iv/identity_verify.htm?tag=524288&htoken=HPmfPaArell-__dnrHBll3L4LgDKywvDyBjXmQwhR2pzlGGxnhU7ssR5tJ9xUDUy&appName= + while (string.IsNullOrEmpty(result) && DateTime.Now < starter.AddMinutes(2)) + { + result = AutoAgree($"https://passport.taobao.com/iv/onekey/check_status.do?htoken={htoken}", ref cookie, secUrl, refere); + Thread.Sleep(2000); + } + if (!string.IsNullOrEmpty(result)) + return result; + else + { + //超时 + } + + //if (!string.IsNullOrEmpty(result)) + //{ + // HttpItem testor = new HttpItem(); + // var time = GetTimeSpan(DateTime.Now); + // testor.URL = $"https://www.alimama.com/index.htm"; + // testor.Cookie = result; + // testor.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"; + // item.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + // testor.Referer = "https://www.alimama.com/index.htm"; + // var r = http.GetHtml(testor, ref result).Html; + // MessageBox.Show(result); + // //testor.URL = "https://media.alimama.com/user/base_info.htm"; + // //r = http.GetHtml(testor, ref result).Html; + //} + //else + //{ + // //超时 + //} + } + } + } + return null; + } + + /// + /// 手淘自动同意 + /// + /// + /// + /// + /// + public string AutoAgree(string url, ref string cookie, string refer, string refere) + { + var autoItem = new HttpItem(); + autoItem.URL = url; + autoItem.Cookie = cookie; + autoItem.Referer = refere; + autoItem.Method = "GET"; + autoItem.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; + autoItem.Accept = "application/json, text/javascript, */*; q=0.01"; + var http = new HttpHelper(); + var autoRes = http.GetHtml(autoItem); + cookie = autoRes.UpdateCookies(cookie); + if (autoRes.Html.Contains("loginBySafe.htm?havana_iv_token")) + { + //{"hasError":false,"content":{"ivToken":"CN-SPLIT-AQjUwM7JAhDYBCINaGF2YW5hX2FwcF9pdjIBATi056Cm8S5AAUoQZFB4_ulEvO8HjakHUwWV1BP74LVaZpLxJn5AoM2Cb9tGdIod","code":"1","url":"https:\/\/login.taobao.com\/member\/loginBySafe.htm?havana_iv_token=CN-SPLIT-AQjUwM7JAhDYBCINaGF2YW5hX2FwcF9pdjIBATi056Cm8S5AAUoQZFB4_ulEvO8HjakHUwWV1BP74LVaZpLxJn5AoM2Cb9tGdIod&sub=false&c_is_scure=true&from=alimama&style=default&css_style=default&tpl_redirect_url=https%3A%2F%2Fwww.alimama.com%2Findex.htm&user_num_id=691249236&login_type=3&loginsite=0&lang=zh_CN&appkey=00000000&new_iv_check=true"}} + var html1 = autoRes.Html; + var autoObj = JObject.Parse(autoRes.Html); + autoItem.URL = autoObj["content"]["url"].ToString(); + autoItem.Allowautoredirect = true; + var res = http.GetHtml(autoItem); + cookie = res.UpdateCookies(cookie); + //var cookice = res.Header["Set-Cookie"]; + //TODO 这里位置返回的数据有问题 + + var html = res.Html; + var reg = Regex.Match(html, @"var\s*?result\s*?=\s*?(?<重定向Json>[^;]+?);"); + if (reg.Success) + return reg.Groups["重定向Json"].Value; + } + else if (autoRes.Html.Contains("会话已失效")) + { + //throw new Exception("会话已失效"); + } + return string.Empty; + } + + #region 其他 + /// + /// 日期转换成时间戳Timestamp + /// + /// + /// + public long GetTimeSpan(DateTime time) + { + DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + + return (long)(time - dtStart).TotalMilliseconds; + } + + public enum qrState + { + 未扫码, + 已扫码, + 已确认, + 已发码, + 登录成功, + 二维码超时, + 确认超时 + } + + public enum d + { + 生成二维码, + 二维码已确认, + 二维码过期, + 登录成功, + 开始执行, + 验证码已发送, + 手淘点击确认, + 发送完毕, + 确认超时 + } + + /// + /// + /// + public class verifyStruct + { + /// + /// 从cookie中获取 + /// + public string _tb_token_ { get; set; } + + public string action { get; set; } = "verify_action"; + + public string event_submit_do_validate { get; set; } = "notNull"; + + /// + /// 来源渠道 + /// + public string fmt { get; set; } = "8"; + + /// + /// htoken + /// + public string fmh { get; set; } + + /// + /// 来源渠道 + /// + public string fmc { get; set; } = "8"; + + /// + /// 电话号码 + /// + public string fmp { get; set; } + + /// + /// 地区码 + /// + public string fma { get; set; } + + /// + /// 验证码 + /// + public string fmph { get; set; } + + /// + /// 固定 + /// + public string fmpho { get; set; } = "sms"; + + public string cookie { get; set; } + + public string refer { get; set; } + } + #endregion + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + View(); + } + } +} diff --git a/类库/Api.Framework/UIForm/AliQrCordControl.resx b/类库/Api.Framework/UIForm/AliQrCordControl.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/Api.Framework/UIForm/AliQrCordControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/Api.Framework/UIForm/SetConnectionConfig.Designer.cs b/类库/Api.Framework/UIForm/SetConnectionConfig.Designer.cs new file mode 100644 index 0000000..abc5336 --- /dev/null +++ b/类库/Api.Framework/UIForm/SetConnectionConfig.Designer.cs @@ -0,0 +1,264 @@ +namespace Api.Framework.UIForm +{ + partial class SetConnectionConfig + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SetConnectionConfig)); + this.toolTip1 = new System.Windows.Forms.ToolTip(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.groupControl2 = new DevExpress.XtraEditors.GroupControl(); + this.textEdit5 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit4 = new DevExpress.XtraEditors.TextEdit(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl6 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).BeginInit(); + this.groupControl2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // simpleButton2 + // + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(223, 371); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(160, 47); + this.simpleButton2.TabIndex = 9; + this.simpleButton2.Text = "完成配置"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.labelControl1); + this.groupControl1.Controls.Add(this.radioGroup1); + this.groupControl1.Location = new System.Drawing.Point(12, 12); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(558, 107); + this.groupControl1.TabIndex = 11; + this.groupControl1.Text = "数据库选择"; + // + // labelControl1 + // + this.labelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelControl1.Appearance.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(192)))), ((int)(((byte)(0))))); + this.labelControl1.Appearance.Options.UseFont = true; + this.labelControl1.Appearance.Options.UseForeColor = true; + this.labelControl1.Location = new System.Drawing.Point(362, 34); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(44, 19); + this.labelControl1.TabIndex = 8; + this.labelControl1.Text = "(推荐)"; + // + // radioGroup1 + // + this.radioGroup1.Location = new System.Drawing.Point(108, 24); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "Sqlite(精巧型数据库、免安装、免配置)"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "Mysql(服务型数据库、需要单独安装或购买云数据库)")}); + this.radioGroup1.Size = new System.Drawing.Size(393, 71); + this.radioGroup1.TabIndex = 7; + this.radioGroup1.SelectedIndexChanged += new System.EventHandler(this.radioGroup1_SelectedIndexChanged); + // + // groupControl2 + // + this.groupControl2.Controls.Add(this.textEdit5); + this.groupControl2.Controls.Add(this.textEdit4); + this.groupControl2.Controls.Add(this.simpleButton1); + this.groupControl2.Controls.Add(this.textEdit3); + this.groupControl2.Controls.Add(this.labelControl6); + this.groupControl2.Controls.Add(this.textEdit2); + this.groupControl2.Controls.Add(this.textEdit1); + this.groupControl2.Controls.Add(this.labelControl5); + this.groupControl2.Controls.Add(this.labelControl4); + this.groupControl2.Controls.Add(this.labelControl3); + this.groupControl2.Controls.Add(this.labelControl2); + this.groupControl2.Location = new System.Drawing.Point(12, 124); + this.groupControl2.Name = "groupControl2"; + this.groupControl2.Size = new System.Drawing.Size(558, 232); + this.groupControl2.TabIndex = 12; + this.groupControl2.Text = "Mysql 详细配置"; + // + // textEdit5 + // + this.textEdit5.Location = new System.Drawing.Point(192, 188); + this.textEdit5.Name = "textEdit5"; + this.textEdit5.Properties.PasswordChar = '*'; + this.textEdit5.Size = new System.Drawing.Size(160, 20); + this.textEdit5.TabIndex = 15; + // + // textEdit4 + // + this.textEdit4.Location = new System.Drawing.Point(193, 148); + this.textEdit4.Name = "textEdit4"; + this.textEdit4.Size = new System.Drawing.Size(269, 20); + this.textEdit4.TabIndex = 14; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(360, 186); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(102, 23); + this.simpleButton1.TabIndex = 13; + this.simpleButton1.Text = "尝试连接"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit3 + // + this.textEdit3.Location = new System.Drawing.Point(193, 107); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Size = new System.Drawing.Size(269, 20); + this.textEdit3.TabIndex = 9; + // + // labelControl6 + // + this.labelControl6.Location = new System.Drawing.Point(120, 190); + this.labelControl6.Name = "labelControl6"; + this.labelControl6.Size = new System.Drawing.Size(52, 14); + this.labelControl6.TabIndex = 4; + this.labelControl6.Text = "登录密码:"; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(192, 73); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Properties.Mask.EditMask = "d"; + this.textEdit2.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.Numeric; + this.textEdit2.Size = new System.Drawing.Size(269, 20); + this.textEdit2.TabIndex = 7; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(192, 34); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(269, 20); + this.textEdit1.TabIndex = 6; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(132, 151); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(40, 14); + this.labelControl5.TabIndex = 3; + this.labelControl5.Text = "用户名:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(108, 110); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(64, 14); + this.labelControl4.TabIndex = 2; + this.labelControl4.Text = "数据库名称:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(132, 75); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(40, 14); + this.labelControl3.TabIndex = 1; + this.labelControl3.Text = "端口号:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(108, 37); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(64, 14); + this.labelControl2.TabIndex = 0; + this.labelControl2.Text = "服务器地址:"; + // + // SetConnectionConfig + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(584, 433); + this.Controls.Add(this.groupControl2); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.simpleButton2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.IconOptions.Icon = ((System.Drawing.Icon)(resources.GetObject("SetConnectionConfig.IconOptions.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SetConnectionConfig"; + this.Text = "设置存储模式"; + this.Load += new System.EventHandler(this.SetConnectionConfig_Load); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl2)).EndInit(); + this.groupControl2.ResumeLayout(false); + this.groupControl2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit5.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit4.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.ToolTip toolTip1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.GroupControl groupControl1; + private DevExpress.XtraEditors.GroupControl groupControl2; + private DevExpress.XtraEditors.TextEdit textEdit3; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl6; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit5; + private DevExpress.XtraEditors.TextEdit textEdit4; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/UIForm/SetConnectionConfig.cs b/类库/Api.Framework/UIForm/SetConnectionConfig.cs new file mode 100644 index 0000000..587b691 --- /dev/null +++ b/类库/Api.Framework/UIForm/SetConnectionConfig.cs @@ -0,0 +1,105 @@ +using Api.Framework.Tools; +using Api.Framework.Tools; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Api.Framework.UIForm +{ + /// + /// 选择数据库 + /// + public partial class SetConnectionConfig : BaseForm + { + public SetConnectionConfig() + { + InitializeComponent(); + } + + private void SetConnectionConfig_Load(object sender, EventArgs e) + { + this.Icon = PublickIcon; + var config = ApiClient.Setting.DbConfig; + //Data Source = localhost; Initial Catalog = test_db; Persist Security Info = True; User ID = root; Password = 123456; Min Pool Size = 1; Max Pool Size = 3; + if (config != null && !string.IsNullOrEmpty(config.ConnectionString)) + { + var reg = Regex.Match(config.ConnectionString, "Data Source=(?.*?);Initial Catalog=(?.*?);Persist Security Info=True;User ID=(?.*?);Password=(?.*?);Port=(?.*?);"); + if (reg.Success) + { + this.textEdit1.Text = reg.Groups["db_host"].ToString(); + this.textEdit3.Text = reg.Groups["db_name"].ToString(); + this.textEdit2.Text = reg.Groups["db_port"].ToString(); + this.textEdit4.Text = reg.Groups["db_user"].ToString(); + this.textEdit5.Text = reg.Groups["db_pass"].ToString(); + } + } + + radioGroup1_SelectedIndexChanged(null,null); + } + + ConnectionConfig tempConfig = null; + + public bool IsOk { get; set; } + + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + tempConfig = new ConnectionConfig(); + //SessionThreadLocal.Clear(); + tempConfig.ConnectionString =string.Format("Data Source={0};Initial Catalog={1};Persist Security Info=True;User ID={2};Password={3};Port={4};Min Pool Size = 5; Max Pool Size = 30;Charset=utf8;", this.textEdit1.Text,this.textEdit3.Text,this.textEdit4.Text,this.textEdit5.Text, this.textEdit2.Text); + tempConfig.DatabaseType = DatabaseType.MYSQL; + var session = ApiClient.GetSession(tempConfig); + session.BeginTransaction(); + session.Rollback(); + ShowSuccess("恭喜您,数据库可以成功连接!"); + } + catch (Exception ex) + { + tempConfig = null; + ShowError(ex); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + if (this.radioGroup1.SelectedIndex==0) + { + + string src = string.Format("Data Source={0};Version=3;password={1};Journal Mode=WAL;", Util.MapFile("数据库.db", "Config"), ""); + tempConfig = new ConnectionConfig() { ConnectionString = src, DatabaseType = DatabaseType.SQLITE }; + ApiClient.Setting.DbConfig = tempConfig; + IsOk = true; + } + else + { + if (tempConfig == null) throw new Exception("请先测试Mysql 是否可以正常连接!"); + IsOk = true; + } + ApiClient.Setting.DbConfig = tempConfig; + //Util.Save(ApiClient.Setting); + this.Close(); + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void radioGroup1_SelectedIndexChanged(object sender, EventArgs e) + { + this.groupControl2.Enabled = this.radioGroup1.SelectedIndex == 1; + } + } +} diff --git a/类库/Api.Framework/UIForm/SetConnectionConfig.resx b/类库/Api.Framework/UIForm/SetConnectionConfig.resx new file mode 100644 index 0000000..451a90d --- /dev/null +++ b/类库/Api.Framework/UIForm/SetConnectionConfig.resx @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAUdEVYdFRpdGxlAEh5cGVybGluaztXZWI7Bv6gzgAA + BGFJREFUWEfFlXtQVFUcxxUWsEwT/pFmUsnRNI0EEi2EeAwiYOqyKwuLYAGxAgt7eQTyUAZalOWZ1oxB + BqQwU1pOBj3MxBZiWpYWQeSNoBINWiZvcMr8ds4VaWGvI39dz+znj/O933u/v3vO756dB+CJwinyCafI + J5win3CKfMIp8gmnyCecIp9winxiKMwc82dhpAedzx6P9RvkzZj8Px7eLCCYEMwITxEWTvH0lGZM0A+b + k39GJke4kUiWtiIwtuCLgLj836VMHvwU2fCVZ0EccQjCsIwBr71Jles3e9gQ7zMEEx9ZmhXxfzlHPy1y + uojZBczfHaFczyiPD2kudeCvoVFyaea4PTiM6rrLCIxRjbzssN3LXSJ3iM4oGqqpb8HNPwfxz717+Pf+ + fZDftL9G2/zA/7q3O8mgRRiTSwYF0GUUSJncr+qaOtkH9d0aRNv1ATR29aOhow/a1mv4uakbal07lB+W + w8knXCMMS6+uuKBB97XfoG3uhoZAfbr2G6hvuw5NSy/qrvQgp+gU3hBF/kQyLAmmNI+rADNpTO7w+MRd + 3Lh1BwfzS7DVn8FGz2Bs9g5FgOIQ5OlFCIx/H/5MDsSRWdglU2J7SBo8glLg/VYq3CQM7L1CWL9UnoHy + impUN3YhObcErhJmgmSsJND+MCiANtFCv6hsMgVaewfgKAyHpzSqyFhg8tJiC0v7wLiCyebOPgyNTuD2 + 8Bhu3hlBb/8fuNTWg3PVOhwrq4CjiPl7tZ2rD/UHRKR86huhxEVdJ1LySuEsjqZB62gOwaAA2qHPiiMP + 03w0dveTt4/Btt3BsQJTM1sLSysXX7lqrKm9F2ptCyrUOpz5UYviM1XIKjyNWGUhpNGZ2CJSTK6ycfZf + ZL7UcZdf8IHQ/UdwTtPCroCjMJIGvUKgfWBQAO1Oc6EsfXR8YpLd85NnL2JHcDI8g/ZjR2ga/BUqiMKV + 2LY3BW4BiXCWxMNJHEtCGRYXSRzcpfHw2JPA+t9JOopfr1xF+Tc1eDfrOF57M+wuybAmPHIFlngGJV74 + paGNNM9VtoFqm3ugbujCeW0rTv2gwdGTlWDeOwZ/sr+27tJuN4mirfT09zhxtgqffVeLr9UNOK9pRZWu + A9/WXkZZZQ3SjpQhNCEXNm5+9SRjNeHRPWDt4O2xhzk8ovroc7JsxThYcAIH8kuRnFeCpOxP2PC341XY + IpRNPP/iq8y6TVtDpFGZY8oPypGo+hipZK9TiTeFkJxTjNjMQoQk5MDRZ9+45QvWQSRjKcFkOlevAPoV + 0FPMYvkaO2ennTK1izhq0NlXASeRnN0/h537sMkreHiDi6/W4rmVYmOB6SqB6YJlK9ZudH2c39zSSkSe + vZxAT0UjgwL0iqDf6BLCMsJawgaCHcF+ClvCGgJ9E7qXCwhz9c8IZzP1J6zwoAjaD/TspgGLCIv1oHO6 + h3S1Hv7JzNlvkDdb4BtOkU84RT7hFPmEU+QTTpFPOEU+4RT5hFPkD8z7D3RuucIJQA76AAAAAElFTkSu + QmCC + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAgBAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5ZgAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5RB1U + +UQdVPlEHVT5RB1U+UQdVPlEHVT5RB1U+UQdVPlEHVT5RB1U+UQdVPlEHVT5RB1U+UQdVPlEHVT5RB1U + +UQdVPlEHVT5IgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdVPn/HVT57h1U+YgdVPkiHVT5Ih1U + +bsdVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPndAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1U+f8dVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPlmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+d0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAdVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPnuHVT5dx1U+REAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAB1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5mR1U+f8dVPnMHVT5Zh1U+REdVPkRHVT5qh1U + +bsdVPm7HVT5ux1U+bsdVPlmAAAAAAAAAAAAAAAAHVT5mR1U+bsdVPm7HVT5ux1U+bsdVPmIAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAHVT5/x1U+f8dVPn/HVT5/x1U+VUAAAAAHVT5/x1U+f8dVPn/HVT57h1U + +VUdVPlmHVT5/x1U+f8dVPn/HVT5/x1U+f8dVPkzAAAAAB1U+YgdVPn/HVT5/x1U+f8dVPn/HVT57h1U + +TMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdVPn/HVT5/x1U+f8dVPn/HVT5RAAAAAAdVPn/HVT5/x1U + +f8dVPn/HVT5dwAAAAAdVPmIHVT5/x1U+f8dVPn/HVT5/x1U+d0dVPl3HVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPlEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1U+f8dVPn/HVT5/x1U+f8dVPlEAAAAAB1U + +f8dVPn/HVT5/x1U+f8dVPl3AAAAAAAAAAAdVPnMHVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPn/HVT5dwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5/x1U+f8dVPn/HVT5/x1U + +UQAAAAAHVT5/x1U+f8dVPn/HVT5/x1U+XcAAAAAAAAAAB1U+REdVPnuHVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+ZkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdVPn/HVT5/x1U + +f8dVPn/HVT5RAAAAAAdVPn/HVT5/x1U+f8dVPn/HVT5dwAAAAAAAAAAAAAAAB1U+UQdVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPnMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1U + +f8dVPn/HVT5/x1U+f8dVPlEAAAAAB1U+f8dVPn/HVT5/x1U+f8dVPl3AAAAAAAAAAAAAAAAAAAAAB1U + +bsdVPn/HVT5/x1U+f8dVPn/HVT5/x1U+TMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAHVT5/x1U+f8dVPn/HVT5/x1U+UQAAAAAHVT5/x1U+f8dVPn/HVT5/x1U+XcAAAAAAAAAAAAA + AAAdVPlmHVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5zAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAdVPn/HVT5/x1U+f8dVPn/HVT5RAAAAAAdVPn/HVT5/x1U+f8dVPn/HVT5dwAA + AAAAAAAAHVT5Mx1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5iAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1U+f8dVPn/HVT5/x1U+f8dVPlEAAAAAB1U+f8dVPn/HVT5/x1U + +f8dVPl3AAAAAB1U+REdVPnuHVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5ZgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5/x1U+f8dVPn/HVT5/x1U+UQAAAAAHVT5/x1U + +f8dVPn/HVT5/x1U+XcAAAAAHVT5zB1U+f8dVPn/HVT5/x1U+f8dVPmZHVT5VR1U+f8dVPn/HVT5/x1U + +f8dVPnuHVT5MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdVPn/HVT5/x1U+f8dVPn/HVT5RAAA + AAAdVPn/HVT5/x1U+f8dVPn/HVT5dx1U+WYdVPm7HVT5ux1U+bsdVPm7HVT5qh1U+REAAAAAHVT5iB1U + +f8dVPn/HVT5/x1U+f8dVPnMHVT5EQAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPlEAAAAAB1U+f8dVPn/HVT5/x1U+f8dVPl3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAHVT5ux1U+f8dVPn/HVT5/x1U+f8dVPl3AAAAAAAAAAAAAAAAAAAAAAAAAAAdVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+UQAAAAAHVT5/x1U+f8dVPn/HVT5/x1U+XcdVPlmHVT5ux1U+bsdVPm7HVT5ux1U + +bsdVPm7HVT5ux1U+bsdVPnMHVT5/x1U+f8dVPn/HVT5/x1U+XcAAAAAAAAAAAAAAAAAAAAAAAAAAB1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5RAAAAAAdVPn/HVT5/x1U+f8dVPn/HVT5dx1U+XcdVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5dwAAAAAAAAAAAAAAAAAA + AAAAAAAAHVT5dx1U+XcdVPl3HVT5dx1U+XcdVPkiAAAAAB1U+f8dVPn/HVT5/x1U+f8dVPl3HVT5dx1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPl3AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5/x1U+f8dVPn/HVT5/x1U + +XcdVPkzHVT5RB1U+UQdVPlEHVT5RB1U+UQdVPlEHVT5RB1U+UQdVPlEHVT5RB1U+UQdVPlEHVT5RB1U + +SIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdVPlEHVT5dx1U+XcdVPkRAAAAAAAAAAAdVPn/HVT5/x1U + +f8dVPn/HVT5dwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5Zh1U+f8dVPn/HVT5/x1U+e4dVPkRAAAAAB1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+d0dVPm7HVT5ux1U+aodVPl3HVT5dx1U+XcdVPlEHVT5RB1U + +UQdVPkRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdVPndHVT5/x1U+f8dVPn/HVT5/x1U + +XcAAAAAHVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5iAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1U+e4dVPn/HVT5/x1U + +f8dVPn/HVT5dwAAAAAdVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPndAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVT5iB1U + +f8dVPn/HVT5/x1U+e4dVPkiAAAAAB1U+UQdVPlEHVT5dx1U+XcdVPl3HVT5qh1U+bsdVPm7HVT57h1U + +f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPn/HVT5/x1U+f8dVPkzAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAHVT5dx1U+bsdVPmqHVT5MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAdVPkiHVT5RB1U+UQdVPlVHVT5dx1U+XcdVPmIHVT5ux1U+WYAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA///////////vgAAP4AAAD+AAAAfgAAAH4A///+AADgfggAQH4IIAD+CD + AB/ggwA/4IOAf+CDwH/gg4B/4IMAP+CCAB/gggAP4IAEB8CD/gfAgAAHwIAAB8CAAAf/gAAH4YP//8CA + AD/AgAAPwIAAD8CAAAfh//AH//////////8= + + + \ No newline at end of file diff --git a/类库/Api.Framework/UIForm/smsCode.Designer.cs b/类库/Api.Framework/UIForm/smsCode.Designer.cs new file mode 100644 index 0000000..874aba7 --- /dev/null +++ b/类库/Api.Framework/UIForm/smsCode.Designer.cs @@ -0,0 +1,75 @@ +namespace PcLogger +{ + partial class smsCode + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(2, 14); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(166, 21); + this.textBox1.TabIndex = 0; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(175, 13); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 1; + this.button1.Text = "提交"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // smsCode + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(257, 49); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "smsCode"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "输入验证码"; + this.Load += new System.EventHandler(this.smsCode_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/类库/Api.Framework/UIForm/smsCode.cs b/类库/Api.Framework/UIForm/smsCode.cs new file mode 100644 index 0000000..cfe4057 --- /dev/null +++ b/类库/Api.Framework/UIForm/smsCode.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace PcLogger +{ + /// + /// 阿里妈妈扫码协议登录验证码 + /// + public partial class smsCode : Form + { + public string sms { get; set; } + public smsCode() + { + InitializeComponent(); + sms = ""; + } + + /// + /// 提交验证码 + /// + /// + /// + private void button1_Click(object sender, EventArgs e) + { + var temp = textBox1.Text; + Regex regex = new Regex(@"^\d{6}$", RegexOptions.ECMAScript); + if (regex.IsMatch(temp)) + { + sms = textBox1.Text; + this.DialogResult = DialogResult.OK; + } + else + { + return; + } + } + + private void smsCode_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/类库/Api.Framework/UIForm/smsCode.resx b/类库/Api.Framework/UIForm/smsCode.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/Api.Framework/UIForm/smsCode.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/Api.Framework/WebClient.cs b/类库/Api.Framework/WebClient.cs new file mode 100644 index 0000000..a155215 --- /dev/null +++ b/类库/Api.Framework/WebClient.cs @@ -0,0 +1,491 @@ +using Api.Framework.Events; +using CsharpHttpHelper; +using Microsoft.Owin; +using Microsoft.Owin.Builder; +using Microsoft.Owin.Cors; +using Microsoft.Owin.Hosting; +using Owin; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Web.Http; + +[assembly: OwinStartup(typeof(Api.Framework.WebClient))] +namespace Api.Framework +{ + /// + /// web管理 + /// + public class WebClient + { + /// + /// 响应结果 + /// + public class Result + { + public int Code { get; set; } + + public int code { get => Code; } + + public object Message { get; set; } + + public object data { get => Message; } + } + + public class Util + { + /// + /// 将查询字符串解析转换为名值集合. + /// + /// + /// + /// + /// + public static NameValueCollection GetQueryString(string queryString, Encoding encoding) + { + queryString = queryString.Replace("?", ""); + NameValueCollection result = new NameValueCollection(StringComparer.OrdinalIgnoreCase); + if (!string.IsNullOrEmpty(queryString)) + { + int count = queryString.Length; + for (int i = 0; i < count; i++) + { + int startIndex = i; + int index = -1; + while (i < count) + { + char item = queryString[i]; + if (item == '=') + { + if (index < 0) + { + index = i; + } + } + else if (item == '&') + { + break; + } + i++; + } + string key = null; + string value = null; + if (index >= 0) + { + key = queryString.Substring(startIndex, index - startIndex); + value = queryString.Substring(index + 1, (i - index) - 1); + } + else + { + key = queryString.Substring(startIndex, i - startIndex); + } + result[key] = value; + if ((i == (count - 1)) && (queryString[i] == '&')) + { + result[key] = string.Empty; + } + } + } + return result; + } + + } + + private static IDisposable server = null; + public static bool IsStart + { + get + { + if (server == null) return false; + else return true; + } + } + + public static List GetNetwork() + { + List list = new List(); + NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); + foreach (NetworkInterface adapter in nics) + { + //判断是否为以太网卡 + //Wireless80211 无线网卡 Ppp 宽带连接 + //Ethernet 以太网卡 + //这里篇幅有限贴几个常用的,其他的返回值大家就自己百度吧! + if (adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet) + { + //获取以太网卡网络接口信息 + IPInterfaceProperties ip = adapter.GetIPProperties(); + //获取单播地址集 + UnicastIPAddressInformationCollection ipCollection = ip.UnicastAddresses; + foreach (UnicastIPAddressInformation _ip in ipCollection) + { + //InterNetwork IPV4地址 InterNetworkV6 IPV6地址 + //Max MAX 位址 + list.Add(_ip.Address); + } + } + } + + return list; + } + public static void Start(string ip, int port, bool throwExcption = true) + { + try + { + if (server != null) Close(); + + server = WebApp.Start($"http://{ip}:{port}/"); + ApiClient.Setting.ServerConfig.Host = ip; + ApiClient.Setting.ServerConfig.Port = port; + Api.Framework.Tools.Util.Save(ApiClient.Setting.ServerConfig); + + } + catch (Exception ex) + { + //Console.WriteLine("WebClient Start Error:" + ex.Message); + if (!throwExcption) return; + if (ex.InnerException != null) + { + var msg = ex.InnerException.Message; + if (msg.Contains("拒绝访问")) throw new Exception("权限不足,请关闭防火墙,并以管理员方式启动程序!"); + else if (msg.Contains("另一个程序正在使用此文件,进程无法访问。")) throw new Exception("端口号被其他应用占用,请更换端口号!"); + } + throw new Exception(ex.InnerException.Message); + } + } + + public static void Close() + { + if (server != null) + { + server.Dispose(); + server = null; + } + } + + //public void Configuration(IAppBuilder app) + //{ + // // ConfigureAuth(app); + // try + // { + // app.UseCors(CorsOptions.AllowAll); + + // app.Use(async (context, next) => + // { + // var respose = new Result(); + // //是否已经处理 + // try + // { + // bool is_handle = false; + // Dictionary Param = new Dictionary(); + // var contentType = context.Request.ContentType; + // if (context.Request.Method.ToLower() == "post") + // { + // if (contentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) + // { + // string body = new StreamReader(context.Request.Body, Encoding.UTF8).ReadToEnd(); + // var postdata = Util.GetQueryString(body, Encoding.UTF8); + // if (postdata != null) + // { + // foreach (var item in postdata.AllKeys) + // { + // Param[item] = postdata[item]; + // } + //} + // } + // } + // if (context.Request.Query != null && context.Request.Query.Count() > 0) + // { + // foreach (var item in context.Request.Query) + // { + // if (item.Value != null && item.Value.Length > 0) Param[item.Key] = item.Value[0]; + // } + // } + + // if (EventClient.StopParsing) return; + // var plugins = PluginClient.Plugins.ToArray(); + //var events = new WebRequestEvents(context, Param, respose); + // //正常事件解析 + // foreach (var plugin in plugins) + // { + // if (!plugin.IsRun) continue;//未运行 + // if (events.Cancel) break;//已取消传递 + // plugin.SDK.OnEvent(context, events); + // } + // } + // catch (Exception ex) + // { + // respose.Code = -1; + // respose.Message = ex.Message; + // } + // finally + // { + // if (respose.Message == null) + // { + // respose.Code = -1; + // respose.Message = $"请求成功,但未响应结果!{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; + // } + // var msg = HttpHelper.ObjectToJson(respose); + //context.Response.StatusCode = (int) HttpStatusCode.OK; + //context.Response.Write(msg); + // } + + // await next(); + // }); + + + // //app.Map("/api", map => + // //{ + // // map.Use(async (context, next) => + // // { + + // // System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); + // // sw.Start(); + // // context.Response.StatusCode = 200; + // // Uri uri = context.Request.Uri; + // // string ip = "未知IP"; + // // try + // // { + + // // switch (uri.AbsolutePath.ToLower()) + // // { + // // case "/api": + // // { + + // // break; + // // } + // // break; + // // default: + // // { + + // // context.Response.StatusCode = 404; + // // } + // // break; + // // } + // // ip = context.Request.RemoteIpAddress; + // // } + // // catch (Exception e) + // // { + // // context.Response.StatusCode = 500; + // // context.Response.Write("

" + e.Message + "

" + e.StackTrace); + // // EventClient.OnEvent(this,"【WebAPI处理请求出错】" + e.Message); + // // } + // // finally + // // { + + // // } + // // sw.Stop(); + // // TimeSpan ts = sw.Elapsed; + // // // Library.LogHelper.Log("【" + ts.TotalMilliseconds + "】【"+ip+"】" + uri.PathAndQuery, 90); + // // await next(); + // // }); + + // //}); + + // } + // catch (Exception ex) + // { + + // throw; + // } + //} + + #region 路由器初始化 + + /// + /// 默认 + /// + private static string _siteDir = Directory.GetCurrentDirectory() + "\\wwwroot"; + + /// + /// 配置管理器 + /// + /// + public void Configuration(IAppBuilder app) + { + app.UseCors(CorsOptions.AllowAll); + app.Use((context, fun) => + { + return RequestHandler(context, fun); + }); + } + + + + /// + /// 挂载静态数据 + /// + /// + /// + /// + public async Task RequestHandler(IOwinContext context, Func next) + { + try + { + var path = GetFilePath(context.Request.Path.Value); + + if (File.Exists(path)) + { + //Console.WriteLine(path); + await SetResponse(context, path); + } + else + { + await TodoApi(context, next); + } + } + catch (Exception) + { + } + await next(); + } + + private Task TodoApi(IOwinContext context, Func next) + { + var respose = new Result(); + try + { + bool is_handle = false; + Dictionary Param = new Dictionary(); + var contentType = context.Request.ContentType; + if (context.Request.Method.ToLower() == "post") + { + //Console.WriteLine(contentType); + if (contentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) + { + string body = new StreamReader(context.Request.Body, Encoding.UTF8).ReadToEnd(); + var postdata = Util.GetQueryString(body, Encoding.UTF8); + if (postdata != null) + { + foreach (var item in postdata.AllKeys) + { + Param[item] = HttpHelper.URLDecode(postdata[item]); + } + } + } + + } + + if (context.Request.Query != null && context.Request.Query.Count() > 0) + { + foreach (var item in context.Request.Query) + { + if (item.Value != null && item.Value.Length > 0) Param[item.Key] = HttpHelper.URLDecode(item.Value[0]); + } + } + + if (EventClient.StopParsing) return next(); + var plugins = PluginClient.Plugins.ToArray(); + var events = new WebRequestEvents(context, Param, respose); + //正常事件解析 + foreach (var plugin in plugins) + { + if (!plugin.IsRun) continue;//未运行 + if (events.Cancel) break;//已取消传递 + plugin.SDK.OnEvent(context, events); + } + } + catch (Exception ex) + { + respose.Code = -1; + respose.Message = ex.Message; + } + + if (respose.Message == null) + { + respose.Code = -1; + respose.Message = $"请求成功,但未响应结果!{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"; + } + var msg = HttpHelper.ObjectToJson(respose); + context.Response.StatusCode = (int)HttpStatusCode.OK; + return context.Response.WriteAsync(msg); + } + + /// + /// 查找本地数据,无数据 返回index + /// + /// + /// + public static string GetFilePath(string relPath) + { + if (string.IsNullOrEmpty(relPath) || relPath == "/") + { + relPath = "index.html"; + } + + return Path.Combine( + AppDomain.CurrentDomain.BaseDirectory + , _siteDir + , relPath.TrimStart('/').Replace('/', '\\')); + } + + /// + /// 设置返回contenttype 并返回数据 + /// + /// + /// + /// + public Task SetResponse(IOwinContext context, string path) + { + var perfix = Path.GetExtension(path); + if (perfix == ".html") + { + context.Response.ContentType = "text/html; charset=utf-8"; + return context.Response.WriteAsync(File.ReadAllText(path)); + } + else if (perfix == ".js") + { + context.Response.ContentType = "application/x-javascript"; + return context.Response.WriteAsync(File.ReadAllText(path)); + } + else if (perfix == ".css") + { + context.Response.ContentType = "text/css"; + return context.Response.WriteAsync(File.ReadAllText(path)); + } + else if (perfix == ".jpg" || perfix == ".jpeg") + { + context.Response.ContentType = "image/jpeg"; + return context.Response.WriteAsync(File.ReadAllBytes(path)); + } + else if (perfix == ".png") + { + context.Response.ContentType = "application/x-png"; + return context.Response.WriteAsync(File.ReadAllBytes(path)); + } + else if (perfix == ".mp4") + { + context.Response.ContentType = "video/mpeg4"; + return context.Response.WriteAsync(File.ReadAllBytes(path)); + } + else if (perfix == ".webp") + { + context.Response.ContentType = "image/webp"; + return context.Response.WriteAsync(File.ReadAllBytes(path)); + } + else if (perfix == ".gif") + { + context.Response.ContentType = "image/gif"; + return context.Response.WriteAsync(File.ReadAllBytes(path)); + } + else if (perfix == ".woff2") + { + context.Response.ContentType = "application/x-font-woff"; + return context.Response.WriteAsync(File.ReadAllBytes(path)); + } + + + return context.Response.WriteAsync(File.ReadAllText(path)); + } + #endregion + + } +} diff --git a/类库/Api.Framework/app.config b/类库/Api.Framework/app.config new file mode 100644 index 0000000..cdc92b8 --- /dev/null +++ b/类库/Api.Framework/app.config @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/Api.Framework/packages.config b/类库/Api.Framework/packages.config new file mode 100644 index 0000000..324568d --- /dev/null +++ b/类库/Api.Framework/packages.config @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/Api.Framework/supersocket.cmd b/类库/Api.Framework/supersocket.cmd new file mode 100644 index 0000000..4532661 --- /dev/null +++ b/类库/Api.Framework/supersocket.cmd @@ -0,0 +1,2 @@ +@echo off +SuperSocket.SocketService.exe -c %1 %2 \ No newline at end of file diff --git a/类库/Api.Framework/supersocket.sh b/类库/Api.Framework/supersocket.sh new file mode 100644 index 0000000..f3cd0d9 --- /dev/null +++ b/类库/Api.Framework/supersocket.sh @@ -0,0 +1,2 @@ +#!/bin/bash +mono SuperSocket.SocketService.exe -c $1 $2 \ No newline at end of file diff --git a/类库/Chat.Framework/App.config b/类库/Chat.Framework/App.config new file mode 100644 index 0000000..ca97710 --- /dev/null +++ b/类库/Chat.Framework/App.config @@ -0,0 +1,43 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/Chat.Framework/BaseEvent.cs b/类库/Chat.Framework/BaseEvent.cs new file mode 100644 index 0000000..2fb1dc4 --- /dev/null +++ b/类库/Chat.Framework/BaseEvent.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework +{ + /// + /// 事件基础类 + /// + public class ChatEvent + { + public bool IsToString { get; set; } + /// + /// 是否取消传递 + /// + public bool Cancel { get; set; } + /// + /// 创建时间 + /// + public DateTime CrtTime { get; private set; } + public ChatEvent() + { + CrtTime = DateTime.Now; + } + } +} diff --git a/类库/Chat.Framework/Chat.Framework.csproj b/类库/Chat.Framework/Chat.Framework.csproj new file mode 100644 index 0000000..e4e63a6 --- /dev/null +++ b/类库/Chat.Framework/Chat.Framework.csproj @@ -0,0 +1,340 @@ + + + + + + Debug + AnyCPU + {08421940-859B-4E93-B8D5-C4BEF64B0A95} + Library + Properties + Chat.Framework + Chat.Framework + v4.6.1 + 512 + + + + + + true + full + false + ..\..\Debug\ + DEBUG;TRACE + prompt + 4 + AnyCPU + ..\..\Debug\Chat.Framework.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + False + + + + ..\..\packages\EntityFramework.6.3.0\lib\net45\EntityFramework.dll + + + ..\..\packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll + + + False + ..\..\packages\Google.Protobuf.3.7.0\lib\net45\Google.Protobuf.dll + + + False + ..\..\Debug\Grant.Framework.dll + + + ..\..\DLL\Interop.MSScriptControl.dll + True + + + ..\..\packages\log4net.2.0.3\lib\net40-full\log4net.dll + + + False + ..\..\DLL\Newtonsoft.Json.dll + + + False + ..\..\PCRobot.Pack\bin\Debug\PCRobot.Pack.dll + False + + + False + ..\..\Debug\Robot.Framework.dll + False + + + ..\..\DLL\Socket.Framework.dll + + + ..\..\packages\SuperSocket.1.6.6.1\lib\net45\SuperSocket.Common.dll + + + ..\..\packages\SuperSocket.1.6.6.1\lib\net45\SuperSocket.Facility.dll + + + ..\..\packages\SuperSocket.ProtoBase.1.7.0.17\lib\net45\SuperSocket.ProtoBase.dll + + + ..\..\packages\SuperSocket.1.6.6.1\lib\net45\SuperSocket.SocketBase.dll + + + ..\..\packages\SuperSocket.Engine.1.6.6.1\lib\net45\SuperSocket.SocketEngine.dll + + + ..\..\packages\SuperSocket.Engine.1.6.6.1\lib\net45\SuperSocket.SocketService.exe + + + + ..\..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll + + + + + + + + + + + ..\..\packages\System.Net.NameResolution.4.3.0\lib\net46\System.Net.NameResolution.dll + + + ..\..\packages\System.Net.Security.4.3.0\lib\net46\System.Net.Security.dll + + + ..\..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll + + + + ..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll + + + ..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll + + + ..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll + + + ..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll + + + + + + + + + + + + + + False + ..\编译测试\UI.Framework.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + + + + + + + + + Form + + + FormSlide.cs + + + + Form + + + QQLoginForm.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + BrowserForm.cs + + + Form + + + LoginwxPassForm.cs + + + Form + + + PCLoginForm.cs + + + Form + + + SetwxhForm.cs + + + + + + + + + + + + + + + + + + + + + Form + + + LoginForm.cs + + + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + FormSlide.cs + + + QQLoginForm.cs + Designer + + + BrowserForm.cs + Designer + + + LoginForm.cs + Designer + + + LoginwxPassForm.cs + + + PCLoginForm.cs + + + SetwxhForm.cs + + + + + + + + + + {b54ae050-dd6c-4f73-95e8-9d8c1cf38ffe} + HttpHelper + False + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + + + + \ No newline at end of file diff --git a/类库/Chat.Framework/ChatClient.cs b/类库/Chat.Framework/ChatClient.cs new file mode 100644 index 0000000..f09704c --- /dev/null +++ b/类库/Chat.Framework/ChatClient.cs @@ -0,0 +1,573 @@ +using Chat.Framework.PCRobotSDK; +using Chat.Framework.Properties; +using Chat.Framework.QQSdk; +using Chat.Framework.QQSdk.Events; +using Chat.Framework.QQSdk.QPlus; +//using Chat.Framework.QQSdk.PCQQ; +using Chat.Framework.WXSdk; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.Implement; +using Chat.Framework.WXSdk.UIForm; +using CsharpHttpHelper; +using Grant.Framework; +using Newtonsoft.Json; +using PCRobot.Pack; +using Robot.Framework; +using Robot.Framework.Entities; +using SuperSocket.SocketBase; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework +{ + /// + /// 机器人综合管理类 + /// + public class ChatClient + { + /// + /// 消息频繁休眠时间 + /// + public static int MessFrequentSleepTime { get; set; } = 5; + + /// + /// Hook通讯秘钥 + /// + public static string SocketPassword { get; set; } = ""; + + static ChatClient() + { + try + { + QQClients = new Dictionary(); + WXClient = new Dictionary(); + //PCRobotPool = new PCRobotPool(); + //QQPool = new QQPool(); + WXSdkConfig = new WXSdkConfig(); + QQEvents = new QQEventManage(); + Events = new EventManage(); + Grant.Framework.GrantClient.Get().GrantEvent += GrantEvent; + Wechat_HeadPack = new HeadPack_Hook();//注册微信Hook 的掉线检测包 + } + catch (Exception ex) + { + } + } + + /// + /// 图片CDN缓存 + /// + public static Dictionary ImageCDNs = new Dictionary(); + + /// + /// hook(易转发) + /// + public static PCRobotPool PCRobotPool { get; private set; } = new PCRobotPool(); + //public static QQPool QQPool { get; private set; } + + /// + /// 机器人QQ基础字典 + /// + public static Dictionary QQClients { get; private set; } + + /// + /// 机器人微信基类集合,已经登录微信机器人集合 + /// + public static Dictionary WXClient { get; private set; } + /// + /// + /// + public static WXSdkConfig WXSdkConfig { get; private set; } + /// + /// 微信事件管理 + /// + public static EventManage Events { get; private set; } + /// + /// QQ事件管理 + /// + public static QQEventManage QQEvents { get; private set; } + + //public static QQCaptchaBrowser QQBrowser; + private static HeadPack_Hook Wechat_HeadPack { get; set; } + + internal static QQClient IniClient(uint qq, string pass, bool isCache = true) + { + var qClient = new QQClient(qq, pass); + if (isCache) + { + if (QQClients.ContainsKey(qq.ToString())) + { + //var qClientTmp = QQClients[qq.ToString()]; + //if (qClientTmp != null && qClientTmp.User != null && qClientTmp.User.Status != QQStatus.离线) + // qClientTmp.Logout(); + + var qBaseTmp = QQClients[qq.ToString()]; + qBaseTmp.Login(); + } + QQClients[qq.ToString()] = new QQClientImpl_QQPlus(qClient); + } + return qClient; + } + + private static void GrantEvent(customer customer, string message) + { + try + { + if (!string.IsNullOrEmpty(message)) + { + //.WriteLog("授权异常!" + (string.IsNullOrEmpty(message) ? "" : message)); + if (customer.softId == 1001) + { + var v = WXClient.Values.FirstOrDefault(f => f.Status == WxStatus.在线 && f.User.Uin.ToString() == customer.cardname); + if (v == null) return; + //【xxxxxxxxxxxxx】授权检测异常:刷新Token失败,请重新登录。 + if (message.Contains("Token")) + return; + + v.LoginOut(); + v.ChangeStatus(WxStatus.已退出); + Events.OnEvent(new WXWriteLog(v) { Message = $"【{v.WeixinHao}】授权检测异常:" + message }); + } + else if (customer.softId == 1002 && QQClients.ContainsKey(customer.cardname)) + { + var qBase = QQClients[customer.cardname]; + + if (qBase is QQClientImpl_QQPlus) + { + var tmp = (qBase as QQClientImpl_QQPlus); + var client = tmp.QQClient; + if (client != null && client.User != null && client.User.LoginStatus == LoginStatus.Login) + { + if (message.Contains("Token")) + return; + + //v.User.Status = QQStatus.离线; + client.Logout(); + QQEvents.OnEvent(new QQLogEvents(tmp) { Message = $"【{customer.cardname}】授权检测异常:" + message }); + } + } + } + } + } + catch (Exception) + { + + } + } + + private static object license_data = new object(); + + public delegate byte[] FindLicenseData(string method, string data, string api); + private static FindLicenseData FindLicense; + + public static void BindLicenseData(FindLicenseData action) + { + if (FindLicense == null) + { + FindLicense = action; + } + } + + public delegate string GetServerData(string key); + public static GetServerData GetServerDataMethod; + + /// + /// 查询数据中的用户信息 + /// + public static Func GetDBWechatFriend; + + + //internal static Dictionary GetLicenseData(string method, object data, string api = "api/member.ashx") + //{ + // lock (license_data) + // { + // var _data = Util.HexToStr(Encoding.UTF8.GetBytes(Util.ObjectToJson(data))); + // var _rest = FindLicense.Invoke(method, _data, api); + // var _json = Encoding.UTF8.GetString(_rest); + // if (!_json.StartsWith("{")) throw new Exception(_json); + // var _dic = Util.ConvertJsonToDic(_json); + // if (_dic == null) throw new Exception(_json); + // return _dic; + // } + //} + + /// + /// hook协议退出微信 + /// + /// 要退出的微信号 + public static void LoginOutWeixin(string wei_xin_hao) + { + var wx = WXClient.FirstOrDefault(f => f.Key == wei_xin_hao).Value; + if (wx != null) + { + WXClient.Remove(wei_xin_hao); + wx.LoginOut(); + wx.Dispose(); + wx = null; + } + var pcRobot = PCRobotPool.GetSession(wei_xin_hao); + if (pcRobot != null) + PCRobotPool.Remove(pcRobot); + } + + /// + /// hook协议退出调用此方法,附带提示语信息 + /// + /// 要退出的微信号 + /// 附带退出原因(弹窗) + public static void LoginOutWeixin(string wei_xin_hao, string message) + { + var wx = WXClient.FirstOrDefault(f => f.Key == wei_xin_hao).Value; + if (wx != null) + { + WXClient.Remove(wei_xin_hao); + wx.LoginOut(message); + wx.Dispose(); + wx = null; + } + var pcRobot = PCRobotPool.GetSession(wei_xin_hao); + if (pcRobot != null) + PCRobotPool.Remove(pcRobot); + } + + /// + /// 协议微信登录 + /// + /// + /// + /// + /// + /// + public static string LoginWeixin(string weixinhao, string username, string userpass, string data62) + { + var v = WXClient.FirstOrDefault(f => f.Key == weixinhao).Value as WXClientImpl_IPAD; + if (v == null) + { + v = new WXClientImpl_IPAD(weixinhao); + } + if (v.Status == WxStatus.在线) return string.Empty; + if (v.Login(username, userpass, data62)) + { + return string.Empty; + } + else return v.LoginErrorMessage; + } + + /// + /// 协议微信登录 + /// + /// + /// + /// + public static bool LoginWeixin(string wei_xin_hao = "", string data = "") + { + string deviceid = string.Empty; + if (string.IsNullOrEmpty(wei_xin_hao)) + { + // if (MessageBox.Show(@"对不起,由于近期个别微信有出现封号! + //为了您的账号安全,暂时不提供协议登陆! + //请下载【易转发-微信官方客户端】登陆,保障您的账号安全! + //------------- + //下载地址已复制到剪切板,请粘贴到浏览器下载 + //------------- + //注意:如果您执意要通过协议登陆,请点击确定!!!", "温馨提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Cancel) + if (BaseForm.ShowSuccessAutoClose(@"对不起,由于近期个别微信有出现封号! +为了您的账号安全,暂时不提供协议登陆! +请下载【易转发-微信官方客户端】登陆,保障您的账号安全! +------------- +下载地址已复制到剪切板,请粘贴到浏览器下载 +------------- +注意:如果您执意要通过协议登陆,请点击确定!!!", new DialogResult[] { DialogResult.OK, DialogResult.Cancel }) == DialogResult.Cancel) + { + try + { + Clipboard.SetDataObject(Resources.易转发下载地址 + "?=" + new Random().Next(100, 2000)); + } + catch (Exception ex) + { } + return false; + } + else + { + var WeixinHao = new WXSdk.UIForm.SetwxhForm(); + WeixinHao.ShowDialog(); + if (string.IsNullOrEmpty(WeixinHao.wxh)) + { + return false; + } + else + { + wei_xin_hao = WeixinHao.wxh; + deviceid = WeixinHao.deviceid; + } + } + } + + var v = WXClient.FirstOrDefault(f => f.Key == wei_xin_hao).Value; + if (v != null) + { + var vx = new WXClientImpl_IPAD(wei_xin_hao); + if (!string.IsNullOrEmpty(deviceid)) vx.DeviceId = deviceid; + v = vx; + v.ShowLogin(); + } + else if (data == "input_password") + { + var vx = new WXClientImpl_IPAD(wei_xin_hao); + v = vx; + vx.ShowPasswordForm(); + } + else if (string.IsNullOrEmpty(data)) + { + var vx = new WXClientImpl_IPAD(wei_xin_hao); + if (!string.IsNullOrEmpty(deviceid)) vx.DeviceId = deviceid; + v = vx; + v.ShowLogin(); + } + else + { + v = new WXClientImpl_IPAD(wei_xin_hao, data); + v.ResetConnection(); + } + return v.Status == WxStatus.在线 ? true : false; + } + + /// + /// PC微信设置登录 + /// + /// 之前登陆的设备信息 + /// 之前登陆的微信账号 + /// + public static bool LoginPcWeixin(string device, string robotname, RobotType rType) + { + try + { + var appSs = PCRobotPool.ClientSessions.Values.Where(f => f.device == device).ToList(); + if (appSs == null || appSs.Count == 0) + BaseForm.ShowSuccessAutoClose(@"未找到该设备信息 +可能原因如下: +1、易转发软件非最新版(升级试试) +2、请检查易转发是否已和软件连接成功 +3、易转发端软件目录变更(需要易转发端登录)"); + else + { + var appS = appSs[0]; + //foreach (var appS in appSs) + { + try + { + var msgid = SendServer(appS.appSession, robotname, rType); + if (!string.IsNullOrEmpty(msgid)) + { + var rst = PCRobotPool.PackHist.GetResult(msgid).Result; + if (rst != null) + { + try + { + var commonResult = rst as CommonResult; + if (commonResult != null) + { + if (string.IsNullOrWhiteSpace(commonResult.Data)) + throw new Exception("获取二维码异常"); + var rlc = JsonConvert.DeserializeObject(commonResult.Data); + if (rlc != null) + { + if (rlc.pid == -1) + throw new Exception(rlc.b64Md5); + var codeImg = Utils.Common.ConvertBase64ToImage(rlc.cImgB64); + var form = new PCLoginForm(codeImg, rlc, robotname, appS.appSession); + form.ShowDialog(); + } + } + } + catch (Exception ex) + { + BaseForm.ShowSuccessAutoClose("请求易转发:" + ex.Message); + } + } + } + } + catch (Exception ex) + { } + } + } + } + catch (Exception ex) + { + BaseForm.ShowSuccessAutoClose("PC登录异常:" + ex.Message); + } + return false; + } + + internal static string SendServer(AppSession app, string robotname, RobotType rType, string pid = "-1") + { + try + { + var cmd = PCRobotCMD.getlogincode; + var msg = new LoginCodeMsg() + { + Cmd = cmd, + RobotType = rType, + RobotUsername = robotname, + RobotUsernick = string.Empty, + Data = pid, + Key = SocketPassword + }; + var json = HttpHelper.ObjectToJson(msg); + var text = PackTool.CompressString(json); + //var t = PackTool.DecompressString(text); + + var need_send = $"{cmd} {text}\r\n"; + app.TrySend(need_send); + return msg.MsgId; + } + catch (Exception ex) + { } + return string.Empty; + } + + + internal static void UpdateWXClient(WeixinBase Client) + { + if (!WXClient.ContainsKey(Client.WeixinHao)) + { + WXClient.Add(Client.WeixinHao, Client); + } + else + { + var tempClient = WXClient[Client.WeixinHao]; + if (tempClient != Client) + { + tempClient.LoginOut(); + } + WXClient[Client.WeixinHao] = Client; + } + Console.Write(Client.ToString()); + Events.OnEvent(new WXSdk.Events.WXRefreshUser(Client)); + } + + #region QQ + /// + /// QQ登录 + /// + /// QQ账号 + /// QQ密码 + /// 是否企业QQ + /// + public static bool LoginQQ(string qqStr = "", string pass = "", bool isEQQ = false) + { + var flag = false; + QQClient qClient = null; + if (!string.IsNullOrWhiteSpace(qqStr) && !string.IsNullOrWhiteSpace(pass)) + { + uint qq; + if (uint.TryParse(qqStr, out qq)) + { + var q = QQClients.FirstOrDefault(f => f.Key == qqStr).Value; + if (q == null) + { + qClient = new QQClient(); + new QQClientImpl_QQPlus(qClient); + //qClient.LoginStatusChanged += QClient_LoginStatusChanged; + qClient.QQProtocol = isEQQ ? "企业QQ" : "PCQQ"; + qClient.User = new QQUser(qq, pass); + qClient.Login(); + flag = true; + } + } + } + if (!flag) + { + var form = new QQLoginForm(qqStr); + if (form.ShowDialog() != DialogResult.OK) + return false; + qClient = form.qPlusClient.QQClient; + } + + return qClient.User.LoginStatus == LoginStatus.Login; + } + + //private static void QClient_LoginStatusChanged(object sender, Robot.Framework.SDK.LoginStatusChangedQQEventArgs e) + //{ + // if (sender is QQClient) + // { + // var q = sender as QQClient; + // QQEvents.OnEvent(new QQLogEvents(null) { Message = $"QQ({q.User.NickName}【{q.User.QQ}】) {LoginStatus.Failed} {e.Other}" }); + // if (e.LoginStatus == LoginStatus.Login) + // { + // UpdateQQClient(new QQClientImpl_QQPlus(sender as QQClient)); + // q.LoginStatusChanged -= QClient_LoginStatusChanged; + // } + // else if(e.LoginStatus == LoginStatus.Failed || e.LoginStatus == LoginStatus.WrongPassword || e.LoginStatus == LoginStatus.JiHuo) + // { + // q.LoginStatusChanged -= QClient_LoginStatusChanged; + // } + // } + //} + + /// + /// 退出QQ + /// + /// QQ + public static void LoginOutQQ(string qq) + { + if (QQClients.ContainsKey(qq)) + { + var qClient = QQClients[qq]; + QQClients.Remove(qq); + qClient.Logout(); + qClient = null; + } + } + + /// + /// 更新QQ信息 + /// + /// + internal static void UpdateQQClient(QQBase Client) + { + if (!QQClients.ContainsKey(Client.QQ.ToString())) + { + QQClients.Add(Client.QQ.ToString(), Client); + } + else + { + var qBase = QQClients[Client.QQ.ToString()]; + //if (tempClient != Client) + //{ + // tempClient.Logout(); + //} + //QQClients[Client.User.QQ.ToString()] = Client; + if (qBase != Client) + { + qBase.Logout(); + } + QQClients[Client.QQ.ToString()] = Client; + } + //Console.Write(Client.ToString()); + QQEvents.OnEvent(new QQSdk.Events.QQRefreshUser(Client)); + } + #endregion + + + public static void SetWeixinCore(string[] grpc, string[] auth) + { + // WXClientTool.grpc_info = grpc; + WXClientTool.auth_info = auth; + } + + //public static Client LoginQQ(uint QQ, string pass, bool isEQQ = false) + //{ + // var User = new QQUser(QQ, pass); + // User.LoginMode = QQLite.Framework.QQEnum.QQStatus.const_3;//QQ登录状态(在线|Q我吧|离开...) + // var client = new Client(User); + // //client.SetTXProtocol(isEQQ ? QQLite.Framework.QQEnum.TXProtocolType.QQEIM_1_9 : QQLite.Framework.QQEnum.TXProtocolType.QQ_6_8, true); + // client.SetTXProtocol(isEQQ ? QQLite.Framework.QQEnum.TXProtocolType.QQEIM_1_9 : QQLite.Framework.QQEnum.TXProtocolType.QQ_8_9, true); + // return client; + //} + + } +} diff --git a/类库/Chat.Framework/Config/log4net.config b/类库/Chat.Framework/Config/log4net.config new file mode 100644 index 0000000..c1ebe95 --- /dev/null +++ b/类库/Chat.Framework/Config/log4net.config @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/Chat.Framework/Config/log4net.unix.config b/类库/Chat.Framework/Config/log4net.unix.config new file mode 100644 index 0000000..3b07772 --- /dev/null +++ b/类库/Chat.Framework/Config/log4net.unix.config @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/Chat.Framework/LogHelper.cs b/类库/Chat.Framework/LogHelper.cs new file mode 100644 index 0000000..844b6f0 --- /dev/null +++ b/类库/Chat.Framework/LogHelper.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework +{ + /// + /// 日志类 + /// + internal sealed class LogParameter + { +        /// +        /// 日志等级 +        /// +        public int LogGrade { get; set; } + + /// +         /// 日志类型 +         /// + public string LogType { get; set; } + + /// +         /// 日志记录类名和方法名(className/methodName) +         /// + public string LogName { get; set; } + + /// +         /// 日志记录文本内容 +         /// + public string LogContent { get; set; } + } + + /// + /// 自定义之日助手 + /// + internal sealed class LogHelper + { + #region 单利模式 + //创建私有静态字段,接收类的实例化对象 + private static readonly LogHelper _LogHelper = null; + //构造函数私有化 + internal LogHelper() { } + //静态构造函数,创建单利对象资源 + static LogHelper() + { + _LogHelper = new LogHelper(); + } + + //获取单利对象资源 + public static LogHelper GetSingleObj() + { + return _LogHelper; + } + #endregion + + /// + /// 日志等级 + /// + private enum LogType { ERROR = 1, INFO = 2, DEBUG = 3 }; + + /// + /// 指定日志文件夹(项目跟路劲文件夹) + /// + public string Path { get; set; } + + /// + /// 向日志文件写入调试信息 + /// + /// 类名/方法名 + /// 日志记录内容 + public void Debug(string logName, string logContent) + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.DEBUG, LogType = nameof(LogType.DEBUG), LogName = logName, LogContent = logContent }); + } + + /// + /// 向日志文件写入运行时信息 + /// + /// 类名/方法名 + /// 日志记录内容 + public void Info(string logName, string logContent) + { + WriteLog(new LogParameter() { LogGrade = (int)LogType.INFO, LogType = nameof(LogType.INFO), LogName = logName, LogContent = logContent }); + } + + /// + /// 向日志文件写入出错信息 + /// + /// 类名/方法名 + /// 日志记录内容 + public void Error(string logName, string logContent) + { + + WriteLog(new LogParameter() { LogGrade = (int)LogType.ERROR, LogType = nameof(LogType.ERROR), LogName = logName, LogContent = logContent }); + } + + /// + /// 实际的写日志操作 + /// + /// 日志参数model + private void WriteLog(LogParameter _logParameter) + { + //Console.WriteLine($"{_logParameter.LogType}->{_logParameter.LogName}:{_logParameter.LogContent}"); + LogParameter logParameter = _logParameter; + var m = new Action(delegate () + //Task.Factory.StartNew(delegate () + { + try + { + string filename = Util.MapFile($"{DateTime.Now.ToString("yyyy-MM-dd HH")}.log", "Cache\\Wechat"); + + #region 原始写法 + //创建或打开日志文件,向日志文件末尾追加记录 + //StreamWriter mySw = File.AppendText(filename); + + //向日志文件写入内容 + //string writeContent = time + "|" + typeGrade + ":" + type + "|" + className + ":" + content; + //mySw.WriteLine(writeContent); + + //关闭日志文件 + //mySw.Close(); + #endregion + + //(优化写法)创建或打开日志文件,向日志文件末尾追加记录,关闭日志文件 + using (StreamWriter mySw = File.AppendText(filename)) + { + string writeContent = $"{DateTime.Now.ToString("HH:mm:ss")}---{logParameter.LogGrade}|{logParameter.LogType}|{logParameter.LogName}---{logParameter.LogContent}"; + mySw.WriteLine(writeContent);//向日志文件写入内容 + mySw.Close(); //关闭日志文件 + } + } + catch (Exception ex) + { + } + }); + m.BeginInvoke(null, null); + } + } + +} diff --git a/类库/Chat.Framework/PCRobotSDK/ChatSupperSocket.cs b/类库/Chat.Framework/PCRobotSDK/ChatSupperSocket.cs new file mode 100644 index 0000000..96e78cb --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/ChatSupperSocket.cs @@ -0,0 +1,51 @@ +using SuperSocket.SocketBase; +using SuperSocket.SocketBase.Config; +using SuperSocket.SocketBase.Protocol; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK +{ + /// + /// + /// + public class SupperSocketSession : AppSession + { + + } + public class AppServer : AppServer + { + + // public TestServer() : base(new CommandLineReceiveFilterFactory(Encoding.UTF8, new BasicRequestInfoParser(":", ","))) + public AppServer() : base(new CommandLineReceiveFilterFactory(Encoding.UTF8, new BasicRequestInfoParser(" ", ","))) + { + + } + + protected override bool Setup(IRootConfig rootConfig, IServerConfig config) + { + return base.Setup(rootConfig, config); + } + protected override void OnNewSessionConnected(SupperSocketSession session) + { + //Console.WriteLine($"{session.SessionID} Connected"); + base.OnNewSessionConnected(session); + } + + protected override void OnSessionClosed(SupperSocketSession session, CloseReason reason) + { + + //Console.WriteLine($"{session.SessionID} Closed CloseReason {reason.ToString()}"); + base.OnSessionClosed(session, reason); + } + protected override void OnStarted() + { + Console.WriteLine($"OnStarted"); + base.OnStarted(); + + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/PCRobotPool.cs b/类库/Chat.Framework/PCRobotSDK/PCRobotPool.cs new file mode 100644 index 0000000..1f651f3 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/PCRobotPool.cs @@ -0,0 +1,316 @@ +using Chat.Framework.WXSdk.Implement; +using PCRobot.Pack; +using SuperSocket.SocketBase; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK +{ + /// + /// 获取消息之心跳类 + /// + public class PackHist : IRunable + { + public PackHist() + { + ThreadExcutor.RegisterIntervalObject(this, this, 1000 * 60, false); + } + class Pack + { + public DateTime CreateTime { get; set; } + public BaseMsg BaseMsg { get; set; } + } + //private object mPackDicObj = new object(); + private Dictionary mPackDic = new Dictionary(); + + public bool IsRunning { get; set; } + + public RegisteredWaitHandle RegisterdHandler { get; set; } + public WaitHandle WaitHandler { get; set; } + + private BaseMsg _GetResultMsg(string msgId) + { + try + { + lock (mPackDic) + { + //Thread.Sleep(10); + BaseMsg buf = null; + try + { + if (mPackDic.ContainsKey(msgId)) + { + buf = mPackDic[msgId].BaseMsg; + mPackDic.Remove(msgId); + return buf; + } + } + catch (Exception ee) + { } + return buf; + } + } + catch (Exception) + { + } + return null; + } + + public void Run(object state, bool timedOut) + { + if (IsRunning) return; + try + { + IsRunning = true; + var t = DateTime.Now.AddMinutes(-5); + var list = mPackDic.ToList().Where(f => f.Value.CreateTime < t);//5分钟前的包,直接忽略 + foreach (var item in list) if (mPackDic.ContainsKey(item.Key)) mPackDic.Remove(item.Key); + } + catch (Exception) + { } + finally + { + IsRunning = false; + } + } + + public void Dispose() + { + + } + /// + /// 设置接收数据包 + /// + /// + /// + public void SetResult(BaseMsg msg) + { + try + { + lock (mPackDic) + { + Console.WriteLine("add" + msg.MsgId); + if (mPackDic.ContainsKey(msg.MsgId)) mPackDic.Add(msg.MsgId, new Pack() { BaseMsg = msg }); + else mPackDic[msg.MsgId] = new Pack() { BaseMsg = msg }; + } + } + catch (Exception) + { } + } + + /// + /// 获取接收数据包 + /// + /// msgId + /// + public Task GetResult(string _msg_id) + { + var msg_id = _msg_id; + return Task.Factory.StartNew(delegate () + { + try + { + Console.WriteLine($"get {msg_id}"); + DateTime end_time = DateTime.Now.AddSeconds(60); + while (end_time > DateTime.Now) + { + var r = _GetResultMsg(msg_id); + + if (r != null) return r; + Thread.Sleep(20); + } + } + catch (Exception) + { + + } + return null; + }); + } + } + + /// + /// PC机器人(易转发)管理端 + /// + public class PCRobotPool + { + public class AppSessionInfo + { + public AppSession appSession { get; set; } + public string device { get; set; } + } + + #region superSocket 1.0 + /* + private object _lock = new object(); + private Dictionary AppSessions { get; set; } + + public PackHist PackHist { get; private set; } + + public PCRobotPool() + { + AppSessions = new Dictionary(); + PackHist = new PackHist(); + } + public void Update(string username, SupperSocketSession session) + { + lock (_lock) + { + AppSessions[username] = session; + } + } + public string Remove(SupperSocketSession session) + { + lock (_lock) + { + try + { + var removeName = string.Empty; + foreach (var item in AppSessions) + { + if (item.Value == session) + { + removeName = item.Key; + break; + } + else if (item.Value.RemoteEndPoint.Address == session.RemoteEndPoint.Address && item.Value.RemoteEndPoint.Port == session.RemoteEndPoint.Port) + { + removeName = item.Key; + break; + } + } + if (!string.IsNullOrEmpty(removeName)) + { + this.AppSessions.Remove(removeName); + return removeName; + } + } + catch (Exception) + { + } + } + return string.Empty; + } + public SupperSocketSession GetSession(string robotname) + { + if (AppSessions.ContainsKey(robotname)) return AppSessions[robotname]; + return null; + } + */ + #endregion + + #region superSocket 2.0 + private object _lock = new object(); + private Dictionary AppSessions { get; set; } + + /// + /// 客户端链接集合 + /// + //public Dictionary ClientSessions { get; set; } + public Dictionary ClientSessions { get; set; } + + public PackHist PackHist { get; private set; } + + public PCRobotPool() + { + AppSessions = new Dictionary(); + //ClientSessions = new Dictionary(); + ClientSessions = new Dictionary(); + PackHist = new PackHist(); + } + + /// + /// 更新连接 + /// + /// + /// + public void Update(string username, AppSession session) + { + lock (_lock) + { + AppSessions[username] = session; + } + } + + /// + /// 删除连接 + /// + /// + /// + public string Remove(AppSession session) + { + lock (_lock) + { + try + { + var removeName = string.Empty; + foreach (var item in AppSessions) + { + if (item.Value == session) + { + removeName = item.Key; + break; + } + else if (item.Value.RemoteEndPoint.Address == session.RemoteEndPoint.Address && item.Value.RemoteEndPoint.Port == session.RemoteEndPoint.Port) + { + removeName = item.Key; + break; + } + } + if (!string.IsNullOrEmpty(removeName)) + { + this.AppSessions.Remove(removeName); + return removeName; + } + } + catch (Exception) + { + } + } + return string.Empty; + } + + /// + /// 获取连接 + /// + /// + /// + public AppSession GetSession(string robotname) + { + if (AppSessions.ContainsKey(robotname)) return AppSessions[robotname]; + return null; + } + + public void SendAppUpdate() + { + try + { + if (ClientSessions.Count == 0) return; + + var apps = new List(); + var appSessionList = ClientSessions.Values.ToList(); + for (int i = 0; i < appSessionList.Count; i++) + { + if (apps.FirstOrDefault(f => f.RemoteEndPoint == appSessionList[i].appSession.RemoteEndPoint) == null) + { + apps.Add(appSessionList[i].appSession); + + var need_send = $"{PCRobotCMD.updateApp} {PackTool.CompressString("A")}\r\n"; + Thread.Sleep(70); + appSessionList[i].appSession.TrySend(need_send); + } + } + } + catch (Exception ex) + { + } + } + + #endregion + + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/RemoteLoginCode.cs b/类库/Chat.Framework/PCRobotSDK/RemoteLoginCode.cs new file mode 100644 index 0000000..2aba690 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/RemoteLoginCode.cs @@ -0,0 +1,40 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK +{ + /// + /// 远程登录微信二维码类 + /// + public class RemoteLoginCode + { + /// + /// 微信pid + /// + public int pid { get; set; } + + /// + /// 二维码图片文件md5 + /// + public string b64Md5 { get; set; } + + /// + /// 机器人类型 + /// + public RobotType rType { get; set; } + + /// + /// 二维码图片Base64 + /// + public string cImgB64 { get; set; } + + /// + /// 请求二维码时间 + /// + public long t { get; set; } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatApplyFriendEvents.cs b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatApplyFriendEvents.cs new file mode 100644 index 0000000..877e6de --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatApplyFriendEvents.cs @@ -0,0 +1,38 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WechatEvents +{ + /// + /// 申请添加我为好友,需要审核事件 + /// + public class WechatApplyFriendEvents : ChatEvent + { + //public override string ToString() + //{ + // if (string.IsNullOrEmpty(Data.OldFriendWxid)) + // { + // return $"微信【{Data.RobotUsernick}({Data.RobotUsername})】->验证好友->{Data.NewFriendNick}({Data.NewFriendWxid}),通过[{Data.OldFriendNick}({Data.OldFriendWxid})]的介绍,添加您为好友!验证:{Data.Message}"; + // } + // else + // { + // return $"微信【{Data.RobotUsernick}({Data.RobotUsername})】->验证好友->{Data.NewFriendNick}({Data.NewFriendWxid}),添加您为好友!验证:{Data.Message}"; + // } + //} + + /// + /// 申请添加我为好友,需要审核信息 + /// + public WechatApplyFriend Data { get; private set; } + + public WechatApplyFriendEvents(WechatApplyFriend data) + { + IsToString = true; + this.Data = data; + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatContactListEvents.cs b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatContactListEvents.cs new file mode 100644 index 0000000..1a5bf86 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatContactListEvents.cs @@ -0,0 +1,26 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WechatEvents +{ + /// + /// 获取到通讯录列表事件 + /// + public class WechatContactListEvents : ChatEvent + { + /// + /// 获取到通讯录信息 + /// + public WechatContact Data { get; private set; } + + public WechatContactListEvents(WechatContact data) + { + this.Data = data; + } + } +} + diff --git a/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatGroupMemberEvents.cs b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatGroupMemberEvents.cs new file mode 100644 index 0000000..42b550e --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatGroupMemberEvents.cs @@ -0,0 +1,26 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WechatEvents +{ + /// + /// 微信获取到群成员信息事件 + /// + public class WechatGroupMemberEvents : ChatEvent + { + /// + /// 微信获取到群成员信息 + /// + public WechatGroupMember Data { get; private set; } + + public WechatGroupMemberEvents(WechatGroupMember data) + { + this.Data = data; + } + } +} + diff --git a/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatNewFriendEvents.cs b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatNewFriendEvents.cs new file mode 100644 index 0000000..26ff2bb --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatNewFriendEvents.cs @@ -0,0 +1,25 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WechatEvents +{ + /// + /// 微信新好友事件 + /// + public class WechatNewFriendEvents + { + /// + /// 微信新好友信息 + /// + public WechatNewFriend Data { get; private set; } + + public WechatNewFriendEvents(WechatNewFriend data) + { + this.Data = data; + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatNewMemerEvents.cs b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatNewMemerEvents.cs new file mode 100644 index 0000000..eff83a7 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatNewMemerEvents.cs @@ -0,0 +1,25 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WechatEvents +{ + /// + /// 新用户入群事件 + /// + public class WechatNewMemerEvents : ChatEvent + { + /// + /// 新用户入群信息 + /// + public WechatNewMemer Data { get;private set; } + + public WechatNewMemerEvents(WechatNewMemer data) + { + this.Data = data; + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatReceiveMsgEvents.cs b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatReceiveMsgEvents.cs new file mode 100644 index 0000000..78178e6 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatReceiveMsgEvents.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PCRobot.Pack; +namespace Chat.Framework.PCRobotSDK.WechatEvents +{ + /// + /// 微信收到消息事件 + /// + public class WechatReceiveMsgEvents : ChatEvent + { + + //public override string ToString() + //{ + // if (string.IsNullOrEmpty(Data.FromGroupid)) return $"微信【{Data.RobotUsernick}({Data.RobotUsername})】收到【{Data.FromUsernick}({Data.FromUsername})】消息:{Data.FromMessage}"; + // else return $"微信【{Data.RobotUsernick}({Data.RobotUsername})】收到群【{Data.FromGroupid}】-【{Data.FromUsernick}({Data.FromUsername})】消息:{Data.FromMessage}"; + //} + /// + /// 微信收到消息信息 + /// + public WechatReceiveMsg Data { get; private set; } + + public WechatReceiveMsgEvents(WechatReceiveMsg msg) + { + IsToString = true; + this.Data = msg; + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatReicevePayEvents.cs b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatReicevePayEvents.cs new file mode 100644 index 0000000..11a116a --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatReicevePayEvents.cs @@ -0,0 +1,32 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WechatEvents +{ + /// + /// 微信收到转账收款事件 + /// + public class WechatReicevePayEvents : ChatEvent + { + //public override string ToString() + //{ + // return $"微信-【{Data.RobotUsernick}({Data.RobotUsername})】->待收款->{Data.FromUsernick}({Data.FromUsername})向您转账了¥{Data.Money}元!"; + //} + + /// + /// 微信收到转账收款 + /// + public WechatReicevePay Data { get; private set; } + + public WechatReicevePayEvents(WechatReicevePay data) + { + IsToString = true; + this.Data = data; + } + + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatStatusEvents.cs b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatStatusEvents.cs new file mode 100644 index 0000000..4842d60 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WechatEvents/WechatStatusEvents.cs @@ -0,0 +1,69 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WechatEvents +{ + /// + /// 微信状态事件 + /// + public class WechatStatusEvents : ChatEvent + { + /// + /// Uin + /// + public string Uin { get; private set; } + + /// + /// 状态 + /// + public Status Status { get; private set; } + + /// + /// 消息命令 + /// + public PCRobotCMD Cmd { get; private set; } + + /// + /// 机器人账号 + /// + public string RobotUsername { get; private set; } + + /// + /// 机器人昵称 + /// + public string RobotUsernick { get; private set; } + + /// + /// 机器人类型 + /// + public RobotType RobotType { get; private set; } + + /// + /// 秘钥 + /// + public string Key { get; private set; } + + /// + /// 消息命 + /// + public string MsgId { get; private set; } + //public WechatStatus Data { get; private set; } + + public WechatStatusEvents(WechatStatus data) + { + this.Uin = data.Uin; + this.Status = data.Status; + this.RobotUsernick = data.RobotUsernick; + this.RobotUsername = data.RobotUsername; + this.RobotType = data.RobotType; + this.MsgId = data.MsgId; + this.Key = data.Key; + this.Cmd = data.Cmd; + } + + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatApplyFriendEvents.cs b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatApplyFriendEvents.cs new file mode 100644 index 0000000..61d0335 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatApplyFriendEvents.cs @@ -0,0 +1,37 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WorkWechatEvents +{ + /// + /// 企业微信-申请添加我为好友,需要审核事件 + /// + public class WorkWechatApplyFriendEvents : ChatEvent + { + //public override string ToString() + //{ + // if (string.IsNullOrEmpty(Data.OldFriendWxid)) + // { + // return $"微信【{Data.RobotUsernick}({Data.RobotUsername})】->验证好友->{Data.NewFriendNick}({Data.NewFriendWxid}),通过[{Data.OldFriendNick}({Data.OldFriendWxid})]的介绍,添加您为好友!验证:{Data.Message}"; + // } + // else + // { + // return $"微信【{Data.RobotUsernick}({Data.RobotUsername})】->验证好友->{Data.NewFriendNick}({Data.NewFriendWxid}),添加您为好友!验证:{Data.Message}"; + // } + //} + /// + /// 企业微信-申请添加我为好友,需要审核信息 + /// + public WorkWechatApplyFriend Data { get; private set; } + + public WorkWechatApplyFriendEvents(WorkWechatApplyFriend data) + { + IsToString = true; + this.Data = data; + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatContactListEvents.cs b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatContactListEvents.cs new file mode 100644 index 0000000..7a5985d --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatContactListEvents.cs @@ -0,0 +1,26 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WorkWechatEvents +{ + /// + /// 企业微信-获取到通讯录列表事件 + /// + public class WorkWechatContactListEvents : ChatEvent + { + /// + /// 企业微信-获取到通讯录类列表信息 + /// + public WorkWechatContact Data { get; private set; } + + public WorkWechatContactListEvents(WorkWechatContact data) + { + this.Data = data; + } + } +} + diff --git a/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatGroupMemberEvents.cs b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatGroupMemberEvents.cs new file mode 100644 index 0000000..3329d2d --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatGroupMemberEvents.cs @@ -0,0 +1,26 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WorkWechatEvents +{ + /// + /// 企业微信-获取到群成员信息事件 + /// + public class WorkWechatGroupMemberEvents : ChatEvent + { + /// + /// 企业微信-获取到群成员信息 + /// + public WorkWechatGroupMember Data { get; private set; } + + public WorkWechatGroupMemberEvents(WorkWechatGroupMember data) + { + this.Data = data; + } + } +} + diff --git a/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatNewFriendEvents.cs b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatNewFriendEvents.cs new file mode 100644 index 0000000..43749c0 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatNewFriendEvents.cs @@ -0,0 +1,25 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WorkWechatEvents +{ + /// + /// 企业微信-增加新好友事件 + /// + public class WorkWechatNewFriendEvents + { + /// + /// 企业微信-增加新好友信息 + /// + public WorkWechatNewFriend Data { get; private set; } + + public WorkWechatNewFriendEvents(WorkWechatNewFriend data) + { + this.Data = data; + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatNewMemerEvents.cs b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatNewMemerEvents.cs new file mode 100644 index 0000000..660a14c --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatNewMemerEvents.cs @@ -0,0 +1,25 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WorkWechatEvents +{ + /// + /// 企业微信-增加新群成员事件 + /// + public class WorkWechatNewMemerEvents : ChatEvent + { + /// + /// 企业微信-增加新群成员信息 + /// + public WorkWechatNewMemer Data { get;private set; } + + public WorkWechatNewMemerEvents(WorkWechatNewMemer data) + { + this.Data = data; + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatReceiveMsgEvents.cs b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatReceiveMsgEvents.cs new file mode 100644 index 0000000..1092678 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatReceiveMsgEvents.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using PCRobot.Pack; +namespace Chat.Framework.PCRobotSDK.WorkWechatEvents +{ + /// + /// 企业微信-收到消息事件 + /// + public class WorkWechatReceiveMsgEvents : ChatEvent + { + + //public override string ToString() + //{ + // if (string.IsNullOrEmpty(Data.FromGroupid)) return $"微信【{Data.RobotUsernick}({Data.RobotUsername})】收到【{Data.FromUsernick}({Data.FromUsername})】消息:{Data.FromMessage}"; + // else return $"微信【{Data.RobotUsernick}({Data.RobotUsername})】收到群【{Data.FromGroupid}】-【{Data.FromUsernick}({Data.FromUsername})】消息:{Data.FromMessage}"; + //} + /// + /// 企业微信-收到消息信息 + /// + public WorkWechatReceiveMsg Data { get; private set; } + + public WorkWechatReceiveMsgEvents(WorkWechatReceiveMsg msg) + { + IsToString = true; + this.Data = msg; + } + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatReicevePayEvents.cs b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatReicevePayEvents.cs new file mode 100644 index 0000000..5c346d0 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatReicevePayEvents.cs @@ -0,0 +1,31 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WorkWechatEvents +{ + /// + /// 企业微信-收到红包事件 + /// + public class WorkWechatReicevePayEvents : ChatEvent + { + //public override string ToString() + //{ + // return $"微信-【{Data.RobotUsernick}({Data.RobotUsername})】->待收款->{Data.FromUsernick}({Data.FromUsername})向您转账了¥{Data.Money}元!"; + //} + /// + /// 企业微信-收到红包信息 + /// + public WorkWechatReicevePay Data { get; private set; } + + public WorkWechatReicevePayEvents(WorkWechatReicevePay data) + { + IsToString = true; + this.Data = data; + } + + } +} diff --git a/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatStatusEvents.cs b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatStatusEvents.cs new file mode 100644 index 0000000..52ba330 --- /dev/null +++ b/类库/Chat.Framework/PCRobotSDK/WorkWechatEvents/WorkWechatStatusEvents.cs @@ -0,0 +1,64 @@ +using PCRobot.Pack; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.PCRobotSDK.WorkWechatEvents +{ + //public class WorkWechatStatusEvents : ChatEvent + //{ + // public string Uin { get; private set; } + + // /// + // /// 状态 + // /// + // public Status Status { get; private set; } + + // /// + // /// 消息命令 + // /// + // public PCRobotCMD Cmd { get; private set; } + + // /// + // /// 机器人账号 + // /// + // public string RobotUsername { get; private set; } + + // /// + // /// 机器人昵称 + // /// + // public string RobotUsernick { get; private set; } + + // /// + // /// 机器人类型 + // /// + // public RobotType RobotType { get; private set; } + + // /// + // /// 秘钥 + // /// + // public string Key { get; private set; } + + // /// + // /// 消息命 + // /// + // public string MsgId { get; private set; } + + // //public BaseMsg Data { get; private set; } + + // public WorkWechatStatusEvents(WechatStatus data) + // { + // //this.Data = data; + // this.Uin = data.Uin; + // this.Status = data.Status; + // this.RobotUsernick = data.RobotUsernick; + // this.RobotUsername = data.RobotUsername; + // this.RobotType = data.RobotType; + // this.MsgId = data.MsgId; + // this.Key = data.Key; + // this.Cmd = data.Cmd; + // } + //} +} diff --git a/类库/Chat.Framework/Properties/AssemblyInfo.cs b/类库/Chat.Framework/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..82da0a8 --- /dev/null +++ b/类库/Chat.Framework/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Chat.Framework")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Chat.Framework")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("08421940-859b-4e93-b8d5-c4bef64b0a95")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/类库/Chat.Framework/Properties/Resources.Designer.cs b/类库/Chat.Framework/Properties/Resources.Designer.cs new file mode 100644 index 0000000..194ed07 --- /dev/null +++ b/类库/Chat.Framework/Properties/Resources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Chat.Framework.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Chat.Framework.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找类似 http://qiniu.down.api.52cmg.cn/%E6%98%93%E8%BD%AC%E5%8F%91%EF%BC%88%E5%85%8D%E8%B4%B9%E5%AE%A2%E6%88%B7%E7%AB%AF%EF%BC%89.rar 的本地化字符串。 + /// + internal static string 易转发下载地址 { + get { + return ResourceManager.GetString("易转发下载地址", resourceCulture); + } + } + } +} diff --git a/类库/Chat.Framework/Properties/Resources.resx b/类库/Chat.Framework/Properties/Resources.resx new file mode 100644 index 0000000..3003b43 --- /dev/null +++ b/类库/Chat.Framework/Properties/Resources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + http://qiniu.down.api.52cmg.cn/%E6%98%93%E8%BD%AC%E5%8F%91%EF%BC%88%E5%85%8D%E8%B4%B9%E5%AE%A2%E6%88%B7%E7%AB%AF%EF%BC%89.rar + + \ No newline at end of file diff --git a/类库/Chat.Framework/Properties/licenses.licx b/类库/Chat.Framework/Properties/licenses.licx new file mode 100644 index 0000000..411a995 --- /dev/null +++ b/类库/Chat.Framework/Properties/licenses.licx @@ -0,0 +1,3 @@ +DevExpress.XtraEditors.ComboBoxEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.CheckEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/类库/Chat.Framework/QQSdk/AndroidQQ/AndroidQQClient.cs b/类库/Chat.Framework/QQSdk/AndroidQQ/AndroidQQClient.cs new file mode 100644 index 0000000..59ab421 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/AndroidQQ/AndroidQQClient.cs @@ -0,0 +1,62 @@ +using AndroidQQ_Lib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.AndroidQQ +{ + public class AndroidQQClient : QQBase, ISDKCallBack + { + + private SDKInterFace SDK; + public void Login(string Username, string Userpass) + { + if (SDK == null) SDK = SDKHelper.GetSDK(this); + SDK.Login(Username, Userpass); + } + + public void Login() + { + new LoginForm(this).ShowDialog(); + } + + public void OnCallBack(int tag, object msg) + { + Console.WriteLine(tag+","+msg); + } + + public void SendFriendImage(uint QQ, string ImageSrc) + { + throw new NotImplementedException(); + } + + public void SendFriendMessage(uint QQ, string Message) + { + throw new NotImplementedException(); + } + + public void SendGroupImage(uint GroupId, string ImageSrc) + { + throw new NotImplementedException(); + } + + public void SendGroupMessage(uint GroupId, string Message) + { + throw new NotImplementedException(); + } + + public void SendMessage(uint QQ, string message) + { + if (SDK != null) + { + SDK.SendMsg(new AndroidQQ_Lib.qq658.core.data.SendMsg_Friend_Text + { + Uin = QQ, + Msg = message + }); + } + } + } +} diff --git a/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.Designer.cs b/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.Designer.cs new file mode 100644 index 0000000..245c79f --- /dev/null +++ b/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.Designer.cs @@ -0,0 +1,59 @@ +namespace Chat.Framework.QQSdk.AndroidQQ +{ + partial class LoginForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.SuspendLayout(); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(194, 272); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(81, 23); + this.simpleButton1.TabIndex = 0; + this.simpleButton1.Text = "登陆"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // LoginForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(458, 342); + this.Controls.Add(this.simpleButton1); + this.Name = "LoginForm"; + this.Text = "LoginQQ"; + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.cs b/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.cs new file mode 100644 index 0000000..79fe5d3 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.QQSdk.AndroidQQ +{ + public partial class LoginForm : BaseForm + { + AndroidQQClient qq; + public LoginForm(AndroidQQClient qq) + { + InitializeComponent(); + this.qq = qq; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + qq.Login("123495534","qq12345554"); + } + catch (Exception) + { + } + } + } +} diff --git a/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.resx b/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/AndroidQQ/LoginForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/Events/QQAddMeNeedAuthEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQAddMeNeedAuthEvents.cs new file mode 100644 index 0000000..b8e30b3 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQAddMeNeedAuthEvents.cs @@ -0,0 +1,38 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ收到好友申请事件 + /// + public class QQAddMeNeedAuthEvents : QQEvents + { + public override string ToString() + { + return $"QQ({QQBase.Nickname}【{QQBase.QQ}】)->申请加好友->{Nickname}({QQ}) 申请内容:{Message}"; + } + + public QQAddMeNeedAuthEvents(QQBase QQBase) : base(QQBase) { } + + /// + /// 申请用户QQ + /// + public uint QQ { get; set; } + + /// + /// 申请用户昵称 + /// + public string Nickname { get; internal set; } + + /// + /// 用户的申请提示 + /// + public string Message { get; internal set; } + + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQAddToClusterNeedAuthEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQAddToClusterNeedAuthEvents.cs new file mode 100644 index 0000000..e4a5fdf --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQAddToClusterNeedAuthEvents.cs @@ -0,0 +1,57 @@ + +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ新人申请加好友事件 + /// + public class QQAddToClusterNeedAuthEvents : QQEvents + { + public override string ToString() + { + return $"QQ({QQBase.Nickname}【{QQBase.QQ}】)->申请加好友->{Nickname}({QQ})申请内容:{Message}"; + } + + public QQAddToClusterNeedAuthEvents(QQBase QQBase) : base(QQBase) { } + + /// + /// 申请用户QQ + /// + public uint QQ { get; set; } + + /// + /// 申请用户昵称 + /// + public string Nickname { get; internal set; } + + /// + /// 用户的申请提示 + /// + public string Message { get; internal set; } + + /// + /// 群账号 + /// + public uint GroupId { get; internal set; } + /// + /// 群昵称 + /// + public string GroupName { get; internal set; } + /// + /// 群创建者QQ + /// + public uint Creator { get; internal set; } + + /// + /// 群ID + /// + public uint ClusterId { get; set; } + + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQEvents.cs new file mode 100644 index 0000000..824deae --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQEvents.cs @@ -0,0 +1,21 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ事件基类 + /// + public class QQEvents: ChatEvent + { + /// + /// QQ基类 + /// + public QQBase QQBase { get; private set; } + public QQEvents(QQBase QQBase) { this.QQBase = QQBase; } + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQLogEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQLogEvents.cs new file mode 100644 index 0000000..c3b367d --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQLogEvents.cs @@ -0,0 +1,25 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ日志事件 + /// + public class QQLogEvents : QQEvents + { + /// + /// 日志内容 + /// + public string Message { get; internal set; } + + public QQLogEvents(QQBase client) : base(client) + { + + } + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQLoginChangeEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQLoginChangeEvents.cs new file mode 100644 index 0000000..46f689b --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQLoginChangeEvents.cs @@ -0,0 +1,35 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ登录状态改变事件 + /// + public class QQLoginChangeEvents : QQEvents + { + public override string ToString() + { + return $"QQ({QQBase.Nickname}【{QQBase.QQ}】)->状态修改->{(IsLogin ? "在线" : "离线")}"; + } + + /// + /// 是否已经登录 + /// + public bool IsLogin { get; internal set; } + /// + /// 登录附带信息 + /// + public string Message { get; internal set; } + public QQLoginChangeEvents(QQBase QQBase, bool IsLogin, string Message) : base(QQBase) + { + this.IsLogin = IsLogin; + this.Message = Message; + } + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQLostConnectionEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQLostConnectionEvents.cs new file mode 100644 index 0000000..e777bab --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQLostConnectionEvents.cs @@ -0,0 +1,22 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ失去连接事件 + /// + public class QQLostConnectionEvents : QQEvents + { + /// + /// 消息 + /// + public string Message { get; set; } + + public QQLostConnectionEvents(QQBase QQBase, string message) : base(QQBase) { this.Message = message; } + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQNewFriendEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQNewFriendEvents.cs new file mode 100644 index 0000000..aeff0f3 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQNewFriendEvents.cs @@ -0,0 +1,25 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ增加新好友事件 + /// + public class QQNewFriendEvents : QQEvents + { + /// + /// QQ + /// + public uint QQ { get; internal set; } + /// + /// 昵称 + /// + public string Nickname { get; internal set; } + public QQNewFriendEvents(QQBase QQBase) : base(QQBase) { } + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQNewGroupMemberEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQNewGroupMemberEvents.cs new file mode 100644 index 0000000..3fc4c0f --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQNewGroupMemberEvents.cs @@ -0,0 +1,60 @@ + +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ群新增加群成员事件 + /// + public class QQNewGroupMemberEvents : QQEvents + { + public override string ToString() + { + return $"QQ({QQBase.Nickname}【{QQBase.QQ}】)->群{GroupName}({GroupId}),新增群成员->{NewFriendNick}({NewFriendQQ})邀请人{InviteNick}({InviteQQ})"; + } + + /// + /// 群账号 + /// + public uint GroupId { get; internal set; } + /// + /// 群昵称 + /// + public string GroupName { get; internal set; } + /// + /// 群创建者QQ + /// + public uint Creator { get; internal set; } + /// + /// 新用户QQ + /// + public uint NewFriendQQ { get; internal set; } + /// + /// 新用户昵称 + /// + public string NewFriendNick { get; internal set; } + /// + /// 推荐者QQ + /// + public uint InviteQQ { get; internal set; } + /// + /// 推荐者昵称 + /// + public string InviteNick { get; internal set; } + /// + /// 操作员昵称 + /// + public string OperatorName { get; internal set; } + /// + /// 操作员 + /// + public uint Operator { get; internal set; } + + public QQNewGroupMemberEvents(QQBase QQBase) : base(QQBase) { } + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQReceiveFriendMsgEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQReceiveFriendMsgEvents.cs new file mode 100644 index 0000000..cf87c3b --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQReceiveFriendMsgEvents.cs @@ -0,0 +1,40 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ收到私人消息事件 + /// + public class QQReceiveFriendMsgEvents : QQEvents + { + public override string ToString() + { + return $"QQ({QQBase.Nickname}【{QQBase.QQ}】)->私消息->{Nickname}({QQ})说:{Message}"; + } + /// + /// 发送消息的用户QQ + /// + public uint QQ { get; internal set; } + /// + /// 发送消息的用户昵称 + /// + public string Nickname { get; internal set; } + + /// + /// 收到消息内容 + /// + public string Message { get; internal set; } + + /// + /// 是否是临时消息 + /// + public bool IsTemp { get; internal set; } = false; + + public QQReceiveFriendMsgEvents(QQBase QQBase) : base(QQBase) { } + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQReceiveGroupMsgEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQReceiveGroupMsgEvents.cs new file mode 100644 index 0000000..10824c6 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQReceiveGroupMsgEvents.cs @@ -0,0 +1,47 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ收到群消息事件 + /// + public class QQReceiveGroupMsgEvents : QQEvents + { + public override string ToString() + { + return $"QQ({QQBase.Nickname}【{QQBase.QQ}】)->群消息->{Nickname}({QQ})在[{GroupName}({GroupId})]群说:{Message}"; + } + /// + /// QQ + /// + public uint QQ { get; internal set; } + /// + /// 昵称 + /// + public string Nickname { get; internal set; } + /// + /// 消息 + /// + public string Message { get; internal set; } + /// + /// 群账号 + /// + public uint GroupId { get; internal set; } + /// + /// 群昵称 + /// + public string GroupName { get; internal set; } + + public QQReceiveGroupMsgEvents(QQBase QQBase) : base(QQBase) + { + + } + + + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQRefreshUser.cs b/类库/Chat.Framework/QQSdk/Events/QQRefreshUser.cs new file mode 100644 index 0000000..26d3d0e --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQRefreshUser.cs @@ -0,0 +1,18 @@ +using Robot.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + /// + /// QQ更新信息事件 + /// + public class QQRefreshUser : QQEvents + { + public QQRefreshUser(QQBase QQBase) : base(QQBase) + { } + } +} diff --git a/类库/Chat.Framework/QQSdk/Events/QQVerifyCodeEvents.cs b/类库/Chat.Framework/QQSdk/Events/QQVerifyCodeEvents.cs new file mode 100644 index 0000000..74d1c93 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/Events/QQVerifyCodeEvents.cs @@ -0,0 +1,22 @@ +//using Chat.Framework.QQSdk.PCQQ; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.Events +{ + //public class QQVerifyCodeEvents : QQEvents + //{ + // public string ImageFile { get; internal set; } + // public uint QQ { get; internal set; } + // public string Session { get; internal set; } + // public VerifyCodeEventType Type { get; internal set; } + + // public QQVerifyCodeEvents(QQBase client) : base(client) + // { + + // } + //} +} \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/PCQQ/Enums.cs b/类库/Chat.Framework/QQSdk/PCQQ/Enums.cs new file mode 100644 index 0000000..9c46b9e --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/Enums.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.PCQQ +{ + public enum VerifyCodeEventType + { + 登录 = 0, + 添加好友 = 1, + 申请入群 = 2 + } + +} diff --git a/类库/Chat.Framework/QQSdk/PCQQ/InputCode.Designer.cs b/类库/Chat.Framework/QQSdk/PCQQ/InputCode.Designer.cs new file mode 100644 index 0000000..9c6b6ee --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/InputCode.Designer.cs @@ -0,0 +1,91 @@ +namespace Chat.Framework.QQSdk.PCQQ +{ + partial class InputCode + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox1 + // + this.pictureBox1.Location = new System.Drawing.Point(21, 12); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(153, 94); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureBox1.TabIndex = 0; + this.pictureBox1.TabStop = false; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(21, 123); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(100, 22); + this.textBox1.TabIndex = 1; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(137, 122); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(45, 23); + this.button1.TabIndex = 2; + this.button1.Text = "确定"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // InputCode + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(194, 162); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.pictureBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InputCode"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "输入验证码"; + this.Load += new System.EventHandler(this.InputCode_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/PCQQ/InputCode.cs b/类库/Chat.Framework/QQSdk/PCQQ/InputCode.cs new file mode 100644 index 0000000..a98b109 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/InputCode.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.QQSdk.PCQQ +{ + public partial class InputCode : BaseForm + { + public string Code { get; private set; } + private uint qq; + public InputCode(uint qq) + { + InitializeComponent(); + + this.qq = qq; + } + + private void button1_Click(object sender, EventArgs e) + { + this.Code = this.textBox1.Text; + this.Close(); + } + + private void InputCode_Load(object sender, EventArgs e) + { + var file = CsharpHttpHelper.HttpExtend.MapFile(qq + ".png", "Verify"); + if (!System.IO.File.Exists(file)) + { + file = CsharpHttpHelper.HttpExtend.MapFile(qq + ".png", "Assembly\\apifile\\Verify"); + } + if (System.IO.File.Exists(file)) this.pictureBox1.ImageLocation = file; + else this.Close(); + } + } +} diff --git a/类库/Chat.Framework/QQSdk/PCQQ/InputCode.resx b/类库/Chat.Framework/QQSdk/PCQQ/InputCode.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/InputCode.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.Designer.cs b/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.Designer.cs new file mode 100644 index 0000000..6b6afe9 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.Designer.cs @@ -0,0 +1,182 @@ +namespace Chat.Framework.QQSdk.PCQQ +{ + partial class LoginForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.radioGroup2 = new DevExpress.XtraEditors.RadioGroup(); + this.label1 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup2.Properties)).BeginInit(); + this.SuspendLayout(); + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(44, 37); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(28, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "账号:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(44, 87); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(28, 14); + this.labelControl2.TabIndex = 1; + this.labelControl2.Text = "密码:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(88, 34); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(161, 22); + this.textBox1.TabIndex = 2; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(88, 83); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(161, 22); + this.textBox2.TabIndex = 3; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(79, 216); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(128, 30); + this.simpleButton1.TabIndex = 6; + this.simpleButton1.Text = "登陆"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(44, 173); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(28, 14); + this.labelControl3.TabIndex = 8; + this.labelControl3.Text = "版本:"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(44, 131); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(28, 14); + this.labelControl4.TabIndex = 9; + this.labelControl4.Text = "通讯:"; + // + // radioGroup1 + // + this.radioGroup1.EditValue = "企业"; + this.radioGroup1.Location = new System.Drawing.Point(88, 169); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem("国际", "国际QQ"), + new DevExpress.XtraEditors.Controls.RadioGroupItem("企业", "正常QQ")}); + this.radioGroup1.Size = new System.Drawing.Size(161, 24); + this.radioGroup1.TabIndex = 10; + // + // radioGroup2 + // + this.radioGroup2.EditValue = false; + this.radioGroup2.Location = new System.Drawing.Point(88, 128); + this.radioGroup2.Name = "radioGroup2"; + this.radioGroup2.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup2.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup2.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup2.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(false, "TCP"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(true, "UDP")}); + this.radioGroup2.Size = new System.Drawing.Size(161, 22); + this.radioGroup2.TabIndex = 11; + // + // label1 + // + this.label1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.label1.Location = new System.Drawing.Point(0, 260); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(293, 23); + this.label1.TabIndex = 12; + this.label1.Text = "未登录"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // LoginForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(293, 283); + this.Controls.Add(this.label1); + this.Controls.Add(this.radioGroup2); + this.Controls.Add(this.radioGroup1); + this.Controls.Add(this.labelControl4); + this.Controls.Add(this.labelControl3); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.labelControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "LoginForm"; + this.Text = "登陆QQ"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LoginForm_FormClosing); + this.Load += new System.EventHandler(this.LoginForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup2.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.TextBox textBox2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + private DevExpress.XtraEditors.RadioGroup radioGroup2; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.cs b/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.cs new file mode 100644 index 0000000..8b9f975 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.QQSdk.PCQQ +{ + public partial class LoginForm : BaseForm + { + PCQQClient client; + public LoginForm(PCQQClient client) + { + InitializeComponent(); + this.client = client; + } + + private void LoginForm_Load(object sender, EventArgs e) + { + ChatClient.QQPool.LoginChangeEvent += QQPool_LoginChangeEvent; + + } + + private void QQPool_LoginChangeEvent(object sender, Events.QQLoginChangeEvents e) + { + var qq = e.QQClient as PCQQClient; + if (qq != null && qq.QQ.ToString() == this.textBox1.Text) + { + this.Invoke(new Action(delegate + { + try + { + this.label1.Text = e.Message; + if (e.Message.Contains("需要验证码")) + { + Plugin.GetVerifyCode(); + string codePath = QQPlus.Framework.Utils.Util.MapFile($"Verify\\{qq.QQ}.png"); + var input = new InputCode(codePath); + input.TopMost = true; + input.ShowDialog(); + if (!string.IsNullOrEmpty(input.Code)) + { + qq.qqclient.SendVerifyCode(input.Code); + } + } + else if (e.IsLogin) this.Close(); + } + catch (Exception) + { + } + })); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + client.Login(this.textBox1.Text,this.textBox2.Text,(string)this.radioGroup1.EditValue , (bool)this.radioGroup2.EditValue); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void LoginForm_FormClosing(object sender, FormClosingEventArgs e) + { + ChatClient.QQPool.LoginChangeEvent -= QQPool_LoginChangeEvent; + } + } +} diff --git a/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.resx b/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/LoginForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.Designer.cs b/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.Designer.cs new file mode 100644 index 0000000..feaea09 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.Designer.cs @@ -0,0 +1,166 @@ +namespace Chat.Framework.QQSdk.PCQQ +{ + partial class LoginLiteQQ + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.radioGroup1 = new DevExpress.XtraEditors.RadioGroup(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.status = new System.Windows.Forms.ToolStripStatusLabel(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).BeginInit(); + this.statusStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(37, 43); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 14); + this.label1.TabIndex = 0; + this.label1.Text = "账号:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(98, 40); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(157, 22); + this.textBox1.TabIndex = 1; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(37, 93); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(43, 14); + this.label2.TabIndex = 2; + this.label2.Text = "密码:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(98, 88); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(157, 22); + this.textBox2.TabIndex = 3; + this.textBox2.UseSystemPasswordChar = true; + this.textBox2.Enter += new System.EventHandler(this.textBox2_Enter); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(37, 150); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(43, 14); + this.label3.TabIndex = 4; + this.label3.Text = "协议:"; + // + // radioGroup1 + // + this.radioGroup1.Location = new System.Drawing.Point(98, 139); + this.radioGroup1.Name = "radioGroup1"; + this.radioGroup1.Properties.Appearance.BackColor = System.Drawing.Color.Transparent; + this.radioGroup1.Properties.Appearance.Options.UseBackColor = true; + this.radioGroup1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.NoBorder; + this.radioGroup1.Properties.Items.AddRange(new DevExpress.XtraEditors.Controls.RadioGroupItem[] { + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "正常QQ"), + new DevExpress.XtraEditors.Controls.RadioGroupItem(null, "企业QQ")}); + this.radioGroup1.Size = new System.Drawing.Size(192, 34); + this.radioGroup1.TabIndex = 5; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(110, 193); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(91, 33); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = "登陆"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // status + // + this.status.Name = "status"; + this.status.Size = new System.Drawing.Size(0, 17); + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.status}); + this.statusStrip1.Location = new System.Drawing.Point(0, 244); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Size = new System.Drawing.Size(309, 22); + this.statusStrip1.TabIndex = 7; + this.statusStrip1.Text = "statusStrip1"; + // + // LoginLiteQQ + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(309, 266); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.radioGroup1); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "LoginLiteQQ"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "登陆QQ"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LoginLiteQQ_FormClosing); + this.Load += new System.EventHandler(this.LoginLiteQQ_Load); + ((System.ComponentModel.ISupportInitialize)(this.radioGroup1.Properties)).EndInit(); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label3; + private DevExpress.XtraEditors.RadioGroup radioGroup1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.ToolStripStatusLabel status; + private System.Windows.Forms.StatusStrip statusStrip1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.cs b/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.cs new file mode 100644 index 0000000..ccffaca --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.cs @@ -0,0 +1,215 @@ +using DevExpress.XtraEditors; +using QQLite.Framework; +using QQLite.Framework.Event; +using QQLite.Framework.SDK; +using System; +using System.Diagnostics; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.QQSdk.PCQQ +{ + + public partial class LoginLiteQQ : BaseForm + { + QQClient client; + public LoginLiteQQ(QQClient client) + { + InitializeComponent(); + this.client = client; + if (client.QQ != 0) + { + this.textBox1.Enabled = false; + this.textBox1.Text = client.QQ.ToString(); + } + ChatClient.QQPool.LoginChangeEvent += QQPool_LoginChangeEvent; + } + + + private void QQPool_LoginChangeEvent(object sender, Events.QQLoginChangeEvents e) + { + if (e.QQClient.QQ == client.QQ) + { + this.UpdateUI(() => + { + try + { + this.status.Text = e.Message; + if (e.IsLogin) this.Close(); + else + { + if (!e.IsLogin) + { + if (e.Message.Contains("需要验证码")) + { + StatusLabel("需要验证码"); + var input = new InputCode(client.QQ); + input.ShowDialog(); + if (!string.IsNullOrEmpty(input.Code)) + { + client.SendVerifyCode(input.Code); + return; + } + } + else if (e.Message.IndexOf("需要激活", StringComparison.Ordinal) != -1) + { + StatusLabel("QQ需要激活"); + if (XtraMessageBox.Show(this, "该QQ需要激活,是否打开安全中心?", "登录异常", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) + { + Process.Start("http://aq.qq.com/007"); + } + } + else if (!string.IsNullOrEmpty(e.Message) && e.Message.IndexOf("您输入的帐号不存在", StringComparison.Ordinal) != -1) + { + StatusLabel("您输入的帐号不存在"); + ShowErrorAutoClose("您输入的帐号不存在!"); + return; + } + else if (!string.IsNullOrEmpty(e.Message) && e.Message.IndexOf("您的帐号长期未登录已被冻结回收", StringComparison.Ordinal) != -1) + { + StatusLabel("该帐号长期未登录已被冻结回收"); + ShowErrorAutoClose("该帐号长期未登录已被冻结回收!"); + return; + } + else if (!string.IsNullOrEmpty(e.Message) && e.Message.IndexOf("点此恢复正常使用", StringComparison.Ordinal) != -1) + { + StatusLabel("该QQ暂时无法登录"); + if (XtraMessageBox.Show(this, @"该QQ暂时无法登录 +是否去恢复使用?", "登录异常", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) + { + Process.Start("http://aq.qq.com/007"); + } + } + } + } + } + catch (Exception ex) + { } + }); + } + } + + /// + /// 更新登录窗体左下角内容 + /// + /// + private void StatusLabel(string text) + { + try + { + this.UpdateUI(() => + { + try + { + statusStrip1.Text = text; + } + catch (Exception) + { } + }); + } + catch (Exception ex) + { } + } + + private void EndSdk_SlipVerifyCode(object sender, VerifyCodeEventArgs e) + { + try + { + Client client = sender as Client; + this.BeginInvoke(new MethodInvoker(delegate () + { + try + { + var slipCode = new SlipCode(e.ImageFile); + if (slipCode.ShowDialog() == DialogResult.OK) + { + client.SendVerifyCode(e, slipCode.VerifyCode, slipCode.Ticket); + } + slipCode.Dispose(); + slipCode = null; + } + catch (Exception ex) + { } + })); + } + catch (Exception ex) + { } + } + + private void LoginLiteQQ_FormClosing(object sender, FormClosingEventArgs e) + { + ChatClient.QQPool.LoginChangeEvent -= QQPool_LoginChangeEvent; + + } + + private void LoginLiteQQ_Load(object sender, EventArgs e) + { + textBox1.Text = client.QQ == 0 ? string.Empty : client.QQ.ToString(); + } + + private void textBox2_Enter(object sender, EventArgs e) + { + textBox2.SelectAll(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + simpleButton1.Enabled = false; + if (string.IsNullOrWhiteSpace(this.textBox1.Text)) throw new Exception("请输入QQ账号"); + if (string.IsNullOrWhiteSpace(this.textBox2.Text)) throw new Exception("请输入QQ密码!"); + var isPcQQ = radioGroup1.SelectedIndex == 0; + var QQ = uint.Parse(textBox1.Text); + var pass = textBox2.Text; + client.IsEQQ = !isPcQQ; + client.Client = ChatClient.LoginQQ(QQ, pass, client.IsEQQ); + var Plugin = QQClient.GetLitePlugin(client.Client);//装载QQ,数据库相关信息 + Plugin.EndSdk = new QQClientSDK(); + Plugin.EndSdk.SlipVerifyCode -= EndSdk_SlipVerifyCode; + Plugin.EndSdk.SlipVerifyCode += EndSdk_SlipVerifyCode; + client.Login(Plugin, client.Client, pass); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + finally + { + simpleButton1.Enabled = true; + } + } + + + /// + /// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + /// + /// + /// + private void simpleButton2_Click(object sender, EventArgs e) + { + //try + //{ + // simpleButton1.Enabled = false; + + // var isPcQQ = radioGroup1.SelectedIndex == 0; + // client.IsEQQ = !isPcQQ; + // client.Client = ChatClient.LoginQQ; + // client.Client.QrLogin(); + // var Plugin = QQClient.GetLitePlugin(client.Client);//装载QQ,数据库相关信息 + // Plugin.EndSdk = new QQClientSDK(); + // Plugin.EndSdk.SlipVerifyCode -= EndSdk_SlipVerifyCode; + // Plugin.EndSdk.SlipVerifyCode += EndSdk_SlipVerifyCode; + // //client.Login(Plugin, client.Client, pass); + //} + //catch (Exception ex) + //{ + // BaseForm.ShowError(ex); + //} + //finally + //{ + // simpleButton1.Enabled = true; + //} + } + } +} diff --git a/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.resx b/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.resx new file mode 100644 index 0000000..91ddbd4 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/LoginLiteQQ.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/PCQQ/PCQQClient.cs b/类库/Chat.Framework/QQSdk/PCQQ/PCQQClient.cs new file mode 100644 index 0000000..db60311 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/PCQQClient.cs @@ -0,0 +1,496 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Chat.Framework.QQSdk.Events; +using QQPlus.Framework; +using QQPlus.Framework.Entities; +using QQPlus.Framework.SDK; + +namespace Chat.Framework.QQSdk.PCQQ +{ + public class PCQQClient : QQBase + { + private void Close() + { + if (qqclient != null) + { + if (qqclient.User != null) qqclient.Logout(); + qqclient.LoginSuccessed -= Qqclient_LoginSuccessed; + qqclient.LoginStatusChanged -= Qqclient_LoginStatusChanged; + } + this.UnRegisterEvent(); + qqclient = null; + } + public override void AutoLogin() + { + this.Login(base.QQ.ToString(), base.Password); + } + private void Qqclient_LoginStatusChanged(object sender, LoginStatusChangedQQEventArgs e) + { + var msg = $"{e.LoginStatus}-{e.Other}"; + if (msg.Contains("0836")) + { + qqclient.Login(); + } + else + { + this.IsLogin = (e.LoginStatus == LoginStatus.Login); + if (!this.IsLogin) OnLog("状态修改为:" + e.Other); + if (IsLogin) this.Nickname = this.qqclient.User.NickName; + var x = new QQLoginChangeEvents(this, IsLogin, msg); + ChatClient.QQPool.OnEvent(x); + } + } + + private void Qqclient_LoginSuccessed(object sender, LoginSuccessedQQEventArgs e) + { + var client = sender as QQClient; + var x = new QQLoginChangeEvents(this, true, $"登陆成功!"); + ChatClient.QQPool.OnEvent(x); + OnLog($"QQ:{(client == null ? string.Empty : client.User.NickName)}({(client == null ? 0 : client.User.QQ)}) 登陆成功!"); + } + + internal QQPlus.Framework.QQClient qqclient { get; private set; } + public bool IsUDP { get; private set; } + public string Version { get; private set; } + public void Login(string Username, string Userpass, string Version, bool IsUDP) + { + this.Version = Version; + this.IsUDP = IsUDP; + this.Login(Username, Userpass); + } + + public override void Logout() + { + this.Close(); + } + + public override void Login(string Username, string Userpass) + { + uint QQ; + if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Userpass) || !uint.TryParse(Username, out QQ)) throw new Exception("您输入的QQ或密码格式不正确!"); + this.Close(); + this.QQ = QQ; + this.QQReLoginDic[QQ] = 0;//重置计时器 + this.Password = Userpass; + qqclient = new QQPlus.Framework.QQClient(QQ, Userpass); + qqclient.User.IsUdp = this.IsUDP; + qqclient.Config.QQProtocol = this.Version; + qqclient.LoginSuccessed += Qqclient_LoginSuccessed; + qqclient.LoginStatusChanged += Qqclient_LoginStatusChanged; + qqclient.Login(); + } + + + internal override void RegisterEvent() + { + if (qqclient != null && !IsRegisterEvent) + { + IsRegisterEvent = true; + qqclient.LostConnection += Qqclient_LostConnection; + qqclient.ReceiveNormalIM += Qqclient_ReceiveNormalIM; + qqclient.ReceiveClusterIM += Qqclient_ReceiveClusterIM; + qqclient.ReceiveTempIM += Qqclient_ReceiveTempIM; + qqclient.AddMeFriend += Qqclient_AddMeFriend; + qqclient.AddMeFriendNeedAuth += Qqclient_AddMeFriendNeedAuth; + qqclient.AddedToCluster += Qqclient_AddedToCluster; + //qqclient.AddToClusterNeedAuth += Qqclient_AddToClusterNeedAuth; + qqclient.AddedToClusterInvite += Qqclient_AddedToClusterInvite; + } + } + + /// + /// QQ群新人申请进群需要审核 + /// + /// + /// + private void Qqclient_AddedToClusterInvite(object sender, AddedToClusterInviteQQEventArgs e) + { + try + { + //var evt = new QQNewGroupMemberEvents(this) { GroupId = e.Cluster.ExternalId, GroupName = e.Cluster.Name, Creator = e.Cluster.Creator, NewFriendQQ = e.ClusterMember.QQ, NewFriendNick = e.ClusterMember.Nick == null ? string.Empty : e.ClusterMember.Nick, OldFriendNick = e.ClusterMemberAdmin.Nick, OldFriendQQ = e.ClusterMemberAdmin.QQ }; + //ChatClient.QQPool.OnEvent(evt); + var evt = new InviteAddClusterNeedAuthEvents(this) { GroupId = e.Cluster.ExternalId, GroupName = e.Cluster.Name, Creator = e.Cluster.Creator, NewFriendQQ = e.ClusterMember.QQ, NewFriendNick = e.ClusterMember.Nick == null ? string.Empty : e.ClusterMember.Nick, OldFriendNick = e.ClusterMemberAdmin.Nick, OldFriendQQ = e.ClusterMemberAdmin.QQ }; + ChatClient.QQPool.OnEvent(evt); + } + catch (Exception ex) + { + this.OnLog($"Qqclient_AddedToClusterInvite Error:{ex.Message}"); + } + } + + /// + /// 1视乎是通过群申请以后进这个事件 + /// + /// + /// + private void Qqclient_AddedToCluster(object sender, AddedToClusterQQEventArgs e) + { + try + { + var evt = new QQNewGroupMemberEvents(this) { GroupId = e.Cluster.ExternalId, GroupName = e.Cluster.Name, Creator = e.Cluster.Creator, NewFriendQQ = e.ClusterMember.QQ, NewFriendNick = e.ClusterMember.Nick == null ? string.Empty : e.ClusterMember.Nick, OldFriendNick = e.ClusterMemberAdmin.Nick, OldFriendQQ = e.ClusterMemberAdmin.QQ }; + ChatClient.QQPool.OnEvent(evt); + } + catch (Exception ex) + { + this.OnLog($"Qqclient_AddedToCluster Error:{ex.Message}"); + } + } + + private void Qqclient_AddMeFriend(object sender, AddMeFriendQQEventArgs e) + { + try + { + var friend = qqclient.GetFriend(e.QQ); + var evt = new QQNewFriendEvents(this) { QQ = e.QQ, Nickname = friend != null ? friend.NickName : string.Empty }; + ChatClient.QQPool.OnEvent(evt); + } + catch (Exception ex) + { + this.OnLog($"Qqclient_AddMeFriend Error:{ex.Message}"); + } + } + + ///// + ///// 添加到集群需要验证 + ///// + ///// + ///// + //private void Qqclient_AddToClusterNeedAuth(object sender, AddToClusterNeedAuthQQEventArgs e) + //{ + // try + // { + // var evt = new QQAddToClusterNeedAuthEvents(this) { QQ = e.QQ, Message = e.Message, Cluster = e.Cluster }; + // ChatClient.QQPool.OnEvent(evt); + // } + // catch (Exception ex) + // { + // this.OnLog($"Qqclient_AddToClusterNeedAuth Error:{ex.Message}"); + // } + //} + + private void Qqclient_AddMeFriendNeedAuth(object sender, AddMeFriendNeedAuthQQEventArgs e) + { + try + { + var evt = new QQAddMeNeedAuthEvents(this) { QQ = e.QQ, Nickname = e.Nick, Message = e.Message }; + ChatClient.QQPool.OnEvent(evt); + } + catch (Exception ex) + { + this.OnLog($"Qqclient_AddMeFriendNeedAuth Error:{ex.Message}"); + } + } + + private void Qqclient_ReceiveTempIM(object sender, ReceiveTempIMQQEventArgs e) + { + try + { + var friend = qqclient.GetFriend(e.QQ); + var temp = new QQReceiveFriendMsgEvents(this) { TempMsgID = e.ExternalId, QQ = e.QQ, Message = e.Message, Nickname = (friend == null ? string.Empty : friend.NickName) }; + ChatClient.QQPool.OnEvent(temp); + } + catch (Exception ex) + { + this.OnLog($"Qqclient_ReceiveTempIM Error:{ex.Message}"); + } + } + + /// + /// 记录QQ重新登录 + /// + Dictionary QQReLoginDic = new Dictionary(); + + private void Qqclient_LostConnection(object sender, LostConnectionQQEventArgs e) + { + //看看是否有已登录的,并且自己还没有被移除 + var v = ChatClient.QQPool.QQClients.Where(f => f.Value.IsLogin); + if (v != null && ChatClient.QQPool.QQClients.Values.Contains(this)) + { + ChatClient.QQPool.OnEvent(new QQLostConnectionEvents(this, e.Message)); + } + } + + + + internal override void UnRegisterEvent() + { + + if (qqclient != null && IsRegisterEvent) + { + IsRegisterEvent = false; + qqclient.ReceiveClusterIM -= Qqclient_ReceiveClusterIM; + qqclient.LostConnection -= Qqclient_LostConnection; + qqclient.ReceiveNormalIM -= Qqclient_ReceiveNormalIM; + qqclient.ReceiveTempIM -= Qqclient_ReceiveTempIM; + qqclient.AddMeFriend -= Qqclient_AddMeFriend; + qqclient.AddMeFriendNeedAuth -= Qqclient_AddMeFriendNeedAuth; + qqclient.AddedToCluster -= Qqclient_AddedToCluster; + //qqclient.AddToClusterNeedAuth -= Qqclient_AddToClusterNeedAuth; + + } + } + + + private void Qqclient_ReceiveClusterIM(object sender, ReceiveClusterIMQQEventArgs e) + { + try + { + if (e.ClusterMember.QQ == this.QQ) return; + var client = sender as QQClient; + this.OnLog($"QQ({(client == null ? 0 : client.User.QQ)})->群消息->{e.ClusterMember.Nick}({e.ClusterMember.QQ})在[{e.Cluster.Name}({e.Cluster.ExternalId})]群说:{e.Message}"); + var temp = new QQReceiveGroupMsgEvents(this) { QQ = e.ClusterMember.QQ, Message = e.Message, Nickname = e.ClusterMember.Nick, GroupName = e.Cluster.Name, GroupId = e.Cluster.ExternalId }; + ChatClient.QQPool.OnEvent(temp); + } + catch (Exception ex) + { + this.OnLog($"Qqclient_ReceiveNormalIM Error:{ex.Message}"); + } + } + + + private void Qqclient_ReceiveNormalIM(object sender, ReceiveNormalIMQQEventArgs e) + { + try + { + if (e.QQ == this.QQ) return; + var client = sender as QQClient; + this.OnLog($"QQ({(client == null ? 0 : client.User.QQ)})->私消息->{string.Empty}({e.QQ})说:{e.Message}"); + var friend = qqclient.GetFriend(e.QQ); + var temp = new QQReceiveFriendMsgEvents(this) { QQ = e.QQ, Message = e.Message, Nickname = (friend != null ? friend.NickName : string.Empty) }; + ChatClient.QQPool.OnEvent(temp); + } + catch (Exception ex) + { + this.OnLog($"Qqclient_ReceiveNormalIM Error:{ex.Message}"); + } + } + + public override void AerifyAddMe(uint QQ, bool Agree) + { + try + { + if (IsLogin) qqclient.AgreeFriendInvite(QQ, (byte)(Agree ? 4 : 5)); + } + catch (Exception ex) + { + this.OnLog($"Qqclient_ReceiveNormalIM Error:{ex.Message}"); + } + } + + class QQMessagePack + { + private string content; + List needMessage; + public QQMessagePack(string Message) + { + this.content = Message; + this.needMessage = GetNeedMessage(); + } + + + #region 返回一个随机表情 + private static string Expression = "[微笑],[憨笑],[呲牙],[爱心],[啤酒],[太阳],[礼物],[抱拳],[咖啡],[调皮],[激动],[回头],[色],[愉快],[爱情],[飞吻],[跳跳],[发抖],[转圈],[献吻],[耶],[红包],[嘿哈]"; + private static List ExpressionList = null; + private static Random random = new Random(); + public static string FindRandomExpression() + { + if (ExpressionList == null) + ExpressionList = Expression.Split(',').ToList(); + return ExpressionList[random.Next(ExpressionList.Count)]; + } + #endregion + + private List GetNeedMessage() + { + List _msgs = new List(); + + if (string.IsNullOrEmpty(content)) return _msgs; + content = content.Replace("\r\n", "\n").Trim().Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + try + { + foreach (var msg in msgs) + { + var message = msg.Trim(); + if (string.IsNullOrEmpty(message)) continue; + + message = message.Contains("[随机表情]") ? message.Replace("[随机表情]", FindRandomExpression()) : message; + + if (message.StartsWith("[延迟=")) + { + var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + //_msgs.Add(reg.Groups[1].Value); + } + } + + //发送XML消息 + if (message.StartsWith("")) + { + _msgs.Add("暂不支持微信卡片消息!"); + } + + //发送图片消息 + var matchs = Regex.Matches(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + _msgs.Add($"[image={ match.Groups[1].Value}]"); + } + message = Regex.Replace(message, @"\[图片\=([^\]]+)\]", ""); + + //发送语音消息 + matchs = Regex.Matches(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + //暂不支持语音消息 + } + message = Regex.Replace(message, @"\[语音\=([^\]]+)\]", ""); + + matchs = Regex.Matches(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + var video = Util.StrToHex(item.Groups[1].Value); + if (video != null) + { + var video_json = Encoding.UTF8.GetString(video); + var video_data = CsharpHttpHelper.HttpExtend.JsonToDictionary(video_json); + if (video_data != null) + { + //暂不支持视频消息 + } + } + } + message = Regex.Replace(message, @"\[视频\=([^\]]+)\]", ""); + + + matchs = Regex.Matches(message, @"\[卡片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + //暂不支持卡片 + //SendCard(username, item.Groups[1].Value == "自己" ? User.Username : item.Groups[1].Value); + } + message = Regex.Replace(message, @"\[卡片\=([^\]]+)\]", ""); + + if (string.IsNullOrEmpty(message)) continue; + if (message.StartsWith("\r\n")) message = message.Substring("\r\n".Length); + if (message.StartsWith("\n")) message = message.Substring("\n".Length); + _msgs.Add(message); + } + } + catch (Exception) + { + } + return _msgs; + } + private int index = 0; + public string NextMessage() + { + if (needMessage.Count == index) return string.Empty; + string msg = needMessage[index]; + var reg = Regex.Match(msg, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + } + index++; + return msg; + } + } + + public override void SendFriendImage(uint QQ, string ImageSrc) + { + try + { + if (qqclient != null) qqclient.SendMessage(QQ, $"[image={ImageSrc}]"); + } + catch (Exception) + { + } + } + + public override void SendFriendMessage(uint QQ, string Message) + { + if (IsLogin) + { + try + { + QQMessagePack pack = new QQMessagePack(Message); + do + { + var msg = pack.NextMessage(); + if (string.IsNullOrEmpty(msg)) break; + qqclient.SendMessage(QQ, msg); + } while (true); + + } + catch (Exception) + { + } + } + + } + + public override void SendGroupImage(uint GroupId, string ImageSrc) + { + try + { + if (qqclient != null) qqclient.SendClusterMessage(GroupId, $"[image={ImageSrc}]"); + } + catch (Exception) + { + } + } + + public override void SendGroupMessage(uint GroupId, string Message) + { + if (IsLogin) + { + try + { + QQMessagePack pack = new QQMessagePack(Message); + do + { + var msg = pack.NextMessage(); + if (string.IsNullOrEmpty(msg)) break; + //this.OnLog($"准备发送{GroupId}-{Message}"); + qqclient.SendClusterMessage(GroupId, msg); + } while (true); + } + catch (Exception) + { + } + } + } + + public override void SendTempMessage(uint QQ, string Message) + { + if (IsLogin) + { + try + { + QQMessagePack pack = new QQMessagePack(Message); + do + { + var msg = pack.NextMessage(); + if (string.IsNullOrEmpty(msg)) break; + var result = qqclient.SendTempMessage(QQ, msg); + Console.WriteLine("result = " + result); + } while (true); + + } + catch (Exception) + { + } + } + } + } +} diff --git a/类库/Chat.Framework/QQSdk/PCQQ/QQClient.cs b/类库/Chat.Framework/QQSdk/PCQQ/QQClient.cs new file mode 100644 index 0000000..1aa1a9d --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/QQClient.cs @@ -0,0 +1,849 @@ +using Chat.Framework.QQSdk.Events; +using Grant.Framework; +using QQLite; +using QQLite.Framework; +using QQLite.Framework.Browser; +using QQLite.Framework.Dapper; +using QQLite.Framework.Entity; +using QQLite.Framework.SDK; +using System; +using System.Collections.Generic; +using System.Data.SQLite; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Chat.Framework.QQSdk.PCQQ +{ + public class QQClient : QQBase + { + + private QQUser User; + + public QQLite.Framework.Client Client; + + private QQLitePlugin Plugin; + + /// + /// 通过窗体登陆 + /// + public void Login(uint QQ) + { + this.QQ = QQ; + new LoginLiteQQ(this).ShowDialog(); + } + + private void SDK_LoginStatusChange(object sender, QQLite.Framework.Event.LoginStatusChangeEventArgs e) + { + try + { + var x = new QQLoginChangeEvents(this, e.LoginStatus == LoginStatus.Login, e.LoginStatusMessage); + ChatClient.QQPool.OnEvent(x); + this.OnLog(e.LoginStatusMessage); + } + catch (Exception ex) + { + this.OnLog($"{ex.Message} ~ {ex.StackTrace}"); + } + } + + public void SendVerifyCode(string code) + { + this.Client.SendVerifyCode(new QQLite.Framework.Event.VerifyCodeEventArgs() { Termination = true }, code); + } + + ///// + ///// 通过账号密码登陆 + ///// + ///// 账号 + ///// 密码 + //public void Login(string username, string userpass, bool pcqq = true) + //{ + // try + // { + // if (this.User != null && this.Client != null) this.Client.Logout(); + // this.QQ = uint.Parse(username); + // this.User = new QQUser(QQ, userpass); + // base.Password = userpass; + // base.IsEQQ = !pcqq; + // this.Client = new Client(this.User); + // this.Plugin = GetLitePlugin(this.Client);//装载QQ,数据库相关信息 + // this.Plugin.SDK.LoginStatusChange += SDK_LoginStatusChange; + // this.Plugin.EndSdk = new QQClientSDK(); + // this.Plugin.EndSdk.SlipVerifyCode += EndSdk_SlipVerifyCode; + // this.User.LoginMode = QQLite.Framework.QQEnum.QQStatus.const_3;//QQ登录状态(在线|Q我吧|离开...) + // this.Client.SetTXProtocol(pcqq ? QQLite.Framework.QQEnum.TXProtocolType.QQ_9_1 : QQLite.Framework.QQEnum.TXProtocolType.QQEIM, true); + // this.Client.Login(); + // } + // catch (Exception ex) + // { + // throw ex; + // } + //} + + /// + /// 通过账号密码登陆 + /// + /// 账号 + /// 密码 + public void Login(QQLitePlugin plugin, Client client, string pass) + { + try + { + this.Client = client; + this.User = client.QQUser; + this.QQ = User.QQ; + this.Password = pass; + if (!this.IsLogin || !isRegisterLog) + { + isRegisterLog = true; + this.Plugin = GetLitePlugin(this.Client);//装载QQ,数据库相关信息 + this.Plugin.SDK.LoginStatusChange -= SDK_LoginStatusChange; + this.Plugin.SDK.LoginStatusChange += SDK_LoginStatusChange; + } + this.Client.Login(); + } + catch (Exception ex) + { } + } + + bool isRegisterLog = false; + + bool isRegisterEvent = false; + + internal override void RegisterEvent() + { + if (this.Client != null) + { + this.Nickname = this.Client.QQUser.NickName; + SendMessageQueue.InitQueueTimer(true, 1);//队列 + this.Client.CanSendTime = DateTime.Now.AddSeconds(20); + this.Client.AllowSendCluster = true; + this.Client.AllowSendTempIM = true; + this.Client.AllowSendQQ = true; + this.Client.AllowSendDiscuss = true; + this.Client.ClusterUseXml = false; + this.Client.FriendUseXml = false; + if (!isRegisterLog) + { + isRegisterLog = true; + Plugin = GetLitePlugin(this.Client); + Plugin.SDK.LoginStatusChange += SDK_LoginStatusChange; + } + IsRegisterEvent = true; + + if (!isRegisterEvent) + { + isRegisterEvent = true; + Plugin.SDK.SlipVerifyCode += SDK_SlipVerifyCode; + Plugin.SDK.ReceiveClusterIM += SDK_ReceiveClusterIM; //群消息 + Plugin.SDK.ReceiveNormalIM += SDK_ReceiveNormalIM; //私人消息 + Plugin.SDK.ReceiveTempSessionIM += SDK_ReceiveTempSessionIM; //临时会话 + Plugin.SDK.ClusterMemberJoin += SDK_ClusterMemberJoin; //新用户加入群 + Plugin.SDK.ClusterRequestJoin += SDK_ClusterRequestJoin; //用户请求加入群 + Plugin.SDK.FriendRequestAddMeAuth += SDK_FriendRequestAddMeAuth;//请求加我为好友 + Plugin.SDK.FriendAddSuccess += SDK_FriendAddSuccess; + Plugin.SDK.FriendRequestAddMe += SDK_FriendRequestAddMe; //加我好友 + } + } + } + + private void QQClient_GrantEvent(customer customer, string message) + { + if (!string.IsNullOrEmpty(message) && this.Client != null && this.Client.QQUser.QQ.ToString() == customer.cardname && "1002" == customer.softId.ToString()) + { + var x = new QQLoginChangeEvents(this, false, $"授权异常!{(string.IsNullOrEmpty(message) ? "" : message)}"); + ChatClient.QQPool.OnEvent(x); + } + } + + private void SDK_SlipVerifyCode(object sender, QQLite.Framework.Event.VerifyCodeEventArgs e) + { + + } + + //private void SDK_VerifyCode(object sender, QQLite.Framework.Event.VerifyCodeEventArgs e) + //{ + // try + // { + // this.OnLog($"验证码图片:{e.ImageFile}"); + // //this.OnLog($"QQ({(Client == null ? 0 : Client.QQUser.QQ)})->【{e.QQ}】需要验证码"); + // var evt = new QQVerifyCodeEvents(this) { ImageFile = e.ImageFile, QQ = e.QQ, Session = e.Session, Type = (VerifyCodeEventType)((int)e.Type) }; + // ChatClient.QQPool.OnEvent(evt); + // } + // catch (Exception ex) + // { + // this.OnLog($"VerifyCode Error:{ex.Message}"); + // } + //} + + internal override void UnRegisterEvent() + { + if (this.Client != null && isRegisterEvent) + { + try + { + isRegisterEvent = false; + IsRegisterEvent = false; + Plugin.SDK.SlipVerifyCode -= SDK_SlipVerifyCode; + Plugin.SDK.ReceiveClusterIM -= SDK_ReceiveClusterIM; //群消息 + Plugin.SDK.ReceiveNormalIM -= SDK_ReceiveNormalIM; //私人消息 + Plugin.SDK.ReceiveTempSessionIM -= SDK_ReceiveTempSessionIM; //临时会话 + Plugin.SDK.ClusterMemberJoin -= SDK_ClusterMemberJoin; //新用户加入群 + Plugin.SDK.ClusterRequestJoin -= SDK_ClusterRequestJoin; //用户请求加入群 + Plugin.SDK.FriendAddSuccess -= SDK_FriendAddSuccess; // + Plugin.SDK.FriendRequestAddMeAuth -= SDK_FriendRequestAddMeAuth;//请求加我为好友 + Plugin.SDK.FriendRequestAddMe -= SDK_FriendRequestAddMe; //加我好友 + Plugin.SDK.LoginStatusChange -= SDK_LoginStatusChange; + if (ChatClient.QQPool.QQClients.ContainsKey(this.QQ)) + { + QQBase b; + ChatClient.QQPool.QQClients.TryRemove(this.QQ, out b); + } + + } + catch (Exception) + { } + finally { RemovePlugin(Plugin); } + } + } + + /// + /// 用户申请添加好友 + /// + /// + /// + private void SDK_FriendRequestAddMeAuth(object sender, QQLite.Framework.Event.FriendRequestAddMeEventArgs e) + { + try + { + this.OnLog($"QQ({(this.Client == null ? 0 : this.Client.QQUser.QQ)})->用户【{e.QQ}】申请添加好友!"); + var evt = new QQAddMeNeedAuthEvents(this) { QQ = e.QQ, Message = e.Message }; + ChatClient.QQPool.OnEvent(evt); + } + catch (Exception ex) + { + this.OnLog($"FRAddMeAuth Error:{ex.Message}"); + } + } + + private void SDK_FriendRequestAddMe(object sender, QQLite.Framework.Event.FriendRequestAddMeEventArgs e) + { + try + { + } + catch (Exception ex) + { + this.OnLog($"FRAddMe Error:{ex.Message}"); + } + } + + private void SDK_FriendAddSuccess(object sender, QQLite.Framework.Event.FriendAddSuccessEventArgs e) + { + try + { + //this.OnLog($"QQ({(Client == null ? 0 : Client.QQUser.QQ)})->用户【{e.QQ}】申请添加好友!"); + } + catch (Exception ex) + { + this.OnLog($"FAddSuccess Error:{ex.Message}"); + } + } + + /// + /// 新人申请入QQ群 + /// + /// + /// + private void SDK_ClusterRequestJoin(object sender, QQLite.Framework.Event.ClusterRequestJoinEventArgs e) + { + try + { + var evt = new QQAddToClusterNeedAuthEvents(this) { ClusterId = e.ClusterInfo.ClusterId, QQ = e.MemberQQ, Nickname = e.MemberName, Message = e.Message, GroupId = e.ClusterInfo.ExternalId, GroupName = e.ClusterInfo.Name, Creator = e.ClusterInfo.Creator }; + ChatClient.QQPool.OnEvent(evt); + } + catch (Exception ex) + { + this.OnLog($"CRJoin Error:{ex.Message}"); + } + } + + /// + /// 群加入新用户 + /// + /// + /// + private void SDK_ClusterMemberJoin(object sender, QQLite.Framework.Event.ClusterMemberJoinEventArgs e) + { + try + { + var evt = new QQNewGroupMemberEvents(this) { GroupId = e.ClusterInfo.ExternalId, GroupName = e.ClusterInfo.Name, Creator = e.ClusterInfo.Creator, NewFriendQQ = e.MemberQQ, NewFriendNick = e.MemberName, InviteQQ = e.InviteQQ, Operator = e.Operator, OperatorName = e.OperatorName }; + ChatClient.QQPool.OnEvent(evt); + } + catch (Exception ex) + { + this.OnLog($"CMJoin Error:{ex.Message}"); + } + } + + /// + /// 收到临时会话 + /// + /// + /// + private void SDK_ReceiveTempSessionIM(object sender, QQLite.Framework.Event.TempSessionIMEventArgs e) + { + try + { + Client = sender as Client; + this.OnLog($"QQ({(Client == null ? 0 : Client.QQUser.QQ)})->临时消息->{e.SenderName}({e.Sender})说:{e.Message}"); + var temp = new QQReceiveFriendMsgEvents(this) { Token = e.Token, TempMsgID = e.Sender, QQ = e.Sender, Nickname = e.SenderName, Message = e.Message }; + ChatClient.QQPool.OnEvent(temp); + } + catch (Exception ex) + { + this.OnLog($"RTSIM Error:{ex.Message}"); + } + } + + /// + /// 收到私人消息 + /// + /// + /// + private void SDK_ReceiveNormalIM(object sender, QQLite.Framework.Event.NormalIMEventArgs e) + { + try + { + if (e.Sender == this.QQ) return; + Client = sender as Client; + this.OnLog($"QQ({(Client == null ? 0 : Client.QQUser.QQ)})->私消息->{e.SenderName}({e.Sender})说:{e.Message}"); + var temp = new QQReceiveFriendMsgEvents(this) { QQ = e.Sender, Message = e.Message, Nickname = e.SenderName }; + ChatClient.QQPool.OnEvent(temp); + } + catch (Exception ex) + { + this.OnLog($"RNIM Error:{ex.Message}"); + } + } + + /// + /// 收到群消息 + /// + /// + /// + private void SDK_ReceiveClusterIM(object sender, QQLite.Framework.Event.ClusterIMEventArgs e) + { + try + { + if (e.Sender == this.QQ) return;//忽略自己的消息 + this.OnLog($"QQ({(this.Client == null ? 0 : this.Client.QQUser.QQ)})->群消息->{e.SenderName}({e.Sender})在[{e.ClusterInfo.Name}({e.ClusterInfo.ExternalId})]群说:{e.Message}"); + var temp = new QQReceiveGroupMsgEvents(this) { QQ = e.Sender, Message = e.Message, Nickname = e.SenderName, GroupName = e.ClusterInfo.Name, GroupId = e.ClusterInfo.ExternalId }; + ChatClient.QQPool.OnEvent(temp); + } + catch (Exception ex) + { + this.OnLog($"RCIM Error:{ex.Message}"); + } + } + + public override void SendFriendImage(uint QQ, string ImageSrc) + { + try + { + if (this.Client != null) this.Client.SendIM(QQ, $"[image]{ImageSrc}[/image]"); + } + catch (Exception) + { } + } + + public override void SendFriendMessage(uint QQ, string Message) + { + if (IsLogin) + { + try + { + QQMessagePack pack = new QQMessagePack(Message); + do + { + var msg = pack.NextMessage(); + msg = Regex.Replace(msg, @"(\[@\d+\])", ""); + if (string.IsNullOrEmpty(msg)) break; + var result = this.Client.SendIM(QQ, msg); + } while (true); + } + catch (Exception) + { } + } + } + + public override void SendGroupImage(uint GroupId, string ImageSrc) + { + try + { + if (this.Client != null) this.Client.SendClusterIM(GroupId, $"[image]{ImageSrc}[/image]"); + } + catch (Exception) + { } + } + + //public override void SendFriendVideo(uint toUsername, string videoSrc) + //{ + // try + // { + // if (this.Client != null) this.Client.SendIM(toUsername, $"[Video]{videoSrc}[/Video]"); + // } + // catch (Exception ex) + // { } + //} + + //public override void SendGroupVideo(uint GroupId, string ImageSrc) + //{ + // try + // { + // if (this.Client != null) this.Client.SendClusterIM(GroupId, $"[Video]{ImageSrc}[/Video]"); + // } + // catch (Exception) + // { } + //} + + /// + /// 显示登录窗口 + /// + /// + public override void ShowLogin(string Username) + { + if (!string.IsNullOrEmpty(Username)) this.QQ = uint.Parse(Username); + var form = new LoginLiteQQ(this); + form.ShowDialog(); + } + + public override void SendGroupMessage(uint GroupId, string Message) + { + if (IsLogin) + { + try + { + QQMessagePack pack = new QQMessagePack(Message); + do + { + var msg = pack.NextMessage(); + if (string.IsNullOrEmpty(msg)) break; + var result = this.Client.SendClusterIM(GroupId, msg); + } while (true); + } + catch (Exception) + { } + } + } + + public override void SendTempMessage(uint QQ, string Message, byte[] Token) + { + if (IsLogin) + { + try + { + QQMessagePack pack = new QQMessagePack(Message); + do + { + var msg = pack.NextMessage(); + msg = Regex.Replace(msg, @"\[image.+image\]", "【临时消息不支持图片】"); + if (string.IsNullOrEmpty(msg)) break; + var result = this.Client.SendTempIM(QQ, msg, Token); + } while (true); + } + catch (Exception) + { } + } + } + + public override void SendTempMessage(uint QQ, string Message) + { + if (IsLogin) + { + try + { + QQMessagePack pack = new QQMessagePack(Message); + do + { + var msg = pack.NextMessage(); + msg = Regex.Replace(msg, @"\[image.+image\]", "【临时消息不支持图片】"); + if (string.IsNullOrEmpty(msg)) break; + var result = this.Client.SendTempIM(QQ, msg); + } while (true); + } + catch (Exception) + { } + } + } + + public override void AerifyAddMe(uint QQ, bool Agree) + { + try + { + if (IsLogin) this.Client.FriendApprovedAddMe(QQ); + } + catch (Exception ex) + { + this.OnLog($"AAddMe Error:{ex.Message}"); + } + } + + public override void AerifyAddGroup(uint groupId, uint QQ) + { + try + { + if (IsLogin) + { + var result = this.Client.ClusterApproveInviteJoin(groupId, QQ); + } + } + catch (Exception ex) + { + this.OnLog($"AerifyAddGroup Error:{ex.Message}"); + } + } + + public override void Logout() + { + try + { + if (this.Client != null && isRegisterEvent) + { + try + { + isRegisterEvent = false; + IsRegisterEvent = false; + Plugin.SDK.SlipVerifyCode -= SDK_SlipVerifyCode; + Plugin.SDK.ReceiveClusterIM -= SDK_ReceiveClusterIM; //群消息 + Plugin.SDK.ReceiveNormalIM -= SDK_ReceiveNormalIM; //私人消息 + Plugin.SDK.ReceiveTempSessionIM -= SDK_ReceiveTempSessionIM; //临时会话 + Plugin.SDK.ClusterMemberJoin -= SDK_ClusterMemberJoin; //新用户加入群 + Plugin.SDK.ClusterRequestJoin -= SDK_ClusterRequestJoin; //用户请求加入群 + Plugin.SDK.FriendAddSuccess -= SDK_FriendAddSuccess; // + Plugin.SDK.FriendRequestAddMeAuth -= SDK_FriendRequestAddMeAuth;//请求加我为好友 + Plugin.SDK.FriendRequestAddMe -= SDK_FriendRequestAddMe; //加我好友 + Plugin.SDK.LoginStatusChange -= SDK_LoginStatusChange; + } + catch (Exception) + { } + } + RemovePlugin(Plugin); + } + catch (Exception ex) + { + this.OnLog($"Logout Error:{ex.Message}"); + } + } + + public override void AutoLogin() + { + try + { + this.Client.Login(); + } + catch (Exception ex) + { + this.OnLog($"algn Error:{ex.Message}"); + } + + } + + #region 内部类 + class QQMessagePack + { + private string content; + List needMessage; + public QQMessagePack(string Message) + { + this.content = Message; + this.needMessage = GetNeedMessage(); + } + + + #region 返回一个随机表情 + private static string Expression = "[微笑],[憨笑],[呲牙],[爱心],[啤酒],[太阳],[礼物],[抱拳],[咖啡],[调皮],[激动],[回头],[色],[愉快],[爱情],[飞吻],[跳跳],[发抖],[转圈],[献吻],[耶],[红包],[嘿哈]"; + private static List ExpressionList = null; + private static Random random = new Random(); + public static string FindRandomExpression() + { + if (ExpressionList == null) + ExpressionList = Expression.Split(',').ToList(); + return ExpressionList[random.Next(ExpressionList.Count)]; + } + #endregion + + private List GetNeedMessage() + { + List _msgs = new List(); + + if (string.IsNullOrEmpty(content)) return _msgs; + content = content.Replace("\r\n", "\n").Trim().Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + try + { + foreach (var msg in msgs) + { + var message = msg.Trim(); + if (string.IsNullOrEmpty(message)) continue; + + message = message.Contains("[随机表情]") ? message.Replace("[随机表情]", FindRandomExpression()) : message; + + if (message.StartsWith("[延迟=")) + { + var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + //_msgs.Add(reg.Groups[1].Value); + } + } + + //发送XML消息 + if (message.StartsWith("")) + { + _msgs.Add("暂不支持QQ卡片消息!"); + } + + //发送图片消息 + var matchs = Regex.Matches(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + _msgs.Add($"[image]{ match.Groups[1].Value}[/image]"); + } + message = Regex.Replace(message, @"\[图片\=([^\]]+)\]", ""); + + //发送语音消息 + matchs = Regex.Matches(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + //暂不支持语音消息 + } + message = Regex.Replace(message, @"\[语音\=([^\]]+)\]", ""); + + matchs = Regex.Matches(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + //foreach (Match item in matchs) + //{ + // try + // { + // _msgs.Add($"[Video]{ item.Groups[1].Value}[/Video]"); + // //var video = Util.StrToHex(temp); + // //if (video != null) + // //{ + // // var video_json = Encoding.UTF8.GetString(video); + // // var video_data = CsharpHttpHelper.HttpExtend.JsonToDictionary(video_json); + // // if (video_data != null) + // // { + // // //暂不支持视频消息 + // // } + // //} + // } + // catch (Exception ex) + // { } + //} + message = Regex.Replace(message, @"\[视频\=([^\]]+)\]", ""); + + + matchs = Regex.Matches(message, @"\[卡片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + //暂不支持卡片 + //SendCard(username, item.Groups[1].Value == "自己" ? User.Username : item.Groups[1].Value); + } + message = Regex.Replace(message, @"\[卡片\=([^\]]+)\]", ""); + + if (string.IsNullOrEmpty(message)) continue; + if (message.StartsWith("\r\n")) message = message.Substring("\r\n".Length); + if (message.StartsWith("\n")) message = message.Substring("\n".Length); + _msgs.Add(message); + } + } + catch (Exception ex) + { + } + return _msgs; + } + private int index = 0; + public string NextMessage() + { + if (needMessage.Count == index) return string.Empty; + string msg = needMessage[index]; + var reg = Regex.Match(msg, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + } + index++; + return msg; + } + } + #endregion + + #region 暂时固定写死 + private static bool i5MxESGqfP(string string_0, string string_1) + { + bool result; + try + { + if (string_1[string_1.Length - 1] != Path.DirectorySeparatorChar) + { + string_1 += Path.DirectorySeparatorChar.ToString(); + } + if (!Directory.Exists(string_1)) + { + Directory.CreateDirectory(string_1); + } + string[] fileSystemEntries = Directory.GetFileSystemEntries(string_0); + foreach (string text in fileSystemEntries) + { + if (Directory.Exists(text)) + { + i5MxESGqfP(text, string_1 + Path.GetFileName(text)); + } + else + { + File.Copy(text, string_1 + Path.GetFileName(text), true); + } + } + result = true; + } + catch + { + result = false; + } + return result; + } + + /// + /// 初始化QQ + /// + /// + /// + public static QQLite.QQLitePlugin GetLitePlugin(Client Client) + { + QQLite.QQLitePlugin plugin = null; + DbBase.RobotQQ = Client.QQ; + + + string text = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "QQ\\" + Client.QQ); + if (!Directory.Exists(text)) + { + string text2 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "QQ\\0"); + if (Directory.Exists(text2)) + { + i5MxESGqfP(text2, text); + } + else + { + Directory.CreateDirectory(text); + } + } + text = Path.Combine(text, "QQLite.db"); + if (!File.Exists(text)) + { + using (DbBase dbBase = new DbBase("Data Source=" + text + ";Pooling=true;FailIfMissing=false")) + { + dbBase.BeginTransation(); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine("DROP TABLE IF EXISTS `QQLite_Config`;"); + stringBuilder.AppendLine("CREATE TABLE IF NOT EXISTS `QQLite_Config` ("); + stringBuilder.AppendLine("`ConfigId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"); + stringBuilder.AppendLine("`PluginId` TEXT(255) NOT NULL DEFAULT ('qqrobot'),"); + stringBuilder.AppendLine("`ConfigName` TEXT(20) NOT NULL COLLATE NOCASE ,"); + stringBuilder.AppendLine("`ConfigInfo` TEXT(100) NOT NULL COLLATE NOCASE ,"); + stringBuilder.AppendLine("`ConfigType` TEXT(10) NOT NULL COLLATE NOCASE DEFAULT ('string'),"); + stringBuilder.AppendLine("`ConfigValue` TEXT COLLATE NOCASE ,"); + stringBuilder.AppendLine("CONSTRAINT `ConfigId` UNIQUE (`ConfigId` ASC)"); + stringBuilder.AppendLine(");"); + stringBuilder.AppendLine("DROP TABLE IF EXISTS `QQLite_Plugin`;"); + stringBuilder.AppendLine("CREATE TABLE IF NOT EXISTS `QQLite_Plugin` ("); + stringBuilder.AppendLine("`Pid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"); + stringBuilder.AppendLine("`PluginId` TEXT(255) NOT NULL ,"); + stringBuilder.AppendLine("`IsInstall` INTEGER NOT NULL DEFAULT (0),"); + stringBuilder.AppendLine("`IsEnabled` INTEGER NOT NULL DEFAULT (0),"); + stringBuilder.AppendLine("`Priority` INTEGER NOT NULL DEFAULT (0),"); + stringBuilder.AppendLine("`Version` TEXT(20) NOT NULL COLLATE NOCASE ,"); + stringBuilder.AppendLine("CONSTRAINT `Pid` UNIQUE (`Pid` ASC)"); + stringBuilder.AppendLine(");"); + stringBuilder.AppendLine("DROP TABLE IF EXISTS `DBVersion`;"); + stringBuilder.AppendLine("CREATE TABLE `DBVersion`("); + stringBuilder.AppendLine("`Version` TEXT"); + stringBuilder.AppendLine(");"); + stringBuilder.AppendLine("CREATE UNIQUE INDEX IF NOT EXISTS `index_config_plugin` ON `QQLite_Config` (`PluginId` ASC, `ConfigName` ASC);"); + stringBuilder.AppendLine("CREATE UNIQUE INDEX IF NOT EXISTS `index_qqlite_plugin` ON `QQLite_Plugin` (`PluginId` ASC);"); + dbBase.Conn.Execute(stringBuilder.ToString(), null, dbBase.Tran, null, null); + dbBase.Conn.Execute("INSERT INTO `DBVersion` (Version) VALUES (@Version)", new + { + Version = "1.0.0.1" + }, dbBase.Tran, null, null); + dbBase.EndTransaction(); + ((SQLiteConnection)dbBase.Conn).ChangePassword("WomccServices.Desc"); + } + } + else + { + using (DbBase dbBase2 = new DbBase("----------")) + { + dbBase2.BeginTransation(); + //通过表名检测是否存在 + if (dbBase2.Conn.Query("SELECT COUNT(*) as CNT FROM sqlite_master where type='table' and name='DBVersion'").FirstOrDefault() == 0) + { + StringBuilder stringBuilder2 = new StringBuilder(); + stringBuilder2.AppendLine("DROP TABLE IF EXISTS `DBVersion`;"); + stringBuilder2.AppendLine("CREATE TABLE `DBVersion`("); + stringBuilder2.AppendLine("`Version` TEXT"); + stringBuilder2.AppendLine(");"); + dbBase2.Conn.Execute(stringBuilder2.ToString(), null, dbBase2.Tran, null, null); + dbBase2.Conn.Execute("INSERT INTO `DBVersion` (Version) VALUES (@Version)", new + { + Version = "1.0.0.0" + }, dbBase2.Tran, null, null); + } + string a = dbBase2.Conn.Query("SELECT Version FROM `DBVersion`").SingleOrDefault(); + if (a == "1.0.0.0") + { + dbBase2.Conn.Execute("CREATE UNIQUE INDEX IF NOT EXISTS `index_config_plugin` ON `QQLite_Config` (`PluginId` ASC, `ConfigName` ASC);", dbBase2.Tran, null, null, null); + dbBase2.Conn.Execute("ALTER TABLE `QQLite_Plugin` ADD COLUMN `IsInstall` INTEGER NOT NULL DEFAULT (0);", dbBase2.Tran, null, null, null); + dbBase2.Conn.Execute("CREATE UNIQUE INDEX IF NOT EXISTS `index_qqlite_plugin` ON `QQLite_Plugin` (`PluginId` ASC);", dbBase2.Tran, null, null, null); + dbBase2.Conn.Execute("UPDATE `DBVersion` SET Version=@Version", new + { + Version = "1.0.0.1" + }, dbBase2.Tran, null, null); + } + dbBase2.EndTransaction(); + } + } + plugin.PluginAction_StartAll(Client); + plugin = Client.GetPlugin("QQLite.QQLitePlugin") as QQLitePlugin; + plugin.SDK = new QQClientSDK(); + return plugin; + } + + + public static void RemovePlugin(QQLitePlugin plugin) + { + try + { + if (plugin != null) + { + plugin.PluginAction_StopAll(); + plugin.Stop(); + } + } + catch (Exception ex) + { } + finally + { + plugin = null; + } + } + #endregion + + } +} diff --git a/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.Designer.cs b/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.Designer.cs new file mode 100644 index 0000000..a9d3694 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.Designer.cs @@ -0,0 +1,63 @@ +namespace Chat.Framework.QQSdk.PCQQ +{ + partial class SlipCode + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.panel1 = new System.Windows.Forms.Panel(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(343, 242); + this.panel1.TabIndex = 0; + // + // SlipCode + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(343, 242); + this.Controls.Add(this.panel1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SlipCode"; + this.Text = "验证码"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SlipCode_FormClosing_1); + this.Load += new System.EventHandler(this.SlipCode_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel panel1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.cs b/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.cs new file mode 100644 index 0000000..b34643d --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.cs @@ -0,0 +1,55 @@ +using QQLite.Framework.Browser; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.QQSdk.PCQQ +{ + public partial class SlipCode : BaseForm + { + string ImageUrl = string.Empty; + public SlipCode(string url) + { + InitializeComponent(); + this.ImageUrl = url; + } + + private void SlipCode_Load(object sender, EventArgs e) + { + if (ChatClient.QQBrowser == null) + ChatClient.QQBrowser = new QQCaptchaBrowser(ImageUrl, false); + ChatClient.QQBrowser.Url = ImageUrl; + ChatClient.QQBrowser.WebView.Bind(panel1); + ChatClient.QQBrowser.QQCaptchaSucceed += QQBrowser_QQCaptchaSucceed; + ChatClient.QQBrowser.Captcha(); + } + + private void QQBrowser_QQCaptchaSucceed(object sender, EventArgs e) + { + try + { + this.VerifyCode = ChatClient.QQBrowser.VerifyCode; + this.VerifyCode = ChatClient.QQBrowser.Ticket; + base.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { } + } + + public string VerifyCode; + public string Ticket; + + private void SlipCode_FormClosing_1(object sender, FormClosingEventArgs e) + { + ChatClient.QQBrowser.QQCaptchaSucceed -= QQBrowser_QQCaptchaSucceed; + ChatClient.QQBrowser.WebView.Unbind(); ; + } + } +} diff --git a/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.resx b/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/PCQQ/SlipCode.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/QPlus/FormSlide.Designer.cs b/类库/Chat.Framework/QQSdk/QPlus/FormSlide.Designer.cs new file mode 100644 index 0000000..7ba21be --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QPlus/FormSlide.Designer.cs @@ -0,0 +1,69 @@ +namespace Chat.Framework.QQSdk.QPlus +{ + partial class FormSlide + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.webBrowser1 = new System.Windows.Forms.WebBrowser(); + this.SuspendLayout(); + // + // webBrowser1 + // + this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webBrowser1.Location = new System.Drawing.Point(0, 0); + this.webBrowser1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 17); + this.webBrowser1.Name = "webBrowser1"; + this.webBrowser1.ScriptErrorsSuppressed = true; + this.webBrowser1.ScrollBarsEnabled = false; + this.webBrowser1.Size = new System.Drawing.Size(320, 238); + this.webBrowser1.TabIndex = 1; + // + // FormSlide + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(320, 238); + this.Controls.Add(this.webBrowser1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Margin = new System.Windows.Forms.Padding(2); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "FormSlide"; + this.ShowIcon = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "滑块验证码:"; + this.Load += new System.EventHandler(this.FormSlide_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.WebBrowser webBrowser1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/QPlus/FormSlide.cs b/类库/Chat.Framework/QQSdk/QPlus/FormSlide.cs new file mode 100644 index 0000000..9ea7363 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QPlus/FormSlide.cs @@ -0,0 +1,65 @@ +using Robot.Framework.Packets; +using Robot.Framework.Utils; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.QQSdk.QPlus +{ + /// + /// QQ滑动验证码窗体 + /// + [ComVisible(true)] + public partial class FormSlide : Form + { + public FormSlide() + { + InitializeComponent(); + } + + private void FormSlide_Load(object sender, EventArgs e) + { + webBrowser1.ObjectForScripting = this; + webBrowser1.Navigate(captchaURL); + } + + public QQCaptchaResponse resp { get; set; } + public FormSlide(string captchaURL) + { + this.captchaURL = captchaURL; + InitializeComponent(); + } + string captchaURL = null; + + public bool NotifyStartEditContent(string e = "") + { + try + { + if (!string.IsNullOrWhiteSpace(e)) + { + resp = JSON.Deserialize(e); + if (resp != null) + { + this.DialogResult = DialogResult.OK; + this.Close(); + } + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("QQ验证码异常", ex.Message); + } + return true; + } + + } +} diff --git a/类库/Chat.Framework/QQSdk/QPlus/FormSlide.resx b/类库/Chat.Framework/QQSdk/QPlus/FormSlide.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QPlus/FormSlide.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/QPlus/QQClientImpl_QQPlus.cs b/类库/Chat.Framework/QQSdk/QPlus/QQClientImpl_QQPlus.cs new file mode 100644 index 0000000..3b61866 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QPlus/QQClientImpl_QQPlus.cs @@ -0,0 +1,1023 @@ +using Chat.Framework.QQSdk.Events; +using Chat.Framework.Utils; +using Robot.Framework; +using Robot.Framework.Entities; +using Robot.Framework.SDK; +using System; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk.QPlus +{ + /// + /// QQ客户端管理 + /// + public class QQClientImpl_QQPlus : QQBase, IDisposable + { + /// + /// QQ客户端 + /// + public QQClient QQClient { get; internal set; } + + /// + /// 启动时间 + /// + private DateTime StartTime = DateTime.MinValue; + + private QQClientImpl_QQPlus() { } + + int register = 1; + internal QQClientImpl_QQPlus(QQClient QQClient) + { + this.QQClient = QQClient; + this.QQ = QQClient.User.QQ; + this.Nickname = QQClient.User.NickName; + this.IsLogin = QQClient.User.LoginStatus == LoginStatus.Login; + //this.Password = Robot.Framework.Utils.Util.ToHex(QQClient.User.md5_1, "", "{0}"); + //this.Password = QQClient.ToString(); + this.IsEQQ = QQClient.QQProtocol != "PCQQ"; + if (QQClient != null) + { + LogHelper.GetSingleObj().Debug("登录日志", $"账号:{QQ},注册事件 {register}"); + register++; + StartTime = DateTime.Now; + QQClient.LoginStatusChanged += client_LoginStatusChanged; + //QQClient.LoginSuccessed += client_LoginSuccessed; + QQClient.SystemMessage += client_SystemMessage; + QQClient.ReceiveNormalIM += client_ReceiveNormalIM; + QQClient.AddedToCluster += client_AddedToCluster; + QQClient.AddedToClusterInvite += client_AddedToClusterInvite; + QQClient.AddMeFriend += client_AddMeFriend; + QQClient.AddMeFriendNeedAuth += client_AddMeFriendNeedAuth; + QQClient.AddToClusterNeedAuth += client_AddToClusterNeedAuth; + QQClient.CardChanged += client_CardChanged; + QQClient.ClusterAdminChanged += client_ClusterAdminChanged; + QQClient.KeepAlive += client_KeepAlive; + QQClient.LostConnection += client_LostConnection; + QQClient.MemberExitCluster += client_MemberExitCluster; + QQClient.QQLevel += client_QQLevel; + QQClient.ReceiveClusterIM += client_ReceiveClusterIM; + QQClient.ReceiveSubjectIM += client_ReceiveSubjectIM; + QQClient.ReceiveTempIM += client_ReceiveTempIM; + QQClient.ReceiveVibration += client_ReceiveVibration; + QQClient.RejectJoinCluster += client_RejectJoinCluster; + QQClient.SignatureChanged += client_SignatureChanged; + QQClient.StatusChanged += client_StatusChanged; + QQClient.ClusterEvent += client_ClusterEvent; + QQClient.ClusterNoticeChanged += client_ClusterNoticeChanged; + QQClient.VerifyImage += client_VerifyImage; + QQClient.AddMeSubject += client_AddMeSubject; + QQClient.QQClientStatusChanged += client_QQClientStatusChanged; + QQClient.SilencedQQEvent += client_SilencedQQEvent; + QQClient.SignQQEvent += client_SignQQEvent; + QQClient.QQPayEvent += client_QQPayEvent; + QQClient.RecallEvent += client_RecallEvent; + QQClient.RedBagEvent += Client_RedBagEvent; + } + } + + //public override void Login(string Username, string Userpass) + //{ + // QQClient.Login(); + //} + + public override void Login() + { + QQClient.Login(); + } + + public override void Logout() + { + Dispose(); + QQClient.Logout(); + } + + public override void SendTempMessage(uint QQ, string Message) + { + QQClient.SendTempMessage(QQ, Message); + } + + public override void SendTempMessage(uint QQ, string Message, byte[] Token) + { + QQClient.SendTempMessage(QQ, Message); + } + + public override void SendFriendImage(uint QQ, string ImageSrc) + { + QQClient.SendMessage(QQ, $"[图片={ImageSrc}/]"); + } + + public override void SendFriendMessage(uint QQ, string Message) + { + QQClient.SendMessage(QQ, Message); + LogHelper.GetSingleObj().Debug("发送私聊消息", $"接收:{QQ},内容:{Message}"); + } + + public override void SendGroupImage(uint GroupId, string ImageSrc) + { + count++; + StringBuilder strb = new StringBuilder(); + strb.AppendLine($"发送群图片:群:{GroupId},内容:{ImageSrc}"); + var flag = QQClient.SendClusterMessage(GroupId, ImageSrc); + strb.AppendLine($"发送状态:{flag}"); + LogHelper.GetSingleObj().Debug("发送群图片", $"{strb} -> {count}"); + } + public int count = 0; + public override void SendGroupMessage(uint GroupId, string Message) + { + count++; + StringBuilder strb = new StringBuilder(); + strb.AppendLine($"发送群消息:群:{GroupId},内容:{Message}"); + var flag = QQClient.SendClusterMessage(GroupId, Message); + strb.AppendLine($"发送状态:{flag} -> " + count); + LogHelper.GetSingleObj().Debug("发送群消息", $"{strb}"); + } + + //--------------- + + private void client_SystemMessage(object sender, SystemMessageQQEventArgs e) + { + try + { + Console.WriteLine("##########" + e.Message); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_LoginStatusChanged(object sender, LoginStatusChangedQQEventArgs e) + { + try + { + if (sender is QQClient) + { + var client = sender as QQClient; + ChatClient.QQEvents.OnEvent(new QQLogEvents(null) { Message = $"QQ({client.User.NickName}【{client.User.QQ}】) {e.LoginStatus} {e.Other}" }); + + var logstatusTmp = client.User.LoginStatus; + this.QQClient = client; + if (e.LoginStatus == LoginStatus.Login) + { + this.QQ = QQClient.User.QQ; + this.Nickname = QQClient.User.NickName; + this.IsLogin = QQClient.User.LoginStatus == LoginStatus.Login; + //this.Password = Robot.Framework.Utils.Util.ToHex(QQClient.User.md5_1, "", "{0}"); + ChatClient.UpdateQQClient(this); + + //if (client != null && logstatusTmp != e.LoginStatus) + { + QQBase qBase = null; + if (ChatClient.QQClients.ContainsKey(client.QQ.ToString())) + qBase = ChatClient.QQClients[client.QQ.ToString()]; + else + qBase = new QQClientImpl_QQPlus(client); + var x = new QQLoginChangeEvents(qBase, true, "在线"); + ChatClient.QQEvents.OnEvent(x); + } + } + else if (e.LoginStatus == LoginStatus.Logout || e.LoginStatus == LoginStatus.WrongPassword || e.LoginStatus == LoginStatus.JiHuo) + { + this.IsLogin = QQClient.User.LoginStatus == LoginStatus.Login; + ChatClient.LoginOutQQ(this.QQ.ToString()); + } + } + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 用户被邀请进群 + /// + /// + /// + private void client_AddedToCluster(object sender, AddedToClusterQQEventArgs e) + { + try + { + QQNewGroupMemberEvents evt = null; + if (e.IsInvite) + { + evt = new QQNewGroupMemberEvents(this) { GroupId = e.Cluster.ExternalId, GroupName = e.Cluster.Name, Creator = e.ClusterMemberAdmin.QQ, InviteQQ = e.ClusterMemberInviter.QQ, InviteNick = e.ClusterMemberInviter.OldCard, NewFriendNick = e.ClusterMember.Nick, NewFriendQQ = e.ClusterMember.QQ }; + } + else + { + evt = new QQNewGroupMemberEvents(this) { GroupId = e.Cluster.ExternalId, GroupName = e.Cluster.Name, Creator = e.ClusterMemberAdmin.QQ, InviteQQ = 0, NewFriendNick = e.ClusterMember.Nick, NewFriendQQ = e.ClusterMember.QQ }; + } + ChatClient.QQEvents.OnEvent(evt); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 用户进群 + /// + /// + /// + private void client_AddedToClusterInvite(object sender, AddedToClusterInviteQQEventArgs e) + { + try + { + var evt = new QQNewGroupMemberEvents(this) { GroupId = e.Cluster.ExternalId, GroupName = e.Cluster.Name, Creator = e.ClusterMemberAdmin.QQ, InviteQQ = e.ClusterMemberAdmin.QQ, InviteNick = e.ClusterMemberAdmin.CardOrName, NewFriendNick = e.ClusterMember.Nick, NewFriendQQ = e.ClusterMember.QQ }; + ChatClient.QQEvents.OnEvent(evt); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_AddMeFriend(object sender, AddMeFriendQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 添加好友需要审核 + /// + /// + /// + private void client_AddMeFriendNeedAuth(object sender, AddMeFriendNeedAuthQQEventArgs e) + { + try + { + //OnLog($"QQ({this.QQ})->用户【{e.Nick}({e.QQ})】申请添加好友!"); + var evt = new QQAddMeNeedAuthEvents(this) { QQ = e.QQ, Message = e.Message, Nickname = e.Nick }; + ChatClient.QQEvents.OnEvent(evt); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 添加群需要审核 + /// + /// + /// + private void client_AddToClusterNeedAuth(object sender, AddToClusterNeedAuthQQEventArgs e) + { + try + { + //OnLog($"QQ({this.QQ})->用户({e.QQ})申请加入群 {e.Cluster.Name}({e.Cluster.ExternalId}) 申请内容:{e.Message}"); + var evt = new QQAddToClusterNeedAuthEvents(this) { QQ = e.QQ, Message = e.Message, Nickname = string.Empty, ClusterId = e.Cluster.ExternalId, GroupId = e.Cluster.GroupId, Creator = e.Cluster.Creator, GroupName = e.Cluster.Name }; + ChatClient.QQEvents.OnEvent(evt); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + public override void AerifyAddMe(uint QQ, byte Agree = 4, string Message = "") + { + QQClient.AgreeFriendInvite(QQ, Agree, Message); + } + + public override void AerifyAddGroup(uint groupId, uint QQ, bool Agree = true, string Message = "") + { + QQClient.AgreeJoinCluster(groupId, QQ); + } + + private void client_CardChanged(object sender, CardChangedQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 群管理变更 + /// + /// + /// + private void client_ClusterAdminChanged(object sender, ClusterAdminChangedQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 心跳 + /// + /// + /// + private void client_KeepAlive(object sender, KeepAliveQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 断开连接 + /// + /// + /// + private void client_LostConnection(object sender, LostConnectionQQEventArgs e) + { + try + { + this.Login(); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 用户退出群 + /// + /// + /// + private void client_MemberExitCluster(object sender, MemberExitClusterQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_QQLevel(object sender, QQLevelQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 群消息 + /// + /// + /// + private void client_ReceiveClusterIM(object sender, ReceiveClusterIMQQEventArgs e) + { + try + { + if (StartTime.AddSeconds(20) > DateTime.Now) + return; + if (e.SendTime.AddSeconds(60) < DateTime.Now) + return; + + QQClient q = null; + if (sender is QQClient) + { + q = sender as QQClient; + if (q != null && q.QQ == e.ClusterMember.QQ) + return; + } + var nickname = string.Empty; + if (e.ClusterMember != null && !string.IsNullOrWhiteSpace(e.ClusterMember.CardOrName)) + { + nickname = e.ClusterMember.CardOrName; + } + else + { + if (q != null && q.User.Friends != null) + { + var friend = q.User.Friends.FirstOrDefault(f => f.QQ == e.ClusterMember.QQ); + if (friend != null) + nickname = friend.NickName; + } + } + var mess = QQMessReplace(e.Message); + if (string.IsNullOrWhiteSpace(mess)) return; + ChatClient.QQEvents.OnEvent(new Events.QQReceiveGroupMsgEvents(this) { QQ = e.ClusterMember.QQ, GroupId = e.Cluster.ExternalId, GroupName = e.Cluster.Name, Nickname = nickname, Message = mess }); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_ReceiveSubjectIM(object sender, ReceiveSubjectIMQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 正常私人消息 + /// + /// + /// + private void client_ReceiveNormalIM(object sender, ReceiveNormalIMQQEventArgs e) + { + try + { + if (StartTime.AddSeconds(20) > DateTime.Now) + return; + if (e.SendTime.AddSeconds(60) < DateTime.Now) + return; + + var nickname = string.Empty; + if (sender is QQClient) + { + var q = sender as QQClient; + if (q != null && q.User.Friends != null) + { + var friend = q.User.Friends.FirstOrDefault(f => f.QQ == e.QQ); + if (friend != null) + nickname = friend.NickName; + } + } + //你的QQ暂不支持查看视频短片,请期待后续版本。[视频=51A933ED15D1F8969C0D12CD423F54F5.mp4/] + var mess = QQMessReplace(e.Message); + if (string.IsNullOrWhiteSpace(mess)) return; + ChatClient.QQEvents.OnEvent(new Events.QQReceiveFriendMsgEvents(this) { QQ = e.QQ, Nickname = nickname, Message = mess }); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 过来QQ的消息 + /// + /// + /// + private string QQMessReplace(string _mess) + { + try + { + var mess = _mess; + mess = mess.Replace("你的QQ暂不支持查看视频短片,请期待后续版本。", ""); + mess = Regex.Replace(mess, @"(\[(?:声音|图片|视频)=.+?/\])", "", RegexOptions.IgnoreCase); + return mess; + } + catch (Exception ex) + { } + return _mess; + } + + private void client_ReceiveTempIM(object sender, ReceiveTempIMQQEventArgs e) + { + try + { + if (StartTime.AddSeconds(20) > DateTime.Now) + return; + if (e.SendTime.AddSeconds(60) < DateTime.Now) + return; + + var nickname = string.Empty; + if (sender is QQClient) + { + var q = sender as QQClient; + if (q != null && q.User.Friends != null) + { + var friend = q.User.Friends.FirstOrDefault(f => f.QQ == e.QQ); + if (friend != null) + nickname = friend.NickName; + } + } + var mess = QQMessReplace(e.Message); + if (string.IsNullOrWhiteSpace(mess)) return; + ChatClient.QQEvents.OnEvent(new Events.QQReceiveFriendMsgEvents(this) { QQ = e.QQ, Nickname = nickname, Message = mess, IsTemp = true }); + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 震动 + /// + /// + /// + private void client_ReceiveVibration(object sender, ReceiveVibrationQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_RejectJoinCluster(object sender, RejectJoinClusterQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_SignatureChanged(object sender, SignatureChangedQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_StatusChanged(object sender, StatusChangedQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_ClusterEvent(object sender, ClusterEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 群公告修改 + /// + /// + /// + private void client_ClusterNoticeChanged(object sender, ClusterNoticeChangedEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_VerifyImage(object sender, VerifyImageQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_AddMeSubject(object sender, AddMeSubjectQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_QQClientStatusChanged(object sender, QQClientStatusChangedQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_SilencedQQEvent(object sender, SilencedQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + private void client_SignQQEvent(object sender, SignQQEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// QQ支付 + /// + /// + /// + private void client_QQPayEvent(object sender, QQPayEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 撤回 + /// + /// + /// + private void client_RecallEvent(object sender, RecallEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 红包 + /// + /// + /// + private void Client_RedBagEvent(object sender, RedBagEventArgs e) + { + try + { + + } + catch (Exception ex) + { + OnLog(System.Reflection.MethodBase.GetCurrentMethod().Name + " : " + ex.Message + " - " + ex.StackTrace); + } + } + + public void Dispose() + { + if (QQClient != null) + { + QQClient.LoginStatusChanged -= client_LoginStatusChanged; + //QQClient.LoginSuccessed -= client_LoginSuccessed; + QQClient.SystemMessage -= client_SystemMessage; + QQClient.ReceiveNormalIM -= client_ReceiveNormalIM; + QQClient.AddedToCluster -= client_AddedToCluster; + QQClient.AddedToClusterInvite -= client_AddedToClusterInvite; + QQClient.AddMeFriend -= client_AddMeFriend; + QQClient.AddMeFriendNeedAuth -= client_AddMeFriendNeedAuth; + QQClient.AddToClusterNeedAuth -= client_AddToClusterNeedAuth; + QQClient.CardChanged -= client_CardChanged; + QQClient.ClusterAdminChanged -= client_ClusterAdminChanged; + QQClient.KeepAlive -= client_KeepAlive; + QQClient.LostConnection -= client_LostConnection; + QQClient.MemberExitCluster -= client_MemberExitCluster; + QQClient.QQLevel -= client_QQLevel; + QQClient.ReceiveClusterIM -= client_ReceiveClusterIM; + QQClient.ReceiveSubjectIM -= client_ReceiveSubjectIM; + QQClient.ReceiveTempIM -= client_ReceiveTempIM; + QQClient.ReceiveVibration -= client_ReceiveVibration; + QQClient.RejectJoinCluster -= client_RejectJoinCluster; + QQClient.SignatureChanged -= client_SignatureChanged; + QQClient.StatusChanged -= client_StatusChanged; + QQClient.ClusterEvent -= client_ClusterEvent; + QQClient.ClusterNoticeChanged -= client_ClusterNoticeChanged; + QQClient.VerifyImage -= client_VerifyImage; + QQClient.AddMeSubject -= client_AddMeSubject; + QQClient.QQClientStatusChanged -= client_QQClientStatusChanged; + QQClient.SilencedQQEvent -= client_SilencedQQEvent; + QQClient.SignQQEvent -= client_SignQQEvent; + QQClient.QQPayEvent -= client_QQPayEvent; + QQClient.RecallEvent -= client_RecallEvent; + QQClient.RedBagEvent -= Client_RedBagEvent; + } + } + + public override Task SendMessage(uint _username, string _content, bool _isGroup = false, bool _isTemp = false) + { + uint username = _username; + string content = _content; + bool isGroup = _isGroup; + bool isTemp = _isTemp; + + return Task.Run(() => + { + if (string.IsNullOrEmpty(content)) return true; + content = content.Replace("\r\n", "\n").Trim().Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + try + { + foreach (var msg in msgs) + { + var m = msg.Trim(); + if (string.IsNullOrEmpty(m)) continue; + + var message = m.RandomMess(); + + message = message.Contains("[随机表情]") ? message.Replace("[随机表情]", "") : message; + + message = DelayMess(message); + + //发送XML消息 + //if (message.StartsWith("")) + //{ + // WechatPack pack = new WechatPack(this); + // var sendJson = new + // { + // ToUserName = username, + // AppId = "", + // Type = 5, + // Content = message + // }; + // pack.SendAll(WechatCmd.发送XML消息, false, sendJson); + // return true; + //} + + ////发送公告消息 + //var matchs = Regex.Matches(message, @"\[公告\=([^\]]+)\]", RegexOptions.IgnoreCase); + //if (username.Contains("@")) + //{ + // foreach (Match match in matchs) + // { + // SetRoomNotice(match.Groups[1].Value, username); + // } + //} + //message = Regex.Replace(message, @"\[公告\=([^\]]+)\]", ""); + //message = DelayMess(message); + + //发送图片消息 + var matchs = Regex.Matches(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + if (isGroup) + SendGroupMessage(username, $"[图片={match.Groups[1].Value}/]"); + else + { + if (isTemp) + SendTempMessage(username, $"[图片={match.Groups[1].Value}/]"); + else + SendFriendMessage(username, $"[图片={match.Groups[1].Value}/]"); + } + } + message = Regex.Replace(message, @"\[图片\=([^\]]+)\]", ""); + message = DelayMess(message); + + //发送语音消息 + matchs = Regex.Matches(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + if (isGroup) + { + var g = QQClient.GetCluster(username); + QQClient.SendClusterAudio(g, $"{item.Groups[1].Value}"); + } + else + { + if (isTemp) + { + //SendTempMessage(username, $"[语音={item.Groups[1].Value}/]"); + } + else + QQClient.SendAudio(username, $"{item.Groups[1].Value}"); + } + } + message = Regex.Replace(message, @"\[语音\=([^\]]+)\]", ""); + message = DelayMess(message); + matchs = Regex.Matches(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + //foreach (Match item in matchs) + //{ + // var temp = item.Groups[1].Value; + // if (!File.Exists(temp)) continue; + // if (isGroup) + // SendGroupMessage(username, $"[视频={item.Groups[1].Value}/]"); + // else + // { + // if (isTemp) + // SendTempMessage(username, $"[视频={item.Groups[1].Value}/]"); + // else + // SendFriendMessage(username, $"[视频={item.Groups[1].Value}]"); + // } + //} + message = Regex.Replace(message, @"\[视频\=([^\]]+)\]", ""); + message = DelayMess(message); + + matchs = Regex.Matches(message, @"\[卡片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + //SendCard(username, item.Groups[1].Value == "自己" ? User.Username : item.Groups[1].Value); + } + message = Regex.Replace(message, @"\[卡片\=([^\]]+)\]", ""); + message = DelayMess(message); + if (string.IsNullOrWhiteSpace(message)) continue; + if (message.StartsWith("\r\n")) message = message.Substring("\r\n".Length); + if (message.StartsWith("\n")) message = message.Substring("\n".Length); + + //QQchatPack send = new QQchatPack(this); + + #region 提取艾特用户id + + //List atWxidList = new List(); + //var regTmp = Regex.Matches(message, @"(?<全部>\[@(?<账号>[A-Za-z0-9_]+)\])"); + //foreach (Match item in regTmp) + //{ + // if (item.Success) + // { + // var name = item.Groups["账号"].Value; + // atWxidList.Add(name); + // var friend = GetContact(name); + // if (friend != null) + // message = message.Replace(item.Groups["全部"].Value, $"@{friend.NickName} "); + // } + //} + + //if (atWxidList.Count != 0) + //{ + // atUsername = string.Join(",", atWxidList); + //} + #endregion + + //var sendData = new { ToUserName = username, Content = message.Trim(), Type = 0, MsgSource = atUsername }; + //send.SetNextData(new WechatPack.PackMsg() { cmd = WechatCmd.发送文本消息, data = sendData }); + //RunSendMessageQueue(send); + + if (isGroup) + SendGroupMessage(username, message.Trim()); + else + { + if (isTemp) + SendTempMessage(username, message.Trim()); + else + SendFriendMessage(username, message.Trim()); + } + } + return true; + } + catch (Exception ex) + { + this.OnLog("QQSendMessage ERROR:" + ex.Message + "," + ex.StackTrace); + return false; + } + }); + } + + /// + /// 消息延迟 + /// + /// + public string DelayMess(string message) + { + try + { + message = message.Trim(); + if (message.StartsWith("[延迟=")) + { + var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + } + } + } + catch (Exception ex) + { } + return message; + } + + /// + /// 需要发送的消息队列 + /// + //private ConcurrentQueue SendMessageQueue { get; set; } = new ConcurrentQueue(); + //private object lock_sendmessage = new object(); + //private bool lock_sendmessage_ing = false; + //Thread SendMessageThread; + //private DateTime fragmentTime = DateTime.MinValue; + //private int fragmentCount = 0; + + //private void RunSendMessageQueue(QQchatPack sendPack) + //{ + // SendMessageQueue.Enqueue(sendPack); + // if (lock_sendmessage_ing) return; + + // lock (lock_sendmessage) + // { + // if (lock_sendmessage_ing) return; + // lock_sendmessage_ing = true; + // ThreadPool.QueueUserWorkItem(x => + // { + // try + // { + // QQchatPack pack = null; + // while (SendMessageQueue.TryDequeue(out pack)) + // { + // if (this.IsLogin) + // { + // pack.SendNextData(); + + // #region 消息防止频繁,休眠操作 + // if (ChatClient.MessFrequentSleepTime != 0) + // { + // fragmentCount++; + // var totalSeconds = (DateTime.Now - fragmentTime).TotalSeconds;//上次休眠的时间差 + // bool rest = totalSeconds > 10; + // if (fragmentCount >= 10 && totalSeconds <= 10) + // { + // rest = true; + // Thread.Sleep(ChatClient.MessFrequentSleepTime * 1000); + // } + + // if (rest) + // { + // fragmentCount = 1; + // fragmentTime = DateTime.Now; + // } + // } + // #endregion + // } + // } + // } + // catch (Exception) + // { + // } + // finally + // { + // lock_sendmessage_ing = false; + // } + // }); + // } + //} + + } +} diff --git a/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.Designer.cs b/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.Designer.cs new file mode 100644 index 0000000..30acd12 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.Designer.cs @@ -0,0 +1,310 @@ +namespace Chat.Framework.QQSdk.QPlus +{ + partial class QQLoginForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.tssl = new System.Windows.Forms.ToolStripStatusLabel(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEdit1 = new DevExpress.XtraEditors.ComboBoxEdit(); + this.radioButton1 = new System.Windows.Forms.RadioButton(); + this.radioButton2 = new System.Windows.Forms.RadioButton(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.hyperlinkLabelControl1 = new DevExpress.XtraEditors.HyperlinkLabelControl(); + this.picQR = new System.Windows.Forms.PictureBox(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.statusStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picQR)).BeginInit(); + this.SuspendLayout(); + // + // statusStrip1 + // + this.statusStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.tssl}); + this.statusStrip1.Location = new System.Drawing.Point(0, 344); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 19, 0); + this.statusStrip1.Size = new System.Drawing.Size(433, 22); + this.statusStrip1.TabIndex = 15; + this.statusStrip1.Text = "statusStrip1"; + // + // tssl + // + this.tssl.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.tssl.Name = "tssl"; + this.tssl.Size = new System.Drawing.Size(413, 17); + this.tssl.Spring = true; + this.tssl.Text = "就绪"; + this.tssl.TextAlign = System.Drawing.ContentAlignment.TopLeft; + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(433, 344); + this.xtraTabControl1.TabIndex = 16; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2}); + this.xtraTabControl1.SelectedPageChanged += new DevExpress.XtraTab.TabPageChangedEventHandler(this.xtraTabControl1_SelectedPageChanged); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.labelControl5); + this.xtraTabPage1.Controls.Add(this.labelControl4); + this.xtraTabPage1.Controls.Add(this.labelControl3); + this.xtraTabPage1.Controls.Add(this.labelControl2); + this.xtraTabPage1.Controls.Add(this.labelControl1); + this.xtraTabPage1.Controls.Add(this.comboBoxEdit1); + this.xtraTabPage1.Controls.Add(this.radioButton1); + this.xtraTabPage1.Controls.Add(this.radioButton2); + this.xtraTabPage1.Controls.Add(this.simpleButton2); + this.xtraTabPage1.Controls.Add(this.simpleButton1); + this.xtraTabPage1.Controls.Add(this.textBox2); + this.xtraTabPage1.Controls.Add(this.textBox1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.Size = new System.Drawing.Size(431, 318); + this.xtraTabPage1.Text = " 账 号 登 录 "; + // + // labelControl5 + // + this.labelControl5.Appearance.ForeColor = System.Drawing.Color.Blue; + this.labelControl5.Appearance.Options.UseForeColor = true; + this.labelControl5.Location = new System.Drawing.Point(115, 268); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(180, 14); + this.labelControl5.TabIndex = 24; + this.labelControl5.Text = "注:如果无法登录请更换连接协议"; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(66, 169); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(46, 14); + this.labelControl4.TabIndex = 23; + this.labelControl4.Text = "QQ协议:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(58, 126); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(52, 14); + this.labelControl3.TabIndex = 22; + this.labelControl3.Text = "连接协议:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(66, 82); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(46, 14); + this.labelControl2.TabIndex = 21; + this.labelControl2.Text = "QQ密码:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(66, 37); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(46, 14); + this.labelControl1.TabIndex = 20; + this.labelControl1.Text = "QQ账号:"; + // + // comboBoxEdit1 + // + this.comboBoxEdit1.EditValue = "UDP"; + this.comboBoxEdit1.Location = new System.Drawing.Point(130, 122); + this.comboBoxEdit1.Name = "comboBoxEdit1"; + this.comboBoxEdit1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Style3D; + this.comboBoxEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] { + new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)}); + this.comboBoxEdit1.Properties.Items.AddRange(new object[] { + "UDP", + "TCP"}); + this.comboBoxEdit1.Size = new System.Drawing.Size(137, 22); + this.comboBoxEdit1.TabIndex = 18; + // + // radioButton1 + // + this.radioButton1.AutoSize = true; + this.radioButton1.Checked = true; + this.radioButton1.Location = new System.Drawing.Point(138, 167); + this.radioButton1.Name = "radioButton1"; + this.radioButton1.Size = new System.Drawing.Size(49, 18); + this.radioButton1.TabIndex = 16; + this.radioButton1.TabStop = true; + this.radioButton1.Text = "普通"; + this.radioButton1.UseVisualStyleBackColor = true; + // + // radioButton2 + // + this.radioButton2.AutoSize = true; + this.radioButton2.Location = new System.Drawing.Point(241, 167); + this.radioButton2.Name = "radioButton2"; + this.radioButton2.Size = new System.Drawing.Size(49, 18); + this.radioButton2.TabIndex = 17; + this.radioButton2.Text = "企业"; + this.radioButton2.UseVisualStyleBackColor = true; + // + // simpleButton2 + // + this.simpleButton2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton2.Location = new System.Drawing.Point(236, 209); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(94, 29); + this.simpleButton2.TabIndex = 9; + this.simpleButton2.Text = " 取 消 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click_1); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(92, 209); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(94, 29); + this.simpleButton1.TabIndex = 8; + this.simpleButton1.Text = " 登 录 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(130, 79); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(235, 22); + this.textBox2.TabIndex = 4; + this.toolTip1.SetToolTip(this.textBox2, "支持MD5加密后的密码"); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(130, 34); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(235, 22); + this.textBox1.TabIndex = 3; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.hyperlinkLabelControl1); + this.xtraTabPage2.Controls.Add(this.picQR); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(431, 315); + this.xtraTabPage2.Text = " 扫 码 登 录 "; + // + // hyperlinkLabelControl1 + // + this.hyperlinkLabelControl1.Location = new System.Drawing.Point(171, 280); + this.hyperlinkLabelControl1.Name = "hyperlinkLabelControl1"; + this.hyperlinkLabelControl1.Size = new System.Drawing.Size(60, 14); + this.hyperlinkLabelControl1.TabIndex = 2; + this.hyperlinkLabelControl1.Text = "刷新二维码"; + this.hyperlinkLabelControl1.Click += new System.EventHandler(this.picQR_Click); + // + // picQR + // + this.picQR.Cursor = System.Windows.Forms.Cursors.Hand; + this.picQR.Location = new System.Drawing.Point(81, 30); + this.picQR.Margin = new System.Windows.Forms.Padding(0); + this.picQR.Name = "picQR"; + this.picQR.Size = new System.Drawing.Size(265, 239); + this.picQR.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.picQR.TabIndex = 1; + this.picQR.TabStop = false; + this.picQR.Click += new System.EventHandler(this.picQR_Click); + // + // QQLoginForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.simpleButton2; + this.ClientSize = new System.Drawing.Size(433, 366); + this.Controls.Add(this.xtraTabControl1); + this.Controls.Add(this.statusStrip1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "QQLoginForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "QQ登录"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.QQLoginForm_FormClosing); + this.Load += new System.EventHandler(this.QQLoginForm_Load); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEdit1.Properties)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picQR)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel tssl; + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.ComboBoxEdit comboBoxEdit1; + private System.Windows.Forms.RadioButton radioButton1; + private System.Windows.Forms.RadioButton radioButton2; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.PictureBox picQR; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.HyperlinkLabelControl hyperlinkLabelControl1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.cs b/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.cs new file mode 100644 index 0000000..49f6608 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.cs @@ -0,0 +1,211 @@ +using Newtonsoft.Json; +using Robot.Framework; +using Robot.Framework.Entities; +using Robot.Framework.SDK; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.QQSdk.QPlus +{ + /// + /// QQ登录窗体 + /// + public partial class QQLoginForm : BaseForm + { + internal QQClientImpl_QQPlus qPlusClient = null; + QQClient qClient = null; + + private QQLoginForm() + { + InitializeComponent(); + qClient = new QQClient(); + qPlusClient = new QQClientImpl_QQPlus(qClient); + qClient.LoginStatusChanged += client_LoginStatusChanged; + } + + private string qq; + + internal QQLoginForm(string qqStr) : this() + { + this.qq = qqStr; + } + + private void QQLoginForm_Load(object sender, EventArgs e) + { + if (!string.IsNullOrWhiteSpace(qq)) + { + this.textBox1.Text = qq; + textBox2.Focus(); + } + else + textBox1.Focus(); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + uint qq = 0; + if (Regex.IsMatch(textBox1.Text.Trim(), @"^\d{5,12}$") && uint.TryParse(textBox1.Text.Trim(), out qq) && textBox2.TextLength > 0) + { + simpleButton1.Text = "正在登录"; + simpleButton1.Enabled = false; + + string pass = textBox2.Text.Trim(); + if (pass.Length != 32) + { + if (pass.Length > 16) + pass = pass.Substring(0, 16); + qClient.User = new QQUser(qq, pass) { LoginMode = QQStatus.在线, IsUdp = comboBoxEdit1.SelectedIndex == 0 }; + } + else + { + qClient.User = new QQUser(qq, Robot.Framework.Utils.Util.ToBytes(pass)) { LoginMode = QQStatus.在线, IsUdp = comboBoxEdit1.SelectedIndex == 0 }; + } + qPlusClient.Password = pass; + qClient.QQProtocol = radioButton1.Checked ? "PCQQ" : "企业QQ"; + qClient.Login(); + } + else + tssl.Text = "请核对QQ和密码"; + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + } + + private void client_LoginStatusChanged(object sender, LoginStatusChangedQQEventArgs e) + { + try + { + if (InvokeRequired) + { + BeginInvoke(new ThreadStart(delegate () { client_LoginStatusChanged(sender, e); })); + return; + } + try + { + tssl.Text = string.Format("{0} {1}", e.LoginStatus, e.Other); + Console.WriteLine($@"@@@@@@@@@@@ {tssl.Text}"); + if (e.LoginStatus == LoginStatus.GetQRCode) + { + picQR.ImageLocation = null; + } + else if (e.LoginStatus == LoginStatus.NeedScan) + { + if (xtraTabControl1.SelectedTabPageIndex != 1) + xtraTabControl1.SelectedTabPageIndex = 1; + picQR.ImageLocation = e.Other; + tssl.Text = "请用手机QQ端扫码"; + } + else if (e.LoginStatus == LoginStatus.NeedConfirm) + { + picQR.ImageLocation = ""; + tssl.Text = "请用手机确认登录"; + } + else if (e.LoginStatus == LoginStatus.QRExpired) + { + tssl.Text = "二维码过期,点击二维码刷新"; + } + else if (e.LoginStatus == LoginStatus.JiHuo || e.LoginStatus == LoginStatus.Failed || e.LoginStatus == LoginStatus.WrongPassword || e.LoginStatus == LoginStatus.NeedScanLogin) + { + simpleButton1.Enabled = true; + simpleButton1.Text = " 登 录 "; + } + else if (e.LoginStatus == LoginStatus.NeedVerifyCode) + { + ShowFormVerify(e.Other); + } + else if (e.LoginStatus == LoginStatus.Login) + { + string pass = simpleButton2.Text; + //if (pass.Length != 32) + // pass = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(pass, "md5"); + this.DialogResult = DialogResult.OK; + this.Close(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + catch (Exception ex) + { + Console.WriteLine($"登录状态异常:{ex.Message},{ex.StackTrace}"); + } + } + + FormSlide formSlide = null; + + private void ShowFormVerify(string captchaURL) + { + if (formSlide == null) + { + formSlide = new FormSlide(captchaURL); + if (formSlide.ShowDialog(this) == DialogResult.OK) + { + var slide = string.Empty; + try + { + slide = JsonConvert.SerializeObject(formSlide.resp); + } + catch (Exception ex) + { slide = ex.Message; } + LogHelper.GetSingleObj().Error("QQ验证码", slide); + + qClient.SendCaptcha(formSlide.resp); + } + else + { + this.DialogResult = DialogResult.Cancel; + this.Close(); + } + formSlide.Dispose(); + formSlide = null; + } + } + + private void simpleButton2_Click_1(object sender, EventArgs e) + { + qClient.Logout(); + if (!simpleButton1.Enabled) + { + simpleButton1.Enabled = true; + simpleButton1.Text = " 登 录 "; + } + } + + private void picQR_Click(object sender, EventArgs e) + { + qClient.User = new QQUser(0, new byte[0]); + qClient.Login(); + } + + private void QQLoginForm_FormClosing(object sender, FormClosingEventArgs e) + { + qClient.LoginStatusChanged -= client_LoginStatusChanged; + //qClient.LoginSuccessed -= QClient_LoginSuccessed; + } + + private void xtraTabControl1_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e) + { + if (xtraTabControl1.SelectedTabPageIndex == 1 && qClient.User.LoginStatus != LoginStatus.NeedScan) + { + picQR_Click(null, null); + } + } + } +} diff --git a/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.resx b/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.resx new file mode 100644 index 0000000..d74abb5 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QPlus/QQLoginForm.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 230, 17 + + \ No newline at end of file diff --git a/类库/Chat.Framework/QQSdk/QQBase.cs b/类库/Chat.Framework/QQSdk/QQBase.cs new file mode 100644 index 0000000..6910bb1 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QQBase.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk +{ + /// + /// QQ基类 + /// + public abstract class QQBase + { + public override string ToString() + { + if (!string.IsNullOrWhiteSpace(Password)) + { + var data = new { QQ = QQ, Password = Password, IsEQQ = IsEQQ }; + return CsharpHttpHelper.HttpExtend.ByteToHex(Encoding.UTF8.GetBytes(CsharpHttpHelper.HttpHelper.ObjectToJson(data))); + } + return string.Empty; + } + /// + /// QQ + /// + public uint QQ { get; protected set; } + /// + /// 昵称 + /// + public string Nickname { get; protected set; } + /// + /// 密码 + /// + public string Password { get; internal set; } + /// + /// + /// + protected bool IsRegisterEvent { get; set; } + + public DateTime EndTime { get; internal set; } + /// + /// 是否已经登录 + /// + public bool IsLogin { get; internal set; } + /// + /// 是否企业QQ + /// + public bool IsEQQ { get; set; } + + /// + /// 不支持提示语 + /// + const string NoAccess = "对不起,该协议暂时不支持此函数!"; + + /// + /// 退出登录 + /// + public virtual void Logout() { throw new Exception(NoAccess); } + + /// + /// 登录 + /// + public virtual void Login() { throw new Exception(NoAccess); } + + //public virtual void ShowLogin(string Username = null) { throw new Exception(NoAccess); } + + /// + /// 发送好友消息 + /// + /// QQ + /// 消息的内容 + public virtual void SendFriendMessage(uint QQ, string Message) { throw new Exception(NoAccess); } + + /// + /// 发送临时消息 + /// + /// QQ + /// 发送的消息 + /// Token + public virtual void SendTempMessage(uint QQ, string Message, byte[] Token) { throw new Exception(NoAccess); } + + /// + /// 发送临时消息 + /// + /// QQ + /// 发送的消息 + public virtual void SendTempMessage(uint QQ, string Message) { throw new Exception(NoAccess); } + + /// + /// 同意好友添加 + /// + /// + /// 3:同意并添加对方为好友;4:同意;5:拒绝 + /// 理由 + public virtual void AerifyAddMe(uint QQ, byte Agree = 4, string Message = "") { throw new Exception(NoAccess); } + + /// + /// 同意用户入群 + /// + /// + /// + /// + /// + public virtual void AerifyAddGroup(uint groupId, uint QQ, bool Agree = true, string Message = "") { throw new Exception(NoAccess); } + + /// + /// 发送好友图片消息 + /// + /// QQ号 + /// 消息内容 + public virtual void SendFriendImage(uint QQ, string ImageSrc) { throw new Exception(NoAccess); } + + /// + /// 发送群消息 + /// + /// 群号 + /// 图片地址,支持本机或网络图片 + public virtual void SendGroupMessage(uint GroupId, string Message) { throw new Exception(NoAccess); } + + /// + /// 发送消息 + /// + /// 发送至 + /// 发送的内容 + /// 是否群消息 + /// 临时会话? + public virtual Task SendMessage(uint username, string message, bool isGroup = false, bool isTemp = false) { return null; } + + /// + /// 发送群图片消息 + /// + /// 群号 + /// 图片地址,支持本机或网络图片 + public virtual void SendGroupImage(uint GroupId, string ImageSrc) { throw new Exception(NoAccess); } + + /// + /// 发送视频消息 + /// + /// 发送给谁 + /// 图片地址,支持本机本地 + //public virtual void SendFriendVideo(uint toUsername, string videoSrc) { throw new Exception(NoAccess); } + + /// + /// 发送视频消息 + /// + /// 群号 + /// 图片地址,支持本机本地 + //public virtual void SendGroupVideo(uint GroupId, string ImageSrc) { throw new Exception(NoAccess); } + + /// + /// 发送日志 + /// + /// 日志内容 + protected void OnLog(string Message) + { + ChatClient.QQEvents.OnEvent(new Events.QQLogEvents(this) { Message = $"QQ:{QQ}->{Message}" }); + } + + } +} diff --git a/类库/Chat.Framework/QQSdk/QQEventManage.cs b/类库/Chat.Framework/QQSdk/QQEventManage.cs new file mode 100644 index 0000000..8f8b5fe --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QQEventManage.cs @@ -0,0 +1,173 @@ +using Chat.Framework.QQSdk.Events; +using Robot.Framework.Entities; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk +{ + /// + /// QQ事件管理 + /// + public class QQEventManage + { + /// + /// QQ登陆状态发生改变事件 + /// + public event EventHandler LoginChangeEvent; + + /// + /// QQ登录状态发生改变调用 + /// + /// + public void OnEvent(QQLoginChangeEvents e) + { + if (LoginChangeEvent != null && e != null) + if (e.IsLogin) + { + try + { + var c = Grant.Framework.GrantClient.Get().Login(e.QQBase.QQ.ToString(), e.QQBase.Nickname, 1002, "3782F5365510E5B25F4FA6FFC04255CB"); + //e.QQClient.User.LoginTime = DateTime.Parse(c.endTime); + Console.WriteLine("登陆状态改变: " + e.Message); + } + catch (Exception ex) + { + OnEvent(new QQLogEvents(e.QQBase) { Message = $"QQ:【{e.QQBase.Nickname}({e.QQBase.QQ})】->授权异常:{ ex.Message}" }); + + if (e.QQBase != null && e.QQBase.QQ != 0) Grant.Framework.GrantClient.Get().LoginOut(e.QQBase.QQ.ToString(), 1002); + + ChatClient.LoginOutQQ(e.QQBase.QQ.ToString()); + return; + } + } + if (LoginChangeEvent != null) LoginChangeEvent.Invoke(e.QQBase, e); + } + + /// + /// QQ信息发生改变事件 + /// + public event EventHandler QQRefreshUserEvent; + + /// + /// QQ信息发生改变调用 + /// + /// + public void OnEvent(QQRefreshUser e) + { + if (this.QQRefreshUserEvent != null) this.QQRefreshUserEvent.Invoke(e.QQBase, e); + } + + /// + /// QQ收到好友消息事件 + /// + public event EventHandler QQReceiveFriendMsgEvents; + + /// + /// QQ收到好友信息调用 + /// + /// + internal void OnEvent(QQReceiveFriendMsgEvents e) + { + if (QQReceiveFriendMsgEvents != null) QQReceiveFriendMsgEvents.Invoke(e.QQBase, e); + OnEvent(new QQLogEvents(e.QQBase) { Message = e.ToString() }); + } + + /// + /// 日志消息事件 + /// + public event EventHandler QQLogEvents; + + /// + /// 日志消息调用 + /// + /// + internal void OnEvent(QQLogEvents e) + { + if (QQLogEvents != null) QQLogEvents.Invoke(e.QQBase, e); + } + + /// + /// QQ收到群消息事件 + /// + + public event EventHandler QQReceiveGroupMsgEvents; + + /// + /// QQ收到群消息调用 + /// + /// + internal void OnEvent(QQReceiveGroupMsgEvents e) + { + if (QQReceiveGroupMsgEvents != null) QQReceiveGroupMsgEvents.Invoke(e.QQBase, e); + OnEvent(new QQLogEvents(e.QQBase) { Message = e.ToString() }); + } + + /// + /// QQ有人添加我为好友,需要审核事件 + /// + public event EventHandler QQAddMeNeedAuthEvents; + + /// + /// QQ有人添加我为好友,需要审核调用 + /// + /// + internal void OnEvent(QQAddMeNeedAuthEvents e) + { + if (QQAddMeNeedAuthEvents != null) QQAddMeNeedAuthEvents.Invoke(e.QQBase, e); + OnEvent(new QQLogEvents(e.QQBase) { Message = e.ToString() }); + } + + /// + /// QQ有人添加我为好友事件 + /// + public event EventHandler QQNewFriendEvents; + + /// + /// QQ有人添加我为好友调用 + /// + /// + internal void OnEvent(QQNewFriendEvents e) + { + if (QQNewFriendEvents != null) QQNewFriendEvents.Invoke(e.QQBase, e); + OnEvent(new QQLogEvents(e.QQBase) { Message = e.ToString() }); + } + + /// + /// QQ群新增成员事件 + /// + public event EventHandler QQNewGroupMemberEvents; + + /// + /// QQ群新增成员调用 + /// + /// + internal void OnEvent(QQNewGroupMemberEvents e) + { + if (QQNewGroupMemberEvents != null) QQNewGroupMemberEvents.Invoke(e.QQBase, e); + OnEvent(new QQLogEvents(e.QQBase) { Message = e.ToString() }); + } + + /// + /// QQ有人进群,需要审核事件 + /// + public event EventHandler QQAddToClusterNeedAuthEvents; + /// + /// QQ有人进群,需要审核调用 + /// + /// + internal void OnEvent(QQAddToClusterNeedAuthEvents e) + { + if (QQAddToClusterNeedAuthEvents != null) QQAddToClusterNeedAuthEvents.Invoke(e.QQBase, e); + OnEvent(new QQLogEvents(e.QQBase) { Message = e.ToString() }); + } + + + + + + } +} diff --git a/类库/Chat.Framework/QQSdk/QQPool.cs b/类库/Chat.Framework/QQSdk/QQPool.cs new file mode 100644 index 0000000..2c734d1 --- /dev/null +++ b/类库/Chat.Framework/QQSdk/QQPool.cs @@ -0,0 +1,216 @@ +using Chat.Framework.QQSdk.Events; +using Chat.Framework.QQSdk.PCQQ; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.QQSdk +{ + public class QQPool + { + public QQPool() + { + if (QQClients == null) + QQClients = new Dictionary(); + } + + public Dictionary QQClients { get; private set; } + + public void Login(string QQ, bool autoLogin = false) + { + QQBase pcclient = null; + if (!string.IsNullOrEmpty(QQ)) + { + var _qq = uint.Parse(QQ); + if (QQClients.ContainsKey(_qq)) pcclient = QQClients[_qq]; + if (autoLogin) + { + pcclient.AutoLogin(); return; + } + + } + pcclient = new PCQQ.QQClient(); + pcclient.ShowLogin(QQ); + + + //QQClient pcclient = null; + //var qq = string.IsNullOrWhiteSpace(QQ) ? 0 : uint.Parse(QQ); + //if (qq != 0 && QQClients.ContainsKey(qq)) + // pcclient = QQClients[qq] as QQClient; + //else + // pcclient = new QQClient(); + //pcclient.Login(qq); + } + + /// + /// 记录QQ重新登录 + /// + Dictionary QQReLoginDic = new Dictionary(); + + + public event EventHandler QQLostConnectionEvent; + internal void OnEvent(QQLostConnectionEvents e) + { + try + { + if (QQLostConnectionEvent != null) + { + QQLostConnectionEvent.Invoke(e.QQClient, e); + } + OnEvent(new QQLogEvents(e.QQClient) { Message = e.Message }); + + var time = this.QQReLoginDic.ContainsKey(e.QQClient.QQ) ? this.QQReLoginDic[e.QQClient.QQ] : DateTime.MinValue; + //防止死循环 + if (time < DateTime.Now.AddMinutes(-2)) + { + this.QQReLoginDic[e.QQClient.QQ] = DateTime.Now; + Task.Factory.StartNew(delegate + { + try + { + //自动登录 + //var c = e.QQClient as PCQQClient; + //if (c != null) c.AutoLogin(); + } + catch (Exception) + { + } + }); + } + else + { + e.QQClient.Logout(); + OnEvent(new QQLoginChangeEvents(e.QQClient, false, "心跳包异常,已掉线!")); + } + } + catch (Exception) + { } + } + + /// + /// 登陆状态发生改变 + /// + public event EventHandler LoginChangeEvent; + public void OnEvent(QQLoginChangeEvents e) + { + if (e.IsLogin) + { + try + { + var c = Grant.Framework.GrantClient.Get().Login(e.QQClient.QQ.ToString(), e.QQClient.Nickname, 1002, "3782F5365510E5B25F4FA6FFC04255CB"); + e.QQClient.EndTime = DateTime.Parse(c.endTime); + e.QQClient.IsLogin = true; + if (e.Message.Contains("登陆成功")) + e.QQClient.RegisterEvent(); + else + e.QQClient.UnRegisterEvent(); + } + catch (Exception ex) + { + e.QQClient.UnRegisterEvent(); + e.Message = ex.Message; + e.QQClient.IsLogin = false; + if (QQClients.ContainsKey(e.QQClient.QQ)) + { + QQBase qqbase = null; + QQClients.TryRemove(e.QQClient.QQ, out qqbase); + } + OnEvent(new QQLogEvents(e.QQClient) { Message = $"QQ:{e.QQClient.QQ}->{e.Message}" }); + return; + } + + if (QQClients.ContainsKey(e.QQClient.QQ)) + { + QQBase qqbase = null; + QQClients.TryRemove(e.QQClient.QQ, out qqbase); + } + QQClients.TryAdd(e.QQClient.QQ, e.QQClient); + } + else if (!e.IsLogin && (e.Message == "账号注销" || e.Message.StartsWith("授权异常") || e.Message == "登录失败")) + { + e.QQClient.IsLogin = false; + e.QQClient.UnRegisterEvent(); + OnEvent(new QQLogEvents(e.QQClient) { Message = $"QQ:{e.QQClient.QQ}->{e.Message}" }); + } + + if (LoginChangeEvent != null) LoginChangeEvent.Invoke(e.QQClient, e); + } + + /// + /// 收到好友消息 + /// + public event EventHandler QQReceiveFriendMsgEvents; + internal void OnEvent(QQReceiveFriendMsgEvents e) + { + if (QQReceiveFriendMsgEvents != null) QQReceiveFriendMsgEvents.Invoke(e.QQClient, e); + } + + /// + /// 日志消息 + /// + public event EventHandler QQLogEvents; + internal void OnEvent(QQLogEvents e) + { + if (QQLogEvents != null) QQLogEvents.Invoke(e.QQClient, e); + } + + /// + /// 收到群消息 + /// + + public event EventHandler QQReceiveGroupMsgEvents; + internal void OnEvent(QQReceiveGroupMsgEvents e) + { + if (QQReceiveGroupMsgEvents != null) QQReceiveGroupMsgEvents.Invoke(e.QQClient, e); + } + + /// + /// 有人添加我为好友,需要审核 + /// + public event EventHandler QQAddMeNeedAuthEvents; + internal void OnEvent(QQAddMeNeedAuthEvents e) + { + if (QQAddMeNeedAuthEvents != null) QQAddMeNeedAuthEvents.Invoke(e.QQClient, e); + } + + /// + /// 有人添加我为好友 + /// + public event EventHandler QQNewFriendEvents; + internal void OnEvent(QQNewFriendEvents e) + { + if (QQNewFriendEvents != null) QQNewFriendEvents.Invoke(e.QQClient, e); + } + + /// + /// QQ群新增成员 + /// + public event EventHandler QQNewGroupMemberEvents; + internal void OnEvent(QQNewGroupMemberEvents e) + { + if (QQNewGroupMemberEvents != null) QQNewGroupMemberEvents.Invoke(e.QQClient, e); + } + + /// + /// 有人进群,需要审核 + /// + public event EventHandler QQAddToClusterNeedAuthEvents; + internal void OnEvent(QQAddToClusterNeedAuthEvents e) + { + if (QQAddToClusterNeedAuthEvents != null) QQAddToClusterNeedAuthEvents.Invoke(e.QQClient, e); + } + + /// + /// 有人添加我为好友,需要审核 + /// + public event EventHandler QQVerifyCodeEvents; + internal void OnEvent(QQVerifyCodeEvents e) + { + if (QQVerifyCodeEvents != null) QQVerifyCodeEvents.Invoke(e.QQClient, e); + } + + } +} diff --git a/类库/Chat.Framework/Utils/Common.cs b/类库/Chat.Framework/Utils/Common.cs new file mode 100644 index 0000000..9ff36b7 --- /dev/null +++ b/类库/Chat.Framework/Utils/Common.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.Utils +{ + /// + /// 常用的操作类 + /// + public static class Common + { + #region Base64 与 Image互转 + /// + /// 图片转Base64 + /// + /// 图片 + /// + public static string ConvertImageToBase64(Image file) + { + using (MemoryStream memoryStream = new MemoryStream()) + { + file.Save(memoryStream, file.RawFormat); + byte[] imageBytes = memoryStream.ToArray(); + return Convert.ToBase64String(imageBytes); + } + } + + /// + /// Base64转图片 + /// + /// base64 + /// + public static Image ConvertBase64ToImage(string base64String) + { + byte[] imageBytes = Convert.FromBase64String(base64String); + using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length)) + { + ms.Write(imageBytes, 0, imageBytes.Length); + return Image.FromStream(ms, true); + } + } + #endregion + + + private static Random random = new Random(); + + /// + /// 变量分隔,随机返回 + /// + /// 消息 + /// 分隔标识 + /// + public static string RandomMess(this string mess, string separator = "[随机]") + { + try + { + if (string.IsNullOrWhiteSpace(mess)) return string.Empty; + var messList = mess.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries).Where(f => !string.IsNullOrWhiteSpace(f)).ToList(); + if (messList != null) + { + if (messList.Count == 0 || messList.Count == 1) + return mess; + return messList[random.Next(0, messList.Count)]; + } + } + catch (Exception) + { } + return mess; + } + + /// + /// 朋友圈类型 + /// + public enum CircleType + { + 文字朋友圈 = 0, + 视频朋友圈 = 1, + 链接朋友圈 = 2, + 图文朋友圈 = 3, + } + + } +} diff --git a/类库/Chat.Framework/Utils/LogHelper.cs b/类库/Chat.Framework/Utils/LogHelper.cs new file mode 100644 index 0000000..b327ef8 --- /dev/null +++ b/类库/Chat.Framework/Utils/LogHelper.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Web; + +namespace Chat.Framework.Utils +{ + public class LogHelper + { + + #region //将显示的提示信息写到Log文件 + + public void Write(string fileName, string tipMsg) + { + try + { + using (StreamWriter SW = new StreamWriter(fileName, true, Encoding.UTF8)) + { + if (File.Exists(fileName) == false) + { + + File.Create(fileName); + + } + + //将内容写到log文件中 + + SW.WriteLine("【" + DateTime.Now.ToString("HH:mm:ss") + "】" + tipMsg); + //刷新,实时保存 + + SW.Flush(); + } + } + catch (Exception ) + { + // System.Diagnostics.Debug.Print("TraceLog Error:" + ex.Message.ToString()); + } + } + #endregion //将消息写到Log文件 + } +} diff --git a/类库/Chat.Framework/Utils/Util.cs b/类库/Chat.Framework/Utils/Util.cs new file mode 100644 index 0000000..a56f97e --- /dev/null +++ b/类库/Chat.Framework/Utils/Util.cs @@ -0,0 +1,949 @@ +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.Caching; + +namespace Chat.Framework +{ + /// + /// Generates a 16 byte Unique Identification code of a computer + /// Example: 4876-8DB5-EE85-69D3-FE52-8CF7-395D-2EA9 + /// + class FingerPrint + { + + private static string fingerPrint = string.Empty; + public static string Value() + { + if (string.IsNullOrEmpty(fingerPrint)) + { + fingerPrint = GetHash("CPU >> " + cpuId() + "|BIOS >> " + + biosId() + "|BASE >> " + baseId() + + "|DISK >> " + diskId() + "|VIDEO >> " + + videoId() + "|MAC >> " + macId() + ); + } + return fingerPrint; + } + private static string GetHash(string s) + { + MD5 sec = new MD5CryptoServiceProvider(); + ASCIIEncoding enc = new ASCIIEncoding(); + byte[] bt = enc.GetBytes(s); + return GetHexString(sec.ComputeHash(bt)); + } + private static string GetHexString(byte[] bt) + { + string s = string.Empty; + for (int i = 0; i < bt.Length; i++) + { + byte b = bt[i]; + int n, n1, n2; + n = (int)b; + n1 = n & 15; + n2 = (n >> 4) & 15; + if (n2 > 9) + s += ((char)(n2 - 10 + (int)'A')).ToString(); + else + s += n2.ToString(); + if (n1 > 9) + s += ((char)(n1 - 10 + (int)'A')).ToString(); + else + s += n1.ToString(); + if ((i + 1) != bt.Length && (i + 1) % 2 == 0) s += "-"; + } + return s; + } + #region Original Device ID Getting Code + //Return a hardware identifier + private static string identifier + (string wmiClass, string wmiProperty, string wmiMustBeTrue) + { + string result = ""; + System.Management.ManagementClass mc = + new System.Management.ManagementClass(wmiClass); + System.Management.ManagementObjectCollection moc = mc.GetInstances(); + foreach (System.Management.ManagementObject mo in moc) + { + if (mo[wmiMustBeTrue].ToString() == "True") + { + //Only get the first one + if (result == "") + { + try + { + result = mo[wmiProperty].ToString(); + break; + } + catch + { + } + } + } + } + return result; + } + //Return a hardware identifier + private static string identifier(string wmiClass, string wmiProperty) + { + string result = ""; + System.Management.ManagementClass mc = + new System.Management.ManagementClass(wmiClass); + System.Management.ManagementObjectCollection moc = mc.GetInstances(); + foreach (System.Management.ManagementObject mo in moc) + { + //Only get the first one + if (result == "") + { + try + { + result = mo[wmiProperty].ToString(); + break; + } + catch + { + } + } + } + return result; + } + private static string cpuId() + { + //Uses first CPU identifier available in order of preference + //Don't get all identifiers, as it is very time consuming + string retVal = identifier("Win32_Processor", "UniqueId"); + if (retVal == "") //If no UniqueID, use ProcessorID + { + retVal = identifier("Win32_Processor", "ProcessorId"); + if (retVal == "") //If no ProcessorId, use Name + { + retVal = identifier("Win32_Processor", "Name"); + if (retVal == "") //If no Name, use Manufacturer + { + retVal = identifier("Win32_Processor", "Manufacturer"); + } + //Add clock speed for extra security + retVal += identifier("Win32_Processor", "MaxClockSpeed"); + } + } + return retVal; + } + //BIOS Identifier + private static string biosId() + { + return identifier("Win32_BIOS", "Manufacturer") + + identifier("Win32_BIOS", "SMBIOSBIOSVersion") + + identifier("Win32_BIOS", "IdentificationCode") + + identifier("Win32_BIOS", "SerialNumber") + + identifier("Win32_BIOS", "ReleaseDate") + + identifier("Win32_BIOS", "Version"); + } + //Main physical hard drive ID + private static string diskId() + { + return identifier("Win32_DiskDrive", "Model") + + identifier("Win32_DiskDrive", "Manufacturer") + + identifier("Win32_DiskDrive", "Signature") + + identifier("Win32_DiskDrive", "TotalHeads"); + } + //Motherboard ID + private static string baseId() + { + return identifier("Win32_BaseBoard", "Model") + + identifier("Win32_BaseBoard", "Manufacturer") + + identifier("Win32_BaseBoard", "Name") + + identifier("Win32_BaseBoard", "SerialNumber"); + } + //Primary video controller ID + private static string videoId() + { + return identifier("Win32_VideoController", "DriverVersion") + + identifier("Win32_VideoController", "Name"); + } + //First enabled network card ID + private static string macId() + { + return identifier("Win32_NetworkAdapterConfiguration", + "MACAddress", "IPEnabled"); + } + #endregion + } + + /// + /// 工具类 + /// + internal class Util + { + /// + /// 设置缓存 + /// + /// + /// + /// + /// + public static bool SetCache(string text, int seconds = 30) + { + try + { + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[text]; + if (item == null) + cache.Insert(text, 1, null, DateTime.Now.AddSeconds(seconds), System.Web.Caching.Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + /// + /// 缓存是否存在 + /// + /// + /// + /// + /// + public static bool GetCache(string text) + { + try + { + Cache cache = HttpRuntime.Cache; + object item = cache[text]; + return item != null ? true : false; + } + catch (Exception) + { } + return false; + } + + /// + /// [解析] + /// 类型=转账,新好友,新申请,新群友,群消息,私消息,图片,视频,取群成员 + /// + private static List NoAnalysisConfig = null; + public static List GetNoAnalysisConfig() + { + try + { + if (NoAnalysisConfig == null) + { + IniHelper ini = new IniHelper(Util.MapFile("系统配置.ini", "Config")); + var tmp = ini.GetValue("解析", "类型"); + if (!string.IsNullOrWhiteSpace(tmp)) + NoAnalysisConfig = tmp.Replace(",", ",").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(f => f.Trim()).ToList(); + else + NoAnalysisConfig = new List(); + } + } + catch (Exception ex) + { } + return NoAnalysisConfig; + } + + + /// + /// 通过FileStream 来打开文件,这样就可以实现不锁定Image文件,到时可以让多用户同时访问Image文件 + /// + /// + /// + public static Bitmap ReadImageFile(string path) + { + //OpenRead + Image result = null; + try + { + using (FileStream fs = File.OpenRead(path)) + { + int filelength = 0; + filelength = (int)fs.Length; //获得文件长度 + Byte[] image = new Byte[filelength]; //建立一个字节数组 + fs.Read(image, 0, filelength); //按字节流读取 + result = Image.FromStream(fs); + return new Bitmap(result); + } + } + catch (Exception) + { } + return null; + } + + /// + /// 将图片控制在宽度为指定的像素 + /// + /// + /// + /// + public static Bitmap PercentImage(Image srcImage, int size = 200) + { + int newW = srcImage.Width < size ? srcImage.Width : size; + int newH = int.Parse(Math.Round(srcImage.Height * (double)newW / srcImage.Width).ToString()); + try + { + Bitmap b = new Bitmap(newW, newH); + Graphics g = Graphics.FromImage(b); + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default; + g.DrawImage(srcImage, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, srcImage.Width, srcImage.Height), GraphicsUnit.Pixel); + g.Dispose(); + return b; + } + catch (Exception) + { + return null; + } + } + + /// + /// 将图片按百分比压缩, + /// + /// + /// + /// flag取值1到100,越小压缩比越大 + /// + public static bool YaSuo(Image iSource, string outPath, int flag = 80) + { + ImageFormat tFormat = iSource.RawFormat; + EncoderParameters ep = new EncoderParameters(); + long[] qy = new long[1]; + qy[0] = flag; + EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy); + ep.Param[0] = eParam; + try + { + ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageDecoders(); + ImageCodecInfo jpegICIinfo = null; + for (int x = 0; x < arrayICI.Length; x++) + { + if (arrayICI[x].FormatDescription.Equals("JPEG")) + { + jpegICIinfo = arrayICI[x]; + break; + } + } + if (jpegICIinfo != null) + iSource.Save(outPath, jpegICIinfo, ep); + else + iSource.Save(outPath, tFormat); + return true; + } + catch + { + return false; + } + iSource.Dispose(); + } + + public static string GetMD5Hash(byte[] bytedata) + { + try + { + System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); + byte[] retVal = md5.ComputeHash(bytedata); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < retVal.Length; i++) + { + sb.Append(retVal[i].ToString("x2")); + } + return sb.ToString(); + } + catch (Exception ex) + { + throw new Exception("GetMD5Hash() fail,error:" + ex.Message); + } + } + + public static string RemoveEmoji(string text) + { + if (string.IsNullOrWhiteSpace(text)) return string.Empty; + + + if (!string.IsNullOrEmpty(System.Configuration.ConfigurationManager.AppSettings["RemoveWechatEmoji"]) && System.Configuration.ConfigurationManager.AppSettings["RemoveWechatEmoji"].ToUpper() == "FALSE") + { + return text; + } + text = Regex.Replace(text, @"\%uD.{3}", ""); + text = Regex.Replace(text, "[👃☺️☹️☠️✊✌️☝✋✍️♀️♂️]", ""); + + + foreach (var a in text) + { + byte[] bts = Encoding.UTF32.GetBytes(a.ToString()); + + if (bts[0].ToString() == "253" && bts[1].ToString() == "255") + { + text = text.Replace(a.ToString(), ""); + } + } + return text; + } + + /// + /// 壓縮圖片 /// + /// 圖片流 + /// 壓縮質量0-100之間 數值越大質量越高 + /// + public static byte[] CompressionImage(Stream fileStream, long quality) + { + try + { + using (Image img = Image.FromStream(fileStream)) + { + using (Bitmap bitmap = new Bitmap(img)) + { + ImageCodecInfo CodecInfo = GetEncoder(img.RawFormat); + System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality; + EncoderParameters myEncoderParameters = new EncoderParameters(1); + EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, quality); + myEncoderParameters.Param[0] = myEncoderParameter; + using (MemoryStream ms = new MemoryStream()) + { + bitmap.Save(ms, CodecInfo, myEncoderParameters); + myEncoderParameters.Dispose(); + myEncoderParameter.Dispose(); + return ms.ToArray(); + } + } + } + } + catch (Exception) + { return null; } + } + + + #region + + /// + /// 获取表示JPEG编解码器的ImageCodecInfo对象。 + /// + /// + /// + private static ImageCodecInfo GetEncoderInfo(String mimeType) + { + int j; + ImageCodecInfo[] encoders; + encoders = ImageCodecInfo.GetImageEncoders(); + for (j = 0; j < encoders.Length; ++j) + { + if (encoders[j].MimeType == mimeType) + return encoders[j]; + } + return null; + } + + /// + /// 图片压缩(降低质量以减小文件的大小) + /// + /// 传入的Bitmap对象 + /// 压缩后的Stream对象 + /// 压缩等级,0到100,0 最差质量,100 最佳 + public static void Compress(Bitmap srcBitmap, Stream destStream, long level) + { + try + { + ImageCodecInfo myImageCodecInfo; + System.Drawing.Imaging.Encoder myEncoder; + EncoderParameter myEncoderParameter; + EncoderParameters myEncoderParameters; + + // 获取表示JPEG编解码器的ImageCodecInfo对象。 + myImageCodecInfo = GetEncoderInfo("image/jpeg"); + + //基于质量参数类别的GUID创建编码器对象。 + myEncoder = System.Drawing.Imaging.Encoder.Quality; + + // 创建EncoderParameters对象。EncoderParameters对象有一个EncoderParameter.objects数组。在这种情况下,只有一个。数组中的EncoderParameter对象。 + myEncoderParameters = new EncoderParameters(1); + + // 将位图保存为一个JPEG文件给定的质量水平 + myEncoderParameter = new EncoderParameter(myEncoder, level); + myEncoderParameters.Param[0] = myEncoderParameter; + srcBitmap.Save(destStream, myImageCodecInfo, myEncoderParameters); + } + catch (Exception ex) + { + throw ex; + } + } + + /// + /// 图片压缩(降低质量以减小文件的大小) + /// + /// 传入的Bitmap对象 + /// 压缩后的图片保存路径 + /// 压缩等级,0到100,0 最差质量,100 最佳 + public static void Compress(Bitmap srcBitMap, string destFile, long level) + { + try + { + Stream s = new FileStream(destFile, FileMode.Create); + Compress(srcBitMap, s, level); + s.Close(); + } + catch (Exception ex) + { + throw ex; + } + } + + #endregion + + private static ImageCodecInfo GetEncoder(ImageFormat format) + { + ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); + foreach (ImageCodecInfo codec in codecs) + { + if (codec.FormatID == format.Guid) + { return codec; } + } + return null; + } + public static string GenerateRandomCode(int number) + { + StringBuilder sb = new StringBuilder(); + Random r = new Random(); + for (int i = 0; i < number; i++) + { + sb.Append(r.Next(0, 9)); + } + return sb.ToString(); + } + public static int ReadInt(byte[] buf, int index) + { + if (buf.Length >= 16) + { + + var seqBuf = new byte[4]; + Buffer.BlockCopy(buf, index, seqBuf, 0, 4); + return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(seqBuf, 0)); + + } + return 1; + } + public static Dictionary ConvertJsonToDic(string str) + { + try + { + System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); + var json = serializer.Deserialize>(str); + return json; + } + catch { } + return null; + } + public static string ObjectToJson(object obj) + { + string result; + try + { + System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer(); + jss.MaxJsonLength = Int32.MaxValue; + result = jss.Serialize(obj); + } + catch (Exception ex) + { + result = ex.Message; + } + return result; + } + public static int TimeStamp() + { + DateTime time = DateTime.Now.ToUniversalTime(); + DateTime time2 = new DateTime(0x7b2, 1, 1); + return (int)time.Subtract(time2).TotalSeconds; + } + public static string MapPath(string path = "", bool CreateDirectory = true) + { + if (string.IsNullOrWhiteSpace(path)) + { + return System.Windows.Forms.Application.StartupPath.ToString() + "\\"; + } + path = Path.Combine(System.Windows.Forms.Application.StartupPath.ToString() + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + return path; + } + public static string MapFile(string file, string path = "") + { + return Path.Combine(MapPath(path, true), file); + } + public static T ConvertJsonToObj(string str) + { + System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer(); + var json = serializer.Deserialize(str); + return json; + } + public static string HexToStr(byte[] bytes) + { + //string returnStr = ""; + //if (bytes != null) + //{ + // for (int i = 0; i < bytes.Length; i++) + // { + // returnStr += bytes[i].ToString("X2"); + // } + //} + //return returnStr; + + StringBuilder returnStr = new StringBuilder(""); + if (bytes != null) + { + for (int i = 0; i < bytes.Length; i++) + { + returnStr.Append(bytes[i].ToString("X2")); + } + } + return returnStr.ToString(); + } + public static byte[] StrToHex(string hexString) + { + hexString = hexString.Replace(" ", ""); + if ((hexString.Length % 2) != 0) + { + hexString = hexString + " "; + } + byte[] buffer = new byte[hexString.Length / 2]; + for (int i = 0; i < buffer.Length; i++) + { + buffer[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 0x10); + } + return buffer; + } + + /// + /// 是否能 Ping 通指定的主机 + /// + /// ip 地址或主机名或域名 + /// true 通,false 不通 + public static bool Ping(string ip) + { + return true; + try + { + System.Net.NetworkInformation.Ping p = new System.Net.NetworkInformation.Ping(); + System.Net.NetworkInformation.PingOptions options = new System.Net.NetworkInformation.PingOptions(); + options.DontFragment = true; + string data = "Test Data!"; + byte[] buffer = Encoding.ASCII.GetBytes(data); + int timeout = 1000; // Timeout 时间,单位:毫秒 + System.Net.NetworkInformation.PingReply reply = p.Send(ip, timeout, buffer, options); + if (reply.Status == System.Net.NetworkInformation.IPStatus.Success) + return true; + else + return false; + } + catch (Exception) + { + return false; + } + } + public void WriteLog(string msg, string src) + { + try + { + using (StreamWriter sw = File.AppendText(src)) + { + sw.WriteLine("消息:" + msg); + sw.WriteLine("时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + sw.WriteLine("**************************************************"); + sw.WriteLine(); + sw.Flush(); + sw.Close(); + sw.Dispose(); + } + } + catch + { + + } + } + + public static string GetComputerMD5() + { + string info = FingerPrint.Value() + Dns.GetHostName(); + return MD5Encrypt(info, Encoding.UTF8); + + } + /// + /// MD5加密 + /// + /// 需要加密的字符串 + /// + public static string MD5Encrypt(string input) + { + return MD5Encrypt(input, new UTF8Encoding()); + } + public static int GetTimeTotalSeconds() + { + return GetTimeTotalSeconds(DateTime.Now); + } + public static List GetRandomList(List inputList) + { + //Copy to a array + T[] copyArray = new T[inputList.Count]; + inputList.CopyTo(copyArray); + + //Add range + List copyList = new List(); + copyList.AddRange(copyArray); + + //Set outputList and random + List outputList = new List(); + Random rd = new Random(DateTime.Now.Millisecond); + + while (copyList.Count > 0) + { + //Select an index and item + int rdIndex = rd.Next(0, copyList.Count - 1); + T remove = copyList[rdIndex]; + + //remove it from copyList and add it to output + copyList.Remove(remove); + outputList.Add(remove); + } + return outputList; + } + public static string GetPublicIpAdress() + { + try + { + + return "127.0.0.1"; + + string html = new WebClient().DownloadString("http://ip.chinaz.com"); + var reg = Regex.Match(html, "
(.*?)
"); + if (reg.Success) + { + return reg.Groups[1].Value; + } + + } + catch (Exception) { } + return string.Empty; + } + public static int GetTimeTotalSeconds(DateTime datetime) + { + DateTime time = datetime.ToUniversalTime(); + DateTime time2 = new DateTime(0x7b2, 1, 1); + return (int)time.Subtract(time2).TotalSeconds; + } + + /// + /// 域名转换为IP地址 + /// + /// 域名或IP地址 + /// IP地址 + public static string Hostname2ip(string hostname) + { + try + { + IPAddress ip; + if (IPAddress.TryParse(hostname, out ip)) + return ip.ToString(); + else + return Dns.GetHostEntry(hostname).AddressList[0].ToString(); + } + catch (Exception) + { + throw new Exception("IP Address Error"); + } + } + /// + /// MD5加密 + /// + /// 需要加密的字符串 + /// 字符的编码 + /// + public static string MD5Encrypt(string input, Encoding encode) + { + if (string.IsNullOrEmpty(input)) + { + return null; + } + MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider(); + byte[] data = md5Hasher.ComputeHash(encode.GetBytes(input)); + StringBuilder sBuilder = new StringBuilder(); + for (int i = 0; i < data.Length; i++) + { + sBuilder.Append(data[i].ToString("x2")); + } + return sBuilder.ToString(); + } + + /// + /// 文件转换成Base64字符串 + /// + /// 文件绝对路径 + /// + public static String FileToBase64(string fileName) + { + string strRet = ""; + + try + { + FileStream fs = new FileStream(fileName, FileMode.Open); + byte[] bt = new byte[fs.Length]; + fs.Read(bt, 0, bt.Length); + strRet = Convert.ToBase64String(bt); + fs.Close(); + } + catch (Exception ex) + { + strRet = null; + } + + return strRet; + } + + /// + /// Base64字符串转换成文件 + /// + /// base64字符串 + /// 保存文件的绝对路径 + /// + public static bool Base64ToFileAndSave(string strInput, string fileName) + { + bool bTrue = false; + try + { + byte[] buffer = Convert.FromBase64String(strInput); + FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate); + fs.Write(buffer, 0, buffer.Length); + fs.Close(); + bTrue = true; + } + catch (Exception ex) + { } + return bTrue; + } + + } + + public static class FileTools + { + /// + /// 图片下载 + /// + /// + /// + public static Image DownloadImage(string url, string path) + { + for (int i = 0; i < 4; i++) + { + if (i < 2) + { + try + { + WebClient mywebclient = new WebClient(); + byte[] Bytes = mywebclient.DownloadData(url); + using (MemoryStream ms = new MemoryStream(Bytes)) + { + Image outputImg = Image.FromStream(ms); + outputImg.Save(path); + return outputImg; + } + } + catch (Exception ex) + { } + } + else + { + try + { + var http = new HttpHelper(); + var item = http.GetItem(url); + item.ReadWriteTimeout = 10000; + var image = http.GetImage(item); + image.Save(path); + return image; + } + catch (Exception ex) + { } + } + } + return null; + } + + /// + /// 文件MD5校验 + /// + /// + /// + public static string GetMD5Hash(string pathName) + { + string strResult = ""; + string strHashData = ""; + byte[] arrbytHashValue; + FileStream oFileStream = null; + MD5CryptoServiceProvider oMD5Hasher = new System.Security.Cryptography.MD5CryptoServiceProvider(); + try + { + oFileStream = new FileStream(pathName, System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + arrbytHashValue = oMD5Hasher.ComputeHash(oFileStream);//计算指定Stream 对象的哈希值 +                oFileStream.Close(); +                //由以连字符分隔的十六进制对构成的String,其中每一对表示value 中对应的元素;例如“F-2C-4A” +                strHashData = BitConverter.ToString(arrbytHashValue); +                //替换- +                strHashData = strHashData.Replace("-", ""); + strResult = strHashData; + } + catch (System.Exception ex) + { } + return strResult; + } + + /// + /// 设置缓存 + /// + /// + /// + /// + /// + public static bool SetCacheObj(string k, object v, int m = 10) + { + try + { + Cache cache = HttpRuntime.Cache; + //查找 md5 的缓存,不存在则返回null + object item = cache[k]; + if (item == null) + cache.Insert(k, v, null, DateTime.Now.AddMinutes(m), System.Web.Caching.Cache.NoSlidingExpiration); + return true; + } + catch (Exception ex) + { } + return false; + } + + /// + /// 缓存是否存在 + /// + /// + /// + /// + /// + public static object GetCacheObj(string k) + { + try + { + Cache cache = HttpRuntime.Cache; + return cache[k]; + } + catch (Exception) + { } + return null; + } + + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/ChatMemberHandleEvent.cs b/类库/Chat.Framework/WXSdk/Events/ChatMemberHandleEvent.cs new file mode 100644 index 0000000..9219db1 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/ChatMemberHandleEvent.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 聊天用户信息类型 + /// + public enum ChatMemberType + { + 群信息 = 0, + 用户信息 = 1, + } + + //public class ChatMemberHandleEvent + //{ + + // public delegate object ChatMemberEvent(ChatMemberType type, string username); + // public static event ChatMemberEvent FindChatObject; + // public static object OnEvent(ChatMemberType type, string username) + // { + // if (FindChatObject != null) + // { + // Delegate[] delArray = FindChatObject.GetInvocationList(); + // foreach (Delegate del in delArray) + // { + // ChatMemberEvent method = (ChatMemberEvent)del; + // return method(type, username); + // } + // } + // return null; + // } + + //public delegate void UpdateChatFriendsEvent(List objs); + //public static event UpdateChatFriendsEvent UpdateChatFriends; + //public static void OnEvent(List objs) + //{ + // if (UpdateChatFriends != null) + // { + // UpdateChatFriends.Invoke(objs); + // } + //} + + //public delegate void UpdateChatGroupMembersEvent(List objs); + //public static event UpdateChatGroupMembersEvent UpdateChatGroupMembers; + //public static void OnEvent(List objs) + //{ + // if (UpdateChatGroupMembers != null) + // { + // UpdateChatGroupMembers.Invoke(objs); + // } + //} + + //} +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXApplyFriend.cs b/类库/Chat.Framework/WXSdk/Events/WXApplyFriend.cs new file mode 100644 index 0000000..3ed5400 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXApplyFriend.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信新人申请加好友事件 + /// + public class WXApplyFriend : WXEvent + { + public override string ToString() + { + if (string.IsNullOrEmpty(OldFriendWxid)) + { + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->验证好友->{NewFriendNick}({NewFriendWxid}),通过[{OldFriendNick}({OldFriendWxid})]的介绍,添加您为好友!验证:{Message}"; + } + else + { + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->验证好友->{NewFriendNick}({NewFriendWxid}),添加您为好友!验证:{Message}"; + } + } + /// + /// 新朋友Id + /// + public string NewFriendWxid { get; private set; } + + private string _newFriendNick; + /// + /// 新朋友昵称 + /// + public string NewFriendNick + { + get { return _newFriendNick; } + private set { _newFriendNick = Util.RemoveEmoji(value); } + } + + private string _Message; + + /// + /// 附加消息 + /// + public string Message + { + get + { + return _Message; + } + private set + { + _Message = Util.RemoveEmoji(value); + } + } + + /// + /// 推荐人wxid 可能为空 + /// + public string OldFriendWxid { get; private set; } + + private string _oldFriendNick; + /// + /// 推荐人昵称 可能为空 + /// + public string OldFriendNick + { + get { return _oldFriendNick; } + private set { _oldFriendNick = Util.RemoveEmoji(value); } + } + + /// + /// 原始信息,自己解析 + /// + public string Token { get; internal set; } + + public WXApplyFriend(WXClientImpl_IPAD client, string NewFriendWxid, string NewFriendNick, string Message, string FriendWxid, string FriendNick, string token) + : base(client) + { + IsToString = true; + this.NewFriendWxid = NewFriendWxid; + this.NewFriendNick = NewFriendNick; + this.Message = Message; + this.OldFriendWxid = FriendWxid; + this.OldFriendNick = FriendNick; + this.Token = token; + } + + public WXApplyFriend(WXClientImpl_HOOK client, string NewFriendWxid, string NewFriendNick, string Message, string FriendWxid, string FriendNick, string token) + : base(client) + { + IsToString = true; + this.NewFriendWxid = NewFriendWxid; + this.NewFriendNick = NewFriendNick; + this.Message = Message; + this.OldFriendWxid = FriendWxid; + this.OldFriendNick = FriendNick; + this.Token = token; + } + + public WXApplyFriend(WXClientImpl_QYHOOK client, string NewFriendWxid, string NewFriendNick, string Message, string FriendWxid, string FriendNick, string token) + : base(client) + { + IsToString = true; + this.NewFriendWxid = NewFriendWxid; + this.NewFriendNick = NewFriendNick; + this.Message = Message; + this.OldFriendWxid = FriendWxid; + this.OldFriendNick = FriendNick; + this.Token = token; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXApplyGroup.cs b/类库/Chat.Framework/WXSdk/Events/WXApplyGroup.cs new file mode 100644 index 0000000..31c7e7a --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXApplyGroup.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 收到微信用户进群申请事件 + /// + public class WXApplyGroup : WXEvent + { + /// + /// 申请入群用户基础信息 + /// + public class ApplyGroupMember + { + /// + /// 新人账号 + /// + public string wxid { get; set; } + /// + /// 新人昵称 + /// + public string nickname { get; set; } + /// + /// 新人头像 + /// + public string headimgurl { get; set; } + + public string quitchatroominfo { get; set; } + } + + public override string ToString() + { + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->入群验证->{Usernick}({Wxid})申请加入[{GroupName}({GroupId})],验证内容:{Reason}"; + } + + public WXApplyGroup(WXClientImpl_IPAD client) : base(client) + { + IsToString = true; + this.GroupName = string.Empty; + this.Members = new List(); + } + + /// + /// 申请进群的用户集合 + /// + public List Members { get; private set; } + + /// + /// 申请入群账号 + /// + public string Wxid { get; internal set; } + //public string Usernick { get; internal set; } + + private string _usernick; + + /// + /// 申请入群昵称 + /// + public string Usernick + { + get { return _usernick; } + internal set { _usernick = Util.RemoveEmoji(value); } + } + + /// + /// 申请理由 + /// + public string Reason { get; internal set; } + + /// + /// 申请群账号 + /// + public string GroupId { get; internal set; } + //public string GroupName { get; internal set; } + + private string _groupName; + + /// + /// 申请群昵称 + /// + public string GroupName + { + get { return _groupName; } + internal set { _groupName = Util.RemoveEmoji(value); } + } + + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXChangeStatus.cs b/类库/Chat.Framework/WXSdk/Events/WXChangeStatus.cs new file mode 100644 index 0000000..4b97b0e --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXChangeStatus.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; +using Chat.Framework.WXSdk.IPAD; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信状态改变事件 + /// + public class WXChangeStatus : WXEvent + { + public override string ToString() + { + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->状态修改->{Status}"; + } + + public WXChangeStatus(WeixinBase client, string message = "") : base(client) + { + IsToString = true; + this.Status = client.Status; + this.Message = message; + } + /// + /// 微信状态 + /// + public WxStatus Status { get; internal set; } + /// + /// 改变附带的内容 + /// + public string Message { get; internal set; } + /// + /// 登录二维码byte[] + /// + public byte[] ImageByte { get; internal set; } + /// + /// 登录二维码 + /// + public Image Image { get { return Image.FromStream(new MemoryStream(ImageByte)); } } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXEvent.cs b/类库/Chat.Framework/WXSdk/Events/WXEvent.cs new file mode 100644 index 0000000..e024303 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXEvent.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信基础事件 + /// + public class WXEvent : ChatEvent + { + /// + /// 微信基类 + /// + public WeixinBase Client { get; private set; } + /// + /// 构造方法 + /// + /// + public WXEvent(WeixinBase client) + { + this.Client = client; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXGetDevice.cs b/类库/Chat.Framework/WXSdk/Events/WXGetDevice.cs new file mode 100644 index 0000000..fb281e6 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXGetDevice.cs @@ -0,0 +1,25 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 设备信息 + /// + public class WXGetDevice : WXEvent + { + /// + /// 微信设备ID + /// + public string DeviceInfo { get; set; } + + public WXGetDevice(WeixinBase client) : base(client) + { + this.DeviceInfo = string.Empty; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXNewFriend.cs b/类库/Chat.Framework/WXSdk/Events/WXNewFriend.cs new file mode 100644 index 0000000..8b990f4 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXNewFriend.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信新增好友事件 + /// + public class WXNewFriend : WXEvent + { + /// + /// 重写ToString方法 + /// + /// + public override string ToString() + { + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->新增好友->{Friend.GetName()}({Friend.UserName})"; + } + /// + /// 新好友信息 + /// + public Friend Friend { get; private set; } + /// + /// 构造方法 + /// + /// + /// + public WXNewFriend(WeixinBase client, Friend Friend) : base(client) + { + IsToString = true; + this.Friend = Friend; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXNewMemer.cs b/类库/Chat.Framework/WXSdk/Events/WXNewMemer.cs new file mode 100644 index 0000000..3b66a0b --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXNewMemer.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信新人进群事件 + /// + public class WXNewMemer : WXEvent + { + public override string ToString() + { + //return $"微信({Client.User.Nick}【{Client.User.Uin}】)->新增群成员->{MemberNicks}({MemberName})加入了{Group.NickName}({Group.UserName})"; + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->群{Group.NickName}({Group.UserName}),新增群成员->{MemberNicks}({MemberName})邀请人{SourceNick}({SourceName})"; + } + /// + /// 群信息 + /// + public Friend Group { get; internal set; } + /// + /// 群账号 + /// + public string GroupId { get; internal set; } + + //public string MemberNicks { get; internal set; } + private string _memberNicks; + /// + /// 新用户昵称 + /// + public string MemberNicks + { + get { return _memberNicks; } + internal set { _memberNicks = Util.RemoveEmoji(value); } + } + + /// + /// 新用户账号 + /// + public string MemberName { get; internal set; } + /// + /// 邀请人账号 + /// + public string SourceName { get; internal set; } + + //public string SourceNick { get; internal set; } + private string _sourceNick; + /// + /// 邀请人昵称 + /// + public string SourceNick + { + get { return _sourceNick; } + internal set { _sourceNick = Util.RemoveEmoji(value); } + } + + + /// + /// 群成员数量 + /// + public int TotalMember { get; internal set; } + + public WXNewMemer(WXClientImpl_IPAD client) : base(client) + { + IsToString = true; + } + + public WXNewMemer(WXClientImpl_HOOK client) : base(client) + { + IsToString = true; + } + + public WXNewMemer(WXClientImpl_QYHOOK client) : base(client) + { + IsToString = true; + } + + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXOpenWindow.cs b/类库/Chat.Framework/WXSdk/Events/WXOpenWindow.cs new file mode 100644 index 0000000..fde3df5 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXOpenWindow.cs @@ -0,0 +1,24 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 协议用户聊天窗口被打开后触发的事件 + /// + public class WXOpenWindow:WXEvent + { + /// + /// 被打开的用户信息 + /// + public Friend Friend { get; private set; } + public WXOpenWindow(WeixinBase client,Friend friend):base(client) + { + this.Friend = friend; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXReceiveGroupMsg.cs b/类库/Chat.Framework/WXSdk/Events/WXReceiveGroupMsg.cs new file mode 100644 index 0000000..41370c8 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXReceiveGroupMsg.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信收到群消息事件 + /// + public class WXReceiveGroupMsg : WXEvent + { + public override string ToString() + { + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->群消息->{Member.NickName}({Member.Username})在[{Group.NickName}({Group.UserName})]群说:{Message}"; + } + /// + /// 用户信息 + /// + public GroupMember Member { get; internal set; } + /// + /// 群信息 + /// + public Friend Group { get; internal set; } + private string _Message; + /// + /// 收到的消息内容 + /// + public string Message + { + get + { + return _Message; + } + private set + { + //_Message = Util.RemoveEmoji(value); + _Message = value; + } + } + + public WXReceiveGroupMsg(WXClientImpl_IPAD client, GroupMember member, Friend Group, string Message) : base(client) + { + IsToString = true; + this.Member = member; + this.Group = Group; + this.Message = Message; + } + + public WXReceiveGroupMsg(WXClientImpl_HOOK client, GroupMember member, Friend Group, string Message) : base(client) + { + IsToString = true; + this.Member = member; + this.Group = Group; + this.Message = Message; + } + + public WXReceiveGroupMsg(WXClientImpl_QYHOOK client, GroupMember member, Friend Group, string Message) : base(client) + { + IsToString = true; + this.Member = member; + this.Group = Group; + this.Message = Message; + } + + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXRefreshContactSuccess.cs b/类库/Chat.Framework/WXSdk/Events/WXRefreshContactSuccess.cs new file mode 100644 index 0000000..471f97f --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXRefreshContactSuccess.cs @@ -0,0 +1,20 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 更新联系人成功 + /// + public class WXRefreshContactSuccess : WXEvent + { + public WXRefreshContactSuccess(WeixinBase client) : base(client) + { + + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXRefreshUser.cs b/类库/Chat.Framework/WXSdk/Events/WXRefreshUser.cs new file mode 100644 index 0000000..541c33d --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXRefreshUser.cs @@ -0,0 +1,18 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信更新信息事件 + /// + public class WXRefreshUser : WXEvent + { + public WXRefreshUser(WeixinBase wxclient) : base(wxclient) + { } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXReiceveFriendMsg.cs b/类库/Chat.Framework/WXSdk/Events/WXReiceveFriendMsg.cs new file mode 100644 index 0000000..de852b1 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXReiceveFriendMsg.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 私聊消息事件 + /// + public class WXReiceveFriendMsg : WXEvent + { + public override string ToString() + { + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->私消息->{Friend.GetName()}({Friend.UserName})说:{Message}"; + } + + public WXReiceveFriendMsg(WXClientImpl_IPAD client, Friend friend, string message) : base(client) + { + IsToString = true; + this.Friend = friend; + this.Message = message; + } + + public WXReiceveFriendMsg(WXClientImpl_HOOK client, Friend friend, string message) : base(client) + { + IsToString = true; + this.Friend = friend; + this.Message = message; + } + public WXReiceveFriendMsg(WXClientImpl_QYHOOK client, Friend friend, string message) : base(client) + { + IsToString = true; + this.Friend = friend; + this.Message = message; + } + /// + /// 发送者信息 + /// + public Friend Friend { get; private set; } + + private string _Message; + + /// + /// 消息 + /// + public string Message + { + get + { + return _Message; + } + private set + { + //_Message = Util.RemoveEmoji(value); + _Message = value; + } + } + + /// + /// 是否为机器人自己的消息true是自己的消息 + /// + public bool IsRobot { get; internal set; } + + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXReicevePay.cs b/类库/Chat.Framework/WXSdk/Events/WXReicevePay.cs new file mode 100644 index 0000000..a916fc0 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXReicevePay.cs @@ -0,0 +1,59 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信收到转账 + /// + public class WXReicevePay : WXEvent + { + /// + /// 转账用户信息 + /// + public Friend Friend { get; private set; } + /// + /// 无效的时间 + /// + public string Invalidtime { get; private set; } + /// + /// 领取时需要的id + /// + public string Transferid { get; private set; } + /// + /// 金额 + /// + public double Money { get; private set; } + public override string ToString() + { + return $"微信({Client.User.Nick}【{Client.User.Uin}】)->待收款->{Friend.GetName()}({Friend.UserName})向您转账了¥{Money}元!"; + } + public WXReicevePay(WXClientImpl_IPAD client, Friend Friend, string Invalidtime, string Transferid, double Money) : base(client) + { + this.Friend = Friend; + this.Invalidtime = Invalidtime; + this.Transferid = Transferid; + this.Money = Money; + } + + public WXReicevePay(WXClientImpl_HOOK client, Friend Friend, string Invalidtime, string Transferid, double Money) : base(client) + { + this.Friend = Friend; + this.Invalidtime = Invalidtime; + this.Transferid = Transferid; + this.Money = Money; + } + + public WXReicevePay(WXClientImpl_QYHOOK client, Friend Friend, string Invalidtime, string Transferid, double Money) : base(client) + { + this.Friend = Friend; + this.Invalidtime = Invalidtime; + this.Transferid = Transferid; + this.Money = Money; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXScavengEvents.cs b/类库/Chat.Framework/WXSdk/Events/WXScavengEvents.cs new file mode 100644 index 0000000..942fca7 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXScavengEvents.cs @@ -0,0 +1,24 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信获取二维码事件 + /// + public class WXScavengEvents:WXEvent + { + /// + /// 二维码状态 + /// + public int Status { get; set; } + public WXScavengEvents(WeixinBase client):base(client) + { + + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXSendMessage.cs b/类库/Chat.Framework/WXSdk/Events/WXSendMessage.cs new file mode 100644 index 0000000..5ed90a9 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXSendMessage.cs @@ -0,0 +1,30 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信消息发送 + /// + public class WXSendMessage: WXEvent + { + /// + /// 消息内容 + /// + public string Message { get;private set; } + /// + /// 接收者账号 + /// + public string ToUsername { get;private set; } + + public WXSendMessage(WeixinBase client,string Message,string ToUsername) : base(client) + { + this.Message = Message; + this.ToUsername = ToUsername; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Events/WXWriteLog.cs b/类库/Chat.Framework/WXSdk/Events/WXWriteLog.cs new file mode 100644 index 0000000..c449ba4 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Events/WXWriteLog.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Events +{ + /// + /// 微信日志事件 + /// + public class WXWriteLog : WXEvent + { + public WXWriteLog(Implement.WeixinBase wxclient) : base(wxclient) + { + + } + /// + /// 是否为debug + /// + public bool IsDebug { get; internal set; } + /// + /// 消息内容 + /// + public string Message { get; internal set; } + } +} diff --git a/类库/Chat.Framework/WXSdk/HOOK/WechatPack.cs b/类库/Chat.Framework/WXSdk/HOOK/WechatPack.cs new file mode 100644 index 0000000..0e778b7 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/HOOK/WechatPack.cs @@ -0,0 +1,125 @@ +using Chat.Framework.PCRobotSDK; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using PCRobot.Pack; +using SuperSocket.SocketBase; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.HOOK +{ + /// + /// 易转发包 + /// + internal class WechatPack + { + WeixinBase client; + + public WechatPack(WeixinBase client) + { + this.client = client; + } + + internal string SendServer(PCRobotCMD cmd, string message = "", WechatMsgType messageType = WechatMsgType.文本, string tousername = "") + { + if (robot != null) + { + string text = string.Empty; + + var msg = new ServerWechatMsg() + { + Cmd = cmd, + RobotType = client.WeixinType == WeixinType.QYHook微信 ? RobotType.客户端企业微信 : RobotType.客户端微信, + RobotUsername = client.WeixinHao, + RobotUsernick = string.Empty, + ToMessage = message, + ToMessageType = messageType, + ToUsername = tousername,//string.IsNullOrWhiteSpace(groupid) ? tousername : groupid, + Key = ChatClient.SocketPassword + }; + //Console.WriteLine(groupid); + var json = HttpHelper.ObjectToJson(msg); + text = PackTool.CompressString(json); + //var t = PackTool.DecompressString(text); + + var need_send = $"{cmd} {text}\r\n"; + var falg = robot.TrySend(need_send); + + LogHelper.GetSingleObj().Debug("", $"往客户端发送消息.: {json},状态=>{falg}"); + return msg.MsgId; + } + return string.Empty; + } + + private ServerWechatMsg NextSendData; + internal void SetNextData(ServerWechatMsg nextData) + { + this.NextSendData = nextData; + } + + internal void SendNextData() + { + try + { + if (robot != null) + { + NextSendData.Key = ChatClient.SocketPassword; + NextSendData.RobotType = client.WeixinType == WeixinType.QYHook微信 ? RobotType.客户端企业微信 : RobotType.客户端微信; + NextSendData.RobotUsername = client.WeixinHao; + NextSendData.RobotUsernick = string.Empty; + + var json = HttpHelper.ObjectToJson(NextSendData); + var text = PackTool.CompressString(json); + var need_send = $"{NextSendData.Cmd} {text}\r\n"; + Thread.Sleep(70); + var flag = robot.TrySend(need_send); + + + LogHelper.GetSingleObj().Debug("", $"往客户端发送消息: {json} @@@ {text},状态=>{flag}"); + //this.SendAll(this.NextSendData.cmd, false, this.NextSendData.data); + } + } + catch (Exception) + { } + } + + #region SupperSocket 1.0 + //private SupperSocketSession _robot; + //public SupperSocketSession robot + //{ + // get + // { + // if (!string.IsNullOrWhiteSpace(client.WeixinHao)) + // { + // var robotData = ChatClient.PCRobotPool.GetSession(client.WeixinHao); + // if (robotData != null) + // _robot = robotData; + // } + // return _robot; + // } + //} + #endregion + + #region SupperSocket 2.0 + private AppSession _robot; + public AppSession robot + { + get + { + if (!string.IsNullOrWhiteSpace(client.WeixinHao)) + { + var robotData = ChatClient.PCRobotPool.GetSession(client.WeixinHao); + if (robotData != null) + _robot = robotData; + } + return _robot; + } + } + #endregion + + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/GrpcClient.cs b/类库/Chat.Framework/WXSdk/IPAD/GrpcClient.cs new file mode 100644 index 0000000..ea35a65 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/GrpcClient.cs @@ -0,0 +1,459 @@ +using Chat.Framework.WXSdk.Implement; +using Grpc.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using WechatProto; +using static WechatProto.Wechat; + +namespace Chat.Framework.WXSdk.IPAD +{ + public enum GrpcType : int + { + Awei = 0, + Laoyao = 1, + Huangfan = 2, + 未知 = -1 + } + internal class GrpcConfig + { + public GrpcType Type { get; set; } + public string Appid { get; set; } + + public string Appkey { get; set; } + + /// + /// 启用SSL加密 + /// + public bool EnableSSL { get; set; } = true; + + /// + /// 服务器全局解密Key + /// + public byte[] RandomEncryKey { get; set; } + + + ///// + ///// 服务端地址 + ///// + //public string GrpcServer { get; set; } + + ///// + ///// 备用服务器地址 + ///// + //public string GrpcServerBackup { get; set; } + + /// + /// 版本号 + /// + public string Version { get; set; } + + /// + /// Grpc证书 + /// + public string GrpcCredentials { get; set; } + + /// + /// 机器人码 + /// + public string MachineCode { get; set; } + + + private Metadata _authHeader; + /// + /// Grpc验证头 + /// + public Metadata AuthHeader + { + get + { + if (_authHeader == null) + { + _authHeader = new Metadata(); + _authHeader.Add("appid", Appid); + _authHeader.Add("appkey", Appkey); + } + return _authHeader; + } + } + + /// + /// 服务器IP + /// + public List Servers { get; set; } + + + + private static Dictionary grpcConfig = new Dictionary(); + public static GrpcConfig Get(GrpcType type, bool refresh = false) + { + //if (type == GrpcType.Huangfan) + //{ + //} + ////type = GrpcType.Laoyao;//TODO 这里强制用老妖的 + + lock (grpcConfig) + { + GrpcConfig config = grpcConfig.ContainsKey(type) ? grpcConfig[type] : null; + if (config != null && !refresh) return config; + switch (type) + { + case GrpcType.Awei: + config = new GrpcConfig() + { + + Appid = "v1_meesii_CodeVip", + Appkey = "v2_d6fb34d020a209471fe7122d4a55e69c", + Servers = new List() { "grpc.wxipad.com:12580" }, + MachineCode = "v3_e9de924f32fae3126b42fac40b0f5b6d", + RandomEncryKey = CsharpHttpHelper.HttpExtend.RandomByte(16), + EnableSSL = true, + GrpcCredentials = @"-----BEGIN CERTIFICATE----- +MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV +BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw +CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW +Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC +Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV +BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG +eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB +F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD +mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY +ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 +lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd +AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME +GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q +DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc +sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl +bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG +DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf +x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs +-----END CERTIFICATE-----", + Version = "7.0.3" + }; + break; + case GrpcType.Laoyao: + config = new GrpcConfig() + { + Appid = "v1_LCEO_Code", + Appkey = "v2_4d5d55d6fbb6ce87b0f53019fefebb89", + Servers = new List() { "111.230.216.32:12588" }, + MachineCode = "v3_7af2592d5c49d94424bac95e80cb07a4", + RandomEncryKey = CsharpHttpHelper.HttpExtend.RandomByte(16), + EnableSSL = true, + GrpcCredentials = @"-----BEGIN CERTIFICATE----- +MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV +BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw +CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW +Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC +Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV +BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG +eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB +F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD +mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY +ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 +lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd +AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME +GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q +DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc +sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl +bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG +DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf +x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs +-----END CERTIFICATE-----", + Version = "7.0.3" + }; + //Console.WriteLine(config.AuthHeader); + break; + case GrpcType.Huangfan: + config = new GrpcConfig() + { + Appid = "v1_23229f55b208d33b_CodeVip", + Appkey = "v2_d72d0b8d148afb50e8a0beed37efd1b5", + Servers = new List() { "47.93.227.173:12580" }, + MachineCode = "v3_951b8b394d904962d981f02e5d4cee31", + RandomEncryKey = CsharpHttpHelper.HttpExtend.RandomByte(16), + GrpcCredentials = @"-----BEGIN CERTIFICATE----- +MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV +BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw +CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW +Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC +Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV +BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG +eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB +F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD +mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY +ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 +lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd +AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME +GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q +DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc +sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl +bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG +DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf +x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs +-----END CERTIFICATE-----", + Version = "7.0.3" + }; + Console.WriteLine(config.AuthHeader); + break; + default: + break; + } + if (config != null) + { + config.Type = type; + grpcConfig[type] = config; + } + + return config; + } + } + + } + class GrpcClient : IDisposable + { + private Channel _channel; + private WechatClient _baseClient; + + /// + /// GRpc配置信息 + /// + public GrpcConfig Config { get; private set; } + + public GrpcClient(GrpcConfig config = null) + { + if (config != null) + { + Config = config; + } + Init(); + } + + public bool IsConnected + { + get + { + if (_channel != null && (_channel.State == ChannelState.Ready || _channel.State == ChannelState.Connecting || _channel.State == ChannelState.Idle)) + { + return true; + } + return false; + } + } + + /// + /// 初始化 + /// + public void Init() + { + if (Config.Servers.Count == 0) + { + LogHelper.GetSingleObj().Error("Grpc服务器", "当前无可用的Grpc服务器"); + return; + } + this.Stop(); + + Config.Servers = ChatClient.GetServerDataMethod("grpc_type_" + Config.Type.ToString().ToLower()).Split(',').ToList(); + //if (Config.Type == GrpcType.Huangfan) Config.Servers = new string[] { "106.15.26.141:12580" }.ToList(); + // Config.Servers = new string[] { "45.253.67.81:12580" }.ToList(); + //switch (Config.Type) + //{ + // case GrpcType.Awei: + + // break; + // case GrpcType.Laoyao: + // break; + // case GrpcType.Huangfan: + // break; + // default: + // break; + //} + + var channelOptions = new List + { + new ChannelOption(ChannelOptions.SslTargetNameOverride,"wechat@root"), + new ChannelOption(ChannelOptions.MaxConcurrentStreams,int.MaxValue), + new ChannelOption(ChannelOptions.MaxSendMessageLength,int.MaxValue), + new ChannelOption(ChannelOptions.MaxReceiveMessageLength,int.MaxValue) + }; + + if (Config.EnableSSL) + { + var grpcCredentials = new SslCredentials(Config.GrpcCredentials); + _channel = new Channel(ServerIp, grpcCredentials, channelOptions); + } + else + _channel = new Channel(ServerIp, ChannelCredentials.Insecure, channelOptions); + + _baseClient = new WechatClient(_channel); + } + + /// + /// 停止GRpc + /// + public void Stop() + { + if (_channel != null) + { + try + { + _channel.ShutdownAsync().Wait(); + _baseClient = null; + _channel = null; + } + catch + { + // ignored + } + + } + + } + public DateTime LastTime { get; private set; } + + + /// + /// Grpc发包(5次尝试) + /// + /// + /// + public Task Send(WechatMsg _pack, WXClientImpl_IPAD weixin) + { + + #region 2019年8月1日21:49:42 + ////while (_baseClient == null) + ////{ + //// Thread.Sleep(100); + ////} + + //return Task.Run(() => + //{ + // var tryTimes = 3; + + //again: + // var cmd = 0; + // try + // { + // if (this._channel == null) this.Init(); + // LastTime = DateTime.Now; + // cmd = pack.BaseMsg.Cmd; + // var send = pack.Clone(); + // send.Token = Config.MachineCode; + // //return _baseClient.HelloWechat(send, Config.AuthHeader, DateTime.UtcNow.AddSeconds(10)); + // return _baseClient.HelloWechatAsync(send, Config.AuthHeader, DateTime.UtcNow.AddSeconds(10)).ResponseAsync.Result; + // } + // catch (RpcException ex) + // { + // if (tryTimes >= 0) + // { + // tryTimes--; + // Thread.Sleep(1000); + // if (ex.StatusCode == StatusCode.Unknown || ex.StatusCode == StatusCode.DeadlineExceeded) + // { + // this.Init(); + // goto again; + // } + // else if (ex.StatusCode == StatusCode.Unavailable) goto again; + // } + // LogHelper.GetSingleObj().Error("Grpc异常" + cmd, $"StatusCode ->{ex.StatusCode} Msg ->{ex.Message}"); + + // return null; + // } + + //}); + #endregion + + #region + + //while (_baseClient == null) + //{ + // Thread.Sleep(100); + //} + WechatMsg pack = _pack; + return Task.Run(() => + { + var tryTimes = 3; + for (int i = 0; i < tryTimes; i++) + { + if (i > 0) Thread.Sleep(1000); + var cmd = 0; + try + { + if (this._channel == null || _baseClient == null) + this.Init(); + LastTime = DateTime.Now; + cmd = pack.BaseMsg.Cmd; + var send = pack.Clone(); + send.Token = Config.MachineCode; + //return _baseClient.HelloWechat(send, Config.AuthHeader, DateTime.UtcNow.AddSeconds(10)); + return _baseClient.HelloWechatAsync(send, Config.AuthHeader, DateTime.UtcNow.AddSeconds(10)).ResponseAsync.Result; + } + + catch (RpcException ex) + { + + LogHelper.GetSingleObj().Error("Grpc异常" + cmd, $"StatusCode ->{ex.StatusCode} Msg ->{ex.Message}"); + if (ex.StatusCode == StatusCode.Unavailable) continue; + else if (ex.StatusCode == StatusCode.Unknown || ex.StatusCode == StatusCode.DeadlineExceeded) + { + this.Init(); + continue; + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("Grpc异常" + cmd, $"Msg ->{ex.InnerException}"); + continue; + } + } + return null; + }); + #endregion + } + + public void Dispose() + { + + } + + /// + /// 上次获取时间 + /// + private readonly DateTime _checkDate = DateTime.Now; + + /// + /// Grpc服务器IP + /// + private string _serverIp; + + /// + /// Grpc服务器IP + /// + public string ServerIp + { + get + { + //return "grpc.wxipad.com:12580"; + + //if (string.IsNullOrEmpty(ServerIp) || (DateTime.Now - _checkDate).TotalSeconds >= 300) + //{ + // GetConfig(); + //} + + var random = new Random(); + var index = random.Next(0, Config.Servers.Count); + _serverIp = Config.Servers[index]; + return _serverIp; + } + } + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/ISocket.cs b/类库/Chat.Framework/WXSdk/IPAD/ISocket.cs new file mode 100644 index 0000000..20d446d --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/ISocket.cs @@ -0,0 +1,209 @@ +using Sodao.FastSocket.Client; +using Sodao.FastSocket.Client.Messaging; +using Sodao.FastSocket.Client.Protocol; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Implement; +using Sodao.FastSocket.SocketBase; +using Chat.Framework.WXSdk.Events; + +namespace Chat.Framework.WXSdk.IPAD +{ + interface ISocket + { + + FastSocketStatus Status { get; set; } + + + bool Connection(List host, int port); + bool Connection(string host, int port); + void Stop(); + } + public enum FastSocketStatus + { + 未连接 = 1, + 连接中 = 2, + 已连接 = 3, + 已断开 = 4 + } + internal class FastSocket : ISocket,IDisposable + { + public FastSocket(WXClientImpl_IPAD client) { + this.client = client; + } + WXClientImpl_IPAD client { get; set; } + public FastSocketStatus Status { get; set; } + public SocketClient WeChatClient { get; set; } + public void Stop() + { + try + { + Status = FastSocketStatus.未连接; + if (WeChatClient != null) + { + WeChatClient.ReceivedNotifyMessage -= WeChatClient_ReceivedNotifyMessage; + WeChatClient.ReceivedUnknowMessage -= WeChatClient_ReceivedUnknowMessage; + this.WeChatClient.UnRegisterEndPoint("WeChat"); + this.WeChatClient.Stop(); + this.WeChatClient = null; + } + } + catch { } + } + + public bool Connection(List host, int port) + { + try + { + this.Stop(); + //先不改了 - -5s + WeChatClient = new SocketClient(new WeChatProtocol(), 1024, 1024, 60000, 60000); + WeChatClient.ReceivedNotifyMessage += WeChatClient_ReceivedNotifyMessage; + + WeChatClient.ReceivedUnknowMessage += WeChatClient_ReceivedUnknowMessage; + //绑定Unknow 未知包 异常包 事件 + + + List IPEnds = new List(); + foreach (string item in host) + { + var ip = Dns.GetHostAddresses(item); + IPEnds.Add(new IPEndPoint(ip[0], port)); + } + return WeChatClient.TryRegisterEndPoint("WeChat", IPEnds.ToArray(), + connection => + { + var source = new TaskCompletionSource(); + connection.Disconnected += Connection_Disconnected;//如果触发这个事件呢 你好像吧原有的事件叠加了 - - + //在这里绑定 + //此包保持长链接 若链接成功后不发包 则会断开 底层socket 已处理了重连机制 + Request request = null; + if (client.Status!= WxStatus.在线 || true)//全局登录成功的标志位有么 //meijinzheli 不要改 这里是断线重连才会触发的 连接首次连接也会触发 + { + request = WeChatClient.NewRequest("noping", Util.StrToHex("00 00 00 10 00 10 00 01 00 00 00 01 00 00 00 01"), 10000, + //绑定异常回调 + ex => + { //IsAsync=false时 接收超时也会触发断开链接并且重连IsAsync=ture 不会断开重连 超时?由于计算引起的? + //超时会自动废弃包 + Console.WriteLine("连接失败:" + ex); + source.TrySetException(ex); + //Connection_Disconnected(connection,ex); + source.TrySetResult(false); + + }, + + //绑定返回请求的回调 + onResultMessage => + { + Console.WriteLine("long.weixin.qq.com Connect success!"); + //触发此回调说明已经从底层的_receivingQueue 队列中移除了 + + //byte[] buff = onResultMessage.Msg.BaseMsg.Payloads.ToByteArray(); + this.Status = FastSocketStatus.已连接; + source.TrySetResult(true); + }); + connection.BeginSend(request); + var task = source.Task; + + return task; + } + else + { + //这里还没改呢 - - + //绑定SYNC同步消息的包 你改一下,表示没看懂,你让我怎么改~ 告诉sync同步消息的包在?我知道了 - - + source.SetResult(true); + client.AsyncSyncMessage(); + return source.Task; + } + }); + } + catch (Exception ex) + { + Console.WriteLine("异常:" + ex.Message); + } + return false; + } + + private void WeChatClient_ReceivedUnknowMessage(IConnection i, WeChatMessage message) + { + try + { + int Ret = Sodao.FastSocket.SocketBase.Utils.NetworkBitConverter.ToInt32(message.Msg.BaseMsg.Payloads.ToByteArray(), 18); + Console.WriteLine("ReceivedUnknowMessage CMD" + message.CmdID + " 异常返回Ret:" + Ret); + if (Ret == -13 && client.Status == WxStatus.在线) + { + client.ResetConnection(); + } + } + catch { } + } + + private void WeChatClient_ReceivedNotifyMessage(IConnection i, WeChatMessage message) + { + try + { + switch (message.CmdID) + { + case 24: + client.AsyncSyncMessage(); + break; + case 318: + var data = message.Msg.BaseMsg.Payloads.ToByteArray(); //这个DATa就是一个完整的包 + client.DecodeSecureNotifyThread(data); + break; + default: + Console.WriteLine("ReceivedNotifyMessage 未知 CMD:" + message.CmdID); + //client.WriteLog("ReceivedNotifyMessage 未知 CMD" + message.CmdID,true); + break; + + } + } + catch { } + } + + private void Connection_Disconnected(IConnection connection, Exception ex) + { + Console.WriteLine("当前状态:"+Status); + if (connection != null && Status == FastSocketStatus.已连接 ) + { + + Status = FastSocketStatus.已断开; + if (client.Status == WxStatus.在线) + { + client.ResetConnection(); + } + //else + //{ + // client.connection_grpc(); + //} + + } + } + + public bool Connection(string host, int port) + { + var list = new List(); + list.Add(host); + return Connection(list, port); + } + + + + public void Send(Request request) + { + WeChatClient.Send(request); + } + + public void Dispose() + { + + } + + + + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/PayType.cs b/类库/Chat.Framework/WXSdk/IPAD/PayType.cs new file mode 100644 index 0000000..0473a94 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/PayType.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.IPAD +{ + /// + /// 红包来源类型 + /// + public enum PayType:ushort + { + 红包 = 1, + 转账 = 2 + } + + /// + /// 申请订单状态 + /// + public enum ApplyType + { + 未审核 = 1, + 已审核 = 2, + 退回兑换 = 3, + 没收兑换 = 4 + } + + public enum CDNType : ushort + { + 发送图片 = 1, + 发送视频 = 2 + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/Push.cs b/类库/Chat.Framework/WXSdk/IPAD/Push.cs new file mode 100644 index 0000000..e79a5de --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/Push.cs @@ -0,0 +1,241 @@ + +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using socket.core.Client; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.IPAD +{ + public class Push + { + private TcpPushClient client; + Random random = new Random(); + DnsEndPoint hostEndPoint; + public Push(DnsEndPoint hostEndPoint, WeixinBase weixin) + { + this.weixin = weixin; + client = new TcpPushClient(0x20000); + client.OnConnect += Client_OnConnect; + client.OnReceive += Client_OnReceive; + client.OnSend += Client_OnSend; + client.OnClose += Client_OnClose; + this.hostEndPoint = hostEndPoint; + } + public bool Connect() + { + client.Connect(hostEndPoint.Host, hostEndPoint.Port); + return client.Connected; + } + public void ClearPack() + { + lock (mPackDic) + { + var vas = mPackDic.ToList().Where(f => f.Value.Time < DateTime.Now.AddMinutes(-5)); + foreach (var item in vas) + { + mPackDic.Remove(item.Key); + } + } + } + private void Client_OnClose() + { + Console.WriteLine($"Push断开"); + } + + private void Client_OnReceive(byte[] obj) + { + //Console.WriteLine($"Push接收长度[{obj.Length}] {random.Next(1, 9999)}"); + DePack(obj); + } + + /// + /// 通过seq取微信服务器返回的socket包数据 + /// + /// + /// + public byte[] GetBuffBySeq(int Seq) + { + + lock (mPackDicLock) + { + //Thread.Sleep(10); + byte[] buf = null; + try + { + if (mPackDic.ContainsKey(Seq)) + { + buf = mPackDic[Seq].Data; + mPackDic.Remove(Seq); + return buf; + } + } + catch (Exception ee) + { + LogHelper.GetSingleObj().Error("Wechat GetBuffBySeq", $"{weixin.WeixinHao}- 获取超时!{ee.Message}"); + } + return buf; + } + } + + private void Client_OnConnect(bool obj) + { + // Console.WriteLine($"Push连接{obj}"); + } + public bool connected + { + get + { + return client == null ? false : client.Connected; + } + } + private void Client_OnSend(int obj) + { + // LogHelper.GetSingleObj().Info("发送成功"); + } + public void AsynSend(byte[] data,string text="") + { + //Console.WriteLine("1111111111"); + client.Send(data, 0, data.Length,text); + + } + public void AsynSend(byte[] data, int offset, int length) + { + client.Send(data, offset, length); + } + + public void Disconnect() + { + client.Close(); + + } + private object mPackDicLock = new object(); + private byte[] packageData = null; + public bool DePack(byte[] bys) + { + + bool result = false; + int x = bys.Length; + + if (packageData != null) + { + byte[] temp = new byte[packageData.Length + x]; + Buffer.BlockCopy(packageData, 0, temp, 0, packageData.Length); + Buffer.BlockCopy(bys, 0, temp, packageData.Length, x); + packageData = temp; + } + else + { + packageData = new byte[x]; + Buffer.BlockCopy(bys, 0, packageData, 0, x); + } + + while (packageData != null && packageData.Length > 16) + { + int newPackageLength = WXClientTool.ReadInt(packageData, 0); + if (newPackageLength <= 0 || newPackageLength > 8000000) + { + LogHelper.GetSingleObj().Error("Wechat DePack", "长度不合法"); + packageData = null; + } + else if (newPackageLength <= packageData.Length) + { + byte[] newPackage = new byte[newPackageLength]; + Buffer.BlockCopy(packageData, 0, newPackage, 0, newPackageLength); + if (newPackageLength < packageData.Length) + { + byte[] temData = new byte[packageData.Length - newPackageLength]; + Buffer.BlockCopy(packageData, newPackageLength, temData, 0, packageData.Length - newPackageLength); + packageData = temData; + } + else + { + packageData = null; + } + HandlePackage(newPackage); + } + else + { + break; + } + } + return result; + + } + + //解析包 + public void HandlePackage(byte[] bys) + { + if (bys.Length == 20 && bys[3] == 20 && bys[5] == 16 && bys[7] == 1) + { + // 有新消息就会接受到此包 + SaveBufferToPackDic(bys); + return; + } + else + { + if (bys.Length >= 16 && bys[16] != (byte)191 + && !(bys[3] == 58 && bys[5] == 16 && bys[7] == 1 && bys.Length == 58) + && !(bys[3] == 47 && bys[5] == 16 && bys[7] == 1 && bys.Length == 47)) + { + return; + } + SaveBufferToPackDic(bys); + } + } + class SocketResult + { + public DateTime Time { get; set; } + public byte[] Data { get; set; } + } + Dictionary mPackDic = new Dictionary(); + public WeixinBase weixin; + public Func NotifyCallback { get; set; } + // int Seq = 0; + //保存数据到mPackDic + public void SaveBufferToPackDic(byte[] bys) + { + lock (mPackDicLock) + { + var Seq = WXClientTool.ReadInt(bys, 12); + if (Seq == 0) + { + byte[] buffers = new byte[bys.Length]; + Buffer.BlockCopy(bys, 0, buffers, 0, bys.Length); + + int cmd = WXClientTool.ReadInt(buffers, 8); + int selector = WXClientTool.ReadInt(buffers, 16); + LogHelper.GetSingleObj().Info("Wechat SaveBufferToPackDic", $"{weixin.WeixinHao}-收到{buffers.Length}字节!"); + if (cmd == 318 && NotifyCallback != null) + { + NotifyCallback(buffers); + } + + if (cmd == 24 && NotifyCallback != null) + { + NotifyCallback(buffers); + } + + if (cmd != 24 && cmd != 318) + { + } + } + else + { + byte[] buffers = new byte[bys.Length]; + Buffer.BlockCopy(bys, 0, buffers, 0, bys.Length); + mPackDic[Seq] = new SocketResult() { Data = buffers, Time = DateTime.Now }; + Seq = 0; + } + + } + + } + + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/SocketClient.cs b/类库/Chat.Framework/WXSdk/IPAD/SocketClient.cs new file mode 100644 index 0000000..32a8d47 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/SocketClient.cs @@ -0,0 +1,453 @@ + +using Chat.Framework; +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.IPAD +{ + /// + /// Socket管理 + /// + public sealed class SocketClient + { + class SocketResult + { + public DateTime Time { get; set; } + public byte[] Data { get; set; } + } + public WeixinBase weixin; + + public enum WXSocketClientError + { + connetedErr = 0,//连接错误 + sendErr = 1,//发送错误 + receiveErr = 2,//接受错误 + }; + + internal Socket clientSocket; + internal DnsEndPoint hostEndPoint { get; set; } + public bool connected + { + get + { + if (this.clientSocket != null) return this.clientSocket.Connected; + return false; + } + } + Dictionary mPackDic = new Dictionary(); + private object mPackDicLock = new object(); + public Func NotifyCallback { get; set; } + int Seq = 0; + + private byte[] packageData = null; + + public void ClearPack() + { + lock (mPackDic) + { + var vas = mPackDic.ToList().Where(f => f.Value.Time < DateTime.Now.AddMinutes(-5)); + foreach (var item in vas) + { + mPackDic.Remove(item.Key); + } + } + } + + + public Func SocketExceptionCallback { get; set; } + + + public ManualResetEvent allDone = new ManualResetEvent(false); + public SocketClient(DnsEndPoint hostEndPoint, WeixinBase weixin) + { + this.weixin = weixin; + this.hostEndPoint = hostEndPoint; + CreateSocket(); + } + + //创建socket + public bool CreateSocket() + { + clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + clientSocket.SendTimeout = 10000; + SetXinTiao(); + return true; + } + + private object lock_login = new object(); + + public void BeginConnection() + { + try + { + this.allDone = new ManualResetEvent(false); + if (null == clientSocket) + { + CreateSocket(); + } + + //开始连接到服务器 + clientSocket.BeginConnect(hostEndPoint, delegate + { + try + { + AsynRecive(); + if (weixin.Status == Chat.Framework.WXSdk.WxStatus.在线) + { + //var client = (this.weixin as WXClientImpl_IPAD); + //client.AsyncSyncMessage(); + // if (!client.AsyncSyncMessage()) this.weixin.ResetConnection(); + } + } + catch (Exception) + { } + }, null); + + Thread.Sleep(200); + + // wait here until the connect finishes. The callback sets allDone. + //阻塞直到connected=true + //allDone.WaitOne(1000 * 5); + + // Log("连接 WeChat 成功!"); + LogHelper.GetSingleObj().Info("Wechat Connect", $"{weixin.WeixinHao}-{hostEndPoint}-连接成功!!!!"); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("Wechat Connect", $"{weixin.WeixinHao}-{hostEndPoint}-连接失败!{ex.Message}"); + // Log("连接 WeChat 失败!" + ex.Message); + //Log(new LogInfo(jobinfo.JobID, "调试", "创建wx服务器连接失败,详情:" + ex.Message + Environment.NewLine + ex.StackTrace, 3)); + //Log(new LogInfo(jobinfo.JobID, "错误", "创建wx服务器连接异常", 1)); + + } + } + //异步连接 + public bool Connect() + { + lock (lock_login) + { + this.Disconnect(); + BeginConnection(); + Thread.Sleep(1000); + } + + return connected; + } + + //断开socket + public void Disconnect() + { + + try + { + if (clientSocket != null && clientSocket.Connected) + { + LogHelper.GetSingleObj().Info("Wechat Disconnect", $"{weixin.WeixinHao}-{hostEndPoint}-关闭"); + } + clientSocket.Shutdown(SocketShutdown.Both); + clientSocket.Disconnect(true); + clientSocket.Close(); + clientSocket.Dispose(); + clientSocket = null; + allDone.Dispose(); + + } + catch (Exception) + { } + } + + + + ///// 设置socket心跳 + private void SetXinTiao() + { + //byte[] inValue = new byte[] { 1, 0, 0, 0, 0x20, 0x4e, 0, 0, 0xd0, 0x07, 0, 0 };// 首次探测时间20 秒, 间隔侦测时间2 秒 + byte[] inValue = new byte[] { 1, 0, 0, 0, 0x88, 0x13, 0, 0, 0xd0, 0x07, 0, 0 };// 首次探测时间5 秒, 间隔侦测时间2 秒 + clientSocket.IOControl(IOControlCode.KeepAliveValues, inValue, null); + } + + /// + /// 发送vx socket消息 + /// + /// + /// + public void AsynSend(byte[] _SendBuff) + { + try + { + int times = 0; + while (!connected && times < 5) + { + // Log(new LogInfo(jobinfo.JobID, "调试", , 3)); + // LogHelper.GetSingleObj().Error("Wechat AsynSend", $"{weixin.WeixinHao}-{hostEndPoint}- 等待连接!"); + Thread.Sleep(2000); + times++; + } + if (!connected) + { + + LogHelper.GetSingleObj().Error("Wechat AsynSend", $"{weixin.WeixinHao}-{hostEndPoint}- 等待连接!"); + if (null != SocketExceptionCallback) + { + SocketExceptionCallback(WXSocketClientError.connetedErr,this); + } + return; + //Log("wx服务器连接失败,请尝试重启工号"); + // this.Connect(); + } + + byte[] SendBuff = _SendBuff; + var temp = Encoding.UTF8.GetString(SendBuff); + clientSocket.BeginSend(SendBuff, 0, SendBuff.Length, SocketFlags.None, asyncResult => + { + try + { + //完成发送消息 + int length = clientSocket.EndSend(asyncResult); + + LogHelper.GetSingleObj().Info("Wechat AsynSend", $"{weixin.WeixinHao}-{hostEndPoint}-已发送{length}字节!"); + } + catch (Exception) + { } + }, null); + } + catch (Exception ex) + { + //Log ("wx服务器接收数据异常,详情:" + ex.Message + Environment.NewLine + ex.StackTrace) ; + LogHelper.GetSingleObj().Error("Wechat AsynSend", $"{weixin.WeixinHao}-{hostEndPoint}- 发送失败!{ex.Message}"); + //微信socket异常问题 + if (null != SocketExceptionCallback) + { + if (ex.Message.Contains("主机中的软件中止了一个已建立的连接。")) + SocketExceptionCallback(WXSocketClientError.connetedErr,this); + else SocketExceptionCallback(WXSocketClientError.sendErr,this); + } + } + } + + /// + /// 通过seq取微信服务器返回的socket包数据 + /// + /// + /// + public byte[] GetBuffBySeq(int Seq) + { + lock (mPackDicLock) + { + //Thread.Sleep(10); + byte[] buf = null; + try + { + if (mPackDic.ContainsKey(Seq)) + { + buf = mPackDic[Seq].Data; + mPackDic.Remove(Seq); + return buf; + } + } + catch (Exception ee) + { + LogHelper.GetSingleObj().Error("Wechat GetBuffBySeq", $"{weixin.WeixinHao}-{hostEndPoint}- 获取超时!{ee.Message}"); + } + return buf; + } + } + /// + /// 接收微信socket返回的数据 + /// + /// + private void AsynRecive() + { + Thread.Sleep(50); + + if (connected == false || clientSocket == null) + return; + + //byte[] data = new byte[0x20000]; + byte[] data = new byte[150000]; + + try + { + //开始接收数据 + clientSocket.BeginReceive(data, 0, data.Length, SocketFlags.None, + asyncResult => + { + if (connected == false || clientSocket == null) + { + return; + } + try + { + //本次接收的数据长度 + int nowReceiveLenth = clientSocket.EndReceive(asyncResult); + + //建立起连接后 若长时间不发送数据 wx会立马关闭socket + if (nowReceiveLenth == 0) + { + //vx socket 服务端关闭了连接,需要重连socket + //if (clientSocket.Connected)//上次socket的状态 + //{ + //Log("wxsocket服务端关闭了连接,将尝试新建连接"); + //微信socket异常问题 + if (null != SocketExceptionCallback) + { + SocketExceptionCallback(WXSocketClientError.receiveErr,this); + } + //} + return; + } + byte[] new_data = new byte[nowReceiveLenth]; + Buffer.BlockCopy(data, 0, new_data, 0, nowReceiveLenth); + LogHelper.GetSingleObj().Info("Wechat AsynRecive", $"{weixin.WeixinHao}-{hostEndPoint}-{data.Length}"); + DePack(new_data); + AsynRecive(); + } + catch (Exception ex) + { + //LogHelper.GetSingleObj().Error("Wechat AsynRecive1", ex.Message); + LogHelper.GetSingleObj().Error("Wechat AsynRecive1", $"{weixin.WeixinHao}-{hostEndPoint}- { ex.Message}"); + // Log("解析wx数据异常,详情:" + ee.Message + Environment.NewLine + ee.StackTrace); + // Log(new LogInfo(jobinfo.JobID, "调试", "wxsocket服务端关闭了连接,将尝试新建连接", 3)); + //微信socket异常问题 + if (null != SocketExceptionCallback) + { + SocketExceptionCallback(WXSocketClientError.receiveErr,this); + } + } + }, null); + } + catch (Exception ex) + { + // Log("连接被wx服务器关闭,接收数据失败。异常详情:" + ex.Message + Environment.NewLine + ex.StackTrace); + // LogHelper.GetSingleObj().Error("Wechat AsynRecive2", ex.Message); + LogHelper.GetSingleObj().Error("Wechat AsynRecive2", $"{weixin.WeixinHao}-{hostEndPoint}- { ex.Message}"); + //微信socket异常问题 + if (null != SocketExceptionCallback) SocketExceptionCallback(WXSocketClientError.receiveErr,this); + } + //finally + //{ + + //} + } + + //分包 + public bool DePack(byte[] bys) + { + bool result = false; + int x = bys.Length; + + if (packageData != null) + { + byte[] temp = new byte[packageData.Length + x]; + Buffer.BlockCopy(packageData, 0, temp, 0, packageData.Length); + Buffer.BlockCopy(bys, 0, temp, packageData.Length, x); + packageData = temp; + } + else + { + packageData = new byte[x]; + Buffer.BlockCopy(bys, 0, packageData, 0, x); + } + + while (packageData != null && packageData.Length > 16) + { + int newPackageLength = WXClientTool.ReadInt(packageData, 0); + if (newPackageLength <= 0 || newPackageLength > 8000000) + { + LogHelper.GetSingleObj().Error("Wechat DePack", "长度不合法"); + packageData = null; + } + else if (newPackageLength <= packageData.Length) + { + byte[] newPackage = new byte[newPackageLength]; + Buffer.BlockCopy(packageData, 0, newPackage, 0, newPackageLength); + if (newPackageLength < packageData.Length) + { + byte[] temData = new byte[packageData.Length - newPackageLength]; + Buffer.BlockCopy(packageData, newPackageLength, temData, 0, packageData.Length - newPackageLength); + packageData = temData; + } + else + { + packageData = null; + } + HandlePackage(newPackage); + } + else + { + break; + } + } + return result; + } + + //解析包 + public void HandlePackage(byte[] bys) + { + if (bys.Length == 20 && bys[3] == 20 && bys[5] == 16 && bys[7] == 1) + { + // 有新消息就会接受到此包 + SaveBufferToPackDic(bys); + return; + } + else + { + if (bys.Length >= 16 && bys[16] != (byte)191 + && !(bys[3] == 58 && bys[5] == 16 && bys[7] == 1 && bys.Length == 58) + && !(bys[3] == 47 && bys[5] == 16 && bys[7] == 1 && bys.Length == 47)) + { + return; + } + SaveBufferToPackDic(bys); + } + } + + + //保存数据到mPackDic + public void SaveBufferToPackDic(byte[] bys) + { + lock (mPackDicLock) + { + Seq = WXClientTool.ReadInt(bys, 12); + if (Seq == 0) + { + byte[] buffers = new byte[bys.Length]; + Buffer.BlockCopy(bys, 0, buffers, 0, bys.Length); + + int cmd = WXClientTool.ReadInt(buffers, 8); + int selector = WXClientTool.ReadInt(buffers, 16); + LogHelper.GetSingleObj().Info("Wechat SaveBufferToPackDic", $"{weixin.WeixinHao}-{hostEndPoint}-收到{buffers.Length}字节!"); + if (cmd == 318 && NotifyCallback != null) + { + NotifyCallback(buffers); + } + + if (cmd == 24 && NotifyCallback != null) + { + NotifyCallback(buffers); + } + + if (cmd != 24 && cmd != 318) + { + } + } + else + { + byte[] buffers = new byte[bys.Length]; + Buffer.BlockCopy(bys, 0, buffers, 0, bys.Length); + mPackDic[Seq] = new SocketResult() { Data = buffers, Time = DateTime.Now }; + Seq = 0; + } + } + } + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/SocketTest.cs b/类库/Chat.Framework/WXSdk/IPAD/SocketTest.cs new file mode 100644 index 0000000..b23e04c --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/SocketTest.cs @@ -0,0 +1,337 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using SuperSocket.ClientEngine; +using SuperSocket.ProtoBase; + +namespace Chat.Framework.WXSdk.IPAD +{ + public class SocketTest + { + + DnsEndPoint hostEndPoint; + public SocketTest(DnsEndPoint hostEndPoint, WXClientImpl_IPAD weixin) + { + this.weixin = weixin; + this.hostEndPoint = hostEndPoint; + + + } + public bool connected + { + get + { + return Client != null ? Client.IsConnected : false; + } + } + private EasyClient Client; + public bool Connect() + { + this.Disconnect(); + + Client = new EasyClient(); + Client.Initialize(new ProtobufReceiveFilter(), (request) => { + Client_OnReceive(request.buffer); + }); + Client.Error += Client_Error; + Client.Closed += Client_Closed; + var _connected = Client.ConnectAsync(this.hostEndPoint); + return _connected.Result; + + } + + private void Client_Closed(object sender, EventArgs e) + { + LogHelper.GetSingleObj().Error("Socket_Error", $"{weixin.WeixinHao}-Socket Close"); + } + + private void Client_Error(object sender, ErrorEventArgs e) + { + try + { + + LogHelper.GetSingleObj().Error("Socket_Error", $"{weixin.WeixinHao}-Socket Error"); + if (this.weixin.Status == WxStatus.在线) + { + if (this.Connect()) + { + this.weixin.AsyncSyncMessage(); + } + + } + } + catch (Exception) + { + } + + } + + private void Client_OnReceive(byte[] obj) + { + //Console.WriteLine($"Push接收长度[{obj.Length}] {random.Next(1, 9999)}"); + try + { + DePack(obj); + } + catch (Exception) + { + } + } + + + public void AsynSend(byte[] data, string text = "") + { + try + { + Client.Send(data); + } + catch (Exception) + { + } + + } + + public void Disconnect() + { + try + { + if (this.Client != null) + { + this.Client.Close(); + this.Client = null; + } + } + catch (Exception) + { + } + + } + + + + + + + + public void ClearPack() + { + lock (mPackDic) + { + var vas = mPackDic.ToList().Where(f => f.Value.Time < DateTime.Now.AddMinutes(-5)); + foreach (var item in vas) + { + mPackDic.Remove(item.Key); + } + } + } + + + /// + /// 通过seq取微信服务器返回的socket包数据 + /// + /// + /// + public byte[] GetBuffBySeq(int Seq) + { + + lock (mPackDicLock) + { + //Thread.Sleep(10); + byte[] buf = null; + try + { + if (mPackDic.ContainsKey(Seq)) + { + buf = mPackDic[Seq].Data; + mPackDic.Remove(Seq); + return buf; + } + } + catch (Exception ee) + { + LogHelper.GetSingleObj().Error("Wechat GetBuffBySeq", $"{weixin.WeixinHao}- 获取超时!{ee.Message}"); + } + return buf; + } + } + + + private object mPackDicLock = new object(); + private byte[] packageData = null; + public bool DePack(byte[] bys) + { + + bool result = false; + int x = bys.Length; + + if (packageData != null) + { + byte[] temp = new byte[packageData.Length + x]; + Buffer.BlockCopy(packageData, 0, temp, 0, packageData.Length); + Buffer.BlockCopy(bys, 0, temp, packageData.Length, x); + packageData = temp; + } + else + { + packageData = new byte[x]; + Buffer.BlockCopy(bys, 0, packageData, 0, x); + } + + while (packageData != null && packageData.Length > 16) + { + int newPackageLength = WXClientTool.ReadInt(packageData, 0); + if (newPackageLength <= 0 || newPackageLength > 8000000) + { + LogHelper.GetSingleObj().Error("Wechat DePack", "长度不合法"); + packageData = null; + } + else if (newPackageLength <= packageData.Length) + { + byte[] newPackage = new byte[newPackageLength]; + Buffer.BlockCopy(packageData, 0, newPackage, 0, newPackageLength); + if (newPackageLength < packageData.Length) + { + byte[] temData = new byte[packageData.Length - newPackageLength]; + Buffer.BlockCopy(packageData, newPackageLength, temData, 0, packageData.Length - newPackageLength); + packageData = temData; + } + else + { + packageData = null; + } + HandlePackage(newPackage); + } + else + { + break; + } + } + return result; + + } + + //解析包 + public void HandlePackage(byte[] bys) + { + if (bys.Length == 20 && bys[3] == 20 && bys[5] == 16 && bys[7] == 1) + { + // 有新消息就会接受到此包 + SaveBufferToPackDic(bys); + return; + } + else + { + if (bys.Length >= 16 && bys[16] != (byte)191 + && !(bys[3] == 58 && bys[5] == 16 && bys[7] == 1 && bys.Length == 58) + && !(bys[3] == 47 && bys[5] == 16 && bys[7] == 1 && bys.Length == 47)) + { + return; + } + SaveBufferToPackDic(bys); + } + } + class SocketResult + { + public DateTime Time { get; set; } + public byte[] Data { get; set; } + } + Dictionary mPackDic = new Dictionary(); + public WXClientImpl_IPAD weixin; + public Func NotifyCallback { get; set; } + // int Seq = 0; + //保存数据到mPackDic + public void SaveBufferToPackDic(byte[] bys) + { + lock (mPackDicLock) + { + var Seq = WXClientTool.ReadInt(bys, 12); + if (Seq == 0) + { + byte[] buffers = new byte[bys.Length]; + Buffer.BlockCopy(bys, 0, buffers, 0, bys.Length); + + int cmd = WXClientTool.ReadInt(buffers, 8); + int selector = WXClientTool.ReadInt(buffers, 16); + LogHelper.GetSingleObj().Info("Wechat SaveBufferToPackDic", $"{weixin.WeixinHao}-收到{buffers.Length}字节!"); + if (cmd == 318 && NotifyCallback != null) + { + NotifyCallback(buffers); + } + + if (cmd == 24 && NotifyCallback != null) + { + NotifyCallback(buffers); + } + + if (cmd != 24 && cmd != 318) + { + } + } + else + { + byte[] buffers = new byte[bys.Length]; + Buffer.BlockCopy(bys, 0, buffers, 0, bys.Length); + mPackDic[Seq] = new SocketResult() { Data = buffers, Time = DateTime.Now }; + Seq = 0; + } + + } + + } + } + + public class ProtobufPackageInfo : IPackageInfo { + public byte[] buffer { get; set; } + } + public class ProtobufReceiveFilter : IReceiveFilter + { + public IReceiveFilter NextReceiveFilter { get; protected set; } + + public FilterState State => FilterState.Normal; + + public ProtobufPackageInfo Filter(BufferList data, out int rest) + { + rest = 0; + var list = data.Last; + byte[] buffer = new byte[list.Count]; + Array.Copy(list.Array, buffer, list.Count); + return new ProtobufPackageInfo() { buffer = buffer }; + + } + + public void Reset() + { + NextReceiveFilter = null; + } + } + public class MyReceiveFilter : SuperSocket.ProtoBase.IReceiveFilter + { + public IReceiveFilter NextReceiveFilter { get; protected set; } + + public FilterState State => FilterState.Normal; + + public BufferedPackageInfo Filter(BufferList data, out int rest) + { + + rest=0; + var list = data.Last; + byte[] buffer = new byte[list.Count]; + Array.Copy(list.Array, buffer, list.Count); + + return new BufferedPackageInfo("wx", new List>() { + new ArraySegment(buffer) + }); + + } + + public void Reset() + { + NextReceiveFilter = null; + } + } + +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/WechatCmd.cs b/类库/Chat.Framework/WXSdk/IPAD/WechatCmd.cs new file mode 100644 index 0000000..bdf58ca --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/WechatCmd.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.IPAD +{ + /// + /// 协议基础操作类型 + /// + public enum WechatCmd : int + { + 删除好友 = 681, + + 修改标签 = 638, + 获取标签 = 639, + 添加标签 = 635, + + 邀请入群 = 610, + 获取群信息 = 551, + 发送文本消息 = 522, + 发送语音文件 = 127, + 搜索关键词 = 719, + 发送图片文件 = -110, + 发送XML消息 = 222, + 同意添加好友 = 137, + 获取联系人信息 = 182, + 获取登录二维码 = 502, + 获取二维码状态 = 503, + 初始化用户信息 = 1002, + 读取通信录 = 851, + 发送消息 = 522, + 获取SYNC消息 = 138, + noping = 205, + GetA8Key = 233, + 密码登陆 = 2222, + 退出登录 = 281, + 执行二次登陆 = 702, + 心跳验证包 = 205, + 获取联系人二维码 = 168, + 浏览器加密登录 = 380, + 获得银行卡 = 385, + 发送CDN数据 = 149, + 获取登录短信 = 145, + 下载图片 = 109, + 上传朋友圈图片 = 207, + 发送朋友圈 = 209, + 获取朋友圈 = 212, + 评论或点赞 = 213, + 获取朋友圈首页 = 211, + 编辑联系人信息 = 681, + 删除群用户 = 179, + 群公告 = 993, + 创建群 = 119, + 添加群用户 = 120, + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/WechatHost.cs b/类库/Chat.Framework/WXSdk/IPAD/WechatHost.cs new file mode 100644 index 0000000..e6dfcce --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/WechatHost.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.IPAD +{ + /// + /// 协议微信 Host + /// + public class WechatHost + { + public List LongServerList { get; set; } + public List ShortServerList { get; set; } + + public string GetSort() + { + if (ShortServerList.Count == 0) return "short.weixin.qq.com"; + var list = Util.GetRandomList(ShortServerList); + foreach (var item in list) + { + return item; + } + throw new Exception("您的网络可能有问题,无法连接网络!"); + } + public void BindLongip(string ip) + { + LongServerList.Clear(); + LongServerList.Add(ip); + } + + public WechatHost() + { + LongServerList = new List(); + ShortServerList = new List(); + } + + public string GetLong() + { + if (LongServerList == null || LongServerList.Count == 0) return "long.weixin.qq.com"; + + var list = Util.GetRandomList(LongServerList); + foreach (var item in list) + { + var ip = Util.Ping(item); + if (ip) + { + return item; + } + } + return list[0]; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/WechatPack.cs b/类库/Chat.Framework/WXSdk/IPAD/WechatPack.cs new file mode 100644 index 0000000..b9b11ba --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/WechatPack.cs @@ -0,0 +1,372 @@ +using Chat.Framework.WXSdk.Implement; +using Google.Protobuf; +using System; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Script.Serialization; +using WechatProto; +using System.Linq; +using System.Text.RegularExpressions; +using Chat.Framework.WXSdk.Events; +using Grpc.Core; + +namespace Chat.Framework.WXSdk.IPAD +{ + /// + /// 协议发送包 + /// + public class WechatPack + { + public class PackMsg + { + //(WechatCmd cmd, bool isAnalysis, object data = null, ByteString longHead = null,string text="" + public WechatCmd cmd { get; set; } + public object data { get; set; } + } + WXClientImpl_IPAD client; + JavaScriptSerializer js = new JavaScriptSerializer(); + public WechatPack(WXClientImpl_IPAD client) + { + this.client = client; + this.js.MaxJsonLength = int.MaxValue; + } + + public WechatMsg Req { get; private set; } + private int ReadInt(byte[] buf, int index) + { + if (buf.Length >= 16) + { + var seqBuf = new byte[4]; + Buffer.BlockCopy(buf, index, seqBuf, 0, 4); + return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(seqBuf, 0)); + } + return 1; + } + + public byte[] Analysis(int cmd, byte[] data) + { + return Send(cmd > 0 ? cmd * -1 : cmd, data); + } + public byte[] Analysis(WechatCmd cmd, object data) + { + return Send((int)cmd * -1, data); + } + public byte[] Analysis(byte[] data) + { + int cmd = Req.BaseMsg.Cmd * -1; + return Send(cmd, data); + } + /// + /// 发送完整包,并解析微信返回信息 + /// + public byte[] SendAll(WechatCmd cmd, bool isAnalysis, object data = null, ByteString longHead = null, string text = "") + { + + var _data = Send(cmd, data, longHead); + if (_data != null && !IsShortResult)//判断数据不为空,并且不是腾讯短连接返回的结果 + { + _data = SendWx(_data, text: text); + + } + if (isAnalysis) + { + if (_data == null) return null; + return this.Analysis(_data); + } + return _data; + } + private bool IsShortResult { get; set; } + public byte[] Send(WechatCmd cmd, object data = null, ByteString longHead = null) + { + return Send((int)cmd, data, longHead); + } + public byte[] Send(WechatCmd cmd, byte[] data, ByteString longHead = null) + { + return Send((int)cmd, data, longHead); + } + // GrpcClient grpcClient = null; + private GrpcClient GetGrpcClient(WechatMsg req) + { + //if (grpcClient != null && grpcClient.IsConnected) return grpcClient; + GrpcClient grpcClient = null; + if (codes.Contains(req.BaseMsg.Cmd)) + { + grpcClient = client.GetGrpcClient(GrpcType.Huangfan); + //grpcClient = new GrpcClient(GrpcConfig.Get(GrpcType.Huangfan, false)); //client.GetGrpcClient(GrpcType.Huangfan); + } + else + { + grpcClient = client.GetGrpcClient(GrpcType.Laoyao); + } + return grpcClient; + } + public byte[] Send(WechatMsg req) + { + int number = 0; + + //GrpcClient grpc_client = null; + try + { + Next: + IsShortResult = false; + number++; + var msg = req.BaseMsg; + var grpc = GetGrpcClient(req); + //WechatMsg _req = SendGRPC(req, client).Result; + WechatMsg _req = grpc.Send(req, client).Result; + if (_req != null) Req = _req; + else + { + if (number < 3) + { + Thread.Sleep(100); + goto Next; + } + else throw new Exception("无法获取GRPC返回包!"); + } + + var Data = new byte[Req.BaseMsg.LongHead.Length + Req.BaseMsg.Payloads.Length]; + var Head = Req.BaseMsg.LongHead.ToByteArray(); + var Seq = ReadInt(Head, 12); + if (msg.Cmd < 0 && (int)WechatCmd.发送图片文件 != msg.Cmd) + { + ByteString key = null; + if (Req.BaseMsg.User.AutoAuthKey.Length != 0) + { + key = Req.BaseMsg.User.AutoAuthKey; + } + else if (client.User.User.AutoAuthKey.Length != 0) + key = client.User.User.AutoAuthKey; + + if (msg.Cmd == -138 || msg.Cmd == -1002 || msg.Cmd == -702 || msg.Cmd == -1001 || msg.Cmd == -380) + { + client.User.User = Req.BaseMsg.User; + } + if (key != null) + { + client.User.User.AutoAuthKey = key; + } + + return Req.BaseMsg.Payloads.ToByteArray(); + } + + if (msg.Cmd == (int)WechatCmd.获取标签 || msg.Cmd == (int)WechatCmd.添加标签 || msg.Cmd == (int)WechatCmd.修改标签 || msg.Cmd == (int)WechatCmd.搜索关键词 || msg.Cmd == 179 || msg.Cmd == (int)WechatCmd.编辑联系人信息 || msg.Cmd == (int)WechatCmd.删除好友 || msg.Cmd == 281 || msg.Cmd == 851 || msg.Cmd == 551 || msg.Cmd == 805 || msg.Cmd == 610 || msg.Cmd == 385 || msg.Cmd == 945 || msg.Cmd == (int)WechatCmd.评论或点赞 || msg.Cmd == (int)WechatCmd.邀请入群 || msg.Cmd == (int)WechatCmd.获取登录短信 || msg.Cmd == (int)WechatCmd.群公告) + { + IsShortResult = true; + var data = client.Socket.SendWeChatPost(Req.BaseMsg.Payloads.ToByteArray(), Req.BaseMsg.CmdUrl, 3); + //if (data == null) + //{ + // return this.SendWx(data); + //} + //else + + return data; //byte[] _data = null; + //CsharpHttpHelper.HttpHelper http = new CsharpHttpHelper.HttpHelper(); + //for (int i = 0; i < 2; i++) + //{ + // try + // { + // var item = new CsharpHttpHelper.HttpItem() + // { + // URL = "http://" + client.Host.GetSort() + Req.BaseMsg.CmdUrl, + // Method = "post", + // PostdataByte = Req.BaseMsg.Payloads.ToByteArray(), + // UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)", + // ContentType = "application/x-www-form-urlencoded", + // Allowautoredirect = true, + // Timeout = 5000, + // ReadWriteTimeout = 5000, + // ResultType = CsharpHttpHelper.Enum.ResultType.Byte, + // PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte + // }; + // _data = http.GetHtml(item).ResultByte; + // if (_data == null) continue; + // if (_data[0] != 191) continue; + // break; + // } + // catch (Exception) + // { + // } + //} + //return _data; + } + + try + { + var Body = Req.BaseMsg.Payloads.ToByteArray(); + Buffer.BlockCopy(Head, 0, Data, 0, 16); + Buffer.BlockCopy(Body, 0, Data, 16, Body.Length); + return Data; + } + catch (Exception ex) + { + if (number < 3) + { + Thread.Sleep(100); + goto Next; + } + else throw ex; + } + } + catch (Exception ex) + { + throw ex; + } + } + + private static int[] codes = new int[] { };//1111, 2222, 702, 3333, 380 + public byte[] Send(int cmd, object data, ByteString longHead = null) + { + try + { + ByteString param = null; + if (data != null) + { + if (typeof(string) == data.GetType()) + { + param = ByteString.CopyFrom(Encoding.UTF8.GetBytes(data.ToString())); + } + else if (typeof(byte[]) != data.GetType()) + { + var json = js.Serialize(data); + param = ByteString.CopyFrom(json, Encoding.UTF8); + } + else if (typeof(byte[]) == data.GetType()) + { + var _data = data as byte[]; + param = ByteString.CopyFrom(_data); + } + } + WechatProto.BaseMsg msg = null; + if (param != null) + msg = new BaseMsg() { Cmd = cmd, Payloads = param, User = client.User.User }; + else + msg = new BaseMsg() { Cmd = cmd, User = client.User.User }; + if (longHead != null) msg.LongHead = longHead; + Req = new WechatMsg + { + Token = WXClientTool.machine_code, + Version = "7.0.3", + TimeStamp = Util.GetTimeTotalSeconds(), + IP = client.clientIp, + BaseMsg = msg + }; + return Send(Req); + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("发送GRPC-" + cmd, ex.Message); + } + return null; + } + + public byte[] GetResult(int seq) + { + var buffers = this.client.Socket.GetResult(seq); + var start = DateTime.Now; + while (buffers == null) + { + Thread.Sleep(20); + buffers = this.client.Socket.GetResult(seq); + if (null == buffers && (DateTime.Now - start).Seconds > 10)//发送文字超时时间设置成40s + { + break; + } + } + return buffers; + } + + public byte[] SendWx(byte[] Data, int Seq = 0, int retry_number = 1, string text = "") + { + if (Seq == 0) + { + byte[] head = Data; + Seq = Util.ReadInt(head, 12); + } + //执行此方法无须解包 必须删除字典里的未解包 + // this.client.Socket.SendToWeChat(Seq,Data).Result; + for (int i = 1; i <= retry_number; i++) + { + this.client.Socket.SendToWechat(Data, text); + //if (!string.IsNullOrEmpty(rst)) + //{ + // this.client.WriteLog("发送失败:" + rst); + // continue; + //} + var buffer = GetResult(Seq); + if (buffer != null) return buffer; + } + LogHelper.GetSingleObj().Error("SendWx", $"{(string.IsNullOrEmpty(this.client.WeixinHao) ? string.Empty : this.client.WeixinHao)}执行{Seq},数据包发送失败!"); + return null; + + + //FastSocket 重构 + //return client.Socket.SendToWeChat(Seq, Data); + + + // int number = 0; + //Next: + // try + // { + // number++; + // var source = new TaskCompletionSource();// + // byte[] data = null; + // var seq = Seq == 0 ? Req.BaseMsg.Cmd.ToString() : DateTime.Now.Ticks.ToString(); + // var socket = client.Socket as FastSocket; + // var request = socket.WeChatClient.NewRequest(seq, Data, 5000 * 3, + // //绑定异常回调 + // ex => + // { //接收超时也会触发断开链接并且重连并自动清除队列 + // //fClient.SocketNote.BeginInvoke(false, null, null); + // Console.WriteLine("WeChat Socket Error:" + ex.Message); + // source.TrySetException(ex); + // }, + + // //绑定返回请求的回调 + // onResultMessage => + // { + // //触发此回调必有数据 + // //不触发则异常 发送收取超时等 + // data = onResultMessage.Msg.BaseMsg.Payloads.ToByteArray(); + // source.TrySetResult(data); + // } + // ); + // socket.Send(request); + // var Body = source.Task.Result; + // //长链接解包判定 + // if (Body != null && Body.Length > 16 && Body[16] != 191 && number <= 3) + // { + // //client.EventManage.OnEvent(this, QrcodeReq.BaseMsg.Cmd + ",非191,重试发包.."+number); + // goto Next; + // } + // return source.Task; + // } + + // catch (Exception ex) + // { + // client.WriteLog("SendWx(byte[] Data, int Seq = 0) Error:" + ex.Message); + // throw ex; + // } + } + + private PackMsg NextSendData; + public void SetNextData(PackMsg nextData) + { + this.NextSendData = nextData; + } + + public void SendNextData() + { + try + { + this.SendAll(this.NextSendData.cmd, false, this.NextSendData.data); + } + catch (Exception) + { + } + } + + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/WechatProto.cs b/类库/Chat.Framework/WXSdk/IPAD/WechatProto.cs new file mode 100644 index 0000000..a65f668 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/WechatProto.cs @@ -0,0 +1,1285 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: WechatProto.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using System; +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace WechatProto +{ + + /// Holder for reflection information generated from WechatProto.proto + public static partial class WechatProtoReflection + { + + #region Descriptor + /// File descriptor for WechatProto.proto + public static pbr::FileDescriptor Descriptor + { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static WechatProtoReflection() + { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChFXZWNoYXRQcm90by5wcm90bxILV2VjaGF0UHJvdG8icQoJV2VjaGF0TXNn", + "EiUKB2Jhc2VNc2cYASABKAsyFC5XZWNoYXRQcm90by5CYXNlTXNnEg0KBXRv", + "a2VuGAIgASgJEg8KB3ZlcnNpb24YAyABKAkSEQoJdGltZVN0YW1wGAQgASgF", + "EgoKAmlQGAUgASgJIrUBCgdCYXNlTXNnEgsKA3JldBgBIAEoBRILCgNjbWQY", + "AiABKAUSDgoGY21kVXJsGAMgASgJEhEKCXNob3J0SG9zdBgEIAEoCRIQCghs", + "b25nSG9zdBgFIAEoCRIfCgR1c2VyGAYgASgLMhEuV2VjaGF0UHJvdG8uVXNl", + "chIQCghsb25nSGVhZBgHIAEoDBIQCghwYXlsb2FkcxgIIAEoDBIWCg5wbGF5", + "bG9hZGV4dGVuZBgJIAEoDCLnAQoEVXNlchILCgN1aW4YASABKAMSDwoHY29v", + "a2llcxgCIAEoDBISCgpzZXNzaW9uS2V5GAMgASgMEhAKCGRldmljZUlkGAQg", + "ASgJEhIKCmRldmljZVR5cGUYBSABKAkSEgoKZGV2aWNlTmFtZRgGIAEoCRIW", + "Cg5jdXJyZW50c3luY0tleRgHIAEoDBISCgptYXhTeW5jS2V5GAggASgMEhMK", + "C2F1dG9BdXRoS2V5GAkgASgMEg8KB3VzZXJhbWUYCiABKAkSEAoIbmlja25h", + "bWUYCyABKAwSDwoHdXNlckV4dBgMIAEoDDJJCgZXZWNoYXQSPwoLSGVsbG9X", + "ZWNoYXQSFi5XZWNoYXRQcm90by5XZWNoYXRNc2caFi5XZWNoYXRQcm90by5X", + "ZWNoYXRNc2ciAGIGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::WechatProto.WechatMsg), global::WechatProto.WechatMsg.Parser, new[]{ "BaseMsg", "Token", "Version", "TimeStamp", "IP" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::WechatProto.BaseMsg), global::WechatProto.BaseMsg.Parser, new[]{ "Ret", "Cmd", "CmdUrl", "ShortHost", "LongHost", "User", "LongHead", "Payloads", "Playloadextend" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::WechatProto.User), global::WechatProto.User.Parser, new[]{ "Uin", "Cookies", "SessionKey", "DeviceId", "DeviceType", "DeviceName", "CurrentsyncKey", "MaxSyncKey", "AutoAuthKey", "Userame", "Nickname", "UserExt" }, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class WechatMsg : pb::IMessage + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new WechatMsg()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor + { + get { return global::WechatProto.WechatProtoReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor + { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public WechatMsg() + { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public WechatMsg(WechatMsg other) : this() + { + BaseMsg = other.baseMsg_ != null ? other.BaseMsg.Clone() : null; + token_ = other.token_; + version_ = other.version_; + timeStamp_ = other.timeStamp_; + iP_ = other.iP_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public WechatMsg Clone() + { + return new WechatMsg(this); + } + + /// Field number for the "baseMsg" field. + public const int BaseMsgFieldNumber = 1; + private global::WechatProto.BaseMsg baseMsg_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::WechatProto.BaseMsg BaseMsg + { + get { return baseMsg_; } + set + { + baseMsg_ = value; + } + } + + /// Field number for the "token" field. + public const int TokenFieldNumber = 2; + private string token_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Token + { + get { return token_; } + set + { + token_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "version" field. + public const int VersionFieldNumber = 3; + private string version_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Version + { + get { return version_; } + set + { + version_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "timeStamp" field. + public const int TimeStampFieldNumber = 4; + private int timeStamp_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int TimeStamp + { + get { return timeStamp_; } + set + { + timeStamp_ = value; + } + } + + /// Field number for the "iP" field. + public const int IPFieldNumber = 5; + private string iP_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string IP + { + get { return iP_; } + set + { + iP_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) + { + return Equals(other as WechatMsg); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(WechatMsg other) + { + if (ReferenceEquals(other, null)) + { + return false; + } + if (ReferenceEquals(other, this)) + { + return true; + } + if (!object.Equals(BaseMsg, other.BaseMsg)) return false; + if (Token != other.Token) return false; + if (Version != other.Version) return false; + if (TimeStamp != other.TimeStamp) return false; + if (IP != other.IP) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() + { + int hash = 1; + if (baseMsg_ != null) hash ^= BaseMsg.GetHashCode(); + if (Token.Length != 0) hash ^= Token.GetHashCode(); + if (Version.Length != 0) hash ^= Version.GetHashCode(); + if (TimeStamp != 0) hash ^= TimeStamp.GetHashCode(); + if (IP.Length != 0) hash ^= IP.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() + { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) + { + if (baseMsg_ != null) + { + output.WriteRawTag(10); + output.WriteMessage(BaseMsg); + } + if (Token.Length != 0) + { + output.WriteRawTag(18); + output.WriteString(Token); + } + if (Version.Length != 0) + { + output.WriteRawTag(26); + output.WriteString(Version); + } + if (TimeStamp != 0) + { + output.WriteRawTag(32); + output.WriteInt32(TimeStamp); + } + if (IP.Length != 0) + { + output.WriteRawTag(42); + output.WriteString(IP); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() + { + int size = 0; + if (baseMsg_ != null) + { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(BaseMsg); + } + if (Token.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Token); + } + if (Version.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Version); + } + if (TimeStamp != 0) + { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(TimeStamp); + } + if (IP.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(IP); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(WechatMsg other) + { + if (other == null) + { + return; + } + if (other.baseMsg_ != null) + { + if (baseMsg_ == null) + { + baseMsg_ = new global::WechatProto.BaseMsg(); + } + BaseMsg.MergeFrom(other.BaseMsg); + } + if (other.Token.Length != 0) + { + Token = other.Token; + } + if (other.Version.Length != 0) + { + Version = other.Version; + } + if (other.TimeStamp != 0) + { + TimeStamp = other.TimeStamp; + } + if (other.IP.Length != 0) + { + IP = other.IP; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) + { + uint tag; + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { + default: + input.SkipLastField(); + break; + case 10: + { + if (baseMsg_ == null) + { + baseMsg_ = new global::WechatProto.BaseMsg(); + } + input.ReadMessage(baseMsg_); + break; + } + case 18: + { + Token = input.ReadString(); + break; + } + case 26: + { + Version = input.ReadString(); + break; + } + case 32: + { + TimeStamp = input.ReadInt32(); + break; + } + case 42: + { + IP = input.ReadString(); + break; + } + } + } + } + + } + + public sealed partial class BaseMsg : pb::IMessage + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BaseMsg()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor + { + get { return global::WechatProto.WechatProtoReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor + { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BaseMsg() + { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BaseMsg(BaseMsg other) : this() + { + ret_ = other.ret_; + cmd_ = other.cmd_; + cmdUrl_ = other.cmdUrl_; + shortHost_ = other.shortHost_; + longHost_ = other.longHost_; + User = other.user_ != null ? other.User.Clone() : null; + longHead_ = other.longHead_; + payloads_ = other.payloads_; + playloadextend_ = other.playloadextend_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public BaseMsg Clone() + { + return new BaseMsg(this); + } + + /// Field number for the "ret" field. + public const int RetFieldNumber = 1; + private int ret_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Ret + { + get { return ret_; } + set + { + ret_ = value; + } + } + + /// Field number for the "cmd" field. + public const int CmdFieldNumber = 2; + private int cmd_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int Cmd + { + get { return cmd_; } + set + { + cmd_ = value; + } + } + + /// Field number for the "cmdUrl" field. + public const int CmdUrlFieldNumber = 3; + private string cmdUrl_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string CmdUrl + { + get { return cmdUrl_; } + set + { + cmdUrl_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "shortHost" field. + public const int ShortHostFieldNumber = 4; + private string shortHost_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string ShortHost + { + get { return shortHost_; } + set + { + shortHost_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "longHost" field. + public const int LongHostFieldNumber = 5; + private string longHost_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string LongHost + { + get { return longHost_; } + set + { + longHost_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "user" field. + public const int UserFieldNumber = 6; + private global::WechatProto.User user_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::WechatProto.User User + { + get { return user_; } + set + { + user_ = value; + } + } + + /// Field number for the "longHead" field. + public const int LongHeadFieldNumber = 7; + private pb::ByteString longHead_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString LongHead + { + get { return longHead_; } + set + { + longHead_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "payloads" field. + public const int PayloadsFieldNumber = 8; + private pb::ByteString payloads_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Payloads + { + get { return payloads_; } + set + { + payloads_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "playloadextend" field. + public const int PlayloadextendFieldNumber = 9; + private pb::ByteString playloadextend_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Playloadextend + { + get { return playloadextend_; } + set + { + playloadextend_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) + { + return Equals(other as BaseMsg); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(BaseMsg other) + { + if (ReferenceEquals(other, null)) + { + return false; + } + if (ReferenceEquals(other, this)) + { + return true; + } + if (Ret != other.Ret) return false; + if (Cmd != other.Cmd) return false; + if (CmdUrl != other.CmdUrl) return false; + if (ShortHost != other.ShortHost) return false; + if (LongHost != other.LongHost) return false; + if (!object.Equals(User, other.User)) return false; + if (LongHead != other.LongHead) return false; + if (Payloads != other.Payloads) return false; + if (Playloadextend != other.Playloadextend) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() + { + int hash = 1; + if (Ret != 0) hash ^= Ret.GetHashCode(); + if (Cmd != 0) hash ^= Cmd.GetHashCode(); + if (CmdUrl.Length != 0) hash ^= CmdUrl.GetHashCode(); + if (ShortHost.Length != 0) hash ^= ShortHost.GetHashCode(); + if (LongHost.Length != 0) hash ^= LongHost.GetHashCode(); + if (user_ != null) hash ^= User.GetHashCode(); + if (LongHead.Length != 0) hash ^= LongHead.GetHashCode(); + if (Payloads.Length != 0) hash ^= Payloads.GetHashCode(); + if (Playloadextend.Length != 0) hash ^= Playloadextend.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() + { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) + { + if (Ret != 0) + { + output.WriteRawTag(8); + output.WriteInt32(Ret); + } + if (Cmd != 0) + { + output.WriteRawTag(16); + output.WriteInt32(Cmd); + } + if (CmdUrl.Length != 0) + { + output.WriteRawTag(26); + output.WriteString(CmdUrl); + } + if (ShortHost.Length != 0) + { + output.WriteRawTag(34); + output.WriteString(ShortHost); + } + if (LongHost.Length != 0) + { + output.WriteRawTag(42); + output.WriteString(LongHost); + } + if (user_ != null) + { + output.WriteRawTag(50); + output.WriteMessage(User); + } + if (LongHead.Length != 0) + { + output.WriteRawTag(58); + output.WriteBytes(LongHead); + } + if (Payloads.Length != 0) + { + output.WriteRawTag(66); + output.WriteBytes(Payloads); + } + if (Playloadextend.Length != 0) + { + output.WriteRawTag(74); + output.WriteBytes(Playloadextend); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() + { + int size = 0; + if (Ret != 0) + { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Ret); + } + if (Cmd != 0) + { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cmd); + } + if (CmdUrl.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(CmdUrl); + } + if (ShortHost.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ShortHost); + } + if (LongHost.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(LongHost); + } + if (user_ != null) + { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(User); + } + if (LongHead.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(LongHead); + } + if (Payloads.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Payloads); + } + if (Playloadextend.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Playloadextend); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(BaseMsg other) + { + if (other == null) + { + return; + } + if (other.Ret != 0) + { + Ret = other.Ret; + } + if (other.Cmd != 0) + { + Cmd = other.Cmd; + } + if (other.CmdUrl.Length != 0) + { + CmdUrl = other.CmdUrl; + } + if (other.ShortHost.Length != 0) + { + ShortHost = other.ShortHost; + } + if (other.LongHost.Length != 0) + { + LongHost = other.LongHost; + } + if (other.user_ != null) + { + if (user_ == null) + { + user_ = new global::WechatProto.User(); + } + User.MergeFrom(other.User); + } + if (other.LongHead.Length != 0) + { + LongHead = other.LongHead; + } + if (other.Payloads.Length != 0) + { + Payloads = other.Payloads; + } + if (other.Playloadextend.Length != 0) + { + Playloadextend = other.Playloadextend; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) + { + uint tag; + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { + default: + input.SkipLastField(); + break; + case 8: + { + Ret = input.ReadInt32(); + break; + } + case 16: + { + Cmd = input.ReadInt32(); + break; + } + case 26: + { + CmdUrl = input.ReadString(); + break; + } + case 34: + { + ShortHost = input.ReadString(); + break; + } + case 42: + { + LongHost = input.ReadString(); + break; + } + case 50: + { + if (user_ == null) + { + user_ = new global::WechatProto.User(); + } + input.ReadMessage(user_); + break; + } + case 58: + { + LongHead = input.ReadBytes(); + break; + } + case 66: + { + Payloads = input.ReadBytes(); + break; + } + case 74: + { + Playloadextend = input.ReadBytes(); + break; + } + } + } + } + + } + [Serializable] + public sealed partial class User : pb::IMessage + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new User()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor + { + get { return global::WechatProto.WechatProtoReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor + { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public User() + { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public User(User other) : this() + { + uin_ = other.uin_; + cookies_ = other.cookies_; + sessionKey_ = other.sessionKey_; + deviceId_ = other.deviceId_; + deviceType_ = other.deviceType_; + deviceName_ = other.deviceName_; + currentsyncKey_ = other.currentsyncKey_; + maxSyncKey_ = other.maxSyncKey_; + autoAuthKey_ = other.autoAuthKey_; + userame_ = other.userame_; + nickname_ = other.nickname_; + userExt_ = other.userExt_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public User Clone() + { + return new User(this); + } + + /// Field number for the "uin" field. + public const int UinFieldNumber = 1; + private long uin_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public long Uin + { + get { return uin_; } + set + { + uin_ = value; + } + } + + /// Field number for the "cookies" field. + public const int CookiesFieldNumber = 2; + private pb::ByteString cookies_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Cookies + { + get { return cookies_; } + set + { + cookies_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "sessionKey" field. + public const int SessionKeyFieldNumber = 3; + private pb::ByteString sessionKey_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString SessionKey + { + get { return sessionKey_; } + set + { + sessionKey_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "deviceId" field. + public const int DeviceIdFieldNumber = 4; + private string deviceId_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string DeviceId + { + get { return deviceId_; } + set + { + deviceId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "deviceType" field. + public const int DeviceTypeFieldNumber = 5; + private string deviceType_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string DeviceType + { + get { return deviceType_; } + set + { + deviceType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "deviceName" field. + public const int DeviceNameFieldNumber = 6; + private string deviceName_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string DeviceName + { + get { return deviceName_; } + set + { + deviceName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "currentsyncKey" field. + public const int CurrentsyncKeyFieldNumber = 7; + private pb::ByteString currentsyncKey_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString CurrentsyncKey + { + get { return currentsyncKey_; } + set + { + currentsyncKey_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "maxSyncKey" field. + public const int MaxSyncKeyFieldNumber = 8; + private pb::ByteString maxSyncKey_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString MaxSyncKey + { + get { return maxSyncKey_; } + set + { + maxSyncKey_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "autoAuthKey" field. + public const int AutoAuthKeyFieldNumber = 9; + private pb::ByteString autoAuthKey_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString AutoAuthKey + { + get { return autoAuthKey_; } + set + { + autoAuthKey_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "userame" field. + public const int UserameFieldNumber = 10; + private string userame_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Userame + { + get { return userame_; } + set + { + userame_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "nickname" field. + public const int NicknameFieldNumber = 11; + private pb::ByteString nickname_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString Nickname + { + get { return nickname_; } + set + { + nickname_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "userExt" field. + public const int UserExtFieldNumber = 12; + private pb::ByteString userExt_ = pb::ByteString.Empty; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public pb::ByteString UserExt + { + get { return userExt_; } + set + { + userExt_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) + { + return Equals(other as User); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(User other) + { + if (ReferenceEquals(other, null)) + { + return false; + } + if (ReferenceEquals(other, this)) + { + return true; + } + if (Uin != other.Uin) return false; + if (Cookies != other.Cookies) return false; + if (SessionKey != other.SessionKey) return false; + if (DeviceId != other.DeviceId) return false; + if (DeviceType != other.DeviceType) return false; + if (DeviceName != other.DeviceName) return false; + if (CurrentsyncKey != other.CurrentsyncKey) return false; + if (MaxSyncKey != other.MaxSyncKey) return false; + if (AutoAuthKey != other.AutoAuthKey) return false; + if (Userame != other.Userame) return false; + if (Nickname != other.Nickname) return false; + if (UserExt != other.UserExt) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() + { + int hash = 1; + if (Uin != 0L) hash ^= Uin.GetHashCode(); + if (Cookies.Length != 0) hash ^= Cookies.GetHashCode(); + if (SessionKey.Length != 0) hash ^= SessionKey.GetHashCode(); + if (DeviceId.Length != 0) hash ^= DeviceId.GetHashCode(); + if (DeviceType.Length != 0) hash ^= DeviceType.GetHashCode(); + if (DeviceName.Length != 0) hash ^= DeviceName.GetHashCode(); + if (CurrentsyncKey.Length != 0) hash ^= CurrentsyncKey.GetHashCode(); + if (MaxSyncKey.Length != 0) hash ^= MaxSyncKey.GetHashCode(); + if (AutoAuthKey.Length != 0) hash ^= AutoAuthKey.GetHashCode(); + if (Userame.Length != 0) hash ^= Userame.GetHashCode(); + if (Nickname.Length != 0) hash ^= Nickname.GetHashCode(); + if (UserExt.Length != 0) hash ^= UserExt.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() + { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) + { + if (Uin != 0L) + { + output.WriteRawTag(8); + output.WriteInt64(Uin); + } + if (Cookies.Length != 0) + { + output.WriteRawTag(18); + output.WriteBytes(Cookies); + } + if (SessionKey.Length != 0) + { + output.WriteRawTag(26); + output.WriteBytes(SessionKey); + } + if (DeviceId.Length != 0) + { + output.WriteRawTag(34); + output.WriteString(DeviceId); + } + if (DeviceType.Length != 0) + { + output.WriteRawTag(42); + output.WriteString(DeviceType); + } + if (DeviceName.Length != 0) + { + output.WriteRawTag(50); + output.WriteString(DeviceName); + } + if (CurrentsyncKey.Length != 0) + { + output.WriteRawTag(58); + output.WriteBytes(CurrentsyncKey); + } + if (MaxSyncKey.Length != 0) + { + output.WriteRawTag(66); + output.WriteBytes(MaxSyncKey); + } + if (AutoAuthKey.Length != 0) + { + output.WriteRawTag(74); + output.WriteBytes(AutoAuthKey); + } + if (Userame.Length != 0) + { + output.WriteRawTag(82); + output.WriteString(Userame); + } + if (Nickname.Length != 0) + { + output.WriteRawTag(90); + output.WriteBytes(Nickname); + } + if (UserExt.Length != 0) + { + output.WriteRawTag(98); + output.WriteBytes(UserExt); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() + { + int size = 0; + if (Uin != 0L) + { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Uin); + } + if (Cookies.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Cookies); + } + if (SessionKey.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(SessionKey); + } + if (DeviceId.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(DeviceId); + } + if (DeviceType.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(DeviceType); + } + if (DeviceName.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(DeviceName); + } + if (CurrentsyncKey.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(CurrentsyncKey); + } + if (MaxSyncKey.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(MaxSyncKey); + } + if (AutoAuthKey.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(AutoAuthKey); + } + if (Userame.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Userame); + } + if (Nickname.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Nickname); + } + if (UserExt.Length != 0) + { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(UserExt); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(User other) + { + if (other == null) + { + return; + } + if (other.Uin != 0L) + { + Uin = other.Uin; + } + if (other.Cookies.Length != 0) + { + Cookies = other.Cookies; + } + if (other.SessionKey.Length != 0) + { + SessionKey = other.SessionKey; + } + if (other.DeviceId.Length != 0) + { + DeviceId = other.DeviceId; + } + if (other.DeviceType.Length != 0) + { + DeviceType = other.DeviceType; + } + if (other.DeviceName.Length != 0) + { + DeviceName = other.DeviceName; + } + if (other.CurrentsyncKey.Length != 0) + { + CurrentsyncKey = other.CurrentsyncKey; + } + if (other.MaxSyncKey.Length != 0) + { + MaxSyncKey = other.MaxSyncKey; + } + if (other.AutoAuthKey.Length != 0) + { + AutoAuthKey = other.AutoAuthKey; + } + if (other.Userame.Length != 0) + { + Userame = other.Userame; + } + if (other.Nickname.Length != 0) + { + Nickname = other.Nickname; + } + if (other.UserExt.Length != 0) + { + UserExt = other.UserExt; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) + { + uint tag; + while ((tag = input.ReadTag()) != 0) + { + switch (tag) + { + default: + input.SkipLastField(); + break; + case 8: + { + Uin = input.ReadInt64(); + break; + } + case 18: + { + Cookies = input.ReadBytes(); + break; + } + case 26: + { + SessionKey = input.ReadBytes(); + break; + } + case 34: + { + DeviceId = input.ReadString(); + break; + } + case 42: + { + DeviceType = input.ReadString(); + break; + } + case 50: + { + DeviceName = input.ReadString(); + break; + } + case 58: + { + CurrentsyncKey = input.ReadBytes(); + break; + } + case 66: + { + MaxSyncKey = input.ReadBytes(); + break; + } + case 74: + { + AutoAuthKey = input.ReadBytes(); + break; + } + case 82: + { + Userame = input.ReadString(); + break; + } + case 90: + { + Nickname = input.ReadBytes(); + break; + } + case 98: + { + UserExt = input.ReadBytes(); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/类库/Chat.Framework/WXSdk/IPAD/WechatProtoGrpc.cs b/类库/Chat.Framework/WXSdk/IPAD/WechatProtoGrpc.cs new file mode 100644 index 0000000..5928d80 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/WechatProtoGrpc.cs @@ -0,0 +1,128 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: WechatProto.proto +// Original file comments: +// Go support for Protocol Buffers - Google's data interchange format +// +// Copyright 2015 The Go Authors. All rights reserved. +// https://github.com/golang/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#region Designer generated code + +using System; +using System.Threading; +using System.Threading.Tasks; +using grpc = global::Grpc.Core; + +namespace WechatProto { + public static partial class Wechat + { + static readonly string __ServiceName = "WechatProto.Wechat"; + + static readonly grpc::Marshaller __Marshaller_WechatMsg = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::WechatProto.WechatMsg.Parser.ParseFrom); + + static readonly grpc::Method __Method_HelloWechat = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "HelloWechat", + __Marshaller_WechatMsg, + __Marshaller_WechatMsg); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::WechatProto.WechatProtoReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of Wechat + public abstract partial class WechatBase + { + public virtual global::System.Threading.Tasks.Task HelloWechat(global::WechatProto.WechatMsg request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for Wechat + public partial class WechatClient : grpc::ClientBase + { + /// Creates a new client for Wechat + /// The channel to use to make remote calls. + public WechatClient(grpc::Channel channel) : base(channel) + { + } + /// Creates a new client for Wechat that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + public WechatClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + protected WechatClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + protected WechatClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + public virtual global::WechatProto.WechatMsg HelloWechat(global::WechatProto.WechatMsg request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return HelloWechat(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + public virtual global::WechatProto.WechatMsg HelloWechat(global::WechatProto.WechatMsg request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_HelloWechat, null, options, request); + } + public virtual grpc::AsyncUnaryCall HelloWechatAsync(global::WechatProto.WechatMsg request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return HelloWechatAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + public virtual grpc::AsyncUnaryCall HelloWechatAsync(global::WechatProto.WechatMsg request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_HelloWechat, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + protected override WechatClient NewInstance(ClientBaseConfiguration configuration) + { + return new WechatClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + public static grpc::ServerServiceDefinition BindService(WechatBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_HelloWechat, serviceImpl.HelloWechat).Build(); + } + + } +} +#endregion diff --git a/类库/Chat.Framework/WXSdk/IPAD/WechatSocket.cs b/类库/Chat.Framework/WXSdk/IPAD/WechatSocket.cs new file mode 100644 index 0000000..3de77c4 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/WechatSocket.cs @@ -0,0 +1,357 @@ +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using WechatProto; +using static Chat.Framework.WXSdk.IPAD.SocketClient; + +namespace Chat.Framework.WXSdk.IPAD +{ + + + /// + /// 微信Socket + /// + public class WechatSocket + { + + private WXClientImpl_IPAD client; + public void TestError() + { + SocketExceptionCallback( WXSocketClientError.connetedErr,this._socket); + //this._socket.SocketExceptionCallback(WXSocketClientError.connetedErr); + } + public WechatSocket(WXClientImpl_IPAD client) + { + this.client = client; + } + ///// + ///// 微信Socket + ///// + //private SocketClient _socket; + private SocketClient _socket; + + public void ClearPack() + { + if (this._socket != null) this._socket.ClearPack(); + } + public bool IsStop { get;private set; } + /// + /// 停止 + /// + public void Stop() + { + try + { + if (_socket != null) + { + _socket.Disconnect(); + } + //_socket?.Stop(); + //_socket?.UnRegisterEndPoint("WeChat"); + + //_socketServers.Clear(); + //_httpServers.Clear(); + + if (_socket != null) _socket = null; + } + catch + { + // ignored + } + } + + public string ServerIp { get; set; } + /// + /// 连接腾讯服务器 + /// + /// + /// + public bool Connect() + { + + this.Stop(); + ServerIp = this.client.Host.GetLong(); + this._socket = new SocketClient(new DnsEndPoint(ServerIp, 443), this.client); + this._socket.NotifyCallback = (byte[] data) => + { + int cmd = WXClientTool.ReadInt(data, 8); + switch (cmd) + { + case 24: + if (Util.HexToStr(data) == "0000001400100001000000180000000000000100") + { + //朋友圈更新Notify + //Client.SyncMessage(true); + } + else + { + //普通消息Notify + Task.Factory.StartNew(client.AsyncSyncMessage); + } + break; + case 318: + client.DecodeSecureNotifyThread(data); + break; + default: + Console.WriteLine($"ReceivedUnKnowMessage CMD:" + cmd); + break; + } + + return true; + }; + this._socket.SocketExceptionCallback = SocketExceptionCallback; + return this._socket.Connect(); + } + + object lock_obj = new object(); + + private bool SocketExceptionCallback(SocketClient.WXSocketClientError error, SocketClient socketClient) + { + lock (lock_obj) + { + try + { + if (socketClient != null && socketClient == this._socket && socketClient.connected) + { + socketClient.Connect(); + if (client.Status == WxStatus.在线) client.AsyncSyncMessage(); + } + } + catch (Exception) + { + } + return true; + + } + + } + + + + + + ///// + ///// Socket中断 + ///// + ///// + //private void WeChatClient_ReceivedOnDisconnected(Sodao.FastSocket.SocketBase.IConnection connection) + //{ + // if (connection.RemoteEndPoint != null) + // OnReceivedOnDisconnected(connection.RemoteEndPoint.Address); + //} + + + + + + ///// + ///// 收到通知包 + ///// + ///// + ///// + //private void WeChatClient_ReceivedNotifyMessage(Sodao.FastSocket.SocketBase.IConnection connection, WeChatMessage message) + //{ + // if (message != null) OnReceivedNotifyMessage(message); + //} + + ///// + ///// 收到未知信息 + ///// + ///// + ///// + //private void WeChatClient_ReceivedUnknowMessage(IConnection arg1, WeChatMessage arg2) + //{ + // try + // { + // int Ret = Sodao.FastSocket.SocketBase.Utils.NetworkBitConverter.ToInt32(arg2.Msg.BaseMsg.Payloads.ToByteArray(), 18); + // Console.WriteLine("ReceivedUnknowMessage CMD" + arg2.CmdID + " 异常返回Ret:" + Ret); + // if (Ret == -13 && client.Status == WxStatus.在线) + // { + // client.WriteLog($"ReceivedUnknowMessage CMD" + arg2.CmdID + " -13 Need AutoLogin"); + // client.ResetConnection(); + // } + // } + // catch (Exception) + // { + // } + //} + + ///// + ///// 发包到腾讯 + ///// + ///// + ///// + //public byte[] SendToWeChat(WechatMsg pack) + //{ + // if (pack == null) return null; + + // if (_socket == null) Connect(); + + // if (pack.BaseMsg.LongHead.Length < 16 && !string.IsNullOrEmpty(pack.BaseMsg.CmdUrl)) + // { + // Console.WriteLine($"UnKnow pack"); + // return null; + // } + + // var buffers = new byte[pack.BaseMsg.LongHead.Length + pack.BaseMsg.Payloads.Length]; + // var head = pack.BaseMsg.LongHead.ToByteArray(); + // var body = pack.BaseMsg.Payloads.ToByteArray(); + + // try + // { + // if (head.Length > 0) + // { + // Buffer.BlockCopy(head, 0, buffers, 0, 16); + // Buffer.BlockCopy(body, 0, buffers, 16, body.Length); + // } + // else + // { + // Buffer.BlockCopy(body, 0, buffers, 0, body.Length); + // } + // } + // catch + // { + // return null; + // } + + // return SendToWeChat(pack.BaseMsg.Cmd, buffers).Result; + //} + + /// + /// 发包到腾讯 + /// + /// + /// + /// + public Task SendToWeChat(int cmd, byte[] buffers) + { + return null; + } + + + + public void SendToWechat(byte[] buffers,string text="") + { + if (_socket == null || !_socket.connected) + Connect(); + + this._socket.AsynSend(buffers); + } + + public byte[] GetResult(int seq) + { + if (_socket != null) return this._socket.GetBuffBySeq(seq); + return null; + } + + /// + /// 短链发送包 + /// + /// + /// + public byte[] SendWeChatPost(WechatMsg pack) + { + var body = pack.BaseMsg.Payloads.ToByteArray(); + + var result = SendWeChatPost(body, pack.BaseMsg.CmdUrl); + + return result; + } + + /// + /// 短链发送包 + /// + /// + /// + /// + public byte[] SendWeChatPost(byte[] body, string cmdUrl, int retry_number = 2) + { + + // var tryTime = 3; + again: + //"short.weixin.qq.com"; + var baseUrl = client.Host.GetSort(); + + HttpResult result = null; + try + { + var http = new HttpHelper(); + var header = new HttpItem() + { + URL = "http://" + baseUrl + cmdUrl, + Method = "POST", + PostdataByte = body, + PostDataType = CsharpHttpHelper.Enum.PostDataType.Byte, + Timeout = 10000, + ReadWriteTimeout = 10000, + UserAgent = "MicroMessenger Client", + ContentType = "application/octet-stream", + Accept = "*/*", + ResultType = CsharpHttpHelper.Enum.ResultType.Byte + }; + + result = http.GetHtml(header); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + if (result?.StatusCode == HttpStatusCode.OK && result?.ResultByte != null) + { + return result.ResultByte; + } + + if (retry_number > 0) + { + // baseUrl = client.Host.GetSort(); + retry_number--; + Thread.Sleep(10); + goto again; + } + + return null; + } + + /// + /// 连接成功 + /// + public event EventHandler ReceivedOnConnected; + + /// + /// 连接断开 + /// + public event EventHandler ReceivedOnDisconnected; + + ///// + ///// 收到通知包 + ///// + //public event EventHandler ReceivedNotifyMessage; + + ///// + ///// 收到通知包 + ///// + ///// + //protected virtual void OnReceivedNotifyMessage(WeChatMessage e) => ReceivedNotifyMessage?.Invoke(this, e); + + /// + /// 连接成功 + /// + /// + protected virtual void OnReceivedOnConnected(IPAddress e) => ReceivedOnConnected?.Invoke(this, e); + + /// + /// 连接断开 + /// + /// + protected virtual void OnReceivedOnDisconnected(IPAddress e) => ReceivedOnDisconnected?.Invoke(this, e); + } +} diff --git a/类库/Chat.Framework/WXSdk/IPAD/WxQrcode.cs b/类库/Chat.Framework/WXSdk/IPAD/WxQrcode.cs new file mode 100644 index 0000000..f373342 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/IPAD/WxQrcode.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.IPAD +{ + class WxQrcode + { + private int _CheckTime; + private int _Status; + private string _Username; + private string _Password; + private string _HeadImgUrl; + private string _Nickname; + private int _ExpiredTime; + private string _Uuid; + private byte[] _ImgBuf; + private byte[] _NotifyKey; + private byte[] _RandomKey; + + public int CheckTime + { + get + { + return _CheckTime; + } + + set + { + _CheckTime = value; + } + } + + public int Status + { + get + { + return _Status; + } + + set + { + _Status = value; + } + } + + public string Username + { + get + { + return _Username; + } + + set + { + _Username = value; + } + } + + public string Password + { + get + { + return _Password; + } + + set + { + _Password = value; + } + } + + public string HeadImgUrl + { + get + { + return _HeadImgUrl; + } + + set + { + _HeadImgUrl = value; + } + } + + public string Nickname + { + get + { + return _Nickname; + } + + set + { + _Nickname = value; + } + } + + public int ExpiredTime + { + get + { + return _ExpiredTime; + } + + set + { + _ExpiredTime = value; + } + } + + public string Uuid + { + get + { + return _Uuid; + } + + set + { + _Uuid = value; + } + } + + public byte[] ImgBuf + { + get + { + return _ImgBuf; + } + + set + { + _ImgBuf = value; + } + } + + public byte[] NotifyKey + { + get + { + return _NotifyKey; + } + + set + { + _NotifyKey = value; + } + } + + public byte[] RandomKey + { + get + { + return _RandomKey; + } + + set + { + _RandomKey = value; + } + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/EventManage.cs b/类库/Chat.Framework/WXSdk/Implement/EventManage.cs new file mode 100644 index 0000000..07220ce --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/EventManage.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.Events; + +namespace Chat.Framework.WXSdk.Implement +{ + /// + /// 底层事件管理 + /// + public class EventManage + { + public event EventHandler WXOpenWindowEvent; + internal void OnEvent(WXOpenWindow e) + { + if (WXOpenWindowEvent != null) WXOpenWindowEvent.Invoke(e.Client, e); + } + + /// + /// 获取设置信息事件 + /// + public event EventHandler WXGetDeviceEvent; + internal void OnEvent(WXGetDevice e) + { + if (WXGetDeviceEvent != null) WXGetDeviceEvent.Invoke(e.Client,e); + } + + public event EventHandler WXSendMessageEvent; + internal void OnEvent(WXSendMessage e) + { + if (WXSendMessageEvent != null) WXSendMessageEvent.Invoke(e.Client, e); + } + + public event EventHandler WXScavengEvent; + internal void OnEvent(WXScavengEvents e) + { + if (WXScavengEvent != null) WXScavengEvent.Invoke(e.Client,e); + } + + /// + /// 登录状态发生改变 + /// + public event EventHandler WXChangeStatusEvent; + internal void OnEvent(WXChangeStatus e) + { + if (this.WXChangeStatusEvent != null) this.WXChangeStatusEvent.Invoke(e.Client,e); + } + + /// + /// 用户信息发生改变 + /// + public event EventHandler WXRefreshUserEvent; + internal void OnEvent(WXRefreshUser e) + { + if (this.WXRefreshUserEvent != null) this.WXRefreshUserEvent.Invoke(e.Client, e); + } + + /// + /// 日志输出事件 + /// + public event EventHandler WXWriteLogEvent; + internal void OnEvent(WXWriteLog e) + { + if (this.WXWriteLogEvent != null) this.WXWriteLogEvent.Invoke(e.Client, e); + } + + /// + /// 成员申请加入群 + /// + public event EventHandler WXApplyGroupEvent; + internal void OnEvent(WXApplyGroup e) + { + if (this.WXApplyGroupEvent != null) this.WXApplyGroupEvent.Invoke(e.Client, e); + } + + /// + /// 新增微信好友 + /// + public event EventHandler WXNewFriendEvent; + internal void OnEvent(WXNewFriend e) + { + if (this.WXNewFriendEvent != null) this.WXNewFriendEvent.Invoke(e.Client, e); + } + + /// + /// 新增群成员 + /// + public event EventHandler WXNewMemerEvent; + internal void OnEvent(WXNewMemer e) + { + if (this.WXNewMemerEvent != null) this.WXNewMemerEvent.Invoke(e.Client, e); + } + + /// + /// 申请添加好友 + /// + public event EventHandler WXApplyFriendEvent; + internal void OnEvent(WXApplyFriend e) + { + if (string.IsNullOrEmpty(e.OldFriendWxid)) + { + e.Client.WriteLog(string.Format("{0}({1})申请添加我为好友!", e.NewFriendNick, e.NewFriendWxid)); + } + else + { + e.Client.WriteLog(string.Format("{0}({1}),通过{2}({3})介绍,申请添加我为好友!", e.NewFriendNick, e.NewFriendWxid,e.OldFriendNick,e.OldFriendWxid)); + } + + if (this.WXApplyFriendEvent != null) this.WXApplyFriendEvent.Invoke(e.Client,e); + } + + /// + /// 收到群消息 + /// + public event EventHandler WXReceiveGroupMsgEvent; + internal void OnEvent(WXReceiveGroupMsg e) + { + if (this.WXReceiveGroupMsgEvent != null) this.WXReceiveGroupMsgEvent.Invoke(e.Client, e); + } + + /// + /// 收到好友消息 + /// + public event EventHandler WXReiceveFriendMsgEvent; + internal void OnEvent(WXReiceveFriendMsg e) + { + if (this.WXReiceveFriendMsgEvent != null) this.WXReiceveFriendMsgEvent.Invoke(e.Client, e); + } + + + /// + /// 刷新通讯录完成 + /// + public event EventHandler WXRefreshContactSuccessEvent; + internal void OnEvent(WXRefreshContactSuccess e) + { + if (this.WXRefreshContactSuccessEvent != null) this.WXRefreshContactSuccessEvent.Invoke(e.Client, e); + } + + public event EventHandler WXWXReicevePayEvent; + internal void OnEvent(WXReicevePay e) + { + if (this.WXWXReicevePayEvent != null) this.WXWXReicevePayEvent.Invoke(e.Client, e); + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/HeadPack.cs b/类库/Chat.Framework/WXSdk/Implement/HeadPack.cs new file mode 100644 index 0000000..2300c25 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/HeadPack.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Chat.Framework.WXSdk.IPAD; + +namespace Chat.Framework.WXSdk.Implement +{ + public interface IRunable : IDisposable + { + void Run(object state, bool timedOut); + + bool IsRunning { get; } + + RegisteredWaitHandle RegisterdHandler { get; set; } + + WaitHandle WaitHandler { get; set; } + } + public interface ICallable + { + + void Call(object state); + + bool IsRunning { get; } + } + public class ThreadExcutor + { + public static void RegisterIntervalObject(IRunable runnable, object state, long interval, bool onlyOnce) + { + runnable.WaitHandler = new AutoResetEvent(false); + runnable.RegisterdHandler = ThreadPool.RegisterWaitForSingleObject(runnable.WaitHandler, new WaitOrTimerCallback(runnable.Run), state, interval, onlyOnce); + } + + public static void Submit(ICallable callable, object state) + { + if (!callable.IsRunning) + { + ThreadPool.QueueUserWorkItem(new WaitCallback(callable.Call), state); + } + } + + public static void UnRegisterIntervaluObject(IRunable runnable) + { + if (runnable != null) + { + if ((runnable.RegisterdHandler != null) && (runnable.WaitHandler != null)) + { + runnable.RegisterdHandler.Unregister(runnable.WaitHandler); + } + } + } + } + internal class HeadPack : IRunable + { + WXClientImpl_IPAD client; + public HeadPack(WXClientImpl_IPAD client) + { + ThreadExcutor.RegisterIntervalObject(this, this, 1000, false); + this.client = client; + } + public bool IsRunning { get; set; } + + public RegisteredWaitHandle RegisterdHandler { get; set; } + public WaitHandle WaitHandler { get; set; } + + public void Dispose() + { + + } + public int count { get; set; } + public void Run(object state, bool timedOut) + { + //ni轮训获取消息? + + if (IsRunning) return; + var isnext = false; + Next: + try + { + IsRunning = true; + if (client.Status == WxStatus.在线) + { + count++; + if (count % 172800 == 0)//2天重新登录一次 + { + if (client.FastLogin() == null) + { + if (!client.AsyncSyncMessage()) + client.ResetConnection(); + } + else + { + client.ResetConnection(); + } + } + else if (count % 300 == 0)//10分钟一次 + { + client.Socket.ClearPack(); + //20*30 + if (!client.AsyncSyncMessage()) client.ResetConnection(); + } + else if (count % 240 == 0) + { + WechatPack send = new WechatPack(this.client); + var data = send.Send(WechatCmd.心跳验证包); + var _data = send.SendWx(data); + } + } + + if (count % 100 == 0) client.CloseGRPC(true); + } + catch (Exception ex) + { + if (!isnext) + { + try + { + isnext = true; + client.ResetConnection(); + goto Next; + } + catch { } + } + client.WriteLog("心跳线程异常:" + ex.Message); + } + IsRunning = false; + + } + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/HeadPack_Hook.cs b/类库/Chat.Framework/WXSdk/Implement/HeadPack_Hook.cs new file mode 100644 index 0000000..7fb58ae --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/HeadPack_Hook.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Implement +{ + + internal class HeadPack_Hook : IRunable + { + public HeadPack_Hook() + { + ThreadExcutor.RegisterIntervalObject(this, this, 1000 * 30, false); + } + public bool IsRunning { get; set; } + + public RegisteredWaitHandle RegisterdHandler { get; set; } + public WaitHandle WaitHandler { get; set; } + + public void Dispose() + { + + } + + public void Run(object state, bool timedOut) + { + if (IsRunning) return; + try + { + IsRunning = true; + CheckHead(state); + } + catch (Exception ex) + { + + } + finally + { + IsRunning = false; + } + } + + private void CheckHead(object state) + { + try + { + var wechats = ChatClient.WXClient.Values.Where(f => f.WeixinType == WeixinType.Hook微信 && f.Status == WxStatus.在线).ToArray(); + foreach (WXClientImpl_HOOK client in wechats) + { + if (client != null) + { + try + { + //LogHelper.GetSingleObj().Info("", $"获取HeartBreakTime = {client.HeartBreakTime},Uin:{client.User.Uin},{client.User.Nick}({client.WeixinHao})"); + var span = DateTime.Now - client.HeartBreakTime; + if (span.TotalMinutes > 6) + { + LogHelper.GetSingleObj().Info("", $"退出咯: 间隔:{span.TotalMinutes}分,{client.HeartBreakTime},Uin:{client.User.Uin},{client.User.Nick}({client.WeixinHao})"); + //client.Status = WxStatus.已掉线; + client.HeartBreakTime = DateTime.MinValue; + + client.ChangeStatus(WxStatus.已掉线); + //client.Close(); + } + else + client.Status = WxStatus.在线; + } + catch (Exception) + { + } + } + } + + var qywechats = ChatClient.WXClient.Values.Where(f => f.WeixinType == WeixinType.QYHook微信 && f.Status == WxStatus.在线).ToArray(); + foreach (WXClientImpl_QYHOOK client in qywechats) + { + if (client != null) + { + try + { + var span = DateTime.Now - client.HeartBreakTime; + if (span.TotalMinutes > 6) + { + client.Status = WxStatus.已掉线; + client.HeartBreakTime = DateTime.MinValue; + client.ChangeStatus(client.Status); + //client.Close(); + } + else + client.Status = WxStatus.在线; + } + catch (Exception) + { + } + } + } + + } + catch (Exception ex) + { } + } + + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_HOOK.cs b/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_HOOK.cs new file mode 100644 index 0000000..909eacd --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_HOOK.cs @@ -0,0 +1,2683 @@ +using Chat.Framework.PCRobotSDK; +using Chat.Framework.PCRobotSDK.WechatEvents; +using Chat.Framework.Utils; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.HOOK; +using CsharpHttpHelper; +using Newtonsoft.Json; +using PCRobot.Pack; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using UI.Framework.Tools; +using static Chat.Framework.Utils.Common; + +namespace Chat.Framework.WXSdk.Implement +{ + /// + /// 普通PC机器人 + /// + public class WXClientImpl_HOOK : WeixinBase + { + /// + /// 上次心跳时间 + /// + public DateTime HeartBreakTime { get; internal set; } = DateTime.MinValue; + + public WXClientImpl_HOOK(string weixinhao, string usernick, long uin = -1) + { + WeixinType = WeixinType.Hook微信; + WeixinHao = weixinhao; + User = new WeixinBaseUser(WeixinHao, usernick, uin); + Friends = new Dictionary(); + GroupMembers = new Dictionary(); + HeartBreakTime = DateTime.Now; + //LogHelper.GetSingleObj().Info("", $"初始化HeartBreakTime = {HeartBreakTime} ,Uin:{uin}, {usernick}({weixinhao})"); + RequestContact(); + ChangeStatus(WxStatus.在线); + } + + // HeadPack_Hook headPack = null; + + public void Dispose() + { + if (this.User != null && this.User.Uin != 0 && this.User.Uin != -1) Grant.Framework.GrantClient.Get().LoginOut(this.User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0])); + } + + /// + /// pc普通微信状态改变 + /// + /// 状态 + /// 事件 + /// 没用 + public override void ChangeStatus(WxStatus status, WXChangeStatus e = null, bool is_next = true) + { + if (status == WxStatus.已掉线 || status == WxStatus.已退出 || status == WxStatus.未登录 || status == WxStatus.登录失败) + { + if (this.User != null && this.User.Uin != 0 && this.User.Uin != -1) Grant.Framework.GrantClient.Get().LoginOut(this.User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0])); + } + + if (status == WxStatus.在线) + { + if (!Grant.Framework.GrantClient.Get().IsExistCustomers(User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0]))) + { + try + { + //var ss = ChatClient.WXClient; + if (User.Uin.ToString() != "0" && User.Uin.ToString() != "-1") + { + ChatClient.Events.OnEvent(new WXRefreshUser(this)); + var c = Grant.Framework.GrantClient.Get().Login(User.Uin.ToString(), User.Nick, int.Parse(WXClientTool.auth_info[0]), WXClientTool.auth_info[1]); + } + } + catch (Exception ex) + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == WeixinHao).Value; + if (wx == null) + ChatClient.UpdateWXClient(this); + + ChatClient.Events.OnEvent(new WXWriteLog(this) { Message = $"【{User.Uin}({User.Nick})】授权异常:" + ex.Message }); + status = WxStatus.登录失败; + Dispose(); + ChatClient.LoginOutWeixin(WeixinHao, $"【{User.Uin}({User.Nick})】{ex.Message}"); + } + } + } + else + { + ChatClient.LoginOutWeixin(WeixinHao); + LogHelper.GetSingleObj().Debug("", $"微信状态修改:{this.WeixinHao} - {status}"); + } + base.ChangeStatus(status, e); + } + + public Process Process { get; private set; } + + public override void ShowLogin() + { + throw new Exception("请在易转发,客户端执行登陆!"); + } + + /// + /// 获得好友或群组信息 + /// + public override Friend GetContact(string wxid, bool refresh = false) + { + try + { + if (refresh || !Friends.ContainsKey(wxid)) + { + lock (this.Friends) + { + var msg_id = GetWxidInfo(wxid); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + + //{"wxid":"17565003780@chatroom","account":null,"nickname":"群名","avatar":"http://wx.qlogo.cn/mmcrhead/jRoggJ2RF3DSGEj42ibiaTuJExRwM/0","sex":0,"country":null,"province":null,"city":null,"manager_wxid":"wxid_vv722","is_manager":0,"member_list":"wxid_vv722,ws2d76,wxid_jgpp6xc522,wxid_eywrcm0w22"} + + try + { + var contact = rst as WechatContact; + if (!string.IsNullOrWhiteSpace(contact.Message)) + { + var data = @"{""data"":" + contact.Message + "}"; + var _result = CsharpHttpHelper.HttpExtend.JsonToDictionary(data); + if (_result != null) + { + var result = _result["data"] as Dictionary; + var _wxid = result["wxid"]?.ToString(); + var account = result["account"]?.ToString(); + var nickname = result["nickname"]?.ToString(); + var remark = result["remark"]?.ToString(); + var sex = int.Parse(result["sex"]?.ToString()); + var avatar = result["avatar"]?.ToString(); + var manager_wxid = result["manager_wxid"]?.ToString(); + var is_zombie = result["is_zombie"]?.ToString();//等于-1为没有检测,等于0为正常用户,1,2为拉黑用户 + + Friends[_wxid] = new Friend() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, City = string.Empty, Sex = sex, NickName = nickname, Remark = remark, UserName = _wxid, Alias = _wxid, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = manager_wxid, ChatroomVersion = string.Empty, Ticket = is_zombie }; + } + } + } + catch (Exception ex) + { + this.WriteLog($"获取Contact异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + } + if (Friends.ContainsKey(wxid)) return Friends[wxid]; + else + { + var f = ChatClient.GetDBWechatFriend(wxid); + if (f != null) + Friends[wxid] = f; + return f == null ? new Friend() { UserName = wxid, Alias = wxid } : f; + } + } + catch (Exception ex) + { + this.WriteLog($"{ex.Message}"); + } + return new Friend() { UserName = wxid, Alias = wxid }; + } + + #region xx + private readonly object GroupMemberLock = new object(); + private readonly object FriendsLock = new object(); + Action FriendsAction; + private void GetFriends(string friendsJson) + { + try + { + lock (FriendsLock) + { + #region + var dic = HttpExtend.JsonToDictionary(friendsJson); + if (dic != null && dic.ContainsKey("data")) + { + var data = dic["data"] as ArrayList; + foreach (Dictionary item in data) + { + var account = item["account"]?.ToString(); + var avatar = item["avatar"]?.ToString(); + var city = item["city"]?.ToString(); + var country = item["country"]?.ToString(); + var nickname = item["nickname"]?.ToString(); + var province = item["province"]?.ToString(); + var remark = item["remark"]?.ToString(); + var sex = int.Parse(item["sex"]?.ToString()); + var wxid = item["wxid"]?.ToString(); + + var manager_wxid = item["manager_wxid"]?.ToString(); + var is_manager = int.Parse(item["is_manager"].ToString()); + var is_zombie = item["is_zombie"]?.ToString();//等于-1为没有检测,等于0为正常用户,1,2为拉黑用户 + + if (Friends.ContainsKey(wxid)) + { + Friends[wxid].Ticket = is_zombie; + } + else + { + Friends[wxid] = new Friend() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, City = string.Empty, Sex = sex, NickName = nickname, Remark = remark, UserName = wxid, Alias = wxid, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = manager_wxid, ChatroomVersion = string.Empty, Ticket = is_zombie }; + } + } + } + #endregion + } + } + catch (Exception ex) + { } + } + + //Action GroupMembersAction; + + //private void GetGroupMembers(string friendsJson) + //{ + // try + // { + // lock (GroupMemberLock) + // { + // #region + // var dic = HttpExtend.JsonToDictionary(friendsJson); + // if (dic != null && dic.ContainsKey("data")) + // { + // var data = dic["data"] as Dictionary; + // var total_member = int.Parse(data["total_member"].ToString()); + // var gId = data["wxid"].ToString(); + // var list = data["member_list"] as ArrayList; + + // List groups = null; + // if (GroupMembers.ContainsKey(gId)) + // groups = GroupMembers[gId].ToList(); + // else + // groups = new List(); + + // foreach (Dictionary item in list) + // { + // var account = item["account"]?.ToString(); + // var avatar = item["avatar"]?.ToString(); + // var city = item["city"]?.ToString(); + // var country = item["country"]?.ToString(); + // var nickname = item["nickname"]?.ToString(); + // var province = item["province"]?.ToString(); + // var remark = item["remark"]?.ToString(); + // var sex = int.Parse(item["sex"]?.ToString()); + // var wxid = item["wxid"]?.ToString(); + + // if (groups.FirstOrDefault(f => f.Username == wxid) == null) + // groups.Add(new GroupMember() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, Groupid = gId, Username = wxid, NickName = nickname }); + // } + // GroupMembers[gId] = groups.ToArray(); + // } + // #endregion + // } + // } + // catch (Exception ex) + // { } + //} + #endregion + + /// + /// 好友列表 + /// + public Dictionary Friends { get; private set; } + + public override List FindFriends() + { + try + { + var msg_id = RequestContact(); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var commonResult = rst as CommonResult; + if (commonResult != null) + { + var data = commonResult.Data; + return JsonConvert.DeserializeObject>(data); + } + } + catch (Exception ex) + { + this.WriteLog($"获取通讯录用户异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + catch (Exception ex) + { } + return null; + } + + + /// + /// 请求获取联系人 + /// + /// + public string RequestContact() + { + try + { + WechatPack pack = new WechatPack(this); + return pack.SendServer(PCRobotCMD.getContact); + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 检测僵尸(最后获取Friends集合,判断里面的Ticket的值不为空为僵尸) + /// + public void GetZombie() + { + try + { + WechatPack send = new WechatPack(this); + send.SendServer(PCRobotCMD.getZombie); + } + catch (Exception) { } + } + + /// + /// 获取指定的群和用户 + /// + public string GetGroupWxidInfo(string groupId, string wxid) + { + try + { + WechatPack pack = new WechatPack(this); + //类型:图片表示不刷新,文件表示刷新 + return pack.SendServer(PCRobotCMD.getGroupWxidInfo, wxid, WechatMsgType.图片, groupId); + } + catch (Exception ex) + { } + return string.Empty; + } + + // + /// 获取指定的群和用户 + /// + public string GetGroupWxidInfo(string groupId, string wxid, bool flush) + { + try + { + WechatPack pack = new WechatPack(this); + //类型:图片表示不刷新,文件表示刷新 + return pack.SendServer(PCRobotCMD.getGroupWxidInfo, wxid, flush ? WechatMsgType.文件 : WechatMsgType.图片, groupId); + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 群-群成员缓存 + /// + public Dictionary GroupMembers { get; private set; } + + /// + /// 获取群用户信息 + /// + /// + /// + /// + public override GroupMember GetMember(string groupid, string wxid) + { + try + { + if (!GroupMembers.ContainsKey(groupid) || GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid) == null) + { + var msg_id = GetGroupWxidInfo(groupid, wxid); + //GetGroupInfo(groupid); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + // + try + { + //{"wxid":"18736590024@chatroom","nickname":null,"avatar":null,"total_member":88,"friends":[{"wxid":"wxid_vv7rev7a4xpj22","account":"MOKA_1314_","nickname":"A 小叮当21 - 不懂回复帮助","remark":"","avatar":"http://wx.qlogo.cn/mmhead/ver_1/UKuQPgzLzEY0UPqTgmqpSibLmx1BMibAlwJxOp4t8QksClGJP8tLHxUiaBDAax1Vf0Eiae6wKBIoT3ibAgOYTuuWiaVDiaiayiaaIZF46LcE5aBvTtSQ/132","sex":2,"country":"CN","province":"Sichuan","city":"Chengdu","manager_wxid":"","is_manager":0,"member_list":""}]} + + var contact = rst as WechatContact; + if (!string.IsNullOrWhiteSpace(contact.Message)) + { + var data = @"{""data"":" + contact.Message + "}"; + var _result = HttpExtend.JsonToDictionary(data); + if (_result != null) + { + var result = _result["data"] as Dictionary; + + var gwxid = result["wxid"]?.ToString(); + var total_member = result["total_member"]?.ToString(); + var gnickname = result["nickname"]?.ToString(); + var friend = (result["friends"] as ArrayList)[0] as Dictionary; + if (friend != null) + { + var avatar = friend["avatar"]?.ToString(); + var nickname = friend["nickname"]?.ToString(); + var remark = friend["remark"]?.ToString(); + var sex = int.Parse(friend["sex"]?.ToString()); + //var user_id = friend["user_id"]?.ToString(); + var manager_wxid = friend["manager_wxid"]?.ToString(); + if (!GroupMembers.ContainsKey(gwxid)) + { + GroupMembers.Add(gwxid, new GroupMember[] { }); + } + var gm = GroupMembers[gwxid].ToList(); + if (gm.FirstOrDefault(f => f.Username == wxid) == null) + { + gm.Add(new GroupMember() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, Groupid = gwxid, Username = wxid, NickName = nickname }); + GroupMembers[gwxid] = gm.ToArray(); + } + } + } + } + } + catch (Exception ex) + { + this.WriteLog($"获取Member异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + if (!GroupMembers.ContainsKey(groupid)) GroupMembers[groupid] = new GroupMember[] { new GroupMember() { Groupid = groupid, Username = wxid } }; + else + { + var member = GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + if (member == null) + { + var gm = GroupMembers[groupid].ToList(); + gm.Add(new GroupMember() { Groupid = groupid, Username = wxid }); + GroupMembers[groupid] = gm.ToArray(); + } + } + + return GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + } + catch (Exception ex) + { + this.WriteLog($"获取群信息:{ex.Message}"); + } + return new GroupMember() { Groupid = groupid, Username = wxid }; + } + + /// + /// 获取群用户信息 + /// + /// + /// + /// + public override GroupMember GetMember(string groupid, string wxid, bool flush = false) + { + try + { + if (flush || !GroupMembers.ContainsKey(groupid) || GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid) == null) + { + var msg_id = GetGroupWxidInfo(groupid, wxid, flush); + //GetGroupInfo(groupid); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + // + try + { + //{"wxid":"18736590024@chatroom","nickname":null,"avatar":null,"total_member":88,"friends":[{"wxid":"wxid_vv7rev7a4xpj22","account":"MOKA_1314_","nickname":"A 小叮当21 - 不懂回复帮助","remark":"","avatar":"http://wx.qlogo.cn/mmhead/ver_1/UKuQPgzLzEY0UPqTgmqpSibLmx1BMibAlwJxOp4t8QksClGJP8tLHxUiaBDAax1Vf0Eiae6wKBIoT3ibAgOYTuuWiaVDiaiayiaaIZF46LcE5aBvTtSQ/132","sex":2,"country":"CN","province":"Sichuan","city":"Chengdu","manager_wxid":"","is_manager":0,"member_list":""}]} + + var contact = rst as WechatContact; + if (string.IsNullOrWhiteSpace(contact.Message)) return null; + var data = @"{""data"":" + contact.Message + "}"; + var _result = CsharpHttpHelper.HttpExtend.JsonToDictionary(data); + if (_result == null) return null; + + var result = _result["data"] as Dictionary; + + var gwxid = result["wxid"]?.ToString(); + var total_member = result["total_member"]?.ToString(); + var gnickname = result["nickname"]?.ToString(); + var friend = (result["friends"] as ArrayList)[0] as Dictionary; + if (friend != null) + { + var avatar = friend["avatar"]?.ToString(); + var nickname = friend["nickname"]?.ToString(); + var remark = friend["remark"]?.ToString(); + var sex = int.Parse(friend["sex"]?.ToString()); + //var user_id = friend["user_id"]?.ToString(); + var manager_wxid = friend["manager_wxid"]?.ToString(); + if (!GroupMembers.ContainsKey(gwxid)) + { + GroupMembers.Add(gwxid, new GroupMember[] { }); + } + var gm = GroupMembers[gwxid].ToList(); + var info = gm.FirstOrDefault(f => f.Username == wxid); + if (info != null) + { + gm.Remove(info); + info = null; + } + if (info == null) + { + gm.Add(new GroupMember() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, Groupid = gwxid, Username = wxid, NickName = nickname }); + GroupMembers[gwxid] = gm.ToArray(); + } + } + } + catch (Exception ex) + { + this.WriteLog($"获取Member异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + if (!GroupMembers.ContainsKey(groupid)) GroupMembers[groupid] = new GroupMember[] { new GroupMember() { Groupid = groupid, Username = wxid } }; + else + { + var member = GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + if (member == null) + { + var gm = GroupMembers[groupid].ToList(); + gm.Add(new GroupMember() { Groupid = groupid, Username = wxid }); + GroupMembers[groupid] = gm.ToArray(); + } + } + + return GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + } + catch (Exception ex) + { + this.WriteLog($"获取群信息:{ex.Message}"); + } + return null; + } + + /// + /// 创建群 + /// + /// 用户账号需要3个或者以上 + /// + public override string CreateChatRoom(string[] wxids) + { + try + { + if (wxids == null || wxids.Length == 0) return string.Empty; + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.createRoom, string.Join(",", wxids)); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var createRoom = rst as CreateRoom; + if (createRoom != null) + return createRoom.GroupId; + } + catch (Exception ex) + { + this.WriteLog($"创建新群异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 创建群 + /// + /// 用户账号用,分隔 + /// + public override string CreateChatRoom(string wxids) + { + try + { + if (string.IsNullOrWhiteSpace(wxids)) return string.Empty; + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.createRoom, wxids); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var createRoom = rst as CreateRoom; + if (createRoom != null) + return createRoom.GroupId; + } + catch (Exception ex) + { + this.WriteLog($"创建新群异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + public override void AddChatRoomMember(string groupid, string members) + { + try + { + if (string.IsNullOrWhiteSpace(groupid)) return; + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.inviteIntoGroup, groupid, WechatMsgType.文本, members); + } + catch (Exception ex) + { } + } + + public override void AddChatRoomMember_40Down(string groupid, string members) + { + try + { + if (string.IsNullOrWhiteSpace(groupid)) return; + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.inviteIntoGroup_40Down, groupid, WechatMsgType.文本, members); + } + catch (Exception ex) + { } + } + + /// + /// 获取群基本消息(不包含群成员) + /// + /// + public override List GetGroupsNotInMember() + { + List friends = new List(); + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.getGroupsNotInMember); + + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var contact = rst as WechatContact; + + var dic = HttpExtend.JsonToDictionary(contact.Message); + if (dic != null && dic.ContainsKey("data")) + { + var data = dic["data"] as System.Collections.ArrayList; + foreach (Dictionary item in data) + { + var account = item["account"]?.ToString(); + var avatar = item["avatar"]?.ToString(); + var city = item["city"]?.ToString(); + var country = item["country"]?.ToString(); + var nickname = item["nickname"]?.ToString(); + var province = item["province"]?.ToString(); + var remark = item["remark"]?.ToString(); + var sex = int.Parse(item["sex"]?.ToString()); + var wxid = item["wxid"]?.ToString(); + + var manager_wxid = item["manager_wxid"]?.ToString(); + var is_manager = int.Parse(item["is_manager"].ToString()); + var is_zombie = item["is_zombie"]?.ToString();//等于-1为没有检测,等于0为正常用户,1,2为拉黑用户 + + friends.Add(new Friend() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, City = string.Empty, Sex = sex, NickName = nickname, Remark = remark, UserName = wxid, Alias = wxid, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = manager_wxid, ChatroomVersion = string.Empty, Ticket = is_zombie }); + } + } + } + catch (Exception ex) + { + this.WriteLog($"获取群列表异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + return friends; + } + + /// + /// 检测URL在微信中是否有效 + /// + /// 要检查的链接 + /// 返回true为连接没有屏蔽 + public override bool CheckUrl(string url) + { + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.checkUrl, url); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var checkUrl = rst as CheckUrl; + return (checkUrl != null && checkUrl.Status == 0); + } + catch (Exception ex) + { + this.WriteLog($"检测链接是否被封异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + return false; + } + + /// + /// + /// + /// + public override void OpenUrl(string url) + { + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.openUrl, url); + } + + /// + /// 清理历史聊天记录 + /// + public override void ClearChatHistoryMsg() + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.clearChatHistoryMsg); + } + + /// + /// 设置会话已读 + /// + public override void SetSessionReadedMsg(string wxid) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.setSessionReadedMsg, wxid); + } + + /// + /// 修改群聊名称 + /// + /// 新的群名 + /// 群id + public override void SetRoomName(string new_name, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.setRoomName, new_name, tousername: groupId); + } + + /// + /// 修改群公告(可用于@全体) + /// + /// 新公告 + /// 群聊wxid + public override void SetRoomNotice(string notice, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.setRoomNotice, notice, tousername: groupId); + } + + /// + /// 设置自己在群中昵称 + /// + /// 要设置的昵称 + /// 需要设置的群id + public override void ModRoomMyName(string nickname, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.modRoomMyName, nickname, tousername: groupId); + } + + /// + /// 设置是否显示群成员昵称 + /// + /// true为开启 + /// 要显示得到群 + public override void SetRoomShowMemeberName(bool status, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.setRoomShowMemeberName, status.ToString(), tousername: groupId); + } + + /// + /// 修改群聊名称 + /// + /// 新名称 + /// 群号 + public override void ModRoomName(string newnick, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.modRoomName, newnick, tousername: groupId); + } + + /// + /// 是否消息免打扰 + /// + /// true为开启 + /// wxid + public override void SetRecvNotify(bool status, string wxid) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.setRecvNotify, status.ToString(), tousername: wxid); + } + + /// + /// 关注公众号 + /// + /// 公众号wxid + public override void AddPublicUser(string wxid) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.addPublicUser, tousername: wxid); + } + + /// + /// 开启/关闭防撤回功能 + /// + /// 1是开启防撤回,0是关闭 + public override void SetDisableRevoke(bool status) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.setDisableRevoke, status.ToString()); + } + + public override List> FindCircles() + { + return FindCircle(""); + } + + public override List> FindCircle(string username, string firstPageMd5 = "", long MaxId = 0) + { + return FindCircle(username, MaxId.ToString()); + } + + private List> FindCircle(string username, string firstPageMd5 = "", string circleId = "0") + { + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.findCircles, circleId, tousername: username); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var result = rst as CommonResult; + if (result != null && !string.IsNullOrWhiteSpace(result.Data)) + { + //这里为了兼容性,将这里的数据改成ipad朋友圈返回的数据格式 + + #region 修正数据格式 + var jsonDic = HttpExtend.JsonToDictionary(result.Data); + var data = jsonDic["data"] as Dictionary; + //var firstPageMd5 = data["firstPageMd5"].ToString(); + //var data = new { FirFirstPageMd5 = firstPageMd5, SnsObjectsCount = long.Parse(HttpExtend.GetTimeStamp()), }; + + if (data.ContainsKey("objectList")) + { + var objectList = data["objectList"] as ArrayList; + if (objectList != null && objectList.Count != 0) + { + List cirCleInfoList = new List(); + for (int i = 0; i < objectList.Count; i++) + { + var obj = JsonConvert.SerializeObject(objectList[i]); + if (obj != null) + { + var cInfo = JsonConvert.DeserializeObject(obj); + if (cInfo != null) + { + var item = new CirCleInfo() + { + Id = cInfo.id, + Username = cInfo.username, + SnsObjectType = 45, + Nickname = cInfo.nickname, + CreateTime = cInfo.createTime, + + LikeFlag = cInfo.likeFlag, + LikeCount = cInfo.likeCount, + LikeUserListCount = cInfo.likeUserListCount, + + CommentCount = cInfo.commentCount, + CommentUserListCount = cInfo.commentUserListCount, + + WithUserCount = cInfo.withUserCount, + WithUserListCount = cInfo.withUserListCount, + WithUserList = null, + ExtFlag = cInfo.extFlag, + NoChange = cInfo.noChange, + GroupCount = cInfo.groupCount, + GroupList = null, + IsNotRichText = cInfo.isNotRichText, + ReferUsername = cInfo.referUsername, + ReferId = cInfo.referId, + BlackListCount = cInfo.blackListCount, + BlackList = null, + DeleteFlag = cInfo.deleteFlag, + GroupUserCount = cInfo.groupUserCount, + GroupUser = null, + ObjectOperations = null, + SnsRedEnvelops = null + }; + + if (cInfo.objectDesc != null) + item.ObjectDesc = HttpHelper.Base64ToString(cInfo.objectDesc.buffer, Encoding.UTF8); + if (cInfo.likeUserList != null) + { + List likeUList = new List(); + foreach (var tmp in cInfo.likeUserList) + { + likeUList.Add(new LikeUserList() + { + CommentFlag = tmp.commentFlag, + CommentId = tmp.commentId, + CommentId2 = tmp.commentId2, + Content = tmp.content, + CreateTime = tmp.createTime, + DeleteFlag = tmp.deleteFlag, + IsNotRichText = tmp.isNotRichText, + Nickname = tmp.nickname, + ReplyCommentId = tmp.replyCommentId, + ReplyCommentId2 = tmp.replyCommentId2, + ReplyUsername = tmp.replyUsername, + Source = tmp.source, + Type = tmp.type, + Username = tmp.username + }); + } + item.LikeUserList = likeUList; + } + + if (cInfo.commentUserList != null) + { + List commentUList = new List(); + foreach (var tmp in cInfo.commentUserList) + { + commentUList.Add(new CommentUserList() + { + CommentFlag = tmp.commentFlag, + CommentId = tmp.commentId, + CommentId2 = tmp.commentId2, + Content = tmp.content, + CreateTime = tmp.createTime, + DeleteFlag = tmp.deleteFlag, + IsNotRichText = tmp.isNotRichText, + Nickname = tmp.nickname, + ReplyCommentId = tmp.replyCommentId, + ReplyCommentId2 = tmp.replyCommentId2, + ReplyUsername = tmp.replyUsername, + Source = tmp.source, + Type = tmp.type, + Username = tmp.username + }); + } + item.CommentUserList = commentUList; + } + + cirCleInfoList.Add(item); + } + } + } + cirCleInfoList = cirCleInfoList.OrderByDescending(f => f.CreateTime).ToList(); + + List> _objs = new List>(); + + for (int i = 0; i < cirCleInfoList.Count; i++) + { + var tmp = HttpHelper.ObjectToJson(cirCleInfoList[i]); + var dic = HttpExtend.JsonToDictionary(tmp); + _objs.Add(dic); + } + return _objs; + } + } + #endregion + } + } + catch (Exception ex) + { + this.WriteLog($"获取朋友圈数据解析异常:" + ex.Message + " - " + ex.StackTrace); + } + } + else + { + + } + } + return new List>(); + } + + /// + /// 自动授权登录小程序 + /// + /// + public override string AutoAuthMiniAPPLogin(string appid) + { + try + { + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.autoAuthMiniAPPLogin, appid); + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + var result = rst as CommonResult; + if (result != null && !string.IsNullOrWhiteSpace(result.Data)) + { + return result.Data; + } + } + } + catch (Exception ex) + { + this.WriteLog($"获取自动授权登录小程序解析异常:" + ex.Message + " - " + ex.StackTrace); + } + return string.Empty; + } + + #region + /// + /// 点赞 + /// + private class LikeUserList + { + /// + /// + /// + public string Username { get; set; } + /// + /// + /// + public string Nickname { get; set; } + /// + /// + /// + public int Source { get; set; } + /// + /// + /// + public int Type { get; set; } + /// + /// + /// + public string Content { get; set; } + /// + /// + /// + public int CreateTime { get; set; } + /// + /// + /// + public int CommentId { get; set; } + /// + /// + /// + public int ReplyCommentId { get; set; } + /// + /// + /// + public string ReplyUsername { get; set; } + /// + /// + /// + public int IsNotRichText { get; set; } + /// + /// + /// + public int ReplyCommentId2 { get; set; } + /// + /// + /// + public int CommentId2 { get; set; } + /// + /// + /// + public int DeleteFlag { get; set; } + /// + /// + /// + public int CommentFlag { get; set; } + } + /// + /// 评价 + /// + private class CommentUserList + { + /// + /// + /// + public string Username { get; set; } + /// + /// 先森吳 + /// + public string Nickname { get; set; } + /// + /// + /// + public int Source { get; set; } + /// + /// + /// + public int Type { get; set; } + /// + /// + /// + public string Content { get; set; } + /// + /// + /// + public int CreateTime { get; set; } + /// + /// + /// + public int CommentId { get; set; } + /// + /// + /// + public int ReplyCommentId { get; set; } + /// + /// + /// + public string ReplyUsername { get; set; } + /// + /// + /// + public int IsNotRichText { get; set; } + /// + /// + /// + public int ReplyCommentId2 { get; set; } + /// + /// + /// + public int CommentId2 { get; set; } + /// + /// + /// + public int DeleteFlag { get; set; } + /// + /// + /// + public int CommentFlag { get; set; } + } + + /// + /// 朋友圈信息 + /// + private class CirCleInfo + { + /// + /// + /// + public decimal Id { get; set; } + /// + /// + /// + public string Username { get; set; } + /// + /// + /// + public int SnsObjectType { get; set; } + /// + /// + /// + public string Nickname { get; set; } + /// + /// + /// + public int CreateTime { get; set; } + /// + /// 13647904548865061200wxid_tnizkijej5uq221626957005看不懂不应该是常态吗[破涕为笑]0300002 + /// + public string ObjectDesc { get; set; } + /// + /// + /// + public int LikeFlag { get; set; } + /// + /// + /// + public int LikeCount { get; set; } + /// + /// + /// + public int LikeUserListCount { get; set; } + /// + /// + /// + public List LikeUserList { get; set; } + /// + /// + /// + public int CommentCount { get; set; } + /// + /// + /// + public int CommentUserListCount { get; set; } + /// + /// + /// + public List CommentUserList { get; set; } + /// + /// + /// + public int WithUserCount { get; set; } + /// + /// + /// + public int WithUserListCount { get; set; } + /// + /// + /// + public object WithUserList { get; set; } + /// + /// + /// + public int ExtFlag { get; set; } + /// + /// + /// + public int NoChange { get; set; } + /// + /// + /// + public int GroupCount { get; set; } + /// + /// + /// + public object GroupList { get; set; } + /// + /// + /// + public int IsNotRichText { get; set; } + /// + /// + /// + public string ReferUsername { get; set; } + /// + /// + /// + public int ReferId { get; set; } + /// + /// + /// + public int BlackListCount { get; set; } + /// + /// + /// + public object BlackList { get; set; } + /// + /// + /// + public int DeleteFlag { get; set; } + /// + /// + /// + public int GroupUserCount { get; set; } + /// + /// + /// + public object GroupUser { get; set; } + /// + /// + /// + public object ObjectOperations { get; set; } + /// + /// + /// + public object SnsRedEnvelops { get; set; } + } + + + #region pc原始单条朋友圈对象 + + public class CommentUserListOri + { + /// + /// + /// + public int commentFlag { get; set; } + /// + /// + /// + public int commentId { get; set; } + /// + /// + /// + public int commentId2 { get; set; } + /// + /// + /// + public string content { get; set; } + /// + /// + /// + public int createTime { get; set; } + /// + /// + /// + public int deleteFlag { get; set; } + /// + /// + /// + public int isNotRichText { get; set; } + /// + /// 先森吳 + /// + public string nickname { get; set; } + /// + /// + /// + public int replyCommentId { get; set; } + /// + /// + /// + public int replyCommentId2 { get; set; } + /// + /// + /// + public string replyUsername { get; set; } + /// + /// + /// + public int source { get; set; } + /// + /// + /// + public int type { get; set; } + /// + /// + /// + public string username { get; set; } + } + + public class LikeUserListOri + { + /// + /// + /// + public int commentFlag { get; set; } + /// + /// + /// + public int commentId { get; set; } + /// + /// + /// + public int commentId2 { get; set; } + /// + /// + /// + public string content { get; set; } + /// + /// + /// + public int createTime { get; set; } + /// + /// + /// + public int deleteFlag { get; set; } + /// + /// + /// + public int isNotRichText { get; set; } + /// + /// + /// + public string nickname { get; set; } + /// + /// + /// + public int replyCommentId { get; set; } + /// + /// + /// + public int replyCommentId2 { get; set; } + /// + /// + /// + public string replyUsername { get; set; } + /// + /// + /// + public int source { get; set; } + /// + /// + /// + public int type { get; set; } + /// + /// + /// + public string username { get; set; } + } + + public class ObjectDesc + { + /// + /// + /// + public string buffer { get; set; } + /// + /// + /// + public int iLen { get; set; } + } + + public class ObjectOperations + { + /// + /// + /// + public string buffer { get; set; } + /// + /// + /// + public int iLen { get; set; } + } + + public class PreDownloadInfo + { + /// + /// + /// + public string noPreDownloadRange { get; set; } + /// + /// + /// + public int preDownloadNetType { get; set; } + /// + /// + /// + public int preDownloadPercent { get; set; } + } + + public class SnsRedEnvelops + { + /// + /// + /// + public int reportId { get; set; } + /// + /// + /// + public int reportKey { get; set; } + /// + /// + /// + public int resourceId { get; set; } + /// + /// + /// + public int rewardCount { get; set; } + } + + public class WeAppInfo + { + /// + /// + /// + public int appId { get; set; } + /// + /// + /// + public string mapPoiId { get; set; } + /// + /// + /// + public string redirectUrl { get; set; } + /// + /// + /// + public int score { get; set; } + /// + /// + /// + public int showType { get; set; } + /// + /// + /// + public string userName { get; set; } + } + + public class CirCleInfoOri + { + /// + /// + /// + public int blackListCount { get; set; } + /// + /// + /// + public int commentCount { get; set; } + /// + /// + /// + public List commentUserList { get; set; } + /// + /// + /// + public int commentUserListCount { get; set; } + /// + /// + /// + public int createTime { get; set; } + /// + /// + /// + public int deleteFlag { get; set; } + /// + /// + /// + public int extFlag { get; set; } + /// + /// + /// + public int groupCount { get; set; } + /// + /// + /// + public int groupUserCount { get; set; } + /// + /// + /// + public decimal id { get; set; } + /// + /// + /// + public int isNotRichText { get; set; } + /// + /// + /// + public int likeCount { get; set; } + /// + /// + /// + public int likeFlag { get; set; } + /// + /// + /// + public List likeUserList { get; set; } + /// + /// + /// + public int likeUserListCount { get; set; } + /// + /// + /// + public string nickname { get; set; } + /// + /// + /// + public int noChange { get; set; } + /// + /// + /// + public ObjectDesc objectDesc { get; set; } + /// + /// + /// + public ObjectOperations objectOperations { get; set; } + /// + /// + /// + public PreDownloadInfo preDownloadInfo { get; set; } + /// + /// + /// + public int referId { get; set; } + /// + /// + /// + public string referUsername { get; set; } + /// + /// + /// + public SnsRedEnvelops snsRedEnvelops { get; set; } + /// + /// + /// + public string username { get; set; } + /// + /// + /// + public WeAppInfo weAppInfo { get; set; } + /// + /// + /// + public int withUserCount { get; set; } + /// + /// + /// + public int withUserListCount { get; set; } + } + + #endregion + + #endregion + + /// + /// 朋友圈点赞 + /// + /// 无用 + /// 朋友圈id + public override void SendCirclePraise(string username, string circleId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.sendCirclePraise, circleId); + } + + public override void SendCircleComment(string username, string circleId, string content) + { + if (string.IsNullOrEmpty(content)) return; + content = content.Replace("\r\n", "\n").Trim(); + var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + try + { + foreach (var msgTmp in msgs) + { + var msg = msgTmp.RandomMess(); + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.sendCircleComment, msg, tousername: circleId); + Thread.Sleep(2450 + new Random().Next(50, 1000)); + } + } + catch (Exception ex) + { + WriteLog("SendCircleComment Error:" + ex.Message); + } + } + + public override string SendCircle(string msg) + { + var xml = GetCircleXml(msg); + LogHelper.GetSingleObj().Info("发送朋友圈的xml", xml); + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.sendCircle, xml); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var result = rst as CommonResult; + if (result != null && !string.IsNullOrWhiteSpace(result.Data)) + { + return $"{result.Data}"; + } + } + catch (Exception ex) + { + this.WriteLog($"发送朋友圈异常:" + ex.Message + " - " + ex.StackTrace); + } + } + else + { + + } + } + return string.Empty; + } + + #region 发送朋友圈相关 + /// + /// 解析获取xml + /// + /// + /// + private string GetCircleXml(string msg) + { + var xml = string.Empty; + try + { + msg = msg.RandomMess().Trim(); + if (msg.StartsWith("", StringComparison.CurrentCultureIgnoreCase) && msg.EndsWith("", StringComparison.CurrentCultureIgnoreCase)) + { + try + { + msg = Regex.Replace(msg, @"videomd5=""(.{32})""", @"videomd5=""" + Util.GetMD5Hash(Guid.NewGuid().ToByteArray()) + @"""", RegexOptions.IgnoreCase); + msg = Regex.Replace(msg, @"md5=""(.{32})""", @"md5=""" + Util.GetMD5Hash(Guid.NewGuid().ToByteArray()) + @"""", RegexOptions.IgnoreCase); + + + var match = Regex.Matches(msg, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Count > 0) + { + foreach (Match item in match) + { + var imageUrl = UplodCircleImage(item.Groups[1].Value); + Console.WriteLine("@@@@@@@ url=" + imageUrl); + if (!string.IsNullOrWhiteSpace(imageUrl)) + msg = msg.Replace($"[图片={item.Groups[1].Value}]", imageUrl); + } + } + } + catch (Exception) + { } + //xml = SendCircle(msg, null, CircleType.图文朋友圈); + return msg; + } + else + { + if (msg.Contains("[图片")) + { + //检测图片、如果是本地图片或非微信服务器图片、将自动上传并返回最新地址 + List images = null; + var match = Regex.Matches(msg, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Count > 0) + { + images = new List(); + + foreach (Match item in match) + { + images.Add(item.Groups[1].Value); + } + msg = Regex.Replace(msg, "\\[图片=.*?\\]", "").Trim(); + } + xml = SendCircle(msg, images, CircleType.图文朋友圈); + } + else if (msg.Contains("[视频")) + { + //检测图片、如果是本地图片或非微信服务器图片、将自动上传并返回最新地址 + List videos = null; + var match = Regex.Matches(msg, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Count > 0) + { + videos = new List(); + + foreach (Match item in match) + { + videos.Add(item.Groups[1].Value); + } + msg = Regex.Replace(msg, "\\[视频=.*?\\]", "").Trim(); + } + xml = SendCircle(msg, videos, CircleType.视频朋友圈); + } + else if (msg.Contains("[链接")) + { + //检测图片、如果是本地图片或非微信服务器图片、将自动上传并返回最新地址 + List videos = null; + var match = Regex.Matches(msg, @"\[链接\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Count > 0) + { + videos = new List(); + + foreach (Match item in match) + { + videos.Add(item.Groups[1].Value); + } + msg = Regex.Replace(msg, "\\[链接=.*?\\]", "").Trim(); + } + xml = SendCircle(msg, videos, CircleType.视频朋友圈); + } + else + { + xml = SendCircle(msg, null, CircleType.文字朋友圈); + } + } + } + catch (Exception ex) + { } + return xml; + } + + private string SendCircle(string content, List list, CircleType circleType) + { + StringBuilder sb = new StringBuilder(); + try + { + switch (circleType) + { + case CircleType.文字朋友圈: + { + sb.Append("" + Util.GenerateRandomCode(20) + "weixin" + Util.TimeStamp() + "030"); + sb.Append("" + content + ""); + sb.Append("0002"); + } + break; + case CircleType.视频朋友圈: + { + { + sb.Append("" + Util.GenerateRandomCode(20) + "weixin" + Util.TimeStamp() + "000"); + sb.Append("" + content + ""); + sb.Append("00015微信小视频Sight"); + sb.Append("" + Util.GenerateRandomCode(20) + ""); + sb.Append("6"); + sb.Append("0"); + sb.Append(""); + sb.Append("" + content + ""); + sb.Append("00"); + sb.Append("" + ((list != null && list.Count != 0) ? list[0] : "https://support.weixin.qq.com/cgi-bin/mmsupport-bin/readtemplate?t=page/common_page__upgrade&v=1") + ""); + + sb.Append("" + ((list != null && list.Count != 0) ? list[0] : "https://support.weixin.qq.com/cgi-bin/mmsupport-bin/readtemplate?t=page/common_page__upgrade&v=1") + "");//这里应该是视频的第一张图片 + sb.Append("27.166667"); + sb.Append("https://support.weixin.qq.com/cgi-bin/mmsupport-bin/readtemplate?t=page/common_page__upgrade&v=1"); + } + } + break; + case CircleType.链接朋友圈: + { + sb.Append("" + Util.GenerateRandomCode(20) + "weixin" + Util.TimeStamp() + "040000"); + sb.Append("3"); + sb.Append("" + content + ""); + sb.Append("" + content + ""); + sb.Append("" + ((list != null && list.Count != 0) ? list[0] : "https://support.weixin.qq.com/cgi-bin/mmsupport-bin/readtemplate?t=page/common_page__upgrade&v=1") + ""); + sb.Append(""); + sb.Append(""); + sb.Append("" + Util.GenerateRandomCode(20) + ""); + sb.Append("2"); + sb.Append(""); + sb.Append(""); + sb.Append("0"); + sb.Append("0"); + sb.Append("https://img.sj33.cn/uploads/allimg/201402/7-140223103130591.png"); + sb.Append("https://img.sj33.cn/uploads/allimg/201402/7-140223103130591.png"); + sb.Append("https://img.sj33.cn/uploads/allimg/201402/7-140223103130591.png"); + sb.Append(""); + sb.Append(""); + sb.Append(""); + } + break; + case CircleType.图文朋友圈: + { + sb.Append("" + Util.GenerateRandomCode(20) + "weixin" + Util.TimeStamp() + ""); + sb.Append("" + content + ""); + sb.Append("0300001"); + sb.Append(""); + if (list != null) + { + foreach (string temp in list) + { + //var url = temp; + var url = UplodCircleImage(temp); + LogHelper.GetSingleObj().Info("朋友圈图片上传", $"{User.Nick}({User.Username}) => 原图={temp},转后={url}"); + if (string.IsNullOrWhiteSpace(url)) + continue; + sb.Append(""); + sb.Append("" + Util.GenerateRandomCode(20) + ""); + sb.Append("2"); + sb.Append(""); + sb.Append("" + content + ""); + sb.Append("00"); + sb.Append(""); + sb.Append("" + url + ""); + sb.Append("" + url + ""); + sb.Append(""); + sb.Append(""); + } + } + sb.Append(""); + sb.Append(""); + } + break; + default: + break; + } + + + } + catch (Exception ex) + { + + } + return sb.ToString(); + } + + //private string _UplodCirele(string content) + //{ + // try + // { + // var match = Regex.Matches(content, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + // foreach (Match item in match) + // { + // try + // { + // var url = item.Groups[1].Value; + // url = UplodCircleImage(url); + // if (string.IsNullOrWhiteSpace(url)) continue; + // content = content.Replace($"[图片={item.Groups[1].Value}]", url); + // } + // catch (Exception) + // { + // } + // } + // var payloadJson = new + // { + // Content = Encoding.UTF8.GetBytes(content) + // }; + // WechatPack send = new WechatPack(this); + // return Encoding.UTF8.GetString(send.SendAll(WechatCmd.发送朋友圈, true, payloadJson)); + // } + // catch (Exception ex) + // { + // WriteLog("发送朋友圈失败:" + ex.Message); + // return null; + // } + //} + + #region 上传 + private Dictionary CircleUrlDic = new Dictionary(); + private Queue Queues = new Queue(); + + private string GetUrlInfo() + { + try + { + return Queues.Dequeue(); + } + catch (Exception) + { } + return null; + } + private bool _IsRun = false; + private void _ExchangeAction() + { + if (_IsRun) return; + _IsRun = true; + + Task.Run(() => + { + try + { + var data = GetUrlInfo(); + while (!string.IsNullOrWhiteSpace(data)) + { + var md5 = HttpExtend.GetMD5String(data); + try + { + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.uploadCiecleImage, data); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var result = rst as CommonResult; + if (result != null && !string.IsNullOrWhiteSpace(result.Data)) + { + CircleUrlDic.Add(md5, result.Data); + } + } + catch (Exception ex) + { + this.WriteLog($"朋友圈上传本地图片异常:" + ex.Message + " - " + ex.StackTrace); + } + } + else + { + CircleUrlDic.Add(md5, string.Empty); + } + } + //return string.Empty; + + } + catch (Exception ex) + { } + finally + { + if (!CircleUrlDic.ContainsKey(md5)) + CircleUrlDic.Add(md5, string.Empty); + data = GetUrlInfo(); + } + } + } + catch (Exception ex) + { + } + finally + { + _IsRun = false; + } + }); + } + #endregion + + /// + /// 开始上传图片 + /// + public string UplodCircleImage(string url) + { + try + { + var urlResult = string.Empty; + for (int i = 0; i < 1; i++) + { + var data = string.Empty; + if (url.ToLower().StartsWith("http")) + { + url = url.Replace("&", ""); + if (url.Contains("qpic.cn")) return url; + //HttpHelper http = new HttpHelper(); + //var item = http.GetItem(url); + //item.ResultType = CsharpHttpHelper.Enum.ResultType.Byte; + //data = http.GetHtml(item).ResultByte; + data = url; + } + else + { + //FileInfo aFileInfo = new FileInfo(url); + //using (FileStream fsRead = aFileInfo.Open(FileMode.Open)) + //{ + // int fsLen = (int)fsRead.Length; + // data = new byte[fsLen]; + // fsRead.Read(data, 0, data.Length); + //} + if (File.Exists(url)) + { + try + { + var image = Image.FromFile(url); + //var image = PickBox.ResizeImage(image1, new Size((int)(image1.Width * 0.8), (int)(image1.Height * 0.8))); + data = Common.ConvertImageToBase64(image); + //var sss = Common.ConvertBase64ToImage(data); + } + catch (Exception ex) + { } + } + else + return string.Empty; + } + + var md5 = HttpExtend.GetMD5String(data); + + if (CircleUrlDic.ContainsKey(md5) && !string.IsNullOrWhiteSpace(CircleUrlDic[md5])) + return CircleUrlDic[md5]; + + Queues.Enqueue(data); + _ExchangeAction(); + + var dieTime = DateTime.Now.AddMinutes(15); + do + { + Thread.Sleep(500); + if (CircleUrlDic.ContainsKey(md5)) + { + var result = CircleUrlDic[md5]; + if (string.IsNullOrWhiteSpace(result)) + CircleUrlDic.Remove(md5); + return result; + } + } while (DateTime.Now < dieTime); + } + return urlResult; + } + catch + { + return string.Empty; + } + } + + #endregion + + /// + /// 请求获取群信息 + /// + /// + private void GetGroupInfo(string groupid) + { + try + { + lock (GroupMembers) + { + try + { + WechatPack send = new WechatPack(this); + send.SendServer(PCRobotCMD.getGroupMember, groupid); + } + catch (Exception ex) + { + this.WriteLog(ex.Message); + } + } + } + catch (Exception ex) + { + this.WriteLog($"请求群信息:{ex.Message}"); + } + } + + /// + /// 分析hook服务器过来的事件 + /// + /// + public override void Receive(object obj) + { + //LogHelper.GetSingleObj().Debug("", $"获取到解析后的数据 = {obj.GetType().Name},Uin:{this.User.Uin},{this.User.Nick}({this.WeixinHao})"); + var cmd = string.Empty; + try + { + this.HeartBreakTime = DateTime.Now; + var events = ChatClient.Events; + if (obj.GetType() == typeof(WechatReceiveMsgEvents))//私聊和群聊消息 + { + var evt = obj as WechatReceiveMsgEvents; + cmd = evt.Data.Cmd.ToString(); + if (Friends.ContainsKey(evt.Data.FromUsername)) + { + if (Friends[evt.Data.FromUsername].MsgType == 24 || Friends[evt.Data.FromUsername].MsgType == 8 || Friends[evt.Data.FromUsername].MsgType == 29)//公众号 + return; + } + + if (string.IsNullOrWhiteSpace(evt.Data.FromGroupid)) + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) + { + //bool is_phpone = false; + + Friend friend = null; + friend = this.GetContact(evt.Data.FromUsername); + if (!ChatClient.WXSdkConfig.MsgConvertToFriend && evt.Data.IsSend) + { + return; + //if (evt.Data.IsSend == this.WeixinHao) + //{ + // is_phpone = true; + //} + //is_phpone = evt.Data.IsSend; + } + if (friend == null) + { + this.WriteLog(string.Format("获取用户{0}失败。", evt.Data.FromUsername)); + return; + } + friend.NickName = Util.RemoveEmoji(friend.NickName); + var eventobj = new WXReiceveFriendMsg(this, friend, evt.Data.FromMessage); + eventobj.IsRobot = evt.Data.IsSend; + events.OnEvent(eventobj); + } + } + else + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) + { + var group = this.GetContact(evt.Data.FromGroupid); + if (group == null) + { + this.WriteLog(string.Format("获取群{0}失败.。", evt.Data.FromGroupid)); + return; + } + + GroupMember member = this.GetMember(evt.Data.FromGroupid, evt.Data.FromUsername); + if (member == null) + { + this.WriteLog(string.Format("获取群{0}成员{1}信息失败.。", evt.Data.FromGroupid, evt.Data.FromUsername)); + return; + } + events.OnEvent(new WXReceiveGroupMsg(this, member, group, evt.Data.FromMessage)); + return; + } + } + } + else if (obj.GetType() == typeof(WechatApplyFriendEvents))//申请添加我为好友,需要审核 + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新申请")) + { + var evt = obj as WechatApplyFriendEvents; + cmd = evt.Data.Cmd.ToString(); + events.OnEvent(new WXApplyFriend(this, evt.Data.NewFriendWxid, evt.Data.NewFriendNick, evt.Data.Message, evt.Data.OldFriendWxid, evt.Data.OldFriendNick, evt.Data.Token)); + + #region 这里给通过做准备,把用户信息保存起来 + if (!Friends.ContainsKey(evt.Data.NewFriendWxid)) + { + var reg = Regex.Match(evt.Data.Token, @"smallheadimgurl==""(?<头像>[^""]*?)"""); + var headIMG = string.Empty; + if (reg.Success) headIMG = reg.Groups["头像"].Value; + Friends[evt.Data.NewFriendWxid] = new Friend() { SmallHeadImgUrl = headIMG, BigHeadImgUrl = headIMG, City = string.Empty, Sex = 0, MsgType = 0, NickName = evt.Data.NewFriendNick, Remark = evt.Data.NewFriendNick, UserName = evt.Data.NewFriendWxid, Alias = evt.Data.NewFriendWxid, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = string.Empty, ChatroomVersion = string.Empty }; + } + #endregion + } + } + else if (obj.GetType() == typeof(WechatNewFriendEvents)) + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新好友")) + { + var evt = obj as WechatNewFriendEvents; + cmd = evt.Data.Cmd.ToString(); + + Friend friend = null; + friend = this.GetContact(evt.Data.FromUserName);//这里很大概率获取不到用户的昵称,新用户 + if (friend == null) + { + this.WriteLog(string.Format("获取用户{0}失败。", evt.Data.FromUserName)); + return; + } + friend.NickName = Util.RemoveEmoji(friend.NickName); + events.OnEvent(new WXNewFriend(this, friend)); + } + } + else if (obj.GetType() == typeof(WechatReicevePayEvents))//收到支付 + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("转账")) + { + var evt = obj as WechatReicevePayEvents; + cmd = evt.Data.Cmd.ToString(); + + var friend = GetContact(evt.Data.FromUsername); + if (friend != null) + { + friend.NickName = Util.RemoveEmoji(friend.NickName); + var e = new WXReicevePay(this, friend, evt.Data.Invalidtime, evt.Data.Transferid, evt.Data.Money); + events.OnEvent(e); + } + } + } + else if (obj.GetType() == typeof(WechatNewMemerEvents))//新人入群 + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新群友")) + { + var evt = obj as WechatNewMemerEvents; + cmd = evt.Data.Cmd.ToString(); + + var group = GetContact(evt.Data.GroupId); + if (group == null) return; + if (!string.IsNullOrWhiteSpace(evt.Data.SourceName)) + { + var inviteFriend = GetContact(evt.Data.SourceName); + if (inviteFriend != null) + evt.Data.SourceNick = inviteFriend.NickName; + } + + events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = evt.Data.GroupId, MemberNicks = evt.Data.MemberNick, MemberName = evt.Data.MemberName, SourceNick = Util.RemoveEmoji(evt.Data.SourceNick), SourceName = evt.Data.SourceName, TotalMember = evt.Data.TotalMember }); + } + } + else if (obj.GetType() == typeof(WechatContactListEvents))//获得通讯录列表 + { + var evt = obj as WechatContactListEvents; + cmd = evt.Data.Cmd.ToString(); + FriendsAction = GetFriends; + FriendsAction(evt.Data.Message); + } + else if (obj.GetType() == typeof(WechatGroupMemberEvents))//获得群成员 + { + //var evt = obj as WechatGroupMemberEvents; + //cmd = evt.Data.Cmd.ToString(); + + //GroupMembersAction = GetGroupMembers; + //GroupMembersAction(evt.Data.Message); + } + else if (obj.GetType() == typeof(WechatStatusEvents))//微信状态改变 + { + this.HeartBreakTime = DateTime.Now; + //LogHelper.GetSingleObj().Info("", $"刷新HeartBreakTime = {HeartBreakTime},Uin:{this.User.Uin},{this.User.Nick}({this.WeixinHao})"); + var evt = obj as WechatStatusEvents; + cmd = evt.Cmd.ToString(); + ChangeStatus(evt.Status == PCRobot.Pack.Status.在线 ? WxStatus.在线 : WxStatus.已退出); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("", $"PC服务器消息处理异常:【{cmd}】- {ex.Message},{ex.StackTrace}"); + } + } + + /// + /// 获取指定的用户 + /// + public string GetWxidInfo(string wxid) + { + try + { + WechatPack pack = new WechatPack(this); + return pack.SendServer(PCRobotCMD.getWxidInfo, wxid); + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 退出消息 + /// + /// + public override void LoginOut(string message) + { + //发送指令 强制退出易转发那边的微信 + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.closeWechat, message); + try + { + LogHelper.GetSingleObj().Debug("", $"LoginOut带提示:{this.WeixinHao}"); + } + catch (Exception) + { } + } + + /// + /// 退出登录 + /// + public override void LoginOut() + { + //发送指令 强制退出易转发那边的微信 + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.closeWechat); + try + { + LogHelper.GetSingleObj().Debug("", $"LoginOut不带提示:{this.WeixinHao}"); + } + catch (Exception) + { } + } + + /// + /// 领取转账 + /// + /// + /// + /// + /// + public override int TenPayTransferConfirm(string Invalidtime, string Transferid, string FromUsername) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.getPay, HttpHelper.ObjectToJson(new Dictionary() { { "Invalidtime", Invalidtime }, { "Transferid", Transferid }, { "WxId", FromUsername } }), WechatMsgType.文本, FromUsername); + return 0; + } + + /// + /// 发送卡片 + /// + /// + /// + public override void SendCard(string username, string friendwxid) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.sendCard, friendwxid, WechatMsgType.文本, username); + } + + /// + /// 邀请入群 + /// + /// + /// + /// + public override string InviteIntoGroup(string username, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.sendInviteGroup, groupId, WechatMsgType.文本, username); + return string.Empty; + } + + /// + /// 删除群用户 + /// + /// + /// + /// + public override string DeleteGroupMember(string username, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.deleteGroupMember, username, WechatMsgType.文本, groupId); + return string.Empty; + } + + /// + /// 发送图片 + /// + /// + /// + public override void SendImage(string username, string address) + { + try + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.sendImg, address, WechatMsgType.图片, username); + } + catch (Exception ex) + { + this.WriteLog($"发送图片失败:{ex.Message} - {ex.StackTrace}"); + } + } + + + /// + /// 发送消息 + /// + /// + /// + /// + /// + public override Task SendMessage(string _username, string _message, string _atUsername = "") + { + string username = _username; + string content = _message; + string atUsername = _atUsername; + + return Task.Run(() => + { + if (string.IsNullOrEmpty(content)) return true; + content = content.Replace("\r\n", "\n").Trim().Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Replace("[机器人微信]", this.User.Username); + var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + try + { + foreach (var msg in msgs) + { + var m = msg.Replace("\r\n", "\n").Trim(); + if (string.IsNullOrEmpty(m)) continue; + + var message = m.RandomMess(); + + message = message.Contains("[随机表情]") ? message.Replace("[随机表情]", WXClientImpl_IPAD.FindRandomExpression()) : message; + + //if (message.StartsWith("[延迟=")) + //{ + // var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + // if (reg.Success) + // { + // message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + // Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + // } + //} + message = DelayMess(message); + + ChatClient.Events.OnEvent(new WXSendMessage(this, message, username)); + + WechatPack pack = new WechatPack(this); + + //发送XML消息 + if (message.Trim().ToLower().StartsWith("")) + { + message = $@"{WeixinHao}0{msg.Replace("&", "&")}1Window wechat"; + + pack.SendServer(PCRobotCMD.sendTxt, message, WechatMsgType.文本, username); + //LogHelper.GetSingleObj().Debug("XCX发送小程序", $"机器人:{this.User.Nick}({this.WeixinHao}),{message}"); + continue; + } + + //发送图片消息 + var matchs = Regex.Matches(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + var imageBase = string.Empty; + var image = match.Groups[1].Value; + if (!image.ToLower().Trim().StartsWith("http")) + { + if (File.Exists(image)) + { + double size = new FileInfo(image).Length; + if (size > 1024 * 512) + { + try + { + var img = Util.ReadImageFile(image); + var bitmap = Util.PercentImage(img, img.Width); + var _image = image + Path.GetExtension(image);//压缩图片的地址 + if (Util.YaSuo(bitmap, _image)) + { + imageBase = Util.FileToBase64(_image); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("", $"Common图片压缩异常:{ex.Message} - {ex.StackTrace}"); + imageBase = Util.FileToBase64(image); + } + } + else + imageBase = Util.FileToBase64(image); + } + } + else + imageBase = image; + SendImage(username, imageBase); + } + message = Regex.Replace(message, @"\[图片\=([^\]]+)\]", ""); + message = DelayMess(message); + //发送语音消息 + //matchs = Regex.Matches(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); + //foreach (Match item in matchs) + //{ + //SendVoice(username, item.Groups[1].Value);//PC不能发送语音 + //} + message = Regex.Replace(message, @"\[语音\=([^\]]+)\]", ""); + message = DelayMess(message); + matchs = Regex.Matches(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + //var video = Util.StrToHex(item.Groups[1].Value); + //if (video != null) + //{ + // var video_json = Encoding.UTF8.GetString(video); + // var video_data = CsharpHttpHelper.HttpExtend.JsonToDictionary(video_json); + // if (video_data != null) + // { + // SendCDNInfo(username, video_data["cdnurl"].ToString(), video_data["aeskey"].ToString(), CDNType.发送视频); + // } + //} + var filePath = item.Groups[1].Value; + if (!Regex.IsMatch(filePath, @"^[c-zC-Z]:\\")) continue; + + //if (File.Exists(filePath)) + //{ + // //var base64 = Util.FileToBase64(filePath); + //} + pack.SendServer(PCRobotCMD.sendVideo, filePath, WechatMsgType.视频, username); + } + message = Regex.Replace(message, @"\[视频\=([^\]]+)\]", ""); + message = DelayMess(message); + matchs = Regex.Matches(message, @"\[卡片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + SendCard(username, item.Groups[1].Value == "自己" ? User.Username : item.Groups[1].Value); + } + message = Regex.Replace(message, @"\[卡片\=([^\]]+)\]", ""); + message = DelayMess(message); + if (string.IsNullOrWhiteSpace(message)) continue; + if (message.StartsWith("\r\n")) message = message.Substring("\r\n".Length); + if (message.StartsWith("\n")) message = message.Substring("\n".Length); + + //pack.SendServer(PCRobotCMD.sendTxt, message, WechatMsgType.文本, username); + + pack.SetNextData(new ServerWechatMsg() { Cmd = PCRobotCMD.sendTxt, ToMessage = message, ToMessageType = WechatMsgType.文件, ToUsername = username }); + RunSendMessageQueue(pack); + } + return true; + } + catch (Exception ex) + { + this.WriteLog("SendMessage ERROR:" + ex.Message); + return false; + } + }); + } + + #region 消息发送速度处理 + /// + /// 需要发送的消息队列 + /// + private ConcurrentQueue SendMessageQueue { get; set; } = new ConcurrentQueue(); + private object lock_sendmessage = new object(); + private bool lock_sendmessage_ing = false; + //Thread SendMessageThread; + private int fragmentCount = 0; + private DateTime fragmentTime = DateTime.MinValue; + + private void RunSendMessageQueue(WechatPack sendPack) + { + SendMessageQueue.Enqueue(sendPack); + if (lock_sendmessage_ing) return; + + lock (lock_sendmessage) + { + if (lock_sendmessage_ing) return; + lock_sendmessage_ing = true; + ThreadPool.QueueUserWorkItem(x => + { + try + { + WechatPack pack = null; + while (SendMessageQueue.TryDequeue(out pack)) + { + if (this.Status == WxStatus.在线) + { + pack.SendNextData(); + + #region 消息防止频繁,休眠操作 + if (ChatClient.MessFrequentSleepTime != 0) + { + fragmentCount++; + var totalSeconds = (DateTime.Now - fragmentTime).TotalSeconds;//上次休眠的时间差 + bool rest = totalSeconds > 10; + if (fragmentCount >= 10 && totalSeconds <= 10) + { + rest = true; + Thread.Sleep(ChatClient.MessFrequentSleepTime * 1000); + } + + if (rest) + { + fragmentCount = 1; + fragmentTime = DateTime.Now; + } + } + #endregion + } + } + } + catch (Exception) + { + } + finally + { + lock_sendmessage_ing = false; + } + }); + } + } + + #endregion + + /// + /// 同意添加我为好友 + /// + /// + /// + public override string AgreeAddMe(string token) + { + Console.WriteLine(token); + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.agreeFriend, token, WechatMsgType.文本, string.Empty); + return string.Empty; + } + + /// + /// 删除好友 + /// + /// + /// + public override string DeleteFriend(string username) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.deleteFriend, username, WechatMsgType.文本, string.Empty); + return string.Empty; + } + + /// + /// 修改用户信息 + /// + /// + /// + /// + public override void EditContacts(string username, EditContactsType type, string remark = "") + { + if (type == EditContactsType.备注) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.editContacts, remark, WechatMsgType.文本, username); + } + else if (type == EditContactsType.置顶 || type == EditContactsType.取消置顶) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.stateOpt, type == EditContactsType.置顶 ? "1" : "0", WechatMsgType.文本, username); + } + else + throw new Exception("本协议不支持该操作"); + } + + /// + /// 消息延迟 + /// + /// + public string DelayMess(string message) + { + try + { + message = message.Trim(); + if (message.StartsWith("[延迟=")) + { + var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + } + } + } + catch (Exception ex) + { } + return message; + } + + + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_IPAD.cs b/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_IPAD.cs new file mode 100644 index 0000000..5c65428 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_IPAD.cs @@ -0,0 +1,4165 @@ +using Chat.Framework.Utils; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.IPAD; +using Chat.Framework.WXSdk.UIForm; +using CsharpHttpHelper; +using Google.Protobuf; +using Newtonsoft.Json; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; +using WechatProto; +using static Chat.Framework.WXSdk.Implement.WXClientTool; + + +namespace Chat.Framework.WXSdk.Implement +{ + /// + /// 协议微信 + /// + public class WXClientImpl_IPAD : WeixinBase + { + + /// + /// 分析消息 + /// + /// + private void AnalysisMessage(string result) + { + // Util + result = result.Replace("🔑", "¥"); + result = Util.RemoveEmoji(result); + var list = Util.ConvertJsonToObj(result); + if (list == null) return; + int count = 0; + var guid = Guid.NewGuid(); + // this.WriteLog($"{guid},Async数量{list.Count},排除重复后剩余:{count}",true); + // this.WriteLog(); + + foreach (Dictionary xitem in list) + { + var time = DateTime.Now; + var item = xitem; + string json = Util.ObjectToJson(xitem); + var msgType = int.Parse(xitem["MsgType"].ToString()); + //Console.WriteLine("新消息:" + json); + string md5 = Util.MD5Encrypt(json); + if (this.pack.Contains(md5)) + continue; + if (this.pack.Count > 1000) this.pack.Clear(); + this.pack.Add(md5); + count++; + var method = new Action(delegate () + //Task.Factory.StartNew(delegate () + { + var logStrbs = new StringBuilder(); + try + { + var events = ChatClient.Events; + // int msgType = int.Parse(item["MsgType"].ToString()); + switch (msgType) + { + case 10002://获取 + { + logStrbs.Append("1_"); + string content = item["Content"].ToString(); + var contentreg = Regex.Match(content, @"()"); + if (contentreg.Success) + { + content = contentreg.Groups[1].Value.Replace("\n", "").Replace("\t", "");//.Replace("![CDATA[","").Replace("]]",""); + XmlDocument doc = new XmlDocument(); + doc.LoadXml(content); + var xml = doc.SelectSingleNode("sysmsg"); + var type = xml.Attributes["type"]; + if (type != null) + { + xml = xml.SelectSingleNode(type.InnerText); + switch (type.InnerText) + { + case "NewXmlChatRoomAccessVerifyApplication": + { + WXApplyGroup join = new WXApplyGroup(this); + join.Usernick = Regex.Match(xml.SelectSingleNode("text").InnerText, @"""(.*?)""想邀请").Groups[1].Value; + join.GroupId = xml.SelectSingleNode("RoomName").InnerText; + var link = xml.SelectSingleNode("link"); + join.Reason = link.SelectSingleNode("invitationreason").InnerText; + join.Wxid = link.SelectSingleNode("inviterusername").InnerText; + var memberlist = link.SelectSingleNode("memberlist"); + var nodes = memberlist.SelectNodes("member"); + foreach (XmlNode node in nodes) + { + var member = new WXApplyGroup.ApplyGroupMember() + { + wxid = node.SelectSingleNode("username").InnerText, + headimgurl = node.SelectSingleNode("headimgurl").InnerText, + nickname = node.SelectSingleNode("nickname").InnerText, + quitchatroominfo = node.SelectSingleNode("nickname").InnerText + }; + join.Members.Add(member); + } + ChatClient.Events.OnEvent(join); + } + return; + //case "delchatroommember": + // { + + // } + // return; + } + } + Console.WriteLine(); + } + return; + } + case 51://打开用户的聊天窗口 + { + logStrbs.Append("2_"); + if (item.ContainsKey("Status") && item["Status"].ToString() == "3") + { + var Content = item["Content"].ToString(); + var reg = Regex.Match(Content, $"\n\n{item["ToUserName"]}\n\n"); + if (reg.Success) + { + var friend = GetContact(item["ToUserName"].ToString(), true); + events.OnEvent(new WXOpenWindow(this, friend)); + } + } + break; + } + case 10000://系统消息 + { + logStrbs.Append("3_"); + if (item.ContainsKey("Content")) + { + //{"MsgId":1647047807,"FromUserName":"wxid_8s44kddouuaj21","ToUserName":"wxid_7tki0tapwq2s22","MsgType":10000,"Content":"你已添加了千年老妖,现在可以开始聊天了。","Status":4,"ImgStatus":1,"ImgBuf":null,"CreateTime":1508670253,"MsgSource":"","PushContent":"","NewMsgId":6583959598552732769} + #region 添加好友成功 + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新好友")) + { + var reg = Regex.Match(item["Content"].ToString(), "^你已添加了(.*?),现在可以开始聊天了。$"); + if (reg.Success) + { + var friend = GetContact(item["FromUserName"].ToString(), true); + events.OnEvent(new WXNewFriend(this, friend)); + break; + } + + reg = Regex.Match(item["Content"].ToString(), "^(.*?)刚刚把你添加到通讯录,现在可以开始聊天了。$"); + if (reg.Success) + { + //Thread.Sleep(3000); + Friend friend = null; + for (int i = 0; i < 3; i++) + { + friend = GetContact(item["FromUserName"].ToString(), true); + if (friend != null) break; + Thread.Sleep(1500); + } + //var friend = GetContact(item["FromUserName"].ToString(), true); + //LogHelper_.GetSingleObj().Info("BBBBBBBBBB", $"【{item["FromUserName"].ToString()}】 friend = " + friend); + //if (friend == null) break; + events.OnEvent(new WXNewFriend(this, friend)); + break; + } + } + #endregion + + #region 新成员进群 + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新群友")) + { + var User = this.User.User; + + //你邀请"A 小叮当20 - 不懂回复帮助、A 小叮当12 - 不懂回复帮助、A 小叮当16 - 不懂回复帮助、A 小叮当19 - 不懂回复帮助"加入了群聊 + var groupid = item["FromUserName"].ToString(); + var reg = Regex.Match(item["Content"].ToString(), @"""(?<邀请人>.*?)""邀请""(?<新人>.*?)""加入了群聊"); + if (!reg.Success) + reg = Regex.Match(item["Content"].ToString(), @"(?<邀请人>你)邀请""(?<新人>.*?)""加入了群聊"); + if (!reg.Success) + reg = Regex.Match(item["Content"].ToString(), @"""(?<新人>.*?)""通过扫描""(?<邀请人>.*?)""分享的二维码加入群聊"); + if (!reg.Success) + reg = Regex.Match(item["Content"].ToString(), @"""(?<新人>.*?)""通过扫描(?<邀请人>你)分享的二维码加入群聊"); + if (reg.Success) + { + if (!GroupMemberCache.ContainsKey(groupid)) + { + var gmNew = GetMembers(groupid, true); + if (gmNew != null) + { + if (!GroupMemberCache.ContainsKey(groupid)) + GroupMemberCache.Add(groupid, gmNew.ToList()); + + var group = GetContact(groupid); + if (group == null) return; + events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = reg.Groups["新人"].Value, SourceNick = reg.Groups["邀请人"].Value == "你" ? Encoding.UTF8.GetString(User.Nickname.ToArray()) : reg.Groups[1].Value, SourceName = reg.Groups["邀请人"].Value == "你" ? User.Userame : "" }); + return; + } + } + + if (!SyncGroups.ContainsKey(groupid)) + { + SyncGroups.Add(groupid, groupid); + SyncGroup(); + } + break; + } + } + #endregion + } + return; + } + case 37://通过名片添加好友 + { + logStrbs.Append("4_"); + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新申请")) + { + string content = item["Content"].ToString(); + var reg = Regex.Match(content, @"fromusername=""(?.*?)""[\w\W]+fromnickname=""(?.*?)""[\w\W]+content=""(?.*?)""[\w\W]+sourceusername=""(?.*?)""[\w\W]+sourcenickname=""(?.*?)"""); + if (reg.Success) + { + events.OnEvent(new WXApplyFriend(this, reg.Groups["newFriendWxid"].ToString(), reg.Groups["newFriendNick"].ToString(), reg.Groups["newFriendMsg"].ToString(), reg.Groups["sourceFriendWxid"].ToString(), reg.Groups["sourceFriendNick"].ToString(), content)); + } + } + } + return; + case 1://文本消息 + case 42: + case 49: + case 47://表情动画 + { + logStrbs.Append("5_"); + if (item["FromUserName"].ToString() == "newsapp") return; + if (item["FromUserName"].ToString() == "weixin") return; + if (item["FromUserName"].ToString().StartsWith("gh_")) return; + + if (item["Content"].ToString().Contains("[CDATA[微信转账]]") && item["FromUserName"].ToString() != User.Username) + { + logStrbs.Append("5.1_"); + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("转账")) + { + logStrbs.Append("5.2_"); + var content = item["Content"].ToString(); + Console.WriteLine(content); + logStrbs.Append("5.3_"); + var transcationid = Regex.Match(content, "transferid\u003e\u003c!\\[CDATA\\[(\\d+)\\]\\]"); + var invalidtime = Regex.Match(content, "invalidtime\u003e\u003c!\\[CDATA\\[(\\d+)\\]\\]"); + var money = Regex.Match(content, ""); + var fromusername = item["FromUserName"].ToString(); + logStrbs.Append("5.4_"); + var friend = GetContact(fromusername); + logStrbs.Append("5.5_"); + if (friend != null && transcationid.Success && invalidtime.Success && money.Success) + { + logStrbs.Append("5.6_"); + var e = new WXReicevePay(this, friend, invalidtime.Groups[1].Value, transcationid.Groups[1].Value, double.Parse(money.Groups[1].Value)); + logStrbs.Append("5.7_"); + ChatClient.Events.OnEvent(e); + return; + } + } + } + logStrbs.Append("5.8_"); + if (item["Content"].ToString() == "我通过了你的朋友验证请求,现在我们可以开始聊天了" && item.ContainsKey("MsgSource") && string.IsNullOrWhiteSpace(item["MsgSource"].ToString())) + { + logStrbs.Append("5.9_"); + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新好友")) + { + logStrbs.Append("5.10_"); + var UserName = item["FromUserName"].ToString(); + logStrbs.Append("5.11_"); + if (!string.IsNullOrWhiteSpace(UserName)) + { + logStrbs.Append("5.12_"); + var friend = GetContact(UserName, true); + logStrbs.Append("5.13_"); + events.OnEvent(new WXNewFriend(this, friend)); + return; + } + } + } + + logStrbs.Append("5.14_"); + var reg = Regex.Match(item["FromUserName"].ToString(), "^(\\d+@chatroom)$"); + bool is_phpone = false; + logStrbs.Append("5.15_"); + if (item["FromUserName"].ToString() == User.Username) + { + logStrbs.Append("5.16_"); + if (!reg.Success && item["ToUserName"].ToString().Contains("@")) return; + else if (ChatClient.WXSdkConfig.MsgConvertToFriend) + { + logStrbs.Append("5.17_"); + item["FromUserName"] = item["ToUserName"].ToString(); + is_phpone = true; + } + } + logStrbs.Append("5.18_"); + if (reg.Success)//群消息 + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) + { + logStrbs.Append("5.19_"); + string groupid = reg.Groups[1].Value; + + var Content = System.Text.RegularExpressions.Regex.Match(item["Content"].ToString(), "^(.*?):\\s+([\\w\\W]+)$"); + logStrbs.Append("5.20_"); + var group = this.GetContact(groupid); + if (group == null) + { + logStrbs.Append("5.21_"); + this.WriteLog(string.Format("获取群{0}失败。", groupid)); + return; + } + logStrbs.Append("5.22_"); + #region 群用户缓存 + if (!GroupMemberCache.ContainsKey(groupid)) + { + logStrbs.Append("5.23_"); + var gmNew = GetMembers(groupid, true); + if (gmNew != null) + { + logStrbs.Append("5.24_"); + if (!GroupMemberCache.ContainsKey(groupid)) + GroupMemberCache.Add(groupid, gmNew.ToList()); + } + } + #endregion + logStrbs.Append("5.25_"); + string wxid = Content.Groups[1].Value; + //string messsage = Content.Groups[2].Value.Replace("\n", ""); + string messsage = Content.Groups[2].Value; + logStrbs.Append("5.26_"); + GroupMember member = this.GetMember(groupid, wxid); + if (member == null) + { + logStrbs.Append("5.27_"); + this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", groupid, wxid)); + break; + } + logStrbs.Append("5.28_"); + events.OnEvent(new WXReceiveGroupMsg(this, member, group, messsage)); + return; + } + } + else + { + logStrbs.Append("5.29_"); + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) + { + logStrbs.Append("5.30_"); + string wxid = item["FromUserName"].ToString(); + string messsage = item["Content"].ToString(); + + var friend = this.GetContact(wxid); + //if (friend == null) + //{ + // //this.WriteLog(string.Format("获取微信好友{0}信息失败。", wxid)); + // //break; + + // var nickname = item["PushContent"].ToString().Replace(": " + messsage, "").Trim(); + // friend = new Friend() { Ticket = "", Alias = wxid, UserName = wxid, MsgType = 1, ExtInfo = "", NickName = nickname, ContactType = 0, City = "Chaoyang", ChatRoomOwner = "", Remark = "", Sex = 1, Signature = "", ChatroomVersion = "0", id = 0, Province = "BeiJing", BigHeadImgUrl = "", SmallHeadImgUrl = "" }; + //} + logStrbs.Append("5.31_"); + var eventobj = new WXReiceveFriendMsg(this, friend, messsage); + logStrbs.Append("5.32_"); + eventobj.IsRobot = is_phpone; + events.OnEvent(eventobj); + return; + } + } + break; + } + case 3://收到图片 + { + logStrbs.Append("6_"); + #region 历史 + //if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("图片")) + //{ + // var friend = GetContact(item["FromUserName"].ToString()); + // if (friend == null) return; + // var Content = item["Content"].ToString(); + // var imagePath = DownlowdImage(int.Parse(item["MsgId"].ToString()), friend.UserName, int.Parse(Regex.Match(Content, " length=\"(\\d+)").Groups[1].Value)); + + // if (!string.IsNullOrEmpty(imagePath)) + // { + // #region 缓存CDN数据 + // if (ChatClient.ImageCDNs.Count >= 10000)//到达一定数量清空数据 + // ChatClient.ImageCDNs.Clear(); + + // var MD5Hash = FileTools.GetMD5Hash(imagePath); + // if (!ChatClient.ImageCDNs.ContainsKey(MD5Hash)) + // { + // var reg = Regex.Match(Content, @" aeskey=""(?[^""]+)"".+?cdnthumburl=""(?[^""]+)"""); + // if (reg.Success) + // { + // var aeskey = reg.Groups["aeskey"].Value; + // var cdnthumburl = reg.Groups["cdnthumburl"].Value; + // ChatClient.ImageCDNs.Add(MD5Hash, new { aeskey = aeskey, cdnurl = cdnthumburl }); + // } + // } + // #endregion + + // if (!friend.UserName.Contains("@")) + // { + // if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) + // { + // bool is_phpone = false; + + // if (ChatClient.WXSdkConfig.MsgConvertToFriend) + // { + // if (item.ContainsKey("FromUserName") && item["FromUserName"].ToString() == User.Username) + // { + // if (item.ContainsKey("ToUserName")) + // { + // string wxid = item["ToUserName"].ToString(); + // friend = this.GetContact(wxid); + // is_phpone = true; + // } + // } + // } + + // var eventobj = new WXReiceveFriendMsg(this, friend, $"[图片={imagePath}]"); + // eventobj.IsRobot = is_phpone; + // events.OnEvent(eventobj); + // } + // } + // else + // { + // if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) + // { + // var groupid = friend.UserName; + // var reg = Regex.Match(Content, "^(.*?):\\s+([\\w\\W]+)$"); + // var group = this.GetContact(groupid); + // if (group == null) + // { + // this.WriteLog(string.Format("获取群{0}失败。", groupid)); + // return; + // } + // string wxid = reg.Groups[1].Value; + // string messsage = $"[图片={imagePath}]"; + // GroupMember member = this.GetMember(groupid, wxid); + // if (member == null) + // { + // this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", groupid, wxid)); + // break; + // } + // events.OnEvent(new WXReceiveGroupMsg(this, member, group, messsage)); + // return; + // } + // } + // } + //} + #endregion + + #region 新 + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("图片")) + { + logStrbs.Append("6.1_"); + var friend = GetContact(item["FromUserName"].ToString()); + if (friend == null) return; + var Content = item["Content"].ToString(); + logStrbs.Append("6.2_"); + #region 将图片的信息保存起来 + var ContentTmp = Content; + if (friend.UserName.Contains("@")) + { + logStrbs.Append("6.3_"); + var reg = Regex.Match(Content, "^.*?:\\s+([\\w\\W]+)$"); + if (reg.Success) + ContentTmp = reg.Groups[1].Value; + } + CDNImageMsgInfo imgInfo = GetCDNImage(ContentTmp); + logStrbs.Append("6.4_"); + var cdnstr = Util.HexToStr(Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(imgInfo))); + #endregion + logStrbs.Append("6.5_"); + if (!friend.UserName.Contains("@")) + { + logStrbs.Append("6.6_"); + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) + { + logStrbs.Append("6.7_"); + bool is_phpone = false; + + if (ChatClient.WXSdkConfig.MsgConvertToFriend) + { + logStrbs.Append("6.8_"); + if (item.ContainsKey("FromUserName") && item["FromUserName"].ToString() == User.Username) + { + logStrbs.Append("6.9_"); + if (item.ContainsKey("ToUserName")) + { + logStrbs.Append("6.10_"); + string wxid = item["ToUserName"].ToString(); + logStrbs.Append("6.11_"); + friend = this.GetContact(wxid); + logStrbs.Append("6.12_"); + is_phpone = true; + } + } + } + + var eventobj = new WXReiceveFriendMsg(this, friend, $"[图片={cdnstr}]"); + logStrbs.Append("6.13_"); + eventobj.IsRobot = is_phpone; + logStrbs.Append("6.14_"); + events.OnEvent(eventobj); + } + } + else + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) + { + logStrbs.Append("6.15_"); + var groupid = friend.UserName; + var reg = Regex.Match(Content, "^(.*?):\\s+([\\w\\W]+)$"); + logStrbs.Append("6.16_"); + Content = reg.Groups[2].Value; + logStrbs.Append("6.17_"); + var group = this.GetContact(groupid); + logStrbs.Append("6.18_"); + if (group == null) + { + logStrbs.Append("6.19_"); + this.WriteLog(string.Format("获取群{0}失败。", groupid)); + return; + } + + #region 群用户缓存 + if (!GroupMemberCache.ContainsKey(groupid)) + { + logStrbs.Append("6.20_"); + var gmNew = GetMembers(groupid, true); + logStrbs.Append("6.21_"); + if (gmNew != null) + { + logStrbs.Append("6.22_"); + if (!GroupMemberCache.ContainsKey(groupid)) + GroupMemberCache.Add(groupid, gmNew.ToList()); + } + } + #endregion + logStrbs.Append("6.23_"); + string wxid = reg.Groups[1].Value; + logStrbs.Append("6.24_"); + string messsage = $"[图片={cdnstr}]"; + logStrbs.Append("6.25_"); + GroupMember member = this.GetMember(groupid, wxid); + logStrbs.Append("6.26_"); + if (member == null) + { + logStrbs.Append("6.27_"); + this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", groupid, wxid)); + break; + } + logStrbs.Append("6.28_"); + events.OnEvent(new WXReceiveGroupMsg(this, member, group, messsage)); + } + } + } + #endregion + break; + } + case 43://收到视频 + { + logStrbs.Append("7_"); + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("视频")) + { + if (!item.ContainsKey("Content")) return; + string content = item["Content"].ToString(); + + var reg = Regex.Match(content, "aeskey=\"([^\"]+).*?cdnthumburl=\"([^\"]+)"); + if (reg.Success) + { + var aeskey = reg.Groups[1].Value; + var cdnurl = reg.Groups[2].Value; + var cdnstr = Util.HexToStr(Encoding.UTF8.GetBytes(HttpHelper.ObjectToJson(new { aeskey = aeskey, cdnurl = cdnurl }))); + ChatClient.Events.OnEvent(new WXWriteLog(this) { Message = $"来自{item["PushContent"]}:[视频={cdnstr}]" }); + + if (item.ContainsKey("FromUserName")) + { + var fromUserName = item["FromUserName"].ToString(); + if (!fromUserName.Contains("@")) + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) + { + var friend = GetContact(fromUserName, false); + var eventobj = new WXReiceveFriendMsg(this, friend, $"[视频={cdnstr}]"); + events.OnEvent(eventobj); + } + } + else + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) + { + var Content = Regex.Match(item["Content"].ToString(), "^(.*?):\\s+([\\w\\W]+)$"); + var group = this.GetContact(fromUserName); + if (group == null) + { + this.WriteLog(string.Format("获取群{0}失败。", fromUserName)); + return; + } + + #region 群用户缓存 + if (!GroupMemberCache.ContainsKey(fromUserName)) + { + var gmNew = GetMembers(fromUserName, true); + if (gmNew != null) + GroupMemberCache.Add(fromUserName, gmNew.ToList()); + } + #endregion + + string wxid = Content.Groups[1].Value; + string messsage = $"[视频={cdnstr}]"; + GroupMember member = this.GetMember(fromUserName, wxid); + if (member == null) + { + this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", fromUserName, wxid)); + break; + } + events.OnEvent(new WXReceiveGroupMsg(this, member, group, messsage)); + return; + } + } + } + } + } + break; + } + default: + return; + } + //47 动画表情 1 文本消息 + } + catch (Exception ex) + { + this.WriteLog("解析消息异常->" + ex.Message + "-" + ex.StackTrace + " - " + logStrbs); + } + }); + method.BeginInvoke(null, null); + Thread.Sleep(5); + } + } + + #region + + //private void NewMemberEvents(EventManage events, Friend group, string groupid, string membernicks, string sourcenick) + //{ + // try + // { + // var newNick = string.Empty; + // var newName = string.Empty; + + // var sourceNick = string.Empty; + // var sourceName = string.Empty; + // if (sourcenick == "你") + // { + // sourceName = this.User.Username; + // sourceNick = this.User.Nick; + // } + // else + // { + // sourceNick = sourcenick; + // } + // var msTmp = GetMembers(groupid); + // var ms = GetMembers(groupid, true); + // if (ms == null) return; + // #region 没有、分隔的昵称(就判断为只有一个用户进群) + // if (!membernicks.Contains("、")) + // { + // #region 判断昵称 + // var equals = ms.Where(f => Util.RemoveEmoji(f.NickName) == membernicks).ToList(); + // if (equals.Count != 0) + // { + // if (!string.IsNullOrWhiteSpace(sourceName)) + // { + // if (equals.Count == 1) + // { + + // if (equals[0].InviterUserName == sourceName) + // { + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = equals[0].Username, SourceNick = sourceNick, SourceName = sourceName }); + // return; + // } + // else + // { + + + // } + // } + // else + // { + // //多个用户名称一样 + // var tmps = equals.Where(f => f.InviterUserName == sourceName).ToList(); + // if (tmps.Count == 1) + // { + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = tmps[0].Username, SourceNick = sourceNick, SourceName = sourceName }); + // return; + // } + + // } + // } + // else + // { + + // } + // } + // #endregion + // } + // #endregion + // //else + // { + // #region 比较两个集合的差 + + // if (msTmp == null) return; + // //获取缓存中不存在的用户集合 + // var result = ms.Where(a => msTmp.FirstOrDefault(b => b.Username == a.Username) == null).ToList(); + // if (result.Count == 0) + // result = ms.ToList(); + // if (result.Count != 0) + // { + // if (!membernicks.Contains("、")) + // { + // if (!string.IsNullOrWhiteSpace(sourceName)) + // { + // var equals = result.Where(f => f.InviterUserName == sourceName).ToList(); + // if (equals.Count == 1) + // { + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = equals[0].Username, SourceNick = sourceNick, SourceName = sourceName }); + // return; + // } + // } + // else + // { + // var tmps = msTmp.Where(f => Util.RemoveEmoji(f.NickName) == sourceNick).Select(f => f.Username).ToList(); + // if (tmps.Count == 0) + // { + // tmps = Friends.Where(f => f.Value.Remark == sourceNick).Select(f => f.Key).Where(f => !f.Contains("@")).ToList(); + + // } + // if (tmps.Count != 0) + // { + // if (tmps.Count == 1) + // { + // var InviterUserName = tmps[0]; + // var nickTmps = result.Where(f => Util.RemoveEmoji(f.NickName) == membernicks && f.InviterUserName == InviterUserName).ToList(); + // if (nickTmps.Count == 1) + // { + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = nickTmps[0].Username, SourceNick = sourceNick, SourceName = sourceName }); + // return; + // } + // } + // else + // { + // //tmps.FirstOrDefault(f => f.InviterUserName == tmps.FirstOrDefault() != null) + // var nickTmps = result.Where(f => Util.RemoveEmoji(f.NickName) == membernicks && tmps.FirstOrDefault(d => d == f.InviterUserName) != null).ToList(); + // if (nickTmps.Count == 1) + // { + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, MemberName = nickTmps[0].Username, SourceNick = sourceNick, SourceName = sourceName }); + // return; + // } + // } + // } + // } + // } + // else + // { + // var mnicks = "、" + membernicks + "、"; + // if (!string.IsNullOrWhiteSpace(sourceName)) + // { + // var userTmps = result.Where(f => f.InviterUserName == sourceName).ToList(); + // if (userTmps.Count != 0) + // { + // //var newTmps = userTmps.Where(f => (membernicks + "、").Contains(f.NickName + "、")).ToList(); + // foreach (var item in userTmps) + // { + // if (mnicks.Contains("、" + Util.RemoveEmoji(item.NickName) + "、")) + // { + // var count = userTmps.Count(f => Util.RemoveEmoji(f.NickName) == Util.RemoveEmoji(item.NickName)); + // if (count == 1) + // { + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = item.NickName, MemberName = item.Username, SourceNick = sourceNick, SourceName = sourceName }); + // Thread.Sleep(600); + // } + // else + // { + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = Util.RemoveEmoji(item.NickName), SourceNick = sourceNick }); + // } + // } + // } + // return; + // } + // } + // else + // { + // // + // var sourceTmps = ms.Where(f => Util.RemoveEmoji(f.NickName) == sourceNick).Select(f => f.Username).ToList(); + // if (sourceTmps.Count == 0) + // { + // //获取数据中的用户数据 和 缓存中的好友数据 + // sourceTmps = Friends.Where(f => Util.RemoveEmoji(f.Value.Remark) == sourceNick).Select(f => f.Key).Where(f => !f.Contains("@")).ToList(); + + // } + + + // //包含的昵称用户集合 + // var userTmps = result.Where(f => mnicks.Contains("、" + Util.RemoveEmoji(f.NickName) + "、")).ToList(); + // if (userTmps.Count != 0) + // { + // for (int i = 0; i < userTmps.Count; i++) + // { + // var nickTmps = ms.Where(f => f.Username == userTmps[i].Username).ToList(); + + // var user = nickTmps.FirstOrDefault(f => sourceTmps.FirstOrDefault(d => d == f.InviterUserName) != null);//这里邀请人不查询多条件符合 + // if (user != null) + // { + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = Util.RemoveEmoji(user.NickName), MemberName = user.Username, SourceNick = sourceNick, SourceName = sourceName }); + // Thread.Sleep(600); + // } + // //else + // //{ + + // //} + // } + // return; + // } + // } + // return; + // } + // //events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, SourceNick = sourceNick }); + // } + // #endregion + // } + // { + // #region + + // #endregion + // } + // events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = membernicks, SourceNick = sourceNick }); + // } + // catch (Exception ex) + // { + // this.WriteLog("新群用户解析异常->" + ex.Message + " - " + ex.StackTrace); + // } + //} + + #endregion + + #region 非及时通知新用户 + /// + /// 群用户缓存 + /// + private Dictionary> GroupMemberCache = null; + + private List isRunGroup = new List(); + + /// + /// 保存需要同步的群号 + /// + private Dictionary SyncGroups = new Dictionary(); + + /// + /// 同步群(群新用户事件) + /// + private void SyncGroup() + { + try + { + if (SyncGroups.Count != 0) + { + var groupids = SyncGroups.Keys.ToList(); + for (int i = 0; i < groupids.Count; i++) + { + var groupid = groupids[i]; + if (Util.GetCache(groupid)) + continue; + SyncGroups.Remove(groupid); + Util.SetCache(groupid, 60); + FlushGroup(groupid); + } + } + } + catch (Exception ex) + { } + } + + /// + /// 刷新群用户,生成新用户事件 + /// + /// + private void FlushGroup(string groupid) + { + try + { + if (isRunGroup.Contains(groupid)) return; + isRunGroup.Add(groupid); + if (!GroupMemberCache.ContainsKey(groupid)) + { + var gmNew = GetMembers(groupid, true); + if (gmNew != null && !GroupMemberCache.ContainsKey(groupid)) + GroupMemberCache.Add(groupid, gmNew.ToList()); + } + if (GroupMemberCache.ContainsKey(groupid)) + { + var gMembers = GroupMemberCache[groupid]; + if (gMembers.Count != 0) + { + var gmOld = GroupMemberCache[groupid]; + var gmNew = GetMembers(groupid, true); + if (gmNew != null) + { + GroupMemberCache[groupid] = gmNew.ToList(); + + var jiaojis = gmNew.Where(a => gmOld.FirstOrDefault(b => b.Username == a.Username) == null).ToList(); + //if (jiaojis.Count == 0) + // jiaojis = gmNew.ToList(); + if (jiaojis.Count == 0) return; + var group = GetContact(groupid); + if (group != null) + { + foreach (var item in jiaojis) + { + Friend inviter = null; + if (!string.IsNullOrWhiteSpace(item.InviterUserName)) + inviter = GetContact(item.InviterUserName); + ChatClient.Events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = groupid, MemberNicks = item.NickName, MemberName = item.Username, SourceNick = item.InviterUserName == null ? string.Empty : inviter.NickName, SourceName = item.InviterUserName }); + Thread.Sleep(600); + } + } + } + } + } + } + catch (Exception ex) + { } + finally + { + try + { + isRunGroup.Remove(groupid); + } + catch (Exception) + { } + } + } + + #endregion + + public override string ToString() + { + + if (!string.IsNullOrEmpty(WeixinHao) && this.User != null) + { + //var data = User.Data; + //var host = Host; + if (this.Host != null && this.Socket != null && !string.IsNullOrEmpty(this.Socket.ServerIp)) this.Host.BindLongip(this.Socket.ServerIp); + var obj = new + { + data = User.Data, + host = Host, + username = WeixinHao, + password = Password, + login_type = (int)this.LoginDeviceType + }; + return CsharpHttpHelper.HttpHelper.ObjectToJson(obj); + } + return base.ToString(); + } + + #region 删除好友 + /// + /// 删除好友(可以用户清理僵尸粉用) + /// + /// 微信id + /// + public override string DeleteFriend(string username) + { + try + { + WechatPack send = new WechatPack(this);//创建发送对象 + var result = send.Send(WechatCmd.删除好友, new { Cmdid = 7, CmdBuf = username }); + if (this.Friends.ContainsKey(username)) this.Friends.Remove(username); + return string.Empty; + } + catch (Exception ex) + { + return ex.Message; + } + } + + ///// 删除好友 + ///// 老版本的删除僵尸粉 + ///// + ///// + //public void DeleteFriend(Friend friend) + //{ + // try + // { + // string payloadJson = "{\"Cmdid\":7,\"CmdBuf\":\"" + friend.UserName + "\"}"; + // WechatPacket send = new WechatPacket(this); + // var data = send.SendRpc(new BaseMsg + // { + // Cmd = 681, + // User = this.User, + // Payloads = ByteString.CopyFrom(Encoding.UTF8.GetBytes(payloadJson)) + // }); + // data = send.SendRpc(data); + // var msg = Encoding.UTF8.GetString(data); + // Console.WriteLine(msg); + // if (this.Friends.ContainsKey(friend.UserName)) + // this.Friends.Remove(friend.UserName); + // } + // catch (Exception ex) + // { + // EventManage.OnEvent(this, ex.Message); + // } + //} + #endregion + + #region 邀请入群 + /// + /// 邀请入群 + /// + /// 用户wxid + /// 群id + /// + public override string InviteIntoGroup(string username, string groupId) + { + try + { + //WechatPack send = new WechatPack(this);//创建发送对象 + //var result = send.SendAll(WechatCmd.删除好友, true, new { Cmdid = 7, CmdBuf = username }); + //var msg = Encoding.UTF8.GetString(result); + //Console.WriteLine(msg); + //if (this.Friends.ContainsKey(username)) this.Friends.Remove(username); + //return msg; + + WechatPack send = new WechatPack(this);//创建发送对象 + var result = send.Send(WechatCmd.邀请入群, new { ChatRoom = groupId, Username = username }); + var msg = Encoding.UTF8.GetString(result); + + Console.WriteLine("msg = " + msg); + return msg; + + //Console.WriteLine(msg); + + //string payloadJson = "{\"ChatRoom\":\"" + tb_ToUsername.Text + "\",\"Username\":\"" + tb_AtUserlist.Text + "\"}"; + //WechatMsg InviteChatroomUserReq = new WechatMsg + //{ + // Token = ConstProtocol.MachineCode, + // Version = ConstProtocol.Version, + // TimeStamp = Utils.Time_Stamp(), + // IP = ClientIP, + // BaseMsg = new BaseMsg + // { + // Cmd = 610, + // User = vUser, + // Payloads = ByteString.CopyFrom(Encoding.UTF8.GetBytes(payloadJson)) + // } + //}; + //WechatMsg InviteChatroomUserRsp = client.HelloWechat(InviteChatroomUserReq, authHeader); + + //byte[] body = InviteChatroomUserRsp.BaseMsg.Payloads.ToByteArray(); + //byte[] buffers; + //using (WebClient c = new WebClient()) + //{ + // buffers = c.UploadData("http://" + shortServer + InviteChatroomUserRsp.BaseMsg.CmdUrl, body); + //} + ////短链接解包判定 + //if (buffers[0] != 191) + //{ + // Console.WriteLine("未知包:{0}", Utils.HexToStr(buffers)); + // return; + // //说明返回wx出错 + //} + } + catch (Exception ex) + { + return ex.Message; + } + } + #endregion + + public override string DeleteGroupMember(string username, string groupId) + { + WechatPack send = new WechatPack(this);//创建发送对象 + var result = send.Send(WechatCmd.删除群用户, new { ChatRoom = groupId, Username = username }); + var msg = Encoding.UTF8.GetString(result); + + Console.WriteLine("msg = " + msg); + return msg; + } + + private static string GetComputerName() + { + try + { + return System.Environment.GetEnvironmentVariable("ComputerName"); + } + catch + { + return "unknow"; + } + } + + public WXClientImpl_IPAD(string wei_xin_hao) : this() + { + + SetWeixinHao(wei_xin_hao); + this.DeviceName = WeixinHao + "_" + GetComputerName(); + + } + public WXClientImpl_IPAD(string WeixinHao, string data) : this() + { + this.DeviceName = WeixinHao + "_" + GetComputerName(); + var _data = Util.ConvertJsonToDic(data); + var _host = _data["host"] as Dictionary; + + this.Host = new WechatHost(); + var _list = _host["LongServerList"] as ArrayList; + foreach (string item in _list) this.Host.LongServerList.Add(item); + //Socket.UpdateServerIp(this.Host.LongServerList, true); + + + _list = _host["ShortServerList"] as ArrayList; + foreach (string item in _list) this.Host.ShortServerList.Add(item); + //Socket.UpdateServerIp(this.Host.ShortServerList, false); + + this.Password = _data["password"] != null ? _data["password"].ToString() : string.Empty; + this.User = new WeixinBaseUser(_data["data"].ToString()); + if (_data.ContainsKey("login_type")) + { + this.LoginDeviceType = (LoginDeviceType)int.Parse(_data["login_type"].ToString()); + } + this.UUID = Util.MD5Encrypt(User.Username); + SetWeixinHao(WeixinHao); + } + private string Ime; + internal void SetWeixinHao(string wxh) + { + if (string.IsNullOrEmpty(wxh)) return; + this.WeixinHao = wxh; + + if (string.IsNullOrEmpty(this.DeviceId)) + { + var WXGetDeviceResult = new WXGetDevice(this); + ChatClient.Events.OnEvent(WXGetDeviceResult); + this.DeviceId = WXGetDeviceResult.DeviceInfo; + } + + if ((!this.DeviceId.StartsWith("62") && !this.DeviceId.EndsWith("7f"))) + { + Ime = Util.MD5Encrypt(WeixinHao + this.DeviceId); + this.DeviceId = SixTwoData(Ime); + } + + } + #region 功能代码 + + + + /// + /// 刷新通讯录信息(获取好友列表),刷新状态[true为更新中] + /// + public bool IsRefreshContact { get; private set; } + private void GetContact(string[] wxid) + { + _GetContact(string.Join(",", wxid)); + } + private void _GetContact(string wxid) + { + try + { + // string payloadJson = "{\"UserNameList\":\"" + wxid + "\"}"; + WechatPack send = new WechatPack(this); + byte[] buffers = CGetContact(User.User, Encoding.UTF8.GetBytes(CsharpHttpHelper.HttpHelper.ObjectToJson(new { UserNameList = wxid, Chatroomid = "" }))); + int Seq = Util.ReadInt(buffers, 12); + var data = send.SendWx(buffers, Seq); + if (data == null) return; + byte[] encodeBuf = new byte[data.Length - 16];//提取长连接的body 去掉头16个字节 + Buffer.BlockCopy(data, 16, encodeBuf, 0, data.Length - 16); + data = CUnPackGetcontact(User.User, encodeBuf); + + string text = Encoding.UTF8.GetString(data); + //System.Configuration.ConfigurationManager.AppSettings["OEM"] + + text = Util.RemoveEmoji(text); + Friend[] frds = Util.ConvertJsonToObj(text) as Friend[]; + // Console.WriteLine(text); + foreach (Friend item in frds) + { + this.Friends[item.UserName] = item; + } + Console.WriteLine(); + } + catch (Exception) { } + } + + /// + /// 发送卡片消息 + /// + /// + /// + + public override void SendCard(string username, string friendwxid) + { + if (friendwxid.Contains("@chatroom") || friendwxid.Contains("@im.chatroom")) + { + InviteIntoGroup(username, friendwxid); + } + else + { + //WechatPack pack = new WechatPack(this); + //var data = pack.SendAll(WechatCmd.发送消息, false,send); + + var friend = GetContact(friendwxid); + if (friend == null) return; + string str = $""; + var sendJson = new + { + ToUserName = username, + AppId = "", + Type = 42, + Content = str + }; + var temp_pack = new WechatPack(this); + temp_pack.SendAll(WechatCmd.发送文本消息, false, sendJson); + } + } + + /// + /// 获得好友或群组信息 + /// + public override Friend GetContact(string wxid, bool refresh = false) + { + lock (this.Friends) + { + if (refresh || !Friends.ContainsKey(wxid)) + _GetContact(wxid); + if (Friends.ContainsKey(wxid)) return Friends[wxid]; + else + { + return ChatClient.GetDBWechatFriend(wxid); + } + } + } + + /// + /// 刷新通讯录信息(获取好友列表) + /// + public override void RefreshContact(Action method = null) + { + //暂时取消刷新通讯录 + //return; + if (IsRefreshContact) return; + IsRefreshContact = true; + ThreadPool.QueueUserWorkItem(f => + { + bool is_error = false; + + List users = new List(); + try + { + WriteLog("正在刷新通讯录详情..."); + int CurrentWxcontactSeq = 0; + int CurrentChatRoomContactSeq = 0; + Next: + var payloadJson = new + { + CurrentWxcontactSeq = CurrentWxcontactSeq,//初始为0 + CurrentChatRoomContactSeq = CurrentChatRoomContactSeq// 初始为0 + }; + WechatPack send = new WechatPack(this); + var data = send.Send(WechatCmd.读取通信录, payloadJson); + data = send.Analysis(data); + string text = Encoding.UTF8.GetString(data); + var dic = Util.ConvertJsonToDic(text); + #region 一次20 + var count = 8; + var list = dic["UsernameLists"] as ArrayList; + if (list == null || list.Count == 0) + { + if (users.Count > 0) + { + int number = users.Count / count; + if (users.Count % count != 0) number++; + int yu = users.Count % count; + int sum = 0; + for (int i = 0; i < number; i++) + { + List temp = new List(); + for (int j = 0; j < count; j++) + { + if (this.Status != WxStatus.在线) return; + int index = i * count + j; + if (users.Count == (index)) break; + sum++; + temp.Add(users[index]); + } + + if ((i + 1) != number) + { + this.WriteLog(string.Format("读取通讯录详情,{0}/{1}。", sum, users.Count)); + GetContact(temp.ToArray()); + Thread.Sleep(600); + } + else + { + this.WriteLog(string.Format("读取通讯录详情,{0}/{1}。", sum, users.Count)); + GetContact(temp.ToArray()); + } + temp.Clear(); + } + } + return; + } + else + { + foreach (Dictionary item in list) + { + //if (item["Username"].ToString().EndsWith("@chatroom")) + // users.Add(item["Username"].ToString()); + users.Add(item["Username"].ToString()); + } + } + + #endregion + if (this.Status != WxStatus.在线) return; + CurrentWxcontactSeq = int.Parse(dic["CurrentWxcontactSeq"].ToString()); + CurrentChatRoomContactSeq = int.Parse(dic["CurrentChatRoomContactSeq"].ToString()); + if (CurrentWxcontactSeq != 0 || CurrentChatRoomContactSeq != 0) + { + Thread.Sleep(600); + goto Next; + } + } + catch (Exception) + { + is_error = true; + } + finally + { + IsRefreshContact = false; + this.WriteLog(string.Format("读取通讯录完成!")); + + #region 群列表初始化 + var groupTmps = users.Where(z => z.Contains("@chatroom")).ToList(); + if (groupTmps.Count != 0) + { + foreach (var item in groupTmps) + { + if (!GroupMemberCache.ContainsKey(item)) + { + var members = GetMembers(item, true); + if (members != null && members.Length != 0) + GroupMemberCache[item] = members.ToList(); + Thread.Sleep(1000); + } + } + } + #endregion + + + if (!is_error) + { + ChatClient.Events.OnEvent(new WXRefreshContactSuccess(this)); + if (method != null) method.Invoke(this); + } + else + { + + } + } + }); + } + + /// + /// 同意添加我为好友 + /// + /// 收到的Token完整数据 + public override string AgreeAddMe(string token) + { + try + { + string temp = Regex.Replace(token, @"\\""", "\""); + var v2 = Regex.Match(temp, "ticket=\"([^\\s]+)\""); + var v1 = Regex.Match(temp, "encryptusername=\"([^\\s]+)\""); + + var scene = 0; + var sceneReg = Regex.Match(temp, @"scene=\""([^""]+?)\"""); + if (sceneReg.Success) + scene = int.Parse(sceneReg.Groups[1].Value); + + // var us = Regex.Match(temp, "fromusername=\"(.*?)\"").Groups[1].Value; + // Console.WriteLine(us); + if (v1.Success && v2.Success) + { + var payloadJson = new + { + Encryptusername = v1.Groups[1].Value,//v1_ + Ticket = v2.Groups[1].Value,//v2_ + Type = 3,//1关注公众号2打招呼 主动添加好友3通过好友请求 + Sence = scene,//1来源QQ2来源邮箱3来源微信号14群聊15手机号18附近的人25漂流瓶29摇一摇30二维码 + Content = "",//打招呼内容 + }; + + WechatPack send = new WechatPack(this); + var data = send.SendAll(WechatCmd.同意添加好友, true, payloadJson); + string result = Encoding.UTF8.GetString(data); + if (temp.Contains(result)) + { + var reg = Regex.Match(token, @"fromusername=""(?.*?)""[\w\W]+fromnickname=""(?.*?)""[\w\W]+content=""(?.*?)""[\w\W]+sourceusername=""(?.*?)""[\w\W]+sourcenickname=""(?.*?)"""); + if (reg.Success) + { + Task.Factory.StartNew(delegate + { + Thread.Sleep(2000); + var friend = GetContact(reg.Groups["newFriendWxid"].ToString()); + //this.EventManage.OnEvent(new WXAddFriendSuccess() { FriendNick = reg.Groups["newFriendNick"].Value, FriendWxid = reg.Groups["newFriendWxid"].ToString() }); + if (friend != null) ChatClient.Events.OnEvent(new WXNewFriend(this, friend)); + }); + } + return null; + } + else + this.WriteLog(result); + return result; + } + else + return "token 不满足指定条件"; + } + catch (Exception ex) + { + return ex.Message; + } + } + + /// + /// 发送图片 + /// + /// 图片字节 + /// 要发送给谁 + public override void SendImage(byte[] img, string username) + { + int index = 0; + Stream imgStream = new MemoryStream(img); + try + { + int Startpos = 0;//起始位置 + int datalen = 65535;//数据分块长度//dll img 最大缓冲区65535 在大了 wx 收不到包; + int datatotalength = (int)imgStream.Length; + string ClientImgId = User.Username + "_" + Util.TimeStamp().ToString(); + + while (Startpos != (int)datatotalength && index < 15) + {// + index++; + int count = 0; + if (datatotalength - Startpos > datalen) + { + count = datalen; + } + else + { + count = (int)datatotalength - Startpos; + } + + byte[] data = new byte[65535]; + imgStream.Seek(Startpos, SeekOrigin.Begin); + imgStream.Read(data, 0, count); + + UploadImgInfo imginfo = new UploadImgInfo(); + imginfo.ClientImgId = ClientImgId; + imginfo.dwStartPos = Startpos; + imginfo.dwTotalLen = datatotalength; + imginfo.dwDataLen = count; + imginfo.szImgBuf = data; + imginfo.szToUserName = username; + + Startpos = Startpos + count; + Console.WriteLine("Send Img Block {0} next {1}", count, Startpos); + + byte[] buffers = WXClientTool.CUploadImg(User.User, imginfo); + + + Console.WriteLine(buffers == null ? "null" : buffers.Length.ToString()); + int Seq = Util.ReadInt(buffers, 12); + + WechatPack pack = new WechatPack(this); + buffers = pack.SendWx(buffers, Seq); + + //var _temp = pack.Analysis(1100, buffers); + //Console.WriteLine(Encoding.UTF8.GetString(_temp)); + //长链接解包判定 + if (buffers[16] != 191) + { + //说明wx返回出错 + //Console.WriteLine("未知包:{0}", Util.HexToStr(buffers)); + return; + } + + #region xxx + //图片可以不用解包 要解的话就请求服务器好了。。。发送成功最终会返回msgid + /* + WechatMsg IMGMsgRsp = new WechatMsg + { + Token = ConstProtocol.MachineCode, + Version = ConstProtocol.Version, + TimeStamp = Utils.Time_Stamp(), + IP = ClientIP + }; + + IMGMsgRsp.BaseMsg = new BaseMsg + { + Cmd = -1100, + User = vUser, + }; + + IMGMsgRsp.BaseMsg.Payloads = ByteString.CopyFrom(buffers); + IMGMsgRsp = client.HelloWechat(IMGMsgRsp, authHeader); + buffers = IMGMsgRsp.BaseMsg.Payloads.ToByteArray(); + //Console.WriteLine(Encoding.UTF8.GetString(buffers)); + */ + #endregion + } + + } + catch (Exception ex) + { + this.WriteLog($"发送图片失败:{ex.Message} - {ex.StackTrace}"); + this.ResetConnection(); + } + finally + { + imgStream.Close(); + imgStream.Dispose(); + } + } + + //public int SendImageCount; + + /// + /// 发送图片 + /// + /// 要发送给谁 + /// 图片路径,支持http,https + public override void SendImage(string username, string address) + { + //SendImageCount++; + try + { + //if (SendImageCount % 2 == 0) SendMessage("weixin", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + + byte[] ImangByte = null; + + string extension = Path.GetExtension(address); + if (address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + var imagePath = Util.MapFile(DateTime.Now.Ticks.ToString() + "." + extension, "Cache\\image"); + FileTools.DownloadImage(address, imagePath); + address = imagePath; + } + + if (File.Exists(address)) + { + ImangByte = File.ReadAllBytes(address); + + if (ImangByte != null && ImangByte.Length >= 3) + { + SendImage(ImangByte, username); + } + } + else + { + SendCDNImage(username, address); + } + } + catch (Exception ex) + { + this.WriteLog("发送图片失败:" + ex.Message); + this.ResetConnection(); + } + } + + /// + /// 发送语音文件 + /// + /// 名称 + /// 地址 + public override void SendVoice(string username, string url) + { + try + { + byte[] buf; + if (url.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + buf = new WebClient().DownloadData(url); + } + else + { + using (FileStream fsRead = new FileStream(url, FileMode.Open)) + { + int fsLen = (int)fsRead.Length; + buf = new byte[fsLen]; + fsRead.Read(buf, 0, buf.Length); + } + } + + MemoryStream imgStream = new MemoryStream(buf); + + int Startpos = 0;//起始位置 + int datalen = 65535;//数据分块长度 + long datatotalength = imgStream.Length; + string ClientImgId = User.Username + "_" + Util.TimeStamp().ToString(); + int EndFlag = 0; + + while (Startpos != (int)datatotalength) + {// + int count = 0; + if (datatotalength - Startpos > datalen) + { + count = datalen; + } + else + { + count = (int)datatotalength - Startpos; + EndFlag = 1;//最后一个块 + } + + byte[] data = new byte[65535];//不能更改此参数 若要更改必须同步c++ 缓冲器长度 + imgStream.Seek(Startpos, SeekOrigin.Begin); + imgStream.Read(data, 0, count); + + UploadVoiceInfo voiceinfo = new UploadVoiceInfo(); + voiceinfo.ClientMsgId = ClientImgId; + voiceinfo.dwOffset = Startpos; + voiceinfo.dwVoiceBufLength = count; + voiceinfo.dwVoiceLength = 20000;//2s语音 超长语音好像手机端就不显示 多少秒了。。 + voiceinfo.dwEndFlag = EndFlag; + voiceinfo.szVoiceBuf = data; + voiceinfo.dwVoiceFormat = 4;////0->Arm 无amr音频头 2->MP3 3->WAVE 4->SILK + voiceinfo.szToUserName = username; + + Startpos = Startpos + count; + + byte[] buffers = WXClientTool.CUploadVoice(User.User, voiceinfo); + int Seq = Util.ReadInt(buffers, 12); + //Console.WriteLine("Send Seq {0}", Seq); + WechatPack pack = new WechatPack(this); + pack.SendWx(buffers, Seq); + } + imgStream.Close(); + } + catch (Exception ex) + { + WriteLog(ex.Message); + } + } + + #region 返回一个随机表情 + private static string Expression = "[微笑],[憨笑],[呲牙],[爱心],[啤酒],[太阳],[礼物],[抱拳],[咖啡],[调皮],[激动],[回头],[色],[愉快],[爱情],[飞吻],[跳跳],[发抖],[转圈],[献吻],[耶],[红包],[嘿哈]"; + private static List ExpressionList = null; + private static Random random = new Random(); + public static string FindRandomExpression() + { + if (ExpressionList == null) + ExpressionList = Expression.Split(',').ToList(); + return ExpressionList[random.Next(ExpressionList.Count)]; + } + #endregion + + /// + /// 发送文本消息 + /// + /// 用户名 + /// 消息正文 + /// 是否艾特用户 + public override Task SendMessage(string _username, string _content, string _atUsername = "") + { + string username = _username; + string content = _content; + string atUsername = _atUsername; + + return Task.Run(() => + { + if (string.IsNullOrEmpty(content)) return true; + content = content.Replace("\r\n", "\n").Trim().Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + try + { + foreach (var msg in msgs) + { + var m = msg.Trim(); + if (string.IsNullOrEmpty(m)) continue; + + var message = m.RandomMess(); + + message = message.Contains("[随机表情]") ? message.Replace("[随机表情]", FindRandomExpression()) : message; + + //if (message.StartsWith("[延迟=")) + //{ + // var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + // if (reg.Success) + // { + // message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + // Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + // } + //} + message = DelayMess(message); + + ChatClient.Events.OnEvent(new WXSendMessage(this, message, username)); + + //发送XML消息 + if (message.Trim().ToLower().StartsWith("")) + { + WechatPack pack = new WechatPack(this); + var sendJson = new + { + ToUserName = username, + AppId = "", + Type = 5, + Content = message + }; + pack.SendAll(WechatCmd.发送XML消息, false, sendJson); + //return true; + continue; + } + + //发送公告消息 + var matchs = Regex.Matches(message, @"\[公告\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (username.Contains("@")) + { + foreach (Match match in matchs) + { + SetRoomNotice(match.Groups[1].Value, username); + } + } + message = Regex.Replace(message, @"\[公告\=([^\]]+)\]", ""); + message = DelayMess(message); + + //发送图片消息 + matchs = Regex.Matches(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + SendImage(username, match.Groups[1].Value); + } + message = Regex.Replace(message, @"\[图片\=([^\]]+)\]", ""); + message = DelayMess(message); + + //发送语音消息 + matchs = Regex.Matches(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + SendVoice(username, item.Groups[1].Value); + } + message = Regex.Replace(message, @"\[语音\=([^\]]+)\]", ""); + message = DelayMess(message); + matchs = Regex.Matches(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + try + { + var temp = item.Groups[1].Value; + if (File.Exists(temp)) continue; + + var video = Util.StrToHex(temp); + if (video != null) + { + var video_json = Encoding.UTF8.GetString(video); + var video_data = HttpExtend.JsonToDictionary(video_json); + if (video_data != null) + { + //SendCDNInfo(username, video_data["cdnurl"].ToString(), video_data["aeskey"].ToString(), CDNType.发送视频); + SendCDNVideo(username, video_data["cdnurl"].ToString(), video_data["aeskey"].ToString()); + } + } + } + catch (Exception ex) + { } + } + message = Regex.Replace(message, @"\[视频\=([^\]]+)\]", ""); + message = DelayMess(message); + + matchs = Regex.Matches(message, @"\[卡片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + SendCard(username, item.Groups[1].Value == "自己" ? User.Username : item.Groups[1].Value); + } + message = Regex.Replace(message, @"\[卡片\=([^\]]+)\]", ""); + message = DelayMess(message); + if (string.IsNullOrWhiteSpace(message)) continue; + if (message.StartsWith("\r\n")) message = message.Substring("\r\n".Length); + if (message.StartsWith("\n")) message = message.Substring("\n".Length); + + WechatPack send = new WechatPack(this); + + #region 提取艾特用户id + + List atWxidList = new List(); + var regTmp = Regex.Matches(message, @"(?<全部>\[@(?<账号>[A-Za-z0-9_]+)\])"); + foreach (Match item in regTmp) + { + if (item.Success) + { + var name = item.Groups["账号"].Value; + atWxidList.Add(name); + var friend = GetContact(name); + if (friend != null) + message = message.Replace(item.Groups["全部"].Value, $"@{friend.NickName} "); + } + } + + if (atWxidList.Count != 0) + { + atUsername = string.Join(",", atWxidList); + } + #endregion + + var sendData = new { ToUserName = username, Content = message.Trim(), Type = 0, MsgSource = atUsername }; + send.SetNextData(new WechatPack.PackMsg() { cmd = WechatCmd.发送文本消息, data = sendData }); + RunSendMessageQueue(send); + } + return true; + } + catch (Exception ex) + { + this.WriteLog("SendMessage ERROR:" + ex.Message); + return false; + } + }); + } + + /// + /// 消息延迟 + /// + /// + public string DelayMess(string message) + { + try + { + message = message.Trim(); + if (message.StartsWith("[延迟=")) + { + var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + } + } + } + catch (Exception ex) + { } + return message; + } + + /// + /// + /// + private DateTime fragmentTime = DateTime.MinValue; + private int fragmentCount = 0; + + /// + /// 需要发送的消息队列 + /// + private ConcurrentQueue SendMessageQueue { get; set; } = new ConcurrentQueue(); + private object lock_sendmessage = new object(); + private bool lock_sendmessage_ing = false; + Thread SendMessageThread; + private void RunSendMessageQueue(WechatPack sendPack) + { + SendMessageQueue.Enqueue(sendPack); + if (lock_sendmessage_ing) return; + + lock (lock_sendmessage) + { + if (lock_sendmessage_ing) return; + lock_sendmessage_ing = true; + ThreadPool.QueueUserWorkItem(x => + { + try + { + WechatPack pack = null; + while (SendMessageQueue.TryDequeue(out pack)) + { + if (this.Status == WxStatus.在线) + { + pack.SendNextData(); + + #region 消息防止频繁,休眠操作 + if (ChatClient.MessFrequentSleepTime != 0) + { + fragmentCount++; + var totalSeconds = (DateTime.Now - fragmentTime).TotalSeconds;//上次休眠的时间差 + bool rest = totalSeconds > 10; + if (fragmentCount >= 10 && totalSeconds <= 10) + { + rest = true; + Thread.Sleep(ChatClient.MessFrequentSleepTime * 1000); + } + + if (rest) + { + fragmentCount = 1; + fragmentTime = DateTime.Now; + } + } + + // if (ChatClient.MessFrequentSleepTime != 0) + // { + // var totalSeconds = (DateTime.Now - _SendTimePoint).TotalSeconds; + + + // if (_SendTimePoint == DateTime.MinValue || _MessCount < 10 && totalSeconds > 10d) + // { + // _SendTimePoint = DateTime.Now; + // _MessCount = -1; + // Thread.Sleep(50); + // } + // else if (_MessCount >= 10 && totalSeconds <= 10d) + // { + // _SendTimePoint = DateTime.MinValue; + // _MessCount = -1; + // Thread.Sleep(ChatClient.MessFrequentSleepTime * 1000); + // } + // _MessCount++; + //} + #endregion + } + } + } + catch (Exception) + { + } + finally + { + lock_sendmessage_ing = false; + } + }); + } + } + + + private Dictionary ContactQRcodes = new Dictionary(); + /// + /// 获取联系人二维码 + /// + + public override Bitmap GetRobotQRcode(bool Refresh = false) + { + try + { + var username = User.Username; + WechatPack pack = new WechatPack(this); + var data = pack.SendAll(WechatCmd.获取联系人二维码, true, new { Username = username }); + var text = Encoding.UTF8.GetString(data); + var _dic = Util.ConvertJsonToDic(text); + var ba64 = _dic["QrcodeBuf"].ToString(); + + var result = WXClientTool.GetImageFromBase64(ba64); + if (result != null) ContactQRcodes[username] = ba64; + return result; + } + catch (Exception e) + { + this.WriteLog("GetContactQRcode:" + e.Message + " - " + e.StackTrace); + return null; + } + } + + public override string DownlowdImage(int msgid, string fromUsername, int datatotalength) + { + try + { + List downImgData = new List(); + + int Startpos = 0;//起始位置 + int datalen = 30720;//数据分块长度 + // long datatotalength = 55843;//根据需要选择下载 高清图还是缩略图 长度自然是对应 高清长度和缩略长度 + + + while (Startpos != (int)datatotalength) + {// + int count = 0; + if (datatotalength - Startpos > datalen) + { + count = datalen; + } + else + { + count = (int)datatotalength - Startpos; + } + + + var payLoadJson = new + { + MsgId = msgid, + ToUsername = fromUsername,//ToUserName 字段值 + StartPos = Startpos, + TotalLen = (int)datatotalength, + DataLen = count, + CompressType = 0,//hdlength 1高清0缩略 + + }; + WechatPack pack = new WechatPack(this); + var buffers = pack.SendAll(WechatCmd.下载图片, true, payLoadJson); + //Console.WriteLine(Encoding.UTF8.GetString(buffers)); + Startpos = Startpos + buffers.Length;//已实际接受的块的长度做好偏移 下次从 Startpos + buffers.Length 开始拼接 + + downImgData.AddRange(buffers); + + + } + + string image = Util.MapFile(Guid.NewGuid().ToString() + ".jpg", "Cache\\Image"); + + using (FileStream fs = new FileStream(image, FileMode.Create)) + { + fs.Write(downImgData.ToArray(), 0, downImgData.ToArray().Length); + fs.Close(); + } + return image; + } + catch (Exception) { } + return string.Empty; + } + + public void SnsVerify(string code, bool isHongbao, string reqKey, BankCar bank, string token, string pass) + { + //确认支付时返回的JSON + //此处只有短链接 + object obj = null; + if (bank != null) + { + obj = new + { + CgiCmd = isHongbao ? 1617 : 1592,//1617支付红包返回的短信验证 1592 转账支付时候返回的短信 + ReqKey = reqKey, + Bank_TYPE = bank.bank_type, + Bind_SERIAL = bank.bind_serial,//Bank_TYPE=Bind_SERIAL=CFT时 使用零钱转支付 银行卡支付请填写银行卡id 获取银行卡ID btn_GetBlankID_Click + Token = token,//在返回的json里寻找token字段 + PassWord = pass, + SMSVerityCode = code,//短信验证码 + PayScene = bank == null ? "37" : "21" //37使用零钱支付 21银行卡支付(如果支付不成功请联系我重新抓) + }; + } + else + { + obj = new + { + Bank_TYPE = "CFT", + Bind_SERIAL = "CFT", + CgiCmd = isHongbao ? 1617 : 1592,//1617支付红包返回的短信验证 1592 转账支付时候返回的短信 + ReqKey = reqKey, + Token = token,//在返回的json里寻找token字段 + PassWord = pass, + SMSVerityCode = code,//短信验证码 + PayScene = bank == null ? "37" : "21" //37使用零钱支付 21银行卡支付(如果支付不成功请联系我重新抓) + }; + } + string json = CsharpHttpHelper.HttpHelper.ObjectToJson(obj); + WechatPack send = new WechatPack(this); + send.Send(WechatCmd.获得银行卡, json); + } + + public override string CreateChatRoom(string members) + { + try + { + WechatPack pack = new WechatPack(this); + var data = pack.Send(WechatCmd.创建群, new + { + Membernames = members, + ProtocolVer = 1,//值为 1 2 4 6 当然这里你填写3也就是mac的账号密码登陆 具体会出什么问题 自行尝试 + }); + + + var temp = pack.Analysis(data); + var rest = Encoding.UTF8.GetString(temp); + //var json = HttpHelper.ObjectToJson(rest); + Lable[] temp_list = HttpHelper.JsonToObject(rest) as Lable[]; + if (temp_list != null) Lables = temp_list.ToList(); + } + catch (Exception ex) + { + this.WriteLog("创建群异常:" + ex.Message + " - " + ex.StackTrace); + } + return string.Empty; + } + + public override string CreateChatRoom(string[] wxids) + { + try + { + if (wxids == null || wxids.Length == 0) return string.Empty; + WechatPack pack = new WechatPack(this); + var data = pack.Send(WechatCmd.创建群, new + { + Membernames = string.Join(",", wxids), + ProtocolVer = 1,//值为 1 2 4 6 当然这里你填写3也就是mac的账号密码登陆 具体会出什么问题 自行尝试 + }); + + + var temp = pack.Analysis(data); + var rest = Encoding.UTF8.GetString(temp); + //var json = HttpHelper.ObjectToJson(rest); + Lable[] temp_list = HttpHelper.JsonToObject(rest) as Lable[]; + if (temp_list != null) Lables = temp_list.ToList(); + } + catch (Exception ex) + { + this.WriteLog("创建群异常:" + ex.Message + " - " + ex.StackTrace); + } + return string.Empty; + } + + public override void AddChatRoomMember(string groupid, string members) + { + try + { + WechatPack pack = new WechatPack(this); + var payLoadJson = pack.Send(WechatCmd.创建群, new + { + Roomeid = groupid, + Membernames = members, + }); + } + catch (Exception ex) + { + this.WriteLog("添加群用户异常:" + ex.Message + " - " + ex.StackTrace); + } + } + + /// + /// 设置公告 + /// + /// + /// + public override void SetRoomNotice(string notice, string groupId) + { + try + { + WechatPack pack = new WechatPack(this); + pack.Send(WechatCmd.群公告, new + { + ChatRoomName = groupId,//群ID + Announcement = notice//公告内容 + }); + } + catch (Exception ex) + { + this.WriteLog("发送公告异常:" + ex.Message + " - " + ex.StackTrace); + } + } + + [Obsolete("该方法过时,发视频使用:SendCDNVideo,发图片使用:SendCDNImage")] + public override void SendCDNInfo(string tousername, string cdnurl, string aeskey, CDNType type) + { + object payLoadJson = null; + if (type == CDNType.发送视频) + { + payLoadJson = new + { + ToUserName = tousername, + ThumbTotalLen = 2883,//中的值 cdnthumblength=\"2883\" + ThumbStartPos = 2883,////中的值 cdnthumblength=\"2883\" + VideoTotalLen = 401645,//中的值 length=\"401645\" + VideoStartPos = 401645,//中的值 length=\"401645\" + PlayLength = 2,//playlength=\"2\" + AESKey = aeskey,//aeskey=\"ad5b38f66c5849499f294a725e9719a8\" + CDNVideoUrl = cdnurl,//中的值 cdnvideourl=\"304b020100044430420201000204d26d70fe02033d0af802047130feb602045953265e0420777869645f6d307238796d61636f693670333234365f313439383632313533330201000201000400\" + }; + + WechatPack sendPack = new WechatPack(this); + sendPack.SendAll(WechatCmd.发送CDN数据, false, payLoadJson); + } + else if (type == CDNType.发送图片) + { + string ClientImgId = this.User.Username + "_" + Util.TimeStamp(); + + payLoadJson = JsonConvert.SerializeObject(new + { + ClientImgId = ClientImgId, + ToUserName = tousername, + StartPos = 0, + TotalLen = 31572, + DataLen = 31572, + CDNMidImgUrl = cdnurl, + AESKey = aeskey, + CDNMidImgSize = 31572, + CDNThumbImgSize = 3011, + CDNThumbImgHeight = 100, + CDNThumbImgWidth = 343 + }); + + WechatPack sendPack = new WechatPack(this); + + sendPack.SendAll(WechatCmd.发送图片文件, false, payLoadJson); + } + } + + /// + /// 发送CDN视频 + /// + /// + /// + /// + public override void SendCDNVideo(string tousername, string cdnurl, string aeskey) + { + var payLoadJson = new + { + ToUserName = tousername, + ThumbTotalLen = 2883,//中的值 cdnthumblength=\"2883\" + ThumbStartPos = 2883,////中的值 cdnthumblength=\"2883\" + VideoTotalLen = 401645,//中的值 length=\"401645\" + VideoStartPos = 401645,//中的值 length=\"401645\" + PlayLength = 2,//playlength=\"2\" + AESKey = aeskey,//aeskey=\"ad5b38f66c5849499f294a725e9719a8\" + CDNVideoUrl = cdnurl,//中的值 cdnvideourl=\"304b020100044430420201000204d26d70fe02033d0af802047130feb602045953265e0420777869645f6d307238796d61636f693670333234365f313439383632313533330201000201000400\" + }; + + WechatPack sendPack = new WechatPack(this); + sendPack.SendAll(WechatCmd.发送CDN数据, false, payLoadJson); + } + + public override void SendCDNImage(string tousername, string data) + { + try + { + string ClientImgId = this.User.Username + "_" + Util.TimeStamp(); + var tmp = Util.StrToHex(data); + if (tmp != null) + { + var image_json = Encoding.UTF8.GetString(tmp); + + var cdnImgMsg = HttpHelper.JsonToObject(image_json) as CDNImageMsgInfo; + if (cdnImgMsg != null) + { + var payLoadJson = string.Empty; + if (!string.IsNullOrWhiteSpace(cdnImgMsg.CDNBigImgUrl)) + { + payLoadJson = JsonConvert.SerializeObject(new + { + ClientImgId = ClientImgId, + ToUserName = tousername, + StartPos = cdnImgMsg.StartPos, + TotalLen = cdnImgMsg.TotalLen, + DataLen = cdnImgMsg.DataLen, + AESKey = cdnImgMsg.AESKey, + CDNMidImgUrl = cdnImgMsg.CDNMidImgUrl, + CDNMidImgSize = cdnImgMsg.CDNMidImgSize, + CDNBigImgUrl = cdnImgMsg.CDNBigImgUrl, + CDNBigImgSize = cdnImgMsg.CDNBigImgSize, + CDNThumbImgSize = cdnImgMsg.CDNThumbImgSize, + CDNThumbImgHeight = cdnImgMsg.CDNThumbImgHeight, + CDNThumbImgWidth = cdnImgMsg.CDNThumbImgWidth, + CompressType = 1,//高清 + }); + } + else + { + payLoadJson = JsonConvert.SerializeObject(new + { + ClientImgId = ClientImgId, + ToUserName = tousername, + StartPos = cdnImgMsg.StartPos, + TotalLen = cdnImgMsg.TotalLen, + DataLen = cdnImgMsg.DataLen, + AESKey = cdnImgMsg.AESKey, + CDNMidImgUrl = cdnImgMsg.CDNMidImgUrl, + CDNMidImgSize = cdnImgMsg.CDNMidImgSize, + CDNThumbImgSize = cdnImgMsg.CDNThumbImgSize, + CDNThumbImgHeight = cdnImgMsg.CDNThumbImgHeight, + CDNThumbImgWidth = cdnImgMsg.CDNThumbImgWidth + }); + } + + WechatPack sendPack = new WechatPack(this); + var result = sendPack.SendAll(WechatCmd.发送图片文件, false, payLoadJson); + + var text = Encoding.UTF8.GetString(result); + var _dic = Util.ConvertJsonToDic(text); + if (_dic != null) + { } + + //for (int i = 0; i < 10; i++) + //{ + // try + // { + + // if (i % 2 == 0) SendMessage("weixin", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + // } + // catch (Exception ex) + // { + + // } + // Thread.Sleep(5000); + //} + } + } + } + catch (Exception ex) + { + + } + } + + + /// + /// 发送朋友圈 + /// + /// + /// + public override string SendCircle(string msg) + { + try + { + msg = msg.RandomMess().Trim(); + if (msg.StartsWith("") && msg.EndsWith("")) + { + try + { + msg = Regex.Replace(msg, @"videomd5=""(.{32})""", @"videomd5=""" + Util.GetMD5Hash(Guid.NewGuid().ToByteArray()) + @""""); + msg = Regex.Replace(msg, @"md5=""(.{32})""", @"md5=""" + Util.GetMD5Hash(Guid.NewGuid().ToByteArray()) + @""""); + } + catch (Exception) + { } + return _UplodCirele(msg); + } + else + { + if (!msg.Contains("[图片")) throw new Exception("请插入任意一张图片!"); + + //检测图片、如果是本地图片或非微信服务器图片、将自动上传并返回最新地址 + List images = null; + var match = Regex.Matches(msg, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + if (match.Count > 0) + { + images = new List(); + + foreach (Match item in match) + { + images.Add(item.Groups[1].Value); + } + msg = Regex.Replace(msg, "\\[图片=.*?\\]", "").Trim(); + } + + var t = SendCircle(msg, images); + return t; + } + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 获取朋友圈 + /// + /// 微信ID + /// 页码 + /// 页码ID + /// + public override List> FindCircle(string username, string firstPageMd5 = "", long MaxId = 0) + { + try + { + WechatPack send = new WechatPack(this); + var data = send.SendAll(WechatCmd.获取朋友圈, true, new + { + firstPageMd5 = firstPageMd5, + Username = username,//访问好友朋友圈的wxid + MaxId = MaxId //首页为0 次页朋友圈数据id 的最小值 + }); + + var message = Encoding.UTF8.GetString(data); + //Console.WriteLine(message); + var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(message); + if (dic != null) + { + var objs = dic["SnsObjects"] as ArrayList; + if (objs == null || objs.Count == 0) throw new Exception(username + ",朋友圈没有数据!"); + List> _objs = new List>(); + foreach (Dictionary item in objs) + { + _objs.Add(item); + } + int i, j; //先定义一下要用的变量 + for (i = 0; i < _objs.Count - 1; i++) + { + for (j = i + 1; j < _objs.Count; j++) + { + var i_ = long.Parse(_objs[i]["CreateTime"].ToString()); + var j_ = long.Parse(_objs[j]["CreateTime"].ToString()); + if (i_ < j_) //如果第二个小于第一个数 + { + //交换两个数的位置,在这里你也可以单独写一个交换方法,在此调用就行了 + var temp = _objs[i]; //把大的数放在一个临时存储位置 + _objs[i] = _objs[j]; //然后把小的数赋给前一个,保证每趟排序前面的最小 + _objs[j] = temp; //然后把临时位置的那个大数赋给后一个 + } + } + } + return _objs; + } + } + catch (Exception) + { } + return new List>(); + } + + /// + /// 获取朋友圈内容 + /// + /// + public override List> FindCircles() + { + try + { + var obj = new { ClientLatestId = 0 }; + WechatPack pack = new WechatPack(this); + var home = pack.SendAll(WechatCmd.获取朋友圈首页, true, obj); + string text = Encoding.UTF8.GetString(home); + var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(text); + if (dic != null) + { + var objs = dic["SnsObjects"] as ArrayList; + if (objs == null || objs.Count == 0) return new List>(); + List> _objs = new List>(); + foreach (Dictionary item in objs) + { + _objs.Add(item); + } + int i, j; //先定义一下要用的变量 + for (i = 0; i < _objs.Count - 1; i++) + { + for (j = i + 1; j < _objs.Count; j++) + { + var i_ = long.Parse(_objs[i]["CreateTime"].ToString()); + var j_ = long.Parse(_objs[j]["CreateTime"].ToString()); + if (i_ < j_) //如果第二个小于第一个数 + { + //交换两个数的位置,在这里你也可以单独写一个交换方法,在此调用就行了 + var temp = _objs[i]; //把大的数放在一个临时存储位置 + _objs[i] = _objs[j]; //然后把小的数赋给前一个,保证每趟排序前面的最小 + _objs[j] = temp; //然后把临时位置的那个大数赋给后一个 + } + } + } + + return _objs; + } + } + catch (Exception) + { + } + return new List>(); + } + + /// + /// 发表评论 + /// + /// 发送的微信ID + /// 朋友圈的ID + /// 发送的内容 + /// + public override void SendCircleComment(string username, string circleId, string content) + { + #region 老妖的 + //try + //{ + // WechatPack pack = new WechatPack(this); + // var result = pack.Send(WechatCmd.评论或点赞, new + // { + // ID = circleId,//朋友圈ID + // ToUsername = username,//欲被点赞的或评论的wxid 发送该朋友圈的wxid + // Type = 2,//1点赞2评论 + // Content = content //评论的内容 + // }); + // //return Encoding.UTF8.GetString(result); + //} + //catch (Exception ex) + //{ + // WriteLog("SendCircleComment Error:" + ex.Message); + //} + #endregion + + //string username = _username; + //string circleId = _circleId; + //string content = _content; + if (string.IsNullOrEmpty(content)) return; + content = content.Replace("\r\n", "\n").Trim(); + var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + + //Task.Run(delegate + //{ + try + { + WechatPack pack = new WechatPack(this); + foreach (var msgTmp in msgs) + { + var msg = msgTmp.RandomMess(); + pack.Send(WechatCmd.评论或点赞, new + { + ID = circleId,//朋友圈ID + ToUsername = username,//欲被点赞的或评论的wxid 发送该朋友圈的wxid + Type = 2,//1点赞2评论 + Content = msg //评论的内容 + }); + Thread.Sleep(2450 + new Random().Next(50, 1000)); + } + } + catch (Exception ex) + { + WriteLog("SendCircleComment Error:" + ex.Message); + } + //}); + } + + private List Lables = new List(); + /// + /// 获取标签 + /// + public override List GetLabelList(bool refresh = false) + { + try + { + if (!refresh && Lables.Count != 0) return Lables; + WechatPack pack = new WechatPack(this); + var data = pack.Send(WechatCmd.获取标签, null); + var temp = pack.Analysis(data); + var rest = Encoding.UTF8.GetString(temp); + //var json = HttpHelper.ObjectToJson(rest); + Lable[] temp_list = HttpHelper.JsonToObject(rest) as Lable[]; + if (temp_list != null) Lables = temp_list.ToList(); + } + catch (Exception) { } + return Lables; + + } + + /// + /// 添加标签 + /// + public override bool AddLabel(string TagName) + { + try + { + if (Lables.Count == 0) GetLabelList(); + if (Lables.FirstOrDefault(f => f.LabelName == TagName) != null) return true; + string payloadJson = "{\"LabelName\":\"" + TagName + "\"}"; + WechatPack pack = new WechatPack(this); + var data = pack.Send(WechatCmd.添加标签, payloadJson); + var rest = pack.Analysis(data); + var json = HttpHelper.JsonToObject(Encoding.UTF8.GetString(rest)) as Lable[]; + if (json != null) + { + foreach (var item in json) + { + if (Lables.FirstOrDefault(f => f.LabelID == item.LabelID) == null) Lables.Add(item); + } + + return true; + } + //Console.WriteLine(); + } + catch (Exception) + { + + } + return false; + } + + /// + /// 修改标签 + /// + public override bool EditUserLabel(string[] Users, List Lable) + { + try + { + + List list = new List(); + foreach (var item in Lable) list.Add(item.LabelID); + string payloadJson = JsonConvert.SerializeObject(new + { + Labelids = string.Join(",", list),//标签id ,号分割 1,2,3,4 + UserLists = string.Join(",", Users) //微信id 逗号分隔如1,2,2, + }); + WechatPack pack = new WechatPack(this); + var data = pack.Send(WechatCmd.修改标签, payloadJson); + //var rest = pack.Analysis(data); + //var json = Encoding.UTF8.GetString(rest); + return true; + } + catch (Exception) { } + + return false; + + } + + /// + /// 点赞 + /// + /// + /// + public override void SendCirclePraise(string username, string circleId) + { + try + { + WechatPack pack = new WechatPack(this); + var result = pack.Send(WechatCmd.评论或点赞, new + { + ID = circleId,//朋友圈ID + ToUsername = username,//欲被点赞的或评论的wxid 发送该朋友圈的wxid + Type = 1,//1点赞2评论 + Content = "" //评论的内容 + }); + + //return Encoding.UTF8.GetString(result); + } + catch (Exception ex) + { + WriteLog("SendCirclePraise Error:" + ex.Message); + } + } + #region 发送朋友圈 + private string SendCircle(string content, List images = null) + { + string str = UplodCircleStr(content, images); + return _UplodCirele(str); + } + private string _UplodCirele(string content) + { + try + { + var match = Regex.Matches(content, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in match) + { + try + { + var url = item.Groups[1].Value; + url = UplodCircleImage(url); + if (string.IsNullOrWhiteSpace(url)) continue; + content = content.Replace($"[图片={item.Groups[1].Value}]", url); + } + catch (Exception) + { + } + } + var payloadJson = new + { + Content = Encoding.UTF8.GetBytes(content) + }; + WechatPack send = new WechatPack(this); + return Encoding.UTF8.GetString(send.SendAll(WechatCmd.发送朋友圈, true, payloadJson)); + } + catch (Exception ex) + { + WriteLog("发送朋友圈失败:" + ex.Message); + return null; + } + } + + /// + /// 关注公众号 + /// + /// + /// + public override bool FocusWechat(string username) + { + try + { + var qr_reg = Regex.Match(username, "http://weixin.qq.com/r/([a-zA-Z0-9]+)"); + string data = string.Empty; + if (qr_reg.Success) data = qr_reg.Groups[1].Value + "@qr"; + else if (!Regex.Match(username, "^gh_.*?$").Success) throw new Exception("公众号格式错误,请重新输入!"); + else data = username; + string payloadJson = JsonConvert.SerializeObject(new + { + Encryptusername = data,//非原始id 或扫码后的id 识别二维码后得到http://weixin.qq.com/r/RjndxWXExji5rSGm92xU 账号为RjndxWXExji5rSGm92xU@qr 直接关注即可 + Ticket = "",//v2_ + Type = 1,//1关注公众号2打招呼 主动添加好友3通过好友请求 + Sence = 3, + Content = "",//打招呼内容 + ProtocolVer = 1 //ProtocolVer 1-5 + + }); + + WechatPack pack = new WechatPack(this); + pack.SendAll(WechatCmd.同意添加好友, false, payloadJson); + + return true; + } + catch (Exception ex) + { + WriteLog("FocusWechat 异常:" + ex.Message); + } + return false; + } + + public override Dictionary SerchKeyword(string keyword) + { + try + { + WechatPack pack = new WechatPack(this); + var result = pack.Send(WechatCmd.搜索关键词, new + { + Searchinfo = keyword + }); + result = pack.Analysis(result); + var json = Encoding.UTF8.GetString(result); + return HttpExtend.JsonToDictionary(json); + } + catch (Exception ex) + { + WriteLog("SerchKeyword 异常:" + ex.Message); + } + return null; + } + /// + /// 编辑用户信息 + /// + /// 操作用户 + /// 操作类型 + /// 如果Type=备注,为空表示取消备注,不为空表示备注所填写内容 + public override void EditContacts(string username, EditContactsType type, string remark = "") + { + for (int i = 0; i < 3; i++) + { + try + { + if (!string.IsNullOrEmpty(remark)) + { + if (remark.Length > 55) + { + remark = remark.Substring(0, 55); + } + } + var payloadJson = "{\"Cmdid\":2,\"CmdBuf\":\"" + username + "\",\"BitVal\":" + (int)type + ",\"Remark\":\"" + remark + "\"}"; + + WechatPack pack = new WechatPack(this); + pack.Send(WechatCmd.编辑联系人信息, payloadJson); + } + catch (Exception) + { + this.WriteLog($"更新用户信息[{username}]失败!" + type + "," + remark); + } + Thread.Sleep(300); + } + } + + /// + /// 拼接上传信息 + /// + private string UplodCircleStr(string content, List images = null) + { + StringBuilder sb = new StringBuilder(); + sb.Append("" + Util.GenerateRandomCode(20) + "weixin" + Util.TimeStamp() + "000"); + sb.Append("" + content + ""); + sb.Append("0"); + sb.Append(""); + sb.Append("1"); + sb.Append("0"); + sb.Append(""); + sb.Append(""); + sb.Append("https://support.weixin.qq.com/cgi-bin/mmsupport-bin/readtemplate?t=page/common_page__upgrade&v=1"); + sb.Append(""); + if (images != null) + { + foreach (string temp in images) + { + var url = UplodCircleImage(temp); + //Console.WriteLine("url=" + url); + if (string.IsNullOrEmpty(url)) + continue; + sb.Append(""); + sb.Append("" + Util.GenerateRandomCode(20) + ""); + sb.Append("2"); + sb.Append(""); + sb.Append(""); + sb.Append("0"); + sb.Append("" + url + ""); + sb.Append("" + url + ""); + sb.Append(""); + sb.Append(""); + } + } + sb.Append(""); + sb.Append(""); + return sb.ToString(); + + } + + /// + /// 开始上传图片 + /// + private string UplodCircleImage(string url) + { + try + { + var urlResult = string.Empty; + for (int i = 0; i < 8; i++) + { + byte[] data; + if (url.StartsWith("http")) + { + url = url.Replace("&", ""); + if (url.Contains("qpic.cn")) return url; + HttpHelper http = new HttpHelper(); + var item = http.GetItem(url); + item.ResultType = CsharpHttpHelper.Enum.ResultType.Byte; + data = http.GetHtml(item).ResultByte; + } + else + { + FileInfo aFileInfo = new FileInfo(url); + using (FileStream fsRead = aFileInfo.Open(FileMode.Open)) + { + int fsLen = (int)fsRead.Length; + data = new byte[fsLen]; + fsRead.Read(data, 0, data.Length); + } + } + + data = Util.CompressionImage(new MemoryStream(data), 25); + + WechatPack send = new WechatPack(this); + byte[] result = null; + + string ClientImgId = User.Username + "_" + Util.TimeStamp().ToString(); + + var send_data = new + { + StartPos = 0, + ClientId = ClientImgId, + TotalLen = data.Length, + Uploadbuf = data, + }; + + result = send.SendAll(WechatCmd.上传朋友圈图片, true, send_data); + urlResult = Encoding.UTF8.GetString(result); + + if (string.IsNullOrWhiteSpace(urlResult)) + { + Thread.Sleep(100); + continue; + } + break; + } + return urlResult; + } + catch + { + return string.Empty; + } + } + #endregion + + #endregion + + #region 基础函数 + private string HexToStr(byte[] bytes) + { + string returnStr = ""; + if (bytes != null) + { + for (int i = 0; i < bytes.Length; i++) + { + returnStr += bytes[i].ToString("x2"); + } + } + return returnStr; + } + private string SixTwoData(string imei) + { + string hexStr = HexToStr(Encoding.UTF8.GetBytes(imei)).Replace(" ", ""); + string str = "62706c6973743030d4010203040506090a582476657273696f6e58246f626a65637473592461726368697665725424746f7012000186a0a2070855246e756c6c5f1020" + hexStr + "5f100f4e534b657965644172636869766572d10b0c54726f6f74800108111a232d32373a406375787d0000000000000101000000000000000d0000000000000000000000000000007f"; + return str; + } + + WxQrcode _loginWxQrcode; + WechatPack _loginPack; + + + /// + /// 获得登录图片 + /// + public void FindLoginImage(LoginDeviceType type) + { + try + { + Connection(); + + this.User = new WeixinBaseUser(new User() { SessionKey = ByteString.CopyFrom(WXClientTool.random_encry_key), DeviceId = DeviceId }); + this.LoginDeviceType = type; + _loginPack = new WechatPack(this); + var data = new + { + ProtocolVer = (int)this.LoginDeviceType,//此处只有1 3 5值 + DeviceName = DeviceName + }; + ChangeStatus(WxStatus.登录中); + //WriteLog("获取二维码0"); + var byteData = _loginPack.Send(WechatCmd.获取登录二维码, data); + //WriteLog("获取二维码1"); + byteData = _loginPack.SendWx(byteData); + //WriteLog("获取二维码2"); + byteData = _loginPack.Analysis(byteData); + //WriteLog("获取二维码3"); + string _temp = Encoding.UTF8.GetString(byteData); + _loginWxQrcode = JsonConvert.DeserializeObject(_temp); + + this._loginTemp = new LoginTemp(); + this._loginTemp.UUId = _loginWxQrcode.Uuid; + this._loginTemp.NotifyKey = _loginWxQrcode.NotifyKey; + this._loginTemp.LongHead = _loginPack.Req.BaseMsg.LongHead; + this._loginTemp.HeadFlag = false; + ChangeStatus(WxStatus.扫码中, new WXChangeStatus(this) { ImageByte = _loginWxQrcode.ImgBuf }); + } + catch (Exception ex) + { + throw ex; + } + } + private LoginTemp _loginTemp; + private string UUID { get; set; } + private string DeviceType { get; set; } + class LoginTemp + { + public string UUId { get; set; } + public byte[] NotifyKey { get; set; } + public ByteString LongHead { get; set; } + public bool HeadFlag { get; set; } + } + + /// + /// 实现发红包 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public override string SendPay(string toUsername, string content, int TotalAmount, string password, int count, PayType type, BankCar bank = null, Dictionary param = null) + { + try + { + int code = 385; + string payloadJson = string.Empty; + if (type == PayType.红包) + { + payloadJson = "{\"CgiCmd\":1,\"HBType\":\"0\",\"HBFrom\":\"0\",\"ToUsername\":\"" + toUsername + "\",\"Count\":\"" + count + "\",\"TotalAmount\":\"" + TotalAmount + "\",\"HBContent\":\" " + content + "\"}"; + } + else + { + payloadJson = "{\"CgiCmd\":83,\"Desc\":\"" + content + "\",\"ToUsername\":\"" + toUsername + "\",\"Count\":\"" + TotalAmount + "\"}"; + } + + WechatPack send = new WechatPack(this); + //CMD = 385 + + var data = send.Send(code, payloadJson); + data = send.Analysis(data); + string text = Encoding.UTF8.GetString(data); + string ReqKey = string.Empty; + if (type == PayType.红包) + ReqKey = WXClientTool.BetweenArr(text, "reqkey\":\"", "\",\"scene"); + else + ReqKey = WXClientTool.BetweenArr(text, "req_key\":\"", "\",\"tansfering_status"); + + if (bank != null) + { + payloadJson = Util.ObjectToJson(new + { + CgiCmd = 0, + ReqKey = ReqKey, + PassWord = password, + Bank_TYPE = bank.bank_type, + Bind_SERIAL = bank.bind_serial + }); + } + else + { + payloadJson = Util.ObjectToJson(new + { + CgiCmd = 0, + ReqKey = ReqKey, + PassWord = password + }); + } + + data = send.Send(code, payloadJson); + //data = send.SendWx(data); + if (data == null) + throw new Exception("服务器繁忙,请稍后重试"); + data = send.Analysis(data); + + text = Encoding.UTF8.GetString(data); + //Console.WriteLine(text); + + if (text.Contains("支付成功") || text.Contains("请确认银行卡是否扣款后再试")) return null; + else + { + if (param != null) + { + param["reqKey"] = ReqKey; + param["bank"] = bank; + param["isHongbao"] = type == PayType.红包 ? true : false; + param["result"] = text; + param["pass"] = password; + } + this.WriteLog("支付失败:" + text); + return text; + } + } + catch (Exception ex) + { + if (ex.Message.Contains("请确认银行卡是否扣款后再试")) return null; + //else if (ex.Message.Contains("服务器繁忙,请稍后重试")) return null; + this.WriteLog("支付失败:" + ex.Message); + return ex.Message; + } + } + + /// + /// 登录状态检测 + /// + public void FindLoginStatus() + { + try + { + if (_loginWxQrcode.Status == 2) + { + return; + } + + if (_loginWxQrcode == null) return; + + if (_loginWxQrcode.Status == 4) + { + ChangeStatus(WxStatus.取消扫码); + return; + } + + if (_loginWxQrcode.Status == 1 && !_loginTemp.HeadFlag) + { + //lab_ShowMsg.Text = "已扫描 未确认"; + using (WebClient _client = new WebClient()) + { + _loginTemp.HeadFlag = true; + ChangeStatus(WxStatus.获取头像成功, new WXChangeStatus(this) { ImageByte = _client.DownloadData(_loginWxQrcode.HeadImgUrl) }); + } + } + + this.User.User.MaxSyncKey = ByteString.CopyFrom(this._loginTemp.NotifyKey); + + var data = _loginPack.Send(WechatCmd.获取二维码状态, Encoding.UTF8.GetBytes(this._loginTemp.UUId), this._loginTemp.LongHead); + + data = _loginPack.SendWx(data); + + data = _loginPack.Analysis(data); + + var text = Encoding.UTF8.GetString(data); + _loginWxQrcode = JsonConvert.DeserializeObject(text); + if (_loginWxQrcode != null) ChatClient.Events.OnEvent(new WXScavengEvents(this) { Status = _loginWxQrcode.Status }); + + if (_loginWxQrcode.Status == 2) + { + UUID = Util.MD5Encrypt(_loginWxQrcode.Username); + Password = _loginWxQrcode.Password; + Login(_loginWxQrcode.Username, _loginWxQrcode.Password); + } + } + catch (Exception ex) + { + //ChatClient.Events.OnEvent(new WXWriteLog(this) { Message = ex.Message+","+ex.StackTrace} ); + } + + } + private LoginDeviceType LoginDeviceType = LoginDeviceType.未知; + /// + /// 登录密码 + /// + public string Password { get; set; } + + internal bool Login(string username, string userpass, string data62 = "") + { + try + { + //if (LoginDeviceType == LoginDeviceType.未知) LoginDeviceType = LoginDeviceType.Windows; + #region 执行登录 + Status = WxStatus.登录中; + //构造二维码登陆封包结构 + string UUid = Guid.NewGuid().ToString();//随机uuid 667D18B2-BCE3-4AA2-8ED1-7FDC19446567 + string md5 = Util.MD5Encrypt(username); + + this.DeviceType = string.Format("TP_lINKS_5G中国移动{0}:{1}:{2}:{3}:{4}:{5}", md5.Substring(0, 2), md5.Substring(2, 4), md5.Substring(4, 6), md5.Substring(6, 8), md5.Substring(8, 10), md5.Substring(8, 12)); // string DeviceType = "TP_lINKS_5G中国移动c1:cd:2d:1c:5b:11";//随机 单号保持同一设备信息 + if (this.LoginDeviceType == LoginDeviceType.未知) this.LoginDeviceType = LoginDeviceType.Windows; + // "{\"Username\":\"" + username + "\",\"PassWord\":\"" + userpass + "\",\"UUid\":\"" + UUid + "\",\"DeviceType\":\"" + DeviceType + "\"}"; + var payLoadJson = new + { + Username = username, + PassWord = userpass, + UUid = UUid, + DeviceType = DeviceType, + DeviceName = DeviceName,//新增的字段 + ProtocolVer = (int)this.LoginDeviceType + + }; + + + //this.User = new User() { SessionKey = ByteString.CopyFrom(randomEncryKey), DeviceId = DeviceId }; + int cmd = (this.LoginDeviceType == LoginDeviceType.QQBrowser) ? 380 : 1111; + if (userpass.Length <= 32 && !string.IsNullOrEmpty(data62)) + { + Connection(); + + //this.LoginDeviceType = LoginDeviceType.Ipad; + this.DeviceId = data62; + _loginPack = new WechatPack(this); + cmd = 2222; + this.User = new WeixinBaseUser(new User() { SessionKey = ByteString.CopyFrom(WXClientTool.random_encry_key), DeviceId = DeviceId }); + this.User.User.MaxSyncKey = ByteString.CopyFrom(WXClientTool.random_encry_key); + } + + + byte[] data = _loginPack.Send(cmd, payLoadJson); + + + //Socket.Connect(); + var _data = _loginPack.SendWx(data); + _loginPack.Req.BaseMsg.Cmd = (cmd == 380) ? -380 : -1001; + _loginPack.Req.BaseMsg.Payloads = ByteString.CopyFrom(_data); + _data = _loginPack.Send(_loginPack.Req); + var ret = _loginPack.Req.BaseMsg.Ret; + if (ret >= 10000001) + { + switch (ret) + { + case 10000001: + case 10000002: + case 10000003: + case 10000004: + case 10000005: + //Console.WriteLine(Encoding.UTF8.GetString(_data)); + break; + } + } + var str = Encoding.UTF8.GetString(_data); + if (ret < 0 && ret != -301) + { + throw new Exception(str); + } + + var retData = _loginPack.Req.BaseMsg.Playloadextend.ToByteArray(); + string json = Encoding.UTF8.GetString(_loginPack.Req.BaseMsg.Playloadextend.ToByteArray()); + var list = Util.ConvertJsonToDic(json); + + //bool flag = false; + //Next: + string longServer = _loginPack.Req.BaseMsg.LongHost; + string shortServer = _loginPack.Req.BaseMsg.ShortHost; + + + this.Host = new WechatHost(); + + // Console.WriteLine(shortServer); + string msg = Encoding.UTF8.GetString(_loginPack.Req.BaseMsg.Playloadextend.ToByteArray()); + + var LongServerList = Util.ConvertJsonToDic(msg)["LongServerList"] as ArrayList; + var ShortServerList = Util.ConvertJsonToDic(msg)["ShortServerList"] as ArrayList; + + //this.Host.LongServerList.Add(longServer); + //this.Host.LongServerList.Add(shortServer); + //foreach (string item in LongServerList) + //{ + // this.Host.LongServerList.Add(item); + //} + + foreach (string item in ShortServerList) + { + if (item == "127.0.0.1") continue; + this.Host.ShortServerList.Add(item); + } + //Socket.UpdateServerIp(msg); + //Socket.Send + //重新注册及连接微信 + if (_loginPack.Req.BaseMsg.Ret == -301)//重定向 + { + this.Host.BindLongip(_loginPack.Req.BaseMsg.LongHost); + Socket.Connect(); + //Console.WriteLine("WX longServer IP:{0}", longServer); + //Console.WriteLine("WX shortServer IP:{0}", shortServer); + Thread.Sleep(200); + + _data = _loginPack.SendWx(data);//获得微信返回数据 + Thread.Sleep(200); + + _data = _loginPack.Analysis(cmd == 380 ? -380 : -1001, _data); + } + + + if (_loginPack.Req.BaseMsg.Ret == 0)//登陆成功 + { + + this.Host.BindLongip(this.Socket.ServerIp); + //保存用户解构信息 + User.User = _loginPack.Req.BaseMsg.User; + + //如果为0,暂时不验证授权 + //Console.WriteLine(User.Uin.ToString()); + if (User.Uin.ToString() != "0") + { + Grant.Framework.GrantClient.Get().Login(User.Uin.ToString(), User.Nick, int.Parse(WXClientTool.auth_info[0]), WXClientTool.auth_info[1]); + } + + + shortServer = _loginPack.Req.BaseMsg.ShortHost; + Initialization(); + ChangeStatus(WxStatus.在线); + return true; + } + else + { + string message = string.Empty; + if (_loginPack.Req.BaseMsg.Ret == -301) + message = "暂时无法识别您的帐号,请更换帐号。"; + else + message = Encoding.UTF8.GetString(_data); + Console.WriteLine(message); + throw new Exception(message); + //ChangeStatus(WxStatus.登录失败, new WXChangeStatus(this, message)); + } + #endregion + } + catch (Exception ex) + { + LoginErrorMessage = ex.Message; + ChangeStatus(WxStatus.登录失败, new WXChangeStatus(this, ex.Message)); + return false; + } + finally + { + if (Status != WxStatus.在线) + { + this.Socket.Stop(); + } + else LoginErrorMessage = string.Empty; + } + } + public string LoginErrorMessage { get; private set; } + internal string GetLoginCode(string username) + { + Connection(); + + this.User = new WeixinBaseUser(new User() { SessionKey = ByteString.CopyFrom(WXClientTool.random_encry_key), DeviceId = DeviceId }); + + var obj = new + { + Opcode = 16, + Mobile = username,//自己微信号绑定的手机号 没有绑定手机的 获取不聊 + Imei = this.Ime + "-" + Util.TimeStamp().ToString(), + DeviceName = this.DeviceName, + Language = "CN" + }; + + WechatPack pack = new WechatPack(this); + var req = pack.Send(145, obj); + var rsp = pack.Analysis(req); + var str = Encoding.UTF8.GetString(rsp); + + //string msg = Encoding.UTF8.GetString(_loginPack.Req.BaseMsg.Playloadextend.ToByteArray()); + + //var LongServerList = Util.ConvertJsonToDic(str)["LongServerList"] as ArrayList; + //var ShortServerList = Util.ConvertJsonToDic(str)["ShortServerList"] as ArrayList; + + //foreach (string item in LongServerList) + //{ + // this.Host.LongServerList.Add(item); + //} + + //foreach (string item in ShortServerList) + //{ + // if (item == "127.0.0.1") continue; + // this.Host.ShortServerList.Add(item); + //} + + + + //Socket.UpdateServerIp(new string[] { pack.Req.BaseMsg.ShortHost }.ToList()); + + //重新注册及连接微信 + if (pack.Req.BaseMsg.Ret == 0) + { + return string.Empty; + } + else if (pack.Req.BaseMsg.Ret == -301)//重定向 + { + //var shortServer = pack.Req.BaseMsg.ShortHost; + + //var _data = Socket.SendWeChatPost(req, pack.Req.BaseMsg.CmdUrl); + //rsp = pack.Analysis(req); + //str = Encoding.UTF8.GetString(rsp); + //return str; + } + else + { + return str; + } + + return null; + + } + + internal string VerifyLoginSmsCode(string username, string code) + { + object obj = new + { + Opcode = 17, + Mobile = username,//手机号 + Imei = this.Ime + "-" + Util.TimeStamp().ToString(), + Verifycode = code, + DeviceName = DeviceName, + Language = "CN" + }; + WechatPack pack = new WechatPack(this); + var req = pack.Send(145, obj); + var rsp = pack.Analysis(req); + var str = Encoding.UTF8.GetString(rsp); + return str; + } + + + + /// + /// 获得银行卡 + /// + /// + public List FindBankCar() + { + var username = "wxid_8s44kddouuaj21"; + if (Status != WxStatus.在线) throw new Exception("请先登录微信!"); + + + int code = 385; + string payloadJson = "{\"CgiCmd\":1,\"HBType\":\"0\",\"HBFrom\":\"0\",\"ToUsername\":\"" + username + "\",\"Count\":\"1\",\"TotalAmount\":\"1\",\"HBContent\":\"测试\"}"; + + WechatPack send = new WechatPack(this); + var data = send.Send(WechatCmd.获得银行卡, payloadJson); + + data = send.Analysis(data); + + string text = Encoding.UTF8.GetString(data); + string ReqKey = WXClientTool.BetweenArr(text, "reqkey\":\"", "\",\"scene"); + + + payloadJson = CsharpHttpHelper.HttpHelper.ObjectToJson(new + { + CgiCmd = 1569, + ReqKey = ReqKey//创建好支付解构 调用调用此方法 查询银行卡的绑定ID以及类型 + }); + + data = send.Send(WechatCmd.获得银行卡, payloadJson); + data = send.Analysis(data); + string json = Encoding.UTF8.GetString(data); + var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(json); + if (dic.ContainsKey("bindqueryresp")) + { + dic = dic["bindqueryresp"] as Dictionary; + var list = dic["Array"] as ArrayList; + if (list != null && list.Count > 0) + { + List cars = new List(); + foreach (Dictionary item in list) + { + cars.Add(new BankCar() + { + bank_name = item["bank_name"].ToString(), + bind_serial = item["bind_serial"].ToString(), + bind_tail = item["bind_tail"].ToString(), + bank_type = item["bank_type"].ToString() + }); + } + return cars; + } + } + return new List(); + } + + /// + /// 显示登录窗口 + /// + public override void ShowLogin() + { + try + { + //Connection();//链接 + new LoginForm(this).ShowDialog(); + } + catch (Exception ex) + { } + } + + internal void ShowPasswordForm() + { + Connection(); + new LoginwxPassForm(this).ShowDialog(); + } + + #endregion + + #region 连接 + + public void CloseGRPC(bool timeout) + { + lock (lock_grpcp) + { + foreach (var item in GrpcPool.Values) + { + try + { + if (timeout) + { + var time = DateTime.Now - item.LastTime; + if (time.TotalMinutes > 15) item.Stop(); + } + else item.Stop(); + } + catch (Exception) + { + } + } + } + } + private object lock_grpcp = new object(); + /// + /// Grpc 池 + /// + private Dictionary GrpcPool = new Dictionary(); + + internal GrpcClient GetGrpcClient(GrpcType type, bool refresh = false) + { + + lock (lock_grpcp) + { + GrpcClient client = null; + if (GrpcPool.ContainsKey(type)) client = GrpcPool[type]; + else + { + client = new GrpcClient(GrpcConfig.Get(type, true)); + GrpcPool[type] = client; + } + + if (refresh || !client.IsConnected) + client.Init(); + return client; + } + + } + + + private bool Connection() + { + + //this.GetGrpcClient(GrpcType.Huangfan).Init(); + //this.GetGrpcClient(GrpcType.Huangfan).Init(); + return this.Socket.Connect(); + + } + #endregion + + #region Win32 + + #endregion + + #region IPAD协议 + + public WechatHost Host { get; private set; } + public WechatSocket Socket { get; private set; } + + /// + /// 强制拉取消息 + /// + /// + public bool AsyncSyncMessage() + { + bool is_netxt = false; + Next: + try + { + WechatPack send = new WechatPack(this); + var buffers = WXClientTool.CPackSync(this.User.User); + if (buffers == null) throw new Exception("WeChat 未响应数据!1"); + + int Seq = Util.ReadInt(buffers, 12); + buffers = send.SendWx(buffers, Seq); + if (buffers == null) throw new Exception("WeChat 未响应数据!2"); + + byte[] encodeBuf = new byte[buffers.Length - 16];//提取长连接的body 去掉头16个字节 + Buffer.BlockCopy(buffers, 16, encodeBuf, 0, buffers.Length - 16); + byte[] syncKey = new byte[] { }; + var data = CUnPackSync(this.User.User, encodeBuf, ref syncKey); + if (data == null) this.FastLogin(); + if (syncKey.Length > 0) + { + User.User.CurrentsyncKey = ByteString.CopyFrom(syncKey); + //if (this.Status != WxStatus.在线) ChangeStatus(WxStatus.在线); + } + + var result = Encoding.UTF8.GetString(data); + if (result == "offline") + { + if (!is_netxt) + { + is_netxt = true; + goto Next; + } + return false; + } + + if (this.Status != WxStatus.在线) ChangeStatus(WxStatus.在线); + + if (result == "null") + return true; + if (User.LoginTime > DateTime.Now.AddSeconds(-10)) return true; + AnalysisMessage(result); + return true; + } + catch (Exception ex) + { + if (this.Status == WxStatus.在线) + WriteLog($"同步消息失败:{ex.Message}"); + else + LogHelper.GetSingleObj().Error("AsyncSyncMessage", $"{this.WeixinHao}-{ex.Message}"); + } + return false; + } + + private List pack = new List(); + + /// + /// 快速初始化通讯录列表 + /// + /// + public bool Initialization() + { + try + { + this.Friends.Clear(); + Next: + WechatPack send = new WechatPack(this); + var data = send.SendAll(WechatCmd.初始化用户信息, true); + if (send.Req.BaseMsg.Ret != 8888) + { + var json = Encoding.UTF8.GetString(data); + if (json != "null") + { + var list = Util.ConvertJsonToObj(json); + foreach (Friend item in list) + { + if (item == null || string.IsNullOrEmpty(item.UserName)) + Console.WriteLine(); + else + Friends[item.UserName] = item; + } + } + goto Next; + } + + return true; + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("Initialization ERROR: ", $"{this.WeixinHao}-{ex.Message}"); + } + return false; + } + + + internal bool DecodeSecureNotifyThread(byte[] data) + { + return false; + } + + internal string _client_ip; + internal string clientIp + { + get + { + if (string.IsNullOrEmpty(_client_ip)) _client_ip = Util.GetPublicIpAdress(); + return _client_ip; + } + } + + public string DeviceId { get; internal set; } + internal string DeviceName = "FLSystem"; + //internal int ProtocolVer = 7; + + + public WXClientImpl_IPAD() + { + this.Host = new WechatHost(); + this.Socket = new WechatSocket(this); + WeixinType = WeixinType.Grpc微信; + GroupMembers = new Dictionary(); + Friends = new Dictionary(); + Status = WxStatus.未登录; + + //Socket.ReceivedNotifyMessage += Socket_ReceivedNotifyMessage; + Socket.ReceivedOnConnected += Socket_ReceivedOnConnected; + Socket.ReceivedOnDisconnected += Socket_ReceivedOnDisconnected; + + GroupMemberCache = new Dictionary>(); + ThreadPool.RegisterWaitForSingleObject(new AutoResetEvent(true), new WaitOrTimerCallback((state, timedout) => + { + try + { + if (Status == WxStatus.在线) + SyncGroup(); + } + catch (Exception ex) + { } + }), null, 10 * 1000, false);//30秒执行一次 + + } + + private void Socket_ReceivedOnDisconnected(object sender, IPAddress e) + { + //Console.WriteLine(); + //try + //{ + // this.Socket.Connect(this.Host.GetLong()); + //} + //catch (Exception) + //{ + //} + } + + private void Socket_ReceivedOnConnected(object sender, IPAddress e) + { + //this.WriteLog($"服务器 {e.ToString()} 重连成功!"); + //this.WriteLog($"服务器 {e.ToString()} 已链接!"); + + //this.WriteLog($"服务器 {e.ToString()} 已链接!" + Status); + //if (Status == WxStatus.在线) + //{ + // this.WriteLog($"服务器 {e.ToString()} 重连成功!", false); + // Thread.Sleep(300); + // AsyncSyncMessage(); + //} + //else + //{ + // this.WriteLog($"服务器 {e.ToString()} 连接成功!", false); + //} + //ChangeStatus(this.Status); + } + + //private void Socket_ReceivedNotifyMessage(object sender, WeChatMessage message) + //{ + // //新起线程,否则会影响socket + + // Task.Factory.StartNew(() => + // { + // var buffer = message.Msg.BaseMsg.Payloads.ToByteArray(); + + // switch (message.CmdID) + // { + // case 24: + // if (Util.HexToStr(buffer) == "0000001400100001000000180000000000000100") + // { + // //朋友圈更新Notify + // //Client.SyncMessage(true); + // } + // else + // { + // //普通消息Notify + // Task.Factory.StartNew(AsyncSyncMessage); + // } + // break; + // case 318: + // DecodeSecureNotifyThread(buffer); + // break; + // default: + // Console.WriteLine($"ReceivedUnKnowMessage CMD:{message.CmdID}"); + // break; + // } + // }); + //} + + public bool IsRunning => throw new NotImplementedException(); + + public RegisteredWaitHandle RegisterdHandler { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public WaitHandle WaitHandler { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + #endregion + + private HeadPack head = null; + private DateTime lastGetInfo; + + /// + /// 获取群信息 + /// + /// + private void GetGroupInfo(string groupid) + { + lock (GroupMembers) + { + try + { + if (!Friends.ContainsKey(groupid)) + { + var f = GetContact(groupid); + if (f != null) Friends[groupid] = f; + } + if (lastGetInfo > DateTime.Now.AddSeconds(-1)) + { + Thread.Sleep(1000); + } + + WechatPack send = new WechatPack(this); + var data = send.Send(WechatCmd.获取群信息, new { Chatroom = groupid }); + data = send.Analysis(data); + string text = Encoding.UTF8.GetString(data); + + var dic = Util.ConvertJsonToDic(text); + var obj = Util.ObjectToJson(dic["MemberDetails"]); + GroupMember[] temp = Util.ConvertJsonToObj(obj) as GroupMember[]; + if (temp != null) + GroupMembers[groupid] = temp; + lastGetInfo = DateTime.Now; + //Console.WriteLine(); + } + catch (Exception ex) + { + this.WriteLog(ex.Message); + } + } + } + public Dictionary GroupMembers { get; private set; } + + public override GroupMember[] GetMembers(string groupid, bool flag = false) + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("取群成员")) + { + if (flag || !GroupMembers.ContainsKey(groupid)) + GetGroupInfo(groupid); + if (GroupMembers.ContainsKey(groupid)) return GroupMembers[groupid]; + else return null; + } + else + return null; + } + + public override GroupMember GetMember(string groupid, string wxid) + { + if (!GroupMembers.ContainsKey(groupid)) + GetGroupInfo(groupid); + + if (GroupMembers.ContainsKey(groupid)) + { + var member = GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + + if (member == null) + GetGroupInfo(groupid); + else return member; + } + else + return new GroupMember() { Groupid = groupid, Username = wxid }; + if (GroupMembers.ContainsKey(groupid) && GroupMembers[groupid] != null) + return GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + else + return new GroupMember() { Groupid = groupid, Username = wxid }; + } + + //private void OnAnalysisMessage + + /// + /// 执行二次登录 + /// + /// + public string FastLogin() + { + try + { + this.Status = WxStatus.登录中; + if (LoginDeviceType == LoginDeviceType.未知) return $"此版本升级,需要重新登陆!"; + byte[] data = null; + WechatPack send = new WechatPack(this); + if (this.LoginDeviceType == LoginDeviceType.QQBrowser) + { + var obj = new + { + UUId = UUID, + DeviceType = DeviceType, + DeviceName = DeviceName, + ProtocolVer = (int)this.LoginDeviceType, + PassWord = Password + }; + data = send.SendAll(WechatCmd.浏览器加密登录, true, obj); + //return null; + } + else + { + var obj = new + { + UUId = UUID, + DeviceType = DeviceType, + DeviceName = DeviceName, + ProtocolVer = (int)this.LoginDeviceType, + }; + data = send.SendAll(WechatCmd.执行二次登陆, true, obj); + } + + string result = Encoding.UTF8.GetString(data); + if (string.IsNullOrEmpty(result)) return null; + + var reg = Regex.Match(result, @""); + + if (reg.Success) + { + this.WriteLog("快速登陆失败:" + reg.Groups[1].Value); + ChangeStatus(WxStatus.已掉线, null, false); + return result; + } + else + { + if (result.Length > 15 || result == "登录出现错误,请你重新登录。") return null; + + var msg = GetChineseWord(result); + if (string.IsNullOrEmpty(msg)) return null; + this.WriteLog("快速登陆失败:" + result); + return result; + } + } + catch (Exception ex) + { + return ex.Message; + } + } + private string GetChineseWord(string oriText) + { + string x = @"[\u4E00-\u9FFF]+"; + MatchCollection Matches = Regex.Matches + (oriText, x, RegexOptions.IgnoreCase); + StringBuilder sb = new StringBuilder(); + foreach (Match NextMatch in Matches) + { + sb.Append(NextMatch.Value); + } + return sb.ToString(); + } + public override void ChangeStatus(WxStatus status, WXChangeStatus e = null, bool is_next = true) + { + if (status == WxStatus.已掉线 || status == WxStatus.已退出 || status == WxStatus.未登录 || status == WxStatus.登录失败) + { + if (this.User != null && this.User.Uin != 0) Grant.Framework.GrantClient.Get().LoginOut(this.User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0])); + if (this.Socket != null) this.Socket.Stop(); + this.CloseGRPC(false); + if (head != null) ThreadExcutor.UnRegisterIntervaluObject(head); + head = null; + } + + if (status == WxStatus.在线) + { + var v = this.User.User; + if (head == null) + { + try + { + if (User.Uin.ToString() != "0") Grant.Framework.GrantClient.Get().Login(User.Uin.ToString(), User.Nick, int.Parse(WXClientTool.auth_info[0]), WXClientTool.auth_info[1]); + head = new HeadPack(this); + } + catch (Exception ex) + { + status = WxStatus.登录失败; + this.WriteLog("检测授权异常:" + ex.Message); + } + } + } + else + { + this.Lables.Clear(); + } + + if (this.Status == WxStatus.已掉线 && status == WxStatus.已退出) return; + //if (this.Status == WxStatus.未登录) return; + base.ChangeStatus(status, e, is_next); + } + + public bool IsResetConnection { get; private set; } + /// + /// 重新连接 + /// + public override void ResetConnection(int next = 3) + { + if (IsResetConnection) return; + IsResetConnection = true; + try + { + if (string.IsNullOrEmpty(this.DeviceType)) + { + string md5 = Util.MD5Encrypt(this.User.Username); + this.DeviceType = string.Format("TP_lINKS_5G中国移动{0}:{1}:{2}:{3}:{4}:{5}", md5.Substring(0, 2), md5.Substring(2, 4), md5.Substring(4, 6), md5.Substring(6, 8), md5.Substring(8, 10), md5.Substring(8, 12)); + } + for (int i = 1; i <= next; i++) + { + + //if (i > 2) this.Host.LongServerList.Clear(); + Connection(); + if (i > 1) + { + var msg = this.FastLogin(); + if (msg != null && Regex.Match(msg, "(已退出)|(重新登录)|安全").Success) + { + ChangeStatus(WxStatus.已退出); + return; + } + } + //var flag = this.Initialization(); + + //else + //{ + // this.Initialization(); + //} + + if (this.AsyncSyncMessage()) + { + ChangeStatus(WxStatus.在线); + break; + } + + //this.Initialization(); + //if (this.AsyncSyncMessage()) + //{ + + //} + Thread.Sleep(2000); + } + if (Status != WxStatus.在线) + { + ChangeStatus(WxStatus.已掉线); + WriteLog($"经过了{next}次登陆,无法自动登陆!"); + } + else + { + //RefreshContact();//刷新通讯录 + } + } + catch (Exception ex) + { + this.WriteLog("WxSocket连接异常:" + ex.Message); + this.Socket.Stop(); + ChangeStatus(WxStatus.登录失败); + } + finally + { + IsResetConnection = false; + } + } + + /// + /// 退出登录 + /// + public override void LoginOut() + { + //Console.WriteLine($"登录前:{DeviceId}\r\n登陆后:{this.User.User.DeviceId}"); + if (this.Status != WxStatus.已掉线) ChangeStatus(WxStatus.已退出); + } + + public void Dispose() + { + if (this.User != null && this.User.Uin != 0) Grant.Framework.GrantClient.Get().LoginOut(this.User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0])); + if (this.Socket != null) this.Socket.Stop(); + if (head != null) ThreadExcutor.UnRegisterIntervaluObject(head); + } + + public override Dictionary GetBalance() + { + //此处只有短链接 + + + WechatPack pack = new WechatPack(this); + var result = pack.Send(WechatCmd.获得银行卡, new + { + CgiCmd = 72 + }); + result = pack.Analysis(WechatCmd.获得银行卡, result); + var info = Encoding.UTF8.GetString(result); + return CsharpHttpHelper.HttpExtend.JsonToDictionary(info); + + + } + + /// + /// 阅读文章 + /// + /// + /// + public void ReadURL(string requrl) + { + WechatPack web = new WechatPack(this); + var obj2 = new + { + + ReqUrl = requrl,//要获取key的连接 授权登陆时的链接即为转跳链接https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx53c677b55caa45fd&redirect_uri=http%3A%2F%2Fmeidang.cimiworld.com%2Fh5%2Fchourenpin%3Fs%3D77e881961fee12eb65f5497bbff02fac%26from%3Dsinglemessage%26isappinstalled%3D0&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect + Scene = 2,//Scene = 2 来源好友或群 必须设置来源的id 3 历史阅读 4 二维码连接 7 来源公众号 必须设置公众号的id + Username = "", //来源 来源设置wxid 来源群id@chatroom 来源公众号gh_e09c57858a0c原始id + ProtocolVer = 1 //ProtocolVer 1-5 + }; + var data = web.SendAll(WechatCmd.GetA8Key, true, obj2); + var str = WXClientTool.Usc2ToAnsi(Encoding.UTF8.GetString(data)); + var json = CsharpHttpHelper.HttpExtend.JsonToDictionary(str); + var __biz = Regex.Match(json["Url"].ToString(), "__biz=([^&]+)").Groups[1].Value; + var mid = Regex.Match(json["Url"].ToString(), "mid=([^&]+)").Groups[1].Value; + var sn = Regex.Match(json["Url"].ToString(), "sn=([^&]+)").Groups[1].Value; + + var idx = Regex.Match(json["Url"].ToString(), "idx=([^&]+)").Groups[1].Value; + + var pass_ticket = Regex.Match(json["Url"].ToString(), "pass_ticket=([^&]+)").Groups[1].Value; + var http = new CsharpHttpHelper.HttpHelper(); + //https://mp.weixin.qq.com/s?__biz=MzI3ODIxNDcyOQ==&mid=2247486232&idx=1&sn=b8f60db37aa502af496baa4207feca38&ascene=2&devicetype=iPad+iPhone+OS9.3.3&version=16060520&nettype=WIFI&lang=zh_CN&fontScale=100&pass_ticket=mED1lf4PhfHVcXJj9bQsRRNi9wtql9pzkw1ZY5TrjPeIdU9iqbGD0hYz4fxDz%2FI8&wx_header=1 + var url = $"https://mp.weixin.qq.com/s?__biz={__biz}&mid={mid}&idx={idx}&sn={sn}&chksm=fa24a0c0cd5329d66f837dd1d7a36301011ed081faef006fa8a5f7829cd6dc1347a792f44ff8&mpshare=1&scene=1&srcid=&key={json["XWechatKey"]}&ascene=1&uin={json["XWechatUin"]}&devicetype=Windows+10&version=62060739&lang=zh_CN&pass_ticket={pass_ticket}&winzoom=1"; + var item = http.GetItem(url); + item.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.1021.400 QQBrowser/9.0.2524.400"; + + var html = http.GetHtml(item).Html; + var appmsg_type = Regex.Match(html, "appmsg_type = \"(\\d+)\";").Groups[1].Value; + //comment_id + var comment_id = Regex.Match(html, "comment_id = \"(\\d+)\"").Groups[1].Value; + var ct = Regex.Match(html, "ct = \"(\\d+)\";").Groups[1].Value; + var msg_title = Regex.Match(html, "msg_title = \"(.*?)\";").Groups[1].Value; + var req_id = Regex.Match(html, "req_id = '(.*?)';").Groups[1].Value; + + + var appmsg_token = Regex.Match(html, "appmsg_token = \"(.*?)\";").Groups[1].Value; + string goto_url = $"https://mp.weixin.qq.com/mp/getappmsgext?f=json&mock=&uin={json["XWechatUin"]}&key={json["XWechatKey"]}&pass_ticket={pass_ticket}&wxtoken=777&devicetype=Windows%26nbsp%3B10&clientversion=62060739&appmsg_token={appmsg_token}&x5=0&f=json"; + string goto_data = $"r={new Random(Guid.NewGuid().GetHashCode()).NextDouble()}&__biz={__biz}&appmsg_type={appmsg_type}&mid={mid}&sn={sn}&idx={idx}&scene=&title={HttpHelper.URLEncode(msg_title)}&ct={ct}&abtest_cookie=&devicetype=Windows%2010&version=62060739&is_need_ticket=0&is_need_ad=0&comment_id={comment_id}&is_need_reward=0&both_ad=0&reward_uin_count=0&send_time=&msg_daily_idx=1&is_original=0&is_only_read=1&req_id={req_id}&pass_ticket={pass_ticket}&is_temp_url=0&item_show_type=0&tmp_version=1&more_read_type=0&appmsg_like_type=2"; + //var post_html = HttpPost(goto_url,goto_data); + + item = new HttpItem() + { + URL = goto_url, + Method = "POST", + Timeout = 5000, + ReadWriteTimeout = 5000, + IsToLower = false, + Cookie = "", + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 MicroMessenger/6.5.2.501 NetType/WIFI WindowsWechat QBCore/3.43.656.400 QQBrowser/9.0.2524.400", + Accept = "text/html, application/xhtml+xml, */*", + ContentType = "application/json", + Referer = json["Url"].ToString(), + Allowautoredirect = true, + AutoRedirectCookie = true, + Postdata = goto_data, + }; + var _data = http.GetHtml(item).Html; + } + + /// + /// 自动确认收款接口 + /// + /// + /// + /// + /// + public override int TenPayTransferConfirm(string Invalidtime, string Transferid, string FromUsername) + { + var data = new + { + CgiCmd = 85, + Invalidtime = Invalidtime,//"1487236689" + Transferid = Transferid,//"1000050201791702151058985957" + FromUsername = FromUsername //"wxid" + }; + WechatPack pack = new WechatPack(this); + var result = pack.Send(WechatCmd.获得银行卡, data); + result = pack.Analysis(WechatCmd.获得银行卡, result); + var text = Encoding.UTF8.GetString(result); + var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(text); + if (dic["retmsg"].ToString().ToUpper() == "OK") + { + return int.Parse(dic["fee"].ToString()); + } + return -1; + } + + + //xml解析到cdn图片数据 + private CDNImageMsgInfo GetCDNImage(string content) + { + try + { + content = content.Trim().Replace("\n", ""); + XmlDocument doc = new XmlDocument(); + doc.LoadXml(content); + XmlNodeList list = doc.SelectNodes("/msg/img"); + if (list != null && list.Count > 0) + { + XmlNode item = list[0]; + CDNImageMsgInfo image = new CDNImageMsgInfo(); + image.AESKey = item.Attributes["aeskey"].Value.ToString(); + + + XmlAttribute att = item.Attributes["hdlength"]; + + if (att != null && !string.IsNullOrWhiteSpace(att.Value)) + { + //有大图时使用大图 + image.TotalLen = long.Parse(item.Attributes["hdlength"].Value); + image.DataLen = long.Parse(item.Attributes["hdlength"].Value); + image.CDNBigImgUrl = item.Attributes["cdnbigimgurl"].Value.ToString(); + image.CDNBigImgSize = long.Parse(item.Attributes["hdlength"].Value); + + image.CDNMidImgUrl = item.Attributes["cdnmidimgurl"].Value.ToString(); + if (long.Parse(item.Attributes["length"].Value) == long.Parse(item.Attributes["cdnthumblength"].Value)) + { + image.CDNMidImgSize = long.Parse(item.Attributes["hdlength"].Value); + } + else + { + image.CDNMidImgSize = long.Parse(item.Attributes["length"].Value); + } + } + else + { + //使用中图 + image.TotalLen = long.Parse(item.Attributes["length"].Value); + image.DataLen = long.Parse(item.Attributes["length"].Value); + + image.CDNMidImgUrl = item.Attributes["cdnmidimgurl"].Value.ToString(); + image.CDNMidImgSize = long.Parse(item.Attributes["length"].Value); + } + + image.CDNThumbImgSize = long.Parse(item.Attributes["cdnthumblength"].Value); + //image.CDNThumbImgHeight = long.Parse(item.Attributes["cdnthumbheight"].Value); + //image.CDNThumbImgWidth = long.Parse(item.Attributes["cdnthumbwidth"].Value); + image.CDNThumbImgHeight = 0; + image.CDNThumbImgWidth = 0; + if (!string.IsNullOrWhiteSpace(image.AESKey)) + { + return image; + } + } + return null; + } + catch (Exception ee) + { + return null; + } + } + + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_QYHOOK.cs b/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_QYHOOK.cs new file mode 100644 index 0000000..a73cdb3 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/WXClientImpl_QYHOOK.cs @@ -0,0 +1,1247 @@ +using Chat.Framework.PCRobotSDK.WechatEvents; +using Chat.Framework.PCRobotSDK.WorkWechatEvents; +using Chat.Framework.Utils; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.HOOK; +using CsharpHttpHelper; +using Newtonsoft.Json; +using PCRobot.Pack; +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Implement +{ + /// + /// 企业PC机器人 + /// + public class WXClientImpl_QYHOOK : WeixinBase + { + /// + /// 上次心跳时间 + /// + public DateTime HeartBreakTime { get; internal set; } = DateTime.MinValue; + + /// + /// 企业机器人 + /// + /// 企业账号 + /// 企业昵称 + /// 企业账号 + public WXClientImpl_QYHOOK(string weixinhao, string usernick, long uin = -1) + { + WeixinType = WeixinType.QYHook微信; + WeixinHao = weixinhao; + User = new WeixinBaseUser(WeixinHao, usernick, uin); + Friends = new Dictionary(); + GroupMembers = new Dictionary(); + HeartBreakTime = DateTime.Now; + RequestContact(); + base.ChangeStatus(WxStatus.在线); + } + + //HeadPack_Hook headPack = null; + + public void Dispose() + { + if (this.User != null && this.User.Uin != 0 && this.User.Uin != -1) Grant.Framework.GrantClient.Get().LoginOut(this.User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0])); + } + + public override void ChangeStatus(WxStatus status, WXChangeStatus e = null, bool is_next = true) + { + if (status == WxStatus.已掉线 || status == WxStatus.已退出 || status == WxStatus.未登录 || status == WxStatus.登录失败) + { + if (this.User != null && this.User.Uin != 0 && this.User.Uin != -1) Grant.Framework.GrantClient.Get().LoginOut(this.User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0])); + } + + if (status == WxStatus.在线) + { + if (!Grant.Framework.GrantClient.Get().IsExistCustomers(User.Uin.ToString(), int.Parse(WXClientTool.auth_info[0]))) + { + try + { + if (User.Uin.ToString() != "0" && User.Uin.ToString() != "-1") + Grant.Framework.GrantClient.Get().Login(User.Uin.ToString(), User.Nick, int.Parse(WXClientTool.auth_info[0]), WXClientTool.auth_info[1]); + } + catch (Exception ex) + { + var wx = ChatClient.WXClient.FirstOrDefault(f => f.Key == WeixinHao).Value; + if (wx == null) + ChatClient.UpdateWXClient(this); + + ChatClient.Events.OnEvent(new WXWriteLog(this) { Message = $"【{User.Uin}({User.Nick})】授权异常:" + ex.Message }); + status = WxStatus.登录失败; + //LoginOut($"【{User.Username}({User.Nick})】{ex.Message}"); + Dispose(); + ChatClient.LoginOutWeixin(WeixinHao, $"【{User.Uin}({User.Nick})】{ex.Message}"); + } + } + } + else + { + LogHelper.GetSingleObj().Debug("", $"QY微信状态修改:{this.WeixinHao} - {status}"); + ChatClient.LoginOutWeixin(WeixinHao); + } + base.ChangeStatus(status, e); + } + + /// + /// 退出消息 + /// + /// + public override void LoginOut(string message) + { + //发送指令 强制退出易转发那边的微信 + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.closeWechat, message); + try + { + LogHelper.GetSingleObj().Debug("", $"LoginOutQY带提示:{this.WeixinHao}"); + } + catch (Exception) + { } + } + + /// + /// 退出登录 + /// + public override void LoginOut() + { + //发送指令 强制退出易转发那边的微信 + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.closeWechat); + try + { + LogHelper.GetSingleObj().Debug("", $"LoginOutQY不带提示:{this.WeixinHao}"); + } + catch (Exception) + { } + } + + public override void ShowLogin() + { + throw new Exception("请在易转发,客户端执行登陆!"); + } + + /// + /// 获得好友或群组信息 + /// + public override Friend GetContact(string wxid, bool refresh = false) + { + lock (this.Friends) + { + try + { + if (refresh || !Friends.ContainsKey(wxid)) + { + var msg_id = GetWxidInfo(wxid); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + //{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","corp_id":null,"desc":"","external_job":null,"nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":"18","manager_wxid":null,"is_manager":0,"member_list":null} + try + { + var contact = rst as WorkWechatContact; + if (!string.IsNullOrWhiteSpace(contact.Message)) + { + var data = @"{""data"":" + contact.Message + "}"; + var _result = HttpExtend.JsonToDictionary(data); + if (_result != null) + { + var result = _result["data"] as Dictionary; + var avatar = result["avatar"]?.ToString(); + var username = result["username"]?.ToString(); + var user_id = result["user_id"]?.ToString(); + var sex = int.Parse(result["sex"]?.ToString()); + var remark = result["remark"]?.ToString(); + var manager_wxid = result["manager_wxid"]?.ToString(); + + Friends[user_id] = new Friend() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, City = string.Empty, Sex = sex, NickName = username, Remark = remark, UserName = user_id, Alias = user_id, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = manager_wxid, ChatroomVersion = string.Empty }; + } + } + } + catch (Exception ex) + { + this.WriteLog($"获取 Contact异常 :" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + if (Friends.ContainsKey(wxid)) return Friends[wxid]; + else + { + var f = ChatClient.GetDBWechatFriend(wxid); + if (f != null) + Friends[wxid] = f; + return f == null ? new Friend() { UserName = wxid, Alias = wxid } : f; + } + } + catch (Exception ex) + { + this.WriteLog($"{ex.Message}"); + } + return new Friend() { UserName = wxid, Alias = wxid }; + } + } + + public Dictionary GroupMembers { get; private set; } + + /// + /// 获取群成员信息 + /// + /// + /// + /// + public override GroupMember GetMember(string groupid, string wxid) + { + try + { + if (!GroupMembers.ContainsKey(groupid) || GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid) == null) + { + var msg_id = GetGroupWxidInfo(groupid, wxid); + //GetGroupInfo(groupid); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + //{"conversation_id":"R:10696053211008104","total":3,"friends":[{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","corp_id":null,"desc":"","external_job":null,"nickname":"18","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":null,"manager_wxid":"","is_manager":0,"member_list":""}]} + try + { + var contact = rst as WorkWechatContact; + if (!string.IsNullOrWhiteSpace(contact.Message)) + { + var data = @"{""data"":" + contact.Message + "}"; + var _result = HttpExtend.JsonToDictionary(data); + if (_result != null) + { + var result = _result["data"] as Dictionary; + + var conversation_id = result["conversation_id"]?.ToString(); + var total = result["total"]?.ToString(); + var friend = (result["friends"] as ArrayList)[0] as Dictionary; + if (friend != null) + { + var avatar = friend["avatar"]?.ToString(); + var nickname = friend["nickname"]?.ToString(); + var remark = friend["remark"]?.ToString(); + var sex = int.Parse(friend["sex"]?.ToString()); + var user_id = friend["user_id"]?.ToString(); + var manager_wxid = friend["manager_wxid"]?.ToString(); + if (!GroupMembers.ContainsKey(conversation_id)) + { + GroupMembers.Add(conversation_id, new GroupMember[] { }); + } + var gm = GroupMembers[conversation_id].ToList(); + if (gm.FirstOrDefault(f => f.Username == wxid) == null) + { + gm.Add(new GroupMember() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, Groupid = conversation_id, Username = wxid, NickName = nickname }); + GroupMembers[conversation_id] = gm.ToArray(); + } + //Friends[user_id] = new Friend() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, City = string.Empty, Sex = sex, NickName = nickname, Remark = remark, UserName = user_id, Alias = user_id, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = manager_wxid, ChatroomVersion = string.Empty }; + } + } + } + } + catch (Exception ex) + { + this.WriteLog($"获取 Member 异常 :" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + + //if (!GroupMembers.ContainsKey(groupid)) return null; + if (!GroupMembers.ContainsKey(groupid)) + GroupMembers[groupid] = new GroupMember[] { new GroupMember() { Groupid = groupid, Username = wxid } }; + else + { + var member = GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + if (member == null) + { + var gm = GroupMembers[groupid].ToList(); + gm.Add(new GroupMember() { Groupid = groupid, Username = wxid }); + GroupMembers[groupid] = gm.ToArray(); + } + } + + return GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + } + catch (Exception ex) + { + this.WriteLog($"获取群信息:{ex.Message}"); + } + return new GroupMember() { Groupid = groupid, Username = wxid }; + } + + /// + /// 获取群成员信息 + /// + /// + /// + /// + public override GroupMember GetMember(string groupid, string wxid, bool flush = false) + { + try + { + if (flush || !GroupMembers.ContainsKey(groupid) || GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid) == null) + { + var msg_id = GetGroupWxidInfo(groupid, wxid, flush); + //GetGroupInfo(groupid); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + //{"conversation_id":"R:10696053211008104","total":3,"friends":[{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","corp_id":null,"desc":"","external_job":null,"nickname":"18","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":null,"manager_wxid":"","is_manager":0,"member_list":""}]} + try + { + var contact = rst as WorkWechatContact; + if (string.IsNullOrWhiteSpace(contact.Message)) return null; + var data = @"{""data"":" + contact.Message + "}"; + var _result = CsharpHttpHelper.HttpExtend.JsonToDictionary(data); + if (_result == null) return null; + + var result = _result["data"] as Dictionary; + + var conversation_id = result["conversation_id"]?.ToString(); + var total = result["total"]?.ToString(); + var friend = (result["friends"] as ArrayList)[0] as Dictionary; + if (friend != null) + { + var avatar = friend["avatar"]?.ToString(); + var nickname = friend["nickname"]?.ToString(); + var remark = friend["remark"]?.ToString(); + var sex = int.Parse(friend["sex"]?.ToString()); + var user_id = friend["user_id"]?.ToString(); + var manager_wxid = friend["manager_wxid"]?.ToString(); + if (!GroupMembers.ContainsKey(conversation_id)) + { + GroupMembers.Add(conversation_id, new GroupMember[] { }); + } + var gm = GroupMembers[conversation_id].ToList(); + var info = gm.FirstOrDefault(f => f.Username == wxid); + if (info != null) + { + gm.Remove(info); + info = null; + } + if (info == null) + { + gm.Add(new GroupMember() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, Groupid = conversation_id, Username = wxid, NickName = nickname }); + GroupMembers[conversation_id] = gm.ToArray(); + } + //Friends[user_id] = new Friend() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, City = string.Empty, Sex = sex, NickName = nickname, Remark = remark, UserName = user_id, Alias = user_id, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = manager_wxid, ChatroomVersion = string.Empty }; + } + } + catch (Exception ex) + { + this.WriteLog($"获取 Member 异常 :" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + + //if (!GroupMembers.ContainsKey(groupid)) return null; + if (!GroupMembers.ContainsKey(groupid)) GroupMembers[groupid] = new GroupMember[] { new GroupMember() { Groupid = groupid, Username = wxid } }; + + var member = GroupMembers[groupid].FirstOrDefault(f => f.Username == wxid); + return member; + } + catch (Exception ex) + { + this.WriteLog($"获取群信息:{ex.Message}"); + } + return null; + } + + /// + /// 创建群 + /// + /// + public override string CreateChatRoom(string[] wxids) + { + try + { + if (wxids == null || wxids.Length == 0) return string.Empty; + WechatPack pack = new WechatPack(this); + var msg_id = pack.SendServer(PCRobotCMD.createRoom, string.Join(",", wxids)); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var createRoom = rst as CreateRoom; + if (createRoom != null) + return createRoom.GroupId; + } + catch (Exception ex) + { + this.WriteLog($"创建新群异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + catch (Exception ex) + { } + return string.Empty; + } + + #region xx + /// + /// 请求获取群信息 + /// + /// + //private void GetGroupInfo(string groupid) + //{ + // try + // { + // lock (GroupMembers) + // { + // try + // { + // WechatPack send = new WechatPack(this); + // send.SendServer(PCRobotCMD.getGroupMember, groupid); + // } + // catch (Exception ex) + // { + // this.WriteLog(ex.Message); + // } + // } + // } + // catch (Exception ex) + // { + // this.WriteLog($"请求群信息:{ex.Message}"); + // } + //} + + //private readonly object FriendsLock = new object(); + //Action FriendsAction; + // private void GetFriends(string friendsJson) + // { + // try + // { + // this.WriteLog($"GetFriends = {friendsJson}"); + // lock (FriendsLock) + // { + // #region + // var dic = HttpExtend.JsonToDictionary(friendsJson); + // if (dic != null && dic.ContainsKey("data")) + // { + // var data = dic["data"] as System.Collections.ArrayList; + // foreach (Dictionary item in data) + // { + // //var account = item["account"]?.ToString(); + // //var avatar = item["avatar"]?.ToString(); + // //var city = item["city"]?.ToString(); + // //var country = item["country"]?.ToString(); + // //var nickname = item["nickname"]?.ToString(); + // //var province = item["province"]?.ToString(); + // //var remark = item["remark"]?.ToString(); + // //var sex = int.Parse(item["sex"]?.ToString()); + // //var wxid = item["wxid"]?.ToString(); + + + // var avatar = item["avatar"]?.ToString(); + // var conversation_id = item["conversation_id"]?.ToString(); + // var corp_id = item["corp_id"]?.ToString(); + // var desc = item["desc"]?.ToString(); + // var external_job = item["external_job"]?.ToString(); + // var nickname = item["nickname"]?.ToString(); + // var position = item["position"]?.ToString(); + // var realname = item["realname"]?.ToString(); + // var remark = item["remark"]?.ToString(); + // var sex = int.Parse(item["sex"]?.ToString()); + // var username = item["username"]?.ToString(); + // var user_id = item["user_id"]?.ToString(); + + + // var manager_wxid = item["manager_wxid"]?.ToString(); + // var is_manager = int.Parse(item["is_manager"].ToString()); + + // Friends[user_id] = new Friend() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, City = string.Empty, Sex = sex, NickName = nickname, Remark = remark, UserName = user_id, Alias = user_id, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = manager_wxid, ChatroomVersion = string.Empty }; + + // #region 获取群详细信息 + // if (user_id.Contains("R:")) + // { + // GetGroupInfo(user_id); + // Thread.Sleep(5); + // } + // #endregion + // } + // } + // #endregion + // } + // this.WriteLog($"GetFriends@ = {HttpHelper.ObjectToJson(Friends)}"); + // } + // catch (Exception ex) + // { + // this.WriteLog($@"获取成员失败:{ex.Message} - {ex.StackTrace} + + //friendsJson = {friendsJson}"); + // } + //} + + // private readonly object GroupMemberLock = new object(); + // Action GroupMembersAction; + + // private void GetGroupMembers(string friendsJson) + // { + // try + // { + // this.WriteLog($"GetGroupMembers = {friendsJson}"); + // lock (GroupMemberLock) + // { + // #region + // var dic = HttpExtend.JsonToDictionary(friendsJson); + // if (dic != null && dic.ContainsKey("data")) + // { + // var data = dic["data"] as Dictionary; + // //var total_member = int.Parse(data["total_member"].ToString()); + // var gId = data["conversation_id"].ToString(); + // var list = data["member_list"] as ArrayList; + + // List groups = null; + // if (GroupMembers.ContainsKey(gId)) + // groups = GroupMembers[gId].ToList(); + // else + // groups = new List(); + + // foreach (Dictionary item in list) + // { + // //var account = item["account"]?.ToString(); + // var avatar = item["avatar"]?.ToString(); + // //var city = item["city"]?.ToString(); + // //var country = item["country"]?.ToString(); + // var nickname = item["nickname"]?.ToString(); + // //var province = item["province"]?.ToString(); + // var remark = item["remark"]?.ToString(); + // var sex = int.Parse(item["sex"]?.ToString()); + // var wxid = item["user_id"]?.ToString(); + + // if (groups.FirstOrDefault(f => f.Username == wxid) == null) + // groups.Add(new GroupMember() { SmallHeadImgUrl = avatar, BigHeadImgUrl = avatar, Groupid = gId, Username = wxid, NickName = nickname }); + // } + // GroupMembers[gId] = groups.ToArray(); + // } + // #endregion + // } + // this.WriteLog($"GetGroupMembers@ = {HttpHelper.ObjectToJson(GroupMembers)}"); + // } + // catch (Exception ex) + // { + // this.WriteLog($@"获取群成员失败:{ex.Message} - {ex.StackTrace} + + //friendsJson = {friendsJson}"); + // } + // } + + #endregion + + /// + /// 分析hook服务器过来的事件 + /// + /// + public override void Receive(object obj) + { + var cmd = string.Empty; + try + { + //LogHelper.GetSingleObj().Debug("", $"获取到解析后的数据_QY = {obj.GetType().Name},Uin:{this.User.Uin},{this.User.Nick}({this.WeixinHao})"); + var events = ChatClient.Events; + if (obj.GetType() == typeof(WorkWechatReceiveMsgEvents))//私聊和群聊消息 + { + var evt = obj as WorkWechatReceiveMsgEvents; + cmd = evt.Data.Cmd.ToString(); + //if (Friends.ContainsKey(evt.Data.FromUsername)) + //{ + // if (Friends[evt.Data.FromUsername].MsgType == 24 || Friends[evt.Data.FromUsername].MsgType == 8 || Friends[evt.Data.FromUsername].MsgType == 29)//公众号 + // return; + //} + + if (string.IsNullOrWhiteSpace(evt.Data.FromGroupid)) + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("私消息")) + { + //bool is_phpone = false; + + Friend friend = null; + friend = this.GetContact(evt.Data.FromUsername); + if (!ChatClient.WXSdkConfig.MsgConvertToFriend && evt.Data.IsSend) + { + return; + //if (evt.Data.IsSend == this.WeixinHao) + //{ + // is_phpone = true; + //} + //is_phpone = evt.Data.IsSend; + } + if (friend == null) + { + this.WriteLog(string.Format("获取用户{0}失败。", evt.Data.FromUsername)); + return; + } + friend.NickName = Util.RemoveEmoji(friend.NickName); + var eventobj = new WXReiceveFriendMsg(this, friend, evt.Data.FromMessage); + eventobj.IsRobot = evt.Data.IsSend; + events.OnEvent(eventobj); + } + } + else + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("群消息")) + { + var group = this.GetContact(evt.Data.FromGroupid); + if (group == null) + { + this.WriteLog(string.Format("获取群{0}失败。", evt.Data.FromGroupid)); + return; + } + + GroupMember member = this.GetMember(evt.Data.FromGroupid, evt.Data.FromUsername); + if (member == null) + { + this.WriteLog(string.Format("获取群{0}成员{1}信息失败。", evt.Data.FromGroupid, evt.Data.FromUsername)); + return; + } + events.OnEvent(new WXReceiveGroupMsg(this, member, group, evt.Data.FromMessage)); + return; + } + } + } + else if (obj.GetType() == typeof(WorkWechatApplyFriendEvents))//申请添加我为好友,需要审核 + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新申请")) + { + var evt = obj as WorkWechatApplyFriendEvents; + cmd = evt.Data.Cmd.ToString(); + events.OnEvent(new WXApplyFriend(this, evt.Data.NewFriendWxid, evt.Data.NewFriendNick, evt.Data.Message, evt.Data.OldFriendWxid, evt.Data.OldFriendNick, evt.Data.Token)); + + #region 这里给通过做准备,把用户信息保存起来 + if (!Friends.ContainsKey(evt.Data.NewFriendWxid)) + { + var reg = Regex.Match(evt.Data.Token, @"smallheadimgurl==""(?<头像>[^""]*?)"""); + var headIMG = string.Empty; + if (reg.Success) headIMG = reg.Groups["头像"].Value; + Friends[evt.Data.NewFriendWxid] = new Friend() { SmallHeadImgUrl = headIMG, BigHeadImgUrl = headIMG, City = string.Empty, Sex = 0, MsgType = 0, NickName = evt.Data.NewFriendNick, Remark = evt.Data.NewFriendNick, UserName = evt.Data.NewFriendWxid, Alias = evt.Data.NewFriendWxid, ExtInfo = string.Empty, Province = string.Empty, ChatRoomOwner = string.Empty, ChatroomVersion = string.Empty }; + } + #endregion + } + } + else if (obj.GetType() == typeof(WorkWechatNewFriendEvents)) + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新好友")) + { + var evt = obj as WorkWechatNewFriendEvents; + cmd = evt.Data.Cmd.ToString(); + + Friend friend = null; + friend = this.GetContact(evt.Data.FromUserName);//这里很大概率获取不到用户的昵称,新用户 + if (friend == null) + { + this.WriteLog(string.Format("获取用户{0}失败。", evt.Data.FromUserName)); + return; + } + friend.NickName = Util.RemoveEmoji(friend.NickName); + events.OnEvent(new WXNewFriend(this, friend)); + } + } + else if (obj.GetType() == typeof(WorkWechatReicevePayEvents))//收到支付 + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("转账")) + { + var evt = obj as WorkWechatReicevePayEvents; + cmd = evt.Data.Cmd.ToString(); + + var friend = GetContact(evt.Data.FromUsername); + if (friend != null) + { + friend.NickName = Util.RemoveEmoji(friend.NickName); + var e = new WXReicevePay(this, friend, evt.Data.Invalidtime, evt.Data.Transferid, evt.Data.Money); + events.OnEvent(e); + } + } + } + else if (obj.GetType() == typeof(WorkWechatNewMemerEvents))//新人入群 + { + if (Util.GetNoAnalysisConfig().Count == 0 || Util.GetNoAnalysisConfig().Contains("新群友")) + { + var evt = obj as WorkWechatNewMemerEvents; + cmd = evt.Data.Cmd.ToString(); + + var group = GetContact(evt.Data.GroupId); + if (group == null) return; + events.OnEvent(new WXNewMemer(this) { Group = group, GroupId = evt.Data.GroupId, MemberNicks = evt.Data.MemberNick, SourceNick = Util.RemoveEmoji(evt.Data.SourceNick), SourceName = evt.Data.SourceName }); + } + } + else if (obj.GetType() == typeof(WorkWechatContactListEvents))//获得通讯录列表 + { + //var evt = obj as WorkWechatContactListEvents; + //cmd = evt.Data.Cmd.ToString(); + + //FriendsAction = GetFriends; + //FriendsAction(evt.Data.Message); + } + else if (obj.GetType() == typeof(WorkWechatGroupMemberEvents))//获得群成员 + { + //var evt = obj as WorkWechatGroupMemberEvents; + //cmd = evt.Data.Cmd.ToString(); + + //GroupMembersAction = GetGroupMembers; + //GroupMembersAction(evt.Data.Message); + } + else if (obj.GetType() == typeof(WechatStatusEvents))//微信状态改变 + { + var evt = obj as WechatStatusEvents; + cmd = evt.Cmd.ToString(); + ChangeStatus(evt.Status == PCRobot.Pack.Status.在线 ? WxStatus.在线 : WxStatus.已退出); + this.HeartBreakTime = DateTime.Now; + } + } + catch (Exception ex) + { + this.WriteLog($"PC服务器消息处理异常:【{cmd}】- {ex.Message},{ex.StackTrace}"); + } + } + + + /// + /// 好友列表 + /// + public Dictionary Friends { get; private set; } + + public override List FindFriends() + { + try + { + var msg_id = RequestContact(); + if (!string.IsNullOrEmpty(msg_id)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msg_id).Result; + if (rst != null) + { + try + { + var commonResult = rst as CommonResult; + if (commonResult != null) + { + var data = commonResult.Data; + return JsonConvert.DeserializeObject>(data); + } + } + catch (Exception ex) + { + this.WriteLog($"获取企业外部通讯录用户异常:" + ex.Message + " - " + ex.StackTrace); + } + } + } + } + catch (Exception ex) + { } + return null; + } + + /// + /// 请求获取联系人 + /// + /// + public string RequestContact() + { + try + { + WechatPack pack = new WechatPack(this); + return pack.SendServer(PCRobotCMD.getContact); + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 获取指定的用户 + /// + public string GetWxidInfo(string wxid) + { + try + { + WechatPack pack = new WechatPack(this); + return pack.SendServer(PCRobotCMD.getWxidInfo, wxid); + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 获取指定的用户或群的信息 + /// + public string GetGroupWxidInfo(string groupId, string wxid) + { + try + { + WechatPack pack = new WechatPack(this); + return pack.SendServer(PCRobotCMD.getGroupWxidInfo, wxid, WechatMsgType.图片, groupId); + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 获取指定的用户或群的信息 + /// + public string GetGroupWxidInfo(string groupId, string wxid, bool flush) + { + try + { + WechatPack pack = new WechatPack(this); + //类型:图片表示不刷新,文件表示刷新 + return pack.SendServer(PCRobotCMD.getGroupWxidInfo, wxid, flush ? WechatMsgType.文件 : WechatMsgType.图片, groupId); + } + catch (Exception ex) + { } + return string.Empty; + } + + /// + /// 领取转账 + /// + /// + /// + /// + /// + public override int TenPayTransferConfirm(string Invalidtime, string Transferid, string FromUsername) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.getPay, HttpHelper.ObjectToJson(new Dictionary() { { "Invalidtime", Invalidtime }, { "Transferid", Transferid } }), WechatMsgType.文本, FromUsername); + return 0; + } + + /// + /// 发送卡片 + /// + /// + /// + public override void SendCard(string username, string friendwxid) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.sendCard, friendwxid, WechatMsgType.文本, username); + } + + /// + /// 邀请入群发送名片 和 AddChatRoomMember 功能一样 + /// + /// + /// + /// + public override string InviteIntoGroup(string username, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.inviteIntoGroup, groupId, WechatMsgType.文本, username); + return string.Empty; + } + + /// + /// 邀请入群发送名片 和 AddChatRoomMember 功能一样 + /// + /// + /// + public override void AddChatRoomMember_40Down(string groupid, string members) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.inviteIntoGroup, groupid, WechatMsgType.文本, members); + } + + /// + /// 邀请入群发送名片 和 AddChatRoomMember_40Down 功能一样 + /// + /// + /// + public override void AddChatRoomMember(string groupid, string members) + { + AddChatRoomMember_40Down(groupid, members); + } + + /// + /// 删除群用户 + /// + /// + /// + /// + public override string DeleteGroupMember(string username, string groupId) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.deleteGroupMember, username, WechatMsgType.文本, groupId); + return string.Empty; + } + + + /// + /// 发送图片 + /// + /// + /// + public override void SendImage(string username, string address) + { + try + { + byte[] ImangByte = null; + + string extension = Path.GetExtension(address); + if (address.StartsWith("http", StringComparison.InvariantCultureIgnoreCase)) + { + ImangByte = new System.Net.WebClient().DownloadData(address); + byte[] imageHash = new MD5CryptoServiceProvider().ComputeHash(ImangByte); + //图片哈希值 + string StrimageHash = Util.HexToStr(imageHash); + string FileName = StrimageHash + extension; + string FilePath = Path.Combine(Util.MapPath("cache\\image", true), FileName); + if (!File.Exists(FilePath)) + { + File.WriteAllBytes(FilePath, ImangByte); + } + if (File.Exists(FilePath)) + address = FilePath; + else + throw new Exception("图片异常"); + } + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.sendImg, address, WechatMsgType.图片, username); + } + catch (Exception ex) + { + this.WriteLog($"发送图片失败:{ex.Message} - {ex.StackTrace}"); + } + } + + public override void SendProgramMessage(string username, string ghid, string wxid, string name, string title, string enterpoint, string headimg, string image_key1, string image_key2, string image_key3, string image_size) + { + try + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.sendProgramMessage, JsonConvert.SerializeObject(new { data = new { conversation_id = username, ghid = ghid, wxid = wxid, name = name, title = title, enterpoint = enterpoint, headimg = headimg, image_key1 = image_key1, image_key2 = image_key2, image_key3 = image_key3, image_size = image_size } }), WechatMsgType.文本, username); + } + catch (Exception ex) + { + this.WriteLog("SendProgramMessage ERROR:" + ex.Message); + } + } + + /// + /// 发送消息 + /// + /// + /// + /// + /// + public override Task SendMessage(string _username, string _message, string _atUsername = "") + { + string username = _username; + string content = _message; + string atUsername = _atUsername; + + return Task.Run(() => + { + if (string.IsNullOrEmpty(content)) return true; + content = content.Replace("\r\n", "\n").Trim().Replace("[时间]", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Replace("[机器人微信]", this.User.Username); + var msgs = content.Split(new string[] { "[分段]" }, StringSplitOptions.RemoveEmptyEntries); + try + { + foreach (var msg in msgs) + { + var m = msg.Replace("\r\n", "\n").Trim(); + if (string.IsNullOrEmpty(m)) continue; + var message = m.RandomMess(); + + message = message.Contains("[随机表情]") ? message.Replace("[随机表情]", WXClientImpl_IPAD.FindRandomExpression()) : message; + //if (message.StartsWith("[延迟=")) + //{ + // var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + // if (reg.Success) + // { + // message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + // Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + // } + //} + message = DelayMess(message); + ChatClient.Events.OnEvent(new WXSendMessage(this, message, username)); + WechatPack pack = new WechatPack(this); + //发送XML消息 + if (message.ToLower().Trim().StartsWith("")) + { + //if (!message.ToLower().Contains("")) + if (true) + { + message = $@"{WeixinHao}0{msg/*.Replace("&", "&")*/}1Window wechat"; + + pack.SendServer(PCRobotCMD.sendTxt, message, WechatMsgType.文本, username); + } + else + { + /* + {"data":{"content_type":78,"conversation_id":"S:1688852952419302_1688853086316483","enterpoint":"pages/index.html","ghid":"gh_0ed5d82fd775@app","headimg":"http://mmbiz.qpic.cn/mmbiz_png/R5xk2bJZhgSL24GXicQ24b8h7zwWKY9Eia4Pl4RJibFml6k2icWj8H7rbFmiaiakt7wPwx7vUgrKic62PBZpdTTwdsJ2g/640?wx_fmt=png&wxfrom=200","image_key1":"3069020102046230600201000204b84e8be602030f4243020412cf9b24020460df2504042439643136386638302d303661652d343136322d386438342d6265643138623961356665620201000203024ef0041083bf4e722024dbcfc797cfaa1e97ac090201010201000400","image_key2":"13e72cff06014d4e9d392fd059228092","image_key3":"83bf4e722024dbcfc797cfaa1e97ac09","image_size":151279,"is_pc":0,"local_id":"18","name":"通信行程卡","receiver":"1688853086316483","send_time":"1625236741","sender":"1688852952419302","sender_name":"滴滴滴","server_id":"1000455","title":"通信行程卡","wxid":"wx8f446acf8c4a85f5"},"type":11066} + */ + + SendProgramMessage(username, "gh_0ed5d82fd775@app", "wx8f446acf8c4a85f5", "兑换助兑换助兑换助", "兑换助兑换助", "pages/11111111111111", "http://mmbiz.qpic.cn/mmbiz_png/R5xk2bJZhgSL24GXicQ24b8h7zwWKY9Eia4Pl4RJibFml6k2icWj8H7rbFmiaiakt7wPwx7vUgrKic62PBZpdTTwdsJ2g/640?wx_fmt=png&wxfrom=200", "3069020102046230600201000204b84e8be602030f4243020412cf9b24020460df2504042439643136386638302d303661652d343136322d386438342d6265643138623961356665620201000203024ef0041083bf4e722024dbcfc797cfaa1e97ac090201010201000400", "13e72cff06014d4e9d392fd059228092", "83bf4e722024dbcfc797cfaa1e97ac09", "151279"); + } + continue; + } + //发送图片消息 + var matchs = Regex.Matches(message, @"\[图片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match match in matchs) + { + var imageBase = string.Empty; + var image = match.Groups[1].Value; + if (!image.ToLower().Trim().StartsWith("http")) + { + if (File.Exists(image)) + { + double size = new FileInfo(image).Length; + if (size > 1024 * 512) + { + try + { + var img = Util.ReadImageFile(image); + var bitmap = Util.PercentImage(img, img.Width); + var _image = image + Path.GetExtension(image);//压缩图片的地址 + if (Util.YaSuo(bitmap, _image)) + { + imageBase = Util.FileToBase64(_image); + } + } + catch (Exception ex) + { + LogHelper.GetSingleObj().Error("", $"QY图片压缩异常:{ex.Message} - {ex.StackTrace}"); + imageBase = Util.FileToBase64(image); + } + } + else + imageBase = Util.FileToBase64(image); + } + } + else + imageBase = image; + + SendImage(username, imageBase); + } + message = Regex.Replace(message, @"\[图片\=([^\]]+)\]", ""); + message = DelayMess(message); + //发送语音消息 + //matchs = Regex.Matches(message, @"\[语音\=([^\]]+)\]", RegexOptions.IgnoreCase); + //foreach (Match item in matchs) + //{ + //SendVoice(username, item.Groups[1].Value);//PC不能发送语音 + //} + message = Regex.Replace(message, @"\[语音\=([^\]]+)\]", ""); + message = DelayMess(message); + matchs = Regex.Matches(message, @"\[视频\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + //var video = Util.StrToHex(item.Groups[1].Value); + //if (video != null) + //{ + // var video_json = Encoding.UTF8.GetString(video); + // var video_data = CsharpHttpHelper.HttpExtend.JsonToDictionary(video_json); + // if (video_data != null) + // { + // SendCDNInfo(username, video_data["cdnurl"].ToString(), video_data["aeskey"].ToString(), CDNType.发送视频); + // } + //} + var filePath = item.Groups[1].Value; + if (!Regex.IsMatch(filePath, @"^[c-zC-Z]:\\")) continue; + //if (File.Exists(filePath)) + //{ + //var base64 = Util.FileToBase64(filePath); + pack.SendServer(PCRobotCMD.sendVideo, filePath, WechatMsgType.视频, username); + //} + } + message = Regex.Replace(message, @"\[视频\=([^\]]+)\]", ""); + message = DelayMess(message); + matchs = Regex.Matches(message, @"\[卡片\=([^\]]+)\]", RegexOptions.IgnoreCase); + foreach (Match item in matchs) + { + SendCard(username, item.Groups[1].Value == "自己" ? User.Username : item.Groups[1].Value); + } + message = Regex.Replace(message, @"\[卡片\=([^\]]+)\]", ""); + message = DelayMess(message); + if (string.IsNullOrWhiteSpace(message)) continue; + if (message.StartsWith("\r\n")) message = message.Substring("\r\n".Length); + if (message.StartsWith("\n")) message = message.Substring("\n".Length); + //pack.SendServer(PCRobotCMD.sendTxt, message, WechatMsgType.文本, username); + pack.SetNextData(new ServerWechatMsg() { Cmd = PCRobotCMD.sendTxt, ToMessage = message, ToMessageType = WechatMsgType.文件, ToUsername = username }); + RunSendMessageQueue(pack); + } + return true; + } + catch (Exception ex) + { + this.WriteLog("SendMessage ERROR:" + ex.Message); + return false; + } + }); + } + + #region 消息发送速度处理 + /// + /// 需要发送的消息队列 + /// + private ConcurrentQueue SendMessageQueue { get; set; } = new ConcurrentQueue(); + private object lock_sendmessage = new object(); + private bool lock_sendmessage_ing = false; + private int fragmentCount = 0; + private DateTime fragmentTime = DateTime.MinValue; + private Random random = new Random(); + + private void RunSendMessageQueue(WechatPack sendPack) + { + SendMessageQueue.Enqueue(sendPack); + if (lock_sendmessage_ing) return; + + lock (lock_sendmessage) + { + if (lock_sendmessage_ing) return; + lock_sendmessage_ing = true; + ThreadPool.QueueUserWorkItem(x => + { + try + { + WechatPack pack = null; + while (SendMessageQueue.TryDequeue(out pack)) + { + if (this.Status == WxStatus.在线) + { + pack.SendNextData(); + + #region 消息防止频繁,休眠操作 + if (ChatClient.MessFrequentSleepTime != 0) + { + fragmentCount++; + var totalSeconds = (DateTime.Now - fragmentTime).TotalSeconds;//上次休眠的时间差 + bool rest = totalSeconds > 10; + if (fragmentCount >= 10 && totalSeconds <= 10) + { + rest = true; + Thread.Sleep(ChatClient.MessFrequentSleepTime * 1000); + } + + if (rest) + { + fragmentCount = 1; + fragmentTime = DateTime.Now; + } + else + Thread.Sleep(60); + } + else + Thread.Sleep(60); + #endregion + } + } + } + catch (Exception) + { + } + finally + { + lock_sendmessage_ing = false; + } + }); + } + } + + #endregion + + + /// + /// 同意添加我为好友 + /// + /// + /// + public override string AgreeAddMe(string token) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.agreeFriend, token, WechatMsgType.文本, string.Empty); + return string.Empty; + } + + /// + /// 删除好友 + /// + /// + /// + public override string DeleteFriend(string username) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.deleteFriend, username, WechatMsgType.文本, string.Empty); + return string.Empty; + } + + /// + /// 修改用户信息 + /// + /// + /// + /// + public override void EditContacts(string username, EditContactsType type, string remark = "") + { + Task.Run(() => + { + for (int i = 0; i < 3; i++) + { + if (type == EditContactsType.备注) + { + WechatPack pack = new WechatPack(this); + pack.SendServer(PCRobotCMD.editContacts, remark, WechatMsgType.文本, username); + Thread.Sleep(500); + } + //else if (type == EditContactsType.置顶 || type == EditContactsType.取消置顶) + //{ + // WechatPack pack = new WechatPack(this); + // pack.SendServer(PCRobotCMD.stateOpt, type == EditContactsType.置顶 ? "1" : "0", WechatMsgType.文本, username); + //} + //else + // throw new Exception("本协议不支持该操作"); + } + }); + } + + /// + /// 消息延迟 + /// + /// + public string DelayMess(string message) + { + try + { + message = message.Trim(); + if (message.StartsWith("[延迟=")) + { + var reg = Regex.Match(message, @"\[延迟=(\d+)\]"); + if (reg.Success) + { + message = Regex.Replace(message, @"\[延迟=(\d+)\]", "").Trim(); + // this.WriteLog($"需要延迟{reg.Groups[1].Value}秒,再发送:{message}"); + Thread.Sleep(int.Parse(reg.Groups[1].Value) * 1000); + } + } + } + catch (Exception ex) + { } + return message; + } + + + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/WXClientTool.cs b/类库/Chat.Framework/WXSdk/Implement/WXClientTool.cs new file mode 100644 index 0000000..523a671 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/WXClientTool.cs @@ -0,0 +1,547 @@ +using Chat.Framework.WXSdk.IPAD; +using Google.Protobuf; +using Grpc.Core; +using MSScriptControl; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using WechatProto; + +namespace Chat.Framework.WXSdk.Implement +{ + /// + /// 微信管理工具 + /// + internal class WXClientTool + { + + public static int ReadInt(byte[] buf, int index) + { + if (buf.Length >= 16) + { + var seqBuf = new byte[4]; + Buffer.BlockCopy(buf, index, seqBuf, 0, 4); + return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(seqBuf, 0)); + + } + return 1; + } + internal static string[] auth_info { get; set; } + internal static byte[] random_encry_key { get { return GrpcConfig.Get(GrpcType.Laoyao).RandomEncryKey; } } + internal static string machine_code { get { return GrpcConfig.Get(GrpcType.Laoyao).MachineCode; } } + static WXClientTool() + { + + // switch (grpc_type) + // { + // case 1: + // { + //// version = "6.6.6.7"; + //// app_id = "v1_23229f55b208d33b_CodeVip"; + //// app_key = "v2_d72d0b8d148afb50e8a0beed37efd1b5"; + //// machine_code = "v3_951b8b394d904962d981f02e5d4cee31"; + //// channel_credentials = new SslCredentials(@"-----BEGIN CERTIFICATE----- + ////MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV + ////BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw + ////CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW + ////Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC + ////Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV + ////BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw + ////ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG + ////eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB + ////F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD + ////mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY + ////ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 + ////lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd + ////AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME + ////GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG + ////SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q + ////DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc + ////sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl + ////bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG + ////DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf + ////x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs + ////-----END CERTIFICATE-----"); + + // } + // break; + // case 2: + // { + // version = "6.7.2"; + // app_id = "v1_LCEO_Code"; + // app_key = "v2_4d5d55d6fbb6ce87b0f53019fefebb89"; + // machine_code = "v3_7af2592d5c49d94424bac95e80cb07a4"; + // channel_credentials = new SslCredentials(@"-----BEGIN CERTIFICATE----- + //MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV + //BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw + //CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW + //Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC + //Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV + //BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw + //ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG + //eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB + //F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD + //mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY + //ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 + //lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd + //AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME + //GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG + //SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q + //DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc + //sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl + //bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG + //DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf + //x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs + //-----END CERTIFICATE-----"); + // } + // break; + // default: + // break; + // } + + } + // internal static string[] grpc_info { get; set; } + + // internal static byte[] random_encry_key = CsharpHttpHelper.HttpExtend.RandomByte(16); + // internal static string version = "6.7.2"; + // internal static string app_id = "v1_LCEO_Code"; + // internal static string app_key = "v2_4d5d55d6fbb6ce87b0f53019fefebb89"; + // internal static string machine_code = "v3_7af2592d5c49d94424bac95e80cb07a4"; + // internal static SslCredentials channel_credentials = new SslCredentials(@"-----BEGIN CERTIFICATE----- + //MIIDqjCCApKgAwIBAgIJAOf7+/avi9foMA0GCSqGSIb3DQEBCwUAMGoxCzAJBgNV + //BAYTAkNOMQswCQYDVQQIDAJ4eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQsw + //CQYDVQQLDAJ4eDEUMBIGA1UEAwwLd2VjaGF0QHJvb3QxETAPBgkqhkiG9w0BCQEW + //Anh4MB4XDTE4MDUwODAwMzE1MFoXDTI4MDUwNTAwMzE1MFowajELMAkGA1UEBhMC + //Q04xCzAJBgNVBAgMAnh4MQswCQYDVQQHDAJ4eDELMAkGA1UECgwCeHgxCzAJBgNV + //BAsMAnh4MRQwEgYDVQQDDAt3ZWNoYXRAcm9vdDERMA8GCSqGSIb3DQEJARYCeHgw + //ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNcWVlhOpXjqivCpJpVHCG + //eM+Q/e83MDpqXmlT33hAFlCfUzWYYhFAHwc+xShkvuoaBwKpAr0fcHT7Kj4TLSJB + //F9FwBccPp4Tv0YH0h4pzZ9nWZCMGXB5TlXAreXrcu8Qab0MPAxMKtMO0FZzQawRD + //mO/S43u6tDBrhW2zgFzCUo+cRiCYRXoewuFVT4RT7eYvEu579oy4mto7YpR8GfPY + //ywiTh7D/4To7nNoWbly84WB9ZSQ8HZoC1KTykqaeSGw7xUhKEoPoeKPke1ECfXB2 + //lSZMwKar2IU0BVlvxL55EMF8oXJozLVEZeVIZ4Wp9EFY2KaZJowgoOa1I+vcwBbd + //AgMBAAGjUzBRMB0GA1UdDgQWBBR2SmMGUpTN/Dl0wcSYcPav6o01iDAfBgNVHSME + //GDAWgBR2SmMGUpTN/Dl0wcSYcPav6o01iDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG + //SIb3DQEBCwUAA4IBAQAdCSkska27VdLcGqK9/sraopxaX31Nseci/sJbimIHxr+q + //DwAHExU5sJ1qT827n2OpF/lWMRhnJZ3ubeJ8oGA3CAKu4EiKKGA1hGOLCbEvagCc + //sdBSegk050qkMssJzNaw7boZB8vek1RDK32Fuhsh4m+MUZBj6bJCdGW9K+ZMmpZl + //bMwmsgqV6+EMvr+PhFHy8bOAdIs4/eOTjW7R0JwYgFArVXMrVKgiRknkhM+PBBHG + //DPWO0j3855SF2X5r4jQs2PvKGJjOMuQeIgsf2GbwSQhXEhM8lGdjn9up8hm7VSXf + //x8wZquXczPSdDez7tP+g9nKbxcJtGnxo8+Jntmvs + //-----END CERTIFICATE-----"); + + + + /// + /// 执行JS + /// + /// JavaScript代码的字符串 + /// + public static string Usc2ToAnsi(string sCode) + { + ScriptControl scriptControl = new ScriptControl(); + scriptControl.UseSafeSubset = true; + scriptControl.Language = "JScript"; + scriptControl.AddCode("function asciiConvertNative(s){var asciicode=s.split(\"\\\\u\");var nativeValue=asciicode[0];for(var i=1;i4){nativeValue+=code.substring(4,code.length)}}return nativeValue};"); + try + { + string str = scriptControl.Eval(string.Format("asciiConvertNative('{0}')", sCode)).ToString(); + return str; + } + catch (Exception ex) + { + string str = ex.Message; + } + return null; + } + public static string BetweenArr(string str, string leftstr, string rightstr) + { + + int i = str.IndexOf(leftstr) + leftstr.Length; + string temp = str.Substring(i, str.IndexOf(rightstr, i) - i); + return temp; + } + + public static Bitmap GetImageFromBase64(string base64string) + { + byte[] b = Convert.FromBase64String(base64string); + MemoryStream ms = new MemoryStream(b); + Bitmap bitmap = new Bitmap(ms); + //ms.Close(); + return bitmap; + } + + + #region 返回一个随机表情 + private static string Expression = "[微笑],[憨笑],[呲牙],[爱心],[啤酒],[太阳],[礼物],[抱拳],[咖啡],[调皮],[激动],[回头],[色],[愉快],[爱情],[飞吻],[跳跳],[发抖],[转圈],[献吻],[耶],[红包],[嘿哈]"; + private static List ExpressionList = null; + private static Random random = new Random(); + public static string FindRandomExpression() + { + if (ExpressionList == null) + ExpressionList = Expression.Split(',').ToList(); + return ExpressionList[random.Next(ExpressionList.Count)]; + } + #endregion + + #region 发送代码 + // BaseUserInfo定义 + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct BaseUserInfo + { + //public int dwUin; + //public int dwDeviceVersion; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] + // public byte[] szCookies; + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + // public byte[] szSessionKey; + // [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] + // public string szDeviceid; + // [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 38)] + // public string szCode; + public int dwUin; + public int dwDeviceVersion; + public int dwSyncKeyLength; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] + public byte[] szCookies; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] szSessionKey; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] + public byte[] szSyncKey; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] + public string szDeviceid; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 38)] + public string szCode; + + + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct UploadImgInfo + { + + public int dwPayloadsLength; + public int dwTotalLen; + public int dwStartPos; + public int dwDataLen; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 65535 * 2)] + public byte[] szPayLoadsBuf; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 65535)] + public byte[] szImgBuf; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string ClientImgId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string szFromUserName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string szToUserName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string szCmdUrl; + + + } + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct UploadVoiceInfo + { + + public int dwPayloadsLength; + public int dwVoiceLength; + public int dwEndFlag; + public int dwVoiceFormat; + public int dwOffset; + public int dwVoiceBufLength; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 65535 * 2)] + public byte[] szPayLoadsBuf; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 65535)] + public byte[] szVoiceBuf; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string ClientMsgId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string szFromUserName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] + public string szToUserName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string szCmdUrl; + + + } + [DllImport("UICorePlus.dll", EntryPoint = "CUploadImg", CallingConvention = CallingConvention.Cdecl)] + public static extern int CUploadImg(ref BaseUserInfo userinfo, IntPtr imginfo); + + [DllImport("UICorePlus.dll", EntryPoint = "CUploadVoice", CallingConvention = CallingConvention.Cdecl)] + public static extern int CUploadVoice(ref BaseUserInfo userinfo, IntPtr voiceinfo); + [DllImport("UICorePlus.dll", EntryPoint = "CPackSync", CallingConvention = CallingConvention.Cdecl)] + public static extern int CPackSync(ref BaseUserInfo userinfo, ref byte encodeData); + [DllImport("UICorePlus.dll", EntryPoint = "CUnPackSync", CallingConvention = CallingConvention.Cdecl)] + public static extern int CUnPackSync(ref BaseUserInfo baseUserInfo, byte[] playload, int playloadlength, ref byte decodeData); + [DllImport("UICorePlus.dll", EntryPoint = "CGetContact", CallingConvention = CallingConvention.Cdecl)] + public static extern int CGetContact(ref BaseUserInfo baseUserInfo, byte[] playload, int playloadlength, ref byte encodeData); + [DllImport("UICorePlus.dll", EntryPoint = "CUnPackGetcontact", CallingConvention = CallingConvention.Cdecl)] + public static extern int CUnPackGetcontact(ref BaseUserInfo baseUserInfo, byte[] playload, int playloadlength, ref byte decodeData); + [DllImport("UICorePlus.dll", EntryPoint = "CSendMsg", CallingConvention = CallingConvention.Cdecl)] + public static extern int CSendMsg(ref BaseUserInfo baseUserInfo, byte[] playload, int playloadlength, ref byte encodeData); + [DllImport("UICorePlus.dll", EntryPoint = "CSendAppMsg", CallingConvention = CallingConvention.Cdecl)] + public static extern int CSendAppMsg(ref BaseUserInfo baseUserInfo, byte[] playload, int playloadlength, ref byte encodeData); + public static byte[] CUploadImg(User u, UploadImgInfo imginfo) + { //自行做好异常捕获 + BaseUserInfo userinfo = new BaseUserInfo(); + userinfo.szCookies = u.Cookies.ToByteArray(); + userinfo.szSessionKey = u.SessionKey.ToByteArray(); + string[] device = u.DeviceId.Split('@'); + userinfo.szDeviceid = device[2]; + userinfo.dwUin = (int)u.Uin; + userinfo.szCode = machine_code; + imginfo.szFromUserName = u.Userame; + int nSizeImginfo = Marshal.SizeOf(imginfo); + IntPtr intPtr = Marshal.AllocHGlobal(nSizeImginfo); + Marshal.StructureToPtr(imginfo, intPtr, true); + int ret = CUploadImg(ref userinfo, intPtr); + if (ret == -1) + { + //组包大于65535 + return null; + + } + imginfo = (UploadImgInfo)Marshal.PtrToStructure(intPtr, typeof(UploadImgInfo)); + byte[] encodeBuf = new byte[imginfo.dwPayloadsLength]; + Buffer.BlockCopy(imginfo.szPayLoadsBuf, 0, encodeBuf, 0, imginfo.dwPayloadsLength); + return encodeBuf; + } + public static byte[] CUploadVoice(User u, UploadVoiceInfo voiceinfo) + { + //自行做好异常捕获 + BaseUserInfo userinfo = new BaseUserInfo(); + userinfo.szCookies = u.Cookies.ToByteArray(); + userinfo.szSessionKey = u.SessionKey.ToByteArray(); + string[] device = u.DeviceId.Split('@'); + userinfo.szDeviceid = device[2]; + userinfo.dwUin = (int)u.Uin; + voiceinfo.szFromUserName = u.Userame; + userinfo.szCode = machine_code; + + int nSizeImginfo = Marshal.SizeOf(voiceinfo); + IntPtr intPtr = Marshal.AllocHGlobal(nSizeImginfo); + Marshal.StructureToPtr(voiceinfo, intPtr, true); + int ret = CUploadVoice(ref userinfo, intPtr); + if (ret == -1) + { + //组包大于65535 + return null; + + } + voiceinfo = (UploadVoiceInfo)Marshal.PtrToStructure(intPtr, typeof(UploadVoiceInfo)); + byte[] encodeBuf = new byte[voiceinfo.dwPayloadsLength]; + Buffer.BlockCopy(voiceinfo.szPayLoadsBuf, 0, encodeBuf, 0, voiceinfo.dwPayloadsLength); + return encodeBuf; + } + + + public static byte[] CPackSync(User u) + { //自行做好异常捕获 + try + { + BaseUserInfo userinfo = new BaseUserInfo(); + userinfo.szCookies = u.Cookies.ToByteArray(); + userinfo.szSessionKey = u.SessionKey.ToByteArray(); + string[] device = u.DeviceId.Split('@'); + userinfo.szDeviceid = device[2]; + userinfo.dwUin = (int)u.Uin; + byte[] synKeybuf = new byte[512];//不能更改此参数 若要更改必须同步c++ 缓冲器长度 + int keylength = 0; + + byte[] synKey = u.CurrentsyncKey.ToByteArray(); + + if (synKey.Length != 0) + { + + keylength = synKey.Length; + Buffer.BlockCopy(synKey, 0, synKeybuf, 0, keylength); + } + userinfo.szSyncKey = synKeybuf; + userinfo.dwSyncKeyLength = keylength; + userinfo.szCode = machine_code; + + byte[] s = new byte[65535]; + + int packLength = CPackSync(ref userinfo, ref s[0]); + if (packLength == -1) + return null;//组包失败 + + //ret + byte[] encodeBuf = new byte[packLength]; + Buffer.BlockCopy(s, 0, encodeBuf, 0, packLength); + return encodeBuf; + } + catch (Exception ex) + { + throw new Exception($"CPackSync ERROR:{ex.Message}\r\nuser:{Util.HexToStr(u.ToByteArray())}"); + } + } + public static byte[] CUnPackSync(User u, byte[] encodeData, ref byte[] syncKey) + { + //自行做好异常捕获 解包必须判断标准头191 + try + { + BaseUserInfo userinfo = new BaseUserInfo(); + userinfo.szCookies = u.Cookies.ToByteArray(); + userinfo.szSessionKey = u.SessionKey.ToByteArray(); + string[] device = u.DeviceId.Split('@'); + userinfo.szDeviceid = device[2]; + userinfo.dwUin = (int)u.Uin; + userinfo.szCode = machine_code; + byte[] s = new byte[65535 * 10];//可酌情扩容 + int packLength = CUnPackSync(ref userinfo, encodeData, encodeData.Length, ref s[0]); + if (packLength == -1) + return null;//组包失败 + + if (userinfo.dwSyncKeyLength != 0) + { + byte[] _syncKey = new byte[userinfo.dwSyncKeyLength]; + Buffer.BlockCopy(userinfo.szSyncKey, 0, _syncKey, 0, userinfo.dwSyncKeyLength); + syncKey = _syncKey; + } + //ret + byte[] decodeBuf = new byte[packLength]; + Buffer.BlockCopy(s, 0, decodeBuf, 0, packLength); + + return decodeBuf; + } + catch (Exception ex) + { + throw new Exception($"CUnPackSync ERROR:{ex.Message}\r\nuser:{Util.HexToStr(u.ToByteArray())}\r\ndata:{Util.HexToStr(encodeData)}"); + } + } + public static byte[] CGetContact(User u, byte[] jsonData) + { + //自行做好异常捕获 + BaseUserInfo userinfo = new BaseUserInfo(); + userinfo.szCookies = u.Cookies.ToByteArray(); + userinfo.szSessionKey = u.SessionKey.ToByteArray(); + string[] device = u.DeviceId.Split('@'); + userinfo.szDeviceid = device[2]; + userinfo.dwUin = (int)u.Uin; + userinfo.szCode = machine_code; + byte[] s = new byte[65535]; + int packLength = CGetContact(ref userinfo, jsonData, jsonData.Length, ref s[0]); + if (packLength == -1) + { + //组包大于65535 + return null; + + } + byte[] encodeData = new byte[packLength]; + Buffer.BlockCopy(s, 0, encodeData, 0, packLength); + return encodeData; + } + public static byte[] CUnPackGetcontact(User u, byte[] encodeData) + { + //自行做好异常捕获 解包必须判断标准头191 + BaseUserInfo userinfo = new BaseUserInfo(); + userinfo.szCookies = u.Cookies.ToByteArray(); + userinfo.szSessionKey = u.SessionKey.ToByteArray(); + string[] device = u.DeviceId.Split('@'); + userinfo.szDeviceid = device[2]; + userinfo.dwUin = (int)u.Uin; + userinfo.szCode = machine_code; + byte[] s = new byte[65535 * 2]; + int packLength = CUnPackGetcontact(ref userinfo, encodeData, encodeData.Length, ref s[0]); + if (packLength == -1) + { + //组包大于65535 + return null; + + } + + byte[] decodeBuf = new byte[packLength]; + Buffer.BlockCopy(s, 0, decodeBuf, 0, packLength); + return decodeBuf; + } + public static byte[] CSendMsg(User u, byte[] jsonData) + { + try + { + //自行做好异常捕获 + BaseUserInfo userinfo = new BaseUserInfo(); + userinfo.szCookies = u.Cookies.ToByteArray(); + userinfo.szSessionKey = u.SessionKey.ToByteArray(); + string[] device = u.DeviceId.Split('@'); + userinfo.szDeviceid = device[2]; + userinfo.dwUin = (int)u.Uin; + userinfo.szCode = machine_code; + byte[] s = new byte[65535]; + int packLength = CSendMsg(ref userinfo, jsonData, jsonData.Length, ref s[0]); + if (packLength == -1) + { + //组包大于65535 + return null; + + } + byte[] encodeData = new byte[packLength]; + Buffer.BlockCopy(s, 0, encodeData, 0, packLength); + return encodeData; + } + catch (Exception ex) + { + throw ex; + return null; + } + } + public static byte[] CSendAppMsg(User u, byte[] jsonData) + { + try + { + //自行做好异常捕获 + BaseUserInfo userinfo = new BaseUserInfo(); + userinfo.szCookies = u.Cookies.ToByteArray(); + userinfo.szSessionKey = u.SessionKey.ToByteArray(); + string[] device = u.DeviceId.Split('@'); + userinfo.szDeviceid = device[2]; + userinfo.dwUin = (int)u.Uin; + userinfo.szCode = machine_code; + byte[] s = new byte[65535]; + int packLength = CSendAppMsg(ref userinfo, jsonData, jsonData.Length, ref s[0]); + if (packLength == -1) + { + //组包大于65535 + return null; + + } + byte[] encodeData = new byte[packLength]; + Buffer.BlockCopy(s, 0, encodeData, 0, packLength); + return encodeData; + } + catch { } + return null; + } + + [DllImport("WeChatToken.dll", EntryPoint = "TokenSecret")] + + private extern static int TokenSecret(string inputData, StringBuilder outputData); + public static byte[] GetTokenSecret(byte[] inputData) + { + + string Secret = Util.HexToStr(inputData); + StringBuilder build = new StringBuilder(512); + int ret = TokenSecret(Secret, build); + if (ret == 0) + { + + + return Util.StrToHex(build.ToString()); + } + + return new byte[] { 0 }; + + + + } + #endregion + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/WeixinBase.cs b/类库/Chat.Framework/WXSdk/Implement/WeixinBase.cs new file mode 100644 index 0000000..cf048a2 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/WeixinBase.cs @@ -0,0 +1,680 @@ + +using Chat.Framework.PCRobotSDK; +using Chat.Framework.WXSdk.Events; +using Chat.Framework.WXSdk.IPAD; +using Google.Protobuf; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using WechatProto; + +namespace Chat.Framework.WXSdk.Implement +{ + /// + /// 朋友圈评论类型 + /// + public enum CircleCommentType : int + { + 评论 = 2, + 点赞 = 1 + } + + /// + /// 微信类型 + /// + public enum WeixinType + { + Grpc微信 = 1, + Hook微信 = 2, + QYHook微信 = 3 + } + + /// + /// 协议类型 + /// + public enum LoginDeviceType : int + { + 未知 = 0, + Ipad = 1, + Mac = 3, + Windows = 5, + QQBrowser = 7 + } + + /// + /// 协议操作类型 + /// + public enum EditContactsType + { + 保存通讯录 = 2051, + 取消保存通讯录 = 2, + + 星标 = 71, + 取消星标 = 7, + + 备注 = 7, + + 拉黑 = 15, + 取消拉黑 = 7, + + 置顶 = 2055, + 取消置顶 = 7 + } + + /// + /// 标签 + /// + public class Lable + { + /// + /// 标签名称 + /// + public string LabelName { get; set; } + + /// + /// 标签ID + /// + public string LabelID { get; set; } + } + + + /// + /// 微信基础用户 + /// + public class WeixinBaseUser + { + + /// + /// 机器人登录时间 + /// + public DateTime LoginTime { get; private set; } + private long _uin; + private string _nick; + private string _username; + /// + /// Uin + /// + public long Uin + { + get + { + if (this.User != null) return this.User.Uin; + else return _uin; + } + } + + /// + /// 机器人昵称 + /// + public string Nick + { + get + { + if (this.User != null) return Encoding.UTF8.GetString(this.User.Nickname.ToArray()); + else return _nick; + } + } + + /// + /// 机器人微信id + /// + public string Username + { + get + { + if (this.User != null) return this.User.Userame; + else return _username; + } + } + + public string Data + { + get + { + var _data = this.User.ToByteArray(); + return Util.HexToStr(_data); + } + } + + internal User User { get; set; } + + public WeixinBaseUser() + { + this.LoginTime = DateTime.Now; + + } + public WeixinBaseUser(User user) + { + this.User = user; + this.LoginTime = DateTime.Now; + } + public WeixinBaseUser(string data) + { + var temp = Util.StrToHex(data); + this.User = new User(); + this.User.MergeFrom(temp); + this.LoginTime = DateTime.Now; + } + + public WeixinBaseUser(string username, string nick, long uin = -1) + { + this._username = username; + this._uin = uin; + this._nick = nick; + } + } + + /// + /// 微信基类 + /// + public class WeixinBase : IDisposable + { + /// + /// 好友列表 + /// + public Dictionary Friends { get; internal set; } + + /// + /// 用户 + /// + public WeixinBaseUser User { get; set; } + + /// + /// 微信类型 + /// + public WeixinType WeixinType { get; set; } + + /// + /// 微信号 + /// + public string WeixinHao { get; internal set; } + + /// + /// 启动微信 + /// + public virtual void ShowLogin() { } + + /// + /// 退出微信 + /// + public virtual void LoginOut() { } + + /// + /// 退出微信 + /// + /// 退出说明 + public virtual void LoginOut(string message) { } + + /// + /// 微信状态 + /// + public WxStatus Status { get; set; } + + /// + /// 微信状态改变 + /// + /// 状态 + /// 微信修改状态事件,可为空 + /// 无用 + public virtual void ChangeStatus(WxStatus status, WXChangeStatus e = null, bool is_next = true) + { + if (this.Status == status) return; + + this.Status = status; + if (e == null) + { + ChatClient.Events.OnEvent(new WXChangeStatus(this)); + } + else + { + e.Status = status; + ChatClient.Events.OnEvent(e); + } + + if (this.Status == WxStatus.在线) + { + LogHelper.GetSingleObj().Debug("", $"微信状态改变:{this.User.Nick}({this.WeixinHao})"); + ChatClient.UpdateWXClient(this); + } + } + + /// + /// 重新连接微信 + /// + /// 连接数次 + public virtual void ResetConnection(int next = 3) { } + + /// + /// 获得联系人信息 + /// + /// 用户账号 + /// 时候刷新 + /// + public virtual Friend GetContact(string wxid, bool refresh = false) { return null; } + + /// + /// 发送消息 + /// + /// 接收者账号 + /// 发送的消息 + /// 艾特用户 + public virtual Task SendMessage(string username, string message, string atUsername = "") { return null; } + + /// + /// 发送小程序 + /// + /// 发送给谁 + /// 小程序ID + /// 所有者wxid + /// 小程序名称 + /// 小程序分享的标题 + /// 入口点 + /// 小程序图标 + /// 缩略图key1 + /// 缩略图key2 + /// 缩略图key3 + /// 缩略图大小 + public virtual void SendProgramMessage(string username, string ghid, string wxid, string name, string title, string enterpoint, string headimg, string image_key1, string image_key2, string image_key3, string image_size) { throw new Exception("本协议暂时不支持该方法"); } + + + /// + /// 刷新通讯录信息(获取好友列表) + /// + public virtual void RefreshContact(Action method = null) { } + + /// + /// 同意添加我为好友 + /// + /// 收到添加好友信息token信息 + /// + public virtual string AgreeAddMe(string token) { return string.Empty; } + + /// + /// 发送图片 + /// + /// 图片byte[] + /// 接收者账号 + public virtual void SendImage(byte[] img, string username) { throw new Exception("本协议暂时不支持该方法"); } + + /// + /// 分析事件 + /// + /// + public virtual void Receive(object obj) { throw new Exception("本协议暂时不支持该方法"); } + + /// + /// 发送卡片消息 + /// + /// 接收者账号 + /// 卡片用户账号 + public virtual void SendCard(string username, string friendwxid) { throw new Exception("本协议暂时不支持该方法"); } + + /// + /// 获取群成员,不支持pc + /// + /// 群id + /// 是否刷新 + /// + public virtual GroupMember[] GetMembers(string groupid, bool flag = false) { throw new Exception("本协议暂时不支持该方法"); } + + /// + /// 获取群用户信息 + /// + /// 群 + /// 用户账号 + /// + public virtual GroupMember GetMember(string groupid, string wxid) { throw new Exception("本协议暂时不支持该方法"); } + + /// + /// 获取群用户信息带刷新 + /// + /// 群 + /// 用户账号 + /// 刷新 + /// + public virtual GroupMember GetMember(string groupid, string wxid, bool flush = false) { throw new Exception("本协议暂时不支持该方法"); } + + /// + /// 发送图片 + /// + /// 接收者账号 + /// 图片地址 + public virtual void SendImage(string username, string address) { throw new Exception("本协议暂时不支持该方法"); } + /// + /// 搜索关键词 + /// + /// 关键词 + /// + public virtual Dictionary SerchKeyword(string keyword) { throw new Exception("本协议暂时不支持该方法"); } + /// + /// 关注公众号 + /// + /// 公众号账号 + /// + public virtual bool FocusWechat(string username) { throw new Exception("本协议暂时不支持该方法"); } + /// + /// 发送语音 + /// + /// 接收者账号 + /// 连接 + public virtual void SendVoice(string username, string url) { throw new Exception("本协议暂时不支持该方法"); } + + /// + /// 获得联系人二维码 + /// + /// 刷新 + /// + public virtual Bitmap GetRobotQRcode(bool Refresh = false) { return null; } + + /// + /// 验证支付 + /// + /// code + /// isHongbao + /// reqKey + /// bank + /// token + /// pass + /// + public virtual void SnsVerify(string code, bool isHongbao, string reqKey, BankCar bank, string token, string pass) { throw new Exception("本协议暂时不支持该方法"); } + + /// + /// 下载图片 + /// + /// 消息id + /// 账号 + /// 长度 + /// + public virtual string DownlowdImage(int msgid, string fromUsername, int datatotalength) { return string.Empty; } + + /// + /// 秒发CDN消息 + /// + /// 接收者账号 + /// cdnurl + /// aeskey + /// type + public virtual void SendCDNInfo(string tousername, string cdnurl, string aeskey, CDNType type) { } + + /// + /// 发送CDN图片 + /// + /// 接收者账号 + /// 图片cdn + public virtual void SendCDNImage(string tousername, string data) { } + + /// + /// 发送CDN视频 + /// + /// 接收者账号 + /// cdnurl + /// aeskey + public virtual void SendCDNVideo(string tousername, string cdnurl, string aeskey) { } + + /// + /// 发送红包 + /// + /// 接收者账号 + /// content + /// TotalAmount + /// password + /// count + /// type + /// bank + /// param + /// + public virtual string SendPay(string toUsername, string content, int TotalAmount, string password, int count, PayType type, BankCar bank = null, Dictionary param = null) { return string.Empty; } + + /// + /// 获得好友列表 + /// + /// + /// + public virtual List FindFriends() + { + return null; + } + + /// + /// 获取朋友圈 + /// + /// + public virtual List> FindCircles() { throw new Exception("此协议不支持,FindCircles!"); } + + /// + /// 获取群列表(不包含群成员) + /// + /// + public virtual List GetGroupsNotInMember() { return null; } + + /// + /// 检测URL在微信中是否有效 + /// + /// url + /// 0可以访问, -x 负值代表不能访问 + public virtual bool CheckUrl(string url) { throw new Exception("此协议不支持,CheckUrl!"); } + + /// + /// 打开内置浏览器 + /// + /// url + /// + public virtual void OpenUrl(string url) { throw new Exception("此协议不支持,OpenUrl!"); } + + /// + /// 清理历史聊天记录 + /// + /// + public virtual void ClearChatHistoryMsg() { throw new Exception("此协议不支持,ClearChatHistoryMsg!"); } + + /// + /// 设置会话已读 + /// + public virtual void SetSessionReadedMsg(string wxid) { throw new Exception("此协议不支持,SetSessionReadedMsg!"); } + + /// + /// 修改群聊名称 + /// + /// 新的群名 + /// 群id + public virtual void SetRoomName(string new_name, string groupId) { throw new Exception("此协议不支持,SetRoomName!"); } + + /// + /// 修改群公告(可用于@全体) + /// + /// 新公告 + /// 群聊wxid + public virtual void SetRoomNotice(string notice, string groupId) { throw new Exception("此协议不支持,SetRoomNotice!"); } + + /// + /// 设置自己在群中昵称 + /// + /// 要设置的昵称 + /// 需要设置的群id + public virtual void ModRoomMyName(string nickname, string groupId) { throw new Exception("此协议不支持,ModRoomMyName!"); } + + /// + /// 设置是否显示群成员昵称 + /// + /// true为开启 + /// 要显示得到群 + public virtual void SetRoomShowMemeberName(bool status, string groupId) { throw new Exception("此协议不支持,SetRoomShowMemeberName!"); } + + /// + /// 修改群聊名称 + /// + /// 新名称 + /// 群号 + public virtual void ModRoomName(string newnick, string groupId) { throw new Exception("此协议不支持,ModRoomName!"); } + + /// + /// 是否消息免打扰 + /// + /// true为开启 + /// wxid + public virtual void SetRecvNotify(bool status, string wxid) { throw new Exception("此协议不支持,SetRecvNotify!"); } + + /// + /// 创建群聊 + /// + /// 用户账号用英文逗号分隔 + public virtual string CreateChatRoom(string members) { throw new Exception("此协议不支持,CreateChatRoom!"); } + + /// + /// 创建群 + /// + /// 用户账号3个或者以上 + public virtual string CreateChatRoom(string[] wxids) { throw new Exception("此协议不支持,CreateChatRoom!"); } + + /// + /// 添加群用户 + /// + /// 群号 + /// 用户wxid多个用户逗号分隔 + public virtual void AddChatRoomMember(string groupid, string members) { throw new Exception("此协议不支持,AddChatRoomMember!"); } + + /// + /// 添加群用户_40人以下 + /// + /// 群id + /// 用户账号多个用英文逗号分隔 + public virtual void AddChatRoomMember_40Down(string groupid, string members) { throw new Exception("此协议不支持,AddChatRoomMember!"); } + + /// + /// 关注公众号 + /// + /// 公众号wxid + public virtual void AddPublicUser(string wxid) { throw new Exception("此协议不支持,AddPublicUser!"); } + + /// + /// 开启/关闭防撤回功能 + /// + /// 1是开启防撤回,0是关闭 + public virtual void SetDisableRevoke(bool status) { throw new Exception("此协议不支持,SetDisableRevoke!"); } + + /// + /// 发表朋友圈 + /// + /// 内容-需要携带至少一张图片,例如:[图片=路径] + /// + public virtual string SendCircle(string msg) { throw new Exception("此协议不支持,SendCircle!"); } + /// + /// 发表评论 + /// + /// 发送的微信ID + /// 朋友圈的ID + /// 发送的内容 + /// + public virtual void SendCircleComment(string username, string circleId, string content) { throw new Exception("此协议不支持,SendCircleComment!"); } + /// + /// 点赞 + /// + /// 账号 + /// 朋友圈id + public virtual void SendCirclePraise(string username, string circleId) { throw new Exception("此协议不支持,SendCirclePraise!"); } + /// + /// 获取朋友圈 + /// + /// 微信ID + /// 页码 + /// 页码ID + /// + public virtual List> FindCircle(string username, string firstPageMd5 = "", long MaxId = 0) { throw new Exception("此协议不支持,FindCircle!"); } + + /// + /// 自动授权登录小程序 + /// + /// appid + public virtual string AutoAuthMiniAPPLogin(string appid) { throw new Exception("此协议不支持,AutoAuthMiniAPPLogin!"); } + + private static LogHelper log = new LogHelper(); + /// + /// 写出日志 + /// + /// 内容 + /// 是否为debug + public void WriteLog(string msg, bool debug = false) + { + ChatClient.Events.OnEvent(new WXWriteLog(this) { IsDebug = debug, Message = msg }); + } + + /// + /// 编辑用户信息 + /// + /// 操作用户 + /// 操作类型 + /// 如果Type=备注,为空表示取消备注,不为空表示备注所填写内容 + public virtual void EditContacts(string username, EditContactsType type, string remark = "") { } + + /// + /// 删除朋友 + /// + /// 用户wxid + /// + public virtual string DeleteFriend(string username) { return null; } + + /// + /// 邀请入群 + /// + /// 用户wxid + /// 群id + /// + public virtual string InviteIntoGroup(string username, string groupId) { return null; } + + /// + /// 删除群用户 + /// + /// 用户账号 + /// 群id + /// + public virtual string DeleteGroupMember(string username, string groupId) { return null; } + + public void Dispose() + { + + } + + + public virtual Dictionary GetBalance() { return null; } + + /// + /// 领取转账 + /// + /// 收到转账中的Invalidtime + /// 收到转账中的Transferid + /// 收到转账中的FromUsername + /// + public virtual int TenPayTransferConfirm(string Invalidtime, string Transferid, string FromUsername) { return -1; } + + /// + /// 获取标签组 + /// + /// 是否刷新标签组 + /// + public virtual List GetLabelList(bool refresh = false) { throw new Exception("此协议不支持,GetTagList!"); } + + /// + /// 添加标签 + /// + /// 标签名称 + /// + public virtual bool AddLabel(string TagName) { throw new Exception("此协议不支持,AddTag!"); } + + /// + /// 批量修改标签 + /// + /// 用户信息 + /// 标签组 + /// + public virtual bool EditUserLabel(string[] Users, List Lable) { throw new Exception("此协议不支持,ModifyUserTag!"); } + + ///// + ///// 获取PC微信登录二维码 + ///// + ///// + //public virtual RemoteLoginCode GetLoginCode() { throw new Exception("此协议不支持,GetLoginCode!"); } + } +} diff --git a/类库/Chat.Framework/WXSdk/Implement/WeixinClientImpl_TCPHook.cs b/类库/Chat.Framework/WXSdk/Implement/WeixinClientImpl_TCPHook.cs new file mode 100644 index 0000000..7f3a48a --- /dev/null +++ b/类库/Chat.Framework/WXSdk/Implement/WeixinClientImpl_TCPHook.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk.Implement +{ + public class WeixinClientImpl_TCPServer:WeixinBase + { + + } +} diff --git a/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.Designer.cs b/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.Designer.cs new file mode 100644 index 0000000..b6e0711 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.Designer.cs @@ -0,0 +1,62 @@ +namespace Chat.Framework.WXSdk.UIForm +{ + partial class BrowserForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.webBrowser1 = new System.Windows.Forms.WebBrowser(); + this.SuspendLayout(); + // + // webBrowser1 + // + this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill; + this.webBrowser1.Location = new System.Drawing.Point(0, 0); + this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20); + this.webBrowser1.Name = "webBrowser1"; + this.webBrowser1.Size = new System.Drawing.Size(467, 398); + this.webBrowser1.TabIndex = 0; + // + // BrowserForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(467, 398); + this.Controls.Add(this.webBrowser1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "BrowserForm"; + this.Text = "BrowserForm"; + this.Load += new System.EventHandler(this.BrowserForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.WebBrowser webBrowser1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.cs b/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.cs new file mode 100644 index 0000000..c195d80 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Chat.Framework.WXSdk.UIForm +{ + public partial class BrowserForm : Form + { + string url = string.Empty; + /// + /// + /// + /// + public BrowserForm(string url) + { + InitializeComponent(); + this.url = url; + } + + private void BrowserForm_Load(object sender, EventArgs e) + { + webBrowser1.Navigate(url); + } + } +} diff --git a/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.resx b/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/BrowserForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.Designer.cs b/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.Designer.cs new file mode 100644 index 0000000..8910fb5 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.Designer.cs @@ -0,0 +1,48 @@ +namespace Chat.Framework.WXSdk.UIForm +{ + partial class HOOKForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // HOOKForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(249, 69); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "HOOKForm"; + this.Text = "监听微信消息"; + this.ResumeLayout(false); + + } + + #endregion + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.cs b/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.cs new file mode 100644 index 0000000..d06fd8c --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.cs @@ -0,0 +1,129 @@ +using Chat.Framework.WXSdk.Implement; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace Chat.Framework.WXSdk.UIForm +{ + + public partial class HOOKForm : Form + { + public HOOKForm(WXClientImpl_HOOK hook) + { + InitializeComponent(); + this.hook = hook; + this.Text = "MyWeChat"+hook.Process.Id; + } + WXClientImpl_HOOK hook; + public struct COPYDATASTRUCT + { + public IntPtr dwData; + public int cbData; + [MarshalAs(UnmanagedType.LPStr),] + public string lpData; + } + + public enum MsgType:int + { + 获得二维码 = 5, + 登录窗口句柄改变 = 10001, + 聊天窗口句柄改变 = 10002, + 机器人信息刷新 = 10003, + 好友列表数据刷新 = 10004, + 错误信息 = 10005, + 群列表数据刷新 = 10006, + 选中了微信窗口 = 10007, + 查询申请人列表 = 10008, + 收到私聊消息 = 10011, + 收到群聊消息 = 10012, + 发送了一条消息 = 10014, + 未知消息 + } + + /// 消息主要接受程序 + /// + /// + protected override void DefWndProc(ref Message m) + { + switch (m.Msg) + { + case 74: //74代表WM_COPYDATA + // + //消息号 (int)m.WParam + var msg = (int)m.WParam; + MsgType f = (MsgType)(msg); + COPYDATASTRUCT cds = new COPYDATASTRUCT(); + Type t = cds.GetType(); + try + { + cds = (COPYDATASTRUCT)m.GetLParam(t); + } + catch (Exception) + { + } + Console.WriteLine($"{f}:{cds.lpData}"); + switch (f) + { + case MsgType.获得二维码: + { + var temp = cds.lpData.Split(new string[] { "||"}, StringSplitOptions.None); + if (temp.Length > 1 && File.Exists(temp[1])) + { + File.Delete(temp[1]); + } + break; + } + case MsgType.登录窗口句柄改变: + case MsgType.聊天窗口句柄改变: + hook.WxHandel = int.Parse(cds.lpData); + break; + case MsgType.机器人信息刷新: + { + var temp = cds.lpData.Split(new string[] { "||"}, StringSplitOptions.None); + //机器人信息刷新:省钱管家-喵喵||sqgj121||wxid_zia3qen528cf22||http://wx.qlogo.cn/mmhead/ver_1/ibb1ZKLYa6cr5ibEademibNN1AjAu3JT9K3z3uERYXGx3VdWicsThtbBJB7mibRS3Ihk7GqFKXl1KfkNicXjlicmdqAIky2zpsmt7U143hicaxzR6TY/0 + hook.User = new WeixinBaseUser(temp[2],temp[0]); + + } + break; + case MsgType.好友列表数据刷新: + { + + } + break; + case MsgType.错误信息: + break; + case MsgType.群列表数据刷新: + break; + case MsgType.选中了微信窗口: + break; + case MsgType.查询申请人列表: + break; + case MsgType.收到私聊消息: + break; + case MsgType.收到群聊消息: + break; + case MsgType.发送了一条消息: + break; + case MsgType.未知消息: + break; + default: + break; + } + + //消息内容 cds.lpData + break; + default: + base.DefWndProc(ref m); + break; + } + } + } +} diff --git a/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.resx b/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/HOOKForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/LoginForm.Designer.cs b/类库/Chat.Framework/WXSdk/UIForm/LoginForm.Designer.cs new file mode 100644 index 0000000..a40c64e --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/LoginForm.Designer.cs @@ -0,0 +1,180 @@ +namespace Chat.Framework.WXSdk.UIForm +{ + partial class LoginForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.label2 = new System.Windows.Forms.Label(); + this.checkEdit1 = new DevExpress.XtraEditors.CheckEdit(); + this.radioButton2 = new System.Windows.Forms.RadioButton(); + this.radioButton3 = new System.Windows.Forms.RadioButton(); + this.radioButton4 = new System.Windows.Forms.RadioButton(); + this.label3 = new System.Windows.Forms.Label(); + this.radioButton1 = new System.Windows.Forms.RadioButton(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.label1.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(28, 368); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(322, 38); + this.label1.TabIndex = 2; + this.label1.Text = "正在获取登录二维码,请稍等..."; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // pictureBox1 + // + this.pictureBox1.Location = new System.Drawing.Point(62, 12); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(280, 280); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureBox1.TabIndex = 0; + this.pictureBox1.TabStop = false; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.ForeColor = System.Drawing.Color.DarkGray; + this.label2.Location = new System.Drawing.Point(304, 380); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(54, 14); + this.label2.TabIndex = 3; + this.label2.Text = "状态码:0"; + // + // checkEdit1 + // + this.checkEdit1.Location = new System.Drawing.Point(141, 346); + this.checkEdit1.Name = "checkEdit1"; + this.checkEdit1.Properties.Appearance.ForeColor = System.Drawing.Color.Blue; + this.checkEdit1.Properties.Appearance.Options.UseForeColor = true; + this.checkEdit1.Properties.Caption = "初始化通讯录"; + this.checkEdit1.Size = new System.Drawing.Size(107, 18); + this.checkEdit1.TabIndex = 4; + // + // radioButton2 + // + this.radioButton2.AutoSize = true; + this.radioButton2.Location = new System.Drawing.Point(118, 312); + this.radioButton2.Name = "radioButton2"; + this.radioButton2.Size = new System.Drawing.Size(46, 18); + this.radioButton2.TabIndex = 6; + this.radioButton2.Text = "Mac"; + this.radioButton2.UseVisualStyleBackColor = true; + this.radioButton2.CheckedChanged += new System.EventHandler(this.radioButton2_CheckedChanged); + // + // radioButton3 + // + this.radioButton3.AutoSize = true; + this.radioButton3.Location = new System.Drawing.Point(190, 312); + this.radioButton3.Name = "radioButton3"; + this.radioButton3.Size = new System.Drawing.Size(75, 18); + this.radioButton3.TabIndex = 7; + this.radioButton3.Text = "Windows"; + this.radioButton3.UseVisualStyleBackColor = true; + this.radioButton3.CheckedChanged += new System.EventHandler(this.radioButton3_CheckedChanged); + // + // radioButton4 + // + this.radioButton4.AutoSize = true; + this.radioButton4.Location = new System.Drawing.Point(282, 312); + this.radioButton4.Name = "radioButton4"; + this.radioButton4.Size = new System.Drawing.Size(87, 18); + this.radioButton4.TabIndex = 8; + this.radioButton4.Text = "QQBrowser"; + this.radioButton4.UseVisualStyleBackColor = true; + this.radioButton4.CheckedChanged += new System.EventHandler(this.radioButton4_CheckedChanged); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Font = new System.Drawing.Font("Tahoma", 21.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.ForeColor = System.Drawing.Color.Gray; + this.label3.Location = new System.Drawing.Point(126, 130); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(160, 35); + this.label3.TabIndex = 9; + this.label3.Text = "请选择线路"; + // + // radioButton1 + // + this.radioButton1.AutoSize = true; + this.radioButton1.Location = new System.Drawing.Point(43, 312); + this.radioButton1.Name = "radioButton1"; + this.radioButton1.Size = new System.Drawing.Size(49, 18); + this.radioButton1.TabIndex = 10; + this.radioButton1.Text = "Ipad"; + this.radioButton1.UseVisualStyleBackColor = true; + this.radioButton1.Click += new System.EventHandler(this.radioButton1_Click); + // + // LoginForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(408, 414); + this.Controls.Add(this.radioButton1); + this.Controls.Add(this.label3); + this.Controls.Add(this.radioButton4); + this.Controls.Add(this.radioButton3); + this.Controls.Add(this.radioButton2); + this.Controls.Add(this.checkEdit1); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.pictureBox1); + this.IconOptions.ShowIcon = false; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "LoginForm"; + this.Text = "微信登录"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LoginForm_FormClosing); + this.Load += new System.EventHandler(this.LoginForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.checkEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private DevExpress.XtraEditors.CheckEdit checkEdit1; + private System.Windows.Forms.RadioButton radioButton2; + private System.Windows.Forms.RadioButton radioButton3; + private System.Windows.Forms.RadioButton radioButton4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.RadioButton radioButton1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/LoginForm.cs b/类库/Chat.Framework/WXSdk/UIForm/LoginForm.cs new file mode 100644 index 0000000..d774665 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/LoginForm.cs @@ -0,0 +1,278 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Chat.Framework.Properties; +using Chat.Framework.WXSdk.Implement; +using CsharpHttpHelper; +using UI.Framework.Forms; + +namespace Chat.Framework.WXSdk.UIForm +{ + /// + /// + /// + public partial class LoginForm : BaseForm + { + /// + /// + /// + /// + public LoginForm(WXClientImpl_IPAD wx) + { + InitializeComponent(); + this.wx = wx; + + ChatClient.Events.WXChangeStatusEvent += Events_WXStatusChangeEvent; + ChatClient.Events.WXScavengEvent += Events_WXScavengEvent; + } + + private void Events_WXScavengEvent(object sender, Events.WXScavengEvents e) + { + this.Invoke(new Action(delegate + { + this.label2.Text = "状态码:" + e.Status; + })); + } + + private Thread thread_check = null; + + private void Events_WXStatusChangeEvent(object sender, Events.WXChangeStatus e) + { + try + { + this.Invoke(new Action(delegate + { + // this.label1.Text = e.Status.ToString(); + try + { + if (e.ImageByte != null) + { + this.pictureBox1.Image = e.Image; + } + //Console.WriteLine(e.Status); + switch (e.Status) + { + case WxStatus.登录中: + this.label1.Text = "正在获取登录二维码,请稍等..."; + break; + case WxStatus.扫码中: + this.label1.Text = "请打开[手机微信]扫描二维码登录"; + thread_check.Start(); + break; + case WxStatus.在线: + case WxStatus.取消扫码: + this.Close(); + break; + case WxStatus.获取头像成功: + this.label1.Text = "扫码成功,请确认登录"; + break; + case WxStatus.登录失败: + isRun = false; + this.label1.Text = e.Message; + + var url = HttpExtend.RegexMatchUrl(e.Message); + if (!string.IsNullOrWhiteSpace(url)) + { + if (e.Message.Contains("你的微信版本过低,请升级至最新版本微信后再登录微信") && !radioButton4.Checked) + { + radioButton4.Checked = true; + } + else + { + var browser = new BrowserForm(url); + browser.Text = "系统消息"; + browser.Show(); + } + } + else + { + MessageBox.Show(e.Message, "登录失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + this.Close(); + } + break; + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + finally + { + try + { + if (e.Image != null) + e.Image.Dispose(); + } + catch (Exception ex) + { } + } + })); + } + catch (Exception) { } + } + private void CloseThread() + { + isRun = false; + try + { + if (thread_check != null) thread_check.Abort(); + } + catch (Exception) + { + } + + try + { + + if (thread_login != null) thread_login.Abort(); + } + catch (Exception) + { + } + } + private bool isRun = true; + private WXClientImpl_IPAD wx; + private void LoginForm_Load(object sender, EventArgs e) + { + + } + + Thread thread_login = null; + + private void check_login_status() + { + try + { + while (this.wx.Status != WxStatus.登录失败 && isRun) + { + try + { + this.wx.FindLoginStatus(); + Thread.Sleep(200); + } + catch (ThreadAbortException) { } + catch (Exception ex) + { + if (this.IsHandleCreated) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowError(ex.Message + "," + ex.StackTrace); + })); + } + } + } + } + catch (Exception) + { + + } + + } + + private void LoginForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + isRun = false; + ChatClient.Events.WXChangeStatusEvent -= Events_WXStatusChangeEvent; + ChatClient.Events.WXScavengEvent -= Events_WXScavengEvent; + if (wx.Status != WxStatus.在线) + { + wx.LoginOut(); + LogHelper.GetSingleObj().Debug("", $"扫码退出:{wx.User.Nick}({wx.User.Username})"); + } + else + { + if (this.checkEdit1.Checked) + { + wx.RefreshContact();//刷新通讯录 + } + } + } + catch (Exception) + { + } + } + + private void radioButton1_CheckedChanged(object sender, EventArgs e) + { + Login(LoginDeviceType.Ipad); + } + + private bool is_logining = false; + private void Login(LoginDeviceType type) + { + label3.Visible = false; + + CloseThread(); + + try + { + isRun = true; + thread_check = new Thread(new ThreadStart(check_login_status)); + thread_check.IsBackground = true; + + + thread_login = new Thread(new ThreadStart(delegate + { + + Thread.Sleep(10); + try + { + wx.FindLoginImage(type); + } + catch (ThreadAbortException) + { + + } + catch (Exception ex) + { + + if (this.IsHandleCreated) + { + this.Invoke(new Action(delegate + { + BaseForm.ShowError(ex.Message + "," + ex.StackTrace); + })); + } + } + })); + thread_login.IsBackground = true; + thread_login.Start(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void radioButton2_CheckedChanged(object sender, EventArgs e) + { + Login(LoginDeviceType.Mac); + } + + private void radioButton3_CheckedChanged(object sender, EventArgs e) + { + Login(LoginDeviceType.Windows); + } + + private void radioButton4_CheckedChanged(object sender, EventArgs e) + { + Login(LoginDeviceType.QQBrowser); + } + + private void radioButton1_Click(object sender, EventArgs e) + { + Login(LoginDeviceType.Ipad); + } + } +} diff --git a/类库/Chat.Framework/WXSdk/UIForm/LoginForm.resx b/类库/Chat.Framework/WXSdk/UIForm/LoginForm.resx new file mode 100644 index 0000000..e686138 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/LoginForm.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 49 + + \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.Designer.cs b/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.Designer.cs new file mode 100644 index 0000000..20c04d7 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.Designer.cs @@ -0,0 +1,166 @@ +namespace Chat.Framework.WXSdk.UIForm +{ + partial class LoginwxPassForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoginwxPassForm)); + this.tabPane1 = new DevExpress.XtraBars.Navigation.TabPane(); + this.tabNavigationPage1 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).BeginInit(); + this.tabPane1.SuspendLayout(); + this.tabNavigationPage1.SuspendLayout(); + this.SuspendLayout(); + // + // tabPane1 + // + this.tabPane1.AllowCollapse = DevExpress.Utils.DefaultBoolean.Default; + this.tabPane1.Controls.Add(this.tabNavigationPage1); + this.tabPane1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabPane1.Location = new System.Drawing.Point(0, 0); + this.tabPane1.Name = "tabPane1"; + this.tabPane1.Pages.AddRange(new DevExpress.XtraBars.Navigation.NavigationPageBase[] { + this.tabNavigationPage1}); + this.tabPane1.RegularSize = new System.Drawing.Size(385, 403); + this.tabPane1.SelectedPage = this.tabNavigationPage1; + this.tabPane1.Size = new System.Drawing.Size(385, 403); + this.tabPane1.TabIndex = 0; + this.tabPane1.Text = "tabPane1"; + // + // tabNavigationPage1 + // + this.tabNavigationPage1.Caption = "62登陆"; + this.tabNavigationPage1.Controls.Add(this.textBox3); + this.tabNavigationPage1.Controls.Add(this.label3); + this.tabNavigationPage1.Controls.Add(this.simpleButton1); + this.tabNavigationPage1.Controls.Add(this.textBox2); + this.tabNavigationPage1.Controls.Add(this.textBox1); + this.tabNavigationPage1.Controls.Add(this.label2); + this.tabNavigationPage1.Controls.Add(this.label1); + this.tabNavigationPage1.Name = "tabNavigationPage1"; + this.tabNavigationPage1.Size = new System.Drawing.Size(385, 375); + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(129, 153); + this.textBox3.Multiline = true; + this.textBox3.Name = "textBox3"; + this.textBox3.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox3.Size = new System.Drawing.Size(195, 125); + this.textBox3.TabIndex = 17; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(55, 156); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(50, 14); + this.label3.TabIndex = 16; + this.label3.Text = "62Data:"; + // + // simpleButton1 + // + this.simpleButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton1.ImageOptions.Image"))); + this.simpleButton1.Location = new System.Drawing.Point(172, 310); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(107, 34); + this.simpleButton1.TabIndex = 15; + this.simpleButton1.Text = "登陆"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(129, 99); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(195, 22); + this.textBox2.TabIndex = 12; + // + // textBox1 + // + this.textBox1.Enabled = false; + this.textBox1.Location = new System.Drawing.Point(129, 39); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(195, 22); + this.textBox1.TabIndex = 11; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(59, 102); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(51, 14); + this.label2.TabIndex = 9; + this.label2.Text = "密 码:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(55, 42); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 8; + this.label1.Text = "用户名:"; + // + // LoginwxPassForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(385, 403); + this.Controls.Add(this.tabPane1); + this.Name = "LoginwxPassForm"; + this.Text = "登录微信"; + this.Load += new System.EventHandler(this.LoginwxPassForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).EndInit(); + this.tabPane1.ResumeLayout(false); + this.tabNavigationPage1.ResumeLayout(false); + this.tabNavigationPage1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraBars.Navigation.TabPane tabPane1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Label label3; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.cs b/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.cs new file mode 100644 index 0000000..30e9908 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using Chat.Framework.WXSdk.Events; +using UI.Framework.Forms; + +namespace Chat.Framework.WXSdk.UIForm +{ + public partial class LoginwxPassForm : BaseForm + { + public LoginwxPassForm(WXSdk.Implement.WXClientImpl_IPAD client) + { + InitializeComponent(); + this.client = client; + + ChatClient.Events.WXChangeStatusEvent += Events_WXStatusChangeEvent; + ChatClient.Events.WXScavengEvent += Events_WXScavengEvent; + this.textBox1.Text = this.client.WeixinHao; + + } + + private void Events_WXStatusChangeEvent(object sender, WXChangeStatus e) + { + switch (e.Status) + { + case WxStatus.未登录: + break; + case WxStatus.登录中: + break; + case WxStatus.扫码中: + break; + case WxStatus.扫码成功: + break; + case WxStatus.登录失败: + this.Invoke(new Action(delegate + { + MessageBox.Show(e.Message, "登录失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + if (e.Message.Contains("你在新手机登录微信")) + { + var reg = Regex.Match(e.Message, "\\[(https://.*?)\\]"); + if (reg.Success) System.Diagnostics.Process.Start(reg.Groups[1].Value); + } + })); + break; + case WxStatus.在线: + case WxStatus.取消扫码: + this.Close(); + break; + case WxStatus.获取头像成功: + break; + default: + break; + } + + + + } + + private void Events_WXScavengEvent(object sender, WXScavengEvents e) + { + + } + + WXSdk.Implement.WXClientImpl_IPAD client; + private void LoginwxPassForm_Load(object sender, EventArgs e) + { + + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + client.Login(this.textBox1.Text,this.textBox2.Text,this.textBox3.Text); + + } + catch (Exception ex) + { + MessageBox.Show(ex.Message,"操作失败",MessageBoxButtons.OK,MessageBoxIcon.Error); + } + } + + + + + private void linkLabel1_LinkClicked_1(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + string str = client.GetLoginCode(this.textBox1.Text); + var reg = Regex.Match(str, "\\[(https://.*?)\\]"); + if (reg.Success) System.Diagnostics.Process.Start(reg.Groups[1].Value); + else MessageBox.Show(str); + + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + string str = client.VerifyLoginSmsCode(this.textBox1.Text,this.textBox3.Text); + MessageBox.Show(str); + //Console.WriteLine(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + client.Login(this.textBox1.Text, this.textBox2.Text,this.textBox3.Text); + //string str = client.Login62("62706c6973743030d4010203040506090a582476657273696f6e58246f626a65637473592461726368697665725424746f7012000186a0a2070855246e756c6c5f102030656335343133373337626430343665326337376166633837636537633438395f100f4e534b657965644172636869766572d10b0c54726f6f74800108111a232d32373a406375787d0000000000000101000000000000000d0000000000000000000000000000007f"); + //MessageBox.Show(str); + //Console.WriteLine(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.resx b/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.resx new file mode 100644 index 0000000..aa716b0 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/LoginwxPassForm.resx @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.Designer.cs b/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.Designer.cs new file mode 100644 index 0000000..d3f1726 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.Designer.cs @@ -0,0 +1,65 @@ +namespace Chat.Framework.WXSdk.UIForm +{ + partial class PCLoginForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox1 + // + this.pictureBox1.Location = new System.Drawing.Point(12, 12); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(280, 280); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureBox1.TabIndex = 1; + this.pictureBox1.TabStop = false; + // + // PCLoginForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(306, 313); + this.Controls.Add(this.pictureBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "PCLoginForm"; + this.Text = "PC微信登录"; + this.Load += new System.EventHandler(this.PCLoginForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.cs b/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.cs new file mode 100644 index 0000000..87c48c6 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.cs @@ -0,0 +1,70 @@ +using Chat.Framework.PCRobotSDK; +using Newtonsoft.Json; +using PCRobot.Pack; +using SuperSocket.SocketBase; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.WXSdk.UIForm +{ + public partial class PCLoginForm : BaseForm + { + private Image codeImg; + private RemoteLoginCode rlc; + private AppSession appSession; + private string robotname; + + public PCLoginForm(Image codeImg, RemoteLoginCode rlc, string robotname, AppSession appSession) + { + InitializeComponent(); + this.codeImg = codeImg; + this.rlc = rlc; + this.appSession = appSession; + this.robotname = robotname; + } + + private void PCLoginForm_Load(object sender, EventArgs e) + { + this.pictureBox1.Image = codeImg; + Task.Run(() => + { + try + { + var msgid = ChatClient.SendServer(appSession, robotname, rlc.rType, rlc.pid.ToString()); + if (!string.IsNullOrEmpty(msgid)) + { + var rst = ChatClient.PCRobotPool.PackHist.GetResult(msgid).Result; + if (rst != null) + { + try + { + var commonResult = rst as CommonResult; + if (commonResult != null) + { + this.Invoke(new Action(() => + { + this.Close(); + })); + } + } + catch (Exception ex) + { + BaseForm.ShowSuccessAutoClose("验证易转发微信登录:" + ex.Message); + } + } + } + } + catch (Exception) + { } + }); + } + } +} diff --git a/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.resx b/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/PCLoginForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.Designer.cs b/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.Designer.cs new file mode 100644 index 0000000..8d821df --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.Designer.cs @@ -0,0 +1,133 @@ +namespace Chat.Framework.WXSdk.UIForm +{ + partial class SetwxhForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.groupControl1 = new DevExpress.XtraEditors.GroupControl(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).BeginInit(); + this.groupControl1.SuspendLayout(); + this.SuspendLayout(); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(89, 24); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(181, 20); + this.textEdit1.TabIndex = 0; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(30, 27); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(40, 14); + this.labelControl1.TabIndex = 1; + this.labelControl1.Text = "微信号:"; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(293, 22); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(63, 24); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = "确认"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textBox1 + // + this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.textBox1.Location = new System.Drawing.Point(2, 21); + this.textBox1.Multiline = true; + this.textBox1.Name = "textBox1"; + this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.textBox1.Size = new System.Drawing.Size(387, 122); + this.textBox1.TabIndex = 0; + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.ForeColor = System.Drawing.SystemColors.ControlDark; + this.checkBox1.Location = new System.Drawing.Point(8, 69); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(381, 18); + this.checkBox1.TabIndex = 1; + this.checkBox1.Text = "老机器人(AliTools)账号【首次】转入 、输入设备信息防止账号异常"; + this.checkBox1.UseVisualStyleBackColor = true; + this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged); + // + // groupControl1 + // + this.groupControl1.Controls.Add(this.textBox1); + this.groupControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.groupControl1.Location = new System.Drawing.Point(0, 97); + this.groupControl1.Name = "groupControl1"; + this.groupControl1.Size = new System.Drawing.Size(391, 145); + this.groupControl1.TabIndex = 3; + this.groupControl1.Text = "设备信息"; + // + // SetwxhForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(391, 242); + this.Controls.Add(this.checkBox1); + this.Controls.Add(this.groupControl1); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.textEdit1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SetwxhForm"; + this.Text = "设置微信号"; + this.Load += new System.EventHandler(this.SetwxhForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.groupControl1)).EndInit(); + this.groupControl1.ResumeLayout(false); + this.groupControl1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.CheckBox checkBox1; + private DevExpress.XtraEditors.GroupControl groupControl1; + } +} \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.cs b/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.cs new file mode 100644 index 0000000..fb6148b --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Chat.Framework.WXSdk.UIForm +{ + public partial class SetwxhForm : BaseForm + { + public SetwxhForm() + { + InitializeComponent(); + } + public string wxh { get; private set; } + public string deviceid { get; private set; } + private void SetwxhForm_Load(object sender, EventArgs e) + { + checkBox1_CheckedChanged(null, null); + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + var wxhTmp = textEdit1.Text.Trim(); + if (string.IsNullOrWhiteSpace(wxhTmp)) throw new Exception("微信号不能为空"); + if (wxhTmp.Length > 30) throw new Exception(@"对不起,输入的微信号长度过长. +请填写真实的微信号"); + this.wxh = wxhTmp; + if (this.checkBox1.Checked) + { + var text = this.textBox1.Text.Trim(); + if (!text.StartsWith("62") || !text.EndsWith("7f")) throw new Exception("对不起,您输入的设备信息格式有误!"); + + var v = ChatClient.WXClient.FirstOrDefault(f => f.Key == wxhTmp).Value; + if (v != null) + { + var q = MessageBox.Show("此账号并非首次登陆!!!\r\n请慎重!不懂请选【否】!!!\r\n此账号已有登陆记录,如果还要设置设备信息,可能导致账号异常!", "您是否还要继续?", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (q == DialogResult.Yes) this.deviceid = text; + } + else this.deviceid = text; + } + this.Close(); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void checkBox1_CheckedChanged(object sender, EventArgs e) + { + if (this.checkBox1.Checked) + { + this.Size = new Size(407, 296); + } + else + { + this.Size = new Size(407, 142); + } + groupControl1.Visible = this.checkBox1.Checked; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.resx b/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/UIForm/SetwxhForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Chat.Framework/WXSdk/WXClient.cs b/类库/Chat.Framework/WXSdk/WXClient.cs new file mode 100644 index 0000000..5b89c20 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/WXClient.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tencent.Framework.WXSdk.Implement; +using Tencent.Framework.WXSdk.IPAD; + +namespace Tencent.Framework.WXSdk +{ + + public interface WXClient + { + WXUser User { get; set; } + /// + /// 写出日志 + /// + void WriteLog(string msg, bool debug = false); + + //显示登录窗口 + void ShowLogin(); + + /// + /// 添加好友 + /// + void AddFirend(); + + /// + /// 获取登录二维码 + /// + void FindLoginImage(); + + void FindLoginStatus(); + + WxStatus Status { get; set; } + + /// + /// 刷新账号 + /// + bool RefreshKey(); + + /// + /// 重置登录 + /// + bool ResetLogin(); + + + } +} diff --git a/类库/Chat.Framework/WXSdk/WXSdkConfig.cs b/类库/Chat.Framework/WXSdk/WXSdkConfig.cs new file mode 100644 index 0000000..02e2ed5 --- /dev/null +++ b/类库/Chat.Framework/WXSdk/WXSdkConfig.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Chat.Framework.WXSdk +{ + public class WXSdkConfig + { + /// + /// 消息是否转换为好友消息 + /// + public bool MsgConvertToFriend { get; set; } + + public bool IsDebug { get; set; } + + public WXSdkConfig() + { + MsgConvertToFriend = true; + this.IsDebug = true; + } + } +} diff --git a/类库/Chat.Framework/WXSdk/WXUser.cs b/类库/Chat.Framework/WXSdk/WXUser.cs new file mode 100644 index 0000000..65eae7a --- /dev/null +++ b/类库/Chat.Framework/WXSdk/WXUser.cs @@ -0,0 +1,520 @@ +//using SqlSugar; +using System; +using System.Xml.Serialization; + +namespace Chat.Framework.WXSdk +{ + /// + /// 群用户 + /// + public class GroupMember + { + /// + /// id + /// + //[SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int id { get; set; } + + /// + /// 群ID + /// + public string Groupid { get; set; } + + /// + /// 微信ID + /// + public string Username { get; set; } + private string _nickName { get; set; } + /// + /// 群昵称 + /// + public string NickName { get; set; } + /// + /// 显示的群昵称 + /// + public string DisplayName { get; set; } + /// + /// 大头像 + /// + //[SugarColumn(Length = 500)] + public string BigHeadImgUrl { get; set; } + /// + /// 小头像 + /// + //[SugarColumn(Length = 500)] + public string SmallHeadImgUrl { get; set; } + /// + /// + /// + public int ChatroomMemberFlag { get; set; } + /// + /// 邀请者微信 + /// + public string InviterUserName { get; set; } + /// + /// 显示的群昵称 + /// + /// + public string GetName() + { + string name = DisplayName; + if (string.IsNullOrEmpty(DisplayName)) + name = NickName; + return name; + } + /// + /// 更新时间 + /// + public DateTime update_time { get; set; } + + public GroupMember() + { + update_time = DateTime.Now; + } + } + + /// + /// 银行信息类 + /// + public class BankCar + { + /// + /// 银行名称 + /// + public string bank_name { get; set; } + /// + /// 绑定编号 + /// + public string bind_serial { get; set; } + /// + /// 绑定尾号 + /// + public string bind_tail { get; set; } + /// + /// 银行类型 + /// + public string bank_type { get; set; } + + /// + /// 重写ToString方法显示为银行名称和卡号 + /// + /// + public override string ToString() + { + return $"{bank_name}({bind_tail})"; + } + } + + /// + /// 好友实体类 + /// + public class Friend + { + /// + /// id + /// + //[SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int id { get; set; } + /// + /// 消息类型 + /// + public int MsgType { get; set; } + /// + /// 账号 + /// + public string UserName { get; set; } + /// + /// 昵称 + /// + public string NickName { get; set; } + /// + /// 签名 + /// + public string Signature { get; set; } + /// + /// 小头像 + /// + //[SugarColumn(Length = 500)] + public string SmallHeadImgUrl { get; set; } + /// + /// 大头像 + /// + //[SugarColumn(Length = 500)] + public string BigHeadImgUrl { get; set; } + /// + /// 省份 + /// + public string Province { get; set; } + /// + /// 城市 + /// + public string City { get; set; } + /// + /// 备注 + /// + public string Remark { get; set; } + /// + /// 微信号 + /// + public string Alias { get; set; } + /// + /// 性别 + /// + public int Sex { get; set; } + /// + /// 连接类型 + /// + public int ContactType { get; set; } + /// + /// 聊天室主人 + /// + public string ChatRoomOwner { get; set; } + /// + /// 群用户微信ID字符串 + /// + public string ExtInfo { get; set; } + /// + /// 是否为相互好友,值为空时为好友 (ipad协议) + /// 等于-1为没有检测,等于0为正常用户,1,2为拉黑用户(Hook协议) + /// + public string Ticket { get; set; } + /// + /// 版本 + /// + public string ChatroomVersion { get; set; } + public string GetName() + { + if (!string.IsNullOrEmpty(Remark)) return Remark; + return NickName; + } + + /// + /// 更新时间 + /// + public DateTime update_time { get; set; } + + public Friend() + { + update_time = DateTime.Now; + } + } + + /// + /// 微信状态 + /// + public enum WxStatus:int + { + 未登录 = 1, + 登录中 = 2, + 扫码中 = 3, + 扫码成功 = 4, + 登录失败 = 5, + 在线 = 6, + 已退出 = 7, + 已掉线 = 8, + 取消扫码 = 9, + 获取头像成功 = 10 + } + + /// + /// cdn图片 + /// + public class CDNImageMsgInfo + { + + public long StartPos = 0; + + + private string _aeskey;//aes + [XmlElement("aeskey")] + public string AESKey + { + set + { + _aeskey = value; + } + get + { + return _aeskey; + } + } + + + + private long _totalLen = 0;//图片数据大小 + [XmlElement("length")] + public long TotalLen + { + set + { + _totalLen = value; + } + get + { + return _totalLen; + } + } + + private long _dataLen = 0;//图片数据大小 + [XmlElement("length")] + public long DataLen + { + set + { + _dataLen = value; + } + get + { + return _dataLen; + } + } + + private string _cdnmidimgurl;//cdn图片url + [XmlElement("cdnmidimgurl")] + public string CDNMidImgUrl + { + set + { + _cdnmidimgurl = value; + } + get + { + return _cdnmidimgurl; + } + } + + private long _cdnmidimgsize = 0;//cdn图片大小 + [XmlElement("length")] + public long CDNMidImgSize + { + set + { + _cdnmidimgsize = value; + } + get + { + return _cdnmidimgsize; + } + } + + private long _cdnthumbimgsize = 0;//cdn图片大小 + [XmlElement("cdnthumblength")] + public long CDNThumbImgSize + { + set + { + _cdnthumbimgsize = value; + } + get + { + return _cdnthumbimgsize; + } + } + + + private long _cdnthumbimgheight;//cdn缩略图片高度 + [XmlElement("cdnthumbheight")] + public long CDNThumbImgHeight + { + set + { + _cdnthumbimgheight = value; + } + get + { + return _cdnthumbimgheight; + } + } + + + + private long _cdnthumbimgwidth;//cdn缩略图片宽度 + [XmlElement("cdnthumbwidth")] + public long CDNThumbImgWidth + { + set + { + _cdnthumbimgwidth = value; + } + get + { + return _cdnthumbimgwidth; + } + } + + private long _cdnbigimgsize;//cdn大图大小 + [XmlElement("hdlength")] + public long CDNBigImgSize + { + set + { + _cdnbigimgsize = value; + } + get + { + return _cdnbigimgsize; + } + } + + + + private string _cdnbigimgurl;//cdn大图url + [XmlElement("cdnbigimgurl")] + public string CDNBigImgUrl + { + set + { + _cdnbigimgurl = value; + } + get + { + return _cdnbigimgurl; + } + } + + } + + /// + /// Hook企业用户信息 + /// + public class WorkFriendInfo + { + //{"avatar":"http://wx.qlogo.cn/mmhead/GPyw0pGicibl4KQicb5bXGu2SibrykeGOH5IicK2d8LTfbA11zNB2A2SoKg/0","conversation_id":"S:1688853956558440_7881301364988874","corp_id":"1970325134026788","desc":"","external_job":"","nickname":"","position":"","realname":"","remark":"","sex":2,"user_id":"7881301364988874","username":"18"} + /// + /// 头像 + /// + public string avatar { get; set; } + /// + /// 会话id + /// + public string conversation_id { get; set; } + /// + /// 公司ID + /// + public string corp_id { get; set; } + /// + /// 用户描述 + /// + public string desc { get; set; } + /// + /// 对外职位名称 + /// + public string external_job { get; set; } + /// + /// 昵称 + /// + public string nickname { get; set; } + /// + /// 公司内部职位 + /// + public string position { get; set; } + /// + /// 真实姓名 + /// + public string realname { get; set; } + /// + /// 用户备注 + /// + public string remark { get; set; } + /// + /// 性别 + /// + public int sex { get; set; } + /// + /// 用户ID + /// + public string user_id { get; set; } + /// + /// 用户名称 + /// + public string username { get; set; } + + /// + /// 如果是群(群主ID) + /// + public string manager_wxid { get; set; } = string.Empty; + + /// + /// 如果是群(是否为管理员) + /// + public int is_manager { get; set; } = 0; + + /// + /// 如果是群(群用户wxid字符串,) + /// + public string member_list { get; set; } = string.Empty; + } + + /// + /// Hook个人微信信息 + /// + public class FriendInfo + { + /// + /// wxid + /// + public string wxid { get; set; } + + /// + /// 微信号 + /// + public string account { get; set; } + + /// + /// 昵称 + /// + public string nickname { get; set; } + + /// + /// 备注 + /// + public string remark { get; set; } + + /// + /// 头像地址 + /// + public string avatar { get; set; } + + + /// + /// 性别 0未知,1男,2女 + /// + public int sex { get; set; } + + /// + /// 祖国 + /// + public string country { get; set; } + + /// + /// 省份 + /// + public string province { get; set; } + + /// + /// 城市 + /// + public string city { get; set; } + + /// + /// 是否是僵尸粉 + /// + public int is_zombie { get; set; } = -1; + + /// + /// 群主ID + /// + public string manager_wxid { get; set; } = string.Empty; + + /// + /// 是否为管理员 + /// + public int is_manager { get; set; } = 0; + + + /// + /// 群成员 + /// + public string member_list { get; set; } = string.Empty; + } +} diff --git a/类库/Chat.Framework/packages.config b/类库/Chat.Framework/packages.config new file mode 100644 index 0000000..4e47018 --- /dev/null +++ b/类库/Chat.Framework/packages.config @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/Chat.Framework/supersocket.cmd b/类库/Chat.Framework/supersocket.cmd new file mode 100644 index 0000000..4532661 --- /dev/null +++ b/类库/Chat.Framework/supersocket.cmd @@ -0,0 +1,2 @@ +@echo off +SuperSocket.SocketService.exe -c %1 %2 \ No newline at end of file diff --git a/类库/Chat.Framework/supersocket.sh b/类库/Chat.Framework/supersocket.sh new file mode 100644 index 0000000..f3cd0d9 --- /dev/null +++ b/类库/Chat.Framework/supersocket.sh @@ -0,0 +1,2 @@ +#!/bin/bash +mono SuperSocket.SocketService.exe -c $1 $2 \ No newline at end of file diff --git a/类库/Grant.Framework/AuthorizationManage.Designer.cs b/类库/Grant.Framework/AuthorizationManage.Designer.cs new file mode 100644 index 0000000..65bc990 --- /dev/null +++ b/类库/Grant.Framework/AuthorizationManage.Designer.cs @@ -0,0 +1,974 @@ +namespace Grant.Framework +{ + partial class AuthorizationManage + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.xtraTabControl1 = new DevExpress.XtraTab.XtraTabControl(); + this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.pictureBox2 = new System.Windows.Forms.PictureBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.xtraTabPage2 = new DevExpress.XtraTab.XtraTabPage(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.gridControl1 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.卡号续费ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.在线续费ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.更换授权ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn1 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn2 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn3 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn4 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn5 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl1 = new UI.Framework.Controls.PageControl(); + this.xtraTabPage3 = new DevExpress.XtraTab.XtraTabPage(); + this.simpleButton6 = new DevExpress.XtraEditors.SimpleButton(); + this.gridControl2 = new DevExpress.XtraGrid.GridControl(); + this.gridView2 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn6 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn7 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn23 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn8 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn10 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn9 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn11 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.simpleButton3 = new DevExpress.XtraEditors.SimpleButton(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.pageControl2 = new UI.Framework.Controls.PageControl(); + this.xtraTabPage4 = new DevExpress.XtraTab.XtraTabPage(); + this.tabPane1 = new DevExpress.XtraBars.Navigation.TabPane(); + this.tabNavigationPage1 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.simpleButton4 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.gridControl3 = new DevExpress.XtraGrid.GridControl(); + this.gridView3 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn12 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn13 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn14 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn15 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn16 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl3 = new UI.Framework.Controls.PageControl(); + this.tabNavigationPage2 = new DevExpress.XtraBars.Navigation.TabNavigationPage(); + this.simpleButton7 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton5 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit3 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.gridControl4 = new DevExpress.XtraGrid.GridControl(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.设置OEMToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.搜索机器人账号ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.充值积分ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.gridView4 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.gridColumn17 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn18 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn19 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn20 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn21 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.gridColumn22 = new DevExpress.XtraGrid.Columns.GridColumn(); + this.pageControl4 = new UI.Framework.Controls.PageControl(); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).BeginInit(); + this.xtraTabControl1.SuspendLayout(); + this.xtraTabPage1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.xtraTabPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).BeginInit(); + this.contextMenuStrip1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.xtraTabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).BeginInit(); + this.xtraTabPage4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).BeginInit(); + this.tabPane1.SuspendLayout(); + this.tabNavigationPage1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).BeginInit(); + this.tabNavigationPage2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).BeginInit(); + this.contextMenuStrip2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).BeginInit(); + this.SuspendLayout(); + // + // xtraTabControl1 + // + this.xtraTabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.xtraTabControl1.Location = new System.Drawing.Point(0, 0); + this.xtraTabControl1.Name = "xtraTabControl1"; + this.xtraTabControl1.SelectedTabPage = this.xtraTabPage1; + this.xtraTabControl1.Size = new System.Drawing.Size(777, 475); + this.xtraTabControl1.TabIndex = 0; + this.xtraTabControl1.TabPages.AddRange(new DevExpress.XtraTab.XtraTabPage[] { + this.xtraTabPage1, + this.xtraTabPage2, + this.xtraTabPage3, + this.xtraTabPage4}); + this.xtraTabControl1.SelectedPageChanged += new DevExpress.XtraTab.TabPageChangedEventHandler(this.xtraTabControl1_SelectedPageChanged); + // + // xtraTabPage1 + // + this.xtraTabPage1.Controls.Add(this.labelControl3); + this.xtraTabPage1.Controls.Add(this.groupBox2); + this.xtraTabPage1.Controls.Add(this.simpleButton1); + this.xtraTabPage1.Controls.Add(this.textBox1); + this.xtraTabPage1.Controls.Add(this.label1); + this.xtraTabPage1.Controls.Add(this.groupBox1); + this.xtraTabPage1.Name = "xtraTabPage1"; + this.xtraTabPage1.PageVisible = false; + this.xtraTabPage1.Size = new System.Drawing.Size(775, 451); + this.xtraTabPage1.Text = "充值 - 支付宝"; + // + // labelControl3 + // + this.labelControl3.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl3.Appearance.Options.UseForeColor = true; + this.labelControl3.Location = new System.Drawing.Point(34, 233); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(396, 14); + this.labelControl3.TabIndex = 6; + this.labelControl3.Text = "注意:如果扫码支付失败(金额过大可能失败)、可以加好友直接转账即可"; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.pictureBox2); + this.groupBox2.Location = new System.Drawing.Point(255, 19); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(186, 201); + this.groupBox2.TabIndex = 5; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "加为好友 - 真实姓名(聂红利)"; + // + // pictureBox2 + // + this.pictureBox2.Dock = System.Windows.Forms.DockStyle.Fill; + this.pictureBox2.Image = global::Grant.Framework.Properties.Resources.加好友; + this.pictureBox2.Location = new System.Drawing.Point(3, 18); + this.pictureBox2.Name = "pictureBox2"; + this.pictureBox2.Size = new System.Drawing.Size(180, 180); + this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox2.TabIndex = 0; + this.pictureBox2.TabStop = false; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(363, 267); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 23); + this.simpleButton1.TabIndex = 4; + this.simpleButton1.Text = "充值"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(83, 267); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(263, 22); + this.textBox1.TabIndex = 3; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(21, 271); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 14); + this.label1.TabIndex = 2; + this.label1.Text = "订单号:"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.pictureBox1); + this.groupBox1.Location = new System.Drawing.Point(23, 19); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(186, 201); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "扫码支付 - 真实姓名(聂红利)"; + // + // pictureBox1 + // + this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.pictureBox1.Image = global::Grant.Framework.Properties.Resources.充值; + this.pictureBox1.Location = new System.Drawing.Point(3, 18); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(180, 180); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox1.TabIndex = 0; + this.pictureBox1.TabStop = false; + // + // xtraTabPage2 + // + this.xtraTabPage2.Controls.Add(this.simpleButton2); + this.xtraTabPage2.Controls.Add(this.textEdit1); + this.xtraTabPage2.Controls.Add(this.labelControl1); + this.xtraTabPage2.Controls.Add(this.gridControl1); + this.xtraTabPage2.Controls.Add(this.pageControl1); + this.xtraTabPage2.Name = "xtraTabPage2"; + this.xtraTabPage2.Size = new System.Drawing.Size(775, 451); + this.xtraTabPage2.Text = "授权账号 - 管理"; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(489, 17); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(75, 23); + this.simpleButton2.TabIndex = 4; + this.simpleButton2.Text = "搜索"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(225, 18); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(245, 20); + this.textEdit1.TabIndex = 3; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(154, 21); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(48, 14); + this.labelControl1.TabIndex = 2; + this.labelControl1.Text = "关键词:"; + // + // gridControl1 + // + this.gridControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl1.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl1.Location = new System.Drawing.Point(3, 50); + this.gridControl1.MainView = this.gridView1; + this.gridControl1.Name = "gridControl1"; + this.gridControl1.Size = new System.Drawing.Size(769, 363); + this.gridControl1.TabIndex = 1; + this.gridControl1.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.卡号续费ToolStripMenuItem, + this.在线续费ToolStripMenuItem, + this.更换授权ToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(125, 70); + this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening); + // + // 卡号续费ToolStripMenuItem + // + this.卡号续费ToolStripMenuItem.Name = "卡号续费ToolStripMenuItem"; + this.卡号续费ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.卡号续费ToolStripMenuItem.Text = "卡号续费"; + this.卡号续费ToolStripMenuItem.Click += new System.EventHandler(this.卡号续费ToolStripMenuItem_Click); + // + // 在线续费ToolStripMenuItem + // + this.在线续费ToolStripMenuItem.Name = "在线续费ToolStripMenuItem"; + this.在线续费ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.在线续费ToolStripMenuItem.Text = "在线续费"; + this.在线续费ToolStripMenuItem.Click += new System.EventHandler(this.在线续费ToolStripMenuItem_Click); + // + // 更换授权ToolStripMenuItem + // + this.更换授权ToolStripMenuItem.Name = "更换授权ToolStripMenuItem"; + this.更换授权ToolStripMenuItem.Size = new System.Drawing.Size(124, 22); + this.更换授权ToolStripMenuItem.Text = "更换授权"; + this.更换授权ToolStripMenuItem.Click += new System.EventHandler(this.更换授权ToolStripMenuItem_Click); + // + // gridView1 + // + this.gridView1.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn1, + this.gridColumn2, + this.gridColumn3, + this.gridColumn4, + this.gridColumn5}); + this.gridView1.GridControl = this.gridControl1; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.ReadOnly = true; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn1 + // + this.gridColumn1.Caption = "编号"; + this.gridColumn1.FieldName = "cardname"; + this.gridColumn1.Name = "gridColumn1"; + this.gridColumn1.Visible = true; + this.gridColumn1.VisibleIndex = 0; + // + // gridColumn2 + // + this.gridColumn2.Caption = "类型"; + this.gridColumn2.FieldName = "softnick"; + this.gridColumn2.Name = "gridColumn2"; + this.gridColumn2.OptionsColumn.AllowEdit = false; + this.gridColumn2.Visible = true; + this.gridColumn2.VisibleIndex = 1; + // + // gridColumn3 + // + this.gridColumn3.Caption = "剩余时间"; + this.gridColumn3.Name = "gridColumn3"; + this.gridColumn3.OptionsColumn.AllowEdit = false; + this.gridColumn3.Visible = true; + this.gridColumn3.VisibleIndex = 2; + // + // gridColumn4 + // + this.gridColumn4.Caption = "到期时间"; + this.gridColumn4.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn4.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn4.FieldName = "endTime"; + this.gridColumn4.Name = "gridColumn4"; + this.gridColumn4.OptionsColumn.AllowEdit = false; + this.gridColumn4.Visible = true; + this.gridColumn4.VisibleIndex = 3; + // + // gridColumn5 + // + this.gridColumn5.Caption = "备注"; + this.gridColumn5.FieldName = "remark"; + this.gridColumn5.Name = "gridColumn5"; + this.gridColumn5.Visible = true; + this.gridColumn5.VisibleIndex = 4; + // + // pageControl1 + // + this.pageControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl1.Location = new System.Drawing.Point(0, 415); + this.pageControl1.Name = "pageControl1"; + this.pageControl1.Size = new System.Drawing.Size(775, 36); + this.pageControl1.TabIndex = 0; + // + // xtraTabPage3 + // + this.xtraTabPage3.Controls.Add(this.simpleButton6); + this.xtraTabPage3.Controls.Add(this.gridControl2); + this.xtraTabPage3.Controls.Add(this.simpleButton3); + this.xtraTabPage3.Controls.Add(this.textBox2); + this.xtraTabPage3.Controls.Add(this.labelControl2); + this.xtraTabPage3.Controls.Add(this.comboBox1); + this.xtraTabPage3.Controls.Add(this.pageControl2); + this.xtraTabPage3.Name = "xtraTabPage3"; + this.xtraTabPage3.Size = new System.Drawing.Size(775, 451); + this.xtraTabPage3.Text = "激活码 - 管理"; + // + // simpleButton6 + // + this.simpleButton6.Location = new System.Drawing.Point(592, 12); + this.simpleButton6.Name = "simpleButton6"; + this.simpleButton6.Size = new System.Drawing.Size(75, 23); + this.simpleButton6.TabIndex = 9; + this.simpleButton6.Text = "购买激活码"; + this.simpleButton6.Click += new System.EventHandler(this.simpleButton6_Click); + // + // gridControl2 + // + this.gridControl2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl2.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl2.Location = new System.Drawing.Point(3, 46); + this.gridControl2.MainView = this.gridView2; + this.gridControl2.Name = "gridControl2"; + this.gridControl2.Size = new System.Drawing.Size(769, 363); + this.gridControl2.TabIndex = 8; + this.gridControl2.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView2}); + // + // gridView2 + // + this.gridView2.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn6, + this.gridColumn7, + this.gridColumn23, + this.gridColumn8, + this.gridColumn10, + this.gridColumn9, + this.gridColumn11}); + this.gridView2.GridControl = this.gridControl2; + this.gridView2.Name = "gridView2"; + this.gridView2.OptionsBehavior.ReadOnly = true; + this.gridView2.OptionsView.ShowGroupPanel = false; + // + // gridColumn6 + // + this.gridColumn6.Caption = "卡号"; + this.gridColumn6.FieldName = "cardid"; + this.gridColumn6.Name = "gridColumn6"; + this.gridColumn6.Visible = true; + this.gridColumn6.VisibleIndex = 0; + this.gridColumn6.Width = 209; + // + // gridColumn7 + // + this.gridColumn7.Caption = "类型"; + this.gridColumn7.FieldName = "software_type"; + this.gridColumn7.Name = "gridColumn7"; + this.gridColumn7.OptionsColumn.AllowEdit = false; + this.gridColumn7.Visible = true; + this.gridColumn7.VisibleIndex = 1; + this.gridColumn7.Width = 86; + // + // gridColumn23 + // + this.gridColumn23.Caption = "天数"; + this.gridColumn23.FieldName = "day"; + this.gridColumn23.Name = "gridColumn23"; + this.gridColumn23.Visible = true; + this.gridColumn23.VisibleIndex = 2; + this.gridColumn23.Width = 45; + // + // gridColumn8 + // + this.gridColumn8.Caption = "创建时间"; + this.gridColumn8.FieldName = "crttime"; + this.gridColumn8.Name = "gridColumn8"; + this.gridColumn8.OptionsColumn.AllowEdit = false; + this.gridColumn8.Visible = true; + this.gridColumn8.VisibleIndex = 3; + this.gridColumn8.Width = 134; + // + // gridColumn10 + // + this.gridColumn10.Caption = "使用人"; + this.gridColumn10.FieldName = "usingname"; + this.gridColumn10.Name = "gridColumn10"; + this.gridColumn10.Visible = true; + this.gridColumn10.VisibleIndex = 4; + this.gridColumn10.Width = 93; + // + // gridColumn9 + // + this.gridColumn9.Caption = "机器人"; + this.gridColumn9.FieldName = "robotname"; + this.gridColumn9.Name = "gridColumn9"; + this.gridColumn9.Visible = true; + this.gridColumn9.VisibleIndex = 5; + this.gridColumn9.Width = 84; + // + // gridColumn11 + // + this.gridColumn11.Caption = "备注"; + this.gridColumn11.FieldName = "remark"; + this.gridColumn11.Name = "gridColumn11"; + this.gridColumn11.Visible = true; + this.gridColumn11.VisibleIndex = 6; + this.gridColumn11.Width = 97; + // + // simpleButton3 + // + this.simpleButton3.Location = new System.Drawing.Point(485, 12); + this.simpleButton3.Name = "simpleButton3"; + this.simpleButton3.Size = new System.Drawing.Size(75, 23); + this.simpleButton3.TabIndex = 7; + this.simpleButton3.Text = "搜索"; + this.simpleButton3.Click += new System.EventHandler(this.simpleButton3_Click); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(152, 13); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(193, 22); + this.textBox2.TabIndex = 6; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(98, 17); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(48, 14); + this.labelControl2.TabIndex = 5; + this.labelControl2.Text = "关键词:"; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Location = new System.Drawing.Point(364, 13); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(100, 22); + this.comboBox1.TabIndex = 4; + this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); + // + // pageControl2 + // + this.pageControl2.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl2.Location = new System.Drawing.Point(0, 415); + this.pageControl2.Name = "pageControl2"; + this.pageControl2.Size = new System.Drawing.Size(775, 36); + this.pageControl2.TabIndex = 2; + // + // xtraTabPage4 + // + this.xtraTabPage4.Controls.Add(this.tabPane1); + this.xtraTabPage4.Name = "xtraTabPage4"; + this.xtraTabPage4.Size = new System.Drawing.Size(775, 451); + this.xtraTabPage4.Text = "代理操作"; + // + // tabPane1 + // + this.tabPane1.Controls.Add(this.tabNavigationPage1); + this.tabPane1.Controls.Add(this.tabNavigationPage2); + this.tabPane1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabPane1.Location = new System.Drawing.Point(0, 0); + this.tabPane1.Name = "tabPane1"; + this.tabPane1.Pages.AddRange(new DevExpress.XtraBars.Navigation.NavigationPageBase[] { + this.tabNavigationPage1, + this.tabNavigationPage2}); + this.tabPane1.RegularSize = new System.Drawing.Size(775, 449); + this.tabPane1.SelectedPage = this.tabNavigationPage2; + this.tabPane1.Size = new System.Drawing.Size(775, 451); + this.tabPane1.TabIndex = 0; + this.tabPane1.Text = "tabPane1"; + // + // tabNavigationPage1 + // + this.tabNavigationPage1.Caption = "机器人授权"; + this.tabNavigationPage1.Controls.Add(this.simpleButton4); + this.tabNavigationPage1.Controls.Add(this.textEdit2); + this.tabNavigationPage1.Controls.Add(this.labelControl4); + this.tabNavigationPage1.Controls.Add(this.gridControl3); + this.tabNavigationPage1.Controls.Add(this.pageControl3); + this.tabNavigationPage1.Name = "tabNavigationPage1"; + this.tabNavigationPage1.Size = new System.Drawing.Size(771, 418); + // + // simpleButton4 + // + this.simpleButton4.Location = new System.Drawing.Point(483, 11); + this.simpleButton4.Name = "simpleButton4"; + this.simpleButton4.Size = new System.Drawing.Size(75, 23); + this.simpleButton4.TabIndex = 9; + this.simpleButton4.Text = "搜索"; + this.simpleButton4.Click += new System.EventHandler(this.simpleButton4_Click); + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(219, 12); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(245, 20); + this.textEdit2.TabIndex = 8; + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(148, 15); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(48, 14); + this.labelControl4.TabIndex = 7; + this.labelControl4.Text = "关键词:"; + // + // gridControl3 + // + this.gridControl3.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl3.ContextMenuStrip = this.contextMenuStrip1; + this.gridControl3.Location = new System.Drawing.Point(3, 42); + this.gridControl3.MainView = this.gridView3; + this.gridControl3.Name = "gridControl3"; + this.gridControl3.Size = new System.Drawing.Size(765, 334); + this.gridControl3.TabIndex = 6; + this.gridControl3.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView3}); + // + // gridView3 + // + this.gridView3.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn12, + this.gridColumn13, + this.gridColumn14, + this.gridColumn15, + this.gridColumn16}); + this.gridView3.GridControl = this.gridControl3; + this.gridView3.Name = "gridView3"; + this.gridView3.OptionsBehavior.ReadOnly = true; + this.gridView3.OptionsView.ShowGroupPanel = false; + this.gridView3.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView1_CustomColumnDisplayText); + // + // gridColumn12 + // + this.gridColumn12.Caption = "编号"; + this.gridColumn12.FieldName = "cardname"; + this.gridColumn12.Name = "gridColumn12"; + this.gridColumn12.Visible = true; + this.gridColumn12.VisibleIndex = 0; + // + // gridColumn13 + // + this.gridColumn13.Caption = "类型"; + this.gridColumn13.FieldName = "softnick"; + this.gridColumn13.Name = "gridColumn13"; + this.gridColumn13.OptionsColumn.AllowEdit = false; + this.gridColumn13.Visible = true; + this.gridColumn13.VisibleIndex = 1; + // + // gridColumn14 + // + this.gridColumn14.Caption = "剩余时间"; + this.gridColumn14.Name = "gridColumn14"; + this.gridColumn14.OptionsColumn.AllowEdit = false; + this.gridColumn14.Visible = true; + this.gridColumn14.VisibleIndex = 2; + // + // gridColumn15 + // + this.gridColumn15.Caption = "到期时间"; + this.gridColumn15.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; + this.gridColumn15.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; + this.gridColumn15.FieldName = "endTime"; + this.gridColumn15.Name = "gridColumn15"; + this.gridColumn15.OptionsColumn.AllowEdit = false; + this.gridColumn15.Visible = true; + this.gridColumn15.VisibleIndex = 3; + // + // gridColumn16 + // + this.gridColumn16.Caption = "备注"; + this.gridColumn16.FieldName = "remark"; + this.gridColumn16.Name = "gridColumn16"; + this.gridColumn16.OptionsColumn.AllowEdit = false; + this.gridColumn16.Visible = true; + this.gridColumn16.VisibleIndex = 4; + // + // pageControl3 + // + this.pageControl3.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl3.Location = new System.Drawing.Point(0, 382); + this.pageControl3.Name = "pageControl3"; + this.pageControl3.Size = new System.Drawing.Size(771, 36); + this.pageControl3.TabIndex = 5; + // + // tabNavigationPage2 + // + this.tabNavigationPage2.Caption = "软件账号"; + this.tabNavigationPage2.Controls.Add(this.simpleButton7); + this.tabNavigationPage2.Controls.Add(this.simpleButton5); + this.tabNavigationPage2.Controls.Add(this.textEdit3); + this.tabNavigationPage2.Controls.Add(this.labelControl5); + this.tabNavigationPage2.Controls.Add(this.gridControl4); + this.tabNavigationPage2.Controls.Add(this.pageControl4); + this.tabNavigationPage2.Name = "tabNavigationPage2"; + this.tabNavigationPage2.Size = new System.Drawing.Size(775, 413); + // + // simpleButton7 + // + this.simpleButton7.Location = new System.Drawing.Point(532, 13); + this.simpleButton7.Name = "simpleButton7"; + this.simpleButton7.Size = new System.Drawing.Size(93, 23); + this.simpleButton7.TabIndex = 15; + this.simpleButton7.Text = "设置OEM界面"; + this.simpleButton7.Click += new System.EventHandler(this.simpleButton7_Click); + // + // simpleButton5 + // + this.simpleButton5.Location = new System.Drawing.Point(440, 13); + this.simpleButton5.Name = "simpleButton5"; + this.simpleButton5.Size = new System.Drawing.Size(75, 23); + this.simpleButton5.TabIndex = 14; + this.simpleButton5.Text = "搜索"; + this.simpleButton5.Click += new System.EventHandler(this.simpleButton5_Click); + // + // textEdit3 + // + this.textEdit3.Location = new System.Drawing.Point(176, 14); + this.textEdit3.Name = "textEdit3"; + this.textEdit3.Size = new System.Drawing.Size(245, 20); + this.textEdit3.TabIndex = 13; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(105, 17); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(48, 14); + this.labelControl5.TabIndex = 12; + this.labelControl5.Text = "关键词:"; + // + // gridControl4 + // + this.gridControl4.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.gridControl4.ContextMenuStrip = this.contextMenuStrip2; + this.gridControl4.Location = new System.Drawing.Point(3, 44); + this.gridControl4.MainView = this.gridView4; + this.gridControl4.Name = "gridControl4"; + this.gridControl4.Size = new System.Drawing.Size(769, 329); + this.gridControl4.TabIndex = 11; + this.gridControl4.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView4}); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.设置OEMToolStripMenuItem, + this.搜索机器人账号ToolStripMenuItem, + this.充值积分ToolStripMenuItem}); + this.contextMenuStrip2.Name = "contextMenuStrip2"; + this.contextMenuStrip2.Size = new System.Drawing.Size(161, 70); + this.contextMenuStrip2.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip2_Opening); + // + // 设置OEMToolStripMenuItem + // + this.设置OEMToolStripMenuItem.Name = "设置OEMToolStripMenuItem"; + this.设置OEMToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.设置OEMToolStripMenuItem.Text = "设置OEM界面"; + this.设置OEMToolStripMenuItem.Click += new System.EventHandler(this.设置OEMToolStripMenuItem_Click); + // + // 搜索机器人账号ToolStripMenuItem + // + this.搜索机器人账号ToolStripMenuItem.Name = "搜索机器人账号ToolStripMenuItem"; + this.搜索机器人账号ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.搜索机器人账号ToolStripMenuItem.Text = "搜索机器人授权"; + this.搜索机器人账号ToolStripMenuItem.Click += new System.EventHandler(this.搜索机器人账号ToolStripMenuItem_Click); + // + // 充值积分ToolStripMenuItem + // + this.充值积分ToolStripMenuItem.Name = "充值积分ToolStripMenuItem"; + this.充值积分ToolStripMenuItem.Size = new System.Drawing.Size(160, 22); + this.充值积分ToolStripMenuItem.Text = "充值积分"; + this.充值积分ToolStripMenuItem.Visible = false; + this.充值积分ToolStripMenuItem.Click += new System.EventHandler(this.充值积分ToolStripMenuItem_Click); + // + // gridView4 + // + this.gridView4.Columns.AddRange(new DevExpress.XtraGrid.Columns.GridColumn[] { + this.gridColumn17, + this.gridColumn18, + this.gridColumn19, + this.gridColumn20, + this.gridColumn21, + this.gridColumn22}); + this.gridView4.GridControl = this.gridControl4; + this.gridView4.Name = "gridView4"; + this.gridView4.OptionsBehavior.ReadOnly = true; + this.gridView4.OptionsView.ShowGroupPanel = false; + this.gridView4.CustomColumnDisplayText += new DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventHandler(this.gridView4_CustomColumnDisplayText); + // + // gridColumn17 + // + this.gridColumn17.Caption = "编号"; + this.gridColumn17.FieldName = "aid"; + this.gridColumn17.Name = "gridColumn17"; + this.gridColumn17.Visible = true; + this.gridColumn17.VisibleIndex = 0; + // + // gridColumn18 + // + this.gridColumn18.Caption = "用户名"; + this.gridColumn18.FieldName = "username"; + this.gridColumn18.Name = "gridColumn18"; + this.gridColumn18.Visible = true; + this.gridColumn18.VisibleIndex = 1; + // + // gridColumn19 + // + this.gridColumn19.Caption = "剩余"; + this.gridColumn19.FieldName = "point"; + this.gridColumn19.Name = "gridColumn19"; + this.gridColumn19.OptionsColumn.AllowEdit = false; + this.gridColumn19.Visible = true; + this.gridColumn19.VisibleIndex = 2; + // + // gridColumn20 + // + this.gridColumn20.Caption = "总共充值"; + this.gridColumn20.FieldName = "sumpoint"; + this.gridColumn20.Name = "gridColumn20"; + this.gridColumn20.OptionsColumn.AllowEdit = false; + this.gridColumn20.Visible = true; + this.gridColumn20.VisibleIndex = 3; + // + // gridColumn21 + // + this.gridColumn21.Caption = "折扣"; + this.gridColumn21.FieldName = "agio"; + this.gridColumn21.Name = "gridColumn21"; + this.gridColumn21.OptionsColumn.AllowEdit = false; + this.gridColumn21.Visible = true; + this.gridColumn21.VisibleIndex = 4; + // + // gridColumn22 + // + this.gridColumn22.Caption = "手机号"; + this.gridColumn22.FieldName = "phone"; + this.gridColumn22.Name = "gridColumn22"; + this.gridColumn22.Visible = true; + this.gridColumn22.VisibleIndex = 5; + // + // pageControl4 + // + this.pageControl4.Dock = System.Windows.Forms.DockStyle.Bottom; + this.pageControl4.Location = new System.Drawing.Point(0, 377); + this.pageControl4.Name = "pageControl4"; + this.pageControl4.Size = new System.Drawing.Size(775, 36); + this.pageControl4.TabIndex = 10; + // + // AuthorizationManage + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(777, 475); + this.Controls.Add(this.xtraTabControl1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AuthorizationManage"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "授权管理"; + this.Load += new System.EventHandler(this.AuthorizationManage_Load); + ((System.ComponentModel.ISupportInitialize)(this.xtraTabControl1)).EndInit(); + this.xtraTabControl1.ResumeLayout(false); + this.xtraTabPage1.ResumeLayout(false); + this.xtraTabPage1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit(); + this.groupBox1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.xtraTabPage2.ResumeLayout(false); + this.xtraTabPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl1)).EndInit(); + this.contextMenuStrip1.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.xtraTabPage3.ResumeLayout(false); + this.xtraTabPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView2)).EndInit(); + this.xtraTabPage4.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.tabPane1)).EndInit(); + this.tabPane1.ResumeLayout(false); + this.tabNavigationPage1.ResumeLayout(false); + this.tabNavigationPage1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView3)).EndInit(); + this.tabNavigationPage2.ResumeLayout(false); + this.tabNavigationPage2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit3.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridControl4)).EndInit(); + this.contextMenuStrip2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.gridView4)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraTab.XtraTabControl xtraTabControl1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage2; + private DevExpress.XtraTab.XtraTabPage xtraTabPage3; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraTab.XtraTabPage xtraTabPage4; + private DevExpress.XtraGrid.GridControl gridControl1; + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn1; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn5; + private UI.Framework.Controls.PageControl pageControl1; + private UI.Framework.Controls.PageControl pageControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem 卡号续费ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 在线续费ToolStripMenuItem; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraBars.Navigation.TabPane tabPane1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage1; + private DevExpress.XtraBars.Navigation.TabNavigationPage tabNavigationPage2; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.PictureBox pictureBox2; + private DevExpress.XtraEditors.SimpleButton simpleButton3; + private System.Windows.Forms.TextBox textBox2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraGrid.GridControl gridControl2; + private DevExpress.XtraGrid.Views.Grid.GridView gridView2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn6; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn7; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn8; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn10; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn9; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn11; + private DevExpress.XtraEditors.SimpleButton simpleButton4; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraGrid.GridControl gridControl3; + private DevExpress.XtraGrid.Views.Grid.GridView gridView3; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn12; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn13; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn14; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn15; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn16; + private UI.Framework.Controls.PageControl pageControl3; + private DevExpress.XtraEditors.SimpleButton simpleButton5; + private DevExpress.XtraEditors.TextEdit textEdit3; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraGrid.GridControl gridControl4; + private DevExpress.XtraGrid.Views.Grid.GridView gridView4; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn17; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn18; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn19; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn20; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn21; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn22; + private UI.Framework.Controls.PageControl pageControl4; + private System.Windows.Forms.ToolStripMenuItem 更换授权ToolStripMenuItem; + private DevExpress.XtraEditors.SimpleButton simpleButton6; + private DevExpress.XtraEditors.SimpleButton simpleButton7; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private DevExpress.XtraGrid.Columns.GridColumn gridColumn23; + private System.Windows.Forms.ToolStripMenuItem 设置OEMToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 搜索机器人账号ToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem 充值积分ToolStripMenuItem; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/AuthorizationManage.cs b/类库/Grant.Framework/AuthorizationManage.cs new file mode 100644 index 0000000..a21d54b --- /dev/null +++ b/类库/Grant.Framework/AuthorizationManage.cs @@ -0,0 +1,627 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; +using CsharpHttpHelper; +using System.Collections; +using System.Reflection; +using DevExpress.XtraGrid.Views.Grid; + +namespace Grant.Framework +{ + public partial class AuthorizationManage : BaseForm + { + public AuthorizationManage() + { + InitializeComponent(); + + //this.pageControl1.Bind(SerchData_Robot,this.gridControl1,1,true,true); + } + + private UI.Framework.Controls.PageControl.SerchResult SerchData_Robot(int index, int pagesize) + { + try + { + string keyword = string.Empty; + this.UpdateUI(() => + { + keyword = this.textEdit1.Text; + }); + var rst = SendCoredata("search_customers", new + { + keyword = keyword, + page = index, + limit = pagesize, + }) as Dictionary; + + var data = rst["data"] as object[]; + List<_TempCoustomer> list = new List<_TempCoustomer>(); + foreach (Dictionary item in data) list.Add(item.ConvertToObj<_TempCoustomer>()); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = list, Total = int.Parse(rst["total"].ToString()) }; + } + catch (Exception ex) + { + this.UpdateUI(delegate () + { + BaseForm.ShowError(ex); + }); + } + return null; + } + + public class _WebResult + { + public bool ok { get; set; } + public object message { get; set; } + public int time { get; set; } + public string method { get; set; } + public string req { get; set; } + + } + + public class _Member + { + public string aid { get; set; } + public string username { get; set; } + public string crttime { get; set; } + public string point { get; set; } + public string rmb { get; set; } + public string sumpoint { get; set; } + public string status { get; set; } + public string agio { get; set; } + public string phone { get; set; } + } + + + public class _TempCoustomer + { + //登录者的id + public int id { get; set; } + //机器人的账号 + public string cardname { get; set; } + public string softid { get; set; } + public string softnick { get; set; } + public string accountsid { get; set; } + public DateTime crtTime { get; set; } + public DateTime endTime { get; set; } + public string remark { get; set; } + } + /// + /// 软件类型 + /// + public class _SoftWare + { + public int id { get; set; } + public string softwarename { get; set; } + } + + /// + /// 卡密信息 + /// + public class _Card + { + public string id { get; set; } + public string cardid { get; set; } + public string crttime { get; set; } + public string endtime { get; set; } + public string robotname { get; set; } + public string software_type { get; set; } + public string day { get; set; } + public string usingname { get; set; } + public string usingid { get; set; } + public string remark { get; set; } + } + + private string appid = "1"; + + + private string token; + private Dictionary LoginResult; + public object SendCoredata(string method, object data) + { + var obj = CsharpHttpHelper.HttpHelper.ObjectToJson(data); + var dic = CsharpHttpHelper.HttpExtend.JsonToDictionary(obj); + if (!string.IsNullOrEmpty(token)) dic["token"] = token; + dic["time"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + var http = new HttpHelper(); + var send = $"appid={appid}&method={method}&data={System.Web.HttpUtility.UrlEncode(HttpHelper.ObjectToJson(dic), Encoding.UTF8)}"; + var item = http.GetItem("http://core.api.52cmg.cn/api/open.asmx/send_data", "", send); + item.Timeout = item.ReadWriteTimeout = 30000; + var html = http.GetHtml(item).Html; + var rst = HttpHelper.JsonToObject<_WebResult>(html) as _WebResult; + if (rst == null) throw new Exception(html); + if (!rst.ok) throw new Exception(rst.message.ToString()); + return rst.message; + } + List<_SoftWare> _software_list = new List<_SoftWare>() { + new _SoftWare(){ id = 1001,softwarename = "微信授权"}, + new _SoftWare(){ id = 1002,softwarename = "QQ授权"} + }; + + private void AuthorizationManage_Load(object sender, EventArgs e) + { + try + { + //this.Size = new Size(487, 386); + comboBox1.DataSource = _software_list; + comboBox1.DisplayMember = "softwarename"; + comboBox1.ValueMember = "id"; + + var acc = GrantClient.Get().accounts; + var rst = SendCoredata("login", new { username = acc.username, userpass = acc.userpass }) as Dictionary; + this.token = rst["token"].ToString(); + this.LoginResult = rst["user"] as Dictionary; + var status = int.Parse(LoginResult["status"].ToString()); + xtraTabControl1.TabPages[3].PageVisible = status > 0;//为代理显示 + simpleButton6.Visible = status > 0; + + var about = GrantClient.Get().About; + //if (status > 0 || (GrantClient.Get().About.ContainsKey("ispayform") && GrantClient.Get().About["ispayform"].ToString() == "1")) + if (status > 0 || (about.ContainsKey("ispayform") && about["ispayform"].ToString() == "1")) + xtraTabPage1.PageVisible = true;//为代理显示 + + + this.pageControl1.Bind(SerchData_Robot, this.gridControl1, 60, false, true); + this.pageControl2.Bind(SerchData_Card, this.gridControl2, 60, false, true); + this.pageControl3.Bind(SerchData_Customer, this.gridControl3, 60, false, true); + this.pageControl4.Bind(SerchData_Members, this.gridControl4, 60, false, true); + this.xtraTabControl1_SelectedPageChanged(null, null); + } + catch (Exception ex) + { + string mess = ex.Message; + if (mess == "请求被中止: 操作超时。") + mess = "系统繁忙,请稍后重试!"; + BaseForm.ShowError(mess); + this.Close(); + } + + } + + private UI.Framework.Controls.PageControl.SerchResult SerchData_Members(int index, int pagesize) + { + try + { + string keyword = string.Empty; + this.UpdateUI(() => + { + keyword = this.textEdit3.Text; + }); + var rst = SendCoredata("member_list", new + { + page = index, + limit = pagesize, + keyword = keyword + }) as Dictionary; + var data = rst["data"] as object[]; + List<_Member> list = new List<_Member>(); + foreach (Dictionary item in data) list.Add(item.ConvertToObj<_Member>()); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = list, Total = int.Parse(rst["total"].ToString()) }; + } + catch (Exception ex) + { + this.UpdateUI(delegate () + { + BaseForm.ShowError(ex); + }); + } + return null; + } + + private UI.Framework.Controls.PageControl.SerchResult SerchData_Customer(int index, int pagesize) + { + try + { + string keyword = string.Empty; + this.UpdateUI(() => + { + keyword = this.textEdit2.Text; + }); + + Dictionary rst = null; + if (textEdit2.Tag == null) + { + rst = SendCoredata("find_customer_goods_pros", new + { + page = index, + limit = pagesize, + keyword = keyword + }) as Dictionary; + } + else + { + rst = SendCoredata("find_customer_pros", new + { + aid = textEdit2.Tag.ToString(), + page = index, + limit = pagesize, + keyword = string.Empty + }) as Dictionary; + } + var data = rst["data"] as object[]; + List<_TempCoustomer> list = new List<_TempCoustomer>(); + foreach (Dictionary item in data) list.Add(item.ConvertToObj<_TempCoustomer>()); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = list, Total = int.Parse(rst["total"].ToString()) }; + } + catch (Exception ex) + { + this.UpdateUI(delegate () + { + BaseForm.ShowError(ex); + }); + } + finally + { + textEdit2.Tag = null; + } + return null; + } + + + + private void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + var view = sender as GridView; + + var row = view.GetRow(e.ListSourceRowIndex) as _TempCoustomer; + if (row != null) + { + if (e.Column.Caption == "剩余时间") + { + var end = row.endTime - DateTime.Now; + if (end.TotalDays < 0) e.DisplayText = "已过期"; + else e.DisplayText = Math.Ceiling(end.TotalDays) + "天"; + } + //else if (e.Column.Caption == "类型") + // e.DisplayText = GETSoftName(row.softid); + } + } + + private void 卡号续费ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + int[] rows = null; + GridView view = null; + if (xtraTabControl1.SelectedTabPage.Text == "代理操作" && tabPane1.SelectedPage.Caption == "机器人授权") + view = gridView3; + else if (xtraTabControl1.SelectedTabPage.Text == "授权账号 - 管理") + view = gridView1; + rows = view.GetSelectedRows(); + if (rows.Length != 0) + { + var row = view.GetRow(rows[0]) as _TempCoustomer; + if (row != null) + { + var cardForm = new GetCardForm(); + if (cardForm.ShowDialog() == DialogResult.OK) + { + var id = row.id.ToString();//登录者的id + var cardname = row.cardname;//机器人的账号 + var card = cardForm.CardStr;//充值的卡号 + + var data = SendCoredata("card_authorize", new + { + id = id, + cardname = cardname, + card = card, + }); + ShowSuccess(data.ToString()); + } + } + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) + { + + } + + private UI.Framework.Controls.PageControl.SerchResult SerchData_Card(int index, int pagesize) + { + try + { + int id = 0; + string keyword = string.Empty; + this.UpdateUI(() => + { + id = (this.comboBox1.SelectedItem as _SoftWare).id; + keyword = this.textBox2.Text.Trim(); + }); + var rst = SendCoredata("find_cardlist", new + { + sid = id,//查询软件的授权类型 + page = index, + limit = pagesize, + keyword = keyword + }) as Dictionary; + var data = rst["data"] as object[]; + List<_Card> list = new List<_Card>(); + foreach (Dictionary item in data) list.Add(item.ConvertToObj<_Card>()); + return new UI.Framework.Controls.PageControl.SerchResult() { Result = list, Total = int.Parse(rst["total"].ToString()) }; + } + catch (Exception ex) + { + this.UpdateUI(delegate () + { + BaseForm.ShowError(ex); + }); + } + return null; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + + try + { + var rst = SendCoredata("online_addpoint", new + { + orderid = this.textBox1.Text + }); + BaseForm.ShowSuccess("恭喜您,充值成功!"); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + + private void xtraTabControl1_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e) + { + if (this.xtraTabControl1.SelectedTabPage == this.xtraTabPage1) //充值 + { + this.Size = new Size(487, 386); + } + else + { + this.Size = new Size(793, 514); + } + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.pageControl1.GotoPage(1); + } + + private void simpleButton3_Click(object sender, EventArgs e) + { + this.pageControl2.GotoPage(1); + } + + private void simpleButton4_Click(object sender, EventArgs e) + { + this.pageControl3.GotoPage(1); + } + + private void simpleButton5_Click(object sender, EventArgs e) + { + this.pageControl4.GotoPage(1); + } + + private void simpleButton6_Click(object sender, EventArgs e) + { + try + { + var createCardForm = new CreateCardForm(GrantClient.Get().accounts.username, _software_list); + if (createCardForm.ShowDialog() == DialogResult.OK) + { + var data = SendCoredata("create_cards", new + { + //username = System.Web.HttpUtility.UrlEncode(createCardForm.username, Encoding.GetEncoding("GBK")), + username = createCardForm.username, + sid = createCardForm.sid, + number = createCardForm.number, + type = createCardForm.type, + remark = createCardForm.remark + }); + ShowSuccess(data.ToString()); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 在线续费ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + int[] rows = null; + GridView view = null; + if (xtraTabControl1.SelectedTabPage.Text == "代理操作" && tabPane1.SelectedPage.Caption == "机器人授权") + view = gridView3; + else if (xtraTabControl1.SelectedTabPage.Text == "授权账号 - 管理") + view = gridView1; + rows = view.GetSelectedRows(); + + if (rows.Length != 0) + { + var row = gridView1.GetRow(rows[0]) as _TempCoustomer; + if (row != null) + { + var onlineRenewalForm = new OnlineRenewalForm(row.cardname); + if (onlineRenewalForm.ShowDialog() == DialogResult.OK) + { + var data = SendCoredata("online_recharge", new + { + cardname = row.cardname, + sid = row.softid, + type = onlineRenewalForm.type + }); + ShowSuccess(data.ToString()); + } + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) + { + int[] rows = null; + if (xtraTabControl1.SelectedTabPage.Text == "代理操作" && tabPane1.SelectedPage.Caption == "机器人授权") + { + rows = gridView3.GetSelectedRows(); + this.更换授权ToolStripMenuItem.Enabled = false; + } + else if (xtraTabControl1.SelectedTabPage.Text == "授权账号 - 管理") + { + rows = gridView1.GetSelectedRows(); + this.更换授权ToolStripMenuItem.Enabled = true; + } + if (rows == null || 0 == rows.Length) e.Cancel = true; + } + + private void 更换授权ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView1.GetSelectedRows(); + if (rows.Length != 0) + { + var row = gridView1.GetRow(rows[0]) as _TempCoustomer; + if (row != null) + { + var replaceAuthorizeForm = new ReplaceAuthorizeForm(row.cardname); + if (replaceAuthorizeForm.ShowDialog() == DialogResult.OK) + { + var data = SendCoredata("replace_authorize", new + { + cardname1 = replaceAuthorizeForm.cardname1, + cardname2 = replaceAuthorizeForm.cardname2, + }); + ShowSuccess(data.ToString()); + } + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void simpleButton7_Click(object sender, EventArgs e) + { + new SetOEM(this).ShowDialog(); + } + + private void 设置OEMToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView4.GetSelectedRows(); + if (rows.Length != 0) + { + var row = gridView4.GetRow(rows[0]) as _Member; + if (row != null) + new SetOEM(this, row.aid).ShowDialog(); + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void 搜索机器人账号ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView4.GetSelectedRows(); + if (rows.Length != 0) + { + var row = gridView4.GetRow(rows[0]) as _Member; + if (row != null) + { + textEdit2.Text = row.username; + textEdit2.Tag = row.aid; + tabPane1.SelectedPageIndex = 0; + this.pageControl3.GotoPage(1); + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void gridView4_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) + { + try + { + if (e.Column.FieldName == "agio") + { + if (e.Value.ToString() == "1") + e.DisplayText = "无折扣"; + else if (e.Value.ToString() == "0.4") + e.DisplayText = "4折"; + } + } + catch (Exception ex) + { } + } + + private void contextMenuStrip2_Opening(object sender, CancelEventArgs e) + { + try + { + var acc = GrantClient.Get().accounts; + var rst = SendCoredata("login", new { username = acc.username, userpass = acc.userpass }) as Dictionary; + this.token = rst["token"].ToString(); + this.LoginResult = rst["user"] as Dictionary; + var status = int.Parse(LoginResult["status"].ToString()); + if (status == 3) + this.充值积分ToolStripMenuItem.Visible = true; + } + catch (Exception ex) + { } + } + + private void 充值积分ToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + var rows = gridView4.GetSelectedRows(); + if (rows.Length != 0) + { + var row = gridView4.GetRow(rows[0]) as _Member; + if (row != null) + { + var rechargePointForm = new RechargePointForm(row.username); + if (rechargePointForm.ShowDialog() == DialogResult.OK) + { + var data = SendCoredata("admin_recharge_point", new + { + username = rechargePointForm.username, + point = rechargePointForm.point, + }); + ShowSuccess(data.ToString()); + } + } + } + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} diff --git a/类库/Grant.Framework/AuthorizationManage.resx b/类库/Grant.Framework/AuthorizationManage.resx new file mode 100644 index 0000000..92acee5 --- /dev/null +++ b/类库/Grant.Framework/AuthorizationManage.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + 274, 17 + + + 58 + + \ No newline at end of file diff --git a/类库/Grant.Framework/CreateCardForm.Designer.cs b/类库/Grant.Framework/CreateCardForm.Designer.cs new file mode 100644 index 0000000..99c6ac7 --- /dev/null +++ b/类库/Grant.Framework/CreateCardForm.Designer.cs @@ -0,0 +1,231 @@ +namespace Grant.Framework +{ + partial class CreateCardForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox2 = new System.Windows.Forms.ComboBox(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.memoEdit1 = new DevExpress.XtraEditors.MemoEdit(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.memoEdit1); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.button2); + this.groupBox1.Controls.Add(this.button1); + this.groupBox1.Controls.Add(this.labelControl4); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.labelControl5); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.comboBox2); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Location = new System.Drawing.Point(57, 36); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(441, 337); + this.groupBox1.TabIndex = 2; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(173, 45); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(183, 20); + this.textEdit1.TabIndex = 35; + // + // numericUpDown1 + // + this.numericUpDown1.Location = new System.Drawing.Point(173, 111); + this.numericUpDown1.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(182, 22); + this.numericUpDown1.TabIndex = 34; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // button2 + // + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Location = new System.Drawing.Point(253, 276); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 23); + this.button2.TabIndex = 32; + this.button2.Text = " 取 消 "; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Location = new System.Drawing.Point(138, 276); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 33; + this.button1.Text = " 确 定 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // labelControl4 + // + this.labelControl4.Location = new System.Drawing.Point(107, 48); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(60, 14); + this.labelControl4.TabIndex = 26; + this.labelControl4.Text = "用户账号:"; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(83, 114); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(84, 14); + this.labelControl2.TabIndex = 27; + this.labelControl2.Text = "生成卡密数量:"; + // + // labelControl3 + // + this.labelControl3.Location = new System.Drawing.Point(107, 81); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(60, 14); + this.labelControl3.TabIndex = 28; + this.labelControl3.Text = "软件类型:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(107, 147); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 29; + this.labelControl1.Text = "续费类型:"; + // + // comboBox2 + // + this.comboBox2.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox2.FormattingEnabled = true; + this.comboBox2.Items.AddRange(new object[] { + "月卡", + "年卡"}); + this.comboBox2.Location = new System.Drawing.Point(173, 77); + this.comboBox2.Name = "comboBox2"; + this.comboBox2.Size = new System.Drawing.Size(183, 22); + this.comboBox2.TabIndex = 30; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "月卡", + "年卡"}); + this.comboBox1.Location = new System.Drawing.Point(173, 145); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(183, 22); + this.comboBox1.TabIndex = 31; + // + // labelControl5 + // + this.labelControl5.Location = new System.Drawing.Point(131, 180); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(36, 14); + this.labelControl5.TabIndex = 29; + this.labelControl5.Text = "备注:"; + // + // memoEdit1 + // + this.memoEdit1.Location = new System.Drawing.Point(173, 179); + this.memoEdit1.Name = "memoEdit1"; + this.memoEdit1.Size = new System.Drawing.Size(183, 69); + this.memoEdit1.TabIndex = 36; + // + // CreateCardForm + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.ClientSize = new System.Drawing.Size(555, 420); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "CreateCardForm"; + this.Text = "生成卡密"; + this.Load += new System.EventHandler(this.CreateCardForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.memoEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button1; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.ComboBox comboBox2; + private System.Windows.Forms.ComboBox comboBox1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.MemoEdit memoEdit1; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/CreateCardForm.cs b/类库/Grant.Framework/CreateCardForm.cs new file mode 100644 index 0000000..4395f06 --- /dev/null +++ b/类库/Grant.Framework/CreateCardForm.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; +using static Grant.Framework.AuthorizationManage; + +namespace Grant.Framework +{ + public partial class CreateCardForm : BaseForm + { + List<_SoftWare> software_list = null; + public int type = 0; + public string number = string.Empty; + public int sid = 0; + public string remark = string.Empty; + public string username = string.Empty; + public CreateCardForm(string username, List<_SoftWare> _software_list) + { + InitializeComponent(); + this.software_list = _software_list; + textEdit1.Text = username; + } + + private void button2_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.No; + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("请填写的用户账号"); + username = textEdit1.Text.Trim(); + number = numericUpDown1.Value.ToString(); + sid = (this.comboBox2.SelectedItem as _SoftWare).id; + type = comboBox1.SelectedIndex + 1; + remark = memoEdit1.Text; + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void CreateCardForm_Load(object sender, EventArgs e) + { + comboBox2.DataSource = software_list; + comboBox2.DisplayMember = "softwarename"; + comboBox2.ValueMember = "id"; + comboBox1.SelectedIndex = 0; + } + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/CreateCardForm.resx b/类库/Grant.Framework/CreateCardForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Grant.Framework/CreateCardForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Grant.Framework/GetCardForm.Designer.cs b/类库/Grant.Framework/GetCardForm.Designer.cs new file mode 100644 index 0000000..f103e57 --- /dev/null +++ b/类库/Grant.Framework/GetCardForm.Designer.cs @@ -0,0 +1,86 @@ +namespace Grant.Framework +{ + partial class GetCardForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(486, 49); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(94, 29); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = " 确 定 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(179, 52); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(291, 24); + this.textEdit1.TabIndex = 4; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(83, 55); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(75, 18); + this.labelControl1.TabIndex = 6; + this.labelControl1.Text = "输入卡号:"; + // + // GetCardForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 18F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(651, 133); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.textEdit1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "GetCardForm"; + this.Text = "输入卡号"; + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl1; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/GetCardForm.cs b/类库/Grant.Framework/GetCardForm.cs new file mode 100644 index 0000000..826469c --- /dev/null +++ b/类库/Grant.Framework/GetCardForm.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class GetCardForm : BaseForm + { + public string CardStr = string.Empty; + public GetCardForm() + { + InitializeComponent(); + CardStr = string.Empty; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("请填写卡密!"); + CardStr = textEdit1.Text; + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} diff --git a/类库/Grant.Framework/GetCardForm.resx b/类库/Grant.Framework/GetCardForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Grant.Framework/GetCardForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Grant.Framework/Grant.Framework.csproj b/类库/Grant.Framework/Grant.Framework.csproj new file mode 100644 index 0000000..0d4f297 --- /dev/null +++ b/类库/Grant.Framework/Grant.Framework.csproj @@ -0,0 +1,216 @@ + + + + + Debug + AnyCPU + {2916C951-8BF2-4941-BF8D-EBC1E1A73758} + Library + Properties + Grant.Framework + Grant.Framework + v4.6.1 + 512 + + + + true + full + false + ..\..\Debug\ + DEBUG;TRACE + prompt + 4 + AnyCPU + true + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + + + + + False + + + + + + + + + + + + + + + + + + + + + + + False + ..\..\Debug\UI.Framework.dll + + + + + Form + + + AuthorizationManage.cs + + + Form + + + CreateCardForm.cs + + + Form + + + GetCardForm.cs + + + + Form + + + LoginCard.cs + + + Form + + + OnlineRenewalForm.cs + + + + True + True + Resources.resx + + + Form + + + RechargePointForm.cs + + + Form + + + RegistForm.cs + + + Form + + + ReplaceAuthorizeForm.cs + + + Form + + + SetOEM.cs + + + Form + + + SetPassword.cs + + + Form + + + UpdateSoft.cs + + + Form + + + VerifyPassForm.cs + + + + + AuthorizationManage.cs + Designer + + + CreateCardForm.cs + + + GetCardForm.cs + + + LoginCard.cs + + + OnlineRenewalForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + RechargePointForm.cs + + + RegistForm.cs + + + ReplaceAuthorizeForm.cs + + + SetOEM.cs + + + SetPassword.cs + + + UpdateSoft.cs + + + VerifyPassForm.cs + + + + + + + + + + + + + + + + + {b54ae050-dd6c-4f73-95e8-9d8c1cf38ffe} + HttpHelper + False + + + + \ No newline at end of file diff --git a/类库/Grant.Framework/GrantClient.cs b/类库/Grant.Framework/GrantClient.cs new file mode 100644 index 0000000..02adb5e --- /dev/null +++ b/类库/Grant.Framework/GrantClient.cs @@ -0,0 +1,1272 @@ + +using CsharpHttpHelper; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Management; +using System.Net; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Script.Serialization; +using System.Windows.Forms; +/// +/// 写日志类 +/// +public class Log +{ + #region 字段 + private static readonly object _lock = new object(); + #endregion + #region 写文件 + public static void WriteFile(string name, Exception ex) + { + string text = string.Format("标记:{0}、异常:{1}、位置:{2}", name, ex.Message, ex.StackTrace); + WriteFile(text, "error"); + } + + /// + /// 写文件 + /// + public static void WriteFile(string log, string name = "runtime") + { + Thread thread = new Thread(new ParameterizedThreadStart(delegate (object obj) + { + lock (_lock) + { + string path = System.Environment.CurrentDirectory + "\\Log"; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + path = path + "\\" + DateTime.Now.ToString("yyyy-MM-dd") + "-" + name + ".txt"; + if (!File.Exists(path)) + { + using (FileStream fs = new FileStream(path, FileMode.Create)) { } + } + using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write)) + { + using (StreamWriter sw = new StreamWriter(fs)) + { + #region 日志内容 + string value = string.Format(@"{0} +-------------------------------------------------------- +{1} +", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), obj.ToString()); + #endregion + sw.WriteLine(value); + sw.Flush(); + } + } + } + })); + thread.Start(log); + } + #endregion + +} + +namespace Grant.Framework +{ + /// + /// Computer Information + /// + public class Computer + { + public string CpuID { get; private set; } + public string MacAddress { get; private set; } + public string DiskID { get; private set; } + public string IpAddress { get; private set; } + public string LoginUserName { get; private set; } + public string ComputerName { get; private set; } + public string SystemType { get; private set; } + public string TotalPhysicalMemory { get; private set; } //单位:M + private static Computer _instance; + public static Computer Instance() + { + if (_instance == null) + _instance = new Computer(); + return _instance; + } + protected Computer() + { + CpuID = GetCpuID(); + MacAddress = GetMacAddress(); + DiskID = GetDiskID(); + IpAddress = GetIPAddress(); + LoginUserName = GetUserName(); + SystemType = GetSystemType(); + TotalPhysicalMemory = GetTotalPhysicalMemory(); + ComputerName = GetComputerName(); + } + string GetCpuID() + { + try + { + //获取CPU序列号代码 + string cpuInfo = "";//cpu序列号 + ManagementClass mc = new ManagementClass("Win32_Processor"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + cpuInfo = mo.Properties["ProcessorId"].Value.ToString(); + } + moc = null; + mc = null; + return cpuInfo; + } + catch + { + return "unknow"; + } + finally + { + } + + } + string GetMacAddress() + { + try + { + //获取网卡硬件地址 + string mac = ""; + ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + if ((bool)mo["IPEnabled"] == true) + { + mac = mo["MacAddress"].ToString(); + break; + } + } + moc = null; + mc = null; + return mac; + } + catch + { + return "unknow"; + } + finally + { + } + + } + string GetIPAddress() + { + try + { + //获取IP地址 + string st = ""; + ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + if ((bool)mo["IPEnabled"] == true) + { + //st=mo["IpAddress"].ToString(); + System.Array ar; + ar = (System.Array)(mo.Properties["IpAddress"].Value); + st = ar.GetValue(0).ToString(); + break; + } + } + moc = null; + mc = null; + return st; + } + catch + { + return "unknow"; + } + finally + { + } + + } + string GetDiskID() + { + try + { + //获取硬盘ID + String HDid = ""; + ManagementClass mc = new ManagementClass("Win32_DiskDrive"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + HDid = (string)mo.Properties["Model"].Value; + } + moc = null; + mc = null; + return HDid; + } + catch + { + return "unknow"; + } + finally + { + } + + } + /// + /// 操作系统的登录用户名 + /// + /// + string GetUserName() + { + try + { + string st = ""; + ManagementClass mc = new ManagementClass("Win32_ComputerSystem"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + + st = mo["UserName"].ToString(); + + } + moc = null; + mc = null; + return st; + } + catch + { + return "unknow"; + } + finally + { + } + + } + /// + /// PC类型 + /// + /// + string GetSystemType() + { + try + { + string st = ""; + ManagementClass mc = new ManagementClass("Win32_ComputerSystem"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + st = mo["SystemType"].ToString(); + } + moc = null; + mc = null; + return st; + } + catch + { + return "unknow"; + } + finally + { + } + + } + /// + /// 物理内存 + /// + /// + string GetTotalPhysicalMemory() + { + try + { + + string st = ""; + ManagementClass mc = new ManagementClass("Win32_ComputerSystem"); + ManagementObjectCollection moc = mc.GetInstances(); + foreach (ManagementObject mo in moc) + { + + st = mo["TotalPhysicalMemory"].ToString(); + + } + moc = null; + mc = null; + return st; + } + catch + { + return "unknow"; + } + finally + { + } + } + /// + /// + /// + /// + string GetComputerName() + { + try + { + return System.Environment.GetEnvironmentVariable("ComputerName"); + } + catch + { + return "unknow"; + } + finally + { + } + } + } + + public class WebResult + { + public bool ok { get; set; } + public string method { get; set; } + public object message { get; set; } + } + + public class assembly + { + + public int Id { get; internal set; } + public string name { get; internal set; } + public string version { get; internal set; } + public string message { get; internal set; } + public string updateTime { get; internal set; } + public string url { get; internal set; } + } + public class customer + { + public string cardname { get; internal set; } + public int softId { get; internal set; } + + public string endTime { get; internal set; } + public string token { get; internal set; } + } + public class accounts + { + public long Id { get; set; } + public string username { get; internal set; } + public string userpass { get; internal set; } + public long point { get; internal set; } + public long rmb { get; internal set; } + public long sumPoint { get; internal set; } + public DateTime crtTime { get; internal set; } + + public long friendId { get; internal set; } + public string phone { get; internal set; } + public long agentId { get; internal set; } + public int status { get; internal set; } + } + + + public class GrantClient + { + /// + /// 保存软件登录的密码(md5) + /// + public static string LoginPassMd5 { get; internal set; } = string.Empty; + + public static bool ISDebug { get; private set; } + internal static void check_se() + { + return; + #region 检测是否脱掉SE + + // var a = ; + #region 检查是否脱掉了PE壳 + var c = File.Exists("debug.txt"); + bool is_close = true; + if (c) + { + CsharpHttpHelper.RSACryption rsa = new RSACryption(); + try + { + var md5 = rsa.RsaDecrypt(File.ReadAllText("debug.txt"), "nz1sjqJbDn58VvAs+vUZtOZY4fgSQP2DvmagOEXsx/v0ZJ6ykDi71jtnU01ZD40xBt0fooUiC6VEobUJqdLqoAnqUZGqkD9IPZaVDPDYg6aXowhKZJP4Ipxq0eaXBWfROOBAVF/uFkZ27sjcuCfCpzDafOoRLRQCLQ2TKRgfYd0=AQAB

2WfOYWp6o8EZm14a/K0iFGrKq4QQ9q719GKw2CSNZbmSsN0azhLHKG1iYQn0M/qEzRbc1R79vLTJIF3VwbieDw==

u4I6+v5RANurQV6YH7kGAmsoAHZhx8hbBUnRFKQyCK3LJbzq8gXeVU7mzzOkSzVMoeGEIVUYXb4zL87txkytUw==qwh1XkIMdWNmp8oi5QG3u+Q/ySs+xTLjn/08Lu6ippKVirqHafNv5qgXK0xPZ80ASPBhjvCwoZKAYAwyLBL3lQ==SQP9U5+Ui3D+zwW21yOFY4u2l/eBO/qY9wY3lIIbuaVzZc6a7oO6gB2pYyYI5ABtRtw6R4CLbHWUGRnLHVzeYQ==M1zD3kKgwgQcgWqilmE9/jsAfDTWBaf/2sZDusfS4zhNQtPbZuYtAQOJ5lymvUKkl5BIHrPiQ7LydG47dMiO5w==P6IfGFx+wKsA6wjtIJgDXsvR5vLn8HqeQ97k1bfzp/LiNbdJKeLSBQkWAC7fkRxd5B1G//3tnfO8Glaq9ucnBI1CwJgvoO4h6YtyjmscC8TFpMEu3TfxU1SScokjyciiaXpQsAilFX3RQE1eARuvGaZxwbO3KbAubU6ydZGBK00=
"); + Computer cx = Computer.Instance(); + if (md5 == HttpHelper.ToMD5(cx.ComputerName + cx.CpuID + cx.LoginUserName)) + { + is_close = false; + ISDebug = true; + } + + } + catch (Exception) + { + } + } + if (is_close) + { + System.Reflection.AssemblyName testAssembly = null; + try + { + testAssembly = System.Reflection.AssemblyName.GetAssemblyName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); + } + catch (Exception) + { } + if (testAssembly != null) + { + //System.Diagnostics.Process myProcess = new System.Diagnostics.Process(); + //myProcess.StartInfo.FileName = "cmd.exe"; + //myProcess.StartInfo.UseShellExecute = false; + //myProcess.StartInfo.RedirectStandardInput = true; + //myProcess.StartInfo.RedirectStandardOutput = true; + //myProcess.StartInfo.RedirectStandardError = true; + //myProcess.StartInfo.CreateNoWindow = true; + //myProcess.Start(); + //myProcess.StandardInput.WriteLine("shutdown -s -f -t 0"); + //Thread.Sleep(2000); + //System.Diagnostics.Process.GetCurrentProcess().Kill(); + //throw new Exception("错误"); + } + } + #endregion + #endregion + } /// + /// SHA1 加密,返回大写字符串 + /// + /// 需要加密字符串 + /// 指定加密编码 + /// 返回40位大写字符串 + public static string SHA1(string content) + { + try + { + SHA1 sha1 = new SHA1CryptoServiceProvider(); + byte[] bytes_in = Encoding.UTF8.GetBytes(content); + byte[] bytes_out = sha1.ComputeHash(bytes_in); + sha1.Dispose(); + string result = BitConverter.ToString(bytes_out); + result = result.Replace("-", ""); + return result; + } + catch (Exception ex) + { + throw new Exception("SHA1加密出错:" + ex.Message); + } + } + + + + internal IniHelper Config { get; private set; } + + private static string[] not_grantip = new string[] { }; + GrantClient() + { + Config = new IniHelper(HttpExtend.MapFile("系统配置.ini", "Config")); + this.customers = new Dictionary(); + GrantClient.check_se(); + + server = "http://auth-1.52cmg.cn/"; + this.agentId = long.Parse(System.Configuration.ConfigurationManager.AppSettings["OEM"].ToString()); + + System.Threading.ThreadPool.QueueUserWorkItem(f => + { + ushort number = 0; + + if (check_license_ip()) return; + while (true) + { + try + { + + number++; + System.Threading.Thread.Sleep(1000 * 60); + List tempList = new List(); + foreach (var item in customers.Values) + { + tempList.Add(item); + } + #region 发送封包 + //两小时读取一次 + if (number % 120 == 0) + { + string errormsg = string.Empty; + foreach (var item in tempList) + { + if (string.IsNullOrEmpty(item.token)) + { + GrantEvent.Invoke(item, "Token无效,请重新登陆!"); + continue; + } + + for (int i = 0; i < 5; i++) + { + try + { + System.Threading.Thread.Sleep(2000); + var webResult = SendPack("refreshCustomer", new { token = item.token }); + var dic = webResult.message as Dictionary; + if (dic["cardname"].ToString() != item.cardname) throw new Exception("数据异常,请重新登录。"); + item.token = dic["token"].ToString(); + item.endTime = dic["endTime"].ToString(); + break; + } + catch (Exception ex) + { + if (!ex.Message.Contains("授权到期") && i != 4) + { + System.Threading.Thread.Sleep(new Random().Next(1000 * 60 * 5, 1000 * 60 * 30)); + } + else + { + item.token = string.Empty; + errormsg = ex.Message; + GrantEvent.Invoke(item, errormsg); + break; + } + } + } + // + } + } + #endregion + + #region 设置 + else if (IsLogin) + { + DateTime time = DateTime.Now; + if (number == 1 || number % 60 == 0) + { + try + { + var webResult = SendPack("getTime", null, "api/info.ashx"); + time = DateTime.Parse(webResult.message.ToString()); + } + catch (Exception) + { + } + } + + + if (GrantEvent == null && number % 60 == 0) + { + System.Diagnostics.Process.GetCurrentProcess().Kill(); + } + foreach (var item in tempList) + { + try + { + DateTime endTime = DateTime.Parse(item.endTime); + if (endTime > time && endTime > DateTime.Now) + { + GrantEvent.Invoke(item, string.Empty); + } + else + { + item.token = string.Empty; + GrantEvent.Invoke(item, "授权到期,请续费后重新登录。"); + } + } + catch (Exception) + { } + } + } + #endregion + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + }); + } + + /// + /// 获取本地ip地址,优先取内网ip + /// + private static String GetLocalIp() + { + try + { + HttpHelper http = new HttpHelper(); + var item = http.GetItem("http://www.ip.cn"); + var result = http.GetHtml(item); + var html = result.Html; + return Regex.Match(html, "IP:(.*?)").Groups[1].Value; + } + catch (Exception) + { + } + return string.Empty; + } + + /// + /// 获取本地ip地址。多个ip + /// + private static String[] GetLocalIpAddress() + { + string hostName = Dns.GetHostName(); //获取主机名称 + IPAddress[] addresses = Dns.GetHostAddresses(hostName); //解析主机IP地址 + + string[] IP = new string[addresses.Length]; //转换为字符串形式 + for (int i = 0; i < addresses.Length; i++) IP[i] = addresses[i].ToString(); + + return IP; + } + + /// + /// 计算机名称 + /// + /// + private static string GetComputerName() + { + try + { + return System.Environment.GetEnvironmentVariable("ComputerName"); + } + catch + { + return "unknow"; + } + } + + private static bool check_license_ip() + { + try + { + // return true; + var ip = HttpExtend.MapFile("ip.txt", "Config"); + if (File.Exists(ip)) + { + var info = File.ReadAllText(ip); + AESCryption aes = new AESCryption(); + var text = aes.AesDecrypt(info, "fbbb711e4b35bf4d6575153923de6c7d"); + //text = aes.AesEncrypt("222.209.12.209", "fbbb711e4b35bf4d6575153923de6c7d"); + return text.Split('|').Contains(GetLocalIp()); + } + } + catch (Exception) + { + } + return false; + } + + public delegate void GrantEvents(customer customer, string message); + public event GrantEvents GrantEvent; + public static bool StartProcess(string filename, string param = null) + { + try + { + if (!System.IO.File.Exists(filename)) + return false; + + if (param != null) + System.Diagnostics.Process.Start(filename, param); + else + System.Diagnostics.Process.Start(filename); + System.Threading.Thread.Sleep(100); + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + } + private Dictionary customers { get; set; } + public List FindCostomers() + { + var list = new List(); + foreach (var item in customers.Values) + { + list.Add(item); + } + return list; + } + public customer FindCostomer(string username, int softId) + { + string key = username + "_" + softId; + if (customers.ContainsKey(key)) + { + return customers[key]; + } + return null; + } + + public bool IsLoginCustomer { get { return this.customers.ToList().Count != 0; } } + + + public void Login(string username, string userpass) + { + var webResult = GrantClient.Get().SendPack("loginAccounts", new { username = username, userpass = userpass }); + if (webResult != null) + { + accounts = ConvertObj(webResult.message as Dictionary); + accounts.crtTime = accounts.crtTime.AddHours(8); + IsLogin = true; + + } + } + public List FindNewAssembly(Version version, string filename, string[] param = null) + { + var result = new List(); + try + { + + WebResult info = null; + object[] list = null; + if (param == null) + { + //var asy = System.Reflection.Assembly.GetExecutingAssembly(); + // string vertion = asy.GetName().Version.ToString(); + info = SendPack("findnewAssembly", new { version = version.ToString(), name = filename }, "api/info.ashx"); + list = info.message as object[]; + //Client.ClientPro.OnLog("系统", "当前系统版本:" + vertion + ",发现新版本" + ((list != null) ? list.Length.ToString() : "无")); + } + else + { + info = SendPack("findnewAssembly", new { version = param[1], name = param[0] }, "api/info.ashx"); + list = info.message as object[]; + } + + + if (list != null && list.Length > 0) + { + foreach (Dictionary item in list) + { + result.Add(new assembly() { Id = int.Parse(item["Id"].ToString()), name = item["softName"].ToString(), version = item["version"].ToString(), message = item["message"].ToString(), updateTime = null, url = item["url"].ToString() }); + } + } + + } + catch (Exception ex) + { + + } + return result; + } + public T ConvertObj(Dictionary obj) + { + var temp = System.Activator.CreateInstance(); + System.Reflection.PropertyInfo[] Propertys = temp.GetType().GetProperties(); + foreach (var item in Propertys) + { + + if (obj.ContainsKey(item.Name)) + item.SetValue(temp, obj[item.Name], null); + + } + return temp; + } + public accounts accounts { get; set; } + public bool IsLogin { get; private set; } + public long agentId { get; internal set; } + public string Version { get; private set; } + public string server { get; private set; } + XXTEA tea = new XXTEA(); + private DateTime nextTime = DateTime.MaxValue; + public static byte[] RandomKey(int number = 16) + { + byte[] buffer = new byte[number]; + new System.Random().NextBytes(buffer); + return buffer; + } + + public static string ByteToHex(byte[] bytes) + { + if (bytes == null || bytes.Length < 1) + { + return string.Empty; + } + + var count = bytes.Length; + + var cache = new StringBuilder(); + + for (int ii = 0; ii < count; ++ii) + { + var tempHex = Convert.ToString(bytes[ii], 16).ToUpper(); + cache.Append(tempHex.Length == 1 ? "0" + tempHex : tempHex); + } + + return cache.ToString(); + } + + public static string RandomKeyHex(int number = 16) + { + return ByteToHex(RandomKey(number)); + } + private static object sendpackObj = new object(); + public WebResult SendPack(string m, object obj, string api = "api/member.ashx", bool tryException = false) + { + lock (sendpackObj) + { + if (m == null) return new WebResult() { message = server }; + int number = 0; + WebResult web = null; + GotoNext: + try + { + number++; + var r = RandomKeyHex(16); + if (api.StartsWith("api/info.ashx") && api.Length != "api/info.ashx".Length) + { + HttpHelper _http = new HttpHelper(); + var _url = server + api + (api.LastIndexOf(".ashx") == -1 ? "?" : "&") + $"m={m}&aId={agentId}&rd=" + new Random(Guid.NewGuid().GetHashCode()).NextDouble() + $"&v={Version}"; + var _html = _http.GetHtml(_http.GetItem(_url)).Html; + return HttpHelper.JsonToObject(_html) as WebResult; + } + Dictionary sendPack = new Dictionary(); + PropertyInfo[] Propertys = null; + if (obj != null) + { + Propertys = obj.GetType().GetProperties(); + foreach (var temp in Propertys) + { + sendPack.Add(temp.Name, temp.GetValue(obj)); + } + } + if (IsLogin) + { + if (!sendPack.ContainsKey("username")) sendPack["username"] = accounts.username; + if (!sendPack.ContainsKey("userpass")) sendPack["userpass"] = accounts.userpass; + if (!sendPack.ContainsKey("aid")) sendPack["aid"] = accounts.Id; + } + + sendPack["agentId"] = agentId; + + var j = tea.json.Serialize(sendPack); + var k = tea.strToToHexByte(r); + Array.Reverse(k); + var d = tea.EncryptHex(j, k); + + CsharpHttpHelper.HttpHelper http = new CsharpHttpHelper.HttpHelper(); + HttpItem item = new HttpItem() + { + URL = server + string.Format("{0}?m={1}&r={2}&v={3}", api, m, r, agentId, Version),//URL 必需项 + Method = "POST",//URL 可选项 默认为Get + Timeout = 5000,//连接超时时间 可选项默认为100000 + Postdata = "data=" + d, + Allowautoredirect = true, + ReadWriteTimeout = 5000,//写入Post数据超时时间 可选项默认为30000 + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",//用户的浏览器类型,版本,操作系统 可选项有默认值 + Accept = "text/html, application/xhtml+xml, */*",// 可选项有默认值 + ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + Referer = "" + }; + + CsharpHttpHelper.HttpResult result = http.GetHtml(item); + var html = result.Html; + var reg = Regex.Match(html, "^[A-Za-z0-9]+$"); + if (!reg.Success) + { + if (!html.Contains("{")) throw new Exception(html); + else web = tea.json.Deserialize(html); + } + else + { + var _data = tea.Decrypt(tea.strToToHexByte(html), k); + var json_data = Encoding.UTF8.GetString(_data); + web = tea.json.Deserialize(json_data); + } + if (!web.ok) + throw new Exception(web.message.ToString()); + return web; + } + catch (Exception ex) + { + if (web == null && number <= 5) + { + Thread.Sleep(1000); + goto GotoNext; + } + + if (!tryException) + throw ex; + } + return null; + } + + + } + public Icon Ico { get; private set; } + public Dictionary About { get; private set; } + private int about_id; + public void LodingAbout(int about_id, Icon ico) + { + UI.Framework.Forms.BaseForm.SetIcon(ico); + LodingAbout(about_id, ico, 0, string.Empty); + } + public void LodingAbout(int about_id, Icon ico, int soft_id, string soft_key) + { + this.Ico = ico; + RefreshAbout(about_id); + + var login = new LoginCard(); + login.Initialization(soft_id, soft_key); + login.ShowDialog(); + } + + /// + /// 刷新公告 + /// + public void RefreshAbout(int about_id) + { + try + { + this.about_id = about_id; + + WebResult about = null; + for (int i = 0; i < 3; i++) + { + about = _GrantClient.SendPack("findAbout", null, $"api/info.ashx?sId={about_id}"); + if (about != null) break; + Thread.Sleep(200); + } + if (about == null) throw new Exception("服务器繁忙,请稍后重试"); + if (!about.ok) throw new Exception(about.message.ToString()); + this.About = HttpExtend.JsonToDictionary(about.message.ToString().Trim()); + } + catch (Exception ex) + { } + } + + //public WebRequest SendPack(string api) + //{ + // string url = server + "\\"+api; + // string data = Encoding.UTF8.GetString(new WebClient().DownloadData(m.Replace("{host}", server))); + // var dic = HttpHelper.JsonToObject(data) as WebResult; + // if (dic == null) return new WebResult() { message = data, method = m.Replace("{host}", server), ok = true }; + // return dic; + //} + public string GetEXEConfig(string name) + { + try + { + return System.Configuration.ConfigurationManager.AppSettings[name].ToString(); + } + catch { } + return string.Empty; + } + + /// + /// 是否存在授权 + /// + /// + public bool IsExistCustomers(string uin, int softId) + { + return customers.ContainsKey(uin + "_" + softId); + } + + /// + /// 刷新授权 + /// + /// + /// + /// + public customer Refresh(string username, int softId) + { + customer cus = null; + string key = username + "_" + softId; + if (customers.ContainsKey(key)) + { + string errormsg = string.Empty; + cus = customers[key]; + for (int i = 0; i < 5; i++) + { + try + { + System.Threading.Thread.Sleep(2000); + var webResult = SendPack("refreshCustomer", new { token = cus.token }); + var dic = webResult.message as Dictionary; + if (dic["cardname"].ToString() != cus.cardname) throw new Exception("数据异常,请重新登录。"); + cus.token = dic["token"].ToString(); + cus.endTime = dic["endTime"].ToString(); + break; + } + catch (Exception ex) + { + if (!ex.Message.Contains("授权到期") && i != 4) + { + System.Threading.Thread.Sleep(new Random().Next(1000 * 60 * 5, 1000 * 60 * 30)); + } + else + { + cus.token = string.Empty; + errormsg = ex.Message; + GrantEvent.Invoke(cus, errormsg); + break; + } + } + } + } + return cus; + } + + + public customer Login(string uin, string remark, int softId, string softKey) + { + if (string.IsNullOrWhiteSpace(remark)) + remark = string.Empty; + + customer c = null; + if (check_license_ip()) + { + c = new customer() { cardname = uin, endTime = DateTime.MaxValue.ToString("yyyy-MM-dd HH:mm:ss"), softId = softId, token = string.Empty }; + } + else + { + var webResult = SendPack("loginCustomer", new { softId = softId, cardname = uin, remark = remark }); + c = tea.Decrypt(webResult.message.ToString(), softKey); + if (c == null || string.IsNullOrEmpty(c.cardname)) + throw new Exception("登陆失败,无法与服务器正常通信!"); + } + customers[uin + "_" + softId] = c; + softs[softId] = softKey; + return c; + } + public void LoginOut(string username, int softId) + { + string key = username + "_" + softId; + if (customers.ContainsKey(key)) customers.Remove(key); + } + private Dictionary softs = new Dictionary(); + public static GrantClient Get() + { + if (_GrantClient == null) + _GrantClient = new GrantClient(); + return _GrantClient; + } + private static GrantClient _GrantClient { get; set; } + internal class XXTEA + { + public JavaScriptSerializer json = new JavaScriptSerializer(); + /// + /// 字符串转16进制字节数组 + /// + /// + /// + public byte[] strToToHexByte(string hexString) + { + hexString = hexString.Replace(" ", ""); + if ((hexString.Length % 2) != 0) + hexString += " "; + byte[] returnBytes = new byte[hexString.Length / 2]; + for (int i = 0; i < returnBytes.Length; i++) + returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); + return returnBytes; + } + /// + /// 字节数组转16进制字符串 + /// + /// + /// + public string byteToHexStr(byte[] bytes) + { + string returnStr = ""; + if (bytes != null) + { + for (int i = 0; i < bytes.Length; i++) + { + returnStr += bytes[i].ToString("X2"); + } + } + return returnStr; + } + public Byte[] Encrypt(Byte[] Data, Byte[] Key) + { + if (Data.Length == 0) + { + return Data; + } + return ToByteArray(Encrypt(ToUInt32Array(Data, true), ToUInt32Array(Key, false)), false); + } + public string EncryptHex(string data, byte[] key) + { + var _data = Encrypt(Encoding.UTF8.GetBytes(data), key); + return byteToHexStr(_data); + } + public Dictionary DecryptDic(string data, string key) + { + return Decrypt>(data, strToToHexByte(key)); ; + } + public T Decrypt(string data, string key) + { + return Decrypt(data, strToToHexByte(key)); ; + } + public T Decrypt(string data, byte[] key) + { + + var _data = Decrypt(strToToHexByte(data.Trim()), key); + var json_data = Encoding.UTF8.GetString(_data); + // var dic = json.Deserialize>(json_data); + return ConvertToObj(json_data); + } + public T ConvertToObj(string json_data) + { + var dic = json.Deserialize>(json_data); + return ConvertToObj(dic); + } + public static T ConvertToObj(Dictionary dictionary) + { + var _obj = System.Activator.CreateInstance(); + PropertyInfo[] pros = _obj.GetType().GetProperties(); + foreach (var item in pros) + { + if (dictionary.ContainsKey(item.Name)) + { + if (item.PropertyType == typeof(String)) item.SetValue(_obj, dictionary[item.Name].ToString(), null); + else if (item.PropertyType == typeof(Double)) item.SetValue(_obj, Double.Parse(dictionary[item.Name].ToString()), null); + else if (item.PropertyType == typeof(Int32)) item.SetValue(_obj, Int32.Parse(dictionary[item.Name].ToString()), null); + else if (item.PropertyType == typeof(Int64)) item.SetValue(_obj, Int64.Parse(dictionary[item.Name].ToString()), null); + else if (item.PropertyType == typeof(Int16)) item.SetValue(_obj, Int16.Parse(dictionary[item.Name].ToString()), null); + else if (item.PropertyType == typeof(DateTime)) item.SetValue(_obj, DateTime.Parse(dictionary[item.Name].ToString()), null); + else item.SetValue(_obj, dictionary[item.Name], null); + } + } + return _obj; + } + public Byte[] Decrypt(Byte[] Data, Byte[] Key) + { + if (Data.Length == 0) + { + return Data; + } + return ToByteArray(Decrypt(ToUInt32Array(Data, false), ToUInt32Array(Key, false)), true); + } + + private UInt32[] Encrypt(UInt32[] v, UInt32[] k) + { + Int32 n = v.Length - 1; + if (n < 1) + { + return v; + } + if (k.Length < 4) + { + UInt32[] Key = new UInt32[4]; + k.CopyTo(Key, 0); + k = Key; + } + UInt32 z = v[n], y = v[0], delta = 0x9E3779B9, sum = 0, e; + Int32 p, q = 6 + 52 / (n + 1); + while (q-- > 0) + { + sum = unchecked(sum + delta); + e = sum >> 2 & 3; + for (p = 0; p < n; p++) + { + y = v[p + 1]; + z = unchecked(v[p] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)); + } + y = v[0]; + z = unchecked(v[n] += (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)); + } + return v; + } + private UInt32[] Decrypt(UInt32[] v, UInt32[] k) + { + Int32 n = v.Length - 1; + if (n < 1) + { + return v; + } + if (k.Length < 4) + { + UInt32[] Key = new UInt32[4]; + k.CopyTo(Key, 0); + k = Key; + } + UInt32 z = v[n], y = v[0], delta = 0x9E3779B9, sum, e; + Int32 p, q = 6 + 52 / (n + 1); + sum = unchecked((UInt32)(q * delta)); + while (sum != 0) + { + e = sum >> 2 & 3; + for (p = n; p > 0; p--) + { + z = v[p - 1]; + y = unchecked(v[p] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)); + } + z = v[n]; + y = unchecked(v[0] -= (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z)); + sum = unchecked(sum - delta); + } + return v; + } + private UInt32[] ToUInt32Array(Byte[] Data, Boolean IncludeLength) + { + Int32 n = (((Data.Length & 3) == 0) ? (Data.Length >> 2) : ((Data.Length >> 2) + 1)); + UInt32[] Result; + if (IncludeLength) + { + Result = new UInt32[n + 1]; + Result[n] = (UInt32)Data.Length; + } + else + { + Result = new UInt32[n]; + } + n = Data.Length; + for (Int32 i = 0; i < n; i++) + { + Result[i >> 2] |= (UInt32)Data[i] << ((i & 3) << 3); + } + return Result; + } + private Byte[] ToByteArray(UInt32[] Data, Boolean IncludeLength) + { + Int32 n; + if (IncludeLength) + { + n = (Int32)Data[Data.Length - 1]; + } + else + { + n = Data.Length << 2; + } + Byte[] Result = new Byte[n]; + for (Int32 i = 0; i < n; i++) + { + Result[i] = (Byte)(Data[i >> 2] >> ((i & 3) << 3)); + } + return Result; + } + + /// + /// 加密 + /// + /// + /// + public string Encrypt(string Target) + { + return Encrypt(Target, string.Empty); + } + public string Encrypt(string Target, string Key) + { + if (0 == Key.Length) + Key = "1234567890abcdef"; + System.Text.Encoding encoder = System.Text.Encoding.UTF8; + Byte[] data = Encrypt(encoder.GetBytes(Target), encoder.GetBytes(Key)); + return System.Convert.ToBase64String(data); + + } + + /// + /// 解密 + /// + /// + /// + public string Decrypt(string Target) + { + return Decrypt(Target, string.Empty); + } + public string Decrypt(string Target, string Key) + { + if (0 == Key.Length) + Key = "1234567890abcdef"; + System.Text.Encoding encoder = System.Text.Encoding.UTF8; + return encoder.GetString(Decrypt(System.Convert.FromBase64String(Target), encoder.GetBytes(Key))); + + } + + + + } + } +} diff --git a/类库/Grant.Framework/GrantInfo.cs b/类库/Grant.Framework/GrantInfo.cs new file mode 100644 index 0000000..c70a65e --- /dev/null +++ b/类库/Grant.Framework/GrantInfo.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Grant.Framework +{ + public class GrantInfo + { + /// + /// 软件标题 + /// + public string Title { get; set; } + + /// + /// 软件主图 + /// + public string Pict { get; set; } + + /// + /// 付款链接 + /// + public string PayURL { get; set; } + + public Image GetImage() + { + if (!string.IsNullOrEmpty(Pict)) + { + return CsharpHttpHelper.HttpExtend.ToImage(Pict); + } + return null; + } + } +} diff --git a/类库/Grant.Framework/LoginCard.Designer.cs b/类库/Grant.Framework/LoginCard.Designer.cs new file mode 100644 index 0000000..2ae1dd9 --- /dev/null +++ b/类库/Grant.Framework/LoginCard.Designer.cs @@ -0,0 +1,223 @@ +namespace Grant.Framework +{ + partial class LoginCard + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.checkBox2 = new System.Windows.Forms.CheckBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.linkLabel3 = new System.Windows.Forms.LinkLabel(); + this.timer1 = new System.Windows.Forms.Timer(); + this.button1 = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // checkBox2 + // + this.checkBox2.AutoSize = true; + this.checkBox2.Location = new System.Drawing.Point(218, 274); + this.checkBox2.Name = "checkBox2"; + this.checkBox2.Size = new System.Drawing.Size(74, 18); + this.checkBox2.TabIndex = 4; + this.checkBox2.Text = "记住帐号"; + this.checkBox2.UseVisualStyleBackColor = true; + this.checkBox2.CheckedChanged += new System.EventHandler(this.checkBox2_CheckedChanged); + // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(97, 274); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(74, 18); + this.checkBox1.TabIndex = 3; + this.checkBox1.Text = "自动登录"; + this.checkBox1.UseVisualStyleBackColor = true; + // + // linkLabel2 + // + this.linkLabel2.AutoSize = true; + this.linkLabel2.Location = new System.Drawing.Point(307, 187); + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.Size = new System.Drawing.Size(55, 14); + this.linkLabel2.TabIndex = 16; + this.linkLabel2.TabStop = true; + this.linkLabel2.Text = "忘记密码"; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(96, 183); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(196, 22); + this.textBox2.TabIndex = 2; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(307, 142); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(55, 14); + this.linkLabel1.TabIndex = 14; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "注册账号"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(96, 138); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(196, 22); + this.textBox1.TabIndex = 1; + this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown); + this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(49, 187); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(43, 14); + this.label2.TabIndex = 12; + this.label2.Text = "密码:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(49, 142); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 14); + this.label1.TabIndex = 11; + this.label1.Text = "用户:"; + // + // pictureBox1 + // + this.pictureBox1.Location = new System.Drawing.Point(16, 12); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(380, 100); + this.pictureBox1.TabIndex = 10; + this.pictureBox1.TabStop = false; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(37, 234); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(55, 14); + this.label3.TabIndex = 20; + this.label3.Text = "机器码:"; + this.label3.Click += new System.EventHandler(this.label3_Click); + // + // textBox3 + // + this.textBox3.Font = new System.Drawing.Font("宋体", 7.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.textBox3.Location = new System.Drawing.Point(96, 232); + this.textBox3.Name = "textBox3"; + this.textBox3.ReadOnly = true; + this.textBox3.Size = new System.Drawing.Size(196, 19); + this.textBox3.TabIndex = 21; + // + // linkLabel3 + // + this.linkLabel3.AutoSize = true; + this.linkLabel3.Location = new System.Drawing.Point(307, 234); + this.linkLabel3.Name = "linkLabel3"; + this.linkLabel3.Size = new System.Drawing.Size(67, 14); + this.linkLabel3.TabIndex = 22; + this.linkLabel3.TabStop = true; + this.linkLabel3.Text = "复制机器码"; + this.linkLabel3.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel3_LinkClicked); + // + // timer1 + // + this.timer1.Interval = 1000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // button1 + // + this.button1.Location = new System.Drawing.Point(96, 314); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(209, 35); + this.button1.TabIndex = 23; + this.button1.Text = "登录"; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // LoginCard + // + this.AcceptButton = this.button1; + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(408, 377); + this.Controls.Add(this.button1); + this.Controls.Add(this.linkLabel3); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label3); + this.Controls.Add(this.checkBox2); + this.Controls.Add(this.checkBox1); + this.Controls.Add(this.linkLabel2); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label2); + this.Controls.Add(this.label1); + this.Controls.Add(this.pictureBox1); + this.Name = "LoginCard"; + this.Text = "登录"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LoginCard_FormClosing); + this.Load += new System.EventHandler(this.LoginCustomer_Load); + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.LoginCard_KeyDown); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.CheckBox checkBox2; + private System.Windows.Forms.CheckBox checkBox1; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.LinkLabel linkLabel3; + private System.Windows.Forms.Timer timer1; + private DevExpress.XtraEditors.SimpleButton button1; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/LoginCard.cs b/类库/Grant.Framework/LoginCard.cs new file mode 100644 index 0000000..fcc3f50 --- /dev/null +++ b/类库/Grant.Framework/LoginCard.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + internal partial class LoginCard : BaseForm + { + public LoginCard() + { + InitializeComponent(); + } + private int soft_type; + private string soft_key; + + public void Initialization(int soft_type, string soft_key) + { + this.soft_type = soft_type; + this.soft_key = soft_key; + if (string.IsNullOrEmpty(this.soft_key)) + { + this.checkBox1.Location = new Point(96, 229); + this.checkBox2.Location = new Point(224, 229); + this.button1.Location = new Point(96, 268); + this.Size = new Size(424, 372); + this.textBox3.Visible = false; + this.label3.Visible = false; + this.linkLabel3.Visible = false; + } + } + private void LoginCustomer_Load(object sender, EventArgs e) + { + + this.Icon = GrantClient.Get().Ico; + if (GrantClient.Get().About == null) throw new Exception("服务器繁忙,请稍后重试"); + this.pictureBox1.Image = CsharpHttpHelper.HttpExtend.Base64StringToImage(GrantClient.Get().About["logo"].ToString()); + this.textBox1.Text = GrantClient.Get().Config.GetValue("帐号信息", "帐号"); + this.textBox2.Text = GrantClient.Get().Config.GetValue("帐号信息", "密码"); + if (!string.IsNullOrEmpty(this.textBox2.Text)) + { + this.textBox2.Text = CsharpHttpHelper.HttpExtend.DESDecrypt(this.textBox2.Text, "12345678", "12378946"); + } + if (!string.IsNullOrEmpty(soft_key)) + { + var c = Computer.Instance(); + this.textBox3.Text = CsharpHttpHelper.HttpExtend.GetMD5String($"{c.ComputerName}-{c.CpuID}").ToUpper(); + } + this.checkBox1.Checked = GrantClient.Get().Config.GetValue("帐号信息", "自动登录").ToLower() == "false" ? false : true; + this.checkBox2.Checked = GrantClient.Get().Config.GetValue("帐号信息", "记住密码").ToLower() == "false" ? false : true; + + if (this.checkBox1.Checked && !string.IsNullOrEmpty(this.textBox1.Text) && !string.IsNullOrEmpty(this.textBox2.Text)) + { + if (!string.IsNullOrEmpty(this.soft_key) && string.IsNullOrEmpty(this.textBox3.Text)) return; + this.button1.Text = "点击取消-[5]秒后自动登录"; + timer1.Enabled = true; + } + + + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + + if (string.IsNullOrEmpty(this.textBox1.Text) || string.IsNullOrEmpty(this.textBox2.Text)) throw new Exception("请先填写帐号密码!"); + if (this.button1.Text.StartsWith("点击取消")) + { + timer1.Enabled = false; + this.button1.Text = "登录软件"; + } + else + { + GrantClient.Get().Login(this.textBox1.Text, this.textBox2.Text); + if (!string.IsNullOrEmpty(this.soft_key)) + { + var c = Computer.Instance(); + GrantClient.Get().Login(CsharpHttpHelper.HttpExtend.GetMD5String($"{c.ComputerName}-{c.CpuID}").ToUpper(), c.ComputerName, soft_type, soft_key); + } + + string pass = CsharpHttpHelper.HttpExtend.DESEncrypt(this.textBox2.Text, "12345678", "12378946"); + GrantClient.Get().Config.SetValue("帐号信息", "帐号", (this.checkBox1.Checked || this.checkBox2.Checked) ? this.textBox1.Text : string.Empty); + GrantClient.Get().Config.SetValue("帐号信息", "密码", this.checkBox1.Checked ? pass : string.Empty); + // GrantClient.Get().Config.SetValue("帐号信息", "卡号", (this.checkBox1.Checked || this.checkBox2.Checked)?this.textBox3.Text:string.Empty); + GrantClient.Get().Config.SetValue("帐号信息", "记住帐号", this.checkBox2.Checked.ToString()); + GrantClient.Get().Config.SetValue("帐号信息", "自动登录", this.checkBox1.Checked.ToString()); + + GrantClient.LoginPassMd5 = pass; + this.Close(); + } + + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + string text = string.Format("计算机:{0}\r\n机器码:{1}", Computer.Instance().ComputerName, this.textBox3.Text); + Clipboard.SetText(text); + MessageBox.Show($"计算机:{Computer.Instance().ComputerName}\r\n机器码:{this.textBox3.Text}\r\n\r\nCtrl+V 粘贴给软件客服授权!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + //if (string.IsNullOrEmpty(this.textBox1.Text) || string.IsNullOrEmpty(this.textBox2.Text)) throw new Exception("请先填写帐号密码!"); + //var web = GrantClient.Get().SendPack("create_cardname", new { username = this.textBox1.Text,userpass = this.textBox2.Text,softid = soft_type}); + //this.textBox3.Text = web.message.ToString(); + //GrantClient.Get().Config.SetValue("帐号信息", "卡号", (this.checkBox1.Checked || this.checkBox2.Checked) ? this.textBox3.Text : string.Empty); + //MessageBox.Show("请妥善保管您的卡号!","友情提示",MessageBoxButtons.OK,MessageBoxIcon.Information); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "请求错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void timer1_Tick(object sender, EventArgs e) + { + + this.Invoke(new Action(delegate + { + try + { + var reg = Regex.Match(this.button1.Text, @"^点击取消-\[(\d+)\]秒后自动登录$"); + if (reg.Success) + { + int number = int.Parse(reg.Groups[1].Value) - 1; + if (number < 0) + { + this.timer1.Enabled = false; + this.button1.Text = "登录"; + button1_Click(null, null); + + } + else + this.button1.Text = "点击取消-[" + number + "]秒后自动登录"; + + } + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + })); + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + this.Visible = false; + new RegistForm().ShowDialog(); + this.Visible = true; + } + + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + new SetPassword().ShowDialog(); + } + + private void LoginCard_FormClosing(object sender, FormClosingEventArgs e) + { + this.timer1.Stop(); + if (!GrantClient.Get().IsLogin) + System.Diagnostics.Process.GetCurrentProcess().Kill(); + if (!string.IsNullOrEmpty(this.soft_key) && !GrantClient.Get().IsLoginCustomer) + System.Diagnostics.Process.GetCurrentProcess().Kill(); + } + + private void label3_Click(object sender, EventArgs e) + { + + } + + private void checkBox2_CheckedChanged(object sender, EventArgs e) + { + + } + + private void LoginCard_KeyDown(object sender, KeyEventArgs e) + { + + } + + private void textBox1_KeyDown(object sender, KeyEventArgs e) + { + + } + + private void textBox1_KeyPress(object sender, KeyPressEventArgs e) + { + + + } + } +} diff --git a/类库/Grant.Framework/LoginCard.resx b/类库/Grant.Framework/LoginCard.resx new file mode 100644 index 0000000..1ebcfe3 --- /dev/null +++ b/类库/Grant.Framework/LoginCard.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + \ No newline at end of file diff --git a/类库/Grant.Framework/OnlineRenewalForm.Designer.cs b/类库/Grant.Framework/OnlineRenewalForm.Designer.cs new file mode 100644 index 0000000..900b278 --- /dev/null +++ b/类库/Grant.Framework/OnlineRenewalForm.Designer.cs @@ -0,0 +1,145 @@ +namespace Grant.Framework +{ + partial class OnlineRenewalForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button1 = new System.Windows.Forms.Button(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.comboBox1 = new System.Windows.Forms.ComboBox(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.button2); + this.groupBox1.Controls.Add(this.button1); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.comboBox1); + this.groupBox1.Location = new System.Drawing.Point(38, 33); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(372, 228); + this.groupBox1.TabIndex = 1; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // button2 + // + this.button2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button2.Location = new System.Drawing.Point(207, 162); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 23); + this.button2.TabIndex = 16; + this.button2.Text = " 取 消 "; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Location = new System.Drawing.Point(92, 162); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 17; + this.button1.Text = " 确 定 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(131, 59); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(176, 20); + this.textEdit1.TabIndex = 14; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(65, 62); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 11; + this.labelControl2.Text = "续费账号:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(65, 105); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 12; + this.labelControl1.Text = "续费类型:"; + // + // comboBox1 + // + this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox1.FormattingEnabled = true; + this.comboBox1.Items.AddRange(new object[] { + "月卡", + "年卡"}); + this.comboBox1.Location = new System.Drawing.Point(131, 102); + this.comboBox1.Name = "comboBox1"; + this.comboBox1.Size = new System.Drawing.Size(121, 22); + this.comboBox1.TabIndex = 13; + // + // OnlineRenewalForm + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.button2; + this.ClientSize = new System.Drawing.Size(448, 293); + this.Controls.Add(this.groupBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "OnlineRenewalForm"; + this.Text = "在线续费"; + this.Load += new System.EventHandler(this.OnlineRenewalForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.ComboBox comboBox1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button1; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/OnlineRenewalForm.cs b/类库/Grant.Framework/OnlineRenewalForm.cs new file mode 100644 index 0000000..2b46668 --- /dev/null +++ b/类库/Grant.Framework/OnlineRenewalForm.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class OnlineRenewalForm : BaseForm + { + public int type = 1; + public OnlineRenewalForm(string cardname) + { + InitializeComponent(); + textEdit1.Text = cardname; + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + type = comboBox1.SelectedIndex + 1; + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void button2_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.No; + } + + private void OnlineRenewalForm_Load(object sender, EventArgs e) + { + comboBox1.SelectedIndex = 1; + } + + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/OnlineRenewalForm.resx b/类库/Grant.Framework/OnlineRenewalForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Grant.Framework/OnlineRenewalForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Grant.Framework/Properties/AssemblyInfo.cs b/类库/Grant.Framework/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4c2c343 --- /dev/null +++ b/类库/Grant.Framework/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("License.Framework")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("License.Framework")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("2916c951-8bf2-4941-bf8d-ebc1e1a73758")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/类库/Grant.Framework/Properties/Resources.Designer.cs b/类库/Grant.Framework/Properties/Resources.Designer.cs new file mode 100644 index 0000000..a23bd7b --- /dev/null +++ b/类库/Grant.Framework/Properties/Resources.Designer.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace Grant.Framework.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Grant.Framework.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 充值 { + get { + object obj = ResourceManager.GetObject("充值", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap 加好友 { + get { + object obj = ResourceManager.GetObject("加好友", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/类库/Grant.Framework/Properties/Resources.resx b/类库/Grant.Framework/Properties/Resources.resx new file mode 100644 index 0000000..7245043 --- /dev/null +++ b/类库/Grant.Framework/Properties/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\充值.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\加好友.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/类库/Grant.Framework/Properties/licenses.licx b/类库/Grant.Framework/Properties/licenses.licx new file mode 100644 index 0000000..1b83fac --- /dev/null +++ b/类库/Grant.Framework/Properties/licenses.licx @@ -0,0 +1,3 @@ +DevExpress.XtraEditors.ProgressBarControl, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraGrid.GridControl, DevExpress.XtraGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/类库/Grant.Framework/RechargePointForm.Designer.cs b/类库/Grant.Framework/RechargePointForm.Designer.cs new file mode 100644 index 0000000..dc90950 --- /dev/null +++ b/类库/Grant.Framework/RechargePointForm.Designer.cs @@ -0,0 +1,153 @@ +namespace Grant.Framework +{ + partial class RechargePointForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.numericUpDown1 = new System.Windows.Forms.NumericUpDown(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Controls.Add(this.numericUpDown1); + this.groupBox1.Controls.Add(this.textBox1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Location = new System.Drawing.Point(30, 22); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(403, 220); + this.groupBox1.TabIndex = 0; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // simpleButton2 + // + this.simpleButton2.Location = new System.Drawing.Point(92, 155); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(83, 35); + this.simpleButton2.TabIndex = 4; + this.simpleButton2.Text = " 确 定 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(237, 155); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(83, 35); + this.simpleButton1.TabIndex = 5; + this.simpleButton1.Text = " 取 消 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // numericUpDown1 + // + this.numericUpDown1.Increment = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.numericUpDown1.Location = new System.Drawing.Point(137, 95); + this.numericUpDown1.Maximum = new decimal(new int[] { + 99999999, + 0, + 0, + 0}); + this.numericUpDown1.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.numericUpDown1.Name = "numericUpDown1"; + this.numericUpDown1.Size = new System.Drawing.Size(186, 22); + this.numericUpDown1.TabIndex = 2; + this.numericUpDown1.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(137, 55); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(186, 22); + this.textBox1.TabIndex = 1; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(71, 99); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(60, 14); + this.labelControl2.TabIndex = 0; + this.labelControl2.Text = "充值金额:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(71, 59); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(60, 14); + this.labelControl1.TabIndex = 0; + this.labelControl1.Text = "充值账号:"; + // + // RechargePointForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(461, 271); + this.Controls.Add(this.groupBox1); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "RechargePointForm"; + this.Text = "积分充值"; + this.Load += new System.EventHandler(this.RechargePointForm_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private System.Windows.Forms.TextBox textBox1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private System.Windows.Forms.NumericUpDown numericUpDown1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/RechargePointForm.cs b/类库/Grant.Framework/RechargePointForm.cs new file mode 100644 index 0000000..f55c2dd --- /dev/null +++ b/类库/Grant.Framework/RechargePointForm.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class RechargePointForm : BaseForm + { + public RechargePointForm(string username) + { + InitializeComponent(); + textBox1.Text = username; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.No; + } + + public string username = string.Empty; + public int point = 0; + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox1.Text)) throw new Exception("请填写充值账户!"); + username = textBox1.Text.Trim(); + point = (int)(numericUpDown1.Value * 100m); + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + } + + private void RechargePointForm_Load(object sender, EventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/RechargePointForm.resx b/类库/Grant.Framework/RechargePointForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Grant.Framework/RechargePointForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Grant.Framework/RegistForm.Designer.cs b/类库/Grant.Framework/RegistForm.Designer.cs new file mode 100644 index 0000000..ed3d993 --- /dev/null +++ b/类库/Grant.Framework/RegistForm.Designer.cs @@ -0,0 +1,255 @@ +namespace Grant.Framework +{ + partial class RegistForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.textBox3 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.button1 = new System.Windows.Forms.Button(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.pictureBox2 = new System.Windows.Forms.PictureBox(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label7 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label8 = new System.Windows.Forms.Label(); + this.textBox5 = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit(); + this.SuspendLayout(); + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(120, 262); + this.textBox3.Name = "textBox3"; + this.textBox3.PasswordChar = '*'; + this.textBox3.Size = new System.Drawing.Size(175, 21); + this.textBox3.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(73, 267); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(41, 12); + this.label3.TabIndex = 33; + this.label3.Text = "确认:"; + // + // button1 + // + this.button1.BackColor = System.Drawing.Color.Transparent; + this.button1.Font = new System.Drawing.Font("微软雅黑", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.button1.Location = new System.Drawing.Point(101, 405); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(207, 36); + this.button1.TabIndex = 32; + this.button1.Text = "注册"; + this.button1.UseVisualStyleBackColor = false; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(120, 219); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(175, 21); + this.textBox2.TabIndex = 2; + // + // textBox4 + // + this.textBox4.Location = new System.Drawing.Point(120, 176); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(175, 21); + this.textBox4.TabIndex = 1; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(73, 226); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(41, 12); + this.label2.TabIndex = 25; + this.label2.Text = "密码:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(61, 179); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(53, 12); + this.label4.TabIndex = 24; + this.label4.Text = "用户名:"; + this.label4.Click += new System.EventHandler(this.label4_Click); + // + // pictureBox2 + // + this.pictureBox2.Location = new System.Drawing.Point(12, 50); + this.pictureBox2.Name = "pictureBox2"; + this.pictureBox2.Size = new System.Drawing.Size(380, 100); + this.pictureBox2.TabIndex = 23; + this.pictureBox2.TabStop = false; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.ForeColor = System.Drawing.Color.Red; + this.label5.Location = new System.Drawing.Point(312, 183); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(11, 12); + this.label5.TabIndex = 38; + this.label5.Text = "*"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.ForeColor = System.Drawing.Color.Red; + this.label6.Location = new System.Drawing.Point(312, 226); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(11, 12); + this.label6.TabIndex = 39; + this.label6.Text = "*"; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.ForeColor = System.Drawing.Color.Red; + this.label7.Location = new System.Drawing.Point(312, 269); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(11, 12); + this.label7.TabIndex = 40; + this.label7.Text = "*"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(61, 314); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(53, 12); + this.label1.TabIndex = 41; + this.label1.Text = "手机号:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(120, 311); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(175, 21); + this.textBox1.TabIndex = 4; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.ForeColor = System.Drawing.Color.Gray; + this.label8.Location = new System.Drawing.Point(313, 361); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(41, 12); + this.label8.TabIndex = 43; + this.label8.Text = "可不填"; + // + // textBox5 + // + this.textBox5.Location = new System.Drawing.Point(120, 357); + this.textBox5.Name = "textBox5"; + this.textBox5.Size = new System.Drawing.Size(175, 21); + this.textBox5.TabIndex = 5; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(61, 361); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(53, 12); + this.label9.TabIndex = 44; + this.label9.Text = "推荐人:"; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.ForeColor = System.Drawing.Color.Red; + this.label10.Location = new System.Drawing.Point(312, 316); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(11, 12); + this.label10.TabIndex = 46; + this.label10.Text = "*"; + // + // RegistForm + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(404, 460); + this.Controls.Add(this.label10); + this.Controls.Add(this.textBox5); + this.Controls.Add(this.label9); + this.Controls.Add(this.label8); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.Controls.Add(this.label7); + this.Controls.Add(this.label6); + this.Controls.Add(this.label5); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label3); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.textBox4); + this.Controls.Add(this.label2); + this.Controls.Add(this.label4); + this.Controls.Add(this.pictureBox2); + this.Name = "RegistForm"; + this.Text = "注册"; + this.Load += new System.EventHandler(this.RegistForm_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.PictureBox pictureBox2; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.TextBox textBox5; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/RegistForm.cs b/类库/Grant.Framework/RegistForm.cs new file mode 100644 index 0000000..47a26ad --- /dev/null +++ b/类库/Grant.Framework/RegistForm.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class RegistForm : BaseForm + { + public RegistForm() + { + InitializeComponent(); + } + + private void RegistForm_Load(object sender, EventArgs e) + { + this.Icon = Grant.Framework.GrantClient.Get().Ico; + this.pictureBox2.Image = CsharpHttpHelper.HttpExtend.Base64StringToImage(GrantClient.Get().About["logo"].ToString()); + } + + public string username, userpass; + + private void label4_Click(object sender, EventArgs e) + { + + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (this.textBox2.Text != this.textBox3.Text) throw new Exception("您两次填写的密码不一致。"); + var result = GrantClient.Get().SendPack("registAccounts", + new + { + username = this.textBox4.Text.Trim(), + userpass = this.textBox2.Text.Trim(), + phone = this.textBox1.Text.Trim(), + friendName = this.textBox5.Text + }); + + username = this.textBox4.Text; + userpass = this.textBox2.Text; + MessageBox.Show("恭喜您,已经注册成功!","注册成功",MessageBoxButtons.OK,MessageBoxIcon.Information); + this.Close(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } +} diff --git a/类库/Grant.Framework/RegistForm.resx b/类库/Grant.Framework/RegistForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/Grant.Framework/RegistForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/Grant.Framework/ReplaceAuthorizeForm.Designer.cs b/类库/Grant.Framework/ReplaceAuthorizeForm.Designer.cs new file mode 100644 index 0000000..57c9de3 --- /dev/null +++ b/类库/Grant.Framework/ReplaceAuthorizeForm.Designer.cs @@ -0,0 +1,149 @@ +namespace Grant.Framework +{ + partial class ReplaceAuthorizeForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textEdit2 = new DevExpress.XtraEditors.TextEdit(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.labelControl3); + this.groupBox1.Controls.Add(this.textEdit2); + this.groupBox1.Controls.Add(this.textEdit1); + this.groupBox1.Controls.Add(this.labelControl2); + this.groupBox1.Controls.Add(this.labelControl1); + this.groupBox1.Controls.Add(this.simpleButton2); + this.groupBox1.Controls.Add(this.simpleButton1); + this.groupBox1.Location = new System.Drawing.Point(50, 32); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(410, 214); + this.groupBox1.TabIndex = 2; + this.groupBox1.TabStop = false; + this.groupBox1.Text = " 基础信息 "; + // + // textEdit2 + // + this.textEdit2.Location = new System.Drawing.Point(171, 85); + this.textEdit2.Name = "textEdit2"; + this.textEdit2.Size = new System.Drawing.Size(158, 20); + this.textEdit2.TabIndex = 5; + // + // textEdit1 + // + this.textEdit1.Location = new System.Drawing.Point(171, 48); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Size = new System.Drawing.Size(158, 20); + this.textEdit1.TabIndex = 6; + // + // labelControl2 + // + this.labelControl2.Location = new System.Drawing.Point(98, 88); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(72, 14); + this.labelControl2.TabIndex = 3; + this.labelControl2.Text = "新授权账号:"; + // + // labelControl1 + // + this.labelControl1.Location = new System.Drawing.Point(97, 51); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(72, 14); + this.labelControl1.TabIndex = 4; + this.labelControl1.Text = "原授权账号:"; + // + // simpleButton2 + // + this.simpleButton2.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton2.Location = new System.Drawing.Point(251, 156); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(75, 23); + this.simpleButton2.TabIndex = 2; + this.simpleButton2.Text = " 取 消 "; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // simpleButton1 + // + this.simpleButton1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.simpleButton1.Location = new System.Drawing.Point(113, 156); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 23); + this.simpleButton1.TabIndex = 2; + this.simpleButton1.Text = " 确 定 "; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // labelControl3 + // + this.labelControl3.Appearance.ForeColor = System.Drawing.Color.Red; + this.labelControl3.Appearance.Options.UseForeColor = true; + this.labelControl3.Location = new System.Drawing.Point(76, 124); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(288, 14); + this.labelControl3.TabIndex = 7; + this.labelControl3.Text = "注:该操作是将原授权账号与新授权账号授权时间对调"; + // + // ReplaceAuthorizeForm + // + this.AcceptButton = this.simpleButton1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.simpleButton2; + this.ClientSize = new System.Drawing.Size(510, 278); + this.Controls.Add(this.groupBox1); + this.Name = "ReplaceAuthorizeForm"; + this.Text = "更换授权"; + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit2.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.TextEdit textEdit2; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.LabelControl labelControl3; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/ReplaceAuthorizeForm.cs b/类库/Grant.Framework/ReplaceAuthorizeForm.cs new file mode 100644 index 0000000..c0e3c62 --- /dev/null +++ b/类库/Grant.Framework/ReplaceAuthorizeForm.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class ReplaceAuthorizeForm : BaseForm + { + public string cardname1 = string.Empty; + public string cardname2 = string.Empty; + + public ReplaceAuthorizeForm(string cardname) + { + InitializeComponent(); + textEdit1.Text = cardname; + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.No; + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textEdit1.Text)) throw new Exception("对不起,原授权账号不能为空"); + if (string.IsNullOrWhiteSpace(textEdit2.Text)) throw new Exception("对不起,新授权账号不能为空"); + if (textEdit1.Text.Trim() == textEdit2.Text.Trim()) throw new Exception("对不起,更换授权时,两个参数不能一致"); + cardname1 = textEdit1.Text.Trim(); + cardname2 = textEdit2.Text.Trim(); + + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + } + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/ReplaceAuthorizeForm.resx b/类库/Grant.Framework/ReplaceAuthorizeForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Grant.Framework/ReplaceAuthorizeForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Grant.Framework/Resources/充值.jpg b/类库/Grant.Framework/Resources/充值.jpg new file mode 100644 index 0000000..1f33368 Binary files /dev/null and b/类库/Grant.Framework/Resources/充值.jpg differ diff --git a/类库/Grant.Framework/Resources/加好友.jpg b/类库/Grant.Framework/Resources/加好友.jpg new file mode 100644 index 0000000..a1eae29 Binary files /dev/null and b/类库/Grant.Framework/Resources/加好友.jpg differ diff --git a/类库/Grant.Framework/Resources/未命名_副本.png b/类库/Grant.Framework/Resources/未命名_副本.png new file mode 100644 index 0000000..1c7da2f Binary files /dev/null and b/类库/Grant.Framework/Resources/未命名_副本.png differ diff --git a/类库/Grant.Framework/Resources/评价助手Logo.png b/类库/Grant.Framework/Resources/评价助手Logo.png new file mode 100644 index 0000000..6cdf65e Binary files /dev/null and b/类库/Grant.Framework/Resources/评价助手Logo.png differ diff --git a/类库/Grant.Framework/SetOEM.Designer.cs b/类库/Grant.Framework/SetOEM.Designer.cs new file mode 100644 index 0000000..b0ce9d6 --- /dev/null +++ b/类库/Grant.Framework/SetOEM.Designer.cs @@ -0,0 +1,193 @@ +namespace Grant.Framework +{ + partial class SetOEM + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SetOEM)); + this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog(); + this.label4 = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.simpleButton2 = new DevExpress.XtraEditors.SimpleButton(); + this.buttonCheck = new UI.Framework.Controls.ButtonCheck(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // openFileDialog1 + // + this.openFileDialog1.FileName = "openFileDialog1"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.ForeColor = System.Drawing.Color.DarkGray; + this.label4.Location = new System.Drawing.Point(193, 188); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(164, 14); + this.label4.TabIndex = 8; + this.label4.Text = "长380px,宽100px png透明图"; + // + // pictureBox1 + // + this.pictureBox1.Location = new System.Drawing.Point(27, 215); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(380, 100); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureBox1.TabIndex = 7; + this.pictureBox1.TabStop = false; + // + // simpleButton1 + // + this.simpleButton1.Location = new System.Drawing.Point(97, 184); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(75, 23); + this.simpleButton1.TabIndex = 6; + this.simpleButton1.Text = "选择"; + this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(24, 184); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(67, 14); + this.label3.TabIndex = 4; + this.label3.Text = "启动画面:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(27, 140); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(380, 22); + this.textBox2.TabIndex = 3; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(24, 120); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(43, 14); + this.label2.TabIndex = 2; + this.label2.Text = "公告:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(27, 90); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(380, 22); + this.textBox1.TabIndex = 1; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(24, 64); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(43, 14); + this.label1.TabIndex = 0; + this.label1.Text = "标题:"; + // + // simpleButton2 + // + this.simpleButton2.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButton2.ImageOptions.Image"))); + this.simpleButton2.Location = new System.Drawing.Point(146, 343); + this.simpleButton2.Name = "simpleButton2"; + this.simpleButton2.Size = new System.Drawing.Size(147, 34); + this.simpleButton2.TabIndex = 9; + this.simpleButton2.Text = "保存OEM信息"; + this.simpleButton2.Click += new System.EventHandler(this.simpleButton2_Click); + // + // buttonCheck + // + this.buttonCheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCheck.BackColor = System.Drawing.Color.Transparent; + this.buttonCheck.Checked = true; + this.buttonCheck.CheckStyleX = UI.Framework.Controls.CheckStyle.style1; + this.buttonCheck.Cursor = System.Windows.Forms.Cursors.Hand; + this.buttonCheck.Location = new System.Drawing.Point(151, 24); + this.buttonCheck.Margin = new System.Windows.Forms.Padding(1); + this.buttonCheck.Name = "buttonCheck"; + this.buttonCheck.Size = new System.Drawing.Size(57, 24); + this.buttonCheck.TabIndex = 23; + // + // labelControl1 + // + this.labelControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.labelControl1.Location = new System.Drawing.Point(27, 29); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(108, 14); + this.labelControl1.TabIndex = 22; + this.labelControl1.Text = "是否显示充值界面:"; + // + // SetOEM + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(436, 399); + this.Controls.Add(this.buttonCheck); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.simpleButton2); + this.Controls.Add(this.label4); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.Name = "SetOEM"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "设置OEM"; + this.Load += new System.EventHandler(this.SetOEM_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.OpenFileDialog openFileDialog1; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label label4; + private DevExpress.XtraEditors.SimpleButton simpleButton2; + private UI.Framework.Controls.ButtonCheck buttonCheck; + private DevExpress.XtraEditors.LabelControl labelControl1; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/SetOEM.cs b/类库/Grant.Framework/SetOEM.cs new file mode 100644 index 0000000..4d47587 --- /dev/null +++ b/类库/Grant.Framework/SetOEM.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class SetOEM : BaseForm + { + private int sid = 1003; + AuthorizationManage auth; + private string userid = ""; + public SetOEM(AuthorizationManage auth, string userid = "") + { + InitializeComponent(); + this.auth = auth; + this.userid = userid; + } + private string logo = string.Empty; + private void SetOEM_Load(object sender, EventArgs e) + { + try + { + var content = auth.SendCoredata("get_oem", new { cid = userid, sid = sid }) as Dictionary; + //var content = data["content"] as Dictionary; + + this.buttonCheck.Checked = (content.ContainsKey("ispayform") && content["ispayform"].ToString() == "1"); + this.textBox1.Text = content.ContainsKey("title") ? content["title"].ToString() : "秒单客-返利机器人(官网:fanli.miaodanke.com)"; + this.textBox2.Text = content.ContainsKey("notice") ? content["notice"].ToString() : string.Empty; + logo = content.ContainsKey("logo") ? content["logo"].ToString().Replace("data:image/png;base64,", "") : string.Empty; + this.pictureBox1.Image = CsharpHttpHelper.HttpExtend.Base64StringToImage(logo); + + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + //this.Close(); + } + } + + private void simpleButton1_Click(object sender, EventArgs e) + { + try + { + OpenFileDialog dialog = new OpenFileDialog(); + dialog.Multiselect = false;//该值确定是否可以选择多个文件 + dialog.Title = "请选择文件夹"; //窗体标题 + dialog.Filter = "透明图片(*.png)|*.png"; //文件筛选 + //默认路径设置为我的电脑文件夹 + dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer); + if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + string file = dialog.FileName;//文件夹路径 + //Size picSize;float Wpx, Hpx; + //GetSize(file,out picSize,out Wpx,out Hpx); + //if (Wpx != 380 && Hpx != 100) throw new Exception("尺寸必须为:长380 宽100"); + var imgByte = File.ReadAllBytes(file); + this.logo = CsharpHttpHelper.HttpHelper.ByteToBase64(imgByte); + this.pictureBox1.Image = CsharpHttpHelper.HttpExtend.Base64StringToImage(this.logo); + } + + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + + } + } + + public static int GetSize(string FileName, out Size Size, out float Wpx, out float Hpx) + {//C#快速获取JPG图片大小及英寸分辨率 + Size = new Size(0, 0); + Wpx = 0; Hpx = 0; + int rx = 0; + if (!File.Exists(FileName)) return rx; + FileStream F_Stream = File.OpenRead(FileName); + int ff = F_Stream.ReadByte(); + int type = F_Stream.ReadByte(); + //if (ff != 0xff || type != 0xd8) + //{//非JPG文件 + // F_Stream.Close(); + // return rx; + //} + long ps = 0; + do + { + do + { + ff = F_Stream.ReadByte(); + if (ff < 0) //文件结束 + { + F_Stream.Close(); + return rx; + } + } while (ff != 0xff); + + do + { + type = F_Stream.ReadByte(); + } while (type == 0xff); + + //MessageBox.Show(ff.ToString() + "," + type.ToString(), F_Stream.Position.ToString()); + ps = F_Stream.Position; + switch (type) + { + case 0x00: + case 0x01: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + break; + case 0xc0: //SOF0段 + ps = F_Stream.ReadByte() * 256; + ps = F_Stream.Position + ps + F_Stream.ReadByte() - 2; //加段长度 + + F_Stream.ReadByte(); //丢弃精度数据 + //高度 + Size.Height = F_Stream.ReadByte() * 256; + Size.Height = Size.Height + F_Stream.ReadByte(); + //宽度 + Size.Width = F_Stream.ReadByte() * 256; + Size.Width = Size.Width + F_Stream.ReadByte(); + //后面信息忽略 + if (rx != 1 && rx < 3) rx = rx + 1; + break; + case 0xe0: //APP0段 + ps = F_Stream.ReadByte() * 256; + ps = F_Stream.Position + ps + F_Stream.ReadByte() - 2; //加段长度 + + F_Stream.Seek(5, SeekOrigin.Current); //丢弃APP0标记(5bytes) + F_Stream.Seek(2, SeekOrigin.Current); //丢弃主版本号(1bytes)及次版本号(1bytes) + int units = F_Stream.ReadByte(); //X和Y的密度单位,units=0:无单位,units=1:点数/英寸,units=2:点数/厘米 + + //水平方向(像素/英寸)分辨率 + Wpx = F_Stream.ReadByte() * 256; + Wpx = Wpx + F_Stream.ReadByte(); + if (units == 2) Wpx = (float)(Wpx * 2.54); //厘米变为英寸 + //垂直方向(像素/英寸)分辨率 + Hpx = F_Stream.ReadByte() * 256; + Hpx = Hpx + F_Stream.ReadByte(); + if (units == 2) Hpx = (float)(Hpx * 2.54); //厘米变为英寸 + //后面信息忽略 + if (rx != 2 && rx < 3) rx = rx + 2; + break; + + default: //别的段都跳过//////////////// + ps = F_Stream.ReadByte() * 256; + ps = F_Stream.Position + ps + F_Stream.ReadByte() - 2; //加段长度 + break; + } + if (ps + 1 >= F_Stream.Length) //文件结束 + { + F_Stream.Close(); + return rx; + } + F_Stream.Position = ps; //移动指针 + } while (type != 0xda); // 扫描行开始 + F_Stream.Close(); + return rx; + } + + private void simpleButton2_Click(object sender, EventArgs e) + { + try + { + var data = this.auth.SendCoredata("set_oem", new { sid = sid, cid = userid, content = CsharpHttpHelper.HttpHelper.ObjectToJson(new { title = this.textBox1.Text, notice = this.textBox2.Text, ispayform = (buttonCheck.Checked ? "1" : "0"), logo = this.logo }) }); + this.Close(); + } + catch (Exception ex) + { + BaseForm.ShowError(ex); + } + } + } +} diff --git a/类库/Grant.Framework/SetOEM.resx b/类库/Grant.Framework/SetOEM.resx new file mode 100644 index 0000000..86ec5a7 --- /dev/null +++ b/类库/Grant.Framework/SetOEM.resx @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 109, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAQXBwbHk7T0s7Q2hlY2s7QmFycztSaWJib247ZGPIaAAACrBJREFUWEeVVwtQlccZXdu82jyaNmNr + 0zTpREBBBURRFEEMrysQlEReakAUH4ii4BtBERFRQOSN4AUFQZP4BARBAQmgiIkoaAQEL29RQUTBTpzM + nH7fwkVN03a6M2d2//2//c75zu7+XMT2ZEuxQ2kldh6yFqEZCrEnUyHCj80Wkd/aiKiTNiL6tI2IzbYV + 8Tm2IiHPTlAb8d8Qm6sQ+7OtRNQpSxFx3EKEfW0uQrNmieAMM7E9zVQEpJiILYnGYmPcdAqnti3ZQrQ/ + PSw6nqaLzv4McW/giETXQCYhS9x/lsVhaoLfEH5LeI3w+i/Acwx+z3Ej2p9miranR0TrkwzR3JcuVI8P + ibu9aaLxkVKsj5tGIdQCDphT0CEpoKN/UESnFJHJr9XEkjQ0w9wg+rQiOD5/dkViwexrSYU2PydfsPk5 + Id+6Oj7P+tK+ExYh2w+aTKbYNzieIIW09pGAx+nirlpAT6pYH2tEr6gFJH1GClNF25M0coKE9JMbBGrq + il8PyzR3is62bkgtmocLNzegtnMf6h/EoWvgqET9g3iai0Rh7TocPP8FIk+ZN+w4ZLKA1r5JkEKah8ib + HqWKOz0HxbqYIQH+CWaipS+ZRKSQiIMkQsnTsupNMdNHh39jUZlRMh817eHo6FeisTcStx4G4+bDbaju + 2oBrXetR8yAQtQ+2o6EnAq1PlLhOsYeLXbDrqGmVZ6DuWMrFjkg3GntSxJ3uZOEXM5UeqW2ON6G9SaQ9 + SiIhB3iKyV/zT5phufdri0fFtzZB1ReLG/e3oqpjDa52MtZKfH+Pxz6o6lyNyvZVuNTmjYpWL1zt2ICG + RzEorNmAXVkzH/mET7KhnOyGFFHfnSR89xvSkNrGWGPR9DiWRMTxoyTfGD3NKuIbq5+uqoKpsm24REkv + txHaVxLRSlzpGOzVuNzuReQrUN66DN81e6JUtRjFTR74ocMflxuDEZo56/nKUP1hEXUPE8SaKD4q1Hyj + porG3igeStuX75g4dme6WfdV1TZcaV+DsuYlEuUtnkSwFBVtni+Bnlt5nmIIpc0eKFG5o+iuGxLzFVi8 + Uwdnazxw6U4QApXGPc5rxk4gDrkdPpGTmFOIpbt0RcOjcB6yPW9sSTK6lHeN7VyJoqaFKLn7FS5Swosq + N3zX4k5Y9KJvdkdpixsRuxHxVyhWLcSpakd4hugiMNYPMRlRWBIyAQV1S3Dm6mr4RU+qJI53CHwwuWAh + vgocx5203mevwYKIrxW0134ouOOEQsKFRheJoiZXqsyVSOYTGWOBHDN4/gK9Tz5vDdcNU3CioBB1qm40 + qJow13c0EgotUaZai91HrLAocJwHcb1F4IKFWBigzR0/vLkuxrDh/M1VyK93xNk6B+TVO+Bcw5ck5EsU + NM6j3hHnGxkkjvsm6hk03n/aDIv8FSj/vh5t95+ip68Hq3fb4vjl5cj50RknauyRV+2DVeH6jcT1HmHY + BVm9k6+WIijVjOwmu27aIvu2HXJuf47c2/bIrZtDoggNcyXONThQz6BnEhmSZQS3Lda4fL0J97qfoffJ + Y6zYaY3MUg/k3HLCsWprZP1ghXN1ixF40AxzvTTsiVN9K6SAN1w3jY2KO+NCgbNxvMYaJ2sVOHVrNk4T + sm/bEGxJiB0JIlF1jMHx5hQDeGy1xZUaFToePkP3414sC7LCgTwXnPnREUerLZF5zRIZVeZIv6JAfLYL + XDaM5Sv3NoG/sFLFW/O3aFcoi1wRd9EECd/NICHmJMQSx65ZwF85kcZWJEYhBTHOEHYcmYxFW+1QVdOM + ju4B9D79CcFJXtiutJS2Z1Vb4AjlOVQ5CwmllLd0JtJKFoC4+DDyNgwL+L3rFu3utDJHRBdNw/5iI8QU + T0fCxRlYsE0THgE2cNs+DhlXZ+F4rSVO1FohMnsanNfPQEV1A9ofDqCr558ovHwCHkG6yK9zk8RpV8xw + oMwEcSUzEFMynWCMQxVOWLhVp4c4/0jgcyBVvO2yWft5SrkdIi8YYt+FqRILgzTgt3cRvr/VjqNns+G8 + aTwSimYg9rwxHHzHIa+sEq33+6WA1q4WOK6bgG+r3JFcYYbEUlPEl84gR40l+f4iI8ppBGWFPRb46zwn + zj8R+K+oFPCO80bt5wkXzRFeaIjI81MQljsV9ms/QeX1K7hH1d3t6MPpC8WYt04X9ms0cCz/LFSdfWh7 + 0I/uvmfwC5+HyBP2SC7/7CViY3KTHCVXuaDI84YkzAKuVCxxfvCKgHnrxnbvO2eKiMLJiCgwJNtmQlnk + THZNRld3Bzp7nqGJCPPKqpD4Df1RautFK5HzwTtVpKSPz0SkV86hdWz1dERLYiNEFZGbVFAEkTOiCmbC + acNY3oJhAXwG3nZYPeZS6HETRJwzxN78SQgvmISkMkv6pM7D8hAzPOh9gDay+m7nE/yo6kELWd9MaOlq + w9y1mkgtdRokVRMPbSNXzcScL5IK233CFA6rtaqIc/gMsIDf2S7XiNmcMp0CDRGWb4A9BQZyUXKZFfad + ssOavTbo6++XVTNxc9dTuTW7lV4IUJqR5TOHSbli3sZI2s5wcjS8YDIVZUDuTsGWg8aw8RydRJyv3II3 + Z7l8Yu8RpE/BU7H7rD7C8hgTpRsp5QqEHrVCYMJ8PO5/BhWRM67XV8LFXwOpFXNkpbJaJhzCXiqACwnL + nyhzRVDuxTv0YTLvY2fi5O8Acw9+CQl/+NxLsykwy0AKCD2rNySEFlMCZbktAtJMEZ7ujb6Bn2hLBrBq + jyWic+nmSIuZ8AXpHqo4LI8xcThP4NFJsPfWUhHXnwn8JRwhbJZrUj/4LSAXli4MnIA9eZMRkqOLXbm6 + UkjoUII0ukLrE42QfDIAeeXpWBmhh/iSWZJskHAirR2sNoyLIBdDc/Vknr2U023bBJg6fuxNXGr7R4jZ + yzSoly7wiXzfZpnG1bWJRJ6jL0WE0OIXQvRw+NJc+EQb4IuNHyO+wEZWt5sImUyOmZhjh9bJtbn68E3S + BeW+Thwvquem8NQQ+bdY1OBh1DcfZWS/aswj/yO62EkCdmZPkL10ZEhQ+mUHnKxeRKd66iAJEe4aqpTB + seo1ITl68M/Uwxxvzd7xJiNNiYN/DwxWz816iYbIrfUSObXL+ZHPwjtG9h99OddH6/n6NB3sODMewWdI + RPb4QTESlJjxChGLHRJNCKY4Xsc5HNZoPTe0/dCVcr9PYKdHKJZK5/9NgHor3pti9zdHuxWaj73jtKUI + NYJJyKsgIklG7+n55dhV8dqwW6HVZ6j4cD7l5E8v/xwbkUN81kvk2VMLWP6yALWId7WNRk6xXvxptdNm + Law/pIMgShp0Zhx2nCYCAj8zkZx/aY5jnbeMgZXH6Btahh/w/2BcuSRnMBfzysYDnmCwEGpqEbwdfFdH + Gs35yNt68egWB19NLNkzBn5KbWw8rIPtp8ch6NQ4bEzXgV+qDjzpnYOvFqwXa7Qa2f99Na0dRXiXIG1n + qHl+IcBryAXeCi+eVovgw8Inlq/NX/Q/G/W5qfM/4i3cR9+wdP+0ng4wGJbuo+st3D+9Yer8SYLerFFz + KPavBK6af/txIcPkvyrgP4Hay0LYQnaEE48kcHUfDoHHfL34+86nnEUPE/9absb/09RC+KpyYraUBTER + g8c8x+84Rh3/P5oQ/wKtHXLtkLLsUQAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/类库/Grant.Framework/SetPassword.Designer.cs b/类库/Grant.Framework/SetPassword.Designer.cs new file mode 100644 index 0000000..81a7bdd --- /dev/null +++ b/类库/Grant.Framework/SetPassword.Designer.cs @@ -0,0 +1,186 @@ +namespace Grant.Framework +{ + partial class SetPassword + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.label1 = new System.Windows.Forms.Label(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox3 = new System.Windows.Forms.TextBox(); + this.label4 = new System.Windows.Forms.Label(); + this.textBox4 = new System.Windows.Forms.TextBox(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.label5 = new System.Windows.Forms.Label(); + this.textBox5 = new System.Windows.Forms.TextBox(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(39, 74); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(53, 12); + this.label1.TabIndex = 0; + this.label1.Text = "用户名:"; + // + // textBox1 + // + this.textBox1.Location = new System.Drawing.Point(101, 70); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(175, 21); + this.textBox1.TabIndex = 1; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(39, 130); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(53, 12); + this.label2.TabIndex = 2; + this.label2.Text = "新密码:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(101, 126); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(175, 21); + this.textBox2.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(39, 186); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(53, 12); + this.label3.TabIndex = 4; + this.label3.Text = "确 认:"; + // + // textBox3 + // + this.textBox3.Location = new System.Drawing.Point(101, 182); + this.textBox3.Name = "textBox3"; + this.textBox3.PasswordChar = '*'; + this.textBox3.Size = new System.Drawing.Size(175, 21); + this.textBox3.TabIndex = 5; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(39, 242); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(53, 12); + this.label4.TabIndex = 6; + this.label4.Text = "手机号:"; + // + // textBox4 + // + this.textBox4.Location = new System.Drawing.Point(101, 238); + this.textBox4.Name = "textBox4"; + this.textBox4.Size = new System.Drawing.Size(175, 21); + this.textBox4.TabIndex = 7; + // + // linkLabel1 + // + this.linkLabel1.AutoSize = true; + this.linkLabel1.Location = new System.Drawing.Point(211, 298); + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.Size = new System.Drawing.Size(65, 12); + this.linkLabel1.TabIndex = 13; + this.linkLabel1.TabStop = true; + this.linkLabel1.Text = "获取验证码"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(39, 298); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(53, 12); + this.label5.TabIndex = 14; + this.label5.Text = "验证码:"; + // + // textBox5 + // + this.textBox5.Location = new System.Drawing.Point(101, 294); + this.textBox5.Name = "textBox5"; + this.textBox5.Size = new System.Drawing.Size(79, 21); + this.textBox5.TabIndex = 15; + this.textBox5.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.textBox5.TextChanged += new System.EventHandler(this.textBox5_TextChanged); + // + // timer1 + // + this.timer1.Interval = 1000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // SetPassword + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(328, 352); + this.Controls.Add(this.textBox5); + this.Controls.Add(this.label5); + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.textBox4); + this.Controls.Add(this.label4); + this.Controls.Add(this.textBox3); + this.Controls.Add(this.label3); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.label1); + this.Name = "SetPassword"; + this.Text = "设置密码"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SetPassword_FormClosing); + this.Load += new System.EventHandler(this.SetPassword_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textBox3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.TextBox textBox4; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.TextBox textBox5; + private System.Windows.Forms.Timer timer1; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/SetPassword.cs b/类库/Grant.Framework/SetPassword.cs new file mode 100644 index 0000000..c3eaac7 --- /dev/null +++ b/类库/Grant.Framework/SetPassword.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class SetPassword : BaseForm + { + public SetPassword() + { + InitializeComponent(); + } + + private void SetPassword_Load(object sender, EventArgs e) + { + + } + string kName = Guid.NewGuid().ToString(); + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + try + { + if(this.textBox2.Text != this.textBox3.Text) throw new Exception("两次密码输入不一致,请检查!"); + if (this.textBox2.Text.Length < 6) throw new Exception("密码过于简单,请重新输入!"); + var webResult = GrantClient.Get().SendPack("forgetPass", new { kName = kName, username = this.textBox1.Text, phone = this.textBox4.Text, code = "", userpass = this.textBox2.Text }); + MessageBox.Show(webResult.message.ToString(), "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + linkLabel1.Enabled = false; + linkLabel1.Text = "获取验证码" + "(" + 299 + ")"; + this.timer1.Start(); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void textBox5_TextChanged(object sender, EventArgs e) + { + if (this.textBox5.Text.Trim().Length == 4) + { + try + { + var webResult = GrantClient.Get().SendPack("forgetPass", new { kName = kName, username = this.textBox1.Text, phone = this.textBox4.Text, code = this.textBox5.Text, userpass = this.textBox2.Text }); + MessageBox.Show(webResult.message.ToString(), "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + this.Close(); + } + catch (Exception ex) + { + this.textBox5.Clear(); + MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + } + + private void timer1_Tick(object sender, EventArgs e) + { + var reg = Regex.Match(linkLabel1.Text, @"获取验证码\((\d+)\)"); + if (reg.Success) + { + int number = int.Parse(reg.Groups[1].Value) - 1; + if (number <= 0) + { + linkLabel1.Text = "获取验证码"; + linkLabel1.Enabled = true; + } + else + { + linkLabel1.Text = "获取验证码" + "(" + number + ")"; + } + + } + } + + private void SetPassword_FormClosing(object sender, FormClosingEventArgs e) + { + this.timer1.Stop(); + } + } +} diff --git a/类库/Grant.Framework/SetPassword.resx b/类库/Grant.Framework/SetPassword.resx new file mode 100644 index 0000000..1f666f2 --- /dev/null +++ b/类库/Grant.Framework/SetPassword.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/Grant.Framework/UpdateDevForm.resx b/类库/Grant.Framework/UpdateDevForm.resx new file mode 100644 index 0000000..da86b5b --- /dev/null +++ b/类库/Grant.Framework/UpdateDevForm.resx @@ -0,0 +1,369 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + /9j/4AAQSkZJRgABAQEAYABgAAD/7gAOQWRvYmUAZAAAAAAB/+EKckV4aWYAAE1NACoAAAAIAAcBEgAD + AAAAAQABAAABGgAFAAAAAQAAAGIBGwAFAAAAAQAAAGoBKAADAAAAAQACAAABMQACAAAAIgAAAHIBMgAC + AAAAFAAAAJSHaQAEAAAAAQAAAKgAAADUAGADEgABAAAAYAMSAAEAAEFkb2JlIFBob3Rvc2hvcCBDQyAy + MDE5IChXaW5kb3dzKQAyMDE5OjExOjI5IDE4OjQ3OjMzAAADoAEAAwAAAAH//wAAoAIABAAAAAEAAAFK + oAMABAAAAAEAAACQAAAAAAAAAAYBAwADAAAAAQAGAAABGgAFAAAAAQAAASIBGwAFAAAAAQAAASoBKAAD + AAAAAQACAAACAQAEAAAAAQAAATICAgAEAAAAAQAACTgAAAAAAAAASAAAAAEAAABIAAAAAf/Y/+0ADEFk + b2JlX0NNAAL/7gAOQWRvYmUAZIAAAAAB/9sAhAAMCAgICQgMCQkMEQsKCxEVDwwMDxUYExMVExMYEQwM + DAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAQ0LCw0ODRAODhAUDg4OFBQODg4OFBEMDAwM + DBERDAwMDAwMEQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCABGAKADASIAAhEBAxEB/90A + BAAK/8QBPwAAAQUBAQEBAQEAAAAAAAAAAwABAgQFBgcICQoLAQABBQEBAQEBAQAAAAAAAAABAAIDBAUG + BwgJCgsQAAEEAQMCBAIFBwYIBQMMMwEAAhEDBCESMQVBUWETInGBMgYUkaGxQiMkFVLBYjM0coLRQwcl + klPw4fFjczUWorKDJkSTVGRFwqN0NhfSVeJl8rOEw9N14/NGJ5SkhbSVxNTk9KW1xdXl9VZmdoaWprbG + 1ub2N0dXZ3eHl6e3x9fn9xEAAgIBAgQEAwQFBgcHBgU1AQACEQMhMRIEQVFhcSITBTKBkRShsUIjwVLR + 8DMkYuFygpJDUxVjczTxJQYWorKDByY1wtJEk1SjF2RFVTZ0ZeLys4TD03Xj80aUpIW0lcTU5PSltcXV + 5fVWZnaGlqa2xtbm9ic3R1dnd4eXp7fH/9oADAMBAAIRAxEAPwDOhKETaltW/by9o4ShE2pbUrVaOEoR + NqW1K1WjhKETaltStVo4ShE2pbUrVaOEoRNqW1K1WjhKETaltStVo4ShE2pbUrVaOEoRNqW1K1WjhKET + altStVv/0K+xLYi7Eti3LeTtFsS2IuxLYlarRbEti3R0bAd0fHyG3v8AtWU6WEU3Pb/oG4zmVtc2v9bL + a2ZVv6Oz/BouX9X8H17asbMax2NS6y6t7XuM1AfaHtt9lexrn1t/4NRfecd1Z3I2/dbP3PPw8QAOgl80 + f03ndiWxbXTuisysGrItFjbMvKZjY22IDdX5Nz9w9zWVsu2/8JUrmV9U72YbPs7A/JF1gse6xoDqml/o + v2z6bXuaGfRRPMYxLhJo3SI8pnlDjjGxw8Wmp8v736TzOxLYtfp/Rbcvp12W2my17yKsJjCGgvAc+229 + 9g2Mx6mt/O+m/wDRfzuxaVf1a6c7Prwi3qEWViw5QZWccEt37PX2/T/soS5jHEkE7b0nHyeacRIAVKqs + 182zy2xLYtLpuBXk4mbmXh/o4lG9orMF1zv5mvVr/wC2tez6oWV4+U1n6bIaKTjPLwwbif1prmzt2tb/ + ADfqIyzwiakaN1/L/GW4+VzZI8cI2KJ8dOLp/W4PS8tsS2LRxsDFOa7Cz8k4l3qCmsMrNwdYXen6e6v2 + s9239I/2LSo6L0d3VbunerffZjVWOv3N9Joc0VlnpWAe/wCn7kpZ4R0NnTi0H6PmnHyuWYscIs8HqkL4 + /wB3h+d5zYlsWl0Xpo6ha51jXuxqKzbkeiJedD6dVTRu3W2P+gtGjoOB6dDcpuZXl3ZH2V9Ffo2Bj9vr + 7vUA2+jXT9O3/wADSnnhA0TqOysXK5csRKIHCboyNbPObEtiu9QxasfNupp3mljiK3WCHOaNN/0We3du + 2P2+9V9ieJAgEdRbBIGMjE7xJifoi2JbEXYlsRtFv//RnsS2I21Latm3juJDsS2I21LalauJ3sGx+R0W + 5ouw3XMrx6KTRvfYz3foa8n03h9eZ6rt1PpbPRyf0iFm4jrOnMwMbJfZn9NY5/UKA8zY3JPrZO930cnZ + b/O/+TWODaAWtssY0kFzWPc0EtO6t7msPufW731u/wAGo+kDzM6yZMnd/Ob3fSf6v+F3/wA7/hFXGEiR + PEN+IaOgfiEJYxEwlfB7ciJdPmuH9bi4Hax+pvZ0DHttFgbi5XoV/Zi1thb6LiHOdd+j9zrHb1C9vQB0 + DBD+n3uxBfb6VAeze1/v9R73l+x27+ssr9Jt2b3+nO70tx2buPU9L6Hqbfz0j6haGGx5rbq2ouJY0nlz + K/oMc5E4Bdgkeri0PT/vlsfiJEeExEv1Yh6h+n6f/G+GLp9KxrrukZdDMbNtGUSxz6Lam1bOHVBuTcz0 + 3Wu/R5L6qPVtYtuiuwdbxy6vPAFDQSHxgg7D7XY+/wDnv+t/TXGux63uDnNlzdWmToR+c39138tE3X/9 + yMj/ALfu/wDSqZkwSkZEEeq/xZcHxLHjhCJjK4CI0Ir0/wCK6XRb8ijpXUcSxrmMxmtucGe24P3NZY1r + neyt9fofo/8AhUWq3o+R0vq99mHkvba+h2Y2x9ZstcX/AKJzXNd6bPTd/wBD6CyB6gDg2yxof/OAPd7x + /wANr+m/64kPUDS0Pe1jo31tcQx0at9Sse2zZ+ZuT5YbkZXRJB0/weJih8Q4IRhw8QjCcPUOp4/b/wCn + 63Q6CLndT9PpeLW3Dc+t1gyWeo6mtn7lrHiuqx/6T0/538z/AEa0umdXszOs5Yrrxzjena+m1tRFrwws + ax1l3qH1K7f6nv8AYubLCZALmhzSx21xbuY76dVmwjfU/wDPrepN9Rhmux9TojdU5zDH7m6st9n8hKeE + SMje8REf99JWH4gcYgK0E5TmAI1UtoY3R6JflZGe/PdjOsfXSBswSzHraT7a3205V7K7W/Td7327LP8A + ArUqwRX09mFc67ErJty7uom1gspsc8envymn0rLcmmy/131/v/8ACrl30VWACxjXgcBwkf5qXot27DJY + CD6ZJLJaPTY70nH0/wBHX+jr9v6Ov2MQngMpWCANOn7q7D8RjCFTgZy9RuxGPrPFtw+lu/WH7U/q97sq + s1HQUtJDv0TfZU/cJ/nNr7FnbEVtYaIHGgEknQDa1vu/NY0bWN/MT7VNAcMRHsKaebL7mSc9fVIy131Q + 7EtiNtS2p1sfE//SvbUtqLtS2rWt4m0W1Lai7UtqVqtFtS2ou1LalarRbUtqLtS2pWq0W1Lai7UtqVqt + FtS2ou1LalarRbUtqLtS2pWq0W1Lai7UtqVqtFtS2ou1LalarRbUtqLtS2pWq3//09bRLReKJLUeHfa9 + EtF4okkp9r0S0XiiSSn2vRLReKJJKfa9EtF4okkp9r0S0XiiSSn2vRLReKJJKfa9EtF4okkp9r0S0Xii + SSn2vRLReKJJKf/Z/9sAQwACAgICAgICAgICAwICAgMEAwICAwQFBAQEBAQFBgUFBQUFBQYGBwcIBwcG + CQkKCgkJDAwMDAwMDAwMDAwMDAwM/9sAQwEDAwMFBAUJBgYJDQoJCg0PDg4ODg8PDAwMDAwPDwwMDAwM + DA8MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM/8AAEQgAkAFKAwERAAIRAQMRAf/EAB8AAAAHAQEB + AQEAAAAAAAAAAAQFAwIGAQAHCAkKC//EALUQAAIBAwMCBAIGBwMEAgYCcwECAxEEAAUhEjFBUQYTYSJx + gRQykaEHFbFCI8FS0eEzFmLwJHKC8SVDNFOSorJjc8I1RCeTo7M2F1RkdMPS4ggmgwkKGBmElEVGpLRW + 01UoGvLj88TU5PRldYWVpbXF1eX1ZnaGlqa2xtbm9jdHV2d3h5ent8fX5/c4SFhoeIiYqLjI2Oj4KTlJ + WWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/EAB8BAAICAwEBAQEBAAAAAAAAAAEAAgMEBQYHCAkKC//E + ALURAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaS + UyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0+PzhJSktMTU5PRldYWVpbXF1eX1RlZm + doaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq + +v/dAAQAKv/aAAwDAQACEQMRAD8A4txz6Lt+Vrdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdx + xtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdx + xtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdxxtbdx + xtbf/9Dj/DPom35Tt3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG + 1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG + 1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t//0eV+nn0Nb8n2708b + W3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3e + nja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja + 2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3//0ucenn0Hb8l2708b + W3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3e + nja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja + 2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3//04L6ftn0Bb8j270/ + bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja27 + 0/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja + 270/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ft + ja270/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbf/Uinpe2e+2/IVu9L2xtbd6Xtja270vbG1t3pe2Nrbv + S9sbW3el7Y2tu9L2xtbd6Xtja270vbG1t3pe2NrbvS9sbW3el7Y2tu9L2xtbd6Xtja270vbG1t3pe2Nr + bvS9sbW3el7Y2tu9L2xtbd6Xtja270vbG1t3pe2NrbvS9sbW3el7Y2tu9L2xtbd6Xtja270vbG1t3pe2 + NrbvS9sbW3el7Y2tu9L2xtbd6Xtja270vbG1t3pe2NrbvS9sbW3el7Y2tu9L2xtbd6Xtja270vbG1t3p + e2NrbvS9sbW3/9Uk9LPebfj23elja270sbW3elja270sbW3elja270sbW3elja22ISSABUk0AA642kEl + mXmj8uPO3kqK2n81eW7zRILxzHazXCAJI4HIqrKSCQN6Zh6XtHT6okYpiRHc7XtHsTXdnxEtRiMATQJ7 + /ggtA8j+bfNcGoXHlny5qGvx6UYhf/UIHuGjM3L06pGCx5cG6Dtk9RrsGnIGWYjfKzXJp0XZer1sZS0+ + KWQQq+EXV3Ww36HkxyS2khkkhmjaKWJiksTgqyspoQQdwQcyBIEWHBkDEkEUQs9LDbG05tvLHmC90ubW + 7PRL+70a3leC41WC3kkt45EVXZHlVSqkK4NCehymWqxRnwSkBI9CRfycvHodRkxHLDHKUASDIAkAgAmy + OWxCTenl1uJbOfMn5YeevJ+m2+seZfLV1o+mXcyW9tez8ODyyI0iqOLHcqjH6MwdN2nptTMwxTEiBdO4 + 7Q7B1+gxjLqMRhEmgTXMgnoe4Fg3pZnW6e000fy/rPmC8/R2haVd6xf+nJMLKyheeUpEvJ2CICaADKs2 + ox4Y8WSQiO8mnJ0ulzaqfBhgZyomogk0OewQVzY3NnPLa3lvJa3MDcZreZCkiMOzKwBB+eTjOMhYNhpy + QnjkYzBBHMHYj4KHpZK2Fu9LG1t3p42tpzrPljzB5dmFvr+iX+izsSEivreS3LU68fUVa/RlOHVYswvH + IS9xBcvV6HUaQ1mxygf6QI+/miPLPk/zF5x1F9J8saVNrOopC1w1pBx5iJCqs3xEbAsMjqdZi00ePLLh + F1bPs/s7U9oZDj08DOQF0K5bd/vQuveXNY8satd6Fr9hJper2Pp/W7GanOP1Y1lStCRujg/TksGpx54C + eM3E8j9jXrdJm0eU4c0eGcasHpYsfYUo9LLrcW3elja270sbW2aS/lr56g8vjzVN5V1GPy41ul0NZaEi + 3MMlOEnPpQ8hQ5hDtLTHL4QmOO6q97dvLsLXx0/5k4ZeFXFxdKPIsL9LM23UWnOkeWPMGvpevoeiX2sL + psay3/1K3knMKMeKs4jViAT3ynNqsWGuOQjfKzVuXpdDqNUJHDjlPh58IJq++koeB43aORSkiEq6MKEE + bEEHoRlokDuHFlcTR2IW+lhtFu9LG1t3pY2tu9LG1t3pY2tu9LG1t3pY2tu9LG1t3pY2tu9LG1t//9YJ + 6ee62/HFu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t9Ef8AON+kflZ5h83zeW/Pkctx5l1CW1m8 + h2Ua3vGZ7VLm4veb2ymJQiRIf3zAHotd85j2m1mp0+OJwmokES5daA5/Hk+if8D3s7s/W55jUi8gMTjF + y6cRly26R+p9V/nn5u/5xzm1i20P83tWv1v/ACtG0ot7Wz1uW3txfLG9ZZdOt5IeTKqEBm5KD0HLfjuy + 8uswXLT16v6vT3vqvtFp+ytXww11ng3246F95ht8/wBKZ/lHbfl7+XH5eeYvO6a1B5d8jeatVk1DR9a1 + GV7VI9MlZbbTyzXYV1Mn215jl8YqMPauqzazNGMhc4xANfzucuX6O5j7Odn6TsvS5MmM8OLJMyBJ5RNR + hvLffmL33YB5X/Kf/nFTztqTaP5S822/mjVkhe5lsrDXPrU/pIVV5WCFjQMwBJ7keOZ0/aDtLFH1Ch5x + dRi9i+wNTMiB4pc9shJ9/N8d/mx5d0Tyt+Y3mvy55eVk0jRrpLe1V5DKwIgjaQM53JDswPhnb9j6rJqd + LDJk+o3fzL5B7VaDD2f2llwYRUI1W984gnf32+2NYS9/I7/nFuS1gikg8y6rZrbyt+1Bfay9JGY7AG3j + cgbdUHXrnDGf8pdq3/Dxbf1Y/rr7X2Lwz7P+zhBsT4N/KeT/AIkyr4JprH5FPrv5FeXfKekaN5ft/PI0 + vT0m8walCI5Ld2KTXYSeKCWWpPJOm4NdjkcXbZx6+WWUpHGZHYHnzEdrA82ep9k46jsbHpoQxjOIQHFI + cjsZ+rhMt9wzD88/yr8w/mb5D8u+V9CvdPtL/SdVtr66mv5JY4Wjhs7m3YI0UMrFi8ykVUCld+2Y3Yfa + WPQ6iWXICQYkbVe5B6kdzn+1/YGftjQx0+ExEozEvUSBQEh0Ej17n53fmb+UvmH8qb7S9P8AMN9pt7Pq + 0D3FsdOkmkVUjYIefrQwkGp2oDnofZna2LtCMjjBHD31+gl8M9oPZrU9iShHPKMuMEjhJPLvsR7307/z + jn5bs/y08j+aPzp82W0sSTWbRaHbrGzXD2isCTElORa5lCJHTrSvRq5yvtPrTqc0dLjN0d/63/HRz/Y+ + k/8AA97JGg0mTtHOKMx6dt+AdR19Z5d4APVkn5O+Ufzdk/Ns/ml+YtlFBB5z0O5lgginDjTlma3lttPM + b8ZFMUYIPw0qCSeROYXaGr0w0I02I2YS32587lfvdt2J2b2ge2Ja/UxAhkxnh3vh3iRAjYg13Crvqlf5 + p/8AOYGu/lz598zeTLP8oP8AElr5emiiXW/06LT1/UgjmJ9D9HzcOPqcftnpXKtF7PZNVhjlEqB8vOu9 + v7X9usHZ2rnppQsxr+KuYB/mnvZF/wA5f3DXf5U+Urjh6f1vzLZyNHXlTnp189K0FaHMj2R21kh/QP3x + cH/gnG+yoH/bY/7mb4+/I3yS/nf8zfLWmNEZLCwnGqawRsBbWbCQhtjs78Y/9l2652Hbut/LaScup9I9 + 5/ULPwfLvYzsw9o9qYoV6YHjl7o7/bKh8X2l56u7nzv/AM5Ifl75D9AS+XvJOnz+YdeilQPHNNPGyxAq + 1QwTjGN/9+N4Zw2i/wAH7PzZrozIgPvP2fc+x9rS/O9t6bS1ccUZZZXy5cMfkfvZ3pf5UzaL+dB8+aNp + 2g6F5SHl2TSzpunRmC6mvZZlle4lijgWLcALXmTsNtzmLl7TOXReDMylPjuybHDVVzv7HYafsAaftU6v + FGEMZxcNRHDIzMuIyIArltd35PDvzd/5xm89+f8A8x/M/nDSNX0G20zWWszaQXk90k6i3sre2bmsdrIo + q8TEUY7U+Wb7sj2k0+j0scU4yJF8gK3JPUjveM9qPYPXdqdoZNTinjEZcNcRkDtER6RI6d74r0wab5a8 + 4acfMscF7o2ia1DH5iQo80MlrBchLr4VUuw4BqUXl4CudfqcksullLFYJjce+yNny7QY8em7Rhj1ABjD + IBPqKEql51V9LfoZ+VPmP/nGP8zdYvdH/L7yhpWoX+j2i3tzLd6AYRHGJFjUq95CCW5MOm/vnm+sz9o4 + ReXJMA/0j+gvvnZel7C1ciNNhxSMaP0Dbu+oML/NP/nIr8qPJGuebfyub8rtYu7y3t5NL1O/06w0+GzK + 3tuj/upPXDkcZfirGKEd8v0HZ2t1HBmjPa7Fk9C4fbPtD2VoTk0mTHvwmJAERtIe/uPcybXGY/8AOHVk + xJDHynpNfHeS3rh05/14v/bD95RrAP8AQv8A8kI/cH5vCIkgAVJ2AHfPTbfnkG36I/l/pF9+Qv5LXWur + okmp/mT55ngj0jQFX99JeXNY9PtX2BCxBjLLX7NXFemebdr6sdpa3gEqxw69K/il+gd9B9/9mOzZdg9l + HJKBOfLR4etnbHD4Xcr5EyZB+QUnn3yTrOoflV+YOgSNquoRan5tTzwl5DNb37NcWcM6LEgDhudxyJYD + 5bjMTtiWLUVnwn0gRhVURQNfc7L2XjqdFxaTVRrJIzycQIInchZHXnLewE+8t/nzqfmj839e/KvTfy5v + Pq3lu6uYtW84SXqC1jhtjx9X0hEWq7UVVruT1oCcxMvZssWnjnlIVLkOrstN2/j1Guno4RJlj+o9B/b0 + fJf/ADlh5s0fzL+Zsek6TcG6fyhp66dq8qgGNbx5HmeJWBNSisobwaq9Qc7P2Rwzx6eUjykbD5P/AME/ + WYsutx44m5QjUveTdPmP086y3zO3enja2708bW3enja2708bW3enja2708bW3enja2//11vTz3K34z4n + enja8TvTxteJ3p42vE708bXid6eNrxO9PG14nenja8T66/5w+0G0u/OnmTXZviutD0tIbRCBsb2QhnrS + tQsJX/ZHOP8Aa/ORihjH8RJ+X9r6v/wKdIJ6nPnPOEREf55Nn/Y/a+ndW/LTzPrfkH8zPLOo6tp8+r+e + dbutRsblhKbeC1eWD6vBL8IcmOGAISBv2zk8Gshhz48gBqAHz3v7S+pa3srLqtHnwSkOLKTR3oDbhB67 + AUafOlr+aHmD8w/zS/Lr8otR8r2ejW3kLzNf23maK1YzabqR0iKeCBraOReaRKkcjem4NDx+I8a5tj2Z + 4Omyakm+KIMe/wBRHPz3eWj7SjWdo4OzoxAMMkxOvpPhiQFeW10fJPPzM/MrSPyG/O641eP8t21i21/y + tYWaXmltDaSW0S3Vy83GMx8ZObqlRzWnEde0NHoMuv0YEZbxmbv3Cvlv827tft7T9idrGWWBqeKNEbVU + p3Q5G9r3HIPnn8lIbTzh+dPly582oZ5/MOrXur3aCnpvfcJ79Vfl+wZEpTvsM6ntTi0fZpjj6AR+BoF8 + 09mZ4+1vaGOTOL4pynXTiAMhflYfd/583mkT+RNA1G40zUPNujSeYdIuhpWgxLeXeoRczIkdtHyCyers + Njup2OcJ2WZxzHhIieGW52A2fbPaOOOeljxxlOPiQNRFmVSBAA6318nz1+eH5gfnX5z1HQf+VQaP+YPl + DRtP0+SXVpW8vXtpcXF5O9BC6XFsSRCkYIK7EudzTNp2T2fpTGR1E4Xe3qH63mfajt7tOOTHHQYcxFeo + +HLmem8en6XtX/ORT/mgPy38sH8tbzXLLzM+s2g1WfRbZ7m6+q/UboyiSNY5CEMojqSPtUHfMDsfDp8u + cxzkCNHmaF2Hd+1us12l0UZ6KEpZOMAiMTI8NSvYA7XT8+fNlp+bjtZXv5qT+Yb6YK8Gk3uu2UlqQtQz + pGXijDb0JGd/2Xh0mESGnlE3zog/pL4b7S63tTVGE9djnACxHjiY++rAt9x/841fmV58806DDpmueV7T + SfJXkbTVsZfPN1fFpb6W3UBFSAxIsaxxAGR2kalB/N8PD9vaGOnzyPFcpkmq5A/jZ9n9ie2smv0UAYVD + FER4yfqMRW23dzN/sKPy7/Nm+/Nf/nIeW806SeL8v9C0LVLHypGeSx30iz2vr35FBUvQBAd1SnQuww6r + s38roROX1ykL8hRoMOzfaL+Uu2pYsf8AdY8cqPSUuKNn9Xl71/5l/wDOU3nLyH538xeU9L/I+681afoU + sccPmCPV3tluA8EcrERDTpuPEuV+2en0ZDSdiHUYhk4wL6bfrbu1fbD8jqZYPAlLhrcXRsA/zT396Zf8 + 5dym7/K3yjcGP0jceZbSUxVrxLabfmlaCtK5l+ye2sl/UP3h1P8AwUJX2VA/7bH/AHM0v/5w/s/L9t5W + 1/VuaxeYNS1s6Q5mZQzpb2qXcccA6mqvIx8eJ7LlvtbmnLPGH8IjfzNH7mj/AIFumwx0OTMP7yU+E+6I + BAHzJ/sZde+b9H8m/nh5zvLzyZ5v16+1DSNLthrmgaNcatZ2kIVn9Kb6oryo8rAH7BFEG4zU8E8mkhES + iAJSNEgEnbv6D9L1JzYtP2plnKGSUjjgOKMTKIAMjXpBIJP3B51+Quq/n1rH5r6vqf5if4nsvKWq2Wo3 + VnoOp2EttY2UstxE9vDG7wpvHGWVQWqQD1zN7U0mkw6aJxTjKdi6IJ5G+ve6b2b7W7V1faOSOpxZMeGp + GPFAxH1ChZA3q+rD/wA8JP8AnJL/AJWt5sHkPWPOdp5RRrEaRb6Vp0k9mB9QtjN6UiwOGrMX5UY0aozL + 7K0egyaeMs04Ce9gyAPM9L7nV+03bHbmn1+THpMWWWIcNGMDIfSLoiJ628N/L7yQnmr8ydL8m+dri80e + TU571dbuJVW3uo54rWe5PNZkopZ46EFe+dTrtYNJojlw1IRArqCLA6eT5r2L2XLtTtcabV8UDMyMv4ZA + iJlykNtx3P0H/Kb8k/Jf5Za3qWr+WfMFzq11qFj9TuIJ5LZ1WP1Ek5AQohrVQN9s4DtPtnLroxjOIjRv + a/0l9z9nfZTTdiznPDknMzAB4iDy9wDGfO//ADjt+XvnDzZrnmbVvN99YalrEyS3dnFPaKkbJEkQCiSN + mGyA7nMrQ+0WfSYY4owiQO++++913bPsFou09XPU5ck4ylVgGNbADrEno9Svfy68v3f5VxfltLq88fl2 + PTbbT11gPEJjDbsjI/Mr6dSUG/GmaqGunHVfmKHFxGVdLL0mXsbFPs78iZHg4BC9uKgAL5Ve3c+Afz1/ + Kvy3+VzeVf8ACXmK81O51pb95Z5ZYWaBrP6t6TIYEQqSZid/DbO97E7WydojIMkQKrlfW7533PiHtl7M + 6fsCWCennKXGZXZG3Dw1XCB3l9h/lX+bnmzXvIesfmF+Znlyz8k+WNKt1OnXSTyXNzqHpAiW5Efpx8Vk + fikSKGZ3JA/Z5cPr9AMGfwYS4pfd5fr7n2XsTtueu0f5rLDw4VtZsy75cht3d/TpfM/+cfPNfmf8xfzi + /MPzz5htLnTIZ9GhtdF0S4UqbGxNyDbxUI+03ps7nu5NNgKbLtbSQ0mjxQBBJJJrvp0Psx2tl7T7U1OW + UTGMYxjEEVUbP30SjPO3nJv+cdfzK8066nknVPN2mfm8bCfTRpbRqYL+z9dLqFvUpVpWnR1p4nwyGPFP + tHSwhEgHDxXf800QfhRDZqdTi7A7SzZpxlKOr4OGv58LiY/HiBHfZ7l3/OV82h6Z5A8v2X6ItNM8w+Zd + Xjn9CGKL1QsELyXRaVAOQV5EUkdSwy/2WOSWqO5MRE/scL/glnDj7MFxAnOYrYXtZO/45vz99PPRbfAe + J3p42vE708bXid6eNrxO9PG14nenja8TvTxteJ3p42vE/wD/0Df0s9ut+Lbd6WNrbvSxtbd6WNrbvSxt + bd6WNrbvSxtbd6WNrb2X8n/yci/NebzKH89al5LTy9FaSzrprtG9wlx69Gd1miosXpHqD9rt35r2i1sN + OICWMTu+fSq8ut/Y+k/8D3sjL2gc5hnlhEOG+EfVfF5j6a7jz6Pu258jeVtF/JeXyP5h8+Xtj5Vs7L0L + /wA+TajFaXSRm59UStfS8kQ8iE5H5ZwvjGWfjjAXf01Y91PuB0kcei8HJlkAI0Z2BL32dgXlP5KflPpH + k/zP5p/MP9KNdeUdNimi8pa5e3Mdwby2ZBJcanJcqArKwDUcbMCzdKE7rtTtU59NjwAVLnIAVXdED8dH + jfZn2XGi7R1GulImHLGSQTIEAzyE+/YHr6tqpW/MPQ9F/wCckfy10bz/APl8/wBa1XTTcfUbeUGKWVFf + jcWcitTjIGQOnIfcHrg7H10uzNQcebaMqvyPQ/r/AGMva7sWHtL2fDUaQiWSFmPTiH8UPftYvqK2Bt8D + yw6zo17ItvcXfl/WbJpYWlUNDcwM6NDKu4DI3F2XxHzzvsuPHqcfCalE17j1fBtLq9R2bqOONwyRsbii + LFHY8jRfevm3W7vyX/zjb+UOvaRZR3135ctPKVzZWErFI5DBaxURmWpAIFNs87wabx9fkxA1ZmPvfoTW + 9pfkewdPqpDi4I4ZV37ReJN/zml+aaKzH8sNCooJP+n3Hb/YZsf9Csv532POj/gqYj/kvt/Y+r/zx/Nf + zB+V/kTy/wCavL+gWevajrGqW1jNYXczwxpHPaXFwzhkBJIMIAHgc0XZvZ51mU4waoE/aB+l7j2k9oI9 + jaWOolHiEpCNcuYJ/Q+DPzD/ADt83fm9DpFt5k8rWHlyLQ5JpbdrK4knMpnVFIYOBSnDamdv2N2QdDOU + jK7FPivtj7Yw7bxY8cYcPASed8xXc+hPy1/NP81dB/L/AELyvo//ADj9rnnOSzhdbfV5J4dI027triZp + IWSWeKTmPRkFWCkMd69TnN9r6TFPVzkcsQCfeQev29H0f2U7W1OPsrDjjpckiI7GuCMgTYIJ5gxI3rf7 + XonkvWfzR8xfmx5W1H8xPy6t/wAvUtvLmtQ6XZW+pxaoZQ81gzNI0KqsVKAKDuaNttmFlhihpZDHPj9c + b2rpLv5u60ubVZ+08cs+HwgMWQD1CV+rHz4eXle537mJ/mZ/zk1+YXkjzx5j8r6L+UA8yaXokscdtrf1 + +aH1w8EcrH01tZAKFyuzHpl2j7F/MYhk4wL6bfrcLtf2zOg1U9P4EpcNbi6NgH+ae/vZD/zlctxqP5Ye + VriO2dmPmG1ubiNFLemp06+LFqDYLXqcyPZaQjqzZ/hP3hwP+CfGU+yYGIJrJEmug4Z7+58t/wDOPP11 + vzn/AC+tXv5jpdteapeQ6WGpCLqTRruFpyvd/THEE9BWnU16H2j08Dpp5a9VRF+XEHz7/gd9o5f5Sw6W + /wB3c5V/S8OQv7Htn5vfnf5u/KP81vNFt5b8rWHmOPW7HSpblr24kgMTQRSKAoQGtee9c53s/sc67TRk + JVRP6H0L2g9sIdh9oTxyhxccInnXLiHcyT8i/wDnIvzt+aPneTyv5i8maZoFiul3F8l9Z3Us0hkhkiUI + VdQKESE19so7T7EOixCZldmvvc32Z9tYdtak4Iw4aiZc+4gd3mkf5u/85P8An78vvzF8yeTtD8iaTrOm + aIbRbfUrm7milkNxZwXLckVSBxaUqPYZboOwDqsMcolV39hpxe3vb7H2VrZ6WWOzGt7/AJ0RLu83xf5t + v5fP+p63revafFaz+YruS9vNOicvHE0jcuCsaEge+d1pNKMWnjilvQp8Q7W7XOr1+TVwHCZm/c+2f+cS + Pyhtvy80nzF5+1CyXRT5ht44LIXH7tksbctLJNJzpxV2oRWmy8uhGcP7R6jFPLHFi34efvPT4Ptn/A67 + P1WHTT1WqseJXCDsREX6j/W6eQvq+HvzDs/Ln5hee/N3nRtPV4/MOq3FzaOSQWt+fCBiPFo1UnOt7N0E + MemhGQ3rd8m9pPaDLqO0c08UvQZGvcNgfjVvvvX9OtJP+cOLTS3iBs/8JaVB6PbgJLcAfhnF4YA9qcPT + xD95fZ9XnmPZjxAfV4ET9gfnXpXlvTtKMkelWogkuiFIG9T0GejQxwxA1s/O2XV5dSQJG+5+jvl78xP+ + cjk0bQtEtf8AnH1bi70+xgtb/wAyar5htbCGWSGMIZRaCJ5QHoGoDsTSlN88y1Gm03iSPiiiTVAl+mNB + 2j2kcGOJ0h4hECRlKMRYHdud2YeX9Q8zeV/K/wCZP5pfmBo1novmy/8A3S6Pp0j3UbJpkZtbGKJmVWdp + 7hm4im/NfHK8ojlljwY5XEdTtvLc/IVfucnTSnp4ajWZ4CM5dB6rGMcMQOV2br3hNfybsvNWu/lt5QX8 + 2dBH+JvLssb2N1fcZLib6qONrfSKatFMVNG5fESC23KgjrTHBnmMEvSdtu48x5hn2MMus0WGetxVkjRA + lzBH0y8pV8XyR/zlDp3nm7/MN9Z17SntvKdjbJYeULqI+rA0bUknkkcABJZJDQqaHiq0rSp6z2V8GOI8 + MvWTuOvl8Hyf/gpHWS1MDOBGCI9MucSTzs9D5HoNnzV6Wdbb5RbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6 + WNrbvSxtbf/RlHpe2e1W/FHE70vbG14nel7Y2vE70vbG14nel7Y2vE70vbG14nel7Y2vE70vbG14kl1b + y3pWuej+krYXH1ckxb0pXKsmKOT6nK02uy6e/DNW94tvzys9P/J2D8lrDyZqEN1Z2q29n5iZoHsleO8+ + toxiarEClKEdfbOUl2HM605NuC/sp9Zx+3mCHYo0/q8YRAvauIG7/AQ35h/n157/ADS8t6R5OnsF8r6V + DbRr52ntmodWuU2McQG8VsaBilSWJ4k8R8V3Z3s/HDmM57gH0/jvcL2j/wCCJPW6OODCOEyj6z3nqB3R + +/ly5xj8uvzG83fk/rk2seVok1bRNS4jzF5OnlMUFyVHFZ4XAb0plApyCkEbMD8NM7tbseGsFjaQ6uj9 + kfbPL2PMwn6sR5jz7x3H7+vSiPWde1/zbqt/5j8z3IutZ1aZp7ngKRxA/YhjHZI1oq+w33zZaLTR02GO + OPIPNdt9qz7T1mTUT5yPyHQe4B6l5k/Pe181/ll5f/KtPJ+p6dc+X7bS7aTXppImtpTpsKxMVVTzAfjU + VzQaLsnLi10s5I4SZH/TW+g9te1+k1XYMNFAHjEMceleir+54vNCWilUCpKMAPozqCdnyuMtw9y/Mz8/ + 7P8ANbyzo3lG18m6poL6JqMF82pXskLxSrBa3FtxVYySCTMDv2Gcr2L2Tl0molOZFEEfaP1Pq3tt7YaT + tbs+GDCCJCYlvXIRkP0vEfS9s6u3yfieoaf/AM5D/nhoWiaV5W8uDy5p+kaHapaWeoXFrNc3siJ0Llp/ + T2GwAjzl8/s5DNllkJPqJPzfU9D/AMEvNo9JiwQhH93ER5HoK7/0Mk8tf85Y/m/5Zsrqz8yeXrP8yL25 + u3uYNXM8Wki2gaONVtVht7VgwRlZubEseVCaAZh6j2XBkPDNCvf+l2/Z3/BUIgfzEOKV7b8NDbagPxbI + f+h1fP8A/wCWbsf+40//AGR5j/6F8n877P2uw/5Orp/9S/2X/HUr13/nLjzx5n0PW/Ldz+VNnplv5g0+ + 602bUU1d5WgW6haEyiM2q8ivKtKivjmRpfZyeLLCfF9JB5dxvvcDtT/gl4NVpMuAY68SEo/V/OBH83ze + VeRPOUf5cecNC86zaTca3Dob3LSaZaMqTS/WLSe2HEv8IoZQTXsM6LtfTS1OmljjzNfYQXzn2R7Vxdm9 + p49RlvhjxXX9KJj+lGfmN+YEP5p+arnzfb6JdaBFc21vbDTrxkeVTApUmsZIoa5V2Jo56TBwT52S5ntv + 23h7W14zYQREQEd/K/1q35afmPB+U3mg+bLjQrvzDGbCexGn2TIkvKZ4mDVkIFAIzke3NFPV4BCHMSv7 + Cz9he3cPZGtlmzAmJgY7d5IP6Et89+co/wAx/OGu+dYdJuNEh1x7Zo9Mu2V5ovq9pBbHkU+E1MRIp2OX + 9kaaWm00ccuYv7SS4Htd2ri7S7TyajFfDLhq/wCjER/QxuzvdQ0e7tdV0oW51LTpkubIXUSzwmSNgyiS + NwQwqNxmbnx+LjlC+Yp02g1h0uohmABMJA7gEbeReu/mL/zkb52/NDyzbeTofL6+TdPurcR+d7uOYytf + MDRre1Oxjt3Aq3KrEHh9mvPlezvZ3ws3HkNgHZ9U9o/+CONVoxh08eEzFSP3geX9jxhYFRVRVCqoooHY + DOvt8gMrNvbbv/nIWS//ACvi/KL/AAFewmLTbXTf8TG7jMJNs8bGT0fT5Ubh05ZyWPsXLHXePe3ES+ua + j240s+wvyQiePwhDpVgAX9jxCWAvFIg2LqQD4VGdYTYfJIyogvR9W/Pn/nIjWx6Q892flq1A4GHSdOt+ + bqNgTNcrPID7qwzmcfszgid9/wAeVPp2p/4KGumAIVH3Afptkmnf85NfmzZJ5It9Zt4Nat/KF28vmW6Q + Is+v2xURwqwK8YpYgzPUbM4RtqEHFyezMfWYnmPT5Oz03/BQmRgGSPI/vP6Q6e4jn5kDkxj8wPzr/Nb8 + 0byKZtWn/Lzy/ZTrcaR5f0W4ZZ/UjbnFLd3S8GlZSAeICpX9mu+ZOg9ncWON5PUS63t7/gk6nU5ANN6I + A3tzPvP6OSL8xfnp+aHnfylp3kbzKtokdnP6uteZLX4JNWhjA+rxywAcYyr1dypoxC0VaEG3QdhR0upO + UGwOXk43b/t9k7U7NGmIqRPqI/iA5be/c+55p6XtnR2+b8TvS9sbXid6Xtja8TvS9sbXid6Xtja8TvS9 + sbXid6Xtja8TvS9sbXif/9Kcelns1vxHbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSx + tbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd + 6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WNrbvSxtbd6WN + rbvSxtbd6WNrbvSxtbf/0+ken7Z7Hb8PW70/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270/bG1 + t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270/b + G1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270 + /bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbd6ftja270/bG1t3p+2NrbvT9sbW3en7Y2tu9P2xtbf/U6v6e + ev2/DNu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p + 42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42t + u9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t3p42tu9PG1t/9Xsvp56 + 5b8K2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enj + a2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja27 + 08bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3enja2708bW3/1u5ennrN + vwjbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNr + bvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvT + xtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbd6eNrbvTxtbf/X79wz1e34 + Nt3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG + 1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG + 1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t3DG1t//9D0Rxz1S34Kt3HG1t3HG1t3HG1t3HG1 + t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1 + t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1t3HG1 + t3HG1t3HG1t3HG1t3HG1t3HG1t//2Q== + + + \ No newline at end of file diff --git a/类库/Grant.Framework/UpdateSoft.cs b/类库/Grant.Framework/UpdateSoft.cs new file mode 100644 index 0000000..93e28a7 --- /dev/null +++ b/类库/Grant.Framework/UpdateSoft.cs @@ -0,0 +1,364 @@ +using CsharpHttpHelper.Down; +using DevExpress.XtraEditors; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Windows.Forms; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class UpdateSoft : BaseForm + { + public UpdateSoft(List list) + { + InitializeComponent(); + this.list = list; + } + + List list; + private void UpdateSoft_Load(object sender, EventArgs e) + { + try + { + string html = GetStringBulider(list); + this.webBrowser1.DocumentText = html; + var temp = Process.GetCurrentProcess().MainModule.FileName; + var index = temp.LastIndexOf("\\"); + path = temp.Substring(0, index + 1); + exe = temp.Substring(index + 1); + } + catch (Exception) + { } + } + public string path; + public string exe; + string GetStringBulider(List list) + { + StringBuilder builer = new StringBuilder(); + try + { + builer.Append("").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append(" ").Append("\r\n"); + builer.Append(" ").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("").Append("\r\n"); + foreach (assembly item in list) + { + builer.Append("
").Append("\r\n"); + builer.Append(" 版本编号:" + item.version + "").Append("\r\n"); + builer.Append(" ").Append("\r\n"); + builer.Append("
    ").Append("\r\n"); + string[] infos = item.message.Split(new string[] { "\r\n" }, StringSplitOptions.None); + foreach (string info in infos) + { + if (string.IsNullOrWhiteSpace(info)) continue; + builer.Append("
  • " + info + "
  • ").Append("\r\n"); + } + builer.Append("
").Append("\r\n"); + builer.Append("
").Append("\r\n"); + builer.Append("
").Append("\r\n"); + } + + builer.Append("").Append("\r\n"); + builer.Append("").Append("\r\n"); + builer.Append("").Append("\r\n"); + } + catch (Exception) + { } + return builer.ToString();//结果 + } + + private static Stream st = null; + private static Stream so = null; + + internal static void DownloadFile(string URL, string filename, ProgressBarControl prog) + { + float percent = 0; + try + { + if (File.Exists(filename)) + File.Delete(filename); + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + prog.Invoke(new Action(delegate + { + prog.Properties.Maximum = (int)totalBytes; + + })); + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + totalDownloadedByte = osize + totalDownloadedByte; + Application.DoEvents(); + so.Write(by, 0, osize); + prog.Invoke(new Action(delegate { prog.Position = (int)totalDownloadedByte; })); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + catch (Exception ex) + { + throw ex; + } + } + + private void UpdateSoft_FormClosing(object sender, FormClosingEventArgs e) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + + private void download(string path, string dir) + { + try + { + FileDownloader loader = new FileDownloader(path, dir, (int)5); + loader.data.Clear(); + + this.Invoke(new MethodInvoker(() => + { + try + { + statusBar_process.Properties.Maximum = (int)loader.getFileSize(); + } + catch (Exception) + { + } + })); + DownloadProgressListener linstenter = new DownloadProgressListener(); + linstenter.doSendMsg = new DownloadProgressListener.dlgSendMsg(SendMsgHander); + loader.download(linstenter); + } + catch (Exception ex) + { + DownMsg msg = new DownMsg(); + msg.tag = -1; + SendMsgHander(msg); + //Console.WriteLine(ex.Message); + } + } + private void SendMsgHander(DownMsg msg) + { + try + { + switch (msg.tag) + { + case 1: + this.Invoke(new MethodInvoker(() => + { + try + { + statusBar_process.Position = (int)msg.size; + float count = (float)statusBar_process.Position / (float)statusBar_process.Properties.Maximum; + //Console.WriteLine(msg.size + " " + msg.speed); + if (statusBar_process.Properties.Maximum == msg.size) + { + stop.Stop(); + this.statusBar_process.Position = 100; + + WriteUpdateLog(list); + Grant.Framework.GrantClient.StartProcess(path + "\\ZipExtract.exe", exe + " Update.zip"); + is_update = true; + this.DialogResult = DialogResult.OK; + this.Close(); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + })); + break; + case -1: + MessageBox.Show("下载失败"); + break; + } + } + catch (Exception) + { } + } + + public void WriteUpdateLog(List new_log) + { + try + { + var file = path + "\\Cache\\Update.log"; + string text = string.Empty; + if (File.Exists(file)) + { + text = File.ReadAllText(file); + if (text.Length > 2000) + { + text.Remove(1000, 1000); + text = text.Trim(); + text += "..."; + } + } + StringBuilder sb = new StringBuilder(); + foreach (var item in new_log) + { + sb.Append(item.version); + sb.Append("\r\n"); + sb.Append(item.message); + sb.Append("\r\n\r\n"); + } + sb.Append(text); + File.WriteAllText(file, sb.ToString()); + } + catch (Exception) + { } + } + Stopwatch stop; + private void button1_Click(object sender, EventArgs e) + { + if (this.button1.Text == "开始更新") + { + this.button1.Text = "更新中..."; + this.button1.Enabled = false; + try + { + System.Threading.ThreadPool.QueueUserWorkItem(f => + { + try + { + var asy = System.Reflection.Assembly.GetExecutingAssembly(); + string c = System.IO.Directory.GetCurrentDirectory(); + var a = list[0]; + DownloadFile(a.url, c + "\\Update.zip", this.statusBar_process); + //string exe = "ZipExtract.exe"; + //Grant.Framework.GrantClient.StartProcess(c + "\\" + exe, asy.ManifestModule.Name + " Update.zip"); + WriteUpdateLog(list); + this.is_update = true; + GrantClient.StartProcess(c + "\\ZipExtract.exe", exe + " Update.zip"); + this.Invoke(new Action(delegate + { + try + { + this.DialogResult = DialogResult.OK; + this.Close(); + } + catch (Exception) + { + } + })); + } + catch (Exception ex) + { + try + { + this.Invoke(new Action(delegate + { + MessageBox.Show(ex.Message, "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + })); + } + catch (Exception) + { } + } + }); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + MessageBox.Show(ex.Message, "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + this.button1.Text = "更新"; + this.button1.Enabled = true; + })); + } + } + } + string c = System.IO.Directory.GetCurrentDirectory(); + public bool is_update = false; + + //private void DownThread_doSendMsg(CsharpHttpHelper.Down.DownMsg msg) + //{ + // this.Invoke(new Action(delegate + // { + // switch (msg.Tag) + // { + // case CsharpHttpHelper.Down.DownStatus.Start: + // break; + // case CsharpHttpHelper.Down.DownStatus.GetLength: + // //this.Invoke(new Action(delegate + // //{ + // // this.statusBar_process.Properties.Maximum = (int)msg.Length; + // //})); + // break; + // case CsharpHttpHelper.Down.DownStatus.DownLoad: + // this.statusBar_process.Position = (int)msg.Progress; + // break; + // case CsharpHttpHelper.Down.DownStatus.End: + // this.statusBar_process.Position = 100; + // // string exe = "ZipExtract.exe"; + // // var location = this.GetType().Assembly.Location; + // Grant.Framework.GrantClient.StartProcess(path + "\\ZipExtract.exe" ,exe +" Update.zip"); + // is_update = true; + // this.Close(); + // break; + // case CsharpHttpHelper.Down.DownStatus.Error: + // ShowError(msg.ErrMessage); + // this.Close(); + // break; + // default: + // break; + // } + // })); + //} + } +} diff --git a/类库/Grant.Framework/UpdateSoft.designer.cs b/类库/Grant.Framework/UpdateSoft.designer.cs new file mode 100644 index 0000000..2a07374 --- /dev/null +++ b/类库/Grant.Framework/UpdateSoft.designer.cs @@ -0,0 +1,96 @@ +namespace Grant.Framework +{ + partial class UpdateSoft + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.webBrowser1 = new System.Windows.Forms.WebBrowser(); + this.button1 = new DevExpress.XtraEditors.SimpleButton(); + this.statusBar_process = new DevExpress.XtraEditors.ProgressBarControl(); + ((System.ComponentModel.ISupportInitialize)(this.statusBar_process.Properties)).BeginInit(); + this.SuspendLayout(); + // + // webBrowser1 + // + this.webBrowser1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.webBrowser1.IsWebBrowserContextMenuEnabled = false; + this.webBrowser1.Location = new System.Drawing.Point(0, 0); + this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20); + this.webBrowser1.Name = "webBrowser1"; + this.webBrowser1.ScrollBarsEnabled = false; + this.webBrowser1.Size = new System.Drawing.Size(539, 482); + this.webBrowser1.TabIndex = 0; + this.webBrowser1.WebBrowserShortcutsEnabled = false; + // + // button1 + // + this.button1.Anchor = System.Windows.Forms.AnchorStyles.Bottom; + this.button1.Location = new System.Drawing.Point(183, 525); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(165, 29); + this.button1.TabIndex = 1; + this.button1.Text = "开始更新"; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // statusBar_process + // + this.statusBar_process.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.statusBar_process.Location = new System.Drawing.Point(0, 488); + this.statusBar_process.Name = "statusBar_process"; + this.statusBar_process.Size = new System.Drawing.Size(539, 31); + this.statusBar_process.TabIndex = 2; + // + // UpdateSoft + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(539, 561); + this.Controls.Add(this.statusBar_process); + this.Controls.Add(this.button1); + this.Controls.Add(this.webBrowser1); + this.IconOptions.ShowIcon = false; + this.Name = "UpdateSoft"; + this.Text = "程序更新说明"; + this.TopMost = true; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.UpdateSoft_FormClosing); + this.Load += new System.EventHandler(this.UpdateSoft_Load); + ((System.ComponentModel.ISupportInitialize)(this.statusBar_process.Properties)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.WebBrowser webBrowser1; + private DevExpress.XtraEditors.SimpleButton button1; + private DevExpress.XtraEditors.ProgressBarControl statusBar_process; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/UpdateSoft.resx b/类库/Grant.Framework/UpdateSoft.resx new file mode 100644 index 0000000..7bb7d1e --- /dev/null +++ b/类库/Grant.Framework/UpdateSoft.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 43 + + \ No newline at end of file diff --git a/类库/Grant.Framework/VerifyPassForm.Designer.cs b/类库/Grant.Framework/VerifyPassForm.Designer.cs new file mode 100644 index 0000000..96f1170 --- /dev/null +++ b/类库/Grant.Framework/VerifyPassForm.Designer.cs @@ -0,0 +1,104 @@ +namespace Grant.Framework +{ + partial class VerifyPassForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(40, 73); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(67, 14); + this.label2.TabIndex = 14; + this.label2.Text = "登陆密码:"; + // + // textBox2 + // + this.textBox2.Location = new System.Drawing.Point(113, 69); + this.textBox2.Name = "textBox2"; + this.textBox2.PasswordChar = '*'; + this.textBox2.Size = new System.Drawing.Size(196, 22); + this.textBox2.TabIndex = 13; + this.textBox2.UseSystemPasswordChar = true; + // + // button1 + // + this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.button1.Location = new System.Drawing.Point(114, 111); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(131, 30); + this.button1.TabIndex = 16; + this.button1.Text = " 确 定 "; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Tahoma", 10F); + this.label1.ForeColor = System.Drawing.Color.Blue; + this.label1.Location = new System.Drawing.Point(20, 27); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(316, 17); + this.label1.TabIndex = 17; + this.label1.Text = "请输入软件登录密码,验证身份通过才能继续操作"; + // + // VerifyPassForm + // + this.AcceptButton = this.button1; + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(356, 161); + this.Controls.Add(this.label1); + this.Controls.Add(this.button1); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "VerifyPassForm"; + this.Text = " 身 份 验 证 "; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/VerifyPassForm.cs b/类库/Grant.Framework/VerifyPassForm.cs new file mode 100644 index 0000000..2e3040b --- /dev/null +++ b/类库/Grant.Framework/VerifyPassForm.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Forms; + +namespace Grant.Framework +{ + public partial class VerifyPassForm : BaseForm + { + public VerifyPassForm() + { + InitializeComponent(); + } + + private void button1_Click(object sender, EventArgs e) + { + try + { + if (string.IsNullOrWhiteSpace(textBox2.Text)) throw new Exception("密码不能为空"); + if (this.textBox2.Text != Grant.Framework.GrantClient.Get().accounts.userpass) throw new Exception("抱歉,身份验证失败!"); + this.DialogResult = DialogResult.OK; + } + catch (Exception ex) + { + ShowError(ex); + } + + this.Close(); + } + } +} \ No newline at end of file diff --git a/类库/Grant.Framework/VerifyPassForm.resx b/类库/Grant.Framework/VerifyPassForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/Grant.Framework/VerifyPassForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/HttpHelper2.1/Base/HttphelperBase.cs b/类库/HttpHelper2.1/Base/HttphelperBase.cs new file mode 100644 index 0000000..d09ca04 --- /dev/null +++ b/类库/HttpHelper2.1/Base/HttphelperBase.cs @@ -0,0 +1,517 @@ +using CsharpHttpHelper.Enum; +using CsharpHttpHelper.Static; +using System; +using System.Collections.Specialized; +using System.IO; +using System.IO.Compression; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Text.RegularExpressions; + +namespace CsharpHttpHelper.Base +{ + /// + /// Http连接操作帮助类 Copyright:http://www.httphelper.com/ + /// + internal class HttphelperBase + { + private Encoding encoding = Encoding.Default; + + private Encoding postencoding = Encoding.Default; + + private HttpWebRequest request = null; + + private HttpWebResponse response = null; + + private IPEndPoint _IPEndPoint = null; + + /// + /// 根据相传入的数据,得到相应页面数据 + /// + /// 参数类对象 + /// 返回HttpResult类型 + internal HttpResult GetHtml(HttpItem item) + { + HttpResult httpResult = new HttpResult(); + try + { + SetRequest(item); + } + catch (Exception ex) + { + HttpResult httpResult2 = new HttpResult(); + httpResult2.Cookie = string.Empty; + httpResult2.Header = null; + httpResult2.Html = ex.Message; + httpResult2.StatusDescription = "配置参数时出错:" + ex.Message; + return httpResult2; + } + try + { + using (response = (HttpWebResponse)request.GetResponse()) + { + GetData(item, httpResult); + } + } + catch (WebException ex2) + { + if (ex2.Response != null) + { + using (response = (HttpWebResponse)ex2.Response) + { + GetData(item, httpResult); + } + } + else + { + httpResult.Html = ex2.Message; + } + } + catch (Exception ex) + { + httpResult.Html = ex.Message; + } + if (item.IsToLower) + { + httpResult.Html = httpResult.Html.ToLower(); + } + if (item.IsReset) + { + request = null; + response = null; + } + return httpResult; + } + + /// + /// 快速Post数据这个访求与GetHtml一样,只是不接收返回数据,只做提交。 + /// + /// 参数类对象 + /// 返回HttpResult类型 + internal HttpResult FastRequest(HttpItem item) + { + HttpResult httpResult = new HttpResult(); + try + { + SetRequest(item); + } + catch (Exception ex) + { + HttpResult httpResult2 = new HttpResult(); + httpResult2.Cookie = ((((NameValueCollection)response.Headers)["set-cookie"] != null) ? ((NameValueCollection)response.Headers)["set-cookie"] : string.Empty); + httpResult2.Header = null; + httpResult2.Html = ex.Message; + httpResult2.StatusDescription = "配置参数时出错:" + ex.Message; + return httpResult2; + } + try + { + using (response = (HttpWebResponse)request.GetResponse()) + { + HttpResult httpResult3 = new HttpResult(); + httpResult3.Cookie = ((((NameValueCollection)response.Headers)["set-cookie"] != null) ? ((NameValueCollection)response.Headers)["set-cookie"] : string.Empty); + httpResult3.Header = response.Headers; + httpResult3.StatusCode = response.StatusCode; + httpResult3.StatusDescription = response.StatusDescription; + return httpResult3; + } + } + catch (WebException ex2) + { + using (response = (HttpWebResponse)ex2.Response) + { + HttpResult httpResult4 = new HttpResult(); + httpResult4.Cookie = ((((NameValueCollection)response.Headers)["set-cookie"] != null) ? ((NameValueCollection)response.Headers)["set-cookie"] : string.Empty); + httpResult4.Header = response.Headers; + httpResult4.StatusCode = response.StatusCode; + httpResult4.StatusDescription = response.StatusDescription; + return httpResult4; + } + } + catch (Exception ex) + { + httpResult.Html = ex.Message; + } + if (item.IsToLower) + { + httpResult.Html = httpResult.Html.ToLower(); + } + return httpResult; + } + + /// + /// 获取数据的并解析的方法 + /// + /// + /// + private void GetData(HttpItem item, HttpResult result) + { + if (response != null) + { + result.StatusCode = response.StatusCode; + result.ResponseUri = response.ResponseUri.ToString(); + result.StatusDescription = response.StatusDescription; + result.Header = response.Headers; + if (response.Cookies != null) + { + result.CookieCollection = response.Cookies; + } + if (((NameValueCollection)response.Headers)["set-cookie"] != null) + { + result.Cookie = ((NameValueCollection)response.Headers)["set-cookie"]; + } + if (item.IsUpdateCookie) + { + item.Cookie = result.Cookie; + item.CookieCollection = result.CookieCollection; + } + byte[] @byte = GetByte(item); + if (@byte != null && @byte.Length > 0) + { + SetEncoding(item, result, @byte); + SetResultByte(item, result, @byte); + } + else + { + result.Html = string.Empty; + } + } + } + + /// + /// 设置返回的Byte + /// + /// HttpItem + /// result + /// byte + private void SetResultByte(HttpItem item, HttpResult result, byte[] enByte) + { + if (item.ResultType == ResultType.Byte) + { + result.ResultByte = enByte; + } + else if (item.ResultType == ResultType.String) + { + result.Html = encoding.GetString(enByte); + } + else if (item.ResultType == ResultType.StringByte) + { + result.ResultByte = enByte; + result.Html = encoding.GetString(enByte); + } + } + + /// + /// 设置编码 + /// + /// HttpItem + /// HttpResult + /// byte[] + private void SetEncoding(HttpItem item, HttpResult result, byte[] ResponseByte) + { + if (encoding == null) + { + Match match = Regex.Match(Encoding.Default.GetString(ResponseByte), RegexString.Enconding, RegexOptions.IgnoreCase); + string text = string.Empty; + if (match != null && match.Groups.Count > 0) + { + text = match.Groups[1].Value.ToLower().Trim(); + } + string text2 = string.Empty; + if (!string.IsNullOrWhiteSpace(response.CharacterSet)) + { + text2 = response.CharacterSet.Trim().Replace("\"", "").Replace("'", ""); + } + if (text.Length > 2) + { + try + { + encoding = Encoding.GetEncoding(text.Replace("\"", string.Empty).Replace("'", "").Replace(";", "") + .Replace("iso-8859-1", "gbk") + .Trim()); + } + catch + { + if (string.IsNullOrEmpty(text2)) + { + encoding = Encoding.UTF8; + } + else + { + encoding = Encoding.GetEncoding(text2); + } + } + } + else if (string.IsNullOrEmpty(text2)) + { + encoding = Encoding.UTF8; + } + else + { + encoding = Encoding.GetEncoding(text2); + } + } + } + + /// + /// 提取网页Byte + /// + /// + private byte[] GetByte(HttpItem item) + { + byte[] result = null; + using (MemoryStream memoryStream = new MemoryStream()) + { + if (item.IsGzip) + { + new GZipStream(response.GetResponseStream(), CompressionMode.Decompress).CopyTo(memoryStream, 10240); + } + else if (response.ContentEncoding.Equals("gzip", StringComparison.InvariantCultureIgnoreCase)) + { + new GZipStream(response.GetResponseStream(), CompressionMode.Decompress).CopyTo(memoryStream, 10240); + } + else + { + response.GetResponseStream().CopyTo(memoryStream, 10240); + } + result = memoryStream.ToArray(); + } + return result; + } + + /// + /// 为请求准备参数 + /// + /// 参数列表 + private void SetRequest(HttpItem item) + { + if (!string.IsNullOrWhiteSpace(item.CerPath) || !string.IsNullOrWhiteSpace(item.CerPath)) + { + ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult; + } + request = (HttpWebRequest)WebRequest.Create(item.URL); + if (item.IPEndPoint != null) + { + _IPEndPoint = item.IPEndPoint; + request.ServicePoint.BindIPEndPointDelegate = BindIPEndPointCallback; + } + request.AutomaticDecompression = item.AutomaticDecompression; + SetCer(item); + SetCerList(item); + if (item.Header != null && item.Header.Count > 0) + { + string[] allKeys = item.Header.AllKeys; + foreach (string name in allKeys) + { + request.Headers.Add(name, ((NameValueCollection)item.Header)[name]); + } + } + SetProxy(item); + if (item.ProtocolVersion != (Version)null) + { + request.ProtocolVersion = item.ProtocolVersion; + } + request.ServicePoint.Expect100Continue = item.Expect100Continue; + request.Method = item.Method; + request.Timeout = item.Timeout; + request.KeepAlive = item.KeepAlive; + request.ReadWriteTimeout = item.ReadWriteTimeout; + if (!string.IsNullOrWhiteSpace(item.Host)) + { + request.Host = item.Host; + } + if (item.IfModifiedSince.HasValue) + { + request.IfModifiedSince = Convert.ToDateTime(item.IfModifiedSince); + } + request.Accept = item.Accept; + request.ContentType = item.ContentType; + request.UserAgent = item.UserAgent; + encoding = item.Encoding; + request.Credentials = item.ICredentials; + SetCookie(item); + request.Referer = item.Referer; + request.AllowAutoRedirect = item.Allowautoredirect; + if (item.MaximumAutomaticRedirections > 0) + { + request.MaximumAutomaticRedirections = item.MaximumAutomaticRedirections; + } + SetPostData(item); + if (item.Connectionlimit > 0) + { + request.ServicePoint.ConnectionLimit = item.Connectionlimit; + } + if (item.SecurityProtocol > SecurityProtocolType.SystemDefault) + { + ServicePointManager.SecurityProtocol = item.SecurityProtocol; + } + } + + /// + /// 设置证书 + /// + /// + private void SetCer(HttpItem item) + { + if (!string.IsNullOrWhiteSpace(item.CerPath)) + { + if (!string.IsNullOrWhiteSpace(item.CerPwd)) + { + request.ClientCertificates.Add(new X509Certificate(item.CerPath, item.CerPwd)); + } + else + { + request.ClientCertificates.Add(new X509Certificate(item.CerPath)); + } + } + } + + /// + /// 设置多个证书 + /// + /// + private void SetCerList(HttpItem item) + { + if (item.ClentCertificates != null && item.ClentCertificates.Count > 0) + { + X509CertificateCollection.X509CertificateEnumerator enumerator = item.ClentCertificates.GetEnumerator(); + try + { + while (enumerator.MoveNext()) + { + X509Certificate current = enumerator.Current; + request.ClientCertificates.Add(current); + } + } + finally + { + IDisposable disposable = enumerator as IDisposable; + disposable?.Dispose(); + } + } + } + + /// + /// 设置Cookie + /// + /// Http参数 + private void SetCookie(HttpItem item) + { + if (!string.IsNullOrEmpty(item.Cookie)) + { + request.Headers[HttpRequestHeader.Cookie] = item.Cookie; + } + if (item.ResultCookieType == ResultCookieType.CookieCollection) + { + request.CookieContainer = new CookieContainer(); + if (item.CookieCollection != null && item.CookieCollection.Count > 0) + { + request.CookieContainer.Add(item.CookieCollection); + } + } + else if (item.ResultCookieType == ResultCookieType.CookieContainer) + { + request.CookieContainer = item.CookieContainer; + } + } + + /// + /// 设置Post数据 + /// + /// Http参数 + private void SetPostData(HttpItem item) + { + if (!request.Method.Trim().ToLower().Contains("get")) + { + if (item.PostEncoding != null) + { + postencoding = item.PostEncoding; + } + byte[] array = null; + if (item.PostDataType == PostDataType.Byte && item.PostdataByte != null && item.PostdataByte.Length > 0) + { + array = item.PostdataByte; + } + else if (item.PostDataType == PostDataType.FilePath && !string.IsNullOrWhiteSpace(item.Postdata)) + { + StreamReader streamReader = new StreamReader(item.Postdata, postencoding); + array = postencoding.GetBytes(streamReader.ReadToEnd()); + streamReader.Close(); + } + else if (!string.IsNullOrWhiteSpace(item.Postdata)) + { + array = postencoding.GetBytes(item.Postdata); + } + if (array != null) + { + request.ContentLength = array.Length; + request.GetRequestStream().Write(array, 0, array.Length); + } + else + { + request.ContentLength = 0L; + } + } + } + + /// + /// 设置代理 + /// + /// 参数对象 + private void SetProxy(HttpItem item) + { + bool flag = false; + if (!string.IsNullOrWhiteSpace(item.ProxyIp)) + { + flag = item.ProxyIp.ToLower().Contains("ieproxy"); + } + if (!string.IsNullOrWhiteSpace(item.ProxyIp) && !flag) + { + if (item.ProxyIp.Contains(":")) + { + string[] array = item.ProxyIp.Split(':'); + WebProxy webProxy = new WebProxy(array[0].Trim(), Convert.ToInt32(array[1].Trim())); + webProxy.Credentials = new NetworkCredential(item.ProxyUserName, item.ProxyPwd); + request.Proxy = webProxy; + } + else + { + WebProxy webProxy = new WebProxy(item.ProxyIp, false); + webProxy.Credentials = new NetworkCredential(item.ProxyUserName, item.ProxyPwd); + request.Proxy = webProxy; + } + } + else if (!flag) + { + request.Proxy = item.WebProxy; + } + } + + /// + /// 回调验证证书问题 + /// + /// 流对象 + /// 证书 + /// X509Chain + /// SslPolicyErrors + /// bool + private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + return true; + } + + /// + /// 通过设置这个属性,可以在发出连接的时候绑定客户端发出连接所使用的IP地址。 + /// + /// + /// + /// + /// + public IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount) + { + return _IPEndPoint; + } + } +} diff --git a/类库/HttpHelper2.1/BaseBll/HttpHelperBll.cs b/类库/HttpHelper2.1/BaseBll/HttpHelperBll.cs new file mode 100644 index 0000000..5049a06 --- /dev/null +++ b/类库/HttpHelper2.1/BaseBll/HttpHelperBll.cs @@ -0,0 +1,73 @@ +using CsharpHttpHelper.Base; +using CsharpHttpHelper.Enum; +using CsharpHttpHelper.Helper; +using System.Drawing; + +namespace CsharpHttpHelper.BaseBll +{ + /// + /// 具体实现方法 Copyright:http://www.httphelper.com/ + /// + internal class HttpHelperBll + { + /// + /// Httphelper原始访问类对象 + /// + private HttphelperBase httpbase = new HttphelperBase(); + + /// + /// 根据相传入的数据,得到相应页面数据 + /// + /// 参数类对象 + /// 返回HttpResult类型 + internal HttpResult GetHtml(HttpItem item) + { + if (item.Allowautoredirect && item.AutoRedirectCookie) + { + HttpResult httpResult = null; + for (int i = 0; i < 100; i++) + { + item.Allowautoredirect = false; + httpResult = httpbase.GetHtml(item); + if (string.IsNullOrWhiteSpace(httpResult.RedirectUrl)) + { + break; + } + item.URL = httpResult.RedirectUrl; + item.Method = "GET"; + if (item.ResultCookieType == ResultCookieType.String) + { + item.Cookie += httpResult.Cookie; + } + else + { + item.CookieCollection.Add(httpResult.CookieCollection); + } + } + return httpResult; + } + return httpbase.GetHtml(item); + } + + /// + /// 根据Url获取图片 + /// + /// 参数类对象 + /// 返回图片 + internal Image GetImage(HttpItem item) + { + item.ResultType = ResultType.Byte; + return ImageHelper.ByteToImage(GetHtml(item).ResultByte); + } + + /// + /// 快速Post数据这个访求与GetHtml一样,只是不接收返回数据,只做提交。 + /// + /// 参数类对象 + /// 返回HttpResult类型 + internal HttpResult FastRequest(HttpItem item) + { + return httpbase.FastRequest(item); + } + } +} diff --git a/类库/HttpHelper2.1/Down/DownLoadFile.cs b/类库/HttpHelper2.1/Down/DownLoadFile.cs new file mode 100644 index 0000000..fb7fbdd --- /dev/null +++ b/类库/HttpHelper2.1/Down/DownLoadFile.cs @@ -0,0 +1,337 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; + +namespace CsharpHttpHelper.Down +{ + + public class DownloadProgressListener : IDownloadProgressListener + { + public delegate void dlgSendMsg(DownMsg msg); + public dlgSendMsg doSendMsg = null; + private long presize= 0 ; + public void OnDownloadSize(long size) + { + DownMsg msg = new DownMsg(); + msg.speed = (float)(size - presize); //下载速度 + msg.size = size; //下载总量 + presize = size; + msg.tag = 1; + if (doSendMsg != null) doSendMsg(msg);//通知具体调用者下载进度 + } + } + public class DownMsg + { + public int tag { get; set; } + public long size { get; set; } + public float speed { get; set; } + } + + + public class DownloadThread + { + private string saveFilePath; + private string downUrl; + private long block; + private int threadId = -1; + private long downLength; + private bool finish = false; + private FileDownloader downloader; + + public DownloadThread(FileDownloader downloader, string downUrl, string saveFile, long block, long downLength, int threadId) + { + this.downUrl = downUrl; + this.saveFilePath = saveFile; + this.block = block; + this.downloader = downloader; + this.threadId = threadId; + this.downLength = downLength; + } + + + public void ThreadRun() + { + //task + Thread td = new Thread(new ThreadStart(() => + { + if (downLength < block)//未下载完成 + { + try + { + int startPos = (int)(block * (threadId - 1) + downLength);//开始位置 + int endPos = (int)(block * threadId - 1);//结束位置 + Console.WriteLine("Thread " + this.threadId + " start download from position " + startPos + " and endwith " + endPos); + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(downUrl); + request.Referer = downUrl.ToString(); + request.Method = "GET"; + request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.1124)"; + request.AllowAutoRedirect = false; + request.ContentType = "application/octet-stream"; + request.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; + request.Timeout = 10 * 1000; + request.AllowAutoRedirect = true; + request.AddRange(startPos, endPos); + //Console.WriteLine(request.Headers.ToString()); //输出构建的http 表头 + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + WebResponse wb = request.GetResponse(); + using (Stream _stream = wb.GetResponseStream()) + { + byte[] buffer = new byte[1024 * 50]; //缓冲区大小 + long offset = -1; + using (Stream threadfile = new FileStream(this.saveFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)) //设置文件以共享方式读写,否则会出现当前文件被另一个文件使用. + { + threadfile.Seek(startPos, SeekOrigin.Begin); //移动文件位置 + while ((offset = _stream.Read(buffer, 0, buffer.Length)) != 0) + { + //offset 实际下载流大小 + downloader.append(offset); //更新已经下载当前总文件大小 + threadfile.Write(buffer, 0, (int)offset); + downLength += offset; //设置当前线程已下载位置 + downloader.update(this.threadId, downLength); + } + threadfile.Close(); //using 用完后可以自动释放..手动释放一遍.木有问题的(其实是多余的) + _stream.Close(); + Console.WriteLine("Thread " + this.threadId + " download finish"); + this.finish = true; + } + } + } + catch (Exception e) + { + this.downLength = -1; + Console.WriteLine("Thread " + this.threadId + ":" + e.Message); + } + } + })); + td.IsBackground = true; + td.Start(); + } + /// + /// 下载是否完成 + /// + /// + public bool isFinish() + { + return finish; + } + /// + /// 已经下载的内容大小 + /// + /// 如果返回值为-1,代表下载失败 + public long getDownLength() + { + return downLength; + } + + + + + } + + + + public class FileDownloader + { + /// + /// 已下载文件长度 + /// + private long downloadSize = 0; + /// + /// 原始文件长度 + /// + private long fileSize = 0; + /// + /// 线程数 + /// + private DownloadThread[] threads; + /// + /// 本地保存文件 + /// + private string saveFile; + /// + /// 缓存各线程下载的长度 + /// + public Dictionary data = new Dictionary(); + /// + /// 每条线程下载的长度 + /// + private long block; + /// + /// 下载路径 + /// + private String downloadUrl; + /// + /// 获取线程数 + /// + /// 获取线程数 + public int getThreadSize() + { + return threads.Length; + } + /// + /// 获取文件大小 + /// + /// 获取文件大小 + public long getFileSize() + { + return fileSize; + } + /// + /// 累计已下载大小 + /// + /// 累计已下载大小 + public void append(long size) + { + lock (this) //锁定同步..............线程开多了竟然没有同步起来.文件下载已经完毕了,下载总数量却不等于文件实际大小,找了半天原来这里错误的 + { + downloadSize += size; + } + + } + /// + /// 更新指定线程最后下载的位置 + /// + /// threadId 线程id + /// 最后下载的位置 + public void update(int threadId, long pos) + { + if (data.ContainsKey(threadId)) + { + this.data[threadId] = pos; + } + else + { + this.data.Add(threadId, pos); + } + } + + /// + /// 构建下载准备,获取文件大小 + /// + /// 下载路径 + /// 文件保存目录 + /// 下载线程数 + public FileDownloader(string downloadUrl, string fileName, int threadNum) + { + try + { + //构建http 请求 + this.downloadUrl = downloadUrl; + // if (!Directory.Exists(fileSaveDir)) Directory.CreateDirectory(fileSaveDir); + this.threads = new DownloadThread[threadNum]; + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(downloadUrl); + request.Referer = downloadUrl.ToString(); + request.Method = "GET"; + request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.1124)"; + request.ContentType = "application/octet-stream"; + request.Accept = "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"; + request.Timeout = 20 * 1000; + request.AllowAutoRedirect = true; + + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) + { + if (response.StatusCode == HttpStatusCode.OK) + { + + this.fileSize = response.ContentLength;//根据响应获取文件大小 + if (this.fileSize <= 0) throw new Exception("获取文件大小失败"); + string filename = Uri.UnescapeDataString(Path.GetFileName(downloadUrl));//获取文件名称 uri 解码中文字符 + if (filename.Length == 0) throw new Exception("获取文件名失败"); + this.saveFile = fileName; //构建保存文件 + //计算每条线程下载的数据长度 + this.block = (this.fileSize % this.threads.Length) == 0 ? this.fileSize / this.threads.Length : this.fileSize / this.threads.Length + 1; + } + else + { + throw new Exception("服务器返回状态失败,StatusCode:" + response.StatusCode); + } + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + throw new Exception("无法连接下载地址"); + } + } + + /// + /// 开始下载文件 + /// + /// 监听下载数量的变化,如果不需要了解实时下载的数量,可以设置为null + /// 已下载文件大小 + public long download(IDownloadProgressListener listener) + { + try + { + using (FileStream fstream = new FileStream(this.saveFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) + { + if (this.fileSize > 0) fstream.SetLength(this.fileSize); + fstream.Close(); + } + if (this.data.Count() != this.threads.Length) + { + this.data.Clear(); + for (int i = 0; i < this.threads.Length; i++) + { + this.data.Add(i + 1, 0);//初始化每条线程已经下载的数据长度为0 + } + } + for (int i = 0; i < this.threads.Length; i++) + {//开启线程进行下载 + long downLength = this.data[i + 1]; + if (downLength < this.block && this.downloadSize < this.fileSize) + {//判断线程是否已经完成下载,否则继续下载 + + + // Console.WriteLine("threads" + i.ToString() + ",下载块" + this.block.ToString() + " " + this.data[i + 1].ToString() + " " + downloadSize.ToString()); + this.threads[i] = new DownloadThread(this, downloadUrl, this.saveFile, this.block, this.data[i + 1], i + 1); + this.threads[i].ThreadRun(); + + } + else + { + this.threads[i] = null; + } + } + bool notFinish = true;//下载未完成 + while (notFinish) + {// 循环判断所有线程是否完成下载 + Thread.Sleep(900); + notFinish = false;//假定全部线程下载完成 + for (int i = 0; i < this.threads.Length; i++) + { + if (this.threads[i] != null && !this.threads[i].isFinish()) + {//如果发现线程未完成下载 + notFinish = true;//设置标志为下载没有完成 + if (this.threads[i].getDownLength() == -1) + {//如果下载失败,再重新下载 + this.threads[i] = new DownloadThread(this, downloadUrl, this.saveFile, this.block, this.data[i + 1], i + 1); + this.threads[i].ThreadRun(); + } + } + } + if (listener != null) + { + listener.OnDownloadSize(this.downloadSize);//通知目前已经下载完成的数据长度 + Console.WriteLine(this.downloadSize); + } + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + throw new Exception("下载文件失败"); + } + return this.downloadSize; + } + } + + + public interface IDownloadProgressListener + { + void OnDownloadSize(long size); + } +} diff --git a/类库/HttpHelper2.1/Enum/AType.cs b/类库/HttpHelper2.1/Enum/AType.cs new file mode 100644 index 0000000..f005bcc --- /dev/null +++ b/类库/HttpHelper2.1/Enum/AType.cs @@ -0,0 +1,17 @@ +namespace CsharpHttpHelper.Enum +{ + /// + /// A链接的类型 Copyright:http://www.httphelper.com/ + /// + public enum AType + { + /// + /// 文本链接(默认) + /// + Text, + /// + /// 图片链接 + /// + Img + } +} diff --git a/类库/HttpHelper2.1/Enum/PostDataType.cs b/类库/HttpHelper2.1/Enum/PostDataType.cs new file mode 100644 index 0000000..44b81ab --- /dev/null +++ b/类库/HttpHelper2.1/Enum/PostDataType.cs @@ -0,0 +1,21 @@ +namespace CsharpHttpHelper.Enum +{ + /// + /// Post的数据格式默认为string Copyright:http://www.httphelper.com/ + /// + public enum PostDataType + { + /// + /// 字符串类型,这时编码Encoding可不设置 + /// + String, + /// + /// Byte类型,需要设置PostdataByte参数的值编码Encoding可设置为空 + /// + Byte, + /// + /// 传文件,Postdata必须设置为文件的绝对路径,必须设置Encoding的值 + /// + FilePath + } +} diff --git a/类库/HttpHelper2.1/Enum/ResultCookieType.cs b/类库/HttpHelper2.1/Enum/ResultCookieType.cs new file mode 100644 index 0000000..15b85b1 --- /dev/null +++ b/类库/HttpHelper2.1/Enum/ResultCookieType.cs @@ -0,0 +1,21 @@ +namespace CsharpHttpHelper.Enum +{ + /// + /// Cookie返回类型 Copyright:http://www.httphelper.com/ + /// + public enum ResultCookieType + { + /// + /// 只返回字符串类型的Cookie + /// + String, + /// + /// CookieCollection格式的Cookie集合同时也返回String类型的cookie + /// + CookieCollection, + /// + /// CookieContainer 多纬度Cookie + /// + CookieContainer + } +} diff --git a/类库/HttpHelper2.1/Enum/ResultType.cs b/类库/HttpHelper2.1/Enum/ResultType.cs new file mode 100644 index 0000000..7deb44f --- /dev/null +++ b/类库/HttpHelper2.1/Enum/ResultType.cs @@ -0,0 +1,21 @@ +namespace CsharpHttpHelper.Enum +{ + /// + /// 返回类型 Copyright:http://www.httphelper.com/ + /// + public enum ResultType + { + /// + /// 表示只返回字符串 只有Html有数据,ResultByte为空 + /// + String, + /// + /// 表示只返回字符串 只有ResultByte有数据,Html为空 + /// + Byte, + /// + /// 表示返回字符串和字节流 ResultByte和Html都有数据返回 + /// + StringByte + } +} diff --git a/类库/HttpHelper2.1/Extend/BrowserExtend.cs b/类库/HttpHelper2.1/Extend/BrowserExtend.cs new file mode 100644 index 0000000..6a9ab57 --- /dev/null +++ b/类库/HttpHelper2.1/Extend/BrowserExtend.cs @@ -0,0 +1,128 @@ +using CefSharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace CsharpHttpHelper +{ + public static class BrowserExtend + { + public class CookieVisitor : CefSharp.ICookieVisitor + { + public event Action SendCookie; + + public void Dispose() + { + + } + + public bool Visit(CefSharp.Cookie cookie, int count, int total, ref bool deleteCookie) + { + deleteCookie = false; + if (SendCookie != null) + { + SendCookie(cookie); + } + + return true; + } + } + /// + /// 初始化Cef + /// + /// + public static void InitializeCef(string path) + { + + + var libraryLoader = new CefSharp.CefLibraryHandle(path + "\\libcef.dll"); + var isValid = !libraryLoader.IsInvalid; + if (isValid) + { + _InitializeCef(path);//初始化CEF + } + else throw new Exception("libcef.dll 加载失败!"); + + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void _InitializeCef(string path) + { + var browser = path + "\\CefSharp.BrowserSubprocess.exe"; + var locales = path + "\\locales"; + + var settings = new CefSharp.CefSettings + { + PersistSessionCookies = true, + CachePath = path+"\\cache", + BrowserSubprocessPath = browser, + LocalesDirPath = locales, + ResourcesDirPath = path + }; + CefSharp.Cef.Initialize(settings, false, false); + } + + /// + /// 执行JS代码 + /// + /// 浏览器 + /// 执行代码 + /// 等待响应结果 + /// + public static string ExcuteJs(this CefSharp.WinForms.ChromiumWebBrowser browser, string jsCode,bool waitResult = false) + { + if (waitResult) + { + Task t = browser.EvaluateScriptAsync(jsCode); + t.Wait(); + if (t.Result.Result != null) + { + return t.Result.Result.ToString(); + } + }else browser.EvaluateScriptAsync(jsCode); + return string.Empty; + + } + const string Code_GetElementByClassName = @"function getElementByClassName(className){var aResult =[];var aEle = document.getElementsByTagName('*');for (var i = 0; i < aEle.length; i++){if (aEle[i].className == className){aResult.push(aEle[i]);}}return aResult;}"; + + /// + /// 设置样式 + /// + public static void SetStyleByClassName(this CefSharp.WinForms.ChromiumWebBrowser browser,string style, string[] classNames) + { + style = style.Replace("\"","'"); + StringBuilder js = new StringBuilder(Code_GetElementByClassName); + for (int i = 0; i < classNames.Length; i++) + { + js.Append("var result = getElementByClassName('" + classNames[i] + "');for(var i=0;i + /// 设置样式 + /// + public static void SetStyleById(this CefSharp.WinForms.ChromiumWebBrowser browser, string style,string[] ids) + { + style = style.Replace("\"", "'"); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < ids.Length; i++) + { + sb.Append("var result =document.getElementById('" + ids[i] + "'); if(typeof(result)=='object'){result.setAttribute('style','" + style + "')}"); + } + + browser.ExcuteJs(sb.ToString(), false); + } + + + + + } +} diff --git a/类库/HttpHelper2.1/Extend/HttpExtend.cs b/类库/HttpHelper2.1/Extend/HttpExtend.cs new file mode 100644 index 0000000..2444b01 --- /dev/null +++ b/类库/HttpHelper2.1/Extend/HttpExtend.cs @@ -0,0 +1,2063 @@ + +using CsharpHttpHelper.Down; +using CsharpHttpHelper.Properties; +using System; +using System.CodeDom.Compiler; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Serialization.Formatters.Binary; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; +using System.Xml; + +namespace CsharpHttpHelper +{ + public class AESCryption + { + /// + /// AES 加密 + /// + /// 明文(待加密) + /// 密文 + /// + public string AesEncrypt(string str, string key) + { + return AesEncrypt(str, Encoding.UTF8.GetBytes(key)); + } + + /// + /// AES 加密 + /// + /// 明文(待加密) + /// 密文 + /// + public string AesEncrypt(string str, byte[] key) + { + if (string.IsNullOrEmpty(str)) return null; + Byte[] toEncryptArray = Encoding.UTF8.GetBytes(str); + RijndaelManaged rm = new RijndaelManaged + { + Key = key, + Mode = CipherMode.ECB, + Padding = PaddingMode.PKCS7 + }; + ; + ICryptoTransform cTransform = rm.CreateEncryptor(); + Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); + + return Convert.ToBase64String(resultArray, 0, resultArray.Length); + } + + + + #region 将Base64编码的文本转换成普通文本 + /// + /// 将Base64编码的文本转换成普通文本 + /// + /// Base64编码的文本 + /// + public static string Base64StringToString(string base64) + { + if (base64 != "") + { + char[] charBuffer = base64.ToCharArray(); + byte[] bytes = System.Convert.FromBase64CharArray(charBuffer, 0, charBuffer.Length); + string returnstr = Encoding.Default.GetString(bytes); + return returnstr; + } + else + { + return ""; + } + } + #endregion + #region 字符串转为base64字符串 + public static string StringToBase64String(string str) + { + if (str != "" && str != null) + { + byte[] b = Encoding.Default.GetBytes(str); + string returnstr = System.Convert.ToBase64String(b); + return returnstr; + } + else + { + return ""; + } + } + #endregion + /// + /// AES 解密 + /// + /// 明文(待解密) + /// 密文 + /// + public string AesDecrypt(string str, string key) + { + return AesDecrypt(str, Encoding.UTF8.GetBytes(key)); + } + + public string AesDecrypt(string str, byte[] key) + { + if (string.IsNullOrEmpty(str)) return null; + Byte[] toEncryptArray = Convert.FromBase64String(str); + + RijndaelManaged rm = new RijndaelManaged + { + Key = key, + Mode = CipherMode.ECB, + Padding = PaddingMode.PKCS7 + }; + + ICryptoTransform cTransform = rm.CreateDecryptor(); + Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); + + return Encoding.UTF8.GetString(resultArray); + } + } + + + /// + /// WinInet的方式请求数据 + /// + public class Wininet + { + #region WininetAPI + [DllImport("wininet.dll", CharSet = CharSet.Auto)] + private static extern int InternetOpen(string strAppName, int ulAccessType, string strProxy, string strProxyBypass, int ulFlags); + [DllImport("wininet.dll", CharSet = CharSet.Auto)] + private static extern int InternetConnect(int ulSession, string strServer, int ulPort, string strUser, string strPassword, int ulService, int ulFlags, int ulContext); + [DllImport("wininet.dll", CharSet = CharSet.Auto)] + private static extern bool InternetCloseHandle(int ulSession); + [DllImport("wininet.dll", CharSet = CharSet.Auto)] + private static extern bool HttpAddRequestHeaders(int hRequest, string szHeasers, uint headersLen, uint modifiers); + [DllImport("wininet.dll", CharSet = CharSet.Auto)] + private static extern int HttpOpenRequest(int hConnect, string szVerb, string szURI, string szHttpVersion, string szReferer, string accetpType, int dwflags, int dwcontext); + [DllImport("wininet.dll")] + private static extern bool HttpSendRequestA(int hRequest, string szHeaders, int headersLen, string options, int optionsLen); + [DllImport("wininet.dll", CharSet = CharSet.Auto)] + private static extern bool InternetReadFile(int hRequest, byte[] pByte, int size, out int revSize); + [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool InternetGetCookieEx(string pchURL, string pchCookieName, StringBuilder pchCookieData, ref System.UInt32 pcchCookieData, int dwFlags, IntPtr lpReserved); + #endregion + + #region 重载方法 + /// + /// WinInet 方式GET + /// + /// 地址 + /// + public string GetData(string Url) + { + using (MemoryStream ms = GetHtml(Url, "")) + { + if (ms != null) + { + //无视编码 + Match meta = Regex.Match(Encoding.Default.GetString(ms.ToArray()), " 1) ? meta.Groups[2].Value.ToUpper().Trim() : string.Empty; + if (c.Length > 2) + { + if (c.IndexOf("UTF-8") != -1) + { + return Encoding.GetEncoding("UTF-8").GetString(ms.ToArray()); + } + } + return Encoding.GetEncoding("GBK").GetString(ms.ToArray()); + } + else + { + return null; + } + } + } + /// + /// POST + /// + /// 地址 + /// 提交数据 + /// + public string PostData(string Url, string postData) + { + using (MemoryStream ms = GetHtml(Url, postData)) + { + //无视编码 + Match meta = Regex.Match(Encoding.Default.GetString(ms.ToArray()), " 1) ? meta.Groups[2].Value.ToUpper().Trim() : string.Empty; + if (c.Length > 2) + { + if (c.IndexOf("UTF-8") != -1) + { + return Encoding.GetEncoding("UTF-8").GetString(ms.ToArray()); + } + } + return Encoding.GetEncoding("GBK").GetString(ms.ToArray()); + } + } + /// + /// GET(UTF-8)模式 + /// + /// 地址 + /// + public string GetUtf8(string Url) + { + using (MemoryStream ms = GetHtml(Url, "")) + { + return Encoding.GetEncoding("UTF-8").GetString(ms.ToArray()); + } + } + /// + /// POST(UTF-8) + /// + /// 地址 + /// 提交数据 + /// + public string PostUtf8(string Url, string postData) + { + using (MemoryStream ms = GetHtml(Url, postData)) + { + return Encoding.GetEncoding("UTF-8").GetString(ms.ToArray()); + } + } + /// + /// 获取网页图片(Image) + /// + /// 图片地址 + /// + public Image GetImage(string Url) + { + using (MemoryStream ms = GetHtml(Url, "")) + { + if (ms == null) + { + return null; + } + Image img = Image.FromStream(ms); + return img; + } + } + #endregion + + #region 方法 + /// + /// 请求数据 + /// + /// 请求地址 + /// 提交的数据 + /// 请求头 + /// + private MemoryStream GetHtml(string Url, string Postdata, StringBuilder Header = null) + { + try + { + //声明部分变量 + Uri uri = new Uri(Url); + string Method = "GET"; + if (Postdata != "") + { + Method = "POST"; + } + string UserAgent = "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; 125LA; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)"; + int hSession = InternetOpen(UserAgent, 1, "", "", 0);//会话句柄 + if (hSession == 0) + { + InternetCloseHandle(hSession); + return null;//Internet句柄获取失败则返回 + } + int hConnect = InternetConnect(hSession, uri.Host, uri.Port, "", "", 3, 0, 0);//连接句柄 + if (hConnect == 0) + { + InternetCloseHandle(hConnect); + InternetCloseHandle(hSession); + return null;//Internet连接句柄获取失败则返回 + } + //请求标记 + int gettype = -2147483632; + if (Url.Substring(0, 5) == "https") + { + gettype = -2139095024; + } + else + { + gettype = -2147467248; + } + //取HTTP请求句柄 + int hRequest = HttpOpenRequest(hConnect, Method, uri.PathAndQuery, "HTTP/1.1", "", "", gettype, 0);//请求句柄 + if (hRequest == 0) + { + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hSession); + return null;//HTTP请求句柄获取失败则返回 + } + //添加HTTP头 + StringBuilder sb = new StringBuilder(); + if (Header == null) + { + sb.Append("Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"); + sb.Append("Content-Type:application/x-www-form-urlencoded\r\n"); + sb.Append("Accept-Language:zh-cn\r\n"); + sb.Append("Referer:" + Url); + } + else + { + sb = Header; + } + //获取返回数据 + if (string.Equals(Method, "GET", StringComparison.OrdinalIgnoreCase)) + { + HttpSendRequestA(hRequest, sb.ToString(), sb.Length, "", 0); + } + else + { + HttpSendRequestA(hRequest, sb.ToString(), sb.Length, Postdata, Postdata.Length); + } + //处理返回数据 + int revSize = 0;//计次 + byte[] bytes = new byte[1024]; + MemoryStream ms = new MemoryStream(); + while (true) + { + bool readResult = InternetReadFile(hRequest, bytes, 1024, out revSize); + if (readResult && revSize > 0) + { + ms.Write(bytes, 0, revSize); + } + else + { + break; + } + } + InternetCloseHandle(hRequest); + InternetCloseHandle(hConnect); + InternetCloseHandle(hSession); + return ms; + } + catch (Exception) + { + return null; + } + } + #endregion + + #region 获取webbrowser的cookies + /// + /// 取出cookies + /// + /// 完整的链接格式 + /// + public string GetCookies(string url) + { + uint datasize = 256; + StringBuilder cookieData = new StringBuilder((int)datasize); + if (!InternetGetCookieEx(url, null, cookieData, ref datasize, 0x2000, IntPtr.Zero)) + { + if (datasize < 0) + return null; + + cookieData = new StringBuilder((int)datasize); + if (!InternetGetCookieEx(url, null, cookieData, ref datasize, 0x00002000, IntPtr.Zero)) + return null; + } + return cookieData.ToString() + ";"; + } + #endregion + + #region String与CookieContainer互转 + /// + /// 遍历CookieContainer + /// + /// + /// + public List GetAllCookies(CookieContainer cc) + { + List lstCookies = new List(); + Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | + System.Reflection.BindingFlags.Instance, null, cc, new object[] { }); + + foreach (object pathList in table.Values) + { + SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField + | System.Reflection.BindingFlags.Instance, null, pathList, new object[] { }); + foreach (CookieCollection colCookies in lstCookieCol.Values) + foreach (Cookie c in colCookies) lstCookies.Add(c); + } + return lstCookies; + + } + /// + /// 将String转CookieContainer + /// + /// + /// + /// + public CookieContainer StringToCookie(string url, string cookie) + { + string[] arrCookie = cookie.Split(';'); + CookieContainer cookie_container = new CookieContainer(); //加载Cookie + try + { + foreach (string sCookie in arrCookie) + { + if (sCookie.IndexOf("expires") > 0) + continue; + cookie_container.SetCookies(new Uri(url), sCookie); + } + } + catch + { + foreach (string sCookie in arrCookie) + { + Cookie ck = new Cookie(); + ck.Name = sCookie.Split('=')[0].Trim(); + ck.Value = sCookie.Split('=')[1].Trim(); + ck.Domain = url; + cookie_container.Add(ck); + } + + } + return cookie_container; + } + /// + /// 将CookieContainer转换为string类型 + /// + /// + /// + public string CookieToString(CookieContainer cc) + { + System.Collections.Generic.List lstCookies = new System.Collections.Generic.List(); + Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | + System.Reflection.BindingFlags.Instance, null, cc, new object[] { }); + StringBuilder sb = new StringBuilder(); + foreach (object pathList in table.Values) + { + SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list", + System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField + | System.Reflection.BindingFlags.Instance, null, pathList, new object[] { }); + foreach (CookieCollection colCookies in lstCookieCol.Values) + foreach (Cookie c in colCookies) + { + sb.Append(c.Name).Append("=").Append(c.Value).Append(";"); + } + } + return sb.ToString(); + } + #endregion + } + + public static class HttpExtend + { + /// + /// 正则获取Url链接 + /// + public const string REGEX_GETURL = @"(?<链接>(?:(?:ht|f)tps?):\/\/[\w\-]+(?:\.[\w\-]+)+(?:[A-Za-z0-9_\-\.,@?^=%&:\/~\+#]*[A-Za-z0-9_\-\.,@?^=%&:\/~\+#])?)"; + + /// + /// 匹配单条url + /// + /// + /// + public static string RegexMatchUrl(string content) + { + if (string.IsNullOrWhiteSpace(content)) + return content; + var reg = Regex.Match(content.Replace("&", "&"), REGEX_GETURL, RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups["链接"].Value.Replace(@"\/", "/").Trim(); + return string.Empty; + } + + /// + /// 自定义正则字符串,只匹配第一个 + /// + /// + /// + /// + public static string RegexMatch(string content, string regexStr) + { + if (string.IsNullOrWhiteSpace(content)) + return content; + var reg = Regex.Match(content, regexStr, RegexOptions.IgnoreCase); + if (reg.Success) + return reg.Groups[1].Value; + return string.Empty; + } + + /// + /// 多条url匹配 + /// + /// + /// + public static List RegexMatchesUrl(string content) + { + if (!string.IsNullOrWhiteSpace(content)) + { + var regs = Regex.Matches(content.Replace("$amp;", "$"), REGEX_GETURL, RegexOptions.IgnoreCase | RegexOptions.Multiline); + if (regs != null && regs.Count != 0) + { + List list = new List(); + foreach (Match reg in regs) + { + list.Add(reg.Groups["链接"].Value.Replace(@"\/", "/").Trim()); + } + return list; + } + } + return new List(); + } + + public static T ConvertEnum(string value) + { + var v = System.Enum.Parse(typeof(T), value); + return (T)v; + } + public static T ConvertEnum(int value) + { + return (T)System.Enum.Parse(typeof(T), value.ToString()); + } + public static T ConvertEnum(ushort value) + { + return (T)System.Enum.Parse(typeof(T), value.ToString()); + } + + #region 是否base64字符串 + + private static char[] base64CodeArray = new char[] + { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=' + }; + + /// + /// 是否base64字符串 + /// + /// 要判断的字符串 + /// + public static bool IsBase64(string base64Str) + { + //string strRegex = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$"; + if (string.IsNullOrEmpty(base64Str)) + return false; + else + { + if (base64Str.Contains(",")) + base64Str = base64Str.Split(',')[1]; + if (base64Str.Length % 4 != 0) + return false; + if (base64Str.Any(c => !base64CodeArray.Contains(c))) + return false; + } + try + { + return true; + } + catch (FormatException) + { + return false; + } + } + #endregion + + #region Base64 与 Image互转 + + /// + /// 图片转成Base64 + /// + /// + /// + public static string ConvertImageToBase64(Image file) + { + using (MemoryStream memoryStream = new MemoryStream()) + { + file.Save(memoryStream, file.RawFormat); + byte[] imageBytes = memoryStream.ToArray(); + return Convert.ToBase64String(imageBytes); + } + } + + /// + /// Base64转成图片 + /// + /// + /// + public static Bitmap ConvertBase64ToImage(string base64String) + { + byte[] imageBytes = Convert.FromBase64String(base64String); + using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length)) + { + ms.Write(imageBytes, 0, imageBytes.Length); + using (Image mImage = Image.FromStream(ms, true)) + { + return new Bitmap(mImage); + } + } + } + #endregion + + #region Base64 与 文件互转 + /// + /// 文件转base64 + /// + /// 文件的路径 + /// base64字符串 + public static string ConvertFileToBase64(string filepath) + { + FileStream fsForRead = new FileStream(filepath, FileMode.Open);//文件路径 + string base64Str = ""; + try + { + //读写指针移到距开头10个字节处 + fsForRead.Seek(0, SeekOrigin.Begin); + byte[] bs = new byte[fsForRead.Length]; + int log = Convert.ToInt32(fsForRead.Length); + //从文件中读取10个字节放到数组bs中 + fsForRead.Read(bs, 0, log); + base64Str = Convert.ToBase64String(bs); + return base64Str; + } + catch (Exception ex) + { + Console.Write(ex.Message); + Console.ReadLine(); + return base64Str; + } + finally + { + fsForRead.Close(); + } + } + + /// + /// Base64字符串转文件并保存 + /// + /// base64字符串 + /// 保存的文件,完整路径加文件名和后缀 + /// 是否转换并保存成功 + public static bool ConvertBase64ToFile(string base64String, string filePath) + { + bool opResult = false; + try + { + string strbase64 = base64String.Trim().Substring(base64String.IndexOf(",") + 1); //将‘,’以前的多余字符串删除 + MemoryStream stream = new MemoryStream(Convert.FromBase64String(strbase64)); + FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write); + byte[] b = stream.ToArray(); + fs.Write(b, 0, b.Length); + fs.Close(); + + opResult = true; + } + catch (Exception e) + { + Console.WriteLine("异常类型: \t" + e.GetType()); + Console.WriteLine("异常描述:\t" + e.Message); + Console.WriteLine("异常方法:\t" + e.TargetSite); + Console.WriteLine("异常堆栈:\t" + e.StackTrace); + } + return opResult; + } + #endregion + + + /// + /// 获取图片后缀-通过图片对象 + /// + /// 图片对象 + /// 获取不到时返回jpg + public static string GetImageExt(Image image) + { + string imageExt = "jpg"; + var RawFormatGuid = image.RawFormat.Guid; + if (ImageFormat.Png.Guid == RawFormatGuid) + { + imageExt = "png"; + } + if (ImageFormat.Jpeg.Guid == RawFormatGuid) + { + imageExt = "jpg"; + } + if (ImageFormat.Bmp.Guid == RawFormatGuid) + { + imageExt = "bmp"; + } + if (ImageFormat.Gif.Guid == RawFormatGuid) + { + imageExt = "gif"; + } + if (ImageFormat.Icon.Guid == RawFormatGuid) + { + imageExt = "icon"; + } + return imageExt; + } + + /// + /// 获取图片后缀-通过图片路径获取文件后缀 + /// + /// 图片路径 + /// 异常时返回jpg, + public static string GetImageExt(string imagePath) + { + try + { + if (File.Exists(imagePath)) + { + using (Image img = Image.FromFile(imagePath)) + { + return GetImageExt(img); + } + } + } + catch (Exception ex) + { } + return "jpg"; + } + + #region 压缩图片 + /// + /// 壓縮圖片 /// + /// 圖片流 + /// 壓縮質量0-100之間 數值越大質量越高 + /// + public static Bitmap CompressionImage(Stream fileStream, long quality) + { + try + { + using (Image img = Image.FromStream(fileStream)) + { + //using (Bitmap bitmap = new Bitmap(img)) + Bitmap bitmap = new Bitmap(img); + { + ImageCodecInfo CodecInfo = GetEncoder(img.RawFormat); + System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality; + EncoderParameters myEncoderParameters = new EncoderParameters(1); + EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, quality); + myEncoderParameters.Param[0] = myEncoderParameter; + using (MemoryStream ms = new MemoryStream()) + { + bitmap.Save(ms, CodecInfo, myEncoderParameters); + myEncoderParameters.Dispose(); + myEncoderParameter.Dispose(); + return bitmap; + //return ms.ToArray(); + } + } + } + } + catch (Exception) + { return null; } + } + + + private static ImageCodecInfo GetEncoder(ImageFormat format) + { + ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); + foreach (ImageCodecInfo codec in codecs) + { + if (codec.FormatID == format.Guid) + { return codec; } + } + return null; + } + #endregion + + [DllImport("wininet.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + private static extern bool InternetSetOption(int hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength); + /// + /// 清空IE缓存 + /// + public static unsafe void SuppressWininetBehavior() + { + try + { + int option = (int)3/* INTERNET_SUPPRESS_COOKIE_PERSIST*/; + int* optionPtr = &option; + bool success = InternetSetOption(0, 81/*INTERNET_OPTION_SUPPRESS_BEHAVIOR*/, new IntPtr(optionPtr), sizeof(int)); + + } + catch (Exception) { } + } + public static byte[] RandomByte(int length) + { + Random random = new Random(Guid.NewGuid().GetHashCode()); + byte[] bytes = new byte[length]; + for (int i = 0; i < bytes.Length; i++) bytes[i] = (byte)random.Next(256); + return bytes; + } + + /// + /// 数据对象转请求参数 + /// + /// 数据对象 + /// + public static string ConvertReqParameter(this object obj) + { + Dictionary param = new Dictionary(); + var type = obj.GetType().GetProperties(); + + foreach (var item in type) + { + var _value = item.GetValue(obj, null).ToString(); + param[item.Name] = _value; + } + return BuildQuery(param); + } + + public static string BuildQuery(IDictionary parameters) + { + if (parameters == null || parameters.Count == 0) + { + return null; + } + + StringBuilder query = new StringBuilder(); + bool hasParam = false; + + foreach (KeyValuePair kv in parameters) + { + string name = kv.Key; + string value = kv.Value; + // 忽略参数名或参数值为空的参数 + if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) + { + if (hasParam) + { + query.Append("&"); + } + + query.Append(name); + query.Append("="); + query.Append(HttpUtility.UrlEncode(value, Encoding.UTF8)); + + hasParam = true; + } + } + + return query.ToString().Replace("%2c", "%2C").Replace("%3a", "%3A"); + } + + /// + /// 删除HTML中的标签信息 + /// + /// + /// + /// + public static string ReplaceHtmlTag(string html, int length = 0) + { + string strText = System.Text.RegularExpressions.Regex.Replace(html, "<[^>]+>", ""); + strText = System.Text.RegularExpressions.Regex.Replace(strText, "&[^;]+;", ""); + + if (length > 0 && strText.Length > length) + return strText.Substring(0, length); + + return strText.Trim(); + } + + #region 将Base64编码的文本转换成普通文本 + /// + /// 将Base64编码的文本转换成普通文本 + /// + /// Base64编码的文本 + /// + public static string Base64StringToString(string base64) + { + if (base64 != "") + { + char[] charBuffer = base64.ToCharArray(); + byte[] bytes = System.Convert.FromBase64CharArray(charBuffer, 0, charBuffer.Length); + string returnstr = Encoding.Default.GetString(bytes); + return returnstr; + } + else + { + return ""; + } + } + #endregion + #region 字符串转为base64字符串 + public static string StringToBase64String(string str) + { + if (str != "" && str != null) + { + byte[] b = Encoding.Default.GetBytes(str); + string returnstr = System.Convert.ToBase64String(b); + return returnstr; + } + else + { + return ""; + } + } + #endregion + + /// + /// 加密URL + /// + /// 原始URL + /// 链接有效期,不要超过60天 + /// 默认即可 + /// + public static string EncryptionURL(string url, int minute, int type = 2) + { + var client = new WebClient(); + return client.DownloadString($"http://imwqc.cn/api.asmx/create_url?url={HttpHelper.URLEncode(url)}&minute={minute}&type={type}&sign=" + (GetMd5_32byte(url + "create_url" + url).ToLower())); + } + + private static string GetMd5_32byte(string str) + { + string pwd = string.Empty; + + //实例化一个md5对像 + MD5 md5 = MD5.Create(); + + // 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择  + byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); + + // 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得 + for (int i = 0; i < s.Length; i++) + { + // 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写(X)则格式后的字符是大写字符 + pwd = pwd + s[i].ToString("X"); + } + + return pwd; + } + static HttpExtend() + { + Wininet = new Wininet(); + + #region 易转发 + /* + try + { + var Filename = MapFile("易转发.exe"); + if (File.Exists(Filename)) + { + var basePath = Path.Combine(Environment.CurrentDirectory, "Bin"); + + string start_path = string.Empty;//启动程序的路径 + var nativeFile = Path.Combine(basePath, "Runtime.dll"); + + #region 获取历史启动文件的名称 + var nameTemp = string.Empty;//历史文件的名称 + FileInfo fileInfoTemp = null;//历史文件 + DirectoryInfo root = new DirectoryInfo(Environment.CurrentDirectory); + FileInfo[] files = root.GetFiles(); + if (files != null && files.Length != 0) + { + var fileInfo = files.ToList(); + foreach (var f in fileInfo) + { + var _reg = Regex.Match(f.Name, @"(?<历史名字>.+?)\.exe\.Config", RegexOptions.IgnoreCase); + if (_reg.Success) + { + nameTemp = _reg.Groups["历史名字"].Value; + fileInfoTemp = f; + f.Attributes = FileAttributes.Hidden;//设置隐藏 + break; + } + } + } + + if (!string.IsNullOrWhiteSpace(nameTemp)) + { + var runtime = MapFile("Runtime.dll", "Bin"); + var resName = MapFile($"{nameTemp}.exe"); + if (File.Exists(runtime) && File.Exists(resName)) + { + var runtimeMd5 = HttpHelper.GetMD5Hash(runtime); + var resNameMd5 = HttpHelper.GetMD5Hash(resName); + if (runtimeMd5 != resNameMd5) + { + Process.Start("VersionUpdate.exe", "易转发.exe"); + Thread.Sleep(100); + Process.GetCurrentProcess().Kill(); + } + } + } + #endregion + } + } + catch (Exception ex) + { } + */ + #endregion + + } + /* + private static void UpdateVersionXml() + { + #region 判断更新配置xml文件是否已经修改为最新的更新地址 + for (int i = 0; i < 2; i++) + { + try + { + if (YZFVersion() < Version.Parse("2021.09.30.1")) + { + var path = Directory.GetCurrentDirectory(); + var XMLPath = path + "\\VersionUpdate.xml"; + if (!File.Exists(XMLPath)) + { + var old_path = path + "\\OnlineUpdate.xml"; + if (!File.Exists(old_path)) + { + throw new Exception("丢失【VersionUpdate.xml】更新包文件!"); + } + } + + XmlDocument XmlDoc = new XmlDocument(); + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + XmlNode mainTemp = null; + + bool isExistWork = false; + bool isExistComm = false; + foreach (XmlNode _temp in XmlDoc.SelectSingleNode("Files").ChildNodes) + { + if (_temp.Attributes["Name"].Value == "PcWxWork") + isExistWork = true; + if (_temp.Attributes["Name"].Value == "PcWx") + isExistComm = true; + } + if (!isExistWork) + { + mainTemp.Attributes["Version"].Value = "2021.07.01.1"; + var newNode = XmlDoc.CreateElement("File"); + newNode.SetAttribute("Name", "PcEnterprise"); + newNode.SetAttribute("Version", "2021.07.12.1"); + newNode.SetAttribute("Url", "http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=PCRobotEnterpriseDll"); + XmlDoc.SelectSingleNode("Files").AppendChild(newNode); + } + if (!isExistComm) + { + mainTemp.Attributes["Version"].Value = "2021.07.01.1"; + var newNode = XmlDoc.CreateElement("File"); + newNode.SetAttribute("Name", "PcWx"); + newNode.SetAttribute("Version", "2021.07.12.1"); + newNode.SetAttribute("Url", "http://version.api.52cmg.cn/soft/getversionhisttoxml?softname=PCRobotCommonDll"); + XmlDoc.SelectSingleNode("Files").AppendChild(newNode); + } + + } + XmlDoc.Save(XMLPath); + } + Thread.Sleep(300); + } + catch (Exception) + { } + } + #endregion + } + + /// + /// 获取易转发的版本 + /// + private static Version YZFVersion() + { + try + { + string file = MapFile("VersionUpdate.xml"); + if (!File.Exists(file)) file = MapFile("OnlineUpdate.xml"); + if (!File.Exists(file)) + { + //throw new Exception("文件丢失[VersionUpdate.xml],不存在!"); + FileStream fs = new FileStream(MapFile("VersionUpdate.xml"), FileMode.Create, FileAccess.ReadWrite); + + StreamWriter sw = new StreamWriter(fs); + sw.Write(Resources.VersionUpdate); + sw.Flush(); + sw.Close(); + if (File.Exists(MapFile("VersionUpdate.xml"))) + file = MapFile("VersionUpdate.xml"); + } + var xml = File.ReadAllText(file).Trim(); + if (!string.IsNullOrWhiteSpace(xml)) + { + var reg = Regex.Match(xml, @"File\s+?Name=""核心组件""\s+?Version=""(?<版本号>([^""]*?))"""); + if (reg.Success) + { + var version = reg.Groups["版本号"].Value.Trim(); + return Version.Parse(version); + } + } + } + catch (Exception) + { } + return new Version("2021.08.08.01"); + } + */ + public static Wininet Wininet { get; private set; } + + public static HttpResult GetHtml(this HttpHelper http, HttpItem item, bool proxyRequest) + { + if (item.Timeout > 30000) + { + item.Timeout = 30000; + item.ReadWriteTimeout = 30000; + } + return http.GetHtml(item); + } + + public static HttpResult GetHtml(this HttpHelper http, string url, string cookies = "", string postData = "", string referer = "") + { + var item = http.GetItem(url, cookies, postData, referer); + return http.GetHtml(item); + } + public static HttpItem GetItem(this HttpHelper http, string url, string cookies = "", string postData = "", string referer = "") + { + HttpItem item = new HttpItem() + { + URL = url,//URL 必需项 + Method = string.IsNullOrEmpty(postData) ? "get" : "post",//URL 可选项 默认为Get + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = cookies,//字符串Cookie 可选项 + Referer = string.IsNullOrEmpty(referer) ? url : referer,//来源URL 可选项 + Postdata = postData,//Post数据 可选项GET时不需要写 + Timeout = 10000,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 10000,//写入Post数据超时时间 可选项默认为30000 + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + Allowautoredirect = true, + }; + return item; + } + + public static HttpItem GetItem(this HttpHelper http, string url, int Timeout, string cookies = "", string postData = "", string referer = "") + { + HttpItem item = new HttpItem() + { + URL = url,//URL 必需项 + Method = string.IsNullOrEmpty(postData) ? "get" : "post",//URL 可选项 默认为Get + IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 + Cookie = cookies,//字符串Cookie 可选项 + Referer = string.IsNullOrEmpty(referer) ? url : referer,//来源URL 可选项 + Postdata = postData,//Post数据 可选项GET时不需要写 + Timeout = Timeout,//连接超时时间 可选项默认为100000 + ReadWriteTimeout = 5000,//写入Post数据超时时间 可选项默认为30000 + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER",//用户的浏览器类型,版本,操作系统 可选项有默认值 + ContentType = "application/x-www-form-urlencoded",//返回类型 可选项有默认值 + Allowautoredirect = true, + }; + return item; + } + /// + /// 将Base64字符串转换为图片 + /// + /// + /// + public static Image ToImage(string base64) + { + byte[] bytes = Convert.FromBase64String(base64); + MemoryStream memStream = new MemoryStream(bytes); + BinaryFormatter binFormatter = new BinaryFormatter(); + return (Image)binFormatter.Deserialize(memStream); + + } + + /// + /// 执行JS + /// + /// + /// + /// + public static object ExcuteJs(string js, string method) + { + Type obj = Type.GetTypeFromProgID("ScriptControl"); + if (obj == null) return null; + object ScriptControl = Activator.CreateInstance(obj); + obj.InvokeMember("Language", BindingFlags.SetProperty, null, ScriptControl, new object[] { "JavaScript" }); + obj.InvokeMember("AddCode", BindingFlags.InvokeMethod, null, ScriptControl, new object[] { js }); + return obj.InvokeMember("Eval", BindingFlags.InvokeMethod, null, ScriptControl, new object[] { method }).ToString(); + } + /// + /// Unicode转字符串 + /// + /// 经过Unicode编码的字符串 + /// 正常字符串 + public static string Unicode2String(string source) + { + return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace(source, x => Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)).ToString()); + } + + ///// + ///// 启动线程下载文件 + ///// + ///// 下载地址 + ///// 保存路径 + ///// 线程数量 + ///// + //public static DownLoadFile DownloadFile(string url, string savePath,string fileName,int threadNumber=5) + //{ + // if (File.Exists(savePath)) File.Delete(savePath); + + //} + + public static string GetSendData(Dictionary objs) + { + if (objs.Count == 0) return string.Empty; + StringBuilder sb = new StringBuilder(); + foreach (var item in objs) + { + sb.Append(item.Key + "=" + UrlEncode(item.Value)); + sb.Append("&"); + } + var str = sb.ToString(); + return str.Substring(0, str.Length - 1); + } + + /// + /// 将图片数据转换为Base64字符串 + /// + /// + /// + public static string ToBase64(Image img) + { + BinaryFormatter binFormatter = new BinaryFormatter(); + MemoryStream memStream = new MemoryStream(); + binFormatter.Serialize(memStream, img); + byte[] bytes = memStream.GetBuffer(); + return Convert.ToBase64String(bytes); + } + + public static Dictionary JsonToDictionary(string json) + { + return HttpHelper.JsonToObject>(json) as Dictionary; + } + + public static string UpdateCookies(this HttpResult result, string OldCookie) + { + return UpdateCookies(OldCookie, result.Cookie); + } + + public static string SimpleCookies(this string cookie) + { + Dictionary dic = new Dictionary(); + var list = cookie.Split(';'); + if (list == null && list.Length == 0) + return cookie; + + for (int i = 0; i < list.Length; i++) + { + var tmps = list[i].Split('=').Select(f => f.Trim()).ToList(); + if (tmps.Count == 2) + { + dic[tmps[0]] = tmps[1]; + } + } + + List keys = new List(); + foreach (KeyValuePair item in dic) + { + keys.Add($"{item.Key}={item.Value}"); + } + return string.Join(";", keys); + } + + public static string UpdateCookies(string oldCookie, string newCookie) + { + #region 老妖xxx + //if (!string.IsNullOrEmpty(oldCookie) && !string.IsNullOrEmpty(newCookie)) + //{ + // oldCookie = HttpHelper.GetSmallCookie(oldCookie); + // List Old = oldCookie.Split(';').Select(f => f.Trim()).ToList(); + + // newCookie = HttpHelper.GetSmallCookie(newCookie); + // List New = newCookie.Split(';').Select(f => f.Trim()).ToList(); + // foreach (string n in New) + // { + // foreach (string o in Old) + // { + // if (o == n || o.Split('=')[0] == n.Split('=')[0]) + // { + // Old.Remove(o); + // break; + // } + // } + // } + // List list = new List(Old); + // //list.AddRange(New); + // foreach (var item in New) + // { + // if (!string.IsNullOrWhiteSpace(item)) + // { + // var tmp = item.Split('='); + // if (tmp.Length >= 2) + // { + // var oldTmp = list.Where(f => f.Trim().StartsWith(tmp[0] + "=")).ToList(); + // foreach (var oldItem in oldTmp) + // { + // if (!string.IsNullOrWhiteSpace(oldItem)) + // { + // list.Remove(oldItem); + // } + // } + // list.Add(item); + // } + // } + // } + // list = list.Where(f => !string.IsNullOrWhiteSpace(f)).ToList(); + // return string.Join(";", list.ToArray()); + //} + //else if (!string.IsNullOrEmpty(oldCookie)) return oldCookie; + //else if (!string.IsNullOrEmpty(newCookie)) return newCookie; + //else return ""; + #endregion + + #region 老道 + if (!string.IsNullOrEmpty(oldCookie) && !string.IsNullOrEmpty(newCookie)) + { + oldCookie = HttpHelper.GetSmallCookie(oldCookie); + List Old = oldCookie.Split(';').Select(f => f.Trim()).Distinct().ToList(); + + newCookie = HttpHelper.GetSmallCookie(newCookie); + List New = newCookie.Split(';').Select(f => f.Trim()).Distinct().ToList(); + foreach (string n in New) + { + foreach (string o in Old) + { + if (o == n || o.Split('=')[0] == n.Split('=')[0]) + { + Old.Remove(o); + break; + } + } + } + List list = new List(Old); + //list.AddRange(New); + foreach (var item in New) + { + if (!string.IsNullOrWhiteSpace(item)) + { + var tmp = item.Split('='); + if (tmp.Length >= 2) + { + var oldTmp = list.Where(f => f.Trim().StartsWith(tmp[0] + "=")).ToList(); + foreach (var oldItem in oldTmp) + { + if (!string.IsNullOrWhiteSpace(oldItem)) + { + list.Remove(oldItem); + } + } + list.Add(item); + } + } + } + list = list.Where(f => !string.IsNullOrWhiteSpace(f)).ToList(); + return string.Join(";", list.ToArray()); + } + else if (!string.IsNullOrEmpty(oldCookie)) return oldCookie; + else if (!string.IsNullOrEmpty(newCookie)) return newCookie; + else return ""; + #endregion + } + + public static string GetCookiesValue(string cookieName, string cookies) + { + if (string.IsNullOrEmpty(cookies)) return string.Empty; + string[] tempCookies = cookies.Split(';'); + foreach (var item in tempCookies) + { + string[] tempCookie = item.Split('='); + if (tempCookie.Length == 2) + { + if (tempCookie[0].Trim() == cookieName) + { + return tempCookie[1].Split('_')[0]; + } + } + } + return string.Empty; + } + + public static string GetMD5String(string str) + { + MD5 md5 = MD5.Create(); + byte[] data = Encoding.UTF8.GetBytes(str); + byte[] data2 = md5.ComputeHash(data); + + return ByteToHex(data2); + //return BitConverter.ToString(data2).Replace("-", "").ToLower(); + } + + public static string ByteToHex(byte[] bytes) + { + string returnStr = ""; + if (bytes != null) + { + for (int i = 0; i < bytes.Length; i++) + { + returnStr += bytes[i].ToString("X2"); + } + } + return returnStr; + } + + public static byte[] HexToByte(string hexString) + { + hexString = hexString.Replace(" ", ""); + if ((hexString.Length % 2) != 0) + { + hexString = hexString + " "; + } + byte[] buffer = new byte[hexString.Length / 2]; + for (int i = 0; i < buffer.Length; i++) + { + buffer[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 0x10); + } + return buffer; + } + /// + /// 通过伪CDN绕过IP检测 + /// + public static void SetProxyipCDN(this HttpItem item) + { + Random rd = new Random(); + var ip = rd.Next(1, 254) + "." + rd.Next(1, 254) + "." + rd.Next(1, 254) + "." + rd.Next(1, 254); + item.Header["X-Forwarded-For"] = ip; + item.Header["CLIENT_IP"] = ip; + item.Header["REMOTE_ADDR"] = ip; + item.Header["Via"] = ip; + } + + /// + /// 通过代理IP绕过IP检测 + /// + /// + public static bool SetProxyIP(this HttpItem item, HttpHelper http, AuthEndpoint endpoint) + { + try + { + var rst = http.SendData(endpoint); + if (rst.ok) + { + var list = rst.message as object[]; + if (list != null && list.Length != 0) + { + + var ip = list[0].ToString().Split('|'); + item.ProxyIp = ip[0]; + if (ip.Length > 1) item.ProxyPwd = ip[1]; + else item.ProxyPwd = string.Empty; + return true; + } + } + } + catch (Exception) + { + + } + return false; + } + + /// + /// 获取时间戳 + /// + /// + public static string GetTimeStamp() + { + TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); + return Convert.ToInt64(ts.TotalSeconds).ToString(); + } + /// + /// 获取时间戳 + /// + /// + public static int GetTimeStamp(DateTime time) + { + DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + return (int)(time - startTime).TotalSeconds; + } + + /// + /// 时间戳Timestamp转换成日期 + /// + /// + /// + public static DateTime GetDateTime(string timeStamp) + { + DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + long lTime = (long.Parse(timeStamp) * (timeStamp.Length == 13 ? 10000 : 10000000)); + TimeSpan toNow = new TimeSpan(lTime); + DateTime targetDt = dtStart.Add(toNow); + return targetDt; + } + + /// + /// 日期转换成时间戳Timestamp + /// + /// 时间 + /// true毫秒 + /// + public static long GetTimeStamp(DateTime time, bool Milliseconds) + { + DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); + + if (!Milliseconds) + return (long)(time - dtStart).TotalSeconds; + else + return (long)(time - dtStart).TotalMilliseconds; + } + + + /// + /// base64编码的文本 转为 图片 + /// + /// base64字符串 + /// 转换后的Bitmap对象 + public static Bitmap Base64StringToImage(string basestr) + { + Bitmap bitmap = null; + try + { + String inputStr = basestr; + byte[] arr = Convert.FromBase64String(inputStr); + MemoryStream ms = new MemoryStream(arr); + Bitmap bmp = new Bitmap(ms); + ms.Close(); + bitmap = bmp; + //MessageBox.Show("转换成功!"); + } + catch (Exception) + { + return null; + } + + return bitmap; + } + + private static Wininet wininet = new Wininet(); + /// + /// 往终端服务器投递消息 + /// + public static WebResult SendData(this HttpHelper http, AuthEndpoint param, bool throwException = true) + { + // int number = 1; + //Next: + //var item = http.GetItem(param.Host,"", param.Data); + //var rest = http.GetHtml(item); + + //if (number<=3 && (int)rest.StatusCode>=500) + //{ + // number++; + // goto Next; + //} + + var html = wininet.PostUtf8(param.Host, param.Data); + WebResult result = null; + try + { + result = HttpHelper.JsonToObject(html) as WebResult; + } + catch (Exception ex) + { + + } + + if (result != null) + { + //基础连接已经关闭: 服务器关闭了本应保持活动状态的连接。 + //Console.WriteLine(); + + if (!result.ok) + if (throwException) + throw new Exception(result.message.ToString()); + else + return result; + if (param.EncResult) + { + AESCryption aes = new AESCryption(); + result.message = aes.AesDecrypt(result.message.ToString(), HttpExtend.GetMD5String(param.Enckey)); + } + return result; + } + return null; + + //var html = wininet.PostUtf8(param.Host,param.Data); ; + //var result = HttpHelper.JsonToObject(html) as WebResult; + //if (result == null) + //{ + // //基础连接已经关闭: 服务器关闭了本应保持活动状态的连接。 + // Console.WriteLine(); + //} + //if (!result.ok) + // if (throwException) + // throw new Exception(result.message.ToString()); + // else return result; + //if (param.EncResult) + //{ + // AESCryption aes = new AESCryption(); + // result.message = aes.AesDecrypt(result.message.ToString(), HttpExtend.GetMD5String(param.Enckey)); + + //} + //return result; + + } + + + /// + /// 将字典转换成实体类 + /// + /// + /// + /// + public static T ConvertToObj(this Dictionary dictionary) + { + var _obj = System.Activator.CreateInstance(); + return (T)dictionary.ConvertToObj(_obj); + } + public static object ConvertToObj(this Dictionary dictionary, object _obj) + { + if (dictionary == null) return _obj; + PropertyInfo[] pros = _obj.GetType().GetProperties(); + foreach (var item in pros) + { + try + { + if (dictionary.ContainsKey(item.Name)) + { + if (item.PropertyType == typeof(String)) + { + if (dictionary[item.Name] == null) item.SetValue(_obj, string.Empty, null); + else item.SetValue(_obj, dictionary[item.Name].ToString(), null); + } + else if (item.PropertyType == typeof(Double)) + { + if (dictionary[item.Name] != null) + item.SetValue(_obj, Double.Parse(dictionary[item.Name].ToString()), null); + else + item.SetValue(_obj, 0.00, null); + } + else if (item.PropertyType == typeof(Int32)) + { + if (dictionary[item.Name] != null) item.SetValue(_obj, Int32.Parse(dictionary[item.Name].ToString()), null); + else item.SetValue(_obj, 0, null); + } + else if (item.PropertyType == typeof(Int64)) + { + if (dictionary[item.Name] != null) item.SetValue(_obj, Int64.Parse(dictionary[item.Name].ToString()), null); + else item.SetValue(_obj, 0, null); + + } + else if (item.PropertyType == typeof(Int16)) + { + if (dictionary[item.Name] != null) item.SetValue(_obj, Int16.Parse(dictionary[item.Name].ToString()), null); + else item.SetValue(_obj, 0, null); + } + else if (item.PropertyType == typeof(DateTime)) + { + if (dictionary[item.Name] == null) + { + item.SetValue(_obj, DateTime.MinValue, null); continue; + } + string v = dictionary[item.Name].ToString(); + if (Regex.Match(v, @"^\d+$").Success) + { + item.SetValue(_obj, GetDateTime(v), null); + } + else + { + item.SetValue(_obj, DateTime.Parse(v), null); + } + + + } + else item.SetValue(_obj, dictionary[item.Name], null); + } + } + catch (Exception ex) + { } + } + return _obj; + } + + // 从字符串转换到16进制表示的字符串 + /// 编码,如"utf-8","gb2312" + /// 是否每字符用逗号分隔 + public static string ToHex(string s, string charset, bool fenge) + { + if ((s.Length % 2) != 0) + { + s += " ";//空格 + //throw new ArgumentException("s is not valid chinese string!"); + } + System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset); + byte[] bytes = chs.GetBytes(s); + string str = ""; + for (int i = 0; i < bytes.Length; i++) + { + str += string.Format("{0:X}", bytes[i]); + if (fenge && (i != bytes.Length - 1)) + { + str += string.Format("{0}", ","); + } + } + return str.ToLower(); + } + + + /// + /// URL编码 + /// + /// + /// + public static string UrlEncode(string text) + { + System.Text.StringBuilder builder = new System.Text.StringBuilder(); + foreach (char c in text) + { + if (System.Web.HttpUtility.UrlEncode(c.ToString()).Length > 1) + { + builder.Append(System.Web.HttpUtility.UrlEncode(c.ToString()).ToUpper()); + } + else + { + builder.Append(c); + } + } + return builder.ToString(); + } + + public static string MapFile(string file, string path = "") + { + return Path.Combine(MapPath(path, true), file); + } + + + /// + /// C# DES解密方法 + /// + /// 待解密的字符串 + /// 密钥 + /// 向量 + /// 解密后的字符串 + public static string DESDecrypt(string encryptedValue, string key, string iv) + { + try + { + using (DESCryptoServiceProvider sa = + new DESCryptoServiceProvider + { Key = Encoding.UTF8.GetBytes(key), IV = Encoding.UTF8.GetBytes(iv) }) + { + using (ICryptoTransform ct = sa.CreateDecryptor()) + { + byte[] byt = Convert.FromBase64String(encryptedValue); + + using (var ms = new MemoryStream()) + { + using (var cs = new CryptoStream(ms, ct, CryptoStreamMode.Write)) + { + cs.Write(byt, 0, byt.Length); + cs.FlushFinalBlock(); + } + return Encoding.UTF8.GetString(ms.ToArray()); + } + } + } + } + catch { } + return string.Empty; + } + + /// + /// C# DES加密方法 + /// + /// 要加密的字符串 + /// 密钥 + /// 向量 + /// 加密后的字符串 + public static string DESEncrypt(string originalValue, string key, string iv) + { + using (DESCryptoServiceProvider sa + = new DESCryptoServiceProvider { Key = Encoding.UTF8.GetBytes(key), IV = Encoding.UTF8.GetBytes(iv) }) + { + using (ICryptoTransform ct = sa.CreateEncryptor()) + { + byte[] by = Encoding.UTF8.GetBytes(originalValue); + using (var ms = new MemoryStream()) + { + using (var cs = new CryptoStream(ms, ct, + CryptoStreamMode.Write)) + { + cs.Write(by, 0, by.Length); + cs.FlushFinalBlock(); + } + return Convert.ToBase64String(ms.ToArray()); + } + } + } + } + public static string MapPath(string path = "", bool CreateDirectory = true) + { + if (string.IsNullOrWhiteSpace(path)) + { + return System.Windows.Forms.Application.StartupPath.ToString() + "\\"; + } + path = Path.Combine(System.Windows.Forms.Application.StartupPath.ToString() + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + return path; + } + + + /// + /// 重定向Url地址 + /// + /// 需要重定向的链接 + /// 来源 + /// 是否自动重定向,默认不重定向 + /// + public static string GetLocationUrl(string url, string referer = "", bool allowautoredirect = false) + { + try + { + HttpHelper http = new HttpHelper(); + HttpItem item = new HttpItem() + { + URL = url, + IsToLower = false, + Timeout = 5000, + ReadWriteTimeout = 5000, + UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.154 Safari/537.36 LBBROWSER", + ContentType = "application/x-www-form-urlencoded", + Referer = referer, + Allowautoredirect = allowautoredirect + }; + HttpResult result = http.GetHtml(item); + var ss = result.Header.Get("Location"); + return ss; + } + catch (Exception) + { } + return string.Empty; + } + + } + + + + + public class WebResult + { + public bool ok { get; set; } + public object message { get; set; } + public double time { get; set; } + public string method { get; set; } + public string req { get; set; } + + public WebResult() + { + this.req = DateTime.Now.ToString("yyyyMMddHHmmss"); + } + + } + public class IniHelper + { + [DllImport("kernel32")] + private static extern long WritePrivateProfileString(string section, string key, string val, string filepath); + [DllImport("kernel32")] + private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filePath); + + + //获取ini文件路径 + private string inifilepath; + public IniHelper(string fileName) + { + this.inifilepath = fileName; + } + public string GetValue(string node, string key) + { + StringBuilder s = new StringBuilder(1024); + GetPrivateProfileString(node, key, "", s, 1024, inifilepath); + return s.ToString(); + } + + + public void SetValue(string node, string key, string value) + { + try + { + WritePrivateProfileString(node, key, value, inifilepath); + } + catch (Exception ex) + { + throw ex; + } + } + } + /// + /// 终端节点数据 + /// + public class AuthEndpoint + { + /// + /// 授权编号 + /// + public int Appid { get; set; } + /// + /// 服务器地址 + /// + public string Host { get; set; } + + /// + /// 加密数据 + /// + public string Enckey { get; set; } + + /// + /// 调用函数 + /// + public string Method { get; set; } + + /// + /// 版本号 + /// + public string Version { get; set; } + + /// + /// 需要发送的数据 + /// + private Dictionary _param { get; set; } + + /// + /// 返回参数是否加密 + /// + public bool EncResult { get { if (_param != null && _param.ContainsKey("enc_result") && _param["enc_result"].ToString().ToUpper() == "TRUE") return true; else return false; } } + + + /// + /// 参数 + /// + public Dictionary Param + { + get + { + if (_param == null) _param = new Dictionary(); + _param["time"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + return _param; + } + } + /// + /// 完整POST参数 + /// + public string Data + { + get + { + + var json = HttpHelper.ObjectToJson(Param); + var data = RsaCrypto.RsaEncrypt(json, this.Enckey); + return $"appid={Appid}&method={Method}&data={HttpHelper.URLEncode(data)}&v=" + (Version == null ? "1.0" : Version); + } + } + + + public AuthEndpoint() { RsaCrypto = new RSACryption(); } + public RSACryption RsaCrypto { get; private set; } + + + + } + + public class RSACryption + { + public string RsaEncrypt(string rawInput, string publicKey) + { + if (string.IsNullOrEmpty(rawInput)) + { + return string.Empty; + } + + if (string.IsNullOrWhiteSpace(publicKey)) + { + throw new ArgumentException("Invalid Public Key"); + } + + using (var rsaProvider = new RSACryptoServiceProvider()) + { + var inputBytes = Encoding.UTF8.GetBytes(rawInput);//有含义的字符串转化为字节流 + rsaProvider.FromXmlString(publicKey);//载入公钥 + int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度 + var buffer = new byte[bufferSize]; + using (MemoryStream inputStream = new MemoryStream(inputBytes), + outputStream = new MemoryStream()) + { + while (true) + { //分段加密 + int readSize = inputStream.Read(buffer, 0, bufferSize); + if (readSize <= 0) + { + break; + } + + var temp = new byte[readSize]; + Array.Copy(buffer, 0, temp, 0, readSize); + var encryptedBytes = rsaProvider.Encrypt(temp, false); + outputStream.Write(encryptedBytes, 0, encryptedBytes.Length); + } + return Convert.ToBase64String(outputStream.ToArray());//转化为字节流方便传输 + } + } + } + + public string RsaDecrypt(string encryptedInput, string privateKey) + { + if (string.IsNullOrEmpty(encryptedInput)) + { + return string.Empty; + } + + if (string.IsNullOrWhiteSpace(privateKey)) + { + throw new ArgumentException("Invalid Private Key"); + } + + using (var rsaProvider = new RSACryptoServiceProvider()) + { + var inputBytes = Convert.FromBase64String(encryptedInput); + rsaProvider.FromXmlString(privateKey); + int bufferSize = rsaProvider.KeySize / 8; + var buffer = new byte[bufferSize]; + using (MemoryStream inputStream = new MemoryStream(inputBytes), + outputStream = new MemoryStream()) + { + while (true) + { + int readSize = inputStream.Read(buffer, 0, bufferSize); + if (readSize <= 0) + { + break; + } + + var temp = new byte[readSize]; + Array.Copy(buffer, 0, temp, 0, readSize); + var rawBytes = rsaProvider.Decrypt(temp, false); + outputStream.Write(rawBytes, 0, rawBytes.Length); + } + return Encoding.UTF8.GetString(outputStream.ToArray()); + } + } + } + } +} diff --git a/类库/HttpHelper2.1/Helper/Base64Helper.cs b/类库/HttpHelper2.1/Helper/Base64Helper.cs new file mode 100644 index 0000000..aae2229 --- /dev/null +++ b/类库/HttpHelper2.1/Helper/Base64Helper.cs @@ -0,0 +1,46 @@ +using System; +using System.Text; + +namespace CsharpHttpHelper.Helper +{ + /// + /// Base64帮助类 + /// 编码人:苏飞 + /// + public class Base64Helper + { + /// + /// 将Base64编码解析成字符串 + /// + /// 要解码的string字符 + /// 字符编码方案 + /// + public static string Base64ToString(string strbase, Encoding encoding) + { + byte[] bytes = Convert.FromBase64String(strbase); + return encoding.GetString(bytes); + } + + /// + /// 将字节数组为Base64编码 + /// + /// 要编码的byte[] + /// + public static string StringToBase64(byte[] bytebase) + { + return Convert.ToBase64String(bytebase); + } + + /// + /// 将字符串转为Base64编码 + /// + /// 要编码的string字符 + /// 字符编码方案 + /// + public static string StringToBase64(string str, Encoding encoding) + { + byte[] bytes = encoding.GetBytes(str); + return Convert.ToBase64String(bytes); + } + } +} diff --git a/类库/HttpHelper2.1/Helper/EncodingHelper.cs b/类库/HttpHelper2.1/Helper/EncodingHelper.cs new file mode 100644 index 0000000..131f1b5 --- /dev/null +++ b/类库/HttpHelper2.1/Helper/EncodingHelper.cs @@ -0,0 +1,37 @@ +using System.Text; + +namespace CsharpHttpHelper.Helper +{ + internal class EncodingHelper + { + /// + /// 将字节数组转为字符串 + /// + /// 字节数组 + /// 编码,默认为Default + /// + internal static string ByteToString(byte[] b, Encoding e = null) + { + if (e == null) + { + e = Encoding.Default; + } + return e.GetString(b); + } + + /// + /// 将字符串转为字节数组 + /// + /// 字符串 + /// 编码,默认为Default + /// + internal static byte[] StringToByte(string s, Encoding e = null) + { + if (e == null) + { + e = Encoding.Default; + } + return e.GetBytes(s); + } + } +} diff --git a/类库/HttpHelper2.1/Helper/ExecJsHelper.cs b/类库/HttpHelper2.1/Helper/ExecJsHelper.cs new file mode 100644 index 0000000..6e1ee5d --- /dev/null +++ b/类库/HttpHelper2.1/Helper/ExecJsHelper.cs @@ -0,0 +1,57 @@ +using System; +using System.Reflection; + +namespace CsharpHttpHelper.Helper +{ + /// + /// 用户执行JS的方法 Copyright:http://www.httphelper.com/ + /// + internal class ExecJsHelper + { + private static Type type = Type.GetTypeFromProgID("ScriptControl"); + + /// + /// 直接调用JS方法并获取返回的值 + /// + /// 要执行的JS代码 + /// 要调用的方法名 + /// 执行结果 + internal static string JavaScriptEval(string strJs, string main) + { + object scriptControl = GetScriptControl(); + SetScriptControlType(strJs, scriptControl); + return type.InvokeMember("Eval", BindingFlags.InvokeMethod, null, scriptControl, new object[1] + { + main + }).ToString(); + } + + /// + /// 获取ScriptControl接口类 + /// + /// JS + /// 对象 + /// Type + private static Type SetScriptControlType(string strJs, object obj) + { + type.InvokeMember("Language", BindingFlags.SetProperty, null, obj, new object[1] + { + "JScript" + }); + type.InvokeMember("AddCode", BindingFlags.InvokeMethod, null, obj, new object[1] + { + strJs + }); + return type; + } + + /// + /// 获取ScriptControl接口对象 + /// + /// ScriptControl对象 + private static object GetScriptControl() + { + return Activator.CreateInstance(type); + } + } +} diff --git a/类库/HttpHelper2.1/Helper/HtmlHelper.cs b/类库/HttpHelper2.1/Helper/HtmlHelper.cs new file mode 100644 index 0000000..60d0324 --- /dev/null +++ b/类库/HttpHelper2.1/Helper/HtmlHelper.cs @@ -0,0 +1,151 @@ +using CsharpHttpHelper.Enum; +using CsharpHttpHelper.Item; +using CsharpHttpHelper.Static; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace CsharpHttpHelper.Helper +{ + /// + /// Html操作相关 Copyright:http://www.httphelper.com/ + /// + internal class HtmlHelper + { + /// + /// 获取所有的A链接 + /// + /// 要分析的Html代码 + /// 返回一个List存储所有的A标签 + internal static List GetAList(string html) + { + List list = null; + string alist = RegexString.Alist; + if (Regex.IsMatch(html, alist, RegexOptions.IgnoreCase)) + { + list = new List(); + foreach (Match item in Regex.Matches(html, alist, RegexOptions.IgnoreCase)) + { + AItem aItem = null; + try + { + AItem aItem2 = new AItem(); + aItem2.Href = item.Groups[1].Value; + aItem2.Text = item.Groups[2].Value; + aItem2.Html = item.Value; + aItem2.Type = AType.Text; + aItem = aItem2; + List imgList = GetImgList(aItem.Text); + if (imgList != null && imgList.Count > 0) + { + aItem.Type = AType.Img; + aItem.Img = imgList[0]; + } + } + catch + { + aItem = null; + } + if (aItem != null) + { + list.Add(aItem); + } + } + } + return list; + } + + /// + /// 获取所有的Img标签 + /// + /// 要分析的Html代码 + /// 返回一个List存储所有的Img标签 + internal static List GetImgList(string html) + { + List list = null; + string imgList = RegexString.ImgList; + if (Regex.IsMatch(html, imgList, RegexOptions.IgnoreCase)) + { + list = new List(); + foreach (Match item in Regex.Matches(html, imgList, RegexOptions.IgnoreCase)) + { + ImgItem imgItem = null; + try + { + ImgItem imgItem2 = new ImgItem(); + imgItem2.Src = item.Groups[1].Value; + imgItem2.Html = item.Value; + imgItem = imgItem2; + } + catch + { + imgItem = null; + } + if (imgItem != null) + { + list.Add(imgItem); + } + } + } + return list; + } + + /// + /// 过滤html标签 + /// + /// html的内容 + /// 处理后的文本 + internal static string StripHTML(string html) + { + html = Regex.Replace(html, RegexString.Nscript, string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled); + html = Regex.Replace(html, RegexString.Style, string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled); + html = Regex.Replace(html, RegexString.Script, string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled); + html = Regex.Replace(html, RegexString.Html, string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled); + return html; + } + + /// + /// 过滤html中所有的换行符号 + /// + /// html的内容 + /// 处理后的文本 + internal static string ReplaceNewLine(string html) + { + return Regex.Replace(html, RegexString.NewLine, string.Empty, RegexOptions.IgnoreCase | RegexOptions.Compiled); + } + + /// + /// 提取Html字符串中两字符之间的数据 + /// + /// 源Html + /// 开始字符串 + /// 结束字符串 + /// + internal static string GetBetweenHtml(string html, string s, string e) + { + string pattern = $"{s}{RegexString.AllHtml}{e}"; + if (Regex.IsMatch(html, pattern, RegexOptions.IgnoreCase)) + { + Match match = Regex.Match(html, pattern, RegexOptions.IgnoreCase); + if (match != null && match.Groups.Count > 0) + { + return match.Groups[1].Value.Trim(); + } + } + return string.Empty; + } + + /// + /// 提取网页Title + /// + /// Html + /// 返回Title + internal static string GetHtmlTitle(string html) + { + if (Regex.IsMatch(html, RegexString.HtmlTitle)) + { + return Regex.Match(html, RegexString.HtmlTitle).Groups[1].Value.Trim(); + } + return string.Empty; + } + } +} diff --git a/类库/HttpHelper2.1/Helper/HttpCookieHelper.cs b/类库/HttpHelper2.1/Helper/HttpCookieHelper.cs new file mode 100644 index 0000000..5e7fe23 --- /dev/null +++ b/类库/HttpHelper2.1/Helper/HttpCookieHelper.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Net; + +namespace CsharpHttpHelper.Helper +{ + /// + /// Cookie操作帮助类 Copyright:http://www.httphelper.com/ + /// + internal static class HttpCookieHelper + { + /// + /// 根据字符生成Cookie和精简串,将排除path,expires,domain以及重复项 + /// + /// Cookie字符串 + /// 精简串 + internal static string GetSmallCookie(string strcookie) + { + if (string.IsNullOrWhiteSpace(strcookie)) + { + return string.Empty; + } + List list = new List(); + string[] array = strcookie.ToString().Split(new string[2] + { + ",", + ";" + }, StringSplitOptions.RemoveEmptyEntries); + string[] array2 = array; + foreach (string text in array2) + { + string text2 = text.ToLower().Trim().Replace("\r\n", string.Empty) + .Replace("\n", string.Empty); + if (!string.IsNullOrWhiteSpace(text2) && text2.Contains("=") && !text2.Contains("path=") && !text2.Contains("expires=") && !text2.Contains("domain=") && !list.Contains(text)) + { + list.Add($"{text};"); + } + } + return string.Join(";", list); + } + + /// + /// 将字符串Cookie转为CookieCollection + /// + /// Cookie字符串 + /// List-CookieItem + internal static CookieCollection StrCookieToCookieCollection(string strcookie) + { + if (string.IsNullOrWhiteSpace(strcookie)) + { + return null; + } + CookieCollection cookieCollection = new CookieCollection(); + strcookie = GetSmallCookie(strcookie); + string[] array = strcookie.ToString().Split(new string[1] + { + ";" + }, StringSplitOptions.RemoveEmptyEntries); + string[] array2 = array; + foreach (string text in array2) + { + string[] array3 = text.ToString().Split(new string[1] + { + "=" + }, StringSplitOptions.RemoveEmptyEntries); + if (array3.Length == 2) + { + cookieCollection.Add(new Cookie + { + Name = array3[0].Trim(), + Value = array3[1].Trim() + }); + } + } + return cookieCollection; + } + + /// + /// 将CookieCollection转为字符串Cookie + /// + /// Cookie字符串 + /// strcookie + internal static string CookieCollectionToStrCookie(CookieCollection cookie) + { + if (cookie == null) + { + return string.Empty; + } + string text = string.Empty; + foreach (Cookie item in cookie) + { + text += $"{item.Name}={item.Value};"; + } + return text; + } + + /// + /// 自动合并两个Cookie的值返回更新后结果 + /// + /// Cookie1 + /// Cookie2 + /// 返回更新后的Cookie + internal static string GetMergeCookie(string cookie1, string cookie2) + { + if (string.IsNullOrWhiteSpace(cookie1)) + { + return cookie2; + } + if (string.IsNullOrWhiteSpace(cookie2)) + { + return cookie1; + } + List list = new List(); + string[] array = cookie1.ToString().Split(';'); + string[] array2 = cookie2.ToString().Split(';'); + string[] array3 = array; + foreach (string text in array3) + { + if (!list.Contains(text)) + { + list.Add($"{text} "); + } + } + array3 = array2; + foreach (string text in array3) + { + if (!list.Contains(text)) + { + list.Add($"{text}"); + } + } + return string.Join(";", list); + } + } +} diff --git a/类库/HttpHelper2.1/Helper/HttpUrlHelper.cs b/类库/HttpHelper2.1/Helper/HttpUrlHelper.cs new file mode 100644 index 0000000..b0569f5 --- /dev/null +++ b/类库/HttpHelper2.1/Helper/HttpUrlHelper.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Specialized; +using System.Net; +using System.Text; +using System.Web; + +namespace CsharpHttpHelper.Helper +{ + /// + /// 和Url相关的帮助方法 Copyright:http://www.httphelper.com/ + /// + internal class HttpUrlHelper + { + /// + /// 使用指定的编码对象将 URL 编码的字符串转换为已解码的字符串。 + /// + /// 指定的字符串 + /// 指定编码默认为Default + /// + internal static string URLDecode(string text, Encoding encoding = null) + { + if (encoding == null) + { + encoding = Encoding.Default; + } + return HttpUtility.UrlDecode(text, encoding); + } + + /// + /// 使用指定的编码对象对 URL 字符串进行编码。 + /// + /// 指定的字符串 + /// 指定编码默认为Default + /// + internal static string URLEncode(string text, Encoding encoding = null) + { + if (encoding == null) + { + encoding = Encoding.Default; + } + return HttpUtility.UrlEncode(text, encoding); + } + + /// + /// 将Url参数字符串转为一个Key和Value的集合 + /// + /// 要转为集合的字符串 + /// NameValueCollection + internal static NameValueCollection GetNameValueCollection(string str) + { + NameValueCollection result = null; + try + { + result = HttpUtility.ParseQueryString(str); + } + catch + { + } + return result; + } + + /// + /// 提取网站主机部分就是host + /// + /// url + /// host + internal static string GetUrlHost(string url) + { + try + { + return new Uri(url).Host; + } + catch + { + return string.Empty; + } + } + + /// + /// 提取网址对应的IP地址 + /// + /// url + /// 返回Url对应的IP地址 + internal static string GetUrlIp(string url) + { + try + { + IPHostEntry hostByName = Dns.GetHostEntry(GetUrlHost(url)); + //IPHostEntry hostByName = Dns.GetHostByName(GetUrlHost(url)); + return hostByName.AddressList[0].ToString(); + } + catch + { + return string.Empty; + } + } + + /// + /// 获取当前页面的URL(五个数字可选 1~5 ) + /// + /// 1完整url,2域名之后,3域名之后不含参数,4只有域名,5获取参数 + /// + public string getNowURL(int selectNO) + { + //string text = ""; + switch (selectNO) + { + case 1: + return HttpContext.Current.Request.Url.ToString(); + case 2: + return HttpContext.Current.Request.RawUrl; + case 3: + return HttpContext.Current.Request.Url.AbsolutePath; + case 4: + return HttpContext.Current.Request.Url.Host; + case 5: + return HttpContext.Current.Request.Url.Query; + default: + return HttpContext.Current.Request.Url.ToString(); + } + } + } +} diff --git a/类库/HttpHelper2.1/Helper/ImageHelper.cs b/类库/HttpHelper2.1/Helper/ImageHelper.cs new file mode 100644 index 0000000..e951f62 --- /dev/null +++ b/类库/HttpHelper2.1/Helper/ImageHelper.cs @@ -0,0 +1,26 @@ +using System.Drawing; +using System.IO; + +namespace CsharpHttpHelper.Helper +{ + internal class ImageHelper + { + /// + /// 将字节数组转为图片 + /// + /// 字节数组 + /// 返回图片 + internal static Image ByteToImage(byte[] b) + { + try + { + MemoryStream stream = new MemoryStream(b); + return Image.FromStream(stream, true); + } + catch + { + return null; + } + } + } +} diff --git a/类库/HttpHelper2.1/Helper/JsonHelper.cs b/类库/HttpHelper2.1/Helper/JsonHelper.cs new file mode 100644 index 0000000..903325b --- /dev/null +++ b/类库/HttpHelper2.1/Helper/JsonHelper.cs @@ -0,0 +1,47 @@ +using System; +using System.Web.Script.Serialization; + +namespace CsharpHttpHelper.Helper +{ + /// + /// Json操作对象 Copyright:http://www.httphelper.com/ + /// + internal class JsonHelper + { + /// + /// 将指定的Json字符串转为指定的T类型对象 + /// + /// 字符串 + /// 转换后的对象,失败为Null + internal static object JsonToObject(string jsonstr) + { + try + { + JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); + return javaScriptSerializer.Deserialize(jsonstr); + } + catch (Exception) + { + return null; + } + } + + /// + /// 将指定的对象转为Json字符串 + /// + /// 对象 + /// 转换后的字符串失败为空字符串 + internal static string ObjectToJson(object obj) + { + try + { + JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); + return javaScriptSerializer.Serialize(obj); + } + catch (Exception) + { + return string.Empty; + } + } + } +} diff --git a/类库/HttpHelper2.1/Helper/MD5Helper.cs b/类库/HttpHelper2.1/Helper/MD5Helper.cs new file mode 100644 index 0000000..a3c195b --- /dev/null +++ b/类库/HttpHelper2.1/Helper/MD5Helper.cs @@ -0,0 +1,33 @@ +using System.Web.Configuration; +using System.Web.Security; + +namespace CsharpHttpHelper.Helper +{ + /// + /// md5操作相关 Copyright:http://www.httphelper.com/ + /// + internal class MD5Helper + { + /// + /// 传入明文,返回用MD5加密后的字符串 + /// + /// 要加密的字符串 + /// MD5加密后的字符串 + internal static string ToMD5_32(string str) + { + string passwordFormat = FormsAuthPasswordFormat.MD5.ToString(); + return FormsAuthentication.HashPasswordForStoringInConfigFile(str, passwordFormat); + } + + /// + /// 传入明文,返回用SHA1密后的字符串 + /// + /// 要加密的字符串 + /// SHA1加密后的字符串 + internal static string ToSHA1(string str) + { + string passwordFormat = FormsAuthPasswordFormat.SHA1.ToString(); + return FormsAuthentication.HashPasswordForStoringInConfigFile(str, passwordFormat); + } + } +} diff --git a/类库/HttpHelper2.1/HttpHelper.cs b/类库/HttpHelper2.1/HttpHelper.cs new file mode 100644 index 0000000..b5c2391 --- /dev/null +++ b/类库/HttpHelper2.1/HttpHelper.cs @@ -0,0 +1,393 @@ +using CsharpHttpHelper.BaseBll; +using CsharpHttpHelper.Helper; +using CsharpHttpHelper.Item; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Drawing; +using System.IO; +using System.Net; +using System.Runtime.Remoting.Messaging; +using System.Security.Cryptography; +using System.Text; + +namespace CsharpHttpHelper +{ + /// + /// Http帮助类 Copyright:http://www.httphelper.com/ + /// 版本:2.1.10 + /// 作者:苏飞 + /// 更新时间:2017-12-13 + /// + public class HttpHelper + { + + /// + /// gethtml方法异步调用的委托 + /// + /// + /// + private delegate HttpResult GethtmlHandler(HttpItem item); + + /// + /// HttpHelperBLL + /// + private HttpHelperBll bll = new HttpHelperBll(); + + /// + /// 异步调用方法委托 + /// + private ResultHandler resultheadler; + + /// + /// 根据相传入的数据,得到相应页面数据 + /// + /// 参数类对象 + /// 返回HttpResult类型 + public HttpResult GetHtml(HttpItem item) + { + return bll.GetHtml(item); + } + + /// + /// GetHtml方法的异步调用方式,根据相传入的数据,得到相应页面数据 + /// + /// 参数类对象 + /// 回调的方法名 + public void BeginInvokeGetHtml(HttpItem item, ResultHandler resultMainName) + { + resultheadler = resultMainName; + GethtmlHandler gethtmlHandler = GetHtml; + gethtmlHandler.BeginInvoke(item, CallbackFunc, "AsycState:OK"); + } + + /// + /// 内部回调方法 + /// + /// 返回值 + private void CallbackFunc(IAsyncResult resultType) + { + GethtmlHandler gethtmlHandler = (GethtmlHandler)((AsyncResult)resultType).AsyncDelegate; + HttpResult item = gethtmlHandler.EndInvoke(resultType); + resultheadler(item); + } + + /// + /// 根据Url获取图片 + /// + /// HttpItem参数 + /// 返回图片,错误为NULL + public Image GetImage(HttpItem item) + { + return bll.GetImage(item); + } + + /// + /// 快速请求方法FastRequest(极速请求不接收数据,只做提交)不返回Header、Cookie、Html + /// + /// 参数类对象 + /// 返回HttpResult类型 + public HttpResult FastRequest(HttpItem item) + { + return bll.FastRequest(item); + } + + /// + /// 根据字符生成Cookie和精简串,将排除path,expires,domain以及重复项 + /// + /// Cookie字符串 + /// 精简串 + public static string GetSmallCookie(string strcookie) + { + return HttpCookieHelper.GetSmallCookie(strcookie); + } + + /// + /// 将字符串Cookie转为CookieCollection + /// + /// Cookie字符串 + /// List-CookieItem + public static CookieCollection StrCookieToCookieCollection(string strcookie) + { + return HttpCookieHelper.StrCookieToCookieCollection(strcookie); + } + + /// + /// 将CookieCollection转为字符串Cookie + /// + /// Cookie字符串 + /// strcookie + public static string CookieCollectionToStrCookie(CookieCollection cookie) + { + return HttpCookieHelper.CookieCollectionToStrCookie(cookie); + } + + /// + /// 自动合并两个Cookie的值返回更新后结果 + /// + /// Cookie1 + /// Cookie2 + /// 返回更新后的Cookie + public static string GetMergeCookie(string cookie1, string cookie2) + { + return HttpCookieHelper.GetMergeCookie(cookie1, cookie2); + } + + /// + /// 使用指定的编码对象将 URL 编码的字符串转换为已解码的字符串。 + /// + /// 指定的字符串 + /// 指定编码默认为Default + /// 解码后字符串 + public static string URLDecode(string text, Encoding encoding = null) + { + return HttpUrlHelper.URLDecode(text, encoding); + } + + /// + /// 使用指定的编码对象对 URL 字符串进行编码。 + /// + /// 指定的字符串 + /// 指定编码默认为Default + /// 转码后字符串 + public static string URLEncode(string text, Encoding encoding = null) + { + return HttpUrlHelper.URLEncode(text, encoding); + } + + /// + /// 将Url参数字符串转为一个Key和Value的集合 + /// + /// 要转为集合的字符串 + /// NameValueCollection + public static NameValueCollection GetNameValueCollection(string str) + { + return HttpUrlHelper.GetNameValueCollection(str); + } + + /// + /// 文件MD5校验 + /// + /// + /// + public static string GetMD5Hash(string pathName) + { + string strResult = ""; + string strHashData = ""; + byte[] arrbytHashValue; + FileStream oFileStream = null; + MD5CryptoServiceProvider oMD5Hasher = new System.Security.Cryptography.MD5CryptoServiceProvider(); + try + { + oFileStream = new FileStream(pathName, System.IO.FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + arrbytHashValue = oMD5Hasher.ComputeHash(oFileStream);//计算指定Stream 对象的哈希值 +                oFileStream.Close(); +                //由以连字符分隔的十六进制对构成的String,其中每一对表示value 中对应的元素;例如“F-2C-4A” +                strHashData = BitConverter.ToString(arrbytHashValue); +                //替换- +                strHashData = strHashData.Replace("-", ""); + strResult = strHashData; + } + catch (System.Exception ex) + { } + return strResult; + } + + /// + /// 提取网站主机部分就是host + /// + /// url + /// host + public static string GetUrlHost(string url) + { + return HttpUrlHelper.GetUrlHost(url); + } + + /// + /// 提取网址对应的IP地址 + /// + /// url + /// 返回Url对应的IP地址 + public static string GetUrlIp(string url) + { + return HttpUrlHelper.GetUrlIp(url); + } + + /// + /// 传入明文,返回用MD%加密后的字符串32位长度 + /// + /// 要加密的字符串 + /// 用MD5加密后的字符串 + public static string ToMD5(string str) + { + return MD5Helper.ToMD5_32(str); + } + + /// + /// 传入明文,返回用SHA1密后的字符串 + /// + /// 要加密的字符串 + /// SHA1加密后的字符串 + public static string ToSHA1(string str) + { + return MD5Helper.ToSHA1(str); + } + + /// + /// 将指定的Json字符串转为指定的T类型对象 + /// + /// 字符串 + /// 转换后的对象,失败为Null + public static object JsonToObject(string jsonstr) + { + return JsonHelper.JsonToObject(jsonstr); + } + + /// + /// 将指定的对象转为Json字符串 + /// + /// 对象 + /// 转换后的字符串失败为空字符串 + public static string ObjectToJson(object obj) + { + return JsonHelper.ObjectToJson(obj); + } + + /// + /// 获取所有的A链接 + /// + /// 要分析的Html代码 + /// 返回一个List存储所有的A标签 + public static List GetAList(string html) + { + return HtmlHelper.GetAList(html); + } + + /// + /// 获取所有的Img标签 + /// + /// 要分析的Html代码 + /// 返回一个List存储所有的Img标签 + public static List GetImgList(string html) + { + return HtmlHelper.GetImgList(html); + } + + /// + /// 过滤html标签 + /// + /// html的内容 + /// 处理后的文本 + public static string StripHTML(string html) + { + return HtmlHelper.StripHTML(html); + } + + /// + /// 过滤html中所有的换行符号 + /// + /// html的内容 + /// 处理后的文本 + public static string ReplaceNewLine(string html) + { + return HtmlHelper.ReplaceNewLine(html); + } + + /// + /// 提取Html字符串中两字符之间的数据 + /// + /// 源Html + /// 开始字符串 + /// 结束字符串 + /// + public static string GetBetweenHtml(string html, string s, string e) + { + return HtmlHelper.GetBetweenHtml(html, s, e); + } + + /// + /// 提取网页Title + /// + /// Html + /// 返回Title + public static string GetHtmlTitle(string html) + { + return HtmlHelper.GetHtmlTitle(html); + } + + /// + /// 直接调用JS方法并获取返回的值 + /// + /// 要执行的JS代码 + /// 要调用的方法名 + /// 执行结果 + public static string JavaScriptEval(string strJs, string main) + { + return ExecJsHelper.JavaScriptEval(strJs, main); + } + + /// + /// 将字节数组转为图片 + /// + /// 字节数组 + /// 返回图片 + public static Image GetImage(byte[] b) + { + return ImageHelper.ByteToImage(b); + } + + /// + /// 将字节数组转为字符串 + /// + /// 字节数组 + /// 编码,默认为Default + /// 字符串 + public static string ByteToString(byte[] b, Encoding e = null) + { + return EncodingHelper.ByteToString(b, e); + } + + /// + /// 将字符串转为字节数组 + /// + /// 字符串 + /// 编码,默认为Default + /// 字节数组 + public static byte[] StringToByte(string s, Encoding e = null) + { + return EncodingHelper.StringToByte(s, e); + } + + /// + /// 将Base64编码解析成字符串 + /// + /// 要解码的string字符 + /// 字符编码方案 + /// 字符串 + public static string Base64ToString(string strbase, Encoding encoding) + { + return Base64Helper.Base64ToString(strbase, encoding); + } + + /// + /// 将字节数组为Base64编码 + /// + /// 要编码的byte[] + /// base字符串 + public static string ByteToBase64(byte[] bytebase) + { + return Base64Helper.StringToBase64(bytebase); + } + + /// + /// 将字符串转为Base64编码 + /// + /// 要编码的string字符 + /// 字符编码方案 + /// base字符串 + public static string StringToBase64(string str, Encoding encoding) + { + return Base64Helper.StringToBase64(str, encoding); + } + } +} diff --git a/类库/HttpHelper2.1/HttpHelper.csproj b/类库/HttpHelper2.1/HttpHelper.csproj new file mode 100644 index 0000000..1671048 --- /dev/null +++ b/类库/HttpHelper2.1/HttpHelper.csproj @@ -0,0 +1,103 @@ + + + + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE} + Debug + AnyCPU + Library + HttpHelper + .NETFramework + v4.0 + 4 + True + + + + AnyCPU + + + bin\Debug\ + true + full + false + + + bin\Release\ + true + pdbonly + true + + + CsharpHttpHelper + + + AnyCPU + bin\Debug\HttpHelper.xml + false + ..\..\Debug\ + + + false + + + + C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll + + + C:\WINDOWS\Microsoft.NET\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll + + + C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll + + + + C:\WINDOWS\Microsoft.NET\assembly\GAC_MSIL\System.Web.Extensions\v4.0_4.0.0.0__31bf3856ad364e35\System.Web.Extensions.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + \ No newline at end of file diff --git a/类库/HttpHelper2.1/HttpHelper.sln b/类库/HttpHelper2.1/HttpHelper.sln new file mode 100644 index 0000000..fa622ca --- /dev/null +++ b/类库/HttpHelper2.1/HttpHelper.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2020 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpHelper", "HttpHelper.csproj", "{B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B54AE050-DD6C-4F73-95E8-9D8C1CF38FFE}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D1494CDE-918F-4778-93AA-4DF547AF08A2} + EndGlobalSection +EndGlobal diff --git a/类库/HttpHelper2.1/HttpItem.cs b/类库/HttpHelper2.1/HttpItem.cs new file mode 100644 index 0000000..bb9746c --- /dev/null +++ b/类库/HttpHelper2.1/HttpItem.cs @@ -0,0 +1,596 @@ +using CsharpHttpHelper.Enum; +using System; +using System.Net; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace CsharpHttpHelper +{ + /// + /// Http请求参考类 Copyright:http://www.httphelper.com/ + /// + public class HttpItem + { + private string _Method = "GET"; + + private int _Timeout = 100000; + + private int _ReadWriteTimeout = 30000; + + private bool _KeepAlive = true; + + private string _Accept = "text/html, application/xhtml+xml, */*"; + + private string _ContentType = "text/html"; + + private string _UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"; + + private bool _expect100continue = false; + + private DateTime? _IfModifiedSince = null; + + private bool _isGzip = false; + + private DecompressionMethods _AutomaticDecompression = DecompressionMethods.None; + + private PostDataType _PostDataType = PostDataType.String; + + private bool _AutoRedirectCookie = false; + + private ResultCookieType _ResultCookieType = ResultCookieType.String; + + private bool _isUpdateCookie = false; + + private CookieContainer _CookieContainer = new CookieContainer(); + + private ICredentials _ICredentials = CredentialCache.DefaultCredentials; + + private bool isToLower = false; + + private bool allowautoredirect = false; + + private int connectionlimit = 1024; + + private ResultType resulttype = ResultType.String; + + private WebHeaderCollection header = new WebHeaderCollection(); + + private IPEndPoint _IPEndPoint = null; + + private bool _isReset = false; + + /// + /// 请求URL必须填写 + /// + public string URL + { + get; + set; + } + + /// + /// 请求方式默认为GET方式,当为POST方式时必须设置Postdata的值 + /// + public string Method + { + get + { + return _Method; + } + set + { + _Method = value; + } + } + + /// + /// 默认请求超时时间 + /// + public int Timeout + { + get + { + return _Timeout; + } + set + { + _Timeout = value; + } + } + + /// + /// 默认写入和读取Post数据超时间 + /// + public int ReadWriteTimeout + { + get + { + return _ReadWriteTimeout; + } + set + { + _ReadWriteTimeout = value; + } + } + + /// + /// 设置Host的标头信息 + /// + public string Host + { + get; + set; + } + + /// + /// 获取或设置一个值,该值指示是否与 Internet 资源建立持久性连接默认为true。 + /// + public bool KeepAlive + { + get + { + return _KeepAlive; + } + set + { + _KeepAlive = value; + } + } + + /// + /// 请求标头值 默认为text/html, application/xhtml+xml, */* + /// + public string Accept + { + get + { + return _Accept; + } + set + { + _Accept = value; + } + } + + /// + /// 请求返回类型默认 text/html + /// + public string ContentType + { + get + { + return _ContentType; + } + set + { + _ContentType = value; + } + } + + /// + /// 客户端访问信息默认Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) + /// + public string UserAgent + { + get + { + return _UserAgent; + } + set + { + _UserAgent = value; + } + } + + /// + /// 来源地址,上次访问地址 + /// + public string Referer + { + get; + set; + } + + /// + /// 获取或设置用于请求的 HTTP 版本。返回结果:用于请求的 HTTP 版本。默认为 System.Net.HttpVersion.Version11。 + /// + public Version ProtocolVersion + { + get; + set; + } + + /// + /// 获取或设置一个 System.Boolean 值,该值确定是否使用 100-Continue 行为。如果 POST 请求需要 100-Continue 响应,则为 true;否则为 false。默认值为 true。 + /// + public bool Expect100Continue + { + get + { + return _expect100continue; + } + set + { + _expect100continue = value; + } + } + + /// + /// 设置请求将跟随的重定向的最大数目 + /// + public int MaximumAutomaticRedirections + { + get; + set; + } + + /// + /// 获取和设置IfModifiedSince,默认为当前日期和时间 + /// + public DateTime? IfModifiedSince + { + get + { + return _IfModifiedSince; + } + set + { + _IfModifiedSince = value; + } + } + + /// + /// 是否执行Gzip解压 默认为否 + /// + public bool IsGzip + { + get + { + return _isGzip; + } + set + { + _isGzip = value; + } + } + + /// + /// 返回数据编码默认为NUll,可以自动识别,一般为utf-8,gbk,gb2312 + /// + public Encoding Encoding + { + get; + set; + } + + /// + /// 设置或获取Post参数编码,默认的为Default编码 + /// + public Encoding PostEncoding + { + get; + set; + } + + /// + /// + /// + public DecompressionMethods AutomaticDecompression + { + get + { + return _AutomaticDecompression; + } + set + { + _AutomaticDecompression = value; + } + } + + /// + /// Post的数据类型 + /// + public PostDataType PostDataType + { + get + { + return _PostDataType; + } + set + { + _PostDataType = value; + } + } + + /// + /// Post请求时要发送的字符串Post数据 + /// + public string Postdata + { + get; + set; + } + + /// + /// Post请求时要发送的Byte类型的Post数据 + /// + public byte[] PostdataByte + { + get; + set; + } + + /// + /// Cookie对象集合 + /// + public CookieCollection CookieCollection + { + get; + set; + } + + /// + /// 请求时的Cookie + /// + public string Cookie + { + get; + set; + } + + /// + /// 请求时当设置allowautoredirect=true时是否自动处理Cookie + /// + public bool AutoRedirectCookie + { + get + { + return _AutoRedirectCookie; + } + set + { + _AutoRedirectCookie = value; + } + } + + /// + /// Cookie返回类型,默认的是只返回字符串类型 + /// + public ResultCookieType ResultCookieType + { + get + { + return _ResultCookieType; + } + set + { + _ResultCookieType = value; + } + } + + /// + /// 是否自动将Cookie自动更新为请求所获取的新Cookie值 默认为False + /// + public bool IsUpdateCookie + { + get + { + return _isUpdateCookie; + } + set + { + _isUpdateCookie = value; + } + } + + /// + /// Cookie对象的集合容器 模式Cookie,可容纳N个CookieCollection对象 + /// + public CookieContainer CookieContainer + { + get + { + return _CookieContainer; + } + set + { + _CookieContainer = value; + } + } + + /// + /// 证书绝对路径 + /// + public string CerPath + { + get; + set; + } + + /// + /// 证书密码 + /// + public string CerPwd + { + get; + set; + } + + /// + /// 设置509证书集合 + /// + public X509CertificateCollection ClentCertificates + { + get; + set; + } + + /// + /// 获取或设置请求的身份验证信息。 + /// + public ICredentials ICredentials + { + get + { + return _ICredentials; + } + set + { + _ICredentials = value; + } + } + + /// + /// 是否设置为全文小写,默认为不转化 + /// + public bool IsToLower + { + get + { + return isToLower; + } + set + { + isToLower = value; + } + } + + /// + /// 支持跳转页面,查询结果将是跳转后的页面,默认是不跳转 + /// + public bool Allowautoredirect + { + get + { + return allowautoredirect; + } + set + { + allowautoredirect = value; + } + } + + /// + /// 最大连接数 + /// + public int Connectionlimit + { + get + { + return connectionlimit; + } + set + { + connectionlimit = value; + } + } + + /// + /// 设置代理对象,不想使用IE默认配置就设置为Null,而且不要设置ProxyIp + /// + public WebProxy WebProxy + { + get; + set; + } + + /// + /// 代理Proxy 服务器用户名 + /// + public string ProxyUserName + { + get; + set; + } + + /// + /// 代理 服务器密码 + /// + public string ProxyPwd + { + get; + set; + } + + /// + /// 代理 服务IP,如果要使用IE代理就设置为ieproxy + /// + public string ProxyIp + { + get; + set; + } + + /// + /// 设置返回类型String和Byte + /// + public ResultType ResultType + { + get + { + return resulttype; + } + set + { + resulttype = value; + } + } + + /// + /// header对象 + /// + public WebHeaderCollection Header + { + get + { + return header; + } + set + { + header = value; + } + } + + /// + /// 设置本地的出口ip和端口 + /// ] + /// + /// item.IPEndPoint = new IPEndPoint(IPAddress.Parse("192.168.1.1"),80); + /// + public IPEndPoint IPEndPoint + { + get + { + return _IPEndPoint; + } + set + { + _IPEndPoint = value; + } + } + + /// + /// 当出现“请求被中止: 未能创建 SSL/TLS 安全通道”时需要配置此属性 + /// + public SecurityProtocolType SecurityProtocol + { + get; + set; + } + + /// + /// 是否重置request,response的值,默认不重置,当设置为True时request,response将被设置为Null + /// + public bool IsReset + { + get + { + return _isReset; + } + set + { + _isReset = value; + } + } + } +} diff --git a/类库/HttpHelper2.1/HttpResult.cs b/类库/HttpHelper2.1/HttpResult.cs new file mode 100644 index 0000000..4bd8d00 --- /dev/null +++ b/类库/HttpHelper2.1/HttpResult.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Specialized; +using System.Linq; +using System.Net; + +namespace CsharpHttpHelper +{ + /// + /// Http返回参数类 Copyright:http://www.httphelper.com/ + /// + public class HttpResult + { + /// + /// Http请求返回的Cookie + /// + public string Cookie + { + get; + set; + } + + /// + /// Cookie对象集合 + /// + public CookieCollection CookieCollection + { + get; + set; + } + + /// + /// 返回的String类型数据 只有ResultType.String时才返回数据,其它情况为空 + /// + public string Html + { + get; + set; + } + + /// + /// 返回的Byte数组 只有ResultType.Byte时才返回数据,其它情况为空 + /// + public byte[] ResultByte + { + get; + set; + } + + /// + /// header对象 + /// + public WebHeaderCollection Header + { + get; + set; + } + + /// + /// 返回状态说明 + /// + public string StatusDescription + { + get; + set; + } + + /// + /// 返回状态码,默认为OK + /// + public HttpStatusCode StatusCode + { + get; + set; + } + + /// + /// 最后访问的URl + /// + public string ResponseUri + { + get; + set; + } + + /// + /// 获取重定向的URl + /// + public string RedirectUrl + { + get + { + try + { + if (Header != null && Header.Count > 0 && Header.AllKeys.Any((string k) => k.ToLower().Contains("location"))) + { + string text = ((NameValueCollection)Header)["location"].ToString().Trim(); + string text2 = text.ToLower(); + if (!string.IsNullOrWhiteSpace(text2) && !text2.StartsWith("http://") && !text2.StartsWith("https://")) + { + text = new Uri(new Uri(ResponseUri), text).AbsoluteUri; + } + return text; + } + } + catch + { + } + return string.Empty; + } + } + } +} diff --git a/类库/HttpHelper2.1/Item/AItem.cs b/类库/HttpHelper2.1/Item/AItem.cs new file mode 100644 index 0000000..a2ed13d --- /dev/null +++ b/类库/HttpHelper2.1/Item/AItem.cs @@ -0,0 +1,55 @@ +using CsharpHttpHelper.Enum; + +namespace CsharpHttpHelper.Item +{ + /// + /// A连接对象 Copyright:http://www.httphelper.com/ + /// + public class AItem + { + /// + /// 链接地址 + /// + public string Href + { + get; + set; + } + + /// + /// 链接文本 + /// + public string Text + { + get; + set; + } + + /// + /// 链接的图片,如果是文本链接则为空 + /// + public ImgItem Img + { + get; + set; + } + + /// + /// 整个连接Html + /// + public string Html + { + get; + set; + } + + /// + /// A链接的类型 + /// + public AType Type + { + get; + set; + } + } +} diff --git a/类库/HttpHelper2.1/Item/ImgItem.cs b/类库/HttpHelper2.1/Item/ImgItem.cs new file mode 100644 index 0000000..72b733d --- /dev/null +++ b/类库/HttpHelper2.1/Item/ImgItem.cs @@ -0,0 +1,26 @@ +namespace CsharpHttpHelper.Item +{ + /// + /// 图片对象 Copyright:http://www.httphelper.com/ + /// + public class ImgItem + { + /// + /// 图片网址 + /// + public string Src + { + get; + set; + } + + /// + /// 图片标签Html + /// + public string Html + { + get; + set; + } + } +} diff --git a/类库/HttpHelper2.1/Properties/AssemblyInfo.cs b/类库/HttpHelper2.1/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..19229c9 --- /dev/null +++ b/类库/HttpHelper2.1/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +[assembly: ComVisible(true)] +[assembly: AssemblyFileVersion("2.1.10")] +[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] +[assembly: AssemblyTrademark("HttpHelper")] +[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] +[assembly: AssemblyCopyright("Copyright © 苏飞论坛 2018")] +[assembly: Guid("b3dfad27-f808-43d6-b66d-f7dc59221472")] +[assembly: CompilationRelaxations(8)] +[assembly: AssemblyTitle("HttpHelper万能框架")] +[assembly: AssemblyDescription("解决Http协议自动化请求的完美方案")] +[assembly: AssemblyProduct("HttpHelper")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("http://www.httphelper.com/")] +[assembly: AssemblyVersion("2.1.10.0")] diff --git a/类库/HttpHelper2.1/Properties/Resources.Designer.cs b/类库/HttpHelper2.1/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d2e17d3 --- /dev/null +++ b/类库/HttpHelper2.1/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace CsharpHttpHelper.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CsharpHttpHelper.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/类库/HttpHelper2.1/Properties/Resources.resx b/类库/HttpHelper2.1/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/HttpHelper2.1/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/HttpHelper2.1/Resources/VersionUpdate.xml b/类库/HttpHelper2.1/Resources/VersionUpdate.xml new file mode 100644 index 0000000..8cefe2c --- /dev/null +++ b/类库/HttpHelper2.1/Resources/VersionUpdate.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/类库/HttpHelper2.1/ResultHandler.cs b/类库/HttpHelper2.1/ResultHandler.cs new file mode 100644 index 0000000..d812725 --- /dev/null +++ b/类库/HttpHelper2.1/ResultHandler.cs @@ -0,0 +1,9 @@ +namespace CsharpHttpHelper +{ + /// + /// gethtml方法异步调用的委托 + /// + /// + /// + public delegate void ResultHandler(HttpResult item); +} diff --git a/类库/HttpHelper2.1/Static/RegexString.cs b/类库/HttpHelper2.1/Static/RegexString.cs new file mode 100644 index 0000000..40a4a32 --- /dev/null +++ b/类库/HttpHelper2.1/Static/RegexString.cs @@ -0,0 +1,60 @@ +using System; + +namespace CsharpHttpHelper.Static +{ + /// + /// 正则表达式静态类 + /// + internal class RegexString + { + /// + /// 获取所有的A链接 + /// + internal static readonly string Alist = "([\\s\\S]+?)"; + + /// + /// 获取所有的Img标签 + /// + internal static readonly string ImgList = "([\\s\\S]*?)>"; + + /// + /// 所有的Nscript + /// + internal static readonly string Nscript = "[\\s\\S]*?"; + + /// + /// 所有的Style + /// + internal static readonly string Style = "[\\s\\S]*?"; + + /// + /// 所有的Script + /// + internal static readonly string Script = "[\\s\\S]*?"; + + /// + /// 所有的Html + /// + internal static readonly string Html = "<[\\s\\S]*?>"; + + /// + /// 换行符号 + /// + internal static readonly string NewLine = Environment.NewLine; + + /// + /// 获取网页编码 + /// + internal static readonly string Enconding = " + /// 所有Html + /// + internal static readonly string AllHtml = "([\\s\\S]*?)"; + + /// + /// title + /// + internal static readonly string HtmlTitle = "([\\s\\S]*?)"; + } +} diff --git a/类库/OnlineRepair/App.config b/类库/OnlineRepair/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/类库/OnlineRepair/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/类库/OnlineRepair/Client.cs b/类库/OnlineRepair/Client.cs new file mode 100644 index 0000000..dd78d19 --- /dev/null +++ b/类库/OnlineRepair/Client.cs @@ -0,0 +1,372 @@ +using OnlineRepair; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using System.Xml; + +namespace VersionUpdate +{ + public class UpdateClass + { + public string Name { get; set; } + public string Url { get; set; } + public string Version { get; set; } + public List Message { get; set; } + } + public class Client + { + + static string Path = System.IO.Directory.GetCurrentDirectory(); + static string XMLPath = string.Empty; + + static Client() + { + XMLPath = Path + "\\VersionUpdate.xml"; + if (!File.Exists(XMLPath)) + { + var old_path = Path + "\\LevelUpdate.xml"; + if (!File.Exists(old_path)) throw new Exception("丢失【VersionUpdate.xml】更新包文件!"); + else + { + if (File.Exists(Path + "\\LevelUpdate.exe")) + { + try + { + File.Delete(Path + "\\LevelUpdate.exe"); + } + catch (Exception) + { + } + } + File.Move(old_path, XMLPath); + } + } + } + #region XmlDocument读取 + + public List GetVersions() + { + List msgs = new List(); + XmlDocument XmlDoc = new XmlDocument(); + + if (!File.Exists(XMLPath)) throw new Exception("找不到LevelUpdate.xml必备文件!"); + //使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件. + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + XmlNode xn = XmlDoc.SelectSingleNode("Files"); + // 得到根节点的所有子节点 + XmlNodeList xnl = xn.ChildNodes; + foreach (XmlNode node in xnl) + { + try + { + var Name = node.Attributes["Name"].Value; + var Url = node.Attributes["Url"].Value; + var CurVersion = Version.Parse(node.Attributes["Version"].Value); + + XmlDocument temp_xml = new XmlDocument(); + temp_xml.Load(Url); + var temp_node = temp_xml.SelectSingleNode("History"); + + var temp_datas = temp_node.SelectNodes("Data"); + //更新内容 + List temp_update = new List(); + foreach (XmlNode item in temp_datas) + { + var ver = Version.Parse(item.Attributes["Ver"].Value); + if (ver > CurVersion) + { + //发现有更新 + temp_update.Add(item); + } + } + + if (temp_update.Count > 0) + { + var MSG = new UpdateClass() { Name = Name, Url = temp_update[0].Attributes["Url"].Value, Message = new List(), Version = temp_update[0].Attributes["Ver"].Value }; + msgs.Add(MSG); + foreach (var item in temp_update) + { + var temps = item.Attributes["Msg"].Value.Split(new string[] { "[br]" }, StringSplitOptions.None); + foreach (var temp in temps) MSG.Message.Add(temp); + } + } + } + catch (Exception) + { + + } + } + } + + return msgs; + } + + + + public delegate void NeedRestupdate(); + public static NeedRestupdate NeedRestupdateEvent; + + + + internal void DownFile(List update_msg, ProgressBar prog, Label label) + { + int i = 1; + foreach (var item in update_msg) + { + label?.Invoke(new Action(delegate { label.Text = $"正在下载第{i}个文件的更新包...(共{update_msg.Count}个)"; })); + DownloadFile(item.Url, MapFile($"{item.Name}_{item.Version}.zip", "Cache\\VersionUpdate"), prog); + i++; + } + label?.Invoke(new Action(delegate { label.Text = $"下载完成,请重启安装!"; })); + NeedRestupdateEvent?.BeginInvoke(null, null); + } + + /// + /// 检查是否有需要安装的程序 + /// + public bool CheckInstall() + { + var files = GetInstallFiles(); + if (files.Count > 0) + { + new InstallFileForm(files, this).ShowDialog(); + return true; + } + return false; + } + + public static bool StartProcess(string filename, string param = null) + { + try + { + if (!File.Exists(filename)) + return false; + + try + { + if (!System.IO.File.Exists(filename)) + return false; + + if (param != null) + System.Diagnostics.Process.Start(filename, param); + else + System.Diagnostics.Process.Start(filename); + System.Threading.Thread.Sleep(100); + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + } + + + /// + /// 检查是否有新版本 + /// + public bool CheckVersion() + { + var ves = GetVersions(); + if (ves.Count > 0) + { + var f = new DownloadForm(ves, this); + f.ShowDialog(); + return f.IsOk; + } + return false; + } + + public bool DownloadFile(List updateList) + { + if (updateList.Count > 0) + { + var f = new DownloadForm(updateList, this); + f.ShowDialog(); + return f.IsOk; + } + return false; + } + + /// + /// 获得需要安装的文件 + /// + /// + public List GetInstallFiles() + { + var path = MapPath("Cache\\VersionUpdate"); + DirectoryInfo dir = new DirectoryInfo(path); + var zips = dir.GetFiles("*_*.zip", SearchOption.TopDirectoryOnly); + var files = new List(); + foreach (var item in zips) + { + var reg = Regex.Match(item.Name, "^(.*?)_(.*?)\\.zip$"); + if (reg.Success) + { + try + { + var name = item.Name; + var version = Version.Parse(reg.Groups[2].Value); + files.Add(item); + } + catch (Exception) + { } + } + } + + return files; + } + public void StartInstall() + { + var name = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName; + if (name == "VersionUpdate.exe") return; + StartProcess("VersionUpdate.exe", name); + } + + public void InstallFile(FileInfo file) + { + try + { + var data = file.Name.Split('_'); + var reg = Regex.Match(file.Name, "^(.*?)_(.*?).zip$"); + if (!reg.Success) return; + Version version = null; + if (!Version.TryParse(reg.Groups[2].Value, out version)) return; + var name = reg.Groups[1].Value; + + ZipArchive.UnZip(file.FullName, Path); + XmlDocument XmlDoc = new XmlDocument(); + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + foreach (XmlNode _temp in XmlDoc.SelectSingleNode("Files").ChildNodes) + { + if (name == _temp.Attributes["Name"].Value) + { + _temp.Attributes["Version"].Value = version.ToString(); + break; + } + } + } + XmlDoc.Save(XMLPath); + + File.Delete(file.FullName); + + } + catch (Exception ex) + { } + } + + public static string MapFile(string file, string path = "") + { + return System.IO.Path.Combine(MapPath(path, true), file); + } + public static string MapPath(string path = "", bool CreateDirectory = true) + { + try + { + if (string.IsNullOrWhiteSpace(path)) + { + return System.Windows.Forms.Application.StartupPath.ToString() + "\\"; + } + path = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath.ToString() + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + } + catch (Exception) + { } + return path; + } + + public void DownloadFile(string URL, string filename, ProgressBar prog) + { + float percent = 0; + if (File.Exists(filename)) File.Delete(filename); + + Stream st = null; + Stream so = null; + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + prog.Invoke(new Action(delegate + { + prog.Value = 0; + prog.Maximum = (int)totalBytes; + + })); + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + + totalDownloadedByte = osize + totalDownloadedByte; + Application.DoEvents(); + so.Write(by, 0, osize); + + prog.Invoke(new Action(delegate { prog.Value = (int)totalDownloadedByte; })); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + + #endregion XmlDocument读取 + } +} diff --git a/类库/OnlineRepair/DownloadForm.cs b/类库/OnlineRepair/DownloadForm.cs new file mode 100644 index 0000000..98d7370 --- /dev/null +++ b/类库/OnlineRepair/DownloadForm.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace VersionUpdate +{ + public partial class DownloadForm : Form + { + List updateClass; + Client client; + public DownloadForm(List updateClass, Client client) + { + InitializeComponent(); + this.updateClass = updateClass; + this.client = client; + } + public bool IsOk = false; + Thread thread; + private void button1_Click(object sender, EventArgs e) + { + try + { + this.button1.Enabled = false; + thread = new Thread(new ThreadStart(delegate + { + try + { + + client.DownFile(updateClass, this.progressBar1, this.label1); + IsOk = true; + this.Invoke(new Action(delegate + { + this.Close(); + })); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + MessageBox.Show(ex.Message, "下载失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + })); + } + + })); + thread.IsBackground = true; + thread.Start(); + } + catch (Exception ex) + { } + } + + private void DownloadForm_Load(object sender, EventArgs e) + { + try + { + StringBuilder sb = new StringBuilder(); + foreach (var item in updateClass) + { + sb.Append($"{item.Name} -- {item.Version}\r\n"); + + for (int i = 0; i < item.Message.Count; i++) + { + sb.AppendLine($"{i + 1}、{item.Message[i]}"); + } + sb.AppendLine(""); + sb.AppendLine(""); + } + this.richTextBox1.Text = sb.ToString().Trim(); + } + catch (Exception ex) + { } + } + + private void DownloadForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (thread != null && !IsOk) + { + try + { + thread.Abort(); + } + catch (Exception ex1) + { } + } + } + catch (Exception ex) + { } + } + } +} diff --git a/类库/OnlineRepair/DownloadForm.designer.cs b/类库/OnlineRepair/DownloadForm.designer.cs new file mode 100644 index 0000000..544a598 --- /dev/null +++ b/类库/OnlineRepair/DownloadForm.designer.cs @@ -0,0 +1,108 @@ +namespace VersionUpdate +{ + partial class DownloadForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DownloadForm)); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.button1 = new System.Windows.Forms.Button(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // progressBar1 + // + this.progressBar1.Location = new System.Drawing.Point(8, 367); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(479, 25); + this.progressBar1.TabIndex = 6; + // + // button1 + // + this.button1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.button1.Location = new System.Drawing.Point(177, 399); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(136, 34); + this.button1.TabIndex = 5; + this.button1.Text = "开始下载"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // richTextBox1 + // + this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richTextBox1.Location = new System.Drawing.Point(2, 2); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ReadOnly = true; + this.richTextBox1.Size = new System.Drawing.Size(488, 332); + this.richTextBox1.TabIndex = 4; + this.richTextBox1.Text = ""; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(3, 338); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(482, 23); + this.label1.TabIndex = 7; + this.label1.Text = "等待下载"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // DownloadForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(495, 439); + this.Controls.Add(this.label1); + this.Controls.Add(this.progressBar1); + this.Controls.Add(this.button1); + this.Controls.Add(this.richTextBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "DownloadForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "修复版本"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DownloadForm_FormClosing); + this.Load += new System.EventHandler(this.DownloadForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/OnlineRepair/DownloadForm.resx b/类库/OnlineRepair/DownloadForm.resx new file mode 100644 index 0000000..a75e619 --- /dev/null +++ b/类库/OnlineRepair/DownloadForm.resx @@ -0,0 +1,1244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAgH8AAAEAIAAYBgEAFgAAACgAAACAAAAA/gAAAAEAIAAAAAAAAP4AABEXAAARFwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+pogCvqaIAr6miAK+pogCvqaIAr6miAK+p + ogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBY + TA1wWEwTcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + ogCvqaIOr6miOK+pomOvqaJ9r6miga+ponGvqaJMr6miH6+pogGvqaIAr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWEwPcFhMnHBYTLRwWEwecFhMAHBYTABwWEwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miAK+pogCvqaIRr6miaK+posOvqaLxr6mi/6+pov+vqaL/r6mi/6+p + ovmvqaLcr6milK+pojCvqaIAr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMD3BY + TJtwWEz/cFhM/3BYTLdwWEwecFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIAr6miNK+p + orqvqaL9r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi5K+pom6vqaIHr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTA9wWEyccFhM/3BYTP9wWEz/cFhM/3BYTLdwWEwecFhMAHBY + TABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+pokCvqaLar6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi+q+poomvqaIJr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWEwQcFhMnHBY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLhwWEwecFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIqr6mi1a+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+p + oouvqaIJr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAcFhMAHBYTABwWEwAcFhMEHBYTJxwWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TLhwWEwfcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miCK+poqevqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poouvqaIJr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTBBwWEydcFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLhwWEwfcFhMAHBYTABwWEwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaJIr6mi9a+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/K+pooyvqaIJr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABwWEwAcFhMAHBYTABwWEwQcFhMnXBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTLhwWEwfcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miAa+pop2vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/rqih/7Ot + p/+1r6n/r6mj/6+oof+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+pooyvqaIKr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMEHBYTJ1wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLlwWEwfcFhMAHBY + TABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIWr6mi1K+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/7Cqo//NycX/7evq//Hw7//c2db/trGq/6+oof+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/K+pooyvqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBY + TABwWEwAcFhMAHBYTBBwWEyecFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLlwWEwfcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pojCvqaLtr6mi/6+pov+vqaL/r6mi/6+pov+uqKH/xsK9//v7 + +v/////////////////d2tf/sKqj/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+p + oo2vqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWEwQcFhMnnBYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TLpwWEwhcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miQK+p + ovavqaL/r6mi/6+pov+vqaL/r6mi/66oof/c2db///////////////////////Lx8P+2sar/r6mh/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poo2vqaIKr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBY + TABwWEwAcFhMEXBYTJ5wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM8HBYTEpwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaI+r6mi9a+pov+vqaL/r6mi/6+pov+vqaL/rqih/9jV + 0v//////////////////////7+7t/7SvqP+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/K+poo2vqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTBFwWEyecFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TPBwWExlcFhMAnBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+p + oiqvqaLpr6mi/6+pov+vqaL/r6mi/6+pov+uqKH/vbmz//Py8P////////////z8/P/Qzcn/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poo6vqaIKr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TABwWEwRcFhMn3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEzwcFhMZXBYTAFwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miEa+posuvqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/vrmz/9nX0//e3Nn/ycXA/7GrpP+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poo6vqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMEXBYTJ9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM8HBY + TGRwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6mii6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+uqKH/rqih/6+pov+uqKH/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+p + oo6vqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TBFwWEyfcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTPBwWExkcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaI2r6mi6q+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poo+vqaIKr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwMcFhMnXBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEzwcFhMZHBY + TABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pogKvqaKKr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/a+poo+vqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TEtwWEz4cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM8HBYTGNwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pohevqaK4r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+poo+vqaILr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwBcFhMmXBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTO9wWExjcFhMAHBY + TABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiSvqaLAr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/a+poo+vqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TB5wWEzbcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEzvcFhMY3BYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiSvqaLAr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+p + opCvqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMXnBYTP1wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM73BYTGJwWEwAcFhMAHBY + TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiSvqaLAr6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popCvqaILr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBY + TAVwWEyrcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTO9wWExicFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiSvqaLAr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/a+popCvqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMK3BYTOdwWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEzvcFhMYnBYTABwWEwAcFhMAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiSvqaLAr6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popGvqaILr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBY + TABwWExxcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM73BYTGFwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiSvqaK/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popGvqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMCnBYTL1wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTO9wWExhcFhMAHBYTABwWEwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiOvqaK/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+p + opGvqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TABwWExhcFhM9XBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEzucFhMYXBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiOvqaK/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popKvqaILr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMXHBYTOxwWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM7nBYTGFwWEwAcFhMAHBYTAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiOvqaK/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/a+popKvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBY + TF1wWEztcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM43BY + TKVwWExJcFhMAXBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiOvqaK+r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popKvqaIMr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWExdcFhM7XBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEzscFhMtnBYTGlwWEwmcFhMA3BYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiOvqaK+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popOvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMXXBY + TO1wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTPRwWEzGcFhMfHBYTDNwWEwIcFhMAHBY + TABwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiOvqaK+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+p + opOvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTF1wWEztcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEzCcFhMRXBYTA9wWEwAcFhMAHBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiKvqaK9r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popOvqaIMr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWExecFhM7XBY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMwHBYTCRwWEwAcFhMAHBYTABwWEwAcFhMAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiKvqaK9r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/a+popSvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAcFhMAHBYTABwWEwAcFhMXnBYTO1wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TMBwWEwkcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiKvqaK9r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popSvqaIMr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTF5wWEztcFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy/cFhMJHBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiKvqaK9r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popSvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABwWEwAcFhMAHBYTABwWExfcFhM7nBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMv3BY + TCRwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiKvqaK8r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+p + opSvqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMX3BYTO5wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTL9wWEwjcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiGvqaK8r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popWvqaINr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBY + TABwWEwAcFhMAHBYTF9wWEzucFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy/cFhMI3BY + TABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiGvqaK8r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/q+popWvqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWExgcFhM7nBYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhMvnBYTCNwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiGvqaK8r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popWvqaINr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBY + TABwWEwAcFhMYHBYTO5wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTL5wWEwjcFhMAHBY + TABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiGvqaK7r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popavqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTGBwWEzucFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEy+cFhMI3BYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiGvqaK7r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+p + opavqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TABwWExhcFhM7nBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMvnBYTCJwWEwAcFhMAHBY + TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiCvqaK7r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popavqaINr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMYXBYTO9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTL1wWEwicFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiCvqaK7r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/q+popevqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBY + TGFwWEzvcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy9cFhMInBYTABwWEwAcFhMAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiCvqaK6r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popevqaINr6miAK+p + ogCvqaIAAAAAAAAAAABwWEwAcFhMAHBYTABwWExhcFhM73BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhMvXBYTCJwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiCvqaK6r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popevqaIOr6miAK+pogCvqaIAcFhMAHBYTABwWEwAcFhMYnBY + TO9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLxwWEwicFhMAHBYTABwWEwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiCvqaK6r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/7Cqov+xq6L/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+p + opivqaIOr6miAJ+VjABwWEwAcFhMAHBYTGJwWEzvcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEy8cFhMIXBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiCvqaK6r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+wqqL/opyl/5eRp/+ln6T/sKqi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popivqaIOoJaOAHxoXQBwWExicFhM73BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMvHBYTCFwWEwAcFhMAHBYTAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poh+vqaK5r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/rqii/3t1rv87M73/LibA/0M7u/+Jgqv/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/q+popiuqKERb1dLYnBYTO9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TLxwWEwhcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh+vqaK5r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/7Grov+Ujqj/MCi//yEZw/8iGsL/IRnD/zMr + vv+GgKv/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/I9/dsBvV0vscFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy7cFhMIXBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh+vqaK5r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/sauh/3p0rv8jG8L/IxvC/yMbwv8jG8L/IRnC/zMrvv+GgKv/sKqi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+XioH/dV5S/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMu3BY + TCFwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oh+vqaK4r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+xq6L/h4Gr/ycfwf8jG8L/IxvC/yMb + wv8jG8L/IRnC/zIrvv+Gf6v/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/l4qB/3RdUf9vV0v/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLtwWEwgcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh+vqaK4r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+poqP/V1C2/yMbwv8jG8L/IxvC/yMbwv8jG8L/IRnC/zIrv/+Gf6v/sKqi/6+p + ov+vqaL/r6mi/5eKgf90XVH/b1dL/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy6cFhMIHBY + TABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poh6vqaK4r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/7Cqov+knqT/TEW8/yIa + w/8jG8L/IxvC/yMbwv8jG8L/IRnC/zIqv/+Gf6v/sKqi/6+pov+XioH/dF1R/29XS/9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9vV0v/cFhMuXBYTCBwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh6vqaK4r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/sKqh/5iSsv9RSd7/LCTS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IRnC/zIq + v/+Ffqv/l4qA/3RdUf9vV0v/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3xnXOSGdGoxiXhuAJKE + ewBxWU4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh6vqaK3r6mi/6+pov+vqaL/r6mi/7Cqof+XkbL/U0vh/z83 + 7/8+Nuv/LSXR/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrD/zAnu/9cSnT/cFhK/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/29XS/+Cb2T/p5+Y/LCrpJmvqaIPr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oh6vqaK3r6mi/6+pov+wqqH/l5Gy/1NL4f8/N+//QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IhrD/yshtf9ZRm//cVlL/3BYTP9wWEz/cFhM/3BYTP9vV0v/gm9k/6efmP+wqqP/r6mi/6+p + opuvqaIPr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh6vqaK3sKqh/5eRsv9TS+H/Pzfv/0A4 + 7v9AOO7/QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrD/yshtv9ZRm//cVlL/3BY + TP9wWEz/b1dL/4JvZP+on5j/sKqj/6+pov+vqaL/r6mi/6+popuvqaIPr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCpo6YArKakALu1mh2QibjFU0zh/z837/9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yMb + wv8jG8L/IxvC/yMbwv8jG8L/IhrD/yshtv9ZRnD/cVhL/29XS/+Cb2T/qJ+Y/7Cqo/+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+popuvqaIPr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gA+Nu8APjbwOEE57tc/N+7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrD/ysh + tv9ZRXD/g3Bk/6igmP+wqqP/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+popyvqaIPr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA4 + 7gBAOO4AQDjuAEA47jlAOO7WQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrD/ywjt/9/d6T/sauj/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+popyvqaIPr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO46QDju1kA47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IhrD/zIqv/+Efqz/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + opyvqaIQr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gBAOO4AQDjuOkA47tdAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrC/zEqv/+Efqz/sKqi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pop2vqaIQr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47jpAOO7XQDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/z426/88NOj/Pjbr/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yMb + wv8jG8L/IxvC/yMbwv8jG8L/IhrC/zEpv/+Efaz/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pop2vqaIQr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA4 + 7gBAOO46QDju10A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v84MOH/KiLM/yYe + x/8qIsz/ODDi/0A47v9AOO7/QDju/0A47v8+Nuv/LibS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrC/zEp + v/+Efaz/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pop2vqaIQr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuO0A47tdAOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/Ny/g/yYexv8jG8H/IxvC/yIawf8oIMn/PDTp/0A47v9AOO7/QDju/0A4 + 7v8+Nuv/LibS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrC/zEpv/+Efaz/sKqi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pop2vqaIQr6miAK+pogCvqaIAAAAAAAAAAACvqaIAr6miAK+p + ogCvqaIAr6miAK+pogCvqaIAr6miAK+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA4 + 7jtAOO7XQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zcv4P8mHsb/IxvC/yMb + wv8jG8L/IxvC/yQcw/83L+H/QDjv/0A47v9AOO7/QDju/0A47v8+Nuv/LibS/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IhrC/zEpv/+Efqz/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + op6vqaIQr6miAK+pogCvqaIAr6miAK+pogCvqaIAr6miAK+pogKvqaIJr6miDa+pogyvqaIJr6miA6+p + ogCvqaIAr6miAK+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO47QDju2EA47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v83L+D/Jh7G/yMbwv8jG8L/IxvC/yMbwv8jG8L/JR3E/zkx5P9AOO//QDju/0A4 + 7v9AOO7/QDju/0A47v8+Nuv/LibS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IRnC/zcwvf+blKf/sKqi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pop6vqaIQr6miAK+pogSvqaIYr6miOK+p + omCvqaKIr6miqa+por+vqaLIr6mixq+por6vqaKsr6mika+pomyvqaJCr6miHK+pogOvqaIAr6miAK+p + ogCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuPEA4 + 7thAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ny/g/yYexv8jG8L/IxvC/yMb + wv8jG8L/IxvC/yMbwv8vJ9T/Pzft/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yIa + w/8jG8L/IxvC/yMbwv8jG8L/IxvC/312rf+xq6H/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+poqWvqaJ0r6miq6+potavqaLxr6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+povavqaLar6mip6+pomCvqaIfr6miAK+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47jxAOO7YQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/zcv4P8mHsb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LibT/z426/9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47/9BOun/QjrF/yQcwf8jG8L/IxvC/yMbwv8mHsH/hH6s/7Gr + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+p + otuvqaKMr6miMK+pogGvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO48QDju2EA4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v83L+D/Jh7G/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IxvC/y4m0/8+Nuv/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AN+7/Qjrt/3dw + yf+hm6f/WFG2/yQcwv8gGMP/IhrC/05HuP+moKT/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaLnr6mija+poiSvqaIAr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAQDjuAEA47gBAOO4AQDjuPEA47tlAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/Ny/g/yYexv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8uJtP/Pjbr/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDfu/0I67P92b8n/rKak/7Grof+noaT/eXKu/15Xtf9xa7D/opul/7Cq + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi2K+pomKvqaIIr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47j1AOO7ZQDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zcv4P8mHsb/IxvC/yMbwv8jG8L/IxvC/yMb + wv8jG8L/LibT/z426/9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/z837v9COuz/dm/J/6ym + pP+wqqL/r6mi/7Cqov+xq6L/sKqi/7Grov+wqqL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi+a+p + opyvqaIcr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABAOO4AQDjuAEA47gBAOO49QDju2UA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v83L+D/Jh7G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y4m0/8+Nuv/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/Qzvs/3Zvyf+spqT/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+posKvqaIwr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuPUA47tlAOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ny/g/yYexv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMb + wv8uJtP/Pjbr/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/z837/dsZdDarKak/7Cq + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+potSvqaI7r6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA4 + 7gBAOO4AQDjuAEA47j1AOO7ZQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zcv + 4P8mHsb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LibT/z426/9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO76Pzfvg5mTsSWwqqGxr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+potivqaI3r6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO4+QDju2kA47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v83L+D/Jh7G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y4m + 0/8+Nuv/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+kA47oRBOe0HioO7AK+p + ohuvqaKyr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pos6vqaIor6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gBAOO4AQDjuPkA47tpAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ny/g/yYe + xv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8uJtP/Pjbr/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47vpAOO6EQDjuB0A47gCBesIAr6miAK+pohqvqaKxr6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + orSvqaISr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47j5AOO7aQDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/zcv4P8mHsb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LibT/z42 + 6/9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO76QDjug0A47gdAOO4AQDjuAK+p + ogCvqaIAr6miAK+pohqvqaKxr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pooSvqaIBr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA4 + 7gBAOO4+QDju2kA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82LuD/Jh7G/yMb + wv8jG8L/IxvC/yMbwv8jG8L/IxvC/y4m0/8+Nuv/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju+kA47oNAOO4HQDjuAEA47gAAAAAAAAAAAK+pogCvqaIAr6miAK+pohqvqaKxr6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi7q+pokSvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuP0A47tpAOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/Ni7g/yYexv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8uJtP/Pjbr/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vpAOO6CQDjuB0A47gBAOO4AAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+pohqvqaKxr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6miu6+pog+vqaIAr6miAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA4 + 7j9AOO7bQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8mHsb/IxvC/yMb + wv8jG8L/IxvC/yMbwv8jG8L/LibT/z426/9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO76QDjugkA47gdAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + ohqvqaKwr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL7r6miYa+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO4/QDju20A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v82Lt//Jh7G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y4m0/8+Nuv/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+kA47oJAOO4HQDjuAEA47gBAOO4AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+pohyvqaLMr6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaLGr6miEq+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuQEA4 + 7ttAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ni7f/yYexv8jG8L/IxvC/yMb + wv8jG8L/IxvC/yMbwv8uJtP/Pjbr/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7vlAOO6BQDjuB0A47gBAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miH6+potmvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povqvqaJVr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47kBAOO7bQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/zYu3/8mHsb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LibT/z426/9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO75QDjugUA47gZAOO4AQDjuAEA47gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaJor6mi/q+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL9r6mi2a+povavqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + oqmvqaIFr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO5AQDju3EA4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82Lt//Jh7G/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IxvC/y8n0/8+Nuv/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+UA4 + 7oFAOO4GQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miCK+porWvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi7q+pooKvqaIdr6miYa+p + ot2vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi5a+poiivqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAQDjuAEA47gBAOO4AQDjuQEA47txAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/Ni7f/yUdxv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8vJ9T/Pjbr/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47vlAOO6AQDjuBkA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIqr6mi56+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+posmvqaJIr6miAa+pogCvqaIAr6miLa+poq2vqaL8r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL+r6miYK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47kFAOO7cQDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8lHcb/IxvC/yMbwv8jG8L/IxvC/yMb + wv8jG8L/LyfU/z427P9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO75QDjugEA4 + 7gZAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pol6vqaL+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povSvqaKRr6miG6+pogCvqaIAr6miAK+p + ogCvqaIAr6miDK+ponCvqaLlr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaKbr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABAOO4AQDjuAEA47gBAOO5BQDju3EA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v82Lt//JR3G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n1P8+Nuz/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju+UA47oBAOO4GQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6mikq+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaLUr6miVa+pogSvqaIAr6miAK+pogAAAAAAr6miAK+pogCvqaIAr6miAK+pojivqaK5r6mi/q+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+posivqaIOr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuQUA47txAOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ni7f/yUdxv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMb + wv8vJ9T/Pjbs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vlAOO5/QDjuBkA4 + 7gBAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAr6miAK+pogivqaK7r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL4r6mioK+poiSvqaIAr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+pohKvqaJ+r6mi7K+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi5K+poiSvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA4 + 7gBAOO4AQDjuAEA47kJAOO7dQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu + 3/8lHcb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LyfU/z427P9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO75QDjuf0A47gZAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miFq+potavqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi3a+p + omOvqaIIr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + ogCvqaJEr6mixa+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaLzr6miO6+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO5CQDju3UA47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82Lt//JR3G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n + 1P8+Nuz/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+UA47n9AOO4GQDjuAEA4 + 7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIlr6mi5q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poq2vqaIur6miAK+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pogCvqaIZr6mija+povKvqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povevqaJCr6miAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gBAOO4AQDjuQkA47t1AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ni7f/yUd + xv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8vJ9T/Pjbs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47vlAOO5+QDjuBkA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pojCvqaLur6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pouavqaJxr6miDK+p + ogCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pogCvqaIDr6miUa+potCvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi96+pokKvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47kJAOO7dQDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8lHcb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LyfU/z42 + 7P9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO75QDjufkA47gZAOO4AQDjuAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miOK+povKvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaLNr6miOa+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pogCvqaIAr6miIK+p + oqqvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL3r6miQq+p + ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA4 + 7gBAOO5DQDju3UA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82Lt//JR3G/yMb + wv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n1P8+Nuz/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju+UA47n5AOO4GQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaI2r6mi8a+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poo6vqaIAr6miAK+p + ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIAr6miWa+pov6vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povevqaJCr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuQ0A47t5AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/Ni7f/yUdxv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8vJ9T/Pjbs/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vhAOO59QDjuBUA47gBAOO4AQDjuAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+poi6vqaLsr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mij6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+p + ogCvqaJar6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi96+p + okKvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA4 + 7kNAOO7eQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8lHcb/IxvC/yMb + wv8jG8L/IxvC/yMbwv8jG8L/LyfU/z427P9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO74QDjufUA47gVAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miI6+p + ouOvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaKPr6miAK+p + ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+polqvqaL+r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL3r6miQa+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO42QDju20A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v82Lt//JR3F/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n1P8+Nuz/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+EA47n1AOO4FQDjuAEA47gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIUr6mi0q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poo+vqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miWq+pov6vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ovCvqaI1r6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuFUA4 + 7r9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ni7f/yUdxf8jG8L/IxvC/yMb + wv8jG8L/IxvC/yMbwv8vJ9T/Pzfs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7vhAOO58QDjuBUA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+p + ogavqaK2r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mij6+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaJar6mi/q+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi3q+poh2vqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO5zQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/zYu3/8lHcX/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LyfU/z837P9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO74QDjufEA47gVAOO4AQDjuAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pooyvqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaKPr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAr6miAK+polqvqaL+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaK9r6miCa+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuF0A4 + 7tFAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82Lt7/JR3F/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IxvC/y8n1P8/N+z/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+EA4 + 7nxAOO4FQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miWK+povyvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + oo+vqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miWq+pov6vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poouvqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO5OQDju+UA47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/Ni7e/yUdxf8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8vJ9T/Pzfs/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47vhAOO57QDjuBUA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaImr6mi5K+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mij6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaJar6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL5r6miT6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA4 + 7oVAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8lHcX/IxvC/yMbwv8jG8L/IxvC/yMb + wv8jG8L/LyfU/z837P9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO74QDjue0A4 + 7gVAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAr6miAK+pogavqaKvr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaKPr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+polqvqaL+r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+potivqaIbr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4CQDjup0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v87M+f/Jh7H/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n1P8/N+z/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju+EA47ntAOO4FQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pomCvqaL9r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poo+vqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miWq+pov6vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mikq+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gZAOO63QDju/0A47v9AOO7/QDju/0A47v9AOO7/QTnv/zUt3v8jG8L/IxvC/yMbwv8jG8L/IxvC/yMb + wv8vJ9X/Pzfs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vhAOO56QDjuBUA4 + 7gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miG6+potWvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mij6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaJar6mi/q+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povCvqaI+r6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuBUA47rFAOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO//Ny/h/yQcw/8jG8L/IxvC/yMbwv8jG8L/LyfV/z837P9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO73QDjuekA47gVAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6mifK+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaKPr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+polqvqaL+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mirK+pogevqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA4 + 7gBAOO4AQDjumEA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuz/LSXR/yMbwv8jG8H/JBzD/zAo + 1f8/N+z/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju90A47npAOO4FQDjuAEA4 + 7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIgr6mi16+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+poo+vqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miWq+p + ov6vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povGvqaJEr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO5qQDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v8+Nuv/NS3d/zEp1/83L+D/Pzfs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47vdAOO55QDjuBUA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsaWQAr6miAK+p + ogCvqaJrr6mi/K+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mij6+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaJar6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mimq+pogSvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABAOO4AQDjuAEA47jBAOO7qQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO//QDjv/0A4 + 7/9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO73QDjueUA47gRAOO4AQDjuAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pog+vqaK0r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaKPr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+p + olqvqaL+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+potmvqaInr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuBUA47qZAOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju90A47nlAOO4EQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pojSvqaLhr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poo+vqaIAr6miAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miWq+pov6vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL1r6miW6+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAEA47gBAOO4AQDjuO0A47upAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vdAOO54QDjuBEA47gBAOO4AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+pol6vqaL0r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mij6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaJar6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+poomvqaIEr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjueEA4 + 7vxAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO73QDjueEA47gRAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miA6+ponyvqaL7r6mi/6+pov+vqaL/r6mi/6+pov+vqaKPr6miAK+p + ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+polqvqaL+r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaKlr6miD6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4KQDjukEA47v1AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju9kA47ndAOO4EQDjuAEA47gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miCK+p + ooivqaL7r6mi/6+pov+vqaL/r6mi/6+poo+vqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miWq+pov6vqaL/r6mi/6+pov+vqaL/r6mir6+pohivqaIAr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gBAOO4LQDjufUA47u9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7uRAOO5mQDjuBEA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miCa+pooOvqaL3r6mi/6+pov+vqaL/r6mij6+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaJar6mi/q+pov+vqaL/r6mi/6+p + oqivqaIYr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO4CQDjuREA47rNAOO7yQDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47uxAOO6kQDjuNUA47gBAOO4AQDjuAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miBa+pomuvqaLqr6mi/6+pov+vqaKPr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAr6miAK+polqvqaL+r6mi/6+povevqaKOr6miEa+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAQDjuAEA47gBAOO4AQDjuCkA47j5AOO6AQDjusEA47slAOO7RQDjux0A47qtAOO53QDjuNEA4 + 7gVAOO4AQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIAr6miAK+pokWvqaLKr6mi/6+p + opCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miW6+pov+vqaLfr6miY6+p + ogavqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuAEA4 + 7gBAOO4FQDjuDkA47hNAOO4NQDjuA0A47gBAOO4AQDjuAEA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+pohyvqaKPr6mifK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaJRr6mipa+poi+vqaIAr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47gBAOO4AQDjuAEA47gBAOO4AQDjuAEA4 + 7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + ogOvqaIRr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pog2vqaIJr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miAK+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////////// + ////////////////////////////////////////////////////////////////////+B////////// + ////4H///8AB/////////////8A///8AAP////////////+AH//+AAA/////////////AA///AAAH/// + /////////gAH//gAAA////////////wAA//4AAAH///////////4AAH/8AAAA///////////8AAA//AA + AAH//////////+AAAH/wAAAA///////////AAAA/8AAAAH//////////gAAAH/AAAAA//////////wAA + AB/wAAAAH/////////4AAAAf8AAAAA/////////8AAAAH/AAAAAH////////+AAAAD/wAAAAA/////// + //AAAAB/8AAAAAH////////wAAAA//AAAAAA////////4AAAAf/wAAAAAH///////+AAAAP/+AAAAAA/ + ///////gAAAH//gAAAAAH///////wAAAD//8AAAAAA///////8AAAB///gAAAAAH///////AAAA///8A + AAAAA///////gAAAf///gAAAAAH//////4AAAP///8AAAAAA//////8AAAH////gAAAAAH/////+AAAD + ////8AAAAAA//////AAAB/////gAAAAAH/////gAAA/////8AAAAAA/////wAAAf/////gAAAAAH//// + 4AAAP/////8AAAAAA////8AAAf//////gAAAAAH///+AAAf//////8AAAAAA////AAA////////gAAAA + AH///gAAf///////8AAAAAA///wAAP////////gAAAAAH//4AAH////////8AAAAAA//8AAD//////// + /gAAAAAH/+AAB/////////8AAAAAA//AAA//////////gAAAAAH/gAAf/////////8AAAAAA/wAAP/// + ///////gAAAAAH4AAH//////////8AAAAAA8AAD///////////gAAAAAGAAB///////////8AAAAAAAA + A////////////gAAAAAAAAf///////////8AAAAAAAAP////////////gAAAAAAAH////////////8AA + AAAAAD/////////////gAAAAAAB/////////////8AAAAAAA//////////////gAAAAAAf////////// + ///8AAAAAAP//////////////gAAAAAH//////////////8AAAAAA///////////////gAAAAAH///// + /////////8AAAAAA///////////////gAAAAAH//////////////4AAAAAA//////////////8AAAAAA + H/////////////+AAAAAAA//////////////AAAAAAAH/////////////gAAAAAAA/////////////wA + AAAAAAH////////////4AAAAAAAAwAP/////////8AAAAAAAAAAAP////////+AAAAAAAAAAAAf///// + ///AAAAAAAAAAAAB////////gAAAAAAAAAAAAP///////wAAAAAAAAAAAAA///////4AAAAAAAAAAAAA + H//////8AAAAAAAAAAAAAA//////+AAAAAAAAAAAAAAH//////AAAAAAAAAAAAAAA//////gAAAAAAAA + AAAAAAH/////wAAAAAAAAAAAAAAA/////4AAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAB////+AAAA + AAMAAAAAAAAAf////AAAAAAHgAAAAAAAAD////gAAAAAD8AAAAAAAAA////wAAAAAA/gAAAAAAAAH/// + 4AAAAAAf8AAAAAAAAB///8AAAAAAP/AAAAAAAAAf//+AAAAAAP/wAAAAAAAAD///AAAAAAH/4AAAAAAA + AA///gAAAAAD/+AAAAAAAAAP//wAAAAAB//gAAABAAAAD//4AAAAAAf/4AAAA8AAAA//8AAAAAAf/+AA + AA/gAAAP/+AAAAAAP//gAAAf+AAAD//AAAAAAH//4AAAf/wAAA//gAAAAAD//+AAAP/+AAAP/wAAAAAB + ///gAAP//4AAD/4AAAAAAf//4AAH///AAA/8AAAAAAf//+AAB///4AAP/AAAAAAP///gAAf//+AAD/gA + AAAAH///4AAH///gAA/4AAAAAD///+AAB///4AAP8AAAAAB////gAAf//+AAD/AAAAAA////4AAH///g + AA/wAAAAAf////AAB///4AAP8AAAAAP////wAAf//+AAH/AAAAAH////8AAH///gAB/wAAAAD/////gA + B///4AAf8AAAAB/////4AAf//+AAP/AAAAA/////+AAH///gAD/wAAAAf/////wAB///4AB/+AAAAP// + ///+AAf//+AAf/gAAAH//////gAH///gAP/4AAAD//////8AB///4AH//AAAB///////gAf//+AB//4A + AA///////8AH///gA//+AAAf///////gB///4Af//4AAP///////4Af//+AP///AAH////////gH///g + H///8AP////////8B///4H///////////////gf//+D///////////////////////////////////// + //////////////////////////////////////////////////8= + + + \ No newline at end of file diff --git a/类库/OnlineRepair/InstallFileForm.cs b/类库/OnlineRepair/InstallFileForm.cs new file mode 100644 index 0000000..1b0c4ae --- /dev/null +++ b/类库/OnlineRepair/InstallFileForm.cs @@ -0,0 +1,118 @@ +using OnlineRepair; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Management; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace VersionUpdate +{ + public partial class InstallFileForm : Form + { + List infos; + Client client; + public InstallFileForm(List infos, Client client) + { + InitializeComponent(); + this.client = client; + this.infos = infos; + } + + public void Kill(string filePath) + { + try + { + if (string.IsNullOrWhiteSpace(filePath)) return; + var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process"; + using (var searcher = new ManagementObjectSearcher(wmiQueryString)) + using (var results = searcher.Get()) + { + var query = from p in Process.GetProcesses() + join mo in results.Cast() + on p.Id equals (int)(uint)mo["ProcessId"] + select new + { + Process = p, + Path = (string)mo["ExecutablePath"], + CommandLine = (string)mo["CommandLine"], + }; + + foreach (var item in query) + { + if (filePath == item.Path) + { + item.Process.Kill(); + item.Process.WaitForExit(); + } + } + } + } + catch (Exception ex) + { } + } + + private bool IsClose = false; + private void InstallFileForm_Load(object sender, EventArgs e) + { + var method = new Action(delegate () + { + try + { + int i = 1; + Thread.Sleep(2000); + + Kill(Program.ExeName); + + foreach (var item in infos) + { + this.Invoke(new Action(delegate + { + this.label1.Text = $"正在安装第{i}个文件包...(共{infos.Count}个)"; + })); + this.client.InstallFile(item); + Application.DoEvents(); + } + this.Invoke(new Action(delegate + { + this.label1.Text = $"安装完成!"; + IsClose = true; + this.Close(); + })); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + this.label1.Text = $"安装失败:" + ex.Message; + })); + } + finally + { + IsClose = true; + } + }); + method.BeginInvoke(null, null); + } + + private void InstallFileForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (!IsClose) + { + MessageBox.Show("安装还未结束,不能中途退出!", "友情提醒", MessageBoxButtons.OK, MessageBoxIcon.Error); + e.Cancel = true; + } + } + catch (Exception) + { } + } + } +} diff --git a/类库/OnlineRepair/InstallFileForm.designer.cs b/类库/OnlineRepair/InstallFileForm.designer.cs new file mode 100644 index 0000000..4663cf6 --- /dev/null +++ b/类库/OnlineRepair/InstallFileForm.designer.cs @@ -0,0 +1,69 @@ +namespace VersionUpdate +{ + partial class InstallFileForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InstallFileForm)); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(2, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(406, 82); + this.label1.TabIndex = 0; + this.label1.Text = "准备修复"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // InstallFileForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(411, 103); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InstallFileForm"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "正在修复"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.InstallFileForm_FormClosing); + this.Load += new System.EventHandler(this.InstallFileForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/OnlineRepair/InstallFileForm.resx b/类库/OnlineRepair/InstallFileForm.resx new file mode 100644 index 0000000..a75e619 --- /dev/null +++ b/类库/OnlineRepair/InstallFileForm.resx @@ -0,0 +1,1244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAgH8AAAEAIAAYBgEAFgAAACgAAACAAAAA/gAAAAEAIAAAAAAAAP4AABEXAAARFwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+pogCvqaIAr6miAK+pogCvqaIAr6miAK+p + ogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBY + TA1wWEwTcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + ogCvqaIOr6miOK+pomOvqaJ9r6miga+ponGvqaJMr6miH6+pogGvqaIAr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWEwPcFhMnHBYTLRwWEwecFhMAHBYTABwWEwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miAK+pogCvqaIRr6miaK+posOvqaLxr6mi/6+pov+vqaL/r6mi/6+p + ovmvqaLcr6milK+pojCvqaIAr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMD3BY + TJtwWEz/cFhM/3BYTLdwWEwecFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIAr6miNK+p + orqvqaL9r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi5K+pom6vqaIHr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTA9wWEyccFhM/3BYTP9wWEz/cFhM/3BYTLdwWEwecFhMAHBY + TABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+pokCvqaLar6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi+q+poomvqaIJr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWEwQcFhMnHBY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLhwWEwecFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIqr6mi1a+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+p + oouvqaIJr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAcFhMAHBYTABwWEwAcFhMEHBYTJxwWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TLhwWEwfcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miCK+poqevqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poouvqaIJr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTBBwWEydcFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLhwWEwfcFhMAHBYTABwWEwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaJIr6mi9a+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/K+pooyvqaIJr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABwWEwAcFhMAHBYTABwWEwQcFhMnXBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTLhwWEwfcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miAa+pop2vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/rqih/7Ot + p/+1r6n/r6mj/6+oof+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+pooyvqaIKr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMEHBYTJ1wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLlwWEwfcFhMAHBY + TABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIWr6mi1K+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/7Cqo//NycX/7evq//Hw7//c2db/trGq/6+oof+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/K+pooyvqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBY + TABwWEwAcFhMAHBYTBBwWEyecFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLlwWEwfcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pojCvqaLtr6mi/6+pov+vqaL/r6mi/6+pov+uqKH/xsK9//v7 + +v/////////////////d2tf/sKqj/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+p + oo2vqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWEwQcFhMnnBYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TLpwWEwhcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miQK+p + ovavqaL/r6mi/6+pov+vqaL/r6mi/66oof/c2db///////////////////////Lx8P+2sar/r6mh/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poo2vqaIKr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBY + TABwWEwAcFhMEXBYTJ5wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM8HBYTEpwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaI+r6mi9a+pov+vqaL/r6mi/6+pov+vqaL/rqih/9jV + 0v//////////////////////7+7t/7SvqP+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/K+poo2vqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTBFwWEyecFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TPBwWExlcFhMAnBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+p + oiqvqaLpr6mi/6+pov+vqaL/r6mi/6+pov+uqKH/vbmz//Py8P////////////z8/P/Qzcn/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poo6vqaIKr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TABwWEwRcFhMn3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEzwcFhMZXBYTAFwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miEa+posuvqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/vrmz/9nX0//e3Nn/ycXA/7GrpP+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poo6vqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMEXBYTJ9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM8HBY + TGRwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6mii6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+uqKH/rqih/6+pov+uqKH/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+p + oo6vqaIKr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TBFwWEyfcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTPBwWExkcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaI2r6mi6q+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poo+vqaIKr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwMcFhMnXBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEzwcFhMZHBY + TABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pogKvqaKKr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/a+poo+vqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TEtwWEz4cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM8HBYTGNwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pohevqaK4r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+poo+vqaILr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwBcFhMmXBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTO9wWExjcFhMAHBY + TABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiSvqaLAr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/a+poo+vqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TB5wWEzbcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEzvcFhMY3BYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiSvqaLAr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+p + opCvqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMXnBYTP1wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM73BYTGJwWEwAcFhMAHBY + TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiSvqaLAr6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popCvqaILr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBY + TAVwWEyrcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTO9wWExicFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiSvqaLAr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/a+popCvqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMK3BYTOdwWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEzvcFhMYnBYTABwWEwAcFhMAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiSvqaLAr6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popGvqaILr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBY + TABwWExxcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM73BYTGFwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiSvqaK/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popGvqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMCnBYTL1wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTO9wWExhcFhMAHBYTABwWEwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiOvqaK/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+p + opGvqaILr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TABwWExhcFhM9XBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEzucFhMYXBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiOvqaK/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popKvqaILr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMXHBYTOxwWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM7nBYTGFwWEwAcFhMAHBYTAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiOvqaK/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/a+popKvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBY + TF1wWEztcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM43BY + TKVwWExJcFhMAXBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiOvqaK+r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popKvqaIMr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWExdcFhM7XBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEzscFhMtnBYTGlwWEwmcFhMA3BYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiOvqaK+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popOvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMXXBY + TO1wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTPRwWEzGcFhMfHBYTDNwWEwIcFhMAHBY + TABwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiOvqaK+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+p + opOvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTF1wWEztcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEzCcFhMRXBYTA9wWEwAcFhMAHBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiKvqaK9r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popOvqaIMr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWExecFhM7XBY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMwHBYTCRwWEwAcFhMAHBYTABwWEwAcFhMAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiKvqaK9r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/a+popSvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAcFhMAHBYTABwWEwAcFhMXnBYTO1wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TMBwWEwkcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiKvqaK9r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popSvqaIMr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTF5wWEztcFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy/cFhMJHBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiKvqaK9r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/a+popSvqaIMr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABwWEwAcFhMAHBYTABwWExfcFhM7nBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMv3BY + TCRwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiKvqaK8r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+p + opSvqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMX3BYTO5wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTL9wWEwjcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiGvqaK8r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popWvqaINr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBY + TABwWEwAcFhMAHBYTF9wWEzucFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy/cFhMI3BY + TABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiGvqaK8r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/q+popWvqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBYTABwWExgcFhM7nBYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhMvnBYTCNwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiGvqaK8r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popWvqaINr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBY + TABwWEwAcFhMYHBYTO5wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTL5wWEwjcFhMAHBY + TABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiGvqaK7r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popavqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBYTGBwWEzucFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEy+cFhMI3BYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiGvqaK7r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+p + opavqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwWEwAcFhMAHBY + TABwWExhcFhM7nBYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMvnBYTCJwWEwAcFhMAHBY + TAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiCvqaK7r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popavqaINr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAcFhMAHBYTABwWEwAcFhMYXBYTO9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTL1wWEwicFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poiCvqaK7r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/q+popevqaINr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAHBYTABwWEwAcFhMAHBY + TGFwWEzvcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy9cFhMInBYTABwWEwAcFhMAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiCvqaK6r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popevqaINr6miAK+p + ogCvqaIAAAAAAAAAAABwWEwAcFhMAHBYTABwWExhcFhM73BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhMvXBYTCJwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiCvqaK6r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popevqaIOr6miAK+pogCvqaIAcFhMAHBYTABwWEwAcFhMYnBY + TO9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLxwWEwicFhMAHBYTABwWEwAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oiCvqaK6r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/7Cqov+xq6L/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+p + opivqaIOr6miAJ+VjABwWEwAcFhMAHBYTGJwWEzvcFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TP9wWEy8cFhMIXBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poiCvqaK6r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+wqqL/opyl/5eRp/+ln6T/sKqi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+popivqaIOoJaOAHxoXQBwWExicFhM73BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMvHBYTCFwWEwAcFhMAHBYTAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poh+vqaK5r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/rqii/3t1rv87M73/LibA/0M7u/+Jgqv/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/q+popiuqKERb1dLYnBYTO9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BY + TLxwWEwhcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh+vqaK5r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/7Grov+Ujqj/MCi//yEZw/8iGsL/IRnD/zMr + vv+GgKv/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/I9/dsBvV0vscFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy7cFhMIXBYTABwWEwAcFhMAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh+vqaK5r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/sauh/3p0rv8jG8L/IxvC/yMbwv8jG8L/IRnC/zMrvv+GgKv/sKqi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+XioH/dV5S/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhMu3BY + TCFwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oh+vqaK4r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+xq6L/h4Gr/ycfwf8jG8L/IxvC/yMb + wv8jG8L/IRnC/zIrvv+Gf6v/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/l4qB/3RdUf9vV0v/cFhM/3BY + TP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTLtwWEwgcFhMAHBYTABwWEwAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh+vqaK4r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+poqP/V1C2/yMbwv8jG8L/IxvC/yMbwv8jG8L/IRnC/zIrv/+Gf6v/sKqi/6+p + ov+vqaL/r6mi/5eKgf90XVH/b1dL/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEy6cFhMIHBY + TABwWEwAcFhMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miAK+poh6vqaK4r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/7Cqov+knqT/TEW8/yIa + w/8jG8L/IxvC/yMbwv8jG8L/IRnC/zIqv/+Gf6v/sKqi/6+pov+XioH/dF1R/29XS/9wWEz/cFhM/3BY + TP9wWEz/cFhM/3BYTP9vV0v/cFhMuXBYTCBwWEwAcFhMAHBYTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh6vqaK4r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/sKqh/5iSsv9RSd7/LCTS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IRnC/zIq + v/+Ffqv/l4qA/3RdUf9vV0v/cFhM/3BYTP9wWEz/cFhM/3BYTP9wWEz/cFhM/3xnXOSGdGoxiXhuAJKE + ewBxWU4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh6vqaK3r6mi/6+pov+vqaL/r6mi/7Cqof+XkbL/U0vh/z83 + 7/8+Nuv/LSXR/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrD/zAnu/9cSnT/cFhK/3BYTP9wWEz/cFhM/3BY + TP9wWEz/cFhM/29XS/+Cb2T/p5+Y/LCrpJmvqaIPr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + oh6vqaK3r6mi/6+pov+wqqH/l5Gy/1NL4f8/N+//QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IhrD/yshtf9ZRm//cVlL/3BYTP9wWEz/cFhM/3BYTP9vV0v/gm9k/6efmP+wqqP/r6mi/6+p + opuvqaIPr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+poh6vqaK3sKqh/5eRsv9TS+H/Pzfv/0A4 + 7v9AOO7/QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrD/yshtv9ZRm//cVlL/3BY + TP9wWEz/b1dL/4JvZP+on5j/sKqj/6+pov+vqaL/r6mi/6+popuvqaIPr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCpo6YArKakALu1mh2QibjFU0zh/z837/9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yMb + wv8jG8L/IxvC/yMbwv8jG8L/IhrD/yshtv9ZRnD/cVhL/29XS/+Cb2T/qJ+Y/7Cqo/+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+popuvqaIPr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gA+Nu8APjbwOEE57tc/N+7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrD/ysh + tv9ZRXD/g3Bk/6igmP+wqqP/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+popyvqaIPr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA4 + 7gBAOO4AQDjuAEA47jlAOO7WQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrD/ywjt/9/d6T/sauj/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+popyvqaIPr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO46QDju1kA47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IhrD/zIqv/+Efqz/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + opyvqaIQr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gBAOO4AQDjuOkA47tdAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v8+Nuv/LSXS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrC/zEqv/+Efqz/sKqi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pop2vqaIQr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47jpAOO7XQDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/z426/88NOj/Pjbr/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yMb + wv8jG8L/IxvC/yMbwv8jG8L/IhrC/zEpv/+Efaz/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pop2vqaIQr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA4 + 7gBAOO46QDju10A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v84MOH/KiLM/yYe + x/8qIsz/ODDi/0A47v9AOO7/QDju/0A47v8+Nuv/LibS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrC/zEp + v/+Efaz/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pop2vqaIQr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuO0A47tdAOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/Ny/g/yYexv8jG8H/IxvC/yIawf8oIMn/PDTp/0A47v9AOO7/QDju/0A4 + 7v8+Nuv/LibS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IhrC/zEpv/+Efaz/sKqi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pop2vqaIQr6miAK+pogCvqaIAAAAAAAAAAACvqaIAr6miAK+p + ogCvqaIAr6miAK+pogCvqaIAr6miAK+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA4 + 7jtAOO7XQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zcv4P8mHsb/IxvC/yMb + wv8jG8L/IxvC/yQcw/83L+H/QDjv/0A47v9AOO7/QDju/0A47v8+Nuv/LibS/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IhrC/zEpv/+Efqz/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + op6vqaIQr6miAK+pogCvqaIAr6miAK+pogCvqaIAr6miAK+pogKvqaIJr6miDa+pogyvqaIJr6miA6+p + ogCvqaIAr6miAK+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO47QDju2EA47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v83L+D/Jh7G/yMbwv8jG8L/IxvC/yMbwv8jG8L/JR3E/zkx5P9AOO//QDju/0A4 + 7v9AOO7/QDju/0A47v8+Nuv/LibS/yMbwv8jG8L/IxvC/yMbwv8jG8L/IRnC/zcwvf+blKf/sKqi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pop6vqaIQr6miAK+pogSvqaIYr6miOK+p + omCvqaKIr6miqa+por+vqaLIr6mixq+por6vqaKsr6mika+pomyvqaJCr6miHK+pogOvqaIAr6miAK+p + ogCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuPEA4 + 7thAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ny/g/yYexv8jG8L/IxvC/yMb + wv8jG8L/IxvC/yMbwv8vJ9T/Pzft/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuv/LSXS/yIa + w/8jG8L/IxvC/yMbwv8jG8L/IxvC/312rf+xq6H/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+poqWvqaJ0r6miq6+potavqaLxr6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+povavqaLar6mip6+pomCvqaIfr6miAK+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47jxAOO7YQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/zcv4P8mHsb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LibT/z426/9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47/9BOun/QjrF/yQcwf8jG8L/IxvC/yMbwv8mHsH/hH6s/7Gr + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/a+p + otuvqaKMr6miMK+pogGvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO48QDju2EA4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v83L+D/Jh7G/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IxvC/y4m0/8+Nuv/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AN+7/Qjrt/3dw + yf+hm6f/WFG2/yQcwv8gGMP/IhrC/05HuP+moKT/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaLnr6mija+poiSvqaIAr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAQDjuAEA47gBAOO4AQDjuPEA47tlAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/Ny/g/yYexv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8uJtP/Pjbr/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDfu/0I67P92b8n/rKak/7Grof+noaT/eXKu/15Xtf9xa7D/opul/7Cq + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi2K+pomKvqaIIr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47j1AOO7ZQDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zcv4P8mHsb/IxvC/yMbwv8jG8L/IxvC/yMb + wv8jG8L/LibT/z426/9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/z837v9COuz/dm/J/6ym + pP+wqqL/r6mi/7Cqov+xq6L/sKqi/7Grov+wqqL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi+a+p + opyvqaIcr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABAOO4AQDjuAEA47gBAOO49QDju2UA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v83L+D/Jh7G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y4m0/8+Nuv/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/Qzvs/3Zvyf+spqT/sKqi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+posKvqaIwr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuPUA47tlAOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ny/g/yYexv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMb + wv8uJtP/Pjbr/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/z837/dsZdDarKak/7Cq + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+potSvqaI7r6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA4 + 7gBAOO4AQDjuAEA47j1AOO7ZQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zcv + 4P8mHsb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LibT/z426/9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO76Pzfvg5mTsSWwqqGxr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+potivqaI3r6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO4+QDju2kA47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v83L+D/Jh7G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y4m + 0/8+Nuv/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+kA47oRBOe0HioO7AK+p + ohuvqaKyr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pos6vqaIor6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gBAOO4AQDjuPkA47tpAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ny/g/yYe + xv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8uJtP/Pjbr/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47vpAOO6EQDjuB0A47gCBesIAr6miAK+pohqvqaKxr6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + orSvqaISr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47j5AOO7aQDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/zcv4P8mHsb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LibT/z42 + 6/9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO76QDjug0A47gdAOO4AQDjuAK+p + ogCvqaIAr6miAK+pohqvqaKxr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pooSvqaIBr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA4 + 7gBAOO4+QDju2kA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82LuD/Jh7G/yMb + wv8jG8L/IxvC/yMbwv8jG8L/IxvC/y4m0/8+Nuv/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju+kA47oNAOO4HQDjuAEA47gAAAAAAAAAAAK+pogCvqaIAr6miAK+pohqvqaKxr6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi7q+pokSvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuP0A47tpAOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/Ni7g/yYexv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8uJtP/Pjbr/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vpAOO6CQDjuB0A47gBAOO4AAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+pohqvqaKxr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6miu6+pog+vqaIAr6miAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA4 + 7j9AOO7bQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8mHsb/IxvC/yMb + wv8jG8L/IxvC/yMbwv8jG8L/LibT/z426/9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO76QDjugkA47gdAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + ohqvqaKwr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL7r6miYa+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO4/QDju20A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v82Lt//Jh7G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y4m0/8+Nuv/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+kA47oJAOO4HQDjuAEA47gBAOO4AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+pohyvqaLMr6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaLGr6miEq+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuQEA4 + 7ttAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ni7f/yYexv8jG8L/IxvC/yMb + wv8jG8L/IxvC/yMbwv8uJtP/Pjbr/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7vlAOO6BQDjuB0A47gBAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miH6+potmvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povqvqaJVr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47kBAOO7bQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/zYu3/8mHsb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LibT/z426/9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO75QDjugUA47gZAOO4AQDjuAEA47gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaJor6mi/q+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL9r6mi2a+povavqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + oqmvqaIFr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO5AQDju3EA4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82Lt//Jh7G/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IxvC/y8n0/8+Nuv/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+UA4 + 7oFAOO4GQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miCK+porWvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi7q+pooKvqaIdr6miYa+p + ot2vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi5a+poiivqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAQDjuAEA47gBAOO4AQDjuQEA47txAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/Ni7f/yUdxv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8vJ9T/Pjbr/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47vlAOO6AQDjuBkA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIqr6mi56+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+posmvqaJIr6miAa+pogCvqaIAr6miLa+poq2vqaL8r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL+r6miYK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47kFAOO7cQDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8lHcb/IxvC/yMbwv8jG8L/IxvC/yMb + wv8jG8L/LyfU/z427P9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO75QDjugEA4 + 7gZAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pol6vqaL+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povSvqaKRr6miG6+pogCvqaIAr6miAK+p + ogCvqaIAr6miDK+ponCvqaLlr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaKbr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABAOO4AQDjuAEA47gBAOO5BQDju3EA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v82Lt//JR3G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n1P8+Nuz/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju+UA47oBAOO4GQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6mikq+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaLUr6miVa+pogSvqaIAr6miAK+pogAAAAAAr6miAK+pogCvqaIAr6miAK+pojivqaK5r6mi/q+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+posivqaIOr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuQUA47txAOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ni7f/yUdxv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMb + wv8vJ9T/Pjbs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vlAOO5/QDjuBkA4 + 7gBAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAr6miAK+pogivqaK7r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL4r6mioK+poiSvqaIAr6miAK+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+pohKvqaJ+r6mi7K+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi5K+poiSvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA4 + 7gBAOO4AQDjuAEA47kJAOO7dQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu + 3/8lHcb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LyfU/z427P9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO75QDjuf0A47gZAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miFq+potavqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi3a+p + omOvqaIIr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + ogCvqaJEr6mixa+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaLzr6miO6+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO5CQDju3UA47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82Lt//JR3G/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n + 1P8+Nuz/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+UA47n9AOO4GQDjuAEA4 + 7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIlr6mi5q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/K+poq2vqaIur6miAK+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pogCvqaIZr6mija+povKvqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povevqaJCr6miAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gBAOO4AQDjuQkA47t1AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ni7f/yUd + xv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8vJ9T/Pjbs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47vlAOO5+QDjuBkA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pojCvqaLur6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pouavqaJxr6miDK+p + ogCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pogCvqaIDr6miUa+potCvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi96+pokKvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47kJAOO7dQDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8lHcb/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LyfU/z42 + 7P9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO75QDjufkA47gZAOO4AQDjuAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miOK+povKvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaLNr6miOa+pogCvqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pogCvqaIAr6miIK+p + oqqvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL3r6miQq+p + ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA4 + 7gBAOO5DQDju3UA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82Lt//JR3G/yMb + wv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n1P8+Nuz/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju+UA47n5AOO4GQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaI2r6mi8a+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poo6vqaIAr6miAK+p + ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIAr6miWa+pov6vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povevqaJCr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuQ0A47t5AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/Ni7f/yUdxv8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8vJ9T/Pjbs/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vhAOO59QDjuBUA47gBAOO4AQDjuAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+poi6vqaLsr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mij6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+p + ogCvqaJar6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi96+p + okKvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA4 + 7kNAOO7eQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8lHcb/IxvC/yMb + wv8jG8L/IxvC/yMbwv8jG8L/LyfU/z427P9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO74QDjufUA47gVAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miI6+p + ouOvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaKPr6miAK+p + ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+polqvqaL+r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL3r6miQa+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO42QDju20A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v82Lt//JR3F/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n1P8+Nuz/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+EA47n1AOO4FQDjuAEA47gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIUr6mi0q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poo+vqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miWq+pov6vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ovCvqaI1r6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuFUA4 + 7r9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/Ni7f/yUdxf8jG8L/IxvC/yMb + wv8jG8L/IxvC/yMbwv8vJ9T/Pzfs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7vhAOO58QDjuBUA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+p + ogavqaK2r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mij6+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaJar6mi/q+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi3q+poh2vqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO5zQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/zYu3/8lHcX/IxvC/yMbwv8jG8L/IxvC/yMbwv8jG8L/LyfU/z837P9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO74QDjufEA47gVAOO4AQDjuAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pooyvqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaKPr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAr6miAK+polqvqaL+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaK9r6miCa+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuF0A4 + 7tFAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v82Lt7/JR3F/yMbwv8jG8L/IxvC/yMb + wv8jG8L/IxvC/y8n1P8/N+z/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju+EA4 + 7nxAOO4FQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miWK+povyvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + oo+vqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miWq+pov6vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poouvqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO5OQDju+UA47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/Ni7e/yUdxf8jG8L/IxvC/yMbwv8jG8L/IxvC/yMbwv8vJ9T/Pzfs/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47vhAOO57QDjuBUA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaImr6mi5K+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mij6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaJar6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL5r6miT6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA4 + 7oVAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/zYu3/8lHcX/IxvC/yMbwv8jG8L/IxvC/yMb + wv8jG8L/LyfU/z837P9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO74QDjue0A4 + 7gVAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAr6miAK+pogavqaKvr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaKPr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+polqvqaL+r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+potivqaIbr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4CQDjup0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v87M+f/Jh7H/yMbwv8jG8L/IxvC/yMbwv8jG8L/IxvC/y8n1P8/N+z/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju+EA47ntAOO4FQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pomCvqaL9r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poo+vqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miWq+pov6vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mikq+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gZAOO63QDju/0A47v9AOO7/QDju/0A47v9AOO7/QTnv/zUt3v8jG8L/IxvC/yMbwv8jG8L/IxvC/yMb + wv8vJ9X/Pzfs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vhAOO56QDjuBUA4 + 7gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miG6+potWvqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mij6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaJar6mi/q+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povCvqaI+r6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuBUA47rFAOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO//Ny/h/yQcw/8jG8L/IxvC/yMbwv8jG8L/LyfV/z837P9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO73QDjuekA47gVAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6mifK+p + ov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaKPr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+polqvqaL+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mirK+pogevqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA4 + 7gBAOO4AQDjumEA47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v8+Nuz/LSXR/yMbwv8jG8H/JBzD/zAo + 1f8/N+z/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju90A47npAOO4FQDjuAEA4 + 7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIgr6mi16+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+poo+vqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miWq+p + ov6vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+povGvqaJEr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO5qQDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v8+Nuv/NS3d/zEp1/83L+D/Pzfs/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47vdAOO55QDjuBUA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsaWQAr6miAK+p + ogCvqaJrr6mi/K+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mij6+pogCvqaIAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaJar6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mimq+pogSvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABAOO4AQDjuAEA47jBAOO7qQDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO//QDjv/0A4 + 7/9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO73QDjueUA47gRAOO4AQDjuAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miAK+pog+vqaK0r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaKPr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+p + olqvqaL+r6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+potmvqaInr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuBUA47qZAOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju90A47nlAOO4EQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miAK+pojSvqaLhr6mi/6+pov+vqaL/r6mi/6+pov+vqaL/r6mi/6+poo+vqaIAr6miAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miWq+pov6vqaL/r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaL1r6miW6+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAEA47gBAOO4AQDjuO0A47upAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47vdAOO54QDjuBEA47gBAOO4AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+pol6vqaL0r6mi/6+p + ov+vqaL/r6mi/6+pov+vqaL/r6mij6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaJar6mi/q+pov+vqaL/r6mi/6+pov+vqaL/r6mi/q+poomvqaIEr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjueEA4 + 7vxAOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO73QDjueEA47gRAOO4AQDjuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miA6+ponyvqaL7r6mi/6+pov+vqaL/r6mi/6+pov+vqaKPr6miAK+p + ogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+polqvqaL+r6mi/6+pov+vqaL/r6mi/6+p + ov+vqaKlr6miD6+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4KQDjukEA47v1AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju9kA47ndAOO4EQDjuAEA47gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miCK+p + ooivqaL7r6mi/6+pov+vqaL/r6mi/6+poo+vqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AACvqaIAr6miWq+pov6vqaL/r6mi/6+pov+vqaL/r6mir6+pohivqaIAr6miAK+pogAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA4 + 7gBAOO4LQDjufUA47u9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A47v9AOO7/QDju/0A4 + 7uRAOO5mQDjuBEA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miCa+pooOvqaL3r6mi/6+pov+vqaL/r6mij6+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaJar6mi/q+pov+vqaL/r6mi/6+p + oqivqaIYr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOO4AQDjuAEA47gBAOO4CQDjuREA47rNAOO7yQDju/0A4 + 7v9AOO7/QDju/0A47v9AOO7/QDju/0A47uxAOO6kQDjuNUA47gBAOO4AQDjuAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+p + ogCvqaIAr6miBa+pomuvqaLqr6mi/6+pov+vqaKPr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAr6miAK+polqvqaL+r6mi/6+povevqaKOr6miEa+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAQDjuAEA47gBAOO4AQDjuCkA47j5AOO6AQDjusEA47slAOO7RQDjux0A47qtAOO53QDjuNEA4 + 7gVAOO4AQDjuAEA47gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pogCvqaIAr6miAK+pokWvqaLKr6mi/6+p + opCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvqaIAr6miW6+pov+vqaLfr6miY6+p + ogavqaIAr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDjuAEA47gBAOO4AQDjuAEA4 + 7gBAOO4FQDjuDkA47hNAOO4NQDjuA0A47gBAOO4AQDjuAEA47gBAOO4AAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaIAr6miAK+pohyvqaKPr6mifK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAK+pogCvqaJRr6mipa+poi+vqaIAr6miAK+pogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA47gBAOO4AQDjuAEA47gBAOO4AQDjuAEA47gBAOO4AQDjuAEA4 + 7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+p + ogOvqaIRr6miAK+pogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6miAK+pog2vqaIJr6miAK+p + ogCvqaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK+pogCvqaIAr6miAK+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAACvqaIAr6miAK+pogCvqaIAr6miAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////////// + ////////////////////////////////////////////////////////////////////+B////////// + ////4H///8AB/////////////8A///8AAP////////////+AH//+AAA/////////////AA///AAAH/// + /////////gAH//gAAA////////////wAA//4AAAH///////////4AAH/8AAAA///////////8AAA//AA + AAH//////////+AAAH/wAAAA///////////AAAA/8AAAAH//////////gAAAH/AAAAA//////////wAA + AB/wAAAAH/////////4AAAAf8AAAAA/////////8AAAAH/AAAAAH////////+AAAAD/wAAAAA/////// + //AAAAB/8AAAAAH////////wAAAA//AAAAAA////////4AAAAf/wAAAAAH///////+AAAAP/+AAAAAA/ + ///////gAAAH//gAAAAAH///////wAAAD//8AAAAAA///////8AAAB///gAAAAAH///////AAAA///8A + AAAAA///////gAAAf///gAAAAAH//////4AAAP///8AAAAAA//////8AAAH////gAAAAAH/////+AAAD + ////8AAAAAA//////AAAB/////gAAAAAH/////gAAA/////8AAAAAA/////wAAAf/////gAAAAAH//// + 4AAAP/////8AAAAAA////8AAAf//////gAAAAAH///+AAAf//////8AAAAAA////AAA////////gAAAA + AH///gAAf///////8AAAAAA///wAAP////////gAAAAAH//4AAH////////8AAAAAA//8AAD//////// + /gAAAAAH/+AAB/////////8AAAAAA//AAA//////////gAAAAAH/gAAf/////////8AAAAAA/wAAP/// + ///////gAAAAAH4AAH//////////8AAAAAA8AAD///////////gAAAAAGAAB///////////8AAAAAAAA + A////////////gAAAAAAAAf///////////8AAAAAAAAP////////////gAAAAAAAH////////////8AA + AAAAAD/////////////gAAAAAAB/////////////8AAAAAAA//////////////gAAAAAAf////////// + ///8AAAAAAP//////////////gAAAAAH//////////////8AAAAAA///////////////gAAAAAH///// + /////////8AAAAAA///////////////gAAAAAH//////////////4AAAAAA//////////////8AAAAAA + H/////////////+AAAAAAA//////////////AAAAAAAH/////////////gAAAAAAA/////////////wA + AAAAAAH////////////4AAAAAAAAwAP/////////8AAAAAAAAAAAP////////+AAAAAAAAAAAAf///// + ///AAAAAAAAAAAAB////////gAAAAAAAAAAAAP///////wAAAAAAAAAAAAA///////4AAAAAAAAAAAAA + H//////8AAAAAAAAAAAAAA//////+AAAAAAAAAAAAAAH//////AAAAAAAAAAAAAAA//////gAAAAAAAA + AAAAAAH/////wAAAAAAAAAAAAAAA/////4AAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAB////+AAAA + AAMAAAAAAAAAf////AAAAAAHgAAAAAAAAD////gAAAAAD8AAAAAAAAA////wAAAAAA/gAAAAAAAAH/// + 4AAAAAAf8AAAAAAAAB///8AAAAAAP/AAAAAAAAAf//+AAAAAAP/wAAAAAAAAD///AAAAAAH/4AAAAAAA + AA///gAAAAAD/+AAAAAAAAAP//wAAAAAB//gAAABAAAAD//4AAAAAAf/4AAAA8AAAA//8AAAAAAf/+AA + AA/gAAAP/+AAAAAAP//gAAAf+AAAD//AAAAAAH//4AAAf/wAAA//gAAAAAD//+AAAP/+AAAP/wAAAAAB + ///gAAP//4AAD/4AAAAAAf//4AAH///AAA/8AAAAAAf//+AAB///4AAP/AAAAAAP///gAAf//+AAD/gA + AAAAH///4AAH///gAA/4AAAAAD///+AAB///4AAP8AAAAAB////gAAf//+AAD/AAAAAA////4AAH///g + AA/wAAAAAf////AAB///4AAP8AAAAAP////wAAf//+AAH/AAAAAH////8AAH///gAB/wAAAAD/////gA + B///4AAf8AAAAB/////4AAf//+AAP/AAAAA/////+AAH///gAD/wAAAAf/////wAB///4AB/+AAAAP// + ///+AAf//+AAf/gAAAH//////gAH///gAP/4AAAD//////8AB///4AH//AAAB///////gAf//+AB//4A + AA///////8AH///gA//+AAAf///////gB///4Af//4AAP///////4Af//+AP///AAH////////gH///g + H///8AP////////8B///4H///////////////gf//+D///////////////////////////////////// + //////////////////////////////////////////////////8= + + + \ No newline at end of file diff --git a/类库/OnlineRepair/OnlineRepair.csproj b/类库/OnlineRepair/OnlineRepair.csproj new file mode 100644 index 0000000..b72074f --- /dev/null +++ b/类库/OnlineRepair/OnlineRepair.csproj @@ -0,0 +1,162 @@ + + + + + Debug + AnyCPU + {0576158B-ACD4-4467-85A7-6055B278111E} + WinExe + OnlineRepair + 在线修复 + v4.6.1 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + repairing.ico + + + + + + + + + + + + + + + + + + + Form + + + DownloadForm.cs + + + Form + + + InstallFileForm.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DownloadForm.cs + + + InstallFileForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + \ No newline at end of file diff --git a/类库/OnlineRepair/Program.cs b/类库/OnlineRepair/Program.cs new file mode 100644 index 0000000..62cecee --- /dev/null +++ b/类库/OnlineRepair/Program.cs @@ -0,0 +1,56 @@ +using VersionUpdate; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace OnlineRepair +{ + static class Program + { + internal static string ExeName { get; private set; } + + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main(string[] param) + { + try + { + Client client = new Client(); + if (param.Length > 0) + { + ExeName = Client.MapFile(param[0]); + } + if (client.CheckInstall()) + { + if (param.Length > 0) + { + Client.StartProcess(param[0]); + return; + } + } + else + { + if (client.CheckVersion()) + { + if (client.CheckInstall()) + { + if (param.Length > 0) + { + Client.StartProcess(param[0]); + return; + } + } + } + else if (param.Length == 0) MessageBox.Show("没有发现新版本!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + } + catch (Exception ex) + { } + } + } +} diff --git a/类库/OnlineRepair/Properties/AssemblyInfo.cs b/类库/OnlineRepair/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b3b83ee --- /dev/null +++ b/类库/OnlineRepair/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("OnlineRepair")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OnlineRepair")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("0576158b-acd4-4467-85a7-6055b278111e")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/类库/OnlineRepair/Properties/Resources.Designer.cs b/类库/OnlineRepair/Properties/Resources.Designer.cs new file mode 100644 index 0000000..927f3f7 --- /dev/null +++ b/类库/OnlineRepair/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本: 4.0.30319.42000 +// +// 对此文件的更改可能导致不正确的行为,如果 +// 重新生成代码,则所做更改将丢失。 +// +//------------------------------------------------------------------------------ + +namespace OnlineRepair.Properties +{ + + + /// + /// 强类型资源类,用于查找本地化字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 返回此类使用的缓存 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OnlineRepair.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 覆盖当前线程的 CurrentUICulture 属性 + /// 使用此强类型的资源类的资源查找。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/类库/OnlineRepair/Properties/Resources.resx b/类库/OnlineRepair/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/类库/OnlineRepair/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/OnlineRepair/Properties/Settings.Designer.cs b/类库/OnlineRepair/Properties/Settings.Designer.cs new file mode 100644 index 0000000..9b65c87 --- /dev/null +++ b/类库/OnlineRepair/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace OnlineRepair.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/类库/OnlineRepair/Properties/Settings.settings b/类库/OnlineRepair/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/类库/OnlineRepair/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/类库/OnlineRepair/ZIP/BZip2/BZip2.cs b/类库/OnlineRepair/ZIP/BZip2/BZip2.cs new file mode 100644 index 0000000..91669a8 --- /dev/null +++ b/类库/OnlineRepair/ZIP/BZip2/BZip2.cs @@ -0,0 +1,105 @@ +// BZip2.cs +// +// Copyright (C) 2010 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// Suppress this in CF and 1.1, not needed. Static classes introduced in C# version 2.0 +#if !NETCF_2_0 && !NET_1_1 + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.BZip2 { + + /// + /// An example class to demonstrate compression and decompression of BZip2 streams. + /// + public static class BZip2 + { + /// + /// Decompress the input writing + /// uncompressed data to the output stream + /// + /// The readable stream containing data to decompress. + /// The output stream to receive the decompressed data. + /// Both streams are closed on completion if true. + public static void Decompress(Stream inStream, Stream outStream, bool isStreamOwner) + { + if (inStream == null || outStream == null) { + throw new Exception("Null Stream"); + } + + try { + using (BZip2InputStream bzipInput = new BZip2InputStream(inStream)) { + bzipInput.IsStreamOwner = isStreamOwner; + Core.StreamUtils.Copy(bzipInput, outStream, new byte[4096]); + } + } finally { + if (isStreamOwner) { + // inStream is closed by the BZip2InputStream if stream owner + outStream.Close(); + } + } + } + + /// + /// Compress the input stream sending + /// result data to output stream + /// + /// The readable stream to compress. + /// The output stream to receive the compressed data. + /// Both streams are closed on completion if true. + /// Block size acts as compression level (1 to 9) with 1 giving + /// the lowest compression and 9 the highest. + public static void Compress(Stream inStream, Stream outStream, bool isStreamOwner, int level) + { + if (inStream == null || outStream == null) { + throw new Exception("Null Stream"); + } + + try { + using (BZip2OutputStream bzipOutput = new BZip2OutputStream(outStream, level)) { + bzipOutput.IsStreamOwner = isStreamOwner; + Core.StreamUtils.Copy(inStream, bzipOutput, new byte[4096]); + } + } finally { + if (isStreamOwner) { + // outStream is closed by the BZip2OutputStream if stream owner + inStream.Close(); + } + } + } + + } +} +#endif diff --git a/类库/OnlineRepair/ZIP/BZip2/BZip2Constants.cs b/类库/OnlineRepair/ZIP/BZip2/BZip2Constants.cs new file mode 100644 index 0000000..ad3f40d --- /dev/null +++ b/类库/OnlineRepair/ZIP/BZip2/BZip2Constants.cs @@ -0,0 +1,197 @@ +// BZip2Constants.cs +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + /// + /// Defines internal values for both compression and decompression + /// + internal sealed class BZip2Constants + { + /// + /// Random numbers used to randomise repetitive blocks + /// + public readonly static int[] RandomNumbers = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 + }; + + /// + /// When multiplied by compression parameter (1-9) gives the block size for compression + /// 9 gives the best compression but uses the most memory. + /// + public const int BaseBlockSize = 100000; + + /// + /// Backend constant + /// + public const int MaximumAlphaSize = 258; + + /// + /// Backend constant + /// + public const int MaximumCodeLength = 23; + + /// + /// Backend constant + /// + public const int RunA = 0; + + /// + /// Backend constant + /// + public const int RunB = 1; + + /// + /// Backend constant + /// + public const int GroupCount = 6; + + /// + /// Backend constant + /// + public const int GroupSize = 50; + + /// + /// Backend constant + /// + public const int NumberOfIterations = 4; + + /// + /// Backend constant + /// + public const int MaximumSelectors = (2 + (900000 / GroupSize)); + + /// + /// Backend constant + /// + public const int OvershootBytes = 20; + + private BZip2Constants() + { + } + } +} + +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/OnlineRepair/ZIP/BZip2/BZip2Exception.cs b/类库/OnlineRepair/ZIP/BZip2/BZip2Exception.cs new file mode 100644 index 0000000..3b7c8ff --- /dev/null +++ b/类库/OnlineRepair/ZIP/BZip2/BZip2Exception.cs @@ -0,0 +1,90 @@ +// BZip2.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + /// + /// BZip2Exception represents exceptions specific to Bzip2 algorithm + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class BZip2Exception : SharpZipBaseException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected BZip2Exception(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + /// + /// Initialise a new instance of BZip2Exception. + /// + public BZip2Exception() + { + } + + /// + /// Initialise a new instance of BZip2Exception with its message set to message. + /// + /// The message describing the error. + public BZip2Exception(string message) : base(message) + { + } + + /// + /// Initialise an instance of BZip2Exception + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public BZip2Exception(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/OnlineRepair/ZIP/BZip2/BZip2InputStream.cs b/类库/OnlineRepair/ZIP/BZip2/BZip2InputStream.cs new file mode 100644 index 0000000..162c9d0 --- /dev/null +++ b/类库/OnlineRepair/ZIP/BZip2/BZip2InputStream.cs @@ -0,0 +1,1003 @@ +// BZip2InputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + /// + /// An input stream that decompresses files in the BZip2 format + /// + public class BZip2InputStream : Stream + { + #region Constants + const int START_BLOCK_STATE = 1; + const int RAND_PART_A_STATE = 2; + const int RAND_PART_B_STATE = 3; + const int RAND_PART_C_STATE = 4; + const int NO_RAND_PART_A_STATE = 5; + const int NO_RAND_PART_B_STATE = 6; + const int NO_RAND_PART_C_STATE = 7; + #endregion + #region Constructors + /// + /// Construct instance for reading from stream + /// + /// Data source + public BZip2InputStream(Stream stream) + { + // init arrays + for (int i = 0; i < BZip2Constants.GroupCount; ++i) + { + limit[i] = new int[BZip2Constants.MaximumAlphaSize]; + baseArray[i] = new int[BZip2Constants.MaximumAlphaSize]; + perm[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + BsSetStream(stream); + Initialize(); + InitBlock(); + SetupBlock(); + } + + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + + #region Stream Overrides + /// + /// Gets a value indicating if the stream supports reading + /// + public override bool CanRead + { + get { + return baseStream.CanRead; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek { + get { + return baseStream.CanSeek; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// This property always returns false + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// Gets the length in bytes of the stream. + /// + public override long Length { + get { + return baseStream.Length; + } + } + + /// + /// Gets or sets the streams position. + /// Setting the position is not supported and will throw a NotSupportException + /// + /// Any attempt to set the position + public override long Position { + get { + return baseStream.Position; + } + set { + throw new NotSupportedException("BZip2InputStream position cannot be set"); + } + } + + /// + /// Flushes the stream. + /// + public override void Flush() + { + if (baseStream != null) { + baseStream.Flush(); + } + } + + /// + /// Set the streams position. This operation is not supported and will throw a NotSupportedException + /// + /// A byte offset relative to the parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// The new position of the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("BZip2InputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. + /// This operation is not supported and will throw a NotSupportedExceptionortedException + /// + /// The new length for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("BZip2InputStream SetLength not supported"); + } + + /// + /// Writes a block of bytes to this stream using data from a buffer. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The buffer to source data from. + /// The offset to start obtaining data from. + /// The number of bytes of data to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("BZip2InputStream Write not supported"); + } + + /// + /// Writes a byte to the current position in the file stream. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The value to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("BZip2InputStream WriteByte not supported"); + } + + /// + /// Read a sequence of bytes and advances the read position by one byte. + /// + /// Array of bytes to store values in + /// Offset in array to begin storing data + /// The maximum number of bytes to read + /// The total number of bytes read into the buffer. This might be less + /// than the number of bytes requested if that number of bytes are not + /// currently available or zero if the end of the stream is reached. + /// + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + for (int i = 0; i < count; ++i) { + int rb = ReadByte(); + if (rb == -1) { + return i; + } + buffer[offset + i] = (byte)rb; + } + return count; + } + + /// + /// Closes the stream, releasing any associated resources. + /// + public override void Close() + { + if ( IsStreamOwner && (baseStream != null) ) { + baseStream.Close(); + } + } + /// + /// Read a byte from stream advancing position + /// + /// byte read or -1 on end of stream + public override int ReadByte() + { + if (streamEnd) + { + return -1; // ok + } + + int retChar = currentChar; + switch (currentState) + { + case RAND_PART_B_STATE: + SetupRandPartB(); + break; + case RAND_PART_C_STATE: + SetupRandPartC(); + break; + case NO_RAND_PART_B_STATE: + SetupNoRandPartB(); + break; + case NO_RAND_PART_C_STATE: + SetupNoRandPartC(); + break; + case START_BLOCK_STATE: + case NO_RAND_PART_A_STATE: + case RAND_PART_A_STATE: + break; + default: + break; + } + return retChar; + } + + #endregion + + void MakeMaps() + { + nInUse = 0; + for (int i = 0; i < 256; ++i) { + if (inUse[i]) { + seqToUnseq[nInUse] = (byte)i; + unseqToSeq[i] = (byte)nInUse; + nInUse++; + } + } + } + + void Initialize() + { + char magic1 = BsGetUChar(); + char magic2 = BsGetUChar(); + + char magic3 = BsGetUChar(); + char magic4 = BsGetUChar(); + + if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') { + streamEnd = true; + return; + } + + SetDecompressStructureSizes(magic4 - '0'); + computedCombinedCRC = 0; + } + + void InitBlock() + { + char magic1 = BsGetUChar(); + char magic2 = BsGetUChar(); + char magic3 = BsGetUChar(); + char magic4 = BsGetUChar(); + char magic5 = BsGetUChar(); + char magic6 = BsGetUChar(); + + if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) { + Complete(); + return; + } + + if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) { + BadBlockHeader(); + streamEnd = true; + return; + } + + storedBlockCRC = BsGetInt32(); + + blockRandomised = (BsR(1) == 1); + + GetAndMoveToFrontDecode(); + + mCrc.Reset(); + currentState = START_BLOCK_STATE; + } + + void EndBlock() + { + computedBlockCRC = (int)mCrc.Value; + + // -- A bad CRC is considered a fatal error. -- + if (storedBlockCRC != computedBlockCRC) { + CrcError(); + } + + // 1528150659 + computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31); + computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC; + } + + void Complete() + { + storedCombinedCRC = BsGetInt32(); + if (storedCombinedCRC != (int)computedCombinedCRC) { + CrcError(); + } + + streamEnd = true; + } + + void BsSetStream(Stream stream) + { + baseStream = stream; + bsLive = 0; + bsBuff = 0; + } + + void FillBuffer() + { + int thech = 0; + + try { + thech = baseStream.ReadByte(); + } catch (Exception) { + CompressedStreamEOF(); + } + + if (thech == -1) { + CompressedStreamEOF(); + } + + bsBuff = (bsBuff << 8) | (thech & 0xFF); + bsLive += 8; + } + + int BsR(int n) + { + while (bsLive < n) { + FillBuffer(); + } + + int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1); + bsLive -= n; + return v; + } + + char BsGetUChar() + { + return (char)BsR(8); + } + + int BsGetIntVS(int numBits) + { + return BsR(numBits); + } + + int BsGetInt32() + { + int result = BsR(8); + result = (result << 8) | BsR(8); + result = (result << 8) | BsR(8); + result = (result << 8) | BsR(8); + return result; + } + + void RecvDecodingTables() + { + char[][] len = new char[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + len[i] = new char[BZip2Constants.MaximumAlphaSize]; + } + + bool[] inUse16 = new bool[16]; + + //--- Receive the mapping table --- + for (int i = 0; i < 16; i++) { + inUse16[i] = (BsR(1) == 1); + } + + for (int i = 0; i < 16; i++) { + if (inUse16[i]) { + for (int j = 0; j < 16; j++) { + inUse[i * 16 + j] = (BsR(1) == 1); + } + } else { + for (int j = 0; j < 16; j++) { + inUse[i * 16 + j] = false; + } + } + } + + MakeMaps(); + int alphaSize = nInUse + 2; + + //--- Now the selectors --- + int nGroups = BsR(3); + int nSelectors = BsR(15); + + for (int i = 0; i < nSelectors; i++) { + int j = 0; + while (BsR(1) == 1) { + j++; + } + selectorMtf[i] = (byte)j; + } + + //--- Undo the MTF values for the selectors. --- + byte[] pos = new byte[BZip2Constants.GroupCount]; + for (int v = 0; v < nGroups; v++) { + pos[v] = (byte)v; + } + + for (int i = 0; i < nSelectors; i++) { + int v = selectorMtf[i]; + byte tmp = pos[v]; + while (v > 0) { + pos[v] = pos[v - 1]; + v--; + } + pos[0] = tmp; + selector[i] = tmp; + } + + //--- Now the coding tables --- + for (int t = 0; t < nGroups; t++) { + int curr = BsR(5); + for (int i = 0; i < alphaSize; i++) { + while (BsR(1) == 1) { + if (BsR(1) == 0) { + curr++; + } else { + curr--; + } + } + len[t][i] = (char)curr; + } + } + + //--- Create the Huffman decoding tables --- + for (int t = 0; t < nGroups; t++) { + int minLen = 32; + int maxLen = 0; + for (int i = 0; i < alphaSize; i++) { + maxLen = Math.Max(maxLen, len[t][i]); + minLen = Math.Min(minLen, len[t][i]); + } + HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize); + minLens[t] = minLen; + } + } + + void GetAndMoveToFrontDecode() + { + byte[] yy = new byte[256]; + int nextSym; + + int limitLast = BZip2Constants.BaseBlockSize * blockSize100k; + origPtr = BsGetIntVS(24); + + RecvDecodingTables(); + int EOB = nInUse+1; + int groupNo = -1; + int groupPos = 0; + + /*-- + Setting up the unzftab entries here is not strictly + necessary, but it does save having to do it later + in a separate pass, and so saves a block's worth of + cache misses. + --*/ + for (int i = 0; i <= 255; i++) { + unzftab[i] = 0; + } + + for (int i = 0; i <= 255; i++) { + yy[i] = (byte)i; + } + + last = -1; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + int zt = selector[groupNo]; + int zn = minLens[zt]; + int zvec = BsR(zn); + int zj; + + while (zvec > limit[zt][zn]) { + if (zn > 20) { // the longest code + throw new BZip2Exception("Bzip data error"); + } + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive-1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) { + throw new BZip2Exception("Bzip data error"); + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + + while (true) { + if (nextSym == EOB) { + break; + } + + if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) { + int s = -1; + int n = 1; + do { + if (nextSym == BZip2Constants.RunA) { + s += (0 + 1) * n; + } else if (nextSym == BZip2Constants.RunB) { + s += (1 + 1) * n; + } + + n <<= 1; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + + while (zvec > limit[zt][zn]) { + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive - 1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + } while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB); + + s++; + byte ch = seqToUnseq[yy[0]]; + unzftab[ch] += s; + + while (s > 0) { + last++; + ll8[last] = ch; + s--; + } + + if (last >= limitLast) { + BlockOverrun(); + } + continue; + } else { + last++; + if (last >= limitLast) { + BlockOverrun(); + } + + byte tmp = yy[nextSym - 1]; + unzftab[seqToUnseq[tmp]]++; + ll8[last] = seqToUnseq[tmp]; + + for (int j = nextSym-1; j > 0; --j) { + yy[j] = yy[j - 1]; + } + yy[0] = tmp; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + while (zvec > limit[zt][zn]) { + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive-1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + continue; + } + } + } + + void SetupBlock() + { + int[] cftab = new int[257]; + + cftab[0] = 0; + Array.Copy(unzftab, 0, cftab, 1, 256); + + for (int i = 1; i <= 256; i++) { + cftab[i] += cftab[i - 1]; + } + + for (int i = 0; i <= last; i++) { + byte ch = ll8[i]; + tt[cftab[ch]] = i; + cftab[ch]++; + } + + cftab = null; + + tPos = tt[origPtr]; + + count = 0; + i2 = 0; + ch2 = 256; /*-- not a char and not EOF --*/ + + if (blockRandomised) { + rNToGo = 0; + rTPos = 0; + SetupRandPartA(); + } else { + SetupNoRandPartA(); + } + } + + void SetupRandPartA() + { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + ch2 ^= (int)((rNToGo == 1) ? 1 : 0); + i2++; + + currentChar = ch2; + currentState = RAND_PART_B_STATE; + mCrc.Update(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + void SetupNoRandPartA() + { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + i2++; + + currentChar = ch2; + currentState = NO_RAND_PART_B_STATE; + mCrc.Update(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + void SetupRandPartB() + { + if (ch2 != chPrev) { + currentState = RAND_PART_A_STATE; + count = 1; + SetupRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + z ^= (byte)((rNToGo == 1) ? 1 : 0); + j2 = 0; + currentState = RAND_PART_C_STATE; + SetupRandPartC(); + } else { + currentState = RAND_PART_A_STATE; + SetupRandPartA(); + } + } + } + + void SetupRandPartC() + { + if (j2 < (int)z) { + currentChar = ch2; + mCrc.Update(ch2); + j2++; + } else { + currentState = RAND_PART_A_STATE; + i2++; + count = 0; + SetupRandPartA(); + } + } + + void SetupNoRandPartB() + { + if (ch2 != chPrev) { + currentState = NO_RAND_PART_A_STATE; + count = 1; + SetupNoRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + currentState = NO_RAND_PART_C_STATE; + j2 = 0; + SetupNoRandPartC(); + } else { + currentState = NO_RAND_PART_A_STATE; + SetupNoRandPartA(); + } + } + } + + void SetupNoRandPartC() + { + if (j2 < (int)z) { + currentChar = ch2; + mCrc.Update(ch2); + j2++; + } else { + currentState = NO_RAND_PART_A_STATE; + i2++; + count = 0; + SetupNoRandPartA(); + } + } + + void SetDecompressStructureSizes(int newSize100k) + { + if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) { + throw new BZip2Exception("Invalid block size"); + } + + blockSize100k = newSize100k; + + if (newSize100k == 0) { + return; + } + + int n = BZip2Constants.BaseBlockSize * newSize100k; + ll8 = new byte[n]; + tt = new int[n]; + } + + static void CompressedStreamEOF() + { + throw new EndOfStreamException("BZip2 input stream end of compressed stream"); + } + + static void BlockOverrun() + { + throw new BZip2Exception("BZip2 input stream block overrun"); + } + + static void BadBlockHeader() + { + throw new BZip2Exception("BZip2 input stream bad block header"); + } + + static void CrcError() + { + throw new BZip2Exception("BZip2 input stream crc error"); + } + + static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize) + { + int pp = 0; + + for (int i = minLen; i <= maxLen; ++i) + { + for (int j = 0; j < alphaSize; ++j) + { + if (length[j] == i) + { + perm[pp] = j; + ++pp; + } + } + } + + for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) + { + baseArray[i] = 0; + } + + for (int i = 0; i < alphaSize; i++) + { + ++baseArray[length[i] + 1]; + } + + for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++) + { + baseArray[i] += baseArray[i - 1]; + } + + for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) + { + limit[i] = 0; + } + + int vec = 0; + + for (int i = minLen; i <= maxLen; i++) + { + vec += (baseArray[i + 1] - baseArray[i]); + limit[i] = vec - 1; + vec <<= 1; + } + + for (int i = minLen + 1; i <= maxLen; i++) + { + baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i]; + } + } + + #region Instance Fields + /*-- + index of the last char in the block, so + the block size == last + 1. + --*/ + int last; + + /*-- + index in zptr[] of original string after sorting. + --*/ + int origPtr; + + /*-- + always: in the range 0 .. 9. + The current block size is 100000 * this number. + --*/ + int blockSize100k; + + bool blockRandomised; + + int bsBuff; + int bsLive; + IChecksum mCrc = new StrangeCRC(); + + bool[] inUse = new bool[256]; + int nInUse; + + byte[] seqToUnseq = new byte[256]; + byte[] unseqToSeq = new byte[256]; + + byte[] selector = new byte[BZip2Constants.MaximumSelectors]; + byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors]; + + int[] tt; + byte[] ll8; + + /*-- + freq table collected to save a pass over the data + during decompression. + --*/ + int[] unzftab = new int[256]; + + int[][] limit = new int[BZip2Constants.GroupCount][]; + int[][] baseArray = new int[BZip2Constants.GroupCount][]; + int[][] perm = new int[BZip2Constants.GroupCount][]; + int[] minLens = new int[BZip2Constants.GroupCount]; + + Stream baseStream; + bool streamEnd; + + int currentChar = -1; + + int currentState = START_BLOCK_STATE; + + int storedBlockCRC, storedCombinedCRC; + int computedBlockCRC; + uint computedCombinedCRC; + + int count, chPrev, ch2; + int tPos; + int rNToGo; + int rTPos; + int i2, j2; + byte z; + bool isStreamOwner = true; + #endregion + } +} +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/OnlineRepair/ZIP/BZip2/BZip2OutputStream.cs b/类库/OnlineRepair/ZIP/BZip2/BZip2OutputStream.cs new file mode 100644 index 0000000..582f7a4 --- /dev/null +++ b/类库/OnlineRepair/ZIP/BZip2/BZip2OutputStream.cs @@ -0,0 +1,1916 @@ +// BZip2OutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + // TODO: Update to BZip2 1.0.1, 1.0.2 + + /// + /// An output stream that compresses into the BZip2 format + /// including file header chars into another stream. + /// + public class BZip2OutputStream : Stream + { + #region Constants + const int SETMASK = (1 << 21); + const int CLEARMASK = (~SETMASK); + const int GREATER_ICOST = 15; + const int LESSER_ICOST = 0; + const int SMALL_THRESH = 20; + const int DEPTH_THRESH = 10; + + /*-- + If you are ever unlucky/improbable enough + to get a stack overflow whilst sorting, + increase the following constant and try + again. In practice I have never seen the + stack go above 27 elems, so the following + limit seems very generous. + --*/ + const int QSORT_STACK_SIZE = 1000; + + /*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. + --*/ + readonly int[] increments = new int[] { + 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 + }; + #endregion + + #region Constructors + /// + /// Construct a default output stream with maximum block size + /// + /// The stream to write BZip data onto. + public BZip2OutputStream(Stream stream) : this(stream, 9) + { + } + + /// + /// Initialise a new instance of the + /// for the specified stream, using the given blocksize. + /// + /// The stream to write compressed data to. + /// The block size to use. + /// + /// Valid block sizes are in the range 1..9, with 1 giving + /// the lowest compression and 9 the highest. + /// + public BZip2OutputStream(Stream stream, int blockSize) + { + BsSetStream(stream); + + workFactor = 50; + if (blockSize > 9) { + blockSize = 9; + } + + if (blockSize < 1) { + blockSize = 1; + } + blockSize100k = blockSize; + AllocateCompressStructures(); + Initialize(); + InitBlock(); + } + #endregion + + #region Destructor + /// + /// Ensures that resources are freed and other cleanup operations + /// are performed when the garbage collector reclaims the BZip2OutputStream. + /// + ~BZip2OutputStream() + { + Dispose(false); + } + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + + #region Stream overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing + /// + public override bool CanWrite { + get { + return baseStream.CanWrite; + } + } + + /// + /// Gets the length in bytes of the stream + /// + public override long Length { + get { + return baseStream.Length; + } + } + + /// + /// Gets or sets the current position of this stream. + /// + public override long Position { + get { + return baseStream.Position; + } + set { + throw new NotSupportedException("BZip2OutputStream position cannot be set"); + } + } + + /// + /// Sets the current position of this stream to the given value. + /// + /// The point relative to the offset from which to being seeking. + /// The reference point from which to begin seeking. + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("BZip2OutputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. + /// + /// The new stream length. + public override void SetLength(long value) + { + throw new NotSupportedException("BZip2OutputStream SetLength not supported"); + } + + /// + /// Read a byte from the stream advancing the position. + /// + /// The byte read cast to an int; -1 if end of stream. + public override int ReadByte() + { + throw new NotSupportedException("BZip2OutputStream ReadByte not supported"); + } + + /// + /// Read a block of bytes + /// + /// The buffer to read into. + /// The offset in the buffer to start storing data at. + /// The maximum number of bytes to read. + /// The total number of bytes read. This might be less than the number of bytes + /// requested if that number of bytes are not currently available, or zero + /// if the end of the stream is reached. + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("BZip2OutputStream Read not supported"); + } + + /// + /// Write a block of bytes to the stream + /// + /// The buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + public override void Write(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( count < 0 ) + { + throw new ArgumentOutOfRangeException("count"); + } + + if ( buffer.Length - offset < count ) + { + throw new ArgumentException("Offset/count out of range"); + } + + for (int i = 0; i < count; ++i) { + WriteByte(buffer[offset + i]); + } + } + + /// + /// Write a byte to the stream. + /// + /// The byte to write to the stream. + public override void WriteByte(byte value) + { + int b = (256 + value) % 256; + if (currentChar != -1) { + if (currentChar == b) { + runLength++; + if (runLength > 254) { + WriteRun(); + currentChar = -1; + runLength = 0; + } + } else { + WriteRun(); + runLength = 1; + currentChar = b; + } + } else { + currentChar = b; + runLength++; + } + } + + /// + /// End the current block and end compression. + /// Close the stream and free any resources + /// + public override void Close() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + void MakeMaps() + { + nInUse = 0; + for (int i = 0; i < 256; i++) { + if (inUse[i]) { + seqToUnseq[nInUse] = (char)i; + unseqToSeq[i] = (char)nInUse; + nInUse++; + } + } + } + + /// + /// Get the number of bytes written to output. + /// + void WriteRun() + { + if (last < allowableBlockSize) { + inUse[currentChar] = true; + for (int i = 0; i < runLength; i++) { + mCrc.Update(currentChar); + } + + switch (runLength) { + case 1: + last++; + block[last + 1] = (byte)currentChar; + break; + case 2: + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + break; + case 3: + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + break; + default: + inUse[runLength - 4] = true; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)(runLength - 4); + break; + } + } else { + EndBlock(); + InitBlock(); + WriteRun(); + } + } + + /// + /// Get the number of bytes written to the output. + /// + public int BytesWritten + { + get { return bytesOut; } + } + + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. +#if NET_1_0 || NET_1_1 || NETCF_1_0 + protected virtual void Dispose(bool disposing) +#else + override protected void Dispose(bool disposing) +#endif + { + try { +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + base.Dispose(disposing); +#endif + if( !disposed_ ) { + disposed_=true; + + if( runLength>0 ) { + WriteRun(); + } + + currentChar=-1; + EndBlock(); + EndCompression(); + Flush(); + } + } + finally { + if ( disposing ) { + if ( IsStreamOwner ) { + baseStream.Close(); + } + } + } + } + + /// + /// Flush output buffers + /// + public override void Flush() + { + baseStream.Flush(); + } + + void Initialize() + { + bytesOut = 0; + nBlocksRandomised = 0; + + /*--- Write header `magic' bytes indicating file-format == huffmanised, + followed by a digit indicating blockSize100k. + ---*/ + + BsPutUChar('B'); + BsPutUChar('Z'); + + BsPutUChar('h'); + BsPutUChar('0' + blockSize100k); + + combinedCRC = 0; + } + + void InitBlock() + { + mCrc.Reset(); + last = -1; + + for (int i = 0; i < 256; i++) { + inUse[i] = false; + } + + /*--- 20 is just a paranoia constant ---*/ + allowableBlockSize = BZip2Constants.BaseBlockSize * blockSize100k - 20; + } + + void EndBlock() + { + if (last < 0) { // dont do anything for empty files, (makes empty files compatible with original Bzip) + return; + } + + blockCRC = unchecked((uint)mCrc.Value); + combinedCRC = (combinedCRC << 1) | (combinedCRC >> 31); + combinedCRC ^= blockCRC; + + /*-- sort the block and establish position of original string --*/ + DoReversibleTransformation(); + + /*-- + A 6-byte block header, the value chosen arbitrarily + as 0x314159265359 :-). A 32 bit value does not really + give a strong enough guarantee that the value will not + appear by chance in the compressed datastream. Worst-case + probability of this event, for a 900k block, is about + 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits. + For a compressed file of size 100Gb -- about 100000 blocks -- + only a 48-bit marker will do. NB: normal compression/ + decompression do *not* rely on these statistical properties. + They are only important when trying to recover blocks from + damaged files. + --*/ + BsPutUChar(0x31); + BsPutUChar(0x41); + BsPutUChar(0x59); + BsPutUChar(0x26); + BsPutUChar(0x53); + BsPutUChar(0x59); + + /*-- Now the block's CRC, so it is in a known place. --*/ + unchecked { + BsPutint((int)blockCRC); + } + + /*-- Now a single bit indicating randomisation. --*/ + if (blockRandomised) { + BsW(1,1); + nBlocksRandomised++; + } else { + BsW(1,0); + } + + /*-- Finally, block's contents proper. --*/ + MoveToFrontCodeAndSend(); + } + + void EndCompression() + { + /*-- + Now another magic 48-bit number, 0x177245385090, to + indicate the end of the last block. (sqrt(pi), if + you want to know. I did want to use e, but it contains + too much repetition -- 27 18 28 18 28 46 -- for me + to feel statistically comfortable. Call me paranoid.) + --*/ + BsPutUChar(0x17); + BsPutUChar(0x72); + BsPutUChar(0x45); + BsPutUChar(0x38); + BsPutUChar(0x50); + BsPutUChar(0x90); + + unchecked { + BsPutint((int)combinedCRC); + } + + BsFinishedWithStream(); + } + + void BsSetStream(Stream stream) + { + baseStream = stream; + bsLive = 0; + bsBuff = 0; + bytesOut = 0; + } + + void BsFinishedWithStream() + { + while (bsLive > 0) + { + int ch = (bsBuff >> 24); + baseStream.WriteByte((byte)ch); // write 8-bit + bsBuff <<= 8; + bsLive -= 8; + bytesOut++; + } + } + + void BsW(int n, int v) + { + while (bsLive >= 8) { + int ch = (bsBuff >> 24); + unchecked{baseStream.WriteByte((byte)ch);} // write 8-bit + bsBuff <<= 8; + bsLive -= 8; + ++bytesOut; + } + bsBuff |= (v << (32 - bsLive - n)); + bsLive += n; + } + + void BsPutUChar(int c) + { + BsW(8, c); + } + + void BsPutint(int u) + { + BsW(8, (u >> 24) & 0xFF); + BsW(8, (u >> 16) & 0xFF); + BsW(8, (u >> 8) & 0xFF); + BsW(8, u & 0xFF); + } + + void BsPutIntVS(int numBits, int c) + { + BsW(numBits, c); + } + + void SendMTFValues() + { + char[][] len = new char[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + len[i] = new char[BZip2Constants.MaximumAlphaSize]; + } + + int gs, ge, totc, bt, bc, iter; + int nSelectors = 0, alphaSize, minLen, maxLen, selCtr; + int nGroups; + + alphaSize = nInUse + 2; + for (int t = 0; t < BZip2Constants.GroupCount; t++) { + for (int v = 0; v < alphaSize; v++) { + len[t][v] = (char)GREATER_ICOST; + } + } + + /*--- Decide how many coding tables to use ---*/ + if (nMTF <= 0) { + Panic(); + } + + if (nMTF < 200) { + nGroups = 2; + } else if (nMTF < 600) { + nGroups = 3; + } else if (nMTF < 1200) { + nGroups = 4; + } else if (nMTF < 2400) { + nGroups = 5; + } else { + nGroups = 6; + } + + /*--- Generate an initial set of coding tables ---*/ + int nPart = nGroups; + int remF = nMTF; + gs = 0; + while (nPart > 0) { + int tFreq = remF / nPart; + int aFreq = 0; + ge = gs - 1; + while (aFreq < tFreq && ge < alphaSize - 1) { + ge++; + aFreq += mtfFreq[ge]; + } + + if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups - nPart) % 2 == 1)) { + aFreq -= mtfFreq[ge]; + ge--; + } + + for (int v = 0; v < alphaSize; v++) { + if (v >= gs && v <= ge) { + len[nPart - 1][v] = (char)LESSER_ICOST; + } else { + len[nPart - 1][v] = (char)GREATER_ICOST; + } + } + + nPart--; + gs = ge + 1; + remF -= aFreq; + } + + int[][] rfreq = new int[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + rfreq[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + int[] fave = new int[BZip2Constants.GroupCount]; + short[] cost = new short[BZip2Constants.GroupCount]; + /*--- + Iterate up to N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZip2Constants.NumberOfIterations; ++iter) { + for (int t = 0; t < nGroups; ++t) { + fave[t] = 0; + } + + for (int t = 0; t < nGroups; ++t) { + for (int v = 0; v < alphaSize; ++v) { + rfreq[t][v] = 0; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (true) { + /*--- Set group start & end marks. --*/ + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.GroupSize - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (int t = 0; t < nGroups; t++) { + cost[t] = 0; + } + + if (nGroups == 6) { + short cost0, cost1, cost2, cost3, cost4, cost5; + cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0; + for (int i = gs; i <= ge; ++i) { + short icv = szptr[i]; + cost0 += (short)len[0][icv]; + cost1 += (short)len[1][icv]; + cost2 += (short)len[2][icv]; + cost3 += (short)len[3][icv]; + cost4 += (short)len[4][icv]; + cost5 += (short)len[5][icv]; + } + cost[0] = cost0; + cost[1] = cost1; + cost[2] = cost2; + cost[3] = cost3; + cost[4] = cost4; + cost[5] = cost5; + } else { + for (int i = gs; i <= ge; ++i) { + short icv = szptr[i]; + for (int t = 0; t < nGroups; t++) { + cost[t] += (short)len[t][icv]; + } + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; + bt = -1; + for (int t = 0; t < nGroups; ++t) { + if (cost[t] < bc) { + bc = cost[t]; + bt = t; + } + } + totc += bc; + fave[bt]++; + selector[nSelectors] = (char)bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + for (int i = gs; i <= ge; ++i) { + ++rfreq[bt][szptr[i]]; + } + + gs = ge+1; + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + for (int t = 0; t < nGroups; ++t) { + HbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20); + } + } + + rfreq = null; + fave = null; + cost = null; + + if (!(nGroups < 8)) { + Panic(); + } + + if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZip2Constants.GroupSize)))) { + Panic(); + } + + /*--- Compute MTF values for the selectors. ---*/ + char[] pos = new char[BZip2Constants.GroupCount]; + char ll_i, tmp2, tmp; + + for (int i = 0; i < nGroups; i++) { + pos[i] = (char)i; + } + + for (int i = 0; i < nSelectors; i++) { + ll_i = selector[i]; + int j = 0; + tmp = pos[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + } + pos[0] = tmp; + selectorMtf[i] = (char)j; + } + + int[][] code = new int[BZip2Constants.GroupCount][]; + + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + code[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + /*--- Assign actual codes for the tables. --*/ + for (int t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (int i = 0; i < alphaSize; i++) { + if (len[t][i] > maxLen) { + maxLen = len[t][i]; + } + if (len[t][i] < minLen) { + minLen = len[t][i]; + } + } + if (maxLen > 20) { + Panic(); + } + if (minLen < 1) { + Panic(); + } + HbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize); + } + + /*--- Transmit the mapping table. ---*/ + bool[] inUse16 = new bool[16]; + for (int i = 0; i < 16; ++i) { + inUse16[i] = false; + for (int j = 0; j < 16; ++j) { + if (inUse[i * 16 + j]) { + inUse16[i] = true; + } + } + } + + for (int i = 0; i < 16; ++i) { + if (inUse16[i]) { + BsW(1,1); + } else { + BsW(1,0); + } + } + + for (int i = 0; i < 16; ++i) { + if (inUse16[i]) { + for (int j = 0; j < 16; ++j) { + if (inUse[i * 16 + j]) { + BsW(1,1); + } else { + BsW(1,0); + } + } + } + } + + /*--- Now the selectors. ---*/ + BsW(3, nGroups); + BsW(15, nSelectors); + for (int i = 0; i < nSelectors; ++i) { + for (int j = 0; j < selectorMtf[i]; ++j) { + BsW(1,1); + } + BsW(1,0); + } + + /*--- Now the coding tables. ---*/ + for (int t = 0; t < nGroups; ++t) { + int curr = len[t][0]; + BsW(5, curr); + for (int i = 0; i < alphaSize; ++i) { + while (curr < len[t][i]) { + BsW(2, 2); + curr++; /* 10 */ + } + while (curr > len[t][i]) { + BsW(2, 3); + curr--; /* 11 */ + } + BsW (1, 0); + } + } + + /*--- And finally, the block data proper ---*/ + selCtr = 0; + gs = 0; + while (true) { + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.GroupSize - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + for (int i = gs; i <= ge; i++) { + BsW(len[selector[selCtr]][szptr[i]], code[selector[selCtr]][szptr[i]]); + } + + gs = ge + 1; + ++selCtr; + } + if (!(selCtr == nSelectors)) { + Panic(); + } + } + + void MoveToFrontCodeAndSend () + { + BsPutIntVS(24, origPtr); + GenerateMTFValues(); + SendMTFValues(); + } + + void SimpleSort(int lo, int hi, int d) + { + int i, j, h, bigN, hp; + int v; + + bigN = hi - lo + 1; + if (bigN < 2) { + return; + } + + hp = 0; + while (increments[hp] < bigN) { + hp++; + } + hp--; + + for (; hp >= 0; hp--) { + h = increments[hp]; + + i = lo + h; + while (true) { + /*-- copy 1 --*/ + if (i > hi) + break; + v = zptr[i]; + j = i; + while (FullGtU(zptr[j-h]+d, v+d)) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) + break; + } + zptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU ( zptr[j-h]+d, v+d )) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU ( zptr[j-h]+d, v+d)) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + if (workDone > workLimit && firstAttempt) { + return; + } + } + } + } + + void Vswap(int p1, int p2, int n ) + { + int temp = 0; + while (n > 0) { + temp = zptr[p1]; + zptr[p1] = zptr[p2]; + zptr[p2] = temp; + p1++; + p2++; + n--; + } + } + + void QSort3(int loSt, int hiSt, int dSt) + { + int unLo, unHi, ltLo, gtHi, med, n, m; + int lo, hi, d; + + StackElement[] stack = new StackElement[QSORT_STACK_SIZE]; + + int sp = 0; + + stack[sp].ll = loSt; + stack[sp].hh = hiSt; + stack[sp].dd = dSt; + sp++; + + while (sp > 0) { + if (sp >= QSORT_STACK_SIZE) { + Panic(); + } + + sp--; + lo = stack[sp].ll; + hi = stack[sp].hh; + d = stack[sp].dd; + + if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) { + SimpleSort(lo, hi, d); + if (workDone > workLimit && firstAttempt) { + return; + } + continue; + } + + med = Med3(block[zptr[lo] + d + 1], + block[zptr[hi ] + d + 1], + block[zptr[(lo + hi) >> 1] + d + 1]); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (true) { + while (true) { + if (unLo > unHi) { + break; + } + n = ((int)block[zptr[unLo]+d + 1]) - med; + if (n == 0) { + int temp = zptr[unLo]; + zptr[unLo] = zptr[ltLo]; + zptr[ltLo] = temp; + ltLo++; + unLo++; + continue; + } + if (n > 0) { + break; + } + unLo++; + } + + while (true) { + if (unLo > unHi) { + break; + } + n = ((int)block[zptr[unHi]+d + 1]) - med; + if (n == 0) { + int temp = zptr[unHi]; + zptr[unHi] = zptr[gtHi]; + zptr[gtHi] = temp; + gtHi--; + unHi--; + continue; + } + if (n < 0) { + break; + } + unHi--; + } + + if (unLo > unHi) { + break; + } + + { + int temp = zptr[unLo]; + zptr[unLo] = zptr[unHi]; + zptr[unHi] = temp; + unLo++; + unHi--; + } + } + + if (gtHi < ltLo) { + stack[sp].ll = lo; + stack[sp].hh = hi; + stack[sp].dd = d+1; + sp++; + continue; + } + + n = ((ltLo-lo) < (unLo-ltLo)) ? (ltLo-lo) : (unLo-ltLo); + Vswap(lo, unLo-n, n); + m = ((hi-gtHi) < (gtHi-unHi)) ? (hi-gtHi) : (gtHi-unHi); + Vswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + stack[sp].ll = lo; + stack[sp].hh = n; + stack[sp].dd = d; + sp++; + + stack[sp].ll = n + 1; + stack[sp].hh = m - 1; + stack[sp].dd = d+1; + sp++; + + stack[sp].ll = m; + stack[sp].hh = hi; + stack[sp].dd = d; + sp++; + } + } + + void MainSort() + { + int i, j, ss, sb; + int[] runningOrder = new int[256]; + int[] copy = new int[256]; + bool[] bigDone = new bool[256]; + int c1, c2; + int numQSorted; + + /*-- + In the various block-sized structures, live data runs + from 0 to last+NUM_OVERSHOOT_BYTES inclusive. First, + set up the overshoot area for block. + --*/ + + // if (verbosity >= 4) fprintf ( stderr, " sort initialise ...\n" ); + for (i = 0; i < BZip2Constants.OvershootBytes; i++) { + block[last + i + 2] = block[(i % (last + 1)) + 1]; + } + for (i = 0; i <= last + BZip2Constants.OvershootBytes; i++) { + quadrant[i] = 0; + } + + block[0] = (byte)(block[last + 1]); + + if (last < 4000) { + /*-- + Use simpleSort(), since the full sorting mechanism + has quite a large constant overhead. + --*/ + for (i = 0; i <= last; i++) { + zptr[i] = i; + } + firstAttempt = false; + workDone = workLimit = 0; + SimpleSort(0, last, 0); + } else { + numQSorted = 0; + for (i = 0; i <= 255; i++) { + bigDone[i] = false; + } + for (i = 0; i <= 65536; i++) { + ftab[i] = 0; + } + + c1 = block[0]; + for (i = 0; i <= last; i++) { + c2 = block[i + 1]; + ftab[(c1 << 8) + c2]++; + c1 = c2; + } + + for (i = 1; i <= 65536; i++) { + ftab[i] += ftab[i - 1]; + } + + c1 = block[1]; + for (i = 0; i < last; i++) { + c2 = block[i + 2]; + j = (c1 << 8) + c2; + c1 = c2; + ftab[j]--; + zptr[ftab[j]] = i; + } + + j = ((block[last + 1]) << 8) + (block[1]); + ftab[j]--; + zptr[ftab[j]] = last; + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + + for (i = 0; i <= 255; i++) { + runningOrder[i] = i; + } + + int vv; + int h = 1; + do { + h = 3 * h + 1; + } while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ((ftab[((runningOrder[j-h])+1) << 8] - ftab[(runningOrder[j-h]) << 8]) > (ftab[((vv)+1) << 8] - ftab[(vv) << 8])) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) { + break; + } + } + runningOrder[j] = vv; + } + } while (h != 1); + + /*-- + The main sorting loop. + --*/ + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + --*/ + ss = runningOrder[i]; + + /*-- + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j]. Hopefully + previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + sb = (ss << 8) + j; + if(!((ftab[sb] & SETMASK) == SETMASK)) { + int lo = ftab[sb] & CLEARMASK; + int hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + QSort3(lo, hi, 2); + numQSorted += (hi - lo + 1); + if (workDone > workLimit && firstAttempt) { + return; + } + } + ftab[sb] |= SETMASK; + } + } + + /*-- + The ss big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + --*/ + bigDone[ss] = true; + + if (i < 255) { + int bbStart = ftab[ss << 8] & CLEARMASK; + int bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + int shifts = 0; + + while ((bbSize >> shifts) > 65534) { + shifts++; + } + + for (j = 0; j < bbSize; j++) { + int a2update = zptr[bbStart + j]; + int qVal = (j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZip2Constants.OvershootBytes) { + quadrant[a2update + last + 1] = qVal; + } + } + + if (!(((bbSize-1) >> shifts) <= 65535)) { + Panic(); + } + } + + /*-- + Now scan this big bucket so as to synthesise the + sorted order for small buckets [t, ss] for all t != ss. + --*/ + for (j = 0; j <= 255; j++) { + copy[j] = ftab[(j << 8) + ss] & CLEARMASK; + } + + for (j = ftab[ss << 8] & CLEARMASK; j < (ftab[(ss+1) << 8] & CLEARMASK); j++) { + c1 = block[zptr[j]]; + if (!bigDone[c1]) { + zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1; + copy[c1] ++; + } + } + + for (j = 0; j <= 255; j++) { + ftab[(j << 8) + ss] |= SETMASK; + } + } + } + } + + void RandomiseBlock() + { + int i; + int rNToGo = 0; + int rTPos = 0; + for (i = 0; i < 256; i++) { + inUse[i] = false; + } + + for (i = 0; i <= last; i++) { + if (rNToGo == 0) { + rNToGo = (int)BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + block[i + 1] ^= (byte)((rNToGo == 1) ? 1 : 0); + // handle 16 bit signed numbers + block[i + 1] &= 0xFF; + + inUse[block[i + 1]] = true; + } + } + + void DoReversibleTransformation() + { + workLimit = workFactor * last; + workDone = 0; + blockRandomised = false; + firstAttempt = true; + + MainSort(); + + if (workDone > workLimit && firstAttempt) { + RandomiseBlock(); + workLimit = workDone = 0; + blockRandomised = true; + firstAttempt = false; + MainSort(); + } + + origPtr = -1; + for (int i = 0; i <= last; i++) { + if (zptr[i] == 0) { + origPtr = i; + break; + } + } + + if (origPtr == -1) { + Panic(); + } + } + + bool FullGtU(int i1, int i2) + { + int k; + byte c1, c2; + int s1, s2; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + k = last + 1; + + do { + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + if (i1 > last) { + i1 -= last; + i1--; + } + if (i2 > last) { + i2 -= last; + i2--; + } + + k -= 4; + ++workDone; + } while (k >= 0); + + return false; + } + + void AllocateCompressStructures() + { + int n = BZip2Constants.BaseBlockSize * blockSize100k; + block = new byte[(n + 1 + BZip2Constants.OvershootBytes)]; + quadrant = new int[(n + BZip2Constants.OvershootBytes)]; + zptr = new int[n]; + ftab = new int[65537]; + + if (block == null || quadrant == null || zptr == null || ftab == null) { + // int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537; + // compressOutOfMemory ( totalDraw, n ); + } + + /* + The back end needs a place to store the MTF values + whilst it calculates the coding tables. We could + put them in the zptr array. However, these values + will fit in a short, so we overlay szptr at the + start of zptr, in the hope of reducing the number + of cache misses induced by the multiple traversals + of the MTF values when calculating coding tables. + Seems to improve compression speed by about 1%. + */ + // szptr = zptr; + + + szptr = new short[2 * n]; + } + + void GenerateMTFValues() + { + char[] yy = new char[256]; + int i, j; + char tmp; + char tmp2; + int zPend; + int wr; + int EOB; + + MakeMaps(); + EOB = nInUse+1; + + for (i = 0; i <= EOB; i++) { + mtfFreq[i] = 0; + } + + wr = 0; + zPend = 0; + for (i = 0; i < nInUse; i++) { + yy[i] = (char) i; + } + + + for (i = 0; i <= last; i++) { + char ll_i; + + ll_i = unseqToSeq[block[zptr[i]]]; + + j = 0; + tmp = yy[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = yy[j]; + yy[j] = tmp2; + } + yy[0] = tmp; + + if (j == 0) { + zPend++; + } else { + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short)BZip2Constants.RunA; + wr++; + mtfFreq[BZip2Constants.RunA]++; + break; + case 1: + szptr[wr] = (short)BZip2Constants.RunB; + wr++; + mtfFreq[BZip2Constants.RunB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + zPend = 0; + } + szptr[wr] = (short)(j + 1); + wr++; + mtfFreq[j + 1]++; + } + } + + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short)BZip2Constants.RunA; + wr++; + mtfFreq[BZip2Constants.RunA]++; + break; + case 1: + szptr[wr] = (short)BZip2Constants.RunB; + wr++; + mtfFreq[BZip2Constants.RunB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + } + + szptr[wr] = (short)EOB; + wr++; + mtfFreq[EOB]++; + + nMTF = wr; + } + + static void Panic() + { + throw new BZip2Exception("BZip2 output stream panic"); + } + + static void HbMakeCodeLengths(char[] len, int[] freq, int alphaSize, int maxLen) + { + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + int nNodes, nHeap, n1, n2, j, k; + bool tooLong; + + int[] heap = new int[BZip2Constants.MaximumAlphaSize + 2]; + int[] weight = new int[BZip2Constants.MaximumAlphaSize * 2]; + int[] parent = new int[BZip2Constants.MaximumAlphaSize * 2]; + + for (int i = 0; i < alphaSize; ++i) + { + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + } + + while (true) + { + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (int i = 1; i <= alphaSize; ++i) + { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + int zz = nHeap; + int tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) + { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + if (!(nHeap < (BZip2Constants.MaximumAlphaSize+2))) + { + Panic(); + } + + while (nHeap > 1) + { + n1 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + int zz = 1; + int yy = 0; + int tmp = heap[zz]; + while (true) + { + yy = zz << 1; + if (yy > nHeap) + { + break; + } + if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) + { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) + { + break; + } + + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + n2 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + + zz = 1; + yy = 0; + tmp = heap[zz]; + while (true) + { + yy = zz << 1; + if (yy > nHeap) + { + break; + } + if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) + { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) + { + break; + } + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + nNodes++; + parent[n1] = parent[n2] = nNodes; + + weight[nNodes] = (int)((weight[n1] & 0xffffff00) + (weight[n2] & 0xffffff00)) | + (int)(1 + (((weight[n1] & 0x000000ff) > (weight[n2] & 0x000000ff)) ? (weight[n1] & 0x000000ff) : (weight[n2] & 0x000000ff))); + + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + + zz = nHeap; + tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) + { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + if (!(nNodes < (BZip2Constants.MaximumAlphaSize * 2))) + { + Panic(); + } + + tooLong = false; + for (int i = 1; i <= alphaSize; ++i) + { + j = 0; + k = i; + while (parent[k] >= 0) + { + k = parent[k]; + j++; + } + len[i - 1] = (char)j; + if (j > maxLen) + { + tooLong = true; + } + } + + if (!tooLong) + { + break; + } + + for (int i = 1; i < alphaSize; ++i) + { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } + } + + static void HbAssignCodes (int[] code, char[] length, int minLen, int maxLen, int alphaSize) + { + int vec = 0; + for (int n = minLen; n <= maxLen; ++n) + { + for (int i = 0; i < alphaSize; ++i) + { + if (length[i] == n) + { + code[i] = vec; + ++vec; + } + } + vec <<= 1; + } + } + + static byte Med3(byte a, byte b, byte c ) + { + byte t; + if (a > b) + { + t = a; + a = b; + b = t; + } + if (b > c) + { + t = b; + b = c; + c = t; + } + if (a > b) + { + b = a; + } + return b; + } + + struct StackElement + { + public int ll; + public int hh; + public int dd; + } + + #region Instance Fields + bool isStreamOwner = true; + + /*-- + index of the last char in the block, so + the block size == last + 1. + --*/ + int last; + + /*-- + index in zptr[] of original string after sorting. + --*/ + int origPtr; + + /*-- + always: in the range 0 .. 9. + The current block size is 100000 * this number. + --*/ + int blockSize100k; + + bool blockRandomised; + + int bytesOut; + int bsBuff; + int bsLive; + IChecksum mCrc = new StrangeCRC(); + + bool[] inUse = new bool[256]; + int nInUse; + + char[] seqToUnseq = new char[256]; + char[] unseqToSeq = new char[256]; + + char[] selector = new char[BZip2Constants.MaximumSelectors]; + char[] selectorMtf = new char[BZip2Constants.MaximumSelectors]; + + byte[] block; + int[] quadrant; + int[] zptr; + short[] szptr; + int[] ftab; + + int nMTF; + + int[] mtfFreq = new int[BZip2Constants.MaximumAlphaSize]; + + /* + * Used when sorting. If too many long comparisons + * happen, we stop sorting, randomise the block + * slightly, and try again. + */ + int workFactor; + int workDone; + int workLimit; + bool firstAttempt; + int nBlocksRandomised; + + int currentChar = -1; + int runLength; + uint blockCRC, combinedCRC; + int allowableBlockSize; + Stream baseStream; + bool disposed_; + #endregion + } +} + +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/OnlineRepair/ZIP/Checksums/Adler32.cs b/类库/OnlineRepair/ZIP/Checksums/Adler32.cs new file mode 100644 index 0000000..6e358bc --- /dev/null +++ b/类库/OnlineRepair/ZIP/Checksums/Adler32.cs @@ -0,0 +1,237 @@ +// Adler32.cs - Computes Adler32 data checksum of a data stream +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Computes Adler32 checksum for a stream of data. An Adler32 + /// checksum is not as reliable as a CRC32 checksum, but a lot faster to + /// compute. + /// + /// The specification for Adler32 may be found in RFC 1950. + /// ZLIB Compressed Data Format Specification version 3.3) + /// + /// + /// From that document: + /// + /// "ADLER32 (Adler-32 checksum) + /// This contains a checksum value of the uncompressed data + /// (excluding any dictionary data) computed according to Adler-32 + /// algorithm. This algorithm is a 32-bit extension and improvement + /// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + /// standard. + /// + /// Adler-32 is composed of two sums accumulated per byte: s1 is + /// the sum of all bytes, s2 is the sum of all s1 values. Both sums + /// are done modulo 65521. s1 is initialized to 1, s2 to zero. The + /// Adler-32 checksum is stored as s2*65536 + s1 in most- + /// significant-byte first (network) order." + /// + /// "8.2. The Adler-32 algorithm + /// + /// The Adler-32 algorithm is much faster than the CRC32 algorithm yet + /// still provides an extremely low probability of undetected errors. + /// + /// The modulo on unsigned long accumulators can be delayed for 5552 + /// bytes, so the modulo operation time is negligible. If the bytes + /// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + /// and order sensitive, unlike the first sum, which is just a + /// checksum. That 65521 is prime is important to avoid a possible + /// large class of two-byte errors that leave the check unchanged. + /// (The Fletcher checksum uses 255, which is not prime and which also + /// makes the Fletcher check insensitive to single byte changes 0 - + /// 255.) + /// + /// The sum s1 is initialized to 1 instead of zero to make the length + /// of the sequence part of s2, so that the length does not have to be + /// checked separately. (Any sequence of zeroes has a Fletcher + /// checksum of zero.)" + /// + /// + /// + public sealed class Adler32 : IChecksum + { + /// + /// largest prime smaller than 65536 + /// + const uint BASE = 65521; + + /// + /// Returns the Adler32 data checksum computed so far. + /// + public long Value { + get { + return checksum; + } + } + + /// + /// Creates a new instance of the Adler32 class. + /// The checksum starts off with a value of 1. + /// + public Adler32() + { + Reset(); + } + + /// + /// Resets the Adler32 checksum to the initial value. + /// + public void Reset() + { + checksum = 1; + } + + /// + /// Updates the checksum with a byte value. + /// + /// + /// The data value to add. The high byte of the int is ignored. + /// + public void Update(int value) + { + // We could make a length 1 byte array and call update again, but I + // would rather not have that overhead + uint s1 = checksum & 0xFFFF; + uint s2 = checksum >> 16; + + s1 = (s1 + ((uint)value & 0xFF)) % BASE; + s2 = (s1 + s2) % BASE; + + checksum = (s2 << 16) + s1; + } + + /// + /// Updates the checksum with an array of bytes. + /// + /// + /// The source of the data to update with. + /// + public void Update(byte[] buffer) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Updates the checksum with the bytes taken from the array. + /// + /// + /// an array of bytes + /// + /// + /// the start of the data used for this update + /// + /// + /// the number of bytes to use for this update + /// + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if (offset < 0) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "cannot be negative"); +#endif + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "cannot be negative"); +#endif + } + + if (offset >= buffer.Length) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "not a valid index into buffer"); +#endif + } + + if (offset + count > buffer.Length) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "exceeds buffer size"); +#endif + } + + //(By Per Bothner) + uint s1 = checksum & 0xFFFF; + uint s2 = checksum >> 16; + + while (count > 0) { + // We can defer the modulo operation: + // s1 maximally grows from 65521 to 65521 + 255 * 3800 + // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 + int n = 3800; + if (n > count) { + n = count; + } + count -= n; + while (--n >= 0) { + s1 = s1 + (uint)(buffer[offset++] & 0xff); + s2 = s2 + s1; + } + s1 %= BASE; + s2 %= BASE; + } + + checksum = (s2 << 16) | s1; + } + + #region Instance Fields + uint checksum; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Checksums/CRC32.cs b/类库/OnlineRepair/ZIP/Checksums/CRC32.cs new file mode 100644 index 0000000..41d5b4b --- /dev/null +++ b/类库/OnlineRepair/ZIP/Checksums/CRC32.cs @@ -0,0 +1,223 @@ +// CRC32.cs - Computes CRC32 data checksum of a data stream +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + /// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + /// + /// Polynomials over GF(2) are represented in binary, one bit per coefficient, + /// with the lowest powers in the most significant bit. Then adding polynomials + /// is just exclusive-or, and multiplying a polynomial by x is a right shift by + /// one. If we call the above polynomial p, and represent a byte as the + /// polynomial q, also with the lowest power in the most significant bit (so the + /// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + /// where a mod b means the remainder after dividing a by b. + /// + /// This calculation is done using the shift-register method of multiplying and + /// taking the remainder. The register is initialized to zero, and for each + /// incoming bit, x^32 is added mod p to the register if the bit is a one (where + /// x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + /// x (which is shifting right by one and adding x^32 mod p if the bit shifted + /// out is a one). We start with the highest power (least significant bit) of + /// q and repeat for all eight bits of q. + /// + /// The table is simply the CRC of all possible eight bit values. This is all + /// the information needed to generate CRC's on data a byte at a time for all + /// combinations of CRC register values and incoming bytes. + /// + public sealed class Crc32 : IChecksum + { + const uint CrcSeed = 0xFFFFFFFF; + + readonly static uint[] CrcTable = new uint[] { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, + 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, + 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, + 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, + 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, + 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, + 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, + 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, + 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, + 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, + 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, + 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, + 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, + 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, + 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, + 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, + 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, + 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, + 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, + 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, + 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, + 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, + 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, + 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, + 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, + 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, + 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, + 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, + 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, + 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, + 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, + 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, + 0x2D02EF8D + }; + + internal static uint ComputeCrc32(uint oldCrc, byte value) + { + return (uint)(Crc32.CrcTable[(oldCrc ^ value) & 0xFF] ^ (oldCrc >> 8)); + } + + /// + /// The crc data checksum so far. + /// + uint crc; + + /// + /// Returns the CRC32 data checksum computed so far. + /// + public long Value { + get { + return (long)crc; + } + set { + crc = (uint)value; + } + } + + /// + /// Resets the CRC32 data checksum as if no update was ever called. + /// + public void Reset() + { + crc = 0; + } + + /// + /// Updates the checksum with the int bval. + /// + /// + /// the byte is taken as the lower 8 bits of value + /// + public void Update(int value) + { + crc ^= CrcSeed; + crc = CrcTable[(crc ^ value) & 0xFF] ^ (crc >> 8); + crc ^= CrcSeed; + } + + /// + /// Updates the checksum with the bytes taken from the array. + /// + /// + /// buffer an array of bytes + /// + public void Update(byte[] buffer) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Adds the byte array to the data checksum. + /// + /// + /// The buffer which contains the data + /// + /// + /// The offset in the buffer where the data starts + /// + /// + /// The number of data bytes to update the CRC with. + /// + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Count cannot be less than zero"); +#endif + } + + if (offset < 0 || offset + count > buffer.Length) { + throw new ArgumentOutOfRangeException("offset"); + } + + crc ^= CrcSeed; + + while (--count >= 0) { + crc = CrcTable[(crc ^ buffer[offset++]) & 0xFF] ^ (crc >> 8); + } + + crc ^= CrcSeed; + } + } +} diff --git a/类库/OnlineRepair/ZIP/Checksums/IChecksum.cs b/类库/OnlineRepair/ZIP/Checksums/IChecksum.cs new file mode 100644 index 0000000..e2679f9 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Checksums/IChecksum.cs @@ -0,0 +1,93 @@ +// IChecksum.cs - Interface to compute a data checksum +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Interface to compute a data checksum used by checked input/output streams. + /// A data checksum can be updated by one byte or with a byte array. After each + /// update the value of the current checksum can be returned by calling + /// getValue. The complete checksum object can also be reset + /// so it can be used again with new data. + /// + public interface IChecksum + { + /// + /// Returns the data checksum computed so far. + /// + long Value + { + get; + } + + /// + /// Resets the data checksum as if no update was ever called. + /// + void Reset(); + + /// + /// Adds one byte to the data checksum. + /// + /// + /// the data value to add. The high byte of the int is ignored. + /// + void Update(int value); + + /// + /// Updates the data checksum with the bytes taken from the array. + /// + /// + /// buffer an array of bytes + /// + void Update(byte[] buffer); + + /// + /// Adds the byte array to the data checksum. + /// + /// + /// The buffer which contains the data + /// + /// + /// The offset in the buffer where the data starts + /// + /// + /// the number of data bytes to add. + /// + void Update(byte[] buffer, int offset, int count); + } +} diff --git a/类库/OnlineRepair/ZIP/Checksums/StrangeCRC.cs b/类库/OnlineRepair/ZIP/Checksums/StrangeCRC.cs new file mode 100644 index 0000000..6ed7679 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Checksums/StrangeCRC.cs @@ -0,0 +1,208 @@ +// StrangeCRC.cs - computes a crc used in the bziplib +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + /// + /// Bzip2 checksum algorithm + /// + public class StrangeCRC : IChecksum + { + readonly static uint[] crc32Table = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + }; + + int globalCrc; + + /// + /// Initialise a default instance of + /// + public StrangeCRC() + { + Reset(); + } + + /// + /// Reset the state of Crc. + /// + public void Reset() + { + globalCrc = -1; + } + + /// + /// Get the current Crc value. + /// + public long Value { + get { + return ~globalCrc; + } + } + + /// + /// Update the Crc value. + /// + /// data update is based on + public void Update(int value) + { + int temp = (globalCrc >> 24) ^ value; + if (temp < 0) { + temp = 256 + temp; + } + globalCrc = unchecked((int)((globalCrc << 8) ^ crc32Table[temp])); + } + + /// + /// Update Crc based on a block of data + /// + /// The buffer containing data to update the crc with. + public void Update(byte[] buffer) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Update Crc based on a portion of a block of data + /// + /// block of data + /// index of first byte to use + /// number of bytes to use + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "cannot be less than zero"); +#endif + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "cannot be less than zero"); +#endif + } + + if ( offset + count > buffer.Length ) + { + throw new ArgumentOutOfRangeException("count"); + } + + for (int i = 0; i < count; ++i) { + Update(buffer[offset++]); + } + } + } +} diff --git a/类库/OnlineRepair/ZIP/Core/FileSystemScanner.cs b/类库/OnlineRepair/ZIP/Core/FileSystemScanner.cs new file mode 100644 index 0000000..4077a45 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Core/FileSystemScanner.cs @@ -0,0 +1,533 @@ +// FileSystemScanner.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +using System; + +namespace ICSharpCode.SharpZipLib.Core +{ + #region EventArgs + /// + /// Event arguments for scanning. + /// + public class ScanEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file or directory name. + public ScanEventArgs(string name) + { + name_ = name; + } + #endregion + + /// + /// The file or directory name for this event. + /// + public string Name + { + get { return name_; } + } + + /// + /// Get set a value indicating if scanning should continue or not. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + #region Instance Fields + string name_; + bool continueRunning_ = true; + #endregion + } + + /// + /// Event arguments during processing of a single file or directory. + /// + public class ProgressEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file or directory name if known. + /// The number of bytes processed so far + /// The total number of bytes to process, 0 if not known + public ProgressEventArgs(string name, long processed, long target) + { + name_ = name; + processed_ = processed; + target_ = target; + } + #endregion + + /// + /// The name for this event if known. + /// + public string Name + { + get { return name_; } + } + + /// + /// Get set a value indicating wether scanning should continue or not. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + /// + /// Get a percentage representing how much of the has been processed + /// + /// 0.0 to 100.0 percent; 0 if target is not known. + public float PercentComplete + { + get + { + float result; + if (target_ <= 0) + { + result = 0; + } + else + { + result = ((float)processed_ / (float)target_) * 100.0f; + } + return result; + } + } + + /// + /// The number of bytes processed so far + /// + public long Processed + { + get { return processed_; } + } + + /// + /// The number of bytes to process. + /// + /// Target may be 0 or negative if the value isnt known. + public long Target + { + get { return target_; } + } + + #region Instance Fields + string name_; + long processed_; + long target_; + bool continueRunning_ = true; + #endregion + } + + /// + /// Event arguments for directories. + /// + public class DirectoryEventArgs : ScanEventArgs + { + #region Constructors + /// + /// Initialize an instance of . + /// + /// The name for this directory. + /// Flag value indicating if any matching files are contained in this directory. + public DirectoryEventArgs(string name, bool hasMatchingFiles) + : base (name) + { + hasMatchingFiles_ = hasMatchingFiles; + } + #endregion + + /// + /// Get a value indicating if the directory contains any matching files or not. + /// + public bool HasMatchingFiles + { + get { return hasMatchingFiles_; } + } + + #region Instance Fields + bool hasMatchingFiles_; + #endregion + } + + /// + /// Arguments passed when scan failures are detected. + /// + public class ScanFailureEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The name to apply. + /// The exception to use. + public ScanFailureEventArgs(string name, Exception e) + { + name_ = name; + exception_ = e; + continueRunning_ = true; + } + #endregion + + /// + /// The applicable name. + /// + public string Name + { + get { return name_; } + } + + /// + /// The applicable exception. + /// + public Exception Exception + { + get { return exception_; } + } + + /// + /// Get / set a value indicating wether scanning should continue. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + #region Instance Fields + string name_; + Exception exception_; + bool continueRunning_; + #endregion + } + + #endregion + + #region Delegates + /// + /// Delegate invoked before starting to process a directory. + /// + public delegate void ProcessDirectoryHandler(object sender, DirectoryEventArgs e); + + /// + /// Delegate invoked before starting to process a file. + /// + /// The source of the event + /// The event arguments. + public delegate void ProcessFileHandler(object sender, ScanEventArgs e); + + /// + /// Delegate invoked during processing of a file or directory + /// + /// The source of the event + /// The event arguments. + public delegate void ProgressHandler(object sender, ProgressEventArgs e); + + /// + /// Delegate invoked when a file has been completely processed. + /// + /// The source of the event + /// The event arguments. + public delegate void CompletedFileHandler(object sender, ScanEventArgs e); + + /// + /// Delegate invoked when a directory failure is detected. + /// + /// The source of the event + /// The event arguments. + public delegate void DirectoryFailureHandler(object sender, ScanFailureEventArgs e); + + /// + /// Delegate invoked when a file failure is detected. + /// + /// The source of the event + /// The event arguments. + public delegate void FileFailureHandler(object sender, ScanFailureEventArgs e); + #endregion + + /// + /// FileSystemScanner provides facilities scanning of files and directories. + /// + public class FileSystemScanner + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file filter to apply when scanning. + public FileSystemScanner(string filter) + { + fileFilter_ = new PathFilter(filter); + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + /// The directory filter to apply. + public FileSystemScanner(string fileFilter, string directoryFilter) + { + fileFilter_ = new PathFilter(fileFilter); + directoryFilter_ = new PathFilter(directoryFilter); + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + public FileSystemScanner(IScanFilter fileFilter) + { + fileFilter_ = fileFilter; + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + /// The directory filter to apply. + public FileSystemScanner(IScanFilter fileFilter, IScanFilter directoryFilter) + { + fileFilter_ = fileFilter; + directoryFilter_ = directoryFilter; + } + #endregion + + #region Delegates + /// + /// Delegate to invoke when a directory is processed. + /// + public ProcessDirectoryHandler ProcessDirectory; + + /// + /// Delegate to invoke when a file is processed. + /// + public ProcessFileHandler ProcessFile; + + /// + /// Delegate to invoke when processing for a file has finished. + /// + public CompletedFileHandler CompletedFile; + + /// + /// Delegate to invoke when a directory failure is detected. + /// + public DirectoryFailureHandler DirectoryFailure; + + /// + /// Delegate to invoke when a file failure is detected. + /// + public FileFailureHandler FileFailure; + #endregion + + /// + /// Raise the DirectoryFailure event. + /// + /// The directory name. + /// The exception detected. + bool OnDirectoryFailure(string directory, Exception e) + { + DirectoryFailureHandler handler = DirectoryFailure; + bool result = (handler != null); + if ( result ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e); + handler(this, args); + alive_ = args.ContinueRunning; + } + return result; + } + + /// + /// Raise the FileFailure event. + /// + /// The file name. + /// The exception detected. + bool OnFileFailure(string file, Exception e) + { + FileFailureHandler handler = FileFailure; + + bool result = (handler != null); + + if ( result ){ + ScanFailureEventArgs args = new ScanFailureEventArgs(file, e); + FileFailure(this, args); + alive_ = args.ContinueRunning; + } + return result; + } + + /// + /// Raise the ProcessFile event. + /// + /// The file name. + void OnProcessFile(string file) + { + ProcessFileHandler handler = ProcessFile; + + if ( handler!= null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Raise the complete file event + /// + /// The file name + void OnCompleteFile(string file) + { + CompletedFileHandler handler = CompletedFile; + + if (handler != null) + { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Raise the ProcessDirectory event. + /// + /// The directory name. + /// Flag indicating if the directory has matching files. + void OnProcessDirectory(string directory, bool hasMatchingFiles) + { + ProcessDirectoryHandler handler = ProcessDirectory; + + if ( handler != null ) { + DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Scan a directory. + /// + /// The base directory to scan. + /// True to recurse subdirectories, false to scan a single directory. + public void Scan(string directory, bool recurse) + { + alive_ = true; + ScanDir(directory, recurse); + } + + void ScanDir(string directory, bool recurse) + { + + try { + string[] names = System.IO.Directory.GetFiles(directory); + bool hasMatch = false; + for (int fileIndex = 0; fileIndex < names.Length; ++fileIndex) { + if ( !fileFilter_.IsMatch(names[fileIndex]) ) { + names[fileIndex] = null; + } else { + hasMatch = true; + } + } + + OnProcessDirectory(directory, hasMatch); + + if ( alive_ && hasMatch ) { + foreach (string fileName in names) { + try { + if ( fileName != null ) { + OnProcessFile(fileName); + if ( !alive_ ) { + break; + } + } + } + catch (Exception e) { + if (!OnFileFailure(fileName, e)) { + throw; + } + } + } + } + } + catch (Exception e) { + if (!OnDirectoryFailure(directory, e)) { + throw; + } + } + + if ( alive_ && recurse ) { + try { + string[] names = System.IO.Directory.GetDirectories(directory); + foreach (string fulldir in names) { + if ((directoryFilter_ == null) || (directoryFilter_.IsMatch(fulldir))) { + ScanDir(fulldir, true); + if ( !alive_ ) { + break; + } + } + } + } + catch (Exception e) { + if (!OnDirectoryFailure(directory, e)) { + throw; + } + } + } + } + + #region Instance Fields + /// + /// The file filter currently in use. + /// + IScanFilter fileFilter_; + /// + /// The directory filter currently in use. + /// + IScanFilter directoryFilter_; + /// + /// Flag indicating if scanning should continue running. + /// + bool alive_; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Core/INameTransform.cs b/类库/OnlineRepair/ZIP/Core/INameTransform.cs new file mode 100644 index 0000000..88c934f --- /dev/null +++ b/类库/OnlineRepair/ZIP/Core/INameTransform.cs @@ -0,0 +1,57 @@ +// INameTransform.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// INameTransform defines how file system names are transformed for use with archives, or vice versa. + /// + public interface INameTransform + { + /// + /// Given a file name determine the transformed value. + /// + /// The name to transform. + /// The transformed file name. + string TransformFile(string name); + + /// + /// Given a directory name determine the transformed value. + /// + /// The name to transform. + /// The transformed directory name + string TransformDirectory(string name); + } +} diff --git a/类库/OnlineRepair/ZIP/Core/IScanFilter.cs b/类库/OnlineRepair/ZIP/Core/IScanFilter.cs new file mode 100644 index 0000000..64c99a8 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Core/IScanFilter.cs @@ -0,0 +1,50 @@ +// IScanFilter.cs +// +// Copyright 2006 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// Scanning filters support filtering of names. + /// + public interface IScanFilter + { + /// + /// Test a name to see if it 'matches' the filter. + /// + /// The name to test. + /// Returns true if the name matches the filter, false if it does not match. + bool IsMatch(string name); + } +} diff --git a/类库/OnlineRepair/ZIP/Core/NameFilter.cs b/类库/OnlineRepair/ZIP/Core/NameFilter.cs new file mode 100644 index 0000000..eea8fbe --- /dev/null +++ b/类库/OnlineRepair/ZIP/Core/NameFilter.cs @@ -0,0 +1,290 @@ +// NameFilter.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2010-03-03 Z-1654 Fixed bug where escape characters were excluded in SplitQuoted() + +using System; +using System.Collections; +using System.Text; +using System.Text.RegularExpressions; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// NameFilter is a string matching class which allows for both positive and negative + /// matching. + /// A filter is a sequence of independant regular expressions separated by semi-colons ';'. + /// To include a semi-colon it may be quoted as in \;. Each expression can be prefixed by a plus '+' sign or + /// a minus '-' sign to denote the expression is intended to include or exclude names. + /// If neither a plus or minus sign is found include is the default. + /// A given name is tested for inclusion before checking exclusions. Only names matching an include spec + /// and not matching an exclude spec are deemed to match the filter. + /// An empty filter matches any name. + /// + /// The following expression includes all name ending in '.dat' with the exception of 'dummy.dat' + /// "+\.dat$;-^dummy\.dat$" + /// + public class NameFilter : IScanFilter + { + #region Constructors + /// + /// Construct an instance based on the filter expression passed + /// + /// The filter expression. + public NameFilter(string filter) + { + filter_ = filter; + inclusions_ = new ArrayList(); + exclusions_ = new ArrayList(); + Compile(); + } + #endregion + + /// + /// Test a string to see if it is a valid regular expression. + /// + /// The expression to test. + /// True if expression is a valid false otherwise. + public static bool IsValidExpression(string expression) + { + bool result = true; + try { + Regex exp = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + catch (ArgumentException) { + result = false; + } + return result; + } + + /// + /// Test an expression to see if it is valid as a filter. + /// + /// The filter expression to test. + /// True if the expression is valid, false otherwise. + public static bool IsValidFilterExpression(string toTest) + { + if ( toTest == null ) { + throw new ArgumentNullException("toTest"); + } + + bool result = true; + + try { + string[] items = SplitQuoted(toTest); + for (int i = 0; i < items.Length; ++i) { + if ((items[i] != null) && (items[i].Length > 0)) { + string toCompile; + + if (items[i][0] == '+') { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else if (items[i][0] == '-') { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else { + toCompile = items[i]; + } + + Regex testRegex = new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + } + } + catch (ArgumentException) { + result = false; + } + + return result; + } + + /// + /// Split a string into its component pieces + /// + /// The original string + /// Returns an array of values containing the individual filter elements. + public static string[] SplitQuoted(string original) + { + char escape = '\\'; + char[] separators = { ';' }; + + ArrayList result = new ArrayList(); + + if ((original != null) && (original.Length > 0)) { + int endIndex = -1; + StringBuilder b = new StringBuilder(); + + while (endIndex < original.Length) { + endIndex += 1; + if (endIndex >= original.Length) { + result.Add(b.ToString()); + } + else if (original[endIndex] == escape) { + endIndex += 1; + if (endIndex >= original.Length) { +#if NETCF_1_0 + throw new ArgumentException("Missing terminating escape character"); +#else + throw new ArgumentException("Missing terminating escape character", "original"); +#endif + } + // include escape if this is not an escaped separator + if (Array.IndexOf(separators, original[endIndex]) < 0) + b.Append(escape); + + b.Append(original[endIndex]); + } + else { + if (Array.IndexOf(separators, original[endIndex]) >= 0) { + result.Add(b.ToString()); + b.Length = 0; + } + else { + b.Append(original[endIndex]); + } + } + } + } + + return (string[])result.ToArray(typeof(string)); + } + + /// + /// Convert this filter to its string equivalent. + /// + /// The string equivalent for this filter. + public override string ToString() + { + return filter_; + } + + /// + /// Test a value to see if it is included by the filter. + /// + /// The value to test. + /// True if the value is included, false otherwise. + public bool IsIncluded(string name) + { + bool result = false; + if ( inclusions_.Count == 0 ) { + result = true; + } + else { + foreach ( Regex r in inclusions_ ) { + if ( r.IsMatch(name) ) { + result = true; + break; + } + } + } + return result; + } + + /// + /// Test a value to see if it is excluded by the filter. + /// + /// The value to test. + /// True if the value is excluded, false otherwise. + public bool IsExcluded(string name) + { + bool result = false; + foreach ( Regex r in exclusions_ ) { + if ( r.IsMatch(name) ) { + result = true; + break; + } + } + return result; + } + + #region IScanFilter Members + /// + /// Test a value to see if it matches the filter. + /// + /// The value to test. + /// True if the value matches, false otherwise. + public bool IsMatch(string name) + { + return (IsIncluded(name) && !IsExcluded(name)); + } + #endregion + + /// + /// Compile this filter. + /// + void Compile() + { + // TODO: Check to see if combining RE's makes it faster/smaller. + // simple scheme would be to have one RE for inclusion and one for exclusion. + if ( filter_ == null ) { + return; + } + + string[] items = SplitQuoted(filter_); + for ( int i = 0; i < items.Length; ++i ) { + if ( (items[i] != null) && (items[i].Length > 0) ) { + bool include = (items[i][0] != '-'); + string toCompile; + + if ( items[i][0] == '+' ) { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else if ( items[i][0] == '-' ) { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else { + toCompile = items[i]; + } + + // NOTE: Regular expressions can fail to compile here for a number of reasons that cause an exception + // these are left unhandled here as the caller is responsible for ensuring all is valid. + // several functions IsValidFilterExpression and IsValidExpression are provided for such checking + if ( include ) { + inclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)); + } + else { + exclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)); + } + } + } + } + + #region Instance Fields + string filter_; + ArrayList inclusions_; + ArrayList exclusions_; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Core/PathFilter.cs b/类库/OnlineRepair/ZIP/Core/PathFilter.cs new file mode 100644 index 0000000..03b8ff3 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Core/PathFilter.cs @@ -0,0 +1,334 @@ +// PathFilter.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// PathFilter filters directories and files using a form of regular expressions + /// by full path name. + /// See NameFilter for more detail on filtering. + /// + public class PathFilter : IScanFilter + { + #region Constructors + /// + /// Initialise a new instance of . + /// + /// The filter expression to apply. + public PathFilter(string filter) + { + nameFilter_ = new NameFilter(filter); + } + #endregion + + #region IScanFilter Members + /// + /// Test a name to see if it matches the filter. + /// + /// The name to test. + /// True if the name matches, false otherwise. + /// is used to get the full path before matching. + public virtual bool IsMatch(string name) + { + bool result = false; + + if ( name != null ) { + string cooked = (name.Length > 0) ? Path.GetFullPath(name) : ""; + result = nameFilter_.IsMatch(cooked); + } + return result; + } + #endregion + + #region Instance Fields + NameFilter nameFilter_; + #endregion + } + + /// + /// ExtendedPathFilter filters based on name, file size, and the last write time of the file. + /// + /// Provides an example of how to customise filtering. + public class ExtendedPathFilter : PathFilter + { + #region Constructors + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + public ExtendedPathFilter(string filter, + long minSize, long maxSize) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + } + + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum to include. + /// The maximum to include. + public ExtendedPathFilter(string filter, + DateTime minDate, DateTime maxDate) + : base(filter) + { + MinDate = minDate; + MaxDate = maxDate; + } + + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + /// The minimum to include. + /// The maximum to include. + public ExtendedPathFilter(string filter, + long minSize, long maxSize, + DateTime minDate, DateTime maxDate) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + MinDate = minDate; + MaxDate = maxDate; + } + #endregion + + #region IScanFilter Members + /// + /// Test a filename to see if it matches the filter. + /// + /// The filename to test. + /// True if the filter matches, false otherwise. + /// The doesnt exist + public override bool IsMatch(string name) + { + bool result = base.IsMatch(name); + + if ( result ) { + FileInfo fileInfo = new FileInfo(name); + result = + (MinSize <= fileInfo.Length) && + (MaxSize >= fileInfo.Length) && + (MinDate <= fileInfo.LastWriteTime) && + (MaxDate >= fileInfo.LastWriteTime) + ; + } + return result; + } + #endregion + + #region Properties + /// + /// Get/set the minimum size/length for a file that will match this filter. + /// + /// The default value is zero. + /// value is less than zero; greater than + public long MinSize + { + get { return minSize_; } + set + { + if ( (value < 0) || (maxSize_ < value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + minSize_ = value; + } + } + + /// + /// Get/set the maximum size/length for a file that will match this filter. + /// + /// The default value is + /// value is less than zero or less than + public long MaxSize + { + get { return maxSize_; } + set + { + if ( (value < 0) || (minSize_ > value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + maxSize_ = value; + } + } + + /// + /// Get/set the minimum value that will match for this filter. + /// + /// Files with a LastWrite time less than this value are excluded by the filter. + public DateTime MinDate + { + get + { + return minDate_; + } + + set + { + if ( value > maxDate_ ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Exceeds MaxDate"); +#endif + } + + minDate_ = value; + } + } + + /// + /// Get/set the maximum value that will match for this filter. + /// + /// Files with a LastWrite time greater than this value are excluded by the filter. + public DateTime MaxDate + { + get + { + return maxDate_; + } + + set + { + if ( minDate_ > value ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Exceeds MinDate"); +#endif + } + + maxDate_ = value; + } + } + #endregion + + #region Instance Fields + long minSize_; + long maxSize_ = long.MaxValue; + DateTime minDate_ = DateTime.MinValue; + DateTime maxDate_ = DateTime.MaxValue; + #endregion + } + + /// + /// NameAndSizeFilter filters based on name and file size. + /// + /// A sample showing how filters might be extended. + [Obsolete("Use ExtendedPathFilter instead")] + public class NameAndSizeFilter : PathFilter + { + + /// + /// Initialise a new instance of NameAndSizeFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + public NameAndSizeFilter(string filter, long minSize, long maxSize) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + } + + /// + /// Test a filename to see if it matches the filter. + /// + /// The filename to test. + /// True if the filter matches, false otherwise. + public override bool IsMatch(string name) + { + bool result = base.IsMatch(name); + + if ( result ) { + FileInfo fileInfo = new FileInfo(name); + long length = fileInfo.Length; + result = + (MinSize <= length) && + (MaxSize >= length); + } + return result; + } + + /// + /// Get/set the minimum size for a file that will match this filter. + /// + public long MinSize + { + get { return minSize_; } + set { + if ( (value < 0) || (maxSize_ < value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + minSize_ = value; + } + } + + /// + /// Get/set the maximum size for a file that will match this filter. + /// + public long MaxSize + { + get { return maxSize_; } + set + { + if ( (value < 0) || (minSize_ > value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + maxSize_ = value; + } + } + + #region Instance Fields + long minSize_; + long maxSize_ = long.MaxValue; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Core/StreamUtils.cs b/类库/OnlineRepair/ZIP/Core/StreamUtils.cs new file mode 100644 index 0000000..7abdce8 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Core/StreamUtils.cs @@ -0,0 +1,246 @@ +// StreamUtils.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// Provides simple " utilities. + /// + public sealed class StreamUtils + { + /// + /// Read from a ensuring all the required data is read. + /// + /// The stream to read. + /// The buffer to fill. + /// + static public void ReadFully(Stream stream, byte[] buffer) + { + ReadFully(stream, buffer, 0, buffer.Length); + } + + /// + /// Read from a " ensuring all the required data is read. + /// + /// The stream to read data from. + /// The buffer to store data in. + /// The offset at which to begin storing data. + /// The number of bytes of data to store. + /// Required parameter is null + /// and or are invalid. + /// End of stream is encountered before all the data has been read. + static public void ReadFully(Stream stream, byte[] buffer, int offset, int count) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + // Offset can equal length when buffer and count are 0. + if ( (offset < 0) || (offset > buffer.Length) ) { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( (count < 0) || (offset + count > buffer.Length) ) { + throw new ArgumentOutOfRangeException("count"); + } + + while ( count > 0 ) { + int readCount = stream.Read(buffer, offset, count); + if ( readCount <= 0 ) { + throw new EndOfStreamException(); + } + offset += readCount; + count -= readCount; + } + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + static public void Copy(Stream source, Stream destination, byte[] buffer) + { + if (source == null) { + throw new ArgumentNullException("source"); + } + + if (destination == null) { + throw new ArgumentNullException("destination"); + } + + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + // Ensure a reasonable size of buffer is used without being prohibitive. + if (buffer.Length < 128) { + throw new ArgumentException("Buffer is too small", "buffer"); + } + + bool copying = true; + + while (copying) { + int bytesRead = source.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) { + destination.Write(buffer, 0, bytesRead); + } + else { + destination.Flush(); + copying = false; + } + } + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + /// The progress handler delegate to use. + /// The minimum between progress updates. + /// The source for this event. + /// The name to use with the event. + /// This form is specialised for use within #Zip to support events during archive operations. + static public void Copy(Stream source, Stream destination, + byte[] buffer, ProgressHandler progressHandler, TimeSpan updateInterval, object sender, string name) + { + Copy(source, destination, buffer, progressHandler, updateInterval, sender, name, -1); + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + /// The progress handler delegate to use. + /// The minimum between progress updates. + /// The source for this event. + /// The name to use with the event. + /// A predetermined fixed target value to use with progress updates. + /// If the value is negative the target is calculated by looking at the stream. + /// This form is specialised for use within #Zip to support events during archive operations. + static public void Copy(Stream source, Stream destination, + byte[] buffer, + ProgressHandler progressHandler, TimeSpan updateInterval, + object sender, string name, long fixedTarget) + { + if (source == null) { + throw new ArgumentNullException("source"); + } + + if (destination == null) { + throw new ArgumentNullException("destination"); + } + + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + // Ensure a reasonable size of buffer is used without being prohibitive. + if (buffer.Length < 128) { + throw new ArgumentException("Buffer is too small", "buffer"); + } + + if (progressHandler == null) { + throw new ArgumentNullException("progressHandler"); + } + + bool copying = true; + + DateTime marker = DateTime.Now; + long processed = 0; + long target = 0; + + if (fixedTarget >= 0) { + target = fixedTarget; + } + else if (source.CanSeek) { + target = source.Length - source.Position; + } + + // Always fire 0% progress.. + ProgressEventArgs args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + + bool progressFired = true; + + while (copying) { + int bytesRead = source.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) { + processed += bytesRead; + progressFired = false; + destination.Write(buffer, 0, bytesRead); + } + else { + destination.Flush(); + copying = false; + } + + if (DateTime.Now - marker > updateInterval) { + progressFired = true; + marker = DateTime.Now; + args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + + copying = args.ContinueRunning; + } + } + + if (!progressFired) { + args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + } + } + + /// + /// Initialise an instance of + /// + private StreamUtils() + { + // Do nothing. + } + } +} diff --git a/类库/OnlineRepair/ZIP/Core/WindowsPathUtils.cs b/类库/OnlineRepair/ZIP/Core/WindowsPathUtils.cs new file mode 100644 index 0000000..2091945 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Core/WindowsPathUtils.cs @@ -0,0 +1,94 @@ +// WindowsPathUtils.cs +// +// Copyright 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// WindowsPathUtils provides simple utilities for handling windows paths. + /// + public abstract class WindowsPathUtils + { + /// + /// Initializes a new instance of the class. + /// + internal WindowsPathUtils() + { + } + + /// + /// Remove any path root present in the path + /// + /// A containing path information. + /// The path with the root removed if it was present; path otherwise. + /// Unlike the class the path isnt otherwise checked for validity. + public static string DropPathRoot(string path) + { + string result = path; + + if ( (path != null) && (path.Length > 0) ) { + if ((path[0] == '\\') || (path[0] == '/')) { + // UNC name ? + if ((path.Length > 1) && ((path[1] == '\\') || (path[1] == '/'))) { + int index = 2; + int elements = 2; + + // Scan for two separate elements \\machine\share\restofpath + while ((index <= path.Length) && + (((path[index] != '\\') && (path[index] != '/')) || (--elements > 0))) { + index++; + } + + index++; + + if (index < path.Length) { + result = path.Substring(index); + } + else { + result = ""; + } + } + } + else if ((path.Length > 1) && (path[1] == ':')) { + int dropCount = 2; + if ((path.Length > 2) && ((path[2] == '\\') || (path[2] == '/'))) { + dropCount = 3; + } + result = result.Remove(0, dropCount); + } + } + return result; + } + } +} diff --git a/类库/OnlineRepair/ZIP/Encryption/PkzipClassic.cs b/类库/OnlineRepair/ZIP/Encryption/PkzipClassic.cs new file mode 100644 index 0000000..7bed67a --- /dev/null +++ b/类库/OnlineRepair/ZIP/Encryption/PkzipClassic.cs @@ -0,0 +1,498 @@ +// +// PkzipClassic encryption +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + + +#if !NETCF_1_0 + +using System; +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.Encryption +{ + /// + /// PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives. + /// While it has been superceded by more recent and more powerful algorithms, its still in use and + /// is viable for preventing casual snooping + /// + public abstract class PkzipClassic : SymmetricAlgorithm + { + /// + /// Generates new encryption keys based on given seed + /// + /// The seed value to initialise keys with. + /// A new key value. + static public byte[] GenerateKeys(byte[] seed) + { + if ( seed == null ) { + throw new ArgumentNullException("seed"); + } + + if ( seed.Length == 0 ) { + throw new ArgumentException("Length is zero", "seed"); + } + + uint[] newKeys = new uint[] { + 0x12345678, + 0x23456789, + 0x34567890 + }; + + for (int i = 0; i < seed.Length; ++i) { + newKeys[0] = Crc32.ComputeCrc32(newKeys[0], seed[i]); + newKeys[1] = newKeys[1] + (byte)newKeys[0]; + newKeys[1] = newKeys[1] * 134775813 + 1; + newKeys[2] = Crc32.ComputeCrc32(newKeys[2], (byte)(newKeys[1] >> 24)); + } + + byte[] result = new byte[12]; + result[0] = (byte)(newKeys[0] & 0xff); + result[1] = (byte)((newKeys[0] >> 8) & 0xff); + result[2] = (byte)((newKeys[0] >> 16) & 0xff); + result[3] = (byte)((newKeys[0] >> 24) & 0xff); + result[4] = (byte)(newKeys[1] & 0xff); + result[5] = (byte)((newKeys[1] >> 8) & 0xff); + result[6] = (byte)((newKeys[1] >> 16) & 0xff); + result[7] = (byte)((newKeys[1] >> 24) & 0xff); + result[8] = (byte)(newKeys[2] & 0xff); + result[9] = (byte)((newKeys[2] >> 8) & 0xff); + result[10] = (byte)((newKeys[2] >> 16) & 0xff); + result[11] = (byte)((newKeys[2] >> 24) & 0xff); + return result; + } + } + + /// + /// PkzipClassicCryptoBase provides the low level facilities for encryption + /// and decryption using the PkzipClassic algorithm. + /// + class PkzipClassicCryptoBase + { + /// + /// Transform a single byte + /// + /// + /// The transformed value + /// + protected byte TransformByte() + { + uint temp = ((keys[2] & 0xFFFF) | 2); + return (byte)((temp * (temp ^ 1)) >> 8); + } + + /// + /// Set the key schedule for encryption/decryption. + /// + /// The data use to set the keys from. + protected void SetKeys(byte[] keyData) + { + if ( keyData == null ) { + throw new ArgumentNullException("keyData"); + } + + if ( keyData.Length != 12 ) { + throw new InvalidOperationException("Key length is not valid"); + } + + keys = new uint[3]; + keys[0] = (uint)((keyData[3] << 24) | (keyData[2] << 16) | (keyData[1] << 8) | keyData[0]); + keys[1] = (uint)((keyData[7] << 24) | (keyData[6] << 16) | (keyData[5] << 8) | keyData[4]); + keys[2] = (uint)((keyData[11] << 24) | (keyData[10] << 16) | (keyData[9] << 8) | keyData[8]); + } + + /// + /// Update encryption keys + /// + protected void UpdateKeys(byte ch) + { + keys[0] = Crc32.ComputeCrc32(keys[0], ch); + keys[1] = keys[1] + (byte)keys[0]; + keys[1] = keys[1] * 134775813 + 1; + keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24)); + } + + /// + /// Reset the internal state. + /// + protected void Reset() + { + keys[0] = 0; + keys[1] = 0; + keys[2] = 0; + } + + #region Instance Fields + uint[] keys; + #endregion + } + + /// + /// PkzipClassic CryptoTransform for encryption. + /// + class PkzipClassicEncryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform + { + /// + /// Initialise a new instance of + /// + /// The key block to use. + internal PkzipClassicEncryptCryptoTransform(byte[] keyBlock) + { + SetKeys(keyBlock); + } + + #region ICryptoTransform Members + + /// + /// Transforms the specified region of the specified byte array. + /// + /// The input for which to compute the transform. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + /// The computed transform. + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + byte[] result = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, result, 0); + return result; + } + + /// + /// Transforms the specified region of the input byte array and copies + /// the resulting transform to the specified region of the output byte array. + /// + /// The input for which to compute the transform. + /// The offset into the input byte array from which to begin using data. + /// The number of bytes in the input byte array to use as data. + /// The output to which to write the transform. + /// The offset into the output byte array from which to begin writing data. + /// The number of bytes written. + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + for (int i = inputOffset; i < inputOffset + inputCount; ++i) { + byte oldbyte = inputBuffer[i]; + outputBuffer[outputOffset++] = (byte)(inputBuffer[i] ^ TransformByte()); + UpdateKeys(oldbyte); + } + return inputCount; + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform + { + get { + return true; + } + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks + { + get { + return true; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Cleanup internal state. + /// + public void Dispose() + { + Reset(); + } + + #endregion + } + + + /// + /// PkzipClassic CryptoTransform for decryption. + /// + class PkzipClassicDecryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform + { + /// + /// Initialise a new instance of . + /// + /// The key block to decrypt with. + internal PkzipClassicDecryptCryptoTransform(byte[] keyBlock) + { + SetKeys(keyBlock); + } + + #region ICryptoTransform Members + + /// + /// Transforms the specified region of the specified byte array. + /// + /// The input for which to compute the transform. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + /// The computed transform. + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + byte[] result = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, result, 0); + return result; + } + + /// + /// Transforms the specified region of the input byte array and copies + /// the resulting transform to the specified region of the output byte array. + /// + /// The input for which to compute the transform. + /// The offset into the input byte array from which to begin using data. + /// The number of bytes in the input byte array to use as data. + /// The output to which to write the transform. + /// The offset into the output byte array from which to begin writing data. + /// The number of bytes written. + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + for (int i = inputOffset; i < inputOffset + inputCount; ++i) { + byte newByte = (byte)(inputBuffer[i] ^ TransformByte()); + outputBuffer[outputOffset++] = newByte; + UpdateKeys(newByte); + } + return inputCount; + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform + { + get { + return true; + } + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks + { + get { + return true; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Cleanup internal state. + /// + public void Dispose() + { + Reset(); + } + + #endregion + } + + /// + /// Defines a wrapper object to access the Pkzip algorithm. + /// This class cannot be inherited. + /// + public sealed class PkzipClassicManaged : PkzipClassic + { + /// + /// Get / set the applicable block size in bits. + /// + /// The only valid block size is 8. + public override int BlockSize + { + get { + return 8; + } + + set { + if (value != 8) { + throw new CryptographicException("Block size is invalid"); + } + } + } + + /// + /// Get an array of legal key sizes. + /// + public override KeySizes[] LegalKeySizes + { + get { + KeySizes[] keySizes = new KeySizes[1]; + keySizes[0] = new KeySizes(12 * 8, 12 * 8, 0); + return keySizes; + } + } + + /// + /// Generate an initial vector. + /// + public override void GenerateIV() + { + // Do nothing. + } + + /// + /// Get an array of legal block sizes. + /// + public override KeySizes[] LegalBlockSizes + { + get { + KeySizes[] keySizes = new KeySizes[1]; + keySizes[0] = new KeySizes(1 * 8, 1 * 8, 0); + return keySizes; + } + } + + /// + /// Get / set the key value applicable. + /// + public override byte[] Key + { + get { + if ( key_ == null ) { + GenerateKey(); + } + + return (byte[]) key_.Clone(); + } + + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + + if ( value.Length != 12 ) { + throw new CryptographicException("Key size is illegal"); + } + + key_ = (byte[]) value.Clone(); + } + } + + /// + /// Generate a new random key. + /// + public override void GenerateKey() + { + key_ = new byte[12]; + Random rnd = new Random(); + rnd.NextBytes(key_); + } + + /// + /// Create an encryptor. + /// + /// The key to use for this encryptor. + /// Initialisation vector for the new encryptor. + /// Returns a new PkzipClassic encryptor + public override ICryptoTransform CreateEncryptor( + byte[] rgbKey, + byte[] rgbIV) + { + key_ = rgbKey; + return new PkzipClassicEncryptCryptoTransform(Key); + } + + /// + /// Create a decryptor. + /// + /// Keys to use for this new decryptor. + /// Initialisation vector for the new decryptor. + /// Returns a new decryptor. + public override ICryptoTransform CreateDecryptor( + byte[] rgbKey, + byte[] rgbIV) + { + key_ = rgbKey; + return new PkzipClassicDecryptCryptoTransform(Key); + } + + #region Instance Fields + byte[] key_; + #endregion + } +} +#endif diff --git a/类库/OnlineRepair/ZIP/Encryption/ZipAESStream.cs b/类库/OnlineRepair/ZIP/Encryption/ZipAESStream.cs new file mode 100644 index 0000000..d57dc34 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Encryption/ZipAESStream.cs @@ -0,0 +1,170 @@ +// +// ZipAESStream.cs +// +// Copyright 2009 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + +#if !NET_1_1 && !NETCF_2_0 + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace ICSharpCode.SharpZipLib.Encryption { + + // Based on information from http://www.winzip.com/aes_info.htm + // and http://www.gladman.me.uk/cryptography_technology/fileencrypt/ + + /// + /// Encrypts and decrypts AES ZIP + /// + internal class ZipAESStream : CryptoStream { + + /// + /// Constructor + /// + /// The stream on which to perform the cryptographic transformation. + /// Instance of ZipAESTransform + /// Read or Write + public ZipAESStream(Stream stream, ZipAESTransform transform, CryptoStreamMode mode) + : base(stream, transform, mode) { + + _stream = stream; + _transform = transform; + _slideBuffer = new byte[1024]; + + _blockAndAuth = CRYPTO_BLOCK_SIZE + AUTH_CODE_LENGTH; + + // mode: + // CryptoStreamMode.Read means we read from "stream" and pass decrypted to our Read() method. + // Write bypasses this stream and uses the Transform directly. + if (mode != CryptoStreamMode.Read) { + throw new Exception("ZipAESStream only for read"); + } + } + + // The final n bytes of the AES stream contain the Auth Code. + private const int AUTH_CODE_LENGTH = 10; + + private Stream _stream; + private ZipAESTransform _transform; + private byte[] _slideBuffer; + private int _slideBufStartPos; + private int _slideBufFreePos; + // Blocksize is always 16 here, even for AES-256 which has transform.InputBlockSize of 32. + private const int CRYPTO_BLOCK_SIZE = 16; + private int _blockAndAuth; + + /// + /// Reads a sequence of bytes from the current CryptoStream into buffer, + /// and advances the position within the stream by the number of bytes read. + /// + public override int Read(byte[] outBuffer, int offset, int count) { + int nBytes = 0; + while (nBytes < count) { + // Calculate buffer quantities vs read-ahead size, and check for sufficient free space + int byteCount = _slideBufFreePos - _slideBufStartPos; + + // Need to handle final block and Auth Code specially, but don't know total data length. + // Maintain a read-ahead equal to the length of (crypto block + Auth Code). + // When that runs out we can detect these final sections. + int lengthToRead = _blockAndAuth - byteCount; + if (_slideBuffer.Length - _slideBufFreePos < lengthToRead) { + // Shift the data to the beginning of the buffer + int iTo = 0; + for (int iFrom = _slideBufStartPos; iFrom < _slideBufFreePos; iFrom++, iTo++) { + _slideBuffer[iTo] = _slideBuffer[iFrom]; + } + _slideBufFreePos -= _slideBufStartPos; // Note the -= + _slideBufStartPos = 0; + } + int obtained = _stream.Read(_slideBuffer, _slideBufFreePos, lengthToRead); + _slideBufFreePos += obtained; + + // Recalculate how much data we now have + byteCount = _slideBufFreePos - _slideBufStartPos; + if (byteCount >= _blockAndAuth) { + // At least a 16 byte block and an auth code remains. + _transform.TransformBlock(_slideBuffer, + _slideBufStartPos, + CRYPTO_BLOCK_SIZE, + outBuffer, + offset); + nBytes += CRYPTO_BLOCK_SIZE; + offset += CRYPTO_BLOCK_SIZE; + _slideBufStartPos += CRYPTO_BLOCK_SIZE; + } else { + // Last round. + if (byteCount > AUTH_CODE_LENGTH) { + // At least one byte of data plus auth code + int finalBlock = byteCount - AUTH_CODE_LENGTH; + _transform.TransformBlock(_slideBuffer, + _slideBufStartPos, + finalBlock, + outBuffer, + offset); + + nBytes += finalBlock; + _slideBufStartPos += finalBlock; + } + else if (byteCount < AUTH_CODE_LENGTH) + throw new Exception("Internal error missed auth code"); // Coding bug + // Final block done. Check Auth code. + byte[] calcAuthCode = _transform.GetAuthCode(); + for (int i = 0; i < AUTH_CODE_LENGTH; i++) { + if (calcAuthCode[i] != _slideBuffer[_slideBufStartPos + i]) { + throw new Exception("AES Authentication Code does not match. This is a super-CRC check on the data in the file after compression and encryption. \r\n" + + "The file may be damaged."); + } + } + + break; // Reached the auth code + } + } + return nBytes; + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + public override void Write(byte[] buffer, int offset, int count) { + // ZipAESStream is used for reading but not for writing. Writing uses the ZipAESTransform directly. + throw new NotImplementedException(); + } + } +} +#endif \ No newline at end of file diff --git a/类库/OnlineRepair/ZIP/Encryption/ZipAESTransform.cs b/类库/OnlineRepair/ZIP/Encryption/ZipAESTransform.cs new file mode 100644 index 0000000..134c1eb --- /dev/null +++ b/类库/OnlineRepair/ZIP/Encryption/ZipAESTransform.cs @@ -0,0 +1,219 @@ +// +// ZipAESTransform.cs +// +// Copyright 2009 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + +#if !NET_1_1 && !NETCF_2_0 +// Framework version 2.0 required for Rfc2898DeriveBytes + +using System; +using System.Security.Cryptography; + +namespace ICSharpCode.SharpZipLib.Encryption { + + /// + /// Transforms stream using AES in CTR mode + /// + internal class ZipAESTransform : ICryptoTransform { + + private const int PWD_VER_LENGTH = 2; + + // WinZip use iteration count of 1000 for PBKDF2 key generation + private const int KEY_ROUNDS = 1000; + + // For 128-bit AES (16 bytes) the encryption is implemented as expected. + // For 256-bit AES (32 bytes) WinZip do full 256 bit AES of the nonce to create the encryption + // block but use only the first 16 bytes of it, and discard the second half. + private const int ENCRYPT_BLOCK = 16; + + private int _blockSize; + private ICryptoTransform _encryptor; + private readonly byte[] _counterNonce; + private byte[] _encryptBuffer; + private int _encrPos; + private byte[] _pwdVerifier; + private HMACSHA1 _hmacsha1; + private bool _finalised; + + private bool _writeMode; + + /// + /// Constructor. + /// + /// Password string + /// Random bytes, length depends on encryption strength. + /// 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. + /// The encryption strength, in bytes eg 16 for 128 bits. + /// True when creating a zip, false when reading. For the AuthCode. + /// + public ZipAESTransform(string key, byte[] saltBytes, int blockSize, bool writeMode) { + + if (blockSize != 16 && blockSize != 32) // 24 valid for AES but not supported by Winzip + throw new Exception("Invalid blocksize " + blockSize + ". Must be 16 or 32."); + if (saltBytes.Length != blockSize / 2) + throw new Exception("Invalid salt len. Must be " + blockSize / 2 + " for blocksize " + blockSize); + // initialise the encryption buffer and buffer pos + _blockSize = blockSize; + _encryptBuffer = new byte[_blockSize]; + _encrPos = ENCRYPT_BLOCK; + + // Performs the equivalent of derive_key in Dr Brian Gladman's pwd2key.c + Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, saltBytes, KEY_ROUNDS); + RijndaelManaged rm = new RijndaelManaged(); + rm.Mode = CipherMode.ECB; // No feedback from cipher for CTR mode + _counterNonce = new byte[_blockSize]; + byte[] byteKey1 = pdb.GetBytes(_blockSize); + byte[] byteKey2 = pdb.GetBytes(_blockSize); + _encryptor = rm.CreateEncryptor(byteKey1, byteKey2); + _pwdVerifier = pdb.GetBytes(PWD_VER_LENGTH); + // + _hmacsha1 = new HMACSHA1(byteKey2); + _writeMode = writeMode; + } + + /// + /// Implement the ICryptoTransform method. + /// + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { + + // Pass the data stream to the hash algorithm for generating the Auth Code. + // This does not change the inputBuffer. Do this before decryption for read mode. + if (!_writeMode) { + _hmacsha1.TransformBlock(inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset); + } + // Encrypt with AES in CTR mode. Regards to Dr Brian Gladman for this. + int ix = 0; + while (ix < inputCount) { + if (_encrPos == ENCRYPT_BLOCK) { + /* increment encryption nonce */ + int j = 0; + while (++_counterNonce[j] == 0) { + ++j; + } + /* encrypt the nonce to form next xor buffer */ + _encryptor.TransformBlock(_counterNonce, 0, _blockSize, _encryptBuffer, 0); + _encrPos = 0; + } + outputBuffer[ix + outputOffset] = (byte)(inputBuffer[ix + inputOffset] ^ _encryptBuffer[_encrPos++]); + // + ix++; + } + if (_writeMode) { + // This does not change the buffer. + _hmacsha1.TransformBlock(outputBuffer, outputOffset, inputCount, outputBuffer, outputOffset); + } + return inputCount; + } + + /// + /// Returns the 2 byte password verifier + /// + public byte[] PwdVerifier { + get { + return _pwdVerifier; + } + } + + /// + /// Returns the 10 byte AUTH CODE to be checked or appended immediately following the AES data stream. + /// + public byte[] GetAuthCode() { + // We usually don't get advance notice of final block. Hash requres a TransformFinal. + if (!_finalised) { + byte[] dummy = new byte[0]; + _hmacsha1.TransformFinalBlock(dummy, 0, 0); + _finalised = true; + } + return _hmacsha1.Hash; + } + + #region ICryptoTransform Members + + /// + /// Not implemented. + /// + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { + + throw new NotImplementedException("ZipAESTransform.TransformFinalBlock"); + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize { + get { + return _blockSize; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize { + get { + return _blockSize; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks { + get { + return true; + } + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform { + get { + return true; + } + } + + /// + /// Cleanup internal state. + /// + public void Dispose() { + _encryptor.Dispose(); + } + + #endregion + + } +} +#endif \ No newline at end of file diff --git a/类库/OnlineRepair/ZIP/GZip/GZIPConstants.cs b/类库/OnlineRepair/ZIP/GZip/GZIPConstants.cs new file mode 100644 index 0000000..1c0e389 --- /dev/null +++ b/类库/OnlineRepair/ZIP/GZip/GZIPConstants.cs @@ -0,0 +1,97 @@ +// GZipConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This class contains constants used for gzip. + /// + sealed public class GZipConstants + { + /// + /// Magic number found at start of GZIP header + /// + public const int GZIP_MAGIC = 0x1F8B; + + /* The flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + */ + + /// + /// Flag bit mask for text + /// + public const int FTEXT = 0x1; + + /// + /// Flag bitmask for Crc + /// + public const int FHCRC = 0x2; + + /// + /// Flag bit mask for extra + /// + public const int FEXTRA = 0x4; + + /// + /// flag bitmask for name + /// + public const int FNAME = 0x8; + + /// + /// flag bit mask indicating comment is present + /// + public const int FCOMMENT = 0x10; + + /// + /// Initialise default instance. + /// + /// Constructor is private to prevent instances being created. + GZipConstants() + { + } + } +} diff --git a/类库/OnlineRepair/ZIP/GZip/GZipException.cs b/类库/OnlineRepair/ZIP/GZip/GZipException.cs new file mode 100644 index 0000000..7f42931 --- /dev/null +++ b/类库/OnlineRepair/ZIP/GZip/GZipException.cs @@ -0,0 +1,91 @@ +// GZipException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.GZip +{ + /// + /// GZipException represents a Gzip specific exception + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class GZipException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected GZipException(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + + /// + /// Initialise a new instance of GZipException + /// + public GZipException() + { + } + + /// + /// Initialise a new instance of GZipException with its message string. + /// + /// A that describes the error. + public GZipException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of . + /// + /// A that describes the error. + /// The that caused this exception. + public GZipException(string message, Exception innerException) + : base (message, innerException) + { + } + } +} diff --git a/类库/OnlineRepair/ZIP/GZip/GzipInputStream.cs b/类库/OnlineRepair/ZIP/GZip/GzipInputStream.cs new file mode 100644 index 0000000..4cbad94 --- /dev/null +++ b/类库/OnlineRepair/ZIP/GZip/GzipInputStream.cs @@ -0,0 +1,384 @@ +// GzipInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 11-08-2009 GeoffHart T9121 Added Multi-member gzip support + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This filter stream is used to decompress a "GZIP" format stream. + /// The "GZIP" format is described baseInputStream RFC 1952. + /// + /// author of the original java version : John Leuner + /// + /// This sample shows how to unzip a gzipped file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.GZip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream inStream = new GZipInputStream(File.OpenRead(args[0]))) + /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + /// byte[] buffer = new byte[4096]; + /// StreamUtils.Copy(inStream, outStream, buffer); + /// } + /// } + /// } + /// + /// + public class GZipInputStream : InflaterInputStream + { + #region Instance Fields + /// + /// CRC-32 value for uncompressed data + /// + protected Crc32 crc; + + /// + /// Flag to indicate if we've read the GZIP header yet for the current member (block of compressed data). + /// This is tracked per-block as the file is parsed. + /// + bool readGZIPHeader; + #endregion + + #region Constructors + /// + /// Creates a GZipInputStream with the default buffer size + /// + /// + /// The stream to read compressed data from (baseInputStream GZIP format) + /// + public GZipInputStream(Stream baseInputStream) + : this(baseInputStream, 4096) + { + } + + /// + /// Creates a GZIPInputStream with the specified buffer size + /// + /// + /// The stream to read compressed data from (baseInputStream GZIP format) + /// + /// + /// Size of the buffer to use + /// + public GZipInputStream(Stream baseInputStream, int size) + : base(baseInputStream, new Inflater(true), size) + { + } + #endregion + + #region Stream overrides + /// + /// Reads uncompressed data into an array of bytes + /// + /// + /// The buffer to read uncompressed data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of uncompressed bytes to be read + /// + /// Returns the number of bytes actually read. + public override int Read(byte[] buffer, int offset, int count) + { + // A GZIP file can contain multiple blocks of compressed data, although this is quite rare. + // A compressed block could potentially be empty, so we need to loop until we reach EOF or + // we find data. + while (true) { + + // If we haven't read the header for this block, read it + if (! readGZIPHeader) { + + // Try to read header. If there is no header (0 bytes available), this is EOF. If there is + // an incomplete header, this will throw an exception. + if (! ReadHeader()) { + return 0; + } + } + + // Try to read compressed data + int bytesRead = base.Read(buffer, offset, count); + if (bytesRead > 0) { + crc.Update(buffer, offset, bytesRead); + } + + // If this is the end of stream, read the footer + if (inf.IsFinished) { + ReadFooter(); + } + + if (bytesRead > 0) { + return bytesRead; + } + } + } + #endregion + + #region Support routines + bool ReadHeader() + { + // Initialize CRC for this block + crc = new Crc32(); + + // Make sure there is data in file. We can't rely on ReadLeByte() to fill the buffer, as this could be EOF, + // which is fine, but ReadLeByte() throws an exception if it doesn't find data, so we do this part ourselves. + if (inputBuffer.Available <= 0) { + inputBuffer.Fill(); + if (inputBuffer.Available <= 0) { + // No header, EOF. + return false; + } + } + + // 1. Check the two magic bytes + Crc32 headCRC = new Crc32(); + int magic = inputBuffer.ReadLeByte(); + + if (magic < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + headCRC.Update(magic); + if (magic != (GZipConstants.GZIP_MAGIC >> 8)) { + throw new GZipException("Error GZIP header, first magic byte doesn't match"); + } + + //magic = baseInputStream.ReadByte(); + magic = inputBuffer.ReadLeByte(); + + if (magic < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + if (magic != (GZipConstants.GZIP_MAGIC & 0xFF)) { + throw new GZipException("Error GZIP header, second magic byte doesn't match"); + } + + headCRC.Update(magic); + + // 2. Check the compression type (must be 8) + int compressionType = inputBuffer.ReadLeByte(); + + if ( compressionType < 0 ) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + if ( compressionType != 8 ) { + throw new GZipException("Error GZIP header, data not in deflate format"); + } + headCRC.Update(compressionType); + + // 3. Check the flags + int flags = inputBuffer.ReadLeByte(); + if (flags < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(flags); + + /* This flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + */ + + // 3.1 Check the reserved bits are zero + + if ((flags & 0xE0) != 0) { + throw new GZipException("Reserved flag bits in GZIP header != 0"); + } + + // 4.-6. Skip the modification time, extra flags, and OS type + for (int i=0; i< 6; i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + // 7. Read extra field + if ((flags & GZipConstants.FEXTRA) != 0) { + // Skip subfield id + for (int i=0; i< 2; i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + if (inputBuffer.ReadLeByte() < 0 || inputBuffer.ReadLeByte() < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + int len1, len2; + len1 = inputBuffer.ReadLeByte(); + len2 = inputBuffer.ReadLeByte(); + if ((len1 < 0) || (len2 < 0)) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(len1); + headCRC.Update(len2); + + int extraLen = (len1 << 8) | len2; + for (int i = 0; i < extraLen;i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) + { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + } + + // 8. Read file name + if ((flags & GZipConstants.FNAME) != 0) { + int readByte; + while ( (readByte = inputBuffer.ReadLeByte()) > 0) { + headCRC.Update(readByte); + } + + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + // 9. Read comment + if ((flags & GZipConstants.FCOMMENT) != 0) { + int readByte; + while ( (readByte = inputBuffer.ReadLeByte()) > 0) { + headCRC.Update(readByte); + } + + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + headCRC.Update(readByte); + } + + // 10. Read header CRC + if ((flags & GZipConstants.FHCRC) != 0) { + int tempByte; + int crcval = inputBuffer.ReadLeByte(); + if (crcval < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + tempByte = inputBuffer.ReadLeByte(); + if (tempByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + crcval = (crcval << 8) | tempByte; + if (crcval != ((int) headCRC.Value & 0xffff)) { + throw new GZipException("Header CRC value mismatch"); + } + } + + readGZIPHeader = true; + return true; + } + + void ReadFooter() + { + byte[] footer = new byte[8]; + + // End of stream; reclaim all bytes from inf, read the final byte count, and reset the inflator + long bytesRead = inf.TotalOut & 0xffffffff; + inputBuffer.Available += inf.RemainingInput; + inf.Reset(); + + // Read footer from inputBuffer + int needed = 8; + while (needed > 0) { + int count = inputBuffer.ReadClearTextBuffer(footer, 8 - needed, needed); + if (count <= 0) { + throw new EndOfStreamException("EOS reading GZIP footer"); + } + needed -= count; // Jewel Jan 16 + } + + // Calculate CRC + int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8) | ((footer[2] & 0xff) << 16) | (footer[3] << 24); + if (crcval != (int) crc.Value) { + throw new GZipException("GZIP crc sum mismatch, theirs \"" + crcval + "\" and ours \"" + (int) crc.Value); + } + + // NOTE The total here is the original total modulo 2 ^ 32. + uint total = + (uint)((uint)footer[4] & 0xff) | + (uint)(((uint)footer[5] & 0xff) << 8) | + (uint)(((uint)footer[6] & 0xff) << 16) | + (uint)((uint)footer[7] << 24); + + if (bytesRead != total) { + throw new GZipException("Number of bytes mismatch in footer"); + } + + // Mark header read as false so if another header exists, we'll continue reading through the file + readGZIPHeader = false; + } + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/GZip/GzipOutputStream.cs b/类库/OnlineRepair/ZIP/GZip/GzipOutputStream.cs new file mode 100644 index 0000000..0db2e4b --- /dev/null +++ b/类库/OnlineRepair/ZIP/GZip/GzipOutputStream.cs @@ -0,0 +1,261 @@ +// GZipOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This filter stream is used to compress a stream into a "GZIP" stream. + /// The "GZIP" format is described in RFC 1952. + /// + /// author of the original java version : John Leuner + /// + /// This sample shows how to gzip a file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.GZip; + /// using ICSharpCode.SharpZipLib.Core; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz"))) + /// using (FileStream fs = File.OpenRead(args[0])) { + /// byte[] writeData = new byte[4096]; + /// Streamutils.Copy(s, fs, writeData); + /// } + /// } + /// } + /// } + /// + /// + public class GZipOutputStream : DeflaterOutputStream + { + enum OutputState + { + Header, + Footer, + Finished, + Closed, + }; + + #region Instance Fields + /// + /// CRC-32 value for uncompressed data + /// + protected Crc32 crc = new Crc32(); + OutputState state_ = OutputState.Header; + #endregion + + #region Constructors + /// + /// Creates a GzipOutputStream with the default buffer size + /// + /// + /// The stream to read data (to be compressed) from + /// + public GZipOutputStream(Stream baseOutputStream) + : this(baseOutputStream, 4096) + { + } + + /// + /// Creates a GZipOutputStream with the specified buffer size + /// + /// + /// The stream to read data (to be compressed) from + /// + /// + /// Size of the buffer to use + /// + public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size) + { + } + #endregion + + #region Public API + /// + /// Sets the active compression level (1-9). The new level will be activated + /// immediately. + /// + /// The compression level to set. + /// + /// Level specified is not supported. + /// + /// + public void SetLevel(int level) + { + if (level < Deflater.BEST_SPEED) { + throw new ArgumentOutOfRangeException("level"); + } + deflater_.SetLevel(level); + } + + /// + /// Get the current compression level. + /// + /// The current compression level. + public int GetLevel() + { + return deflater_.GetLevel(); + } + #endregion + + #region Stream overrides + /// + /// Write given buffer to output updating crc + /// + /// Buffer to write + /// Offset of first byte in buf to write + /// Number of bytes to write + public override void Write(byte[] buffer, int offset, int count) + { + if ( state_ == OutputState.Header ) { + WriteHeader(); + } + + if( state_!=OutputState.Footer ) + { + throw new InvalidOperationException("Write not permitted in current state"); + } + + crc.Update(buffer, offset, count); + base.Write(buffer, offset, count); + } + + /// + /// Writes remaining compressed output data to the output stream + /// and closes it. + /// + public override void Close() + { + try { + Finish(); + } + finally { + if ( state_ != OutputState.Closed ) { + state_ = OutputState.Closed; + if( IsStreamOwner ) { + baseOutputStream_.Close(); + } + } + } + } + #endregion + + #region DeflaterOutputStream overrides + /// + /// Finish compression and write any footer information required to stream + /// + public override void Finish() + { + // If no data has been written a header should be added. + if ( state_ == OutputState.Header ) { + WriteHeader(); + } + + if( state_ == OutputState.Footer) + { + state_=OutputState.Finished; + base.Finish(); + + uint totalin=(uint)(deflater_.TotalIn&0xffffffff); + uint crcval=(uint)(crc.Value&0xffffffff); + + byte[] gzipFooter; + + unchecked + { + gzipFooter=new byte[] { + (byte) crcval, (byte) (crcval >> 8), + (byte) (crcval >> 16), (byte) (crcval >> 24), + + (byte) totalin, (byte) (totalin >> 8), + (byte) (totalin >> 16), (byte) (totalin >> 24) + }; + } + + baseOutputStream_.Write(gzipFooter, 0, gzipFooter.Length); + } + } + #endregion + + #region Support Routines + void WriteHeader() + { + if ( state_ == OutputState.Header ) + { + state_=OutputState.Footer; + + int mod_time = (int)((DateTime.Now.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000L); // Ticks give back 100ns intervals + byte[] gzipHeader = { + // The two magic bytes + (byte) (GZipConstants.GZIP_MAGIC >> 8), (byte) (GZipConstants.GZIP_MAGIC & 0xff), + + // The compression type + (byte) Deflater.DEFLATED, + + // The flags (not set) + 0, + + // The modification time + (byte) mod_time, (byte) (mod_time >> 8), + (byte) (mod_time >> 16), (byte) (mod_time >> 24), + + // The extra flags + 0, + + // The OS type (unknown) + (byte) 255 + }; + baseOutputStream_.Write(gzipHeader, 0, gzipHeader.Length); + } + } + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Lzw/LzwConstants.cs b/类库/OnlineRepair/ZIP/Lzw/LzwConstants.cs new file mode 100644 index 0000000..699ed09 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Lzw/LzwConstants.cs @@ -0,0 +1,94 @@ +// LzwConstants.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.LZW { + + /// + /// This class contains constants used for LZW + /// + sealed public class LzwConstants { + /// + /// Magic number found at start of LZW header: 0x1f 0x9d + /// + public const int MAGIC = 0x1f9d; + + /// + /// Maximum number of bits per code + /// + public const int MAX_BITS = 16; + + /* 3rd header byte: + * bit 0..4 Number of compression bits + * bit 5 Extended header + * bit 6 Free + * bit 7 Block mode + */ + + /// + /// Mask for 'number of compression bits' + /// + public const int BIT_MASK = 0x1f; + + /// + /// Indicates the presence of a fourth header byte + /// + public const int EXTENDED_MASK = 0x20; + //public const int FREE_MASK = 0x40; + + /// + /// Reserved bits + /// + public const int RESERVED_MASK = 0x60; + + /// + /// Block compression: if table is full and compression rate is dropping, + /// clear the dictionary. + /// + public const int BLOCK_MODE_MASK = 0x80; + + /// + /// LZW file header size (in bytes) + /// + public const int HDR_SIZE = 3; + + /// + /// Initial number of bits per code + /// + public const int INIT_BITS = 9; + + LzwConstants() { + } + } +} diff --git a/类库/OnlineRepair/ZIP/Lzw/LzwException.cs b/类库/OnlineRepair/ZIP/Lzw/LzwException.cs new file mode 100644 index 0000000..10a9547 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Lzw/LzwException.cs @@ -0,0 +1,88 @@ +// LzwException.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.LZW +{ + + /// + /// LzwException represents a LZW specific exception + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class LzwException : SharpZipBaseException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected LzwException(SerializationInfo info, StreamingContext context) + : base(info, context) { + } +#endif + + /// + /// Initialise a new instance of LzwException + /// + public LzwException() { + } + + /// + /// Initialise a new instance of LzwException with its message string. + /// + /// A that describes the error. + public LzwException(string message) + : base(message) { + } + + /// + /// Initialise a new instance of . + /// + /// A that describes the error. + /// The that caused this exception. + public LzwException(string message, Exception innerException) + : base(message, innerException) { + } + } +} diff --git a/类库/OnlineRepair/ZIP/Lzw/LzwInputStream.cs b/类库/OnlineRepair/ZIP/Lzw/LzwInputStream.cs new file mode 100644 index 0000000..94b8b66 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Lzw/LzwInputStream.cs @@ -0,0 +1,598 @@ +// LzwInputStream.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.LZW +{ + + /// + /// This filter stream is used to decompress a LZW format stream. + /// Specifically, a stream that uses the LZC compression method. + /// This file format is usually associated with the .Z file extension. + /// + /// See http://en.wikipedia.org/wiki/Compress + /// See http://wiki.wxwidgets.org/Development:_Z_File_Format + /// + /// The file header consists of 3 (or optionally 4) bytes. The first two bytes + /// contain the magic marker "0x1f 0x9d", followed by a byte of flags. + /// + /// Based on Java code by Ronald Tschalar, which in turn was based on the unlzw.c + /// code in the gzip package. + /// + /// This sample shows how to unzip a compressed file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.LZW; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream inStream = new LzwInputStream(File.OpenRead(args[0]))) + /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + /// byte[] buffer = new byte[4096]; + /// StreamUtils.Copy(inStream, outStream, buffer); + /// // OR + /// inStream.Read(buffer, 0, buffer.Length); + /// // now do something with the buffer + /// } + /// } + /// } + /// + /// + public class LzwInputStream : Stream + { + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + /// + /// The default value is true. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Creates a LzwInputStream + /// + /// + /// The stream to read compressed data from (baseInputStream LZW format) + /// + public LzwInputStream(Stream baseInputStream) { + this.baseInputStream = baseInputStream; + } + + /// + /// See + /// + /// + public override int ReadByte() { + int b = Read(one, 0, 1); + if (b == 1) + return (one[0] & 0xff); + return -1; + } + + /// + /// Reads decompressed data into the provided buffer byte array + /// + /// + /// The array to read and decompress data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of bytes to decompress + /// + /// The number of bytes read. Zero signals the end of stream + public override int Read(byte[] buffer, int offset, int count) { + if (!headerParsed) ParseHeader(); + + if (eof) return -1; + int start = offset; + + /* Using local copies of various variables speeds things up by as + * much as 30% in Java! Performance not tested in C#. + */ + int[] lTabPrefix = tabPrefix; + byte[] lTabSuffix = tabSuffix; + byte[] lStack = stack; + int lNBits = nBits; + int lMaxCode = maxCode; + int lMaxMaxCode = maxMaxCode; + int lBitMask = bitMask; + int lOldCode = oldCode; + byte lFinChar = finChar; + int lStackP = stackP; + int lFreeEnt = freeEnt; + byte[] lData = data; + int lBitPos = bitPos; + + + // empty stack if stuff still left + int sSize = lStack.Length - lStackP; + if (sSize > 0) { + int num = (sSize >= count) ? count : sSize; + Array.Copy(lStack, lStackP, buffer, offset, num); + offset += num; + count -= num; + lStackP += num; + } + + if (count == 0) { + stackP = lStackP; + return offset - start; + } + + + // loop, filling local buffer until enough data has been decompressed + MainLoop: do { + if (end < EXTRA) { + Fill(); + } + + int bitIn = (got > 0) ? (end - end % lNBits) << 3 : + (end << 3) - (lNBits - 1); + + while (lBitPos < bitIn) { + #region A + // handle 1-byte reads correctly + if (count == 0) { + nBits = lNBits; + maxCode = lMaxCode; + maxMaxCode = lMaxMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + return offset - start; + } + + // check for code-width expansion + if (lFreeEnt > lMaxCode) { + int nBytes = lNBits << 3; + lBitPos = (lBitPos - 1) + + nBytes - (lBitPos - 1 + nBytes) % nBytes; + + lNBits++; + lMaxCode = (lNBits == maxBits) ? lMaxMaxCode : + (1 << lNBits) - 1; + + lBitMask = (1 << lNBits) - 1; + lBitPos = ResetBuf(lBitPos); + goto MainLoop; + } + #endregion + + #region B + // read next code + int pos = lBitPos >> 3; + int code = (((lData[pos] & 0xFF) | + ((lData[pos + 1] & 0xFF) << 8) | + ((lData[pos + 2] & 0xFF) << 16)) >> + (lBitPos & 0x7)) & lBitMask; + + lBitPos += lNBits; + + // handle first iteration + if (lOldCode == -1) { + if (code >= 256) throw new LzwException("corrupt input: " + code + " > 255"); + + lFinChar = (byte) (lOldCode = code); + buffer[offset++] = lFinChar; + count--; + continue; + } + + // handle CLEAR code + if (code == TBL_CLEAR && blockMode) { + Array.Copy(zeros, 0, lTabPrefix, 0, zeros.Length); + lFreeEnt = TBL_FIRST - 1; + + int nBytes = lNBits << 3; + lBitPos = (lBitPos - 1) + nBytes - (lBitPos - 1 + nBytes) % nBytes; + lNBits = LzwConstants.INIT_BITS; + lMaxCode = (1 << lNBits) - 1; + lBitMask = lMaxCode; + + // Code tables reset + + lBitPos = ResetBuf(lBitPos); + goto MainLoop; + } + #endregion + + #region C + // setup + int inCode = code; + lStackP = lStack.Length; + + // Handle KwK case + if (code >= lFreeEnt) { + if (code > lFreeEnt) { + throw new LzwException("corrupt input: code=" + code + + ", freeEnt=" + lFreeEnt); + } + + lStack[--lStackP] = lFinChar; + code = lOldCode; + } + + // Generate output characters in reverse order + while (code >= 256) { + lStack[--lStackP] = lTabSuffix[code]; + code = lTabPrefix[code]; + } + + lFinChar = lTabSuffix[code]; + buffer[offset++] = lFinChar; + count--; + + // And put them out in forward order + sSize = lStack.Length - lStackP; + int num = (sSize >= count) ? count : sSize; + Array.Copy(lStack, lStackP, buffer, offset, num); + offset += num; + count -= num; + lStackP += num; + #endregion + + #region D + // generate new entry in table + if (lFreeEnt < lMaxMaxCode) { + lTabPrefix[lFreeEnt] = lOldCode; + lTabSuffix[lFreeEnt] = lFinChar; + lFreeEnt++; + } + + // Remember previous code + lOldCode = inCode; + + // if output buffer full, then return + if (count == 0) { + nBits = lNBits; + maxCode = lMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + return offset - start; + } + #endregion + } // while + + lBitPos = ResetBuf(lBitPos); + + } while (got > 0); // do..while + + nBits = lNBits; + maxCode = lMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + eof = true; + return offset - start; + } + + /// + /// Moves the unread data in the buffer to the beginning and resets + /// the pointers. + /// + /// + /// + private int ResetBuf(int bitPosition) { + int pos = bitPosition >> 3; + Array.Copy(data, pos, data, 0, end - pos); + end -= pos; + return 0; + } + + + private void Fill() { + got = baseInputStream.Read(data, end, data.Length - 1 - end); + if (got > 0) { + end += got; + } + } + + + private void ParseHeader() { + headerParsed = true; + + byte[] hdr = new byte[LzwConstants.HDR_SIZE]; + + int result = baseInputStream.Read(hdr, 0, hdr.Length); + + // Check the magic marker + if (result < 0) + throw new LzwException("Failed to read LZW header"); + + if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) { + throw new LzwException(String.Format( + "Wrong LZW header. Magic bytes don't match. 0x{0:x2} 0x{1:x2}", + hdr[0], hdr[1])); + } + + // Check the 3rd header byte + blockMode = (hdr[2] & LzwConstants.BLOCK_MODE_MASK) > 0; + maxBits = hdr[2] & LzwConstants.BIT_MASK; + + if (maxBits > LzwConstants.MAX_BITS) { + throw new LzwException("Stream compressed with " + maxBits + + " bits, but decompression can only handle " + + LzwConstants.MAX_BITS + " bits."); + } + + if ((hdr[2] & LzwConstants.RESERVED_MASK) > 0) { + throw new LzwException("Unsupported bits set in the header."); + } + + // Initialize variables + maxMaxCode = 1 << maxBits; + nBits = LzwConstants.INIT_BITS; + maxCode = (1 << nBits) - 1; + bitMask = maxCode; + oldCode = -1; + finChar = 0; + freeEnt = blockMode ? TBL_FIRST : 256; + + tabPrefix = new int[1 << maxBits]; + tabSuffix = new byte[1 << maxBits]; + stack = new byte[1 << maxBits]; + stackP = stack.Length; + + for (int idx = 255; idx >= 0; idx--) + tabSuffix[idx] = (byte)idx; + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get + { + return baseInputStream.CanRead; + } + } + + /// + /// Gets a value of false indicating seeking is not supported for this stream. + /// + public override bool CanSeek + { + get + { + return false; + } + } + + /// + /// Gets a value of false indicating that this stream is not writeable. + /// + public override bool CanWrite + { + get + { + return false; + } + } + + /// + /// A value representing the length of the stream in bytes. + /// + public override long Length + { + get + { + return got; + } + } + + /// + /// The current position within the stream. + /// Throws a NotSupportedException when attempting to set the position + /// + /// Attempting to set the position + public override long Position + { + get + { + return baseInputStream.Position; + } + set + { + throw new NotSupportedException("InflaterInputStream Position not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + baseInputStream.Flush(); + } + + /// + /// Sets the position within the current stream + /// Always throws a NotSupportedException + /// + /// The relative offset to seek to. + /// The defining where to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Seek not supported"); + } + + /// + /// Set the length of the current stream + /// Always throws a NotSupportedException + /// + /// The new length value for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("InflaterInputStream SetLength not supported"); + } + + /// + /// Writes a sequence of bytes to stream and advances the current position + /// This method always throws a NotSupportedException + /// + /// Thew buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("InflaterInputStream Write not supported"); + } + + /// + /// Writes one byte to the current stream and advances the current position + /// Always throws a NotSupportedException + /// + /// The byte to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("InflaterInputStream WriteByte not supported"); + } + + /// + /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. + /// + /// The buffer to write data from + /// Offset of first byte to write + /// The maximum number of bytes to write + /// The method to be called when the asynchronous write operation is completed + /// A user-provided object that distinguishes this particular asynchronous write request from other requests + /// An IAsyncResult that references the asynchronous write + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); + } + + /// + /// Closes the input stream. When + /// is true the underlying stream is also closed. + /// + public override void Close() + { + if (!isClosed) + { + isClosed = true; + if (isStreamOwner) + { + baseInputStream.Close(); + } + } + } + + #endregion + + #region Instance Fields + + Stream baseInputStream; + + /// + /// Flag indicating wether this instance is designated the stream owner. + /// When closing if this flag is true the underlying stream is closed. + /// + bool isStreamOwner = true; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + readonly byte[] one = new byte[1]; + bool headerParsed; + + // string table stuff + private const int TBL_CLEAR = 0x100; + private const int TBL_FIRST = TBL_CLEAR + 1; + + private int[] tabPrefix; + private byte[] tabSuffix; + private readonly int[] zeros = new int[256]; + private byte[] stack; + + // various state + private bool blockMode; + private int nBits; + private int maxBits; + private int maxMaxCode; + private int maxCode; + private int bitMask; + private int oldCode; + private byte finChar; + private int stackP; + private int freeEnt; + + // input buffer + private readonly byte[] data = new byte[1024 * 8]; + private int bitPos; + private int end; + int got; + private bool eof; + private const int EXTRA = 64; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/SharpZipBaseException.cs b/类库/OnlineRepair/ZIP/SharpZipBaseException.cs new file mode 100644 index 0000000..7a5d136 --- /dev/null +++ b/类库/OnlineRepair/ZIP/SharpZipBaseException.cs @@ -0,0 +1,94 @@ +// SharpZipBaseException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib +{ + /// + /// SharpZipBaseException is the base exception class for the SharpZipLibrary. + /// All library exceptions are derived from this. + /// + /// NOTE: Not all exceptions thrown will be derived from this class. + /// A variety of other exceptions are possible for example +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class SharpZipBaseException : ApplicationException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected SharpZipBaseException(SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } +#endif + + /// + /// Initializes a new instance of the SharpZipBaseException class. + /// + public SharpZipBaseException() + { + } + + /// + /// Initializes a new instance of the SharpZipBaseException class with a specified error message. + /// + /// A message describing the exception. + public SharpZipBaseException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the SharpZipBaseException class with a specified + /// error message and a reference to the inner exception that is the cause of this exception. + /// + /// A message describing the exception. + /// The inner exception + public SharpZipBaseException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/类库/OnlineRepair/ZIP/Tar/InvalidHeaderException.cs b/类库/OnlineRepair/ZIP/Tar/InvalidHeaderException.cs new file mode 100644 index 0000000..bac9343 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Tar/InvalidHeaderException.cs @@ -0,0 +1,109 @@ +// InvalidHeaderException.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Tar { + + /// + /// This exception is used to indicate that there is a problem + /// with a TAR archive header. + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class InvalidHeaderException : TarException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected InvalidHeaderException(SerializationInfo information, StreamingContext context) + : base(information, context) + + { + } +#endif + + /// + /// Initialise a new instance of the InvalidHeaderException class. + /// + public InvalidHeaderException() + { + } + + /// + /// Initialises a new instance of the InvalidHeaderException class with a specified message. + /// + /// Message describing the exception cause. + public InvalidHeaderException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of InvalidHeaderException + /// + /// Message describing the problem. + /// The exception that is the cause of the current exception. + public InvalidHeaderException(string message, Exception exception) + : base(message, exception) + { + } + } +} + +/* The original Java file had this header: +** Authored by Timothy Gerard Endres +** +** +** This work has been placed into the public domain. +** You may use this work in any way and for any purpose you wish. +** +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR +** REDISTRIBUTION OF THIS SOFTWARE. +** +*/ + diff --git a/类库/OnlineRepair/ZIP/Tar/TarArchive.cs b/类库/OnlineRepair/ZIP/Tar/TarArchive.cs new file mode 100644 index 0000000..5a5510b --- /dev/null +++ b/类库/OnlineRepair/ZIP/Tar/TarArchive.cs @@ -0,0 +1,894 @@ +// TarArchive.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 28-01-2010 DavidPierson Added IsStreamOwner + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + /// + /// Used to advise clients of 'events' while processing archives + /// + public delegate void ProgressMessageHandler(TarArchive archive, TarEntry entry, string message); + + /// + /// The TarArchive class implements the concept of a + /// 'Tape Archive'. A tar archive is a series of entries, each of + /// which represents a file system object. Each entry in + /// the archive consists of a header block followed by 0 or more data blocks. + /// Directory entries consist only of the header block, and are followed by entries + /// for the directory's contents. File entries consist of a + /// header followed by the number of blocks needed to + /// contain the file's contents. All entries are written on + /// block boundaries. Blocks are 512 bytes long. + /// + /// TarArchives are instantiated in either read or write mode, + /// based upon whether they are instantiated with an InputStream + /// or an OutputStream. Once instantiated TarArchives read/write + /// mode can not be changed. + /// + /// There is currently no support for random access to tar archives. + /// However, it seems that subclassing TarArchive, and using the + /// TarBuffer.CurrentRecord and TarBuffer.CurrentBlock + /// properties, this would be rather trivial. + /// + public class TarArchive : IDisposable + { + /// + /// Client hook allowing detailed information to be reported during processing + /// + public event ProgressMessageHandler ProgressMessageEvent; + + /// + /// Raises the ProgressMessage event + /// + /// The TarEntry for this event + /// message for this event. Null is no message + protected virtual void OnProgressMessageEvent(TarEntry entry, string message) + { + ProgressMessageHandler handler = ProgressMessageEvent; + if (handler != null) { + handler(this, entry, message); + } + } + + #region Constructors + /// + /// Constructor for a default . + /// + protected TarArchive() + { + } + + /// + /// Initalise a TarArchive for input. + /// + /// The to use for input. + protected TarArchive(TarInputStream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + tarIn = stream; + } + + /// + /// Initialise a TarArchive for output. + /// + /// The to use for output. + protected TarArchive(TarOutputStream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + tarOut = stream; + } + #endregion + + #region Static factory methods + /// + /// The InputStream based constructors create a TarArchive for the + /// purposes of extracting or listing a tar archive. Thus, use + /// these constructors when you wish to extract files from or list + /// the contents of an existing tar archive. + /// + /// The stream to retrieve archive data from. + /// Returns a new suitable for reading from. + public static TarArchive CreateInputTarArchive(Stream inputStream) + { + if ( inputStream == null ) { + throw new ArgumentNullException("inputStream"); + } + + TarInputStream tarStream = inputStream as TarInputStream; + + TarArchive result; + if ( tarStream != null ) { + result = new TarArchive(tarStream); + } + else { + result = CreateInputTarArchive(inputStream, TarBuffer.DefaultBlockFactor); + } + return result; + } + + /// + /// Create TarArchive for reading setting block factor + /// + /// A stream containing the tar archive contents + /// The blocking factor to apply + /// Returns a suitable for reading. + public static TarArchive CreateInputTarArchive(Stream inputStream, int blockFactor) + { + if ( inputStream == null ) { + throw new ArgumentNullException("inputStream"); + } + + if ( inputStream is TarInputStream ) { + throw new ArgumentException("TarInputStream not valid"); + } + + return new TarArchive(new TarInputStream(inputStream, blockFactor)); + } + + /// + /// Create a TarArchive for writing to, using the default blocking factor + /// + /// The to write to + /// Returns a suitable for writing. + public static TarArchive CreateOutputTarArchive(Stream outputStream) + { + if ( outputStream == null ) { + throw new ArgumentNullException("outputStream"); + } + + TarOutputStream tarStream = outputStream as TarOutputStream; + + TarArchive result; + if ( tarStream != null ) { + result = new TarArchive(tarStream); + } + else { + result = CreateOutputTarArchive(outputStream, TarBuffer.DefaultBlockFactor); + } + return result; + } + + /// + /// Create a tar archive for writing. + /// + /// The stream to write to + /// The blocking factor to use for buffering. + /// Returns a suitable for writing. + public static TarArchive CreateOutputTarArchive(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) { + throw new ArgumentNullException("outputStream"); + } + + if ( outputStream is TarOutputStream ) { + throw new ArgumentException("TarOutputStream is not valid"); + } + + return new TarArchive(new TarOutputStream(outputStream, blockFactor)); + } + #endregion + + /// + /// Set the flag that determines whether existing files are + /// kept, or overwritten during extraction. + /// + /// + /// If true, do not overwrite existing files. + /// + public void SetKeepOldFiles(bool keepExistingFiles) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + keepOldFiles = keepExistingFiles; + } + + /// + /// Get/set the ascii file translation flag. If ascii file translation + /// is true, then the file is checked to see if it a binary file or not. + /// If the flag is true and the test indicates it is ascii text + /// file, it will be translated. The translation converts the local + /// operating system's concept of line ends into the UNIX line end, + /// '\n', which is the defacto standard for a TAR archive. This makes + /// text files compatible with UNIX. + /// + public bool AsciiTranslate + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return asciiTranslate; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + asciiTranslate = value; + } + + } + + /// + /// Set the ascii file translation flag. + /// + /// + /// If true, translate ascii text files. + /// + [Obsolete("Use the AsciiTranslate property")] + public void SetAsciiTranslation(bool translateAsciiFiles) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + asciiTranslate = translateAsciiFiles; + } + + /// + /// PathPrefix is added to entry names as they are written if the value is not null. + /// A slash character is appended after PathPrefix + /// + public string PathPrefix + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return pathPrefix; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + pathPrefix = value; + } + + } + + /// + /// RootPath is removed from entry names if it is found at the + /// beginning of the name. + /// + public string RootPath + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return rootPath; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + rootPath = value; + } + } + + /// + /// Set user and group information that will be used to fill in the + /// tar archive's entry headers. This information is based on that available + /// for the linux operating system, which is not always available on other + /// operating systems. TarArchive allows the programmer to specify values + /// to be used in their place. + /// is set to true by this call. + /// + /// + /// The user id to use in the headers. + /// + /// + /// The user name to use in the headers. + /// + /// + /// The group id to use in the headers. + /// + /// + /// The group name to use in the headers. + /// + public void SetUserInfo(int userId, string userName, int groupId, string groupName) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + this.userId = userId; + this.userName = userName; + this.groupId = groupId; + this.groupName = groupName; + applyUserInfoOverrides = true; + } + + /// + /// Get or set a value indicating if overrides defined by SetUserInfo should be applied. + /// + /// If overrides are not applied then the values as set in each header will be used. + public bool ApplyUserInfoOverrides + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return applyUserInfoOverrides; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + applyUserInfoOverrides = value; + } + } + + /// + /// Get the archive user id. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current user id. + /// + public int UserId { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return userId; + } + } + + /// + /// Get the archive user name. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current user name. + /// + public string UserName { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return userName; + } + } + + /// + /// Get the archive group id. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current group id. + /// + public int GroupId { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return groupId; + } + } + + /// + /// Get the archive group name. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current group name. + /// + public string GroupName { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return groupName; + } + } + + /// + /// Get the archive's record size. Tar archives are composed of + /// a series of RECORDS each containing a number of BLOCKS. + /// This allowed tar archives to match the IO characteristics of + /// the physical device being used. Archives are expected + /// to be properly "blocked". + /// + /// + /// The record size this archive is using. + /// + public int RecordSize { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + if (tarIn != null) { + return tarIn.RecordSize; + } else if (tarOut != null) { + return tarOut.RecordSize; + } + return TarBuffer.DefaultRecordSize; + } + } + + /// + /// Sets the IsStreamOwner property on the underlying stream. + /// Set this to false to prevent the Close of the TarArchive from closing the stream. + /// + public bool IsStreamOwner { + set { + if (tarIn != null) { + tarIn.IsStreamOwner = value; + } else { + tarOut.IsStreamOwner = value; + } + } + } + + /// + /// Close the archive. + /// + [Obsolete("Use Close instead")] + public void CloseArchive() + { + Close(); + } + + /// + /// Perform the "list" command for the archive contents. + /// + /// NOTE That this method uses the progress event to actually list + /// the contents. If the progress display event is not set, nothing will be listed! + /// + public void ListContents() + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + while (true) { + TarEntry entry = tarIn.GetNextEntry(); + + if (entry == null) { + break; + } + OnProgressMessageEvent(entry, null); + } + } + + /// + /// Perform the "extract" command and extract the contents of the archive. + /// + /// + /// The destination directory into which to extract. + /// + public void ExtractContents(string destinationDirectory) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + while (true) { + TarEntry entry = tarIn.GetNextEntry(); + + if (entry == null) { + break; + } + + ExtractEntry(destinationDirectory, entry); + } + } + + /// + /// Extract an entry from the archive. This method assumes that the + /// tarIn stream has been properly set with a call to GetNextEntry(). + /// + /// + /// The destination directory into which to extract. + /// + /// + /// The TarEntry returned by tarIn.GetNextEntry(). + /// + void ExtractEntry(string destDir, TarEntry entry) + { + OnProgressMessageEvent(entry, null); + + string name = entry.Name; + + if (Path.IsPathRooted(name)) { + // NOTE: + // for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt + name = name.Substring(Path.GetPathRoot(name).Length); + } + + name = name.Replace('/', Path.DirectorySeparatorChar); + + string destFile = Path.Combine(destDir, name); + + if (entry.IsDirectory) { + EnsureDirectoryExists(destFile); + } else { + string parentDirectory = Path.GetDirectoryName(destFile); + EnsureDirectoryExists(parentDirectory); + + bool process = true; + FileInfo fileInfo = new FileInfo(destFile); + if (fileInfo.Exists) { + if (keepOldFiles) { + OnProgressMessageEvent(entry, "Destination file already exists"); + process = false; + } else if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0) { + OnProgressMessageEvent(entry, "Destination file already exists, and is read-only"); + process = false; + } + } + + if (process) { + bool asciiTrans = false; + + Stream outputStream = File.Create(destFile); + if (this.asciiTranslate) { + asciiTrans = !IsBinary(destFile); + } + + StreamWriter outw = null; + if (asciiTrans) { + outw = new StreamWriter(outputStream); + } + + byte[] rdbuf = new byte[32 * 1024]; + + while (true) { + int numRead = tarIn.Read(rdbuf, 0, rdbuf.Length); + + if (numRead <= 0) { + break; + } + + if (asciiTrans) { + for (int off = 0, b = 0; b < numRead; ++b) { + if (rdbuf[b] == 10) { + string s = Encoding.ASCII.GetString(rdbuf, off, (b - off)); + outw.WriteLine(s); + off = b + 1; + } + } + } else { + outputStream.Write(rdbuf, 0, numRead); + } + } + + if (asciiTrans) { + outw.Close(); + } else { + outputStream.Close(); + } + } + } + } + + /// + /// Write an entry to the archive. This method will call the putNextEntry + /// and then write the contents of the entry, and finally call closeEntry() + /// for entries that are files. For directories, it will call putNextEntry(), + /// and then, if the recurse flag is true, process each entry that is a + /// child of the directory. + /// + /// + /// The TarEntry representing the entry to write to the archive. + /// + /// + /// If true, process the children of directory entries. + /// + public void WriteEntry(TarEntry sourceEntry, bool recurse) + { + if ( sourceEntry == null ) { + throw new ArgumentNullException("sourceEntry"); + } + + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + try + { + if ( recurse ) { + TarHeader.SetValueDefaults(sourceEntry.UserId, sourceEntry.UserName, + sourceEntry.GroupId, sourceEntry.GroupName); + } + WriteEntryCore(sourceEntry, recurse); + } + finally + { + if ( recurse ) { + TarHeader.RestoreSetValues(); + } + } + } + + /// + /// Write an entry to the archive. This method will call the putNextEntry + /// and then write the contents of the entry, and finally call closeEntry() + /// for entries that are files. For directories, it will call putNextEntry(), + /// and then, if the recurse flag is true, process each entry that is a + /// child of the directory. + /// + /// + /// The TarEntry representing the entry to write to the archive. + /// + /// + /// If true, process the children of directory entries. + /// + void WriteEntryCore(TarEntry sourceEntry, bool recurse) + { + string tempFileName = null; + string entryFilename = sourceEntry.File; + + TarEntry entry = (TarEntry)sourceEntry.Clone(); + + if ( applyUserInfoOverrides ) { + entry.GroupId = groupId; + entry.GroupName = groupName; + entry.UserId = userId; + entry.UserName = userName; + } + + OnProgressMessageEvent(entry, null); + + if (asciiTranslate && !entry.IsDirectory) { + + if (!IsBinary(entryFilename)) { + tempFileName = Path.GetTempFileName(); + + using (StreamReader inStream = File.OpenText(entryFilename)) { + using (Stream outStream = File.Create(tempFileName)) { + + while (true) { + string line = inStream.ReadLine(); + if (line == null) { + break; + } + byte[] data = Encoding.ASCII.GetBytes(line); + outStream.Write(data, 0, data.Length); + outStream.WriteByte((byte)'\n'); + } + + outStream.Flush(); + } + } + + entry.Size = new FileInfo(tempFileName).Length; + entryFilename = tempFileName; + } + } + + string newName = null; + + if (rootPath != null) { + if (entry.Name.StartsWith(rootPath)) { + newName = entry.Name.Substring(rootPath.Length + 1 ); + } + } + + if (pathPrefix != null) { + newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName; + } + + if (newName != null) { + entry.Name = newName; + } + + tarOut.PutNextEntry(entry); + + if (entry.IsDirectory) { + if (recurse) { + TarEntry[] list = entry.GetDirectoryEntries(); + for (int i = 0; i < list.Length; ++i) { + WriteEntryCore(list[i], recurse); + } + } + } + else { + using (Stream inputStream = File.OpenRead(entryFilename)) { + byte[] localBuffer = new byte[32 * 1024]; + while (true) { + int numRead = inputStream.Read(localBuffer, 0, localBuffer.Length); + + if (numRead <=0) { + break; + } + + tarOut.Write(localBuffer, 0, numRead); + } + } + + if ( (tempFileName != null) && (tempFileName.Length > 0) ) { + File.Delete(tempFileName); + } + + tarOut.CloseEntry(); + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if ( !isDisposed ) { + isDisposed = true; + if ( disposing ) { + if ( tarOut != null ) { + tarOut.Flush(); + tarOut.Close(); + } + + if ( tarIn != null ) { + tarIn.Close(); + } + } + } + } + + /// + /// Closes the archive and releases any associated resources. + /// + public virtual void Close() + { + Dispose(true); + } + + /// + /// Ensures that resources are freed and other cleanup operations are performed + /// when the garbage collector reclaims the . + /// + ~TarArchive() + { + Dispose(false); + } + + static void EnsureDirectoryExists(string directoryName) + { + if (!Directory.Exists(directoryName)) { + try { + Directory.CreateDirectory(directoryName); + } + catch (Exception e) { + throw new TarException("Exception creating directory '" + directoryName + "', " + e.Message, e); + } + } + } + + // TODO: TarArchive - Is there a better way to test for a text file? + // It no longer reads entire files into memory but is still a weak test! + // This assumes that byte values 0-7, 14-31 or 255 are binary + // and that all non text files contain one of these values + static bool IsBinary(string filename) + { + using (FileStream fs = File.OpenRead(filename)) + { + int sampleSize = Math.Min(4096, (int)fs.Length); + byte[] content = new byte[sampleSize]; + + int bytesRead = fs.Read(content, 0, sampleSize); + + for (int i = 0; i < bytesRead; ++i) { + byte b = content[i]; + if ( (b < 8) || ((b > 13) && (b < 32)) || (b == 255) ) { + return true; + } + } + } + return false; + } + + #region Instance Fields + bool keepOldFiles; + bool asciiTranslate; + + int userId; + string userName = string.Empty; + int groupId; + string groupName = string.Empty; + + string rootPath; + string pathPrefix; + + bool applyUserInfoOverrides; + + TarInputStream tarIn; + TarOutputStream tarOut; + bool isDisposed; + #endregion + } +} + + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ + diff --git a/类库/OnlineRepair/ZIP/Tar/TarBuffer.cs b/类库/OnlineRepair/ZIP/Tar/TarBuffer.cs new file mode 100644 index 0000000..40b8d93 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Tar/TarBuffer.cs @@ -0,0 +1,624 @@ +// TarBuffer.cs +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarBuffer class implements the tar archive concept + /// of a buffered input stream. This concept goes back to the + /// days of blocked tape drives and special io devices. In the + /// C# universe, the only real function that this class + /// performs is to ensure that files have the correct "record" + /// size, or other tars will complain. + ///

+ /// You should never have a need to access this class directly. + /// TarBuffers are created by Tar IO Streams. + ///

+ ///
+ public class TarBuffer + { + +/* A quote from GNU tar man file on blocking and records + A `tar' archive file contains a series of blocks. Each block +contains `BLOCKSIZE' bytes. Although this format may be thought of as +being on magnetic tape, other media are often used. + + Each file archived is represented by a header block which describes +the file, followed by zero or more blocks which give the contents of +the file. At the end of the archive file there may be a block filled +with binary zeros as an end-of-file marker. A reasonable system should +write a block of zeros at the end, but must not assume that such a +block exists when reading an archive. + + The blocks may be "blocked" for physical I/O operations. Each +record of N blocks is written with a single 'write ()' +operation. On magnetic tapes, the result of such a write is a single +record. When writing an archive, the last record of blocks should be +written at the full size, with blocks after the zero block containing +all zeros. When reading an archive, a reasonable system should +properly handle an archive whose last record is shorter than the rest, +or which contains garbage records after a zero block. +*/ + + #region Constants + /// + /// The size of a block in a tar archive in bytes. + /// + /// This is 512 bytes. + public const int BlockSize = 512; + + /// + /// The number of blocks in a default record. + /// + /// + /// The default value is 20 blocks per record. + /// + public const int DefaultBlockFactor = 20; + + /// + /// The size in bytes of a default record. + /// + /// + /// The default size is 10KB. + /// + public const int DefaultRecordSize = BlockSize * DefaultBlockFactor; + #endregion + + /// + /// Get the record size for this buffer + /// + /// The record size in bytes. + /// This is equal to the multiplied by the + public int RecordSize + { + get { + return recordSize; + } + } + + /// + /// Get the TAR Buffer's record size. + /// + /// The record size in bytes. + /// This is equal to the multiplied by the + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return recordSize; + } + + /// + /// Get the Blocking factor for the buffer + /// + /// This is the number of blocks in each record. + public int BlockFactor { + get { + return blockFactor; + } + } + + /// + /// Get the TAR Buffer's block factor + /// + /// The block factor; the number of blocks per record. + [Obsolete("Use BlockFactor property instead")] + public int GetBlockFactor() + { + return blockFactor; + } + + /// + /// Construct a default TarBuffer + /// + protected TarBuffer() + { + } + + /// + /// Create TarBuffer for reading with default BlockFactor + /// + /// Stream to buffer + /// A new suitable for input. + public static TarBuffer CreateInputTarBuffer(Stream inputStream) + { + if ( inputStream == null ) + { + throw new ArgumentNullException("inputStream"); + } + + return CreateInputTarBuffer(inputStream, DefaultBlockFactor); + } + + /// + /// Construct TarBuffer for reading inputStream setting BlockFactor + /// + /// Stream to buffer + /// Blocking factor to apply + /// A new suitable for input. + public static TarBuffer CreateInputTarBuffer(Stream inputStream, int blockFactor) + { + if ( inputStream == null ) + { + throw new ArgumentNullException("inputStream"); + } + + if ( blockFactor <= 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("blockFactor"); +#else + throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative"); +#endif + } + + TarBuffer tarBuffer = new TarBuffer(); + tarBuffer.inputStream = inputStream; + tarBuffer.outputStream = null; + tarBuffer.Initialize(blockFactor); + + return tarBuffer; + } + + /// + /// Construct TarBuffer for writing with default BlockFactor + /// + /// output stream for buffer + /// A new suitable for output. + public static TarBuffer CreateOutputTarBuffer(Stream outputStream) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + return CreateOutputTarBuffer(outputStream, DefaultBlockFactor); + } + + /// + /// Construct TarBuffer for writing Tar output to streams. + /// + /// Output stream to write to. + /// Blocking factor to apply + /// A new suitable for output. + public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + if ( blockFactor <= 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("blockFactor"); +#else + throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative"); +#endif + } + + TarBuffer tarBuffer = new TarBuffer(); + tarBuffer.inputStream = null; + tarBuffer.outputStream = outputStream; + tarBuffer.Initialize(blockFactor); + + return tarBuffer; + } + + /// + /// Initialization common to all constructors. + /// + void Initialize(int archiveBlockFactor) + { + blockFactor = archiveBlockFactor; + recordSize = archiveBlockFactor * BlockSize; + recordBuffer = new byte[RecordSize]; + + if (inputStream != null) { + currentRecordIndex = -1; + currentBlockIndex = BlockFactor; + } + else { + currentRecordIndex = 0; + currentBlockIndex = 0; + } + } + + /// + /// Determine if an archive block indicates End of Archive. End of + /// archive is indicated by a block that consists entirely of null bytes. + /// All remaining blocks for the record should also be null's + /// However some older tars only do a couple of null blocks (Old GNU tar for one) + /// and also partial records + /// + /// The data block to check. + /// Returns true if the block is an EOF block; false otherwise. + [Obsolete("Use IsEndOfArchiveBlock instead")] + public bool IsEOFBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if ( block.Length != BlockSize ) + { + throw new ArgumentException("block length is invalid"); + } + + for (int i = 0; i < BlockSize; ++i) { + if (block[i] != 0) { + return false; + } + } + + return true; + } + + + /// + /// Determine if an archive block indicates the End of an Archive has been reached. + /// End of archive is indicated by a block that consists entirely of null bytes. + /// All remaining blocks for the record should also be null's + /// However some older tars only do a couple of null blocks (Old GNU tar for one) + /// and also partial records + /// + /// The data block to check. + /// Returns true if the block is an EOF block; false otherwise. + public static bool IsEndOfArchiveBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if ( block.Length != BlockSize ) { + throw new ArgumentException("block length is invalid"); + } + + for ( int i = 0; i < BlockSize; ++i ) { + if ( block[i] != 0 ) { + return false; + } + } + + return true; + } + + /// + /// Skip over a block on the input stream. + /// + public void SkipBlock() + { + if (inputStream == null) { + throw new TarException("no input stream defined"); + } + + if (currentBlockIndex >= BlockFactor) { + if (!ReadRecord()) { + throw new TarException("Failed to read a record"); + } + } + + currentBlockIndex++; + } + + /// + /// Read a block from the input stream. + /// + /// + /// The block of data read. + /// + public byte[] ReadBlock() + { + if (inputStream == null) { + throw new TarException("TarBuffer.ReadBlock - no input stream defined"); + } + + if (currentBlockIndex >= BlockFactor) { + if (!ReadRecord()) { + throw new TarException("Failed to read a record"); + } + } + + byte[] result = new byte[BlockSize]; + + Array.Copy(recordBuffer, (currentBlockIndex * BlockSize), result, 0, BlockSize ); + currentBlockIndex++; + return result; + } + + /// + /// Read a record from data stream. + /// + /// + /// false if End-Of-File, else true. + /// + bool ReadRecord() + { + if (inputStream == null) { + throw new TarException("no input stream stream defined"); + } + + currentBlockIndex = 0; + + int offset = 0; + int bytesNeeded = RecordSize; + + while (bytesNeeded > 0) { + long numBytes = inputStream.Read(recordBuffer, offset, bytesNeeded); + + // + // NOTE + // We have found EOF, and the record is not full! + // + // This is a broken archive. It does not follow the standard + // blocking algorithm. However, because we are generous, and + // it requires little effort, we will simply ignore the error + // and continue as if the entire record were read. This does + // not appear to break anything upstream. We used to return + // false in this case. + // + // Thanks to 'Yohann.Roussel@alcatel.fr' for this fix. + // + if (numBytes <= 0) { + break; + } + + offset += (int)numBytes; + bytesNeeded -= (int)numBytes; + } + + currentRecordIndex++; + return true; + } + + /// + /// Get the current block number, within the current record, zero based. + /// + /// Block numbers are zero based values + /// + public int CurrentBlock + { + get { return currentBlockIndex; } + } + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner_; } + set { isStreamOwner_ = value; } + } + + /// + /// Get the current block number, within the current record, zero based. + /// + /// + /// The current zero based block number. + /// + /// + /// The absolute block number = (record number * block factor) + block number. + /// + [Obsolete("Use CurrentBlock property instead")] + public int GetCurrentBlockNum() + { + return currentBlockIndex; + } + + /// + /// Get the current record number. + /// + /// + /// The current zero based record number. + /// + public int CurrentRecord + { + get { return currentRecordIndex; } + } + + /// + /// Get the current record number. + /// + /// + /// The current zero based record number. + /// + [Obsolete("Use CurrentRecord property instead")] + public int GetCurrentRecordNum() + { + return currentRecordIndex; + } + + /// + /// Write a block of data to the archive. + /// + /// + /// The data to write to the archive. + /// + public void WriteBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if (outputStream == null) { + throw new TarException("TarBuffer.WriteBlock - no output stream defined"); + } + + if (block.Length != BlockSize) { + string errorText = string.Format("TarBuffer.WriteBlock - block to write has length '{0}' which is not the block size of '{1}'", + block.Length, BlockSize ); + throw new TarException(errorText); + } + + if (currentBlockIndex >= BlockFactor) { + WriteRecord(); + } + + Array.Copy(block, 0, recordBuffer, (currentBlockIndex * BlockSize), BlockSize); + currentBlockIndex++; + } + + /// + /// Write an archive record to the archive, where the record may be + /// inside of a larger array buffer. The buffer must be "offset plus + /// record size" long. + /// + /// + /// The buffer containing the record data to write. + /// + /// + /// The offset of the record data within buffer. + /// + public void WriteBlock(byte[] buffer, int offset) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if (outputStream == null) { + throw new TarException("TarBuffer.WriteBlock - no output stream stream defined"); + } + + if ( (offset < 0) || (offset >= buffer.Length) ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ((offset + BlockSize) > buffer.Length) { + string errorText = string.Format("TarBuffer.WriteBlock - record has length '{0}' with offset '{1}' which is less than the record size of '{2}'", + buffer.Length, offset, recordSize); + throw new TarException(errorText); + } + + if (currentBlockIndex >= BlockFactor) { + WriteRecord(); + } + + Array.Copy(buffer, offset, recordBuffer, (currentBlockIndex * BlockSize), BlockSize); + + currentBlockIndex++; + } + + /// + /// Write a TarBuffer record to the archive. + /// + void WriteRecord() + { + if (outputStream == null) { + throw new TarException("TarBuffer.WriteRecord no output stream defined"); + } + + outputStream.Write(recordBuffer, 0, RecordSize); + outputStream.Flush(); + + currentBlockIndex = 0; + currentRecordIndex++; + } + + /// + /// WriteFinalRecord writes the current record buffer to output any unwritten data is present. + /// + /// Any trailing bytes are set to zero which is by definition correct behaviour + /// for the end of a tar stream. + void WriteFinalRecord() + { + if (outputStream == null) { + throw new TarException("TarBuffer.WriteFinalRecord no output stream defined"); + } + + if (currentBlockIndex > 0) { + int dataBytes = currentBlockIndex * BlockSize; + Array.Clear(recordBuffer, dataBytes, RecordSize - dataBytes); + WriteRecord(); + } + + outputStream.Flush(); + } + + /// + /// Close the TarBuffer. If this is an output buffer, also flush the + /// current block before closing. + /// + public void Close() + { + if (outputStream != null) { + WriteFinalRecord(); + + if (isStreamOwner_) { + outputStream.Close(); + } + outputStream = null; + } + else if (inputStream != null) { + if (isStreamOwner_) { + inputStream.Close(); + } + inputStream = null; + } + } + + #region Instance Fields + Stream inputStream; + Stream outputStream; + + byte[] recordBuffer; + int currentBlockIndex; + int currentRecordIndex; + + int recordSize = DefaultRecordSize; + int blockFactor = DefaultBlockFactor; + bool isStreamOwner_ = true; + #endregion + } +} + +/* The original Java file had this header: + * + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/OnlineRepair/ZIP/Tar/TarEntry.cs b/类库/OnlineRepair/ZIP/Tar/TarEntry.cs new file mode 100644 index 0000000..a733e32 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Tar/TarEntry.cs @@ -0,0 +1,559 @@ +// TarEntry.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + /// + /// This class represents an entry in a Tar archive. It consists + /// of the entry's header, as well as the entry's File. Entries + /// can be instantiated in one of three ways, depending on how + /// they are to be used. + ///

+ /// TarEntries that are created from the header bytes read from + /// an archive are instantiated with the TarEntry( byte[] ) + /// constructor. These entries will be used when extracting from + /// or listing the contents of an archive. These entries have their + /// header filled in using the header bytes. They also set the File + /// to null, since they reference an archive entry not a file.

+ ///

+ /// TarEntries that are created from files that are to be written + /// into an archive are instantiated with the CreateEntryFromFile(string) + /// pseudo constructor. These entries have their header filled in using + /// the File's information. They also keep a reference to the File + /// for convenience when writing entries.

+ ///

+ /// Finally, TarEntries can be constructed from nothing but a name. + /// This allows the programmer to construct the entry by hand, for + /// instance when only an InputStream is available for writing to + /// the archive, and the header information is constructed from + /// other information. In this case the header fields are set to + /// defaults and the File is set to null.

+ /// + ///
+ public class TarEntry : ICloneable + { + #region Constructors + /// + /// Initialise a default instance of . + /// + private TarEntry() + { + header = new TarHeader(); + } + + /// + /// Construct an entry from an archive's header bytes. File is set + /// to null. + /// + /// + /// The header bytes from a tar archive entry. + /// + public TarEntry(byte[] headerBuffer) + { + header = new TarHeader(); + header.ParseBuffer(headerBuffer); + } + + /// + /// Construct a TarEntry using the header provided + /// + /// Header details for entry + public TarEntry(TarHeader header) + { + if ( header == null ) + { + throw new ArgumentNullException("header"); + } + + this.header = (TarHeader)header.Clone(); + } + #endregion + + #region ICloneable Members + /// + /// Clone this tar entry. + /// + /// Returns a clone of this entry. + public object Clone() + { + TarEntry entry = new TarEntry(); + entry.file = file; + entry.header = (TarHeader)header.Clone(); + entry.Name = Name; + return entry; + } + #endregion + + /// + /// Construct an entry with only a name. + /// This allows the programmer to construct the entry's header "by hand". + /// + /// The name to use for the entry + /// Returns the newly created + public static TarEntry CreateTarEntry(string name) + { + TarEntry entry = new TarEntry(); + TarEntry.NameTarHeader(entry.header, name); + return entry; + } + + /// + /// Construct an entry for a file. File is set to file, and the + /// header is constructed from information from the file. + /// + /// The file name that the entry represents. + /// Returns the newly created + public static TarEntry CreateEntryFromFile(string fileName) + { + TarEntry entry = new TarEntry(); + entry.GetFileTarHeader(entry.header, fileName); + return entry; + } + + /// + /// Determine if the two entries are equal. Equality is determined + /// by the header names being equal. + /// + /// The to compare with the current Object. + /// + /// True if the entries are equal; false if not. + /// + public override bool Equals(object obj) + { + TarEntry localEntry = obj as TarEntry; + + if ( localEntry != null ) + { + return Name.Equals(localEntry.Name); + } + return false; + } + + /// + /// Derive a Hash value for the current + /// + /// A Hash code for the current + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + /// Determine if the given entry is a descendant of this entry. + /// Descendancy is determined by the name of the descendant + /// starting with this entry's name. + /// + /// + /// Entry to be checked as a descendent of this. + /// + /// + /// True if entry is a descendant of this. + /// + public bool IsDescendent(TarEntry toTest) + { + if ( toTest == null ) { + throw new ArgumentNullException("toTest"); + } + + return toTest.Name.StartsWith(Name); + } + + /// + /// Get this entry's header. + /// + /// + /// This entry's TarHeader. + /// + public TarHeader TarHeader + { + get { + return header; + } + } + + /// + /// Get/Set this entry's name. + /// + public string Name + { + get { + return header.Name; + } + set { + header.Name = value; + } + } + + /// + /// Get/set this entry's user id. + /// + public int UserId + { + get { + return header.UserId; + } + set { + header.UserId = value; + } + } + + /// + /// Get/set this entry's group id. + /// + public int GroupId + { + get { + return header.GroupId; + } + set { + header.GroupId = value; + } + } + + /// + /// Get/set this entry's user name. + /// + public string UserName + { + get { + return header.UserName; + } + set { + header.UserName = value; + } + } + + /// + /// Get/set this entry's group name. + /// + public string GroupName + { + get { + return header.GroupName; + } + set { + header.GroupName = value; + } + } + + /// + /// Convenience method to set this entry's group and user ids. + /// + /// + /// This entry's new user id. + /// + /// + /// This entry's new group id. + /// + public void SetIds(int userId, int groupId) + { + UserId = userId; + GroupId = groupId; + } + + /// + /// Convenience method to set this entry's group and user names. + /// + /// + /// This entry's new user name. + /// + /// + /// This entry's new group name. + /// + public void SetNames(string userName, string groupName) + { + UserName = userName; + GroupName = groupName; + } + + /// + /// Get/Set the modification time for this entry + /// + public DateTime ModTime { + get { + return header.ModTime; + } + set { + header.ModTime = value; + } + } + + /// + /// Get this entry's file. + /// + /// + /// This entry's file. + /// + public string File { + get { + return file; + } + } + + /// + /// Get/set this entry's recorded file size. + /// + public long Size { + get { + return header.Size; + } + set { + header.Size = value; + } + } + + /// + /// Return true if this entry represents a directory, false otherwise + /// + /// + /// True if this entry is a directory. + /// + public bool IsDirectory { + get { + if (file != null) { + return Directory.Exists(file); + } + + if (header != null) { + if ((header.TypeFlag == TarHeader.LF_DIR) || Name.EndsWith( "/" )) { + return true; + } + } + return false; + } + } + + /// + /// Fill in a TarHeader with information from a File. + /// + /// + /// The TarHeader to fill in. + /// + /// + /// The file from which to get the header information. + /// + public void GetFileTarHeader(TarHeader header, string file) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( file == null ) { + throw new ArgumentNullException("file"); + } + + this.file = file; + + // bugfix from torhovl from #D forum: + string name = file; + +#if !NETCF_1_0 && !NETCF_2_0 + // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory + if (name.IndexOf(Environment.CurrentDirectory) == 0) { + name = name.Substring(Environment.CurrentDirectory.Length); + } +#endif + +/* + if (Path.DirectorySeparatorChar == '\\') + { + // check if the OS is Windows + // Strip off drive letters! + if (name.Length > 2) + { + char ch1 = name[0]; + char ch2 = name[1]; + + if (ch2 == ':' && Char.IsLetter(ch1)) + { + name = name.Substring(2); + } + } + } +*/ + + name = name.Replace(Path.DirectorySeparatorChar, '/'); + + // No absolute pathnames + // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\", + // so we loop on starting /'s. + while (name.StartsWith("/")) { + name = name.Substring(1); + } + + header.LinkName = String.Empty; + header.Name = name; + + if (Directory.Exists(file)) { + header.Mode = 1003; // Magic number for security access for a UNIX filesystem + header.TypeFlag = TarHeader.LF_DIR; + if ( (header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') { + header.Name = header.Name + "/"; + } + + header.Size = 0; + } else { + header.Mode = 33216; // Magic number for security access for a UNIX filesystem + header.TypeFlag = TarHeader.LF_NORMAL; + header.Size = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length; + } + + header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime(); + header.DevMajor = 0; + header.DevMinor = 0; + } + + /// + /// Get entries for all files present in this entries directory. + /// If this entry doesnt represent a directory zero entries are returned. + /// + /// + /// An array of TarEntry's for this entry's children. + /// + public TarEntry[] GetDirectoryEntries() + { + if ( (file == null) || !Directory.Exists(file)) { + return new TarEntry[0]; + } + + string[] list = Directory.GetFileSystemEntries(file); + TarEntry[] result = new TarEntry[list.Length]; + + for (int i = 0; i < list.Length; ++i) { + result[i] = TarEntry.CreateEntryFromFile(list[i]); + } + + return result; + } + + /// + /// Write an entry's header information to a header buffer. + /// + /// + /// The tar entry header buffer to fill in. + /// + public void WriteEntryHeader(byte[] outBuffer) + { + header.WriteHeader(outBuffer); + } + + /// + /// Convenience method that will modify an entry's name directly + /// in place in an entry header buffer byte array. + /// + /// + /// The buffer containing the entry header to modify. + /// + /// + /// The new name to place into the header buffer. + /// + static public void AdjustEntryName(byte[] buffer, string newName) + { + TarHeader.GetNameBytes(newName, buffer, 0, TarHeader.NAMELEN); + } + + /// + /// Fill in a TarHeader given only the entry's name. + /// + /// + /// The TarHeader to fill in. + /// + /// + /// The tar entry name. + /// + static public void NameTarHeader(TarHeader header, string name) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + bool isDir = name.EndsWith("/"); + + header.Name = name; + header.Mode = isDir ? 1003 : 33216; + header.UserId = 0; + header.GroupId = 0; + header.Size = 0; + + header.ModTime = DateTime.UtcNow; + + header.TypeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL; + + header.LinkName = String.Empty; + header.UserName = String.Empty; + header.GroupName = String.Empty; + + header.DevMajor = 0; + header.DevMinor = 0; + } + + #region Instance Fields + /// + /// The name of the file this entry represents or null if the entry is not based on a file. + /// + string file; + + /// + /// The entry's header information. + /// + TarHeader header; + #endregion + } +} + + + +/* The original Java file had this header: + * + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/OnlineRepair/ZIP/Tar/TarException.cs b/类库/OnlineRepair/ZIP/Tar/TarException.cs new file mode 100644 index 0000000..84a6eba --- /dev/null +++ b/类库/OnlineRepair/ZIP/Tar/TarException.cs @@ -0,0 +1,91 @@ +// TarException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Tar { + + /// + /// TarExceptions are used for exceptions specific to tar classes and code. + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class TarException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected TarException(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + + /// + /// Initialises a new instance of the TarException class. + /// + public TarException() + { + } + + /// + /// Initialises a new instance of the TarException class with a specified message. + /// + /// The message that describes the error. + public TarException(string message) + : base(message) + { + } + + /// + /// + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public TarException(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/OnlineRepair/ZIP/Tar/TarHeader.cs b/类库/OnlineRepair/ZIP/Tar/TarHeader.cs new file mode 100644 index 0000000..fc49f16 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Tar/TarHeader.cs @@ -0,0 +1,1156 @@ +// TarHeader.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +/* The tar format and its POSIX successor PAX have a long history which makes for compatability + issues when creating and reading files. + + This is further complicated by a large number of programs with variations on formats + One common issue is the handling of names longer than 100 characters. + GNU style long names are currently supported. + +This is the ustar (Posix 1003.1) header. + +struct header +{ + char t_name[100]; // 0 Filename + char t_mode[8]; // 100 Permissions + char t_uid[8]; // 108 Numerical User ID + char t_gid[8]; // 116 Numerical Group ID + char t_size[12]; // 124 Filesize + char t_mtime[12]; // 136 st_mtime + char t_chksum[8]; // 148 Checksum + char t_typeflag; // 156 Type of File + char t_linkname[100]; // 157 Target of Links + char t_magic[6]; // 257 "ustar" or other... + char t_version[2]; // 263 Version fixed to 00 + char t_uname[32]; // 265 User Name + char t_gname[32]; // 297 Group Name + char t_devmajor[8]; // 329 Major for devices + char t_devminor[8]; // 337 Minor for devices + char t_prefix[155]; // 345 Prefix for t_name + char t_mfill[12]; // 500 Filler up to 512 +}; + +*/ + +using System; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + + /// + /// This class encapsulates the Tar Entry Header used in Tar Archives. + /// The class also holds a number of tar constants, used mostly in headers. + /// + public class TarHeader : ICloneable + { + #region Constants + /// + /// The length of the name field in a header buffer. + /// + public const int NAMELEN = 100; + + /// + /// The length of the mode field in a header buffer. + /// + public const int MODELEN = 8; + + /// + /// The length of the user id field in a header buffer. + /// + public const int UIDLEN = 8; + + /// + /// The length of the group id field in a header buffer. + /// + public const int GIDLEN = 8; + + /// + /// The length of the checksum field in a header buffer. + /// + public const int CHKSUMLEN = 8; + + /// + /// Offset of checksum in a header buffer. + /// + public const int CHKSUMOFS = 148; + + /// + /// The length of the size field in a header buffer. + /// + public const int SIZELEN = 12; + + /// + /// The length of the magic field in a header buffer. + /// + public const int MAGICLEN = 6; + + /// + /// The length of the version field in a header buffer. + /// + public const int VERSIONLEN = 2; + + /// + /// The length of the modification time field in a header buffer. + /// + public const int MODTIMELEN = 12; + + /// + /// The length of the user name field in a header buffer. + /// + public const int UNAMELEN = 32; + + /// + /// The length of the group name field in a header buffer. + /// + public const int GNAMELEN = 32; + + /// + /// The length of the devices field in a header buffer. + /// + public const int DEVLEN = 8; + + // + // LF_ constants represent the "type" of an entry + // + + /// + /// The "old way" of indicating a normal file. + /// + public const byte LF_OLDNORM = 0; + + /// + /// Normal file type. + /// + public const byte LF_NORMAL = (byte) '0'; + + /// + /// Link file type. + /// + public const byte LF_LINK = (byte) '1'; + + /// + /// Symbolic link file type. + /// + public const byte LF_SYMLINK = (byte) '2'; + + /// + /// Character device file type. + /// + public const byte LF_CHR = (byte) '3'; + + /// + /// Block device file type. + /// + public const byte LF_BLK = (byte) '4'; + + /// + /// Directory file type. + /// + public const byte LF_DIR = (byte) '5'; + + /// + /// FIFO (pipe) file type. + /// + public const byte LF_FIFO = (byte) '6'; + + /// + /// Contiguous file type. + /// + public const byte LF_CONTIG = (byte) '7'; + + /// + /// Posix.1 2001 global extended header + /// + public const byte LF_GHDR = (byte) 'g'; + + /// + /// Posix.1 2001 extended header + /// + public const byte LF_XHDR = (byte) 'x'; + + // POSIX allows for upper case ascii type as extensions + + /// + /// Solaris access control list file type + /// + public const byte LF_ACL = (byte) 'A'; + + /// + /// GNU dir dump file type + /// This is a dir entry that contains the names of files that were in the + /// dir at the time the dump was made + /// + public const byte LF_GNU_DUMPDIR = (byte) 'D'; + + /// + /// Solaris Extended Attribute File + /// + public const byte LF_EXTATTR = (byte) 'E' ; + + /// + /// Inode (metadata only) no file content + /// + public const byte LF_META = (byte) 'I'; + + /// + /// Identifies the next file on the tape as having a long link name + /// + public const byte LF_GNU_LONGLINK = (byte) 'K'; + + /// + /// Identifies the next file on the tape as having a long name + /// + public const byte LF_GNU_LONGNAME = (byte) 'L'; + + /// + /// Continuation of a file that began on another volume + /// + public const byte LF_GNU_MULTIVOL = (byte) 'M'; + + /// + /// For storing filenames that dont fit in the main header (old GNU) + /// + public const byte LF_GNU_NAMES = (byte) 'N'; + + /// + /// GNU Sparse file + /// + public const byte LF_GNU_SPARSE = (byte) 'S'; + + /// + /// GNU Tape/volume header ignore on extraction + /// + public const byte LF_GNU_VOLHDR = (byte) 'V'; + + /// + /// The magic tag representing a POSIX tar archive. (includes trailing NULL) + /// + public const string TMAGIC = "ustar "; + + /// + /// The magic tag representing an old GNU tar archive where version is included in magic and overwrites it + /// + public const string GNU_TMAGIC = "ustar "; + + const long timeConversionFactor = 10000000L; // 1 tick == 100 nanoseconds + readonly static DateTime dateTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0); + #endregion + + #region Constructors + + /// + /// Initialise a default TarHeader instance + /// + public TarHeader() + { + Magic = TMAGIC; + Version = " "; + + Name = ""; + LinkName = ""; + + UserId = defaultUserId; + GroupId = defaultGroupId; + UserName = defaultUser; + GroupName = defaultGroupName; + Size = 0; + } + + #endregion + + #region Properties + /// + /// Get/set the name for this tar entry. + /// + /// Thrown when attempting to set the property to null. + public string Name + { + get { return name; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + name = value; + } + } + + /// + /// Get the name of this entry. + /// + /// The entry's name. + [Obsolete("Use the Name property instead", true)] + public string GetName() + { + return name; + } + + /// + /// Get/set the entry's Unix style permission mode. + /// + public int Mode + { + get { return mode; } + set { mode = value; } + } + + + /// + /// The entry's user id. + /// + /// + /// This is only directly relevant to unix systems. + /// The default is zero. + /// + public int UserId + { + get { return userId; } + set { userId = value; } + } + + + /// + /// Get/set the entry's group id. + /// + /// + /// This is only directly relevant to linux/unix systems. + /// The default value is zero. + /// + public int GroupId + { + get { return groupId; } + set { groupId = value; } + } + + + /// + /// Get/set the entry's size. + /// + /// Thrown when setting the size to less than zero. + public long Size + { + get { return size; } + set { + if ( value < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Cannot be less than zero"); +#endif + } + size = value; + } + } + + + /// + /// Get/set the entry's modification time. + /// + /// + /// The modification time is only accurate to within a second. + /// + /// Thrown when setting the date time to less than 1/1/1970. + public DateTime ModTime + { + get { return modTime; } + set { + if ( value < dateTime1970 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "ModTime cannot be before Jan 1st 1970"); +#endif + } + modTime = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second); + } + } + + + /// + /// Get the entry's checksum. This is only valid/updated after writing or reading an entry. + /// + public int Checksum + { + get { return checksum; } + } + + + /// + /// Get value of true if the header checksum is valid, false otherwise. + /// + public bool IsChecksumValid + { + get { return isChecksumValid; } + } + + + /// + /// Get/set the entry's type flag. + /// + public byte TypeFlag + { + get { return typeFlag; } + set { typeFlag = value; } + } + + + /// + /// The entry's link name. + /// + /// Thrown when attempting to set LinkName to null. + public string LinkName + { + get { return linkName; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + linkName = value; + } + } + + + /// + /// Get/set the entry's magic tag. + /// + /// Thrown when attempting to set Magic to null. + public string Magic + { + get { return magic; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + magic = value; + } + } + + + /// + /// The entry's version. + /// + /// Thrown when attempting to set Version to null. + public string Version + { + get { + return version; + } + + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + version = value; + } + } + + + /// + /// The entry's user name. + /// + public string UserName + { + get { return userName; } + set { + if (value != null) { + userName = value.Substring(0, Math.Min(UNAMELEN, value.Length)); + } + else { +#if NETCF_1_0 || NETCF_2_0 + string currentUser = "PocketPC"; +#else + string currentUser = Environment.UserName; +#endif + if (currentUser.Length > UNAMELEN) { + currentUser = currentUser.Substring(0, UNAMELEN); + } + userName = currentUser; + } + } + } + + + /// + /// Get/set the entry's group name. + /// + /// + /// This is only directly relevant to unix systems. + /// + public string GroupName + { + get { return groupName; } + set { + if ( value == null ) { + groupName = "None"; + } + else { + groupName = value; + } + } + } + + + /// + /// Get/set the entry's major device number. + /// + public int DevMajor + { + get { return devMajor; } + set { devMajor = value; } + } + + + /// + /// Get/set the entry's minor device number. + /// + public int DevMinor + { + get { return devMinor; } + set { devMinor = value; } + } + + #endregion + + #region ICloneable Members + /// + /// Create a new that is a copy of the current instance. + /// + /// A new that is a copy of the current instance. + public object Clone() + { + return MemberwiseClone(); + } + #endregion + + /// + /// Parse TarHeader information from a header buffer. + /// + /// + /// The tar entry header buffer to get information from. + /// + public void ParseBuffer(byte[] header) + { + if ( header == null ) + { + throw new ArgumentNullException("header"); + } + + int offset = 0; + + name = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString(); + offset += TarHeader.NAMELEN; + + mode = (int)TarHeader.ParseOctal(header, offset, TarHeader.MODELEN); + offset += TarHeader.MODELEN; + + UserId = (int)TarHeader.ParseOctal(header, offset, TarHeader.UIDLEN); + offset += TarHeader.UIDLEN; + + GroupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN); + offset += TarHeader.GIDLEN; + + Size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN); + offset += TarHeader.SIZELEN; + + ModTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN)); + offset += TarHeader.MODTIMELEN; + + checksum = (int)TarHeader.ParseOctal(header, offset, TarHeader.CHKSUMLEN); + offset += TarHeader.CHKSUMLEN; + + TypeFlag = header[ offset++ ]; + + LinkName = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString(); + offset += TarHeader.NAMELEN; + + Magic = TarHeader.ParseName(header, offset, TarHeader.MAGICLEN).ToString(); + offset += TarHeader.MAGICLEN; + + Version = TarHeader.ParseName(header, offset, TarHeader.VERSIONLEN).ToString(); + offset += TarHeader.VERSIONLEN; + + UserName = TarHeader.ParseName(header, offset, TarHeader.UNAMELEN).ToString(); + offset += TarHeader.UNAMELEN; + + GroupName = TarHeader.ParseName(header, offset, TarHeader.GNAMELEN).ToString(); + offset += TarHeader.GNAMELEN; + + DevMajor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN); + offset += TarHeader.DEVLEN; + + DevMinor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN); + + // Fields past this point not currently parsed or used... + + isChecksumValid = Checksum == TarHeader.MakeCheckSum(header); + } + + /// + /// 'Write' header information to buffer provided, updating the check sum. + /// + /// output buffer for header information + public void WriteHeader(byte[] outBuffer) + { + if ( outBuffer == null ) + { + throw new ArgumentNullException("outBuffer"); + } + + int offset = 0; + + offset = GetNameBytes(Name, outBuffer, offset, NAMELEN); + offset = GetOctalBytes(mode, outBuffer, offset, MODELEN); + offset = GetOctalBytes(UserId, outBuffer, offset, UIDLEN); + offset = GetOctalBytes(GroupId, outBuffer, offset, GIDLEN); + + offset = GetLongOctalBytes(Size, outBuffer, offset, SIZELEN); + offset = GetLongOctalBytes(GetCTime(ModTime), outBuffer, offset, MODTIMELEN); + + int csOffset = offset; + for (int c = 0; c < CHKSUMLEN; ++c) + { + outBuffer[offset++] = (byte)' '; + } + + outBuffer[offset++] = TypeFlag; + + offset = GetNameBytes(LinkName, outBuffer, offset, NAMELEN); + offset = GetAsciiBytes(Magic, 0, outBuffer, offset, MAGICLEN); + offset = GetNameBytes(Version, outBuffer, offset, VERSIONLEN); + offset = GetNameBytes(UserName, outBuffer, offset, UNAMELEN); + offset = GetNameBytes(GroupName, outBuffer, offset, GNAMELEN); + + if ((TypeFlag == LF_CHR) || (TypeFlag == LF_BLK)) + { + offset = GetOctalBytes(DevMajor, outBuffer, offset, DEVLEN); + offset = GetOctalBytes(DevMinor, outBuffer, offset, DEVLEN); + } + + for ( ; offset < outBuffer.Length; ) + { + outBuffer[offset++] = 0; + } + + checksum = ComputeCheckSum(outBuffer); + + GetCheckSumOctalBytes(checksum, outBuffer, csOffset, CHKSUMLEN); + isChecksumValid = true; + } + + /// + /// Get a hash code for the current object. + /// + /// A hash code for the current object. + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + /// Determines if this instance is equal to the specified object. + /// + /// The object to compare with. + /// true if the objects are equal, false otherwise. + public override bool Equals(object obj) + { + TarHeader localHeader = obj as TarHeader; + + bool result; + if ( localHeader != null ) + { + result = (name == localHeader.name) + && (mode == localHeader.mode) + && (UserId == localHeader.UserId) + && (GroupId == localHeader.GroupId) + && (Size == localHeader.Size) + && (ModTime == localHeader.ModTime) + && (Checksum == localHeader.Checksum) + && (TypeFlag == localHeader.TypeFlag) + && (LinkName == localHeader.LinkName) + && (Magic == localHeader.Magic) + && (Version == localHeader.Version) + && (UserName == localHeader.UserName) + && (GroupName == localHeader.GroupName) + && (DevMajor == localHeader.DevMajor) + && (DevMinor == localHeader.DevMinor); + } + else + { + result = false; + } + return result; + } + + /// + /// Set defaults for values used when constructing a TarHeader instance. + /// + /// Value to apply as a default for userId. + /// Value to apply as a default for userName. + /// Value to apply as a default for groupId. + /// Value to apply as a default for groupName. + static internal void SetValueDefaults(int userId, string userName, int groupId, string groupName) + { + defaultUserId = userIdAsSet = userId; + defaultUser = userNameAsSet = userName; + defaultGroupId = groupIdAsSet = groupId; + defaultGroupName = groupNameAsSet = groupName; + } + + static internal void RestoreSetValues() + { + defaultUserId = userIdAsSet; + defaultUser = userNameAsSet; + defaultGroupId = groupIdAsSet; + defaultGroupName = groupNameAsSet; + } + + /// + /// Parse an octal string from a header buffer. + /// + /// The header buffer from which to parse. + /// The offset into the buffer from which to parse. + /// The number of header bytes to parse. + /// The long equivalent of the octal string. + static public long ParseOctal(byte[] header, int offset, int length) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + long result = 0; + bool stillPadding = true; + + int end = offset + length; + for (int i = offset; i < end ; ++i) { + if (header[i] == 0) { + break; + } + + if (header[i] == (byte)' ' || header[i] == '0') { + if (stillPadding) { + continue; + } + + if (header[i] == (byte)' ') { + break; + } + } + + stillPadding = false; + + result = (result << 3) + (header[i] - '0'); + } + + return result; + } + + /// + /// Parse a name from a header buffer. + /// + /// + /// The header buffer from which to parse. + /// + /// + /// The offset into the buffer from which to parse. + /// + /// + /// The number of header bytes to parse. + /// + /// + /// The name parsed. + /// + static public StringBuilder ParseName(byte[] header, int offset, int length) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be less than zero"); +#endif + } + + if ( length < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("length"); +#else + throw new ArgumentOutOfRangeException("length", "Cannot be less than zero"); +#endif + } + + if ( offset + length > header.Length ) + { + throw new ArgumentException("Exceeds header size", "length"); + } + + StringBuilder result = new StringBuilder(length); + + for (int i = offset; i < offset + length; ++i) { + if (header[i] == 0) { + break; + } + result.Append((char)header[i]); + } + + return result; + } + + /// + /// Add name to the buffer as a collection of bytes + /// + /// The name to add + /// The offset of the first character + /// The buffer to add to + /// The index of the first byte to add + /// The number of characters/bytes to add + /// The next free index in the + public static int GetNameBytes(StringBuilder name, int nameOffset, byte[] buffer, int bufferOffset, int length) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name.ToString(), nameOffset, buffer, bufferOffset, length); + } + + /// + /// Add name to the buffer as a collection of bytes + /// + /// The name to add + /// The offset of the first character + /// The buffer to add to + /// The index of the first byte to add + /// The number of characters/bytes to add + /// The next free index in the + public static int GetNameBytes(string name, int nameOffset, byte[] buffer, int bufferOffset, int length) + { + if ( name == null ) + { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + int i; + + for (i = 0 ; i < length - 1 && nameOffset + i < name.Length; ++i) { + buffer[bufferOffset + i] = (byte)name[nameOffset + i]; + } + + for (; i < length ; ++i) { + buffer[bufferOffset + i] = 0; + } + + return bufferOffset + length; + } + + /// + /// Add an entry name to the buffer + /// + /// + /// The name to add + /// + /// + /// The buffer to add to + /// + /// + /// The offset into the buffer from which to start adding + /// + /// + /// The number of header bytes to add + /// + /// + /// The index of the next free byte in the buffer + /// + public static int GetNameBytes(StringBuilder name, byte[] buffer, int offset, int length) + { + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name.ToString(), 0, buffer, offset, length); + } + + /// + /// Add an entry name to the buffer + /// + /// The name to add + /// The buffer to add to + /// The offset into the buffer from which to start adding + /// The number of header bytes to add + /// The index of the next free byte in the buffer + public static int GetNameBytes(string name, byte[] buffer, int offset, int length) + { + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name, 0, buffer, offset, length); + } + + /// + /// Add a string to a buffer as a collection of ascii bytes. + /// + /// The string to add + /// The offset of the first character to add. + /// The buffer to add to. + /// The offset to start adding at. + /// The number of ascii characters to add. + /// The next free index in the buffer. + public static int GetAsciiBytes(string toAdd, int nameOffset, byte[] buffer, int bufferOffset, int length ) + { + if ( toAdd == null ) { + throw new ArgumentNullException("toAdd"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + for (int i = 0 ; i < length && nameOffset + i < toAdd.Length; ++i) + { + buffer[bufferOffset + i] = (byte)toAdd[nameOffset + i]; + } + return bufferOffset + length; + } + + /// + /// Put an octal representation of a value into a buffer + /// + /// + /// the value to be converted to octal + /// + /// + /// buffer to store the octal string + /// + /// + /// The offset into the buffer where the value starts + /// + /// + /// The length of the octal string to create + /// + /// + /// The offset of the character next byte after the octal string + /// + public static int GetOctalBytes(long value, byte[] buffer, int offset, int length) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + int localIndex = length - 1; + + // Either a space or null is valid here. We use NULL as per GNUTar + buffer[offset + localIndex] = 0; + --localIndex; + + if (value > 0) { + for ( long v = value; (localIndex >= 0) && (v > 0); --localIndex ) { + buffer[offset + localIndex] = (byte)((byte)'0' + (byte)(v & 7)); + v >>= 3; + } + } + + for ( ; localIndex >= 0; --localIndex ) { + buffer[offset + localIndex] = (byte)'0'; + } + + return offset + length; + } + + /// + /// Put an octal representation of a value into a buffer + /// + /// Value to be convert to octal + /// The buffer to update + /// The offset into the buffer to store the value + /// The length of the octal string + /// Index of next byte + public static int GetLongOctalBytes(long value, byte[] buffer, int offset, int length) + { + return GetOctalBytes(value, buffer, offset, length); + } + + /// + /// Add the checksum integer to header buffer. + /// + /// + /// The header buffer to set the checksum for + /// The offset into the buffer for the checksum + /// The number of header bytes to update. + /// It's formatted differently from the other fields: it has 6 digits, a + /// null, then a space -- rather than digits, a space, then a null. + /// The final space is already there, from checksumming + /// + /// The modified buffer offset + static int GetCheckSumOctalBytes(long value, byte[] buffer, int offset, int length) + { + TarHeader.GetOctalBytes(value, buffer, offset, length - 1); + return offset + length; + } + + /// + /// Compute the checksum for a tar entry header. + /// The checksum field must be all spaces prior to this happening + /// + /// The tar entry's header buffer. + /// The computed checksum. + static int ComputeCheckSum(byte[] buffer) + { + int sum = 0; + for (int i = 0; i < buffer.Length; ++i) { + sum += buffer[i]; + } + return sum; + } + + /// + /// Make a checksum for a tar entry ignoring the checksum contents. + /// + /// The tar entry's header buffer. + /// The checksum for the buffer + static int MakeCheckSum(byte[] buffer) + { + int sum = 0; + for ( int i = 0; i < CHKSUMOFS; ++i ) + { + sum += buffer[i]; + } + + for ( int i = 0; i < TarHeader.CHKSUMLEN; ++i) + { + sum += (byte)' '; + } + + for (int i = CHKSUMOFS + CHKSUMLEN; i < buffer.Length; ++i) + { + sum += buffer[i]; + } + return sum; + } + + static int GetCTime(System.DateTime dateTime) + { + return unchecked((int)((dateTime.Ticks - dateTime1970.Ticks) / timeConversionFactor)); + } + + static DateTime GetDateTimeFromCTime(long ticks) + { + DateTime result; + + try { + result = new DateTime(dateTime1970.Ticks + ticks * timeConversionFactor); + } + catch(ArgumentOutOfRangeException) { + result = dateTime1970; + } + return result; + } + + #region Instance Fields + string name; + int mode; + int userId; + int groupId; + long size; + DateTime modTime; + int checksum; + bool isChecksumValid; + byte typeFlag; + string linkName; + string magic; + string version; + string userName; + string groupName; + int devMajor; + int devMinor; + #endregion + + #region Class Fields + // Values used during recursive operations. + static internal int userIdAsSet; + static internal int groupIdAsSet; + static internal string userNameAsSet; + static internal string groupNameAsSet = "None"; + + static internal int defaultUserId; + static internal int defaultGroupId; + static internal string defaultGroupName = "None"; + static internal string defaultUser; + #endregion + } +} + +/* The original Java file had this header: + * +** Authored by Timothy Gerard Endres +** +** +** This work has been placed into the public domain. +** You may use this work in any way and for any purpose you wish. +** +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR +** REDISTRIBUTION OF THIS SOFTWARE. +** +*/ diff --git a/类库/OnlineRepair/ZIP/Tar/TarInputStream.cs b/类库/OnlineRepair/ZIP/Tar/TarInputStream.cs new file mode 100644 index 0000000..436b002 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Tar/TarInputStream.cs @@ -0,0 +1,695 @@ +// TarInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarInputStream reads a UNIX tar archive as an InputStream. + /// methods are provided to position at each successive entry in + /// the archive, and the read each entry as a normal input stream + /// using read(). + /// + public class TarInputStream : Stream + { + #region Constructors + /// + /// Construct a TarInputStream with default block factor + /// + /// stream to source data from + public TarInputStream(Stream inputStream) + : this(inputStream, TarBuffer.DefaultBlockFactor) + { + } + + /// + /// Construct a TarInputStream with user specified block factor + /// + /// stream to source data from + /// block factor to apply to archive + public TarInputStream(Stream inputStream, int blockFactor) + { + this.inputStream = inputStream; + tarBuffer = TarBuffer.CreateInputTarBuffer(inputStream, blockFactor); + } + + #endregion + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return tarBuffer.IsStreamOwner; } + set { tarBuffer.IsStreamOwner = value; } + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return inputStream.CanRead; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking + /// This property always returns false. + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value indicating if the stream supports writing. + /// This property always returns false. + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// The length in bytes of the stream + /// + public override long Length { + get { + return inputStream.Length; + } + } + + /// + /// Gets or sets the position within the stream. + /// Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException + /// + /// Any attempt to set position + public override long Position { + get { + return inputStream.Position; + } + set { + throw new NotSupportedException("TarInputStream Seek not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + inputStream.Flush(); + } + + /// + /// Set the streams position. This operation is not supported and will throw a NotSupportedException + /// + /// The offset relative to the origin to seek to. + /// The to start seeking from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("TarInputStream Seek not supported"); + } + + /// + /// Sets the length of the stream + /// This operation is not supported and will throw a NotSupportedException + /// + /// The new stream length. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("TarInputStream SetLength not supported"); + } + + /// + /// Writes a block of bytes to this stream using data from a buffer. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The buffer containing bytes to write. + /// The offset in the buffer of the frist byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("TarInputStream Write not supported"); + } + + /// + /// Writes a byte to the current position in the file stream. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The byte value to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("TarInputStream WriteByte not supported"); + } + /// + /// Reads a byte from the current tar archive entry. + /// + /// A byte cast to an int; -1 if the at the end of the stream. + public override int ReadByte() + { + byte[] oneByteBuffer = new byte[1]; + int num = Read(oneByteBuffer, 0, 1); + if (num <= 0) + { + // return -1 to indicate that no byte was read. + return -1; + } + return oneByteBuffer[0]; + } + + /// + /// Reads bytes from the current tar archive entry. + /// + /// This method is aware of the boundaries of the current + /// entry in the archive and will deal with them appropriately + /// + /// + /// The buffer into which to place bytes read. + /// + /// + /// The offset at which to place bytes read. + /// + /// + /// The number of bytes to read. + /// + /// + /// The number of bytes read, or 0 at end of stream/EOF. + /// + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + int totalRead = 0; + + if (entryOffset >= entrySize) + { + return 0; + } + + long numToRead = count; + + if ((numToRead + entryOffset) > entrySize) + { + numToRead = entrySize - entryOffset; + } + + if (readBuffer != null) + { + int sz = (numToRead > readBuffer.Length) ? readBuffer.Length : (int)numToRead; + + Array.Copy(readBuffer, 0, buffer, offset, sz); + + if (sz >= readBuffer.Length) + { + readBuffer = null; + } + else + { + int newLen = readBuffer.Length - sz; + byte[] newBuf = new byte[newLen]; + Array.Copy(readBuffer, sz, newBuf, 0, newLen); + readBuffer = newBuf; + } + + totalRead += sz; + numToRead -= sz; + offset += sz; + } + + while (numToRead > 0) + { + byte[] rec = tarBuffer.ReadBlock(); + if (rec == null) + { + // Unexpected EOF! + throw new TarException("unexpected EOF with " + numToRead + " bytes unread"); + } + + int sz = (int)numToRead; + int recLen = rec.Length; + + if (recLen > sz) + { + Array.Copy(rec, 0, buffer, offset, sz); + readBuffer = new byte[recLen - sz]; + Array.Copy(rec, sz, readBuffer, 0, recLen - sz); + } + else + { + sz = recLen; + Array.Copy(rec, 0, buffer, offset, recLen); + } + + totalRead += sz; + numToRead -= sz; + offset += sz; + } + + entryOffset += totalRead; + + return totalRead; + } + + /// + /// Closes this stream. Calls the TarBuffer's close() method. + /// The underlying stream is closed by the TarBuffer. + /// + public override void Close() + { + tarBuffer.Close(); + } + + #endregion + + /// + /// Set the entry factory for this instance. + /// + /// The factory for creating new entries + public void SetEntryFactory(IEntryFactory factory) + { + entryFactory = factory; + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + public int RecordSize + { + get { return tarBuffer.RecordSize; } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + /// + /// TarBuffer record size. + /// + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return tarBuffer.RecordSize; + } + + /// + /// Get the available data that can be read from the current + /// entry in the archive. This does not indicate how much data + /// is left in the entire archive, only in the current entry. + /// This value is determined from the entry's size header field + /// and the amount of data already read from the current entry. + /// + /// + /// The number of available bytes for the current entry. + /// + public long Available { + get { + return entrySize - entryOffset; + } + } + + /// + /// Skip bytes in the input buffer. This skips bytes in the + /// current entry's data, not the entire archive, and will + /// stop at the end of the current entry's data if the number + /// to skip extends beyond that point. + /// + /// + /// The number of bytes to skip. + /// + public void Skip(long skipCount) + { + // TODO: REVIEW efficiency of TarInputStream.Skip + // This is horribly inefficient, but it ensures that we + // properly skip over bytes via the TarBuffer... + // + byte[] skipBuf = new byte[8 * 1024]; + + for (long num = skipCount; num > 0;) { + int toRead = num > skipBuf.Length ? skipBuf.Length : (int)num; + int numRead = Read(skipBuf, 0, toRead); + + if (numRead == -1) { + break; + } + + num -= numRead; + } + } + + /// + /// Return a value of true if marking is supported; false otherwise. + /// + /// Currently marking is not supported, the return value is always false. + public bool IsMarkSupported { + get { + return false; + } + } + + /// + /// Since we do not support marking just yet, we do nothing. + /// + /// + /// The limit to mark. + /// + public void Mark(int markLimit) + { + } + + /// + /// Since we do not support marking just yet, we do nothing. + /// + public void Reset() + { + } + + /// + /// Get the next entry in this tar archive. This will skip + /// over any remaining data in the current entry, if there + /// is one, and place the input stream at the header of the + /// next entry, and read the header and instantiate a new + /// TarEntry from the header bytes and return that entry. + /// If there are no more entries in the archive, null will + /// be returned to indicate that the end of the archive has + /// been reached. + /// + /// + /// The next TarEntry in the archive, or null. + /// + public TarEntry GetNextEntry() + { + if (hasHitEOF) { + return null; + } + + if (currentEntry != null) { + SkipToNextEntry(); + } + + byte[] headerBuf = tarBuffer.ReadBlock(); + + if (headerBuf == null) { + hasHitEOF = true; + } else if (TarBuffer.IsEndOfArchiveBlock(headerBuf)) { + hasHitEOF = true; + } + + if (hasHitEOF) { + currentEntry = null; + } else { + try { + TarHeader header = new TarHeader(); + header.ParseBuffer(headerBuf); + if ( !header.IsChecksumValid ) + { + throw new TarException("Header checksum is invalid"); + } + this.entryOffset = 0; + this.entrySize = header.Size; + + StringBuilder longName = null; + + if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME) { + + byte[] nameBuffer = new byte[TarBuffer.BlockSize]; + long numToRead = this.entrySize; + + longName = new StringBuilder(); + + while (numToRead > 0) { + int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead)); + + if (numRead == -1) { + throw new InvalidHeaderException("Failed to read long name entry"); + } + + longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString()); + numToRead -= numRead; + } + + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_GHDR) { // POSIX global extended header + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_XHDR) { // POSIX extended header + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR) { + // TODO: could show volume name when verbose + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag != TarHeader.LF_NORMAL && + header.TypeFlag != TarHeader.LF_OLDNORM && + header.TypeFlag != TarHeader.LF_DIR) { + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = tarBuffer.ReadBlock(); + } + + if (entryFactory == null) { + currentEntry = new TarEntry(headerBuf); + if (longName != null) { + currentEntry.Name = longName.ToString(); + } + } else { + currentEntry = entryFactory.CreateEntry(headerBuf); + } + + // Magic was checked here for 'ustar' but there are multiple valid possibilities + // so this is not done anymore. + + entryOffset = 0; + + // TODO: Review How do we resolve this discrepancy?! + entrySize = this.currentEntry.Size; + } catch (InvalidHeaderException ex) { + entrySize = 0; + entryOffset = 0; + currentEntry = null; + string errorText = string.Format("Bad header in record {0} block {1} {2}", + tarBuffer.CurrentRecord, tarBuffer.CurrentBlock, ex.Message); + throw new InvalidHeaderException(errorText); + } + } + return currentEntry; + } + + /// + /// Copies the contents of the current tar archive entry directly into + /// an output stream. + /// + /// + /// The OutputStream into which to write the entry's data. + /// + public void CopyEntryContents(Stream outputStream) + { + byte[] tempBuffer = new byte[32 * 1024]; + + while (true) { + int numRead = Read(tempBuffer, 0, tempBuffer.Length); + if (numRead <= 0) { + break; + } + outputStream.Write(tempBuffer, 0, numRead); + } + } + + void SkipToNextEntry() + { + long numToSkip = entrySize - entryOffset; + + if (numToSkip > 0) + { + Skip(numToSkip); + } + + readBuffer = null; + } + + /// + /// This interface is provided, along with the method , to allow + /// the programmer to have their own subclass instantiated for the + /// entries return from . + /// + public interface IEntryFactory + { + /// + /// Create an entry based on name alone + /// + /// + /// Name of the new EntryPointNotFoundException to create + /// + /// created TarEntry or descendant class + TarEntry CreateEntry(string name); + + /// + /// Create an instance based on an actual file + /// + /// + /// Name of file to represent in the entry + /// + /// + /// Created TarEntry or descendant class + /// + TarEntry CreateEntryFromFile(string fileName); + + /// + /// Create a tar entry based on the header information passed + /// + /// + /// Buffer containing header information to create an an entry from. + /// + /// + /// Created TarEntry or descendant class + /// + TarEntry CreateEntry(byte[] headerBuffer); + } + + /// + /// Standard entry factory class creating instances of the class TarEntry + /// + public class EntryFactoryAdapter : IEntryFactory + { + /// + /// Create a based on named + /// + /// The name to use for the entry + /// A new + public TarEntry CreateEntry(string name) + { + return TarEntry.CreateTarEntry(name); + } + + /// + /// Create a tar entry with details obtained from file + /// + /// The name of the file to retrieve details from. + /// A new + public TarEntry CreateEntryFromFile(string fileName) + { + return TarEntry.CreateEntryFromFile(fileName); + } + + /// + /// Create an entry based on details in header + /// + /// The buffer containing entry details. + /// A new + public TarEntry CreateEntry(byte[] headerBuffer) + { + return new TarEntry(headerBuffer); + } + } + + #region Instance Fields + /// + /// Flag set when last block has been read + /// + protected bool hasHitEOF; + + /// + /// Size of this entry as recorded in header + /// + protected long entrySize; + + /// + /// Number of bytes read for this entry so far + /// + protected long entryOffset; + + /// + /// Buffer used with calls to Read() + /// + protected byte[] readBuffer; + + /// + /// Working buffer + /// + protected TarBuffer tarBuffer; + + /// + /// Current entry being read + /// + TarEntry currentEntry; + + /// + /// Factory used to create TarEntry or descendant class instance + /// + protected IEntryFactory entryFactory; + + /// + /// Stream used as the source of input data. + /// + readonly Stream inputStream; + #endregion + } +} + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ + diff --git a/类库/OnlineRepair/ZIP/Tar/TarOutputStream.cs b/类库/OnlineRepair/ZIP/Tar/TarOutputStream.cs new file mode 100644 index 0000000..fcac26f --- /dev/null +++ b/类库/OnlineRepair/ZIP/Tar/TarOutputStream.cs @@ -0,0 +1,525 @@ +// TarOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarOutputStream writes a UNIX tar archive as an OutputStream. + /// Methods are provided to put entries, and then write their contents + /// by writing to this stream using write(). + /// + /// public + public class TarOutputStream : Stream + { + #region Constructors + /// + /// Construct TarOutputStream using default block factor + /// + /// stream to write to + public TarOutputStream(Stream outputStream) + : this(outputStream, TarBuffer.DefaultBlockFactor) + { + } + + /// + /// Construct TarOutputStream with user specified block factor + /// + /// stream to write to + /// blocking factor + public TarOutputStream(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + this.outputStream = outputStream; + buffer = TarBuffer.CreateOutputTarBuffer(outputStream, blockFactor); + + assemblyBuffer = new byte[TarBuffer.BlockSize]; + blockBuffer = new byte[TarBuffer.BlockSize]; + } + #endregion + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return buffer.IsStreamOwner; } + set { buffer.IsStreamOwner = value; } + } + + /// + /// true if the stream supports reading; otherwise, false. + /// + public override bool CanRead + { + get + { + return outputStream.CanRead; + } + } + + /// + /// true if the stream supports seeking; otherwise, false. + /// + public override bool CanSeek + { + get + { + return outputStream.CanSeek; + } + } + + /// + /// true if stream supports writing; otherwise, false. + /// + public override bool CanWrite + { + get + { + return outputStream.CanWrite; + } + } + + /// + /// length of stream in bytes + /// + public override long Length + { + get + { + return outputStream.Length; + } + } + + /// + /// gets or sets the position within the current stream. + /// + public override long Position + { + get + { + return outputStream.Position; + } + set + { + outputStream.Position = value; + } + } + + /// + /// set the position within the current stream + /// + /// The offset relative to the to seek to + /// The to seek from. + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + return outputStream.Seek(offset, origin); + } + + /// + /// Set the length of the current stream + /// + /// The new stream length. + public override void SetLength(long value) + { + outputStream.SetLength(value); + } + + /// + /// Read a byte from the stream and advance the position within the stream + /// by one byte or returns -1 if at the end of the stream. + /// + /// The byte value or -1 if at end of stream + public override int ReadByte() + { + return outputStream.ReadByte(); + } + + /// + /// read bytes from the current stream and advance the position within the + /// stream by the number of bytes read. + /// + /// The buffer to store read bytes in. + /// The index into the buffer to being storing bytes at. + /// The desired number of bytes to read. + /// The total number of bytes read, or zero if at the end of the stream. + /// The number of bytes may be less than the count + /// requested if data is not avialable. + public override int Read(byte[] buffer, int offset, int count) + { + return outputStream.Read(buffer, offset, count); + } + + /// + /// All buffered data is written to destination + /// + public override void Flush() + { + outputStream.Flush(); + } + + /// + /// Ends the TAR archive without closing the underlying OutputStream. + /// The result is that the EOF block of nulls is written. + /// + public void Finish() + { + if ( IsEntryOpen ) + { + CloseEntry(); + } + WriteEofBlock(); + } + + /// + /// Ends the TAR archive and closes the underlying OutputStream. + /// + /// This means that Finish() is called followed by calling the + /// TarBuffer's Close(). + public override void Close() + { + if ( !isClosed ) + { + isClosed = true; + Finish(); + buffer.Close(); + } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + public int RecordSize + { + get { return buffer.RecordSize; } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + /// + /// The TarBuffer record size. + /// + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return buffer.RecordSize; + } + + /// + /// Get a value indicating wether an entry is open, requiring more data to be written. + /// + bool IsEntryOpen + { + get { return (currBytes < currSize); } + + } + + /// + /// Put an entry on the output stream. This writes the entry's + /// header and positions the output stream for writing + /// the contents of the entry. Once this method is called, the + /// stream is ready for calls to write() to write the entry's + /// contents. Once the contents are written, closeEntry() + /// MUST be called to ensure that all buffered data + /// is completely written to the output stream. + /// + /// + /// The TarEntry to be written to the archive. + /// + public void PutNextEntry(TarEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if (entry.TarHeader.Name.Length >= TarHeader.NAMELEN) { + TarHeader longHeader = new TarHeader(); + longHeader.TypeFlag = TarHeader.LF_GNU_LONGNAME; + longHeader.Name = longHeader.Name + "././@LongLink"; + longHeader.UserId = 0; + longHeader.GroupId = 0; + longHeader.GroupName = ""; + longHeader.UserName = ""; + longHeader.LinkName = ""; + longHeader.Size = entry.TarHeader.Name.Length; + + longHeader.WriteHeader(blockBuffer); + buffer.WriteBlock(blockBuffer); // Add special long filename header block + + int nameCharIndex = 0; + + while (nameCharIndex < entry.TarHeader.Name.Length) { + Array.Clear(blockBuffer, 0, blockBuffer.Length); + TarHeader.GetAsciiBytes(entry.TarHeader.Name, nameCharIndex, this.blockBuffer, 0, TarBuffer.BlockSize); + nameCharIndex += TarBuffer.BlockSize; + buffer.WriteBlock(blockBuffer); + } + } + + entry.WriteEntryHeader(blockBuffer); + buffer.WriteBlock(blockBuffer); + + currBytes = 0; + + currSize = entry.IsDirectory ? 0 : entry.Size; + } + + /// + /// Close an entry. This method MUST be called for all file + /// entries that contain data. The reason is that we must + /// buffer data written to the stream in order to satisfy + /// the buffer's block based writes. Thus, there may be + /// data fragments still being assembled that must be written + /// to the output stream before this entry is closed and the + /// next entry written. + /// + public void CloseEntry() + { + if (assemblyBufferLength > 0) { + Array.Clear(assemblyBuffer, assemblyBufferLength, assemblyBuffer.Length - assemblyBufferLength); + + buffer.WriteBlock(assemblyBuffer); + + currBytes += assemblyBufferLength; + assemblyBufferLength = 0; + } + + if (currBytes < currSize) { + string errorText = string.Format( + "Entry closed at '{0}' before the '{1}' bytes specified in the header were written", + currBytes, currSize); + throw new TarException(errorText); + } + } + + /// + /// Writes a byte to the current tar archive entry. + /// This method simply calls Write(byte[], int, int). + /// + /// + /// The byte to be written. + /// + public override void WriteByte(byte value) + { + Write(new byte[] { value }, 0, 1); + } + + /// + /// Writes bytes to the current tar archive entry. This method + /// is aware of the current entry and will throw an exception if + /// you attempt to write bytes past the length specified for the + /// current entry. The method is also (painfully) aware of the + /// record buffering required by TarBuffer, and manages buffers + /// that are not a multiple of recordsize in length, including + /// assembling records from small buffers. + /// + /// + /// The buffer to write to the archive. + /// + /// + /// The offset in the buffer from which to get bytes. + /// + /// + /// The number of bytes to write. + /// + public override void Write(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( buffer.Length - offset < count ) + { + throw new ArgumentException("offset and count combination is invalid"); + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (currBytes + count) > currSize ) { + string errorText = string.Format("request to write '{0}' bytes exceeds size in header of '{1}' bytes", + count, this.currSize); +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", errorText); +#endif + } + + // + // We have to deal with assembly!!! + // The programmer can be writing little 32 byte chunks for all + // we know, and we must assemble complete blocks for writing. + // TODO REVIEW Maybe this should be in TarBuffer? Could that help to + // eliminate some of the buffer copying. + // + if (assemblyBufferLength > 0) { + if ((assemblyBufferLength + count ) >= blockBuffer.Length) { + int aLen = blockBuffer.Length - assemblyBufferLength; + + Array.Copy(assemblyBuffer, 0, blockBuffer, 0, assemblyBufferLength); + Array.Copy(buffer, offset, blockBuffer, assemblyBufferLength, aLen); + + this.buffer.WriteBlock(blockBuffer); + + currBytes += blockBuffer.Length; + + offset += aLen; + count -= aLen; + + assemblyBufferLength = 0; + } else { + Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count); + offset += count; + assemblyBufferLength += count; + count -= count; + } + } + + // + // When we get here we have EITHER: + // o An empty "assembly" buffer. + // o No bytes to write (count == 0) + // + while (count > 0) { + if (count < blockBuffer.Length) { + Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count); + assemblyBufferLength += count; + break; + } + + this.buffer.WriteBlock(buffer, offset); + + int bufferLength = blockBuffer.Length; + currBytes += bufferLength; + count -= bufferLength; + offset += bufferLength; + } + } + + /// + /// Write an EOF (end of archive) block to the tar archive. + /// An EOF block consists of all zeros. + /// + void WriteEofBlock() + { + Array.Clear(blockBuffer, 0, blockBuffer.Length); + buffer.WriteBlock(blockBuffer); + } + + #region Instance Fields + /// + /// bytes written for this entry so far + /// + long currBytes; + + /// + /// current 'Assembly' buffer length + /// + int assemblyBufferLength; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + /// + /// Size for the current entry + /// + protected long currSize; + + /// + /// single block working buffer + /// + protected byte[] blockBuffer; + + /// + /// 'Assembly' buffer used to assemble data before writing + /// + protected byte[] assemblyBuffer; + + /// + /// TarBuffer used to provide correct blocking factor + /// + protected TarBuffer buffer; + + /// + /// the destination stream for the archive contents + /// + protected Stream outputStream; + #endregion + } +} + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/Deflater.cs b/类库/OnlineRepair/ZIP/Zip/Compression/Deflater.cs new file mode 100644 index 0000000..dadbfb6 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/Deflater.cs @@ -0,0 +1,557 @@ +// Deflater.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This is the Deflater class. The deflater class compresses input + /// with the deflate algorithm described in RFC 1951. It has several + /// compression levels and three different strategies described below. + /// + /// This class is not thread safe. This is inherent in the API, due + /// to the split of deflate and setInput. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class Deflater + { + #region Deflater Documentation + /* + * The Deflater can do the following state transitions: + * + * (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---. + * / | (2) (5) | + * / v (5) | + * (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3) + * \ | (3) | ,--------' + * | | | (3) / + * v v (5) v v + * (1) -> BUSY_STATE ----> FINISHING_STATE + * | (6) + * v + * FINISHED_STATE + * \_____________________________________/ + * | (7) + * v + * CLOSED_STATE + * + * (1) If we should produce a header we start in INIT_STATE, otherwise + * we start in BUSY_STATE. + * (2) A dictionary may be set only when we are in INIT_STATE, then + * we change the state as indicated. + * (3) Whether a dictionary is set or not, on the first call of deflate + * we change to BUSY_STATE. + * (4) -- intentionally left blank -- :) + * (5) FINISHING_STATE is entered, when flush() is called to indicate that + * there is no more INPUT. There are also states indicating, that + * the header wasn't written yet. + * (6) FINISHED_STATE is entered, when everything has been flushed to the + * internal pending output buffer. + * (7) At any time (7) + * + */ + #endregion + #region Public Constants + /// + /// The best and slowest compression level. This tries to find very + /// long and distant string repetitions. + /// + public const int BEST_COMPRESSION = 9; + + /// + /// The worst but fastest compression level. + /// + public const int BEST_SPEED = 1; + + /// + /// The default compression level. + /// + public const int DEFAULT_COMPRESSION = -1; + + /// + /// This level won't compress at all but output uncompressed blocks. + /// + public const int NO_COMPRESSION = 0; + + /// + /// The compression method. This is the only method supported so far. + /// There is no need to use this constant at all. + /// + public const int DEFLATED = 8; + #endregion + #region Local Constants + private const int IS_SETDICT = 0x01; + private const int IS_FLUSHING = 0x04; + private const int IS_FINISHING = 0x08; + + private const int INIT_STATE = 0x00; + private const int SETDICT_STATE = 0x01; + // private static int INIT_FINISHING_STATE = 0x08; + // private static int SETDICT_FINISHING_STATE = 0x09; + private const int BUSY_STATE = 0x10; + private const int FLUSHING_STATE = 0x14; + private const int FINISHING_STATE = 0x1c; + private const int FINISHED_STATE = 0x1e; + private const int CLOSED_STATE = 0x7f; + #endregion + #region Constructors + /// + /// Creates a new deflater with default compression level. + /// + public Deflater() : this(DEFAULT_COMPRESSION, false) + { + + } + + /// + /// Creates a new deflater with given compression level. + /// + /// + /// the compression level, a value between NO_COMPRESSION + /// and BEST_COMPRESSION, or DEFAULT_COMPRESSION. + /// + /// if lvl is out of range. + public Deflater(int level) : this(level, false) + { + + } + + /// + /// Creates a new deflater with given compression level. + /// + /// + /// the compression level, a value between NO_COMPRESSION + /// and BEST_COMPRESSION. + /// + /// + /// true, if we should suppress the Zlib/RFC1950 header at the + /// beginning and the adler checksum at the end of the output. This is + /// useful for the GZIP/PKZIP formats. + /// + /// if lvl is out of range. + public Deflater(int level, bool noZlibHeaderOrFooter) + { + if (level == DEFAULT_COMPRESSION) { + level = 6; + } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) { + throw new ArgumentOutOfRangeException("level"); + } + + pending = new DeflaterPending(); + engine = new DeflaterEngine(pending); + this.noZlibHeaderOrFooter = noZlibHeaderOrFooter; + SetStrategy(DeflateStrategy.Default); + SetLevel(level); + Reset(); + } + #endregion + + /// + /// Resets the deflater. The deflater acts afterwards as if it was + /// just created with the same compression level and strategy as it + /// had before. + /// + public void Reset() + { + state = (noZlibHeaderOrFooter ? BUSY_STATE : INIT_STATE); + totalOut = 0; + pending.Reset(); + engine.Reset(); + } + + /// + /// Gets the current adler checksum of the data that was processed so far. + /// + public int Adler { + get { + return engine.Adler; + } + } + + /// + /// Gets the number of input bytes processed so far. + /// + public long TotalIn { + get { + return engine.TotalIn; + } + } + + /// + /// Gets the number of output bytes so far. + /// + public long TotalOut { + get { + return totalOut; + } + } + + /// + /// Flushes the current input block. Further calls to deflate() will + /// produce enough output to inflate everything in the current input + /// block. This is not part of Sun's JDK so I have made it package + /// private. It is used by DeflaterOutputStream to implement + /// flush(). + /// + public void Flush() + { + state |= IS_FLUSHING; + } + + /// + /// Finishes the deflater with the current input block. It is an error + /// to give more input after this method was called. This method must + /// be called to force all bytes to be flushed. + /// + public void Finish() + { + state |= (IS_FLUSHING | IS_FINISHING); + } + + /// + /// Returns true if the stream was finished and no more output bytes + /// are available. + /// + public bool IsFinished { + get { + return (state == FINISHED_STATE) && pending.IsFlushed; + } + } + + /// + /// Returns true, if the input buffer is empty. + /// You should then call setInput(). + /// NOTE: This method can also return true when the stream + /// was finished. + /// + public bool IsNeedingInput { + get { + return engine.NeedsInput(); + } + } + + /// + /// Sets the data which should be compressed next. This should be only + /// called when needsInput indicates that more input is needed. + /// If you call setInput when needsInput() returns false, the + /// previous input that is still pending will be thrown away. + /// The given byte array should not be changed, before needsInput() returns + /// true again. + /// This call is equivalent to setInput(input, 0, input.length). + /// + /// + /// the buffer containing the input data. + /// + /// + /// if the buffer was finished() or ended(). + /// + public void SetInput(byte[] input) + { + SetInput(input, 0, input.Length); + } + + /// + /// Sets the data which should be compressed next. This should be + /// only called when needsInput indicates that more input is needed. + /// The given byte array should not be changed, before needsInput() returns + /// true again. + /// + /// + /// the buffer containing the input data. + /// + /// + /// the start of the data. + /// + /// + /// the number of data bytes of input. + /// + /// + /// if the buffer was Finish()ed or if previous input is still pending. + /// + public void SetInput(byte[] input, int offset, int count) + { + if ((state & IS_FINISHING) != 0) { + throw new InvalidOperationException("Finish() already called"); + } + engine.SetInput(input, offset, count); + } + + /// + /// Sets the compression level. There is no guarantee of the exact + /// position of the change, but if you call this when needsInput is + /// true the change of compression level will occur somewhere near + /// before the end of the so far given input. + /// + /// + /// the new compression level. + /// + public void SetLevel(int level) + { + if (level == DEFAULT_COMPRESSION) { + level = 6; + } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) { + throw new ArgumentOutOfRangeException("level"); + } + + if (this.level != level) { + this.level = level; + engine.SetLevel(level); + } + } + + /// + /// Get current compression level + /// + /// Returns the current compression level + public int GetLevel() { + return level; + } + + /// + /// Sets the compression strategy. Strategy is one of + /// DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact + /// position where the strategy is changed, the same as for + /// SetLevel() applies. + /// + /// + /// The new compression strategy. + /// + public void SetStrategy(DeflateStrategy strategy) + { + engine.Strategy = strategy; + } + + /// + /// Deflates the current input block with to the given array. + /// + /// + /// The buffer where compressed data is stored + /// + /// + /// The number of compressed bytes added to the output, or 0 if either + /// IsNeedingInput() or IsFinished returns true or length is zero. + /// + public int Deflate(byte[] output) + { + return Deflate(output, 0, output.Length); + } + + /// + /// Deflates the current input block to the given array. + /// + /// + /// Buffer to store the compressed data. + /// + /// + /// Offset into the output array. + /// + /// + /// The maximum number of bytes that may be stored. + /// + /// + /// The number of compressed bytes added to the output, or 0 if either + /// needsInput() or finished() returns true or length is zero. + /// + /// + /// If Finish() was previously called. + /// + /// + /// If offset or length don't match the array length. + /// + public int Deflate(byte[] output, int offset, int length) + { + int origLength = length; + + if (state == CLOSED_STATE) { + throw new InvalidOperationException("Deflater closed"); + } + + if (state < BUSY_STATE) { + // output header + int header = (DEFLATED + + ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8; + int level_flags = (level - 1) >> 1; + if (level_flags < 0 || level_flags > 3) { + level_flags = 3; + } + header |= level_flags << 6; + if ((state & IS_SETDICT) != 0) { + // Dictionary was set + header |= DeflaterConstants.PRESET_DICT; + } + header += 31 - (header % 31); + + pending.WriteShortMSB(header); + if ((state & IS_SETDICT) != 0) { + int chksum = engine.Adler; + engine.ResetAdler(); + pending.WriteShortMSB(chksum >> 16); + pending.WriteShortMSB(chksum & 0xffff); + } + + state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING)); + } + + for (;;) { + int count = pending.Flush(output, offset, length); + offset += count; + totalOut += count; + length -= count; + + if (length == 0 || state == FINISHED_STATE) { + break; + } + + if (!engine.Deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0)) { + if (state == BUSY_STATE) { + // We need more input now + return origLength - length; + } else if (state == FLUSHING_STATE) { + if (level != NO_COMPRESSION) { + /* We have to supply some lookahead. 8 bit lookahead + * is needed by the zlib inflater, and we must fill + * the next byte, so that all bits are flushed. + */ + int neededbits = 8 + ((-pending.BitCount) & 7); + while (neededbits > 0) { + /* write a static tree block consisting solely of + * an EOF: + */ + pending.WriteBits(2, 10); + neededbits -= 10; + } + } + state = BUSY_STATE; + } else if (state == FINISHING_STATE) { + pending.AlignToByte(); + + // Compressed data is complete. Write footer information if required. + if (!noZlibHeaderOrFooter) { + int adler = engine.Adler; + pending.WriteShortMSB(adler >> 16); + pending.WriteShortMSB(adler & 0xffff); + } + state = FINISHED_STATE; + } + } + } + return origLength - length; + } + + /// + /// Sets the dictionary which should be used in the deflate process. + /// This call is equivalent to setDictionary(dict, 0, dict.Length). + /// + /// + /// the dictionary. + /// + /// + /// if SetInput () or Deflate () were already called or another dictionary was already set. + /// + public void SetDictionary(byte[] dictionary) + { + SetDictionary(dictionary, 0, dictionary.Length); + } + + /// + /// Sets the dictionary which should be used in the deflate process. + /// The dictionary is a byte array containing strings that are + /// likely to occur in the data which should be compressed. The + /// dictionary is not stored in the compressed output, only a + /// checksum. To decompress the output you need to supply the same + /// dictionary again. + /// + /// + /// The dictionary data + /// + /// + /// The index where dictionary information commences. + /// + /// + /// The number of bytes in the dictionary. + /// + /// + /// If SetInput () or Deflate() were already called or another dictionary was already set. + /// + public void SetDictionary(byte[] dictionary, int index, int count) + { + if (state != INIT_STATE) { + throw new InvalidOperationException(); + } + + state = SETDICT_STATE; + engine.SetDictionary(dictionary, index, count); + } + + #region Instance Fields + /// + /// Compression level. + /// + int level; + + /// + /// If true no Zlib/RFC1950 headers or footers are generated + /// + bool noZlibHeaderOrFooter; + + /// + /// The current state. + /// + int state; + + /// + /// The total bytes of output written. + /// + long totalOut; + + /// + /// The pending output. + /// + DeflaterPending pending; + + /// + /// The deflater engine. + /// + DeflaterEngine engine; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterConstants.cs b/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterConstants.cs new file mode 100644 index 0000000..a973db2 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterConstants.cs @@ -0,0 +1,186 @@ +// DeflaterConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class contains constants used for deflation. + /// + public class DeflaterConstants + { + /// + /// Set to true to enable debugging + /// + public const bool DEBUGGING = false; + + /// + /// Written to Zip file to identify a stored block + /// + public const int STORED_BLOCK = 0; + + /// + /// Identifies static tree in Zip file + /// + public const int STATIC_TREES = 1; + + /// + /// Identifies dynamic tree in Zip file + /// + public const int DYN_TREES = 2; + + /// + /// Header flag indicating a preset dictionary for deflation + /// + public const int PRESET_DICT = 0x20; + + /// + /// Sets internal buffer sizes for Huffman encoding + /// + public const int DEFAULT_MEM_LEVEL = 8; + + /// + /// Internal compression engine constant + /// + public const int MAX_MATCH = 258; + + /// + /// Internal compression engine constant + /// + public const int MIN_MATCH = 3; + + /// + /// Internal compression engine constant + /// + public const int MAX_WBITS = 15; + + /// + /// Internal compression engine constant + /// + public const int WSIZE = 1 << MAX_WBITS; + + /// + /// Internal compression engine constant + /// + public const int WMASK = WSIZE - 1; + + /// + /// Internal compression engine constant + /// + public const int HASH_BITS = DEFAULT_MEM_LEVEL + 7; + + /// + /// Internal compression engine constant + /// + public const int HASH_SIZE = 1 << HASH_BITS; + + /// + /// Internal compression engine constant + /// + public const int HASH_MASK = HASH_SIZE - 1; + + /// + /// Internal compression engine constant + /// + public const int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH; + + /// + /// Internal compression engine constant + /// + public const int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; + + /// + /// Internal compression engine constant + /// + public const int MAX_DIST = WSIZE - MIN_LOOKAHEAD; + + /// + /// Internal compression engine constant + /// + public const int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8); + + /// + /// Internal compression engine constant + /// + public static int MAX_BLOCK_SIZE = Math.Min(65535, PENDING_BUF_SIZE - 5); + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_STORED = 0; + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_FAST = 1; + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_SLOW = 2; + + /// + /// Internal compression engine constant + /// + public static int[] GOOD_LENGTH = { 0, 4, 4, 4, 4, 8, 8, 8, 32, 32 }; + + /// + /// Internal compression engine constant + /// + public static int[] MAX_LAZY = { 0, 4, 5, 6, 4, 16, 16, 32, 128, 258 }; + + /// + /// Internal compression engine constant + /// + public static int[] NICE_LENGTH = { 0, 8, 16, 32, 16, 32, 128, 128, 258, 258 }; + + /// + /// Internal compression engine constant + /// + public static int[] MAX_CHAIN = { 0, 4, 8, 32, 16, 32, 128, 256, 1024, 4096 }; + + /// + /// Internal compression engine constant + /// + public static int[] COMPR_FUNC = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterEngine.cs b/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterEngine.cs new file mode 100644 index 0000000..3cbb5aa --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterEngine.cs @@ -0,0 +1,869 @@ +// DeflaterEngine.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// Strategies for deflater + /// + public enum DeflateStrategy + { + /// + /// The default strategy + /// + Default = 0, + + /// + /// This strategy will only allow longer string repetitions. It is + /// useful for random data with a small character set. + /// + Filtered = 1, + + + /// + /// This strategy will not look for string repetitions at all. It + /// only encodes with Huffman trees (which means, that more common + /// characters get a smaller encoding. + /// + HuffmanOnly = 2 + } + + // DEFLATE ALGORITHM: + // + // The uncompressed stream is inserted into the window array. When + // the window array is full the first half is thrown away and the + // second half is copied to the beginning. + // + // The head array is a hash table. Three characters build a hash value + // and they the value points to the corresponding index in window of + // the last string with this hash. The prev array implements a + // linked list of matches with the same hash: prev[index & WMASK] points + // to the previous index with the same hash. + // + + + /// + /// Low level compression engine for deflate algorithm which uses a 32K sliding window + /// with secondary compression from Huffman/Shannon-Fano codes. + /// + public class DeflaterEngine : DeflaterConstants + { + #region Constants + const int TooFar = 4096; + #endregion + + #region Constructors + /// + /// Construct instance with pending buffer + /// + /// + /// Pending buffer to use + /// > + public DeflaterEngine(DeflaterPending pending) + { + this.pending = pending; + huffman = new DeflaterHuffman(pending); + adler = new Adler32(); + + window = new byte[2 * WSIZE]; + head = new short[HASH_SIZE]; + prev = new short[WSIZE]; + + // We start at index 1, to avoid an implementation deficiency, that + // we cannot build a repeat pattern at index 0. + blockStart = strstart = 1; + } + + #endregion + + /// + /// Deflate drives actual compression of data + /// + /// True to flush input buffers + /// Finish deflation with the current input. + /// Returns true if progress has been made. + public bool Deflate(bool flush, bool finish) + { + bool progress; + do + { + FillWindow(); + bool canFlush = flush && (inputOff == inputEnd); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.WriteLine("window: [" + blockStart + "," + strstart + "," + + lookahead + "], " + compressionFunction + "," + canFlush); + } +#endif + switch (compressionFunction) + { + case DEFLATE_STORED: + progress = DeflateStored(canFlush, finish); + break; + case DEFLATE_FAST: + progress = DeflateFast(canFlush, finish); + break; + case DEFLATE_SLOW: + progress = DeflateSlow(canFlush, finish); + break; + default: + throw new InvalidOperationException("unknown compressionFunction"); + } + } while (pending.IsFlushed && progress); // repeat while we have no pending output and progress was made + return progress; + } + + /// + /// Sets input data to be deflated. Should only be called when NeedsInput() + /// returns true + /// + /// The buffer containing input data. + /// The offset of the first byte of data. + /// The number of bytes of data to use as input. + public void SetInput(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( count < 0 ) + { + throw new ArgumentOutOfRangeException("count"); + } + + if (inputOff < inputEnd) + { + throw new InvalidOperationException("Old input was not completely processed"); + } + + int end = offset + count; + + /* We want to throw an ArrayIndexOutOfBoundsException early. The + * check is very tricky: it also handles integer wrap around. + */ + if ((offset > end) || (end > buffer.Length) ) + { + throw new ArgumentOutOfRangeException("count"); + } + + inputBuf = buffer; + inputOff = offset; + inputEnd = end; + } + + /// + /// Determines if more input is needed. + /// + /// Return true if input is needed via SetInput + public bool NeedsInput() + { + return (inputEnd == inputOff); + } + + /// + /// Set compression dictionary + /// + /// The buffer containing the dictionary data + /// The offset in the buffer for the first byte of data + /// The length of the dictionary data. + public void SetDictionary(byte[] buffer, int offset, int length) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (strstart != 1) ) + { + throw new InvalidOperationException("strstart not 1"); + } +#endif + adler.Update(buffer, offset, length); + if (length < MIN_MATCH) + { + return; + } + + if (length > MAX_DIST) + { + offset += length - MAX_DIST; + length = MAX_DIST; + } + + System.Array.Copy(buffer, offset, window, strstart, length); + + UpdateHash(); + --length; + while (--length > 0) + { + InsertString(); + strstart++; + } + strstart += 2; + blockStart = strstart; + } + + /// + /// Reset internal state + /// + public void Reset() + { + huffman.Reset(); + adler.Reset(); + blockStart = strstart = 1; + lookahead = 0; + totalIn = 0; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + + for (int i = 0; i < HASH_SIZE; i++) { + head[i] = 0; + } + + for (int i = 0; i < WSIZE; i++) { + prev[i] = 0; + } + } + + /// + /// Reset Adler checksum + /// + public void ResetAdler() + { + adler.Reset(); + } + + /// + /// Get current value of Adler checksum + /// + public int Adler { + get { + return unchecked((int)adler.Value); + } + } + + /// + /// Total data processed + /// + public long TotalIn { + get { + return totalIn; + } + } + + /// + /// Get/set the deflate strategy + /// + public DeflateStrategy Strategy { + get { + return strategy; + } + set { + strategy = value; + } + } + + /// + /// Set the deflate level (0-9) + /// + /// The value to set the level to. + public void SetLevel(int level) + { + if ( (level < 0) || (level > 9) ) + { + throw new ArgumentOutOfRangeException("level"); + } + + goodLength = DeflaterConstants.GOOD_LENGTH[level]; + max_lazy = DeflaterConstants.MAX_LAZY[level]; + niceLength = DeflaterConstants.NICE_LENGTH[level]; + max_chain = DeflaterConstants.MAX_CHAIN[level]; + + if (DeflaterConstants.COMPR_FUNC[level] != compressionFunction) { + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.WriteLine("Change from " + compressionFunction + " to " + + DeflaterConstants.COMPR_FUNC[level]); + } +#endif + switch (compressionFunction) { + case DEFLATE_STORED: + if (strstart > blockStart) { + huffman.FlushStoredBlock(window, blockStart, + strstart - blockStart, false); + blockStart = strstart; + } + UpdateHash(); + break; + + case DEFLATE_FAST: + if (strstart > blockStart) { + huffman.FlushBlock(window, blockStart, strstart - blockStart, + false); + blockStart = strstart; + } + break; + + case DEFLATE_SLOW: + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + if (strstart > blockStart) { + huffman.FlushBlock(window, blockStart, strstart - blockStart, false); + blockStart = strstart; + } + prevAvailable = false; + matchLen = MIN_MATCH - 1; + break; + } + compressionFunction = COMPR_FUNC[level]; + } + } + + /// + /// Fill the window + /// + public void FillWindow() + { + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (strstart >= WSIZE + MAX_DIST) + { + SlideWindow(); + } + + /* If there is not enough lookahead, but still some input left, + * read in the input + */ + while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd) + { + int more = 2 * WSIZE - lookahead - strstart; + + if (more > inputEnd - inputOff) + { + more = inputEnd - inputOff; + } + + System.Array.Copy(inputBuf, inputOff, window, strstart + lookahead, more); + adler.Update(inputBuf, inputOff, more); + + inputOff += more; + totalIn += more; + lookahead += more; + } + + if (lookahead >= MIN_MATCH) + { + UpdateHash(); + } + } + + void UpdateHash() + { +/* + if (DEBUGGING) { + Console.WriteLine("updateHash: "+strstart); + } +*/ + ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1]; + } + + /// + /// Inserts the current string in the head hash and returns the previous + /// value for this hash. + /// + /// The previous hash value + int InsertString() + { + short match; + int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)]) & HASH_MASK; + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^ + (window[strstart + 1] << HASH_SHIFT) ^ + (window[strstart + 2])) & HASH_MASK)) { + throw new SharpZipBaseException("hash inconsistent: " + hash + "/" + +window[strstart] + "," + +window[strstart + 1] + "," + +window[strstart + 2] + "," + HASH_SHIFT); + } + } +#endif + prev[strstart & WMASK] = match = head[hash]; + head[hash] = unchecked((short)strstart); + ins_h = hash; + return match & 0xffff; + } + + void SlideWindow() + { + Array.Copy(window, WSIZE, window, 0, WSIZE); + matchStart -= WSIZE; + strstart -= WSIZE; + blockStart -= WSIZE; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). + for (int i = 0; i < HASH_SIZE; ++i) { + int m = head[i] & 0xffff; + head[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0); + } + + // Slide the prev table. + for (int i = 0; i < WSIZE; i++) { + int m = prev[i] & 0xffff; + prev[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0); + } + } + + /// + /// Find the best (longest) string in the window matching the + /// string starting at strstart. + /// + /// Preconditions: + /// + /// strstart + MAX_MATCH <= window.length. + /// + /// + /// True if a match greater than the minimum length is found + bool FindLongestMatch(int curMatch) + { + int chainLength = this.max_chain; + int niceLength = this.niceLength; + short[] prev = this.prev; + int scan = this.strstart; + int match; + int best_end = this.strstart + matchLen; + int best_len = Math.Max(matchLen, MIN_MATCH - 1); + + int limit = Math.Max(strstart - MAX_DIST, 0); + + int strend = strstart + MAX_MATCH - 1; + byte scan_end1 = window[best_end - 1]; + byte scan_end = window[best_end]; + + // Do not waste too much time if we already have a good match: + if (best_len >= this.goodLength) { + chainLength >>= 2; + } + + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (niceLength > lookahead) { + niceLength = lookahead; + } + +#if DebugDeflation + + if (DeflaterConstants.DEBUGGING && (strstart > 2 * WSIZE - MIN_LOOKAHEAD)) + { + throw new InvalidOperationException("need lookahead"); + } +#endif + + do { + +#if DebugDeflation + + if (DeflaterConstants.DEBUGGING && (curMatch >= strstart) ) + { + throw new InvalidOperationException("no future"); + } +#endif + if (window[curMatch + best_len] != scan_end || + window[curMatch + best_len - 1] != scan_end1 || + window[curMatch] != window[scan] || + window[curMatch + 1] != window[scan + 1]) { + continue; + } + + match = curMatch + 2; + scan += 2; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart + 258. + */ + while ( + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + (scan < strend)) + { + // Do nothing + } + + if (scan > best_end) { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (ins_h == 0) ) + Console.Error.WriteLine("Found match: " + curMatch + "-" + (scan - strstart)); +#endif + matchStart = curMatch; + best_end = scan; + best_len = scan - strstart; + + if (best_len >= niceLength) { + break; + } + + scan_end1 = window[best_end - 1]; + scan_end = window[best_end]; + } + scan = strstart; + } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit && --chainLength != 0); + + matchLen = Math.Min(best_len, lookahead); + return matchLen >= MIN_MATCH; + } + + bool DeflateStored(bool flush, bool finish) + { + if (!flush && (lookahead == 0)) { + return false; + } + + strstart += lookahead; + lookahead = 0; + + int storedLength = strstart - blockStart; + + if ((storedLength >= DeflaterConstants.MAX_BLOCK_SIZE) || // Block is full + (blockStart < WSIZE && storedLength >= MAX_DIST) || // Block may move out of window + flush) { + bool lastBlock = finish; + if (storedLength > DeflaterConstants.MAX_BLOCK_SIZE) { + storedLength = DeflaterConstants.MAX_BLOCK_SIZE; + lastBlock = false; + } + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + Console.WriteLine("storedBlock[" + storedLength + "," + lastBlock + "]"); + } +#endif + + huffman.FlushStoredBlock(window, blockStart, storedLength, lastBlock); + blockStart += storedLength; + return !lastBlock; + } + return true; + } + + bool DeflateFast(bool flush, bool finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) { + return false; + } + + while (lookahead >= MIN_LOOKAHEAD || flush) { + if (lookahead == 0) { + // We are flushing everything + huffman.FlushBlock(window, blockStart, strstart - blockStart, finish); + blockStart = strstart; + return false; + } + + if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) { + /* slide window, as FindLongestMatch needs this. + * This should only happen when flushing and the window + * is almost full. + */ + SlideWindow(); + } + + int hashHead; + if (lookahead >= MIN_MATCH && + (hashHead = InsertString()) != 0 && + strategy != DeflateStrategy.HuffmanOnly && + strstart - hashHead <= MAX_DIST && + FindLongestMatch(hashHead)) { + // longestMatch sets matchStart and matchLen +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) { + if (window[strstart + i] != window[matchStart + i]) { + throw new SharpZipBaseException("Match failure"); + } + } + } +#endif + + bool full = huffman.TallyDist(strstart - matchStart, matchLen); + + lookahead -= matchLen; + if (matchLen <= max_lazy && lookahead >= MIN_MATCH) { + while (--matchLen > 0) { + ++strstart; + InsertString(); + } + ++strstart; + } else { + strstart += matchLen; + if (lookahead >= MIN_MATCH - 1) { + UpdateHash(); + } + } + matchLen = MIN_MATCH - 1; + if (!full) { + continue; + } + } else { + // No match found + huffman.TallyLit(window[strstart] & 0xff); + ++strstart; + --lookahead; + } + + if (huffman.IsFull()) { + bool lastBlock = finish && (lookahead == 0); + huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock); + blockStart = strstart; + return !lastBlock; + } + } + return true; + } + + bool DeflateSlow(bool flush, bool finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) { + return false; + } + + while (lookahead >= MIN_LOOKAHEAD || flush) { + if (lookahead == 0) { + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + prevAvailable = false; + + // We are flushing everything +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && !flush) + { + throw new SharpZipBaseException("Not flushing, but no lookahead"); + } +#endif + huffman.FlushBlock(window, blockStart, strstart - blockStart, + finish); + blockStart = strstart; + return false; + } + + if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) { + /* slide window, as FindLongestMatch needs this. + * This should only happen when flushing and the window + * is almost full. + */ + SlideWindow(); + } + + int prevMatch = matchStart; + int prevLen = matchLen; + if (lookahead >= MIN_MATCH) { + + int hashHead = InsertString(); + + if (strategy != DeflateStrategy.HuffmanOnly && + hashHead != 0 && + strstart - hashHead <= MAX_DIST && + FindLongestMatch(hashHead)) { + + // longestMatch sets matchStart and matchLen + + // Discard match if too small and too far away + if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TooFar))) { + matchLen = MIN_MATCH - 1; + } + } + } + + // previous match was better + if ((prevLen >= MIN_MATCH) && (matchLen <= prevLen) ) { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) { + if (window[strstart-1+i] != window[prevMatch + i]) + throw new SharpZipBaseException(); + } + } +#endif + huffman.TallyDist(strstart - 1 - prevMatch, prevLen); + prevLen -= 2; + do { + strstart++; + lookahead--; + if (lookahead >= MIN_MATCH) { + InsertString(); + } + } while (--prevLen > 0); + + strstart ++; + lookahead--; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + } else { + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + prevAvailable = true; + strstart++; + lookahead--; + } + + if (huffman.IsFull()) { + int len = strstart - blockStart; + if (prevAvailable) { + len--; + } + bool lastBlock = (finish && (lookahead == 0) && !prevAvailable); + huffman.FlushBlock(window, blockStart, len, lastBlock); + blockStart += len; + return !lastBlock; + } + } + return true; + } + + #region Instance Fields + + // Hash index of string to be inserted + int ins_h; + + /// + /// Hashtable, hashing three characters to an index for window, so + /// that window[index]..window[index+2] have this hash code. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xffff. + /// + short[] head; + + /// + /// prev[index & WMASK] points to the previous index that has the + /// same hash code as the string starting at index. This way + /// entries with the same hash code are in a linked list. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xffff. + /// + short[] prev; + + int matchStart; + // Length of best match + int matchLen; + // Set if previous match exists + bool prevAvailable; + int blockStart; + + /// + /// Points to the current character in the window. + /// + int strstart; + + /// + /// lookahead is the number of characters starting at strstart in + /// window that are valid. + /// So window[strstart] until window[strstart+lookahead-1] are valid + /// characters. + /// + int lookahead; + + /// + /// This array contains the part of the uncompressed stream that + /// is of relevance. The current character is indexed by strstart. + /// + byte[] window; + + DeflateStrategy strategy; + int max_chain, max_lazy, niceLength, goodLength; + + /// + /// The current compression function. + /// + int compressionFunction; + + /// + /// The input data for compression. + /// + byte[] inputBuf; + + /// + /// The total bytes of input read. + /// + long totalIn; + + /// + /// The offset into inputBuf, where input data starts. + /// + int inputOff; + + /// + /// The end offset of the input data. + /// + int inputEnd; + + DeflaterPending pending; + DeflaterHuffman huffman; + + /// + /// The adler checksum + /// + Adler32 adler; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterHuffman.cs b/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterHuffman.cs new file mode 100644 index 0000000..8c89e59 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterHuffman.cs @@ -0,0 +1,908 @@ +// DeflaterHuffman.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This is the DeflaterHuffman class. + /// + /// This class is not thread safe. This is inherent in the API, due + /// to the split of Deflate and SetInput. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class DeflaterHuffman + { + const int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6); + const int LITERAL_NUM = 286; + + // Number of distance codes + const int DIST_NUM = 30; + // Number of codes used to transfer bit lengths + const int BITLEN_NUM = 19; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + const int REP_3_6 = 16; + // repeat a zero length 3-10 times (3 bits of repeat count) + const int REP_3_10 = 17; + // repeat a zero length 11-138 times (7 bits of repeat count) + const int REP_11_138 = 18; + + const int EOF_SYMBOL = 256; + + // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit length codes. + static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + static readonly byte[] bit4Reverse = { + 0, + 8, + 4, + 12, + 2, + 10, + 6, + 14, + 1, + 9, + 5, + 13, + 3, + 11, + 7, + 15 + }; + + static short[] staticLCodes; + static byte[] staticLLength; + static short[] staticDCodes; + static byte[] staticDLength; + + class Tree + { + #region Instance Fields + public short[] freqs; + + public byte[] length; + + public int minNumCodes; + + public int numCodes; + + short[] codes; + int[] bl_counts; + int maxLength; + DeflaterHuffman dh; + #endregion + + #region Constructors + public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength) + { + this.dh = dh; + this.minNumCodes = minCodes; + this.maxLength = maxLength; + freqs = new short[elems]; + bl_counts = new int[maxLength]; + } + + #endregion + + /// + /// Resets the internal state of the tree + /// + public void Reset() + { + for (int i = 0; i < freqs.Length; i++) { + freqs[i] = 0; + } + codes = null; + length = null; + } + + public void WriteSymbol(int code) + { + // if (DeflaterConstants.DEBUGGING) { + // freqs[code]--; + // // Console.Write("writeSymbol("+freqs.length+","+code+"): "); + // } + dh.pending.WriteBits(codes[code] & 0xffff, length[code]); + } + + /// + /// Check that all frequencies are zero + /// + /// + /// At least one frequency is non-zero + /// + public void CheckEmpty() + { + bool empty = true; + for (int i = 0; i < freqs.Length; i++) { + if (freqs[i] != 0) { + //Console.WriteLine("freqs[" + i + "] == " + freqs[i]); + empty = false; + } + } + + if (!empty) { + throw new SharpZipBaseException("!Empty"); + } + } + + /// + /// Set static codes and length + /// + /// new codes + /// length for new codes + public void SetStaticCodes(short[] staticCodes, byte[] staticLengths) + { + codes = staticCodes; + length = staticLengths; + } + + /// + /// Build dynamic codes and lengths + /// + public void BuildCodes() + { + int numSymbols = freqs.Length; + int[] nextCode = new int[maxLength]; + int code = 0; + + codes = new short[freqs.Length]; + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("buildCodes: "+freqs.Length); + // } + + for (int bits = 0; bits < maxLength; bits++) { + nextCode[bits] = code; + code += bl_counts[bits] << (15 - bits); + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits] + // +" nextCode: "+code); + // } + } + +#if DebugDeflation + if ( DeflaterConstants.DEBUGGING && (code != 65536) ) + { + throw new SharpZipBaseException("Inconsistent bl_counts!"); + } +#endif + for (int i=0; i < numCodes; i++) { + int bits = length[i]; + if (bits > 0) { + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"), + // +bits); + // } + + codes[i] = BitReverse(nextCode[bits-1]); + nextCode[bits-1] += 1 << (16 - bits); + } + } + } + + public void BuildTree() + { + int numSymbols = freqs.Length; + + /* heap is a priority queue, sorted by frequency, least frequent + * nodes first. The heap is a binary tree, with the property, that + * the parent node is smaller than both child nodes. This assures + * that the smallest node is the first parent. + * + * The binary tree is encoded in an array: 0 is root node and + * the nodes 2*n+1, 2*n+2 are the child nodes of node n. + */ + int[] heap = new int[numSymbols]; + int heapLen = 0; + int maxCode = 0; + for (int n = 0; n < numSymbols; n++) { + int freq = freqs[n]; + if (freq != 0) { + // Insert n into heap + int pos = heapLen++; + int ppos; + while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) { + heap[pos] = heap[ppos]; + pos = ppos; + } + heap[pos] = n; + + maxCode = n; + } + } + + /* We could encode a single literal with 0 bits but then we + * don't see the literals. Therefore we force at least two + * literals to avoid this case. We don't care about order in + * this case, both literals get a 1 bit code. + */ + while (heapLen < 2) { + int node = maxCode < 2 ? ++maxCode : 0; + heap[heapLen++] = node; + } + + numCodes = Math.Max(maxCode + 1, minNumCodes); + + int numLeafs = heapLen; + int[] childs = new int[4 * heapLen - 2]; + int[] values = new int[2 * heapLen - 1]; + int numNodes = numLeafs; + for (int i = 0; i < heapLen; i++) { + int node = heap[i]; + childs[2 * i] = node; + childs[2 * i + 1] = -1; + values[i] = freqs[node] << 8; + heap[i] = i; + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + int first = heap[0]; + int last = heap[--heapLen]; + + // Propagate the hole to the leafs of the heap + int ppos = 0; + int path = 1; + + while (path < heapLen) { + if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) { + path++; + } + + heap[ppos] = heap[path]; + ppos = path; + path = path * 2 + 1; + } + + /* Now propagate the last element down along path. Normally + * it shouldn't go too deep. + */ + int lastVal = values[last]; + while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) { + heap[path] = heap[ppos]; + } + heap[path] = last; + + + int second = heap[0]; + + // Create a new node father of first and second + last = numNodes++; + childs[2 * last] = first; + childs[2 * last + 1] = second; + int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff); + values[last] = lastVal = values[first] + values[second] - mindepth + 1; + + // Again, propagate the hole to the leafs + ppos = 0; + path = 1; + + while (path < heapLen) { + if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) { + path++; + } + + heap[ppos] = heap[path]; + ppos = path; + path = ppos * 2 + 1; + } + + // Now propagate the new element down along path + while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) { + heap[path] = heap[ppos]; + } + heap[path] = last; + } while (heapLen > 1); + + if (heap[0] != childs.Length / 2 - 1) { + throw new SharpZipBaseException("Heap invariant violated"); + } + + BuildLength(childs); + } + + /// + /// Get encoded length + /// + /// Encoded length, the sum of frequencies * lengths + public int GetEncodedLength() + { + int len = 0; + for (int i = 0; i < freqs.Length; i++) { + len += freqs[i] * length[i]; + } + return len; + } + + /// + /// Scan a literal or distance tree to determine the frequencies of the codes + /// in the bit length tree. + /// + public void CalcBLFreq(Tree blTree) + { + int max_count; /* max repeat count */ + int min_count; /* min repeat count */ + int count; /* repeat count of the current code */ + int curlen = -1; /* length of current code */ + + int i = 0; + while (i < numCodes) { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else { + max_count = 6; + min_count = 3; + if (curlen != nextlen) { + blTree.freqs[nextlen]++; + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) { + i++; + if (++count >= max_count) { + break; + } + } + + if (count < min_count) { + blTree.freqs[curlen] += (short)count; + } else if (curlen != 0) { + blTree.freqs[REP_3_6]++; + } else if (count <= 10) { + blTree.freqs[REP_3_10]++; + } else { + blTree.freqs[REP_11_138]++; + } + } + } + + /// + /// Write tree values + /// + /// Tree to write + public void WriteTree(Tree blTree) + { + int max_count; // max repeat count + int min_count; // min repeat count + int count; // repeat count of the current code + int curlen = -1; // length of current code + + int i = 0; + while (i < numCodes) { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else { + max_count = 6; + min_count = 3; + if (curlen != nextlen) { + blTree.WriteSymbol(nextlen); + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) { + i++; + if (++count >= max_count) { + break; + } + } + + if (count < min_count) { + while (count-- > 0) { + blTree.WriteSymbol(curlen); + } + } else if (curlen != 0) { + blTree.WriteSymbol(REP_3_6); + dh.pending.WriteBits(count - 3, 2); + } else if (count <= 10) { + blTree.WriteSymbol(REP_3_10); + dh.pending.WriteBits(count - 3, 3); + } else { + blTree.WriteSymbol(REP_11_138); + dh.pending.WriteBits(count - 11, 7); + } + } + } + + void BuildLength(int[] childs) + { + this.length = new byte [freqs.Length]; + int numNodes = childs.Length / 2; + int numLeafs = (numNodes + 1) / 2; + int overflow = 0; + + for (int i = 0; i < maxLength; i++) { + bl_counts[i] = 0; + } + + // First calculate optimal bit lengths + int[] lengths = new int[numNodes]; + lengths[numNodes-1] = 0; + + for (int i = numNodes - 1; i >= 0; i--) { + if (childs[2 * i + 1] != -1) { + int bitLength = lengths[i] + 1; + if (bitLength > maxLength) { + bitLength = maxLength; + overflow++; + } + lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength; + } else { + // A leaf node + int bitLength = lengths[i]; + bl_counts[bitLength - 1]++; + this.length[childs[2*i]] = (byte) lengths[i]; + } + } + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Tree "+freqs.Length+" lengths:"); + // for (int i=0; i < numLeafs; i++) { + // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + // + " len: "+length[childs[2*i]]); + // } + // } + + if (overflow == 0) { + return; + } + + int incrBitLen = maxLength - 1; + do { + // Find the first bit length which could increase: + while (bl_counts[--incrBitLen] == 0) + ; + + // Move this node one down and remove a corresponding + // number of overflow nodes. + do { + bl_counts[incrBitLen]--; + bl_counts[++incrBitLen]++; + overflow -= 1 << (maxLength - 1 - incrBitLen); + } while (overflow > 0 && incrBitLen < maxLength - 1); + } while (overflow > 0); + + /* We may have overshot above. Move some nodes from maxLength to + * maxLength-1 in that case. + */ + bl_counts[maxLength-1] += overflow; + bl_counts[maxLength-2] -= overflow; + + /* Now recompute all bit lengths, scanning in increasing + * frequency. It is simpler to reconstruct all lengths instead of + * fixing only the wrong ones. This idea is taken from 'ar' + * written by Haruhiko Okumura. + * + * The nodes were inserted with decreasing frequency into the childs + * array. + */ + int nodePtr = 2 * numLeafs; + for (int bits = maxLength; bits != 0; bits--) { + int n = bl_counts[bits-1]; + while (n > 0) { + int childPtr = 2*childs[nodePtr++]; + if (childs[childPtr + 1] == -1) { + // We found another leaf + length[childs[childPtr]] = (byte) bits; + n--; + } + } + } + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("*** After overflow elimination. ***"); + // for (int i=0; i < numLeafs; i++) { + // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + // + " len: "+length[childs[2*i]]); + // } + // } + } + + } + + #region Instance Fields + /// + /// Pending buffer to use + /// + public DeflaterPending pending; + + Tree literalTree; + Tree distTree; + Tree blTree; + + // Buffer for distances + short[] d_buf; + byte[] l_buf; + int last_lit; + int extra_bits; + #endregion + + static DeflaterHuffman() + { + // See RFC 1951 3.2.6 + // Literal codes + staticLCodes = new short[LITERAL_NUM]; + staticLLength = new byte[LITERAL_NUM]; + + int i = 0; + while (i < 144) { + staticLCodes[i] = BitReverse((0x030 + i) << 8); + staticLLength[i++] = 8; + } + + while (i < 256) { + staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7); + staticLLength[i++] = 9; + } + + while (i < 280) { + staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9); + staticLLength[i++] = 7; + } + + while (i < LITERAL_NUM) { + staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8); + staticLLength[i++] = 8; + } + + // Distance codes + staticDCodes = new short[DIST_NUM]; + staticDLength = new byte[DIST_NUM]; + for (i = 0; i < DIST_NUM; i++) { + staticDCodes[i] = BitReverse(i << 11); + staticDLength[i] = 5; + } + } + + /// + /// Construct instance with pending buffer + /// + /// Pending buffer to use + public DeflaterHuffman(DeflaterPending pending) + { + this.pending = pending; + + literalTree = new Tree(this, LITERAL_NUM, 257, 15); + distTree = new Tree(this, DIST_NUM, 1, 15); + blTree = new Tree(this, BITLEN_NUM, 4, 7); + + d_buf = new short[BUFSIZE]; + l_buf = new byte [BUFSIZE]; + } + + /// + /// Reset internal state + /// + public void Reset() + { + last_lit = 0; + extra_bits = 0; + literalTree.Reset(); + distTree.Reset(); + blTree.Reset(); + } + + /// + /// Write all trees to pending buffer + /// + /// The number/rank of treecodes to send. + public void SendAllTrees(int blTreeCodes) + { + blTree.BuildCodes(); + literalTree.BuildCodes(); + distTree.BuildCodes(); + pending.WriteBits(literalTree.numCodes - 257, 5); + pending.WriteBits(distTree.numCodes - 1, 5); + pending.WriteBits(blTreeCodes - 4, 4); + for (int rank = 0; rank < blTreeCodes; rank++) { + pending.WriteBits(blTree.length[BL_ORDER[rank]], 3); + } + literalTree.WriteTree(blTree); + distTree.WriteTree(blTree); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + blTree.CheckEmpty(); + } +#endif + } + + /// + /// Compress current buffer writing data to pending buffer + /// + public void CompressBlock() + { + for (int i = 0; i < last_lit; i++) { + int litlen = l_buf[i] & 0xff; + int dist = d_buf[i]; + if (dist-- != 0) { + // if (DeflaterConstants.DEBUGGING) { + // Console.Write("["+(dist+1)+","+(litlen+3)+"]: "); + // } + + int lc = Lcode(litlen); + literalTree.WriteSymbol(lc); + + int bits = (lc - 261) / 4; + if (bits > 0 && bits <= 5) { + pending.WriteBits(litlen & ((1 << bits) - 1), bits); + } + + int dc = Dcode(dist); + distTree.WriteSymbol(dc); + + bits = dc / 2 - 1; + if (bits > 0) { + pending.WriteBits(dist & ((1 << bits) - 1), bits); + } + } else { + // if (DeflaterConstants.DEBUGGING) { + // if (litlen > 32 && litlen < 127) { + // Console.Write("("+(char)litlen+"): "); + // } else { + // Console.Write("{"+litlen+"}: "); + // } + // } + literalTree.WriteSymbol(litlen); + } + } + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.Write("EOF: "); + } +#endif + literalTree.WriteSymbol(EOF_SYMBOL); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + literalTree.CheckEmpty(); + distTree.CheckEmpty(); + } +#endif + } + + /// + /// Flush block to output with no compression + /// + /// Data to write + /// Index of first byte to write + /// Count of bytes to write + /// True if this is the last block + public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) + { +#if DebugDeflation + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Flushing stored block "+ storedLength); + // } +#endif + pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3); + pending.AlignToByte(); + pending.WriteShort(storedLength); + pending.WriteShort(~storedLength); + pending.WriteBlock(stored, storedOffset, storedLength); + Reset(); + } + + /// + /// Flush block to output with compression + /// + /// Data to flush + /// Index of first byte to flush + /// Count of bytes to flush + /// True if this is the last block + public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) + { + literalTree.freqs[EOF_SYMBOL]++; + + // Build trees + literalTree.BuildTree(); + distTree.BuildTree(); + + // Calculate bitlen frequency + literalTree.CalcBLFreq(blTree); + distTree.CalcBLFreq(blTree); + + // Build bitlen tree + blTree.BuildTree(); + + int blTreeCodes = 4; + for (int i = 18; i > blTreeCodes; i--) { + if (blTree.length[BL_ORDER[i]] > 0) { + blTreeCodes = i+1; + } + } + int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() + + literalTree.GetEncodedLength() + distTree.GetEncodedLength() + + extra_bits; + + int static_len = extra_bits; + for (int i = 0; i < LITERAL_NUM; i++) { + static_len += literalTree.freqs[i] * staticLLength[i]; + } + for (int i = 0; i < DIST_NUM; i++) { + static_len += distTree.freqs[i] * staticDLength[i]; + } + if (opt_len >= static_len) { + // Force static trees + opt_len = static_len; + } + + if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) { + // Store Block + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len + // + " <= " + static_len); + // } + FlushStoredBlock(stored, storedOffset, storedLength, lastBlock); + } else if (opt_len == static_len) { + // Encode with static tree + pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3); + literalTree.SetStaticCodes(staticLCodes, staticLLength); + distTree.SetStaticCodes(staticDCodes, staticDLength); + CompressBlock(); + Reset(); + } else { + // Encode with dynamic tree + pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3); + SendAllTrees(blTreeCodes); + CompressBlock(); + Reset(); + } + } + + /// + /// Get value indicating if internal buffer is full + /// + /// true if buffer is full + public bool IsFull() + { + return last_lit >= BUFSIZE; + } + + /// + /// Add literal to buffer + /// + /// Literal value to add to buffer. + /// Value indicating internal buffer is full + public bool TallyLit(int literal) + { + // if (DeflaterConstants.DEBUGGING) { + // if (lit > 32 && lit < 127) { + // //Console.WriteLine("("+(char)lit+")"); + // } else { + // //Console.WriteLine("{"+lit+"}"); + // } + // } + d_buf[last_lit] = 0; + l_buf[last_lit++] = (byte)literal; + literalTree.freqs[literal]++; + return IsFull(); + } + + /// + /// Add distance code and length to literal and distance trees + /// + /// Distance code + /// Length + /// Value indicating if internal buffer is full + public bool TallyDist(int distance, int length) + { + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("[" + distance + "," + length + "]"); + // } + + d_buf[last_lit] = (short)distance; + l_buf[last_lit++] = (byte)(length - 3); + + int lc = Lcode(length - 3); + literalTree.freqs[lc]++; + if (lc >= 265 && lc < 285) { + extra_bits += (lc - 261) / 4; + } + + int dc = Dcode(distance - 1); + distTree.freqs[dc]++; + if (dc >= 4) { + extra_bits += dc / 2 - 1; + } + return IsFull(); + } + + + /// + /// Reverse the bits of a 16 bit value. + /// + /// Value to reverse bits + /// Value with bits reversed + public static short BitReverse(int toReverse) + { + return (short) (bit4Reverse[toReverse & 0xF] << 12 | + bit4Reverse[(toReverse >> 4) & 0xF] << 8 | + bit4Reverse[(toReverse >> 8) & 0xF] << 4 | + bit4Reverse[toReverse >> 12]); + } + + static int Lcode(int length) + { + if (length == 255) { + return 285; + } + + int code = 257; + while (length >= 8) { + code += 4; + length >>= 1; + } + return code + length; + } + + static int Dcode(int distance) + { + int code = 0; + while (distance >= 4) { + code += 2; + distance >>= 1; + } + return code + distance; + } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterPending.cs b/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterPending.cs new file mode 100644 index 0000000..4cecc2e --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/DeflaterPending.cs @@ -0,0 +1,57 @@ +// DeflaterPending.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class stores the pending output of the Deflater. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class DeflaterPending : PendingBuffer + { + /// + /// Construct instance with default buffer size + /// + public DeflaterPending() : base(DeflaterConstants.PENDING_BUF_SIZE) + { + } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/Inflater.cs b/类库/OnlineRepair/ZIP/Zip/Compression/Inflater.cs new file mode 100644 index 0000000..16c3ef6 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/Inflater.cs @@ -0,0 +1,864 @@ +// Inflater.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + /// + /// Inflater is used to decompress data that has been compressed according + /// to the "deflate" standard described in rfc1951. + /// + /// By default Zlib (rfc1950) headers and footers are expected in the input. + /// You can use constructor public Inflater(bool noHeader) passing true + /// if there is no Zlib header information + /// + /// The usage is as following. First you have to set some input with + /// SetInput(), then Inflate() it. If inflate doesn't + /// inflate any bytes there may be three reasons: + ///
    + ///
  • IsNeedingInput() returns true because the input buffer is empty. + /// You have to provide more input with SetInput(). + /// NOTE: IsNeedingInput() also returns true when, the stream is finished. + ///
  • + ///
  • IsNeedingDictionary() returns true, you have to provide a preset + /// dictionary with SetDictionary().
  • + ///
  • IsFinished returns true, the inflater has finished.
  • + ///
+ /// Once the first output byte is produced, a dictionary will not be + /// needed at a later stage. + /// + /// author of the original java version : John Leuner, Jochen Hoenicke + ///
+ public class Inflater + { + #region Constants/Readonly + /// + /// Copy lengths for literal codes 257..285 + /// + static readonly int[] CPLENS = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 + }; + + /// + /// Extra bits for literal codes 257..285 + /// + static readonly int[] CPLEXT = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; + + /// + /// Copy offsets for distance codes 0..29 + /// + static readonly int[] CPDIST = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + /// + /// Extra bits for distance codes + /// + static readonly int[] CPDEXT = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + }; + + /// + /// These are the possible states for an inflater + /// + const int DECODE_HEADER = 0; + const int DECODE_DICT = 1; + const int DECODE_BLOCKS = 2; + const int DECODE_STORED_LEN1 = 3; + const int DECODE_STORED_LEN2 = 4; + const int DECODE_STORED = 5; + const int DECODE_DYN_HEADER = 6; + const int DECODE_HUFFMAN = 7; + const int DECODE_HUFFMAN_LENBITS = 8; + const int DECODE_HUFFMAN_DIST = 9; + const int DECODE_HUFFMAN_DISTBITS = 10; + const int DECODE_CHKSUM = 11; + const int FINISHED = 12; + #endregion + + #region Instance Fields + /// + /// This variable contains the current state. + /// + int mode; + + /// + /// The adler checksum of the dictionary or of the decompressed + /// stream, as it is written in the header resp. footer of the + /// compressed stream. + /// Only valid if mode is DECODE_DICT or DECODE_CHKSUM. + /// + int readAdler; + + /// + /// The number of bits needed to complete the current state. This + /// is valid, if mode is DECODE_DICT, DECODE_CHKSUM, + /// DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. + /// + int neededBits; + int repLength; + int repDist; + int uncomprLen; + + /// + /// True, if the last block flag was set in the last block of the + /// inflated stream. This means that the stream ends after the + /// current block. + /// + bool isLastBlock; + + /// + /// The total number of inflated bytes. + /// + long totalOut; + + /// + /// The total number of bytes set with setInput(). This is not the + /// value returned by the TotalIn property, since this also includes the + /// unprocessed input. + /// + long totalIn; + + /// + /// This variable stores the noHeader flag that was given to the constructor. + /// True means, that the inflated stream doesn't contain a Zlib header or + /// footer. + /// + bool noHeader; + + StreamManipulator input; + OutputWindow outputWindow; + InflaterDynHeader dynHeader; + InflaterHuffmanTree litlenTree, distTree; + Adler32 adler; + #endregion + + #region Constructors + /// + /// Creates a new inflater or RFC1951 decompressor + /// RFC1950/Zlib headers and footers will be expected in the input data + /// + public Inflater() : this(false) + { + } + + /// + /// Creates a new inflater. + /// + /// + /// True if no RFC1950/Zlib header and footer fields are expected in the input data + /// + /// This is used for GZIPed/Zipped input. + /// + /// For compatibility with + /// Sun JDK you should provide one byte of input more than needed in + /// this case. + /// + public Inflater(bool noHeader) + { + this.noHeader = noHeader; + this.adler = new Adler32(); + input = new StreamManipulator(); + outputWindow = new OutputWindow(); + mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; + } + #endregion + + /// + /// Resets the inflater so that a new stream can be decompressed. All + /// pending input and output will be discarded. + /// + public void Reset() + { + mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; + totalIn = 0; + totalOut = 0; + input.Reset(); + outputWindow.Reset(); + dynHeader = null; + litlenTree = null; + distTree = null; + isLastBlock = false; + adler.Reset(); + } + + /// + /// Decodes a zlib/RFC1950 header. + /// + /// + /// False if more input is needed. + /// + /// + /// The header is invalid. + /// + private bool DecodeHeader() + { + int header = input.PeekBits(16); + if (header < 0) { + return false; + } + input.DropBits(16); + + // The header is written in "wrong" byte order + header = ((header << 8) | (header >> 8)) & 0xffff; + if (header % 31 != 0) { + throw new SharpZipBaseException("Header checksum illegal"); + } + + if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) { + throw new SharpZipBaseException("Compression Method unknown"); + } + + /* Maximum size of the backwards window in bits. + * We currently ignore this, but we could use it to make the + * inflater window more space efficient. On the other hand the + * full window (15 bits) is needed most times, anyway. + int max_wbits = ((header & 0x7000) >> 12) + 8; + */ + + if ((header & 0x0020) == 0) { // Dictionary flag? + mode = DECODE_BLOCKS; + } else { + mode = DECODE_DICT; + neededBits = 32; + } + return true; + } + + /// + /// Decodes the dictionary checksum after the deflate header. + /// + /// + /// False if more input is needed. + /// + private bool DecodeDict() + { + while (neededBits > 0) { + int dictByte = input.PeekBits(8); + if (dictByte < 0) { + return false; + } + input.DropBits(8); + readAdler = (readAdler << 8) | dictByte; + neededBits -= 8; + } + return false; + } + + /// + /// Decodes the huffman encoded symbols in the input stream. + /// + /// + /// false if more input is needed, true if output window is + /// full or the current block ends. + /// + /// + /// if deflated stream is invalid. + /// + private bool DecodeHuffman() + { + int free = outputWindow.GetFreeSpace(); + while (free >= 258) + { + int symbol; + switch (mode) + { + case DECODE_HUFFMAN: + // This is the inner loop so it is optimized a bit + while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0) + { + outputWindow.Write(symbol); + if (--free < 258) + { + return true; + } + } + + if (symbol < 257) + { + if (symbol < 0) + { + return false; + } + else + { + // symbol == 256: end of block + distTree = null; + litlenTree = null; + mode = DECODE_BLOCKS; + return true; + } + } + + try + { + repLength = CPLENS[symbol - 257]; + neededBits = CPLEXT[symbol - 257]; + } + catch (Exception) + { + throw new SharpZipBaseException("Illegal rep length code"); + } + goto case DECODE_HUFFMAN_LENBITS; // fall through + + case DECODE_HUFFMAN_LENBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_LENBITS; + int i = input.PeekBits(neededBits); + if (i < 0) + { + return false; + } + input.DropBits(neededBits); + repLength += i; + } + mode = DECODE_HUFFMAN_DIST; + goto case DECODE_HUFFMAN_DIST; // fall through + + case DECODE_HUFFMAN_DIST: + symbol = distTree.GetSymbol(input); + if (symbol < 0) + { + return false; + } + + try + { + repDist = CPDIST[symbol]; + neededBits = CPDEXT[symbol]; + } + catch (Exception) + { + throw new SharpZipBaseException("Illegal rep dist code"); + } + + goto case DECODE_HUFFMAN_DISTBITS; // fall through + + case DECODE_HUFFMAN_DISTBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_DISTBITS; + int i = input.PeekBits(neededBits); + if (i < 0) + { + return false; + } + input.DropBits(neededBits); + repDist += i; + } + + outputWindow.Repeat(repLength, repDist); + free -= repLength; + mode = DECODE_HUFFMAN; + break; + + default: + throw new SharpZipBaseException("Inflater unknown mode"); + } + } + return true; + } + + /// + /// Decodes the adler checksum after the deflate stream. + /// + /// + /// false if more input is needed. + /// + /// + /// If checksum doesn't match. + /// + private bool DecodeChksum() + { + while (neededBits > 0) { + int chkByte = input.PeekBits(8); + if (chkByte < 0) { + return false; + } + input.DropBits(8); + readAdler = (readAdler << 8) | chkByte; + neededBits -= 8; + } + + if ((int) adler.Value != readAdler) { + throw new SharpZipBaseException("Adler chksum doesn't match: " + (int)adler.Value + " vs. " + readAdler); + } + + mode = FINISHED; + return false; + } + + /// + /// Decodes the deflated stream. + /// + /// + /// false if more input is needed, or if finished. + /// + /// + /// if deflated stream is invalid. + /// + private bool Decode() + { + switch (mode) { + case DECODE_HEADER: + return DecodeHeader(); + + case DECODE_DICT: + return DecodeDict(); + + case DECODE_CHKSUM: + return DecodeChksum(); + + case DECODE_BLOCKS: + if (isLastBlock) { + if (noHeader) { + mode = FINISHED; + return false; + } else { + input.SkipToByteBoundary(); + neededBits = 32; + mode = DECODE_CHKSUM; + return true; + } + } + + int type = input.PeekBits(3); + if (type < 0) { + return false; + } + input.DropBits(3); + + if ((type & 1) != 0) { + isLastBlock = true; + } + switch (type >> 1){ + case DeflaterConstants.STORED_BLOCK: + input.SkipToByteBoundary(); + mode = DECODE_STORED_LEN1; + break; + case DeflaterConstants.STATIC_TREES: + litlenTree = InflaterHuffmanTree.defLitLenTree; + distTree = InflaterHuffmanTree.defDistTree; + mode = DECODE_HUFFMAN; + break; + case DeflaterConstants.DYN_TREES: + dynHeader = new InflaterDynHeader(); + mode = DECODE_DYN_HEADER; + break; + default: + throw new SharpZipBaseException("Unknown block type " + type); + } + return true; + + case DECODE_STORED_LEN1: + { + if ((uncomprLen = input.PeekBits(16)) < 0) { + return false; + } + input.DropBits(16); + mode = DECODE_STORED_LEN2; + } + goto case DECODE_STORED_LEN2; // fall through + + case DECODE_STORED_LEN2: + { + int nlen = input.PeekBits(16); + if (nlen < 0) { + return false; + } + input.DropBits(16); + if (nlen != (uncomprLen ^ 0xffff)) { + throw new SharpZipBaseException("broken uncompressed block"); + } + mode = DECODE_STORED; + } + goto case DECODE_STORED; // fall through + + case DECODE_STORED: + { + int more = outputWindow.CopyStored(input, uncomprLen); + uncomprLen -= more; + if (uncomprLen == 0) { + mode = DECODE_BLOCKS; + return true; + } + return !input.IsNeedingInput; + } + + case DECODE_DYN_HEADER: + if (!dynHeader.Decode(input)) { + return false; + } + + litlenTree = dynHeader.BuildLitLenTree(); + distTree = dynHeader.BuildDistTree(); + mode = DECODE_HUFFMAN; + goto case DECODE_HUFFMAN; // fall through + + case DECODE_HUFFMAN: + case DECODE_HUFFMAN_LENBITS: + case DECODE_HUFFMAN_DIST: + case DECODE_HUFFMAN_DISTBITS: + return DecodeHuffman(); + + case FINISHED: + return false; + + default: + throw new SharpZipBaseException("Inflater.Decode unknown mode"); + } + } + + /// + /// Sets the preset dictionary. This should only be called, if + /// needsDictionary() returns true and it should set the same + /// dictionary, that was used for deflating. The getAdler() + /// function returns the checksum of the dictionary needed. + /// + /// + /// The dictionary. + /// + public void SetDictionary(byte[] buffer) + { + SetDictionary(buffer, 0, buffer.Length); + } + + /// + /// Sets the preset dictionary. This should only be called, if + /// needsDictionary() returns true and it should set the same + /// dictionary, that was used for deflating. The getAdler() + /// function returns the checksum of the dictionary needed. + /// + /// + /// The dictionary. + /// + /// + /// The index into buffer where the dictionary starts. + /// + /// + /// The number of bytes in the dictionary. + /// + /// + /// No dictionary is needed. + /// + /// + /// The adler checksum for the buffer is invalid + /// + public void SetDictionary(byte[] buffer, int index, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( index < 0 ) { + throw new ArgumentOutOfRangeException("index"); + } + + if ( count < 0 ) { + throw new ArgumentOutOfRangeException("count"); + } + + if (!IsNeedingDictionary) { + throw new InvalidOperationException("Dictionary is not needed"); + } + + adler.Update(buffer, index, count); + + if ((int)adler.Value != readAdler) { + throw new SharpZipBaseException("Wrong adler checksum"); + } + adler.Reset(); + outputWindow.CopyDict(buffer, index, count); + mode = DECODE_BLOCKS; + } + + /// + /// Sets the input. This should only be called, if needsInput() + /// returns true. + /// + /// + /// the input. + /// + public void SetInput(byte[] buffer) + { + SetInput(buffer, 0, buffer.Length); + } + + /// + /// Sets the input. This should only be called, if needsInput() + /// returns true. + /// + /// + /// The source of input data + /// + /// + /// The index into buffer where the input starts. + /// + /// + /// The number of bytes of input to use. + /// + /// + /// No input is needed. + /// + /// + /// The index and/or count are wrong. + /// + public void SetInput(byte[] buffer, int index, int count) + { + input.SetInput(buffer, index, count); + totalIn += (long)count; + } + + /// + /// Inflates the compressed stream to the output buffer. If this + /// returns 0, you should check, whether IsNeedingDictionary(), + /// IsNeedingInput() or IsFinished() returns true, to determine why no + /// further output is produced. + /// + /// + /// the output buffer. + /// + /// + /// The number of bytes written to the buffer, 0 if no further + /// output can be produced. + /// + /// + /// if buffer has length 0. + /// + /// + /// if deflated stream is invalid. + /// + public int Inflate(byte[] buffer) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + return Inflate(buffer, 0, buffer.Length); + } + + /// + /// Inflates the compressed stream to the output buffer. If this + /// returns 0, you should check, whether needsDictionary(), + /// needsInput() or finished() returns true, to determine why no + /// further output is produced. + /// + /// + /// the output buffer. + /// + /// + /// the offset in buffer where storing starts. + /// + /// + /// the maximum number of bytes to output. + /// + /// + /// the number of bytes written to the buffer, 0 if no further output can be produced. + /// + /// + /// if count is less than 0. + /// + /// + /// if the index and / or count are wrong. + /// + /// + /// if deflated stream is invalid. + /// + public int Inflate(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "count cannot be negative"); +#endif + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "offset cannot be negative"); +#endif + } + + if ( offset + count > buffer.Length ) { + throw new ArgumentException("count exceeds buffer bounds"); + } + + // Special case: count may be zero + if (count == 0) + { + if (!IsFinished) { // -jr- 08-Nov-2003 INFLATE_BUG fix.. + Decode(); + } + return 0; + } + + int bytesCopied = 0; + + do { + if (mode != DECODE_CHKSUM) { + /* Don't give away any output, if we are waiting for the + * checksum in the input stream. + * + * With this trick we have always: + * IsNeedingInput() and not IsFinished() + * implies more output can be produced. + */ + int more = outputWindow.CopyOutput(buffer, offset, count); + if ( more > 0 ) { + adler.Update(buffer, offset, more); + offset += more; + bytesCopied += more; + totalOut += (long)more; + count -= more; + if (count == 0) { + return bytesCopied; + } + } + } + } while (Decode() || ((outputWindow.GetAvailable() > 0) && (mode != DECODE_CHKSUM))); + return bytesCopied; + } + + /// + /// Returns true, if the input buffer is empty. + /// You should then call setInput(). + /// NOTE: This method also returns true when the stream is finished. + /// + public bool IsNeedingInput { + get { + return input.IsNeedingInput; + } + } + + /// + /// Returns true, if a preset dictionary is needed to inflate the input. + /// + public bool IsNeedingDictionary { + get { + return mode == DECODE_DICT && neededBits == 0; + } + } + + /// + /// Returns true, if the inflater has finished. This means, that no + /// input is needed and no output can be produced. + /// + public bool IsFinished { + get { + return mode == FINISHED && outputWindow.GetAvailable() == 0; + } + } + + /// + /// Gets the adler checksum. This is either the checksum of all + /// uncompressed bytes returned by inflate(), or if needsDictionary() + /// returns true (and thus no output was yet produced) this is the + /// adler checksum of the expected dictionary. + /// + /// + /// the adler checksum. + /// + public int Adler { + get { + return IsNeedingDictionary ? readAdler : (int) adler.Value; + } + } + + /// + /// Gets the total number of output bytes returned by Inflate(). + /// + /// + /// the total number of output bytes. + /// + public long TotalOut { + get { + return totalOut; + } + } + + /// + /// Gets the total number of processed compressed input bytes. + /// + /// + /// The total number of bytes of processed input bytes. + /// + public long TotalIn { + get { + return totalIn - (long)RemainingInput; + } + } + + /// + /// Gets the number of unprocessed input bytes. Useful, if the end of the + /// stream is reached and you want to further process the bytes after + /// the deflate stream. + /// + /// + /// The number of bytes of the input which have not been processed. + /// + public int RemainingInput { + // TODO: This should be a long? + get { + return input.AvailableBytes; + } + } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/InflaterDynHeader.cs b/类库/OnlineRepair/ZIP/Zip/Compression/InflaterDynHeader.cs new file mode 100644 index 0000000..77e87ac --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/InflaterDynHeader.cs @@ -0,0 +1,218 @@ +// InflaterDynHeader.cs +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + class InflaterDynHeader + { + #region Constants + const int LNUM = 0; + const int DNUM = 1; + const int BLNUM = 2; + const int BLLENS = 3; + const int LENS = 4; + const int REPS = 5; + + static readonly int[] repMin = { 3, 3, 11 }; + static readonly int[] repBits = { 2, 3, 7 }; + + static readonly int[] BL_ORDER = + { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + #endregion + + #region Constructors + public InflaterDynHeader() + { + } + #endregion + + public bool Decode(StreamManipulator input) + { + decode_loop: + for (;;) { + switch (mode) { + case LNUM: + lnum = input.PeekBits(5); + if (lnum < 0) { + return false; + } + lnum += 257; + input.DropBits(5); + // System.err.println("LNUM: "+lnum); + mode = DNUM; + goto case DNUM; // fall through + case DNUM: + dnum = input.PeekBits(5); + if (dnum < 0) { + return false; + } + dnum++; + input.DropBits(5); + // System.err.println("DNUM: "+dnum); + num = lnum+dnum; + litdistLens = new byte[num]; + mode = BLNUM; + goto case BLNUM; // fall through + case BLNUM: + blnum = input.PeekBits(4); + if (blnum < 0) { + return false; + } + blnum += 4; + input.DropBits(4); + blLens = new byte[19]; + ptr = 0; + // System.err.println("BLNUM: "+blnum); + mode = BLLENS; + goto case BLLENS; // fall through + case BLLENS: + while (ptr < blnum) { + int len = input.PeekBits(3); + if (len < 0) { + return false; + } + input.DropBits(3); + // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); + blLens[BL_ORDER[ptr]] = (byte) len; + ptr++; + } + blTree = new InflaterHuffmanTree(blLens); + blLens = null; + ptr = 0; + mode = LENS; + goto case LENS; // fall through + case LENS: + { + int symbol; + while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) { + /* Normal case: symbol in [0..15] */ + + // System.err.println("litdistLens["+ptr+"]: "+symbol); + litdistLens[ptr++] = lastLen = (byte)symbol; + + if (ptr == num) { + /* Finished */ + return true; + } + } + + /* need more input ? */ + if (symbol < 0) { + return false; + } + + /* otherwise repeat code */ + if (symbol >= 17) { + /* repeat zero */ + // System.err.println("repeating zero"); + lastLen = 0; + } else { + if (ptr == 0) { + throw new SharpZipBaseException(); + } + } + repSymbol = symbol-16; + } + mode = REPS; + goto case REPS; // fall through + case REPS: + { + int bits = repBits[repSymbol]; + int count = input.PeekBits(bits); + if (count < 0) { + return false; + } + input.DropBits(bits); + count += repMin[repSymbol]; + // System.err.println("litdistLens repeated: "+count); + + if (ptr + count > num) { + throw new SharpZipBaseException(); + } + while (count-- > 0) { + litdistLens[ptr++] = lastLen; + } + + if (ptr == num) { + /* Finished */ + return true; + } + } + mode = LENS; + goto decode_loop; + } + } + } + + public InflaterHuffmanTree BuildLitLenTree() + { + byte[] litlenLens = new byte[lnum]; + Array.Copy(litdistLens, 0, litlenLens, 0, lnum); + return new InflaterHuffmanTree(litlenLens); + } + + public InflaterHuffmanTree BuildDistTree() + { + byte[] distLens = new byte[dnum]; + Array.Copy(litdistLens, lnum, distLens, 0, dnum); + return new InflaterHuffmanTree(distLens); + } + + #region Instance Fields + byte[] blLens; + byte[] litdistLens; + + InflaterHuffmanTree blTree; + + /// + /// The current decode mode + /// + int mode; + int lnum, dnum, blnum, num; + int repSymbol; + byte lastLen; + int ptr; + #endregion + + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/InflaterHuffmanTree.cs b/类库/OnlineRepair/ZIP/Zip/Compression/InflaterHuffmanTree.cs new file mode 100644 index 0000000..2f61118 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/InflaterHuffmanTree.cs @@ -0,0 +1,232 @@ +// InflaterHuffmanTree.cs +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// Huffman tree used for inflation + /// + public class InflaterHuffmanTree + { + #region Constants + const int MAX_BITLEN = 15; + #endregion + + #region Instance Fields + short[] tree; + #endregion + + /// + /// Literal length tree + /// + public static InflaterHuffmanTree defLitLenTree; + + /// + /// Distance tree + /// + public static InflaterHuffmanTree defDistTree; + + static InflaterHuffmanTree() + { + try { + byte[] codeLengths = new byte[288]; + int i = 0; + while (i < 144) { + codeLengths[i++] = 8; + } + while (i < 256) { + codeLengths[i++] = 9; + } + while (i < 280) { + codeLengths[i++] = 7; + } + while (i < 288) { + codeLengths[i++] = 8; + } + defLitLenTree = new InflaterHuffmanTree(codeLengths); + + codeLengths = new byte[32]; + i = 0; + while (i < 32) { + codeLengths[i++] = 5; + } + defDistTree = new InflaterHuffmanTree(codeLengths); + } catch (Exception) { + throw new SharpZipBaseException("InflaterHuffmanTree: static tree length illegal"); + } + } + + #region Constructors + /// + /// Constructs a Huffman tree from the array of code lengths. + /// + /// + /// the array of code lengths + /// + public InflaterHuffmanTree(byte[] codeLengths) + { + BuildTree(codeLengths); + } + #endregion + + void BuildTree(byte[] codeLengths) + { + int[] blCount = new int[MAX_BITLEN + 1]; + int[] nextCode = new int[MAX_BITLEN + 1]; + + for (int i = 0; i < codeLengths.Length; i++) { + int bits = codeLengths[i]; + if (bits > 0) { + blCount[bits]++; + } + } + + int code = 0; + int treeSize = 512; + for (int bits = 1; bits <= MAX_BITLEN; bits++) { + nextCode[bits] = code; + code += blCount[bits] << (16 - bits); + if (bits >= 10) { + /* We need an extra table for bit lengths >= 10. */ + int start = nextCode[bits] & 0x1ff80; + int end = code & 0x1ff80; + treeSize += (end - start) >> (16 - bits); + } + } + +/* -jr comment this out! doesnt work for dynamic trees and pkzip 2.04g + if (code != 65536) + { + throw new SharpZipBaseException("Code lengths don't add up properly."); + } +*/ + /* Now create and fill the extra tables from longest to shortest + * bit len. This way the sub trees will be aligned. + */ + tree = new short[treeSize]; + int treePtr = 512; + for (int bits = MAX_BITLEN; bits >= 10; bits--) { + int end = code & 0x1ff80; + code -= blCount[bits] << (16 - bits); + int start = code & 0x1ff80; + for (int i = start; i < end; i += 1 << 7) { + tree[DeflaterHuffman.BitReverse(i)] = (short) ((-treePtr << 4) | bits); + treePtr += 1 << (bits-9); + } + } + + for (int i = 0; i < codeLengths.Length; i++) { + int bits = codeLengths[i]; + if (bits == 0) { + continue; + } + code = nextCode[bits]; + int revcode = DeflaterHuffman.BitReverse(code); + if (bits <= 9) { + do { + tree[revcode] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } while (revcode < 512); + } else { + int subTree = tree[revcode & 511]; + int treeLen = 1 << (subTree & 15); + subTree = -(subTree >> 4); + do { + tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } while (revcode < treeLen); + } + nextCode[bits] = code + (1 << (16 - bits)); + } + + } + + /// + /// Reads the next symbol from input. The symbol is encoded using the + /// huffman tree. + /// + /// + /// input the input source. + /// + /// + /// the next symbol, or -1 if not enough input is available. + /// + public int GetSymbol(StreamManipulator input) + { + int lookahead, symbol; + if ((lookahead = input.PeekBits(9)) >= 0) { + if ((symbol = tree[lookahead]) >= 0) { + input.DropBits(symbol & 15); + return symbol >> 4; + } + int subtree = -(symbol >> 4); + int bitlen = symbol & 15; + if ((lookahead = input.PeekBits(bitlen)) >= 0) { + symbol = tree[subtree | (lookahead >> 9)]; + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + int bits = input.AvailableBits; + lookahead = input.PeekBits(bits); + symbol = tree[subtree | (lookahead >> 9)]; + if ((symbol & 15) <= bits) { + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + return -1; + } + } + } else { + int bits = input.AvailableBits; + lookahead = input.PeekBits(bits); + symbol = tree[lookahead]; + if (symbol >= 0 && (symbol & 15) <= bits) { + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + return -1; + } + } + } + } +} + diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/PendingBuffer.cs b/类库/OnlineRepair/ZIP/Zip/Compression/PendingBuffer.cs new file mode 100644 index 0000000..d205845 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/PendingBuffer.cs @@ -0,0 +1,295 @@ +// PendingBuffer.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class is general purpose class for writing data to a buffer. + /// + /// It allows you to write bits as well as bytes + /// Based on DeflaterPending.java + /// + /// author of the original java version : Jochen Hoenicke + /// + public class PendingBuffer + { + #region Instance Fields + /// + /// Internal work buffer + /// + byte[] buffer_; + + int start; + int end; + + uint bits; + int bitCount; + #endregion + + #region Constructors + /// + /// construct instance using default buffer size of 4096 + /// + public PendingBuffer() : this( 4096 ) + { + } + + /// + /// construct instance using specified buffer size + /// + /// + /// size to use for internal buffer + /// + public PendingBuffer(int bufferSize) + { + buffer_ = new byte[bufferSize]; + } + + #endregion + + /// + /// Clear internal state/buffers + /// + public void Reset() + { + start = end = bitCount = 0; + } + + /// + /// Write a byte to buffer + /// + /// + /// The value to write + /// + public void WriteByte(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + } + + /// + /// Write a short value to buffer LSB first + /// + /// + /// The value to write. + /// + public void WriteShort(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + buffer_[end++] = unchecked((byte) (value >> 8)); + } + + /// + /// write an integer LSB first + /// + /// The value to write. + public void WriteInt(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + buffer_[end++] = unchecked((byte) (value >> 8)); + buffer_[end++] = unchecked((byte) (value >> 16)); + buffer_[end++] = unchecked((byte) (value >> 24)); + } + + /// + /// Write a block of data to buffer + /// + /// data to write + /// offset of first byte to write + /// number of bytes to write + public void WriteBlock(byte[] block, int offset, int length) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + System.Array.Copy(block, offset, buffer_, end, length); + end += length; + } + + /// + /// The number of bits written to the buffer + /// + public int BitCount { + get { + return bitCount; + } + } + + /// + /// Align internal buffer on a byte boundary + /// + public void AlignToByte() + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + if (bitCount > 0) + { + buffer_[end++] = unchecked((byte) bits); + if (bitCount > 8) { + buffer_[end++] = unchecked((byte) (bits >> 8)); + } + } + bits = 0; + bitCount = 0; + } + + /// + /// Write bits to internal buffer + /// + /// source of bits + /// number of bits to write + public void WriteBits(int b, int count) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("writeBits("+b+","+count+")"); + // } +#endif + bits |= (uint)(b << bitCount); + bitCount += count; + if (bitCount >= 16) { + buffer_[end++] = unchecked((byte) bits); + buffer_[end++] = unchecked((byte) (bits >> 8)); + bits >>= 16; + bitCount -= 16; + } + } + + /// + /// Write a short value to internal buffer most significant byte first + /// + /// value to write + public void WriteShortMSB(int s) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) (s >> 8)); + buffer_[end++] = unchecked((byte) s); + } + + /// + /// Indicates if buffer has been flushed + /// + public bool IsFlushed { + get { + return end == 0; + } + } + + /// + /// Flushes the pending buffer into the given output array. If the + /// output array is to small, only a partial flush is done. + /// + /// The output array. + /// The offset into output array. + /// The maximum number of bytes to store. + /// The number of bytes flushed. + public int Flush(byte[] output, int offset, int length) + { + if (bitCount >= 8) { + buffer_[end++] = unchecked((byte) bits); + bits >>= 8; + bitCount -= 8; + } + + if (length > end - start) { + length = end - start; + System.Array.Copy(buffer_, start, output, offset, length); + start = 0; + end = 0; + } else { + System.Array.Copy(buffer_, start, output, offset, length); + start += length; + } + return length; + } + + /// + /// Convert internal buffer to byte array. + /// Buffer is empty on completion + /// + /// + /// The internal buffer contents converted to a byte array. + /// + public byte[] ToByteArray() + { + byte[] result = new byte[end - start]; + System.Array.Copy(buffer_, start, result, 0, result.Length); + start = 0; + end = 0; + return result; + } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs b/类库/OnlineRepair/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs new file mode 100644 index 0000000..55bdb05 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -0,0 +1,602 @@ +// DeflaterOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support + +using System; +using System.IO; + +#if !NETCF_1_0 +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Encryption; +#endif + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + /// + /// A special stream deflating or compressing the bytes that are + /// written to it. It uses a Deflater to perform actual deflating.
+ /// Authors of the original java version : Tom Tromey, Jochen Hoenicke + ///
+ public class DeflaterOutputStream : Stream + { + #region Constructors + /// + /// Creates a new DeflaterOutputStream with a default Deflater and default buffer size. + /// + /// + /// the output stream where deflated output should be written. + /// + public DeflaterOutputStream(Stream baseOutputStream) + : this(baseOutputStream, new Deflater(), 512) + { + } + + /// + /// Creates a new DeflaterOutputStream with the given Deflater and + /// default buffer size. + /// + /// + /// the output stream where deflated output should be written. + /// + /// + /// the underlying deflater. + /// + public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater) + : this(baseOutputStream, deflater, 512) + { + } + + /// + /// Creates a new DeflaterOutputStream with the given Deflater and + /// buffer size. + /// + /// + /// The output stream where deflated output is written. + /// + /// + /// The underlying deflater to use + /// + /// + /// The buffer size in bytes to use when deflating (minimum value 512) + /// + /// + /// bufsize is less than or equal to zero. + /// + /// + /// baseOutputStream does not support writing + /// + /// + /// deflater instance is null + /// + public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int bufferSize) + { + if ( baseOutputStream == null ) { + throw new ArgumentNullException("baseOutputStream"); + } + + if (baseOutputStream.CanWrite == false) { + throw new ArgumentException("Must support writing", "baseOutputStream"); + } + + if (deflater == null) { + throw new ArgumentNullException("deflater"); + } + + if (bufferSize < 512) { + throw new ArgumentOutOfRangeException("bufferSize"); + } + + baseOutputStream_ = baseOutputStream; + buffer_ = new byte[bufferSize]; + deflater_ = deflater; + } + #endregion + + #region Public API + /// + /// Finishes the stream by calling finish() on the deflater. + /// + /// + /// Not all input is deflated + /// + public virtual void Finish() + { + deflater_.Finish(); + while (!deflater_.IsFinished) { + int len = deflater_.Deflate(buffer_, 0, buffer_.Length); + if (len <= 0) { + break; + } + +#if NETCF_1_0 + if ( keys != null ) { +#else + if (cryptoTransform_ != null) { +#endif + EncryptBlock(buffer_, 0, len); + } + + baseOutputStream_.Write(buffer_, 0, len); + } + + if (!deflater_.IsFinished) { + throw new SharpZipBaseException("Can't deflate all input?"); + } + + baseOutputStream_.Flush(); + +#if NETCF_1_0 + if ( keys != null ) { + keys = null; + } +#else + if (cryptoTransform_ != null) { +#if !NET_1_1 && !NETCF_2_0 + if (cryptoTransform_ is ZipAESTransform) { + AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode(); + } +#endif + cryptoTransform_.Dispose(); + cryptoTransform_ = null; + } +#endif + } + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner_; } + set { isStreamOwner_ = value; } + } + + /// + /// Allows client to determine if an entry can be patched after its added + /// + public bool CanPatchEntries { + get { + return baseOutputStream_.CanSeek; + } + } + + #endregion + + #region Encryption + + string password; + +#if NETCF_1_0 + uint[] keys; +#else + ICryptoTransform cryptoTransform_; + + /// + /// Returns the 10 byte AUTH CODE to be appended immediately following the AES data stream. + /// + protected byte[] AESAuthCode; +#endif + + /// + /// Get/set the password used for encryption. + /// + /// When set to null or if the password is empty no encryption is performed + public string Password { + get { + return password; + } + set { + if ( (value != null) && (value.Length == 0) ) { + password = null; + } else { + password = value; + } + } + } + + /// + /// Encrypt a block of data + /// + /// + /// Data to encrypt. NOTE the original contents of the buffer are lost + /// + /// + /// Offset of first byte in buffer to encrypt + /// + /// + /// Number of bytes in buffer to encrypt + /// + protected void EncryptBlock(byte[] buffer, int offset, int length) + { +#if NETCF_1_0 + for (int i = offset; i < offset + length; ++i) { + byte oldbyte = buffer[i]; + buffer[i] ^= EncryptByte(); + UpdateKeys(oldbyte); + } +#else + cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0); +#endif + } + + /// + /// Initializes encryption keys based on given . + /// + /// The password. + protected void InitializePassword(string password) + { +#if NETCF_1_0 + keys = new uint[] { + 0x12345678, + 0x23456789, + 0x34567890 + }; + + byte[] rawPassword = ZipConstants.ConvertToArray(password); + + for (int i = 0; i < rawPassword.Length; ++i) { + UpdateKeys((byte)rawPassword[i]); + } + +#else + PkzipClassicManaged pkManaged = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password)); + cryptoTransform_ = pkManaged.CreateEncryptor(key, null); +#endif + } + +#if !NET_1_1 && !NETCF_2_0 + /// + /// Initializes encryption keys based on given password. + /// + protected void InitializeAESPassword(ZipEntry entry, string rawPassword, + out byte[] salt, out byte[] pwdVerifier) { + salt = new byte[entry.AESSaltLen]; + // Salt needs to be cryptographically random, and unique per file + if (_aesRnd == null) + _aesRnd = new RNGCryptoServiceProvider(); + _aesRnd.GetBytes(salt); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true); + pwdVerifier = ((ZipAESTransform)cryptoTransform_).PwdVerifier; + } +#endif + +#if NETCF_1_0 + + /// + /// Encrypt a single byte + /// + /// + /// The encrypted value + /// + protected byte EncryptByte() + { + uint temp = ((keys[2] & 0xFFFF) | 2); + return (byte)((temp * (temp ^ 1)) >> 8); + } + + /// + /// Update encryption keys + /// + protected void UpdateKeys(byte ch) + { + keys[0] = Crc32.ComputeCrc32(keys[0], ch); + keys[1] = keys[1] + (byte)keys[0]; + keys[1] = keys[1] * 134775813 + 1; + keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24)); + } +#endif + + #endregion + + #region Deflation Support + /// + /// Deflates everything in the input buffers. This will call + /// def.deflate() until all bytes from the input buffers + /// are processed. + /// + protected void Deflate() + { + while (!deflater_.IsNeedingInput) + { + int deflateCount = deflater_.Deflate(buffer_, 0, buffer_.Length); + + if (deflateCount <= 0) { + break; + } +#if NETCF_1_0 + if (keys != null) +#else + if (cryptoTransform_ != null) +#endif + { + EncryptBlock(buffer_, 0, deflateCount); + } + + baseOutputStream_.Write(buffer_, 0, deflateCount); + } + + if (!deflater_.IsNeedingInput) { + throw new SharpZipBaseException("DeflaterOutputStream can't deflate all input?"); + } + } + #endregion + + #region Stream Overrides + /// + /// Gets value indicating stream can be read from + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Gets a value indicating if seeking is supported for this stream + /// This property always returns false + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Get value indicating if this stream supports writing + /// + public override bool CanWrite { + get { + return baseOutputStream_.CanWrite; + } + } + + /// + /// Get current length of stream + /// + public override long Length { + get { + return baseOutputStream_.Length; + } + } + + /// + /// Gets the current position within the stream. + /// + /// Any attempt to set position + public override long Position { + get { + return baseOutputStream_.Position; + } + set { + throw new NotSupportedException("Position property not supported"); + } + } + + /// + /// Sets the current position of this stream to the given value. Not supported by this class! + /// + /// The offset relative to the to seek. + /// The to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("DeflaterOutputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. Not supported by this class! + /// + /// The new stream length. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("DeflaterOutputStream SetLength not supported"); + } + + /// + /// Read a byte from stream advancing position by one + /// + /// The byte read cast to an int. THe value is -1 if at the end of the stream. + /// Any access + public override int ReadByte() + { + throw new NotSupportedException("DeflaterOutputStream ReadByte not supported"); + } + + /// + /// Read a block of bytes from stream + /// + /// The buffer to store read data in. + /// The offset to start storing at. + /// The maximum number of bytes to read. + /// The actual number of bytes read. Zero if end of stream is detected. + /// Any access + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("DeflaterOutputStream Read not supported"); + } + + /// + /// Asynchronous reads are not supported a NotSupportedException is always thrown + /// + /// The buffer to read into. + /// The offset to start storing data at. + /// The number of bytes to read + /// The async callback to use. + /// The state to use. + /// Returns an + /// Any access + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("DeflaterOutputStream BeginRead not currently supported"); + } + + /// + /// Asynchronous writes arent supported, a NotSupportedException is always thrown + /// + /// The buffer to write. + /// The offset to begin writing at. + /// The number of bytes to write. + /// The to use. + /// The state object. + /// Returns an IAsyncResult. + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("BeginWrite is not supported"); + } + + /// + /// Flushes the stream by calling Flush on the deflater and then + /// on the underlying stream. This ensures that all bytes are flushed. + /// + public override void Flush() + { + deflater_.Flush(); + Deflate(); + baseOutputStream_.Flush(); + } + + /// + /// Calls and closes the underlying + /// stream when is true. + /// + public override void Close() + { + if ( !isClosed_ ) { + isClosed_ = true; + + try { + Finish(); +#if NETCF_1_0 + keys=null; +#else + if ( cryptoTransform_ != null ) { + GetAuthCodeIfAES(); + cryptoTransform_.Dispose(); + cryptoTransform_ = null; + } +#endif + } + finally { + if( isStreamOwner_ ) { + baseOutputStream_.Close(); + } + } + } + } + + private void GetAuthCodeIfAES() { +#if !NET_1_1 && !NETCF_2_0 + if (cryptoTransform_ is ZipAESTransform) { + AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode(); + } +#endif + } + + /// + /// Writes a single byte to the compressed output stream. + /// + /// + /// The byte value. + /// + public override void WriteByte(byte value) + { + byte[] b = new byte[1]; + b[0] = value; + Write(b, 0, 1); + } + + /// + /// Writes bytes from an array to the compressed stream. + /// + /// + /// The byte array + /// + /// + /// The offset into the byte array where to start. + /// + /// + /// The number of bytes to write. + /// + public override void Write(byte[] buffer, int offset, int count) + { + deflater_.SetInput(buffer, offset, count); + Deflate(); + } + #endregion + + #region Instance Fields + /// + /// This buffer is used temporarily to retrieve the bytes from the + /// deflater and write them to the underlying output stream. + /// + byte[] buffer_; + + /// + /// The deflater which is used to deflate the stream. + /// + protected Deflater deflater_; + + /// + /// Base stream the deflater depends on. + /// + protected Stream baseOutputStream_; + + bool isClosed_; + + bool isStreamOwner_ = true; + #endregion + + #region Static Fields + +#if !NET_1_1 && !NETCF_2_0 + // Static to help ensure that multiple files within a zip will get different random salt + private static RNGCryptoServiceProvider _aesRnd; +#endif + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/Streams/InflaterInputStream.cs b/类库/OnlineRepair/ZIP/Zip/Compression/Streams/InflaterInputStream.cs new file mode 100644 index 0000000..6699444 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/Streams/InflaterInputStream.cs @@ -0,0 +1,732 @@ +// InflaterInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 11-08-2009 GeoffHart T9121 Added Multi-member gzip support + +using System; +using System.IO; + +#if !NETCF_1_0 +using System.Security.Cryptography; +#endif + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// An input buffer customised for use by + /// + /// + /// The buffer supports decryption of incoming data. + /// + public class InflaterInputBuffer + { + #region Constructors + /// + /// Initialise a new instance of with a default buffer size + /// + /// The stream to buffer. + public InflaterInputBuffer(Stream stream) : this(stream , 4096) + { + } + + /// + /// Initialise a new instance of + /// + /// The stream to buffer. + /// The size to use for the buffer + /// A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB. + public InflaterInputBuffer(Stream stream, int bufferSize) + { + inputStream = stream; + if ( bufferSize < 1024 ) { + bufferSize = 1024; + } + rawData = new byte[bufferSize]; + clearText = rawData; + } + #endregion + + /// + /// Get the length of bytes bytes in the + /// + public int RawLength + { + get { + return rawLength; + } + } + + /// + /// Get the contents of the raw data buffer. + /// + /// This may contain encrypted data. + public byte[] RawData + { + get { + return rawData; + } + } + + /// + /// Get the number of useable bytes in + /// + public int ClearTextLength + { + get { + return clearTextLength; + } + } + + /// + /// Get the contents of the clear text buffer. + /// + public byte[] ClearText + { + get { + return clearText; + } + } + + /// + /// Get/set the number of bytes available + /// + public int Available + { + get { return available; } + set { available = value; } + } + + /// + /// Call passing the current clear text buffer contents. + /// + /// The inflater to set input for. + public void SetInflaterInput(Inflater inflater) + { + if ( available > 0 ) { + inflater.SetInput(clearText, clearTextLength - available, available); + available = 0; + } + } + + /// + /// Fill the buffer from the underlying input stream. + /// + public void Fill() + { + rawLength = 0; + int toRead = rawData.Length; + + while (toRead > 0) { + int count = inputStream.Read(rawData, rawLength, toRead); + if ( count <= 0 ) { + break; + } + rawLength += count; + toRead -= count; + } + +#if !NETCF_1_0 + if ( cryptoTransform != null ) { + clearTextLength = cryptoTransform.TransformBlock(rawData, 0, rawLength, clearText, 0); + } + else +#endif + { + clearTextLength = rawLength; + } + + available = clearTextLength; + } + + /// + /// Read a buffer directly from the input stream + /// + /// The buffer to fill + /// Returns the number of bytes read. + public int ReadRawBuffer(byte[] buffer) + { + return ReadRawBuffer(buffer, 0, buffer.Length); + } + + /// + /// Read a buffer directly from the input stream + /// + /// The buffer to read into + /// The offset to start reading data into. + /// The number of bytes to read. + /// Returns the number of bytes read. + public int ReadRawBuffer(byte[] outBuffer, int offset, int length) + { + if ( length < 0 ) { + throw new ArgumentOutOfRangeException("length"); + } + + int currentOffset = offset; + int currentLength = length; + + while ( currentLength > 0 ) { + if ( available <= 0 ) { + Fill(); + if (available <= 0) { + return 0; + } + } + int toCopy = Math.Min(currentLength, available); + System.Array.Copy(rawData, rawLength - (int)available, outBuffer, currentOffset, toCopy); + currentOffset += toCopy; + currentLength -= toCopy; + available -= toCopy; + } + return length; + } + + /// + /// Read clear text data from the input stream. + /// + /// The buffer to add data to. + /// The offset to start adding data at. + /// The number of bytes to read. + /// Returns the number of bytes actually read. + public int ReadClearTextBuffer(byte[] outBuffer, int offset, int length) + { + if ( length < 0 ) { + throw new ArgumentOutOfRangeException("length"); + } + + int currentOffset = offset; + int currentLength = length; + + while ( currentLength > 0 ) { + if ( available <= 0 ) { + Fill(); + if (available <= 0) { + return 0; + } + } + + int toCopy = Math.Min(currentLength, available); + Array.Copy(clearText, clearTextLength - (int)available, outBuffer, currentOffset, toCopy); + currentOffset += toCopy; + currentLength -= toCopy; + available -= toCopy; + } + return length; + } + + /// + /// Read a from the input stream. + /// + /// Returns the byte read. + public int ReadLeByte() + { + if (available <= 0) { + Fill(); + if (available <= 0) { + throw new ZipException("EOF in header"); + } + } + byte result = rawData[rawLength - available]; + available -= 1; + return result; + } + + /// + /// Read an in little endian byte order. + /// + /// The short value read case to an int. + public int ReadLeShort() + { + return ReadLeByte() | (ReadLeByte() << 8); + } + + /// + /// Read an in little endian byte order. + /// + /// The int value read. + public int ReadLeInt() + { + return ReadLeShort() | (ReadLeShort() << 16); + } + + /// + /// Read a in little endian byte order. + /// + /// The long value read. + public long ReadLeLong() + { + return (uint)ReadLeInt() | ((long)ReadLeInt() << 32); + } + +#if !NETCF_1_0 + /// + /// Get/set the to apply to any data. + /// + /// Set this value to null to have no transform applied. + public ICryptoTransform CryptoTransform + { + set { + cryptoTransform = value; + if ( cryptoTransform != null ) { + if ( rawData == clearText ) { + if ( internalClearText == null ) { + internalClearText = new byte[rawData.Length]; + } + clearText = internalClearText; + } + clearTextLength = rawLength; + if ( available > 0 ) { + cryptoTransform.TransformBlock(rawData, rawLength - available, available, clearText, rawLength - available); + } + } else { + clearText = rawData; + clearTextLength = rawLength; + } + } + } +#endif + + #region Instance Fields + int rawLength; + byte[] rawData; + + int clearTextLength; + byte[] clearText; +#if !NETCF_1_0 + byte[] internalClearText; +#endif + + int available; + +#if !NETCF_1_0 + ICryptoTransform cryptoTransform; +#endif + Stream inputStream; + #endregion + } + + /// + /// This filter stream is used to decompress data compressed using the "deflate" + /// format. The "deflate" format is described in RFC 1951. + /// + /// This stream may form the basis for other decompression filters, such + /// as the GZipInputStream. + /// + /// Author of the original java version : John Leuner. + /// + public class InflaterInputStream : Stream + { + #region Constructors + /// + /// Create an InflaterInputStream with the default decompressor + /// and a default buffer size of 4KB. + /// + /// + /// The InputStream to read bytes from + /// + public InflaterInputStream(Stream baseInputStream) + : this(baseInputStream, new Inflater(), 4096) + { + } + + /// + /// Create an InflaterInputStream with the specified decompressor + /// and a default buffer size of 4KB. + /// + /// + /// The source of input data + /// + /// + /// The decompressor used to decompress data read from baseInputStream + /// + public InflaterInputStream(Stream baseInputStream, Inflater inf) + : this(baseInputStream, inf, 4096) + { + } + + /// + /// Create an InflaterInputStream with the specified decompressor + /// and the specified buffer size. + /// + /// + /// The InputStream to read bytes from + /// + /// + /// The decompressor to use + /// + /// + /// Size of the buffer to use + /// + public InflaterInputStream(Stream baseInputStream, Inflater inflater, int bufferSize) + { + if (baseInputStream == null) { + throw new ArgumentNullException("baseInputStream"); + } + + if (inflater == null) { + throw new ArgumentNullException("inflater"); + } + + if (bufferSize <= 0) { + throw new ArgumentOutOfRangeException("bufferSize"); + } + + this.baseInputStream = baseInputStream; + this.inf = inflater; + + inputBuffer = new InflaterInputBuffer(baseInputStream, bufferSize); + } + + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + /// + /// The default value is true. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Skip specified number of bytes of uncompressed data + /// + /// + /// Number of bytes to skip + /// + /// + /// The number of bytes skipped, zero if the end of + /// stream has been reached + /// + /// + /// The number of bytes to skip is less than or equal to zero. + /// + public long Skip(long count) + { + if (count <= 0) { + throw new ArgumentOutOfRangeException("count"); + } + + // v0.80 Skip by seeking if underlying stream supports it... + if (baseInputStream.CanSeek) { + baseInputStream.Seek(count, SeekOrigin.Current); + return count; + } + else { + int length = 2048; + if (count < length) { + length = (int) count; + } + + byte[] tmp = new byte[length]; + int readCount = 1; + long toSkip = count; + + while ((toSkip > 0) && (readCount > 0) ) { + if (toSkip < length) { + length = (int)toSkip; + } + + readCount = baseInputStream.Read(tmp, 0, length); + toSkip -= readCount; + } + + return count - toSkip; + } + } + + /// + /// Clear any cryptographic state. + /// + protected void StopDecrypting() + { +#if !NETCF_1_0 + inputBuffer.CryptoTransform = null; +#endif + } + + /// + /// Returns 0 once the end of the stream (EOF) has been reached. + /// Otherwise returns 1. + /// + public virtual int Available + { + get { + return inf.IsFinished ? 0 : 1; + } + } + + /// + /// Fills the buffer with more data to decompress. + /// + /// + /// Stream ends early + /// + protected void Fill() + { + // Protect against redundant calls + if (inputBuffer.Available <= 0) { + inputBuffer.Fill(); + if (inputBuffer.Available <= 0) { + throw new SharpZipBaseException("Unexpected EOF"); + } + } + inputBuffer.SetInflaterInput(inf); + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return baseInputStream.CanRead; + } + } + + /// + /// Gets a value of false indicating seeking is not supported for this stream. + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value of false indicating that this stream is not writeable. + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// A value representing the length of the stream in bytes. + /// + public override long Length { + get { + return inputBuffer.RawLength; + } + } + + /// + /// The current position within the stream. + /// Throws a NotSupportedException when attempting to set the position + /// + /// Attempting to set the position + public override long Position { + get { + return baseInputStream.Position; + } + set { + throw new NotSupportedException("InflaterInputStream Position not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + baseInputStream.Flush(); + } + + /// + /// Sets the position within the current stream + /// Always throws a NotSupportedException + /// + /// The relative offset to seek to. + /// The defining where to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Seek not supported"); + } + + /// + /// Set the length of the current stream + /// Always throws a NotSupportedException + /// + /// The new length value for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("InflaterInputStream SetLength not supported"); + } + + /// + /// Writes a sequence of bytes to stream and advances the current position + /// This method always throws a NotSupportedException + /// + /// Thew buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("InflaterInputStream Write not supported"); + } + + /// + /// Writes one byte to the current stream and advances the current position + /// Always throws a NotSupportedException + /// + /// The byte to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("InflaterInputStream WriteByte not supported"); + } + + /// + /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. + /// + /// The buffer to write data from + /// Offset of first byte to write + /// The maximum number of bytes to write + /// The method to be called when the asynchronous write operation is completed + /// A user-provided object that distinguishes this particular asynchronous write request from other requests + /// An IAsyncResult that references the asynchronous write + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); + } + + /// + /// Closes the input stream. When + /// is true the underlying stream is also closed. + /// + public override void Close() + { + if ( !isClosed ) { + isClosed = true; + if ( isStreamOwner ) { + baseInputStream.Close(); + } + } + } + + /// + /// Reads decompressed data into the provided buffer byte array + /// + /// + /// The array to read and decompress data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of bytes to decompress + /// + /// The number of bytes read. Zero signals the end of stream + /// + /// Inflater needs a dictionary + /// + public override int Read(byte[] buffer, int offset, int count) + { + if (inf.IsNeedingDictionary) + { + throw new SharpZipBaseException("Need a dictionary"); + } + + int remainingBytes = count; + while (true) { + int bytesRead = inf.Inflate(buffer, offset, remainingBytes); + offset += bytesRead; + remainingBytes -= bytesRead; + + if (remainingBytes == 0 || inf.IsFinished) { + break; + } + + if ( inf.IsNeedingInput ) { + Fill(); + } + else if ( bytesRead == 0 ) { + throw new ZipException("Dont know what to do"); + } + } + return count - remainingBytes; + } + #endregion + + #region Instance Fields + /// + /// Decompressor for this stream + /// + protected Inflater inf; + + /// + /// Input buffer for this stream. + /// + protected InflaterInputBuffer inputBuffer; + + /// + /// Base stream the inflater reads from. + /// + private Stream baseInputStream; + + /// + /// The compressed size + /// + protected long csize; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + /// + /// Flag indicating wether this instance is designated the stream owner. + /// When closing if this flag is true the underlying stream is closed. + /// + bool isStreamOwner = true; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/Streams/OutputWindow.cs b/类库/OnlineRepair/ZIP/Zip/Compression/Streams/OutputWindow.cs new file mode 100644 index 0000000..be828e2 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/Streams/OutputWindow.cs @@ -0,0 +1,235 @@ +// OutputWindow.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// Contains the output from the Inflation process. + /// We need to have a window so that we can refer backwards into the output stream + /// to repeat stuff.
+ /// Author of the original java version : John Leuner + ///
+ public class OutputWindow + { + #region Constants + const int WindowSize = 1 << 15; + const int WindowMask = WindowSize - 1; + #endregion + + #region Instance Fields + byte[] window = new byte[WindowSize]; //The window is 2^15 bytes + int windowEnd; + int windowFilled; + #endregion + + /// + /// Write a byte to this output window + /// + /// value to write + /// + /// if window is full + /// + public void Write(int value) + { + if (windowFilled++ == WindowSize) { + throw new InvalidOperationException("Window full"); + } + window[windowEnd++] = (byte) value; + windowEnd &= WindowMask; + } + + + private void SlowRepeat(int repStart, int length, int distance) + { + while (length-- > 0) { + window[windowEnd++] = window[repStart++]; + windowEnd &= WindowMask; + repStart &= WindowMask; + } + } + + /// + /// Append a byte pattern already in the window itself + /// + /// length of pattern to copy + /// distance from end of window pattern occurs + /// + /// If the repeated data overflows the window + /// + public void Repeat(int length, int distance) + { + if ((windowFilled += length) > WindowSize) { + throw new InvalidOperationException("Window full"); + } + + int repStart = (windowEnd - distance) & WindowMask; + int border = WindowSize - length; + if ( (repStart <= border) && (windowEnd < border) ) { + if (length <= distance) { + System.Array.Copy(window, repStart, window, windowEnd, length); + windowEnd += length; + } else { + // We have to copy manually, since the repeat pattern overlaps. + while (length-- > 0) { + window[windowEnd++] = window[repStart++]; + } + } + } else { + SlowRepeat(repStart, length, distance); + } + } + + /// + /// Copy from input manipulator to internal window + /// + /// source of data + /// length of data to copy + /// the number of bytes copied + public int CopyStored(StreamManipulator input, int length) + { + length = Math.Min(Math.Min(length, WindowSize - windowFilled), input.AvailableBytes); + int copied; + + int tailLen = WindowSize - windowEnd; + if (length > tailLen) { + copied = input.CopyBytes(window, windowEnd, tailLen); + if (copied == tailLen) { + copied += input.CopyBytes(window, 0, length - tailLen); + } + } else { + copied = input.CopyBytes(window, windowEnd, length); + } + + windowEnd = (windowEnd + copied) & WindowMask; + windowFilled += copied; + return copied; + } + + /// + /// Copy dictionary to window + /// + /// source dictionary + /// offset of start in source dictionary + /// length of dictionary + /// + /// If window isnt empty + /// + public void CopyDict(byte[] dictionary, int offset, int length) + { + if ( dictionary == null ) { + throw new ArgumentNullException("dictionary"); + } + + if (windowFilled > 0) { + throw new InvalidOperationException(); + } + + if (length > WindowSize) { + offset += length - WindowSize; + length = WindowSize; + } + System.Array.Copy(dictionary, offset, window, 0, length); + windowEnd = length & WindowMask; + } + + /// + /// Get remaining unfilled space in window + /// + /// Number of bytes left in window + public int GetFreeSpace() + { + return WindowSize - windowFilled; + } + + /// + /// Get bytes available for output in window + /// + /// Number of bytes filled + public int GetAvailable() + { + return windowFilled; + } + + /// + /// Copy contents of window to output + /// + /// buffer to copy to + /// offset to start at + /// number of bytes to count + /// The number of bytes copied + /// + /// If a window underflow occurs + /// + public int CopyOutput(byte[] output, int offset, int len) + { + int copyEnd = windowEnd; + if (len > windowFilled) { + len = windowFilled; + } else { + copyEnd = (windowEnd - windowFilled + len) & WindowMask; + } + + int copied = len; + int tailLen = len - copyEnd; + + if (tailLen > 0) { + System.Array.Copy(window, WindowSize - tailLen, output, offset, tailLen); + offset += tailLen; + len = copyEnd; + } + System.Array.Copy(window, copyEnd - len, output, offset, len); + windowFilled -= copied; + if (windowFilled < 0) { + throw new InvalidOperationException(); + } + return copied; + } + + /// + /// Reset by clearing window so GetAvailable returns 0 + /// + public void Reset() + { + windowFilled = windowEnd = 0; + } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/Compression/Streams/StreamManipulator.cs b/类库/OnlineRepair/ZIP/Zip/Compression/Streams/StreamManipulator.cs new file mode 100644 index 0000000..ac57e1e --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/Compression/Streams/StreamManipulator.cs @@ -0,0 +1,297 @@ +// StreamManipulator.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// This class allows us to retrieve a specified number of bits from + /// the input buffer, as well as copy big byte blocks. + /// + /// It uses an int buffer to store up to 31 bits for direct + /// manipulation. This guarantees that we can get at least 16 bits, + /// but we only need at most 15, so this is all safe. + /// + /// There are some optimizations in this class, for example, you must + /// never peek more than 8 bits more than needed, and you must first + /// peek bits before you may drop them. This is not a general purpose + /// class but optimized for the behaviour of the Inflater. + /// + /// authors of the original java version : John Leuner, Jochen Hoenicke + /// + public class StreamManipulator + { + #region Constructors + /// + /// Constructs a default StreamManipulator with all buffers empty + /// + public StreamManipulator() + { + } + #endregion + + /// + /// Get the next sequence of bits but don't increase input pointer. bitCount must be + /// less or equal 16 and if this call succeeds, you must drop + /// at least n - 8 bits in the next call. + /// + /// The number of bits to peek. + /// + /// the value of the bits, or -1 if not enough bits available. */ + /// + public int PeekBits(int bitCount) + { + if (bitsInBuffer_ < bitCount) { + if (windowStart_ == windowEnd_) { + return -1; // ok + } + buffer_ |= (uint)((window_[windowStart_++] & 0xff | + (window_[windowStart_++] & 0xff) << 8) << bitsInBuffer_); + bitsInBuffer_ += 16; + } + return (int)(buffer_ & ((1 << bitCount) - 1)); + } + + /// + /// Drops the next n bits from the input. You should have called PeekBits + /// with a bigger or equal n before, to make sure that enough bits are in + /// the bit buffer. + /// + /// The number of bits to drop. + public void DropBits(int bitCount) + { + buffer_ >>= bitCount; + bitsInBuffer_ -= bitCount; + } + + /// + /// Gets the next n bits and increases input pointer. This is equivalent + /// to followed by , except for correct error handling. + /// + /// The number of bits to retrieve. + /// + /// the value of the bits, or -1 if not enough bits available. + /// + public int GetBits(int bitCount) + { + int bits = PeekBits(bitCount); + if (bits >= 0) { + DropBits(bitCount); + } + return bits; + } + + /// + /// Gets the number of bits available in the bit buffer. This must be + /// only called when a previous PeekBits() returned -1. + /// + /// + /// the number of bits available. + /// + public int AvailableBits { + get { + return bitsInBuffer_; + } + } + + /// + /// Gets the number of bytes available. + /// + /// + /// The number of bytes available. + /// + public int AvailableBytes { + get { + return windowEnd_ - windowStart_ + (bitsInBuffer_ >> 3); + } + } + + /// + /// Skips to the next byte boundary. + /// + public void SkipToByteBoundary() + { + buffer_ >>= (bitsInBuffer_ & 7); + bitsInBuffer_ &= ~7; + } + + /// + /// Returns true when SetInput can be called + /// + public bool IsNeedingInput { + get { + return windowStart_ == windowEnd_; + } + } + + /// + /// Copies bytes from input buffer to output buffer starting + /// at output[offset]. You have to make sure, that the buffer is + /// byte aligned. If not enough bytes are available, copies fewer + /// bytes. + /// + /// + /// The buffer to copy bytes to. + /// + /// + /// The offset in the buffer at which copying starts + /// + /// + /// The length to copy, 0 is allowed. + /// + /// + /// The number of bytes copied, 0 if no bytes were available. + /// + /// + /// Length is less than zero + /// + /// + /// Bit buffer isnt byte aligned + /// + public int CopyBytes(byte[] output, int offset, int length) + { + if (length < 0) { + throw new ArgumentOutOfRangeException("length"); + } + + if ((bitsInBuffer_ & 7) != 0) { + // bits_in_buffer may only be 0 or a multiple of 8 + throw new InvalidOperationException("Bit buffer is not byte aligned!"); + } + + int count = 0; + while ((bitsInBuffer_ > 0) && (length > 0)) { + output[offset++] = (byte) buffer_; + buffer_ >>= 8; + bitsInBuffer_ -= 8; + length--; + count++; + } + + if (length == 0) { + return count; + } + + int avail = windowEnd_ - windowStart_; + if (length > avail) { + length = avail; + } + System.Array.Copy(window_, windowStart_, output, offset, length); + windowStart_ += length; + + if (((windowStart_ - windowEnd_) & 1) != 0) { + // We always want an even number of bytes in input, see peekBits + buffer_ = (uint)(window_[windowStart_++] & 0xff); + bitsInBuffer_ = 8; + } + return count + length; + } + + /// + /// Resets state and empties internal buffers + /// + public void Reset() + { + buffer_ = 0; + windowStart_ = windowEnd_ = bitsInBuffer_ = 0; + } + + /// + /// Add more input for consumption. + /// Only call when IsNeedingInput returns true + /// + /// data to be input + /// offset of first byte of input + /// number of bytes of input to add. + public void SetInput(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if (windowStart_ < windowEnd_) { + throw new InvalidOperationException("Old input was not completely processed"); + } + + int end = offset + count; + + // We want to throw an ArrayIndexOutOfBoundsException early. + // Note the check also handles integer wrap around. + if ((offset > end) || (end > buffer.Length) ) { + throw new ArgumentOutOfRangeException("count"); + } + + if ((count & 1) != 0) { + // We always want an even number of bytes in input, see PeekBits + buffer_ |= (uint)((buffer[offset++] & 0xff) << bitsInBuffer_); + bitsInBuffer_ += 8; + } + + window_ = buffer; + windowStart_ = offset; + windowEnd_ = end; + } + + #region Instance Fields + private byte[] window_; + private int windowStart_; + private int windowEnd_; + + private uint buffer_; + private int bitsInBuffer_; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/FastZip.cs b/类库/OnlineRepair/ZIP/Zip/FastZip.cs new file mode 100644 index 0000000..623eea0 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/FastZip.cs @@ -0,0 +1,729 @@ +// FastZip.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// FastZipEvents supports all events applicable to FastZip operations. + /// + public class FastZipEvents + { + /// + /// Delegate to invoke when processing directories. + /// + public ProcessDirectoryHandler ProcessDirectory; + + /// + /// Delegate to invoke when processing files. + /// + public ProcessFileHandler ProcessFile; + + /// + /// Delegate to invoke during processing of files. + /// + public ProgressHandler Progress; + + /// + /// Delegate to invoke when processing for a file has been completed. + /// + public CompletedFileHandler CompletedFile; + + /// + /// Delegate to invoke when processing directory failures. + /// + public DirectoryFailureHandler DirectoryFailure; + + /// + /// Delegate to invoke when processing file failures. + /// + public FileFailureHandler FileFailure; + + /// + /// Raise the directory failure event. + /// + /// The directory causing the failure. + /// The exception for this event. + /// A boolean indicating if execution should continue or not. + public bool OnDirectoryFailure(string directory, Exception e) + { + bool result = false; + DirectoryFailureHandler handler = DirectoryFailure; + + if ( handler != null ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the file failure handler delegate. + /// + /// The file causing the failure. + /// The exception for this failure. + /// A boolean indicating if execution should continue or not. + public bool OnFileFailure(string file, Exception e) + { + FileFailureHandler handler = FileFailure; + bool result = (handler != null); + + if ( result ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(file, e); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the ProcessFile delegate. + /// + /// The file being processed. + /// A boolean indicating if execution should continue or not. + public bool OnProcessFile(string file) + { + bool result = true; + ProcessFileHandler handler = ProcessFile; + + if ( handler != null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the delegate + /// + /// The file whose processing has been completed. + /// A boolean indicating if execution should continue or not. + public bool OnCompletedFile(string file) + { + bool result = true; + CompletedFileHandler handler = CompletedFile; + if ( handler != null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the process directory delegate. + /// + /// The directory being processed. + /// Flag indicating if the directory has matching files as determined by the current filter. + /// A of true if the operation should continue; false otherwise. + public bool OnProcessDirectory(string directory, bool hasMatchingFiles) + { + bool result = true; + ProcessDirectoryHandler handler = ProcessDirectory; + if ( handler != null ) { + DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// The minimum timespan between events. + /// + /// The minimum period of time between events. + /// + /// The default interval is three seconds. + public TimeSpan ProgressInterval + { + get { return progressInterval_; } + set { progressInterval_ = value; } + } + + #region Instance Fields + TimeSpan progressInterval_ = TimeSpan.FromSeconds(3); + #endregion + } + + /// + /// FastZip provides facilities for creating and extracting zip files. + /// + public class FastZip + { + #region Enumerations + /// + /// Defines the desired handling when overwriting files during extraction. + /// + public enum Overwrite + { + /// + /// Prompt the user to confirm overwriting + /// + Prompt, + /// + /// Never overwrite files. + /// + Never, + /// + /// Always overwrite files. + /// + Always + } + #endregion + + #region Constructors + /// + /// Initialise a default instance of . + /// + public FastZip() + { + } + + /// + /// Initialise a new instance of + /// + /// The events to use during operations. + public FastZip(FastZipEvents events) + { + events_ = events; + } + #endregion + + #region Properties + /// + /// Get/set a value indicating wether empty directories should be created. + /// + public bool CreateEmptyDirectories + { + get { return createEmptyDirectories_; } + set { createEmptyDirectories_ = value; } + } + +#if !NETCF_1_0 + /// + /// Get / set the password value. + /// + public string Password + { + get { return password_; } + set { password_ = value; } + } +#endif + + /// + /// Get or set the active when creating Zip files. + /// + /// + public INameTransform NameTransform + { + get { return entryFactory_.NameTransform; } + set { + entryFactory_.NameTransform = value; + } + } + + /// + /// Get or set the active when creating Zip files. + /// + public IEntryFactory EntryFactory + { + get { return entryFactory_; } + set { + if ( value == null ) { + entryFactory_ = new ZipEntryFactory(); + } + else { + entryFactory_ = value; + } + } + } + + /// + /// Gets or sets the setting for Zip64 handling when writing. + /// + /// + /// The default value is dynamic which is not backwards compatible with old + /// programs and can cause problems with XP's built in compression which cant + /// read Zip64 archives. However it does avoid the situation were a large file + /// is added and cannot be completed correctly. + /// NOTE: Setting the size for entries before they are added is the best solution! + /// By default the EntryFactory used by FastZip will set fhe file size. + /// + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + /// + /// Get/set a value indicating wether file dates and times should + /// be restored when extracting files from an archive. + /// + /// The default value is false. + public bool RestoreDateTimeOnExtract + { + get { + return restoreDateTimeOnExtract_; + } + set { + restoreDateTimeOnExtract_ = value; + } + } + + /// + /// Get/set a value indicating wether file attributes should + /// be restored during extract operations + /// + public bool RestoreAttributesOnExtract + { + get { return restoreAttributesOnExtract_; } + set { restoreAttributesOnExtract_ = value; } + } + #endregion + + #region Delegates + /// + /// Delegate called when confirming overwriting of files. + /// + public delegate bool ConfirmOverwriteDelegate(string fileName); + #endregion + + #region CreateZip + /// + /// Create a zip file. + /// + /// The name of the zip file to create. + /// The directory to source files from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + /// The directory filter to apply. + public void CreateZip(string zipFileName, string sourceDirectory, + bool recurse, string fileFilter, string directoryFilter) + { + CreateZip(File.Create(zipFileName), sourceDirectory, recurse, fileFilter, directoryFilter); + } + + /// + /// Create a zip file/archive. + /// + /// The name of the zip file to create. + /// The directory to obtain files and directories from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + public void CreateZip(string zipFileName, string sourceDirectory, bool recurse, string fileFilter) + { + CreateZip(File.Create(zipFileName), sourceDirectory, recurse, fileFilter, null); + } + + /// + /// Create a zip archive sending output to the passed. + /// + /// The stream to write archive data to. + /// The directory to source files from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + /// The directory filter to apply. + /// The is closed after creation. + public void CreateZip(Stream outputStream, string sourceDirectory, bool recurse, string fileFilter, string directoryFilter) + { + NameTransform = new ZipNameTransform(sourceDirectory); + sourceDirectory_ = sourceDirectory; + + using ( outputStream_ = new ZipOutputStream(outputStream) ) { + +#if !NETCF_1_0 + if ( password_ != null ) { + outputStream_.Password = password_; + } +#endif + + outputStream_.UseZip64 = UseZip64; + FileSystemScanner scanner = new FileSystemScanner(fileFilter, directoryFilter); + scanner.ProcessFile += new ProcessFileHandler(ProcessFile); + if ( this.CreateEmptyDirectories ) { + scanner.ProcessDirectory += new ProcessDirectoryHandler(ProcessDirectory); + } + + if (events_ != null) { + if ( events_.FileFailure != null ) { + scanner.FileFailure += events_.FileFailure; + } + + if ( events_.DirectoryFailure != null ) { + scanner.DirectoryFailure += events_.DirectoryFailure; + } + } + + scanner.Scan(sourceDirectory, recurse); + } + } + + #endregion + + #region ExtractZip + /// + /// Extract the contents of a zip file. + /// + /// The zip file to extract from. + /// The directory to save extracted information in. + /// A filter to apply to files. + public void ExtractZip(string zipFileName, string targetDirectory, string fileFilter) + { + ExtractZip(zipFileName, targetDirectory, Overwrite.Always, null, fileFilter, null, restoreDateTimeOnExtract_); + } + + /// + /// Extract the contents of a zip file. + /// + /// The zip file to extract from. + /// The directory to save extracted information in. + /// The style of overwriting to apply. + /// A delegate to invoke when confirming overwriting. + /// A filter to apply to files. + /// A filter to apply to directories. + /// Flag indicating whether to restore the date and time for extracted files. + public void ExtractZip(string zipFileName, string targetDirectory, + Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate, + string fileFilter, string directoryFilter, bool restoreDateTime) + { + Stream inputStream = File.Open(zipFileName, FileMode.Open, FileAccess.Read, FileShare.Read); + ExtractZip(inputStream, targetDirectory, overwrite, confirmDelegate, fileFilter, directoryFilter, restoreDateTime, true); + } + + /// + /// Extract the contents of a zip file held in a stream. + /// + /// The seekable input stream containing the zip to extract from. + /// The directory to save extracted information in. + /// The style of overwriting to apply. + /// A delegate to invoke when confirming overwriting. + /// A filter to apply to files. + /// A filter to apply to directories. + /// Flag indicating whether to restore the date and time for extracted files. + /// Flag indicating whether the inputStream will be closed by this method. + public void ExtractZip(Stream inputStream, string targetDirectory, + Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate, + string fileFilter, string directoryFilter, bool restoreDateTime, + bool isStreamOwner) + { + if ((overwrite == Overwrite.Prompt) && (confirmDelegate == null)) { + throw new ArgumentNullException("confirmDelegate"); + } + + continueRunning_ = true; + overwrite_ = overwrite; + confirmDelegate_ = confirmDelegate; + extractNameTransform_ = new WindowsNameTransform(targetDirectory); + + fileFilter_ = new NameFilter(fileFilter); + directoryFilter_ = new NameFilter(directoryFilter); + restoreDateTimeOnExtract_ = restoreDateTime; + + using (zipFile_ = new ZipFile(inputStream)) { + +#if !NETCF_1_0 + if (password_ != null) { + zipFile_.Password = password_; + } +#endif + zipFile_.IsStreamOwner = isStreamOwner; + System.Collections.IEnumerator enumerator = zipFile_.GetEnumerator(); + while (continueRunning_ && enumerator.MoveNext()) { + ZipEntry entry = (ZipEntry)enumerator.Current; + if (entry.IsFile) + { + // TODO Path.GetDirectory can fail here on invalid characters. + if (directoryFilter_.IsMatch(Path.GetDirectoryName(entry.Name)) && fileFilter_.IsMatch(entry.Name)) { + ExtractEntry(entry); + } + } + else if (entry.IsDirectory) { + if (directoryFilter_.IsMatch(entry.Name) && CreateEmptyDirectories) { + ExtractEntry(entry); + } + } + else { + // Do nothing for volume labels etc... + } + } + } + } + #endregion + + #region Internal Processing + void ProcessDirectory(object sender, DirectoryEventArgs e) + { + if ( !e.HasMatchingFiles && CreateEmptyDirectories ) { + if ( events_ != null ) { + events_.OnProcessDirectory(e.Name, e.HasMatchingFiles); + } + + if ( e.ContinueRunning ) { + if (e.Name != sourceDirectory_) { + ZipEntry entry = entryFactory_.MakeDirectoryEntry(e.Name); + outputStream_.PutNextEntry(entry); + } + } + } + } + + void ProcessFile(object sender, ScanEventArgs e) + { + if ( (events_ != null) && (events_.ProcessFile != null) ) { + events_.ProcessFile(sender, e); + } + + if ( e.ContinueRunning ) { + try { + // The open below is equivalent to OpenRead which gaurantees that if opened the + // file will not be changed by subsequent openers, but precludes opening in some cases + // were it could succeed. + using (FileStream stream = File.Open(e.Name, FileMode.Open, FileAccess.Read, FileShare.Read)) { + ZipEntry entry = entryFactory_.MakeFileEntry(e.Name); + outputStream_.PutNextEntry(entry); + AddFileContents(e.Name, stream); + } + } + catch(Exception ex) { + if (events_ != null) { + continueRunning_ = events_.OnFileFailure(e.Name, ex); + } + else { + continueRunning_ = false; + throw; + } + } + } + } + + void AddFileContents(string name, Stream stream) + { + if( stream==null ) { + throw new ArgumentNullException("stream"); + } + + if( buffer_==null ) { + buffer_=new byte[4096]; + } + + if( (events_!=null)&&(events_.Progress!=null) ) { + StreamUtils.Copy(stream, outputStream_, buffer_, + events_.Progress, events_.ProgressInterval, this, name); + } + else { + StreamUtils.Copy(stream, outputStream_, buffer_); + } + + if( events_!=null ) { + continueRunning_=events_.OnCompletedFile(name); + } + } + + void ExtractFileEntry(ZipEntry entry, string targetName) + { + bool proceed = true; + if ( overwrite_ != Overwrite.Always ) { + if ( File.Exists(targetName) ) { + if ( (overwrite_ == Overwrite.Prompt) && (confirmDelegate_ != null) ) { + proceed = confirmDelegate_(targetName); + } + else { + proceed = false; + } + } + } + + if ( proceed ) { + if ( events_ != null ) { + continueRunning_ = events_.OnProcessFile(entry.Name); + } + + if ( continueRunning_ ) { + try { + using ( FileStream outputStream = File.Create(targetName) ) { + if ( buffer_ == null ) { + buffer_ = new byte[4096]; + } + if ((events_ != null) && (events_.Progress != null)) + { + StreamUtils.Copy(zipFile_.GetInputStream(entry), outputStream, buffer_, + events_.Progress, events_.ProgressInterval, this, entry.Name, entry.Size); + } + else + { + StreamUtils.Copy(zipFile_.GetInputStream(entry), outputStream, buffer_); + } + + if (events_ != null) { + continueRunning_ = events_.OnCompletedFile(entry.Name); + } + } + +#if !NETCF_1_0 && !NETCF_2_0 + if ( restoreDateTimeOnExtract_ ) { + File.SetLastWriteTime(targetName, entry.DateTime); + } + + if ( RestoreAttributesOnExtract && entry.IsDOSEntry && (entry.ExternalFileAttributes != -1)) { + FileAttributes fileAttributes = (FileAttributes) entry.ExternalFileAttributes; + // TODO: FastZip - Setting of other file attributes on extraction is a little trickier. + fileAttributes &= (FileAttributes.Archive | FileAttributes.Normal | FileAttributes.ReadOnly | FileAttributes.Hidden); + File.SetAttributes(targetName, fileAttributes); + } +#endif + } + catch(Exception ex) { + if ( events_ != null ) { + continueRunning_ = events_.OnFileFailure(targetName, ex); + } + else { + continueRunning_ = false; + throw; + } + } + } + } + } + + void ExtractEntry(ZipEntry entry) + { + bool doExtraction = entry.IsCompressionMethodSupported(); + string targetName = entry.Name; + + if ( doExtraction ) { + if ( entry.IsFile ) { + targetName = extractNameTransform_.TransformFile(targetName); + } + else if ( entry.IsDirectory ) { + targetName = extractNameTransform_.TransformDirectory(targetName); + } + + doExtraction = !((targetName == null) || (targetName.Length == 0)); + } + + // TODO: Fire delegate/throw exception were compression method not supported, or name is invalid? + + string dirName = null; + + if ( doExtraction ) { + if ( entry.IsDirectory ) { + dirName = targetName; + } + else { + dirName = Path.GetDirectoryName(Path.GetFullPath(targetName)); + } + } + + if ( doExtraction && !Directory.Exists(dirName) ) { + if ( !entry.IsDirectory || CreateEmptyDirectories ) { + try { + Directory.CreateDirectory(dirName); + } + catch (Exception ex) { + doExtraction = false; + if ( events_ != null ) { + if ( entry.IsDirectory ) { + continueRunning_ = events_.OnDirectoryFailure(targetName, ex); + } + else { + continueRunning_ = events_.OnFileFailure(targetName, ex); + } + } + else { + continueRunning_ = false; + throw; + } + } + } + } + + if ( doExtraction && entry.IsFile ) { + ExtractFileEntry(entry, targetName); + } + } + + static int MakeExternalAttributes(FileInfo info) + { + return (int)info.Attributes; + } + +#if NET_1_0 || NET_1_1 || NETCF_1_0 + static bool NameIsValid(string name) + { + return (name != null) && + (name.Length > 0) && + (name.IndexOfAny(Path.InvalidPathChars) < 0); + } +#else + static bool NameIsValid(string name) + { + return (name != null) && + (name.Length > 0) && + (name.IndexOfAny(Path.GetInvalidPathChars()) < 0); + } +#endif + #endregion + + #region Instance Fields + bool continueRunning_; + byte[] buffer_; + ZipOutputStream outputStream_; + ZipFile zipFile_; + string sourceDirectory_; + NameFilter fileFilter_; + NameFilter directoryFilter_; + Overwrite overwrite_; + ConfirmOverwriteDelegate confirmDelegate_; + + bool restoreDateTimeOnExtract_; + bool restoreAttributesOnExtract_; + bool createEmptyDirectories_; + FastZipEvents events_; + IEntryFactory entryFactory_ = new ZipEntryFactory(); + INameTransform extractNameTransform_; + UseZip64 useZip64_=UseZip64.Dynamic; + +#if !NETCF_1_0 + string password_; +#endif + + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/IEntryFactory.cs b/类库/OnlineRepair/ZIP/Zip/IEntryFactory.cs new file mode 100644 index 0000000..f0bcaee --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/IEntryFactory.cs @@ -0,0 +1,82 @@ +// IEntryFactory.cs +// +// Copyright 2006 John Reilly +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// Defines factory methods for creating new values. + /// + public interface IEntryFactory + { + /// + /// Create a for a file given its name + /// + /// The name of the file to create an entry for. + /// Returns a file entry based on the passed. + ZipEntry MakeFileEntry(string fileName); + + /// + /// Create a for a file given its name + /// + /// The name of the file to create an entry for. + /// If true get details from the file system if the file exists. + /// Returns a file entry based on the passed. + ZipEntry MakeFileEntry(string fileName, bool useFileSystem); + + /// + /// Create a for a directory given its name + /// + /// The name of the directory to create an entry for. + /// Returns a directory entry based on the passed. + ZipEntry MakeDirectoryEntry(string directoryName); + + /// + /// Create a for a directory given its name + /// + /// The name of the directory to create an entry for. + /// If true get details from the file system for this directory if it exists. + /// Returns a directory entry based on the passed. + ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem); + + /// + /// Get/set the applicable. + /// + INameTransform NameTransform { get; set; } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/WindowsNameTransform.cs b/类库/OnlineRepair/ZIP/Zip/WindowsNameTransform.cs new file mode 100644 index 0000000..31430c6 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/WindowsNameTransform.cs @@ -0,0 +1,272 @@ +// WindowsNameTransform.cs +// +// Copyright 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// WindowsNameTransform transforms names to windows compatible ones. + /// + public class WindowsNameTransform : INameTransform + { + /// + /// Initialises a new instance of + /// + /// + public WindowsNameTransform(string baseDirectory) + { + if ( baseDirectory == null ) { + throw new ArgumentNullException("baseDirectory", "Directory name is invalid"); + } + + BaseDirectory = baseDirectory; + } + + /// + /// Initialise a default instance of + /// + public WindowsNameTransform() + { + // Do nothing. + } + + /// + /// Gets or sets a value containing the target directory to prefix values with. + /// + public string BaseDirectory + { + get { return _baseDirectory; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + + _baseDirectory = Path.GetFullPath(value); + } + } + + /// + /// Gets or sets a value indicating wether paths on incoming values should be removed. + /// + public bool TrimIncomingPaths + { + get { return _trimIncomingPaths; } + set { _trimIncomingPaths = value; } + } + + /// + /// Transform a Zip directory name to a windows directory name. + /// + /// The directory name to transform. + /// The transformed name. + public string TransformDirectory(string name) + { + name = TransformFile(name); + if (name.Length > 0) { + while ( name.EndsWith(@"\") ) { + name = name.Remove(name.Length - 1, 1); + } + } + else { + throw new ZipException("Cannot have an empty directory name"); + } + return name; + } + + /// + /// Transform a Zip format file name to a windows style one. + /// + /// The file name to transform. + /// The transformed name. + public string TransformFile(string name) + { + if (name != null) { + name = MakeValidName(name, _replacementChar); + + if ( _trimIncomingPaths ) { + name = Path.GetFileName(name); + } + + // This may exceed windows length restrictions. + // Combine will throw a PathTooLongException in that case. + if ( _baseDirectory != null ) { + name = Path.Combine(_baseDirectory, name); + } + } + else { + name = string.Empty; + } + return name; + } + + /// + /// Test a name to see if it is a valid name for a windows filename as extracted from a Zip archive. + /// + /// The name to test. + /// Returns true if the name is a valid zip name; false otherwise. + /// The filename isnt a true windows path in some fundamental ways like no absolute paths, no rooted paths etc. + public static bool IsValidName(string name) + { + bool result = + (name != null) && + (name.Length <= MaxPath) && + (string.Compare(name, MakeValidName(name, '_')) == 0) + ; + + return result; + } + + /// + /// Initialise static class information. + /// + static WindowsNameTransform() + { + char[] invalidPathChars; + +#if NET_1_0 || NET_1_1 || NETCF_1_0 + invalidPathChars = Path.InvalidPathChars; +#else + invalidPathChars = Path.GetInvalidPathChars(); +#endif + int howMany = invalidPathChars.Length + 3; + + InvalidEntryChars = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length); + InvalidEntryChars[howMany - 1] = '*'; + InvalidEntryChars[howMany - 2] = '?'; + InvalidEntryChars[howMany - 3] = ':'; + } + + /// + /// Force a name to be valid by replacing invalid characters with a fixed value + /// + /// The name to make valid + /// The replacement character to use for any invalid characters. + /// Returns a valid name + public static string MakeValidName(string name, char replacement) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + name = WindowsPathUtils.DropPathRoot(name.Replace("/", @"\")); + + // Drop any leading slashes. + while ( (name.Length > 0) && (name[0] == '\\')) { + name = name.Remove(0, 1); + } + + // Drop any trailing slashes. + while ( (name.Length > 0) && (name[name.Length - 1] == '\\')) { + name = name.Remove(name.Length - 1, 1); + } + + // Convert consecutive \\ characters to \ + int index = name.IndexOf(@"\\"); + while (index >= 0) { + name = name.Remove(index, 1); + index = name.IndexOf(@"\\"); + } + + // Convert any invalid characters using the replacement one. + index = name.IndexOfAny(InvalidEntryChars); + if (index >= 0) { + StringBuilder builder = new StringBuilder(name); + + while (index >= 0 ) { + builder[index] = replacement; + + if (index >= name.Length) { + index = -1; + } + else { + index = name.IndexOfAny(InvalidEntryChars, index + 1); + } + } + name = builder.ToString(); + } + + // Check for names greater than MaxPath characters. + // TODO: Were is CLR version of MaxPath defined? Can't find it in Environment. + if ( name.Length > MaxPath ) { + throw new PathTooLongException(); + } + + return name; + } + + /// + /// Gets or set the character to replace invalid characters during transformations. + /// + public char Replacement + { + get { return _replacementChar; } + set { + for ( int i = 0; i < InvalidEntryChars.Length; ++i ) { + if ( InvalidEntryChars[i] == value ) { + throw new ArgumentException("invalid path character"); + } + } + + if ((value == '\\') || (value == '/')) { + throw new ArgumentException("invalid replacement character"); + } + + _replacementChar = value; + } + } + + /// + /// The maximum windows path name permitted. + /// + /// This may not valid for all windows systems - CE?, etc but I cant find the equivalent in the CLR. + const int MaxPath = 260; + + #region Instance Fields + string _baseDirectory; + bool _trimIncomingPaths; + char _replacementChar = '_'; + #endregion + + #region Class Fields + static readonly char[] InvalidEntryChars; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipConstants.cs b/类库/OnlineRepair/ZIP/Zip/ZipConstants.cs new file mode 100644 index 0000000..3a19c5f --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipConstants.cs @@ -0,0 +1,632 @@ +// ZipConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support + +using System; +using System.Text; +using System.Threading; + +#if NETCF_1_0 || NETCF_2_0 +using System.Globalization; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + + #region Enumerations + + /// + /// Determines how entries are tested to see if they should use Zip64 extensions or not. + /// + public enum UseZip64 + { + /// + /// Zip64 will not be forced on entries during processing. + /// + /// An entry can have this overridden if required + Off, + /// + /// Zip64 should always be used. + /// + On, + /// + /// #ZipLib will determine use based on entry values when added to archive. + /// + Dynamic, + } + + /// + /// The kind of compression used for an entry in an archive + /// + public enum CompressionMethod + { + /// + /// A direct copy of the file contents is held in the archive + /// + Stored = 0, + + /// + /// Common Zip compression method using a sliding dictionary + /// of up to 32KB and secondary compression from Huffman/Shannon-Fano trees + /// + Deflated = 8, + + /// + /// An extension to deflate with a 64KB window. Not supported by #Zip currently + /// + Deflate64 = 9, + + /// + /// BZip2 compression. Not supported by #Zip. + /// + BZip2 = 11, + + /// + /// WinZip special for AES encryption, Now supported by #Zip. + /// + WinZipAES = 99, + + } + + /// + /// Identifies the encryption algorithm used for an entry + /// + public enum EncryptionAlgorithm + { + /// + /// No encryption has been used. + /// + None = 0, + /// + /// Encrypted using PKZIP 2.0 or 'classic' encryption. + /// + PkzipClassic = 1, + /// + /// DES encryption has been used. + /// + Des = 0x6601, + /// + /// RCS encryption has been used for encryption. + /// + RC2 = 0x6602, + /// + /// Triple DES encryption with 168 bit keys has been used for this entry. + /// + TripleDes168 = 0x6603, + /// + /// Triple DES with 112 bit keys has been used for this entry. + /// + TripleDes112 = 0x6609, + /// + /// AES 128 has been used for encryption. + /// + Aes128 = 0x660e, + /// + /// AES 192 has been used for encryption. + /// + Aes192 = 0x660f, + /// + /// AES 256 has been used for encryption. + /// + Aes256 = 0x6610, + /// + /// RC2 corrected has been used for encryption. + /// + RC2Corrected = 0x6702, + /// + /// Blowfish has been used for encryption. + /// + Blowfish = 0x6720, + /// + /// Twofish has been used for encryption. + /// + Twofish = 0x6721, + /// + /// RC4 has been used for encryption. + /// + RC4 = 0x6801, + /// + /// An unknown algorithm has been used for encryption. + /// + Unknown = 0xffff + } + + /// + /// Defines the contents of the general bit flags field for an archive entry. + /// + [Flags] + public enum GeneralBitFlags : int + { + /// + /// Bit 0 if set indicates that the file is encrypted + /// + Encrypted = 0x0001, + /// + /// Bits 1 and 2 - Two bits defining the compression method (only for Method 6 Imploding and 8,9 Deflating) + /// + Method = 0x0006, + /// + /// Bit 3 if set indicates a trailing data desciptor is appended to the entry data + /// + Descriptor = 0x0008, + /// + /// Bit 4 is reserved for use with method 8 for enhanced deflation + /// + ReservedPKware4 = 0x0010, + /// + /// Bit 5 if set indicates the file contains Pkzip compressed patched data. + /// Requires version 2.7 or greater. + /// + Patched = 0x0020, + /// + /// Bit 6 if set indicates strong encryption has been used for this entry. + /// + StrongEncryption = 0x0040, + /// + /// Bit 7 is currently unused + /// + Unused7 = 0x0080, + /// + /// Bit 8 is currently unused + /// + Unused8 = 0x0100, + /// + /// Bit 9 is currently unused + /// + Unused9 = 0x0200, + /// + /// Bit 10 is currently unused + /// + Unused10 = 0x0400, + /// + /// Bit 11 if set indicates the filename and + /// comment fields for this file must be encoded using UTF-8. + /// + UnicodeText = 0x0800, + /// + /// Bit 12 is documented as being reserved by PKware for enhanced compression. + /// + EnhancedCompress = 0x1000, + /// + /// Bit 13 if set indicates that values in the local header are masked to hide + /// their actual values, and the central directory is encrypted. + /// + /// + /// Used when encrypting the central directory contents. + /// + HeaderMasked = 0x2000, + /// + /// Bit 14 is documented as being reserved for use by PKware + /// + ReservedPkware14 = 0x4000, + /// + /// Bit 15 is documented as being reserved for use by PKware + /// + ReservedPkware15 = 0x8000 + } + + #endregion + + /// + /// This class contains constants used for Zip format files + /// + public sealed class ZipConstants + { + #region Versions + /// + /// The version made by field for entries in the central header when created by this library + /// + /// + /// This is also the Zip version for the library when comparing against the version required to extract + /// for an entry. See . + /// + public const int VersionMadeBy = 51; // was 45 before AES + + /// + /// The version made by field for entries in the central header when created by this library + /// + /// + /// This is also the Zip version for the library when comparing against the version required to extract + /// for an entry. See ZipInputStream.CanDecompressEntry. + /// + [Obsolete("Use VersionMadeBy instead")] + public const int VERSION_MADE_BY = 51; + + /// + /// The minimum version required to support strong encryption + /// + public const int VersionStrongEncryption = 50; + + /// + /// The minimum version required to support strong encryption + /// + [Obsolete("Use VersionStrongEncryption instead")] + public const int VERSION_STRONG_ENCRYPTION = 50; + + /// + /// Version indicating AES encryption + /// + public const int VERSION_AES = 51; + + /// + /// The version required for Zip64 extensions (4.5 or higher) + /// + public const int VersionZip64 = 45; + #endregion + + #region Header Sizes + /// + /// Size of local entry header (excluding variable length fields at end) + /// + public const int LocalHeaderBaseSize = 30; + + /// + /// Size of local entry header (excluding variable length fields at end) + /// + [Obsolete("Use LocalHeaderBaseSize instead")] + public const int LOCHDR = 30; + + /// + /// Size of Zip64 data descriptor + /// + public const int Zip64DataDescriptorSize = 24; + + /// + /// Size of data descriptor + /// + public const int DataDescriptorSize = 16; + + /// + /// Size of data descriptor + /// + [Obsolete("Use DataDescriptorSize instead")] + public const int EXTHDR = 16; + + /// + /// Size of central header entry (excluding variable fields) + /// + public const int CentralHeaderBaseSize = 46; + + /// + /// Size of central header entry + /// + [Obsolete("Use CentralHeaderBaseSize instead")] + public const int CENHDR = 46; + + /// + /// Size of end of central record (excluding variable fields) + /// + public const int EndOfCentralRecordBaseSize = 22; + + /// + /// Size of end of central record (excluding variable fields) + /// + [Obsolete("Use EndOfCentralRecordBaseSize instead")] + public const int ENDHDR = 22; + + /// + /// Size of 'classic' cryptographic header stored before any entry data + /// + public const int CryptoHeaderSize = 12; + + /// + /// Size of cryptographic header stored before entry data + /// + [Obsolete("Use CryptoHeaderSize instead")] + public const int CRYPTO_HEADER_SIZE = 12; + #endregion + + #region Header Signatures + + /// + /// Signature for local entry header + /// + public const int LocalHeaderSignature = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); + + /// + /// Signature for local entry header + /// + [Obsolete("Use LocalHeaderSignature instead")] + public const int LOCSIG = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); + + /// + /// Signature for spanning entry + /// + public const int SpanningSignature = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for spanning entry + /// + [Obsolete("Use SpanningSignature instead")] + public const int SPANNINGSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for temporary spanning entry + /// + public const int SpanningTempSignature = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24); + + /// + /// Signature for temporary spanning entry + /// + [Obsolete("Use SpanningTempSignature instead")] + public const int SPANTEMPSIG = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24); + + /// + /// Signature for data descriptor + /// + /// + /// This is only used where the length, Crc, or compressed size isnt known when the + /// entry is created and the output stream doesnt support seeking. + /// The local entry cannot be 'patched' with the correct values in this case + /// so the values are recorded after the data prefixed by this header, as well as in the central directory. + /// + public const int DataDescriptorSignature = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for data descriptor + /// + /// + /// This is only used where the length, Crc, or compressed size isnt known when the + /// entry is created and the output stream doesnt support seeking. + /// The local entry cannot be 'patched' with the correct values in this case + /// so the values are recorded after the data prefixed by this header, as well as in the central directory. + /// + [Obsolete("Use DataDescriptorSignature instead")] + public const int EXTSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for central header + /// + [Obsolete("Use CentralHeaderSignature instead")] + public const int CENSIG = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); + + /// + /// Signature for central header + /// + public const int CentralHeaderSignature = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); + + /// + /// Signature for Zip64 central file header + /// + public const int Zip64CentralFileHeaderSignature = 'P' | ('K' << 8) | (6 << 16) | (6 << 24); + + /// + /// Signature for Zip64 central file header + /// + [Obsolete("Use Zip64CentralFileHeaderSignature instead")] + public const int CENSIG64 = 'P' | ('K' << 8) | (6 << 16) | (6 << 24); + + /// + /// Signature for Zip64 central directory locator + /// + public const int Zip64CentralDirLocatorSignature = 'P' | ('K' << 8) | (6 << 16) | (7 << 24); + + /// + /// Signature for archive extra data signature (were headers are encrypted). + /// + public const int ArchiveExtraDataSignature = 'P' | ('K' << 8) | (6 << 16) | (7 << 24); + + /// + /// Central header digitial signature + /// + public const int CentralHeaderDigitalSignature = 'P' | ('K' << 8) | (5 << 16) | (5 << 24); + + /// + /// Central header digitial signature + /// + [Obsolete("Use CentralHeaderDigitalSignaure instead")] + public const int CENDIGITALSIG = 'P' | ('K' << 8) | (5 << 16) | (5 << 24); + + /// + /// End of central directory record signature + /// + public const int EndOfCentralDirectorySignature = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); + + /// + /// End of central directory record signature + /// + [Obsolete("Use EndOfCentralDirectorySignature instead")] + public const int ENDSIG = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); + #endregion + +#if NETCF_1_0 || NETCF_2_0 + // This isnt so great but is better than nothing. + // Trying to work out an appropriate OEM code page would be good. + // 850 is a good default for english speakers particularly in Europe. + static int defaultCodePage = CultureInfo.CurrentCulture.TextInfo.ANSICodePage; +#else + static int defaultCodePage = Thread.CurrentThread.CurrentCulture.TextInfo.OEMCodePage; +#endif + + /// + /// Default encoding used for string conversion. 0 gives the default system OEM code page. + /// Dont use unicode encodings if you want to be Zip compatible! + /// Using the default code page isnt the full solution neccessarily + /// there are many variable factors, codepage 850 is often a good choice for + /// European users, however be careful about compatability. + /// + public static int DefaultCodePage { + get { + return defaultCodePage; + } + set { + defaultCodePage = value; + } + } + + /// + /// Convert a portion of a byte array to a string. + /// + /// + /// Data to convert to string + /// + /// + /// Number of bytes to convert starting from index 0 + /// + /// + /// data[0]..data[length - 1] converted to a string + /// + public static string ConvertToString(byte[] data, int count) + { + if ( data == null ) { + return string.Empty; + } + + return Encoding.GetEncoding(DefaultCodePage).GetString(data, 0, count); + } + + /// + /// Convert a byte array to string + /// + /// + /// Byte array to convert + /// + /// + /// dataconverted to a string + /// + public static string ConvertToString(byte[] data) + { + if ( data == null ) { + return string.Empty; + } + return ConvertToString(data, data.Length); + } + + /// + /// Convert a byte array to string + /// + /// The applicable general purpose bits flags + /// + /// Byte array to convert + /// + /// The number of bytes to convert. + /// + /// dataconverted to a string + /// + public static string ConvertToStringExt(int flags, byte[] data, int count) + { + if ( data == null ) { + return string.Empty; + } + + if ( (flags & (int)GeneralBitFlags.UnicodeText) != 0 ) { + return Encoding.UTF8.GetString(data, 0, count); + } + else { + return ConvertToString(data, count); + } + } + + /// + /// Convert a byte array to string + /// + /// + /// Byte array to convert + /// + /// The applicable general purpose bits flags + /// + /// dataconverted to a string + /// + public static string ConvertToStringExt(int flags, byte[] data) + { + if ( data == null ) { + return string.Empty; + } + + if ( (flags & (int)GeneralBitFlags.UnicodeText) != 0 ) { + return Encoding.UTF8.GetString(data, 0, data.Length); + } + else { + return ConvertToString(data, data.Length); + } + } + + /// + /// Convert a string to a byte array + /// + /// + /// String to convert to an array + /// + /// Converted array + public static byte[] ConvertToArray(string str) + { + if ( str == null ) { + return new byte[0]; + } + + return Encoding.GetEncoding(DefaultCodePage).GetBytes(str); + } + + /// + /// Convert a string to a byte array + /// + /// The applicable general purpose bits flags + /// + /// String to convert to an array + /// + /// Converted array + public static byte[] ConvertToArray(int flags, string str) + { + if (str == null) { + return new byte[0]; + } + + if ((flags & (int)GeneralBitFlags.UnicodeText) != 0) { + return Encoding.UTF8.GetBytes(str); + } + else { + return ConvertToArray(str); + } + } + + + /// + /// Initialise default instance of ZipConstants + /// + /// + /// Private to prevent instances being created. + /// + ZipConstants() + { + // Do nothing + } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipEntry.cs b/类库/OnlineRepair/ZIP/Zip/ZipEntry.cs new file mode 100644 index 0000000..febbc20 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipEntry.cs @@ -0,0 +1,1252 @@ +// ZipEntry.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support +// 02-02-2010 DavidPierson Changed NTFS Extra Data min length to 4 + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Defines known values for the property. + /// + public enum HostSystemID + { + /// + /// Host system = MSDOS + /// + Msdos = 0, + /// + /// Host system = Amiga + /// + Amiga = 1, + /// + /// Host system = Open VMS + /// + OpenVms = 2, + /// + /// Host system = Unix + /// + Unix = 3, + /// + /// Host system = VMCms + /// + VMCms = 4, + /// + /// Host system = Atari ST + /// + AtariST = 5, + /// + /// Host system = OS2 + /// + OS2 = 6, + /// + /// Host system = Macintosh + /// + Macintosh = 7, + /// + /// Host system = ZSystem + /// + ZSystem = 8, + /// + /// Host system = Cpm + /// + Cpm = 9, + /// + /// Host system = Windows NT + /// + WindowsNT = 10, + /// + /// Host system = MVS + /// + MVS = 11, + /// + /// Host system = VSE + /// + Vse = 12, + /// + /// Host system = Acorn RISC + /// + AcornRisc = 13, + /// + /// Host system = VFAT + /// + Vfat = 14, + /// + /// Host system = Alternate MVS + /// + AlternateMvs = 15, + /// + /// Host system = BEOS + /// + BeOS = 16, + /// + /// Host system = Tandem + /// + Tandem = 17, + /// + /// Host system = OS400 + /// + OS400 = 18, + /// + /// Host system = OSX + /// + OSX = 19, + /// + /// Host system = WinZIP AES + /// + WinZipAES = 99, + } + + /// + /// This class represents an entry in a zip archive. This can be a file + /// or a directory + /// ZipFile and ZipInputStream will give you instances of this class as + /// information about the members in an archive. ZipOutputStream + /// uses an instance of this class when creating an entry in a Zip file. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ public class ZipEntry : ICloneable + { + [Flags] + enum Known : byte + { + None = 0, + Size = 0x01, + CompressedSize = 0x02, + Crc = 0x04, + Time = 0x08, + ExternalAttributes = 0x10, + } + + #region Constructors + /// + /// Creates a zip entry with the given name. + /// + /// + /// The name for this entry. Can include directory components. + /// The convention for names is 'unix' style paths with relative names only. + /// There are with no device names and path elements are separated by '/' characters. + /// + /// + /// The name passed is null + /// + public ZipEntry(string name) + : this(name, 0, ZipConstants.VersionMadeBy, CompressionMethod.Deflated) + { + } + + /// + /// Creates a zip entry with the given name and version required to extract + /// + /// + /// The name for this entry. Can include directory components. + /// The convention for names is 'unix' style paths with no device names and + /// path elements separated by '/' characters. This is not enforced see CleanName + /// on how to ensure names are valid if this is desired. + /// + /// + /// The minimum 'feature version' required this entry + /// + /// + /// The name passed is null + /// + internal ZipEntry(string name, int versionRequiredToExtract) + : this(name, versionRequiredToExtract, ZipConstants.VersionMadeBy, + CompressionMethod.Deflated) + { + } + + /// + /// Initializes an entry with the given name and made by information + /// + /// Name for this entry + /// Version and HostSystem Information + /// Minimum required zip feature version required to extract this entry + /// Compression method for this entry. + /// + /// The name passed is null + /// + /// + /// versionRequiredToExtract should be 0 (auto-calculate) or > 10 + /// + /// + /// This constructor is used by the ZipFile class when reading from the central header + /// It is not generally useful, use the constructor specifying the name only. + /// + internal ZipEntry(string name, int versionRequiredToExtract, int madeByInfo, + CompressionMethod method) + { + if (name == null) { + throw new System.ArgumentNullException("name"); + } + + if ( name.Length > 0xffff ) { + throw new ArgumentException("Name is too long", "name"); + } + + if ( (versionRequiredToExtract != 0) && (versionRequiredToExtract < 10) ) { + throw new ArgumentOutOfRangeException("versionRequiredToExtract"); + } + + this.DateTime = System.DateTime.Now; + this.name = name; + this.versionMadeBy = (ushort)madeByInfo; + this.versionToExtract = (ushort)versionRequiredToExtract; + this.method = method; + } + + /// + /// Creates a deep copy of the given zip entry. + /// + /// + /// The entry to copy. + /// + [Obsolete("Use Clone instead")] + public ZipEntry(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + known = entry.known; + name = entry.name; + size = entry.size; + compressedSize = entry.compressedSize; + crc = entry.crc; + dosTime = entry.dosTime; + method = entry.method; + comment = entry.comment; + versionToExtract = entry.versionToExtract; + versionMadeBy = entry.versionMadeBy; + externalFileAttributes = entry.externalFileAttributes; + flags = entry.flags; + + zipFileIndex = entry.zipFileIndex; + offset = entry.offset; + + forceZip64_ = entry.forceZip64_; + + if ( entry.extra != null ) { + extra = new byte[entry.extra.Length]; + Array.Copy(entry.extra, 0, extra, 0, entry.extra.Length); + } + } + + #endregion + + /// + /// Get a value indicating wether the entry has a CRC value available. + /// + public bool HasCrc + { + get { + return (known & Known.Crc) != 0; + } + } + + /// + /// Get/Set flag indicating if entry is encrypted. + /// A simple helper routine to aid interpretation of flags + /// + /// This is an assistant that interprets the flags property. + public bool IsCrypted + { + get { + return (flags & 1) != 0; + } + set { + if (value) { + flags |= 1; + } + else { + flags &= ~1; + } + } + } + + /// + /// Get / set a flag indicating wether entry name and comment text are + /// encoded in unicode UTF8. + /// + /// This is an assistant that interprets the flags property. + public bool IsUnicodeText + { + get { + return ( flags & (int)GeneralBitFlags.UnicodeText ) != 0; + } + set { + if ( value ) { + flags |= (int)GeneralBitFlags.UnicodeText; + } + else { + flags &= ~(int)GeneralBitFlags.UnicodeText; + } + } + } + + /// + /// Value used during password checking for PKZIP 2.0 / 'classic' encryption. + /// + internal byte CryptoCheckValue + { + get { + return cryptoCheckValue_; + } + + set { + cryptoCheckValue_ = value; + } + } + + /// + /// Get/Set general purpose bit flag for entry + /// + /// + /// General purpose bit flag
+ ///
+ /// Bit 0: If set, indicates the file is encrypted
+ /// Bit 1-2 Only used for compression type 6 Imploding, and 8, 9 deflating
+ /// Imploding:
+ /// Bit 1 if set indicates an 8K sliding dictionary was used. If clear a 4k dictionary was used
+ /// Bit 2 if set indicates 3 Shannon-Fanno trees were used to encode the sliding dictionary, 2 otherwise
+ ///
+ /// Deflating:
+ /// Bit 2 Bit 1
+ /// 0 0 Normal compression was used
+ /// 0 1 Maximum compression was used
+ /// 1 0 Fast compression was used
+ /// 1 1 Super fast compression was used
+ ///
+ /// Bit 3: If set, the fields crc-32, compressed size + /// and uncompressed size are were not able to be written during zip file creation + /// The correct values are held in a data descriptor immediately following the compressed data.
+ /// Bit 4: Reserved for use by PKZIP for enhanced deflating
+ /// Bit 5: If set indicates the file contains compressed patch data
+ /// Bit 6: If set indicates strong encryption was used.
+ /// Bit 7-10: Unused or reserved
+ /// Bit 11: If set the name and comments for this entry are in unicode.
+ /// Bit 12-15: Unused or reserved
+ ///
+ /// + /// + public int Flags + { + get { + return flags; + } + set { + flags = value; + } + } + + /// + /// Get/Set index of this entry in Zip file + /// + /// This is only valid when the entry is part of a + public long ZipFileIndex + { + get { + return zipFileIndex; + } + set { + zipFileIndex = value; + } + } + + /// + /// Get/set offset for use in central header + /// + public long Offset + { + get { + return offset; + } + set { + offset = value; + } + } + + /// + /// Get/Set external file attributes as an integer. + /// The values of this are operating system dependant see + /// HostSystem for details + /// + public int ExternalFileAttributes + { + get { + if ((known & Known.ExternalAttributes) == 0) { + return -1; + } + else { + return externalFileAttributes; + } + } + + set { + externalFileAttributes = value; + known |= Known.ExternalAttributes; + } + } + + /// + /// Get the version made by for this entry or zero if unknown. + /// The value / 10 indicates the major version number, and + /// the value mod 10 is the minor version number + /// + public int VersionMadeBy + { + get { + return (versionMadeBy & 0xff); + } + } + + /// + /// Get a value indicating this entry is for a DOS/Windows system. + /// + public bool IsDOSEntry + { + get { + return ((HostSystem == ( int )HostSystemID.Msdos) || + (HostSystem == ( int )HostSystemID.WindowsNT)); + } + } + + /// + /// Test the external attributes for this to + /// see if the external attributes are Dos based (including WINNT and variants) + /// and match the values + /// + /// The attributes to test. + /// Returns true if the external attributes are known to be DOS/Windows + /// based and have the same attributes set as the value passed. + bool HasDosAttributes(int attributes) + { + bool result = false; + if ( (known & Known.ExternalAttributes) != 0 ) { + if ( ((HostSystem == (int)HostSystemID.Msdos) || + (HostSystem == (int)HostSystemID.WindowsNT)) && + (ExternalFileAttributes & attributes) == attributes) { + result = true; + } + } + return result; + } + + /// + /// Gets the compatability information for the external file attribute + /// If the external file attributes are compatible with MS-DOS and can be read + /// by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value + /// will be non-zero and identify the host system on which the attributes are compatible. + /// + /// + /// + /// The values for this as defined in the Zip File format and by others are shown below. The values are somewhat + /// misleading in some cases as they are not all used as shown. You should consult the relevant documentation + /// to obtain up to date and correct information. The modified appnote by the infozip group is + /// particularly helpful as it documents a lot of peculiarities. The document is however a little dated. + /// + /// 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + /// 1 - Amiga + /// 2 - OpenVMS + /// 3 - Unix + /// 4 - VM/CMS + /// 5 - Atari ST + /// 6 - OS/2 HPFS + /// 7 - Macintosh + /// 8 - Z-System + /// 9 - CP/M + /// 10 - Windows NTFS + /// 11 - MVS (OS/390 - Z/OS) + /// 12 - VSE + /// 13 - Acorn Risc + /// 14 - VFAT + /// 15 - Alternate MVS + /// 16 - BeOS + /// 17 - Tandem + /// 18 - OS/400 + /// 19 - OS/X (Darwin) + /// 99 - WinZip AES + /// remainder - unused + /// + /// + public int HostSystem + { + get { + return (versionMadeBy >> 8) & 0xff; + } + + set { + versionMadeBy &= 0xff; + versionMadeBy |= (ushort)((value & 0xff) << 8); + } + } + + /// + /// Get minimum Zip feature version required to extract this entry + /// + /// + /// Minimum features are defined as:
+ /// 1.0 - Default value
+ /// 1.1 - File is a volume label
+ /// 2.0 - File is a folder/directory
+ /// 2.0 - File is compressed using Deflate compression
+ /// 2.0 - File is encrypted using traditional encryption
+ /// 2.1 - File is compressed using Deflate64
+ /// 2.5 - File is compressed using PKWARE DCL Implode
+ /// 2.7 - File is a patch data set
+ /// 4.5 - File uses Zip64 format extensions
+ /// 4.6 - File is compressed using BZIP2 compression
+ /// 5.0 - File is encrypted using DES
+ /// 5.0 - File is encrypted using 3DES
+ /// 5.0 - File is encrypted using original RC2 encryption
+ /// 5.0 - File is encrypted using RC4 encryption
+ /// 5.1 - File is encrypted using AES encryption
+ /// 5.1 - File is encrypted using corrected RC2 encryption
+ /// 5.1 - File is encrypted using corrected RC2-64 encryption
+ /// 6.1 - File is encrypted using non-OAEP key wrapping
+ /// 6.2 - Central directory encryption (not confirmed yet)
+ /// 6.3 - File is compressed using LZMA
+ /// 6.3 - File is compressed using PPMD+
+ /// 6.3 - File is encrypted using Blowfish
+ /// 6.3 - File is encrypted using Twofish
+ ///
+ /// + public int Version + { + get { + // Return recorded version if known. + if (versionToExtract != 0) { + return versionToExtract; + } + else { + int result = 10; + if (AESKeySize > 0) { + result = ZipConstants.VERSION_AES; // Ver 5.1 = AES + } + else if (CentralHeaderRequiresZip64) { + result = ZipConstants.VersionZip64; + } + else if (CompressionMethod.Deflated == method) { + result = 20; + } + else if (IsDirectory == true) { + result = 20; + } + else if (IsCrypted == true) { + result = 20; + } + else if (HasDosAttributes(0x08) ) { + result = 11; + } + return result; + } + } + } + + /// + /// Get a value indicating whether this entry can be decompressed by the library. + /// + /// This is based on the and + /// wether the compression method is supported. + public bool CanDecompress + { + get { + return (Version <= ZipConstants.VersionMadeBy) && + ((Version == 10) || + (Version == 11) || + (Version == 20) || + (Version == 45) || + (Version == 51)) && + IsCompressionMethodSupported(); + } + } + + /// + /// Force this entry to be recorded using Zip64 extensions. + /// + public void ForceZip64() + { + forceZip64_ = true; + } + + /// + /// Get a value indicating wether Zip64 extensions were forced. + /// + /// A value of true if Zip64 extensions have been forced on; false if not. + public bool IsZip64Forced() + { + return forceZip64_; + } + + /// + /// Gets a value indicating if the entry requires Zip64 extensions + /// to store the full entry values. + /// + /// A value of true if a local header requires Zip64 extensions; false if not. + public bool LocalHeaderRequiresZip64 + { + get { + bool result = forceZip64_; + + if ( !result ) { + ulong trueCompressedSize = compressedSize; + + if ( (versionToExtract == 0) && IsCrypted ) { + trueCompressedSize += ZipConstants.CryptoHeaderSize; + } + + // TODO: A better estimation of the true limit based on compression overhead should be used + // to determine when an entry should use Zip64. + result = + ((this.size >= uint.MaxValue) || (trueCompressedSize >= uint.MaxValue)) && + ((versionToExtract == 0) || (versionToExtract >= ZipConstants.VersionZip64)); + } + + return result; + } + } + + /// + /// Get a value indicating wether the central directory entry requires Zip64 extensions to be stored. + /// + public bool CentralHeaderRequiresZip64 + { + get { + return LocalHeaderRequiresZip64 || (offset >= uint.MaxValue); + } + } + + /// + /// Get/Set DosTime value. + /// + /// + /// The MS-DOS date format can only represent dates between 1/1/1980 and 12/31/2107. + /// + public long DosTime + { + get { + if ((known & Known.Time) == 0) { + return 0; + } + else { + return dosTime; + } + } + + set { + unchecked { + dosTime = (uint)value; + } + + known |= Known.Time; + } + } + + /// + /// Gets/Sets the time of last modification of the entry. + /// + /// + /// The property is updated to match this as far as possible. + /// + public DateTime DateTime + { + get { + uint sec = Math.Min(59, 2 * (dosTime & 0x1f)); + uint min = Math.Min(59, (dosTime >> 5) & 0x3f); + uint hrs = Math.Min(23, (dosTime >> 11) & 0x1f); + uint mon = Math.Max(1, Math.Min(12, ((dosTime >> 21) & 0xf))); + uint year = ((dosTime >> 25) & 0x7f) + 1980; + int day = Math.Max(1, Math.Min(DateTime.DaysInMonth((int)year, (int)mon), (int)((dosTime >> 16) & 0x1f))); + return new System.DateTime((int)year, (int)mon, day, (int)hrs, (int)min, (int)sec); + } + + set { + uint year = (uint) value.Year; + uint month = (uint) value.Month; + uint day = (uint) value.Day; + uint hour = (uint) value.Hour; + uint minute = (uint) value.Minute; + uint second = (uint) value.Second; + + if ( year < 1980 ) { + year = 1980; + month = 1; + day = 1; + hour = 0; + minute = 0; + second = 0; + } + else if ( year > 2107 ) { + year = 2107; + month = 12; + day = 31; + hour = 23; + minute = 59; + second = 59; + } + + DosTime = ((year - 1980) & 0x7f) << 25 | + (month << 21) | + (day << 16) | + (hour << 11) | + (minute << 5) | + (second >> 1); + } + } + + /// + /// Returns the entry name. + /// + /// + /// The unix naming convention is followed. + /// Path components in the entry should always separated by forward slashes ('/'). + /// Dos device names like C: should also be removed. + /// See the class, or + /// + public string Name + { + get { + return name; + } + } + + /// + /// Gets/Sets the size of the uncompressed data. + /// + /// + /// The size or -1 if unknown. + /// + /// Setting the size before adding an entry to an archive can help + /// avoid compatability problems with some archivers which dont understand Zip64 extensions. + public long Size + { + get { + return (known & Known.Size) != 0 ? (long)size : -1L; + } + set { + this.size = (ulong)value; + this.known |= Known.Size; + } + } + + /// + /// Gets/Sets the size of the compressed data. + /// + /// + /// The compressed entry size or -1 if unknown. + /// + public long CompressedSize + { + get { + return (known & Known.CompressedSize) != 0 ? (long)compressedSize : -1L; + } + set { + this.compressedSize = (ulong)value; + this.known |= Known.CompressedSize; + } + } + + /// + /// Gets/Sets the crc of the uncompressed data. + /// + /// + /// Crc is not in the range 0..0xffffffffL + /// + /// + /// The crc value or -1 if unknown. + /// + public long Crc + { + get { + return (known & Known.Crc) != 0 ? crc & 0xffffffffL : -1L; + } + set { + if (((ulong)crc & 0xffffffff00000000L) != 0) { + throw new ArgumentOutOfRangeException("value"); + } + this.crc = (uint)value; + this.known |= Known.Crc; + } + } + + /// + /// Gets/Sets the compression method. Only Deflated and Stored are supported. + /// + /// + /// The compression method for this entry + /// + /// + /// + public CompressionMethod CompressionMethod { + get { + return method; + } + + set { + if ( !IsCompressionMethodSupported(value) ) { + throw new NotSupportedException("Compression method not supported"); + } + this.method = value; + } + } + + /// + /// Gets the compression method for outputting to the local or central header. + /// Returns same value as CompressionMethod except when AES encrypting, which + /// places 99 in the method and places the real method in the extra data. + /// + internal CompressionMethod CompressionMethodForHeader { + get { + return (AESKeySize > 0) ? CompressionMethod.WinZipAES : method; + } + } + + /// + /// Gets/Sets the extra data. + /// + /// + /// Extra data is longer than 64KB (0xffff) bytes. + /// + /// + /// Extra data or null if not set. + /// + public byte[] ExtraData { + + get { +// TODO: This is slightly safer but less efficient. Think about wether it should change. +// return (byte[]) extra.Clone(); + return extra; + } + + set { + if (value == null) { + extra = null; + } + else { + if (value.Length > 0xffff) { + throw new System.ArgumentOutOfRangeException("value"); + } + + extra = new byte[value.Length]; + Array.Copy(value, 0, extra, 0, value.Length); + } + } + } + + +#if !NET_1_1 && !NETCF_2_0 + /// + /// For AES encrypted files returns or sets the number of bits of encryption (128, 192 or 256). + /// When setting, only 0 (off), 128 or 256 is supported. + /// + public int AESKeySize { + get { + // the strength (1 or 3) is in the entry header + switch (_aesEncryptionStrength) { + case 0: return 0; // Not AES + case 1: return 128; + case 2: return 192; // Not used by WinZip + case 3: return 256; + default: throw new ZipException("Invalid AESEncryptionStrength " + _aesEncryptionStrength); + } + } + set { + switch (value) { + case 0: _aesEncryptionStrength = 0; break; + case 128: _aesEncryptionStrength = 1; break; + case 256: _aesEncryptionStrength = 3; break; + default: throw new ZipException("AESKeySize must be 0, 128 or 256: " + value); + } + } + } + + /// + /// AES Encryption strength for storage in extra data in entry header. + /// 1 is 128 bit, 2 is 192 bit, 3 is 256 bit. + /// + internal byte AESEncryptionStrength { + get { + return (byte)_aesEncryptionStrength; + } + } +#else + /// + /// AES unsupported prior to .NET 2.0 + /// + internal int AESKeySize; +#endif + + /// + /// Returns the length of the salt, in bytes + /// + internal int AESSaltLen { + get { + // Key size -> Salt length: 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. + return AESKeySize / 16; + } + } + + /// + /// Number of extra bytes required to hold the AES Header fields (Salt, Pwd verify, AuthCode) + /// + internal int AESOverheadSize { + get { + // File format: + // Bytes Content + // Variable Salt value + // 2 Password verification value + // Variable Encrypted file data + // 10 Authentication code + return 12 + AESSaltLen; + } + } + + /// + /// Process extra data fields updating the entry based on the contents. + /// + /// True if the extra data fields should be handled + /// for a local header, rather than for a central header. + /// + internal void ProcessExtraData(bool localHeader) + { + ZipExtraData extraData = new ZipExtraData(this.extra); + + if ( extraData.Find(0x0001) ) { + // Version required to extract is ignored here as some archivers dont set it correctly + // in theory it should be version 45 or higher + + // The recorded size will change but remember that this is zip64. + forceZip64_ = true; + + if ( extraData.ValueLength < 4 ) { + throw new ZipException("Extra data extended Zip64 information length is invalid"); + } + + if ( localHeader || (size == uint.MaxValue) ) { + size = (ulong)extraData.ReadLong(); + } + + if ( localHeader || (compressedSize == uint.MaxValue) ) { + compressedSize = (ulong)extraData.ReadLong(); + } + + if ( !localHeader && (offset == uint.MaxValue) ) { + offset = extraData.ReadLong(); + } + + // Disk number on which file starts is ignored + } + else { + if ( + ((versionToExtract & 0xff) >= ZipConstants.VersionZip64) && + ((size == uint.MaxValue) || (compressedSize == uint.MaxValue)) + ) { + throw new ZipException("Zip64 Extended information required but is missing."); + } + } + + if ( extraData.Find(10) ) { + // No room for any tags. + if ( extraData.ValueLength < 4 ) { + throw new ZipException("NTFS Extra data invalid"); + } + + extraData.ReadInt(); // Reserved + + while ( extraData.UnreadCount >= 4 ) { + int ntfsTag = extraData.ReadShort(); + int ntfsLength = extraData.ReadShort(); + if ( ntfsTag == 1 ) { + if ( ntfsLength >= 24 ) { + long lastModification = extraData.ReadLong(); + long lastAccess = extraData.ReadLong(); + long createTime = extraData.ReadLong(); + + DateTime = System.DateTime.FromFileTime(lastModification); + } + break; + } + else { + // An unknown NTFS tag so simply skip it. + extraData.Skip(ntfsLength); + } + } + } + else if ( extraData.Find(0x5455) ) { + int length = extraData.ValueLength; + int flags = extraData.ReadByte(); + + // Can include other times but these are ignored. Length of data should + // actually be 1 + 4 * no of bits in flags. + if ( ((flags & 1) != 0) && (length >= 5) ) { + int iTime = extraData.ReadInt(); + + DateTime = (new System.DateTime ( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime() + + new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime(); + } + } + if (method == CompressionMethod.WinZipAES) { + ProcessAESExtraData(extraData); + } + } + + // For AES the method in the entry is 99, and the real compression method is in the extradata + // + private void ProcessAESExtraData(ZipExtraData extraData) { + +#if !NET_1_1 && !NETCF_2_0 + if (extraData.Find(0x9901)) { + // Set version and flag for Zipfile.CreateAndInitDecryptionStream + versionToExtract = ZipConstants.VERSION_AES; // Ver 5.1 = AES see "Version" getter + // Set StrongEncryption flag for ZipFile.CreateAndInitDecryptionStream + Flags = Flags | (int)GeneralBitFlags.StrongEncryption; + // + // Unpack AES extra data field see http://www.winzip.com/aes_info.htm + int length = extraData.ValueLength; // Data size currently 7 + if (length < 7) + throw new ZipException("AES Extra Data Length " + length + " invalid."); + int ver = extraData.ReadShort(); // Version number (1=AE-1 2=AE-2) + int vendorId = extraData.ReadShort(); // 2-character vendor ID 0x4541 = "AE" + int encrStrength = extraData.ReadByte(); // encryption strength 1 = 128 2 = 192 3 = 256 + int actualCompress = extraData.ReadShort(); // The actual compression method used to compress the file + _aesVer = ver; + _aesEncryptionStrength = encrStrength; + method = (CompressionMethod)actualCompress; + } else + throw new ZipException("AES Extra Data missing"); +#else + throw new ZipException("AES unsupported"); +#endif + } + + /// + /// Gets/Sets the entry comment. + /// + /// + /// If comment is longer than 0xffff. + /// + /// + /// The comment or null if not set. + /// + /// + /// A comment is only available for entries when read via the class. + /// The class doesnt have the comment data available. + /// + public string Comment { + get { + return comment; + } + set { + // This test is strictly incorrect as the length is in characters + // while the storage limit is in bytes. + // While the test is partially correct in that a comment of this length or greater + // is definitely invalid, shorter comments may also have an invalid length + // where there are multi-byte characters + // The full test is not possible here however as the code page to apply conversions with + // isnt available. + if ( (value != null) && (value.Length > 0xffff) ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "cannot exceed 65535"); +#endif + } + + comment = value; + } + } + + /// + /// Gets a value indicating if the entry is a directory. + /// however. + /// + /// + /// A directory is determined by an entry name with a trailing slash '/'. + /// The external file attributes can also indicate an entry is for a directory. + /// Currently only dos/windows attributes are tested in this manner. + /// The trailing slash convention should always be followed. + /// + public bool IsDirectory + { + get { + int nameLength = name.Length; + bool result = + ((nameLength > 0) && + ((name[nameLength - 1] == '/') || (name[nameLength - 1] == '\\'))) || + HasDosAttributes(16) + ; + return result; + } + } + + /// + /// Get a value of true if the entry appears to be a file; false otherwise + /// + /// + /// This only takes account of DOS/Windows attributes. Other operating systems are ignored. + /// For linux and others the result may be incorrect. + /// + public bool IsFile + { + get { + return !IsDirectory && !HasDosAttributes(8); + } + } + + /// + /// Test entry to see if data can be extracted. + /// + /// Returns true if data can be extracted for this entry; false otherwise. + public bool IsCompressionMethodSupported() + { + return IsCompressionMethodSupported(CompressionMethod); + } + + #region ICloneable Members + /// + /// Creates a copy of this zip entry. + /// + /// An that is a copy of the current instance. + public object Clone() + { + ZipEntry result = (ZipEntry)this.MemberwiseClone(); + + // Ensure extra data is unique if it exists. + if ( extra != null ) { + result.extra = new byte[extra.Length]; + Array.Copy(extra, 0, result.extra, 0, extra.Length); + } + + return result; + } + + #endregion + + /// + /// Gets a string representation of this ZipEntry. + /// + /// A readable textual representation of this + public override string ToString() + { + return name; + } + + /// + /// Test a compression method to see if this library + /// supports extracting data compressed with that method + /// + /// The compression method to test. + /// Returns true if the compression method is supported; false otherwise + public static bool IsCompressionMethodSupported(CompressionMethod method) + { + return + ( method == CompressionMethod.Deflated ) || + ( method == CompressionMethod.Stored ); + } + + /// + /// Cleans a name making it conform to Zip file conventions. + /// Devices names ('c:\') and UNC share names ('\\server\share') are removed + /// and forward slashes ('\') are converted to back slashes ('/'). + /// Names are made relative by trimming leading slashes which is compatible + /// with the ZIP naming convention. + /// + /// The name to clean + /// The 'cleaned' name. + /// + /// The Zip name transform class is more flexible. + /// + public static string CleanName(string name) + { + if (name == null) { + return string.Empty; + } + + if (Path.IsPathRooted(name) == true) { + // NOTE: + // for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt + name = name.Substring(Path.GetPathRoot(name).Length); + } + + name = name.Replace(@"\", "/"); + + while ( (name.Length > 0) && (name[0] == '/')) { + name = name.Remove(0, 1); + } + return name; + } + + #region Instance Fields + Known known; + int externalFileAttributes = -1; // contains external attributes (O/S dependant) + + ushort versionMadeBy; // Contains host system and version information + // only relevant for central header entries + + string name; + ulong size; + ulong compressedSize; + ushort versionToExtract; // Version required to extract (library handles <= 2.0) + uint crc; + uint dosTime; + + CompressionMethod method = CompressionMethod.Deflated; + byte[] extra; + string comment; + + int flags; // general purpose bit flags + + long zipFileIndex = -1; // used by ZipFile + long offset; // used by ZipFile and ZipOutputStream + + bool forceZip64_; + byte cryptoCheckValue_; +#if !NET_1_1 && !NETCF_2_0 + int _aesVer; // Version number (2 = AE-2 ?). Assigned but not used. + int _aesEncryptionStrength; // Encryption strength 1 = 128 2 = 192 3 = 256 +#endif + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipEntryFactory.cs b/类库/OnlineRepair/ZIP/Zip/ZipEntryFactory.cs new file mode 100644 index 0000000..164a80e --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipEntryFactory.cs @@ -0,0 +1,413 @@ +// ZipEntryFactory.cs +// +// Copyright 2006 John Reilly +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// Basic implementation of + /// + public class ZipEntryFactory : IEntryFactory + { + #region Enumerations + /// + /// Defines the possible values to be used for the . + /// + public enum TimeSetting + { + /// + /// Use the recorded LastWriteTime value for the file. + /// + LastWriteTime, + /// + /// Use the recorded LastWriteTimeUtc value for the file + /// + LastWriteTimeUtc, + /// + /// Use the recorded CreateTime value for the file. + /// + CreateTime, + /// + /// Use the recorded CreateTimeUtc value for the file. + /// + CreateTimeUtc, + /// + /// Use the recorded LastAccessTime value for the file. + /// + LastAccessTime, + /// + /// Use the recorded LastAccessTimeUtc value for the file. + /// + LastAccessTimeUtc, + /// + /// Use a fixed value. + /// + /// The actual value used can be + /// specified via the constructor or + /// using the with the setting set + /// to which will use the when this class was constructed. + /// The property can also be used to set this value. + Fixed, + } + #endregion + + #region Constructors + /// + /// Initialise a new instance of the class. + /// + /// A default , and the LastWriteTime for files is used. + public ZipEntryFactory() + { + nameTransform_ = new ZipNameTransform(); + } + + /// + /// Initialise a new instance of using the specified + /// + /// The time setting to use when creating Zip entries. + public ZipEntryFactory(TimeSetting timeSetting) + { + timeSetting_ = timeSetting; + nameTransform_ = new ZipNameTransform(); + } + + /// + /// Initialise a new instance of using the specified + /// + /// The time to set all values to. + public ZipEntryFactory(DateTime time) + { + timeSetting_ = TimeSetting.Fixed; + FixedDateTime = time; + nameTransform_ = new ZipNameTransform(); + } + + #endregion + + #region Properties + /// + /// Get / set the to be used when creating new values. + /// + /// + /// Setting this property to null will cause a default name transform to be used. + /// + public INameTransform NameTransform + { + get { return nameTransform_; } + set + { + if (value == null) { + nameTransform_ = new ZipNameTransform(); + } + else { + nameTransform_ = value; + } + } + } + + /// + /// Get / set the in use. + /// + public TimeSetting Setting + { + get { return timeSetting_; } + set { timeSetting_ = value; } + } + + /// + /// Get / set the value to use when is set to + /// + public DateTime FixedDateTime + { + get { return fixedDateTime_; } + set + { + if (value.Year < 1970) { + throw new ArgumentException("Value is too old to be valid", "value"); + } + fixedDateTime_ = value; + } + } + + /// + /// A bitmask defining the attributes to be retrieved from the actual file. + /// + /// The default is to get all possible attributes from the actual file. + public int GetAttributes + { + get { return getAttributes_; } + set { getAttributes_ = value; } + } + + /// + /// A bitmask defining which attributes are to be set on. + /// + /// By default no attributes are set on. + public int SetAttributes + { + get { return setAttributes_; } + set { setAttributes_ = value; } + } + + /// + /// Get set a value indicating wether unidoce text should be set on. + /// + public bool IsUnicodeText + { + get { return isUnicodeText_; } + set { isUnicodeText_ = value; } + } + + #endregion + + #region IEntryFactory Members + + /// + /// Make a new for a file. + /// + /// The name of the file to create a new entry for. + /// Returns a new based on the . + public ZipEntry MakeFileEntry(string fileName) + { + return MakeFileEntry(fileName, true); + } + + /// + /// Make a new from a name. + /// + /// The name of the file to create a new entry for. + /// If true entry detail is retrieved from the file system if the file exists. + /// Returns a new based on the . + public ZipEntry MakeFileEntry(string fileName, bool useFileSystem) + { + ZipEntry result = new ZipEntry(nameTransform_.TransformFile(fileName)); + result.IsUnicodeText = isUnicodeText_; + + int externalAttributes = 0; + bool useAttributes = (setAttributes_ != 0); + + FileInfo fi = null; + if (useFileSystem) + { + fi = new FileInfo(fileName); + } + + if ((fi != null) && fi.Exists) + { + switch (timeSetting_) + { + case TimeSetting.CreateTime: + result.DateTime = fi.CreationTime; + break; + + case TimeSetting.CreateTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.CreationTime.ToUniversalTime(); +#else + result.DateTime = fi.CreationTimeUtc; +#endif + break; + + case TimeSetting.LastAccessTime: + result.DateTime = fi.LastAccessTime; + break; + + case TimeSetting.LastAccessTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.LastAccessTime.ToUniversalTime(); +#else + result.DateTime = fi.LastAccessTimeUtc; +#endif + break; + + case TimeSetting.LastWriteTime: + result.DateTime = fi.LastWriteTime; + break; + + case TimeSetting.LastWriteTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.LastWriteTime.ToUniversalTime(); +#else + result.DateTime = fi.LastWriteTimeUtc; +#endif + break; + + case TimeSetting.Fixed: + result.DateTime = fixedDateTime_; + break; + + default: + throw new ZipException("Unhandled time setting in MakeFileEntry"); + } + + result.Size = fi.Length; + + useAttributes = true; + externalAttributes = ((int)fi.Attributes & getAttributes_); + } + else + { + if (timeSetting_ == TimeSetting.Fixed) + { + result.DateTime = fixedDateTime_; + } + } + + if (useAttributes) + { + externalAttributes |= setAttributes_; + result.ExternalFileAttributes = externalAttributes; + } + + return result; + } + + /// + /// Make a new for a directory. + /// + /// The raw untransformed name for the new directory + /// Returns a new representing a directory. + public ZipEntry MakeDirectoryEntry(string directoryName) + { + return MakeDirectoryEntry(directoryName, true); + } + + /// + /// Make a new for a directory. + /// + /// The raw untransformed name for the new directory + /// If true entry detail is retrieved from the file system if the file exists. + /// Returns a new representing a directory. + public ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem) + { + + ZipEntry result = new ZipEntry(nameTransform_.TransformDirectory(directoryName)); + result.IsUnicodeText = isUnicodeText_; + result.Size = 0; + + int externalAttributes = 0; + + DirectoryInfo di = null; + + if (useFileSystem) + { + di = new DirectoryInfo(directoryName); + } + + + if ((di != null) && di.Exists) + { + switch (timeSetting_) + { + case TimeSetting.CreateTime: + result.DateTime = di.CreationTime; + break; + + case TimeSetting.CreateTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.CreationTime.ToUniversalTime(); +#else + result.DateTime = di.CreationTimeUtc; +#endif + break; + + case TimeSetting.LastAccessTime: + result.DateTime = di.LastAccessTime; + break; + + case TimeSetting.LastAccessTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.LastAccessTime.ToUniversalTime(); +#else + result.DateTime = di.LastAccessTimeUtc; +#endif + break; + + case TimeSetting.LastWriteTime: + result.DateTime = di.LastWriteTime; + break; + + case TimeSetting.LastWriteTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.LastWriteTime.ToUniversalTime(); +#else + result.DateTime = di.LastWriteTimeUtc; +#endif + break; + + case TimeSetting.Fixed: + result.DateTime = fixedDateTime_; + break; + + default: + throw new ZipException("Unhandled time setting in MakeDirectoryEntry"); + } + + externalAttributes = ((int)di.Attributes & getAttributes_); + } + else + { + if (timeSetting_ == TimeSetting.Fixed) + { + result.DateTime = fixedDateTime_; + } + } + + // Always set directory attribute on. + externalAttributes |= (setAttributes_ | 16); + result.ExternalFileAttributes = externalAttributes; + + return result; + } + + #endregion + + #region Instance Fields + INameTransform nameTransform_; + DateTime fixedDateTime_ = DateTime.Now; + TimeSetting timeSetting_; + bool isUnicodeText_; + + int getAttributes_ = -1; + int setAttributes_; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipException.cs b/类库/OnlineRepair/ZIP/Zip/ZipException.cs new file mode 100644 index 0000000..1cf4f16 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipException.cs @@ -0,0 +1,94 @@ +// ZipException.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Represents exception conditions specific to Zip archive handling + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class ZipException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected ZipException(SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } +#endif + + /// + /// Initializes a new instance of the ZipException class. + /// + public ZipException() + { + } + + /// + /// Initializes a new instance of the ZipException class with a specified error message. + /// + /// The error message that explains the reason for the exception. + public ZipException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of ZipException. + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public ZipException(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipExtraData.cs b/类库/OnlineRepair/ZIP/Zip/ZipExtraData.cs new file mode 100644 index 0000000..aaeb0a6 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipExtraData.cs @@ -0,0 +1,987 @@ +// +// ZipExtraData.cs +// +// Copyright 2004-2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Zip +{ + // TODO: Sort out wether tagged data is useful and what a good implementation might look like. + // Its just a sketch of an idea at the moment. + + /// + /// ExtraData tagged value interface. + /// + public interface ITaggedData + { + /// + /// Get the ID for this tagged data value. + /// + short TagID { get; } + + /// + /// Set the contents of this instance from the data passed. + /// + /// The data to extract contents from. + /// The offset to begin extracting data from. + /// The number of bytes to extract. + void SetData(byte[] data, int offset, int count); + + /// + /// Get the data representing this instance. + /// + /// Returns the data for this instance. + byte[] GetData(); + } + + /// + /// A raw binary tagged value + /// + public class RawTaggedData : ITaggedData + { + /// + /// Initialise a new instance. + /// + /// The tag ID. + public RawTaggedData(short tag) + { + _tag = tag; + } + + #region ITaggedData Members + + /// + /// Get the ID for this tagged data value. + /// + public short TagID + { + get { return _tag; } + set { _tag = value; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int offset, int count) + { + if( data==null ) + { + throw new ArgumentNullException("data"); + } + + _data=new byte[count]; + Array.Copy(data, offset, _data, 0, count); + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + return _data; + } + + #endregion + + /// + /// Get /set the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] Data + { + get { return _data; } + set { _data=value; } + } + + #region Instance Fields + /// + /// The tag ID for this instance. + /// + short _tag; + + byte[] _data; + #endregion + } + + /// + /// Class representing extended unix date time values. + /// + public class ExtendedUnixData : ITaggedData + { + /// + /// Flags indicate which values are included in this instance. + /// + [Flags] + public enum Flags : byte + { + /// + /// The modification time is included + /// + ModificationTime = 0x01, + + /// + /// The access time is included + /// + AccessTime = 0x02, + + /// + /// The create time is included. + /// + CreateTime = 0x04, + } + + #region ITaggedData Members + + /// + /// Get the ID + /// + public short TagID + { + get { return 0x5455; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int index, int count) + { + using (MemoryStream ms = new MemoryStream(data, index, count, false)) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + // bit 0 if set, modification time is present + // bit 1 if set, access time is present + // bit 2 if set, creation time is present + + _flags = (Flags)helperStream.ReadByte(); + if (((_flags & Flags.ModificationTime) != 0) && (count >= 5)) + { + int iTime = helperStream.ReadLEInt(); + + _modificationTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + + if ((_flags & Flags.AccessTime) != 0) + { + int iTime = helperStream.ReadLEInt(); + + _lastAccessTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + + if ((_flags & Flags.CreateTime) != 0) + { + int iTime = helperStream.ReadLEInt(); + + _createTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + } + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + using (MemoryStream ms = new MemoryStream()) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.IsStreamOwner = false; + helperStream.WriteByte((byte)_flags); // Flags + if ( (_flags & Flags.ModificationTime) != 0) { + TimeSpan span = _modificationTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + if ( (_flags & Flags.AccessTime) != 0) { + TimeSpan span = _lastAccessTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + if ( (_flags & Flags.CreateTime) != 0) { + TimeSpan span = _createTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + return ms.ToArray(); + } + } + + #endregion + + /// + /// Test a value to see if is valid and can be represented here. + /// + /// The value to test. + /// Returns true if the value is valid and can be represented; false if not. + /// The standard Unix time is a signed integer data type, directly encoding the Unix time number, + /// which is the number of seconds since 1970-01-01. + /// Being 32 bits means the values here cover a range of about 136 years. + /// The minimum representable time is 1901-12-13 20:45:52, + /// and the maximum representable time is 2038-01-19 03:14:07. + /// + public static bool IsValidValue(DateTime value) + { + return (( value >= new DateTime(1901, 12, 13, 20, 45, 52)) || + ( value <= new DateTime(2038, 1, 19, 03, 14, 07) )); + } + + /// + /// Get /set the Modification Time + /// + /// + /// + public DateTime ModificationTime + { + get { return _modificationTime; } + set + { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.ModificationTime; + _modificationTime=value; + } + } + + /// + /// Get / set the Access Time + /// + /// + /// + public DateTime AccessTime + { + get { return _lastAccessTime; } + set { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.AccessTime; + _lastAccessTime=value; + } + } + + /// + /// Get / Set the Create Time + /// + /// + /// + public DateTime CreateTime + { + get { return _createTime; } + set { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.CreateTime; + _createTime=value; + } + } + + /// + /// Get/set the values to include. + /// + Flags Include + { + get { return _flags; } + set { _flags = value; } + } + + #region Instance Fields + Flags _flags; + DateTime _modificationTime = new DateTime(1970,1,1); + DateTime _lastAccessTime = new DateTime(1970, 1, 1); + DateTime _createTime = new DateTime(1970, 1, 1); + #endregion + } + + /// + /// Class handling NT date time values. + /// + public class NTTaggedData : ITaggedData + { + /// + /// Get the ID for this tagged data value. + /// + public short TagID + { + get { return 10; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int index, int count) + { + using (MemoryStream ms = new MemoryStream(data, index, count, false)) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.ReadLEInt(); // Reserved + while (helperStream.Position < helperStream.Length) + { + int ntfsTag = helperStream.ReadLEShort(); + int ntfsLength = helperStream.ReadLEShort(); + if (ntfsTag == 1) + { + if (ntfsLength >= 24) + { + long lastModificationTicks = helperStream.ReadLELong(); + _lastModificationTime = DateTime.FromFileTime(lastModificationTicks); + + long lastAccessTicks = helperStream.ReadLELong(); + _lastAccessTime = DateTime.FromFileTime(lastAccessTicks); + + long createTimeTicks = helperStream.ReadLELong(); + _createTime = DateTime.FromFileTime(createTimeTicks); + } + break; + } + else + { + // An unknown NTFS tag so simply skip it. + helperStream.Seek(ntfsLength, SeekOrigin.Current); + } + } + } + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + using (MemoryStream ms = new MemoryStream()) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.IsStreamOwner = false; + helperStream.WriteLEInt(0); // Reserved + helperStream.WriteLEShort(1); // Tag + helperStream.WriteLEShort(24); // Length = 3 x 8. + helperStream.WriteLELong(_lastModificationTime.ToFileTime()); + helperStream.WriteLELong(_lastAccessTime.ToFileTime()); + helperStream.WriteLELong(_createTime.ToFileTime()); + return ms.ToArray(); + } + } + + /// + /// Test a valuie to see if is valid and can be represented here. + /// + /// The value to test. + /// Returns true if the value is valid and can be represented; false if not. + /// + /// NTFS filetimes are 64-bit unsigned integers, stored in Intel + /// (least significant byte first) byte order. They determine the + /// number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", + /// which is "01-Jan-1601 00:00:00 UTC". 28 May 60056 is the upper limit + /// + public static bool IsValidValue(DateTime value) + { + bool result = true; + try + { + value.ToFileTimeUtc(); + } + catch + { + result = false; + } + return result; + } + + /// + /// Get/set the last modification time. + /// + public DateTime LastModificationTime + { + get { return _lastModificationTime; } + set { + if (! IsValidValue(value)) + { + throw new ArgumentOutOfRangeException("value"); + } + _lastModificationTime = value; + } + } + + /// + /// Get /set the create time + /// + public DateTime CreateTime + { + get { return _createTime; } + set { + if ( !IsValidValue(value)) { + throw new ArgumentOutOfRangeException("value"); + } + _createTime = value; + } + } + + /// + /// Get /set the last access time. + /// + public DateTime LastAccessTime + { + get { return _lastAccessTime; } + set { + if (!IsValidValue(value)) { + throw new ArgumentOutOfRangeException("value"); + } + _lastAccessTime = value; + } + } + + #region Instance Fields + DateTime _lastAccessTime = DateTime.FromFileTime(0); + DateTime _lastModificationTime = DateTime.FromFileTime(0); + DateTime _createTime = DateTime.FromFileTime(0); + #endregion + } + + /// + /// A factory that creates tagged data instances. + /// + interface ITaggedDataFactory + { + /// + /// Get data for a specific tag value. + /// + /// The tag ID to find. + /// The data to search. + /// The offset to begin extracting data from. + /// The number of bytes to extract. + /// The located value found, or null if not found. + ITaggedData Create(short tag, byte[] data, int offset, int count); + } + + /// + /// + /// A class to handle the extra data field for Zip entries + /// + /// + /// Extra data contains 0 or more values each prefixed by a header tag and length. + /// They contain zero or more bytes of actual data. + /// The data is held internally using a copy on write strategy. This is more efficient but + /// means that for extra data created by passing in data can have the values modified by the caller + /// in some circumstances. + /// + sealed public class ZipExtraData : IDisposable + { + #region Constructors + /// + /// Initialise a default instance. + /// + public ZipExtraData() + { + Clear(); + } + + /// + /// Initialise with known extra data. + /// + /// The extra data. + public ZipExtraData(byte[] data) + { + if ( data == null ) + { + _data = new byte[0]; + } + else + { + _data = data; + } + } + #endregion + + /// + /// Get the raw extra data value + /// + /// Returns the raw byte[] extra data this instance represents. + public byte[] GetEntryData() + { + if ( Length > ushort.MaxValue ) { + throw new ZipException("Data exceeds maximum length"); + } + + return (byte[])_data.Clone(); + } + + /// + /// Clear the stored data. + /// + public void Clear() + { + if ( (_data == null) || (_data.Length != 0) ) { + _data = new byte[0]; + } + } + + /// + /// Gets the current extra data length. + /// + public int Length + { + get { return _data.Length; } + } + + /// + /// Get a read-only for the associated tag. + /// + /// The tag to locate data for. + /// Returns a containing tag data or null if no tag was found. + public Stream GetStreamForTag(int tag) + { + Stream result = null; + if ( Find(tag) ) { + result = new MemoryStream(_data, _index, _readValueLength, false); + } + return result; + } + + /// + /// Get the tagged data for a tag. + /// + /// The tag to search for. + /// Returns a tagged value or null if none found. + private ITaggedData GetData(short tag) + { + ITaggedData result = null; + if (Find(tag)) + { + result = Create(tag, _data, _readValueStart, _readValueLength); + } + return result; + } + + static ITaggedData Create(short tag, byte[] data, int offset, int count) + { + ITaggedData result = null; + switch ( tag ) + { + case 0x000A: + result = new NTTaggedData(); + break; + case 0x5455: + result = new ExtendedUnixData(); + break; + default: + result = new RawTaggedData(tag); + break; + } + result.SetData(data, offset, count); + return result; + } + + /// + /// Get the length of the last value found by + /// + /// This is only valid if has previously returned true. + public int ValueLength + { + get { return _readValueLength; } + } + + /// + /// Get the index for the current read value. + /// + /// This is only valid if has previously returned true. + /// Initially the result will be the index of the first byte of actual data. The value is updated after calls to + /// , and . + public int CurrentReadIndex + { + get { return _index; } + } + + /// + /// Get the number of bytes remaining to be read for the current value; + /// + public int UnreadCount + { + get + { + if ((_readValueStart > _data.Length) || + (_readValueStart < 4) ) { + throw new ZipException("Find must be called before calling a Read method"); + } + + return _readValueStart + _readValueLength - _index; + } + } + + /// + /// Find an extra data value + /// + /// The identifier for the value to find. + /// Returns true if the value was found; false otherwise. + public bool Find(int headerID) + { + _readValueStart = _data.Length; + _readValueLength = 0; + _index = 0; + + int localLength = _readValueStart; + int localTag = headerID - 1; + + // Trailing bytes that cant make up an entry (as there arent enough + // bytes for a tag and length) are ignored! + while ( (localTag != headerID) && (_index < _data.Length - 3) ) { + localTag = ReadShortInternal(); + localLength = ReadShortInternal(); + if ( localTag != headerID ) { + _index += localLength; + } + } + + bool result = (localTag == headerID) && ((_index + localLength) <= _data.Length); + + if ( result ) { + _readValueStart = _index; + _readValueLength = localLength; + } + + return result; + } + + /// + /// Add a new entry to extra data. + /// + /// The value to add. + public void AddEntry(ITaggedData taggedData) + { + if (taggedData == null) + { + throw new ArgumentNullException("taggedData"); + } + AddEntry(taggedData.TagID, taggedData.GetData()); + } + + /// + /// Add a new entry to extra data + /// + /// The ID for this entry. + /// The data to add. + /// If the ID already exists its contents are replaced. + public void AddEntry(int headerID, byte[] fieldData) + { + if ( (headerID > ushort.MaxValue) || (headerID < 0)) { + throw new ArgumentOutOfRangeException("headerID"); + } + + int addLength = (fieldData == null) ? 0 : fieldData.Length; + + if ( addLength > ushort.MaxValue ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("fieldData"); +#else + throw new ArgumentOutOfRangeException("fieldData", "exceeds maximum length"); +#endif + } + + // Test for new length before adjusting data. + int newLength = _data.Length + addLength + 4; + + if ( Find(headerID) ) + { + newLength -= (ValueLength + 4); + } + + if ( newLength > ushort.MaxValue ) { + throw new ZipException("Data exceeds maximum length"); + } + + Delete(headerID); + + byte[] newData = new byte[newLength]; + _data.CopyTo(newData, 0); + int index = _data.Length; + _data = newData; + SetShort(ref index, headerID); + SetShort(ref index, addLength); + if ( fieldData != null ) { + fieldData.CopyTo(newData, index); + } + } + + /// + /// Start adding a new entry. + /// + /// Add data using , , , or . + /// The new entry is completed and actually added by calling + /// + public void StartNewEntry() + { + _newEntry = new MemoryStream(); + } + + /// + /// Add entry data added since using the ID passed. + /// + /// The identifier to use for this entry. + public void AddNewEntry(int headerID) + { + byte[] newData = _newEntry.ToArray(); + _newEntry = null; + AddEntry(headerID, newData); + } + + /// + /// Add a byte of data to the pending new entry. + /// + /// The byte to add. + /// + public void AddData(byte data) + { + _newEntry.WriteByte(data); + } + + /// + /// Add data to a pending new entry. + /// + /// The data to add. + /// + public void AddData(byte[] data) + { + if ( data == null ) { + throw new ArgumentNullException("data"); + } + + _newEntry.Write(data, 0, data.Length); + } + + /// + /// Add a short value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeShort(int toAdd) + { + unchecked { + _newEntry.WriteByte(( byte )toAdd); + _newEntry.WriteByte(( byte )(toAdd >> 8)); + } + } + + /// + /// Add an integer value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeInt(int toAdd) + { + unchecked { + AddLeShort(( short )toAdd); + AddLeShort(( short )(toAdd >> 16)); + } + } + + /// + /// Add a long value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeLong(long toAdd) + { + unchecked { + AddLeInt(( int )(toAdd & 0xffffffff)); + AddLeInt(( int )(toAdd >> 32)); + } + } + + /// + /// Delete an extra data field. + /// + /// The identifier of the field to delete. + /// Returns true if the field was found and deleted. + public bool Delete(int headerID) + { + bool result = false; + + if ( Find(headerID) ) { + result = true; + int trueStart = _readValueStart - 4; + + byte[] newData = new byte[_data.Length - (ValueLength + 4)]; + Array.Copy(_data, 0, newData, 0, trueStart); + + int trueEnd = trueStart + ValueLength + 4; + Array.Copy(_data, trueEnd, newData, trueStart, _data.Length - trueEnd); + _data = newData; + } + return result; + } + + #region Reading Support + /// + /// Read a long in little endian form from the last found data value + /// + /// Returns the long value read. + public long ReadLong() + { + ReadCheck(8); + return (ReadInt() & 0xffffffff) | ((( long )ReadInt()) << 32); + } + + /// + /// Read an integer in little endian form from the last found data value. + /// + /// Returns the integer read. + public int ReadInt() + { + ReadCheck(4); + + int result = _data[_index] + (_data[_index + 1] << 8) + + (_data[_index + 2] << 16) + (_data[_index + 3] << 24); + _index += 4; + return result; + } + + /// + /// Read a short value in little endian form from the last found data value. + /// + /// Returns the short value read. + public int ReadShort() + { + ReadCheck(2); + int result = _data[_index] + (_data[_index + 1] << 8); + _index += 2; + return result; + } + + /// + /// Read a byte from an extra data + /// + /// The byte value read or -1 if the end of data has been reached. + public int ReadByte() + { + int result = -1; + if ( (_index < _data.Length) && (_readValueStart + _readValueLength > _index) ) { + result = _data[_index]; + _index += 1; + } + return result; + } + + /// + /// Skip data during reading. + /// + /// The number of bytes to skip. + public void Skip(int amount) + { + ReadCheck(amount); + _index += amount; + } + + void ReadCheck(int length) + { + if ((_readValueStart > _data.Length) || + (_readValueStart < 4) ) { + throw new ZipException("Find must be called before calling a Read method"); + } + + if (_index > _readValueStart + _readValueLength - length ) { + throw new ZipException("End of extra data"); + } + + if ( _index + length < 4 ) { + throw new ZipException("Cannot read before start of tag"); + } + } + + /// + /// Internal form of that reads data at any location. + /// + /// Returns the short value read. + int ReadShortInternal() + { + if ( _index > _data.Length - 2) { + throw new ZipException("End of extra data"); + } + + int result = _data[_index] + (_data[_index + 1] << 8); + _index += 2; + return result; + } + + void SetShort(ref int index, int source) + { + _data[index] = (byte)source; + _data[index + 1] = (byte)(source >> 8); + index += 2; + } + + #endregion + + #region IDisposable Members + + /// + /// Dispose of this instance. + /// + public void Dispose() + { + if ( _newEntry != null ) { + _newEntry.Close(); + } + } + + #endregion + + #region Instance Fields + int _index; + int _readValueStart; + int _readValueLength; + + MemoryStream _newEntry; + byte[] _data; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipFile.cs b/类库/OnlineRepair/ZIP/Zip/ZipFile.cs new file mode 100644 index 0000000..af4000b --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipFile.cs @@ -0,0 +1,4486 @@ +// ZipFile.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2009-12-22 Z-1649 Added AES support +// 2010-03-02 Z-1650 Fixed updating ODT archives in memory. Exposed exceptions in updating. +// 2010-05-25 Z-1663 Fixed exception when testing local header compressed size of -1 + +using System; +using System.Collections; +using System.IO; +using System.Text; +using System.Globalization; + +#if !NETCF_1_0 +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Encryption; +#endif + +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using ICSharpCode.SharpZipLib.Zip.Compression; + +namespace ICSharpCode.SharpZipLib.Zip +{ + #region Keys Required Event Args + /// + /// Arguments used with KeysRequiredEvent + /// + public class KeysRequiredEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The name of the file for which keys are required. + public KeysRequiredEventArgs(string name) + { + fileName = name; + } + + /// + /// Initialise a new instance of + /// + /// The name of the file for which keys are required. + /// The current key value. + public KeysRequiredEventArgs(string name, byte[] keyValue) + { + fileName = name; + key = keyValue; + } + + #endregion + #region Properties + /// + /// Gets the name of the file for which keys are required. + /// + public string FileName + { + get { return fileName; } + } + + /// + /// Gets or sets the key value + /// + public byte[] Key + { + get { return key; } + set { key = value; } + } + #endregion + + #region Instance Fields + string fileName; + byte[] key; + #endregion + } + #endregion + + #region Test Definitions + /// + /// The strategy to apply to testing. + /// + public enum TestStrategy + { + /// + /// Find the first error only. + /// + FindFirstError, + /// + /// Find all possible errors. + /// + FindAllErrors, + } + + /// + /// The operation in progress reported by a during testing. + /// + /// TestArchive + public enum TestOperation + { + /// + /// Setting up testing. + /// + Initialising, + + /// + /// Testing an individual entries header + /// + EntryHeader, + + /// + /// Testing an individual entries data + /// + EntryData, + + /// + /// Testing an individual entry has completed. + /// + EntryComplete, + + /// + /// Running miscellaneous tests + /// + MiscellaneousTests, + + /// + /// Testing is complete + /// + Complete, + } + + /// + /// Status returned returned by during testing. + /// + /// TestArchive + public class TestStatus + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The this status applies to. + public TestStatus(ZipFile file) + { + file_ = file; + } + #endregion + + #region Properties + + /// + /// Get the current in progress. + /// + public TestOperation Operation + { + get { return operation_; } + } + + /// + /// Get the this status is applicable to. + /// + public ZipFile File + { + get { return file_; } + } + + /// + /// Get the current/last entry tested. + /// + public ZipEntry Entry + { + get { return entry_; } + } + + /// + /// Get the number of errors detected so far. + /// + public int ErrorCount + { + get { return errorCount_; } + } + + /// + /// Get the number of bytes tested so far for the current entry. + /// + public long BytesTested + { + get { return bytesTested_; } + } + + /// + /// Get a value indicating wether the last entry test was valid. + /// + public bool EntryValid + { + get { return entryValid_; } + } + #endregion + + #region Internal API + internal void AddError() + { + errorCount_++; + entryValid_ = false; + } + + internal void SetOperation(TestOperation operation) + { + operation_ = operation; + } + + internal void SetEntry(ZipEntry entry) + { + entry_ = entry; + entryValid_ = true; + bytesTested_ = 0; + } + + internal void SetBytesTested(long value) + { + bytesTested_ = value; + } + #endregion + + #region Instance Fields + ZipFile file_; + ZipEntry entry_; + bool entryValid_; + int errorCount_; + long bytesTested_; + TestOperation operation_; + #endregion + } + + /// + /// Delegate invoked during testing if supplied indicating current progress and status. + /// + /// If the message is non-null an error has occured. If the message is null + /// the operation as found in status has started. + public delegate void ZipTestResultHandler(TestStatus status, string message); + #endregion + + #region Update Definitions + /// + /// The possible ways of applying updates to an archive. + /// + public enum FileUpdateMode + { + /// + /// Perform all updates on temporary files ensuring that the original file is saved. + /// + Safe, + /// + /// Update the archive directly, which is faster but less safe. + /// + Direct, + } + #endregion + + #region ZipFile Class + /// + /// This class represents a Zip archive. You can ask for the contained + /// entries, or get an input stream for a file entry. The entry is + /// automatically decompressed. + /// + /// You can also update the archive adding or deleting entries. + /// + /// This class is thread safe for input: You can open input streams for arbitrary + /// entries in different threads. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// + /// + /// using System; + /// using System.Text; + /// using System.Collections; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// static public void Main(string[] args) + /// { + /// using (ZipFile zFile = new ZipFile(args[0])) { + /// Console.WriteLine("Listing of : " + zFile.Name); + /// Console.WriteLine(""); + /// Console.WriteLine("Raw Size Size Date Time Name"); + /// Console.WriteLine("-------- -------- -------- ------ ---------"); + /// foreach (ZipEntry e in zFile) { + /// if ( e.IsFile ) { + /// DateTime d = e.DateTime; + /// Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize, + /// d.ToString("dd-MM-yy"), d.ToString("HH:mm"), + /// e.Name); + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipFile : IEnumerable, IDisposable + { + #region KeyHandling + + /// + /// Delegate for handling keys/password setting during compresion/decompression. + /// + public delegate void KeysRequiredEventHandler( + object sender, + KeysRequiredEventArgs e + ); + + /// + /// Event handler for handling encryption keys. + /// + public KeysRequiredEventHandler KeysRequired; + + /// + /// Handles getting of encryption keys when required. + /// + /// The file for which encryption keys are required. + void OnKeysRequired(string fileName) + { + if (KeysRequired != null) { + KeysRequiredEventArgs krea = new KeysRequiredEventArgs(fileName, key); + KeysRequired(this, krea); + key = krea.Key; + } + } + + /// + /// Get/set the encryption key value. + /// + byte[] Key + { + get { return key; } + set { key = value; } + } + +#if !NETCF_1_0 + /// + /// Password to be used for encrypting/decrypting files. + /// + /// Set to null if no password is required. + public string Password + { + set + { + if ( (value == null) || (value.Length == 0) ) { + key = null; + } + else { + rawPassword_ = value; + key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(value)); + } + } + } +#endif + + /// + /// Get a value indicating wether encryption keys are currently available. + /// + bool HaveKeys + { + get { return key != null; } + } + #endregion + + #region Constructors + /// + /// Opens a Zip file with the given name for reading. + /// + /// The name of the file to open. + /// The argument supplied is null. + /// + /// An i/o error occurs + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(string name) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + name_ = name; + + baseStream_ = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read); + isStreamOwner = true; + + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } + + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// The supplied argument is null. + /// + /// An i/o error occurs. + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(FileStream file) + { + if ( file == null ) { + throw new ArgumentNullException("file"); + } + + if ( !file.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "file"); + } + + baseStream_ = file; + name_ = file.Name; + isStreamOwner = true; + + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } + + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// + /// An i/o error occurs + /// + /// + /// The stream doesn't contain a valid zip archive.
+ ///
+ /// + /// The stream doesnt support seeking. + /// + /// + /// The stream argument is null. + /// + public ZipFile(Stream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + if ( !stream.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "stream"); + } + + baseStream_ = stream; + isStreamOwner = true; + + if ( baseStream_.Length > 0 ) { + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } else { + entries_ = new ZipEntry[0]; + isNewArchive_ = true; + } + } + + /// + /// Initialises a default instance with no entries and no file storage. + /// + internal ZipFile() + { + entries_ = new ZipEntry[0]; + isNewArchive_ = true; + } + + #endregion + + #region Destructors and Closing + /// + /// Finalize this instance. + /// + ~ZipFile() + { + Dispose(false); + } + + /// + /// Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. + /// Once closed, no further instance methods should be called. + /// + /// + /// An i/o error occurs. + /// + public void Close() + { + DisposeInternal(true); + GC.SuppressFinalize(this); + } + + #endregion + + #region Creators + /// + /// Create a new whose data will be stored in a file. + /// + /// The name of the archive to create. + /// Returns the newly created + /// is null + public static ZipFile Create(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + FileStream fs = File.Create(fileName); + + ZipFile result = new ZipFile(); + result.name_ = fileName; + result.baseStream_ = fs; + result.isStreamOwner = true; + return result; + } + + /// + /// Create a new whose data will be stored on a stream. + /// + /// The stream providing data storage. + /// Returns the newly created + /// is null + /// doesnt support writing. + public static ZipFile Create(Stream outStream) + { + if ( outStream == null ) { + throw new ArgumentNullException("outStream"); + } + + if ( !outStream.CanWrite ) { + throw new ArgumentException("Stream is not writeable", "outStream"); + } + + if ( !outStream.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "outStream"); + } + + ZipFile result = new ZipFile(); + result.baseStream_ = outStream; + return result; + } + + #endregion + + #region Properties + /// + /// Get/set a flag indicating if the underlying stream is owned by the ZipFile instance. + /// If the flag is true then the stream will be closed when Close is called. + /// + /// + /// The default value is true in all cases. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Get a value indicating wether + /// this archive is embedded in another file or not. + /// + public bool IsEmbeddedArchive + { + // Not strictly correct in all circumstances currently + get { return offsetOfFirstEntry > 0; } + } + + /// + /// Get a value indicating that this archive is a new one. + /// + public bool IsNewArchive + { + get { return isNewArchive_; } + } + + /// + /// Gets the comment for the zip file. + /// + public string ZipFileComment + { + get { return comment_; } + } + + /// + /// Gets the name of this zip file. + /// + public string Name + { + get { return name_; } + } + + /// + /// Gets the number of entries in this zip file. + /// + /// + /// The Zip file has been closed. + /// + [Obsolete("Use the Count property instead")] + public int Size + { + get + { + return entries_.Length; + } + } + + /// + /// Get the number of entries contained in this . + /// + public long Count + { + get + { + return entries_.Length; + } + } + + /// + /// Indexer property for ZipEntries + /// + [System.Runtime.CompilerServices.IndexerNameAttribute("EntryByIndex")] + public ZipEntry this[int index] + { + get { + return (ZipEntry) entries_[index].Clone(); + } + } + + #endregion + + #region Input Handling + /// + /// Gets an enumerator for the Zip entries in this Zip file. + /// + /// Returns an for this archive. + /// + /// The Zip file has been closed. + /// + public IEnumerator GetEnumerator() + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + return new ZipEntryEnumerator(entries_); + } + + /// + /// Return the index of the entry with a matching name + /// + /// Entry name to find + /// If true the comparison is case insensitive + /// The index position of the matching entry or -1 if not found + /// + /// The Zip file has been closed. + /// + public int FindEntry(string name, bool ignoreCase) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + // TODO: This will be slow as the next ice age for huge archives! + for (int i = 0; i < entries_.Length; i++) { + if (string.Compare(name, entries_[i].Name, ignoreCase, CultureInfo.InvariantCulture) == 0) { + return i; + } + } + return -1; + } + + /// + /// Searches for a zip entry in this archive with the given name. + /// String comparisons are case insensitive + /// + /// + /// The name to find. May contain directory components separated by slashes ('/'). + /// + /// + /// A clone of the zip entry, or null if no entry with that name exists. + /// + /// + /// The Zip file has been closed. + /// + public ZipEntry GetEntry(string name) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + int index = FindEntry(name, true); + return (index >= 0) ? (ZipEntry) entries_[index].Clone() : null; + } + + /// + /// Gets an input stream for reading the given zip entry data in an uncompressed form. + /// Normally the should be an entry returned by GetEntry(). + /// + /// The to obtain a data for + /// An input containing data for this + /// + /// The ZipFile has already been closed + /// + /// + /// The compression method for the entry is unknown + /// + /// + /// The entry is not found in the ZipFile + /// + public Stream GetInputStream(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + long index = entry.ZipFileIndex; + if ( (index < 0) || (index >= entries_.Length) || (entries_[index].Name != entry.Name) ) { + index = FindEntry(entry.Name, true); + if (index < 0) { + throw new ZipException("Entry cannot be found"); + } + } + return GetInputStream(index); + } + + /// + /// Creates an input stream reading a zip entry + /// + /// The index of the entry to obtain an input stream for. + /// + /// An input containing data for this + /// + /// + /// The ZipFile has already been closed + /// + /// + /// The compression method for the entry is unknown + /// + /// + /// The entry is not found in the ZipFile + /// + public Stream GetInputStream(long entryIndex) + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + long start = LocateEntry(entries_[entryIndex]); + CompressionMethod method = entries_[entryIndex].CompressionMethod; + Stream result = new PartialInputStream(this, start, entries_[entryIndex].CompressedSize); + + if (entries_[entryIndex].IsCrypted == true) { +#if NETCF_1_0 + throw new ZipException("decryption not supported for Compact Framework 1.0"); +#else + result = CreateAndInitDecryptionStream(result, entries_[entryIndex]); + if (result == null) { + throw new ZipException("Unable to decrypt this entry"); + } +#endif + } + + switch (method) { + case CompressionMethod.Stored: + // read as is. + break; + + case CompressionMethod.Deflated: + // No need to worry about ownership and closing as underlying stream close does nothing. + result = new InflaterInputStream(result, new Inflater(true)); + break; + + default: + throw new ZipException("Unsupported compression method " + method); + } + + return result; + } + + #endregion + + #region Archive Testing + /// + /// Test an archive for integrity/validity + /// + /// Perform low level data Crc check + /// true if all tests pass, false otherwise + /// Testing will terminate on the first error found. + public bool TestArchive(bool testData) + { + return TestArchive(testData, TestStrategy.FindFirstError, null); + } + + /// + /// Test an archive for integrity/validity + /// + /// Perform low level data Crc check + /// The to apply. + /// The handler to call during testing. + /// true if all tests pass, false otherwise + /// The object has already been closed. + public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandler resultHandler) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + TestStatus status = new TestStatus(this); + + if ( resultHandler != null ) { + resultHandler(status, null); + } + + HeaderTest test = testData ? (HeaderTest.Header | HeaderTest.Extract) : HeaderTest.Header; + + bool testing = true; + + try { + int entryIndex = 0; + + while ( testing && (entryIndex < Count) ) { + if ( resultHandler != null ) { + status.SetEntry(this[entryIndex]); + status.SetOperation(TestOperation.EntryHeader); + resultHandler(status, null); + } + + try { + TestLocalHeader(this[entryIndex], test); + } + catch(ZipException ex) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, + string.Format("Exception during test - '{0}'", ex.Message)); + } + + if ( strategy == TestStrategy.FindFirstError ) { + testing = false; + } + } + + if ( testing && testData && this[entryIndex].IsFile ) { + if ( resultHandler != null ) { + status.SetOperation(TestOperation.EntryData); + resultHandler(status, null); + } + + Crc32 crc = new Crc32(); + + using (Stream entryStream = this.GetInputStream(this[entryIndex])) + { + + byte[] buffer = new byte[4096]; + long totalBytes = 0; + int bytesRead; + while ((bytesRead = entryStream.Read(buffer, 0, buffer.Length)) > 0) + { + crc.Update(buffer, 0, bytesRead); + + if (resultHandler != null) + { + totalBytes += bytesRead; + status.SetBytesTested(totalBytes); + resultHandler(status, null); + } + } + } + + if (this[entryIndex].Crc != crc.Value) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, "CRC mismatch"); + } + + if ( strategy == TestStrategy.FindFirstError ) { + testing = false; + } + } + + if (( this[entryIndex].Flags & (int)GeneralBitFlags.Descriptor) != 0 ) { + ZipHelperStream helper = new ZipHelperStream(baseStream_); + DescriptorData data = new DescriptorData(); + helper.ReadDataDescriptor(this[entryIndex].LocalHeaderRequiresZip64, data); + if (this[entryIndex].Crc != data.Crc) { + status.AddError(); + } + + if (this[entryIndex].CompressedSize != data.CompressedSize) { + status.AddError(); + } + + if (this[entryIndex].Size != data.Size) { + status.AddError(); + } + } + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.EntryComplete); + resultHandler(status, null); + } + + entryIndex += 1; + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.MiscellaneousTests); + resultHandler(status, null); + } + + // TODO: the 'Corrina Johns' test where local headers are missing from + // the central directory. They are therefore invisible to many archivers. + } + catch (Exception ex) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, string.Format("Exception during test - '{0}'", ex.Message)); + } + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.Complete); + status.SetEntry(null); + resultHandler(status, null); + } + + return (status.ErrorCount == 0); + } + + [Flags] + enum HeaderTest + { + Extract = 0x01, // Check that this header represents an entry whose data can be extracted + Header = 0x02, // Check that this header contents are valid + } + + /// + /// Test a local header against that provided from the central directory + /// + /// + /// The entry to test against + /// + /// The type of tests to carry out. + /// The offset of the entries data in the file + long TestLocalHeader(ZipEntry entry, HeaderTest tests) + { + lock(baseStream_) + { + bool testHeader = (tests & HeaderTest.Header) != 0; + bool testData = (tests & HeaderTest.Extract) != 0; + + baseStream_.Seek(offsetOfFirstEntry + entry.Offset, SeekOrigin.Begin); + if ((int)ReadLEUint() != ZipConstants.LocalHeaderSignature) { + throw new ZipException(string.Format("Wrong local header signature @{0:X}", offsetOfFirstEntry + entry.Offset)); + } + + short extractVersion = ( short )ReadLEUshort(); + short localFlags = ( short )ReadLEUshort(); + short compressionMethod = ( short )ReadLEUshort(); + short fileTime = ( short )ReadLEUshort(); + short fileDate = ( short )ReadLEUshort(); + uint crcValue = ReadLEUint(); + long compressedSize = ReadLEUint(); + long size = ReadLEUint(); + int storedNameLength = ReadLEUshort(); + int extraDataLength = ReadLEUshort(); + + byte[] nameData = new byte[storedNameLength]; + StreamUtils.ReadFully(baseStream_, nameData); + + byte[] extraData = new byte[extraDataLength]; + StreamUtils.ReadFully(baseStream_, extraData); + + ZipExtraData localExtraData = new ZipExtraData(extraData); + + // Extra data / zip64 checks + if (localExtraData.Find(1)) + { + // 2010-03-04 Forum 10512: removed checks for version >= ZipConstants.VersionZip64 + // and size or compressedSize = MaxValue, due to rogue creators. + + size = localExtraData.ReadLong(); + compressedSize = localExtraData.ReadLong(); + + if ((localFlags & (int)GeneralBitFlags.Descriptor) != 0) + { + // These may be valid if patched later + if ( (size != -1) && (size != entry.Size)) { + throw new ZipException("Size invalid for descriptor"); + } + + if ((compressedSize != -1) && (compressedSize != entry.CompressedSize)) { + throw new ZipException("Compressed size invalid for descriptor"); + } + } + } + else + { + // No zip64 extra data but entry requires it. + if ((extractVersion >= ZipConstants.VersionZip64) && + (((uint)size == uint.MaxValue) || ((uint)compressedSize == uint.MaxValue))) + { + throw new ZipException("Required Zip64 extended information missing"); + } + } + + if ( testData ) { + if ( entry.IsFile ) { + if ( !entry.IsCompressionMethodSupported() ) { + throw new ZipException("Compression method not supported"); + } + + if ( (extractVersion > ZipConstants.VersionMadeBy) + || ((extractVersion > 20) && (extractVersion < ZipConstants.VersionZip64)) ) { + throw new ZipException(string.Format("Version required to extract this entry not supported ({0})", extractVersion)); + } + + if ( (localFlags & ( int )(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0 ) { + throw new ZipException("The library does not support the zip version required to extract this entry"); + } + } + } + + if (testHeader) + { + if ((extractVersion <= 63) && // Ignore later versions as we dont know about them.. + (extractVersion != 10) && + (extractVersion != 11) && + (extractVersion != 20) && + (extractVersion != 21) && + (extractVersion != 25) && + (extractVersion != 27) && + (extractVersion != 45) && + (extractVersion != 46) && + (extractVersion != 50) && + (extractVersion != 51) && + (extractVersion != 52) && + (extractVersion != 61) && + (extractVersion != 62) && + (extractVersion != 63) + ) + { + throw new ZipException(string.Format("Version required to extract this entry is invalid ({0})", extractVersion)); + } + + // Local entry flags dont have reserved bit set on. + if ((localFlags & (int)(GeneralBitFlags.ReservedPKware4 | GeneralBitFlags.ReservedPkware14 | GeneralBitFlags.ReservedPkware15)) != 0) + { + throw new ZipException("Reserved bit flags cannot be set."); + } + + // Encryption requires extract version >= 20 + if (((localFlags & (int)GeneralBitFlags.Encrypted) != 0) && (extractVersion < 20)) + { + throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion)); + } + + // Strong encryption requires encryption flag to be set and extract version >= 50. + if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0) + { + if ((localFlags & (int)GeneralBitFlags.Encrypted) == 0) + { + throw new ZipException("Strong encryption flag set but encryption flag is not set"); + } + + if (extractVersion < 50) + { + throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion)); + } + } + + // Patched entries require extract version >= 27 + if (((localFlags & (int)GeneralBitFlags.Patched) != 0) && (extractVersion < 27)) + { + throw new ZipException(string.Format("Patched data requires higher version than ({0})", extractVersion)); + } + + // Central header flags match local entry flags. + if (localFlags != entry.Flags) + { + throw new ZipException("Central header/local header flags mismatch"); + } + + // Central header compression method matches local entry + if (entry.CompressionMethod != (CompressionMethod)compressionMethod) + { + throw new ZipException("Central header/local header compression method mismatch"); + } + + if (entry.Version != extractVersion) + { + throw new ZipException("Extract version mismatch"); + } + + // Strong encryption and extract version match + if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0) + { + if (extractVersion < 62) + { + throw new ZipException("Strong encryption flag set but version not high enough"); + } + } + + if ((localFlags & (int)GeneralBitFlags.HeaderMasked) != 0) + { + if ((fileTime != 0) || (fileDate != 0)) + { + throw new ZipException("Header masked set but date/time values non-zero"); + } + } + + if ((localFlags & (int)GeneralBitFlags.Descriptor) == 0) + { + if (crcValue != (uint)entry.Crc) + { + throw new ZipException("Central header/local header crc mismatch"); + } + } + + // Crc valid for empty entry. + // This will also apply to streamed entries where size isnt known and the header cant be patched + if ((size == 0) && (compressedSize == 0)) + { + if (crcValue != 0) + { + throw new ZipException("Invalid CRC for empty entry"); + } + } + + // TODO: make test more correct... can't compare lengths as was done originally as this can fail for MBCS strings + // Assuming a code page at this point is not valid? Best is to store the name length in the ZipEntry probably + if (entry.Name.Length > storedNameLength) + { + throw new ZipException("File name length mismatch"); + } + + // Name data has already been read convert it and compare. + string localName = ZipConstants.ConvertToStringExt(localFlags, nameData); + + // Central directory and local entry name match + if (localName != entry.Name) + { + throw new ZipException("Central header and local header file name mismatch"); + } + + // Directories have zero actual size but can have compressed size + if (entry.IsDirectory) + { + if (size > 0) + { + throw new ZipException("Directory cannot have size"); + } + + // There may be other cases where the compressed size can be greater than this? + // If so until details are known we will be strict. + if (entry.IsCrypted) + { + if (compressedSize > ZipConstants.CryptoHeaderSize + 2) + { + throw new ZipException("Directory compressed size invalid"); + } + } + else if (compressedSize > 2) + { + // When not compressed the directory size can validly be 2 bytes + // if the true size wasnt known when data was originally being written. + // NOTE: Versions of the library 0.85.4 and earlier always added 2 bytes + throw new ZipException("Directory compressed size invalid"); + } + } + + if (!ZipNameTransform.IsValidName(localName, true)) + { + throw new ZipException("Name is invalid"); + } + } + + // Tests that apply to both data and header. + + // Size can be verified only if it is known in the local header. + // it will always be known in the central header. + if (((localFlags & (int)GeneralBitFlags.Descriptor) == 0) || + ((size > 0) || (compressedSize > 0))) { + + if (size != entry.Size) { + throw new ZipException( + string.Format("Size mismatch between central header({0}) and local header({1})", + entry.Size, size)); + } + + if (compressedSize != entry.CompressedSize && + compressedSize != 0xFFFFFFFF && compressedSize != -1) { + throw new ZipException( + string.Format("Compressed size mismatch between central header({0}) and local header({1})", + entry.CompressedSize, compressedSize)); + } + } + + int extraLength = storedNameLength + extraDataLength; + return offsetOfFirstEntry + entry.Offset + ZipConstants.LocalHeaderBaseSize + extraLength; + } + } + + #endregion + + #region Updating + + const int DefaultBufferSize = 4096; + + /// + /// The kind of update to apply. + /// + enum UpdateCommand + { + Copy, // Copy original file contents. + Modify, // Change encryption, compression, attributes, name, time etc, of an existing file. + Add, // Add a new file to the archive. + } + + #region Properties + /// + /// Get / set the to apply to names when updating. + /// + public INameTransform NameTransform + { + get { + return updateEntryFactory_.NameTransform; + } + + set { + updateEntryFactory_.NameTransform = value; + } + } + + /// + /// Get/set the used to generate values + /// during updates. + /// + public IEntryFactory EntryFactory + { + get { + return updateEntryFactory_; + } + + set { + if (value == null) { + updateEntryFactory_ = new ZipEntryFactory(); + } + else { + updateEntryFactory_ = value; + } + } + } + + /// + /// Get /set the buffer size to be used when updating this zip file. + /// + public int BufferSize + { + get { return bufferSize_; } + set { + if ( value < 1024 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "cannot be below 1024"); +#endif + } + + if ( bufferSize_ != value ) { + bufferSize_ = value; + copyBuffer_ = null; + } + } + } + + /// + /// Get a value indicating an update has been started. + /// + public bool IsUpdating + { + get { return updates_ != null; } + } + + /// + /// Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + /// + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + #endregion + + #region Immediate updating +// TBD: Direct form of updating +// +// public void Update(IEntryMatcher deleteMatcher) +// { +// } +// +// public void Update(IScanner addScanner) +// { +// } + #endregion + + #region Deferred Updating + /// + /// Begin updating this archive. + /// + /// The archive storage for use during the update. + /// The data source to utilise during updating. + /// ZipFile has been closed. + /// One of the arguments provided is null + /// ZipFile has been closed. + public void BeginUpdate(IArchiveStorage archiveStorage, IDynamicDataSource dataSource) + { + if ( archiveStorage == null ) { + throw new ArgumentNullException("archiveStorage"); + } + + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + if ( IsEmbeddedArchive ) { + throw new ZipException ("Cannot update embedded/SFX archives"); + } + + archiveStorage_ = archiveStorage; + updateDataSource_ = dataSource; + + // NOTE: the baseStream_ may not currently support writing or seeking. + + updateIndex_ = new Hashtable(); + + updates_ = new ArrayList(entries_.Length); + foreach(ZipEntry entry in entries_) { + int index = updates_.Add(new ZipUpdate(entry)); + updateIndex_.Add(entry.Name, index); + } + + // We must sort by offset before using offset's calculated sizes + updates_.Sort(new UpdateComparer()); + + int idx = 0; + foreach (ZipUpdate update in updates_) { + //If last entry, there is no next entry offset to use + if (idx == updates_.Count - 1) + break; + + update.OffsetBasedSize = ((ZipUpdate)updates_[idx + 1]).Entry.Offset - update.Entry.Offset; + idx++; + } + updateCount_ = updates_.Count; + + contentsEdited_ = false; + commentEdited_ = false; + newComment_ = null; + } + + /// + /// Begin updating to this archive. + /// + /// The storage to use during the update. + public void BeginUpdate(IArchiveStorage archiveStorage) + { + BeginUpdate(archiveStorage, new DynamicDiskDataSource()); + } + + /// + /// Begin updating this archive. + /// + /// + /// + /// + public void BeginUpdate() + { + if ( Name == null ) { + BeginUpdate(new MemoryArchiveStorage(), new DynamicDiskDataSource()); + } + else { + BeginUpdate(new DiskArchiveStorage(this), new DynamicDiskDataSource()); + } + } + + /// + /// Commit current updates, updating this archive. + /// + /// + /// + /// ZipFile has been closed. + public void CommitUpdate() + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + CheckUpdating(); + + try { + updateIndex_.Clear(); + updateIndex_=null; + + if( contentsEdited_ ) { + RunUpdates(); + } + else if( commentEdited_ ) { + UpdateCommentOnly(); + } + else { + // Create an empty archive if none existed originally. + if( entries_.Length==0 ) { + byte[] theComment=(newComment_!=null)?newComment_.RawComment:ZipConstants.ConvertToArray(comment_); + using( ZipHelperStream zhs=new ZipHelperStream(baseStream_) ) { + zhs.WriteEndOfCentralDirectory(0, 0, 0, theComment); + } + } + } + + } + finally { + PostUpdateCleanup(); + } + } + + /// + /// Abort updating leaving the archive unchanged. + /// + /// + /// + public void AbortUpdate() + { + PostUpdateCleanup(); + } + + /// + /// Set the file comment to be recorded when the current update is commited. + /// + /// The comment to record. + /// ZipFile has been closed. + public void SetComment(string comment) + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + CheckUpdating(); + + newComment_ = new ZipString(comment); + + if ( newComment_.RawLength > 0xffff ) { + newComment_ = null; + throw new ZipException("Comment length exceeds maximum - 65535"); + } + + // We dont take account of the original and current comment appearing to be the same + // as encoding may be different. + commentEdited_ = true; + } + + #endregion + + #region Adding Entries + + void AddUpdate(ZipUpdate update) + { + contentsEdited_ = true; + + int index = FindExistingUpdate(update.Entry.Name); + + if (index >= 0) { + if ( updates_[index] == null ) { + updateCount_ += 1; + } + + // Direct replacement is faster than delete and add. + updates_[index] = update; + } + else { + index = updates_.Add(update); + updateCount_ += 1; + updateIndex_.Add(update.Entry.Name, index); + } + } + + /// + /// Add a new entry to the archive. + /// + /// The name of the file to add. + /// The compression method to use. + /// Ensure Unicode text is used for name and comment for this entry. + /// Argument supplied is null. + /// ZipFile has been closed. + /// Compression method is not supported. + public void Add(string fileName, CompressionMethod compressionMethod, bool useUnicodeText ) + { + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + if (!ZipEntry.IsCompressionMethodSupported(compressionMethod)) { + throw new ArgumentOutOfRangeException("compressionMethod"); + } + + CheckUpdating(); + contentsEdited_ = true; + + ZipEntry entry = EntryFactory.MakeFileEntry(fileName); + entry.IsUnicodeText = useUnicodeText; + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(fileName, entry)); + } + + /// + /// Add a new entry to the archive. + /// + /// The name of the file to add. + /// The compression method to use. + /// ZipFile has been closed. + /// The compression method is not supported. + public void Add(string fileName, CompressionMethod compressionMethod) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + if ( !ZipEntry.IsCompressionMethodSupported(compressionMethod) ) { + throw new ArgumentOutOfRangeException("compressionMethod"); + } + + CheckUpdating(); + contentsEdited_ = true; + + ZipEntry entry = EntryFactory.MakeFileEntry(fileName); + entry.CompressionMethod = compressionMethod; + AddUpdate(new ZipUpdate(fileName, entry)); + } + + /// + /// Add a file to the archive. + /// + /// The name of the file to add. + /// Argument supplied is null. + public void Add(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(fileName, EntryFactory.MakeFileEntry(fileName))); + } + + /// + /// Add a file to the archive. + /// + /// The name of the file to add. + /// The name to use for the on the Zip file created. + /// Argument supplied is null. + public void Add(string fileName, string entryName) + { + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(fileName, EntryFactory.MakeFileEntry(entryName))); + } + + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + public void Add(IStaticDataSource dataSource, string entryName) + { + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(dataSource, EntryFactory.MakeFileEntry(entryName, false))); + } + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + /// The compression method to use. + public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod) + { + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + + ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false); + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(dataSource, entry)); + } + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + /// The compression method to use. + /// Ensure Unicode text is used for name and comments for this entry. + public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod, bool useUnicodeText) + { + if (dataSource == null) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + + ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false); + entry.IsUnicodeText = useUnicodeText; + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(dataSource, entry)); + } + + /// + /// Add a that contains no data. + /// + /// The entry to add. + /// This can be used to add directories, volume labels, or empty file entries. + public void Add(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + CheckUpdating(); + + if ( (entry.Size != 0) || (entry.CompressedSize != 0) ) { + throw new ZipException("Entry cannot have any data"); + } + + AddUpdate(new ZipUpdate(UpdateCommand.Add, entry)); + } + + /// + /// Add a directory entry to the archive. + /// + /// The directory to add. + public void AddDirectory(string directoryName) + { + if ( directoryName == null ) { + throw new ArgumentNullException("directoryName"); + } + + CheckUpdating(); + + ZipEntry dirEntry = EntryFactory.MakeDirectoryEntry(directoryName); + AddUpdate(new ZipUpdate(UpdateCommand.Add, dirEntry)); + } + + #endregion + + #region Modifying Entries +/* Modify not yet ready for public consumption. + Direct modification of an entry should not overwrite original data before its read. + Safe mode is trivial in this sense. + public void Modify(ZipEntry original, ZipEntry updated) + { + if ( original == null ) { + throw new ArgumentNullException("original"); + } + + if ( updated == null ) { + throw new ArgumentNullException("updated"); + } + + CheckUpdating(); + contentsEdited_ = true; + updates_.Add(new ZipUpdate(original, updated)); + } +*/ + #endregion + + #region Deleting Entries + /// + /// Delete an entry by name + /// + /// The filename to delete + /// True if the entry was found and deleted; false otherwise. + public bool Delete(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + CheckUpdating(); + + bool result = false; + int index = FindExistingUpdate(fileName); + if ( (index >= 0) && (updates_[index] != null) ) { + result = true; + contentsEdited_ = true; + updates_[index] = null; + updateCount_ -= 1; + } + else { + throw new ZipException("Cannot find entry to delete"); + } + return result; + } + + /// + /// Delete a from the archive. + /// + /// The entry to delete. + public void Delete(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + CheckUpdating(); + + int index = FindExistingUpdate(entry); + if ( index >= 0 ) { + contentsEdited_ = true; + updates_[index] = null; + updateCount_ -= 1; + } + else { + throw new ZipException("Cannot find entry to delete"); + } + } + + #endregion + + #region Update Support + + #region Writing Values/Headers + void WriteLEShort(int value) + { + baseStream_.WriteByte(( byte )(value & 0xff)); + baseStream_.WriteByte(( byte )((value >> 8) & 0xff)); + } + + /// + /// Write an unsigned short in little endian byte order. + /// + void WriteLEUshort(ushort value) + { + baseStream_.WriteByte(( byte )(value & 0xff)); + baseStream_.WriteByte(( byte )(value >> 8)); + } + + /// + /// Write an int in little endian byte order. + /// + void WriteLEInt(int value) + { + WriteLEShort(value & 0xffff); + WriteLEShort(value >> 16); + } + + /// + /// Write an unsigned int in little endian byte order. + /// + void WriteLEUint(uint value) + { + WriteLEUshort((ushort)(value & 0xffff)); + WriteLEUshort((ushort)(value >> 16)); + } + + /// + /// Write a long in little endian byte order. + /// + void WriteLeLong(long value) + { + WriteLEInt(( int )(value & 0xffffffff)); + WriteLEInt(( int )(value >> 32)); + } + + void WriteLEUlong(ulong value) + { + WriteLEUint(( uint )(value & 0xffffffff)); + WriteLEUint(( uint )(value >> 32)); + } + + void WriteLocalEntryHeader(ZipUpdate update) + { + ZipEntry entry = update.OutEntry; + + // TODO: Local offset will require adjusting for multi-disk zip files. + entry.Offset = baseStream_.Position; + + // TODO: Need to clear any entry flags that dont make sense or throw an exception here. + if (update.Command != UpdateCommand.Copy) { + if (entry.CompressionMethod == CompressionMethod.Deflated) { + if (entry.Size == 0) { + // No need to compress - no data. + entry.CompressedSize = entry.Size; + entry.Crc = 0; + entry.CompressionMethod = CompressionMethod.Stored; + } + } + else if (entry.CompressionMethod == CompressionMethod.Stored) { + entry.Flags &= ~(int)GeneralBitFlags.Descriptor; + } + + if (HaveKeys) { + entry.IsCrypted = true; + if (entry.Crc < 0) { + entry.Flags |= (int)GeneralBitFlags.Descriptor; + } + } + else { + entry.IsCrypted = false; + } + + switch (useZip64_) { + case UseZip64.Dynamic: + if (entry.Size < 0) { + entry.ForceZip64(); + } + break; + + case UseZip64.On: + entry.ForceZip64(); + break; + + case UseZip64.Off: + // Do nothing. The entry itself may be using Zip64 independantly. + break; + } + } + + // Write the local file header + WriteLEInt(ZipConstants.LocalHeaderSignature); + + WriteLEShort(entry.Version); + WriteLEShort(entry.Flags); + + WriteLEShort((byte)entry.CompressionMethod); + WriteLEInt(( int )entry.DosTime); + + if ( !entry.HasCrc ) { + // Note patch address for updating CRC later. + update.CrcPatchOffset = baseStream_.Position; + WriteLEInt(( int )0); + } + else { + WriteLEInt(unchecked(( int )entry.Crc)); + } + + if (entry.LocalHeaderRequiresZip64) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + if ( (entry.CompressedSize < 0) || (entry.Size < 0) ) { + update.SizePatchOffset = baseStream_.Position; + } + + WriteLEInt(( int )entry.CompressedSize); + WriteLEInt(( int )entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if ( name.Length > 0xFFFF ) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.LocalHeaderRequiresZip64 ) { + ed.StartNewEntry(); + + // Local entry header always includes size and compressed size. + // NOTE the order of these fields is reversed when compared to the normal headers! + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + ed.AddNewEntry(1); + } + else { + ed.Delete(1); + } + + entry.ExtraData = ed.GetEntryData(); + + WriteLEShort(name.Length); + WriteLEShort(entry.ExtraData.Length); + + if ( name.Length > 0 ) { + baseStream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 ) { + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cannot find extra data"); + } + + update.SizePatchOffset = baseStream_.Position + ed.CurrentReadIndex; + } + + if ( entry.ExtraData.Length > 0 ) { + baseStream_.Write(entry.ExtraData, 0, entry.ExtraData.Length); + } + } + + int WriteCentralDirectoryHeader(ZipEntry entry) + { + if ( entry.CompressedSize < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown csize"); + } + + if ( entry.Size < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown size"); + } + + if ( entry.Crc < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown crc"); + } + + // Write the central file header + WriteLEInt(ZipConstants.CentralHeaderSignature); + + // Version made by + WriteLEShort(ZipConstants.VersionMadeBy); + + // Version required to extract + WriteLEShort(entry.Version); + + WriteLEShort(entry.Flags); + + unchecked { + WriteLEShort((byte)entry.CompressionMethod); + WriteLEInt((int)entry.DosTime); + WriteLEInt((int)entry.Crc); + } + + if ( (entry.IsZip64Forced()) || (entry.CompressedSize >= 0xffffffff) ) { + WriteLEInt(-1); + } + else { + WriteLEInt((int)(entry.CompressedSize & 0xffffffff)); + } + + if ( (entry.IsZip64Forced()) || (entry.Size >= 0xffffffff) ) { + WriteLEInt(-1); + } + else { + WriteLEInt((int)entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if ( name.Length > 0xFFFF ) { + throw new ZipException("Entry name is too long."); + } + + WriteLEShort(name.Length); + + // Central header extra data is different to local header version so regenerate. + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.CentralHeaderRequiresZip64 ) { + ed.StartNewEntry(); + + if ( (entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) ) + { + ed.AddLeLong(entry.Size); + } + + if ( (entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) ) + { + ed.AddLeLong(entry.CompressedSize); + } + + if ( entry.Offset >= 0xffffffff ) { + ed.AddLeLong(entry.Offset); + } + + // Number of disk on which this file starts isnt supported and is never written here. + ed.AddNewEntry(1); + } + else { + // Should have already be done when local header was added. + ed.Delete(1); + } + + byte[] centralExtraData = ed.GetEntryData(); + + WriteLEShort(centralExtraData.Length); + WriteLEShort(entry.Comment != null ? entry.Comment.Length : 0); + + WriteLEShort(0); // disk number + WriteLEShort(0); // internal file attributes + + // External file attributes... + if ( entry.ExternalFileAttributes != -1 ) { + WriteLEInt(entry.ExternalFileAttributes); + } + else { + if ( entry.IsDirectory ) { + WriteLEUint(16); + } + else { + WriteLEUint(0); + } + } + + if ( entry.Offset >= 0xffffffff ) { + WriteLEUint(0xffffffff); + } + else { + WriteLEUint((uint)(int)entry.Offset); + } + + if ( name.Length > 0 ) { + baseStream_.Write(name, 0, name.Length); + } + + if ( centralExtraData.Length > 0 ) { + baseStream_.Write(centralExtraData, 0, centralExtraData.Length); + } + + byte[] rawComment = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : new byte[0]; + + if ( rawComment.Length > 0 ) { + baseStream_.Write(rawComment, 0, rawComment.Length); + } + + return ZipConstants.CentralHeaderBaseSize + name.Length + centralExtraData.Length + rawComment.Length; + } + #endregion + + void PostUpdateCleanup() + { + updateDataSource_ = null; + updates_ = null; + updateIndex_ = null; + + if (archiveStorage_ != null) + { + archiveStorage_.Dispose(); + archiveStorage_=null; + } + } + + string GetTransformedFileName(string name) + { + INameTransform transform = NameTransform; + return (transform != null) ? + transform.TransformFile(name) : + name; + } + + string GetTransformedDirectoryName(string name) + { + INameTransform transform = NameTransform; + return (transform != null) ? + transform.TransformDirectory(name) : + name; + } + + /// + /// Get a raw memory buffer. + /// + /// Returns a raw memory buffer. + byte[] GetBuffer() + { + if ( copyBuffer_ == null ) { + copyBuffer_ = new byte[bufferSize_]; + } + return copyBuffer_; + } + + void CopyDescriptorBytes(ZipUpdate update, Stream dest, Stream source) + { + int bytesToCopy = GetDescriptorSize(update); + + if ( bytesToCopy > 0 ) { + byte[] buffer = GetBuffer(); + + while ( bytesToCopy > 0 ) { + int readSize = Math.Min(buffer.Length, bytesToCopy); + + int bytesRead = source.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + dest.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + } + else { + throw new ZipException("Unxpected end of stream"); + } + } + } + } + + void CopyBytes(ZipUpdate update, Stream destination, Stream source, + long bytesToCopy, bool updateCrc) + { + if ( destination == source ) { + throw new InvalidOperationException("Destination and source are the same"); + } + + // NOTE: Compressed size is updated elsewhere. + Crc32 crc = new Crc32(); + byte[] buffer = GetBuffer(); + + long targetBytes = bytesToCopy; + long totalBytesRead = 0; + + int bytesRead; + do { + int readSize = buffer.Length; + + if ( bytesToCopy < readSize ) { + readSize = (int)bytesToCopy; + } + + bytesRead = source.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + if ( updateCrc ) { + crc.Update(buffer, 0, bytesRead); + } + destination.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + totalBytesRead += bytesRead; + } + } + while ( (bytesRead > 0) && (bytesToCopy > 0) ); + + if ( totalBytesRead != targetBytes ) { + throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); + } + + if ( updateCrc ) { + update.OutEntry.Crc = crc.Value; + } + } + + /// + /// Get the size of the source descriptor for a . + /// + /// The update to get the size for. + /// The descriptor size, zero if there isnt one. + int GetDescriptorSize(ZipUpdate update) + { + int result = 0; + if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) { + result = ZipConstants.DataDescriptorSize - 4; + if ( update.Entry.LocalHeaderRequiresZip64 ) { + result = ZipConstants.Zip64DataDescriptorSize - 4; + } + } + return result; + } + + void CopyDescriptorBytesDirect(ZipUpdate update, Stream stream, ref long destinationPosition, long sourcePosition) + { + int bytesToCopy = GetDescriptorSize(update); + + while ( bytesToCopy > 0 ) { + int readSize = (int)bytesToCopy; + byte[] buffer = GetBuffer(); + + stream.Position = sourcePosition; + int bytesRead = stream.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + stream.Position = destinationPosition; + stream.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + destinationPosition += bytesRead; + sourcePosition += bytesRead; + } + else { + throw new ZipException("Unxpected end of stream"); + } + } + } + + void CopyEntryDataDirect(ZipUpdate update, Stream stream, bool updateCrc, ref long destinationPosition, ref long sourcePosition) + { + long bytesToCopy = update.Entry.CompressedSize; + + // NOTE: Compressed size is updated elsewhere. + Crc32 crc = new Crc32(); + byte[] buffer = GetBuffer(); + + long targetBytes = bytesToCopy; + long totalBytesRead = 0; + + int bytesRead; + do + { + int readSize = buffer.Length; + + if ( bytesToCopy < readSize ) { + readSize = (int)bytesToCopy; + } + + stream.Position = sourcePosition; + bytesRead = stream.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + if ( updateCrc ) { + crc.Update(buffer, 0, bytesRead); + } + stream.Position = destinationPosition; + stream.Write(buffer, 0, bytesRead); + + destinationPosition += bytesRead; + sourcePosition += bytesRead; + bytesToCopy -= bytesRead; + totalBytesRead += bytesRead; + } + } + while ( (bytesRead > 0) && (bytesToCopy > 0) ); + + if ( totalBytesRead != targetBytes ) { + throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); + } + + if ( updateCrc ) { + update.OutEntry.Crc = crc.Value; + } + } + + int FindExistingUpdate(ZipEntry entry) + { + int result = -1; + string convertedName = GetTransformedFileName(entry.Name); + + if (updateIndex_.ContainsKey(convertedName)) { + result = (int)updateIndex_[convertedName]; + } +/* + // This is slow like the coming of the next ice age but takes less storage and may be useful + // for CF? + for (int index = 0; index < updates_.Count; ++index) + { + ZipUpdate zu = ( ZipUpdate )updates_[index]; + if ( (zu.Entry.ZipFileIndex == entry.ZipFileIndex) && + (string.Compare(convertedName, zu.Entry.Name, true, CultureInfo.InvariantCulture) == 0) ) { + result = index; + break; + } + } + */ + return result; + } + + int FindExistingUpdate(string fileName) + { + int result = -1; + + string convertedName = GetTransformedFileName(fileName); + + if (updateIndex_.ContainsKey(convertedName)) { + result = (int)updateIndex_[convertedName]; + } + +/* + // This is slow like the coming of the next ice age but takes less storage and may be useful + // for CF? + for ( int index = 0; index < updates_.Count; ++index ) { + if ( string.Compare(convertedName, (( ZipUpdate )updates_[index]).Entry.Name, + true, CultureInfo.InvariantCulture) == 0 ) { + result = index; + break; + } + } + */ + + return result; + } + + /// + /// Get an output stream for the specified + /// + /// The entry to get an output stream for. + /// The output stream obtained for the entry. + Stream GetOutputStream(ZipEntry entry) + { + Stream result = baseStream_; + + if ( entry.IsCrypted == true ) { +#if NETCF_1_0 + throw new ZipException("Encryption not supported for Compact Framework 1.0"); +#else + result = CreateAndInitEncryptionStream(result, entry); +#endif + } + + switch ( entry.CompressionMethod ) { + case CompressionMethod.Stored: + result = new UncompressedStream(result); + break; + + case CompressionMethod.Deflated: + DeflaterOutputStream dos = new DeflaterOutputStream(result, new Deflater(9, true)); + dos.IsStreamOwner = false; + result = dos; + break; + + default: + throw new ZipException("Unknown compression method " + entry.CompressionMethod); + } + return result; + } + + void AddEntry(ZipFile workFile, ZipUpdate update) + { + Stream source = null; + + if ( update.Entry.IsFile ) { + source = update.GetSource(); + + if ( source == null ) { + source = updateDataSource_.GetSource(update.Entry, update.Filename); + } + } + + if ( source != null ) { + using ( source ) { + long sourceStreamLength = source.Length; + if ( update.OutEntry.Size < 0 ) { + update.OutEntry.Size = sourceStreamLength; + } + else { + // Check for errant entries. + if ( update.OutEntry.Size != sourceStreamLength ) { + throw new ZipException("Entry size/stream size mismatch"); + } + } + + workFile.WriteLocalEntryHeader(update); + + long dataStart = workFile.baseStream_.Position; + + using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) { + CopyBytes(update, output, source, sourceStreamLength, true); + } + + long dataEnd = workFile.baseStream_.Position; + update.OutEntry.CompressedSize = dataEnd - dataStart; + + if ((update.OutEntry.Flags & (int)GeneralBitFlags.Descriptor) == (int)GeneralBitFlags.Descriptor) + { + ZipHelperStream helper = new ZipHelperStream(workFile.baseStream_); + helper.WriteDataDescriptor(update.OutEntry); + } + } + } + else { + workFile.WriteLocalEntryHeader(update); + update.OutEntry.CompressedSize = 0; + } + + } + + void ModifyEntry(ZipFile workFile, ZipUpdate update) + { + workFile.WriteLocalEntryHeader(update); + long dataStart = workFile.baseStream_.Position; + + // TODO: This is slow if the changes don't effect the data!! + if ( update.Entry.IsFile && (update.Filename != null) ) { + using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) { + using ( Stream source = this.GetInputStream(update.Entry) ) { + CopyBytes(update, output, source, source.Length, true); + } + } + } + + long dataEnd = workFile.baseStream_.Position; + update.Entry.CompressedSize = dataEnd - dataStart; + } + + void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition) + { + bool skipOver = false; + if ( update.Entry.Offset == destinationPosition ) { + skipOver = true; + } + + if ( !skipOver ) { + baseStream_.Position = destinationPosition; + workFile.WriteLocalEntryHeader(update); + destinationPosition = baseStream_.Position; + } + + long sourcePosition = 0; + + const int NameLengthOffset = 26; + + // TODO: Add base for SFX friendly handling + long entryDataOffset = update.Entry.Offset + NameLengthOffset; + + baseStream_.Seek(entryDataOffset, SeekOrigin.Begin); + + // Clumsy way of handling retrieving the original name and extra data length for now. + // TODO: Stop re-reading name and data length in CopyEntryDirect. + uint nameLength = ReadLEUshort(); + uint extraLength = ReadLEUshort(); + + sourcePosition = baseStream_.Position + nameLength + extraLength; + + if (skipOver) { + if (update.OffsetBasedSize != -1) + destinationPosition += update.OffsetBasedSize; + else + // TODO: Find out why this calculation comes up 4 bytes short on some entries in ODT (Office Document Text) archives. + // WinZip produces a warning on these entries: + // "caution: value of lrec.csize (compressed size) changed from ..." + destinationPosition += + (sourcePosition - entryDataOffset) + NameLengthOffset + // Header size + update.Entry.CompressedSize + GetDescriptorSize(update); + } + else { + if ( update.Entry.CompressedSize > 0 ) { + CopyEntryDataDirect(update, baseStream_, false, ref destinationPosition, ref sourcePosition ); + } + CopyDescriptorBytesDirect(update, baseStream_, ref destinationPosition, sourcePosition); + } + } + + void CopyEntry(ZipFile workFile, ZipUpdate update) + { + workFile.WriteLocalEntryHeader(update); + + if ( update.Entry.CompressedSize > 0 ) { + const int NameLengthOffset = 26; + + long entryDataOffset = update.Entry.Offset + NameLengthOffset; + + // TODO: This wont work for SFX files! + baseStream_.Seek(entryDataOffset, SeekOrigin.Begin); + + uint nameLength = ReadLEUshort(); + uint extraLength = ReadLEUshort(); + + baseStream_.Seek(nameLength + extraLength, SeekOrigin.Current); + + CopyBytes(update, workFile.baseStream_, baseStream_, update.Entry.CompressedSize, false); + } + CopyDescriptorBytes(update, workFile.baseStream_, baseStream_); + } + + void Reopen(Stream source) + { + if ( source == null ) { + throw new ZipException("Failed to reopen archive - no source"); + } + + isNewArchive_ = false; + baseStream_ = source; + ReadEntries(); + } + + void Reopen() + { + if (Name == null) { + throw new InvalidOperationException("Name is not known cannot Reopen"); + } + + Reopen(File.Open(Name, FileMode.Open, FileAccess.Read, FileShare.Read)); + } + + void UpdateCommentOnly() + { + long baseLength = baseStream_.Length; + + ZipHelperStream updateFile = null; + + if ( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { + Stream copyStream = archiveStorage_.MakeTemporaryCopy(baseStream_); + updateFile = new ZipHelperStream(copyStream); + updateFile.IsStreamOwner = true; + + baseStream_.Close(); + baseStream_ = null; + } + else { + if (archiveStorage_.UpdateMode == FileUpdateMode.Direct) { + // TODO: archiveStorage wasnt originally intended for this use. + // Need to revisit this to tidy up handling as archive storage currently doesnt + // handle the original stream well. + // The problem is when using an existing zip archive with an in memory archive storage. + // The open stream wont support writing but the memory storage should open the same file not an in memory one. + + // Need to tidy up the archive storage interface and contract basically. + baseStream_ = archiveStorage_.OpenForDirectUpdate(baseStream_); + updateFile = new ZipHelperStream(baseStream_); + } + else { + baseStream_.Close(); + baseStream_ = null; + updateFile = new ZipHelperStream(Name); + } + } + + using ( updateFile ) { + long locatedCentralDirOffset = + updateFile.LocateBlockWithSignature(ZipConstants.EndOfCentralDirectorySignature, + baseLength, ZipConstants.EndOfCentralRecordBaseSize, 0xffff); + if ( locatedCentralDirOffset < 0 ) { + throw new ZipException("Cannot find central directory"); + } + + const int CentralHeaderCommentSizeOffset = 16; + updateFile.Position += CentralHeaderCommentSizeOffset; + + byte[] rawComment = newComment_.RawComment; + + updateFile.WriteLEShort(rawComment.Length); + updateFile.Write(rawComment, 0, rawComment.Length); + updateFile.SetLength(updateFile.Position); + } + + if ( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { + Reopen(archiveStorage_.ConvertTemporaryToFinal()); + } + else { + ReadEntries(); + } + } + + /// + /// Class used to sort updates. + /// + class UpdateComparer : IComparer + { + /// + /// Compares two objects and returns a value indicating whether one is + /// less than, equal to or greater than the other. + /// + /// First object to compare + /// Second object to compare. + /// Compare result. + public int Compare( + object x, + object y) + { + ZipUpdate zx = x as ZipUpdate; + ZipUpdate zy = y as ZipUpdate; + + int result; + + if (zx == null) { + if (zy == null) { + result = 0; + } + else { + result = -1; + } + } + else if (zy == null) { + result = 1; + } + else { + int xCmdValue = ((zx.Command == UpdateCommand.Copy) || (zx.Command == UpdateCommand.Modify)) ? 0 : 1; + int yCmdValue = ((zy.Command == UpdateCommand.Copy) || (zy.Command == UpdateCommand.Modify)) ? 0 : 1; + + result = xCmdValue - yCmdValue; + if (result == 0) { + long offsetDiff = zx.Entry.Offset - zy.Entry.Offset; + if (offsetDiff < 0) { + result = -1; + } + else if (offsetDiff == 0) { + result = 0; + } + else { + result = 1; + } + } + } + return result; + } + } + + void RunUpdates() + { + long sizeEntries = 0; + long endOfStream = 0; + bool directUpdate = false; + long destinationPosition = 0; // NOT SFX friendly + + ZipFile workFile; + + if ( IsNewArchive ) { + workFile = this; + workFile.baseStream_.Position = 0; + directUpdate = true; + } + else if ( archiveStorage_.UpdateMode == FileUpdateMode.Direct ) { + workFile = this; + workFile.baseStream_.Position = 0; + directUpdate = true; + + // Sort the updates by offset within copies/modifies, then adds. + // This ensures that data required by copies will not be overwritten. + updates_.Sort(new UpdateComparer()); + } + else { + workFile = ZipFile.Create(archiveStorage_.GetTemporaryOutput()); + workFile.UseZip64 = UseZip64; + + if (key != null) { + workFile.key = (byte[])key.Clone(); + } + } + + try { + foreach ( ZipUpdate update in updates_ ) { + if (update != null) { + switch (update.Command) { + case UpdateCommand.Copy: + if (directUpdate) { + CopyEntryDirect(workFile, update, ref destinationPosition); + } + else { + CopyEntry(workFile, update); + } + break; + + case UpdateCommand.Modify: + // TODO: Direct modifying of an entry will take some legwork. + ModifyEntry(workFile, update); + break; + + case UpdateCommand.Add: + if (!IsNewArchive && directUpdate) { + workFile.baseStream_.Position = destinationPosition; + } + + AddEntry(workFile, update); + + if (directUpdate) { + destinationPosition = workFile.baseStream_.Position; + } + break; + } + } + } + + if ( !IsNewArchive && directUpdate ) { + workFile.baseStream_.Position = destinationPosition; + } + + long centralDirOffset = workFile.baseStream_.Position; + + foreach ( ZipUpdate update in updates_ ) { + if (update != null) { + sizeEntries += workFile.WriteCentralDirectoryHeader(update.OutEntry); + } + } + + byte[] theComment = (newComment_ != null) ? newComment_.RawComment : ZipConstants.ConvertToArray(comment_); + using ( ZipHelperStream zhs = new ZipHelperStream(workFile.baseStream_) ) { + zhs.WriteEndOfCentralDirectory(updateCount_, sizeEntries, centralDirOffset, theComment); + } + + endOfStream = workFile.baseStream_.Position; + + // And now patch entries... + foreach ( ZipUpdate update in updates_ ) { + if (update != null) + { + // If the size of the entry is zero leave the crc as 0 as well. + // The calculated crc will be all bits on... + if ((update.CrcPatchOffset > 0) && (update.OutEntry.CompressedSize > 0)) { + workFile.baseStream_.Position = update.CrcPatchOffset; + workFile.WriteLEInt((int)update.OutEntry.Crc); + } + + if (update.SizePatchOffset > 0) { + workFile.baseStream_.Position = update.SizePatchOffset; + if (update.OutEntry.LocalHeaderRequiresZip64) { + workFile.WriteLeLong(update.OutEntry.Size); + workFile.WriteLeLong(update.OutEntry.CompressedSize); + } + else { + workFile.WriteLEInt((int)update.OutEntry.CompressedSize); + workFile.WriteLEInt((int)update.OutEntry.Size); + } + } + } + } + } + catch { + workFile.Close(); + if (!directUpdate && (workFile.Name != null)) { + File.Delete(workFile.Name); + } + throw; + } + + if (directUpdate) { + workFile.baseStream_.SetLength(endOfStream); + workFile.baseStream_.Flush(); + isNewArchive_ = false; + ReadEntries(); + } + else { + baseStream_.Close(); + Reopen(archiveStorage_.ConvertTemporaryToFinal()); + } + } + + void CheckUpdating() + { + if ( updates_ == null ) { + throw new InvalidOperationException("BeginUpdate has not been called"); + } + } + + #endregion + + #region ZipUpdate class + /// + /// Represents a pending update to a Zip file. + /// + class ZipUpdate + { + #region Constructors + public ZipUpdate(string fileName, ZipEntry entry) + { + command_ = UpdateCommand.Add; + entry_ = entry; + filename_ = fileName; + } + + [Obsolete] + public ZipUpdate(string fileName, string entryName, CompressionMethod compressionMethod) + { + command_ = UpdateCommand.Add; + entry_ = new ZipEntry(entryName); + entry_.CompressionMethod = compressionMethod; + filename_ = fileName; + } + + [Obsolete] + public ZipUpdate(string fileName, string entryName) + : this(fileName, entryName, CompressionMethod.Deflated) + { + // Do nothing. + } + + [Obsolete] + public ZipUpdate(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod) + { + command_ = UpdateCommand.Add; + entry_ = new ZipEntry(entryName); + entry_.CompressionMethod = compressionMethod; + dataSource_ = dataSource; + } + + public ZipUpdate(IStaticDataSource dataSource, ZipEntry entry) + { + command_ = UpdateCommand.Add; + entry_ = entry; + dataSource_ = dataSource; + } + + public ZipUpdate(ZipEntry original, ZipEntry updated) + { + throw new ZipException("Modify not currently supported"); + /* + command_ = UpdateCommand.Modify; + entry_ = ( ZipEntry )original.Clone(); + outEntry_ = ( ZipEntry )updated.Clone(); + */ + } + + public ZipUpdate(UpdateCommand command, ZipEntry entry) + { + command_ = command; + entry_ = ( ZipEntry )entry.Clone(); + } + + + /// + /// Copy an existing entry. + /// + /// The existing entry to copy. + public ZipUpdate(ZipEntry entry) + : this(UpdateCommand.Copy, entry) + { + // Do nothing. + } + #endregion + + /// + /// Get the for this update. + /// + /// This is the source or original entry. + public ZipEntry Entry + { + get { return entry_; } + } + + /// + /// Get the that will be written to the updated/new file. + /// + public ZipEntry OutEntry + { + get { + if ( outEntry_ == null ) { + outEntry_ = (ZipEntry)entry_.Clone(); + } + + return outEntry_; + } + } + + /// + /// Get the command for this update. + /// + public UpdateCommand Command + { + get { return command_; } + } + + /// + /// Get the filename if any for this update. Null if none exists. + /// + public string Filename + { + get { return filename_; } + } + + /// + /// Get/set the location of the size patch for this update. + /// + public long SizePatchOffset + { + get { return sizePatchOffset_; } + set { sizePatchOffset_ = value; } + } + + /// + /// Get /set the location of the crc patch for this update. + /// + public long CrcPatchOffset + { + get { return crcPatchOffset_; } + set { crcPatchOffset_ = value; } + } + + /// + /// Get/set the size calculated by offset. + /// Specifically, the difference between this and next entry's starting offset. + /// + public long OffsetBasedSize + { + get { return _offsetBasedSize; } + set { _offsetBasedSize = value; } + } + + public Stream GetSource() + { + Stream result = null; + if ( dataSource_ != null ) { + result = dataSource_.GetSource(); + } + + return result; + } + + #region Instance Fields + ZipEntry entry_; + ZipEntry outEntry_; + UpdateCommand command_; + IStaticDataSource dataSource_; + string filename_; + long sizePatchOffset_ = -1; + long crcPatchOffset_ = -1; + long _offsetBasedSize = -1; + #endregion + } + + #endregion + #endregion + + #region Disposing + + #region IDisposable Members + void IDisposable.Dispose() + { + Close(); + } + #endregion + + void DisposeInternal(bool disposing) + { + if ( !isDisposed_ ) { + isDisposed_ = true; + entries_ = new ZipEntry[0]; + + if ( IsStreamOwner && (baseStream_ != null) ) { + lock(baseStream_) { + baseStream_.Close(); + } + } + + PostUpdateCleanup(); + } + } + + /// + /// Releases the unmanaged resources used by the this instance and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + DisposeInternal(disposing); + } + + #endregion + + #region Internal routines + #region Reading + /// + /// Read an unsigned short in little endian byte order. + /// + /// Returns the value read. + /// + /// The stream ends prematurely + /// + ushort ReadLEUshort() + { + int data1 = baseStream_.ReadByte(); + + if ( data1 < 0 ) { + throw new EndOfStreamException("End of stream"); + } + + int data2 = baseStream_.ReadByte(); + + if ( data2 < 0 ) { + throw new EndOfStreamException("End of stream"); + } + + + return unchecked((ushort)((ushort)data1 | (ushort)(data2 << 8))); + } + + /// + /// Read a uint in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + uint ReadLEUint() + { + return (uint)(ReadLEUshort() | (ReadLEUshort() << 16)); + } + + ulong ReadLEUlong() + { + return ReadLEUint() | ((ulong)ReadLEUint() << 32); + } + + #endregion + // NOTE this returns the offset of the first byte after the signature. + long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + { + using ( ZipHelperStream les = new ZipHelperStream(baseStream_) ) { + return les.LocateBlockWithSignature(signature, endLocation, minimumBlockSize, maximumVariableData); + } + } + + /// + /// Search for and read the central directory of a zip file filling the entries array. + /// + /// + /// An i/o error occurs. + /// + /// + /// The central directory is malformed or cannot be found + /// + void ReadEntries() + { + // Search for the End Of Central Directory. When a zip comment is + // present the directory will start earlier + // + // The search is limited to 64K which is the maximum size of a trailing comment field to aid speed. + // This should be compatible with both SFX and ZIP files but has only been tested for Zip files + // If a SFX file has the Zip data attached as a resource and there are other resources occuring later then + // this could be invalid. + // Could also speed this up by reading memory in larger blocks. + + if (baseStream_.CanSeek == false) { + throw new ZipException("ZipFile stream must be seekable"); + } + + long locatedEndOfCentralDir = LocateBlockWithSignature(ZipConstants.EndOfCentralDirectorySignature, + baseStream_.Length, ZipConstants.EndOfCentralRecordBaseSize, 0xffff); + + if (locatedEndOfCentralDir < 0) { + throw new ZipException("Cannot find central directory"); + } + + // Read end of central directory record + ushort thisDiskNumber = ReadLEUshort(); + ushort startCentralDirDisk = ReadLEUshort(); + ulong entriesForThisDisk = ReadLEUshort(); + ulong entriesForWholeCentralDir = ReadLEUshort(); + ulong centralDirSize = ReadLEUint(); + long offsetOfCentralDir = ReadLEUint(); + uint commentSize = ReadLEUshort(); + + if ( commentSize > 0 ) { + byte[] comment = new byte[commentSize]; + + StreamUtils.ReadFully(baseStream_, comment); + comment_ = ZipConstants.ConvertToString(comment); + } + else { + comment_ = string.Empty; + } + + bool isZip64 = false; + + // Check if zip64 header information is required. + if ( (thisDiskNumber == 0xffff) || + (startCentralDirDisk == 0xffff) || + (entriesForThisDisk == 0xffff) || + (entriesForWholeCentralDir == 0xffff) || + (centralDirSize == 0xffffffff) || + (offsetOfCentralDir == 0xffffffff) ) { + isZip64 = true; + + long offset = LocateBlockWithSignature(ZipConstants.Zip64CentralDirLocatorSignature, locatedEndOfCentralDir, 0, 0x1000); + if ( offset < 0 ) { + throw new ZipException("Cannot find Zip64 locator"); + } + + // number of the disk with the start of the zip64 end of central directory 4 bytes + // relative offset of the zip64 end of central directory record 8 bytes + // total number of disks 4 bytes + ReadLEUint(); // startDisk64 is not currently used + ulong offset64 = ReadLEUlong(); + uint totalDisks = ReadLEUint(); + + baseStream_.Position = (long)offset64; + long sig64 = ReadLEUint(); + + if ( sig64 != ZipConstants.Zip64CentralFileHeaderSignature ) { + throw new ZipException(string.Format("Invalid Zip64 Central directory signature at {0:X}", offset64)); + } + + // NOTE: Record size = SizeOfFixedFields + SizeOfVariableData - 12. + ulong recordSize = ReadLEUlong(); + int versionMadeBy = ReadLEUshort(); + int versionToExtract = ReadLEUshort(); + uint thisDisk = ReadLEUint(); + uint centralDirDisk = ReadLEUint(); + entriesForThisDisk = ReadLEUlong(); + entriesForWholeCentralDir = ReadLEUlong(); + centralDirSize = ReadLEUlong(); + offsetOfCentralDir = (long)ReadLEUlong(); + + // NOTE: zip64 extensible data sector (variable size) is ignored. + } + + entries_ = new ZipEntry[entriesForThisDisk]; + + // SFX/embedded support, find the offset of the first entry vis the start of the stream + // This applies to Zip files that are appended to the end of an SFX stub. + // Or are appended as a resource to an executable. + // Zip files created by some archivers have the offsets altered to reflect the true offsets + // and so dont require any adjustment here... + // TODO: Difficulty with Zip64 and SFX offset handling needs resolution - maths? + if ( !isZip64 && (offsetOfCentralDir < locatedEndOfCentralDir - (4 + (long)centralDirSize)) ) { + offsetOfFirstEntry = locatedEndOfCentralDir - (4 + (long)centralDirSize + offsetOfCentralDir); + if (offsetOfFirstEntry <= 0) { + throw new ZipException("Invalid embedded zip archive"); + } + } + + baseStream_.Seek(offsetOfFirstEntry + offsetOfCentralDir, SeekOrigin.Begin); + + for (ulong i = 0; i < entriesForThisDisk; i++) { + if (ReadLEUint() != ZipConstants.CentralHeaderSignature) { + throw new ZipException("Wrong Central Directory signature"); + } + + int versionMadeBy = ReadLEUshort(); + int versionToExtract = ReadLEUshort(); + int bitFlags = ReadLEUshort(); + int method = ReadLEUshort(); + uint dostime = ReadLEUint(); + uint crc = ReadLEUint(); + long csize = (long)ReadLEUint(); + long size = (long)ReadLEUint(); + int nameLen = ReadLEUshort(); + int extraLen = ReadLEUshort(); + int commentLen = ReadLEUshort(); + + int diskStartNo = ReadLEUshort(); // Not currently used + int internalAttributes = ReadLEUshort(); // Not currently used + + uint externalAttributes = ReadLEUint(); + long offset = ReadLEUint(); + + byte[] buffer = new byte[Math.Max(nameLen, commentLen)]; + + StreamUtils.ReadFully(baseStream_, buffer, 0, nameLen); + string name = ZipConstants.ConvertToStringExt(bitFlags, buffer, nameLen); + + ZipEntry entry = new ZipEntry(name, versionToExtract, versionMadeBy, (CompressionMethod)method); + entry.Crc = crc & 0xffffffffL; + entry.Size = size & 0xffffffffL; + entry.CompressedSize = csize & 0xffffffffL; + entry.Flags = bitFlags; + entry.DosTime = (uint)dostime; + entry.ZipFileIndex = (long)i; + entry.Offset = offset; + entry.ExternalFileAttributes = (int)externalAttributes; + + if ((bitFlags & 8) == 0) { + entry.CryptoCheckValue = (byte)(crc >> 24); + } + else { + entry.CryptoCheckValue = (byte)((dostime >> 8) & 0xff); + } + + if (extraLen > 0) { + byte[] extra = new byte[extraLen]; + StreamUtils.ReadFully(baseStream_, extra); + entry.ExtraData = extra; + } + + entry.ProcessExtraData(false); + + if (commentLen > 0) { + StreamUtils.ReadFully(baseStream_, buffer, 0, commentLen); + entry.Comment = ZipConstants.ConvertToStringExt(bitFlags, buffer, commentLen); + } + + entries_[i] = entry; + } + } + + /// + /// Locate the data for a given entry. + /// + /// + /// The start offset of the data. + /// + /// + /// The stream ends prematurely + /// + /// + /// The local header signature is invalid, the entry and central header file name lengths are different + /// or the local and entry compression methods dont match + /// + long LocateEntry(ZipEntry entry) + { + return TestLocalHeader(entry, HeaderTest.Extract); + } + +#if !NETCF_1_0 + Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) + { + CryptoStream result = null; + + if ( (entry.Version < ZipConstants.VersionStrongEncryption) + || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { + PkzipClassicManaged classicManaged = new PkzipClassicManaged(); + + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for encrypted stream"); + } + + result = new CryptoStream(baseStream, classicManaged.CreateDecryptor(key, null), CryptoStreamMode.Read); + CheckClassicPassword(result, entry); + } + else { +#if !NET_1_1 && !NETCF_2_0 + if (entry.Version == ZipConstants.VERSION_AES) { + // + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for AES encrypted stream"); + } + int saltLen = entry.AESSaltLen; + byte[] saltBytes = new byte[saltLen]; + int saltIn = baseStream.Read(saltBytes, 0, saltLen); + if (saltIn != saltLen) + throw new ZipException("AES Salt expected " + saltLen + " got " + saltIn); + // + byte[] pwdVerifyRead = new byte[2]; + baseStream.Read(pwdVerifyRead, 0, 2); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + ZipAESTransform decryptor = new ZipAESTransform(rawPassword_, saltBytes, blockSize, false); + byte[] pwdVerifyCalc = decryptor.PwdVerifier; + if (pwdVerifyCalc[0] != pwdVerifyRead[0] || pwdVerifyCalc[1] != pwdVerifyRead[1]) + throw new Exception("Invalid password for AES"); + result = new ZipAESStream(baseStream, decryptor, CryptoStreamMode.Read); + } + else +#endif + { + throw new ZipException("Decryption method not supported"); + } + } + + return result; + } + + Stream CreateAndInitEncryptionStream(Stream baseStream, ZipEntry entry) + { + CryptoStream result = null; + if ( (entry.Version < ZipConstants.VersionStrongEncryption) + || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { + PkzipClassicManaged classicManaged = new PkzipClassicManaged(); + + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for encrypted stream"); + } + + // Closing a CryptoStream will close the base stream as well so wrap it in an UncompressedStream + // which doesnt do this. + result = new CryptoStream(new UncompressedStream(baseStream), + classicManaged.CreateEncryptor(key, null), CryptoStreamMode.Write); + + if ( (entry.Crc < 0) || (entry.Flags & 8) != 0) { + WriteEncryptionHeader(result, entry.DosTime << 16); + } + else { + WriteEncryptionHeader(result, entry.Crc); + } + } + return result; + } + + static void CheckClassicPassword(CryptoStream classicCryptoStream, ZipEntry entry) + { + byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize]; + StreamUtils.ReadFully(classicCryptoStream, cryptbuffer); + if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue) { + throw new ZipException("Invalid password"); + } + } +#endif + + static void WriteEncryptionHeader(Stream stream, long crcValue) + { + byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize]; + Random rnd = new Random(); + rnd.NextBytes(cryptBuffer); + cryptBuffer[11] = (byte)(crcValue >> 24); + stream.Write(cryptBuffer, 0, cryptBuffer.Length); + } + + #endregion + + #region Instance Fields + bool isDisposed_; + string name_; + string comment_; + string rawPassword_; + Stream baseStream_; + bool isStreamOwner; + long offsetOfFirstEntry; + ZipEntry[] entries_; + byte[] key; + bool isNewArchive_; + + // Default is dynamic which is not backwards compatible and can cause problems + // with XP's built in compression which cant read Zip64 archives. + // However it does avoid the situation were a large file is added and cannot be completed correctly. + // Hint: Set always ZipEntry size before they are added to an archive and this setting isnt needed. + UseZip64 useZip64_ = UseZip64.Dynamic ; + + #region Zip Update Instance Fields + ArrayList updates_; + long updateCount_; // Count is managed manually as updates_ can contain nulls! + Hashtable updateIndex_; + IArchiveStorage archiveStorage_; + IDynamicDataSource updateDataSource_; + bool contentsEdited_; + int bufferSize_ = DefaultBufferSize; + byte[] copyBuffer_; + ZipString newComment_; + bool commentEdited_; + IEntryFactory updateEntryFactory_ = new ZipEntryFactory(); + #endregion + #endregion + + #region Support Classes + /// + /// Represents a string from a which is stored as an array of bytes. + /// + class ZipString + { + #region Constructors + /// + /// Initialise a with a string. + /// + /// The textual string form. + public ZipString(string comment) + { + comment_ = comment; + isSourceString_ = true; + } + + /// + /// Initialise a using a string in its binary 'raw' form. + /// + /// + public ZipString(byte[] rawString) + { + rawComment_ = rawString; + } + #endregion + + /// + /// Get a value indicating the original source of data for this instance. + /// True if the source was a string; false if the source was binary data. + /// + public bool IsSourceString + { + get { return isSourceString_; } + } + + /// + /// Get the length of the comment when represented as raw bytes. + /// + public int RawLength + { + get { + MakeBytesAvailable(); + return rawComment_.Length; + } + } + + /// + /// Get the comment in its 'raw' form as plain bytes. + /// + public byte[] RawComment + { + get { + MakeBytesAvailable(); + return (byte[])rawComment_.Clone(); + } + } + + /// + /// Reset the comment to its initial state. + /// + public void Reset() + { + if ( isSourceString_ ) { + rawComment_ = null; + } + else { + comment_ = null; + } + } + + void MakeTextAvailable() + { + if ( comment_ == null ) { + comment_ = ZipConstants.ConvertToString(rawComment_); + } + } + + void MakeBytesAvailable() + { + if ( rawComment_ == null ) { + rawComment_ = ZipConstants.ConvertToArray(comment_); + } + } + + /// + /// Implicit conversion of comment to a string. + /// + /// The to convert to a string. + /// The textual equivalent for the input value. + static public implicit operator string(ZipString zipString) + { + zipString.MakeTextAvailable(); + return zipString.comment_; + } + + #region Instance Fields + string comment_; + byte[] rawComment_; + bool isSourceString_; + #endregion + } + + /// + /// An enumerator for Zip entries + /// + class ZipEntryEnumerator : IEnumerator + { + #region Constructors + public ZipEntryEnumerator(ZipEntry[] entries) + { + array = entries; + } + + #endregion + #region IEnumerator Members + public object Current + { + get { + return array[index]; + } + } + + public void Reset() + { + index = -1; + } + + public bool MoveNext() + { + return (++index < array.Length); + } + #endregion + #region Instance Fields + ZipEntry[] array; + int index = -1; + #endregion + } + + /// + /// An is a stream that you can write uncompressed data + /// to and flush, but cannot read, seek or do anything else to. + /// + class UncompressedStream : Stream + { + #region Constructors + public UncompressedStream(Stream baseStream) + { + baseStream_ = baseStream; + } + + #endregion + + /// + /// Close this stream instance. + /// + public override void Close() + { + // Do nothing + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Write any buffered data to underlying storage. + /// + public override void Flush() + { + baseStream_.Flush(); + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + public override bool CanWrite + { + get { + return baseStream_.CanWrite; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek + { + get { + return false; + } + } + + /// + /// Get the length in bytes of the stream. + /// + public override long Length + { + get { + return 0; + } + } + + /// + /// Gets or sets the position within the current stream. + /// + public override long Position + { + get { + return baseStream_.Position; + } + + set + { + } + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + + /// + /// Sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// + /// The new position within the current stream. + /// + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. + public override long Seek(long offset, SeekOrigin origin) + { + return 0; + } + + /// + /// Sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. + public override void SetLength(long value) + { + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. + public override void Write(byte[] buffer, int offset, int count) + { + baseStream_.Write(buffer, offset, count); + } + + #region Instance Fields + Stream baseStream_; + #endregion + } + + /// + /// A is an + /// whose data is only a part or subsection of a file. + /// + class PartialInputStream : Stream + { + #region Constructors + /// + /// Initialise a new instance of the class. + /// + /// The containing the underlying stream to use for IO. + /// The start of the partial data. + /// The length of the partial data. + public PartialInputStream(ZipFile zipFile, long start, long length) + { + start_ = start; + length_ = length; + + // Although this is the only time the zipfile is used + // keeping a reference here prevents premature closure of + // this zip file and thus the baseStream_. + + // Code like this will cause apparently random failures depending + // on the size of the files and when garbage is collected. + // + // ZipFile z = new ZipFile (stream); + // Stream reader = z.GetInputStream(0); + // uses reader here.... + zipFile_ = zipFile; + baseStream_ = zipFile_.baseStream_; + readPos_ = start; + end_ = start + length; + } + #endregion + + /// + /// Read a byte from this stream. + /// + /// Returns the byte read or -1 on end of stream. + public override int ReadByte() + { + if (readPos_ >= end_) { + // -1 is the correct value at end of stream. + return -1; + } + + lock( baseStream_ ) { + baseStream_.Seek(readPos_++, SeekOrigin.Begin); + return baseStream_.ReadByte(); + } + } + + /// + /// Close this partial input stream. + /// + /// + /// The underlying stream is not closed. Close the parent ZipFile class to do that. + /// + public override void Close() + { + // Do nothing at all! + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. + public override int Read(byte[] buffer, int offset, int count) + { + lock(baseStream_) { + if (count > end_ - readPos_) { + count = (int) (end_ - readPos_); + if (count == 0) { + return 0; + } + } + + baseStream_.Seek(readPos_, SeekOrigin.Begin); + int readCount = baseStream_.Read(buffer, offset, count); + if (readCount > 0) { + readPos_ += readCount; + } + return readCount; + } + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + /// + /// When overridden in a derived class, sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + /// + /// When overridden in a derived class, sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// + /// The new position within the current stream. + /// + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. + public override long Seek(long offset, SeekOrigin origin) + { + long newPos = readPos_; + + switch ( origin ) + { + case SeekOrigin.Begin: + newPos = start_ + offset; + break; + + case SeekOrigin.Current: + newPos = readPos_ + offset; + break; + + case SeekOrigin.End: + newPos = end_ + offset; + break; + } + + if ( newPos < start_ ) { + throw new ArgumentException("Negative position is invalid"); + } + + if ( newPos >= end_ ) { + throw new IOException("Cannot seek past end"); + } + readPos_ = newPos; + return readPos_; + } + + /// + /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. + /// + /// An I/O error occurs. + public override void Flush() + { + // Nothing to do. + } + + /// + /// Gets or sets the position within the current stream. + /// + /// + /// The current position within the stream. + /// An I/O error occurs. + /// The stream does not support seeking. + /// Methods were called after the stream was closed. + public override long Position { + get { return readPos_ - start_; } + set { + long newPos = start_ + value; + + if ( newPos < start_ ) { + throw new ArgumentException("Negative position is invalid"); + } + + if ( newPos >= end_ ) { + throw new InvalidOperationException("Cannot seek past end"); + } + readPos_ = newPos; + } + } + + /// + /// Gets the length in bytes of the stream. + /// + /// + /// A long value representing the length of the stream in bytes. + /// A class derived from Stream does not support seeking. + /// Methods were called after the stream was closed. + public override long Length { + get { return length_; } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + /// false + /// true if the stream supports writing; otherwise, false. + public override bool CanWrite { + get { return false; } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + /// true + /// true if the stream supports seeking; otherwise, false. + public override bool CanSeek { + get { return true; } + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + /// true. + /// true if the stream supports reading; otherwise, false. + public override bool CanRead { + get { return true; } + } + +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + /// + /// Gets a value that determines whether the current stream can time out. + /// + /// + /// A value that determines whether the current stream can time out. + public override bool CanTimeout { + get { return baseStream_.CanTimeout; } + } +#endif + #region Instance Fields + ZipFile zipFile_; + Stream baseStream_; + long start_; + long length_; + long readPos_; + long end_; + #endregion + } + #endregion + } + + #endregion + + #region DataSources + /// + /// Provides a static way to obtain a source of data for an entry. + /// + public interface IStaticDataSource + { + /// + /// Get a source of data by creating a new stream. + /// + /// Returns a to use for compression input. + /// Ideally a new stream is created and opened to achieve this, to avoid locking problems. + Stream GetSource(); + } + + /// + /// Represents a source of data that can dynamically provide + /// multiple data sources based on the parameters passed. + /// + public interface IDynamicDataSource + { + /// + /// Get a data source. + /// + /// The to get a source for. + /// The name for data if known. + /// Returns a to use for compression input. + /// Ideally a new stream is created and opened to achieve this, to avoid locking problems. + Stream GetSource(ZipEntry entry, string name); + } + + /// + /// Default implementation of a for use with files stored on disk. + /// + public class StaticDiskDataSource : IStaticDataSource + { + /// + /// Initialise a new instnace of + /// + /// The name of the file to obtain data from. + public StaticDiskDataSource(string fileName) + { + fileName_ = fileName; + } + + #region IDataSource Members + + /// + /// Get a providing data. + /// + /// Returns a provising data. + public Stream GetSource() + { + return File.Open(fileName_, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + #endregion + #region Instance Fields + string fileName_; + #endregion + } + + + /// + /// Default implementation of for files stored on disk. + /// + public class DynamicDiskDataSource : IDynamicDataSource + { + /// + /// Initialise a default instance of . + /// + public DynamicDiskDataSource() + { + } + + #region IDataSource Members + /// + /// Get a providing data for an entry. + /// + /// The entry to provide data for. + /// The file name for data if known. + /// Returns a stream providing data; or null if not available + public Stream GetSource(ZipEntry entry, string name) + { + Stream result = null; + + if ( name != null ) { + result = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + return result; + } + + #endregion + } + + #endregion + + #region Archive Storage + /// + /// Defines facilities for data storage when updating Zip Archives. + /// + public interface IArchiveStorage + { + /// + /// Get the to apply during updates. + /// + FileUpdateMode UpdateMode { get; } + + /// + /// Get an empty that can be used for temporary output. + /// + /// Returns a temporary output + /// + Stream GetTemporaryOutput(); + + /// + /// Convert a temporary output stream to a final stream. + /// + /// The resulting final + /// + Stream ConvertTemporaryToFinal(); + + /// + /// Make a temporary copy of the original stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + Stream MakeTemporaryCopy(Stream stream); + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The current stream. + /// Returns a stream suitable for direct updating. + /// This may be the current stream passed. + Stream OpenForDirectUpdate(Stream stream); + + /// + /// Dispose of this instance. + /// + void Dispose(); + } + + /// + /// An abstract suitable for extension by inheritance. + /// + abstract public class BaseArchiveStorage : IArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The update mode. + protected BaseArchiveStorage(FileUpdateMode updateMode) + { + updateMode_ = updateMode; + } + #endregion + + #region IArchiveStorage Members + + /// + /// Gets a temporary output + /// + /// Returns the temporary output stream. + /// + public abstract Stream GetTemporaryOutput(); + + /// + /// Converts the temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + /// + public abstract Stream ConvertTemporaryToFinal(); + + /// + /// Make a temporary copy of a . + /// + /// The to make a copy of. + /// Returns a temporary output that is a copy of the input. + public abstract Stream MakeTemporaryCopy(Stream stream); + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The to open for direct update. + /// Returns a stream suitable for direct updating. + public abstract Stream OpenForDirectUpdate(Stream stream); + + /// + /// Disposes this instance. + /// + public abstract void Dispose(); + + /// + /// Gets the update mode applicable. + /// + /// The update mode. + public FileUpdateMode UpdateMode + { + get { + return updateMode_; + } + } + + #endregion + + #region Instance Fields + FileUpdateMode updateMode_; + #endregion + } + + /// + /// An implementation suitable for hard disks. + /// + public class DiskArchiveStorage : BaseArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The file. + /// The update mode. + public DiskArchiveStorage(ZipFile file, FileUpdateMode updateMode) + : base(updateMode) + { + if ( file.Name == null ) { + throw new ZipException("Cant handle non file archives"); + } + + fileName_ = file.Name; + } + + /// + /// Initializes a new instance of the class. + /// + /// The file. + public DiskArchiveStorage(ZipFile file) + : this(file, FileUpdateMode.Safe) + { + } + #endregion + + #region IArchiveStorage Members + + /// + /// Gets a temporary output for performing updates on. + /// + /// Returns the temporary output stream. + public override Stream GetTemporaryOutput() + { + if ( temporaryName_ != null ) { + temporaryName_ = GetTempFileName(temporaryName_, true); + temporaryStream_ = File.Open(temporaryName_, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + else { + // Determine where to place files based on internal strategy. + // Currently this is always done in system temp directory. + temporaryName_ = Path.GetTempFileName(); + temporaryStream_ = File.Open(temporaryName_, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + + return temporaryStream_; + } + + /// + /// Converts a temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + public override Stream ConvertTemporaryToFinal() + { + if ( temporaryStream_ == null ) { + throw new ZipException("No temporary stream has been created"); + } + + Stream result = null; + + string moveTempName = GetTempFileName(fileName_, false); + bool newFileCreated = false; + + try { + temporaryStream_.Close(); + File.Move(fileName_, moveTempName); + File.Move(temporaryName_, fileName_); + newFileCreated = true; + File.Delete(moveTempName); + + result = File.Open(fileName_, FileMode.Open, FileAccess.Read, FileShare.Read); + } + catch(Exception) { + result = null; + + // Try to roll back changes... + if ( !newFileCreated ) { + File.Move(moveTempName, fileName_); + File.Delete(temporaryName_); + } + + throw; + } + + return result; + } + + /// + /// Make a temporary copy of a stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + public override Stream MakeTemporaryCopy(Stream stream) + { + stream.Close(); + + temporaryName_ = GetTempFileName(fileName_, true); + File.Copy(fileName_, temporaryName_, true); + + temporaryStream_ = new FileStream(temporaryName_, + FileMode.Open, + FileAccess.ReadWrite); + return temporaryStream_; + } + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The current stream. + /// Returns a stream suitable for direct updating. + /// If the stream is not null this is used as is. + public override Stream OpenForDirectUpdate(Stream stream) + { + Stream result; + if ((stream == null) || !stream.CanWrite) + { + if (stream != null) { + stream.Close(); + } + + result = new FileStream(fileName_, + FileMode.Open, + FileAccess.ReadWrite); + } + else + { + result = stream; + } + + return result; + } + + /// + /// Disposes this instance. + /// + public override void Dispose() + { + if ( temporaryStream_ != null ) { + temporaryStream_.Close(); + } + } + + #endregion + + #region Internal routines + static string GetTempFileName(string original, bool makeTempFile) + { + string result = null; + + if ( original == null ) { + result = Path.GetTempFileName(); + } + else { + int counter = 0; + int suffixSeed = DateTime.Now.Second; + + while ( result == null ) { + counter += 1; + string newName = string.Format("{0}.{1}{2}.tmp", original, suffixSeed, counter); + if ( !File.Exists(newName) ) { + if ( makeTempFile) { + try { + // Try and create the file. + using ( FileStream stream = File.Create(newName) ) { + } + result = newName; + } + catch { + suffixSeed = DateTime.Now.Second; + } + } + else { + result = newName; + } + } + } + } + return result; + } + #endregion + + #region Instance Fields + Stream temporaryStream_; + string fileName_; + string temporaryName_; + #endregion + } + + /// + /// An implementation suitable for in memory streams. + /// + public class MemoryArchiveStorage : BaseArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + public MemoryArchiveStorage() + : base(FileUpdateMode.Direct) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The to use + /// This constructor is for testing as memory streams dont really require safe mode. + public MemoryArchiveStorage(FileUpdateMode updateMode) + : base(updateMode) + { + } + + #endregion + + #region Properties + /// + /// Get the stream returned by if this was in fact called. + /// + public MemoryStream FinalStream + { + get { return finalStream_; } + } + + #endregion + + #region IArchiveStorage Members + + /// + /// Gets the temporary output + /// + /// Returns the temporary output stream. + public override Stream GetTemporaryOutput() + { + temporaryStream_ = new MemoryStream(); + return temporaryStream_; + } + + /// + /// Converts the temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + public override Stream ConvertTemporaryToFinal() + { + if ( temporaryStream_ == null ) { + throw new ZipException("No temporary stream has been created"); + } + + finalStream_ = new MemoryStream(temporaryStream_.ToArray()); + return finalStream_; + } + + /// + /// Make a temporary copy of the original stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + public override Stream MakeTemporaryCopy(Stream stream) + { + temporaryStream_ = new MemoryStream(); + stream.Position = 0; + StreamUtils.Copy(stream, temporaryStream_, new byte[4096]); + return temporaryStream_; + } + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The original source stream + /// Returns a stream suitable for direct updating. + /// If the passed is not null this is used; + /// otherwise a new is returned. + public override Stream OpenForDirectUpdate(Stream stream) + { + Stream result; + if ((stream == null) || !stream.CanWrite) { + + result = new MemoryStream(); + + if (stream != null) { + stream.Position = 0; + StreamUtils.Copy(stream, result, new byte[4096]); + + stream.Close(); + } + } + else { + result = stream; + } + + return result; + } + + /// + /// Disposes this instance. + /// + public override void Dispose() + { + if ( temporaryStream_ != null ) { + temporaryStream_.Close(); + } + } + + #endregion + + #region Instance Fields + MemoryStream temporaryStream_; + MemoryStream finalStream_; + #endregion + } + + #endregion +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipHelperStream.cs b/类库/OnlineRepair/ZIP/Zip/ZipHelperStream.cs new file mode 100644 index 0000000..a2f905d --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipHelperStream.cs @@ -0,0 +1,623 @@ +// ZipHelperStream.cs +// +// Copyright 2006, 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Holds data pertinent to a data descriptor. + /// + public class DescriptorData + { + /// + /// Get /set the compressed size of data. + /// + public long CompressedSize + { + get { return compressedSize; } + set { compressedSize = value; } + } + + /// + /// Get / set the uncompressed size of data + /// + public long Size + { + get { return size; } + set { size = value; } + } + + /// + /// Get /set the crc value. + /// + public long Crc + { + get { return crc; } + set { crc = (value & 0xffffffff); } + } + + #region Instance Fields + long size; + long compressedSize; + long crc; + #endregion + } + + class EntryPatchData + { + public long SizePatchOffset + { + get { return sizePatchOffset_; } + set { sizePatchOffset_ = value; } + } + + public long CrcPatchOffset + { + get { return crcPatchOffset_; } + set { crcPatchOffset_ = value; } + } + + #region Instance Fields + long sizePatchOffset_; + long crcPatchOffset_; + #endregion + } + + /// + /// This class assists with writing/reading from Zip files. + /// + internal class ZipHelperStream : Stream + { + #region Constructors + /// + /// Initialise an instance of this class. + /// + /// The name of the file to open. + public ZipHelperStream(string name) + { + stream_ = new FileStream(name, FileMode.Open, FileAccess.ReadWrite); + isOwner_ = true; + } + + /// + /// Initialise a new instance of . + /// + /// The stream to use. + public ZipHelperStream(Stream stream) + { + stream_ = stream; + } + #endregion + + /// + /// Get / set a value indicating wether the the underlying stream is owned or not. + /// + /// If the stream is owned it is closed when this instance is closed. + public bool IsStreamOwner + { + get { return isOwner_; } + set { isOwner_ = value; } + } + + #region Base Stream Methods + public override bool CanRead + { + get { return stream_.CanRead; } + } + + public override bool CanSeek + { + get { return stream_.CanSeek; } + } + +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + public override bool CanTimeout + { + get { return stream_.CanTimeout; } + } +#endif + + public override long Length + { + get { return stream_.Length; } + } + + public override long Position + { + get { return stream_.Position; } + set { stream_.Position = value; } + } + + public override bool CanWrite + { + get { return stream_.CanWrite; } + } + + public override void Flush() + { + stream_.Flush(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + return stream_.Seek(offset, origin); + } + + public override void SetLength(long value) + { + stream_.SetLength(value); + } + + public override int Read(byte[] buffer, int offset, int count) + { + return stream_.Read(buffer, offset, count); + } + + public override void Write(byte[] buffer, int offset, int count) + { + stream_.Write(buffer, offset, count); + } + + /// + /// Close the stream. + /// + /// + /// The underlying stream is closed only if is true. + /// + override public void Close() + { + Stream toClose = stream_; + stream_ = null; + if (isOwner_ && (toClose != null)) + { + isOwner_ = false; + toClose.Close(); + } + } + #endregion + + // Write the local file header + // TODO: ZipHelperStream.WriteLocalHeader is not yet used and needs checking for ZipFile and ZipOuptutStream usage + void WriteLocalHeader(ZipEntry entry, EntryPatchData patchData) + { + CompressionMethod method = entry.CompressionMethod; + bool headerInfoAvailable = true; // How to get this? + bool patchEntryHeader = false; + + WriteLEInt(ZipConstants.LocalHeaderSignature); + + WriteLEShort(entry.Version); + WriteLEShort(entry.Flags); + WriteLEShort((byte)method); + WriteLEInt((int)entry.DosTime); + + if (headerInfoAvailable == true) { + WriteLEInt((int)entry.Crc); + if ( entry.LocalHeaderRequiresZip64 ) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + WriteLEInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize); + WriteLEInt((int)entry.Size); + } + } else { + if (patchData != null) { + patchData.CrcPatchOffset = stream_.Position; + } + WriteLEInt(0); // Crc + + if ( patchData != null ) { + patchData.SizePatchOffset = stream_.Position; + } + + // For local header both sizes appear in Zip64 Extended Information + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + WriteLEInt(0); // Compressed size + WriteLEInt(0); // Uncompressed size + } + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xFFFF) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if (entry.LocalHeaderRequiresZip64 && (headerInfoAvailable || patchEntryHeader)) { + ed.StartNewEntry(); + if (headerInfoAvailable) { + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + } + else { + ed.AddLeLong(-1); + ed.AddLeLong(-1); + } + ed.AddNewEntry(1); + + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cant find extra data"); + } + + if ( patchData != null ) { + patchData.SizePatchOffset = ed.CurrentReadIndex; + } + } + else { + ed.Delete(1); + } + + byte[] extra = ed.GetEntryData(); + + WriteLEShort(name.Length); + WriteLEShort(extra.Length); + + if ( name.Length > 0 ) { + stream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + patchData.SizePatchOffset += stream_.Position; + } + + if ( extra.Length > 0 ) { + stream_.Write(extra, 0, extra.Length); + } + } + + /// + /// Locates a block with the desired . + /// + /// The signature to find. + /// Location, marking the end of block. + /// Minimum size of the block. + /// The maximum variable data. + /// Eeturns the offset of the first byte after the signature; -1 if not found + public long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + { + long pos = endLocation - minimumBlockSize; + if ( pos < 0 ) { + return -1; + } + + long giveUpMarker = Math.Max(pos - maximumVariableData, 0); + + // TODO: This loop could be optimised for speed. + do { + if ( pos < giveUpMarker ) { + return -1; + } + Seek(pos--, SeekOrigin.Begin); + } while ( ReadLEInt() != signature ); + + return Position; + } + + /// + /// Write Zip64 end of central directory records (File header and locator). + /// + /// The number of entries in the central directory. + /// The size of entries in the central directory. + /// The offset of the dentral directory. + public void WriteZip64EndOfCentralDirectory(long noOfEntries, long sizeEntries, long centralDirOffset) + { + long centralSignatureOffset = stream_.Position; + WriteLEInt(ZipConstants.Zip64CentralFileHeaderSignature); + WriteLELong(44); // Size of this record (total size of remaining fields in header or full size - 12) + WriteLEShort(ZipConstants.VersionMadeBy); // Version made by + WriteLEShort(ZipConstants.VersionZip64); // Version to extract + WriteLEInt(0); // Number of this disk + WriteLEInt(0); // number of the disk with the start of the central directory + WriteLELong(noOfEntries); // No of entries on this disk + WriteLELong(noOfEntries); // Total No of entries in central directory + WriteLELong(sizeEntries); // Size of the central directory + WriteLELong(centralDirOffset); // offset of start of central directory + // zip64 extensible data sector not catered for here (variable size) + + // Write the Zip64 end of central directory locator + WriteLEInt(ZipConstants.Zip64CentralDirLocatorSignature); + + // no of the disk with the start of the zip64 end of central directory + WriteLEInt(0); + + // relative offset of the zip64 end of central directory record + WriteLELong(centralSignatureOffset); + + // total number of disks + WriteLEInt(1); + } + + /// + /// Write the required records to end the central directory. + /// + /// The number of entries in the directory. + /// The size of the entries in the directory. + /// The start of the central directory. + /// The archive comment. (This can be null). + public void WriteEndOfCentralDirectory(long noOfEntries, long sizeEntries, + long startOfCentralDirectory, byte[] comment) + { + + if ( (noOfEntries >= 0xffff) || + (startOfCentralDirectory >= 0xffffffff) || + (sizeEntries >= 0xffffffff) ) { + WriteZip64EndOfCentralDirectory(noOfEntries, sizeEntries, startOfCentralDirectory); + } + + WriteLEInt(ZipConstants.EndOfCentralDirectorySignature); + + // TODO: ZipFile Multi disk handling not done + WriteLEShort(0); // number of this disk + WriteLEShort(0); // no of disk with start of central dir + + + // Number of entries + if ( noOfEntries >= 0xffff ) { + WriteLEUshort(0xffff); // Zip64 marker + WriteLEUshort(0xffff); + } + else { + WriteLEShort(( short )noOfEntries); // entries in central dir for this disk + WriteLEShort(( short )noOfEntries); // total entries in central directory + } + + // Size of the central directory + if ( sizeEntries >= 0xffffffff ) { + WriteLEUint(0xffffffff); // Zip64 marker + } + else { + WriteLEInt(( int )sizeEntries); + } + + + // offset of start of central directory + if ( startOfCentralDirectory >= 0xffffffff ) { + WriteLEUint(0xffffffff); // Zip64 marker + } + else { + WriteLEInt(( int )startOfCentralDirectory); + } + + int commentLength = (comment != null) ? comment.Length : 0; + + if ( commentLength > 0xffff ) { + throw new ZipException(string.Format("Comment length({0}) is too long can only be 64K", commentLength)); + } + + WriteLEShort(commentLength); + + if ( commentLength > 0 ) { + Write(comment, 0, comment.Length); + } + } + + #region LE value reading/writing + /// + /// Read an unsigned short in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + public int ReadLEShort() + { + int byteValue1 = stream_.ReadByte(); + + if (byteValue1 < 0) { + throw new EndOfStreamException(); + } + + int byteValue2 = stream_.ReadByte(); + if (byteValue2 < 0) { + throw new EndOfStreamException(); + } + + return byteValue1 | (byteValue2 << 8); + } + + /// + /// Read an int in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + public int ReadLEInt() + { + return ReadLEShort() | (ReadLEShort() << 16); + } + + /// + /// Read a long in little endian byte order. + /// + /// The value read. + public long ReadLELong() + { + return (uint)ReadLEInt() | ((long)ReadLEInt() << 32); + } + + /// + /// Write an unsigned short in little endian byte order. + /// + /// The value to write. + public void WriteLEShort(int value) + { + stream_.WriteByte(( byte )(value & 0xff)); + stream_.WriteByte(( byte )((value >> 8) & 0xff)); + } + + /// + /// Write a ushort in little endian byte order. + /// + /// The value to write. + public void WriteLEUshort(ushort value) + { + stream_.WriteByte(( byte )(value & 0xff)); + stream_.WriteByte(( byte )(value >> 8)); + } + + /// + /// Write an int in little endian byte order. + /// + /// The value to write. + public void WriteLEInt(int value) + { + WriteLEShort(value); + WriteLEShort(value >> 16); + } + + /// + /// Write a uint in little endian byte order. + /// + /// The value to write. + public void WriteLEUint(uint value) + { + WriteLEUshort(( ushort )(value & 0xffff)); + WriteLEUshort(( ushort )(value >> 16)); + } + + /// + /// Write a long in little endian byte order. + /// + /// The value to write. + public void WriteLELong(long value) + { + WriteLEInt(( int )value); + WriteLEInt(( int )(value >> 32)); + } + + /// + /// Write a ulong in little endian byte order. + /// + /// The value to write. + public void WriteLEUlong(ulong value) + { + WriteLEUint(( uint )(value & 0xffffffff)); + WriteLEUint(( uint )(value >> 32)); + } + + #endregion + + /// + /// Write a data descriptor. + /// + /// The entry to write a descriptor for. + /// Returns the number of descriptor bytes written. + public int WriteDataDescriptor(ZipEntry entry) + { + if (entry == null) { + throw new ArgumentNullException("entry"); + } + + int result=0; + + // Add data descriptor if flagged as required + if ((entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) + { + // The signature is not PKZIP originally but is now described as optional + // in the PKZIP Appnote documenting trhe format. + WriteLEInt(ZipConstants.DataDescriptorSignature); + WriteLEInt(unchecked((int)(entry.Crc))); + + result+=8; + + if (entry.LocalHeaderRequiresZip64) + { + WriteLELong(entry.CompressedSize); + WriteLELong(entry.Size); + result+=16; + } + else + { + WriteLEInt((int)entry.CompressedSize); + WriteLEInt((int)entry.Size); + result+=8; + } + } + + return result; + } + + /// + /// Read data descriptor at the end of compressed data. + /// + /// if set to true [zip64]. + /// The data to fill in. + /// Returns the number of bytes read in the descriptor. + public void ReadDataDescriptor(bool zip64, DescriptorData data) + { + int intValue = ReadLEInt(); + + // In theory this may not be a descriptor according to PKZIP appnote. + // In practise its always there. + if (intValue != ZipConstants.DataDescriptorSignature) { + throw new ZipException("Data descriptor signature not found"); + } + + data.Crc = ReadLEInt(); + + if (zip64) { + data.CompressedSize = ReadLELong(); + data.Size = ReadLELong(); + } + else { + data.CompressedSize = ReadLEInt(); + data.Size = ReadLEInt(); + } + } + + #region Instance Fields + bool isOwner_; + Stream stream_; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipInputStream.cs b/类库/OnlineRepair/ZIP/Zip/ZipInputStream.cs new file mode 100644 index 0000000..b481ea1 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipInputStream.cs @@ -0,0 +1,675 @@ +// ZipInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2010-05-25 Z-1663 Fixed exception when testing local header compressed size of -1 + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +#if !NETCF_1_0 +using ICSharpCode.SharpZipLib.Encryption; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// This is an InflaterInputStream that reads the files baseInputStream an zip archive + /// one after another. It has a special method to get the zip entry of + /// the next file. The zip entry contains information about the file name + /// size, compressed size, Crc, etc. + /// It includes support for Stored and Deflated entries. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// + /// This sample shows how to read a zip file + /// + /// using System; + /// using System.Text; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using ( ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]))) { + /// + /// ZipEntry theEntry; + /// const int size = 2048; + /// byte[] data = new byte[2048]; + /// + /// while ((theEntry = s.GetNextEntry()) != null) { + /// if ( entry.IsFile ) { + /// Console.Write("Show contents (y/n) ?"); + /// if (Console.ReadLine() == "y") { + /// while (true) { + /// size = s.Read(data, 0, data.Length); + /// if (size > 0) { + /// Console.Write(new ASCIIEncoding().GetString(data, 0, size)); + /// } else { + /// break; + /// } + /// } + /// } + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipInputStream : InflaterInputStream + { + #region Instance Fields + + /// + /// Delegate for reading bytes from a stream. + /// + delegate int ReadDataHandler(byte[] b, int offset, int length); + + /// + /// The current reader this instance. + /// + ReadDataHandler internalReader; + + Crc32 crc = new Crc32(); + ZipEntry entry; + + long size; + int method; + int flags; + string password; + #endregion + + #region Constructors + /// + /// Creates a new Zip input stream, for reading a zip archive. + /// + /// The underlying providing data. + public ZipInputStream(Stream baseInputStream) + : base(baseInputStream, new Inflater(true)) + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + } + + /// + /// Creates a new Zip input stream, for reading a zip archive. + /// + /// The underlying providing data. + /// Size of the buffer. + public ZipInputStream( Stream baseInputStream, int bufferSize ) + : base(baseInputStream, new Inflater(true), bufferSize) + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + } + #endregion + + /// + /// Optional password used for encryption when non-null + /// + /// A password for all encrypted entries in this + public string Password + { + get { + return password; + } + set { + password = value; + } + } + + + /// + /// Gets a value indicating if there is a current entry and it can be decompressed + /// + /// + /// The entry can only be decompressed if the library supports the zip features required to extract it. + /// See the ZipEntry Version property for more details. + /// + public bool CanDecompressEntry { + get { + return (entry != null) && entry.CanDecompress; + } + } + + /// + /// Advances to the next entry in the archive + /// + /// + /// The next entry in the archive or null if there are no more entries. + /// + /// + /// If the previous entry is still open CloseEntry is called. + /// + /// + /// Input stream is closed + /// + /// + /// Password is not set, password is invalid, compression method is invalid, + /// version required to extract is not supported + /// + public ZipEntry GetNextEntry() + { + if (crc == null) { + throw new InvalidOperationException("Closed."); + } + + if (entry != null) { + CloseEntry(); + } + + int header = inputBuffer.ReadLeInt(); + + if (header == ZipConstants.CentralHeaderSignature || + header == ZipConstants.EndOfCentralDirectorySignature || + header == ZipConstants.CentralHeaderDigitalSignature || + header == ZipConstants.ArchiveExtraDataSignature || + header == ZipConstants.Zip64CentralFileHeaderSignature) { + // No more individual entries exist + Close(); + return null; + } + + // -jr- 07-Dec-2003 Ignore spanning temporary signatures if found + // Spanning signature is same as descriptor signature and is untested as yet. + if ( (header == ZipConstants.SpanningTempSignature) || (header == ZipConstants.SpanningSignature) ) { + header = inputBuffer.ReadLeInt(); + } + + if (header != ZipConstants.LocalHeaderSignature) { + throw new ZipException("Wrong Local header signature: 0x" + String.Format("{0:X}", header)); + } + + short versionRequiredToExtract = (short)inputBuffer.ReadLeShort(); + + flags = inputBuffer.ReadLeShort(); + method = inputBuffer.ReadLeShort(); + uint dostime = (uint)inputBuffer.ReadLeInt(); + int crc2 = inputBuffer.ReadLeInt(); + csize = inputBuffer.ReadLeInt(); + size = inputBuffer.ReadLeInt(); + int nameLen = inputBuffer.ReadLeShort(); + int extraLen = inputBuffer.ReadLeShort(); + + bool isCrypted = (flags & 1) == 1; + + byte[] buffer = new byte[nameLen]; + inputBuffer.ReadRawBuffer(buffer); + + string name = ZipConstants.ConvertToStringExt(flags, buffer); + + entry = new ZipEntry(name, versionRequiredToExtract); + entry.Flags = flags; + + entry.CompressionMethod = (CompressionMethod)method; + + if ((flags & 8) == 0) { + entry.Crc = crc2 & 0xFFFFFFFFL; + entry.Size = size & 0xFFFFFFFFL; + entry.CompressedSize = csize & 0xFFFFFFFFL; + + entry.CryptoCheckValue = (byte)((crc2 >> 24) & 0xff); + + } else { + + // This allows for GNU, WinZip and possibly other archives, the PKZIP spec + // says these values are zero under these circumstances. + if (crc2 != 0) { + entry.Crc = crc2 & 0xFFFFFFFFL; + } + + if (size != 0) { + entry.Size = size & 0xFFFFFFFFL; + } + + if (csize != 0) { + entry.CompressedSize = csize & 0xFFFFFFFFL; + } + + entry.CryptoCheckValue = (byte)((dostime >> 8) & 0xff); + } + + entry.DosTime = dostime; + + // If local header requires Zip64 is true then the extended header should contain + // both values. + + // Handle extra data if present. This can set/alter some fields of the entry. + if (extraLen > 0) { + byte[] extra = new byte[extraLen]; + inputBuffer.ReadRawBuffer(extra); + entry.ExtraData = extra; + } + + entry.ProcessExtraData(true); + if ( entry.CompressedSize >= 0 ) { + csize = entry.CompressedSize; + } + + if ( entry.Size >= 0 ) { + size = entry.Size; + } + + if (method == (int)CompressionMethod.Stored && (!isCrypted && csize != size || (isCrypted && csize - ZipConstants.CryptoHeaderSize != size))) { + throw new ZipException("Stored, but compressed != uncompressed"); + } + + // Determine how to handle reading of data if this is attempted. + if (entry.IsCompressionMethodSupported()) { + internalReader = new ReadDataHandler(InitialRead); + } else { + internalReader = new ReadDataHandler(ReadingNotSupported); + } + + return entry; + } + + /// + /// Read data descriptor at the end of compressed data. + /// + void ReadDataDescriptor() + { + if (inputBuffer.ReadLeInt() != ZipConstants.DataDescriptorSignature) { + throw new ZipException("Data descriptor signature not found"); + } + + entry.Crc = inputBuffer.ReadLeInt() & 0xFFFFFFFFL; + + if ( entry.LocalHeaderRequiresZip64 ) { + csize = inputBuffer.ReadLeLong(); + size = inputBuffer.ReadLeLong(); + } else { + csize = inputBuffer.ReadLeInt(); + size = inputBuffer.ReadLeInt(); + } + entry.CompressedSize = csize; + entry.Size = size; + } + + /// + /// Complete cleanup as the final part of closing. + /// + /// True if the crc value should be tested + void CompleteCloseEntry(bool testCrc) + { + StopDecrypting(); + + if ((flags & 8) != 0) { + ReadDataDescriptor(); + } + + size = 0; + + if ( testCrc && + ((crc.Value & 0xFFFFFFFFL) != entry.Crc) && (entry.Crc != -1)) { + throw new ZipException("CRC mismatch"); + } + + crc.Reset(); + + if (method == (int)CompressionMethod.Deflated) { + inf.Reset(); + } + entry = null; + } + + /// + /// Closes the current zip entry and moves to the next one. + /// + /// + /// The stream is closed + /// + /// + /// The Zip stream ends early + /// + public void CloseEntry() + { + if (crc == null) { + throw new InvalidOperationException("Closed"); + } + + if (entry == null) { + return; + } + + if (method == (int)CompressionMethod.Deflated) { + if ((flags & 8) != 0) { + // We don't know how much we must skip, read until end. + byte[] tmp = new byte[4096]; + + // Read will close this entry + while (Read(tmp, 0, tmp.Length) > 0) { + } + return; + } + + csize -= inf.TotalIn; + inputBuffer.Available += inf.RemainingInput; + } + + if ( (inputBuffer.Available > csize) && (csize >= 0) ) { + inputBuffer.Available = (int)((long)inputBuffer.Available - csize); + } else { + csize -= inputBuffer.Available; + inputBuffer.Available = 0; + while (csize != 0) { + long skipped = base.Skip(csize); + + if (skipped <= 0) { + throw new ZipException("Zip archive ends early."); + } + + csize -= skipped; + } + } + + CompleteCloseEntry(false); + } + + /// + /// Returns 1 if there is an entry available + /// Otherwise returns 0. + /// + public override int Available { + get { + return entry != null ? 1 : 0; + } + } + + /// + /// Returns the current size that can be read from the current entry if available + /// + /// Thrown if the entry size is not known. + /// Thrown if no entry is currently available. + public override long Length + { + get { + if ( entry != null ) { + if ( entry.Size >= 0 ) { + return entry.Size; + } else { + throw new ZipException("Length not available for the current entry"); + } + } + else { + throw new InvalidOperationException("No current entry"); + } + } + + } + + /// + /// Reads a byte from the current zip entry. + /// + /// + /// The byte or -1 if end of stream is reached. + /// + public override int ReadByte() + { + byte[] b = new byte[1]; + if (Read(b, 0, 1) <= 0) { + return -1; + } + return b[0] & 0xff; + } + + /// + /// Handle attempts to read by throwing an . + /// + /// The destination array to store data in. + /// The offset at which data read should be stored. + /// The maximum number of bytes to read. + /// Returns the number of bytes actually read. + int ReadingNotAvailable(byte[] destination, int offset, int count) + { + throw new InvalidOperationException("Unable to read from this stream"); + } + + /// + /// Handle attempts to read from this entry by throwing an exception + /// + int ReadingNotSupported(byte[] destination, int offset, int count) + { + throw new ZipException("The compression method for this entry is not supported"); + } + + /// + /// Perform the initial read on an entry which may include + /// reading encryption headers and setting up inflation. + /// + /// The destination to fill with data read. + /// The offset to start reading at. + /// The maximum number of bytes to read. + /// The actual number of bytes read. + int InitialRead(byte[] destination, int offset, int count) + { + if ( !CanDecompressEntry ) { + throw new ZipException("Library cannot extract this entry. Version required is (" + entry.Version.ToString() + ")"); + } + + // Handle encryption if required. + if (entry.IsCrypted) { +#if NETCF_1_0 + throw new ZipException("Encryption not supported for Compact Framework 1.0"); +#else + if (password == null) { + throw new ZipException("No password set."); + } + + // Generate and set crypto transform... + PkzipClassicManaged managed = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password)); + + inputBuffer.CryptoTransform = managed.CreateDecryptor(key, null); + + byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize]; + inputBuffer.ReadClearTextBuffer(cryptbuffer, 0, ZipConstants.CryptoHeaderSize); + + if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue) { + throw new ZipException("Invalid password"); + } + + if (csize >= ZipConstants.CryptoHeaderSize) { + csize -= ZipConstants.CryptoHeaderSize; + } + else if ( (entry.Flags & (int)GeneralBitFlags.Descriptor) == 0 ) { + throw new ZipException(string.Format("Entry compressed size {0} too small for encryption", csize)); + } +#endif + } else { +#if !NETCF_1_0 + inputBuffer.CryptoTransform = null; +#endif + } + + if ((csize > 0) || ((flags & (int)GeneralBitFlags.Descriptor) != 0)) { + if ((method == (int)CompressionMethod.Deflated) && (inputBuffer.Available > 0)) { + inputBuffer.SetInflaterInput(inf); + } + + internalReader = new ReadDataHandler(BodyRead); + return BodyRead(destination, offset, count); + } + else { + internalReader = new ReadDataHandler(ReadingNotAvailable); + return 0; + } + } + + /// + /// Read a block of bytes from the stream. + /// + /// The destination for the bytes. + /// The index to start storing data. + /// The number of bytes to attempt to read. + /// Returns the number of bytes read. + /// Zero bytes read means end of stream. + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (buffer.Length - offset) < count ) { + throw new ArgumentException("Invalid offset/count combination"); + } + + return internalReader(buffer, offset, count); + } + + /// + /// Reads a block of bytes from the current zip entry. + /// + /// + /// The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. + /// + /// + /// An i/o error occured. + /// + /// + /// The deflated stream is corrupted. + /// + /// + /// The stream is not open. + /// + int BodyRead(byte[] buffer, int offset, int count) + { + if ( crc == null ) { + throw new InvalidOperationException("Closed"); + } + + if ( (entry == null) || (count <= 0) ) { + return 0; + } + + if ( offset + count > buffer.Length ) { + throw new ArgumentException("Offset + count exceeds buffer size"); + } + + bool finished = false; + + switch (method) { + case (int)CompressionMethod.Deflated: + count = base.Read(buffer, offset, count); + if (count <= 0) { + if (!inf.IsFinished) { + throw new ZipException("Inflater not finished!"); + } + inputBuffer.Available = inf.RemainingInput; + + // A csize of -1 is from an unpatched local header + if ((flags & 8) == 0 && + (inf.TotalIn != csize && csize != 0xFFFFFFFF && csize != -1 || inf.TotalOut != size)) { + throw new ZipException("Size mismatch: " + csize + ";" + size + " <-> " + inf.TotalIn + ";" + inf.TotalOut); + } + inf.Reset(); + finished = true; + } + break; + + case (int)CompressionMethod.Stored: + if ( (count > csize) && (csize >= 0) ) { + count = (int)csize; + } + + if ( count > 0 ) { + count = inputBuffer.ReadClearTextBuffer(buffer, offset, count); + if (count > 0) { + csize -= count; + size -= count; + } + } + + if (csize == 0) { + finished = true; + } else { + if (count < 0) { + throw new ZipException("EOF in stored block"); + } + } + break; + } + + if (count > 0) { + crc.Update(buffer, offset, count); + } + + if (finished) { + CompleteCloseEntry(true); + } + + return count; + } + + /// + /// Closes the zip input stream + /// + public override void Close() + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + crc = null; + entry = null; + + base.Close(); + } + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipNameTransform.cs b/类库/OnlineRepair/ZIP/Zip/ZipNameTransform.cs new file mode 100644 index 0000000..9dc1176 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipNameTransform.cs @@ -0,0 +1,269 @@ +// ZipNameTransform.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +using System; +using System.IO; +using System.Text; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// ZipNameTransform transforms names as per the Zip file naming convention. + /// + /// The use of absolute names is supported although its use is not valid + /// according to Zip naming conventions, and should not be used if maximum compatability is desired. + public class ZipNameTransform : INameTransform + { + #region Constructors + /// + /// Initialize a new instance of + /// + public ZipNameTransform() + { + } + + /// + /// Initialize a new instance of + /// + /// The string to trim from the front of paths if found. + public ZipNameTransform(string trimPrefix) + { + TrimPrefix = trimPrefix; + } + #endregion + + /// + /// Static constructor. + /// + static ZipNameTransform() + { + char[] invalidPathChars; +#if NET_1_0 || NET_1_1 || NETCF_1_0 + invalidPathChars = Path.InvalidPathChars; +#else + invalidPathChars = Path.GetInvalidPathChars(); +#endif + int howMany = invalidPathChars.Length + 2; + + InvalidEntryCharsRelaxed = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryCharsRelaxed, 0, invalidPathChars.Length); + InvalidEntryCharsRelaxed[howMany - 1] = '*'; + InvalidEntryCharsRelaxed[howMany - 2] = '?'; + + howMany = invalidPathChars.Length + 4; + InvalidEntryChars = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length); + InvalidEntryChars[howMany - 1] = ':'; + InvalidEntryChars[howMany - 2] = '\\'; + InvalidEntryChars[howMany - 3] = '*'; + InvalidEntryChars[howMany - 4] = '?'; + } + + /// + /// Transform a windows directory name according to the Zip file naming conventions. + /// + /// The directory name to transform. + /// The transformed name. + public string TransformDirectory(string name) + { + name = TransformFile(name); + if (name.Length > 0) { + if ( !name.EndsWith("/") ) { + name += "/"; + } + } + else { + throw new ZipException("Cannot have an empty directory name"); + } + return name; + } + + /// + /// Transform a windows file name according to the Zip file naming conventions. + /// + /// The file name to transform. + /// The transformed name. + public string TransformFile(string name) + { + if (name != null) { + string lowerName = name.ToLower(); + if ( (trimPrefix_ != null) && (lowerName.IndexOf(trimPrefix_) == 0) ) { + name = name.Substring(trimPrefix_.Length); + } + + name = name.Replace(@"\", "/"); + name = WindowsPathUtils.DropPathRoot(name); + + // Drop any leading slashes. + while ((name.Length > 0) && (name[0] == '/')) + { + name = name.Remove(0, 1); + } + + // Drop any trailing slashes. + while ((name.Length > 0) && (name[name.Length - 1] == '/')) + { + name = name.Remove(name.Length - 1, 1); + } + + // Convert consecutive // characters to / + int index = name.IndexOf("//"); + while (index >= 0) + { + name = name.Remove(index, 1); + index = name.IndexOf("//"); + } + + name = MakeValidName(name, '_'); + } + else { + name = string.Empty; + } + return name; + } + + /// + /// Get/set the path prefix to be trimmed from paths if present. + /// + /// The prefix is trimmed before any conversion from + /// a windows path is done. + public string TrimPrefix + { + get { return trimPrefix_; } + set { + trimPrefix_ = value; + if (trimPrefix_ != null) { + trimPrefix_ = trimPrefix_.ToLower(); + } + } + } + + /// + /// Force a name to be valid by replacing invalid characters with a fixed value + /// + /// The name to force valid + /// The replacement character to use. + /// Returns a valid name + static string MakeValidName(string name, char replacement) + { + int index = name.IndexOfAny(InvalidEntryChars); + if (index >= 0) { + StringBuilder builder = new StringBuilder(name); + + while (index >= 0 ) { + builder[index] = replacement; + + if (index >= name.Length) { + index = -1; + } + else { + index = name.IndexOfAny(InvalidEntryChars, index + 1); + } + } + name = builder.ToString(); + } + + if (name.Length > 0xffff) { + throw new PathTooLongException(); + } + + return name; + } + + /// + /// Test a name to see if it is a valid name for a zip entry. + /// + /// The name to test. + /// If true checking is relaxed about windows file names and absolute paths. + /// Returns true if the name is a valid zip name; false otherwise. + /// Zip path names are actually in Unix format, and should only contain relative paths. + /// This means that any path stored should not contain a drive or + /// device letter, or a leading slash. All slashes should forward slashes '/'. + /// An empty name is valid for a file where the input comes from standard input. + /// A null name is not considered valid. + /// + public static bool IsValidName(string name, bool relaxed) + { + bool result = (name != null); + + if ( result ) { + if ( relaxed ) { + result = name.IndexOfAny(InvalidEntryCharsRelaxed) < 0; + } + else { + result = + (name.IndexOfAny(InvalidEntryChars) < 0) && + (name.IndexOf('/') != 0); + } + } + + return result; + } + + /// + /// Test a name to see if it is a valid name for a zip entry. + /// + /// The name to test. + /// Returns true if the name is a valid zip name; false otherwise. + /// Zip path names are actually in unix format, + /// and should only contain relative paths if a path is present. + /// This means that the path stored should not contain a drive or + /// device letter, or a leading slash. All slashes should forward slashes '/'. + /// An empty name is valid where the input comes from standard input. + /// A null name is not considered valid. + /// + public static bool IsValidName(string name) + { + bool result = + (name != null) && + (name.IndexOfAny(InvalidEntryChars) < 0) && + (name.IndexOf('/') != 0) + ; + return result; + } + + #region Instance Fields + string trimPrefix_; + #endregion + + #region Class Fields + static readonly char[] InvalidEntryChars; + static readonly char[] InvalidEntryCharsRelaxed; + #endregion + } +} diff --git a/类库/OnlineRepair/ZIP/Zip/ZipOutputStream.cs b/类库/OnlineRepair/ZIP/Zip/ZipOutputStream.cs new file mode 100644 index 0000000..eae4171 --- /dev/null +++ b/类库/OnlineRepair/ZIP/Zip/ZipOutputStream.cs @@ -0,0 +1,900 @@ +// ZipOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 Z-1649 Added AES support +// 22-02-2010 Z-1648 Zero byte entries would create invalid zip files + +using System; +using System.IO; +using System.Collections; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// This is a DeflaterOutputStream that writes the files into a zip + /// archive one after another. It has a special method to start a new + /// zip entry. The zip entries contains information about the file name + /// size, compressed size, CRC, etc. + /// + /// It includes support for Stored and Deflated entries. + /// This class is not thread safe. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// This sample shows how to create a zip file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// string[] filenames = Directory.GetFiles(args[0]); + /// byte[] buffer = new byte[4096]; + /// + /// using ( ZipOutputStream s = new ZipOutputStream(File.Create(args[1])) ) { + /// + /// s.SetLevel(9); // 0 - store only to 9 - means best compression + /// + /// foreach (string file in filenames) { + /// ZipEntry entry = new ZipEntry(file); + /// s.PutNextEntry(entry); + /// + /// using (FileStream fs = File.OpenRead(file)) { + /// StreamUtils.Copy(fs, s, buffer); + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipOutputStream : DeflaterOutputStream + { + #region Constructors + /// + /// Creates a new Zip output stream, writing a zip archive. + /// + /// + /// The output stream to which the archive contents are written. + /// + public ZipOutputStream(Stream baseOutputStream) + : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true)) + { + } + + /// + /// Creates a new Zip output stream, writing a zip archive. + /// + /// The output stream to which the archive contents are written. + /// Size of the buffer to use. + public ZipOutputStream( Stream baseOutputStream, int bufferSize ) + : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), bufferSize) + { + } + #endregion + + /// + /// Gets a flag value of true if the central header has been added for this archive; false if it has not been added. + /// + /// No further entries can be added once this has been done. + public bool IsFinished + { + get { + return entries == null; + } + } + + /// + /// Set the zip file comment. + /// + /// + /// The comment text for the entire archive. + /// + /// + /// The converted comment is longer than 0xffff bytes. + /// + public void SetComment(string comment) + { + // TODO: Its not yet clear how to handle unicode comments here. + byte[] commentBytes = ZipConstants.ConvertToArray(comment); + if (commentBytes.Length > 0xffff) { + throw new ArgumentOutOfRangeException("comment"); + } + zipComment = commentBytes; + } + + /// + /// Sets the compression level. The new level will be activated + /// immediately. + /// + /// The new compression level (1 to 9). + /// + /// Level specified is not supported. + /// + /// + public void SetLevel(int level) + { + deflater_.SetLevel(level); + defaultCompressionLevel = level; + } + + /// + /// Get the current deflater compression level + /// + /// The current compression level + public int GetLevel() + { + return deflater_.GetLevel(); + } + + /// + /// Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + /// + /// Older archivers may not understand Zip64 extensions. + /// If backwards compatability is an issue be careful when adding entries to an archive. + /// Setting this property to off is workable but less desirable as in those circumstances adding a file + /// larger then 4GB will fail. + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + /// + /// Write an unsigned short in little endian byte order. + /// + private void WriteLeShort(int value) + { + unchecked { + baseOutputStream_.WriteByte((byte)(value & 0xff)); + baseOutputStream_.WriteByte((byte)((value >> 8) & 0xff)); + } + } + + /// + /// Write an int in little endian byte order. + /// + private void WriteLeInt(int value) + { + unchecked { + WriteLeShort(value); + WriteLeShort(value >> 16); + } + } + + /// + /// Write an int in little endian byte order. + /// + private void WriteLeLong(long value) + { + unchecked { + WriteLeInt((int)value); + WriteLeInt((int)(value >> 32)); + } + } + + /// + /// Starts a new Zip entry. It automatically closes the previous + /// entry if present. + /// All entry elements bar name are optional, but must be correct if present. + /// If the compression method is stored and the output is not patchable + /// the compression for that entry is automatically changed to deflate level 0 + /// + /// + /// the entry. + /// + /// + /// if entry passed is null. + /// + /// + /// if an I/O error occured. + /// + /// + /// if stream was finished + /// + /// + /// Too many entries in the Zip file
+ /// Entry name is too long
+ /// Finish has already been called
+ ///
+ public void PutNextEntry(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if (entries == null) { + throw new InvalidOperationException("ZipOutputStream was finished"); + } + + if (curEntry != null) { + CloseEntry(); + } + + if (entries.Count == int.MaxValue) { + throw new ZipException("Too many entries for Zip file"); + } + + CompressionMethod method = entry.CompressionMethod; + int compressionLevel = defaultCompressionLevel; + + // Clear flags that the library manages internally + entry.Flags &= (int)GeneralBitFlags.UnicodeText; + patchEntryHeader = false; + + bool headerInfoAvailable; + + // No need to compress - definitely no data. + if (entry.Size == 0) + { + entry.CompressedSize = entry.Size; + entry.Crc = 0; + method = CompressionMethod.Stored; + headerInfoAvailable = true; + } + else + { + headerInfoAvailable = (entry.Size >= 0) && entry.HasCrc; + + // Switch to deflation if storing isnt possible. + if (method == CompressionMethod.Stored) + { + if (!headerInfoAvailable) + { + if (!CanPatchEntries) + { + // Can't patch entries so storing is not possible. + method = CompressionMethod.Deflated; + compressionLevel = 0; + } + } + else // entry.size must be > 0 + { + entry.CompressedSize = entry.Size; + headerInfoAvailable = entry.HasCrc; + } + } + } + + if (headerInfoAvailable == false) { + if (CanPatchEntries == false) { + // Only way to record size and compressed size is to append a data descriptor + // after compressed data. + + // Stored entries of this form have already been converted to deflating. + entry.Flags |= 8; + } else { + patchEntryHeader = true; + } + } + + if (Password != null) { + entry.IsCrypted = true; + if (entry.Crc < 0) { + // Need to append a data descriptor as the crc isnt available for use + // with encryption, the date is used instead. Setting the flag + // indicates this to the decompressor. + entry.Flags |= 8; + } + } + + entry.Offset = offset; + entry.CompressionMethod = (CompressionMethod)method; + + curMethod = method; + sizePatchPos = -1; + + if ( (useZip64_ == UseZip64.On) || ((entry.Size < 0) && (useZip64_ == UseZip64.Dynamic)) ) { + entry.ForceZip64(); + } + + // Write the local file header + WriteLeInt(ZipConstants.LocalHeaderSignature); + + WriteLeShort(entry.Version); + WriteLeShort(entry.Flags); + WriteLeShort((byte)entry.CompressionMethodForHeader); + WriteLeInt((int)entry.DosTime); + + // TODO: Refactor header writing. Its done in several places. + if (headerInfoAvailable == true) { + WriteLeInt((int)entry.Crc); + if ( entry.LocalHeaderRequiresZip64 ) { + WriteLeInt(-1); + WriteLeInt(-1); + } + else { + WriteLeInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize); + WriteLeInt((int)entry.Size); + } + } else { + if (patchEntryHeader) { + crcPatchPos = baseOutputStream_.Position; + } + WriteLeInt(0); // Crc + + if ( patchEntryHeader ) { + sizePatchPos = baseOutputStream_.Position; + } + + // For local header both sizes appear in Zip64 Extended Information + if ( entry.LocalHeaderRequiresZip64 || patchEntryHeader ) { + WriteLeInt(-1); + WriteLeInt(-1); + } + else { + WriteLeInt(0); // Compressed size + WriteLeInt(0); // Uncompressed size + } + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xFFFF) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if (entry.LocalHeaderRequiresZip64) { + ed.StartNewEntry(); + if (headerInfoAvailable) { + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + } + else { + ed.AddLeLong(-1); + ed.AddLeLong(-1); + } + ed.AddNewEntry(1); + + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cant find extra data"); + } + + if ( patchEntryHeader ) { + sizePatchPos = ed.CurrentReadIndex; + } + } + else { + ed.Delete(1); + } + +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + AddExtraDataAES(entry, ed); + } +#endif + byte[] extra = ed.GetEntryData(); + + WriteLeShort(name.Length); + WriteLeShort(extra.Length); + + if ( name.Length > 0 ) { + baseOutputStream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + sizePatchPos += baseOutputStream_.Position; + } + + if ( extra.Length > 0 ) { + baseOutputStream_.Write(extra, 0, extra.Length); + } + + offset += ZipConstants.LocalHeaderBaseSize + name.Length + extra.Length; + // Fix offsetOfCentraldir for AES + if (entry.AESKeySize > 0) + offset += entry.AESOverheadSize; + + // Activate the entry. + curEntry = entry; + crc.Reset(); + if (method == CompressionMethod.Deflated) { + deflater_.Reset(); + deflater_.SetLevel(compressionLevel); + } + size = 0; + + if (entry.IsCrypted) { +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + WriteAESHeader(entry); + } else +#endif + { + if (entry.Crc < 0) { // so testing Zip will says its ok + WriteEncryptionHeader(entry.DosTime << 16); + } else { + WriteEncryptionHeader(entry.Crc); + } + } + } + } + + /// + /// Closes the current entry, updating header and footer information as required + /// + /// + /// An I/O error occurs. + /// + /// + /// No entry is active. + /// + public void CloseEntry() + { + if (curEntry == null) { + throw new InvalidOperationException("No open entry"); + } + + long csize = size; + + // First finish the deflater, if appropriate + if (curMethod == CompressionMethod.Deflated) { + if (size >= 0) { + base.Finish(); + csize = deflater_.TotalOut; + } + else { + deflater_.Reset(); + } + } + + // Write the AES Authentication Code (a hash of the compressed and encrypted data) + if (curEntry.AESKeySize > 0) { + baseOutputStream_.Write(AESAuthCode, 0, 10); + } + + if (curEntry.Size < 0) { + curEntry.Size = size; + } else if (curEntry.Size != size) { + throw new ZipException("size was " + size + ", but I expected " + curEntry.Size); + } + + if (curEntry.CompressedSize < 0) { + curEntry.CompressedSize = csize; + } else if (curEntry.CompressedSize != csize) { + throw new ZipException("compressed size was " + csize + ", but I expected " + curEntry.CompressedSize); + } + + if (curEntry.Crc < 0) { + curEntry.Crc = crc.Value; + } else if (curEntry.Crc != crc.Value) { + throw new ZipException("crc was " + crc.Value + ", but I expected " + curEntry.Crc); + } + + offset += csize; + + if (curEntry.IsCrypted) { + if (curEntry.AESKeySize > 0) { + curEntry.CompressedSize += curEntry.AESOverheadSize; + + } else { + curEntry.CompressedSize += ZipConstants.CryptoHeaderSize; + } + } + + // Patch the header if possible + if (patchEntryHeader) { + patchEntryHeader = false; + + long curPos = baseOutputStream_.Position; + baseOutputStream_.Seek(crcPatchPos, SeekOrigin.Begin); + WriteLeInt((int)curEntry.Crc); + + if ( curEntry.LocalHeaderRequiresZip64 ) { + + if ( sizePatchPos == -1 ) { + throw new ZipException("Entry requires zip64 but this has been turned off"); + } + + baseOutputStream_.Seek(sizePatchPos, SeekOrigin.Begin); + WriteLeLong(curEntry.Size); + WriteLeLong(curEntry.CompressedSize); + } + else { + WriteLeInt((int)curEntry.CompressedSize); + WriteLeInt((int)curEntry.Size); + } + baseOutputStream_.Seek(curPos, SeekOrigin.Begin); + } + + // Add data descriptor if flagged as required + if ((curEntry.Flags & 8) != 0) { + WriteLeInt(ZipConstants.DataDescriptorSignature); + WriteLeInt(unchecked((int)curEntry.Crc)); + + if ( curEntry.LocalHeaderRequiresZip64 ) { + WriteLeLong(curEntry.CompressedSize); + WriteLeLong(curEntry.Size); + offset += ZipConstants.Zip64DataDescriptorSize; + } + else { + WriteLeInt((int)curEntry.CompressedSize); + WriteLeInt((int)curEntry.Size); + offset += ZipConstants.DataDescriptorSize; + } + } + + entries.Add(curEntry); + curEntry = null; + } + + void WriteEncryptionHeader(long crcValue) + { + offset += ZipConstants.CryptoHeaderSize; + + InitializePassword(Password); + + byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize]; + Random rnd = new Random(); + rnd.NextBytes(cryptBuffer); + cryptBuffer[11] = (byte)(crcValue >> 24); + + EncryptBlock(cryptBuffer, 0, cryptBuffer.Length); + baseOutputStream_.Write(cryptBuffer, 0, cryptBuffer.Length); + } + +#if !NET_1_1 && !NETCF_2_0 + private static void AddExtraDataAES(ZipEntry entry, ZipExtraData extraData) { + + // Vendor Version: AE-1 IS 1. AE-2 is 2. With AE-2 no CRC is required and 0 is stored. + const int VENDOR_VERSION = 2; + // Vendor ID is the two ASCII characters "AE". + const int VENDOR_ID = 0x4541; //not 6965; + extraData.StartNewEntry(); + // Pack AES extra data field see http://www.winzip.com/aes_info.htm + //extraData.AddLeShort(7); // Data size (currently 7) + extraData.AddLeShort(VENDOR_VERSION); // 2 = AE-2 + extraData.AddLeShort(VENDOR_ID); // "AE" + extraData.AddData(entry.AESEncryptionStrength); // 1 = 128, 2 = 192, 3 = 256 + extraData.AddLeShort((int)entry.CompressionMethod); // The actual compression method used to compress the file + extraData.AddNewEntry(0x9901); + } + + // Replaces WriteEncryptionHeader for AES + // + private void WriteAESHeader(ZipEntry entry) { + byte[] salt; + byte[] pwdVerifier; + InitializeAESPassword(entry, Password, out salt, out pwdVerifier); + // File format for AES: + // Size (bytes) Content + // ------------ ------- + // Variable Salt value + // 2 Password verification value + // Variable Encrypted file data + // 10 Authentication code + // + // Value in the "compressed size" fields of the local file header and the central directory entry + // is the total size of all the items listed above. In other words, it is the total size of the + // salt value, password verification value, encrypted data, and authentication code. + baseOutputStream_.Write(salt, 0, salt.Length); + baseOutputStream_.Write(pwdVerifier, 0, pwdVerifier.Length); + } +#endif + + /// + /// Writes the given buffer to the current entry. + /// + /// The buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Archive size is invalid + /// No entry is active. + public override void Write(byte[] buffer, int offset, int count) + { + if (curEntry == null) { + throw new InvalidOperationException("No open entry."); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (buffer.Length - offset) < count ) { + throw new ArgumentException("Invalid offset/count combination"); + } + + crc.Update(buffer, offset, count); + size += count; + + switch (curMethod) { + case CompressionMethod.Deflated: + base.Write(buffer, offset, count); + break; + + case CompressionMethod.Stored: + if (Password != null) { + CopyAndEncrypt(buffer, offset, count); + } else { + baseOutputStream_.Write(buffer, offset, count); + } + break; + } + } + + void CopyAndEncrypt(byte[] buffer, int offset, int count) + { + const int CopyBufferSize = 4096; + byte[] localBuffer = new byte[CopyBufferSize]; + while ( count > 0 ) { + int bufferCount = (count < CopyBufferSize) ? count : CopyBufferSize; + + Array.Copy(buffer, offset, localBuffer, 0, bufferCount); + EncryptBlock(localBuffer, 0, bufferCount); + baseOutputStream_.Write(localBuffer, 0, bufferCount); + count -= bufferCount; + offset += bufferCount; + } + } + + /// + /// Finishes the stream. This will write the central directory at the + /// end of the zip file and flush the stream. + /// + /// + /// This is automatically called when the stream is closed. + /// + /// + /// An I/O error occurs. + /// + /// + /// Comment exceeds the maximum length
+ /// Entry name exceeds the maximum length + ///
+ public override void Finish() + { + if (entries == null) { + return; + } + + if (curEntry != null) { + CloseEntry(); + } + + long numEntries = entries.Count; + long sizeEntries = 0; + + foreach (ZipEntry entry in entries) { + WriteLeInt(ZipConstants.CentralHeaderSignature); + WriteLeShort(ZipConstants.VersionMadeBy); + WriteLeShort(entry.Version); + WriteLeShort(entry.Flags); + WriteLeShort((short)entry.CompressionMethodForHeader); + WriteLeInt((int)entry.DosTime); + WriteLeInt((int)entry.Crc); + + if ( entry.IsZip64Forced() || + (entry.CompressedSize >= uint.MaxValue) ) + { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.CompressedSize); + } + + if ( entry.IsZip64Forced() || + (entry.Size >= uint.MaxValue) ) + { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xffff) { + throw new ZipException("Name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.CentralHeaderRequiresZip64 ) { + ed.StartNewEntry(); + if ( entry.IsZip64Forced() || + (entry.Size >= 0xffffffff) ) + { + ed.AddLeLong(entry.Size); + } + + if ( entry.IsZip64Forced() || + (entry.CompressedSize >= 0xffffffff) ) + { + ed.AddLeLong(entry.CompressedSize); + } + + if ( entry.Offset >= 0xffffffff ) + { + ed.AddLeLong(entry.Offset); + } + + ed.AddNewEntry(1); + } + else { + ed.Delete(1); + } + +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + AddExtraDataAES(entry, ed); + } +#endif + byte[] extra = ed.GetEntryData(); + + byte[] entryComment = + (entry.Comment != null) ? + ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : + new byte[0]; + + if (entryComment.Length > 0xffff) { + throw new ZipException("Comment too long."); + } + + WriteLeShort(name.Length); + WriteLeShort(extra.Length); + WriteLeShort(entryComment.Length); + WriteLeShort(0); // disk number + WriteLeShort(0); // internal file attributes + // external file attributes + + if (entry.ExternalFileAttributes != -1) { + WriteLeInt(entry.ExternalFileAttributes); + } else { + if (entry.IsDirectory) { // mark entry as directory (from nikolam.AT.perfectinfo.com) + WriteLeInt(16); + } else { + WriteLeInt(0); + } + } + + if ( entry.Offset >= uint.MaxValue ) { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.Offset); + } + + if ( name.Length > 0 ) { + baseOutputStream_.Write(name, 0, name.Length); + } + + if ( extra.Length > 0 ) { + baseOutputStream_.Write(extra, 0, extra.Length); + } + + if ( entryComment.Length > 0 ) { + baseOutputStream_.Write(entryComment, 0, entryComment.Length); + } + + sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length; + } + + using ( ZipHelperStream zhs = new ZipHelperStream(baseOutputStream_) ) { + zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment); + } + + entries = null; + } + + #region Instance Fields + /// + /// The entries for the archive. + /// + ArrayList entries = new ArrayList(); + + /// + /// Used to track the crc of data added to entries. + /// + Crc32 crc = new Crc32(); + + /// + /// The current entry being added. + /// + ZipEntry curEntry; + + int defaultCompressionLevel = Deflater.DEFAULT_COMPRESSION; + + CompressionMethod curMethod = CompressionMethod.Deflated; + + /// + /// Used to track the size of data for an entry during writing. + /// + long size; + + /// + /// Offset to be recorded for each entry in the central header. + /// + long offset; + + /// + /// Comment for the entire archive recorded in central header. + /// + byte[] zipComment = new byte[0]; + + /// + /// Flag indicating that header patching is required for the current entry. + /// + bool patchEntryHeader; + + /// + /// Position to patch crc + /// + long crcPatchPos = -1; + + /// + /// Position to patch size. + /// + long sizePatchPos = -1; + + // Default is dynamic which is not backwards compatible and can cause problems + // with XP's built in compression which cant read Zip64 archives. + // However it does avoid the situation were a large file is added and cannot be completed correctly. + // NOTE: Setting the size for entries before they are added is the best solution! + UseZip64 useZip64_ = UseZip64.Dynamic; + #endregion + } +} diff --git a/类库/OnlineRepair/ZipArchive.cs b/类库/OnlineRepair/ZipArchive.cs new file mode 100644 index 0000000..f2cd8a0 --- /dev/null +++ b/类库/OnlineRepair/ZipArchive.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; + +using System.Reflection; +using System.Web; +using System.Windows.Forms; +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip; + + + +namespace OnlineRepair +{ + internal class ZipArchive + { + /// + /// 功能:解压zip格式的文件。 + /// + /// 压缩文件路径 + /// 解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 + /// 出错信息 + /// 解压是否成功 + public static void UnZip(string zipFilePath, string unZipDir) + { + try + { + if (zipFilePath == string.Empty) + { + throw new Exception("压缩文件不能为空!"); + } + if (!File.Exists(zipFilePath)) + { + throw new System.IO.FileNotFoundException("压缩文件不存在!"); + } + //解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 + if (unZipDir == string.Empty) + unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), + Path.GetFileNameWithoutExtension(zipFilePath)); + if (!unZipDir.EndsWith("/")) + unZipDir += "/"; + if (!Directory.Exists(unZipDir)) + Directory.CreateDirectory(unZipDir); + + using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath))) + { + + ZipEntry theEntry; + while ((theEntry = s.GetNextEntry()) != null) + { + string directoryName = Path.GetDirectoryName(theEntry.Name); + string fileName = Path.GetFileName(theEntry.Name); + if (directoryName.Length > 0) + { + Directory.CreateDirectory(unZipDir + directoryName); + } + if (!directoryName.EndsWith("/")) + directoryName += "/"; + if (fileName != String.Empty) + { + if (theEntry.Name == "OnlineUpdate.exe") continue; + using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name)) + { + + int size = 5048; + byte[] data = new byte[size]; + while (true) + { + size = s.Read(data, 0, data.Length); + if (size > 0) + { + streamWriter.Write(data, 0, size); + } + else + { + break; + } + } + } + } + } + } + } + catch (Exception ex) + { } + } + } +} \ No newline at end of file diff --git a/类库/OnlineRepair/repairing.ico b/类库/OnlineRepair/repairing.ico new file mode 100644 index 0000000..8dc7294 Binary files /dev/null and b/类库/OnlineRepair/repairing.ico differ diff --git a/类库/SqlSugar/5.0.0.9/Abstract/AdoProvider/AdoAccessory.cs b/类库/SqlSugar/5.0.0.9/Abstract/AdoProvider/AdoAccessory.cs new file mode 100644 index 0000000..634fd21 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/AdoProvider/AdoAccessory.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public partial class AdoAccessory + { + protected IDbBind _DbBind; + protected IDbFirst _DbFirst; + protected ICodeFirst _CodeFirst; + protected IDbMaintenance _DbMaintenance; + protected IDbConnection _DbConnection; + + protected virtual SugarParameter[] GetParameters(object parameters, PropertyInfo[] propertyInfo, string sqlParameterKeyWord) + { + List result = new List(); + if (parameters != null) + { + var entityType = parameters.GetType(); + var isDictionary = entityType.IsIn(UtilConstants.DicArraySO, UtilConstants.DicArraySS); + if (isDictionary) + DictionaryToParameters(parameters, sqlParameterKeyWord, result, entityType); + else if (parameters is List) + { + result = (parameters as List); + } + else if (parameters is SugarParameter[]) + { + result = (parameters as SugarParameter[]).ToList(); + } + else + { + Check.Exception(!entityType.IsAnonymousType(), "The parameter format is wrong. \nUse new{{xx=xx, xx2=xx2}} or \nDictionary or \nSugarParameter [] "); + ProperyToParameter(parameters, propertyInfo, sqlParameterKeyWord, result, entityType); + } + } + return result.ToArray(); + } + protected void ProperyToParameter(object parameters, PropertyInfo[] propertyInfo, string sqlParameterKeyWord, List listParams, Type entityType) + { + PropertyInfo[] properties = null; + if (propertyInfo != null) + properties = propertyInfo; + else + properties = entityType.GetProperties(); + + foreach (PropertyInfo properyty in properties) + { + var value = properyty.GetValue(parameters, null); + if (properyty.PropertyType.IsEnum()) + value = Convert.ToInt64(value); + if (value == null || value.Equals(DateTime.MinValue)) value = DBNull.Value; + if (properyty.Name.ToLower().Contains("hierarchyid")) + { + var parameter = new SugarParameter(sqlParameterKeyWord + properyty.Name, SqlDbType.Udt); + parameter.UdtTypeName = "HIERARCHYID"; + parameter.Value = value; + listParams.Add(parameter); + } + else + { + var parameter = new SugarParameter(sqlParameterKeyWord + properyty.Name, value); + listParams.Add(parameter); + } + } + } + protected void DictionaryToParameters(object parameters, string sqlParameterKeyWord, List listParams, Type entityType) + { + if (entityType == UtilConstants.DicArraySO) + { + var dictionaryParameters = (Dictionary)parameters; + var sugarParameters = dictionaryParameters.Select(it => new SugarParameter(sqlParameterKeyWord + it.Key, it.Value)); + listParams.AddRange(sugarParameters); + } + else + { + var dictionaryParameters = (Dictionary)parameters; + var sugarParameters = dictionaryParameters.Select(it => new SugarParameter(sqlParameterKeyWord + it.Key, it.Value)); + listParams.AddRange(sugarParameters); ; + } + } + } +} \ No newline at end of file diff --git a/类库/SqlSugar/5.0.0.9/Abstract/AdoProvider/AdoProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/AdoProvider/AdoProvider.cs new file mode 100644 index 0000000..2bedc5e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/AdoProvider/AdoProvider.cs @@ -0,0 +1,1453 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +namespace SqlSugar +{ + /// + /// ** description:ActiveX Data Objects + /// ** author:sunkaixuan + /// ** date:2017/1/2 + /// ** email:610262374@qq.com + /// + public abstract partial class AdoProvider : AdoAccessory, IAdo + { + #region Constructor + public AdoProvider() + { + this.IsEnableLogEvent = false; + this.CommandType = CommandType.Text; + this.IsClearParameters = true; + this.CommandTimeOut = 300; + } + #endregion + + #region Properties + protected List OutputParameters { get; set; } + public virtual string SqlParameterKeyWord { get { return "@"; } } + public IDbTransaction Transaction { get; set; } + public virtual SqlSugarProvider Context { get; set; } + internal CommandType OldCommandType { get; set; } + internal bool OldClearParameters { get; set; } + public IDataParameterCollection DataReaderParameters { get; set; } + public TimeSpan SqlExecutionTime { get { return AfterTime - BeforeTime; } } + public bool IsDisableMasterSlaveSeparation { get; set; } + internal DateTime BeforeTime = DateTime.MinValue; + internal DateTime AfterTime = DateTime.MinValue; + public virtual IDbBind DbBind + { + get + { + if (base._DbBind == null) + { + IDbBind bind = InstanceFactory.GetDbBind(this.Context.CurrentConnectionConfig); + base._DbBind = bind; + bind.Context = this.Context; + } + return base._DbBind; + } + } + public virtual int CommandTimeOut { get; set; } + public virtual CommandType CommandType { get; set; } + public virtual bool IsEnableLogEvent { get; set; } + public virtual bool IsClearParameters { get; set; } + public virtual Action LogEventStarting => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuting; + public virtual Action LogEventCompleted => this.Context.CurrentConnectionConfig.AopEvents?.OnLogExecuted; + public virtual Func> ProcessingEventStartingSQL => this.Context.CurrentConnectionConfig.AopEvents?.OnExecutingChangeSql; + protected virtual Func FormatSql { get; set; } + public virtual Action ErrorEvent => this.Context.CurrentConnectionConfig.AopEvents?.OnError; + public virtual Action DiffLogEvent => this.Context.CurrentConnectionConfig.AopEvents?.OnDiffLogEvent; + public virtual List SlaveConnections { get; set; } + public virtual IDbConnection MasterConnection { get; set; } + #endregion + + #region Connection + public virtual void Open() + { + CheckConnection(); + } + public virtual void Close() + { + if (this.Transaction != null) + { + this.Transaction = null; + } + if (this.Connection != null && this.Connection.State == ConnectionState.Open) + { + this.Connection.Close(); + } + if (this.IsMasterSlaveSeparation && this.SlaveConnections.HasValue()) + { + foreach (var slaveConnection in this.SlaveConnections) + { + if (slaveConnection != null && slaveConnection.State == ConnectionState.Open) + { + slaveConnection.Close(); + } + } + } + } + public virtual void Dispose() + { + if (this.Transaction != null) + { + this.Transaction.Commit(); + this.Transaction = null; + } + if (this.Connection != null && this.Connection.State != ConnectionState.Open) + { + this.Connection.Close(); + } + if (this.Connection != null) + { + this.Connection.Dispose(); + } + this.Connection = null; + + if (this.IsMasterSlaveSeparation) + { + if (this.SlaveConnections != null) + { + foreach (var slaveConnection in this.SlaveConnections) + { + if (slaveConnection != null && slaveConnection.State == ConnectionState.Open) + { + slaveConnection.Dispose(); + } + } + } + } + } + public virtual void CheckConnection() + { + if (this.Connection.State != ConnectionState.Open) + { + try + { + this.Connection.Open(); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + } + + #endregion + + #region Transaction + public virtual void BeginTran() + { + CheckConnection(); + if (this.Transaction == null) + this.Transaction = this.Connection.BeginTransaction(); + } + public virtual void BeginTran(IsolationLevel iso) + { + CheckConnection(); + if (this.Transaction == null) + this.Transaction = this.Connection.BeginTransaction(iso); + } + public virtual void RollbackTran() + { + if (this.Transaction != null) + { + this.Transaction.Rollback(); + this.Transaction = null; + if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) this.Close(); + } + } + public virtual void CommitTran() + { + if (this.Transaction != null) + { + this.Transaction.Commit(); + this.Transaction = null; + if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) this.Close(); + } + } + #endregion + + #region abstract + public abstract IDataParameter[] ToIDbDataParameter(params SugarParameter[] pars); + public abstract void SetCommandToAdapter(IDataAdapter adapter, DbCommand command); + public abstract IDataAdapter GetAdapter(); + public abstract DbCommand GetCommand(string sql, SugarParameter[] pars); + public abstract IDbConnection Connection { get; set; } + public abstract void BeginTran(string transactionName);//Only SqlServer + public abstract void BeginTran(IsolationLevel iso, string transactionName);//Only SqlServer + #endregion + + #region Use + public DbResult UseTran(Action action, Action errorCallBack = null) + { + var result = new DbResult(); + try + { + this.BeginTran(); + if (action != null) + action(); + this.CommitTran(); + result.Data = result.IsSuccess = true; + } + catch (Exception ex) + { + result.ErrorException = ex; + result.ErrorMessage = ex.Message; + result.IsSuccess = false; + this.RollbackTran(); + if (errorCallBack != null) + { + errorCallBack(ex); + } + } + return result; + } + + public Task> UseTranAsync(Action action, Action errorCallBack = null) + { + return Task.FromResult(UseTran(action, errorCallBack)); + } + + public DbResult UseTran(Func action, Action errorCallBack = null) + { + var result = new DbResult(); + try + { + this.BeginTran(); + if (action != null) + result.Data = action(); + this.CommitTran(); + result.IsSuccess = true; + } + catch (Exception ex) + { + result.ErrorException = ex; + result.ErrorMessage = ex.Message; + result.IsSuccess = false; + this.RollbackTran(); + if (errorCallBack != null) + { + errorCallBack(ex); + } + } + return result; + } + + public Task> UseTranAsync(Func action, Action errorCallBack = null) + { + return Task.FromResult(UseTran(action, errorCallBack)); + } + + public IAdo UseStoredProcedure() + { + this.OldCommandType = this.CommandType; + this.OldClearParameters = this.IsClearParameters; + this.CommandType = CommandType.StoredProcedure; + this.IsClearParameters = false; + return this; + } + #endregion + + #region Core + public virtual int ExecuteCommand(string sql, params SugarParameter[] parameters) + { + try + { + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + IDbCommand sqlCommand = GetCommand(sql, parameters); + int count = sqlCommand.ExecuteNonQuery(); + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + return count; + } + catch (Exception ex) + { + CommandType = CommandType.Text; + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + finally + { + if (this.IsAutoClose()) this.Close(); + SetConnectionEnd(sql); + } + } + public virtual IDataReader GetDataReader(string sql, params SugarParameter[] parameters) + { + try + { + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + var isSp = this.CommandType == CommandType.StoredProcedure; + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + IDbCommand sqlCommand = GetCommand(sql, parameters); + IDataReader sqlDataReader = sqlCommand.ExecuteReader(this.IsAutoClose() ? CommandBehavior.CloseConnection : CommandBehavior.Default); + if (isSp) + DataReaderParameters = sqlCommand.Parameters; + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + SetConnectionEnd(sql); + return sqlDataReader; + } + catch (Exception ex) + { + CommandType = CommandType.Text; + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + } + public virtual DataSet GetDataSetAll(string sql, params SugarParameter[] parameters) + { + try + { + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + IDataAdapter dataAdapter = this.GetAdapter(); + DbCommand sqlCommand = GetCommand(sql, parameters); + this.SetCommandToAdapter(dataAdapter, sqlCommand); + DataSet ds = new DataSet(); + dataAdapter.Fill(ds); + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + return ds; + } + catch (Exception ex) + { + CommandType = CommandType.Text; + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + finally + { + if (this.IsAutoClose()) this.Close(); + SetConnectionEnd(sql); + } + } + public virtual object GetScalar(string sql, params SugarParameter[] parameters) + { + try + { + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + IDbCommand sqlCommand = GetCommand(sql, parameters); + object scalar = sqlCommand.ExecuteScalar(); + //scalar = (scalar == null ? 0 : scalar); + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + return scalar; + } + catch (Exception ex) + { + CommandType = CommandType.Text; + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + finally + { + if (this.IsAutoClose()) this.Close(); + SetConnectionEnd(sql); + } + } + + public virtual async Task ExecuteCommandAsync(string sql, params SugarParameter[] parameters) + { + try + { + Async(); + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + var sqlCommand = GetCommand(sql, parameters); + int count = await sqlCommand.ExecuteNonQueryAsync(); + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + return count; + } + catch (Exception ex) + { + CommandType = CommandType.Text; + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + finally + { + if (this.IsAutoClose()) this.Close(); + SetConnectionEnd(sql); + } + } + public virtual async Task GetDataReaderAsync(string sql, params SugarParameter[] parameters) + { + try + { + Async(); + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + var isSp = this.CommandType == CommandType.StoredProcedure; + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + var sqlCommand = GetCommand(sql, parameters); + var sqlDataReader = await sqlCommand.ExecuteReaderAsync(this.IsAutoClose() ? CommandBehavior.CloseConnection : CommandBehavior.Default); + if (isSp) + DataReaderParameters = sqlCommand.Parameters; + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + SetConnectionEnd(sql); + return sqlDataReader; + } + catch (Exception ex) + { + CommandType = CommandType.Text; + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + } + public virtual async Task GetScalarAsync(string sql, params SugarParameter[] parameters) + { + try + { + Async(); + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + var sqlCommand = GetCommand(sql, parameters); + var scalar = await sqlCommand.ExecuteScalarAsync(); + //scalar = (scalar == null ? 0 : scalar); + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + return scalar; + } + catch (Exception ex) + { + CommandType = CommandType.Text; + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + finally + { + if (this.IsAutoClose()) this.Close(); + SetConnectionEnd(sql); + } + } + public virtual Task GetDataSetAllAsync(string sql, params SugarParameter[] parameters) + { + Async(); + //False asynchrony . No Support DataSet + return Task.FromResult(GetDataSetAll(sql, parameters)); + } + #endregion + + #region Methods + + public virtual string GetString(string sql, object parameters) + { + return GetString(sql, this.GetParameters(parameters)); + } + public virtual string GetString(string sql, params SugarParameter[] parameters) + { + return Convert.ToString(GetScalar(sql, parameters)); + } + public virtual string GetString(string sql, List parameters) + { + if (parameters == null) + { + return GetString(sql); + } + else + { + return GetString(sql, parameters.ToArray()); + } + } + + + public virtual Task GetStringAsync(string sql, object parameters) + { + return GetStringAsync(sql, this.GetParameters(parameters)); + } + public virtual async Task GetStringAsync(string sql, params SugarParameter[] parameters) + { + return Convert.ToString(await GetScalarAsync(sql, parameters)); + } + public virtual Task GetStringAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetStringAsync(sql); + } + else + { + return GetStringAsync(sql, parameters.ToArray()); + } + } + + + + public virtual long GetLong(string sql, object parameters = null) + { + return Convert.ToInt64(GetScalar(sql, GetParameters(parameters))); + } + public virtual async Task GetLongAsync(string sql, object parameters = null) + { + return Convert.ToInt64(await GetScalarAsync(sql, GetParameters(parameters))); + } + + + public virtual int GetInt(string sql, object parameters) + { + return GetInt(sql, this.GetParameters(parameters)); + } + public virtual int GetInt(string sql, List parameters) + { + if (parameters == null) + { + return GetInt(sql); + } + else + { + return GetInt(sql, parameters.ToArray()); + } + } + public virtual int GetInt(string sql, params SugarParameter[] parameters) + { + return GetScalar(sql, parameters).ObjToInt(); + } + + public virtual Task GetIntAsync(string sql, object parameters) + { + return GetIntAsync(sql, this.GetParameters(parameters)); + } + public virtual Task GetIntAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetIntAsync(sql); + } + else + { + return GetIntAsync(sql, parameters.ToArray()); + } + } + public virtual async Task GetIntAsync(string sql, params SugarParameter[] parameters) + { + var list = await GetScalarAsync(sql, parameters); + return list.ObjToInt(); + } + + public virtual Double GetDouble(string sql, object parameters) + { + return GetDouble(sql, this.GetParameters(parameters)); + } + public virtual Double GetDouble(string sql, params SugarParameter[] parameters) + { + return GetScalar(sql, parameters).ObjToMoney(); + } + public virtual Double GetDouble(string sql, List parameters) + { + if (parameters == null) + { + return GetDouble(sql); + } + else + { + return GetDouble(sql, parameters.ToArray()); + } + } + + public virtual Task GetDoubleAsync(string sql, object parameters) + { + return GetDoubleAsync(sql, this.GetParameters(parameters)); + } + public virtual async Task GetDoubleAsync(string sql, params SugarParameter[] parameters) + { + var result = await GetScalarAsync(sql, parameters); + return result.ObjToMoney(); + } + public virtual Task GetDoubleAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetDoubleAsync(sql); + } + else + { + return GetDoubleAsync(sql, parameters.ToArray()); + } + } + + + public virtual decimal GetDecimal(string sql, object parameters) + { + return GetDecimal(sql, this.GetParameters(parameters)); + } + public virtual decimal GetDecimal(string sql, params SugarParameter[] parameters) + { + return GetScalar(sql, parameters).ObjToDecimal(); + } + public virtual decimal GetDecimal(string sql, List parameters) + { + if (parameters == null) + { + return GetDecimal(sql); + } + else + { + return GetDecimal(sql, parameters.ToArray()); + } + } + + + public virtual Task GetDecimalAsync(string sql, object parameters) + { + return GetDecimalAsync(sql, this.GetParameters(parameters)); + } + public virtual async Task GetDecimalAsync(string sql, params SugarParameter[] parameters) + { + var result = await GetScalarAsync(sql, parameters); + return result.ObjToDecimal(); + } + public virtual Task GetDecimalAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetDecimalAsync(sql); + } + else + { + return GetDecimalAsync(sql, parameters.ToArray()); + } + } + + + + public virtual DateTime GetDateTime(string sql, object parameters) + { + return GetDateTime(sql, this.GetParameters(parameters)); + } + public virtual DateTime GetDateTime(string sql, params SugarParameter[] parameters) + { + return GetScalar(sql, parameters).ObjToDate(); + } + public virtual DateTime GetDateTime(string sql, List parameters) + { + if (parameters == null) + { + return GetDateTime(sql); + } + else + { + return GetDateTime(sql, parameters.ToArray()); + } + } + + + + + public virtual Task GetDateTimeAsync(string sql, object parameters) + { + return GetDateTimeAsync(sql, this.GetParameters(parameters)); + } + public virtual async Task GetDateTimeAsync(string sql, params SugarParameter[] parameters) + { + var list = await GetScalarAsync(sql, parameters); + return list.ObjToDate(); + } + public virtual Task GetDateTimeAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetDateTimeAsync(sql); + } + else + { + return GetDateTimeAsync(sql, parameters.ToArray()); + } + } + + + public virtual List SqlQuery(string sql, object parameters = null) + { + var sugarParameters = this.GetParameters(parameters); + return SqlQuery(sql, sugarParameters); + } + public virtual List SqlQuery(string sql, params SugarParameter[] parameters) + { + var result = SqlQuery(sql, parameters); + return result.Item1; + } + public virtual List SqlQuery(string sql, List parameters) + { + if (parameters != null) + { + return SqlQuery(sql, parameters.ToArray()); + } + else + { + return SqlQuery(sql); + } + } + public Tuple, List> SqlQuery(string sql, object parameters = null) + { + var result = SqlQuery(sql, parameters); + return new Tuple, List>(result.Item1, result.Item2); + } + public Tuple, List, List> SqlQuery(string sql, object parameters = null) + { + var result = SqlQuery(sql, parameters); + return new Tuple, List, List>(result.Item1, result.Item2, result.Item3); + } + public Tuple, List, List, List> SqlQuery(string sql, object parameters = null) + { + var result = SqlQuery(sql, parameters); + return new Tuple, List, List, List>(result.Item1, result.Item2, result.Item3, result.Item4); + } + public Tuple, List, List, List, List> SqlQuery(string sql, object parameters = null) + { + var result = SqlQuery(sql, parameters); + return new Tuple, List, List, List, List>(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5); + } + public Tuple, List, List, List, List, List> SqlQuery(string sql, object parameters = null) + { + var result = SqlQuery(sql, parameters); + return new Tuple, List, List, List, List, List>(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5, result.Item6); + } + public Tuple, List, List, List, List, List, List> SqlQuery(string sql, object parameters = null) + { + var parsmeterArray = this.GetParameters(parameters); + this.Context.InitMappingInfo(); + var builder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + builder.SqlQueryBuilder.sql.Append(sql); + if (parsmeterArray != null && parsmeterArray.Any()) + builder.SqlQueryBuilder.Parameters.AddRange(parsmeterArray); + using (var dataReader = this.GetDataReader(builder.SqlQueryBuilder.ToSqlString(), builder.SqlQueryBuilder.Parameters.ToArray())) + { + DbDataReader DbReader = (DbDataReader)dataReader; + List result = new List(); + if (DbReader.HasRows) + { + result = GetData(typeof(T), dataReader); + } + List result2 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result2 = GetData(typeof(T2), dataReader); + } + List result3 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result3 = GetData(typeof(T3), dataReader); + } + List result4 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result4 = GetData(typeof(T4), dataReader); + } + List result5 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result5 = GetData(typeof(T5), dataReader); + } + List result6 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result6 = GetData(typeof(T6), dataReader); + } + List result7 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result7 = GetData(typeof(T7), dataReader); + } + builder.SqlQueryBuilder.Clear(); + if (this.Context.Ado.DataReaderParameters != null) + { + foreach (IDataParameter item in this.Context.Ado.DataReaderParameters) + { + var parameter = parsmeterArray.FirstOrDefault(it => item.ParameterName.Substring(1) == it.ParameterName.Substring(1)); + if (parameter != null) + { + parameter.Value = item.Value; + } + } + this.Context.Ado.DataReaderParameters = null; + } + return Tuple.Create, List, List, List, List, List, List>(result, result2, result3, result4, result5, result6, result7); + } + } + public virtual Task> SqlQueryAsync(string sql, object parameters = null) + { + var sugarParameters = this.GetParameters(parameters); + return SqlQueryAsync(sql, sugarParameters); + } + public virtual async Task> SqlQueryAsync(string sql, params SugarParameter[] parameters) + { + var result = await SqlQueryAsync(sql, parameters); + return result.Item1; + } + public virtual Task> SqlQueryAsync(string sql, List parameters) + { + if (parameters != null) + { + return SqlQueryAsync(sql, parameters.ToArray()); + } + else + { + return SqlQueryAsync(sql); + } + } + public async Task, List>> SqlQueryAsync(string sql, object parameters = null) + { + var result = await SqlQueryAsync(sql, parameters); + return new Tuple, List>(result.Item1, result.Item2); + } + public async Task, List, List>> SqlQueryAsync(string sql, object parameters = null) + { + var result = await SqlQueryAsync(sql, parameters); + return new Tuple, List, List>(result.Item1, result.Item2, result.Item3); + } + public async Task, List, List, List>> SqlQueryAsync(string sql, object parameters = null) + { + var result = await SqlQueryAsync(sql, parameters); + return new Tuple, List, List, List>(result.Item1, result.Item2, result.Item3, result.Item4); + } + public async Task, List, List, List, List>> SqlQueryAsync(string sql, object parameters = null) + { + var result = await SqlQueryAsync(sql, parameters); + return new Tuple, List, List, List, List>(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5); + } + public async Task, List, List, List, List, List>> SqlQueryAsync(string sql, object parameters = null) + { + var result =await SqlQueryAsync(sql, parameters); + return new Tuple, List, List, List, List, List>(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5, result.Item6); + } + public async Task, List, List, List, List, List, List>> SqlQueryAsync(string sql, object parameters = null) + { + var parsmeterArray = this.GetParameters(parameters); + this.Context.InitMappingInfo(); + var builder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + builder.SqlQueryBuilder.sql.Append(sql); + if (parsmeterArray != null && parsmeterArray.Any()) + builder.SqlQueryBuilder.Parameters.AddRange(parsmeterArray); + using (var dataReader = await this.GetDataReaderAsync(builder.SqlQueryBuilder.ToSqlString(), builder.SqlQueryBuilder.Parameters.ToArray())) + { + DbDataReader DbReader = (DbDataReader)dataReader; + List result = new List(); + if (DbReader.HasRows) + { + result =await GetDataAsync(typeof(T), dataReader); + } + List result2 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result2 = await GetDataAsync(typeof(T2), dataReader); + } + List result3 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result3 = await GetDataAsync(typeof(T3), dataReader); + } + List result4 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result4 = await GetDataAsync(typeof(T4), dataReader); + } + List result5 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result5 = await GetDataAsync(typeof(T5), dataReader); + } + List result6 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result6 = await GetDataAsync(typeof(T6), dataReader); + } + List result7 = null; + if (NextResult(dataReader)) + { + this.Context.InitMappingInfo(); + result7 = await GetDataAsync(typeof(T7), dataReader); + } + builder.SqlQueryBuilder.Clear(); + if (this.Context.Ado.DataReaderParameters != null) + { + foreach (IDataParameter item in this.Context.Ado.DataReaderParameters) + { + var parameter = parsmeterArray.FirstOrDefault(it => item.ParameterName.Substring(1) == it.ParameterName.Substring(1)); + if (parameter != null) + { + parameter.Value = item.Value; + } + } + this.Context.Ado.DataReaderParameters = null; + } + return Tuple.Create, List, List, List, List, List, List>(result, result2, result3, result4, result5, result6, result7); + } + } + + public virtual T SqlQuerySingle(string sql, object parameters = null) + { + var result = SqlQuery(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + public virtual T SqlQuerySingle(string sql, params SugarParameter[] parameters) + { + var result = SqlQuery(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + public virtual T SqlQuerySingle(string sql, List parameters) + { + var result = SqlQuery(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + + + public virtual async Task SqlQuerySingleAsync(string sql, object parameters = null) + { + var result = await SqlQueryAsync(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + public virtual async Task SqlQuerySingleAsync(string sql, params SugarParameter[] parameters) + { + var result = await SqlQueryAsync(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + public virtual async Task SqlQuerySingleAsync(string sql, List parameters) + { + var result = await SqlQueryAsync(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + + + + public virtual DataTable GetDataTable(string sql, params SugarParameter[] parameters) + { + var ds = GetDataSetAll(sql, parameters); + if (ds.Tables.Count != 0 && ds.Tables.Count > 0) return ds.Tables[0]; + return new DataTable(); + } + public virtual DataTable GetDataTable(string sql, object parameters) + { + return GetDataTable(sql, this.GetParameters(parameters)); + } + public virtual DataTable GetDataTable(string sql, List parameters) + { + if (parameters == null) + { + return GetDataTable(sql); + } + else + { + return GetDataTable(sql, parameters.ToArray()); + } + } + + + public virtual async Task GetDataTableAsync(string sql, params SugarParameter[] parameters) + { + var ds = await GetDataSetAllAsync(sql, parameters); + if (ds.Tables.Count != 0 && ds.Tables.Count > 0) return ds.Tables[0]; + return new DataTable(); + } + public virtual Task GetDataTableAsync(string sql, object parameters) + { + return GetDataTableAsync(sql, this.GetParameters(parameters)); + } + public virtual Task GetDataTableAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetDataTableAsync(sql); + } + else + { + return GetDataTableAsync(sql, parameters.ToArray()); + } + } + + + public virtual DataSet GetDataSetAll(string sql, object parameters) + { + return GetDataSetAll(sql, this.GetParameters(parameters)); + } + public virtual DataSet GetDataSetAll(string sql, List parameters) + { + if (parameters == null) + { + return GetDataSetAll(sql); + } + else + { + return GetDataSetAll(sql, parameters.ToArray()); + } + } + + public virtual Task GetDataSetAllAsync(string sql, object parameters) + { + return GetDataSetAllAsync(sql, this.GetParameters(parameters)); + } + public virtual Task GetDataSetAllAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetDataSetAllAsync(sql); + } + else + { + return GetDataSetAllAsync(sql, parameters.ToArray()); + } + } + + + + + public virtual IDataReader GetDataReader(string sql, object parameters) + { + return GetDataReader(sql, this.GetParameters(parameters)); + } + public virtual IDataReader GetDataReader(string sql, List parameters) + { + if (parameters == null) + { + return GetDataReader(sql); + } + else + { + return GetDataReader(sql, parameters.ToArray()); + } + } + public virtual Task GetDataReaderAsync(string sql, object parameters) + { + return GetDataReaderAsync(sql, this.GetParameters(parameters)); + } + public virtual Task GetDataReaderAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetDataReaderAsync(sql); + } + else + { + return GetDataReaderAsync(sql, parameters.ToArray()); + } + } + public virtual object GetScalar(string sql, object parameters) + { + return GetScalar(sql, this.GetParameters(parameters)); + } + public virtual object GetScalar(string sql, List parameters) + { + if (parameters == null) + { + return GetScalar(sql); + } + else + { + return GetScalar(sql, parameters.ToArray()); + } + } + public virtual Task GetScalarAsync(string sql, object parameters) + { + return GetScalarAsync(sql, this.GetParameters(parameters)); + } + public virtual Task GetScalarAsync(string sql, List parameters) + { + if (parameters == null) + { + return GetScalarAsync(sql); + } + else + { + return GetScalarAsync(sql, parameters.ToArray()); + } + } + public virtual int ExecuteCommand(string sql, object parameters) + { + return ExecuteCommand(sql, GetParameters(parameters)); + } + public virtual int ExecuteCommand(string sql, List parameters) + { + if (parameters == null) + { + return ExecuteCommand(sql); + } + else + { + return ExecuteCommand(sql, parameters.ToArray()); + } + } + public virtual Task ExecuteCommandAsync(string sql, object parameters) + { + return ExecuteCommandAsync(sql, GetParameters(parameters)); + } + public virtual Task ExecuteCommandAsync(string sql, List parameters) + { + if (parameters == null) + { + return ExecuteCommandAsync(sql); + } + else + { + return ExecuteCommandAsync(sql, parameters.ToArray()); + } + } + #endregion + + #region Helper + private void Async() + { + if (this.Context.Root != null & this.Context.Root.AsyncId == null) + { + this.Context.Root.AsyncId = Guid.NewGuid(); ; + } + } + private static bool NextResult(IDataReader dataReader) + { + try + { + return dataReader.NextResult(); + } + catch + { + return false; + } + } + + private void ExecuteProcessingSQL(ref string sql, SugarParameter[] parameters) + { + var result = this.ProcessingEventStartingSQL(sql, parameters); + sql = result.Key; + parameters = result.Value; + } + public virtual void ExecuteBefore(string sql, SugarParameter[] parameters) + { + if (this.Context.CurrentConnectionConfig.Debugger != null && this.Context.CurrentConnectionConfig.Debugger.EnableThreadSecurityValidation == true) + { + + var contextId = this.Context.ContextID.ToString(); + var processId = Thread.CurrentThread.ManagedThreadId.ToString(); + var cache = new ReflectionInoCacheService(); + if (!cache.ContainsKey(contextId)) + { + cache.Add(contextId, processId); + } + else + { + var cacheValue = cache.Get(contextId); + if (processId != cacheValue) + { + throw new SqlSugarException(this.Context, ErrorMessage.GetThrowMessage("Detection of SqlSugarClient cross-threading usage,a thread needs a new one", "检测到声名的SqlSugarClient跨线程使用,请检查是否静态、是否单例、或者IOC配置错误引起的,保证一个线程new出一个对象 ,具本Sql:") + sql, parameters); + } + } + } + this.BeforeTime = DateTime.Now; + if (this.IsEnableLogEvent) + { + Action action = LogEventStarting; + if (action != null) + { + if (parameters == null || parameters.Length == 0) + { + action(sql, new SugarParameter[] { }); + } + else + { + action(sql, parameters); + } + } + } + } + public virtual void ExecuteAfter(string sql, SugarParameter[] parameters) + { + this.AfterTime = DateTime.Now; + var hasParameter = parameters.HasValue(); + if (hasParameter) + { + foreach (var outputParameter in parameters.Where(it => it.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput, ParameterDirection.ReturnValue))) + { + var gobalOutputParamter = this.OutputParameters.FirstOrDefault(it => it.ParameterName == outputParameter.ParameterName); + if (gobalOutputParamter == null) + {//Oracle bug + gobalOutputParamter = this.OutputParameters.FirstOrDefault(it => it.ParameterName == outputParameter.ParameterName.TrimStart(outputParameter.ParameterName.First())); + } + outputParameter.Value = gobalOutputParamter.Value; + this.OutputParameters.Remove(gobalOutputParamter); + } + } + if (this.IsEnableLogEvent) + { + Action action = LogEventCompleted; + if (action != null) + { + if (parameters == null || parameters.Length == 0) + { + action(sql, new SugarParameter[] { }); + } + else + { + action(sql, parameters); + } + } + } + if (this.OldCommandType != 0) + { + this.CommandType = this.OldCommandType; + this.IsClearParameters = this.OldClearParameters; + this.OldCommandType = 0; + this.OldClearParameters = false; + } + } + public virtual SugarParameter[] GetParameters(object parameters, PropertyInfo[] propertyInfo = null) + { + if (parameters == null) return null; + return base.GetParameters(parameters, propertyInfo, this.SqlParameterKeyWord); + } + private bool IsAutoClose() + { + return this.Context.CurrentConnectionConfig.IsAutoCloseConnection && this.Transaction == null; + } + private bool IsMasterSlaveSeparation + { + get + { + return this.Context.CurrentConnectionConfig.SlaveConnectionConfigs.HasValue() && this.IsDisableMasterSlaveSeparation == false; + } + } + private void SetConnectionStart(string sql) + { + if (this.Transaction == null && this.IsMasterSlaveSeparation && IsRead(sql)) + { + if (this.MasterConnection == null) + { + this.MasterConnection = this.Connection; + } + var saves = this.Context.CurrentConnectionConfig.SlaveConnectionConfigs.Where(it => it.HitRate > 0).ToList(); + var currentIndex = UtilRandom.GetRandomIndex(saves.ToDictionary(it => saves.ToList().IndexOf(it), it => it.HitRate)); + var currentSaveConnection = saves[currentIndex]; + this.Connection = null; + this.Context.CurrentConnectionConfig.ConnectionString = currentSaveConnection.ConnectionString; + this.Connection = this.Connection; + if (this.SlaveConnections.IsNullOrEmpty() || !this.SlaveConnections.Any(it => EqualsConnectionString(it.ConnectionString, this.Connection.ConnectionString))) + { + if (this.SlaveConnections == null) this.SlaveConnections = new List(); + this.SlaveConnections.Add(this.Connection); + } + } + } + + private bool EqualsConnectionString(string connectionString1, string connectionString2) + { + var connectionString1Array = connectionString1.Split(';'); + var connectionString2Array = connectionString2.Split(';'); + var result = connectionString1Array.Except(connectionString2Array); + return result.Count() == 0; + } + + private void SetConnectionEnd(string sql) + { + if (this.IsMasterSlaveSeparation && IsRead(sql) && this.Transaction == null) + { + this.Connection = this.MasterConnection; + this.Context.CurrentConnectionConfig.ConnectionString = this.MasterConnection.ConnectionString; + } + } + + private bool IsRead(string sql) + { + var sqlLower = sql.ToLower(); + var result = Regex.IsMatch(sqlLower, "[ ]*select[ ]") && !Regex.IsMatch(sqlLower, "[ ]*insert[ ]|[ ]*update[ ]|[ ]*delete[ ]"); + return result; + } + + private void ExecuteErrorEvent(string sql, SugarParameter[] parameters, Exception ex) + { + ErrorEvent(new SqlSugarException(this.Context, ex, sql, parameters)); + } + private void InitParameters(ref string sql, SugarParameter[] parameters) + { + if (parameters.HasValue()) + { + foreach (var item in parameters) + { + if (item.Value != null) + { + var type = item.Value.GetType(); + if ((type != UtilConstants.ByteArrayType && type.IsArray) || type.FullName.IsCollectionsList()) + { + var newValues = new List(); + foreach (var inValute in item.Value as IEnumerable) + { + newValues.Add(inValute.ObjToString()); + } + if (newValues.IsNullOrEmpty()) + { + newValues.Add("-1"); + } + if (item.ParameterName.Substring(0, 1) == ":") + { + sql = sql.Replace("@" + item.ParameterName.Substring(1), newValues.ToArray().ToJoinSqlInVals()); + } + sql = sql.Replace(item.ParameterName, newValues.ToArray().ToJoinSqlInVals()); + item.Value = DBNull.Value; + } + } + } + } + } + private List GetData(Type entityType, IDataReader dataReader) + { + List result; + if (entityType == UtilConstants.DynamicType) + { + result = this.Context.Utilities.DataReaderToExpandoObjectListNoUsing(dataReader) as List; + } + else if (entityType == UtilConstants.ObjType) + { + result = this.Context.Utilities.DataReaderToExpandoObjectListNoUsing(dataReader).Select(it => ((TResult)(object)it)).ToList(); + } + else if (entityType.IsAnonymousType()) + { + result = this.Context.Utilities.DataReaderToListNoUsing(dataReader); + } + else + { + result = this.Context.Ado.DbBind.DataReaderToListNoUsing(entityType, dataReader); + } + return result; + } + private async Task> GetDataAsync(Type entityType, IDataReader dataReader) + { + List result; + if (entityType == UtilConstants.DynamicType) + { + result =await this.Context.Utilities.DataReaderToExpandoObjectListAsyncNoUsing(dataReader) as List; + } + else if (entityType == UtilConstants.ObjType) + { + var list = await this.Context.Utilities.DataReaderToExpandoObjectListAsyncNoUsing(dataReader); + result = list.Select(it => ((TResult)(object)it)).ToList(); + } + else if (entityType.IsAnonymousType()) + { + result =await this.Context.Utilities.DataReaderToListAsyncNoUsing(dataReader); + } + else + { + result =await this.Context.Ado.DbBind.DataReaderToListNoUsingAsync(entityType, dataReader); + } + return result; + } + #endregion + + #region Obsolete + [Obsolete] + public virtual dynamic SqlQueryDynamic(string sql, object parameters = null) + { + var dt = this.GetDataTable(sql, parameters); + return dt == null ? null : this.Context.Utilities.DataTableToDynamic(dt); + } + [Obsolete] + public virtual dynamic SqlQueryDynamic(string sql, params SugarParameter[] parameters) + { + var dt = this.GetDataTable(sql, parameters); + return dt == null ? null : this.Context.Utilities.DataTableToDynamic(dt); + } + [Obsolete] + public dynamic SqlQueryDynamic(string sql, List parameters) + { + var dt = this.GetDataTable(sql, parameters); + return dt == null ? null : this.Context.Utilities.DataTableToDynamic(dt); + } + [Obsolete] + public void UseStoredProcedure(Action action) + { + var oldCommandType = this.CommandType; + this.CommandType = CommandType.StoredProcedure; + this.IsClearParameters = false; + if (action != null) + { + action(); + } + this.CommandType = oldCommandType; + this.IsClearParameters = true; + } + [Obsolete] + public T UseStoredProcedure(Func action) + { + T result = default(T); + var oldCommandType = this.CommandType; + this.CommandType = CommandType.StoredProcedure; + this.IsClearParameters = false; + if (action != null) + { + result = action(); + } + this.CommandType = oldCommandType; + this.IsClearParameters = true; + return result; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/AopProvider/AopProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/AopProvider/AopProvider.cs new file mode 100644 index 0000000..22f62f0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/AopProvider/AopProvider.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class AopProvider + { + private AopProvider() { } + public AopProvider(SqlSugarProvider context) + { + this.Context = context; + this.Context.Ado.IsEnableLogEvent = true; + } + private SqlSugarProvider Context { get; set; } + public Action OnDiffLogEvent { set { this.Context.CurrentConnectionConfig.AopEvents.OnDiffLogEvent = value; } } + public Action OnError { set { this.Context.CurrentConnectionConfig.AopEvents.OnError = value; } } + public Action OnLogExecuting { set { this.Context.CurrentConnectionConfig.AopEvents.OnLogExecuting= value; } } + public Action OnLogExecuted { set { this.Context.CurrentConnectionConfig.AopEvents.OnLogExecuted = value; } } + public Func> OnExecutingChangeSql { set { this.Context.CurrentConnectionConfig.AopEvents.OnExecutingChangeSql = value; } } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/CodeFirstProvider/CodeFirstProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/CodeFirstProvider/CodeFirstProvider.cs new file mode 100644 index 0000000..1ec62ee --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/CodeFirstProvider/CodeFirstProvider.cs @@ -0,0 +1,329 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public partial class CodeFirstProvider : ICodeFirst + { + #region Properties + public virtual SqlSugarProvider Context { get; set; } + protected bool IsBackupTable { get; set; } + protected int MaxBackupDataRows { get; set; } + protected virtual int DefultLength { get; set; } + public CodeFirstProvider() + { + if (DefultLength == 0) + { + DefultLength = 255; + } + } + #endregion + + #region Public methods + public virtual ICodeFirst BackupTable(int maxBackupDataRows = int.MaxValue) + { + this.IsBackupTable = true; + this.MaxBackupDataRows = maxBackupDataRows; + return this; + } + + public virtual ICodeFirst SetStringDefaultLength(int length) + { + DefultLength = length; + return this; + } + + public virtual void InitTables(Type entityType) + { + + this.Context.Utilities.RemoveCacheAll(); + this.Context.InitMappingInfo(entityType); + if (!this.Context.DbMaintenance.IsAnySystemTablePermissions()) + { + Check.Exception(true, "Dbfirst and Codefirst requires system table permissions"); + } + Check.Exception(this.Context.IsSystemTablesConfig, "Please set SqlSugarClent Parameter ConnectionConfig.InitKeyType=InitKeyType.Attribute "); + var executeResult = Context.Ado.UseTran(() => + { + Execute(entityType); + }); + Check.Exception(!executeResult.IsSuccess, executeResult.ErrorMessage); + } + public void InitTables() + { + InitTables(typeof(T)); + } + public void InitTables() + { + InitTables(typeof(T), typeof(T2)); + } + public void InitTables() + { + InitTables(typeof(T), typeof(T2), typeof(T3)); + } + public void InitTables() + { + InitTables(typeof(T), typeof(T2), typeof(T3), typeof(T4)); + } + public virtual void InitTables(params Type[] entityTypes) + { + if (entityTypes.HasValue()) + { + foreach (var item in entityTypes) + { + InitTables(item); + } + } + } + public virtual void InitTables(string entitiesNamespace) + { + var types = Assembly.Load(entitiesNamespace).GetTypes(); + InitTables(types); + } + public virtual void InitTables(params string[] entitiesNamespaces) + { + if (entitiesNamespaces.HasValue()) + { + foreach (var item in entitiesNamespaces) + { + InitTables(item); + } + } + } + #endregion + + #region Core Logic + protected virtual void Execute(Type entityType) + { + var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(entityType); + if (this.DefultLength > 0) + { + foreach (var item in entityInfo.Columns) + { + if (item.PropertyInfo.PropertyType == UtilConstants.StringType && item.DataType.IsNullOrEmpty() && item.Length == 0) + { + item.Length = DefultLength; + } + } + } + var tableName = GetTableName(entityInfo); + var isAny = this.Context.DbMaintenance.IsAnyTable(tableName); + if (isAny) + ExistLogic(entityInfo); + else + NoExistLogic(entityInfo); + + this.Context.DbMaintenance.AddRemark(entityInfo); + this.Context.DbMaintenance.AddIndex(entityInfo); + this.Context.DbMaintenance.AddDefaultValue(entityInfo); + } + public virtual void NoExistLogic(EntityInfo entityInfo) + { + var tableName = GetTableName(entityInfo); + //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimarykey ? 0 : 1).Where(it => it.IsIgnore == false)) + { + DbColumnInfo dbColumnInfo = EntityColumnToDbColumn(entityInfo, tableName, item); + columns.Add(dbColumnInfo); + } + } + this.Context.DbMaintenance.CreateTable(tableName, columns, true); + } + public virtual void ExistLogic(EntityInfo entityInfo) + { + if (entityInfo.Columns.HasValue()) + { + //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Multiple primary keys do not support modifications"); + + var tableName = GetTableName(entityInfo); + var dbColumns = this.Context.DbMaintenance.GetColumnInfosByTableName(tableName); + ConvertColumns(dbColumns); + var entityColumns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToList(); + var dropColumns = dbColumns + .Where(dc => !entityColumns.Any(ec => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(dc => !entityColumns.Any(ec => dc.DbColumnName.Equals(ec.DbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToList(); + var addColumns = entityColumns + .Where(ec => ec.OldDbColumnName.IsNullOrEmpty() || !dbColumns.Any(dc => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(ec => !dbColumns.Any(dc => ec.DbColumnName.Equals(dc.DbColumnName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + var alterColumns = entityColumns + .Where(ec => !dbColumns.Any(dc => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(ec => + dbColumns.Any(dc => dc.DbColumnName.Equals(ec.DbColumnName) + && ((ec.Length != dc.Length && !UtilMethods.GetUnderType(ec.PropertyInfo).IsEnum() && UtilMethods.GetUnderType(ec.PropertyInfo).IsIn(UtilConstants.StringType)) || + ec.IsNullable != dc.IsNullable || + IsSamgeType(ec, dc)))).ToList(); + var renameColumns = entityColumns + .Where(it => !string.IsNullOrEmpty(it.OldDbColumnName)) + .Where(entityColumn => dbColumns.Any(dbColumn => entityColumn.OldDbColumnName.Equals(dbColumn.DbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToList(); + + + var isMultiplePrimaryKey = dbColumns.Where(it => it.IsPrimarykey).Count() > 1 || entityColumns.Where(it => it.IsPrimarykey).Count() > 1; + + + var isChange = false; + foreach (var item in addColumns) + { + this.Context.DbMaintenance.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + isChange = true; + } + foreach (var item in dropColumns) + { + this.Context.DbMaintenance.DropColumn(tableName, item.DbColumnName); + isChange = true; + } + foreach (var item in alterColumns) + { + this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + isChange = true; + } + foreach (var item in renameColumns) + { + this.Context.DbMaintenance.RenameColumn(tableName, item.OldDbColumnName, item.DbColumnName); + isChange = true; + } + + foreach (var item in entityColumns) + { + var dbColumn = dbColumns.FirstOrDefault(dc => dc.DbColumnName.Equals(item.DbColumnName, StringComparison.CurrentCultureIgnoreCase)); + if (dbColumn == null) continue; + bool pkDiff, idEntityDiff; + KeyAction(item, dbColumn, out pkDiff, out idEntityDiff); + if (dbColumn != null && pkDiff && !idEntityDiff && isMultiplePrimaryKey == false) + { + var isAdd = item.IsPrimarykey; + if (isAdd) + { + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + else + { + this.Context.DbMaintenance.DropConstraint(tableName, string.Format("PK_{0}_{1}", tableName, item.DbColumnName)); + } + } + else if ((pkDiff || idEntityDiff) && isMultiplePrimaryKey == false) + { + ChangeKey(entityInfo, tableName, item); + } + } + if (isMultiplePrimaryKey) + { + var oldPkNames = dbColumns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName.ToLower()).OrderBy(it => it).ToList(); + var newPkNames = entityColumns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName.ToLower()).OrderBy(it => it).ToList(); + if (!Enumerable.SequenceEqual(oldPkNames, newPkNames)) + { + Check.Exception(true, ErrorMessage.GetThrowMessage("Modification of multiple primary key tables is not supported. Delete tables while creating", "不支持修改多主键表,请删除表在创建")); + } + + } + if (isChange && IsBackupTable) + { + this.Context.DbMaintenance.BackupTable(tableName, tableName + DateTime.Now.ToString("yyyyMMddHHmmss"), MaxBackupDataRows); + } + } + } + + protected virtual void KeyAction(EntityColumnInfo item, DbColumnInfo dbColumn, out bool pkDiff, out bool idEntityDiff) + { + pkDiff = item.IsPrimarykey != dbColumn.IsPrimarykey; + idEntityDiff = item.IsIdentity != dbColumn.IsIdentity; + } + + protected virtual void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + string constraintName = string.Format("PK_{0}_{1}", tableName, item.DbColumnName); + if (this.Context.DbMaintenance.IsAnyConstraint(constraintName)) + this.Context.DbMaintenance.DropConstraint(tableName, constraintName); + this.Context.DbMaintenance.DropColumn(tableName, item.DbColumnName); + this.Context.DbMaintenance.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + if (item.IsPrimarykey) + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + + protected virtual void ConvertColumns(List dbColumns) + { + + } + #endregion + + #region Helper methods + public virtual string GetCreateTableString(EntityInfo entityInfo) + { + StringBuilder result = new StringBuilder(); + var tableName = GetTableName(entityInfo); + return result.ToString(); + } + public virtual string GetCreateColumnsString(EntityInfo entityInfo) + { + StringBuilder result = new StringBuilder(); + var tableName = GetTableName(entityInfo); + return result.ToString(); + } + protected virtual string GetTableName(EntityInfo entityInfo) + { + return this.Context.EntityMaintenance.GetTableName(entityInfo.EntityName); + } + protected virtual DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + var propertyType = UtilMethods.GetUnderType(item.PropertyInfo); + var result = new DbColumnInfo() + { + TableId = entityInfo.Columns.IndexOf(item), + DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName, + IsPrimarykey = item.IsPrimarykey, + IsIdentity = item.IsIdentity, + TableName = tableName, + IsNullable = item.IsNullable, + DefaultValue = item.DefaultValue, + ColumnDescription = item.ColumnDescription, + Length = item.Length, + DecimalDigits = item.DecimalDigits + }; + GetDbType(item, propertyType, result); + return result; + } + + protected virtual void GetDbType(EntityColumnInfo item, Type propertyType, DbColumnInfo result) + { + if (!string.IsNullOrEmpty(item.DataType)) + { + result.DataType = item.DataType; + } + else if (propertyType.IsEnum()) + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(item.Length > 9 ? UtilConstants.LongType.Name : UtilConstants.IntType.Name); + } + else + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(propertyType.Name); + } + } + + protected virtual bool IsSamgeType(EntityColumnInfo ec, DbColumnInfo dc) + { + if (!string.IsNullOrEmpty(ec.DataType)) + { + return ec.DataType != dc.DataType; + } + var propertyType = UtilMethods.GetUnderType(ec.PropertyInfo); + var properyTypeName = string.Empty; + if (propertyType.IsEnum()) + { + properyTypeName = this.Context.Ado.DbBind.GetDbTypeName(ec.Length > 9 ? UtilConstants.LongType.Name : UtilConstants.IntType.Name); + } + else + { + properyTypeName = this.Context.Ado.DbBind.GetDbTypeName(propertyType.Name); + } + var dataType = dc.DataType; + return properyTypeName != dataType; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/DbBindAccessory.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/DbBindAccessory.cs new file mode 100644 index 0000000..2d1df66 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/DbBindAccessory.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class DbBindAccessory + { + protected List GetEntityList(SqlSugarProvider context, IDataReader dataReader) + { + Type type = typeof(T); + var fieldNames = GetDataReaderNames(dataReader); + string cacheKey = GetCacheKey(type,fieldNames); + IDataReaderEntityBuilder entytyList = context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => + { + var cacheResult = new IDataReaderEntityBuilder(context, dataReader,fieldNames).CreateBuilder(type); + return cacheResult; + }); + List result = new List(); + try + { + if (dataReader == null) return result; + while (dataReader.Read()) + { + result.Add(entytyList.Build(dataReader)); + } + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.EntityMappingError, ex.Message); + } + return result; + } + protected async Task> GetEntityListAsync(SqlSugarProvider context, IDataReader dataReader) + { + Type type = typeof(T); + var fieldNames = GetDataReaderNames(dataReader); + string cacheKey = GetCacheKey(type, fieldNames); + IDataReaderEntityBuilder entytyList = context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => + { + var cacheResult = new IDataReaderEntityBuilder(context, dataReader, fieldNames).CreateBuilder(type); + return cacheResult; + }); + List result = new List(); + try + { + if (dataReader == null) return result; + while (await((DbDataReader)dataReader).ReadAsync()) + { + result.Add(entytyList.Build(dataReader)); + } + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.EntityMappingError, ex.Message); + } + return result; + } + + private string GetCacheKey(Type type,List keys) + { + StringBuilder sb = new StringBuilder("DataReaderToList."); + sb.Append(type.FullName); + sb.Append("."); + foreach (var item in keys) + { + sb.Append(item); + } + return sb.ToString(); + } + + private List GetDataReaderNames(IDataReader dataReader) + { + List keys = new List(); + var count = dataReader.FieldCount; + for (int i = 0; i < count; i++) + { + keys.Add(dataReader.GetName(i)); + } + return keys; + } + + protected List GetKeyValueList(Type type, IDataReader dataReader) + { + List result = new List(); + while (dataReader.Read()) + { + GetKeyValueList(type, dataReader, result); + } + return result; + } + + protected async Task> GetKeyValueListAsync(Type type, IDataReader dataReader) + { + List result = new List(); + while (await ((DbDataReader)dataReader).ReadAsync()) + { + GetKeyValueList(type, dataReader, result); + } + return result; + } + + private static void GetKeyValueList(Type type, IDataReader dataReader, List result) + { + if (UtilConstants.DicOO == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0), dataReader.GetValue(1)); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.DicIS == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToInt(), dataReader.GetValue(1).ObjToString()); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.Dicii == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToInt(), dataReader.GetValue(1).ObjToInt()); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.DicSi == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1).ObjToInt()); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.DicSo == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1)); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.DicSS == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1).ObjToString()); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else + { + Check.Exception(true, ErrorMessage.NotSupportedDictionary); + } + } + + + protected async Task> GetArrayListAsync(Type type, IDataReader dataReader) + { + List result = new List(); + int count = dataReader.FieldCount; + var childType = type.GetElementType(); + while (await((DbDataReader)dataReader).ReadAsync()) + { + GetArrayList(type, dataReader, result, count, childType); + } + return result; + } + + protected List GetArrayList(Type type, IDataReader dataReader) + { + List result = new List(); + int count = dataReader.FieldCount; + var childType = type.GetElementType(); + while (dataReader.Read()) + { + GetArrayList(type, dataReader, result, count, childType); + } + return result; + } + + + + private static void GetArrayList(Type type, IDataReader dataReader, List result, int count, Type childType) + { + object[] array = new object[count]; + for (int i = 0; i < count; i++) + { + array[i] = Convert.ChangeType(dataReader.GetValue(i), childType); + } + if (childType == UtilConstants.StringType) + result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToString()).ToArray(), type)); + else if (childType == UtilConstants.ObjType) + result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? null : (object)it).ToArray(), type)); + else if (childType == UtilConstants.BoolType) + result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToBool()).ToArray(), type)); + else if (childType == UtilConstants.ByteType) + result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? 0 : (byte)it).ToArray(), type)); + else if (childType == UtilConstants.DecType) + result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToDecimal()).ToArray(), type)); + else if (childType == UtilConstants.GuidType) + result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? Guid.Empty : (Guid)it).ToArray(), type)); + else if (childType == UtilConstants.DateType) + result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? DateTime.MinValue : (DateTime)it).ToArray(), type)); + else if (childType == UtilConstants.IntType) + result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToInt()).ToArray(), type)); + else + Check.Exception(true, ErrorMessage.NotSupportedArray); + } + + protected List GetValueTypeList(Type type, IDataReader dataReader) + { + List result = new List(); + while (dataReader.Read()) + { + GetValueTypeList(type, dataReader, result); + } + return result; + } + protected async Task> GetValueTypeListAsync(Type type, IDataReader dataReader) + { + List result = new List(); + while (await ((DbDataReader)dataReader).ReadAsync()) + { + GetValueTypeList(type, dataReader, result); + } + return result; + } + + private static void GetValueTypeList(Type type, IDataReader dataReader, List result) + { + var value = dataReader.GetValue(0); + if (type == UtilConstants.GuidType) + { + value = Guid.Parse(value.ToString()); + } + if (value == DBNull.Value) + { + result.Add(default(T)); + } + else if (type.IsEnum) + { + result.Add((T)Enum.Parse(type, value.ObjToString())); + } + else + { + result.Add((T)Convert.ChangeType(value, UtilMethods.GetUnderType(type))); + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/DbBindProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/DbBindProvider.cs new file mode 100644 index 0000000..daa55f8 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/DbBindProvider.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public abstract partial class DbBindProvider : DbBindAccessory, IDbBind + { + #region Properties + public virtual SqlSugarProvider Context { get; set; } + public abstract List> MappingTypes { get; } + #endregion + + #region Public methods + public virtual string GetDbTypeName(string csharpTypeName) + { + if (csharpTypeName == UtilConstants.ByteArrayType.Name) + return "varbinary"; + if (csharpTypeName.ToLower() == "int32") + csharpTypeName = "int"; + if (csharpTypeName.ToLower() == "int16") + csharpTypeName = "short"; + if (csharpTypeName.ToLower() == "int64") + csharpTypeName = "long"; + if (csharpTypeName.ToLower().IsIn("boolean", "bool")) + csharpTypeName = "bool"; + var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)); + return mappings.HasValue() ? mappings.First().Key : "varchar"; + } + public string GetCsharpTypeName(string dbTypeName) + { + var mappings = this.MappingTypes.Where(it => it.Key == dbTypeName); + return mappings.HasValue() ? mappings.First().Key : "string"; + } + public virtual string GetConvertString(string dbTypeName) + { + string result = string.Empty; + switch (dbTypeName.ToLower()) + { + #region Int + case "int": + result = "Convert.ToInt32"; + break; + #endregion + + #region String + case "nchar": + case "char": + case "ntext": + case "nvarchar": + case "varchar": + case "text": + result = "Convert.ToString"; + break; + #endregion + + #region Long + case "bigint": + result = "Convert.ToInt64"; + break; + #endregion + + #region Bool + case "bit": + result = "Convert.ToBoolean"; + break; + + #endregion + + #region Datetime + case "timestamp": + case "smalldatetime": + case "datetime": + case "date": + case "datetime2": + result = "Convert.ToDateTime"; + break; + #endregion + + #region Decimal + case "smallmoney": + case "single": + case "numeric": + case "money": + case "decimal": + result = "Convert.ToDecimal"; + break; + #endregion + + #region Double + case "float": + result = "Convert.ToDouble"; + break; + #endregion + + #region Byte[] + case "varbinary": + case "binary": + case "image": + result = "byte[]"; + break; + #endregion + + #region Float + case "real": + result = "Convert.ToSingle"; + break; + #endregion + + #region Short + case "smallint": + result = "Convert.ToInt16"; + break; + #endregion + + #region Byte + case "tinyint": + result = "Convert.ToByte"; + break; + + #endregion + + #region Guid + case "uniqueidentifier": + result = "Guid.Parse"; + break; + #endregion + + #region Null + default: + result = null; + break; + #endregion + } + return result; + } + public virtual string GetPropertyTypeName(string dbTypeName) + { + dbTypeName = dbTypeName.ToLower(); + var propertyTypes = MappingTypes.Where(it => it.Key.Equals(dbTypeName, StringComparison.CurrentCultureIgnoreCase)); + if (dbTypeName == "int32") + { + return "int"; + } + else if (dbTypeName == "int64") + { + return "long"; + } + else if (dbTypeName == "int16") + { + return "short"; + } + else if (propertyTypes == null) + { + return "other"; + } + else if (dbTypeName.IsContainsIn("xml", "string", "String")) + { + return "string"; + } + else if (dbTypeName.IsContainsIn("boolean", "bool")) + { + return "bool"; + } + else if (propertyTypes == null || propertyTypes.Count() == 0) + { + return "object"; + } + else if (propertyTypes.First().Value == CSharpDataType.byteArray) + { + return "byte[]"; + } + else + { + return propertyTypes.First().Value.ToString(); + } + } + public virtual List DataReaderToList(Type type, IDataReader dataReader) + { + using (dataReader) + { + if (type.Name.StartsWith("KeyValuePair")) + { + return GetKeyValueList(type, dataReader); + } + else if (type.IsValueType() || type == UtilConstants.StringType || type == UtilConstants.ByteArrayType) + { + return GetValueTypeList(type, dataReader); + } + else if (type.IsArray) + { + return GetArrayList(type, dataReader); + } + else + { + return GetEntityList(Context, dataReader); + } + } + } + public virtual async Task> DataReaderToListAsync(Type type, IDataReader dataReader) + { + using (dataReader) + { + if (type.Name.StartsWith("KeyValuePair")) + { + return await GetKeyValueListAsync(type, dataReader); + } + else if (type.IsValueType() || type == UtilConstants.StringType || type == UtilConstants.ByteArrayType) + { + return await GetValueTypeListAsync(type, dataReader); + } + else if (type.IsArray) + { + return await GetArrayListAsync(type, dataReader); + } + else + { + return await GetEntityListAsync(Context, dataReader); + } + } + } + public virtual List DataReaderToListNoUsing(Type type, IDataReader dataReader) + { + if (type.Name.StartsWith("KeyValuePair")) + { + return GetKeyValueList(type, dataReader); + } + else if (type.IsValueType() || type == UtilConstants.StringType || type == UtilConstants.ByteArrayType) + { + return GetValueTypeList(type, dataReader); + } + else if (type.IsArray) + { + return GetArrayList(type, dataReader); + } + else + { + return GetEntityList(Context, dataReader); + } + } + public virtual Task> DataReaderToListNoUsingAsync(Type type, IDataReader dataReader) + { + if (type.Name.StartsWith("KeyValuePair")) + { + return GetKeyValueListAsync(type, dataReader); + } + else if (type.IsValueType() || type == UtilConstants.StringType || type == UtilConstants.ByteArrayType) + { + return GetValueTypeListAsync(type, dataReader); + } + else if (type.IsArray) + { + return GetArrayListAsync(type, dataReader); + } + else + { + return GetEntityListAsync(Context, dataReader); + } + } + #endregion + + #region Throw rule + + public virtual List IntThrow + { + get + { + return new List() { "datetime", "byte" }; + } + } + public virtual List ShortThrow + { + get + { + return new List() { "datetime", "guid" }; + } + } + public virtual List DecimalThrow + { + get + { + return new List() { "datetime", "byte", "guid" }; + } + } + public virtual List DoubleThrow + { + get + { + return new List() { "datetime", "byte", "guid" }; + } + } + public virtual List DateThrow + { + get + { + return new List() { "int32", "decimal", "double", "byte", "guid" }; + } + } + public virtual List GuidThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte" }; + } + } + public virtual List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte", "guid" }; + } + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/IDataReaderEntityBuilder.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/IDataReaderEntityBuilder.cs new file mode 100644 index 0000000..efbeedc --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/IDataReaderEntityBuilder.cs @@ -0,0 +1,339 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +using System.Reflection; +using System.Reflection.Emit; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + /// + /// ** description:IDataReader Entity Builder + /// ** author:sunkaixuan + /// ** date:2017/4/2 + /// ** qq:610262374 + /// + public partial class IDataReaderEntityBuilder + { + #region Properies + private List ReaderKeys { get; set; } + #endregion + + #region Fields + private SqlSugarProvider Context = null; + private IDataReaderEntityBuilder DynamicBuilder; + private IDataRecord DataRecord; + private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new Type[] { typeof(int) }); + private static readonly MethodInfo getBoolean = typeof(IDataRecord).GetMethod("GetBoolean", new Type[] { typeof(int) }); + private static readonly MethodInfo getByte = typeof(IDataRecord).GetMethod("GetByte", new Type[] { typeof(int) }); + private static readonly MethodInfo getDateTime = typeof(IDataRecord).GetMethod("GetDateTime", new Type[] { typeof(int) }); + private static readonly MethodInfo getDecimal = typeof(IDataRecord).GetMethod("GetDecimal", new Type[] { typeof(int) }); + private static readonly MethodInfo getDouble = typeof(IDataRecord).GetMethod("GetDouble", new Type[] { typeof(int) }); + private static readonly MethodInfo getFloat = typeof(IDataRecord).GetMethod("GetFloat", new Type[] { typeof(int) }); + private static readonly MethodInfo getGuid = typeof(IDataRecord).GetMethod("GetGuid", new Type[] { typeof(int) }); + private static readonly MethodInfo getInt16 = typeof(IDataRecord).GetMethod("GetInt16", new Type[] { typeof(int) }); + private static readonly MethodInfo getInt32 = typeof(IDataRecord).GetMethod("GetInt32", new Type[] { typeof(int) }); + private static readonly MethodInfo getInt64 = typeof(IDataRecord).GetMethod("GetInt64", new Type[] { typeof(int) }); + private static readonly MethodInfo getString = typeof(IDataRecord).GetMethod("GetString", new Type[] { typeof(int) }); + private static readonly MethodInfo getConvertValueMethod = typeof(IDataRecordExtensions).GetMethod("GetConvertValue"); + private static readonly MethodInfo getdatetimeoffset = typeof(IDataRecordExtensions).GetMethod("Getdatetimeoffset"); + private static readonly MethodInfo getdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod("GetdatetimeoffsetDate"); + private static readonly MethodInfo getStringGuid = typeof(IDataRecordExtensions).GetMethod("GetStringGuid"); + private static readonly MethodInfo getConvertStringGuid = typeof(IDataRecordExtensions).GetMethod("GetConvertStringGuid"); + private static readonly MethodInfo getEnum = typeof(IDataRecordExtensions).GetMethod("GetEnum"); + private static readonly MethodInfo getConvertString = typeof(IDataRecordExtensions).GetMethod("GetConvertString"); + private static readonly MethodInfo getConvertFloat = typeof(IDataRecordExtensions).GetMethod("GetConvertFloat"); + private static readonly MethodInfo getConvertBoolean = typeof(IDataRecordExtensions).GetMethod("GetConvertBoolean"); + private static readonly MethodInfo getConvertByte = typeof(IDataRecordExtensions).GetMethod("GetConvertByte"); + private static readonly MethodInfo getConvertChar = typeof(IDataRecordExtensions).GetMethod("GetConvertChar"); + private static readonly MethodInfo getConvertDateTime = typeof(IDataRecordExtensions).GetMethod("GetConvertDateTime"); + private static readonly MethodInfo getConvertTime = typeof(IDataRecordExtensions).GetMethod("GetConvertTime"); + private static readonly MethodInfo getTime = typeof(IDataRecordExtensions).GetMethod("GetTime"); + private static readonly MethodInfo getConvertDecimal = typeof(IDataRecordExtensions).GetMethod("GetConvertDecimal"); + private static readonly MethodInfo getConvertDouble = typeof(IDataRecordExtensions).GetMethod("GetConvertDouble"); + private static readonly MethodInfo getConvertDoubleToFloat = typeof(IDataRecordExtensions).GetMethod("GetConvertDoubleToFloat"); + private static readonly MethodInfo getConvertGuid = typeof(IDataRecordExtensions).GetMethod("GetConvertGuid"); + private static readonly MethodInfo getConvertInt16 = typeof(IDataRecordExtensions).GetMethod("GetConvertInt16"); + private static readonly MethodInfo getConvertInt32 = typeof(IDataRecordExtensions).GetMethod("GetConvertInt32"); + private static readonly MethodInfo getConvertInt64 = typeof(IDataRecordExtensions).GetMethod("GetConvetInt64"); + private static readonly MethodInfo getConvertEnum_Null = typeof(IDataRecordExtensions).GetMethod("GetConvertEnum_Null"); + private static readonly MethodInfo getConvertdatetimeoffset = typeof(IDataRecordExtensions).GetMethod("GetConvertdatetimeoffset"); + private static readonly MethodInfo getConvertdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod("GetConvertdatetimeoffsetDate"); + private static readonly MethodInfo getOtherNull = typeof(IDataRecordExtensions).GetMethod("GetOtherNull"); + private static readonly MethodInfo getOther = typeof(IDataRecordExtensions).GetMethod("GetOther"); + private static readonly MethodInfo getJson = typeof(IDataRecordExtensions).GetMethod("GetJson"); + private static readonly MethodInfo getEntity = typeof(IDataRecordExtensions).GetMethod("GetEntity", new Type[] { typeof(SqlSugarProvider) }); + + private delegate T Load(IDataRecord dataRecord); + private Load handler; + #endregion + + #region Constructor + private IDataReaderEntityBuilder() + { + + } + + public IDataReaderEntityBuilder(SqlSugarProvider context, IDataRecord dataRecord, List fieldNames) + { + this.Context = context; + this.DataRecord = dataRecord; + this.DynamicBuilder = new IDataReaderEntityBuilder(); + this.ReaderKeys = fieldNames; + } + #endregion + + #region Public methods + public T Build(IDataRecord dataRecord) + { + return handler(dataRecord); + } + + public IDataReaderEntityBuilder CreateBuilder(Type type) + { + DynamicMethod method = new DynamicMethod("SqlSugarEntity", type, + new Type[] { typeof(IDataRecord) }, type, true); + ILGenerator generator = method.GetILGenerator(); + LocalBuilder result = generator.DeclareLocal(type); + generator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes)); + generator.Emit(OpCodes.Stloc, result); + this.Context.InitMappingInfo(type); + var columnInfos = this.Context.EntityMaintenance.GetEntityInfo(type).Columns; + foreach (var columnInfo in columnInfos) + { + string fileName = columnInfo.DbColumnName ?? columnInfo.PropertyName; + if (columnInfo.IsIgnore && !this.ReaderKeys.Any(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))) + { + continue; + } + if (columnInfo != null && columnInfo.PropertyInfo.GetSetMethod() != null) + { + if (columnInfo.PropertyInfo.PropertyType.IsClass() && columnInfo.PropertyInfo.PropertyType != UtilConstants.ByteArrayType && columnInfo.PropertyInfo.PropertyType != UtilConstants.ObjType) + { + if (this.ReaderKeys.Any(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))) + { + BindClass(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))); + } + } + else + { + if (this.ReaderKeys.Any(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))) + { + BindField(generator, result, columnInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))); + } + } + } + } + generator.Emit(OpCodes.Ldloc, result); + generator.Emit(OpCodes.Ret); + DynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load)); + return DynamicBuilder; + } + + #endregion + + #region Private methods + private void BindClass(ILGenerator generator, LocalBuilder result, EntityColumnInfo columnInfo, string fieldName) + { + if (columnInfo.IsJson) + { + MethodInfo jsonMethod = getJson.MakeGenericMethod(columnInfo.PropertyInfo.PropertyType); + int i = DataRecord.GetOrdinal(fieldName); + Label endIfLabel = generator.DefineLabel(); + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldc_I4, i); + generator.Emit(OpCodes.Callvirt, isDBNullMethod); + generator.Emit(OpCodes.Brtrue, endIfLabel); + generator.Emit(OpCodes.Ldloc, result); + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldc_I4, i); + generator.Emit(OpCodes.Call, jsonMethod); + generator.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.GetSetMethod()); + generator.MarkLabel(endIfLabel); + } + } + private void BindField(ILGenerator generator, LocalBuilder result, EntityColumnInfo columnInfo, string fieldName) + { + int i = DataRecord.GetOrdinal(fieldName); + Label endIfLabel = generator.DefineLabel(); + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldc_I4, i); + generator.Emit(OpCodes.Callvirt, isDBNullMethod); + generator.Emit(OpCodes.Brtrue, endIfLabel); + generator.Emit(OpCodes.Ldloc, result); + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldc_I4, i); + BindMethod(generator, columnInfo, i); + generator.Emit(OpCodes.Callvirt, columnInfo.PropertyInfo.GetSetMethod()); + generator.MarkLabel(endIfLabel); + } + private void BindMethod(ILGenerator generator, EntityColumnInfo columnInfo, int ordinal) + { + IDbBind bind = Context.Ado.DbBind; + bool isNullableType = false; + MethodInfo method = null; + Type bindPropertyType = UtilMethods.GetUnderType(columnInfo.PropertyInfo, ref isNullableType); + string dbTypeName = UtilMethods.GetParenthesesValue(DataRecord.GetDataTypeName(ordinal)); + if (dbTypeName.IsNullOrEmpty()) + { + dbTypeName = bindPropertyType.Name; + } + string propertyName = columnInfo.PropertyName; + string validPropertyName = bind.GetPropertyTypeName(dbTypeName); + validPropertyName = validPropertyName == "byte[]" ? "byteArray" : validPropertyName; + CSharpDataType validPropertyType = (CSharpDataType)Enum.Parse(typeof(CSharpDataType), validPropertyName); + + #region Sqlite Logic + if (this.Context.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + if (bindPropertyType.IsEnum()) + { + method = isNullableType ? getConvertEnum_Null.MakeGenericMethod(bindPropertyType) : getEnum.MakeGenericMethod(bindPropertyType); + } + else if (bindPropertyType == UtilConstants.IntType) + { + method = isNullableType ? getConvertInt32 : getInt32; + } + else if (bindPropertyType == UtilConstants.ByteType) + { + method = isNullableType ? getConvertByte : getByte; + } + else if (bindPropertyType == UtilConstants.StringType) + { + method = getString; + } + else + { + method = getConvertValueMethod.MakeGenericMethod(columnInfo.PropertyInfo.PropertyType); + } + + if (method.IsVirtual) + generator.Emit(OpCodes.Callvirt, method); + else + generator.Emit(OpCodes.Call, method); + return; + }; + #endregion + + #region Common Database Logic + string bindProperyTypeName = bindPropertyType.Name.ToLower(); + bool isEnum = bindPropertyType.IsEnum(); + if (isEnum) { validPropertyType = CSharpDataType.@enum; } + switch (validPropertyType) + { + case CSharpDataType.@int: + CheckType(bind.IntThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName.IsContainsIn("int", "int32")) + method = isNullableType ? getConvertInt32 : getInt32; + if (bindProperyTypeName.IsContainsIn("int64")) + method = isNullableType ? getConvertInt64 : getInt64; + if (bindProperyTypeName.IsContainsIn("byte")) + method = isNullableType ? getConvertByte : getByte; + if (bindProperyTypeName.IsContainsIn("int16")) + method = isNullableType ? getConvertInt16 : getInt16; + break; + case CSharpDataType.@bool: + if (bindProperyTypeName == "bool" || bindProperyTypeName == "boolean") + method = isNullableType ? getConvertBoolean : getBoolean; + break; + case CSharpDataType.@string: + CheckType(bind.StringThrow, bindProperyTypeName, validPropertyName, propertyName); + method = getString; + if (bindProperyTypeName == "guid") + { + method = isNullableType ? getConvertStringGuid : getStringGuid; + } + break; + case CSharpDataType.DateTime: + CheckType(bind.DateThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName == "datetime") + method = isNullableType ? getConvertDateTime : getDateTime; + if (bindProperyTypeName == "datetime" && dbTypeName.ToLower() == "time") + method = isNullableType ? getConvertTime : getTime; + break; + case CSharpDataType.@decimal: + CheckType(bind.DecimalThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName == "decimal") + method = isNullableType ? getConvertDecimal : getDecimal; + break; + case CSharpDataType.@float: + case CSharpDataType.@double: + CheckType(bind.DoubleThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName.IsIn("double", "single") && dbTypeName != "real") + method = isNullableType ? getConvertDouble : getDouble; + else + method = isNullableType ? getConvertFloat : getFloat; + if (dbTypeName.Equals("float", StringComparison.CurrentCultureIgnoreCase) && isNullableType && bindProperyTypeName.Equals("single", StringComparison.CurrentCultureIgnoreCase)) + { + method = getConvertDoubleToFloat; + } + if (bindPropertyType == UtilConstants.DecType) + { + method = getConvertValueMethod.MakeGenericMethod(bindPropertyType); + } + if (bindPropertyType == UtilConstants.IntType) + { + method = getConvertValueMethod.MakeGenericMethod(bindPropertyType); + } + break; + case CSharpDataType.Guid: + CheckType(bind.GuidThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName == "guid") + method = isNullableType ? getConvertGuid : getGuid; + break; + case CSharpDataType.@byte: + if (bindProperyTypeName == "byte") + method = isNullableType ? getConvertByte : getByte; + break; + case CSharpDataType.@enum: + method = isNullableType ? getConvertEnum_Null.MakeGenericMethod(bindPropertyType) : getEnum.MakeGenericMethod(bindPropertyType); + break; + case CSharpDataType.@short: + CheckType(bind.ShortThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName == "int16" || bindProperyTypeName == "short") + method = isNullableType ? getConvertInt16 : getInt16; + break; + case CSharpDataType.@long: + if (bindProperyTypeName == "int64" || bindProperyTypeName == "long") + method = isNullableType ? getConvertInt64 : getInt64; + break; + case CSharpDataType.DateTimeOffset: + method = isNullableType ? getConvertdatetimeoffset : getdatetimeoffset; + if (bindProperyTypeName == "datetime") + method = isNullableType ? getConvertdatetimeoffsetDate : getdatetimeoffsetDate; + break; + default: + method = getConvertValueMethod.MakeGenericMethod(bindPropertyType); + break; + } + if (method == null && bindPropertyType == UtilConstants.StringType) + { + method = getConvertString; + } + if (bindPropertyType == UtilConstants.ObjType) + { + method = getConvertValueMethod.MakeGenericMethod(bindPropertyType); + } + if (method == null) + method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType); + + if (method.IsVirtual) + generator.Emit(OpCodes.Callvirt, method); + else + generator.Emit(OpCodes.Call, method); + #endregion + } + + private void CheckType(List invalidTypes, string bindProperyTypeName, string validPropertyType, string propertyName) + { + var isAny = invalidTypes.Contains(bindProperyTypeName); + if (isAny) + { + throw new SqlSugarException(string.Format("{0} can't convert {1} to {2}", propertyName, validPropertyType, bindProperyTypeName)); + } + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/IDataRecordExtensions.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/IDataRecordExtensions.cs new file mode 100644 index 0000000..68712a2 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbBindProvider/IDataRecordExtensions.cs @@ -0,0 +1,297 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +namespace SqlSugar +{ + public static partial class IDataRecordExtensions + { + + #region Common Extensions + public static Guid GetStringGuid(this IDataRecord dr, int i) + { + var result = Guid.Parse(dr.GetValue(i).ToString()); + return result; + } + + public static Guid? GetConvertStringGuid(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return Guid.Empty; + } + var result = Guid.Parse(dr.GetValue(i).ToString()); + return result; + } + + public static bool? GetConvertBoolean(this IDataRecord dr, int i) + { + var result = dr.GetBoolean(i); + return result; + } + + public static byte? GetConvertByte(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetByte(i); + return result; + } + + public static char? GetConvertChar(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetChar(i); + return result; + } + + public static DateTime? GetConvertDateTime(this IDataRecord dr, int i) + { + var result = dr.GetDateTime(i); + if (result == DateTime.MinValue) + { + return null; ; + } + return result; + } + public static DateTime? GetConvertTime(this IDataRecord dr, int i) + { + var result = dr.GetValue(i); + if (result == DBNull.Value) + { + return null; ; + } + return Convert.ToDateTime(result.ToString()); + } + public static DateTime GetTime(this IDataRecord dr, int i) + { + return Convert.ToDateTime(dr.GetValue(i).ToString()); + } + + public static decimal? GetConvertDecimal(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetDecimal(i); + return result; + } + + + public static double? GetConvertDouble(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetDouble(i); + return result; + } + + + public static float? GetConvertDoubleToFloat(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetDouble(i); + return Convert.ToSingle(result); + } + + + public static Guid? GetConvertGuid(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetGuid(i); + return result; + } + + public static short? GetConvertInt16(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetInt16(i); + return result; + } + + public static Int32? GetConvertInt32(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetInt32(i); + return result; + } + public static T GetConvertValue(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return default(T); + } + object result = null; + try + { + result = dr[i]; + } + catch (Exception ex) + { + + } + return UtilMethods.To(result); + + } + + public static long? GetConvetInt64(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetInt64(i); + return result; + } + + public static float? GetConvertFloat(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetFloat(i); + return result; + } + + public static DateTime GetdatetimeoffsetDate(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return DateTime.MinValue; + } + var offsetValue = (DateTimeOffset)dr.GetValue(i); + var result = offsetValue.DateTime; + return result; + } + + public static DateTime? GetConvertdatetimeoffsetDate(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return DateTime.MinValue; + } + var offsetValue = (DateTimeOffset)dr.GetValue(i); + var result = offsetValue.DateTime; + return result; + } + + public static DateTimeOffset Getdatetimeoffset(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return default(DateTimeOffset); + } + var result = (DateTimeOffset)dr.GetValue(i); + return result; + } + + public static DateTimeOffset? GetConvertdatetimeoffset(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return default(DateTimeOffset); + } + var result = (DateTimeOffset)dr.GetValue(i); + return result; + } + + + public static string GetConvertString(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = Convert.ToString(dr.GetValue(i)); + return result; + } + + public static Nullable GetOtherNull(this IDataReader dr, int i) where T : struct + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetValue(i); + return UtilMethods.To(result); + + } + + public static T GetOther(this IDataReader dr, int i) + { + if (dr.IsDBNull(i)) + { + return default(T); + } + var result = dr.GetValue(i); + return UtilMethods.To(result); + } + + public static T GetJson(this IDataReader dr, int i) + { + var obj = dr.GetValue(i); + if (obj == null) + return default(T); + var value = obj.ObjToString(); + return new SerializeService().DeserializeObject(value); + } + + public static Nullable GetConvertEnum_Null(this IDataReader dr, int i) where T : struct + { + if (dr.IsDBNull(i)) + { + return null; + } + object value = dr.GetValue(i); + T t = (T)Enum.ToObject(typeof(T), value); + return t; + } + + public static T GetEnum(this IDataReader dr, int i) where T : struct + { + object value = dr.GetValue(i); + if (value != null) + { + if (value.GetType() == UtilConstants.DecType) + { + value = Convert.ToUInt32(value); + } + else if (value.GetType() == UtilConstants.StringType) + { + return (T)Enum.Parse(typeof(T), value.ObjToString()); + } + } + T t = (T)Enum.ToObject(typeof(T), value); + return t; + } + + public static object GetEntity(this IDataReader dr, SqlSugarProvider context) + { + return null; + } + + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbFirstProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbFirstProvider.cs new file mode 100644 index 0000000..3688892 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbFirstProvider.cs @@ -0,0 +1,444 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public abstract partial class DbFirstProvider : IDbFirst + { + public virtual ISqlSugarClient Context { get; set; } + private string ClassTemplate { get; set; } + private string ClassDescriptionTemplate { get; set; } + private string PropertyTemplate { get; set; } + private string PropertyDescriptionTemplate { get; set; } + private string ConstructorTemplate { get; set; } + private string UsingTemplate { get; set; } + private string Namespace { get; set; } + private bool IsAttribute { get; set; } + private bool IsDefaultValue { get; set; } + private ISqlBuilder SqlBuilder + { + get + { + return InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + } + } + private List TableInfoList { get; set; } + + public DbFirstProvider() + { + this.ClassTemplate = DbFirstTemplate.ClassTemplate; + this.ClassDescriptionTemplate = DbFirstTemplate.ClassDescriptionTemplate; + this.PropertyTemplate = DbFirstTemplate.PropertyTemplate; + this.PropertyDescriptionTemplate = DbFirstTemplate.PropertyDescriptionTemplate; + this.ConstructorTemplate = DbFirstTemplate.ConstructorTemplate; + this.UsingTemplate = DbFirstTemplate.UsingTemplate; + } + + public void Init() + { + this.Context.Utilities.RemoveCacheAll(); + if (!this.Context.DbMaintenance.IsAnySystemTablePermissions()) + { + Check.Exception(true, "Dbfirst and Codefirst requires system table permissions"); + } + this.TableInfoList = this.Context.Utilities.TranslateCopy(this.Context.DbMaintenance.GetTableInfoList()); + var viewList = this.Context.Utilities.TranslateCopy(this.Context.DbMaintenance.GetViewInfoList()); + if (viewList.HasValue()) + { + this.TableInfoList.AddRange(viewList); + } + } + + #region Setting Template + public IDbFirst SettingClassDescriptionTemplate(Func func) + { + this.ClassDescriptionTemplate = func(this.ClassDescriptionTemplate); + return this; + } + + public IDbFirst SettingClassTemplate(Func func) + { + this.ClassTemplate = func(this.ClassTemplate); + return this; + } + + public IDbFirst SettingConstructorTemplate(Func func) + { + this.ConstructorTemplate = func(this.ConstructorTemplate); + return this; + } + + public IDbFirst SettingPropertyDescriptionTemplate(Func func) + { + this.PropertyDescriptionTemplate = func(this.PropertyDescriptionTemplate); + return this; + } + + public IDbFirst SettingNamespaceTemplate(Func func) + { + this.UsingTemplate = func(this.UsingTemplate); + return this; + } + + public IDbFirst SettingPropertyTemplate(Func func) + { + this.PropertyTemplate = func(this.PropertyTemplate); + return this; + } + public RazorFirst UseRazorAnalysis(string razorClassTemplate,string classNamespace="Models" ) + { + if (razorClassTemplate == null) + { + razorClassTemplate = ""; + } + razorClassTemplate=razorClassTemplate.Replace("@Model.Namespace", classNamespace); + var result = new RazorFirst(); + if (this.Context.CurrentConnectionConfig.ConfigureExternalServices?.RazorService != null) + { + List razorList = new List(); + var tables = this.Context.DbMaintenance.GetTableInfoList(false); + if (tables.HasValue()) + { + foreach (var item in tables) + { + var columns = this.Context.DbMaintenance.GetColumnInfosByTableName(item.Name, false); + RazorTableInfo table = new RazorTableInfo() + { + Columns = columns.Select(it => new RazorColumnInfo() + { + ColumnDescription = it.ColumnDescription, + DataType = it.DataType, + DbColumnName = it.DbColumnName, + DefaultValue = it.DefaultValue, + IsIdentity = it.IsIdentity, + IsNullable = it.IsNullable, + IsPrimarykey = it.IsPrimarykey, + Length = it.Length + }).ToList(), + Description = item.Description, + DbTableName = item.Name + }; + foreach (var col in table.Columns) + { + col.DataType = GetPropertyTypeName(columns.First(it=>it.DbColumnName==col.DbColumnName)); + } + razorList.Add(table); + } + } + result.ClassStringList = this.Context.CurrentConnectionConfig.ConfigureExternalServices.RazorService.GetClassStringList(razorClassTemplate, razorList); + } + else + { + Check.Exception(true, ErrorMessage.GetThrowMessage("Need to achieve ConnectionConfig.ConfigureExternal Services.RazorService", "需要实现 ConnectionConfig.ConfigureExternal Services.RazorService接口")); + } + this.Context.Utilities.RemoveCacheAll(); + return result; + } + #endregion + + #region Setting Content + public IDbFirst IsCreateAttribute(bool isCreateAttribute = true) + { + this.IsAttribute = isCreateAttribute; + return this; + } + public IDbFirst IsCreateDefaultValue(bool isCreateDefaultValue = true) + { + this.IsDefaultValue = isCreateDefaultValue; + return this; + } + #endregion + + #region Where + public IDbFirst Where(DbObjectType dbObjectType) + { + if (dbObjectType != DbObjectType.All) + this.TableInfoList = this.TableInfoList.Where(it => it.DbObjectType == dbObjectType).ToList(); + return this; + } + + public IDbFirst Where(Func func) + { + this.TableInfoList = this.TableInfoList.Where(it => func(it.Name)).ToList(); + return this; + } + + public IDbFirst Where(params string[] objectNames) + { + if (objectNames.HasValue()) + { + this.TableInfoList = this.TableInfoList.Where(it => objectNames.Select(x => x.ToLower()).Contains(it.Name.ToLower())).ToList(); + } + return this; + } + #endregion + + #region Core + public Dictionary ToClassStringList(string nameSpace = "Models") + { + this.Namespace = nameSpace; + Dictionary result = new Dictionary(); + if (this.TableInfoList.HasValue()) + { + foreach (var tableInfo in this.TableInfoList) + { + try + { + string classText = null; + string className = tableInfo.Name; + classText = GetClassString(tableInfo, ref className); + result.Remove(className); + result.Add(className, classText); + } + catch (Exception ex) + { + Check.Exception(true, "Table '{0}' error,You can filter it with Db.DbFirst.Where(name=>name!=\"{0}\" ) \r\n Error message:{1}", tableInfo.Name, ex.Message); + } + } + } + return result; + } + + internal string GetClassString(DbTableInfo tableInfo, ref string className) + { + string classText; + var columns = this.Context.DbMaintenance.GetColumnInfosByTableName(tableInfo.Name); + if (this.Context.IgnoreColumns.HasValue()) + { + var entityName = this.Context.EntityMaintenance.GetEntityName(tableInfo.Name); + columns = columns.Where(c => + !this.Context.IgnoreColumns.Any(ig => ig.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase) && c.DbColumnName == ig.PropertyName) + ).ToList(); + } + classText = this.ClassTemplate; + string ConstructorText = IsDefaultValue ? this.ConstructorTemplate : null; + if (this.Context.MappingTables.HasValue()) + { + var mappingInfo = this.Context.MappingTables.FirstOrDefault(it => it.DbTableName.Equals(tableInfo.Name, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo.HasValue()) + { + className = mappingInfo.EntityName; + } + if (mappingInfo != null) + { + classText = classText.Replace(DbFirstTemplate.KeyClassName, mappingInfo.EntityName); + } + } + classText = classText.Replace(DbFirstTemplate.KeyClassName, className); + classText = classText.Replace(DbFirstTemplate.KeyNamespace, this.Namespace); + classText = classText.Replace(DbFirstTemplate.KeyUsing, IsAttribute ? (this.UsingTemplate + "using " + UtilConstants.AssemblyName + ";\r\n") : this.UsingTemplate); + classText = classText.Replace(DbFirstTemplate.KeyClassDescription, this.ClassDescriptionTemplate.Replace(DbFirstTemplate.KeyClassDescription, tableInfo.Description + "\r\n")); + classText = classText.Replace(DbFirstTemplate.KeySugarTable, IsAttribute ? string.Format(DbFirstTemplate.ValueSugarTable, tableInfo.Name) : null); + if (columns.HasValue()) + { + foreach (var item in columns) + { + var isLast = columns.Last() == item; + var index = columns.IndexOf(item); + string PropertyText = this.PropertyTemplate; + string PropertyDescriptionText = this.PropertyDescriptionTemplate; + string propertyName = GetPropertyName(item); + string propertyTypeName = GetPropertyTypeName(item); + PropertyText = GetPropertyText(item, PropertyText); + PropertyDescriptionText = GetPropertyDescriptionText(item, PropertyDescriptionText); + PropertyText = PropertyDescriptionText + PropertyText; + classText = classText.Replace(DbFirstTemplate.KeyPropertyName, PropertyText + (isLast ? "" : ("\r\n" + DbFirstTemplate.KeyPropertyName))); + if (ConstructorText.HasValue() && item.DefaultValue != null) + { + var hasDefaultValue = columns.Skip(index + 1).Any(it => it.DefaultValue.HasValue()); + ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyPropertyName, propertyName); + ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyDefaultValue, GetPropertyTypeConvert(item)) + (!hasDefaultValue ? "" : this.ConstructorTemplate); + } + } + } + if (!columns.Any(it => it.DefaultValue != null)) + { + ConstructorText = null; + } + classText = classText.Replace(DbFirstTemplate.KeyConstructor, ConstructorText); + classText = classText.Replace(DbFirstTemplate.KeyPropertyName, null); + return classText; + } + internal string GetClassString(List columns, ref string className) + { + string classText = this.ClassTemplate; + string ConstructorText = IsDefaultValue ? this.ConstructorTemplate : null; + classText = classText.Replace(DbFirstTemplate.KeyClassName, className); + classText = classText.Replace(DbFirstTemplate.KeyNamespace, this.Namespace); + classText = classText.Replace(DbFirstTemplate.KeyUsing, IsAttribute ? (this.UsingTemplate + "using " + UtilConstants.AssemblyName + ";\r\n") : this.UsingTemplate); + classText = classText.Replace(DbFirstTemplate.KeyClassDescription, this.ClassDescriptionTemplate.Replace(DbFirstTemplate.KeyClassDescription, "\r\n")); + classText = classText.Replace(DbFirstTemplate.KeySugarTable, IsAttribute ? string.Format(DbFirstTemplate.ValueSugarTable, className) : null); + if (columns.HasValue()) + { + foreach (var item in columns) + { + var isLast = columns.Last() == item; + var index = columns.IndexOf(item); + string PropertyText = this.PropertyTemplate; + string PropertyDescriptionText = this.PropertyDescriptionTemplate; + string propertyName = GetPropertyName(item); + string propertyTypeName = item.PropertyName; + PropertyText = GetPropertyText(item, PropertyText); + PropertyDescriptionText = GetPropertyDescriptionText(item, PropertyDescriptionText); + PropertyText = PropertyDescriptionText + PropertyText; + classText = classText.Replace(DbFirstTemplate.KeyPropertyName, PropertyText + (isLast ? "" : ("\r\n" + DbFirstTemplate.KeyPropertyName))); + if (ConstructorText.HasValue() && item.DefaultValue != null) + { + var hasDefaultValue = columns.Skip(index + 1).Any(it => it.DefaultValue.HasValue()); + ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyPropertyName, propertyName); + ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyDefaultValue, GetPropertyTypeConvert(item)) + (!hasDefaultValue ? "" : this.ConstructorTemplate); + } + } + } + if (!columns.Any(it => it.DefaultValue != null)) + { + ConstructorText = null; + } + classText = classText.Replace(DbFirstTemplate.KeyConstructor, ConstructorText); + classText = classText.Replace(DbFirstTemplate.KeyPropertyName, null); + return classText; + } + public void CreateClassFile(string directoryPath, string nameSpace = "Models") + { + var seChar = Path.DirectorySeparatorChar.ToString(); + Check.ArgumentNullException(directoryPath, "directoryPath can't null"); + var classStringList = ToClassStringList(nameSpace); + if (classStringList.IsValuable()) + { + foreach (var item in classStringList) + { + var filePath = directoryPath.TrimEnd('\\').TrimEnd('/') + string.Format(seChar + "{0}.cs", item.Key); + FileHelper.CreateFile(filePath, item.Value, Encoding.UTF8); + } + } + } + #endregion + + #region Private methods + private string GetProertypeDefaultValue(DbColumnInfo item) + { + var result = item.DefaultValue; + if (result == null) return null; + if (Regex.IsMatch(result, @"^\(\'(.+)\'\)$")) + { + result = Regex.Match(result, @"^\(\'(.+)\'\)$").Groups[1].Value; + } + if (Regex.IsMatch(result, @"^\(\((.+)\)\)$")) + { + result = Regex.Match(result, @"^\(\((.+)\)\)$").Groups[1].Value; + } + if (Regex.IsMatch(result, @"^\((.+)\)$")) + { + result = Regex.Match(result, @"^\((.+)\)$").Groups[1].Value; + } + if (result.Equals(this.SqlBuilder.SqlDateNow, StringComparison.CurrentCultureIgnoreCase)) + { + result = "DateTime.Now"; + } + result = result.Replace("\r", "\t").Replace("\n", "\t"); + result = result.IsIn("''", "\"\"") ? string.Empty : result; + return result; + } + private string GetPropertyText(DbColumnInfo item, string PropertyText) + { + string SugarColumnText = DbFirstTemplate.ValueSugarCoulmn; + var propertyName = GetPropertyName(item); + var isMappingColumn = propertyName != item.DbColumnName; + var hasSugarColumn = item.IsPrimarykey == true || item.IsIdentity == true || isMappingColumn; + if (hasSugarColumn && this.IsAttribute) + { + List joinList = new List(); + if (item.IsPrimarykey) + { + joinList.Add("IsPrimaryKey=true"); + } + if (item.IsIdentity) + { + joinList.Add("IsIdentity=true"); + } + if (isMappingColumn) + { + joinList.Add("ColumnName=\"" + item.DbColumnName + "\""); + } + SugarColumnText = string.Format(SugarColumnText, string.Join(",", joinList)); + } + else + { + SugarColumnText = null; + } + string typeString = GetPropertyTypeName(item); + PropertyText = PropertyText.Replace(DbFirstTemplate.KeySugarColumn, SugarColumnText); + PropertyText = PropertyText.Replace(DbFirstTemplate.KeyPropertyType, typeString); + PropertyText = PropertyText.Replace(DbFirstTemplate.KeyPropertyName, propertyName); + return PropertyText; + } + private string GetEnityName(DbColumnInfo item) + { + var mappingInfo = this.Context.MappingTables.FirstOrDefault(it => it.DbTableName.Equals(item.TableName, StringComparison.CurrentCultureIgnoreCase)); + return mappingInfo == null ? item.TableName : mappingInfo.EntityName; + } + private string GetPropertyName(DbColumnInfo item) + { + if (this.Context.MappingColumns.HasValue()) + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.DbColumnName == item.DbColumnName && it.EntityName == GetEnityName(item)); + return mappingInfo == null ? item.DbColumnName : mappingInfo.PropertyName; + } + else + { + return item.DbColumnName; + } + } + private string GetPropertyTypeName(DbColumnInfo item) + { + string result = item.PropertyType != null ? item.PropertyType.Name : this.Context.Ado.DbBind.GetPropertyTypeName(item.DataType); + if (result != "string" && result != "byte[]" && result != "object" && item.IsNullable) + { + result += "?"; + } + if (result == "Int32") + { + result = "int"; + } + if (result == "String") + { + result = "string"; + } + return result; + } + private string GetPropertyTypeConvert(DbColumnInfo item) + { + var convertString = GetProertypeDefaultValue(item); + if (convertString == "DateTime.Now" || convertString == null) + return convertString; + if (convertString.ObjToString() == "newid()") + { + return "Guid.NewGuid()"; + } + if (item.DataType == "bit") + return (convertString == "1" || convertString.Equals("true", StringComparison.CurrentCultureIgnoreCase)).ToString().ToLower(); + string result = this.Context.Ado.DbBind.GetConvertString(item.DataType) + "(\"" + convertString + "\")"; + return result; + } + private string GetPropertyDescriptionText(DbColumnInfo item, string propertyDescriptionText) + { + propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyPropertyDescription, GetColumnDescription(item.ColumnDescription)); + propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyDefaultValue, GetProertypeDefaultValue(item)); + propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyIsNullable, item.IsNullable.ObjToString()); + return propertyDescriptionText; + } + private string GetColumnDescription(string columnDescription) + { + if (columnDescription == null) return columnDescription; + columnDescription = columnDescription.Replace("\r", "\t"); + columnDescription = columnDescription.Replace("\n", "\t"); + columnDescription = Regex.Replace(columnDescription, "\t{2,}", "\t"); + return columnDescription; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbFirstTemplate.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbFirstTemplate.cs new file mode 100644 index 0000000..ab7fdd2 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbFirstTemplate.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DbFirstTemplate + { + #region Template + public static string ClassTemplate = "{using}\r\n" + + "namespace {Namespace}\r\n" + + "{\r\n" + + "{ClassDescription}{SugarTable}\r\n" + + ClassSpace+ "public partial class {ClassName}\r\n" + + ClassSpace + "{\r\n" + + PropertySpace + "public {ClassName}(){\r\n\r\n" + + "{Constructor}\r\n" + + PropertySpace + "}\r\n" + + "{PropertyName}\r\n" + + ClassSpace + "}\r\n" + + "}\r\n"; + public static string ClassDescriptionTemplate = + ClassSpace + "///\r\n" + + ClassSpace + "///{ClassDescription}" + + ClassSpace + "///"; + + public static string PropertyTemplate = PropertySpace + "{SugarColumn}\r\n" + + PropertySpace + "public {PropertyType} {PropertyName} {get;set;}\r\n"; + + public static string PropertyDescriptionTemplate = + PropertySpace + "/// \r\n" + + PropertySpace + "/// Desc:{PropertyDescription}\r\n" + + PropertySpace + "/// Default:{DefaultValue}\r\n" + + PropertySpace + "/// Nullable:{IsNullable}\r\n" + + PropertySpace + "/// "; + + public static string ConstructorTemplate = PropertySpace + " this.{PropertyName} ={DefaultValue};\r\n"; + + public static string UsingTemplate = "using System;\r\n" + + "using System.Linq;\r\n" + + "using System.Text;" + "\r\n"; + #endregion + + #region Replace Key + public const string KeyUsing = "{using}"; + public const string KeyNamespace = "{Namespace}"; + public const string KeyClassName = "{ClassName}"; + public const string KeyIsNullable = "{IsNullable}"; + public const string KeySugarTable = "{SugarTable}"; + public const string KeyConstructor = "{Constructor}"; + public const string KeySugarColumn = "{SugarColumn}"; + public const string KeyPropertyType = "{PropertyType}"; + public const string KeyPropertyName = "{PropertyName}"; + public const string KeyDefaultValue = "{DefaultValue}"; + public const string KeyClassDescription = "{ClassDescription}"; + public const string KeyPropertyDescription = "{PropertyDescription}"; + #endregion + + #region Replace Value + public const string ValueSugarTable = "\r\n"+ClassSpace+"[SugarTable(\"{0}\")]"; + public const string ValueSugarCoulmn = "\r\n"+PropertySpace+"[SugarColumn({0})]"; + #endregion + + #region Space + public const string PropertySpace = " "; + public const string ClassSpace = " "; + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbRazor.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbRazor.cs new file mode 100644 index 0000000..7e5c6dd --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbFirstProvider/DbRazor.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class RazorFirst + { + internal List> ClassStringList { get; set; } + + public static string DefaultRazorClassTemplate = +@"using System; +using System.Linq; +using System.Text; +using SqlSugar; +namespace @Model.Namespace +{ + /// + /// + /// + public partial class @Model.ClassName + { + public @(Model.ClassName)(){ + + + } + @foreach (var item in @Model.Columns) + { + if(item.IsPrimarykey&&item.IsIdentity){ + @:/// + @:/// Desc:@item.ColumnDescription + @:/// Default:@item.DefaultValue + @:/// Nullable:@item.IsNullable + @:/// + @:[SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + @:public @item.DataType @item.DbColumnName {get;set;} + } + else if(item.IsPrimarykey) + { + @:/// + @:/// Desc:@item.ColumnDescription + @:/// Default:@item.DefaultValue + @:/// Nullable:@item.IsNullable + @:/// + @:[SqlSugar.SugarColumn(IsPrimaryKey = true)] + @:public @item.DataType @item.DbColumnName {get;set;} + } + else if(item.IsIdentity) + { + @:/// + @:/// Desc:@item.ColumnDescription + @:/// Default:@item.DefaultValue + @:/// Nullable:@item.IsNullable + @:/// + @:[SqlSugar.SugarColumn(IsIdentity = true)] + @:public @item.DataType @item.DbColumnName {get;set;} + } + else + { + @:/// + @:/// Desc:@item.ColumnDescription + @:/// Default:@item.DefaultValue + @:/// Nullable:@item.IsNullable + @:/// + @:public @item.DataType @item.DbColumnName {get;set;} + } + } + + } +}"; + + public void CreateClassFile(string directoryPath) + { + var seChar = Path.DirectorySeparatorChar.ToString(); + if (ClassStringList.HasValue()) + { + foreach (var item in ClassStringList) + { + var filePath = directoryPath.TrimEnd('\\').TrimEnd('/') + string.Format(seChar + "{0}.cs", item.Key); + FileHelper.CreateFile(filePath, item.Value, Encoding.UTF8); + } + } + } + public List> GetClassStringList() + { + return ClassStringList; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbMaintenanceProvider/Methods.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbMaintenanceProvider/Methods.cs new file mode 100644 index 0000000..ebb1071 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbMaintenanceProvider/Methods.cs @@ -0,0 +1,494 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public abstract partial class DbMaintenanceProvider : IDbMaintenance + { + #region DML + public virtual List GetDataBaseList(SqlSugarClient db) + { + return db.Ado.SqlQuery(this.GetDataBaseSql); + } + public virtual List GetViewInfoList(bool isCache = true) + { + string cacheKey = "DbMaintenanceProvider.GetViewInfoList"; + cacheKey = GetCacheKey(cacheKey); + var result = new List(); + if (isCache) + result = GetListOrCache(cacheKey, this.GetViewInfoListSql); + else + result = this.Context.Ado.SqlQuery(this.GetViewInfoListSql); + foreach (var item in result) + { + item.DbObjectType = DbObjectType.View; + } + return result; + } + public virtual List GetTableInfoList(bool isCache = true) + { + string cacheKey = "DbMaintenanceProvider.GetTableInfoList"; + cacheKey = GetCacheKey(cacheKey); + var result = new List(); + if (isCache) + result = GetListOrCache(cacheKey, this.GetTableInfoListSql); + else + result = this.Context.Ado.SqlQuery(this.GetTableInfoListSql); + foreach (var item in result) + { + item.DbObjectType = DbObjectType.Table; + } + return result; + } + public virtual List GetColumnInfosByTableName(string tableName, bool isCache = true) + { + if (string.IsNullOrEmpty(tableName)) return new List(); + string cacheKey = "DbMaintenanceProvider.GetColumnInfosByTableName." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + var sql = string.Format(this.GetColumnInfosByTableNameSql, tableName); + if (isCache) + return GetListOrCache(cacheKey, sql).GroupBy(it => it.DbColumnName).Select(it => it.First()).ToList(); + else + return this.Context.Ado.SqlQuery(sql).GroupBy(it => it.DbColumnName).Select(it => it.First()).ToList(); + + } + public virtual List GetIsIdentities(string tableName) + { + string cacheKey = "DbMaintenanceProvider.GetIsIdentities" + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => + { + var result = GetColumnInfosByTableName(tableName).Where(it => it.IsIdentity).ToList(); + return result.Select(it => it.DbColumnName).ToList(); + }); + } + public virtual List GetPrimaries(string tableName) + { + string cacheKey = "DbMaintenanceProvider.GetPrimaries" + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => + { + var result = GetColumnInfosByTableName(tableName).Where(it => it.IsPrimarykey).ToList(); + return result.Select(it => it.DbColumnName).ToList(); + }); + } + #endregion + + #region Check + public virtual bool IsAnyTable(string tableName, bool isCache = true) + { + tableName = this.SqlBuilder.GetNoTranslationColumnName(tableName); + var tables = GetTableInfoList(isCache); + if (tables == null) return false; + else return tables.Any(it => it.Name.Equals(tableName, StringComparison.CurrentCultureIgnoreCase)); + } + public virtual bool IsAnyColumn(string tableName, string columnName) + { + columnName = this.SqlBuilder.GetNoTranslationColumnName(columnName); + tableName = this.SqlBuilder.GetNoTranslationColumnName(tableName); + var isAny = IsAnyTable(tableName); + Check.Exception(!isAny, string.Format("Table {0} does not exist", tableName)); + var columns = GetColumnInfosByTableName(tableName); + if (columns.IsNullOrEmpty()) return false; + return columns.Any(it => it.DbColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase)); + } + public virtual bool IsPrimaryKey(string tableName, string columnName) + { + columnName = this.SqlBuilder.GetNoTranslationColumnName(columnName); + var isAny = IsAnyTable(tableName); + Check.Exception(!isAny, string.Format("Table {0} does not exist", tableName)); + var columns = GetColumnInfosByTableName(tableName); + if (columns.IsNullOrEmpty()) return false; + var result=columns.Any(it => it.IsPrimarykey == true && it.DbColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase)); + return result; + } + public virtual bool IsIdentity(string tableName, string columnName) + { + columnName = this.SqlBuilder.GetNoTranslationColumnName(columnName); + var isAny = IsAnyTable(tableName); + Check.Exception(!isAny, string.Format("Table {0} does not exist", tableName)); + var columns = GetColumnInfosByTableName(tableName); + if (columns.IsNullOrEmpty()) return false; + return columns.Any(it => it.IsIdentity = true && it.DbColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase)); + } + public virtual bool IsAnyConstraint(string constraintName) + { + return this.Context.Ado.GetInt("select object_id('" + constraintName + "')") > 0; + } + public virtual bool IsAnySystemTablePermissions() + { + this.Context.Ado.CheckConnection(); + string sql = this.CheckSystemTablePermissionsSql; + try + { + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + this.Context.Ado.ExecuteCommand(sql); + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + return true; + } + catch + { + return false; + } + } + #endregion + + #region DDL + /// + ///by current connection string + /// + /// + /// + public virtual bool CreateDatabase(string databaseDirectory = null) + { + var seChar = Path.DirectorySeparatorChar.ToString(); + if (databaseDirectory.HasValue()) + { + databaseDirectory = databaseDirectory.TrimEnd('\\').TrimEnd('/'); + } + var databaseName= this.Context.Ado.Connection.Database; + return CreateDatabase(databaseName,databaseDirectory); + } + /// + /// by databaseName + /// + /// + /// + /// + public virtual bool CreateDatabase(string databaseName, string databaseDirectory = null) + { + this.Context.Ado.ExecuteCommand(string.Format(CreateDataBaseSql, databaseName, databaseDirectory)); + return true; + } + + public virtual bool AddPrimaryKey(string tableName, string columnName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + columnName = this.SqlBuilder.GetTranslationTableName(columnName); + string sql = string.Format(this.AddPrimaryKeySql, tableName, string.Format("PK_{0}_{1}", this.SqlBuilder.GetNoTranslationColumnName(tableName), this.SqlBuilder.GetNoTranslationColumnName(columnName)), columnName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + + public bool AddPrimaryKeys(string tableName, string[] columnNames) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + var columnName = string.Join(",", columnNames); + string sql = string.Format(this.AddPrimaryKeySql, tableName, string.Format("PK_{0}_{1}", this.SqlBuilder.GetNoTranslationColumnName(columnNames.First()), this.SqlBuilder.GetNoTranslationColumnName(columnNames.First())), columnName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool AddColumn(string tableName, DbColumnInfo columnInfo) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string sql = GetAddColumnSql(tableName, columnInfo); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool UpdateColumn(string tableName, DbColumnInfo column) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string sql = GetUpdateColumnSql(tableName, column); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public abstract bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true); + public virtual bool DropTable(string tableName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + this.Context.Ado.ExecuteCommand(string.Format(this.DropTableSql, tableName)); + return true; + } + + public virtual bool TruncateTable() + { + this.Context.InitMappingInfo(); + return this.TruncateTable(this.Context.EntityMaintenance.GetEntityInfo().DbTableName); + } + public virtual bool DropColumn(string tableName, string columnName) + { + columnName = this.SqlBuilder.GetTranslationColumnName(columnName); + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + this.Context.Ado.ExecuteCommand(string.Format(this.DropColumnToTableSql, tableName, columnName)); + return true; + } + public virtual bool DropConstraint(string tableName, string constraintName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string sql = string.Format(this.DropConstraintSql, tableName, constraintName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool TruncateTable(string tableName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + this.Context.Ado.ExecuteCommand(string.Format(this.TruncateTableSql, tableName)); + return true; + } + public virtual bool BackupDataBase(string databaseName, string fullFileName) + { + var directory = FileHelper.GetDirectoryFromFilePath(fullFileName); + if (!FileHelper.IsExistDirectory(directory)) + { + FileHelper.CreateDirectory(directory); + } + this.Context.Ado.ExecuteCommand(string.Format(this.BackupDataBaseSql, databaseName, fullFileName)); + return true; + } + public virtual bool BackupTable(string oldTableName, string newTableName, int maxBackupDataRows = int.MaxValue) + { + oldTableName = this.SqlBuilder.GetTranslationTableName(oldTableName); + newTableName = this.SqlBuilder.GetTranslationTableName(newTableName); + string sql = string.Format(this.BackupTableSql, maxBackupDataRows, newTableName, oldTableName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool RenameColumn(string tableName, string oldColumnName, string newColumnName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + oldColumnName = this.SqlBuilder.GetTranslationColumnName(oldColumnName); + newColumnName = this.SqlBuilder.GetTranslationColumnName(newColumnName); + string sql = string.Format(this.RenameColumnSql, tableName, oldColumnName, newColumnName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool AddColumnRemark(string columnName, string tableName, string description) + { + string sql = string.Format(this.AddColumnRemarkSql, columnName, tableName, description); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool DeleteColumnRemark(string columnName, string tableName) + { + string sql = string.Format(this.DeleteColumnRemarkSql, columnName, tableName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool IsAnyColumnRemark(string columnName, string tableName) + { + string sql = string.Format(this.IsAnyColumnRemarkSql, columnName, tableName); + var dt=this.Context.Ado.GetDataTable(sql); + return dt.Rows!=null&&dt.Rows.Count>0; + } + public virtual bool AddTableRemark(string tableName, string description) + { + string sql = string.Format(this.AddTableRemarkSql,tableName, description); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool DeleteTableRemark(string tableName) + { + string sql = string.Format(this.DeleteTableRemarkSql,tableName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool IsAnyTableRemark(string tableName) + { + string sql = string.Format(this.IsAnyTableRemarkSql, tableName); + var dt=this.Context.Ado.GetDataTable(sql); + return dt.Rows != null && dt.Rows.Count > 0; + } + public virtual bool AddDefaultValue(string tableName, string columnName, string defaultValue) + { + if (defaultValue == "''") + { + defaultValue = ""; + } + string sql = string.Format(AddDefaultValueSql, tableName, columnName,defaultValue); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool CreateIndex(string tableName, string[] columnNames) + { + string sql = string.Format(CreateIndexSql,tableName,string.Join(",",columnNames), string.Join("_", columnNames)); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool IsAnyIndex(string indexName) + { + string sql = string.Format(this.IsAnyIndexSql, indexName); + return this.Context.Ado.GetInt(sql)>0; + } + public virtual bool AddRemark(EntityInfo entity) + { + var db = this.Context; + var columns = entity.Columns.Where(it => it.IsIgnore == false).ToList(); + + foreach (var item in columns) + { + if (item.ColumnDescription != null) + { + //column remak + if (db.DbMaintenance.IsAnyColumnRemark(item.DbColumnName, item.DbTableName)) + { + db.DbMaintenance.DeleteColumnRemark(item.DbColumnName, item.DbTableName); + db.DbMaintenance.AddColumnRemark(item.DbColumnName, item.DbTableName, item.ColumnDescription); + } + else + { + db.DbMaintenance.AddColumnRemark(item.DbColumnName, item.DbTableName, item.ColumnDescription); + } + } + } + + //table remak + if (entity.TableDescription != null) + { + if (db.DbMaintenance.IsAnyTableRemark(entity.DbTableName)) + { + db.DbMaintenance.DeleteTableRemark(entity.DbTableName); + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + else + { + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + } + return true; + } + + public virtual void AddIndex(EntityInfo entityInfo) + { + var db = this.Context; + var columns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToList(); + var indexColumns = columns.Where(it => it.IndexGroupNameList.HasValue()).ToList(); + if (indexColumns.HasValue()) + { + var groups = indexColumns.SelectMany(it => it.IndexGroupNameList).GroupBy(it => it).Select(it=>it.Key).ToList(); + foreach (var item in groups) + { + var columnNames = indexColumns.Where(it => it.IndexGroupNameList.Any(i => i.Equals(item, StringComparison.CurrentCultureIgnoreCase))).Select(it=>it.DbColumnName).ToArray(); + var indexName = string.Format("Index_{0}_{1}",entityInfo.DbTableName, string.Join("_", columnNames)); + if (!IsAnyIndex(indexName)) + { + CreateIndex(entityInfo.DbTableName, columnNames); + } + } + } + } + + protected virtual bool IsAnyDefaultValue(string tableName, string columnName,List columns) + { + var defaultValue = columns.Where(it => it.DbColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase)).First().DefaultValue; + return defaultValue.HasValue(); + } + + public virtual bool IsAnyDefaultValue(string tableName, string columnName) + { + return IsAnyDefaultValue(tableName, columnName, this.GetColumnInfosByTableName(tableName, false)); + } + + public virtual void AddDefaultValue(EntityInfo entityInfo) + { + var dbColumns=this.GetColumnInfosByTableName(entityInfo.DbTableName, false); + var db = this.Context; + var columns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToList(); + foreach (var item in columns) + { + if (item.DefaultValue.HasValue()) + { + if (!IsAnyDefaultValue(entityInfo.DbTableName,item.DbColumnName,dbColumns)) + { + this.AddDefaultValue(entityInfo.DbTableName, item.DbColumnName, item.DefaultValue); + } + } + } + } + + public virtual bool RenameTable(string oldTableName, string newTableName) + { + string sql = string.Format(this.RenameTableSql, oldTableName,newTableName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + #endregion + + #region Private + private List GetListOrCache(string cacheKey, string sql) + { + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + var isEnableLogEvent = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + var result = this.Context.Ado.SqlQuery(sql); + this.Context.Ado.IsEnableLogEvent = isEnableLogEvent; + return result; + }); + } + protected virtual string GetCreateTableSql(string tableName, List columns) + { + List columnArray = new List(); + Check.Exception(columns.IsNullOrEmpty(), "No columns found "); + foreach (var item in columns) + { + string columnName = this.SqlBuilder.GetTranslationTableName(item.DbColumnName); + string dataType = item.DataType; + string dataSize = GetSize(item); + string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string identity = item.IsIdentity ? this.CreateTableIdentity : null; + string addItem = string.Format(this.CreateTableColumn, columnName, dataType, dataSize, nullType, primaryKey, identity); + columnArray.Add(addItem); + } + string tableString = string.Format(this.CreateTableSql, this.SqlBuilder.GetTranslationTableName(tableName), string.Join(",\r\n", columnArray)); + return tableString; + } + protected virtual string GetAddColumnSql(string tableName, DbColumnInfo columnInfo) + { + string columnName = this.SqlBuilder.GetTranslationColumnName(columnInfo.DbColumnName); + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string dataType = columnInfo.DataType; + string dataSize = GetSize(columnInfo); + string nullType = columnInfo.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string identity = null; + string result = string.Format(this.AddColumnToTableSql, tableName, columnName, dataType, dataSize, nullType, primaryKey, identity); + return result; + } + protected virtual string GetUpdateColumnSql(string tableName, DbColumnInfo columnInfo) + { + string columnName = this.SqlBuilder.GetTranslationColumnName(columnInfo.DbColumnName); + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string dataSize = GetSize(columnInfo); + string dataType = columnInfo.DataType; + string nullType = columnInfo.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string identity = null; + string result = string.Format(this.AlterColumnToTableSql, tableName, columnName, dataType, dataSize, nullType, primaryKey, identity); + return result; + } + protected virtual string GetCacheKey(string cacheKey) + { + return this.Context.CurrentConnectionConfig.DbType + "." + this.Context.Ado.Connection.Database + "." + cacheKey; + } + protected virtual string GetSize(DbColumnInfo item) + { + string dataSize = null; + var isMax = item.Length > 4000 || item.Length == -1; + if (isMax) + { + dataSize = item.Length > 0 ? string.Format("({0})", "max") : null; + } + else if (item.Length == 0 && item.DecimalDigits > 0) + { + item.Length = 10; + dataSize = string.Format("({0},{1})", item.Length, item.DecimalDigits); + } + else if (item.Length > 0 && item.DecimalDigits == 0) + { + dataSize = item.Length > 0 ? string.Format("({0})", item.Length) : null; + } + else if (item.Length > 0 && item.DecimalDigits > 0) + { + dataSize = item.Length > 0 ? string.Format("({0},{1})", item.Length, item.DecimalDigits) : null; + } + return dataSize; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DbMaintenanceProvider/Properties.cs b/类库/SqlSugar/5.0.0.9/Abstract/DbMaintenanceProvider/Properties.cs new file mode 100644 index 0000000..c0e2eb7 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DbMaintenanceProvider/Properties.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public abstract partial class DbMaintenanceProvider : IDbMaintenance + { + #region Context + private ISqlBuilder _SqlBuilder; + public SqlSugarProvider Context { get; set; } + public ISqlBuilder SqlBuilder + { + get + { + if (_SqlBuilder == null) + { + _SqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + _SqlBuilder.Context = this.Context; + } + return _SqlBuilder; + } + } + #endregion + + #region DML + protected abstract string GetViewInfoListSql { get; } + protected abstract string GetDataBaseSql { get; } + protected abstract string GetTableInfoListSql { get; } + protected abstract string GetColumnInfosByTableNameSql { get; } + #endregion + + #region DDL + protected abstract string CreateIndexSql { get; } + protected abstract string IsAnyIndexSql { get; } + protected abstract string AddDefaultValueSql { get; } + protected abstract string CreateDataBaseSql { get; } + protected abstract string AddColumnToTableSql { get; } + protected abstract string AlterColumnToTableSql { get; } + protected abstract string BackupDataBaseSql { get; } + protected abstract string CreateTableSql { get; } + protected abstract string CreateTableColumn { get; } + protected abstract string BackupTableSql { get; } + protected abstract string TruncateTableSql { get; } + protected abstract string DropTableSql { get; } + protected abstract string DropColumnToTableSql { get; } + protected abstract string DropConstraintSql { get; } + protected abstract string AddPrimaryKeySql { get; } + protected abstract string RenameColumnSql { get; } + protected abstract string AddColumnRemarkSql { get; } + protected abstract string DeleteColumnRemarkSql { get; } + protected abstract string IsAnyColumnRemarkSql { get; } + protected abstract string AddTableRemarkSql { get; } + protected abstract string DeleteTableRemarkSql { get; } + protected abstract string IsAnyTableRemarkSql { get; } + protected abstract string RenameTableSql { get; } + #endregion + + #region Check + protected abstract string CheckSystemTablePermissionsSql { get; } + #endregion + + #region Scattered + protected abstract string CreateTableNull { get; } + protected abstract string CreateTableNotNull { get; } + protected abstract string CreateTablePirmaryKey { get; } + protected abstract string CreateTableIdentity { get; } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/DeleteProvider/DeleteableProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/DeleteProvider/DeleteableProvider.cs new file mode 100644 index 0000000..823cd8c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/DeleteProvider/DeleteableProvider.cs @@ -0,0 +1,442 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class DeleteableProvider : IDeleteable where T : class, new() + { + public ISqlSugarClient Context { get; set; } + public IAdo Db { get { return Context.Ado; } } + public ISqlBuilder SqlBuilder { get; set; } + public DeleteBuilder DeleteBuilder { get; set; } + public MappingTableList OldMappingTableList { get; set; } + public bool IsAs { get; set; } + public bool IsEnableDiffLogEvent { get; set; } + public DiffLogModel diffModel { get; set; } + public List tempPrimaryKeys { get; set; } + private Action RemoveCacheFunc { get; set; } + public EntityInfo EntityInfo + { + get + { + return this.Context.EntityMaintenance.GetEntityInfo(); + } + } + public void AddQueue() + { + var sqlObj = this.ToSql(); + this.Context.Queues.Add(sqlObj.Key, sqlObj.Value); + } + public int ExecuteCommand() + { + string sql; + SugarParameter[] paramters; + _ExecuteCommand(out sql, out paramters); + var result = Db.ExecuteCommand(sql, paramters); + After(sql); + return result; + } + public bool ExecuteCommandHasChange() + { + return ExecuteCommand() > 0; + } + public async Task ExecuteCommandAsync() + { + string sql; + SugarParameter[] paramters; + _ExecuteCommand(out sql, out paramters); + var result =await Db.ExecuteCommandAsync(sql, paramters); + After(sql); + return result; + } + public async Task ExecuteCommandHasChangeAsync() + { + return await ExecuteCommandAsync() > 0; + } + public IDeleteable AS(string tableName) + { + var entityName = typeof(T).Name; + IsAs = true; + OldMappingTableList = this.Context.MappingTables; + this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); + if (this.Context.MappingTables.Any(it => it.EntityName == entityName)) + { + this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName); + } + this.Context.MappingTables.Add(entityName, tableName); + return this; ; + } + + public IDeleteable EnableDiffLogEvent(object businessData = null) + { + + diffModel = new DiffLogModel(); + this.IsEnableDiffLogEvent = true; + diffModel.BusinessData = businessData; + diffModel.DiffType = DiffType.delete; + return this; + } + + public IDeleteable Where(List deleteObjs) + { + if (deleteObjs == null || deleteObjs.Count() == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + string tableName = this.Context.EntityMaintenance.GetTableName(); + var primaryFields = this.GetPrimaryKeys(); + var isSinglePrimaryKey = primaryFields.Count == 1; + Check.Exception(primaryFields.IsNullOrEmpty(), string.Format("Table {0} with no primarykey", tableName)); + if (isSinglePrimaryKey) + { + List primaryKeyValues = new List(); + var primaryField = primaryFields.Single(); + foreach (var deleteObj in deleteObjs) + { + var entityPropertyName = this.Context.EntityMaintenance.GetPropertyName(primaryField); + var columnInfo = EntityInfo.Columns.Single(it => it.PropertyName.Equals(entityPropertyName, StringComparison.CurrentCultureIgnoreCase)); + var value = columnInfo.PropertyInfo.GetValue(deleteObj, null); + primaryKeyValues.Add(value); + } + if (primaryKeyValues.Count < 10000) + { + var inValueString = primaryKeyValues.ToArray().ToJoinSqlInVals(); + Where(string.Format(DeleteBuilder.WhereInTemplate, SqlBuilder.GetTranslationColumnName(primaryFields.Single()), inValueString)); + } + else + { + if (DeleteBuilder.BigDataInValues == null) + DeleteBuilder.BigDataInValues = new List(); + DeleteBuilder.BigDataInValues.AddRange(primaryKeyValues); + DeleteBuilder.BigDataFiled = primaryField; + } + } + else + { + StringBuilder whereInSql = new StringBuilder(); + foreach (var deleteObj in deleteObjs) + { + StringBuilder orString = new StringBuilder(); + var isFirst = deleteObjs.IndexOf(deleteObj) == 0; + if (!isFirst) + { + orString.Append(DeleteBuilder.WhereInOrTemplate + UtilConstants.Space); + } + int i = 0; + StringBuilder andString = new StringBuilder(); + foreach (var primaryField in primaryFields) + { + if (i != 0) + andString.Append(DeleteBuilder.WhereInAndTemplate + UtilConstants.Space); + var entityPropertyName = this.Context.EntityMaintenance.GetPropertyName(primaryField); + var columnInfo = EntityInfo.Columns.Single(it => it.PropertyName == entityPropertyName); + var entityValue = columnInfo.PropertyInfo.GetValue(deleteObj, null); + if (this.Context.CurrentConnectionConfig.DbType == DbType.Oracle) + { + andString.AppendFormat(DeleteBuilder.WhereInEqualTemplate, primaryField.ToUpper(), entityValue); + } + else + { + andString.AppendFormat(DeleteBuilder.WhereInEqualTemplate, primaryField, entityValue); + } + ++i; + } + orString.AppendFormat(DeleteBuilder.WhereInAreaTemplate, andString); + whereInSql.Append(orString); + } + Where(string.Format(DeleteBuilder.WhereInAreaTemplate, whereInSql.ToString())); + } + return this; + } + + public IDeleteable Where(Expression> expression) + { + var expResult = DeleteBuilder.GetExpressionValue(expression, ResolveExpressType.WhereSingle); + var whereString = expResult.GetResultString(); + if (expression.ToString().Contains("Subqueryable()")){ + whereString = whereString.Replace(this.SqlBuilder.GetTranslationColumnName(expression.Parameters.First().Name) + ".",this.SqlBuilder.GetTranslationTableName(this.EntityInfo.DbTableName) + "."); + } + DeleteBuilder.WhereInfos.Add(whereString); + return this; + } + + public IDeleteable Where(T deleteObj) + { + Check.Exception(GetPrimaryKeys().IsNullOrEmpty(), "Where(entity) Primary key required"); + Where(new List() { deleteObj }); + return this; + } + + public IDeleteable Where(string whereString, object parameters = null) + { + DeleteBuilder.WhereInfos.Add(whereString); + if (parameters != null) + { + if (DeleteBuilder.Parameters == null) + { + DeleteBuilder.Parameters = new List(); + } + DeleteBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + } + return this; + } + + public IDeleteable Where(string whereString, SugarParameter parameter) + { + DeleteBuilder.Parameters.Add(parameter); + return this; + } + public IDeleteable Where(string whereString, SugarParameter[] parameters) + { + DeleteBuilder.Parameters.AddRange(parameters); + return this; + } + public IDeleteable Where(string whereString, List parameters) + { + DeleteBuilder.Parameters.AddRange(parameters); + return this; + } + + public IDeleteable RemoveDataCache() + { + this.RemoveCacheFunc = () => + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + CacheSchemeMain.RemoveCache(cacheService, this.Context.EntityMaintenance.GetTableName()); + }; + return this; + } + + public IDeleteable In(List primaryKeyValues) + { + if (primaryKeyValues == null || primaryKeyValues.Count() == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + return In(primaryKeyValues.ToArray()); + } + + public IDeleteable In(PkType[] primaryKeyValues) + { + if (primaryKeyValues == null || primaryKeyValues.Count() == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + string tableName = this.Context.EntityMaintenance.GetTableName(); + string primaryField = null; + primaryField = GetPrimaryKeys().FirstOrDefault(); + Check.ArgumentNullException(primaryField, "Table " + tableName + " with no primarykey"); + if (primaryKeyValues.Length < 10000) + { + Where(string.Format(DeleteBuilder.WhereInTemplate, SqlBuilder.GetTranslationColumnName(primaryField), primaryKeyValues.ToJoinSqlInVals())); + } + else + { + if (DeleteBuilder.BigDataInValues == null) + DeleteBuilder.BigDataInValues = new List(); + DeleteBuilder.BigDataInValues.AddRange(primaryKeyValues.Select(it => (object)it)); + DeleteBuilder.BigDataFiled = primaryField; + } + return this; + } + + public IDeleteable In(PkType primaryKeyValue) + { + if (typeof(PkType).FullName.IsCollectionsList()) + { + var newValues = new List(); + foreach (var item in primaryKeyValue as IEnumerable) + { + newValues.Add(item); + } + return In(newValues); + } + + + In(new PkType[] { primaryKeyValue }); + return this; + } + + public IDeleteable In(Expression> inField, PkType primaryKeyValue) + { + var lamResult = DeleteBuilder.GetExpressionValue(inField, ResolveExpressType.FieldSingle); + var fieldName = lamResult.GetResultString(); + tempPrimaryKeys = new List() { fieldName }; + var result = In(primaryKeyValue);; + tempPrimaryKeys = null; + return this; + } + public IDeleteable In(Expression> inField, PkType[] primaryKeyValues) + { + var lamResult = DeleteBuilder.GetExpressionValue(inField, ResolveExpressType.FieldSingle); + var fieldName = lamResult.GetResultString(); + tempPrimaryKeys = new List() { fieldName }; + var result = In(primaryKeyValues); + tempPrimaryKeys = null; + return this; + } + public IDeleteable In(Expression> inField, List primaryKeyValues) + { + var lamResult = DeleteBuilder.GetExpressionValue(inField, ResolveExpressType.FieldSingle); + var fieldName = lamResult.GetResultString(); + tempPrimaryKeys = new List() { fieldName }; + var result = In(primaryKeyValues); + tempPrimaryKeys = null; + return this; + } + + public IDeleteable With(string lockString) + { + if (this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer) + DeleteBuilder.TableWithString = lockString; + return this; + } + + public KeyValuePair> ToSql() + { + DeleteBuilder.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); + string sql = DeleteBuilder.ToSqlString(); + var paramters = DeleteBuilder.Parameters == null ? null : DeleteBuilder.Parameters.ToList(); + RestoreMapping(); + return new KeyValuePair>(sql, paramters); + } + + private List GetPrimaryKeys() + { + if (tempPrimaryKeys.HasValue()) + { + return tempPrimaryKeys; + } + else if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + private void _ExecuteCommand(out string sql, out SugarParameter[] paramters) + { + DeleteBuilder.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); + sql = DeleteBuilder.ToSqlString(); + paramters = DeleteBuilder.Parameters == null ? null : DeleteBuilder.Parameters.ToArray(); + RestoreMapping(); + AutoRemoveDataCache(); + Before(sql); + } + + protected virtual List GetIdentityKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetIsIdentities(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); + } + } + + private void RestoreMapping() + { + if (IsAs) + { + this.Context.MappingTables = OldMappingTableList; + } + } + + //private void TaskStart(Task result) + //{ + // if (this.Context.CurrentConnectionConfig.IsShardSameThread) + // { + // Check.Exception(true, "IsShardSameThread=true can't be used async method"); + // } + // result.Start(); + //} + + private void AutoRemoveDataCache() + { + var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (moreSetts != null && moreSetts.IsAutoRemoveDataCache && extService != null && extService.DataInfoCacheService != null) + { + this.RemoveDataCache(); + } + } + + + private void After(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation; + this.Context.Ado.IsDisableMasterSlaveSeparation = true; + var parameters = DeleteBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.AfterData = null; + diffModel.Time = this.Context.Ado.SqlExecutionTime; + if (this.Context.CurrentConnectionConfig.AopEvents.OnDiffLogEvent != null) + this.Context.CurrentConnectionConfig.AopEvents.OnDiffLogEvent(diffModel); + this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + } + if (this.RemoveCacheFunc != null) { + this.RemoveCacheFunc(); + } + } + + private void Before(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation; + this.Context.Ado.IsDisableMasterSlaveSeparation = true; + var parameters = DeleteBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.BeforeData = GetDiffTable(sql, parameters); + diffModel.Sql = sql; + diffModel.Parameters = parameters.ToArray(); + this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + } + } + + private List GetDiffTable(string sql, List parameters) + { + List result = new List(); + var whereSql = Regex.Replace(sql, ".* WHERE ", "", RegexOptions.Singleline); + var dt = this.Context.Queryable().Where(whereSql).AddParameters(parameters).ToDataTable(); + if (dt.Rows != null && dt.Rows.Count > 0) + { + foreach (DataRow row in dt.Rows) + { + DiffLogTableInfo item = new DiffLogTableInfo(); + item.TableDescription = this.EntityInfo.TableDescription; + item.TableName = this.EntityInfo.DbTableName; + item.Columns = new List(); + foreach (DataColumn col in dt.Columns) + { + DiffLogColumnInfo addItem = new DiffLogColumnInfo(); + addItem.Value = row[col.ColumnName]; + addItem.ColumnName = col.ColumnName; + addItem.ColumnDescription = this.EntityInfo.Columns.First(it => it.DbColumnName.Equals(col.ColumnName, StringComparison.CurrentCultureIgnoreCase)).ColumnDescription; + item.Columns.Add(addItem); + } + result.Add(item); + } + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/EntityMaintenance/EntityMaintenance.cs b/类库/SqlSugar/5.0.0.9/Abstract/EntityMaintenance/EntityMaintenance.cs new file mode 100644 index 0000000..21016b9 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/EntityMaintenance/EntityMaintenance.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class EntityMaintenance + { + public SqlSugarProvider Context { get; set; } + + public EntityInfo GetEntityInfo() + { + return GetEntityInfo(typeof(T)); + } + public EntityInfo GetEntityInfo(Type type) + { + string cacheKey = "GetEntityInfo" + type.FullName; + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + EntityInfo result = new EntityInfo(); + var sugarAttributeInfo = type.GetTypeInfo().GetCustomAttributes(typeof(SugarTable), true).Where(it => it is SugarTable).SingleOrDefault(); + if (sugarAttributeInfo.HasValue()) + { + var sugarTable = (SugarTable)sugarAttributeInfo; + result.DbTableName = sugarTable.TableName; + result.TableDescription = sugarTable.TableDescription; + } + if (this.Context.Context.CurrentConnectionConfig.ConfigureExternalServices != null && this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityNameService != null) { + if (result.DbTableName == null) + { + result.DbTableName = type.Name; + } + this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityNameService(type,result); + } + result.Type = type; + result.EntityName = result.Type.Name; + result.Columns = new List(); + SetColumns(result); + return result; + }); + } + public string GetTableName() + { + var typeName = typeof(T).Name; + if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) + { + var entity = this.GetEntityInfo(); + if (entity.DbTableName.HasValue()) return entity.DbTableName; + else return entity.EntityName; + } + else + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == typeName); + return mappingInfo == null ? typeName : mappingInfo.DbTableName; + } + } + public string GetTableName(Type entityType) + { + var typeName = entityType.Name; + if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) + { + var entity = this.GetEntityInfo(entityType); + if (entity.DbTableName.HasValue()) return entity.DbTableName; + else return entity.EntityName; + } + else + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == typeName); + return mappingInfo == null ? typeName : mappingInfo.DbTableName; + } + } + public string GetTableName(string entityName) + { + var typeName = entityName; + if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) return typeName; + else + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == typeName); + return mappingInfo == null ? typeName : mappingInfo.DbTableName; + } + } + public string GetEntityName(string tableName) + { + if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) return tableName; + else + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.DbTableName == tableName); + return mappingInfo == null ? tableName : mappingInfo.EntityName; + } + } + public string GetDbColumnName(string propertyName) + { + var isAny = this.GetEntityInfo().Columns.Any(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + Check.Exception(!isAny, "Property " + propertyName + " is Invalid"); + var typeName = typeof(T).Name; + if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) + { + var column= this.GetEntityInfo().Columns.First(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + if (column.DbColumnName.HasValue()) return column.DbColumnName; + else return column.PropertyName; + } + else + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.PropertyName == propertyName); + return mappingInfo == null ? propertyName : mappingInfo.DbColumnName; + } + } + public string GetDbColumnName(string propertyName,Type entityType) + { + var isAny = this.GetEntityInfo(entityType).Columns.Any(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + Check.Exception(!isAny, "Property " + propertyName + " is Invalid"); + var typeName = entityType.Name; + if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) + { + var column = this.GetEntityInfo(entityType).Columns.First(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + if (column.DbColumnName.HasValue()) return column.DbColumnName; + else return column.PropertyName; + } + else + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.PropertyName == propertyName); + return mappingInfo == null ? propertyName : mappingInfo.DbColumnName; + } + } + public string GetPropertyName(string dbColumnName) + { + var typeName = typeof(T).Name; + if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) return dbColumnName; + else + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.DbColumnName.Equals(dbColumnName,StringComparison.CurrentCultureIgnoreCase)); + return mappingInfo == null ? dbColumnName : mappingInfo.PropertyName; + } + } + public string GetPropertyName(string dbColumnName,Type entityType) + { + var typeName = entityType.Name; + if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) return dbColumnName; + else + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.DbColumnName.Equals(dbColumnName,StringComparison.CurrentCultureIgnoreCase)); + return mappingInfo == null ? dbColumnName : mappingInfo.PropertyName; + } + } + public PropertyInfo GetProperty(string dbColumnName) + { + var propertyName = GetPropertyName(dbColumnName); + return typeof(T).GetProperties().First(it => it.Name == propertyName); + } + #region Primary key + private void SetColumns(EntityInfo result) + { + foreach (var property in result.Type.GetProperties()) + { + EntityColumnInfo column = new EntityColumnInfo(); + //var isVirtual = property.GetGetMethod().IsVirtual; + //if (isVirtual) continue; + var sugarColumn = property.GetCustomAttributes(typeof(SugarColumn), true) + .Where(it => it is SugarColumn) + .Select(it => (SugarColumn)it) + .FirstOrDefault(); + column.DbTableName = result.DbTableName; + column.EntityName = result.EntityName; + column.PropertyName = property.Name; + column.PropertyInfo = property; + if (sugarColumn.IsNullOrEmpty()) + { + column.DbColumnName = property.Name; + } + else + { + if (sugarColumn.IsIgnore == false) + { + column.DbColumnName = sugarColumn.ColumnName.IsNullOrEmpty() ? property.Name : sugarColumn.ColumnName; + column.IsPrimarykey = sugarColumn.IsPrimaryKey; + column.IsIdentity = sugarColumn.IsIdentity; + column.ColumnDescription = sugarColumn.ColumnDescription; + column.IsNullable = sugarColumn.IsNullable; + column.Length = sugarColumn.Length; + column.OldDbColumnName = sugarColumn.OldColumnName; + column.DataType = sugarColumn.ColumnDataType; + column.DecimalDigits = sugarColumn.DecimalDigits; + column.OracleSequenceName = sugarColumn.OracleSequenceName; + column.IsOnlyIgnoreInsert = sugarColumn.IsOnlyIgnoreInsert; + column.IsEnableUpdateVersionValidation = sugarColumn.IsEnableUpdateVersionValidation; + column.IsTranscoding = sugarColumn.IsTranscoding; + column.SerializeDateTimeFormat = sugarColumn.SerializeDateTimeFormat; + column.IsJson = sugarColumn.IsJson; + column.NoSerialize = sugarColumn.NoSerialize; + column.DefaultValue = sugarColumn.DefaultValue; + column.IndexGroupNameList = sugarColumn.IndexGroupNameList; + column.IsOnlyIgnoreUpdate = sugarColumn.IsOnlyIgnoreUpdate; + } + else + { + column.IsIgnore = true; + column.NoSerialize = sugarColumn.NoSerialize; + } + } + if (this.Context.MappingColumns.HasValue()) + { + var golbalMappingInfo = this.Context.MappingColumns.FirstOrDefault(it => it.EntityName.Equals(result.EntityName, StringComparison.CurrentCultureIgnoreCase) && it.PropertyName == column.PropertyName); + if (golbalMappingInfo != null) + column.DbColumnName = golbalMappingInfo.DbColumnName; + } + if (this.Context.IgnoreColumns.HasValue()) + { + var golbalMappingInfo = this.Context.IgnoreColumns.FirstOrDefault(it => it.EntityName.Equals(result.EntityName, StringComparison.CurrentCultureIgnoreCase) && it.PropertyName == column.PropertyName); + if (golbalMappingInfo != null) + column.IsIgnore = true; + } + if (this.Context.CurrentConnectionConfig.ConfigureExternalServices != null && this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityService != null) { + this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityService(property, column); + } + result.Columns.Add(column); + } + } + #endregion + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/ExpressionableProvider/Expressionable.cs b/类库/SqlSugar/5.0.0.9/Abstract/ExpressionableProvider/Expressionable.cs new file mode 100644 index 0000000..b4f0958 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/ExpressionableProvider/Expressionable.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class Expressionable where T : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = it => true; + return _exp; + } + } + public class Expressionable where T : class, new() where T2 : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it, t2) => true; + return _exp; + } + } + public class Expressionable where T : class, new() where T2 : class, new() where T3 : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it, t2, t3) => true; + return _exp; + } + } + public class Expressionable where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it, t2, t3, t4) => true; + return _exp; + } + } + public class Expressionable where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it, t2, t3, t4, T5) => true; + return _exp; + } + } + + public class Expressionable where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it, t2, t3, t4, T5, t6) => true; + return _exp; + } + } + public class Expressionable + { + public static Expressionable Create() where T : class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() where T3 : class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5 : class, new() where T6 : class, new() + { + return new Expressionable(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/FilterProvider/FilterProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/FilterProvider/FilterProvider.cs new file mode 100644 index 0000000..ff28e05 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/FilterProvider/FilterProvider.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class QueryFilterProvider : IFilter + { + internal SqlSugarProvider Context { get; set; } + private List _Filters { get; set; } + + public IFilter Add(SqlFilterItem filter) + { + if (_Filters == null) + _Filters = new List(); + if (this.Context.CurrentConnectionConfig.IsShardSameThread) + { + if (!_Filters.Select(it => it.FilterValue(this.Context).Sql).Contains(filter.FilterValue(this.Context).Sql)) + _Filters.Add(filter); + } + else + { + _Filters.Add(filter); + } + return this; + } + + public void Remove(string filterName) + { + if (_Filters == null) + _Filters = new List(); + _Filters.RemoveAll(it => it.FilterName == filterName); + } + + public List GeFilterList + { + get + { + if (_Filters == null) + _Filters = new List(); + return _Filters; + } + } + public void Clear() + { + _Filters = new List(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/InsertableProvider/InsertableProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/InsertableProvider/InsertableProvider.cs new file mode 100644 index 0000000..02f8d88 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/InsertableProvider/InsertableProvider.cs @@ -0,0 +1,615 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class InsertableProvider : IInsertable where T : class, new() + { + public SqlSugarProvider Context { get; set; } + public IAdo Ado { get { return Context.Ado; } } + public ISqlBuilder SqlBuilder { get; set; } + public InsertBuilder InsertBuilder { get; set; } + + public bool IsMappingTable { get { return this.Context.MappingTables != null && this.Context.MappingTables.Any(); } } + public bool IsMappingColumns { get { return this.Context.MappingColumns != null && this.Context.MappingColumns.Any(); } } + public bool IsSingle { get { return this.InsertObjs.Length == 1; } } + + public EntityInfo EntityInfo { get; set; } + public List MappingColumnList { get; set; } + private List IgnoreColumnNameList { get; set; } + private bool IsOffIdentity { get; set; } + public T[] InsertObjs { get; set; } + + public MappingTableList OldMappingTableList { get; set; } + public bool IsAs { get; set; } + public bool IsEnableDiffLogEvent { get; set; } + public DiffLogModel diffModel { get; set; } + private Action RemoveCacheFunc { get; set; } + + + #region Core + public void AddQueue() + { + var sqlObj = this.ToSql(); + this.Context.Queues.Add(sqlObj.Key, sqlObj.Value); + } + public virtual int ExecuteCommand() + { + if (this.InsertObjs.Count() == 1 && this.InsertObjs.First() == null) + { + return 0; + } + string sql = _ExecuteCommand(); + var result = Ado.ExecuteCommand(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + After(sql, null); + return result; + } + public virtual KeyValuePair> ToSql() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + AutoRemoveDataCache(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + return new KeyValuePair>(sql, InsertBuilder.Parameters); + } + public virtual int ExecuteReturnIdentity() + { + if (this.InsertObjs.Count() == 1 && this.InsertObjs.First() == null) + { + return 0; + } + string sql = _ExecuteReturnIdentity(); + var result = Ado.GetInt(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + After(sql, result); + return result; + } + + public virtual long ExecuteReturnBigIdentity() + { + if (this.InsertObjs.Count() == 1 && this.InsertObjs.First() == null) + { + return 0; + } + string sql = _ExecuteReturnBigIdentity(); + var result = Convert.ToInt64(Ado.GetScalar(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray())); + After(sql, result); + return result; + } + + + + public virtual T ExecuteReturnEntity() + { + ExecuteCommandIdentityIntoEntity(); + return InsertObjs.First(); + } + public virtual bool ExecuteCommandIdentityIntoEntity() + { + var result = InsertObjs.First(); + var identityKeys = GetIdentityKeys(); + if (identityKeys.Count == 0) { return this.ExecuteCommand() > 0; } + var idValue = ExecuteReturnBigIdentity(); + Check.Exception(identityKeys.Count > 1, "ExecuteCommandIdentityIntoEntity does not support multiple identity keys"); + var identityKey = identityKeys.First(); + object setValue = 0; + if (idValue > int.MaxValue) + setValue = idValue; + else + setValue = Convert.ToInt32(idValue); + this.Context.EntityMaintenance.GetProperty(identityKey).SetValue(result, setValue, null); + return idValue > 0; + } + + public async Task ExecuteCommandAsync() + { + if (this.InsertObjs.Count() == 1 && this.InsertObjs.First() == null) + { + return 0; + } + string sql = _ExecuteCommand(); + var result =await Ado.ExecuteCommandAsync(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + After(sql, null); + return result; + } + public virtual async Task ExecuteReturnIdentityAsync() + { + if (this.InsertObjs.Count() == 1 && this.InsertObjs.First() == null) + { + return 0; + } + string sql = _ExecuteReturnIdentity(); + var result =await Ado.GetIntAsync(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + After(sql, result); + return result; + } + public async Task ExecuteReturnEntityAsync() + { + await ExecuteCommandIdentityIntoEntityAsync(); + return InsertObjs.First(); + } + public async Task ExecuteCommandIdentityIntoEntityAsync() + { + var result = InsertObjs.First(); + var identityKeys = GetIdentityKeys(); + if (identityKeys.Count == 0) { return await this.ExecuteCommandAsync() > 0; } + var idValue =await ExecuteReturnBigIdentityAsync(); + Check.Exception(identityKeys.Count > 1, "ExecuteCommandIdentityIntoEntity does not support multiple identity keys"); + var identityKey = identityKeys.First(); + object setValue = 0; + if (idValue > int.MaxValue) + setValue = idValue; + else + setValue = Convert.ToInt32(idValue); + this.Context.EntityMaintenance.GetProperty(identityKey).SetValue(result, setValue, null); + return idValue > 0; + } + public virtual async Task ExecuteReturnBigIdentityAsync() + { + if (this.InsertObjs.Count() == 1 && this.InsertObjs.First() == null) + { + return 0; + } + string sql = _ExecuteReturnBigIdentity(); + var result = Convert.ToInt64(await Ado.GetScalarAsync(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray())); + After(sql, result); + return result; + } + #endregion + + #region Setting + public IInsertable AS(string tableName) + { + var entityName = typeof(T).Name; + IsAs = true; + OldMappingTableList = this.Context.MappingTables; + this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); + if (this.Context.MappingTables.Any(it => it.EntityName == entityName)) + { + this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName); + } + this.Context.MappingTables.Add(entityName, tableName); + return this; ; + } + public IInsertable IgnoreColumns(Expression> columns) + { + var ignoreColumns = InsertBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it)).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => !ignoreColumns.Any(ig => ig.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => !ignoreColumns.Any(ig => ig.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + return this; + } + public IInsertable IgnoreColumns(params string[] columns) + { + if (columns == null) + columns = new string[] { }; + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => !columns.Any(ig => ig.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + return this; + } + + public IInsertable InsertColumns(Expression> columns) + { + var ignoreColumns = InsertBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it)).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => ignoreColumns.Any(ig => ig.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + return this; + } + + public IInsertable InsertColumns(string[] columns) + { + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => columns.Any(ig => ig.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + return this; + } + + public IInsertable With(string lockString) + { + if (this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer) + this.InsertBuilder.TableWithString = lockString; + return this; + } + public IInsertable IgnoreColumns(bool ignoreNullColumn, bool isOffIdentity = false) { + Check.Exception(this.InsertObjs.Count() > 1&& ignoreNullColumn, ErrorMessage.GetThrowMessage("ignoreNullColumn NoSupport batch insert", "ignoreNullColumn 不支持批量操作")); + this.IsOffIdentity = isOffIdentity; + if (this.InsertBuilder.LambdaExpressions == null) + this.InsertBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.Context.CurrentConnectionConfig); + this.InsertBuilder.IsNoInsertNull = ignoreNullColumn; + return this; + } + + public IInsertable RemoveDataCache() + { + this.RemoveCacheFunc = () => + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + CacheSchemeMain.RemoveCache(cacheService, this.Context.EntityMaintenance.GetTableName()); + }; + return this; + } + public IInsertable EnableDiffLogEvent(object businessData = null) + { + Check.Exception(this.InsertObjs.HasValue() && this.InsertObjs.Count() > 1, "DiffLog does not support batch operations"); + diffModel = new DiffLogModel(); + this.IsEnableDiffLogEvent = true; + diffModel.BusinessData = businessData; + diffModel.DiffType = DiffType.insert; + return this; + } + #endregion + + #region Protected Methods + private string _ExecuteReturnBigIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + AutoRemoveDataCache(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + Before(sql); + return sql; + } + private string _ExecuteReturnIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + AutoRemoveDataCache(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + Before(sql); + return sql; + } + + private string _ExecuteCommand() + { + if (InsertBuilder.DbColumnInfoList.HasValue()) + { + var pks = GetPrimaryKeys(); + foreach (var item in InsertBuilder.DbColumnInfoList) + { + var isPk = pks.Any(y => y.Equals(item.DbColumnName, StringComparison.CurrentCultureIgnoreCase)) || item.IsPrimarykey; + if (isPk && item.PropertyType == UtilConstants.GuidType && item.Value.ObjToString() == Guid.Empty.ToString()) + { + item.Value = Guid.NewGuid(); + if (InsertObjs.First().GetType().GetProperties().Any(it => it.Name == item.PropertyName)) + InsertObjs.First().GetType().GetProperties().First(it => it.Name == item.PropertyName).SetValue(InsertObjs.First(), item.Value, null); + } + } + } + InsertBuilder.IsReturnIdentity = false; + PreToSql(); + AutoRemoveDataCache(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + Before(sql); + return sql; + } + private void AutoRemoveDataCache() + { + var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (moreSetts != null && moreSetts.IsAutoRemoveDataCache && extService != null && extService.DataInfoCacheService != null) + { + this.RemoveDataCache(); + } + } + protected virtual void PreToSql() + { + #region Identities + if (!IsOffIdentity) + { + List identities = GetIdentityKeys(); + if (identities != null && identities.Any()) + { + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => + { + return !identities.Any(i => it.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + }).ToList(); + } + } + #endregion + + #region IgnoreColumns + if (this.Context.IgnoreColumns != null && this.Context.IgnoreColumns.Any()) + { + var currentIgnoreColumns = this.Context.IgnoreColumns.Where(it => it.EntityName == this.EntityInfo.EntityName).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => + { + return !currentIgnoreColumns.Any(i => it.PropertyName.Equals(i.PropertyName, StringComparison.CurrentCulture)); + }).ToList(); + } + + if (this.Context.IgnoreInsertColumns != null && this.Context.IgnoreInsertColumns.Any()) + { + var currentIgnoreColumns = this.Context.IgnoreInsertColumns.Where(it => it.EntityName == this.EntityInfo.EntityName).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => + { + return !currentIgnoreColumns.Any(i => it.PropertyName.Equals(i.PropertyName, StringComparison.CurrentCulture)); + }).ToList(); + } + #endregion + if (this.IsSingle) + { + foreach (var item in this.InsertBuilder.DbColumnInfoList) + { + if (this.InsertBuilder.Parameters == null) this.InsertBuilder.Parameters = new List(); + var paramters = new SugarParameter(this.SqlBuilder.SqlParameterKeyWord + item.DbColumnName, item.Value, item.PropertyType); + if (InsertBuilder.IsNoInsertNull && paramters.Value == null) + { + continue; + } + this.InsertBuilder.Parameters.Add(paramters); + } + } + } + internal void Init() + { + InsertBuilder.EntityInfo = this.EntityInfo; + Check.Exception(InsertObjs == null || InsertObjs.Count() == 0, "InsertObjs is null"); + int i = 0; + foreach (var item in InsertObjs) + { + List insertItem = new List(); + if (item is Dictionary) + { + SetInsertItemByDic(i, item, insertItem); + } + else + { + SetInsertItemByEntity(i, item, insertItem); + } + this.InsertBuilder.DbColumnInfoList.AddRange(insertItem); + ++i; + } + } + private void SetInsertItemByDic(int i, T item, List insertItem) + { + foreach (var column in item as Dictionary) + { + var columnInfo = new DbColumnInfo() + { + Value = column.Value, + DbColumnName = column.Key, + PropertyName = column.Key, + PropertyType = column.Value == null ? DBNull.Value.GetType() : UtilMethods.GetUnderType(column.Value.GetType()), + TableId = i + }; + if (columnInfo.PropertyType.IsEnum()) + { + columnInfo.Value = Convert.ToInt64(columnInfo.Value); + } + insertItem.Add(columnInfo); + } + } + private void SetInsertItemByEntity(int i, T item, List insertItem) + { + if (item == null) + { + return; + } + foreach (var column in EntityInfo.Columns) + { + if (column.IsIgnore || column.IsOnlyIgnoreInsert) continue; + var columnInfo = new DbColumnInfo() + { + Value = column.PropertyInfo.GetValue(item, null), + DbColumnName = GetDbColumnName(column.PropertyName), + PropertyName = column.PropertyName, + PropertyType = UtilMethods.GetUnderType(column.PropertyInfo), + TableId = i + }; + if (columnInfo.PropertyType.IsEnum()) + { + columnInfo.Value = Convert.ToInt64(columnInfo.Value); + } + if (column.IsJson&& columnInfo.Value!=null) + { + columnInfo.Value = this.Context.Utilities.SerializeObject(columnInfo.Value); + } + var tranColumn=EntityInfo.Columns.FirstOrDefault(it => it.IsTranscoding && it.DbColumnName.Equals(column.DbColumnName, StringComparison.CurrentCultureIgnoreCase)); + if (tranColumn!=null&&columnInfo.Value.HasValue()) { + columnInfo.Value = UtilMethods.EncodeBase64(columnInfo.Value.ToString()); + } + insertItem.Add(columnInfo); + } + } + + private string GetDbColumnName(string propertyName) + { + if (!IsMappingColumns) + { + return propertyName; + } + if (this.Context.MappingColumns.Any(it => it.EntityName.Equals(EntityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase))) + { + this.MappingColumnList = this.Context.MappingColumns.Where(it => it.EntityName.Equals(EntityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase)).ToList(); + } + if (MappingColumnList == null || !MappingColumnList.Any()) + { + return propertyName; + } + else + { + var mappInfo = this.MappingColumnList.FirstOrDefault(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + return mappInfo == null ? propertyName : mappInfo.DbColumnName; + } + } + + protected virtual List GetPrimaryKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + protected virtual List GetIdentityKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetIsIdentities(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); + } + } + //private void TaskStart(Task result) + //{ + // if (this.Context.CurrentConnectionConfig.IsShardSameThread) + // { + // Check.Exception(true, "IsShardSameThread=true can't be used async method"); + // } + // result.Start(); + //} + protected void RestoreMapping() + { + if (IsAs) + { + this.Context.MappingTables = OldMappingTableList; + } + } + //protected IInsertable CopyInsertable() + //{ + // var asyncContext = this.Context.Utilities.CopyContext(true); + // asyncContext.CurrentConnectionConfig.IsAutoCloseConnection = true; + // asyncContext.IsAsyncMethod = true; + // var asyncInsertable = asyncContext.Insertable(this.InsertObjs); + // var asyncInsertableBuilder = asyncInsertable.InsertBuilder; + // asyncInsertableBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList; + // asyncInsertableBuilder.EntityInfo = this.InsertBuilder.EntityInfo; + // asyncInsertableBuilder.Parameters = this.InsertBuilder.Parameters; + // asyncInsertableBuilder.sql = this.InsertBuilder.sql; + // asyncInsertableBuilder.IsNoInsertNull = this.InsertBuilder.IsNoInsertNull; + // asyncInsertableBuilder.IsReturnIdentity = this.InsertBuilder.IsReturnIdentity; + // asyncInsertableBuilder.EntityInfo = this.InsertBuilder.EntityInfo; + // asyncInsertableBuilder.TableWithString = this.InsertBuilder.TableWithString; + // if (this.RemoveCacheFunc != null) + // { + // asyncInsertable.RemoveDataCache(); + // } + // return asyncInsertable; + //} + + private void After(string sql, long? result) + { + if (this.IsEnableDiffLogEvent) + { + var isDisableMasterSlaveSeparation = this.Ado.IsDisableMasterSlaveSeparation; + this.Ado.IsDisableMasterSlaveSeparation = true; + var parameters = InsertBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.AfterData = GetDiffTable(sql, result); + diffModel.Time = this.Context.Ado.SqlExecutionTime; + if (this.Context.CurrentConnectionConfig.AopEvents.OnDiffLogEvent != null) + this.Context.CurrentConnectionConfig.AopEvents.OnDiffLogEvent(diffModel); + this.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + } + if (this.RemoveCacheFunc != null) + { + this.RemoveCacheFunc(); + } + } + private void Before(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var isDisableMasterSlaveSeparation = this.Ado.IsDisableMasterSlaveSeparation; + this.Ado.IsDisableMasterSlaveSeparation = true; + var parameters = InsertBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.BeforeData = null; + diffModel.Sql = sql; + diffModel.Parameters = parameters.ToArray(); + this.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + } + } + private List GetDiffTable(string sql, long? identity) + { + List parameters = new List(); + List result = new List(); + var whereSql = string.Empty; + List cons = new List(); + if (identity != null && identity > 0 && GetIdentityKeys().HasValue()) + { + var fieldName = GetIdentityKeys().Last(); + cons.Add(new ConditionalModel() { ConditionalType = ConditionalType.Equal, FieldName = fieldName, FieldValue = identity.ToString() }); + } + else + { + foreach (var item in this.EntityInfo.Columns.Where(it => it.IsIgnore == false && GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase)))) + { + var fielddName = item.DbColumnName; + var fieldValue = this.EntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.PropertyName).PropertyInfo.GetValue(this.InsertObjs.Last(), null).ObjToString(); + cons.Add(new ConditionalModel() { ConditionalType = ConditionalType.Equal, FieldName = fielddName, FieldValue = fieldValue }); + } + } + Check.Exception(cons.IsNullOrEmpty(), "Insertable.EnableDiffLogEvent need primary key"); + var sqlable = this.SqlBuilder.ConditionalModelToSql(cons); + whereSql = sqlable.Key; + parameters.AddRange(sqlable.Value); + var dt = this.Context.Queryable().Where(whereSql).AddParameters(parameters).ToDataTable(); + if (dt.Rows != null && dt.Rows.Count > 0) + { + foreach (DataRow row in dt.Rows) + { + DiffLogTableInfo item = new DiffLogTableInfo(); + item.TableDescription = this.EntityInfo.TableDescription; + item.TableName = this.EntityInfo.DbTableName; + item.Columns = new List(); + foreach (DataColumn col in dt.Columns) + { + DiffLogColumnInfo addItem = new DiffLogColumnInfo(); + addItem.Value = row[col.ColumnName]; + addItem.ColumnName = col.ColumnName; + addItem.ColumnDescription = this.EntityInfo.Columns.First(it => it.DbColumnName.Equals(col.ColumnName, StringComparison.CurrentCultureIgnoreCase)).ColumnDescription; + item.Columns.Add(addItem); + } + result.Add(item); + } + return result; + } + else + { + DiffLogTableInfo diffTable = new DiffLogTableInfo(); + diffTable.TableName = this.EntityInfo.DbTableName; + diffTable.TableDescription = this.EntityInfo.TableDescription; + diffTable.Columns = this.EntityInfo.Columns.Where(it => it.IsIgnore == false).Select(it => new DiffLogColumnInfo() + { + ColumnDescription = it.ColumnDescription, + ColumnName = it.DbColumnName, + Value = it.PropertyInfo.GetValue(this.InsertObjs.Last(), null) + }).ToList(); + return new List() { diffTable }; + } + + } + #endregion + + #region Obsolete + [Obsolete] + public IInsertable InsertColumns(Func insertColumMethod) + { + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => insertColumMethod(it.PropertyName)).ToList(); + return this; + } + [Obsolete] + public IInsertable IgnoreColumns(Func ignoreColumMethod) + { + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => !ignoreColumMethod(it.PropertyName)).ToList(); + return this; + } + [Obsolete] + public IInsertable Where(bool ignoreNullColumn, bool isOffIdentity = false) + { + return IgnoreColumns(ignoreNullColumn, isOffIdentity); + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/QueryableProvider/QueryableAccessory.cs b/类库/SqlSugar/5.0.0.9/Abstract/QueryableProvider/QueryableAccessory.cs new file mode 100644 index 0000000..21f64cf --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/QueryableProvider/QueryableAccessory.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class QueryableAccessory + { + protected ILambdaExpressions _LambdaExpressions; + protected bool _RestoreMapping = true; + protected int _InQueryableIndex = 100; + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/QueryableProvider/QueryableProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/QueryableProvider/QueryableProvider.cs new file mode 100644 index 0000000..0b02847 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/QueryableProvider/QueryableProvider.cs @@ -0,0 +1,6334 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; +using System.Reflection; +using System.Dynamic; +using System.Threading.Tasks; + +namespace SqlSugar +{ + #region T1 + public partial class QueryableProvider : QueryableAccessory, ISugarQueryable + { + public SqlSugarProvider Context { get; set; } + public IAdo Db { get { return Context.Ado; } } + public IDbBind Bind { get { return this.Db.DbBind; } } + public ISqlBuilder SqlBuilder { get; set; } + public MappingTableList OldMappingTableList { get; set; } + public MappingTableList QueryableMappingTableList { get; set; } + public Action MapperAction { get; set; } + public Action> MapperActionWithCache { get; set; } + public List>> Mappers { get; set; } + public bool IsCache { get; set; } + public int CacheTime { get; set; } + public bool IsAs { get; set; } + public QueryBuilder QueryBuilder + { + get + { + return this.SqlBuilder.QueryBuilder; + } + set + { + this.SqlBuilder.QueryBuilder = value; + } + } + public EntityInfo EntityInfo + { + get + { + return this.Context.EntityMaintenance.GetEntityInfo(); + } + } + public void Clear() + { + QueryBuilder.Clear(); + } + public ISugarQueryable IgnoreColumns(Expression> columns) + { + var ignoreColumns = QueryBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it).ToLower()).ToList(); + return IgnoreColumns(ignoreColumns.ToArray()); + } + public ISugarQueryable IgnoreColumns(params string[] columns) + { + if (QueryBuilder.IgnoreColumns.IsNullOrEmpty()) + { + QueryBuilder.IgnoreColumns = new List(); + } + QueryBuilder.IgnoreColumns.AddRange(columns); + return this; + } + public void AddQueue() + { + var sqlObj = this.ToSql(); + this.Context.Queues.Add(sqlObj.Key, sqlObj.Value); + } + public ISugarQueryable Clone() + { + var queryable = this.Context.Queryable().WithCacheIF(IsCache, CacheTime); + CopyQueryBuilder(queryable.QueryBuilder); + ((QueryableProvider)queryable).MapperAction = this.MapperAction; + ((QueryableProvider)queryable).MapperActionWithCache = this.MapperActionWithCache; + ((QueryableProvider)queryable).Mappers = this.Mappers; + return queryable; + } + public virtual ISugarQueryable AS(string tableName) + { + var entityName = typeof(T2).Name; + return _As(tableName, entityName); + } + public ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + return _As(tableName, entityName); + } + public virtual ISugarQueryable With(string withString) + { + QueryBuilder.TableWithString = withString; + return this; + } + + public virtual ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + + public virtual ISugarQueryable Mapper(Action mapperAction) + { + this.MapperAction = mapperAction; + return this; + } + public virtual ISugarQueryable Mapper(Action> mapperAction) + { + this.MapperActionWithCache = mapperAction; + return this; + } + public ISugarQueryable Mapper(Expression> mapperObject, Expression> mainField, Expression> childField) + { + return _Mapper(mapperObject, mainField, childField); + } + public ISugarQueryable Mapper(Expression>> mapperObject, Expression> mainField, Expression> childField) + { + return _Mapper(mapperObject, mainField, childField); + } + public virtual ISugarQueryable Mapper(Expression>> mapperObject, Expression> mapperField) + { + return _Mapper(mapperObject, mapperField); + } + public virtual ISugarQueryable Mapper(Expression> mapperObject, Expression> mapperField) + { + return _Mapper(mapperObject, mapperField); + } + + public virtual ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public virtual ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public virtual ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public virtual ISugarQueryable AddParameters(SugarParameter parameter) + { + if (parameter != null) + QueryBuilder.Parameters.Add(parameter); + return this; + } + + public virtual ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + + /// + /// if a property that is not empty is a condition + /// + /// + /// + public ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + return WhereClass(new List() { whereClass }, ignoreDefaultValue); + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + if (whereClassTypes.HasValue()) + { + var columns = this.Context.EntityMaintenance.GetEntityInfo().Columns.Where(it => it.IsIgnore == false).ToList(); + List whereModels = new List(); + foreach (var item in whereClassTypes) + { + var cons = new ConditionalCollections(); + foreach (var column in columns) + { + + var value = column.PropertyInfo.GetValue(item, null); + WhereType WhereType = WhereType.And; + var isNotNull = ignoreDefaultValue == false && value != null; + var isNotNullAndDefault = ignoreDefaultValue && value != null && value.ObjToString() != UtilMethods.DefaultForType(column.PropertyInfo.PropertyType).ObjToString(); + if (isNotNull || isNotNullAndDefault) + { + if (cons.ConditionalList == null) + { + cons.ConditionalList = new List>(); + if (QueryBuilder.WhereInfos.IsNullOrEmpty() && whereModels.IsNullOrEmpty()) + { + + } + else + { + WhereType = WhereType.Or; + } + + } + cons.ConditionalList.Add(new KeyValuePair(WhereType, new ConditionalModel() + { + ConditionalType = ConditionalType.Equal, + FieldName = column.DbColumnName, + FieldValue = value.ObjToString() + })); + } + } + if (cons.HasValue()) + { + whereModels.Add(cons); + } + } + this.Where(whereModels); + } + return this; + } + public virtual ISugarQueryable Where(Expression> expression) + { + this._Where(expression); + return this; + } + public virtual ISugarQueryable Where(string whereString, object whereObj = null) + { + if (whereString.HasValue()) + this.Where(whereString, whereObj); + return this; + } + + public virtual ISugarQueryable Where(List conditionalModels) + { + if (conditionalModels.IsNullOrEmpty()) return this; + var sqlObj = this.SqlBuilder.ConditionalModelToSql(conditionalModels); + return this.Where(sqlObj.Key, sqlObj.Value); + } + + public virtual ISugarQueryable Where(string whereString, object whereObj = null) + { + var whereValue = QueryBuilder.WhereInfos; + whereValue.Add(SqlBuilder.AppendWhereOrAnd(whereValue.Count == 0, whereString + UtilConstants.Space)); + if (whereObj != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(whereObj)); + return this; + } + + public virtual ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + public virtual ISugarQueryable Having(string whereString, object parameters = null) + { + + QueryBuilder.HavingInfos = SqlBuilder.AppendHaving(whereString); + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + + public virtual ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (!isWhere) return this; + _Where(expression); + return this; + } + public virtual ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj = null) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + + public virtual T InSingle(object pkValue) + { + Check.Exception(this.QueryBuilder.SelectValue.HasValue(), "'InSingle' and' Select' can't be used together,You can use .Select(it=>...).Single(it.id==1)"); + var list = In(pkValue).ToList(); + if (list == null) return default(T); + else return list.SingleOrDefault(); + } + public virtual ISugarQueryable In(params TParamter[] pkValues) + { + if (pkValues == null || pkValues.Length == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + if (pkValues.Length == 1 && pkValues.First().GetType().FullName.IsCollectionsList() || (pkValues.First() is IEnumerable && pkValues.First().GetType() != UtilConstants.StringType)) + { + var newValues = new List(); + foreach (var item in pkValues.First() as IEnumerable) + { + newValues.Add(item); + } + return In(newValues); + } + var pks = GetPrimaryKeys().Select(it => SqlBuilder.GetTranslationTableName(it)).ToList(); + Check.Exception(pks == null || pks.Count != 1, "Queryable.In(params object[] pkValues): Only one primary key"); + string filed = pks.FirstOrDefault(); + string shortName = QueryBuilder.TableShortName == null ? null : (QueryBuilder.TableShortName + "."); + filed = shortName + filed; + return In(filed, pkValues); + } + public virtual ISugarQueryable In(string filed, params FieldType[] inValues) + { + if (inValues.Length == 1) + { + if (inValues.GetType().IsArray) + { + var whereIndex = QueryBuilder.WhereIndex; + string parameterName = this.SqlBuilder.SqlParameterKeyWord + "InPara" + whereIndex; + this.AddParameters(new SugarParameter(parameterName, inValues[0])); + this.Where(string.Format(QueryBuilder.InTemplate, filed, parameterName)); + QueryBuilder.WhereIndex++; + } + else + { + var values = new List(); + foreach (var item in ((IEnumerable)inValues[0])) + { + if (item != null) + { + values.Add(item.ToString().ToSqlValue()); + } + } + this.Where(string.Format(QueryBuilder.InTemplate, filed, string.Join(",", values))); + } + } + else + { + var values = new List(); + foreach (var item in inValues) + { + if (item != null) + { + values.Add(item.ToString().ToSqlValue()); + } + } + this.Where(string.Format(QueryBuilder.InTemplate, filed, string.Join(",", values))); + + } + return this; + } + public virtual ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + return In(fieldName, inValues); + } + public virtual ISugarQueryable In(List pkValues) + { + if (pkValues == null || pkValues.Count == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + return In(pkValues.ToArray()); + } + public virtual ISugarQueryable In(string InFieldName, List inValues) + { + if (inValues == null || inValues.Count == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + return In(InFieldName, inValues.ToArray()); + } + public virtual ISugarQueryable In(Expression> expression, List inValues) + { + if (inValues == null || inValues.Count == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + return In(expression, inValues.ToArray()); + } + + public virtual ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + public virtual ISugarQueryable OrderBy(string orderFileds) + { + var orderByValue = QueryBuilder.OrderByValue; + if (QueryBuilder.OrderByValue.IsNullOrEmpty()) + { + QueryBuilder.OrderByValue = QueryBuilder.OrderByTemplate; + } + QueryBuilder.OrderByValue += string.IsNullOrEmpty(orderByValue) ? orderFileds : ("," + orderFileds); + return this; + } + public virtual ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + this._OrderBy(expression, type); + return this; + } + public virtual ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public virtual ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + return this.OrderBy(orderFileds); + else + return this; + } + public virtual ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + return this.OrderBy(expression, type); + else + return this; + } + + public virtual ISugarQueryable GroupBy(string groupFileds) + { + var croupByValue = QueryBuilder.GroupByValue; + if (QueryBuilder.GroupByValue.IsNullOrEmpty()) + { + QueryBuilder.GroupByValue = QueryBuilder.GroupByTemplate; + } + QueryBuilder.GroupByValue += string.IsNullOrEmpty(croupByValue) ? groupFileds : ("," + groupFileds); + return this; + } + + public virtual ISugarQueryable PartitionBy(Expression> expression) + { + if (QueryBuilder.Take == null) + QueryBuilder.Take = 1; + _PartitionBy(expression); + return this; + } + public virtual ISugarQueryable PartitionBy(string groupFileds) + { + var partitionByValue = QueryBuilder.PartitionByValue; + if (QueryBuilder.PartitionByValue.IsNullOrEmpty()) + { + QueryBuilder.PartitionByValue = QueryBuilder.PartitionByTemplate; + } + QueryBuilder.PartitionByValue += string.IsNullOrEmpty(partitionByValue) ? groupFileds : ("," + groupFileds); + return this; + } + + public virtual ISugarQueryable Skip(int num) + { + QueryBuilder.Skip = num; + return this; + } + public virtual ISugarQueryable Take(int num) + { + QueryBuilder.Take = num; + return this; + } + + public virtual T Single() + { + if (QueryBuilder.OrderByValue.IsNullOrEmpty()) + { + QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate; + } + var oldSkip = QueryBuilder.Skip; + var oldTake = QueryBuilder.Take; + var oldOrderBy = QueryBuilder.OrderByValue; + QueryBuilder.Skip = null; + QueryBuilder.Take = null; + QueryBuilder.OrderByValue = null; + var result = this.ToList(); + QueryBuilder.Skip = oldSkip; + QueryBuilder.Take = oldTake; + QueryBuilder.OrderByValue = oldOrderBy; + if (result == null || result.Count == 0) + { + return default(T); + } + else if (result.Count == 2) + { + Check.Exception(true, ".Single() result must not exceed one . You can use.First()"); + return default(T); + } + else + { + return result.SingleOrDefault(); + } + } + public virtual T Single(Expression> expression) + { + _Where(expression); + var result = Single(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public virtual T First() + { + if (QueryBuilder.OrderByValue.IsNullOrEmpty()) + { + QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate; + } + if (QueryBuilder.Skip.HasValue) + { + QueryBuilder.Take = 1; + return this.ToList().FirstOrDefault(); + } + else + { + QueryBuilder.Skip = 0; + QueryBuilder.Take = 1; + var result = this.ToList(); + if (result.HasValue()) + return result.FirstOrDefault(); + else + return default(T); + } + } + public virtual T First(Expression> expression) + { + _Where(expression); + var result = First(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public virtual bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public virtual bool Any() + { + return this.Count() > 0; + } + + public virtual ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + + public virtual ISugarQueryable Select() + { + var isJoin = this.QueryBuilder.JoinExpression != null; + if (isJoin) + { + var selectValue = new SugarMapper(this.Context).GetSelectValue(this.QueryBuilder); + return this.Select(selectValue); + } + else + { + return this.Select(this.SqlBuilder.SqlSelectAll); + } + } + + public virtual ISugarQueryable Select(string selectValue) + { + var result = InstanceFactory.GetQueryable(this.Context.CurrentConnectionConfig); + result.Context = this.Context; + result.SqlBuilder = this.SqlBuilder; + QueryBuilder.SelectValue = selectValue; + if (this.IsAs) + { + ((QueryableProvider)result).IsAs = true; + } + return result; + } + public virtual ISugarQueryable Select(string selectValue) + { + QueryBuilder.SelectValue = selectValue; + return this; + } + public virtual ISugarQueryable MergeTable() + { + Check.Exception(this.MapperAction != null || this.MapperActionWithCache != null, "'Mapper’ needs to be written after ‘MergeTable’ "); + Check.Exception(this.QueryBuilder.SelectValue.IsNullOrEmpty(), "MergeTable need to use Queryable.Select Method ."); + Check.Exception(this.QueryBuilder.Skip > 0 || this.QueryBuilder.Take > 0 || this.QueryBuilder.OrderByValue.HasValue(), "MergeTable Queryable cannot Take Skip OrderBy PageToList "); + ToSqlBefore(); + var sql = QueryBuilder.ToSqlString(); + var tableName = this.SqlBuilder.GetPackTable(sql, "MergeTable"); + var mergeQueryable = this.Context.Queryable(); + mergeQueryable.QueryBuilder.Parameters = QueryBuilder.Parameters; + mergeQueryable.QueryBuilder.WhereIndex = QueryBuilder.WhereIndex + 1; + mergeQueryable.QueryBuilder.JoinIndex = QueryBuilder.JoinIndex + 1; + mergeQueryable.QueryBuilder.LambdaExpressions.ParameterIndex = QueryBuilder.LambdaExpressions.ParameterIndex; + return mergeQueryable.AS(tableName).Select("*"); + } + + public ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + public virtual int Count() + { + MappingTableList expMapping; + int result; + _CountBegin(out expMapping, out result); + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return GetCount(); }, CacheTime, this.Context); + } + else + { + result = GetCount(); + } + _CountEnd(expMapping); + return result; + } + + public virtual int Count(Expression> expression) + { + _Where(expression); + var result = Count(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public virtual TResult Max(string maxField) + { + this.Select(string.Format(QueryBuilder.MaxTemplate, maxField)); + var result = this._ToList().SingleOrDefault(); + return result; + } + public virtual TResult Max(Expression> expression) + { + return _Max(expression); + } + + public virtual TResult Min(string minField) + { + this.Select(string.Format(QueryBuilder.MinTemplate, minField)); + var result = this._ToList().SingleOrDefault(); + return result; + } + public virtual TResult Min(Expression> expression) + { + return _Min(expression); + } + + public virtual TResult Sum(string sumField) + { + this.Select(string.Format(QueryBuilder.SumTemplate, sumField)); + var result = this._ToList().SingleOrDefault(); + return result; + } + public virtual TResult Sum(Expression> expression) + { + return _Sum(expression); + } + + public virtual TResult Avg(string avgField) + { + this.Select(string.Format(QueryBuilder.AvgTemplate, avgField)); + var result = this._ToList().SingleOrDefault(); + return result; + } + public virtual TResult Avg(Expression> expression) + { + return _Avg(expression); + } + public virtual T[] ToArray() + { + + var result = this.ToList(); + if (result.HasValue()) + return result.ToArray(); + else + return null; + } + public virtual string ToJson() + { + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + var result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => + { + return this.Context.Utilities.SerializeObject(this.ToList(),typeof(T)); + }, CacheTime, this.Context); + return result; + } + else + { + return this.Context.Utilities.SerializeObject(this.ToList(), typeof(T)); + } + } + public virtual string ToJsonPage(int pageIndex, int pageSize) + { + return this.Context.Utilities.SerializeObject(this.ToPageList(pageIndex, pageSize), typeof(T)); + } + public virtual string ToJsonPage(int pageIndex, int pageSize, ref int totalNumber) + { + return this.Context.Utilities.SerializeObject(this.ToPageList(pageIndex, pageSize, ref totalNumber), typeof(T)); + } + + public virtual DataTable ToDataTable() + { + InitMapping(); + var sqlObj = this.ToSql(); + RestoreMapping(); + DataTable result = null; + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); }, CacheTime, this.Context); + } + else + { + result = this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); + } + return result; + } + public virtual DataTable ToDataTablePage(int pageIndex, int pageSize) + { + if (pageIndex == 0) + pageIndex = 1; + if (QueryBuilder.PartitionByValue.HasValue()) + { + QueryBuilder.ExternalPageIndex = pageIndex; + QueryBuilder.ExternalPageSize = pageSize; + } + else + { + QueryBuilder.Skip = (pageIndex - 1) * pageSize; + QueryBuilder.Take = pageSize; + } + return ToDataTable(); + } + public virtual DataTable ToDataTablePage(int pageIndex, int pageSize, ref int totalNumber) + { + _RestoreMapping = false; + totalNumber = this.Count(); + _RestoreMapping = true; + var result = ToDataTablePage(pageIndex, pageSize); + return result; + } + public virtual DataTable ToDataTablePage(int pageIndex, int pageSize, ref int totalNumber, ref int totalPage) + { + var result = ToDataTablePage(pageIndex, pageSize, ref totalNumber); + totalPage = (totalNumber + pageSize - 1) / pageSize; + return result; + } + + public virtual List ToList() + { + InitMapping(); + return _ToList(); + } + public virtual List ToPageList(int pageIndex, int pageSize) + { + pageIndex = _PageList(pageIndex, pageSize); + return ToList(); + } + public virtual List ToPageList(int pageIndex, int pageSize, ref int totalNumber) + { + _RestoreMapping = false; + List result = null; + int count = this.Count(); + _RestoreMapping = true; + QueryBuilder.IsDisabledGobalFilter = UtilMethods.GetOldValue(QueryBuilder.IsDisabledGobalFilter, () => + { + QueryBuilder.IsDisabledGobalFilter = true; + if (count == 0) + result = new List(); + else + result = ToPageList(pageIndex, pageSize); + + }); + totalNumber = count; + return result; + } + public virtual List ToPageList(int pageIndex, int pageSize, ref int totalNumber, ref int totalPage) + { + var result = ToPageList(pageIndex, pageSize, ref totalNumber); + totalPage = (totalNumber + pageSize - 1) / pageSize; + return result; + } + + public virtual KeyValuePair> ToSql() + { + InitMapping(); + ToSqlBefore(); + string sql = QueryBuilder.ToSqlString(); + RestoreMapping(); + return new KeyValuePair>(sql, QueryBuilder.Parameters); + } + public ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + Check.ArgumentNullException(this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService, "Use Cache ConnectionConfig.ConfigureExternalServices.DataInfoCacheService is required "); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + + public ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (isCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + public string ToClassString(string className) + { + List columns = new List(); + var properties = typeof(T).GetProperties(); + foreach (var item in properties) + { + columns.Add(new DbColumnInfo() + { + DbColumnName = item.Name, + PropertyName = UtilMethods.GetUnderType(item.PropertyType).Name, + PropertyType = UtilMethods.GetUnderType(item.PropertyType) + }); + } + var result = ((this.Context.DbFirst) as DbFirstProvider).GetClassString(columns, ref className); + return result; + } + #region Async methods + public virtual async Task InSingleAsync(object pkValue) + { + Check.Exception(this.QueryBuilder.SelectValue.HasValue(), "'InSingle' and' Select' can't be used together,You can use .Select(it=>...).Single(it.id==1)"); + var list =await In(pkValue).ToListAsync(); + if (list == null) return default(T); + else return list.SingleOrDefault(); + } + public async Task SingleAsync() + { + if (QueryBuilder.OrderByValue.IsNullOrEmpty()) + { + QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate; + } + var oldSkip = QueryBuilder.Skip; + var oldTake = QueryBuilder.Take; + var oldOrderBy = QueryBuilder.OrderByValue; + QueryBuilder.Skip = null; + QueryBuilder.Take = null; + QueryBuilder.OrderByValue = null; + var result =await this.ToListAsync(); + QueryBuilder.Skip = oldSkip; + QueryBuilder.Take = oldTake; + QueryBuilder.OrderByValue = oldOrderBy; + if (result == null || result.Count == 0) + { + return default(T); + } + else if (result.Count == 2) + { + Check.Exception(true, ".Single() result must not exceed one . You can use.First()"); + return default(T); + } + else + { + return result.SingleOrDefault(); + } + } + + public async Task SingleAsync(Expression> expression) + { + _Where(expression); + var result =await SingleAsync(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public async Task FirstAsync() + { + if (QueryBuilder.OrderByValue.IsNullOrEmpty()) + { + QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate; + } + if (QueryBuilder.Skip.HasValue) + { + QueryBuilder.Take = 1; + var list = await this.ToListAsync(); + return list.FirstOrDefault(); + } + else + { + QueryBuilder.Skip = 0; + QueryBuilder.Take = 1; + var result =await this.ToListAsync(); + if (result.HasValue()) + return result.FirstOrDefault(); + else + return default(T); + } + } + + public async Task FirstAsync(Expression> expression) + { + _Where(expression); + var result = await FirstAsync(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public async Task AnyAsync(Expression> expression) + { + _Where(expression); + var result =await AnyAsync(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public async Task AnyAsync() + { + return await this.CountAsync() > 0; + } + + public async Task CountAsync() + { + MappingTableList expMapping; + int result; + _CountBegin(out expMapping, out result); + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return GetCount(); }, CacheTime, this.Context); + } + else + { + result =await GetCountAsync(); + } + _CountEnd(expMapping); + return result; + } + public async Task CountAsync(Expression> expression) + { + _Where(expression); + var result =await CountAsync(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public async Task MaxAsync(string maxField) + { + this.Select(string.Format(QueryBuilder.MaxTemplate, maxField)); + var list = await this._ToListAsync(); + var result =list.SingleOrDefault(); + return result; + } + + public Task MaxAsync(Expression> expression) + { + return _MaxAsync(expression); + } + + public async Task MinAsync(string minField) + { + this.Select(string.Format(QueryBuilder.MinTemplate, minField)); + var list = await this._ToListAsync(); + var result = list.SingleOrDefault(); + return result; + } + + public Task MinAsync(Expression> expression) + { + return _MinAsync(expression); + } + + public async Task SumAsync(string sumField) + { + this.Select(string.Format(QueryBuilder.SumTemplate, sumField)); + var list = await this._ToListAsync(); + var result = list.SingleOrDefault(); + return result; + } + + public Task SumAsync(Expression> expression) + { + return _SumAsync(expression); + } + + public async Task AvgAsync(string avgField) + { + this.Select(string.Format(QueryBuilder.AvgTemplate, avgField)); + var list = await this._ToListAsync(); + var result = list.SingleOrDefault(); + return result; + } + + public Task AvgAsync(Expression> expression) + { + return _AvgAsync(expression); + } + + public Task> ToListAsync() + { + InitMapping(); + return _ToListAsync(); + } + public Task> ToPageListAsync(int pageIndex, int pageSize) + { + pageIndex = _PageList(pageIndex, pageSize); + return ToListAsync(); + } + public async Task> ToPageListAsync(int pageIndex, int pageSize, RefAsync totalNumber) + { + totalNumber.Value = await this.Clone().CountAsync(); + return await this.Clone().ToPageListAsync(pageIndex, pageSize); + } + public async Task ToJsonAsync() + { + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + var result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => + { + return this.Context.Utilities.SerializeObject(this.ToList(), typeof(T)); + }, CacheTime, this.Context); + return result; + } + else + { + return this.Context.Utilities.SerializeObject(await this.ToListAsync(), typeof(T)); + } + } + public async Task ToJsonPageAsync(int pageIndex, int pageSize) + { + return this.Context.Utilities.SerializeObject(await this.ToPageListAsync(pageIndex, pageSize), typeof(T)); + } + public async Task ToJsonPageAsync(int pageIndex, int pageSize, RefAsync totalNumber) + { + totalNumber.Value = await this.Clone().CountAsync(); + return await this.Clone().ToJsonPageAsync(pageIndex, pageSize); + } + public async Task ToDataTableAsync() + { + InitMapping(); + var sqlObj = this.ToSql(); + RestoreMapping(); + DataTable result = null; + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); }, CacheTime, this.Context); + } + else + { + result = await this.Db.GetDataTableAsync(sqlObj.Key, sqlObj.Value.ToArray()); + } + return result; + } + public Task ToDataTablePageAsync(int pageIndex, int pageSize) + { + pageIndex = _PageList(pageIndex, pageSize); + return ToDataTableAsync(); + } + public async Task ToDataTablePageAsync(int pageIndex, int pageSize, RefAsync totalNumber) + { + totalNumber.Value = await this.Clone().CountAsync(); + return await this.Clone().ToDataTablePageAsync(pageIndex, pageSize); + } + + #endregion + + #region Private Methods + private void _CountEnd(MappingTableList expMapping) + { + RestoreMapping(); + QueryBuilder.IsCount = false; + if (expMapping.Count > 0) + { + if (this.QueryableMappingTableList == null) + { + this.QueryableMappingTableList = new MappingTableList(); + } + this.QueryableMappingTableList.Add(expMapping.First()); + } + } + + private void _CountBegin(out MappingTableList expMapping, out int result) + { + expMapping = new MappingTableList(); + if (QueryBuilder.EntityName == "ExpandoObject" && this.Context.MappingTables.Any(it => it.EntityName == "ExpandoObject")) + { + expMapping.Add("ExpandoObject", this.Context.MappingTables.First(it => it.EntityName == "ExpandoObject").DbTableName); + } + InitMapping(); + QueryBuilder.IsCount = true; + result = 0; + } + protected ISugarQueryable _Select(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Select"); + this.Context.InitMappingInfo(typeof(TResult)); + var result = InstanceFactory.GetQueryable(this.Context.CurrentConnectionConfig); + result.Context = this.Context; + result.SqlBuilder = this.SqlBuilder; + result.SqlBuilder.QueryBuilder.Parameters = QueryBuilder.Parameters; + result.SqlBuilder.QueryBuilder.SelectValue = expression; + return result; + } + protected void _Where(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Where"); + var isSingle = QueryBuilder.IsSingle(); + var result = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple); + QueryBuilder.WhereInfos.Add(SqlBuilder.AppendWhereOrAnd(QueryBuilder.WhereInfos.IsNullOrEmpty(), result.GetResultString())); + } + protected ISugarQueryable _OrderBy(Expression expression, OrderByType type = OrderByType.Asc) + { + QueryBuilder.CheckExpression(expression, "OrderBy"); + var isSingle = QueryBuilder.IsSingle(); + if ((expression as LambdaExpression).Body is NewExpression) + { + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.ArraySingle : ResolveExpressType.ArrayMultiple); + var items = lamResult.GetResultString().Split(',').Where(it => it.HasValue()).Select(it => it + UtilConstants.Space + type.ToString().ToUpper()).ToList(); + OrderBy(string.Join(",", items)); + return this; + } + else + { + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + OrderBy(lamResult.GetResultString() + UtilConstants.Space + type.ToString().ToUpper()); + return this; + } + } + private int _PageList(int pageIndex, int pageSize) + { + if (pageIndex == 0) + pageIndex = 1; + if (QueryBuilder.PartitionByValue.HasValue()) + { + QueryBuilder.ExternalPageIndex = pageIndex; + QueryBuilder.ExternalPageSize = pageSize; + } + else + { + QueryBuilder.Skip = (pageIndex - 1) * pageSize; + QueryBuilder.Take = pageSize; + } + + return pageIndex; + } + protected ISugarQueryable _GroupBy(Expression expression) + { + QueryBuilder.CheckExpression(expression, "GroupBy"); + LambdaExpression lambda = expression as LambdaExpression; + expression = lambda.Body; + var isSingle = QueryBuilder.IsSingle(); + ExpressionResult lamResult = null; + string result = null; + if (expression is NewExpression) + { + lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.ArraySingle : ResolveExpressType.ArrayMultiple); + result = string.Join(",", lamResult.GetResultArray().Select(it => it)); + } + else + { + lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + result = lamResult.GetResultString(); + } + GroupBy(result); + return this; + } + protected TResult _Min(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Main"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var result = Min(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return result; + } + protected async Task _MinAsync(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Main"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var result = await MinAsync(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return result; + } + protected TResult _Avg(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Avg"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + return Avg(lamResult.GetResultString()); + } + protected async Task _AvgAsync(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Avg"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + return await AvgAsync(lamResult.GetResultString()); + } + protected TResult _Max(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Max"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var reslut = Max(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return reslut; + } + protected async Task _MaxAsync(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Max"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var reslut =await MaxAsync(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return reslut; + } + protected TResult _Sum(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Sum"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var reslut = Sum(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return reslut; + } + protected async Task _SumAsync(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Sum"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var reslut =await SumAsync(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return reslut; + } + protected ISugarQueryable _As(string tableName, string entityName) + { + IsAs = true; + OldMappingTableList = this.Context.MappingTables; + this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); + if (this.Context.MappingTables.Any(it => it.EntityName == entityName)) + { + this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName); + } + this.Context.MappingTables.Add(entityName, tableName); + this.QueryableMappingTableList = this.Context.MappingTables; + return this; + } + protected void _Filter(string FilterName, bool isDisabledGobalFilter) + { + QueryBuilder.IsDisabledGobalFilter = isDisabledGobalFilter; + if (this.Context.QueryFilter.GeFilterList.HasValue() && FilterName.HasValue()) + { + var list = this.Context.QueryFilter.GeFilterList.Where(it => it.FilterName == FilterName && it.IsJoinQuery == !QueryBuilder.IsSingle()); + foreach (var item in list) + { + var filterResult = item.FilterValue(this.Context); + Where(filterResult.Sql + UtilConstants.Space, filterResult.Parameters); + } + } + } + public ISugarQueryable _PartitionBy(Expression expression) + { + QueryBuilder.CheckExpression(expression, "PartitionBy"); + LambdaExpression lambda = expression as LambdaExpression; + expression = lambda.Body; + var isSingle = QueryBuilder.IsSingle(); + ExpressionResult lamResult = null; + string result = null; + if (expression is NewExpression) + { + lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.ArraySingle : ResolveExpressType.ArrayMultiple); + result = string.Join(",", lamResult.GetResultArray()); + } + else + { + lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + result = lamResult.GetResultString(); + } + PartitionBy(result); + return this; + } + protected ISugarQueryable _Having(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Having"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple); + Having(lamResult.GetResultString()); + return this; + } + protected List _ToList() + { + List result = null; + var sqlObj = this.ToSql(); + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate>(cacheService, this.QueryBuilder, () => { return GetData(sqlObj); }, CacheTime, this.Context); + } + else + { + result = GetData(sqlObj); + } + RestoreMapping(); + _Mapper(result); + return result; + } + protected async Task> _ToListAsync() + { + List result = null; + var sqlObj = this.ToSql(); + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate>(cacheService, this.QueryBuilder, () => { return GetData(sqlObj); }, CacheTime, this.Context); + } + else + { + result =await GetDataAsync(sqlObj); + } + RestoreMapping(); + _Mapper(result); + return result; + } + + protected void _Mapper(List result) + { + if (this.EntityInfo.Columns.Any(it => it.IsTranscoding)) + { + foreach (var item in result) + { + foreach (var column in this.EntityInfo.Columns.Where(it => it.IsTranscoding)) + { + var value = column.PropertyInfo.GetValue(item, null); + if (value != null) + { + column.PropertyInfo.SetValue(item, UtilMethods.DecodeBase64(value.ToString()), null); + } + } + } + } + if (this.Mappers.HasValue()) + { + foreach (var mapper in this.Mappers) + { + if (typeof(TResult) == typeof(T)) + { + mapper(result.Select(it => (T)Convert.ChangeType(it, typeof(T))).ToList()); + } + else + { + Check.Exception(true, "{0} and {1} are not a type, Try .select().mapper().ToList", typeof(TResult).FullName, typeof(T).FullName); + } + } + } + if (this.MapperAction != null) + { + foreach (TResult item in result) + { + if (typeof(TResult) == typeof(T)) + { + this.MapperAction((T)(item as object)); + } + else + { + Check.Exception(true, "{0} and {1} are not a type, Try .select().mapper().ToList", typeof(TResult).FullName, typeof(T).FullName); + } + } + } + if (this.MapperActionWithCache != null) + { + if (typeof(TResult) == typeof(T)) + { + var list = (List)Convert.ChangeType(result, typeof(List)); + var mapperCache = new MapperCache(list, this.Context); + foreach (T item in list) + { + mapperCache.GetIndex = 0; + this.MapperActionWithCache(item, mapperCache); + } + } + else + { + Check.Exception(true, "{0} and {1} are not a type, Try .select().mapper().ToList", typeof(TResult).FullName, typeof(T).FullName); + } + } + } + + private ISugarQueryable _Mapper(Expression mapperObject, Expression mapperField) + { + if ((mapperObject as LambdaExpression).Body is UnaryExpression) + { + mapperObject = ((mapperObject as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + mapperObject = (mapperObject as LambdaExpression).Body; + } + if ((mapperField as LambdaExpression).Body is UnaryExpression) + { + mapperField = ((mapperField as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + mapperField = (mapperField as LambdaExpression).Body; + } + Check.Exception(mapperObject is MemberExpression == false || mapperField is MemberExpression == false, ".Mapper() parameter error"); + var mapperObjectExp = mapperObject as MemberExpression; + var mapperFieldExp = mapperField as MemberExpression; + Check.Exception(mapperFieldExp.Type.IsClass(), ".Mapper() parameter error"); + var objType = mapperObjectExp.Type; + var filedType = mapperFieldExp.Expression.Type; + Check.Exception(objType != typeof(TObject) && objType != typeof(List), ".Mapper() parameter error"); + if (objType == typeof(List)) + { + objType = typeof(TObject); + } + var filedName = mapperFieldExp.Member.Name; + var objName = mapperObjectExp.Member.Name; + var filedEntity = this.Context.EntityMaintenance.GetEntityInfo(objType); + var objEntity = this.Context.EntityMaintenance.GetEntityInfo(filedType); + var isSelf = filedType == typeof(T); + if (Mappers == null) + Mappers = new List>>(); + if (isSelf) + { + Action> mapper = (entitys) => + { + if (entitys.IsNullOrEmpty() || !entitys.Any()) return; + var entity = entitys.First(); + var whereCol = filedEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals(filedName, StringComparison.CurrentCultureIgnoreCase)); + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals("id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => (it.PropertyName).Equals(it.EntityName + "id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + Check.Exception(true, ".Mapper() parameter error"); + } + List inValues = entitys.Select(it => it.GetType().GetProperty(filedName).GetValue(it, null).ObjToString()).ToList(); + List wheres = new List() + { + new ConditionalModel() + { + FieldName=whereCol.DbColumnName, + ConditionalType= ConditionalType.In, + FieldValue=string.Join(",",inValues.Distinct()) + } + }; + var list = this.Context.Queryable().Where(wheres).ToList(); + foreach (var item in entitys) + { + var whereValue = item.GetType().GetProperty(filedName).GetValue(item, null); + var setValue = list.Where(x => x.GetType().GetProperty(whereCol.PropertyName).GetValue(x, null).ObjToString() == whereValue.ObjToString()).ToList(); + var setObject = item.GetType().GetProperty(objName); + if (setObject.PropertyType.FullName.IsCollectionsList()) + { + setObject.SetValue(item, setValue.ToList(), null); + } + else + { + setObject.SetValue(item, setValue.FirstOrDefault(), null); + } + } + }; + Mappers.Add(mapper); + } + else + { + Action> mapper = (entitys) => + { + if (entitys.IsNullOrEmpty() || !entitys.Any()) return; + var entity = entitys.First(); + var tEntity = this.Context.EntityMaintenance.GetEntityInfo(); + var whereCol = tEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals(filedName, StringComparison.CurrentCultureIgnoreCase)); + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals("id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => (it.PropertyName).Equals(it.EntityName + "id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + Check.Exception(true, ".Mapper() parameter error"); + } + List inValues = entitys.Select(it => it.GetType().GetProperty(whereCol.PropertyName).GetValue(it, null).ObjToString()).ToList(); + var dbColumnName = filedEntity.Columns.FirstOrDefault(it => it.PropertyName == filedName).DbColumnName; + List wheres = new List() + { + new ConditionalModel() + { + FieldName=dbColumnName, + ConditionalType= ConditionalType.In, + FieldValue=string.Join(",",inValues) + } + }; + var list = this.Context.Queryable().Where(wheres).ToList(); + foreach (var item in entitys) + { + var whereValue = item.GetType().GetProperty(whereCol.PropertyName).GetValue(item, null); + var setValue = list.Where(x => x.GetType().GetProperty(filedName).GetValue(x, null).ObjToString() == whereValue.ObjToString()).ToList(); + var setObject = item.GetType().GetProperty(objName); + if (setObject.PropertyType.FullName.IsCollectionsList()) + { + setObject.SetValue(item, setValue.ToList(), null); + } + else + { + setObject.SetValue(item, setValue.FirstOrDefault(), null); + } + } + }; + Mappers.Add(mapper); + } + + return this; + } + + private ISugarQueryable _Mapper(Expression mapperObject, Expression mainField, Expression childField) + { + if ((mapperObject as LambdaExpression).Body is UnaryExpression) + { + mapperObject = ((mapperObject as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + mapperObject = (mapperObject as LambdaExpression).Body; + } + if ((mainField as LambdaExpression).Body is UnaryExpression) + { + mainField = ((mainField as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + mainField = (mainField as LambdaExpression).Body; + } + if ((childField as LambdaExpression).Body is UnaryExpression) + { + childField = ((childField as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + childField = (childField as LambdaExpression).Body; + } + Check.Exception(mapperObject is MemberExpression == false || mainField is MemberExpression == false, ".Mapper() parameter error"); + var mapperObjectExp = mapperObject as MemberExpression; + var mainFieldExp = mainField as MemberExpression; + var childFieldExp = childField as MemberExpression; + Check.Exception(mainFieldExp.Type.IsClass(), ".Mapper() parameter error"); + Check.Exception(childFieldExp.Type.IsClass(), ".Mapper() parameter error"); + var objType = mapperObjectExp.Type; + var filedType = mainFieldExp.Expression.Type; + Check.Exception(objType != typeof(TObject) && objType != typeof(List), ".Mapper() parameter error"); + if (objType == typeof(List)) + { + objType = typeof(TObject); + } + var mainFiledName = mainFieldExp.Member.Name; + var childFiledName = childFieldExp.Member.Name; + var objName = mapperObjectExp.Member.Name; + var filedEntity = this.Context.EntityMaintenance.GetEntityInfo(objType); + var objEntity = this.Context.EntityMaintenance.GetEntityInfo(filedType); + var isSelf = filedType == typeof(T); + if (Mappers == null) + Mappers = new List>>(); + if (isSelf) + { + Action> mapper = (entitys) => + { + if (entitys.IsNullOrEmpty() || !entitys.Any()) return; + var entity = entitys.First(); + var whereCol = filedEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals(childFiledName, StringComparison.CurrentCultureIgnoreCase)); + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals("id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => (it.PropertyName).Equals(it.EntityName + "id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + Check.Exception(true, ".Mapper() parameter error"); + } + List inValues = entitys.Select(it => it.GetType().GetProperty(mainFiledName).GetValue(it, null).ObjToString()).ToList(); + List wheres = new List() + { + new ConditionalModel() + { + FieldName=whereCol.DbColumnName, + ConditionalType= ConditionalType.In, + FieldValue=string.Join(",",inValues.Distinct()) + } + }; + var list = this.Context.Queryable().Where(wheres).ToList(); + foreach (var item in entitys) + { + var whereValue = item.GetType().GetProperty(mainFiledName).GetValue(item, null); + var setValue = list.Where(x => x.GetType().GetProperty(whereCol.PropertyName).GetValue(x, null).ObjToString() == whereValue.ObjToString()).ToList(); + var setObject = item.GetType().GetProperty(objName); + if (setObject.PropertyType.FullName.IsCollectionsList()) + { + setObject.SetValue(item, setValue.ToList(), null); + } + else + { + setObject.SetValue(item, setValue.FirstOrDefault(), null); + } + } + }; + Mappers.Add(mapper); + } + else + { + Action> mapper = (entitys) => + { + if (entitys.IsNullOrEmpty() || !entitys.Any()) return; + var entity = entitys.First(); + var tEntity = this.Context.EntityMaintenance.GetEntityInfo(); + var whereCol = tEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals(childFiledName, StringComparison.CurrentCultureIgnoreCase)); + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals("id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => (it.PropertyName).Equals(it.EntityName + "id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + Check.Exception(true, ".Mapper() parameter error"); + } + List inValues = entitys.Select(it => it.GetType().GetProperty(whereCol.PropertyName).GetValue(it, null).ObjToString()).ToList(); + var dbColumnName = filedEntity.Columns.FirstOrDefault(it => it.PropertyName == mainFiledName).DbColumnName; + List wheres = new List() + { + new ConditionalModel() + { + FieldName=dbColumnName, + ConditionalType= ConditionalType.In, + FieldValue=string.Join(",",inValues) + } + }; + var list = this.Context.Queryable().Where(wheres).ToList(); + foreach (var item in entitys) + { + var whereValue = item.GetType().GetProperty(whereCol.PropertyName).GetValue(item, null); + var setValue = list.Where(x => x.GetType().GetProperty(mainFiledName).GetValue(x, null).ObjToString() == whereValue.ObjToString()).ToList(); + var setObject = item.GetType().GetProperty(objName); + if (setObject.PropertyType.FullName.IsCollectionsList()) + { + setObject.SetValue(item, setValue.ToList(), null); + } + else + { + setObject.SetValue(item, setValue.FirstOrDefault(), null); + } + } + }; + Mappers.Add(mapper); + } + + return this; + } + protected int GetCount() + { + var sql = string.Empty; + ToSqlBefore(); + sql = QueryBuilder.ToSqlString(); + sql = QueryBuilder.ToCountSql(sql); + var result = Context.Ado.GetInt(sql, QueryBuilder.Parameters.ToArray()); + return result; + } + protected async Task GetCountAsync() + { + var sql = string.Empty; + ToSqlBefore(); + sql = QueryBuilder.ToSqlString(); + sql = QueryBuilder.ToCountSql(sql); + var result =Convert.ToInt32(await Context.Ado.GetScalarAsync(sql, QueryBuilder.Parameters.ToArray())); + return result; + } + + private void ToSqlBefore() + { + var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; + if (moreSetts != null && moreSetts.IsWithNoLockQuery && string.IsNullOrEmpty(QueryBuilder.TableWithString)) + { + this.With(SqlWith.NoLock); + } + } + + protected List GetData(KeyValuePair> sqlObj) + { + List result; + var isComplexModel = QueryBuilder.IsComplexModel(sqlObj.Key); + var entityType = typeof(TResult); + var dataReader = this.Db.GetDataReader(sqlObj.Key, sqlObj.Value.ToArray()); + result = GetData(isComplexModel, entityType, dataReader); + return result; + } + protected async Task> GetDataAsync(KeyValuePair> sqlObj) + { + List result; + var isComplexModel = QueryBuilder.IsComplexModel(sqlObj.Key); + var entityType = typeof(TResult); + var dataReader = await this.Db.GetDataReaderAsync(sqlObj.Key, sqlObj.Value.ToArray()); + result =await GetDataAsync(isComplexModel, entityType, dataReader); + return result; + } + + private List GetData(bool isComplexModel, Type entityType, IDataReader dataReader) + { + List result; + if (entityType == UtilConstants.DynamicType) + { + result = this.Context.Utilities.DataReaderToExpandoObjectList(dataReader) as List; + } + else if (entityType == UtilConstants.ObjType) + { + result = this.Context.Utilities.DataReaderToExpandoObjectList(dataReader).Select(it => ((TResult)(object)it)).ToList(); + } + else if (entityType.IsAnonymousType() || isComplexModel) + { + result = this.Context.Utilities.DataReaderToList(dataReader); + } + else + { + result = this.Bind.DataReaderToList(entityType, dataReader); + } + SetContextModel(result, entityType); + return result; + } + private async Task> GetDataAsync(bool isComplexModel, Type entityType, IDataReader dataReader) + { + List result; + if (entityType == UtilConstants.DynamicType) + { + result =await this.Context.Utilities.DataReaderToExpandoObjectListAsync(dataReader) as List; + } + else if (entityType == UtilConstants.ObjType) + { + var expObj = await this.Context.Utilities.DataReaderToExpandoObjectListAsync(dataReader); + result = expObj.Select(it => ((TResult)(object)it)).ToList(); + } + else if (entityType.IsAnonymousType() || isComplexModel) + { + result =await this.Context.Utilities.DataReaderToListAsync(dataReader); + } + else + { + result =await this.Bind.DataReaderToListAsync(entityType, dataReader); + } + SetContextModel(result, entityType); + return result; + } + + protected void _InQueryable(Expression expression, KeyValuePair> sqlObj) + { + QueryBuilder.CheckExpression(expression, "In"); + string sql = sqlObj.Key; + if (sqlObj.Value.HasValue()) + { + this.SqlBuilder.RepairReplicationParameters(ref sql, sqlObj.Value.ToArray(), 100); + this.QueryBuilder.Parameters.AddRange(sqlObj.Value); + } + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + var whereSql = string.Format(this.QueryBuilder.InTemplate, fieldName, sql); + this.QueryBuilder.WhereInfos.Add(SqlBuilder.AppendWhereOrAnd(this.QueryBuilder.WhereInfos.IsNullOrEmpty(), whereSql)); + base._InQueryableIndex += 100; + } + + protected List GetPrimaryKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + protected virtual List GetIdentityKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetIsIdentities(this.EntityInfo.DbTableName); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); + } + } + + protected void RestoreMapping() + { + if (IsAs && _RestoreMapping) + { + this.Context.MappingTables = OldMappingTableList == null ? new MappingTableList() : OldMappingTableList; + } + } + protected void InitMapping() + { + if (this.QueryableMappingTableList != null) + this.Context.MappingTables = this.QueryableMappingTableList; + } + + private void SetContextModel(List result, Type entityType) + { + if (result.HasValue()) + { + if (UtilMethods.GetRootBaseType(entityType).HasValue() && UtilMethods.GetRootBaseType(entityType) == UtilConstants.ModelType) + { + foreach (var item in result) + { + var contextProperty = item.GetType().GetProperty("Context"); + SqlSugarProvider newClient = this.Context.Utilities.CopyContext(); + newClient.Ado.IsDisableMasterSlaveSeparation = true; + if (newClient.CurrentConnectionConfig.AopEvents == null) + newClient.CurrentConnectionConfig.AopEvents = new AopEvents(); + contextProperty.SetValue(item, newClient, null); + } + } + } + } + protected void CopyQueryBuilder(QueryBuilder asyncQueryableBuilder) + { + var pars = new List(); + pars.AddRange(this.QueryBuilder.Parameters); + asyncQueryableBuilder.Take = this.QueryBuilder.Take; + asyncQueryableBuilder.Skip = this.QueryBuilder.Skip; + asyncQueryableBuilder.SelectValue = this.QueryBuilder.SelectValue; + asyncQueryableBuilder.WhereInfos = this.Context.Utilities.TranslateCopy(this.QueryBuilder.WhereInfos); + asyncQueryableBuilder.EasyJoinInfos = this.QueryBuilder.EasyJoinInfos; + asyncQueryableBuilder.JoinQueryInfos = this.QueryBuilder.JoinQueryInfos; + asyncQueryableBuilder.WhereIndex = this.QueryBuilder.WhereIndex; + asyncQueryableBuilder.EntityType = this.QueryBuilder.EntityType; + asyncQueryableBuilder.EntityName = this.QueryBuilder.EntityName; + asyncQueryableBuilder.Parameters = pars; + asyncQueryableBuilder.TableShortName = this.QueryBuilder.TableShortName; + asyncQueryableBuilder.TableWithString = this.QueryBuilder.TableWithString; + asyncQueryableBuilder.GroupByValue = this.QueryBuilder.GroupByValue; + asyncQueryableBuilder.IsDistinct = this.QueryBuilder.IsDistinct; + asyncQueryableBuilder.OrderByValue = this.QueryBuilder.OrderByValue; + asyncQueryableBuilder.IsDisabledGobalFilter = this.QueryBuilder.IsDisabledGobalFilter; + asyncQueryableBuilder.PartitionByValue = this.QueryBuilder.PartitionByValue; + asyncQueryableBuilder.JoinExpression = this.QueryBuilder.JoinExpression; + asyncQueryableBuilder.WhereIndex = this.QueryBuilder.WhereIndex; + asyncQueryableBuilder.HavingInfos = this.QueryBuilder.HavingInfos; + asyncQueryableBuilder.LambdaExpressions.ParameterIndex = this.QueryBuilder.LambdaExpressions.ParameterIndex; + asyncQueryableBuilder.IgnoreColumns = this.QueryBuilder.IgnoreColumns; + } + protected int SetCacheTime(int cacheDurationInSeconds) + { + if (cacheDurationInSeconds == int.MaxValue && this.Context.CurrentConnectionConfig.MoreSettings != null && this.Context.CurrentConnectionConfig.MoreSettings.DefaultCacheDurationInSeconds > 0) + { + cacheDurationInSeconds = this.Context.CurrentConnectionConfig.MoreSettings.DefaultCacheDurationInSeconds; + } + + return cacheDurationInSeconds; + } + + #endregion + } + #endregion + #region T2 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + + #endregion + + #region Order + public new ISugarQueryable OrderBy(string orderFileds) + { + base.OrderBy(orderFileds); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public new ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public new ISugarQueryable Having(string whereString, object whereObj) + { + base.Having(whereString, whereObj); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (isCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T3 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Group + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public new ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public new ISugarQueryable Having(string whereString, object whereObj) + { + base.Having(whereString, whereObj); + return this; + } + #endregion + + #region Order + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + #endregion + + #region Where + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T4 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public new ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public new ISugarQueryable Having(string whereString, object whereObj) + { + base.Having(whereString, whereObj); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T5 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T6 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T7 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T8 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T9 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8, t9) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + #endregion + } + #endregion + #region T10 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8, t9, t10) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + #endregion + } + #endregion + #region T11 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8, t9, t10, t11) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + #endregion + } + #endregion + #region T12 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8, t9, t10, t11, t12) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + cacheDurationInSeconds = SetCacheTime(cacheDurationInSeconds); + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + #endregion + } + #endregion +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SaveableProvider/SaveableProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/SaveableProvider/SaveableProvider.cs new file mode 100644 index 0000000..c7589a6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SaveableProvider/SaveableProvider.cs @@ -0,0 +1,229 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SaveableProvider : ISaveable where T : class, new() + { + internal SaveableProvider(SqlSugarProvider context,List saveObjects) + { + this.saveObjects = saveObjects; + this.Context = context; + this.Context.InitMappingInfo(); + } + internal SaveableProvider(SqlSugarProvider context, T saveObject) + { + this.saveObjects = new List() { saveObject }; + this.Context = context; + this.Context.InitMappingInfo(); + } + public SqlSugarProvider Context { get; set; } + public List saveObjects = new List(); + public List existsObjects = null; + public List insertObjects + { + get + { + var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation; + this.Context.Ado.IsDisableMasterSlaveSeparation = true; + List result = new List(); + var pks = GetPrimaryKeys(); + Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); + Check.Exception(pks.Count() > 1, "Multiple primary keys are not supported"); + var pkInfo = this.EntityInfo.Columns.Where(it=>it.IsIgnore==false).Where(it => it.DbColumnName.Equals(pks.First(), StringComparison.CurrentCultureIgnoreCase)).First(); + var pkValues = saveObjects.Select(it=>it.GetType().GetProperty(pkInfo.PropertyName).GetValue(it,null)); + if(existsObjects==null) + existsObjects=this.Context.Queryable().In(pkValues).ToList(); + this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + return saveObjects.Where(it=>! + existsObjects.Any(e=> + e.GetType().GetProperty(pkInfo.PropertyName).GetValue(e,null).ObjToString() + == + it.GetType().GetProperty(pkInfo.PropertyName).GetValue(it, null).ObjToString())).ToList(); + } + } + public List updatObjects + { + get + { + var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation; + this.Context.Ado.IsDisableMasterSlaveSeparation = true; + List result = new List(); + var pks = GetPrimaryKeys(); + Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); + Check.Exception(pks.Count() > 1, "Multiple primary keys are not supported"); + var pkInfo = this.EntityInfo.Columns.Where(it => it.IsIgnore == false).Where(it => it.DbColumnName.Equals(pks.First(), StringComparison.CurrentCultureIgnoreCase)).First(); + var pkValues = saveObjects.Select(it => it.GetType().GetProperty(pkInfo.PropertyName).GetValue(it, null)); + if (existsObjects == null) + existsObjects = this.Context.Queryable().In(pkValues).ToList(); + this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + return saveObjects.Where(it => + existsObjects.Any(e => + e.GetType().GetProperty(pkInfo.PropertyName).GetValue(e, null).ObjToString() + == + it.GetType().GetProperty(pkInfo.PropertyName).GetValue(it, null).ObjToString())).ToList(); + } + } + + public IInsertable insertable { get; set; } + public IUpdateable updateable { get; set; } + + public EntityInfo EntityInfo + { + get + { + return this.Context.EntityMaintenance.GetEntityInfo(); + } + } + + #region Core + public int ExecuteCommand() + { + LoadInsertable(); + LoadUpdateable(); + var insertCount = 0; + var updateCount = 0; + if (insertable != null) + { + insertCount = insertable.ExecuteCommand(); + } + if (updateable != null) + { + updateCount = updateable.ExecuteCommand(); + } + return updateCount + insertCount; + } + + public T ExecuteReturnEntity() + { + LoadInsertable(); + LoadUpdateable(); + if (insertable != null) + insertable.ExecuteCommandIdentityIntoEntity(); + if (updateable != null) + updateable.ExecuteCommand(); + return saveObjects.First(); + } + + public List ExecuteReturnList() + { + LoadInsertable(); + LoadUpdateable(); + if (insertable != null) + insertable.ExecuteCommand(); + if (updateable != null) + updateable.ExecuteCommand(); + return saveObjects; + } + #endregion + #region Core Async + public Task ExecuteCommandAsync() + { + return Task.FromResult(ExecuteCommand()); + } + + public Task ExecuteReturnEntityAsync() + { + return Task.FromResult(ExecuteReturnEntity()); + } + + public Task> ExecuteReturnListAsync() + { + return Task.FromResult(ExecuteReturnList()); + } + #endregion + public ISaveable InsertColumns(Expression> columns) + { + LoadInsertable(); + if (this.insertable != null) + { + this.insertable.InsertColumns(columns); + } + return this; + } + + public ISaveable EnableDiffLogEvent(object businessData = null) + { + LoadInsertable(); + LoadUpdateable(); + if (this.insertable != null) + { + this.insertable.EnableDiffLogEvent(businessData); + } + if (this.updateable != null) + { + this.updateable.EnableDiffLogEvent(businessData); + } + return this; + } + + public ISaveable InsertIgnoreColumns(Expression> columns) + { + LoadInsertable(); + if (this.insertable != null) + { + this.insertable.IgnoreColumns(columns); + } + return this; + } + + public ISaveable UpdateColumns(Expression> columns) + { + LoadUpdateable(); + if (this.updateable != null) + { + this.updateable.UpdateColumns(columns); + } + return this; + } + + public ISaveable UpdateIgnoreColumns(Expression> columns) + { + LoadUpdateable(); + if (this.updateable != null) + { + this.updateable.IgnoreColumns(columns); + } + return this; + } + + public ISaveable UpdateWhereColumns(Expression> columns) + { + LoadUpdateable(); + if (this.updateable != null) + { + this.updateable.WhereColumns(columns); + } + return this; + } + protected virtual List GetPrimaryKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + private void LoadInsertable() + { + var temp = insertObjects; + if (insertable == null && temp.HasValue()) + insertable = this.Context.Insertable(temp); + } + private void LoadUpdateable() + { + var temp = updatObjects; + if (updateable == null && temp.HasValue()) + updateable = this.Context.Updateable(temp); + } + + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/DeleteBuilder.cs b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/DeleteBuilder.cs new file mode 100644 index 0000000..a1938bb --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/DeleteBuilder.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class DeleteBuilder : IDMLBuilder + { + #region Fields + private List _WhereInfos; + #endregion + + #region Common Properties + public EntityInfo EntityInfo { get; set; } + public SqlSugarProvider Context { get; set; } + public ILambdaExpressions LambdaExpressions { get; set; } + public List Parameters { get; set; } + public StringBuilder sql { get; set; } + public ISqlBuilder Builder { get; set; } + public string TableWithString { get; set; } + public virtual List WhereInfos + { + get + { + _WhereInfos = UtilMethods.IsNullReturnNew(_WhereInfos); + return _WhereInfos; + } + set { _WhereInfos = value; } + } + public virtual List BigDataInValues { get; set; } + public virtual string BigDataFiled { get; set; } + #endregion + + #region Sql Template + public string SqlTemplate + { + get + { + return "DELETE FROM {0}{1}"; + } + } + public string WhereInTemplate + { + get + { + return "{0} IN ({1})"; + } + } + public string WhereInOrTemplate + { + get + { + return "OR"; + } + } + public string WhereInAndTemplate + { + get + { + return "AND"; + } + } + public string WhereInEqualTemplate + { + get + { + return Builder.SqlTranslationLeft+"{0}"+Builder.SqlTranslationRight+"=N'{1}'"; + } + } + public string WhereInAreaTemplate + { + get + { + return "({0})"; + } + } + #endregion + + #region Get Sql + public virtual string GetTableNameString + { + get + { + var result = Builder.GetTranslationTableName(EntityInfo.EntityName); + result += UtilConstants.Space; + if (this.TableWithString.HasValue()) + { + result += TableWithString + UtilConstants.Space; + } + return result; + } + } + public virtual string GetWhereString + { + get + { + if (_WhereInfos == null || _WhereInfos.Count == 0) return null; + string whereString = null; + int i = 0; + foreach (var item in _WhereInfos) + { + var isFirst = i == 0; + whereString += isFirst ? "WHERE " : "AND "; + whereString += (item + UtilConstants.Space); + ++i; + } + return whereString; + } + } + + #endregion + + #region Public methods + public virtual void Clear() + { + } + public virtual string ToSqlString() + { + if (this.BigDataInValues.IsNullOrEmpty()) + { + return string.Format(SqlTemplate, GetTableNameString, GetWhereString); + } + else//big data + { + var whereString = GetWhereString; + var sql = string.Format(SqlTemplate, GetTableNameString, whereString); + sql += whereString.IsNullOrEmpty() ? " WHERE " : " AND "; + StringBuilder batchDeleteSql = new StringBuilder(); + int pageSize = 1000; + int pageIndex = 1; + int totalRecord = this.BigDataInValues.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + while (pageCount >= pageIndex) + { + var inValues = this.BigDataInValues.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); + batchDeleteSql.Append(sql+string.Format(WhereInTemplate,BigDataFiled,inValues.ToArray().ToJoinSqlInVals())); + batchDeleteSql.Append(";"); + pageIndex++; + } + return batchDeleteSql.ToString(); + } + } + public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType) + { + ILambdaExpressions resolveExpress = this.LambdaExpressions; + this.LambdaExpressions.Clear(); + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + resolveExpress.InitMappingInfo = Context.InitMappingInfo; + resolveExpress.RefreshMapping = () => + { + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + }; + resolveExpress.Resolve(expression, resolveType); + if (this.Parameters == null) + this.Parameters = new List(); + this.Parameters.AddRange(resolveExpress.Parameters); + var result = resolveExpress.Result; + return result; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/InsertBuilder.cs b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/InsertBuilder.cs new file mode 100644 index 0000000..b3bfd7b --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/InsertBuilder.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using System.Linq.Expressions; +namespace SqlSugar +{ + public class InsertBuilder : IDMLBuilder + { + #region Init + public InsertBuilder() + { + this.sql = new StringBuilder(); + this.Parameters = new List(); + this.DbColumnInfoList = new List(); + } + + #endregion + + #region Common Properties + public SqlSugarProvider Context { get; set; } + public ILambdaExpressions LambdaExpressions { get; set; } + public ISqlBuilder Builder { get; set; } + public StringBuilder sql { get; set; } + public List Parameters { get; set; } + public string TableWithString { get; set; } + public List DbColumnInfoList { get; set; } + public bool IsNoInsertNull { get; set; } + public bool IsReturnIdentity { get; set; } + public EntityInfo EntityInfo { get; set; } + public Dictionary OracleSeqInfoList { get; set; } + #endregion + + #region SqlTemplate + public virtual string SqlTemplate + { + get + { + if (IsReturnIdentity) + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;SELECT SCOPE_IDENTITY();"; + } + else + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;"; + + } + } + } + public virtual string SqlTemplateBatch + { + get + { + return "INSERT {0} ({1})"; + } + } + public virtual string SqlTemplateBatchSelect + { + get + { + return "{0} AS {1}"; + } + } + public virtual string SqlTemplateBatchUnion + { + get + { + return "\t\r\nUNION ALL "; + } + } + + #endregion + + #region Methods + public virtual void Clear() + { + + } + public virtual string GetTableNameString + { + get + { + var result = Builder.GetTranslationTableName(EntityInfo.EntityName); + result += UtilConstants.Space; + if (this.TableWithString.HasValue()) + { + result += TableWithString + UtilConstants.Space; + } + return result; + } + } + public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType) + { + ILambdaExpressions resolveExpress = this.LambdaExpressions; + this.LambdaExpressions.Clear(); + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + resolveExpress.Resolve(expression, resolveType); + this.Parameters.AddRange(resolveExpress.Parameters); + var result = resolveExpress.Result; + return result; + } + public virtual string ToSqlString() + { + if (IsNoInsertNull) + { + DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList(); + } + var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); + var isSingle = groupList.Count() == 1; + string columnsString = string.Join(",", groupList.First().Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + if (isSingle) + { + string columnParametersString = string.Join(",", this.DbColumnInfoList.Select(it => Builder.SqlParameterKeyWord + it.DbColumnName)); + return string.Format(SqlTemplate, GetTableNameString, columnsString, columnParametersString); + } + else + { + StringBuilder batchInsetrSql = new StringBuilder(); + int pageSize = 200; + if (this.EntityInfo.Columns.Count > 30) + { + pageSize = 50; + } + else if (this.EntityInfo.Columns.Count > 20) + { + pageSize = 100; + } + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + while (pageCount >= pageIndex) + { + batchInsetrSql.AppendFormat(SqlTemplateBatch, GetTableNameString, columnsString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + batchInsetrSql.Append(SqlTemplateBatchUnion); + } + batchInsetrSql.Append("\r\n SELECT " + string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value),Builder.GetTranslationColumnName(it.DbColumnName))))); + ++i; + } + pageIndex++; + batchInsetrSql.Append("\r\n;\r\n"); + } + return batchInsetrSql.ToString(); + } + } + public virtual object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type =UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "N'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "N'" + value.ToString() + "'"; + } + } + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/QueryBuilder.cs b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/QueryBuilder.cs new file mode 100644 index 0000000..daae085 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/QueryBuilder.cs @@ -0,0 +1,561 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public abstract class QueryBuilder : IDMLBuilder + { + + public QueryBuilder() + { + this.Parameters = new List(); + } + + #region Private Fileds + protected List _JoinQueryInfos; + protected Dictionary _EasyJoinInfos; + private List _WhereInfos; + private string _HavingInfos; + protected string _TableNameString; + #endregion + + #region Service object + public StringBuilder sql { get; set; } + public SqlSugarProvider Context { get; set; } + public ILambdaExpressions LambdaExpressions { get; set; } + public ISqlBuilder Builder { get; set; } + #endregion + + #region Splicing basic + public List IgnoreColumns { get; set; } + public bool IsCount { get; set; } + public int? Skip { get; set; } + public int ExternalPageIndex { get; set; } + public int ExternalPageSize { get; set; } + public int? Take { get; set; } + public string OrderByValue { get; set; } + public object SelectValue { get; set; } + public string SelectCacheKey { get; set; } + public string EntityName { get; set; } + + + public Type EntityType { get; set; } + public string TableWithString { get; set; } + public string GroupByValue { get; set; } + public string PartitionByValue { get; set; } + public int WhereIndex { get; set; } + public bool IsDistinct { get; set; } + public int JoinIndex { get; set; } + public bool IsDisabledGobalFilter { get; set; } + public virtual List Parameters { get; set; } + public Expression JoinExpression { get; set; } + public Dictionary EasyJoinInfos + { + get + { + _EasyJoinInfos = UtilMethods.IsNullReturnNew(_EasyJoinInfos); + return _EasyJoinInfos; + } + set { _EasyJoinInfos = value; } + } + public virtual List JoinQueryInfos + { + get + { + _JoinQueryInfos = UtilMethods.IsNullReturnNew(_JoinQueryInfos); + return _JoinQueryInfos; + } + set { _JoinQueryInfos = value; } + } + public virtual string TableShortName { get; set; } + public virtual List WhereInfos + { + get + { + _WhereInfos = UtilMethods.IsNullReturnNew(_WhereInfos); + return _WhereInfos; + } + set { _WhereInfos = value; } + } + public virtual string HavingInfos + { + get + { + return _HavingInfos; + } + set + { + _HavingInfos = value; + } + } + #endregion + + #region Lambada Type + public ResolveExpressType SelectType + { + get + { + return this.IsSingle() ? ResolveExpressType.SelectSingle : ResolveExpressType.SelectMultiple; + } + } + public ResolveExpressType WheretType + { + get + { + return this.IsSingle() ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple; + } + } + #endregion + + #region Sql Template + public virtual string SqlTemplate + { + get + { + return "SELECT {0} FROM {1}{2}{3}{4} "; + } + } + public virtual string JoinTemplate + { + get + { + return "{0}JOIN {1}{2}ON {3} "; + } + } + public virtual string PageTempalte + { + get + { + return @"SELECT * FROM ({0}) T WHERE RowIndex BETWEEN {1} AND {2}"; + } + } + public virtual string ExternalPageTempalte + { + get + { + return @"SELECT * FROM ({0}) T WHERE RowIndex2 BETWEEN {1} AND {2}"; + } + } + public virtual string DefaultOrderByTemplate + { + get + { + return "ORDER BY "+this.Builder.SqlDateNow+" "; + } + } + public virtual string OrderByTemplate + { + get + { + return "ORDER BY "; + } + } + public virtual string GroupByTemplate + { + get + { + return "GROUP BY "; + } + } + public virtual string PartitionByTemplate + { + get + { + return "PARTITION BY "; + } + } + public virtual string MaxTemplate + { + get + { + return "MAX({0})"; + } + } + public virtual string MinTemplate + { + get + { + return "MIN({0})"; + } + } + public virtual string SumTemplate + { + get + { + return "SUM({0})"; + } + } + public virtual string AvgTemplate + { + get + { + return "AVG({0})"; + } + } + public virtual string InTemplate + { + get + { + return "{0} IN ({1}) "; + } + } + #endregion + + #region Common Methods + public virtual bool IsSingle() + { + var isSingle = Builder.QueryBuilder.JoinQueryInfos.IsNullOrEmpty() && !EasyJoinInfos.Any(); + return isSingle; + } + public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType) + { + ILambdaExpressions resolveExpress = this.LambdaExpressions; + if (resolveType.IsIn(ResolveExpressType.FieldSingle,ResolveExpressType.FieldMultiple,ResolveExpressType.SelectSingle, ResolveExpressType.SelectMultiple) &&(expression is LambdaExpression)&& (expression as LambdaExpression).Body is BinaryExpression) { + resolveType = resolveType.IsIn(ResolveExpressType.SelectSingle, ResolveExpressType.FieldSingle) ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple; + } + this.LambdaExpressions.Clear(); + resolveExpress.JoinQueryInfos = Builder.QueryBuilder.JoinQueryInfos; + resolveExpress.IsSingle = IsSingle(); + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + resolveExpress.InitMappingInfo = this.Context.InitMappingInfo; + resolveExpress.RefreshMapping = () => + { + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + }; + resolveExpress.Resolve(expression, resolveType); + this.Parameters.AddRange(resolveExpress.Parameters); + var result = resolveExpress.Result; + var isSingleTableHasSubquery = IsSingle() && resolveExpress.SingleTableNameSubqueryShortName.HasValue(); + if (isSingleTableHasSubquery) { + Check.Exception(!string.IsNullOrEmpty(this.TableShortName) && resolveExpress.SingleTableNameSubqueryShortName != this.TableShortName, "{0} and {1} need same name"); + this.TableShortName = resolveExpress.SingleTableNameSubqueryShortName; + } + return result; + } + public virtual string ToSqlString() + { + string oldOrderBy = this.OrderByValue; + string externalOrderBy = oldOrderBy; + var isIgnoreOrderBy = this.IsCount&&this.PartitionByValue.IsNullOrEmpty(); + AppendFilter(); + sql = new StringBuilder(); + if (this.OrderByValue == null && (Skip != null || Take != null)) this.OrderByValue = " ORDER BY GetDate() "; + if (this.PartitionByValue.HasValue()) + { + this.OrderByValue = this.PartitionByValue + this.OrderByValue; + } + var isRowNumber = Skip != null || Take != null; + var rowNumberString = string.Format(",ROW_NUMBER() OVER({0}) AS RowIndex ", GetOrderByString); + string groupByValue = GetGroupByString + HavingInfos; + string orderByValue = (!isRowNumber && this.OrderByValue.HasValue()) ? GetOrderByString : null; + if (isIgnoreOrderBy) { orderByValue = null; } + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, groupByValue, orderByValue); + sql.Replace(UtilConstants.ReplaceKey, isRowNumber ? (isIgnoreOrderBy ? null : rowNumberString) : null); + if (isIgnoreOrderBy) { this.OrderByValue = oldOrderBy; return sql.ToString(); } + var result = ToPageSql(sql.ToString(), this.Take, this.Skip); + if (ExternalPageIndex > 0) + { + if (externalOrderBy.IsNullOrEmpty()) + { + externalOrderBy = " ORDER BY GetDate() "; + } + result = string.Format("SELECT *,ROW_NUMBER() OVER({0}) AS RowIndex2 FROM ({1}) ExternalTable ", GetExternalOrderBy(externalOrderBy), result); + result = ToPageSql2(result, ExternalPageIndex, ExternalPageSize, true); + } + this.OrderByValue = oldOrderBy; + return result; + } + + public virtual void AppendFilter() + { + if (!IsDisabledGobalFilter && this.Context.QueryFilter.GeFilterList.HasValue()) + { + var gobalFilterList = this.Context.QueryFilter.GeFilterList.Where(it => it.FilterName.IsNullOrEmpty()).ToList(); + foreach (var item in gobalFilterList.Where(it => it.IsJoinQuery == !IsSingle())) + { + var filterResult = item.FilterValue(this.Context); + WhereInfos.Add(this.Builder.AppendWhereOrAnd(this.WhereInfos.IsNullOrEmpty(), filterResult.Sql+UtilConstants.Space)); + var filterParamters = this.Context.Ado.GetParameters(filterResult.Parameters); + if (filterParamters.HasValue()) + { + this.Parameters.AddRange(filterParamters); + } + } + } + } + + public virtual string GetExternalOrderBy(string externalOrderBy) + { + return Regex.Replace(externalOrderBy, @"\[\w+\]\.", ""); + } + + public virtual string ToCountSql(string sql) + { + + return string.Format(" SELECT COUNT(1) FROM ({0}) CountTable ", sql); + } + + public virtual string ToPageSql(string sql, int? take, int? skip, bool isExternal = false) + { + string temp = isExternal ? ExternalPageTempalte : PageTempalte; + if (skip != null && take == null) + { + return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, long.MaxValue); + } + else if (skip == null && take != null) + { + return string.Format(temp, sql.ToString(), 1, take.ObjToInt()); + } + else if (skip != null && take != null) + { + return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, skip.ObjToInt() + take.ObjToInt()); + } + else + { + return sql.ToString(); + } + } + + public virtual string ToPageSql2(string sql, int? pageIndex, int? pageSize, bool isExternal = false) + { + string temp = isExternal ? ExternalPageTempalte : PageTempalte; + return string.Format(temp, sql.ToString(), (pageIndex - 1) * pageSize+1, pageIndex * pageSize); + } + + public virtual string GetSelectByItems(List> items) + { + var array = items.Select(it => { + dynamic dynamicObj = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(it.Value)); + var dbName =Builder.GetTranslationColumnName( (string)(dynamicObj.dbName)); + var asName = Builder.GetTranslationColumnName((string)(dynamicObj.asName)); + return string.Format("{0}.{1} AS {2}",it.Key,dbName,asName); + }); + return string.Join(",",array); + } + + public virtual string ToJoinString(JoinQueryInfo joinInfo) + { + return string.Format( + this.JoinTemplate, + joinInfo.JoinType.ToString() + UtilConstants.Space, + Builder.GetTranslationTableName(joinInfo.TableName) + UtilConstants.Space, + joinInfo.ShortName + UtilConstants.Space + TableWithString, + joinInfo.JoinWhere); + } + public virtual void Clear() + { + this.Skip = 0; + this.Take = 0; + this.sql = null; + this.WhereIndex = 0; + this.Parameters = null; + this.GroupByValue = null; + this._TableNameString = null; + this.WhereInfos = null; + this.JoinQueryInfos = null; + this.IsDistinct = false; + } + public virtual bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS \[\w+\.\w+\]"); + } + #endregion + + #region Get SQL Partial + public virtual string GetSelectValue + { + get + { + string result = string.Empty; + if (this.SelectValue == null || this.SelectValue is string) + { + result = GetSelectValueByString(); + } + else + { + result = GetSelectValueByExpression(); + } + if (this.SelectType == ResolveExpressType.SelectMultiple) + { + this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this._JoinQueryInfos.Select(it => it.TableName)); + } + if (IsDistinct) + { + result = " DISTINCT " + result; + } + return result; + } + } + public virtual string GetSelectValueByExpression() + { + var expression = this.SelectValue as Expression; + var result = GetExpressionValue(expression, this.SelectType).GetResultString(); + if (result == null) + { + return "*"; + } + if (result.Contains(".*") && this.IsSingle()) + { + return "*"; + } + else + { + if (expression is LambdaExpression && (expression as LambdaExpression).Body is MethodCallExpression&&this.Context.CurrentConnectionConfig.DbType==DbType.SqlServer&&this.OrderByValue.HasValue()) + { + result = result + " AS columnName"; + } + this.SelectCacheKey = result; + return result; + } + } + public virtual string GetSelectValueByString() + { + string result; + if (this.SelectValue.IsNullOrEmpty()) + { + string pre = null; + if (this.JoinQueryInfos.HasValue() && this.JoinQueryInfos.Any(it => TableShortName.HasValue())) + { + pre = Builder.GetTranslationColumnName(TableShortName) + "."; + } + var columns = this.Context.EntityMaintenance.GetEntityInfo(this.EntityType).Columns.Where(it => !it.IsIgnore); + if (this.IgnoreColumns.HasValue()) + { + columns = columns.Where(c => !this.IgnoreColumns.Any(i=>c.PropertyName.Equals(i,StringComparison.CurrentCultureIgnoreCase)||c.DbColumnName.Equals(i,StringComparison.CurrentCultureIgnoreCase))).ToList(); + } + result = string.Join(",", columns.Select(it => pre + Builder.GetTranslationColumnName(it.EntityName, it.PropertyName))); + } + else + { + result = this.SelectValue.ObjToString(); + this.SelectCacheKey = result; + } + if (result.IsNullOrEmpty()) + { + result = "*"; + } + return result; + } + public virtual string GetWhereValueString + { + get + { + if (this.WhereInfos == null) return null; + else + { + return string.Join(UtilConstants.Space, this.WhereInfos); + } + } + } + public virtual string GetJoinValueString + { + get + { + if (this.JoinQueryInfos.IsNullOrEmpty()) return null; + else + { + return string.Join(UtilConstants.Space, this.JoinQueryInfos.Select(it => this.ToJoinString(it))); + } + } + } + public virtual string GetTableNameString + { + get + { + var result = Builder.GetTranslationTableName(EntityName); + result += UtilConstants.Space; + if (this.TableShortName.HasValue()) + { + result += (TableShortName + UtilConstants.Space); + } + if (this.TableWithString.HasValue()&&this.TableWithString!= SqlWith.Null) + { + result += TableWithString + UtilConstants.Space; + } + if (!this.IsSingle()) + { + result += GetJoinValueString + UtilConstants.Space; + } + if (this.EasyJoinInfos.IsValuable()) + { + + if (this.TableWithString.HasValue() && this.TableWithString != SqlWith.Null) + { + result += "," + string.Join(",", this.EasyJoinInfos.Select(it => string.Format("{0} {1} {2} ", GetTableName(it.Value), it.Key, TableWithString))); + } + else + { + result += "," + string.Join(",", this.EasyJoinInfos.Select(it => string.Format("{0} {1} ", GetTableName(it.Value), it.Key))); + } + } + return result; + } + } + public virtual string GetOrderByString + { + get + { + if (this.OrderByValue == null) return null; + if (IsCount&&this.PartitionByValue.IsNullOrEmpty()) return null; + else + { + return this.OrderByValue; + } + } + } + public virtual string GetGroupByString + { + get + { + if (this.GroupByValue == null) return null; + if (this.GroupByValue.Last() != ' ' ) + { + return this.GroupByValue + UtilConstants.Space; + } + return this.GroupByValue; + } + } + + #endregion + + private string GetTableName(string entityName) + { + var result = this.Context.EntityMaintenance.GetTableName(entityName); + return this.Builder.GetTranslationTableName(result); + } + + public void CheckExpression(Expression expression, string methodName) + { + if (IsSingle() == false&& this.JoinExpression!=null) + { + var jsoinParameters = (this.JoinExpression as LambdaExpression).Parameters; + var currentParametres = (expression as LambdaExpression).Parameters; + if ((expression as LambdaExpression).Body.ToString() == "True") { + return; + } + if (currentParametres != null && currentParametres.Count > 0) + { + foreach (var item in currentParametres) + { + var index = currentParametres.IndexOf(item); + var name = item.Name; + var joinName = jsoinParameters[index].Name; + Check.Exception(name.ToLower() != joinName.ToLower(), ErrorMessage.ExpressionCheck, joinName, methodName, name); + } + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlBuilderAccessory.cs b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlBuilderAccessory.cs new file mode 100644 index 0000000..dd14e8e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlBuilderAccessory.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial class SqlBuilderAccessory + { + protected DeleteBuilder _DeleteBuilder; + + protected InsertBuilder _InsertBuilder; + + protected QueryBuilder _QueryBuilder; + + protected SqlQueryBuilder _SqlQueryBuilder; + + protected UpdateBuilder _UpdateBuilder; + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs new file mode 100644 index 0000000..a2d5d53 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs @@ -0,0 +1,278 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +namespace SqlSugar +{ + public abstract partial class SqlBuilderProvider : SqlBuilderAccessory, ISqlBuilder + { + #region Properties + public SqlSugarProvider Context { get; set; } + public CommandType CommandType { get; set; } + public DeleteBuilder DeleteBuilder { get; set; } + public InsertBuilder InsertBuilder { get; set; } + public QueryBuilder QueryBuilder { get; set; } + public UpdateBuilder UpdateBuilder { get; set; } + public SqlQueryBuilder SqlQueryBuilder + { + get + { + base._SqlQueryBuilder = UtilMethods.IsNullReturnNew(base._SqlQueryBuilder); + return base._SqlQueryBuilder; + } + set { base._SqlQueryBuilder = value; } + } + #endregion + + #region abstract Methods + public virtual string GetTranslationTableName(string name) + { + Check.ArgumentNullException(name, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + if (name.IsContainsIn("(", ")", SqlTranslationLeft)&&name!= "Dictionary`2") + { + return name; + } + var context = this.Context; + var mappingInfo = context + .MappingTables + .FirstOrDefault(it => it.EntityName.Equals(name, StringComparison.CurrentCultureIgnoreCase)); + name = (mappingInfo == null ? name : mappingInfo.DbTableName); + if (name.IsContainsIn("(", ")", SqlTranslationLeft)) + { + return name; + } + if (name.Contains(".")) + { + return string.Join(".", name.Split('.').Select(it => SqlTranslationLeft + it + SqlTranslationRight)); + } + else + { + return SqlTranslationLeft + name + SqlTranslationRight; + } + } + public virtual string GetTranslationColumnName(string entityName, string propertyName) + { + Check.ArgumentNullException(entityName, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + Check.ArgumentNullException(propertyName, string.Format(ErrorMessage.ObjNotExist, "Column Name")); + var context = this.Context; + var mappingInfo = context + .MappingColumns + .FirstOrDefault(it => + it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase) && + it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + return (mappingInfo == null ? SqlTranslationLeft + propertyName + SqlTranslationRight : SqlTranslationLeft + mappingInfo.DbColumnName + SqlTranslationRight); + } + + public virtual string GetTranslationColumnName(string propertyName) + { + if (propertyName.Contains(SqlTranslationLeft)) return propertyName; + else + return SqlTranslationLeft + propertyName + SqlTranslationRight; + } + + public virtual string GetNoTranslationColumnName(string name) + { + if (name.Contains("=")) + { + name=name.Split('=').First(); + } + if (!name.Contains(SqlTranslationLeft)) return name; + return name == null ? string.Empty : Regex.Match(name, @".*" + "\\" + SqlTranslationLeft + "(.*?)" + "\\" + SqlTranslationRight + "").Groups[1].Value; + } + public virtual string GetPackTable(string sql, string shortName) + { + return UtilMethods.GetPackTable(sql, shortName); + } + public virtual string GetDefaultShortName() + { + return "t"; + } + + + public string GetWhere(string fieldName,string conditionalType,int? parameterIndex=null) + { + return string.Format(" {0} {1} {2}{3} ",fieldName,conditionalType,this.SqlParameterKeyWord,fieldName+ parameterIndex); + } + public virtual string GetUnionAllSql(List sqlList) + { + return string.Join(" UNION ALL \r\n", sqlList); + } + public virtual string GetUnionSql(List sqlList) + { + return string.Join(" UNION \r\n", sqlList); + } + public virtual void RepairReplicationParameters(ref string appendSql, SugarParameter[] parameters, int addIndex) + { + UtilMethods.RepairReplicationParameters(ref appendSql, parameters, addIndex); + } + public KeyValuePair ConditionalModelToSql(List models, int beginIndex = 0) + { + if (models.IsNullOrEmpty()) return new KeyValuePair(); + StringBuilder builder = new StringBuilder(); + List parameters = new List(); + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + foreach (var model in models) + { + if (model is ConditionalModel) + { + var item = model as ConditionalModel; + var index = models.IndexOf(item) + beginIndex; + var type = index == 0 ? "" : "AND"; + if (beginIndex > 0) + { + type = null; + } + string temp = " {0} {1} {2} {3} "; + string parameterName = string.Format("{0}Conditional{1}{2}", sqlBuilder.SqlParameterKeyWord, item.FieldName, index); + if (parameterName.Contains(".")) + { + parameterName = parameterName.Replace(".", "_"); + } + switch (item.ConditionalType) + { + case ConditionalType.Equal: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "=", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.Like: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "LIKE", parameterName); + parameters.Add(new SugarParameter(parameterName, "%" + item.FieldValue + "%")); + break; + case ConditionalType.GreaterThan: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), ">", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.GreaterThanOrEqual: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), ">=", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.LessThan: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "<", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.LessThanOrEqual: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "<=", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.In: + if (item.FieldValue == null) item.FieldValue = string.Empty; + var inValue1 = ("(" + item.FieldValue.Split(',').ToJoinSqlInVals() + ")"); + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "IN", inValue1); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + break; + case ConditionalType.NotIn: + if (item.FieldValue == null) item.FieldValue = string.Empty; + var inValue2 = ("(" + item.FieldValue.Split(',').ToJoinSqlInVals() + ")"); + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "NOT IN", inValue2); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + break; + case ConditionalType.LikeLeft: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "LIKE", parameterName); + parameters.Add(new SugarParameter(parameterName, item.FieldValue + "%")); + break; + case ConditionalType.NoLike: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), " NOT LIKE", parameterName); + parameters.Add(new SugarParameter(parameterName, item.FieldValue + "%")); + break; + case ConditionalType.LikeRight: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "LIKE", parameterName); + parameters.Add(new SugarParameter(parameterName, "%" + item.FieldValue)); + break; + case ConditionalType.NoEqual: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "<>", parameterName); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + break; + case ConditionalType.IsNullOrEmpty: + builder.AppendFormat("{0} ({1}) OR ({2}) ", type, item.FieldName.ToSqlFilter() + " IS NULL ", item.FieldName.ToSqlFilter() + " = '' "); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + break; + case ConditionalType.IsNot: + if (item.FieldValue == null) + { + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), " IS NOT ", "NULL"); + } + else + { + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "<>", parameterName); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + } + break; + default: + break; + } + } + else + { + var item = model as ConditionalCollections; + if (item != null && item.ConditionalList.HasValue()) + { + foreach (var con in item.ConditionalList) + { + var index = item.ConditionalList.IndexOf(con); + var isFirst = index == 0; + var isLast = index == (item.ConditionalList.Count - 1); + if (models.IndexOf(item) == 0 && index == 0 && beginIndex == 0) + { + builder.AppendFormat(" ( "); + + } + else if (isFirst) + { + builder.AppendFormat(" {0} ( ", con.Key.ToString().ToUpper()); + } + List conModels = new List(); + conModels.Add(con.Value); + var childSqlInfo = ConditionalModelToSql(conModels, 1000 * (1 + index) + models.IndexOf(item)); + if (!isFirst) + { + + builder.AppendFormat(" {0} ", con.Key.ToString().ToUpper()); + } + builder.Append(childSqlInfo.Key); + parameters.AddRange(childSqlInfo.Value); + if (isLast) + { + builder.Append(" ) "); + } + else + { + + } + } + } + } + } + return new KeyValuePair(builder.ToString(), parameters.ToArray()); + } + + private static object GetFieldValue(ConditionalModel item) + { + if (item.FieldValueConvertFunc != null) + return item.FieldValueConvertFunc(item.FieldValue); + else + return item.FieldValue; + } + #endregion + + #region Common SqlTemplate + public string AppendWhereOrAnd(bool isWhere, string sqlString) + { + return isWhere ? (" WHERE " + sqlString) : (" AND " + sqlString); + } + public string AppendHaving(string sqlString) + { + return " HAVING " + sqlString; + } + public virtual string SqlParameterKeyWord { get { return "@"; } } + public abstract string SqlTranslationLeft { get; } + public abstract string SqlTranslationRight { get; } + public virtual string SqlFalse { get { return "1=2 "; } } + public virtual string SqlDateNow { get { return "GETDATE()"; } } + public virtual string FullSqlDateNow { get { return "SELECT GETDATE()"; } } + public virtual string SqlSelectAll { get { return "*"; } } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlQueryBuilder.cs b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlQueryBuilder.cs new file mode 100644 index 0000000..2bbdc50 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/SqlQueryBuilder.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class SqlQueryBuilder : IDMLBuilder + { + + #region Fields + private string _Fields; + private StringBuilder _Sql; + private List _Parameters; + #endregion + + #region Properties + public SqlSugarProvider Context { get; set; } + public string Fields + { + get + { + if (this._Fields.IsNullOrEmpty()) + { + this._Fields = Regex.Match(this.sql.ObjToString().Replace("\n", string.Empty).Replace("\r", string.Empty).Trim(), @"select(.*?)from", RegexOptions.IgnoreCase).Groups[1].Value; + if (this._Fields.IsNullOrEmpty()) + { + this._Fields = "*"; + } + } + return this._Fields; + } + set + { + _Fields = value; + } + } + public StringBuilder sql + { + get + { + _Sql = UtilMethods.IsNullReturnNew(_Sql); + return _Sql; + } + set + { + _Sql = value; + } + } + public string SqlTemplate + { + get + { + return null; + } + } + public List Parameters + { + get + { + _Parameters = UtilMethods.IsNullReturnNew(_Parameters); + return _Parameters; + } + set + { + _Parameters = value; + } + } + #endregion + + #region Methods + public string ToSqlString() + { + return sql.ToString(); + } + public void Clear() + { + this.sql = null; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/UpdateBuilder.cs b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/UpdateBuilder.cs new file mode 100644 index 0000000..a5319b9 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SqlBuilderProvider/UpdateBuilder.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class UpdateBuilder : IDMLBuilder + { + public UpdateBuilder() + { + this.sql = new StringBuilder(); + this.DbColumnInfoList = new List(); + this.SetValues = new List>(); + this.WhereValues = new List(); + this.Parameters = new List(); + } + public SqlSugarProvider Context { get; set; } + public ILambdaExpressions LambdaExpressions { get; set; } + public ISqlBuilder Builder { get; set; } + public StringBuilder sql { get; set; } + public List Parameters { get; set; } + public string TableName { get; set; } + public string TableWithString { get; set; } + public List DbColumnInfoList { get; set; } + public List WhereValues { get; set; } + public List> SetValues { get; set; } + public bool IsNoUpdateNull { get; set; } + public bool IsNoUpdateDefaultValue { get; set; } + public List PrimaryKeys { get; set; } + public bool IsOffIdentity { get; set; } + public bool IsWhereColumns { get; set; } + + public virtual string SqlTemplate + { + get + { + return @"UPDATE {0} SET + {1} {2}"; + + } + } + + public virtual string SqlTemplateBatch + { + get + { + return @"UPDATE S SET {0} FROM {1} S {2} INNER JOIN "; + } + } + + public virtual string SqlTemplateJoin + { + get + { + return @" ( + {0} + + ) T ON {1} + ; "; + } + } + + public virtual string SqlTemplateBatchSet + { + get + { + return "{0} AS {1}"; + } + } + public virtual string SqlTemplateBatchSelect + { + get + { + return "{0} AS {1}"; + } + } + + public virtual string SqlTemplateBatchUnion + { + get + { + return "\t\t\r\nUNION ALL "; + } + } + + public virtual void Clear() + { + + } + public virtual string GetTableNameString + { + get + { + var result = Builder.GetTranslationTableName(TableName); + result += UtilConstants.Space; + if (this.TableWithString.HasValue()) + { + result += TableWithString + UtilConstants.Space; + } + return result; + } + } + public virtual string GetTableNameStringNoWith + { + get + { + var result = Builder.GetTranslationTableName(TableName); + return result; + } + } + + public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType, bool isMapping = true) + { + ILambdaExpressions resolveExpress = this.LambdaExpressions; + this.LambdaExpressions.Clear(); + if (isMapping) + { + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + } + resolveExpress.InitMappingInfo = Context.InitMappingInfo; + resolveExpress.RefreshMapping = () => + { + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + }; + resolveExpress.Resolve(expression, resolveType); + this.Parameters.AddRange(resolveExpress.Parameters); + var result = resolveExpress.Result; + return result; + } + public virtual string ToSqlString() + { + if (IsNoUpdateNull) + { + DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList(); + } + if (IsNoUpdateDefaultValue) + { + DbColumnInfoList = DbColumnInfoList.Where(it => it.Value.ObjToString() !=UtilMethods.DefaultForType(it.PropertyType).ObjToString()).ToList(); + } + var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); + var isSingle = groupList.Count() == 1; + if (isSingle) + { + return ToSingleSqlString(groupList); + } + else + { + return TomultipleSqlString(groupList); + } + } + + protected virtual string TomultipleSqlString(List> groupList) + { + Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List need Primary key"); + int pageSize = 200; + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + StringBuilder batchUpdateSql = new StringBuilder(); + while (pageCount >= pageIndex) + { + StringBuilder updateTable = new StringBuilder(); + string setValues = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it => + { + if (SetValues.IsValuable()) + { + var setValue = SetValues.Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName)); + if (setValue != null && setValue.Any()) + { + return setValue.First().Value; + } + } + var result = string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(it.DbColumnName)); + return result; + })); + batchUpdateSql.AppendFormat(SqlTemplateBatch.ToString(), setValues, GetTableNameStringNoWith, TableWithString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + updateTable.Append(SqlTemplateBatchUnion); + } + updateTable.Append("\r\n SELECT " + string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value), Builder.GetTranslationColumnName(it.DbColumnName))))); + ++i; + } + pageIndex++; + updateTable.Append("\r\n"); + string whereString = null; + if (this.WhereValues.HasValue()) + { + foreach (var item in WhereValues) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += Regex.Replace(item,"\\"+this.Builder.SqlTranslationLeft,"S."+ this.Builder.SqlTranslationLeft); + } + } + if (PrimaryKeys.HasValue()) + { + foreach (var item in PrimaryKeys) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(item)); + } + } + batchUpdateSql.AppendFormat(SqlTemplateJoin, updateTable, whereString); + } + return batchUpdateSql.ToString(); + } + + protected virtual string ToSingleSqlString(List> groupList) + { + string columnsString = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it => + { + if (SetValues.IsValuable()) + { + var setValue = SetValues.Where(sv => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName) || sv.Key == Builder.GetTranslationColumnName(it.PropertyName)); + if (setValue != null && setValue.Any()) + { + return setValue.First().Value; + } + } + var result = Builder.GetTranslationColumnName(it.DbColumnName) + "=" + this.Context.Ado.SqlParameterKeyWord + it.DbColumnName; + return result; + })); + string whereString = null; + if (this.WhereValues.HasValue()) + { + foreach (var item in WhereValues) + { + var isFirst = whereString == null; + whereString += (isFirst ? " WHERE " : " AND "); + whereString += item; + } + } + else if (PrimaryKeys.HasValue()) + { + foreach (var item in PrimaryKeys) + { + var isFirst = whereString == null; + whereString += (isFirst ? " WHERE " : " AND "); + whereString += Builder.GetTranslationColumnName(item) + "=" + this.Context.Ado.SqlParameterKeyWord + item; + } + } + if (PrimaryKeys.HasValue()&&IsWhereColumns) + { + foreach (var item in PrimaryKeys) + { + var isFirst = whereString == null; + whereString += (isFirst ? " WHERE " : " AND "); + whereString += Builder.GetTranslationColumnName(item) + "=" + this.Context.Ado.SqlParameterKeyWord + item; + } + } + return string.Format(SqlTemplate, GetTableNameString, columnsString, whereString); + } + + public virtual object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "N'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "N'" + value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SugarProvider/SqlSugarAccessory.cs b/类库/SqlSugar/5.0.0.9/Abstract/SugarProvider/SqlSugarAccessory.cs new file mode 100644 index 0000000..3ebfdc6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SugarProvider/SqlSugarAccessory.cs @@ -0,0 +1,440 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial class SqlSugarProvider + { + #region Properties + public SqlSugarProvider Context + { + get + { + _Context = this; + return _Context; + } + set + { + _Context = value; + } + } + public SqlSugarClient Root { get; set; } + public ConnectionConfig CurrentConnectionConfig { get; set; } + public Dictionary TempItems { get { if (_TempItems == null) { _TempItems = new Dictionary(); } return _TempItems; } set { _TempItems = value; } } + public bool IsSystemTablesConfig { get { return this.CurrentConnectionConfig.InitKeyType == InitKeyType.SystemTable; } } + public Guid ContextID { get; set; } + public MappingTableList MappingTables { get; set; } + public MappingColumnList MappingColumns { get; set; } + public IgnoreColumnList IgnoreColumns { get; set; } + public IgnoreColumnList IgnoreInsertColumns { get; set; } + + + #endregion + + #region Fields + public Dictionary _TempItems; + public QueueList _Queues; + protected ISqlBuilder _SqlBuilder; + protected SqlSugarProvider _Context { get; set; } + protected EntityMaintenance _EntityProvider; + protected IAdo _Ado; + protected ILambdaExpressions _LambdaExpressions; + protected IContextMethods _RewritableMethods; + protected IDbMaintenance _DbMaintenance; + protected QueryFilterProvider _QueryFilterProvider; + protected SimpleClient _SimpleClient; + protected IAdo ContextAdo + { + get + { + return this._Ado; + } + set + { + this._Ado = value; + } + } + protected IContextMethods ContextRewritableMethods + { + get + { + return this._RewritableMethods; + } + set + { + this._RewritableMethods = value; + } + } + #endregion + + #region Init mappingInfo + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + + #region 9-12 + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + protected void InitMappingInfo() + { + InitMappingInfo(); + InitMappingInfo(); + } + #endregion + + public void InitMappingInfo() + { + InitMappingInfo(typeof(T)); + } + public void InitMappingInfo(Type type) + { + string cacheKey = "Context.InitAttributeMappingTables" + type.FullName; + var entityInfo = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + var result = this.Context.EntityMaintenance.GetEntityInfo(type); + return result; + }); + var copyObj = CopyEntityInfo(entityInfo); + InitMappingInfo(copyObj); + } + + private EntityInfo CopyEntityInfo(EntityInfo entityInfo) + { + EntityInfo result = new EntityInfo() + { + DbTableName = entityInfo.DbTableName, + EntityName = entityInfo.EntityName, + Type = entityInfo.Type + }; + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns) + { + EntityColumnInfo column = new EntityColumnInfo() + { + ColumnDescription = item.ColumnDescription, + DataType = item.DataType, + DbColumnName = item.DbColumnName, + DbTableName = item.DbTableName, + DecimalDigits = item.DecimalDigits, + DefaultValue = item.DefaultValue, + EntityName = item.EntityName, + IsIdentity = item.IsIdentity, + IsIgnore = item.IsIgnore, + IsNullable = item.IsNullable, + IsOnlyIgnoreInsert = item.IsOnlyIgnoreInsert, + IsPrimarykey = item.IsPrimarykey, + Length = item.Length, + OldDbColumnName = item.OldDbColumnName, + OracleSequenceName = item.OracleSequenceName, + PropertyInfo = item.PropertyInfo, + PropertyName = item.PropertyName + }; + columns.Add(item); + } + } + result.Columns = columns; + return result; + } + + private void InitMappingInfo(EntityInfo entityInfo) + { + if (this.MappingTables == null) + this.MappingTables = new MappingTableList(); + if (this.MappingColumns == null) + this.MappingColumns = new MappingColumnList(); + if (this.IgnoreColumns == null) + this.IgnoreColumns = new IgnoreColumnList(); + if (this.IgnoreInsertColumns == null) + this.IgnoreInsertColumns = new IgnoreColumnList(); + if (!this.MappingTables.Any(it => it.EntityName == entityInfo.EntityName)) + { + if (entityInfo.DbTableName != entityInfo.EntityName && entityInfo.DbTableName.HasValue()) + { + this.MappingTables.Add(entityInfo.EntityName, entityInfo.DbTableName); + } + } + if (entityInfo.Columns.Any(it => it.EntityName == entityInfo.EntityName)) + { + var mappingColumnInfos = this.MappingColumns.Where(it => it.EntityName == entityInfo.EntityName); + foreach (var item in entityInfo.Columns.Where(it => it.IsIgnore == false)) + { + if (!mappingColumnInfos.Any(it => it.PropertyName == item.PropertyName)) + if (item.PropertyName != item.DbColumnName && item.DbColumnName.HasValue()) + this.MappingColumns.Add(item.PropertyName, item.DbColumnName, item.EntityName); + } + var ignoreInfos = this.IgnoreColumns.Where(it => it.EntityName == entityInfo.EntityName); + foreach (var item in entityInfo.Columns.Where(it => it.IsIgnore)) + { + if (!ignoreInfos.Any(it => it.PropertyName == item.PropertyName)) + this.IgnoreColumns.Add(item.PropertyName, item.EntityName); + } + + var ignoreInsertInfos = this.IgnoreInsertColumns.Where(it => it.EntityName == entityInfo.EntityName); + foreach (var item in entityInfo.Columns.Where(it => it.IsOnlyIgnoreInsert)) + { + if (!ignoreInsertInfos.Any(it => it.PropertyName == item.PropertyName)) + this.IgnoreInsertColumns.Add(item.PropertyName, item.EntityName); + } + } + } + #endregion + + #region Create Instance + protected ISugarQueryable CreateQueryable() + { + ISugarQueryable result = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + return CreateQueryable(result); + } + protected ISugarQueryable CreateQueryable(ISugarQueryable result) + { + Check.Exception(typeof(T).IsClass() == false || typeof(T).GetConstructors().Length == 0, "Queryable<{0}> Error ,{0} is invalid , need is a class,and can new().", typeof(T).Name); + var sqlBuilder = InstanceFactory.GetSqlbuilder(CurrentConnectionConfig); + result.Context = this.Context; + result.SqlBuilder = sqlBuilder; + result.SqlBuilder.QueryBuilder = InstanceFactory.GetQueryBuilder(CurrentConnectionConfig); + result.SqlBuilder.QueryBuilder.Builder = sqlBuilder; + result.SqlBuilder.Context = result.SqlBuilder.QueryBuilder.Context = this; + result.SqlBuilder.QueryBuilder.EntityType = typeof(T); + result.SqlBuilder.QueryBuilder.EntityName = typeof(T).Name; + result.SqlBuilder.QueryBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(CurrentConnectionConfig); + return result; + } + protected InsertableProvider CreateInsertable(T[] insertObjs) where T : class, new() + { + var result = InstanceFactory.GetInsertableProvider(this.CurrentConnectionConfig); + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; + result.Context = this; + result.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); + result.SqlBuilder = sqlBuilder; + result.InsertObjs = insertObjs; + sqlBuilder.InsertBuilder = result.InsertBuilder = InstanceFactory.GetInsertBuilder(this.CurrentConnectionConfig); + sqlBuilder.InsertBuilder.Builder = sqlBuilder; + sqlBuilder.InsertBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); + sqlBuilder.Context = result.SqlBuilder.InsertBuilder.Context = this; + result.Init(); + return result; + } + protected DeleteableProvider CreateDeleteable() where T : class, new() + { + var result = InstanceFactory.GetDeleteableProvider(this.CurrentConnectionConfig); + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; + result.Context = this; + result.SqlBuilder = sqlBuilder; + sqlBuilder.DeleteBuilder = result.DeleteBuilder = InstanceFactory.GetDeleteBuilder(this.CurrentConnectionConfig); + sqlBuilder.DeleteBuilder.Builder = sqlBuilder; + sqlBuilder.DeleteBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); + sqlBuilder.Context = result.SqlBuilder.DeleteBuilder.Context = this; + return result; + } + protected UpdateableProvider CreateUpdateable(T[] UpdateObjs) where T : class, new() + { + var result = InstanceFactory.GetUpdateableProvider(this.CurrentConnectionConfig); + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; + result.Context = this; + result.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); + result.SqlBuilder = sqlBuilder; + result.UpdateObjs = UpdateObjs; + sqlBuilder.UpdateBuilder = result.UpdateBuilder = InstanceFactory.GetUpdateBuilder(this.CurrentConnectionConfig); + sqlBuilder.UpdateBuilder.Builder = sqlBuilder; + sqlBuilder.UpdateBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); + sqlBuilder.Context = result.SqlBuilder.UpdateBuilder.Context = this; + result.Init(); + var ignoreColumns = result.EntityInfo.Columns.Where(it => it.IsOnlyIgnoreUpdate).ToList(); + if (ignoreColumns!=null&&ignoreColumns.Any()) + { + result = (UpdateableProvider)result.IgnoreColumns(ignoreColumns.Select(it=>it.PropertyName).ToArray()); + } + return result; + } + + protected void CreateQueryJoin(Expression joinExpression, Type[] types, ISugarQueryable queryable) + { + this.CreateQueryable(queryable); + string shortName = string.Empty; + List paramters = new List(); + queryable.SqlBuilder.QueryBuilder.JoinQueryInfos = this.GetJoinInfos(queryable.SqlBuilder, joinExpression, ref paramters, ref shortName, types); + queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; + queryable.SqlBuilder.QueryBuilder.JoinExpression = joinExpression; + if (paramters != null) + { + queryable.SqlBuilder.QueryBuilder.Parameters.AddRange(paramters); + } + } + protected void CreateEasyQueryJoin(Expression joinExpression, Type[] types, ISugarQueryable queryable) + { + this.CreateQueryable(queryable); + string shortName = string.Empty; + queryable.SqlBuilder.QueryBuilder.EasyJoinInfos = this.GetEasyJoinInfo(joinExpression, ref shortName, queryable.SqlBuilder, types); + queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; + queryable.SqlBuilder.QueryBuilder.JoinExpression = joinExpression; + } + #endregion + + #region Private methods + private static void CheckDbDependency(ConnectionConfig config) + { + switch (config.DbType) + { + case DbType.MySql: + DependencyManagement.TryMySqlData(); + break; + case DbType.SqlServer: + break; + case DbType.Sqlite: + DependencyManagement.TrySqlite(); + break; + case DbType.Oracle: + DependencyManagement.TryOracle(); + break; + case DbType.PostgreSQL: + DependencyManagement.TryPostgreSQL(); + break; + default: + throw new Exception("ConnectionConfig.DbType is null"); + } + } + protected List GetJoinInfos(ISqlBuilder sqlBuilder, Expression joinExpression, ref List parameters, ref string shortName, params Type[] entityTypeArray) + { + List result = new List(); + var lambdaParameters = ((LambdaExpression)joinExpression).Parameters.ToList(); + ILambdaExpressions expressionContext = sqlBuilder.QueryBuilder.LambdaExpressions; + expressionContext.MappingColumns = this.MappingColumns; + expressionContext.MappingTables = this.MappingTables; + if (this.Context.CurrentConnectionConfig.ConfigureExternalServices != null) + expressionContext.SqlFuncServices = this.Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + expressionContext.Resolve(joinExpression, ResolveExpressType.Join); + int i = 0; + var joinArray = MergeJoinArray(expressionContext.Result.GetResultArray()); + if (joinArray == null) return null; + parameters = expressionContext.Parameters; + foreach (var entityType in entityTypeArray) + { + var isFirst = i == 0; ++i; + JoinQueryInfo joinInfo = new JoinQueryInfo(); + var hasMappingTable = expressionContext.MappingTables.HasValue(); + MappingTable mappingInfo = null; + if (hasMappingTable) + { + mappingInfo = expressionContext.MappingTables.FirstOrDefault(it => it.EntityName.Equals(entityType.Name, StringComparison.CurrentCultureIgnoreCase)); + joinInfo.TableName = mappingInfo != null ? mappingInfo.DbTableName : entityType.Name; + } + else + { + joinInfo.TableName = entityType.Name; + } + if (isFirst) + { + var firstItem = lambdaParameters.First(); + lambdaParameters.Remove(firstItem); + shortName = firstItem.Name; + } + var joinString = joinArray[i * 2 - 2]; + joinInfo.ShortName = lambdaParameters[i - 1].Name; + joinInfo.JoinType = (JoinType)Enum.Parse(typeof(JoinType), joinString); + joinInfo.JoinWhere = joinArray[i * 2 - 1]; + joinInfo.JoinIndex = i; + result.Add((joinInfo)); + } + expressionContext.Clear(); + return result; + } + + private string[] MergeJoinArray(string[] joinArray) + { + List result = new List(); + string joinValue = null; + int i = 0; + if (joinArray == null) return null; + foreach (var item in joinArray) + { + ++i; + var isLast = joinArray.Length == i; + var isJoinType = item.IsIn(JoinType.Inner.ToString(), JoinType.Left.ToString(), JoinType.Right.ToString()); + if (isJoinType) + { + if (joinValue != null) + result.Add(joinValue); + joinValue = null; + result.Add(item); + } + else + { + isJoinType = false; + joinValue += joinValue == null ? item : ("," + item); + } + if (isLast) + { + result.Add(joinValue); + } + } + return result.ToArray(); ; + } + + protected Dictionary GetEasyJoinInfo(Expression joinExpression, ref string shortName, ISqlBuilder builder, params Type[] entityTypeArray) + { + Dictionary result = new Dictionary(); + var lambdaParameters = ((LambdaExpression)joinExpression).Parameters.ToList(); + shortName = lambdaParameters.First().Name; + var index = 1; + foreach (var item in entityTypeArray) + { + result.Add(UtilConstants.Space + lambdaParameters[index].Name, item.Name); + ++index; + } + return result; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/SugarProvider/SqlSugarProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/SugarProvider/SqlSugarProvider.cs new file mode 100644 index 0000000..c34bb5a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/SugarProvider/SqlSugarProvider.cs @@ -0,0 +1,987 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +namespace SqlSugar +{ + /// + /// ** description:Create datathis.access object + /// ** author:sunkaixuan + /// ** date:2017/1/2 + /// ** email:610262374@qq.com + /// + public partial class SqlSugarProvider: ISqlSugarClient + { + + #region Constructor + public SqlSugarProvider(ConnectionConfig config) + { + this.Context = this; + this.CurrentConnectionConfig = config; + this.ContextID = Guid.NewGuid(); + Check.ArgumentNullException(config, "config is null"); + CheckDbDependency(config); + } + #endregion + + #region ADO Methods + /// + ///Datathis.operation + /// + public virtual IAdo Ado + { + get + { + if (this.ContextAdo == null) + { + var result = InstanceFactory.GetAdo(this.Context.CurrentConnectionConfig); + this.ContextAdo = result; + result.Context = this; + return result; + } + return this._Ado; + } + } + #endregion + + #region Aop Log Methods + public virtual AopProvider Aop { get { return new AopProvider(this); } } + #endregion + + #region Util Methods + [Obsolete("Use SqlSugarClient.Utilities")] + public virtual IContextMethods RewritableMethods + { + get { return this.Context.Utilities; } + set { this.Context.Utilities = value; } + } + public virtual IContextMethods Utilities + { + get + { + if (ContextRewritableMethods == null) + { + ContextRewritableMethods = new ContextMethods(); + ContextRewritableMethods.Context = this; + } + return ContextRewritableMethods; + } + set { ContextRewritableMethods = value; } + } + #endregion + + #region Queryable + /// + /// Get datebase time + /// + /// + public DateTime GetDate() + { + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + return this.Ado.GetDateTime(sqlBuilder.FullSqlDateNow); + } + /// + /// Lambda Query operation + /// + public virtual ISugarQueryable Queryable() + { + + InitMappingInfo(); + var result = this.CreateQueryable(); + return result; + } + /// + /// Lambda Query operation + /// + public virtual ISugarQueryable Queryable(string shortName) + { + Check.Exception(shortName.HasValue() && shortName.Length > 20, ErrorMessage.GetThrowMessage("shortName参数长度不能超过20,你可能是想用这个方法 db.SqlQueryable(sql)而不是db.Queryable(shortName)", "Queryable.shortName max length 20")); + var queryable = Queryable(); + queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; + return queryable; + } + /// + /// Lambda Query operation + /// + public virtual ISugarQueryable Queryable(string tableName, string shortName) + { + var queryable = Queryable(); + queryable.SqlBuilder.QueryBuilder.EntityName = tableName; + queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + #region 9-12 + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + #endregion + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + + #region 9-12 + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMappingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(ISugarQueryable queryable) where T : class, new() + { + var sqlobj = queryable.ToSql(); + return this.SqlQueryable(sqlobj.Key).AddParameters(sqlobj.Value); + } + public virtual ISugarQueryable Queryable( + ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, Expression> joinExpression) where T : class, new() where T2 : class, new() + { + return Queryable(joinQueryable1, joinQueryable2, JoinType.Inner, joinExpression); + } + public virtual ISugarQueryable Queryable( + ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, JoinType joinType, Expression> joinExpression) where T : class, new() where T2 : class, new() + { + Check.Exception(joinQueryable1.QueryBuilder.Take != null || joinQueryable1.QueryBuilder.Skip != null || joinQueryable1.QueryBuilder.OrderByValue.HasValue(), "joinQueryable1 Cannot have 'Skip' 'ToPageList' 'Take' Or 'OrderBy'"); + Check.Exception(joinQueryable2.QueryBuilder.Take != null || joinQueryable2.QueryBuilder.Skip != null || joinQueryable2.QueryBuilder.OrderByValue.HasValue(), "joinQueryable2 Cannot have 'Skip' 'ToPageList' 'Take' Or 'OrderBy'"); + + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + + sqlBuilder.Context = this; + InitMappingInfo(); + var types = new Type[] { typeof(T2) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + queryable.Context = this.Context; + queryable.SqlBuilder = sqlBuilder; + queryable.QueryBuilder = InstanceFactory.GetQueryBuilder(this.CurrentConnectionConfig); + queryable.QueryBuilder.JoinQueryInfos = new List(); + queryable.QueryBuilder.Builder = sqlBuilder; + queryable.QueryBuilder.Context = this; + queryable.QueryBuilder.EntityType = typeof(T); + queryable.QueryBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); + + //master + var shortName1 = joinExpression.Parameters[0].Name; + var sqlObj1 = joinQueryable1.ToSql(); + string sql1 = sqlObj1.Key; + UtilMethods.RepairReplicationParameters(ref sql1, sqlObj1.Value.ToArray(), 0, "Join"); + queryable.QueryBuilder.EntityName = sqlBuilder.GetPackTable(sql1, shortName1); ; + queryable.QueryBuilder.Parameters.AddRange(sqlObj1.Value); + + //join table 1 + var shortName2 = joinExpression.Parameters[1].Name; + var sqlObj2 = joinQueryable2.ToSql(); + string sql2 = sqlObj2.Key; + UtilMethods.RepairReplicationParameters(ref sql2, sqlObj2.Value.ToArray(), 1, "Join"); + queryable.QueryBuilder.Parameters.AddRange(sqlObj2.Value); + var exp = queryable.QueryBuilder.GetExpressionValue(joinExpression, ResolveExpressType.WhereMultiple); + queryable.QueryBuilder.JoinQueryInfos.Add(new JoinQueryInfo() { JoinIndex = 0, JoinType = joinType, JoinWhere = exp.GetResultString(), TableName = sqlBuilder.GetPackTable(sql2, shortName2) }); + + return queryable; + } + #endregion + + public virtual ISugarQueryable UnionAll(params ISugarQueryable[] queryables) where T : class, new() + { + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + Check.Exception(queryables.IsNullOrEmpty(), "UnionAll.queryables is null "); + int i = 1; + List>> allItems = new List>>(); + foreach (var item in queryables) + { + var sqlObj = item.ToSql(); + string sql = sqlObj.Key; + UtilMethods.RepairReplicationParameters(ref sql, sqlObj.Value.ToArray(), i, "UnionAll"); + if (sqlObj.Value.HasValue()) + allItems.Add(new KeyValuePair>(sql, sqlObj.Value)); + else + allItems.Add(new KeyValuePair>(sql, new List())); + i++; + } + var allSql = sqlBuilder.GetUnionAllSql(allItems.Select(it => it.Key).ToList()); + var allParameters = allItems.SelectMany(it => it.Value).ToArray(); + var resulut = this.Context.Queryable().AS(UtilMethods.GetPackTable(allSql, "unionTable")).With(SqlWith.Null); + resulut.AddParameters(allParameters); + return resulut.Select(sqlBuilder.SqlSelectAll); + } + public virtual ISugarQueryable UnionAll(List> queryables) where T : class, new() + { + Check.Exception(queryables.IsNullOrEmpty(), "UnionAll.queryables is null "); + return UnionAll(queryables.ToArray()); + } + public virtual ISugarQueryable Union(params ISugarQueryable[] queryables) where T : class, new() + { + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + Check.Exception(queryables.IsNullOrEmpty(), "UnionAll.queryables is null "); + int i = 1; + List>> allItems = new List>>(); + foreach (var item in queryables) + { + var sqlObj = item.ToSql(); + string sql = sqlObj.Key; + UtilMethods.RepairReplicationParameters(ref sql, sqlObj.Value.ToArray(), i, "Union"); + if (sqlObj.Value.HasValue()) + allItems.Add(new KeyValuePair>(sql, sqlObj.Value)); + else + allItems.Add(new KeyValuePair>(sql, new List())); + i++; + } + var allSql = sqlBuilder.GetUnionSql(allItems.Select(it => it.Key).ToList()); + var allParameters = allItems.SelectMany(it => it.Value).ToArray(); + var resulut = this.Context.Queryable().AS(UtilMethods.GetPackTable(allSql, "unionTable")).With(SqlWith.Null); + resulut.AddParameters(allParameters); + return resulut.Select(sqlBuilder.SqlSelectAll); + } + public virtual ISugarQueryable Union(List> queryables) where T : class, new() + { + Check.Exception(queryables.IsNullOrEmpty(), "Union.queryables is null "); + return Union(queryables.ToArray()); + } + #endregion + + #region SqlQueryable + public ISugarQueryable SqlQueryable(string sql) where T : class, new() + { + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + return this.Context.Queryable().AS(sqlBuilder.GetPackTable(sql, sqlBuilder.GetDefaultShortName())).With(SqlWith.Null).Select(sqlBuilder.GetDefaultShortName() + ".*"); + } + #endregion + + #region Insertable + public virtual IInsertable Insertable(T[] insertObjs) where T : class, new() + { + InitMappingInfo(); + InsertableProvider result = this.CreateInsertable(insertObjs); + return result; + } + public virtual IInsertable Insertable(List insertObjs) where T : class, new() + { + if (insertObjs == null|| insertObjs.IsNullOrEmpty()) + { + insertObjs = new List(); + insertObjs.Add(default(T)); + } + return this.Context.Insertable(insertObjs.ToArray()); + } + public virtual IInsertable Insertable(T insertObj) where T : class, new() + { + return this.Context.Insertable(new T[] { insertObj }); + } + public virtual IInsertable Insertable(Dictionary columnDictionary) where T : class, new() + { + InitMappingInfo(); + Check.Exception(columnDictionary == null || columnDictionary.Count == 0, "Insertable.columnDictionary can't be null"); + var insertObject = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(columnDictionary)); + var columns = columnDictionary.Select(it => it.Key).ToList(); + return this.Context.Insertable(insertObject).InsertColumns(columns.ToArray()); ; + } + public virtual IInsertable Insertable(dynamic insertDynamicObject) where T : class, new() + { + InitMappingInfo(); + if (insertDynamicObject is T) + { + return this.Context.Insertable((T)insertDynamicObject); + } + else + { + var columns = ((object)insertDynamicObject).GetType().GetProperties().Select(it => it.Name).ToList(); + Check.Exception(columns.IsNullOrEmpty(), "Insertable.updateDynamicObject can't be null"); + T insertObject = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(insertDynamicObject)); + return this.Context.Insertable(insertObject).InsertColumns(columns.ToArray()); + } + } + #endregion + + #region Deleteable + public virtual IDeleteable Deleteable() where T : class, new() + { + InitMappingInfo(); + DeleteableProvider result = this.CreateDeleteable(); + return result; + } + public virtual IDeleteable Deleteable(Expression> expression) where T : class, new() + { + InitMappingInfo(); + return this.Context.Deleteable().Where(expression); + } + public virtual IDeleteable Deleteable(dynamic primaryKeyValue) where T : class, new() + { + InitMappingInfo(); + return this.Context.Deleteable().In(primaryKeyValue); + } + public virtual IDeleteable Deleteable(dynamic[] primaryKeyValues) where T : class, new() + { + InitMappingInfo(); + return this.Context.Deleteable().In(primaryKeyValues); + } + public virtual IDeleteable Deleteable(List pkValue) where T : class, new() + { + InitMappingInfo(); + return this.Context.Deleteable().In(pkValue); + } + public virtual IDeleteable Deleteable(T deleteObj) where T : class, new() + { + InitMappingInfo(); + return this.Context.Deleteable().Where(deleteObj); + } + public virtual IDeleteable Deleteable(List deleteObjs) where T : class, new() + { + InitMappingInfo(); + return this.Context.Deleteable().Where(deleteObjs); + } + #endregion + + #region Updateable + public virtual IUpdateable Updateable(T[] UpdateObjs) where T : class, new() + { + InitMappingInfo(); + UpdateableProvider result = this.CreateUpdateable(UpdateObjs); + return result; + } + public virtual IUpdateable Updateable(List UpdateObjs) where T : class, new() + { + Check.ArgumentNullException(UpdateObjs, "Updateable.UpdateObjs can't be null"); + return Updateable(UpdateObjs.ToArray()); + } + public virtual IUpdateable Updateable(T UpdateObj) where T : class, new() + { + return this.Context.Updateable(new T[] { UpdateObj }); + } + public virtual IUpdateable Updateable() where T : class, new() + { + var result = this.Context.Updateable(new T[] { new T() }); + result.UpdateParameterIsNull = true; + return result; + } + public virtual IUpdateable Updateable(Expression> columns) where T : class, new() + { + var result = this.Context.Updateable().SetColumns(columns); + result.UpdateParameterIsNull = true; + return result; + } + public virtual IUpdateable Updateable(Expression> columns) where T : class, new() + { + var result = this.Context.Updateable().SetColumns(columns); + result.UpdateParameterIsNull = true; + return result; + } + + + public virtual IUpdateable Updateable(Dictionary columnDictionary) where T : class, new() + { + InitMappingInfo(); + Check.Exception(columnDictionary == null || columnDictionary.Count == 0, "Updateable.columnDictionary can't be null"); + var updateObject = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(columnDictionary)); + var columns = columnDictionary.Select(it => it.Key).ToList(); + return this.Context.Updateable(updateObject).UpdateColumns(columns.ToArray()); ; + } + public virtual IUpdateable Updateable(dynamic updateDynamicObject) where T : class, new() + { + InitMappingInfo(); + if (updateDynamicObject is T) + { + return this.Context.Updateable((T)updateDynamicObject); + } + else + { + var columns = ((object)updateDynamicObject).GetType().GetProperties().Select(it => it.Name).ToList(); + Check.Exception(columns.IsNullOrEmpty(), "Updateable.updateDynamicObject can't be null"); + T updateObject = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(updateDynamicObject)); + return this.Context.Updateable(updateObject).UpdateColumns(columns.ToArray()); ; + } + } + #endregion + + #region Saveable + public ISaveable Saveable(List saveObjects) where T : class, new() + { + return new SaveableProvider(this, saveObjects); + } + public ISaveable Saveable(T saveObject) where T : class, new() + { + return new SaveableProvider(this, saveObject); + } + #endregion + + #region DbFirst + public virtual IDbFirst DbFirst + { + get + { + IDbFirst dbFirst = InstanceFactory.GetDbFirst(this.Context.CurrentConnectionConfig); + dbFirst.Context = this.Context; + dbFirst.Init(); + return dbFirst; + } + } + #endregion + + #region CodeFirst + public virtual ICodeFirst CodeFirst + { + get + { + ICodeFirst codeFirst = InstanceFactory.GetCodeFirst(this.Context.CurrentConnectionConfig); + codeFirst.Context = this; + return codeFirst; + } + } + #endregion + + #region Db Maintenance + public virtual IDbMaintenance DbMaintenance + { + get + { + if (this._DbMaintenance == null) + { + IDbMaintenance maintenance = InstanceFactory.GetDbMaintenance(this.Context.CurrentConnectionConfig); + this._DbMaintenance = maintenance; + maintenance.Context = this; + } + return this._DbMaintenance; + } + } + #endregion + + #region Entity Maintenance + [Obsolete("Use SqlSugarClient.EntityMaintenance")] + public virtual EntityMaintenance EntityProvider + { + get { return this.Context.EntityMaintenance; } + set { this.Context.EntityMaintenance = value; } + } + public virtual EntityMaintenance EntityMaintenance + { + get + { + if (this._EntityProvider == null) + { + this._EntityProvider = new EntityMaintenance(); + this._EntityProvider.Context = this; + } + return this._EntityProvider; + } + set { this._EntityProvider = value; } + } + #endregion + + #region Gobal Filter + public virtual QueryFilterProvider QueryFilter + { + get + { + if (this._QueryFilterProvider == null) + { + this._QueryFilterProvider = new QueryFilterProvider(); + this._QueryFilterProvider.Context = this; + } + return this._QueryFilterProvider; + } + set { this._QueryFilterProvider = value; } + } + #endregion + + #region SimpleClient + [Obsolete("Use SqlSugarClient.GetSimpleClient() Or SqlSugarClient.GetSimpleClient() ")] + public virtual SimpleClient SimpleClient + { + get + { + if (this._SimpleClient == null) + this._SimpleClient = new SimpleClient(this); + return this._SimpleClient; + } + } + public virtual SimpleClient GetSimpleClient() where T : class, new() + { + return new SimpleClient(this); + } + public virtual SimpleClient GetSimpleClient() + { + if (this._SimpleClient == null) + this._SimpleClient = new SimpleClient(this); + return this._SimpleClient; + } + #endregion + + #region Dispose OR Close + public virtual void Close() + { + if (this.Context.Ado != null) + this.Context.Ado.Close(); + } + public virtual void Open() + { + if (this.Context.Ado != null) + this.Context.Ado.Open(); + } + public virtual void Dispose() + { + if (this.Context.Ado != null) + this.Context.Ado.Dispose(); + } + #endregion + + #region Queue + public int SaveQueues(bool isTran = true) + { + return SaveQueuesProvider(isTran, (sql, parameters) => { return this.Ado.ExecuteCommand(sql, parameters); }); + } + + public async Task SaveQueuesAsync(bool isTran = true) + { + return await SaveQueuesProviderAsync(isTran, (sql, parameters) => { return this.Ado.ExecuteCommandAsync(sql, parameters); }); + } + public List SaveQueues(bool isTran = true) + { + return SaveQueuesProvider(isTran, (sql, parameters) => { return this.Ado.SqlQuery(sql, parameters); }); + } + public async Task> SaveQueuesAsync(bool isTran = true) + { + return await SaveQueuesProviderAsync(isTran, (sql, parameters) => { return this.Ado.SqlQueryAsync(sql, parameters); }); + } + public Tuple, List> SaveQueues(bool isTran = true) + { + return SaveQueuesProvider(isTran, (sql, parameters) => { return this.Ado.SqlQuery(sql, parameters); }); + } + public async Task, List>> SaveQueuesAsync(bool isTran = true) + { + return await SaveQueuesProviderAsync(isTran, (sql, parameters) => { return this.Ado.SqlQueryAsync(sql, parameters); }); + } + public Tuple, List, List> SaveQueues(bool isTran = true) + { + return SaveQueuesProvider(isTran, (sql, parameters) => { return this.Ado.SqlQuery(sql, parameters); }); + } + public async Task, List, List>> SaveQueuesAsync(bool isTran = true) + { + return await SaveQueuesProviderAsync(isTran, (sql, parameters) => { return this.Ado.SqlQueryAsync(sql, parameters); }); + } + public Tuple, List, List, List> SaveQueues(bool isTran = true) + { + return SaveQueuesProvider(isTran, (sql, parameters) => { return this.Ado.SqlQuery(sql, parameters); }); + } + public async Task, List, List, List>> SaveQueuesAsync(bool isTran = true) + { + return await SaveQueuesProviderAsync(isTran, (sql, parameters) => { return this.Ado.SqlQueryAsync(sql, parameters); }); + } + public Tuple, List, List, List, List> SaveQueues(bool isTran = true) + { + return SaveQueuesProvider(isTran, (sql, parameters) => { return this.Ado.SqlQuery(sql, parameters); }); + } + public async Task, List, List, List, List>> SaveQueuesAsync(bool isTran = true) + { + return await SaveQueuesProviderAsync(isTran, (sql, parameters) => { return this.Ado.SqlQueryAsync(sql, parameters); }); + } + public Tuple, List, List, List, List, List> SaveQueues(bool isTran = true) + { + return SaveQueuesProvider(isTran, (sql, parameters) => { return this.Ado.SqlQuery(sql, parameters); }); + } + public async Task, List, List, List, List, List>> SaveQueuesAsync(bool isTran = true) + { + return await SaveQueuesProviderAsync(isTran, (sql, parameters) => { return this.Ado.SqlQueryAsync(sql, parameters); }); + } + public Tuple, List, List, List, List, List, List> SaveQueues(bool isTran = true) + { + return SaveQueuesProvider(isTran, (sql, parameters) => { return this.Ado.SqlQuery(sql, parameters); }); + } + public async Task, List, List, List, List, List, List>> SaveQueuesAsync(bool isTran = true) + { + return await SaveQueuesProviderAsync(isTran, (sql, parameters) => { return this.Ado.SqlQueryAsync(sql, parameters); }); + } + public void AddQueue(string sql, object parsmeters=null) + { + if (Queues == null) + { + Queues = new QueueList(); + } + this.Queues.Add(sql,this.Context.Ado.GetParameters(parsmeters)); + } + public void AddQueue(string sql, SugarParameter parsmeter) + { + if (Queues == null) + { + Queues = new QueueList(); + } + this.Queues.Add(sql, new List() { parsmeter }); + } + public void AddQueue(string sql, List parsmeters) + { + if (Queues == null) + { + Queues = new QueueList(); + } + this.Queues.Add(sql, parsmeters); + } + public QueueList Queues { get { if (_Queues == null) { _Queues = new QueueList(); } return _Queues; } set { _Queues = value; } } + + + + private async Task SaveQueuesProviderAsync(bool isTran, Func, Task> func) + { + try + { + if (this.CurrentConnectionConfig.DbType == DbType.Oracle) + { + throw new Exception("Oracle no support SaveQueues"); + } + if (this.Queues == null || this.Queues.Count == 0) return default(T); + isTran = isTran && this.Ado.Transaction == null; + if (isTran) this.Ado.BeginTran(); + StringBuilder sqlBuilder = new StringBuilder(); + var parsmeters = new List(); + var index = 1; + if (this.Queues.HasValue()) + { + foreach (var item in Queues) + { + if (item.Sql == null) + item.Sql = string.Empty; + if (item.Parameters == null) + item.Parameters = new SugarParameter[] { }; + var itemParsmeters = item.Parameters.OrderByDescending(it => it.ParameterName.Length).ToList(); + List addParameters = new List(); + var itemSql = item.Sql; + foreach (var itemParameter in itemParsmeters) + { + var newName = itemParameter.ParameterName + "_q_" + index; + SugarParameter parameter = new SugarParameter(newName, itemParameter.Value); + parameter.DbType = itemParameter.DbType; + itemSql = UtilMethods.ReplaceSqlParameter(itemSql, itemParameter, newName); + addParameters.Add(parameter); + } + parsmeters.AddRange(addParameters); + itemSql = itemSql.TrimEnd(';') + ";"; + sqlBuilder.AppendLine(itemSql); + index++; + } + } + this.Queues.Clear(); + var result =await func(sqlBuilder.ToString(), parsmeters); + if (isTran) this.Ado.CommitTran(); + return result; + } + catch (Exception ex) + { + if (isTran) this.Ado.RollbackTran(); + throw ex; + } + } + private T SaveQueuesProvider(bool isTran, Func, T> func) + { + try + { + if (this.CurrentConnectionConfig.DbType == DbType.Oracle) { + throw new Exception("Oracle no support SaveQueues"); + } + if (this.Queues == null || this.Queues.Count == 0) return default(T); + isTran = isTran && this.Ado.Transaction == null; + if (isTran) this.Ado.BeginTran(); + StringBuilder sqlBuilder = new StringBuilder(); + var parsmeters = new List(); + var index = 1; + if (this.Queues.HasValue()) + { + foreach (var item in Queues) + { + if (item.Sql == null) + item.Sql = string.Empty; + if (item.Parameters == null) + item.Parameters = new SugarParameter[] { }; + var itemParsmeters = item.Parameters.OrderByDescending(it => it.ParameterName.Length).ToList(); + List addParameters = new List(); + var itemSql = item.Sql; + foreach (var itemParameter in itemParsmeters) + { + var newName = itemParameter.ParameterName + "_q_" + index; + SugarParameter parameter = new SugarParameter(newName, itemParameter.Value); + parameter.DbType = itemParameter.DbType; + itemSql = UtilMethods.ReplaceSqlParameter(itemSql, itemParameter, newName); + addParameters.Add(parameter); + } + parsmeters.AddRange(addParameters); + itemSql = itemSql.TrimEnd(';')+";"; + sqlBuilder.AppendLine(itemSql); + index++; + } + } + this.Queues.Clear(); + var result = func(sqlBuilder.ToString(), parsmeters); + if (isTran) this.Ado.CommitTran(); + return result; + } + catch (Exception ex) + { + if (isTran) this.Ado.RollbackTran(); + throw ex; + } + } + + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Abstract/UpdateProvider/UpdateableProvider.cs b/类库/SqlSugar/5.0.0.9/Abstract/UpdateProvider/UpdateableProvider.cs new file mode 100644 index 0000000..cc7d825 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Abstract/UpdateProvider/UpdateableProvider.cs @@ -0,0 +1,735 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class UpdateableProvider : IUpdateable where T : class, new() + { + #region Property + public SqlSugarProvider Context { get; internal set; } + public EntityInfo EntityInfo { get; internal set; } + public ISqlBuilder SqlBuilder { get; internal set; } + public UpdateBuilder UpdateBuilder { get; set; } + public IAdo Ado { get { return Context.Ado; } } + public T[] UpdateObjs { get; set; } + public bool UpdateParameterIsNull { get; set; } + public bool IsMappingTable { get { return this.Context.MappingTables != null && this.Context.MappingTables.Any(); } } + public bool IsMappingColumns { get { return this.Context.MappingColumns != null && this.Context.MappingColumns.Any(); } } + public bool IsSingle { get { return this.UpdateObjs.Length == 1; } } + public List MappingColumnList { get; set; } + private List IgnoreColumnNameList { get; set; } + private List WhereColumnList { get; set; } + private bool IsWhereColumns { get; set; } + private bool IsOffIdentity { get; set; } + private bool IsVersionValidation { get; set; } + public MappingTableList OldMappingTableList { get; set; } + public bool IsAs { get; set; } + public bool IsEnableDiffLogEvent { get; set; } + public DiffLogModel diffModel { get; set; } + private Action RemoveCacheFunc { get; set; } + private int SetColumnsIndex { get; set; } + #endregion + + #region Core + + public KeyValuePair> ToSql() + { + PreToSql(); + string sql = UpdateBuilder.ToSqlString(); + RestoreMapping(); + return new KeyValuePair>(sql, UpdateBuilder.Parameters); + } + public void AddQueue() + { + var sqlObj = this.ToSql(); + this.Context.Queues.Add(sqlObj.Key, sqlObj.Value); + } + public virtual int ExecuteCommand() + { + string sql = _ExecuteCommand(); + var result = this.Ado.ExecuteCommand(sql, UpdateBuilder.Parameters == null ? null : UpdateBuilder.Parameters.ToArray()); + After(sql); + return result; + } + public bool ExecuteCommandHasChange() + { + return this.ExecuteCommand() > 0; + } + public async Task ExecuteCommandAsync() + { + string sql = _ExecuteCommand(); + var result =await this.Ado.ExecuteCommandAsync(sql, UpdateBuilder.Parameters == null ? null : UpdateBuilder.Parameters.ToArray()); + After(sql); + return result; + } + public async Task ExecuteCommandHasChangeAsync() + { + return await this.ExecuteCommandAsync() > 0; + } + #endregion + + public IUpdateable With(string lockString) + { + if (this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer) + this.UpdateBuilder.TableWithString = lockString; + return this; + } + public IUpdateable RemoveDataCache() + { + this.RemoveCacheFunc = () => + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + CacheSchemeMain.RemoveCache(cacheService, this.Context.EntityMaintenance.GetTableName()); + }; + return this; + } + public IUpdateable IsEnableUpdateVersionValidation() + { + this.IsVersionValidation = true; + return this; + } + public IUpdateable AS(string tableName) + { + var entityName = typeof(T).Name; + IsAs = true; + OldMappingTableList = this.Context.MappingTables; + this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); + if (this.Context.MappingTables.Any(it => it.EntityName == entityName)) + { + this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName); + } + this.Context.MappingTables.Add(entityName, tableName); + return this; ; + } + public IUpdateable EnableDiffLogEvent(object businessData = null) + { + Check.Exception(this.UpdateObjs.HasValue() && this.UpdateObjs.Count() > 1, "DiffLog does not support batch operations"); + diffModel = new DiffLogModel(); + this.IsEnableDiffLogEvent = true; + diffModel.BusinessData = businessData; + diffModel.DiffType = DiffType.update; + return this; + } + + + + public IUpdateable IgnoreColumns(bool ignoreAllNullColumns, bool isOffIdentity = false,bool ignoreAllDefaultValue = false) + { + Check.Exception(this.UpdateObjs.Count() > 1 && ignoreAllNullColumns, ErrorMessage.GetThrowMessage("ignoreNullColumn NoSupport batch insert", "ignoreNullColumn 不支持批量操作")); + UpdateBuilder.IsOffIdentity = isOffIdentity; + if (this.UpdateBuilder.LambdaExpressions == null) + this.UpdateBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.Context.CurrentConnectionConfig); + this.UpdateBuilder.IsNoUpdateNull = ignoreAllNullColumns; + this.UpdateBuilder.IsNoUpdateDefaultValue = ignoreAllDefaultValue; + return this; + } + public IUpdateable IgnoreColumns(Expression> columns) + { + var ignoreColumns = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it).ToLower()).ToList(); + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => !ignoreColumns.Contains(it.PropertyName.ToLower())).ToList(); + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => !ignoreColumns.Contains(it.DbColumnName.ToLower())).ToList(); + return this; + } + public IUpdateable IgnoreColumns(string [] columns) + { + if (columns.HasValue()) + { + var ignoreColumns = columns.Select(it => it.ToLower()).ToList() ; + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => !ignoreColumns.Contains(it.PropertyName.ToLower())).ToList(); + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => !ignoreColumns.Contains(it.DbColumnName.ToLower())).ToList(); + } + return this; + } + + + public IUpdateable ReSetValue(Expression> setValueExpression) + { + Check.Exception(!IsSingle, "Batch operation not supported ReSetValue"); + var expResult = UpdateBuilder.GetExpressionValue(setValueExpression, ResolveExpressType.WhereSingle); + var resultString = Regex.Match(expResult.GetResultString(), @"\((.+)\)").Groups[1].Value; + LambdaExpression lambda = setValueExpression as LambdaExpression; + var expression = lambda.Body; + Check.Exception(!(expression is BinaryExpression), "Expression format error"); + Check.Exception( (expression as BinaryExpression).NodeType!=ExpressionType.Equal, "Expression format error"); + var leftExpression = (expression as BinaryExpression).Left; + Check.Exception(!(leftExpression is MemberExpression), "Expression format error"); + var leftResultString = UpdateBuilder.GetExpressionValue(leftExpression, ResolveExpressType.FieldSingle).GetString(); + UpdateBuilder.SetValues.Add(new KeyValuePair(leftResultString, resultString)); + return this; + } + + + public IUpdateable WhereColumns(Expression> columns) + { + this.IsWhereColumns = true; + UpdateBuilder.IsWhereColumns = true; + Check.Exception(UpdateParameterIsNull == true, "Updateable().Updateable is error,Use Updateable(obj).WhereColumns"); + var whereColumns = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it)).ToList(); + if (this.WhereColumnList == null) this.WhereColumnList = new List(); + foreach (var item in whereColumns) + { + this.WhereColumnList.Add(item); + } + return this; + } + public IUpdateable WhereColumns(string columnName) + { + if (this.WhereColumnList == null) this.WhereColumnList = new List(); + this.WhereColumnList.Add(columnName); + return this; + } + public IUpdateable WhereColumns(string[] columnNames) + { + if (this.WhereColumnList == null) this.WhereColumnList = new List(); + foreach (var columnName in columnNames) + { + this.WhereColumnList.Add(columnName); + } + return this; + } + + + public IUpdateable UpdateColumns(Expression> columns) + { + var updateColumns = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it)).ToList(); + List primaryKeys = GetPrimaryKeys(); + foreach (var item in this.UpdateBuilder.DbColumnInfoList) + { + var mappingInfo = primaryKeys.SingleOrDefault(i => item.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null && mappingInfo.Any()) + { + item.IsPrimarykey = true; + } + } + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => updateColumns.Any(uc => uc.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase) || uc.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase)) || it.IsPrimarykey || it.IsIdentity).ToList(); + return this; + } + public IUpdateable UpdateColumns(string[] columns) + { + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => GetPrimaryKeys().Select(iit => iit.ToLower()).Contains(it.DbColumnName.ToLower()) || columns.Contains(it.PropertyName, StringComparer.OrdinalIgnoreCase)).ToList(); + return this; + } + + public IUpdateable SetColumns(Expression> columns) + { + var expResult = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.Update); + var resultArray = expResult.GetResultArray(); + Check.ArgumentNullException(resultArray, "UpdateColumns Parameter error, UpdateColumns(it=>new T{ it.id=1}) is valid, UpdateColumns(it=>T) is error"); + if (resultArray.HasValue()) + { + foreach (var item in resultArray) + { + string key = SqlBuilder.GetNoTranslationColumnName(item); + UpdateBuilder.SetValues.Add(new KeyValuePair(SqlBuilder.GetTranslationColumnName(key), item)); + } + } + this.UpdateBuilder.DbColumnInfoList = UpdateBuilder.DbColumnInfoList.Where(it => (UpdateParameterIsNull==false&&IsPrimaryKey(it)) || UpdateBuilder.SetValues.Any(v => SqlBuilder.GetNoTranslationColumnName(v.Key).Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase) || SqlBuilder.GetNoTranslationColumnName(v.Key).Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase)) || it.IsPrimarykey == true).ToList(); + CheckTranscodeing(); + AppendSets(); + return this; + } + + public IUpdateable SetColumns(Expression> columns) + { + CheckTranscodeing(); + var binaryExp = columns.Body as BinaryExpression; + Check.Exception(!binaryExp.NodeType.IsIn(ExpressionType.Equal), "No support {0}", columns.ToString()); + Check.Exception(!(binaryExp.Left is MemberExpression) && !(binaryExp.Left is UnaryExpression), "No support {0}", columns.ToString()); + Check.Exception(ExpressionTool.IsConstExpression(binaryExp.Left as MemberExpression), "No support {0}", columns.ToString()); + var expResult = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.WhereSingle).GetResultString().Replace(")", " )").Replace("(", "( ").Trim().TrimStart('(').TrimEnd(')'); + string key = SqlBuilder.GetNoTranslationColumnName(expResult); + UpdateBuilder.SetValues.Add(new KeyValuePair(SqlBuilder.GetTranslationColumnName(key), expResult)); + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => (UpdateParameterIsNull == false && IsPrimaryKey(it)) || UpdateBuilder.SetValues.Any(v => SqlBuilder.GetNoTranslationColumnName(v.Key).Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase) || SqlBuilder.GetNoTranslationColumnName(v.Key).Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase)) || it.IsPrimarykey == true).ToList(); + AppendSets(); + return this; + } + + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, Expression> columns) + { + if (isUpdateColumns) + UpdateColumns(columns); + return this; + } + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, string [] columns) + { + if (isUpdateColumns) + UpdateColumns(columns); + return this; + } + + + public IUpdateable SetColumnsIF(bool isUpdateColumns, Expression> columns) + { + if (isUpdateColumns) + SetColumns(columns); + return this; + } + public IUpdateable SetColumnsIF(bool isUpdateColumns, Expression> columns) + { + if (isUpdateColumns) + SetColumns(columns); + return this; + } + + + public IUpdateable Where(Expression> expression) + { + var expResult = UpdateBuilder.GetExpressionValue(expression, ResolveExpressType.WhereSingle); + var whereString = expResult.GetResultString(); + if (expression.ToString().Contains("Subqueryable()")) + { + whereString = whereString.Replace(this.SqlBuilder.GetTranslationColumnName(expression.Parameters.First().Name) + ".", this.SqlBuilder.GetTranslationTableName(this.EntityInfo.DbTableName) + "."); + } + UpdateBuilder.WhereValues.Add(whereString); + return this; + } + public IUpdateable Where(string whereSql, object parameters = null) + { + if (whereSql.HasValue()) + { + UpdateBuilder.WhereValues.Add(whereSql); + } + if (parameters != null) + { + UpdateBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + } + return this; + } + public IUpdateable Where(string fieldName, string conditionalType, object fieldValue) + { + var whereSql = this.SqlBuilder.GetWhere(fieldName, conditionalType, 0); + this.Where(whereSql); + string parameterName = this.SqlBuilder.SqlParameterKeyWord + fieldName + "0"; + this.UpdateBuilder.Parameters.Add(new SugarParameter(parameterName, fieldValue)); + return this; + } + + + + + #region delete obj + [Obsolete] + public IUpdateable UpdateColumns(Expression> columns) + { + return this.SetColumns(columns); + } + [Obsolete] + public IUpdateable UpdateColumns(Expression> columns) + { + return this.SetColumns(columns); + } + [Obsolete] + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, Expression> columns) + { + return this.SetColumnsIF(isUpdateColumns, columns); + } + [Obsolete] + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, Expression> columns) + { + return this.SetColumnsIF(isUpdateColumns, columns); + } + [Obsolete] + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, Func updateColumMethod) + { + if (isUpdateColumns) + UpdateColumns(updateColumMethod); + return this; + } + [Obsolete] + public IUpdateable UpdateColumns(Func updateColumMethod) + { + List primaryKeys = GetPrimaryKeys(); + foreach (var item in this.UpdateBuilder.DbColumnInfoList) + { + var mappingInfo = primaryKeys.SingleOrDefault(i => item.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null && mappingInfo.Any()) + { + item.IsPrimarykey = true; + } + } + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => updateColumMethod(it.PropertyName) || it.IsPrimarykey || it.IsIdentity).ToList(); + return this; + } + [Obsolete] + public IUpdateable IgnoreColumns(Func ignoreColumMethod) + { + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => !ignoreColumMethod(it.PropertyName)).ToList(); + return this; + } + [Obsolete("Use IUpdateable IgnoreColumns(bool ignoreAllNullColumns, bool isOffIdentity = false);")] + public IUpdateable Where(bool isUpdateNull, bool IsOffIdentity = false) + { + UpdateBuilder.IsOffIdentity = IsOffIdentity; + if (this.UpdateBuilder.LambdaExpressions == null) + this.UpdateBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.Context.CurrentConnectionConfig); + this.UpdateBuilder.IsNoUpdateNull = isUpdateNull; + return this; + } + #endregion + + #region Helper + private void AppendSets() + { + if (SetColumnsIndex > 0) + { + var keys = UpdateBuilder.SetValues.Select(it => SqlBuilder.GetNoTranslationColumnName(it.Key.ToLower())).ToList(); + var addKeys = keys.Where(k => !this.UpdateBuilder.DbColumnInfoList.Any(it => it.PropertyName.ToLower() == k || it.DbColumnName.ToLower() == k)).ToList(); + var addItems = this.EntityInfo.Columns.Where(it =>!GetPrimaryKeys().Any(p=>p.ToLower()==it.PropertyName?.ToLower()|| p.ToLower() == it.DbColumnName?.ToLower()) && addKeys.Any(k => it.PropertyName?.ToLower() == k || it.DbColumnName?.ToLower() == k)).ToList(); + this.UpdateBuilder.DbColumnInfoList.AddRange(addItems.Select(it => new DbColumnInfo() { PropertyName = it.PropertyName, DbColumnName = it.DbColumnName })); + } + SetColumnsIndex++; + } + private string _ExecuteCommand() + { + PreToSql(); + AutoRemoveDataCache(); + Check.Exception(UpdateBuilder.WhereValues.IsNullOrEmpty() && GetPrimaryKeys().IsNullOrEmpty(), "You cannot have no primary key and no conditions"); + string sql = UpdateBuilder.ToSqlString(); + ValidateVersion(); + RestoreMapping(); + Before(sql); + return sql; + } + private void AutoRemoveDataCache() + { + var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (moreSetts != null && moreSetts.IsAutoRemoveDataCache && extService != null && extService.DataInfoCacheService != null) + { + this.RemoveDataCache(); + } + } + internal void Init() + { + this.UpdateBuilder.TableName = EntityInfo.EntityName; + if (IsMappingTable) + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == EntityInfo.EntityName); + if (mappingInfo != null) + { + this.UpdateBuilder.TableName = mappingInfo.DbTableName; + } + } + Check.Exception(UpdateObjs == null || UpdateObjs.Count() == 0, "UpdateObjs is null"); + int i = 0; + foreach (var item in UpdateObjs) + { + List updateItem = new List(); + var isDic = item is Dictionary; + if (isDic) + { + SetUpdateItemByDic(i, item, updateItem); + } + else + { + SetUpdateItemByEntity(i, item, updateItem); + } + ++i; + } + } + private void CheckTranscodeing() + { + if (this.EntityInfo.Columns.Any(it => it.IsTranscoding)) + { + Check.Exception(true, ErrorMessage.GetThrowMessage("UpdateColumns no support IsTranscoding", "SetColumns方式更新不支持IsTranscoding,你可以使用db.Updateable(实体)的方式更新")); + } + if (this.EntityInfo.Columns.Any(it => it.IsJson)) + { + Check.Exception(true, ErrorMessage.GetThrowMessage("UpdateColumns no support IsJson", "SetColumns方式更新不支持IsJson,你可以使用db.Updateable(实体)的方式更新")); + } + } + private void SetUpdateItemByDic(int i, T item, List updateItem) + { + foreach (var column in item as Dictionary) + { + var columnInfo = new DbColumnInfo() + { + Value = column.Value, + DbColumnName = column.Key, + PropertyName = column.Key, + PropertyType = column.Value == null ? DBNull.Value.GetType() : UtilMethods.GetUnderType(column.Value.GetType()), + TableId = i + }; + if (columnInfo.PropertyType.IsEnum()) + { + columnInfo.Value = Convert.ToInt64(columnInfo.Value); + } + updateItem.Add(columnInfo); + } + this.UpdateBuilder.DbColumnInfoList.AddRange(updateItem); + } + private void SetUpdateItemByEntity(int i, T item, List updateItem) + { + foreach (var column in EntityInfo.Columns) + { + if (column.IsIgnore) continue; + var columnInfo = new DbColumnInfo() + { + Value = column.PropertyInfo.GetValue(item, null), + DbColumnName = GetDbColumnName(column.PropertyName), + PropertyName = column.PropertyName, + PropertyType = UtilMethods.GetUnderType(column.PropertyInfo), + TableId = i + }; + if (columnInfo.PropertyType.IsEnum()) + { + columnInfo.Value = Convert.ToInt64(columnInfo.Value); + } + if (column.IsJson) + { + columnInfo.Value = this.Context.Utilities.SerializeObject(columnInfo.Value); + } + var tranColumn = EntityInfo.Columns.FirstOrDefault(it => it.IsTranscoding && it.DbColumnName.Equals(column.DbColumnName, StringComparison.CurrentCultureIgnoreCase)); + if (tranColumn != null && columnInfo.Value.HasValue()) + { + columnInfo.Value = UtilMethods.EncodeBase64(columnInfo.Value.ToString()); + } + updateItem.Add(columnInfo); + } + this.UpdateBuilder.DbColumnInfoList.AddRange(updateItem); + } + + private void PreToSql() + { + UpdateBuilder.PrimaryKeys = GetPrimaryKeys(); + if (this.IsWhereColumns) + { + foreach (var pkName in UpdateBuilder.PrimaryKeys) + { + var isContains = this.UpdateBuilder.DbColumnInfoList.Select(it => it.DbColumnName.ToLower()).Contains(pkName.ToLower()); + Check.Exception(isContains == false, "Use UpdateColumns().WhereColumn() ,UpdateColumns need {0}", pkName); + } + } + #region IgnoreColumns + if (this.Context.IgnoreColumns != null && this.Context.IgnoreColumns.Any()) + { + var currentIgnoreColumns = this.Context.IgnoreColumns.Where(it => it.EntityName == this.EntityInfo.EntityName).ToList(); + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => + { + return !currentIgnoreColumns.Any(i => it.PropertyName.Equals(i.PropertyName, StringComparison.CurrentCulture)); + }).ToList(); + } + #endregion + if (this.IsSingle) + { + foreach (var item in this.UpdateBuilder.DbColumnInfoList) + { + if (this.UpdateBuilder.Parameters == null) this.UpdateBuilder.Parameters = new List(); + if (this.UpdateBuilder.SetValues.Any(it => this.SqlBuilder.GetNoTranslationColumnName(it.Key) == item.PropertyName)) + { + continue; + } + this.UpdateBuilder.Parameters.Add(new SugarParameter(this.SqlBuilder.SqlParameterKeyWord + item.DbColumnName, item.Value, item.PropertyType)); + } + } + + #region Identities + List identities = GetIdentityKeys(); + if (identities != null && identities.Any()) + { + this.UpdateBuilder.DbColumnInfoList.ForEach(it => + { + var mappingInfo = identities.SingleOrDefault(i => it.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null && mappingInfo.Any()) + { + it.IsIdentity = true; + } + }); + } + #endregion + List primaryKey = GetPrimaryKeys(); + if (primaryKey != null && primaryKey.Count > 0) + { + this.UpdateBuilder.DbColumnInfoList.ForEach(it => + { + var mappingInfo = primaryKey.SingleOrDefault(i => it.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null && mappingInfo.Any()) + { + it.IsPrimarykey = true; + } + }); + } + if (this.UpdateBuilder.Parameters.HasValue() && this.UpdateBuilder.SetValues.IsValuable()) + { + this.UpdateBuilder.Parameters.RemoveAll(it => this.UpdateBuilder.SetValues.Any(v => (SqlBuilder.SqlParameterKeyWord + SqlBuilder.GetNoTranslationColumnName(v.Key)) == it.ParameterName)); + } + } + private string GetDbColumnName(string propertyName) + { + if (!IsMappingColumns) + { + return propertyName; + } + if (this.Context.MappingColumns.Any(it => it.EntityName.Equals(EntityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase))) + { + this.MappingColumnList = this.Context.MappingColumns.Where(it => it.EntityName.Equals(EntityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase)).ToList(); + } + if (MappingColumnList == null || !MappingColumnList.Any()) + { + return propertyName; + } + else + { + var mappInfo = this.MappingColumnList.FirstOrDefault(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + return mappInfo == null ? propertyName : mappInfo.DbColumnName; + } + } + private List GetPrimaryKeys() + { + if (this.WhereColumnList.HasValue()) + { + return this.WhereColumnList; + } + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + protected virtual List GetIdentityKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetIsIdentities(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); + } + } + private void RestoreMapping() + { + if (IsAs) + { + this.Context.MappingTables = OldMappingTableList; + } + } + + + private void ValidateVersion() + { + var versionColumn = this.EntityInfo.Columns.FirstOrDefault(it => it.IsEnableUpdateVersionValidation); + var pks = this.UpdateBuilder.DbColumnInfoList.Where(it => it.IsPrimarykey).ToList(); + if (versionColumn != null && this.IsVersionValidation) + { + Check.Exception(pks.IsNullOrEmpty(), "UpdateVersionValidation the primary key is required."); + List conModels = new List(); + foreach (var item in pks) + { + conModels.Add(new ConditionalModel() { FieldName = item.DbColumnName, ConditionalType = ConditionalType.Equal, FieldValue = item.Value.ObjToString() }); + } + var dbInfo = this.Context.Queryable().Where(conModels).First(); + if (dbInfo != null) + { + var currentVersion = this.EntityInfo.Type.GetProperty(versionColumn.PropertyName).GetValue(UpdateObjs.Last(), null); + var dbVersion = this.EntityInfo.Type.GetProperty(versionColumn.PropertyName).GetValue(dbInfo, null); + Check.Exception(currentVersion == null, "UpdateVersionValidation entity property {0} is not null", versionColumn.PropertyName); + Check.Exception(dbVersion == null, "UpdateVersionValidation database column {0} is not null", versionColumn.DbColumnName); + if (versionColumn.PropertyInfo.PropertyType.IsIn(UtilConstants.IntType, UtilConstants.LongType)) + { + if (Convert.ToInt64(dbVersion) != Convert.ToInt64(currentVersion)) + { + throw new VersionExceptions(string.Format("UpdateVersionValidation {0} Not the latest version ", versionColumn.PropertyName)); + } + } + else if (versionColumn.PropertyInfo.PropertyType.IsIn(UtilConstants.DateType)) + { + if (dbVersion.ObjToDate() != currentVersion.ObjToDate()) + { + throw new VersionExceptions(string.Format("UpdateVersionValidation {0} Not the latest version ", versionColumn.PropertyName)); + } + } + else if (versionColumn.PropertyInfo.PropertyType.IsIn(UtilConstants.ByteArrayType)) + { + if (UtilMethods.GetLong((byte[])dbVersion) != UtilMethods.GetLong((byte[])currentVersion)) + { + throw new VersionExceptions(string.Format("UpdateVersionValidation {0} Not the latest version ", versionColumn.PropertyName)); + } + } + else + { + Check.ThrowNotSupportedException(string.Format("UpdateVersionValidation Not Supported Type [ {0} ] , {1}", versionColumn.PropertyInfo.PropertyType, versionColumn.PropertyName)); + } + } + } + } + private void After(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var isDisableMasterSlaveSeparation = this.Ado.IsDisableMasterSlaveSeparation; + this.Ado.IsDisableMasterSlaveSeparation = true; + var parameters = UpdateBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.AfterData = GetDiffTable(sql, parameters); + diffModel.Time = this.Context.Ado.SqlExecutionTime; + if (this.Context.CurrentConnectionConfig.AopEvents.OnDiffLogEvent != null) + this.Context.CurrentConnectionConfig.AopEvents.OnDiffLogEvent(diffModel); + this.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + } + if (this.RemoveCacheFunc != null) + { + this.RemoveCacheFunc(); + } + } + + private void Before(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var isDisableMasterSlaveSeparation = this.Ado.IsDisableMasterSlaveSeparation; + this.Ado.IsDisableMasterSlaveSeparation = true; + var parameters = UpdateBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.BeforeData = GetDiffTable(sql, parameters); + diffModel.Sql = sql; + diffModel.Parameters = parameters.ToArray(); + this.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + } + } + private bool IsPrimaryKey(DbColumnInfo it) + { + var result= GetPrimaryKeys().Any(p => p.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase) || p.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + return result; + } + + private List GetDiffTable(string sql, List parameters) + { + List result = new List(); + var whereSql = Regex.Replace(sql, ".* WHERE ", "", RegexOptions.Singleline); + var dt = this.Context.Queryable().Where(whereSql).AddParameters(parameters).ToDataTable(); + if (dt.Rows != null && dt.Rows.Count > 0) + { + foreach (DataRow row in dt.Rows) + { + DiffLogTableInfo item = new DiffLogTableInfo(); + item.TableDescription = this.EntityInfo.TableDescription; + item.TableName = this.EntityInfo.DbTableName; + item.Columns = new List(); + foreach (DataColumn col in dt.Columns) + { + DiffLogColumnInfo addItem = new DiffLogColumnInfo(); + addItem.Value = row[col.ColumnName]; + addItem.ColumnName = col.ColumnName; + addItem.ColumnDescription = this.EntityInfo.Columns.First(it => it.DbColumnName.Equals(col.ColumnName, StringComparison.CurrentCultureIgnoreCase)).ColumnDescription; + item.Columns.Add(addItem); + } + result.Add(item); + } + } + return result; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/CacheScheme/CacheKeyBuider.cs b/类库/SqlSugar/5.0.0.9/CacheScheme/CacheKeyBuider.cs new file mode 100644 index 0000000..856a068 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/CacheScheme/CacheKeyBuider.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + internal class CacheKeyBuider + { + public static CacheKey GetKey(SqlSugarProvider context, QueryBuilder queryBuilder) + { + CacheKey result = new CacheKey(); + result.Database = context.Context.Ado.Connection.Database; + AddTables(context, queryBuilder, result); + AddIdentificationList(queryBuilder, result); + return result; + } + + private static void AddIdentificationList(QueryBuilder queryBuilder, CacheKey result) + { + result.IdentificationList = new List(); + result.IdentificationList.Add(queryBuilder.GetTableNameString); + result.IdentificationList.Add(queryBuilder.GetJoinValueString); + result.IdentificationList.Add(queryBuilder.GetOrderByString); + result.IdentificationList.Add(queryBuilder.GetGroupByString); + result.IdentificationList.Add(queryBuilder.GetWhereValueString); + result.IdentificationList.Add(queryBuilder.PartitionByValue); + result.IdentificationList.Add(queryBuilder.Take.ObjToString()); + result.IdentificationList.Add(queryBuilder.Skip.ObjToString()); + result.IdentificationList.Add(queryBuilder.IsCount.ObjToString()); + result.IdentificationList.Add(UtilMethods.GetMD5(queryBuilder.GetSelectValue.ObjToString())); + if (queryBuilder.Parameters.HasValue()) + { + foreach (var item in queryBuilder.Parameters) + { + result.IdentificationList.Add(item.ParameterName + "_" + item.Value); + } + } + } + + private static void AddTables(ISqlSugarClient context, QueryBuilder queryBuilder, CacheKey result) + { + result.Tables = new List(); + result.Tables.Add(context.EntityMaintenance.GetTableName(queryBuilder.EntityName)); + if (queryBuilder.EasyJoinInfos.HasValue()) + { + foreach (var item in queryBuilder.EasyJoinInfos) + { + result.Tables.Add(context.EntityMaintenance.GetTableName(item.Value)); + } + } + if (queryBuilder.JoinQueryInfos.HasValue()) + { + foreach (var item in queryBuilder.JoinQueryInfos) + { + result.Tables.Add(queryBuilder.Builder.GetNoTranslationColumnName(item.TableName)); + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/CacheScheme/CacheSchemeMain.cs b/类库/SqlSugar/5.0.0.9/CacheScheme/CacheSchemeMain.cs new file mode 100644 index 0000000..edec0a6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/CacheScheme/CacheSchemeMain.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + internal class CacheSchemeMain + { + public static T GetOrCreate(ICacheService cacheService, QueryBuilder queryBuilder, Func getData, int cacheDurationInSeconds, SqlSugarProvider context) + { + CacheKey key = CacheKeyBuider.GetKey(context, queryBuilder); + string keyString = key.ToString(); + var result = cacheService.GetOrCreate(keyString, getData, cacheDurationInSeconds); + return result; + } + + public static void RemoveCache(ICacheService cacheService, string tableName) + { + var keys = cacheService.GetAllKey(); + if (keys.HasValue()) + { + foreach (var item in keys) + { + if (item.ToLower().Contains(UtilConstants.Dot + tableName.ToLower() + UtilConstants.Dot)) + { + cacheService.Remove(item); + } + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/AsyncRef.cs b/类库/SqlSugar/5.0.0.9/Entities/AsyncRef.cs new file mode 100644 index 0000000..e50ab6d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/AsyncRef.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class RefAsync + { + public RefAsync() { } + public RefAsync(T value) { Value = value; } + public T Value { get; set; } + public override string ToString() + { + T value = Value; + return value == null ? "" : value.ToString(); + } + public static implicit operator T(RefAsync r) { return r.Value; } + public static implicit operator RefAsync(T value) { return new RefAsync(value); } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/CacheKey.cs b/类库/SqlSugar/5.0.0.9/Entities/CacheKey.cs new file mode 100644 index 0000000..40cd87a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/CacheKey.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class CacheKey + { + public string Database { get; set; } + public List Tables { get; set; } + public List IdentificationList { get; set; } + public new string ToString() + { + return "SqlSugarDataCache" + UtilConstants.Dot + string.Join(UtilConstants.Dot, this.Tables) +UtilConstants.Dot+ string.Join(UtilConstants.Dot, this.IdentificationList.Where(it=>it.HasValue())); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/ConditionalModel.cs b/类库/SqlSugar/5.0.0.9/Entities/ConditionalModel.cs new file mode 100644 index 0000000..3d58da6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/ConditionalModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public interface IConditionalModel { + + } + public class ConditionalCollections : IConditionalModel + { + public List> ConditionalList { get; set; } + } + + public class ConditionalModel: IConditionalModel + { + public ConditionalModel() + { + this.ConditionalType = ConditionalType.Equal; + } + public string FieldName { get; set; } + public string FieldValue { get; set; } + public ConditionalType ConditionalType { get; set; } + public Func FieldValueConvertFunc { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/ConnMoreSettings.cs b/类库/SqlSugar/5.0.0.9/Entities/ConnMoreSettings.cs new file mode 100644 index 0000000..92fba30 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/ConnMoreSettings.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class ConnMoreSettings + { + public bool IsAutoRemoveDataCache { get; set; } + public bool IsWithNoLockQuery { get; set; } + /// + /// Some MYSQL databases do not support NVarchar set true + /// + public bool MySqlDisableNarvchar { get; set; } + public int DefaultCacheDurationInSeconds { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/ConnectionConfig.cs b/类库/SqlSugar/5.0.0.9/Entities/ConnectionConfig.cs new file mode 100644 index 0000000..c34910c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/ConnectionConfig.cs @@ -0,0 +1,129 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class ConnectionConfig + { + /// + /// + /// + public dynamic ConfigId { get; set; } + /// + ///DbType.SqlServer Or Other + /// + public DbType DbType { get; set; } + /// + ///Database Connection string + /// + public string ConnectionString { get; set; } + /// + /// true does not need to close the connection + /// + public bool IsAutoCloseConnection { get; set; } + /// + /// Default SystemTable,If you do not have system table permissions, use attribute + /// + public InitKeyType InitKeyType = InitKeyType.SystemTable; + /// + ///If true, there is only one connection instance in the same thread within the same connection string + /// + public bool IsShardSameThread { get; set; } + /// + /// Configure External Services replace default services,For example, Redis storage + /// + [JsonIgnore] + public ConfigureExternalServices ConfigureExternalServices = new ConfigureExternalServices(); + /// + /// If SlaveConnectionStrings has value,ConnectionString is write operation, SlaveConnectionStrings is read operation. + /// All operations within a transaction is ConnectionString + /// + public List SlaveConnectionConfigs { get; set; } + /// + /// More Gobal Settings + /// + public ConnMoreSettings MoreSettings { get; set; } + /// + /// Used for debugging errors or BUG,Used for debugging, which has an impact on Performance + /// + public SugarDebugger Debugger { get; set; } + + [JsonIgnore] + public AopEvents AopEvents { get;set; } + } + public class AopEvents + { + public Action OnDiffLogEvent { get; set; } + public Action OnError { get; set; } + public Action OnLogExecuting { get; set; } + public Action OnLogExecuted { get; set; } + public Func> OnExecutingChangeSql { get; set; } + } + public class ConfigureExternalServices + { + + private ISerializeService _SerializeService; + private ICacheService _ReflectionInoCache; + private ICacheService _DataInfoCache; + private IRazorService _RazorService; + + public IRazorService RazorService + { + get + { + if (_RazorService == null) + return _RazorService; + else + return _RazorService; + } + set { _RazorService = value; } + } + + public ISerializeService SerializeService + { + get + { + if (_SerializeService == null) + return DefaultServices.Serialize; + else + return _SerializeService; + } + set{ _SerializeService = value;} + } + + public ICacheService ReflectionInoCacheService + { + get + { + if (_ReflectionInoCache == null) + return DefaultServices.ReflectionInoCache; + else + return _ReflectionInoCache; + } + set{_ReflectionInoCache = value;} + } + + public ICacheService DataInfoCacheService + { + get + { + if (_DataInfoCache == null) + return DefaultServices.DataInoCache; + else + return _DataInfoCache; + } + set { _DataInfoCache = value; } + } + + public List SqlFuncServices { get; set; } + public List> AppendDataReaderTypeMappings { get; set; } + + + public Action EntityService{ get; set; } + public Action EntityNameService { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/DbColumnInfo.cs b/类库/SqlSugar/5.0.0.9/Entities/DbColumnInfo.cs new file mode 100644 index 0000000..3fbd9d3 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/DbColumnInfo.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class DbColumnInfo + { + public string TableName { get; set; } + public int TableId { get; set; } + public string DbColumnName { get; set; } + public string PropertyName { get; set; } + public string DataType { get; set; } + public Type PropertyType { get; set; } + public int Length { get; set; } + public string ColumnDescription { get; set; } + public string DefaultValue { get; set; } + public bool IsNullable { get; set; } + public bool IsIdentity { get; set; } + public bool IsPrimarykey { get; set; } + public object Value { get; set; } + public int DecimalDigits { get; set; } + public int Scale { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/DbResult.cs b/类库/SqlSugar/5.0.0.9/Entities/DbResult.cs new file mode 100644 index 0000000..fd6aa90 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/DbResult.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DbResult + { + public bool IsSuccess { get; set; } + public Exception ErrorException { get; set; } + public string ErrorMessage { get; set; } + public T Data { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/DbTableInfo.cs b/类库/SqlSugar/5.0.0.9/Entities/DbTableInfo.cs new file mode 100644 index 0000000..cb8fead --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/DbTableInfo.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DbTableInfo + { + public string Name { get; set; } + public string Description { get; set; } + public DbObjectType DbObjectType { get; set; } + } + + public class RazorTableInfo + { + public string DbTableName { get; set; } + public string ClassName { get; set; } + public string Description { get; set; } + public DbObjectType DbObjectType { get; set; } + public List Columns { get; set; } + } + + public class RazorColumnInfo { + public string DbColumnName { get; set; } + public string DataType { get; set; } + public int Length { get; set; } + public string ColumnDescription { get; set; } + public string DefaultValue { get; set; } + public bool IsNullable { get; set; } + public bool IsIdentity { get; set; } + public bool IsPrimarykey { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/DefaultServices.cs b/类库/SqlSugar/5.0.0.9/Entities/DefaultServices.cs new file mode 100644 index 0000000..dedca8d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/DefaultServices.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DefaultServices + { + public static ICacheService ReflectionInoCache= new ReflectionInoCacheService(); + public static ICacheService DataInoCache = null; + public static ISerializeService Serialize= new SerializeService(); + } +} \ No newline at end of file diff --git a/类库/SqlSugar/5.0.0.9/Entities/DiffLogModel.cs b/类库/SqlSugar/5.0.0.9/Entities/DiffLogModel.cs new file mode 100644 index 0000000..d8ae772 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/DiffLogModel.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DiffLogModel + { + public List AfterData { get; set; } + public List BeforeData { get; set; } + public SugarParameter[] Parameters { get; set; } + public string Sql { get; set; } + public TimeSpan? Time { get; set; } + public object BusinessData { get; set; } + public DiffType DiffType { get; set; } + } + public class DiffLogTableInfo + { + public string TableName { get; set; } + public string TableDescription { get; set; } + public List Columns { get; set; } + } + public class DiffLogColumnInfo { + + public string ColumnName { get; set; } + public string ColumnDescription { get; set; } + public object Value { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/DiffType.cs b/类库/SqlSugar/5.0.0.9/Entities/DiffType.cs new file mode 100644 index 0000000..08dc77a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/DiffType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum DiffType + { + insert=0, + update=1, + delete=2 + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/EntityColumnInfo.cs b/类库/SqlSugar/5.0.0.9/Entities/EntityColumnInfo.cs new file mode 100644 index 0000000..a69a248 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/EntityColumnInfo.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class EntityColumnInfo + { + public PropertyInfo PropertyInfo { get; set; } + public string PropertyName { get; set; } + public string DbColumnName { get; set; } + public string OldDbColumnName { get; set; } + public int Length { get; set; } + public string ColumnDescription { get; set; } + public string DefaultValue { get; set; } + public bool IsNullable { get; set; } + public bool IsIdentity { get; set; } + public bool IsPrimarykey { get; set; } + public bool IsEnableUpdateVersionValidation { get; set; } + public string EntityName { get; set; } + public string DbTableName { get; set; } + public bool IsIgnore { get; set; } + public string DataType { get; set; } + public int DecimalDigits { get; set; } + public string OracleSequenceName { get; set; } + public bool IsOnlyIgnoreInsert { get; set; } + public bool IsOnlyIgnoreUpdate { get; set; } + public bool IsTranscoding { get; set; } + public string SerializeDateTimeFormat { get; set; } + public bool IsJson { get; set; } + public bool NoSerialize { get; set; } + public string[] IndexGroupNameList { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/EntityInfo.cs b/类库/SqlSugar/5.0.0.9/Entities/EntityInfo.cs new file mode 100644 index 0000000..f3241b0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/EntityInfo.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class EntityInfo + { + private string _DbTableName; + public string EntityName { get; set; } + public string DbTableName { get { return _DbTableName == null ? EntityName : _DbTableName; } set { _DbTableName = value; } } + public string TableDescription { get; set; } + public Type Type { get; set; } + public List Columns { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/JoinQueryInfo.cs b/类库/SqlSugar/5.0.0.9/Entities/JoinQueryInfo.cs new file mode 100644 index 0000000..aa07be1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/JoinQueryInfo.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class JoinQueryInfo + { + public JoinType JoinType { get; set; } + public string TableName { get; set; } + public string ShortName { get; set; } + public int JoinIndex { get; set; } + public string JoinWhere { get; set; } + } + public class JoinQueryInfos + { + private JoinQueryInfos() { } + public JoinQueryInfos(JoinType joinType, bool whereExpress) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3, JoinType joinType4, bool whereExpress4) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3, JoinType joinType4, bool whereExpress4, JoinType joinType5, bool whereExpress5) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3, JoinType joinType4, bool whereExpress4, JoinType joinType5, bool whereExpress5, JoinType joinType6, bool whereExpress6) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3, JoinType joinType4, bool whereExpress4, JoinType joinType5, bool whereExpress5, JoinType joinType6, bool whereExpress6, JoinType joinType7, bool whereExpress7) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3, JoinType joinType4, bool whereExpress4, JoinType joinType5, bool whereExpress5, JoinType joinType6, bool whereExpress6, JoinType joinType7, bool whereExpress7, JoinType joinType8, bool whereExpress8) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3, JoinType joinType4, bool whereExpress4, JoinType joinType5, bool whereExpress5, JoinType joinType6, bool whereExpress6, JoinType joinType7, bool whereExpress7, JoinType joinType8, bool whereExpress8, JoinType joinType9, bool whereExpress9) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3, JoinType joinType4, bool whereExpress4, JoinType joinType5, bool whereExpress5, JoinType joinType6, bool whereExpress6, JoinType joinType7, bool whereExpress7, JoinType joinType8, bool whereExpress8, JoinType joinType9, bool whereExpress9, JoinType joinType10, bool whereExpress10) + { + + } + public JoinQueryInfos(JoinType joinType, bool whereExpress, JoinType joinType2, bool whereExpress2, JoinType joinType3, bool whereExpress3, JoinType joinType4, bool whereExpress4, JoinType joinType5, bool whereExpress5, JoinType joinType6, bool whereExpress6, JoinType joinType7, bool whereExpress7, JoinType joinType8, bool whereExpress8, JoinType joinType9, bool whereExpress9, JoinType joinType10, bool whereExpress10, JoinType joinType11, bool whereExpress11) + { + + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/MapperCache.cs b/类库/SqlSugar/5.0.0.9/Entities/MapperCache.cs new file mode 100644 index 0000000..b6e2d4c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/MapperCache.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MapperCache + { + private Dictionary caches = new Dictionary(); + private List _list { get; set; } + private ISqlSugarClient _context { get; set; } + public int GetIndex { get; set; } + private MapperCache() + { + } + public MapperCache(List list, ISqlSugarClient context) + { + _list = list; + _context = context; + } + public Result Get(Func, Result> action) + { + GetIndex++; + string key = "Get" +typeof(Result)+action.GetHashCode()+action.Method.Name; + if (caches.ContainsKey(key)) + { + return (Result)caches[key]; + } + else + { + var result = action(_list); + caches.Add(key, result); + return result; + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + private List GetListByPrimaryKeys(Func action, string key) where Result : class, new() + { + if (caches.ContainsKey(key)) + { + return (List)caches[key]; + } + else + { + var ids = _list.Select(action).ToList().Distinct().ToList(); + var result = _context.Queryable().In(ids).ToList(); + caches.Add(key, result); + return result; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/Mapping/IgnoreComumn.cs b/类库/SqlSugar/5.0.0.9/Entities/Mapping/IgnoreComumn.cs new file mode 100644 index 0000000..58cb337 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/Mapping/IgnoreComumn.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class IgnoreColumn + { + public string EntityName { get; set; } + public string PropertyName { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/Mapping/MappingColumn.cs b/类库/SqlSugar/5.0.0.9/Entities/Mapping/MappingColumn.cs new file mode 100644 index 0000000..85b3ff8 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/Mapping/MappingColumn.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MappingColumn + { + public string PropertyName { get; set; } + public string DbColumnName { get; set; } + public string EntityName { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/Mapping/MappingTable.cs b/类库/SqlSugar/5.0.0.9/Entities/Mapping/MappingTable.cs new file mode 100644 index 0000000..99b3fd0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/Mapping/MappingTable.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MappingTable + { + public string EntityName { get; set; } + public string DbTableName { get; set; } + public string DbShortTaleName { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/Mapping/SugarMappingAttribute.cs b/类库/SqlSugar/5.0.0.9/Entities/Mapping/SugarMappingAttribute.cs new file mode 100644 index 0000000..c3bc580 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/Mapping/SugarMappingAttribute.cs @@ -0,0 +1,176 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System; + +namespace SqlSugar +{ + [AttributeUsage(AttributeTargets.Class, Inherited = true)] + public class SugarTable : Attribute { + private SugarTable() { } + public string TableName { get; set; } + public string TableDescription { get; set; } + public SugarTable(string tableName) { + this.TableName = tableName; + } + public SugarTable(string tableName,string tableDescription) + { + this.TableName = tableName; + this.TableDescription = tableDescription; + } + } + [AttributeUsage(AttributeTargets.Property , Inherited = true)] + public class SugarColumn : Attribute + { + private string _ColumnName; + public string ColumnName + { + get { return _ColumnName; } + set { _ColumnName = value; } + } + + private bool _IsIgnore; + public bool IsIgnore + { + get { return _IsIgnore; } + set { _IsIgnore = value; } + } + + private bool _IsPrimaryKey; + public bool IsPrimaryKey + { + get { return _IsPrimaryKey; } + set { _IsPrimaryKey = value; } + } + + private bool _IsIdentity; + public bool IsIdentity + { + get { return _IsIdentity; } + set { _IsIdentity = value; } + } + + private string _MappingKeys; + public string MappingKeys + { + get { return _MappingKeys; } + set { _MappingKeys = value; } + } + + private string _ColumnDescription; + public string ColumnDescription + { + get { return _ColumnDescription; } + set { _ColumnDescription = value; } + } + + private int _Length; + public int Length + { + get { return _Length; } + set { _Length = value; } + } + + private bool _IsNullable; + public bool IsNullable + { + get { return _IsNullable; } + set { _IsNullable = value; } + } + + private string _OldColumnName; + public string OldColumnName + { + get { return _OldColumnName; } + set { _OldColumnName = value; } + } + + private string _ColumnDataType; + public string ColumnDataType + { + get { return _ColumnDataType; } + set { _ColumnDataType = value; } + } + + private int _DecimalDigits; + public int DecimalDigits { + get { return _DecimalDigits; } + set { _DecimalDigits = value; } + } + + private string _OracleSequenceName; + public string OracleSequenceName { + get { return _OracleSequenceName; } + set { _OracleSequenceName = value; } + } + + private bool _IsOnlyIgnoreInsert; + public bool IsOnlyIgnoreInsert + { + get { return _IsOnlyIgnoreInsert; } + set { _IsOnlyIgnoreInsert = value; } + } + + private bool _IsOnlyIgnoreUpdate; + public bool IsOnlyIgnoreUpdate + { + get { return _IsOnlyIgnoreUpdate; } + set { _IsOnlyIgnoreUpdate = value; } + } + + + private bool _IsEnableUpdateVersionValidation; + public bool IsEnableUpdateVersionValidation { + get { return _IsEnableUpdateVersionValidation; } + set { _IsEnableUpdateVersionValidation = value; } + } + + + + private bool _IsTranscoding; + public bool IsTranscoding + { + get { return _IsTranscoding; } + set { _IsTranscoding = value; } + } + + private bool _NoSerialize; + public bool NoSerialize + { + get { return _NoSerialize; } + set { _NoSerialize = value; } + } + + private string _SerializeDateTimeFormat; + public string SerializeDateTimeFormat + { + get { return _SerializeDateTimeFormat; } + set { _SerializeDateTimeFormat = value; } + } + + private bool _IsJson; + public bool IsJson + { + get { return _IsJson; } + set { _IsJson = value; } + } + + + private string _DefaultValue; + public string DefaultValue + { + get { return _DefaultValue; } + set { _DefaultValue = value; } + } + + private string[] _IndexGroupNameList; + public string[] IndexGroupNameList + { + get { return _IndexGroupNameList; } + set { _IndexGroupNameList = value; } + } + + } + +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/ModelContext.cs b/类库/SqlSugar/5.0.0.9/Entities/ModelContext.cs new file mode 100644 index 0000000..6b7e73e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/ModelContext.cs @@ -0,0 +1,23 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class ModelContext + { + [SugarColumn(IsIgnore = true)] + [JsonIgnore] + public SqlSugarProvider Context { get; set; } + public ISugarQueryable CreateMapping() where T : class, new() + { + Check.ArgumentNullException(Context, "Please use Sqlugar.ModelContext"); + using (Context) + { + return Context.Queryable(); + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/PageModel.cs b/类库/SqlSugar/5.0.0.9/Entities/PageModel.cs new file mode 100644 index 0000000..4d510dc --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/PageModel.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class PageModel + { + public int PageIndex { get; set; } + public int PageSize { get; set; } + /// + /// output + /// + public int PageCount { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/QueueItem.cs b/类库/SqlSugar/5.0.0.9/Entities/QueueItem.cs new file mode 100644 index 0000000..295d579 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/QueueItem.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class QueueItem + { + public string Sql { get; set; } + public SugarParameter[] Parameters { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/SchemaInfo.cs b/类库/SqlSugar/5.0.0.9/Entities/SchemaInfo.cs new file mode 100644 index 0000000..53f2b29 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/SchemaInfo.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SchemaInfo + { + public string TableName { get; set; } + public string SchemaName { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/SlaveConnectionConfig.cs b/类库/SqlSugar/5.0.0.9/Entities/SlaveConnectionConfig.cs new file mode 100644 index 0000000..b0d3e64 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/SlaveConnectionConfig.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SlaveConnectionConfig + { + /// + ///Default value is 1 + ///If value is 0 means permanent non execution + /// + public int HitRate = 1; + public string ConnectionString { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/SqlFilter.cs b/类库/SqlSugar/5.0.0.9/Entities/SqlFilter.cs new file mode 100644 index 0000000..d650ac1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/SqlFilter.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlFilterItem + { + /// + /// Equal to NULL representing global + /// + public string FilterName { get; set; } + public Func FilterValue { get; set; } + /// + /// Is it a multiple table query? + /// + public bool IsJoinQuery { get; set; } + } + + public class SqlFilterResult + { + public string Sql { get; set; } + public object Parameters { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/SqlWith.cs b/类库/SqlSugar/5.0.0.9/Entities/SqlWith.cs new file mode 100644 index 0000000..0d7876e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/SqlWith.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SqlWith + { + public const string NoLock = "WITH(NOLOCK) "; + public const string HoldLock = "WITH(HOLDLOCK)"; + public const string PagLock = "WITH(PAGLOCK)"; + public const string ReadCommitted = "WITH(READCOMMITTED)"; + public const string TabLockX = "WITH(TABLOCKX)"; + public const string UpdLock = "WITH(UPDLOCK)"; + public const string RowLock = "WITH(ROWLOCK)"; + public const string Null = "Non"; + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/SugarDebugger.cs b/类库/SqlSugar/5.0.0.9/Entities/SugarDebugger.cs new file mode 100644 index 0000000..7d876a5 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/SugarDebugger.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + /// + /// Used for debugging errors or BUG,Used for debugging, which has an impact on Performance + /// + public class SugarDebugger + { + /// + /// If you use the same Db object across threads, you will be prompted + /// + public bool EnableThreadSecurityValidation { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/SugarList.cs b/类库/SqlSugar/5.0.0.9/Entities/SugarList.cs new file mode 100644 index 0000000..43e5ffb --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/SugarList.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MappingTableList : List + { + public void Add(string entityName, string dbTableName) + { + this.RemoveAll(it => it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase)); + this.Add(new MappingTable() { EntityName = entityName, DbTableName = dbTableName }); + } + public void Add(string entityName, string dbTableName, string dbTableShortName) + { + this.RemoveAll(it => it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase)); + this.Add(new MappingTable() { EntityName = entityName, DbTableName = dbTableName, DbShortTaleName = dbTableShortName }); + } + public new void Clear() + { + this.RemoveAll(it => true); + } + } + + public class IgnoreColumnList : List + { + public void Add(string propertyName, string EntityName) + { + this.RemoveAll(it => it.EntityName == EntityName && it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + this.Add(new IgnoreColumn() { PropertyName = propertyName, EntityName = EntityName }); + } + + public new void Clear() + { + this.RemoveAll(it => true); + } + } + + public class MappingColumnList : List + { + public void Add(string propertyName, string dbColumnName, string entityName) + { + this.RemoveAll(it => it.EntityName == entityName && it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + this.Add(new MappingColumn() { PropertyName = propertyName, DbColumnName = dbColumnName, EntityName = entityName }); + } + public new void Clear() + { + this.RemoveAll(it => true); + } + } + + + public class QueueList : List + { + public void Add(string sql, SugarParameter[] parameters) + { + this.Add(new QueueItem() { Sql = sql, Parameters = parameters }); + } + public void Add(string sql, List parameters) + { + if (parameters == null) + parameters = new List(); + this.Add(new QueueItem() { Sql = sql, Parameters = parameters.ToArray() }); + } + public new void Clear() + { + this.RemoveAll(it => true); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Entities/SugarTerant.cs b/类库/SqlSugar/5.0.0.9/Entities/SugarTerant.cs new file mode 100644 index 0000000..bfa6351 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Entities/SugarTerant.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SugarTenant + { + public SqlSugarProvider Context { get; set; } + public ConnectionConfig ConnectionConfig { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/ApplyType.cs b/类库/SqlSugar/5.0.0.9/Enum/ApplyType.cs new file mode 100644 index 0000000..36a8cb4 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/ApplyType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum ApplyType + { + Cross = 1, + Outer = 2 + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/ConditionalType.cs b/类库/SqlSugar/5.0.0.9/Enum/ConditionalType.cs new file mode 100644 index 0000000..e998c5e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/ConditionalType.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum ConditionalType + { + Equal=0, + Like=1, + GreaterThan =2, + GreaterThanOrEqual = 3, + LessThan=4, + LessThanOrEqual = 5, + In=6, + NotIn=7, + LikeLeft=8, + LikeRight=9, + NoEqual=10, + IsNullOrEmpty=11, + IsNot=12, + NoLike = 13, + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/DbObjectType.cs b/类库/SqlSugar/5.0.0.9/Enum/DbObjectType.cs new file mode 100644 index 0000000..affb501 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/DbObjectType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum DbObjectType + { + Table = 0, + View = 1, + All = 2 + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/DbType.cs b/类库/SqlSugar/5.0.0.9/Enum/DbType.cs new file mode 100644 index 0000000..40e040c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/DbType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum DbType + { + MySql , + SqlServer, + Sqlite, + Oracle, + PostgreSQL + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/InitKeyType.cs b/类库/SqlSugar/5.0.0.9/Enum/InitKeyType.cs new file mode 100644 index 0000000..55d487e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/InitKeyType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum InitKeyType + { + /// + /// Init primary key and identity key from the system table + /// + SystemTable = 0, + /// + /// Init primary key and identity key from the attribute + /// + Attribute = 1 + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/JoinType.cs b/类库/SqlSugar/5.0.0.9/Enum/JoinType.cs new file mode 100644 index 0000000..0ee5af8 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/JoinType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum JoinType + { + Inner = 0, + Left = 1, + Right = 2 + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/OrderByType.cs b/类库/SqlSugar/5.0.0.9/Enum/OrderByType.cs new file mode 100644 index 0000000..4069370 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/OrderByType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum OrderByType + { + Asc = 0, + Desc = 1 + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/ProperyType.cs b/类库/SqlSugar/5.0.0.9/Enum/ProperyType.cs new file mode 100644 index 0000000..9ec6734 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/ProperyType.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum CSharpDataType + { + @int, + @bool, + @string, + @DateTime, + @decimal, + @double, + @Guid, + @byte, + @enum, + @short, + @long, + @object, + @other, + @byteArray, + @float, + @time, + @DateTimeOffset, + @Single, + @TimeSpan + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/SugarDateTimeFormat.cs b/类库/SqlSugar/5.0.0.9/Enum/SugarDateTimeFormat.cs new file mode 100644 index 0000000..4f98c05 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/SugarDateTimeFormat.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public partial class SugarDateTimeFormat + { + public const string Default = "yyyy-MM-dd HH:mm:ss"; + public const string Date = "yyyy-MM-dd HH"; + } +} diff --git a/类库/SqlSugar/5.0.0.9/Enum/WhereType.cs b/类库/SqlSugar/5.0.0.9/Enum/WhereType.cs new file mode 100644 index 0000000..c49492a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Enum/WhereType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum WhereType + { + And=0, + Or=1 + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/CaseWhen/CaseWhen.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/CaseWhen/CaseWhen.cs new file mode 100644 index 0000000..3e74788 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/CaseWhen/CaseWhen.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class CaseWhen + { + public CaseThen ElseIF(bool condition) + { + return null; + } + public T End(T defaultValue) + { + return default(T); + } + } + public class CaseThen + { + + public CaseWhen Return(T result) + { + return null; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/CaseWhen/CaseWhenResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/CaseWhen/CaseWhenResolve.cs new file mode 100644 index 0000000..94b92c3 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/CaseWhen/CaseWhenResolve.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + + public class CaseWhenResolve + { + List allMethods = new List(); + private ExpressionContext context = null; + public CaseWhenResolve(MethodCallExpression expression, ExpressionContext context, Expression oppsiteExpression) + { + this.context = context; + var currentExpression = expression; + allMethods.Add(currentExpression); + if (context.IsSingle && oppsiteExpression != null&& oppsiteExpression is MemberExpression) + { + var childExpression = (oppsiteExpression as MemberExpression).Expression; + this.context.SingleTableNameSubqueryShortName = (childExpression as ParameterExpression).Name; + } + else if (context.IsSingle) + { + this.context.SingleTableNameSubqueryShortName = (context.Expression as LambdaExpression).Parameters.First().Name; + } + while (currentExpression != null) + { + var addItem = currentExpression.Object as MethodCallExpression; + if (addItem != null) + allMethods.Add(addItem); + currentExpression = addItem; + } + } + + public string GetSql() + { + allMethods.Reverse(); + List> sqls = new List>(); + foreach (var methodExp in allMethods) + { + var isFirst = allMethods.First() == methodExp; + var isLast= allMethods.Last() == methodExp; + var sql= SubTools.GetMethodValue(this.context, methodExp.Arguments[0],this.context.IsSingle?ResolveExpressType.WhereSingle:ResolveExpressType.WhereMultiple); + sqls.Add(new KeyValuePair(methodExp.Method.Name, sql)); + } + var result= this.context.DbMehtods.CaseWhen(sqls); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/BinaryExpressionInfo.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/BinaryExpressionInfo.cs new file mode 100644 index 0000000..a35b85f --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/BinaryExpressionInfo.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class BinaryExpressionInfo + { + public bool IsLeft { get; set; } + public Type ExpressionType { get;set;} + public object Value { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/CommonTempDataType.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/CommonTempDataType.cs new file mode 100644 index 0000000..989deec --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/CommonTempDataType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public enum CommonTempDataType + { + Default = 0, + Result = 1, + Append=2, + Simple = 3 + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/DateType.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/DateType.cs new file mode 100644 index 0000000..6de1122 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/DateType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public enum DateType + { + Year = 1, + Month = 2, + Day =3, + Hour = 4, + Second=5, + Minute=6, + Millisecond=7 + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ErrorMessage.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ErrorMessage.cs new file mode 100644 index 0000000..ff90336 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ErrorMessage.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + internal static partial class ErrorMessage + { + internal static string OperatorError + { + get + { + return ErrorMessage.GetThrowMessage("Lambda parsing error: {0} does not support the operator to find!","拉姆达解析出错:不支持{0}此种运算符查找!"); + } + } + internal static string ExpFileldError + { + get + { + return ErrorMessage.GetThrowMessage("Expression format error, correct format: it=>it.fieldName","表达式格式错误,正确格式: it=>it.fieldName"); + } + } + + internal static string MethodError + { + get + { + return ErrorMessage.GetThrowMessage("Expression parsing does not support the current function {0}. There are many functions available in the SqlFunc class, for example, it=>SqlFunc.HasValue(it.Id)", "拉姆达解析不支持当前函数{0},SqlFunc这个类里面有大量函数可用,也许有你想要的,例如: it=>SqlFunc.HasValue(it.Id)"); + } + } + + public static string ConnnectionOpen + { + get + { + return ErrorMessage.GetThrowMessage("Connection open error . {0}", " 连接数据库过程中发生错误,检查服务器是否正常连接字符串是否正确,实在找不到原因请先Google错误信息:{0}."); + } + } + public static string ExpressionCheck + { + get + { + return ErrorMessage.GetThrowMessage("Join {0} needs to be the same as {1} {2}", "多表查询存在别名不一致,请把{1}中的{2}改成{0}就可以了,特殊需求可以使用.Select((x,y)=>new{{ id=x.id,name=y.name}}).MergeTable().Orderby(xxx=>xxx.Id)功能将Select中的多表结果集变成单表,这样就可以不限制别名一样"); + } + } + + public static string WhereIFCheck + { + get + { + return ErrorMessage.GetThrowMessage("Subquery.WhereIF.IsWhere {0} not supported", "Subquery.WhereIF 第一个参数不支持表达式中的变量,只支持外部变量"); + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpResolveAccessory.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpResolveAccessory.cs new file mode 100644 index 0000000..d7fe5a1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpResolveAccessory.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class ExpResolveAccessory + { + protected List _Parameters; + protected ExpressionResult _Result; + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionConst.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionConst.cs new file mode 100644 index 0000000..bbc5f94 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionConst.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + internal class ExpressionConst + { + public const string Const = "Const"; + public const string FormatSymbol = "{0}"; + public const string RightParenthesis = ")"; + public const string LeftParenthesis = "("; + public const string MethodConst = "MethodConst"; + public const string SqlFuncFullName = "SqlSugar.SqlFunc"; + public const string BinaryFormatString = " ( {0} {1} {2} ) "; + public const string ExpressionReplace = "46450BDC-77B7-4025-B2A6-3F048CA85AD0"; + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionParameter.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionParameter.cs new file mode 100644 index 0000000..39638e4 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionParameter.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class ExpressionParameter + { + public ExpressionContext Context { get; set; } + public ExpressionParameter BaseParameter { get; set; } + public Expression BaseExpression { get; set; } + public Expression ChildExpression { get; set; } + public Expression LeftExpression { get; set; } + public Expression RightExpression { get; set; } + public Expression CurrentExpression { get; set; } + public string OperatorValue { get; set; } + public bool? IsLeft { get; set; } + public int Index { get; set; } + public bool ValueIsNull { get; set; } + public object CommonTempData { get; set; } + public ExpressionResultAppendType AppendType { get; set; } + public void IsAppendResult() + { + this.AppendType = ExpressionResultAppendType.AppendResult; + } + public void IsAppendTempDate() + { + this.AppendType = ExpressionResultAppendType.AppendTempDate; + } + public Expression OppsiteExpression + { + get + { + return this.IsLeft == true ? this.BaseParameter.RightExpression : this.BaseParameter.LeftExpression; + } + } + public bool IsSetTempData + { + get + { + return BaseParameter.CommonTempData.HasValue() && BaseParameter.CommonTempData.Equals(CommonTempDataType.Result); + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionResult.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionResult.cs new file mode 100644 index 0000000..316e715 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionResult.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class ExpressionResult + { + public bool IsLockCurrentParameter { get; set; } + public bool IsUpper { get; set; } + private ExpressionParameter _CurrentParameter; + public ExpressionParameter CurrentParameter + { + get + { + return this._CurrentParameter; + } + set + { + Check.Exception(value != null && IsLockCurrentParameter, "CurrentParameter is locked."); + this._CurrentParameter = value; + this.IsLockCurrentParameter = false; + } + } + #region constructor + private ExpressionResult() + { + } + public ExpressionResult(ResolveExpressType resolveExpressType) + { + this._ResolveExpressType = resolveExpressType; + } + #endregion + + #region Fields + private ResolveExpressType _ResolveExpressType; + private StringBuilder _Result; + #endregion + + #region properties + private StringBuilder Result + { + get + { + if (_Result == null) _Result = new StringBuilder(); + return _Result; + } + + set + { + _Result = value; + } + } + public bool LastCharIsSpace{ + get { + if (_Result == null|| _Result.Length==0) return true; + return _Result.ToString().Last() == UtilConstants.SpaceChar; + } + } + #endregion + public string GetString() + { + if (_Result == null) return null; + if (IsUpper) + return _Result.ToString().ToUpper().Replace(UtilConstants.ReplaceCommaKey,",").TrimEnd(','); + else + return _Result.ToString().Replace(UtilConstants.ReplaceCommaKey, ",").TrimEnd(','); + } + #region functions + public string[] GetResultArray() + { + if (this._Result == null) return null; + var reslut = new List(); + + if (IsUpper) + reslut= this.Result.ToString().ToUpper().TrimEnd(',').Split(',').ToList(); + else + reslut= this.Result.ToString().TrimEnd(',').Split(',').ToList(); + + if (this.Result.ToString().Contains(UtilConstants.ReplaceCommaKey)) + { + for (int i = 0; i < reslut.Count; i++) + { + reslut[i] = reslut[i].Replace(UtilConstants.ReplaceCommaKey, ","); + } + } + return reslut.ToArray(); + } + + public string GetResultString() + { + if (this._Result == null) return null; + if (this._ResolveExpressType.IsIn(ResolveExpressType.SelectMultiple, ResolveExpressType.SelectSingle)) + { + return this.Result.ToString().Replace(UtilConstants.ReplaceCommaKey, ",").TrimEnd(','); + } + if (IsUpper) + return this.Result.ToString().Replace(UtilConstants.ReplaceCommaKey, ",").ToUpper(); + else + return this.Result.ToString().Replace(UtilConstants.ReplaceCommaKey, ","); + } + + public void TrimEnd() + { + if (this._Result == null) return; + this.Result = this.Result.Remove(this.Result.Length - 1, 1); + } + + public bool Contains(string value) + { + if (this.Result.Equals(value)) return true; + return (this.Result.ToString().Contains(value)); + } + + internal void Insert(int index, string value) + { + if (this.Result == null) this.Result.Append(value); + this.Result.Insert(index, value); + } + + public void Append(object parameter) + { + if (this.CurrentParameter.HasValue() && this.CurrentParameter.AppendType.IsIn(ExpressionResultAppendType.AppendTempDate)) + { + this.CurrentParameter.CommonTempData = parameter; + return; + } + switch (this._ResolveExpressType) + { + case ResolveExpressType.ArraySingle: + case ResolveExpressType.ArrayMultiple: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + parameter = parameter + ","; + break; + case ResolveExpressType.WhereSingle: + break; + case ResolveExpressType.WhereMultiple: + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + default: + break; + } + this.Result.Append(parameter); + } + + public void AppendFormat(string parameter, params object[] orgs) + { + if (this.CurrentParameter.HasValue() && this.CurrentParameter.AppendType.IsIn(ExpressionResultAppendType.AppendTempDate)) + { + this.CurrentParameter.CommonTempData = new KeyValuePair(parameter, orgs); + return; + } + switch (this._ResolveExpressType) + { + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + parameter = parameter + ","; + break; + case ResolveExpressType.WhereSingle: + break; + case ResolveExpressType.WhereMultiple: + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + default: + break; + } + this.Result.AppendFormat(parameter, orgs); + } + + public void Replace(string parameter, string newValue) + { + this.Result.Replace(parameter, newValue); + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionResultAcceptType.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionResultAcceptType.cs new file mode 100644 index 0000000..5fe72fd --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionResultAcceptType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public enum ExpressionResultAppendType + { + AppendResult=0, + AppendTempDate=1 + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionTool.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionTool.cs new file mode 100644 index 0000000..50fbe41 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ExpressionTool.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public class ExpressionTool + { + public static string GetOperator(ExpressionType expressiontype) + { + switch (expressiontype) + { + case ExpressionType.And: + case ExpressionType.AndAlso: + return "AND"; + case ExpressionType.Equal: + return "="; + case ExpressionType.GreaterThan: + return ">"; + case ExpressionType.GreaterThanOrEqual: + return ">="; + case ExpressionType.LessThan: + return "<"; + case ExpressionType.LessThanOrEqual: + return "<="; + case ExpressionType.NotEqual: + return "<>"; + case ExpressionType.Or: + case ExpressionType.OrElse: + return "OR"; + case ExpressionType.Add: + case ExpressionType.AddChecked: + return "+"; + case ExpressionType.Subtract: + case ExpressionType.SubtractChecked: + return "-"; + case ExpressionType.Divide: + return "/"; + case ExpressionType.Multiply: + case ExpressionType.MultiplyChecked: + return "*"; + case ExpressionType.Modulo: + return "%"; + case ExpressionType.Coalesce: + throw new Exception("Expression no support ?? ,Use SqlFunc.IsNull"); + default: + Check.ThrowNotSupportedException(string.Format(ErrorMessage.OperatorError, expressiontype.ToString())); + return null; + } + } + + public static object GetValue(object value) + { + if (value == null) return value; + var type = value.GetType(); + if (type.IsEnum()&& type != typeof(DateType)&& type!=typeof(JoinType)&&type!=typeof(OrderByType)) return Convert.ToInt64(value); + else + return value; + } + + public static bool IsLogicOperator(string operatorValue) + { + return operatorValue == "&&" || operatorValue == "||"||operatorValue == "AND" || operatorValue == "OR"; + } + + public static bool IsLogicOperator(Expression expression) + { + return expression.NodeType == ExpressionType.And || + expression.NodeType == ExpressionType.AndAlso || + expression.NodeType == ExpressionType.Or || + expression.NodeType == ExpressionType.OrElse; + } + public static bool IsComparisonOperator(Expression expression) + { + return expression.NodeType != ExpressionType.And && + expression.NodeType != ExpressionType.AndAlso && + expression.NodeType != ExpressionType.Or && + expression.NodeType != ExpressionType.OrElse; + } + public static object GetMemberValue(MemberInfo member, Expression expression) + { + var rootExpression = expression as MemberExpression; + var memberInfos = new Stack(); + var fieldInfo = member as System.Reflection.FieldInfo; + object reval = null; + MemberExpression memberExpr = null; + while (expression is MemberExpression) + { + memberExpr = expression as MemberExpression; + memberInfos.Push(memberExpr.Member); + if (memberExpr.Expression == null) + { + var isProperty = memberExpr.Member.MemberType == MemberTypes.Property; + var isField = memberExpr.Member.MemberType == MemberTypes.Field; + if (isProperty) + { + try + { + reval = GetPropertyValue(memberExpr); + } + catch + { + reval = null; + } + } + else if (isField) + { + reval = GetFiledValue(memberExpr); + } + } + if (memberExpr.Expression == null) + { + + } + expression = memberExpr.Expression; + } + // fetch the root object reference: + var constExpr = expression as ConstantExpression; + if (constExpr == null) { + return DynamicInvoke(rootExpression); + } + object objReference = constExpr.Value; + // "ascend" back whence we came from and resolve object references along the way: + while (memberInfos.Count > 0) // or some other break condition + { + var mi = memberInfos.Pop(); + if (mi.MemberType == MemberTypes.Property) + { + var objProp = objReference.GetType().GetProperty(mi.Name); + if (objProp == null) + { + objReference = DynamicInvoke(expression, rootExpression==null?memberExpr: rootExpression); + } + else + { + objReference = objProp.GetValue(objReference, null); + } + } + else if (mi.MemberType == MemberTypes.Field) + { + var objField = objReference.GetType().GetField(mi.Name); + if (objField == null) + { + objReference = DynamicInvoke(expression, rootExpression==null?memberExpr: rootExpression); + } + else + { + objReference = objField.GetValue(objReference); + } + } + } + reval = objReference; + return reval; + } + + public static object GetFiledValue(MemberExpression memberExpr) + { + if (!(memberExpr.Member is FieldInfo)) + { + return DynamicInvoke(memberExpr); + } + object reval = null; + FieldInfo field = (FieldInfo)memberExpr.Member; + Check.Exception(field.IsPrivate, string.Format(" Field \"{0}\" can't be private ", field.Name)); + reval = field.GetValue(memberExpr.Member); + if (reval != null && reval.GetType().IsClass() && reval.GetType() != UtilConstants.StringType) + { + var fieldName = memberExpr.Member.Name; + var proInfo = reval.GetType().GetProperty(fieldName); + if (proInfo != null) + { + reval = proInfo.GetValue(reval, null); + } + var fieInfo = reval.GetType().GetField(fieldName); + if (fieInfo != null) + { + reval = fieInfo.GetValue(reval); + } + if (fieInfo == null && proInfo == null) + { + Check.Exception(field.IsPrivate, string.Format(" Field \"{0}\" can't be private ", field.Name)); + } + } + return reval; + } + + + public static bool IsConstExpression(MemberExpression memberExpr) + { + var result = false; + while (memberExpr!=null&&memberExpr.Expression != null) + { + var isConst = memberExpr.Expression is ConstantExpression; + if (isConst) + { + result = true; + break; + } + memberExpr = memberExpr.Expression as MemberExpression; + } + return result; + } + + public static object GetPropertyValue(MemberExpression memberExpr) + { + if (!(memberExpr.Member is PropertyInfo)) + { + return DynamicInvoke(memberExpr); + } + object reval = null; + PropertyInfo pro = (PropertyInfo)memberExpr.Member; + reval = pro.GetValue(memberExpr.Member, null); + if (reval != null && reval.GetType().IsClass() && reval.GetType() != UtilConstants.StringType) + { + var fieldName = memberExpr.Member.Name; + var proInfo = reval.GetType().GetProperty(fieldName); + if (proInfo != null) + { + reval = proInfo.GetValue(reval, null); + } + var fieInfo = reval.GetType().GetField(fieldName); + if (fieInfo != null) + { + reval = fieInfo.GetValue(reval); + } + if (fieInfo == null && proInfo == null) + { + Check.Exception(true, string.Format(" Property \"{0}\" can't be private ", pro.Name)); + } + } + return reval; + } + + public static object DynamicInvoke(Expression expression,MemberExpression memberExpression=null) + { + object value = Expression.Lambda(expression).Compile().DynamicInvoke(); + if (value != null && value.GetType().IsClass() && value.GetType() != UtilConstants.StringType&& memberExpression!=null) + { + value = Expression.Lambda(memberExpression).Compile().DynamicInvoke(); + } + + return value; + } + + public static Type GetPropertyOrFieldType(MemberInfo propertyOrField) + { + if (propertyOrField.MemberType == MemberTypes.Property) + return ((PropertyInfo)propertyOrField).PropertyType; + if (propertyOrField.MemberType == MemberTypes.Field) + return ((FieldInfo)propertyOrField).FieldType; + throw new NotSupportedException(); + } + + public static bool IsEntity(Type type) + { + return type.IsClass() && type != UtilConstants.StringType; + } + + public static bool IsValueType(Type type) + { + return !IsEntity(type); + } + + public static bool IsUnConvertExpress(Expression item) + { + return item is UnaryExpression && item.NodeType == ExpressionType.Convert; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/MethodCallExpressionModel.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/MethodCallExpressionModel.cs new file mode 100644 index 0000000..78f7ab7 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/MethodCallExpressionModel.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Linq.Expressions; +namespace SqlSugar +{ + public class MethodCallExpressionModel + { + public List Args { get; set; } + public string Name { get; set; } + public dynamic Data { get; set; } + } + + public class MethodCallExpressionArgs + { + public bool IsMember { get; set; } + public object MemberName { get; set; } + public object MemberValue { get; set; } + public Type Type { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ResolveExpressType.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ResolveExpressType.cs new file mode 100644 index 0000000..2c97a23 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/ResolveExpressType.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public enum ResolveExpressType + { + None = 0, + WhereSingle = 1, + WhereMultiple = 2, + SelectSingle=3, + SelectMultiple=4, + FieldSingle=5, + FieldMultiple=7, + Join=8, + ArraySingle=9, + ArrayMultiple = 10, + Update =11 + + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/SugarParameter.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/SugarParameter.cs new file mode 100644 index 0000000..97cc596 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Common/SugarParameter.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class SugarParameter : DbParameter + { + public bool IsRefCursor { get; set; } + public SugarParameter(string name, object value) + { + this.Value = value; + this.ParameterName = name; + if (value != null) + { + SettingDataType(value.GetType()); + } + } + public SugarParameter(string name, object value, Type type) + { + this.Value = value; + this.ParameterName = name; + SettingDataType(type); + } + public SugarParameter(string name, object value, Type type, ParameterDirection direction) + { + this.Value = value; + this.ParameterName = name; + this.Direction = direction; + SettingDataType(type); + } + public SugarParameter(string name, object value, Type type, ParameterDirection direction, int size) + { + this.Value = value; + this.ParameterName = name; + this.Direction = direction; + this.Size = size; + SettingDataType(type); + } + + + public SugarParameter(string name, object value, System.Data.DbType type) + { + this.Value = value; + this.ParameterName = name; + this.DbType = type; + } + public SugarParameter(string name, DataTable value, string SqlServerTypeName) + { + this.Value = value; + this.ParameterName = name; + this.TypeName = SqlServerTypeName; + } + public SugarParameter(string name, object value, System.Data.DbType type, ParameterDirection direction) + { + this.Value = value; + this.ParameterName = name; + this.Direction = direction; + this.DbType = type; + } + public SugarParameter(string name, object value, System.Data.DbType type, ParameterDirection direction, int size) + { + this.Value = value; + this.ParameterName = name; + this.Direction = direction; + this.Size = size; + this.DbType = type; + } + + private void SettingDataType(Type type) + { + if (type == UtilConstants.ByteArrayType) + { + this.DbType = System.Data.DbType.Binary; + } + else if (type == UtilConstants.GuidType) + { + this.DbType = System.Data.DbType.Guid; + } + else if (type == UtilConstants.IntType) + { + this.DbType = System.Data.DbType.Int32; + } + else if (type == UtilConstants.ShortType) + { + this.DbType = System.Data.DbType.Int16; + } + else if (type == UtilConstants.LongType) + { + this.DbType = System.Data.DbType.Int64; + } + else if (type == UtilConstants.DateType) + { + this.DbType = System.Data.DbType.DateTime; + } + else if (type == UtilConstants.DobType) + { + this.DbType = System.Data.DbType.Double; + } + else if (type == UtilConstants.DecType) + { + this.DbType = System.Data.DbType.Decimal; + } + else if (type == UtilConstants.ByteType) + { + this.DbType = System.Data.DbType.Byte; + } + else if (type == UtilConstants.FloatType) + { + this.DbType = System.Data.DbType.Single; + } + else if (type == UtilConstants.BoolType) + { + this.DbType = System.Data.DbType.Boolean; + } + else if (type == UtilConstants.StringType) + { + this.DbType = System.Data.DbType.String; + } + else if (type == UtilConstants.DateTimeOffsetType) + { + this.DbType = System.Data.DbType.DateTimeOffset; + } + else if (type == UtilConstants.TimeSpanType) + { + if (this.Value != null) + this.Value = this.Value.ToString(); + } + else if (type.IsEnum()) + { + this.DbType = System.Data.DbType.Int64; + } + + } + public SugarParameter(string name, object value, bool isOutput) + { + this.Value = value; + this.ParameterName = name; + if (isOutput) + { + this.Direction = ParameterDirection.Output; + } + } + public override System.Data.DbType DbType + { + get; set; + } + + public override ParameterDirection Direction + { + get; set; + } + + public override bool IsNullable + { + get; set; + } + + public override string ParameterName + { + get; set; + } + + public int _Size; + + public override int Size + { + get + { + if (_Size == 0 && Value != null) + { + var isByteArray = Value.GetType() == UtilConstants.ByteArrayType; + if (isByteArray) + _Size = -1; + else + { + var length = Value.ToString().Length; + _Size = length < 4000 ? 4000 : -1; + + } + } + if (_Size == 0) + _Size = 4000; + return _Size; + } + set + { + _Size = value; + } + } + + public override string SourceColumn + { + get; set; + } + + public override bool SourceColumnNullMapping + { + get; set; + } + public string UdtTypeName + { + get; + set; + } + + public override object Value + { + get; set; + } + + public Dictionary TempDate + { + get; set; + } + + /// + /// 如果类库是.NET 4.5请删除该属性 + /// If the SqlSugar library is.NET 4.5, delete the property + /// + public override DataRowVersion SourceVersion + { + get; set; + } + + public override void ResetDbType() + { + this.DbType = System.Data.DbType.String; + } + + + public string TypeName { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/DefaultDbMethod.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/DefaultDbMethod.cs new file mode 100644 index 0000000..56f7d8e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/DefaultDbMethod.cs @@ -0,0 +1,405 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial class DefaultDbMethod : IDbMethods + { + public virtual string IIF(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("( CASE WHEN {0} THEN {1} ELSE {2} END )", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + + public virtual string IsNullOrEmpty(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("( {0}='' OR {0} IS NULL )", parameter.MemberName); + } + + public virtual string HasValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("( {0}<>'' AND {0} IS NOT NULL )", parameter.MemberName); + } + + public virtual string HasNumber(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("( {0}>0 AND {0} IS NOT NULL )", parameter.MemberName); + } + + + public virtual string ToUpper(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" (UPPER({0})) ", parameter.MemberName); + } + + public virtual string ToLower(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" (LOWER({0})) ", parameter.MemberName); + } + + public virtual string Trim(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" (rtrim(ltrim({0}))) ", parameter.MemberName); + } + + public virtual string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'+{1}+'%') ", parameter.MemberName, parameter2.MemberName); + } + public virtual string ContainsArray(MethodCallExpressionModel model) + { + var inValueIEnumerable = (IEnumerable)model.Args[0].MemberValue; + List inValues = new List(); + if (inValueIEnumerable != null) + { + foreach (var item in inValueIEnumerable) + { + if (item != null && item.GetType().IsEnum()) + { + inValues.Add(Convert.ToInt64(item)); + } + else + { + inValues.Add(item); + } + } + } + var value = model.Args[1].MemberName; + string inValueString = null; + if (inValues != null && inValues.Count > 0) + { + inValueString = inValues.ToArray().ToJoinSqlInVals(); + } + if (inValueString.IsNullOrEmpty()) + { + return " (1=2) "; + } + else + { + return string.Format(" ({0} IN ({1})) ", value, inValueString); + } + } + + public virtual string ContainsArrayUseSqlParameters(MethodCallExpressionModel model) + { + var inValueIEnumerable = (IEnumerable)model.Args[0].MemberValue; + List inValues = new List(); + if (inValueIEnumerable != null) + { + foreach (var item in inValueIEnumerable) + { + if (item != null && item.GetType().IsEnum()) + { + inValues.Add(Convert.ToInt64(item)); + } + else + { + inValues.Add(item); + } + } + } + var value = model.Args[1].MemberName; + string inValueString = null; + if (inValues != null && inValues.Count > 0) + { + for (int i = 0; i < inValues.Count; i++) + { + inValueString += model.Data + "_" + i+","; + } + } + if (inValueString.IsNullOrEmpty()) + { + return " (1=2) "; + } + else + { + inValueString=inValueString.TrimEnd(','); + return string.Format(" ({0} IN ({1})) ", value, inValueString); + } + } + + public virtual string Equals(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} = {1}) ", parameter.MemberName, parameter2.MemberName); ; + } + + public virtual string DateIsSameDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (DATEDIFF(day,{0},{1})=0) ", parameter.MemberName, parameter2.MemberName); ; + } + + public virtual string DateIsSameByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (DATEDIFF({2},{0},{1})=0) ", parameter.MemberName, parameter2.MemberName, parameter3.MemberValue); + } + + public virtual string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (DATEADD({2},{1},{0})) ", parameter.MemberName, parameter2.MemberName, parameter3.MemberValue); + } + + public virtual string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (DATEADD(day,{1},{0})) ", parameter.MemberName, parameter2.MemberName); + } + + public virtual string Between(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + var parameter2 = model.Args[2]; + return string.Format(" ({0} BETWEEN {1} AND {2}) ", parameter.MemberName, parameter1.MemberName, parameter2.MemberName); + } + + public virtual string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like {1}+'%') ", parameter.MemberName, parameter2.MemberName); + } + + public virtual string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'+{1}) ", parameter.MemberName, parameter2.MemberName); + } + + public virtual string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" DateName({0},{1}) ", parameter2.MemberValue, parameter.MemberName); + } + + public virtual string ToInt32(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS INT)", parameter.MemberName); + } + + public virtual string ToInt64(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS BIGINT)", parameter.MemberName); + } + + public virtual string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS NVARCHAR(MAX))", parameter.MemberName); + } + + public virtual string ToGuid(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS UNIQUEIDENTIFIER)", parameter.MemberName); + } + + public virtual string ToDouble(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS FLOAT)", parameter.MemberName); + } + + public virtual string ToBool(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS BIT)", parameter.MemberName); + } + + public virtual string ToDate(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DATETIME)", parameter.MemberName); + } + + public virtual string ToTime(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS TIME)", parameter.MemberName); + } + + public virtual string ToDecimal(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS MONEY)", parameter.MemberName); + } + public virtual string Substring(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("SUBSTRING({0},1 + {1},{2})", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + + public virtual string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("LEN({0})", parameter.MemberName); + } + + public virtual string Replace(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("REPLACE({0},{1},{2})", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + + public virtual string AggregateSum(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("SUM({0})", parameter.MemberName); + } + + public virtual string AggregateAvg(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("AVG({0})", parameter.MemberName); + } + + public virtual string AggregateMin(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("MIN({0})", parameter.MemberName); + } + + public virtual string AggregateMax(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("MAX({0})", parameter.MemberName); + } + + public virtual string AggregateCount(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("COUNT({0})", parameter.MemberName); + } + + public virtual string AggregateDistinctCount(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("COUNT(DISTINCT{0})", parameter.MemberName); + } + + public virtual string MappingColumn(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("{0}", parameter1.MemberValue); + } + + public virtual string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("ISNULL({0},{1})", parameter.MemberName, parameter1.MemberName); + } + + public virtual string True() + { + return "( 1 = 1 ) "; + } + + public virtual string False() + { + return "( 1 = 2 ) "; + } + + public string GuidNew() + { + return "'" + Guid.NewGuid() + "' "; + } + + public string GetSelfAndAutoFill(string shortName, bool isSingle) + { + if (isSingle) return "*"; + else + return string.Format("{0}.*", shortName); + } + + public virtual string MergeString(params string[] strings) + { + return string.Join("+", strings); + } + + public virtual string Pack(string sql) + { + return "(" + sql + ")"; + } + + public virtual string EqualTrue(string fieldName) + { + return "( " + fieldName + "=1 )"; + } + + public virtual string Null() + { + return "NULL"; + } + + public virtual string GetDate() + { + return "GETDATE()"; + } + + public virtual string GetRandom() + { + return "NEWID()"; + } + + public virtual string CaseWhen(List> sqls) + { + StringBuilder reslut = new StringBuilder(); + foreach (var item in sqls) + { + if (item.Key == "IF") + { + reslut.AppendFormat(" ( CASE WHEN {0} ", item.Value); + } + else if (item.Key == "End") + { + reslut.AppendFormat("ELSE {0} END )", item.Value); + } + else if (item.Key == "Return") + { + reslut.AppendFormat(" THEN {0} ", item.Value); + } + else { + reslut.AppendFormat(" WHEN {0} ", item.Value); + } + } + return reslut.ToString(); + } + public virtual string CharIndex(MethodCallExpressionModel model) + { + return string.Format("CHARINDEX ({0},{1})", model.Args[0].MemberName, model.Args[1].MemberName); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/IDbMethods.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/IDbMethods.cs new file mode 100644 index 0000000..7d99494 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/IDbMethods.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IDbMethods + { + string IIF(MethodCallExpressionModel model); + string HasNumber(MethodCallExpressionModel model); + string HasValue(MethodCallExpressionModel model); + string IsNullOrEmpty(MethodCallExpressionModel model); + string ToLower(MethodCallExpressionModel model); + string ToUpper(MethodCallExpressionModel model); + string Trim(MethodCallExpressionModel model); + string Contains(MethodCallExpressionModel model); + string ContainsArray(MethodCallExpressionModel model); + string ContainsArrayUseSqlParameters(MethodCallExpressionModel model); + string Equals(MethodCallExpressionModel model); + string DateIsSameDay(MethodCallExpressionModel model); + string DateIsSameByType(MethodCallExpressionModel model); + string DateAddByType(MethodCallExpressionModel model); + + string DateValue(MethodCallExpressionModel model); + string DateAddDay(MethodCallExpressionModel model); + string Between(MethodCallExpressionModel model); + string StartsWith(MethodCallExpressionModel model); + string EndsWith(MethodCallExpressionModel model); + string ToInt32(MethodCallExpressionModel model); + string ToInt64(MethodCallExpressionModel model); + string ToString(MethodCallExpressionModel model); + string ToGuid(MethodCallExpressionModel model); + string ToDouble(MethodCallExpressionModel model); + string ToBool(MethodCallExpressionModel model); + string CaseWhen(List> sqls); + string Substring(MethodCallExpressionModel model); + string ToDate(MethodCallExpressionModel model); + string ToTime(MethodCallExpressionModel model); + string ToDecimal(MethodCallExpressionModel model); + string Length(MethodCallExpressionModel model); + string Replace(MethodCallExpressionModel model); + string AggregateSum(MethodCallExpressionModel model); + string AggregateAvg(MethodCallExpressionModel model); + string AggregateMin(MethodCallExpressionModel model); + string AggregateMax(MethodCallExpressionModel model); + string AggregateCount(MethodCallExpressionModel model); + string AggregateDistinctCount(MethodCallExpressionModel model); + string MappingColumn(MethodCallExpressionModel model); + string IsNull(MethodCallExpressionModel model); + string GetSelfAndAutoFill(string shortName,bool isSingle); + string True(); + string False(); + string GuidNew(); + string MergeString(params string[] strings); + string EqualTrue(string value); + string Pack(string sql); + string Null(); + string GetDate(); + string GetRandom(); + string CharIndex(MethodCallExpressionModel model); + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/SqlFunc.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/SqlFunc.cs new file mode 100644 index 0000000..6507670 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/SqlFunc.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SqlFunc + { + public static bool HasNumber(object thisValue) + { + return thisValue.ObjToInt() > 0; + } + public static bool HasValue(object thisValue) + { + return thisValue.HasValue(); + } + public static bool IsNullOrEmpty(object thisValue) + { + return thisValue.IsNullOrEmpty(); + } + public static string ToLower(object thisValue) + { + return thisValue == null ? null : thisValue.ToString().ToLower(); + } + public static string ToUpper(object thisValue) + { + return thisValue == null ? null : thisValue.ToString().ToUpper(); + } + public static string Trim(object thisValue) + { + return thisValue == null ? null : thisValue.ToString().Trim(); + } + public static bool Contains(string thisValue, string parameterValue) + { + return thisValue.Contains(parameterValue); + } + public static bool ContainsArray(T[] thisValue, object InField) + { + return thisValue.Contains((T)InField); + } + public static bool ContainsArray(List thisValue, object InField) + { + return thisValue.Contains((T)InField); + } + public static bool ContainsArrayUseSqlParameters(List thisValue, object InField) + { + return thisValue.Contains((T)InField); + } + public static bool ContainsArrayUseSqlParameters(T[] thisValue, object InField) + { + return thisValue.Contains((T)InField); + } + public static bool StartsWith(string thisValue, string parameterValue) + { + return thisValue.StartsWith(parameterValue); + } + public static bool EndsWith(string thisValue, string parameterValue) + { + return thisValue.EndsWith(parameterValue); + } + public new static bool Equals(object thisValue, object parameterValue) + { + return thisValue.Equals(parameterValue); + } + public static bool DateIsSame(DateTime date1, DateTime date2) + { + return date1.ToString("yyyy-MM-dd") == date2.ToString("yyyy-MM-dd"); + } + public static bool DateIsSame(DateTime? date1, DateTime? date2) + { + return ((DateTime)date1).ToString("yyyy-MM-dd") == ((DateTime)date2).ToString("yyyy-MM-dd"); + } + public static bool DateIsSame(DateTime date1, DateTime date2, DateType dataType) { throw new NotSupportedException("Can only be used in expressions"); } + public static DateTime DateAdd(DateTime date, int addValue, DateType dataType) { throw new NotSupportedException("Can only be used in expressions"); } + public static DateTime DateAdd(DateTime date, int addValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static int DateValue(DateTime date, DateType dataType) { throw new NotSupportedException("Can only be used in expressions"); } + public static bool Between(object value, object start, object end) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult IIF(bool Expression, TResult thenValue, TResult elseValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult IsNull(TResult thisValue, TResult ifNullValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1,string value2) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2,string value3) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2,string value3,string value4) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2, string value3, string value4,string value5) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2, string value3, string value4, string value5,string value6) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2, string value3, string value4, string value5, string value6,string value7) { throw new NotSupportedException("Can only be used in expressions"); } + public static int ToInt32(object value) { return value.ObjToInt(); } + public static long ToInt64(object value) { return Convert.ToInt64(value); } + /// + /// yyyy-MM-dd HH:mm:ss.fff + /// + /// + /// + public static DateTime ToDate(object value) { return value.ObjToDate(); } + /// + ///HH:mm:ss + /// + /// + /// + public static TimeSpan ToTime(object value) { throw new NotSupportedException("Can only be used in expressions"); } + public static string ToString(object value) { return value.ObjToString(); } + public static decimal ToDecimal(object value) { return value.ObjToDecimal(); } + public static Guid ToGuid(object value) { return Guid.Parse(value.ObjToString()); } + public static double ToDouble(object value) { return value.ObjToMoney(); } + public static bool ToBool(object value) { return value.ObjToBool(); } + public static string Substring(object value, int index, int length) { return value.ObjToString().Substring(index, length); } + public static string Replace(object value, string oldChar, string newChar) { return value.ObjToString().Replace(oldChar, newChar); } + public static int Length(object value) { return value.ObjToString().Length; } + public static TResult AggregateSum(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult AggregateAvg(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult AggregateMin(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult AggregateMax(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static int AggregateCount(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static int AggregateDistinctCount(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult MappingColumn(TResult oldColumnName,string newColumnName) { throw new NotSupportedException("Can only be used in expressions"); } + /// + ///Example: new NewT(){name=SqlFunc.GetSelfAndAutoFill(it)} Generated SQL it.* + /// + /// + /// + /// + public static TResult GetSelfAndAutoFill(TResult value) { throw new NotSupportedException("Can only be used in expressions"); } + public static DateTime GetDate() { throw new NotSupportedException("Can only be used in expressions"); } + public static string GetRandom() { throw new NotSupportedException("Can only be used in expressions"); } + /// + /// Subquery + /// + /// + /// + public static Subqueryable Subqueryable() where T:class,new(){ throw new NotSupportedException("Can only be used in expressions");} + public static CaseThen IF(bool condition) { throw new NotSupportedException("Can only be used in expressions"); } + public static int CharIndex(string findChar,string searchValue) { throw new NotSupportedException("Can only be used in expressions"); } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/SqlFuncExternal.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/SqlFuncExternal.cs new file mode 100644 index 0000000..306475d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/DbMethods/SqlFuncExternal.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlFuncExternal + { + public string UniqueMethodName { get; set; } + public Func MethodValue { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ExpressionContext.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ExpressionContext.cs new file mode 100644 index 0000000..921b421 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ExpressionContext.cs @@ -0,0 +1,240 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + /// + /// ** description:Expression to sql + /// ** author:sunkaixuan + /// ** date:2017/1/14 + /// ** email:610262374@qq.com + public class ExpressionContext : ExpResolveAccessory + { + #region Fields + private bool _IsSingle = true; + private IDbMethods _DbMehtods { get; set; } + #endregion + + #region Properties + public IDbMethods DbMehtods + { + get + { + if (_DbMehtods == null) + { + _DbMehtods = new DefaultDbMethod(); + } + return _DbMehtods; + } + set + { + _DbMehtods = value; + } + } + public int SubQueryIndex { get; set; } + public int Index { get; set; } + public int ParameterIndex { get; set; } + public string SingleTableNameSubqueryShortName{ get; set; } + public MappingColumnList MappingColumns { get; set; } + public MappingTableList MappingTables { get; set; } + public IgnoreColumnList IgnoreComumnList { get; set; } + public List SqlFuncServices { get; set; } + public bool IsSingle + { + get + { + return _IsSingle; + } + set + { + _IsSingle = value; + } + } + public bool IsJoin + { + get + { + return !IsSingle; + } + } + public List JoinQueryInfos { get; set; } + public ResolveExpressType ResolveType { get; set; } + public Expression Expression { get; set; } + public ExpressionResult Result + { + get + { + if (base._Result == null) + { + this.Result = new ExpressionResult(this.ResolveType); + } + return base._Result; + } + set + { + this._Result = value; + } + } + public List Parameters + { + get + { + if (base._Parameters == null) + base._Parameters = new List(); + return base._Parameters; + } + set + { + base._Parameters = value; + } + } + public virtual string SqlParameterKeyWord + { + get + { + return "@"; + } + } + public virtual string SqlTranslationLeft { get { return "["; } } + public virtual string SqlTranslationRight { get { return "]"; } } + public virtual Action InitMappingInfo { get; set; } + public virtual Action RefreshMapping { get; set; } + #endregion + + #region Core methods + public void Resolve(Expression expression, ResolveExpressType resolveType) + { + this.ResolveType = resolveType; + this.Expression = expression; + BaseResolve resolve = new BaseResolve(new ExpressionParameter() { CurrentExpression = this.Expression, Context = this }); + resolve.Start(); + } + public void Clear() + { + base._Result = null; + base._Parameters = new List(); + } + public ExpressionContext GetCopyContext() + { + ExpressionContext copyContext = (ExpressionContext)Activator.CreateInstance(this.GetType(), true); + copyContext.Index = this.Index; + copyContext.InitMappingInfo = this.InitMappingInfo; + copyContext.RefreshMapping = this.RefreshMapping; + copyContext.ParameterIndex = this.ParameterIndex; + return copyContext; + } + public ExpressionContext GetCopyContextWithMapping() + { + ExpressionContext copyContext = (ExpressionContext)Activator.CreateInstance(this.GetType(), true); + copyContext.Index = this.Index; + copyContext.ParameterIndex = this.ParameterIndex; + copyContext.MappingColumns = this.MappingColumns; + copyContext.MappingTables = this.MappingTables; + copyContext.IgnoreComumnList = this.IgnoreComumnList; + copyContext.SqlFuncServices = this.SqlFuncServices; + copyContext.InitMappingInfo = this.InitMappingInfo; + copyContext.RefreshMapping = this.RefreshMapping; + return copyContext; + } + #endregion + + #region Override methods + public virtual string GetTranslationTableName(string entityName, bool isMapping = true) + { + Check.ArgumentNullException(entityName, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + if (IsTranslationText(entityName)) return entityName; + isMapping = isMapping && this.MappingTables.HasValue(); + var isComplex = entityName.Contains(UtilConstants.Dot); + if (isMapping && isComplex) + { + var columnInfo = entityName.Split(UtilConstants.DotChar); + var mappingInfo = this.MappingTables.FirstOrDefault(it => it.EntityName.Equals(columnInfo.Last(), StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null) + { + columnInfo[columnInfo.Length - 1] = mappingInfo.EntityName; + } + return string.Join(UtilConstants.Dot, columnInfo.Select(it => GetTranslationText(it))); + } + else if (isMapping) + { + var mappingInfo = this.MappingTables.FirstOrDefault(it => it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase)); + var name = (mappingInfo == null ? entityName : mappingInfo.DbTableName); + if (name.Contains(".")) + { + return string.Join(".", name.Split('.').Select(it => SqlTranslationLeft + it + SqlTranslationRight)); + } + else + { + return SqlTranslationLeft + name + SqlTranslationRight; + } + } + else if (isComplex) + { + return string.Join(UtilConstants.Dot, entityName.Split(UtilConstants.DotChar).Select(it => GetTranslationText(it))); + } + else + { + return GetTranslationText(entityName); + } + } + public virtual string GetTranslationColumnName(string columnName) + { + Check.ArgumentNullException(columnName, string.Format(ErrorMessage.ObjNotExist, "Column Name")); + if (columnName.Substring(0, 1) == this.SqlParameterKeyWord) + { + return columnName; + } + if (IsTranslationText(columnName)) return columnName; + if (columnName.Contains(UtilConstants.Dot)) + { + return string.Join(UtilConstants.Dot, columnName.Split(UtilConstants.DotChar).Select(it => GetTranslationText(it))); + } + else + { + return GetTranslationText(columnName); + } + } + public virtual string GetDbColumnName(string entityName, string propertyName) + { + if (this.MappingColumns.HasValue()) + { + var mappingInfo = this.MappingColumns.SingleOrDefault(it => it.EntityName == entityName && it.PropertyName == propertyName); + return mappingInfo == null ? propertyName : mappingInfo.DbColumnName; + } + else + { + return propertyName; + } + } + public virtual bool IsTranslationText(string name) + { + var result = name.IsContainsIn(SqlTranslationLeft, SqlTranslationRight, UtilConstants.Space, ExpressionConst.LeftParenthesis, ExpressionConst.RightParenthesis); + return result; + } + public virtual string GetTranslationText(string name) + { + return SqlTranslationLeft + name + SqlTranslationRight; + } + public virtual string GetAsString(string asName, string fieldValue) + { + if (fieldValue.Contains(".*") || fieldValue == "*") return fieldValue; + return string.Format(" {0} {1} {2} ", GetTranslationColumnName(fieldValue), "AS", GetTranslationColumnName(asName)); + } + + public virtual string GetEqString(string eqName, string fieldValue) + { + return string.Format(" {0} {1} {2} ", GetTranslationColumnName(eqName), "=", GetTranslationColumnName(fieldValue)); + } + + public virtual string GetAsString(string asName, string fieldValue, string fieldShortName) + { + if (fieldValue.Contains(".*") || fieldValue == "*") return fieldValue; + return string.Format(" {0} {1} {2} ", GetTranslationColumnName(fieldShortName + "." + fieldValue), "AS", GetTranslationColumnName(asName)); + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BaseResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BaseResolve.cs new file mode 100644 index 0000000..89155f5 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BaseResolve.cs @@ -0,0 +1,556 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public class BaseResolve + { + protected Expression Expression { get; set; } + protected Expression ExactExpression { get; set; } + public ExpressionContext Context { get; set; } + public bool? IsLeft { get; set; } + public int ContentIndex { get { return this.Context.Index; } } + public int Index { get; set; } + public ExpressionParameter BaseParameter { get; set; } + + private BaseResolve() + { + + } + public BaseResolve(ExpressionParameter parameter) + { + this.Expression = parameter.CurrentExpression; + this.Context = parameter.Context; + this.BaseParameter = parameter; + } + + public BaseResolve Start() + { + Context.Index++; + Expression expression = this.Expression; + ExpressionParameter parameter = new ExpressionParameter() + { + Context = this.Context, + CurrentExpression = expression, + IsLeft = this.IsLeft, + BaseExpression = this.ExactExpression, + BaseParameter = this.BaseParameter, + Index = Context.Index + }; + if (expression is LambdaExpression) + { + return new LambdaExpressionResolve(parameter); + } + else if (expression is BinaryExpression && expression.NodeType == ExpressionType.Coalesce) + { + return new CoalesceResolveItems(parameter); + } + else if (expression is BinaryExpression) + { + return new BinaryExpressionResolve(parameter); + } + else if (expression is BlockExpression) + { + Check.ThrowNotSupportedException("BlockExpression"); + } + else if (expression is ConditionalExpression) + { + return new ConditionalExpressionResolve(parameter); + } + else if (expression is MethodCallExpression) + { + return new MethodCallExpressionResolve(parameter); + } + else if (expression is MemberExpression && ((MemberExpression)expression).Expression == null) + { + return new MemberNoExpressionResolve(parameter); + } + else if (expression is MemberExpression && ((MemberExpression)expression).Expression.NodeType == ExpressionType.Constant) + { + return new MemberConstExpressionResolve(parameter); + } + else if (expression is MemberExpression && ((MemberExpression)expression).Expression.NodeType == ExpressionType.New) + { + return new MemberNewExpressionResolve(parameter); + } + else if (expression is ConstantExpression) + { + return new ConstantExpressionResolve(parameter); + } + else if (expression is MemberExpression) + { + return new MemberExpressionResolve(parameter); + } + else if (expression is UnaryExpression) + { + return new UnaryExpressionResolve(parameter); + } + else if (expression is MemberInitExpression) + { + return new MemberInitExpressionResolve(parameter); + } + else if (expression is NewExpression) + { + return new NewExpressionResolve(parameter); + } + else if (expression is NewArrayExpression) + { + return new NewArrayExpessionResolve(parameter); + } + else if (expression is ParameterExpression) + { + return new TypeParameterExpressionReolve(parameter); + } + else if (expression != null && expression.NodeType.IsIn(ExpressionType.NewArrayBounds)) + { + Check.ThrowNotSupportedException("ExpressionType.NewArrayBounds"); + } + return null; + } + + protected void AppendMember(ExpressionParameter parameter, bool? isLeft, object appendValue) + { + + Context.ParameterIndex++; + if (isLeft == true) + { + appendValue += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue.ObjToString()); + } + else + { + this.Context.Result.Append(appendValue); + } + } + protected void AppendValue(ExpressionParameter parameter, bool? isLeft, object value) + { + if (parameter.BaseExpression is BinaryExpression || parameter.BaseExpression == null) + { + var oppoSiteExpression = isLeft == true ? parameter.BaseParameter.RightExpression : parameter.BaseParameter.LeftExpression; + if (parameter.CurrentExpression is MethodCallExpression||parameter.CurrentExpression is ConditionalExpression||parameter.CurrentExpression.NodeType==ExpressionType.Coalesce) + { + var appendValue = value; + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue.ObjToString()); + } + else + { + this.Context.Result.Append(appendValue); + } + this.AppendOpreator(parameter, isLeft); + } + else if (oppoSiteExpression is MemberExpression) + { + string appendValue = Context.SqlParameterKeyWord + + ((MemberExpression)oppoSiteExpression).Member.Name + + Context.ParameterIndex; + if (value.ObjToString() != "NULL" && !parameter.ValueIsNull) + { + this.Context.Parameters.Add(new SugarParameter(appendValue, value)); + } + else + { + appendValue = value.ObjToString(); + } + Context.ParameterIndex++; + appendValue = string.Format(" {0} ", appendValue); + if (isLeft == true) + { + appendValue += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue); + } + else + { + this.Context.Result.Append(appendValue); + } + } + else if ((oppoSiteExpression is UnaryExpression && (oppoSiteExpression as UnaryExpression).Operand is MemberExpression)) { + string appendValue = Context.SqlParameterKeyWord + + ((MemberExpression)(oppoSiteExpression as UnaryExpression).Operand).Member.Name + + Context.ParameterIndex; + if (value.ObjToString() != "NULL" && !parameter.ValueIsNull) + { + this.Context.Parameters.Add(new SugarParameter(appendValue, value)); + } + else + { + appendValue = value.ObjToString(); + } + Context.ParameterIndex++; + appendValue = string.Format(" {0} ", appendValue); + if (isLeft == true) + { + appendValue += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue); + } + else + { + this.Context.Result.Append(appendValue); + } + } + else + { + var appendValue = this.Context.SqlParameterKeyWord + ExpressionConst.Const + Context.ParameterIndex; + Context.ParameterIndex++; + if (value != null && value.GetType().IsEnum()) + { + value = Convert.ToInt64(value); + } + this.Context.Parameters.Add(new SugarParameter(appendValue, value)); + appendValue = string.Format(" {0} ", appendValue); + if (isLeft == true) + { + appendValue += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue); + } + else + { + this.Context.Result.Append(appendValue); + } + } + } + } + protected void AppendOpreator(ExpressionParameter parameter, bool? isLeft) + { + if (isLeft == true) + { + this.Context.Result.Append(" " + ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index); + } + } + protected string AppendParameter(object paramterValue) + { + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; ; + this.Context.Parameters.Add(new SugarParameter(parameterName, paramterValue)); + return parameterName; + } + protected void AppendNot(object Value) + { + var isAppend = !this.Context.Result.Contains(ExpressionConst.FormatSymbol); + var lastCharIsSpace = this.Context.Result.LastCharIsSpace; + if (isAppend) + { + this.Context.Result.Append(lastCharIsSpace?"NOT":" NOT"); + } + else + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, "NOT"); + } + } + protected void AppendNegate(object Value) + { + var isAppend = !this.Context.Result.Contains(ExpressionConst.FormatSymbol); + var lastCharIsSpace = this.Context.Result.LastCharIsSpace; + if (isAppend) + { + this.Context.Result.Append(lastCharIsSpace ? "-" : " -"); + } + else + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, "-"); + } + } + + protected MethodCallExpressionArgs GetMethodCallArgs(ExpressionParameter parameter, Expression item) + { + var newContext = this.Context.GetCopyContext(); + newContext.MappingColumns = this.Context.MappingColumns; + newContext.MappingTables = this.Context.MappingTables; + newContext.IgnoreComumnList = this.Context.IgnoreComumnList; + newContext.IsSingle = this.Context.IsSingle; + newContext.SqlFuncServices = this.Context.SqlFuncServices; + newContext.Resolve(item, this.Context.IsJoin ? ResolveExpressType.WhereMultiple : ResolveExpressType.WhereSingle); + this.Context.Index = newContext.Index; + this.Context.ParameterIndex = newContext.ParameterIndex; + if (newContext.Parameters.HasValue()) + { + this.Context.Parameters.AddRange(newContext.Parameters); + } + if (newContext.SingleTableNameSubqueryShortName.HasValue()) + { + this.Context.SingleTableNameSubqueryShortName = newContext.SingleTableNameSubqueryShortName; + } + var methodCallExpressionArgs = new MethodCallExpressionArgs() + { + IsMember = true, + MemberName = newContext.Result.GetResultString() + }; + return methodCallExpressionArgs; + } + + protected string GetNewExpressionValue(Expression item) + { + var newContext = this.Context.GetCopyContextWithMapping(); + newContext.Resolve(item, this.Context.IsJoin ? ResolveExpressType.WhereMultiple : ResolveExpressType.WhereSingle); + this.Context.Index = newContext.Index; + this.Context.ParameterIndex = newContext.ParameterIndex; + if (newContext.Parameters.HasValue()) + { + this.Context.Parameters.AddRange(newContext.Parameters); + } + return newContext.Result.GetResultString(); + } + + protected void ResolveNewExpressions(ExpressionParameter parameter, Expression item, string asName) + { + if (item is ConstantExpression) + { + this.Expression = item; + this.Start(); + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); + } + else if ((item is MemberExpression) && ((MemberExpression)item).Expression == null) + { + var paramterValue = ExpressionTool.GetPropertyValue(item as MemberExpression); + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, paramterValue)); + } + else if ((item is MemberExpression) && ((MemberExpression)item).Expression.NodeType == ExpressionType.Constant) + { + this.Expression = item; + this.Start(); + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); + } + else if (item is MemberExpression) + { + if (this.Context.Result.IsLockCurrentParameter == false) + { + this.Context.Result.CurrentParameter = parameter; + this.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + this.Expression = item; + this.Start(); + parameter.IsAppendResult(); + this.Context.Result.Append(this.Context.GetAsString(asName, parameter.CommonTempData.ObjToString())); + this.Context.Result.CurrentParameter = null; + } + } + else if (item is UnaryExpression && ((UnaryExpression)item).Operand is MemberExpression) + { + if (this.Context.Result.IsLockCurrentParameter == false) + { + var expression = ((UnaryExpression)item).Operand as MemberExpression; + var isDateTimeNow = ((UnaryExpression)item).Operand.ToString() == "DateTime.Now"; + if (expression.Expression == null && !isDateTimeNow) + { + this.Context.Result.CurrentParameter = parameter; + this.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + this.Expression = item; + this.Start(); + parameter.IsAppendResult(); + this.Context.Result.Append(this.Context.GetAsString(asName, parameter.CommonTempData.ObjToString())); + this.Context.Result.CurrentParameter = null; + } + else if (expression.Expression is ConstantExpression || isDateTimeNow) + { + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, ExpressionTool.GetMemberValue(expression.Member, expression))); + } + else + { + this.Context.Result.CurrentParameter = parameter; + this.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + this.Expression = item; + this.Start(); + parameter.IsAppendResult(); + this.Context.Result.Append(this.Context.GetAsString(asName, parameter.CommonTempData.ObjToString())); + this.Context.Result.CurrentParameter = null; + } + } + } + else if (item is UnaryExpression && ((UnaryExpression)item).Operand is ConstantExpression) + { + if (this.Context.Result.IsLockCurrentParameter == false) + { + this.Expression = ((UnaryExpression)item).Operand; + this.Start(); + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); + } + } + else if (item is BinaryExpression) + { + if (this.Context.Result.IsLockCurrentParameter == false) + { + var newContext = this.Context.GetCopyContextWithMapping(); + var resolveExpressType = this.Context.IsSingle ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple; + newContext.Resolve(item, resolveExpressType); + this.Context.Index = newContext.Index; + this.Context.ParameterIndex = newContext.ParameterIndex; + if (newContext.Parameters.HasValue()) + { + this.Context.Parameters.AddRange(newContext.Parameters); + } + this.Context.Result.Append(this.Context.GetAsString(asName, newContext.Result.GetString())); + this.Context.Result.CurrentParameter = null; + if (this.Context.SingleTableNameSubqueryShortName.IsNullOrEmpty() && newContext.SingleTableNameSubqueryShortName.HasValue()) + { + this.Context.SingleTableNameSubqueryShortName = newContext.SingleTableNameSubqueryShortName; + } + } + } + else if (item.Type.IsClass()) + { + this.Expression = item; + this.Start(); + var shortName = parameter.CommonTempData; + var listProperties = item.Type.GetProperties().Cast().ToList(); + foreach (var property in listProperties) + { + var hasIgnore = this.Context.IgnoreComumnList != null && this.Context.IgnoreComumnList.Any(it => it.EntityName.Equals(item.Type.Name, StringComparison.CurrentCultureIgnoreCase) && it.PropertyName.Equals(property.Name, StringComparison.CurrentCultureIgnoreCase)); + if (hasIgnore) + { + continue; + } + if (property.PropertyType.IsClass()) + { + + } + else + { + var propertyName = property.Name; + var dbColumnName = propertyName; + var mappingInfo = this.Context.MappingColumns.FirstOrDefault(it => it.EntityName == item.Type.Name && it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo.HasValue()) + { + dbColumnName = mappingInfo.DbColumnName; + } + asName = this.Context.GetTranslationText(item.Type.Name + "." + propertyName); + if (Context.IsJoin) + { + this.Context.Result.Append(Context.GetAsString(asName, dbColumnName, shortName.ObjToString())); + } + else + { + this.Context.Result.Append(Context.GetAsString(asName, dbColumnName)); + } + } + } + } + else if (item.Type == UtilConstants.BoolType && item is MethodCallExpression && (item as MethodCallExpression).Method.Name == "Any"&&IsSubMethod(item as MethodCallExpression)) + { + this.Expression = item; + this.Start(); + var sql= this.Context.DbMehtods.IIF(new MethodCallExpressionModel() + { + Args=new List() { + new MethodCallExpressionArgs() { + IsMember=true, + MemberName=parameter.CommonTempData.ObjToString() + }, + new MethodCallExpressionArgs() { + IsMember=true, + MemberName=1 + }, + new MethodCallExpressionArgs() { + IsMember=true, + MemberName=0 + } + } + }); + parameter.Context.Result.Append(this.Context.GetAsString(asName, sql)); + } + else if (item is MethodCallExpression || item is UnaryExpression || item is ConditionalExpression || item.NodeType == ExpressionType.Coalesce) + { + this.Expression = item; + this.Start(); + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameter.CommonTempData.ObjToString())); + } + else + { + Check.ThrowNotSupportedException(item.GetType().Name); + } + } + protected static bool IsConvert(Expression item) + { + return item is UnaryExpression && item.NodeType == ExpressionType.Convert; + } + + protected static bool IsNotMember(Expression item) + { + return item is UnaryExpression && + item.Type == UtilConstants.BoolType && + (item as UnaryExpression).NodeType == ExpressionType.Not && + (item as UnaryExpression).Operand is MemberExpression && + ((item as UnaryExpression).Operand as MemberExpression).Expression != null && + ((item as UnaryExpression).Operand as MemberExpression).Expression.NodeType == ExpressionType.Parameter; + } + protected static bool IsNotParameter(Expression item) + { + return item is UnaryExpression && + item.Type == UtilConstants.BoolType && + (item as UnaryExpression).NodeType == ExpressionType.Not && + (item as UnaryExpression).Operand is MemberExpression && + ((item as UnaryExpression).Operand as MemberExpression).Expression != null && + ((item as UnaryExpression).Operand as MemberExpression).Expression.NodeType == ExpressionType.MemberAccess; + } + + protected bool IsSubMethod(MethodCallExpression express) + { + return SubTools.SubItemsConst.Any(it => express.Object != null && express.Object.Type.Name == "Subqueryable`1"); + } + protected static Dictionary MethodMapping = new Dictionary() { + { "ToString","ToString"}, + { "ToInt32","ToInt32"}, + { "ToInt16","ToInt32"}, + { "ToInt64","ToInt64"}, + { "ToDecimal","ToDecimal"}, + { "ToDateTime","ToDate"}, + { "ToBoolean","ToBool"}, + { "ToDouble","ToDouble"}, + { "Length","Length"}, + { "Replace","Replace"}, + { "Contains","Contains"}, + { "ContainsArray","ContainsArray"}, + { "EndsWith","EndsWith"}, + { "StartsWith","StartsWith"}, + { "HasValue","HasValue"}, + { "Trim","Trim"}, + { "Equals","Equals"}, + { "ToLower","ToLower"}, + { "ToUpper","ToUpper"}, + { "Substring","Substring"}, + { "DateAdd","DateAdd"} + }; + + protected static Dictionary MethodTimeMapping = new Dictionary() { + { "AddYears",DateType.Year}, + { "AddMonths",DateType.Month}, + { "AddDays",DateType.Day}, + { "AddHours",DateType.Hour}, + { "AddMinutes",DateType.Minute}, + { "AddSeconds",DateType.Second}, + { "AddMilliseconds",DateType.Millisecond} + }; + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BinaryExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BinaryExpressionResolve.cs new file mode 100644 index 0000000..a503bb0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BinaryExpressionResolve.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class BinaryExpressionResolve : BaseResolve + { + public BinaryExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = this.Expression as BinaryExpression; + var operatorValue = parameter.OperatorValue = ExpressionTool.GetOperator(expression.NodeType); + var isEqual = expression.NodeType == ExpressionType.Equal; + var isComparisonOperator = ExpressionTool.IsComparisonOperator(expression); + base.ExactExpression = expression; + var leftExpression = expression.Left; + var rightExpression = expression.Right; + var leftIsBinary = leftExpression is BinaryExpression; + var rightBinary = rightExpression is BinaryExpression; + var lbrs = leftIsBinary && !rightBinary; + var lsrb = !leftIsBinary && rightBinary; + var lbrb = rightBinary && leftIsBinary; + var lsbs = !leftIsBinary && !rightBinary; + var isAppend = !base.Context.Result.Contains(ExpressionConst.FormatSymbol); + if (isAppend) + { + base.Context.Result.Append(ExpressionConst.LeftParenthesis); + base.Context.Result.Append(ExpressionConst.FormatSymbol); + } + else + { + base.Context.Result.Replace(ExpressionConst.FormatSymbol, ExpressionConst.LeftParenthesis + ExpressionConst.FormatSymbol); + } + if (leftExpression is UnaryExpression && (leftExpression as UnaryExpression).Operand is UnaryExpression&& (leftExpression as UnaryExpression).NodeType == ExpressionType.Convert) + { + leftExpression = (leftExpression as UnaryExpression).Operand; + } + if (leftExpression is UnaryExpression && (leftExpression as UnaryExpression).Operand.Type == UtilConstants.BoolType && (leftExpression as UnaryExpression).NodeType == ExpressionType.Convert&&rightExpression.Type==UtilConstants.BoolTypeNull) + { + leftExpression = (leftExpression as UnaryExpression).Operand; + } + if (rightExpression is UnaryExpression&& (rightExpression as UnaryExpression).Operand.Type==UtilConstants.BoolType&& (rightExpression as UnaryExpression).NodeType == ExpressionType.Convert) + { + rightExpression = (rightExpression as UnaryExpression).Operand; + } + parameter.LeftExpression = leftExpression; + parameter.RightExpression = rightExpression; + base.Expression = leftExpression; + base.IsLeft = true; + base.Start(); + if (leftExpression is UnaryExpression && leftExpression.Type == UtilConstants.BoolType&&!this.Context.Result.Contains(ExpressionConst.ExpressionReplace)) + { + this.Context.Result.AppendFormat(" {0} ", ExpressionTool.GetOperator(expression.NodeType)); + } + base.IsLeft = false; + base.Expression = rightExpression; + base.Start(); + base.IsLeft = null; + if (lsbs && parameter.ValueIsNull) + { + base.Context.Result.Replace(ExpressionConst.ExpressionReplace + parameter.Index, isEqual ? "IS" : "IS NOT"); + base.Context.Result.Replace(ExpressionConst.ExpressionReplace + (parameter.Index + 1), isEqual ? "IS" : "IS NOT"); + } + else + { + base.Context.Result.Replace(ExpressionConst.ExpressionReplace + parameter.Index, operatorValue); + base.Context.Result.Replace(ExpressionConst.ExpressionReplace + (parameter.Index + 1), operatorValue); + } + base.Context.Result.Append(ExpressionConst.RightParenthesis); + if (parameter.BaseExpression is BinaryExpression && parameter.IsLeft == true) + { + base.Context.Result.Append(" " + ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index + " "); + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BlockExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BlockExpressionResolve.cs new file mode 100644 index 0000000..1c35ed9 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/BlockExpressionResolve.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class BlockExpressionResolve:BaseResolve + { + public BlockExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/CoalesceResolveItems.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/CoalesceResolveItems.cs new file mode 100644 index 0000000..0887070 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/CoalesceResolveItems.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class CoalesceResolveItems : MethodCallExpressionResolve + { + public CoalesceResolveItems(ExpressionParameter parameter) : base(parameter) + { + string name = "IsNull"; + var express = base.Expression as BinaryExpression; + var args = new List() { + express.Left, + express.Right + }; + var isLeft = parameter.IsLeft; + MethodCallExpressionModel model = new MethodCallExpressionModel(); + model.Args = new List(); + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + Check.Exception(name == "GetSelfAndAutoFill", "SqlFunc.GetSelfAndAutoFill can only be used in Select."); + base.Where(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + base.Select(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + base.Field(parameter, isLeft, name, args, model); + break; + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs new file mode 100644 index 0000000..784a909 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class ConditionalExpressionResolve: MethodCallExpressionResolve + { + public ConditionalExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + + string name = "IIF"; + var express = base.Expression as ConditionalExpression; + var args = new List() { + express.Test, + express.IfTrue, + express.IfFalse + }; + var isLeft = parameter.IsLeft; + MethodCallExpressionModel model = new MethodCallExpressionModel(); + model.Args = new List(); + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + Check.Exception(name == "GetSelfAndAutoFill", "SqlFunc.GetSelfAndAutoFill can only be used in Select."); + base.Where(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + base.Select(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + base.Field(parameter, isLeft, name, args, model); + break; + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/ConstantExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/ConstantExpressionResolve.cs new file mode 100644 index 0000000..0a80640 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/ConstantExpressionResolve.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public class ConstantExpressionResolve : BaseResolve + { + public ConstantExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as ConstantExpression; + var isLeft = parameter.IsLeft; + object value = ExpressionTool.GetValue(expression.Value); + var baseParameter = parameter.BaseParameter; + baseParameter.ChildExpression = expression; + var isSetTempData = baseParameter.CommonTempData.HasValue() && baseParameter.CommonTempData.Equals(CommonTempDataType.Result); + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.SelectSingle: + case ResolveExpressType.Update: + case ResolveExpressType.SelectMultiple: + baseParameter.CommonTempData = value; + break; + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + var parentIsBinary = parameter.BaseParameter.CurrentExpression is BinaryExpression; + var parentIsRoot = parameter.BaseParameter.CurrentExpression is LambdaExpression; + var isBool = value != null && value.GetType() == UtilConstants.BoolType; + if (parentIsRoot && isBool) + { + this.Context.Result.Append(value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False()); + break; + } + if (parentIsBinary && isBool) + { + var isLogicOperator = + parameter.BaseExpression.NodeType == ExpressionType.And || + parameter.BaseExpression.NodeType == ExpressionType.AndAlso || + parameter.BaseExpression.NodeType == ExpressionType.Or || + parameter.BaseExpression.NodeType == ExpressionType.OrElse; + if (isLogicOperator) + { + AppendMember(parameter, isLeft, (value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False())); + break; + } + } + if (value == null && parentIsBinary) + { + parameter.BaseParameter.ValueIsNull = true; + value = this.Context.DbMehtods.Null(); + } + AppendValue(parameter, isLeft, value); + } + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/LambdaExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/LambdaExpressionResolve.cs new file mode 100644 index 0000000..fa63291 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/LambdaExpressionResolve.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class LambdaExpressionResolve : BaseResolve + { + public LambdaExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + LambdaExpression lambda = base.Expression as LambdaExpression; + var expression = lambda.Body; + base.Expression = expression; + if (parameter.Context.ResolveType.IsIn(ResolveExpressType.FieldMultiple, ResolveExpressType.FieldSingle)) { + parameter.CommonTempData = CommonTempDataType.Append; + } + base.Start(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberConstExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberConstExpressionResolve.cs new file mode 100644 index 0000000..8835c3f --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberConstExpressionResolve.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MemberConstExpressionResolve : BaseResolve + { + public MemberConstExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as MemberExpression; + var isLeft = parameter.IsLeft; + object value = ExpressionTool.GetMemberValue(expression.Member, expression); + var baseParameter = parameter.BaseParameter; + var isSetTempData = baseParameter.CommonTempData.HasValue() && baseParameter.CommonTempData.Equals(CommonTempDataType.Result); + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.Update: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + if (value != null && value.GetType().IsEnum()) + { + value = Convert.ToInt64(value); + } + parameter.BaseParameter.CommonTempData = value; + break; + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + AppendValue(parameter, isLeft, value); + } + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + break; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs new file mode 100644 index 0000000..40e72de --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs @@ -0,0 +1,498 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class MemberExpressionResolve : BaseResolve + { + public ExpressionParameter Parameter { get; set; } + public MemberExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + ExpressionParameter baseParameter; + MemberExpression expression; + bool? isLeft; + bool isSetTempData, isValue, isValueBool, isLength, isDateValue, isHasValue, isDateDate, isMemberValue, isSingle, fieldIsBool, isSelectField, isField; + SettingParameters(parameter, out baseParameter, out expression, out isLeft, out isSetTempData, out isValue, out isValueBool, out isLength, out isDateValue, out isHasValue, out isDateDate, out isMemberValue, out isSingle, out fieldIsBool, out isSelectField, out isField); + baseParameter.ChildExpression = expression; + if (isLength) + { + ResolveLength(parameter, isLeft, expression); + } + else if (isHasValue) + { + ResolveHasValue(parameter, expression); + } + else if (isDateValue) + { + ResolveDateValue(parameter, isLeft, expression); + } + else if (isValueBool) + { + ResolveValueBool(parameter, baseParameter, expression, isLeft, isSingle); + } + else if (isValue && expression.Expression != null && expression.Expression is MethodCallExpression) + { + ResolveCallValue(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + else if (isValue) + { + ResolveValue(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + else if (expression.Expression != null && expression.Expression.Type == UtilConstants.DateType && expression is MemberExpression && expression.Expression is MethodCallExpression) + { + ResolveDateDateByCall(parameter, isLeft, expression); + } + else if (isDateDate) + { + ResolveDateDate(parameter, isLeft, expression); + } + else if (isMemberValue) + { + ResolveMemberValue(parameter, baseParameter, isLeft, isSetTempData, expression); + } + else if (fieldIsBool && !isField && !isSelectField) + { + ResolvefieldIsBool(parameter, baseParameter, isLeft, isSetTempData, expression, isSingle); + } + else + { + ResolveDefault(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + } + + + #region Resolve default + private void ResolveDefault(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + string fieldName = string.Empty; + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.Update: + case ResolveExpressType.SelectSingle: + fieldName = GetSingleName(parameter, expression, isLeft); + if (isSetTempData) + baseParameter.CommonTempData = fieldName; + else + base.Context.Result.Append(fieldName); + break; + case ResolveExpressType.SelectMultiple: + fieldName = GetMultipleName(parameter, expression, isLeft); + if (isSetTempData) + baseParameter.CommonTempData = fieldName; + else + base.Context.Result.Append(fieldName); + break; + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + ResolveWhereLogic(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + break; + case ResolveExpressType.FieldSingle: + fieldName = GetSingleName(parameter, expression, isLeft); + base.Context.Result.Append(fieldName); + break; + case ResolveExpressType.FieldMultiple: + fieldName = GetMultipleName(parameter, expression, isLeft); + base.Context.Result.Append(fieldName); + break; + case ResolveExpressType.ArrayMultiple: + case ResolveExpressType.ArraySingle: + fieldName = GetName(parameter, expression, isLeft, parameter.Context.ResolveType == ResolveExpressType.ArraySingle); + base.Context.Result.Append(fieldName); + break; + default: + break; + } + } + + #endregion + + #region Resolve Where + private void ResolveBoolLogic(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + string fieldName = string.Empty; + if (isSetTempData) + { + if (ExpressionTool.IsConstExpression(expression)) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + baseParameter.CommonTempData = value+"=1 "; + } + else + { + fieldName = GetName(parameter, expression, null, isSingle); + baseParameter.CommonTempData = fieldName+"=1 "; + } + } + else + { + if (ExpressionTool.IsConstExpression(expression)) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + base.AppendValue(parameter, isLeft, value+"=1 "); + } + else + { + fieldName = GetName(parameter, expression, isLeft, isSingle); + AppendMember(parameter, isLeft, fieldName+"=1 "); + } + } + } + + private void ResolveWhereLogic(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + string fieldName = string.Empty; + if (isSetTempData) + { + if (ExpressionTool.IsConstExpression(expression)) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + baseParameter.CommonTempData = value; + } + else + { + fieldName = GetName(parameter, expression, null, isSingle); + baseParameter.CommonTempData = fieldName; + } + } + else + { + if (ExpressionTool.IsConstExpression(expression)) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + base.AppendValue(parameter, isLeft, value); + } + else + { + fieldName = GetName(parameter, expression, isLeft, isSingle); + AppendMember(parameter, isLeft, fieldName); + } + } + } + #endregion + + #region Resolve special member + private void ResolveDateDateByCall(ExpressionParameter parameter, bool? isLeft, MemberExpression expression) + { + var value = GetNewExpressionValue(expression.Expression); + if (expression.Member.Name == "Date") + { + AppendMember(parameter, isLeft, GetToDate(this.Context.DbMehtods.MergeString( + this.GetDateValue(value, DateType.Year), + "'-'", + this.GetDateValue(value, DateType.Month), + "'-'", + this.GetDateValue(value, DateType.Day)))); + } + else + { + foreach (int myCode in Enum.GetValues(typeof(DateType))) + { + string strName = Enum.GetName(typeof(DateType), myCode);//获取名称 + if (expression.Member.Name == strName) + { + AppendMember(parameter, isLeft, this.Context.DbMehtods.MergeString(this.GetDateValue(value, (DateType)(myCode)))); + } + } + } + } + private void ResolveCallValue(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + try + { + baseParameter.ChildExpression = expression; + string fieldName = string.Empty; + if (isSetTempData) + { + var value = ExpressionTool.DynamicInvoke(expression); + baseParameter.CommonTempData = value; + } + else + { + var value = ExpressionTool.DynamicInvoke(expression); + base.AppendValue(parameter, isLeft, value); + } + } + catch + { + Check.Exception(true, "Not Support {0}",expression.ToString()); + } + } + + private MemberExpression ResolveValue(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + expression = expression.Expression as MemberExpression; + baseParameter.ChildExpression = expression; + if (UtilMethods.GetUnderType(expression.Type) == UtilConstants.BoolType&¶meter.BaseExpression!=null&&ExpressionTool.IsLogicOperator(parameter.BaseExpression)) + { + ResolveBoolLogic(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + else + { + ResolveWhereLogic(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + return expression; + } + + private void ResolveValueBool(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSingle) + { + string fieldName = GetName(parameter, expression.Expression as MemberExpression, isLeft, isSingle); + if (expression.Type == UtilConstants.BoolType && baseParameter.OperatorValue.IsNullOrEmpty()) + { + fieldName = this.Context.DbMehtods.EqualTrue(fieldName); + } + AppendMember(parameter, isLeft, fieldName); + } + + private void ResolveMemberValue(ExpressionParameter parameter, ExpressionParameter baseParameter, bool? isLeft, bool isSetTempData, MemberExpression expression) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + AppendValue(parameter, isLeft, value); + } + } + private void ResolvefieldIsBool(ExpressionParameter parameter, ExpressionParameter baseParameter, bool? isLeft, bool isSetTempData, MemberExpression expression, bool isSingle) + { + var fieldName = GetName(parameter, expression, isLeft, isSingle); + if (isSetTempData) + { + baseParameter.CommonTempData = fieldName; + } + else + { + fieldName = this.Context.DbMehtods.EqualTrue(fieldName.ObjToString()); + AppendMember(parameter, isLeft, fieldName); + } + } + + private void ResolveDateDate(ExpressionParameter parameter, bool? isLeft, MemberExpression expression) + { + var name = expression.Member.Name; + var oldCommonTempDate = parameter.CommonTempData; + parameter.CommonTempData = CommonTempDataType.Result; + this.Expression = expression.Expression; + this.Start(); + var isConst = parameter.CommonTempData.GetType() == UtilConstants.DateType; + if (isConst) + { + AppendValue(parameter, isLeft, parameter.CommonTempData.ObjToDate().Date); + } + else + { + var GetYear = new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { IsMember=true, MemberName=parameter.CommonTempData, MemberValue=parameter.CommonTempData }, + new MethodCallExpressionArgs() { MemberName=DateType.Year, MemberValue=DateType.Year} + } + }; + AppendMember(parameter, isLeft, GetToDate(this.Context.DbMehtods.MergeString( + this.GetDateValue(parameter.CommonTempData, DateType.Year), + "'-'", + this.GetDateValue(parameter.CommonTempData, DateType.Month), + "'-'", + this.GetDateValue(parameter.CommonTempData, DateType.Day)))); + } + parameter.CommonTempData = oldCommonTempDate; + } + + private void ResolveDateValue(ExpressionParameter parameter, bool? isLeft, MemberExpression expression) + { + var name = expression.Member.Name; + var oldCommonTempDate = parameter.CommonTempData; + parameter.CommonTempData = CommonTempDataType.Result; + this.Expression = expression.Expression; + var isConst = this.Expression is ConstantExpression; + if (this.Expression.Type == UtilConstants.DateType && this.Expression.ToString() == "DateTime.Now") + { + this.Expression = expression; + var parameterName = base.AppendParameter(ExpressionTool.GetMemberValue(expression.Member, expression)); + base.AppendMember(parameter, isLeft, parameterName); + } + else + { + this.Start(); + var result = this.Context.DbMehtods.DateValue(new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { IsMember = !isConst, MemberName = parameter.CommonTempData, MemberValue = null }, + new MethodCallExpressionArgs() { IsMember = true, MemberName = name, MemberValue = name } + } + }); + base.AppendMember(parameter, isLeft, result); + } + parameter.CommonTempData = oldCommonTempDate; + } + + private void ResolveHasValue(ExpressionParameter parameter, MemberExpression expression) + { + parameter.CommonTempData = CommonTempDataType.Result; + this.Expression = expression.Expression; + this.Start(); + var methodParamter = new MethodCallExpressionArgs() { IsMember = true, MemberName = parameter.CommonTempData, MemberValue = null }; + if (expression.Expression?.Type != null) + { + methodParamter.Type =UtilMethods.GetUnderType(expression.Expression?.Type); + } + var result = this.Context.DbMehtods.HasValue(new MethodCallExpressionModel() + { + Args = new List() { + methodParamter + } + }); + if (parameter.BaseExpression != null && ExpressionTool.IsLogicOperator(parameter.BaseExpression) && parameter.IsLeft == true) + { + if (base.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + base.Context.Result.Replace(ExpressionConst.FormatSymbol, ""); + } + this.Context.Result.Append(result+" "+ExpressionTool.GetOperator(parameter.BaseExpression.NodeType)+" "); + } + else + { + this.Context.Result.Append(result); + } + parameter.CommonTempData = null; + } + + private void ResolveLength(ExpressionParameter parameter, bool? isLeft, MemberExpression expression) + { + if (parameter.Context.ResolveType == ResolveExpressType.FieldSingle) + { + parameter.Context.ResolveType = ResolveExpressType.WhereSingle; + } + if (parameter.Context.ResolveType == ResolveExpressType.FieldMultiple) + { + parameter.Context.ResolveType = ResolveExpressType.WhereMultiple; + } + var oldCommonTempDate = parameter.CommonTempData; + parameter.CommonTempData = CommonTempDataType.Result; + this.Expression = expression.Expression; + var isConst = this.Expression is ConstantExpression; + this.Start(); + var methodParamter = new MethodCallExpressionArgs() { IsMember = !isConst, MemberName = parameter.CommonTempData, MemberValue = null }; + var result = this.Context.DbMehtods.Length(new MethodCallExpressionModel() + { + Args = new List() { + methodParamter + } + }); + base.AppendMember(parameter, isLeft, result); + parameter.CommonTempData = oldCommonTempDate; + } + #endregion + + #region Helper + private string AppendMember(ExpressionParameter parameter, bool? isLeft, string fieldName) + { + if (parameter.BaseExpression is BinaryExpression || (parameter.BaseParameter.CommonTempData != null && parameter.BaseParameter.CommonTempData.Equals(CommonTempDataType.Append))) + { + fieldName = string.Format(" {0} ", fieldName); + if (isLeft == true) + { + fieldName += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (base.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + base.Context.Result.Replace(ExpressionConst.FormatSymbol, fieldName); + } + else + { + base.Context.Result.Append(fieldName); + } + } + else + { + base.Context.Result.Append(fieldName); + } + + return fieldName; + } + + private string GetName(ExpressionParameter parameter, MemberExpression expression, bool? isLeft, bool isSingle) + { + if (isSingle) + { + return GetSingleName(parameter, expression, IsLeft); + } + else + { + return GetMultipleName(parameter, expression, IsLeft); + } + } + + private string GetMultipleName(ExpressionParameter parameter, MemberExpression expression, bool? isLeft) + { + string shortName = expression.Expression.ToString(); + string fieldName = expression.Member.Name; + fieldName = this.Context.GetDbColumnName(expression.Expression.Type.Name, fieldName); + fieldName = Context.GetTranslationColumnName(shortName + UtilConstants.Dot + fieldName); + return fieldName; + } + + private string GetSingleName(ExpressionParameter parameter, MemberExpression expression, bool? isLeft) + { + string fieldName = expression.Member.Name; + fieldName = this.Context.GetDbColumnName(expression.Expression.Type.Name, fieldName); + fieldName = Context.GetTranslationColumnName(fieldName); + return fieldName; + } + + private string GetDateValue(object value, DateType type) + { + var pars = new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { IsMember=true, MemberName=value, MemberValue=value }, + new MethodCallExpressionArgs() { MemberName=type, MemberValue=type} + } + }; + return this.Context.DbMehtods.DateValue(pars); + } + + private string GetToDate(string value) + { + var pars = new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { MemberName=value, MemberValue=value }, + } + }; + return this.Context.DbMehtods.ToDate(pars); + } + + private void SettingParameters(ExpressionParameter parameter, out ExpressionParameter baseParameter, out MemberExpression expression, out bool? isLeft, out bool isSetTempData, out bool isValue, out bool isValueBool, out bool isLength, out bool isDateValue, out bool isHasValue, out bool isDateDate, out bool isMemberValue, out bool isSingle, out bool fieldIsBool, out bool isSelectField, out bool isField) + { + baseParameter = parameter.BaseParameter; + expression = base.Expression as MemberExpression; + var childExpression = expression.Expression as MemberExpression; + var memberName = expression.Member.Name; + var childIsMember = childExpression != null; + var isRoot = parameter.BaseExpression == null; + isLeft = parameter.IsLeft; + isSetTempData = parameter.IsSetTempData; + isValue = memberName == "Value" && expression.Member.DeclaringType.Name == "Nullable`1"; + var isBool = expression.Type == UtilConstants.BoolType; + isValueBool = isValue && isBool && isRoot; + isLength = memberName == "Length" && childIsMember && childExpression.Type == UtilConstants.StringType; + isDateValue = memberName.IsIn(Enum.GetNames(typeof(DateType))) && (childIsMember && childExpression.Type == UtilConstants.DateType); + var isLogicOperator = ExpressionTool.IsLogicOperator(baseParameter.OperatorValue) || baseParameter.OperatorValue.IsNullOrEmpty(); + isHasValue = isLogicOperator && memberName == "HasValue" && expression.Expression != null && expression.NodeType == ExpressionType.MemberAccess; + isDateDate = memberName == "Date" && expression.Expression.Type == UtilConstants.DateType; + isMemberValue = expression.Expression != null && expression.Expression.NodeType != ExpressionType.Parameter && !isValueBool; + isSingle = parameter.Context.ResolveType.IsIn(ResolveExpressType.WhereSingle, ResolveExpressType.SelectSingle, ResolveExpressType.FieldSingle, ResolveExpressType.ArraySingle); + fieldIsBool = isBool && isLogicOperator && (parameter.BaseParameter == null || !(parameter.BaseParameter.CurrentExpression is MemberInitExpression || parameter.BaseParameter.CurrentExpression is NewExpression)); + var isSelect = this.Context.ResolveType.IsIn(ResolveExpressType.SelectSingle, ResolveExpressType.SelectMultiple); + isSelectField = isSelect && isRoot; + isField = this.Context.ResolveType.IsIn(ResolveExpressType.FieldSingle, ResolveExpressType.FieldMultiple); + } + + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs new file mode 100644 index 0000000..241aa90 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs @@ -0,0 +1,251 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MemberInitExpressionResolve : BaseResolve + { + public MemberInitExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as MemberInitExpression; + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + break; + case ResolveExpressType.WhereMultiple: + break; + case ResolveExpressType.SelectSingle: + Select(expression, parameter, true); + break; + case ResolveExpressType.SelectMultiple: + Select(expression, parameter, false); + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + case ResolveExpressType.Update: + Update(expression, parameter); + break; + default: + break; + } + } + + private void Update(MemberInitExpression expression, ExpressionParameter parameter) + { + int i = 0; + foreach (MemberBinding binding in expression.Bindings) + { + ++i; + if (binding.BindingType != MemberBindingType.Assignment) + { + throw new NotSupportedException(); + } + MemberAssignment memberAssignment = (MemberAssignment)binding; + var type = expression.Type; + var memberName = this.Context.GetDbColumnName(type.Name, memberAssignment.Member.Name); + var item = memberAssignment.Expression; + if ((item is MemberExpression) && ((MemberExpression)item).Expression == null) + { + var paramterValue = ExpressionTool.DynamicInvoke(item); + string parameterName = AppendParameter(paramterValue); + this.Context.Result.Append(base.Context.GetEqString(memberName, parameterName)); + } + else if (IsNotMember(item)) + { + if (base.Context.Result.IsLockCurrentParameter == false) + { + base.Context.Result.CurrentParameter = parameter; + base.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + base.Expression = item; + base.Expression = (item as UnaryExpression).Operand; + base.Start(); + parameter.IsAppendResult(); + var result = this.Context.DbMehtods.IIF(new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs(){ IsMember=true, MemberName=parameter.CommonTempData.ObjToString()+"=1" }, + new MethodCallExpressionArgs(){ IsMember=true,MemberName=AppendParameter(0) }, + new MethodCallExpressionArgs(){ IsMember=true, MemberName=AppendParameter(1) } + } + }); + parameter.Context.Result.Append(base.Context.GetEqString(memberName, result)); + base.Context.Result.CurrentParameter = null; + } + } + else if (IsNotParameter(item)) + { + try + { + parameter.Context.Result.Append(base.Context.GetEqString(memberName,AppendParameter(ExpressionTool.DynamicInvoke(item).ObjToBool()))); + } + catch + { + throw new NotSupportedException(item.ToString()); + } + } + else if (IsMethod(item)) + { + if (item is UnaryExpression) + item = (item as UnaryExpression).Operand; + var callMethod = item as MethodCallExpression; + if (MethodTimeMapping.Any(it => it.Key == callMethod.Method.Name) || MethodMapping.Any(it => it.Key == callMethod.Method.Name) || IsExtMethod(callMethod.Method.Name) || IsSubMethod(callMethod) || callMethod.Method.DeclaringType.FullName.StartsWith(UtilConstants.AssemblyName + UtilConstants.Dot)) + { + MethodCall(parameter, memberName, item); + } + else + { + var paramterValue = ExpressionTool.DynamicInvoke(item); + string parameterName = AppendParameter(paramterValue); + this.Context.Result.Append(base.Context.GetEqString(memberName, parameterName)); + } + } + else if (IsConst(item)&&IsConvert(item)&&UtilMethods.IsNullable(item.Type) && UtilMethods.GetUnderType(item.Type)==UtilConstants.BoolType) + { + item = (item as UnaryExpression).Operand; + parameter.Context.Result.Append(base.Context.GetEqString(memberName, GetNewExpressionValue(item))); + } + else if (IsConst(item)) + { + base.Expression = item; + base.Start(); + string parameterName = this.Context.SqlParameterKeyWord + ExpressionConst.Const + this.Context.ParameterIndex; + parameter.Context.Result.Append(base.Context.GetEqString(memberName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); + this.Context.ParameterIndex++; + } + else if (item is MemberExpression) + { + if (base.Context.Result.IsLockCurrentParameter == false) + { + base.Context.Result.CurrentParameter = parameter; + base.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + base.Expression = item; + base.Start(); + parameter.IsAppendResult(); + parameter.Context.Result.Append(base.Context.GetEqString(memberName, parameter.CommonTempData.ObjToString())); + base.Context.Result.CurrentParameter = null; + } + } + else if (item is BinaryExpression) + { + var result = GetNewExpressionValue(item); + this.Context.Result.Append(base.Context.GetEqString(memberName, result)); + } + else if (item is MemberInitExpression) + { + try + { + var value = ExpressionTool.DynamicInvoke(item); + var parameterName = AppendParameter(value); + parameter.Context.Result.Append(base.Context.GetEqString(memberName, parameterName)); + } + catch (Exception ex) + { + throw new NotSupportedException("Not Supported " + item.ToString() + " " + ex.Message); + } + } + else if (item is NewExpression) + { + try + { + var value = ExpressionTool.DynamicInvoke(item); + var parameterName = AppendParameter(value); + parameter.Context.Result.Append(base.Context.GetEqString(memberName, parameterName)); + } + catch (Exception ex) + { + throw new NotSupportedException("Not Supported " + item.ToString() + " " + ex.Message); + } + } + } + } + private static bool IsConst(Expression item) + { + return item is UnaryExpression || item.NodeType == ExpressionType.Constant || (item is MemberExpression) && ((MemberExpression)item).Expression.NodeType == ExpressionType.Constant; + } + + private static bool IsMethod(Expression item) + { + return item is MethodCallExpression || (item is UnaryExpression && (item as UnaryExpression).Operand is MethodCallExpression); + } + + private void MethodCall(ExpressionParameter parameter, string memberName, Expression item) + { + if (IsSubMethod(item as MethodCallExpression)) + { + UtilMethods.GetOldValue(parameter.CommonTempData, () => + { + parameter.CommonTempData = CommonTempDataType.Result; + base.Expression = item; + base.Start(); + var subSql = base.Context.GetEqString(memberName, parameter.CommonTempData.ObjToString()); + if (subSql.Contains(",")) { + subSql = subSql.Replace(",", UtilConstants.ReplaceCommaKey); + } + if (ResolveExpressType.Update == this.Context.ResolveType) + { + string name = this.Context.GetTranslationTableName(parameter.CurrentExpression.Type.Name, true); + if (name.Contains(".")) + { + + } + else + { + subSql = Regex.Replace(subSql, @" \[\w+?\]\.| ""\w+?""\.| \`\w+?\`\.", name + "."); + } + } + parameter.Context.Result.Append(subSql); + }); + } + else + { + base.Expression = item; + base.Start(); + parameter.Context.Result.Append(base.Context.GetEqString(memberName, parameter.CommonTempData.ObjToString().Replace(",", UtilConstants.ReplaceCommaKey))); + } + } + + private void Select(MemberInitExpression expression, ExpressionParameter parameter, bool isSingle) + { + foreach (MemberBinding binding in expression.Bindings) + { + if (binding.BindingType != MemberBindingType.Assignment) + { + throw new NotSupportedException(); + } + MemberAssignment memberAssignment = (MemberAssignment)binding; + var memberName = memberAssignment.Member.Name; + var item = memberAssignment.Expression; + ResolveNewExpressions(parameter, item, memberName); + } + } + + //private bool IsSubMethod(MethodCallExpression express) + //{ + // return SubTools.SubItemsConst.Any(it =>express.Object != null && express.Object.Type.Name == "Subqueryable`1"); + //} + private bool IsExtMethod(string methodName) + { + if (this.Context.SqlFuncServices == null) return false; + return this.Context.SqlFuncServices.Select(it => it.UniqueMethodName).Contains(methodName); + } + private bool CheckMethod(MethodCallExpression expression) + { + if (IsExtMethod(expression.Method.Name)) + return true; + if (expression.Method.ReflectedType().FullName != ExpressionConst.SqlFuncFullName) + return false; + else + return true; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberNewExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberNewExpressionResolve.cs new file mode 100644 index 0000000..22f28c1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberNewExpressionResolve.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MemberNewExpressionResolve : BaseResolve + { + public MemberNewExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as MemberExpression; + var isLeft = parameter.IsLeft; + object value = null; + value = ExpressionTool.DynamicInvoke(expression); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberNoExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberNoExpressionResolve.cs new file mode 100644 index 0000000..2a926d6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MemberNoExpressionResolve.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MemberNoExpressionResolve : BaseResolve + { + public MemberNoExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as MemberExpression; + var isLeft = parameter.IsLeft; + object value = null; + var isField = expression.Member is System.Reflection.FieldInfo; + var isProperty = expression.Member is System.Reflection.PropertyInfo; + var baseParameter = parameter.BaseParameter; + var isSetTempData = baseParameter.CommonTempData.HasValue() && baseParameter.CommonTempData.Equals(CommonTempDataType.Result); + if (isField) + { + value = ExpressionTool.GetFiledValue(expression); + } + else if (isProperty) + { + value = ExpressionTool.GetPropertyValue(expression); + } + switch (base.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + AppendValue(parameter, isLeft, value); + } + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + default: + break; + } + } + } + +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs new file mode 100644 index 0000000..907a58a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs @@ -0,0 +1,777 @@ +using SqlSugar; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class MethodCallExpressionResolve : BaseResolve + { + int contextIndex = 0; + public MethodCallExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + contextIndex = this.Context.Index; + var express = base.Expression as MethodCallExpression; + if (express == null) return; + var isLeft = parameter.IsLeft; + string methodName = express.Method.Name; + var isValidNativeMethod = IsValidNativeMethod(express, methodName); + List appendArgs = null; + if (MethodTimeMapping.ContainsKey(methodName)) + { + appendArgs = new List(); + var dateType = MethodTimeMapping[methodName]; + string paramterName = this.Context.SqlParameterKeyWord + ExpressionConst.Const + this.Context.ParameterIndex; + appendArgs.Add(new MethodCallExpressionArgs() { IsMember = false, MemberName = paramterName, MemberValue = dateType }); + this.Context.Parameters.Add(new SugarParameter(paramterName, dateType.ToString())); + this.Context.ParameterIndex++; + methodName = "DateAdd"; + isValidNativeMethod = true; + } + else if (methodName == "get_Item") + { + string paramterName = this.Context.SqlParameterKeyWord + ExpressionConst.Const + this.Context.ParameterIndex; + this.Context.Parameters.Add(new SugarParameter(paramterName, ExpressionTool.DynamicInvoke(express))); + this.Context.Result.Append(string.Format(" {0} ", paramterName)); + this.Context.ParameterIndex++; + return; + } + else if (methodName == "NewGuid") + { + this.Context.Result.Append(this.Context.DbMehtods.GuidNew()); + return; + } + else if (IsSubMethod(express, methodName)) + { + //Check.Exception(!(parameter.BaseExpression is BinaryExpression), "Current expressions are not supported"); + SubResolve subResolve = new SubResolve(express, this.Context, parameter.OppsiteExpression); + var appendSql = subResolve.GetSql(); + if (this.Context.ResolveType.IsIn(ResolveExpressType.SelectMultiple, ResolveExpressType.SelectSingle) || (parameter.BaseParameter != null && parameter.BaseParameter.CommonTempData != null && parameter.BaseParameter.CommonTempData.Equals(CommonTempDataType.Result))) + { + parameter.BaseParameter.CommonTempData = appendSql; + } + else + { + base.AppendValue(parameter, isLeft, appendSql); + } + return; + } + else if (IsIfElse(express, methodName)) + { + CaseWhenResolve caseResole = new CaseWhenResolve(express, this.Context, parameter.OppsiteExpression); + var appendSql = caseResole.GetSql(); + var isRoot = contextIndex == 2 && parameter.BaseExpression == null; + if (isRoot || (parameter.BaseExpression != null && ExpressionTool.IsLogicOperator(parameter.BaseExpression))) + { + appendSql = appendSql + "=1 "; + } + if (this.Context.ResolveType.IsIn(ResolveExpressType.SelectMultiple, ResolveExpressType.SelectSingle, ResolveExpressType.Update)) + { + parameter.BaseParameter.CommonTempData = appendSql; + } + else + { + base.AppendValue(parameter, isLeft, appendSql); + } + return; + } + if (IsContainsArray(express, methodName, isValidNativeMethod)) + { + methodName = "ContainsArray"; + isValidNativeMethod = true; + } + if (isValidNativeMethod) + { + NativeExtensionMethod(parameter, express, isLeft, MethodMapping[methodName], appendArgs); + } + else + { + SqlFuncMethod(parameter, express, isLeft); + } + } + + private bool IsValidNativeMethod(MethodCallExpression express, string methodName) + { + return MethodMapping.ContainsKey(methodName) && express.Method.DeclaringType.Namespace == ("System"); + } + + private bool IsExtMethod(string methodName) + { + if (this.Context.SqlFuncServices == null) return false; + return this.Context.SqlFuncServices.Select(it => it.UniqueMethodName).Contains(methodName); + } + + private bool IsIfElse(MethodCallExpression express, string methodName) + { + if (methodName == "End" && express.Object.Type == typeof(CaseWhen)) + return true; + else + return false; + } + + protected void SqlFuncMethod(ExpressionParameter parameter, MethodCallExpression express, bool? isLeft) + { + if (!CheckMethod(express)) + { + CusMethod(parameter, express, isLeft); + } + else + { + var method = express.Method; + string name = method.Name; + var args = express.Arguments.Cast().ToList(); + MethodCallExpressionModel model = new MethodCallExpressionModel(); + model.Args = new List(); + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + Check.Exception(name == "GetSelfAndAutoFill", "SqlFunc.GetSelfAndAutoFill can only be used in Select."); + Where(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + Select(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + Field(parameter, isLeft, name, args, model); + break; + default: + break; + } + } + } + + private void CusMethod(ExpressionParameter parameter, MethodCallExpression express, bool? isLeft) + { + try + { + var constValue = ExpressionTool.DynamicInvoke(express); + parameter.BaseParameter.CommonTempData = constValue; + var parameterName = base.AppendParameter(constValue); + if (parameter.BaseParameter.CommonTempData != null && parameter.BaseParameter.CommonTempData.Equals(CommonTempDataType.Result)) + { + this.Context.Result.Append(parameterName); + } + else + { + base.AppendValue(parameter, isLeft, parameterName); + } + } + catch + { + Check.Exception(true, string.Format(ErrorMessage.MethodError, express.Method.Name)); + } + } + + private void NativeExtensionMethod(ExpressionParameter parameter, MethodCallExpression express, bool? isLeft, string name, List appendArgs = null) + { + var method = express.Method; + var args = express.Arguments.Cast().ToList(); + MethodCallExpressionModel model = new MethodCallExpressionModel(); + model.Name = name; + model.Args = new List(); + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + if (express.Object != null) + args.Insert(0, express.Object); + Where(parameter, isLeft, name, args, model, appendArgs); + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + if (express.Object != null) + args.Insert(0, express.Object); + Select(parameter, isLeft, name, args, model, appendArgs); + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + default: + break; + } + } + + protected void Field(ExpressionParameter parameter, bool? isLeft, string name, IEnumerable args, MethodCallExpressionModel model, List appendArgs = null) + { + if (this.Context.ResolveType == ResolveExpressType.FieldSingle) + { + this.Context.ResolveType = ResolveExpressType.WhereSingle; + } + else + { + this.Context.ResolveType = ResolveExpressType.WhereMultiple; + } + Where(parameter, isLeft, name, args, model); + } + protected void Select(ExpressionParameter parameter, bool? isLeft, string name, IEnumerable args, MethodCallExpressionModel model, List appendArgs = null) + { + if (name == "GetSelfAndAutoFill") + { + var memberValue = (args.First() as MemberExpression).Expression.ToString(); + model.Args.Add(new MethodCallExpressionArgs() { MemberValue = memberValue, IsMember = true, MemberName = memberValue }); + } + else + { + foreach (var item in args) + { + AppendItem(parameter, name, args, model, item); + } + if (appendArgs != null) + { + model.Args.AddRange(appendArgs); + } + } + if (parameter.BaseParameter.BaseParameter.BaseParameter == null) + { + this.Context.Result.Append(GetMethodValue(name, model)); + } + else + { + parameter.BaseParameter.CommonTempData = GetMethodValue(name, model); + } + } + protected void Where(ExpressionParameter parameter, bool? isLeft, string name, IEnumerable args, MethodCallExpressionModel model, List appendArgs = null) + { + foreach (var item in args) + { + var expItem = item; + if (item is UnaryExpression) + { + expItem = (item as UnaryExpression).Operand; + } + AppendItem(parameter, name, args, model, expItem); + } + if (appendArgs != null) + { + model.Args.AddRange(appendArgs); + } + var methodValue = GetMethodValue(name, model); + if (parameter.BaseExpression is BinaryExpression && parameter.OppsiteExpression.Type == UtilConstants.BoolType && name == "HasValue" && !(parameter.OppsiteExpression is BinaryExpression) && !(parameter.OppsiteExpression is MethodCallExpression && parameter.OppsiteExpression.Type == UtilConstants.BoolType)) + { + methodValue = packIfElse(methodValue); + } + if (parameter.OppsiteExpression != null && name == "IsNullOrEmpty" && parameter.OppsiteExpression.Type == UtilConstants.BoolType && parameter.OppsiteExpression is ConstantExpression) + { + methodValue = packIfElse(methodValue); + } + var isRoot = contextIndex == 2; + if (isRoot && parameter.BaseExpression == null && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is MethodCallExpression) && ((parameter.CurrentExpression as MethodCallExpression).Method.Name.IsIn("ToBool", "ToBoolean"))) + { + methodValue = methodValue + "=1 "; + ; + } + if (isRoot && parameter.BaseExpression == null && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is ConditionalExpression) && ((parameter.CurrentExpression as ConditionalExpression).Type == UtilConstants.BoolType)) + { + methodValue = methodValue + "=1 "; + } + if (isRoot && parameter.BaseExpression == null && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is MethodCallExpression) && ((parameter.CurrentExpression as MethodCallExpression).Method.Name.IsIn("IIF")) && (parameter.CurrentExpression as MethodCallExpression).Method.ReturnType == UtilConstants.BoolType) + { + methodValue = methodValue + "=1 "; + } + if (parameter.BaseExpression != null && ExpressionTool.IsLogicOperator(parameter.BaseExpression) && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is ConditionalExpression) && ((parameter.CurrentExpression as ConditionalExpression).Type == UtilConstants.BoolType)) + { + methodValue = methodValue + "=1 "; + } + if (parameter.BaseExpression != null && ExpressionTool.IsLogicOperator(parameter.BaseExpression) && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is MethodCallExpression) && ((parameter.CurrentExpression as MethodCallExpression).Method.Name.IsIn("IIF")) && (parameter.CurrentExpression as MethodCallExpression).Method.ReturnType == UtilConstants.BoolType) + { + methodValue = methodValue + "=1 "; + } + if (parameter.BaseExpression != null && ExpressionTool.IsLogicOperator(parameter.BaseExpression) && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is MethodCallExpression) && ((parameter.CurrentExpression as MethodCallExpression).Method.Name.IsIn("ToBool", "ToBoolean"))) + { + methodValue = methodValue + "=1 "; + } + base.AppendValue(parameter, isLeft, methodValue); + } + + private object packIfElse(object methodValue) + { + methodValue = this.Context.DbMehtods.CaseWhen(new List>() { + new KeyValuePair("IF",methodValue.ObjToString()), + new KeyValuePair("Return","1"), + new KeyValuePair("End","0") + }); + return methodValue; + } + + private void AppendItem(ExpressionParameter parameter, string name, IEnumerable args, MethodCallExpressionModel model, Expression item) + { + if (ExpressionTool.IsUnConvertExpress(item)) + { + item = (item as UnaryExpression).Operand; + } + var isBinaryExpression = item is BinaryExpression || item is MethodCallExpression; + var isConst = item is ConstantExpression; + var isIIF = name == "IIF"; + var isIFFBoolMember = isIIF && (item is MemberExpression) && (item as MemberExpression).Type == UtilConstants.BoolType; + var isIFFUnary = isIIF && (item is UnaryExpression) && (item as UnaryExpression).Operand.Type == UtilConstants.BoolType; + var isIFFBoolBinary = isIIF && (item is BinaryExpression) && (item as BinaryExpression).Type == UtilConstants.BoolType; + var isIFFBoolMethod = isIIF && (item is MethodCallExpression) && (item as MethodCallExpression).Type == UtilConstants.BoolType; + var isFirst = item == args.First(); + if (isFirst && isIIF && isConst) + { + var value = (item as ConstantExpression).Value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False(); + var methodCallExpressionArgs = new MethodCallExpressionArgs() + { + IsMember = true, + MemberName = value, + MemberValue = value + }; + model.Args.Add(methodCallExpressionArgs); + } + else if (isIFFUnary && !isFirst) + { + AppendModelByIIFMember(parameter, model, (item as UnaryExpression).Operand); + } + else if (isIFFBoolMember && !isFirst) + { + AppendModelByIIFMember(parameter, model, item); + + } + else if (isIFFBoolBinary && !isFirst) + { + AppendModelByIIFBinary(parameter, model, item); + + } + else if (isIFFBoolMethod && !isFirst) + { + AppendModelByIIFMethod(parameter, model, item); + } + else if (isBinaryExpression) + { + model.Args.Add(GetMethodCallArgs(parameter, item)); + } + else + { + AppendModel(parameter, model, item); + } + } + + + private void AppendModelByIIFMember(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) + { + parameter.CommonTempData = CommonTempDataType.Result; + base.Expression = item; + base.Start(); + var methodCallExpressionArgs = new MethodCallExpressionArgs() + { + IsMember = parameter.ChildExpression is MemberExpression, + MemberName = parameter.CommonTempData + }; + if (methodCallExpressionArgs.IsMember && parameter.ChildExpression != null && parameter.ChildExpression.ToString() == "DateTime.Now") + { + methodCallExpressionArgs.IsMember = false; + } + var value = methodCallExpressionArgs.MemberName; + if (methodCallExpressionArgs.IsMember) + { + var childExpression = parameter.ChildExpression as MemberExpression; + if (childExpression.Expression != null && childExpression.Expression is ConstantExpression) + { + methodCallExpressionArgs.IsMember = false; + } + } + if (methodCallExpressionArgs.IsMember == false) + { + var parameterName = this.Context.SqlParameterKeyWord + ExpressionConst.MethodConst + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + methodCallExpressionArgs.MemberName = parameterName; + methodCallExpressionArgs.MemberValue = value; + this.Context.Parameters.Add(new SugarParameter(parameterName, value)); + } + model.Args.Add(methodCallExpressionArgs); + parameter.ChildExpression = null; + } + private void AppendModelByIIFBinary(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) + { + Check.Exception(true, "The SqlFunc.IIF(arg1,arg2,arg3) , {0} argument do not support ", item.ToString()); + } + private void AppendModelByIIFMethod(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) + { + var methodExpression = item as MethodCallExpression; + if (methodExpression.Method.Name.IsIn("ToBool", "ToBoolean", "IIF")) + { + model.Args.Add(base.GetMethodCallArgs(parameter, item)); + } + else + { + Check.Exception(true, "The SqlFunc.IIF(arg1,arg2,arg3) , {0} argument do not support ", item.ToString()); + } + } + private void AppendModel(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) + { + parameter.CommonTempData = CommonTempDataType.Result; + base.Expression = item; + if (item.Type == UtilConstants.DateType && parameter.CommonTempData.ObjToString() == CommonTempDataType.Result.ToString() && item.ToString() == "DateTime.Now.Date") + { + parameter.CommonTempData = DateTime.Now.Date; + } + else if (IsDateDate(item)) + { + parameter.CommonTempData = GetNewExpressionValue(item); + } + else if (IsDateValue(item)) + { + parameter.CommonTempData = GetNewExpressionValue(item); + } + else if (model.Name == "ToString" && item is ConstantExpression && (item as ConstantExpression).Type.IsEnum()) + { + parameter.CommonTempData = item.ToString(); + } + else + { + base.Start(); + } + var methodCallExpressionArgs = new MethodCallExpressionArgs() + { + IsMember = parameter.ChildExpression is MemberExpression && !ExpressionTool.IsConstExpression(parameter.ChildExpression as MemberExpression), + MemberName = parameter.CommonTempData + }; + if (methodCallExpressionArgs.IsMember && parameter.ChildExpression != null && parameter.ChildExpression.ToString() == "DateTime.Now") + { + methodCallExpressionArgs.IsMember = false; + } + var value = methodCallExpressionArgs.MemberName; + if (methodCallExpressionArgs.IsMember) + { + var childExpression = parameter.ChildExpression as MemberExpression; + if (childExpression.Expression != null && childExpression.Expression is ConstantExpression) + { + methodCallExpressionArgs.IsMember = false; + } + } + if (IsDateDate(item)||IsDateValue(item)) + { + methodCallExpressionArgs.IsMember = true; + } + if (methodCallExpressionArgs.IsMember == false && (item is MethodCallExpression && item.ToString() == "GetDate()") || (item is UnaryExpression && ((UnaryExpression)item).Operand.ToString() == "GetDate()")) + { + var parameterName = this.Context.SqlParameterKeyWord + ExpressionConst.MethodConst + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + methodCallExpressionArgs.MemberName = value; + methodCallExpressionArgs.MemberValue = null; + } + else if (methodCallExpressionArgs.IsMember == false) + { + var parameterName = this.Context.SqlParameterKeyWord + ExpressionConst.MethodConst + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + methodCallExpressionArgs.MemberName = parameterName; + methodCallExpressionArgs.MemberValue = value; + this.Context.Parameters.Add(new SugarParameter(parameterName, value)); + } + model.Args.Add(methodCallExpressionArgs); + parameter.ChildExpression = null; + } + + private static bool IsDateDate(Expression item) + { + return item.Type == UtilConstants.DateType && item is MemberExpression && (item as MemberExpression).Member.Name == "Date"&&item.ToString()!= "DateTime.Now.Date"; + } + private static bool IsDateValue(Expression item) + { + return item.Type == UtilConstants.IntType && + item is MemberExpression && + (item as MemberExpression).Expression!=null&& + (item as MemberExpression).Expression.Type==UtilConstants.DateType&& + (item as MemberExpression).Expression is MemberExpression&& + ((item as MemberExpression).Expression as MemberExpression).Member.Name=="Value"; + } + + private object GetMethodValue(string name, MethodCallExpressionModel model) + { + if (IsExtMethod(name)) + { + DbType type = DbType.SqlServer; + if (this.Context is SqlServerExpressionContext) + type = DbType.SqlServer; + else if (this.Context is MySqlExpressionContext) + type = DbType.MySql; + else if (this.Context is SqliteExpressionContext) + type = DbType.Sqlite; + else if (this.Context is OracleExpressionContext) + type = DbType.Oracle; + return this.Context.SqlFuncServices.First(it => it.UniqueMethodName == name).MethodValue(model, type, this.Context); + } + else + { + if (name == "Parse" && TempParseType.IsIn(UtilConstants.GuidType)) + { + name = "Equals"; + } + else if (name == "Parse") + { + name = "To" + TempParseType.Name; + } + switch (name) + { + case "IIF": + return this.Context.DbMehtods.IIF(model); + case "HasNumber": + return this.Context.DbMehtods.HasNumber(model); + case "HasValue": + return this.Context.DbMehtods.HasValue(model); + case "IsNullOrEmpty": + return this.Context.DbMehtods.IsNullOrEmpty(model); + case "ToLower": + return this.Context.DbMehtods.ToLower(model); + case "ToUpper": + return this.Context.DbMehtods.ToUpper(model); + case "Trim": + return this.Context.DbMehtods.Trim(model); + case "Contains": + return this.Context.DbMehtods.Contains(model); + case "ContainsArray": + if (model.Args[0].MemberValue == null) + { + var first = this.Context.Parameters.FirstOrDefault(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); + if (first.HasValue()) + { + model.Args[0].MemberValue = first.Value; + } + } + var caResult = this.Context.DbMehtods.ContainsArray(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); + return caResult; + case "ContainsArrayUseSqlParameters": + if (model.Args[0].MemberValue == null) + { + var first = this.Context.Parameters.FirstOrDefault(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); + if (first.HasValue()) + { + model.Args[0].MemberValue = first.Value; + } + } + model.Data =this.Context.SqlParameterKeyWord+"INP_"+this.Context.ParameterIndex; + this.Context.ParameterIndex++; + if (model.Args[0].MemberValue.HasValue()) + { + var inValueIEnumerable = (IEnumerable)model.Args[0].MemberValue; + int i = 0; + foreach (var item in inValueIEnumerable) + { + this.Context.Parameters.Add(new SugarParameter(model.Data+"_"+i,item)); + i++; + } + } + var caResult2 = this.Context.DbMehtods.ContainsArrayUseSqlParameters(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); + return caResult2; + case "Equals": + return this.Context.DbMehtods.Equals(model); + case "DateIsSame": + if (model.Args.Count == 2) + return this.Context.DbMehtods.DateIsSameDay(model); + else + { + var dsResult = this.Context.DbMehtods.DateIsSameByType(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[2].MemberName.ObjToString()); + return dsResult; + } + case "DateAdd": + if (model.Args.Count == 2) + return this.Context.DbMehtods.DateAddDay(model); + else + { + var daResult = this.Context.DbMehtods.DateAddByType(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[2].MemberName.ObjToString()); + return daResult; + } + case "DateValue": + var dvResult = this.Context.DbMehtods.DateValue(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[1].MemberName.ObjToString()); + return dvResult; + case "Between": + return this.Context.DbMehtods.Between(model); + case "StartsWith": + return this.Context.DbMehtods.StartsWith(model); + case "EndsWith": + return this.Context.DbMehtods.EndsWith(model); + case "ToInt32": + return this.Context.DbMehtods.ToInt32(model); + case "ToInt64": + return this.Context.DbMehtods.ToInt64(model); + case "ToDate": + return this.Context.DbMehtods.ToDate(model); + case "ToDateTime": + return this.Context.DbMehtods.ToDate(model); + case "ToTime": + return this.Context.DbMehtods.ToTime(model); + case "ToString": + if (model.Args.Count > 1 && model.Args.Last().MemberValue.ObjToString().IsContainsIn("-", "/", ":", "yy", "ms", "hh")) + { + return GeDateFormat(model.Args.Last().MemberValue.ObjToString(), model.Args.First().MemberName.ObjToString()); + } + Check.Exception(model.Args.Count > 1, "ToString (Format) is not supported, Use ToString().If time formatting can be used it.Date.Year+\"-\"+it.Data.Month+\"-\"+it.Date.Day "); + return this.Context.DbMehtods.ToString(model); + case "ToDecimal": + return this.Context.DbMehtods.ToDecimal(model); + case "ToGuid": + return this.Context.DbMehtods.ToGuid(model); + case "ToDouble": + return this.Context.DbMehtods.ToDouble(model); + case "ToBool": + return this.Context.DbMehtods.ToBool(model); + case "ToBoolean": + return this.Context.DbMehtods.ToBool(model); + case "Substring": + return this.Context.DbMehtods.Substring(model); + case "Replace": + return this.Context.DbMehtods.Replace(model); + case "Length": + return this.Context.DbMehtods.Length(model); + case "AggregateSum": + return this.Context.DbMehtods.AggregateSum(model); + case "AggregateAvg": + return this.Context.DbMehtods.AggregateAvg(model); + case "AggregateMin": + return this.Context.DbMehtods.AggregateMin(model); + case "AggregateMax": + return this.Context.DbMehtods.AggregateMax(model); + case "AggregateCount": + return this.Context.DbMehtods.AggregateCount(model); + case "AggregateDistinctCount": + return this.Context.DbMehtods.AggregateDistinctCount(model); + case "MappingColumn": + var mappingColumnResult = this.Context.DbMehtods.MappingColumn(model); + var isValid = model.Args[0].IsMember && model.Args[1].IsMember == false; + Check.Exception(!isValid, "SqlFunc.MappingColumn parameters error, The property name on the left, string value on the right"); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[1].MemberName.ObjToString()); + return mappingColumnResult; + case "IsNull": + return this.Context.DbMehtods.IsNull(model); + case "MergeString": + return this.Context.DbMehtods.MergeString(model.Args.Select(it => it.MemberName.ObjToString()).ToArray()); + case "GetSelfAndAutoFill": + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); + return this.Context.DbMehtods.GetSelfAndAutoFill(model.Args[0].MemberValue.ObjToString(), this.Context.IsSingle); + case "GetDate": + return this.Context.DbMehtods.GetDate(); + case "GetRandom": + return this.Context.DbMehtods.GetRandom(); + case "CharIndex": + return this.Context.DbMehtods.CharIndex(model); + default: + break; + } + } + return null; + } + + private bool IsContainsArray(MethodCallExpression express, string methodName, bool isValidNativeMethod) + { + return !isValidNativeMethod && express.Method.DeclaringType.Namespace.IsIn("System.Linq", "System.Collections.Generic") && methodName == "Contains"; + } + + private bool IsSubMethod(MethodCallExpression express, string methodName) + { + return SubTools.SubItemsConst.Any(it => it.Name == methodName) && express.Object != null && express.Object.Type.Name == "Subqueryable`1"; + } + private bool CheckMethod(MethodCallExpression expression) + { + if (IsExtMethod(expression.Method.Name)) + return true; + if (IsParseMethod(expression)) + return true; + if (expression.Method.Name == "IsNullOrEmpty" && expression.Method.DeclaringType == UtilConstants.StringType) + { + return true; + } + if (expression.Method.ReflectedType().FullName != ExpressionConst.SqlFuncFullName) + return false; + else + return true; + } + private Type TempParseType; + public bool IsParseMethod(MethodCallExpression expression) + { + if (expression.Method.Name == "Parse" && expression.Method.DeclaringType.IsIn( + UtilConstants.DecType, + UtilConstants.DateType, + UtilConstants.DobType, + UtilConstants.GuidType, + UtilConstants.FloatType, + UtilConstants.ShortType, + UtilConstants.LongType, + UtilConstants.IntType, + UtilConstants.BoolType)) + { + TempParseType = expression.Method.DeclaringType; + return true; + } + return false; + } + + + public string GeDateFormat(string formatString, string value) + { + var parameter = new MethodCallExpressionArgs() { IsMember = true, MemberValue = DateType.Year }; + var parameter2 = new MethodCallExpressionArgs() { IsMember = true, MemberName = value }; + var parameters = new MethodCallExpressionModel() { Args = new List() { parameter2, parameter } }; + var begin = @"^"; + var end = @"$"; + formatString = formatString.Replace("yyyy", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + formatString = formatString.Replace("yy", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + + parameters.Args.Last().MemberValue = DateType.Month; + formatString = formatString.Replace("MM", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + formatString = formatString.Replace("M", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + + parameters.Args.Last().MemberValue = DateType.Day; + formatString = formatString.Replace("dd", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + formatString = formatString.Replace("d", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + + parameters.Args.Last().MemberValue = DateType.Hour; + formatString = Regex.Replace(formatString, "hh", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end, RegexOptions.IgnoreCase); + formatString = Regex.Replace(formatString, "h", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end, RegexOptions.IgnoreCase); + + parameters.Args.Last().MemberValue = DateType.Minute; + formatString = formatString.Replace("mm", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + formatString = formatString.Replace("m", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + + parameters.Args.Last().MemberValue = DateType.Second; + formatString = formatString.Replace("ss", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + formatString = formatString.Replace("s", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + + parameters.Args.Last().MemberValue = DateType.Millisecond; + formatString = formatString.Replace("ms", begin + UtilMethods.ConvertStringToNumbers(this.GetMethodValue("DateValue", parameters).ObjToString()) + end); + var items = Regex.Matches(formatString, @"\^\d+\$").Cast().ToList(); + foreach (var item in items) + { + formatString = formatString.Replace(item.Value, "$@" + UtilMethods.ConvertNumbersToString(item.Value.TrimStart('^').TrimEnd('$')) + "$"); + } + var strings = formatString.TrimStart('$').TrimEnd('$').Split('$'); + var joinStringParameter = new MethodCallExpressionModel() + { + Args = new List() + }; + foreach (var r in strings) + { + if (r.Substring(0, 1) == "@") + { + joinStringParameter.Args.Add(new MethodCallExpressionArgs() + { + MemberName=r.TrimStart('@') + }); + } + else + { + + var name = base.AppendParameter(r); + joinStringParameter.Args.Add(new MethodCallExpressionArgs() + { + MemberName= name + }); + } + } + return this.GetMethodValue("MergeString", joinStringParameter).ObjToString(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/NewArrayExpessionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/NewArrayExpessionResolve.cs new file mode 100644 index 0000000..2ad08a9 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/NewArrayExpessionResolve.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class NewArrayExpessionResolve : BaseResolve + { + public NewArrayExpessionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = (NewArrayExpression)base.Expression; + switch (base.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + try + { + var value = ExpressionTool.DynamicInvoke(expression); + var isLeft = parameter.IsLeft; + var baseParameter = parameter.BaseParameter; + var isSetTempData = baseParameter.CommonTempData.HasValue() && baseParameter.CommonTempData.Equals(CommonTempDataType.Result); + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + var parentIsBinary = parameter.BaseParameter.CurrentExpression is BinaryExpression; + var parentIsRoot = parameter.BaseParameter.CurrentExpression is LambdaExpression; + var isBool = value != null && value.GetType() == UtilConstants.BoolType; + if (parentIsRoot && isBool) + { + this.Context.Result.Append(value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False()); + break; + } + if (parentIsBinary && isBool) + { + var isLogicOperator = + parameter.BaseExpression.NodeType == ExpressionType.And || + parameter.BaseExpression.NodeType == ExpressionType.AndAlso || + parameter.BaseExpression.NodeType == ExpressionType.Or || + parameter.BaseExpression.NodeType == ExpressionType.OrElse; + if (isLogicOperator) + { + AppendMember(parameter, isLeft, (value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False())); + break; + } + } + if (value == null && parentIsBinary) + { + parameter.BaseParameter.ValueIsNull = true; + value = this.Context.DbMehtods.Null(); + } + AppendValue(parameter, isLeft, value); + } + } + catch (Exception) + { + Check.ThrowNotSupportedException("NewArrayExpression"); + } + break; + case ResolveExpressType.ArraySingle: + foreach (var item in expression.Expressions) + { + base.Expression = item; + base.Start(); + } + break; + case ResolveExpressType.Join: + base.Context.ResolveType = ResolveExpressType.WhereMultiple; + int i = 0; + foreach (var item in expression.Expressions) + { + if (item is UnaryExpression) + { + base.Expression = item; + base.Start(); + if (parameter.CommonTempData is JoinType) + { + if (i > 0) + { + base.Context.Result.Append("," + parameter.CommonTempData.ObjToString().Replace(",",UtilConstants.ReplaceCommaKey) + ","); + } + else + { + base.Context.Result.Append(parameter.CommonTempData.ObjToString().Replace(",", UtilConstants.ReplaceCommaKey) + ","); + } + ++i; + } + } + } + break; + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs new file mode 100644 index 0000000..0bc23c8 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class NewExpressionResolve : BaseResolve + { + public NewExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as NewExpression; + if (expression.Type.IsIn(UtilConstants.DateType,UtilConstants.GuidType)) + { + NewValueType(parameter, expression); + return; + } + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + Check.ThrowNotSupportedException(expression.ToString()); + break; + case ResolveExpressType.WhereMultiple: + Check.ThrowNotSupportedException(expression.ToString()); + break; + case ResolveExpressType.SelectSingle: + Check.Exception(expression.Type == UtilConstants.DateType, "ThrowNotSupportedException {0} ", expression.ToString()); + Select(expression, parameter, true); + break; + case ResolveExpressType.SelectMultiple: + Check.Exception(expression.Type == UtilConstants.DateType, "ThrowNotSupportedException {0} ", expression.ToString()); + Select(expression, parameter, false); + break; + case ResolveExpressType.FieldSingle: + Check.ThrowNotSupportedException(expression.ToString()); + break; + case ResolveExpressType.FieldMultiple: + case ResolveExpressType.ArrayMultiple: + case ResolveExpressType.ArraySingle: + foreach (var item in expression.Arguments) + { + base.Expression = item; + base.Start(); + } + break; + case ResolveExpressType.Join: + base.Context.ResolveType = ResolveExpressType.WhereMultiple; + int i = 0; + foreach (var item in expression.Arguments) + { + if (item.Type!=typeof(JoinType)) + { + base.Expression = item; + base.Start(); + } + if (item.Type == typeof(JoinType)) + { + if (i > 0) + { + base.Context.Result.Append("," + item.ToString()+ ","); + } + else + { + base.Context.Result.Append(item.ToString() + ","); + } + ++i; + } + } + break; + default: + break; + } + } + + private void NewValueType(ExpressionParameter parameter, NewExpression expression) + { + try + { + var value = ExpressionTool.DynamicInvoke(expression); + var isSetTempData = parameter.CommonTempData.HasValue() && parameter.CommonTempData.Equals(CommonTempDataType.Result); + if (isSetTempData) + { + parameter.CommonTempData = value; + } + else + { + AppendValue(parameter, parameter.IsLeft, value); + } + } + catch (Exception ex) + { + Check.Exception(expression.Type == UtilConstants.DateType, "ThrowNotSupportedException {0} ", ex.ToString()); + } + } + + private void Select(NewExpression expression, ExpressionParameter parameter, bool isSingle) + { + if (expression.Arguments != null) + { + int i = 0; + foreach (var item in expression.Arguments) + { + string memberName = expression.Members[i].Name; + ++i; + ResolveNewExpressions(parameter, item, memberName); + } + } + } + } +} + diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/TypeParameterExpressionReolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/TypeParameterExpressionReolve.cs new file mode 100644 index 0000000..0572476 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/TypeParameterExpressionReolve.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class TypeParameterExpressionReolve : BaseResolve + { + public TypeParameterExpressionReolve(ExpressionParameter parameter) : base(parameter) + { + var expression = (ParameterExpression)base.Expression; + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + break; + case ResolveExpressType.WhereMultiple: + break; + case ResolveExpressType.Update: + parameter.BaseParameter.CommonTempData = expression.Name; + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + if (parameter.BaseParameter!=null&¶meter.BaseParameter.CurrentExpression.NodeType == ExpressionType.Lambda) + { + this.Context.Result.Append(expression.Name + ".*"); + } + else + { + parameter.BaseParameter.CommonTempData = expression.Name; + } + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + case ResolveExpressType.Join: + break; + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/UnaryExpressionResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/UnaryExpressionResolve.cs new file mode 100644 index 0000000..7f9c41d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/ResolveItems/UnaryExpressionResolve.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class UnaryExpressionResolve : BaseResolve + { + public UnaryExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var oldExpression = base.Expression; + var expression = base.Expression as UnaryExpression; + var baseParameter = parameter.BaseParameter; + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.ArraySingle: + case ResolveExpressType.ArrayMultiple: + case ResolveExpressType.Update: + var nodeType = expression.NodeType; + base.Expression = expression.Operand; + var isMember = expression.Operand is MemberExpression; + var isConst = expression.Operand is ConstantExpression; + var offsetIsNull = (parameter.OppsiteExpression is ConstantExpression) + &&(parameter.OppsiteExpression as ConstantExpression).Value==null + &&ExpressionTool.IsComparisonOperator(expression.Operand); + if (isMember && offsetIsNull) { + Append(parameter, nodeType); + } + else if (baseParameter.CurrentExpression is NewArrayExpression) + { + Result(parameter, nodeType); + } + else if (baseParameter.OperatorValue == "=" &&IsNotMember(oldExpression)) + { + AppendNotMember(parameter,nodeType); + } + else if (baseParameter.OperatorValue == "=" && IsNotParameter(oldExpression)) + { + AppendNotParameter(parameter, nodeType); + } + else if (base.Expression is BinaryExpression || parameter.BaseExpression is BinaryExpression || baseParameter.CommonTempData.ObjToString() == CommonTempDataType.Append.ToString()) + { + Append(parameter, nodeType); + } + else if (isMember) + { + MemberLogic(parameter, baseParameter, nodeType); + } + else if (isConst) + { + Result(parameter, nodeType); + } + else + { + Append(parameter, nodeType); + } + break; + default: + break; + } + } + + private void MemberLogic(ExpressionParameter parameter, ExpressionParameter baseParameter, ExpressionType nodeType) + { + var memberExpression = (base.Expression as MemberExpression); + var isLogicOperator = ExpressionTool.IsLogicOperator(baseParameter.OperatorValue) || baseParameter.OperatorValue.IsNullOrEmpty(); + var isHasValue = isLogicOperator && memberExpression.Member.Name == "HasValue" && memberExpression.Expression != null && memberExpression.NodeType == ExpressionType.MemberAccess; + if (isHasValue) + { + var member = memberExpression.Expression as MemberExpression; + parameter.CommonTempData = CommonTempDataType.Result; + var isConst = member.Expression != null && member.Expression is ConstantExpression; + if (isConst) + { + var paramterValue = ExpressionTool.DynamicInvoke(member); + var paramterName= base.AppendParameter(paramterValue); + var result = this.Context.DbMehtods.HasValue(new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { IsMember=false, MemberName=paramterName, MemberValue=paramterValue } } + }); + this.Context.Result.Append(result); + } + else + { + this.Expression = isConst ? member.Expression : member; + this.Start(); + var methodParamter = isConst ? new MethodCallExpressionArgs() { IsMember = false } : new MethodCallExpressionArgs() { IsMember = true, MemberName = parameter.CommonTempData, MemberValue = null }; + var result = this.Context.DbMehtods.HasValue(new MethodCallExpressionModel() + { + Args = new List() { + methodParamter + } + }); + this.Context.Result.Append(result); + parameter.CommonTempData = null; + } + } + else if (memberExpression.Type == UtilConstants.BoolType && isLogicOperator) + { + Append(parameter, nodeType); + } + else + { + Result(parameter, nodeType); + } + } + + private void Result(ExpressionParameter parameter, ExpressionType nodeType) + { + BaseParameter.ChildExpression = base.Expression; + parameter.CommonTempData = CommonTempDataType.Result; + if (nodeType == ExpressionType.Not) + AppendNot(parameter.CommonTempData); + base.Start(); + parameter.BaseParameter.CommonTempData = parameter.CommonTempData; + parameter.BaseParameter.ChildExpression = base.Expression; + parameter.CommonTempData = null; + } + + private void Append(ExpressionParameter parameter, ExpressionType nodeType) + { + BaseParameter.ChildExpression = base.Expression; + this.IsLeft = parameter.IsLeft; + parameter.CommonTempData = CommonTempDataType.Append; + if (nodeType == ExpressionType.Not) + AppendNot(parameter.CommonTempData); + if (nodeType == ExpressionType.Negate) + AppendNegate(parameter.CommonTempData); + base.Start(); + parameter.BaseParameter.CommonTempData = parameter.CommonTempData; + parameter.BaseParameter.ChildExpression = base.Expression; + parameter.CommonTempData = null; + } + + + private void AppendNotMember(ExpressionParameter parameter, ExpressionType nodeType) + { + BaseParameter.ChildExpression = base.Expression; + this.IsLeft = parameter.IsLeft; + parameter.CommonTempData = CommonTempDataType.Result; + base.Start(); + var result= this.Context.DbMehtods.IIF(new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs(){ IsMember=true, MemberName=parameter.CommonTempData.ObjToString()+"=1" }, + new MethodCallExpressionArgs(){ IsMember=true,MemberName=AppendParameter(0) }, + new MethodCallExpressionArgs(){ IsMember=true, MemberName=AppendParameter(1) } + } + }); + this.Context.Result.Append(result); + parameter.BaseParameter.ChildExpression = base.Expression; + parameter.CommonTempData = null; + } + + + private void AppendNotParameter(ExpressionParameter parameter, ExpressionType nodeType) + { + BaseParameter.ChildExpression = base.Expression; + this.IsLeft = parameter.IsLeft; + parameter.CommonTempData = CommonTempDataType.Result; + base.Start(); + var result = this.Context.DbMehtods.IIF(new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs(){ IsMember=true, MemberName=AppendParameter(parameter.CommonTempData)+"=1" }, + new MethodCallExpressionArgs(){ IsMember=true,MemberName=AppendParameter(0) }, + new MethodCallExpressionArgs(){ IsMember=true, MemberName=AppendParameter(1) } + } + }); + this.Context.Result.Append(result); + parameter.BaseParameter.ChildExpression = base.Expression; + parameter.CommonTempData = null; + } + + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/ISubOperation.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/ISubOperation.cs new file mode 100644 index 0000000..432f67b --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/ISubOperation.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public interface ISubOperation + { + ExpressionContext Context { get; set; } + string Name { get; } + string GetValue(Expression expression); + int Sort { get; } + Expression Expression { get; set; } + bool HasWhere { get; set; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAnd.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAnd.cs new file mode 100644 index 0000000..b45a3d4 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAnd.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class SubAnd:ISubOperation + { + public string Name + { + get { return "And"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 401; + } + } + + public ExpressionContext Context + { + get;set; + } + + public bool HasWhere + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var result = "AND " + SubTools.GetMethodValue(this.Context, argExp, ResolveExpressType.WhereMultiple); + + + var regex = @"^AND (\@Const\d+) $"; + if (this.Context is OracleExpressionContext) + { + regex = @"^AND (\:Const\d+) $"; + } + if (Regex.IsMatch(result, regex)) + { + result = "AND " + this.Context.Parameters.First(it => it.ParameterName == Regex.Match(result, regex).Groups[1].Value).Value; + return result; + } + + var selfParameterName = this.Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAndIF.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAndIF.cs new file mode 100644 index 0000000..15e2e24 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAndIF.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubAndIF : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "WhereIF"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 400; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + object value = null; + try + { + value = ExpressionTool.DynamicInvoke(exp.Arguments[0]); + } + catch + { + Check.Exception(true, ErrorMessage.WhereIFCheck,exp.Arguments[0].ToString()); + } + var isWhere= Convert.ToBoolean(value); + if (!Convert.ToBoolean(isWhere)) { + return ""; + } + var argExp = exp.Arguments[1]; + var result = "AND " + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple); ; + var selfParameterName = Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAny.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAny.cs new file mode 100644 index 0000000..476c69c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAny.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubAny : ISubOperation + { + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get;set; + } + + public bool HasWhere + { + get;set; + } + + public string Name + { + get + { + return "Any"; + } + } + + public int Sort + { + get + { + return 0; + } + } + + public string GetValue(Expression expression) + { + return "EXISTS"; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAvg.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAvg.cs new file mode 100644 index 0000000..0018739 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubAvg.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubAvg: ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Avg"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + return "AVG(" + SubTools.GetMethodValue(this.Context, exp.Arguments[0], ResolveExpressType.FieldSingle) + ")"; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubBegin.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubBegin.cs new file mode 100644 index 0000000..879d60f --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubBegin.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubBegin : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Begin"; + } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 100; + } + } + + public ExpressionContext Context + { + get;set; + } + + public string GetValue(Expression expression) + { + return "SELECT"; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubCount.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubCount.cs new file mode 100644 index 0000000..bbb1cd1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubCount.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubCount: ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Count"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + return "COUNT(*)"; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubFromTable.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubFromTable.cs new file mode 100644 index 0000000..7db117a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubFromTable.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubFromTable : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Subqueryable"; + } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 300; + } + } + + public ExpressionContext Context + { + get;set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var resType = exp.Method.ReturnType; + var entityType = resType.GetGenericArguments().First(); + var name = entityType.Name; + if (this.Context.InitMappingInfo != null) + { + this.Context.InitMappingInfo(entityType); + this.Context.RefreshMapping(); + } + var result= "FROM "+this.Context.GetTranslationTableName(name,true); + if (this.Context.SubQueryIndex > 0) { + result += " subTableIndex"+this.Context.SubQueryIndex; + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubGroupBy.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubGroupBy.cs new file mode 100644 index 0000000..1d00254 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubGroupBy.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubGroupBy : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "GroupBy"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 479; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var type = ResolveExpressType.FieldSingle; + if ((argExp as LambdaExpression).Body is NewExpression) { + type = ResolveExpressType.ArraySingle; + } + var result = "GROUP BY " + SubTools.GetMethodValue(this.Context, argExp,type); + result = result.TrimEnd(','); + var selfParameterName = this.Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubLeftBracket.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubLeftBracket.cs new file mode 100644 index 0000000..29be63a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubLeftBracket.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubLeftBracket : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get;set; + } + + public string Name + { + get + { + return "LeftBracket"; + } + } + + public int Sort + { + get + { + return 50; + } + } + + public string GetValue(Expression expression) + { + return "("; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubMax.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubMax.cs new file mode 100644 index 0000000..aee39de --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubMax.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubMax:ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Max"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var parametres = (argExp as LambdaExpression).Parameters; + if ((argExp as LambdaExpression).Body is UnaryExpression) + { + argExp = ((argExp as LambdaExpression).Body as UnaryExpression).Operand; + } + var result = "MAX(" + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple) + ")"; + var selfParameterName = Context.GetTranslationColumnName(parametres.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubMin.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubMin.cs new file mode 100644 index 0000000..41fd561 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubMin.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubMin: ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Min"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var parametres = (argExp as LambdaExpression).Parameters; + if ((argExp as LambdaExpression).Body is UnaryExpression) + { + argExp = ((argExp as LambdaExpression).Body as UnaryExpression).Operand; + } + var result = "MIN(" + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple) + ")"; + var selfParameterName = Context.GetTranslationColumnName(parametres.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubNotAny.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubNotAny.cs new file mode 100644 index 0000000..7805505 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubNotAny.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubNotAny : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get; set; + } + + public string Name + { + get + { + return "NotAny"; + } + } + + public int Sort + { + get + { + return 0; + } + } + + public string GetValue(Expression expression) + { + return "NOT EXISTS"; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubOrderBy.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubOrderBy.cs new file mode 100644 index 0000000..f71ee71 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubOrderBy.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubOrderBy : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "OrderBy"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 480; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + if (this.Context is OracleExpressionContext) + { + throw new Exception("Oracle Subquery can't OrderBy"); + } + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var result = "ORDER BY " + SubTools.GetMethodValue(this.Context, argExp, ResolveExpressType.FieldSingle); + var selfParameterName = this.Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } + public class SubOrderByDesc : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "OrderByDesc"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 480; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var result = "ORDER BY " + SubTools.GetMethodValue(this.Context, argExp, ResolveExpressType.FieldSingle)+" DESC"; + var selfParameterName = this.Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, string.Empty); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubRightBracket.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubRightBracket.cs new file mode 100644 index 0000000..970d3a6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubRightBracket.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubRightBracket : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get;set; + } + + public string Name + { + get + { + return "RightBracket"; + } + } + + public int Sort + { + get + { + return 500; + } + } + + public string GetValue(Expression expression) + { + return ")"; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSelect.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSelect.cs new file mode 100644 index 0000000..d2b853f --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSelect.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubSelect : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Select"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get;set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + var entityType = (exp.Arguments[0] as LambdaExpression).Parameters[0].Type; + if (this.Context.InitMappingInfo != null) + { + this.Context.InitMappingInfo(entityType); + this.Context.RefreshMapping(); + } + return SubTools.GetMethodValue(this.Context, exp.Arguments[0],ResolveExpressType.FieldSingle); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSelectDefault.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSelectDefault.cs new file mode 100644 index 0000000..a60e6af --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSelectDefault.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubSelectDefault : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get;set; + } + + public string Name + { + get { + return "SelectDefault"; + } + } + + public int Sort + { + get + { + return 250; + } + } + + public string GetValue(Expression expression) + { + return "*"; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSum.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSum.cs new file mode 100644 index 0000000..03f1454 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubSum.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubSum : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Sum"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var parametres = (argExp as LambdaExpression).Parameters; + if ((argExp as LambdaExpression).Body is UnaryExpression) + { + argExp =((argExp as LambdaExpression).Body as UnaryExpression).Operand; + } + var result = "SUM(" + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple)+")"; + var selfParameterName = Context.GetTranslationColumnName(parametres.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubTop.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubTop.cs new file mode 100644 index 0000000..11d2e17 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubTop.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubTop : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get; set; + } + + public Expression Expression + { + get; set; + } + + public string Name + { + get + { + return "Top"; + } + } + + public int Sort + { + get + { + if (this.Context is SqlServerExpressionContext) + { + return 150; + } + else if (this.Context is OracleExpressionContext) { + + return 401; + } + else + { + return 490; + } + } + } + + + public string GetValue(Expression expression) + { + if (this.Context is SqlServerExpressionContext) + { + return "TOP 1"; + } + else if (this.Context is OracleExpressionContext) + { + return (HasWhere?"AND":"WHERE")+ " ROWNUM=1"; + } + else if (this.Context is PostgreSQLExpressionContext) + { + return "limit 1"; + } + else + { + return "limit 0,1"; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubWhere.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubWhere.cs new file mode 100644 index 0000000..7174e5c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubWhere.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class SubWhere: ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "Where"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 400; + } + } + + public ExpressionContext Context + { + get;set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var argExp= exp.Arguments[0]; + var result= "WHERE "+SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple); + + + var regex = @"^WHERE (\@Const\d+) $"; + if (this.Context is OracleExpressionContext) + { + regex = @"^WHERE (\:Const\d+) $"; + } + if (Regex.IsMatch(result, regex)) + { + result = "WHERE " + this.Context.Parameters.First(it => it.ParameterName == Regex.Match(result, regex).Groups[1].Value).Value; + return result; + } + + var selfParameterName = Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name)+UtilConstants.Dot; + result = result.Replace(selfParameterName,SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubWhereIF.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubWhereIF.cs new file mode 100644 index 0000000..1e266e1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Items/SubWhereIF.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubWhereIF : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "WhereIF"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 400; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + object value = null; + try + { + value = ExpressionTool.DynamicInvoke(exp.Arguments[0]); + } + catch + { + Check.Exception(true, ErrorMessage.WhereIFCheck,exp.Arguments[0].ToString()); + } + var isWhere= Convert.ToBoolean(value); + if (!Convert.ToBoolean(isWhere)) { + return "WHERE 1=1 "; + } + var argExp = exp.Arguments[1]; + var result = "WHERE " + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple); ; + var selfParameterName = Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/SubResolve.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/SubResolve.cs new file mode 100644 index 0000000..f417e56 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/SubResolve.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + /// + /// ** description:Get subquery sql + /// ** author:sunkaixuan + /// ** date:2017/9/17 + /// ** email:610262374@qq.com + /// + public class SubResolve + { + List allMethods = new List(); + private ExpressionContext context = null; + private bool hasWhere; + public SubResolve(MethodCallExpression expression, ExpressionContext context, Expression oppsiteExpression) + { + this.context = context; + var currentExpression = expression; + allMethods.Add(currentExpression); + if (context.IsSingle && oppsiteExpression != null && oppsiteExpression is MemberExpression) + { + var childExpression = (oppsiteExpression as MemberExpression).Expression; + if (childExpression is ParameterExpression) + this.context.SingleTableNameSubqueryShortName = (childExpression as ParameterExpression).Name; + else { + this.context.SingleTableNameSubqueryShortName = (context.Expression as LambdaExpression).Parameters.First().Name; + } + } + else if (context.IsSingle) + { + if (context.Expression is LambdaExpression) + { + this.context.SingleTableNameSubqueryShortName = (context.Expression as LambdaExpression).Parameters.First().Name; + } + else if (context.Expression is MethodCallExpression) + { + var expArgs = ((context.Expression as MethodCallExpression).Object as MethodCallExpression).Arguments; + if (expArgs != null && expArgs.Any()) + { + var meExp = expArgs[0] as LambdaExpression; + var selfParameterName = meExp.Parameters.First().Name; + context.SingleTableNameSubqueryShortName = (((meExp.Body as BinaryExpression).Left as MemberExpression).Expression as ParameterExpression).Name; + if (context.SingleTableNameSubqueryShortName == selfParameterName) + { + context.SingleTableNameSubqueryShortName = (((meExp.Body as BinaryExpression).Right as MemberExpression).Expression as ParameterExpression).Name; + } + } + } + else if (context.Expression.GetType().Name == "MethodBinaryExpression") + { + + var subExp = (context.Expression as BinaryExpression).Left is MethodCallExpression ? (context.Expression as BinaryExpression).Left : (context.Expression as BinaryExpression).Right; + var meExp = ((subExp as MethodCallExpression).Object as MethodCallExpression).Arguments[0] as LambdaExpression; + var selfParameterName = meExp.Parameters.First().Name; + context.SingleTableNameSubqueryShortName = (((meExp.Body as BinaryExpression).Left as MemberExpression).Expression as ParameterExpression).Name; + if (context.SingleTableNameSubqueryShortName == selfParameterName) + { + context.SingleTableNameSubqueryShortName = (((meExp.Body as BinaryExpression).Right as MemberExpression).Expression as ParameterExpression).Name; + } + } + else + { + Check.Exception(true, "I'm sorry I can't parse the current expression"); + } + } + var subIndex = this.context.SubQueryIndex; + while (currentExpression != null) + { + var addItem = currentExpression.Object as MethodCallExpression; + if (addItem != null) + allMethods.Add(addItem); + if (subIndex==this.context.SubQueryIndex&&addItem !=null&&addItem.Arguments.HasValue()&&addItem.Arguments.Any(it=>it.ToString().Contains("Subqueryable()"))) { + this.context.SubQueryIndex++; + } + currentExpression = addItem; + } + } + + public string GetSql() + { + List subItems = GetSubItems(); + var sql = string.Join(UtilConstants.Space, subItems); + return this.context.DbMehtods.Pack(sql); + } + + private List GetSubItems() + { + var isubList = this.allMethods.Select(exp => + { + var methodName = exp.Method.Name; + var items = SubTools.SubItems(this.context); + var item = items.First(s => s.Name == methodName); + if (item is SubWhere && hasWhere == false) + { + hasWhere = true; + } + else if (item is SubWhere) + { + item = items.First(s => s is SubAnd); + } + + if (item is SubWhereIF && hasWhere == false) + { + hasWhere = true; + } + else if (item is SubWhereIF) + { + item = items.First(s => s is SubAndIF); + } + + item.Context = this.context; + item.Expression = exp; + return item; + }).ToList(); + isubList.Insert(0, new SubBegin()); + if (isubList.Any(it => it is SubSelect)) + { + isubList.Add(new SubTop() { Context = this.context }); + } + if (isubList.Any(it => it is SubAny || it is SubNotAny)) + { + isubList.Add(new SubLeftBracket()); + isubList.Add(new SubRightBracket()); + isubList.Add(new SubSelectDefault()); + } + isubList = isubList.OrderBy(it => it.Sort).ToList(); + var isHasWhere = isubList.Where(it => it is SubWhere).Any(); + List result = isubList.Select(it => + { + it.HasWhere = isHasWhere; + return it.GetValue(it.Expression); + }).ToList(); + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/SubTools.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/SubTools.cs new file mode 100644 index 0000000..8896c09 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/SubTools.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubTools + { + public static List SubItems(ExpressionContext Context) + { + + return new List() + { + new SubSelect() { Context=Context }, + new SubWhere(){ Context=Context }, + new SubWhereIF(){ Context=Context }, + new SubAnd(){ Context=Context }, + new SubAndIF(){ Context=Context }, + new SubAny(){ Context=Context }, + new SubNotAny(){ Context=Context }, + new SubBegin(){ Context=Context }, + new SubFromTable(){ Context=Context }, + new SubCount(){ Context=Context }, + new SubMax(){ Context=Context }, + new SubMin(){ Context=Context }, + new SubSum(){ Context=Context }, + new SubAvg(){ Context=Context }, + new SubOrderBy(){ Context=Context }, + new SubOrderByDesc(){ Context=Context }, + new SubGroupBy(){ Context=Context} + }; + } + + public static string GetSubReplace(ExpressionContext context) + { + if (context.SubQueryIndex == 0) + return string.Empty; + else + return "subTableIndex"+context.SubQueryIndex+"."; + } + + public static List SubItemsConst = SubItems(null); + + public static string GetMethodValue(ExpressionContext context, Expression item, ResolveExpressType type) + { + var newContext = context.GetCopyContext(); + newContext.MappingColumns = context.MappingColumns; + newContext.MappingTables = context.MappingTables; + newContext.InitMappingInfo = context.InitMappingInfo; + newContext.RefreshMapping = context.RefreshMapping; + newContext.IgnoreComumnList = context.IgnoreComumnList; + newContext.SqlFuncServices = context.SqlFuncServices; + newContext.Resolve(item, type); + context.Index = newContext.Index; + context.ParameterIndex = newContext.ParameterIndex; + if (newContext.Parameters.HasValue()) + context.Parameters.AddRange(newContext.Parameters); + return newContext.Result.GetResultString(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Subquerable.cs b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Subquerable.cs new file mode 100644 index 0000000..3d6f772 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExpressionsToSql/Subquery/Subquerable.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + + public class Subqueryable where T : class, new() + { + public Subqueryable Where(string where) + { + return this; + } + public Subqueryable Where(Func expression) + { + return this; + } + public Subqueryable WhereIF(bool isWhere,Func expression) + { + return this; + } + public Subqueryable OrderBy(Func expression) + { + return this; + } + public Subqueryable GroupBy(Func expression) + { + return this; + } + public Subqueryable OrderByDesc(Func expression) + { + return this; + } + + public TResult Select(Func expression) where TResult :struct + { + return default(TResult); + } + public Byte[] Select(Func expression) + { + return null; + } + public string Select(Func expression) + { + return default(string); + } + + public TResult Max(Func expression) where TResult : struct + { + return default(TResult); + } + public Byte[] Max(Func expression) + { + return null; + } + public string Max(Func expression) + { + return default(string); + } + + public string Min(Func expression) + { + return default(string); + } + public TResult Min(Func expression) where TResult : struct + { + return default(TResult); + } + public Byte[] Min(Func expression) + { + return null; + } + + + public string Sum(Func expression) + { + return default(string); + } + public TResult Sum(Func expression) where TResult : struct + { + return default(TResult); + } + public Byte[] Sum(Func expression) + { + return null; + } + + public string Avg(Func expression) + { + return default(string); + } + public TResult Avg(Func expression) where TResult : struct + { + return default(TResult); + } + public Byte[] Avg(Func expression) + { + return null; + } + + public bool Any() + { + return default(bool); + } + + public bool NotAny() + { + return default(bool); + } + + public int Count() + { + return default(int); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/ICacheService.cs b/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/ICacheService.cs new file mode 100644 index 0000000..a932fa6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/ICacheService.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace SqlSugar +{ + public interface ICacheService + { + void Add(string key, V value); + void Add(string key, V value, int cacheDurationInSeconds); + bool ContainsKey(string key); + V Get(string key); + IEnumerable GetAllKey(); + void Remove(string key); + V GetOrCreate(string cacheKey, Func create,int cacheDurationInSeconds=int.MaxValue); + } +} \ No newline at end of file diff --git a/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/IRazorService.cs b/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/IRazorService.cs new file mode 100644 index 0000000..98dd9e2 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/IRazorService.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IRazorService + { + List> GetClassStringList(string razorTemplate, List model); + } +} diff --git a/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/ISerializeService.cs b/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/ISerializeService.cs new file mode 100644 index 0000000..61a72f4 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/ExternalServiceInterface/ISerializeService.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public interface ISerializeService + { + string SerializeObject(object value); + string SugarSerializeObject(object value); + T DeserializeObject(string value); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Infrastructure/ContextMethods.cs b/类库/SqlSugar/5.0.0.9/Infrastructure/ContextMethods.cs new file mode 100644 index 0000000..a8d7ea7 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Infrastructure/ContextMethods.cs @@ -0,0 +1,530 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Dynamic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial class ContextMethods : IContextMethods + { + public SqlSugarProvider Context { get; set; } + #region DataReader + + /// + ///DataReader to Dynamic + /// + /// + /// + public ExpandoObject DataReaderToExpandoObject(IDataReader reader) + { + ExpandoObject result = new ExpandoObject(); + var dic = ((IDictionary)result); + for (int i = 0; i < reader.FieldCount; i++) + { + try + { + var addItem = reader.GetValue(i); + if (addItem == DBNull.Value) + addItem = null; + dic.Add(reader.GetName(i), addItem); + } + catch + { + dic.Add(reader.GetName(i), null); + } + } + return result; + } + + /// + ///DataReader to Dynamic List + /// + /// + /// + public List DataReaderToExpandoObjectList(IDataReader reader) + { + using (reader) + { + List result = new List(); + if (reader != null && !reader.IsClosed) + { + while (reader.Read()) + { + result.Add(DataReaderToExpandoObject(reader)); + } + } + return result; + } + } + /// + ///DataReader to Dynamic List + /// + /// + /// + public async Task> DataReaderToExpandoObjectListAsync(IDataReader reader) + { + using (reader) + { + List result = new List(); + if (reader != null && !reader.IsClosed) + { + while (await((DbDataReader)reader).ReadAsync()) + { + result.Add(DataReaderToExpandoObject(reader)); + } + } + return result; + } + } + + + /// + ///DataReader to Dynamic List + /// + /// + /// + public List DataReaderToExpandoObjectListNoUsing(IDataReader reader) + { + List result = new List(); + if (reader != null && !reader.IsClosed) + { + while (reader.Read()) + { + result.Add(DataReaderToExpandoObject(reader)); + } + } + return result; + } + + /// + ///DataReader to Dynamic List + /// + /// + /// + public async Task> DataReaderToExpandoObjectListAsyncNoUsing(IDataReader reader) + { + List result = new List(); + if (reader != null && !reader.IsClosed) + { + while (await ((DbDataReader)reader).ReadAsync()) + { + result.Add(DataReaderToExpandoObject(reader)); + } + } + return result; + } + + + /// + ///DataReader to DataReaderToDictionary + /// + /// + /// + public Dictionary DataReaderToDictionary(IDataReader reader) + { + Dictionary result = new Dictionary(); + for (int i = 0; i < reader.FieldCount; i++) + { + try + { + var addItem = reader.GetValue(i); + if (addItem == DBNull.Value) + addItem = null; + result.Add(reader.GetName(i), addItem); + } + catch + { + result.Add(reader.GetName(i), null); + } + } + return result; + } + + /// + ///DataReader to DataReaderToDictionary + /// + /// + /// + public Dictionary DataReaderToDictionary(IDataReader reader, Type type) + { + Dictionary result = new Dictionary(); + for (int i = 0; i < reader.FieldCount; i++) + { + string name = reader.GetName(i); + try + { + name = this.Context.EntityMaintenance.GetPropertyName(name, type); + var addItem = reader.GetValue(i); + if (addItem == DBNull.Value) + addItem = null; + result.Add(name, addItem); + } + catch + { + result.Add(name, null); + } + } + return result; + } + + /// + /// DataReaderToList + /// + /// + /// + /// + public List DataReaderToList(IDataReader reader) + { + using (reader) + { + var tType = typeof(T); + var classProperties = tType.GetProperties().ToList(); + var reval = new List(); + if (reader != null && !reader.IsClosed) + { + while (reader.Read()) + { + Dictionary result = DataReaderToList(reader, tType, classProperties, reval); + var stringValue = SerializeObject(result); + reval.Add((T)DeserializeObject(stringValue)); + } + } + return reval; + } + } + /// + /// DataReaderToList + /// + /// + /// + /// + public List DataReaderToListNoUsing(IDataReader reader) + { + var tType = typeof(T); + var classProperties = tType.GetProperties().ToList(); + var reval = new List(); + if (reader != null && !reader.IsClosed) + { + while (reader.Read()) + { + Dictionary result = DataReaderToList(reader, tType, classProperties, reval); + var stringValue = SerializeObject(result); + reval.Add((T)DeserializeObject(stringValue)); + } + } + return reval; + } + /// + /// DataReaderToList + /// + /// + /// + /// + public async Task> DataReaderToListAsync(IDataReader reader) + { + using (reader) + { + var tType = typeof(T); + var classProperties = tType.GetProperties().ToList(); + var reval = new List(); + if (reader != null && !reader.IsClosed) + { + while (await ((DbDataReader)reader).ReadAsync()) + { + Dictionary result = DataReaderToList(reader, tType, classProperties, reval); + var stringValue = SerializeObject(result); + reval.Add((T)DeserializeObject(stringValue)); + } + } + return reval; + } + } + /// + /// DataReaderToList + /// + /// + /// + /// + public async Task> DataReaderToListAsyncNoUsing(IDataReader reader) + { + var tType = typeof(T); + var classProperties = tType.GetProperties().ToList(); + var reval = new List(); + if (reader != null && !reader.IsClosed) + { + while (await ((DbDataReader)reader).ReadAsync()) + { + Dictionary result = DataReaderToList(reader, tType, classProperties, reval); + var stringValue = SerializeObject(result); + reval.Add((T)DeserializeObject(stringValue)); + } + } + return reval; + } + + private Dictionary DataReaderToList(IDataReader reader, Type tType, List classProperties, List reval) + { + var readerValues = DataReaderToDictionary(reader, tType); + var result = new Dictionary(); + foreach (var item in classProperties) + { + var name = item.Name; + var typeName = tType.Name; + if (item.PropertyType.IsClass()) + { + result.Add(name, DataReaderToDynamicList_Part(readerValues, item, reval)); + } + else + { + if (readerValues.Any(it => it.Key.Equals(name, StringComparison.CurrentCultureIgnoreCase))) + { + var addValue = readerValues.ContainsKey(name) ? readerValues[name] : readerValues.First(it => it.Key.Equals(name, StringComparison.CurrentCultureIgnoreCase)).Value; + if (addValue == DBNull.Value || addValue == null) + { + if (item.PropertyType.IsIn(UtilConstants.IntType, UtilConstants.DecType, UtilConstants.DobType, UtilConstants.ByteType)) + { + addValue = 0; + } + else if (item.PropertyType == UtilConstants.GuidType) + { + addValue = Guid.Empty; + } + else if (item.PropertyType == UtilConstants.DateType) + { + addValue = DateTime.MinValue; + } + else if (item.PropertyType == UtilConstants.StringType) + { + addValue = null; + } + else + { + addValue = null; + } + } + else if (item.PropertyType == UtilConstants.IntType) + { + addValue = Convert.ToInt32(addValue); + } + else if (UtilMethods.GetUnderType(item.PropertyType) == UtilConstants.LongType) + { + addValue = Convert.ToInt64(addValue); + } + result.Add(name, addValue); + } + } + } + + return result; + } + + private Dictionary DataReaderToDynamicList_Part(Dictionary readerValues, PropertyInfo item, List reval) + { + Dictionary result = new Dictionary(); + var type = item.PropertyType; + if (UtilConstants.SugarType == type) + { + return result; + } + if (type.FullName.IsCollectionsList()) + { + return null; + } + var classProperties = type.GetProperties().ToList(); + foreach (var prop in classProperties) + { + var name = prop.Name; + var typeName = type.Name; + if (prop.PropertyType.IsClass()) + { + result.Add(name, DataReaderToDynamicList_Part(readerValues, prop, reval)); + } + else + { + var key = typeName + "." + name; + var info = readerValues.Select(it => it.Key).FirstOrDefault(it => it.ToLower() == key.ToLower()); + if (info != null) + { + var addItem = readerValues[info]; + if (addItem == DBNull.Value) + addItem = null; + if (prop.PropertyType == UtilConstants.IntType) + { + addItem = addItem.ObjToInt(); + } + result.Add(name, addItem); + } + } + } + return result; + } + #endregion + + #region Serialize + /// + /// Serialize Object + /// + /// + /// + public string SerializeObject(object value) + { + DependencyManagement.TryJsonNet(); + return Context.CurrentConnectionConfig.ConfigureExternalServices.SerializeService.SerializeObject(value); + } + public string SerializeObject(object value, Type type) + { + DependencyManagement.TryJsonNet(); + if (type.IsAnonymousType()) + { + return Context.CurrentConnectionConfig.ConfigureExternalServices.SerializeService.SerializeObject(value); + } + else + { + var isSugar = this.Context.EntityMaintenance.GetEntityInfo(type).Columns.Any(it=>it.NoSerialize || it.SerializeDateTimeFormat.HasValue()); + if (isSugar) + { + return Context.CurrentConnectionConfig.ConfigureExternalServices.SerializeService.SugarSerializeObject(value); + } + else + { + return Context.CurrentConnectionConfig.ConfigureExternalServices.SerializeService.SerializeObject(value); + } + } + } + + + /// + /// Serialize Object + /// + /// + /// + public T DeserializeObject(string value) + { + DependencyManagement.TryJsonNet(); + return Context.CurrentConnectionConfig.ConfigureExternalServices.SerializeService.DeserializeObject(value); + } + #endregion + + #region Copy Object + /// + /// Copy new Object + /// + /// + /// + /// + public T TranslateCopy(T sourceObject) + { + if (sourceObject == null) return default(T); + else + { + var jsonString = SerializeObject(sourceObject); + return DeserializeObject(jsonString); + } + } + public SqlSugarProvider CopyContext(bool isCopyEvents = false) + { + var newClient = new SqlSugarProvider(this.TranslateCopy(Context.CurrentConnectionConfig)); + newClient.CurrentConnectionConfig.ConfigureExternalServices = Context.CurrentConnectionConfig.ConfigureExternalServices; + newClient.MappingColumns = this.TranslateCopy(Context.MappingColumns); + newClient.MappingTables = this.TranslateCopy(Context.MappingTables); + newClient.IgnoreColumns = this.TranslateCopy(Context.IgnoreColumns); + newClient.IgnoreInsertColumns = this.TranslateCopy(Context.IgnoreInsertColumns); + if (isCopyEvents) + { + newClient.QueryFilter = Context.QueryFilter; + newClient.CurrentConnectionConfig.AopEvents = Context.CurrentConnectionConfig.AopEvents; + } + return newClient; + } + #endregion + + #region DataTable + public dynamic DataTableToDynamic(DataTable table) + { + List> deserializeObject = new List>(); + Dictionary childRow; + foreach (DataRow row in table.Rows) + { + childRow = new Dictionary(); + foreach (DataColumn col in table.Columns) + { + var addItem = row[col]; + if (addItem == DBNull.Value) + addItem = null; + childRow.Add(col.ColumnName, addItem); + } + deserializeObject.Add(childRow); + } + return this.DeserializeObject(this.SerializeObject(deserializeObject)); + + } + public List DataTableToList(DataTable table) + { + List> deserializeObject = new List>(); + Dictionary childRow; + foreach (DataRow row in table.Rows) + { + childRow = new Dictionary(); + foreach (DataColumn col in table.Columns) + { + var addItem = row[col]; + if (addItem == DBNull.Value) + addItem = null; + childRow.Add(col.ColumnName, addItem); + } + deserializeObject.Add(childRow); + } + return this.DeserializeObject>(this.SerializeObject(deserializeObject)); + } + public Dictionary DataTableToDictionary(DataTable table) + { + return table.Rows.Cast().ToDictionary(x => x[0].ToString(), x => x[1]); + } + + #endregion + + #region Cache + public ICacheService GetReflectionInoCacheInstance() + { + return Context.CurrentConnectionConfig.ConfigureExternalServices.ReflectionInoCacheService; + } + + public void RemoveCacheAll() + { + ReflectionInoHelper.RemoveAllCache(); + InstanceFactory.RemoveCache(); + } + + public void RemoveCacheAll() + { + ReflectionInoCore.GetInstance().RemoveAllCache(); + } + + public void RemoveCache(string key) + { + ReflectionInoCore.GetInstance().Remove(key); + } + #endregion + + #region + public void PageEach(IEnumerable pageItems,int pageSize, Action> action) + { + if (pageItems != null&& pageItems.Any()) + { + int totalRecord = pageItems.Count(); + int pageCount = (totalRecord + pageSize - 1) / pageSize; + for (int i = 1; i <= pageCount; i++) + { + var list = pageItems.Skip((i - 1) * pageSize).Take(pageSize).ToList(); + action(list); + } + } + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Infrastructure/DependencyManagement.cs b/类库/SqlSugar/5.0.0.9/Infrastructure/DependencyManagement.cs new file mode 100644 index 0000000..f8f6ab2 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Infrastructure/DependencyManagement.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + internal class DependencyManagement + { + private static bool IsTryJsonNet = false; + private static bool IsTryMySqlData = false; + private static bool IsTrySqlite = false; + private static bool IsTryOracle = false; + private static bool IsTryPgSql = false; + public static void TryJsonNet() + { + if (!IsTryJsonNet) + { + try + { + new SerializeService().SerializeObject(new { }); + IsTryJsonNet = true; + } + catch + { + var message = ErrorMessage.GetThrowMessage( + " SqlSugar Some functions are used in newtonsoft ,Nuget references Newtonsoft.Json 9.0.0.1 + .", + " SqlSugar 部分功能用到Newtonsoft.Json.dll,需要在Nuget上安装 Newtonsoft.Json 9.0.0.1及以上版本。如果有版本兼容问题请先删除原有引用(注意:所有项目类库),全部重新从NUGET下载,如果还不明白,请查看详细教程 http://www.codeisbug.com/Doc/8/1154"); + throw new Exception(message); + } + } + } + public static void TryMySqlData() + { + if (!IsTryMySqlData) + { + try + { + MySqlProvider db = new MySqlProvider(); + var conn = db.GetAdapter(); + IsTryMySqlData = true; + } + catch + { + var message = ErrorMessage.GetThrowMessage( + "You need to refer to MySql.Data.dll", + "需要引用MySql.Data.dll,请在Nuget安装最新稳定版本,如果有版本兼容问题请先删除原有引用"); + throw new Exception(message); + } + } + } + + public static void TryPostgreSQL() + { + if (!IsTryPgSql) + { + try + { + PostgreSQLProvider db = new PostgreSQLProvider(); + var conn = db.GetAdapter(); + IsTryPgSql = true; + } + catch + { + var message = ErrorMessage.GetThrowMessage( + "You need to refer to Npgsql.dll", + "需要引用Npgsql.dll,请在Nuget安装最新稳定版本,如果有版本兼容问题请先删除原有引用"); + throw new Exception(message); + } + } + } + + internal static void TryOracle() + { + if (!IsTryOracle) + { + try + { + OracleProvider db = new OracleProvider(); + var conn = db.GetAdapter(); + IsTryOracle = true; + } + catch + { + var message = ErrorMessage.GetThrowMessage( + "You need to refer to Oracle.ManagedDataAccess.dll", + "需要引用ManagedDataAccess.dll,请在Nuget安装最新稳定版本,如果有版本兼容问题请先删除原有引用"); + throw new Exception(message); + } + } + } + + public static void TrySqlite() + { + if (!IsTrySqlite) + { + try + { + SqliteProvider db = new SqliteProvider(); + var conn = db.GetAdapter(); + IsTrySqlite = true; + } + catch (Exception ex) + { + var message = ErrorMessage.GetThrowMessage( + "You need to refer to System.Data.SQLite.dll." + ex.Message, + "你需要引用System.Data.SQLite.dll,如果有版本兼容问题请先删除原有引用"); + throw new Exception(message); + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Infrastructure/InstanceFactory.cs b/类库/SqlSugar/5.0.0.9/Infrastructure/InstanceFactory.cs new file mode 100644 index 0000000..a88dd08 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Infrastructure/InstanceFactory.cs @@ -0,0 +1,387 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class InstanceFactory + { + static Assembly assembly = Assembly.Load(UtilConstants.AssemblyName); + static Dictionary typeCache = new Dictionary(); + + + public static void RemoveCache() + { + typeCache = new Dictionary(); + } + + #region Queryable + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerQueryable(); + } + else + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerQueryable(); + } + else + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerQueryable(); + } + else + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + + #region 9-12 + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + #endregion + + #endregion + + public static QueryBuilder GetQueryBuilder(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerQueryBuilder(); + } + else if (currentConnectionConfig.DbType == DbType.MySql) + { + return new MySqlQueryBuilder(); + } + else + { + QueryBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "QueryBuilder")); + return result; + } + } + public static InsertBuilder GetInsertBuilder(ConnectionConfig currentConnectionConfig) + { + InsertBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "InsertBuilder")); + return result; + } + public static UpdateBuilder GetUpdateBuilder(ConnectionConfig currentConnectionConfig) + { + UpdateBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "UpdateBuilder")); + return result; + } + public static DeleteBuilder GetDeleteBuilder(ConnectionConfig currentConnectionConfig) + { + DeleteBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "DeleteBuilder")); + return result; + } + + public static ILambdaExpressions GetLambdaExpressions(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerExpressionContext(); + } + else if (currentConnectionConfig.DbType == DbType.MySql) + { + return new MySqlExpressionContext(); + } + else + { + ILambdaExpressions result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "ExpressionContext")); + return result; + } + } + + public static ISqlBuilder GetSqlbuilder(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerBuilder(); + } + else if (currentConnectionConfig.DbType == DbType.MySql) + { + return new MySqlBuilder(); + } + else + { + ISqlBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "Builder")); + return result; + } + } + + public static UpdateableProvider GetUpdateableProvider(ConnectionConfig currentConnectionConfig) where T : class, new() + { + if (currentConnectionConfig.DbType == DbType.Oracle) + { + return new OracleUpdateable(); + } + else + { + return new UpdateableProvider(); + } + } + + public static DeleteableProvider GetDeleteableProvider(ConnectionConfig currentConnectionConfig) where T : class, new() + { + if (currentConnectionConfig.DbType == DbType.Oracle) + { + return new OracleDeleteable(); + } + else + { + return new DeleteableProvider(); + } + } + + public static InsertableProvider GetInsertableProvider(ConnectionConfig currentConnectionConfig) where T : class, new() + { + if (currentConnectionConfig.DbType == DbType.Oracle) + { + return new OracleInsertable(); + } + else if (currentConnectionConfig.DbType == DbType.PostgreSQL) + { + return new PostgreSQLInserttable(); + } + else + { + return new InsertableProvider(); + } + } + + public static IDbBind GetDbBind(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerDbBind(); + } + else + { + IDbBind result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "DbBind")); + return result; + } + } + + public static IDbMaintenance GetDbMaintenance(ConnectionConfig currentConnectionConfig) + { + IDbMaintenance result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "DbMaintenance")); + return result; + } + + public static IDbFirst GetDbFirst(ConnectionConfig currentConnectionConfig) + { + IDbFirst result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "DbFirst")); + return result; + } + + public static ICodeFirst GetCodeFirst(ConnectionConfig currentConnectionConfig) + { + ICodeFirst result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "CodeFirst")); + return result; + } + + public static IAdo GetAdo(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerProvider(); + } + else + { + IAdo result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "Provider")); + return result; + } + } + + private static string GetClassName(string type, string name) + { + return UtilConstants.AssemblyName + "." + type + name; + } + + #region CreateInstance + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8)); + } + + #region 9-12 + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12)); + } + #endregion + + private static Restult CreateInstance(string className, params Type[] types) + { + var cacheKey = className + string.Join(",", types.Select(it => it.FullName)); + Type type; + if (typeCache.ContainsKey(cacheKey)) + { + type = typeCache[cacheKey]; + } + else + { + lock (typeCache) + { + type = Type.GetType(className + "`" + types.Length, true).MakeGenericType(types); + Check.ArgumentNullException(type, string.Format(ErrorMessage.ObjNotExist, className)); + if (!typeCache.ContainsKey(cacheKey)) + { + typeCache.Add(cacheKey, type); + } + } + } + var result = (Restult)Activator.CreateInstance(type, true); + return result; + } + public static T CreateInstance(string className) + { + Type type; + if (typeCache.ContainsKey(className)) + { + type = typeCache[className]; + } + else + { + lock (typeCache) + { + type = assembly.GetType(className); + Check.ArgumentNullException(type, string.Format(ErrorMessage.ObjNotExist, className)); + if (!typeCache.ContainsKey(className)) + { + typeCache.Add(className, type); + } + } + } + var result = (T)Activator.CreateInstance(type, true); + return result; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Infrastructure/Mapper.cs b/类库/SqlSugar/5.0.0.9/Infrastructure/Mapper.cs new file mode 100644 index 0000000..c8bb72b --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Infrastructure/Mapper.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SugarMapper + { + private ISqlSugarClient _context; + public SugarMapper(ISqlSugarClient context) + { + _context = context; + } + + public string GetSelectValue(QueryBuilder queryBuilder) + { + string result = string.Empty; + var veiwModel = _context.EntityMaintenance.GetEntityInfo(); + var exp = (queryBuilder.JoinExpression as LambdaExpression); + List> selectItems = new List>(); + foreach (var viewColumn in veiwModel.Columns) + { + var exParsmeters = exp.Parameters.Select(it => new { shortName = it.Name, type = it.Type }).ToList(); + foreach (var expPars in exParsmeters) + { + var columns = _context.EntityMaintenance.GetEntityInfo(expPars.type).Columns.Where(it => it.IsIgnore == false); + var joinModelDbColumns = columns.Select(it => + new { asName = it.PropertyName, dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelProperties = columns.Select(it => + new { asName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelDbColumnsWithType = columns.Select(it => + new { asName = (expPars.type.Name + it.PropertyName), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelPropertiesWithTye = columns.Select(it => + new { asName = (expPars.type.Name + _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type)), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelDbColumns_WithType = columns.Select(it => + new { asName = (expPars.type.Name +"_"+ it.PropertyName), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelProperties_WithType = columns.Select(it => + new { asName = (expPars.type.Name +"_"+ _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type)), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelDbColumnsWithSN = columns.Select(it => + new { asName = (expPars.shortName + it.PropertyName), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelPropertiesWithSN = columns.Select(it => + new { asName = (expPars.shortName + _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type)), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + + if (joinModelDbColumns.Any(it => it.asName.Equals(viewColumn.PropertyName,StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelDbColumns.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName,value)); + break; + } + if (joinModelProperties.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelProperties.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelDbColumnsWithType.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelDbColumnsWithType.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelPropertiesWithTye.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelPropertiesWithTye.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + + if (joinModelDbColumns_WithType.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelDbColumns_WithType.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelProperties_WithType.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelProperties_WithType.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelDbColumnsWithSN.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelDbColumnsWithSN.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelPropertiesWithSN.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelPropertiesWithSN.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + } + } + result = queryBuilder.GetSelectByItems(selectItems); + if (_context.CurrentConnectionConfig.DbType == DbType.PostgreSQL) + { + result = result.ToLower(); + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/IntegrationServices/CacheService.cs b/类库/SqlSugar/5.0.0.9/IntegrationServices/CacheService.cs new file mode 100644 index 0000000..7401157 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/IntegrationServices/CacheService.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; +using System.Linq.Expressions; +namespace SqlSugar +{ + public class ReflectionInoCacheService : ICacheService + { + public void Add(string key, V value) + { + ReflectionInoCore.GetInstance().Add(key,value); + } + public void Add(string key, V value, int cacheDurationInSeconds) + { + ReflectionInoCore.GetInstance().Add(key, value,cacheDurationInSeconds); + } + + public bool ContainsKey(string key) + { + return ReflectionInoCore.GetInstance().ContainsKey(key); + } + + public V Get(string key) + { + return ReflectionInoCore.GetInstance().Get(key); + } + + public IEnumerable GetAllKey() + { + return ReflectionInoCore.GetInstance().GetAllKey(); + } + + public V GetOrCreate(string cacheKey, Func create,int cacheDurationInSeconds=int.MaxValue) + { + return ReflectionInoCore.GetInstance().GetOrCreate(cacheKey, create); + } + + public void Remove(string key) + { + ReflectionInoCore.GetInstance().Remove(key); + } + } + public class ReflectionInoCore + { + readonly System.Collections.Concurrent.ConcurrentDictionary InstanceCache = new System.Collections.Concurrent.ConcurrentDictionary(); + private static ReflectionInoCore _instance = null; + private static readonly object _instanceLock = new object(); + private ReflectionInoCore() { } + + public V this[string key] + { + get + { + return this.Get(key); + } + } + + public bool ContainsKey(string key) + { + return this.InstanceCache.ContainsKey(key); + } + + public V Get(string key) + { + if (this.ContainsKey(key)) + return this.InstanceCache[key]; + else + return default(V); + } + + public static ReflectionInoCore GetInstance() + { + if (_instance == null) + lock (_instanceLock) + if (_instance == null) + { + _instance = new ReflectionInoCore(); + Action addItem =()=> { ReflectionInoCore.GetInstance().RemoveAllCache(); }; + ReflectionInoHelper.AddRemoveFunc(addItem); + } + return _instance; + } + + public void Add(string key, V value) + { + this.InstanceCache.GetOrAdd(key, value); + } + + public void Add(string key, V value, int cacheDurationInSeconds) + { + Check.ThrowNotSupportedException("ReflectionInoCache.Add(string key, V value, int cacheDurationInSeconds)"); + } + + public void Remove(string key) + { + V val; + this.InstanceCache.TryRemove(key, out val); + } + + public void RemoveAllCache() + { + foreach (var key in GetAllKey()) + { + this.Remove(key); + } + } + + public IEnumerable GetAllKey() + { + return this.InstanceCache.Keys; + } + + public V GetOrCreate(string cacheKey, Func create) + { + if (this.ContainsKey(cacheKey)) return Get(cacheKey); + else + { + var reval = create(); + this.Add(cacheKey, reval); + return reval; + } + } + } + internal static class ReflectionInoHelper + { + private static List removeActions = new List(); + internal static void AddRemoveFunc(Action removeAction) + { + removeActions.Add(removeAction); + } + + public static void RemoveAllCache() + { + lock (removeActions) + { + foreach (var item in removeActions) + { + item(); + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/IntegrationServices/SerializeService.cs b/类库/SqlSugar/5.0.0.9/IntegrationServices/SerializeService.cs new file mode 100644 index 0000000..93eb13c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/IntegrationServices/SerializeService.cs @@ -0,0 +1,82 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SerializeService : ISerializeService + { + public string SerializeObject(object value) + { + return JsonConvert.SerializeObject(value); + } + + public string SugarSerializeObject(object value) + { + return JsonConvert.SerializeObject(value, new JsonSerializerSettings() + { + ContractResolver = new MyContractResolver() + }); + } + + public T DeserializeObject(string value) + { + var jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; + return JsonConvert.DeserializeObject(value, jSetting); + } + } + public class MyContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver + { + + + public MyContractResolver() + { + + } + + protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) + { + if (type.IsAnonymousType()||type==UtilConstants.ObjType|| type.Namespace=="SqlSugar"|| type.IsClass()==false) + { + return base.CreateProperties(type, memberSerialization); + } + else + { + var list = type.GetProperties() + .Where(x => !x.GetCustomAttributes(true).Any(a => (a is SugarColumn) && ((SugarColumn)a).NoSerialize == true)) + .Select(p => new JsonProperty() + { + PropertyName = p.Name, + PropertyType = p.PropertyType, + Readable = true, + Writable = true, + ValueProvider = base.CreateMemberValueProvider(p) + }).ToList(); + foreach (var item in list) + { + if (UtilMethods.GetUnderType(item.PropertyType) == UtilConstants.DateType) + { + CreateDateProperty(type, item); + } + } + return list; + } + } + + private static void CreateDateProperty(Type type, JsonProperty item) + { + var property = type.GetProperties().Where(it => it.Name == item.PropertyName).First(); + var itemType = UtilMethods.GetUnderType(property); + if (property.GetCustomAttributes(true).Any(it => it is SugarColumn)) + { + var sugarAttribute = (SugarColumn)property.GetCustomAttributes(true).First(it => it is SugarColumn); + item.Converter = new IsoDateTimeConverter() { DateTimeFormat = sugarAttribute.SerializeDateTimeFormat }; + } + } + } + +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IAdo.cs b/类库/SqlSugar/5.0.0.9/Interface/IAdo.cs new file mode 100644 index 0000000..df2cbe4 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IAdo.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial interface IAdo + { + string SqlParameterKeyWord { get; } + IDbConnection Connection { get; set; } + IDbTransaction Transaction { get; set; } + IDataParameter[] ToIDbDataParameter(params SugarParameter[] pars); + SugarParameter[] GetParameters(object obj, PropertyInfo[] propertyInfo = null); + SqlSugarProvider Context { get; set; } + void ExecuteBefore(string sql, SugarParameter[] pars); + void ExecuteAfter(string sql, SugarParameter[] pars); + bool IsEnableLogEvent{get;set;} + + IDataParameterCollection DataReaderParameters { get; set; } + CommandType CommandType { get; set; } + + bool IsDisableMasterSlaveSeparation { get; set; } + bool IsClearParameters { get; set; } + int CommandTimeOut { get; set; } + TimeSpan SqlExecutionTime { get; } + IDbBind DbBind { get; } + void SetCommandToAdapter(IDataAdapter adapter, DbCommand command); + IDataAdapter GetAdapter(); + DbCommand GetCommand(string sql, SugarParameter[] parameters); + + + DataTable GetDataTable(string sql, object parameters); + DataTable GetDataTable(string sql, params SugarParameter[] parameters); + DataTable GetDataTable(string sql, List parameters); + + Task GetDataTableAsync(string sql, object parameters); + Task GetDataTableAsync(string sql, params SugarParameter[] parameters); + Task GetDataTableAsync(string sql, List parameters); + + DataSet GetDataSetAll(string sql, object parameters); + DataSet GetDataSetAll(string sql, params SugarParameter[] parameters); + DataSet GetDataSetAll(string sql, List parameters); + + Task GetDataSetAllAsync(string sql, object parameters); + Task GetDataSetAllAsync(string sql, params SugarParameter[] parameters); + Task GetDataSetAllAsync(string sql, List parameters); + + IDataReader GetDataReader(string sql, object parameters); + IDataReader GetDataReader(string sql, params SugarParameter[] parameters); + IDataReader GetDataReader(string sql, List parameters); + + + Task GetDataReaderAsync(string sql, object parameters); + Task GetDataReaderAsync(string sql, params SugarParameter[] parameters); + Task GetDataReaderAsync(string sql, List parameters); + + + object GetScalar(string sql, object parameters); + object GetScalar(string sql, params SugarParameter[] parameters); + object GetScalar(string sql, List parameters); + + Task GetScalarAsync(string sql, object parameters); + Task GetScalarAsync(string sql, params SugarParameter[] parameters); + Task GetScalarAsync(string sql, List parameters); + + int ExecuteCommand(string sql, object parameters); + int ExecuteCommand(string sql, params SugarParameter[] parameters); + int ExecuteCommand(string sql, List parameters); + + Task ExecuteCommandAsync(string sql, params SugarParameter[] parameters); + Task ExecuteCommandAsync(string sql, object parameters); + Task ExecuteCommandAsync(string sql, List parameters); + + string GetString(string sql, object parameters); + string GetString(string sql, params SugarParameter[] parameters); + string GetString(string sql, List parameters); + Task GetStringAsync(string sql, object parameters); + Task GetStringAsync(string sql, params SugarParameter[] parameters); + Task GetStringAsync(string sql, List parameters); + + + int GetInt(string sql, object pars); + int GetInt(string sql, params SugarParameter[] parameters); + int GetInt(string sql, List parameters); + + Task GetIntAsync(string sql, object pars); + Task GetIntAsync(string sql, params SugarParameter[] parameters); + Task GetIntAsync(string sql, List parameters); + + + long GetLong(string sql, object pars=null); + + Task GetLongAsync(string sql, object pars=null); + + + Double GetDouble(string sql, object parameters); + Double GetDouble(string sql, params SugarParameter[] parameters); + Double GetDouble(string sql, List parameters); + + + Task GetDoubleAsync(string sql, object parameters); + Task GetDoubleAsync(string sql, params SugarParameter[] parameters); + Task GetDoubleAsync(string sql, List parameters); + + + decimal GetDecimal(string sql, object parameters); + decimal GetDecimal(string sql, params SugarParameter[] parameters); + decimal GetDecimal(string sql, List parameters); + + Task GetDecimalAsync(string sql, object parameters); + Task GetDecimalAsync(string sql, params SugarParameter[] parameters); + Task GetDecimalAsync(string sql, List parameters); + + + DateTime GetDateTime(string sql, object parameters); + DateTime GetDateTime(string sql, params SugarParameter[] parameters); + DateTime GetDateTime(string sql, List parameters); + + Task GetDateTimeAsync(string sql, object parameters); + Task GetDateTimeAsync(string sql, params SugarParameter[] parameters); + Task GetDateTimeAsync(string sql, List parameters); + + + Tuple, List> SqlQuery(string sql, object parameters = null); + Tuple, List, List> SqlQuery(string sql, object parameters = null); + Tuple, List, List,List> SqlQuery(string sql, object parameters = null); + Tuple, List, List, List, List> SqlQuery(string sql, object parameters = null); + Tuple, List, List, List, List, List> SqlQuery(string sql, object parameters = null); + Tuple, List, List, List, List, List, List> SqlQuery(string sql, object parameters = null); + + Task, List>> SqlQueryAsync(string sql, object parameters = null); + Task, List, List>> SqlQueryAsync(string sql, object parameters = null); + Task, List, List, List>> SqlQueryAsync(string sql, object parameters = null); + Task, List, List, List, List>> SqlQueryAsync(string sql, object parameters = null); + Task, List, List, List, List, List>> SqlQueryAsync(string sql, object parameters = null); + Task, List, List, List, List, List, List>> SqlQueryAsync(string sql, object parameters = null); + + List SqlQuery(string sql, object parameters = null); + List SqlQuery(string sql, params SugarParameter[] parameters); + List SqlQuery(string sql, List parameters); + + Task> SqlQueryAsync(string sql, object parameters = null); + Task> SqlQueryAsync(string sql, List parameters); + Task> SqlQueryAsync(string sql, params SugarParameter[] parameters); + + T SqlQuerySingle(string sql, object whereObj = null); + T SqlQuerySingle(string sql, params SugarParameter[] parameters); + T SqlQuerySingle(string sql, List parameters); + + Task SqlQuerySingleAsync(string sql, object whereObj = null); + Task SqlQuerySingleAsync(string sql, params SugarParameter[] parameters); + Task SqlQuerySingleAsync(string sql, List parameters); + + + void Dispose(); + void Close(); + void Open(); + void CheckConnection(); + + void BeginTran(); + void BeginTran(IsolationLevel iso); + void BeginTran(string transactionName); + void BeginTran(IsolationLevel iso, string transactionName); + void RollbackTran(); + void CommitTran(); + + DbResult UseTran(Action action, Action errorCallBack = null); + DbResult UseTran(Func action, Action errorCallBack = null); + Task> UseTranAsync(Action action, Action errorCallBack = null); + Task> UseTranAsync(Func action, Action errorCallBack = null); + IAdo UseStoredProcedure(); + + + + #region Obsolete + [Obsolete("Use db.ado.UseStoredProcedure().MethodName()")] + void UseStoredProcedure(Action action); + [Obsolete("Use db.ado.UseStoredProcedure().MethodName()")] + T UseStoredProcedure(Func action); + [Obsolete("Use SqlQuery(sql)")] + dynamic SqlQueryDynamic(string sql, object whereObj = null); + [Obsolete("Use SqlQuery(sql)")] + dynamic SqlQueryDynamic(string sql, params SugarParameter[] parameters); + [Obsolete("Use SqlQuery(sql)")] + dynamic SqlQueryDynamic(string sql, List parameters); + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/ICodeFirst.cs b/类库/SqlSugar/5.0.0.9/Interface/ICodeFirst.cs new file mode 100644 index 0000000..46b7af0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/ICodeFirst.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial interface ICodeFirst + { + SqlSugarProvider Context { get; set; } + ICodeFirst BackupTable(int maxBackupDataRows = int.MaxValue); + ICodeFirst SetStringDefaultLength(int length); + void InitTables(string entitiesNamespace); + void InitTables(string[] entitiesNamespaces); + void InitTables(params Type[] entityTypes); + void InitTables(Type entityType); + void InitTables(); + void InitTables(); + void InitTables(); + void InitTables(); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IContextMethods.cs b/类库/SqlSugar/5.0.0.9/Interface/IContextMethods.cs new file mode 100644 index 0000000..4cd026c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IContextMethods.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Dynamic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial interface IContextMethods + { + SqlSugarProvider Context { get; set; } + ExpandoObject DataReaderToExpandoObject(IDataReader reader); + List DataReaderToExpandoObjectList(IDataReader reader); + Task> DataReaderToExpandoObjectListAsync(IDataReader dataReader); + List DataReaderToExpandoObjectListNoUsing(IDataReader reader); + Task> DataReaderToExpandoObjectListAsyncNoUsing(IDataReader dataReader); + List DataReaderToList(IDataReader reader); + List DataReaderToListNoUsing(IDataReader reader); + Task> DataReaderToListAsync(IDataReader dataReader); + Task> DataReaderToListAsyncNoUsing(IDataReader dataReader); + string SerializeObject(object value); + string SerializeObject(object value, Type type); + T DeserializeObject(string value); + T TranslateCopy(T sourceObject); + SqlSugarProvider CopyContext(bool isCopyEvents = false); + dynamic DataTableToDynamic(DataTable table); + List DataTableToList(DataTable table); + Dictionary DataTableToDictionary(DataTable table); + ICacheService GetReflectionInoCacheInstance(); + void RemoveCacheAll(); + void RemoveCacheAll(); + void RemoveCache(string key); + void PageEach(IEnumerable pageItems, int pageSize, Action> action); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IDMLBuilder.cs b/类库/SqlSugar/5.0.0.9/Interface/IDMLBuilder.cs new file mode 100644 index 0000000..16e6f8b --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IDMLBuilder.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public partial interface IDMLBuilder + { + string SqlTemplate { get; } + List Parameters { get; set; } + SqlSugarProvider Context { get; set; } + StringBuilder sql { get; set; } + string ToSqlString(); + void Clear(); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IDbBind.cs b/类库/SqlSugar/5.0.0.9/Interface/IDbBind.cs new file mode 100644 index 0000000..14e99c0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IDbBind.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial interface IDbBind + { + SqlSugarProvider Context { get; set; } + List GuidThrow { get; } + List IntThrow { get; } + List StringThrow { get; } + List DecimalThrow { get; } + List DoubleThrow { get; } + List DateThrow { get; } + List ShortThrow { get; } + string GetPropertyTypeName(string dbTypeName); + string GetConvertString(string dbTypeName); + string GetDbTypeName(string csharpTypeName); + string GetCsharpTypeName(string dbTypeName); + List> MappingTypes { get; } + List DataReaderToList(Type type, IDataReader reader); + Task> DataReaderToListAsync(Type entityType, IDataReader dataReader); + List DataReaderToListNoUsing(Type type, IDataReader reader); + Task> DataReaderToListNoUsingAsync(Type type, IDataReader reader); + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IDbFirst.cs b/类库/SqlSugar/5.0.0.9/Interface/IDbFirst.cs new file mode 100644 index 0000000..53978fc --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IDbFirst.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial interface IDbFirst + { + ISqlSugarClient Context { get; set; } + IDbFirst SettingClassTemplate(Func func); + IDbFirst SettingClassDescriptionTemplate(Func func); + IDbFirst SettingPropertyTemplate(Func func); + IDbFirst SettingPropertyDescriptionTemplate(Func func); + IDbFirst SettingConstructorTemplate(Func func); + IDbFirst SettingNamespaceTemplate(Func func); + RazorFirst UseRazorAnalysis(string razorClassString, string classNamespace = "Models"); + IDbFirst IsCreateAttribute(bool isCreateAttribute = true); + IDbFirst IsCreateDefaultValue(bool isCreateDefaultValue=true); + IDbFirst Where(params string[] objectNames); + IDbFirst Where(Func func); + IDbFirst Where(DbObjectType dbObjectType); + void CreateClassFile(string directoryPath, string nameSpace = "Models"); + Dictionary ToClassStringList(string nameSpace = "Models"); + void Init(); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IDbMaintenance.cs b/类库/SqlSugar/5.0.0.9/Interface/IDbMaintenance.cs new file mode 100644 index 0000000..0cb175a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IDbMaintenance.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial interface IDbMaintenance + { + SqlSugarProvider Context { get; set; } + + #region DML + List GetDataBaseList(SqlSugarClient db); + List GetViewInfoList(bool isCache=true); + List GetTableInfoList(bool isCache=true); + List GetColumnInfosByTableName(string tableName,bool isCache=true); + List GetIsIdentities(string tableName); + List GetPrimaries(string tableName); + #endregion + + #region Check + bool IsAnyTable(string tableName, bool isCache = true); + bool IsAnyColumn(string tableName, string column); + bool IsPrimaryKey(string tableName, string column); + bool IsIdentity(string tableName, string column); + bool IsAnyConstraint(string ConstraintName); + bool IsAnySystemTablePermissions(); + #endregion + + #region DDL + bool AddDefaultValue(string tableName,string columnName,string defaultValue); + bool CreateIndex(string tableName, string [] columnNames); + bool DropTable(string tableName); + bool TruncateTable(string tableName); + bool TruncateTable(); + bool CreateTable(string tableName, List columns,bool isCreatePrimaryKey=true); + bool AddColumn(string tableName, DbColumnInfo column); + bool UpdateColumn(string tableName, DbColumnInfo column); + bool AddPrimaryKey(string tableName,string columnName); + bool AddPrimaryKeys(string tableName, string [] columnNames); + bool DropConstraint(string tableName, string constraintName); + bool BackupDataBase(string databaseName,string fullFileName); + bool BackupTable(string oldTableName, string newTableName, int maxBackupDataRows = int.MaxValue); + bool DropColumn(string tableName,string columnName); + bool RenameColumn(string tableName, string oldColumnName, string newColumnName); + bool AddRemark(EntityInfo entity); + void AddIndex(EntityInfo entityInfo); + void AddDefaultValue(EntityInfo entityInfo); + bool IsAnyDefaultValue(string tableName, string columnName); + bool IsAnyIndex(string indexName); + bool AddColumnRemark(string columnName,string tableName,string description); + bool DeleteColumnRemark(string columnName, string tableName); + bool IsAnyColumnRemark(string columnName, string tableName); + bool AddTableRemark( string tableName, string description); + bool DeleteTableRemark(string tableName); + bool IsAnyTableRemark(string tableName); + bool RenameTable(string oldTableName,string newTableName); + /// + ///by current connection string + /// + /// + /// + bool CreateDatabase(string databaseDirectory = null); + /// + /// by databaseName + /// + /// + /// + /// + bool CreateDatabase(string databaseName,string databaseDirectory = null); + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IDeleteable.cs b/类库/SqlSugar/5.0.0.9/Interface/IDeleteable.cs new file mode 100644 index 0000000..b292d6d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IDeleteable.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IDeleteable where T : class, new() + { + DeleteBuilder DeleteBuilder { get; set; } + int ExecuteCommand(); + bool ExecuteCommandHasChange(); + Task ExecuteCommandAsync(); + Task ExecuteCommandHasChangeAsync(); + IDeleteable AS(string tableName); + IDeleteable With(string lockString); + IDeleteable Where(T deleteObj); + IDeleteable Where(Expression> expression); + IDeleteable Where(List deleteObjs); + IDeleteable In(PkType primaryKeyValue); + IDeleteable In(PkType[] primaryKeyValues); + IDeleteable In(List primaryKeyValues); + IDeleteable In(Expression> inField,PkType primaryKeyValue); + IDeleteable In(Expression> inField,PkType[] primaryKeyValues); + IDeleteable In(Expression> inField,List primaryKeyValues); + IDeleteable Where(string whereString,object parameters=null); + IDeleteable Where(string whereString, SugarParameter parameter); + IDeleteable Where(string whereString, SugarParameter[] parameters); + IDeleteable Where(string whereString, List parameters); + IDeleteable EnableDiffLogEvent(object businessData = null); + IDeleteable RemoveDataCache(); + KeyValuePair> ToSql(); + void AddQueue(); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IFilter.cs b/类库/SqlSugar/5.0.0.9/Interface/IFilter.cs new file mode 100644 index 0000000..265a163 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IFilter.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public interface IFilter + { + IFilter Add(SqlFilterItem filter); + void Remove(string filterName); + List GeFilterList { get; } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/ILambdaExpressions.cs b/类库/SqlSugar/5.0.0.9/Interface/ILambdaExpressions.cs new file mode 100644 index 0000000..4cc0b04 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/ILambdaExpressions.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial interface ILambdaExpressions + { + MappingColumnList MappingColumns { get; set; } + MappingTableList MappingTables { get; set; } + IgnoreColumnList IgnoreComumnList { get; set; } + List SqlFuncServices { get; set; } + + List JoinQueryInfos { get; set; } + bool IsSingle { get; set; } + SqlSugarProvider Context { get; set; } + IDbMethods DbMehtods { get; set; } + Expression Expression { get; set; } + int Index { get; set; } + int ParameterIndex { get; set; } + List Parameters { get; set; } + ExpressionResult Result { get; set; } + string SqlParameterKeyWord { get; } + string SingleTableNameSubqueryShortName { get; set; } + Action InitMappingInfo { get; set; } + Action RefreshMapping { get; set; } + + string GetAsString(string fieldName, string fieldValue); + void Resolve(Expression expression, ResolveExpressType resolveType); + void Clear(); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IQueryable.cs b/类库/SqlSugar/5.0.0.9/Interface/IQueryable.cs new file mode 100644 index 0000000..83573d0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IQueryable.cs @@ -0,0 +1,1228 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial interface ISugarQueryable + { + SqlSugarProvider Context { get; set; } + ISqlBuilder SqlBuilder { get; set; } + QueryBuilder QueryBuilder { get; set; } + ISugarQueryable Clone(); + ISugarQueryable AS(string tableName); + ISugarQueryable AS(string tableName); + ISugarQueryable With(string withString); + ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + ISugarQueryable Mapper(Action mapperAction); + ISugarQueryable Mapper(Action> mapperAction); + ISugarQueryable Mapper(Expression> mapperObject, Expression> mainField, Expression> childField); + ISugarQueryable Mapper(Expression>> mapperObject, Expression> mainField, Expression> childField); + ISugarQueryable Mapper(Expression> mapperObject, Expression> mapperField); + ISugarQueryable Mapper(Expression>> mapperObject, Expression> mapperField); + ISugarQueryable AddParameters(object parameters); + ISugarQueryable AddParameters(SugarParameter[] parameters); + ISugarQueryable AddParameters(List parameters); + ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + ISugarQueryable WhereClass(ClassType whereClass,bool ignoreDefaultValue=false)where ClassType: class,new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + ISugarQueryable WhereClass(List whereClassList,bool ignoreDefaultValue = false) where ClassType : class, new(); + + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(string whereString, object parameters = null); + ISugarQueryable Where(List conditionalModels); + + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(string whereString, object parameters = null); + + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + T InSingle(object pkValue); + Task InSingleAsync(object pkValue); + ISugarQueryable In(params TParamter[] pkValues); + ISugarQueryable In(string InFieldName, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(List pkValues); + ISugarQueryable In(string InFieldName, List inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable OrderBy(string orderFileds); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + + + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(string groupFileds); + + ISugarQueryable PartitionBy(Expression> expression); + ISugarQueryable PartitionBy(string groupFileds); + + ISugarQueryable Skip(int index); + ISugarQueryable Take(int num); + ISugarQueryable Distinct(); + + T Single(); + Task SingleAsync(); + T Single(Expression> expression); + Task SingleAsync(Expression> expression); + + T First(); + Task FirstAsync(); + T First(Expression> expression); + Task FirstAsync(Expression> expression); + + bool Any(Expression> expression); + Task AnyAsync(Expression> expression); + bool Any(); + Task AnyAsync(); + + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(); + ISugarQueryable Select(string select); + ISugarQueryable Select(string select); + ISugarQueryable MergeTable(); + + int Count(); + Task CountAsync(); + int Count(Expression> expression); + Task CountAsync(Expression> expression); + TResult Max(string maxField); + Task MaxAsync(string maxField); + TResult Max(Expression> expression); + Task MaxAsync(Expression> expression); + TResult Min(string minField); + Task MinAsync(string minField); + TResult Min(Expression> expression); + Task MinAsync(Expression> expression); + TResult Sum(string sumField); + Task SumAsync(string sumField); + TResult Sum(Expression> expression); + Task SumAsync(Expression> expression); + TResult Avg(string avgField); + Task AvgAsync(string avgField); + TResult Avg(Expression> expression); + Task AvgAsync(Expression> expression); + + List ToList(); + T[] ToArray(); + Task> ToListAsync(); + + string ToJson(); + Task ToJsonAsync(); + string ToJsonPage(int pageIndex, int pageSize); + Task ToJsonPageAsync(int pageIndex, int pageSize); + string ToJsonPage(int pageIndex, int pageSize, ref int totalNumber); + Task ToJsonPageAsync(int pageIndex, int pageSize, RefAsync totalNumber); + KeyValuePair> ToSql(); + + + DataTable ToDataTable(); + Task ToDataTableAsync(); + DataTable ToDataTablePage(int pageIndex, int pageSize); + Task ToDataTablePageAsync(int pageIndex, int pageSize); + DataTable ToDataTablePage(int pageIndex, int pageSize, ref int totalNumber); + DataTable ToDataTablePage(int pageIndex, int pageSize, ref int totalNumber,ref int totalPage); + Task ToDataTablePageAsync(int pageIndex, int pageSize, RefAsync totalNumber); + + List ToPageList(int pageIndex, int pageSize); + Task> ToPageListAsync(int pageIndex, int pageSize); + List ToPageList(int pageIndex, int pageSize, ref int totalNumber); + List ToPageList(int pageIndex, int pageSize, ref int totalNumber,ref int totalPage); + Task> ToPageListAsync(int pageIndex, int pageSize, RefAsync totalNumber); + ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + string ToClassString(string className); + void Clear(); + void AddQueue(); + ISugarQueryable IgnoreColumns(Expression> columns); + ISugarQueryable IgnoreColumns(params string[] columns); + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object whereObj = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj = null); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(string orderFileds); + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + new ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + new ISugarQueryable Having(string whereString, object whereObj = null); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + new ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + new ISugarQueryable Having(string whereString, object parameters = null); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + new ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + new ISugarQueryable Having(string whereString, object parameters = null); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + + #region 9-12 + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + #endregion + } + #endregion +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/ISaveable.cs b/类库/SqlSugar/5.0.0.9/Interface/ISaveable.cs new file mode 100644 index 0000000..2a515fc --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/ISaveable.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial interface ISaveable where T : class, new() + { + Task ExecuteCommandAsync(); + Task ExecuteReturnEntityAsync(); + + Task> ExecuteReturnListAsync(); + int ExecuteCommand(); + T ExecuteReturnEntity(); + List ExecuteReturnList(); + ISaveable InsertColumns(Expression> columns); + ISaveable InsertIgnoreColumns(Expression> columns); + ISaveable UpdateColumns(Expression> columns); + ISaveable UpdateIgnoreColumns(Expression> columns); + ISaveable UpdateWhereColumns(Expression> columns); + ISaveable EnableDiffLogEvent(object businessData = null); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/ISqlBuilder.cs b/类库/SqlSugar/5.0.0.9/Interface/ISqlBuilder.cs new file mode 100644 index 0000000..ce13741 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/ISqlBuilder.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial interface ISqlBuilder + { + SqlSugarProvider Context { get; set; } + CommandType CommandType { get; set; } + String AppendWhereOrAnd(bool isWhere, string sqlString); + string AppendHaving(string sqlString); + + SqlQueryBuilder SqlQueryBuilder { get; set; } + QueryBuilder QueryBuilder { get; set; } + InsertBuilder InsertBuilder { get; set; } + DeleteBuilder DeleteBuilder { get; set; } + UpdateBuilder UpdateBuilder { get; set; } + + string SqlParameterKeyWord { get; } + string SqlFalse { get; } + string SqlDateNow { get; } + string FullSqlDateNow { get; } + string SqlTranslationLeft { get; } + string SqlTranslationRight { get; } + string SqlSelectAll { get; } + + string GetTranslationTableName(string name); + string GetTranslationColumnName(string entityName, string propertyName); + string GetTranslationColumnName(string propertyName); + string GetNoTranslationColumnName(string name); + string GetPackTable(string sql,string shortName); + string GetDefaultShortName(); + + string GetWhere(string fieldName, string conditionalType, int? parameterIndex = null); + string GetUnionAllSql(List sqlList); + string GetUnionSql(List sqlList); + void RepairReplicationParameters(ref string appendSql, SugarParameter[] parameters, int addIndex); + KeyValuePair ConditionalModelToSql(List models, int beginIndex = 0); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/ISqlSugarClient.cs b/类库/SqlSugar/5.0.0.9/Interface/ISqlSugarClient.cs new file mode 100644 index 0000000..4b550b6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/ISqlSugarClient.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface ISqlSugarClient: IDisposable + { + MappingTableList MappingTables { get; set; } + MappingColumnList MappingColumns { get; set; } + IgnoreColumnList IgnoreColumns { get; set; } + IgnoreColumnList IgnoreInsertColumns { get; set; } + Dictionary TempItems { get; set; } + + + bool IsSystemTablesConfig { get; } + Guid ContextID { get; set; } + ConnectionConfig CurrentConnectionConfig { get; set; } + + + IAdo Ado { get; } + AopProvider Aop { get; } + ICodeFirst CodeFirst { get; } + + + IDbFirst DbFirst { get; } + IDbMaintenance DbMaintenance { get; } + EntityMaintenance EntityMaintenance { get; set; } + QueryFilterProvider QueryFilter { get; set; } + IContextMethods Utilities { get; set; } + + + #region Deleteable + IDeleteable Deleteable() where T : class, new(); + IDeleteable Deleteable(dynamic primaryKeyValue) where T : class, new(); + IDeleteable Deleteable(dynamic[] primaryKeyValues) where T : class, new(); + IDeleteable Deleteable(Expression> expression) where T : class, new(); + IDeleteable Deleteable(List pkValue) where T : class, new(); + IDeleteable Deleteable(List deleteObjs) where T : class, new(); + IDeleteable Deleteable(T deleteObj) where T : class, new(); + #endregion + + #region Other methods + DateTime GetDate(); + SimpleClient GetSimpleClient(); + SimpleClient GetSimpleClient() where T : class, new(); + void InitMappingInfo(Type type); + void InitMappingInfo(); + void Open(); + void Close(); + #endregion + + #region Insertable + IInsertable Insertable(Dictionary columnDictionary) where T : class, new(); + IInsertable Insertable(dynamic insertDynamicObject) where T : class, new(); + IInsertable Insertable(List insertObjs) where T : class, new(); + IInsertable Insertable(T insertObj) where T : class, new(); + IInsertable Insertable(T[] insertObjs) where T : class, new(); + #endregion + + #region Queryable + ISugarQueryable SqlQueryable(string sql) where T : class, new(); + ISugarQueryable Queryable(string tableName, string shortName); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression) where T : class, new(); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(Expression> joinExpression); + ISugarQueryable Queryable(ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, Expression> joinExpression) + where T : class, new() + where T2 : class, new(); + ISugarQueryable Queryable(ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, JoinType joinType, Expression> joinExpression) + where T : class, new() + where T2 : class, new(); + ISugarQueryable Queryable(); + ISugarQueryable Queryable(ISugarQueryable queryable) where T : class, new(); + ISugarQueryable Queryable(string shortName); + #endregion + + #region Saveable + ISaveable Saveable(List saveObjects) where T : class, new(); + ISaveable Saveable(T saveObject) where T : class, new(); + #endregion + + #region Queue + QueueList Queues { get; set; } + void AddQueue(string sql, object parsmeters = null); + void AddQueue(string sql, List parsmeters); + void AddQueue(string sql, SugarParameter parsmeter); + int SaveQueues(bool isTran = true); + Tuple, List, List, List, List, List, List> SaveQueues(bool isTran = true); + Tuple, List, List, List, List, List> SaveQueues(bool isTran = true); + Tuple, List, List, List, List> SaveQueues(bool isTran = true); + Tuple, List, List, List> SaveQueues(bool isTran = true); + Tuple, List, List> SaveQueues(bool isTran = true); + Tuple, List> SaveQueues(bool isTran = true); + List SaveQueues(bool isTran = true); + Task SaveQueuesAsync(bool isTran = true); + Task, List, List, List, List, List, List>> SaveQueuesAsync(bool isTran = true); + Task, List, List, List, List, List>> SaveQueuesAsync(bool isTran = true); + Task, List, List, List, List>> SaveQueuesAsync(bool isTran = true); + Task, List, List, List>> SaveQueuesAsync(bool isTran = true); + Task, List, List>> SaveQueuesAsync(bool isTran = true); + Task, List>> SaveQueuesAsync(bool isTran = true); + Task> SaveQueuesAsync(bool isTran = true); + #endregion + + #region Union + ISugarQueryable Union(List> queryables) where T : class, new(); + ISugarQueryable Union(params ISugarQueryable[] queryables) where T : class, new(); + ISugarQueryable UnionAll(List> queryables) where T : class, new(); + ISugarQueryable UnionAll(params ISugarQueryable[] queryables) where T : class, new(); + #endregion + + #region Updateable + IUpdateable Updateable() where T : class, new(); + IUpdateable Updateable(Dictionary columnDictionary) where T : class, new(); + IUpdateable Updateable(dynamic updateDynamicObject) where T : class, new(); + IUpdateable Updateable(Expression> columns) where T : class, new(); + IUpdateable Updateable(Expression> columns) where T : class, new(); + IUpdateable Updateable(List UpdateObjs) where T : class, new(); + IUpdateable Updateable(T UpdateObj) where T : class, new(); + IUpdateable Updateable(T[] UpdateObjs) where T : class, new(); + #endregion + + #region Obsolete + [Obsolete("use Utilities")] + IContextMethods RewritableMethods { get; set; } + [Obsolete("use GetSimpleClient()")] + SimpleClient SimpleClient { get; } + [Obsolete("use EntityMaintenance")] + EntityMaintenance EntityProvider { get; set; } + #endregion + } +} \ No newline at end of file diff --git a/类库/SqlSugar/5.0.0.9/Interface/ITenant.cs b/类库/SqlSugar/5.0.0.9/Interface/ITenant.cs new file mode 100644 index 0000000..3691805 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/ITenant.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface ITenant + { + void BeginTran(); + void CommitTran(); + void RollbackTran(); + void ChangeDatabase(string configId); + void ChangeDatabase(Func changeExpression); + DbResult UseTran(Action action, Action errorCallBack = null); + Task> UseTranAsync(Action action, Action errorCallBack = null); + DbResult UseTran(Func action, Action errorCallBack = null); + + Task> UseTranAsync(Func action, Action errorCallBack = null); + + void Close(); + void Open(); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/IUpdateable.cs b/类库/SqlSugar/5.0.0.9/Interface/IUpdateable.cs new file mode 100644 index 0000000..489c962 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/IUpdateable.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IUpdateable where T : class, new() + { + UpdateBuilder UpdateBuilder { get; set; } + bool UpdateParameterIsNull { get; set; } + + int ExecuteCommand(); + bool ExecuteCommandHasChange(); + Task ExecuteCommandAsync(); + Task ExecuteCommandHasChangeAsync(); + + + IUpdateable AS(string tableName); + IUpdateable With(string lockString); + + + IUpdateable Where(Expression> expression); + IUpdateable Where(string whereSql,object parameters=null); + /// + /// + /// + /// + /// for example : = + /// + /// + IUpdateable Where(string fieldName, string conditionalType, object fieldValue); + + + + /// + /// Non primary key entity update function,.WhereColumns(it=>new{ it.Id }) + /// + /// + /// + IUpdateable WhereColumns(Expression> columns); + IUpdateable WhereColumns(string columnName); + IUpdateable WhereColumns(string [] columnNames); + + /// + /// .UpdateColumns(it=>new{ it.Name,it.Price}) + /// + /// + /// + IUpdateable UpdateColumns(Expression> columns); + IUpdateable UpdateColumns(params string[] columns); + + + /// + ///.SetColumns(it=>it.Name=="a") + /// + /// + /// + IUpdateable SetColumns(Expression> columns); + /// + /// .SetColumns(it=> new class() { it.Name="a",it.Price=0}) + /// + /// + /// + IUpdateable SetColumns(Expression> columns); + + + + IUpdateable UpdateColumnsIF(bool isUpdateColumns,Expression> columns); + IUpdateable UpdateColumnsIF(bool isUpdateColumns, params string[] columns); + + + IUpdateable SetColumnsIF(bool isUpdateColumns,Expression> columns); + IUpdateable SetColumnsIF(bool isUpdateColumns, Expression> columns); + + + + IUpdateable IgnoreColumns(bool ignoreAllNullColumns, bool isOffIdentity = false, bool ignoreAllDefaultValue = false); + IUpdateable IgnoreColumns(Expression> columns); + IUpdateable IgnoreColumns(params string[] columns); + + + + IUpdateable IsEnableUpdateVersionValidation(); + IUpdateable EnableDiffLogEvent(object businessData = null); + IUpdateable ReSetValue(Expression> setValueExpression); + IUpdateable RemoveDataCache(); + KeyValuePair> ToSql(); + void AddQueue(); + + + #region delete obj + + [Obsolete("Use IUpdateable UpdateColumns(string [] columns)")] + IUpdateable UpdateColumns(Func updateColumMethod); + [Obsolete("Use IUpdateable IgnoreColumns(string [] columns)")] + IUpdateable IgnoreColumns(Func ignoreColumMethod); + [Obsolete("Use IUpdateable IgnoreColumns(bool ignoreAllNullColumns, bool isOffIdentity = false);")] + IUpdateable Where(bool isNoUpdateNull, bool IsOffIdentity = false); + [Obsolete("Use IUpdateable UpdateColumnsIF(bool isUpdateColumns,string [] columns")] + IUpdateable UpdateColumnsIF(bool isUpdateColumns, Func updateColumMethod); + [Obsolete("Use SetColumns(Expression> columns)")] + IUpdateable UpdateColumns(Expression> columns); + [Obsolete("Use SetColumns(Expression> columns")] + IUpdateable UpdateColumns(Expression> columns); + + [Obsolete("Use SetColumnsIF(bool isUpdateColumns, Expression> columns)")] + IUpdateable UpdateColumnsIF(bool isUpdateColumns, Expression> columns); + [Obsolete("Use SetColumnsIF(bool isUpdateColumns, Expression> columns")] + IUpdateable UpdateColumnsIF(bool isUpdateColumns, Expression> columns); + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Interface/Insertable.cs b/类库/SqlSugar/5.0.0.9/Interface/Insertable.cs new file mode 100644 index 0000000..f563f34 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Interface/Insertable.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IInsertable + { + InsertBuilder InsertBuilder { get; set; } + int ExecuteCommand(); + Task ExecuteCommandAsync(); + int ExecuteReturnIdentity(); + Task ExecuteReturnIdentityAsync(); + T ExecuteReturnEntity(); + Task ExecuteReturnEntityAsync(); + bool ExecuteCommandIdentityIntoEntity(); + Task ExecuteCommandIdentityIntoEntityAsync(); + long ExecuteReturnBigIdentity(); + Task ExecuteReturnBigIdentityAsync(); + IInsertable AS(string tableName); + IInsertable With(string lockString); + IInsertable InsertColumns(Expression> columns); + IInsertable InsertColumns(params string[] columns); + + IInsertable IgnoreColumns(Expression> columns); + IInsertable IgnoreColumns(params string[]columns); + IInsertable IgnoreColumns(bool ignoreNullColumn, bool isOffIdentity = false); + + + IInsertable EnableDiffLogEvent(object businessData = null); + IInsertable RemoveDataCache(); + KeyValuePair> ToSql(); + void AddQueue(); + + #region Obsolete + [Obsolete("use IgnoreColumns(string[] columns")] + + IInsertable IgnoreColumns(Func ignoreColumMethod); + [Obsolete("use InsertColumns(string[] columns")] + IInsertable InsertColumns(Func insertColumMethod); + [Obsolete("use IgnoreColumns(bool isNoInsertNull, bool isOffIdentity = false)")] + IInsertable Where(bool ignoreNullColumn, bool isOffIdentity = false); + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/NuGet.exe b/类库/SqlSugar/5.0.0.9/NuGet.exe new file mode 100644 index 0000000..6bb79fe Binary files /dev/null and b/类库/SqlSugar/5.0.0.9/NuGet.exe differ diff --git a/类库/SqlSugar/5.0.0.9/Properties/AssemblyInfo.cs b/类库/SqlSugar/5.0.0.9/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c3b64f0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SqlSugar4")] +[assembly: AssemblyDescription("author sunkaixuan Apache Licence 2.0")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SqlSugar 4")] +[assembly: AssemblyCopyright("Copyright © 2016")] + + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c7c121b9-80c6-4caf-aadd-d85118ad1cf2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("5.0.0.9")] +[assembly: AssemblyFileVersion("5.0.0.9")] diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/CodeFirst/MySqlCodeFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/CodeFirst/MySqlCodeFirst.cs new file mode 100644 index 0000000..1de23e6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/CodeFirst/MySqlCodeFirst.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MySqlCodeFirst : CodeFirstProvider + { + public override void NoExistLogic(EntityInfo entityInfo) + { + var tableName = GetTableName(entityInfo); + //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimarykey ? 0 : 1)) + { + if (item.IsIgnore) + continue; + DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item); + columns.Add(dbColumnInfo); + } + } + this.Context.DbMaintenance.CreateTable(tableName, columns,true); + } + protected override DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + var propertyType = UtilMethods.GetUnderType(item.PropertyInfo); + var result = new DbColumnInfo() + { + TableId = entityInfo.Columns.IndexOf(item), + DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName, + IsPrimarykey = item.IsPrimarykey, + IsIdentity = item.IsIdentity, + TableName = tableName, + IsNullable = item.IsNullable, + DefaultValue = item.DefaultValue, + ColumnDescription = item.ColumnDescription, + Length = item.Length, + DecimalDigits=item.DecimalDigits + }; + GetDbType(item, propertyType, result); + if (result.DataType.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.Length == 0) + { + result.Length = 1; + } + return result; + } + + protected override void ConvertColumns(List dbColumns) + { + foreach (var item in dbColumns) + { + if (item.DataType == "DateTime") + { + item.Length = 0; + } + } + } + + protected override void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + if (!item.IsPrimarykey) + this.Context.DbMaintenance.DropConstraint(tableName,null); + if (item.IsPrimarykey) + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + + internal DbColumnInfo GetEntityColumnToDbColumn(EntityInfo entity, string dbTableName, EntityColumnInfo item) + { + return EntityColumnToDbColumn(entity,dbTableName,item); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/DbBind/MySqlDbBind.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/DbBind/MySqlDbBind.cs new file mode 100644 index 0000000..c85e426 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/DbBind/MySqlDbBind.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SqlSugar +{ + public class MySqlDbBind : DbBindProvider + { + public override string GetDbTypeName(string csharpTypeName) + { + if (csharpTypeName == UtilConstants.ByteArrayType.Name) + { + return "blob"; + } + if (csharpTypeName == "Int32") + csharpTypeName = "int"; + if (csharpTypeName == "Int16") + csharpTypeName = "short"; + if (csharpTypeName == "Int64") + csharpTypeName = "long"; + if (csharpTypeName == "Boolean") + csharpTypeName = "bool"; + var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)); + return mappings.HasValue() ? mappings.First().Key : "varchar"; + } + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null && extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>(){ + + new KeyValuePair("int",CSharpDataType.@int), + new KeyValuePair("mediumint",CSharpDataType.@int), + new KeyValuePair("integer",CSharpDataType.@int), + + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("text",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("enum",CSharpDataType.@string), + new KeyValuePair("mediumtext",CSharpDataType.@string), + new KeyValuePair("tinytext",CSharpDataType.@string), + new KeyValuePair("longtext",CSharpDataType.@string), + + new KeyValuePair("tinyint",CSharpDataType.@byte), + new KeyValuePair("smallint",CSharpDataType.@short), + new KeyValuePair("bigint",CSharpDataType.@long), + new KeyValuePair("bit",CSharpDataType.@bool), + new KeyValuePair("real",CSharpDataType.@double), + new KeyValuePair("double",CSharpDataType.@double), + new KeyValuePair("float",CSharpDataType.@float), + new KeyValuePair("float",CSharpDataType.Single), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("numeric",CSharpDataType.@decimal), + new KeyValuePair("year",CSharpDataType.@int), + + new KeyValuePair("datetime",CSharpDataType.DateTime), + new KeyValuePair("timestamp",CSharpDataType.DateTime), + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("time",CSharpDataType.DateTime), + + new KeyValuePair("blob",CSharpDataType.byteArray), + new KeyValuePair("longblob",CSharpDataType.byteArray), + new KeyValuePair("tinyblob",CSharpDataType.byteArray), + new KeyValuePair("varbinary",CSharpDataType.byteArray), + new KeyValuePair("binary",CSharpDataType.byteArray), + new KeyValuePair("multipoint",CSharpDataType.byteArray), + new KeyValuePair("geometry",CSharpDataType.byteArray), + new KeyValuePair("multilinestring",CSharpDataType.byteArray), + new KeyValuePair("polygon",CSharpDataType.byteArray), + new KeyValuePair("mediumblob",CSharpDataType.byteArray), + + new KeyValuePair("varchar",CSharpDataType.Guid), + }; + public override List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte" }; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/DbFirst/MySqlDbFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/DbFirst/MySqlDbFirst.cs new file mode 100644 index 0000000..6ecb3bb --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/DbFirst/MySqlDbFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MySqlDbFirst : DbFirstProvider + { + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/DbMaintenance/MySqlDbMaintenance.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/DbMaintenance/MySqlDbMaintenance.cs new file mode 100644 index 0000000..a9039d0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/DbMaintenance/MySqlDbMaintenance.cs @@ -0,0 +1,460 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MySqlDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetDataBaseSql + { + get + { + return "SHOW DATABASES"; + } + } + protected override string GetColumnInfosByTableNameSql + { + get + { + string sql = @"SELECT + 0 as TableId, + TABLE_NAME as TableName, + column_name AS DbColumnName, + CASE WHEN left(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)-1)='' THEN COLUMN_TYPE ELSE left(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)-1) END AS DataType, + CAST(SUBSTRING(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)+1,LOCATE(')',COLUMN_TYPE)-LOCATE('(',COLUMN_TYPE)-1) AS signed) AS Length, + column_default AS `DefaultValue`, + column_comment AS `ColumnDescription`, + CASE WHEN COLUMN_KEY = 'PRI' + THEN true ELSE false END AS `IsPrimaryKey`, + CASE WHEN EXTRA='auto_increment' THEN true ELSE false END as IsIdentity, + CASE WHEN is_nullable = 'YES' + THEN true ELSE false END AS `IsNullable` + FROM + Information_schema.columns where TABLE_NAME='{0}' and TABLE_SCHEMA=(select database()) ORDER BY TABLE_NAME"; + return sql; + } + } + protected override string GetTableInfoListSql + { + get + { + return @"select TABLE_NAME as Name,TABLE_COMMENT as Description from information_schema.tables + where TABLE_SCHEMA=(select database()) AND TABLE_TYPE='BASE TABLE'"; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"select TABLE_NAME as Name,TABLE_COMMENT as Description from information_schema.tables + where TABLE_SCHEMA=(select database()) AND TABLE_TYPE='VIEW' + "; + } + } + #endregion + + #region DDL + protected override string CreateDataBaseSql + { + get + { + return "CREATE DATABASE {0}"; + } + } + protected override string AddPrimaryKeySql + { + get + { + return "ALTER TABLE {0} ADD PRIMARY KEY({2}) /*{1}*/"; + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD {1} {2}{3} {4} {5} {6}"; + } + } + protected override string AlterColumnToTableSql + { + get + { + // return "ALTER TABLE {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}"; + return "alter table {0} change column {1} {1} {2}{3} {4} {5} {6}"; + } + } + protected override string BackupDataBaseSql + { + get + { + return "mysqldump.exe {0} -uroot -p > {1} "; + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1} $PrimaryKey)"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "TRUNCATE TABLE {0}"; + } + } + protected override string BackupTableSql + { + get + { + return "Create table {1} (Select * from {2} LIMIT 0,{0})"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + return "ALTER TABLE {0} DROP COLUMN {1}"; + } + } + protected override string DropConstraintSql + { + get + { + return "ALTER TABLE {0} drop primary key;"; + } + } + protected override string RenameColumnSql + { + get + { + return "alter table {0} change column {1} {2}"; + } + } + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select 1 from Information_schema.columns limit 0,1"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return "DEFAULT NULL"; + } + } + protected override string CreateTableNotNull + { + get + { + return "NOT NULL"; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return "AUTO_INCREMENT"; + } + } + + protected override string AddColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string DeleteColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string IsAnyColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string AddTableRemarkSql + { + get + { + return "ALTER TABLE {0} COMMENT='{1}';"; + } + } + + protected override string DeleteTableRemarkSql + { + get + { + return "ALTER TABLE {0} COMMENT='';"; + } + } + + protected override string IsAnyTableRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string RenameTableSql { + get + { + return "alter table {0} rename {1}"; + } + } + + protected override string CreateIndexSql + { + get + { + return "CREATE INDEX Index_{0}_{2} ON {0} ({1})"; + } + } + + protected override string AddDefaultValueSql + { + get + { + return "ALTER TABLE {0} ALTER COLUMN {1} SET DEFAULT '{2}'"; + } + } + protected override string IsAnyIndexSql + { + get + { + return "SELECT count(*) FROM information_schema.statistics WHERE index_name = '{0}'"; + } + } + #endregion + + #region Methods + /// + ///by current connection string + /// + /// + /// + public override bool CreateDatabase(string databaseName, string databaseDirectory = null) + { + if (databaseDirectory != null) + { + if (!FileHelper.IsExistDirectory(databaseDirectory)) + { + FileHelper.CreateDirectory(databaseDirectory); + } + } + var oldDatabaseName = this.Context.Ado.Connection.Database; + var connection = this.Context.CurrentConnectionConfig.ConnectionString; + connection = connection.Replace(oldDatabaseName, "mysql"); + var newDb = new SqlSugarClient(new ConnectionConfig() + { + DbType = this.Context.CurrentConnectionConfig.DbType, + IsAutoCloseConnection = true, + ConnectionString = connection + }); + if (!GetDataBaseList(newDb).Any(it => it.Equals(databaseName, StringComparison.CurrentCultureIgnoreCase))) + { + newDb.Ado.ExecuteCommand(string.Format(CreateDataBaseSql, databaseName, databaseDirectory)); + } + return true; + } + public override bool AddTableRemark(string tableName, string description) + { + string sql = string.Format(this.AddTableRemarkSql, this.SqlBuilder.GetTranslationTableName(tableName), description); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + if (columns.HasValue()) + { + foreach (var item in columns) + { + if (item.DbColumnName.Equals("GUID",StringComparison.CurrentCultureIgnoreCase)&&item.Length==0) + { + item.Length = 10; + } + } + } + string sql = GetCreateTableSql(tableName, columns); + string primaryKeyInfo = null; + if (columns.Any(it => it.IsPrimarykey)&&isCreatePrimaryKey) { + primaryKeyInfo =string.Format( ", Primary key({0})",string.Join(",",columns.Where(it=>it.IsPrimarykey).Select(it=>this.SqlBuilder.GetTranslationColumnName(it.DbColumnName)))); + + } + sql = sql.Replace("$PrimaryKey", primaryKeyInfo); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public override bool AddRemark(EntityInfo entity) + { + var db = this.Context; + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + List columns = entity.Columns.Where(it => it.IsIgnore == false).ToList(); + foreach (var item in columns) + { + if (item.ColumnDescription != null) + { + var mySqlCodeFirst = this.Context.CodeFirst as MySqlCodeFirst; + string sql = GetUpdateColumnSql(entity.DbTableName, mySqlCodeFirst.GetEntityColumnToDbColumn(entity, entity.DbTableName, item))+" "+(item.IsIdentity? "AUTO_INCREMENT" : "")+" " + " COMMENT '" + item.ColumnDescription + "'"; + db.Ado.ExecuteCommand(sql); + } + } + return true; + } + protected override string GetCreateTableSql(string tableName, List columns) + { + List columnArray = new List(); + Check.Exception(columns.IsNullOrEmpty(), "No columns found "); + foreach (var item in columns) + { + string columnName = item.DbColumnName; + string dataSize = ""; + dataSize = GetSize(item); + string dataType = item.DataType; + string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string identity = item.IsIdentity ? this.CreateTableIdentity : null; + string addItem = string.Format(this.CreateTableColumn, this.SqlBuilder.GetTranslationColumnName(columnName), dataType, dataSize, nullType, primaryKey, identity); + columnArray.Add(addItem); + } + string tableString = string.Format(this.CreateTableSql, this.SqlBuilder.GetTranslationTableName(tableName), string.Join(",\r\n", columnArray)); + return tableString; + } + + protected override string GetSize(DbColumnInfo item) + { + string dataSize = null; + var isMax = item.Length > 4000 || item.Length == -1; + if (isMax) + { + dataSize=""; + item.DataType = "longtext"; + } + else if (item.Length > 0 && item.DecimalDigits == 0) + { + dataSize = item.Length > 0 ? string.Format("({0})", item.Length) : null; + } + else if (item.Length == 0 && item.DecimalDigits > 0) + { + item.Length = 10; + dataSize = string.Format("({0},{1})", item.Length, item.DecimalDigits); + } + else if (item.Length > 0 && item.DecimalDigits > 0) + { + dataSize = item.Length > 0 ? string.Format("({0},{1})", item.Length, item.DecimalDigits) : null; + } + return dataSize; + } + + public override bool RenameColumn(string tableName, string oldColumnName, string newColumnName) + { + var columns=GetColumnInfosByTableName(tableName).Where(it=>it.DbColumnName.Equals(oldColumnName,StringComparison.CurrentCultureIgnoreCase)); + if (columns != null && columns.Any()) + { + var column = columns.First(); + var appendSql = " " + column.DataType; + if (column.Length > 0 && column.Scale == 0) + { + appendSql += string.Format("({0}) ", column.Length); + } + else if (column.Scale > 0 && column.Length > 0) + { + appendSql += string.Format("({0},{1}) ", column.Length, column.Scale); + } + else + { + appendSql += column.IsNullable ? " NULL " : " NOT NULL "; + } + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + oldColumnName = this.SqlBuilder.GetTranslationColumnName(oldColumnName); + newColumnName = this.SqlBuilder.GetTranslationColumnName(newColumnName); + string sql = string.Format(this.RenameColumnSql, tableName, oldColumnName, newColumnName+appendSql); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + else + { + return false; + } + } + public override bool AddDefaultValue(string tableName, string columnName, string defaultValue) + { + if (defaultValue == "''") + { + defaultValue = ""; + } + if (defaultValue.ToLower().IsIn("now()", "current_timestamp")) + { + string template = "ALTER table {0} CHANGE COLUMN {1} {1} {3} default {2}"; + var dbColumnInfo = this.Context.DbMaintenance.GetColumnInfosByTableName(tableName).First(it => it.DbColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase)); + string sql = string.Format(template, tableName, columnName, defaultValue, dbColumnInfo.DataType); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + else if (defaultValue=="0"|| defaultValue == "1") + { + string sql = string.Format(AddDefaultValueSql.Replace("'",""), tableName, columnName, defaultValue); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + else + { + return base.AddDefaultValue(tableName, columnName, defaultValue); + } + } + public override bool IsAnyConstraint(string constraintName) + { + throw new NotSupportedException("MySql IsAnyConstraint NotSupportedException"); + } + public override bool BackupDataBase(string databaseName, string fullFileName) + { + Check.ThrowNotSupportedException("MySql BackupDataBase NotSupported"); + return false; + } + + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/MySqlProvider.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/MySqlProvider.cs new file mode 100644 index 0000000..00484e3 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/MySqlProvider.cs @@ -0,0 +1,117 @@ +using MySql.Data.MySqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MySqlProvider : AdoProvider + { + public MySqlProvider() { } + public override IDbConnection Connection + { + get + { + if (base._DbConnection == null) + { + try + { + var mySqlConnectionString = base.Context.CurrentConnectionConfig.ConnectionString; + if (!mySqlConnectionString.ToLower().Contains("charset")) + { + mySqlConnectionString = mySqlConnectionString.Trim().TrimEnd(';') + ";charset=utf8;"; + } + base._DbConnection = new MySqlConnection(mySqlConnectionString); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + + public override void BeginTran(string transactionName) + { + base.BeginTran(); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + base.BeginTran(iso); + } + public override IDataAdapter GetAdapter() + { + return new MySqlDataAdapter(); + } + public override DbCommand GetCommand(string sql, SugarParameter[] parameters) + { + MySqlCommand sqlCommand = new MySqlCommand(sql, (MySqlConnection)this.Connection); + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (MySqlTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + IDataParameter[] ipars = ToIDbDataParameter(parameters); + sqlCommand.Parameters.AddRange((MySqlParameter[])ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, DbCommand command) + { + ((MySqlDataAdapter)dataAdapter).SelectCommand = (MySqlCommand)command; + } + /// + /// if mysql return MySqlParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + MySqlParameter[] result = new MySqlParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + var sqlParameter = new MySqlParameter(); + sqlParameter.ParameterName = parameter.ParameterName; + sqlParameter.Size = parameter.Size; + sqlParameter.Value = parameter.Value; + sqlParameter.DbType = parameter.DbType; + sqlParameter.Direction = parameter.Direction; + if (sqlParameter.Direction == 0) + { + sqlParameter.Direction = ParameterDirection.Input; + } + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue)) + { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/Queryable/MySqlQueryable.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/Queryable/MySqlQueryable.cs new file mode 100644 index 0000000..2abc0a3 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/Queryable/MySqlQueryable.cs @@ -0,0 +1,60 @@ +namespace SqlSugar +{ + public class MySqlQueryable : QueryableProvider + { + public override ISugarQueryable With(string withString) + { + return this; + } + + public override ISugarQueryable PartitionBy(string groupFileds) + { + this.GroupBy(groupFileds); + return this; + } + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlBuilder.cs new file mode 100644 index 0000000..51152c0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlBuilder.cs @@ -0,0 +1,26 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class MySqlBuilder : SqlBuilderProvider + { + public override string SqlTranslationLeft { get { return "`"; } } + public override string SqlTranslationRight { get { return "`"; } } + public override string SqlDateNow + { + get + { + return "sysdate()"; + } + } + public override string FullSqlDateNow + { + get + { + return "select sysdate()"; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlDeleteBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlDeleteBuilder.cs new file mode 100644 index 0000000..97189bc --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlDeleteBuilder.cs @@ -0,0 +1,7 @@ +namespace SqlSugar +{ + public class MySqlDeleteBuilder : DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlExpressionContext.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlExpressionContext.cs new file mode 100644 index 0000000..b59e7dd --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlExpressionContext.cs @@ -0,0 +1,147 @@ +using System; +using System.Linq; +namespace SqlSugar +{ + public class MySqlExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarProvider Context { get; set; } + public MySqlExpressionContext() + { + base.DbMehtods = new MySqlMethod(); + } + public override string SqlTranslationLeft { get { return "`"; } } + public override string SqlTranslationRight { get { return "`"; } } + } + public class MySqlMethod : DefaultDbMethod, IDbMethods + { + public override string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" {0}({1}) ", parameter2.MemberValue, parameter.MemberName); + } + + public override string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat('%',{1},'%')) ", parameter.MemberName, parameter2.MemberName ); + } + + public override string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat({1},'%')) ", parameter.MemberName, parameter2.MemberName); + } + + public override string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat('%',{1}))", parameter.MemberName,parameter2.MemberName); + } + + public override string DateIsSameDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (TIMESTAMPDIFF(day,date({0}),date({1}))=0) ", parameter.MemberName, parameter2.MemberName); ; + } + + public override string DateIsSameByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (TIMESTAMPDIFF({2},{0},{1})=0) ", parameter.MemberName, parameter2.MemberName, parameter3.MemberValue); + } + + public override string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (DATE_ADD({1} , INTERVAL {2} {0})) ", parameter3.MemberValue, parameter.MemberName, parameter2.MemberName); + } + + public override string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (DATE_ADD({1} INTERVAL {0} day)) ", parameter.MemberName, parameter2.MemberName); + } + + public override string ToInt32(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToInt64(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS CHAR)", parameter.MemberName); + } + + public override string ToGuid(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS CHAR)", parameter.MemberName); + } + + public override string ToDouble(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string ToBool(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToDecimal(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" LENGTH({0})", parameter.MemberName); + } + public override string MergeString(params string[] strings) + { + return " concat("+string.Join(",", strings) + ") "; + } + public override string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("IFNULL({0},{1})", parameter.MemberName, parameter1.MemberName); + } + public override string GetDate() + { + return "NOW()"; + } + + public override string GetRandom() + { + return "rand()"; + } + + public override string CharIndex(MethodCallExpressionModel model) + { + return string.Format("instr ({0},{1})", model.Args[0].MemberName, model.Args[1].MemberName); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlInsertBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlInsertBuilder.cs new file mode 100644 index 0000000..5fca051 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlInsertBuilder.cs @@ -0,0 +1,84 @@ +using System; + +namespace SqlSugar +{ + public class MySqlInsertBuilder : InsertBuilder + { + public override string SqlTemplate + { + get + { + if (IsReturnIdentity) + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;SELECT LAST_INSERT_ID();"; + } + else + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;"; + + } + } + } + public override object FormatValue(object value) + { + var n = "N"; + if (this.Context.CurrentConnectionConfig.MoreSettings != null && this.Context.CurrentConnectionConfig.MoreSettings.MySqlDisableNarvchar) + { + n = ""; + } + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return n+"'" + GetString(value).ToSqlFilter() + "'"; + } + else + { + return n+"'" + GetString(value) + "'"; + } + } + } + private string GetString(object value) + { + var result = value.ToString(); + if (result.HasValue() && result.Contains("\\")) + { + result = result.Replace("\\", "\\\\"); + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlQueryBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlQueryBuilder.cs new file mode 100644 index 0000000..27432a3 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlQueryBuilder.cs @@ -0,0 +1,137 @@ +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public partial class MySqlQueryBuilder : QueryBuilder + { + #region Sql Template + public override string PageTempalte + { + get + { + /* + SELECT * FROM TABLE WHERE CONDITION ORDER BY ID DESC LIMIT 0,10 + */ + var template = "SELECT {0} FROM {1} {2} {3} {4} LIMIT {5},{6}"; + return template; + } + } + public override string DefaultOrderByTemplate + { + get + { + return "ORDER BY NOW() "; + } + } + + #endregion + + #region Common Methods + public override bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS \`\w+\.\w+\`"); + } + public override string ToSqlString() + { + base.AppendFilter(); + string oldOrderValue = this.OrderByValue; + string result = null; + sql = new StringBuilder(); + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString); + if (IsCount) { return sql.ToString(); } + if (Skip != null && Take == null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString, Skip.ObjToInt(), long.MaxValue); + } + else if (Skip == null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, 0, Take.ObjToInt()); + } + else if (Skip != null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, Skip.ObjToInt() > 0 ? Skip.ObjToInt() : 0, Take); + } + else + { + result = sql.ToString(); + } + this.OrderByValue = oldOrderValue; + return result; + } + private string ToCountSqlString() + { + base.AppendFilter(); + string oldOrderValue = this.OrderByValue; + string result = null; + sql = new StringBuilder(); + sql.AppendFormat(SqlTemplate, "Count(*)", GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString); + if (IsCount) { return sql.ToString(); } + if (Skip != null && Take == null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString, Skip.ObjToInt(), long.MaxValue); + } + else if (Skip == null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, 0, Take.ObjToInt()); + } + else if (Skip != null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, Skip.ObjToInt() > 0 ? Skip.ObjToInt() : 0, Take); + } + else + { + result = sql.ToString(); + } + this.OrderByValue = oldOrderValue; + return result; + } + public override string ToCountSql(string sql) + { + if (this.GroupByValue.HasValue()) + { + return base.ToCountSql(sql); + } + else + { + return ToCountSqlString(); + } + } + #endregion + + #region Get SQL Partial + public override string GetSelectValue + { + get + { + string result = string.Empty; + if (this.SelectValue == null || this.SelectValue is string) + { + result = GetSelectValueByString(); + } + else + { + result = GetSelectValueByExpression(); + } + if (this.SelectType == ResolveExpressType.SelectMultiple) + { + this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this.JoinQueryInfos.Select(it => it.TableName)); + } + if (IsDistinct) + { + result = " DISTINCT " + result; + } + return result; + } + } + + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlUpdateBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlUpdateBuilder.cs new file mode 100644 index 0000000..dfaffa7 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/MySql/SqlBuilder/MySqlUpdateBuilder.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class MySqlUpdateBuilder : UpdateBuilder + { + public override string SqlTemplateBatch + { + get + { + return @"UPDATE {1} S {2} INNER JOIN ${{0}} SET {0} "; + } + } + public override string SqlTemplateJoin + { + get + { + return @" ( + {0} + + ) T ON {1} + "; + } + } + protected override string TomultipleSqlString(List> groupList) + { + Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List need Primary key"); + int pageSize = 200; + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + StringBuilder batchUpdateSql = new StringBuilder(); + while (pageCount >= pageIndex) + { + StringBuilder updateTable = new StringBuilder(); + string setValues = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it => + { + if (SetValues.IsValuable()) + { + var setValue = SetValues.Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName)); + if (setValue != null && setValue.Any()) + { + return setValue.First().Value; + } + } + var result = string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(it.DbColumnName)); + return result; + })); + batchUpdateSql.AppendFormat(SqlTemplateBatch.ToString(), setValues, GetTableNameStringNoWith, TableWithString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + updateTable.Append(SqlTemplateBatchUnion); + } + updateTable.Append("\r\n SELECT " + string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value),this.Builder.GetTranslationColumnName(it.DbColumnName))))); + ++i; + } + pageIndex++; + updateTable.Append("\r\n"); + string whereString = null; + if (this.WhereValues.HasValue()) + { + foreach (var item in WhereValues) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += Regex.Replace(item, " \\" + this.Builder.SqlTranslationLeft, "S." + this.Builder.SqlTranslationLeft); + } + } + if (PrimaryKeys.HasValue()) + { + foreach (var item in PrimaryKeys) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(item)); + } + } + var format= string.Format(SqlTemplateJoin, updateTable, whereString); + batchUpdateSql.Replace("${0}",format); + batchUpdateSql.Append(";"); + } + return batchUpdateSql.ToString(); + } + public override object FormatValue(object value) + { + var n = "N"; + if (this.Context.CurrentConnectionConfig.MoreSettings != null&&this.Context.CurrentConnectionConfig.MoreSettings.MySqlDisableNarvchar) + { + n = ""; + } + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return n+"'" + GetString(value).ToSqlFilter() + "'"; + } + else + { + return n+"'" + GetString(value) + "'"; + } + } + } + private string GetString(object value) + { + var result = value.ToString(); + if (result.HasValue() && result.Contains("\\")) + { + result = result.Replace("\\", "\\\\"); + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/CodeFirst/OracleCodeFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/CodeFirst/OracleCodeFirst.cs new file mode 100644 index 0000000..3d7cafb --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/CodeFirst/OracleCodeFirst.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleCodeFirst : CodeFirstProvider + { + public OracleCodeFirst() { + if (DefultLength == 0) + DefultLength = 40; + } + protected override int DefultLength { get; set; } + + protected override void GetDbType(EntityColumnInfo item, Type propertyType, DbColumnInfo result) + { + if (!string.IsNullOrEmpty(item.DataType)) + { + result.DataType = item.DataType; + } + else if (propertyType.IsEnum()) + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(item.Length > 9 ? UtilConstants.LongType.Name : UtilConstants.IntType.Name); + } + else + { + if (propertyType.Name.Equals("Guid", StringComparison.CurrentCultureIgnoreCase)) + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(UtilConstants.StringType.Name); + } + else + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(propertyType.Name); + } + } + } + + protected override void KeyAction(EntityColumnInfo item, DbColumnInfo dbColumn, out bool pkDiff, out bool idEntityDiff) + { + pkDiff = item.IsPrimarykey != dbColumn.IsPrimarykey; + idEntityDiff = false; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbBind/OracleDbBind.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbBind/OracleDbBind.cs new file mode 100644 index 0000000..42fb2cc --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbBind/OracleDbBind.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class OracleDbBind : DbBindProvider + { + public override string GetDbTypeName(string csharpTypeName) + { + if (csharpTypeName == UtilConstants.ByteArrayType.Name) + return "blob"; + if (csharpTypeName.ToLower() == "int32") + csharpTypeName = "int"; + if (csharpTypeName.ToLower() == "int16") + csharpTypeName = "short"; + if (csharpTypeName.ToLower() == "int64") + csharpTypeName = "long"; + if (csharpTypeName.ToLower().IsIn("boolean", "bool")) + csharpTypeName = "bool"; + var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)); + return mappings.HasValue() ? mappings.First().Key : "varchar"; + } + public override string GetPropertyTypeName(string dbTypeName) + { + dbTypeName = dbTypeName.ToLower(); + var propertyTypes = MappingTypes.Where(it => it.Value.ToString().ToLower() == dbTypeName || it.Key.ToLower() == dbTypeName); + if (dbTypeName == "int32") + { + return "int"; + } + else if (dbTypeName == "int64") + { + return "long"; + } + else if (dbTypeName == "int16") + { + return "short"; + } + else if (propertyTypes == null) + { + return "other"; + } + else if (dbTypeName == "xml" || dbTypeName == "string") + { + return "string"; + } + if (dbTypeName == "byte[]") + { + return "byte[]"; + } + else if (propertyTypes == null || propertyTypes.Count() == 0) + { + Check.ThrowNotSupportedException(string.Format(" \"{0}\" Type NotSupported, DbBindProvider.GetPropertyTypeName error.", dbTypeName)); + return null; + } + else if (propertyTypes.First().Value == CSharpDataType.byteArray) + { + return "byte[]"; + } + else + { + return propertyTypes.First().Value.ToString(); + } + } + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null && extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>() + { + new KeyValuePair("int",CSharpDataType.@int), + new KeyValuePair("integer",CSharpDataType.@int), + new KeyValuePair("interval year to month",CSharpDataType.@int), + new KeyValuePair("interval day to second",CSharpDataType.@int), + + new KeyValuePair("number",CSharpDataType.@int), + new KeyValuePair("number",CSharpDataType.@float), + new KeyValuePair("number",CSharpDataType.@short), + new KeyValuePair("number",CSharpDataType.@byte), + new KeyValuePair("number",CSharpDataType.@double), + new KeyValuePair("number",CSharpDataType.@long), + new KeyValuePair("number",CSharpDataType.@bool), + new KeyValuePair("number",CSharpDataType.@decimal), + new KeyValuePair("number",CSharpDataType.Single), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("decimal",CSharpDataType.Single), + + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("varchar2",CSharpDataType.@string), + new KeyValuePair("nvarchar2",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("nchar",CSharpDataType.@string), + new KeyValuePair("clob",CSharpDataType.@string), + new KeyValuePair("long",CSharpDataType.@string), + new KeyValuePair("nclob",CSharpDataType.@string), + new KeyValuePair("rowid",CSharpDataType.@string), + + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("timestamp",CSharpDataType.DateTime), + new KeyValuePair("timestamp with local time zone",CSharpDataType.DateTime), + new KeyValuePair("timestamp with time zone",CSharpDataType.DateTime), + new KeyValuePair("timestamp with time zone",CSharpDataType.DateTime), + + new KeyValuePair("float",CSharpDataType.@decimal), + + new KeyValuePair("blob",CSharpDataType.byteArray), + new KeyValuePair("long raw",CSharpDataType.byteArray), + new KeyValuePair("raw",CSharpDataType.byteArray), + new KeyValuePair("bfile",CSharpDataType.byteArray), + new KeyValuePair("varbinary",CSharpDataType.byteArray) }; + public override List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte" }; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbFirst/OracleDbFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbFirst/OracleDbFirst.cs new file mode 100644 index 0000000..fba461c --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbFirst/OracleDbFirst.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleDbFirst : DbFirstProvider + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbMaintenance/OracleDbMaintenance.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbMaintenance/OracleDbMaintenance.cs new file mode 100644 index 0000000..c7d3589 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/DbMaintenance/OracleDbMaintenance.cs @@ -0,0 +1,470 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetDataBaseSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string GetColumnInfosByTableNameSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string GetTableInfoListSql + { + get + { + return @"SELECT table_name name from user_tables where + table_name!='HELP' + AND table_name NOT LIKE '%$%' + AND table_name NOT LIKE 'LOGMNRC_%' + AND table_name!='LOGMNRP_CTAS_PART_MAP' + AND table_name!='LOGMNR_LOGMNR_BUILDLOG' + AND table_name!='SQLPLUS_PRODUCT_PROFILE' + "; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"select view_name name from user_views + WHERE VIEW_name NOT LIKE '%$%' + AND VIEW_NAME !='PRODUCT_PRIVS' + AND VIEW_NAME NOT LIKE 'MVIEW_%' "; + } + } + #endregion + + #region DDL + protected override string IsAnyIndexSql + { + get + { + return "select count(1) from user_ind_columns where index_name=('{0}')"; + } + } + protected override string CreateIndexSql + { + get + { + return "CREATE INDEX Index_{0}_{2} ON {0}({1})"; + } + } + protected override string AddDefaultValueSql + { + get + { + return "ALTER TABLE {0} MODIFY({1} DEFAULT '{2}')"; + } + } + protected override string CreateDataBaseSql + { + get + { + return "CREATE DATABASE {0}"; + } + } + protected override string AddPrimaryKeySql + { + get + { + return "ALTER TABLE {0} ADD CONSTRAINT {1} PRIMARY KEY({2})"; + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD ({1} {2}{3} {4} {5} {6})"; + } + } + protected override string AlterColumnToTableSql + { + get + { + return "ALTER TABLE {0} modify ({1} {2}{3} {4} {5} {6}) "; + } + } + protected override string BackupDataBaseSql + { + get + { + return @"USE master;BACKUP DATABASE {0} TO disk = '{1}'"; + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1})"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "TRUNCATE TABLE {0}"; + } + } + protected override string BackupTableSql + { + get + { + return "create table {1} as select * from {2} where ROWNUM<={0}"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + return "ALTER TABLE {0} DROP COLUMN {1}"; + } + } + protected override string DropConstraintSql + { + get + { + return "ALTER TABLE {0} DROP CONSTRAINT {1}"; + } + } + protected override string RenameColumnSql + { + get + { + return "ALTER TABLE {0} rename column {1} to {2}"; + } + } + protected override string AddColumnRemarkSql + { + get + { + return "comment on column {1}.{0} is '{2}'"; + } + } + + protected override string DeleteColumnRemarkSql + { + get + { + return "comment on column {1}.{0} is ''"; + } + } + + protected override string IsAnyColumnRemarkSql + { + get + { + return "select * from user_col_comments where Table_Name='{1}' AND COLUMN_NAME='{0}' order by column_name"; + } + } + + protected override string AddTableRemarkSql + { + get + { + return "comment on table {0} is '{1}'"; + } + } + + protected override string DeleteTableRemarkSql + { + get + { + return "comment on table {0} is ''"; + } + } + + protected override string IsAnyTableRemarkSql + { + get + { + return "select * from user_tab_comments where Table_Name='{0}'order by Table_Name"; + } + } + + protected override string RenameTableSql + { + get + { + return "alter table {0} rename to {1}"; + } + } + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select t.table_name from user_tables t where rownum=1"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return ""; + } + } + protected override string CreateTableNotNull + { + get + { + return ""; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return ""; + } + } + #endregion + + #region Methods + public override bool AddColumn(string tableName, DbColumnInfo columnInfo) + { + if (columnInfo.DataType == "varchar"&& columnInfo.Length ==0) + { + columnInfo.DataType = "varchar2"; + columnInfo.Length = 50; + } + return base.AddColumn(tableName,columnInfo); + } + public override bool CreateIndex(string tableName, string[] columnNames) + { + string sql = string.Format(CreateIndexSql, tableName, string.Join(",", columnNames), string.Join("_", columnNames.Select(it=>(it+"abc").Substring(0,3)))); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public override bool AddDefaultValue(string tableName, string columnName, string defaultValue) + { + if (defaultValue == "''") + { + defaultValue = ""; + } + if (defaultValue.ToLower().IsIn("sysdate")) + { + var template = AddDefaultValueSql.Replace("'", ""); + string sql = string.Format(template,tableName,columnName,defaultValue); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + else + { + return base.AddDefaultValue(tableName, columnName, defaultValue); + } + } + public override bool CreateDatabase(string databaseDirectory = null) + { + throw new NotSupportedException(); + } + public override bool CreateDatabase(string databaseName, string databaseDirectory = null) + { + throw new NotSupportedException(); + } + public override bool AddRemark(EntityInfo entity) + { + var db = this.Context; + var columns = entity.Columns.Where(it => it.IsIgnore == false).ToList(); + + foreach (var item in columns) + { + if (item.ColumnDescription != null) + { + //column remak + if (db.DbMaintenance.IsAnyColumnRemark(item.DbColumnName.ToUpper(), item.DbTableName.ToUpper())) + { + db.DbMaintenance.DeleteColumnRemark(item.DbColumnName.ToUpper(), item.DbTableName.ToUpper()); + db.DbMaintenance.AddColumnRemark(item.DbColumnName.ToUpper(), item.DbTableName.ToUpper(), item.ColumnDescription); + } + else + { + db.DbMaintenance.AddColumnRemark(item.DbColumnName.ToUpper(), item.DbTableName.ToUpper(), item.ColumnDescription); + } + } + } + + //table remak + if (entity.TableDescription != null) + { + if (db.DbMaintenance.IsAnyTableRemark(entity.DbTableName)) + { + db.DbMaintenance.DeleteTableRemark(entity.DbTableName); + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + else + { + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + } + return true; + } + public override List GetColumnInfosByTableName(string tableName, bool isCache = true) + { + string cacheKey = "DbMaintenanceProvider.GetColumnInfosByTableName." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + if (!isCache) + return GetColumnInfosByTableName(tableName); + else + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + return GetColumnInfosByTableName(tableName); + + }); + } + + private List GetColumnInfosByTableName(string tableName) + { + string sql = "select * from " +SqlBuilder.GetTranslationTableName(tableName) + " WHERE 1=2 "; + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + using (DbDataReader reader = (DbDataReader)this.Context.Ado.GetDataReader(sql)) + { + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + List result = new List(); + var schemaTable = reader.GetSchemaTable(); + foreach (System.Data.DataRow row in schemaTable.Rows) + { + DbColumnInfo column = new DbColumnInfo() + { + TableName = tableName, + DataType = row["DataType"].ToString().Replace("System.", "").Trim(), + IsNullable = (bool)row["AllowDBNull"], + //IsIdentity = (bool)row["IsAutoIncrement"], + ColumnDescription = GetFieldComment(tableName, row["ColumnName"].ToString()), + DbColumnName = row["ColumnName"].ToString(), + //DefaultValue = row["defaultValue"].ToString(), + IsPrimarykey = GetPrimaryKeyByTableNames(tableName).Any(it => it.Equals(row["ColumnName"].ToString(), StringComparison.CurrentCultureIgnoreCase)), + Length = row["ColumnSize"].ObjToInt(), + Scale = row["numericscale"].ObjToInt() + }; + result.Add(column); + } + return result; + } + } + + private List GetPrimaryKeyByTableNames(string tableName) + { + string cacheKey = "DbMaintenanceProvider.GetPrimaryKeyByTableNames." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + string sql = @" select distinct cu.COLUMN_name KEYNAME from user_cons_columns cu, user_constraints au + where cu.constraint_name = au.constraint_name + and au.constraint_type = 'P' and au.table_name = '" + tableName.ToUpper() + @"'"; + var pks = this.Context.Ado.SqlQuery(sql); + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + return pks; + }); + } + + public string GetTableComment(string tableName) + { + string cacheKey = "DbMaintenanceProvider.GetTableComment." + tableName; + var comments = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + string sql = "SELECT COMMENTS FROM USER_TAB_COMMENTS WHERE TABLE_NAME =@tableName ORDER BY TABLE_NAME"; + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + var pks = this.Context.Ado.SqlQuery(sql, new { tableName = tableName.ToUpper() }); + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + return pks; + }); + return comments.HasValue() ? comments.First() : ""; + } + + public string GetFieldComment(string tableName, string filedName) + { + string cacheKey = "DbMaintenanceProvider.GetFieldComment." + tableName; + var comments = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + string sql = "SELECT TABLE_NAME AS TableName, COLUMN_NAME AS DbColumnName,COMMENTS AS ColumnDescription FROM user_col_comments WHERE TABLE_NAME =@tableName ORDER BY TABLE_NAME"; + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + var pks = this.Context.Ado.SqlQuery(sql, new { tableName = tableName.ToUpper() }); + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + return pks; + }); + return comments.HasValue() ? comments.First(it => it.DbColumnName.Equals(filedName, StringComparison.CurrentCultureIgnoreCase)).ColumnDescription : ""; + + } + + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + if (columns.HasValue()) + { + foreach (var item in columns) + { + if (item.DbColumnName.Equals("GUID", StringComparison.CurrentCultureIgnoreCase) && item.Length == 0) + { + item.Length = 50; + } + if (item.DataType == "varchar" && item.Length == 0) + { + item.Length = 50; + } + } + } + string sql = GetCreateTableSql(tableName, columns); + this.Context.Ado.ExecuteCommand(sql); + if (isCreatePrimaryKey) + { + var pkColumns = columns.Where(it => it.IsPrimarykey).ToList(); + foreach (var item in pkColumns) + { + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + } + return true; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/Deleteable/OracleDeleteable.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/Deleteable/OracleDeleteable.cs new file mode 100644 index 0000000..fbd8d54 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/Deleteable/OracleDeleteable.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleDeleteable:DeleteableProvider where T:class,new() + { + protected override List GetIdentityKeys() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.DbColumnName).ToList(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/Insertable/OracleInsertable.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/Insertable/OracleInsertable.cs new file mode 100644 index 0000000..f11790a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/Insertable/OracleInsertable.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleInsertable : InsertableProvider where T : class, new() + { + + protected override List GetIdentityKeys() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.DbColumnName).ToList(); + } + protected string GetSeqName() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.OracleSequenceName).First(); + } + protected List GetSeqNames() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.OracleSequenceName).ToList(); + } + public override int ExecuteReturnIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation; + this.Context.Ado.IsDisableMasterSlaveSeparation = true; + var count = Ado.ExecuteCommand(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + var result = (this.GetIdentityKeys().IsNullOrEmpty() || count == 0) ? 0 : GetSeqValue(GetSeqName()).ObjToInt(); + this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + return result; + } + + public override long ExecuteReturnBigIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + var isDisableMasterSlaveSeparation = this.Context.Ado.IsDisableMasterSlaveSeparation; + this.Context.Ado.IsDisableMasterSlaveSeparation = true; + var count = Ado.ExecuteCommand(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + var result = (this.GetIdentityKeys().IsNullOrEmpty() || count == 0) ? 0 :Convert.ToInt64(GetSeqValue(GetSeqName())); + this.Context.Ado.IsDisableMasterSlaveSeparation = isDisableMasterSlaveSeparation; + return result; + } + + + public override int ExecuteCommand() + { + base.ExecuteCommand(); + return base.InsertObjs.Count(); + } + + private object GetSeqValue(string seqName) + { + return Ado.GetScalar(" SELECT " + seqName + ".currval FROM DUAL"); + } + protected override void PreToSql() + { + var identities = GetSeqNames(); + var insertCount = InsertObjs.Count(); + InsertBuilder.OracleSeqInfoList = new Dictionary(); + if (identities.HasValue() && insertCount > 1) + { + Check.Exception(identities.Count != identities.Distinct().Count(), "The field sequence needs to be unique"); + foreach (var seqName in identities) + { + int seqBeginValue = 0; + this.Ado.ExecuteCommand("alter sequence " + seqName + " increment by " + insertCount); + seqBeginValue = this.Ado.GetInt("select " + seqName + ".Nextval from dual") - insertCount; + this.Ado.ExecuteCommand("alter sequence " + seqName + " increment by " + 1); + InsertBuilder.OracleSeqInfoList.Add(seqName, seqBeginValue); + } + } + base.PreToSql(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/OracleProvider.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/OracleProvider.cs new file mode 100644 index 0000000..ecec0cd --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/OracleProvider.cs @@ -0,0 +1,176 @@ +using Oracle.ManagedDataAccess.Client; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class OracleProvider : AdoProvider + { + public OracleProvider() + { + this.FormatSql = sql => + { + sql = sql.Replace("+@", "+:"); + if (sql.HasValue()&&sql.Contains("@")) { + var exceptionalCaseInfo = Regex.Matches(sql, @"\'.*?\@.*?\'| [\.,\w]+\@[\.,\w]+ | [\.,\w]+\@[\.,\w]+"); + if (exceptionalCaseInfo != null) { + foreach (var item in exceptionalCaseInfo.Cast()) + { + sql = sql.Replace(item.Value, item.Value.Replace("@", UtilConstants.ReplaceKey)); + } + } + sql = sql .Replace("@",":"); + sql = sql.Replace(UtilConstants.ReplaceKey, "@"); + } + return sql; + }; + } + public override string SqlParameterKeyWord + { + get + { + return ":"; + } + } + public override IDbConnection Connection + { + get + { + try + { + if (base._DbConnection == null) + { + base._DbConnection = new OracleConnection(base.Context.CurrentConnectionConfig.ConnectionString); + } + } + catch (Exception ex) + { + + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + /// + /// Only SqlServer + /// + /// + public override void BeginTran(string transactionName) + { + ((OracleConnection)this.Connection).BeginTransaction(); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + ((OracleConnection)this.Connection).BeginTransaction(iso); + } + public override IDataAdapter GetAdapter() + { + return new OracleDataAdapter(); + } + public override DbCommand GetCommand(string sql, SugarParameter[] parameters) + { + OracleCommand sqlCommand = new OracleCommand(sql, (OracleConnection)this.Connection); + sqlCommand.BindByName = true; + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (OracleTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + IDataParameter[] ipars = ToIDbDataParameter(parameters); + sqlCommand.Parameters.AddRange((OracleParameter[])ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, DbCommand command) + { + ((OracleDataAdapter)dataAdapter).SelectCommand = (OracleCommand)command; + } + /// + /// if mysql return MySqlParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + OracleParameter[] result = new OracleParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + var sqlParameter = new OracleParameter(); + sqlParameter.Size = parameter.Size == -1 ? 0 : parameter.Size; + sqlParameter.ParameterName = parameter.ParameterName; + if (sqlParameter.ParameterName[0] == '@') + { + sqlParameter.ParameterName = ':' + sqlParameter.ParameterName.Substring(1, sqlParameter.ParameterName.Length - 1); + } + if (this.CommandType == CommandType.StoredProcedure) + { + sqlParameter.ParameterName = sqlParameter.ParameterName.TrimStart(':'); + } + if (parameter.IsRefCursor) + { + sqlParameter.OracleDbType = OracleDbType.RefCursor; + } + if (sqlParameter.DbType == System.Data.DbType.Guid) + { + sqlParameter.DbType = System.Data.DbType.String; + sqlParameter.Value = sqlParameter.Value.ObjToString(); + } + else if (parameter.DbType == System.Data.DbType.Boolean) + { + sqlParameter.DbType = System.Data.DbType.Int16; + if (parameter.Value == DBNull.Value) + { + parameter.Value = 0; + } + else + { + sqlParameter.Value = (bool)parameter.Value ? 1 : 0; + } + } + else + { + if (parameter.Value != null && parameter.Value.GetType() == UtilConstants.GuidType) + { + parameter.Value = parameter.Value.ToString(); + } + sqlParameter.Value = parameter.Value; + } + if (parameter.Direction != 0) + sqlParameter.Direction = parameter.Direction; + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue)) + { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/Queryable/OracleQueryable.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/Queryable/OracleQueryable.cs new file mode 100644 index 0000000..720bdc8 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/Queryable/OracleQueryable.cs @@ -0,0 +1,65 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class OracleQueryable : QueryableProvider + { + public override ISugarQueryable With(string withString) + { + return this; + } + protected override List GetIdentityKeys() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.DbColumnName).ToList(); + } + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleBuilder.cs new file mode 100644 index 0000000..c0e9026 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleBuilder.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleBuilder : SqlBuilderProvider + { + public override string SqlParameterKeyWord + { + get + { + return ":"; + } + } + public override string SqlDateNow + { + get + { + return "sysdate"; + } + } + public override string FullSqlDateNow + { + get + { + return "select sysdate from dual"; + } + } + public override string SqlTranslationLeft { get { return "\""; } } + public override string SqlTranslationRight { get { return "\""; } } + public override string GetTranslationTableName(string name) + { + var result = base.GetTranslationTableName(name); + if (result.Contains("(") && result.Contains(")")) + return result; + else + return result.ToUpper(); + } + public override string GetTranslationColumnName(string entityName, string propertyName) + { + var result = base.GetTranslationColumnName(entityName, propertyName); + return result.ToUpper(); + } + public override string GetTranslationColumnName(string propertyName) + { + var result = base.GetTranslationColumnName(propertyName); + return result.ToUpper(); + } + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleDeleteBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleDeleteBuilder.cs new file mode 100644 index 0000000..504d0be --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleDeleteBuilder.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleDeleteBuilder : DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleExpressionContext.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleExpressionContext.cs new file mode 100644 index 0000000..218fb72 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleExpressionContext.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class OracleExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarProvider Context { get; set; } + public OracleExpressionContext() + { + base.DbMehtods = new OracleMethod(); + } + public override string SqlParameterKeyWord + { + get + { + return ":"; + } + } + public override string SqlTranslationLeft { get { return "\""; } } + public override string SqlTranslationRight { get { return "\""; } } + public override string GetTranslationTableName(string entityName, bool isMapping = true) + { + return base.GetTranslationTableName(entityName, isMapping).ToUpper(); + } + public override string GetTranslationColumnName(string columnName) + { + return base.GetTranslationColumnName(columnName).ToUpper(); + } + public override string GetDbColumnName(string entityName, string propertyName) + { + return base.GetDbColumnName(entityName,propertyName).ToUpper(); + } + } + public partial class OracleMethod : DefaultDbMethod, IDbMethods + { + public override string ToInt64(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS Number)", parameter.MemberName); + } + + public override string ToTime(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" to_timestamp({0},'0000-01-01 hh24:mi:ss') ", parameter.MemberName); + } + public override string Substring(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("SUBSTR({0},1 + {1},{2})", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + public override string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var type = (DateType)Enum.Parse(typeof(DateType), parameter2.MemberValue.ObjToString(), false); + switch (type) + { + case DateType.Year: + return string.Format("(CAST(TO_CHAR({0},'yyyy') AS NUMBER))", parameter.MemberName); + case DateType.Month: + return string.Format("(CAST(TO_CHAR({0},'mm') AS NUMBER))", parameter.MemberName); + case DateType.Hour: + return string.Format("(CAST(TO_CHAR({0},'hh24') AS NUMBER))", parameter.MemberName); + case DateType.Second: + return string.Format("(CAST(TO_CHAR({0},'ss') AS NUMBER))", parameter.MemberName); + case DateType.Minute: + return string.Format("(CAST(TO_CHAR({0},'mi') AS NUMBER))", parameter.MemberName); + case DateType.Millisecond: + return string.Format("(CAST(TO_CHAR({0},'ff3') AS NUMBER))", parameter.MemberName); + case DateType.Day: + default: + return string.Format("(CAST(TO_CHAR({0},'dd') AS NUMBER))", parameter.MemberName); + } + } + public override string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + var type = (DateType)Enum.Parse(typeof(DateType), parameter3.MemberValue.ObjToString(), false); + double time = 1; + switch (type) + { + case DateType.Year: + time = 1 * 365; + break; + case DateType.Month: + time = 1 *30; + break; + case DateType.Day: + break; + case DateType.Hour: + time = 1 / 24.0; + break; + case DateType.Second: + time = 1 / 24.0/60.0/60.0; + break; + case DateType.Minute: + time = 1 / 24.0/60.0; + break; + case DateType.Millisecond: + time = 1 / 24.0 / 60.0 / 60.0/1000; + break; + } + return string.Format("({0}+({1}*{2})) ", parameter.MemberName, time,parameter2.MemberName); + } + + public override string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format("({0}+(1*{1})) ", parameter.MemberName, parameter2.MemberName); + } + + public override string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS VARCHAR2(4000))", parameter.MemberName); + } + + public override string ToDate(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" to_date({0},'yyyy-mm-dd hh24:mi:ss')", parameter.MemberName); + } + public override string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'||{1}||'%') ", parameter.MemberName, parameter2.MemberName); + } + public override string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like {1}||'%') ", parameter.MemberName, parameter2.MemberName); + } + public override string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'||{1}) ", parameter.MemberName, parameter2.MemberName); + } + public override string Trim(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" trim({0}) ", parameter.MemberName); + } + public override string DateIsSameDay(MethodCallExpressionModel model) + { + throw new NotSupportedException("Oracle NotSupportedException DateIsSameDay"); + } + public override string DateIsSameByType(MethodCallExpressionModel model) + { + throw new NotSupportedException("Oracle NotSupportedException DateIsSameDay"); + } + public override string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" LENGTH({0}) ", parameter.MemberName); + } + + public override string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("NVL({0},{1})", parameter.MemberName, parameter1.MemberName); + } + + public override string MergeString(params string[] strings) + { + return string.Join("||", strings); + } + + public override string GetDate() + { + return "sysdate"; + } + + public override string GetRandom() + { + return "dbms_random.value"; + } + + public override string CharIndex(MethodCallExpressionModel model) + { + return string.Format("instr ({0},{1},1,1) ", model.Args[0].MemberName, model.Args[1].MemberName); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleInsertBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleInsertBuilder.cs new file mode 100644 index 0000000..892f40d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleInsertBuilder.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleInsertBuilder : InsertBuilder + { + public override string SqlTemplate + { + get + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) "; + + } + } + public override string SqlTemplateBatch + { + get + { + return "INSERT INTO {0} ({1})"; + } + } + public override string ToSqlString() + { + var identities = this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).ToList(); + if (IsNoInsertNull) + { + DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList(); + } + var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); + var isSingle = groupList.Count() == 1; + string columnsString = string.Join(",", groupList.First().Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + if (isSingle) + { + string columnParametersString = string.Join(",", this.DbColumnInfoList.Select(it => Builder.SqlParameterKeyWord + it.DbColumnName)); + if (identities.HasValue()) + { + columnsString = columnsString.TrimEnd(',') + "," + string.Join(",", identities.Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + columnParametersString = columnParametersString.TrimEnd(',') + "," + string.Join(",", identities.Select(it => it.OracleSequenceName + ".nextval")); + } + return string.Format(SqlTemplate, GetTableNameString, columnsString, columnParametersString); + } + else + { + StringBuilder batchInsetrSql = new StringBuilder(); + int pageSize = 200; + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + if (identities.HasValue()) + { + columnsString = columnsString.TrimEnd(',') + "," + string.Join(",", identities.Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + } + while (pageCount >= pageIndex) + { + batchInsetrSql.AppendFormat(SqlTemplateBatch, GetTableNameString, columnsString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + batchInsetrSql.Append(SqlTemplateBatchUnion); + } + var insertColumns = string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value), Builder.GetTranslationColumnName(it.DbColumnName)))); + if (identities.HasValue()) + { + insertColumns = insertColumns.TrimEnd(',') + "," + string.Join(",", identities.Select(it => + { + var seqValue = this.OracleSeqInfoList[it.OracleSequenceName]; + this.OracleSeqInfoList[it.OracleSequenceName] = this.OracleSeqInfoList[it.OracleSequenceName] + 1; + return seqValue + 1+" AS "+it.DbColumnName; + })); + } + batchInsetrSql.Append("\r\n SELECT " + insertColumns + " FROM DUAL "); + ++i; + } + pageIndex++; + batchInsetrSql.Append("\r\n;\r\n"); + } + return "BEGIN\r\n"+ batchInsetrSql.ToString()+"\r\nEND;"; + } + } + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "to_date('"+ date.ToString("yyyy-MM-dd HH:mm:ss") + "', 'YYYY-MM-DD HH24:MI:SS') "; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "N'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "N'" + value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleQueryBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleQueryBuilder.cs new file mode 100644 index 0000000..b81f025 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleQueryBuilder.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleQueryBuilder : QueryBuilder + { + public override bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS ""\w+\.\w+"""); + } + public override string SqlTemplate + { + get + { + return "SELECT {0}{"+UtilConstants.ReplaceKey+"} FROM {1}{2}{3}{4}"; + } + } + public override string ToSqlString() + { + string oldOrderBy = this.OrderByValue; + string externalOrderBy = oldOrderBy; + var isIgnoreOrderBy = this.IsCount && this.PartitionByValue.IsNullOrEmpty(); + AppendFilter(); + sql = new StringBuilder(); + if (this.OrderByValue == null && (Skip != null || Take != null)) this.OrderByValue = " ORDER BY "+ this.Builder.SqlDateNow + " "; + if (this.PartitionByValue.HasValue()) + { + this.OrderByValue = this.PartitionByValue + this.OrderByValue; + } + var isRowNumber = Skip != null || Take != null; + var rowNumberString = string.Format(",ROW_NUMBER() OVER({0}) AS RowIndex ", GetOrderByString); + string groupByValue = GetGroupByString + HavingInfos; + string orderByValue = (!isRowNumber && this.OrderByValue.HasValue()) ? GetOrderByString : null; + if (isIgnoreOrderBy) { orderByValue = null; } + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, groupByValue, orderByValue); + sql.Replace(UtilConstants.ReplaceKey, isRowNumber ? (isIgnoreOrderBy ? null : rowNumberString) : null); + if (isIgnoreOrderBy) { this.OrderByValue = oldOrderBy; return sql.ToString(); } + var result = ToPageSql(sql.ToString(), this.Take, this.Skip); + if (ExternalPageIndex > 0) + { + if (externalOrderBy.IsNullOrEmpty()) + { + externalOrderBy = " ORDER BY "+ this.Builder.SqlDateNow + " "; + } + result = string.Format("SELECT *,ROW_NUMBER() OVER({0}) AS RowIndex2 FROM ({1}) ExternalTable ", GetExternalOrderBy(externalOrderBy), result); + result = ToPageSql2(result, ExternalPageIndex, ExternalPageSize, true); + } + this.OrderByValue = oldOrderBy; + return result; + } + public override string ToPageSql(string sql, int? take, int? skip, bool isExternal = false) + { + string temp = isExternal ? ExternalPageTempalte : PageTempalte; + if (skip != null && take == null) + { + return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, long.MaxValue); + } + else if (skip == null && take != null) + { + return string.Format(temp, sql.ToString(), 1, take.ObjToInt()); + } + else if (skip != null && take != null) + { + return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, skip.ObjToInt() + take.ObjToInt()); + } + else + { + return sql.ToString(); + } + } + + public override string ToPageSql2(string sql, int? pageIndex, int? pageSize, bool isExternal = false) + { + string temp = isExternal ? ExternalPageTempalte : PageTempalte; + return string.Format(temp, sql.ToString(), (pageIndex - 1) * pageSize + 1, pageIndex * pageSize); + } + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleUpdateBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleUpdateBuilder.cs new file mode 100644 index 0000000..6023222 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/SqlBuilder/OracleUpdateBuilder.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleUpdateBuilder : UpdateBuilder + { + protected override string TomultipleSqlString(List> groupList) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("Begin"); + sb.AppendLine(string.Join("\r\n", groupList.Select(t => + { + var updateTable = string.Format("UPDATE {0} SET", base.GetTableNameStringNoWith); + var setValues = string.Join(",", t.Where(s => !s.IsPrimarykey).Select(m => GetOracleUpdateColums(m)).ToArray()); + var pkList = t.Where(s => s.IsPrimarykey).ToList(); + List whereList = new List(); + foreach (var item in pkList) + { + var isFirst = pkList.First() == item; + var whereString = isFirst ? " " : " AND "; + whereString += GetOracleUpdateColums(item); + whereList.Add(whereString); + } + return string.Format("{0} {1} WHERE {2};", updateTable, setValues, string.Join("",whereList)); + }).ToArray())); + sb.AppendLine("End;"); + return sb.ToString(); + } + + private string GetOracleUpdateColums(DbColumnInfo m) + { + return string.Format("\"{0}\"={1}", m.DbColumnName.ToUpper(), FormatValue(m.Value)); + } + + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "to_date('" + date.ToString("yyyy-MM-dd HH:mm:ss") + "', 'YYYY-MM-DD HH24:MI:SS') "; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "N'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "N'" + value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Oracle/Updateable/OracleUpdateable.cs b/类库/SqlSugar/5.0.0.9/Realization/Oracle/Updateable/OracleUpdateable.cs new file mode 100644 index 0000000..c8a985a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Oracle/Updateable/OracleUpdateable.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleUpdateable : UpdateableProvider where T : class, new() + { + protected override List GetIdentityKeys() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.DbColumnName).ToList(); + } + public override int ExecuteCommand() + { + if (base.UpdateObjs.Count() == 1) + { + return base.ExecuteCommand(); + } + else + { + base.ExecuteCommand(); + return base.UpdateObjs.Count(); + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/CodeFirst/PostgreSQLCodeFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/CodeFirst/PostgreSQLCodeFirst.cs new file mode 100644 index 0000000..bd89f5f --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/CodeFirst/PostgreSQLCodeFirst.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class PostgreSQLCodeFirst : CodeFirstProvider + { + public override void NoExistLogic(EntityInfo entityInfo) + { + var tableName = GetTableName(entityInfo); + //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns.Where(it=>it.IsIgnore==false)) + { + DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item); + columns.Add(dbColumnInfo); + } + } + this.Context.DbMaintenance.CreateTable(tableName, columns,true); + } + protected override DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + var propertyType = UtilMethods.GetUnderType(item.PropertyInfo); + var result = new DbColumnInfo() + { + TableId = entityInfo.Columns.IndexOf(item), + DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName, + IsPrimarykey = item.IsPrimarykey, + IsIdentity = item.IsIdentity, + TableName = tableName, + IsNullable = item.IsNullable, + DefaultValue = item.DefaultValue, + ColumnDescription = item.ColumnDescription, + Length = item.Length + }; + GetDbType(item, propertyType, result); + if (result.DataType.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.Length == 0) + { + result.Length = 1; + } + return result; + } + + protected override void ConvertColumns(List dbColumns) + { + foreach (var item in dbColumns) + { + if (item.DataType == "DateTime") + { + item.Length = 0; + } + } + } + + protected override void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + if (!item.IsPrimarykey) + this.Context.DbMaintenance.DropConstraint(tableName,null); + if (item.IsPrimarykey) + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbBind/PostgreSQLDbBind.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbBind/PostgreSQLDbBind.cs new file mode 100644 index 0000000..41f98a5 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbBind/PostgreSQLDbBind.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SqlSugar +{ + public class PostgreSQLDbBind : DbBindProvider + { + public override string GetPropertyTypeName(string dbTypeName) + { + dbTypeName = dbTypeName.ToLower(); + var propertyTypes = MappingTypes.Where(it => it.Value.ToString().ToLower() == dbTypeName || it.Key.ToLower() == dbTypeName); + if (propertyTypes == null) + { + return "other"; + } + else if (dbTypeName == "xml" || dbTypeName == "string"|| dbTypeName == "jsonb"|| dbTypeName == "json") + { + return "string"; + }else if (dbTypeName == "bpchar")//数据库char datatype 查询出来的时候是 bpchar + { + return "char"; + } + if (dbTypeName == "byte[]") + { + return "byte[]"; + } + else if (propertyTypes == null || propertyTypes.Count() == 0) + { + Check.ThrowNotSupportedException(string.Format(" \"{0}\" Type NotSupported, DbBindProvider.GetPropertyTypeName error.", dbTypeName)); + return null; + } + else if (propertyTypes.First().Value == CSharpDataType.byteArray) + { + return "byte[]"; + } + else + { + return propertyTypes.First().Value.ToString(); + } + } + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null && extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>(){ + + new KeyValuePair("int2",CSharpDataType.@short), + new KeyValuePair("smallint",CSharpDataType.@short), + new KeyValuePair("int4",CSharpDataType.@int), + new KeyValuePair("integer",CSharpDataType.@int), + new KeyValuePair("int8",CSharpDataType.@long), + new KeyValuePair("bigint",CSharpDataType.@long), + new KeyValuePair("float4",CSharpDataType.@float), + new KeyValuePair("real",CSharpDataType.@float), + new KeyValuePair("float8",CSharpDataType.@double), + new KeyValuePair("double precision",CSharpDataType.@int), + new KeyValuePair("numeric",CSharpDataType.@decimal), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("path",CSharpDataType.@decimal), + new KeyValuePair("point",CSharpDataType.@decimal), + new KeyValuePair("polygon",CSharpDataType.@decimal), + + new KeyValuePair("boolean",CSharpDataType.@bool), + new KeyValuePair("bool",CSharpDataType.@bool), + new KeyValuePair("box",CSharpDataType.@bool), + new KeyValuePair("bytea",CSharpDataType.@bool), + + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("character varying",CSharpDataType.@string), + new KeyValuePair("text",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("character",CSharpDataType.@string), + new KeyValuePair("cidr",CSharpDataType.@string), + new KeyValuePair("circle",CSharpDataType.@string), + new KeyValuePair("tsquery",CSharpDataType.@string), + new KeyValuePair("tsvector",CSharpDataType.@string), + new KeyValuePair("txid_snapshot",CSharpDataType.@string), + new KeyValuePair("uuid",CSharpDataType.Guid), + new KeyValuePair("xml",CSharpDataType.@string), + new KeyValuePair("json",CSharpDataType.@string), + + new KeyValuePair("interval",CSharpDataType.@decimal), + new KeyValuePair("lseg",CSharpDataType.@decimal), + new KeyValuePair("macaddr",CSharpDataType.@decimal), + new KeyValuePair("money",CSharpDataType.@decimal), + new KeyValuePair("timestamp",CSharpDataType.DateTime), + new KeyValuePair("timestamp with time zone",CSharpDataType.DateTime), + new KeyValuePair("timestamptz",CSharpDataType.DateTime), + new KeyValuePair("timestamp without time zone",CSharpDataType.DateTime), + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("time",CSharpDataType.DateTime), + new KeyValuePair("time with time zone",CSharpDataType.DateTime), + new KeyValuePair("timetz",CSharpDataType.DateTime), + new KeyValuePair("time without time zone",CSharpDataType.DateTime), + + new KeyValuePair("bit",CSharpDataType.byteArray), + new KeyValuePair("bit varying",CSharpDataType.byteArray), + new KeyValuePair("varbit",CSharpDataType.@byte), + + }; + public override List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte" }; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbFirst/PostgreSQLDbFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbFirst/PostgreSQLDbFirst.cs new file mode 100644 index 0000000..fe829d0 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbFirst/PostgreSQLDbFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class PostgreSQLDbFirst : DbFirstProvider + { + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbMaintenance/PostgreSQLDbMaintenance.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbMaintenance/PostgreSQLDbMaintenance.cs new file mode 100644 index 0000000..83145e8 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/DbMaintenance/PostgreSQLDbMaintenance.cs @@ -0,0 +1,363 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class PostgreSQLDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetDataBaseSql + { + get + { + return "SELECT datname FROM pg_database"; + } + } + protected override string GetColumnInfosByTableNameSql + { + get + { + string sql = @"select cast (pclass.oid as int4) as TableId,cast(ptables.tablename as varchar) as TableName, + pcolumn.column_name as DbColumnName,pcolumn.udt_name as DataType, + pcolumn.character_maximum_length as Length, + pcolumn.column_default as DefaultValue, + col_description(pclass.oid, pcolumn.ordinal_position) as ColumnDescription, + case when pkey.colname = pcolumn.column_name + then true else false end as IsPrimaryKey, + case when pcolumn.column_default like 'nextval%' + then true else false end as IsIdentity, + case when pcolumn.is_nullable = 'YES' + then true else false end as IsNullable + from (select * from pg_tables where tablename = '{0}' and schemaname='public') ptables inner join pg_class pclass + on ptables.tablename = pclass.relname inner join (SELECT * + FROM information_schema.columns + ) pcolumn on pcolumn.table_name = ptables.tablename + left join ( + select pg_class.relname,pg_attribute.attname as colname from + pg_constraint inner join pg_class + on pg_constraint.conrelid = pg_class.oid + inner join pg_attribute on pg_attribute.attrelid = pg_class.oid + and pg_attribute.attnum = pg_constraint.conkey[1] + inner join pg_type on pg_type.oid = pg_attribute.atttypid + where pg_constraint.contype='p' + ) pkey on pcolumn.table_name = pkey.relname + order by ptables.tablename"; + return sql; + } + } + protected override string GetTableInfoListSql + { + get + { + return @"select cast(relname as varchar) as Name, + cast(obj_description(relfilenode,'pg_class') as varchar) as Description from pg_class c + where relkind = 'r' and relname not like 'pg_%' and relname not like 'sql_%' order by relname"; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"select cast(relname as varchar) as Name,cast(Description as varchar) from pg_description + join pg_class on pg_description.objoid = pg_class.oid + where objsubid = 0 and relname in (SELECT viewname from pg_views + WHERE schemaname ='public')"; + } + } + #endregion + + #region DDL + protected override string CreateDataBaseSql + { + get + { + return "CREATE DATABASE {0}"; + } + } + protected override string AddPrimaryKeySql + { + get + { + return "ALTER TABLE {0} ADD PRIMARY KEY({2}) /*{1}*/"; + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD COLUMN {1} {2}{3} {4} {5} {6}"; + } + } + protected override string AlterColumnToTableSql + { + get + { + return "alter table {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}"; + } + } + protected override string BackupDataBaseSql + { + get + { + return "mysqldump.exe {0} -uroot -p > {1} "; + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1} $PrimaryKey)"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "TRUNCATE TABLE {0}"; + } + } + protected override string BackupTableSql + { + get + { + return "create table {0} as (select * from {1} limit {2} offset 0)"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + return "ALTER TABLE {0} DROP COLUMN {1}"; + } + } + protected override string DropConstraintSql + { + get + { + return "ALTER TABLE {0} DROP CONSTRAINT {1}"; + } + } + protected override string RenameColumnSql + { + get + { + return "ALTER TABLE {0} RENAME {1} TO {2}"; + } + } + protected override string AddColumnRemarkSql => "comment on column {1}.{0} is '{2}'"; + + protected override string DeleteColumnRemarkSql => "comment on column {1}.{0} is ''"; + + protected override string IsAnyColumnRemarkSql { get { throw new NotSupportedException(); } } + + protected override string AddTableRemarkSql => "comment on table {0} is '{1}'"; + + protected override string DeleteTableRemarkSql => "comment on table {0} is ''"; + + protected override string IsAnyTableRemarkSql { get { throw new NotSupportedException(); } } + + protected override string RenameTableSql => "alter table 表名 {0} to {1}"; + + protected override string CreateIndexSql + { + get + { + return "CREATE INDEX Index_{0}_{2} ON {0} ({1})"; + } + } + protected override string AddDefaultValueSql + { + get + { + return "ALTER TABLE {0} ALTER COLUMN {1} SET DEFAULT {2}"; + } + } + protected override string IsAnyIndexSql + { + get + { + return " Select count(1) from (SELECT to_regclass('Index_UnitCodeTest1_Id_CreateDate') as c ) t where t.c is not null"; + } + } + + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select 1 from information_schema.columns limit 1 offset 0"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return "DEFAULT NULL"; + } + } + protected override string CreateTableNotNull + { + get + { + return "NOT NULL"; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return "serial"; + } + } + #endregion + + #region Methods + /// + ///by current connection string + /// + /// + /// + public override bool CreateDatabase(string databaseName, string databaseDirectory = null) + { + if (databaseDirectory != null) + { + if (!FileHelper.IsExistDirectory(databaseDirectory)) + { + FileHelper.CreateDirectory(databaseDirectory); + } + } + var oldDatabaseName = this.Context.Ado.Connection.Database; + var connection = this.Context.CurrentConnectionConfig.ConnectionString; + connection = connection.Replace(oldDatabaseName, "postgres"); + var newDb = new SqlSugarClient(new ConnectionConfig() + { + DbType = this.Context.CurrentConnectionConfig.DbType, + IsAutoCloseConnection = true, + ConnectionString = connection + }); + if (!GetDataBaseList(newDb).Any(it => it.Equals(databaseName, StringComparison.CurrentCultureIgnoreCase))) + { + newDb.Ado.ExecuteCommand(string.Format(CreateDataBaseSql, this.SqlBuilder.SqlTranslationLeft+databaseName+this.SqlBuilder.SqlTranslationRight, databaseDirectory)); + } + return true; + } + public override bool AddRemark(EntityInfo entity) + { + var db = this.Context; + var columns = entity.Columns.Where(it => it.IsIgnore == false).ToList(); + + foreach (var item in columns) + { + if (item.ColumnDescription != null) + { + db.DbMaintenance.AddColumnRemark(item.DbColumnName, item.DbTableName, item.ColumnDescription); + + } + } + //table remak + if (entity.TableDescription != null) + { + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + return true; + } + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + if (columns.HasValue()) + { + foreach (var item in columns) + { + if (item.DbColumnName.Equals("GUID", StringComparison.CurrentCultureIgnoreCase) && item.Length == 0) + { + item.Length = 10; + } + } + } + string sql = GetCreateTableSql(tableName, columns); + string primaryKeyInfo = null; + if (columns.Any(it => it.IsPrimarykey) && isCreatePrimaryKey) + { + primaryKeyInfo = string.Format(", Primary key({0})", string.Join(",", columns.Where(it => it.IsPrimarykey).Select(it => this.SqlBuilder.GetTranslationColumnName(it.DbColumnName.ToLower())))); + + } + sql = sql.Replace("$PrimaryKey", primaryKeyInfo); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + protected override string GetCreateTableSql(string tableName, List columns) + { + List columnArray = new List(); + Check.Exception(columns.IsNullOrEmpty(), "No columns found "); + foreach (var item in columns) + { + string columnName = item.DbColumnName; + string dataType = item.DataType; + if (dataType == "varchar" && item.Length == 0) + { + item.Length = 1; + } + if (dataType == "uuid") + { + item.Length = 50; + dataType = "varchar"; + } + string dataSize = item.Length > 0 ? string.Format("({0})", item.Length) : null; + string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string addItem = string.Format(this.CreateTableColumn, this.SqlBuilder.GetTranslationColumnName(columnName.ToLower()), dataType, dataSize, nullType, primaryKey, ""); + if (item.IsIdentity) + { + string length = dataType.Substring(dataType.Length - 1); + string identityDataType = "serial" + length; + addItem = addItem.Replace(dataType, identityDataType); + } + columnArray.Add(addItem); + } + string tableString = string.Format(this.CreateTableSql, this.SqlBuilder.GetTranslationTableName(tableName.ToLower()), string.Join(",\r\n", columnArray)); + return tableString; + } + public override bool IsAnyConstraint(string constraintName) + { + throw new NotSupportedException("PgSql IsAnyConstraint NotSupportedException"); + } + public override bool BackupDataBase(string databaseName, string fullFileName) + { + Check.ThrowNotSupportedException("PgSql BackupDataBase NotSupported"); + return false; + } + + public override List GetColumnInfosByTableName(string tableName, bool isCache = true) + { + return base.GetColumnInfosByTableName(tableName.TrimEnd('"').TrimStart('"').ToLower(), isCache); + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/Insertable/PostgreSQLInserttable.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/Insertable/PostgreSQLInserttable.cs new file mode 100644 index 0000000..06ddf6d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/Insertable/PostgreSQLInserttable.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class PostgreSQLInserttable : InsertableProvider where T : class, new() + { + public override int ExecuteReturnIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + string sql = InsertBuilder.ToSqlString().Replace("$PrimaryKey", GetIdentityKeys().FirstOrDefault()); + RestoreMapping(); + var result = Ado.GetScalar(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()).ObjToInt(); + return result; + } + public override async Task ExecuteReturnIdentityAsync() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + string sql = InsertBuilder.ToSqlString().Replace("$PrimaryKey", GetIdentityKeys().FirstOrDefault()); + RestoreMapping(); + var obj = await Ado.GetScalarAsync(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + var result = obj.ObjToInt(); + return result; + } + public override KeyValuePair> ToSql() + { + var result= base.ToSql(); + return new KeyValuePair>(result.Key.Replace("$PrimaryKey", GetPrimaryKeys().FirstOrDefault()), result.Value); + } + + public override long ExecuteReturnBigIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + string sql = InsertBuilder.ToSqlString().Replace("$PrimaryKey", GetIdentityKeys().FirstOrDefault()); + RestoreMapping(); + var result = Convert.ToInt64(Ado.GetScalar(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()) ?? "0"); + return result; + } + public override async Task ExecuteReturnBigIdentityAsync() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + string sql = InsertBuilder.ToSqlString().Replace("$PrimaryKey", GetIdentityKeys().FirstOrDefault()); + RestoreMapping(); + var result = Convert.ToInt64(await Ado.GetScalarAsync(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()) ?? "0"); + return result; + } + + public override bool ExecuteCommandIdentityIntoEntity() + { + var result = InsertObjs.First(); + var identityKeys = GetIdentityKeys(); + if (identityKeys.Count == 0) { return this.ExecuteCommand() > 0; } + var idValue = ExecuteReturnBigIdentity(); + Check.Exception(identityKeys.Count > 1, "ExecuteCommandIdentityIntoEntity does not support multiple identity keys"); + var identityKey = identityKeys.First(); + object setValue = 0; + if (idValue > int.MaxValue) + setValue = idValue; + else + setValue = Convert.ToInt32(idValue); + var propertyName = this.Context.EntityMaintenance.GetPropertyName(identityKey); + typeof(T).GetProperties().First(t => t.Name.ToUpper() == propertyName.ToUpper()).SetValue(result, setValue, null); + return idValue > 0; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/PostgreSQLProvider.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/PostgreSQLProvider.cs new file mode 100644 index 0000000..db992ca --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/PostgreSQLProvider.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Npgsql; + +namespace SqlSugar +{ + public partial class PostgreSQLProvider : AdoProvider + { + public PostgreSQLProvider() { } + public override IDbConnection Connection + { + get + { + if (base._DbConnection == null) + { + try + { + var npgsqlConnectionString = base.Context.CurrentConnectionConfig.ConnectionString; + base._DbConnection = new NpgsqlConnection(npgsqlConnectionString); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + + public override void BeginTran(string transactionName) + { + base.BeginTran(); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + base.BeginTran(iso); + } + public override IDataAdapter GetAdapter() + { + return new NpgsqlDataAdapter(); + } + public override DbCommand GetCommand(string sql, SugarParameter[] parameters) + { + NpgsqlCommand sqlCommand = new NpgsqlCommand(sql, (NpgsqlConnection)this.Connection); + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (NpgsqlTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + IDataParameter[] ipars = ToIDbDataParameter(parameters); + sqlCommand.Parameters.AddRange((NpgsqlParameter[])ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, DbCommand command) + { + ((NpgsqlDataAdapter)dataAdapter).SelectCommand = (NpgsqlCommand)command; + } + /// + /// if mysql return MySqlParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + NpgsqlParameter[] result = new NpgsqlParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + var sqlParameter = new NpgsqlParameter(); + sqlParameter.ParameterName = parameter.ParameterName; + sqlParameter.Size = parameter.Size; + sqlParameter.Value = parameter.Value; + sqlParameter.DbType = parameter.DbType; + sqlParameter.Direction = parameter.Direction; + if (sqlParameter.Direction == 0) + { + sqlParameter.Direction = ParameterDirection.Input; + } + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput, ParameterDirection.ReturnValue)) + { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/Queryable/PostgreSqlQueryable.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/Queryable/PostgreSqlQueryable.cs new file mode 100644 index 0000000..c4b1de6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/Queryable/PostgreSqlQueryable.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class PostgreSQLQueryable : QueryableProvider + { + public override ISugarQueryable With(string withString) + { + return this; + } + + public override ISugarQueryable PartitionBy(string groupFileds) + { + this.GroupBy(groupFileds); + return this; + } + } + public class PostgreSQLQueryable : QueryableProvider + { + public new ISugarQueryable With(string withString) + { + return this; + } + } + public class PostgreSQLQueryable : QueryableProvider + { + + } + public class PostgreSQLQueryable : QueryableProvider + { + + } + public class PostgreSQLQueryable : QueryableProvider + { + + } + public class PostgreSQLQueryable : QueryableProvider + { + + } + public class PostgreSQLQueryable : QueryableProvider + { + + } + public class PostgreSqlQueryable : QueryableProvider + { + + } + public class PostgreSQLQueryable : QueryableProvider + { + + } + public class PostgreSQLQueryable : QueryableProvider + { + + } + public class PostgreSQLQueryable : QueryableProvider + { + + } + public class PostgreSQLQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLBuilder.cs new file mode 100644 index 0000000..b64ffd2 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLBuilder.cs @@ -0,0 +1,88 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class PostgreSQLBuilder : SqlBuilderProvider + { + public override string SqlTranslationLeft + { + get + { + return "\""; + } + } + public override string SqlTranslationRight + { + get + { + return "\""; + } + } + public override string SqlDateNow + { + get + { + return "current_date"; + } + } + public override string FullSqlDateNow + { + get + { + return "select current_date"; + } + } + public override string GetTranslationColumnName(string propertyName) + { + if (propertyName.Contains(SqlTranslationLeft)) return propertyName; + else + return SqlTranslationLeft + propertyName.ToLower() + SqlTranslationRight; + } + + //public override string GetNoTranslationColumnName(string name) + //{ + // return name.TrimEnd(Convert.ToChar(SqlTranslationRight)).TrimStart(Convert.ToChar(SqlTranslationLeft)).ToLower(); + //} + public override string GetTranslationColumnName(string entityName, string propertyName) + { + Check.ArgumentNullException(entityName, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + Check.ArgumentNullException(propertyName, string.Format(ErrorMessage.ObjNotExist, "Column Name")); + var context = this.Context; + var mappingInfo = context + .MappingColumns + .FirstOrDefault(it => + it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase) && + it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + return (mappingInfo == null ? SqlTranslationLeft + propertyName.ToLower() + SqlTranslationRight : SqlTranslationLeft + mappingInfo.DbColumnName.ToLower() + SqlTranslationRight); + } + + public override string GetTranslationTableName(string name) + { + Check.ArgumentNullException(name, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + var context = this.Context; + + var mappingInfo = context + .MappingTables + .FirstOrDefault(it => it.EntityName.Equals(name, StringComparison.CurrentCultureIgnoreCase)); + name = (mappingInfo == null ? name : mappingInfo.DbTableName); + if (name.Contains(".")&& !name.Contains("(")) + { + return string.Join(".", name.ToLower().Split('.').Select(it => SqlTranslationLeft + it + SqlTranslationRight)); + } + else if (name.Contains("(")) + { + return name; + } + else if (name.Contains(SqlTranslationLeft) && name.Contains(SqlTranslationRight)) + { + return name; + } + else + { + return SqlTranslationLeft + name.ToLower().TrimEnd('"').TrimStart('"') + SqlTranslationRight; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLDeleteBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLDeleteBuilder.cs new file mode 100644 index 0000000..57f4ba3 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLDeleteBuilder.cs @@ -0,0 +1,7 @@ +namespace SqlSugar +{ + public class PostgreSQLDeleteBuilder : DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLExpressionContext.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLExpressionContext.cs new file mode 100644 index 0000000..bdb70fb --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLExpressionContext.cs @@ -0,0 +1,250 @@ +using System; +using System.Linq; +namespace SqlSugar +{ + public class PostgreSQLExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarProvider Context { get; set; } + public PostgreSQLExpressionContext() + { + base.DbMehtods = new PostgreSQLMethod(); + } + public override string SqlTranslationLeft + { + get + { + return "\""; + } + } + public override string SqlTranslationRight + { + get + { + return "\""; + } + } + public override string GetTranslationText(string name) + { + return SqlTranslationLeft + name.ToLower() + SqlTranslationRight; + } + public override string GetTranslationTableName(string entityName, bool isMapping = true) + { + Check.ArgumentNullException(entityName, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + if (IsTranslationText(entityName)) return entityName; + isMapping = isMapping && this.MappingTables.HasValue(); + var isComplex = entityName.Contains(UtilConstants.Dot); + if (isMapping && isComplex) + { + var columnInfo = entityName.Split(UtilConstants.DotChar); + var mappingInfo = this.MappingTables.FirstOrDefault(it => it.EntityName.Equals(columnInfo.Last(), StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null) + { + columnInfo[columnInfo.Length - 1] = mappingInfo.EntityName; + } + return string.Join(UtilConstants.Dot, columnInfo.Select(it => GetTranslationText(it))); + } + else if (isMapping) + { + var mappingInfo = this.MappingTables.FirstOrDefault(it => it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase)); + return SqlTranslationLeft + (mappingInfo == null ? entityName : mappingInfo.DbTableName).ToLower() + SqlTranslationRight; + } + else if (isComplex) + { + return string.Join(UtilConstants.Dot, entityName.Split(UtilConstants.DotChar).Select(it => GetTranslationText(it))); + } + else + { + return GetTranslationText(entityName); + } + } + public override string GetTranslationColumnName(string columnName) + { + Check.ArgumentNullException(columnName, string.Format(ErrorMessage.ObjNotExist, "Column Name")); + if (columnName.Substring(0, 1) == this.SqlParameterKeyWord) + { + return columnName; + } + if (IsTranslationText(columnName)) return columnName; + if (columnName.Contains(UtilConstants.Dot)) + { + return string.Join(UtilConstants.Dot, columnName.Split(UtilConstants.DotChar).Select(it => GetTranslationText(it))); + } + else + { + return GetTranslationText(columnName); + } + } + public override string GetDbColumnName(string entityName, string propertyName) + { + if (this.MappingColumns.HasValue()) + { + var mappingInfo = this.MappingColumns.SingleOrDefault(it => it.EntityName == entityName && it.PropertyName == propertyName); + return (mappingInfo == null ? propertyName : mappingInfo.DbColumnName).ToLower(); + } + else + { + return propertyName.ToLower(); + } + } + } + public class PostgreSQLMethod : DefaultDbMethod, IDbMethods + { + public override string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var format = "dd"; + if (parameter2.MemberValue.ObjToString() == DateType.Year.ToString()) + { + format = "yyyy"; + } + if (parameter2.MemberValue.ObjToString() == DateType.Month.ToString()) + { + format = "MM"; + } + if (parameter2.MemberValue.ObjToString() == DateType.Day.ToString()) + { + format = "dd"; + } + if (parameter2.MemberValue.ObjToString() == DateType.Hour.ToString()) + { + format = "hh"; + } + if (parameter2.MemberValue.ObjToString() == DateType.Minute.ToString()) + { + format = "mm"; + } + if (parameter2.MemberValue.ObjToString() == DateType.Second.ToString()) + { + format = "ss"; + } + if (parameter2.MemberValue.ObjToString() == DateType.Millisecond.ToString()) + { + format = "ss"; + } + return string.Format(" cast( to_char({1},'{0}')as integer ) ", format, parameter.MemberName); + } + + public override string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat('%',{1},'%')) ", parameter.MemberName, parameter2.MemberName ); + } + + public override string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat({1},'%')) ", parameter.MemberName, parameter2.MemberName); + } + + public override string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat('%',{1}))", parameter.MemberName,parameter2.MemberName); + } + + public override string DateIsSameDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (date_part('day',{0}-{1})=0) ", parameter.MemberName, parameter2.MemberName); ; + } + + public override string DateIsSameByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (date_part('{2}',{0}-{1})=0) ", parameter.MemberName, parameter2.MemberName, parameter3.MemberValue); + } + + public override string ToDate(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS timestamp)", parameter.MemberName); + } + public override string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (DATE_ADD({1} , INTERVAL {2} {0})) ", parameter3.MemberValue, parameter.MemberName, parameter2.MemberName); + } + + public override string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (DATE_ADD({1} INTERVAL {0} day)) ", parameter.MemberName, parameter2.MemberName); + } + + public override string ToInt32(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToInt64(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS VARCHAR)", parameter.MemberName); + } + + public override string ToGuid(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS VARCHAR)", parameter.MemberName); + } + + public override string ToDouble(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string ToBool(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToDecimal(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" LENGTH({0})", parameter.MemberName); + } + public override string MergeString(params string[] strings) + { + return " concat("+string.Join(",", strings).Replace("+", "") + ") "; + } + public override string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("(CASE WHEN {0} IS NULL THEN {1} ELSE {0} END)", parameter.MemberName, parameter1.MemberName); + } + public override string GetDate() + { + return "NOW()"; + } + public override string GetRandom() + { + return "RANDOM()"; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLInsertBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLInsertBuilder.cs new file mode 100644 index 0000000..db2f10e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLInsertBuilder.cs @@ -0,0 +1,93 @@ +using System; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class PostgreSQLInsertBuilder : InsertBuilder + { + public override string SqlTemplate + { + get + { + if (IsReturnIdentity) + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) returning $PrimaryKey"; + } + else + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;"; + + } + } + } + public override string SqlTemplateBatch => "INSERT INTO {0} ({1})"; + public override string SqlTemplateBatchUnion => " VALUES "; + + public override string SqlTemplateBatchSelect => " {0} "; + + public override string ToSqlString() + { + if (IsNoInsertNull) + { + DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList(); + } + var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); + var isSingle = groupList.Count() == 1; + string columnsString = string.Join(",", groupList.First().Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + if (isSingle) + { + string columnParametersString = string.Join(",", this.DbColumnInfoList.Select(it => Builder.SqlParameterKeyWord + it.DbColumnName)); + return string.Format(SqlTemplate, GetTableNameString, columnsString, columnParametersString); + } + else + { + StringBuilder batchInsetrSql = new StringBuilder(); + int pageSize = 200; + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + while (pageCount >= pageIndex) + { + batchInsetrSql.AppendFormat(SqlTemplateBatch, GetTableNameString, columnsString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (isFirst) + { + batchInsetrSql.Append(SqlTemplateBatchUnion); + } + batchInsetrSql.Append("\r\n ( " + string.Join(",", columns.Select(it => + { + object value = null; + if (it.Value is DateTime) + { + value = ((DateTime)it.Value).ToString("O"); + } + else + { + value = it.Value; + } + if (value == null) + { + return string.Format(SqlTemplateBatchSelect, "NULL"); + } + return string.Format(SqlTemplateBatchSelect, "'" + value + "'"); + })) + "),"); + ++i; + } + pageIndex++; + batchInsetrSql.Remove(batchInsetrSql.Length - 1,1).Append("\r\n;\r\n"); + } + return batchInsetrSql.ToString(); + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLQueryBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLQueryBuilder.cs new file mode 100644 index 0000000..5f4b467 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLQueryBuilder.cs @@ -0,0 +1,93 @@ +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public partial class PostgreSQLQueryBuilder : QueryBuilder + { + #region Sql Template + public override string PageTempalte + { + get + { + /* + SELECT * FROM TABLE WHERE CONDITION ORDER BY ID DESC LIMIT 10 offset 0 + */ + var template = "SELECT {0} FROM {1} {2} {3} {4} LIMIT {6} offset {5}"; + return template; + } + } + public override string DefaultOrderByTemplate + { + get + { + return "ORDER BY NOW() "; + } + } + + #endregion + + #region Common Methods + public override bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS \w+\.\w+"); + } + public override string ToSqlString() + { + base.AppendFilter(); + string oldOrderValue = this.OrderByValue; + string result = null; + sql = new StringBuilder(); + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString); + if (IsCount) { return sql.ToString(); } + if (Skip != null && Take == null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString, Skip.ObjToInt(), long.MaxValue); + } + else if (Skip == null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, 0, Take.ObjToInt()); + } + else if (Skip != null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, Skip.ObjToInt() > 0 ? Skip.ObjToInt() : 0, Take); + } + else + { + result = sql.ToString(); + } + this.OrderByValue = oldOrderValue; + return result; + } + + #endregion + + #region Get SQL Partial + public override string GetSelectValue + { + get + { + string result = string.Empty; + if (this.SelectValue == null || this.SelectValue is string) + { + result = GetSelectValueByString(); + } + else + { + result = GetSelectValueByExpression(); + } + if (this.SelectType == ResolveExpressType.SelectMultiple) + { + this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this.JoinQueryInfos.Select(it => it.TableName)); + } + return result; + } + } + + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLUpdateBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLUpdateBuilder.cs new file mode 100644 index 0000000..61c26f2 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/PostgreSQL/SqlBuilder/PostgreSQLUpdateBuilder.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class PostgreSQLUpdateBuilder : UpdateBuilder + { + public override string SqlTemplateBatch + { + get + { + return @"UPDATE {1} {2} SET {0} FROM ${{0}} "; + } + } + public override string SqlTemplateJoin + { + get + { + return @" (VALUES + {0} + + ) AS T ({2}) WHERE {1} + "; + } + } + + public override string SqlTemplateBatchUnion + { + get + { + return ","; + } + } + + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = value.GetType(); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "'" + value.ToString() + "'"; + } + } + } + + protected override string TomultipleSqlString(List> groupList) + { + Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List need Primary key"); + int pageSize = 200; + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + StringBuilder batchUpdateSql = new StringBuilder(); + while (pageCount >= pageIndex) + { + StringBuilder updateTable = new StringBuilder(); + string setValues = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it => + { + if (SetValues.IsValuable()) + { + var setValue = SetValues.Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName)); + if (setValue != null && setValue.Any()) + { + return setValue.First().Value; + } + } + var result = string.Format("{0}=T.{0}", Builder.GetTranslationColumnName(it.DbColumnName)); + return result; + })); + string tempColumnValue = string.Join(",", groupList.First().Select(it => + { + if (SetValues.IsValuable()) + { + var setValue = SetValues.Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName)); + if (setValue != null && setValue.Any()) + { + return setValue.First().Value; + } + } + var result = Builder.GetTranslationColumnName(it.DbColumnName); + return result; + })); + batchUpdateSql.AppendFormat(SqlTemplateBatch.ToString(), setValues, GetTableNameStringNoWith, TableWithString); + int i = 0; + var tableColumnList = this.Context.DbMaintenance.GetColumnInfosByTableName(GetTableNameStringNoWith); + + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + updateTable.Append(SqlTemplateBatchUnion); + } + updateTable.Append("\r\n (" + string.Join(",", columns.Select(it => + { + var columnInfo = tableColumnList.FirstOrDefault(x => x.DbColumnName.Equals(it.DbColumnName, StringComparison.OrdinalIgnoreCase)); + var dbType = columnInfo?.DataType; + if (dbType == null) { + var typeName = it.PropertyType.Name.ToLower(); + if (typeName == "int32") + typeName = "int"; + if (typeName == "int64") + typeName = "long"; + if (typeName == "int16") + typeName = "short"; + + var isAnyType = PostgreSQLDbBind.MappingTypesConst.Where(x => x.Value.ToString().ToLower() == typeName).Any(); + if (isAnyType) + { + dbType = PostgreSQLDbBind.MappingTypesConst.Where(x => x.Value.ToString().ToLower() == typeName).FirstOrDefault().Key; + } + else { + dbType = "varchar"; + } + } + return string.Format("CAST({0} AS {1})", FormatValue(it.Value), dbType); + + })) + ")"); + ++i; + } + pageIndex++; + updateTable.Append("\r\n"); + string whereString = null; + if (this.WhereValues.HasValue()) + { + foreach (var item in WhereValues) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += item; + } + } + else if (PrimaryKeys.HasValue()) + { + foreach (var item in PrimaryKeys) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += string.Format("{0}.{1}=T.{1}", GetTableNameStringNoWith, Builder.GetTranslationColumnName(item)); + } + } + var format = string.Format(SqlTemplateJoin, updateTable, whereString, tempColumnValue); + batchUpdateSql.Replace("${0}", format); + batchUpdateSql.Append(";"); + } + return batchUpdateSql.ToString(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/CodeFirst/SqlServerCodeFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/CodeFirst/SqlServerCodeFirst.cs new file mode 100644 index 0000000..814ef1b --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/CodeFirst/SqlServerCodeFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlServerCodeFirst:CodeFirstProvider + { + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbBind/SqlServerDbBind.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbBind/SqlServerDbBind.cs new file mode 100644 index 0000000..60716cf --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbBind/SqlServerDbBind.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class SqlServerDbBind : DbBindProvider + { + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null&& extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>() + { + new KeyValuePair("int",CSharpDataType.@int), + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("nvarchar",CSharpDataType.@string), + new KeyValuePair("sql_variant",CSharpDataType.@string), + new KeyValuePair("text",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("ntext",CSharpDataType.@string), + new KeyValuePair("nchar",CSharpDataType.@string), + new KeyValuePair("hierarchyid",CSharpDataType.@string), + new KeyValuePair("bigint",CSharpDataType.@long), + new KeyValuePair("bit",CSharpDataType.@bool), + new KeyValuePair("datetime",CSharpDataType.DateTime), + new KeyValuePair("time",CSharpDataType.DateTime), + new KeyValuePair("smalldatetime",CSharpDataType.DateTime), + new KeyValuePair("timestamp",CSharpDataType.byteArray), + new KeyValuePair("datetime2",CSharpDataType.DateTime), + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("single",CSharpDataType.@decimal), + new KeyValuePair("money",CSharpDataType.@decimal), + new KeyValuePair("numeric",CSharpDataType.@decimal), + new KeyValuePair("smallmoney",CSharpDataType.@decimal), + new KeyValuePair("float",CSharpDataType.@double), + new KeyValuePair("float",CSharpDataType.Single), + new KeyValuePair("real",CSharpDataType.@float), + new KeyValuePair("smallint",CSharpDataType.@short), + new KeyValuePair("tinyint",CSharpDataType.@byte), + new KeyValuePair("uniqueidentifier",CSharpDataType.Guid), + new KeyValuePair("binary",CSharpDataType.byteArray), + new KeyValuePair("image",CSharpDataType.byteArray), + new KeyValuePair("varbinary",CSharpDataType.byteArray), + new KeyValuePair("datetimeoffset", CSharpDataType.DateTimeOffset), + new KeyValuePair("datetimeoffset", CSharpDataType.DateTime)}; + }; + +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbFirst/SqlServerDbFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbFirst/SqlServerDbFirst.cs new file mode 100644 index 0000000..dd86e4d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbFirst/SqlServerDbFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlServerDbFirst : DbFirstProvider + { + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbMaintenance/SqlServerDbMaintenance.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbMaintenance/SqlServerDbMaintenance.cs new file mode 100644 index 0000000..20716c1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/DbMaintenance/SqlServerDbMaintenance.cs @@ -0,0 +1,404 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlServerDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetDataBaseSql + { + get + { + return "SELECT NAME FROM MASTER.DBO.SYSDATABASES ORDER BY NAME"; + } + } + protected override string GetColumnInfosByTableNameSql + { + get + { + string sql = @"SELECT sysobjects.name AS TableName, + syscolumns.Id AS TableId, + syscolumns.name AS DbColumnName, + systypes.name AS DataType, + syscolumns.length AS [Length], + sys.extended_properties.[value] AS [ColumnDescription], + syscomments.text AS DefaultValue, + syscolumns.isnullable AS IsNullable, + columnproperty(syscolumns.id,syscolumns.name,'IsIdentity')as IsIdentity, + (CASE + WHEN EXISTS + ( + select 1 + from sysindexes i + join sysindexkeys k on i.id = k.id and i.indid = k.indid + join sysobjects o on i.id = o.id + join syscolumns c on i.id=c.id and k.colid = c.colid + where o.xtype = 'U' + and exists(select 1 from sysobjects where xtype = 'PK' and name = i.name) + and o.name=sysobjects.name and c.name=syscolumns.name + ) THEN 1 + ELSE 0 + END) AS IsPrimaryKey + FROM syscolumns + INNER JOIN systypes ON syscolumns.xtype = systypes.xtype + LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id + LEFT OUTER JOIN sys.extended_properties ON (sys.extended_properties.minor_id = syscolumns.colid + AND sys.extended_properties.major_id = syscolumns.id) + LEFT OUTER JOIN syscomments ON syscolumns.cdefault = syscomments.id + WHERE syscolumns.id IN + (SELECT id + FROM sysobjects + WHERE xtype IN('u', + 'v') ) + AND (systypes.name <> 'sysname') + AND sysobjects.name='{0}' + AND systypes.name<>'geometry' + AND systypes.name<>'geography' + ORDER BY syscolumns.colid"; + return sql; + } + } + protected override string GetTableInfoListSql + { + get + { + return @"SELECT s.Name,Convert(varchar(max),tbp.value) as Description + FROM sysobjects s + LEFT JOIN sys.extended_properties as tbp ON s.id=tbp.major_id and tbp.minor_id=0 AND (tbp.Name='MS_Description' OR tbp.Name is null) WHERE s.xtype IN('U') "; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"SELECT s.Name,Convert(varchar(max),tbp.value) as Description + FROM sysobjects s + LEFT JOIN sys.extended_properties as tbp ON s.id=tbp.major_id and tbp.minor_id=0 AND (tbp.Name='MS_Description' OR tbp.Name is null) WHERE s.xtype IN('V') "; + } + } + #endregion + + #region DDL + protected override string CreateDataBaseSql + { + get + { + return @"create database {0} "; + } + } + protected override string AddPrimaryKeySql + { + get + { + return "ALTER TABLE {0} ADD CONSTRAINT {1} PRIMARY KEY({2})"; + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD {1} {2}{3} {4} {5} {6}"; + } + } + protected override string AlterColumnToTableSql + { + get + { + return "ALTER TABLE {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}"; + } + } + protected override string BackupDataBaseSql + { + get + { + return @"USE master;BACKUP DATABASE {0} TO disk = '{1}'"; + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1})"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "TRUNCATE TABLE {0}"; + } + } + protected override string BackupTableSql + { + get + { + return "SELECT TOP {0} * INTO {1} FROM {2}"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + return "ALTER TABLE {0} DROP COLUMN {1}"; + } + } + protected override string DropConstraintSql + { + get + { + return "ALTER TABLE {0} DROP CONSTRAINT {1}"; + } + } + protected override string RenameColumnSql + { + get + { + return "exec sp_rename '{0}.{1}','{2}','column';"; + } + } + protected override string AddColumnRemarkSql + { + get + { + return "EXECUTE sp_addextendedproperty N'MS_Description', '{2}', N'user', N'dbo', N'table', N'{1}', N'column', N'{0}'"; ; + } + } + + protected override string DeleteColumnRemarkSql + { + get + { + return "EXEC sp_dropextendedproperty 'MS_Description','user',dbo,'table','{1}','column',{0}"; + } + + } + + protected override string IsAnyColumnRemarkSql + { + get + { + return @"SELECT" + + " A.name AS table_name," + + " B.name AS column_name," + + " C.value AS column_description" + + " FROM sys.tables A" + + " LEFT JOIN sys.extended_properties C ON C.major_id = A.object_id" + + " LEFT JOIN sys.columns B ON B.object_id = A.object_id AND C.minor_id = B.column_id" + + " INNER JOIN sys.schemas SC ON SC.schema_id = A.schema_id AND SC.name = 'dbo'" + + " WHERE A.name = '{1}' and b.name = '{0}'"; + + } + } + + protected override string AddTableRemarkSql + { + get + { + return "EXECUTE sp_addextendedproperty N'MS_Description', '{1}', N'user', N'dbo', N'table', N'{0}', NULL, NULL"; + } + } + + protected override string DeleteTableRemarkSql + { + get + { + return "EXEC sp_dropextendedproperty 'MS_Description','user',dbo,'table','{0}' "; + } + + } + + protected override string IsAnyTableRemarkSql + { + get + { + return @"SELECT C.class_desc + FROM sys.tables A + LEFT JOIN sys.extended_properties C ON C.major_id = A.object_id + INNER JOIN sys.schemas SC ON SC.schema_id=A.schema_id AND SC.name='dbo' + WHERE A.name = '{0}' AND minor_id=0"; + } + + } + + protected override string RenameTableSql + { + get + { + return "EXEC sp_rename '{0}','{1}'"; + } + } + + protected override string CreateIndexSql + { + get + { + return "CREATE NONCLUSTERED INDEX Index_{0}_{2} ON {0}({1})"; + } + } + protected override string AddDefaultValueSql + { + get + { + return "alter table {0} ADD DEFAULT '{2}' FOR {1}"; + } + } + protected override string IsAnyIndexSql + { + get + { + return "select count(*) from sys.indexes where name='{0}'"; + } + } + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select top 1 id from sysobjects"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return "NULL"; + } + } + protected override string CreateTableNotNull + { + get + { + return "NOT NULL"; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return "IDENTITY(1,1)"; + } + } + + #endregion + + #region Methods + + /// + ///by current connection string + /// + /// + /// + public override bool CreateDatabase(string databaseName, string databaseDirectory = null) + { + if (databaseDirectory != null) + { + if (!FileHelper.IsExistDirectory(databaseDirectory)) + { + FileHelper.CreateDirectory(databaseDirectory); + } + } + var oldDatabaseName = this.Context.Ado.Connection.Database; + var connection = this.Context.CurrentConnectionConfig.ConnectionString; + connection = connection.Replace(oldDatabaseName, "master"); + var newDb = new SqlSugarClient(new ConnectionConfig() + { + DbType = this.Context.CurrentConnectionConfig.DbType, + IsAutoCloseConnection = true, + ConnectionString = connection + }); + if (!GetDataBaseList(newDb).Any(it => it.Equals(databaseName, StringComparison.CurrentCultureIgnoreCase))) + { + var sql = CreateDataBaseSql; + if (databaseDirectory.HasValue()) + { + sql += @"on primary + ( + name = N'{0}', + filename = N'{1}\{0}.mdf', + size = 10mb, + maxsize = 100mb, + filegrowth = 1mb + ), + ( + name = N'{0}_ndf', + filename = N'{1}\{0}.ndf', + size = 10mb, + maxsize = 100mb, + filegrowth = 10 % + ) + log on + ( + name = N'{0}_log', + filename = N'{1}\{0}.ldf', + size = 100mb, + maxsize = 1gb, + filegrowth = 10mb + ); "; + } + newDb.Ado.ExecuteCommand(string.Format(sql, databaseName, databaseDirectory)); + } + return true; + } + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string sql = GetCreateTableSql(tableName, columns); + this.Context.Ado.ExecuteCommand(sql); + if (isCreatePrimaryKey) + { + var pkColumns = columns.Where(it => it.IsPrimarykey).ToList(); + if (pkColumns.Count > 1) + { + this.Context.DbMaintenance.AddPrimaryKeys(tableName, pkColumns.Select(it => it.DbColumnName).ToArray()); + } + else + { + foreach (var item in pkColumns) + { + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + } + } + return true; + } + public override bool RenameColumn(string tableName, string oldColumnName, string newColumnName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + oldColumnName = this.SqlBuilder.GetTranslationColumnName(oldColumnName); + newColumnName = this.SqlBuilder.GetNoTranslationColumnName(newColumnName); + string sql = string.Format(this.RenameColumnSql, tableName, oldColumnName, newColumnName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/Queryable/SqlServerQueryable.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/Queryable/SqlServerQueryable.cs new file mode 100644 index 0000000..ae13f69 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/Queryable/SqlServerQueryable.cs @@ -0,0 +1,58 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SqlServerQueryable:QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerBuilder.cs new file mode 100644 index 0000000..51fbbf4 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerBuilder.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerBuilder : SqlBuilderProvider + { + public override string SqlTranslationLeft { get { return "["; } } + public override string SqlTranslationRight { get { return "]"; } } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerDeleteBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerDeleteBuilder.cs new file mode 100644 index 0000000..516e451 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerDeleteBuilder.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerDeleteBuilder: DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerExpressionContext.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerExpressionContext.cs new file mode 100644 index 0000000..210f487 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerExpressionContext.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SqlServerExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarProvider Context { get; set; } + public SqlServerExpressionContext() + { + base.DbMehtods = new SqlServerMethod(); + } + + } + public partial class SqlServerMethod : DefaultDbMethod, IDbMethods + { + public override string HasValue(MethodCallExpressionModel model) + { + if (model.Args[0].Type == UtilConstants.GuidType) + { + var parameter = model.Args[0]; + return string.Format("( {0} IS NOT NULL )", parameter.MemberName); + } + else + { + var parameter = model.Args[0]; + return string.Format("( {0}<>'' AND {0} IS NOT NULL )", parameter.MemberName); + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerInsertBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerInsertBuilder.cs new file mode 100644 index 0000000..ecab5d4 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerInsertBuilder.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerInsertBuilder:InsertBuilder + { + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerQueryBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerQueryBuilder.cs new file mode 100644 index 0000000..d463d7e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerQueryBuilder.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerQueryBuilder: QueryBuilder + { + public override string SqlTemplate + { + get + { + return "SELECT {0}{"+UtilConstants.ReplaceKey+"} FROM {1}{2}{3}{4}"; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerUpdateBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerUpdateBuilder.cs new file mode 100644 index 0000000..75a86c4 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlBuilder/SqlServerUpdateBuilder.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerUpdateBuilder: UpdateBuilder + { + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlServerProvider.cs b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlServerProvider.cs new file mode 100644 index 0000000..640ecf6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/SqlServer/SqlServerProvider.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class SqlServerProvider : AdoProvider + { + public SqlServerProvider() { } + public override IDbConnection Connection + { + get + { + if (base._DbConnection == null) + { + try + { + base._DbConnection = new SqlConnection(base.Context.CurrentConnectionConfig.ConnectionString); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + /// + /// Only SqlServer + /// + /// + public override void BeginTran(string transactionName) + { + CheckConnection(); + base.Transaction = ((SqlConnection)this.Connection).BeginTransaction(transactionName); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + CheckConnection(); + base.Transaction = ((SqlConnection)this.Connection).BeginTransaction(iso, transactionName); + } + public override IDataAdapter GetAdapter() + { + return new SqlDataAdapter(); + } + public override DbCommand GetCommand(string sql, SugarParameter[] parameters) + { + SqlCommand sqlCommand = new SqlCommand(sql, (SqlConnection)this.Connection); + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (SqlTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + SqlParameter[] ipars = GetSqlParameter(parameters); + sqlCommand.Parameters.AddRange(ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, DbCommand command) + { + ((SqlDataAdapter)dataAdapter).SelectCommand = (SqlCommand)command; + } + /// + /// if mysql return MySqlParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + SqlParameter[] result = new SqlParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + var sqlParameter = new SqlParameter(); + sqlParameter.ParameterName = parameter.ParameterName; + sqlParameter.UdtTypeName = parameter.UdtTypeName; + sqlParameter.Size = parameter.Size; + sqlParameter.Value = parameter.Value; + sqlParameter.DbType = parameter.DbType; + sqlParameter.Direction = parameter.Direction; + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue)) + { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + ++index; + } + return result; + } + /// + /// if mysql return MySqlParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public SqlParameter[] GetSqlParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + SqlParameter[] result = new SqlParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + var sqlParameter = new SqlParameter(); + sqlParameter.ParameterName = parameter.ParameterName; + sqlParameter.UdtTypeName = parameter.UdtTypeName; + sqlParameter.Size = parameter.Size; + sqlParameter.Value = parameter.Value; + sqlParameter.DbType = parameter.DbType; + if (sqlParameter.Value!=null&& sqlParameter.Value != DBNull.Value && sqlParameter.DbType == System.Data.DbType.DateTime) + { + var date = Convert.ToDateTime(sqlParameter.Value); + if (date==DateTime.MinValue) + { + sqlParameter.Value = Convert.ToDateTime("1753/01/01"); + } + } + sqlParameter.Direction = parameter.Direction; + result[index] = sqlParameter; + if (parameter.TypeName.HasValue()) { + sqlParameter.TypeName = parameter.TypeName; + sqlParameter.SqlDbType = SqlDbType.Structured; + sqlParameter.DbType = System.Data.DbType.Object; + } + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput, ParameterDirection.ReturnValue)) + { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/CodeFirst/SqliteCodeFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/CodeFirst/SqliteCodeFirst.cs new file mode 100644 index 0000000..57a1c3e --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/CodeFirst/SqliteCodeFirst.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqliteCodeFirst : CodeFirstProvider + { + public override void ExistLogic(EntityInfo entityInfo) + { + if (entityInfo.Columns.HasValue()) + { + Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + + var tableName = GetTableName(entityInfo); + var dbColumns = this.Context.DbMaintenance.GetColumnInfosByTableName(tableName); + ConvertColumns(dbColumns); + var entityColumns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToList(); + var dropColumns = dbColumns + .Where(dc => !entityColumns.Any(ec => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(dc => !entityColumns.Any(ec => dc.DbColumnName.Equals(ec.DbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToList(); + var addColumns = entityColumns + .Where(ec => ec.OldDbColumnName.IsNullOrEmpty() || !dbColumns.Any(dc => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(ec => !dbColumns.Any(dc => ec.DbColumnName.Equals(dc.DbColumnName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + //var alterColumns = entityColumns + // .Where(ec => !dbColumns.Any(dc => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + // .Where(ec => + // dbColumns.Any(dc => dc.DbColumnName.Equals(ec.DbColumnName) + // && ((!UtilMethods.GetUnderType(ec.PropertyInfo).IsEnum() && UtilMethods.GetUnderType(ec.PropertyInfo).IsIn(UtilConstants.StringType)) || + + // IsSamgeType(ec, dc)))).ToList(); + var renameColumns = entityColumns + .Where(it => !string.IsNullOrEmpty(it.OldDbColumnName)) + .Where(entityColumn => dbColumns.Any(dbColumn => entityColumn.OldDbColumnName.Equals(dbColumn.DbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToList(); + + + var isChange = false; + foreach (var item in addColumns) + { + this.Context.DbMaintenance.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + isChange = true; + } + foreach (var item in dropColumns) + { + //this.Context.DbMaintenance.DropColumn(tableName, item.DbColumnName); + //isChange = true; + } + //foreach (var item in alterColumns) + //{ + // //this.Context.DbMaintenance.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + // //isChange = true; + //} + foreach (var item in renameColumns) + { + throw new NotSupportedException("rename Column"); + } + + foreach (var item in entityColumns) + { + var dbColumn = dbColumns.FirstOrDefault(dc => dc.DbColumnName.Equals(item.DbColumnName, StringComparison.CurrentCultureIgnoreCase)); + if (dbColumn == null) continue; + bool pkDiff, idEntityDiff; + KeyAction(item, dbColumn, out pkDiff, out idEntityDiff); + if (dbColumn != null && pkDiff && !idEntityDiff) + { + var isAdd = item.IsPrimarykey; + if (isAdd) + { + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + else + { + this.Context.DbMaintenance.DropConstraint(tableName, string.Format("PK_{0}_{1}", tableName, item.DbColumnName)); + } + } + else if (pkDiff || idEntityDiff) + { + ChangeKey(entityInfo, tableName, item); + } + } + if (isChange && base.IsBackupTable) + { + this.Context.DbMaintenance.BackupTable(tableName, tableName + DateTime.Now.ToString("yyyyMMddHHmmss"), MaxBackupDataRows); + } + } + } + public override void NoExistLogic(EntityInfo entityInfo) + { + var tableName = GetTableName(entityInfo); + string backupName=tableName+DateTime.Now.ToString("yyyyMMddHHmmss"); + Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimarykey ? 0 : 1).Where(it=>it.IsIgnore==false)) + { + DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item); + columns.Add(dbColumnInfo); + } + } + this.Context.DbMaintenance.CreateTable(tableName, columns,true); + } + protected override DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + var propertyType = UtilMethods.GetUnderType(item.PropertyInfo); + var result = new DbColumnInfo() + { + TableId = entityInfo.Columns.IndexOf(item), + DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName, + IsPrimarykey = item.IsPrimarykey, + IsIdentity = item.IsIdentity, + TableName = tableName, + IsNullable = item.IsNullable, + DefaultValue = item.DefaultValue, + ColumnDescription = item.ColumnDescription, + Length = item.Length + }; + GetDbType(item, propertyType, result); + if (result.DataType.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.Length == 0) + { + result.Length = 1; + } + return result; + } + + protected override void ConvertColumns(List dbColumns) + { + foreach (var item in dbColumns) + { + if (item.DataType == "DateTime") + { + item.Length = 0; + } + } + } + + protected override void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + if (!item.IsPrimarykey) + this.Context.DbMaintenance.DropConstraint(tableName,null); + if (item.IsPrimarykey) + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbBind/SqliteDbBind.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbBind/SqliteDbBind.cs new file mode 100644 index 0000000..6da28d2 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbBind/SqliteDbBind.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SqlSugar +{ + public class SqliteDbBind : DbBindProvider + { + public override string GetDbTypeName(string csharpTypeName) + { + if (csharpTypeName == UtilConstants.ByteArrayType.Name) + { + return "blob"; + } + if (csharpTypeName == "Int32") + csharpTypeName = "int"; + if (csharpTypeName == "Int16") + csharpTypeName = "short"; + if (csharpTypeName == "Int64") + csharpTypeName = "long"; + if (csharpTypeName == "Boolean") + csharpTypeName = "bool"; + var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)); + return mappings.HasValue() ? mappings.First().Key : "varchar"; + } + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null && extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>() + { + + new KeyValuePair("integer",CSharpDataType.@int), + new KeyValuePair("int",CSharpDataType.@int), + new KeyValuePair("int32",CSharpDataType.@int), + new KeyValuePair("integer32",CSharpDataType.@int), + new KeyValuePair("number",CSharpDataType.@int), + + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("varchar2",CSharpDataType.@string), + new KeyValuePair("nvarchar",CSharpDataType.@string), + new KeyValuePair("nvarchar2",CSharpDataType.@string), + new KeyValuePair("text",CSharpDataType.@string), + new KeyValuePair("ntext",CSharpDataType.@string), + new KeyValuePair("blob_text",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("nchar",CSharpDataType.@string), + new KeyValuePair("num",CSharpDataType.@string), + new KeyValuePair("currency",CSharpDataType.@string), + new KeyValuePair("datetext",CSharpDataType.@string), + new KeyValuePair("word",CSharpDataType.@string), + new KeyValuePair("graphic",CSharpDataType.@string), + + new KeyValuePair("tinyint",CSharpDataType.@byte), + new KeyValuePair("unsignedinteger8",CSharpDataType.@byte), + new KeyValuePair("smallint",CSharpDataType.@short), + new KeyValuePair("int16",CSharpDataType.@short), + new KeyValuePair("bigint",CSharpDataType.@long), + new KeyValuePair("int64",CSharpDataType.@long), + new KeyValuePair("long",CSharpDataType.@long), + new KeyValuePair("integer64",CSharpDataType.@long), + new KeyValuePair("bit",CSharpDataType.@bool), + new KeyValuePair("bool",CSharpDataType.@bool), + new KeyValuePair("boolean",CSharpDataType.@bool), + new KeyValuePair("real",CSharpDataType.@double), + new KeyValuePair("double",CSharpDataType.@double), + new KeyValuePair("float",CSharpDataType.@float), + new KeyValuePair("float",CSharpDataType.Single), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("dec",CSharpDataType.@decimal), + new KeyValuePair("numeric",CSharpDataType.@decimal), + new KeyValuePair("money",CSharpDataType.@decimal), + new KeyValuePair("smallmoney",CSharpDataType.@decimal), + + new KeyValuePair("datetime",CSharpDataType.DateTime), + new KeyValuePair("timestamp",CSharpDataType.DateTime), + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("time",CSharpDataType.DateTime), + + new KeyValuePair("blob",CSharpDataType.byteArray), + new KeyValuePair("clob",CSharpDataType.byteArray), + new KeyValuePair("raw",CSharpDataType.byteArray), + new KeyValuePair("oleobject",CSharpDataType.byteArray), + new KeyValuePair("binary",CSharpDataType.byteArray), + new KeyValuePair("photo",CSharpDataType.byteArray), + new KeyValuePair("picture",CSharpDataType.byteArray), + + new KeyValuePair("uniqueidentifier",CSharpDataType.Guid), + new KeyValuePair("varchar",CSharpDataType.Guid), + new KeyValuePair("guid",CSharpDataType.Guid) + }; + public override List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte"}; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbFirst/SqliteDbFirst.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbFirst/SqliteDbFirst.cs new file mode 100644 index 0000000..cb378dc --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbFirst/SqliteDbFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqliteDbFirst : DbFirstProvider + { + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbMaintenance/SqliteDbMaintenance.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbMaintenance/SqliteDbMaintenance.cs new file mode 100644 index 0000000..50a31e5 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/DbMaintenance/SqliteDbMaintenance.cs @@ -0,0 +1,410 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SQLite; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class SqliteDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetDataBaseSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string GetColumnInfosByTableNameSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string GetTableInfoListSql + { + get + { + return @"select Name from sqlite_master where type='table' and name<>'sqlite_sequence' order by name;"; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"select Name from sqlite_master where type='view' order by name;"; + } + } + #endregion + + #region DDL + protected override string CreateDataBaseSql + { + get + { + return "CREATE DATABASE {0}"; + } + } + protected override string AddPrimaryKeySql + { + get + { + throw new NotSupportedException(); + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD COLUMN {1} {2}{3}"; + } + } + protected override string AlterColumnToTableSql + { + get + { + // return "ALTER TABLE {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}"; + throw new NotSupportedException(); + } + } + protected override string BackupDataBaseSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1} )"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "DELETE FROM {0}"; + } + } + protected override string BackupTableSql + { + get + { + return " CREATE TABLE {0} AS SELECT * FROM {1} limit 0,{2}"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string DropConstraintSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string RenameColumnSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string AddColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string DeleteColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string IsAnyColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string AddTableRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string DeleteTableRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string IsAnyTableRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string RenameTableSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string CreateIndexSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string AddDefaultValueSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string IsAnyIndexSql + { + get + { + throw new NotSupportedException(); + } + } + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select Name from sqlite_master limit 0,1"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return "NULL"; + } + } + protected override string CreateTableNotNull + { + get + { + return "NOT NULL"; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return "AUTOINCREMENT"; + } + } + #endregion + + #region Methods + /// + ///by current connection string + /// + /// + /// + public override bool CreateDatabase(string databaseName, string databaseDirectory = null) + { + var connString=this.Context.CurrentConnectionConfig.ConnectionString; + var path = Regex.Match(connString, @"[a-z,A-Z]\:\\.+\\").Value; + if (path.IsNullOrEmpty()) + { + path = Regex.Match(connString, @"[a-z,A-Z]\:\/.+\/").Value; + } + if (!FileHelper.IsExistDirectory(path)) + { + FileHelper.CreateDirectory(path); + } + this.Context.Ado.Connection.Open(); + this.Context.Ado.Connection.Close(); + return true; + } + public override List GetColumnInfosByTableName(string tableName, bool isCache = true) + { + string cacheKey = "DbMaintenanceProvider.GetColumnInfosByTableName." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + if (!isCache) + { + return GetColumnInfosByTableName(tableName); + } + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + return GetColumnsByTableName(tableName); + + }); + } + public override bool AddRemark(EntityInfo entity) + { + return true; + } + private List GetColumnsByTableName(string tableName) + { + tableName = SqlBuilder.GetTranslationTableName(tableName); + string sql = "select * from " + tableName + " limit 0,1"; + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + using (DbDataReader reader = (SQLiteDataReader)this.Context.Ado.GetDataReader(sql)) + { + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + List result = new List(); + var schemaTable = reader.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + { + DbColumnInfo column = new DbColumnInfo() + { + TableName = tableName, + DataType = row["DataTypeName"].ToString().Trim(), + IsNullable = (bool)row["AllowDBNull"], + IsIdentity = (bool)row["IsAutoIncrement"], + ColumnDescription = null, + DbColumnName = row["ColumnName"].ToString(), + DefaultValue = row["defaultValue"].ToString(), + IsPrimarykey = (bool)row["IsKey"], + Length = Convert.ToInt32(row["ColumnSize"]) + }; + result.Add(column); + } + return result; + } + } + public override bool BackupTable(string oldTableName, string newTableName, int maxBackupDataRows = int.MaxValue) + { + oldTableName = this.SqlBuilder.GetTranslationTableName(oldTableName); + newTableName = this.SqlBuilder.GetTranslationTableName(newTableName); + string sql = string.Format(this.BackupTableSql, newTableName, oldTableName, maxBackupDataRows); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + if (columns.HasValue()) + { + foreach (var item in columns) + { + //if (item.DbColumnName.Equals("GUID", StringComparison.CurrentCultureIgnoreCase)) + //{ + // item.Length = 20; + //} + if (item.IsIdentity && !item.IsPrimarykey) + { + item.IsPrimarykey = true; + Check.Exception(item.DataType == "integer", "Identity only integer type"); + } + } + } + string sql = GetCreateTableSql(tableName, columns); + if (!isCreatePrimaryKey) + { + sql = sql.Replace("PRIMARY KEY AUTOINCREMENT", "").Replace("PRIMARY KEY", ""); + } + this.Context.Ado.ExecuteCommand(sql); + return true; + } + protected override string GetCreateTableSql(string tableName, List columns) + { + List columnArray = new List(); + Check.Exception(columns.IsNullOrEmpty(), "No columns found "); + foreach (var item in columns) + { + string columnName = item.DbColumnName; + string dataType = item.DataType; + if (dataType == "varchar" && item.Length == 0) + { + item.Length = 1; + } + string dataSize = item.Length > 0 ? string.Format("({0})", item.Length) : null; + string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = item.IsPrimarykey ? this.CreateTablePirmaryKey : null; + string identity = item.IsIdentity ? this.CreateTableIdentity : null; + string addItem = string.Format(this.CreateTableColumn, this.SqlBuilder.GetTranslationColumnName(columnName), dataType, dataSize, nullType, primaryKey, identity); + columnArray.Add(addItem); + } + string tableString = string.Format(this.CreateTableSql, this.SqlBuilder.GetTranslationTableName(tableName), string.Join(",\r\n", columnArray)); + tableString = tableString.Replace("`", "\""); + return tableString; + } + public override bool IsAnyConstraint(string constraintName) + { + throw new NotSupportedException("MySql IsAnyConstraint NotSupportedException"); + } + public override bool BackupDataBase(string databaseName, string fullFileName) + { + Check.ThrowNotSupportedException("MySql BackupDataBase NotSupported"); + return false; + } + private List GetListOrCache(string cacheKey, string sql) + { + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + var isEnableLogEvent = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + var reval = this.Context.Ado.SqlQuery(sql); + this.Context.Ado.IsEnableLogEvent = isEnableLogEvent; + return reval; + }); + } + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/Queryable/SqliteQueryable.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/Queryable/SqliteQueryable.cs new file mode 100644 index 0000000..9411159 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/Queryable/SqliteQueryable.cs @@ -0,0 +1,60 @@ +namespace SqlSugar +{ + public class SqliteQueryable:QueryableProvider + { + public override ISugarQueryable With(string withString) + { + return this; + } + + public override ISugarQueryable PartitionBy(string groupFileds) + { + this.GroupBy(groupFileds); + return this; + } + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteBuilder.cs new file mode 100644 index 0000000..4e085ec --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteBuilder.cs @@ -0,0 +1,26 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class SqliteBuilder : SqlBuilderProvider + { + public override string SqlTranslationLeft { get { return "`"; } } + public override string SqlTranslationRight { get { return "`"; } } + public override string SqlDateNow + { + get + { + return "DATETIME('now') "; + } + } + public override string FullSqlDateNow + { + get + { + return "select DATETIME('now') "; + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteDeleteBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteDeleteBuilder.cs new file mode 100644 index 0000000..9c70f83 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteDeleteBuilder.cs @@ -0,0 +1,7 @@ +namespace SqlSugar +{ + public class SqliteDeleteBuilder : DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteExpressionContext.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteExpressionContext.cs new file mode 100644 index 0000000..22494ad --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteExpressionContext.cs @@ -0,0 +1,230 @@ +using System; +using System.Linq; +namespace SqlSugar +{ + public class SqliteExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarProvider Context { get; set; } + public SqliteExpressionContext() + { + base.DbMehtods = new SqliteMethod(); + } + public override string SqlTranslationLeft { get { return "`"; } } + public override string SqlTranslationRight { get { return "`"; } } + } + public class SqliteMethod : DefaultDbMethod, IDbMethods + { + public override string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("LENGTH({0})", parameter.MemberName); + } + + public override string Substring(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("SUBSTR({0},1 + {1},{2})", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + + public override string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'||{1}||'%') ", parameter.MemberName, parameter2.MemberName); + } + + public override string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like {1}||'%') ", parameter.MemberName, parameter2.MemberName); + } + + public override string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'||{1}) ", parameter.MemberName, parameter2.MemberName); + } + + public override string ToInt32(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS INTEGER)", parameter.MemberName); + } + + public override string ToInt64(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS INTEGER)", parameter.MemberName); + } + + public override string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS TEXT)", parameter.MemberName); + } + + public override string ToGuid(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS TEXT)", parameter.MemberName); + } + + public override string ToDouble(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string ToBool(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToDecimal(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string ToDate(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" DATETIME({0})", parameter.MemberName); + } + + public override string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + if (parameter2.MemberValue.ObjToInt() < 0) + { + return string.Format(" DATE(DATETIME({0}), '-{1} days')", parameter.MemberName, Math.Abs(parameter2.MemberValue.ObjToInt())); + } + else + { + return string.Format(" DATE(DATETIME({0}), '+{1} days')", parameter.MemberName, parameter2.MemberValue); + } + } + + public override string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0].MemberName; + var parameter2 = model.Args[1].MemberValue; + var parameter3 = model.Args[2].MemberValue; + if (parameter2.ObjToInt() < 0) + { + return string.Format(" DATETIME(DATETIME({0}), '+{1} {2}s')", parameter, Math.Abs(parameter2.ObjToInt()), parameter3); + } + else + { + return string.Format(" DATETIME(DATETIME({0}), '+{1} {2}s')", parameter, parameter2, parameter3); + } + } + + public override string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var typeName = model.Args[1].MemberValue.ToString(); + var parameter2 = typeName; + var type = (DateType)Enum.Parse(typeof(DateType), parameter2, false); + switch (type) + { + case DateType.Year: + parameter2 = "%Y"; + break; + case DateType.Month: + parameter2 = "%m"; + break; + case DateType.Day: + parameter2 = "%d"; + break; + case DateType.Hour: + parameter2 = "%H"; + break; + case DateType.Second: + parameter2 = "%S"; + break; + case DateType.Minute: + parameter2 = "%M"; + break; + case DateType.Millisecond: + default: + Check.ThrowNotSupportedException(typeName); + break; + } + return string.Format(" CAST(STRFTIME('{1}', DATETIME(DATETIME({0}), 'LOCALTIME')) AS INTEGER)", parameter.MemberName, parameter2); + } + + public override string DateIsSameDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0].MemberName; + var parameter2 = model.Args[1].MemberName; + int time = 1; + return string.Format(" Cast((JulianDay({0}) - JulianDay({1})) *{2} As INTEGER)=0 ", parameter, parameter2, time); + } + public override string DateIsSameByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0].MemberName; + var parameter2 = model.Args[1].MemberName; + var parameter3 = model.Args[2].MemberValue; + var type = (DateType)Enum.Parse(typeof(DateType), parameter3.ObjToString(), false); + int time = 1; + switch (type) + { + case DateType.Year: + time = time * 1 / 365; + break; + case DateType.Month: + time = time * 1 / 30; + break; + case DateType.Day: + break; + case DateType.Hour: + time = time * 24; + break; + case DateType.Second: + time = time * 24 * 60 * 60; + break; + case DateType.Minute: + time = time * 24 * 60; + break; + case DateType.Millisecond: + time = time * 24 * 60 * 60 * 1000; + break; + } + return string.Format(" Cast((JulianDay({0}) - JulianDay({1})) *{2} As INTEGER)", parameter, parameter2, time); + } + + public override string MergeString(params string[] strings) + { + return string.Join("||", strings).Replace("+",""); + } + + public override string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("IFNULL({0},{1})", parameter.MemberName, parameter1.MemberName); + } + + public override string GetDate() + { + return "DATETIME('now')"; + } + + public override string GetRandom() + { + return "RANDOM()"; + } + + public override string CharIndex(MethodCallExpressionModel model) + { + throw new NotSupportedException("Slqite Not Supported CharIndex"); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteInsertBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteInsertBuilder.cs new file mode 100644 index 0000000..e5babf1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteInsertBuilder.cs @@ -0,0 +1,79 @@ +using System; + +namespace SqlSugar +{ + public class SqliteInsertBuilder : InsertBuilder + { + public override string SqlTemplate + { + get + { + if (IsReturnIdentity) + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;SELECT LAST_INSERT_ROWID();"; + } + else + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;"; + + } + } + } + + public override string SqlTemplateBatch + { + get + { + return "INSERT INTO {0} ({1})"; + } + } + + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value); + return bytesString; + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "'"+value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteQueryBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteQueryBuilder.cs new file mode 100644 index 0000000..dc31cd5 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteQueryBuilder.cs @@ -0,0 +1,97 @@ +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public partial class SqliteQueryBuilder : QueryBuilder + { + #region Sql Template + public override string PageTempalte + { + get + { + /* + SELECT * FROM TABLE WHERE CONDITION ORDER BY ID DESC LIMIT 0,10 + */ + var template = "SELECT {0} FROM {1} {2} {3} {4} LIMIT {5},{6}"; + return template; + } + } + public override string DefaultOrderByTemplate + { + get + { + return "ORDER BY DATETIME('now') "; + } + } + + #endregion + + #region Common Methods + public override bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS \`\w+\.\w+\`"); + } + public override string ToSqlString() + { + base.AppendFilter(); + string result = null; + string oldOrderBy = this.OrderByValue; + sql = new StringBuilder(); + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString); + if (IsCount) { return sql.ToString(); } + if (Skip != null && Take == null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result= string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString, Skip.ObjToInt(), long.MaxValue); + } + else if (Skip == null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result= string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, 0, Take.ObjToInt()); + } + else if (Skip != null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result= string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, Skip.ObjToInt() > 0 ? Skip.ObjToInt(): 0, Take); + } + else + { + result= sql.ToString(); + } + this.OrderByValue = oldOrderBy; + return result; + } + + #endregion + + #region Get SQL Partial + public override string GetSelectValue + { + get + { + string reval = string.Empty; + if (this.SelectValue == null || this.SelectValue is string) + { + reval = GetSelectValueByString(); + } + else + { + reval = GetSelectValueByExpression(); + } + if (this.SelectType == ResolveExpressType.SelectMultiple) + { + this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this.JoinQueryInfos.Select(it => it.TableName)); + } + if (IsDistinct) + { + reval = " DISTINCT " + reval; + } + return reval; + } + } + + #endregion + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteUpdateBuilder.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteUpdateBuilder.cs new file mode 100644 index 0000000..4f05306 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqlBuilder/SqliteUpdateBuilder.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqliteUpdateBuilder : UpdateBuilder + { + protected override string TomultipleSqlString(List> groupList) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(string.Join("\r\n", groupList.Select(t => + { + var updateTable = string.Format("UPDATE {0} SET", base.GetTableNameStringNoWith); + var setValues = string.Join(",", t.Where(s => !s.IsPrimarykey).Select(m => GetOracleUpdateColums(m)).ToArray()); + var pkList = t.Where(s => s.IsPrimarykey).ToList(); + List whereList = new List(); + foreach (var item in pkList) + { + var isFirst = pkList.First() == item; + var whereString = ""; + whereString += GetOracleUpdateColums(item); + whereList.Add(whereString); + } + return string.Format("{0} {1} WHERE {2};", updateTable, setValues, string.Join("AND", whereList)); + }).ToArray())); + return sb.ToString(); + } + + private string GetOracleUpdateColums(DbColumnInfo m) + { + return string.Format("\"{0}\"={1}", m.DbColumnName.ToUpper(), FormatValue(m.Value)); + } + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value); + return bytesString; + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "'" + value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqliteProvider.cs b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqliteProvider.cs new file mode 100644 index 0000000..412190d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Realization/Sqlite/SqliteProvider.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Data.SQLite; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial class SqliteProvider : AdoProvider + { + public SqliteProvider() { } + public override IDbConnection Connection + { + get + { + if (base._DbConnection == null) + { + try + { + var SQLiteConnectionString = base.Context.CurrentConnectionConfig.ConnectionString; + base._DbConnection = new SQLiteConnection(SQLiteConnectionString); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + + public override void BeginTran(string transactionName) + { + base.BeginTran(); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + base.BeginTran(iso); + } + public override IDataAdapter GetAdapter() + { + return new SQLiteDataAdapter(); + } + public override DbCommand GetCommand(string sql, SugarParameter[] parameters) + { + SQLiteCommand sqlCommand = new SQLiteCommand(sql, (SQLiteConnection)this.Connection); + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (SQLiteTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + IDataParameter[] ipars = ToIDbDataParameter(parameters); + sqlCommand.Parameters.AddRange((SQLiteParameter[])ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, DbCommand command) + { + ((SQLiteDataAdapter)dataAdapter).SelectCommand = (SQLiteCommand)command; + } + /// + /// if SQLite return SQLiteParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + SQLiteParameter[] result = new SQLiteParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + if (parameter.Value.GetType() == UtilConstants.GuidType) + { + parameter.Value = parameter.Value.ToString(); + } + var sqlParameter = new SQLiteParameter(); + sqlParameter.ParameterName = parameter.ParameterName; + sqlParameter.Size = parameter.Size; + sqlParameter.Value = parameter.Value; + sqlParameter.DbType = parameter.DbType; + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue)) { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + if (sqlParameter.DbType == System.Data.DbType.Guid) { + sqlParameter.DbType = System.Data.DbType.String; + sqlParameter.Value = sqlParameter.Value.ObjToString(); + } + + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/References/MySql.Data.dll b/类库/SqlSugar/5.0.0.9/References/MySql.Data.dll new file mode 100644 index 0000000..80bf09b Binary files /dev/null and b/类库/SqlSugar/5.0.0.9/References/MySql.Data.dll differ diff --git a/类库/SqlSugar/5.0.0.9/References/Newtonsoft.Json.dll b/类库/SqlSugar/5.0.0.9/References/Newtonsoft.Json.dll new file mode 100644 index 0000000..20dae62 Binary files /dev/null and b/类库/SqlSugar/5.0.0.9/References/Newtonsoft.Json.dll differ diff --git a/类库/SqlSugar/5.0.0.9/References/Npgsql.dll b/类库/SqlSugar/5.0.0.9/References/Npgsql.dll new file mode 100644 index 0000000..dbef33c Binary files /dev/null and b/类库/SqlSugar/5.0.0.9/References/Npgsql.dll differ diff --git a/类库/SqlSugar/5.0.0.9/References/Oracle.ManagedDataAccess.dll b/类库/SqlSugar/5.0.0.9/References/Oracle.ManagedDataAccess.dll new file mode 100644 index 0000000..473ca83 Binary files /dev/null and b/类库/SqlSugar/5.0.0.9/References/Oracle.ManagedDataAccess.dll differ diff --git a/类库/SqlSugar/5.0.0.9/References/System.Data.SQLite.dll b/类库/SqlSugar/5.0.0.9/References/System.Data.SQLite.dll new file mode 100644 index 0000000..1ee930f Binary files /dev/null and b/类库/SqlSugar/5.0.0.9/References/System.Data.SQLite.dll differ diff --git a/类库/SqlSugar/5.0.0.9/SimpleClient.cs b/类库/SqlSugar/5.0.0.9/SimpleClient.cs new file mode 100644 index 0000000..909221a --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/SimpleClient.cs @@ -0,0 +1,298 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + + public partial class SimpleClient where T : class, new() + { + protected ISqlSugarClient Context { get; set; } + + public ITenant AsTenant() + { + return this.Context as ITenant; + } + public ISqlSugarClient AsSugarClient() + { + return this.Context; + } + + private SimpleClient() + { + + } + public SimpleClient(ISqlSugarClient context) + { + this.Context = context; + } + + public ISugarQueryable AsQueryable() + { + return Context.Queryable(); + } + public IInsertable AsInsertable(T insertObj) + { + return Context.Insertable(insertObj); + } + public IInsertable AsInsertable(T[] insertObjs) + { + return Context.Insertable(insertObjs); + } + public IInsertable AsInsertable(List insertObjs) + { + return Context.Insertable(insertObjs); + } + public IUpdateable AsUpdateable(T updateObj) + { + return Context.Updateable(updateObj); + } + public IUpdateable AsUpdateable(T[] updateObjs) + { + return Context.Updateable(updateObjs); + } + public IUpdateable AsUpdateable(List updateObjs) + { + return Context.Updateable(updateObjs); + } + public IDeleteable AsDeleteable() + { + return Context.Deleteable(); + } + + public T GetById(dynamic id) + { + return Context.Queryable().InSingle(id); + } + public List GetList() + { + return Context.Queryable().ToList(); + } + + public List GetList(Expression> whereExpression) + { + return Context.Queryable().Where(whereExpression).ToList(); + } + public T GetSingle(Expression> whereExpression) + { + return Context.Queryable().Single(whereExpression); + } + public List GetPageList(Expression> whereExpression, PageModel page) + { + int count = 0; + var result = Context.Queryable().Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(Expression> whereExpression, PageModel page, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc) + { + int count = 0; + var result = Context.Queryable().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(List conditionalList, PageModel page) + { + int count = 0; + var result = Context.Queryable().Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(List conditionalList, PageModel page, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc) + { + int count = 0; + var result = Context.Queryable().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public bool IsAny(Expression> whereExpression) + { + return Context.Queryable().Where(whereExpression).Any(); + } + public int Count(Expression> whereExpression) + { + + return Context.Queryable().Where(whereExpression).Count(); + } + + public bool Insert(T insertObj) + { + return this.Context.Insertable(insertObj).ExecuteCommand() > 0; + } + public int InsertReturnIdentity(T insertObj) + { + return this.Context.Insertable(insertObj).ExecuteReturnIdentity(); + } + public bool InsertRange(T[] insertObjs) + { + return this.Context.Insertable(insertObjs).ExecuteCommand() > 0; + } + public bool InsertRange(List insertObjs) + { + return this.Context.Insertable(insertObjs).ExecuteCommand() > 0; + } + public bool Update(T updateObj) + { + return this.Context.Updateable(updateObj).ExecuteCommand() > 0; + } + public bool UpdateRange(T[] updateObjs) + { + return this.Context.Updateable(updateObjs).ExecuteCommand() > 0; + } + public bool UpdateRange(List updateObjs) + { + return this.Context.Updateable(updateObjs).ExecuteCommand() > 0; + } + public bool Update(Expression> columns, Expression> whereExpression) + { + return this.Context.Updateable().SetColumns(columns).Where(whereExpression).ExecuteCommand() > 0; + } + public bool Delete(T deleteObj) + { + return this.Context.Deleteable().Where(deleteObj).ExecuteCommand() > 0; + } + public bool Delete(Expression> whereExpression) + { + return this.Context.Deleteable().Where(whereExpression).ExecuteCommand() > 0; + } + public bool DeleteById(dynamic id) + { + return this.Context.Deleteable().In(id).ExecuteCommand() > 0; + } + public bool DeleteByIds(dynamic[] ids) + { + return this.Context.Deleteable().In(ids).ExecuteCommand() > 0; + } + + [Obsolete("Use AsSugarClient()")] + public ISqlSugarClient FullClient { get { return this.Context; } } + } + + + public partial class SimpleClient + { + protected ISqlSugarClient Context { get; set; } + public ITenant AsTenant() + { + return this.Context as ITenant; + } + public ISqlSugarClient AsSugarClient() + { + return this.Context; + } + + private SimpleClient() + { + + } + public SimpleClient(ISqlSugarClient context) + { + this.Context = context; + } + + public T GetById(dynamic id) where T : class, new() + { + return Context.Queryable().InSingle(id); + } + public int Count(Expression> whereExpression) + { + return Context.Queryable().Where(whereExpression).Count(); + } + public List GetList() where T : class, new() + { + return Context.Queryable().ToList(); + } + public T GetSingle(Expression> whereExpression) where T : class, new() + { + return Context.Queryable().Single(whereExpression); + } + public List GetList(Expression> whereExpression) where T : class, new() + { + return Context.Queryable().Where(whereExpression).ToList(); + } + public List GetPageList(Expression> whereExpression, PageModel page) where T : class, new() + { + int count = 0; + var result = Context.Queryable().Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(Expression> whereExpression, PageModel page, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc) where T : class, new() + { + int count = 0; + var result = Context.Queryable().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(List conditionalList, PageModel page) where T : class, new() + { + int count = 0; + var result = Context.Queryable().Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(List conditionalList, PageModel page, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc) where T : class, new() + { + int count = 0; + var result = Context.Queryable().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public bool IsAny(Expression> whereExpression) where T : class, new() + { + return Context.Queryable().Where(whereExpression).Any(); + } + public bool Insert(T insertObj) where T : class, new() + { + return this.Context.Insertable(insertObj).ExecuteCommand() > 0; + } + public int InsertReturnIdentity(T insertObj) where T : class, new() + { + return this.Context.Insertable(insertObj).ExecuteReturnIdentity(); + } + public bool InsertRange(T[] insertObjs) where T : class, new() + { + return this.Context.Insertable(insertObjs).ExecuteCommand() > 0; + } + public bool InsertRange(List insertObjs) where T : class, new() + { + return this.Context.Insertable(insertObjs).ExecuteCommand() > 0; + } + public bool Update(T updateObj) where T : class, new() + { + return this.Context.Updateable(updateObj).ExecuteCommand() > 0; + } + public bool UpdateRange(T[] updateObjs) where T : class, new() + { + return this.Context.Updateable(updateObjs).ExecuteCommand() > 0; + } + public bool UpdateRange(List updateObjs) where T : class, new() + { + return this.Context.Updateable(updateObjs).ExecuteCommand() > 0; + } + public bool Update(Expression> columns, Expression> whereExpression) where T : class, new() + { + return this.Context.Updateable(columns).Where(whereExpression).ExecuteCommand() > 0; + } + public bool Delete(T deleteObj) where T : class, new() + { + return this.Context.Deleteable().Where(deleteObj).ExecuteCommand() > 0; + } + public bool Delete(Expression> whereExpression) where T : class, new() + { + return this.Context.Deleteable().Where(whereExpression).ExecuteCommand() > 0; + } + public bool DeleteById(dynamic id) where T : class, new() + { + return this.Context.Deleteable().In(id).ExecuteCommand() > 0; + } + public bool DeleteByIds(dynamic[] ids) where T : class, new() + { + return this.Context.Deleteable().In(ids).ExecuteCommand() > 0; + } + [Obsolete("Use AsSugarClient()")] + public ISqlSugarClient FullClient { get { return this.Context; } } + } +} diff --git a/类库/SqlSugar/5.0.0.9/SqlSugar.csproj b/类库/SqlSugar/5.0.0.9/SqlSugar.csproj new file mode 100644 index 0000000..cee3452 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/SqlSugar.csproj @@ -0,0 +1,320 @@ + + + + + Debug + AnyCPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5} + Library + Properties + SqlSugar + SqlSugar + v4.5 + 512 + + + + true + full + false + ..\..\..\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + False + Lib\MySql.Data.dll + + + False + Lib\Newtonsoft.Json.dll + + + False + References\Npgsql.dll + + + False + References\Oracle.ManagedDataAccess.dll + + + + + False + Lib\System.Data.SQLite.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/SqlSugar/5.0.0.9/SqlSugar.nuspec b/类库/SqlSugar/5.0.0.9/SqlSugar.nuspec new file mode 100644 index 0000000..ca34aaa --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/SqlSugar.nuspec @@ -0,0 +1,20 @@ + + + + sqlSugar + 5.0.0.8 + SqlSugar 5.0+ .Net Framework 4.5+ , SqlSugar 4.0+ .Net Framework 4.0+ + sun kaixuan + landa + https://github.com/sunkaixuan/SqlSugar + https://github.com/sunkaixuan/SqlSugar + https://secure.gravatar.com/avatar/a82c03402497b2e58fd65038a3699b30 + false + SqlSugar 5.0+ .Net Framework 4.5+ , SqlSugar 4.0+ .Net Framework 4.0+ + Copyright 2017 + asp.net orm + + + + + \ No newline at end of file diff --git a/类库/SqlSugar/5.0.0.9/SqlSugarClient.cs b/类库/SqlSugar/5.0.0.9/SqlSugarClient.cs new file mode 100644 index 0000000..ea9205d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/SqlSugarClient.cs @@ -0,0 +1,909 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SqlSugarClient : ISqlSugarClient, ITenant + { + #region Gobal Property + private SqlSugarProvider _Context = null; + private string _ThreadId; + private ConnectionConfig _CurrentConnectionConfig; + private List _AllClients; + private bool _IsAllTran = false; + private bool _IsOpen = false; + private MappingTableList _MappingTables; + private MappingColumnList _MappingColumns; + private IgnoreColumnList _IgnoreColumns; + private IgnoreColumnList _IgnoreInsertColumns; + internal Guid? AsyncId { get; set; } + internal bool? IsSingleInstance { get; set; } + + #endregion + + #region Constructor + public SqlSugarClient(ConnectionConfig config) + { + Check.Exception(config == null, "ConnectionConfig config is null"); + InitContext(config); + } + + public SqlSugarClient(List configs) + { + Check.Exception(configs.IsNullOrEmpty(), "List configs is null"); + InitConfigs(configs); + var config = configs.First(); + InitContext(config); + _AllClients = configs.Select(it => new SugarTenant() { ConnectionConfig = it }).ToList(); ; + _AllClients.First(it => it.ConnectionConfig.ConfigId == config.ConfigId).Context = this.Context; + } + + #endregion + + #region Global variable + public SqlSugarProvider Context { get { return GetContext(); } } + public bool IsSystemTablesConfig => this.Context.IsSystemTablesConfig; + public ConnectionConfig CurrentConnectionConfig { get { return _CurrentConnectionConfig; } set { _CurrentConnectionConfig = value; } } + public Guid ContextID { get { return this.Context.ContextID; } set { this.Context.ContextID = value; } } + + + public MappingTableList MappingTables { get { return _MappingTables; } set { _MappingTables = value; } } + public MappingColumnList MappingColumns { get { return _MappingColumns; } set { _MappingColumns = value; } } + public IgnoreColumnList IgnoreColumns { get { return _IgnoreColumns; } set { _IgnoreColumns = value; } } + public IgnoreColumnList IgnoreInsertColumns { get { return _IgnoreInsertColumns; } set { _IgnoreInsertColumns = value; } } + public Dictionary TempItems { get { return this.Context.TempItems; } set { this.Context.TempItems = value; } } + #endregion + + #region SimpleClient + public SimpleClient GetSimpleClient() + { + return this.Context.GetSimpleClient(); + } + + public SimpleClient GetSimpleClient() where T : class, new() + { + return this.Context.GetSimpleClient(); + } + #endregion + + #region Insertable + public IInsertable Insertable(Dictionary columnDictionary) where T : class, new() + { + return this.Context.Insertable(columnDictionary); + } + + public IInsertable Insertable(dynamic insertDynamicObject) where T : class, new() + { + return this.Context.Insertable(insertDynamicObject); + } + + public IInsertable Insertable(List insertObjs) where T : class, new() + { + return this.Context.Insertable(insertObjs); + } + + public IInsertable Insertable(T insertObj) where T : class, new() + { + return this.Context.Insertable(insertObj); + } + + public IInsertable Insertable(T[] insertObjs) where T : class, new() + { + return this.Context.Insertable(insertObjs); + } + + #endregion + + #region Queryable + + #region Union + public ISugarQueryable Union(List> queryables) where T : class, new() + { + return this.Context.Union(queryables); + } + + public ISugarQueryable Union(params ISugarQueryable[] queryables) where T : class, new() + { + return this.Context.Union(queryables); + } + + public ISugarQueryable UnionAll(List> queryables) where T : class, new() + { + return this.Context.UnionAll(queryables); + } + + public ISugarQueryable UnionAll(params ISugarQueryable[] queryables) where T : class, new() + { + return this.Context.UnionAll(queryables); + } + #endregion + + public ISugarQueryable SqlQueryable(string sql) where T : class, new() + { + return this.Context.SqlQueryable(sql); + } + public ISugarQueryable Queryable(string tableName, string shortName) + { + return this.Context.Queryable(tableName, shortName); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(Expression> joinExpression) + { + return this.Context.Queryable(joinExpression); + } + + public ISugarQueryable Queryable(ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, Expression> joinExpression) + where T : class, new() + where T2 : class, new() + { + return this.Context.Queryable(joinQueryable1, joinQueryable2, joinExpression); + } + + public ISugarQueryable Queryable(ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, JoinType joinType, Expression> joinExpression) + where T : class, new() + where T2 : class, new() + { + return this.Context.Queryable(joinQueryable1, joinQueryable2, joinType, joinExpression); + } + + public ISugarQueryable Queryable() + { + return this.Context.Queryable(); + } + + public ISugarQueryable Queryable(ISugarQueryable queryable) where T : class, new() + { + return this.Context.Queryable(queryable); + } + + public ISugarQueryable Queryable(string shortName) + { + return this.Context.Queryable(shortName); + } + + #endregion + + #region Saveable + public ISaveable Saveable(List saveObjects) where T : class, new() + { + return this.Context.Saveable(saveObjects); + } + + public ISaveable Saveable(T saveObject) where T : class, new() + { + return this.Context.Saveable(saveObject); + } + #endregion + + #region Queue + public QueueList Queues { get { return this.Context.Queues; } set { this.Context.Queues = value; } } + public void AddQueue(string sql, object parsmeters = null) + { + this.Context.AddQueue(sql, parsmeters); + } + + public void AddQueue(string sql, List parsmeters) + { + this.Context.AddQueue(sql, parsmeters); + } + + public void AddQueue(string sql, SugarParameter parsmeter) + { + this.Context.AddQueue(sql, parsmeter); + } + public int SaveQueues(bool isTran = true) + { + return this.Context.SaveQueues(isTran); + } + + public Tuple, List, List, List, List, List, List> SaveQueues(bool isTran = true) + { + return this.Context.SaveQueues(isTran); + } + + public Tuple, List, List, List, List, List> SaveQueues(bool isTran = true) + { + return this.Context.SaveQueues(isTran); + } + + public Tuple, List, List, List, List> SaveQueues(bool isTran = true) + { + return this.Context.SaveQueues(isTran); + } + + public Tuple, List, List, List> SaveQueues(bool isTran = true) + { + return this.Context.SaveQueues(isTran); + } + + public Tuple, List, List> SaveQueues(bool isTran = true) + { + return this.Context.SaveQueues(isTran); + } + + public Tuple, List> SaveQueues(bool isTran = true) + { + return this.Context.SaveQueues(isTran); + } + + public List SaveQueues(bool isTran = true) + { + return this.Context.SaveQueues(isTran); + } + + public Task SaveQueuesAsync(bool isTran = true) + { + return this.Context.SaveQueuesAsync(isTran); + } + + public Task, List, List, List, List, List, List>> SaveQueuesAsync(bool isTran = true) + { + return this.Context.SaveQueuesAsync(isTran); + } + + public Task, List, List, List, List, List>> SaveQueuesAsync(bool isTran = true) + { + return this.Context.SaveQueuesAsync(isTran); + } + + public Task, List, List, List, List>> SaveQueuesAsync(bool isTran = true) + { + return this.Context.SaveQueuesAsync(isTran); + } + + public Task, List, List, List>> SaveQueuesAsync(bool isTran = true) + { + return this.Context.SaveQueuesAsync(isTran); + } + + public Task, List, List>> SaveQueuesAsync(bool isTran = true) + { + return this.Context.SaveQueuesAsync(isTran); + } + + public Task, List>> SaveQueuesAsync(bool isTran = true) + { + return this.Context.SaveQueuesAsync(isTran); + } + + public Task> SaveQueuesAsync(bool isTran = true) + { + return this.Context.SaveQueuesAsync(isTran); + } + #endregion + + #region Updateable + public IUpdateable Updateable() where T : class, new() + { + return this.Context.Updateable(); + } + + public IUpdateable Updateable(Dictionary columnDictionary) where T : class, new() + { + return this.Context.Updateable(columnDictionary); + } + + public IUpdateable Updateable(dynamic updateDynamicObject) where T : class, new() + { + return this.Context.Updateable(updateDynamicObject); + } + + public IUpdateable Updateable(Expression> columns) where T : class, new() + { + return this.Context.Updateable(columns); + } + + public IUpdateable Updateable(Expression> columns) where T : class, new() + { + return this.Context.Updateable(columns); + } + + public IUpdateable Updateable(List UpdateObjs) where T : class, new() + { + return this.Context.Updateable(UpdateObjs); + } + + public IUpdateable Updateable(T UpdateObj) where T : class, new() + { + return this.Context.Updateable(UpdateObj); + } + + public IUpdateable Updateable(T[] UpdateObjs) where T : class, new() + { + return this.Context.Updateable(UpdateObjs); + } + + #endregion + + #region Ado + public IAdo Ado => this.Context.Ado; + + #endregion + + #region Deleteable + public IDeleteable Deleteable() where T : class, new() + { + return this.Context.Deleteable(); + } + + public IDeleteable Deleteable(dynamic primaryKeyValue) where T : class, new() + { + return this.Context.Deleteable(primaryKeyValue); + } + + public IDeleteable Deleteable(dynamic[] primaryKeyValues) where T : class, new() + { + return this.Context.Deleteable(primaryKeyValues); + } + + public IDeleteable Deleteable(Expression> expression) where T : class, new() + { + return this.Context.Deleteable(expression); + } + + public IDeleteable Deleteable(List pkValue) where T : class, new() + { + return this.Context.Deleteable(pkValue); + } + + public IDeleteable Deleteable(List deleteObjs) where T : class, new() + { + return this.Context.Deleteable(deleteObjs); + } + + public IDeleteable Deleteable(T deleteObj) where T : class, new() + { + return this.Context.Deleteable(deleteObj); + } + + + #endregion + + #region More api + public IContextMethods Utilities { get { return this.Context.Utilities; } set { this.Context.Utilities = value; } } + public AopProvider Aop => this.Context.Aop; + public ICodeFirst CodeFirst => this.Context.CodeFirst; + public IDbFirst DbFirst => this.Context.DbFirst; + public IDbMaintenance DbMaintenance => this.Context.DbMaintenance; + public EntityMaintenance EntityMaintenance { get { return this.Context.EntityMaintenance; } set { this.Context.EntityMaintenance = value; } } + public QueryFilterProvider QueryFilter { get { return this.Context.QueryFilter; }set { this.Context.QueryFilter = value; } } + #endregion + + #region TenantManager + public void ChangeDatabase(string configId) + { + Check.Exception(!_AllClients.Any(it => it.ConnectionConfig.ConfigId == configId), "ConfigId was not found {0}", configId); + InitTenant(_AllClients.First(it => it.ConnectionConfig.ConfigId == configId)); + if (this._IsAllTran) + this.Ado.BeginTran(); + if (this._IsOpen) + this.Open(); + } + public void ChangeDatabase(Func changeExpression) + { + var allConfigs = _AllClients.Select(it => it.ConnectionConfig); + Check.Exception(!allConfigs.Any(changeExpression), "changeExpression was not found {0}", changeExpression.ToString()); + InitTenant(_AllClients.First(it => it.ConnectionConfig == allConfigs.First(changeExpression))); + if (this._IsAllTran) + this.Ado.BeginTran(); + if (this._IsOpen) + this.Open(); + } + public void BeginTran() + { + _IsAllTran = true; + this.Context.Ado.BeginTran(); + } + public void CommitTran() + { + this.Context.Ado.CommitTran(); + AllClientEach(it => it.Ado.CommitTran()); + _IsAllTran = false; + } + public DbResult UseTran(Action action, Action errorCallBack = null) + { + var result = new DbResult(); + try + { + this.BeginTran(); + if (action != null) + action(); + this.CommitTran(); + result.Data = result.IsSuccess = true; + } + catch (Exception ex) + { + result.ErrorException = ex; + result.ErrorMessage = ex.Message; + result.IsSuccess = false; + this.RollbackTran(); + if (errorCallBack != null) + { + errorCallBack(ex); + } + } + return result; + } + + public Task> UseTranAsync(Action action, Action errorCallBack = null) + { + return Task.FromResult(UseTran(action, errorCallBack)); + } + + public DbResult UseTran(Func action, Action errorCallBack = null) + { + var result = new DbResult(); + try + { + this.BeginTran(); + if (action != null) + result.Data = action(); + this.CommitTran(); + result.IsSuccess = true; + } + catch (Exception ex) + { + result.ErrorException = ex; + result.ErrorMessage = ex.Message; + result.IsSuccess = false; + this.RollbackTran(); + if (errorCallBack != null) + { + errorCallBack(ex); + } + } + return result; + } + + public Task> UseTranAsync(Func action, Action errorCallBack = null) + { + return Task.FromResult(UseTran(action, errorCallBack)); + } + + public void RollbackTran() + { + this.Context.Ado.RollbackTran(); + AllClientEach(it => it.Ado.RollbackTran()); + _IsAllTran = false; + } + public void Close() + { + this.Context.Close(); + AllClientEach(it => it.Close()); + _IsOpen = false; + } + public void Open() + { + this.Context.Open(); + _IsOpen = true; + } + + #endregion + + #region IDispose + public void Dispose() + { + this.Context.Dispose(); + AllClientEach(it => it.Ado.RollbackTran()); + } + + #endregion + + #region Other method + public DateTime GetDate() + { + return this.Context.GetDate(); + } + public void InitMappingInfo(Type type) + { + this.Context.InitMappingInfo(type); + } + public void InitMappingInfo() + { + this.Context.InitMappingInfo(typeof(T)); + } + #endregion + + #region Helper + private SqlSugarProvider GetContext() + { + SqlSugarProvider result = null; + if (IsSameThreadAndShard()) + { + result = SameThreadAndShard(); + } + else if (IsNoSameThreadAndShard()) + { + result = NoSameThreadAndShard(); + } + else if (IsSynchronization()) + { + result = Synchronization(); + } + else if (IsSingleInstanceAsync()) + { + result = NoSameThreadAsync(); + } + else if (IsAsync()) + { + result = Synchronization(); + } + else + { + IsSingleInstance = true; + result = NoSameThread(); + } + if (result.Root == null) + { + result.Root = this; + } + return result; + } + + private SqlSugarProvider NoSameThreadAsync() + { + var result = GetCallContext(); + return result; + } + private SqlSugarProvider NoSameThread() + { + if (CallContext.ContextList.Value == null) + { + var context = CopyClient(); + AddCallContext(context); + return context; + } + else + { + var result = GetCallContext(); + if (result == null) + { + var copy = CopyClient(); + AddCallContext(copy); + return copy; + } + else + { + return result; + } + } + } + + private SqlSugarProvider Synchronization() + { + _Context.MappingColumns = _MappingColumns; + _Context.MappingTables = _MappingTables; + _Context.IgnoreColumns = _IgnoreColumns; + _Context.IgnoreInsertColumns = _IgnoreInsertColumns; + return _Context; + } + + private SqlSugarProvider NoSameThreadAndShard() + { + if (CallContext.ContextList.Value.IsNullOrEmpty()) + { + var copy = CopyClient(); + AddCallContext(copy); + return copy; + } + else + { + var result = GetCallContext(); + if (result == null) + { + var copy = CopyClient(); + AddCallContext(copy); + return copy; + } + else + { + return result; + } + } + } + + private SqlSugarProvider SameThreadAndShard() + { + if (CallContext.ContextList.Value.IsNullOrEmpty()) + { + AddCallContext(_Context); + return _Context; + } + else + { + var result = GetCallContext(); + if (result == null) + { + var copy = CopyClient(); + AddCallContext(copy); + return copy; + } + else + { + return result; + } + } + } + + private bool IsAsync() + { + return AsyncId != null; + } + + private bool IsSingleInstanceAsync() + { + return IsSingleInstance == true && AsyncId != null; + } + + private bool IsSynchronization() + { + return _ThreadId == Thread.CurrentThread.ManagedThreadId.ToString(); + } + + private bool IsNoSameThreadAndShard() + { + return CurrentConnectionConfig.IsShardSameThread && _ThreadId != Thread.CurrentThread.ManagedThreadId.ToString(); + } + + private bool IsSameThreadAndShard() + { + return CurrentConnectionConfig.IsShardSameThread && _ThreadId == Thread.CurrentThread.ManagedThreadId.ToString(); + } + + private SqlSugarProvider CopyClient() + { + var result = new SqlSugarProvider(this.CurrentConnectionConfig); + result.MappingColumns = _MappingColumns; + result.MappingTables = _MappingTables; + result.IgnoreColumns = _IgnoreColumns; + result.IgnoreInsertColumns = _IgnoreInsertColumns; + + return result; + } + private void AddCallContext(SqlSugarProvider context) + { + CallContext.ContextList.Value = new List(); + CallContext.ContextList.Value.Add(context); + } + + private SqlSugarProvider GetCallContext() + { + return CallContext.ContextList.Value.FirstOrDefault(it => + it.CurrentConnectionConfig.DbType == _Context.CurrentConnectionConfig.DbType && + it.CurrentConnectionConfig.ConnectionString == _Context.CurrentConnectionConfig.ConnectionString && + it.CurrentConnectionConfig.InitKeyType == _Context.CurrentConnectionConfig.InitKeyType && + it.CurrentConnectionConfig.IsAutoCloseConnection == _Context.CurrentConnectionConfig.IsAutoCloseConnection + ); + } + + private void InitContext(ConnectionConfig config) + { + var aopIsNull = config.AopEvents == null; + if (aopIsNull) + { + config.AopEvents = new AopEvents(); + } + _Context = new SqlSugarProvider(config); + if (!aopIsNull) + _Context.Ado.IsEnableLogEvent = true; + this.CurrentConnectionConfig = config; + _ThreadId = Thread.CurrentThread.ManagedThreadId.ToString(); + if (_MappingColumns == null) + this.MappingTables = new MappingTableList(); + if (this.MappingColumns == null) + this.MappingColumns = new MappingColumnList(); + if (this.IgnoreColumns == null) + this.IgnoreColumns = new IgnoreColumnList(); + if (this.IgnoreInsertColumns == null) + this.IgnoreInsertColumns = new IgnoreColumnList(); + } + + private void InitConfigs(List configs) + { + foreach (var item in configs) + { + if (item.ConfigId == null) + { + item.ConfigId = Guid.NewGuid().ToString(); + } + } + } + private void AllClientEach(Action action) + { + if (_AllClients.HasValue()) + { + foreach (var item in _AllClients.Where(it => it.Context.HasValue())) + { + action(item.Context); + } + } + } + + private void InitTenant(SugarTenant Tenant) + { + if (Tenant.Context == null) + { + Tenant.Context = new SqlSugarProvider(Tenant.ConnectionConfig); + } + _Context = Tenant.Context; + this.CurrentConnectionConfig = Tenant.ConnectionConfig; + } + #endregion + + #region Obsolete + [Obsolete("Use EntityMaintenance")] + public EntityMaintenance EntityProvider { get { return this.Context.EntityProvider; } set { this.Context.EntityProvider = value; } } + [Obsolete("Use Utilities")] + public IContextMethods RewritableMethods { get { return this.Context.RewritableMethods; } set { this.Context.RewritableMethods = value; } } + [Obsolete("Use GetSimpleClient")] + public SimpleClient SimpleClient { get { return this.Context.SimpleClient; } } + #endregion + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/CallContext.cs b/类库/SqlSugar/5.0.0.9/Utilities/CallContext.cs new file mode 100644 index 0000000..8cfb2d2 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/CallContext.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading; + +namespace SqlSugar +{ + internal class CallContext + { + public static ThreadLocal> ContextList = new ThreadLocal>(); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/Check.cs b/类库/SqlSugar/5.0.0.9/Utilities/Check.cs new file mode 100644 index 0000000..6aab959 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/Check.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class Check + { + public static void ThrowNotSupportedException(string message) + { + message = message.IsNullOrEmpty() ? new NotSupportedException().Message : message; + throw new SqlSugarException("SqlSugarException.NotSupportedException:" + message); + } + + public static void ArgumentNullException(object checkObj, string message) + { + if (checkObj == null) + throw new SqlSugarException("SqlSugarException.ArgumentNullException:" + message); + } + + public static void ArgumentNullException(object [] checkObj, string message) + { + if (checkObj == null|| checkObj.Length==0) + throw new SqlSugarException("SqlSugarException.ArgumentNullException:" + message); + } + + public static void Exception(bool isException, string message, params string[] args) + { + if (isException) + throw new SqlSugarException(string.Format(message, args)); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/DbExtensions.cs b/类库/SqlSugar/5.0.0.9/Utilities/DbExtensions.cs new file mode 100644 index 0000000..d6ad91b --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/DbExtensions.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +namespace SqlSugar +{ + public static class DbExtensions + { + public static string ToJoinSqlInVals(this T[] array) + { + if (array == null || array.Length == 0) + { + return ToSqlValue(string.Empty); + } + else + { + return string.Join(",", array.Where(c => c != null).Select(it => (it + "").ToSqlValue())); + } + } + + public static string ToSqlValue(this string value) + { + return string.Format("'{0}'", value.ToSqlFilter()); + } + + /// + ///Sql Filter + /// + /// + /// + public static string ToSqlFilter(this string value) + { + if (!value.IsNullOrEmpty()) + { + value = value.Replace("'", "''"); + } + return value; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/ErrorMessage.cs b/类库/SqlSugar/5.0.0.9/Utilities/ErrorMessage.cs new file mode 100644 index 0000000..41c710b --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/ErrorMessage.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + internal static partial class ErrorMessage + { + internal static string ObjNotExist + { + get + { + return GetThrowMessage("{0} does not exist.", + "{0}不存在。"); + } + } + internal static string EntityMappingError + { + get + { + return GetThrowMessage("Entity mapping error.{0}", + "实体与表映射出错。{0}"); + } + } + + public static string NotSupportedDictionary + { + get + { + return GetThrowMessage("This type of Dictionary is not supported for the time being. You can try Dictionary, or contact the author!!", + "暂时不支持该类型的Dictionary 你可以试试 Dictionary或者联系作者!!"); + } + } + + public static string NotSupportedArray + { + get + { + return GetThrowMessage("This type of Array is not supported for the time being. You can try object[] or contact the author!!", + "暂时不支持该类型的Array 你可以试试 object[] 或者联系作者!!"); + } + } + + internal static string GetThrowMessage(string enMessage, string cnMessage, params string[] args) + { + List formatArgs = new List() { enMessage, cnMessage }; + formatArgs.AddRange(args); + return string.Format(@"English Message : {0} +Chinese Message : {1}", formatArgs.ToArray()); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/FileHelper.cs b/类库/SqlSugar/5.0.0.9/Utilities/FileHelper.cs new file mode 100644 index 0000000..ac786a7 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/FileHelper.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + internal class FileHelper + { + public static void CreateFile(string filePath, string text, Encoding encoding) + { + try + { + if (IsExistFile(filePath)) + { + DeleteFile(filePath); + } + if (!IsExistFile(filePath)) + { + string directoryPath = GetDirectoryFromFilePath(filePath); + CreateDirectory(directoryPath); + + //Create File + FileInfo file = new FileInfo(filePath); + using (FileStream stream = file.Create()) + { + using (StreamWriter writer = new StreamWriter(stream, encoding)) + { + writer.Write(text); + writer.Flush(); + } + } + } + } + catch(Exception ex) + { + throw ex; + } + } + public static bool IsExistDirectory(string directoryPath) + { + return Directory.Exists(directoryPath); + } + public static void CreateDirectory(string directoryPath) + { + if (!IsExistDirectory(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + } + } + public static void DeleteFile(string filePath) + { + if (IsExistFile(filePath)) + { + File.Delete(filePath); + } + } + public static string GetDirectoryFromFilePath(string filePath) + { + FileInfo file = new FileInfo(filePath); + DirectoryInfo directory = file.Directory; + return directory.FullName; + } + public static bool IsExistFile(string filePath) + { + return File.Exists(filePath); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/ReflectionExtensions.cs b/类库/SqlSugar/5.0.0.9/Utilities/ReflectionExtensions.cs new file mode 100644 index 0000000..eadffd1 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/ReflectionExtensions.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace SqlSugar +{ + + public static class ReflectionExtensions + { + public static Type GetTypeInfo(this Type typeInfo) + { + return typeInfo; + } + + public static Type[] GetGenericArguments(this Type type) + { + var reval = type.GetTypeInfo().GetGenericArguments(); + return reval; + } + public static bool IsGenericType(this Type type) + { + var reval = type.GetTypeInfo().IsGenericType; + return reval; + } + public static PropertyInfo[] GetProperties(this Type type) + { + var reval = type.GetTypeInfo().GetProperties(); + return reval; + } + public static PropertyInfo GetProperty(this Type type, string name) + { + var reval = type.GetTypeInfo().GetProperty(name); + return reval; + } + + public static FieldInfo GetField(this Type type, string name) + { + var reval = type.GetTypeInfo().GetField(name); + return reval; + } + + public static bool IsEnum(this Type type) + { + var reval = type.GetTypeInfo().IsEnum; + return reval; + } + + public static MethodInfo GetMethod(this Type type, string name) + { + var reval = type.GetTypeInfo().GetMethod(name); + return reval; + } + public static MethodInfo GetMethod(this Type type, string name, Type[] types) + { + var reval = type.GetTypeInfo().GetMethod(name, types); + return reval; + } + public static ConstructorInfo GetConstructor(this Type type, Type[] types) + { + var reval = type.GetTypeInfo().GetConstructor(types); + return reval; + } + + public static bool IsValueType(this Type type) + { + return type.GetTypeInfo().IsValueType; + } + + public static bool IsEntity(this Type type) + { + return type.GetTypeInfo().IsClass; + } + + public static Type ReflectedType(this MethodInfo method) + { + return method.ReflectedType; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/UtilConstants.cs b/类库/SqlSugar/5.0.0.9/Utilities/UtilConstants.cs new file mode 100644 index 0000000..375a701 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/UtilConstants.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + internal static class UtilConstants + { + public const string Dot = "."; + public const char DotChar = '.'; + internal const string Space = " "; + internal const char SpaceChar =' '; + internal const string AssemblyName = "SqlSugar"; + internal const string ReplaceKey = "{662E689B-17A1-4D06-9D27-F29EAB8BC3D6}"; + internal const string ReplaceCommaKey = "{112A689B-17A1-4A06-9D27-A39EAB8BC3D5}"; + + internal static Type IntType = typeof(int); + internal static Type LongType = typeof(long); + internal static Type GuidType = typeof(Guid); + internal static Type BoolType = typeof(bool); + internal static Type BoolTypeNull = typeof(bool?); + internal static Type ByteType = typeof(Byte); + internal static Type ObjType = typeof(object); + internal static Type DobType = typeof(double); + internal static Type FloatType = typeof(float); + internal static Type ShortType = typeof(short); + internal static Type DecType = typeof(decimal); + internal static Type StringType = typeof(string); + internal static Type DateType = typeof(DateTime); + internal static Type DateTimeOffsetType = typeof(DateTimeOffset); + internal static Type TimeSpanType = typeof(TimeSpan); + internal static Type ByteArrayType = typeof(byte[]); + internal static Type ModelType= typeof(ModelContext); + internal static Type DynamicType = typeof(ExpandoObject); + internal static Type Dicii = typeof(KeyValuePair); + internal static Type DicIS = typeof(KeyValuePair); + internal static Type DicSi = typeof(KeyValuePair); + internal static Type DicSS = typeof(KeyValuePair); + internal static Type DicOO = typeof(KeyValuePair); + internal static Type DicSo = typeof(KeyValuePair); + internal static Type DicArraySS = typeof(Dictionary); + internal static Type DicArraySO = typeof(Dictionary); + + public static Type SugarType = typeof(SqlSugarProvider); + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/UtilConvert.cs b/类库/SqlSugar/5.0.0.9/Utilities/UtilConvert.cs new file mode 100644 index 0000000..ca44956 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/UtilConvert.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public static class UtilConvert + { + public static int ObjToInt(this object thisValue) + { + int reval = 0; + if (thisValue == null) return 0; + if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return reval; + } + + public static int ObjToInt(this object thisValue, int errorValue) + { + int reval = 0; + if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return errorValue; + } + + public static double ObjToMoney(this object thisValue) + { + double reval = 0; + if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return 0; + } + + public static double ObjToMoney(this object thisValue, double errorValue) + { + double reval = 0; + if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return errorValue; + } + + public static string ObjToString(this object thisValue) + { + if (thisValue != null) return thisValue.ToString().Trim(); + return ""; + } + + public static string ObjToString(this object thisValue, string errorValue) + { + if (thisValue != null) return thisValue.ToString().Trim(); + return errorValue; + } + + public static Decimal ObjToDecimal(this object thisValue) + { + Decimal reval = 0; + if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return 0; + } + + public static Decimal ObjToDecimal(this object thisValue, decimal errorValue) + { + Decimal reval = 0; + if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return errorValue; + } + + public static DateTime ObjToDate(this object thisValue) + { + DateTime reval = DateTime.MinValue; + if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval)) + { + reval = Convert.ToDateTime(thisValue); + } + return reval; + } + + public static DateTime ObjToDate(this object thisValue, DateTime errorValue) + { + DateTime reval = DateTime.MinValue; + if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return errorValue; + } + + public static bool ObjToBool(this object thisValue) + { + bool reval = false; + if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return reval; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/UtilExceptions.cs b/类库/SqlSugar/5.0.0.9/Utilities/UtilExceptions.cs new file mode 100644 index 0000000..a2cd98d --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/UtilExceptions.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Newtonsoft.Json; +namespace SqlSugar +{ + public class SqlSugarException : Exception + { + public string Sql { get; set; } + public object Parametres { get; set; } + public new Exception InnerException; + public new string StackTrace; + public new MethodBase TargetSite; + public new string Source; + + public SqlSugarException(string message) + : base(message){} + + public SqlSugarException(SqlSugarProvider context,string message, string sql) + : base(message) { + this.Sql = sql; + } + + public SqlSugarException(SqlSugarProvider context, string message, string sql, object pars) + : base(message) { + this.Sql = sql; + this.Parametres = pars; + } + + public SqlSugarException(SqlSugarProvider context, Exception ex, string sql, object pars) + : base(ex.Message) + { + this.Sql = sql; + this.Parametres = pars; + this.InnerException = ex.InnerException; + this.StackTrace = ex.StackTrace; + this.TargetSite = ex.TargetSite; + this.Source = ex.Source; + } + + public SqlSugarException(SqlSugarProvider context, string message, object pars) + : base(message) { + this.Parametres = pars; + } + } + public class VersionExceptions : SqlSugarException + { + public VersionExceptions(string message) + : base(message){ } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/UtilMethods.cs b/类库/SqlSugar/5.0.0.9/Utilities/UtilMethods.cs new file mode 100644 index 0000000..52f7bcf --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/UtilMethods.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Data.SqlClient; +using System.Globalization; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class UtilMethods + { + + internal static object To(object value, Type destinationType) + { + return To(value, destinationType, CultureInfo.InvariantCulture); + } + + internal static object To(object value, Type destinationType, CultureInfo culture) + { + if (value != null) + { + destinationType = UtilMethods.GetUnderType(destinationType); + var sourceType = value.GetType(); + + var destinationConverter = TypeDescriptor.GetConverter(destinationType); + if (destinationConverter != null && destinationConverter.CanConvertFrom(value.GetType())) + return destinationConverter.ConvertFrom(null, culture, value); + + var sourceConverter = TypeDescriptor.GetConverter(sourceType); + if (sourceConverter != null && sourceConverter.CanConvertTo(destinationType)) + return sourceConverter.ConvertTo(null, culture, value, destinationType); + + if (destinationType.IsEnum && value is int) + return Enum.ToObject(destinationType, (int)value); + + if (!destinationType.IsInstanceOfType(value)) + return Convert.ChangeType(value, destinationType, culture); + } + return value; + } + + internal static T To(object value) + { + return (T)To(value, typeof(T)); + } + internal static Type GetUnderType(Type oldType) + { + Type type = Nullable.GetUnderlyingType(oldType); + return type == null ? oldType : type; + } + public static string ReplaceSqlParameter(string itemSql, SugarParameter itemParameter, string newName) + { + itemSql = Regex.Replace(itemSql, string.Format(@"{0} ", "\\" + itemParameter.ParameterName), newName + " ", RegexOptions.IgnoreCase); + itemSql = Regex.Replace(itemSql, string.Format(@"{0}\)", "\\" + itemParameter.ParameterName), newName + ")", RegexOptions.IgnoreCase); + itemSql = Regex.Replace(itemSql, string.Format(@"{0}\,", "\\" + itemParameter.ParameterName), newName + ",", RegexOptions.IgnoreCase); + itemSql = Regex.Replace(itemSql, string.Format(@"{0}$", "\\" + itemParameter.ParameterName), newName, RegexOptions.IgnoreCase); + return itemSql; + } + internal static Type GetRootBaseType(Type entityType) + { + var baseType = entityType.BaseType; + while (baseType != null && baseType.BaseType != UtilConstants.ObjType) + { + baseType = baseType.BaseType; + } + return baseType; + } + + + internal static Type GetUnderType(PropertyInfo propertyInfo, ref bool isNullable) + { + Type unType = Nullable.GetUnderlyingType(propertyInfo.PropertyType); + isNullable = unType != null; + unType = unType ?? propertyInfo.PropertyType; + return unType; + } + + internal static Type GetUnderType(PropertyInfo propertyInfo) + { + Type unType = Nullable.GetUnderlyingType(propertyInfo.PropertyType); + unType = unType ?? propertyInfo.PropertyType; + return unType; + } + + internal static bool IsNullable(PropertyInfo propertyInfo) + { + Type unType = Nullable.GetUnderlyingType(propertyInfo.PropertyType); + return unType != null; + } + + internal static bool IsNullable(Type type) + { + Type unType = Nullable.GetUnderlyingType(type); + return unType != null; + } + internal static T IsNullReturnNew(T returnObj) where T : new() + { + if (returnObj.IsNullOrEmpty()) + { + returnObj = new T(); + } + return returnObj; + } + + internal static T ChangeType(T obj, Type type) + { + return (T)Convert.ChangeType(obj, type); + } + + internal static T ChangeType(T obj) + { + return (T)Convert.ChangeType(obj, typeof(T)); + } + + internal static void RepairReplicationParameters(ref string appendSql, SugarParameter[] parameters, int addIndex,string append=null) + { + if (appendSql.HasValue() && parameters.HasValue()) + { + foreach (var parameter in parameters.OrderByDescending(it => it.ParameterName.Length)) + { + //Compatible with.NET CORE parameters case + var name = parameter.ParameterName; + string newName = name +append+ addIndex; + appendSql = ReplaceSqlParameter(appendSql, parameter, newName); + parameter.ParameterName = newName; + } + } + } + + internal static string GetPackTable(string sql, string shortName) + { + return string.Format(" ({0}) {1} ", sql, shortName); + } + + internal static string GetParenthesesValue(string dbTypeName) + { + if (Regex.IsMatch(dbTypeName, @"\(.+\)")) + { + dbTypeName = Regex.Replace(dbTypeName, @"\(.+\)", ""); + } + dbTypeName = dbTypeName.Trim(); + return dbTypeName; + } + + internal static T GetOldValue(T value, Action action) + { + action(); + return value; + } + + internal static object DefaultForType(Type targetType) + { + return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; + } + + internal static Int64 GetLong(byte[] bytes) + { + return Convert.ToInt64(string.Join("", bytes).PadRight(20, '0')); + } + + internal static string GetMD5(string myString) + { + MD5 md5 = new MD5CryptoServiceProvider(); + byte[] fromData = System.Text.Encoding.Unicode.GetBytes(myString); + byte[] targetData = md5.ComputeHash(fromData); + string byte2String = null; + + for (int i = 0; i < targetData.Length; i++) + { + byte2String += targetData[i].ToString("x"); + } + + return byte2String; + } + + public static string EncodeBase64(string code) + { + if (code.IsNullOrEmpty()) return code; + string encode = ""; + byte[] bytes = Encoding.GetEncoding("utf-8").GetBytes(code); + try + { + encode = Convert.ToBase64String(bytes); + } + catch + { + encode = code; + } + return encode; + } + public static string ConvertNumbersToString(string value) + { + string[] splitInt = value.Split(new char[] { '9' }, StringSplitOptions.RemoveEmptyEntries); + + var splitChars = splitInt.Select(s => Convert.ToChar( + Convert.ToInt32(s, 8) + ).ToString()); + + return string.Join("", splitChars); + } + public static string ConvertStringToNumbers(string value) + { + StringBuilder sb = new StringBuilder(); + + foreach (char c in value) + { + int cAscil = (int)c; + sb.Append(Convert.ToString(c, 8) + "9"); + } + + return sb.ToString(); + } + + public static string DecodeBase64(string code) + { + try + { + if (code.IsNullOrEmpty()) return code; + string decode = ""; + byte[] bytes = Convert.FromBase64String(code); + try + { + decode = Encoding.GetEncoding("utf-8").GetString(bytes); + } + catch + { + decode = code; + } + return decode; + } + catch + { + return code; + } + } + + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/UtilRandom.cs b/类库/SqlSugar/5.0.0.9/Utilities/UtilRandom.cs new file mode 100644 index 0000000..5a51119 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/UtilRandom.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class UtilRandom + { + public static Random Random = new Random(); + public static int GetRandomIndex(Dictionary pars) + { + int maxValue = 0; + foreach (var item in pars) + { + maxValue += item.Value; + } + var num = Random.Next(1, maxValue); + var result = 0; + var endValue = 0; + foreach (var item in pars) + { + var index = pars.ToList().IndexOf(item); + var beginValue = index == 0 ? 0 : pars[index - 1]; + endValue += item.Value; + result = item.Key; + if (num >= beginValue && num <= endValue) + break; + } + return result; + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/Utilities/ValidateExtensions.cs b/类库/SqlSugar/5.0.0.9/Utilities/ValidateExtensions.cs new file mode 100644 index 0000000..df518b7 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/Utilities/ValidateExtensions.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +namespace SqlSugar +{ + internal static class ValidateExtensions + { + public static bool IsInRange(this int thisValue, int begin, int end) + { + return thisValue >= begin && thisValue <= end; + } + + public static bool IsInRange(this DateTime thisValue, DateTime begin, DateTime end) + { + return thisValue >= begin && thisValue <= end; + } + + public static bool IsIn(this T thisValue, params T[] values) + { + return values.Contains(thisValue); + } + + public static bool IsContainsIn(this string thisValue, params string[] inValues) + { + return inValues.Any(it => thisValue.Contains(it)); + } + + public static bool IsNullOrEmpty(this object thisValue) + { + if (thisValue == null || thisValue == DBNull.Value) return true; + return thisValue.ToString() == ""; + } + + public static bool IsNullOrEmpty(this Guid? thisValue) + { + if (thisValue == null) return true; + return thisValue == Guid.Empty; + } + + public static bool IsNullOrEmpty(this Guid thisValue) + { + if (thisValue == null) return true; + return thisValue == Guid.Empty; + } + + public static bool IsNullOrEmpty(this IEnumerable thisValue) + { + if (thisValue == null || thisValue.Count() == 0) return true; + return false; + } + + public static bool HasValue(this object thisValue) + { + if (thisValue == null || thisValue == DBNull.Value) return false; + return thisValue.ToString() != ""; + } + + public static bool HasValue(this IEnumerable thisValue) + { + if (thisValue == null || thisValue.Count() == 0) return false; + return true; + } + + public static bool IsValuable(this IEnumerable> thisValue) + { + if (thisValue == null || thisValue.Count() == 0) return false; + return true; + } + + public static bool IsZero(this object thisValue) + { + return (thisValue == null || thisValue.ToString() == "0"); + } + + public static bool IsInt(this object thisValue) + { + if (thisValue == null) return false; + return Regex.IsMatch(thisValue.ToString(), @"^\d+$"); + } + + /// + public static bool IsNoInt(this object thisValue) + { + if (thisValue == null) return true; + return !Regex.IsMatch(thisValue.ToString(), @"^\d+$"); + } + + public static bool IsMoney(this object thisValue) + { + if (thisValue == null) return false; + double outValue = 0; + return double.TryParse(thisValue.ToString(), out outValue); + } + public static bool IsGuid(this object thisValue) + { + if (thisValue == null) return false; + Guid outValue = Guid.Empty; + return Guid.TryParse(thisValue.ToString(), out outValue); + } + + public static bool IsDate(this object thisValue) + { + if (thisValue == null) return false; + DateTime outValue = DateTime.MinValue; + return DateTime.TryParse(thisValue.ToString(), out outValue); + } + + public static bool IsEamil(this object thisValue) + { + if (thisValue == null) return false; + return Regex.IsMatch(thisValue.ToString(), @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"); + } + + public static bool IsMobile(this object thisValue) + { + if (thisValue == null) return false; + return Regex.IsMatch(thisValue.ToString(), @"^\d{11}$"); + } + + public static bool IsTelephone(this object thisValue) + { + if (thisValue == null) return false; + return System.Text.RegularExpressions.Regex.IsMatch(thisValue.ToString(), @"^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}$"); + + } + + public static bool IsIDcard(this object thisValue) + { + if (thisValue == null) return false; + return System.Text.RegularExpressions.Regex.IsMatch(thisValue.ToString(), @"^(\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$"); + } + + public static bool IsFax(this object thisValue) + { + if (thisValue == null) return false; + return System.Text.RegularExpressions.Regex.IsMatch(thisValue.ToString(), @"^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$"); + } + + public static bool IsMatch(this object thisValue, string pattern) + { + if (thisValue == null) return false; + Regex reg = new Regex(pattern); + return reg.IsMatch(thisValue.ToString()); + } + public static bool IsAnonymousType(this Type type) + { + string typeName = type.Name; + return typeName.Contains("<>") && typeName.Contains("__") && typeName.Contains("AnonymousType"); + } + public static bool IsCollectionsList(this string thisValue) + { + return (thisValue + "").StartsWith("System.Collections.Generic.List")|| (thisValue + "").StartsWith("System.Collections.Generic.IEnumerable"); + } + public static bool IsStringArray(this string thisValue) + { + return (thisValue + "").IsMatch(@"System\.[a-z,A-Z,0-9]+?\[\]"); + } + public static bool IsEnumerable(this string thisValue) + { + return (thisValue + "").StartsWith("System.Linq.Enumerable"); + } + + public static Type StringType = typeof (string); + + public static bool IsClass(this Type thisValue) + { + return thisValue != StringType && thisValue.IsEntity(); + } + } +} diff --git a/类库/SqlSugar/5.0.0.9/nuget.bat b/类库/SqlSugar/5.0.0.9/nuget.bat new file mode 100644 index 0000000..68b1bf6 --- /dev/null +++ b/类库/SqlSugar/5.0.0.9/nuget.bat @@ -0,0 +1 @@ +%~dp0nuget.exe pack %~dp0SqlSugar.nuspec -OutputDirectory %~dp0 \ No newline at end of file diff --git a/类库/SqlSugar/Abstract/AdoProvider/AdoAccessory.cs b/类库/SqlSugar/Abstract/AdoProvider/AdoAccessory.cs new file mode 100644 index 0000000..634fd21 --- /dev/null +++ b/类库/SqlSugar/Abstract/AdoProvider/AdoAccessory.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public partial class AdoAccessory + { + protected IDbBind _DbBind; + protected IDbFirst _DbFirst; + protected ICodeFirst _CodeFirst; + protected IDbMaintenance _DbMaintenance; + protected IDbConnection _DbConnection; + + protected virtual SugarParameter[] GetParameters(object parameters, PropertyInfo[] propertyInfo, string sqlParameterKeyWord) + { + List result = new List(); + if (parameters != null) + { + var entityType = parameters.GetType(); + var isDictionary = entityType.IsIn(UtilConstants.DicArraySO, UtilConstants.DicArraySS); + if (isDictionary) + DictionaryToParameters(parameters, sqlParameterKeyWord, result, entityType); + else if (parameters is List) + { + result = (parameters as List); + } + else if (parameters is SugarParameter[]) + { + result = (parameters as SugarParameter[]).ToList(); + } + else + { + Check.Exception(!entityType.IsAnonymousType(), "The parameter format is wrong. \nUse new{{xx=xx, xx2=xx2}} or \nDictionary or \nSugarParameter [] "); + ProperyToParameter(parameters, propertyInfo, sqlParameterKeyWord, result, entityType); + } + } + return result.ToArray(); + } + protected void ProperyToParameter(object parameters, PropertyInfo[] propertyInfo, string sqlParameterKeyWord, List listParams, Type entityType) + { + PropertyInfo[] properties = null; + if (propertyInfo != null) + properties = propertyInfo; + else + properties = entityType.GetProperties(); + + foreach (PropertyInfo properyty in properties) + { + var value = properyty.GetValue(parameters, null); + if (properyty.PropertyType.IsEnum()) + value = Convert.ToInt64(value); + if (value == null || value.Equals(DateTime.MinValue)) value = DBNull.Value; + if (properyty.Name.ToLower().Contains("hierarchyid")) + { + var parameter = new SugarParameter(sqlParameterKeyWord + properyty.Name, SqlDbType.Udt); + parameter.UdtTypeName = "HIERARCHYID"; + parameter.Value = value; + listParams.Add(parameter); + } + else + { + var parameter = new SugarParameter(sqlParameterKeyWord + properyty.Name, value); + listParams.Add(parameter); + } + } + } + protected void DictionaryToParameters(object parameters, string sqlParameterKeyWord, List listParams, Type entityType) + { + if (entityType == UtilConstants.DicArraySO) + { + var dictionaryParameters = (Dictionary)parameters; + var sugarParameters = dictionaryParameters.Select(it => new SugarParameter(sqlParameterKeyWord + it.Key, it.Value)); + listParams.AddRange(sugarParameters); + } + else + { + var dictionaryParameters = (Dictionary)parameters; + var sugarParameters = dictionaryParameters.Select(it => new SugarParameter(sqlParameterKeyWord + it.Key, it.Value)); + listParams.AddRange(sugarParameters); ; + } + } + } +} \ No newline at end of file diff --git a/类库/SqlSugar/Abstract/AdoProvider/AdoProvider.cs b/类库/SqlSugar/Abstract/AdoProvider/AdoProvider.cs new file mode 100644 index 0000000..b92364e --- /dev/null +++ b/类库/SqlSugar/Abstract/AdoProvider/AdoProvider.cs @@ -0,0 +1,850 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +namespace SqlSugar +{ + /// + /// ** description:ActiveX Data Objects + /// ** author:sunkaixuan + /// ** date:2017/1/2 + /// ** email:610262374@qq.com + /// + public abstract partial class AdoProvider : AdoAccessory, IAdo + { + #region Constructor + public AdoProvider() + { + this.IsEnableLogEvent = false; + this.CommandType = CommandType.Text; + this.IsClearParameters = true; + this.CommandTimeOut = 30000; + } + #endregion + + #region Properties + protected List OutputParameters { get; set; } + public virtual string SqlParameterKeyWord { get { return "@"; } } + public IDbTransaction Transaction { get; set; } + public virtual SqlSugarClient Context { get; set; } + internal CommandType OldCommandType { get; set; } + internal bool OldClearParameters { get; set; } + public IDataParameterCollection DataReaderParameters { get; set; } + public TimeSpan SqlExecutionTime { get { return AfterTime - BeforeTime; } } + internal DateTime BeforeTime = DateTime.MinValue; + internal DateTime AfterTime = DateTime.MinValue; + public virtual IDbBind DbBind + { + get + { + if (base._DbBind == null) + { + IDbBind bind = InstanceFactory.GetDbBind(this.Context.CurrentConnectionConfig); + base._DbBind = bind; + bind.Context = this.Context; + } + return base._DbBind; + } + } + public virtual int CommandTimeOut { get; set; } + public virtual CommandType CommandType { get; set; } + public virtual bool IsEnableLogEvent { get; set; } + public virtual bool IsClearParameters { get; set; } + public virtual Action LogEventStarting { get; set; } + public virtual Action LogEventCompleted { get; set; } + public virtual Func> ProcessingEventStartingSQL { get; set; } + protected virtual Func FormatSql { get; set; } + public virtual Action ErrorEvent { get; set; } + public virtual Action DiffLogEvent { get; set; } + public virtual List SlaveConnections { get; set; } + public virtual IDbConnection MasterConnection { get; set; } + #endregion + + #region Connection + public virtual void Open() + { + CheckConnection(); + } + public virtual void Close() + { + if (this.Transaction != null) + { + this.Transaction = null; + } + if (this.Connection != null && this.Connection.State == ConnectionState.Open) + { + this.Connection.Close(); + } + if (this.IsMasterSlaveSeparation && this.SlaveConnections.HasValue()) + { + foreach (var slaveConnection in this.SlaveConnections) + { + if (slaveConnection != null && slaveConnection.State == ConnectionState.Open) + { + slaveConnection.Close(); + } + } + } + } + public virtual void Dispose() + { + if (this.Transaction != null) + { + this.Transaction.Commit(); + this.Transaction = null; + } + if (this.Connection != null && this.Connection.State != ConnectionState.Open) + { + this.Connection.Close(); + } + if (this.Connection != null) + { + this.Connection.Dispose(); + } + this.Connection = null; + + if (this.IsMasterSlaveSeparation) + { + if (this.SlaveConnections != null) + { + foreach (var slaveConnection in this.SlaveConnections) + { + if (slaveConnection != null && slaveConnection.State == ConnectionState.Open) + { + slaveConnection.Dispose(); + } + } + } + } + } + public virtual void CheckConnection() + { + if (this.Connection.State != ConnectionState.Open) + { + try + { + this.Connection.Open(); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + } + + #endregion + + #region Transaction + public virtual void BeginTran() + { + CheckConnection(); + this.Transaction = this.Connection.BeginTransaction(); + } + public virtual void BeginTran(IsolationLevel iso) + { + CheckConnection(); + this.Transaction = this.Connection.BeginTransaction(iso); + } + public virtual void RollbackTran() + { + if (this.Transaction != null) + { + this.Transaction.Rollback(); + this.Transaction = null; + if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) this.Close(); + } + } + public virtual void CommitTran() + { + if (this.Transaction != null) + { + this.Transaction.Commit(); + this.Transaction = null; + if (this.Context.CurrentConnectionConfig.IsAutoCloseConnection) this.Close(); + } + } + #endregion + + #region abstract + public abstract IDataParameter[] ToIDbDataParameter(params SugarParameter[] pars); + public abstract void SetCommandToAdapter(IDataAdapter adapter, IDbCommand command); + public abstract IDataAdapter GetAdapter(); + public abstract IDbCommand GetCommand(string sql, SugarParameter[] pars); + public abstract IDbConnection Connection { get; set; } + public abstract void BeginTran(string transactionName);//Only SqlServer + public abstract void BeginTran(IsolationLevel iso, string transactionName);//Only SqlServer + #endregion + + #region Use + public DbResult UseTran(Action action) + { + var result = new DbResult(); + try + { + this.BeginTran(); + if (action != null) + action(); + this.CommitTran(); + result.Data = result.IsSuccess = true; + } + catch (Exception ex) + { + result.ErrorException = ex; + result.ErrorMessage = ex.Message; + result.IsSuccess = false; + this.RollbackTran(); + } + return result; + } + + public Task> UseTranAsync(Action action) + { + Task> result = new Task>(() => + { + return UseTran(action); + }); + TaskStart(result); + return result; + } + + public DbResult UseTran(Func action) + { + var result = new DbResult(); + try + { + this.BeginTran(); + if (action != null) + result.Data = action(); + this.CommitTran(); + result.IsSuccess = true; + } + catch (Exception ex) + { + result.ErrorException = ex; + result.ErrorMessage = ex.Message; + result.IsSuccess = false; + this.RollbackTran(); + } + return result; + } + + public Task> UseTranAsync(Func action) + { + Task> result = new Task>(() => + { + return UseTran(action); + }); + TaskStart(result); + return result; + } + + public void UseStoredProcedure(Action action) + { + var oldCommandType = this.CommandType; + this.CommandType = CommandType.StoredProcedure; + this.IsClearParameters = false; + if (action != null) + { + action(); + } + this.CommandType = oldCommandType; + this.IsClearParameters = true; + } + public T UseStoredProcedure(Func action) + { + T result = default(T); + var oldCommandType = this.CommandType; + this.CommandType = CommandType.StoredProcedure; + this.IsClearParameters = false; + if (action != null) + { + result = action(); + } + this.CommandType = oldCommandType; + this.IsClearParameters = true; + return result; + } + public IAdo UseStoredProcedure() + { + this.OldCommandType = this.CommandType; + this.OldClearParameters = this.IsClearParameters; + this.CommandType = CommandType.StoredProcedure; + this.IsClearParameters = false; + return this; + } + #endregion + + #region Core + public virtual int ExecuteCommand(string sql, params SugarParameter[] parameters) + { + try + { + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + IDbCommand sqlCommand = GetCommand(sql, parameters); + int count = sqlCommand.ExecuteNonQuery(); + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + return count; + } + catch (Exception ex) + { + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + finally + { + if (this.IsAutoClose()) this.Close(); + SetConnectionEnd(sql); + } + } + public virtual IDataReader GetDataReader(string sql, params SugarParameter[] parameters) + { + try + { + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + var isSp = this.CommandType == CommandType.StoredProcedure; + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + IDbCommand sqlCommand = GetCommand(sql, parameters); + IDataReader sqlDataReader = sqlCommand.ExecuteReader(this.IsAutoClose() ? CommandBehavior.CloseConnection : CommandBehavior.Default); + if (isSp) + DataReaderParameters = sqlCommand.Parameters; + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + SetConnectionEnd(sql); + return sqlDataReader; + } + catch (Exception ex) + { + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + } + public virtual DataSet GetDataSetAll(string sql, params SugarParameter[] parameters) + { + try + { + InitParameters(ref sql, parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + IDataAdapter dataAdapter = this.GetAdapter(); + IDbCommand sqlCommand = GetCommand(sql, parameters); + this.SetCommandToAdapter(dataAdapter, sqlCommand); + DataSet ds = new DataSet(); + dataAdapter.Fill(ds); + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + return ds; + } + catch (Exception ex) + { + if (ErrorEvent != null) + ExecuteErrorEvent(sql, parameters, ex); + throw ex; + } + finally + { + if (this.IsAutoClose()) this.Close(); + SetConnectionEnd(sql); + } + } + public virtual object GetScalar(string sql, params SugarParameter[] parameters) + { + try + { + InitParameters(ref sql,parameters); + if (FormatSql != null) + sql = FormatSql(sql); + SetConnectionStart(sql); + if (this.ProcessingEventStartingSQL != null) + ExecuteProcessingSQL(ref sql, parameters); + ExecuteBefore(sql, parameters); + IDbCommand sqlCommand = GetCommand(sql, parameters); + object scalar = sqlCommand.ExecuteScalar(); + //scalar = (scalar == null ? 0 : scalar); + if (this.IsClearParameters) + sqlCommand.Parameters.Clear(); + ExecuteAfter(sql, parameters); + return scalar; + } + catch (Exception ex) + { + if (ErrorEvent != null) + ExecuteErrorEvent(sql,parameters,ex); + throw ex; + } + finally + { + if (this.IsAutoClose()) this.Close(); + SetConnectionEnd(sql); + } + } + #endregion + + #region Methods + + public virtual string GetString(string sql, object parameters) + { + return GetString(sql, this.GetParameters(parameters)); + } + public virtual string GetString(string sql, params SugarParameter[] parameters) + { + return Convert.ToString(GetScalar(sql, parameters)); + } + public virtual string GetString(string sql, List parameters) + { + if (parameters == null) + { + return GetString(sql); + } + else + { + return GetString(sql, parameters.ToArray()); + } + } + public virtual int GetInt(string sql, object parameters) + { + return GetInt(sql, this.GetParameters(parameters)); + } + public virtual int GetInt(string sql, params SugarParameter[] parameters) + { + return GetScalar(sql, parameters).ObjToInt(); + } + public virtual int GetInt(string sql, List parameters) + { + if (parameters == null) + { + return GetInt(sql); + } + else + { + return GetInt(sql, parameters.ToArray()); + } + } + public virtual Double GetDouble(string sql, object parameters) + { + return GetDouble(sql, this.GetParameters(parameters)); + } + public virtual Double GetDouble(string sql, params SugarParameter[] parameters) + { + return GetScalar(sql, parameters).ObjToMoney(); + } + public virtual Double GetDouble(string sql, List parameters) + { + if (parameters == null) + { + return GetDouble(sql); + } + else + { + return GetDouble(sql, parameters.ToArray()); + } + } + public virtual decimal GetDecimal(string sql, object parameters) + { + return GetDecimal(sql, this.GetParameters(parameters)); + } + public virtual decimal GetDecimal(string sql, params SugarParameter[] parameters) + { + return GetScalar(sql, parameters).ObjToDecimal(); + } + public virtual decimal GetDecimal(string sql, List parameters) + { + if (parameters == null) + { + return GetDecimal(sql); + } + else + { + return GetDecimal(sql, parameters.ToArray()); + } + } + public virtual DateTime GetDateTime(string sql, object parameters) + { + return GetDateTime(sql, this.GetParameters(parameters)); + } + public virtual DateTime GetDateTime(string sql, params SugarParameter[] parameters) + { + return GetScalar(sql, parameters).ObjToDate(); + } + public virtual DateTime GetDateTime(string sql, List parameters) + { + if (parameters == null) + { + return GetDateTime(sql); + } + else + { + return GetDateTime(sql, parameters.ToArray()); + } + } + public virtual List SqlQuery(string sql, object parameters = null) + { + var sugarParameters = this.GetParameters(parameters); + return SqlQuery(sql, sugarParameters); + } + public virtual List SqlQuery(string sql, params SugarParameter[] parameters) + { + this.Context.InitMppingInfo(); + var builder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + builder.SqlQueryBuilder.sql.Append(sql); + if (parameters != null && parameters.Any()) + builder.SqlQueryBuilder.Parameters.AddRange(parameters); + var dataReader = this.GetDataReader(builder.SqlQueryBuilder.ToSqlString(), builder.SqlQueryBuilder.Parameters.ToArray()); + List result = this.DbBind.DataReaderToList(typeof(T), dataReader); + builder.SqlQueryBuilder.Clear(); + if (this.Context.Ado.DataReaderParameters != null) + { + foreach (IDataParameter item in this.Context.Ado.DataReaderParameters) + { + var parameter = parameters.FirstOrDefault(it => item.ParameterName.Substring(1) == it.ParameterName.Substring(1)); + if (parameter != null) + { + parameter.Value = item.Value; + } + } + this.Context.Ado.DataReaderParameters = null; + } + return result; + } + + public virtual List SqlQuery(string sql, List parameters) + { + if (parameters != null) + { + return SqlQuery(sql, parameters.ToArray()); + } + else + { + return SqlQuery(sql); + } + } + public virtual T SqlQuerySingle(string sql, object parameters = null) + { + var result = SqlQuery(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + public virtual T SqlQuerySingle(string sql, params SugarParameter[] parameters) + { + var result = SqlQuery(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + public virtual T SqlQuerySingle(string sql, List parameters) + { + var result = SqlQuery(sql, parameters); + return result == null ? default(T) : result.FirstOrDefault(); + } + public virtual dynamic SqlQueryDynamic(string sql, object parameters = null) + { + var dt = this.GetDataTable(sql, parameters); + return dt == null ? null : this.Context.Utilities.DataTableToDynamic(dt); + } + public virtual dynamic SqlQueryDynamic(string sql, params SugarParameter[] parameters) + { + var dt = this.GetDataTable(sql, parameters); + return dt == null ? null : this.Context.Utilities.DataTableToDynamic(dt); + } + public dynamic SqlQueryDynamic(string sql, List parameters) + { + var dt = this.GetDataTable(sql, parameters); + return dt == null ? null : this.Context.Utilities.DataTableToDynamic(dt); + } + public virtual DataTable GetDataTable(string sql, params SugarParameter[] parameters) + { + var ds = GetDataSetAll(sql, parameters); + if (ds.Tables.Count != 0 && ds.Tables.Count > 0) return ds.Tables[0]; + return new DataTable(); + } + public virtual DataTable GetDataTable(string sql, object parameters) + { + return GetDataTable(sql, this.GetParameters(parameters)); + } + public virtual DataTable GetDataTable(string sql, List parameters) + { + if (parameters == null) + { + return GetDataTable(sql); + } + else + { + return GetDataTable(sql, parameters.ToArray()); + } + } + public virtual DataSet GetDataSetAll(string sql, object parameters) + { + return GetDataSetAll(sql, this.GetParameters(parameters)); + } + public virtual DataSet GetDataSetAll(string sql, List parameters) + { + if (parameters == null) + { + return GetDataSetAll(sql); + } + else + { + return GetDataSetAll(sql, parameters.ToArray()); + } + } + public virtual IDataReader GetDataReader(string sql, object parameters) + { + return GetDataReader(sql, this.GetParameters(parameters)); + } + public virtual IDataReader GetDataReader(string sql, List parameters) + { + if (parameters == null) + { + return GetDataReader(sql); + } + else + { + return GetDataReader(sql, parameters.ToArray()); + } + } + public virtual object GetScalar(string sql, object parameters) + { + return GetScalar(sql, this.GetParameters(parameters)); + } + public virtual object GetScalar(string sql, List parameters) + { + if (parameters == null) + { + return GetScalar(sql); + } + else + { + return GetScalar(sql, parameters.ToArray()); + } + } + public virtual int ExecuteCommand(string sql, object parameters) + { + return ExecuteCommand(sql, GetParameters(parameters)); + } + public virtual int ExecuteCommand(string sql, List parameters) + { + if (parameters == null) + { + return ExecuteCommand(sql); + } + else + { + return ExecuteCommand(sql, parameters.ToArray()); + } + } + #endregion + + #region Helper + private void TaskStart(Task result) + { + if (this.Context.CurrentConnectionConfig.IsShardSameThread) + { + Check.Exception(true, "IsShardSameThread=true can't be used async method"); + } + result.Start(); + } + private void ExecuteProcessingSQL(ref string sql, SugarParameter[] parameters) + { + var result = this.ProcessingEventStartingSQL(sql, parameters); + sql = result.Key; + parameters = result.Value; + } + public virtual void ExecuteBefore(string sql, SugarParameter[] parameters) + { + if (this.Context.IsAsyncMethod==false&&this.Context.CurrentConnectionConfig.Debugger != null && this.Context.CurrentConnectionConfig.Debugger.EnableThreadSecurityValidation == true) { + + var contextId =this.Context.ContextID.ToString(); + var processId = Thread.CurrentThread.ManagedThreadId.ToString(); + var cache = new ReflectionInoCacheService(); + if (!cache.ContainsKey(contextId)) + { + cache.Add(contextId, processId); + } + else { + var cacheValue = cache.Get(contextId); + if (processId != cacheValue) { + throw new SqlSugarException(this.Context,ErrorMessage.GetThrowMessage("Detection of SqlSugarClient cross-threading usage,a thread needs a new one", "检测到声名的SqlSugarClient跨线程使用,请检查是否静态、是否单例、或者IOC配置错误引起的,保证一个线程new出一个对象 ,具本Sql:")+sql,parameters); + } + } + } + this.BeforeTime = DateTime.Now; + if (this.IsEnableLogEvent) + { + Action action = LogEventStarting; + if (action != null) + { + if (parameters == null || parameters.Length == 0) + { + action(sql, new SugarParameter[] { }); + } + else + { + action(sql, parameters); + } + } + } + } + public virtual void ExecuteAfter(string sql, SugarParameter[] parameters) + { + this.AfterTime = DateTime.Now; + var hasParameter = parameters.HasValue(); + if (hasParameter) + { + foreach (var outputParameter in parameters.Where(it => it.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue))) + { + var gobalOutputParamter = this.OutputParameters.FirstOrDefault(it => it.ParameterName == outputParameter.ParameterName); + if (gobalOutputParamter == null) {//Oracle bug + gobalOutputParamter=this.OutputParameters.FirstOrDefault(it => it.ParameterName == outputParameter.ParameterName.TrimStart(outputParameter.ParameterName.First())); + } + outputParameter.Value = gobalOutputParamter.Value; + this.OutputParameters.Remove(gobalOutputParamter); + } + } + if (this.IsEnableLogEvent) + { + Action action = LogEventCompleted; + if (action != null) + { + if (parameters == null || parameters.Length == 0) + { + action(sql, new SugarParameter[] { }); + } + else + { + action(sql, parameters); + } + } + } + if (this.OldCommandType != 0) + { + this.CommandType = this.OldCommandType; + this.IsClearParameters = this.OldClearParameters; + this.OldCommandType = 0; + this.OldClearParameters = false; + } + } + public virtual SugarParameter[] GetParameters(object parameters, PropertyInfo[] propertyInfo = null) + { + if (parameters == null) return null; + return base.GetParameters(parameters, propertyInfo, this.SqlParameterKeyWord); + } + private bool IsAutoClose() + { + return this.Context.CurrentConnectionConfig.IsAutoCloseConnection && this.Transaction == null; + } + private bool IsMasterSlaveSeparation + { + get + { + return this.Context.CurrentConnectionConfig.SlaveConnectionConfigs.HasValue(); + } + } + private void SetConnectionStart(string sql) + { + if (this.Transaction==null&&this.IsMasterSlaveSeparation && IsRead(sql)) + { + if (this.MasterConnection == null) + { + this.MasterConnection = this.Connection; + } + var saves = this.Context.CurrentConnectionConfig.SlaveConnectionConfigs.Where(it => it.HitRate > 0).ToList(); + var currentIndex = UtilRandom.GetRandomIndex(saves.ToDictionary(it => saves.ToList().IndexOf(it), it => it.HitRate)); + var currentSaveConnection = saves[currentIndex]; + this.Connection = null; + this.Context.CurrentConnectionConfig.ConnectionString = currentSaveConnection.ConnectionString; + this.Connection = this.Connection; + if (this.SlaveConnections.IsNullOrEmpty() || !this.SlaveConnections.Any(it => EqualsConnectionString(it.ConnectionString, this.Connection.ConnectionString))) + { + if (this.SlaveConnections == null) this.SlaveConnections = new List(); + this.SlaveConnections.Add(this.Connection); + } + } + } + + private bool EqualsConnectionString(string connectionString1, string connectionString2) + { + var connectionString1Array = connectionString1.Split(';'); + var connectionString2Array = connectionString2.Split(';'); + var result = connectionString1Array.Except(connectionString2Array); + return result.Count() == 0; + } + + private void SetConnectionEnd(string sql) + { + if (this.IsMasterSlaveSeparation && IsRead(sql)&&this.Transaction==null) + { + this.Connection = this.MasterConnection; + this.Context.CurrentConnectionConfig.ConnectionString = this.MasterConnection.ConnectionString; + } + } + + private bool IsRead(string sql) + { + var sqlLower = sql.ToLower(); + var result = Regex.IsMatch(sqlLower, "[ ]*select[ ]") && !Regex.IsMatch(sqlLower, "[ ]*insert[ ]|[ ]*update[ ]|[ ]*delete[ ]"); + return result; + } + + private void ExecuteErrorEvent(string sql, SugarParameter[] parameters, Exception ex) + { + ErrorEvent(new SqlSugarException(this.Context,ex, sql, parameters)); + } + private void InitParameters(ref string sql, SugarParameter[] parameters) + { + if (parameters.HasValue()) + { + foreach (var item in parameters) + { + if (item.Value != null) + { + var type = item.Value.GetType(); + if ((type != UtilConstants.ByteArrayType && type.IsArray) || type.FullName.IsCollectionsList()) + { + var newValues = new List(); + foreach (var inValute in item.Value as IEnumerable) + { + newValues.Add(inValute.ObjToString()); + } + if (newValues.IsNullOrEmpty()) + { + newValues.Add("-1"); + } + if (item.ParameterName.Substring(0, 1) == ":") + { + sql = sql.Replace("@"+item.ParameterName.Substring(1), newValues.ToArray().ToJoinSqlInVals()); + } + sql = sql.Replace(item.ParameterName, newValues.ToArray().ToJoinSqlInVals()); + item.Value = DBNull.Value; + } + } + } + } + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/AopProvider/AopProvider.cs b/类库/SqlSugar/Abstract/AopProvider/AopProvider.cs new file mode 100644 index 0000000..4dc2641 --- /dev/null +++ b/类库/SqlSugar/Abstract/AopProvider/AopProvider.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class AopProvider + { + private AopProvider() { } + public AopProvider(SqlSugarClient context) + { + this.Context = context; + this.Context.Ado.IsEnableLogEvent = true; + } + private SqlSugarClient Context { get; set; } + public Action OnDiffLogEvent { set { this.Context.Ado.DiffLogEvent = value; } } + public Action OnError { set { this.Context.Ado.ErrorEvent = value; } } + public Action OnLogExecuting { set { this.Context.Ado.LogEventStarting = value; } } + public Action OnLogExecuted { set { this.Context.Ado.LogEventCompleted = value; } } + public Func> OnExecutingChangeSql { set { this.Context.Ado.ProcessingEventStartingSQL = value; } } + } +} diff --git a/类库/SqlSugar/Abstract/CodeFirstProvider/CodeFirstProvider.cs b/类库/SqlSugar/Abstract/CodeFirstProvider/CodeFirstProvider.cs new file mode 100644 index 0000000..8c551d0 --- /dev/null +++ b/类库/SqlSugar/Abstract/CodeFirstProvider/CodeFirstProvider.cs @@ -0,0 +1,299 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public partial class CodeFirstProvider : ICodeFirst + { + #region Properties + public virtual SqlSugarClient Context { get; set; } + protected bool IsBackupTable { get; set; } + protected int MaxBackupDataRows { get; set; } + protected virtual int DefultLength { get; set; } + #endregion + + #region Public methods + public virtual ICodeFirst BackupTable(int maxBackupDataRows = int.MaxValue) + { + this.IsBackupTable = true; + this.MaxBackupDataRows = maxBackupDataRows; + return this; + } + + public virtual ICodeFirst SetStringDefaultLength(int length) { + DefultLength = length; + return this; + } + + public virtual void InitTables(Type entityType) + { + + this.Context.Utilities.RemoveCacheAll(); + this.Context.InitMppingInfo(entityType); + if (!this.Context.DbMaintenance.IsAnySystemTablePermissions()) + { + Check.Exception(true, "Dbfirst and Codefirst requires system table permissions"); + } + Check.Exception(this.Context.IsSystemTablesConfig, "Please set SqlSugarClent Parameter ConnectionConfig.InitKeyType=InitKeyType.Attribute "); + var executeResult = Context.Ado.UseTran(() => + { + Execute(entityType); + }); + Check.Exception(!executeResult.IsSuccess, executeResult.ErrorMessage); + } + public virtual void InitTables(Type[] entityTypes) + { + if (entityTypes.HasValue()) + { + foreach (var item in entityTypes) + { + InitTables(item); + } + } + } + public virtual void InitTables(string entitiesNamespace) + { + var types = Assembly.Load(entitiesNamespace).GetTypes(); + InitTables(types); + } + public virtual void InitTables(params string[] entitiesNamespaces) + { + if (entitiesNamespaces.HasValue()) + { + foreach (var item in entitiesNamespaces) + { + InitTables(item); + } + } + } + #endregion + + #region Core Logic + protected virtual void Execute(Type entityType) + { + var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(entityType); + if (this.DefultLength > 0) { + foreach (var item in entityInfo.Columns) + { + if (item.PropertyInfo.PropertyType == UtilConstants.StringType && item.DataType.IsNullOrEmpty()&& item.Length==0) { + item.Length = DefultLength; + } + } + } + var tableName = GetTableName(entityInfo); + var isAny = this.Context.DbMaintenance.IsAnyTable(tableName); + if (isAny) + ExistLogic(entityInfo); + else + NoExistLogic(entityInfo); + + this.Context.DbMaintenance.AddRemark(entityInfo); + } + public virtual void NoExistLogic(EntityInfo entityInfo) + { + var tableName = GetTableName(entityInfo); + //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns.OrderBy(it=>it.IsPrimarykey?0:1).Where(it => it.IsIgnore == false)) + { + DbColumnInfo dbColumnInfo = EntityColumnToDbColumn(entityInfo, tableName, item); + columns.Add(dbColumnInfo); + } + } + this.Context.DbMaintenance.CreateTable(tableName, columns,true); + } + public virtual void ExistLogic(EntityInfo entityInfo) + { + if (entityInfo.Columns.HasValue()) + { + //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Multiple primary keys do not support modifications"); + + var tableName = GetTableName(entityInfo); + var dbColumns = this.Context.DbMaintenance.GetColumnInfosByTableName(tableName); + ConvertColumns(dbColumns); + var entityColumns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToList(); + var dropColumns = dbColumns + .Where(dc => !entityColumns.Any(ec => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(dc => !entityColumns.Any(ec => dc.DbColumnName.Equals(ec.DbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToList(); + var addColumns = entityColumns + .Where(ec => ec.OldDbColumnName.IsNullOrEmpty() || !dbColumns.Any(dc => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(ec => !dbColumns.Any(dc => ec.DbColumnName.Equals(dc.DbColumnName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + var alterColumns = entityColumns + .Where(ec => !dbColumns.Any(dc => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(ec => + dbColumns.Any(dc => dc.DbColumnName.Equals(ec.DbColumnName) + && ((ec.Length != dc.Length && !UtilMethods.GetUnderType(ec.PropertyInfo).IsEnum() && UtilMethods.GetUnderType(ec.PropertyInfo).IsIn(UtilConstants.StringType)) || + ec.IsNullable != dc.IsNullable || + IsSamgeType(ec, dc)))).ToList(); + var renameColumns = entityColumns + .Where(it => !string.IsNullOrEmpty(it.OldDbColumnName)) + .Where(entityColumn => dbColumns.Any(dbColumn => entityColumn.OldDbColumnName.Equals(dbColumn.DbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToList(); + + + var isMultiplePrimaryKey = dbColumns.Where(it => it.IsPrimarykey).Count() > 1|| entityColumns.Where(it => it.IsPrimarykey).Count() > 1; + + + var isChange = false; + foreach (var item in addColumns) + { + this.Context.DbMaintenance.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + isChange = true; + } + foreach (var item in dropColumns) + { + this.Context.DbMaintenance.DropColumn(tableName, item.DbColumnName); + isChange = true; + } + foreach (var item in alterColumns) + { + this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + isChange = true; + } + foreach (var item in renameColumns) + { + this.Context.DbMaintenance.RenameColumn(tableName, item.OldDbColumnName, item.DbColumnName); + isChange = true; + } + + foreach (var item in entityColumns) + { + var dbColumn = dbColumns.FirstOrDefault(dc => dc.DbColumnName.Equals(item.DbColumnName, StringComparison.CurrentCultureIgnoreCase)); + if (dbColumn == null) continue; + bool pkDiff, idEntityDiff; + KeyAction(item, dbColumn, out pkDiff, out idEntityDiff); + if (dbColumn != null && pkDiff && !idEntityDiff&& isMultiplePrimaryKey==false) + { + var isAdd = item.IsPrimarykey; + if (isAdd) + { + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + else + { + this.Context.DbMaintenance.DropConstraint(tableName, string.Format("PK_{0}_{1}", tableName, item.DbColumnName)); + } + } + else if ((pkDiff || idEntityDiff)&& isMultiplePrimaryKey==false) + { + ChangeKey(entityInfo, tableName, item); + } + } + if (isMultiplePrimaryKey) { + var oldPkNames = dbColumns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName.ToLower()).OrderBy(it=>it).ToList(); + var newPkNames = entityColumns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName.ToLower()).OrderBy(it=>it).ToList(); + if (!Enumerable.SequenceEqual(oldPkNames,newPkNames)) { + Check.Exception(true, ErrorMessage.GetThrowMessage("Modification of multiple primary key tables is not supported. Delete tables while creating", "不支持修改多主键表,请删除表在创建")); + } + + } + if (isChange && IsBackupTable) + { + this.Context.DbMaintenance.BackupTable(tableName, tableName + DateTime.Now.ToString("yyyyMMddHHmmss"), MaxBackupDataRows); + } + } + } + + protected virtual void KeyAction(EntityColumnInfo item, DbColumnInfo dbColumn, out bool pkDiff, out bool idEntityDiff) + { + pkDiff = item.IsPrimarykey != dbColumn.IsPrimarykey; + idEntityDiff = item.IsIdentity != dbColumn.IsIdentity; + } + + protected virtual void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + string constraintName = string.Format("PK_{0}_{1}", tableName, item.DbColumnName); + if (this.Context.DbMaintenance.IsAnyConstraint(constraintName)) + this.Context.DbMaintenance.DropConstraint(tableName, constraintName); + this.Context.DbMaintenance.DropColumn(tableName, item.DbColumnName); + this.Context.DbMaintenance.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + if (item.IsPrimarykey) + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + + protected virtual void ConvertColumns(List dbColumns) + { + + } + #endregion + + #region Helper methods + public virtual string GetCreateTableString(EntityInfo entityInfo) + { + StringBuilder result = new StringBuilder(); + var tableName = GetTableName(entityInfo); + return result.ToString(); + } + public virtual string GetCreateColumnsString(EntityInfo entityInfo) + { + StringBuilder result = new StringBuilder(); + var tableName = GetTableName(entityInfo); + return result.ToString(); + } + protected virtual string GetTableName(EntityInfo entityInfo) + { + return this.Context.EntityMaintenance.GetTableName(entityInfo.EntityName); + } + protected virtual DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + var propertyType = UtilMethods.GetUnderType(item.PropertyInfo); + var result = new DbColumnInfo() + { + TableId = entityInfo.Columns.IndexOf(item), + DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName, + IsPrimarykey = item.IsPrimarykey, + IsIdentity = item.IsIdentity, + TableName = tableName, + IsNullable = item.IsNullable, + DefaultValue = item.DefaultValue, + ColumnDescription = item.ColumnDescription, + Length = item.Length, + DecimalDigits = item.DecimalDigits + }; + GetDbType(item, propertyType, result); + return result; + } + + protected virtual void GetDbType(EntityColumnInfo item, Type propertyType, DbColumnInfo result) + { + if (!string.IsNullOrEmpty(item.DataType)) + { + result.DataType = item.DataType; + } + else if (propertyType.IsEnum()) + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(item.Length > 9 ? UtilConstants.LongType.Name : UtilConstants.IntType.Name); + } + else + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(propertyType.Name); + } + } + + protected virtual bool IsSamgeType(EntityColumnInfo ec, DbColumnInfo dc) + { + if (!string.IsNullOrEmpty(ec.DataType)) + { + return ec.DataType != dc.DataType; + } + var propertyType = UtilMethods.GetUnderType(ec.PropertyInfo); + var properyTypeName = string.Empty; + if (propertyType.IsEnum()) + { + properyTypeName = this.Context.Ado.DbBind.GetDbTypeName(ec.Length > 9 ? UtilConstants.LongType.Name : UtilConstants.IntType.Name); + } + else + { + properyTypeName = this.Context.Ado.DbBind.GetDbTypeName(propertyType.Name); + } + var dataType = dc.DataType; + return properyTypeName != dataType; + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/DbBindProvider/DbBindAccessory.cs b/类库/SqlSugar/Abstract/DbBindProvider/DbBindAccessory.cs new file mode 100644 index 0000000..02d3a0b --- /dev/null +++ b/类库/SqlSugar/Abstract/DbBindProvider/DbBindAccessory.cs @@ -0,0 +1,245 @@ + +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public partial class DbBindAccessory + { + + + + /// + /// 根据输入类型获取对应的成员属性集合 + /// + /// + /// + public static PropertyInfo[] GetProperties(Type type) + { + return type.GetProperties(BindingFlags.Public | BindingFlags.Instance); + } + + /// + /// 设置属性值 + /// + /// + /// + /// + public static void SetPropertyValue(object obj, PropertyInfo property, object value) + { + if (property.CanWrite) + { + Type Ts = obj.GetType(); + object v = Convert.ChangeType(value, Ts.GetProperty(property.Name).PropertyType); + Ts.GetProperty(property.Name).SetValue(obj, v, null); + + } + } + + protected List GetEntityList(SqlSugarClient context, IDataReader dataReader) + { + Type type = typeof(T); + var fieldNames = GetDataReaderNames(dataReader); + string cacheKey = GetCacheKey(type,fieldNames); + IDataReaderEntityBuilder entytyList = context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => + { + var cacheResult = new IDataReaderEntityBuilder(context, dataReader,fieldNames).CreateBuilder(type); + return cacheResult; + }); + List result = new List(); + + //PropertyInfo[] properties = GetProperties(type); + //while (dataReader.Read()) + //{ + // T entity = new T(); + // foreach (PropertyInfo property in properties) + // { + // String name = tableInfo.PropToColumn[property.Name].ToString(); + // ReflectionHelper.SetPropertyValue(entity, property, sdr[name]); + // } + // list.Add(entity); + //} + + //Console.WriteLine(fieldNames); + try + { + + if (dataReader == null) return result; + while (dataReader.Read()) + { + //zheli + + var tar = entytyList.Build(dataReader); + result.Add(entytyList.Build(dataReader)); + } + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.EntityMappingError, ex.Message); + } + return result; + } + + + + protected List GetEntityListNew(SqlSugarClient context, IDataReader dataReader) + { + Type type = typeof(T); + var fieldNames = GetDataReaderNames(dataReader); + string cacheKey = GetCacheKey(type, fieldNames); + IDataReaderEntityBuilder entytyList = context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => + { + var cacheResult = new IDataReaderEntityBuilder(context, dataReader, fieldNames).CreateBuilder(type); + return cacheResult; + }); + + List result = new List(); + //Console.WriteLine(fieldNames); + try + { + + if (dataReader == null) return result; + while (dataReader.Read()) + { + //zheli + result.Add(entytyList.Build(dataReader)); + } + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.EntityMappingError, ex.Message); + } + return result; + } + + private string GetCacheKey(Type type,List keys) + { + StringBuilder sb = new StringBuilder("DataReaderToList."); + sb.Append(type.FullName); + sb.Append("."); + foreach (var item in keys) + { + sb.Append(item); + } + return sb.ToString(); + } + + private List GetDataReaderNames(IDataReader dataReader) + { + List keys = new List(); + var count = dataReader.FieldCount; + for (int i = 0; i < count; i++) + { + keys.Add(dataReader.GetName(i)); + } + return keys; + } + + protected List GetKeyValueList(Type type, IDataReader dataReader) + { + List result = new List(); + while (dataReader.Read()) + { + if (UtilConstants.DicOO == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0), dataReader.GetValue(1)); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.DicIS == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToInt(), dataReader.GetValue(1).ObjToString()); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.Dicii == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToInt(), dataReader.GetValue(1).ObjToInt()); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.DicSi == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1).ObjToInt()); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.DicSo == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1)); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else if (UtilConstants.DicSS == type) + { + var kv = new KeyValuePair(dataReader.GetValue(0).ObjToString(), dataReader.GetValue(1).ObjToString()); + result.Add((T)Convert.ChangeType(kv, typeof(KeyValuePair))); + } + else + { + Check.Exception(true, ErrorMessage.NotSupportedDictionary); + } + } + return result; + } + + protected List GetArrayList(Type type, IDataReader dataReader) + { + List result = new List(); + int count = dataReader.FieldCount; + var childType = type.GetElementType(); + while (dataReader.Read()) + { + object[] array = new object[count]; + for (int i = 0; i < count; i++) + { + array[i] = Convert.ChangeType(dataReader.GetValue(i), childType); + } + if (childType == UtilConstants.StringType) + result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToString()).ToArray(), type)); + else if (childType == UtilConstants.ObjType) + result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? null : (object)it).ToArray(), type)); + else if (childType == UtilConstants.BoolType) + result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToBool()).ToArray(), type)); + else if (childType == UtilConstants.ByteType) + result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? 0 : (byte)it).ToArray(), type)); + else if (childType == UtilConstants.DecType) + result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToDecimal()).ToArray(), type)); + else if (childType == UtilConstants.GuidType) + result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? Guid.Empty : (Guid)it).ToArray(), type)); + else if (childType == UtilConstants.DateType) + result.Add((T)Convert.ChangeType(array.Select(it => it == DBNull.Value ? DateTime.MinValue : (DateTime)it).ToArray(), type)); + else if (childType == UtilConstants.IntType) + result.Add((T)Convert.ChangeType(array.Select(it => it.ObjToInt()).ToArray(), type)); + else + Check.Exception(true, ErrorMessage.NotSupportedArray); + } + return result; + } + + protected List GetValueTypeList(Type type, IDataReader dataReader) + { + List result = new List(); + while (dataReader.Read()) + { + var value = dataReader.GetValue(0); + if (type == UtilConstants.GuidType) + { + value = Guid.Parse(value.ToString()); + } + if (value == DBNull.Value) + { + result.Add(default(T)); + } + else if (type.IsEnum) + { + result.Add((T)Enum.Parse(type, value.ObjToString())); + } + else + { + result.Add((T)Convert.ChangeType(value, UtilMethods.GetUnderType(type))); + } + } + return result; + } + } +} diff --git a/类库/SqlSugar/Abstract/DbBindProvider/DbBindProvider.cs b/类库/SqlSugar/Abstract/DbBindProvider/DbBindProvider.cs new file mode 100644 index 0000000..0a74580 --- /dev/null +++ b/类库/SqlSugar/Abstract/DbBindProvider/DbBindProvider.cs @@ -0,0 +1,260 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public abstract partial class DbBindProvider : DbBindAccessory, IDbBind + { + #region Properties + public virtual SqlSugarClient Context { get; set; } + public abstract List> MappingTypes { get; } + #endregion + + #region Public methods + public virtual string GetDbTypeName(string csharpTypeName) + { + if (csharpTypeName == UtilConstants.ByteArrayType.Name) + return "varbinary"; + if (csharpTypeName.ToLower() == "int32") + csharpTypeName = "int"; + if (csharpTypeName.ToLower() == "int16") + csharpTypeName = "short"; + if (csharpTypeName.ToLower() == "int64") + csharpTypeName = "long"; + if (csharpTypeName.ToLower().IsIn("boolean", "bool")) + csharpTypeName = "bool"; + var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)); + return mappings.HasValue() ? mappings.First().Key : "varchar"; + } + public string GetCsharpTypeName(string dbTypeName) + { + var mappings = this.MappingTypes.Where(it => it.Key == dbTypeName); + return mappings.HasValue() ? mappings.First().Key : "string"; + } + public virtual string GetConvertString(string dbTypeName) + { + string result = string.Empty; + switch (dbTypeName.ToLower()) + { + #region Int + case "int": + result = "Convert.ToInt32"; + break; + #endregion + + #region String + case "nchar": + case "char": + case "ntext": + case "nvarchar": + case "varchar": + case "text": + result = "Convert.ToString"; + break; + #endregion + + #region Long + case "bigint": + result = "Convert.ToInt64"; + break; + #endregion + + #region Bool + case "bit": + result = "Convert.ToBoolean"; + break; + + #endregion + + #region Datetime + case "timestamp": + case "smalldatetime": + case "datetime": + case "date": + case "datetime2": + result = "Convert.ToDateTime"; + break; + #endregion + + #region Decimal + case "smallmoney": + case "single": + case "numeric": + case "money": + case "decimal": + result = "Convert.ToDecimal"; + break; + #endregion + + #region Double + case "float": + result = "Convert.ToDouble"; + break; + #endregion + + #region Byte[] + case "varbinary": + case "binary": + case "image": + result = "byte[]"; + break; + #endregion + + #region Float + case "real": + result = "Convert.ToSingle"; + break; + #endregion + + #region Short + case "smallint": + result = "Convert.ToInt16"; + break; + #endregion + + #region Byte + case "tinyint": + result = "Convert.ToByte"; + break; + + #endregion + + #region Guid + case "uniqueidentifier": + result = "Guid.Parse"; + break; + #endregion + + #region Null + default: + result = null; + break; + #endregion + } + return result; + } + public virtual string GetPropertyTypeName(string dbTypeName) + { + dbTypeName = dbTypeName.ToLower(); + var propertyTypes = MappingTypes.Where(it => it.Key.Equals(dbTypeName, StringComparison.CurrentCultureIgnoreCase)); + if (dbTypeName == "int32") + { + return "int"; + } + else if (dbTypeName == "int64") + { + return "long"; + } + else if (dbTypeName == "int16") + { + return "short"; + } + else if (propertyTypes == null) + { + return "other"; + } + else if (dbTypeName.IsContainsIn("xml", "string", "String")) + { + return "string"; + } + else if (dbTypeName.IsContainsIn("boolean", "bool")) + { + return "bool"; + } + else if (propertyTypes == null || propertyTypes.Count() == 0) + { + Check.ThrowNotSupportedException(string.Format(" \"{0}\" Type NotSupported, DbBindProvider.GetPropertyTypeName error.", dbTypeName)); + return null; + } + else if (propertyTypes.First().Value == CSharpDataType.byteArray) + { + return "byte[]"; + } + else + { + return propertyTypes.First().Value.ToString(); + } + } + public virtual List DataReaderToList(Type type, IDataReader dataReader) + { + using (dataReader) + { + if (type.Name.Contains("KeyValuePair")) + { + return GetKeyValueList(type, dataReader); + } + else if (type.IsValueType() || type == UtilConstants.StringType||type== UtilConstants.ByteArrayType) + { + return GetValueTypeList(type, dataReader); + } + else if (type.IsArray) + { + return GetArrayList(type, dataReader); + } + else + { + + return GetEntityList(Context, dataReader); + } + } + } + #endregion + + #region Throw rule + + public virtual List IntThrow + { + get + { + return new List() { "datetime", "byte" }; + } + } + public virtual List ShortThrow + { + get + { + return new List() { "datetime", "guid" }; + } + } + public virtual List DecimalThrow + { + get + { + return new List() { "datetime", "byte", "guid" }; + } + } + public virtual List DoubleThrow + { + get + { + return new List() { "datetime", "byte", "guid" }; + } + } + public virtual List DateThrow + { + get + { + return new List() { "int32", "decimal", "double", "byte", "guid" }; + } + } + public virtual List GuidThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte" }; + } + } + public virtual List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte", "guid" }; + } + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/DbBindProvider/IDataReaderEntityBuilder.cs b/类库/SqlSugar/Abstract/DbBindProvider/IDataReaderEntityBuilder.cs new file mode 100644 index 0000000..0bacfe1 --- /dev/null +++ b/类库/SqlSugar/Abstract/DbBindProvider/IDataReaderEntityBuilder.cs @@ -0,0 +1,338 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +using System.Reflection; +using System.Reflection.Emit; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + /// + /// ** description:IDataReader Entity Builder + /// ** author:sunkaixuan + /// ** date:2017/4/2 + /// ** qq:610262374 + /// + public partial class IDataReaderEntityBuilder + { + #region Properies + private List ReaderKeys { get; set; } + #endregion + + #region Fields + private SqlSugarClient Context = null; + private IDataReaderEntityBuilder DynamicBuilder; + private IDataRecord DataRecord; + private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new Type[] { typeof(int) }); + private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod("get_Item", new Type[] { typeof(int) }); + private static readonly MethodInfo getBoolean = typeof(IDataRecord).GetMethod("GetBoolean", new Type[] { typeof(int) }); + private static readonly MethodInfo getByte = typeof(IDataRecord).GetMethod("GetByte", new Type[] { typeof(int) }); + private static readonly MethodInfo getDateTime = typeof(IDataRecord).GetMethod("GetDateTime", new Type[] { typeof(int) }); + private static readonly MethodInfo getDecimal = typeof(IDataRecord).GetMethod("GetDecimal", new Type[] { typeof(int) }); + private static readonly MethodInfo getDouble = typeof(IDataRecord).GetMethod("GetDouble", new Type[] { typeof(int) }); + private static readonly MethodInfo getFloat = typeof(IDataRecord).GetMethod("GetFloat", new Type[] { typeof(int) }); + private static readonly MethodInfo getGuid = typeof(IDataRecord).GetMethod("GetGuid", new Type[] { typeof(int) }); + private static readonly MethodInfo getInt16 = typeof(IDataRecord).GetMethod("GetInt16", new Type[] { typeof(int) }); + private static readonly MethodInfo getInt32 = typeof(IDataRecord).GetMethod("GetInt32", new Type[] { typeof(int) }); + private static readonly MethodInfo getInt64 = typeof(IDataRecord).GetMethod("GetInt64", new Type[] { typeof(int) }); + private static readonly MethodInfo getString = typeof(IDataRecord).GetMethod("GetString", new Type[] { typeof(int) }); + private static readonly MethodInfo getdatetimeoffset = typeof(IDataRecordExtensions).GetMethod("Getdatetimeoffset"); + private static readonly MethodInfo getdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod("GetdatetimeoffsetDate"); + private static readonly MethodInfo getStringGuid = typeof(IDataRecordExtensions).GetMethod("GetStringGuid"); + private static readonly MethodInfo getConvertStringGuid = typeof(IDataRecordExtensions).GetMethod("GetConvertStringGuid"); + private static readonly MethodInfo getEnum = typeof(IDataRecordExtensions).GetMethod("GetEnum"); + private static readonly MethodInfo getConvertString = typeof(IDataRecordExtensions).GetMethod("GetConvertString"); + private static readonly MethodInfo getConvertFloat = typeof(IDataRecordExtensions).GetMethod("GetConvertFloat"); + private static readonly MethodInfo getConvertBoolean = typeof(IDataRecordExtensions).GetMethod("GetConvertBoolean"); + private static readonly MethodInfo getConvertByte = typeof(IDataRecordExtensions).GetMethod("GetConvertByte"); + private static readonly MethodInfo getConvertChar = typeof(IDataRecordExtensions).GetMethod("GetConvertChar"); + private static readonly MethodInfo getConvertDateTime = typeof(IDataRecordExtensions).GetMethod("GetConvertDateTime"); + private static readonly MethodInfo getConvertTime = typeof(IDataRecordExtensions).GetMethod("GetConvertTime"); + private static readonly MethodInfo getTime = typeof(IDataRecordExtensions).GetMethod("GetTime"); + private static readonly MethodInfo getConvertDecimal = typeof(IDataRecordExtensions).GetMethod("GetConvertDecimal"); + private static readonly MethodInfo getConvertDouble = typeof(IDataRecordExtensions).GetMethod("GetConvertDouble"); + private static readonly MethodInfo getConvertDoubleToFloat = typeof(IDataRecordExtensions).GetMethod("GetConvertDoubleToFloat"); + private static readonly MethodInfo getConvertGuid = typeof(IDataRecordExtensions).GetMethod("GetConvertGuid"); + private static readonly MethodInfo getConvertInt16 = typeof(IDataRecordExtensions).GetMethod("GetConvertInt16"); + private static readonly MethodInfo getConvertInt32 = typeof(IDataRecordExtensions).GetMethod("GetConvertInt32"); + private static readonly MethodInfo getConvertInt64 = typeof(IDataRecordExtensions).GetMethod("GetConvetInt64"); + private static readonly MethodInfo getConvertEnum_Null = typeof(IDataRecordExtensions).GetMethod("GetConvertEnum_Null"); + private static readonly MethodInfo getConvertdatetimeoffset = typeof(IDataRecordExtensions).GetMethod("GetConvertdatetimeoffset"); + private static readonly MethodInfo getConvertdatetimeoffsetDate = typeof(IDataRecordExtensions).GetMethod("GetConvertdatetimeoffsetDate"); + private static readonly MethodInfo getOtherNull = typeof(IDataRecordExtensions).GetMethod("GetOtherNull"); + private static readonly MethodInfo getOther = typeof(IDataRecordExtensions).GetMethod("GetOther"); + private static readonly MethodInfo getSqliteTypeNull = typeof(IDataRecordExtensions).GetMethod("GetSqliteTypeNull"); + private static readonly MethodInfo getSqliteType = typeof(IDataRecordExtensions).GetMethod("GetSqliteType"); + private static readonly MethodInfo getEntity = typeof(IDataRecordExtensions).GetMethod("GetEntity", new Type[] { typeof(SqlSugarClient) }); + + private delegate T Load(IDataRecord dataRecord); + private Load handler; + #endregion + + #region Constructor + private IDataReaderEntityBuilder() + { + + } + + public IDataReaderEntityBuilder(SqlSugarClient context, IDataRecord dataRecord,List fieldNames) + { + this.Context = context; + this.DataRecord = dataRecord; + this.DynamicBuilder = new IDataReaderEntityBuilder(); + this.ReaderKeys = fieldNames; + } + #endregion + + #region Public methods + public T Build(IDataRecord dataRecord) + { + + + + return handler(dataRecord); + } + + + + + + public IDataReaderEntityBuilder CreateBuilder(Type type) + { + DynamicMethod method = new DynamicMethod("SqlSugarEntity", type, + new Type[] { typeof(IDataRecord) }, type, true); + ILGenerator generator = method.GetILGenerator(); + LocalBuilder result = generator.DeclareLocal(type); + generator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes)); + generator.Emit(OpCodes.Stloc, result); + var mappingColumns = Context.MappingColumns.Where(it => it.EntityName.Equals(type.Name, StringComparison.CurrentCultureIgnoreCase)).ToList(); + var properties = type.GetProperties(); + foreach (var propertyInfo in properties) + { + string fileName = propertyInfo.Name; + if (mappingColumns != null) + { + var mappInfo = mappingColumns.SingleOrDefault(it => it.EntityName == type.Name && it.PropertyName.Equals(propertyInfo.Name)); + if (mappInfo != null) + { + if (!ReaderKeys.Contains(mappInfo.DbColumnName)) + { + fileName = ReaderKeys.FirstOrDefault(it => it.Equals(mappInfo.DbColumnName, StringComparison.CurrentCultureIgnoreCase)|| it.Equals(mappInfo.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + } + else + { + fileName = mappInfo.DbColumnName; + } + } + } + if (IsIgnore(type, propertyInfo)&&!this.ReaderKeys.Any(it=>it==fileName)) + { + continue; + } + if (propertyInfo != null && propertyInfo.GetSetMethod() != null) + { + if (propertyInfo.PropertyType.IsClass() && propertyInfo.PropertyType != UtilConstants.ByteArrayType && propertyInfo.PropertyType != UtilConstants.ObjType) + { + BindClass(generator, result, propertyInfo); + } + else + { + if (this.ReaderKeys.Any(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))) + { + BindField(generator, result, propertyInfo, ReaderKeys.First(it => it.Equals(fileName, StringComparison.CurrentCultureIgnoreCase))); + } + } + } + } + generator.Emit(OpCodes.Ldloc, result); + generator.Emit(OpCodes.Ret); + DynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load)); + return DynamicBuilder; + } + + #endregion + + #region Private methods + private bool IsIgnore(Type type, PropertyInfo propertyInfo) + { + return Context.IgnoreColumns != null && Context.IgnoreColumns.Any(it => it.PropertyName.Equals(propertyInfo.Name, StringComparison.CurrentCultureIgnoreCase) + && it.EntityName.Equals(type.Name, StringComparison.CurrentCultureIgnoreCase)); + } + private void BindClass(ILGenerator generator, LocalBuilder result, PropertyInfo propertyInfo) + { + + } + private void BindField(ILGenerator generator, LocalBuilder result, PropertyInfo propertyInfo, string fileName) + { + int i = DataRecord.GetOrdinal(fileName); + Label endIfLabel = generator.DefineLabel(); + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldc_I4, i); + generator.Emit(OpCodes.Callvirt, isDBNullMethod); + generator.Emit(OpCodes.Brtrue, endIfLabel); + generator.Emit(OpCodes.Ldloc, result); + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldc_I4, i); + BindMethod(generator, propertyInfo, i); + generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); + generator.MarkLabel(endIfLabel); + } + private void BindMethod(ILGenerator generator, PropertyInfo bindProperty, int ordinal) + { + IDbBind bind = Context.Ado.DbBind; + bool isNullableType = false; + MethodInfo method = null; + Type bindPropertyType = UtilMethods.GetUnderType(bindProperty, ref isNullableType); + string dbTypeName = UtilMethods.GetParenthesesValue(DataRecord.GetDataTypeName(ordinal)); + if (dbTypeName.IsNullOrEmpty()) { + dbTypeName = bindPropertyType.Name; + } + string propertyName = bindProperty.Name; + string validPropertyName = bind.GetPropertyTypeName(dbTypeName); + validPropertyName = validPropertyName == "byte[]" ? "byteArray" : validPropertyName; + CSharpDataType validPropertyType = (CSharpDataType)Enum.Parse(typeof(CSharpDataType), validPropertyName); + + #region Sqlite Logic + if (this.Context.CurrentConnectionConfig.DbType == DbType.Sqlite) + { + if (bindPropertyType.IsEnum()) + { + method = isNullableType ? getConvertEnum_Null.MakeGenericMethod(bindPropertyType) : getEnum.MakeGenericMethod(bindPropertyType); + } + else if (bindPropertyType == UtilConstants.IntType) + { + method = isNullableType ? getConvertInt32 : getInt32; + } + else if (bindPropertyType == UtilConstants.StringType) + { + method = getString; + } + else if (bindPropertyType == UtilConstants.ByteArrayType) + { + method = getValueMethod; + generator.Emit(OpCodes.Call, method); + generator.Emit(OpCodes.Unbox_Any, bindProperty.PropertyType); + return; + } + else + { + method = isNullableType ? getSqliteTypeNull.MakeGenericMethod(bindPropertyType) : getSqliteType.MakeGenericMethod(bindPropertyType); + } + generator.Emit(OpCodes.Call, method); + return; + }; + #endregion + + #region Common Database Logic + string bindProperyTypeName = bindPropertyType.Name.ToLower(); + bool isEnum = bindPropertyType.IsEnum(); + if (isEnum) { validPropertyType = CSharpDataType.@enum; } + switch (validPropertyType) + { + case CSharpDataType.@int: + CheckType(bind.IntThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName.IsContainsIn("int", "int32")) + method = isNullableType ? getConvertInt32 : getInt32; + if (bindProperyTypeName.IsContainsIn("int64")) + method = isNullableType ? getConvertInt64 : getInt64; + if (bindProperyTypeName.IsContainsIn("byte")) + method = isNullableType ? getConvertByte : getByte; + if (bindProperyTypeName.IsContainsIn("int16")) + method = isNullableType ? getConvertInt16 : getInt16; + break; + case CSharpDataType.@bool: + if (bindProperyTypeName == "bool" || bindProperyTypeName == "boolean") + method = isNullableType ? getConvertBoolean : getBoolean; + break; + case CSharpDataType.@string: + CheckType(bind.StringThrow, bindProperyTypeName, validPropertyName, propertyName); + method = getString; + if (bindProperyTypeName == "guid") + { + method = isNullableType ? getConvertStringGuid : getStringGuid; + } + break; + case CSharpDataType.DateTime: + CheckType(bind.DateThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName == "datetime") + method = isNullableType ? getConvertDateTime : getDateTime; + if (bindProperyTypeName == "datetime"&&dbTypeName == "time") + method = isNullableType ? getConvertTime : getTime; + break; + case CSharpDataType.@decimal: + CheckType(bind.DecimalThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName == "decimal") + method = isNullableType ? getConvertDecimal : getDecimal; + break; + case CSharpDataType.@float: + case CSharpDataType.@double: + CheckType(bind.DoubleThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName.IsIn( "double", "single")&&dbTypeName!="real") + method = isNullableType ? getConvertDouble : getDouble; + else + method = isNullableType ? getConvertFloat : getFloat; + if (dbTypeName.Equals("float",StringComparison.CurrentCultureIgnoreCase) && isNullableType && bindProperyTypeName.Equals("single",StringComparison.CurrentCultureIgnoreCase)) { + method = getConvertDoubleToFloat; + } + break; + case CSharpDataType.Guid: + CheckType(bind.GuidThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName == "guid") + method = isNullableType ? getConvertGuid : getGuid; + break; + case CSharpDataType.@byte: + if (bindProperyTypeName == "byte") + method = isNullableType ? getConvertByte : getByte; + break; + case CSharpDataType.@enum: + method = isNullableType ? getConvertEnum_Null.MakeGenericMethod(bindPropertyType) : getEnum.MakeGenericMethod(bindPropertyType); + break; + case CSharpDataType.@short: + CheckType(bind.ShortThrow, bindProperyTypeName, validPropertyName, propertyName); + if (bindProperyTypeName == "int16" || bindProperyTypeName == "short") + method = isNullableType ? getConvertInt16 : getInt16; + break; + case CSharpDataType.@long: + if (bindProperyTypeName == "int64" || bindProperyTypeName == "long") + method = isNullableType ? getConvertInt64 : getInt64; + break; + case CSharpDataType.DateTimeOffset: + method = isNullableType ? getConvertdatetimeoffset : getdatetimeoffset; + if (bindProperyTypeName == "datetime") + method = isNullableType ? getConvertdatetimeoffsetDate : getdatetimeoffsetDate; + break; + default: + method = getValueMethod; + break; + } + if (method == null && bindPropertyType == UtilConstants.StringType) + { + method = getConvertString; + } + if (bindPropertyType == UtilConstants.ObjType) + { + method = getValueMethod; + } + if (method == null) + method = isNullableType ? getOtherNull.MakeGenericMethod(bindPropertyType) : getOther.MakeGenericMethod(bindPropertyType); + generator.Emit(OpCodes.Call, method); + if (method == getValueMethod) + { + generator.Emit(OpCodes.Unbox_Any, bindProperty.PropertyType); + } + #endregion + } + + private void CheckType(List invalidTypes, string bindProperyTypeName, string validPropertyType, string propertyName) + { + var isAny = invalidTypes.Contains(bindProperyTypeName); + if (isAny) + { + throw new SqlSugarException(string.Format("{0} can't convert {1} to {2}", propertyName, validPropertyType, bindProperyTypeName)); + } + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/DbBindProvider/IDataRecordExtensions.cs b/类库/SqlSugar/Abstract/DbBindProvider/IDataRecordExtensions.cs new file mode 100644 index 0000000..37ecd8d --- /dev/null +++ b/类库/SqlSugar/Abstract/DbBindProvider/IDataRecordExtensions.cs @@ -0,0 +1,370 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Data; +namespace SqlSugar +{ + public static partial class IDataRecordExtensions + { + + #region Common Extensions + public static Guid GetStringGuid(this IDataRecord dr, int i) + { + var result = Guid.Parse(dr.GetValue(i).ToString()); + return result; + } + + public static Guid? GetConvertStringGuid(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return Guid.Empty; + } + var result = Guid.Parse(dr.GetValue(i).ToString()); + return result; + } + + public static bool? GetConvertBoolean(this IDataRecord dr, int i) + { + var result = dr.GetBoolean(i); + return result; + } + + public static byte? GetConvertByte(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetByte(i); + return result; + } + + public static char? GetConvertChar(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetChar(i); + return result; + } + + public static DateTime? GetConvertDateTime(this IDataRecord dr, int i) + { + var result = dr.GetDateTime(i); + if (result == DateTime.MinValue) + { + return null; ; + } + return result; + } + public static DateTime? GetConvertTime(this IDataRecord dr, int i) + { + var result = dr.GetValue(i); + if (result == DBNull.Value) + { + return null; ; + } + return Convert.ToDateTime(result.ToString()); + } + public static DateTime GetTime(this IDataRecord dr, int i) + { + return Convert.ToDateTime(dr.GetValue(i).ToString()); + } + + public static decimal? GetConvertDecimal(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetDecimal(i); + return result; + } + + + public static double? GetConvertDouble(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetDouble(i); + return result; + } + + + public static float? GetConvertDoubleToFloat(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetDouble(i); + return Convert.ToSingle(result); + } + + + public static Guid? GetConvertGuid(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetGuid(i); + return result; + } + + public static short? GetConvertInt16(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetInt16(i); + return result; + } + + public static Int32? GetConvertInt32(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetInt32(i); + return result; + } + + public static long? GetConvetInt64(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetInt64(i); + return result; + } + + public static float? GetConvertFloat(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = dr.GetFloat(i); + return result; + } + + public static DateTime GetdatetimeoffsetDate(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return DateTime.MinValue; + } + var offsetValue = (DateTimeOffset)dr.GetValue(i); + var result = offsetValue.DateTime; + return result; + } + + public static DateTime? GetConvertdatetimeoffsetDate(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return DateTime.MinValue; + } + var offsetValue = (DateTimeOffset)dr.GetValue(i); + var result = offsetValue.DateTime; + return result; + } + + public static DateTimeOffset Getdatetimeoffset(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return default(DateTimeOffset); + } + var result = (DateTimeOffset)dr.GetValue(i); + return result; + } + + public static DateTimeOffset? GetConvertdatetimeoffset(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return default(DateTimeOffset); + } + var result = (DateTimeOffset)dr.GetValue(i); + return result; + } + + + public static string GetConvertString(this IDataRecord dr, int i) + { + if (dr.IsDBNull(i)) + { + return null; + } + var result = Convert.ToString(dr.GetValue(i)); + return result; + } + + public static Nullable GetOtherNull(this IDataReader dr, int i) where T : struct + { + if (dr.IsDBNull(i)) + { + return null; + } + return (T)Convert.ChangeType(dr.GetValue(i), typeof(T)); + + } + + public static T GetOther(this IDataReader dr, int i) + { + return (T)Convert.ChangeType(dr.GetValue(i), typeof(T)); + } + + public static Nullable GetConvertEnum_Null(this IDataReader dr, int i) where T : struct + { + if (dr.IsDBNull(i)) + { + return null; + } + object value = dr.GetValue(i); + T t = (T)Enum.ToObject(typeof(T), value); + return t; + } + + public static T GetEnum(this IDataReader dr, int i) where T : struct + { + object value = dr.GetValue(i); + T t = (T)Enum.ToObject(typeof(T), value); + return t; + } + + public static object GetEntity(this IDataReader dr, SqlSugarClient context) + { + return null; + } + + #endregion + + #region Sqlite Extensions + public static Nullable GetSqliteTypeNull(this IDataReader dr, int i) where T : struct + { + var type = UtilMethods.GetUnderType(typeof(T)); + if (dr.IsDBNull(i)) + { + return null; + } + return SqliteTypeConvert(dr, i, type); + } + + public static T GetSqliteType(this IDataReader dr, int i) where T : struct + { + var type = typeof(T); + return SqliteTypeConvert(dr, i, type); + } + + private static T SqliteTypeConvert(IDataReader dr, int i, Type type) where T : struct + { + if (type.IsIn(UtilConstants.IntType)) + { + try + { + return (T)((object)(dr.GetInt32(i))); + } + catch (Exception) + { + return (T)Convert.ChangeType(0, type); + } + } + else if (type == UtilConstants.DateType) + { + try + { + return (T)Convert.ChangeType(Convert.ToDateTime(dr.GetString(i)), type); + } + catch (Exception) + { + + return (T)Convert.ChangeType(new DateTime(), type); + } + + } + else if (type == UtilConstants.DecType) + { + try + { + return (T)Convert.ChangeType(dr.GetDecimal(i), type); + } + catch (Exception) + { + return (T)Convert.ChangeType(0m, type); + } + } + else if (type == UtilConstants.DobType) + { + try + { + return (T)Convert.ChangeType(dr.GetDouble(i), type); + } + catch (Exception) + { + return (T)Convert.ChangeType(0d, type); + } + + } + else if (type == UtilConstants.BoolType) + { + try + { + return (T)Convert.ChangeType(dr.GetBoolean(i), type); + } + catch (Exception) + { + return (T)Convert.ChangeType(false, type); + } + + } + else if (type == UtilConstants.LongType) + { + try + { + return (T)Convert.ChangeType(dr.GetInt64(i), type); + } + catch (Exception) + { + return (T)Convert.ChangeType(0, type); + } + } + else if (type == UtilConstants.GuidType) + { + string guidString = dr.GetString(i); + string changeValue = guidString.IsNullOrEmpty() ? Guid.Empty.ToString() : guidString; + return (T)Convert.ChangeType(Guid.Parse(changeValue), type); + } + else if (type == UtilConstants.StringType) + { + try + { + var temp = dr.GetString(i); + if (temp == null) return (T)Convert.ChangeType(string.Empty, type); + return (T)Convert.ChangeType(temp, type); + } + catch (Exception) + { + + return (T)Convert.ChangeType("", type); + } + + } + else + { + return (T)Convert.ChangeType((dr.GetString(i)), type); + } + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/DbFirstProvider/DbFirstProvider.cs b/类库/SqlSugar/Abstract/DbFirstProvider/DbFirstProvider.cs new file mode 100644 index 0000000..59e05b4 --- /dev/null +++ b/类库/SqlSugar/Abstract/DbFirstProvider/DbFirstProvider.cs @@ -0,0 +1,390 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public abstract partial class DbFirstProvider : IDbFirst + { + public virtual SqlSugarClient Context { get; set; } + private string ClassTemplate { get; set; } + private string ClassDescriptionTemplate { get; set; } + private string PropertyTemplate { get; set; } + private string PropertyDescriptionTemplate { get; set; } + private string ConstructorTemplate { get; set; } + private string UsingTemplate { get; set; } + private string Namespace { get; set; } + private bool IsAttribute { get; set; } + private bool IsDefaultValue { get; set; } + private ISqlBuilder SqlBuilder + { + get + { + return InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + } + } + private List TableInfoList { get; set; } + + public DbFirstProvider() + { + this.ClassTemplate = DbFirstTemplate.ClassTemplate; + this.ClassDescriptionTemplate = DbFirstTemplate.ClassDescriptionTemplate; + this.PropertyTemplate = DbFirstTemplate.PropertyTemplate; + this.PropertyDescriptionTemplate = DbFirstTemplate.PropertyDescriptionTemplate; + this.ConstructorTemplate = DbFirstTemplate.ConstructorTemplate; + this.UsingTemplate = DbFirstTemplate.UsingTemplate; + } + + public void Init() + { + this.Context.Utilities.RemoveCacheAll(); + if (!this.Context.DbMaintenance.IsAnySystemTablePermissions()) + { + Check.Exception(true, "Dbfirst and Codefirst requires system table permissions"); + } + this.TableInfoList = this.Context.Utilities.TranslateCopy(this.Context.DbMaintenance.GetTableInfoList()); + var viewList = this.Context.Utilities.TranslateCopy(this.Context.DbMaintenance.GetViewInfoList()); + if (viewList.HasValue()) + { + this.TableInfoList.AddRange(viewList); + } + } + + #region Setting Template + public IDbFirst SettingClassDescriptionTemplate(Func func) + { + this.ClassDescriptionTemplate = func(this.ClassDescriptionTemplate); + return this; + } + + public IDbFirst SettingClassTemplate(Func func) + { + this.ClassTemplate = func(this.ClassTemplate); + return this; + } + + public IDbFirst SettingConstructorTemplate(Func func) + { + this.ConstructorTemplate = func(this.ConstructorTemplate); + return this; + } + + public IDbFirst SettingPropertyDescriptionTemplate(Func func) + { + this.PropertyDescriptionTemplate = func(this.PropertyDescriptionTemplate); + return this; + } + + public IDbFirst SettingNamespaceTemplate(Func func) + { + this.UsingTemplate = func(this.UsingTemplate); + return this; + } + + public IDbFirst SettingPropertyTemplate(Func func) + { + this.PropertyTemplate = func(this.PropertyTemplate); + return this; + } + #endregion + + #region Setting Content + public IDbFirst IsCreateAttribute(bool isCreateAttribute = true) + { + this.IsAttribute = isCreateAttribute; + return this; + } + public IDbFirst IsCreateDefaultValue(bool isCreateDefaultValue = true) + { + this.IsDefaultValue = isCreateDefaultValue; + return this; + } + #endregion + + #region Where + public IDbFirst Where(DbObjectType dbObjectType) + { + if (dbObjectType != DbObjectType.All) + this.TableInfoList = this.TableInfoList.Where(it => it.DbObjectType == dbObjectType).ToList(); + return this; + } + + public IDbFirst Where(Func func) + { + this.TableInfoList = this.TableInfoList.Where(it => func(it.Name)).ToList(); + return this; + } + + public IDbFirst Where(params string[] objectNames) + { + if (objectNames.HasValue()) + { + this.TableInfoList = this.TableInfoList.Where(it => objectNames.Select(x=>x.ToLower()).Contains(it.Name.ToLower())).ToList(); + } + return this; + } + #endregion + + #region Core + public Dictionary ToClassStringList(string nameSpace = "Models") + { + this.Namespace = nameSpace; + Dictionary result = new Dictionary(); + if (this.TableInfoList.HasValue()) + { + foreach (var tableInfo in this.TableInfoList) + { + try + { + string classText = null; + string className = tableInfo.Name; + classText = GetClassString(tableInfo, ref className); + result.Remove(className); + result.Add(className, classText); + } + catch (Exception ex) + { + Check.Exception(true, "Table '{0}' error,You can filter it with Db.DbFirst.Where(name=>name!=\"{0}\" ) \r\n Error message:{1}", tableInfo.Name, ex.Message); + } + } + } + return result; + } + + internal string GetClassString(DbTableInfo tableInfo, ref string className) + { + string classText; + var columns = this.Context.DbMaintenance.GetColumnInfosByTableName(tableInfo.Name); + if (this.Context.IgnoreColumns.HasValue()) + { + var entityName = this.Context.EntityMaintenance.GetEntityName(tableInfo.Name); + columns = columns.Where(c => + !this.Context.IgnoreColumns.Any(ig => ig.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase) && c.DbColumnName == ig.PropertyName) + ).ToList(); + } + classText = this.ClassTemplate; + string ConstructorText = IsDefaultValue ? this.ConstructorTemplate : null; + if (this.Context.MappingTables.HasValue()) + { + var mappingInfo = this.Context.MappingTables.FirstOrDefault(it => it.DbTableName.Equals(tableInfo.Name, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo.HasValue()) + { + className = mappingInfo.EntityName; + } + if (mappingInfo != null) + { + classText = classText.Replace(DbFirstTemplate.KeyClassName, mappingInfo.EntityName); + } + } + classText = classText.Replace(DbFirstTemplate.KeyClassName, className); + classText = classText.Replace(DbFirstTemplate.KeyNamespace, this.Namespace); + classText = classText.Replace(DbFirstTemplate.KeyUsing, IsAttribute ? (this.UsingTemplate + "using " + UtilConstants.AssemblyName + ";\r\n") : this.UsingTemplate); + classText = classText.Replace(DbFirstTemplate.KeyClassDescription, this.ClassDescriptionTemplate.Replace(DbFirstTemplate.KeyClassDescription, tableInfo.Description + "\r\n")); + classText = classText.Replace(DbFirstTemplate.KeySugarTable, IsAttribute ? string.Format(DbFirstTemplate.ValueSugarTable, tableInfo.Name) : null); + if (columns.HasValue()) + { + foreach (var item in columns) + { + var isLast = columns.Last() == item; + var index = columns.IndexOf(item); + string PropertyText = this.PropertyTemplate; + string PropertyDescriptionText = this.PropertyDescriptionTemplate; + string propertyName = GetPropertyName(item); + string propertyTypeName = GetPropertyTypeName(item); + PropertyText = GetPropertyText(item, PropertyText); + PropertyDescriptionText = GetPropertyDescriptionText(item, PropertyDescriptionText); + PropertyText = PropertyDescriptionText + PropertyText; + classText = classText.Replace(DbFirstTemplate.KeyPropertyName, PropertyText + (isLast ? "" : ("\r\n" + DbFirstTemplate.KeyPropertyName))); + if (ConstructorText.HasValue() && item.DefaultValue != null) + { + var hasDefaultValue = columns.Skip(index + 1).Any(it => it.DefaultValue.HasValue()); + ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyPropertyName, propertyName); + ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyDefaultValue, GetPropertyTypeConvert(item)) + (!hasDefaultValue ? "" : this.ConstructorTemplate); + } + } + } + if (!columns.Any(it => it.DefaultValue != null)) + { + ConstructorText = null; + } + classText = classText.Replace(DbFirstTemplate.KeyConstructor, ConstructorText); + classText = classText.Replace(DbFirstTemplate.KeyPropertyName, null); + return classText; + } + internal string GetClassString(List columns, ref string className) + { + string classText = this.ClassTemplate; + string ConstructorText = IsDefaultValue ? this.ConstructorTemplate : null; + classText = classText.Replace(DbFirstTemplate.KeyClassName, className); + classText = classText.Replace(DbFirstTemplate.KeyNamespace, this.Namespace); + classText = classText.Replace(DbFirstTemplate.KeyUsing, IsAttribute ? (this.UsingTemplate + "using " + UtilConstants.AssemblyName + ";\r\n") : this.UsingTemplate); + classText = classText.Replace(DbFirstTemplate.KeyClassDescription, this.ClassDescriptionTemplate.Replace(DbFirstTemplate.KeyClassDescription,"\r\n")); + classText = classText.Replace(DbFirstTemplate.KeySugarTable, IsAttribute ? string.Format(DbFirstTemplate.ValueSugarTable, className) : null); + if (columns.HasValue()) + { + foreach (var item in columns) + { + var isLast = columns.Last() == item; + var index = columns.IndexOf(item); + string PropertyText = this.PropertyTemplate; + string PropertyDescriptionText = this.PropertyDescriptionTemplate; + string propertyName = GetPropertyName(item); + string propertyTypeName =item.PropertyName; + PropertyText = GetPropertyText(item, PropertyText); + PropertyDescriptionText = GetPropertyDescriptionText(item, PropertyDescriptionText); + PropertyText = PropertyDescriptionText + PropertyText; + classText = classText.Replace(DbFirstTemplate.KeyPropertyName, PropertyText + (isLast ? "" : ("\r\n" + DbFirstTemplate.KeyPropertyName))); + if (ConstructorText.HasValue() && item.DefaultValue != null) + { + var hasDefaultValue = columns.Skip(index + 1).Any(it => it.DefaultValue.HasValue()); + ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyPropertyName, propertyName); + ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyDefaultValue, GetPropertyTypeConvert(item)) + (!hasDefaultValue ? "" : this.ConstructorTemplate); + } + } + } + if (!columns.Any(it => it.DefaultValue != null)) + { + ConstructorText = null; + } + classText = classText.Replace(DbFirstTemplate.KeyConstructor, ConstructorText); + classText = classText.Replace(DbFirstTemplate.KeyPropertyName, null); + return classText; + } + public void CreateClassFile(string directoryPath, string nameSpace = "Models") + { + var seChar= Path.DirectorySeparatorChar.ToString(); + Check.ArgumentNullException(directoryPath, "directoryPath can't null"); + var classStringList = ToClassStringList(nameSpace); + if (classStringList.IsValuable()) + { + foreach (var item in classStringList) + { + var filePath = directoryPath.TrimEnd('\\').TrimEnd('/') + string.Format(seChar + "{0}.cs", item.Key); + FileHelper.CreateFile(filePath, item.Value, Encoding.UTF8); + } + } + } + #endregion + + #region Private methods + private string GetProertypeDefaultValue(DbColumnInfo item) + { + var result = item.DefaultValue; + if (result == null) return null; + if (Regex.IsMatch(result, @"^\(\'(.+)\'\)$")) + { + result = Regex.Match(result, @"^\(\'(.+)\'\)$").Groups[1].Value; + } + if (Regex.IsMatch(result, @"^\(\((.+)\)\)$")) + { + result = Regex.Match(result, @"^\(\((.+)\)\)$").Groups[1].Value; + } + if (Regex.IsMatch(result, @"^\((.+)\)$")) + { + result = Regex.Match(result, @"^\((.+)\)$").Groups[1].Value; + } + if (result.Equals(this.SqlBuilder.SqlDateNow, StringComparison.CurrentCultureIgnoreCase)) + { + result = "DateTime.Now"; + } + result = result.Replace("\r", "\t").Replace("\n", "\t"); + result = result.IsIn("''","\"\"") ? string.Empty : result; + return result; + } + private string GetPropertyText(DbColumnInfo item, string PropertyText) + { + string SugarColumnText = DbFirstTemplate.ValueSugarCoulmn; + var propertyName = GetPropertyName(item); + var isMappingColumn = propertyName != item.DbColumnName; + var hasSugarColumn = item.IsPrimarykey == true || item.IsIdentity == true || isMappingColumn; + if (hasSugarColumn && this.IsAttribute) + { + List joinList = new List(); + if (item.IsPrimarykey) + { + joinList.Add("IsPrimaryKey=true"); + } + if (item.IsIdentity) + { + joinList.Add("IsIdentity=true"); + } + if (isMappingColumn) + { + joinList.Add("ColumnName=\"" + item.DbColumnName + "\""); + } + SugarColumnText = string.Format(SugarColumnText, string.Join(",", joinList)); + } + else + { + SugarColumnText = null; + } + string typeString = GetPropertyTypeName(item); + PropertyText = PropertyText.Replace(DbFirstTemplate.KeySugarColumn, SugarColumnText); + PropertyText = PropertyText.Replace(DbFirstTemplate.KeyPropertyType, typeString); + PropertyText = PropertyText.Replace(DbFirstTemplate.KeyPropertyName, propertyName); + return PropertyText; + } + private string GetEnityName(DbColumnInfo item) + { + var mappingInfo = this.Context.MappingTables.FirstOrDefault(it => it.DbTableName.Equals(item.TableName, StringComparison.CurrentCultureIgnoreCase)); + return mappingInfo == null ? item.TableName : mappingInfo.EntityName; + } + private string GetPropertyName(DbColumnInfo item) + { + if (this.Context.MappingColumns.HasValue()) + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.DbColumnName == item.DbColumnName && it.EntityName == GetEnityName(item)); + return mappingInfo == null ? item.DbColumnName : mappingInfo.PropertyName; + } + else + { + return item.DbColumnName; + } + } + private string GetPropertyTypeName(DbColumnInfo item) + { + string result =item.PropertyType!=null?item.PropertyType.Name:this.Context.Ado.DbBind.GetPropertyTypeName(item.DataType); + if (result != "string" && result != "byte[]" && result != "object" && item.IsNullable) + { + result += "?"; + } + if (result == "Int32") { + result = "int"; + } + if (result == "String") + { + result = "string"; + } + return result; + } + private string GetPropertyTypeConvert(DbColumnInfo item) + { + var convertString = GetProertypeDefaultValue(item); + if (convertString == "DateTime.Now" || convertString == null) + return convertString; + if (item.DataType == "bit") + return (convertString == "1" || convertString.Equals("true",StringComparison.CurrentCultureIgnoreCase)).ToString().ToLower(); + string result = this.Context.Ado.DbBind.GetConvertString(item.DataType) + "(\"" + convertString + "\")"; + return result; + } + private string GetPropertyDescriptionText(DbColumnInfo item, string propertyDescriptionText) + { + propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyPropertyDescription, GetColumnDescription(item.ColumnDescription)); + propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyDefaultValue, GetProertypeDefaultValue(item)); + propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyIsNullable, item.IsNullable.ObjToString()); + return propertyDescriptionText; + } + private string GetColumnDescription(string columnDescription) + { + if (columnDescription == null) return columnDescription; + columnDescription = columnDescription.Replace("\r", "\t"); + columnDescription = columnDescription.Replace("\n", "\t"); + columnDescription = Regex.Replace(columnDescription, "\t{2,}", "\t"); + return columnDescription; + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/DbFirstProvider/DbFirstTemplate.cs b/类库/SqlSugar/Abstract/DbFirstProvider/DbFirstTemplate.cs new file mode 100644 index 0000000..ab7fdd2 --- /dev/null +++ b/类库/SqlSugar/Abstract/DbFirstProvider/DbFirstTemplate.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DbFirstTemplate + { + #region Template + public static string ClassTemplate = "{using}\r\n" + + "namespace {Namespace}\r\n" + + "{\r\n" + + "{ClassDescription}{SugarTable}\r\n" + + ClassSpace+ "public partial class {ClassName}\r\n" + + ClassSpace + "{\r\n" + + PropertySpace + "public {ClassName}(){\r\n\r\n" + + "{Constructor}\r\n" + + PropertySpace + "}\r\n" + + "{PropertyName}\r\n" + + ClassSpace + "}\r\n" + + "}\r\n"; + public static string ClassDescriptionTemplate = + ClassSpace + "///\r\n" + + ClassSpace + "///{ClassDescription}" + + ClassSpace + "///"; + + public static string PropertyTemplate = PropertySpace + "{SugarColumn}\r\n" + + PropertySpace + "public {PropertyType} {PropertyName} {get;set;}\r\n"; + + public static string PropertyDescriptionTemplate = + PropertySpace + "/// \r\n" + + PropertySpace + "/// Desc:{PropertyDescription}\r\n" + + PropertySpace + "/// Default:{DefaultValue}\r\n" + + PropertySpace + "/// Nullable:{IsNullable}\r\n" + + PropertySpace + "/// "; + + public static string ConstructorTemplate = PropertySpace + " this.{PropertyName} ={DefaultValue};\r\n"; + + public static string UsingTemplate = "using System;\r\n" + + "using System.Linq;\r\n" + + "using System.Text;" + "\r\n"; + #endregion + + #region Replace Key + public const string KeyUsing = "{using}"; + public const string KeyNamespace = "{Namespace}"; + public const string KeyClassName = "{ClassName}"; + public const string KeyIsNullable = "{IsNullable}"; + public const string KeySugarTable = "{SugarTable}"; + public const string KeyConstructor = "{Constructor}"; + public const string KeySugarColumn = "{SugarColumn}"; + public const string KeyPropertyType = "{PropertyType}"; + public const string KeyPropertyName = "{PropertyName}"; + public const string KeyDefaultValue = "{DefaultValue}"; + public const string KeyClassDescription = "{ClassDescription}"; + public const string KeyPropertyDescription = "{PropertyDescription}"; + #endregion + + #region Replace Value + public const string ValueSugarTable = "\r\n"+ClassSpace+"[SugarTable(\"{0}\")]"; + public const string ValueSugarCoulmn = "\r\n"+PropertySpace+"[SugarColumn({0})]"; + #endregion + + #region Space + public const string PropertySpace = " "; + public const string ClassSpace = " "; + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/DbMaintenanceProvider/Methods.cs b/类库/SqlSugar/Abstract/DbMaintenanceProvider/Methods.cs new file mode 100644 index 0000000..29cf211 --- /dev/null +++ b/类库/SqlSugar/Abstract/DbMaintenanceProvider/Methods.cs @@ -0,0 +1,386 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public abstract partial class DbMaintenanceProvider : IDbMaintenance + { + #region DML + public virtual List GetViewInfoList(bool isCache = true) + { + string cacheKey = "DbMaintenanceProvider.GetViewInfoList"; + cacheKey = GetCacheKey(cacheKey); + var result = new List(); + if (isCache) + result = GetListOrCache(cacheKey, this.GetViewInfoListSql); + else + result = this.Context.Ado.SqlQuery(this.GetViewInfoListSql); + foreach (var item in result) + { + item.DbObjectType = DbObjectType.View; + } + return result; + } + public virtual List GetTableInfoList(bool isCache = true) + { + string cacheKey = "DbMaintenanceProvider.GetTableInfoList"; + cacheKey = GetCacheKey(cacheKey); + var result = new List(); + if (isCache) + result = GetListOrCache(cacheKey, this.GetTableInfoListSql); + else + result = this.Context.Ado.SqlQuery(this.GetTableInfoListSql); + foreach (var item in result) + { + item.DbObjectType = DbObjectType.Table; + } + return result; + } + public virtual List GetColumnInfosByTableName(string tableName, bool isCache = true) + { + if (string.IsNullOrEmpty(tableName)) return new List(); + string cacheKey = "DbMaintenanceProvider.GetColumnInfosByTableName." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + var sql = string.Format(this.GetColumnInfosByTableNameSql, tableName); + if (isCache) + return GetListOrCache(cacheKey, sql).GroupBy(it => it.DbColumnName).Select(it => it.First()).ToList(); + else + return this.Context.Ado.SqlQuery(sql).GroupBy(it => it.DbColumnName).Select(it => it.First()).ToList(); + + } + public virtual List GetIsIdentities(string tableName) + { + string cacheKey = "DbMaintenanceProvider.GetIsIdentities" + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => + { + var result = GetColumnInfosByTableName(tableName).Where(it => it.IsIdentity).ToList(); + return result.Select(it => it.DbColumnName).ToList(); + }); + } + public virtual List GetPrimaries(string tableName) + { + string cacheKey = "DbMaintenanceProvider.GetPrimaries" + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, () => + { + var result = GetColumnInfosByTableName(tableName).Where(it => it.IsPrimarykey).ToList(); + return result.Select(it => it.DbColumnName).ToList(); + }); + } + #endregion + + #region Check + public virtual bool IsAnyTable(string tableName, bool isCache = true) + { + tableName = this.SqlBuilder.GetNoTranslationColumnName(tableName); + var tables = GetTableInfoList(isCache); + if (tables == null) return false; + else return tables.Any(it => it.Name.Equals(tableName, StringComparison.CurrentCultureIgnoreCase)); + } + public virtual bool IsAnyColumn(string tableName, string columnName) + { + columnName = this.SqlBuilder.GetNoTranslationColumnName(columnName); + tableName = this.SqlBuilder.GetNoTranslationColumnName(tableName); + var isAny = IsAnyTable(tableName); + Check.Exception(!isAny, string.Format("Table {0} does not exist", tableName)); + var columns = GetColumnInfosByTableName(tableName); + if (columns.IsNullOrEmpty()) return false; + return columns.Any(it => it.DbColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase)); + } + public virtual bool IsPrimaryKey(string tableName, string columnName) + { + columnName = this.SqlBuilder.GetNoTranslationColumnName(columnName); + var isAny = IsAnyTable(tableName); + Check.Exception(!isAny, string.Format("Table {0} does not exist", tableName)); + var columns = GetColumnInfosByTableName(tableName); + if (columns.IsNullOrEmpty()) return false; + return columns.Any(it => it.IsPrimarykey = true && it.DbColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase)); + } + public virtual bool IsIdentity(string tableName, string columnName) + { + columnName = this.SqlBuilder.GetNoTranslationColumnName(columnName); + var isAny = IsAnyTable(tableName); + Check.Exception(!isAny, string.Format("Table {0} does not exist", tableName)); + var columns = GetColumnInfosByTableName(tableName); + if (columns.IsNullOrEmpty()) return false; + return columns.Any(it => it.IsIdentity = true && it.DbColumnName.Equals(columnName, StringComparison.CurrentCultureIgnoreCase)); + } + public virtual bool IsAnyConstraint(string constraintName) + { + return this.Context.Ado.GetInt("select object_id('" + constraintName + "')") > 0; + } + public virtual bool IsAnySystemTablePermissions() + { + this.Context.Ado.CheckConnection(); + string sql = this.CheckSystemTablePermissionsSql; + try + { + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + this.Context.Ado.ExecuteCommand(sql); + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + return true; + } + catch + { + return false; + } + } + #endregion + + #region DDL + public virtual bool AddPrimaryKey(string tableName, string columnName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + columnName = this.SqlBuilder.GetTranslationTableName(columnName); + string sql = string.Format(this.AddPrimaryKeySql, tableName, string.Format("PK_{0}_{1}", this.SqlBuilder.GetNoTranslationColumnName(tableName), this.SqlBuilder.GetNoTranslationColumnName(columnName)), columnName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + + public bool AddPrimaryKeys(string tableName, string[] columnNames) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + var columnName = string.Join(",", columnNames); + string sql = string.Format(this.AddPrimaryKeySql, tableName, string.Format("PK_{0}_{1}", this.SqlBuilder.GetNoTranslationColumnName(columnNames.First()), this.SqlBuilder.GetNoTranslationColumnName(columnNames.First())), columnName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool AddColumn(string tableName, DbColumnInfo columnInfo) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string sql = GetAddColumnSql(tableName, columnInfo); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool UpdateColumn(string tableName, DbColumnInfo column) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string sql = GetUpdateColumnSql(tableName, column); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public abstract bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true); + public virtual bool DropTable(string tableName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + this.Context.Ado.ExecuteCommand(string.Format(this.DropTableSql, tableName)); + return true; + } + public virtual bool DropColumn(string tableName, string columnName) + { + columnName = this.SqlBuilder.GetTranslationColumnName(columnName); + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + this.Context.Ado.ExecuteCommand(string.Format(this.DropColumnToTableSql, tableName, columnName)); + return true; + } + public virtual bool DropConstraint(string tableName, string constraintName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string sql = string.Format(this.DropConstraintSql, tableName, constraintName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool TruncateTable(string tableName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + this.Context.Ado.ExecuteCommand(string.Format(this.TruncateTableSql, tableName)); + return true; + } + public virtual bool BackupDataBase(string databaseName, string fullFileName) + { + var directory = FileHelper.GetDirectoryFromFilePath(fullFileName); + if (!FileHelper.IsExistDirectory(directory)) + { + FileHelper.CreateDirectory(directory); + } + this.Context.Ado.ExecuteCommand(string.Format(this.BackupDataBaseSql, databaseName, fullFileName)); + return true; + } + public virtual bool BackupTable(string oldTableName, string newTableName, int maxBackupDataRows = int.MaxValue) + { + oldTableName = this.SqlBuilder.GetTranslationTableName(oldTableName); + newTableName = this.SqlBuilder.GetTranslationTableName(newTableName); + string sql = string.Format(this.BackupTableSql, maxBackupDataRows, newTableName, oldTableName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool RenameColumn(string tableName, string oldColumnName, string newColumnName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + oldColumnName = this.SqlBuilder.GetTranslationColumnName(oldColumnName); + newColumnName = this.SqlBuilder.GetTranslationColumnName(newColumnName); + string sql = string.Format(this.RenameColumnSql, tableName, oldColumnName, newColumnName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool AddColumnRemark(string columnName, string tableName, string description) + { + string sql = string.Format(this.AddColumnRemarkSql, columnName, tableName, description); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool DeleteColumnRemark(string columnName, string tableName) + { + string sql = string.Format(this.DeleteColumnRemarkSql, columnName, tableName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool IsAnyColumnRemark(string columnName, string tableName) + { + string sql = string.Format(this.IsAnyColumnRemarkSql, columnName, tableName); + var dt=this.Context.Ado.GetDataTable(sql); + return dt.Rows!=null&&dt.Rows.Count>0; + } + public virtual bool AddTableRemark(string tableName, string description) + { + string sql = string.Format(this.AddTableRemarkSql, tableName, description); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool DeleteTableRemark(string tableName) + { + string sql = string.Format(this.DeleteTableRemarkSql,tableName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public virtual bool IsAnyTableRemark(string tableName) + { + string sql = string.Format(this.IsAnyTableRemarkSql, tableName); + var dt=this.Context.Ado.GetDataTable(sql); + return dt.Rows != null && dt.Rows.Count > 0; + } + public virtual bool AddRemark(EntityInfo entity) + { + var db = this.Context; + var columns = entity.Columns.Where(it => it.IsIgnore == false).ToList(); + + foreach (var item in columns) + { + if (item.ColumnDescription != null) + { + //column remak + if (db.DbMaintenance.IsAnyColumnRemark(item.DbColumnName, item.DbTableName)) + { + db.DbMaintenance.DeleteColumnRemark(item.DbColumnName, item.DbTableName); + db.DbMaintenance.AddColumnRemark(item.DbColumnName, item.DbTableName, item.ColumnDescription); + } + else + { + db.DbMaintenance.AddColumnRemark(item.DbColumnName, item.DbTableName, item.ColumnDescription); + } + } + } + + //table remak + if (entity.TableDescription != null) + { + if (db.DbMaintenance.IsAnyTableRemark(entity.DbTableName)) + { + db.DbMaintenance.DeleteTableRemark(entity.DbTableName); + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + else + { + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + } + return true; + } + + public virtual bool RenameTable(string oldTableName, string newTableName) + { + string sql = string.Format(this.RenameTableSql, oldTableName,newTableName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + #endregion + + #region Private + private List GetListOrCache(string cacheKey, string sql) + { + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + var isEnableLogEvent = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + var result = this.Context.Ado.SqlQuery(sql); + this.Context.Ado.IsEnableLogEvent = isEnableLogEvent; + return result; + }); + } + protected virtual string GetCreateTableSql(string tableName, List columns) + { + List columnArray = new List(); + Check.Exception(columns.IsNullOrEmpty(), "No columns found "); + foreach (var item in columns) + { + string columnName = this.SqlBuilder.GetTranslationTableName(item.DbColumnName); + string dataType = item.DataType; + string dataSize = GetSize(item); + string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string identity = item.IsIdentity ? this.CreateTableIdentity : null; + string addItem = string.Format(this.CreateTableColumn, columnName, dataType, dataSize, nullType, primaryKey, identity); + columnArray.Add(addItem); + } + string tableString = string.Format(this.CreateTableSql, this.SqlBuilder.GetTranslationTableName(tableName), string.Join(",\r\n", columnArray)); + return tableString; + } + protected virtual string GetAddColumnSql(string tableName, DbColumnInfo columnInfo) + { + string columnName = this.SqlBuilder.GetTranslationColumnName(columnInfo.DbColumnName); + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string dataType = columnInfo.DataType; + string dataSize = GetSize(columnInfo); + string nullType = columnInfo.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string identity = null; + string result = string.Format(this.AddColumnToTableSql, tableName, columnName, dataType, dataSize, nullType, primaryKey, identity); + return result; + } + protected virtual string GetUpdateColumnSql(string tableName, DbColumnInfo columnInfo) + { + string columnName = this.SqlBuilder.GetTranslationTableName(columnInfo.DbColumnName); + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string dataSize = GetSize(columnInfo); + string dataType = columnInfo.DataType; + string nullType = columnInfo.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string identity = null; + string result = string.Format(this.AlterColumnToTableSql, tableName, columnName, dataType, dataSize, nullType, primaryKey, identity); + return result; + } + protected virtual string GetCacheKey(string cacheKey) + { + return this.Context.CurrentConnectionConfig.DbType + "." + this.Context.Ado.Connection.Database + "." + cacheKey; + } + protected virtual string GetSize(DbColumnInfo item) + { + string dataSize = null; + var isMax = item.Length > 4000 || item.Length == -1; + if (isMax) + { + dataSize = item.Length > 0 ? string.Format("({0})", "max") : null; + } + else if (item.Length == 0 && item.DecimalDigits > 0) + { + item.Length = 10; + dataSize = string.Format("({0},{1})", item.Length, item.DecimalDigits); + } + else if (item.Length > 0 && item.DecimalDigits == 0) + { + dataSize = item.Length > 0 ? string.Format("({0})", item.Length) : null; + } + else if (item.Length > 0 && item.DecimalDigits > 0) + { + dataSize = item.Length > 0 ? string.Format("({0},{1})", item.Length, item.DecimalDigits) : null; + } + return dataSize; + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/DbMaintenanceProvider/Properties.cs b/类库/SqlSugar/Abstract/DbMaintenanceProvider/Properties.cs new file mode 100644 index 0000000..cd89c6f --- /dev/null +++ b/类库/SqlSugar/Abstract/DbMaintenanceProvider/Properties.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public abstract partial class DbMaintenanceProvider : IDbMaintenance + { + #region Context + private ISqlBuilder _SqlBuilder; + public SqlSugarClient Context { get; set; } + public ISqlBuilder SqlBuilder + { + get + { + if (_SqlBuilder == null) + { + _SqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + _SqlBuilder.Context = this.Context; + } + return _SqlBuilder; + } + } + #endregion + + #region DML + protected abstract string GetViewInfoListSql { get; } + protected abstract string GetTableInfoListSql { get; } + protected abstract string GetColumnInfosByTableNameSql { get; } + #endregion + + #region DDL + protected abstract string AddColumnToTableSql { get; } + protected abstract string AlterColumnToTableSql { get; } + protected abstract string BackupDataBaseSql { get; } + protected abstract string CreateTableSql { get; } + protected abstract string CreateTableColumn { get; } + protected abstract string BackupTableSql { get; } + protected abstract string TruncateTableSql { get; } + protected abstract string DropTableSql { get; } + protected abstract string DropColumnToTableSql { get; } + protected abstract string DropConstraintSql { get; } + protected abstract string AddPrimaryKeySql { get; } + protected abstract string RenameColumnSql { get; } + protected abstract string AddColumnRemarkSql { get; } + protected abstract string DeleteColumnRemarkSql { get; } + protected abstract string IsAnyColumnRemarkSql { get; } + protected abstract string AddTableRemarkSql { get; } + protected abstract string DeleteTableRemarkSql { get; } + protected abstract string IsAnyTableRemarkSql { get; } + protected abstract string RenameTableSql { get; } + #endregion + + #region Check + protected abstract string CheckSystemTablePermissionsSql { get; } + #endregion + + #region Scattered + protected abstract string CreateTableNull { get; } + protected abstract string CreateTableNotNull { get; } + protected abstract string CreateTablePirmaryKey { get; } + protected abstract string CreateTableIdentity { get; } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/DeleteProvider/DeleteableProvider.cs b/类库/SqlSugar/Abstract/DeleteProvider/DeleteableProvider.cs new file mode 100644 index 0000000..2a8e40f --- /dev/null +++ b/类库/SqlSugar/Abstract/DeleteProvider/DeleteableProvider.cs @@ -0,0 +1,455 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class DeleteableProvider : IDeleteable where T : class, new() + { + public SqlSugarClient Context { get; set; } + public IAdo Db { get { return Context.Ado; } } + public ISqlBuilder SqlBuilder { get; set; } + public DeleteBuilder DeleteBuilder { get; set; } + public MappingTableList OldMappingTableList { get; set; } + public bool IsAs { get; set; } + public bool IsEnableDiffLogEvent { get; set; } + public DiffLogModel diffModel { get; set; } + public List tempPrimaryKeys { get; set; } + private Action RemoveCacheFunc { get; set; } + public EntityInfo EntityInfo + { + get + { + return this.Context.EntityMaintenance.GetEntityInfo(); + } + } + public int ExecuteCommand() + { + DeleteBuilder.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); + string sql = DeleteBuilder.ToSqlString(); + var paramters = DeleteBuilder.Parameters == null ? null : DeleteBuilder.Parameters.ToArray(); + RestoreMapping(); + AutoRemoveDataCache(); + Before(sql); + var result = Db.ExecuteCommand(sql, paramters); + After(sql); + return result; + } + + public bool ExecuteCommandHasChange() + { + return ExecuteCommand() > 0; + } + public Task ExecuteCommandAsync() + { + Task result = new Task(() => + { + IDeleteable asyncDeleteable = CopyDeleteable(); + return asyncDeleteable.ExecuteCommand(); + }); + TaskStart(result); + return result; + } + + public Task ExecuteCommandHasChangeAsync() + { + Task result = new Task(() => + { + IDeleteable asyncDeleteable = CopyDeleteable(); + return asyncDeleteable.ExecuteCommand() > 0; + }); + TaskStart(result); + return result; + } + public IDeleteable AS(string tableName) + { + var entityName = typeof(T).Name; + IsAs = true; + OldMappingTableList = this.Context.MappingTables; + this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); + if (this.Context.MappingTables.Any(it => it.EntityName == entityName)) + { + this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName); + } + this.Context.MappingTables.Add(entityName, tableName); + return this; ; + } + + public IDeleteable EnableDiffLogEvent(object businessData = null) + { + + diffModel = new DiffLogModel(); + this.IsEnableDiffLogEvent = true; + diffModel.BusinessData = businessData; + diffModel.DiffType = DiffType.delete; + return this; + } + + public IDeleteable Where(List deleteObjs) + { + if (deleteObjs == null || deleteObjs.Count() == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + string tableName = this.Context.EntityMaintenance.GetTableName(); + var primaryFields = this.GetPrimaryKeys(); + var isSinglePrimaryKey = primaryFields.Count == 1; + Check.Exception(primaryFields.IsNullOrEmpty(), string.Format("Table {0} with no primarykey", tableName)); + if (isSinglePrimaryKey) + { + List primaryKeyValues = new List(); + var primaryField = primaryFields.Single(); + foreach (var deleteObj in deleteObjs) + { + var entityPropertyName = this.Context.EntityMaintenance.GetPropertyName(primaryField); + var columnInfo = EntityInfo.Columns.Single(it => it.PropertyName.Equals(entityPropertyName, StringComparison.CurrentCultureIgnoreCase)); + var value = columnInfo.PropertyInfo.GetValue(deleteObj, null); + primaryKeyValues.Add(value); + } + if (primaryKeyValues.Count < 10000) + { + var inValueString = primaryKeyValues.ToArray().ToJoinSqlInVals(); + Where(string.Format(DeleteBuilder.WhereInTemplate, SqlBuilder.GetTranslationColumnName(primaryFields.Single()), inValueString)); + } + else + { + if (DeleteBuilder.BigDataInValues == null) + DeleteBuilder.BigDataInValues = new List(); + DeleteBuilder.BigDataInValues.AddRange(primaryKeyValues); + DeleteBuilder.BigDataFiled = primaryField; + } + } + else + { + StringBuilder whereInSql = new StringBuilder(); + foreach (var deleteObj in deleteObjs) + { + StringBuilder orString = new StringBuilder(); + var isFirst = deleteObjs.IndexOf(deleteObj) == 0; + if (!isFirst) + { + orString.Append(DeleteBuilder.WhereInOrTemplate + UtilConstants.Space); + } + int i = 0; + StringBuilder andString = new StringBuilder(); + foreach (var primaryField in primaryFields) + { + if (i != 0) + andString.Append(DeleteBuilder.WhereInAndTemplate + UtilConstants.Space); + var entityPropertyName = this.Context.EntityMaintenance.GetPropertyName(primaryField); + var columnInfo = EntityInfo.Columns.Single(it => it.PropertyName == entityPropertyName); + var entityValue = columnInfo.PropertyInfo.GetValue(deleteObj, null); + if (this.Context.CurrentConnectionConfig.DbType == DbType.Oracle) + { + andString.AppendFormat(DeleteBuilder.WhereInEqualTemplate, primaryField.ToUpper(), entityValue); + } + else + { + andString.AppendFormat(DeleteBuilder.WhereInEqualTemplate, primaryField, entityValue); + } + ++i; + } + orString.AppendFormat(DeleteBuilder.WhereInAreaTemplate, andString); + whereInSql.Append(orString); + } + Where(string.Format(DeleteBuilder.WhereInAreaTemplate, whereInSql.ToString())); + } + return this; + } + + public IDeleteable Where(Expression> expression) + { + var expResult = DeleteBuilder.GetExpressionValue(expression, ResolveExpressType.WhereSingle); + var whereString = expResult.GetResultString(); + if (expression.ToString().Contains("Subqueryable()")){ + whereString = whereString.Replace(this.SqlBuilder.GetTranslationColumnName(expression.Parameters.First().Name) + ".",this.SqlBuilder.GetTranslationTableName(this.EntityInfo.DbTableName) + "."); + } + DeleteBuilder.WhereInfos.Add(whereString); + return this; + } + + public IDeleteable Where(T deleteObj) + { + Check.Exception(GetPrimaryKeys().IsNullOrEmpty(), "Where(entity) Primary key required"); + Where(new List() { deleteObj }); + return this; + } + + public IDeleteable Where(string whereString, object parameters = null) + { + DeleteBuilder.WhereInfos.Add(whereString); + if (parameters != null) + { + if (DeleteBuilder.Parameters == null) + { + DeleteBuilder.Parameters = new List(); + } + DeleteBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + } + return this; + } + + public IDeleteable Where(string whereString, SugarParameter parameter) + { + DeleteBuilder.Parameters.Add(parameter); + return this; + } + public IDeleteable Where(string whereString, SugarParameter[] parameters) + { + DeleteBuilder.Parameters.AddRange(parameters); + return this; + } + public IDeleteable Where(string whereString, List parameters) + { + DeleteBuilder.Parameters.AddRange(parameters); + return this; + } + + public IDeleteable RemoveDataCache() + { + this.RemoveCacheFunc = () => + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + CacheSchemeMain.RemoveCache(cacheService, this.Context.EntityMaintenance.GetTableName()); + }; + return this; + } + + public IDeleteable In(List primaryKeyValues) + { + if (primaryKeyValues == null || primaryKeyValues.Count() == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + return In(primaryKeyValues.ToArray()); + } + + public IDeleteable In(PkType[] primaryKeyValues) + { + if (primaryKeyValues == null || primaryKeyValues.Count() == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + string tableName = this.Context.EntityMaintenance.GetTableName(); + string primaryField = null; + primaryField = GetPrimaryKeys().FirstOrDefault(); + Check.ArgumentNullException(primaryField, "Table " + tableName + " with no primarykey"); + if (primaryKeyValues.Length < 10000) + { + Where(string.Format(DeleteBuilder.WhereInTemplate, SqlBuilder.GetTranslationColumnName(primaryField), primaryKeyValues.ToJoinSqlInVals())); + } + else + { + if (DeleteBuilder.BigDataInValues == null) + DeleteBuilder.BigDataInValues = new List(); + DeleteBuilder.BigDataInValues.AddRange(primaryKeyValues.Select(it => (object)it)); + DeleteBuilder.BigDataFiled = primaryField; + } + return this; + } + + public IDeleteable In(PkType primaryKeyValue) + { + if (typeof(PkType).FullName.IsCollectionsList()) + { + var newValues = new List(); + foreach (var item in primaryKeyValue as IEnumerable) + { + newValues.Add(item); + } + return In(newValues); + } + + + In(new PkType[] { primaryKeyValue }); + return this; + } + + public IDeleteable In(Expression> inField, PkType primaryKeyValue) + { + var lamResult = DeleteBuilder.GetExpressionValue(inField, ResolveExpressType.FieldSingle); + var fieldName = lamResult.GetResultString(); + tempPrimaryKeys = new List() { fieldName }; + var result = In(primaryKeyValue);; + tempPrimaryKeys = null; + return this; + } + public IDeleteable In(Expression> inField, PkType[] primaryKeyValues) + { + var lamResult = DeleteBuilder.GetExpressionValue(inField, ResolveExpressType.FieldSingle); + var fieldName = lamResult.GetResultString(); + tempPrimaryKeys = new List() { fieldName }; + var result = In(primaryKeyValues); + tempPrimaryKeys = null; + return this; + } + public IDeleteable In(Expression> inField, List primaryKeyValues) + { + var lamResult = DeleteBuilder.GetExpressionValue(inField, ResolveExpressType.FieldSingle); + var fieldName = lamResult.GetResultString(); + tempPrimaryKeys = new List() { fieldName }; + var result = In(primaryKeyValues); + tempPrimaryKeys = null; + return this; + } + + public IDeleteable With(string lockString) + { + if (this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer) + DeleteBuilder.TableWithString = lockString; + return this; + } + + public KeyValuePair> ToSql() + { + DeleteBuilder.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); + string sql = DeleteBuilder.ToSqlString(); + var paramters = DeleteBuilder.Parameters == null ? null : DeleteBuilder.Parameters.ToList(); + RestoreMapping(); + return new KeyValuePair>(sql, paramters); + } + + private List GetPrimaryKeys() + { + if (tempPrimaryKeys.HasValue()) + { + return tempPrimaryKeys; + } + else if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + + protected virtual List GetIdentityKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetIsIdentities(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); + } + } + + private void RestoreMapping() + { + if (IsAs) + { + this.Context.MappingTables = OldMappingTableList; + } + } + + private void TaskStart(Task result) + { + if (this.Context.CurrentConnectionConfig.IsShardSameThread) + { + Check.Exception(true, "IsShardSameThread=true can't be used async method"); + } + result.Start(); + } + + private void AutoRemoveDataCache() + { + var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (moreSetts != null && moreSetts.IsAutoRemoveDataCache && extService != null && extService.DataInfoCacheService != null) + { + this.RemoveDataCache(); + } + } + + + private IDeleteable CopyDeleteable() + { + var asyncContext = this.Context.Utilities.CopyContext(true); + asyncContext.CurrentConnectionConfig.IsAutoCloseConnection = true; + asyncContext.IsAsyncMethod = true; + + var asyncDeleteable = asyncContext.Deleteable(); + var asyncDeleteBuilder = asyncDeleteable.DeleteBuilder; + asyncDeleteBuilder.BigDataFiled = this.DeleteBuilder.BigDataFiled; + asyncDeleteBuilder.BigDataInValues = this.DeleteBuilder.BigDataInValues; + asyncDeleteBuilder.Parameters = this.DeleteBuilder.Parameters; + asyncDeleteBuilder.sql = this.DeleteBuilder.sql; + asyncDeleteBuilder.WhereInfos = this.DeleteBuilder.WhereInfos; + asyncDeleteBuilder.TableWithString = this.DeleteBuilder.TableWithString; + if (this.RemoveCacheFunc != null) + { + asyncDeleteable.RemoveDataCache(); + } + return asyncDeleteable; + } + + private void After(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var parameters = DeleteBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.AfterData = null; + diffModel.Time = this.Context.Ado.SqlExecutionTime; + if (this.Context.Ado.DiffLogEvent != null) + this.Context.Ado.DiffLogEvent(diffModel); + } + if (this.RemoveCacheFunc != null) { + this.RemoveCacheFunc(); + } + } + + private void Before(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var parameters = DeleteBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.BeforeData = GetDiffTable(sql, parameters); + diffModel.Sql = sql; + diffModel.Parameters = parameters.ToArray(); + } + } + + private List GetDiffTable(string sql, List parameters) + { + List result = new List(); + var whereSql = Regex.Replace(sql, ".* WHERE ", "", RegexOptions.Singleline); + var dt = this.Context.Queryable().Where(whereSql).AddParameters(parameters).ToDataTable(); + if (dt.Rows != null && dt.Rows.Count > 0) + { + foreach (DataRow row in dt.Rows) + { + DiffLogTableInfo item = new DiffLogTableInfo(); + item.TableDescription = this.EntityInfo.TableDescription; + item.TableName = this.EntityInfo.DbTableName; + item.Columns = new List(); + foreach (DataColumn col in dt.Columns) + { + DiffLogColumnInfo addItem = new DiffLogColumnInfo(); + addItem.Value = row[col.ColumnName]; + addItem.ColumnName = col.ColumnName; + addItem.ColumnDescription = this.EntityInfo.Columns.First(it => it.DbColumnName.Equals(col.ColumnName, StringComparison.CurrentCultureIgnoreCase)).ColumnDescription; + item.Columns.Add(addItem); + } + result.Add(item); + } + } + return result; + } + } +} diff --git a/类库/SqlSugar/Abstract/EntityMaintenance/EntityMaintenance.cs b/类库/SqlSugar/Abstract/EntityMaintenance/EntityMaintenance.cs new file mode 100644 index 0000000..50c9a8c --- /dev/null +++ b/类库/SqlSugar/Abstract/EntityMaintenance/EntityMaintenance.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class EntityMaintenance + { + public SqlSugarClient Context { get; set; } + + public EntityInfo GetEntityInfo() + { + return GetEntityInfo(typeof(T)); + } + public EntityInfo GetEntityInfo(Type type) + { + string cacheKey = "GetEntityInfo" + type.FullName; + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + EntityInfo result = new EntityInfo(); + var sugarAttributeInfo = type.GetTypeInfo().GetCustomAttributes(typeof(SugarTable), true).Where(it => it is SugarTable).SingleOrDefault(); + if (sugarAttributeInfo.HasValue()) + { + var sugarTable = (SugarTable)sugarAttributeInfo; + result.DbTableName = sugarTable.TableName; + result.TableDescription = sugarTable.TableDescription; + } + if (this.Context.Context.CurrentConnectionConfig.ConfigureExternalServices != null && this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityNameService != null) { + this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityNameService(type,result); + } + result.Type = type; + result.EntityName = result.Type.Name; + result.Columns = new List(); + SetColumns(result); + return result; + }); + } + public string GetTableName() + { + var typeName = typeof(T).Name; + if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) return typeName; + else + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == typeName); + return mappingInfo == null ? typeName : mappingInfo.DbTableName; + } + } + public string GetTableName(Type entityType) + { + var typeName = entityType.Name; + if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) return typeName; + else + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == typeName); + return mappingInfo == null ? typeName : mappingInfo.DbTableName; + } + } + public string GetTableName(string entityName) + { + var typeName = entityName; + if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) return typeName; + else + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == typeName); + return mappingInfo == null ? typeName : mappingInfo.DbTableName; + } + } + public string GetEntityName(string tableName) + { + if (this.Context.MappingTables == null || this.Context.MappingTables.Count == 0) return tableName; + else + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.DbTableName == tableName); + return mappingInfo == null ? tableName : mappingInfo.EntityName; + } + } + public string GetDbColumnName(string propertyName) + { + var isAny = this.GetEntityInfo().Columns.Any(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + Check.Exception(!isAny, "Property " + propertyName + " is Invalid"); + var typeName = typeof(T).Name; + if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) return propertyName; + else + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.PropertyName == propertyName); + return mappingInfo == null ? propertyName : mappingInfo.DbColumnName; + } + } + public string GetDbColumnName(string propertyName,Type entityType) + { + var isAny = this.GetEntityInfo(entityType).Columns.Any(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + Check.Exception(!isAny, "Property " + propertyName + " is Invalid"); + var typeName = entityType.Name; + if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) return propertyName; + else + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.PropertyName == propertyName); + return mappingInfo == null ? propertyName : mappingInfo.DbColumnName; + } + } + public string GetPropertyName(string dbColumnName) + { + var typeName = typeof(T).Name; + if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) return dbColumnName; + else + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.DbColumnName.Equals(dbColumnName,StringComparison.CurrentCultureIgnoreCase)); + return mappingInfo == null ? dbColumnName : mappingInfo.PropertyName; + } + } + public string GetPropertyName(string dbColumnName,Type entityType) + { + var typeName = entityType.Name; + if (this.Context.MappingColumns == null || this.Context.MappingColumns.Count == 0) return dbColumnName; + else + { + var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.EntityName == typeName && it.DbColumnName.Equals(dbColumnName,StringComparison.CurrentCultureIgnoreCase)); + return mappingInfo == null ? dbColumnName : mappingInfo.PropertyName; + } + } + public PropertyInfo GetProperty(string dbColumnName) + { + var propertyName = GetPropertyName(dbColumnName); + return typeof(T).GetProperties().First(it => it.Name == propertyName); + } + #region Primary key + private void SetColumns(EntityInfo result) + { + foreach (var property in result.Type.GetProperties()) + { + EntityColumnInfo column = new EntityColumnInfo(); + //var isVirtual = property.GetGetMethod().IsVirtual; + //if (isVirtual) continue; + var sugarColumn = property.GetCustomAttributes(typeof(SugarColumn), true) + .Where(it => it is SugarColumn) + .Select(it => (SugarColumn)it) + .FirstOrDefault(); + + if (sugarColumn.IsNullOrEmpty()) + { + sugarColumn = new SugarColumn(); + } + + var t = property.PropertyType; + if (sugarColumn.Length == 0) + { + if (t == typeof(String)) sugarColumn.Length = 255; + else if (t == typeof(Int64) || t == typeof(Int32)) sugarColumn.Length = 11; + + } + if (typeof(String) == t && sugarColumn.Length == 0) + { + sugarColumn.Length = 255; + } + + column.DbTableName = result.DbTableName; + column.EntityName = result.EntityName; + column.PropertyName = property.Name; + column.PropertyInfo = property; + + if (sugarColumn.IsNullOrEmpty()) + { + column.DbColumnName = property.Name; + } + else + { + if (sugarColumn.IsIgnore == false) + { + column.DbColumnName = sugarColumn.ColumnName.IsNullOrEmpty() ? property.Name : sugarColumn.ColumnName; + column.IsPrimarykey = sugarColumn.IsPrimaryKey; + column.IsIdentity = sugarColumn.IsIdentity; + column.ColumnDescription = sugarColumn.ColumnDescription; + column.IsNullable = sugarColumn.IsNullable; + column.Length = sugarColumn.Length; + column.OldDbColumnName = sugarColumn.OldColumnName; + column.DataType = sugarColumn.ColumnDataType; + column.DecimalDigits = sugarColumn.DecimalDigits; + column.OracleSequenceName = sugarColumn.OracleSequenceName; + column.IsOnlyIgnoreInsert = sugarColumn.IsOnlyIgnoreInsert; + column.IsEnableUpdateVersionValidation = sugarColumn.IsEnableUpdateVersionValidation; + } + else + { + column.IsIgnore = true; + } + } + if (this.Context.MappingColumns.HasValue()) + { + var golbalMappingInfo = this.Context.MappingColumns.FirstOrDefault(it => it.EntityName.Equals(result.EntityName, StringComparison.CurrentCultureIgnoreCase) && it.PropertyName == column.PropertyName); + if (golbalMappingInfo != null) + column.DbColumnName = golbalMappingInfo.DbColumnName; + } + if (this.Context.IgnoreColumns.HasValue()) + { + var golbalMappingInfo = this.Context.IgnoreColumns.FirstOrDefault(it => it.EntityName.Equals(result.EntityName, StringComparison.CurrentCultureIgnoreCase) && it.PropertyName == column.PropertyName); + if (golbalMappingInfo != null) + column.IsIgnore = true; + } + if (this.Context.CurrentConnectionConfig.ConfigureExternalServices != null && this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityService != null) { + this.Context.CurrentConnectionConfig.ConfigureExternalServices.EntityService(property, column); + } + result.Columns.Add(column); + } + } + #endregion + + } +} diff --git a/类库/SqlSugar/Abstract/ExpressionableProvider/Expressionable.cs b/类库/SqlSugar/Abstract/ExpressionableProvider/Expressionable.cs new file mode 100644 index 0000000..a339e02 --- /dev/null +++ b/类库/SqlSugar/Abstract/ExpressionableProvider/Expressionable.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class Expressionable where T : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = it => true; + return _exp; + } + } + public class Expressionable where T : class, new() where T2 : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it,t2) => true; + return _exp; + } + } + public class Expressionable where T : class, new() where T2 : class, new() where T3 : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it, t2,t3) => true; + return _exp; + } + } + public class Expressionable where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it, t2, t3,t4) => true; + return _exp; + } + } + public class Expressionable where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5: class,new() + { + Expression> _exp = null; + + public Expressionable And(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.AndAlso(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable AndIF(bool isAnd, Expression> exp) + { + if (isAnd) + And(exp); + return this; + } + + public Expressionable Or(Expression> exp) + { + if (_exp == null) + _exp = exp; + else + _exp = Expression.Lambda>(Expression.OrElse(_exp.Body, exp.Body), _exp.Parameters); + return this; + } + + public Expressionable OrIF(bool isOr, Expression> exp) + { + if (isOr) + Or(exp); + return this; + } + + + public Expression> ToExpression() + { + if (_exp == null) + _exp = (it, t2, t3, t4,T5) => true; + return _exp; + } + } + + public class Expressionable + { + public static Expressionable Create() where T : class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() where T3 : class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() where T3 : class, new() where T4: class, new() + { + return new Expressionable(); + } + public static Expressionable Create() where T : class, new() where T2 : class, new() where T3 : class, new() where T4 : class, new() where T5:class,new() + { + return new Expressionable(); + } + } +} diff --git a/类库/SqlSugar/Abstract/FilterProvider/FilterProvider.cs b/类库/SqlSugar/Abstract/FilterProvider/FilterProvider.cs new file mode 100644 index 0000000..fef2042 --- /dev/null +++ b/类库/SqlSugar/Abstract/FilterProvider/FilterProvider.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class QueryFilterProvider : IFilter + { + internal SqlSugarClient Context { get; set; } + private List _Filters { get; set; } + + public IFilter Add(SqlFilterItem filter) + { + if (_Filters == null) + _Filters = new List(); + _Filters.Add(filter); + return this; + } + + public void Remove(string filterName) + { + if (_Filters == null) + _Filters = new List(); + _Filters.RemoveAll(it => it.FilterName == filterName); + } + + public List GeFilterList + { + get + { + if (_Filters == null) + _Filters = new List(); + return _Filters; + } + } + public void Clear() + { + _Filters = new List(); + } + } +} diff --git a/类库/SqlSugar/Abstract/InsertableProvider/InsertableProvider.cs b/类库/SqlSugar/Abstract/InsertableProvider/InsertableProvider.cs new file mode 100644 index 0000000..d713544 --- /dev/null +++ b/类库/SqlSugar/Abstract/InsertableProvider/InsertableProvider.cs @@ -0,0 +1,540 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class InsertableProvider : IInsertable where T : class, new() + { + public SqlSugarClient Context { get; set; } + public IAdo Ado { get { return Context.Ado; } } + public ISqlBuilder SqlBuilder { get; set; } + public InsertBuilder InsertBuilder { get; set; } + + public bool IsMappingTable { get { return this.Context.MappingTables != null && this.Context.MappingTables.Any(); } } + public bool IsMappingColumns { get { return this.Context.MappingColumns != null && this.Context.MappingColumns.Any(); } } + public bool IsSingle { get { return this.InsertObjs.Length == 1; } } + + public EntityInfo EntityInfo { get; set; } + public List MappingColumnList { get; set; } + private List IgnoreColumnNameList { get; set; } + private bool IsOffIdentity { get; set; } + public T[] InsertObjs { get; set; } + + public MappingTableList OldMappingTableList { get; set; } + public bool IsAs { get; set; } + public bool IsEnableDiffLogEvent { get; set; } + public DiffLogModel diffModel { get; set; } + private Action RemoveCacheFunc { get; set; } + + + #region Core + public virtual int ExecuteCommand() + { + if (InsertBuilder.DbColumnInfoList.HasValue()) + { + var pks = GetPrimaryKeys(); + foreach (var item in InsertBuilder.DbColumnInfoList) + { + var isPk = pks.Any(y => y.Equals(item.DbColumnName, StringComparison.CurrentCultureIgnoreCase)) || item.IsPrimarykey; + if (isPk && item.PropertyType == UtilConstants.GuidType && item.Value.ObjToString() == Guid.Empty.ToString()) + { + item.Value = Guid.NewGuid(); + if (InsertObjs.First().GetType().GetProperties().Any(it => it.Name == item.PropertyName)) + InsertObjs.First().GetType().GetProperties().First(it => it.Name == item.PropertyName).SetValue(InsertObjs.First(), item.Value, null); + } + } + } + InsertBuilder.IsReturnIdentity = false; + PreToSql(); + AutoRemoveDataCache(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + Before(sql); + var result = Ado.ExecuteCommand(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + After(sql, null); + return result; + } + + public virtual KeyValuePair> ToSql() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + AutoRemoveDataCache(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + return new KeyValuePair>(sql, InsertBuilder.Parameters); + } + public virtual int ExecuteReturnIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + AutoRemoveDataCache(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + Before(sql); + var result = Ado.GetInt(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + After(sql, result); + return result; + } + public virtual long ExecuteReturnBigIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + AutoRemoveDataCache(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + Before(sql); + var result = Convert.ToInt64(Ado.GetScalar(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray())); + After(sql, result); + return result; + } + public virtual T ExecuteReturnEntity() + { + ExecuteCommandIdentityIntoEntity(); + return InsertObjs.First(); + } + public virtual bool ExecuteCommandIdentityIntoEntity() + { + var result = InsertObjs.First(); + var identityKeys = GetIdentityKeys(); + if (identityKeys.Count == 0) { return this.ExecuteCommand() > 0; } + var idValue = ExecuteReturnBigIdentity(); + Check.Exception(identityKeys.Count > 1, "ExecuteCommandIdentityIntoEntity does not support multiple identity keys"); + var identityKey = identityKeys.First(); + object setValue = 0; + if (idValue > int.MaxValue) + setValue = idValue; + else + setValue = Convert.ToInt32(idValue); + this.Context.EntityMaintenance.GetProperty(identityKey).SetValue(result, setValue, null); + return idValue > 0; + } + public Task ExecuteCommandAsync() + { + Task result = new Task(() => + { + IInsertable asyncInsertable = CopyInsertable(); + return asyncInsertable.ExecuteCommand(); + }); + TaskStart(result); + return result; + } + public Task ExecuteReturnIdentityAsync() + { + Task result = new Task(() => + { + IInsertable asyncInsertable = CopyInsertable(); + return asyncInsertable.ExecuteReturnIdentity(); + }); + TaskStart(result); + return result; + } + public Task ExecuteReturnEntityAsync() + { + Task result = new Task(() => + { + IInsertable asyncInsertable = CopyInsertable(); + return asyncInsertable.ExecuteReturnEntity(); + }); + TaskStart(result); + return result; + } + public Task ExecuteCommandIdentityIntoEntityAsync() + { + Task result = new Task(() => + { + IInsertable asyncInsertable = CopyInsertable(); + return asyncInsertable.ExecuteCommandIdentityIntoEntity(); + }); + TaskStart(result); + return result; + } + public Task ExecuteReturnBigIdentityAsync() + { + Task result = new Task(() => + { + IInsertable asyncInsertable = CopyInsertable(); + return asyncInsertable.ExecuteReturnBigIdentity(); + }); + TaskStart(result); + return result; + } + #endregion + + #region Setting + public IInsertable AS(string tableName) + { + var entityName = typeof(T).Name; + IsAs = true; + OldMappingTableList = this.Context.MappingTables; + this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); + if (this.Context.MappingTables.Any(it => it.EntityName == entityName)) + { + this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName); + } + this.Context.MappingTables.Add(entityName, tableName); + return this; ; + } + public IInsertable IgnoreColumns(Expression> columns) + { + var ignoreColumns = InsertBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it)).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => !ignoreColumns.Any(ig => ig.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + return this; + } + public IInsertable IgnoreColumns(Func ignoreColumMethod) + { + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => !ignoreColumMethod(it.PropertyName)).ToList(); + return this; + } + + public IInsertable InsertColumns(Expression> columns) + { + var ignoreColumns = InsertBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it)).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => ignoreColumns.Any(ig => ig.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + return this; + } + + public IInsertable InsertColumns(string[] columns) + { + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => columns.Any(ig => ig.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + return this; + } + + public IInsertable InsertColumns(Func insertColumMethod) + { + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => insertColumMethod(it.PropertyName)).ToList(); + return this; + } + + public IInsertable With(string lockString) + { + if (this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer) + this.InsertBuilder.TableWithString = lockString; + return this; + } + + public IInsertable Where(bool isNoInsertNull, bool isOffIdentity = false) + { + this.IsOffIdentity = isOffIdentity; + if (this.InsertBuilder.LambdaExpressions == null) + this.InsertBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.Context.CurrentConnectionConfig); + this.InsertBuilder.IsNoInsertNull = isNoInsertNull; + return this; + } + + public IInsertable RemoveDataCache() + { + this.RemoveCacheFunc = () => + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + CacheSchemeMain.RemoveCache(cacheService, this.Context.EntityMaintenance.GetTableName()); + }; + return this; + } + public IInsertable EnableDiffLogEvent(object businessData = null) + { + Check.Exception(this.InsertObjs.HasValue() && this.InsertObjs.Count() > 1, "DiffLog does not support batch operations"); + diffModel = new DiffLogModel(); + this.IsEnableDiffLogEvent = true; + diffModel.BusinessData = businessData; + diffModel.DiffType = DiffType.insert; + return this; + } + #endregion + + #region Protected Methods + private void AutoRemoveDataCache() + { + var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (moreSetts != null && moreSetts.IsAutoRemoveDataCache && extService != null && extService.DataInfoCacheService != null) + { + this.RemoveDataCache(); + } + } + protected virtual void PreToSql() + { + #region Identities + if (!IsOffIdentity) + { + List identities = GetIdentityKeys(); + if (identities != null && identities.Any()) + { + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => + { + return !identities.Any(i => it.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + }).ToList(); + } + } + #endregion + + #region IgnoreColumns + if (this.Context.IgnoreColumns != null && this.Context.IgnoreColumns.Any()) + { + var currentIgnoreColumns = this.Context.IgnoreColumns.Where(it => it.EntityName == this.EntityInfo.EntityName).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => + { + return !currentIgnoreColumns.Any(i => it.PropertyName.Equals(i.PropertyName, StringComparison.CurrentCulture)); + }).ToList(); + } + + if (this.Context.IgnoreInsertColumns != null && this.Context.IgnoreInsertColumns.Any()) + { + var currentIgnoreColumns = this.Context.IgnoreInsertColumns.Where(it => it.EntityName == this.EntityInfo.EntityName).ToList(); + this.InsertBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList.Where(it => + { + return !currentIgnoreColumns.Any(i => it.PropertyName.Equals(i.PropertyName, StringComparison.CurrentCulture)); + }).ToList(); + } + #endregion + if (this.IsSingle) + { + foreach (var item in this.InsertBuilder.DbColumnInfoList) + { + if (this.InsertBuilder.Parameters == null) this.InsertBuilder.Parameters = new List(); + var paramters = new SugarParameter(this.SqlBuilder.SqlParameterKeyWord + item.DbColumnName, item.Value, item.PropertyType); + if (InsertBuilder.IsNoInsertNull && paramters.Value == null) + { + continue; + } + this.InsertBuilder.Parameters.Add(paramters); + } + } + } + internal void Init() + { + InsertBuilder.EntityInfo = this.EntityInfo; + Check.Exception(InsertObjs == null || InsertObjs.Count() == 0, "InsertObjs is null"); + int i = 0; + foreach (var item in InsertObjs) + { + List insertItem = new List(); + if (item is Dictionary) + { + SetInsertItemByDic(i, item, insertItem); + } + else + { + SetInsertItemByEntity(i, item, insertItem); + } + this.InsertBuilder.DbColumnInfoList.AddRange(insertItem); + ++i; + } + } + private void SetInsertItemByDic(int i, T item, List insertItem) + { + foreach (var column in item as Dictionary) + { + var columnInfo = new DbColumnInfo() + { + Value = column.Value, + DbColumnName = column.Key, + PropertyName = column.Key, + PropertyType = column.Value == null ? DBNull.Value.GetType() : UtilMethods.GetUnderType(column.Value.GetType()), + TableId = i + }; + if (columnInfo.PropertyType.IsEnum()) + { + columnInfo.Value = Convert.ToInt64(columnInfo.Value); + } + insertItem.Add(columnInfo); + } + } + private void SetInsertItemByEntity(int i, T item, List insertItem) + { + foreach (var column in EntityInfo.Columns) + { + if (column.IsIgnore || column.IsOnlyIgnoreInsert) continue; + var columnInfo = new DbColumnInfo() + { + Value = column.PropertyInfo.GetValue(item, null), + DbColumnName = GetDbColumnName(column.PropertyName), + PropertyName = column.PropertyName, + PropertyType = UtilMethods.GetUnderType(column.PropertyInfo), + TableId = i + }; + if (columnInfo.PropertyType.IsEnum()) + { + columnInfo.Value = Convert.ToInt64(columnInfo.Value); + } + insertItem.Add(columnInfo); + } + } + + private string GetDbColumnName(string propertyName) + { + if (!IsMappingColumns) + { + return propertyName; + } + if (this.Context.MappingColumns.Any(it => it.EntityName.Equals(EntityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase))) + { + this.MappingColumnList = this.Context.MappingColumns.Where(it => it.EntityName.Equals(EntityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase)).ToList(); + } + if (MappingColumnList == null || !MappingColumnList.Any()) + { + return propertyName; + } + else + { + var mappInfo = this.MappingColumnList.FirstOrDefault(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + return mappInfo == null ? propertyName : mappInfo.DbColumnName; + } + } + + protected virtual List GetPrimaryKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + protected virtual List GetIdentityKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetIsIdentities(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); + } + } + private void TaskStart(Task result) + { + if (this.Context.CurrentConnectionConfig.IsShardSameThread) + { + Check.Exception(true, "IsShardSameThread=true can't be used async method"); + } + result.Start(); + } + protected void RestoreMapping() + { + if (IsAs) + { + this.Context.MappingTables = OldMappingTableList; + } + } + protected IInsertable CopyInsertable() + { + var asyncContext = this.Context.Utilities.CopyContext(true); + asyncContext.CurrentConnectionConfig.IsAutoCloseConnection = true; + asyncContext.IsAsyncMethod = true; + var asyncInsertable = asyncContext.Insertable(this.InsertObjs); + var asyncInsertableBuilder = asyncInsertable.InsertBuilder; + asyncInsertableBuilder.DbColumnInfoList = this.InsertBuilder.DbColumnInfoList; + asyncInsertableBuilder.EntityInfo = this.InsertBuilder.EntityInfo; + asyncInsertableBuilder.Parameters = this.InsertBuilder.Parameters; + asyncInsertableBuilder.sql = this.InsertBuilder.sql; + asyncInsertableBuilder.IsNoInsertNull = this.InsertBuilder.IsNoInsertNull; + asyncInsertableBuilder.IsReturnIdentity = this.InsertBuilder.IsReturnIdentity; + asyncInsertableBuilder.EntityInfo = this.InsertBuilder.EntityInfo; + asyncInsertableBuilder.TableWithString = this.InsertBuilder.TableWithString; + if (this.RemoveCacheFunc != null) + { + asyncInsertable.RemoveDataCache(); + } + return asyncInsertable; + } + + private void After(string sql, long? result) + { + if (this.IsEnableDiffLogEvent) + { + var parameters = InsertBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.AfterData = GetDiffTable(sql, result); + diffModel.Time = this.Context.Ado.SqlExecutionTime; + if (this.Context.Ado.DiffLogEvent != null) + this.Context.Ado.DiffLogEvent(diffModel); + } + if (this.RemoveCacheFunc != null) + { + this.RemoveCacheFunc(); + } + } + private void Before(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var parameters = InsertBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.BeforeData = null; + diffModel.Sql = sql; + diffModel.Parameters = parameters.ToArray(); + } + } + private List GetDiffTable(string sql, long? identity) + { + List parameters = new List(); + List result = new List(); + var whereSql = string.Empty; + List cons = new List(); + if (identity != null && identity > 0 && GetIdentityKeys().HasValue()) + { + var fieldName = GetIdentityKeys().Last(); + cons.Add(new ConditionalModel() { ConditionalType = ConditionalType.Equal, FieldName = fieldName, FieldValue = identity.ToString() }); + } + else + { + foreach (var item in this.EntityInfo.Columns.Where(it => it.IsIgnore == false && GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase)))) + { + var fielddName = item.DbColumnName; + var fieldValue = this.EntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.PropertyName).PropertyInfo.GetValue(this.InsertObjs.Last(), null).ObjToString(); + cons.Add(new ConditionalModel() { ConditionalType = ConditionalType.Equal, FieldName = fielddName, FieldValue = fieldValue }); + } + } + Check.Exception(cons.IsNullOrEmpty(), "Insertable.EnableDiffLogEvent need primary key"); + var sqlable = this.Context.Utilities.ConditionalModelToSql(cons); + whereSql = sqlable.Key; + parameters.AddRange(sqlable.Value); + var dt = this.Context.Queryable().Where(whereSql).AddParameters(parameters).ToDataTable(); + if (dt.Rows != null && dt.Rows.Count > 0) + { + foreach (DataRow row in dt.Rows) + { + DiffLogTableInfo item = new DiffLogTableInfo(); + item.TableDescription = this.EntityInfo.TableDescription; + item.TableName = this.EntityInfo.DbTableName; + item.Columns = new List(); + foreach (DataColumn col in dt.Columns) + { + DiffLogColumnInfo addItem = new DiffLogColumnInfo(); + addItem.Value = row[col.ColumnName]; + addItem.ColumnName = col.ColumnName; + addItem.ColumnDescription = this.EntityInfo.Columns.First(it => it.DbColumnName.Equals(col.ColumnName, StringComparison.CurrentCultureIgnoreCase)).ColumnDescription; + item.Columns.Add(addItem); + } + result.Add(item); + } + return result; + } + else + { + DiffLogTableInfo diffTable = new DiffLogTableInfo(); + diffTable.TableName = this.EntityInfo.DbTableName; + diffTable.TableDescription = this.EntityInfo.TableDescription; + diffTable.Columns = this.EntityInfo.Columns.Where(it => it.IsIgnore == false).Select(it => new DiffLogColumnInfo() + { + ColumnDescription = it.ColumnDescription, + ColumnName = it.DbColumnName, + Value = it.PropertyInfo.GetValue(this.InsertObjs.Last(), null) + }).ToList(); + return new List() { diffTable }; + } + + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/QueryableProvider/QueryableAccessory.cs b/类库/SqlSugar/Abstract/QueryableProvider/QueryableAccessory.cs new file mode 100644 index 0000000..21f64cf --- /dev/null +++ b/类库/SqlSugar/Abstract/QueryableProvider/QueryableAccessory.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class QueryableAccessory + { + protected ILambdaExpressions _LambdaExpressions; + protected bool _RestoreMapping = true; + protected int _InQueryableIndex = 100; + } +} diff --git a/类库/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs b/类库/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs new file mode 100644 index 0000000..953c205 --- /dev/null +++ b/类库/SqlSugar/Abstract/QueryableProvider/QueryableProvider.cs @@ -0,0 +1,6001 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; +using System.Reflection; +using System.Dynamic; +using System.Threading.Tasks; + +namespace SqlSugar +{ + #region T1 + public partial class QueryableProvider : QueryableAccessory, ISugarQueryable + { + public SqlSugarClient Context { get; set; } + public IAdo Db { get { return Context.Ado; } } + public IDbBind Bind { get { return this.Db.DbBind; } } + public ISqlBuilder SqlBuilder { get; set; } + public MappingTableList OldMappingTableList { get; set; } + public MappingTableList QueryableMappingTableList { get; set; } + public Action MapperAction { get; set; } + public Action> MapperActionWithCache { get; set; } + public List>> Mappers { get; set; } + public bool IsCache { get; set; } + public int CacheTime { get; set; } + public bool IsAs { get; set; } + public QueryBuilder QueryBuilder + { + get + { + return this.SqlBuilder.QueryBuilder; + } + set + { + this.SqlBuilder.QueryBuilder = value; + } + } + public EntityInfo EntityInfo + { + get + { + return this.Context.EntityMaintenance.GetEntityInfo(); + } + } + public void Clear() + { + QueryBuilder.Clear(); + } + + public ISugarQueryable Clone() + { + var queryable = this.Context.Queryable().WithCacheIF(IsCache, CacheTime); + CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public virtual ISugarQueryable AS(string tableName) + { + var entityName = typeof(T2).Name; + return _As(tableName, entityName); + } + public ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + return _As(tableName, entityName); + } + public virtual ISugarQueryable With(string withString) + { + QueryBuilder.TableWithString = withString; + return this; + } + + public virtual ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + + public virtual ISugarQueryable Mapper(Action mapperAction) + { + this.MapperAction = mapperAction; + return this; + } + public virtual ISugarQueryable Mapper(Action> mapperAction) + { + this.MapperActionWithCache = mapperAction; + return this; + } + public virtual ISugarQueryable Mapper(Expression>> mapperObject, Expression> mapperField) + { + return _Mapper(mapperObject, mapperField); + } + public virtual ISugarQueryable Mapper(Expression> mapperObject, Expression> mapperField) + { + return _Mapper(mapperObject, mapperField); + } + + public virtual ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public virtual ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public virtual ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public virtual ISugarQueryable AddParameters(SugarParameter parameter) + { + if (parameter != null) + QueryBuilder.Parameters.Add(parameter); + return this; + } + + public virtual ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + + /// + /// if a property that is not empty is a condition + /// + /// + /// + public ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + return WhereClass(new List() { whereClass },ignoreDefaultValue); + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + if (whereClassTypes.HasValue()) + { + var columns = this.Context.EntityMaintenance.GetEntityInfo().Columns.Where(it => it.IsIgnore == false).ToList(); + List whereModels = new List(); + foreach (var item in whereClassTypes) + { + var cons = new ConditionalCollections(); + foreach (var column in columns) + { + + var value = column.PropertyInfo.GetValue(item, null); + WhereType WhereType = WhereType.And; + var isNotNull = ignoreDefaultValue == false&&value != null ; + var isNotNullAndDefault = ignoreDefaultValue&& value!=null && value.ObjToString() != UtilMethods.DefaultForType(column.PropertyInfo.PropertyType).ObjToString(); + if (isNotNull||isNotNullAndDefault) + { + if (cons.ConditionalList == null) + { + cons.ConditionalList = new List>(); + if (QueryBuilder.WhereInfos.IsNullOrEmpty() && whereModels.IsNullOrEmpty()) + { + + } + else + { + WhereType = WhereType.Or; + } + + } + cons.ConditionalList.Add(new KeyValuePair(WhereType, new ConditionalModel() + { + ConditionalType = ConditionalType.Equal, + FieldName = column.DbColumnName, + FieldValue = value.ObjToString() + })); + } + } + if (cons.HasValue()) + { + whereModels.Add(cons); + } + } + this.Where(whereModels); + } + return this; + } + public virtual ISugarQueryable Where(Expression> expression) + { + this._Where(expression); + return this; + } + public virtual ISugarQueryable Where(string whereString, object whereObj = null) + { + if (whereString.HasValue()) + this.Where(whereString, whereObj); + return this; + } + + public virtual ISugarQueryable Where(List conditionalModels) + { + if (conditionalModels.IsNullOrEmpty()) return this; + var sqlObj = this.Context.Utilities.ConditionalModelToSql(conditionalModels); + return this.Where(sqlObj.Key, sqlObj.Value); + } + + public virtual ISugarQueryable Where(string whereString, object whereObj = null) + { + var whereValue = QueryBuilder.WhereInfos; + whereValue.Add(SqlBuilder.AppendWhereOrAnd(whereValue.Count == 0, whereString + UtilConstants.Space)); + if (whereObj != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(whereObj)); + return this; + } + + public virtual ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + public virtual ISugarQueryable Having(string whereString, object parameters = null) + { + + QueryBuilder.HavingInfos = SqlBuilder.AppendHaving(whereString); + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + + public virtual ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (!isWhere) return this; + _Where(expression); + return this; + } + public virtual ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj = null) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + + public virtual T InSingle(object pkValue) + { + Check.Exception(this.QueryBuilder.SelectValue.HasValue(), "'InSingle' and' Select' can't be used together,You can use .Select(it=>...).Single(it.id==1)"); + var list = In(pkValue).ToList(); + if (list == null) return default(T); + else return list.SingleOrDefault(); + } + public virtual ISugarQueryable In(params TParamter[] pkValues) + { + if (pkValues == null || pkValues.Length == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + if (pkValues.Length == 1 && pkValues.First().GetType().FullName.IsCollectionsList()|| (pkValues.First() is IEnumerable&&pkValues.First().GetType()!=UtilConstants.StringType)) + { + var newValues = new List(); + foreach (var item in pkValues.First() as IEnumerable) + { + newValues.Add(item); + } + return In(newValues); + } + var pks = GetPrimaryKeys().Select(it => SqlBuilder.GetTranslationTableName(it)).ToList(); + Check.Exception(pks == null || pks.Count != 1, "Queryable.In(params object[] pkValues): Only one primary key"); + string filed = pks.FirstOrDefault(); + string shortName = QueryBuilder.TableShortName == null ? null : (QueryBuilder.TableShortName + "."); + filed = shortName + filed; + return In(filed, pkValues); + } + public virtual ISugarQueryable In(string filed, params FieldType[] inValues) + { + if (inValues.Length == 1) + { + if (inValues.GetType().IsArray) + { + var whereIndex = QueryBuilder.WhereIndex; + string parameterName = this.SqlBuilder.SqlParameterKeyWord + "InPara" + whereIndex; + this.AddParameters(new SugarParameter(parameterName, inValues[0])); + this.Where(string.Format(QueryBuilder.InTemplate, filed, parameterName)); + QueryBuilder.WhereIndex++; + } + else + { + var values = new List(); + foreach (var item in ((IEnumerable)inValues[0])) + { + if (item != null) + { + values.Add(item.ToString().ToSqlValue()); + } + } + this.Where(string.Format(QueryBuilder.InTemplate, filed, string.Join(",", values))); + } + } + else + { + var values = new List(); + foreach (var item in inValues) + { + if (item != null) + { + values.Add(item.ToString().ToSqlValue()); + } + } + this.Where(string.Format(QueryBuilder.InTemplate, filed, string.Join(",", values))); + + } + return this; + } + public virtual ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + return In(fieldName, inValues); + } + public virtual ISugarQueryable In(List pkValues) + { + if (pkValues == null || pkValues.Count == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + return In(pkValues.ToArray()); + } + public virtual ISugarQueryable In(string InFieldName, List inValues) + { + if (inValues == null || inValues.Count == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + return In(InFieldName, inValues.ToArray()); + } + public virtual ISugarQueryable In(Expression> expression, List inValues) + { + if (inValues == null || inValues.Count == 0) + { + Where(SqlBuilder.SqlFalse); + return this; + } + return In(expression, inValues.ToArray()); + } + + public virtual ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + public virtual ISugarQueryable OrderBy(string orderFileds) + { + var orderByValue = QueryBuilder.OrderByValue; + if (QueryBuilder.OrderByValue.IsNullOrEmpty()) + { + QueryBuilder.OrderByValue = QueryBuilder.OrderByTemplate; + } + QueryBuilder.OrderByValue += string.IsNullOrEmpty(orderByValue) ? orderFileds : ("," + orderFileds); + return this; + } + public virtual ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + this._OrderBy(expression, type); + return this; + } + public virtual ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public virtual ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + return this.OrderBy(orderFileds); + else + return this; + } + public virtual ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + return this.OrderBy(expression, type); + else + return this; + } + + public virtual ISugarQueryable GroupBy(string groupFileds) + { + var croupByValue = QueryBuilder.GroupByValue; + if (QueryBuilder.GroupByValue.IsNullOrEmpty()) + { + QueryBuilder.GroupByValue = QueryBuilder.GroupByTemplate; + } + QueryBuilder.GroupByValue += string.IsNullOrEmpty(croupByValue) ? groupFileds : ("," + groupFileds); + return this; + } + + public virtual ISugarQueryable PartitionBy(Expression> expression) + { + if (QueryBuilder.Take == null) + QueryBuilder.Take = 1; + _PartitionBy(expression); + return this; + } + public virtual ISugarQueryable PartitionBy(string groupFileds) + { + var partitionByValue = QueryBuilder.PartitionByValue; + if (QueryBuilder.PartitionByValue.IsNullOrEmpty()) + { + QueryBuilder.PartitionByValue = QueryBuilder.PartitionByTemplate; + } + QueryBuilder.PartitionByValue += string.IsNullOrEmpty(partitionByValue) ? groupFileds : ("," + groupFileds); + return this; + } + + public virtual ISugarQueryable Skip(int num) + { + QueryBuilder.Skip = num; + return this; + } + public virtual ISugarQueryable Take(int num) + { + QueryBuilder.Take = num; + return this; + } + + public virtual T Single() + { + if (QueryBuilder.OrderByValue.IsNullOrEmpty()) + { + QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate; + } + var oldSkip = QueryBuilder.Skip; + var oldTake = QueryBuilder.Take; + var oldOrderBy = QueryBuilder.OrderByValue; + QueryBuilder.Skip = null; + QueryBuilder.Take = null; + QueryBuilder.OrderByValue = null; + var result = this.ToList(); + QueryBuilder.Skip = oldSkip; + QueryBuilder.Take = oldTake; + QueryBuilder.OrderByValue = oldOrderBy; + if (result == null || result.Count == 0) + { + return default(T); + } + else if (result.Count == 2) + { + Check.Exception(true, ".Single() result must not exceed one . You can use.First()"); + return default(T); + } + else + { + return result.SingleOrDefault(); + } + } + public virtual T Single(Expression> expression) + { + _Where(expression); + var result = Single(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public virtual T First() + { + if (QueryBuilder.OrderByValue.IsNullOrEmpty()) + { + QueryBuilder.OrderByValue = QueryBuilder.DefaultOrderByTemplate; + } + if (QueryBuilder.Skip.HasValue) + { + QueryBuilder.Take = 1; + return this.ToList().FirstOrDefault(); + } + else + { + QueryBuilder.Skip = 0; + QueryBuilder.Take = 1; + var result = this.ToList(); + if (result.HasValue()) + return result.FirstOrDefault(); + else + return default(T); + } + } + public virtual T First(Expression> expression) + { + _Where(expression); + var result = First(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public virtual bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public virtual bool Any() + { + return this.Count() > 0; + } + + public virtual ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + + public virtual ISugarQueryable Select() + { + var isJoin = this.QueryBuilder.JoinExpression != null; + if (isJoin) + { + var selectValue = new SugarMapper(this.Context).GetSelectValue(this.QueryBuilder); + return this.Select(selectValue); + } + else + { + return this.Select(this.SqlBuilder.SqlSelectAll); + } + } + + public virtual ISugarQueryable Select(string selectValue) + { + var result = InstanceFactory.GetQueryable(this.Context.CurrentConnectionConfig); + result.Context = this.Context; + result.SqlBuilder = this.SqlBuilder; + QueryBuilder.SelectValue = selectValue; + return result; + } + public virtual ISugarQueryable Select(string selectValue) + { + QueryBuilder.SelectValue = selectValue; + return this; + } + public virtual ISugarQueryable MergeTable() + { + Check.Exception(this.MapperAction != null || this.MapperActionWithCache != null, "'Mapper’ needs to be written after ‘MergeTable’ "); + Check.Exception(this.QueryBuilder.SelectValue.IsNullOrEmpty(), "MergeTable need to use Queryable.Select Method ."); + Check.Exception(this.QueryBuilder.Skip > 0 || this.QueryBuilder.Take > 0 || this.QueryBuilder.OrderByValue.HasValue(), "MergeTable Queryable cannot Take Skip OrderBy PageToList "); + ToSqlBefore(); + var sql = QueryBuilder.ToSqlString(); + var tableName = this.SqlBuilder.GetPackTable(sql, "MergeTable"); + var mergeQueryable = this.Context.Queryable(); + mergeQueryable.QueryBuilder.Parameters = QueryBuilder.Parameters; + mergeQueryable.QueryBuilder.WhereIndex = QueryBuilder.WhereIndex + 1; + mergeQueryable.QueryBuilder.JoinIndex = QueryBuilder.JoinIndex + 1; + mergeQueryable.QueryBuilder.LambdaExpressions.ParameterIndex = QueryBuilder.LambdaExpressions.ParameterIndex; + return mergeQueryable.AS(tableName).Select("*"); + } + + public ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + public virtual int Count() + { + InitMapping(); + QueryBuilder.IsCount = true; + int result = 0; + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return GetCount(); }, CacheTime, this.Context); + } + else + { + result = GetCount(); + } + RestoreMapping(); + QueryBuilder.IsCount = false; + return result; + } + + public virtual int Count(Expression> expression) + { + _Where(expression); + var result = Count(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + + public virtual TResult Max(string maxField) + { + this.Select(string.Format(QueryBuilder.MaxTemplate, maxField)); + var result = this._ToList().SingleOrDefault(); + return result; + } + public virtual TResult Max(Expression> expression) + { + return _Max(expression); + } + + public virtual TResult Min(string minField) + { + this.Select(string.Format(QueryBuilder.MinTemplate, minField)); + var result = this._ToList().SingleOrDefault(); + return result; + } + public virtual TResult Min(Expression> expression) + { + return _Min(expression); + } + + public virtual TResult Sum(string sumField) + { + this.Select(string.Format(QueryBuilder.SumTemplate, sumField)); + var result = this._ToList().SingleOrDefault(); + return result; + } + public virtual TResult Sum(Expression> expression) + { + return _Sum(expression); + } + + public virtual TResult Avg(string avgField) + { + this.Select(string.Format(QueryBuilder.AvgTemplate, avgField)); + var result = this._ToList().SingleOrDefault(); + return result; + } + public virtual TResult Avg(Expression> expression) + { + return _Avg(expression); + } + public virtual string ToJson() + { + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + var result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return this.Context.Utilities.SerializeObject(this.ToList()); }, CacheTime, this.Context); + return result; + } + else + { + return this.Context.Utilities.SerializeObject(this.ToList()); + } + } + public virtual string ToJsonPage(int pageIndex, int pageSize) + { + return this.Context.Utilities.SerializeObject(this.ToPageList(pageIndex, pageSize)); + } + public virtual string ToJsonPage(int pageIndex, int pageSize, ref int totalNumber) + { + return this.Context.Utilities.SerializeObject(this.ToPageList(pageIndex, pageSize, ref totalNumber)); + } + + public virtual DataTable ToDataTable() + { + InitMapping(); + var sqlObj = this.ToSql(); + RestoreMapping(); + DataTable result = null; + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); }, CacheTime, this.Context); + } + else + { + result = this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); + } + return result; + } + public virtual DataTable ToDataTablePage(int pageIndex, int pageSize) + { + if (pageIndex == 0) + pageIndex = 1; + if (QueryBuilder.PartitionByValue.HasValue()) + { + QueryBuilder.ExternalPageIndex = pageIndex; + QueryBuilder.ExternalPageSize = pageSize; + } + else + { + QueryBuilder.Skip = (pageIndex - 1) * pageSize; + QueryBuilder.Take = pageSize; + } + return ToDataTable(); + } + public virtual DataTable ToDataTablePage(int pageIndex, int pageSize, ref int totalNumber) + { + _RestoreMapping = false; + totalNumber = this.Count(); + _RestoreMapping = true; + var result = ToDataTablePage(pageIndex, pageSize); + return result; + } + + public virtual List ToList() + { + InitMapping(); + return _ToList(); + } + public virtual List ToPageList(int pageIndex, int pageSize) + { + if (pageIndex == 0) + pageIndex = 1; + if (QueryBuilder.PartitionByValue.HasValue()) + { + QueryBuilder.ExternalPageIndex = pageIndex; + QueryBuilder.ExternalPageSize = pageSize; + } + else + { + QueryBuilder.Skip = (pageIndex - 1) * pageSize; + QueryBuilder.Take = pageSize; + } + return ToList(); + } + public virtual List ToPageList(int pageIndex, int pageSize, ref int totalNumber) + { + _RestoreMapping = false; + List result = null; + int count = this.Count(); + _RestoreMapping = true; + QueryBuilder.IsDisabledGobalFilter = UtilMethods.GetOldValue(QueryBuilder.IsDisabledGobalFilter, () => + { + QueryBuilder.IsDisabledGobalFilter = true; + if (count == 0) + result = new List(); + else + result = ToPageList(pageIndex, pageSize); + + }); + totalNumber = count; + return result; + } + + public virtual KeyValuePair> ToSql() + { + InitMapping(); + ToSqlBefore(); + string sql = QueryBuilder.ToSqlString(); + RestoreMapping(); + return new KeyValuePair>(sql, QueryBuilder.Parameters); + } + public ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + Check.ArgumentNullException(this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService, "Use Cache ConnectionConfig.ConfigureExternalServices.DataInfoCacheService is required "); + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (isCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + public string ToClassString(string className) + { + List columns = new List(); + var properties = typeof(T).GetProperties(); + foreach (var item in properties) + { + columns.Add(new DbColumnInfo() + { + DbColumnName = item.Name, + PropertyName = UtilMethods.GetUnderType(item.PropertyType).Name, + PropertyType = UtilMethods.GetUnderType(item.PropertyType) + }); + } + var result = ((this.Context.DbFirst) as DbFirstProvider).GetClassString(columns, ref className); + return result; + } + #region Async methods + public Task SingleAsync() + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Single(); + }); + TaskStart(result); + return result; + } + + public Task SingleAsync(Expression> expression) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Single(expression); + }); + TaskStart(result); + return result; + } + + public Task FirstAsync() + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.First(); + }); + TaskStart(result); + return result; + } + + public Task FirstAsync(Expression> expression) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.First(expression); + }); + TaskStart(result); + return result; + } + + public Task AnyAsync(Expression> expression) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Any(expression); + }); + TaskStart(result); + return result; + } + + public Task AnyAsync() + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Any(); + }); + TaskStart(result); + return result; + } + + public Task CountAsync() + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Count(); + }); + TaskStart(result); + return result; + } + public Task CountAsync(Expression> expression) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Count(expression); + }); + TaskStart(result); ; + return result; + } + public Task MaxAsync(string maxField) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Max(maxField); + }); + TaskStart(result); + return result; + } + + public Task MaxAsync(Expression> expression) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Max(expression); + }); + TaskStart(result); + return result; + } + + public Task MinAsync(string minField) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Min(minField); + }); + TaskStart(result); + return result; + } + + public Task MinAsync(Expression> expression) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Min(expression); + }); + TaskStart(result); + return result; + } + + public Task SumAsync(string sumField) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Sum(sumField); + }); + TaskStart(result); + return result; + } + + public Task SumAsync(Expression> expression) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Sum(expression); + }); + TaskStart(result); + return result; + } + + public Task AvgAsync(string avgField) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Avg(avgField); + }); + TaskStart(result); + return result; + } + + public Task AvgAsync(Expression> expression) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.Avg(expression); + }); + TaskStart(result); + return result; + } + + public Task> ToListAsync() + { + Task> result = new Task>(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.ToList(); + }); + TaskStart(result); + return result; + } + + public Task ToJsonAsync() + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.ToJson(); + }); + TaskStart(result); + return result; + } + + public Task ToJsonPageAsync(int pageIndex, int pageSize) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.ToJsonPage(pageIndex, pageSize); + }); + TaskStart(result); + return result; + } + + public Task> ToJsonPageAsync(int pageIndex, int pageSize, int totalNumber) + { + Task> result = new Task>(() => + { + int totalNumberAsync = 0; + ISugarQueryable asyncQueryable = CopyQueryable(); + var list = asyncQueryable.ToJsonPage(pageIndex, pageSize, ref totalNumberAsync); + return new KeyValuePair(list, totalNumberAsync); + }); + TaskStart(result); + return result; + } + + public Task ToDataTableAsync() + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.ToDataTable(); + }); + TaskStart(result); + return result; + } + + public Task ToDataTablePageAsync(int pageIndex, int pageSize) + { + Task result = new Task(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.ToDataTablePage(pageIndex, pageSize); + }); + TaskStart(result); + return result; + } + + public Task> ToDataTablePageAsync(int pageIndex, int pageSize, int totalNumber) + { + Task> result = new Task>(() => + { + int totalNumberAsync = 0; + ISugarQueryable asyncQueryable = CopyQueryable(); + var list = asyncQueryable.ToDataTablePage(pageIndex, pageSize, ref totalNumberAsync); + return new KeyValuePair(list, totalNumberAsync); + }); + TaskStart(result); + return result; + } + + public Task> ToPageListAsync(int pageIndex, int pageSize) + { + Task> result = new Task>(() => + { + ISugarQueryable asyncQueryable = CopyQueryable(); + return asyncQueryable.ToPageList(pageIndex, pageSize); + }); + TaskStart(result); + return result; + } + + public Task, int>> ToPageListAsync(int pageIndex, int pageSize, int totalNumber) + { + Task, int>> result = new Task, int>>(() => + { + int totalNumberAsync = 0; + ISugarQueryable asyncQueryable = CopyQueryable(); + var list = asyncQueryable.ToPageList(pageIndex, pageSize, ref totalNumberAsync); + return new KeyValuePair, int>(list, totalNumberAsync); + }); + TaskStart(result); + return result; + } + #endregion + + #region Private Methods + private void TaskStart(Task result) + { + if (this.Context.CurrentConnectionConfig.IsShardSameThread) + { + Check.Exception(true, "IsShardSameThread=true can't be used async method"); + } + result.Start(); + } + protected ISugarQueryable _Select(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Select"); + this.Context.InitMppingInfo(); + var result = InstanceFactory.GetQueryable(this.Context.CurrentConnectionConfig); + result.Context = this.Context; + result.SqlBuilder = this.SqlBuilder; + result.SqlBuilder.QueryBuilder.Parameters = QueryBuilder.Parameters; + result.SqlBuilder.QueryBuilder.SelectValue = expression; + return result; + } + protected void _Where(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Where"); + var isSingle = QueryBuilder.IsSingle(); + var result = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple); + QueryBuilder.WhereInfos.Add(SqlBuilder.AppendWhereOrAnd(QueryBuilder.WhereInfos.IsNullOrEmpty(), result.GetResultString())); + } + protected ISugarQueryable _OrderBy(Expression expression, OrderByType type = OrderByType.Asc) + { + QueryBuilder.CheckExpression(expression, "OrderBy"); + var isSingle = QueryBuilder.IsSingle(); + if ((expression as LambdaExpression).Body is NewExpression) + { + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.ArraySingle : ResolveExpressType.ArrayMultiple); + var items = lamResult.GetResultString().Split(',').Where(it => it.HasValue()).Select(it => it + UtilConstants.Space + type.ToString().ToUpper()).ToList(); + OrderBy(string.Join(",", items)); + return this; + } + else + { + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + OrderBy(lamResult.GetResultString() + UtilConstants.Space + type.ToString().ToUpper()); + return this; + } + } + protected ISugarQueryable _GroupBy(Expression expression) + { + QueryBuilder.CheckExpression(expression, "GroupBy"); + LambdaExpression lambda = expression as LambdaExpression; + expression = lambda.Body; + var isSingle = QueryBuilder.IsSingle(); + ExpressionResult lamResult = null; + string result = null; + if (expression is NewExpression) + { + lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.ArraySingle : ResolveExpressType.ArrayMultiple); + result = string.Join(",", lamResult.GetResultArray().Select(it => it)); + } + else + { + lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + result = lamResult.GetResultString(); + } + GroupBy(result); + return this; + } + protected TResult _Min(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Main"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var result = Min(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return result; + } + protected TResult _Avg(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Avg"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + return Avg(lamResult.GetResultString()); + } + protected TResult _Max(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Max"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var reslut = Max(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return reslut; + } + protected TResult _Sum(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Sum"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var reslut = Sum(lamResult.GetResultString()); + QueryBuilder.SelectValue = null; + return reslut; + } + protected ISugarQueryable _As(string tableName, string entityName) + { + IsAs = true; + OldMappingTableList = this.Context.MappingTables; + this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); + if (this.Context.MappingTables.Any(it => it.EntityName == entityName)) + { + this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName); + } + this.Context.MappingTables.Add(entityName, tableName); + this.QueryableMappingTableList = this.Context.MappingTables; + return this; + } + protected void _Filter(string FilterName, bool isDisabledGobalFilter) + { + QueryBuilder.IsDisabledGobalFilter = isDisabledGobalFilter; + if (this.Context.QueryFilter.GeFilterList.HasValue() && FilterName.HasValue()) + { + var list = this.Context.QueryFilter.GeFilterList.Where(it => it.FilterName == FilterName && it.IsJoinQuery == !QueryBuilder.IsSingle()); + foreach (var item in list) + { + var filterResult = item.FilterValue(this.Context); + Where(filterResult.Sql, filterResult.Parameters); + } + } + } + public ISugarQueryable _PartitionBy(Expression expression) + { + QueryBuilder.CheckExpression(expression, "PartitionBy"); + LambdaExpression lambda = expression as LambdaExpression; + expression = lambda.Body; + var isSingle = QueryBuilder.IsSingle(); + ExpressionResult lamResult = null; + string result = null; + if (expression is NewExpression) + { + lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.ArraySingle : ResolveExpressType.ArrayMultiple); + result = string.Join(",", lamResult.GetResultArray()); + } + else + { + lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + result = lamResult.GetResultString(); + } + PartitionBy(result); + return this; + } + protected ISugarQueryable _Having(Expression expression) + { + QueryBuilder.CheckExpression(expression, "Having"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple); + Having(lamResult.GetResultString()); + return this; + } + protected List _ToList() + { + List result = null; + var sqlObj = this.ToSql(); + if (IsCache) + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + result = CacheSchemeMain.GetOrCreate>(cacheService, this.QueryBuilder, () => { return GetData(sqlObj); }, CacheTime, this.Context); + } + else + { + result = GetData(sqlObj); + } + RestoreMapping(); + _Mapper(result); + return result; + } + + protected void _Mapper(List result) + { + if (this.Mappers.HasValue()) + { + foreach (var mapper in this.Mappers) + { + if (typeof(TResult) == typeof(T)) + { + mapper(result.Select(it => (T)Convert.ChangeType(it, typeof(T))).ToList()); + } + else + { + Check.Exception(true, "{0} and {1} are not a type, Try .select().mapper().ToList", typeof(TResult).FullName, typeof(T).FullName); + } + } + } + if (this.MapperAction != null) + { + foreach (TResult item in result) + { + if (typeof(TResult) == typeof(T)) + { + this.MapperAction((T)Convert.ChangeType(item, typeof(T))); + } + else + { + Check.Exception(true, "{0} and {1} are not a type, Try .select().mapper().ToList", typeof(TResult).FullName, typeof(T).FullName); + } + } + } + if (this.MapperActionWithCache != null) + { + if (typeof(TResult) == typeof(T)) + { + var list = (List)Convert.ChangeType(result, typeof(List)); + var mapperCache = new MapperCache(list, this.Context); + foreach (T item in list) + { + this.MapperActionWithCache(item, mapperCache); + } + } + else + { + Check.Exception(true, "{0} and {1} are not a type, Try .select().mapper().ToList", typeof(TResult).FullName, typeof(T).FullName); + } + } + } + + private ISugarQueryable _Mapper(Expression mapperObject, Expression mapperField) + { + if ((mapperObject as LambdaExpression).Body is UnaryExpression) + { + mapperObject = ((mapperObject as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + mapperObject = (mapperObject as LambdaExpression).Body; + } + if ((mapperField as LambdaExpression).Body is UnaryExpression) + { + mapperField = ((mapperField as LambdaExpression).Body as UnaryExpression).Operand; + } + else + { + mapperField = (mapperField as LambdaExpression).Body; + } + Check.Exception(mapperObject is MemberExpression == false || mapperField is MemberExpression == false, ".Mapper() parameter error"); + var mapperObjectExp = mapperObject as MemberExpression; + var mapperFieldExp = mapperField as MemberExpression; + Check.Exception(mapperFieldExp.Type.IsClass(), ".Mapper() parameter error"); + var objType = mapperObjectExp.Type; + var filedType = mapperFieldExp.Expression.Type; + Check.Exception(objType != typeof(TObject) && objType != typeof(List), ".Mapper() parameter error"); + if (objType == typeof(List)) + { + objType = typeof(TObject); + } + var filedName = mapperFieldExp.Member.Name; + var objName = mapperObjectExp.Member.Name; + var filedEntity = this.Context.EntityMaintenance.GetEntityInfo(objType); + var objEntity = this.Context.EntityMaintenance.GetEntityInfo(filedType); + var isSelf = filedType == typeof(T); + if (Mappers == null) + Mappers = new List>>(); + if (isSelf) + { + Action> mapper = (entitys) => + { + if (entitys.IsNullOrEmpty()||!entitys.Any()) return; + var entity = entitys.First(); + var whereCol = filedEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals(filedName, StringComparison.CurrentCultureIgnoreCase)); + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => GetPrimaryKeys().Any(pk=>pk.Equals(it.DbColumnName,StringComparison.CurrentCultureIgnoreCase)) ); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals("id",StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + whereCol = filedEntity.Columns.FirstOrDefault(it => (it.PropertyName).Equals(it.EntityName+"id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + Check.Exception(true, ".Mapper() parameter error"); + } + List inValues = entitys.Select(it => it.GetType().GetProperty(filedName).GetValue(it, null).ObjToString()).ToList(); + List wheres = new List() + { + new ConditionalModel() + { + FieldName=whereCol.DbColumnName, + ConditionalType= ConditionalType.In, + FieldValue=string.Join(",",inValues.Distinct()) + } + }; + var list = this.Context.Queryable().Where(wheres).ToList(); + foreach (var item in entitys) + { + var whereValue = item.GetType().GetProperty(filedName).GetValue(item, null); + var setValue = list.Where(x => x.GetType().GetProperty(whereCol.PropertyName).GetValue(x, null).ObjToString() == whereValue.ObjToString()).ToList(); + var setObject = item.GetType().GetProperty(objName); + if (setObject.PropertyType.FullName.IsCollectionsList()) + { + setObject.SetValue(item, setValue.ToList(), null); + } + else + { + setObject.SetValue(item, setValue.FirstOrDefault(), null); + } + } + }; + Mappers.Add(mapper); + } + else + { + Action> mapper = (entitys) => + { + if (entitys.IsNullOrEmpty()||!entitys.Any()) return; + var entity = entitys.First(); + var tEntity = this.Context.EntityMaintenance.GetEntityInfo(); + var whereCol = tEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals(filedName, StringComparison.CurrentCultureIgnoreCase)); + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => GetPrimaryKeys().Any(pk => pk.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase))); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => it.PropertyName.Equals("id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + whereCol = tEntity.Columns.FirstOrDefault(it => (it.PropertyName).Equals(it.EntityName + "id", StringComparison.CurrentCultureIgnoreCase)); + } + if (whereCol == null) + { + Check.Exception(true, ".Mapper() parameter error"); + } + List inValues = entitys.Select(it => it.GetType().GetProperty(whereCol.PropertyName).GetValue(it, null).ObjToString()).ToList(); + var dbColumnName = filedEntity.Columns.FirstOrDefault(it => it.PropertyName == filedName).DbColumnName; + List wheres = new List() + { + new ConditionalModel() + { + FieldName=dbColumnName, + ConditionalType= ConditionalType.In, + FieldValue=string.Join(",",inValues) + } + }; + var list = this.Context.Queryable().Where(wheres).ToList(); + foreach (var item in entitys) + { + var whereValue = item.GetType().GetProperty(whereCol.PropertyName).GetValue(item, null); + var setValue = list.Where(x => x.GetType().GetProperty(filedName).GetValue(x, null).ObjToString() == whereValue.ObjToString()).ToList(); + var setObject = item.GetType().GetProperty(objName); + if (setObject.PropertyType.FullName.IsCollectionsList()) + { + setObject.SetValue(item, setValue.ToList(), null); + } + else + { + setObject.SetValue(item, setValue.FirstOrDefault(), null); + } + } + }; + Mappers.Add(mapper); + } + + return this; + } + + protected int GetCount() + { + var sql = string.Empty; + ToSqlBefore(); + sql = QueryBuilder.ToSqlString(); + sql = QueryBuilder.ToCountSql(sql); + var result = Context.Ado.GetInt(sql, QueryBuilder.Parameters.ToArray()); + return result; + } + + private void ToSqlBefore() + { + var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; + if (moreSetts != null && moreSetts.IsWithNoLockQuery && string.IsNullOrEmpty(QueryBuilder.TableWithString)) + { + this.With(SqlWith.NoLock); + } + } + + protected List GetData(KeyValuePair> sqlObj) + { + List result; + var isComplexModel = QueryBuilder.IsComplexModel(sqlObj.Key); + var entityType = typeof(TResult); + var dataReader = this.Db.GetDataReader(sqlObj.Key, sqlObj.Value.ToArray()); + if (entityType == UtilConstants.DynamicType) + { + result = this.Context.Utilities.DataReaderToExpandoObjectList(dataReader) as List; + } + else if (entityType == UtilConstants.ObjType) + { + result = this.Context.Utilities.DataReaderToExpandoObjectList(dataReader).Select(it => ((TResult)(object)it)).ToList(); + } + else if (entityType.IsAnonymousType() || isComplexModel) + { + result = this.Context.Utilities.DataReaderToList(dataReader); + } + else + { + result = this.Bind.DataReaderToList(entityType, dataReader); + } + SetContextModel(result, entityType); + return result; + } + + protected void _InQueryable(Expression expression, KeyValuePair> sqlObj) + { + QueryBuilder.CheckExpression(expression, "In"); + string sql = sqlObj.Key; + if (sqlObj.Value.HasValue()) + { + this.SqlBuilder.RepairReplicationParameters(ref sql, sqlObj.Value.ToArray(), 100); + this.QueryBuilder.Parameters.AddRange(sqlObj.Value); + } + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + var whereSql = string.Format(this.QueryBuilder.InTemplate, fieldName, sql); + this.QueryBuilder.WhereInfos.Add(SqlBuilder.AppendWhereOrAnd(this.QueryBuilder.WhereInfos.IsNullOrEmpty(), whereSql)); + base._InQueryableIndex += 100; + } + + protected List GetPrimaryKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + protected virtual List GetIdentityKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetIsIdentities(this.EntityInfo.DbTableName); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); + } + } + + protected void RestoreMapping() + { + if (IsAs && _RestoreMapping) + { + this.Context.MappingTables = OldMappingTableList == null ? new MappingTableList() : OldMappingTableList; + } + } + protected void InitMapping() + { + if (this.QueryableMappingTableList != null) + this.Context.MappingTables = this.QueryableMappingTableList; + } + + private void SetContextModel(List result, Type entityType) + { + if (result.HasValue()) + { + if (UtilMethods.GetRootBaseType(entityType).HasValue() && UtilMethods.GetRootBaseType(entityType) == UtilConstants.ModelType) + { + foreach (var item in result) + { + var contextProperty = item.GetType().GetProperty("Context"); + SqlSugarClient newClient = this.Context.Utilities.CopyContext(); + contextProperty.SetValue(item, newClient, null); + } + } + } + } + protected ISugarQueryable CopyQueryable() + { + var asyncContext = this.Context.Utilities.CopyContext(true); + asyncContext.IsAsyncMethod = true; + asyncContext.CurrentConnectionConfig.IsAutoCloseConnection = true; + var asyncQueryable = asyncContext.Queryable().Select(string.Empty).WithCacheIF(IsCache, CacheTime); + if (this.MapperAction != null) + asyncQueryable.Mapper(MapperAction); + if (this.MapperActionWithCache != null) + asyncQueryable.Mapper(MapperActionWithCache); + if (this.Mappers != null && ((asyncQueryable as QueryableProvider)!=null)) + { + (asyncQueryable as QueryableProvider).Mappers = this.Mappers; + } + CopyQueryBuilder(asyncQueryable.QueryBuilder); return asyncQueryable; + } + + protected void CopyQueryBuilder(QueryBuilder asyncQueryableBuilder) + { + var pars = new List(); + pars.AddRange(this.QueryBuilder.Parameters); + asyncQueryableBuilder.Take = this.QueryBuilder.Take; + asyncQueryableBuilder.Skip = this.QueryBuilder.Skip; + asyncQueryableBuilder.SelectValue = this.QueryBuilder.SelectValue; + asyncQueryableBuilder.WhereInfos = this.Context.Utilities.TranslateCopy(this.QueryBuilder.WhereInfos); + asyncQueryableBuilder.EasyJoinInfos = this.QueryBuilder.EasyJoinInfos; + asyncQueryableBuilder.JoinQueryInfos = this.QueryBuilder.JoinQueryInfos; + asyncQueryableBuilder.WhereIndex = this.QueryBuilder.WhereIndex; + asyncQueryableBuilder.EntityType = this.QueryBuilder.EntityType; + asyncQueryableBuilder.EntityName = this.QueryBuilder.EntityName; + asyncQueryableBuilder.Parameters = pars; + asyncQueryableBuilder.TableShortName = this.QueryBuilder.TableShortName; + asyncQueryableBuilder.TableWithString = this.QueryBuilder.TableWithString; + asyncQueryableBuilder.GroupByValue = this.QueryBuilder.GroupByValue; + asyncQueryableBuilder.IsDistinct = this.QueryBuilder.IsDistinct; + asyncQueryableBuilder.OrderByValue = this.QueryBuilder.OrderByValue; + asyncQueryableBuilder.IsDisabledGobalFilter = this.QueryBuilder.IsDisabledGobalFilter; + asyncQueryableBuilder.PartitionByValue = this.QueryBuilder.PartitionByValue; + asyncQueryableBuilder.JoinExpression = this.QueryBuilder.JoinExpression; + asyncQueryableBuilder.WhereIndex = this.QueryBuilder.WhereIndex; + asyncQueryableBuilder.HavingInfos = this.QueryBuilder.HavingInfos; + asyncQueryableBuilder.LambdaExpressions.ParameterIndex = this.QueryBuilder.LambdaExpressions.ParameterIndex; + } + + #endregion + } + #endregion + #region T2 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + + #endregion + + #region Order + public new ISugarQueryable OrderBy(string orderFileds) + { + base.OrderBy(orderFileds); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public new ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public new ISugarQueryable Having(string whereString, object whereObj) + { + base.Having(whereString, whereObj); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (isCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T3 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Group + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + public new ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public new ISugarQueryable Having(string whereString, object whereObj) + { + base.Having(whereString, whereObj); + return this; + } + #endregion + + #region Order + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + #endregion + + #region Where + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T4 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public new ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public ISugarQueryable Having(Expression> expression) + { + this._Having(expression); + return this; + } + + public new ISugarQueryable Having(string whereString, object whereObj) + { + base.Having(whereString, whereObj); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + + public ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, List inValues) + { + QueryBuilder.CheckExpression(expression, "In"); + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T5 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T6 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T7 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T8 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new() + { + base.WhereClass(whereClass, ignoreDefaultValue); + return this; + } + /// + /// if a property that is not empty is a condition + /// + /// + /// + public new ISugarQueryable WhereClass(List whereClassTypes, bool ignoreDefaultValue = false) where ClassType : class, new() + { + + base.WhereClass(whereClassTypes, ignoreDefaultValue); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds) + { + if (isOrderBy) + base.OrderBy(orderFileds); + return this; + } + public new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc) + { + if (isOrderBy) + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + + public bool Any(Expression> expression) + { + _Where(expression); + var result = Any(); + this.QueryBuilder.WhereInfos.Remove(this.QueryBuilder.WhereInfos.Last()); + return result; + } + public new ISugarQueryable Distinct() + { + QueryBuilder.IsDistinct = true; + return this; + } + #endregion + } + #endregion + #region T9 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8, t9) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + #endregion + } + #endregion + #region T10 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8, t9, t10) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + #endregion + } + #endregion + #region T11 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8, t9, t10, t11) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + #endregion + } + #endregion + #region T12 + public partial class QueryableProvider : QueryableProvider, ISugarQueryable + { + #region Where + public new ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public ISugarQueryable Where(Expression> expression) + { + _Where(expression); + return this; + } + public new ISugarQueryable Where(List conditionalModels) + { + base.Where(conditionalModels); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public ISugarQueryable WhereIF(bool isWhere, Expression> expression) + { + if (isWhere) + _Where(expression); + return this; + } + public new ISugarQueryable Where(string whereString, object whereObj) + { + Where(whereString, whereObj); + return this; + } + + public new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj) + { + if (!isWhere) return this; + this.Where(whereString, whereObj); + return this; + } + #endregion + + #region Select + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + public ISugarQueryable Select(Expression> expression) + { + return _Select(expression); + } + #endregion + + #region OrderBy + public new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + public ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc) + { + _OrderBy(expression, type); + return this; + } + #endregion + + #region GroupBy + public new ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + public ISugarQueryable GroupBy(Expression> expression) + { + _GroupBy(expression); + return this; + } + #endregion + + #region Aggr + public TResult Max(Expression> expression) + { + return _Max(expression); + } + public TResult Min(Expression> expression) + { + return _Min(expression); + } + public TResult Sum(Expression> expression) + { + return _Sum(expression); + } + public TResult Avg(Expression> expression) + { + return _Avg(expression); + } + #endregion + + #region In + public new ISugarQueryable In(Expression> expression, params FieldType[] inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, List inValues) + { + var isSingle = QueryBuilder.IsSingle(); + var lamResult = QueryBuilder.GetExpressionValue(expression, isSingle ? ResolveExpressType.FieldSingle : ResolveExpressType.FieldMultiple); + var fieldName = lamResult.GetResultString(); + In(fieldName, inValues); + return this; + } + public new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression) + { + var sqlObj = childQueryExpression.ToSql(); + _InQueryable(expression, sqlObj); + return this; + } + #endregion + + #region Other + public new ISugarQueryable Clone() + { + var queryable = this.Context.Queryable((t, t2, t3, t4, t5, T6, t7, t8, t9, t10, t11, t12) => new object[] { }).WithCacheIF(IsCache, CacheTime); + base.CopyQueryBuilder(queryable.QueryBuilder); + return queryable; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(AsT).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable AS(string tableName) + { + var entityName = typeof(T).Name; + _As(tableName, entityName); + return this; + } + public new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false) + { + _Filter(FilterName, isDisabledGobalFilter); + return this; + } + public new ISugarQueryable AddParameters(object parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + return this; + } + public new ISugarQueryable AddParameters(SugarParameter[] parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddParameters(List parameters) + { + if (parameters != null) + QueryBuilder.Parameters.AddRange(parameters); + return this; + } + public new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left) + { + QueryBuilder.JoinIndex = +1; + QueryBuilder.JoinQueryInfos + .Add(new JoinQueryInfo() + { + JoinIndex = QueryBuilder.JoinIndex, + TableName = tableName, + ShortName = shortName, + JoinType = type, + JoinWhere = joinWhere + }); + return this; + } + public new ISugarQueryable With(string withString) + { + base.With(withString); + return this; + } + public new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + return this; + } + public new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue) + { + if (IsCache) + { + this.IsCache = true; + this.CacheTime = cacheDurationInSeconds; + } + return this; + } + #endregion + } + #endregion +} diff --git a/类库/SqlSugar/Abstract/SaveableProvider/SaveableProvider.cs b/类库/SqlSugar/Abstract/SaveableProvider/SaveableProvider.cs new file mode 100644 index 0000000..0c8de76 --- /dev/null +++ b/类库/SqlSugar/Abstract/SaveableProvider/SaveableProvider.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SaveableProvider : ISaveable where T : class, new() + { + internal SaveableProvider(SqlSugarClient context,List saveObjects) + { + this.saveObjects = saveObjects; + this.Context = context; + } + internal SaveableProvider(SqlSugarClient context, T saveObject) + { + this.saveObjects = new List() { saveObject }; + this.Context = context; + } + public SqlSugarClient Context { get; set; } + public List saveObjects = new List(); + public List existsObjects = null; + public List insertObjects + { + get + { + List result = new List(); + var pks = GetPrimaryKeys(); + Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); + Check.Exception(pks.Count() > 1, "Multiple primary keys are not supported"); + var pkInfo = this.EntityInfo.Columns.Where(it => it.DbColumnName.Equals(pks.First(), StringComparison.CurrentCultureIgnoreCase)).First(); + var pkValues = saveObjects.Select(it=>it.GetType().GetProperty(pkInfo.PropertyName).GetValue(it,null)); + if(existsObjects==null) + existsObjects=this.Context.Queryable().In(pkValues).ToList(); + return saveObjects.Where(it=>! + existsObjects.Any(e=> + e.GetType().GetProperty(pkInfo.PropertyName).GetValue(e,null).ObjToString() + == + it.GetType().GetProperty(pkInfo.PropertyName).GetValue(it, null).ObjToString())).ToList(); + } + } + public List updatObjects + { + get + { + List result = new List(); + var pks = GetPrimaryKeys(); + Check.Exception(pks.IsNullOrEmpty(), "Need primary key"); + Check.Exception(pks.Count() > 1, "Multiple primary keys are not supported"); + var pkInfo = this.EntityInfo.Columns.Where(it => it.DbColumnName.Equals(pks.First(), StringComparison.CurrentCultureIgnoreCase)).First(); + var pkValues = saveObjects.Select(it => it.GetType().GetProperty(pkInfo.PropertyName).GetValue(it, null)); + if (existsObjects == null) + existsObjects = this.Context.Queryable().In(pkValues).ToList(); + return saveObjects.Where(it => + existsObjects.Any(e => + e.GetType().GetProperty(pkInfo.PropertyName).GetValue(e, null).ObjToString() + == + it.GetType().GetProperty(pkInfo.PropertyName).GetValue(it, null).ObjToString())).ToList(); + } + } + + public IInsertable insertable { get; set; } + public IUpdateable updateable { get; set; } + + public EntityInfo EntityInfo + { + get + { + return this.Context.EntityMaintenance.GetEntityInfo(); + } + } + + public int ExecuteCommand() + { + LoadInsertable(); + LoadUpdateable(); + var insertCount = 0; + var updateCount = 0; + if (insertable != null) + { + insertCount = insertable.ExecuteCommand(); + } + if (updateable != null) + { + updateCount = updateable.ExecuteCommand(); + } + return updateCount + insertCount; + } + + public T ExecuteReturnEntity() + { + LoadInsertable(); + LoadUpdateable(); + if (insertable != null) + insertable.ExecuteCommandIdentityIntoEntity(); + if (updateable != null) + updateable.ExecuteCommand(); + return saveObjects.First(); + } + + public List ExecuteReturnList() + { + LoadInsertable(); + LoadUpdateable(); + if (insertable != null) + insertable.ExecuteCommand(); + if (updateable != null) + updateable.ExecuteCommand(); + return saveObjects; + } + public ISaveable InsertColumns(Expression> columns) + { + LoadInsertable(); + if (this.insertable != null) + { + this.insertable.InsertColumns(columns); + } + return this; + } + + public ISaveable EnableDiffLogEvent(object businessData = null) + { + LoadInsertable(); + if (this.insertable != null) + { + this.insertable.EnableDiffLogEvent(businessData); + } + if (this.updateable != null) + { + this.updateable.EnableDiffLogEvent(businessData); + } + return this; + } + + public ISaveable InsertIgnoreColumns(Expression> columns) + { + LoadInsertable(); + if (this.insertable != null) + { + this.insertable.IgnoreColumns(columns); + } + return this; + } + + public ISaveable UpdateColumns(Expression> columns) + { + LoadUpdateable(); + if (this.updateable != null) + { + this.updateable.UpdateColumns(columns); + } + return this; + } + + public ISaveable UpdateIgnoreColumns(Expression> columns) + { + LoadUpdateable(); + if (this.updateable != null) + { + this.updateable.IgnoreColumns(columns); + } + return this; + } + + protected virtual List GetPrimaryKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + private void LoadInsertable() + { + var temp = insertObjects; + if (insertable == null && temp.HasValue()) + insertable = this.Context.Insertable(temp); + } + private void LoadUpdateable() + { + var temp = updatObjects; + if (updateable == null && temp.HasValue()) + updateable = this.Context.Updateable(temp); + } + + } +} diff --git a/类库/SqlSugar/Abstract/SqlBuilderProvider/DeleteBuilder.cs b/类库/SqlSugar/Abstract/SqlBuilderProvider/DeleteBuilder.cs new file mode 100644 index 0000000..52512fd --- /dev/null +++ b/类库/SqlSugar/Abstract/SqlBuilderProvider/DeleteBuilder.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class DeleteBuilder : IDMLBuilder + { + #region Fields + private List _WhereInfos; + #endregion + + #region Common Properties + public EntityInfo EntityInfo { get; set; } + public SqlSugarClient Context { get; set; } + public ILambdaExpressions LambdaExpressions { get; set; } + public List Parameters { get; set; } + public StringBuilder sql { get; set; } + public ISqlBuilder Builder { get; set; } + public string TableWithString { get; set; } + public virtual List WhereInfos + { + get + { + _WhereInfos = UtilMethods.IsNullReturnNew(_WhereInfos); + return _WhereInfos; + } + set { _WhereInfos = value; } + } + public virtual List BigDataInValues { get; set; } + public virtual string BigDataFiled { get; set; } + #endregion + + #region Sql Template + public string SqlTemplate + { + get + { + return "DELETE FROM {0}{1}"; + } + } + public string WhereInTemplate + { + get + { + return "{0} IN ({1})"; + } + } + public string WhereInOrTemplate + { + get + { + return "OR"; + } + } + public string WhereInAndTemplate + { + get + { + return "AND"; + } + } + public string WhereInEqualTemplate + { + get + { + return Builder.SqlTranslationLeft+"{0}"+Builder.SqlTranslationRight+"=N'{1}'"; + } + } + public string WhereInAreaTemplate + { + get + { + return "({0})"; + } + } + #endregion + + #region Get Sql + public virtual string GetTableNameString + { + get + { + var result = Builder.GetTranslationTableName(EntityInfo.EntityName); + result += UtilConstants.Space; + if (this.TableWithString.HasValue()) + { + result += TableWithString + UtilConstants.Space; + } + return result; + } + } + public virtual string GetWhereString + { + get + { + if (_WhereInfos == null || _WhereInfos.Count == 0) return null; + string whereString = null; + int i = 0; + foreach (var item in _WhereInfos) + { + var isFirst = i == 0; + whereString += isFirst ? "WHERE " : "AND "; + whereString += (item + UtilConstants.Space); + ++i; + } + return whereString; + } + } + + #endregion + + #region Public methods + public virtual void Clear() + { + } + public virtual string ToSqlString() + { + if (this.BigDataInValues.IsNullOrEmpty()) + { + return string.Format(SqlTemplate, GetTableNameString, GetWhereString); + } + else//big data + { + var whereString = GetWhereString; + var sql = string.Format(SqlTemplate, GetTableNameString, whereString); + sql += whereString.IsNullOrEmpty() ? " WHERE " : " AND "; + StringBuilder batchDeleteSql = new StringBuilder(); + int pageSize = 1000; + int pageIndex = 1; + int totalRecord = this.BigDataInValues.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + while (pageCount >= pageIndex) + { + var inValues = this.BigDataInValues.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); + batchDeleteSql.Append(sql+string.Format(WhereInTemplate,BigDataFiled,inValues.ToArray().ToJoinSqlInVals())); + batchDeleteSql.Append(";"); + pageIndex++; + } + return batchDeleteSql.ToString(); + } + } + public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType) + { + ILambdaExpressions resolveExpress = this.LambdaExpressions; + this.LambdaExpressions.Clear(); + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + resolveExpress.InitMappingInfo = Context.InitMppingInfo; + resolveExpress.RefreshMapping = () => + { + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + }; + resolveExpress.Resolve(expression, resolveType); + if (this.Parameters == null) + this.Parameters = new List(); + this.Parameters.AddRange(resolveExpress.Parameters); + var result = resolveExpress.Result; + return result; + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/SqlBuilderProvider/InsertBuilder.cs b/类库/SqlSugar/Abstract/SqlBuilderProvider/InsertBuilder.cs new file mode 100644 index 0000000..a00f5c4 --- /dev/null +++ b/类库/SqlSugar/Abstract/SqlBuilderProvider/InsertBuilder.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using System.Linq.Expressions; +namespace SqlSugar +{ + public class InsertBuilder : IDMLBuilder + { + #region Init + public InsertBuilder() + { + this.sql = new StringBuilder(); + this.Parameters = new List(); + this.DbColumnInfoList = new List(); + } + + #endregion + + #region Common Properties + public SqlSugarClient Context { get; set; } + public ILambdaExpressions LambdaExpressions { get; set; } + public ISqlBuilder Builder { get; set; } + public StringBuilder sql { get; set; } + public List Parameters { get; set; } + public string TableWithString { get; set; } + public List DbColumnInfoList { get; set; } + public bool IsNoInsertNull { get; set; } + public bool IsReturnIdentity { get; set; } + public EntityInfo EntityInfo { get; set; } + public Dictionary OracleSeqInfoList { get; set; } + #endregion + + #region SqlTemplate + public virtual string SqlTemplate + { + get + { + if (IsReturnIdentity) + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;SELECT SCOPE_IDENTITY();"; + } + else + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;"; + + } + } + } + public virtual string SqlTemplateBatch + { + get + { + return "INSERT {0} ({1})"; + } + } + public virtual string SqlTemplateBatchSelect + { + get + { + return "{0} AS {1}"; + } + } + public virtual string SqlTemplateBatchUnion + { + get + { + return "\t\r\nUNION ALL "; + } + } + + #endregion + + #region Methods + public virtual void Clear() + { + + } + public virtual string GetTableNameString + { + get + { + var result = Builder.GetTranslationTableName(EntityInfo.EntityName); + result += UtilConstants.Space; + if (this.TableWithString.HasValue()) + { + result += TableWithString + UtilConstants.Space; + } + return result; + } + } + public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType) + { + ILambdaExpressions resolveExpress = this.LambdaExpressions; + this.LambdaExpressions.Clear(); + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + resolveExpress.Resolve(expression, resolveType); + this.Parameters.AddRange(resolveExpress.Parameters); + var result = resolveExpress.Result; + return result; + } + public virtual string ToSqlString() + { + if (IsNoInsertNull) + { + DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList(); + } + var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); + var isSingle = groupList.Count() == 1; + string columnsString = string.Join(",", groupList.First().Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + if (isSingle) + { + string columnParametersString = string.Join(",", this.DbColumnInfoList.Select(it => Builder.SqlParameterKeyWord + it.DbColumnName)); + return string.Format(SqlTemplate, GetTableNameString, columnsString, columnParametersString); + } + else + { + StringBuilder batchInsetrSql = new StringBuilder(); + int pageSize = 200; + if (this.EntityInfo.Columns.Count > 30) + { + pageSize = 50; + } + else if (this.EntityInfo.Columns.Count > 20) + { + pageSize = 100; + } + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + while (pageCount >= pageIndex) + { + batchInsetrSql.AppendFormat(SqlTemplateBatch, GetTableNameString, columnsString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + batchInsetrSql.Append(SqlTemplateBatchUnion); + } + batchInsetrSql.Append("\r\n SELECT " + string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value),Builder.GetTranslationColumnName(it.DbColumnName))))); + ++i; + } + pageIndex++; + batchInsetrSql.Append("\r\n;\r\n"); + } + return batchInsetrSql.ToString(); + } + } + public virtual object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type =UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "N'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "N'" + value.ToString() + "'"; + } + } + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/SqlBuilderProvider/QueryBuilder.cs b/类库/SqlSugar/Abstract/SqlBuilderProvider/QueryBuilder.cs new file mode 100644 index 0000000..a9d2556 --- /dev/null +++ b/类库/SqlSugar/Abstract/SqlBuilderProvider/QueryBuilder.cs @@ -0,0 +1,547 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public abstract class QueryBuilder : IDMLBuilder + { + + public QueryBuilder() + { + this.Parameters = new List(); + } + + #region Private Fileds + protected List _JoinQueryInfos; + protected Dictionary _EasyJoinInfos; + private List _WhereInfos; + private string _HavingInfos; + protected string _TableNameString; + #endregion + + #region Service object + public StringBuilder sql { get; set; } + public SqlSugarClient Context { get; set; } + public ILambdaExpressions LambdaExpressions { get; set; } + public ISqlBuilder Builder { get; set; } + #endregion + + #region Splicing basic + public bool IsCount { get; set; } + public int? Skip { get; set; } + public int ExternalPageIndex { get; set; } + public int ExternalPageSize { get; set; } + public int? Take { get; set; } + public string OrderByValue { get; set; } + public object SelectValue { get; set; } + public string SelectCacheKey { get; set; } + public string EntityName { get; set; } + + + public Type EntityType { get; set; } + public string TableWithString { get; set; } + public string GroupByValue { get; set; } + public string PartitionByValue { get; set; } + public int WhereIndex { get; set; } + public bool IsDistinct { get; set; } + public int JoinIndex { get; set; } + public bool IsDisabledGobalFilter { get; set; } + public virtual List Parameters { get; set; } + public Expression JoinExpression { get; set; } + public Dictionary EasyJoinInfos + { + get + { + _EasyJoinInfos = UtilMethods.IsNullReturnNew(_EasyJoinInfos); + return _EasyJoinInfos; + } + set { _EasyJoinInfos = value; } + } + public virtual List JoinQueryInfos + { + get + { + _JoinQueryInfos = UtilMethods.IsNullReturnNew(_JoinQueryInfos); + return _JoinQueryInfos; + } + set { _JoinQueryInfos = value; } + } + public virtual string TableShortName { get; set; } + public virtual List WhereInfos + { + get + { + _WhereInfos = UtilMethods.IsNullReturnNew(_WhereInfos); + return _WhereInfos; + } + set { _WhereInfos = value; } + } + public virtual string HavingInfos + { + get + { + return _HavingInfos; + } + set + { + _HavingInfos = value; + } + } + #endregion + + #region Lambada Type + public ResolveExpressType SelectType + { + get + { + return this.IsSingle() ? ResolveExpressType.SelectSingle : ResolveExpressType.SelectMultiple; + } + } + public ResolveExpressType WheretType + { + get + { + return this.IsSingle() ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple; + } + } + #endregion + + #region Sql Template + public virtual string SqlTemplate + { + get + { + return "SELECT {0} FROM {1}{2}{3}{4} "; + } + } + public virtual string JoinTemplate + { + get + { + return "{0}JOIN {1}{2}ON {3} "; + } + } + public virtual string PageTempalte + { + get + { + return @"SELECT * FROM ({0}) T WHERE RowIndex BETWEEN {1} AND {2}"; + } + } + public virtual string ExternalPageTempalte + { + get + { + return @"SELECT * FROM ({0}) T WHERE RowIndex2 BETWEEN {1} AND {2}"; + } + } + public virtual string DefaultOrderByTemplate + { + get + { + return "ORDER BY "+this.Builder.SqlDateNow+" "; + } + } + public virtual string OrderByTemplate + { + get + { + return "ORDER BY "; + } + } + public virtual string GroupByTemplate + { + get + { + return "GROUP BY "; + } + } + public virtual string PartitionByTemplate + { + get + { + return "PARTITION BY "; + } + } + public virtual string MaxTemplate + { + get + { + return "MAX({0})"; + } + } + public virtual string MinTemplate + { + get + { + return "MIN({0})"; + } + } + public virtual string SumTemplate + { + get + { + return "SUM({0})"; + } + } + public virtual string AvgTemplate + { + get + { + return "AVG({0})"; + } + } + public virtual string InTemplate + { + get + { + return "{0} IN ({1}) "; + } + } + #endregion + + #region Common Methods + public virtual bool IsSingle() + { + var isSingle = Builder.QueryBuilder.JoinQueryInfos.IsNullOrEmpty() && !EasyJoinInfos.Any(); + return isSingle; + } + public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType) + { + ILambdaExpressions resolveExpress = this.LambdaExpressions; + if (resolveType.IsIn(ResolveExpressType.FieldSingle,ResolveExpressType.FieldMultiple,ResolveExpressType.SelectSingle, ResolveExpressType.SelectMultiple) &&(expression is LambdaExpression)&& (expression as LambdaExpression).Body is BinaryExpression) { + resolveType = resolveType.IsIn(ResolveExpressType.SelectSingle, ResolveExpressType.FieldSingle) ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple; + } + this.LambdaExpressions.Clear(); + resolveExpress.JoinQueryInfos = Builder.QueryBuilder.JoinQueryInfos; + resolveExpress.IsSingle = IsSingle(); + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + resolveExpress.InitMappingInfo = this.Context.InitMppingInfo; + resolveExpress.RefreshMapping = () => + { + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + }; + resolveExpress.Resolve(expression, resolveType); + this.Parameters.AddRange(resolveExpress.Parameters); + var result = resolveExpress.Result; + var isSingleTableHasSubquery = IsSingle() && resolveExpress.SingleTableNameSubqueryShortName.HasValue(); + if (isSingleTableHasSubquery) { + Check.Exception(!string.IsNullOrEmpty(this.TableShortName) && resolveExpress.SingleTableNameSubqueryShortName != this.TableShortName, "{0} and {1} need same name"); + this.TableShortName = resolveExpress.SingleTableNameSubqueryShortName; + } + return result; + } + public virtual string ToSqlString() + { + string oldOrderBy = this.OrderByValue; + string externalOrderBy = oldOrderBy; + var isIgnoreOrderBy = this.IsCount&&this.PartitionByValue.IsNullOrEmpty(); + AppendFilter(); + sql = new StringBuilder(); + if (this.OrderByValue == null && (Skip != null || Take != null)) this.OrderByValue = " ORDER BY GetDate() "; + if (this.PartitionByValue.HasValue()) + { + this.OrderByValue = this.PartitionByValue + this.OrderByValue; + } + var isRowNumber = Skip != null || Take != null; + var rowNumberString = string.Format(",ROW_NUMBER() OVER({0}) AS RowIndex ", GetOrderByString); + string groupByValue = GetGroupByString + HavingInfos; + string orderByValue = (!isRowNumber && this.OrderByValue.HasValue()) ? GetOrderByString : null; + if (isIgnoreOrderBy) { orderByValue = null; } + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, groupByValue, orderByValue); + sql.Replace(UtilConstants.ReplaceKey, isRowNumber ? (isIgnoreOrderBy ? null : rowNumberString) : null); + if (isIgnoreOrderBy) { this.OrderByValue = oldOrderBy; return sql.ToString(); } + var result = ToPageSql(sql.ToString(), this.Take, this.Skip); + if (ExternalPageIndex > 0) + { + if (externalOrderBy.IsNullOrEmpty()) + { + externalOrderBy = " ORDER BY GetDate() "; + } + result = string.Format("SELECT *,ROW_NUMBER() OVER({0}) AS RowIndex2 FROM ({1}) ExternalTable ", GetExternalOrderBy(externalOrderBy), result); + result = ToPageSql2(result, ExternalPageIndex, ExternalPageSize, true); + } + this.OrderByValue = oldOrderBy; + return result; + } + + public virtual void AppendFilter() + { + if (!IsDisabledGobalFilter && this.Context.QueryFilter.GeFilterList.HasValue()) + { + var gobalFilterList = this.Context.QueryFilter.GeFilterList.Where(it => it.FilterName.IsNullOrEmpty()).ToList(); + foreach (var item in gobalFilterList.Where(it => it.IsJoinQuery == !IsSingle())) + { + var filterResult = item.FilterValue(this.Context); + WhereInfos.Add(this.Builder.AppendWhereOrAnd(this.WhereInfos.IsNullOrEmpty(), filterResult.Sql)); + var filterParamters = this.Context.Ado.GetParameters(filterResult.Parameters); + if (filterParamters.HasValue()) + { + this.Parameters.AddRange(filterParamters); + } + } + } + } + + public virtual string GetExternalOrderBy(string externalOrderBy) + { + return Regex.Replace(externalOrderBy, @"\[\w+\]\.", ""); + } + + public virtual string ToCountSql(string sql) + { + + return string.Format(" SELECT COUNT(1) FROM ({0}) CountTable ", sql); + } + + public virtual string ToPageSql(string sql, int? take, int? skip, bool isExternal = false) + { + string temp = isExternal ? ExternalPageTempalte : PageTempalte; + if (skip != null && take == null) + { + return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, long.MaxValue); + } + else if (skip == null && take != null) + { + return string.Format(temp, sql.ToString(), 1, take.ObjToInt()); + } + else if (skip != null && take != null) + { + return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, skip.ObjToInt() + take.ObjToInt()); + } + else + { + return sql.ToString(); + } + } + + public virtual string ToPageSql2(string sql, int? pageIndex, int? pageSize, bool isExternal = false) + { + string temp = isExternal ? ExternalPageTempalte : PageTempalte; + return string.Format(temp, sql.ToString(), (pageIndex - 1) * pageSize+1, pageIndex * pageSize); + } + + public virtual string GetSelectByItems(List> items) + { + var array = items.Select(it => { + dynamic dynamicObj = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(it.Value)); + var dbName =Builder.GetTranslationColumnName( (string)(dynamicObj.dbName)); + var asName = Builder.GetTranslationColumnName((string)(dynamicObj.asName)); + return string.Format("{0}.{1} AS {2}",it.Key,dbName,asName); + }); + return string.Join(",",array); + } + + public virtual string ToJoinString(JoinQueryInfo joinInfo) + { + return string.Format( + this.JoinTemplate, + joinInfo.JoinType.ToString() + UtilConstants.Space, + Builder.GetTranslationTableName(joinInfo.TableName) + UtilConstants.Space, + joinInfo.ShortName + UtilConstants.Space + TableWithString, + joinInfo.JoinWhere); + } + public virtual void Clear() + { + this.Skip = 0; + this.Take = 0; + this.sql = null; + this.WhereIndex = 0; + this.Parameters = null; + this.GroupByValue = null; + this._TableNameString = null; + this.WhereInfos = null; + this.JoinQueryInfos = null; + this.IsDistinct = false; + } + public virtual bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS \[\w+\.\w+\]"); + } + #endregion + + #region Get SQL Partial + public virtual string GetSelectValue + { + get + { + string result = string.Empty; + if (this.SelectValue == null || this.SelectValue is string) + { + result = GetSelectValueByString(); + } + else + { + result = GetSelectValueByExpression(); + } + if (this.SelectType == ResolveExpressType.SelectMultiple) + { + this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this._JoinQueryInfos.Select(it => it.TableName)); + } + if (IsDistinct) + { + result = " DISTINCT " + result; + } + return result; + } + } + public virtual string GetSelectValueByExpression() + { + var expression = this.SelectValue as Expression; + var result = GetExpressionValue(expression, this.SelectType).GetResultString(); + if (result.Contains(".*") && this.IsSingle()) + { + return "*"; + } + else + { + this.SelectCacheKey = result; + return result; + } + } + public virtual string GetSelectValueByString() + { + string result; + if (this.SelectValue.IsNullOrEmpty()) + { + string pre = null; + if (this.JoinQueryInfos.HasValue() && this.JoinQueryInfos.Any(it => TableShortName.HasValue())) + { + pre = Builder.GetTranslationColumnName(TableShortName) + "."; + } + result = string.Join(",", this.Context.EntityMaintenance.GetEntityInfo(this.EntityType).Columns.Where(it => !it.IsIgnore).Select(it => pre + Builder.GetTranslationColumnName(it.EntityName, it.PropertyName))); + } + else + { + result = this.SelectValue.ObjToString(); + this.SelectCacheKey = result; + } + if (result.IsNullOrEmpty()) + { + result = "*"; + } + return result; + } + public virtual string GetWhereValueString + { + get + { + if (this.WhereInfos == null) return null; + else + { + return string.Join(UtilConstants.Space, this.WhereInfos); + } + } + } + public virtual string GetJoinValueString + { + get + { + if (this.JoinQueryInfos.IsNullOrEmpty()) return null; + else + { + return string.Join(UtilConstants.Space, this.JoinQueryInfos.Select(it => this.ToJoinString(it))); + } + } + } + public virtual string GetTableNameString + { + get + { + var result = Builder.GetTranslationTableName(EntityName); + result += UtilConstants.Space; + if (this.TableShortName.HasValue()) + { + result += (TableShortName + UtilConstants.Space); + } + if (this.TableWithString.HasValue()&&this.TableWithString!= SqlWith.Null) + { + result += TableWithString + UtilConstants.Space; + } + if (!this.IsSingle()) + { + result += GetJoinValueString + UtilConstants.Space; + } + if (this.EasyJoinInfos.IsValuable()) + { + + if (this.TableWithString.HasValue() && this.TableWithString != SqlWith.Null) + { + result += "," + string.Join(",", this.EasyJoinInfos.Select(it => string.Format("{0} {1} {2} ", GetTableName(it.Value), it.Key, TableWithString))); + } + else + { + result += "," + string.Join(",", this.EasyJoinInfos.Select(it => string.Format("{0} {1} ", GetTableName(it.Value), it.Key))); + } + } + return result; + } + } + public virtual string GetOrderByString + { + get + { + if (this.OrderByValue == null) return null; + if (IsCount&&this.PartitionByValue.IsNullOrEmpty()) return null; + else + { + return this.OrderByValue; + } + } + } + public virtual string GetGroupByString + { + get + { + if (this.GroupByValue == null) return null; + if (this.GroupByValue.Last() != ' ' ) + { + return this.GroupByValue + UtilConstants.Space; + } + return this.GroupByValue; + } + } + + #endregion + + private string GetTableName(string entityName) + { + var result = this.Context.EntityMaintenance.GetTableName(entityName); + return this.Builder.GetTranslationTableName(result); + } + + public void CheckExpression(Expression expression, string methodName) + { + if (IsSingle() == false&& this.JoinExpression!=null) + { + var jsoinParameters = (this.JoinExpression as LambdaExpression).Parameters; + var currentParametres = (expression as LambdaExpression).Parameters; + if ((expression as LambdaExpression).Body.ToString() == "True") { + return; + } + if (currentParametres != null && currentParametres.Count > 0) + { + foreach (var item in currentParametres) + { + var index = currentParametres.IndexOf(item); + var name = item.Name; + var joinName = jsoinParameters[index].Name; + Check.Exception(name.ToLower() != joinName.ToLower(), ErrorMessage.ExpressionCheck, joinName, methodName, name); + } + } + } + } + } +} diff --git a/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderAccessory.cs b/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderAccessory.cs new file mode 100644 index 0000000..dd14e8e --- /dev/null +++ b/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderAccessory.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial class SqlBuilderAccessory + { + protected DeleteBuilder _DeleteBuilder; + + protected InsertBuilder _InsertBuilder; + + protected QueryBuilder _QueryBuilder; + + protected SqlQueryBuilder _SqlQueryBuilder; + + protected UpdateBuilder _UpdateBuilder; + } +} diff --git a/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs b/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs new file mode 100644 index 0000000..40b183a --- /dev/null +++ b/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlBuilderProvider.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +namespace SqlSugar +{ + public abstract partial class SqlBuilderProvider : SqlBuilderAccessory, ISqlBuilder + { + #region Properties + public SqlSugarClient Context { get; set; } + public CommandType CommandType { get; set; } + public DeleteBuilder DeleteBuilder { get; set; } + public InsertBuilder InsertBuilder { get; set; } + public QueryBuilder QueryBuilder { get; set; } + public UpdateBuilder UpdateBuilder { get; set; } + public SqlQueryBuilder SqlQueryBuilder + { + get + { + base._SqlQueryBuilder = UtilMethods.IsNullReturnNew(base._SqlQueryBuilder); + return base._SqlQueryBuilder; + } + set { base._SqlQueryBuilder = value; } + } + #endregion + + #region abstract Methods + public virtual string GetTranslationTableName(string name) + { + Check.ArgumentNullException(name, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + if (name.IsContainsIn("(", ")", SqlTranslationLeft)&&name!= "Dictionary`2") + { + return name; + } + var context = this.Context; + var mappingInfo = context + .MappingTables + .FirstOrDefault(it => it.EntityName.Equals(name, StringComparison.CurrentCultureIgnoreCase)); + name = (mappingInfo == null ? name : mappingInfo.DbTableName); + if (name.IsContainsIn("(", ")", SqlTranslationLeft)) + { + return name; + } + if (name.Contains(".")) + { + return string.Join(".", name.Split('.').Select(it => SqlTranslationLeft + it + SqlTranslationRight)); + } + else + { + return SqlTranslationLeft + name + SqlTranslationRight; + } + } + public virtual string GetTranslationColumnName(string entityName, string propertyName) + { + Check.ArgumentNullException(entityName, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + Check.ArgumentNullException(propertyName, string.Format(ErrorMessage.ObjNotExist, "Column Name")); + var context = this.Context; + var mappingInfo = context + .MappingColumns + .FirstOrDefault(it => + it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase) && + it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + return (mappingInfo == null ? SqlTranslationLeft + propertyName + SqlTranslationRight : SqlTranslationLeft + mappingInfo.DbColumnName + SqlTranslationRight); + } + + public virtual string GetTranslationColumnName(string propertyName) + { + if (propertyName.Contains(SqlTranslationLeft)) return propertyName; + else + return SqlTranslationLeft + propertyName + SqlTranslationRight; + } + + public virtual string GetNoTranslationColumnName(string name) + { + if (name.Contains("=")) + { + name=name.Split('=').First(); + } + if (!name.Contains(SqlTranslationLeft)) return name; + return name == null ? string.Empty : Regex.Match(name, @".*" + "\\" + SqlTranslationLeft + "(.*?)" + "\\" + SqlTranslationRight + "").Groups[1].Value; + } + public virtual string GetPackTable(string sql, string shortName) + { + return UtilMethods.GetPackTable(sql, shortName); + } + public virtual string GetDefaultShortName() + { + return "t"; + } + + + public string GetWhere(string fieldName,string conditionalType,int? parameterIndex=null) + { + return string.Format(" {0} {1} {2}{3} ",fieldName,conditionalType,this.SqlParameterKeyWord,fieldName+ parameterIndex); + } + public virtual string GetUnionAllSql(List sqlList) + { + return string.Join(" UNION ALL \r\n", sqlList); + } + public virtual string GetUnionSql(List sqlList) + { + return string.Join(" UNION \r\n", sqlList); + } + public virtual void RepairReplicationParameters(ref string appendSql, SugarParameter[] parameters, int addIndex) + { + UtilMethods.RepairReplicationParameters(ref appendSql, parameters, addIndex); + } + #endregion + + #region Common SqlTemplate + public string AppendWhereOrAnd(bool isWhere, string sqlString) + { + return isWhere ? (" WHERE " + sqlString) : (" AND " + sqlString); + } + public string AppendHaving(string sqlString) + { + return " HAVING " + sqlString; + } + public virtual string SqlParameterKeyWord { get { return "@"; } } + public abstract string SqlTranslationLeft { get; } + public abstract string SqlTranslationRight { get; } + public virtual string SqlFalse { get { return "1=2 "; } } + public virtual string SqlDateNow { get { return "GETDATE()"; } } + public virtual string FullSqlDateNow { get { return "SELECT GETDATE()"; } } + public virtual string SqlSelectAll { get { return "*"; } } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlQueryBuilder.cs b/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlQueryBuilder.cs new file mode 100644 index 0000000..de1ebe3 --- /dev/null +++ b/类库/SqlSugar/Abstract/SqlBuilderProvider/SqlQueryBuilder.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class SqlQueryBuilder : IDMLBuilder + { + + #region Fields + private string _Fields; + private StringBuilder _Sql; + private List _Parameters; + #endregion + + #region Properties + public SqlSugarClient Context { get; set; } + public string Fields + { + get + { + if (this._Fields.IsNullOrEmpty()) + { + this._Fields = Regex.Match(this.sql.ObjToString().Replace("\n", string.Empty).Replace("\r", string.Empty).Trim(), @"select(.*?)from", RegexOptions.IgnoreCase).Groups[1].Value; + if (this._Fields.IsNullOrEmpty()) + { + this._Fields = "*"; + } + } + return this._Fields; + } + set + { + _Fields = value; + } + } + public StringBuilder sql + { + get + { + _Sql = UtilMethods.IsNullReturnNew(_Sql); + return _Sql; + } + set + { + _Sql = value; + } + } + public string SqlTemplate + { + get + { + return null; + } + } + public List Parameters + { + get + { + _Parameters = UtilMethods.IsNullReturnNew(_Parameters); + return _Parameters; + } + set + { + _Parameters = value; + } + } + #endregion + + #region Methods + public string ToSqlString() + { + return sql.ToString(); + } + public void Clear() + { + this.sql = null; + } + #endregion + } +} diff --git a/类库/SqlSugar/Abstract/SqlBuilderProvider/UpdateBuilder.cs b/类库/SqlSugar/Abstract/SqlBuilderProvider/UpdateBuilder.cs new file mode 100644 index 0000000..8dfe265 --- /dev/null +++ b/类库/SqlSugar/Abstract/SqlBuilderProvider/UpdateBuilder.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class UpdateBuilder : IDMLBuilder + { + public UpdateBuilder() + { + this.sql = new StringBuilder(); + this.DbColumnInfoList = new List(); + this.SetValues = new List>(); + this.WhereValues = new List(); + this.Parameters = new List(); + } + public SqlSugarClient Context { get; set; } + public ILambdaExpressions LambdaExpressions { get; set; } + public ISqlBuilder Builder { get; set; } + public StringBuilder sql { get; set; } + public List Parameters { get; set; } + public string TableName { get; set; } + public string TableWithString { get; set; } + public List DbColumnInfoList { get; set; } + public List WhereValues { get; set; } + public List> SetValues { get; set; } + public bool IsNoUpdateNull { get; set; } + public List PrimaryKeys { get; set; } + public bool IsOffIdentity { get; set; } + + public virtual string SqlTemplate + { + get + { + return @"UPDATE {0} SET + {1} {2}"; + + } + } + + public virtual string SqlTemplateBatch + { + get + { + return @"UPDATE S SET {0} FROM {1} S {2} INNER JOIN "; + } + } + + public virtual string SqlTemplateJoin + { + get + { + return @" ( + {0} + + ) T ON {1} + ; "; + } + } + + public virtual string SqlTemplateBatchSet + { + get + { + return "{0} AS {1}"; + } + } + public virtual string SqlTemplateBatchSelect + { + get + { + return "{0} AS {1}"; + } + } + + public virtual string SqlTemplateBatchUnion + { + get + { + return "\t\t\r\nUNION ALL "; + } + } + + public virtual void Clear() + { + + } + public virtual string GetTableNameString + { + get + { + var result = Builder.GetTranslationTableName(TableName); + result += UtilConstants.Space; + if (this.TableWithString.HasValue()) + { + result += TableWithString + UtilConstants.Space; + } + return result; + } + } + public virtual string GetTableNameStringNoWith + { + get + { + var result = Builder.GetTranslationTableName(TableName); + return result; + } + } + + public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType, bool isMapping = true) + { + ILambdaExpressions resolveExpress = this.LambdaExpressions; + this.LambdaExpressions.Clear(); + if (isMapping) + { + resolveExpress.MappingColumns = Context.MappingColumns; + resolveExpress.MappingTables = Context.MappingTables; + resolveExpress.IgnoreComumnList = Context.IgnoreColumns; + resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + } + resolveExpress.Resolve(expression, resolveType); + this.Parameters.AddRange(resolveExpress.Parameters); + var result = resolveExpress.Result; + return result; + } + public virtual string ToSqlString() + { + if (IsNoUpdateNull) + { + DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList(); + } + var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); + var isSingle = groupList.Count() == 1; + if (isSingle) + { + return ToSingleSqlString(groupList); + } + else + { + return TomultipleSqlString(groupList); + } + } + + protected virtual string TomultipleSqlString(List> groupList) + { + Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List need Primary key"); + int pageSize = 200; + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + StringBuilder batchUpdateSql = new StringBuilder(); + while (pageCount >= pageIndex) + { + StringBuilder updateTable = new StringBuilder(); + string setValues = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it => + { + if (SetValues.IsValuable()) + { + var setValue = SetValues.Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName)); + if (setValue != null && setValue.Any()) + { + return setValue.First().Value; + } + } + var result = string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(it.DbColumnName)); + return result; + })); + batchUpdateSql.AppendFormat(SqlTemplateBatch.ToString(), setValues, GetTableNameStringNoWith, TableWithString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + updateTable.Append(SqlTemplateBatchUnion); + } + updateTable.Append("\r\n SELECT " + string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value), Builder.GetTranslationColumnName(it.DbColumnName))))); + ++i; + } + pageIndex++; + updateTable.Append("\r\n"); + string whereString = null; + if (this.WhereValues.HasValue()) + { + foreach (var item in WhereValues) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += item; + } + } + else if (PrimaryKeys.HasValue()) + { + foreach (var item in PrimaryKeys) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(item)); + } + } + batchUpdateSql.AppendFormat(SqlTemplateJoin, updateTable, whereString); + } + return batchUpdateSql.ToString(); + } + + protected virtual string ToSingleSqlString(List> groupList) + { + string columnsString = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it => + { + if (SetValues.IsValuable()) + { + var setValue = SetValues.Where(sv => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName) || sv.Key == Builder.GetTranslationColumnName(it.PropertyName)); + if (setValue != null && setValue.Any()) + { + return setValue.First().Value; + } + } + var result = Builder.GetTranslationColumnName(it.DbColumnName) + "=" + this.Context.Ado.SqlParameterKeyWord + it.DbColumnName; + return result; + })); + string whereString = null; + if (this.WhereValues.HasValue()) + { + foreach (var item in WhereValues) + { + var isFirst = whereString == null; + whereString += (isFirst ? " WHERE " : " AND "); + whereString += item; + } + } + else if (PrimaryKeys.HasValue()) + { + foreach (var item in PrimaryKeys) + { + var isFirst = whereString == null; + whereString += (isFirst ? " WHERE " : " AND "); + whereString += Builder.GetTranslationColumnName(item) + "=" + this.Context.Ado.SqlParameterKeyWord + item; + } + } + return string.Format(SqlTemplate, GetTableNameString, columnsString, whereString); + } + + public virtual object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "N'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "N'" + value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs b/类库/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs new file mode 100644 index 0000000..e9ac54a --- /dev/null +++ b/类库/SqlSugar/Abstract/UpdateProvider/UpdateableProvider.cs @@ -0,0 +1,660 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class UpdateableProvider : IUpdateable where T : class, new() + { + public SqlSugarClient Context { get; internal set; } + public EntityInfo EntityInfo { get; internal set; } + public ISqlBuilder SqlBuilder { get; internal set; } + public UpdateBuilder UpdateBuilder { get; set; } + public IAdo Ado { get { return Context.Ado; } } + public T[] UpdateObjs { get; set; } + public bool UpdateParameterIsNull { get; set; } + public bool IsMappingTable { get { return this.Context.MappingTables != null && this.Context.MappingTables.Any(); } } + public bool IsMappingColumns { get { return this.Context.MappingColumns != null && this.Context.MappingColumns.Any(); } } + public bool IsSingle { get { return this.UpdateObjs.Length == 1; } } + public List MappingColumnList { get; set; } + private List IgnoreColumnNameList { get; set; } + private List WhereColumnList { get; set; } + private bool IsWhereColumns { get; set; } + private bool IsOffIdentity { get; set; } + private bool IsVersionValidation { get; set; } + public MappingTableList OldMappingTableList { get; set; } + public bool IsAs { get; set; } + public bool IsEnableDiffLogEvent { get; set; } + public DiffLogModel diffModel { get; set; } + private Action RemoveCacheFunc { get; set; } + + public virtual int ExecuteCommand() + { + PreToSql(); + AutoRemoveDataCache(); + Check.Exception(UpdateBuilder.WhereValues.IsNullOrEmpty() && GetPrimaryKeys().IsNullOrEmpty(), "You cannot have no primary key and no conditions"); + string sql = UpdateBuilder.ToSqlString(); + ValidateVersion(); + RestoreMapping(); + Before(sql); + var result = this.Ado.ExecuteCommand(sql, UpdateBuilder.Parameters == null ? null : UpdateBuilder.Parameters.ToArray()); + After(sql); + return result; + } + + public bool ExecuteCommandHasChange() + { + return this.ExecuteCommand() > 0; + } + public Task ExecuteCommandAsync() + { + Task result = new Task(() => + { + IUpdateable asyncUpdateable = CopyUpdateable(); + return asyncUpdateable.ExecuteCommand(); + }); + TaskStart(result); + return result; + } + public Task ExecuteCommandHasChangeAsync() + { + Task result = new Task(() => + { + IUpdateable asyncUpdateable = CopyUpdateable(); + return asyncUpdateable.ExecuteCommand() > 0; + }); + TaskStart(result); + return result; + } + public IUpdateable AS(string tableName) + { + var entityName = typeof(T).Name; + IsAs = true; + OldMappingTableList = this.Context.MappingTables; + this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); + if (this.Context.MappingTables.Any(it => it.EntityName == entityName)) + { + this.Context.MappingTables.Add(this.Context.MappingTables.First(it => it.EntityName == entityName).DbTableName, tableName); + } + this.Context.MappingTables.Add(entityName, tableName); + return this; ; + } + public IUpdateable IgnoreColumns(Func ignoreColumMethod) + { + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => !ignoreColumMethod(it.PropertyName)).ToList(); + return this; + } + + public IUpdateable IsEnableUpdateVersionValidation() + { + this.IsVersionValidation = true; + return this; + } + + public IUpdateable EnableDiffLogEvent(object businessData = null) + { + Check.Exception(this.UpdateObjs.HasValue() && this.UpdateObjs.Count() > 1, "DiffLog does not support batch operations"); + diffModel = new DiffLogModel(); + this.IsEnableDiffLogEvent = true; + diffModel.BusinessData = businessData; + diffModel.DiffType = DiffType.update; + return this; + } + + public IUpdateable IgnoreColumns(bool ignoreAllNullColumns, bool isOffIdentity = false) + { + UpdateBuilder.IsOffIdentity = isOffIdentity; + if (this.UpdateBuilder.LambdaExpressions == null) + this.UpdateBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.Context.CurrentConnectionConfig); + this.UpdateBuilder.IsNoUpdateNull = ignoreAllNullColumns; + return this; + } + + public IUpdateable IgnoreColumns(Expression> columns) + { + var ignoreColumns = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it).ToLower()).ToList(); + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => !ignoreColumns.Contains(it.PropertyName.ToLower())).ToList(); + return this; + } + + public IUpdateable ReSetValue(Expression> setValueExpression) + { + Check.Exception(!IsSingle, "Batch operation not supported ReSetValue"); + var expResult = UpdateBuilder.GetExpressionValue(setValueExpression, ResolveExpressType.WhereSingle); + var resultString = Regex.Match(expResult.GetResultString(), @"\((.+)\)").Groups[1].Value; + LambdaExpression lambda = setValueExpression as LambdaExpression; + var expression = lambda.Body; + Check.Exception(!(expression is BinaryExpression), "Expression format error"); + var leftExpression = (expression as BinaryExpression).Left; + Check.Exception(!(leftExpression is MemberExpression), "Expression format error"); + var leftResultString = UpdateBuilder.GetExpressionValue(leftExpression, ResolveExpressType.WhereSingle).GetString(); + UpdateBuilder.SetValues.Add(new KeyValuePair(leftResultString, resultString)); + return this; + } + private void AutoRemoveDataCache() + { + var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (moreSetts != null && moreSetts.IsAutoRemoveDataCache && extService != null && extService.DataInfoCacheService != null) + { + this.RemoveDataCache(); + } + } + public KeyValuePair> ToSql() + { + PreToSql(); + string sql = UpdateBuilder.ToSqlString(); + RestoreMapping(); + return new KeyValuePair>(sql, UpdateBuilder.Parameters); + } + + public IUpdateable WhereColumns(Expression> columns) + { + this.IsWhereColumns = true; + Check.Exception(UpdateParameterIsNull==true, "Updateable().Updateable is error,Use Updateable(obj).WhereColumns"); + var whereColumns = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it)).ToList(); + if (this.WhereColumnList == null) this.WhereColumnList = new List(); + foreach (var item in whereColumns) + { + this.WhereColumnList.Add(item); + } + return this; + } + public IUpdateable WhereColumns(string columnName) + { + if (this.WhereColumnList == null) this.WhereColumnList = new List(); + this.WhereColumnList.Add(columnName); + return this; + } + + public IUpdateable WhereColumns(string [] columnNames) + { + if (this.WhereColumnList == null) this.WhereColumnList = new List(); + foreach (var columnName in columnNames) + { + this.WhereColumnList.Add(columnName); + } + return this; + } + + public IUpdateable UpdateColumns(Expression> columns) + { + var updateColumns = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => this.SqlBuilder.GetNoTranslationColumnName(it)).ToList(); + List primaryKeys = GetPrimaryKeys(); + foreach (var item in this.UpdateBuilder.DbColumnInfoList) + { + var mappingInfo = primaryKeys.SingleOrDefault(i => item.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null && mappingInfo.Any()) + { + item.IsPrimarykey = true; + } + } + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => updateColumns.Any(uc => uc.Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase) || uc.Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase)) || it.IsPrimarykey || it.IsIdentity).ToList(); + return this; + } + + public IUpdateable UpdateColumns(Expression> columns) + { + var binaryExp = columns.Body as BinaryExpression; + Check.Exception(!binaryExp.NodeType.IsIn(ExpressionType.Equal), "No support {0}", columns.ToString()); + Check.Exception(!(binaryExp.Left is MemberExpression) && !(binaryExp.Left is UnaryExpression), "No support {0}", columns.ToString()); + Check.Exception(ExpressionTool.IsConstExpression(binaryExp.Left as MemberExpression), "No support {0}", columns.ToString()); + var expResult = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.WhereSingle).GetResultString().Replace("))", ") )").Replace("((", "( (").Trim().TrimStart('(').TrimEnd(')'); + string key = SqlBuilder.GetNoTranslationColumnName(expResult); + UpdateBuilder.SetValues.Add(new KeyValuePair(SqlBuilder.GetTranslationColumnName(key), expResult)); + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => UpdateBuilder.SetValues.Any(v => SqlBuilder.GetNoTranslationColumnName(v.Key).Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase) || SqlBuilder.GetNoTranslationColumnName(v.Key).Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase)) || it.IsPrimarykey == true).ToList(); + return this; + } + + public IUpdateable UpdateColumns(string[] columns) + { + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => columns.Contains(it.PropertyName, StringComparer.OrdinalIgnoreCase)).ToList(); + return this; + } + + public IUpdateable UpdateColumns(Func updateColumMethod) + { + List primaryKeys = GetPrimaryKeys(); + foreach (var item in this.UpdateBuilder.DbColumnInfoList) + { + var mappingInfo = primaryKeys.SingleOrDefault(i => item.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null && mappingInfo.Any()) + { + item.IsPrimarykey = true; + } + } + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => updateColumMethod(it.PropertyName) || it.IsPrimarykey || it.IsIdentity).ToList(); + return this; + } + public IUpdateable UpdateColumns(Expression> columns) + { + var expResult = UpdateBuilder.GetExpressionValue(columns, ResolveExpressType.Update); + var resultArray = expResult.GetResultArray(); + Check.ArgumentNullException(resultArray, "UpdateColumns Parameter error, UpdateColumns(it=>new T{ it.id=1}) is valid, UpdateColumns(it=>T) is error"); + if (resultArray.HasValue()) + { + foreach (var item in resultArray) + { + string key = SqlBuilder.GetNoTranslationColumnName(item); + UpdateBuilder.SetValues.Add(new KeyValuePair(SqlBuilder.GetTranslationColumnName(key), item)); + } + } + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => UpdateBuilder.SetValues.Any(v => SqlBuilder.GetNoTranslationColumnName(v.Key).Equals(it.DbColumnName, StringComparison.CurrentCultureIgnoreCase) || SqlBuilder.GetNoTranslationColumnName(v.Key).Equals(it.PropertyName, StringComparison.CurrentCultureIgnoreCase)) || it.IsPrimarykey == true).ToList(); + return this; + } + + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, Expression> columns) + { + if (isUpdateColumns) + UpdateColumns(columns); + return this; + } + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, Expression> columns) + { + if (isUpdateColumns) + UpdateColumns(columns); + return this; + } + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, Func updateColumMethod) + { + if (isUpdateColumns) + UpdateColumns(updateColumMethod); + return this; + } + public IUpdateable UpdateColumnsIF(bool isUpdateColumns, Expression> columns) + { + if (isUpdateColumns) + UpdateColumns(columns); + return this; + } + + [Obsolete("Use IUpdateable IgnoreColumns(bool ignoreAllNullColumns, bool isOffIdentity = false);")] + public IUpdateable Where(bool isUpdateNull, bool IsOffIdentity = false) + { + UpdateBuilder.IsOffIdentity = IsOffIdentity; + if (this.UpdateBuilder.LambdaExpressions == null) + this.UpdateBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.Context.CurrentConnectionConfig); + this.UpdateBuilder.IsNoUpdateNull = isUpdateNull; + return this; + } + public IUpdateable Where(Expression> expression) + { + var expResult = UpdateBuilder.GetExpressionValue(expression, ResolveExpressType.WhereSingle); + var whereString = expResult.GetResultString(); + if (expression.ToString().Contains("Subqueryable()")) + { + whereString = whereString.Replace(this.SqlBuilder.GetTranslationColumnName(expression.Parameters.First().Name) + ".", this.SqlBuilder.GetTranslationTableName(this.EntityInfo.DbTableName) + "."); + } + UpdateBuilder.WhereValues.Add(whereString); + return this; + } + + public IUpdateable Where(string whereSql, object parameters = null) + { + if (whereSql.HasValue()) + { + UpdateBuilder.WhereValues.Add(whereSql); + } + if (parameters != null) + { + UpdateBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); + } + return this; + } + + public IUpdateable Where(string fieldName, string conditionalType, object fieldValue) + { + var whereSql = this.SqlBuilder.GetWhere(fieldName, conditionalType, 0); + this.Where(whereSql); + string parameterName = this.SqlBuilder.SqlParameterKeyWord + fieldName + "0"; + this.UpdateBuilder.Parameters.Add(new SugarParameter(parameterName, fieldValue)); + return this; + } + + public IUpdateable With(string lockString) + { + if (this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer) + this.UpdateBuilder.TableWithString = lockString; + return this; + } + + public IUpdateable RemoveDataCache() + { + this.RemoveCacheFunc = () => + { + var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; + CacheSchemeMain.RemoveCache(cacheService, this.Context.EntityMaintenance.GetTableName()); + }; + return this; + } + + internal void Init() + { + this.UpdateBuilder.TableName = EntityInfo.EntityName; + if (IsMappingTable) + { + var mappingInfo = this.Context.MappingTables.SingleOrDefault(it => it.EntityName == EntityInfo.EntityName); + if (mappingInfo != null) + { + this.UpdateBuilder.TableName = mappingInfo.DbTableName; + } + } + Check.Exception(UpdateObjs == null || UpdateObjs.Count() == 0, "UpdateObjs is null"); + int i = 0; + foreach (var item in UpdateObjs) + { + List updateItem = new List(); + var isDic = item is Dictionary; + if (isDic) + { + SetUpdateItemByDic(i, item, updateItem); + } + else + { + SetUpdateItemByEntity(i, item, updateItem); + } + ++i; + } + } + private void SetUpdateItemByDic(int i, T item, List updateItem) + { + foreach (var column in item as Dictionary) + { + var columnInfo = new DbColumnInfo() + { + Value = column.Value, + DbColumnName = column.Key, + PropertyName = column.Key, + PropertyType = column.Value == null ? DBNull.Value.GetType() : UtilMethods.GetUnderType(column.Value.GetType()), + TableId = i + }; + if (columnInfo.PropertyType.IsEnum()) + { + columnInfo.Value = Convert.ToInt64(columnInfo.Value); + } + updateItem.Add(columnInfo); + } + this.UpdateBuilder.DbColumnInfoList.AddRange(updateItem); + } + private void SetUpdateItemByEntity(int i, T item, List updateItem) + { + foreach (var column in EntityInfo.Columns) + { + if (column.IsIgnore) continue; + var columnInfo = new DbColumnInfo() + { + Value = column.PropertyInfo.GetValue(item, null), + DbColumnName = GetDbColumnName(column.PropertyName), + PropertyName = column.PropertyName, + PropertyType = UtilMethods.GetUnderType(column.PropertyInfo), + TableId = i + }; + if (columnInfo.PropertyType.IsEnum()) + { + columnInfo.Value = Convert.ToInt64(columnInfo.Value); + } + updateItem.Add(columnInfo); + } + this.UpdateBuilder.DbColumnInfoList.AddRange(updateItem); + } + + private void PreToSql() + { + UpdateBuilder.PrimaryKeys = GetPrimaryKeys(); + if (this.IsWhereColumns) { + foreach (var pkName in UpdateBuilder.PrimaryKeys) + { + var isContains=this.UpdateBuilder.DbColumnInfoList.Select(it => it.DbColumnName.ToLower()).Contains(pkName.ToLower()); + Check.Exception(isContains == false, "Use UpdateColumns().WhereColumn() ,UpdateColumns need {0}", pkName); + } + } + #region IgnoreColumns + if (this.Context.IgnoreColumns != null && this.Context.IgnoreColumns.Any()) + { + var currentIgnoreColumns = this.Context.IgnoreColumns.Where(it => it.EntityName == this.EntityInfo.EntityName).ToList(); + this.UpdateBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList.Where(it => + { + return !currentIgnoreColumns.Any(i => it.PropertyName.Equals(i.PropertyName, StringComparison.CurrentCulture)); + }).ToList(); + } + #endregion + if (this.IsSingle) + { + foreach (var item in this.UpdateBuilder.DbColumnInfoList) + { + if (this.UpdateBuilder.Parameters == null) this.UpdateBuilder.Parameters = new List(); + if (this.UpdateBuilder.SetValues.Any(it => this.SqlBuilder.GetNoTranslationColumnName(it.Key) == item.PropertyName)) + { + continue; + } + this.UpdateBuilder.Parameters.Add(new SugarParameter(this.SqlBuilder.SqlParameterKeyWord + item.DbColumnName, item.Value, item.PropertyType)); + } + } + + #region Identities + List identities = GetIdentityKeys(); + if (identities != null && identities.Any()) + { + this.UpdateBuilder.DbColumnInfoList.ForEach(it => + { + var mappingInfo = identities.SingleOrDefault(i => it.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null && mappingInfo.Any()) + { + it.IsIdentity = true; + } + }); + } + #endregion + List primaryKey = GetPrimaryKeys(); + if (primaryKey != null && primaryKey.Count > 0) + { + this.UpdateBuilder.DbColumnInfoList.ForEach(it => + { + var mappingInfo = primaryKey.SingleOrDefault(i => it.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null && mappingInfo.Any()) + { + it.IsPrimarykey = true; + } + }); + } + if (this.UpdateBuilder.Parameters.HasValue() && this.UpdateBuilder.SetValues.IsValuable()) + { + this.UpdateBuilder.Parameters.RemoveAll(it => this.UpdateBuilder.SetValues.Any(v => (SqlBuilder.SqlParameterKeyWord + SqlBuilder.GetNoTranslationColumnName(v.Key)) == it.ParameterName)); + } + } + private string GetDbColumnName(string propertyName) + { + if (!IsMappingColumns) + { + return propertyName; + } + if (this.Context.MappingColumns.Any(it => it.EntityName.Equals(EntityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase))) + { + this.MappingColumnList = this.Context.MappingColumns.Where(it => it.EntityName.Equals(EntityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase)).ToList(); + } + if (MappingColumnList == null || !MappingColumnList.Any()) + { + return propertyName; + } + else + { + var mappInfo = this.MappingColumnList.FirstOrDefault(it => it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + return mappInfo == null ? propertyName : mappInfo.DbColumnName; + } + } + private List GetPrimaryKeys() + { + if (this.WhereColumnList.HasValue()) + { + return this.WhereColumnList; + } + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); + } + } + protected virtual List GetIdentityKeys() + { + if (this.Context.IsSystemTablesConfig) + { + return this.Context.DbMaintenance.GetIsIdentities(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); + } + else + { + return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); + } + } + private void RestoreMapping() + { + if (IsAs) + { + this.Context.MappingTables = OldMappingTableList; + } + } + private void TaskStart(Task result) + { + if (this.Context.CurrentConnectionConfig.IsShardSameThread) + { + Check.Exception(true, "IsShardSameThread=true can't be used async method"); + } + result.Start(); + } + private IUpdateable CopyUpdateable() + { + var asyncContext = this.Context.Utilities.CopyContext(true); + asyncContext.CurrentConnectionConfig.IsAutoCloseConnection = true; + asyncContext.IsAsyncMethod = true; + + var asyncUpdateable = asyncContext.Updateable(this.UpdateObjs); + var asyncUpdateableBuilder = asyncUpdateable.UpdateBuilder; + asyncUpdateableBuilder.DbColumnInfoList = this.UpdateBuilder.DbColumnInfoList; + asyncUpdateableBuilder.IsNoUpdateNull = this.UpdateBuilder.IsNoUpdateNull; + asyncUpdateableBuilder.Parameters = this.UpdateBuilder.Parameters; + asyncUpdateableBuilder.sql = this.UpdateBuilder.sql; + asyncUpdateableBuilder.WhereValues = this.UpdateBuilder.WhereValues; + asyncUpdateableBuilder.TableWithString = this.UpdateBuilder.TableWithString; + asyncUpdateableBuilder.TableName = this.UpdateBuilder.TableName; + asyncUpdateableBuilder.PrimaryKeys = this.UpdateBuilder.PrimaryKeys; + asyncUpdateableBuilder.IsOffIdentity = this.UpdateBuilder.IsOffIdentity; + asyncUpdateableBuilder.SetValues = this.UpdateBuilder.SetValues; + if (this.RemoveCacheFunc != null) + { + asyncUpdateable.RemoveDataCache(); + } + return asyncUpdateable; + } + + private void ValidateVersion() + { + var versionColumn = this.EntityInfo.Columns.FirstOrDefault(it => it.IsEnableUpdateVersionValidation); + var pks = this.UpdateBuilder.DbColumnInfoList.Where(it => it.IsPrimarykey).ToList(); + if (versionColumn != null && this.IsVersionValidation) + { + Check.Exception(pks.IsNullOrEmpty(), "UpdateVersionValidation the primary key is required."); + List conModels = new List(); + foreach (var item in pks) + { + conModels.Add(new ConditionalModel() { FieldName = item.DbColumnName, ConditionalType = ConditionalType.Equal, FieldValue = item.Value.ObjToString() }); + } + var dbInfo = this.Context.Queryable().Where(conModels).First(); + if (dbInfo != null) + { + var currentVersion = this.EntityInfo.Type.GetProperty(versionColumn.PropertyName).GetValue(UpdateObjs.Last(), null); + var dbVersion = this.EntityInfo.Type.GetProperty(versionColumn.PropertyName).GetValue(dbInfo, null); + Check.Exception(currentVersion == null, "UpdateVersionValidation entity property {0} is not null", versionColumn.PropertyName); + Check.Exception(dbVersion == null, "UpdateVersionValidation database column {0} is not null", versionColumn.DbColumnName); + if (versionColumn.PropertyInfo.PropertyType.IsIn(UtilConstants.IntType, UtilConstants.LongType)) + { + if (Convert.ToInt64(dbVersion) > Convert.ToInt64(currentVersion)) + { + throw new VersionExceptions(string.Format("UpdateVersionValidation {0} Not the latest version ", versionColumn.PropertyName)); + } + } + else if (versionColumn.PropertyInfo.PropertyType.IsIn(UtilConstants.DateType)) + { + if (dbVersion.ObjToDate() > currentVersion.ObjToDate()) + { + throw new VersionExceptions(string.Format("UpdateVersionValidation {0} Not the latest version ", versionColumn.PropertyName)); + } + } + else if (versionColumn.PropertyInfo.PropertyType.IsIn(UtilConstants.ByteArrayType)) + { + if (UtilMethods.GetLong((byte[])dbVersion) > UtilMethods.GetLong((byte[])currentVersion)) + { + throw new VersionExceptions(string.Format("UpdateVersionValidation {0} Not the latest version ", versionColumn.PropertyName)); + } + } + else + { + Check.ThrowNotSupportedException(string.Format("UpdateVersionValidation Not Supported Type [ {0} ] , {1}", versionColumn.PropertyInfo.PropertyType, versionColumn.PropertyName)); + } + } + } + } + private void After(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var parameters = UpdateBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.AfterData = GetDiffTable(sql, parameters); + diffModel.Time = this.Context.Ado.SqlExecutionTime; + if (this.Context.Ado.DiffLogEvent != null) + this.Context.Ado.DiffLogEvent(diffModel); + } + if (this.RemoveCacheFunc != null) { + this.RemoveCacheFunc(); + } + } + + private void Before(string sql) + { + if (this.IsEnableDiffLogEvent) + { + var parameters = UpdateBuilder.Parameters; + if (parameters == null) + parameters = new List(); + diffModel.BeforeData = GetDiffTable(sql, parameters); + diffModel.Sql = sql; + diffModel.Parameters = parameters.ToArray(); + } + } + + private List GetDiffTable(string sql, List parameters) + { + List result = new List(); + var whereSql = Regex.Replace(sql, ".* WHERE ", "", RegexOptions.Singleline); + var dt = this.Context.Queryable().Where(whereSql).AddParameters(parameters).ToDataTable(); + if (dt.Rows != null && dt.Rows.Count > 0) + { + foreach (DataRow row in dt.Rows) + { + DiffLogTableInfo item = new DiffLogTableInfo(); + item.TableDescription = this.EntityInfo.TableDescription; + item.TableName = this.EntityInfo.DbTableName; + item.Columns = new List(); + foreach (DataColumn col in dt.Columns) + { + DiffLogColumnInfo addItem = new DiffLogColumnInfo(); + addItem.Value = row[col.ColumnName]; + addItem.ColumnName = col.ColumnName; + addItem.ColumnDescription = this.EntityInfo.Columns.First(it => it.DbColumnName.Equals(col.ColumnName, StringComparison.CurrentCultureIgnoreCase)).ColumnDescription; + item.Columns.Add(addItem); + } + result.Add(item); + } + } + return result; + } + } +} diff --git a/类库/SqlSugar/App.config b/类库/SqlSugar/App.config new file mode 100644 index 0000000..3a6488b --- /dev/null +++ b/类库/SqlSugar/App.config @@ -0,0 +1,19 @@ + + + + +
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/SqlSugar/CacheScheme/CacheKeyBuider.cs b/类库/SqlSugar/CacheScheme/CacheKeyBuider.cs new file mode 100644 index 0000000..3168d87 --- /dev/null +++ b/类库/SqlSugar/CacheScheme/CacheKeyBuider.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + internal class CacheKeyBuider + { + public static CacheKey GetKey(SqlSugarClient context, QueryBuilder queryBuilder) + { + CacheKey result = new CacheKey(); + result.Database = context.Context.Ado.Connection.Database; + AddTables(context, queryBuilder, result); + AddIdentificationList(queryBuilder, result); + return result; + } + + private static void AddIdentificationList(QueryBuilder queryBuilder, CacheKey result) + { + result.IdentificationList = new List(); + result.IdentificationList.Add(queryBuilder.GetTableNameString); + result.IdentificationList.Add(queryBuilder.GetJoinValueString); + result.IdentificationList.Add(queryBuilder.GetOrderByString); + result.IdentificationList.Add(queryBuilder.GetGroupByString); + result.IdentificationList.Add(queryBuilder.GetWhereValueString); + result.IdentificationList.Add(queryBuilder.PartitionByValue); + result.IdentificationList.Add(queryBuilder.Take.ObjToString()); + result.IdentificationList.Add(queryBuilder.Skip.ObjToString()); + result.IdentificationList.Add(queryBuilder.IsCount.ObjToString()); + result.IdentificationList.Add(UtilMethods.GetMD5(queryBuilder.GetSelectValue.ObjToString())); + if (queryBuilder.Parameters.HasValue()) + { + foreach (var item in queryBuilder.Parameters) + { + result.IdentificationList.Add(item.ParameterName + "_" + item.Value); + } + } + } + + private static void AddTables(SqlSugarClient context, QueryBuilder queryBuilder, CacheKey result) + { + result.Tables = new List(); + result.Tables.Add(context.EntityMaintenance.GetTableName(queryBuilder.EntityName)); + if (queryBuilder.EasyJoinInfos.HasValue()) + { + foreach (var item in queryBuilder.EasyJoinInfos) + { + result.Tables.Add(context.EntityMaintenance.GetTableName(item.Value)); + } + } + if (queryBuilder.JoinQueryInfos.HasValue()) + { + foreach (var item in queryBuilder.JoinQueryInfos) + { + result.Tables.Add(queryBuilder.Builder.GetNoTranslationColumnName(item.TableName)); + } + } + } + } +} diff --git a/类库/SqlSugar/CacheScheme/CacheSchemeMain.cs b/类库/SqlSugar/CacheScheme/CacheSchemeMain.cs new file mode 100644 index 0000000..449dfd5 --- /dev/null +++ b/类库/SqlSugar/CacheScheme/CacheSchemeMain.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + internal class CacheSchemeMain + { + public static T GetOrCreate(ICacheService cacheService, QueryBuilder queryBuilder, Func getData, int cacheDurationInSeconds, SqlSugarClient context) + { + CacheKey key = CacheKeyBuider.GetKey(context, queryBuilder); + string keyString = key.ToString(); + var result = cacheService.GetOrCreate(keyString, getData, cacheDurationInSeconds); + return result; + } + + public static void RemoveCache(ICacheService cacheService, string tableName) + { + var keys = cacheService.GetAllKey(); + if (keys.HasValue()) + { + foreach (var item in keys) + { + if (item.ToLower().Contains(UtilConstants.Dot + tableName.ToLower() + UtilConstants.Dot)) + { + cacheService.Remove(item); + } + } + } + } + } +} diff --git a/类库/SqlSugar/Entities/CacheKey.cs b/类库/SqlSugar/Entities/CacheKey.cs new file mode 100644 index 0000000..40cd87a --- /dev/null +++ b/类库/SqlSugar/Entities/CacheKey.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class CacheKey + { + public string Database { get; set; } + public List Tables { get; set; } + public List IdentificationList { get; set; } + public new string ToString() + { + return "SqlSugarDataCache" + UtilConstants.Dot + string.Join(UtilConstants.Dot, this.Tables) +UtilConstants.Dot+ string.Join(UtilConstants.Dot, this.IdentificationList.Where(it=>it.HasValue())); + } + } +} diff --git a/类库/SqlSugar/Entities/ConditionalModel.cs b/类库/SqlSugar/Entities/ConditionalModel.cs new file mode 100644 index 0000000..3d58da6 --- /dev/null +++ b/类库/SqlSugar/Entities/ConditionalModel.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public interface IConditionalModel { + + } + public class ConditionalCollections : IConditionalModel + { + public List> ConditionalList { get; set; } + } + + public class ConditionalModel: IConditionalModel + { + public ConditionalModel() + { + this.ConditionalType = ConditionalType.Equal; + } + public string FieldName { get; set; } + public string FieldValue { get; set; } + public ConditionalType ConditionalType { get; set; } + public Func FieldValueConvertFunc { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/ConnMoreSettings.cs b/类库/SqlSugar/Entities/ConnMoreSettings.cs new file mode 100644 index 0000000..61da92d --- /dev/null +++ b/类库/SqlSugar/Entities/ConnMoreSettings.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class ConnMoreSettings + { + public bool IsAutoRemoveDataCache { get; set; } + public bool IsWithNoLockQuery { get; set; } + /// + /// Some MYSQL databases do not support NVarchar set true + /// + public bool MySqlDisableNarvchar { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/ConnectionConfig.cs b/类库/SqlSugar/Entities/ConnectionConfig.cs new file mode 100644 index 0000000..e767f1b --- /dev/null +++ b/类库/SqlSugar/Entities/ConnectionConfig.cs @@ -0,0 +1,103 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class ConnectionConfig + { + /// + ///DbType.SqlServer Or Other + /// + public DbType DbType { get; set; } + /// + ///Database Connection string + /// + public string ConnectionString { get; set; } + /// + /// true does not need to close the connection + /// + public bool IsAutoCloseConnection { get; set; } + /// + /// Default SystemTable,If you do not have system table permissions, use attribute + /// + public InitKeyType InitKeyType = InitKeyType.SystemTable; + /// + ///If true, there is only one connection instance in the same thread within the same connection string + /// + public bool IsShardSameThread { get; set; } + /// + /// Configure External Services replace default services,For example, Redis storage + /// + [JsonIgnore] + public ConfigureExternalServices ConfigureExternalServices = _DefaultServices; + private static ConfigureExternalServices _DefaultServices = new ConfigureExternalServices(); + /// + /// If SlaveConnectionStrings has value,ConnectionString is write operation, SlaveConnectionStrings is read operation. + /// All operations within a transaction is ConnectionString + /// + public List SlaveConnectionConfigs { get; set; } + /// + /// More Gobal Settings + /// + public ConnMoreSettings MoreSettings { get; set; } + /// + /// Used for debugging errors or BUG,Used for debugging, which has an impact on Performance + /// + public SugarDebugger Debugger { get; set; } + } + + public class ConfigureExternalServices + { + + private ISerializeService _SerializeService; + private ICacheService _ReflectionInoCache; + private ICacheService _DataInfoCache; + + public ISerializeService SerializeService + { + get + { + if (_SerializeService == null) + return DefaultServices.Serialize; + else + return _SerializeService; + } + set{ _SerializeService = value;} + } + + public ICacheService ReflectionInoCacheService + { + get + { + if (_ReflectionInoCache == null) + return DefaultServices.ReflectionInoCache; + else + return _ReflectionInoCache; + } + set{_ReflectionInoCache = value;} + } + + public ICacheService DataInfoCacheService + { + get + { + if (_DataInfoCache == null) + return DefaultServices.DataInoCache; + else + return _DataInfoCache; + } + set { _DataInfoCache = value; } + } + + public List SqlFuncServices { get; set; } + public List> AppendDataReaderTypeMappings { get; set; } + + + public Action EntityService{ get; set; } + public Action EntityNameService { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/DbColumnInfo.cs b/类库/SqlSugar/Entities/DbColumnInfo.cs new file mode 100644 index 0000000..3fbd9d3 --- /dev/null +++ b/类库/SqlSugar/Entities/DbColumnInfo.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class DbColumnInfo + { + public string TableName { get; set; } + public int TableId { get; set; } + public string DbColumnName { get; set; } + public string PropertyName { get; set; } + public string DataType { get; set; } + public Type PropertyType { get; set; } + public int Length { get; set; } + public string ColumnDescription { get; set; } + public string DefaultValue { get; set; } + public bool IsNullable { get; set; } + public bool IsIdentity { get; set; } + public bool IsPrimarykey { get; set; } + public object Value { get; set; } + public int DecimalDigits { get; set; } + public int Scale { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/DbResult.cs b/类库/SqlSugar/Entities/DbResult.cs new file mode 100644 index 0000000..fd6aa90 --- /dev/null +++ b/类库/SqlSugar/Entities/DbResult.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DbResult + { + public bool IsSuccess { get; set; } + public Exception ErrorException { get; set; } + public string ErrorMessage { get; set; } + public T Data { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/DbTableInfo.cs b/类库/SqlSugar/Entities/DbTableInfo.cs new file mode 100644 index 0000000..0dd4c70 --- /dev/null +++ b/类库/SqlSugar/Entities/DbTableInfo.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DbTableInfo + { + public string Name { get; set; } + public string Description { get; set; } + public DbObjectType DbObjectType { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/DefaultServices.cs b/类库/SqlSugar/Entities/DefaultServices.cs new file mode 100644 index 0000000..dedca8d --- /dev/null +++ b/类库/SqlSugar/Entities/DefaultServices.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DefaultServices + { + public static ICacheService ReflectionInoCache= new ReflectionInoCacheService(); + public static ICacheService DataInoCache = null; + public static ISerializeService Serialize= new SerializeService(); + } +} \ No newline at end of file diff --git a/类库/SqlSugar/Entities/DiffLogModel.cs b/类库/SqlSugar/Entities/DiffLogModel.cs new file mode 100644 index 0000000..d8ae772 --- /dev/null +++ b/类库/SqlSugar/Entities/DiffLogModel.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class DiffLogModel + { + public List AfterData { get; set; } + public List BeforeData { get; set; } + public SugarParameter[] Parameters { get; set; } + public string Sql { get; set; } + public TimeSpan? Time { get; set; } + public object BusinessData { get; set; } + public DiffType DiffType { get; set; } + } + public class DiffLogTableInfo + { + public string TableName { get; set; } + public string TableDescription { get; set; } + public List Columns { get; set; } + } + public class DiffLogColumnInfo { + + public string ColumnName { get; set; } + public string ColumnDescription { get; set; } + public object Value { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/DiffType.cs b/类库/SqlSugar/Entities/DiffType.cs new file mode 100644 index 0000000..08dc77a --- /dev/null +++ b/类库/SqlSugar/Entities/DiffType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum DiffType + { + insert=0, + update=1, + delete=2 + } +} diff --git a/类库/SqlSugar/Entities/EntityColumnInfo.cs b/类库/SqlSugar/Entities/EntityColumnInfo.cs new file mode 100644 index 0000000..c35cb9d --- /dev/null +++ b/类库/SqlSugar/Entities/EntityColumnInfo.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class EntityColumnInfo + { + public PropertyInfo PropertyInfo { get; set; } + public string PropertyName { get; set; } + public string DbColumnName { get; set; } + public string OldDbColumnName { get; set; } + public int Length { get; set; } + public string ColumnDescription { get; set; } + public string DefaultValue { get; set; } + public bool IsNullable { get; set; } + public bool IsIdentity { get; set; } + public bool IsPrimarykey { get; set; } + public bool IsEnableUpdateVersionValidation { get; set; } + public string EntityName { get; set; } + public string DbTableName { get; set; } + public bool IsIgnore { get; set; } + public string DataType { get; set; } + public int DecimalDigits { get; set; } + public string OracleSequenceName { get; set; } + public bool IsOnlyIgnoreInsert { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/EntityInfo.cs b/类库/SqlSugar/Entities/EntityInfo.cs new file mode 100644 index 0000000..f3241b0 --- /dev/null +++ b/类库/SqlSugar/Entities/EntityInfo.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class EntityInfo + { + private string _DbTableName; + public string EntityName { get; set; } + public string DbTableName { get { return _DbTableName == null ? EntityName : _DbTableName; } set { _DbTableName = value; } } + public string TableDescription { get; set; } + public Type Type { get; set; } + public List Columns { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/JoinQueryInfo.cs b/类库/SqlSugar/Entities/JoinQueryInfo.cs new file mode 100644 index 0000000..a2d4e38 --- /dev/null +++ b/类库/SqlSugar/Entities/JoinQueryInfo.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class JoinQueryInfo + { + public JoinType JoinType{ get; set; } + public string TableName { get; set; } + public string ShortName { get; set; } + public int JoinIndex { get; set; } + public string JoinWhere { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/MapperCache.cs b/类库/SqlSugar/Entities/MapperCache.cs new file mode 100644 index 0000000..083a39e --- /dev/null +++ b/类库/SqlSugar/Entities/MapperCache.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MapperCache + { + private Dictionary caches = new Dictionary(); + private List _list { get; set; } + private SqlSugarClient _context { get; set; } + private MapperCache() + { + } + public MapperCache(List list, SqlSugarClient context) + { + _list = list; + _context = context; + } + public Result Get(Func, Result> action) + { + string key = "Get" + typeof(Result) + action.GetHashCode().ToString(); + if (caches.ContainsKey(key)) + { + return (Result)caches[key]; + } + else + { + var result = action(_list); + caches.Add(key, result); + return result; + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + public List GetListByPrimaryKeys(Func action) where Result : class, new() + { + { + string key = "GetListById" + typeof(Result) + action.GetHashCode().ToString(); + return GetListByPrimaryKeys(action, key); + } + } + private List GetListByPrimaryKeys(Func action, string key) where Result : class, new() + { + if (caches.ContainsKey(key)) + { + return (List)caches[key]; + } + else + { + var ids = _list.Select(action).ToList().Distinct().ToList(); + var result = _context.Queryable().In(ids).ToList(); + caches.Add(key, result); + return result; + } + } + } +} diff --git a/类库/SqlSugar/Entities/Mapping/IgnoreComumn.cs b/类库/SqlSugar/Entities/Mapping/IgnoreComumn.cs new file mode 100644 index 0000000..58cb337 --- /dev/null +++ b/类库/SqlSugar/Entities/Mapping/IgnoreComumn.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class IgnoreColumn + { + public string EntityName { get; set; } + public string PropertyName { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/Mapping/MappingColumn.cs b/类库/SqlSugar/Entities/Mapping/MappingColumn.cs new file mode 100644 index 0000000..85b3ff8 --- /dev/null +++ b/类库/SqlSugar/Entities/Mapping/MappingColumn.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MappingColumn + { + public string PropertyName { get; set; } + public string DbColumnName { get; set; } + public string EntityName { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/Mapping/MappingTable.cs b/类库/SqlSugar/Entities/Mapping/MappingTable.cs new file mode 100644 index 0000000..99b3fd0 --- /dev/null +++ b/类库/SqlSugar/Entities/Mapping/MappingTable.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MappingTable + { + public string EntityName { get; set; } + public string DbTableName { get; set; } + public string DbShortTaleName { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs b/类库/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs new file mode 100644 index 0000000..36e1b36 --- /dev/null +++ b/类库/SqlSugar/Entities/Mapping/SugarMappingAttribute.cs @@ -0,0 +1,125 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System; + +namespace SqlSugar +{ + [AttributeUsage(AttributeTargets.Class, Inherited = true)] + public class SugarTable : Attribute { + private SugarTable() { } + public string TableName { get; set; } + public string TableDescription { get; set; } + public SugarTable(string tableName) { + this.TableName = tableName; + } + public SugarTable(string tableName,string tableDescription) + { + this.TableName = tableName; + this.TableDescription = tableDescription; + } + } + [AttributeUsage(AttributeTargets.Property , Inherited = true)] + public class SugarColumn : Attribute + { + private string _ColumnName; + public string ColumnName + { + get { return _ColumnName; } + set { _ColumnName = value; } + } + + private bool _IsIgnore; + public bool IsIgnore + { + get { return _IsIgnore; } + set { _IsIgnore = value; } + } + + private bool _IsPrimaryKey; + public bool IsPrimaryKey + { + get { return _IsPrimaryKey; } + set { _IsPrimaryKey = value; } + } + + private bool _IsIdentity; + public bool IsIdentity + { + get { return _IsIdentity; } + set { _IsIdentity = value; } + } + + private string _MappingKeys; + public string MappingKeys + { + get { return _MappingKeys; } + set { _MappingKeys = value; } + } + + private string _ColumnDescription; + public string ColumnDescription + { + get { return _ColumnDescription; } + set { _ColumnDescription = value; } + } + + private int _Length ; + public int Length + { + get { return _Length; } + set { _Length = value; } + } + + private bool _IsNullable; + public bool IsNullable + { + get { return _IsNullable; } + set { _IsNullable = value; } + } + + private string _OldColumnName; + public string OldColumnName + { + get { return _OldColumnName; } + set { _OldColumnName = value; } + } + + private string _ColumnDataType; + public string ColumnDataType + { + get { return _ColumnDataType; } + set { _ColumnDataType = value; } + } + + private int _DecimalDigits; + public int DecimalDigits { + get { return _DecimalDigits; } + set { _DecimalDigits = value; } + } + + private string _OracleSequenceName; + public string OracleSequenceName { + get { return _OracleSequenceName; } + set { _OracleSequenceName = value; } + } + + private bool _IsOnlyIgnoreInsert; + public bool IsOnlyIgnoreInsert + { + get { return _IsOnlyIgnoreInsert; } + set { _IsOnlyIgnoreInsert = value; } + } + + + private bool _IsEnableUpdateVersionValidation; + public bool IsEnableUpdateVersionValidation { + get { return _IsEnableUpdateVersionValidation; } + set { _IsEnableUpdateVersionValidation = value; } + } + + + } + +} diff --git a/类库/SqlSugar/Entities/ModelContext.cs b/类库/SqlSugar/Entities/ModelContext.cs new file mode 100644 index 0000000..302b68e --- /dev/null +++ b/类库/SqlSugar/Entities/ModelContext.cs @@ -0,0 +1,23 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class ModelContext + { + [SugarColumn(IsIgnore = true)] + [JsonIgnore] + public SqlSugarClient Context { get; set; } + public ISugarQueryable CreateMapping() where T : class, new() + { + Check.ArgumentNullException(Context, "Please use Sqlugar.ModelContext"); + using (Context) + { + return Context.Queryable(); + } + } + } +} diff --git a/类库/SqlSugar/Entities/PageModel.cs b/类库/SqlSugar/Entities/PageModel.cs new file mode 100644 index 0000000..4d510dc --- /dev/null +++ b/类库/SqlSugar/Entities/PageModel.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class PageModel + { + public int PageIndex { get; set; } + public int PageSize { get; set; } + /// + /// output + /// + public int PageCount { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/SchemaInfo.cs b/类库/SqlSugar/Entities/SchemaInfo.cs new file mode 100644 index 0000000..53f2b29 --- /dev/null +++ b/类库/SqlSugar/Entities/SchemaInfo.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SchemaInfo + { + public string TableName { get; set; } + public string SchemaName { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/SlaveConnectionConfig.cs b/类库/SqlSugar/Entities/SlaveConnectionConfig.cs new file mode 100644 index 0000000..b0d3e64 --- /dev/null +++ b/类库/SqlSugar/Entities/SlaveConnectionConfig.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SlaveConnectionConfig + { + /// + ///Default value is 1 + ///If value is 0 means permanent non execution + /// + public int HitRate = 1; + public string ConnectionString { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/SqlFilter.cs b/类库/SqlSugar/Entities/SqlFilter.cs new file mode 100644 index 0000000..30bed34 --- /dev/null +++ b/类库/SqlSugar/Entities/SqlFilter.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlFilterItem + { + /// + /// Equal to NULL representing global + /// + public string FilterName { get; set; } + public Func FilterValue { get; set; } + /// + /// Is it a multiple table query? + /// + public bool IsJoinQuery { get; set; } + } + + public class SqlFilterResult + { + public string Sql { get; set; } + public object Parameters { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/SqlWith.cs b/类库/SqlSugar/Entities/SqlWith.cs new file mode 100644 index 0000000..0d7876e --- /dev/null +++ b/类库/SqlSugar/Entities/SqlWith.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SqlWith + { + public const string NoLock = "WITH(NOLOCK) "; + public const string HoldLock = "WITH(HOLDLOCK)"; + public const string PagLock = "WITH(PAGLOCK)"; + public const string ReadCommitted = "WITH(READCOMMITTED)"; + public const string TabLockX = "WITH(TABLOCKX)"; + public const string UpdLock = "WITH(UPDLOCK)"; + public const string RowLock = "WITH(ROWLOCK)"; + public const string Null = "Non"; + } +} diff --git a/类库/SqlSugar/Entities/SugarDebugger.cs b/类库/SqlSugar/Entities/SugarDebugger.cs new file mode 100644 index 0000000..7d876a5 --- /dev/null +++ b/类库/SqlSugar/Entities/SugarDebugger.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + /// + /// Used for debugging errors or BUG,Used for debugging, which has an impact on Performance + /// + public class SugarDebugger + { + /// + /// If you use the same Db object across threads, you will be prompted + /// + public bool EnableThreadSecurityValidation { get; set; } + } +} diff --git a/类库/SqlSugar/Entities/SugarList.cs b/类库/SqlSugar/Entities/SugarList.cs new file mode 100644 index 0000000..9098588 --- /dev/null +++ b/类库/SqlSugar/Entities/SugarList.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MappingTableList : List + { + public void Add(string entityName, string dbTableName) + { + this.RemoveAll(it => it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase)); + this.Add(new MappingTable() { EntityName = entityName, DbTableName = dbTableName }); + } + public void Add(string entityName, string dbTableName, string dbTableShortName) + { + this.RemoveAll(it => it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase)); + this.Add(new MappingTable() { EntityName = entityName, DbTableName = dbTableName, DbShortTaleName = dbTableShortName }); + } + public new void Clear() + { + this.RemoveAll(it=>true); + } + } + + public class IgnoreColumnList : List + { + public void Add(string propertyName, string EntityName) + { + this.RemoveAll(it =>it.EntityName==EntityName&&it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + this.Add(new IgnoreColumn() { PropertyName = propertyName, EntityName = EntityName }); + } + + public new void Clear() + { + this.RemoveAll(it => true); + } + } + + public class MappingColumnList : List + { + public void Add(string propertyName, string dbColumnName, string entityName) + { + this.RemoveAll(it =>it.EntityName==entityName &&it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + this.Add(new MappingColumn() { PropertyName = propertyName, DbColumnName = dbColumnName, EntityName = entityName }); + } + public new void Clear() + { + this.RemoveAll(it => true); + } + } +} diff --git a/类库/SqlSugar/Enum/ApplyType.cs b/类库/SqlSugar/Enum/ApplyType.cs new file mode 100644 index 0000000..36a8cb4 --- /dev/null +++ b/类库/SqlSugar/Enum/ApplyType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum ApplyType + { + Cross = 1, + Outer = 2 + } +} diff --git a/类库/SqlSugar/Enum/ConditionalType.cs b/类库/SqlSugar/Enum/ConditionalType.cs new file mode 100644 index 0000000..e998c5e --- /dev/null +++ b/类库/SqlSugar/Enum/ConditionalType.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum ConditionalType + { + Equal=0, + Like=1, + GreaterThan =2, + GreaterThanOrEqual = 3, + LessThan=4, + LessThanOrEqual = 5, + In=6, + NotIn=7, + LikeLeft=8, + LikeRight=9, + NoEqual=10, + IsNullOrEmpty=11, + IsNot=12, + NoLike = 13, + } +} diff --git a/类库/SqlSugar/Enum/DbObjectType.cs b/类库/SqlSugar/Enum/DbObjectType.cs new file mode 100644 index 0000000..affb501 --- /dev/null +++ b/类库/SqlSugar/Enum/DbObjectType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum DbObjectType + { + Table = 0, + View = 1, + All = 2 + } +} diff --git a/类库/SqlSugar/Enum/DbType.cs b/类库/SqlSugar/Enum/DbType.cs new file mode 100644 index 0000000..40e040c --- /dev/null +++ b/类库/SqlSugar/Enum/DbType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum DbType + { + MySql , + SqlServer, + Sqlite, + Oracle, + PostgreSQL + } +} diff --git a/类库/SqlSugar/Enum/InitKeyType.cs b/类库/SqlSugar/Enum/InitKeyType.cs new file mode 100644 index 0000000..55d487e --- /dev/null +++ b/类库/SqlSugar/Enum/InitKeyType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum InitKeyType + { + /// + /// Init primary key and identity key from the system table + /// + SystemTable = 0, + /// + /// Init primary key and identity key from the attribute + /// + Attribute = 1 + } +} diff --git a/类库/SqlSugar/Enum/JoinType.cs b/类库/SqlSugar/Enum/JoinType.cs new file mode 100644 index 0000000..0ee5af8 --- /dev/null +++ b/类库/SqlSugar/Enum/JoinType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum JoinType + { + Inner = 0, + Left = 1, + Right = 2 + } +} diff --git a/类库/SqlSugar/Enum/OrderByType.cs b/类库/SqlSugar/Enum/OrderByType.cs new file mode 100644 index 0000000..4069370 --- /dev/null +++ b/类库/SqlSugar/Enum/OrderByType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum OrderByType + { + Asc = 0, + Desc = 1 + } +} diff --git a/类库/SqlSugar/Enum/ProperyType.cs b/类库/SqlSugar/Enum/ProperyType.cs new file mode 100644 index 0000000..525d252 --- /dev/null +++ b/类库/SqlSugar/Enum/ProperyType.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum CSharpDataType + { + @int, + @bool, + @string, + @DateTime, + @decimal, + @double, + @Guid, + @byte, + @enum, + @short, + @long, + @object, + @other, + @byteArray, + @float, + @time, + @DateTimeOffset, + @Single + } +} diff --git a/类库/SqlSugar/Enum/WhereType.cs b/类库/SqlSugar/Enum/WhereType.cs new file mode 100644 index 0000000..c49492a --- /dev/null +++ b/类库/SqlSugar/Enum/WhereType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public enum WhereType + { + And=0, + Or=1 + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/CaseWhen/CaseWhen.cs b/类库/SqlSugar/ExpressionsToSql/CaseWhen/CaseWhen.cs new file mode 100644 index 0000000..3e74788 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/CaseWhen/CaseWhen.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class CaseWhen + { + public CaseThen ElseIF(bool condition) + { + return null; + } + public T End(T defaultValue) + { + return default(T); + } + } + public class CaseThen + { + + public CaseWhen Return(T result) + { + return null; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/CaseWhen/CaseWhenResolve.cs b/类库/SqlSugar/ExpressionsToSql/CaseWhen/CaseWhenResolve.cs new file mode 100644 index 0000000..94b92c3 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/CaseWhen/CaseWhenResolve.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + + public class CaseWhenResolve + { + List allMethods = new List(); + private ExpressionContext context = null; + public CaseWhenResolve(MethodCallExpression expression, ExpressionContext context, Expression oppsiteExpression) + { + this.context = context; + var currentExpression = expression; + allMethods.Add(currentExpression); + if (context.IsSingle && oppsiteExpression != null&& oppsiteExpression is MemberExpression) + { + var childExpression = (oppsiteExpression as MemberExpression).Expression; + this.context.SingleTableNameSubqueryShortName = (childExpression as ParameterExpression).Name; + } + else if (context.IsSingle) + { + this.context.SingleTableNameSubqueryShortName = (context.Expression as LambdaExpression).Parameters.First().Name; + } + while (currentExpression != null) + { + var addItem = currentExpression.Object as MethodCallExpression; + if (addItem != null) + allMethods.Add(addItem); + currentExpression = addItem; + } + } + + public string GetSql() + { + allMethods.Reverse(); + List> sqls = new List>(); + foreach (var methodExp in allMethods) + { + var isFirst = allMethods.First() == methodExp; + var isLast= allMethods.Last() == methodExp; + var sql= SubTools.GetMethodValue(this.context, methodExp.Arguments[0],this.context.IsSingle?ResolveExpressType.WhereSingle:ResolveExpressType.WhereMultiple); + sqls.Add(new KeyValuePair(methodExp.Method.Name, sql)); + } + var result= this.context.DbMehtods.CaseWhen(sqls); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/BinaryExpressionInfo.cs b/类库/SqlSugar/ExpressionsToSql/Common/BinaryExpressionInfo.cs new file mode 100644 index 0000000..a35b85f --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/BinaryExpressionInfo.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class BinaryExpressionInfo + { + public bool IsLeft { get; set; } + public Type ExpressionType { get;set;} + public object Value { get; set; } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/CommonTempDataType.cs b/类库/SqlSugar/ExpressionsToSql/Common/CommonTempDataType.cs new file mode 100644 index 0000000..989deec --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/CommonTempDataType.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public enum CommonTempDataType + { + Default = 0, + Result = 1, + Append=2, + Simple = 3 + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/DateType.cs b/类库/SqlSugar/ExpressionsToSql/Common/DateType.cs new file mode 100644 index 0000000..6de1122 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/DateType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public enum DateType + { + Year = 1, + Month = 2, + Day =3, + Hour = 4, + Second=5, + Minute=6, + Millisecond=7 + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/ErrorMessage.cs b/类库/SqlSugar/ExpressionsToSql/Common/ErrorMessage.cs new file mode 100644 index 0000000..ff90336 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/ErrorMessage.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + internal static partial class ErrorMessage + { + internal static string OperatorError + { + get + { + return ErrorMessage.GetThrowMessage("Lambda parsing error: {0} does not support the operator to find!","拉姆达解析出错:不支持{0}此种运算符查找!"); + } + } + internal static string ExpFileldError + { + get + { + return ErrorMessage.GetThrowMessage("Expression format error, correct format: it=>it.fieldName","表达式格式错误,正确格式: it=>it.fieldName"); + } + } + + internal static string MethodError + { + get + { + return ErrorMessage.GetThrowMessage("Expression parsing does not support the current function {0}. There are many functions available in the SqlFunc class, for example, it=>SqlFunc.HasValue(it.Id)", "拉姆达解析不支持当前函数{0},SqlFunc这个类里面有大量函数可用,也许有你想要的,例如: it=>SqlFunc.HasValue(it.Id)"); + } + } + + public static string ConnnectionOpen + { + get + { + return ErrorMessage.GetThrowMessage("Connection open error . {0}", " 连接数据库过程中发生错误,检查服务器是否正常连接字符串是否正确,实在找不到原因请先Google错误信息:{0}."); + } + } + public static string ExpressionCheck + { + get + { + return ErrorMessage.GetThrowMessage("Join {0} needs to be the same as {1} {2}", "多表查询存在别名不一致,请把{1}中的{2}改成{0}就可以了,特殊需求可以使用.Select((x,y)=>new{{ id=x.id,name=y.name}}).MergeTable().Orderby(xxx=>xxx.Id)功能将Select中的多表结果集变成单表,这样就可以不限制别名一样"); + } + } + + public static string WhereIFCheck + { + get + { + return ErrorMessage.GetThrowMessage("Subquery.WhereIF.IsWhere {0} not supported", "Subquery.WhereIF 第一个参数不支持表达式中的变量,只支持外部变量"); + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/ExpResolveAccessory.cs b/类库/SqlSugar/ExpressionsToSql/Common/ExpResolveAccessory.cs new file mode 100644 index 0000000..d7fe5a1 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/ExpResolveAccessory.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class ExpResolveAccessory + { + protected List _Parameters; + protected ExpressionResult _Result; + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/ExpressionConst.cs b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionConst.cs new file mode 100644 index 0000000..bbc5f94 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionConst.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + internal class ExpressionConst + { + public const string Const = "Const"; + public const string FormatSymbol = "{0}"; + public const string RightParenthesis = ")"; + public const string LeftParenthesis = "("; + public const string MethodConst = "MethodConst"; + public const string SqlFuncFullName = "SqlSugar.SqlFunc"; + public const string BinaryFormatString = " ( {0} {1} {2} ) "; + public const string ExpressionReplace = "46450BDC-77B7-4025-B2A6-3F048CA85AD0"; + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/ExpressionParameter.cs b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionParameter.cs new file mode 100644 index 0000000..39638e4 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionParameter.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class ExpressionParameter + { + public ExpressionContext Context { get; set; } + public ExpressionParameter BaseParameter { get; set; } + public Expression BaseExpression { get; set; } + public Expression ChildExpression { get; set; } + public Expression LeftExpression { get; set; } + public Expression RightExpression { get; set; } + public Expression CurrentExpression { get; set; } + public string OperatorValue { get; set; } + public bool? IsLeft { get; set; } + public int Index { get; set; } + public bool ValueIsNull { get; set; } + public object CommonTempData { get; set; } + public ExpressionResultAppendType AppendType { get; set; } + public void IsAppendResult() + { + this.AppendType = ExpressionResultAppendType.AppendResult; + } + public void IsAppendTempDate() + { + this.AppendType = ExpressionResultAppendType.AppendTempDate; + } + public Expression OppsiteExpression + { + get + { + return this.IsLeft == true ? this.BaseParameter.RightExpression : this.BaseParameter.LeftExpression; + } + } + public bool IsSetTempData + { + get + { + return BaseParameter.CommonTempData.HasValue() && BaseParameter.CommonTempData.Equals(CommonTempDataType.Result); + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/ExpressionResult.cs b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionResult.cs new file mode 100644 index 0000000..316e715 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionResult.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class ExpressionResult + { + public bool IsLockCurrentParameter { get; set; } + public bool IsUpper { get; set; } + private ExpressionParameter _CurrentParameter; + public ExpressionParameter CurrentParameter + { + get + { + return this._CurrentParameter; + } + set + { + Check.Exception(value != null && IsLockCurrentParameter, "CurrentParameter is locked."); + this._CurrentParameter = value; + this.IsLockCurrentParameter = false; + } + } + #region constructor + private ExpressionResult() + { + } + public ExpressionResult(ResolveExpressType resolveExpressType) + { + this._ResolveExpressType = resolveExpressType; + } + #endregion + + #region Fields + private ResolveExpressType _ResolveExpressType; + private StringBuilder _Result; + #endregion + + #region properties + private StringBuilder Result + { + get + { + if (_Result == null) _Result = new StringBuilder(); + return _Result; + } + + set + { + _Result = value; + } + } + public bool LastCharIsSpace{ + get { + if (_Result == null|| _Result.Length==0) return true; + return _Result.ToString().Last() == UtilConstants.SpaceChar; + } + } + #endregion + public string GetString() + { + if (_Result == null) return null; + if (IsUpper) + return _Result.ToString().ToUpper().Replace(UtilConstants.ReplaceCommaKey,",").TrimEnd(','); + else + return _Result.ToString().Replace(UtilConstants.ReplaceCommaKey, ",").TrimEnd(','); + } + #region functions + public string[] GetResultArray() + { + if (this._Result == null) return null; + var reslut = new List(); + + if (IsUpper) + reslut= this.Result.ToString().ToUpper().TrimEnd(',').Split(',').ToList(); + else + reslut= this.Result.ToString().TrimEnd(',').Split(',').ToList(); + + if (this.Result.ToString().Contains(UtilConstants.ReplaceCommaKey)) + { + for (int i = 0; i < reslut.Count; i++) + { + reslut[i] = reslut[i].Replace(UtilConstants.ReplaceCommaKey, ","); + } + } + return reslut.ToArray(); + } + + public string GetResultString() + { + if (this._Result == null) return null; + if (this._ResolveExpressType.IsIn(ResolveExpressType.SelectMultiple, ResolveExpressType.SelectSingle)) + { + return this.Result.ToString().Replace(UtilConstants.ReplaceCommaKey, ",").TrimEnd(','); + } + if (IsUpper) + return this.Result.ToString().Replace(UtilConstants.ReplaceCommaKey, ",").ToUpper(); + else + return this.Result.ToString().Replace(UtilConstants.ReplaceCommaKey, ","); + } + + public void TrimEnd() + { + if (this._Result == null) return; + this.Result = this.Result.Remove(this.Result.Length - 1, 1); + } + + public bool Contains(string value) + { + if (this.Result.Equals(value)) return true; + return (this.Result.ToString().Contains(value)); + } + + internal void Insert(int index, string value) + { + if (this.Result == null) this.Result.Append(value); + this.Result.Insert(index, value); + } + + public void Append(object parameter) + { + if (this.CurrentParameter.HasValue() && this.CurrentParameter.AppendType.IsIn(ExpressionResultAppendType.AppendTempDate)) + { + this.CurrentParameter.CommonTempData = parameter; + return; + } + switch (this._ResolveExpressType) + { + case ResolveExpressType.ArraySingle: + case ResolveExpressType.ArrayMultiple: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + parameter = parameter + ","; + break; + case ResolveExpressType.WhereSingle: + break; + case ResolveExpressType.WhereMultiple: + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + default: + break; + } + this.Result.Append(parameter); + } + + public void AppendFormat(string parameter, params object[] orgs) + { + if (this.CurrentParameter.HasValue() && this.CurrentParameter.AppendType.IsIn(ExpressionResultAppendType.AppendTempDate)) + { + this.CurrentParameter.CommonTempData = new KeyValuePair(parameter, orgs); + return; + } + switch (this._ResolveExpressType) + { + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + parameter = parameter + ","; + break; + case ResolveExpressType.WhereSingle: + break; + case ResolveExpressType.WhereMultiple: + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + default: + break; + } + this.Result.AppendFormat(parameter, orgs); + } + + public void Replace(string parameter, string newValue) + { + this.Result.Replace(parameter, newValue); + } + #endregion + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/ExpressionResultAcceptType.cs b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionResultAcceptType.cs new file mode 100644 index 0000000..5fe72fd --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionResultAcceptType.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public enum ExpressionResultAppendType + { + AppendResult=0, + AppendTempDate=1 + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs new file mode 100644 index 0000000..f9bcf07 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/ExpressionTool.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public class ExpressionTool + { + public static string GetOperator(ExpressionType expressiontype) + { + switch (expressiontype) + { + case ExpressionType.And: + case ExpressionType.AndAlso: + return "AND"; + case ExpressionType.Equal: + return "="; + case ExpressionType.GreaterThan: + return ">"; + case ExpressionType.GreaterThanOrEqual: + return ">="; + case ExpressionType.LessThan: + return "<"; + case ExpressionType.LessThanOrEqual: + return "<="; + case ExpressionType.NotEqual: + return "<>"; + case ExpressionType.Or: + case ExpressionType.OrElse: + return "OR"; + case ExpressionType.Add: + case ExpressionType.AddChecked: + return "+"; + case ExpressionType.Subtract: + case ExpressionType.SubtractChecked: + return "-"; + case ExpressionType.Divide: + return "/"; + case ExpressionType.Multiply: + case ExpressionType.MultiplyChecked: + return "*"; + case ExpressionType.Modulo: + return "%"; + case ExpressionType.Coalesce: + throw new Exception("Expression no support ?? ,Use SqlFunc.IsNull"); + default: + Check.ThrowNotSupportedException(string.Format(ErrorMessage.OperatorError, expressiontype.ToString())); + return null; + } + } + + public static object GetValue(object value) + { + if (value == null) return value; + var type = value.GetType(); + if (type.IsEnum()&& type != typeof(DateType)&& type!=typeof(JoinType)&&type!=typeof(OrderByType)) return Convert.ToInt64(value); + else + return value; + } + + public static bool IsLogicOperator(string operatorValue) + { + return operatorValue == "&&" || operatorValue == "||"||operatorValue == "AND" || operatorValue == "OR"; + } + + public static bool IsLogicOperator(Expression expression) + { + return expression.NodeType == ExpressionType.And || + expression.NodeType == ExpressionType.AndAlso || + expression.NodeType == ExpressionType.Or || + expression.NodeType == ExpressionType.OrElse; + } + public static bool IsComparisonOperator(Expression expression) + { + return expression.NodeType != ExpressionType.And && + expression.NodeType != ExpressionType.AndAlso && + expression.NodeType != ExpressionType.Or && + expression.NodeType != ExpressionType.OrElse; + } + public static object GetMemberValue(MemberInfo member, Expression expression) + { + var rootExpression = expression as MemberExpression; + var memberInfos = new Stack(); + var fieldInfo = member as System.Reflection.FieldInfo; + object reval = null; + MemberExpression memberExpr = null; + while (expression is MemberExpression) + { + memberExpr = expression as MemberExpression; + memberInfos.Push(memberExpr.Member); + if (memberExpr.Expression == null) + { + var isProperty = memberExpr.Member.MemberType == MemberTypes.Property; + var isField = memberExpr.Member.MemberType == MemberTypes.Field; + if (isProperty) + { + reval = GetPropertyValue(memberExpr); + } + else if (isField) + { + reval = GetFiledValue(memberExpr); + } + } + if (memberExpr.Expression == null) + { + + } + expression = memberExpr.Expression; + } + // fetch the root object reference: + var constExpr = expression as ConstantExpression; + if (constExpr == null) { + return DynamicInvoke(rootExpression); + } + object objReference = constExpr.Value; + // "ascend" back whence we came from and resolve object references along the way: + while (memberInfos.Count > 0) // or some other break condition + { + var mi = memberInfos.Pop(); + if (mi.MemberType == MemberTypes.Property) + { + var objProp = objReference.GetType().GetProperty(mi.Name); + if (objProp == null) + { + objReference = DynamicInvoke(expression, rootExpression==null?memberExpr: rootExpression); + } + else + { + objReference = objProp.GetValue(objReference, null); + } + } + else if (mi.MemberType == MemberTypes.Field) + { + var objField = objReference.GetType().GetField(mi.Name); + if (objField == null) + { + objReference = DynamicInvoke(expression, rootExpression==null?memberExpr: rootExpression); + } + else + { + objReference = objField.GetValue(objReference); + } + } + } + reval = objReference; + return reval; + } + + public static object GetFiledValue(MemberExpression memberExpr) + { + if (!(memberExpr.Member is FieldInfo)) + { + return DynamicInvoke(memberExpr); + } + object reval = null; + FieldInfo field = (FieldInfo)memberExpr.Member; + Check.Exception(field.IsPrivate, string.Format(" Field \"{0}\" can't be private ", field.Name)); + reval = field.GetValue(memberExpr.Member); + if (reval != null && reval.GetType().IsClass() && reval.GetType() != UtilConstants.StringType) + { + var fieldName = memberExpr.Member.Name; + var proInfo = reval.GetType().GetProperty(fieldName); + if (proInfo != null) + { + reval = proInfo.GetValue(reval, null); + } + var fieInfo = reval.GetType().GetField(fieldName); + if (fieInfo != null) + { + reval = fieInfo.GetValue(reval); + } + if (fieInfo == null && proInfo == null) + { + Check.Exception(field.IsPrivate, string.Format(" Field \"{0}\" can't be private ", field.Name)); + } + } + return reval; + } + + + public static bool IsConstExpression(MemberExpression memberExpr) + { + var result = false; + while (memberExpr!=null&&memberExpr.Expression != null) + { + var isConst = memberExpr.Expression is ConstantExpression; + if (isConst) + { + result = true; + break; + } + memberExpr = memberExpr.Expression as MemberExpression; + } + return result; + } + + public static object GetPropertyValue(MemberExpression memberExpr) + { + if (!(memberExpr.Member is PropertyInfo)) + { + return DynamicInvoke(memberExpr); + } + object reval = null; + PropertyInfo pro = (PropertyInfo)memberExpr.Member; + reval = pro.GetValue(memberExpr.Member, null); + if (reval != null && reval.GetType().IsClass() && reval.GetType() != UtilConstants.StringType) + { + var fieldName = memberExpr.Member.Name; + var proInfo = reval.GetType().GetProperty(fieldName); + if (proInfo != null) + { + reval = proInfo.GetValue(reval, null); + } + var fieInfo = reval.GetType().GetField(fieldName); + if (fieInfo != null) + { + reval = fieInfo.GetValue(reval); + } + if (fieInfo == null && proInfo == null) + { + Check.Exception(true, string.Format(" Property \"{0}\" can't be private ", pro.Name)); + } + } + return reval; + } + + public static object DynamicInvoke(Expression expression,MemberExpression memberExpression=null) + { + object value = Expression.Lambda(expression).Compile().DynamicInvoke(); + if (value != null && value.GetType().IsClass() && value.GetType() != UtilConstants.StringType&& memberExpression!=null) + { + value = Expression.Lambda(memberExpression).Compile().DynamicInvoke(); + } + + return value; + } + + public static Type GetPropertyOrFieldType(MemberInfo propertyOrField) + { + if (propertyOrField.MemberType == MemberTypes.Property) + return ((PropertyInfo)propertyOrField).PropertyType; + if (propertyOrField.MemberType == MemberTypes.Field) + return ((FieldInfo)propertyOrField).FieldType; + throw new NotSupportedException(); + } + + public static bool IsEntity(Type type) + { + return type.IsClass() && type != UtilConstants.StringType; + } + + public static bool IsValueType(Type type) + { + return !IsEntity(type); + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/MethodCallExpressionModel.cs b/类库/SqlSugar/ExpressionsToSql/Common/MethodCallExpressionModel.cs new file mode 100644 index 0000000..91e5ae8 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/MethodCallExpressionModel.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Linq.Expressions; +namespace SqlSugar +{ + public class MethodCallExpressionModel + { + public List Args { get; set; } + } + + public class MethodCallExpressionArgs + { + public bool IsMember { get; set; } + public object MemberName { get; set; } + public object MemberValue { get; set; } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/ResolveExpressType.cs b/类库/SqlSugar/ExpressionsToSql/Common/ResolveExpressType.cs new file mode 100644 index 0000000..2c97a23 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/ResolveExpressType.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public enum ResolveExpressType + { + None = 0, + WhereSingle = 1, + WhereMultiple = 2, + SelectSingle=3, + SelectMultiple=4, + FieldSingle=5, + FieldMultiple=7, + Join=8, + ArraySingle=9, + ArrayMultiple = 10, + Update =11 + + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Common/SugarParameter.cs b/类库/SqlSugar/ExpressionsToSql/Common/SugarParameter.cs new file mode 100644 index 0000000..f6dbbf4 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Common/SugarParameter.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class SugarParameter : DbParameter + { + public bool IsRefCursor { get; set; } + public SugarParameter(string name, object value) + { + this.Value = value; + this.ParameterName = name; + if (value != null) + { + SettingDataType(value.GetType()); + } + } + public SugarParameter(string name, object value, Type type) + { + this.Value = value; + this.ParameterName = name; + SettingDataType(type); + } + public SugarParameter(string name, object value, Type type, ParameterDirection direction) + { + this.Value = value; + this.ParameterName = name; + this.Direction = direction; + SettingDataType(type); + } + public SugarParameter(string name, object value, Type type, ParameterDirection direction, int size) + { + this.Value = value; + this.ParameterName = name; + this.Direction = direction; + this.Size = size; + SettingDataType(type); + } + + private void SettingDataType(Type type) + { + if (type == UtilConstants.ByteArrayType) + { + this.DbType = System.Data.DbType.Binary; + } + else if (type == UtilConstants.GuidType) + { + this.DbType = System.Data.DbType.Guid; + } + else if (type == UtilConstants.IntType) + { + this.DbType = System.Data.DbType.Int32; + } + else if (type == UtilConstants.ShortType) + { + this.DbType = System.Data.DbType.Int16; + } + else if (type == UtilConstants.LongType) + { + this.DbType = System.Data.DbType.Int64; + } + else if (type == UtilConstants.DateType) + { + this.DbType = System.Data.DbType.DateTime; + } + else if (type == UtilConstants.DobType) + { + this.DbType = System.Data.DbType.Double; + } + else if (type == UtilConstants.DecType) + { + this.DbType = System.Data.DbType.Decimal; + } + else if (type == UtilConstants.ByteType) + { + this.DbType = System.Data.DbType.Byte; + } + else if (type == UtilConstants.FloatType) + { + this.DbType = System.Data.DbType.Single; + } + else if (type == UtilConstants.BoolType) + { + this.DbType = System.Data.DbType.Boolean; + } + else if (type == UtilConstants.StringType) + { + this.DbType = System.Data.DbType.String; + } + else if (type == UtilConstants.DateTimeOffsetType) + { + this.DbType = System.Data.DbType.DateTimeOffset; + } + else if (type == UtilConstants.TimeSpanType) + { + this.Value = this.Value.ToString(); + } + + } + public SugarParameter(string name, object value, bool isOutput) + { + this.Value = value; + this.ParameterName = name; + if (isOutput) + { + this.Direction = ParameterDirection.Output; + } + } + public override System.Data.DbType DbType + { + get; set; + } + + public override ParameterDirection Direction + { + get; set; + } + + public override bool IsNullable + { + get; set; + } + + public override string ParameterName + { + get; set; + } + + public int _Size; + + public override int Size + { + get + { + if (_Size == 0 && Value != null) + { + var isByteArray = Value.GetType() == UtilConstants.ByteArrayType; + if (isByteArray) + _Size = -1; + else + { + var length = Value.ToString().Length; + _Size = length < 4000 ? 4000 : -1; + + } + } + if (_Size == 0) + _Size = 4000; + return _Size; + } + set + { + _Size = value; + } + } + + public override string SourceColumn + { + get; set; + } + + public override bool SourceColumnNullMapping + { + get; set; + } + public string UdtTypeName + { + get; + set; + } + + public override object Value + { + get; set; + } + + public Dictionary TempDate + { + get; set; + } + + /// + /// 如果类库是.NET 4.5请删除该属性 + /// If the SqlSugar library is.NET 4.5, delete the property + /// + public override DataRowVersion SourceVersion + { + get; set; + } + + public override void ResetDbType() + { + this.DbType = System.Data.DbType.String; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs b/类库/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs new file mode 100644 index 0000000..b91e925 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/DbMethods/DefaultDbMethod.cs @@ -0,0 +1,357 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial class DefaultDbMethod : IDbMethods + { + public virtual string IIF(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("( CASE WHEN {0} THEN {1} ELSE {2} END )", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + + public virtual string IsNullOrEmpty(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("( {0}='' OR {0} IS NULL )", parameter.MemberName); + } + + public virtual string HasValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("( {0}<>'' AND {0} IS NOT NULL )", parameter.MemberName); + } + + public virtual string HasNumber(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("( {0}>0 AND {0} IS NOT NULL )", parameter.MemberName); + } + + + public virtual string ToUpper(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" (UPPER({0})) ", parameter.MemberName); + } + + public virtual string ToLower(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" (LOWER({0})) ", parameter.MemberName); + } + + public virtual string Trim(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" (rtrim(ltrim({0}))) ", parameter.MemberName); + } + + public virtual string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'+{1}+'%') ", parameter.MemberName, parameter2.MemberName); + } + public virtual string ContainsArray(MethodCallExpressionModel model) + { + var inValueIEnumerable = (IEnumerable)model.Args[0].MemberValue; + List inValues = new List(); + if (inValueIEnumerable != null) + { + foreach (var item in inValueIEnumerable) + { + if (item != null && item.GetType().IsEnum()) + { + inValues.Add(Convert.ToInt64(item)); + } + else + { + inValues.Add(item); + } + } + } + var value = model.Args[1].MemberName; + string inValueString = null; + if (inValues != null && inValues.Count > 0) + { + inValueString = inValues.ToArray().ToJoinSqlInVals(); + } + if (inValueString.IsNullOrEmpty()) + { + return " (1=2) "; + } + else + { + return string.Format(" ({0} IN ({1})) ", value, inValueString); + } + } + + public virtual string Equals(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} = {1}) ", parameter.MemberName, parameter2.MemberName); ; + } + + public virtual string DateIsSameDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (DATEDIFF(day,{0},{1})=0) ", parameter.MemberName, parameter2.MemberName); ; + } + + public virtual string DateIsSameByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (DATEDIFF({2},{0},{1})=0) ", parameter.MemberName, parameter2.MemberName, parameter3.MemberValue); + } + + public virtual string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (DATEADD({2},{1},{0})) ", parameter.MemberName, parameter2.MemberName, parameter3.MemberValue); + } + + public virtual string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (DATEADD(day,{1},{0})) ", parameter.MemberName, parameter2.MemberName); + } + + public virtual string Between(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + var parameter2 = model.Args[2]; + return string.Format(" ({0} BETWEEN {1} AND {2}) ", parameter.MemberName, parameter1.MemberName, parameter2.MemberName); + } + + public virtual string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like {1}+'%') ", parameter.MemberName, parameter2.MemberName); + } + + public virtual string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'+{1}) ", parameter.MemberName, parameter2.MemberName); + } + + public virtual string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" DateName({0},{1}) ", parameter2.MemberValue, parameter.MemberName); + } + + public virtual string ToInt32(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS INT)", parameter.MemberName); + } + + public virtual string ToInt64(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS BIGINT)", parameter.MemberName); + } + + public virtual string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS NVARCHAR(MAX))", parameter.MemberName); + } + + public virtual string ToGuid(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS UNIQUEIDENTIFIER)", parameter.MemberName); + } + + public virtual string ToDouble(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS FLOAT)", parameter.MemberName); + } + + public virtual string ToBool(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS BIT)", parameter.MemberName); + } + + public virtual string ToDate(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DATETIME)", parameter.MemberName); + } + + public virtual string ToTime(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS TIME)", parameter.MemberName); + } + + public virtual string ToDecimal(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS MONEY)", parameter.MemberName); + } + public virtual string Substring(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("SUBSTRING({0},1 + {1},{2})", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + + public virtual string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("LEN({0})", parameter.MemberName); + } + + public virtual string Replace(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("REPLACE({0},{1},{2})", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + + public virtual string AggregateSum(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("SUM({0})", parameter.MemberName); + } + + public virtual string AggregateAvg(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("AVG({0})", parameter.MemberName); + } + + public virtual string AggregateMin(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("MIN({0})", parameter.MemberName); + } + + public virtual string AggregateMax(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("MAX({0})", parameter.MemberName); + } + + public virtual string AggregateCount(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("COUNT({0})", parameter.MemberName); + } + + public virtual string MappingColumn(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("{0}", parameter1.MemberValue); + } + + public virtual string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("ISNULL({0},{1})", parameter.MemberName, parameter1.MemberName); + } + + public virtual string True() + { + return "( 1 = 1 ) "; + } + + public virtual string False() + { + return "( 1 = 2 ) "; + } + + public string GuidNew() + { + return "'" + Guid.NewGuid() + "' "; + } + + public string GetSelfAndAutoFill(string shortName, bool isSingle) + { + if (isSingle) return "*"; + else + return string.Format("{0}.*", shortName); + } + + public virtual string MergeString(params string[] strings) + { + return string.Join("+", strings); + } + + public virtual string Pack(string sql) + { + return "(" + sql + ")"; + } + + public virtual string EqualTrue(string fieldName) + { + return "( " + fieldName + "=1 )"; + } + + public virtual string Null() + { + return "NULL"; + } + + public virtual string GetDate() + { + return "GETDATE()"; + } + + public virtual string GetRandom() + { + return "NEWID()"; + } + + public virtual string CaseWhen(List> sqls) + { + StringBuilder reslut = new StringBuilder(); + foreach (var item in sqls) + { + if (item.Key == "IF") + { + reslut.AppendFormat(" ( CASE WHEN {0} ", item.Value); + } + else if (item.Key == "End") + { + reslut.AppendFormat("ELSE {0} END )", item.Value); + } + else if (item.Key == "Return") + { + reslut.AppendFormat(" THEN {0} ", item.Value); + } + else { + reslut.AppendFormat(" WHEN {0} ", item.Value); + } + } + return reslut.ToString(); + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs b/类库/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs new file mode 100644 index 0000000..5e6c1b7 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/DbMethods/IDbMethods.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IDbMethods + { + string IIF(MethodCallExpressionModel model); + string HasNumber(MethodCallExpressionModel model); + string HasValue(MethodCallExpressionModel model); + string IsNullOrEmpty(MethodCallExpressionModel model); + string ToLower(MethodCallExpressionModel model); + string ToUpper(MethodCallExpressionModel model); + string Trim(MethodCallExpressionModel model); + string Contains(MethodCallExpressionModel model); + string ContainsArray(MethodCallExpressionModel model); + string Equals(MethodCallExpressionModel model); + string DateIsSameDay(MethodCallExpressionModel model); + string DateIsSameByType(MethodCallExpressionModel model); + string DateAddByType(MethodCallExpressionModel model); + + string DateValue(MethodCallExpressionModel model); + string DateAddDay(MethodCallExpressionModel model); + string Between(MethodCallExpressionModel model); + string StartsWith(MethodCallExpressionModel model); + string EndsWith(MethodCallExpressionModel model); + string ToInt32(MethodCallExpressionModel model); + string ToInt64(MethodCallExpressionModel model); + string ToString(MethodCallExpressionModel model); + string ToGuid(MethodCallExpressionModel model); + string ToDouble(MethodCallExpressionModel model); + string ToBool(MethodCallExpressionModel model); + string CaseWhen(List> sqls); + string Substring(MethodCallExpressionModel model); + string ToDate(MethodCallExpressionModel model); + string ToTime(MethodCallExpressionModel model); + string ToDecimal(MethodCallExpressionModel model); + string Length(MethodCallExpressionModel model); + string Replace(MethodCallExpressionModel model); + string AggregateSum(MethodCallExpressionModel model); + string AggregateAvg(MethodCallExpressionModel model); + string AggregateMin(MethodCallExpressionModel model); + string AggregateMax(MethodCallExpressionModel model); + string AggregateCount(MethodCallExpressionModel model); + string MappingColumn(MethodCallExpressionModel model); + string IsNull(MethodCallExpressionModel model); + string GetSelfAndAutoFill(string shortName,bool isSingle); + string True(); + string False(); + string GuidNew(); + string MergeString(params string[] strings); + string EqualTrue(string value); + string Pack(string sql); + string Null(); + string GetDate(); + string GetRandom(); + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/DbMethods/SqlFunc.cs b/类库/SqlSugar/ExpressionsToSql/DbMethods/SqlFunc.cs new file mode 100644 index 0000000..4ea9dc4 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/DbMethods/SqlFunc.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SqlFunc + { + public static bool HasNumber(object thisValue) + { + return thisValue.ObjToInt() > 0; + } + public static bool HasValue(object thisValue) + { + return thisValue.HasValue(); + } + public static bool IsNullOrEmpty(object thisValue) + { + return thisValue.IsNullOrEmpty(); + } + public static string ToLower(object thisValue) + { + return thisValue == null ? null : thisValue.ToString().ToLower(); + } + public static string ToUpper(object thisValue) + { + return thisValue == null ? null : thisValue.ToString().ToUpper(); + } + public static string Trim(object thisValue) + { + return thisValue == null ? null : thisValue.ToString().Trim(); + } + public static bool Contains(string thisValue, string parameterValue) + { + return thisValue.Contains(parameterValue); + } + public static bool ContainsArray(T[] thisValue, object parameterValue) + { + return thisValue.Contains((T)parameterValue); + } + public static bool StartsWith(string thisValue, string parameterValue) + { + return thisValue.StartsWith(parameterValue); + } + public static bool EndsWith(string thisValue, string parameterValue) + { + return thisValue.EndsWith(parameterValue); + } + public new static bool Equals(object thisValue, object parameterValue) + { + return thisValue.Equals(parameterValue); + } + public static bool DateIsSame(DateTime date1, DateTime date2) + { + return date1.ToString("yyyy-MM-dd") == date2.ToString("yyyy-MM-dd"); + } + public static bool DateIsSame(DateTime? date1, DateTime? date2) + { + return ((DateTime)date1).ToString("yyyy-MM-dd") == ((DateTime)date2).ToString("yyyy-MM-dd"); + } + public static bool DateIsSame(DateTime date1, DateTime date2, DateType dataType) { throw new NotSupportedException("Can only be used in expressions"); } + public static DateTime DateAdd(DateTime date, int addValue, DateType dataType) { throw new NotSupportedException("Can only be used in expressions"); } + public static DateTime DateAdd(DateTime date, int addValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static int DateValue(DateTime date, DateType dataType) { throw new NotSupportedException("Can only be used in expressions"); } + public static bool Between(object value, object start, object end) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult IIF(bool Expression, TResult thenValue, TResult elseValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult IsNull(TResult thisValue, TResult ifNullValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1,string value2) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2,string value3) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2,string value3,string value4) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2, string value3, string value4,string value5) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2, string value3, string value4, string value5,string value6) { throw new NotSupportedException("Can only be used in expressions"); } + public static string MergeString(string value1, string value2, string value3, string value4, string value5, string value6,string value7) { throw new NotSupportedException("Can only be used in expressions"); } + public static int ToInt32(object value) { return value.ObjToInt(); } + public static long ToInt64(object value) { return Convert.ToInt64(value); } + /// + /// yyyy-MM-dd HH:mm:ss.fff + /// + /// + /// + public static DateTime ToDate(object value) { return value.ObjToDate(); } + /// + ///HH:mm:ss + /// + /// + /// + public static TimeSpan ToTime(object value) { throw new NotSupportedException("Can only be used in expressions"); } + public static string ToString(object value) { return value.ObjToString(); } + public static decimal ToDecimal(object value) { return value.ObjToDecimal(); } + public static Guid ToGuid(object value) { return Guid.Parse(value.ObjToString()); } + public static double ToDouble(object value) { return value.ObjToMoney(); } + public static bool ToBool(object value) { return value.ObjToBool(); } + public static string Substring(object value, int index, int length) { return value.ObjToString().Substring(index, length); } + public static string Replace(object value, string oldChar, string newChar) { return value.ObjToString().Replace(oldChar, newChar); } + public static int Length(object value) { return value.ObjToString().Length; } + public static TResult AggregateSum(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult AggregateAvg(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult AggregateMin(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult AggregateMax(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static int AggregateCount(TResult thisValue) { throw new NotSupportedException("Can only be used in expressions"); } + public static TResult MappingColumn(TResult oldColumnName,string newColumnName) { throw new NotSupportedException("Can only be used in expressions"); } + /// + ///Example: new NewT(){name=SqlFunc.GetSelfAndAutoFill(it)} Generated SQL it.* + /// + /// + /// + /// + public static TResult GetSelfAndAutoFill(TResult value) { throw new NotSupportedException("Can only be used in expressions"); } + public static DateTime GetDate() { throw new NotSupportedException("Can only be used in expressions"); } + public static string GetRandom() { throw new NotSupportedException("Can only be used in expressions"); } + /// + /// Subquery + /// + /// + /// + public static Subqueryable Subqueryable() where T:class,new(){ throw new NotSupportedException("Can only be used in expressions");} + public static CaseThen IF(bool condition) { throw new NotSupportedException("Can only be used in expressions"); } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/DbMethods/SqlFuncExternal.cs b/类库/SqlSugar/ExpressionsToSql/DbMethods/SqlFuncExternal.cs new file mode 100644 index 0000000..306475d --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/DbMethods/SqlFuncExternal.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlFuncExternal + { + public string UniqueMethodName { get; set; } + public Func MethodValue { get; set; } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ExpressionContext.cs b/类库/SqlSugar/ExpressionsToSql/ExpressionContext.cs new file mode 100644 index 0000000..2c6ba59 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ExpressionContext.cs @@ -0,0 +1,232 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + /// + /// ** description:Expression to sql + /// ** author:sunkaixuan + /// ** date:2017/1/14 + /// ** email:610262374@qq.com + public class ExpressionContext : ExpResolveAccessory + { + #region Fields + private bool _IsSingle = true; + private IDbMethods _DbMehtods { get; set; } + #endregion + + #region Properties + public IDbMethods DbMehtods + { + get + { + if (_DbMehtods == null) + { + _DbMehtods = new DefaultDbMethod(); + } + return _DbMehtods; + } + set + { + _DbMehtods = value; + } + } + public int SubQueryIndex { get; set; } + public int Index { get; set; } + public int ParameterIndex { get; set; } + public string SingleTableNameSubqueryShortName{ get; set; } + public MappingColumnList MappingColumns { get; set; } + public MappingTableList MappingTables { get; set; } + public IgnoreColumnList IgnoreComumnList { get; set; } + public List SqlFuncServices { get; set; } + public bool IsSingle + { + get + { + return _IsSingle; + } + set + { + _IsSingle = value; + } + } + public bool IsJoin + { + get + { + return !IsSingle; + } + } + public List JoinQueryInfos { get; set; } + public ResolveExpressType ResolveType { get; set; } + public Expression Expression { get; set; } + public ExpressionResult Result + { + get + { + if (base._Result == null) + { + this.Result = new ExpressionResult(this.ResolveType); + } + return base._Result; + } + set + { + this._Result = value; + } + } + public List Parameters + { + get + { + if (base._Parameters == null) + base._Parameters = new List(); + return base._Parameters; + } + set + { + base._Parameters = value; + } + } + public virtual string SqlParameterKeyWord + { + get + { + return "@"; + } + } + public virtual string SqlTranslationLeft { get { return "["; } } + public virtual string SqlTranslationRight { get { return "]"; } } + public virtual Action InitMappingInfo { get; set; } + public virtual Action RefreshMapping { get; set; } + #endregion + + #region Core methods + public void Resolve(Expression expression, ResolveExpressType resolveType) + { + this.ResolveType = resolveType; + this.Expression = expression; + BaseResolve resolve = new BaseResolve(new ExpressionParameter() { CurrentExpression = this.Expression, Context = this }); + resolve.Start(); + } + public void Clear() + { + base._Result = null; + base._Parameters = new List(); + } + public ExpressionContext GetCopyContext() + { + ExpressionContext copyContext = (ExpressionContext)Activator.CreateInstance(this.GetType(), true); + copyContext.Index = this.Index; + copyContext.InitMappingInfo = this.InitMappingInfo; + copyContext.RefreshMapping = this.RefreshMapping; + copyContext.ParameterIndex = this.ParameterIndex; + return copyContext; + } + public ExpressionContext GetCopyContextWithMapping() + { + ExpressionContext copyContext = (ExpressionContext)Activator.CreateInstance(this.GetType(), true); + copyContext.Index = this.Index; + copyContext.ParameterIndex = this.ParameterIndex; + copyContext.MappingColumns = this.MappingColumns; + copyContext.MappingTables = this.MappingTables; + copyContext.IgnoreComumnList = this.IgnoreComumnList; + copyContext.SqlFuncServices = this.SqlFuncServices; + copyContext.InitMappingInfo = this.InitMappingInfo; + copyContext.RefreshMapping = this.RefreshMapping; + return copyContext; + } + #endregion + + #region Override methods + public virtual string GetTranslationTableName(string entityName, bool isMapping = true) + { + Check.ArgumentNullException(entityName, string.Format(ErrorMessage.ObjNotExist, "Table Name")); + if (IsTranslationText(entityName)) return entityName; + isMapping = isMapping && this.MappingTables.HasValue(); + var isComplex = entityName.Contains(UtilConstants.Dot); + if (isMapping && isComplex) + { + var columnInfo = entityName.Split(UtilConstants.DotChar); + var mappingInfo = this.MappingTables.FirstOrDefault(it => it.EntityName.Equals(columnInfo.Last(), StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo != null) + { + columnInfo[columnInfo.Length - 1] = mappingInfo.EntityName; + } + return string.Join(UtilConstants.Dot, columnInfo.Select(it => GetTranslationText(it))); + } + else if (isMapping) + { + var mappingInfo = this.MappingTables.FirstOrDefault(it => it.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase)); + return SqlTranslationLeft + (mappingInfo == null ? entityName : mappingInfo.DbTableName) + SqlTranslationRight; + } + else if (isComplex) + { + return string.Join(UtilConstants.Dot, entityName.Split(UtilConstants.DotChar).Select(it => GetTranslationText(it))); + } + else + { + return GetTranslationText(entityName); + } + } + public virtual string GetTranslationColumnName(string columnName) + { + Check.ArgumentNullException(columnName, string.Format(ErrorMessage.ObjNotExist, "Column Name")); + if (columnName.Substring(0, 1) == this.SqlParameterKeyWord) + { + return columnName; + } + if (IsTranslationText(columnName)) return columnName; + if (columnName.Contains(UtilConstants.Dot)) + { + return string.Join(UtilConstants.Dot, columnName.Split(UtilConstants.DotChar).Select(it => GetTranslationText(it))); + } + else + { + return GetTranslationText(columnName); + } + } + public virtual string GetDbColumnName(string entityName, string propertyName) + { + if (this.MappingColumns.HasValue()) + { + var mappingInfo = this.MappingColumns.SingleOrDefault(it => it.EntityName == entityName && it.PropertyName == propertyName); + return mappingInfo == null ? propertyName : mappingInfo.DbColumnName; + } + else + { + return propertyName; + } + } + public virtual bool IsTranslationText(string name) + { + var result = name.IsContainsIn(SqlTranslationLeft, SqlTranslationRight, UtilConstants.Space, ExpressionConst.LeftParenthesis, ExpressionConst.RightParenthesis); + return result; + } + public virtual string GetTranslationText(string name) + { + return SqlTranslationLeft + name + SqlTranslationRight; + } + public virtual string GetAsString(string asName, string fieldValue) + { + if (fieldValue.Contains(".*") || fieldValue == "*") return fieldValue; + return string.Format(" {0} {1} {2} ", GetTranslationColumnName(fieldValue), "AS", GetTranslationColumnName(asName)); + } + + public virtual string GetEqString(string eqName, string fieldValue) + { + return string.Format(" {0} {1} {2} ", GetTranslationColumnName(eqName), "=", GetTranslationColumnName(fieldValue)); + } + + public virtual string GetAsString(string asName, string fieldValue, string fieldShortName) + { + if (fieldValue.Contains(".*") || fieldValue == "*") return fieldValue; + return string.Format(" {0} {1} {2} ", GetTranslationColumnName(fieldShortName + "." + fieldValue), "AS", GetTranslationColumnName(asName)); + } + #endregion + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/BaseResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/BaseResolve.cs new file mode 100644 index 0000000..34b8eff --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/BaseResolve.cs @@ -0,0 +1,490 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public class BaseResolve + { + protected Expression Expression { get; set; } + protected Expression ExactExpression { get; set; } + public ExpressionContext Context { get; set; } + public bool? IsLeft { get; set; } + public int ContentIndex { get { return this.Context.Index; } } + public int Index { get; set; } + public ExpressionParameter BaseParameter { get; set; } + + private BaseResolve() + { + + } + public BaseResolve(ExpressionParameter parameter) + { + this.Expression = parameter.CurrentExpression; + this.Context = parameter.Context; + this.BaseParameter = parameter; + } + + public BaseResolve Start() + { + Context.Index++; + Expression expression = this.Expression; + ExpressionParameter parameter = new ExpressionParameter() + { + Context = this.Context, + CurrentExpression = expression, + IsLeft = this.IsLeft, + BaseExpression = this.ExactExpression, + BaseParameter = this.BaseParameter, + Index = Context.Index + }; + if (expression is LambdaExpression) + { + return new LambdaExpressionResolve(parameter); + } + else if (expression is BinaryExpression && expression.NodeType == ExpressionType.Coalesce) + { + return new CoalesceResolveItems(parameter); + } + else if (expression is BinaryExpression) + { + return new BinaryExpressionResolve(parameter); + } + else if (expression is BlockExpression) + { + Check.ThrowNotSupportedException("BlockExpression"); + } + else if (expression is ConditionalExpression) + { + return new ConditionalExpressionResolve(parameter); + } + else if (expression is MethodCallExpression) + { + return new MethodCallExpressionResolve(parameter); + } + else if (expression is MemberExpression && ((MemberExpression)expression).Expression == null) + { + return new MemberNoExpressionResolve(parameter); + } + else if (expression is MemberExpression && ((MemberExpression)expression).Expression.NodeType == ExpressionType.Constant) + { + return new MemberConstExpressionResolve(parameter); + } + else if (expression is MemberExpression && ((MemberExpression)expression).Expression.NodeType == ExpressionType.New) + { + return new MemberNewExpressionResolve(parameter); + } + else if (expression is ConstantExpression) + { + return new ConstantExpressionResolve(parameter); + } + else if (expression is MemberExpression) + { + return new MemberExpressionResolve(parameter); + } + else if (expression is UnaryExpression) + { + return new UnaryExpressionResolve(parameter); + } + else if (expression is MemberInitExpression) + { + return new MemberInitExpressionResolve(parameter); + } + else if (expression is NewExpression) + { + return new NewExpressionResolve(parameter); + } + else if (expression is NewArrayExpression) + { + return new NewArrayExpessionResolve(parameter); + } + else if (expression is ParameterExpression) + { + return new TypeParameterExpressionReolve(parameter); + } + else if (expression != null && expression.NodeType.IsIn(ExpressionType.NewArrayBounds)) + { + Check.ThrowNotSupportedException("ExpressionType.NewArrayBounds"); + } + return null; + } + + protected void AppendMember(ExpressionParameter parameter, bool? isLeft, object appendValue) + { + + Context.ParameterIndex++; + if (isLeft == true) + { + appendValue += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue.ObjToString()); + } + else + { + this.Context.Result.Append(appendValue); + } + } + protected void AppendValue(ExpressionParameter parameter, bool? isLeft, object value) + { + if (parameter.BaseExpression is BinaryExpression || parameter.BaseExpression == null) + { + var oppoSiteExpression = isLeft == true ? parameter.BaseParameter.RightExpression : parameter.BaseParameter.LeftExpression; + if (parameter.CurrentExpression is MethodCallExpression||parameter.CurrentExpression is ConditionalExpression||parameter.CurrentExpression.NodeType==ExpressionType.Coalesce) + { + var appendValue = value; + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue.ObjToString()); + } + else + { + this.Context.Result.Append(appendValue); + } + this.AppendOpreator(parameter, isLeft); + } + else if (oppoSiteExpression is MemberExpression) + { + string appendValue = Context.SqlParameterKeyWord + + ((MemberExpression)oppoSiteExpression).Member.Name + + Context.ParameterIndex; + if (value.ObjToString() != "NULL" && !parameter.ValueIsNull) + { + this.Context.Parameters.Add(new SugarParameter(appendValue, value)); + } + else + { + appendValue = value.ObjToString(); + } + Context.ParameterIndex++; + appendValue = string.Format(" {0} ", appendValue); + if (isLeft == true) + { + appendValue += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue); + } + else + { + this.Context.Result.Append(appendValue); + } + } + else if ((oppoSiteExpression is UnaryExpression && (oppoSiteExpression as UnaryExpression).Operand is MemberExpression)) { + string appendValue = Context.SqlParameterKeyWord + + ((MemberExpression)(oppoSiteExpression as UnaryExpression).Operand).Member.Name + + Context.ParameterIndex; + if (value.ObjToString() != "NULL" && !parameter.ValueIsNull) + { + this.Context.Parameters.Add(new SugarParameter(appendValue, value)); + } + else + { + appendValue = value.ObjToString(); + } + Context.ParameterIndex++; + appendValue = string.Format(" {0} ", appendValue); + if (isLeft == true) + { + appendValue += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue); + } + else + { + this.Context.Result.Append(appendValue); + } + } + else + { + var appendValue = this.Context.SqlParameterKeyWord + ExpressionConst.Const + Context.ParameterIndex; + Context.ParameterIndex++; + if (value != null && value.GetType().IsEnum()) + { + value = Convert.ToInt64(value); + } + this.Context.Parameters.Add(new SugarParameter(appendValue, value)); + appendValue = string.Format(" {0} ", appendValue); + if (isLeft == true) + { + appendValue += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (this.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, appendValue); + } + else + { + this.Context.Result.Append(appendValue); + } + } + } + } + protected void AppendOpreator(ExpressionParameter parameter, bool? isLeft) + { + if (isLeft == true) + { + this.Context.Result.Append(" " + ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index); + } + } + protected string AppendParameter(object paramterValue) + { + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; ; + this.Context.Parameters.Add(new SugarParameter(parameterName, paramterValue)); + return parameterName; + } + protected void AppendNot(object Value) + { + var isAppend = !this.Context.Result.Contains(ExpressionConst.FormatSymbol); + var lastCharIsSpace = this.Context.Result.LastCharIsSpace; + if (isAppend) + { + this.Context.Result.Append(lastCharIsSpace?"NOT":" NOT"); + } + else + { + this.Context.Result.Replace(ExpressionConst.FormatSymbol, "NOT"); + } + } + + protected MethodCallExpressionArgs GetMethodCallArgs(ExpressionParameter parameter, Expression item) + { + var newContext = this.Context.GetCopyContext(); + newContext.MappingColumns = this.Context.MappingColumns; + newContext.MappingTables = this.Context.MappingTables; + newContext.IgnoreComumnList = this.Context.IgnoreComumnList; + newContext.IsSingle = this.Context.IsSingle; + newContext.SqlFuncServices = this.Context.SqlFuncServices; + newContext.Resolve(item, this.Context.IsJoin ? ResolveExpressType.WhereMultiple : ResolveExpressType.WhereSingle); + this.Context.Index = newContext.Index; + this.Context.ParameterIndex = newContext.ParameterIndex; + if (newContext.Parameters.HasValue()) + { + this.Context.Parameters.AddRange(newContext.Parameters); + } + if (newContext.SingleTableNameSubqueryShortName.HasValue()) + { + this.Context.SingleTableNameSubqueryShortName = newContext.SingleTableNameSubqueryShortName; + } + var methodCallExpressionArgs = new MethodCallExpressionArgs() + { + IsMember = true, + MemberName = newContext.Result.GetResultString() + }; + return methodCallExpressionArgs; + } + + protected string GetNewExpressionValue(Expression item) + { + var newContext = this.Context.GetCopyContextWithMapping(); + newContext.Resolve(item, this.Context.IsJoin ? ResolveExpressType.WhereMultiple : ResolveExpressType.WhereSingle); + this.Context.Index = newContext.Index; + this.Context.ParameterIndex = newContext.ParameterIndex; + if (newContext.Parameters.HasValue()) + { + this.Context.Parameters.AddRange(newContext.Parameters); + } + return newContext.Result.GetResultString(); + } + + protected void ResolveNewExpressions(ExpressionParameter parameter, Expression item, string asName) + { + if (item is ConstantExpression) + { + this.Expression = item; + this.Start(); + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); + } + else if ((item is MemberExpression) && ((MemberExpression)item).Expression == null) + { + var paramterValue = ExpressionTool.GetPropertyValue(item as MemberExpression); + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, paramterValue)); + } + else if ((item is MemberExpression) && ((MemberExpression)item).Expression.NodeType == ExpressionType.Constant) + { + this.Expression = item; + this.Start(); + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); + } + else if (item is MemberExpression) + { + if (this.Context.Result.IsLockCurrentParameter == false) + { + this.Context.Result.CurrentParameter = parameter; + this.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + this.Expression = item; + this.Start(); + parameter.IsAppendResult(); + this.Context.Result.Append(this.Context.GetAsString(asName, parameter.CommonTempData.ObjToString())); + this.Context.Result.CurrentParameter = null; + } + } + else if (item is UnaryExpression && ((UnaryExpression)item).Operand is MemberExpression) + { + if (this.Context.Result.IsLockCurrentParameter == false) + { + var expression = ((UnaryExpression)item).Operand as MemberExpression; + var isDateTimeNow = ((UnaryExpression)item).Operand.ToString() == "DateTime.Now"; + if (expression.Expression == null&&!isDateTimeNow) + { + this.Context.Result.CurrentParameter = parameter; + this.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + this.Expression = item; + this.Start(); + parameter.IsAppendResult(); + this.Context.Result.Append(this.Context.GetAsString(asName, parameter.CommonTempData.ObjToString())); + this.Context.Result.CurrentParameter = null; + } + else if (expression.Expression is ConstantExpression||isDateTimeNow) + { + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, ExpressionTool.GetMemberValue(expression.Member, expression))); + } + else + { + this.Context.Result.CurrentParameter = parameter; + this.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + this.Expression = item; + this.Start(); + parameter.IsAppendResult(); + this.Context.Result.Append(this.Context.GetAsString(asName, parameter.CommonTempData.ObjToString())); + this.Context.Result.CurrentParameter = null; + } + } + } + else if (item is UnaryExpression && ((UnaryExpression)item).Operand is ConstantExpression) + { + if (this.Context.Result.IsLockCurrentParameter == false) + { + this.Expression = ((UnaryExpression)item).Operand; + this.Start(); + string parameterName = this.Context.SqlParameterKeyWord + "constant" + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); + } + } + else if (item is BinaryExpression) + { + if (this.Context.Result.IsLockCurrentParameter == false) + { + var newContext = this.Context.GetCopyContextWithMapping(); + var resolveExpressType = this.Context.IsSingle ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple; + newContext.Resolve(item, resolveExpressType); + this.Context.Index = newContext.Index; + this.Context.ParameterIndex = newContext.ParameterIndex; + if (newContext.Parameters.HasValue()) + { + this.Context.Parameters.AddRange(newContext.Parameters); + } + this.Context.Result.Append(this.Context.GetAsString(asName, newContext.Result.GetString())); + this.Context.Result.CurrentParameter = null; + if (this.Context.SingleTableNameSubqueryShortName.IsNullOrEmpty() && newContext.SingleTableNameSubqueryShortName.HasValue()) { + this.Context.SingleTableNameSubqueryShortName = newContext.SingleTableNameSubqueryShortName; + } + } + } + else if (item.Type.IsClass()) + { + this.Expression = item; + this.Start(); + var shortName = parameter.CommonTempData; + var listProperties = item.Type.GetProperties().Cast().ToList(); + foreach (var property in listProperties) + { + var hasIgnore = this.Context.IgnoreComumnList != null && this.Context.IgnoreComumnList.Any(it => it.EntityName.Equals(item.Type.Name, StringComparison.CurrentCultureIgnoreCase) && it.PropertyName.Equals(property.Name, StringComparison.CurrentCultureIgnoreCase)); + if (hasIgnore) + { + continue; + } + if (property.PropertyType.IsClass()) + { + + } + else + { + var propertyName = property.Name; + var dbColumnName = propertyName; + var mappingInfo = this.Context.MappingColumns.FirstOrDefault(it => it.EntityName == item.Type.Name && it.PropertyName.Equals(propertyName, StringComparison.CurrentCultureIgnoreCase)); + if (mappingInfo.HasValue()) { + dbColumnName = mappingInfo.DbColumnName; + } + asName = this.Context.GetTranslationText(item.Type.Name + "." + propertyName); + if (Context.IsJoin) + { + this.Context.Result.Append(Context.GetAsString(asName, dbColumnName, shortName.ObjToString())); + } + else + { + this.Context.Result.Append(Context.GetAsString(asName, dbColumnName)); + } + } + } + } + else if (item is MethodCallExpression|| item is UnaryExpression||item is ConditionalExpression|| item.NodeType==ExpressionType.Coalesce) + { + this.Expression = item; + this.Start(); + parameter.Context.Result.Append(this.Context.GetAsString(asName, parameter.CommonTempData.ObjToString())); + } + else + { + Check.ThrowNotSupportedException(item.GetType().Name); + } + } + protected static Dictionary MethodMapping = new Dictionary() { + { "ToString","ToString"}, + { "ToInt32","ToInt32"}, + { "ToInt16","ToInt32"}, + { "ToInt64","ToInt64"}, + { "ToDecimal","ToDecimal"}, + { "ToDateTime","ToDate"}, + { "ToBoolean","ToBool"}, + { "ToDouble","ToDouble"}, + { "Length","Length"}, + { "Replace","Replace"}, + { "Contains","Contains"}, + { "ContainsArray","ContainsArray"}, + { "EndsWith","EndsWith"}, + { "StartsWith","StartsWith"}, + { "HasValue","HasValue"}, + { "Trim","Trim"}, + { "Equals","Equals"}, + { "ToLower","ToLower"}, + { "ToUpper","ToUpper"}, + { "Substring","Substring"}, + { "DateAdd","DateAdd"} + }; + + protected static Dictionary MethodTimeMapping = new Dictionary() { + { "AddYears",DateType.Year}, + { "AddMonths",DateType.Month}, + { "AddDays",DateType.Day}, + { "AddHours",DateType.Hour}, + { "AddMinutes",DateType.Minute}, + { "AddSeconds",DateType.Second}, + { "AddMilliseconds",DateType.Millisecond} + }; + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/BinaryExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/BinaryExpressionResolve.cs new file mode 100644 index 0000000..f106a6b --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/BinaryExpressionResolve.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class BinaryExpressionResolve : BaseResolve + { + public BinaryExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = this.Expression as BinaryExpression; + var operatorValue = parameter.OperatorValue = ExpressionTool.GetOperator(expression.NodeType); + var isEqual = expression.NodeType == ExpressionType.Equal; + var isComparisonOperator = ExpressionTool.IsComparisonOperator(expression); + base.ExactExpression = expression; + var leftExpression = expression.Left; + var rightExpression = expression.Right; + var leftIsBinary = leftExpression is BinaryExpression; + var rightBinary = rightExpression is BinaryExpression; + var lbrs = leftIsBinary && !rightBinary; + var lsrb = !leftIsBinary && rightBinary; + var lbrb = rightBinary && leftIsBinary; + var lsbs = !leftIsBinary && !rightBinary; + var isAppend = !base.Context.Result.Contains(ExpressionConst.FormatSymbol); + if (isAppend) + { + base.Context.Result.Append(ExpressionConst.LeftParenthesis); + base.Context.Result.Append(ExpressionConst.FormatSymbol); + } + else + { + base.Context.Result.Replace(ExpressionConst.FormatSymbol, ExpressionConst.LeftParenthesis + ExpressionConst.FormatSymbol); + } + if (leftExpression is UnaryExpression && (leftExpression as UnaryExpression).Operand is UnaryExpression&& (leftExpression as UnaryExpression).NodeType != ExpressionType.Not) + { + leftExpression = (leftExpression as UnaryExpression).Operand; + } + if (leftExpression is UnaryExpression && (leftExpression as UnaryExpression).Operand.Type == UtilConstants.BoolType && (leftExpression as UnaryExpression).NodeType != ExpressionType.Not&&rightExpression.Type==UtilConstants.BoolTypeNull) + { + leftExpression = (leftExpression as UnaryExpression).Operand; + } + if (rightExpression is UnaryExpression&& (rightExpression as UnaryExpression).Operand.Type==UtilConstants.BoolType&& (rightExpression as UnaryExpression).NodeType != ExpressionType.Not) + { + rightExpression = (rightExpression as UnaryExpression).Operand; + } + parameter.LeftExpression = leftExpression; + parameter.RightExpression = rightExpression; + base.Expression = leftExpression; + base.IsLeft = true; + base.Start(); + if (leftExpression is UnaryExpression && leftExpression.Type == UtilConstants.BoolType&&!this.Context.Result.Contains(ExpressionConst.ExpressionReplace)) + { + this.Context.Result.AppendFormat(" {0} ", ExpressionTool.GetOperator(expression.NodeType)); + } + base.IsLeft = false; + base.Expression = rightExpression; + base.Start(); + base.IsLeft = null; + if (lsbs && parameter.ValueIsNull) + { + base.Context.Result.Replace(ExpressionConst.ExpressionReplace + parameter.Index, isEqual ? "IS" : "IS NOT"); + base.Context.Result.Replace(ExpressionConst.ExpressionReplace + (parameter.Index + 1), isEqual ? "IS" : "IS NOT"); + } + else + { + base.Context.Result.Replace(ExpressionConst.ExpressionReplace + parameter.Index, operatorValue); + base.Context.Result.Replace(ExpressionConst.ExpressionReplace + (parameter.Index + 1), operatorValue); + } + base.Context.Result.Append(ExpressionConst.RightParenthesis); + if (parameter.BaseExpression is BinaryExpression && parameter.IsLeft == true) + { + base.Context.Result.Append(" " + ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index + " "); + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/BlockExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/BlockExpressionResolve.cs new file mode 100644 index 0000000..1c35ed9 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/BlockExpressionResolve.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class BlockExpressionResolve:BaseResolve + { + public BlockExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/CoalesceResolveItems.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/CoalesceResolveItems.cs new file mode 100644 index 0000000..0887070 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/CoalesceResolveItems.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class CoalesceResolveItems : MethodCallExpressionResolve + { + public CoalesceResolveItems(ExpressionParameter parameter) : base(parameter) + { + string name = "IsNull"; + var express = base.Expression as BinaryExpression; + var args = new List() { + express.Left, + express.Right + }; + var isLeft = parameter.IsLeft; + MethodCallExpressionModel model = new MethodCallExpressionModel(); + model.Args = new List(); + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + Check.Exception(name == "GetSelfAndAutoFill", "SqlFunc.GetSelfAndAutoFill can only be used in Select."); + base.Where(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + base.Select(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + base.Field(parameter, isLeft, name, args, model); + break; + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs new file mode 100644 index 0000000..784a909 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/ConditionalExpressionResolve.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class ConditionalExpressionResolve: MethodCallExpressionResolve + { + public ConditionalExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + + string name = "IIF"; + var express = base.Expression as ConditionalExpression; + var args = new List() { + express.Test, + express.IfTrue, + express.IfFalse + }; + var isLeft = parameter.IsLeft; + MethodCallExpressionModel model = new MethodCallExpressionModel(); + model.Args = new List(); + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + Check.Exception(name == "GetSelfAndAutoFill", "SqlFunc.GetSelfAndAutoFill can only be used in Select."); + base.Where(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + base.Select(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + base.Field(parameter, isLeft, name, args, model); + break; + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/ConstantExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/ConstantExpressionResolve.cs new file mode 100644 index 0000000..0a80640 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/ConstantExpressionResolve.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + public class ConstantExpressionResolve : BaseResolve + { + public ConstantExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as ConstantExpression; + var isLeft = parameter.IsLeft; + object value = ExpressionTool.GetValue(expression.Value); + var baseParameter = parameter.BaseParameter; + baseParameter.ChildExpression = expression; + var isSetTempData = baseParameter.CommonTempData.HasValue() && baseParameter.CommonTempData.Equals(CommonTempDataType.Result); + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.SelectSingle: + case ResolveExpressType.Update: + case ResolveExpressType.SelectMultiple: + baseParameter.CommonTempData = value; + break; + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + var parentIsBinary = parameter.BaseParameter.CurrentExpression is BinaryExpression; + var parentIsRoot = parameter.BaseParameter.CurrentExpression is LambdaExpression; + var isBool = value != null && value.GetType() == UtilConstants.BoolType; + if (parentIsRoot && isBool) + { + this.Context.Result.Append(value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False()); + break; + } + if (parentIsBinary && isBool) + { + var isLogicOperator = + parameter.BaseExpression.NodeType == ExpressionType.And || + parameter.BaseExpression.NodeType == ExpressionType.AndAlso || + parameter.BaseExpression.NodeType == ExpressionType.Or || + parameter.BaseExpression.NodeType == ExpressionType.OrElse; + if (isLogicOperator) + { + AppendMember(parameter, isLeft, (value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False())); + break; + } + } + if (value == null && parentIsBinary) + { + parameter.BaseParameter.ValueIsNull = true; + value = this.Context.DbMehtods.Null(); + } + AppendValue(parameter, isLeft, value); + } + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/LambdaExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/LambdaExpressionResolve.cs new file mode 100644 index 0000000..fa63291 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/LambdaExpressionResolve.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class LambdaExpressionResolve : BaseResolve + { + public LambdaExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + LambdaExpression lambda = base.Expression as LambdaExpression; + var expression = lambda.Body; + base.Expression = expression; + if (parameter.Context.ResolveType.IsIn(ResolveExpressType.FieldMultiple, ResolveExpressType.FieldSingle)) { + parameter.CommonTempData = CommonTempDataType.Append; + } + base.Start(); + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberConstExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberConstExpressionResolve.cs new file mode 100644 index 0000000..8835c3f --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberConstExpressionResolve.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MemberConstExpressionResolve : BaseResolve + { + public MemberConstExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as MemberExpression; + var isLeft = parameter.IsLeft; + object value = ExpressionTool.GetMemberValue(expression.Member, expression); + var baseParameter = parameter.BaseParameter; + var isSetTempData = baseParameter.CommonTempData.HasValue() && baseParameter.CommonTempData.Equals(CommonTempDataType.Result); + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.Update: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + if (value != null && value.GetType().IsEnum()) + { + value = Convert.ToInt64(value); + } + parameter.BaseParameter.CommonTempData = value; + break; + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + AppendValue(parameter, isLeft, value); + } + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + break; + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs new file mode 100644 index 0000000..261232a --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberExpressionResolve.cs @@ -0,0 +1,438 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class MemberExpressionResolve : BaseResolve + { + public ExpressionParameter Parameter { get; set; } + public MemberExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + ExpressionParameter baseParameter; + MemberExpression expression; + bool? isLeft; + bool isSetTempData, isValue, isValueBool, isLength, isDateValue, isHasValue, isDateDate, isMemberValue, isSingle, fieldIsBool, isSelectField, isField; + SettingParameters(parameter, out baseParameter, out expression, out isLeft, out isSetTempData, out isValue, out isValueBool, out isLength, out isDateValue, out isHasValue, out isDateDate, out isMemberValue, out isSingle, out fieldIsBool, out isSelectField, out isField); + baseParameter.ChildExpression = expression; + if (isLength) + { + ResolveLength(parameter, isLeft, expression); + } + else if (isHasValue) + { + ResolveHasValue(parameter, expression); + } + else if (isDateValue) + { + ResolveDateValue(parameter, isLeft, expression); + } + else if (isValueBool) + { + ResolveValueBool(parameter, baseParameter, expression, isLeft, isSingle); + } + else if (isValue) + { + ResolveValue(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + else if (isDateDate) + { + ResolveDateDate(parameter, isLeft, expression); + } + else if (isMemberValue) + { + ResolveMemberValue(parameter, baseParameter, isLeft, isSetTempData, expression); + } + else if (fieldIsBool && !isField && !isSelectField) + { + ResolvefieldIsBool(parameter, baseParameter, isLeft, isSetTempData, expression, isSingle); + } + else + { + ResolveDefault(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + } + + #region Resolve default + private void ResolveDefault(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + string fieldName = string.Empty; + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.Update: + case ResolveExpressType.SelectSingle: + fieldName = GetSingleName(parameter, expression, isLeft); + if (isSetTempData) + baseParameter.CommonTempData = fieldName; + else + base.Context.Result.Append(fieldName); + break; + case ResolveExpressType.SelectMultiple: + fieldName = GetMultipleName(parameter, expression, isLeft); + if (isSetTempData) + baseParameter.CommonTempData = fieldName; + else + base.Context.Result.Append(fieldName); + break; + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + ResolveWhereLogic(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + break; + case ResolveExpressType.FieldSingle: + fieldName = GetSingleName(parameter, expression, isLeft); + base.Context.Result.Append(fieldName); + break; + case ResolveExpressType.FieldMultiple: + fieldName = GetMultipleName(parameter, expression, isLeft); + base.Context.Result.Append(fieldName); + break; + case ResolveExpressType.ArrayMultiple: + case ResolveExpressType.ArraySingle: + fieldName = GetName(parameter, expression, isLeft, parameter.Context.ResolveType == ResolveExpressType.ArraySingle); + base.Context.Result.Append(fieldName); + break; + default: + break; + } + } + + #endregion + + #region Resolve Where + private void ResolveBoolLogic(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + string fieldName = string.Empty; + if (isSetTempData) + { + if (ExpressionTool.IsConstExpression(expression)) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + baseParameter.CommonTempData = value+"=1 "; + } + else + { + fieldName = GetName(parameter, expression, null, isSingle); + baseParameter.CommonTempData = fieldName+"=1 "; + } + } + else + { + if (ExpressionTool.IsConstExpression(expression)) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + base.AppendValue(parameter, isLeft, value+"=1 "); + } + else + { + fieldName = GetName(parameter, expression, isLeft, isSingle); + AppendMember(parameter, isLeft, fieldName+"=1 "); + } + } + } + + private void ResolveWhereLogic(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + string fieldName = string.Empty; + if (isSetTempData) + { + if (ExpressionTool.IsConstExpression(expression)) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + baseParameter.CommonTempData = value; + } + else + { + fieldName = GetName(parameter, expression, null, isSingle); + baseParameter.CommonTempData = fieldName; + } + } + else + { + if (ExpressionTool.IsConstExpression(expression)) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + base.AppendValue(parameter, isLeft, value); + } + else + { + fieldName = GetName(parameter, expression, isLeft, isSingle); + AppendMember(parameter, isLeft, fieldName); + } + } + } + #endregion + + #region Resolve special member + private MemberExpression ResolveValue(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSetTempData, bool isSingle) + { + expression = expression.Expression as MemberExpression; + baseParameter.ChildExpression = expression; + if (UtilMethods.GetUnderType(expression.Type) == UtilConstants.BoolType&¶meter.BaseExpression!=null&&ExpressionTool.IsLogicOperator(parameter.BaseExpression)) + { + ResolveBoolLogic(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + else + { + ResolveWhereLogic(parameter, baseParameter, expression, isLeft, isSetTempData, isSingle); + } + return expression; + } + + private void ResolveValueBool(ExpressionParameter parameter, ExpressionParameter baseParameter, MemberExpression expression, bool? isLeft, bool isSingle) + { + string fieldName = GetName(parameter, expression.Expression as MemberExpression, isLeft, isSingle); + if (expression.Type == UtilConstants.BoolType && baseParameter.OperatorValue.IsNullOrEmpty()) + { + fieldName = this.Context.DbMehtods.EqualTrue(fieldName); + } + AppendMember(parameter, isLeft, fieldName); + } + + private void ResolveMemberValue(ExpressionParameter parameter, ExpressionParameter baseParameter, bool? isLeft, bool isSetTempData, MemberExpression expression) + { + var value = ExpressionTool.GetMemberValue(expression.Member, expression); + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + AppendValue(parameter, isLeft, value); + } + } + private void ResolvefieldIsBool(ExpressionParameter parameter, ExpressionParameter baseParameter, bool? isLeft, bool isSetTempData, MemberExpression expression, bool isSingle) + { + var fieldName = GetName(parameter, expression, isLeft, isSingle); + if (isSetTempData) + { + baseParameter.CommonTempData = fieldName; + } + else + { + fieldName = this.Context.DbMehtods.EqualTrue(fieldName.ObjToString()); + AppendMember(parameter, isLeft, fieldName); + } + } + + private void ResolveDateDate(ExpressionParameter parameter, bool? isLeft, MemberExpression expression) + { + var name = expression.Member.Name; + var oldCommonTempDate = parameter.CommonTempData; + parameter.CommonTempData = CommonTempDataType.Result; + this.Expression = expression.Expression; + this.Start(); + var isConst = parameter.CommonTempData.GetType() == UtilConstants.DateType; + if (isConst) + { + AppendValue(parameter, isLeft, parameter.CommonTempData.ObjToDate().Date); + } + else + { + var GetYear = new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { IsMember=true, MemberName=parameter.CommonTempData, MemberValue=parameter.CommonTempData }, + new MethodCallExpressionArgs() { MemberName=DateType.Year, MemberValue=DateType.Year} + } + }; + AppendMember(parameter, isLeft, GetToDate(this.Context.DbMehtods.MergeString( + this.GetDateValue(parameter.CommonTempData, DateType.Year), + "'-'", + this.GetDateValue(parameter.CommonTempData, DateType.Month), + "'-'", + this.GetDateValue(parameter.CommonTempData, DateType.Day)))); + } + parameter.CommonTempData = oldCommonTempDate; + } + + private void ResolveDateValue(ExpressionParameter parameter, bool? isLeft, MemberExpression expression) + { + var name = expression.Member.Name; + var oldCommonTempDate = parameter.CommonTempData; + parameter.CommonTempData = CommonTempDataType.Result; + this.Expression = expression.Expression; + var isConst = this.Expression is ConstantExpression; + if (this.Expression.Type == UtilConstants.DateType && this.Expression.ToString() == "DateTime.Now") + { + this.Expression = expression; + var parameterName = base.AppendParameter(ExpressionTool.GetMemberValue(expression.Member, expression)); + base.AppendMember(parameter, isLeft, parameterName); + } + else + { + this.Start(); + var result = this.Context.DbMehtods.DateValue(new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { IsMember = !isConst, MemberName = parameter.CommonTempData, MemberValue = null }, + new MethodCallExpressionArgs() { IsMember = true, MemberName = name, MemberValue = name } + } + }); + base.AppendMember(parameter, isLeft, result); + } + parameter.CommonTempData = oldCommonTempDate; + } + + private void ResolveHasValue(ExpressionParameter parameter, MemberExpression expression) + { + parameter.CommonTempData = CommonTempDataType.Result; + this.Expression = expression.Expression; + this.Start(); + var methodParamter = new MethodCallExpressionArgs() { IsMember = true, MemberName = parameter.CommonTempData, MemberValue = null }; + var result = this.Context.DbMehtods.HasValue(new MethodCallExpressionModel() + { + Args = new List() { + methodParamter + } + }); + if (parameter.BaseExpression != null && ExpressionTool.IsLogicOperator(parameter.BaseExpression) && parameter.IsLeft == true) + { + if (base.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + base.Context.Result.Replace(ExpressionConst.FormatSymbol, ""); + } + this.Context.Result.Append(result+" "+ExpressionTool.GetOperator(parameter.BaseExpression.NodeType)+" "); + } + else + { + this.Context.Result.Append(result); + } + parameter.CommonTempData = null; + } + + private void ResolveLength(ExpressionParameter parameter, bool? isLeft, MemberExpression expression) + { + if (parameter.Context.ResolveType == ResolveExpressType.FieldSingle) + { + parameter.Context.ResolveType = ResolveExpressType.WhereSingle; + } + if (parameter.Context.ResolveType == ResolveExpressType.FieldMultiple) + { + parameter.Context.ResolveType = ResolveExpressType.WhereMultiple; + } + var oldCommonTempDate = parameter.CommonTempData; + parameter.CommonTempData = CommonTempDataType.Result; + this.Expression = expression.Expression; + var isConst = this.Expression is ConstantExpression; + this.Start(); + var methodParamter = new MethodCallExpressionArgs() { IsMember = !isConst, MemberName = parameter.CommonTempData, MemberValue = null }; + var result = this.Context.DbMehtods.Length(new MethodCallExpressionModel() + { + Args = new List() { + methodParamter + } + }); + base.AppendMember(parameter, isLeft, result); + parameter.CommonTempData = oldCommonTempDate; + } + #endregion + + #region Helper + private string AppendMember(ExpressionParameter parameter, bool? isLeft, string fieldName) + { + if (parameter.BaseExpression is BinaryExpression || (parameter.BaseParameter.CommonTempData != null && parameter.BaseParameter.CommonTempData.Equals(CommonTempDataType.Append))) + { + fieldName = string.Format(" {0} ", fieldName); + if (isLeft == true) + { + fieldName += ExpressionConst.ExpressionReplace + parameter.BaseParameter.Index; + } + if (base.Context.Result.Contains(ExpressionConst.FormatSymbol)) + { + base.Context.Result.Replace(ExpressionConst.FormatSymbol, fieldName); + } + else + { + base.Context.Result.Append(fieldName); + } + } + else + { + base.Context.Result.Append(fieldName); + } + + return fieldName; + } + + private string GetName(ExpressionParameter parameter, MemberExpression expression, bool? isLeft, bool isSingle) + { + if (isSingle) + { + return GetSingleName(parameter, expression, IsLeft); + } + else + { + return GetMultipleName(parameter, expression, IsLeft); + } + } + + private string GetMultipleName(ExpressionParameter parameter, MemberExpression expression, bool? isLeft) + { + string shortName = expression.Expression.ToString(); + string fieldName = expression.Member.Name; + fieldName = this.Context.GetDbColumnName(expression.Expression.Type.Name, fieldName); + fieldName = Context.GetTranslationColumnName(shortName + UtilConstants.Dot + fieldName); + return fieldName; + } + + private string GetSingleName(ExpressionParameter parameter, MemberExpression expression, bool? isLeft) + { + string fieldName = expression.Member.Name; + fieldName = this.Context.GetDbColumnName(expression.Expression.Type.Name, fieldName); + fieldName = Context.GetTranslationColumnName(fieldName); + return fieldName; + } + + private string GetDateValue(object value, DateType type) + { + var pars = new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { IsMember=true, MemberName=value, MemberValue=value }, + new MethodCallExpressionArgs() { MemberName=type, MemberValue=type} + } + }; + return this.Context.DbMehtods.DateValue(pars); + } + + private string GetToDate(string value) + { + var pars = new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { MemberName=value, MemberValue=value }, + } + }; + return this.Context.DbMehtods.ToDate(pars); + } + + private void SettingParameters(ExpressionParameter parameter, out ExpressionParameter baseParameter, out MemberExpression expression, out bool? isLeft, out bool isSetTempData, out bool isValue, out bool isValueBool, out bool isLength, out bool isDateValue, out bool isHasValue, out bool isDateDate, out bool isMemberValue, out bool isSingle, out bool fieldIsBool, out bool isSelectField, out bool isField) + { + baseParameter = parameter.BaseParameter; + expression = base.Expression as MemberExpression; + var childExpression = expression.Expression as MemberExpression; + var memberName = expression.Member.Name; + var childIsMember = childExpression != null; + var isRoot = parameter.BaseExpression == null; + isLeft = parameter.IsLeft; + isSetTempData = parameter.IsSetTempData; + isValue = memberName == "Value" && expression.Member.DeclaringType.Name == "Nullable`1"; + var isBool = expression.Type == UtilConstants.BoolType; + isValueBool = isValue && isBool && isRoot; + isLength = memberName == "Length" && childIsMember && childExpression.Type == UtilConstants.StringType; + isDateValue = memberName.IsIn(Enum.GetNames(typeof(DateType))) && (childIsMember && childExpression.Type == UtilConstants.DateType); + var isLogicOperator = ExpressionTool.IsLogicOperator(baseParameter.OperatorValue) || baseParameter.OperatorValue.IsNullOrEmpty(); + isHasValue = isLogicOperator && memberName == "HasValue" && expression.Expression != null && expression.NodeType == ExpressionType.MemberAccess; + isDateDate = memberName == "Date" && expression.Expression.Type == UtilConstants.DateType; + isMemberValue = expression.Expression != null && expression.Expression.NodeType != ExpressionType.Parameter && !isValueBool; + isSingle = parameter.Context.ResolveType.IsIn(ResolveExpressType.WhereSingle, ResolveExpressType.SelectSingle, ResolveExpressType.FieldSingle, ResolveExpressType.ArraySingle); + fieldIsBool = isBool && isLogicOperator && (parameter.BaseParameter == null || !(parameter.BaseParameter.CurrentExpression is MemberInitExpression || parameter.BaseParameter.CurrentExpression is NewExpression)); + var isSelect = this.Context.ResolveType.IsIn(ResolveExpressType.SelectSingle, ResolveExpressType.SelectMultiple); + isSelectField = isSelect && isRoot; + isField = this.Context.ResolveType.IsIn(ResolveExpressType.FieldSingle, ResolveExpressType.FieldMultiple); + } + + #endregion + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs new file mode 100644 index 0000000..54978a6 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MemberInitExpressionResolve : BaseResolve + { + public MemberInitExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as MemberInitExpression; + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + break; + case ResolveExpressType.WhereMultiple: + break; + case ResolveExpressType.SelectSingle: + Select(expression, parameter, true); + break; + case ResolveExpressType.SelectMultiple: + Select(expression, parameter, false); + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + case ResolveExpressType.Update: + Update(expression, parameter); + break; + default: + break; + } + } + + private void Update(MemberInitExpression expression, ExpressionParameter parameter) + { + int i = 0; + foreach (MemberBinding binding in expression.Bindings) + { + ++i; + if (binding.BindingType != MemberBindingType.Assignment) + { + throw new NotSupportedException(); + } + MemberAssignment memberAssignment = (MemberAssignment)binding; + var type =expression.Type; + var memberName = this.Context.GetDbColumnName(type.Name, memberAssignment.Member.Name); + var item = memberAssignment.Expression; + if ((item is MemberExpression) && ((MemberExpression)item).Expression == null) + { + var paramterValue = ExpressionTool.DynamicInvoke(item); + string parameterName = AppendParameter(paramterValue); + this.Context.Result.Append(base.Context.GetEqString(memberName, parameterName)); + } + else if (IsMethod(item)) + { + if (item is UnaryExpression) + item = (item as UnaryExpression).Operand; + var callMethod = item as MethodCallExpression; + if (MethodTimeMapping.Any(it => it.Key == callMethod.Method.Name) || MethodMapping.Any(it=>it.Key==callMethod.Method.Name)||IsExtMethod(callMethod.Method.Name)||IsSubMethod(callMethod)|| callMethod.Method.DeclaringType.FullName.StartsWith(UtilConstants.AssemblyName+UtilConstants.Dot)) + { + MethodCall(parameter, memberName, item); + } + else + { + var paramterValue = ExpressionTool.DynamicInvoke(item); + string parameterName = AppendParameter(paramterValue); + this.Context.Result.Append(base.Context.GetEqString(memberName, parameterName)); + } + } + else if (IsConst(item)) + { + base.Expression = item; + base.Start(); + string parameterName = this.Context.SqlParameterKeyWord + ExpressionConst.Const + this.Context.ParameterIndex; + parameter.Context.Result.Append(base.Context.GetEqString(memberName, parameterName)); + this.Context.Parameters.Add(new SugarParameter(parameterName, parameter.CommonTempData)); + this.Context.ParameterIndex++; + } + else if (item is MemberExpression) + { + if (base.Context.Result.IsLockCurrentParameter == false) + { + base.Context.Result.CurrentParameter = parameter; + base.Context.Result.IsLockCurrentParameter = true; + parameter.IsAppendTempDate(); + base.Expression = item; + base.Start(); + parameter.IsAppendResult(); + parameter.Context.Result.Append(base.Context.GetEqString(memberName, parameter.CommonTempData.ObjToString())); + base.Context.Result.CurrentParameter = null; + } + } + else if (item is BinaryExpression) + { + var result = GetNewExpressionValue(item); + this.Context.Result.Append(base.Context.GetEqString(memberName, result)); + } + } + } + + private static bool IsConst(Expression item) + { + return item is UnaryExpression || item.NodeType == ExpressionType.Constant || (item is MemberExpression) && ((MemberExpression)item).Expression.NodeType == ExpressionType.Constant; + } + + private static bool IsMethod(Expression item) + { + return item is MethodCallExpression || (item is UnaryExpression && (item as UnaryExpression).Operand is MethodCallExpression); + } + + private void MethodCall(ExpressionParameter parameter, string memberName, Expression item) + { + if (IsSubMethod(item as MethodCallExpression)) + { + UtilMethods.GetOldValue(parameter.CommonTempData, () => + { + parameter.CommonTempData = CommonTempDataType.Result; + base.Expression = item; + base.Start(); + var subSql = base.Context.GetEqString(memberName, parameter.CommonTempData.ObjToString()); + if (ResolveExpressType.Update == this.Context.ResolveType) + { + subSql = Regex.Replace(subSql, @" \[\w+?\]\.| ""\w+?""\.| \`\w+?\`\.", this.Context.GetTranslationTableName(parameter.CurrentExpression.Type.Name,true) +"."); + } + parameter.Context.Result.Append(subSql); + }); + } + else + { + base.Expression = item; + base.Start(); + parameter.Context.Result.Append(base.Context.GetEqString(memberName, parameter.CommonTempData.ObjToString().Replace(",", UtilConstants.ReplaceCommaKey))); + } + } + + private void Select(MemberInitExpression expression, ExpressionParameter parameter, bool isSingle) + { + foreach (MemberBinding binding in expression.Bindings) + { + if (binding.BindingType != MemberBindingType.Assignment) + { + throw new NotSupportedException(); + } + MemberAssignment memberAssignment = (MemberAssignment)binding; + var memberName = memberAssignment.Member.Name; + var item = memberAssignment.Expression; + ResolveNewExpressions(parameter, item, memberName); + } + } + + private bool IsSubMethod(MethodCallExpression express) + { + return SubTools.SubItemsConst.Any(it =>express.Object != null && express.Object.Type.Name == "Subqueryable`1"); + } + private bool IsExtMethod(string methodName) + { + if (this.Context.SqlFuncServices == null) return false; + return this.Context.SqlFuncServices.Select(it => it.UniqueMethodName).Contains(methodName); + } + private bool CheckMethod(MethodCallExpression expression) + { + if (IsExtMethod(expression.Method.Name)) + return true; + if (expression.Method.ReflectedType().FullName != ExpressionConst.SqlFuncFullName) + return false; + else + return true; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberNewExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberNewExpressionResolve.cs new file mode 100644 index 0000000..22f28c1 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberNewExpressionResolve.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MemberNewExpressionResolve : BaseResolve + { + public MemberNewExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as MemberExpression; + var isLeft = parameter.IsLeft; + object value = null; + value = ExpressionTool.DynamicInvoke(expression); + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberNoExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberNoExpressionResolve.cs new file mode 100644 index 0000000..2a926d6 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MemberNoExpressionResolve.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MemberNoExpressionResolve : BaseResolve + { + public MemberNoExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as MemberExpression; + var isLeft = parameter.IsLeft; + object value = null; + var isField = expression.Member is System.Reflection.FieldInfo; + var isProperty = expression.Member is System.Reflection.PropertyInfo; + var baseParameter = parameter.BaseParameter; + var isSetTempData = baseParameter.CommonTempData.HasValue() && baseParameter.CommonTempData.Equals(CommonTempDataType.Result); + if (isField) + { + value = ExpressionTool.GetFiledValue(expression); + } + else if (isProperty) + { + value = ExpressionTool.GetPropertyValue(expression); + } + switch (base.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + AppendValue(parameter, isLeft, value); + } + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + default: + break; + } + } + } + +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs new file mode 100644 index 0000000..58f0285 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/MethodCallExpressionResolve.cs @@ -0,0 +1,604 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class MethodCallExpressionResolve : BaseResolve + { + int contextIndex = 0; + public MethodCallExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + contextIndex = this.Context.Index; + var express = base.Expression as MethodCallExpression; + if (express == null) return; + var isLeft = parameter.IsLeft; + string methodName = express.Method.Name; + var isValidNativeMethod = IsValidNativeMethod(express, methodName); + List appendArgs = null; + if (MethodTimeMapping.ContainsKey(methodName)) + { + appendArgs = new List(); + var dateType = MethodTimeMapping[methodName]; + string paramterName = this.Context.SqlParameterKeyWord + ExpressionConst.Const + this.Context.ParameterIndex; + appendArgs.Add(new MethodCallExpressionArgs() { IsMember = false, MemberName = paramterName, MemberValue = dateType }); + this.Context.Parameters.Add(new SugarParameter(paramterName, dateType.ToString())); + this.Context.ParameterIndex++; + methodName = "DateAdd"; + isValidNativeMethod = true; + } + else if (methodName == "get_Item") + { + string paramterName = this.Context.SqlParameterKeyWord + ExpressionConst.Const + this.Context.ParameterIndex; + this.Context.Parameters.Add(new SugarParameter(paramterName, ExpressionTool.DynamicInvoke(express))); + this.Context.Result.Append(string.Format(" {0} ", paramterName)); + this.Context.ParameterIndex++; + return; + } + else if (methodName == "NewGuid") + { + this.Context.Result.Append(this.Context.DbMehtods.GuidNew()); + return; + } + else if (IsSubMethod(express, methodName)) + { + //Check.Exception(!(parameter.BaseExpression is BinaryExpression), "Current expressions are not supported"); + SubResolve subResolve = new SubResolve(express, this.Context, parameter.OppsiteExpression); + var appendSql = subResolve.GetSql(); + if (this.Context.ResolveType.IsIn(ResolveExpressType.SelectMultiple, ResolveExpressType.SelectSingle)||(parameter.BaseParameter!=null&¶meter.BaseParameter.CommonTempData!=null&¶meter.BaseParameter.CommonTempData.Equals(CommonTempDataType.Result))) + { + parameter.BaseParameter.CommonTempData = appendSql; + } + else + { + base.AppendValue(parameter, isLeft, appendSql); + } + return; + } + else if (IsIfElse(express, methodName)) + { + CaseWhenResolve caseResole = new CaseWhenResolve(express, this.Context, parameter.OppsiteExpression); + var appendSql = caseResole.GetSql(); + var isRoot = contextIndex == 2&¶meter.BaseExpression==null; + if (isRoot||(parameter.BaseExpression!=null&&ExpressionTool.IsLogicOperator(parameter.BaseExpression))) { + appendSql= appendSql+"=1 "; + } + if (this.Context.ResolveType.IsIn(ResolveExpressType.SelectMultiple, ResolveExpressType.SelectSingle,ResolveExpressType.Update)) + { + parameter.BaseParameter.CommonTempData = appendSql; + } + else + { + base.AppendValue(parameter, isLeft, appendSql); + } + return; + } + if (IsContainsArray(express, methodName, isValidNativeMethod)) + { + methodName = "ContainsArray"; + isValidNativeMethod = true; + } + if (isValidNativeMethod) + { + NativeExtensionMethod(parameter, express, isLeft, MethodMapping[methodName], appendArgs); + } + else + { + SqlFuncMethod(parameter, express, isLeft); + } + } + + private bool IsValidNativeMethod(MethodCallExpression express, string methodName) + { + return MethodMapping.ContainsKey(methodName) && express.Method.DeclaringType.Namespace == ("System"); + } + + private bool IsExtMethod(string methodName) + { + if (this.Context.SqlFuncServices == null) return false; + return this.Context.SqlFuncServices.Select(it => it.UniqueMethodName).Contains(methodName); + } + + private bool IsIfElse(MethodCallExpression express, string methodName) + { + if (methodName == "End"&& express.Object.Type==typeof(CaseWhen)) + return true; + else + return false; + } + + protected void SqlFuncMethod(ExpressionParameter parameter, MethodCallExpression express, bool? isLeft) + { + if (!CheckMethod(express)) + { + CusMethod(parameter, express, isLeft); + } + else + { + var method = express.Method; + string name = method.Name; + var args = express.Arguments.Cast().ToList(); + MethodCallExpressionModel model = new MethodCallExpressionModel(); + model.Args = new List(); + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + Check.Exception(name == "GetSelfAndAutoFill", "SqlFunc.GetSelfAndAutoFill can only be used in Select."); + Where(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + Select(parameter, isLeft, name, args, model); + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + Field(parameter, isLeft, name, args, model); + break; + default: + break; + } + } + } + + private void CusMethod(ExpressionParameter parameter, MethodCallExpression express, bool? isLeft) + { + try + { + var constValue = ExpressionTool.DynamicInvoke(express); + parameter.BaseParameter.CommonTempData = constValue; + var parameterName = base.AppendParameter(constValue); + if (parameter.BaseParameter.CommonTempData != null && parameter.BaseParameter.CommonTempData.Equals(CommonTempDataType.Result)) + { + this.Context.Result.Append(parameterName); + } + else + { + base.AppendValue(parameter, isLeft, parameterName); + } + } + catch + { + Check.Exception(true, string.Format(ErrorMessage.MethodError, express.Method.Name)); + } + } + + private void NativeExtensionMethod(ExpressionParameter parameter, MethodCallExpression express, bool? isLeft, string name, List appendArgs = null) + { + var method = express.Method; + var args = express.Arguments.Cast().ToList(); + MethodCallExpressionModel model = new MethodCallExpressionModel(); + model.Args = new List(); + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + if (express.Object != null) + args.Insert(0, express.Object); + Where(parameter, isLeft, name, args, model, appendArgs); + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.Update: + if (express.Object != null) + args.Insert(0, express.Object); + Select(parameter, isLeft, name, args, model, appendArgs); + break; + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + default: + break; + } + } + + protected void Field(ExpressionParameter parameter, bool? isLeft, string name, IEnumerable args, MethodCallExpressionModel model, List appendArgs = null) + { + if (this.Context.ResolveType == ResolveExpressType.FieldSingle) + { + this.Context.ResolveType = ResolveExpressType.WhereSingle; + } + else + { + this.Context.ResolveType = ResolveExpressType.WhereMultiple; + } + Where(parameter, isLeft, name, args, model); + } + protected void Select(ExpressionParameter parameter, bool? isLeft, string name, IEnumerable args, MethodCallExpressionModel model, List appendArgs = null) + { + if (name == "GetSelfAndAutoFill") + { + var memberValue = (args.First() as MemberExpression).Expression.ToString(); + model.Args.Add(new MethodCallExpressionArgs() { MemberValue = memberValue, IsMember = true, MemberName = memberValue }); + } + else + { + foreach (var item in args) + { + AppendItem(parameter, name, args, model, item); + } + if (appendArgs != null) + { + model.Args.AddRange(appendArgs); + } + } + if (parameter.BaseParameter.BaseParameter.BaseParameter == null) + { + this.Context.Result.Append(GetMethodValue(name, model)); + } + else + { + parameter.BaseParameter.CommonTempData = GetMethodValue(name, model); + } + } + protected void Where(ExpressionParameter parameter, bool? isLeft, string name, IEnumerable args, MethodCallExpressionModel model, List appendArgs = null) + { + foreach (var item in args) + { + var expItem = item; + if (item is UnaryExpression) { + expItem = (item as UnaryExpression).Operand; + } + AppendItem(parameter, name, args, model, expItem); + } + if (appendArgs != null) + { + model.Args.AddRange(appendArgs); + } + var methodValue = GetMethodValue(name, model); + if (parameter.BaseExpression is BinaryExpression && parameter.OppsiteExpression.Type == UtilConstants.BoolType&&name=="HasValue"&&!(parameter.OppsiteExpression is BinaryExpression)&& !(parameter.OppsiteExpression is MethodCallExpression && parameter.OppsiteExpression.Type == UtilConstants.BoolType)) { + methodValue = this.Context.DbMehtods.CaseWhen(new List>() { + new KeyValuePair("IF",methodValue.ObjToString()), + new KeyValuePair("Return","1"), + new KeyValuePair("End","0") + }); + } + var isRoot = contextIndex == 2; + if (isRoot && parameter.BaseExpression == null &&this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple,ResolveExpressType.WhereSingle)&& (parameter.CurrentExpression is MethodCallExpression) && ((parameter.CurrentExpression as MethodCallExpression).Method.Name.IsIn("ToBool", "ToBoolean"))) + { + methodValue = methodValue + "=1 "; +; } + if (isRoot && parameter.BaseExpression == null && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is ConditionalExpression) && ((parameter.CurrentExpression as ConditionalExpression).Type==UtilConstants.BoolType)) + { + methodValue = methodValue + "=1 "; + } + if (isRoot && parameter.BaseExpression == null && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is MethodCallExpression) && ((parameter.CurrentExpression as MethodCallExpression).Method.Name.IsIn("IIF"))&& (parameter.CurrentExpression as MethodCallExpression).Method.ReturnType==UtilConstants.BoolType) + { + methodValue = methodValue + "=1 "; + } + if (parameter.BaseExpression != null&&ExpressionTool.IsLogicOperator(parameter.BaseExpression) && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is ConditionalExpression) && ((parameter.CurrentExpression as ConditionalExpression).Type == UtilConstants.BoolType)) + { + methodValue = methodValue + "=1 "; + } + if (parameter.BaseExpression != null && ExpressionTool.IsLogicOperator(parameter.BaseExpression) && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is MethodCallExpression) && ((parameter.CurrentExpression as MethodCallExpression).Method.Name.IsIn("IIF")) && (parameter.CurrentExpression as MethodCallExpression).Method.ReturnType == UtilConstants.BoolType) + { + methodValue = methodValue + "=1 "; + } + if (parameter.BaseExpression != null&& ExpressionTool.IsLogicOperator(parameter.BaseExpression) && this.Context.ResolveType.IsIn(ResolveExpressType.WhereMultiple, ResolveExpressType.WhereSingle) && (parameter.CurrentExpression is MethodCallExpression) && ((parameter.CurrentExpression as MethodCallExpression).Method.Name.IsIn("ToBool", "ToBoolean"))) + { + methodValue = methodValue + "=1 "; + } + base.AppendValue(parameter, isLeft, methodValue); + } + + private void AppendItem(ExpressionParameter parameter, string name, IEnumerable args, MethodCallExpressionModel model, Expression item) + { + var isBinaryExpression = item is BinaryExpression || item is MethodCallExpression; + var isConst = item is ConstantExpression; + var isIIF = name == "IIF"; + var isIFFBoolMember = isIIF && (item is MemberExpression) && (item as MemberExpression).Type == UtilConstants.BoolType; + var isIFFUnary = isIIF && (item is UnaryExpression) && (item as UnaryExpression).Operand.Type == UtilConstants.BoolType; + var isIFFBoolBinary = isIIF && (item is BinaryExpression) && (item as BinaryExpression).Type == UtilConstants.BoolType; + var isIFFBoolMethod = isIIF && (item is MethodCallExpression) && (item as MethodCallExpression).Type == UtilConstants.BoolType; + var isFirst = item == args.First(); + if (isFirst && isIIF && isConst) + { + var value = (item as ConstantExpression).Value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False(); + var methodCallExpressionArgs = new MethodCallExpressionArgs() + { + IsMember = true, + MemberName = value, + MemberValue = value + }; + model.Args.Add(methodCallExpressionArgs); + } + else if (isIFFUnary && !isFirst) + { + AppendModelByIIFMember(parameter, model, (item as UnaryExpression).Operand); + } + else if (isIFFBoolMember && !isFirst) + { + AppendModelByIIFMember(parameter, model, item); + + } + else if (isIFFBoolBinary && !isFirst) + { + AppendModelByIIFBinary(parameter, model, item); + + } + else if (isIFFBoolMethod && !isFirst) + { + AppendModelByIIFMethod(parameter, model, item); + } + else if (isBinaryExpression) + { + model.Args.Add(GetMethodCallArgs(parameter, item)); + } + else + { + AppendModel(parameter, model, item); + } + } + private void AppendModelByIIFMember(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) + { + parameter.CommonTempData = CommonTempDataType.Result; + base.Expression = item; + base.Start(); + var methodCallExpressionArgs = new MethodCallExpressionArgs() + { + IsMember = parameter.ChildExpression is MemberExpression, + MemberName = parameter.CommonTempData + }; + if (methodCallExpressionArgs.IsMember && parameter.ChildExpression != null && parameter.ChildExpression.ToString() == "DateTime.Now") + { + methodCallExpressionArgs.IsMember = false; + } + var value = methodCallExpressionArgs.MemberName; + if (methodCallExpressionArgs.IsMember) + { + var childExpression = parameter.ChildExpression as MemberExpression; + if (childExpression.Expression != null && childExpression.Expression is ConstantExpression) + { + methodCallExpressionArgs.IsMember = false; + } + } + if (methodCallExpressionArgs.IsMember == false) + { + var parameterName = this.Context.SqlParameterKeyWord + ExpressionConst.MethodConst + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + methodCallExpressionArgs.MemberName = parameterName; + methodCallExpressionArgs.MemberValue = value; + this.Context.Parameters.Add(new SugarParameter(parameterName, value)); + } + model.Args.Add(methodCallExpressionArgs); + parameter.ChildExpression = null; + } + private void AppendModelByIIFBinary(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) + { + Check.Exception(true, "The SqlFunc.IIF(arg1,arg2,arg3) , {0} argument do not support ", item.ToString()); + } + private void AppendModelByIIFMethod(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) + { + var methodExpression = item as MethodCallExpression; + if (methodExpression.Method.Name.IsIn("ToBool", "ToBoolean", "IIF")) + { + model.Args.Add(base.GetMethodCallArgs(parameter, item)); + } + else + { + Check.Exception(true, "The SqlFunc.IIF(arg1,arg2,arg3) , {0} argument do not support ", item.ToString()); + } + } + private void AppendModel(ExpressionParameter parameter, MethodCallExpressionModel model, Expression item) + { + parameter.CommonTempData = CommonTempDataType.Result; + base.Expression = item; + base.Start(); + var methodCallExpressionArgs = new MethodCallExpressionArgs() + { + IsMember = parameter.ChildExpression is MemberExpression && !ExpressionTool.IsConstExpression(parameter.ChildExpression as MemberExpression), + MemberName = parameter.CommonTempData + }; + if (methodCallExpressionArgs.IsMember && parameter.ChildExpression != null && parameter.ChildExpression.ToString() == "DateTime.Now") + { + methodCallExpressionArgs.IsMember = false; + } + var value = methodCallExpressionArgs.MemberName; + if (methodCallExpressionArgs.IsMember) + { + var childExpression = parameter.ChildExpression as MemberExpression; + if (childExpression.Expression != null && childExpression.Expression is ConstantExpression) + { + methodCallExpressionArgs.IsMember = false; + } + } + if (methodCallExpressionArgs.IsMember == false) + { + var parameterName = this.Context.SqlParameterKeyWord + ExpressionConst.MethodConst + this.Context.ParameterIndex; + this.Context.ParameterIndex++; + methodCallExpressionArgs.MemberName = parameterName; + methodCallExpressionArgs.MemberValue = value; + this.Context.Parameters.Add(new SugarParameter(parameterName, value)); + } + model.Args.Add(methodCallExpressionArgs); + parameter.ChildExpression = null; + } + + private object GetMethodValue(string name, MethodCallExpressionModel model) + { + if (IsExtMethod(name)) + { + DbType type = DbType.SqlServer; + if (this.Context is SqlServerExpressionContext) + type = DbType.SqlServer; + else if (this.Context is MySqlExpressionContext) + type = DbType.MySql; + else if (this.Context is SqliteExpressionContext) + type = DbType.Sqlite; + else if(this.Context is OracleExpressionContext) + type = DbType.Oracle; + return this.Context.SqlFuncServices.First(it => it.UniqueMethodName == name).MethodValue(model,type,this.Context); + } + else + { + if (name == "Parse" && TempParseType.IsIn(UtilConstants.GuidType)) + { + name = "Equals"; + } + else if(name== "Parse") + { + name = "To"+TempParseType.Name; + } + switch (name) + { + case "IIF": + return this.Context.DbMehtods.IIF(model); + case "HasNumber": + return this.Context.DbMehtods.HasNumber(model); + case "HasValue": + return this.Context.DbMehtods.HasValue(model); + case "IsNullOrEmpty": + return this.Context.DbMehtods.IsNullOrEmpty(model); + case "ToLower": + return this.Context.DbMehtods.ToLower(model); + case "ToUpper": + return this.Context.DbMehtods.ToUpper(model); + case "Trim": + return this.Context.DbMehtods.Trim(model); + case "Contains": + return this.Context.DbMehtods.Contains(model); + case "ContainsArray": + var caResult = this.Context.DbMehtods.ContainsArray(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); + return caResult; + case "Equals": + return this.Context.DbMehtods.Equals(model); + case "DateIsSame": + if (model.Args.Count == 2) + return this.Context.DbMehtods.DateIsSameDay(model); + else + { + var dsResult = this.Context.DbMehtods.DateIsSameByType(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[2].MemberName.ObjToString()); + return dsResult; + } + case "DateAdd": + if (model.Args.Count == 2) + return this.Context.DbMehtods.DateAddDay(model); + else + { + var daResult = this.Context.DbMehtods.DateAddByType(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[2].MemberName.ObjToString()); + return daResult; + } + case "DateValue": + var dvResult = this.Context.DbMehtods.DateValue(model); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[1].MemberName.ObjToString()); + return dvResult; + case "Between": + return this.Context.DbMehtods.Between(model); + case "StartsWith": + return this.Context.DbMehtods.StartsWith(model); + case "EndsWith": + return this.Context.DbMehtods.EndsWith(model); + case "ToInt32": + return this.Context.DbMehtods.ToInt32(model); + case "ToInt64": + return this.Context.DbMehtods.ToInt64(model); + case "ToDate": + return this.Context.DbMehtods.ToDate(model); + case "ToDateTime": + return this.Context.DbMehtods.ToDate(model); + case "ToTime": + return this.Context.DbMehtods.ToTime(model); + case "ToString": + Check.Exception(model.Args.Count > 1, "ToString (Format) is not supported, Use ToString().If time formatting can be used it.Date.Year+\"-\"+it.Data.Month+\"-\"+it.Date.Day "); + return this.Context.DbMehtods.ToString(model); + case "ToDecimal": + return this.Context.DbMehtods.ToDecimal(model); + case "ToGuid": + return this.Context.DbMehtods.ToGuid(model); + case "ToDouble": + return this.Context.DbMehtods.ToDouble(model); + case "ToBool": + return this.Context.DbMehtods.ToBool(model); + case "ToBoolean": + return this.Context.DbMehtods.ToBool(model); + case "Substring": + return this.Context.DbMehtods.Substring(model); + case "Replace": + return this.Context.DbMehtods.Replace(model); + case "Length": + return this.Context.DbMehtods.Length(model); + case "AggregateSum": + return this.Context.DbMehtods.AggregateSum(model); + case "AggregateAvg": + return this.Context.DbMehtods.AggregateAvg(model); + case "AggregateMin": + return this.Context.DbMehtods.AggregateMin(model); + case "AggregateMax": + return this.Context.DbMehtods.AggregateMax(model); + case "AggregateCount": + return this.Context.DbMehtods.AggregateCount(model); + case "MappingColumn": + var mappingColumnResult = this.Context.DbMehtods.MappingColumn(model); + var isValid = model.Args[0].IsMember && model.Args[1].IsMember == false; + Check.Exception(!isValid, "SqlFunc.MappingColumn parameters error, The property name on the left, string value on the right"); + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[1].MemberName.ObjToString()); + return mappingColumnResult; + case "IsNull": + return this.Context.DbMehtods.IsNull(model); + case "MergeString": + return this.Context.DbMehtods.MergeString(model.Args.Select(it => it.MemberName.ObjToString()).ToArray()); + case "GetSelfAndAutoFill": + this.Context.Parameters.RemoveAll(it => it.ParameterName == model.Args[0].MemberName.ObjToString()); + return this.Context.DbMehtods.GetSelfAndAutoFill(model.Args[0].MemberValue.ObjToString(), this.Context.IsSingle); + case "GetDate": + return this.Context.DbMehtods.GetDate(); + case "GetRandom": + return this.Context.DbMehtods.GetRandom(); + default: + break; + } + } + return null; + } + + private bool IsContainsArray(MethodCallExpression express, string methodName, bool isValidNativeMethod) + { + return !isValidNativeMethod && express.Method.DeclaringType.Namespace.IsIn("System.Linq", "System.Collections.Generic") && methodName == "Contains"; + } + + private bool IsSubMethod(MethodCallExpression express, string methodName) + { + return SubTools.SubItemsConst.Any(it => it.Name == methodName) && express.Object != null && express.Object.Type.Name == "Subqueryable`1"; + } + private bool CheckMethod(MethodCallExpression expression) + { + if (IsExtMethod(expression.Method.Name)) + return true; + if (IsParseMethod(expression)) + return true; + if (expression.Method.Name == "IsNullOrEmpty"&&expression.Method.DeclaringType==UtilConstants.StringType) + { + return true; + } + if (expression.Method.ReflectedType().FullName != ExpressionConst.SqlFuncFullName) + return false; + else + return true; + } + private Type TempParseType; + public bool IsParseMethod(MethodCallExpression expression) + { + if (expression.Method.Name == "Parse"&&expression.Method.DeclaringType.IsIn( + UtilConstants.DecType, + UtilConstants.DateType, + UtilConstants.DobType, + UtilConstants.GuidType, + UtilConstants.FloatType, + UtilConstants.ShortType, + UtilConstants.LongType, + UtilConstants.IntType, + UtilConstants.BoolType)) + { + TempParseType = expression.Method.DeclaringType; + return true; + } + return false; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/NewArrayExpessionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/NewArrayExpessionResolve.cs new file mode 100644 index 0000000..2ad08a9 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/NewArrayExpessionResolve.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class NewArrayExpessionResolve : BaseResolve + { + public NewArrayExpessionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = (NewArrayExpression)base.Expression; + switch (base.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + try + { + var value = ExpressionTool.DynamicInvoke(expression); + var isLeft = parameter.IsLeft; + var baseParameter = parameter.BaseParameter; + var isSetTempData = baseParameter.CommonTempData.HasValue() && baseParameter.CommonTempData.Equals(CommonTempDataType.Result); + if (isSetTempData) + { + baseParameter.CommonTempData = value; + } + else + { + var parentIsBinary = parameter.BaseParameter.CurrentExpression is BinaryExpression; + var parentIsRoot = parameter.BaseParameter.CurrentExpression is LambdaExpression; + var isBool = value != null && value.GetType() == UtilConstants.BoolType; + if (parentIsRoot && isBool) + { + this.Context.Result.Append(value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False()); + break; + } + if (parentIsBinary && isBool) + { + var isLogicOperator = + parameter.BaseExpression.NodeType == ExpressionType.And || + parameter.BaseExpression.NodeType == ExpressionType.AndAlso || + parameter.BaseExpression.NodeType == ExpressionType.Or || + parameter.BaseExpression.NodeType == ExpressionType.OrElse; + if (isLogicOperator) + { + AppendMember(parameter, isLeft, (value.ObjToBool() ? this.Context.DbMehtods.True() : this.Context.DbMehtods.False())); + break; + } + } + if (value == null && parentIsBinary) + { + parameter.BaseParameter.ValueIsNull = true; + value = this.Context.DbMehtods.Null(); + } + AppendValue(parameter, isLeft, value); + } + } + catch (Exception) + { + Check.ThrowNotSupportedException("NewArrayExpression"); + } + break; + case ResolveExpressType.ArraySingle: + foreach (var item in expression.Expressions) + { + base.Expression = item; + base.Start(); + } + break; + case ResolveExpressType.Join: + base.Context.ResolveType = ResolveExpressType.WhereMultiple; + int i = 0; + foreach (var item in expression.Expressions) + { + if (item is UnaryExpression) + { + base.Expression = item; + base.Start(); + if (parameter.CommonTempData is JoinType) + { + if (i > 0) + { + base.Context.Result.Append("," + parameter.CommonTempData.ObjToString().Replace(",",UtilConstants.ReplaceCommaKey) + ","); + } + else + { + base.Context.Result.Append(parameter.CommonTempData.ObjToString().Replace(",", UtilConstants.ReplaceCommaKey) + ","); + } + ++i; + } + } + } + break; + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs new file mode 100644 index 0000000..55f4c65 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/NewExpressionResolve.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class NewExpressionResolve : BaseResolve + { + public NewExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as NewExpression; + Check.Exception(expression.Type == UtilConstants.GuidType, "Not Support new Guid(), Use Guid.New()"); + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + Check.ThrowNotSupportedException(expression.ToString()); + break; + case ResolveExpressType.WhereMultiple: + Check.ThrowNotSupportedException(expression.ToString()); + break; + case ResolveExpressType.SelectSingle: + Check.Exception(expression.Type == UtilConstants.DateType, "ThrowNotSupportedException {0} ",expression.ToString()); + Select(expression, parameter, true); + break; + case ResolveExpressType.SelectMultiple: + Check.Exception(expression.Type == UtilConstants.DateType, "ThrowNotSupportedException {0} ", expression.ToString()); + Select(expression, parameter, false); + break; + case ResolveExpressType.FieldSingle: + Check.ThrowNotSupportedException(expression.ToString()); + break; + case ResolveExpressType.FieldMultiple: + case ResolveExpressType.ArrayMultiple: + case ResolveExpressType.ArraySingle: + foreach (var item in expression.Arguments) + { + base.Expression = item; + base.Start(); + } + break; + default: + break; + } + } + + private void Select(NewExpression expression, ExpressionParameter parameter, bool isSingle) + { + if (expression.Arguments != null) + { + int i = 0; + foreach (var item in expression.Arguments) + { + string memberName = expression.Members[i].Name; + ++i; + ResolveNewExpressions(parameter, item, memberName); + } + } + } + } +} + diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/TypeParameterExpressionReolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/TypeParameterExpressionReolve.cs new file mode 100644 index 0000000..0572476 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/TypeParameterExpressionReolve.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class TypeParameterExpressionReolve : BaseResolve + { + public TypeParameterExpressionReolve(ExpressionParameter parameter) : base(parameter) + { + var expression = (ParameterExpression)base.Expression; + switch (parameter.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + break; + case ResolveExpressType.WhereMultiple: + break; + case ResolveExpressType.Update: + parameter.BaseParameter.CommonTempData = expression.Name; + break; + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + if (parameter.BaseParameter!=null&¶meter.BaseParameter.CurrentExpression.NodeType == ExpressionType.Lambda) + { + this.Context.Result.Append(expression.Name + ".*"); + } + else + { + parameter.BaseParameter.CommonTempData = expression.Name; + } + break; + case ResolveExpressType.FieldSingle: + break; + case ResolveExpressType.FieldMultiple: + break; + case ResolveExpressType.Join: + break; + default: + break; + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/ResolveItems/UnaryExpressionResolve.cs b/类库/SqlSugar/ExpressionsToSql/ResolveItems/UnaryExpressionResolve.cs new file mode 100644 index 0000000..d559410 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/ResolveItems/UnaryExpressionResolve.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +namespace SqlSugar +{ + public class UnaryExpressionResolve : BaseResolve + { + public UnaryExpressionResolve(ExpressionParameter parameter) : base(parameter) + { + var expression = base.Expression as UnaryExpression; + var baseParameter = parameter.BaseParameter; + switch (this.Context.ResolveType) + { + case ResolveExpressType.WhereSingle: + case ResolveExpressType.WhereMultiple: + case ResolveExpressType.FieldSingle: + case ResolveExpressType.FieldMultiple: + case ResolveExpressType.SelectSingle: + case ResolveExpressType.SelectMultiple: + case ResolveExpressType.ArraySingle: + case ResolveExpressType.ArrayMultiple: + case ResolveExpressType.Update: + var nodeType = expression.NodeType; + base.Expression = expression.Operand; + var isMember = expression.Operand is MemberExpression; + var isConst = expression.Operand is ConstantExpression; + var offsetIsNull = (parameter.OppsiteExpression is ConstantExpression) + &&(parameter.OppsiteExpression as ConstantExpression).Value==null + &&ExpressionTool.IsComparisonOperator(expression.Operand); + if (isMember && offsetIsNull) { + Append(parameter, nodeType); + } + else if (baseParameter.CurrentExpression is NewArrayExpression) + { + Result(parameter, nodeType); + } + else if (base.Expression is BinaryExpression || parameter.BaseExpression is BinaryExpression || baseParameter.CommonTempData.ObjToString() == CommonTempDataType.Append.ToString()) + { + Append(parameter, nodeType); + } + else if (isMember) + { + MemberLogic(parameter, baseParameter, nodeType); + } + else if (isConst) + { + Result(parameter, nodeType); + } + else + { + Append(parameter, nodeType); + } + break; + default: + break; + } + } + + private void MemberLogic(ExpressionParameter parameter, ExpressionParameter baseParameter, ExpressionType nodeType) + { + var memberExpression = (base.Expression as MemberExpression); + var isLogicOperator = ExpressionTool.IsLogicOperator(baseParameter.OperatorValue) || baseParameter.OperatorValue.IsNullOrEmpty(); + var isHasValue = isLogicOperator && memberExpression.Member.Name == "HasValue" && memberExpression.Expression != null && memberExpression.NodeType == ExpressionType.MemberAccess; + if (isHasValue) + { + var member = memberExpression.Expression as MemberExpression; + parameter.CommonTempData = CommonTempDataType.Result; + var isConst = member.Expression != null && member.Expression is ConstantExpression; + if (isConst) + { + var paramterValue = ExpressionTool.DynamicInvoke(member); + var paramterName= base.AppendParameter(paramterValue); + var result = this.Context.DbMehtods.HasValue(new MethodCallExpressionModel() + { + Args = new List() { + new MethodCallExpressionArgs() { IsMember=false, MemberName=paramterName, MemberValue=paramterValue } } + }); + this.Context.Result.Append(result); + } + else + { + this.Expression = isConst ? member.Expression : member; + this.Start(); + var methodParamter = isConst ? new MethodCallExpressionArgs() { IsMember = false } : new MethodCallExpressionArgs() { IsMember = true, MemberName = parameter.CommonTempData, MemberValue = null }; + var result = this.Context.DbMehtods.HasValue(new MethodCallExpressionModel() + { + Args = new List() { + methodParamter + } + }); + this.Context.Result.Append(result); + parameter.CommonTempData = null; + } + } + else if (memberExpression.Type == UtilConstants.BoolType && isLogicOperator) + { + Append(parameter, nodeType); + } + else + { + Result(parameter, nodeType); + } + } + + private void Result(ExpressionParameter parameter, ExpressionType nodeType) + { + BaseParameter.ChildExpression = base.Expression; + parameter.CommonTempData = CommonTempDataType.Result; + if (nodeType == ExpressionType.Not) + AppendNot(parameter.CommonTempData); + base.Start(); + parameter.BaseParameter.CommonTempData = parameter.CommonTempData; + parameter.BaseParameter.ChildExpression = base.Expression; + parameter.CommonTempData = null; + } + + private void Append(ExpressionParameter parameter, ExpressionType nodeType) + { + BaseParameter.ChildExpression = base.Expression; + this.IsLeft = parameter.IsLeft; + parameter.CommonTempData = CommonTempDataType.Append; + if (nodeType == ExpressionType.Not) + AppendNot(parameter.CommonTempData); + base.Start(); + parameter.BaseParameter.CommonTempData = parameter.CommonTempData; + parameter.BaseParameter.ChildExpression = base.Expression; + parameter.CommonTempData = null; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/ISubOperation.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/ISubOperation.cs new file mode 100644 index 0000000..432f67b --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/ISubOperation.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public interface ISubOperation + { + ExpressionContext Context { get; set; } + string Name { get; } + string GetValue(Expression expression); + int Sort { get; } + Expression Expression { get; set; } + bool HasWhere { get; set; } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAnd.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAnd.cs new file mode 100644 index 0000000..8709f47 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAnd.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubAnd:ISubOperation + { + public string Name + { + get { return "And"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 401; + } + } + + public ExpressionContext Context + { + get;set; + } + + public bool HasWhere + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var result = "AND " + SubTools.GetMethodValue(this.Context, argExp, ResolveExpressType.WhereMultiple); + var selfParameterName = this.Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAndIF.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAndIF.cs new file mode 100644 index 0000000..15e2e24 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAndIF.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubAndIF : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "WhereIF"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 400; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + object value = null; + try + { + value = ExpressionTool.DynamicInvoke(exp.Arguments[0]); + } + catch + { + Check.Exception(true, ErrorMessage.WhereIFCheck,exp.Arguments[0].ToString()); + } + var isWhere= Convert.ToBoolean(value); + if (!Convert.ToBoolean(isWhere)) { + return ""; + } + var argExp = exp.Arguments[1]; + var result = "AND " + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple); ; + var selfParameterName = Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAny.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAny.cs new file mode 100644 index 0000000..476c69c --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAny.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubAny : ISubOperation + { + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get;set; + } + + public bool HasWhere + { + get;set; + } + + public string Name + { + get + { + return "Any"; + } + } + + public int Sort + { + get + { + return 0; + } + } + + public string GetValue(Expression expression) + { + return "EXISTS"; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAvg.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAvg.cs new file mode 100644 index 0000000..0018739 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubAvg.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubAvg: ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Avg"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + return "AVG(" + SubTools.GetMethodValue(this.Context, exp.Arguments[0], ResolveExpressType.FieldSingle) + ")"; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubBegin.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubBegin.cs new file mode 100644 index 0000000..879d60f --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubBegin.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubBegin : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Begin"; + } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 100; + } + } + + public ExpressionContext Context + { + get;set; + } + + public string GetValue(Expression expression) + { + return "SELECT"; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubCount.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubCount.cs new file mode 100644 index 0000000..bbb1cd1 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubCount.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubCount: ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Count"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + return "COUNT(*)"; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubFromTable.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubFromTable.cs new file mode 100644 index 0000000..13375ca --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubFromTable.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubFromTable : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Subqueryable"; + } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 300; + } + } + + public ExpressionContext Context + { + get;set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var resType = exp.Method.ReturnType; + var entityType = resType.GetGenericArguments().First(); + var name = entityType.Name; + if (this.Context.InitMappingInfo != null) + { + this.Context.InitMappingInfo(entityType); + this.Context.RefreshMapping(); + } + var result= "FROM "+this.Context.GetTranslationTableName(name, true); + if (this.Context.SubQueryIndex > 0) { + result += " subTableIndex"+this.Context.SubQueryIndex; + } + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubGroupBy.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubGroupBy.cs new file mode 100644 index 0000000..3b16cd9 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubGroupBy.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubGroupBy : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "GroupBy"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 479; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var result = "GROUP BY " + SubTools.GetMethodValue(this.Context, argExp, ResolveExpressType.FieldSingle); + var selfParameterName = this.Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubLeftBracket.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubLeftBracket.cs new file mode 100644 index 0000000..29be63a --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubLeftBracket.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubLeftBracket : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get;set; + } + + public string Name + { + get + { + return "LeftBracket"; + } + } + + public int Sort + { + get + { + return 50; + } + } + + public string GetValue(Expression expression) + { + return "("; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubMax.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubMax.cs new file mode 100644 index 0000000..aee39de --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubMax.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubMax:ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Max"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var parametres = (argExp as LambdaExpression).Parameters; + if ((argExp as LambdaExpression).Body is UnaryExpression) + { + argExp = ((argExp as LambdaExpression).Body as UnaryExpression).Operand; + } + var result = "MAX(" + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple) + ")"; + var selfParameterName = Context.GetTranslationColumnName(parametres.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubMin.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubMin.cs new file mode 100644 index 0000000..41fd561 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubMin.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubMin: ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Min"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var parametres = (argExp as LambdaExpression).Parameters; + if ((argExp as LambdaExpression).Body is UnaryExpression) + { + argExp = ((argExp as LambdaExpression).Body as UnaryExpression).Operand; + } + var result = "MIN(" + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple) + ")"; + var selfParameterName = Context.GetTranslationColumnName(parametres.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubNotAny.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubNotAny.cs new file mode 100644 index 0000000..7805505 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubNotAny.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubNotAny : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get; set; + } + + public string Name + { + get + { + return "NotAny"; + } + } + + public int Sort + { + get + { + return 0; + } + } + + public string GetValue(Expression expression) + { + return "NOT EXISTS"; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubOrderBy.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubOrderBy.cs new file mode 100644 index 0000000..f71ee71 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubOrderBy.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubOrderBy : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "OrderBy"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 480; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + if (this.Context is OracleExpressionContext) + { + throw new Exception("Oracle Subquery can't OrderBy"); + } + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var result = "ORDER BY " + SubTools.GetMethodValue(this.Context, argExp, ResolveExpressType.FieldSingle); + var selfParameterName = this.Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } + public class SubOrderByDesc : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "OrderByDesc"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 480; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var result = "ORDER BY " + SubTools.GetMethodValue(this.Context, argExp, ResolveExpressType.FieldSingle)+" DESC"; + var selfParameterName = this.Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, string.Empty); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubRightBracket.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubRightBracket.cs new file mode 100644 index 0000000..970d3a6 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubRightBracket.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubRightBracket : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get;set; + } + + public string Name + { + get + { + return "RightBracket"; + } + } + + public int Sort + { + get + { + return 500; + } + } + + public string GetValue(Expression expression) + { + return ")"; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelect.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelect.cs new file mode 100644 index 0000000..d2b853f --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelect.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubSelect : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Select"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get;set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + var entityType = (exp.Arguments[0] as LambdaExpression).Parameters[0].Type; + if (this.Context.InitMappingInfo != null) + { + this.Context.InitMappingInfo(entityType); + this.Context.RefreshMapping(); + } + return SubTools.GetMethodValue(this.Context, exp.Arguments[0],ResolveExpressType.FieldSingle); + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelectDefault.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelectDefault.cs new file mode 100644 index 0000000..a60e6af --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSelectDefault.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubSelectDefault : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get;set; + } + + public Expression Expression + { + get;set; + } + + public string Name + { + get { + return "SelectDefault"; + } + } + + public int Sort + { + get + { + return 250; + } + } + + public string GetValue(Expression expression) + { + return "*"; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSum.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSum.cs new file mode 100644 index 0000000..03f1454 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubSum.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubSum : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get + { + return "Sum"; + } + } + + public Expression Expression + { + get; set; + } + + + public int Sort + { + get + { + return 200; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression = null) + { + var exp = expression as MethodCallExpression; + var argExp = exp.Arguments[0]; + var parametres = (argExp as LambdaExpression).Parameters; + if ((argExp as LambdaExpression).Body is UnaryExpression) + { + argExp =((argExp as LambdaExpression).Body as UnaryExpression).Operand; + } + var result = "SUM(" + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple)+")"; + var selfParameterName = Context.GetTranslationColumnName(parametres.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubTop.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubTop.cs new file mode 100644 index 0000000..11d2e17 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubTop.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubTop : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public ExpressionContext Context + { + get; set; + } + + public Expression Expression + { + get; set; + } + + public string Name + { + get + { + return "Top"; + } + } + + public int Sort + { + get + { + if (this.Context is SqlServerExpressionContext) + { + return 150; + } + else if (this.Context is OracleExpressionContext) { + + return 401; + } + else + { + return 490; + } + } + } + + + public string GetValue(Expression expression) + { + if (this.Context is SqlServerExpressionContext) + { + return "TOP 1"; + } + else if (this.Context is OracleExpressionContext) + { + return (HasWhere?"AND":"WHERE")+ " ROWNUM=1"; + } + else if (this.Context is PostgreSQLExpressionContext) + { + return "limit 1"; + } + else + { + return "limit 0,1"; + } + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhere.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhere.cs new file mode 100644 index 0000000..cb02caf --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhere.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubWhere: ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "Where"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 400; + } + } + + public ExpressionContext Context + { + get;set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + var argExp= exp.Arguments[0]; + var result= "WHERE "+SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple);; + var selfParameterName = Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name)+UtilConstants.Dot; + result = result.Replace(selfParameterName,SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhereIF.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhereIF.cs new file mode 100644 index 0000000..1e266e1 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Items/SubWhereIF.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubWhereIF : ISubOperation + { + public bool HasWhere + { + get; set; + } + + public string Name + { + get { return "WhereIF"; } + } + + public Expression Expression + { + get; set; + } + + public int Sort + { + get + { + return 400; + } + } + + public ExpressionContext Context + { + get; set; + } + + public string GetValue(Expression expression) + { + var exp = expression as MethodCallExpression; + object value = null; + try + { + value = ExpressionTool.DynamicInvoke(exp.Arguments[0]); + } + catch + { + Check.Exception(true, ErrorMessage.WhereIFCheck,exp.Arguments[0].ToString()); + } + var isWhere= Convert.ToBoolean(value); + if (!Convert.ToBoolean(isWhere)) { + return "WHERE 1=1 "; + } + var argExp = exp.Arguments[1]; + var result = "WHERE " + SubTools.GetMethodValue(Context, argExp, ResolveExpressType.WhereMultiple); ; + var selfParameterName = Context.GetTranslationColumnName((argExp as LambdaExpression).Parameters.First().Name) + UtilConstants.Dot; + result = result.Replace(selfParameterName, SubTools.GetSubReplace(this.Context)); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs new file mode 100644 index 0000000..6bacca1 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/SubResolve.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + /// + /// ** description:Get subquery sql + /// ** author:sunkaixuan + /// ** date:2017/9/17 + /// ** email:610262374@qq.com + /// + public class SubResolve + { + List allMethods = new List(); + private ExpressionContext context = null; + private bool hasWhere; + public SubResolve(MethodCallExpression expression, ExpressionContext context, Expression oppsiteExpression) + { + this.context = context; + var currentExpression = expression; + allMethods.Add(currentExpression); + if (context.IsSingle && oppsiteExpression != null && oppsiteExpression is MemberExpression) + { + var childExpression = (oppsiteExpression as MemberExpression).Expression; + if (childExpression is ParameterExpression) + this.context.SingleTableNameSubqueryShortName = (childExpression as ParameterExpression).Name; + else { + this.context.SingleTableNameSubqueryShortName = (context.Expression as LambdaExpression).Parameters.First().Name; + } + } + else if (context.IsSingle) + { + if (context.Expression is LambdaExpression) + { + this.context.SingleTableNameSubqueryShortName = (context.Expression as LambdaExpression).Parameters.First().Name; + } + else if (context.Expression is MethodCallExpression) + { + var meExp = ((context.Expression as MethodCallExpression).Object as MethodCallExpression).Arguments[0] as LambdaExpression; + var selfParameterName = meExp.Parameters.First().Name; + context.SingleTableNameSubqueryShortName = (((meExp.Body as BinaryExpression).Left as MemberExpression).Expression as ParameterExpression).Name; + if (context.SingleTableNameSubqueryShortName == selfParameterName) + { + context.SingleTableNameSubqueryShortName = (((meExp.Body as BinaryExpression).Right as MemberExpression).Expression as ParameterExpression).Name; + } + } + else if (context.Expression.GetType().Name == "MethodBinaryExpression") + { + + var subExp = (context.Expression as BinaryExpression).Left is MethodCallExpression ? (context.Expression as BinaryExpression).Left : (context.Expression as BinaryExpression).Right; + var meExp = ((subExp as MethodCallExpression).Object as MethodCallExpression).Arguments[0] as LambdaExpression; + var selfParameterName = meExp.Parameters.First().Name; + context.SingleTableNameSubqueryShortName = (((meExp.Body as BinaryExpression).Left as MemberExpression).Expression as ParameterExpression).Name; + if (context.SingleTableNameSubqueryShortName == selfParameterName) + { + context.SingleTableNameSubqueryShortName = (((meExp.Body as BinaryExpression).Right as MemberExpression).Expression as ParameterExpression).Name; + } + } + else + { + Check.Exception(true, "I'm sorry I can't parse the current expression"); + } + } + var subIndex = this.context.SubQueryIndex; + while (currentExpression != null) + { + var addItem = currentExpression.Object as MethodCallExpression; + if (addItem != null) + allMethods.Add(addItem); + if (subIndex==this.context.SubQueryIndex&&addItem !=null&&addItem.Arguments.HasValue()&&addItem.Arguments.Any(it=>it.ToString().Contains("Subqueryable()"))) { + this.context.SubQueryIndex++; + } + currentExpression = addItem; + } + } + + public string GetSql() + { + List subItems = GetSubItems(); + var sql = string.Join(UtilConstants.Space, subItems); + return this.context.DbMehtods.Pack(sql); + } + + private List GetSubItems() + { + var isubList = this.allMethods.Select(exp => + { + var methodName = exp.Method.Name; + var items = SubTools.SubItems(this.context); + var item = items.First(s => s.Name == methodName); + if (item is SubWhere && hasWhere == false) + { + hasWhere = true; + } + else if (item is SubWhere) + { + item = items.First(s => s is SubAnd); + } + + if (item is SubWhereIF && hasWhere == false) + { + hasWhere = true; + } + else if (item is SubWhereIF) + { + item = items.First(s => s is SubAndIF); + } + + item.Context = this.context; + item.Expression = exp; + return item; + }).ToList(); + isubList.Insert(0, new SubBegin()); + if (isubList.Any(it => it is SubSelect)) + { + isubList.Add(new SubTop() { Context = this.context }); + } + if (isubList.Any(it => it is SubAny || it is SubNotAny)) + { + isubList.Add(new SubLeftBracket()); + isubList.Add(new SubRightBracket()); + isubList.Add(new SubSelectDefault()); + } + isubList = isubList.OrderBy(it => it.Sort).ToList(); + var isHasWhere = isubList.Where(it => it is SubWhere).Any(); + List result = isubList.Select(it => + { + it.HasWhere = isHasWhere; + return it.GetValue(it.Expression); + }).ToList(); + return result; + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/SubTools.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/SubTools.cs new file mode 100644 index 0000000..8896c09 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/SubTools.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SubTools + { + public static List SubItems(ExpressionContext Context) + { + + return new List() + { + new SubSelect() { Context=Context }, + new SubWhere(){ Context=Context }, + new SubWhereIF(){ Context=Context }, + new SubAnd(){ Context=Context }, + new SubAndIF(){ Context=Context }, + new SubAny(){ Context=Context }, + new SubNotAny(){ Context=Context }, + new SubBegin(){ Context=Context }, + new SubFromTable(){ Context=Context }, + new SubCount(){ Context=Context }, + new SubMax(){ Context=Context }, + new SubMin(){ Context=Context }, + new SubSum(){ Context=Context }, + new SubAvg(){ Context=Context }, + new SubOrderBy(){ Context=Context }, + new SubOrderByDesc(){ Context=Context }, + new SubGroupBy(){ Context=Context} + }; + } + + public static string GetSubReplace(ExpressionContext context) + { + if (context.SubQueryIndex == 0) + return string.Empty; + else + return "subTableIndex"+context.SubQueryIndex+"."; + } + + public static List SubItemsConst = SubItems(null); + + public static string GetMethodValue(ExpressionContext context, Expression item, ResolveExpressType type) + { + var newContext = context.GetCopyContext(); + newContext.MappingColumns = context.MappingColumns; + newContext.MappingTables = context.MappingTables; + newContext.InitMappingInfo = context.InitMappingInfo; + newContext.RefreshMapping = context.RefreshMapping; + newContext.IgnoreComumnList = context.IgnoreComumnList; + newContext.SqlFuncServices = context.SqlFuncServices; + newContext.Resolve(item, type); + context.Index = newContext.Index; + context.ParameterIndex = newContext.ParameterIndex; + if (newContext.Parameters.HasValue()) + context.Parameters.AddRange(newContext.Parameters); + return newContext.Result.GetResultString(); + } + } +} diff --git a/类库/SqlSugar/ExpressionsToSql/Subquery/Subquerable.cs b/类库/SqlSugar/ExpressionsToSql/Subquery/Subquerable.cs new file mode 100644 index 0000000..dd727e3 --- /dev/null +++ b/类库/SqlSugar/ExpressionsToSql/Subquery/Subquerable.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + + public class Subqueryable where T : class, new() + { + public Subqueryable Where(Func expression) + { + return this; + } + public Subqueryable WhereIF(bool isWhere,Func expression) + { + return this; + } + public Subqueryable OrderBy(Func expression) + { + return this; + } + public Subqueryable GroupBy(Func expression) + { + return this; + } + public Subqueryable OrderByDesc(Func expression) + { + return this; + } + + public TResult Select(Func expression) where TResult :struct + { + return default(TResult); + } + public Byte[] Select(Func expression) + { + return null; + } + public string Select(Func expression) + { + return default(string); + } + + public TResult Max(Func expression) where TResult : struct + { + return default(TResult); + } + public Byte[] Max(Func expression) + { + return null; + } + public string Max(Func expression) + { + return default(string); + } + + public string Min(Func expression) + { + return default(string); + } + public TResult Min(Func expression) where TResult : struct + { + return default(TResult); + } + public Byte[] Min(Func expression) + { + return null; + } + + + public string Sum(Func expression) + { + return default(string); + } + public TResult Sum(Func expression) where TResult : struct + { + return default(TResult); + } + public Byte[] Sum(Func expression) + { + return null; + } + + public string Avg(Func expression) + { + return default(string); + } + public TResult Avg(Func expression) where TResult : struct + { + return default(TResult); + } + public Byte[] Avg(Func expression) + { + return null; + } + + public bool Any() + { + return default(bool); + } + + public bool NotAny() + { + return default(bool); + } + + public int Count() + { + return default(int); + } + } +} diff --git a/类库/SqlSugar/ExternalServiceInterface/ICacheService.cs b/类库/SqlSugar/ExternalServiceInterface/ICacheService.cs new file mode 100644 index 0000000..a932fa6 --- /dev/null +++ b/类库/SqlSugar/ExternalServiceInterface/ICacheService.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; + +namespace SqlSugar +{ + public interface ICacheService + { + void Add(string key, V value); + void Add(string key, V value, int cacheDurationInSeconds); + bool ContainsKey(string key); + V Get(string key); + IEnumerable GetAllKey(); + void Remove(string key); + V GetOrCreate(string cacheKey, Func create,int cacheDurationInSeconds=int.MaxValue); + } +} \ No newline at end of file diff --git a/类库/SqlSugar/ExternalServiceInterface/ISerializeService.cs b/类库/SqlSugar/ExternalServiceInterface/ISerializeService.cs new file mode 100644 index 0000000..3441076 --- /dev/null +++ b/类库/SqlSugar/ExternalServiceInterface/ISerializeService.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public interface ISerializeService + { + string SerializeObject(object value); + T DeserializeObject(string value); + } +} diff --git a/类库/SqlSugar/Infrastructure/ContextMethods.cs b/类库/SqlSugar/Infrastructure/ContextMethods.cs new file mode 100644 index 0000000..adc0b23 --- /dev/null +++ b/类库/SqlSugar/Infrastructure/ContextMethods.cs @@ -0,0 +1,501 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Dynamic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class ContextMethods : IContextMethods + { + public SqlSugarClient Context { get; set; } + #region DataReader + + /// + ///DataReader to Dynamic + /// + /// + /// + public ExpandoObject DataReaderToExpandoObject(IDataReader reader) + { + ExpandoObject result = new ExpandoObject(); + var dic = ((IDictionary)result); + for (int i = 0; i < reader.FieldCount; i++) + { + try + { + var addItem = reader.GetValue(i); + if (addItem == DBNull.Value) + addItem = null; + dic.Add(reader.GetName(i), addItem); + } + catch + { + dic.Add(reader.GetName(i), null); + } + } + return result; + } + + /// + ///DataReader to Dynamic List + /// + /// + /// + public List DataReaderToExpandoObjectList(IDataReader reader) + { + using (reader) + { + List result = new List(); + if (reader != null && !reader.IsClosed) + { + while (reader.Read()) + { + result.Add(DataReaderToExpandoObject(reader)); + } + } + return result; + } + } + + /// + ///DataReader to DataReaderToDictionary + /// + /// + /// + public Dictionary DataReaderToDictionary(IDataReader reader) + { + Dictionary result = new Dictionary(); + for (int i = 0; i < reader.FieldCount; i++) + { + try + { + var addItem = reader.GetValue(i); + if (addItem == DBNull.Value) + addItem = null; + result.Add(reader.GetName(i), addItem); + } + catch + { + result.Add(reader.GetName(i), null); + } + } + return result; + } + + /// + ///DataReader to DataReaderToDictionary + /// + /// + /// + public Dictionary DataReaderToDictionary(IDataReader reader, Type type) + { + Dictionary result = new Dictionary(); + for (int i = 0; i < reader.FieldCount; i++) + { + string name = reader.GetName(i); + try + { + name = this.Context.EntityMaintenance.GetPropertyName(name, type); + var addItem = reader.GetValue(i); + if (addItem == DBNull.Value) + addItem = null; + result.Add(name, addItem); + } + catch + { + result.Add(name, null); + } + } + return result; + } + + /// + /// DataReaderToList + /// + /// + /// + /// + public List DataReaderToList(IDataReader reader) + { + using (reader) + { + var tType = typeof(T); + var classProperties = tType.GetProperties().ToList(); + var reval = new List(); + if (reader != null && !reader.IsClosed) + { + while (reader.Read()) + { + var readerValues = DataReaderToDictionary(reader, tType); + var result = new Dictionary(); + foreach (var item in classProperties) + { + var name = item.Name; + var typeName = tType.Name; + if (item.PropertyType.IsClass()) + { + result.Add(name, DataReaderToDynamicList_Part(readerValues, item, reval)); + } + else + { + if (readerValues.Any(it => it.Key.Equals(name, StringComparison.CurrentCultureIgnoreCase))) + { + var addValue = readerValues.ContainsKey(name) ? readerValues[name] : readerValues.First(it => it.Key.Equals(name, StringComparison.CurrentCultureIgnoreCase)).Value; + if (addValue == DBNull.Value) + { + if (item.PropertyType.IsIn(UtilConstants.IntType, UtilConstants.DecType, UtilConstants.DobType, UtilConstants.ByteType)) + { + addValue = 0; + } + else if (item.PropertyType == UtilConstants.GuidType) + { + addValue = Guid.Empty; + } + else if (item.PropertyType == UtilConstants.DateType) + { + addValue = DateTime.MinValue; + } + else if (item.PropertyType == UtilConstants.StringType) + { + addValue = null; + } + else + { + addValue = null; + } + } + else if (item.PropertyType == UtilConstants.IntType) + { + addValue = Convert.ToInt32(addValue); + } + result.Add(name, addValue); + } + } + } + var stringValue = SerializeObject(result); + reval.Add((T)DeserializeObject(stringValue)); + } + } + return reval; + } + } + + private Dictionary DataReaderToDynamicList_Part(Dictionary readerValues, PropertyInfo item, List reval) + { + Dictionary result = new Dictionary(); + var type = item.PropertyType; + if (UtilConstants.SugarType == type) + { + return result; + } + if (type.FullName.IsCollectionsList()) + { + return null; + } + var classProperties = type.GetProperties().ToList(); + foreach (var prop in classProperties) + { + var name = prop.Name; + var typeName = type.Name; + if (prop.PropertyType.IsClass()) + { + result.Add(name, DataReaderToDynamicList_Part(readerValues, prop, reval)); + } + else + { + var key = typeName + "." + name; + var info = readerValues.Select(it => it.Key).FirstOrDefault(it => it.ToLower() == key.ToLower()); + if (info != null) + { + var addItem = readerValues[info]; + if (addItem == DBNull.Value) + addItem = null; + if (prop.PropertyType == UtilConstants.IntType) + { + addItem = addItem.ObjToInt(); + } + result.Add(name, addItem); + } + } + } + return result; + } + #endregion + + #region Serialize + /// + /// Serialize Object + /// + /// + /// + public string SerializeObject(object value) + { + DependencyManagement.TryJsonNet(); + return Context.CurrentConnectionConfig.ConfigureExternalServices.SerializeService.SerializeObject(value); + } + + + + /// + /// Serialize Object + /// + /// + /// + public T DeserializeObject(string value) + { + DependencyManagement.TryJsonNet(); + return Context.CurrentConnectionConfig.ConfigureExternalServices.SerializeService.DeserializeObject(value); + } + #endregion + + #region Copy Object + /// + /// Copy new Object + /// + /// + /// + /// + public T TranslateCopy(T sourceObject) + { + if (sourceObject == null) return default(T); + else + { + var jsonString = SerializeObject(sourceObject); + return DeserializeObject(jsonString); + } + } + public SqlSugarClient CopyContext(bool isCopyEvents = false) + { + var newClient = new SqlSugarClient(this.TranslateCopy(Context.CurrentConnectionConfig)); + newClient.CurrentConnectionConfig.ConfigureExternalServices = Context.CurrentConnectionConfig.ConfigureExternalServices; + newClient.MappingColumns = this.TranslateCopy(Context.MappingColumns); + newClient.MappingTables = this.TranslateCopy(Context.MappingTables); + newClient.IgnoreColumns = this.TranslateCopy(Context.IgnoreColumns); + if (isCopyEvents) + { + newClient.Ado.IsEnableLogEvent = Context.Ado.IsEnableLogEvent; + newClient.Ado.LogEventStarting = Context.Ado.LogEventStarting; + newClient.Ado.LogEventCompleted = Context.Ado.LogEventCompleted; + newClient.Ado.ProcessingEventStartingSQL = Context.Ado.ProcessingEventStartingSQL; + newClient.QueryFilter = Context.QueryFilter; + } + return newClient; + } + #endregion + + #region DataTable + public dynamic DataTableToDynamic(DataTable table) + { + List> deserializeObject = new List>(); + Dictionary childRow; + foreach (DataRow row in table.Rows) + { + childRow = new Dictionary(); + foreach (DataColumn col in table.Columns) + { + var addItem = row[col]; + if (addItem == DBNull.Value) + addItem = null; + childRow.Add(col.ColumnName, addItem); + } + deserializeObject.Add(childRow); + } + return this.DeserializeObject(this.SerializeObject(deserializeObject)); + + } + public List DataTableToList(DataTable table) + { + List> deserializeObject = new List>(); + Dictionary childRow; + foreach (DataRow row in table.Rows) + { + childRow = new Dictionary(); + foreach (DataColumn col in table.Columns) + { + var addItem = row[col]; + if (addItem == DBNull.Value) + addItem = null; + childRow.Add(col.ColumnName, addItem); + } + deserializeObject.Add(childRow); + } + return this.DeserializeObject>(this.SerializeObject(deserializeObject)); + } + #endregion + + #region Cache + public ICacheService GetReflectionInoCacheInstance() + { + return Context.CurrentConnectionConfig.ConfigureExternalServices.ReflectionInoCacheService; + } + + public void RemoveCacheAll() + { + ReflectionInoHelper.RemoveAllCache(); + InstanceFactory.RemoveCache(); + } + + public void RemoveCacheAll() + { + ReflectionInoCore.GetInstance().RemoveAllCache(); + } + + public void RemoveCache(string key) + { + ReflectionInoCore.GetInstance().Remove(key); + } + #endregion + + #region Query + public KeyValuePair ConditionalModelToSql(List models, int beginIndex = 0) + { + if (models.IsNullOrEmpty()) return new KeyValuePair(); + StringBuilder builder = new StringBuilder(); + List parameters = new List(); + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + foreach (var model in models) + { + if (model is ConditionalModel) + { + var item = model as ConditionalModel; + var index = models.IndexOf(item) + beginIndex; + var type = index == 0 ? "" : "AND"; + if (beginIndex > 0) + { + type = null; + } + string temp = " {0} {1} {2} {3} "; + string parameterName = string.Format("{0}Conditional{1}{2}", sqlBuilder.SqlParameterKeyWord, item.FieldName, index); + if (parameterName.Contains(".")) + { + parameterName = parameterName.Replace(".", "_"); + } + switch (item.ConditionalType) + { + case ConditionalType.Equal: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "=", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.Like: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "LIKE", parameterName); + parameters.Add(new SugarParameter(parameterName, "%" + item.FieldValue + "%")); + break; + case ConditionalType.GreaterThan: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), ">", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.GreaterThanOrEqual: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), ">=", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.LessThan: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "<", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.LessThanOrEqual: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "<=", parameterName); + parameters.Add(new SugarParameter(parameterName, GetFieldValue(item))); + break; + case ConditionalType.In: + if (item.FieldValue == null) item.FieldValue = string.Empty; + var inValue1 = ("(" + item.FieldValue.Split(',').ToJoinSqlInVals() + ")"); + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "IN", inValue1); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + break; + case ConditionalType.NotIn: + if (item.FieldValue == null) item.FieldValue = string.Empty; + var inValue2 = ("(" + item.FieldValue.Split(',').ToJoinSqlInVals() + ")"); + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "NOT IN", inValue2); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + break; + case ConditionalType.LikeLeft: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "LIKE", parameterName); + parameters.Add(new SugarParameter(parameterName, item.FieldValue + "%")); + break; + case ConditionalType.NoLike: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), " NOT LIKE", parameterName); + parameters.Add(new SugarParameter(parameterName, item.FieldValue + "%")); + break; + case ConditionalType.LikeRight: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "LIKE", parameterName); + parameters.Add(new SugarParameter(parameterName, "%" + item.FieldValue)); + break; + case ConditionalType.NoEqual: + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "<>", parameterName); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + break; + case ConditionalType.IsNullOrEmpty: + builder.AppendFormat("{0} ({1}) OR ({2}) ", type, item.FieldName.ToSqlFilter() + " IS NULL ", item.FieldName.ToSqlFilter() + " = '' "); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + break; + case ConditionalType.IsNot: + if (item.FieldValue == null) + { + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), " IS NOT ", "NULL"); + } + else + { + builder.AppendFormat(temp, type, item.FieldName.ToSqlFilter(), "<>", parameterName); + parameters.Add(new SugarParameter(parameterName, item.FieldValue)); + } + break; + default: + break; + } + } + else + { + var item = model as ConditionalCollections; + if (item != null&& item.ConditionalList.HasValue()) + { + foreach (var con in item.ConditionalList) + { + var index = item.ConditionalList.IndexOf(con); + var isFirst = index == 0; + var isLast = index == (item.ConditionalList.Count - 1); + if (models.IndexOf(item) == 0 &&index==0&& beginIndex == 0) + { + builder.AppendFormat(" ( "); + + }else if (isFirst) + { + builder.AppendFormat(" {0} ( ", con.Key.ToString().ToUpper()); + } + List conModels = new List(); + conModels.Add(con.Value); + var childSqlInfo = ConditionalModelToSql(conModels, 1000 * (1 + index)); + if (!isFirst) + { + + builder.AppendFormat(" {0} ", con.Key.ToString().ToUpper()); + } + builder.Append(childSqlInfo.Key); + parameters.AddRange(childSqlInfo.Value); + if (isLast) + { + builder.Append(" ) "); + } + else + { + + } + } + } + } + } + return new KeyValuePair(builder.ToString(), parameters.ToArray()); + } + + private static object GetFieldValue(ConditionalModel item) + { + if (item.FieldValueConvertFunc != null) + return item.FieldValueConvertFunc(item.FieldValue); + else + return item.FieldValue; + } + #endregion + } +} diff --git a/类库/SqlSugar/Infrastructure/DependencyManagement.cs b/类库/SqlSugar/Infrastructure/DependencyManagement.cs new file mode 100644 index 0000000..ac22fc1 --- /dev/null +++ b/类库/SqlSugar/Infrastructure/DependencyManagement.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Text; +namespace SqlSugar +{ + internal class DependencyManagement + { + private static bool IsTryJsonNet = false; + private static bool IsTryMySqlData = false; + private static bool IsTrySqlite = false; + private static bool IsTryOracle = false; + public static void TryJsonNet() + { + if (!IsTryJsonNet) + { + try + { + new SerializeService().SerializeObject(new { }); + IsTryJsonNet = true; + } + catch + { + var message = ErrorMessage.GetThrowMessage( + " SqlSugar Some functions are used in newtonsoft ,Nuget references Newtonsoft.Json 9.0.0.1 + .", + " SqlSugar 部分功能用到Newtonsoft.Json.dll,需要在Nuget上安装 Newtonsoft.Json 9.0.0.1及以上版本。如果有版本兼容问题请先删除原有引用(注意:所有项目类库),全部重新从NUGET下载,如果还不明白,请查看详细教程 http://www.codeisbug.com/Doc/8/1154"); + throw new Exception(message); + } + } + } + public static void TryMySqlData() + { + if (!IsTryMySqlData) + { + try + { + MySqlProvider db = new MySqlProvider(); + var conn = db.GetAdapter(); + IsTryMySqlData = true; + } + catch + { + var message = ErrorMessage.GetThrowMessage( + "You need to refer to MySql.Data.dll", + "需要引用MySql.Data.dll,请在Nuget安装最新稳定版本,如果有版本兼容问题请先删除原有引用"); + throw new Exception(message); + } + } + } + + internal static void TryPostgreSQL() + { + var message = ErrorMessage.GetThrowMessage( + "SqlSugar PostGreSQL only support.NET CORE", + "SqlSugar使用 PostGreSQL只支持.NET CORE"); + throw new Exception(message); + } + + internal static void TryOracle() + { + if (!IsTryOracle) + { + try + { + OracleProvider db = new OracleProvider(); + var conn = db.GetAdapter(); + IsTryOracle = true; + } + catch + { + var message = ErrorMessage.GetThrowMessage( + "You need to refer to Oracle.ManagedDataAccess.dll", + "需要引用ManagedDataAccess.dll,请在Nuget安装最新稳定版本,如果有版本兼容问题请先删除原有引用"); + throw new Exception(message); + } + } + } + + public static void TrySqlite() + { + if (!IsTrySqlite) + { + try + { + SqliteProvider db = new SqliteProvider(); + var conn = db.GetAdapter(); + IsTrySqlite = true; + } + catch (Exception ex) + { + var message = ErrorMessage.GetThrowMessage( + "You need to refer to System.Data.SQLite.dll." + ex.Message, + "你需要引用System.Data.SQLite.dll,如果有版本兼容问题请先删除原有引用"); + throw new Exception(message); + } + } + } + } +} diff --git a/类库/SqlSugar/Infrastructure/InstanceFactory.cs b/类库/SqlSugar/Infrastructure/InstanceFactory.cs new file mode 100644 index 0000000..3b7b4eb --- /dev/null +++ b/类库/SqlSugar/Infrastructure/InstanceFactory.cs @@ -0,0 +1,375 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class InstanceFactory + { + static Assembly assembly = Assembly.Load(UtilConstants.AssemblyName); + static Dictionary typeCache = new Dictionary(); + + + public static void RemoveCache() + { + typeCache = new Dictionary(); + } + + #region Queryable + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerQueryable(); + } + else + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerQueryable(); + } + else + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerQueryable(); + } + else + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + + #region 9-12 + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + public static ISugarQueryable GetQueryable(ConnectionConfig currentConnectionConfig) + { + string className = "Queryable"; + className = GetClassName(currentConnectionConfig.DbType.ToString(), className); + ISugarQueryable result = CreateInstance>(className); + return result; + } + #endregion + + #endregion + + public static QueryBuilder GetQueryBuilder(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerQueryBuilder(); + } + else + { + QueryBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "QueryBuilder")); + return result; + } + } + public static InsertBuilder GetInsertBuilder(ConnectionConfig currentConnectionConfig) + { + InsertBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "InsertBuilder")); + return result; + } + public static UpdateBuilder GetUpdateBuilder(ConnectionConfig currentConnectionConfig) + { + UpdateBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "UpdateBuilder")); + return result; + } + public static DeleteBuilder GetDeleteBuilder(ConnectionConfig currentConnectionConfig) + { + DeleteBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "DeleteBuilder")); + return result; + } + + public static ILambdaExpressions GetLambdaExpressions(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerExpressionContext(); + } + else + { + ILambdaExpressions result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "ExpressionContext")); + return result; + } + } + + public static ISqlBuilder GetSqlbuilder(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerBuilder(); + } + else + { + ISqlBuilder result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "Builder")); + return result; + } + } + + public static UpdateableProvider GetUpdateableProvider(ConnectionConfig currentConnectionConfig) where T : class, new() + { + if (currentConnectionConfig.DbType == DbType.Oracle) + { + return new OracleUpdateable(); + } + else + { + return new UpdateableProvider(); + } + } + + public static DeleteableProvider GetDeleteableProvider(ConnectionConfig currentConnectionConfig) where T : class, new() + { + if (currentConnectionConfig.DbType == DbType.Oracle) + { + return new OracleDeleteable(); + } + else + { + return new DeleteableProvider(); + } + } + + public static InsertableProvider GetInsertableProvider(ConnectionConfig currentConnectionConfig) where T : class, new() + { + if (currentConnectionConfig.DbType == DbType.Oracle) + { + return new OracleInsertable(); + } + else if (currentConnectionConfig.DbType == DbType.PostgreSQL) + { + return new PostgreSQLInserttable(); + } + else + { + return new InsertableProvider(); + } + } + + public static IDbBind GetDbBind(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerDbBind(); + } + else + { + IDbBind result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "DbBind")); + return result; + } + } + + public static IDbMaintenance GetDbMaintenance(ConnectionConfig currentConnectionConfig) + { + IDbMaintenance result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "DbMaintenance")); + return result; + } + + public static IDbFirst GetDbFirst(ConnectionConfig currentConnectionConfig) + { + IDbFirst result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "DbFirst")); + return result; + } + + public static ICodeFirst GetCodeFirst(ConnectionConfig currentConnectionConfig) + { + ICodeFirst result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "CodeFirst")); + return result; + } + + public static IAdo GetAdo(ConnectionConfig currentConnectionConfig) + { + if (currentConnectionConfig.DbType == DbType.SqlServer) + { + return new SqlServerProvider(); + } + else + { + IAdo result = CreateInstance(GetClassName(currentConnectionConfig.DbType.ToString(), "Provider")); + return result; + } + } + + private static string GetClassName(string type, string name) + { + return UtilConstants.AssemblyName + "." + type + name; + } + + #region CreateInstance + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8)); + } + + #region 9-12 + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11)); + } + private static Restult CreateInstance(string className) + { + return CreateInstance(className, typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12)); + } + #endregion + + private static Restult CreateInstance(string className, params Type[] types) + { + var cacheKey = className + string.Join(",", types.Select(it => it.FullName)); + Type type; + if (typeCache.ContainsKey(cacheKey)) + { + type = typeCache[cacheKey]; + } + else + { + lock (typeCache) + { + type = Type.GetType(className + "`" + types.Length, true).MakeGenericType(types); + Check.ArgumentNullException(type, string.Format(ErrorMessage.ObjNotExist, className)); + if (!typeCache.ContainsKey(cacheKey)) + { + typeCache.Add(cacheKey, type); + } + } + } + var result = (Restult)Activator.CreateInstance(type, true); + return result; + } + public static T CreateInstance(string className) + { + Type type; + if (typeCache.ContainsKey(className)) + { + type = typeCache[className]; + } + else + { + lock (typeCache) + { + type = assembly.GetType(className); + Check.ArgumentNullException(type, string.Format(ErrorMessage.ObjNotExist, className)); + if (!typeCache.ContainsKey(className)) + { + typeCache.Add(className, type); + } + } + } + var result = (T)Activator.CreateInstance(type, true); + return result; + } + #endregion + } +} diff --git a/类库/SqlSugar/Infrastructure/Mapper.cs b/类库/SqlSugar/Infrastructure/Mapper.cs new file mode 100644 index 0000000..9f6f2b9 --- /dev/null +++ b/类库/SqlSugar/Infrastructure/Mapper.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SugarMapper + { + private SqlSugarClient _context; + public SugarMapper(SqlSugarClient context) + { + _context = context; + } + + public string GetSelectValue(QueryBuilder queryBuilder) + { + string result = string.Empty; + var veiwModel = _context.EntityMaintenance.GetEntityInfo(); + var exp = (queryBuilder.JoinExpression as LambdaExpression); + List> selectItems = new List>(); + foreach (var viewColumn in veiwModel.Columns) + { + var exParsmeters = exp.Parameters.Select(it => new { shortName = it.Name, type = it.Type }).ToList(); + foreach (var expPars in exParsmeters) + { + var columns = _context.EntityMaintenance.GetEntityInfo(expPars.type).Columns.Where(it => it.IsIgnore == false); + var joinModelDbColumns = columns.Select(it => + new { asName = it.PropertyName, dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelProperties = columns.Select(it => + new { asName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelDbColumnsWithType = columns.Select(it => + new { asName = (expPars.type.Name + it.PropertyName), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelPropertiesWithTye = columns.Select(it => + new { asName = (expPars.type.Name + _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type)), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelDbColumns_WithType = columns.Select(it => + new { asName = (expPars.type.Name +"_"+ it.PropertyName), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelProperties_WithType = columns.Select(it => + new { asName = (expPars.type.Name +"_"+ _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type)), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelDbColumnsWithSN = columns.Select(it => + new { asName = (expPars.shortName + it.PropertyName), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + var joinModelPropertiesWithSN = columns.Select(it => + new { asName = (expPars.shortName + _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type)), dbName = _context.EntityMaintenance.GetDbColumnName(it.PropertyName, expPars.type) }).ToList(); + + if (joinModelDbColumns.Any(it => it.asName.Equals(viewColumn.PropertyName,StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelDbColumns.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName,value)); + break; + } + if (joinModelProperties.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelProperties.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelDbColumnsWithType.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelDbColumnsWithType.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelPropertiesWithTye.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelPropertiesWithTye.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + + if (joinModelDbColumns_WithType.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelDbColumns_WithType.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelProperties_WithType.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelProperties_WithType.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelDbColumnsWithSN.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelDbColumnsWithSN.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + if (joinModelPropertiesWithSN.Any(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase))) + { + var value = joinModelPropertiesWithSN.First(it => it.asName.Equals(viewColumn.PropertyName, StringComparison.CurrentCultureIgnoreCase)); + if (viewColumn.PropertyName.Equals(value.asName, StringComparison.CurrentCultureIgnoreCase)) + selectItems.Add(new KeyValuePair(expPars.shortName, value)); + break; + } + } + } + result = queryBuilder.GetSelectByItems(selectItems); + if (_context.CurrentConnectionConfig.DbType == DbType.PostgreSQL) + { + result = result.ToLower(); + } + return result; + } + } +} diff --git a/类库/SqlSugar/Infrastructure/SqlSugarAccessory.cs b/类库/SqlSugar/Infrastructure/SqlSugarAccessory.cs new file mode 100644 index 0000000..25a9811 --- /dev/null +++ b/类库/SqlSugar/Infrastructure/SqlSugarAccessory.cs @@ -0,0 +1,429 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial class SqlSugarClient + { + #region Properties + public SqlSugarClient Context + { + get + { + var result = _Context; ; + if (CurrentConnectionConfig.IsShardSameThread) + { + if (CallContext.ContextList.Value.IsNullOrEmpty()) + { + CallContext.ContextList.Value = new List(); + CallContext.ContextList.Value.Add(_Context); + } + else + { + var cacheContext = CallContext.ContextList.Value.FirstOrDefault(it => + it.CurrentConnectionConfig.ConnectionString == _Context.CurrentConnectionConfig.ConnectionString && + it.CurrentConnectionConfig.DbType == _Context.CurrentConnectionConfig.DbType && + it.CurrentConnectionConfig.IsAutoCloseConnection == _Context.CurrentConnectionConfig.IsAutoCloseConnection && + it.CurrentConnectionConfig.IsShardSameThread == _Context.CurrentConnectionConfig.IsShardSameThread); + if (cacheContext != null) + { + return cacheContext; + } + } + } + return result; + } + set + { + _Context = value; + } + } + public ConnectionConfig CurrentConnectionConfig { get; set; } + public Dictionary TempItems { get; set; } + public bool IsSystemTablesConfig { get { return this.CurrentConnectionConfig.InitKeyType == InitKeyType.SystemTable; } } + public Guid ContextID { get; set; } + internal bool IsAsyncMethod { get; set; } + public MappingTableList MappingTables = new MappingTableList(); + public MappingColumnList MappingColumns = new MappingColumnList(); + public IgnoreColumnList IgnoreColumns = new IgnoreColumnList(); + public IgnoreColumnList IgnoreInsertColumns = new IgnoreColumnList(); + #endregion + + #region Fields + protected ISqlBuilder _SqlBuilder; + protected SqlSugarClient _Context { get; set; } + protected EntityMaintenance _EntityProvider; + protected IAdo _Ado; + protected ILambdaExpressions _LambdaExpressions; + protected IContextMethods _RewritableMethods; + protected IDbMaintenance _DbMaintenance; + protected QueryFilterProvider _QueryFilterProvider; + protected SimpleClient _SimpleClient; + protected IAdo ContextAdo + { + get + { + return this.Context._Ado; + } + set + { + this.Context._Ado = value; + } + } + protected IContextMethods ContextRewritableMethods + { + get + { + return this.Context._RewritableMethods; + } + set + { + this.Context._RewritableMethods = value; + } + } + #endregion + + #region Init mppingInfo + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + + #region 9-12 + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + protected void InitMppingInfo() + { + InitMppingInfo(); + InitMppingInfo(); + } + #endregion + + internal void InitMppingInfo() + { + InitMppingInfo(typeof(T)); + } + public void InitMppingInfo(Type type) + { + string cacheKey = "Context.InitAttributeMappingTables" + type.FullName; + var entityInfo = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + var result = this.Context.EntityMaintenance.GetEntityInfo(type); + return result; + }); + var copyObj = CopyEntityInfo(entityInfo); + InitMppingInfo(copyObj); + } + + private EntityInfo CopyEntityInfo(EntityInfo entityInfo) + { + EntityInfo result = new EntityInfo() + { + DbTableName = entityInfo.DbTableName, + EntityName = entityInfo.EntityName, + Type = entityInfo.Type + }; + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns) + { + EntityColumnInfo column = new EntityColumnInfo() + { + ColumnDescription = item.ColumnDescription, + DataType = item.DataType, + DbColumnName = item.DbColumnName, + DbTableName = item.DbTableName, + DecimalDigits = item.DecimalDigits, + DefaultValue = item.DefaultValue, + EntityName = item.EntityName, + IsIdentity = item.IsIdentity, + IsIgnore = item.IsIgnore, + IsNullable = item.IsNullable, + IsOnlyIgnoreInsert = item.IsOnlyIgnoreInsert, + IsPrimarykey = item.IsPrimarykey, + Length = item.Length, + OldDbColumnName = item.OldDbColumnName, + OracleSequenceName = item.OracleSequenceName, + PropertyInfo = item.PropertyInfo, + PropertyName = item.PropertyName + }; + columns.Add(item); + } + } + result.Columns = columns; + return result; + } + + private void InitMppingInfo(EntityInfo entityInfo) + { + if (this.Context.MappingTables == null) + this.Context.MappingTables = new MappingTableList(); + if (this.Context.MappingColumns == null) + this.Context.MappingColumns = new MappingColumnList(); + if (this.Context.IgnoreColumns == null) + this.Context.IgnoreColumns = new IgnoreColumnList(); + if (this.Context.IgnoreInsertColumns == null) + this.Context.IgnoreInsertColumns = new IgnoreColumnList(); + if (!this.Context.MappingTables.Any(it => it.EntityName == entityInfo.EntityName)) + { + if (entityInfo.DbTableName != entityInfo.EntityName && entityInfo.DbTableName.HasValue()) + { + this.Context.MappingTables.Add(entityInfo.EntityName, entityInfo.DbTableName); + } + } + if (entityInfo.Columns.Any(it => it.EntityName == entityInfo.EntityName)) + { + var mappingColumnInfos = this.Context.MappingColumns.Where(it => it.EntityName == entityInfo.EntityName); + foreach (var item in entityInfo.Columns.Where(it => it.IsIgnore == false)) + { + if (!mappingColumnInfos.Any(it => it.PropertyName == item.PropertyName)) + if (item.PropertyName != item.DbColumnName && item.DbColumnName.HasValue()) + this.Context.MappingColumns.Add(item.PropertyName, item.DbColumnName, item.EntityName); + } + var ignoreInfos = this.Context.IgnoreColumns.Where(it => it.EntityName == entityInfo.EntityName); + foreach (var item in entityInfo.Columns.Where(it => it.IsIgnore)) + { + if (!ignoreInfos.Any(it => it.PropertyName == item.PropertyName)) + this.Context.IgnoreColumns.Add(item.PropertyName, item.EntityName); + } + + var ignoreInsertInfos = this.Context.IgnoreInsertColumns.Where(it => it.EntityName == entityInfo.EntityName); + foreach (var item in entityInfo.Columns.Where(it => it.IsOnlyIgnoreInsert)) + { + if (!ignoreInsertInfos.Any(it => it.PropertyName == item.PropertyName)) + this.Context.IgnoreInsertColumns.Add(item.PropertyName, item.EntityName); + } + } + } + #endregion + + #region Create Instance + protected ISugarQueryable CreateQueryable() + { + ISugarQueryable result = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + return CreateQueryable(result); + } + protected ISugarQueryable CreateQueryable(ISugarQueryable result) + { + Check.Exception(typeof(T).IsClass() == false || typeof(T).GetConstructors().Length == 0, "Queryable<{0}> Error ,{0} is invalid , need is a class,and can new().", typeof(T).Name); + var sqlBuilder = InstanceFactory.GetSqlbuilder(CurrentConnectionConfig); + result.Context = this.Context; + result.SqlBuilder = sqlBuilder; + result.SqlBuilder.QueryBuilder = InstanceFactory.GetQueryBuilder(CurrentConnectionConfig); + result.SqlBuilder.QueryBuilder.Builder = sqlBuilder; + result.SqlBuilder.Context = result.SqlBuilder.QueryBuilder.Context = this.Context; + result.SqlBuilder.QueryBuilder.EntityType = typeof(T); + result.SqlBuilder.QueryBuilder.EntityName = typeof(T).Name; + result.SqlBuilder.QueryBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(CurrentConnectionConfig); + return result; + } + protected InsertableProvider CreateInsertable(T[] insertObjs) where T : class, new() + { + var result = InstanceFactory.GetInsertableProvider(this.CurrentConnectionConfig); + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; + result.Context = this.Context; + result.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); + result.SqlBuilder = sqlBuilder; + result.InsertObjs = insertObjs; + sqlBuilder.InsertBuilder = result.InsertBuilder = InstanceFactory.GetInsertBuilder(this.CurrentConnectionConfig); + sqlBuilder.InsertBuilder.Builder = sqlBuilder; + sqlBuilder.InsertBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); + sqlBuilder.Context = result.SqlBuilder.InsertBuilder.Context = this.Context; + result.Init(); + return result; + } + protected DeleteableProvider CreateDeleteable() where T : class, new() + { + var result = InstanceFactory.GetDeleteableProvider(this.CurrentConnectionConfig); + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; + result.Context = this.Context; + result.SqlBuilder = sqlBuilder; + sqlBuilder.DeleteBuilder = result.DeleteBuilder = InstanceFactory.GetDeleteBuilder(this.CurrentConnectionConfig); + sqlBuilder.DeleteBuilder.Builder = sqlBuilder; + sqlBuilder.DeleteBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); + sqlBuilder.Context = result.SqlBuilder.DeleteBuilder.Context = this.Context; + return result; + } + protected UpdateableProvider CreateUpdateable(T[] UpdateObjs) where T : class, new() + { + var result = InstanceFactory.GetUpdateableProvider(this.CurrentConnectionConfig); + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.CurrentConnectionConfig); ; + result.Context = this.Context; + result.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); + result.SqlBuilder = sqlBuilder; + result.UpdateObjs = UpdateObjs; + sqlBuilder.UpdateBuilder = result.UpdateBuilder = InstanceFactory.GetUpdateBuilder(this.CurrentConnectionConfig); + sqlBuilder.UpdateBuilder.Builder = sqlBuilder; + sqlBuilder.UpdateBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); + sqlBuilder.Context = result.SqlBuilder.UpdateBuilder.Context = this.Context; + result.Init(); + return result; + } + + protected void CreateQueryJoin(Expression joinExpression, Type[] types, ISugarQueryable queryable) + { + this.CreateQueryable(queryable); + string shortName = string.Empty; + List paramters = new List(); + queryable.SqlBuilder.QueryBuilder.JoinQueryInfos = this.GetJoinInfos(queryable.SqlBuilder, joinExpression, ref paramters, ref shortName, types); + queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; + queryable.SqlBuilder.QueryBuilder.JoinExpression = joinExpression; + if (paramters != null) + { + queryable.SqlBuilder.QueryBuilder.Parameters.AddRange(paramters); + } + } + protected void CreateEasyQueryJoin(Expression joinExpression, Type[] types, ISugarQueryable queryable) + { + this.CreateQueryable(queryable); + string shortName = string.Empty; + queryable.SqlBuilder.QueryBuilder.EasyJoinInfos = this.GetEasyJoinInfo(joinExpression, ref shortName, queryable.SqlBuilder, types); + queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; + queryable.SqlBuilder.QueryBuilder.JoinExpression = joinExpression; + } + #endregion + + #region Private methods + protected List GetJoinInfos(ISqlBuilder sqlBuilder, Expression joinExpression, ref List parameters, ref string shortName, params Type[] entityTypeArray) + { + List result = new List(); + var lambdaParameters = ((LambdaExpression)joinExpression).Parameters.ToList(); + ILambdaExpressions expressionContext = sqlBuilder.QueryBuilder.LambdaExpressions; + expressionContext.MappingColumns = this.Context.MappingColumns; + expressionContext.MappingTables = this.Context.MappingTables; + if (this.Context.CurrentConnectionConfig.ConfigureExternalServices != null) + expressionContext.SqlFuncServices = this.Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices; + expressionContext.Resolve(joinExpression, ResolveExpressType.Join); + int i = 0; + var joinArray = MergeJoinArray(expressionContext.Result.GetResultArray()); + if (joinArray == null) return null; + parameters = expressionContext.Parameters; + foreach (var entityType in entityTypeArray) + { + var isFirst = i == 0; ++i; + JoinQueryInfo joinInfo = new JoinQueryInfo(); + var hasMappingTable = expressionContext.MappingTables.HasValue(); + MappingTable mappingInfo = null; + if (hasMappingTable) + { + mappingInfo = expressionContext.MappingTables.FirstOrDefault(it => it.EntityName.Equals(entityType.Name, StringComparison.CurrentCultureIgnoreCase)); + joinInfo.TableName = mappingInfo != null ? mappingInfo.DbTableName : entityType.Name; + } + else + { + joinInfo.TableName = entityType.Name; + } + if (isFirst) + { + var firstItem = lambdaParameters.First(); + lambdaParameters.Remove(firstItem); + shortName = firstItem.Name; + } + var joinString = joinArray[i * 2 - 2]; + joinInfo.ShortName = lambdaParameters[i - 1].Name; + joinInfo.JoinType = (JoinType)Enum.Parse(typeof(JoinType), joinString); + joinInfo.JoinWhere = joinArray[i * 2 - 1]; + joinInfo.JoinIndex = i; + result.Add((joinInfo)); + } + expressionContext.Clear(); + return result; + } + + private string[] MergeJoinArray(string[] joinArray) + { + List result = new List(); + string joinValue = null; + int i = 0; + if (joinArray == null) return null; + foreach (var item in joinArray) + { + ++i; + var isLast = joinArray.Length == i; + var isJoinType = item.IsIn(JoinType.Inner.ToString(), JoinType.Left.ToString(), JoinType.Right.ToString()); + if (isJoinType) + { + if (joinValue != null) + result.Add(joinValue); + joinValue = null; + result.Add(item); + } + else + { + isJoinType = false; + joinValue += joinValue == null ? item : ("," + item); + } + if (isLast) + { + result.Add(joinValue); + } + } + return result.ToArray(); ; + } + + protected Dictionary GetEasyJoinInfo(Expression joinExpression, ref string shortName, ISqlBuilder builder, params Type[] entityTypeArray) + { + Dictionary result = new Dictionary(); + var lambdaParameters = ((LambdaExpression)joinExpression).Parameters.ToList(); + shortName = lambdaParameters.First().Name; + var index = 1; + foreach (var item in entityTypeArray) + { + result.Add(UtilConstants.Space + lambdaParameters[index].Name, item.Name); + ++index; + } + return result; + } + #endregion + } +} diff --git a/类库/SqlSugar/IntegrationServices/CacheService.cs b/类库/SqlSugar/IntegrationServices/CacheService.cs new file mode 100644 index 0000000..7401157 --- /dev/null +++ b/类库/SqlSugar/IntegrationServices/CacheService.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; +using System.Linq.Expressions; +namespace SqlSugar +{ + public class ReflectionInoCacheService : ICacheService + { + public void Add(string key, V value) + { + ReflectionInoCore.GetInstance().Add(key,value); + } + public void Add(string key, V value, int cacheDurationInSeconds) + { + ReflectionInoCore.GetInstance().Add(key, value,cacheDurationInSeconds); + } + + public bool ContainsKey(string key) + { + return ReflectionInoCore.GetInstance().ContainsKey(key); + } + + public V Get(string key) + { + return ReflectionInoCore.GetInstance().Get(key); + } + + public IEnumerable GetAllKey() + { + return ReflectionInoCore.GetInstance().GetAllKey(); + } + + public V GetOrCreate(string cacheKey, Func create,int cacheDurationInSeconds=int.MaxValue) + { + return ReflectionInoCore.GetInstance().GetOrCreate(cacheKey, create); + } + + public void Remove(string key) + { + ReflectionInoCore.GetInstance().Remove(key); + } + } + public class ReflectionInoCore + { + readonly System.Collections.Concurrent.ConcurrentDictionary InstanceCache = new System.Collections.Concurrent.ConcurrentDictionary(); + private static ReflectionInoCore _instance = null; + private static readonly object _instanceLock = new object(); + private ReflectionInoCore() { } + + public V this[string key] + { + get + { + return this.Get(key); + } + } + + public bool ContainsKey(string key) + { + return this.InstanceCache.ContainsKey(key); + } + + public V Get(string key) + { + if (this.ContainsKey(key)) + return this.InstanceCache[key]; + else + return default(V); + } + + public static ReflectionInoCore GetInstance() + { + if (_instance == null) + lock (_instanceLock) + if (_instance == null) + { + _instance = new ReflectionInoCore(); + Action addItem =()=> { ReflectionInoCore.GetInstance().RemoveAllCache(); }; + ReflectionInoHelper.AddRemoveFunc(addItem); + } + return _instance; + } + + public void Add(string key, V value) + { + this.InstanceCache.GetOrAdd(key, value); + } + + public void Add(string key, V value, int cacheDurationInSeconds) + { + Check.ThrowNotSupportedException("ReflectionInoCache.Add(string key, V value, int cacheDurationInSeconds)"); + } + + public void Remove(string key) + { + V val; + this.InstanceCache.TryRemove(key, out val); + } + + public void RemoveAllCache() + { + foreach (var key in GetAllKey()) + { + this.Remove(key); + } + } + + public IEnumerable GetAllKey() + { + return this.InstanceCache.Keys; + } + + public V GetOrCreate(string cacheKey, Func create) + { + if (this.ContainsKey(cacheKey)) return Get(cacheKey); + else + { + var reval = create(); + this.Add(cacheKey, reval); + return reval; + } + } + } + internal static class ReflectionInoHelper + { + private static List removeActions = new List(); + internal static void AddRemoveFunc(Action removeAction) + { + removeActions.Add(removeAction); + } + + public static void RemoveAllCache() + { + lock (removeActions) + { + foreach (var item in removeActions) + { + item(); + } + } + } + } +} diff --git a/类库/SqlSugar/IntegrationServices/SerializeService.cs b/类库/SqlSugar/IntegrationServices/SerializeService.cs new file mode 100644 index 0000000..cf6ec0a --- /dev/null +++ b/类库/SqlSugar/IntegrationServices/SerializeService.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SerializeService:ISerializeService + { + public string SerializeObject(object value) + { + return JsonConvert.SerializeObject(value); + } + + public T DeserializeObject(string value) + { + var jSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; + return JsonConvert.DeserializeObject(value, jSetting); + } + } +} diff --git a/类库/SqlSugar/Interface/IAdo.cs b/类库/SqlSugar/Interface/IAdo.cs new file mode 100644 index 0000000..36d7ec6 --- /dev/null +++ b/类库/SqlSugar/Interface/IAdo.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial interface IAdo + { + string SqlParameterKeyWord { get; } + IDbConnection Connection { get; set; } + IDbTransaction Transaction { get; set; } + IDataParameter[] ToIDbDataParameter(params SugarParameter[] pars); + SugarParameter[] GetParameters(object obj, PropertyInfo[] propertyInfo = null); + SqlSugarClient Context { get; set; } + void ExecuteBefore(string sql, SugarParameter[] pars); + void ExecuteAfter(string sql, SugarParameter[] pars); + + IDataParameterCollection DataReaderParameters { get; set; } + CommandType CommandType { get; set; } + bool IsEnableLogEvent { get; set; } + Action LogEventStarting { get; set; } + Action LogEventCompleted { get; set; } + Func> ProcessingEventStartingSQL { get; set; } + Action ErrorEvent { get; set; } + Action DiffLogEvent { get; set; } + bool IsClearParameters { get; set; } + int CommandTimeOut { get; set; } + TimeSpan SqlExecutionTime { get; } + IDbBind DbBind { get; } + void SetCommandToAdapter(IDataAdapter adapter, IDbCommand command); + IDataAdapter GetAdapter(); + IDbCommand GetCommand(string sql, SugarParameter[] parameters); + DataTable GetDataTable(string sql, object parameters); + DataTable GetDataTable(string sql, params SugarParameter[] parameters); + DataTable GetDataTable(string sql, List parameters); + DataSet GetDataSetAll(string sql, object parameters); + DataSet GetDataSetAll(string sql, params SugarParameter[] parameters); + DataSet GetDataSetAll(string sql, List parameters); + IDataReader GetDataReader(string sql, object parameters); + IDataReader GetDataReader(string sql, params SugarParameter[] parameters); + IDataReader GetDataReader(string sql, List parameters); + object GetScalar(string sql, object parameters); + object GetScalar(string sql, params SugarParameter[] parameters); + object GetScalar(string sql, List parameters); + int ExecuteCommand(string sql, object parameters); + int ExecuteCommand(string sql, params SugarParameter[] parameters); + int ExecuteCommand(string sql, List parameters); + string GetString(string sql, object parameters); + string GetString(string sql, params SugarParameter[] parameters); + string GetString(string sql, List parameters); + int GetInt(string sql, object pars); + int GetInt(string sql, params SugarParameter[] parameters); + int GetInt(string sql, List parameters); + Double GetDouble(string sql, object parameters); + Double GetDouble(string sql, params SugarParameter[] parameters); + Double GetDouble(string sql, List parameters); + decimal GetDecimal(string sql, object parameters); + decimal GetDecimal(string sql, params SugarParameter[] parameters); + decimal GetDecimal(string sql, List parameters); + DateTime GetDateTime(string sql, object parameters); + DateTime GetDateTime(string sql, params SugarParameter[] parameters); + DateTime GetDateTime(string sql, List parameters); + List SqlQuery(string sql, object parameters = null); + List SqlQuery(string sql, params SugarParameter[] parameters); + List SqlQuery(string sql, List parameters); + T SqlQuerySingle(string sql, object whereObj = null); + T SqlQuerySingle(string sql, params SugarParameter[] parameters); + T SqlQuerySingle(string sql, List parameters); + dynamic SqlQueryDynamic(string sql, object whereObj = null); + dynamic SqlQueryDynamic(string sql, params SugarParameter[] parameters); + dynamic SqlQueryDynamic(string sql, List parameters); + void Dispose(); + void Close(); + void Open(); + void CheckConnection(); + + void BeginTran(); + void BeginTran(IsolationLevel iso); + void BeginTran(string transactionName); + void BeginTran(IsolationLevel iso, string transactionName); + void RollbackTran(); + void CommitTran(); + + DbResult UseTran(Action action); + DbResult UseTran(Func action); + Task> UseTranAsync(Action action); + Task> UseTranAsync(Func action); + + void UseStoredProcedure(Action action); + T UseStoredProcedure(Func action); + IAdo UseStoredProcedure(); + } +} diff --git a/类库/SqlSugar/Interface/ICodeFirst.cs b/类库/SqlSugar/Interface/ICodeFirst.cs new file mode 100644 index 0000000..015c360 --- /dev/null +++ b/类库/SqlSugar/Interface/ICodeFirst.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial interface ICodeFirst + { + SqlSugarClient Context { get; set; } + ICodeFirst BackupTable(int maxBackupDataRows=int.MaxValue); + ICodeFirst SetStringDefaultLength(int length); + void InitTables(string entitiesNamespace); + void InitTables(string [] entitiesNamespaces); + void InitTables(params Type [] entityTypes); + void InitTables(Type entityType); + } +} diff --git a/类库/SqlSugar/Interface/IContextMethods.cs b/类库/SqlSugar/Interface/IContextMethods.cs new file mode 100644 index 0000000..2ed561d --- /dev/null +++ b/类库/SqlSugar/Interface/IContextMethods.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Dynamic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IContextMethods + { + SqlSugarClient Context { get; set; } + ExpandoObject DataReaderToExpandoObject(IDataReader reader); + List DataReaderToExpandoObjectList(IDataReader reader); + List DataReaderToList(IDataReader reader); + string SerializeObject(object value); + T DeserializeObject(string value); + T TranslateCopy(T sourceObject); + SqlSugarClient CopyContext(bool isCopyEvents = false); + dynamic DataTableToDynamic(DataTable table); + List DataTableToList(DataTable table); + ICacheService GetReflectionInoCacheInstance(); + void RemoveCacheAll(); + void RemoveCacheAll(); + void RemoveCache(string key); + KeyValuePair ConditionalModelToSql(List models,int beginIndex=0); + + } +} diff --git a/类库/SqlSugar/Interface/IDMLBuilder.cs b/类库/SqlSugar/Interface/IDMLBuilder.cs new file mode 100644 index 0000000..d067f56 --- /dev/null +++ b/类库/SqlSugar/Interface/IDMLBuilder.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public partial interface IDMLBuilder + { + string SqlTemplate { get; } + List Parameters { get; set; } + SqlSugarClient Context { get; set; } + StringBuilder sql { get; set; } + string ToSqlString(); + void Clear(); + } +} diff --git a/类库/SqlSugar/Interface/IDbBind.cs b/类库/SqlSugar/Interface/IDbBind.cs new file mode 100644 index 0000000..ebd3463 --- /dev/null +++ b/类库/SqlSugar/Interface/IDbBind.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial interface IDbBind + { + SqlSugarClient Context { get; set; } + List GuidThrow { get; } + List IntThrow { get; } + List StringThrow { get; } + List DecimalThrow { get; } + List DoubleThrow { get; } + List DateThrow { get; } + List ShortThrow { get; } + string GetPropertyTypeName(string dbTypeName); + string GetConvertString(string dbTypeName); + string GetDbTypeName(string csharpTypeName); + string GetCsharpTypeName(string dbTypeName); + List> MappingTypes { get; } + List DataReaderToList(Type type, IDataReader reader) ; + } +} diff --git a/类库/SqlSugar/Interface/IDbFirst.cs b/类库/SqlSugar/Interface/IDbFirst.cs new file mode 100644 index 0000000..b95ad66 --- /dev/null +++ b/类库/SqlSugar/Interface/IDbFirst.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial interface IDbFirst + { + SqlSugarClient Context { get; set; } + IDbFirst SettingClassTemplate(Func func); + IDbFirst SettingClassDescriptionTemplate(Func func); + IDbFirst SettingPropertyTemplate(Func func); + IDbFirst SettingPropertyDescriptionTemplate(Func func); + IDbFirst SettingConstructorTemplate(Func func); + IDbFirst SettingNamespaceTemplate(Func func); + IDbFirst IsCreateAttribute(bool isCreateAttribute = true); + IDbFirst IsCreateDefaultValue(bool isCreateDefaultValue=true); + IDbFirst Where(params string[] objectNames); + IDbFirst Where(Func func); + IDbFirst Where(DbObjectType dbObjectType); + void CreateClassFile(string directoryPath, string nameSpace = "Models"); + Dictionary ToClassStringList(string nameSpace = "Models"); + void Init(); + } +} diff --git a/类库/SqlSugar/Interface/IDbMaintenance.cs b/类库/SqlSugar/Interface/IDbMaintenance.cs new file mode 100644 index 0000000..c693304 --- /dev/null +++ b/类库/SqlSugar/Interface/IDbMaintenance.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public partial interface IDbMaintenance + { + SqlSugarClient Context { get; set; } + + #region DML + List GetViewInfoList(bool isCache=true); + List GetTableInfoList(bool isCache=true); + List GetColumnInfosByTableName(string tableName,bool isCache=true); + List GetIsIdentities(string tableName); + List GetPrimaries(string tableName); + #endregion + + #region Check + bool IsAnyTable(string tableName, bool isCache = true); + bool IsAnyColumn(string tableName, string column); + bool IsPrimaryKey(string tableName, string column); + bool IsIdentity(string tableName, string column); + bool IsAnyConstraint(string ConstraintName); + bool IsAnySystemTablePermissions(); + #endregion + + #region DDL + bool DropTable(string tableName); + bool TruncateTable(string tableName); + bool CreateTable(string tableName, List columns,bool isCreatePrimaryKey=true); + bool AddColumn(string tableName, DbColumnInfo column); + bool UpdateColumn(string tableName, DbColumnInfo column); + bool AddPrimaryKey(string tableName,string columnName); + bool AddPrimaryKeys(string tableName, string [] columnNames); + bool DropConstraint(string tableName, string constraintName); + bool BackupDataBase(string databaseName,string fullFileName); + bool BackupTable(string oldTableName, string newTableName, int maxBackupDataRows = int.MaxValue); + bool DropColumn(string tableName,string columnName); + bool RenameColumn(string tableName, string oldColumnName, string newColumnName); + bool AddRemark(EntityInfo entity); + bool AddColumnRemark(string columnName,string tableName,string description); + bool DeleteColumnRemark(string columnName, string tableName); + bool IsAnyColumnRemark(string columnName, string tableName); + bool AddTableRemark( string tableName, string description); + bool DeleteTableRemark(string tableName); + bool IsAnyTableRemark(string tableName); + bool RenameTable(string oldTableName,string newTableName); + #endregion + } +} diff --git a/类库/SqlSugar/Interface/IDeleteable.cs b/类库/SqlSugar/Interface/IDeleteable.cs new file mode 100644 index 0000000..418da30 --- /dev/null +++ b/类库/SqlSugar/Interface/IDeleteable.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IDeleteable where T : class, new() + { + DeleteBuilder DeleteBuilder { get; set; } + int ExecuteCommand(); + bool ExecuteCommandHasChange(); + Task ExecuteCommandAsync(); + Task ExecuteCommandHasChangeAsync(); + IDeleteable AS(string tableName); + IDeleteable With(string lockString); + IDeleteable Where(T deleteObj); + IDeleteable Where(Expression> expression); + IDeleteable Where(List deleteObjs); + IDeleteable In(PkType primaryKeyValue); + IDeleteable In(PkType[] primaryKeyValues); + IDeleteable In(List primaryKeyValues); + IDeleteable In(Expression> inField,PkType primaryKeyValue); + IDeleteable In(Expression> inField,PkType[] primaryKeyValues); + IDeleteable In(Expression> inField,List primaryKeyValues); + IDeleteable Where(string whereString,object parameters=null); + IDeleteable Where(string whereString, SugarParameter parameter); + IDeleteable Where(string whereString, SugarParameter[] parameters); + IDeleteable Where(string whereString, List parameters); + IDeleteable EnableDiffLogEvent(object businessData = null); + IDeleteable RemoveDataCache(); + KeyValuePair> ToSql(); + } +} diff --git a/类库/SqlSugar/Interface/IFilter.cs b/类库/SqlSugar/Interface/IFilter.cs new file mode 100644 index 0000000..265a163 --- /dev/null +++ b/类库/SqlSugar/Interface/IFilter.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public interface IFilter + { + IFilter Add(SqlFilterItem filter); + void Remove(string filterName); + List GeFilterList { get; } + } +} diff --git a/类库/SqlSugar/Interface/ILambdaExpressions.cs b/类库/SqlSugar/Interface/ILambdaExpressions.cs new file mode 100644 index 0000000..41ba694 --- /dev/null +++ b/类库/SqlSugar/Interface/ILambdaExpressions.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial interface ILambdaExpressions + { + MappingColumnList MappingColumns { get; set; } + MappingTableList MappingTables { get; set; } + IgnoreColumnList IgnoreComumnList { get; set; } + List SqlFuncServices { get; set; } + + List JoinQueryInfos { get; set; } + bool IsSingle { get; set; } + SqlSugarClient Context { get; set; } + IDbMethods DbMehtods { get; set; } + Expression Expression { get; set; } + int Index { get; set; } + int ParameterIndex { get; set; } + List Parameters { get; set; } + ExpressionResult Result { get; set; } + string SqlParameterKeyWord { get; } + string SingleTableNameSubqueryShortName { get; set; } + Action InitMappingInfo { get; set; } + Action RefreshMapping { get; set; } + + string GetAsString(string fieldName, string fieldValue); + void Resolve(Expression expression, ResolveExpressType resolveType); + void Clear(); + } +} diff --git a/类库/SqlSugar/Interface/IQueryable.cs b/类库/SqlSugar/Interface/IQueryable.cs new file mode 100644 index 0000000..e1d7a6e --- /dev/null +++ b/类库/SqlSugar/Interface/IQueryable.cs @@ -0,0 +1,1219 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial interface ISugarQueryable + { + SqlSugarClient Context { get; set; } + ISqlBuilder SqlBuilder { get; set; } + QueryBuilder QueryBuilder { get; set; } + ISugarQueryable Clone(); + ISugarQueryable AS(string tableName); + ISugarQueryable AS(string tableName); + ISugarQueryable With(string withString); + ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + ISugarQueryable Mapper(Action mapperAction); + ISugarQueryable Mapper(Action> mapperAction); + ISugarQueryable Mapper(Expression> mapperObject, Expression> mapperField); + ISugarQueryable Mapper(Expression>> mapperObject, Expression> mapperField); + ISugarQueryable AddParameters(object parameters); + ISugarQueryable AddParameters(SugarParameter[] parameters); + ISugarQueryable AddParameters(List parameters); + ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + ISugarQueryable WhereClass(ClassType whereClass,bool ignoreDefaultValue=false)where ClassType: class,new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + ISugarQueryable WhereClass(List whereClassList,bool ignoreDefaultValue = false) where ClassType : class, new(); + + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(string whereString, object parameters = null); + ISugarQueryable Where(List conditionalModels); + + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(string whereString, object parameters = null); + + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + T InSingle(object pkValue); + ISugarQueryable In(params TParamter[] pkValues); + ISugarQueryable In(string InFieldName, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(List pkValues); + ISugarQueryable In(string InFieldName, List inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable OrderBy(string orderFileds); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + + + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(string groupFileds); + + ISugarQueryable PartitionBy(Expression> expression); + ISugarQueryable PartitionBy(string groupFileds); + + ISugarQueryable Skip(int index); + ISugarQueryable Take(int num); + ISugarQueryable Distinct(); + + T Single(); + Task SingleAsync(); + T Single(Expression> expression); + Task SingleAsync(Expression> expression); + + T First(); + Task FirstAsync(); + T First(Expression> expression); + Task FirstAsync(Expression> expression); + + bool Any(Expression> expression); + Task AnyAsync(Expression> expression); + bool Any(); + Task AnyAsync(); + + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(); + ISugarQueryable Select(string select); + ISugarQueryable Select(string select); + ISugarQueryable MergeTable(); + + int Count(); + Task CountAsync(); + int Count(Expression> expression); + Task CountAsync(Expression> expression); + TResult Max(string maxField); + Task MaxAsync(string maxField); + TResult Max(Expression> expression); + Task MaxAsync(Expression> expression); + TResult Min(string minField); + Task MinAsync(string minField); + TResult Min(Expression> expression); + Task MinAsync(Expression> expression); + TResult Sum(string sumField); + Task SumAsync(string sumField); + TResult Sum(Expression> expression); + Task SumAsync(Expression> expression); + TResult Avg(string avgField); + Task AvgAsync(string avgField); + TResult Avg(Expression> expression); + Task AvgAsync(Expression> expression); + + List ToList(); + Task> ToListAsync(); + + string ToJson(); + Task ToJsonAsync(); + string ToJsonPage(int pageIndex, int pageSize); + Task ToJsonPageAsync(int pageIndex, int pageSize); + string ToJsonPage(int pageIndex, int pageSize, ref int totalNumber); + Task> ToJsonPageAsync(int pageIndex, int pageSize, int totalNumber); + KeyValuePair> ToSql(); + + + DataTable ToDataTable(); + Task ToDataTableAsync(); + DataTable ToDataTablePage(int pageIndex, int pageSize); + Task ToDataTablePageAsync(int pageIndex, int pageSize); + DataTable ToDataTablePage(int pageIndex, int pageSize, ref int totalNumber); + Task> ToDataTablePageAsync(int pageIndex, int pageSize, int totalNumber); + + List ToPageList(int pageIndex, int pageSize); + Task> ToPageListAsync(int pageIndex, int pageSize); + List ToPageList(int pageIndex, int pageSize, ref int totalNumber); + Task, int>> ToPageListAsync(int pageIndex, int pageSize, int totalNumber); + ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + string ToClassString(string className); + void Clear(); + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object whereObj = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object whereObj = null); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(string orderFileds); + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + new ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + new ISugarQueryable Having(string whereString, object whereObj = null); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + new ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + new ISugarQueryable Having(string whereString, object parameters = null); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + new ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + ISugarQueryable Having(Expression> expression); + new ISugarQueryable Having(string whereString, object parameters = null); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + + ISugarQueryable In(Expression> expression, params FieldType[] inValues); + ISugarQueryable In(Expression> expression, List inValues); + ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(ClassType whereClass, bool ignoreDefaultValue = false) where ClassType : class, new(); + /// + /// if a property that is not empty is a condition + /// + /// + /// + new ISugarQueryable WhereClass(List whereClassList, bool ignoreDefaultValue = false) where ClassType : class, new(); + + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + new ISugarQueryable OrderByIF(bool isOrderBy, string orderFileds); + new ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderByIF(bool isOrderBy, Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable Distinct(); + bool Any(Expression> expression); + #endregion + } + + #region 9-12 + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + #endregion + } + public partial interface ISugarQueryable : ISugarQueryable + { + #region Where + new ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + ISugarQueryable Where(Expression> expression); + new ISugarQueryable Where(List conditionalModels); + + new ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + ISugarQueryable WhereIF(bool isWhere, Expression> expression); + + new ISugarQueryable Where(string whereString, object parameters = null); + new ISugarQueryable WhereIF(bool isWhere, string whereString, object parameters = null); + #endregion + + #region Select + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + ISugarQueryable Select(Expression> expression); + #endregion + + #region OrderBy + new ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + ISugarQueryable OrderBy(Expression> expression, OrderByType type = OrderByType.Asc); + #endregion + + #region GroupBy + new ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + ISugarQueryable GroupBy(Expression> expression); + #endregion + + #region Aggr + TResult Max(Expression> expression); + TResult Min(Expression> expression); + TResult Sum(Expression> expression); + TResult Avg(Expression> expression); + #endregion + + #region In + new ISugarQueryable In(Expression> expression, params FieldType[] inValues); + new ISugarQueryable In(Expression> expression, List inValues); + new ISugarQueryable In(Expression> expression, ISugarQueryable childQueryExpression); + #endregion + + #region Other + new ISugarQueryable Clone(); + new ISugarQueryable AS(string tableName); + new ISugarQueryable AS(string tableName); + new ISugarQueryable Filter(string FilterName, bool isDisabledGobalFilter = false); + new ISugarQueryable AddParameters(object parameters); + new ISugarQueryable AddParameters(SugarParameter[] parameters); + new ISugarQueryable AddParameters(List parameters); + new ISugarQueryable AddJoinInfo(string tableName, string shortName, string joinWhere, JoinType type = JoinType.Left); + new ISugarQueryable With(string withString); + new ISugarQueryable WithCache(int cacheDurationInSeconds = int.MaxValue); + new ISugarQueryable WithCacheIF(bool isCache, int cacheDurationInSeconds = int.MaxValue); + #endregion + } + #endregion +} diff --git a/类库/SqlSugar/Interface/ISaveable.cs b/类库/SqlSugar/Interface/ISaveable.cs new file mode 100644 index 0000000..bedaa7f --- /dev/null +++ b/类库/SqlSugar/Interface/ISaveable.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public partial interface ISaveable where T : class, new() + { + int ExecuteCommand(); + T ExecuteReturnEntity(); + List ExecuteReturnList(); + ISaveable InsertColumns(Expression> columns); + ISaveable InsertIgnoreColumns(Expression> columns); + ISaveable UpdateColumns(Expression> columns); + ISaveable UpdateIgnoreColumns(Expression> columns); + ISaveable EnableDiffLogEvent(object businessData = null); + } +} diff --git a/类库/SqlSugar/Interface/ISqlBuilder.cs b/类库/SqlSugar/Interface/ISqlBuilder.cs new file mode 100644 index 0000000..b866e0e --- /dev/null +++ b/类库/SqlSugar/Interface/ISqlBuilder.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial interface ISqlBuilder + { + SqlSugarClient Context { get; set; } + CommandType CommandType { get; set; } + String AppendWhereOrAnd(bool isWhere, string sqlString); + string AppendHaving(string sqlString); + + SqlQueryBuilder SqlQueryBuilder { get; set; } + QueryBuilder QueryBuilder { get; set; } + InsertBuilder InsertBuilder { get; set; } + DeleteBuilder DeleteBuilder { get; set; } + UpdateBuilder UpdateBuilder { get; set; } + + string SqlParameterKeyWord { get; } + string SqlFalse { get; } + string SqlDateNow { get; } + string FullSqlDateNow { get; } + string SqlTranslationLeft { get; } + string SqlTranslationRight { get; } + string SqlSelectAll { get; } + + string GetTranslationTableName(string name); + string GetTranslationColumnName(string entityName, string propertyName); + string GetTranslationColumnName(string propertyName); + string GetNoTranslationColumnName(string name); + string GetPackTable(string sql,string shortName); + string GetDefaultShortName(); + + string GetWhere(string fieldName, string conditionalType, int? parameterIndex = null); + string GetUnionAllSql(List sqlList); + string GetUnionSql(List sqlList); + void RepairReplicationParameters(ref string appendSql, SugarParameter[] parameters, int addIndex); + } +} diff --git a/类库/SqlSugar/Interface/IUpdateable.cs b/类库/SqlSugar/Interface/IUpdateable.cs new file mode 100644 index 0000000..51f1872 --- /dev/null +++ b/类库/SqlSugar/Interface/IUpdateable.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IUpdateable where T : class, new() + { + UpdateBuilder UpdateBuilder { get; set; } + bool UpdateParameterIsNull { get; set; } + + int ExecuteCommand(); + bool ExecuteCommandHasChange(); + Task ExecuteCommandAsync(); + Task ExecuteCommandHasChangeAsync(); + IUpdateable AS(string tableName); + IUpdateable With(string lockString); + [Obsolete("Use IUpdateable IgnoreColumns(bool ignoreAllNullColumns, bool isOffIdentity = false);")] + IUpdateable Where(bool isNoUpdateNull,bool IsOffIdentity = false); + IUpdateable Where(Expression> expression); + IUpdateable Where(string whereSql,object parameters=null); + /// + /// + /// + /// + /// for example : = + /// + /// + IUpdateable Where(string fieldName, string conditionalType, object fieldValue); + /// + /// Non primary key entity update function + /// + /// + /// + IUpdateable WhereColumns(Expression> columns); + IUpdateable WhereColumns(string columnName); + IUpdateable WhereColumns(string [] columnNames); + IUpdateable UpdateColumns(Expression> columns); + IUpdateable UpdateColumns(Expression> columns); + IUpdateable UpdateColumns(Func updateColumMethod); + IUpdateable UpdateColumns(string[] columns); + IUpdateable UpdateColumns(Expression> columns); + IUpdateable UpdateColumnsIF(bool isUpdateColumns,Expression> columns); + IUpdateable UpdateColumnsIF(bool isUpdateColumns,Expression> columns); + IUpdateable UpdateColumnsIF(bool isUpdateColumns,Func updateColumMethod); + IUpdateable UpdateColumnsIF(bool isUpdateColumns,Expression> columns); + IUpdateable IgnoreColumns(bool ignoreAllNullColumns, bool isOffIdentity = false); + IUpdateable IgnoreColumns(Expression> columns); + IUpdateable IgnoreColumns(Func ignoreColumMethod); + IUpdateable IsEnableUpdateVersionValidation(); + IUpdateable EnableDiffLogEvent(object businessData = null); + IUpdateable ReSetValue(Expression> setValueExpression); + IUpdateable RemoveDataCache(); + KeyValuePair> ToSql(); + } +} diff --git a/类库/SqlSugar/Interface/Insertable.cs b/类库/SqlSugar/Interface/Insertable.cs new file mode 100644 index 0000000..5091f49 --- /dev/null +++ b/类库/SqlSugar/Interface/Insertable.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public interface IInsertable + { + InsertBuilder InsertBuilder { get; set; } + int ExecuteCommand(); + Task ExecuteCommandAsync(); + int ExecuteReturnIdentity(); + Task ExecuteReturnIdentityAsync(); + T ExecuteReturnEntity(); + Task ExecuteReturnEntityAsync(); + bool ExecuteCommandIdentityIntoEntity(); + Task ExecuteCommandIdentityIntoEntityAsync(); + long ExecuteReturnBigIdentity(); + Task ExecuteReturnBigIdentityAsync(); + IInsertable AS(string tableName); + IInsertable With(string lockString); + IInsertable InsertColumns(Expression> columns); + IInsertable InsertColumns(string[] columns); + IInsertable InsertColumns(Func insertColumMethod); + IInsertable IgnoreColumns(Expression> columns); + IInsertable IgnoreColumns(Func ignoreColumMethod); + IInsertable Where(bool isInsertNull, bool isOffIdentity = false); + IInsertable EnableDiffLogEvent(object businessData = null); + IInsertable RemoveDataCache(); + KeyValuePair> ToSql(); + } +} diff --git a/类库/SqlSugar/NuGet.exe b/类库/SqlSugar/NuGet.exe new file mode 100644 index 0000000..6bb79fe Binary files /dev/null and b/类库/SqlSugar/NuGet.exe differ diff --git a/类库/SqlSugar/OnlyNet/PostgreSQLExpressionContext.cs b/类库/SqlSugar/OnlyNet/PostgreSQLExpressionContext.cs new file mode 100644 index 0000000..32a0c86 --- /dev/null +++ b/类库/SqlSugar/OnlyNet/PostgreSQLExpressionContext.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + internal class PostgreSQLInserttable :InsertableProvider where T : class, new() + { + } + internal class PostgreSQLExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarClient Context + { + get + { + var message = ErrorMessage.GetThrowMessage( + "SqlSugar PostGreSQL only support.NET CORE", + "SqlSugar使用 PostGreSQL只支持.NET CORE"); + throw new Exception(message); + } + + set + { + var message = ErrorMessage.GetThrowMessage( + "SqlSugar PostGreSQL only support.NET CORE", + "SqlSugar使用 PostGreSQL只支持.NET CORE"); + throw new Exception(message); + } + } + } +} diff --git a/类库/SqlSugar/Properties/AssemblyInfo.cs b/类库/SqlSugar/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8217f6d --- /dev/null +++ b/类库/SqlSugar/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SqlSugar4")] +[assembly: AssemblyDescription("author sunkaixuan Apache Licence 2.0")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SqlSugar 4")] +[assembly: AssemblyCopyright("Copyright © 2016")] + + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c7c121b9-80c6-4caf-aadd-d85118ad1cf2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("4.9.9.3")] +[assembly: AssemblyFileVersion("4.9.9.3")] diff --git a/类库/SqlSugar/Realization/MySql/CodeFirst/MySqlCodeFirst.cs b/类库/SqlSugar/Realization/MySql/CodeFirst/MySqlCodeFirst.cs new file mode 100644 index 0000000..1de23e6 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/CodeFirst/MySqlCodeFirst.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MySqlCodeFirst : CodeFirstProvider + { + public override void NoExistLogic(EntityInfo entityInfo) + { + var tableName = GetTableName(entityInfo); + //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimarykey ? 0 : 1)) + { + if (item.IsIgnore) + continue; + DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item); + columns.Add(dbColumnInfo); + } + } + this.Context.DbMaintenance.CreateTable(tableName, columns,true); + } + protected override DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + var propertyType = UtilMethods.GetUnderType(item.PropertyInfo); + var result = new DbColumnInfo() + { + TableId = entityInfo.Columns.IndexOf(item), + DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName, + IsPrimarykey = item.IsPrimarykey, + IsIdentity = item.IsIdentity, + TableName = tableName, + IsNullable = item.IsNullable, + DefaultValue = item.DefaultValue, + ColumnDescription = item.ColumnDescription, + Length = item.Length, + DecimalDigits=item.DecimalDigits + }; + GetDbType(item, propertyType, result); + if (result.DataType.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.Length == 0) + { + result.Length = 1; + } + return result; + } + + protected override void ConvertColumns(List dbColumns) + { + foreach (var item in dbColumns) + { + if (item.DataType == "DateTime") + { + item.Length = 0; + } + } + } + + protected override void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + if (!item.IsPrimarykey) + this.Context.DbMaintenance.DropConstraint(tableName,null); + if (item.IsPrimarykey) + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + + internal DbColumnInfo GetEntityColumnToDbColumn(EntityInfo entity, string dbTableName, EntityColumnInfo item) + { + return EntityColumnToDbColumn(entity,dbTableName,item); + } + } +} diff --git a/类库/SqlSugar/Realization/MySql/DbBind/MySqlDbBind.cs b/类库/SqlSugar/Realization/MySql/DbBind/MySqlDbBind.cs new file mode 100644 index 0000000..c85e426 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/DbBind/MySqlDbBind.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SqlSugar +{ + public class MySqlDbBind : DbBindProvider + { + public override string GetDbTypeName(string csharpTypeName) + { + if (csharpTypeName == UtilConstants.ByteArrayType.Name) + { + return "blob"; + } + if (csharpTypeName == "Int32") + csharpTypeName = "int"; + if (csharpTypeName == "Int16") + csharpTypeName = "short"; + if (csharpTypeName == "Int64") + csharpTypeName = "long"; + if (csharpTypeName == "Boolean") + csharpTypeName = "bool"; + var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)); + return mappings.HasValue() ? mappings.First().Key : "varchar"; + } + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null && extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>(){ + + new KeyValuePair("int",CSharpDataType.@int), + new KeyValuePair("mediumint",CSharpDataType.@int), + new KeyValuePair("integer",CSharpDataType.@int), + + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("text",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("enum",CSharpDataType.@string), + new KeyValuePair("mediumtext",CSharpDataType.@string), + new KeyValuePair("tinytext",CSharpDataType.@string), + new KeyValuePair("longtext",CSharpDataType.@string), + + new KeyValuePair("tinyint",CSharpDataType.@byte), + new KeyValuePair("smallint",CSharpDataType.@short), + new KeyValuePair("bigint",CSharpDataType.@long), + new KeyValuePair("bit",CSharpDataType.@bool), + new KeyValuePair("real",CSharpDataType.@double), + new KeyValuePair("double",CSharpDataType.@double), + new KeyValuePair("float",CSharpDataType.@float), + new KeyValuePair("float",CSharpDataType.Single), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("numeric",CSharpDataType.@decimal), + new KeyValuePair("year",CSharpDataType.@int), + + new KeyValuePair("datetime",CSharpDataType.DateTime), + new KeyValuePair("timestamp",CSharpDataType.DateTime), + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("time",CSharpDataType.DateTime), + + new KeyValuePair("blob",CSharpDataType.byteArray), + new KeyValuePair("longblob",CSharpDataType.byteArray), + new KeyValuePair("tinyblob",CSharpDataType.byteArray), + new KeyValuePair("varbinary",CSharpDataType.byteArray), + new KeyValuePair("binary",CSharpDataType.byteArray), + new KeyValuePair("multipoint",CSharpDataType.byteArray), + new KeyValuePair("geometry",CSharpDataType.byteArray), + new KeyValuePair("multilinestring",CSharpDataType.byteArray), + new KeyValuePair("polygon",CSharpDataType.byteArray), + new KeyValuePair("mediumblob",CSharpDataType.byteArray), + + new KeyValuePair("varchar",CSharpDataType.Guid), + }; + public override List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte" }; + } + } + } +} diff --git a/类库/SqlSugar/Realization/MySql/DbFirst/MySqlDbFirst.cs b/类库/SqlSugar/Realization/MySql/DbFirst/MySqlDbFirst.cs new file mode 100644 index 0000000..6ecb3bb --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/DbFirst/MySqlDbFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MySqlDbFirst : DbFirstProvider + { + } +} diff --git a/类库/SqlSugar/Realization/MySql/DbMaintenance/MySqlDbMaintenance.cs b/类库/SqlSugar/Realization/MySql/DbMaintenance/MySqlDbMaintenance.cs new file mode 100644 index 0000000..fb4a508 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/DbMaintenance/MySqlDbMaintenance.cs @@ -0,0 +1,332 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MySqlDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetColumnInfosByTableNameSql + { + get + { + string sql = @"SELECT + 0 as TableId, + TABLE_NAME as TableName, + column_name AS DbColumnName, + CASE WHEN left(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)-1)='' THEN COLUMN_TYPE ELSE left(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)-1) END AS DataType, + CAST(SUBSTRING(COLUMN_TYPE,LOCATE('(',COLUMN_TYPE)+1,LOCATE(')',COLUMN_TYPE)-LOCATE('(',COLUMN_TYPE)-1) AS signed) AS Length, + column_default AS `DefaultValue`, + column_comment AS `ColumnDescription`, + CASE WHEN COLUMN_KEY = 'PRI' + THEN true ELSE false END AS `IsPrimaryKey`, + CASE WHEN EXTRA='auto_increment' THEN true ELSE false END as IsIdentity, + CASE WHEN is_nullable = 'YES' + THEN true ELSE false END AS `IsNullable` + FROM + Information_schema.columns where TABLE_NAME='{0}' and TABLE_SCHEMA=(select database()) ORDER BY TABLE_NAME"; + return sql; + } + } + protected override string GetTableInfoListSql + { + get + { + return @"select TABLE_NAME as Name,TABLE_COMMENT as Description from information_schema.tables + where TABLE_SCHEMA=(select database()) AND TABLE_TYPE='BASE TABLE'"; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"select TABLE_NAME as Name,TABLE_COMMENT as Description from information_schema.tables + where TABLE_SCHEMA=(select database()) AND TABLE_TYPE='VIEW' + "; + } + } + #endregion + + #region DDL + protected override string AddPrimaryKeySql + { + get + { + return "ALTER TABLE {0} ADD PRIMARY KEY({2}) /*{1}*/"; + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD {1} {2}{3} {4} {5} {6}"; + } + } + protected override string AlterColumnToTableSql + { + get + { + // return "ALTER TABLE {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}"; + return "alter table {0} change column {1} {1} {2}{3} {4} {5} {6}"; + } + } + protected override string BackupDataBaseSql + { + get + { + return "mysqldump.exe {0} -uroot -p > {1} "; + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1} $PrimaryKey)"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "TRUNCATE TABLE {0}"; + } + } + protected override string BackupTableSql + { + get + { + return "Create table {1} (Select * from {2} LIMIT 0,{0})"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + return "ALTER TABLE {0} DROP COLUMN {1}"; + } + } + protected override string DropConstraintSql + { + get + { + return "ALTER TABLE {0} drop primary key;"; + } + } + protected override string RenameColumnSql + { + get + { + return "exec sp_rename '{0}.{1}','{2}','column';"; + } + } + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select 1 from Information_schema.columns limit 0,1"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return "DEFAULT NULL"; + } + } + protected override string CreateTableNotNull + { + get + { + return "NOT NULL"; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return "AUTO_INCREMENT"; + } + } + + protected override string AddColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string DeleteColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string IsAnyColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string AddTableRemarkSql + { + get + { + return "ALTER TABLE {0} COMMENT='{1}';"; + } + } + + protected override string DeleteTableRemarkSql + { + get + { + return "ALTER TABLE {0} COMMENT='';"; + } + } + + protected override string IsAnyTableRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string RenameTableSql { + get + { + return "alter table {0} rename {1}"; + } + } + #endregion + + #region Methods + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + if (columns.HasValue()) + { + foreach (var item in columns) + { + if (item.DbColumnName.Equals("GUID",StringComparison.CurrentCultureIgnoreCase)&&item.Length==0) + { + item.Length = 10; + } + } + } + string sql = GetCreateTableSql(tableName, columns); + string primaryKeyInfo = null; + if (columns.Any(it => it.IsPrimarykey)&&isCreatePrimaryKey) { + primaryKeyInfo =string.Format( ", Primary key({0})",string.Join(",",columns.Where(it=>it.IsPrimarykey).Select(it=>this.SqlBuilder.GetTranslationColumnName(it.DbColumnName)))); + + } + sql = sql.Replace("$PrimaryKey", primaryKeyInfo); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public override bool AddRemark(EntityInfo entity) + { + var db = this.Context; + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + List columns = entity.Columns.Where(it => it.IsIgnore == false).ToList(); + foreach (var item in columns) + { + if (item.ColumnDescription != null) + { + var mySqlCodeFirst = this.Context.CodeFirst as MySqlCodeFirst; + string sql = GetUpdateColumnSql(entity.DbTableName, mySqlCodeFirst.GetEntityColumnToDbColumn(entity, entity.DbTableName, item))+" "+(item.IsIdentity? "AUTO_INCREMENT" : "")+" " + " COMMENT '" + item.ColumnDescription + "'"; + db.Ado.ExecuteCommand(sql); + } + } + return true; + } + protected override string GetCreateTableSql(string tableName, List columns) + { + List columnArray = new List(); + Check.Exception(columns.IsNullOrEmpty(), "No columns found "); + foreach (var item in columns) + { + string columnName = item.DbColumnName; + string dataSize = ""; + dataSize = GetSize(item); + string dataType = item.DataType; + string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = null; + string identity = item.IsIdentity ? this.CreateTableIdentity : null; + string addItem = string.Format(this.CreateTableColumn, this.SqlBuilder.GetTranslationColumnName(columnName), dataType, dataSize, nullType, primaryKey, identity); + columnArray.Add(addItem); + } + string tableString = string.Format(this.CreateTableSql, this.SqlBuilder.GetTranslationTableName(tableName), string.Join(",\r\n", columnArray)); + return tableString; + } + + protected override string GetSize(DbColumnInfo item) + { + string dataSize = null; + var isMax = item.Length > 4000 || item.Length == -1; + if (isMax) + { + dataSize=""; + item.DataType = "longtext"; + } + else if (item.Length > 0 && item.DecimalDigits == 0) + { + dataSize = item.Length > 0 ? string.Format("({0})", item.Length) : null; + } + else if (item.Length == 0 && item.DecimalDigits > 0) + { + item.Length = 10; + dataSize = string.Format("({0},{1})", item.Length, item.DecimalDigits); + } + else if (item.Length > 0 && item.DecimalDigits > 0) + { + dataSize = item.Length > 0 ? string.Format("({0},{1})", item.Length, item.DecimalDigits) : null; + } + return dataSize; + } + + public override bool IsAnyConstraint(string constraintName) + { + throw new NotSupportedException("MySql IsAnyConstraint NotSupportedException"); + } + public override bool BackupDataBase(string databaseName, string fullFileName) + { + Check.ThrowNotSupportedException("MySql BackupDataBase NotSupported"); + return false; + } + + #endregion + } +} diff --git a/类库/SqlSugar/Realization/MySql/MySqlProvider.cs b/类库/SqlSugar/Realization/MySql/MySqlProvider.cs new file mode 100644 index 0000000..36c6601 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/MySqlProvider.cs @@ -0,0 +1,116 @@ +using MySql.Data.MySqlClient; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class MySqlProvider : AdoProvider + { + public MySqlProvider() { } + public override IDbConnection Connection + { + get + { + if (base._DbConnection == null) + { + try + { + var mySqlConnectionString = base.Context.CurrentConnectionConfig.ConnectionString; + if (!mySqlConnectionString.ToLower().Contains("charset")) + { + mySqlConnectionString = mySqlConnectionString.Trim().TrimEnd(';') + ";charset=utf8;"; + } + base._DbConnection = new MySqlConnection(mySqlConnectionString); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + + public override void BeginTran(string transactionName) + { + base.BeginTran(); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + base.BeginTran(iso); + } + public override IDataAdapter GetAdapter() + { + return new MySqlDataAdapter(); + } + public override IDbCommand GetCommand(string sql, SugarParameter[] parameters) + { + MySqlCommand sqlCommand = new MySqlCommand(sql, (MySqlConnection)this.Connection); + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (MySqlTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + IDataParameter[] ipars = ToIDbDataParameter(parameters); + sqlCommand.Parameters.AddRange((MySqlParameter[])ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, IDbCommand command) + { + ((MySqlDataAdapter)dataAdapter).SelectCommand = (MySqlCommand)command; + } + /// + /// if mysql return MySqlParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + MySqlParameter[] result = new MySqlParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + var sqlParameter = new MySqlParameter(); + sqlParameter.ParameterName = parameter.ParameterName; + sqlParameter.Size = parameter.Size; + sqlParameter.Value = parameter.Value; + sqlParameter.DbType = parameter.DbType; + sqlParameter.Direction = parameter.Direction; + if (sqlParameter.Direction == 0) + { + sqlParameter.Direction = ParameterDirection.Input; + } + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue)) + { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/Realization/MySql/Queryable/MySqlQueryable.cs b/类库/SqlSugar/Realization/MySql/Queryable/MySqlQueryable.cs new file mode 100644 index 0000000..2abc0a3 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/Queryable/MySqlQueryable.cs @@ -0,0 +1,60 @@ +namespace SqlSugar +{ + public class MySqlQueryable : QueryableProvider + { + public override ISugarQueryable With(string withString) + { + return this; + } + + public override ISugarQueryable PartitionBy(string groupFileds) + { + this.GroupBy(groupFileds); + return this; + } + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } + public class MySqlQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlBuilder.cs b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlBuilder.cs new file mode 100644 index 0000000..51152c0 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlBuilder.cs @@ -0,0 +1,26 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class MySqlBuilder : SqlBuilderProvider + { + public override string SqlTranslationLeft { get { return "`"; } } + public override string SqlTranslationRight { get { return "`"; } } + public override string SqlDateNow + { + get + { + return "sysdate()"; + } + } + public override string FullSqlDateNow + { + get + { + return "select sysdate()"; + } + } + } +} diff --git a/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlDeleteBuilder.cs b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlDeleteBuilder.cs new file mode 100644 index 0000000..97189bc --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlDeleteBuilder.cs @@ -0,0 +1,7 @@ +namespace SqlSugar +{ + public class MySqlDeleteBuilder : DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlExpressionContext.cs b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlExpressionContext.cs new file mode 100644 index 0000000..7e1d6a3 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlExpressionContext.cs @@ -0,0 +1,142 @@ +using System; +using System.Linq; +namespace SqlSugar +{ + public class MySqlExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarClient Context { get; set; } + public MySqlExpressionContext() + { + base.DbMehtods = new MySqlMethod(); + } + public override string SqlTranslationLeft { get { return "`"; } } + public override string SqlTranslationRight { get { return "`"; } } + } + public class MySqlMethod : DefaultDbMethod, IDbMethods + { + public override string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" {0}({1}) ", parameter2.MemberValue, parameter.MemberName); + } + + public override string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat('%',{1},'%')) ", parameter.MemberName, parameter2.MemberName ); + } + + public override string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat({1},'%')) ", parameter.MemberName, parameter2.MemberName); + } + + public override string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like concat('%',{1}))", parameter.MemberName,parameter2.MemberName); + } + + public override string DateIsSameDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (TIMESTAMPDIFF(day,date({0}),date({1}))=0) ", parameter.MemberName, parameter2.MemberName); ; + } + + public override string DateIsSameByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (TIMESTAMPDIFF({2},{0},{1})=0) ", parameter.MemberName, parameter2.MemberName, parameter3.MemberValue); + } + + public override string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format(" (DATE_ADD({1} , INTERVAL {2} {0})) ", parameter3.MemberValue, parameter.MemberName, parameter2.MemberName); + } + + public override string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" (DATE_ADD({1} INTERVAL {0} day)) ", parameter.MemberName, parameter2.MemberName); + } + + public override string ToInt32(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToInt64(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS CHAR)", parameter.MemberName); + } + + public override string ToGuid(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS CHAR)", parameter.MemberName); + } + + public override string ToDouble(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string ToBool(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToDecimal(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" LENGTH({0})", parameter.MemberName); + } + public override string MergeString(params string[] strings) + { + return " concat("+string.Join(",", strings).Replace("+", "") + ") "; + } + public override string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("IFNULL({0},{1})", parameter.MemberName, parameter1.MemberName); + } + public override string GetDate() + { + return "NOW()"; + } + + public override string GetRandom() + { + return "rand()"; + } + } +} diff --git a/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlInsertBuilder.cs b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlInsertBuilder.cs new file mode 100644 index 0000000..5fca051 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlInsertBuilder.cs @@ -0,0 +1,84 @@ +using System; + +namespace SqlSugar +{ + public class MySqlInsertBuilder : InsertBuilder + { + public override string SqlTemplate + { + get + { + if (IsReturnIdentity) + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;SELECT LAST_INSERT_ID();"; + } + else + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;"; + + } + } + } + public override object FormatValue(object value) + { + var n = "N"; + if (this.Context.CurrentConnectionConfig.MoreSettings != null && this.Context.CurrentConnectionConfig.MoreSettings.MySqlDisableNarvchar) + { + n = ""; + } + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return n+"'" + GetString(value).ToSqlFilter() + "'"; + } + else + { + return n+"'" + GetString(value) + "'"; + } + } + } + private string GetString(object value) + { + var result = value.ToString(); + if (result.HasValue() && result.Contains("\\")) + { + result = result.Replace("\\", "\\\\"); + } + return result; + } + } +} diff --git a/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlQueryBuilder.cs b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlQueryBuilder.cs new file mode 100644 index 0000000..27432a3 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlQueryBuilder.cs @@ -0,0 +1,137 @@ +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public partial class MySqlQueryBuilder : QueryBuilder + { + #region Sql Template + public override string PageTempalte + { + get + { + /* + SELECT * FROM TABLE WHERE CONDITION ORDER BY ID DESC LIMIT 0,10 + */ + var template = "SELECT {0} FROM {1} {2} {3} {4} LIMIT {5},{6}"; + return template; + } + } + public override string DefaultOrderByTemplate + { + get + { + return "ORDER BY NOW() "; + } + } + + #endregion + + #region Common Methods + public override bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS \`\w+\.\w+\`"); + } + public override string ToSqlString() + { + base.AppendFilter(); + string oldOrderValue = this.OrderByValue; + string result = null; + sql = new StringBuilder(); + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString); + if (IsCount) { return sql.ToString(); } + if (Skip != null && Take == null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString, Skip.ObjToInt(), long.MaxValue); + } + else if (Skip == null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, 0, Take.ObjToInt()); + } + else if (Skip != null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, Skip.ObjToInt() > 0 ? Skip.ObjToInt() : 0, Take); + } + else + { + result = sql.ToString(); + } + this.OrderByValue = oldOrderValue; + return result; + } + private string ToCountSqlString() + { + base.AppendFilter(); + string oldOrderValue = this.OrderByValue; + string result = null; + sql = new StringBuilder(); + sql.AppendFormat(SqlTemplate, "Count(*)", GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString); + if (IsCount) { return sql.ToString(); } + if (Skip != null && Take == null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString, Skip.ObjToInt(), long.MaxValue); + } + else if (Skip == null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, 0, Take.ObjToInt()); + } + else if (Skip != null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result = string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, Skip.ObjToInt() > 0 ? Skip.ObjToInt() : 0, Take); + } + else + { + result = sql.ToString(); + } + this.OrderByValue = oldOrderValue; + return result; + } + public override string ToCountSql(string sql) + { + if (this.GroupByValue.HasValue()) + { + return base.ToCountSql(sql); + } + else + { + return ToCountSqlString(); + } + } + #endregion + + #region Get SQL Partial + public override string GetSelectValue + { + get + { + string result = string.Empty; + if (this.SelectValue == null || this.SelectValue is string) + { + result = GetSelectValueByString(); + } + else + { + result = GetSelectValueByExpression(); + } + if (this.SelectType == ResolveExpressType.SelectMultiple) + { + this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this.JoinQueryInfos.Select(it => it.TableName)); + } + if (IsDistinct) + { + result = " DISTINCT " + result; + } + return result; + } + } + + #endregion + } +} diff --git a/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlUpdateBuilder.cs b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlUpdateBuilder.cs new file mode 100644 index 0000000..2504cc0 --- /dev/null +++ b/类库/SqlSugar/Realization/MySql/SqlBuilder/MySqlUpdateBuilder.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class MySqlUpdateBuilder : UpdateBuilder + { + public override string SqlTemplateBatch + { + get + { + return @"UPDATE {1} S {2} INNER JOIN ${{0}} SET {0} "; + } + } + public override string SqlTemplateJoin + { + get + { + return @" ( + {0} + + ) T ON {1} + "; + } + } + protected override string TomultipleSqlString(List> groupList) + { + Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List need Primary key"); + int pageSize = 200; + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + StringBuilder batchUpdateSql = new StringBuilder(); + while (pageCount >= pageIndex) + { + StringBuilder updateTable = new StringBuilder(); + string setValues = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it => + { + if (SetValues.IsValuable()) + { + var setValue = SetValues.Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName)); + if (setValue != null && setValue.Any()) + { + return setValue.First().Value; + } + } + var result = string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(it.DbColumnName)); + return result; + })); + batchUpdateSql.AppendFormat(SqlTemplateBatch.ToString(), setValues, GetTableNameStringNoWith, TableWithString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + updateTable.Append(SqlTemplateBatchUnion); + } + updateTable.Append("\r\n SELECT " + string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value),this.Builder.GetTranslationColumnName(it.DbColumnName))))); + ++i; + } + pageIndex++; + updateTable.Append("\r\n"); + string whereString = null; + if (this.WhereValues.HasValue()) + { + foreach (var item in WhereValues) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += item; + } + } + else if (PrimaryKeys.HasValue()) + { + foreach (var item in PrimaryKeys) + { + var isFirst = whereString == null; + whereString += (isFirst ? null : " AND "); + whereString += string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(item)); + } + } + var format= string.Format(SqlTemplateJoin, updateTable, whereString); + batchUpdateSql.Replace("${0}",format); + batchUpdateSql.Append(";"); + } + return batchUpdateSql.ToString(); + } + public override object FormatValue(object value) + { + var n = "N"; + if (this.Context.CurrentConnectionConfig.MoreSettings != null&&this.Context.CurrentConnectionConfig.MoreSettings.MySqlDisableNarvchar) + { + n = ""; + } + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return n+"'" + GetString(value).ToSqlFilter() + "'"; + } + else + { + return n+"'" + GetString(value) + "'"; + } + } + } + private string GetString(object value) + { + var result = value.ToString(); + if (result.HasValue() && result.Contains("\\")) + { + result = result.Replace("\\", "\\\\"); + } + return result; + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/CodeFirst/OracleCodeFirst.cs b/类库/SqlSugar/Realization/Oracle/CodeFirst/OracleCodeFirst.cs new file mode 100644 index 0000000..3d7cafb --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/CodeFirst/OracleCodeFirst.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleCodeFirst : CodeFirstProvider + { + public OracleCodeFirst() { + if (DefultLength == 0) + DefultLength = 40; + } + protected override int DefultLength { get; set; } + + protected override void GetDbType(EntityColumnInfo item, Type propertyType, DbColumnInfo result) + { + if (!string.IsNullOrEmpty(item.DataType)) + { + result.DataType = item.DataType; + } + else if (propertyType.IsEnum()) + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(item.Length > 9 ? UtilConstants.LongType.Name : UtilConstants.IntType.Name); + } + else + { + if (propertyType.Name.Equals("Guid", StringComparison.CurrentCultureIgnoreCase)) + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(UtilConstants.StringType.Name); + } + else + { + result.DataType = this.Context.Ado.DbBind.GetDbTypeName(propertyType.Name); + } + } + } + + protected override void KeyAction(EntityColumnInfo item, DbColumnInfo dbColumn, out bool pkDiff, out bool idEntityDiff) + { + pkDiff = item.IsPrimarykey != dbColumn.IsPrimarykey; + idEntityDiff = false; + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/DbBind/OracleDbBind.cs b/类库/SqlSugar/Realization/Oracle/DbBind/OracleDbBind.cs new file mode 100644 index 0000000..42fb2cc --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/DbBind/OracleDbBind.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class OracleDbBind : DbBindProvider + { + public override string GetDbTypeName(string csharpTypeName) + { + if (csharpTypeName == UtilConstants.ByteArrayType.Name) + return "blob"; + if (csharpTypeName.ToLower() == "int32") + csharpTypeName = "int"; + if (csharpTypeName.ToLower() == "int16") + csharpTypeName = "short"; + if (csharpTypeName.ToLower() == "int64") + csharpTypeName = "long"; + if (csharpTypeName.ToLower().IsIn("boolean", "bool")) + csharpTypeName = "bool"; + var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)); + return mappings.HasValue() ? mappings.First().Key : "varchar"; + } + public override string GetPropertyTypeName(string dbTypeName) + { + dbTypeName = dbTypeName.ToLower(); + var propertyTypes = MappingTypes.Where(it => it.Value.ToString().ToLower() == dbTypeName || it.Key.ToLower() == dbTypeName); + if (dbTypeName == "int32") + { + return "int"; + } + else if (dbTypeName == "int64") + { + return "long"; + } + else if (dbTypeName == "int16") + { + return "short"; + } + else if (propertyTypes == null) + { + return "other"; + } + else if (dbTypeName == "xml" || dbTypeName == "string") + { + return "string"; + } + if (dbTypeName == "byte[]") + { + return "byte[]"; + } + else if (propertyTypes == null || propertyTypes.Count() == 0) + { + Check.ThrowNotSupportedException(string.Format(" \"{0}\" Type NotSupported, DbBindProvider.GetPropertyTypeName error.", dbTypeName)); + return null; + } + else if (propertyTypes.First().Value == CSharpDataType.byteArray) + { + return "byte[]"; + } + else + { + return propertyTypes.First().Value.ToString(); + } + } + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null && extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>() + { + new KeyValuePair("int",CSharpDataType.@int), + new KeyValuePair("integer",CSharpDataType.@int), + new KeyValuePair("interval year to month",CSharpDataType.@int), + new KeyValuePair("interval day to second",CSharpDataType.@int), + + new KeyValuePair("number",CSharpDataType.@int), + new KeyValuePair("number",CSharpDataType.@float), + new KeyValuePair("number",CSharpDataType.@short), + new KeyValuePair("number",CSharpDataType.@byte), + new KeyValuePair("number",CSharpDataType.@double), + new KeyValuePair("number",CSharpDataType.@long), + new KeyValuePair("number",CSharpDataType.@bool), + new KeyValuePair("number",CSharpDataType.@decimal), + new KeyValuePair("number",CSharpDataType.Single), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("decimal",CSharpDataType.Single), + + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("varchar2",CSharpDataType.@string), + new KeyValuePair("nvarchar2",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("nchar",CSharpDataType.@string), + new KeyValuePair("clob",CSharpDataType.@string), + new KeyValuePair("long",CSharpDataType.@string), + new KeyValuePair("nclob",CSharpDataType.@string), + new KeyValuePair("rowid",CSharpDataType.@string), + + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("timestamp",CSharpDataType.DateTime), + new KeyValuePair("timestamp with local time zone",CSharpDataType.DateTime), + new KeyValuePair("timestamp with time zone",CSharpDataType.DateTime), + new KeyValuePair("timestamp with time zone",CSharpDataType.DateTime), + + new KeyValuePair("float",CSharpDataType.@decimal), + + new KeyValuePair("blob",CSharpDataType.byteArray), + new KeyValuePair("long raw",CSharpDataType.byteArray), + new KeyValuePair("raw",CSharpDataType.byteArray), + new KeyValuePair("bfile",CSharpDataType.byteArray), + new KeyValuePair("varbinary",CSharpDataType.byteArray) }; + public override List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte" }; + } + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/DbFirst/OracleDbFirst.cs b/类库/SqlSugar/Realization/Oracle/DbFirst/OracleDbFirst.cs new file mode 100644 index 0000000..fba461c --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/DbFirst/OracleDbFirst.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleDbFirst : DbFirstProvider + { + + } +} diff --git a/类库/SqlSugar/Realization/Oracle/DbMaintenance/OracleDbMaintenance.cs b/类库/SqlSugar/Realization/Oracle/DbMaintenance/OracleDbMaintenance.cs new file mode 100644 index 0000000..81639b7 --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/DbMaintenance/OracleDbMaintenance.cs @@ -0,0 +1,394 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetColumnInfosByTableNameSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string GetTableInfoListSql + { + get + { + return @"SELECT table_name name from user_tables where + table_name!='HELP' + AND table_name NOT LIKE '%$%' + AND table_name NOT LIKE 'LOGMNRC_%' + AND table_name!='LOGMNRP_CTAS_PART_MAP' + AND table_name!='LOGMNR_LOGMNR_BUILDLOG' + AND table_name!='SQLPLUS_PRODUCT_PROFILE' + "; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"select view_name name from user_views + WHERE VIEW_name NOT LIKE '%$%' + AND VIEW_NAME !='PRODUCT_PRIVS' + AND VIEW_NAME NOT LIKE 'MVIEW_%' "; + } + } + #endregion + + #region DDL + protected override string AddPrimaryKeySql + { + get + { + return "ALTER TABLE {0} ADD CONSTRAINT {1} PRIMARY KEY({2})"; + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD ({1} {2}{3} {4} {5} {6})"; + } + } + protected override string AlterColumnToTableSql + { + get + { + return "ALTER TABLE {0} modify ({1} {2}{3} {4} {5} {6}) "; + } + } + protected override string BackupDataBaseSql + { + get + { + return @"USE master;BACKUP DATABASE {0} TO disk = '{1}'"; + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1})"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "TRUNCATE TABLE {0}"; + } + } + protected override string BackupTableSql + { + get + { + return "create table {1} as select * from {2} where ROWNUM<={0}"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + return "ALTER TABLE {0} DROP COLUMN {1}"; + } + } + protected override string DropConstraintSql + { + get + { + return "ALTER TABLE {0} DROP CONSTRAINT {1}"; + } + } + protected override string RenameColumnSql + { + get + { + return "ALTER TABLE {0} rename column {1} to {2}"; + } + } + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select t.table_name from user_tables t where rownum=1"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return ""; + } + } + protected override string CreateTableNotNull + { + get + { + return ""; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return ""; + } + } + + protected override string AddColumnRemarkSql + { + get + { + return "comment on column {1}.{0} is '{2}'"; + } + } + + protected override string DeleteColumnRemarkSql + { + get + { + return "comment on column {1}.{0} is ''"; + } + } + + protected override string IsAnyColumnRemarkSql + { + get + { + return "select * from user_col_comments where Table_Name='{1}' AND COLUMN_NAME='{0}' order by column_name"; + } + } + + protected override string AddTableRemarkSql + { + get + { + return "comment on table {0} is '{1}'"; + } + } + + protected override string DeleteTableRemarkSql + { + get + { + return "comment on table {0} is ''"; + } + } + + protected override string IsAnyTableRemarkSql + { + get + { + return "select * from user_tab_comments where Table_Name='{0}'order by Table_Name"; + } + } + + protected override string RenameTableSql { + get + { + return "alter table {0} rename to {1}"; + } + } + #endregion + + #region Methods + public override bool AddRemark(EntityInfo entity) + { + var db = this.Context; + var columns = entity.Columns.Where(it => it.IsIgnore == false).ToList(); + + foreach (var item in columns) + { + if (item.ColumnDescription != null) + { + //column remak + if (db.DbMaintenance.IsAnyColumnRemark(item.DbColumnName.ToUpper(), item.DbTableName.ToUpper())) + { + db.DbMaintenance.DeleteColumnRemark(item.DbColumnName.ToUpper(), item.DbTableName.ToUpper()); + db.DbMaintenance.AddColumnRemark(item.DbColumnName.ToUpper(), item.DbTableName.ToUpper(), item.ColumnDescription); + } + else + { + db.DbMaintenance.AddColumnRemark(item.DbColumnName.ToUpper(), item.DbTableName.ToUpper(), item.ColumnDescription); + } + } + } + + //table remak + if (entity.TableDescription != null) + { + if (db.DbMaintenance.IsAnyTableRemark(entity.DbTableName)) + { + db.DbMaintenance.DeleteTableRemark(entity.DbTableName); + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + else + { + db.DbMaintenance.AddTableRemark(entity.DbTableName, entity.TableDescription); + } + } + return true; + } + public override List GetColumnInfosByTableName(string tableName, bool isCache = true) + { + string cacheKey = "DbMaintenanceProvider.GetColumnInfosByTableName." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + if (!isCache) + return GetColumnInfosByTableName(tableName); + else + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + return GetColumnInfosByTableName(tableName); + + }); + } + + private List GetColumnInfosByTableName(string tableName) + { + string sql = "select * from " + tableName + " WHERE 1=2 "; + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + using (DbDataReader reader = (DbDataReader)this.Context.Ado.GetDataReader(sql)) + { + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + List result = new List(); + var schemaTable = reader.GetSchemaTable(); + foreach (System.Data.DataRow row in schemaTable.Rows) + { + DbColumnInfo column = new DbColumnInfo() + { + TableName = tableName, + DataType = row["DataType"].ToString().Replace("System.", "").Trim(), + IsNullable = (bool)row["AllowDBNull"], + //IsIdentity = (bool)row["IsAutoIncrement"], + ColumnDescription = GetFieldComment(tableName, row["ColumnName"].ToString()), + DbColumnName = row["ColumnName"].ToString(), + //DefaultValue = row["defaultValue"].ToString(), + IsPrimarykey = GetPrimaryKeyByTableNames(tableName).Any(it => it.Equals(row["ColumnName"].ToString(), StringComparison.CurrentCultureIgnoreCase)), + Length = row["ColumnSize"].ObjToInt(), + Scale = row["numericscale"].ObjToInt() + }; + result.Add(column); + } + return result; + } + } + + private List GetPrimaryKeyByTableNames(string tableName) + { + string cacheKey = "DbMaintenanceProvider.GetPrimaryKeyByTableNames." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + string sql = @" select distinct cu.COLUMN_name KEYNAME from user_cons_columns cu, user_constraints au + where cu.constraint_name = au.constraint_name + and au.constraint_type = 'P' and au.table_name = '" + tableName.ToUpper() + @"'"; + var pks = this.Context.Ado.SqlQuery(sql); + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + return pks; + }); + } + + public string GetTableComment(string tableName) + { + string cacheKey = "DbMaintenanceProvider.GetTableComment." + tableName; + var comments = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + string sql = "SELECT COMMENTS FROM USER_TAB_COMMENTS WHERE TABLE_NAME =@tableName ORDER BY TABLE_NAME"; + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + var pks = this.Context.Ado.SqlQuery(sql, new { tableName = tableName.ToUpper() }); + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + return pks; + }); + return comments.HasValue() ? comments.First() : ""; + } + + public string GetFieldComment(string tableName, string filedName) + { + string cacheKey = "DbMaintenanceProvider.GetFieldComment." + tableName; + var comments = this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + string sql = "SELECT TABLE_NAME AS TableName, COLUMN_NAME AS DbColumnName,COMMENTS AS ColumnDescription FROM user_col_comments WHERE TABLE_NAME =@tableName ORDER BY TABLE_NAME"; + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + var pks = this.Context.Ado.SqlQuery(sql, new { tableName = tableName.ToUpper() }); + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + return pks; + }); + return comments.HasValue() ? comments.First(it => it.DbColumnName.Equals(filedName, StringComparison.CurrentCultureIgnoreCase)).ColumnDescription : ""; + + } + + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + if (columns.HasValue()) + { + foreach (var item in columns) + { + if (item.DbColumnName.Equals("GUID", StringComparison.CurrentCultureIgnoreCase) && item.Length == 0) + { + item.Length = 50; + } + if (item.DataType == "varchar" && item.Length == 0) + { + item.Length = 50; + } + } + } + string sql = GetCreateTableSql(tableName, columns); + this.Context.Ado.ExecuteCommand(sql); + if (isCreatePrimaryKey) + { + var pkColumns = columns.Where(it => it.IsPrimarykey).ToList(); + foreach (var item in pkColumns) + { + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + } + return true; + } + #endregion + } +} diff --git a/类库/SqlSugar/Realization/Oracle/Deleteable/OracleDeleteable.cs b/类库/SqlSugar/Realization/Oracle/Deleteable/OracleDeleteable.cs new file mode 100644 index 0000000..fbd8d54 --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/Deleteable/OracleDeleteable.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleDeleteable:DeleteableProvider where T:class,new() + { + protected override List GetIdentityKeys() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.DbColumnName).ToList(); + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/Insertable/OracleInsertable.cs b/类库/SqlSugar/Realization/Oracle/Insertable/OracleInsertable.cs new file mode 100644 index 0000000..05dbb22 --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/Insertable/OracleInsertable.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleInsertable : InsertableProvider where T : class, new() + { + + protected override List GetIdentityKeys() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.DbColumnName).ToList(); + } + protected string GetSeqName() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.OracleSequenceName).First(); + } + protected List GetSeqNames() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.OracleSequenceName).ToList(); + } + public override int ExecuteReturnIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + var count = Ado.ExecuteCommand(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + var result = (this.GetIdentityKeys().IsNullOrEmpty() || count == 0) ? 0 : GetSeqValue(GetSeqName()).ObjToInt(); + return result; + } + + public override long ExecuteReturnBigIdentity() + { + InsertBuilder.IsReturnIdentity = true; + PreToSql(); + string sql = InsertBuilder.ToSqlString(); + RestoreMapping(); + var count = Ado.ExecuteCommand(sql, InsertBuilder.Parameters == null ? null : InsertBuilder.Parameters.ToArray()); + var result = (this.GetIdentityKeys().IsNullOrEmpty() || count == 0) ? 0 :Convert.ToInt64(GetSeqValue(GetSeqName())); + return result; + } + + + public override int ExecuteCommand() + { + base.ExecuteCommand(); + return base.InsertObjs.Count(); + } + + private object GetSeqValue(string seqName) + { + return Ado.GetScalar(" SELECT " + seqName + ".currval FROM DUAL"); + } + protected override void PreToSql() + { + var identities = GetSeqNames(); + var insertCount = InsertObjs.Count(); + InsertBuilder.OracleSeqInfoList = new Dictionary(); + if (identities.HasValue() && insertCount > 1) + { + Check.Exception(identities.Count != identities.Distinct().Count(), "The field sequence needs to be unique"); + foreach (var seqName in identities) + { + int seqBeginValue = 0; + this.Ado.ExecuteCommand("alter sequence " + seqName + " increment by " + insertCount); + seqBeginValue = this.Ado.GetInt("select " + seqName + ".Nextval from dual") - insertCount; + this.Ado.ExecuteCommand("alter sequence " + seqName + " increment by " + 1); + InsertBuilder.OracleSeqInfoList.Add(seqName, seqBeginValue); + } + } + base.PreToSql(); + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/OracleProvider.cs b/类库/SqlSugar/Realization/Oracle/OracleProvider.cs new file mode 100644 index 0000000..365965e --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/OracleProvider.cs @@ -0,0 +1,174 @@ +using Oracle.ManagedDataAccess.Client; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class OracleProvider : AdoProvider + { + public OracleProvider() + { + this.FormatSql = sql => + { + if (sql.HasValue()&&sql.Contains("@")) { + var exceptionalCaseInfo = Regex.Matches(sql, @"\'.*?\@.*?\'| [\.,\w]+\@[\.,\w]+ | [\.,\w]+\@[\.,\w]+"); + if (exceptionalCaseInfo != null) { + foreach (var item in exceptionalCaseInfo.Cast()) + { + sql = sql.Replace(item.Value, item.Value.Replace("@", UtilConstants.ReplaceKey)); + } + } + sql = sql .Replace("@",":"); + sql = sql.Replace(UtilConstants.ReplaceKey, "@"); + } + return sql; + }; + } + public override string SqlParameterKeyWord + { + get + { + return ":"; + } + } + public override IDbConnection Connection + { + get + { + try + { + if (base._DbConnection == null) + { + base._DbConnection = new OracleConnection(base.Context.CurrentConnectionConfig.ConnectionString); + } + } + catch (Exception ex) + { + + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + /// + /// Only SqlServer + /// + /// + public override void BeginTran(string transactionName) + { + ((OracleConnection)this.Connection).BeginTransaction(); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + ((OracleConnection)this.Connection).BeginTransaction(iso); + } + public override IDataAdapter GetAdapter() + { + return new OracleDataAdapter(); + } + public override IDbCommand GetCommand(string sql, SugarParameter[] parameters) + { + OracleCommand sqlCommand = new OracleCommand(sql, (OracleConnection)this.Connection); + sqlCommand.BindByName = true; + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (OracleTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + IDataParameter[] ipars = ToIDbDataParameter(parameters); + sqlCommand.Parameters.AddRange((OracleParameter[])ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, IDbCommand command) + { + ((OracleDataAdapter)dataAdapter).SelectCommand = (OracleCommand)command; + } + /// + /// if mysql return MySqlParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + OracleParameter[] result = new OracleParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + var sqlParameter = new OracleParameter(); + sqlParameter.Size = parameter.Size == -1 ? 0 : parameter.Size; + sqlParameter.ParameterName = parameter.ParameterName; + if (sqlParameter.ParameterName[0] == '@') + { + sqlParameter.ParameterName = ':' + sqlParameter.ParameterName.Substring(1, sqlParameter.ParameterName.Length - 1); + } + if (this.CommandType == CommandType.StoredProcedure) + { + sqlParameter.ParameterName = sqlParameter.ParameterName.TrimStart(':'); + } + if (parameter.IsRefCursor) + { + sqlParameter.OracleDbType = OracleDbType.RefCursor; + } + if (sqlParameter.DbType == System.Data.DbType.Guid) + { + sqlParameter.DbType = System.Data.DbType.String; + sqlParameter.Value = sqlParameter.Value.ObjToString(); + } + else if (parameter.DbType == System.Data.DbType.Boolean) + { + sqlParameter.DbType = System.Data.DbType.Int16; + if (parameter.Value == DBNull.Value) + { + parameter.Value = 0; + } + else + { + sqlParameter.Value = (bool)parameter.Value ? 1 : 0; + } + } + else + { + if (parameter.Value != null && parameter.Value.GetType() == UtilConstants.GuidType) + { + parameter.Value = parameter.Value.ToString(); + } + sqlParameter.Value = parameter.Value; + } + if (parameter.Direction != 0) + sqlParameter.Direction = parameter.Direction; + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue)) + { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/Queryable/OracleQueryable.cs b/类库/SqlSugar/Realization/Oracle/Queryable/OracleQueryable.cs new file mode 100644 index 0000000..720bdc8 --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/Queryable/OracleQueryable.cs @@ -0,0 +1,65 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class OracleQueryable : QueryableProvider + { + public override ISugarQueryable With(string withString) + { + return this; + } + protected override List GetIdentityKeys() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.DbColumnName).ToList(); + } + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } + public class OracleQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleBuilder.cs b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleBuilder.cs new file mode 100644 index 0000000..c0e9026 --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleBuilder.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleBuilder : SqlBuilderProvider + { + public override string SqlParameterKeyWord + { + get + { + return ":"; + } + } + public override string SqlDateNow + { + get + { + return "sysdate"; + } + } + public override string FullSqlDateNow + { + get + { + return "select sysdate from dual"; + } + } + public override string SqlTranslationLeft { get { return "\""; } } + public override string SqlTranslationRight { get { return "\""; } } + public override string GetTranslationTableName(string name) + { + var result = base.GetTranslationTableName(name); + if (result.Contains("(") && result.Contains(")")) + return result; + else + return result.ToUpper(); + } + public override string GetTranslationColumnName(string entityName, string propertyName) + { + var result = base.GetTranslationColumnName(entityName, propertyName); + return result.ToUpper(); + } + public override string GetTranslationColumnName(string propertyName) + { + var result = base.GetTranslationColumnName(propertyName); + return result.ToUpper(); + } + + } +} diff --git a/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleDeleteBuilder.cs b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleDeleteBuilder.cs new file mode 100644 index 0000000..504d0be --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleDeleteBuilder.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleDeleteBuilder : DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleExpressionContext.cs b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleExpressionContext.cs new file mode 100644 index 0000000..340973a --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleExpressionContext.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class OracleExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarClient Context { get; set; } + public OracleExpressionContext() + { + base.DbMehtods = new OracleMethod(); + } + public override string SqlParameterKeyWord + { + get + { + return ":"; + } + } + public override string SqlTranslationLeft { get { return "\""; } } + public override string SqlTranslationRight { get { return "\""; } } + public override string GetTranslationTableName(string entityName, bool isMapping = true) + { + return base.GetTranslationTableName(entityName, isMapping).ToUpper(); + } + public override string GetTranslationColumnName(string columnName) + { + return base.GetTranslationColumnName(columnName).ToUpper(); + } + public override string GetDbColumnName(string entityName, string propertyName) + { + return base.GetDbColumnName(entityName,propertyName).ToUpper(); + } + } + public partial class OracleMethod : DefaultDbMethod, IDbMethods + { + public override string ToTime(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" to_timestamp({0},'0000-01-01 hh24:mi:ss') ", parameter.MemberName); + } + public override string Substring(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("SUBSTR({0},1 + {1},{2})", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + public override string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var type = (DateType)Enum.Parse(typeof(DateType), parameter2.MemberValue.ObjToString(), false); + switch (type) + { + case DateType.Year: + return string.Format("(CAST(TO_CHAR({0},'yyyy') AS NUMBER))", parameter.MemberName); + case DateType.Month: + return string.Format("(CAST(TO_CHAR({0},'mm') AS NUMBER))", parameter.MemberName); + case DateType.Hour: + return string.Format("(CAST(TO_CHAR({0},'hh24') AS NUMBER))", parameter.MemberName); + case DateType.Second: + return string.Format("(CAST(TO_CHAR({0},'ss') AS NUMBER))", parameter.MemberName); + case DateType.Minute: + return string.Format("(CAST(TO_CHAR({0},'mi') AS NUMBER))", parameter.MemberName); + case DateType.Millisecond: + return string.Format("(CAST(TO_CHAR({0},'ff3') AS NUMBER))", parameter.MemberName); + case DateType.Day: + default: + return string.Format("(CAST(TO_CHAR({0},'dd') AS NUMBER))", parameter.MemberName); + } + } + public override string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + var type = (DateType)Enum.Parse(typeof(DateType), parameter3.MemberValue.ObjToString(), false); + double time = 1; + switch (type) + { + case DateType.Year: + time = 1 * 365; + break; + case DateType.Month: + time = 1 *30; + break; + case DateType.Day: + break; + case DateType.Hour: + time = 1 / 24.0; + break; + case DateType.Second: + time = 1 / 24.0/60.0/60.0; + break; + case DateType.Minute: + time = 1 / 24.0/60.0; + break; + case DateType.Millisecond: + time = 1 / 24.0 / 60.0 / 60.0/1000; + break; + } + return string.Format("({0}+({1}*{2})) ", parameter.MemberName, time,parameter2.MemberName); + } + + public override string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format("({0}+(1*{1})) ", parameter.MemberName, parameter2.MemberName); + } + + public override string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS VARCHAR2(4000))", parameter.MemberName); + } + + public override string ToDate(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" to_date({0},'yyyy-mm-dd hh24:mi:ss')", parameter.MemberName); + } + public override string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'||{1}||'%') ", parameter.MemberName, parameter2.MemberName); + } + public override string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like {1}||'%') ", parameter.MemberName, parameter2.MemberName); + } + public override string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'||{1}) ", parameter.MemberName, parameter2.MemberName); + } + public override string Trim(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" trim({0}) ", parameter.MemberName); + } + public override string DateIsSameDay(MethodCallExpressionModel model) + { + throw new NotSupportedException("Oracle NotSupportedException DateIsSameDay"); + } + public override string DateIsSameByType(MethodCallExpressionModel model) + { + throw new NotSupportedException("Oracle NotSupportedException DateIsSameDay"); + } + public override string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" LENGTH({0}) ", parameter.MemberName); + } + + public override string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("NVL({0},{1})", parameter.MemberName, parameter1.MemberName); + } + + public override string MergeString(params string[] strings) + { + return string.Join("||", strings).Replace("+", ""); + } + + public override string GetDate() + { + return "sysdate"; + } + + public override string GetRandom() + { + return "dbms_random.value"; + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleInsertBuilder.cs b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleInsertBuilder.cs new file mode 100644 index 0000000..892f40d --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleInsertBuilder.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleInsertBuilder : InsertBuilder + { + public override string SqlTemplate + { + get + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) "; + + } + } + public override string SqlTemplateBatch + { + get + { + return "INSERT INTO {0} ({1})"; + } + } + public override string ToSqlString() + { + var identities = this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).ToList(); + if (IsNoInsertNull) + { + DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList(); + } + var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList(); + var isSingle = groupList.Count() == 1; + string columnsString = string.Join(",", groupList.First().Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + if (isSingle) + { + string columnParametersString = string.Join(",", this.DbColumnInfoList.Select(it => Builder.SqlParameterKeyWord + it.DbColumnName)); + if (identities.HasValue()) + { + columnsString = columnsString.TrimEnd(',') + "," + string.Join(",", identities.Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + columnParametersString = columnParametersString.TrimEnd(',') + "," + string.Join(",", identities.Select(it => it.OracleSequenceName + ".nextval")); + } + return string.Format(SqlTemplate, GetTableNameString, columnsString, columnParametersString); + } + else + { + StringBuilder batchInsetrSql = new StringBuilder(); + int pageSize = 200; + int pageIndex = 1; + int totalRecord = groupList.Count; + int pageCount = (totalRecord + pageSize - 1) / pageSize; + if (identities.HasValue()) + { + columnsString = columnsString.TrimEnd(',') + "," + string.Join(",", identities.Select(it => Builder.GetTranslationColumnName(it.DbColumnName))); + } + while (pageCount >= pageIndex) + { + batchInsetrSql.AppendFormat(SqlTemplateBatch, GetTableNameString, columnsString); + int i = 0; + foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()) + { + var isFirst = i == 0; + if (!isFirst) + { + batchInsetrSql.Append(SqlTemplateBatchUnion); + } + var insertColumns = string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value), Builder.GetTranslationColumnName(it.DbColumnName)))); + if (identities.HasValue()) + { + insertColumns = insertColumns.TrimEnd(',') + "," + string.Join(",", identities.Select(it => + { + var seqValue = this.OracleSeqInfoList[it.OracleSequenceName]; + this.OracleSeqInfoList[it.OracleSequenceName] = this.OracleSeqInfoList[it.OracleSequenceName] + 1; + return seqValue + 1+" AS "+it.DbColumnName; + })); + } + batchInsetrSql.Append("\r\n SELECT " + insertColumns + " FROM DUAL "); + ++i; + } + pageIndex++; + batchInsetrSql.Append("\r\n;\r\n"); + } + return "BEGIN\r\n"+ batchInsetrSql.ToString()+"\r\nEND;"; + } + } + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "to_date('"+ date.ToString("yyyy-MM-dd HH:mm:ss") + "', 'YYYY-MM-DD HH24:MI:SS') "; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "N'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "N'" + value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleQueryBuilder.cs b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleQueryBuilder.cs new file mode 100644 index 0000000..b81f025 --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleQueryBuilder.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleQueryBuilder : QueryBuilder + { + public override bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS ""\w+\.\w+"""); + } + public override string SqlTemplate + { + get + { + return "SELECT {0}{"+UtilConstants.ReplaceKey+"} FROM {1}{2}{3}{4}"; + } + } + public override string ToSqlString() + { + string oldOrderBy = this.OrderByValue; + string externalOrderBy = oldOrderBy; + var isIgnoreOrderBy = this.IsCount && this.PartitionByValue.IsNullOrEmpty(); + AppendFilter(); + sql = new StringBuilder(); + if (this.OrderByValue == null && (Skip != null || Take != null)) this.OrderByValue = " ORDER BY "+ this.Builder.SqlDateNow + " "; + if (this.PartitionByValue.HasValue()) + { + this.OrderByValue = this.PartitionByValue + this.OrderByValue; + } + var isRowNumber = Skip != null || Take != null; + var rowNumberString = string.Format(",ROW_NUMBER() OVER({0}) AS RowIndex ", GetOrderByString); + string groupByValue = GetGroupByString + HavingInfos; + string orderByValue = (!isRowNumber && this.OrderByValue.HasValue()) ? GetOrderByString : null; + if (isIgnoreOrderBy) { orderByValue = null; } + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, groupByValue, orderByValue); + sql.Replace(UtilConstants.ReplaceKey, isRowNumber ? (isIgnoreOrderBy ? null : rowNumberString) : null); + if (isIgnoreOrderBy) { this.OrderByValue = oldOrderBy; return sql.ToString(); } + var result = ToPageSql(sql.ToString(), this.Take, this.Skip); + if (ExternalPageIndex > 0) + { + if (externalOrderBy.IsNullOrEmpty()) + { + externalOrderBy = " ORDER BY "+ this.Builder.SqlDateNow + " "; + } + result = string.Format("SELECT *,ROW_NUMBER() OVER({0}) AS RowIndex2 FROM ({1}) ExternalTable ", GetExternalOrderBy(externalOrderBy), result); + result = ToPageSql2(result, ExternalPageIndex, ExternalPageSize, true); + } + this.OrderByValue = oldOrderBy; + return result; + } + public override string ToPageSql(string sql, int? take, int? skip, bool isExternal = false) + { + string temp = isExternal ? ExternalPageTempalte : PageTempalte; + if (skip != null && take == null) + { + return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, long.MaxValue); + } + else if (skip == null && take != null) + { + return string.Format(temp, sql.ToString(), 1, take.ObjToInt()); + } + else if (skip != null && take != null) + { + return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, skip.ObjToInt() + take.ObjToInt()); + } + else + { + return sql.ToString(); + } + } + + public override string ToPageSql2(string sql, int? pageIndex, int? pageSize, bool isExternal = false) + { + string temp = isExternal ? ExternalPageTempalte : PageTempalte; + return string.Format(temp, sql.ToString(), (pageIndex - 1) * pageSize + 1, pageIndex * pageSize); + } + + } +} diff --git a/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleUpdateBuilder.cs b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleUpdateBuilder.cs new file mode 100644 index 0000000..6023222 --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/SqlBuilder/OracleUpdateBuilder.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class OracleUpdateBuilder : UpdateBuilder + { + protected override string TomultipleSqlString(List> groupList) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("Begin"); + sb.AppendLine(string.Join("\r\n", groupList.Select(t => + { + var updateTable = string.Format("UPDATE {0} SET", base.GetTableNameStringNoWith); + var setValues = string.Join(",", t.Where(s => !s.IsPrimarykey).Select(m => GetOracleUpdateColums(m)).ToArray()); + var pkList = t.Where(s => s.IsPrimarykey).ToList(); + List whereList = new List(); + foreach (var item in pkList) + { + var isFirst = pkList.First() == item; + var whereString = isFirst ? " " : " AND "; + whereString += GetOracleUpdateColums(item); + whereList.Add(whereString); + } + return string.Format("{0} {1} WHERE {2};", updateTable, setValues, string.Join("",whereList)); + }).ToArray())); + sb.AppendLine("End;"); + return sb.ToString(); + } + + private string GetOracleUpdateColums(DbColumnInfo m) + { + return string.Format("\"{0}\"={1}", m.DbColumnName.ToUpper(), FormatValue(m.Value)); + } + + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "to_date('" + date.ToString("yyyy-MM-dd HH:mm:ss") + "', 'YYYY-MM-DD HH24:MI:SS') "; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", ""); + return bytesString; + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "N'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "N'" + value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/Realization/Oracle/Updateable/OracleUpdateable.cs b/类库/SqlSugar/Realization/Oracle/Updateable/OracleUpdateable.cs new file mode 100644 index 0000000..c8a985a --- /dev/null +++ b/类库/SqlSugar/Realization/Oracle/Updateable/OracleUpdateable.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class OracleUpdateable : UpdateableProvider where T : class, new() + { + protected override List GetIdentityKeys() + { + return this.EntityInfo.Columns.Where(it => it.OracleSequenceName.HasValue()).Select(it => it.DbColumnName).ToList(); + } + public override int ExecuteCommand() + { + if (base.UpdateObjs.Count() == 1) + { + return base.ExecuteCommand(); + } + else + { + base.ExecuteCommand(); + return base.UpdateObjs.Count(); + } + } + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/CodeFirst/SqlServerCodeFirst.cs b/类库/SqlSugar/Realization/SqlServer/CodeFirst/SqlServerCodeFirst.cs new file mode 100644 index 0000000..814ef1b --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/CodeFirst/SqlServerCodeFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlServerCodeFirst:CodeFirstProvider + { + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/DbBind/SqlServerDbBind.cs b/类库/SqlSugar/Realization/SqlServer/DbBind/SqlServerDbBind.cs new file mode 100644 index 0000000..60716cf --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/DbBind/SqlServerDbBind.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class SqlServerDbBind : DbBindProvider + { + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null&& extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>() + { + new KeyValuePair("int",CSharpDataType.@int), + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("nvarchar",CSharpDataType.@string), + new KeyValuePair("sql_variant",CSharpDataType.@string), + new KeyValuePair("text",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("ntext",CSharpDataType.@string), + new KeyValuePair("nchar",CSharpDataType.@string), + new KeyValuePair("hierarchyid",CSharpDataType.@string), + new KeyValuePair("bigint",CSharpDataType.@long), + new KeyValuePair("bit",CSharpDataType.@bool), + new KeyValuePair("datetime",CSharpDataType.DateTime), + new KeyValuePair("time",CSharpDataType.DateTime), + new KeyValuePair("smalldatetime",CSharpDataType.DateTime), + new KeyValuePair("timestamp",CSharpDataType.byteArray), + new KeyValuePair("datetime2",CSharpDataType.DateTime), + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("single",CSharpDataType.@decimal), + new KeyValuePair("money",CSharpDataType.@decimal), + new KeyValuePair("numeric",CSharpDataType.@decimal), + new KeyValuePair("smallmoney",CSharpDataType.@decimal), + new KeyValuePair("float",CSharpDataType.@double), + new KeyValuePair("float",CSharpDataType.Single), + new KeyValuePair("real",CSharpDataType.@float), + new KeyValuePair("smallint",CSharpDataType.@short), + new KeyValuePair("tinyint",CSharpDataType.@byte), + new KeyValuePair("uniqueidentifier",CSharpDataType.Guid), + new KeyValuePair("binary",CSharpDataType.byteArray), + new KeyValuePair("image",CSharpDataType.byteArray), + new KeyValuePair("varbinary",CSharpDataType.byteArray), + new KeyValuePair("datetimeoffset", CSharpDataType.DateTimeOffset), + new KeyValuePair("datetimeoffset", CSharpDataType.DateTime)}; + }; + +} diff --git a/类库/SqlSugar/Realization/SqlServer/DbFirst/SqlServerDbFirst.cs b/类库/SqlSugar/Realization/SqlServer/DbFirst/SqlServerDbFirst.cs new file mode 100644 index 0000000..dd86e4d --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/DbFirst/SqlServerDbFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlServerDbFirst : DbFirstProvider + { + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/DbMaintenance/SqlServerDbMaintenance.cs b/类库/SqlSugar/Realization/SqlServer/DbMaintenance/SqlServerDbMaintenance.cs new file mode 100644 index 0000000..e51a343 --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/DbMaintenance/SqlServerDbMaintenance.cs @@ -0,0 +1,310 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqlServerDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetColumnInfosByTableNameSql + { + get + { + string sql = @"SELECT sysobjects.name AS TableName, + syscolumns.Id AS TableId, + syscolumns.name AS DbColumnName, + systypes.name AS DataType, + syscolumns.length AS [Length], + sys.extended_properties.[value] AS [ColumnDescription], + syscomments.text AS DefaultValue, + syscolumns.isnullable AS IsNullable, + columnproperty(syscolumns.id,syscolumns.name,'IsIdentity')as IsIdentity, + (CASE + WHEN EXISTS + ( + select 1 + from sysindexes i + join sysindexkeys k on i.id = k.id and i.indid = k.indid + join sysobjects o on i.id = o.id + join syscolumns c on i.id=c.id and k.colid = c.colid + where o.xtype = 'U' + and exists(select 1 from sysobjects where xtype = 'PK' and name = i.name) + and o.name=sysobjects.name and c.name=syscolumns.name + ) THEN 1 + ELSE 0 + END) AS IsPrimaryKey + FROM syscolumns + INNER JOIN systypes ON syscolumns.xtype = systypes.xtype + LEFT JOIN sysobjects ON syscolumns.id = sysobjects.id + LEFT OUTER JOIN sys.extended_properties ON (sys.extended_properties.minor_id = syscolumns.colid + AND sys.extended_properties.major_id = syscolumns.id) + LEFT OUTER JOIN syscomments ON syscolumns.cdefault = syscomments.id + WHERE syscolumns.id IN + (SELECT id + FROM sysobjects + WHERE xtype IN('u', + 'v') ) + AND (systypes.name <> 'sysname') + AND sysobjects.name='{0}' + AND systypes.name<>'geometry' + AND systypes.name<>'geography' + ORDER BY syscolumns.colid"; + return sql; + } + } + protected override string GetTableInfoListSql + { + get + { + return @"SELECT s.Name,Convert(varchar(max),tbp.value) as Description + FROM sysobjects s + LEFT JOIN sys.extended_properties as tbp ON s.id=tbp.major_id and tbp.minor_id=0 AND (tbp.Name='MS_Description' OR tbp.Name is null) WHERE s.xtype IN('U') "; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"SELECT s.Name,Convert(varchar(max),tbp.value) as Description + FROM sysobjects s + LEFT JOIN sys.extended_properties as tbp ON s.id=tbp.major_id and tbp.minor_id=0 AND (tbp.Name='MS_Description' OR tbp.Name is null) WHERE s.xtype IN('V') "; + } + } + #endregion + + #region DDL + protected override string AddPrimaryKeySql + { + get + { + return "ALTER TABLE {0} ADD CONSTRAINT {1} PRIMARY KEY({2})"; + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD {1} {2}{3} {4} {5} {6}"; + } + } + protected override string AlterColumnToTableSql + { + get + { + return "ALTER TABLE {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}"; + } + } + protected override string BackupDataBaseSql + { + get + { + return @"USE master;BACKUP DATABASE {0} TO disk = '{1}'"; + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1})"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "TRUNCATE TABLE {0}"; + } + } + protected override string BackupTableSql + { + get + { + return "SELECT TOP {0} * INTO {1} FROM {2}"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + return "ALTER TABLE {0} DROP COLUMN {1}"; + } + } + protected override string DropConstraintSql + { + get + { + return "ALTER TABLE {0} DROP CONSTRAINT {1}"; + } + } + protected override string RenameColumnSql + { + get + { + return "exec sp_rename '{0}.{1}','{2}','column';"; + } + } + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select top 1 id from sysobjects"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return "NULL"; + } + } + protected override string CreateTableNotNull + { + get + { + return "NOT NULL"; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return "IDENTITY(1,1)"; + } + } + + protected override string AddColumnRemarkSql + { + get + { + return "EXECUTE sp_addextendedproperty N'MS_Description', '{2}', N'user', N'dbo', N'table', N'{1}', N'column', N'{0}'"; ; + } + } + + protected override string DeleteColumnRemarkSql + { + get + { + return "EXEC sp_dropextendedproperty 'MS_Description','user',dbo,'table','{1}','column',{0}"; + } + + } + + protected override string IsAnyColumnRemarkSql + { + get + { + return @"SELECT" + + " A.name AS table_name," + + " B.name AS column_name," + + " C.value AS column_description" + + " FROM sys.tables A" + + " LEFT JOIN sys.extended_properties C ON C.major_id = A.object_id" + + " LEFT JOIN sys.columns B ON B.object_id = A.object_id AND C.minor_id = B.column_id" + + " INNER JOIN sys.schemas SC ON SC.schema_id = A.schema_id AND SC.name = 'dbo'" + + " WHERE A.name = '{1}' and b.name = '{0}'"; + + } + } + + protected override string AddTableRemarkSql + { + get + { + return "EXECUTE sp_addextendedproperty N'MS_Description', '{1}', N'user', N'dbo', N'table', N'{0}', NULL, NULL"; + } + } + + protected override string DeleteTableRemarkSql + { + get + { + return "EXEC sp_dropextendedproperty 'MS_Description','user',dbo,'table','{0}' "; + } + + } + + protected override string IsAnyTableRemarkSql + { + get + { + return @"SELECT C.class_desc + FROM sys.tables A + LEFT JOIN sys.extended_properties C ON C.major_id = A.object_id + INNER JOIN sys.schemas SC ON SC.schema_id=A.schema_id AND SC.name='dbo' + WHERE A.name = '{0}' AND minor_id=0"; + } + + } + + protected override string RenameTableSql + { + get + { + return "EXEC sp_rename '{0}','{1}'"; + } + } + #endregion + + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + string sql = GetCreateTableSql(tableName, columns); + this.Context.Ado.ExecuteCommand(sql); + if (isCreatePrimaryKey) + { + var pkColumns = columns.Where(it => it.IsPrimarykey).ToList(); + if (pkColumns.Count > 1) + { + this.Context.DbMaintenance.AddPrimaryKeys(tableName, pkColumns.Select(it=>it.DbColumnName).ToArray()); + } + else + { + foreach (var item in pkColumns) + { + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + } + } + return true; + } + + public override bool RenameColumn(string tableName, string oldColumnName, string newColumnName) + { + tableName = this.SqlBuilder.GetTranslationTableName(tableName); + oldColumnName = this.SqlBuilder.GetTranslationColumnName(oldColumnName); + newColumnName = this.SqlBuilder.GetNoTranslationColumnName(newColumnName); + string sql = string.Format(this.RenameColumnSql, tableName, oldColumnName, newColumnName); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/Queryable/SqlServerQueryable.cs b/类库/SqlSugar/Realization/SqlServer/Queryable/SqlServerQueryable.cs new file mode 100644 index 0000000..ae13f69 --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/Queryable/SqlServerQueryable.cs @@ -0,0 +1,58 @@ +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public class SqlServerQueryable:QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } + public class SqlServerQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerBuilder.cs b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerBuilder.cs new file mode 100644 index 0000000..51fbbf4 --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerBuilder.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerBuilder : SqlBuilderProvider + { + public override string SqlTranslationLeft { get { return "["; } } + public override string SqlTranslationRight { get { return "]"; } } + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerDeleteBuilder.cs b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerDeleteBuilder.cs new file mode 100644 index 0000000..516e451 --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerDeleteBuilder.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerDeleteBuilder: DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerExpressionContext.cs b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerExpressionContext.cs new file mode 100644 index 0000000..9742ba8 --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerExpressionContext.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public partial class SqlServerExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarClient Context { get; set; } + public SqlServerExpressionContext() + { + base.DbMehtods = new SqlServerMethod(); + } + + } + public partial class SqlServerMethod : DefaultDbMethod, IDbMethods + { + + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerInsertBuilder.cs b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerInsertBuilder.cs new file mode 100644 index 0000000..ecab5d4 --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerInsertBuilder.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerInsertBuilder:InsertBuilder + { + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerQueryBuilder.cs b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerQueryBuilder.cs new file mode 100644 index 0000000..d463d7e --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerQueryBuilder.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerQueryBuilder: QueryBuilder + { + public override string SqlTemplate + { + get + { + return "SELECT {0}{"+UtilConstants.ReplaceKey+"} FROM {1}{2}{3}{4}"; + } + } + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerUpdateBuilder.cs b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerUpdateBuilder.cs new file mode 100644 index 0000000..75a86c4 --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/SqlBuilder/SqlServerUpdateBuilder.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class SqlServerUpdateBuilder: UpdateBuilder + { + } +} diff --git a/类库/SqlSugar/Realization/SqlServer/SqlServerProvider.cs b/类库/SqlSugar/Realization/SqlServer/SqlServerProvider.cs new file mode 100644 index 0000000..d45877a --- /dev/null +++ b/类库/SqlSugar/Realization/SqlServer/SqlServerProvider.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public class SqlServerProvider : AdoProvider + { + public SqlServerProvider() { } + public override IDbConnection Connection + { + get + { + if (base._DbConnection == null) + { + try + { + base._DbConnection = new SqlConnection(base.Context.CurrentConnectionConfig.ConnectionString); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + /// + /// Only SqlServer + /// + /// + public override void BeginTran(string transactionName) + { + CheckConnection(); + base.Transaction = ((SqlConnection)this.Connection).BeginTransaction(transactionName); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + CheckConnection(); + base.Transaction = ((SqlConnection)this.Connection).BeginTransaction(iso, transactionName); + } + public override IDataAdapter GetAdapter() + { + return new SqlDataAdapter(); + } + public override IDbCommand GetCommand(string sql, SugarParameter[] parameters) + { + SqlCommand sqlCommand = new SqlCommand(sql, (SqlConnection)this.Connection); + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (SqlTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + IDataParameter[] ipars = ToIDbDataParameter(parameters); + sqlCommand.Parameters.AddRange((SqlParameter[])ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, IDbCommand command) + { + ((SqlDataAdapter)dataAdapter).SelectCommand = (SqlCommand)command; + } + /// + /// if mysql return MySqlParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + SqlParameter[] result = new SqlParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + var sqlParameter = new SqlParameter(); + sqlParameter.ParameterName = parameter.ParameterName; + sqlParameter.UdtTypeName = parameter.UdtTypeName; + sqlParameter.Size = parameter.Size; + sqlParameter.Value = parameter.Value; + sqlParameter.DbType = parameter.DbType; + sqlParameter.Direction = parameter.Direction; + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue)) + { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/CodeFirst/SqliteCodeFirst.cs b/类库/SqlSugar/Realization/Sqlite/CodeFirst/SqliteCodeFirst.cs new file mode 100644 index 0000000..57a1c3e --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/CodeFirst/SqliteCodeFirst.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqliteCodeFirst : CodeFirstProvider + { + public override void ExistLogic(EntityInfo entityInfo) + { + if (entityInfo.Columns.HasValue()) + { + Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + + var tableName = GetTableName(entityInfo); + var dbColumns = this.Context.DbMaintenance.GetColumnInfosByTableName(tableName); + ConvertColumns(dbColumns); + var entityColumns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToList(); + var dropColumns = dbColumns + .Where(dc => !entityColumns.Any(ec => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(dc => !entityColumns.Any(ec => dc.DbColumnName.Equals(ec.DbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToList(); + var addColumns = entityColumns + .Where(ec => ec.OldDbColumnName.IsNullOrEmpty() || !dbColumns.Any(dc => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .Where(ec => !dbColumns.Any(dc => ec.DbColumnName.Equals(dc.DbColumnName, StringComparison.CurrentCultureIgnoreCase))).ToList(); + //var alterColumns = entityColumns + // .Where(ec => !dbColumns.Any(dc => dc.DbColumnName.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase))) + // .Where(ec => + // dbColumns.Any(dc => dc.DbColumnName.Equals(ec.DbColumnName) + // && ((!UtilMethods.GetUnderType(ec.PropertyInfo).IsEnum() && UtilMethods.GetUnderType(ec.PropertyInfo).IsIn(UtilConstants.StringType)) || + + // IsSamgeType(ec, dc)))).ToList(); + var renameColumns = entityColumns + .Where(it => !string.IsNullOrEmpty(it.OldDbColumnName)) + .Where(entityColumn => dbColumns.Any(dbColumn => entityColumn.OldDbColumnName.Equals(dbColumn.DbColumnName, StringComparison.CurrentCultureIgnoreCase))) + .ToList(); + + + var isChange = false; + foreach (var item in addColumns) + { + this.Context.DbMaintenance.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + isChange = true; + } + foreach (var item in dropColumns) + { + //this.Context.DbMaintenance.DropColumn(tableName, item.DbColumnName); + //isChange = true; + } + //foreach (var item in alterColumns) + //{ + // //this.Context.DbMaintenance.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + // //isChange = true; + //} + foreach (var item in renameColumns) + { + throw new NotSupportedException("rename Column"); + } + + foreach (var item in entityColumns) + { + var dbColumn = dbColumns.FirstOrDefault(dc => dc.DbColumnName.Equals(item.DbColumnName, StringComparison.CurrentCultureIgnoreCase)); + if (dbColumn == null) continue; + bool pkDiff, idEntityDiff; + KeyAction(item, dbColumn, out pkDiff, out idEntityDiff); + if (dbColumn != null && pkDiff && !idEntityDiff) + { + var isAdd = item.IsPrimarykey; + if (isAdd) + { + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + else + { + this.Context.DbMaintenance.DropConstraint(tableName, string.Format("PK_{0}_{1}", tableName, item.DbColumnName)); + } + } + else if (pkDiff || idEntityDiff) + { + ChangeKey(entityInfo, tableName, item); + } + } + if (isChange && base.IsBackupTable) + { + this.Context.DbMaintenance.BackupTable(tableName, tableName + DateTime.Now.ToString("yyyyMMddHHmmss"), MaxBackupDataRows); + } + } + } + public override void NoExistLogic(EntityInfo entityInfo) + { + var tableName = GetTableName(entityInfo); + string backupName=tableName+DateTime.Now.ToString("yyyyMMddHHmmss"); + Check.Exception(entityInfo.Columns.Where(it => it.IsPrimarykey).Count() > 1, "Use Code First ,The primary key must not exceed 1"); + List columns = new List(); + if (entityInfo.Columns.HasValue()) + { + foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimarykey ? 0 : 1).Where(it=>it.IsIgnore==false)) + { + DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item); + columns.Add(dbColumnInfo); + } + } + this.Context.DbMaintenance.CreateTable(tableName, columns,true); + } + protected override DbColumnInfo EntityColumnToDbColumn(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + var propertyType = UtilMethods.GetUnderType(item.PropertyInfo); + var result = new DbColumnInfo() + { + TableId = entityInfo.Columns.IndexOf(item), + DbColumnName = item.DbColumnName.HasValue() ? item.DbColumnName : item.PropertyName, + IsPrimarykey = item.IsPrimarykey, + IsIdentity = item.IsIdentity, + TableName = tableName, + IsNullable = item.IsNullable, + DefaultValue = item.DefaultValue, + ColumnDescription = item.ColumnDescription, + Length = item.Length + }; + GetDbType(item, propertyType, result); + if (result.DataType.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.Length == 0) + { + result.Length = 1; + } + return result; + } + + protected override void ConvertColumns(List dbColumns) + { + foreach (var item in dbColumns) + { + if (item.DataType == "DateTime") + { + item.Length = 0; + } + } + } + + protected override void ChangeKey(EntityInfo entityInfo, string tableName, EntityColumnInfo item) + { + this.Context.DbMaintenance.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item)); + if (!item.IsPrimarykey) + this.Context.DbMaintenance.DropConstraint(tableName,null); + if (item.IsPrimarykey) + this.Context.DbMaintenance.AddPrimaryKey(tableName, item.DbColumnName); + } + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/DbBind/SqliteDbBind.cs b/类库/SqlSugar/Realization/Sqlite/DbBind/SqliteDbBind.cs new file mode 100644 index 0000000..031db86 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/DbBind/SqliteDbBind.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SqlSugar +{ + public class SqliteDbBind : DbBindProvider + { + public override string GetDbTypeName(string csharpTypeName) + { + if (csharpTypeName == UtilConstants.ByteArrayType.Name) + { + return "blob"; + } + if (csharpTypeName == "Int32") + csharpTypeName = "int"; + if (csharpTypeName == "Int16") + csharpTypeName = "short"; + if (csharpTypeName == "Int64") + csharpTypeName = "long"; + if (csharpTypeName == "Boolean") + csharpTypeName = "bool"; + var mappings = this.MappingTypes.Where(it => it.Value.ToString().Equals(csharpTypeName, StringComparison.CurrentCultureIgnoreCase)); + return mappings.HasValue() ? mappings.First().Key : "varchar"; + } + public override List> MappingTypes + { + get + { + var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; + if (extService != null && extService.AppendDataReaderTypeMappings.HasValue()) + { + return extService.AppendDataReaderTypeMappings.Union(MappingTypesConst).ToList(); + } + else + { + return MappingTypesConst; + } + } + } + public static List> MappingTypesConst = new List>() + { + + new KeyValuePair("integer",CSharpDataType.@int), + new KeyValuePair("int",CSharpDataType.@int), + new KeyValuePair("int32",CSharpDataType.@int), + new KeyValuePair("integer32",CSharpDataType.@int), + new KeyValuePair("number",CSharpDataType.@int), + + new KeyValuePair("varchar",CSharpDataType.@string), + new KeyValuePair("varchar2",CSharpDataType.@string), + new KeyValuePair("nvarchar",CSharpDataType.@string), + new KeyValuePair("nvarchar2",CSharpDataType.@string), + new KeyValuePair("text",CSharpDataType.@string), + new KeyValuePair("ntext",CSharpDataType.@string), + new KeyValuePair("blob_text",CSharpDataType.@string), + new KeyValuePair("char",CSharpDataType.@string), + new KeyValuePair("nchar",CSharpDataType.@string), + new KeyValuePair("num",CSharpDataType.@string), + new KeyValuePair("currency",CSharpDataType.@string), + new KeyValuePair("datetext",CSharpDataType.@string), + new KeyValuePair("word",CSharpDataType.@string), + new KeyValuePair("graphic",CSharpDataType.@string), + + new KeyValuePair("tinyint",CSharpDataType.@byte), + new KeyValuePair("unsignedinteger8",CSharpDataType.@byte), + new KeyValuePair("smallint",CSharpDataType.@short), + new KeyValuePair("int16",CSharpDataType.@short), + new KeyValuePair("bigint",CSharpDataType.@long), + new KeyValuePair("int64",CSharpDataType.@long), + new KeyValuePair("long",CSharpDataType.@long), + new KeyValuePair("integer64",CSharpDataType.@long), + new KeyValuePair("bit",CSharpDataType.@bool), + new KeyValuePair("bool",CSharpDataType.@bool), + new KeyValuePair("boolean",CSharpDataType.@bool), + new KeyValuePair("real",CSharpDataType.@double), + new KeyValuePair("double",CSharpDataType.@double), + new KeyValuePair("float",CSharpDataType.@float), + new KeyValuePair("float",CSharpDataType.Single), + new KeyValuePair("decimal",CSharpDataType.@decimal), + new KeyValuePair("dec",CSharpDataType.@decimal), + new KeyValuePair("numeric",CSharpDataType.@decimal), + new KeyValuePair("money",CSharpDataType.@decimal), + new KeyValuePair("smallmoney",CSharpDataType.@decimal), + + new KeyValuePair("datetime",CSharpDataType.DateTime), + new KeyValuePair("timestamp",CSharpDataType.DateTime), + new KeyValuePair("date",CSharpDataType.DateTime), + new KeyValuePair("time",CSharpDataType.DateTime), + + new KeyValuePair("blob",CSharpDataType.byteArray), + new KeyValuePair("clob",CSharpDataType.byteArray), + new KeyValuePair("raw",CSharpDataType.byteArray), + new KeyValuePair("oleobject",CSharpDataType.byteArray), + new KeyValuePair("binary",CSharpDataType.byteArray), + new KeyValuePair("photo",CSharpDataType.byteArray), + new KeyValuePair("picture",CSharpDataType.byteArray), + + new KeyValuePair("varchar",CSharpDataType.Guid), + new KeyValuePair("guid",CSharpDataType.Guid) + }; + public override List StringThrow + { + get + { + return new List() { "int32", "datetime", "decimal", "double", "byte"}; + } + } + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/DbFirst/SqliteDbFirst.cs b/类库/SqlSugar/Realization/Sqlite/DbFirst/SqliteDbFirst.cs new file mode 100644 index 0000000..cb378dc --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/DbFirst/SqliteDbFirst.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqliteDbFirst : DbFirstProvider + { + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/DbMaintenance/SqliteDbMaintenance.cs b/类库/SqlSugar/Realization/Sqlite/DbMaintenance/SqliteDbMaintenance.cs new file mode 100644 index 0000000..47e5a00 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/DbMaintenance/SqliteDbMaintenance.cs @@ -0,0 +1,351 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SQLite; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqliteDbMaintenance : DbMaintenanceProvider + { + #region DML + protected override string GetColumnInfosByTableNameSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string GetTableInfoListSql + { + get + { + return @"select Name from sqlite_master where type='table' and name<>'sqlite_sequence' order by name;"; + } + } + protected override string GetViewInfoListSql + { + get + { + return @"select Name from sqlite_master where type='view' order by name;"; + } + } + #endregion + + #region DDL + protected override string AddPrimaryKeySql + { + get + { + throw new NotSupportedException(); + } + } + protected override string AddColumnToTableSql + { + get + { + return "ALTER TABLE {0} ADD COLUMN {1} {2}{3}"; + } + } + protected override string AlterColumnToTableSql + { + get + { + // return "ALTER TABLE {0} ALTER COLUMN {1} {2}{3} {4} {5} {6}"; + throw new NotSupportedException(); + } + } + protected override string BackupDataBaseSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string CreateTableSql + { + get + { + return "CREATE TABLE {0}(\r\n{1} )"; + } + } + protected override string CreateTableColumn + { + get + { + return "{0} {1}{2} {3} {4} {5}"; + } + } + protected override string TruncateTableSql + { + get + { + return "DELETE FROM {0}"; + } + } + protected override string BackupTableSql + { + get + { + return " CREATE TABLE {0} AS SELECT * FROM {1} limit 0,{2}"; + } + } + protected override string DropTableSql + { + get + { + return "DROP TABLE {0}"; + } + } + protected override string DropColumnToTableSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string DropConstraintSql + { + get + { + throw new NotSupportedException(); + } + } + protected override string RenameColumnSql + { + get + { + throw new NotSupportedException(); + } + } + #endregion + + #region Check + protected override string CheckSystemTablePermissionsSql + { + get + { + return "select Name from sqlite_master limit 0,1"; + } + } + #endregion + + #region Scattered + protected override string CreateTableNull + { + get + { + return "NULL"; + } + } + protected override string CreateTableNotNull + { + get + { + return "NOT NULL"; + } + } + protected override string CreateTablePirmaryKey + { + get + { + return "PRIMARY KEY"; + } + } + protected override string CreateTableIdentity + { + get + { + return "AUTOINCREMENT"; + } + } + + protected override string AddColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string DeleteColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string IsAnyColumnRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string AddTableRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string DeleteTableRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string IsAnyTableRemarkSql + { + get + { + throw new NotSupportedException(); + } + } + + protected override string RenameTableSql + { + get + { + throw new NotSupportedException(); + } + } + #endregion + + #region Methods + + public override List GetColumnInfosByTableName(string tableName, bool isCache = true) + { + string cacheKey = "DbMaintenanceProvider.GetColumnInfosByTableName." + this.SqlBuilder.GetNoTranslationColumnName(tableName).ToLower(); + cacheKey = GetCacheKey(cacheKey); + if (!isCache) + { + return GetColumnInfosByTableName(tableName); + } + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + return GetColumnsByTableName(tableName); + + }); + } + public override bool AddRemark(EntityInfo entity) + { + return true; + } + private List GetColumnsByTableName(string tableName) + { + string sql = "select * from " + tableName + " limit 0,1"; + var oldIsEnableLog = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + using (DbDataReader reader = (SQLiteDataReader)this.Context.Ado.GetDataReader(sql)) + { + this.Context.Ado.IsEnableLogEvent = oldIsEnableLog; + List result = new List(); + var schemaTable = reader.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + { + DbColumnInfo column = new DbColumnInfo() + { + TableName = tableName, + DataType = row["DataTypeName"].ToString().Trim(), + IsNullable = (bool)row["AllowDBNull"], + IsIdentity = (bool)row["IsAutoIncrement"], + ColumnDescription = null, + DbColumnName = row["ColumnName"].ToString(), + DefaultValue = row["defaultValue"].ToString(), + IsPrimarykey = (bool)row["IsKey"], + Length = Convert.ToInt32(row["ColumnSize"]) + }; + result.Add(column); + } + return result; + } + } + public override bool BackupTable(string oldTableName, string newTableName, int maxBackupDataRows = int.MaxValue) + { + oldTableName = this.SqlBuilder.GetTranslationTableName(oldTableName); + newTableName = this.SqlBuilder.GetTranslationTableName(newTableName); + string sql = string.Format(this.BackupTableSql, newTableName, oldTableName, maxBackupDataRows); + this.Context.Ado.ExecuteCommand(sql); + return true; + } + public override bool CreateTable(string tableName, List columns, bool isCreatePrimaryKey = true) + { + if (columns.HasValue()) + { + foreach (var item in columns) + { + if (item.DbColumnName.Equals("GUID", StringComparison.CurrentCultureIgnoreCase)) + { + item.Length = 20; + } + if (item.IsIdentity && !item.IsPrimarykey) + { + item.IsPrimarykey = true; + Check.Exception(item.DataType == "integer", "Identity only integer type"); + } + } + } + string sql = GetCreateTableSql(tableName, columns); + if (!isCreatePrimaryKey) + { + sql = sql.Replace("PRIMARY KEY AUTOINCREMENT", "").Replace("PRIMARY KEY", ""); + } + this.Context.Ado.ExecuteCommand(sql); + return true; + } + protected override string GetCreateTableSql(string tableName, List columns) + { + List columnArray = new List(); + Check.Exception(columns.IsNullOrEmpty(), "No columns found "); + foreach (var item in columns) + { + string columnName = item.DbColumnName; + string dataType = item.DataType; + if (dataType == "varchar" && item.Length == 0) + { + item.Length = 1; + } + string dataSize = item.Length > 0 ? string.Format("({0})", item.Length) : null; + string nullType = item.IsNullable ? this.CreateTableNull : CreateTableNotNull; + string primaryKey = item.IsPrimarykey ? this.CreateTablePirmaryKey : null; + string identity = item.IsIdentity ? this.CreateTableIdentity : null; + string addItem = string.Format(this.CreateTableColumn, this.SqlBuilder.GetTranslationColumnName(columnName), dataType, dataSize, nullType, primaryKey, identity); + columnArray.Add(addItem); + } + string tableString = string.Format(this.CreateTableSql, this.SqlBuilder.GetTranslationTableName(tableName), string.Join(",\r\n", columnArray)); + tableString = tableString.Replace("`", "\""); + return tableString; + } + public override bool IsAnyConstraint(string constraintName) + { + throw new NotSupportedException("MySql IsAnyConstraint NotSupportedException"); + } + public override bool BackupDataBase(string databaseName, string fullFileName) + { + Check.ThrowNotSupportedException("MySql BackupDataBase NotSupported"); + return false; + } + private List GetListOrCache(string cacheKey, string sql) + { + return this.Context.Utilities.GetReflectionInoCacheInstance().GetOrCreate(cacheKey, + () => + { + var isEnableLogEvent = this.Context.Ado.IsEnableLogEvent; + this.Context.Ado.IsEnableLogEvent = false; + var reval = this.Context.Ado.SqlQuery(sql); + this.Context.Ado.IsEnableLogEvent = isEnableLogEvent; + return reval; + }); + } + #endregion + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/Queryable/SqliteQueryable.cs b/类库/SqlSugar/Realization/Sqlite/Queryable/SqliteQueryable.cs new file mode 100644 index 0000000..9411159 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/Queryable/SqliteQueryable.cs @@ -0,0 +1,60 @@ +namespace SqlSugar +{ + public class SqliteQueryable:QueryableProvider + { + public override ISugarQueryable With(string withString) + { + return this; + } + + public override ISugarQueryable PartitionBy(string groupFileds) + { + this.GroupBy(groupFileds); + return this; + } + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } + public class SqliteQueryable : QueryableProvider + { + + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteBuilder.cs b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteBuilder.cs new file mode 100644 index 0000000..4e085ec --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteBuilder.cs @@ -0,0 +1,26 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class SqliteBuilder : SqlBuilderProvider + { + public override string SqlTranslationLeft { get { return "`"; } } + public override string SqlTranslationRight { get { return "`"; } } + public override string SqlDateNow + { + get + { + return "DATETIME('now') "; + } + } + public override string FullSqlDateNow + { + get + { + return "select DATETIME('now') "; + } + } + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteDeleteBuilder.cs b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteDeleteBuilder.cs new file mode 100644 index 0000000..9c70f83 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteDeleteBuilder.cs @@ -0,0 +1,7 @@ +namespace SqlSugar +{ + public class SqliteDeleteBuilder : DeleteBuilder + { + + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteExpressionContext.cs b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteExpressionContext.cs new file mode 100644 index 0000000..fbd7ac0 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteExpressionContext.cs @@ -0,0 +1,225 @@ +using System; +using System.Linq; +namespace SqlSugar +{ + public class SqliteExpressionContext : ExpressionContext, ILambdaExpressions + { + public SqlSugarClient Context { get; set; } + public SqliteExpressionContext() + { + base.DbMehtods = new SqliteMethod(); + } + public override string SqlTranslationLeft { get { return "`"; } } + public override string SqlTranslationRight { get { return "`"; } } + } + public class SqliteMethod : DefaultDbMethod, IDbMethods + { + public override string Length(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format("LENGTH({0})", parameter.MemberName); + } + + public override string Substring(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + var parameter3 = model.Args[2]; + return string.Format("SUBSTR({0},1 + {1},{2})", parameter.MemberName, parameter2.MemberName, parameter3.MemberName); + } + + public override string Contains(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'||{1}||'%') ", parameter.MemberName, parameter2.MemberName); + } + + public override string StartsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like {1}||'%') ", parameter.MemberName, parameter2.MemberName); + } + + public override string EndsWith(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + return string.Format(" ({0} like '%'||{1}) ", parameter.MemberName, parameter2.MemberName); + } + + public override string ToInt32(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS INTEGER)", parameter.MemberName); + } + + public override string ToInt64(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS INTEGER)", parameter.MemberName); + } + + public override string ToString(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS TEXT)", parameter.MemberName); + } + + public override string ToGuid(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS TEXT)", parameter.MemberName); + } + + public override string ToDouble(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string ToBool(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS SIGNED)", parameter.MemberName); + } + + public override string ToDecimal(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" CAST({0} AS DECIMAL(18,4))", parameter.MemberName); + } + + public override string ToDate(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + return string.Format(" DATETIME({0})", parameter.MemberName); + } + + public override string DateAddDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter2 = model.Args[1]; + if (parameter2.MemberValue.ObjToInt() < 0) + { + return string.Format(" DATE(DATETIME({0}), '-{1} days')", parameter.MemberName, Math.Abs(parameter2.MemberValue.ObjToInt())); + } + else + { + return string.Format(" DATE(DATETIME({0}), '+{1} days')", parameter.MemberName, parameter2.MemberValue); + } + } + + public override string DateAddByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0].MemberName; + var parameter2 = model.Args[1].MemberValue; + var parameter3 = model.Args[2].MemberValue; + if (parameter2.ObjToInt() < 0) + { + return string.Format(" DATETIME(DATETIME({0}), '+{1} {2}s')", parameter, Math.Abs(parameter2.ObjToInt()), parameter3); + } + else + { + return string.Format(" DATETIME(DATETIME({0}), '+{1} {2}s')", parameter, parameter2, parameter3); + } + } + + public override string DateValue(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var typeName = model.Args[1].MemberValue.ToString(); + var parameter2 = typeName; + var type = (DateType)Enum.Parse(typeof(DateType), parameter2, false); + switch (type) + { + case DateType.Year: + parameter2 = "%Y"; + break; + case DateType.Month: + parameter2 = "%m"; + break; + case DateType.Day: + parameter2 = "%d"; + break; + case DateType.Hour: + parameter2 = "%H"; + break; + case DateType.Second: + parameter2 = "%S"; + break; + case DateType.Minute: + parameter2 = "%M"; + break; + case DateType.Millisecond: + default: + Check.ThrowNotSupportedException(typeName); + break; + } + return string.Format(" CAST(STRFTIME('{1}', DATETIME(DATETIME({0}), 'LOCALTIME')) AS INTEGER)", parameter.MemberName, parameter2); + } + + public override string DateIsSameDay(MethodCallExpressionModel model) + { + var parameter = model.Args[0].MemberName; + var parameter2 = model.Args[1].MemberName; + int time = 1; + return string.Format(" Cast((JulianDay({0}) - JulianDay({1})) *{2} As INTEGER)=0 ", parameter, parameter2, time); + } + public override string DateIsSameByType(MethodCallExpressionModel model) + { + var parameter = model.Args[0].MemberName; + var parameter2 = model.Args[1].MemberName; + var parameter3 = model.Args[2].MemberValue; + var type = (DateType)Enum.Parse(typeof(DateType), parameter3.ObjToString(), false); + int time = 1; + switch (type) + { + case DateType.Year: + time = time * 1 / 365; + break; + case DateType.Month: + time = time * 1 / 30; + break; + case DateType.Day: + break; + case DateType.Hour: + time = time * 24; + break; + case DateType.Second: + time = time * 24 * 60 * 60; + break; + case DateType.Minute: + time = time * 24 * 60; + break; + case DateType.Millisecond: + time = time * 24 * 60 * 60 * 1000; + break; + } + return string.Format(" Cast((JulianDay({0}) - JulianDay({1})) *{2} As INTEGER)", parameter, parameter2, time); + } + + public override string MergeString(params string[] strings) + { + return string.Join("||", strings).Replace("+",""); + } + + public override string IsNull(MethodCallExpressionModel model) + { + var parameter = model.Args[0]; + var parameter1 = model.Args[1]; + return string.Format("IFNULL({0},{1})", parameter.MemberName, parameter1.MemberName); + } + + public override string GetDate() + { + return "DATETIME('now')"; + } + + public override string GetRandom() + { + return "RANDOM()"; + } + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteInsertBuilder.cs b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteInsertBuilder.cs new file mode 100644 index 0000000..e5babf1 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteInsertBuilder.cs @@ -0,0 +1,79 @@ +using System; + +namespace SqlSugar +{ + public class SqliteInsertBuilder : InsertBuilder + { + public override string SqlTemplate + { + get + { + if (IsReturnIdentity) + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;SELECT LAST_INSERT_ROWID();"; + } + else + { + return @"INSERT INTO {0} + ({1}) + VALUES + ({2}) ;"; + + } + } + } + + public override string SqlTemplateBatch + { + get + { + return "INSERT INTO {0} ({1})"; + } + } + + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value); + return bytesString; + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "'"+value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteQueryBuilder.cs b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteQueryBuilder.cs new file mode 100644 index 0000000..dc31cd5 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteQueryBuilder.cs @@ -0,0 +1,97 @@ +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public partial class SqliteQueryBuilder : QueryBuilder + { + #region Sql Template + public override string PageTempalte + { + get + { + /* + SELECT * FROM TABLE WHERE CONDITION ORDER BY ID DESC LIMIT 0,10 + */ + var template = "SELECT {0} FROM {1} {2} {3} {4} LIMIT {5},{6}"; + return template; + } + } + public override string DefaultOrderByTemplate + { + get + { + return "ORDER BY DATETIME('now') "; + } + } + + #endregion + + #region Common Methods + public override bool IsComplexModel(string sql) + { + return Regex.IsMatch(sql, @"AS \`\w+\.\w+\`"); + } + public override string ToSqlString() + { + base.AppendFilter(); + string result = null; + string oldOrderBy = this.OrderByValue; + sql = new StringBuilder(); + sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString); + if (IsCount) { return sql.ToString(); } + if (Skip != null && Take == null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result= string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, (Skip != null || Take != null) ? null : GetOrderByString, Skip.ObjToInt(), long.MaxValue); + } + else if (Skip == null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result= string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, 0, Take.ObjToInt()); + } + else if (Skip != null && Take != null) + { + if (this.OrderByValue == "ORDER BY ") this.OrderByValue += GetSelectValue.Split(',')[0]; + result= string.Format(PageTempalte, GetSelectValue, GetTableNameString, GetWhereValueString, GetGroupByString + HavingInfos, GetOrderByString, Skip.ObjToInt() > 0 ? Skip.ObjToInt(): 0, Take); + } + else + { + result= sql.ToString(); + } + this.OrderByValue = oldOrderBy; + return result; + } + + #endregion + + #region Get SQL Partial + public override string GetSelectValue + { + get + { + string reval = string.Empty; + if (this.SelectValue == null || this.SelectValue is string) + { + reval = GetSelectValueByString(); + } + else + { + reval = GetSelectValueByExpression(); + } + if (this.SelectType == ResolveExpressType.SelectMultiple) + { + this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this.JoinQueryInfos.Select(it => it.TableName)); + } + if (IsDistinct) + { + reval = " DISTINCT " + reval; + } + return reval; + } + } + + #endregion + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteUpdateBuilder.cs b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteUpdateBuilder.cs new file mode 100644 index 0000000..34582a0 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/SqlBuilder/SqliteUpdateBuilder.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class SqliteUpdateBuilder : UpdateBuilder + { + protected override string TomultipleSqlString(List> groupList) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(string.Join("\r\n", groupList.Select(t => + { + var updateTable = string.Format("UPDATE {0} SET", base.GetTableNameStringNoWith); + var setValues = string.Join(",", t.Where(s => !s.IsPrimarykey).Select(m => GetOracleUpdateColums(m)).ToArray()); + var pkList = t.Where(s => s.IsPrimarykey).ToList(); + List whereList = new List(); + foreach (var item in pkList) + { + var isFirst = pkList.First() == item; + var whereString = isFirst ? " " : " AND "; + whereString += GetOracleUpdateColums(item); + whereList.Add(whereString); + } + return string.Format("{0} {1} WHERE {2};", updateTable, setValues, string.Join("AND", whereList)); + }).ToArray())); + return sb.ToString(); + } + + private string GetOracleUpdateColums(DbColumnInfo m) + { + return string.Format("\"{0}\"={1}", m.DbColumnName.ToUpper(), FormatValue(m.Value)); + } + public override object FormatValue(object value) + { + if (value == null) + { + return "NULL"; + } + else + { + var type = UtilMethods.GetUnderType(value.GetType()); + if (type == UtilConstants.DateType) + { + var date = value.ObjToDate(); + if (date < Convert.ToDateTime("1900-1-1")) + { + date = Convert.ToDateTime("1900-1-1"); + } + return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'"; + } + else if (type.IsEnum()) + { + return Convert.ToInt64(value); + } + else if (type == UtilConstants.ByteArrayType) + { + string bytesString = "0x" + BitConverter.ToString((byte[])value); + return bytesString; + } + else if (type == UtilConstants.BoolType) + { + return value.ObjToBool() ? "1" : "0"; + } + else if (type == UtilConstants.StringType || type == UtilConstants.ObjType) + { + return "'" + value.ToString().ToSqlFilter() + "'"; + } + else + { + return "'" + value.ToString() + "'"; + } + } + } + } +} diff --git a/类库/SqlSugar/Realization/Sqlite/SqliteProvider.cs b/类库/SqlSugar/Realization/Sqlite/SqliteProvider.cs new file mode 100644 index 0000000..d14b086 --- /dev/null +++ b/类库/SqlSugar/Realization/Sqlite/SqliteProvider.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Data.SQLite; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + public partial class SqliteProvider : AdoProvider + { + public SqliteProvider() { } + public override IDbConnection Connection + { + get + { + if (base._DbConnection == null) + { + try + { + var SQLiteConnectionString = base.Context.CurrentConnectionConfig.ConnectionString; + base._DbConnection = new SQLiteConnection(SQLiteConnectionString); + } + catch (Exception ex) + { + Check.Exception(true, ErrorMessage.ConnnectionOpen, ex.Message); + } + } + return base._DbConnection; + } + set + { + base._DbConnection = value; + } + } + + public override void BeginTran(string transactionName) + { + base.BeginTran(); + } + /// + /// Only SqlServer + /// + /// + /// + public override void BeginTran(IsolationLevel iso, string transactionName) + { + base.BeginTran(iso); + } + public override IDataAdapter GetAdapter() + { + return new SQLiteDataAdapter(); + } + public override IDbCommand GetCommand(string sql, SugarParameter[] parameters) + { + SQLiteCommand sqlCommand = new SQLiteCommand(sql, (SQLiteConnection)this.Connection); + sqlCommand.CommandType = this.CommandType; + sqlCommand.CommandTimeout = this.CommandTimeOut; + if (this.Transaction != null) + { + sqlCommand.Transaction = (SQLiteTransaction)this.Transaction; + } + if (parameters.HasValue()) + { + IDataParameter[] ipars = ToIDbDataParameter(parameters); + sqlCommand.Parameters.AddRange((SQLiteParameter[])ipars); + } + CheckConnection(); + return sqlCommand; + } + public override void SetCommandToAdapter(IDataAdapter dataAdapter, IDbCommand command) + { + ((SQLiteDataAdapter)dataAdapter).SelectCommand = (SQLiteCommand)command; + } + /// + /// if SQLite return SQLiteParameter[] pars + /// if sqlerver return SqlParameter[] pars ... + /// + /// + /// + public override IDataParameter[] ToIDbDataParameter(params SugarParameter[] parameters) + { + if (parameters == null || parameters.Length == 0) return null; + SQLiteParameter[] result = new SQLiteParameter[parameters.Length]; + int index = 0; + foreach (var parameter in parameters) + { + if (parameter.Value == null) parameter.Value = DBNull.Value; + if (parameter.Value.GetType() == UtilConstants.GuidType) + { + parameter.Value = parameter.Value.ToString(); + } + var sqlParameter = new SQLiteParameter(); + sqlParameter.ParameterName = parameter.ParameterName; + sqlParameter.Size = parameter.Size; + sqlParameter.Value = parameter.Value; + sqlParameter.DbType = parameter.DbType; + result[index] = sqlParameter; + if (sqlParameter.Direction.IsIn(ParameterDirection.Output, ParameterDirection.InputOutput,ParameterDirection.ReturnValue)) { + if (this.OutputParameters == null) this.OutputParameters = new List(); + this.OutputParameters.RemoveAll(it => it.ParameterName == sqlParameter.ParameterName); + this.OutputParameters.Add(sqlParameter); + } + if (sqlParameter.DbType == System.Data.DbType.Guid) { + sqlParameter.DbType = System.Data.DbType.String; + sqlParameter.Value = sqlParameter.Value.ObjToString(); + } + + ++index; + } + return result; + } + } +} diff --git a/类库/SqlSugar/References/MySql.Data.dll b/类库/SqlSugar/References/MySql.Data.dll new file mode 100644 index 0000000..80bf09b Binary files /dev/null and b/类库/SqlSugar/References/MySql.Data.dll differ diff --git a/类库/SqlSugar/References/Newtonsoft.Json.dll b/类库/SqlSugar/References/Newtonsoft.Json.dll new file mode 100644 index 0000000..20dae62 Binary files /dev/null and b/类库/SqlSugar/References/Newtonsoft.Json.dll differ diff --git a/类库/SqlSugar/References/Oracle.ManagedDataAccess.dll b/类库/SqlSugar/References/Oracle.ManagedDataAccess.dll new file mode 100644 index 0000000..473ca83 Binary files /dev/null and b/类库/SqlSugar/References/Oracle.ManagedDataAccess.dll differ diff --git a/类库/SqlSugar/References/SQLite.Interop.dll b/类库/SqlSugar/References/SQLite.Interop.dll new file mode 100644 index 0000000..1838fba Binary files /dev/null and b/类库/SqlSugar/References/SQLite.Interop.dll differ diff --git a/类库/SqlSugar/References/System.Data.SQLite.dll b/类库/SqlSugar/References/System.Data.SQLite.dll new file mode 100644 index 0000000..1ee930f Binary files /dev/null and b/类库/SqlSugar/References/System.Data.SQLite.dll differ diff --git a/类库/SqlSugar/SimpleClient.cs b/类库/SqlSugar/SimpleClient.cs new file mode 100644 index 0000000..899ccf5 --- /dev/null +++ b/类库/SqlSugar/SimpleClient.cs @@ -0,0 +1,270 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace SqlSugar +{ + public partial class SimpleClient + { + protected SqlSugarClient Context { get; set; } + public SqlSugarClient FullClient { get { return this.Context; } } + + private SimpleClient() + { + + } + public SimpleClient(SqlSugarClient context) + { + this.Context = context; + } + + public T GetById(dynamic id) where T : class, new() + { + return Context.Queryable().InSingle(id); + } + public List GetList() where T : class, new() + { + return Context.Queryable().ToList(); + } + public T GetSingle(Expression> whereExpression) where T : class, new() + { + return Context.Queryable().Single(whereExpression); + } + public List GetList(Expression> whereExpression) where T : class, new() + { + return Context.Queryable().Where(whereExpression).ToList(); + } + public List GetPageList(Expression> whereExpression, PageModel page) where T : class, new() + { + int count = 0; + var result = Context.Queryable().Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(Expression> whereExpression, PageModel page, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc) where T : class, new() + { + int count = 0; + var result = Context.Queryable().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(List conditionalList, PageModel page) where T : class, new() + { + int count = 0; + var result = Context.Queryable().Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(List conditionalList, PageModel page, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc) where T : class, new() + { + int count = 0; + var result = Context.Queryable().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public bool IsAny(Expression> whereExpression) where T : class, new() + { + return Context.Queryable().Where(whereExpression).Any(); + } + public bool Insert(T insertObj) where T : class, new() + { + return this.Context.Insertable(insertObj).ExecuteCommand() > 0; + } + public int InsertReturnIdentity(T insertObj) where T : class, new() + { + return this.Context.Insertable(insertObj).ExecuteReturnIdentity(); + } + public bool InsertRange(T[] insertObjs) where T : class, new() + { + return this.Context.Insertable(insertObjs).ExecuteCommand() > 0; + } + public bool InsertRange(List insertObjs) where T : class, new() + { + return this.Context.Insertable(insertObjs).ExecuteCommand() > 0; + } + public bool Update(T updateObj) where T : class, new() + { + return this.Context.Updateable(updateObj).ExecuteCommand() > 0; + } + public bool UpdateRange(T[] updateObjs) where T : class, new() + { + return this.Context.Updateable(updateObjs).ExecuteCommand() > 0; + } + public bool UpdateRange(List updateObjs) where T : class, new() + { + return this.Context.Updateable(updateObjs).ExecuteCommand() > 0; + } + public bool Update(Expression> columns, Expression> whereExpression) where T : class, new() + { + return this.Context.Updateable().UpdateColumns(columns).Where(whereExpression).ExecuteCommand() > 0; + } + public bool Delete(T deleteObj) where T : class, new() + { + return this.Context.Deleteable().Where(deleteObj).ExecuteCommand() > 0; + } + public bool Delete(Expression> whereExpression) where T : class, new() + { + return this.Context.Deleteable().Where(whereExpression).ExecuteCommand() > 0; + } + public bool DeleteById(dynamic id) where T : class, new() + { + return this.Context.Deleteable().In(id).ExecuteCommand() > 0; + } + public bool DeleteByIds(dynamic[] ids) where T : class, new() + { + return this.Context.Deleteable().In(ids).ExecuteCommand() > 0; + } + } + public partial class SimpleClient where T : class, new() + { + protected SqlSugarClient Context { get; set; } + public SqlSugarClient FullClient { get { return this.Context; } } + + private SimpleClient() + { + + } + public SimpleClient(SqlSugarClient context) + { + this.Context = context; + } + + public ISugarQueryable AsQueryable() + { + return Context.Queryable(); + } + public IInsertable AsInsertable(T insertObj) + { + return Context.Insertable(insertObj); + } + public IInsertable AsInsertable(T[] insertObjs) + { + return Context.Insertable(insertObjs); + } + public IInsertable AsInsertable(List insertObjs) + { + return Context.Insertable(insertObjs); + } + public IUpdateable AsUpdateable(T updateObj) + { + return Context.Updateable(updateObj); + } + public IUpdateable AsUpdateable(T[] updateObjs) + { + return Context.Updateable(updateObjs); + } + public IUpdateable AsUpdateable(List updateObjs) + { + return Context.Updateable(updateObjs); + } + public IDeleteable AsDeleteable() + { + return Context.Deleteable(); + } + + public T GetById(dynamic id) + { + return Context.Queryable().InSingle(id); + } + public List GetList() + { + return Context.Queryable().ToList(); + } + public List GetList(Expression> whereExpression) + { + return Context.Queryable().Where(whereExpression).ToList(); + } + public T GetSingle(Expression> whereExpression) + { + return Context.Queryable().Single(whereExpression); + } + public List GetPageList(Expression> whereExpression, PageModel page) + { + int count = 0; + var result = Context.Queryable().Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(Expression> whereExpression, PageModel page, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc) + { + int count = 0; + var result = Context.Queryable().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(List conditionalList, PageModel page) + { + int count = 0; + var result = Context.Queryable().Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public List GetPageList(List conditionalList, PageModel page, Expression> orderByExpression = null, OrderByType orderByType = OrderByType.Asc) + { + int count = 0; + var result = Context.Queryable().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count); + page.PageCount = count; + return result; + } + public bool IsAny(Expression> whereExpression) + { + return Context.Queryable().Where(whereExpression).Any(); + } + public int Count(Expression> whereExpression) + { + + return Context.Queryable().Where(whereExpression).Count(); + } + + public bool Insert(T insertObj) + { + return this.Context.Insertable(insertObj).ExecuteCommand() > 0; + } + public int InsertReturnIdentity(T insertObj) + { + return this.Context.Insertable(insertObj).ExecuteReturnIdentity(); + } + public bool InsertRange(T[] insertObjs) + { + return this.Context.Insertable(insertObjs).ExecuteCommand() > 0; + } + public bool InsertRange(List insertObjs) + { + return this.Context.Insertable(insertObjs).ExecuteCommand() > 0; + } + public bool Update(T updateObj) + { + return this.Context.Updateable(updateObj).ExecuteCommand() > 0; + } + public bool UpdateRange(T[] updateObjs) + { + return this.Context.Updateable(updateObjs).ExecuteCommand() > 0; + } + public bool UpdateRange(List updateObjs) + { + return this.Context.Updateable(updateObjs).ExecuteCommand() > 0; + } + public bool Update(Expression> columns, Expression> whereExpression) + { + return this.Context.Updateable().UpdateColumns(columns).Where(whereExpression).ExecuteCommand() > 0; + } + public bool Delete(T deleteObj) + { + return this.Context.Deleteable().Where(deleteObj).ExecuteCommand() > 0; + } + public bool Delete(Expression> whereExpression) + { + return this.Context.Deleteable().Where(whereExpression).ExecuteCommand() > 0; + } + public bool DeleteById(dynamic id) + { + return this.Context.Deleteable().In(id).ExecuteCommand() > 0; + } + public bool DeleteByIds(dynamic[] ids) + { + return this.Context.Deleteable().In(ids).ExecuteCommand() > 0; + } + } +} diff --git a/类库/SqlSugar/SqlSugar.csproj b/类库/SqlSugar/SqlSugar.csproj new file mode 100644 index 0000000..17a7a84 --- /dev/null +++ b/类库/SqlSugar/SqlSugar.csproj @@ -0,0 +1,312 @@ + + + + + Debug + AnyCPU + {489BB790-226C-4FAD-8D1E-51D72A7FF8E5} + Library + Properties + SqlSugar + SqlSugar + v4.6.1 + 512 + + + + + + true + full + false + ..\..\Debug\ + DEBUG;TRACE + prompt + 4 + false + AnyCPU + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + ..\..\packages\MySql.Data.8.0.15\lib\net452\MySql.Data.dll + + + ..\..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll + + + False + References\Oracle.ManagedDataAccess.dll + + + + + + + + + False + ..\..\Debug\System.Data.SQLite.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + + \ No newline at end of file diff --git a/类库/SqlSugar/SqlSugar.nuspec b/类库/SqlSugar/SqlSugar.nuspec new file mode 100644 index 0000000..16a1f15 --- /dev/null +++ b/类库/SqlSugar/SqlSugar.nuspec @@ -0,0 +1,20 @@ + + + + sqlSugar + 4.9.9.3 + SqlSugar .Net Framework 4.0+ ORM + sun kaixuan + landa + https://github.com/sunkaixuan/SqlSugar + https://github.com/sunkaixuan/SqlSugar + https://secure.gravatar.com/avatar/a82c03402497b2e58fd65038a3699b30 + false + SqlSugar ORM .Net Framework 4.0+ High-performance, lightweight http://www.codeisbug.com/Doc/8 + Copyright 2017 + asp.net orm + + + + + \ No newline at end of file diff --git a/类库/SqlSugar/SqlSugarClient.cs b/类库/SqlSugar/SqlSugarClient.cs new file mode 100644 index 0000000..ba914d4 --- /dev/null +++ b/类库/SqlSugar/SqlSugarClient.cs @@ -0,0 +1,703 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Dynamic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +namespace SqlSugar +{ + /// + /// ** description:Create datathis.access object + /// ** author:sunkaixuan + /// ** date:2017/1/2 + /// ** email:610262374@qq.com + /// + public partial class SqlSugarClient : IDisposable + { + + #region Constructor + public SqlSugarClient(ConnectionConfig config) + { + this.Context = this; + this.CurrentConnectionConfig = config; + this.ContextID = Guid.NewGuid(); + Check.ArgumentNullException(config, "config is null"); + switch (config.DbType) + { + case DbType.MySql: + DependencyManagement.TryMySqlData(); + break; + case DbType.SqlServer: + break; + case DbType.Sqlite: + DependencyManagement.TrySqlite(); + break; + case DbType.Oracle: + DependencyManagement.TryOracle(); + break; + case DbType.PostgreSQL: + DependencyManagement.TryPostgreSQL(); + break; + default: + throw new Exception("ConnectionConfig.DbType is null"); + } + } + #endregion + + #region ADO Methods + /// + ///Datathis.operation + /// + public virtual IAdo Ado + { + get + { + if (this.ContextAdo == null) + { + var result = InstanceFactory.GetAdo(this.Context.CurrentConnectionConfig); + this.ContextAdo = result; + result.Context = this.Context; + return result; + } + return this.Context._Ado; + } + } + #endregion + + #region Aop Log Methods + public virtual AopProvider Aop { get { return new AopProvider(this.Context); } } + #endregion + + #region Util Methods + [Obsolete("Use SqlSugarClient.Utilities")] + public virtual IContextMethods RewritableMethods + { + get { return this.Context.Utilities; } + set { this.Context.Utilities = value; } + } + public virtual IContextMethods Utilities + { + get + { + if (ContextRewritableMethods == null) + { + ContextRewritableMethods = new ContextMethods(); + ContextRewritableMethods.Context = this.Context; + } + return ContextRewritableMethods; + } + set { ContextRewritableMethods = value; } + } + #endregion + + #region Queryable + /// + /// Get datebase time + /// + /// + public DateTime GetDate() { + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + return this.Ado.GetDateTime(sqlBuilder.FullSqlDateNow); + } + /// + /// Lambda Query operation + /// + public virtual ISugarQueryable Queryable() + { + + InitMppingInfo(); + var result = this.CreateQueryable(); + return result; + } + /// + /// Lambda Query operation + /// + public virtual ISugarQueryable Queryable(string shortName) + { + var queryable = Queryable(); + queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; + return queryable; + } + /// + /// Lambda Query operation + /// + public virtual ISugarQueryable Queryable(string tableName, string shortName) + { + var queryable = Queryable(); + queryable.SqlBuilder.QueryBuilder.EntityName = tableName; + queryable.SqlBuilder.QueryBuilder.TableShortName = shortName; + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + #region 9-12 + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateQueryJoin(joinExpression, types, queryable); + return queryable; + } + #endregion + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + + #region 9-12 + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(Expression> joinExpression) where T : class, new() + { + InitMppingInfo(); + var types = new Type[] { typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + this.CreateEasyQueryJoin(joinExpression, types, queryable); + queryable.Where(joinExpression); + return queryable; + } + public virtual ISugarQueryable Queryable(ISugarQueryable queryable) where T : class, new() + { + var sqlobj = queryable.ToSql(); + return this.SqlQueryable(sqlobj.Key).AddParameters(sqlobj.Value); + } + public virtual ISugarQueryable Queryable( + ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, Expression> joinExpression) where T : class, new() where T2 : class, new() + { + return Queryable(joinQueryable1, joinQueryable2, JoinType.Inner, joinExpression); + } + public virtual ISugarQueryable Queryable( + ISugarQueryable joinQueryable1, ISugarQueryable joinQueryable2, JoinType joinType, Expression> joinExpression) where T : class, new() where T2 : class, new() + { + Check.Exception(joinQueryable1.QueryBuilder.Take != null || joinQueryable1.QueryBuilder.Skip != null || joinQueryable1.QueryBuilder.OrderByValue.HasValue(), "joinQueryable1 Cannot have 'Skip' 'ToPageList' 'Take' Or 'OrderBy'"); + Check.Exception(joinQueryable2.QueryBuilder.Take != null || joinQueryable2.QueryBuilder.Skip != null || joinQueryable2.QueryBuilder.OrderByValue.HasValue(), "joinQueryable2 Cannot have 'Skip' 'ToPageList' 'Take' Or 'OrderBy'"); + + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + + sqlBuilder.Context = this.Context; + InitMppingInfo(); + var types = new Type[] { typeof(T2) }; + var queryable = InstanceFactory.GetQueryable(this.CurrentConnectionConfig); + queryable.Context = this.Context; + queryable.SqlBuilder = sqlBuilder; + queryable.QueryBuilder = InstanceFactory.GetQueryBuilder(this.CurrentConnectionConfig); + queryable.QueryBuilder.JoinQueryInfos = new List(); + queryable.QueryBuilder.Builder = sqlBuilder; + queryable.QueryBuilder.Context = this.Context; + queryable.QueryBuilder.EntityType = typeof(T); + queryable.QueryBuilder.LambdaExpressions = InstanceFactory.GetLambdaExpressions(this.CurrentConnectionConfig); + + //master + var shortName1 = joinExpression.Parameters[0].Name; + var sqlObj1 = joinQueryable1.ToSql(); + string sql1 = sqlObj1.Key; + UtilMethods.RepairReplicationParameters(ref sql1, sqlObj1.Value.ToArray(), 0,"Join"); + queryable.QueryBuilder.EntityName = sqlBuilder.GetPackTable(sql1, shortName1); ; + queryable.QueryBuilder.Parameters.AddRange(sqlObj1.Value); + + //join table 1 + var shortName2 = joinExpression.Parameters[1].Name; + var sqlObj2 = joinQueryable2.ToSql(); + string sql2 = sqlObj2.Key; + UtilMethods.RepairReplicationParameters(ref sql2, sqlObj2.Value.ToArray(), 1, "Join"); + queryable.QueryBuilder.Parameters.AddRange(sqlObj2.Value); + var exp = queryable.QueryBuilder.GetExpressionValue(joinExpression, ResolveExpressType.WhereMultiple); + queryable.QueryBuilder.JoinQueryInfos.Add(new JoinQueryInfo() { JoinIndex = 0, JoinType = joinType, JoinWhere = exp.GetResultString(), TableName = sqlBuilder.GetPackTable(sql2, shortName2) }); + + return queryable; + } + #endregion + + public virtual ISugarQueryable UnionAll(params ISugarQueryable[] queryables) where T : class, new() + { + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + Check.Exception(queryables.IsNullOrEmpty(), "UnionAll.queryables is null "); + int i = 1; + List>> allItems = new List>>(); + foreach (var item in queryables) + { + var sqlObj = item.ToSql(); + string sql = sqlObj.Key; + UtilMethods.RepairReplicationParameters(ref sql, sqlObj.Value.ToArray(), i, "UnionAll"); + if (sqlObj.Value.HasValue()) + allItems.Add(new KeyValuePair>(sql, sqlObj.Value)); + else + allItems.Add(new KeyValuePair>(sql, new List())); + i++; + } + var allSql = sqlBuilder.GetUnionAllSql(allItems.Select(it => it.Key).ToList()); + var allParameters = allItems.SelectMany(it => it.Value).ToArray(); + var resulut = this.Context.Queryable().AS(UtilMethods.GetPackTable(allSql, "unionTable")).With(SqlWith.Null); + resulut.AddParameters(allParameters); + return resulut.Select(sqlBuilder.SqlSelectAll); + } + public virtual ISugarQueryable UnionAll(List> queryables) where T : class, new() + { + Check.Exception(queryables.IsNullOrEmpty(), "UnionAll.queryables is null "); + return UnionAll(queryables.ToArray()); + } + public virtual ISugarQueryable Union(params ISugarQueryable[] queryables) where T : class, new() + { + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + Check.Exception(queryables.IsNullOrEmpty(), "UnionAll.queryables is null "); + int i = 1; + List>> allItems = new List>>(); + foreach (var item in queryables) + { + var sqlObj = item.ToSql(); + string sql = sqlObj.Key; + UtilMethods.RepairReplicationParameters(ref sql, sqlObj.Value.ToArray(), i, "Union"); + if (sqlObj.Value.HasValue()) + allItems.Add(new KeyValuePair>(sql, sqlObj.Value)); + else + allItems.Add(new KeyValuePair>(sql, new List())); + i++; + } + var allSql = sqlBuilder.GetUnionSql(allItems.Select(it => it.Key).ToList()); + var allParameters = allItems.SelectMany(it => it.Value).ToArray(); + var resulut = this.Context.Queryable().AS(UtilMethods.GetPackTable(allSql, "unionTable")).With(SqlWith.Null); + resulut.AddParameters(allParameters); + return resulut.Select(sqlBuilder.SqlSelectAll); + } + public virtual ISugarQueryable Union(List> queryables) where T : class, new() + { + Check.Exception(queryables.IsNullOrEmpty(), "Union.queryables is null "); + return Union(queryables.ToArray()); + } + #endregion + + #region SqlQueryable + public ISugarQueryable SqlQueryable(string sql) where T : class, new() + { + var sqlBuilder = InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig); + return this.Context.Queryable().AS(sqlBuilder.GetPackTable(sql, sqlBuilder.GetDefaultShortName())).With(SqlWith.Null).Select(sqlBuilder.GetDefaultShortName()+".*"); + } + #endregion + + #region Insertable + public virtual IInsertable Insertable(T[] insertObjs) where T : class, new() + { + InitMppingInfo(); + InsertableProvider result = this.CreateInsertable(insertObjs); + return result; + } + public virtual IInsertable Insertable(List insertObjs) where T : class, new() + { + Check.ArgumentNullException(insertObjs, "Insertable.insertObjs can't be null"); + return this.Context.Insertable(insertObjs.ToArray()); + } + public virtual IInsertable Insertable(T insertObj) where T : class, new() + { + return this.Context.Insertable(new T[] { insertObj }); + } + public virtual IInsertable Insertable(Dictionary columnDictionary) where T : class, new() + { + InitMppingInfo(); + Check.Exception(columnDictionary == null || columnDictionary.Count == 0, "Insertable.columnDictionary can't be null"); + var insertObject = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(columnDictionary)); + var columns = columnDictionary.Select(it => it.Key).ToList(); + return this.Context.Insertable(insertObject).InsertColumns(it => columns.Any(c => it.Equals(c, StringComparison.CurrentCultureIgnoreCase))); ; + } + public virtual IInsertable Insertable(dynamic insertDynamicObject) where T : class, new() + { + InitMppingInfo(); + if (insertDynamicObject is T) + { + return this.Context.Insertable((T)insertDynamicObject); + } + else + { + var columns = ((object)insertDynamicObject).GetType().GetProperties().Select(it => it.Name).ToList(); + Check.Exception(columns.IsNullOrEmpty(), "Insertable.updateDynamicObject can't be null"); + T insertObject = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(insertDynamicObject)); + return this.Context.Insertable(insertObject).InsertColumns(it => columns.Any(c => it.Equals(c, StringComparison.CurrentCultureIgnoreCase))); + } + } + #endregion + + #region Deleteable + public virtual IDeleteable Deleteable() where T : class, new() + { + InitMppingInfo(); + DeleteableProvider result = this.CreateDeleteable(); + return result; + } + public virtual IDeleteable Deleteable(Expression> expression) where T : class, new() + { + InitMppingInfo(); + return this.Context.Deleteable().Where(expression); + } + public virtual IDeleteable Deleteable(dynamic primaryKeyValue) where T : class, new() + { + InitMppingInfo(); + return this.Context.Deleteable().In(primaryKeyValue); + } + public virtual IDeleteable Deleteable(dynamic[] primaryKeyValues) where T : class, new() + { + InitMppingInfo(); + return this.Context.Deleteable().In(primaryKeyValues); + } + public virtual IDeleteable Deleteable(List pkValue) where T : class, new() + { + InitMppingInfo(); + return this.Context.Deleteable().In(pkValue); + } + public virtual IDeleteable Deleteable(T deleteObj) where T : class, new() + { + InitMppingInfo(); + return this.Context.Deleteable().Where(deleteObj); + } + public virtual IDeleteable Deleteable(List deleteObjs) where T : class, new() + { + InitMppingInfo(); + return this.Context.Deleteable().Where(deleteObjs); + } + #endregion + + #region Updateable + public virtual IUpdateable Updateable(T[] UpdateObjs) where T : class, new() + { + InitMppingInfo(); + UpdateableProvider result = this.CreateUpdateable(UpdateObjs); + return result; + } + public virtual IUpdateable Updateable(List UpdateObjs) where T : class, new() + { + Check.ArgumentNullException(UpdateObjs, "Updateable.UpdateObjs can't be null"); + return Updateable(UpdateObjs.ToArray()); + } + public virtual IUpdateable Updateable(T UpdateObj) where T : class, new() + { + return this.Context.Updateable(new T[] { UpdateObj }); + } + public virtual IUpdateable Updateable() where T : class, new() + { + var result= this.Context.Updateable(new T[] { new T() }); + result.UpdateParameterIsNull=true; + return result; + } + public virtual IUpdateable Updateable(Dictionary columnDictionary) where T : class, new() + { + InitMppingInfo(); + Check.Exception(columnDictionary == null || columnDictionary.Count == 0, "Updateable.columnDictionary can't be null"); + var updateObject = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(columnDictionary)); + var columns = columnDictionary.Select(it => it.Key).ToList(); + return this.Context.Updateable(updateObject).UpdateColumns(it => columns.Any(c => it.Equals(c, StringComparison.CurrentCultureIgnoreCase))); ; + } + public virtual IUpdateable Updateable(dynamic updateDynamicObject) where T : class, new() + { + InitMppingInfo(); + if (updateDynamicObject is T) + { + return this.Context.Updateable((T)updateDynamicObject); + } + else + { + var columns = ((object)updateDynamicObject).GetType().GetProperties().Select(it => it.Name).ToList(); + Check.Exception(columns.IsNullOrEmpty(), "Updateable.updateDynamicObject can't be null"); + T updateObject = this.Context.Utilities.DeserializeObject(this.Context.Utilities.SerializeObject(updateDynamicObject)); + return this.Context.Updateable(updateObject).UpdateColumns(it => columns.Any(c => it.Equals(c, StringComparison.CurrentCultureIgnoreCase))); ; + } + } + #endregion + + #region Saveable + public ISaveable Saveable(List saveObjects)where T:class,new() + { + return new SaveableProvider(this,saveObjects); + } + public ISaveable Saveable(T saveObject) where T : class, new() + { + return new SaveableProvider(this,saveObject); + } + #endregion + + #region DbFirst + public virtual IDbFirst DbFirst + { + get + { + IDbFirst dbFirst = InstanceFactory.GetDbFirst(this.Context.CurrentConnectionConfig); + dbFirst.Context = this.Context; + dbFirst.Init(); + return dbFirst; + } + } + #endregion + + #region CodeFirst + public virtual ICodeFirst CodeFirst + { + get + { + ICodeFirst codeFirst = InstanceFactory.GetCodeFirst(this.Context.CurrentConnectionConfig); + codeFirst.Context = this.Context; + return codeFirst; + } + } + #endregion + + #region Db Maintenance + public virtual IDbMaintenance DbMaintenance + { + get + { + if (this.Context._DbMaintenance == null) + { + IDbMaintenance maintenance = InstanceFactory.GetDbMaintenance(this.Context.CurrentConnectionConfig); + this.Context._DbMaintenance = maintenance; + maintenance.Context = this.Context; + } + return this.Context._DbMaintenance; + } + } + #endregion + + #region Entity Maintenance + [Obsolete("Use SqlSugarClient.EntityMaintenance")] + public virtual EntityMaintenance EntityProvider + { + get { return this.Context.EntityMaintenance; } + set { this.Context.EntityMaintenance = value; } + } + public virtual EntityMaintenance EntityMaintenance + { + get + { + if (this.Context._EntityProvider == null) + { + this.Context._EntityProvider = new EntityMaintenance(); + this.Context._EntityProvider.Context = this.Context; + } + return this.Context._EntityProvider; + } + set { this.Context._EntityProvider = value; } + } + #endregion + + #region Gobal Filter + public virtual QueryFilterProvider QueryFilter + { + get + { + if (this.Context._QueryFilterProvider == null) + { + this.Context._QueryFilterProvider = new QueryFilterProvider(); + this.Context._QueryFilterProvider.Context = this.Context; + } + return this.Context._QueryFilterProvider; + } + set { this.Context._QueryFilterProvider = value; } + } + #endregion + + #region SimpleClient + [Obsolete("Use SqlSugarClient.GetSimpleClient() Or SqlSugarClient.GetSimpleClient() ")] + public virtual SimpleClient SimpleClient + { + get + { + if (this.Context._SimpleClient == null) + this.Context._SimpleClient = new SimpleClient(this.Context); + return this.Context._SimpleClient; + } + } + public virtual SimpleClient GetSimpleClient() where T : class, new() + { + return new SimpleClient(this.Context); + } + public virtual SimpleClient GetSimpleClient() + { + if (this.Context._SimpleClient == null) + this.Context._SimpleClient = new SimpleClient(this.Context); + return this.Context._SimpleClient; + } + #endregion + + #region Dispose OR Close + public virtual void Close() + { + if (this.Context.Ado != null) + this.Context.Ado.Close(); + //Context.Utilities.RemoveCacheAll(); + //if (this.Context != null && this.Context.Utilities != null) + // this.Context.Utilities.RemoveCacheAll(); + } + public virtual void Open() + { + if (this.Context.Ado != null) + this.Context.Ado.Open(); + } + public virtual void Dispose() + { + if (this.Context.Ado != null) + this.Context.Ado.Dispose(); + } + #endregion + } +} diff --git a/类库/SqlSugar/Utilities/CallContext.cs b/类库/SqlSugar/Utilities/CallContext.cs new file mode 100644 index 0000000..5e9cd32 --- /dev/null +++ b/类库/SqlSugar/Utilities/CallContext.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading; + +namespace SqlSugar +{ + internal class CallContext + { + public static ThreadLocal> ContextList = new ThreadLocal>(); + } +} diff --git a/类库/SqlSugar/Utilities/Check.cs b/类库/SqlSugar/Utilities/Check.cs new file mode 100644 index 0000000..6aab959 --- /dev/null +++ b/类库/SqlSugar/Utilities/Check.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public class Check + { + public static void ThrowNotSupportedException(string message) + { + message = message.IsNullOrEmpty() ? new NotSupportedException().Message : message; + throw new SqlSugarException("SqlSugarException.NotSupportedException:" + message); + } + + public static void ArgumentNullException(object checkObj, string message) + { + if (checkObj == null) + throw new SqlSugarException("SqlSugarException.ArgumentNullException:" + message); + } + + public static void ArgumentNullException(object [] checkObj, string message) + { + if (checkObj == null|| checkObj.Length==0) + throw new SqlSugarException("SqlSugarException.ArgumentNullException:" + message); + } + + public static void Exception(bool isException, string message, params string[] args) + { + if (isException) + throw new SqlSugarException(string.Format(message, args)); + } + } +} diff --git a/类库/SqlSugar/Utilities/DbExtensions.cs b/类库/SqlSugar/Utilities/DbExtensions.cs new file mode 100644 index 0000000..d6ad91b --- /dev/null +++ b/类库/SqlSugar/Utilities/DbExtensions.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +namespace SqlSugar +{ + public static class DbExtensions + { + public static string ToJoinSqlInVals(this T[] array) + { + if (array == null || array.Length == 0) + { + return ToSqlValue(string.Empty); + } + else + { + return string.Join(",", array.Where(c => c != null).Select(it => (it + "").ToSqlValue())); + } + } + + public static string ToSqlValue(this string value) + { + return string.Format("'{0}'", value.ToSqlFilter()); + } + + /// + ///Sql Filter + /// + /// + /// + public static string ToSqlFilter(this string value) + { + if (!value.IsNullOrEmpty()) + { + value = value.Replace("'", "''"); + } + return value; + } + } +} diff --git a/类库/SqlSugar/Utilities/ErrorMessage.cs b/类库/SqlSugar/Utilities/ErrorMessage.cs new file mode 100644 index 0000000..41c710b --- /dev/null +++ b/类库/SqlSugar/Utilities/ErrorMessage.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + internal static partial class ErrorMessage + { + internal static string ObjNotExist + { + get + { + return GetThrowMessage("{0} does not exist.", + "{0}不存在。"); + } + } + internal static string EntityMappingError + { + get + { + return GetThrowMessage("Entity mapping error.{0}", + "实体与表映射出错。{0}"); + } + } + + public static string NotSupportedDictionary + { + get + { + return GetThrowMessage("This type of Dictionary is not supported for the time being. You can try Dictionary, or contact the author!!", + "暂时不支持该类型的Dictionary 你可以试试 Dictionary或者联系作者!!"); + } + } + + public static string NotSupportedArray + { + get + { + return GetThrowMessage("This type of Array is not supported for the time being. You can try object[] or contact the author!!", + "暂时不支持该类型的Array 你可以试试 object[] 或者联系作者!!"); + } + } + + internal static string GetThrowMessage(string enMessage, string cnMessage, params string[] args) + { + List formatArgs = new List() { enMessage, cnMessage }; + formatArgs.AddRange(args); + return string.Format(@"English Message : {0} +Chinese Message : {1}", formatArgs.ToArray()); + } + } +} diff --git a/类库/SqlSugar/Utilities/FileHelper.cs b/类库/SqlSugar/Utilities/FileHelper.cs new file mode 100644 index 0000000..ac786a7 --- /dev/null +++ b/类库/SqlSugar/Utilities/FileHelper.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + internal class FileHelper + { + public static void CreateFile(string filePath, string text, Encoding encoding) + { + try + { + if (IsExistFile(filePath)) + { + DeleteFile(filePath); + } + if (!IsExistFile(filePath)) + { + string directoryPath = GetDirectoryFromFilePath(filePath); + CreateDirectory(directoryPath); + + //Create File + FileInfo file = new FileInfo(filePath); + using (FileStream stream = file.Create()) + { + using (StreamWriter writer = new StreamWriter(stream, encoding)) + { + writer.Write(text); + writer.Flush(); + } + } + } + } + catch(Exception ex) + { + throw ex; + } + } + public static bool IsExistDirectory(string directoryPath) + { + return Directory.Exists(directoryPath); + } + public static void CreateDirectory(string directoryPath) + { + if (!IsExistDirectory(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + } + } + public static void DeleteFile(string filePath) + { + if (IsExistFile(filePath)) + { + File.Delete(filePath); + } + } + public static string GetDirectoryFromFilePath(string filePath) + { + FileInfo file = new FileInfo(filePath); + DirectoryInfo directory = file.Directory; + return directory.FullName; + } + public static bool IsExistFile(string filePath) + { + return File.Exists(filePath); + } + } +} diff --git a/类库/SqlSugar/Utilities/ReflectionExtensions.cs b/类库/SqlSugar/Utilities/ReflectionExtensions.cs new file mode 100644 index 0000000..4530c4b --- /dev/null +++ b/类库/SqlSugar/Utilities/ReflectionExtensions.cs @@ -0,0 +1,313 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; + +namespace SqlSugar +{ + + public static class ReflectionExtensions + { + /// + /// 检查输入值是否为空 + /// + /// + /// + static bool isNullOrEmpty(object val) + { + if (val == null) return true; + if (val.ToString() == "") return true; + return false; + } + /// Delegate to set an arbitrary property at runtime. + /// the object instance whose property will be modified. + /// + public delegate void FastPropertySetHandler(object target, object parameter); + /// + /// 用于存放SetPropertySetter的Dictionary + /// + private static Dictionary dictSetter = new Dictionary(); + + /// + /// 快速设置成员属性 + /// + /// + /// + public static FastPropertySetHandler GetPropertySetter(PropertyInfo propInfo) + { + lock (dictSetter) + { + if (dictSetter.ContainsKey(propInfo)) return dictSetter[propInfo]; + + // generates a dynamic method to generate a FastPropertySetHandler delegate + DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, null, new Type[] { typeof(object), typeof(object) }, propInfo.DeclaringType.Module); + + ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); + + // loads the object into the stack + ilGenerator.Emit(OpCodes.Ldarg_0); + + // loads the parameter from the stack + ilGenerator.Emit(OpCodes.Ldarg_1); + + // cast to the proper type (unboxing if needed) + EmitCastToReference(ilGenerator, propInfo.PropertyType); + + // calls the setter + ilGenerator.EmitCall(OpCodes.Callvirt, propInfo.GetSetMethod(), null); + + // terminates the call + ilGenerator.Emit(OpCodes.Ret); + + // converts the DynamicMethod to a FastPropertyGetHandler delegate to get the property + FastPropertySetHandler setter = (FastPropertySetHandler)dynamicMethod.CreateDelegate(typeof(FastPropertySetHandler)); + + dictSetter.Add(propInfo, setter); + + return setter; + } + } + + /// Emits the cast to a reference, unboxing if needed. + /// The MSIL generator. + /// The type to cast. + private static void EmitCastToReference(ILGenerator ilGenerator, System.Type type) + { + if (type.IsValueType) + { + ilGenerator.Emit(OpCodes.Unbox_Any, type); + } + else + { + ilGenerator.Emit(OpCodes.Castclass, type); + } + } + + /// + /// 根据数据类型将指定数据进行相应转换 + /// + /// + /// + /// + public static object ConvertForType(object value, Type type) + { + if (Convert.IsDBNull(value) || (value == null)) + { + return null; + } + + string typeName = type.FullName.ToString(); + + if (type == typeof(System.Nullable)) + { + value = Convert.ToUInt16(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToUInt32(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToUInt64(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToInt32(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToInt64(value); + } + else if (type == typeof(System.Nullable)) + { + value = Convert.ToDateTime(value); + } + + switch (typeName) + { + case "System.String": + if (!isNullOrEmpty(value)) + value = value.ToString(); + else + value = string.Empty; + break; + case "System.Boolean": + if (!isNullOrEmpty(value)) + value = Convert.ToBoolean(value); + break; + case "System.Int16": + if (!isNullOrEmpty(value)) + value = Convert.ToInt16(value); + break; + case "System.Int32": + if (!isNullOrEmpty(value)) + value = Convert.ToInt32(value); + else + value = 0; + break; + case "System.Int64": + if (!isNullOrEmpty(value)) + value = Convert.ToInt64(value); + else + value = 0; + break; + case "System.Double": + if (!isNullOrEmpty(value)) + value = Convert.ToDouble(value); + else + value = 0.00; + break; + case "System.Float": + if (!isNullOrEmpty(value)) + value = Convert.ToDouble(value); + else + value = 0.00; + break; + case "System.Single": + if (!isNullOrEmpty(value)) + value = Convert.ToSingle(value); + + break; + case "System.Decimal": + if (!isNullOrEmpty(value)) + value = Convert.ToDecimal(value); + else + value = 0.00; + break; + case "System.DateTime": + if (!isNullOrEmpty(value)) + value = Convert.ToDateTime(value); + else + value = DateTime.MinValue; + break; + } + + return value; + } + /// + /// 设置属性值 + /// + /// + /// + /// + public static void SetPropertyValue(object obj, PropertyInfo property, object value) + { + if (property.CanWrite) + { + var propertySetter = GetPropertySetter(property); + value = ConvertForType(value, property.PropertyType); + if (value != null) + { + if (property.PropertyType.BaseType.Name == "Enum") + { + propertySetter(obj, Enum.Parse(property.PropertyType, value.ToString())); + } + else + propertySetter(obj, value); + + + } + } + } + + /// + /// 设置属性值 + /// + /// + /// + /// + public static void SetPropertyValue(object obj, string propertyName, object value) + { + SetPropertyValue(obj.GetType(), obj, propertyName, value); + } + + /// + /// 设置属性值 + /// + /// + /// + /// + /// + public static void SetPropertyValue(Type type, object obj, string propertyName, object value) + { + PropertyInfo property = type.GetProperty(propertyName); + if (property != null) + { + SetPropertyValue(obj, property, value); + } + } + + public static Type GetTypeInfo(this Type typeInfo) + { + return typeInfo; + } + + public static Type[] GetGenericArguments(this Type type) + { + var reval = type.GetTypeInfo().GetGenericArguments(); + return reval; + } + public static bool IsGenericType(this Type type) + { + var reval = type.GetTypeInfo().IsGenericType; + return reval; + } + public static PropertyInfo[] GetProperties(this Type type) + { + var reval = type.GetTypeInfo().GetProperties(); + return reval; + } + public static PropertyInfo GetProperty(this Type type, string name) + { + var reval = type.GetTypeInfo().GetProperty(name); + return reval; + } + + public static FieldInfo GetField(this Type type, string name) + { + var reval = type.GetTypeInfo().GetField(name); + return reval; + } + + public static bool IsEnum(this Type type) + { + var reval = type.GetTypeInfo().IsEnum; + return reval; + } + + public static MethodInfo GetMethod(this Type type, string name) + { + var reval = type.GetTypeInfo().GetMethod(name); + return reval; + } + public static MethodInfo GetMethod(this Type type, string name, Type[] types) + { + var reval = type.GetTypeInfo().GetMethod(name, types); + return reval; + } + public static ConstructorInfo GetConstructor(this Type type, Type[] types) + { + var reval = type.GetTypeInfo().GetConstructor(types); + return reval; + } + + public static bool IsValueType(this Type type) + { + return type.GetTypeInfo().IsValueType; + } + + public static bool IsEntity(this Type type) + { + return type.GetTypeInfo().IsClass; + } + + public static Type ReflectedType(this MethodInfo method) + { + return method.ReflectedType; + } + } +} diff --git a/类库/SqlSugar/Utilities/UtilConstants.cs b/类库/SqlSugar/Utilities/UtilConstants.cs new file mode 100644 index 0000000..f0a7f6a --- /dev/null +++ b/类库/SqlSugar/Utilities/UtilConstants.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + internal static class UtilConstants + { + public const string Dot = "."; + public const char DotChar = '.'; + internal const string Space = " "; + internal const char SpaceChar =' '; + internal const string AssemblyName = "SqlSugar"; + internal const string ReplaceKey = "{662E689B-17A1-4D06-9D27-F29EAB8BC3D6}"; + internal const string ReplaceCommaKey = "{112A689B-17A1-4A06-9D27-A39EAB8BC3D5}"; + + internal static Type IntType = typeof(int); + internal static Type LongType = typeof(long); + internal static Type GuidType = typeof(Guid); + internal static Type BoolType = typeof(bool); + internal static Type BoolTypeNull = typeof(bool?); + internal static Type ByteType = typeof(Byte); + internal static Type ObjType = typeof(object); + internal static Type DobType = typeof(double); + internal static Type FloatType = typeof(float); + internal static Type ShortType = typeof(short); + internal static Type DecType = typeof(decimal); + internal static Type StringType = typeof(string); + internal static Type DateType = typeof(DateTime); + internal static Type DateTimeOffsetType = typeof(DateTimeOffset); + internal static Type TimeSpanType = typeof(TimeSpan); + internal static Type ByteArrayType = typeof(byte[]); + internal static Type ModelType= typeof(ModelContext); + internal static Type DynamicType = typeof(ExpandoObject); + internal static Type Dicii = typeof(KeyValuePair); + internal static Type DicIS = typeof(KeyValuePair); + internal static Type DicSi = typeof(KeyValuePair); + internal static Type DicSS = typeof(KeyValuePair); + internal static Type DicOO = typeof(KeyValuePair); + internal static Type DicSo = typeof(KeyValuePair); + internal static Type DicArraySS = typeof(Dictionary); + internal static Type DicArraySO = typeof(Dictionary); + + public static Type SugarType = typeof(SqlSugarClient); + } +} diff --git a/类库/SqlSugar/Utilities/UtilConvert.cs b/类库/SqlSugar/Utilities/UtilConvert.cs new file mode 100644 index 0000000..ca44956 --- /dev/null +++ b/类库/SqlSugar/Utilities/UtilConvert.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +namespace SqlSugar +{ + public static class UtilConvert + { + public static int ObjToInt(this object thisValue) + { + int reval = 0; + if (thisValue == null) return 0; + if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return reval; + } + + public static int ObjToInt(this object thisValue, int errorValue) + { + int reval = 0; + if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return errorValue; + } + + public static double ObjToMoney(this object thisValue) + { + double reval = 0; + if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return 0; + } + + public static double ObjToMoney(this object thisValue, double errorValue) + { + double reval = 0; + if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return errorValue; + } + + public static string ObjToString(this object thisValue) + { + if (thisValue != null) return thisValue.ToString().Trim(); + return ""; + } + + public static string ObjToString(this object thisValue, string errorValue) + { + if (thisValue != null) return thisValue.ToString().Trim(); + return errorValue; + } + + public static Decimal ObjToDecimal(this object thisValue) + { + Decimal reval = 0; + if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return 0; + } + + public static Decimal ObjToDecimal(this object thisValue, decimal errorValue) + { + Decimal reval = 0; + if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return errorValue; + } + + public static DateTime ObjToDate(this object thisValue) + { + DateTime reval = DateTime.MinValue; + if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval)) + { + reval = Convert.ToDateTime(thisValue); + } + return reval; + } + + public static DateTime ObjToDate(this object thisValue, DateTime errorValue) + { + DateTime reval = DateTime.MinValue; + if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return errorValue; + } + + public static bool ObjToBool(this object thisValue) + { + bool reval = false; + if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval)) + { + return reval; + } + return reval; + } + } +} diff --git a/类库/SqlSugar/Utilities/UtilExceptions.cs b/类库/SqlSugar/Utilities/UtilExceptions.cs new file mode 100644 index 0000000..0632b54 --- /dev/null +++ b/类库/SqlSugar/Utilities/UtilExceptions.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Newtonsoft.Json; +namespace SqlSugar +{ + public class SqlSugarException : Exception + { + public string Sql { get; set; } + public object Parametres { get; set; } + public new Exception InnerException; + public new string StackTrace; + public new MethodBase TargetSite; + public new string Source; + + public SqlSugarException(string message) + : base(message){} + + public SqlSugarException(SqlSugarClient context,string message, string sql) + : base(message) { + this.Sql = sql; + } + + public SqlSugarException(SqlSugarClient context, string message, string sql, object pars) + : base(message) { + this.Sql = sql; + this.Parametres = pars; + } + + public SqlSugarException(SqlSugarClient context, Exception ex, string sql, object pars) + : base(ex.Message) + { + this.Sql = sql; + this.Parametres = pars; + this.InnerException = ex.InnerException; + this.StackTrace = ex.StackTrace; + this.TargetSite = ex.TargetSite; + this.Source = ex.Source; + } + + public SqlSugarException(SqlSugarClient context, string message, object pars) + : base(message) { + this.Parametres = pars; + } + } + public class VersionExceptions : SqlSugarException + { + public VersionExceptions(string message) + : base(message){ } + } +} diff --git a/类库/SqlSugar/Utilities/UtilMethods.cs b/类库/SqlSugar/Utilities/UtilMethods.cs new file mode 100644 index 0000000..031ccfa --- /dev/null +++ b/类库/SqlSugar/Utilities/UtilMethods.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; + +namespace SqlSugar +{ + public class UtilMethods + { + internal static Type GetUnderType(Type oldType) + { + Type type = Nullable.GetUnderlyingType(oldType); + return type == null ? oldType : type; + } + + internal static Type GetRootBaseType(Type entityType) + { + var baseType = entityType.BaseType; + while (baseType != null && baseType.BaseType != UtilConstants.ObjType) + { + baseType = baseType.BaseType; + } + return baseType; + } + + + internal static Type GetUnderType(PropertyInfo propertyInfo, ref bool isNullable) + { + Type unType = Nullable.GetUnderlyingType(propertyInfo.PropertyType); + isNullable = unType != null; + unType = unType ?? propertyInfo.PropertyType; + return unType; + } + + internal static Type GetUnderType(PropertyInfo propertyInfo) + { + Type unType = Nullable.GetUnderlyingType(propertyInfo.PropertyType); + unType = unType ?? propertyInfo.PropertyType; + return unType; + } + + internal static bool IsNullable(PropertyInfo propertyInfo) + { + Type unType = Nullable.GetUnderlyingType(propertyInfo.PropertyType); + return unType != null; + } + + internal static T IsNullReturnNew(T returnObj) where T : new() + { + if (returnObj.IsNullOrEmpty()) + { + returnObj = new T(); + } + return returnObj; + } + + internal static T ChangeType(T obj, Type type) + { + return (T)Convert.ChangeType(obj, type); + } + + internal static T ChangeType(T obj) + { + return (T)Convert.ChangeType(obj, typeof(T)); + } + + internal static void RepairReplicationParameters(ref string appendSql, SugarParameter[] parameters, int addIndex,string append=null) + { + if (appendSql.HasValue() && parameters.HasValue()) + { + foreach (var parameter in parameters.OrderByDescending(it => it.ParameterName.Length)) + { + //Compatible with.NET CORE parameters case + var name = parameter.ParameterName; + string newName = name +append+ addIndex; + appendSql =Regex.Replace(appendSql,name,newName,RegexOptions.IgnoreCase); + parameter.ParameterName = newName; + } + } + } + + internal static string GetPackTable(string sql, string shortName) + { + return string.Format(" ({0}) {1} ", sql, shortName); + } + + internal static string GetParenthesesValue(string dbTypeName) + { + if (Regex.IsMatch(dbTypeName, @"\(.+\)")) + { + dbTypeName = Regex.Replace(dbTypeName, @"\(.+\)", ""); + } + dbTypeName = dbTypeName.Trim(); + return dbTypeName; + } + + internal static T GetOldValue(T value, Action action) + { + action(); + return value; + } + + internal static object DefaultForType(Type targetType) + { + return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; + } + + internal static Int64 GetLong(byte[] bytes) + { + return Convert.ToInt64(string.Join("", bytes).PadRight(20, '0')); + } + + internal static string GetMD5(string myString) + { + MD5 md5 = new MD5CryptoServiceProvider(); + byte[] fromData = System.Text.Encoding.Unicode.GetBytes(myString); + byte[] targetData = md5.ComputeHash(fromData); + string byte2String = null; + + for (int i = 0; i < targetData.Length; i++) + { + byte2String += targetData[i].ToString("x"); + } + + return byte2String; + } + + } +} diff --git a/类库/SqlSugar/Utilities/UtilRandom.cs b/类库/SqlSugar/Utilities/UtilRandom.cs new file mode 100644 index 0000000..5a51119 --- /dev/null +++ b/类库/SqlSugar/Utilities/UtilRandom.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SqlSugar +{ + public class UtilRandom + { + public static Random Random = new Random(); + public static int GetRandomIndex(Dictionary pars) + { + int maxValue = 0; + foreach (var item in pars) + { + maxValue += item.Value; + } + var num = Random.Next(1, maxValue); + var result = 0; + var endValue = 0; + foreach (var item in pars) + { + var index = pars.ToList().IndexOf(item); + var beginValue = index == 0 ? 0 : pars[index - 1]; + endValue += item.Value; + result = item.Key; + if (num >= beginValue && num <= endValue) + break; + } + return result; + } + } +} diff --git a/类库/SqlSugar/Utilities/ValidateExtensions.cs b/类库/SqlSugar/Utilities/ValidateExtensions.cs new file mode 100644 index 0000000..df518b7 --- /dev/null +++ b/类库/SqlSugar/Utilities/ValidateExtensions.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +namespace SqlSugar +{ + internal static class ValidateExtensions + { + public static bool IsInRange(this int thisValue, int begin, int end) + { + return thisValue >= begin && thisValue <= end; + } + + public static bool IsInRange(this DateTime thisValue, DateTime begin, DateTime end) + { + return thisValue >= begin && thisValue <= end; + } + + public static bool IsIn(this T thisValue, params T[] values) + { + return values.Contains(thisValue); + } + + public static bool IsContainsIn(this string thisValue, params string[] inValues) + { + return inValues.Any(it => thisValue.Contains(it)); + } + + public static bool IsNullOrEmpty(this object thisValue) + { + if (thisValue == null || thisValue == DBNull.Value) return true; + return thisValue.ToString() == ""; + } + + public static bool IsNullOrEmpty(this Guid? thisValue) + { + if (thisValue == null) return true; + return thisValue == Guid.Empty; + } + + public static bool IsNullOrEmpty(this Guid thisValue) + { + if (thisValue == null) return true; + return thisValue == Guid.Empty; + } + + public static bool IsNullOrEmpty(this IEnumerable thisValue) + { + if (thisValue == null || thisValue.Count() == 0) return true; + return false; + } + + public static bool HasValue(this object thisValue) + { + if (thisValue == null || thisValue == DBNull.Value) return false; + return thisValue.ToString() != ""; + } + + public static bool HasValue(this IEnumerable thisValue) + { + if (thisValue == null || thisValue.Count() == 0) return false; + return true; + } + + public static bool IsValuable(this IEnumerable> thisValue) + { + if (thisValue == null || thisValue.Count() == 0) return false; + return true; + } + + public static bool IsZero(this object thisValue) + { + return (thisValue == null || thisValue.ToString() == "0"); + } + + public static bool IsInt(this object thisValue) + { + if (thisValue == null) return false; + return Regex.IsMatch(thisValue.ToString(), @"^\d+$"); + } + + /// + public static bool IsNoInt(this object thisValue) + { + if (thisValue == null) return true; + return !Regex.IsMatch(thisValue.ToString(), @"^\d+$"); + } + + public static bool IsMoney(this object thisValue) + { + if (thisValue == null) return false; + double outValue = 0; + return double.TryParse(thisValue.ToString(), out outValue); + } + public static bool IsGuid(this object thisValue) + { + if (thisValue == null) return false; + Guid outValue = Guid.Empty; + return Guid.TryParse(thisValue.ToString(), out outValue); + } + + public static bool IsDate(this object thisValue) + { + if (thisValue == null) return false; + DateTime outValue = DateTime.MinValue; + return DateTime.TryParse(thisValue.ToString(), out outValue); + } + + public static bool IsEamil(this object thisValue) + { + if (thisValue == null) return false; + return Regex.IsMatch(thisValue.ToString(), @"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"); + } + + public static bool IsMobile(this object thisValue) + { + if (thisValue == null) return false; + return Regex.IsMatch(thisValue.ToString(), @"^\d{11}$"); + } + + public static bool IsTelephone(this object thisValue) + { + if (thisValue == null) return false; + return System.Text.RegularExpressions.Regex.IsMatch(thisValue.ToString(), @"^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{8}$"); + + } + + public static bool IsIDcard(this object thisValue) + { + if (thisValue == null) return false; + return System.Text.RegularExpressions.Regex.IsMatch(thisValue.ToString(), @"^(\d{15}$|^\d{18}$|^\d{17}(\d|X|x))$"); + } + + public static bool IsFax(this object thisValue) + { + if (thisValue == null) return false; + return System.Text.RegularExpressions.Regex.IsMatch(thisValue.ToString(), @"^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$"); + } + + public static bool IsMatch(this object thisValue, string pattern) + { + if (thisValue == null) return false; + Regex reg = new Regex(pattern); + return reg.IsMatch(thisValue.ToString()); + } + public static bool IsAnonymousType(this Type type) + { + string typeName = type.Name; + return typeName.Contains("<>") && typeName.Contains("__") && typeName.Contains("AnonymousType"); + } + public static bool IsCollectionsList(this string thisValue) + { + return (thisValue + "").StartsWith("System.Collections.Generic.List")|| (thisValue + "").StartsWith("System.Collections.Generic.IEnumerable"); + } + public static bool IsStringArray(this string thisValue) + { + return (thisValue + "").IsMatch(@"System\.[a-z,A-Z,0-9]+?\[\]"); + } + public static bool IsEnumerable(this string thisValue) + { + return (thisValue + "").StartsWith("System.Linq.Enumerable"); + } + + public static Type StringType = typeof (string); + + public static bool IsClass(this Type thisValue) + { + return thisValue != StringType && thisValue.IsEntity(); + } + } +} diff --git a/类库/SqlSugar/nuget.bat b/类库/SqlSugar/nuget.bat new file mode 100644 index 0000000..68b1bf6 --- /dev/null +++ b/类库/SqlSugar/nuget.bat @@ -0,0 +1 @@ +%~dp0nuget.exe pack %~dp0SqlSugar.nuspec -OutputDirectory %~dp0 \ No newline at end of file diff --git a/类库/SqlSugar/packages.config b/类库/SqlSugar/packages.config new file mode 100644 index 0000000..7e6d08f --- /dev/null +++ b/类库/SqlSugar/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/类库/UI.Framework/Controls/ButtonCheck.cs b/类库/UI.Framework/Controls/ButtonCheck.cs new file mode 100644 index 0000000..893a5e0 --- /dev/null +++ b/类库/UI.Framework/Controls/ButtonCheck.cs @@ -0,0 +1,129 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UI.Framework.Controls +{ + public enum CheckStyle + { + style1 = 0, + style2 = 1, + style3 = 2, + style4 = 3, + style5 = 4, + style6 = 5 + }; + + public partial class ButtonCheck : UserControl + { + public ButtonCheck() + { + try + { + InitializeComponent(); + + //设置Style支持透明背景色并且双缓冲 + this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); + this.SetStyle(ControlStyles.DoubleBuffer, true); + this.SetStyle(ControlStyles.ResizeRedraw, true); + this.SetStyle(ControlStyles.Selectable, true); + this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); + this.SetStyle(ControlStyles.UserPaint, true); + this.BackColor = Color.Transparent; + + this.Cursor = Cursors.Hand; + this.Size = new Size(87, 27); + } + catch (Exception) + { } + } + + bool isCheck = false; + + /// + /// 是否选中 + /// + public bool Checked + { + set { isCheck = value; this.Invalidate(); } + get { return isCheck; } + } + + CheckStyle checkStyle = CheckStyle.style1; + + /// + /// 样式 + /// + public CheckStyle CheckStyleX + { + set { checkStyle = value; this.Invalidate(); } + get { return checkStyle; } + } + + protected override void OnPaint(PaintEventArgs e) + { + Bitmap bitMapOn = null; + Bitmap bitMapOff = null; + Graphics g = null; + + try + { + if (checkStyle == CheckStyle.style1) + { + bitMapOn = Properties.Resources.btncheckon1; + bitMapOff = Properties.Resources.btncheckoff1; + } + else if (checkStyle == CheckStyle.style2) + { + bitMapOn = Properties.Resources.btncheckon2; + bitMapOff = Properties.Resources.btncheckoff2; + } + else if (checkStyle == CheckStyle.style3) + { + bitMapOn = Properties.Resources.btncheckon3; + bitMapOff = Properties.Resources.btncheckoff3; + } + else if (checkStyle == CheckStyle.style4) + { + bitMapOn = Properties.Resources.btncheckon4; + bitMapOff = Properties.Resources.btncheckoff4; + } + else if (checkStyle == CheckStyle.style5) + { + bitMapOn = Properties.Resources.btncheckon5; + bitMapOff = Properties.Resources.btncheckoff5; + } + else if (checkStyle == CheckStyle.style6) + { + bitMapOn = Properties.Resources.btncheckon6; + bitMapOff = Properties.Resources.btncheckoff6; + } + + g = e.Graphics; + Rectangle rec = new Rectangle(0, 0, this.Size.Width, this.Size.Height); + g.DrawImage(isCheck ? bitMapOn : bitMapOff, rec); + } + catch (Exception) + { } + finally + { + if (bitMapOn != null) + bitMapOn.Dispose(); + if (bitMapOff != null) + bitMapOff.Dispose(); + } + } + + private void myButtonCheck_Click(object sender, EventArgs e) + { + try + { + isCheck = !isCheck; + this.Invalidate(); + } + catch (Exception) + { } + } + + } +} diff --git a/类库/UI.Framework/Controls/ButtonCheck.designer.cs b/类库/UI.Framework/Controls/ButtonCheck.designer.cs new file mode 100644 index 0000000..f37c916 --- /dev/null +++ b/类库/UI.Framework/Controls/ButtonCheck.designer.cs @@ -0,0 +1,45 @@ +namespace UI.Framework.Controls +{ + partial class ButtonCheck + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region 组件设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // myButtonCheck + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Name = "myButtonCheck"; + this.Click += new System.EventHandler(this.myButtonCheck_Click); + this.ResumeLayout(false); + + } + + #endregion + } +} diff --git a/类库/UI.Framework/Controls/ButtonCheck.resx b/类库/UI.Framework/Controls/ButtonCheck.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/UI.Framework/Controls/ButtonCheck.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/UI.Framework/Controls/GridPageControl.Designer.cs b/类库/UI.Framework/Controls/GridPageControl.Designer.cs new file mode 100644 index 0000000..901ae97 --- /dev/null +++ b/类库/UI.Framework/Controls/GridPageControl.Designer.cs @@ -0,0 +1,92 @@ +namespace UI.Framework.Controls +{ + partial class GridPageControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.DataView = new DevExpress.XtraGrid.GridControl(); + this.gridView1 = new DevExpress.XtraGrid.Views.Grid.GridView(); + this.DataPage = new UI.Framework.Controls.PageControl(); + ((System.ComponentModel.ISupportInitialize)(this.DataView)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).BeginInit(); + this.SuspendLayout(); + // + // DataView + // + this.DataView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.DataView.Location = new System.Drawing.Point(0, 0); + this.DataView.MainView = this.gridView1; + this.DataView.Name = "DataView"; + this.DataView.Size = new System.Drawing.Size(712, 428); + this.DataView.TabIndex = 0; + this.DataView.ViewCollection.AddRange(new DevExpress.XtraGrid.Views.Base.BaseView[] { + this.gridView1}); + // + // gridView1 + // + this.gridView1.Appearance.HeaderPanel.Options.UseTextOptions = true; + this.gridView1.Appearance.HeaderPanel.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.Appearance.Row.Options.UseTextOptions = true; + this.gridView1.Appearance.Row.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.gridView1.GridControl = this.DataView; + this.gridView1.IndicatorWidth = 50; + this.gridView1.Name = "gridView1"; + this.gridView1.OptionsBehavior.Editable = false; + this.gridView1.OptionsSelection.EnableAppearanceFocusedCell = false; + this.gridView1.OptionsView.ShowGroupPanel = false; + this.gridView1.CustomDrawRowIndicator += new DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventHandler(this.gridView1_CustomDrawRowIndicator); + // + // DataPage + // + this.DataPage.Dock = System.Windows.Forms.DockStyle.Bottom; + this.DataPage.Location = new System.Drawing.Point(0, 434); + this.DataPage.Name = "DataPage"; + this.DataPage.Size = new System.Drawing.Size(715, 20); + this.DataPage.TabIndex = 1; + // + // GridPageControl + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.DataPage); + this.Controls.Add(this.DataView); + this.Name = "GridPageControl"; + this.Size = new System.Drawing.Size(715, 454); + ((System.ComponentModel.ISupportInitialize)(this.DataView)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.gridView1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private DevExpress.XtraGrid.Views.Grid.GridView gridView1; + private PageControl DataPage; + public DevExpress.XtraGrid.GridControl DataView; + } +} diff --git a/类库/UI.Framework/Controls/GridPageControl.cs b/类库/UI.Framework/Controls/GridPageControl.cs new file mode 100644 index 0000000..f7a2460 --- /dev/null +++ b/类库/UI.Framework/Controls/GridPageControl.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using UI.Framework.Entitys; +using DevExpress.XtraGrid.Columns; + +namespace UI.Framework.Controls +{ + public partial class GridPageControl : DevExpress.XtraEditors.XtraUserControl + { + public GridPageControl() + { + InitializeComponent(); + } + /// + /// + /// + public void Bind(PageControl.SerchEvents serchDataMethod, int pageSize = 30) + { + try + { + var type = typeof(T); + var properties = type.GetProperties(); + int number = 1; + List GridColumns = new List(); + foreach (var item in properties) + { + + DataViewAtrribute att = item.GetCustomAttributes(typeof(DataViewAtrribute), true).FirstOrDefault() as DataViewAtrribute; + + var column = new DevExpress.XtraGrid.Columns.GridColumn(); + column.Caption = att != null ? att.Name : item.Name; + column.Name = item.Name; + column.Visible = true; + column.VisibleIndex = item.Name.ToLower() == "id" ? 0 : number; + if (item.Name.ToLower() == "id") column.MinWidth = column.Width = column.MaxWidth = 80; + column.FieldName = item.Name; + GridColumns.Add(column); + } + this.gridView1.Columns.AddRange(GridColumns.ToArray()); + this.DataPage.Bind(serchDataMethod, DataView, pageSize);//给分页组件绑定值,搜索函数,显示控件,每页显示行数 + } + catch (Exception) + { } + } + + /// + /// 绑定数据源 + /// + public void Bind(PageControl.SerchEvents serchDataMethod, int pageSize = 30) + { + try + { + this.DataPage.Bind(serchDataMethod, DataView, pageSize);//给分页组件绑定值,搜索函数,显示控件,每页显示行数 + } + catch (Exception) + { } + } + /// + /// + /// + private void gridView1_CustomDrawRowIndicator(object sender, DevExpress.XtraGrid.Views.Grid.RowIndicatorCustomDrawEventArgs e) + { + try + { + if (e.Info.IsRowIndicator && e.RowHandle >= 0) e.Info.DisplayText = (e.RowHandle + 1).ToString(); + } + catch (Exception) + { } + } + } + + +} diff --git a/类库/UI.Framework/Controls/GridPageControl.resx b/类库/UI.Framework/Controls/GridPageControl.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/UI.Framework/Controls/GridPageControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/UI.Framework/Controls/PageControl.Designer.cs b/类库/UI.Framework/Controls/PageControl.Designer.cs new file mode 100644 index 0000000..069e5a5 --- /dev/null +++ b/类库/UI.Framework/Controls/PageControl.Designer.cs @@ -0,0 +1,400 @@ +namespace UI.Framework.Controls +{ + partial class PageControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PageControl)); + this.popupMenu1 = new DevExpress.XtraBars.PopupMenu(); + this.barButtonItem1 = new DevExpress.XtraBars.BarButtonItem(); + this.barButtonItem3 = new DevExpress.XtraBars.BarButtonItem(); + this.barManager1 = new DevExpress.XtraBars.BarManager(); + this.barDockControlTop = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlBottom = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlLeft = new DevExpress.XtraBars.BarDockControl(); + this.barDockControlRight = new DevExpress.XtraBars.BarDockControl(); + this.SaveFileDialog = new DevExpress.XtraEditors.XtraSaveFileDialog(); + this.simpleButton1 = new DevExpress.XtraEditors.SimpleButton(); + this.labelControl5 = new DevExpress.XtraEditors.LabelControl(); + this.textEdit1 = new DevExpress.XtraEditors.TextEdit(); + this.labelControl3 = new DevExpress.XtraEditors.LabelControl(); + this.comboBoxEditTotal = new DevExpress.XtraEditors.TextEdit(); + this.labelControl2 = new DevExpress.XtraEditors.LabelControl(); + this.textEditToPageSize = new DevExpress.XtraEditors.TextEdit(); + this.labelControl4 = new DevExpress.XtraEditors.LabelControl(); + this.textEditToPageMax = new DevExpress.XtraEditors.TextEdit(); + this.dropDownButton1 = new DevExpress.XtraEditors.DropDownButton(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + this.simpleButtonEnd = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButtonNext = new DevExpress.XtraEditors.SimpleButton(); + this.textEditCurPage = new DevExpress.XtraEditors.TextEdit(); + this.simpleButtonPre = new DevExpress.XtraEditors.SimpleButton(); + this.simpleButtonFirst = new DevExpress.XtraEditors.SimpleButton(); + ((System.ComponentModel.ISupportInitialize)(this.popupMenu1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.barManager1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEditTotal.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEditToPageSize.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEditToPageMax.Properties)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEditCurPage.Properties)).BeginInit(); + this.SuspendLayout(); + // + // popupMenu1 + // + this.popupMenu1.LinksPersistInfo.AddRange(new DevExpress.XtraBars.LinkPersistInfo[] { + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem1), + new DevExpress.XtraBars.LinkPersistInfo(this.barButtonItem3)}); + this.popupMenu1.Manager = this.barManager1; + this.popupMenu1.Name = "popupMenu1"; + // + // barButtonItem1 + // + this.barButtonItem1.Caption = "导出当前页Excel"; + this.barButtonItem1.Id = 6; + this.barButtonItem1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem1.ImageOptions.Image"))); + this.barButtonItem1.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem1.ImageOptions.LargeImage"))); + this.barButtonItem1.Name = "barButtonItem1"; + this.barButtonItem1.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem1_ItemClick); + // + // barButtonItem3 + // + this.barButtonItem3.Caption = "打印当前页数据"; + this.barButtonItem3.Id = 8; + this.barButtonItem3.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("barButtonItem3.ImageOptions.Image"))); + this.barButtonItem3.ImageOptions.LargeImage = ((System.Drawing.Image)(resources.GetObject("barButtonItem3.ImageOptions.LargeImage"))); + this.barButtonItem3.Name = "barButtonItem3"; + this.barButtonItem3.ItemClick += new DevExpress.XtraBars.ItemClickEventHandler(this.barButtonItem3_ItemClick); + // + // barManager1 + // + this.barManager1.DockControls.Add(this.barDockControlTop); + this.barManager1.DockControls.Add(this.barDockControlBottom); + this.barManager1.DockControls.Add(this.barDockControlLeft); + this.barManager1.DockControls.Add(this.barDockControlRight); + this.barManager1.Form = this; + this.barManager1.Items.AddRange(new DevExpress.XtraBars.BarItem[] { + this.barButtonItem1, + this.barButtonItem3}); + this.barManager1.MaxItemId = 10; + // + // barDockControlTop + // + this.barDockControlTop.CausesValidation = false; + this.barDockControlTop.Dock = System.Windows.Forms.DockStyle.Top; + this.barDockControlTop.Location = new System.Drawing.Point(0, 0); + this.barDockControlTop.Manager = this.barManager1; + this.barDockControlTop.Size = new System.Drawing.Size(741, 0); + // + // barDockControlBottom + // + this.barDockControlBottom.CausesValidation = false; + this.barDockControlBottom.Dock = System.Windows.Forms.DockStyle.Bottom; + this.barDockControlBottom.Location = new System.Drawing.Point(0, 36); + this.barDockControlBottom.Manager = this.barManager1; + this.barDockControlBottom.Size = new System.Drawing.Size(741, 0); + // + // barDockControlLeft + // + this.barDockControlLeft.CausesValidation = false; + this.barDockControlLeft.Dock = System.Windows.Forms.DockStyle.Left; + this.barDockControlLeft.Location = new System.Drawing.Point(0, 0); + this.barDockControlLeft.Manager = this.barManager1; + this.barDockControlLeft.Size = new System.Drawing.Size(0, 36); + // + // barDockControlRight + // + this.barDockControlRight.CausesValidation = false; + this.barDockControlRight.Dock = System.Windows.Forms.DockStyle.Right; + this.barDockControlRight.Location = new System.Drawing.Point(741, 0); + this.barDockControlRight.Manager = this.barManager1; + this.barDockControlRight.Size = new System.Drawing.Size(0, 36); + // + // SaveFileDialog + // + this.SaveFileDialog.FileName = null; + // + // simpleButton1 + // + this.simpleButton1.Appearance.Options.UseTextOptions = true; + this.simpleButton1.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.simpleButton1.ImageOptions.Location = DevExpress.XtraEditors.ImageLocation.MiddleCenter; + this.simpleButton1.Location = new System.Drawing.Point(553, 5); + this.simpleButton1.Name = "simpleButton1"; + this.simpleButton1.Size = new System.Drawing.Size(48, 23); + this.simpleButton1.TabIndex = 62; + this.simpleButton1.Text = "跳转"; + this.simpleButton1.Click += new System.EventHandler(this.Go); + // + // labelControl5 + // + this.labelControl5.AutoSizeMode = DevExpress.XtraEditors.LabelAutoSizeMode.None; + this.labelControl5.Location = new System.Drawing.Point(530, 6); + this.labelControl5.Name = "labelControl5"; + this.labelControl5.Size = new System.Drawing.Size(17, 21); + this.labelControl5.TabIndex = 61; + this.labelControl5.Text = " 页"; + // + // textEdit1 + // + this.textEdit1.EditValue = "1"; + this.textEdit1.Location = new System.Drawing.Point(487, 6); + this.textEdit1.Name = "textEdit1"; + this.textEdit1.Properties.Appearance.Options.UseTextOptions = true; + this.textEdit1.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.textEdit1.Properties.AutoHeight = false; + this.textEdit1.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Simple; + this.textEdit1.Properties.Mask.EditMask = "\\d+"; + this.textEdit1.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx; + this.textEdit1.Size = new System.Drawing.Size(37, 21); + this.textEdit1.TabIndex = 60; + // + // labelControl3 + // + this.labelControl3.AutoSizeMode = DevExpress.XtraEditors.LabelAutoSizeMode.None; + this.labelControl3.Location = new System.Drawing.Point(451, 6); + this.labelControl3.Name = "labelControl3"; + this.labelControl3.Size = new System.Drawing.Size(42, 21); + this.labelControl3.TabIndex = 59; + this.labelControl3.Text = " 行,第"; + // + // comboBoxEditTotal + // + this.comboBoxEditTotal.EditValue = "0"; + this.comboBoxEditTotal.Location = new System.Drawing.Point(377, 6); + this.comboBoxEditTotal.Name = "comboBoxEditTotal"; + this.comboBoxEditTotal.Properties.Appearance.Options.UseTextOptions = true; + this.comboBoxEditTotal.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.comboBoxEditTotal.Properties.AutoHeight = false; + this.comboBoxEditTotal.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Simple; + this.comboBoxEditTotal.Properties.DisplayFormat.FormatString = "d"; + this.comboBoxEditTotal.Properties.DisplayFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.comboBoxEditTotal.Properties.EditFormat.FormatString = "d"; + this.comboBoxEditTotal.Properties.EditFormat.FormatType = DevExpress.Utils.FormatType.Numeric; + this.comboBoxEditTotal.Properties.EditValueChangedDelay = 1; + this.comboBoxEditTotal.Properties.Mask.EditMask = "\\d{0,9}"; + this.comboBoxEditTotal.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx; + this.comboBoxEditTotal.Properties.ReadOnly = true; + this.comboBoxEditTotal.Size = new System.Drawing.Size(68, 21); + this.comboBoxEditTotal.TabIndex = 58; + // + // labelControl2 + // + this.labelControl2.AutoSizeMode = DevExpress.XtraEditors.LabelAutoSizeMode.None; + this.labelControl2.Location = new System.Drawing.Point(341, 6); + this.labelControl2.Name = "labelControl2"; + this.labelControl2.Size = new System.Drawing.Size(36, 21); + this.labelControl2.TabIndex = 57; + this.labelControl2.Text = " 行,共"; + // + // textEditToPageSize + // + this.textEditToPageSize.EditValue = "100"; + this.textEditToPageSize.Location = new System.Drawing.Point(299, 6); + this.textEditToPageSize.Name = "textEditToPageSize"; + this.textEditToPageSize.Properties.Appearance.Options.UseTextOptions = true; + this.textEditToPageSize.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.textEditToPageSize.Properties.AutoHeight = false; + this.textEditToPageSize.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Simple; + this.textEditToPageSize.Properties.Mask.EditMask = "\\d+"; + this.textEditToPageSize.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx; + this.textEditToPageSize.Size = new System.Drawing.Size(42, 21); + this.textEditToPageSize.TabIndex = 55; + // + // labelControl4 + // + this.labelControl4.AutoSizeMode = DevExpress.XtraEditors.LabelAutoSizeMode.None; + this.labelControl4.Location = new System.Drawing.Point(251, 6); + this.labelControl4.Name = "labelControl4"; + this.labelControl4.Size = new System.Drawing.Size(48, 21); + this.labelControl4.TabIndex = 56; + this.labelControl4.Text = " 页,每页"; + // + // textEditToPageMax + // + this.textEditToPageMax.EditValue = "1"; + this.textEditToPageMax.Location = new System.Drawing.Point(207, 6); + this.textEditToPageMax.Name = "textEditToPageMax"; + this.textEditToPageMax.Properties.Appearance.Options.UseTextOptions = true; + this.textEditToPageMax.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.textEditToPageMax.Properties.AutoHeight = false; + this.textEditToPageMax.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Simple; + this.textEditToPageMax.Properties.Mask.EditMask = "\\d+"; + this.textEditToPageMax.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx; + this.textEditToPageMax.Size = new System.Drawing.Size(44, 20); + this.textEditToPageMax.TabIndex = 54; + // + // dropDownButton1 + // + this.dropDownButton1.DropDownArrowStyle = DevExpress.XtraEditors.DropDownArrowStyle.Show; + this.dropDownButton1.DropDownControl = this.popupMenu1; + this.dropDownButton1.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("dropDownButton1.ImageOptions.Image"))); + this.dropDownButton1.Location = new System.Drawing.Point(624, 4); + this.dropDownButton1.Name = "dropDownButton1"; + this.dropDownButton1.Size = new System.Drawing.Size(99, 25); + this.dropDownButton1.TabIndex = 53; + this.dropDownButton1.Text = "导出打印"; + // + // labelControl1 + // + this.labelControl1.AutoSizeMode = DevExpress.XtraEditors.LabelAutoSizeMode.None; + this.labelControl1.Location = new System.Drawing.Point(188, 6); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(19, 21); + this.labelControl1.TabIndex = 52; + this.labelControl1.Text = " 共"; + // + // simpleButtonEnd + // + this.simpleButtonEnd.Appearance.Options.UseTextOptions = true; + this.simpleButtonEnd.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.simpleButtonEnd.Enabled = false; + this.simpleButtonEnd.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButtonEnd.ImageOptions.Image"))); + this.simpleButtonEnd.ImageOptions.Location = DevExpress.XtraEditors.ImageLocation.MiddleCenter; + this.simpleButtonEnd.Location = new System.Drawing.Point(154, 6); + this.simpleButtonEnd.Name = "simpleButtonEnd"; + this.simpleButtonEnd.Size = new System.Drawing.Size(34, 21); + this.simpleButtonEnd.TabIndex = 47; + this.simpleButtonEnd.Click += new System.EventHandler(this.simpleButtonEnd_Click); + // + // simpleButtonNext + // + this.simpleButtonNext.Appearance.Options.UseTextOptions = true; + this.simpleButtonNext.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.simpleButtonNext.Enabled = false; + this.simpleButtonNext.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButtonNext.ImageOptions.Image"))); + this.simpleButtonNext.ImageOptions.Location = DevExpress.XtraEditors.ImageLocation.MiddleCenter; + this.simpleButtonNext.Location = new System.Drawing.Point(120, 6); + this.simpleButtonNext.Name = "simpleButtonNext"; + this.simpleButtonNext.Size = new System.Drawing.Size(34, 21); + this.simpleButtonNext.TabIndex = 48; + this.simpleButtonNext.Click += new System.EventHandler(this.simpleButtonNext_Click); + // + // textEditCurPage + // + this.textEditCurPage.EditValue = "1"; + this.textEditCurPage.Location = new System.Drawing.Point(83, 6); + this.textEditCurPage.Name = "textEditCurPage"; + this.textEditCurPage.Properties.Appearance.Options.UseTextOptions = true; + this.textEditCurPage.Properties.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.textEditCurPage.Properties.AutoHeight = false; + this.textEditCurPage.Properties.BorderStyle = DevExpress.XtraEditors.Controls.BorderStyles.Simple; + this.textEditCurPage.Properties.Mask.EditMask = "\\d+"; + this.textEditCurPage.Properties.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx; + this.textEditCurPage.Size = new System.Drawing.Size(37, 21); + this.textEditCurPage.TabIndex = 51; + // + // simpleButtonPre + // + this.simpleButtonPre.Appearance.Options.UseTextOptions = true; + this.simpleButtonPre.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.simpleButtonPre.Enabled = false; + this.simpleButtonPre.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButtonPre.ImageOptions.Image"))); + this.simpleButtonPre.ImageOptions.Location = DevExpress.XtraEditors.ImageLocation.MiddleCenter; + this.simpleButtonPre.Location = new System.Drawing.Point(49, 6); + this.simpleButtonPre.Name = "simpleButtonPre"; + this.simpleButtonPre.Size = new System.Drawing.Size(34, 21); + this.simpleButtonPre.TabIndex = 49; + this.simpleButtonPre.Click += new System.EventHandler(this.simpleButtonPre_Click); + // + // simpleButtonFirst + // + this.simpleButtonFirst.Appearance.Options.UseTextOptions = true; + this.simpleButtonFirst.Appearance.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Center; + this.simpleButtonFirst.Enabled = false; + this.simpleButtonFirst.ImageOptions.Image = ((System.Drawing.Image)(resources.GetObject("simpleButtonFirst.ImageOptions.Image"))); + this.simpleButtonFirst.ImageOptions.Location = DevExpress.XtraEditors.ImageLocation.MiddleCenter; + this.simpleButtonFirst.Location = new System.Drawing.Point(15, 6); + this.simpleButtonFirst.Name = "simpleButtonFirst"; + this.simpleButtonFirst.Size = new System.Drawing.Size(34, 21); + this.simpleButtonFirst.TabIndex = 50; + this.simpleButtonFirst.Click += new System.EventHandler(this.simpleButtonFirst_Click); + // + // PageControl + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.simpleButton1); + this.Controls.Add(this.labelControl5); + this.Controls.Add(this.textEdit1); + this.Controls.Add(this.labelControl3); + this.Controls.Add(this.comboBoxEditTotal); + this.Controls.Add(this.labelControl2); + this.Controls.Add(this.textEditToPageSize); + this.Controls.Add(this.labelControl4); + this.Controls.Add(this.textEditToPageMax); + this.Controls.Add(this.dropDownButton1); + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.simpleButtonEnd); + this.Controls.Add(this.simpleButtonNext); + this.Controls.Add(this.textEditCurPage); + this.Controls.Add(this.simpleButtonPre); + this.Controls.Add(this.simpleButtonFirst); + this.Controls.Add(this.barDockControlLeft); + this.Controls.Add(this.barDockControlRight); + this.Controls.Add(this.barDockControlBottom); + this.Controls.Add(this.barDockControlTop); + this.Name = "PageControl"; + this.Size = new System.Drawing.Size(741, 36); + ((System.ComponentModel.ISupportInitialize)(this.popupMenu1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.barManager1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEdit1.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.comboBoxEditTotal.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEditToPageSize.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEditToPageMax.Properties)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.textEditCurPage.Properties)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private DevExpress.XtraBars.PopupMenu popupMenu1; + private DevExpress.XtraEditors.XtraSaveFileDialog SaveFileDialog; + private DevExpress.XtraBars.BarManager barManager1; + private DevExpress.XtraBars.BarDockControl barDockControlTop; + private DevExpress.XtraBars.BarDockControl barDockControlBottom; + private DevExpress.XtraBars.BarDockControl barDockControlLeft; + private DevExpress.XtraBars.BarDockControl barDockControlRight; + private DevExpress.XtraBars.BarButtonItem barButtonItem1; + private DevExpress.XtraBars.BarButtonItem barButtonItem3; + private DevExpress.XtraEditors.SimpleButton simpleButton1; + private DevExpress.XtraEditors.LabelControl labelControl5; + private DevExpress.XtraEditors.TextEdit textEdit1; + private DevExpress.XtraEditors.LabelControl labelControl3; + private DevExpress.XtraEditors.TextEdit comboBoxEditTotal; + private DevExpress.XtraEditors.LabelControl labelControl2; + private DevExpress.XtraEditors.TextEdit textEditToPageSize; + private DevExpress.XtraEditors.LabelControl labelControl4; + private DevExpress.XtraEditors.TextEdit textEditToPageMax; + private DevExpress.XtraEditors.DropDownButton dropDownButton1; + private DevExpress.XtraEditors.LabelControl labelControl1; + private DevExpress.XtraEditors.SimpleButton simpleButtonEnd; + private DevExpress.XtraEditors.SimpleButton simpleButtonNext; + private DevExpress.XtraEditors.TextEdit textEditCurPage; + private DevExpress.XtraEditors.SimpleButton simpleButtonPre; + private DevExpress.XtraEditors.SimpleButton simpleButtonFirst; + } +} diff --git a/类库/UI.Framework/Controls/PageControl.cs b/类库/UI.Framework/Controls/PageControl.cs new file mode 100644 index 0000000..bd8da88 --- /dev/null +++ b/类库/UI.Framework/Controls/PageControl.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using DevExpress.XtraGrid; +using DevExpress.XtraPrinting; +using System.Collections; +using System.Threading; +using UI.Framework.Forms; + +namespace UI.Framework.Controls +{ + public partial class PageControl : DevExpress.XtraEditors.XtraUserControl + { + public class SerchResult + { + /// + /// 总行数 + /// + public long Total { get; set; } + + /// + /// 查询结果 + /// + public object Result { get; set; } + } + + public PageControl() + { + InitializeComponent(); + } + + public delegate SerchResult SerchEvents(int curPage, int pageSize); + private SerchEvents method; + private GridControl gridControl; + private bool beginQuery; + public void Bind(SerchEvents method, GridControl gridControl, int pageSize, bool goto_first = true, bool beginQuery = false) + { + try + { + this.beginQuery = beginQuery; + this.textEditToPageSize.Text = pageSize.ToString(); + this.method = method; + this.gridControl = gridControl; + this.textEditToPageSize.Text = PageSize.ToString(); + if (goto_first) GotoPage(1); + } + catch (Exception ex) + { + BaseForm.ShowError(ex.Message + "._", "系统错误"); + } + } + + /// + /// 每页行 + /// + public int PageSize + { + get + { + return int.Parse(textEditToPageSize.Text); + } + } + + /// + /// 总页数 + /// + + public int PageMax + { + get + { + return int.Parse(this.textEditToPageMax.Text); + } + } + + /// + /// 当前页 + /// + public int PageCur + { + get { return int.Parse(this.textEditCurPage.Text); } + } + + /// + /// 代理委托更新UI + /// + /// + protected delegate void DelegateUpdateUI(Action act); + + /// + /// 代理委托更新UI + /// + /// + protected void UpdateUI(Action act) + { + try + { + if (!InvokeRequired) + { + act.Invoke(); + } + else + { + DelegateUpdateUI delegateUpdateUI = new DelegateUpdateUI(UpdateUI); + Invoke(delegateUpdateUI, act); + } + } + catch (Exception) + { } + } + + /// + /// 查询第几页 + /// + /// + public void GotoPage(int toPage = 1) + { + try + { + if (toPage <= 0) toPage = 1; + if (method == null) throw new Exception("请先调用Bind函数,绑定委托!"); + + SerchResult result = null; + this.UpdateUI(() => + { + this.gridControl.DataSource = null; + }); + + result = this.method(toPage, PageSize); + + if (result == null) result = new SerchResult() { Result = new ArrayList(), Total = 0 }; + + //分页计算 + var rows = result.Total / PageSize; + if (rows != 0 && result.Total % PageSize != 0) rows++; + + this.UpdateUI(() => + { + this.gridControl.DataSource = result.Result; + //控件绑定 + this.textEditCurPage.Text = toPage.ToString(); + this.comboBoxEditTotal.Text = result.Total.ToString(); + this.textEditToPageMax.Text = rows.ToString(); + + //控制显示 + simpleButtonPre.Enabled = false; + simpleButtonFirst.Enabled = false; + simpleButtonNext.Enabled = false; + simpleButtonEnd.Enabled = false; + if (result.Total > 0) + { + if (toPage > 1) + { + simpleButtonPre.Enabled = true; + simpleButtonFirst.Enabled = true; + } + if (toPage < rows) + { + simpleButtonNext.Enabled = true; + simpleButtonEnd.Enabled = true; + } + } + }); + } + catch (Exception ex) + { + this.UpdateUI(() => + { + BaseForm.ShowError(ex.Message); + }); + } + } + + #region 分页按钮被单击 + private async void simpleButtonFirst_Click(object sender, EventArgs e) + { + if (beginQuery) await Task.Run(() => { GotoPage(1); }); + else GotoPage(1); + } + + private async void simpleButtonPre_Click(object sender, EventArgs e) + { + if (beginQuery) await Task.Run(() => { GotoPage((PageCur - 1)); }); + else GotoPage((PageCur - 1)); + } + + private async void simpleButtonNext_Click(object sender, EventArgs e) + { + if (beginQuery) await Task.Run(() => { GotoPage(PageCur + 1); }); + else GotoPage(PageCur + 1); + } + + private async void simpleButtonEnd_Click(object sender, EventArgs e) + { + if (beginQuery) await Task.Run(() => { GotoPage(PageMax); }); + else GotoPage(PageMax); + } + + public async void Go(object sender, EventArgs e) + { + var btn = sender as SimpleButton; + if (btn != null) btn.Enabled = false; + if (beginQuery) + await Task.Run(() => { GotoPage(int.Parse(textEdit1.Text)); }); + else GotoPage(int.Parse(textEdit1.Text)); + if (btn != null) btn.Enabled = true; + } + #endregion + + //导出Excel + private void barButtonItem1_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + try + { + if (this.gridControl == null) throw new Exception("没有需要导出的数据!"); + if (XtraMessageBox.Show("确定要将本页面数据导入到Excel内?", "请选择", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) + { + var table = this.gridControl.DataSource as DataTable; + //if (table == null || table.Rows.Count == 0) throw new Exception("没有需要导出的数据!"); + + this.SaveFileDialog.Filter = "Excel文件(*.xls)|*.xls"; + if (this.SaveFileDialog.ShowDialog(this) == DialogResult.OK) + { + DevExpress.XtraPrinting.XlsExportOptions options = new DevExpress.XtraPrinting.XlsExportOptions(); + this.gridControl.ExportToXls(this.SaveFileDialog.FileName); + XtraMessageBox.Show("恭喜您,已完成数据导出!", "导出完成", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + } + } + catch (Exception vErr) + { + XtraMessageBox.Show(vErr.Message, "导出错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + //打印数据 + private void barButtonItem3_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) + { + try + { + PrintingSystem print = new DevExpress.XtraPrinting.PrintingSystem(); + PrintableComponentLink link = new PrintableComponentLink(print); + print.Links.Add(link); + link.Component = this.gridControl;//这里可以是可打印的部件 + PageHeaderFooter phf = link.PageHeaderFooter as PageHeaderFooter; + phf.Header.Content.Clear(); + phf.Header.Content.AddRange(new string[] { "", "", "" }); + phf.Header.Font = new System.Drawing.Font("宋体", 14, System.Drawing.FontStyle.Bold); + phf.Header.LineAlignment = BrickAlignment.Center; + link.CreateDocument(); //建立文档 + print.PreviewFormEx.Show();//进行预览 + + } + catch (Exception ex) + { + XtraMessageBox.Show(ex.Message, "打印错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + } +} diff --git a/类库/UI.Framework/Controls/PageControl.resx b/类库/UI.Framework/Controls/PageControl.resx new file mode 100644 index 0000000..4b8e782 --- /dev/null +++ b/类库/UI.Framework/Controls/PageControl.resx @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 106, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAA10RVh0VGl0 + bGUARXhwb3J0OxFDFhwAAACFSURBVDhPzZFRCoAwCEB3p86xA3Sb0V9n6QL97mKZjhy2dJMgSHgwnT4c + CwDgJi47ARcT5eVinTcw0CQ0WCU3gRI0EMXAA1WQc2bkyiqeDbiZzr4nGBuwoA5TPtxAA3sLdOaCJVBD + 9A+/scs3ggMLPWQvhi1o87ZOYPxIkOSFk1QF74FwAiSb4wVKYz/SAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAA10RVh0VGl0 + bGUARXhwb3J0OxFDFhwAAAD+SURBVFhH7ZLNDcIwDEa7U+dgAG6M0Bm4MQsL9JpNugQStxBHSeTYcX5a + UoSUT3qijR37gZi01t253FeNmA1wZmusuQduKZOAGmvuASxzS5lE1Pi4PvVO/KKbYXULapiZAPpsiV/+ + RsOrYAKexoBAyzf38F/ggMALDYb3gKu3/QdwlFIlYAEeDvNs4NmQXA5UCVREFDChtbAcOEUgR/QiCSR+ + ckpOwIbMDjvDA0CaWhLNcUQhs0MfvnBEoBgyewgMgbJAT/DOIVAUOBph5p8K5GpS6B13bwgMAVFgSzSH + 5GpS6B3DZo5FgQUaUPO3gdkL3hkJ/ILk4ZkkD89DTx+76kmrFvn0twAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABR0RVh0VGl0 + bGUAUHJpbnQ7UHJpbnRlcjti43w7AAAAeklEQVQ4T8WQWwrAMAgEc8FequRI+SjkcNYtedhEoi2FLgyI + 6EgSiKgRYyQPcmcSWPlewI2MJuMW1Fkm1+Kt4PZxsrbQBXzABWbr3pOrKv8IyjOuehJYGechSLKBbPuh + gshZJo2/i5llykzbUQXadYC4BKuYAg99h8IJUhbv41/hlbkAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAABR0RVh0VGl0 + bGUAUHJpbnQ7UHJpbnRlcjti43w7AAAA5UlEQVRYR+3QSw6DMAwEUC7YS1UciUUlDpd6KpA8w1RqQkg3 + WHoLm/jTTqWUv7LFkWxxJFscyRazeZ7LGTpP2WK2DWmK+4D7gKYDomlF46bLAWneijyjBNJj6H3AJ88o + gfw4aF5NZ+57dpRAfhwO31vkmfqNEsiPr6D7KAHX1JPuowRcU0+6jxJwTSdgHs3UfZRAfnwF3UcJuKae + dB8l4JqgNtwMiKB9lEA8WrQJEI/n6ycINyMs8Yn2UfINmmtj67HzMltU+wHu1zqISw6oifsf6H5AC53j + 2OJItjiSLY5ki+OU6Q31DgCfhx3xBwAAAABJRU5ErkJggg== + + + + 376, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAEB0RVh0VGl0 + bGUAQWxpZ247VGV4dDtJbWFnZTtMYXlvdXQ7U2hhcGU7Q2VudGVyO1dyYXA7VG9wO1NxdWFyZTtSaWdo + dIWhfGcAAAKFSURBVDhPXZLbTxNBFIc3mph4ASwlGv8444NYSUgwqEBbCghSrlKKLTeRIKLCI5eIEQ1S + aLHcUjA+GBQVBIGC0C5bSrvb/jxnWhZxkm9mH2a+35kzKwGQ2geWxjsGPoGh7xT9S2h7tShoZV4yAbhf + BODs8U9KknSOzwpBG23+fyQZmpI0naxJJIiW3gU6KZ2nLSmBi6w83FQB46IKXP20kjh6pCHYew2r7qtY + tudA05Jo6p5jwUVdwEZODO5HENw7TPEngm0iEtXw03EFXyqMWCw0IK4l0NDlPy1oejYnymyhezrpnk6q + qPl5AI6+AJRDFZ9tRszlG+C9kYmYmkBN+zQLLumChq4ZIdjcVbC5c0xEICsawhEVIUEcR/EEqlxTLMjQ + BbVk5AY19iwQ84K6p/Oo755FHVHTNQv7k1lUd84gGkugzOFhQaYuqHJ7RXc3KHkjqGCd2Vbwa+tAsLol + Y3VTxo/fMhTqiaVxnAVZuqDC6RECOyVUd/rxsMOPqvaPqGxlpvHA7UM54/LigHpSVP/utMBKRi2RxBqn + UdJx2ndBOMVGGCtEmPpQaB9jwWVdUFT7XgjKXT6UPZ6GrcUHW/MUSp1eWGllLI5JmJsmsa/EUVD5hgUG + XXC3+i1U+kE4iVNW1kOCb+thIoSvayEsp9mT48gve82CbF1wp3IUKr2vhRLMjzwoIYobJwgPihomcJ+p + /4B7xG44hjzrCAuMuiC/YhRxEihRFTI1SaY357vuKyr2DmKUGsMuJe+EjhAMxWAyD52uwGQdHMuzjeB2 + 6QhMpcMwWYeRax7GLctQipIh3CRyiwcF1wv6fCQ4+RNpnCEuEFmEIU12GuM/5KTXDOIsAOkvYejd/wM3 + 4EUAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACp0RVh0VGl0 + bGUATGFzdDtBcnJvdztGb3J3YXJkO1NraXA7TmV4dDtSZXdpbmQ7W0SSRQAAAuBJREFUOE+lkllIVFEc + xo+a5b6QSaZIgVE9CFEIKUmpuVQWLaQSLmUTltmGWpZGjWvpIC7jkpMmA5ZGkQ9GaprpuMyMy4ympoRJ + YAmpOTqjjVtf54xzg+itHn733v893/c7l8shAP6L1QshBpQ1egyji5UkSqggvPwuEpnbScIFchL6QEpC + 0jrIqdQ2cpIv+UtgfEM8gCihvDEo6ZkHndcy0dlsOQnLlJHTGR0kOK2d5biN2LqxbtYL1sWWv8fgmAb3 + nn5AaPrbCt/zwh36oKFiYonIxrUsZ5wgVrZE5XeDl93eolvXC0yulfZiehEYnQVq+6YQI1Roj916Xejq + G+2kC67ubpL4ZADTC8C5HDkrmnIC05iSHozP/cSrzyuQjK9AObmM0qYxBCW3znhfquJvcHG3ozmrBHE/ + akYWECGQsqI5JzC7WNCDUfUKKocXUTGoRcWQlga1qB2Zx53KYfjH133ZFZwTF1vWh5cftQjNaGdFS05g + zsvtQv/UMh73/8CjPi0Ke+aQK1cjn1Leq4GocxqROQpcKVGgamiefpmEFa04gUWEQAbp1yUUKOaQ16mB + QKZBevsskt+pkC5RIe3NNwRlSHFB2A1xvxrH7zazojUnsAxJbUPtJy0yO2ZxnxZTWlRIbVWB3ziBYEEX + doZWjm32Sow7kyVDqXIGR243saINJ7A6wZeganAOfLpjSvM0ZQrhQiV2Rz6fdQnISjaz2+5Ac/bBqRIU + dalw8GYjK9pyAuvApGYU96h1Ap5oEHt41Qsuh3JENlt8XOi6KcWQ5Y4mNSFP+h2+sQ1/CGz84hsQWzmK + vdE12Hq4oNreNcyNvjenGFEMEuonWc7c63K1xOd6PTyjXrTS2eL3P9h/tQ7bAos7HNxiAthMYUfWwNmv + jDgeEJFN3g9ZjsksKLb6uxEnYGFWYujOuLN/GXHyFRFHnxLi4PWQbNxXROw9C4mdh5Csd8/X9XRd7uHf + APkFKGYIzpiwM1AAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABt0RVh0VGl0 + bGUATmV4dDtQbGF5O0Fycm93O1JpZ2h0FuQOrgAAAvpJREFUOE+dk31MzHEcxz+HJCSZIVL65xozm8Uf + KiKKYmQW81CLUKloWTWWUJKiu67rwZRVtEoeV5FK57p2PcxdepAlk4e2dNeTo+uc1Nv3l5q7f/229377 + /L6/1+vz++77+REAYhePZQaLCcs0ro7MbqLw7FcUdusVhWY0UrC4gQKF9XRcICe/JBl5x7z4y04KTOKK + 2xGVo2gLSCrdw2pTTnQms5FC0hooSFRHJxnof11GR6/V0MHYavI6V2EkML1Y2Ir3ai1EJR0ITpVJ9kfk + Ok+J3g6NUku/nprUemr8+pN2n3tOnpHlRoJZ0fnNGBodx6fhMdR0DuJCbguOxJYXbvGJXz0lquvR0cuP + WvKIeEbbw8uMBGZRuUqodOOQfR2Fom8UrCsK5d0IEMj1u8/ez1jl4mvD3pvJidxOl5JraImRYPbZLAW6 + h3+j/NNPlH0YQVnXCKRfdKj5PIIbJe+wL7pSs+lYVsyC5WsXTYp4hoI5p9Mb0Tn0C486h1HcoUVB+3fk + tWhwp1mDolYN8pQDCE5XYHPQw+613smBjDE1FMwNSJHjtUqPu29+IKf5O24qviGlYRDXpH2Ik6iQVKuG + uK4fic+74XC4gIPMDQXmvvFSVHVpIawbQLJ8AImyPlyRqnHpRS9iq1VIqOqFn6AeDofyBvnuV2MYY2Yo + mHcgVoIH7RoksI7xL1W4XM1Adk+QqnAiU4n1R/J1fPeENAsbRzsOZplmKLDYG12FbOUQLlapJrrGSdQI + ud0GJ/+iMfsdSfcW8j2545zDMp2FZ+ee8ZedFMzfGfkMwtp+XKjsxZmCDrgEPQTfUyCxWuOzma2bs3Cj + zjtf0UO2rmJa7ppqJLB0CytF1OMusAGBvYeo1XrdSS/23IKF+z94UU97aCrWLkJa6iwwEsxzCXyClbvS + P69wijjFakuWibO2c0sj261istkiYmDKBGjllEyLHZONBNzncd24cGPL9phGK7aJGZzKQBEt2ygkKwYv + 4WDnG7RoQ+I/wf8H9AfzkgPsW69SXwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACF0RVh0VGl0 + bGUAUHJldjtBcnJvdztMZWZ0O0JhY2s7UmV3aW5kCyuHDwAAAvxJREFUOE+d038s1HEcx/F38iOtJfTj + D/4wa5lM6YfIVEutKVn5ES0mUskkJnTlmh/jJE2WyiJynHM//Ii4kPOjK0X5cThMLKXu/D4/wmXTu+/n + cpf+7bbX7v74Ph/f7333/cKdEgkwiiWQUNQDsXwJRHO6IIrVCbQ8MUQy2+F6VhtQn1XUVlNbszwNRAQy + YBRRMRXGcCVAZ3fCTVYH3MgVQ0R2G4RltlLHggY13TO0fHf/ZJHE/14jVcFaNRDP64I4XidMLC6BTPEL + hqmR7+VQ53TY04MXkurrYzkSFPbJ0StRRID1aiCG2wnRBWKY/LkE0oUlEpLL1T5xJcXCN1FYEMXswPKO + MXwvVWCTTIEe8Q3/ArfZYqCz2lWhlr17mJEvo+phRGaLgtckxdaxRaz9Oo+FPTNYMziHrvQ6AuipgeVQ + c5u1o753XCkt+FHzdO7rIWwdVeBb6qyCgTnkd88gq2MKKz7N4kmakFQbVgKaFxPL/AIeNH5JEwygiDqL + aEiBVZ/nsaTvB/Ikf+Ks1knkS6bRMbKaVPorAd2Q9A/Y0D+Nlf2zWNw7qwxy2qaQ2S7HZ21yzPw4gY+b + JjCnZRKPhFaSymAloO15q5DmlVA3HsfrQa5YTsVyZZD2bhxT34zh3YYRZNTK8L5oBA8FVZDKcCVA7oGO + qfVpY4dAZqpLVPUCndOLGc3jmCIaxaT6EYwXDmNstUyJ2AWWk2qjGvCIrlEhygfG1Mbb3NYni3M8UrAU + zu7BpDoZxrySIr3yO0ZXSdHmUhkBNqkBZ1olOEUI4EnzmAoij+w6E7sAeyu3jDqHEAEGs7ox6uU35fb6 + PifAZjVwLPgFHA4qheT6EWDUDkOCcFgFaVHTM7a96mrmnN7lEEpB7D608ikmwBY1cOByMdj5F8I+Hy7s + 8WbDLs982OGRDxbueQQif0ubmqGRTfg1k6Npg5bnCgnw9ybu9+ODzXku7D6bDzs9WGDpngvb3XLB3IUJ + ZqdyYKtTtgoib6HB8rTUgOrH/w3hN+JHFcmyNSXMAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACd0RVh0VGl0 + bGUARmlyc3Q7QXJyb3c7QmFjaztTa2lwO1ByZXY7UmV3aW5kAY6Q1AAAAuRJREFUOE+lk3ss1WEYx98S + MfeU/rDWSkupyDStrcusNFJS1KGrQpLYMdel3JJqYSedMA61Qy5rIrQJdTjkzuEcl9KsZVab4rg7hz++ + ve+xn61/692+v9/zPO/z/Tx7f3t/BMB/aSWIKR4kUQUDJFI8QMLE/YT/QkFCchUkKLuXBGbKyA1hN6Fr + NZUOlS6LNQC6VlGtoWIb2izn58nJ7ZxeciurhwQIZbSkMa51CRYd9k6ql3g9aGFOPQ6gHS3ukQY864Jf + WrOU5jpjCyC/qehicJ1jvqm7eIl1ReEiOSrlSngmNrJNQw6gG1PYD6Ua8BW0a8hUzKjtcDrUghdfkxGS + KVOVdv5C46gaH0fUcIuVsj4jDqAXLe5D1bAaV1NaWcV4q72zqWds5T1/QcdUQdNPdI0toXJYheedcygb + WsCJKImmjwPoh+XJUfZVhUsPm+ESks2/ntY6mlHzHZ0/FtEwuoSCQRUyuueQ0jaLQsUcnMI/MKcJBzAI + yZah5PM8ztOzJRf1ov7bPOpHF/F6SIVcxbJZ0DaDR5+mIZLNwpFfw5ymHMDwprAL4r4ZnIlrQJSoHYXy + aYj7l43pHbOaycnN00ion8TT9ikcDKxmznUcwMjnSRtye6Zw6o4E+zyS+M4R1SNBOX0QtCiRSiffl04i + rkGJmLpxPG6awv6Ad8xpxgGMeUmNyOychEuU5mwbTTfZmdvxMuKPBFVN+2UpkCAZR4xEicjaccTR2N63 + gvWtXwG43ZUgvXUCTmF1rGJKxS6OrrmVi6W1uzDngN9b9ZWsfkS8H0d07QRsL5ezvg0cQN8xuLzxaGgN + DgWUNtHcIFmqZHV2F7TYvrnNBYctxwUV9tfK4JP3Bbu9y5jTnAOwJgMqNpm9tfZ4FZKdHgVkh3s+TVeu + upGZjb+rhaOg3crrDXMuf0T2YNp7sYTY8oqJ9blXxPpsPtnuJibbTr4klq55ZLOziAOx/8WYyoRK+y/A + vwnkDyZtCRwu2eOiAAAAAElFTkSuQmCC + + + + 238, 17 + + \ No newline at end of file diff --git a/类库/UI.Framework/Controls/SettingControl.Designer.cs b/类库/UI.Framework/Controls/SettingControl.Designer.cs new file mode 100644 index 0000000..597b5e7 --- /dev/null +++ b/类库/UI.Framework/Controls/SettingControl.Designer.cs @@ -0,0 +1,92 @@ +namespace UI.Framework.Controls +{ + partial class SettingControl + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.PropertyControl = new DevExpress.XtraVerticalGrid.PropertyGridControl(); + this.propertyDescriptionControl1 = new DevExpress.XtraVerticalGrid.PropertyDescriptionControl(); + this.labelControl1 = new DevExpress.XtraEditors.LabelControl(); + ((System.ComponentModel.ISupportInitialize)(this.PropertyControl)).BeginInit(); + this.SuspendLayout(); + // + // PropertyControl + // + this.PropertyControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.PropertyControl.Location = new System.Drawing.Point(0, 0); + this.PropertyControl.Name = "PropertyControl"; + this.PropertyControl.OptionsBehavior.ResizeRowHeaders = false; + this.PropertyControl.RecordWidth = 140; + this.PropertyControl.RowHeaderWidth = 60; + this.PropertyControl.Size = new System.Drawing.Size(587, 376); + this.PropertyControl.TabIndex = 0; + // + // propertyDescriptionControl1 + // + this.propertyDescriptionControl1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.propertyDescriptionControl1.Location = new System.Drawing.Point(0, 382); + this.propertyDescriptionControl1.Name = "propertyDescriptionControl1"; + this.propertyDescriptionControl1.PropertyGrid = this.PropertyControl; + this.propertyDescriptionControl1.Size = new System.Drawing.Size(590, 80); + this.propertyDescriptionControl1.TabIndex = 1; + this.propertyDescriptionControl1.TabStop = false; + // + // labelControl1 + // + this.labelControl1.Appearance.BackColor = System.Drawing.Color.White; + this.labelControl1.Appearance.Font = new System.Drawing.Font("Tahoma", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelControl1.Appearance.Options.UseBackColor = true; + this.labelControl1.Appearance.Options.UseFont = true; + this.labelControl1.Location = new System.Drawing.Point(201, 129); + this.labelControl1.Name = "labelControl1"; + this.labelControl1.Size = new System.Drawing.Size(148, 19); + this.labelControl1.TabIndex = 2; + this.labelControl1.Text = "正在读取配置信息...."; + this.labelControl1.Visible = false; + // + // SettingControl + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.Controls.Add(this.labelControl1); + this.Controls.Add(this.propertyDescriptionControl1); + this.Controls.Add(this.PropertyControl); + this.Name = "SettingControl"; + this.Size = new System.Drawing.Size(590, 462); + ((System.ComponentModel.ISupportInitialize)(this.PropertyControl)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private DevExpress.XtraVerticalGrid.PropertyDescriptionControl propertyDescriptionControl1; + public DevExpress.XtraVerticalGrid.PropertyGridControl PropertyControl; + private DevExpress.XtraEditors.LabelControl labelControl1; + } +} diff --git a/类库/UI.Framework/Controls/SettingControl.cs b/类库/UI.Framework/Controls/SettingControl.cs new file mode 100644 index 0000000..601b39e --- /dev/null +++ b/类库/UI.Framework/Controls/SettingControl.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; + +namespace UI.Framework.Controls +{ + public partial class SettingControl : DevExpress.XtraEditors.XtraUserControl + { + public SettingControl() + { + InitializeComponent(); + } + /// + /// 绑定对象 + /// + /// + public void Bind(Object obj, int descriptionHeight = 90) + { + try + { + this.PropertyControl.Height = this.Height - (descriptionHeight + 5); + this.propertyDescriptionControl1.Height = descriptionHeight; + this.PropertyControl.SelectedObject = obj; + } + catch (Exception) + { } + } + + /// + /// 绑定对象组 + /// + /// + public void Bind(Object[] objs) + { + labelControl1.Visible = true; + this.PropertyControl.SelectedObjects = objs; + labelControl1.Visible = false; + } + } +} diff --git a/类库/UI.Framework/Controls/SettingControl.resx b/类库/UI.Framework/Controls/SettingControl.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/UI.Framework/Controls/SettingControl.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/UI.Framework/Entitys/DataViewAtrribute.cs b/类库/UI.Framework/Entitys/DataViewAtrribute.cs new file mode 100644 index 0000000..f4722c2 --- /dev/null +++ b/类库/UI.Framework/Entitys/DataViewAtrribute.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UI.Framework.Entitys +{ + public class DataViewAtrribute: Attribute + { + /// + /// 显示名称 + /// + public string Name { get; set; } + + /// + /// 宽度 + /// + public int Width { get; set; } + + + } +} diff --git a/类库/UI.Framework/Entitys/MyTypeConverter.cs b/类库/UI.Framework/Entitys/MyTypeConverter.cs new file mode 100644 index 0000000..79d00e1 --- /dev/null +++ b/类库/UI.Framework/Entitys/MyTypeConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UI.Framework.Entitys +{ + public class MyTypeConverter : TypeConverter + { + + public virtual string[] GetValues() + { + return new string[] { "请继承MyTypeConverter,并重写GetValues!" }; + } + public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) + { + + return new StandardValuesCollection(GetValues()); //编辑下拉框中的items + } + + //true: disable text editting. false: enable text editting; + public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) + { + return false; + } + + public override bool GetStandardValuesSupported(ITypeDescriptorContext context) + { + return true; + } + } + + } diff --git a/类库/UI.Framework/Entitys/PropertyGridRichText.cs b/类库/UI.Framework/Entitys/PropertyGridRichText.cs new file mode 100644 index 0000000..43b9028 --- /dev/null +++ b/类库/UI.Framework/Entitys/PropertyGridRichText.cs @@ -0,0 +1,70 @@ +using DevExpress.XtraRichEdit; +using System; +using System.Collections.Generic; +using System.Drawing.Design; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows.Forms.Design; + +namespace UI.Framework.Entitys +{ + /// + /// PropertyGridMutiText 的摘要说明。 + /// + + public class PropertyGridRichText : PropertyGridEditStyle + { + + + public PropertyGridRichText() + { + RichEditControl box = new RichEditControl(); + box.ActiveViewType = DevExpress.XtraRichEdit.RichEditViewType.Simple; + Control = box; + } + + public override string GetValue() + { + return Control.Text; + } + + public override void SetValue(object value) + { + Control.Text = value as string; + } + } + + + public abstract class PropertyGridEditStyle : UITypeEditor + { + protected UITypeEditorEditStyle UITypeEditorEditStyle = UITypeEditorEditStyle.DropDown; + protected Control Control = null; + public abstract string GetValue(); + public abstract void SetValue(object value); + public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context) + { + return UITypeEditorEditStyle; + } + + public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value) + { + try + { + IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService)); + if (edSvc != null) + { + SetValue(value); + if(UITypeEditorEditStyle == UITypeEditorEditStyle.DropDown) edSvc.DropDownControl(Control); + return GetValue(); + } + } + catch (Exception ) + { + return value; + } + return value; + } + } +} diff --git a/类库/UI.Framework/Forms/BaseForm.Designer.cs b/类库/UI.Framework/Forms/BaseForm.Designer.cs new file mode 100644 index 0000000..bb370f0 --- /dev/null +++ b/类库/UI.Framework/Forms/BaseForm.Designer.cs @@ -0,0 +1,54 @@ +namespace UI.Framework.Forms +{ + partial class BaseForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.Loding = new DevExpress.XtraSplashScreen.SplashScreenManager(this, typeof(global::UI.Framework.Forms.LodingForm), true, true); + this.SuspendLayout(); + // + // Loding + // + this.Loding.ClosingDelay = 500; + // + // BaseForm + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(284, 261); + this.Name = "BaseForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "BaseForm"; + this.Load += new System.EventHandler(this.BaseForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + protected DevExpress.XtraSplashScreen.SplashScreenManager Loding; + } +} \ No newline at end of file diff --git a/类库/UI.Framework/Forms/BaseForm.cs b/类库/UI.Framework/Forms/BaseForm.cs new file mode 100644 index 0000000..8b21810 --- /dev/null +++ b/类库/UI.Framework/Forms/BaseForm.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; + +namespace UI.Framework.Forms +{ + public partial class BaseForm : DevExpress.XtraEditors.XtraForm + { + public BaseForm() + { + InitializeComponent(); + if (PublickIcon != null) this.Icon = PublickIcon; + } + + private void BaseForm_Load(object sender, EventArgs e) + { + } + + + /// + /// 代理委托更新UI + /// + /// + protected delegate void DelegateUpdateUI(Action act); + + /// + /// 代理委托更新UI + /// + /// + protected void UpdateUI(Action act) + { + try + { + if (!InvokeRequired) + { + act.Invoke(); + } + else + { + DelegateUpdateUI delegateUpdateUI = new DelegateUpdateUI(UpdateUI); + Invoke(delegateUpdateUI, act); + } + } + catch (Exception ex) + { } + } + public static void ShowSuccess(string message, string title = "友情提示") + { + XtraMessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + public static void ShowError(Exception ex, string title = "系统错误") + { + //var messagebox_param = new XtraMessageBoxArgs(); + //messagebox_param.AutoCloseOptions.ShowTimerOnDefaultButton = true; + //messagebox_param.AutoCloseOptions.Delay = 5000; + //messagebox_param.Caption = title; + //messagebox_param.Text = ex.Message; + + //XtraMessageBox.Show(messagebox_param); + + XtraMessageBox.Show(ex.Message, title, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + public static void ShowError(string message, string title = "系统错误") + { + XtraMessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + public static void ShowErrorAutoClose(Exception ex, int secondtime = 5000, string title = "系统错误") + { + XtraMessageBoxArgs args = new XtraMessageBoxArgs(); + args.AutoCloseOptions.Delay = secondtime; + args.Caption = $"{title} - {(secondtime / 1000)}秒后自动关闭"; + args.Text = $@"{ex.Message}"; + args.Buttons = new DialogResult[] { DialogResult.OK }; + XtraMessageBox.Show(args).ToString(); + } + + public static void ShowErrorAutoClose(string message, int secondtime = 5000, string title = "系统错误") + { + XtraMessageBoxArgs args = new XtraMessageBoxArgs(); + args.AutoCloseOptions.Delay = secondtime; + args.Caption = $"{title} - {(secondtime / 1000)}秒后自动关闭"; + args.Text = $@"{message}"; + args.Buttons = new DialogResult[] { DialogResult.OK }; + XtraMessageBox.Show(args).ToString(); + } + + public static void ShowSuccessAutoClose(string message, int secondtime = 5000, string title = "友情提示") + { + XtraMessageBoxArgs args = new XtraMessageBoxArgs(); + args.AutoCloseOptions.Delay = secondtime; + args.Caption = $"{title} - {(secondtime / 1000)}秒后自动关闭"; + args.Text = $@"{message}"; + args.Buttons = new DialogResult[] { DialogResult.OK }; + XtraMessageBox.Show(args).ToString(); + } + + public static DialogResult ShowSuccessAutoClose(string message, DialogResult[] dialogResults, int defaultButtonIndex = 1, int secondtime = 5000, string title = "友情提示") + { + XtraMessageBoxArgs args = new XtraMessageBoxArgs(); + args.AutoCloseOptions.Delay = secondtime; + args.Caption = $"{title} - {(secondtime / 1000)}秒后自动关闭"; + args.Text = $@"{message}"; + args.Buttons = dialogResults;// new DialogResult[] { DialogResult.OK, DialogResult.Cancel }; + args.DefaultButtonIndex = defaultButtonIndex; + args.AutoCloseOptions.ShowTimerOnDefaultButton = true; + return XtraMessageBox.Show(args); + } + + public static Icon PublickIcon { get; private set; } + public static void SetIcon(Icon icon) + { + PublickIcon = icon; + } + + } +} \ No newline at end of file diff --git a/类库/UI.Framework/Forms/BaseForm.resx b/类库/UI.Framework/Forms/BaseForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/UI.Framework/Forms/BaseForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/UI.Framework/Forms/LodingForm.Designer.cs b/类库/UI.Framework/Forms/LodingForm.Designer.cs new file mode 100644 index 0000000..53f39a2 --- /dev/null +++ b/类库/UI.Framework/Forms/LodingForm.Designer.cs @@ -0,0 +1,66 @@ +namespace UI.Framework.Forms +{ + partial class LodingForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.ProgressPanel = new DevExpress.XtraWaitForm.ProgressPanel(); + this.SuspendLayout(); + // + // ProgressPanel + // + this.ProgressPanel.Appearance.BackColor = System.Drawing.Color.Transparent; + this.ProgressPanel.Appearance.Options.UseBackColor = true; + this.ProgressPanel.BarAnimationElementThickness = 2; + this.ProgressPanel.Caption = "正在加载,请稍等..."; + this.ProgressPanel.ContentAlignment = System.Drawing.ContentAlignment.BottomCenter; + this.ProgressPanel.Description = ""; + this.ProgressPanel.Dock = System.Windows.Forms.DockStyle.Fill; + this.ProgressPanel.Location = new System.Drawing.Point(0, 0); + this.ProgressPanel.Name = "ProgressPanel"; + this.ProgressPanel.Size = new System.Drawing.Size(240, 50); + this.ProgressPanel.TabIndex = 0; + this.ProgressPanel.WaitAnimationType = DevExpress.Utils.Animation.WaitingAnimatorType.Bar; + // + // LodingForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(240, 50); + this.Controls.Add(this.ProgressPanel); + this.Name = "LodingForm"; + this.Text = "LodingForm"; + this.Load += new System.EventHandler(this.LodingForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private DevExpress.XtraWaitForm.ProgressPanel ProgressPanel; + } +} \ No newline at end of file diff --git a/类库/UI.Framework/Forms/LodingForm.cs b/类库/UI.Framework/Forms/LodingForm.cs new file mode 100644 index 0000000..c4a19c1 --- /dev/null +++ b/类库/UI.Framework/Forms/LodingForm.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; +using DevExpress.XtraWaitForm; +using System.Runtime.InteropServices; + +namespace UI.Framework.Forms +{ + public partial class LodingForm : WaitForm + { + public LodingForm() + { + InitializeComponent(); + } + + private void LodingForm_Load(object sender, EventArgs e) + { + this.ProgressPanel.MouseMove += MouseMove; + this.ProgressPanel.MouseDown += MouseDown; + this.ProgressPanel.MouseUp += MouseUp; + } + + [DllImport("user32.dll")] + public static extern bool ReleaseCapture(); + [DllImport("user32.dll")] + public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam); + + + + bool beginMove = false;//初始化鼠标位置 + int currentXPosition; + int currentYPosition; + + //获取鼠标按下时的位置 + private new void MouseDown(object sender, MouseEventArgs e) + { + try + { + if (e.Button == MouseButtons.Left) + { + beginMove = true; + currentXPosition = MousePosition.X;//鼠标的x坐标为当前窗体左上角x坐标 + currentYPosition = MousePosition.Y;//鼠标的y坐标为当前窗体左上角y坐标 + } + } + catch (Exception) + { } + } + + //获取鼠标移动到的位置 + private new void MouseMove(object sender, MouseEventArgs e) + { + try + { + if (beginMove) + { + this.Left += MousePosition.X - currentXPosition;//根据鼠标x坐标确定窗体的左边坐标x + this.Top += MousePosition.Y - currentYPosition;//根据鼠标的y坐标窗体的顶部,即Y坐标 + currentXPosition = MousePosition.X; + currentYPosition = MousePosition.Y; + } + } + catch (Exception) + { } + } + + //释放鼠标时的位置 + private new void MouseUp(object sender, MouseEventArgs e) + { + try + { + if (e.Button == MouseButtons.Left) + { + currentXPosition = 0; //设置初始状态 + currentYPosition = 0; + beginMove = false; + } + } + catch (Exception) + { } + } + } +} \ No newline at end of file diff --git a/类库/UI.Framework/Forms/LodingForm.resx b/类库/UI.Framework/Forms/LodingForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/类库/UI.Framework/Forms/LodingForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/UI.Framework/Forms/SetTingForm.Designer.cs b/类库/UI.Framework/Forms/SetTingForm.Designer.cs new file mode 100644 index 0000000..527bd71 --- /dev/null +++ b/类库/UI.Framework/Forms/SetTingForm.Designer.cs @@ -0,0 +1,58 @@ +namespace UI.Framework.Forms +{ + partial class SettingForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.propertyGrid1 = new System.Windows.Forms.PropertyGrid(); + this.SuspendLayout(); + // + // propertyGrid1 + // + this.propertyGrid1.Dock = System.Windows.Forms.DockStyle.Fill; + this.propertyGrid1.Location = new System.Drawing.Point(0, 0); + this.propertyGrid1.Name = "propertyGrid1"; + this.propertyGrid1.Size = new System.Drawing.Size(469, 423); + this.propertyGrid1.TabIndex = 0; + // + // SettingForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 14F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(469, 423); + this.Controls.Add(this.propertyGrid1); + this.Name = "SettingForm"; + this.Text = "SetingForm"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PropertyGrid propertyGrid1; + } +} \ No newline at end of file diff --git a/类库/UI.Framework/Forms/SetTingForm.resx b/类库/UI.Framework/Forms/SetTingForm.resx new file mode 100644 index 0000000..9bcc643 --- /dev/null +++ b/类库/UI.Framework/Forms/SetTingForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/类库/UI.Framework/Forms/SettingForm.cs b/类库/UI.Framework/Forms/SettingForm.cs new file mode 100644 index 0000000..590dcf3 --- /dev/null +++ b/类库/UI.Framework/Forms/SettingForm.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using DevExpress.XtraEditors; + +namespace UI.Framework.Forms +{ + public partial class SettingForm : BaseForm + { + public SettingForm(object obj) + { + try + { + InitializeComponent(); + this.propertyGrid1.SelectedObject = obj; + } + catch (Exception) + { } + } + } +} \ No newline at end of file diff --git a/类库/UI.Framework/Forms/UIExtend.cs b/类库/UI.Framework/Forms/UIExtend.cs new file mode 100644 index 0000000..1eb1978 --- /dev/null +++ b/类库/UI.Framework/Forms/UIExtend.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace UI.Framework.Forms +{ + public static class UIExtend + { + + /// + /// 刷新控件 + /// + /// + /// + public static void RefreshContral(this Control parent, int top = 10) + { + try + { + List controls = new List(); + foreach (Control item in parent.Controls) + { + controls.Add(item); + } + parent.Controls.Clear(); + foreach (Control item in controls) + { + parent.AddContral(item, top); + } + } + catch (Exception) + { } + } + /// + /// 删除Control + /// + /// + public static void RemoveContral(this Control cur) + { + try + { + var p = cur.Parent; + var top = cur.Top; + if (p == null) return; + p.Controls.Remove(cur); + if (p.Controls.Count > 0) + p.RefreshContral(); + } + catch (Exception) + { } + } + /// + /// 添加Control + /// + /// 需要添加 + /// 父容器 + public static void AddContral(this Control parent, Control add, int top = 20) + { + try + { + int addwidth = add.Width; + + //每行多少个 + int number = parent.Width / addwidth;//总宽度/控件宽度 + if (number == 0) return; + //每行间距 + int left = parent.Width % addwidth / (number + 1);//总剩余空间/总个数 + + //计算出总宽度、总高度 + int sumLeft = 0, sumpTop = 0; + int rowIndex = parent.Controls.Count / number; + sumpTop = top * rowIndex + add.Height * rowIndex + top; + + int leftIndex = parent.Controls.Count % number; + sumLeft = left * leftIndex + addwidth * leftIndex + left; + + if (sumLeft == 0) sumLeft = 10; + + add.Parent = parent; + add.Top = sumpTop; + add.Left = sumLeft; + + parent.Controls.Add(add); + } + catch (Exception) + { } + } + + + /// + /// 添加Controls + /// + /// 需要添加集合 + /// 父容器 + public static void AddContrals(this Control parent, Control[] adds, int top = 20) + { + try + { + foreach (var add in adds) + { + int addwidth = add.Width + 10; + + //每行多少个 + int number = parent.Width / addwidth;//总宽度/控件宽度 + if (number == 0) return; + //每行间距 + int left = parent.Width % addwidth / (number + 2);//总剩余空间/总个数 + + //计算出总宽度、总高度 + int sumLeft = 0, sumpTop = 0; + int rowIndex = parent.Controls.Count / number; + sumpTop = top * rowIndex + add.Height * rowIndex + top; + + int leftIndex = parent.Controls.Count % number; + sumLeft = left * leftIndex + addwidth * leftIndex + left; + + add.Parent = parent; + add.Top = sumpTop; + add.Left = sumLeft; + } + + parent.Controls.AddRange(adds); + } + catch (Exception) + { } + } + + } +} diff --git a/类库/UI.Framework/Properties/AssemblyInfo.cs b/类库/UI.Framework/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0a2a644 --- /dev/null +++ b/类库/UI.Framework/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("UI.Framework")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("UI.Framework")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("f865d881-b9d2-4c90-9ad0-0667103827f6")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/类库/UI.Framework/Properties/Resources.Designer.cs b/类库/UI.Framework/Properties/Resources.Designer.cs new file mode 100644 index 0000000..9f1c7b5 --- /dev/null +++ b/类库/UI.Framework/Properties/Resources.Designer.cs @@ -0,0 +1,183 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace UI.Framework.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UI.Framework.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckoff1 { + get { + object obj = ResourceManager.GetObject("btncheckoff1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckoff2 { + get { + object obj = ResourceManager.GetObject("btncheckoff2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckoff3 { + get { + object obj = ResourceManager.GetObject("btncheckoff3", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckoff4 { + get { + object obj = ResourceManager.GetObject("btncheckoff4", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckoff5 { + get { + object obj = ResourceManager.GetObject("btncheckoff5", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckoff6 { + get { + object obj = ResourceManager.GetObject("btncheckoff6", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckon1 { + get { + object obj = ResourceManager.GetObject("btncheckon1", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckon2 { + get { + object obj = ResourceManager.GetObject("btncheckon2", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckon3 { + get { + object obj = ResourceManager.GetObject("btncheckon3", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckon4 { + get { + object obj = ResourceManager.GetObject("btncheckon4", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckon5 { + get { + object obj = ResourceManager.GetObject("btncheckon5", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap btncheckon6 { + get { + object obj = ResourceManager.GetObject("btncheckon6", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/类库/UI.Framework/Properties/Resources.resx b/类库/UI.Framework/Properties/Resources.resx new file mode 100644 index 0000000..1dc08ea --- /dev/null +++ b/类库/UI.Framework/Properties/Resources.resx @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\btncheckoff1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckoff2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckoff3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckoff4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckoff5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckoff6.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckon1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckon2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckon3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckon4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckon5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\btncheckon6.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/类库/UI.Framework/Properties/licenses.licx b/类库/UI.Framework/Properties/licenses.licx new file mode 100644 index 0000000..3a17da8 --- /dev/null +++ b/类库/UI.Framework/Properties/licenses.licx @@ -0,0 +1,4 @@ +DevExpress.XtraVerticalGrid.PropertyDescriptionControl, DevExpress.XtraVerticalGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraBars.BarManager, DevExpress.XtraBars.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraEditors.TextEdit, DevExpress.XtraEditors.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a +DevExpress.XtraVerticalGrid.PropertyGridControl, DevExpress.XtraVerticalGrid.v19.2, Version=19.2.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a diff --git a/类库/UI.Framework/Resources/btncheckoff1.png b/类库/UI.Framework/Resources/btncheckoff1.png new file mode 100644 index 0000000..bfa8ebb Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckoff1.png differ diff --git a/类库/UI.Framework/Resources/btncheckoff2.png b/类库/UI.Framework/Resources/btncheckoff2.png new file mode 100644 index 0000000..a3954e0 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckoff2.png differ diff --git a/类库/UI.Framework/Resources/btncheckoff3.png b/类库/UI.Framework/Resources/btncheckoff3.png new file mode 100644 index 0000000..3f53684 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckoff3.png differ diff --git a/类库/UI.Framework/Resources/btncheckoff4.png b/类库/UI.Framework/Resources/btncheckoff4.png new file mode 100644 index 0000000..2e39e0c Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckoff4.png differ diff --git a/类库/UI.Framework/Resources/btncheckoff5.png b/类库/UI.Framework/Resources/btncheckoff5.png new file mode 100644 index 0000000..d6a9496 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckoff5.png differ diff --git a/类库/UI.Framework/Resources/btncheckoff6.png b/类库/UI.Framework/Resources/btncheckoff6.png new file mode 100644 index 0000000..a9c0136 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckoff6.png differ diff --git a/类库/UI.Framework/Resources/btncheckon1.png b/类库/UI.Framework/Resources/btncheckon1.png new file mode 100644 index 0000000..2bab009 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckon1.png differ diff --git a/类库/UI.Framework/Resources/btncheckon2.png b/类库/UI.Framework/Resources/btncheckon2.png new file mode 100644 index 0000000..27beb42 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckon2.png differ diff --git a/类库/UI.Framework/Resources/btncheckon3.png b/类库/UI.Framework/Resources/btncheckon3.png new file mode 100644 index 0000000..5741c29 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckon3.png differ diff --git a/类库/UI.Framework/Resources/btncheckon4.png b/类库/UI.Framework/Resources/btncheckon4.png new file mode 100644 index 0000000..47317d7 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckon4.png differ diff --git a/类库/UI.Framework/Resources/btncheckon5.png b/类库/UI.Framework/Resources/btncheckon5.png new file mode 100644 index 0000000..dca751e Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckon5.png differ diff --git a/类库/UI.Framework/Resources/btncheckon6.png b/类库/UI.Framework/Resources/btncheckon6.png new file mode 100644 index 0000000..4e9e338 Binary files /dev/null and b/类库/UI.Framework/Resources/btncheckon6.png differ diff --git a/类库/UI.Framework/Tools/PickBox.cs b/类库/UI.Framework/Tools/PickBox.cs new file mode 100644 index 0000000..5f45dee --- /dev/null +++ b/类库/UI.Framework/Tools/PickBox.cs @@ -0,0 +1,299 @@ +using System; +using System.Windows.Forms; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace UI.Framework.Tools +{ + /// + /// ʵ˷ּƶ + /// ͼοƵʱ༭ + /// + public class PickBox + { + ////////////////////////////////////////////////////////////////// + // ˽˳ͱ + ////////////////////////////////////////////////////////////////// + + private const int BOX_SIZE = 8; + private Color BOX_COLOR = Color.White; + //private ContainerControl m_container; + private Control m_control; + private Label[] lbl = new Label[8]; + private int startl; + private int startt; + private int startw; + private int starth; + private int startx; + private int starty; + private bool dragging; + private Cursor[] arrArrow = new Cursor[] {Cursors.SizeNWSE, Cursors.SizeNS, + Cursors.SizeNESW, Cursors.SizeWE, Cursors.SizeNWSE, Cursors.SizeNS, + Cursors.SizeNESW, Cursors.SizeWE}; + private Cursor oldCursor; + + private const int MIN_SIZE = 20; + + public static Image ResizeImage(Image imgToResize, Size size) + { + //ȡͼƬ + int sourceWidth = imgToResize.Width; + //ȡͼƬ߶ + int sourceHeight = imgToResize.Height; + + float nPercent = 0; + float nPercentW = 0; + float nPercentH = 0; + //ȵű + nPercentW = ((float)size.Width / (float)sourceWidth); + //߶ȵű + nPercentH = ((float)size.Height / (float)sourceHeight); + + if (nPercentH < nPercentW) + nPercent = nPercentH; + else + nPercent = nPercentW; + //Ŀ + int destWidth = (int)(sourceWidth * nPercent); + //ĸ߶ + int destHeight = (int)(sourceHeight * nPercent); + + Bitmap b = new Bitmap(destWidth, destHeight); + using (Graphics g = Graphics.FromImage((Image)b)) + { + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + //ͼ + g.DrawImage(imgToResize, 0, 0, destWidth, destHeight); + } + return (Image)b; + } + + public PickBox() + { + for (int i = 0; i < 8; i++) + { + lbl[i] = new Label(); + lbl[i].TabIndex = i; + lbl[i].FlatStyle = 0; + lbl[i].BorderStyle = BorderStyle.FixedSingle; + lbl[i].BackColor = BOX_COLOR; + lbl[i].Cursor = arrArrow[i]; + lbl[i].Text = ""; + lbl[i].BringToFront(); + lbl[i].MouseDown += new MouseEventHandler(this.lbl_MouseDown); + lbl[i].MouseMove += new MouseEventHandler(this.lbl_MouseMove); + lbl[i].MouseUp += new MouseEventHandler(this.lbl_MouseUp); + } + } + + public void RemoveSelect() + { + try + { + if (lbl != null && m_control != null) + { + for (int i = 0; i < 8; i++) + { + //lbl[i].BorderStyle = BorderStyle.None; + //lbl[i].MouseDown -= new MouseEventHandler(this.lbl_MouseDown); + //lbl[i].MouseMove -= new MouseEventHandler(this.lbl_MouseMove); + //lbl[i].MouseUp -= new MouseEventHandler(this.lbl_MouseUp); + m_control.Parent.Controls.Remove(lbl[i]); + } + } + } + catch { } + } + + + public void WireControl(Control ctl) + { + ctl.Click += new EventHandler(this.SelectControl); + } + + + ///////////////////////////////////////////////////////////////// + // ˽з + ///////////////////////////////////////////////////////////////// + + // + // һѡ򸽼ӵͷؼ + // + private void SelectControl(object sender, EventArgs e) + { + + if (m_control is Control) + { + m_control.Cursor = oldCursor; + + //ɾ฽κѴڵ¼ + m_control.MouseDown -= new MouseEventHandler(this.ctl_MouseDown); + m_control.MouseMove -= new MouseEventHandler(this.ctl_MouseMove); + m_control.MouseUp -= new MouseEventHandler(this.ctl_MouseUp); + + m_control = null; + } + + m_control = (Control)sender; + //ΪƶѡĿؼ¼ + m_control.MouseDown += new MouseEventHandler(this.ctl_MouseDown); + m_control.MouseMove += new MouseEventHandler(this.ctl_MouseMove); + m_control.MouseUp += new MouseEventHandler(this.ctl_MouseUp); + + //Add sizing handles to Control's container (Form or PictureBox) + for (int i = 0; i < 8; i++) + { + m_control.Parent.Controls.Add(lbl[i]); + lbl[i].BringToFront(); + } + + //λõ + MoveHandles(); + + //ʾּ + ShowHandles(); + + oldCursor = m_control.Cursor; + m_control.Cursor = Cursors.SizeAll; + + } + + public void Remove() + { + HideHandles(); + m_control.Cursor = oldCursor; + } + + private void ShowHandles() + { + if (m_control != null) + { + for (int i = 0; i < 8; i++) + { + lbl[i].Visible = true; + } + } + } + + private void HideHandles() + { + for (int i = 0; i < 8; i++) + { + lbl[i].Visible = false; + } + } + + private void MoveHandles() + { + int sX = m_control.Left - BOX_SIZE; + int sY = m_control.Top - BOX_SIZE; + int sW = m_control.Width + BOX_SIZE; + int sH = m_control.Height + BOX_SIZE; + int hB = BOX_SIZE / 2; + int[] arrPosX = new int[] {sX+hB, sX + sW / 2, sX + sW-hB, sX + sW-hB, + sX + sW-hB, sX + sW / 2, sX+hB, sX+hB}; + int[] arrPosY = new int[] {sY+hB, sY+hB, sY+hB, sY + sH / 2, sY + sH-hB, + sY + sH-hB, sY + sH-hB, sY + sH / 2}; + for (int i = 0; i < 8; i++) + lbl[i].SetBounds(arrPosX[i], arrPosY[i], BOX_SIZE, BOX_SIZE); + } + + private void lbl_MouseDown(object sender, MouseEventArgs e) + { + dragging = true; + startl = m_control.Left; + startt = m_control.Top; + startw = m_control.Width; + starth = m_control.Height; + HideHandles(); + } + private void lbl_MouseMove(object sender, MouseEventArgs e) + { + int l = m_control.Left; + int w = m_control.Width; + int t = m_control.Top; + int h = m_control.Height; + if (dragging) + { + switch (((Label)sender).TabIndex) + { + case 0: // ϶ϵķּ + l = startl + e.X < startl + startw - MIN_SIZE ? startl + e.X : startl + startw - MIN_SIZE; + t = startt + e.Y < startt + starth - MIN_SIZE ? startt + e.Y : startt + starth - MIN_SIZE; + w = startl + startw - m_control.Left; + h = startt + starth - m_control.Top; + break; + case 1: // ϶Ϸּ + t = startt + e.Y < startt + starth - MIN_SIZE ? startt + e.Y : startt + starth - MIN_SIZE; + h = startt + starth - m_control.Top; + break; + case 2: // ϶ϵķּ + w = startw + e.X > MIN_SIZE ? startw + e.X : MIN_SIZE; + t = startt + e.Y < startt + starth - MIN_SIZE ? startt + e.Y : startt + starth - MIN_SIZE; + h = startt + starth - m_control.Top; + break; + case 3: // ϶ҲмСĺ + w = startw + e.X > MIN_SIZE ? startw + e.X : MIN_SIZE; + break; + case 4: // ϶right-bottomּ + w = startw + e.X > MIN_SIZE ? startw + e.X : MIN_SIZE; + h = starth + e.Y > MIN_SIZE ? starth + e.Y : MIN_SIZE; + break; + case 5: // ϶²ּ + h = starth + e.Y > MIN_SIZE ? starth + e.Y : MIN_SIZE; + break; + case 6: // ϶½ǴС + l = startl + e.X < startl + startw - MIN_SIZE ? startl + e.X : startl + startw - MIN_SIZE; + w = startl + startw - m_control.Left; + h = starth + e.Y > MIN_SIZE ? starth + e.Y : MIN_SIZE; + break; + case 7: //϶ʩ + l = startl + e.X < startl + startw - MIN_SIZE ? startl + e.X : startl + startw - MIN_SIZE; + w = startl + startw - m_control.Left; + break; + } + l = (l < 0) ? 0 : l; + t = (t < 0) ? 0 : t; + m_control.SetBounds(l, t, w, h); + } + } + private void lbl_MouseUp(object sender, MouseEventArgs e) + { + dragging = false; + MoveHandles(); + ShowHandles(); + } + + private void ctl_MouseDown(object sender, MouseEventArgs e) + { + dragging = true; + startx = e.X; + starty = e.Y; + HideHandles(); + } + private void ctl_MouseMove(object sender, MouseEventArgs e) + { + if (dragging) + { + int l = m_control.Left + e.X - startx; + int t = m_control.Top + e.Y - starty; + int w = m_control.Width; + int h = m_control.Height; + l = (l < 0) ? 0 : ((l + w > m_control.Parent.ClientRectangle.Width) ? + m_control.Parent.ClientRectangle.Width - w : l); + t = (t < 0) ? 0 : ((t + h > m_control.Parent.ClientRectangle.Height) ? + m_control.Parent.ClientRectangle.Height - h : t); + m_control.Left = l; + m_control.Top = t; + } + } + private void ctl_MouseUp(object sender, MouseEventArgs e) + { + dragging = false; + MoveHandles(); + ShowHandles(); + } + + } +} + diff --git a/类库/UI.Framework/Tools/RichTextBoxEx.cs b/类库/UI.Framework/Tools/RichTextBoxEx.cs new file mode 100644 index 0000000..640b94d --- /dev/null +++ b/类库/UI.Framework/Tools/RichTextBoxEx.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace UI.Framework.Tools +{ + public static class RichTextBoxEx + { + /// + /// 文本控件方法扩展 + /// + /// + /// 控件内容 + /// 显示的颜色 + /// 是否换行 + public static void AppendTextColorful(this RichTextBox rtBox, string text, Color color, bool addNewLine = true) + { + if (addNewLine) + text += Environment.NewLine; + rtBox.SelectionStart = rtBox.TextLength; + rtBox.SelectionLength = 0; + rtBox.SelectionColor = color; + rtBox.AppendText(text); + rtBox.SelectionColor = rtBox.ForeColor; + } + } +} diff --git a/类库/UI.Framework/UI.Framework.csproj b/类库/UI.Framework/UI.Framework.csproj new file mode 100644 index 0000000..9c2b982 --- /dev/null +++ b/类库/UI.Framework/UI.Framework.csproj @@ -0,0 +1,186 @@ + + + + + Debug + AnyCPU + {F865D881-B9D2-4C90-9AD0-0667103827F6} + Library + Properties + UI.Framework + UI.Framework + v4.6.1 + 512 + + + true + full + false + ..\..\Debug\ + DEBUG;TRACE + prompt + 4 + ..\..\Debug\UI.Framework.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + False + + + + + + + + + + False + + + + + + + + + + + + + + + UserControl + + + ButtonCheck.cs + + + UserControl + + + GridPageControl.cs + + + UserControl + + + PageControl.cs + + + + + UserControl + + + SettingControl.cs + + + + + Form + + + BaseForm.cs + + + Form + + + LodingForm.cs + + + Form + + + SettingForm.cs + + + + + True + True + Resources.resx + + + + + + ButtonCheck.cs + + + GridPageControl.cs + + + PageControl.cs + Designer + + + SettingControl.cs + + + BaseForm.cs + + + LodingForm.cs + + + SettingForm.cs + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/类库/Update/Client.cs b/类库/Update/Client.cs new file mode 100644 index 0000000..dba0b9a --- /dev/null +++ b/类库/Update/Client.cs @@ -0,0 +1,371 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using System.Xml; + +namespace OnlineUpdate +{ + public class UpdateClass + { + public string Name { get; set; } + public string Url { get; set; } + public string Version { get; set; } + public List Message { get; set; } + } + public class Client + { + + static string Path = System.IO.Directory.GetCurrentDirectory(); + static string XMLPath = string.Empty; + + static Client() + { + XMLPath = Path + "\\OnlineUpdate.xml"; + if (!File.Exists(XMLPath)) + { + var old_path = Path + "\\LevelUpdate.xml"; + if (!File.Exists(old_path)) throw new Exception("丢失【OnlineUpdate.xml】更新包文件!"); + else + { + if (File.Exists(Path + "\\LevelUpdate.exe")) + { + try + { + File.Delete(Path + "\\LevelUpdate.exe"); + } + catch (Exception) + { + } + } + File.Move(old_path, XMLPath); + } + } + } + #region XmlDocument读取 + + public List GetVersions() + { + List msgs = new List(); + XmlDocument XmlDoc = new XmlDocument(); + + if (!File.Exists(XMLPath)) throw new Exception("找不到LevelUpdate.xml必备文件!"); + //使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件. + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + XmlNode xn = XmlDoc.SelectSingleNode("Files"); + // 得到根节点的所有子节点 + XmlNodeList xnl = xn.ChildNodes; + foreach (XmlNode node in xnl) + { + try + { + var Name = node.Attributes["Name"].Value; + var Url = node.Attributes["Url"].Value; + var CurVersion = Version.Parse(node.Attributes["Version"].Value); + + XmlDocument temp_xml = new XmlDocument(); + temp_xml.Load(Url); + var temp_node = temp_xml.SelectSingleNode("History"); + + var temp_datas = temp_node.SelectNodes("Data"); + //更新内容 + List temp_update = new List(); + foreach (XmlNode item in temp_datas) + { + var ver = Version.Parse(item.Attributes["Ver"].Value); + if (ver > CurVersion) + { + //发现有更新 + temp_update.Add(item); + } + } + + if (temp_update.Count > 0) + { + var MSG = new UpdateClass() { Name = Name, Url = temp_update[0].Attributes["Url"].Value, Message = new List(), Version = temp_update[0].Attributes["Ver"].Value }; + msgs.Add(MSG); + foreach (var item in temp_update) + { + var temps = item.Attributes["Msg"].Value.Split(new string[] { "[br]" }, StringSplitOptions.None); + foreach (var temp in temps) MSG.Message.Add(temp); + } + } + } + catch (Exception) + { + + } + } + } + + return msgs; + } + + + + public delegate void NeedRestupdate(); + public static NeedRestupdate NeedRestupdateEvent; + + + + internal void DownFile(List update_msg, ProgressBar prog, Label label) + { + int i = 1; + foreach (var item in update_msg) + { + label?.Invoke(new Action(delegate { label.Text = $"正在下载第{i}个文件的更新包...(共{update_msg.Count}个)"; })); + DownloadFile(item.Url, MapFile($"{item.Name}_{item.Version}.zip", "Cache\\OnlineUpdate"), prog); + i++; + } + label?.Invoke(new Action(delegate { label.Text = $"下载完成,请重启安装!"; })); + NeedRestupdateEvent?.BeginInvoke(null, null); + } + + /// + /// 检查是否有需要安装的程序 + /// + public bool CheckInstall() + { + var files = GetInstallFiles(); + if (files.Count > 0) + { + new InstallFileForm(files, this).ShowDialog(); + return true; + } + return false; + } + + public static bool StartProcess(string filename, string param = null) + { + try + { + if (!File.Exists(filename)) + return false; + + try + { + if (!System.IO.File.Exists(filename)) + return false; + + if (param != null) + System.Diagnostics.Process.Start(filename, param); + else + System.Diagnostics.Process.Start(filename); + System.Threading.Thread.Sleep(100); + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + } + + + /// + /// 检查是否有新版本 + /// + public bool CheckVersion() + { + var ves = GetVersions(); + if (ves.Count > 0) + { + var f = new DownloadForm(ves, this); + f.ShowDialog(); + return f.IsOk; + } + return false; + } + + public bool DownloadFile(List updateList) + { + if (updateList.Count > 0) + { + var f = new DownloadForm(updateList, this); + f.ShowDialog(); + return f.IsOk; + } + return false; + } + + /// + /// 获得需要安装的文件 + /// + /// + public List GetInstallFiles() + { + var path = MapPath("Cache\\OnlineUpdate"); + DirectoryInfo dir = new DirectoryInfo(path); + var zips = dir.GetFiles("*_*.zip", SearchOption.TopDirectoryOnly); + var files = new List(); + foreach (var item in zips) + { + var reg = Regex.Match(item.Name, "^(.*?)_(.*?)\\.zip$"); + if (reg.Success) + { + try + { + var name = item.Name; + var version = Version.Parse(reg.Groups[2].Value); + files.Add(item); + } + catch (Exception) + { } + } + } + + return files; + } + public void StartInstall() + { + var name = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName; + if (name == "OnlineUpdate.exe") return; + StartProcess("OnlineUpdate.exe", name); + } + + public void InstallFile(FileInfo file) + { + try + { + var data = file.Name.Split('_'); + var reg = Regex.Match(file.Name, "^(.*?)_(.*?).zip$"); + if (!reg.Success) return; + Version version = null; + if (!Version.TryParse(reg.Groups[2].Value, out version)) return; + var name = reg.Groups[1].Value; + + ZipArchive.UnZip(file.FullName, Path); + XmlDocument XmlDoc = new XmlDocument(); + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + foreach (XmlNode _temp in XmlDoc.SelectSingleNode("Files").ChildNodes) + { + if (name == _temp.Attributes["Name"].Value) + { + _temp.Attributes["Version"].Value = version.ToString(); + break; + } + } + } + XmlDoc.Save(XMLPath); + + File.Delete(file.FullName); + + } + catch (Exception ex) + { } + } + + public static string MapFile(string file, string path = "") + { + return System.IO.Path.Combine(MapPath(path, true), file); + } + public static string MapPath(string path = "", bool CreateDirectory = true) + { + try + { + if (string.IsNullOrWhiteSpace(path)) + { + return System.Windows.Forms.Application.StartupPath.ToString() + "\\"; + } + path = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath.ToString() + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + } + catch (Exception) + { } + return path; + } + + public void DownloadFile(string URL, string filename, ProgressBar prog) + { + float percent = 0; + if (File.Exists(filename)) File.Delete(filename); + + Stream st = null; + Stream so = null; + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + prog.Invoke(new Action(delegate + { + prog.Value = 0; + prog.Maximum = (int)totalBytes; + + })); + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + + totalDownloadedByte = osize + totalDownloadedByte; + Application.DoEvents(); + so.Write(by, 0, osize); + + prog.Invoke(new Action(delegate { prog.Value = (int)totalDownloadedByte; })); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + + #endregion XmlDocument读取 + } +} diff --git a/类库/Update/DownloadForm.Designer.cs b/类库/Update/DownloadForm.Designer.cs new file mode 100644 index 0000000..0770e74 --- /dev/null +++ b/类库/Update/DownloadForm.Designer.cs @@ -0,0 +1,108 @@ +namespace OnlineUpdate +{ + partial class DownloadForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DownloadForm)); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.button1 = new System.Windows.Forms.Button(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // progressBar1 + // + this.progressBar1.Location = new System.Drawing.Point(8, 367); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(479, 25); + this.progressBar1.TabIndex = 6; + // + // button1 + // + this.button1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.button1.Location = new System.Drawing.Point(177, 399); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(136, 34); + this.button1.TabIndex = 5; + this.button1.Text = "开始下载"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // richTextBox1 + // + this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richTextBox1.Location = new System.Drawing.Point(2, 2); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ReadOnly = true; + this.richTextBox1.Size = new System.Drawing.Size(488, 332); + this.richTextBox1.TabIndex = 4; + this.richTextBox1.Text = ""; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(3, 338); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(482, 23); + this.label1.TabIndex = 7; + this.label1.Text = "等待下载"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // DownloadForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(495, 439); + this.Controls.Add(this.label1); + this.Controls.Add(this.progressBar1); + this.Controls.Add(this.button1); + this.Controls.Add(this.richTextBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "DownloadForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "下载新版本"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DownloadForm_FormClosing); + this.Load += new System.EventHandler(this.DownloadForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/Update/DownloadForm.cs b/类库/Update/DownloadForm.cs new file mode 100644 index 0000000..fb5469d --- /dev/null +++ b/类库/Update/DownloadForm.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace OnlineUpdate +{ + public partial class DownloadForm : Form + { + List updateClass; + Client client; + public DownloadForm(List updateClass, Client client) + { + InitializeComponent(); + this.updateClass = updateClass; + this.client = client; + } + public bool IsOk = false; + Thread thread; + private void button1_Click(object sender, EventArgs e) + { + try + { + this.button1.Enabled = false; + thread = new Thread(new ThreadStart(delegate + { + try + { + + client.DownFile(updateClass, this.progressBar1, this.label1); + IsOk = true; + this.Invoke(new Action(delegate + { + this.Close(); + })); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + MessageBox.Show(ex.Message, "下载失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + })); + } + + })); + thread.IsBackground = true; + thread.Start(); + } + catch (Exception ex) + { } + } + + private void DownloadForm_Load(object sender, EventArgs e) + { + try + { + StringBuilder sb = new StringBuilder(); + foreach (var item in updateClass) + { + sb.Append($"{item.Name} -- {item.Version}\r\n"); + + for (int i = 0; i < item.Message.Count; i++) + { + sb.AppendLine($"{i + 1}、{item.Message[i]}"); + } + sb.AppendLine(""); + sb.AppendLine(""); + } + this.richTextBox1.Text = sb.ToString().Trim(); + } + catch (Exception ex) + { } + } + + private void DownloadForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (thread != null && !IsOk) + { + try + { + thread.Abort(); + } + catch (Exception ex1) + { } + } + } + catch (Exception ex) + { } + } + } +} diff --git a/类库/Update/DownloadForm.resx b/类库/Update/DownloadForm.resx new file mode 100644 index 0000000..1bbaeaa --- /dev/null +++ b/类库/Update/DownloadForm.resx @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhSMALXdEABCALwAQfC4AAIkPAxGBMC4lhj9wLIlEoyqK + RM0rjEXwK4xF6iqLRdQriUS8K4lEnx+EO1sKgisbPXtQAB2BOAAWiDQAHYQ4AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAC6TSgAAgh0AAIQjAAAAAAAAAAAAAAAAACR6PAASfzAAAI8cAgp6KDcTejCRH4E50y2M + R/w8mFT/TaJk/1epbv9Tp2r/TKNl/0efX/87llP/KolE8h6AOb8TfDB2FIExJSw9NgAKgysACIIpAAAA + AAAAAAAAAAAAAAAAAAAAAAAALpRKHuxTxQAYfjMABoIoABGCMAAdjD0AGnw1AAyAKxUYezN4HH434DqT + Uv9frXT/h8SY/4/Jn/+Jxpr/hcOW/3/AkP94vYr/crmF/2u2f/9drnL/RZ5d/zONTPsmgj/TGX40VQCF + HwYUgTEAAJonAA2MLwAAAAAAAAAAAAAAAAAphELEHH02aRiFNhIfZzIADocvABp1MgAWfjMvFHcvriuH + RPplr3n/ksui/5vNqf+TyaL/jMac/4XClv99v5D/d7yK/3K5hf9stoD/ZrN6/1+wdf9brnH/Uqpq/z2Y + Vv8kgD3pGXozehqGNQ8jejsAMnNGAACFJAAAAAAAAAAAACqBQv8of0D3GXYytw91Kk4Jjy0IHn85Mx95 + N8dAk1b/hcKV/6HRrv+azqj/k8qi/36/kP9otH3/Waxv/02nZf9KpmP/UKlo/1Oqa/9WrG3/Wa1v/1Op + av9NpmX/R6Vh/zqaVP8rg0P4Inw6nhqCNxkbfjYAMlI7AAAAAAAAAAAALINE/n65jv9YoWz/H3g36x51 + N6gedTbKR5Zd/5fMpf+i0a//ms6o/4LClP9WrG3/PJ9X/y+ZTP8wmkz/MZtO/zKcT/8xm07/MJpN/zWc + Uf8/oFn/SKRh/0akYP9AoVr/O6BW/zSaUP8qgkL8HHY0kACAIgoOfSwACYQrAAAAAAAqf0H+oMys/8Lj + y/+GwJb/PY1T/0mWXf+azqj/o9Kw/5bLpP9qtn//Op5V/y+ZTP8ynE//NZ1R/zOYT/8xkUv/MI9J/zCR + Sv8ylk3/NJ1Q/zOcT/81nFH/PJ9X/zueVf81nFH/NJxQ/zOYTv8ieTr0E3EsagCcIgMLhCwAG3k1ACp+ + Qf2WxqT/vN/G/7Xbv/+g0Kz/m86p/6LSr/+Wy6T/W69y/zGaTf8ym07/NZ5R/zGTS/8pfkD8JHc77Bty + M8wSayu0F28vxiF1OOkpf0H9MZNM/zWdUf80nFD/NZxR/zSbUP80m1D/NZ1R/zCSS/8hdDjiGnUzSSM3 + KgAZfzQAK3xB/JPDof+027//qdS0/6XSsf+g0K3/lsqk/1isb/8wmUz/M5xP/zSbUP8tiEb/H3E25BZu + LYUTdi4zCnAnEwBuFQ0AbB0REnQtMxluMIkgbzbnLIlF/zSdUf80nFD/NJtQ/zSbUP81nlH/M5lP/yZ4 + PP8bbjGvFIExDRh4MgAsekH8kMKe/67Zuv+j0bD/nc6r/5vNqP9ms3v/MJlN/zObT/80m1D/K4BB/yNr + NvcbdjR3AJgkCBVxLgAQcysAAm0gAAttJgAXbzAAAJQqAw5rJ1QYaC3WK4VE/zWeUf81nlH/NZxR/y6K + R/8fcDX1FWksqRJwKz0MgioEEHgsACx4QfyMv5r/qNa1/53Pq/+bzqn/eLyK/zSbUP8ymk//NJtQ/zSc + Uf8ylk3/Kn5B/htpMN4TZiqBD3UrJQDBGwAAiiQAAHQKAA91LAAJfCgARh9CAAhpI0cZZy7jMI5K/zGT + TP8ldjv+HGYwyxJrKWEAdyENHGUxABF4LAAlfT0ALHZA+4i8lv+i06//ms6o/4fEl/9AoVr/MZlN/zSb + UP80m1D/NJtQ/zWdUf82oVP/L4tI/x5kMf8OYCSsA3UhIQR0IwAAdAoAAAAAAAZ2IwAKdCYAALMYAhRm + K3IfZzL2IGg06RZlK4sOciklLTwyAAVtIAAadTMACGwgEyV+PVcsdD/6hLqS/53Qq/+RyaD/Tqhn/y+Z + TP80m1D/NJtQ/zSbUP81nlH/NJtQ/yyERP8gajPxGWMtpwxrJjwBdSAGBHMjAAB0CgAAAAAAAAAAABVh + KQAQcyoADXwrDgxiI3ATaypFE5Q3BRNqKgAIbyIAAGAJBw9xKUYfeDe0Jnw97SxxP/qAt4//m8+p/2y3 + gP8wmk3/M5tP/zSbUP81nVH/NZ5R/y+MSf8gazX6FFwoxBBiJlcNfywOEGYnAAN1IQAEcyMAAHQKAAAA + AAAAAAAAAYkmABtjLgATbiwAGlYtABpgLgAKcCUAAFgAAQBnFykNbieSRItY6EqSXv8meT35K289+X21 + jf+LyJz/QqJc/zGZTf80nFH/NZ9S/zGSTP8kcTn/Glws2BRfKXQIbyQZITknAA96LAAWcy8AAYkmAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAGERAABaBgALcSUAD3ApAABpGxgNbydvKX0/1m+lfv+izK7/P5lY/yV1 + O/krbT74e7SL/2i2ff8xmk3/NZ5S/zOZTv8nej7/GV0s7BFYJZQRaikwAP+hAA5lJQAHgCgADG4mAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9zKgAHcSIAFngyAAFrGQkDah1NEnEsuEyRX/mYwqP/weDJ/3W+ + iP8rjkb/JXE6+i1uP/durYD/QKVc/zKcT/8shET/HmMx9g5VIrAJXyFFBJMqBxRjKgAQmjUAE34wAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtvJgAFaRwADXApAACCEgEPcSg0EXErmjKCSO96roj/tdi+/7ne + w/+bzqj/P6JZ/y2OR/8kbTj6MHBC9kudYf8vj0n/IWo1/RZZKM0TXihjCnwqEhBaJAAMbiYAALwrAAGL + JwAAAAAAAAAAAAAAAAAAAAAAAAAAAABXDAAUfTMADnMoACiBRQAEbCEbEHAqdyJ5Otpam2z/pMyu/7nd + w/+t17n/qNS0/2Kxd/8vm0z/MI9K/yNpNvsmaDf2Imk1/xRZJ94OWSGCDGslHioAAAAOeywAH5I/ACuW + SwAZiTcAMpZNAAmBKQAAAAAAAAAAAAAAAAAAYxEAAGEOABR2LgALciYNEXEpVxRyLsQ9iVL7iryX/7fb + wv+y2r3/pdOx/6HRrv+Fw5b/NZtR/zOdUP8wjkn/IWMz+x5kMeMOViKiBmIfNwCzIAMMZyQAHpA9AACB + GwMVjDU6GI04cQ+GLhUYiDYAap9+AAAAAAAAAAAAAAAAAABjEQAAXwoFD3IpOR55N6QtgUTwbKl9/6vT + tv+13MD/qdW1/6HQrv+azaj/ksqh/06oZ/8wmUz/NZ5R/y+NSP8gXzH8KIFAPgx/KgsKVyAADoswACaU + RQAXjTcdGY04fiSRQeEwlUv5HYk7ghOEMwUXgTQAEXYtAACGJAAAAAAAAGIRAABhDhoUciygI3g6/Wqm + ev+33MH/stu+/6LRr/+bzan/lMqj/5HIoP9rtn//MppO/zObT/81nlH/L4xI/x5bL/whbjYABmwgAByQ + OwAEhScJG487UiKRQL9CoFz8o9Cv/5bIo/8likHrFH0wWP///wARdCwAHHg1AAAAAAAALAAAJKZaAA9u + KB4TbCt3HW802E2OX/2FuJP/mMyn/5DIn/+JxZr/fr+Q/z+gWf8xmk7/NJtQ/zWeUf8vi0j/HVgt/QCB + IQAAbgACFIszMyWTQ5kok0bwcreE/+Hw5f/6/Pv/7/fx/3OzhP8ZfDTfGHkyYA5yKAYVbiwACGIfAABc + FgAMYSEAEWopAABRAAUSZSlqGGQt8jp8TP+Cu5L/hMOV/37Akf9Vq23/MJpN/zSbUP80m1D/NZ5R/y+L + SP8dVy39B4InAAB0DQgcjTuXMZZM/y+YTP+KxZr/9fr2/+n07P/k8ef/1Ora/3Cwgf8kfjztEW8rkwxq + JDoFYRsSAFsQDgtjIRIJXx8zCVsfgRtkL99LjFz/e7mM/4HCk/96vYz/Y7J5/zacUv8zm0//NJxQ/zSb + UP81nlH/L4tI/x1YLf4KgyoAR5lgAB+LPTwrjkbaL5RL/zKbT/+czqn/4O/j/9br2//Q6Nf/yOXQ/4m+ + l/9Cjlj+HXEz7ApgIcsHXB24Dl8kyyJrNes4e0r8YqFz/4PDlP98v47/dLqG/2aze/87n1f/MpxP/zSb + T/80m0//NZ5R/zWeUv8vi0j/HVgt/gqDKgABeSIAAFsAARmANWQnh0HzLpVK/zScUP+Gw5b/yeTQ/8bj + zf+73sT/ut7E/6fTs/+Eu5P/cayB/2Cgcf9mpHj/crGD/4C+kP+AwpL/dbuI/2+4gv9hsXf/QKFa/zKc + T/80m1D/JnM7/yJnNf8vi0j/NqFT/y+OSf8dWC3+AAAAAAZ6JwAOeSsAAG4aCh59OI4rhUT5L5RK/y+a + Tf9brnL/nM6q/7LZvP+q1bX/otGv/57Qq/+Yzab/jsme/4jGmf+BwpL/d7yJ/2+4g/9ptX7/Wa1w/zuf + Vv8znE//NJtQ/yVxOv8YUSjZGFAnrhZSJuskcTn/K4FD/x1ZLv4AAAAAAAAAAP///wAdfzkAGnkzFBt1 + NI8jejr3L5BJ/y6aTP86n1b/XrB0/4fEmP+TyqL/jsie/4nEmf+BwZL/eb2M/3K5hv9rtX7/Xq90/0ak + X/82nFL/M55Q/zKXTv8jbjf/FVAl2Q1NHkYAUw8KBEYTTwtHGbgVUyb4HFYs/wAAAAAAAAAAAF0OACSB + PwAWdC8AAGIWDA1oJn4ecDXvLIVE/zCWTP8wnE3/M5xQ/0ChW/9Uq2z/XrB0/16wdP9arnH/Tqdm/0Gh + Wv82nVH/M51P/zSeUf8th0b/G14t/gpGGcEFRxY/ED8wAAFPEQAOTTEAAEIGEglKGGoZVinHAAAAAAAA + AAAAAAAAAIckABNoKwAFZB4AAFsQCg9iJFkXYyvIIW42+y2HRv8ymE7/M5xP/zGcTv8wnE7/MJxN/zGc + Tv8ynU//M51P/zScUP8tiEX/Ims1/xlVKesNSh2MAEIKIQxKGwAJURkABkgOAABDAAABRA4AN3NvACBi + MSEAAAAAAAAAAAAAAAAAAAAAAAAAAABfFwAAXhYAN4JfAAJXFh0TWSZ4GVwrzxxfLvYkbzn/Kn9C/y2G + Rf8uiUb/LolH/yqAQv8mczv/HV4v/hFOId8GQxWiBUgTSQlWGQUGRBMAGDooAAAAAAAAAAAAAAAAAAA/ + AAAAOAAAH2ExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhcHAACWBEACloeAAAzAAEATxIsDlIgWx1Z + LaAcVSzaG1Mr7BxVK/UcViz2G1Qr3RxVLLUTTyR/AUcSPQA+AAgMShYADFAcAAAeAAAATA0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/AAAPxwAAB8AAAAHAAAAAwAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAA + AAAAACAAAAAwAAAAMAAAAPgAAAPwAAAPwAAAHwAAAA4AAAAOAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAA + AACAAAAAwAAAAMAAAADgAAAA+AAAOPwAAD8= + + + \ No newline at end of file diff --git a/类库/Update/InstallFileForm.Designer.cs b/类库/Update/InstallFileForm.Designer.cs new file mode 100644 index 0000000..5c21151 --- /dev/null +++ b/类库/Update/InstallFileForm.Designer.cs @@ -0,0 +1,70 @@ +namespace OnlineUpdate +{ + partial class InstallFileForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InstallFileForm)); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(2, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(406, 82); + this.label1.TabIndex = 0; + this.label1.Text = "准备安装"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // InstallFileForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(411, 103); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InstallFileForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "正在安装"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.InstallFileForm_FormClosing); + this.Load += new System.EventHandler(this.InstallFileForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/Update/InstallFileForm.cs b/类库/Update/InstallFileForm.cs new file mode 100644 index 0000000..f8f13be --- /dev/null +++ b/类库/Update/InstallFileForm.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Management; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace OnlineUpdate +{ + public partial class InstallFileForm : Form + { + List infos; + Client client; + public InstallFileForm(List infos, Client client) + { + InitializeComponent(); + this.client = client; + this.infos = infos; + } + + public void Kill(string filePath) + { + try + { + if (string.IsNullOrWhiteSpace(filePath)) return; + var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process"; + using (var searcher = new ManagementObjectSearcher(wmiQueryString)) + using (var results = searcher.Get()) + { + var query = from p in Process.GetProcesses() + join mo in results.Cast() + on p.Id equals (int)(uint)mo["ProcessId"] + select new + { + Process = p, + Path = (string)mo["ExecutablePath"], + CommandLine = (string)mo["CommandLine"], + }; + + foreach (var item in query) + { + if (filePath == item.Path) + { + item.Process.Kill(); + item.Process.WaitForExit(); + } + } + } + } + catch (Exception ex) + { } + } + + private bool IsClose = false; + private void InstallFileForm_Load(object sender, EventArgs e) + { + var method = new Action(delegate () + { + try + { + int i = 1; + Thread.Sleep(2000); + + //for (int z = 0; z < 4; z++) + //{ + // try + // { + // Process[] MyProcesses = Process.GetProcesses(); + // foreach (var MyProcess in MyProcesses) + // { + // try + // { + // if (MyProcess.MainModule.FileName.ToUpper().Trim() == Program.ExeName.ToUpper().Trim()) + // { + // MyProcess.Kill(); + // MyProcess.WaitForExit(); + // } + // } + // catch (Exception) + // { } + // } + + // var process = Process.GetProcesses().FirstOrDefault(f => f.MainModule.FileName.ToUpper().Trim() == Program.ExeName.ToUpper().Trim()); + // if (process == null) break; + // Thread.Sleep(z == 0 ? 3000 : 500); + // } + // catch (Exception) + // { } + //} + + + Kill(Program.ExeName); + + foreach (var item in infos) + { + this.Invoke(new Action(delegate + { + this.label1.Text = $"正在安装第{i}个文件包...(共{infos.Count}个)"; + })); + this.client.InstallFile(item); + Application.DoEvents(); + } + this.Invoke(new Action(delegate + { + this.label1.Text = $"安装完成!"; + IsClose = true; + this.Close(); + })); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + this.label1.Text = $"安装失败:" + ex.Message; + })); + } + finally + { + IsClose = true; + } + }); + method.BeginInvoke(null, null); + } + + private void InstallFileForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (!IsClose) + { + MessageBox.Show("安装还未结束,不能中途退出!", "友情提醒", MessageBoxButtons.OK, MessageBoxIcon.Error); + e.Cancel = true; + } + } + catch (Exception) + { } + } + } +} diff --git a/类库/Update/InstallFileForm.resx b/类库/Update/InstallFileForm.resx new file mode 100644 index 0000000..1bbaeaa --- /dev/null +++ b/类库/Update/InstallFileForm.resx @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhSMALXdEABCALwAQfC4AAIkPAxGBMC4lhj9wLIlEoyqK + RM0rjEXwK4xF6iqLRdQriUS8K4lEnx+EO1sKgisbPXtQAB2BOAAWiDQAHYQ4AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAC6TSgAAgh0AAIQjAAAAAAAAAAAAAAAAACR6PAASfzAAAI8cAgp6KDcTejCRH4E50y2M + R/w8mFT/TaJk/1epbv9Tp2r/TKNl/0efX/87llP/KolE8h6AOb8TfDB2FIExJSw9NgAKgysACIIpAAAA + AAAAAAAAAAAAAAAAAAAAAAAALpRKHuxTxQAYfjMABoIoABGCMAAdjD0AGnw1AAyAKxUYezN4HH434DqT + Uv9frXT/h8SY/4/Jn/+Jxpr/hcOW/3/AkP94vYr/crmF/2u2f/9drnL/RZ5d/zONTPsmgj/TGX40VQCF + HwYUgTEAAJonAA2MLwAAAAAAAAAAAAAAAAAphELEHH02aRiFNhIfZzIADocvABp1MgAWfjMvFHcvriuH + RPplr3n/ksui/5vNqf+TyaL/jMac/4XClv99v5D/d7yK/3K5hf9stoD/ZrN6/1+wdf9brnH/Uqpq/z2Y + Vv8kgD3pGXozehqGNQ8jejsAMnNGAACFJAAAAAAAAAAAACqBQv8of0D3GXYytw91Kk4Jjy0IHn85Mx95 + N8dAk1b/hcKV/6HRrv+azqj/k8qi/36/kP9otH3/Waxv/02nZf9KpmP/UKlo/1Oqa/9WrG3/Wa1v/1Op + av9NpmX/R6Vh/zqaVP8rg0P4Inw6nhqCNxkbfjYAMlI7AAAAAAAAAAAALINE/n65jv9YoWz/H3g36x51 + N6gedTbKR5Zd/5fMpf+i0a//ms6o/4LClP9WrG3/PJ9X/y+ZTP8wmkz/MZtO/zKcT/8xm07/MJpN/zWc + Uf8/oFn/SKRh/0akYP9AoVr/O6BW/zSaUP8qgkL8HHY0kACAIgoOfSwACYQrAAAAAAAqf0H+oMys/8Lj + y/+GwJb/PY1T/0mWXf+azqj/o9Kw/5bLpP9qtn//Op5V/y+ZTP8ynE//NZ1R/zOYT/8xkUv/MI9J/zCR + Sv8ylk3/NJ1Q/zOcT/81nFH/PJ9X/zueVf81nFH/NJxQ/zOYTv8ieTr0E3EsagCcIgMLhCwAG3k1ACp+ + Qf2WxqT/vN/G/7Xbv/+g0Kz/m86p/6LSr/+Wy6T/W69y/zGaTf8ym07/NZ5R/zGTS/8pfkD8JHc77Bty + M8wSayu0F28vxiF1OOkpf0H9MZNM/zWdUf80nFD/NZxR/zSbUP80m1D/NZ1R/zCSS/8hdDjiGnUzSSM3 + KgAZfzQAK3xB/JPDof+027//qdS0/6XSsf+g0K3/lsqk/1isb/8wmUz/M5xP/zSbUP8tiEb/H3E25BZu + LYUTdi4zCnAnEwBuFQ0AbB0REnQtMxluMIkgbzbnLIlF/zSdUf80nFD/NJtQ/zSbUP81nlH/M5lP/yZ4 + PP8bbjGvFIExDRh4MgAsekH8kMKe/67Zuv+j0bD/nc6r/5vNqP9ms3v/MJlN/zObT/80m1D/K4BB/yNr + NvcbdjR3AJgkCBVxLgAQcysAAm0gAAttJgAXbzAAAJQqAw5rJ1QYaC3WK4VE/zWeUf81nlH/NZxR/y6K + R/8fcDX1FWksqRJwKz0MgioEEHgsACx4QfyMv5r/qNa1/53Pq/+bzqn/eLyK/zSbUP8ymk//NJtQ/zSc + Uf8ylk3/Kn5B/htpMN4TZiqBD3UrJQDBGwAAiiQAAHQKAA91LAAJfCgARh9CAAhpI0cZZy7jMI5K/zGT + TP8ldjv+HGYwyxJrKWEAdyENHGUxABF4LAAlfT0ALHZA+4i8lv+i06//ms6o/4fEl/9AoVr/MZlN/zSb + UP80m1D/NJtQ/zWdUf82oVP/L4tI/x5kMf8OYCSsA3UhIQR0IwAAdAoAAAAAAAZ2IwAKdCYAALMYAhRm + K3IfZzL2IGg06RZlK4sOciklLTwyAAVtIAAadTMACGwgEyV+PVcsdD/6hLqS/53Qq/+RyaD/Tqhn/y+Z + TP80m1D/NJtQ/zSbUP81nlH/NJtQ/yyERP8gajPxGWMtpwxrJjwBdSAGBHMjAAB0CgAAAAAAAAAAABVh + KQAQcyoADXwrDgxiI3ATaypFE5Q3BRNqKgAIbyIAAGAJBw9xKUYfeDe0Jnw97SxxP/qAt4//m8+p/2y3 + gP8wmk3/M5tP/zSbUP81nVH/NZ5R/y+MSf8gazX6FFwoxBBiJlcNfywOEGYnAAN1IQAEcyMAAHQKAAAA + AAAAAAAAAYkmABtjLgATbiwAGlYtABpgLgAKcCUAAFgAAQBnFykNbieSRItY6EqSXv8meT35K289+X21 + jf+LyJz/QqJc/zGZTf80nFH/NZ9S/zGSTP8kcTn/Glws2BRfKXQIbyQZITknAA96LAAWcy8AAYkmAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAGERAABaBgALcSUAD3ApAABpGxgNbydvKX0/1m+lfv+izK7/P5lY/yV1 + O/krbT74e7SL/2i2ff8xmk3/NZ5S/zOZTv8nej7/GV0s7BFYJZQRaikwAP+hAA5lJQAHgCgADG4mAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9zKgAHcSIAFngyAAFrGQkDah1NEnEsuEyRX/mYwqP/weDJ/3W+ + iP8rjkb/JXE6+i1uP/durYD/QKVc/zKcT/8shET/HmMx9g5VIrAJXyFFBJMqBxRjKgAQmjUAE34wAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtvJgAFaRwADXApAACCEgEPcSg0EXErmjKCSO96roj/tdi+/7ne + w/+bzqj/P6JZ/y2OR/8kbTj6MHBC9kudYf8vj0n/IWo1/RZZKM0TXihjCnwqEhBaJAAMbiYAALwrAAGL + JwAAAAAAAAAAAAAAAAAAAAAAAAAAAABXDAAUfTMADnMoACiBRQAEbCEbEHAqdyJ5Otpam2z/pMyu/7nd + w/+t17n/qNS0/2Kxd/8vm0z/MI9K/yNpNvsmaDf2Imk1/xRZJ94OWSGCDGslHioAAAAOeywAH5I/ACuW + SwAZiTcAMpZNAAmBKQAAAAAAAAAAAAAAAAAAYxEAAGEOABR2LgALciYNEXEpVxRyLsQ9iVL7iryX/7fb + wv+y2r3/pdOx/6HRrv+Fw5b/NZtR/zOdUP8wjkn/IWMz+x5kMeMOViKiBmIfNwCzIAMMZyQAHpA9AACB + GwMVjDU6GI04cQ+GLhUYiDYAap9+AAAAAAAAAAAAAAAAAABjEQAAXwoFD3IpOR55N6QtgUTwbKl9/6vT + tv+13MD/qdW1/6HQrv+azaj/ksqh/06oZ/8wmUz/NZ5R/y+NSP8gXzH8KIFAPgx/KgsKVyAADoswACaU + RQAXjTcdGY04fiSRQeEwlUv5HYk7ghOEMwUXgTQAEXYtAACGJAAAAAAAAGIRAABhDhoUciygI3g6/Wqm + ev+33MH/stu+/6LRr/+bzan/lMqj/5HIoP9rtn//MppO/zObT/81nlH/L4xI/x5bL/whbjYABmwgAByQ + OwAEhScJG487UiKRQL9CoFz8o9Cv/5bIo/8likHrFH0wWP///wARdCwAHHg1AAAAAAAALAAAJKZaAA9u + KB4TbCt3HW802E2OX/2FuJP/mMyn/5DIn/+JxZr/fr+Q/z+gWf8xmk7/NJtQ/zWeUf8vi0j/HVgt/QCB + IQAAbgACFIszMyWTQ5kok0bwcreE/+Hw5f/6/Pv/7/fx/3OzhP8ZfDTfGHkyYA5yKAYVbiwACGIfAABc + FgAMYSEAEWopAABRAAUSZSlqGGQt8jp8TP+Cu5L/hMOV/37Akf9Vq23/MJpN/zSbUP80m1D/NZ5R/y+L + SP8dVy39B4InAAB0DQgcjTuXMZZM/y+YTP+KxZr/9fr2/+n07P/k8ef/1Ora/3Cwgf8kfjztEW8rkwxq + JDoFYRsSAFsQDgtjIRIJXx8zCVsfgRtkL99LjFz/e7mM/4HCk/96vYz/Y7J5/zacUv8zm0//NJxQ/zSb + UP81nlH/L4tI/x1YLf4KgyoAR5lgAB+LPTwrjkbaL5RL/zKbT/+czqn/4O/j/9br2//Q6Nf/yOXQ/4m+ + l/9Cjlj+HXEz7ApgIcsHXB24Dl8kyyJrNes4e0r8YqFz/4PDlP98v47/dLqG/2aze/87n1f/MpxP/zSb + T/80m0//NZ5R/zWeUv8vi0j/HVgt/gqDKgABeSIAAFsAARmANWQnh0HzLpVK/zScUP+Gw5b/yeTQ/8bj + zf+73sT/ut7E/6fTs/+Eu5P/cayB/2Cgcf9mpHj/crGD/4C+kP+AwpL/dbuI/2+4gv9hsXf/QKFa/zKc + T/80m1D/JnM7/yJnNf8vi0j/NqFT/y+OSf8dWC3+AAAAAAZ6JwAOeSsAAG4aCh59OI4rhUT5L5RK/y+a + Tf9brnL/nM6q/7LZvP+q1bX/otGv/57Qq/+Yzab/jsme/4jGmf+BwpL/d7yJ/2+4g/9ptX7/Wa1w/zuf + Vv8znE//NJtQ/yVxOv8YUSjZGFAnrhZSJuskcTn/K4FD/x1ZLv4AAAAAAAAAAP///wAdfzkAGnkzFBt1 + NI8jejr3L5BJ/y6aTP86n1b/XrB0/4fEmP+TyqL/jsie/4nEmf+BwZL/eb2M/3K5hv9rtX7/Xq90/0ak + X/82nFL/M55Q/zKXTv8jbjf/FVAl2Q1NHkYAUw8KBEYTTwtHGbgVUyb4HFYs/wAAAAAAAAAAAF0OACSB + PwAWdC8AAGIWDA1oJn4ecDXvLIVE/zCWTP8wnE3/M5xQ/0ChW/9Uq2z/XrB0/16wdP9arnH/Tqdm/0Gh + Wv82nVH/M51P/zSeUf8th0b/G14t/gpGGcEFRxY/ED8wAAFPEQAOTTEAAEIGEglKGGoZVinHAAAAAAAA + AAAAAAAAAIckABNoKwAFZB4AAFsQCg9iJFkXYyvIIW42+y2HRv8ymE7/M5xP/zGcTv8wnE7/MJxN/zGc + Tv8ynU//M51P/zScUP8tiEX/Ims1/xlVKesNSh2MAEIKIQxKGwAJURkABkgOAABDAAABRA4AN3NvACBi + MSEAAAAAAAAAAAAAAAAAAAAAAAAAAABfFwAAXhYAN4JfAAJXFh0TWSZ4GVwrzxxfLvYkbzn/Kn9C/y2G + Rf8uiUb/LolH/yqAQv8mczv/HV4v/hFOId8GQxWiBUgTSQlWGQUGRBMAGDooAAAAAAAAAAAAAAAAAAA/ + AAAAOAAAH2ExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhcHAACWBEACloeAAAzAAEATxIsDlIgWx1Z + LaAcVSzaG1Mr7BxVK/UcViz2G1Qr3RxVLLUTTyR/AUcSPQA+AAgMShYADFAcAAAeAAAATA0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/AAAPxwAAB8AAAAHAAAAAwAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAA + AAAAACAAAAAwAAAAMAAAAPgAAAPwAAAPwAAAHwAAAA4AAAAOAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAA + AACAAAAAwAAAAMAAAADgAAAA+AAAOPwAAD8= + + + \ No newline at end of file diff --git a/类库/Update/OnlineUpdate.csproj b/类库/Update/OnlineUpdate.csproj new file mode 100644 index 0000000..9bfe5a1 --- /dev/null +++ b/类库/Update/OnlineUpdate.csproj @@ -0,0 +1,168 @@ + + + + + Debug + AnyCPU + {38B69C05-86D3-49EC-BC45-698E8B5919F4} + WinExe + Properties + OnlineUpdate + OnlineUpdate + v4.0 + 512 + + + x86 + true + full + false + ..\..\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + gtk_refresh_reload_update_32px_2205_easyicon.net.ico + + + + + + + + + + + + + + + + + + + + Form + + + InstallFileForm.cs + + + + + Form + + + DownloadForm.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InstallFileForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + DownloadForm.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + \ No newline at end of file diff --git a/类库/Update/Program.cs b/类库/Update/Program.cs new file mode 100644 index 0000000..1422900 --- /dev/null +++ b/类库/Update/Program.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using System.Windows.Forms; + +namespace OnlineUpdate +{ + static class Program + { + + internal static string ExeName { get; private set; } + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main(string[] param) + { + try + { + Client client = new Client(); + if (param.Length > 0) + { + ExeName = Client.MapFile(param[0]); + } + if (client.CheckInstall()) + { + if (param.Length > 0) + { + Client.StartProcess(param[0]); + return; + } + } + else + { + if (client.CheckVersion()) + { + if (client.CheckInstall()) + { + if (param.Length > 0) + { + Client.StartProcess(param[0]); + return; + } + } + } + else if (param.Length == 0) MessageBox.Show("没有发现新版本!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + } + catch (Exception ex) + { } + } + } +} diff --git a/类库/Update/Properties/AssemblyInfo.cs b/类库/Update/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..550f7b0 --- /dev/null +++ b/类库/Update/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("OnlineUpdate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OnlineUpdate")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +//将 ComVisible 设置为 false 将使此程序集中的类型 +//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("38b69c05-86d3-49ec-bc45-698e8b5919f4")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/类库/Update/Properties/Resources.Designer.cs b/类库/Update/Properties/Resources.Designer.cs new file mode 100644 index 0000000..64b1b24 --- /dev/null +++ b/类库/Update/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace OnlineUpdate.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OnlineUpdate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/类库/Update/Properties/Resources.resx b/类库/Update/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/类库/Update/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/Update/Properties/Settings.Designer.cs b/类库/Update/Properties/Settings.Designer.cs new file mode 100644 index 0000000..2e1903a --- /dev/null +++ b/类库/Update/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace OnlineUpdate.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/类库/Update/Properties/Settings.settings b/类库/Update/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/类库/Update/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/类库/Update/UpdateForm.Designer.cs b/类库/Update/UpdateForm.Designer.cs new file mode 100644 index 0000000..6b5a919 --- /dev/null +++ b/类库/Update/UpdateForm.Designer.cs @@ -0,0 +1,106 @@ +namespace LevelUpdate +{ + partial class UpdateForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UpdateForm)); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // richTextBox1 + // + this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richTextBox1.Location = new System.Drawing.Point(-1, 1); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ReadOnly = true; + this.richTextBox1.Size = new System.Drawing.Size(487, 326); + this.richTextBox1.TabIndex = 1; + this.richTextBox1.Text = ""; + // + // button1 + // + this.button1.Enabled = false; + this.button1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.button1.Location = new System.Drawing.Point(172, 395); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(136, 34); + this.button1.TabIndex = 2; + this.button1.Text = "开始更新"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // progressBar1 + // + this.progressBar1.Location = new System.Drawing.Point(3, 362); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(479, 25); + this.progressBar1.TabIndex = 3; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(1, 332); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(482, 23); + this.label1.TabIndex = 4; + this.label1.Text = "准备就绪..."; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // UpdateForm + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(485, 436); + this.Controls.Add(this.label1); + this.Controls.Add(this.progressBar1); + this.Controls.Add(this.button1); + this.Controls.Add(this.richTextBox1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UpdateForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = " 检 查 更 新"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.UpdateForm_FormClosing); + this.Load += new System.EventHandler(this.UpdateForm_Load); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/Update/UpdateForm.cs b/类库/Update/UpdateForm.cs new file mode 100644 index 0000000..3897658 --- /dev/null +++ b/类库/Update/UpdateForm.cs @@ -0,0 +1,413 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Xml; +using System.Xml.Linq; + +namespace LevelUpdate +{ + public partial class UpdateForm : Form + { + public UpdateForm() + { + InitializeComponent(); + } + + private void UpdateForm_Load(object sender, EventArgs e) + { + if (!Program.NotRelationEXE) + { + this.button1.Text = "重启更新"; + } + var thraed = new Thread(new ThreadStart(delegate { + try + { + CheckUpdate(); + } + catch (Exception ex) + { + ChangeStatus("更新失败:" + ex.Message); + } + })); + thraed.IsBackground = true; + thraed.Start(); + + + } + private void ChangeStatus(string text,params object[] objs) + { + if (!this.IsDisposed && !this.IsClose) + { + var temp = string.Format(text, objs); + this.label1.Invoke(new Action(delegate + { + this.label1.Text = temp; + + })); + } + + } + + string Path = System.IO.Directory.GetCurrentDirectory(); + string XMLPath = string.Empty; + XmlDocument XmlDoc = new XmlDocument(); + #region XmlDocument读取 + List need_update = new List(); + InstallFileForm lodingUpdate = null; + public void CheckUpdate() + { + + + XMLPath = Path + "\\LevelUpdate.xml"; + if (!File.Exists(XMLPath)) throw new Exception("找不到LevelUpdate.xml必备文件!"); + //使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件. + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + XmlNode xn = XmlDoc.SelectSingleNode("Files"); + // 得到根节点的所有子节点 + XmlNodeList xnl = xn.ChildNodes; + StringBuilder sb = new StringBuilder(); + foreach (XmlNode node in xnl) + { + try + { + var Name = node.Attributes["Name"].Value; + var Url = node.Attributes["Url"].Value; + var CurVersion = Version.Parse(node.Attributes["Version"].Value); + ChangeStatus("正在检测{0}文件包...",Name); + XmlDocument temp_xml = new XmlDocument(); + temp_xml.Load(Url); + var temp_node = temp_xml.SelectSingleNode("History"); + + var temp_datas = temp_node.SelectNodes("Data"); + //更新内容 + List temp_update = new List(); + foreach (XmlNode item in temp_datas) + { + var ver = Version.Parse(item.Attributes["Ver"].Value); + if (ver > CurVersion) temp_update.Add(item); + } + + if (temp_update.Count > 0) + { + sb.AppendLine(Name + "文件包更新内容如下:"); + sb.AppendLine("-------------------------------"); + foreach (var item in temp_update) + { + sb.AppendLine(item.Attributes["Ver"].Value); + sb.AppendLine(item.Attributes["Msg"].Value.Replace("[br]", "\r\n")); + sb.AppendLine(); + } + var new_data = temp_update[0]; + this.richTextBox1.Invoke(new Action(delegate + { + this.richTextBox1.Text = sb.ToString(); + })); + var t = temp_update[0]; + XmlAttribute attr = t.OwnerDocument.CreateAttribute("Name"); + attr.Value = Name; + t.Attributes.Append(attr); + need_update.Add(temp_update[0]); + sb.AppendLine(""); + + } + else ChangeStatus("正在检测{0}文件包无新版本!", Name); + + } + catch (Exception ex) + { + ChangeStatus("更新错误:{0}", ex.Message); + } + } + } + + + if (need_update.Count > 0) + { + ChangeStatus("发现有{0}个新文件包!", need_update.Count); + this.button1.Invoke(new Action(delegate + { + this.button1.Enabled = true; + //if(Program.NotRelationEXE) button1_Click(null,null); + })); + } + else + { + ChangeStatus("没有发现新版本文件包!"); + Thread.Sleep(1000); + if (!this.IsDisposed && !IsClose) + { + this.Invoke(new Action(delegate + { + this.Close(); + })); + } + } + + } + + #endregion XmlDocument读取 + + + + + + + + /// + /// 退出 + /// + private static void Exit(bool start = false) + { + try + { + if (start) + { + //程序位置 + string strAppFileName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; + System.Diagnostics.Process myNewProcess = new System.Diagnostics.Process(); + //要启动的应用程序 + myNewProcess.StartInfo.FileName = strAppFileName; + // 设置要启动的进程的初始目录 + myNewProcess.StartInfo.WorkingDirectory = Application.ExecutablePath; + //启动程序 + myNewProcess.Start(); + } + //结束该程序 + // Application.Exit(); + //结束该所有线程 + //Environment.Exit(0); + System.Diagnostics.Process.GetCurrentProcess().Kill(); + } + catch (Exception) + { } + } + + public static string MapFile(string file, string path = "") + { + return System.IO.Path.Combine(MapPath(path, true), file); + } + public static string MapPath(string path = "", bool CreateDirectory = true) + { + if (string.IsNullOrWhiteSpace(path)) + { + return System.Windows.Forms.Application.StartupPath.ToString() + "\\"; + } + path = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath.ToString() + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + return path; + } + + class Cmd + { + private static string CmdPath = @"C:\Windows\System32\cmd.exe"; + /// + /// 执行cmd命令 返回cmd窗口显示的信息 + /// 多命令请使用批处理命令连接符: + /// + /// + /// 执行的命令 + public static string RunCmd(string cmd) + { + cmd = cmd.Trim().TrimEnd('&') + "&exit";//说明:不管命令是否成功均执行exit命令,否则当调用ReadToEnd()方法时,会处于假死状态 + using (Process p = new Process()) + { + p.StartInfo.FileName = CmdPath; + p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动 + p.StartInfo.RedirectStandardInput = true; //接受来自调用程序的输入信息 + p.StartInfo.RedirectStandardOutput = true; //由调用程序获取输出信息 + p.StartInfo.RedirectStandardError = true; //重定向标准错误输出 + p.StartInfo.CreateNoWindow = true; //不显示程序窗口 + p.Start();//启动程序 + + //向cmd窗口写入命令 + p.StandardInput.WriteLine(cmd); + p.StandardInput.AutoFlush = true; + + //获取cmd窗口的输出信息 + string output = p.StandardOutput.ReadToEnd(); + p.WaitForExit();//等待程序执行完退出进程 + p.Close(); + + return output; + } + } + } + + + + private void button1_Click(object sender, EventArgs e) + { + if (!Program.NotRelationEXE) + { + var name = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName; + var update = MapFile("LevelUpdate.exe"); + Program.StartProcess(update, name); + //this.Visible = false; + Thread.Sleep(500); + Exit(); + return; + } + + try + { + this.button1.Text = "更新中.."; + this.button1.Enabled = false; + var thread = new Thread(new ThreadStart(delegate + { + int number = 1; + try + { + + foreach (var item in need_update) + { + var filename = MapFile(item.Attributes["Ver"].Value + "_" + DateTime.Now.Ticks + ".zip", "Cache\\Update"); //GetPath("Cache")+ "\\Update\\"+Guid.NewGuid().ToString() + "_"+ item.Attributes["Ver"].Value + ".zip"; + ChangeStatus("开始更新{0}文件包,共{1}/{2}个文件包..", item.Attributes["Name"].Value, number, need_update.Count); + foreach (XmlNode _temp in XmlDoc.SelectSingleNode("Files").ChildNodes) + { + + if (item.Attributes["Name"].Value == _temp.Attributes["Name"].Value) + { + _temp.Attributes["Version"].Value = item.Attributes["Ver"].Value; + break; + } + } + + DownloadFile(item.Attributes["Url"].Value, filename, this.progressBar1); + ChangeStatus("正在安装{0}文件包..", item.Attributes["Name"].Value); + ZipArchive.UnZip(filename, Path); + XmlDoc.Save(XMLPath); + number++; + } + ChangeStatus("更新完成!"); + + var file_name = MapFile(Program.ExeName); + Program.StartProcess(file_name); + if (!IsClose && !this.IsDisposed) + { + this.Invoke(new Action(delegate () { + this.Close(); + })); + } + } + catch (Exception ex) + { + ChangeStatus("更新失败:" + ex.Message); + if (!IsClose) MessageBox.Show(ex.Message, "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + })); + thread.IsBackground = true; + thread.Start(); + + } + catch (Exception ex) + { + ChangeStatus("更新失败:"+ex.Message); + if(!IsClose) + MessageBox.Show(ex.Message,"更新失败",MessageBoxButtons.OK,MessageBoxIcon.Error); + } + } + + private static Stream st = null; + private static Stream so = null; + private void DownloadFile(string URL, string filename, ProgressBar prog) + { + float percent = 0; + try + { + if (File.Exists(filename)) + File.Delete(filename); + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + prog.Invoke(new Action(delegate + { + prog.Maximum = (int)totalBytes; + + })); + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + + totalDownloadedByte = osize + totalDownloadedByte; + Application.DoEvents(); + so.Write(by, 0, osize); + if (IsClose) return; + prog.Invoke(new Action(delegate { prog.Value = (int)totalDownloadedByte; })); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + catch (Exception ex) + { + throw ex; + } + } + private bool IsClose = false; + private void UpdateForm_FormClosing(object sender, FormClosingEventArgs e) + { + IsClose = true; + } + } +} diff --git a/类库/Update/UpdateForm.resx b/类库/Update/UpdateForm.resx new file mode 100644 index 0000000..1bbaeaa --- /dev/null +++ b/类库/Update/UpdateForm.resx @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhSMALXdEABCALwAQfC4AAIkPAxGBMC4lhj9wLIlEoyqK + RM0rjEXwK4xF6iqLRdQriUS8K4lEnx+EO1sKgisbPXtQAB2BOAAWiDQAHYQ4AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAC6TSgAAgh0AAIQjAAAAAAAAAAAAAAAAACR6PAASfzAAAI8cAgp6KDcTejCRH4E50y2M + R/w8mFT/TaJk/1epbv9Tp2r/TKNl/0efX/87llP/KolE8h6AOb8TfDB2FIExJSw9NgAKgysACIIpAAAA + AAAAAAAAAAAAAAAAAAAAAAAALpRKHuxTxQAYfjMABoIoABGCMAAdjD0AGnw1AAyAKxUYezN4HH434DqT + Uv9frXT/h8SY/4/Jn/+Jxpr/hcOW/3/AkP94vYr/crmF/2u2f/9drnL/RZ5d/zONTPsmgj/TGX40VQCF + HwYUgTEAAJonAA2MLwAAAAAAAAAAAAAAAAAphELEHH02aRiFNhIfZzIADocvABp1MgAWfjMvFHcvriuH + RPplr3n/ksui/5vNqf+TyaL/jMac/4XClv99v5D/d7yK/3K5hf9stoD/ZrN6/1+wdf9brnH/Uqpq/z2Y + Vv8kgD3pGXozehqGNQ8jejsAMnNGAACFJAAAAAAAAAAAACqBQv8of0D3GXYytw91Kk4Jjy0IHn85Mx95 + N8dAk1b/hcKV/6HRrv+azqj/k8qi/36/kP9otH3/Waxv/02nZf9KpmP/UKlo/1Oqa/9WrG3/Wa1v/1Op + av9NpmX/R6Vh/zqaVP8rg0P4Inw6nhqCNxkbfjYAMlI7AAAAAAAAAAAALINE/n65jv9YoWz/H3g36x51 + N6gedTbKR5Zd/5fMpf+i0a//ms6o/4LClP9WrG3/PJ9X/y+ZTP8wmkz/MZtO/zKcT/8xm07/MJpN/zWc + Uf8/oFn/SKRh/0akYP9AoVr/O6BW/zSaUP8qgkL8HHY0kACAIgoOfSwACYQrAAAAAAAqf0H+oMys/8Lj + y/+GwJb/PY1T/0mWXf+azqj/o9Kw/5bLpP9qtn//Op5V/y+ZTP8ynE//NZ1R/zOYT/8xkUv/MI9J/zCR + Sv8ylk3/NJ1Q/zOcT/81nFH/PJ9X/zueVf81nFH/NJxQ/zOYTv8ieTr0E3EsagCcIgMLhCwAG3k1ACp+ + Qf2WxqT/vN/G/7Xbv/+g0Kz/m86p/6LSr/+Wy6T/W69y/zGaTf8ym07/NZ5R/zGTS/8pfkD8JHc77Bty + M8wSayu0F28vxiF1OOkpf0H9MZNM/zWdUf80nFD/NZxR/zSbUP80m1D/NZ1R/zCSS/8hdDjiGnUzSSM3 + KgAZfzQAK3xB/JPDof+027//qdS0/6XSsf+g0K3/lsqk/1isb/8wmUz/M5xP/zSbUP8tiEb/H3E25BZu + LYUTdi4zCnAnEwBuFQ0AbB0REnQtMxluMIkgbzbnLIlF/zSdUf80nFD/NJtQ/zSbUP81nlH/M5lP/yZ4 + PP8bbjGvFIExDRh4MgAsekH8kMKe/67Zuv+j0bD/nc6r/5vNqP9ms3v/MJlN/zObT/80m1D/K4BB/yNr + NvcbdjR3AJgkCBVxLgAQcysAAm0gAAttJgAXbzAAAJQqAw5rJ1QYaC3WK4VE/zWeUf81nlH/NZxR/y6K + R/8fcDX1FWksqRJwKz0MgioEEHgsACx4QfyMv5r/qNa1/53Pq/+bzqn/eLyK/zSbUP8ymk//NJtQ/zSc + Uf8ylk3/Kn5B/htpMN4TZiqBD3UrJQDBGwAAiiQAAHQKAA91LAAJfCgARh9CAAhpI0cZZy7jMI5K/zGT + TP8ldjv+HGYwyxJrKWEAdyENHGUxABF4LAAlfT0ALHZA+4i8lv+i06//ms6o/4fEl/9AoVr/MZlN/zSb + UP80m1D/NJtQ/zWdUf82oVP/L4tI/x5kMf8OYCSsA3UhIQR0IwAAdAoAAAAAAAZ2IwAKdCYAALMYAhRm + K3IfZzL2IGg06RZlK4sOciklLTwyAAVtIAAadTMACGwgEyV+PVcsdD/6hLqS/53Qq/+RyaD/Tqhn/y+Z + TP80m1D/NJtQ/zSbUP81nlH/NJtQ/yyERP8gajPxGWMtpwxrJjwBdSAGBHMjAAB0CgAAAAAAAAAAABVh + KQAQcyoADXwrDgxiI3ATaypFE5Q3BRNqKgAIbyIAAGAJBw9xKUYfeDe0Jnw97SxxP/qAt4//m8+p/2y3 + gP8wmk3/M5tP/zSbUP81nVH/NZ5R/y+MSf8gazX6FFwoxBBiJlcNfywOEGYnAAN1IQAEcyMAAHQKAAAA + AAAAAAAAAYkmABtjLgATbiwAGlYtABpgLgAKcCUAAFgAAQBnFykNbieSRItY6EqSXv8meT35K289+X21 + jf+LyJz/QqJc/zGZTf80nFH/NZ9S/zGSTP8kcTn/Glws2BRfKXQIbyQZITknAA96LAAWcy8AAYkmAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAGERAABaBgALcSUAD3ApAABpGxgNbydvKX0/1m+lfv+izK7/P5lY/yV1 + O/krbT74e7SL/2i2ff8xmk3/NZ5S/zOZTv8nej7/GV0s7BFYJZQRaikwAP+hAA5lJQAHgCgADG4mAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9zKgAHcSIAFngyAAFrGQkDah1NEnEsuEyRX/mYwqP/weDJ/3W+ + iP8rjkb/JXE6+i1uP/durYD/QKVc/zKcT/8shET/HmMx9g5VIrAJXyFFBJMqBxRjKgAQmjUAE34wAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtvJgAFaRwADXApAACCEgEPcSg0EXErmjKCSO96roj/tdi+/7ne + w/+bzqj/P6JZ/y2OR/8kbTj6MHBC9kudYf8vj0n/IWo1/RZZKM0TXihjCnwqEhBaJAAMbiYAALwrAAGL + JwAAAAAAAAAAAAAAAAAAAAAAAAAAAABXDAAUfTMADnMoACiBRQAEbCEbEHAqdyJ5Otpam2z/pMyu/7nd + w/+t17n/qNS0/2Kxd/8vm0z/MI9K/yNpNvsmaDf2Imk1/xRZJ94OWSGCDGslHioAAAAOeywAH5I/ACuW + SwAZiTcAMpZNAAmBKQAAAAAAAAAAAAAAAAAAYxEAAGEOABR2LgALciYNEXEpVxRyLsQ9iVL7iryX/7fb + wv+y2r3/pdOx/6HRrv+Fw5b/NZtR/zOdUP8wjkn/IWMz+x5kMeMOViKiBmIfNwCzIAMMZyQAHpA9AACB + GwMVjDU6GI04cQ+GLhUYiDYAap9+AAAAAAAAAAAAAAAAAABjEQAAXwoFD3IpOR55N6QtgUTwbKl9/6vT + tv+13MD/qdW1/6HQrv+azaj/ksqh/06oZ/8wmUz/NZ5R/y+NSP8gXzH8KIFAPgx/KgsKVyAADoswACaU + RQAXjTcdGY04fiSRQeEwlUv5HYk7ghOEMwUXgTQAEXYtAACGJAAAAAAAAGIRAABhDhoUciygI3g6/Wqm + ev+33MH/stu+/6LRr/+bzan/lMqj/5HIoP9rtn//MppO/zObT/81nlH/L4xI/x5bL/whbjYABmwgAByQ + OwAEhScJG487UiKRQL9CoFz8o9Cv/5bIo/8likHrFH0wWP///wARdCwAHHg1AAAAAAAALAAAJKZaAA9u + KB4TbCt3HW802E2OX/2FuJP/mMyn/5DIn/+JxZr/fr+Q/z+gWf8xmk7/NJtQ/zWeUf8vi0j/HVgt/QCB + IQAAbgACFIszMyWTQ5kok0bwcreE/+Hw5f/6/Pv/7/fx/3OzhP8ZfDTfGHkyYA5yKAYVbiwACGIfAABc + FgAMYSEAEWopAABRAAUSZSlqGGQt8jp8TP+Cu5L/hMOV/37Akf9Vq23/MJpN/zSbUP80m1D/NZ5R/y+L + SP8dVy39B4InAAB0DQgcjTuXMZZM/y+YTP+KxZr/9fr2/+n07P/k8ef/1Ora/3Cwgf8kfjztEW8rkwxq + JDoFYRsSAFsQDgtjIRIJXx8zCVsfgRtkL99LjFz/e7mM/4HCk/96vYz/Y7J5/zacUv8zm0//NJxQ/zSb + UP81nlH/L4tI/x1YLf4KgyoAR5lgAB+LPTwrjkbaL5RL/zKbT/+czqn/4O/j/9br2//Q6Nf/yOXQ/4m+ + l/9Cjlj+HXEz7ApgIcsHXB24Dl8kyyJrNes4e0r8YqFz/4PDlP98v47/dLqG/2aze/87n1f/MpxP/zSb + T/80m0//NZ5R/zWeUv8vi0j/HVgt/gqDKgABeSIAAFsAARmANWQnh0HzLpVK/zScUP+Gw5b/yeTQ/8bj + zf+73sT/ut7E/6fTs/+Eu5P/cayB/2Cgcf9mpHj/crGD/4C+kP+AwpL/dbuI/2+4gv9hsXf/QKFa/zKc + T/80m1D/JnM7/yJnNf8vi0j/NqFT/y+OSf8dWC3+AAAAAAZ6JwAOeSsAAG4aCh59OI4rhUT5L5RK/y+a + Tf9brnL/nM6q/7LZvP+q1bX/otGv/57Qq/+Yzab/jsme/4jGmf+BwpL/d7yJ/2+4g/9ptX7/Wa1w/zuf + Vv8znE//NJtQ/yVxOv8YUSjZGFAnrhZSJuskcTn/K4FD/x1ZLv4AAAAAAAAAAP///wAdfzkAGnkzFBt1 + NI8jejr3L5BJ/y6aTP86n1b/XrB0/4fEmP+TyqL/jsie/4nEmf+BwZL/eb2M/3K5hv9rtX7/Xq90/0ak + X/82nFL/M55Q/zKXTv8jbjf/FVAl2Q1NHkYAUw8KBEYTTwtHGbgVUyb4HFYs/wAAAAAAAAAAAF0OACSB + PwAWdC8AAGIWDA1oJn4ecDXvLIVE/zCWTP8wnE3/M5xQ/0ChW/9Uq2z/XrB0/16wdP9arnH/Tqdm/0Gh + Wv82nVH/M51P/zSeUf8th0b/G14t/gpGGcEFRxY/ED8wAAFPEQAOTTEAAEIGEglKGGoZVinHAAAAAAAA + AAAAAAAAAIckABNoKwAFZB4AAFsQCg9iJFkXYyvIIW42+y2HRv8ymE7/M5xP/zGcTv8wnE7/MJxN/zGc + Tv8ynU//M51P/zScUP8tiEX/Ims1/xlVKesNSh2MAEIKIQxKGwAJURkABkgOAABDAAABRA4AN3NvACBi + MSEAAAAAAAAAAAAAAAAAAAAAAAAAAABfFwAAXhYAN4JfAAJXFh0TWSZ4GVwrzxxfLvYkbzn/Kn9C/y2G + Rf8uiUb/LolH/yqAQv8mczv/HV4v/hFOId8GQxWiBUgTSQlWGQUGRBMAGDooAAAAAAAAAAAAAAAAAAA/ + AAAAOAAAH2ExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhcHAACWBEACloeAAAzAAEATxIsDlIgWx1Z + LaAcVSzaG1Mr7BxVK/UcViz2G1Qr3RxVLLUTTyR/AUcSPQA+AAgMShYADFAcAAAeAAAATA0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/AAAPxwAAB8AAAAHAAAAAwAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAA + AAAAACAAAAAwAAAAMAAAAPgAAAPwAAAPwAAAHwAAAA4AAAAOAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAA + AACAAAAAwAAAAMAAAADgAAAA+AAAOPwAAD8= + + + \ No newline at end of file diff --git a/类库/Update/ZIP/BZip2/BZip2.cs b/类库/Update/ZIP/BZip2/BZip2.cs new file mode 100644 index 0000000..91669a8 --- /dev/null +++ b/类库/Update/ZIP/BZip2/BZip2.cs @@ -0,0 +1,105 @@ +// BZip2.cs +// +// Copyright (C) 2010 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// Suppress this in CF and 1.1, not needed. Static classes introduced in C# version 2.0 +#if !NETCF_2_0 && !NET_1_1 + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.BZip2 { + + /// + /// An example class to demonstrate compression and decompression of BZip2 streams. + /// + public static class BZip2 + { + /// + /// Decompress the input writing + /// uncompressed data to the output stream + /// + /// The readable stream containing data to decompress. + /// The output stream to receive the decompressed data. + /// Both streams are closed on completion if true. + public static void Decompress(Stream inStream, Stream outStream, bool isStreamOwner) + { + if (inStream == null || outStream == null) { + throw new Exception("Null Stream"); + } + + try { + using (BZip2InputStream bzipInput = new BZip2InputStream(inStream)) { + bzipInput.IsStreamOwner = isStreamOwner; + Core.StreamUtils.Copy(bzipInput, outStream, new byte[4096]); + } + } finally { + if (isStreamOwner) { + // inStream is closed by the BZip2InputStream if stream owner + outStream.Close(); + } + } + } + + /// + /// Compress the input stream sending + /// result data to output stream + /// + /// The readable stream to compress. + /// The output stream to receive the compressed data. + /// Both streams are closed on completion if true. + /// Block size acts as compression level (1 to 9) with 1 giving + /// the lowest compression and 9 the highest. + public static void Compress(Stream inStream, Stream outStream, bool isStreamOwner, int level) + { + if (inStream == null || outStream == null) { + throw new Exception("Null Stream"); + } + + try { + using (BZip2OutputStream bzipOutput = new BZip2OutputStream(outStream, level)) { + bzipOutput.IsStreamOwner = isStreamOwner; + Core.StreamUtils.Copy(inStream, bzipOutput, new byte[4096]); + } + } finally { + if (isStreamOwner) { + // outStream is closed by the BZip2OutputStream if stream owner + inStream.Close(); + } + } + } + + } +} +#endif diff --git a/类库/Update/ZIP/BZip2/BZip2Constants.cs b/类库/Update/ZIP/BZip2/BZip2Constants.cs new file mode 100644 index 0000000..ad3f40d --- /dev/null +++ b/类库/Update/ZIP/BZip2/BZip2Constants.cs @@ -0,0 +1,197 @@ +// BZip2Constants.cs +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + /// + /// Defines internal values for both compression and decompression + /// + internal sealed class BZip2Constants + { + /// + /// Random numbers used to randomise repetitive blocks + /// + public readonly static int[] RandomNumbers = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 + }; + + /// + /// When multiplied by compression parameter (1-9) gives the block size for compression + /// 9 gives the best compression but uses the most memory. + /// + public const int BaseBlockSize = 100000; + + /// + /// Backend constant + /// + public const int MaximumAlphaSize = 258; + + /// + /// Backend constant + /// + public const int MaximumCodeLength = 23; + + /// + /// Backend constant + /// + public const int RunA = 0; + + /// + /// Backend constant + /// + public const int RunB = 1; + + /// + /// Backend constant + /// + public const int GroupCount = 6; + + /// + /// Backend constant + /// + public const int GroupSize = 50; + + /// + /// Backend constant + /// + public const int NumberOfIterations = 4; + + /// + /// Backend constant + /// + public const int MaximumSelectors = (2 + (900000 / GroupSize)); + + /// + /// Backend constant + /// + public const int OvershootBytes = 20; + + private BZip2Constants() + { + } + } +} + +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/Update/ZIP/BZip2/BZip2Exception.cs b/类库/Update/ZIP/BZip2/BZip2Exception.cs new file mode 100644 index 0000000..3b7c8ff --- /dev/null +++ b/类库/Update/ZIP/BZip2/BZip2Exception.cs @@ -0,0 +1,90 @@ +// BZip2.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + /// + /// BZip2Exception represents exceptions specific to Bzip2 algorithm + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class BZip2Exception : SharpZipBaseException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected BZip2Exception(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + /// + /// Initialise a new instance of BZip2Exception. + /// + public BZip2Exception() + { + } + + /// + /// Initialise a new instance of BZip2Exception with its message set to message. + /// + /// The message describing the error. + public BZip2Exception(string message) : base(message) + { + } + + /// + /// Initialise an instance of BZip2Exception + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public BZip2Exception(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/Update/ZIP/BZip2/BZip2InputStream.cs b/类库/Update/ZIP/BZip2/BZip2InputStream.cs new file mode 100644 index 0000000..162c9d0 --- /dev/null +++ b/类库/Update/ZIP/BZip2/BZip2InputStream.cs @@ -0,0 +1,1003 @@ +// BZip2InputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + /// + /// An input stream that decompresses files in the BZip2 format + /// + public class BZip2InputStream : Stream + { + #region Constants + const int START_BLOCK_STATE = 1; + const int RAND_PART_A_STATE = 2; + const int RAND_PART_B_STATE = 3; + const int RAND_PART_C_STATE = 4; + const int NO_RAND_PART_A_STATE = 5; + const int NO_RAND_PART_B_STATE = 6; + const int NO_RAND_PART_C_STATE = 7; + #endregion + #region Constructors + /// + /// Construct instance for reading from stream + /// + /// Data source + public BZip2InputStream(Stream stream) + { + // init arrays + for (int i = 0; i < BZip2Constants.GroupCount; ++i) + { + limit[i] = new int[BZip2Constants.MaximumAlphaSize]; + baseArray[i] = new int[BZip2Constants.MaximumAlphaSize]; + perm[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + BsSetStream(stream); + Initialize(); + InitBlock(); + SetupBlock(); + } + + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + + #region Stream Overrides + /// + /// Gets a value indicating if the stream supports reading + /// + public override bool CanRead + { + get { + return baseStream.CanRead; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek { + get { + return baseStream.CanSeek; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// This property always returns false + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// Gets the length in bytes of the stream. + /// + public override long Length { + get { + return baseStream.Length; + } + } + + /// + /// Gets or sets the streams position. + /// Setting the position is not supported and will throw a NotSupportException + /// + /// Any attempt to set the position + public override long Position { + get { + return baseStream.Position; + } + set { + throw new NotSupportedException("BZip2InputStream position cannot be set"); + } + } + + /// + /// Flushes the stream. + /// + public override void Flush() + { + if (baseStream != null) { + baseStream.Flush(); + } + } + + /// + /// Set the streams position. This operation is not supported and will throw a NotSupportedException + /// + /// A byte offset relative to the parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// The new position of the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("BZip2InputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. + /// This operation is not supported and will throw a NotSupportedExceptionortedException + /// + /// The new length for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("BZip2InputStream SetLength not supported"); + } + + /// + /// Writes a block of bytes to this stream using data from a buffer. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The buffer to source data from. + /// The offset to start obtaining data from. + /// The number of bytes of data to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("BZip2InputStream Write not supported"); + } + + /// + /// Writes a byte to the current position in the file stream. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The value to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("BZip2InputStream WriteByte not supported"); + } + + /// + /// Read a sequence of bytes and advances the read position by one byte. + /// + /// Array of bytes to store values in + /// Offset in array to begin storing data + /// The maximum number of bytes to read + /// The total number of bytes read into the buffer. This might be less + /// than the number of bytes requested if that number of bytes are not + /// currently available or zero if the end of the stream is reached. + /// + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + for (int i = 0; i < count; ++i) { + int rb = ReadByte(); + if (rb == -1) { + return i; + } + buffer[offset + i] = (byte)rb; + } + return count; + } + + /// + /// Closes the stream, releasing any associated resources. + /// + public override void Close() + { + if ( IsStreamOwner && (baseStream != null) ) { + baseStream.Close(); + } + } + /// + /// Read a byte from stream advancing position + /// + /// byte read or -1 on end of stream + public override int ReadByte() + { + if (streamEnd) + { + return -1; // ok + } + + int retChar = currentChar; + switch (currentState) + { + case RAND_PART_B_STATE: + SetupRandPartB(); + break; + case RAND_PART_C_STATE: + SetupRandPartC(); + break; + case NO_RAND_PART_B_STATE: + SetupNoRandPartB(); + break; + case NO_RAND_PART_C_STATE: + SetupNoRandPartC(); + break; + case START_BLOCK_STATE: + case NO_RAND_PART_A_STATE: + case RAND_PART_A_STATE: + break; + default: + break; + } + return retChar; + } + + #endregion + + void MakeMaps() + { + nInUse = 0; + for (int i = 0; i < 256; ++i) { + if (inUse[i]) { + seqToUnseq[nInUse] = (byte)i; + unseqToSeq[i] = (byte)nInUse; + nInUse++; + } + } + } + + void Initialize() + { + char magic1 = BsGetUChar(); + char magic2 = BsGetUChar(); + + char magic3 = BsGetUChar(); + char magic4 = BsGetUChar(); + + if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') { + streamEnd = true; + return; + } + + SetDecompressStructureSizes(magic4 - '0'); + computedCombinedCRC = 0; + } + + void InitBlock() + { + char magic1 = BsGetUChar(); + char magic2 = BsGetUChar(); + char magic3 = BsGetUChar(); + char magic4 = BsGetUChar(); + char magic5 = BsGetUChar(); + char magic6 = BsGetUChar(); + + if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) { + Complete(); + return; + } + + if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) { + BadBlockHeader(); + streamEnd = true; + return; + } + + storedBlockCRC = BsGetInt32(); + + blockRandomised = (BsR(1) == 1); + + GetAndMoveToFrontDecode(); + + mCrc.Reset(); + currentState = START_BLOCK_STATE; + } + + void EndBlock() + { + computedBlockCRC = (int)mCrc.Value; + + // -- A bad CRC is considered a fatal error. -- + if (storedBlockCRC != computedBlockCRC) { + CrcError(); + } + + // 1528150659 + computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31); + computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC; + } + + void Complete() + { + storedCombinedCRC = BsGetInt32(); + if (storedCombinedCRC != (int)computedCombinedCRC) { + CrcError(); + } + + streamEnd = true; + } + + void BsSetStream(Stream stream) + { + baseStream = stream; + bsLive = 0; + bsBuff = 0; + } + + void FillBuffer() + { + int thech = 0; + + try { + thech = baseStream.ReadByte(); + } catch (Exception) { + CompressedStreamEOF(); + } + + if (thech == -1) { + CompressedStreamEOF(); + } + + bsBuff = (bsBuff << 8) | (thech & 0xFF); + bsLive += 8; + } + + int BsR(int n) + { + while (bsLive < n) { + FillBuffer(); + } + + int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1); + bsLive -= n; + return v; + } + + char BsGetUChar() + { + return (char)BsR(8); + } + + int BsGetIntVS(int numBits) + { + return BsR(numBits); + } + + int BsGetInt32() + { + int result = BsR(8); + result = (result << 8) | BsR(8); + result = (result << 8) | BsR(8); + result = (result << 8) | BsR(8); + return result; + } + + void RecvDecodingTables() + { + char[][] len = new char[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + len[i] = new char[BZip2Constants.MaximumAlphaSize]; + } + + bool[] inUse16 = new bool[16]; + + //--- Receive the mapping table --- + for (int i = 0; i < 16; i++) { + inUse16[i] = (BsR(1) == 1); + } + + for (int i = 0; i < 16; i++) { + if (inUse16[i]) { + for (int j = 0; j < 16; j++) { + inUse[i * 16 + j] = (BsR(1) == 1); + } + } else { + for (int j = 0; j < 16; j++) { + inUse[i * 16 + j] = false; + } + } + } + + MakeMaps(); + int alphaSize = nInUse + 2; + + //--- Now the selectors --- + int nGroups = BsR(3); + int nSelectors = BsR(15); + + for (int i = 0; i < nSelectors; i++) { + int j = 0; + while (BsR(1) == 1) { + j++; + } + selectorMtf[i] = (byte)j; + } + + //--- Undo the MTF values for the selectors. --- + byte[] pos = new byte[BZip2Constants.GroupCount]; + for (int v = 0; v < nGroups; v++) { + pos[v] = (byte)v; + } + + for (int i = 0; i < nSelectors; i++) { + int v = selectorMtf[i]; + byte tmp = pos[v]; + while (v > 0) { + pos[v] = pos[v - 1]; + v--; + } + pos[0] = tmp; + selector[i] = tmp; + } + + //--- Now the coding tables --- + for (int t = 0; t < nGroups; t++) { + int curr = BsR(5); + for (int i = 0; i < alphaSize; i++) { + while (BsR(1) == 1) { + if (BsR(1) == 0) { + curr++; + } else { + curr--; + } + } + len[t][i] = (char)curr; + } + } + + //--- Create the Huffman decoding tables --- + for (int t = 0; t < nGroups; t++) { + int minLen = 32; + int maxLen = 0; + for (int i = 0; i < alphaSize; i++) { + maxLen = Math.Max(maxLen, len[t][i]); + minLen = Math.Min(minLen, len[t][i]); + } + HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize); + minLens[t] = minLen; + } + } + + void GetAndMoveToFrontDecode() + { + byte[] yy = new byte[256]; + int nextSym; + + int limitLast = BZip2Constants.BaseBlockSize * blockSize100k; + origPtr = BsGetIntVS(24); + + RecvDecodingTables(); + int EOB = nInUse+1; + int groupNo = -1; + int groupPos = 0; + + /*-- + Setting up the unzftab entries here is not strictly + necessary, but it does save having to do it later + in a separate pass, and so saves a block's worth of + cache misses. + --*/ + for (int i = 0; i <= 255; i++) { + unzftab[i] = 0; + } + + for (int i = 0; i <= 255; i++) { + yy[i] = (byte)i; + } + + last = -1; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + int zt = selector[groupNo]; + int zn = minLens[zt]; + int zvec = BsR(zn); + int zj; + + while (zvec > limit[zt][zn]) { + if (zn > 20) { // the longest code + throw new BZip2Exception("Bzip data error"); + } + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive-1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) { + throw new BZip2Exception("Bzip data error"); + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + + while (true) { + if (nextSym == EOB) { + break; + } + + if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) { + int s = -1; + int n = 1; + do { + if (nextSym == BZip2Constants.RunA) { + s += (0 + 1) * n; + } else if (nextSym == BZip2Constants.RunB) { + s += (1 + 1) * n; + } + + n <<= 1; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + + while (zvec > limit[zt][zn]) { + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive - 1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + } while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB); + + s++; + byte ch = seqToUnseq[yy[0]]; + unzftab[ch] += s; + + while (s > 0) { + last++; + ll8[last] = ch; + s--; + } + + if (last >= limitLast) { + BlockOverrun(); + } + continue; + } else { + last++; + if (last >= limitLast) { + BlockOverrun(); + } + + byte tmp = yy[nextSym - 1]; + unzftab[seqToUnseq[tmp]]++; + ll8[last] = seqToUnseq[tmp]; + + for (int j = nextSym-1; j > 0; --j) { + yy[j] = yy[j - 1]; + } + yy[0] = tmp; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + while (zvec > limit[zt][zn]) { + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive-1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + continue; + } + } + } + + void SetupBlock() + { + int[] cftab = new int[257]; + + cftab[0] = 0; + Array.Copy(unzftab, 0, cftab, 1, 256); + + for (int i = 1; i <= 256; i++) { + cftab[i] += cftab[i - 1]; + } + + for (int i = 0; i <= last; i++) { + byte ch = ll8[i]; + tt[cftab[ch]] = i; + cftab[ch]++; + } + + cftab = null; + + tPos = tt[origPtr]; + + count = 0; + i2 = 0; + ch2 = 256; /*-- not a char and not EOF --*/ + + if (blockRandomised) { + rNToGo = 0; + rTPos = 0; + SetupRandPartA(); + } else { + SetupNoRandPartA(); + } + } + + void SetupRandPartA() + { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + ch2 ^= (int)((rNToGo == 1) ? 1 : 0); + i2++; + + currentChar = ch2; + currentState = RAND_PART_B_STATE; + mCrc.Update(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + void SetupNoRandPartA() + { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + i2++; + + currentChar = ch2; + currentState = NO_RAND_PART_B_STATE; + mCrc.Update(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + void SetupRandPartB() + { + if (ch2 != chPrev) { + currentState = RAND_PART_A_STATE; + count = 1; + SetupRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + z ^= (byte)((rNToGo == 1) ? 1 : 0); + j2 = 0; + currentState = RAND_PART_C_STATE; + SetupRandPartC(); + } else { + currentState = RAND_PART_A_STATE; + SetupRandPartA(); + } + } + } + + void SetupRandPartC() + { + if (j2 < (int)z) { + currentChar = ch2; + mCrc.Update(ch2); + j2++; + } else { + currentState = RAND_PART_A_STATE; + i2++; + count = 0; + SetupRandPartA(); + } + } + + void SetupNoRandPartB() + { + if (ch2 != chPrev) { + currentState = NO_RAND_PART_A_STATE; + count = 1; + SetupNoRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + currentState = NO_RAND_PART_C_STATE; + j2 = 0; + SetupNoRandPartC(); + } else { + currentState = NO_RAND_PART_A_STATE; + SetupNoRandPartA(); + } + } + } + + void SetupNoRandPartC() + { + if (j2 < (int)z) { + currentChar = ch2; + mCrc.Update(ch2); + j2++; + } else { + currentState = NO_RAND_PART_A_STATE; + i2++; + count = 0; + SetupNoRandPartA(); + } + } + + void SetDecompressStructureSizes(int newSize100k) + { + if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) { + throw new BZip2Exception("Invalid block size"); + } + + blockSize100k = newSize100k; + + if (newSize100k == 0) { + return; + } + + int n = BZip2Constants.BaseBlockSize * newSize100k; + ll8 = new byte[n]; + tt = new int[n]; + } + + static void CompressedStreamEOF() + { + throw new EndOfStreamException("BZip2 input stream end of compressed stream"); + } + + static void BlockOverrun() + { + throw new BZip2Exception("BZip2 input stream block overrun"); + } + + static void BadBlockHeader() + { + throw new BZip2Exception("BZip2 input stream bad block header"); + } + + static void CrcError() + { + throw new BZip2Exception("BZip2 input stream crc error"); + } + + static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize) + { + int pp = 0; + + for (int i = minLen; i <= maxLen; ++i) + { + for (int j = 0; j < alphaSize; ++j) + { + if (length[j] == i) + { + perm[pp] = j; + ++pp; + } + } + } + + for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) + { + baseArray[i] = 0; + } + + for (int i = 0; i < alphaSize; i++) + { + ++baseArray[length[i] + 1]; + } + + for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++) + { + baseArray[i] += baseArray[i - 1]; + } + + for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) + { + limit[i] = 0; + } + + int vec = 0; + + for (int i = minLen; i <= maxLen; i++) + { + vec += (baseArray[i + 1] - baseArray[i]); + limit[i] = vec - 1; + vec <<= 1; + } + + for (int i = minLen + 1; i <= maxLen; i++) + { + baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i]; + } + } + + #region Instance Fields + /*-- + index of the last char in the block, so + the block size == last + 1. + --*/ + int last; + + /*-- + index in zptr[] of original string after sorting. + --*/ + int origPtr; + + /*-- + always: in the range 0 .. 9. + The current block size is 100000 * this number. + --*/ + int blockSize100k; + + bool blockRandomised; + + int bsBuff; + int bsLive; + IChecksum mCrc = new StrangeCRC(); + + bool[] inUse = new bool[256]; + int nInUse; + + byte[] seqToUnseq = new byte[256]; + byte[] unseqToSeq = new byte[256]; + + byte[] selector = new byte[BZip2Constants.MaximumSelectors]; + byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors]; + + int[] tt; + byte[] ll8; + + /*-- + freq table collected to save a pass over the data + during decompression. + --*/ + int[] unzftab = new int[256]; + + int[][] limit = new int[BZip2Constants.GroupCount][]; + int[][] baseArray = new int[BZip2Constants.GroupCount][]; + int[][] perm = new int[BZip2Constants.GroupCount][]; + int[] minLens = new int[BZip2Constants.GroupCount]; + + Stream baseStream; + bool streamEnd; + + int currentChar = -1; + + int currentState = START_BLOCK_STATE; + + int storedBlockCRC, storedCombinedCRC; + int computedBlockCRC; + uint computedCombinedCRC; + + int count, chPrev, ch2; + int tPos; + int rNToGo; + int rTPos; + int i2, j2; + byte z; + bool isStreamOwner = true; + #endregion + } +} +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/Update/ZIP/BZip2/BZip2OutputStream.cs b/类库/Update/ZIP/BZip2/BZip2OutputStream.cs new file mode 100644 index 0000000..582f7a4 --- /dev/null +++ b/类库/Update/ZIP/BZip2/BZip2OutputStream.cs @@ -0,0 +1,1916 @@ +// BZip2OutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + // TODO: Update to BZip2 1.0.1, 1.0.2 + + /// + /// An output stream that compresses into the BZip2 format + /// including file header chars into another stream. + /// + public class BZip2OutputStream : Stream + { + #region Constants + const int SETMASK = (1 << 21); + const int CLEARMASK = (~SETMASK); + const int GREATER_ICOST = 15; + const int LESSER_ICOST = 0; + const int SMALL_THRESH = 20; + const int DEPTH_THRESH = 10; + + /*-- + If you are ever unlucky/improbable enough + to get a stack overflow whilst sorting, + increase the following constant and try + again. In practice I have never seen the + stack go above 27 elems, so the following + limit seems very generous. + --*/ + const int QSORT_STACK_SIZE = 1000; + + /*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. + --*/ + readonly int[] increments = new int[] { + 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 + }; + #endregion + + #region Constructors + /// + /// Construct a default output stream with maximum block size + /// + /// The stream to write BZip data onto. + public BZip2OutputStream(Stream stream) : this(stream, 9) + { + } + + /// + /// Initialise a new instance of the + /// for the specified stream, using the given blocksize. + /// + /// The stream to write compressed data to. + /// The block size to use. + /// + /// Valid block sizes are in the range 1..9, with 1 giving + /// the lowest compression and 9 the highest. + /// + public BZip2OutputStream(Stream stream, int blockSize) + { + BsSetStream(stream); + + workFactor = 50; + if (blockSize > 9) { + blockSize = 9; + } + + if (blockSize < 1) { + blockSize = 1; + } + blockSize100k = blockSize; + AllocateCompressStructures(); + Initialize(); + InitBlock(); + } + #endregion + + #region Destructor + /// + /// Ensures that resources are freed and other cleanup operations + /// are performed when the garbage collector reclaims the BZip2OutputStream. + /// + ~BZip2OutputStream() + { + Dispose(false); + } + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + + #region Stream overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing + /// + public override bool CanWrite { + get { + return baseStream.CanWrite; + } + } + + /// + /// Gets the length in bytes of the stream + /// + public override long Length { + get { + return baseStream.Length; + } + } + + /// + /// Gets or sets the current position of this stream. + /// + public override long Position { + get { + return baseStream.Position; + } + set { + throw new NotSupportedException("BZip2OutputStream position cannot be set"); + } + } + + /// + /// Sets the current position of this stream to the given value. + /// + /// The point relative to the offset from which to being seeking. + /// The reference point from which to begin seeking. + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("BZip2OutputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. + /// + /// The new stream length. + public override void SetLength(long value) + { + throw new NotSupportedException("BZip2OutputStream SetLength not supported"); + } + + /// + /// Read a byte from the stream advancing the position. + /// + /// The byte read cast to an int; -1 if end of stream. + public override int ReadByte() + { + throw new NotSupportedException("BZip2OutputStream ReadByte not supported"); + } + + /// + /// Read a block of bytes + /// + /// The buffer to read into. + /// The offset in the buffer to start storing data at. + /// The maximum number of bytes to read. + /// The total number of bytes read. This might be less than the number of bytes + /// requested if that number of bytes are not currently available, or zero + /// if the end of the stream is reached. + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("BZip2OutputStream Read not supported"); + } + + /// + /// Write a block of bytes to the stream + /// + /// The buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + public override void Write(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( count < 0 ) + { + throw new ArgumentOutOfRangeException("count"); + } + + if ( buffer.Length - offset < count ) + { + throw new ArgumentException("Offset/count out of range"); + } + + for (int i = 0; i < count; ++i) { + WriteByte(buffer[offset + i]); + } + } + + /// + /// Write a byte to the stream. + /// + /// The byte to write to the stream. + public override void WriteByte(byte value) + { + int b = (256 + value) % 256; + if (currentChar != -1) { + if (currentChar == b) { + runLength++; + if (runLength > 254) { + WriteRun(); + currentChar = -1; + runLength = 0; + } + } else { + WriteRun(); + runLength = 1; + currentChar = b; + } + } else { + currentChar = b; + runLength++; + } + } + + /// + /// End the current block and end compression. + /// Close the stream and free any resources + /// + public override void Close() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + void MakeMaps() + { + nInUse = 0; + for (int i = 0; i < 256; i++) { + if (inUse[i]) { + seqToUnseq[nInUse] = (char)i; + unseqToSeq[i] = (char)nInUse; + nInUse++; + } + } + } + + /// + /// Get the number of bytes written to output. + /// + void WriteRun() + { + if (last < allowableBlockSize) { + inUse[currentChar] = true; + for (int i = 0; i < runLength; i++) { + mCrc.Update(currentChar); + } + + switch (runLength) { + case 1: + last++; + block[last + 1] = (byte)currentChar; + break; + case 2: + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + break; + case 3: + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + break; + default: + inUse[runLength - 4] = true; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)(runLength - 4); + break; + } + } else { + EndBlock(); + InitBlock(); + WriteRun(); + } + } + + /// + /// Get the number of bytes written to the output. + /// + public int BytesWritten + { + get { return bytesOut; } + } + + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. +#if NET_1_0 || NET_1_1 || NETCF_1_0 + protected virtual void Dispose(bool disposing) +#else + override protected void Dispose(bool disposing) +#endif + { + try { +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + base.Dispose(disposing); +#endif + if( !disposed_ ) { + disposed_=true; + + if( runLength>0 ) { + WriteRun(); + } + + currentChar=-1; + EndBlock(); + EndCompression(); + Flush(); + } + } + finally { + if ( disposing ) { + if ( IsStreamOwner ) { + baseStream.Close(); + } + } + } + } + + /// + /// Flush output buffers + /// + public override void Flush() + { + baseStream.Flush(); + } + + void Initialize() + { + bytesOut = 0; + nBlocksRandomised = 0; + + /*--- Write header `magic' bytes indicating file-format == huffmanised, + followed by a digit indicating blockSize100k. + ---*/ + + BsPutUChar('B'); + BsPutUChar('Z'); + + BsPutUChar('h'); + BsPutUChar('0' + blockSize100k); + + combinedCRC = 0; + } + + void InitBlock() + { + mCrc.Reset(); + last = -1; + + for (int i = 0; i < 256; i++) { + inUse[i] = false; + } + + /*--- 20 is just a paranoia constant ---*/ + allowableBlockSize = BZip2Constants.BaseBlockSize * blockSize100k - 20; + } + + void EndBlock() + { + if (last < 0) { // dont do anything for empty files, (makes empty files compatible with original Bzip) + return; + } + + blockCRC = unchecked((uint)mCrc.Value); + combinedCRC = (combinedCRC << 1) | (combinedCRC >> 31); + combinedCRC ^= blockCRC; + + /*-- sort the block and establish position of original string --*/ + DoReversibleTransformation(); + + /*-- + A 6-byte block header, the value chosen arbitrarily + as 0x314159265359 :-). A 32 bit value does not really + give a strong enough guarantee that the value will not + appear by chance in the compressed datastream. Worst-case + probability of this event, for a 900k block, is about + 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits. + For a compressed file of size 100Gb -- about 100000 blocks -- + only a 48-bit marker will do. NB: normal compression/ + decompression do *not* rely on these statistical properties. + They are only important when trying to recover blocks from + damaged files. + --*/ + BsPutUChar(0x31); + BsPutUChar(0x41); + BsPutUChar(0x59); + BsPutUChar(0x26); + BsPutUChar(0x53); + BsPutUChar(0x59); + + /*-- Now the block's CRC, so it is in a known place. --*/ + unchecked { + BsPutint((int)blockCRC); + } + + /*-- Now a single bit indicating randomisation. --*/ + if (blockRandomised) { + BsW(1,1); + nBlocksRandomised++; + } else { + BsW(1,0); + } + + /*-- Finally, block's contents proper. --*/ + MoveToFrontCodeAndSend(); + } + + void EndCompression() + { + /*-- + Now another magic 48-bit number, 0x177245385090, to + indicate the end of the last block. (sqrt(pi), if + you want to know. I did want to use e, but it contains + too much repetition -- 27 18 28 18 28 46 -- for me + to feel statistically comfortable. Call me paranoid.) + --*/ + BsPutUChar(0x17); + BsPutUChar(0x72); + BsPutUChar(0x45); + BsPutUChar(0x38); + BsPutUChar(0x50); + BsPutUChar(0x90); + + unchecked { + BsPutint((int)combinedCRC); + } + + BsFinishedWithStream(); + } + + void BsSetStream(Stream stream) + { + baseStream = stream; + bsLive = 0; + bsBuff = 0; + bytesOut = 0; + } + + void BsFinishedWithStream() + { + while (bsLive > 0) + { + int ch = (bsBuff >> 24); + baseStream.WriteByte((byte)ch); // write 8-bit + bsBuff <<= 8; + bsLive -= 8; + bytesOut++; + } + } + + void BsW(int n, int v) + { + while (bsLive >= 8) { + int ch = (bsBuff >> 24); + unchecked{baseStream.WriteByte((byte)ch);} // write 8-bit + bsBuff <<= 8; + bsLive -= 8; + ++bytesOut; + } + bsBuff |= (v << (32 - bsLive - n)); + bsLive += n; + } + + void BsPutUChar(int c) + { + BsW(8, c); + } + + void BsPutint(int u) + { + BsW(8, (u >> 24) & 0xFF); + BsW(8, (u >> 16) & 0xFF); + BsW(8, (u >> 8) & 0xFF); + BsW(8, u & 0xFF); + } + + void BsPutIntVS(int numBits, int c) + { + BsW(numBits, c); + } + + void SendMTFValues() + { + char[][] len = new char[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + len[i] = new char[BZip2Constants.MaximumAlphaSize]; + } + + int gs, ge, totc, bt, bc, iter; + int nSelectors = 0, alphaSize, minLen, maxLen, selCtr; + int nGroups; + + alphaSize = nInUse + 2; + for (int t = 0; t < BZip2Constants.GroupCount; t++) { + for (int v = 0; v < alphaSize; v++) { + len[t][v] = (char)GREATER_ICOST; + } + } + + /*--- Decide how many coding tables to use ---*/ + if (nMTF <= 0) { + Panic(); + } + + if (nMTF < 200) { + nGroups = 2; + } else if (nMTF < 600) { + nGroups = 3; + } else if (nMTF < 1200) { + nGroups = 4; + } else if (nMTF < 2400) { + nGroups = 5; + } else { + nGroups = 6; + } + + /*--- Generate an initial set of coding tables ---*/ + int nPart = nGroups; + int remF = nMTF; + gs = 0; + while (nPart > 0) { + int tFreq = remF / nPart; + int aFreq = 0; + ge = gs - 1; + while (aFreq < tFreq && ge < alphaSize - 1) { + ge++; + aFreq += mtfFreq[ge]; + } + + if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups - nPart) % 2 == 1)) { + aFreq -= mtfFreq[ge]; + ge--; + } + + for (int v = 0; v < alphaSize; v++) { + if (v >= gs && v <= ge) { + len[nPart - 1][v] = (char)LESSER_ICOST; + } else { + len[nPart - 1][v] = (char)GREATER_ICOST; + } + } + + nPart--; + gs = ge + 1; + remF -= aFreq; + } + + int[][] rfreq = new int[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + rfreq[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + int[] fave = new int[BZip2Constants.GroupCount]; + short[] cost = new short[BZip2Constants.GroupCount]; + /*--- + Iterate up to N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZip2Constants.NumberOfIterations; ++iter) { + for (int t = 0; t < nGroups; ++t) { + fave[t] = 0; + } + + for (int t = 0; t < nGroups; ++t) { + for (int v = 0; v < alphaSize; ++v) { + rfreq[t][v] = 0; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (true) { + /*--- Set group start & end marks. --*/ + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.GroupSize - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (int t = 0; t < nGroups; t++) { + cost[t] = 0; + } + + if (nGroups == 6) { + short cost0, cost1, cost2, cost3, cost4, cost5; + cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0; + for (int i = gs; i <= ge; ++i) { + short icv = szptr[i]; + cost0 += (short)len[0][icv]; + cost1 += (short)len[1][icv]; + cost2 += (short)len[2][icv]; + cost3 += (short)len[3][icv]; + cost4 += (short)len[4][icv]; + cost5 += (short)len[5][icv]; + } + cost[0] = cost0; + cost[1] = cost1; + cost[2] = cost2; + cost[3] = cost3; + cost[4] = cost4; + cost[5] = cost5; + } else { + for (int i = gs; i <= ge; ++i) { + short icv = szptr[i]; + for (int t = 0; t < nGroups; t++) { + cost[t] += (short)len[t][icv]; + } + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; + bt = -1; + for (int t = 0; t < nGroups; ++t) { + if (cost[t] < bc) { + bc = cost[t]; + bt = t; + } + } + totc += bc; + fave[bt]++; + selector[nSelectors] = (char)bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + for (int i = gs; i <= ge; ++i) { + ++rfreq[bt][szptr[i]]; + } + + gs = ge+1; + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + for (int t = 0; t < nGroups; ++t) { + HbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20); + } + } + + rfreq = null; + fave = null; + cost = null; + + if (!(nGroups < 8)) { + Panic(); + } + + if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZip2Constants.GroupSize)))) { + Panic(); + } + + /*--- Compute MTF values for the selectors. ---*/ + char[] pos = new char[BZip2Constants.GroupCount]; + char ll_i, tmp2, tmp; + + for (int i = 0; i < nGroups; i++) { + pos[i] = (char)i; + } + + for (int i = 0; i < nSelectors; i++) { + ll_i = selector[i]; + int j = 0; + tmp = pos[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + } + pos[0] = tmp; + selectorMtf[i] = (char)j; + } + + int[][] code = new int[BZip2Constants.GroupCount][]; + + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + code[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + /*--- Assign actual codes for the tables. --*/ + for (int t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (int i = 0; i < alphaSize; i++) { + if (len[t][i] > maxLen) { + maxLen = len[t][i]; + } + if (len[t][i] < minLen) { + minLen = len[t][i]; + } + } + if (maxLen > 20) { + Panic(); + } + if (minLen < 1) { + Panic(); + } + HbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize); + } + + /*--- Transmit the mapping table. ---*/ + bool[] inUse16 = new bool[16]; + for (int i = 0; i < 16; ++i) { + inUse16[i] = false; + for (int j = 0; j < 16; ++j) { + if (inUse[i * 16 + j]) { + inUse16[i] = true; + } + } + } + + for (int i = 0; i < 16; ++i) { + if (inUse16[i]) { + BsW(1,1); + } else { + BsW(1,0); + } + } + + for (int i = 0; i < 16; ++i) { + if (inUse16[i]) { + for (int j = 0; j < 16; ++j) { + if (inUse[i * 16 + j]) { + BsW(1,1); + } else { + BsW(1,0); + } + } + } + } + + /*--- Now the selectors. ---*/ + BsW(3, nGroups); + BsW(15, nSelectors); + for (int i = 0; i < nSelectors; ++i) { + for (int j = 0; j < selectorMtf[i]; ++j) { + BsW(1,1); + } + BsW(1,0); + } + + /*--- Now the coding tables. ---*/ + for (int t = 0; t < nGroups; ++t) { + int curr = len[t][0]; + BsW(5, curr); + for (int i = 0; i < alphaSize; ++i) { + while (curr < len[t][i]) { + BsW(2, 2); + curr++; /* 10 */ + } + while (curr > len[t][i]) { + BsW(2, 3); + curr--; /* 11 */ + } + BsW (1, 0); + } + } + + /*--- And finally, the block data proper ---*/ + selCtr = 0; + gs = 0; + while (true) { + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.GroupSize - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + for (int i = gs; i <= ge; i++) { + BsW(len[selector[selCtr]][szptr[i]], code[selector[selCtr]][szptr[i]]); + } + + gs = ge + 1; + ++selCtr; + } + if (!(selCtr == nSelectors)) { + Panic(); + } + } + + void MoveToFrontCodeAndSend () + { + BsPutIntVS(24, origPtr); + GenerateMTFValues(); + SendMTFValues(); + } + + void SimpleSort(int lo, int hi, int d) + { + int i, j, h, bigN, hp; + int v; + + bigN = hi - lo + 1; + if (bigN < 2) { + return; + } + + hp = 0; + while (increments[hp] < bigN) { + hp++; + } + hp--; + + for (; hp >= 0; hp--) { + h = increments[hp]; + + i = lo + h; + while (true) { + /*-- copy 1 --*/ + if (i > hi) + break; + v = zptr[i]; + j = i; + while (FullGtU(zptr[j-h]+d, v+d)) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) + break; + } + zptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU ( zptr[j-h]+d, v+d )) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU ( zptr[j-h]+d, v+d)) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + if (workDone > workLimit && firstAttempt) { + return; + } + } + } + } + + void Vswap(int p1, int p2, int n ) + { + int temp = 0; + while (n > 0) { + temp = zptr[p1]; + zptr[p1] = zptr[p2]; + zptr[p2] = temp; + p1++; + p2++; + n--; + } + } + + void QSort3(int loSt, int hiSt, int dSt) + { + int unLo, unHi, ltLo, gtHi, med, n, m; + int lo, hi, d; + + StackElement[] stack = new StackElement[QSORT_STACK_SIZE]; + + int sp = 0; + + stack[sp].ll = loSt; + stack[sp].hh = hiSt; + stack[sp].dd = dSt; + sp++; + + while (sp > 0) { + if (sp >= QSORT_STACK_SIZE) { + Panic(); + } + + sp--; + lo = stack[sp].ll; + hi = stack[sp].hh; + d = stack[sp].dd; + + if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) { + SimpleSort(lo, hi, d); + if (workDone > workLimit && firstAttempt) { + return; + } + continue; + } + + med = Med3(block[zptr[lo] + d + 1], + block[zptr[hi ] + d + 1], + block[zptr[(lo + hi) >> 1] + d + 1]); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (true) { + while (true) { + if (unLo > unHi) { + break; + } + n = ((int)block[zptr[unLo]+d + 1]) - med; + if (n == 0) { + int temp = zptr[unLo]; + zptr[unLo] = zptr[ltLo]; + zptr[ltLo] = temp; + ltLo++; + unLo++; + continue; + } + if (n > 0) { + break; + } + unLo++; + } + + while (true) { + if (unLo > unHi) { + break; + } + n = ((int)block[zptr[unHi]+d + 1]) - med; + if (n == 0) { + int temp = zptr[unHi]; + zptr[unHi] = zptr[gtHi]; + zptr[gtHi] = temp; + gtHi--; + unHi--; + continue; + } + if (n < 0) { + break; + } + unHi--; + } + + if (unLo > unHi) { + break; + } + + { + int temp = zptr[unLo]; + zptr[unLo] = zptr[unHi]; + zptr[unHi] = temp; + unLo++; + unHi--; + } + } + + if (gtHi < ltLo) { + stack[sp].ll = lo; + stack[sp].hh = hi; + stack[sp].dd = d+1; + sp++; + continue; + } + + n = ((ltLo-lo) < (unLo-ltLo)) ? (ltLo-lo) : (unLo-ltLo); + Vswap(lo, unLo-n, n); + m = ((hi-gtHi) < (gtHi-unHi)) ? (hi-gtHi) : (gtHi-unHi); + Vswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + stack[sp].ll = lo; + stack[sp].hh = n; + stack[sp].dd = d; + sp++; + + stack[sp].ll = n + 1; + stack[sp].hh = m - 1; + stack[sp].dd = d+1; + sp++; + + stack[sp].ll = m; + stack[sp].hh = hi; + stack[sp].dd = d; + sp++; + } + } + + void MainSort() + { + int i, j, ss, sb; + int[] runningOrder = new int[256]; + int[] copy = new int[256]; + bool[] bigDone = new bool[256]; + int c1, c2; + int numQSorted; + + /*-- + In the various block-sized structures, live data runs + from 0 to last+NUM_OVERSHOOT_BYTES inclusive. First, + set up the overshoot area for block. + --*/ + + // if (verbosity >= 4) fprintf ( stderr, " sort initialise ...\n" ); + for (i = 0; i < BZip2Constants.OvershootBytes; i++) { + block[last + i + 2] = block[(i % (last + 1)) + 1]; + } + for (i = 0; i <= last + BZip2Constants.OvershootBytes; i++) { + quadrant[i] = 0; + } + + block[0] = (byte)(block[last + 1]); + + if (last < 4000) { + /*-- + Use simpleSort(), since the full sorting mechanism + has quite a large constant overhead. + --*/ + for (i = 0; i <= last; i++) { + zptr[i] = i; + } + firstAttempt = false; + workDone = workLimit = 0; + SimpleSort(0, last, 0); + } else { + numQSorted = 0; + for (i = 0; i <= 255; i++) { + bigDone[i] = false; + } + for (i = 0; i <= 65536; i++) { + ftab[i] = 0; + } + + c1 = block[0]; + for (i = 0; i <= last; i++) { + c2 = block[i + 1]; + ftab[(c1 << 8) + c2]++; + c1 = c2; + } + + for (i = 1; i <= 65536; i++) { + ftab[i] += ftab[i - 1]; + } + + c1 = block[1]; + for (i = 0; i < last; i++) { + c2 = block[i + 2]; + j = (c1 << 8) + c2; + c1 = c2; + ftab[j]--; + zptr[ftab[j]] = i; + } + + j = ((block[last + 1]) << 8) + (block[1]); + ftab[j]--; + zptr[ftab[j]] = last; + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + + for (i = 0; i <= 255; i++) { + runningOrder[i] = i; + } + + int vv; + int h = 1; + do { + h = 3 * h + 1; + } while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ((ftab[((runningOrder[j-h])+1) << 8] - ftab[(runningOrder[j-h]) << 8]) > (ftab[((vv)+1) << 8] - ftab[(vv) << 8])) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) { + break; + } + } + runningOrder[j] = vv; + } + } while (h != 1); + + /*-- + The main sorting loop. + --*/ + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + --*/ + ss = runningOrder[i]; + + /*-- + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j]. Hopefully + previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + sb = (ss << 8) + j; + if(!((ftab[sb] & SETMASK) == SETMASK)) { + int lo = ftab[sb] & CLEARMASK; + int hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + QSort3(lo, hi, 2); + numQSorted += (hi - lo + 1); + if (workDone > workLimit && firstAttempt) { + return; + } + } + ftab[sb] |= SETMASK; + } + } + + /*-- + The ss big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + --*/ + bigDone[ss] = true; + + if (i < 255) { + int bbStart = ftab[ss << 8] & CLEARMASK; + int bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + int shifts = 0; + + while ((bbSize >> shifts) > 65534) { + shifts++; + } + + for (j = 0; j < bbSize; j++) { + int a2update = zptr[bbStart + j]; + int qVal = (j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZip2Constants.OvershootBytes) { + quadrant[a2update + last + 1] = qVal; + } + } + + if (!(((bbSize-1) >> shifts) <= 65535)) { + Panic(); + } + } + + /*-- + Now scan this big bucket so as to synthesise the + sorted order for small buckets [t, ss] for all t != ss. + --*/ + for (j = 0; j <= 255; j++) { + copy[j] = ftab[(j << 8) + ss] & CLEARMASK; + } + + for (j = ftab[ss << 8] & CLEARMASK; j < (ftab[(ss+1) << 8] & CLEARMASK); j++) { + c1 = block[zptr[j]]; + if (!bigDone[c1]) { + zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1; + copy[c1] ++; + } + } + + for (j = 0; j <= 255; j++) { + ftab[(j << 8) + ss] |= SETMASK; + } + } + } + } + + void RandomiseBlock() + { + int i; + int rNToGo = 0; + int rTPos = 0; + for (i = 0; i < 256; i++) { + inUse[i] = false; + } + + for (i = 0; i <= last; i++) { + if (rNToGo == 0) { + rNToGo = (int)BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + block[i + 1] ^= (byte)((rNToGo == 1) ? 1 : 0); + // handle 16 bit signed numbers + block[i + 1] &= 0xFF; + + inUse[block[i + 1]] = true; + } + } + + void DoReversibleTransformation() + { + workLimit = workFactor * last; + workDone = 0; + blockRandomised = false; + firstAttempt = true; + + MainSort(); + + if (workDone > workLimit && firstAttempt) { + RandomiseBlock(); + workLimit = workDone = 0; + blockRandomised = true; + firstAttempt = false; + MainSort(); + } + + origPtr = -1; + for (int i = 0; i <= last; i++) { + if (zptr[i] == 0) { + origPtr = i; + break; + } + } + + if (origPtr == -1) { + Panic(); + } + } + + bool FullGtU(int i1, int i2) + { + int k; + byte c1, c2; + int s1, s2; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + k = last + 1; + + do { + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + if (i1 > last) { + i1 -= last; + i1--; + } + if (i2 > last) { + i2 -= last; + i2--; + } + + k -= 4; + ++workDone; + } while (k >= 0); + + return false; + } + + void AllocateCompressStructures() + { + int n = BZip2Constants.BaseBlockSize * blockSize100k; + block = new byte[(n + 1 + BZip2Constants.OvershootBytes)]; + quadrant = new int[(n + BZip2Constants.OvershootBytes)]; + zptr = new int[n]; + ftab = new int[65537]; + + if (block == null || quadrant == null || zptr == null || ftab == null) { + // int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537; + // compressOutOfMemory ( totalDraw, n ); + } + + /* + The back end needs a place to store the MTF values + whilst it calculates the coding tables. We could + put them in the zptr array. However, these values + will fit in a short, so we overlay szptr at the + start of zptr, in the hope of reducing the number + of cache misses induced by the multiple traversals + of the MTF values when calculating coding tables. + Seems to improve compression speed by about 1%. + */ + // szptr = zptr; + + + szptr = new short[2 * n]; + } + + void GenerateMTFValues() + { + char[] yy = new char[256]; + int i, j; + char tmp; + char tmp2; + int zPend; + int wr; + int EOB; + + MakeMaps(); + EOB = nInUse+1; + + for (i = 0; i <= EOB; i++) { + mtfFreq[i] = 0; + } + + wr = 0; + zPend = 0; + for (i = 0; i < nInUse; i++) { + yy[i] = (char) i; + } + + + for (i = 0; i <= last; i++) { + char ll_i; + + ll_i = unseqToSeq[block[zptr[i]]]; + + j = 0; + tmp = yy[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = yy[j]; + yy[j] = tmp2; + } + yy[0] = tmp; + + if (j == 0) { + zPend++; + } else { + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short)BZip2Constants.RunA; + wr++; + mtfFreq[BZip2Constants.RunA]++; + break; + case 1: + szptr[wr] = (short)BZip2Constants.RunB; + wr++; + mtfFreq[BZip2Constants.RunB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + zPend = 0; + } + szptr[wr] = (short)(j + 1); + wr++; + mtfFreq[j + 1]++; + } + } + + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short)BZip2Constants.RunA; + wr++; + mtfFreq[BZip2Constants.RunA]++; + break; + case 1: + szptr[wr] = (short)BZip2Constants.RunB; + wr++; + mtfFreq[BZip2Constants.RunB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + } + + szptr[wr] = (short)EOB; + wr++; + mtfFreq[EOB]++; + + nMTF = wr; + } + + static void Panic() + { + throw new BZip2Exception("BZip2 output stream panic"); + } + + static void HbMakeCodeLengths(char[] len, int[] freq, int alphaSize, int maxLen) + { + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + int nNodes, nHeap, n1, n2, j, k; + bool tooLong; + + int[] heap = new int[BZip2Constants.MaximumAlphaSize + 2]; + int[] weight = new int[BZip2Constants.MaximumAlphaSize * 2]; + int[] parent = new int[BZip2Constants.MaximumAlphaSize * 2]; + + for (int i = 0; i < alphaSize; ++i) + { + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + } + + while (true) + { + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (int i = 1; i <= alphaSize; ++i) + { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + int zz = nHeap; + int tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) + { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + if (!(nHeap < (BZip2Constants.MaximumAlphaSize+2))) + { + Panic(); + } + + while (nHeap > 1) + { + n1 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + int zz = 1; + int yy = 0; + int tmp = heap[zz]; + while (true) + { + yy = zz << 1; + if (yy > nHeap) + { + break; + } + if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) + { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) + { + break; + } + + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + n2 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + + zz = 1; + yy = 0; + tmp = heap[zz]; + while (true) + { + yy = zz << 1; + if (yy > nHeap) + { + break; + } + if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) + { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) + { + break; + } + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + nNodes++; + parent[n1] = parent[n2] = nNodes; + + weight[nNodes] = (int)((weight[n1] & 0xffffff00) + (weight[n2] & 0xffffff00)) | + (int)(1 + (((weight[n1] & 0x000000ff) > (weight[n2] & 0x000000ff)) ? (weight[n1] & 0x000000ff) : (weight[n2] & 0x000000ff))); + + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + + zz = nHeap; + tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) + { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + if (!(nNodes < (BZip2Constants.MaximumAlphaSize * 2))) + { + Panic(); + } + + tooLong = false; + for (int i = 1; i <= alphaSize; ++i) + { + j = 0; + k = i; + while (parent[k] >= 0) + { + k = parent[k]; + j++; + } + len[i - 1] = (char)j; + if (j > maxLen) + { + tooLong = true; + } + } + + if (!tooLong) + { + break; + } + + for (int i = 1; i < alphaSize; ++i) + { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } + } + + static void HbAssignCodes (int[] code, char[] length, int minLen, int maxLen, int alphaSize) + { + int vec = 0; + for (int n = minLen; n <= maxLen; ++n) + { + for (int i = 0; i < alphaSize; ++i) + { + if (length[i] == n) + { + code[i] = vec; + ++vec; + } + } + vec <<= 1; + } + } + + static byte Med3(byte a, byte b, byte c ) + { + byte t; + if (a > b) + { + t = a; + a = b; + b = t; + } + if (b > c) + { + t = b; + b = c; + c = t; + } + if (a > b) + { + b = a; + } + return b; + } + + struct StackElement + { + public int ll; + public int hh; + public int dd; + } + + #region Instance Fields + bool isStreamOwner = true; + + /*-- + index of the last char in the block, so + the block size == last + 1. + --*/ + int last; + + /*-- + index in zptr[] of original string after sorting. + --*/ + int origPtr; + + /*-- + always: in the range 0 .. 9. + The current block size is 100000 * this number. + --*/ + int blockSize100k; + + bool blockRandomised; + + int bytesOut; + int bsBuff; + int bsLive; + IChecksum mCrc = new StrangeCRC(); + + bool[] inUse = new bool[256]; + int nInUse; + + char[] seqToUnseq = new char[256]; + char[] unseqToSeq = new char[256]; + + char[] selector = new char[BZip2Constants.MaximumSelectors]; + char[] selectorMtf = new char[BZip2Constants.MaximumSelectors]; + + byte[] block; + int[] quadrant; + int[] zptr; + short[] szptr; + int[] ftab; + + int nMTF; + + int[] mtfFreq = new int[BZip2Constants.MaximumAlphaSize]; + + /* + * Used when sorting. If too many long comparisons + * happen, we stop sorting, randomise the block + * slightly, and try again. + */ + int workFactor; + int workDone; + int workLimit; + bool firstAttempt; + int nBlocksRandomised; + + int currentChar = -1; + int runLength; + uint blockCRC, combinedCRC; + int allowableBlockSize; + Stream baseStream; + bool disposed_; + #endregion + } +} + +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/Update/ZIP/Checksums/Adler32.cs b/类库/Update/ZIP/Checksums/Adler32.cs new file mode 100644 index 0000000..6e358bc --- /dev/null +++ b/类库/Update/ZIP/Checksums/Adler32.cs @@ -0,0 +1,237 @@ +// Adler32.cs - Computes Adler32 data checksum of a data stream +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Computes Adler32 checksum for a stream of data. An Adler32 + /// checksum is not as reliable as a CRC32 checksum, but a lot faster to + /// compute. + /// + /// The specification for Adler32 may be found in RFC 1950. + /// ZLIB Compressed Data Format Specification version 3.3) + /// + /// + /// From that document: + /// + /// "ADLER32 (Adler-32 checksum) + /// This contains a checksum value of the uncompressed data + /// (excluding any dictionary data) computed according to Adler-32 + /// algorithm. This algorithm is a 32-bit extension and improvement + /// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + /// standard. + /// + /// Adler-32 is composed of two sums accumulated per byte: s1 is + /// the sum of all bytes, s2 is the sum of all s1 values. Both sums + /// are done modulo 65521. s1 is initialized to 1, s2 to zero. The + /// Adler-32 checksum is stored as s2*65536 + s1 in most- + /// significant-byte first (network) order." + /// + /// "8.2. The Adler-32 algorithm + /// + /// The Adler-32 algorithm is much faster than the CRC32 algorithm yet + /// still provides an extremely low probability of undetected errors. + /// + /// The modulo on unsigned long accumulators can be delayed for 5552 + /// bytes, so the modulo operation time is negligible. If the bytes + /// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + /// and order sensitive, unlike the first sum, which is just a + /// checksum. That 65521 is prime is important to avoid a possible + /// large class of two-byte errors that leave the check unchanged. + /// (The Fletcher checksum uses 255, which is not prime and which also + /// makes the Fletcher check insensitive to single byte changes 0 - + /// 255.) + /// + /// The sum s1 is initialized to 1 instead of zero to make the length + /// of the sequence part of s2, so that the length does not have to be + /// checked separately. (Any sequence of zeroes has a Fletcher + /// checksum of zero.)" + /// + /// + /// + public sealed class Adler32 : IChecksum + { + /// + /// largest prime smaller than 65536 + /// + const uint BASE = 65521; + + /// + /// Returns the Adler32 data checksum computed so far. + /// + public long Value { + get { + return checksum; + } + } + + /// + /// Creates a new instance of the Adler32 class. + /// The checksum starts off with a value of 1. + /// + public Adler32() + { + Reset(); + } + + /// + /// Resets the Adler32 checksum to the initial value. + /// + public void Reset() + { + checksum = 1; + } + + /// + /// Updates the checksum with a byte value. + /// + /// + /// The data value to add. The high byte of the int is ignored. + /// + public void Update(int value) + { + // We could make a length 1 byte array and call update again, but I + // would rather not have that overhead + uint s1 = checksum & 0xFFFF; + uint s2 = checksum >> 16; + + s1 = (s1 + ((uint)value & 0xFF)) % BASE; + s2 = (s1 + s2) % BASE; + + checksum = (s2 << 16) + s1; + } + + /// + /// Updates the checksum with an array of bytes. + /// + /// + /// The source of the data to update with. + /// + public void Update(byte[] buffer) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Updates the checksum with the bytes taken from the array. + /// + /// + /// an array of bytes + /// + /// + /// the start of the data used for this update + /// + /// + /// the number of bytes to use for this update + /// + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if (offset < 0) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "cannot be negative"); +#endif + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "cannot be negative"); +#endif + } + + if (offset >= buffer.Length) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "not a valid index into buffer"); +#endif + } + + if (offset + count > buffer.Length) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "exceeds buffer size"); +#endif + } + + //(By Per Bothner) + uint s1 = checksum & 0xFFFF; + uint s2 = checksum >> 16; + + while (count > 0) { + // We can defer the modulo operation: + // s1 maximally grows from 65521 to 65521 + 255 * 3800 + // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 + int n = 3800; + if (n > count) { + n = count; + } + count -= n; + while (--n >= 0) { + s1 = s1 + (uint)(buffer[offset++] & 0xff); + s2 = s2 + s1; + } + s1 %= BASE; + s2 %= BASE; + } + + checksum = (s2 << 16) | s1; + } + + #region Instance Fields + uint checksum; + #endregion + } +} diff --git a/类库/Update/ZIP/Checksums/CRC32.cs b/类库/Update/ZIP/Checksums/CRC32.cs new file mode 100644 index 0000000..41d5b4b --- /dev/null +++ b/类库/Update/ZIP/Checksums/CRC32.cs @@ -0,0 +1,223 @@ +// CRC32.cs - Computes CRC32 data checksum of a data stream +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + /// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + /// + /// Polynomials over GF(2) are represented in binary, one bit per coefficient, + /// with the lowest powers in the most significant bit. Then adding polynomials + /// is just exclusive-or, and multiplying a polynomial by x is a right shift by + /// one. If we call the above polynomial p, and represent a byte as the + /// polynomial q, also with the lowest power in the most significant bit (so the + /// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + /// where a mod b means the remainder after dividing a by b. + /// + /// This calculation is done using the shift-register method of multiplying and + /// taking the remainder. The register is initialized to zero, and for each + /// incoming bit, x^32 is added mod p to the register if the bit is a one (where + /// x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + /// x (which is shifting right by one and adding x^32 mod p if the bit shifted + /// out is a one). We start with the highest power (least significant bit) of + /// q and repeat for all eight bits of q. + /// + /// The table is simply the CRC of all possible eight bit values. This is all + /// the information needed to generate CRC's on data a byte at a time for all + /// combinations of CRC register values and incoming bytes. + /// + public sealed class Crc32 : IChecksum + { + const uint CrcSeed = 0xFFFFFFFF; + + readonly static uint[] CrcTable = new uint[] { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, + 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, + 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, + 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, + 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, + 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, + 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, + 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, + 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, + 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, + 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, + 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, + 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, + 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, + 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, + 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, + 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, + 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, + 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, + 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, + 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, + 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, + 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, + 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, + 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, + 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, + 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, + 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, + 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, + 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, + 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, + 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, + 0x2D02EF8D + }; + + internal static uint ComputeCrc32(uint oldCrc, byte value) + { + return (uint)(Crc32.CrcTable[(oldCrc ^ value) & 0xFF] ^ (oldCrc >> 8)); + } + + /// + /// The crc data checksum so far. + /// + uint crc; + + /// + /// Returns the CRC32 data checksum computed so far. + /// + public long Value { + get { + return (long)crc; + } + set { + crc = (uint)value; + } + } + + /// + /// Resets the CRC32 data checksum as if no update was ever called. + /// + public void Reset() + { + crc = 0; + } + + /// + /// Updates the checksum with the int bval. + /// + /// + /// the byte is taken as the lower 8 bits of value + /// + public void Update(int value) + { + crc ^= CrcSeed; + crc = CrcTable[(crc ^ value) & 0xFF] ^ (crc >> 8); + crc ^= CrcSeed; + } + + /// + /// Updates the checksum with the bytes taken from the array. + /// + /// + /// buffer an array of bytes + /// + public void Update(byte[] buffer) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Adds the byte array to the data checksum. + /// + /// + /// The buffer which contains the data + /// + /// + /// The offset in the buffer where the data starts + /// + /// + /// The number of data bytes to update the CRC with. + /// + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Count cannot be less than zero"); +#endif + } + + if (offset < 0 || offset + count > buffer.Length) { + throw new ArgumentOutOfRangeException("offset"); + } + + crc ^= CrcSeed; + + while (--count >= 0) { + crc = CrcTable[(crc ^ buffer[offset++]) & 0xFF] ^ (crc >> 8); + } + + crc ^= CrcSeed; + } + } +} diff --git a/类库/Update/ZIP/Checksums/IChecksum.cs b/类库/Update/ZIP/Checksums/IChecksum.cs new file mode 100644 index 0000000..e2679f9 --- /dev/null +++ b/类库/Update/ZIP/Checksums/IChecksum.cs @@ -0,0 +1,93 @@ +// IChecksum.cs - Interface to compute a data checksum +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Interface to compute a data checksum used by checked input/output streams. + /// A data checksum can be updated by one byte or with a byte array. After each + /// update the value of the current checksum can be returned by calling + /// getValue. The complete checksum object can also be reset + /// so it can be used again with new data. + /// + public interface IChecksum + { + /// + /// Returns the data checksum computed so far. + /// + long Value + { + get; + } + + /// + /// Resets the data checksum as if no update was ever called. + /// + void Reset(); + + /// + /// Adds one byte to the data checksum. + /// + /// + /// the data value to add. The high byte of the int is ignored. + /// + void Update(int value); + + /// + /// Updates the data checksum with the bytes taken from the array. + /// + /// + /// buffer an array of bytes + /// + void Update(byte[] buffer); + + /// + /// Adds the byte array to the data checksum. + /// + /// + /// The buffer which contains the data + /// + /// + /// The offset in the buffer where the data starts + /// + /// + /// the number of data bytes to add. + /// + void Update(byte[] buffer, int offset, int count); + } +} diff --git a/类库/Update/ZIP/Checksums/StrangeCRC.cs b/类库/Update/ZIP/Checksums/StrangeCRC.cs new file mode 100644 index 0000000..6ed7679 --- /dev/null +++ b/类库/Update/ZIP/Checksums/StrangeCRC.cs @@ -0,0 +1,208 @@ +// StrangeCRC.cs - computes a crc used in the bziplib +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + /// + /// Bzip2 checksum algorithm + /// + public class StrangeCRC : IChecksum + { + readonly static uint[] crc32Table = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + }; + + int globalCrc; + + /// + /// Initialise a default instance of + /// + public StrangeCRC() + { + Reset(); + } + + /// + /// Reset the state of Crc. + /// + public void Reset() + { + globalCrc = -1; + } + + /// + /// Get the current Crc value. + /// + public long Value { + get { + return ~globalCrc; + } + } + + /// + /// Update the Crc value. + /// + /// data update is based on + public void Update(int value) + { + int temp = (globalCrc >> 24) ^ value; + if (temp < 0) { + temp = 256 + temp; + } + globalCrc = unchecked((int)((globalCrc << 8) ^ crc32Table[temp])); + } + + /// + /// Update Crc based on a block of data + /// + /// The buffer containing data to update the crc with. + public void Update(byte[] buffer) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Update Crc based on a portion of a block of data + /// + /// block of data + /// index of first byte to use + /// number of bytes to use + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "cannot be less than zero"); +#endif + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "cannot be less than zero"); +#endif + } + + if ( offset + count > buffer.Length ) + { + throw new ArgumentOutOfRangeException("count"); + } + + for (int i = 0; i < count; ++i) { + Update(buffer[offset++]); + } + } + } +} diff --git a/类库/Update/ZIP/Core/FileSystemScanner.cs b/类库/Update/ZIP/Core/FileSystemScanner.cs new file mode 100644 index 0000000..4077a45 --- /dev/null +++ b/类库/Update/ZIP/Core/FileSystemScanner.cs @@ -0,0 +1,533 @@ +// FileSystemScanner.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +using System; + +namespace ICSharpCode.SharpZipLib.Core +{ + #region EventArgs + /// + /// Event arguments for scanning. + /// + public class ScanEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file or directory name. + public ScanEventArgs(string name) + { + name_ = name; + } + #endregion + + /// + /// The file or directory name for this event. + /// + public string Name + { + get { return name_; } + } + + /// + /// Get set a value indicating if scanning should continue or not. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + #region Instance Fields + string name_; + bool continueRunning_ = true; + #endregion + } + + /// + /// Event arguments during processing of a single file or directory. + /// + public class ProgressEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file or directory name if known. + /// The number of bytes processed so far + /// The total number of bytes to process, 0 if not known + public ProgressEventArgs(string name, long processed, long target) + { + name_ = name; + processed_ = processed; + target_ = target; + } + #endregion + + /// + /// The name for this event if known. + /// + public string Name + { + get { return name_; } + } + + /// + /// Get set a value indicating wether scanning should continue or not. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + /// + /// Get a percentage representing how much of the has been processed + /// + /// 0.0 to 100.0 percent; 0 if target is not known. + public float PercentComplete + { + get + { + float result; + if (target_ <= 0) + { + result = 0; + } + else + { + result = ((float)processed_ / (float)target_) * 100.0f; + } + return result; + } + } + + /// + /// The number of bytes processed so far + /// + public long Processed + { + get { return processed_; } + } + + /// + /// The number of bytes to process. + /// + /// Target may be 0 or negative if the value isnt known. + public long Target + { + get { return target_; } + } + + #region Instance Fields + string name_; + long processed_; + long target_; + bool continueRunning_ = true; + #endregion + } + + /// + /// Event arguments for directories. + /// + public class DirectoryEventArgs : ScanEventArgs + { + #region Constructors + /// + /// Initialize an instance of . + /// + /// The name for this directory. + /// Flag value indicating if any matching files are contained in this directory. + public DirectoryEventArgs(string name, bool hasMatchingFiles) + : base (name) + { + hasMatchingFiles_ = hasMatchingFiles; + } + #endregion + + /// + /// Get a value indicating if the directory contains any matching files or not. + /// + public bool HasMatchingFiles + { + get { return hasMatchingFiles_; } + } + + #region Instance Fields + bool hasMatchingFiles_; + #endregion + } + + /// + /// Arguments passed when scan failures are detected. + /// + public class ScanFailureEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The name to apply. + /// The exception to use. + public ScanFailureEventArgs(string name, Exception e) + { + name_ = name; + exception_ = e; + continueRunning_ = true; + } + #endregion + + /// + /// The applicable name. + /// + public string Name + { + get { return name_; } + } + + /// + /// The applicable exception. + /// + public Exception Exception + { + get { return exception_; } + } + + /// + /// Get / set a value indicating wether scanning should continue. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + #region Instance Fields + string name_; + Exception exception_; + bool continueRunning_; + #endregion + } + + #endregion + + #region Delegates + /// + /// Delegate invoked before starting to process a directory. + /// + public delegate void ProcessDirectoryHandler(object sender, DirectoryEventArgs e); + + /// + /// Delegate invoked before starting to process a file. + /// + /// The source of the event + /// The event arguments. + public delegate void ProcessFileHandler(object sender, ScanEventArgs e); + + /// + /// Delegate invoked during processing of a file or directory + /// + /// The source of the event + /// The event arguments. + public delegate void ProgressHandler(object sender, ProgressEventArgs e); + + /// + /// Delegate invoked when a file has been completely processed. + /// + /// The source of the event + /// The event arguments. + public delegate void CompletedFileHandler(object sender, ScanEventArgs e); + + /// + /// Delegate invoked when a directory failure is detected. + /// + /// The source of the event + /// The event arguments. + public delegate void DirectoryFailureHandler(object sender, ScanFailureEventArgs e); + + /// + /// Delegate invoked when a file failure is detected. + /// + /// The source of the event + /// The event arguments. + public delegate void FileFailureHandler(object sender, ScanFailureEventArgs e); + #endregion + + /// + /// FileSystemScanner provides facilities scanning of files and directories. + /// + public class FileSystemScanner + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file filter to apply when scanning. + public FileSystemScanner(string filter) + { + fileFilter_ = new PathFilter(filter); + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + /// The directory filter to apply. + public FileSystemScanner(string fileFilter, string directoryFilter) + { + fileFilter_ = new PathFilter(fileFilter); + directoryFilter_ = new PathFilter(directoryFilter); + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + public FileSystemScanner(IScanFilter fileFilter) + { + fileFilter_ = fileFilter; + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + /// The directory filter to apply. + public FileSystemScanner(IScanFilter fileFilter, IScanFilter directoryFilter) + { + fileFilter_ = fileFilter; + directoryFilter_ = directoryFilter; + } + #endregion + + #region Delegates + /// + /// Delegate to invoke when a directory is processed. + /// + public ProcessDirectoryHandler ProcessDirectory; + + /// + /// Delegate to invoke when a file is processed. + /// + public ProcessFileHandler ProcessFile; + + /// + /// Delegate to invoke when processing for a file has finished. + /// + public CompletedFileHandler CompletedFile; + + /// + /// Delegate to invoke when a directory failure is detected. + /// + public DirectoryFailureHandler DirectoryFailure; + + /// + /// Delegate to invoke when a file failure is detected. + /// + public FileFailureHandler FileFailure; + #endregion + + /// + /// Raise the DirectoryFailure event. + /// + /// The directory name. + /// The exception detected. + bool OnDirectoryFailure(string directory, Exception e) + { + DirectoryFailureHandler handler = DirectoryFailure; + bool result = (handler != null); + if ( result ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e); + handler(this, args); + alive_ = args.ContinueRunning; + } + return result; + } + + /// + /// Raise the FileFailure event. + /// + /// The file name. + /// The exception detected. + bool OnFileFailure(string file, Exception e) + { + FileFailureHandler handler = FileFailure; + + bool result = (handler != null); + + if ( result ){ + ScanFailureEventArgs args = new ScanFailureEventArgs(file, e); + FileFailure(this, args); + alive_ = args.ContinueRunning; + } + return result; + } + + /// + /// Raise the ProcessFile event. + /// + /// The file name. + void OnProcessFile(string file) + { + ProcessFileHandler handler = ProcessFile; + + if ( handler!= null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Raise the complete file event + /// + /// The file name + void OnCompleteFile(string file) + { + CompletedFileHandler handler = CompletedFile; + + if (handler != null) + { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Raise the ProcessDirectory event. + /// + /// The directory name. + /// Flag indicating if the directory has matching files. + void OnProcessDirectory(string directory, bool hasMatchingFiles) + { + ProcessDirectoryHandler handler = ProcessDirectory; + + if ( handler != null ) { + DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Scan a directory. + /// + /// The base directory to scan. + /// True to recurse subdirectories, false to scan a single directory. + public void Scan(string directory, bool recurse) + { + alive_ = true; + ScanDir(directory, recurse); + } + + void ScanDir(string directory, bool recurse) + { + + try { + string[] names = System.IO.Directory.GetFiles(directory); + bool hasMatch = false; + for (int fileIndex = 0; fileIndex < names.Length; ++fileIndex) { + if ( !fileFilter_.IsMatch(names[fileIndex]) ) { + names[fileIndex] = null; + } else { + hasMatch = true; + } + } + + OnProcessDirectory(directory, hasMatch); + + if ( alive_ && hasMatch ) { + foreach (string fileName in names) { + try { + if ( fileName != null ) { + OnProcessFile(fileName); + if ( !alive_ ) { + break; + } + } + } + catch (Exception e) { + if (!OnFileFailure(fileName, e)) { + throw; + } + } + } + } + } + catch (Exception e) { + if (!OnDirectoryFailure(directory, e)) { + throw; + } + } + + if ( alive_ && recurse ) { + try { + string[] names = System.IO.Directory.GetDirectories(directory); + foreach (string fulldir in names) { + if ((directoryFilter_ == null) || (directoryFilter_.IsMatch(fulldir))) { + ScanDir(fulldir, true); + if ( !alive_ ) { + break; + } + } + } + } + catch (Exception e) { + if (!OnDirectoryFailure(directory, e)) { + throw; + } + } + } + } + + #region Instance Fields + /// + /// The file filter currently in use. + /// + IScanFilter fileFilter_; + /// + /// The directory filter currently in use. + /// + IScanFilter directoryFilter_; + /// + /// Flag indicating if scanning should continue running. + /// + bool alive_; + #endregion + } +} diff --git a/类库/Update/ZIP/Core/INameTransform.cs b/类库/Update/ZIP/Core/INameTransform.cs new file mode 100644 index 0000000..88c934f --- /dev/null +++ b/类库/Update/ZIP/Core/INameTransform.cs @@ -0,0 +1,57 @@ +// INameTransform.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// INameTransform defines how file system names are transformed for use with archives, or vice versa. + /// + public interface INameTransform + { + /// + /// Given a file name determine the transformed value. + /// + /// The name to transform. + /// The transformed file name. + string TransformFile(string name); + + /// + /// Given a directory name determine the transformed value. + /// + /// The name to transform. + /// The transformed directory name + string TransformDirectory(string name); + } +} diff --git a/类库/Update/ZIP/Core/IScanFilter.cs b/类库/Update/ZIP/Core/IScanFilter.cs new file mode 100644 index 0000000..64c99a8 --- /dev/null +++ b/类库/Update/ZIP/Core/IScanFilter.cs @@ -0,0 +1,50 @@ +// IScanFilter.cs +// +// Copyright 2006 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// Scanning filters support filtering of names. + /// + public interface IScanFilter + { + /// + /// Test a name to see if it 'matches' the filter. + /// + /// The name to test. + /// Returns true if the name matches the filter, false if it does not match. + bool IsMatch(string name); + } +} diff --git a/类库/Update/ZIP/Core/NameFilter.cs b/类库/Update/ZIP/Core/NameFilter.cs new file mode 100644 index 0000000..eea8fbe --- /dev/null +++ b/类库/Update/ZIP/Core/NameFilter.cs @@ -0,0 +1,290 @@ +// NameFilter.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2010-03-03 Z-1654 Fixed bug where escape characters were excluded in SplitQuoted() + +using System; +using System.Collections; +using System.Text; +using System.Text.RegularExpressions; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// NameFilter is a string matching class which allows for both positive and negative + /// matching. + /// A filter is a sequence of independant regular expressions separated by semi-colons ';'. + /// To include a semi-colon it may be quoted as in \;. Each expression can be prefixed by a plus '+' sign or + /// a minus '-' sign to denote the expression is intended to include or exclude names. + /// If neither a plus or minus sign is found include is the default. + /// A given name is tested for inclusion before checking exclusions. Only names matching an include spec + /// and not matching an exclude spec are deemed to match the filter. + /// An empty filter matches any name. + /// + /// The following expression includes all name ending in '.dat' with the exception of 'dummy.dat' + /// "+\.dat$;-^dummy\.dat$" + /// + public class NameFilter : IScanFilter + { + #region Constructors + /// + /// Construct an instance based on the filter expression passed + /// + /// The filter expression. + public NameFilter(string filter) + { + filter_ = filter; + inclusions_ = new ArrayList(); + exclusions_ = new ArrayList(); + Compile(); + } + #endregion + + /// + /// Test a string to see if it is a valid regular expression. + /// + /// The expression to test. + /// True if expression is a valid false otherwise. + public static bool IsValidExpression(string expression) + { + bool result = true; + try { + Regex exp = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + catch (ArgumentException) { + result = false; + } + return result; + } + + /// + /// Test an expression to see if it is valid as a filter. + /// + /// The filter expression to test. + /// True if the expression is valid, false otherwise. + public static bool IsValidFilterExpression(string toTest) + { + if ( toTest == null ) { + throw new ArgumentNullException("toTest"); + } + + bool result = true; + + try { + string[] items = SplitQuoted(toTest); + for (int i = 0; i < items.Length; ++i) { + if ((items[i] != null) && (items[i].Length > 0)) { + string toCompile; + + if (items[i][0] == '+') { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else if (items[i][0] == '-') { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else { + toCompile = items[i]; + } + + Regex testRegex = new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + } + } + catch (ArgumentException) { + result = false; + } + + return result; + } + + /// + /// Split a string into its component pieces + /// + /// The original string + /// Returns an array of values containing the individual filter elements. + public static string[] SplitQuoted(string original) + { + char escape = '\\'; + char[] separators = { ';' }; + + ArrayList result = new ArrayList(); + + if ((original != null) && (original.Length > 0)) { + int endIndex = -1; + StringBuilder b = new StringBuilder(); + + while (endIndex < original.Length) { + endIndex += 1; + if (endIndex >= original.Length) { + result.Add(b.ToString()); + } + else if (original[endIndex] == escape) { + endIndex += 1; + if (endIndex >= original.Length) { +#if NETCF_1_0 + throw new ArgumentException("Missing terminating escape character"); +#else + throw new ArgumentException("Missing terminating escape character", "original"); +#endif + } + // include escape if this is not an escaped separator + if (Array.IndexOf(separators, original[endIndex]) < 0) + b.Append(escape); + + b.Append(original[endIndex]); + } + else { + if (Array.IndexOf(separators, original[endIndex]) >= 0) { + result.Add(b.ToString()); + b.Length = 0; + } + else { + b.Append(original[endIndex]); + } + } + } + } + + return (string[])result.ToArray(typeof(string)); + } + + /// + /// Convert this filter to its string equivalent. + /// + /// The string equivalent for this filter. + public override string ToString() + { + return filter_; + } + + /// + /// Test a value to see if it is included by the filter. + /// + /// The value to test. + /// True if the value is included, false otherwise. + public bool IsIncluded(string name) + { + bool result = false; + if ( inclusions_.Count == 0 ) { + result = true; + } + else { + foreach ( Regex r in inclusions_ ) { + if ( r.IsMatch(name) ) { + result = true; + break; + } + } + } + return result; + } + + /// + /// Test a value to see if it is excluded by the filter. + /// + /// The value to test. + /// True if the value is excluded, false otherwise. + public bool IsExcluded(string name) + { + bool result = false; + foreach ( Regex r in exclusions_ ) { + if ( r.IsMatch(name) ) { + result = true; + break; + } + } + return result; + } + + #region IScanFilter Members + /// + /// Test a value to see if it matches the filter. + /// + /// The value to test. + /// True if the value matches, false otherwise. + public bool IsMatch(string name) + { + return (IsIncluded(name) && !IsExcluded(name)); + } + #endregion + + /// + /// Compile this filter. + /// + void Compile() + { + // TODO: Check to see if combining RE's makes it faster/smaller. + // simple scheme would be to have one RE for inclusion and one for exclusion. + if ( filter_ == null ) { + return; + } + + string[] items = SplitQuoted(filter_); + for ( int i = 0; i < items.Length; ++i ) { + if ( (items[i] != null) && (items[i].Length > 0) ) { + bool include = (items[i][0] != '-'); + string toCompile; + + if ( items[i][0] == '+' ) { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else if ( items[i][0] == '-' ) { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else { + toCompile = items[i]; + } + + // NOTE: Regular expressions can fail to compile here for a number of reasons that cause an exception + // these are left unhandled here as the caller is responsible for ensuring all is valid. + // several functions IsValidFilterExpression and IsValidExpression are provided for such checking + if ( include ) { + inclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)); + } + else { + exclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)); + } + } + } + } + + #region Instance Fields + string filter_; + ArrayList inclusions_; + ArrayList exclusions_; + #endregion + } +} diff --git a/类库/Update/ZIP/Core/PathFilter.cs b/类库/Update/ZIP/Core/PathFilter.cs new file mode 100644 index 0000000..03b8ff3 --- /dev/null +++ b/类库/Update/ZIP/Core/PathFilter.cs @@ -0,0 +1,334 @@ +// PathFilter.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// PathFilter filters directories and files using a form of regular expressions + /// by full path name. + /// See NameFilter for more detail on filtering. + /// + public class PathFilter : IScanFilter + { + #region Constructors + /// + /// Initialise a new instance of . + /// + /// The filter expression to apply. + public PathFilter(string filter) + { + nameFilter_ = new NameFilter(filter); + } + #endregion + + #region IScanFilter Members + /// + /// Test a name to see if it matches the filter. + /// + /// The name to test. + /// True if the name matches, false otherwise. + /// is used to get the full path before matching. + public virtual bool IsMatch(string name) + { + bool result = false; + + if ( name != null ) { + string cooked = (name.Length > 0) ? Path.GetFullPath(name) : ""; + result = nameFilter_.IsMatch(cooked); + } + return result; + } + #endregion + + #region Instance Fields + NameFilter nameFilter_; + #endregion + } + + /// + /// ExtendedPathFilter filters based on name, file size, and the last write time of the file. + /// + /// Provides an example of how to customise filtering. + public class ExtendedPathFilter : PathFilter + { + #region Constructors + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + public ExtendedPathFilter(string filter, + long minSize, long maxSize) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + } + + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum to include. + /// The maximum to include. + public ExtendedPathFilter(string filter, + DateTime minDate, DateTime maxDate) + : base(filter) + { + MinDate = minDate; + MaxDate = maxDate; + } + + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + /// The minimum to include. + /// The maximum to include. + public ExtendedPathFilter(string filter, + long minSize, long maxSize, + DateTime minDate, DateTime maxDate) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + MinDate = minDate; + MaxDate = maxDate; + } + #endregion + + #region IScanFilter Members + /// + /// Test a filename to see if it matches the filter. + /// + /// The filename to test. + /// True if the filter matches, false otherwise. + /// The doesnt exist + public override bool IsMatch(string name) + { + bool result = base.IsMatch(name); + + if ( result ) { + FileInfo fileInfo = new FileInfo(name); + result = + (MinSize <= fileInfo.Length) && + (MaxSize >= fileInfo.Length) && + (MinDate <= fileInfo.LastWriteTime) && + (MaxDate >= fileInfo.LastWriteTime) + ; + } + return result; + } + #endregion + + #region Properties + /// + /// Get/set the minimum size/length for a file that will match this filter. + /// + /// The default value is zero. + /// value is less than zero; greater than + public long MinSize + { + get { return minSize_; } + set + { + if ( (value < 0) || (maxSize_ < value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + minSize_ = value; + } + } + + /// + /// Get/set the maximum size/length for a file that will match this filter. + /// + /// The default value is + /// value is less than zero or less than + public long MaxSize + { + get { return maxSize_; } + set + { + if ( (value < 0) || (minSize_ > value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + maxSize_ = value; + } + } + + /// + /// Get/set the minimum value that will match for this filter. + /// + /// Files with a LastWrite time less than this value are excluded by the filter. + public DateTime MinDate + { + get + { + return minDate_; + } + + set + { + if ( value > maxDate_ ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Exceeds MaxDate"); +#endif + } + + minDate_ = value; + } + } + + /// + /// Get/set the maximum value that will match for this filter. + /// + /// Files with a LastWrite time greater than this value are excluded by the filter. + public DateTime MaxDate + { + get + { + return maxDate_; + } + + set + { + if ( minDate_ > value ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Exceeds MinDate"); +#endif + } + + maxDate_ = value; + } + } + #endregion + + #region Instance Fields + long minSize_; + long maxSize_ = long.MaxValue; + DateTime minDate_ = DateTime.MinValue; + DateTime maxDate_ = DateTime.MaxValue; + #endregion + } + + /// + /// NameAndSizeFilter filters based on name and file size. + /// + /// A sample showing how filters might be extended. + [Obsolete("Use ExtendedPathFilter instead")] + public class NameAndSizeFilter : PathFilter + { + + /// + /// Initialise a new instance of NameAndSizeFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + public NameAndSizeFilter(string filter, long minSize, long maxSize) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + } + + /// + /// Test a filename to see if it matches the filter. + /// + /// The filename to test. + /// True if the filter matches, false otherwise. + public override bool IsMatch(string name) + { + bool result = base.IsMatch(name); + + if ( result ) { + FileInfo fileInfo = new FileInfo(name); + long length = fileInfo.Length; + result = + (MinSize <= length) && + (MaxSize >= length); + } + return result; + } + + /// + /// Get/set the minimum size for a file that will match this filter. + /// + public long MinSize + { + get { return minSize_; } + set { + if ( (value < 0) || (maxSize_ < value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + minSize_ = value; + } + } + + /// + /// Get/set the maximum size for a file that will match this filter. + /// + public long MaxSize + { + get { return maxSize_; } + set + { + if ( (value < 0) || (minSize_ > value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + maxSize_ = value; + } + } + + #region Instance Fields + long minSize_; + long maxSize_ = long.MaxValue; + #endregion + } +} diff --git a/类库/Update/ZIP/Core/StreamUtils.cs b/类库/Update/ZIP/Core/StreamUtils.cs new file mode 100644 index 0000000..7abdce8 --- /dev/null +++ b/类库/Update/ZIP/Core/StreamUtils.cs @@ -0,0 +1,246 @@ +// StreamUtils.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// Provides simple " utilities. + /// + public sealed class StreamUtils + { + /// + /// Read from a ensuring all the required data is read. + /// + /// The stream to read. + /// The buffer to fill. + /// + static public void ReadFully(Stream stream, byte[] buffer) + { + ReadFully(stream, buffer, 0, buffer.Length); + } + + /// + /// Read from a " ensuring all the required data is read. + /// + /// The stream to read data from. + /// The buffer to store data in. + /// The offset at which to begin storing data. + /// The number of bytes of data to store. + /// Required parameter is null + /// and or are invalid. + /// End of stream is encountered before all the data has been read. + static public void ReadFully(Stream stream, byte[] buffer, int offset, int count) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + // Offset can equal length when buffer and count are 0. + if ( (offset < 0) || (offset > buffer.Length) ) { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( (count < 0) || (offset + count > buffer.Length) ) { + throw new ArgumentOutOfRangeException("count"); + } + + while ( count > 0 ) { + int readCount = stream.Read(buffer, offset, count); + if ( readCount <= 0 ) { + throw new EndOfStreamException(); + } + offset += readCount; + count -= readCount; + } + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + static public void Copy(Stream source, Stream destination, byte[] buffer) + { + if (source == null) { + throw new ArgumentNullException("source"); + } + + if (destination == null) { + throw new ArgumentNullException("destination"); + } + + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + // Ensure a reasonable size of buffer is used without being prohibitive. + if (buffer.Length < 128) { + throw new ArgumentException("Buffer is too small", "buffer"); + } + + bool copying = true; + + while (copying) { + int bytesRead = source.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) { + destination.Write(buffer, 0, bytesRead); + } + else { + destination.Flush(); + copying = false; + } + } + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + /// The progress handler delegate to use. + /// The minimum between progress updates. + /// The source for this event. + /// The name to use with the event. + /// This form is specialised for use within #Zip to support events during archive operations. + static public void Copy(Stream source, Stream destination, + byte[] buffer, ProgressHandler progressHandler, TimeSpan updateInterval, object sender, string name) + { + Copy(source, destination, buffer, progressHandler, updateInterval, sender, name, -1); + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + /// The progress handler delegate to use. + /// The minimum between progress updates. + /// The source for this event. + /// The name to use with the event. + /// A predetermined fixed target value to use with progress updates. + /// If the value is negative the target is calculated by looking at the stream. + /// This form is specialised for use within #Zip to support events during archive operations. + static public void Copy(Stream source, Stream destination, + byte[] buffer, + ProgressHandler progressHandler, TimeSpan updateInterval, + object sender, string name, long fixedTarget) + { + if (source == null) { + throw new ArgumentNullException("source"); + } + + if (destination == null) { + throw new ArgumentNullException("destination"); + } + + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + // Ensure a reasonable size of buffer is used without being prohibitive. + if (buffer.Length < 128) { + throw new ArgumentException("Buffer is too small", "buffer"); + } + + if (progressHandler == null) { + throw new ArgumentNullException("progressHandler"); + } + + bool copying = true; + + DateTime marker = DateTime.Now; + long processed = 0; + long target = 0; + + if (fixedTarget >= 0) { + target = fixedTarget; + } + else if (source.CanSeek) { + target = source.Length - source.Position; + } + + // Always fire 0% progress.. + ProgressEventArgs args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + + bool progressFired = true; + + while (copying) { + int bytesRead = source.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) { + processed += bytesRead; + progressFired = false; + destination.Write(buffer, 0, bytesRead); + } + else { + destination.Flush(); + copying = false; + } + + if (DateTime.Now - marker > updateInterval) { + progressFired = true; + marker = DateTime.Now; + args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + + copying = args.ContinueRunning; + } + } + + if (!progressFired) { + args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + } + } + + /// + /// Initialise an instance of + /// + private StreamUtils() + { + // Do nothing. + } + } +} diff --git a/类库/Update/ZIP/Core/WindowsPathUtils.cs b/类库/Update/ZIP/Core/WindowsPathUtils.cs new file mode 100644 index 0000000..2091945 --- /dev/null +++ b/类库/Update/ZIP/Core/WindowsPathUtils.cs @@ -0,0 +1,94 @@ +// WindowsPathUtils.cs +// +// Copyright 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// WindowsPathUtils provides simple utilities for handling windows paths. + /// + public abstract class WindowsPathUtils + { + /// + /// Initializes a new instance of the class. + /// + internal WindowsPathUtils() + { + } + + /// + /// Remove any path root present in the path + /// + /// A containing path information. + /// The path with the root removed if it was present; path otherwise. + /// Unlike the class the path isnt otherwise checked for validity. + public static string DropPathRoot(string path) + { + string result = path; + + if ( (path != null) && (path.Length > 0) ) { + if ((path[0] == '\\') || (path[0] == '/')) { + // UNC name ? + if ((path.Length > 1) && ((path[1] == '\\') || (path[1] == '/'))) { + int index = 2; + int elements = 2; + + // Scan for two separate elements \\machine\share\restofpath + while ((index <= path.Length) && + (((path[index] != '\\') && (path[index] != '/')) || (--elements > 0))) { + index++; + } + + index++; + + if (index < path.Length) { + result = path.Substring(index); + } + else { + result = ""; + } + } + } + else if ((path.Length > 1) && (path[1] == ':')) { + int dropCount = 2; + if ((path.Length > 2) && ((path[2] == '\\') || (path[2] == '/'))) { + dropCount = 3; + } + result = result.Remove(0, dropCount); + } + } + return result; + } + } +} diff --git a/类库/Update/ZIP/Encryption/PkzipClassic.cs b/类库/Update/ZIP/Encryption/PkzipClassic.cs new file mode 100644 index 0000000..7bed67a --- /dev/null +++ b/类库/Update/ZIP/Encryption/PkzipClassic.cs @@ -0,0 +1,498 @@ +// +// PkzipClassic encryption +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + + +#if !NETCF_1_0 + +using System; +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.Encryption +{ + /// + /// PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives. + /// While it has been superceded by more recent and more powerful algorithms, its still in use and + /// is viable for preventing casual snooping + /// + public abstract class PkzipClassic : SymmetricAlgorithm + { + /// + /// Generates new encryption keys based on given seed + /// + /// The seed value to initialise keys with. + /// A new key value. + static public byte[] GenerateKeys(byte[] seed) + { + if ( seed == null ) { + throw new ArgumentNullException("seed"); + } + + if ( seed.Length == 0 ) { + throw new ArgumentException("Length is zero", "seed"); + } + + uint[] newKeys = new uint[] { + 0x12345678, + 0x23456789, + 0x34567890 + }; + + for (int i = 0; i < seed.Length; ++i) { + newKeys[0] = Crc32.ComputeCrc32(newKeys[0], seed[i]); + newKeys[1] = newKeys[1] + (byte)newKeys[0]; + newKeys[1] = newKeys[1] * 134775813 + 1; + newKeys[2] = Crc32.ComputeCrc32(newKeys[2], (byte)(newKeys[1] >> 24)); + } + + byte[] result = new byte[12]; + result[0] = (byte)(newKeys[0] & 0xff); + result[1] = (byte)((newKeys[0] >> 8) & 0xff); + result[2] = (byte)((newKeys[0] >> 16) & 0xff); + result[3] = (byte)((newKeys[0] >> 24) & 0xff); + result[4] = (byte)(newKeys[1] & 0xff); + result[5] = (byte)((newKeys[1] >> 8) & 0xff); + result[6] = (byte)((newKeys[1] >> 16) & 0xff); + result[7] = (byte)((newKeys[1] >> 24) & 0xff); + result[8] = (byte)(newKeys[2] & 0xff); + result[9] = (byte)((newKeys[2] >> 8) & 0xff); + result[10] = (byte)((newKeys[2] >> 16) & 0xff); + result[11] = (byte)((newKeys[2] >> 24) & 0xff); + return result; + } + } + + /// + /// PkzipClassicCryptoBase provides the low level facilities for encryption + /// and decryption using the PkzipClassic algorithm. + /// + class PkzipClassicCryptoBase + { + /// + /// Transform a single byte + /// + /// + /// The transformed value + /// + protected byte TransformByte() + { + uint temp = ((keys[2] & 0xFFFF) | 2); + return (byte)((temp * (temp ^ 1)) >> 8); + } + + /// + /// Set the key schedule for encryption/decryption. + /// + /// The data use to set the keys from. + protected void SetKeys(byte[] keyData) + { + if ( keyData == null ) { + throw new ArgumentNullException("keyData"); + } + + if ( keyData.Length != 12 ) { + throw new InvalidOperationException("Key length is not valid"); + } + + keys = new uint[3]; + keys[0] = (uint)((keyData[3] << 24) | (keyData[2] << 16) | (keyData[1] << 8) | keyData[0]); + keys[1] = (uint)((keyData[7] << 24) | (keyData[6] << 16) | (keyData[5] << 8) | keyData[4]); + keys[2] = (uint)((keyData[11] << 24) | (keyData[10] << 16) | (keyData[9] << 8) | keyData[8]); + } + + /// + /// Update encryption keys + /// + protected void UpdateKeys(byte ch) + { + keys[0] = Crc32.ComputeCrc32(keys[0], ch); + keys[1] = keys[1] + (byte)keys[0]; + keys[1] = keys[1] * 134775813 + 1; + keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24)); + } + + /// + /// Reset the internal state. + /// + protected void Reset() + { + keys[0] = 0; + keys[1] = 0; + keys[2] = 0; + } + + #region Instance Fields + uint[] keys; + #endregion + } + + /// + /// PkzipClassic CryptoTransform for encryption. + /// + class PkzipClassicEncryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform + { + /// + /// Initialise a new instance of + /// + /// The key block to use. + internal PkzipClassicEncryptCryptoTransform(byte[] keyBlock) + { + SetKeys(keyBlock); + } + + #region ICryptoTransform Members + + /// + /// Transforms the specified region of the specified byte array. + /// + /// The input for which to compute the transform. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + /// The computed transform. + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + byte[] result = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, result, 0); + return result; + } + + /// + /// Transforms the specified region of the input byte array and copies + /// the resulting transform to the specified region of the output byte array. + /// + /// The input for which to compute the transform. + /// The offset into the input byte array from which to begin using data. + /// The number of bytes in the input byte array to use as data. + /// The output to which to write the transform. + /// The offset into the output byte array from which to begin writing data. + /// The number of bytes written. + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + for (int i = inputOffset; i < inputOffset + inputCount; ++i) { + byte oldbyte = inputBuffer[i]; + outputBuffer[outputOffset++] = (byte)(inputBuffer[i] ^ TransformByte()); + UpdateKeys(oldbyte); + } + return inputCount; + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform + { + get { + return true; + } + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks + { + get { + return true; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Cleanup internal state. + /// + public void Dispose() + { + Reset(); + } + + #endregion + } + + + /// + /// PkzipClassic CryptoTransform for decryption. + /// + class PkzipClassicDecryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform + { + /// + /// Initialise a new instance of . + /// + /// The key block to decrypt with. + internal PkzipClassicDecryptCryptoTransform(byte[] keyBlock) + { + SetKeys(keyBlock); + } + + #region ICryptoTransform Members + + /// + /// Transforms the specified region of the specified byte array. + /// + /// The input for which to compute the transform. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + /// The computed transform. + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + byte[] result = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, result, 0); + return result; + } + + /// + /// Transforms the specified region of the input byte array and copies + /// the resulting transform to the specified region of the output byte array. + /// + /// The input for which to compute the transform. + /// The offset into the input byte array from which to begin using data. + /// The number of bytes in the input byte array to use as data. + /// The output to which to write the transform. + /// The offset into the output byte array from which to begin writing data. + /// The number of bytes written. + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + for (int i = inputOffset; i < inputOffset + inputCount; ++i) { + byte newByte = (byte)(inputBuffer[i] ^ TransformByte()); + outputBuffer[outputOffset++] = newByte; + UpdateKeys(newByte); + } + return inputCount; + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform + { + get { + return true; + } + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks + { + get { + return true; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Cleanup internal state. + /// + public void Dispose() + { + Reset(); + } + + #endregion + } + + /// + /// Defines a wrapper object to access the Pkzip algorithm. + /// This class cannot be inherited. + /// + public sealed class PkzipClassicManaged : PkzipClassic + { + /// + /// Get / set the applicable block size in bits. + /// + /// The only valid block size is 8. + public override int BlockSize + { + get { + return 8; + } + + set { + if (value != 8) { + throw new CryptographicException("Block size is invalid"); + } + } + } + + /// + /// Get an array of legal key sizes. + /// + public override KeySizes[] LegalKeySizes + { + get { + KeySizes[] keySizes = new KeySizes[1]; + keySizes[0] = new KeySizes(12 * 8, 12 * 8, 0); + return keySizes; + } + } + + /// + /// Generate an initial vector. + /// + public override void GenerateIV() + { + // Do nothing. + } + + /// + /// Get an array of legal block sizes. + /// + public override KeySizes[] LegalBlockSizes + { + get { + KeySizes[] keySizes = new KeySizes[1]; + keySizes[0] = new KeySizes(1 * 8, 1 * 8, 0); + return keySizes; + } + } + + /// + /// Get / set the key value applicable. + /// + public override byte[] Key + { + get { + if ( key_ == null ) { + GenerateKey(); + } + + return (byte[]) key_.Clone(); + } + + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + + if ( value.Length != 12 ) { + throw new CryptographicException("Key size is illegal"); + } + + key_ = (byte[]) value.Clone(); + } + } + + /// + /// Generate a new random key. + /// + public override void GenerateKey() + { + key_ = new byte[12]; + Random rnd = new Random(); + rnd.NextBytes(key_); + } + + /// + /// Create an encryptor. + /// + /// The key to use for this encryptor. + /// Initialisation vector for the new encryptor. + /// Returns a new PkzipClassic encryptor + public override ICryptoTransform CreateEncryptor( + byte[] rgbKey, + byte[] rgbIV) + { + key_ = rgbKey; + return new PkzipClassicEncryptCryptoTransform(Key); + } + + /// + /// Create a decryptor. + /// + /// Keys to use for this new decryptor. + /// Initialisation vector for the new decryptor. + /// Returns a new decryptor. + public override ICryptoTransform CreateDecryptor( + byte[] rgbKey, + byte[] rgbIV) + { + key_ = rgbKey; + return new PkzipClassicDecryptCryptoTransform(Key); + } + + #region Instance Fields + byte[] key_; + #endregion + } +} +#endif diff --git a/类库/Update/ZIP/Encryption/ZipAESStream.cs b/类库/Update/ZIP/Encryption/ZipAESStream.cs new file mode 100644 index 0000000..d57dc34 --- /dev/null +++ b/类库/Update/ZIP/Encryption/ZipAESStream.cs @@ -0,0 +1,170 @@ +// +// ZipAESStream.cs +// +// Copyright 2009 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + +#if !NET_1_1 && !NETCF_2_0 + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace ICSharpCode.SharpZipLib.Encryption { + + // Based on information from http://www.winzip.com/aes_info.htm + // and http://www.gladman.me.uk/cryptography_technology/fileencrypt/ + + /// + /// Encrypts and decrypts AES ZIP + /// + internal class ZipAESStream : CryptoStream { + + /// + /// Constructor + /// + /// The stream on which to perform the cryptographic transformation. + /// Instance of ZipAESTransform + /// Read or Write + public ZipAESStream(Stream stream, ZipAESTransform transform, CryptoStreamMode mode) + : base(stream, transform, mode) { + + _stream = stream; + _transform = transform; + _slideBuffer = new byte[1024]; + + _blockAndAuth = CRYPTO_BLOCK_SIZE + AUTH_CODE_LENGTH; + + // mode: + // CryptoStreamMode.Read means we read from "stream" and pass decrypted to our Read() method. + // Write bypasses this stream and uses the Transform directly. + if (mode != CryptoStreamMode.Read) { + throw new Exception("ZipAESStream only for read"); + } + } + + // The final n bytes of the AES stream contain the Auth Code. + private const int AUTH_CODE_LENGTH = 10; + + private Stream _stream; + private ZipAESTransform _transform; + private byte[] _slideBuffer; + private int _slideBufStartPos; + private int _slideBufFreePos; + // Blocksize is always 16 here, even for AES-256 which has transform.InputBlockSize of 32. + private const int CRYPTO_BLOCK_SIZE = 16; + private int _blockAndAuth; + + /// + /// Reads a sequence of bytes from the current CryptoStream into buffer, + /// and advances the position within the stream by the number of bytes read. + /// + public override int Read(byte[] outBuffer, int offset, int count) { + int nBytes = 0; + while (nBytes < count) { + // Calculate buffer quantities vs read-ahead size, and check for sufficient free space + int byteCount = _slideBufFreePos - _slideBufStartPos; + + // Need to handle final block and Auth Code specially, but don't know total data length. + // Maintain a read-ahead equal to the length of (crypto block + Auth Code). + // When that runs out we can detect these final sections. + int lengthToRead = _blockAndAuth - byteCount; + if (_slideBuffer.Length - _slideBufFreePos < lengthToRead) { + // Shift the data to the beginning of the buffer + int iTo = 0; + for (int iFrom = _slideBufStartPos; iFrom < _slideBufFreePos; iFrom++, iTo++) { + _slideBuffer[iTo] = _slideBuffer[iFrom]; + } + _slideBufFreePos -= _slideBufStartPos; // Note the -= + _slideBufStartPos = 0; + } + int obtained = _stream.Read(_slideBuffer, _slideBufFreePos, lengthToRead); + _slideBufFreePos += obtained; + + // Recalculate how much data we now have + byteCount = _slideBufFreePos - _slideBufStartPos; + if (byteCount >= _blockAndAuth) { + // At least a 16 byte block and an auth code remains. + _transform.TransformBlock(_slideBuffer, + _slideBufStartPos, + CRYPTO_BLOCK_SIZE, + outBuffer, + offset); + nBytes += CRYPTO_BLOCK_SIZE; + offset += CRYPTO_BLOCK_SIZE; + _slideBufStartPos += CRYPTO_BLOCK_SIZE; + } else { + // Last round. + if (byteCount > AUTH_CODE_LENGTH) { + // At least one byte of data plus auth code + int finalBlock = byteCount - AUTH_CODE_LENGTH; + _transform.TransformBlock(_slideBuffer, + _slideBufStartPos, + finalBlock, + outBuffer, + offset); + + nBytes += finalBlock; + _slideBufStartPos += finalBlock; + } + else if (byteCount < AUTH_CODE_LENGTH) + throw new Exception("Internal error missed auth code"); // Coding bug + // Final block done. Check Auth code. + byte[] calcAuthCode = _transform.GetAuthCode(); + for (int i = 0; i < AUTH_CODE_LENGTH; i++) { + if (calcAuthCode[i] != _slideBuffer[_slideBufStartPos + i]) { + throw new Exception("AES Authentication Code does not match. This is a super-CRC check on the data in the file after compression and encryption. \r\n" + + "The file may be damaged."); + } + } + + break; // Reached the auth code + } + } + return nBytes; + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + public override void Write(byte[] buffer, int offset, int count) { + // ZipAESStream is used for reading but not for writing. Writing uses the ZipAESTransform directly. + throw new NotImplementedException(); + } + } +} +#endif \ No newline at end of file diff --git a/类库/Update/ZIP/Encryption/ZipAESTransform.cs b/类库/Update/ZIP/Encryption/ZipAESTransform.cs new file mode 100644 index 0000000..134c1eb --- /dev/null +++ b/类库/Update/ZIP/Encryption/ZipAESTransform.cs @@ -0,0 +1,219 @@ +// +// ZipAESTransform.cs +// +// Copyright 2009 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + +#if !NET_1_1 && !NETCF_2_0 +// Framework version 2.0 required for Rfc2898DeriveBytes + +using System; +using System.Security.Cryptography; + +namespace ICSharpCode.SharpZipLib.Encryption { + + /// + /// Transforms stream using AES in CTR mode + /// + internal class ZipAESTransform : ICryptoTransform { + + private const int PWD_VER_LENGTH = 2; + + // WinZip use iteration count of 1000 for PBKDF2 key generation + private const int KEY_ROUNDS = 1000; + + // For 128-bit AES (16 bytes) the encryption is implemented as expected. + // For 256-bit AES (32 bytes) WinZip do full 256 bit AES of the nonce to create the encryption + // block but use only the first 16 bytes of it, and discard the second half. + private const int ENCRYPT_BLOCK = 16; + + private int _blockSize; + private ICryptoTransform _encryptor; + private readonly byte[] _counterNonce; + private byte[] _encryptBuffer; + private int _encrPos; + private byte[] _pwdVerifier; + private HMACSHA1 _hmacsha1; + private bool _finalised; + + private bool _writeMode; + + /// + /// Constructor. + /// + /// Password string + /// Random bytes, length depends on encryption strength. + /// 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. + /// The encryption strength, in bytes eg 16 for 128 bits. + /// True when creating a zip, false when reading. For the AuthCode. + /// + public ZipAESTransform(string key, byte[] saltBytes, int blockSize, bool writeMode) { + + if (blockSize != 16 && blockSize != 32) // 24 valid for AES but not supported by Winzip + throw new Exception("Invalid blocksize " + blockSize + ". Must be 16 or 32."); + if (saltBytes.Length != blockSize / 2) + throw new Exception("Invalid salt len. Must be " + blockSize / 2 + " for blocksize " + blockSize); + // initialise the encryption buffer and buffer pos + _blockSize = blockSize; + _encryptBuffer = new byte[_blockSize]; + _encrPos = ENCRYPT_BLOCK; + + // Performs the equivalent of derive_key in Dr Brian Gladman's pwd2key.c + Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, saltBytes, KEY_ROUNDS); + RijndaelManaged rm = new RijndaelManaged(); + rm.Mode = CipherMode.ECB; // No feedback from cipher for CTR mode + _counterNonce = new byte[_blockSize]; + byte[] byteKey1 = pdb.GetBytes(_blockSize); + byte[] byteKey2 = pdb.GetBytes(_blockSize); + _encryptor = rm.CreateEncryptor(byteKey1, byteKey2); + _pwdVerifier = pdb.GetBytes(PWD_VER_LENGTH); + // + _hmacsha1 = new HMACSHA1(byteKey2); + _writeMode = writeMode; + } + + /// + /// Implement the ICryptoTransform method. + /// + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { + + // Pass the data stream to the hash algorithm for generating the Auth Code. + // This does not change the inputBuffer. Do this before decryption for read mode. + if (!_writeMode) { + _hmacsha1.TransformBlock(inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset); + } + // Encrypt with AES in CTR mode. Regards to Dr Brian Gladman for this. + int ix = 0; + while (ix < inputCount) { + if (_encrPos == ENCRYPT_BLOCK) { + /* increment encryption nonce */ + int j = 0; + while (++_counterNonce[j] == 0) { + ++j; + } + /* encrypt the nonce to form next xor buffer */ + _encryptor.TransformBlock(_counterNonce, 0, _blockSize, _encryptBuffer, 0); + _encrPos = 0; + } + outputBuffer[ix + outputOffset] = (byte)(inputBuffer[ix + inputOffset] ^ _encryptBuffer[_encrPos++]); + // + ix++; + } + if (_writeMode) { + // This does not change the buffer. + _hmacsha1.TransformBlock(outputBuffer, outputOffset, inputCount, outputBuffer, outputOffset); + } + return inputCount; + } + + /// + /// Returns the 2 byte password verifier + /// + public byte[] PwdVerifier { + get { + return _pwdVerifier; + } + } + + /// + /// Returns the 10 byte AUTH CODE to be checked or appended immediately following the AES data stream. + /// + public byte[] GetAuthCode() { + // We usually don't get advance notice of final block. Hash requres a TransformFinal. + if (!_finalised) { + byte[] dummy = new byte[0]; + _hmacsha1.TransformFinalBlock(dummy, 0, 0); + _finalised = true; + } + return _hmacsha1.Hash; + } + + #region ICryptoTransform Members + + /// + /// Not implemented. + /// + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { + + throw new NotImplementedException("ZipAESTransform.TransformFinalBlock"); + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize { + get { + return _blockSize; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize { + get { + return _blockSize; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks { + get { + return true; + } + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform { + get { + return true; + } + } + + /// + /// Cleanup internal state. + /// + public void Dispose() { + _encryptor.Dispose(); + } + + #endregion + + } +} +#endif \ No newline at end of file diff --git a/类库/Update/ZIP/GZip/GZIPConstants.cs b/类库/Update/ZIP/GZip/GZIPConstants.cs new file mode 100644 index 0000000..1c0e389 --- /dev/null +++ b/类库/Update/ZIP/GZip/GZIPConstants.cs @@ -0,0 +1,97 @@ +// GZipConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This class contains constants used for gzip. + /// + sealed public class GZipConstants + { + /// + /// Magic number found at start of GZIP header + /// + public const int GZIP_MAGIC = 0x1F8B; + + /* The flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + */ + + /// + /// Flag bit mask for text + /// + public const int FTEXT = 0x1; + + /// + /// Flag bitmask for Crc + /// + public const int FHCRC = 0x2; + + /// + /// Flag bit mask for extra + /// + public const int FEXTRA = 0x4; + + /// + /// flag bitmask for name + /// + public const int FNAME = 0x8; + + /// + /// flag bit mask indicating comment is present + /// + public const int FCOMMENT = 0x10; + + /// + /// Initialise default instance. + /// + /// Constructor is private to prevent instances being created. + GZipConstants() + { + } + } +} diff --git a/类库/Update/ZIP/GZip/GZipException.cs b/类库/Update/ZIP/GZip/GZipException.cs new file mode 100644 index 0000000..7f42931 --- /dev/null +++ b/类库/Update/ZIP/GZip/GZipException.cs @@ -0,0 +1,91 @@ +// GZipException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.GZip +{ + /// + /// GZipException represents a Gzip specific exception + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class GZipException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected GZipException(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + + /// + /// Initialise a new instance of GZipException + /// + public GZipException() + { + } + + /// + /// Initialise a new instance of GZipException with its message string. + /// + /// A that describes the error. + public GZipException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of . + /// + /// A that describes the error. + /// The that caused this exception. + public GZipException(string message, Exception innerException) + : base (message, innerException) + { + } + } +} diff --git a/类库/Update/ZIP/GZip/GzipInputStream.cs b/类库/Update/ZIP/GZip/GzipInputStream.cs new file mode 100644 index 0000000..4cbad94 --- /dev/null +++ b/类库/Update/ZIP/GZip/GzipInputStream.cs @@ -0,0 +1,384 @@ +// GzipInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 11-08-2009 GeoffHart T9121 Added Multi-member gzip support + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This filter stream is used to decompress a "GZIP" format stream. + /// The "GZIP" format is described baseInputStream RFC 1952. + /// + /// author of the original java version : John Leuner + /// + /// This sample shows how to unzip a gzipped file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.GZip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream inStream = new GZipInputStream(File.OpenRead(args[0]))) + /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + /// byte[] buffer = new byte[4096]; + /// StreamUtils.Copy(inStream, outStream, buffer); + /// } + /// } + /// } + /// + /// + public class GZipInputStream : InflaterInputStream + { + #region Instance Fields + /// + /// CRC-32 value for uncompressed data + /// + protected Crc32 crc; + + /// + /// Flag to indicate if we've read the GZIP header yet for the current member (block of compressed data). + /// This is tracked per-block as the file is parsed. + /// + bool readGZIPHeader; + #endregion + + #region Constructors + /// + /// Creates a GZipInputStream with the default buffer size + /// + /// + /// The stream to read compressed data from (baseInputStream GZIP format) + /// + public GZipInputStream(Stream baseInputStream) + : this(baseInputStream, 4096) + { + } + + /// + /// Creates a GZIPInputStream with the specified buffer size + /// + /// + /// The stream to read compressed data from (baseInputStream GZIP format) + /// + /// + /// Size of the buffer to use + /// + public GZipInputStream(Stream baseInputStream, int size) + : base(baseInputStream, new Inflater(true), size) + { + } + #endregion + + #region Stream overrides + /// + /// Reads uncompressed data into an array of bytes + /// + /// + /// The buffer to read uncompressed data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of uncompressed bytes to be read + /// + /// Returns the number of bytes actually read. + public override int Read(byte[] buffer, int offset, int count) + { + // A GZIP file can contain multiple blocks of compressed data, although this is quite rare. + // A compressed block could potentially be empty, so we need to loop until we reach EOF or + // we find data. + while (true) { + + // If we haven't read the header for this block, read it + if (! readGZIPHeader) { + + // Try to read header. If there is no header (0 bytes available), this is EOF. If there is + // an incomplete header, this will throw an exception. + if (! ReadHeader()) { + return 0; + } + } + + // Try to read compressed data + int bytesRead = base.Read(buffer, offset, count); + if (bytesRead > 0) { + crc.Update(buffer, offset, bytesRead); + } + + // If this is the end of stream, read the footer + if (inf.IsFinished) { + ReadFooter(); + } + + if (bytesRead > 0) { + return bytesRead; + } + } + } + #endregion + + #region Support routines + bool ReadHeader() + { + // Initialize CRC for this block + crc = new Crc32(); + + // Make sure there is data in file. We can't rely on ReadLeByte() to fill the buffer, as this could be EOF, + // which is fine, but ReadLeByte() throws an exception if it doesn't find data, so we do this part ourselves. + if (inputBuffer.Available <= 0) { + inputBuffer.Fill(); + if (inputBuffer.Available <= 0) { + // No header, EOF. + return false; + } + } + + // 1. Check the two magic bytes + Crc32 headCRC = new Crc32(); + int magic = inputBuffer.ReadLeByte(); + + if (magic < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + headCRC.Update(magic); + if (magic != (GZipConstants.GZIP_MAGIC >> 8)) { + throw new GZipException("Error GZIP header, first magic byte doesn't match"); + } + + //magic = baseInputStream.ReadByte(); + magic = inputBuffer.ReadLeByte(); + + if (magic < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + if (magic != (GZipConstants.GZIP_MAGIC & 0xFF)) { + throw new GZipException("Error GZIP header, second magic byte doesn't match"); + } + + headCRC.Update(magic); + + // 2. Check the compression type (must be 8) + int compressionType = inputBuffer.ReadLeByte(); + + if ( compressionType < 0 ) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + if ( compressionType != 8 ) { + throw new GZipException("Error GZIP header, data not in deflate format"); + } + headCRC.Update(compressionType); + + // 3. Check the flags + int flags = inputBuffer.ReadLeByte(); + if (flags < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(flags); + + /* This flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + */ + + // 3.1 Check the reserved bits are zero + + if ((flags & 0xE0) != 0) { + throw new GZipException("Reserved flag bits in GZIP header != 0"); + } + + // 4.-6. Skip the modification time, extra flags, and OS type + for (int i=0; i< 6; i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + // 7. Read extra field + if ((flags & GZipConstants.FEXTRA) != 0) { + // Skip subfield id + for (int i=0; i< 2; i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + if (inputBuffer.ReadLeByte() < 0 || inputBuffer.ReadLeByte() < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + int len1, len2; + len1 = inputBuffer.ReadLeByte(); + len2 = inputBuffer.ReadLeByte(); + if ((len1 < 0) || (len2 < 0)) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(len1); + headCRC.Update(len2); + + int extraLen = (len1 << 8) | len2; + for (int i = 0; i < extraLen;i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) + { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + } + + // 8. Read file name + if ((flags & GZipConstants.FNAME) != 0) { + int readByte; + while ( (readByte = inputBuffer.ReadLeByte()) > 0) { + headCRC.Update(readByte); + } + + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + // 9. Read comment + if ((flags & GZipConstants.FCOMMENT) != 0) { + int readByte; + while ( (readByte = inputBuffer.ReadLeByte()) > 0) { + headCRC.Update(readByte); + } + + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + headCRC.Update(readByte); + } + + // 10. Read header CRC + if ((flags & GZipConstants.FHCRC) != 0) { + int tempByte; + int crcval = inputBuffer.ReadLeByte(); + if (crcval < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + tempByte = inputBuffer.ReadLeByte(); + if (tempByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + crcval = (crcval << 8) | tempByte; + if (crcval != ((int) headCRC.Value & 0xffff)) { + throw new GZipException("Header CRC value mismatch"); + } + } + + readGZIPHeader = true; + return true; + } + + void ReadFooter() + { + byte[] footer = new byte[8]; + + // End of stream; reclaim all bytes from inf, read the final byte count, and reset the inflator + long bytesRead = inf.TotalOut & 0xffffffff; + inputBuffer.Available += inf.RemainingInput; + inf.Reset(); + + // Read footer from inputBuffer + int needed = 8; + while (needed > 0) { + int count = inputBuffer.ReadClearTextBuffer(footer, 8 - needed, needed); + if (count <= 0) { + throw new EndOfStreamException("EOS reading GZIP footer"); + } + needed -= count; // Jewel Jan 16 + } + + // Calculate CRC + int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8) | ((footer[2] & 0xff) << 16) | (footer[3] << 24); + if (crcval != (int) crc.Value) { + throw new GZipException("GZIP crc sum mismatch, theirs \"" + crcval + "\" and ours \"" + (int) crc.Value); + } + + // NOTE The total here is the original total modulo 2 ^ 32. + uint total = + (uint)((uint)footer[4] & 0xff) | + (uint)(((uint)footer[5] & 0xff) << 8) | + (uint)(((uint)footer[6] & 0xff) << 16) | + (uint)((uint)footer[7] << 24); + + if (bytesRead != total) { + throw new GZipException("Number of bytes mismatch in footer"); + } + + // Mark header read as false so if another header exists, we'll continue reading through the file + readGZIPHeader = false; + } + #endregion + } +} diff --git a/类库/Update/ZIP/GZip/GzipOutputStream.cs b/类库/Update/ZIP/GZip/GzipOutputStream.cs new file mode 100644 index 0000000..0db2e4b --- /dev/null +++ b/类库/Update/ZIP/GZip/GzipOutputStream.cs @@ -0,0 +1,261 @@ +// GZipOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This filter stream is used to compress a stream into a "GZIP" stream. + /// The "GZIP" format is described in RFC 1952. + /// + /// author of the original java version : John Leuner + /// + /// This sample shows how to gzip a file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.GZip; + /// using ICSharpCode.SharpZipLib.Core; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz"))) + /// using (FileStream fs = File.OpenRead(args[0])) { + /// byte[] writeData = new byte[4096]; + /// Streamutils.Copy(s, fs, writeData); + /// } + /// } + /// } + /// } + /// + /// + public class GZipOutputStream : DeflaterOutputStream + { + enum OutputState + { + Header, + Footer, + Finished, + Closed, + }; + + #region Instance Fields + /// + /// CRC-32 value for uncompressed data + /// + protected Crc32 crc = new Crc32(); + OutputState state_ = OutputState.Header; + #endregion + + #region Constructors + /// + /// Creates a GzipOutputStream with the default buffer size + /// + /// + /// The stream to read data (to be compressed) from + /// + public GZipOutputStream(Stream baseOutputStream) + : this(baseOutputStream, 4096) + { + } + + /// + /// Creates a GZipOutputStream with the specified buffer size + /// + /// + /// The stream to read data (to be compressed) from + /// + /// + /// Size of the buffer to use + /// + public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size) + { + } + #endregion + + #region Public API + /// + /// Sets the active compression level (1-9). The new level will be activated + /// immediately. + /// + /// The compression level to set. + /// + /// Level specified is not supported. + /// + /// + public void SetLevel(int level) + { + if (level < Deflater.BEST_SPEED) { + throw new ArgumentOutOfRangeException("level"); + } + deflater_.SetLevel(level); + } + + /// + /// Get the current compression level. + /// + /// The current compression level. + public int GetLevel() + { + return deflater_.GetLevel(); + } + #endregion + + #region Stream overrides + /// + /// Write given buffer to output updating crc + /// + /// Buffer to write + /// Offset of first byte in buf to write + /// Number of bytes to write + public override void Write(byte[] buffer, int offset, int count) + { + if ( state_ == OutputState.Header ) { + WriteHeader(); + } + + if( state_!=OutputState.Footer ) + { + throw new InvalidOperationException("Write not permitted in current state"); + } + + crc.Update(buffer, offset, count); + base.Write(buffer, offset, count); + } + + /// + /// Writes remaining compressed output data to the output stream + /// and closes it. + /// + public override void Close() + { + try { + Finish(); + } + finally { + if ( state_ != OutputState.Closed ) { + state_ = OutputState.Closed; + if( IsStreamOwner ) { + baseOutputStream_.Close(); + } + } + } + } + #endregion + + #region DeflaterOutputStream overrides + /// + /// Finish compression and write any footer information required to stream + /// + public override void Finish() + { + // If no data has been written a header should be added. + if ( state_ == OutputState.Header ) { + WriteHeader(); + } + + if( state_ == OutputState.Footer) + { + state_=OutputState.Finished; + base.Finish(); + + uint totalin=(uint)(deflater_.TotalIn&0xffffffff); + uint crcval=(uint)(crc.Value&0xffffffff); + + byte[] gzipFooter; + + unchecked + { + gzipFooter=new byte[] { + (byte) crcval, (byte) (crcval >> 8), + (byte) (crcval >> 16), (byte) (crcval >> 24), + + (byte) totalin, (byte) (totalin >> 8), + (byte) (totalin >> 16), (byte) (totalin >> 24) + }; + } + + baseOutputStream_.Write(gzipFooter, 0, gzipFooter.Length); + } + } + #endregion + + #region Support Routines + void WriteHeader() + { + if ( state_ == OutputState.Header ) + { + state_=OutputState.Footer; + + int mod_time = (int)((DateTime.Now.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000L); // Ticks give back 100ns intervals + byte[] gzipHeader = { + // The two magic bytes + (byte) (GZipConstants.GZIP_MAGIC >> 8), (byte) (GZipConstants.GZIP_MAGIC & 0xff), + + // The compression type + (byte) Deflater.DEFLATED, + + // The flags (not set) + 0, + + // The modification time + (byte) mod_time, (byte) (mod_time >> 8), + (byte) (mod_time >> 16), (byte) (mod_time >> 24), + + // The extra flags + 0, + + // The OS type (unknown) + (byte) 255 + }; + baseOutputStream_.Write(gzipHeader, 0, gzipHeader.Length); + } + } + #endregion + } +} diff --git a/类库/Update/ZIP/Lzw/LzwConstants.cs b/类库/Update/ZIP/Lzw/LzwConstants.cs new file mode 100644 index 0000000..699ed09 --- /dev/null +++ b/类库/Update/ZIP/Lzw/LzwConstants.cs @@ -0,0 +1,94 @@ +// LzwConstants.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.LZW { + + /// + /// This class contains constants used for LZW + /// + sealed public class LzwConstants { + /// + /// Magic number found at start of LZW header: 0x1f 0x9d + /// + public const int MAGIC = 0x1f9d; + + /// + /// Maximum number of bits per code + /// + public const int MAX_BITS = 16; + + /* 3rd header byte: + * bit 0..4 Number of compression bits + * bit 5 Extended header + * bit 6 Free + * bit 7 Block mode + */ + + /// + /// Mask for 'number of compression bits' + /// + public const int BIT_MASK = 0x1f; + + /// + /// Indicates the presence of a fourth header byte + /// + public const int EXTENDED_MASK = 0x20; + //public const int FREE_MASK = 0x40; + + /// + /// Reserved bits + /// + public const int RESERVED_MASK = 0x60; + + /// + /// Block compression: if table is full and compression rate is dropping, + /// clear the dictionary. + /// + public const int BLOCK_MODE_MASK = 0x80; + + /// + /// LZW file header size (in bytes) + /// + public const int HDR_SIZE = 3; + + /// + /// Initial number of bits per code + /// + public const int INIT_BITS = 9; + + LzwConstants() { + } + } +} diff --git a/类库/Update/ZIP/Lzw/LzwException.cs b/类库/Update/ZIP/Lzw/LzwException.cs new file mode 100644 index 0000000..10a9547 --- /dev/null +++ b/类库/Update/ZIP/Lzw/LzwException.cs @@ -0,0 +1,88 @@ +// LzwException.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.LZW +{ + + /// + /// LzwException represents a LZW specific exception + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class LzwException : SharpZipBaseException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected LzwException(SerializationInfo info, StreamingContext context) + : base(info, context) { + } +#endif + + /// + /// Initialise a new instance of LzwException + /// + public LzwException() { + } + + /// + /// Initialise a new instance of LzwException with its message string. + /// + /// A that describes the error. + public LzwException(string message) + : base(message) { + } + + /// + /// Initialise a new instance of . + /// + /// A that describes the error. + /// The that caused this exception. + public LzwException(string message, Exception innerException) + : base(message, innerException) { + } + } +} diff --git a/类库/Update/ZIP/Lzw/LzwInputStream.cs b/类库/Update/ZIP/Lzw/LzwInputStream.cs new file mode 100644 index 0000000..94b8b66 --- /dev/null +++ b/类库/Update/ZIP/Lzw/LzwInputStream.cs @@ -0,0 +1,598 @@ +// LzwInputStream.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.LZW +{ + + /// + /// This filter stream is used to decompress a LZW format stream. + /// Specifically, a stream that uses the LZC compression method. + /// This file format is usually associated with the .Z file extension. + /// + /// See http://en.wikipedia.org/wiki/Compress + /// See http://wiki.wxwidgets.org/Development:_Z_File_Format + /// + /// The file header consists of 3 (or optionally 4) bytes. The first two bytes + /// contain the magic marker "0x1f 0x9d", followed by a byte of flags. + /// + /// Based on Java code by Ronald Tschalar, which in turn was based on the unlzw.c + /// code in the gzip package. + /// + /// This sample shows how to unzip a compressed file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.LZW; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream inStream = new LzwInputStream(File.OpenRead(args[0]))) + /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + /// byte[] buffer = new byte[4096]; + /// StreamUtils.Copy(inStream, outStream, buffer); + /// // OR + /// inStream.Read(buffer, 0, buffer.Length); + /// // now do something with the buffer + /// } + /// } + /// } + /// + /// + public class LzwInputStream : Stream + { + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + /// + /// The default value is true. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Creates a LzwInputStream + /// + /// + /// The stream to read compressed data from (baseInputStream LZW format) + /// + public LzwInputStream(Stream baseInputStream) { + this.baseInputStream = baseInputStream; + } + + /// + /// See + /// + /// + public override int ReadByte() { + int b = Read(one, 0, 1); + if (b == 1) + return (one[0] & 0xff); + return -1; + } + + /// + /// Reads decompressed data into the provided buffer byte array + /// + /// + /// The array to read and decompress data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of bytes to decompress + /// + /// The number of bytes read. Zero signals the end of stream + public override int Read(byte[] buffer, int offset, int count) { + if (!headerParsed) ParseHeader(); + + if (eof) return -1; + int start = offset; + + /* Using local copies of various variables speeds things up by as + * much as 30% in Java! Performance not tested in C#. + */ + int[] lTabPrefix = tabPrefix; + byte[] lTabSuffix = tabSuffix; + byte[] lStack = stack; + int lNBits = nBits; + int lMaxCode = maxCode; + int lMaxMaxCode = maxMaxCode; + int lBitMask = bitMask; + int lOldCode = oldCode; + byte lFinChar = finChar; + int lStackP = stackP; + int lFreeEnt = freeEnt; + byte[] lData = data; + int lBitPos = bitPos; + + + // empty stack if stuff still left + int sSize = lStack.Length - lStackP; + if (sSize > 0) { + int num = (sSize >= count) ? count : sSize; + Array.Copy(lStack, lStackP, buffer, offset, num); + offset += num; + count -= num; + lStackP += num; + } + + if (count == 0) { + stackP = lStackP; + return offset - start; + } + + + // loop, filling local buffer until enough data has been decompressed + MainLoop: do { + if (end < EXTRA) { + Fill(); + } + + int bitIn = (got > 0) ? (end - end % lNBits) << 3 : + (end << 3) - (lNBits - 1); + + while (lBitPos < bitIn) { + #region A + // handle 1-byte reads correctly + if (count == 0) { + nBits = lNBits; + maxCode = lMaxCode; + maxMaxCode = lMaxMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + return offset - start; + } + + // check for code-width expansion + if (lFreeEnt > lMaxCode) { + int nBytes = lNBits << 3; + lBitPos = (lBitPos - 1) + + nBytes - (lBitPos - 1 + nBytes) % nBytes; + + lNBits++; + lMaxCode = (lNBits == maxBits) ? lMaxMaxCode : + (1 << lNBits) - 1; + + lBitMask = (1 << lNBits) - 1; + lBitPos = ResetBuf(lBitPos); + goto MainLoop; + } + #endregion + + #region B + // read next code + int pos = lBitPos >> 3; + int code = (((lData[pos] & 0xFF) | + ((lData[pos + 1] & 0xFF) << 8) | + ((lData[pos + 2] & 0xFF) << 16)) >> + (lBitPos & 0x7)) & lBitMask; + + lBitPos += lNBits; + + // handle first iteration + if (lOldCode == -1) { + if (code >= 256) throw new LzwException("corrupt input: " + code + " > 255"); + + lFinChar = (byte) (lOldCode = code); + buffer[offset++] = lFinChar; + count--; + continue; + } + + // handle CLEAR code + if (code == TBL_CLEAR && blockMode) { + Array.Copy(zeros, 0, lTabPrefix, 0, zeros.Length); + lFreeEnt = TBL_FIRST - 1; + + int nBytes = lNBits << 3; + lBitPos = (lBitPos - 1) + nBytes - (lBitPos - 1 + nBytes) % nBytes; + lNBits = LzwConstants.INIT_BITS; + lMaxCode = (1 << lNBits) - 1; + lBitMask = lMaxCode; + + // Code tables reset + + lBitPos = ResetBuf(lBitPos); + goto MainLoop; + } + #endregion + + #region C + // setup + int inCode = code; + lStackP = lStack.Length; + + // Handle KwK case + if (code >= lFreeEnt) { + if (code > lFreeEnt) { + throw new LzwException("corrupt input: code=" + code + + ", freeEnt=" + lFreeEnt); + } + + lStack[--lStackP] = lFinChar; + code = lOldCode; + } + + // Generate output characters in reverse order + while (code >= 256) { + lStack[--lStackP] = lTabSuffix[code]; + code = lTabPrefix[code]; + } + + lFinChar = lTabSuffix[code]; + buffer[offset++] = lFinChar; + count--; + + // And put them out in forward order + sSize = lStack.Length - lStackP; + int num = (sSize >= count) ? count : sSize; + Array.Copy(lStack, lStackP, buffer, offset, num); + offset += num; + count -= num; + lStackP += num; + #endregion + + #region D + // generate new entry in table + if (lFreeEnt < lMaxMaxCode) { + lTabPrefix[lFreeEnt] = lOldCode; + lTabSuffix[lFreeEnt] = lFinChar; + lFreeEnt++; + } + + // Remember previous code + lOldCode = inCode; + + // if output buffer full, then return + if (count == 0) { + nBits = lNBits; + maxCode = lMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + return offset - start; + } + #endregion + } // while + + lBitPos = ResetBuf(lBitPos); + + } while (got > 0); // do..while + + nBits = lNBits; + maxCode = lMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + eof = true; + return offset - start; + } + + /// + /// Moves the unread data in the buffer to the beginning and resets + /// the pointers. + /// + /// + /// + private int ResetBuf(int bitPosition) { + int pos = bitPosition >> 3; + Array.Copy(data, pos, data, 0, end - pos); + end -= pos; + return 0; + } + + + private void Fill() { + got = baseInputStream.Read(data, end, data.Length - 1 - end); + if (got > 0) { + end += got; + } + } + + + private void ParseHeader() { + headerParsed = true; + + byte[] hdr = new byte[LzwConstants.HDR_SIZE]; + + int result = baseInputStream.Read(hdr, 0, hdr.Length); + + // Check the magic marker + if (result < 0) + throw new LzwException("Failed to read LZW header"); + + if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) { + throw new LzwException(String.Format( + "Wrong LZW header. Magic bytes don't match. 0x{0:x2} 0x{1:x2}", + hdr[0], hdr[1])); + } + + // Check the 3rd header byte + blockMode = (hdr[2] & LzwConstants.BLOCK_MODE_MASK) > 0; + maxBits = hdr[2] & LzwConstants.BIT_MASK; + + if (maxBits > LzwConstants.MAX_BITS) { + throw new LzwException("Stream compressed with " + maxBits + + " bits, but decompression can only handle " + + LzwConstants.MAX_BITS + " bits."); + } + + if ((hdr[2] & LzwConstants.RESERVED_MASK) > 0) { + throw new LzwException("Unsupported bits set in the header."); + } + + // Initialize variables + maxMaxCode = 1 << maxBits; + nBits = LzwConstants.INIT_BITS; + maxCode = (1 << nBits) - 1; + bitMask = maxCode; + oldCode = -1; + finChar = 0; + freeEnt = blockMode ? TBL_FIRST : 256; + + tabPrefix = new int[1 << maxBits]; + tabSuffix = new byte[1 << maxBits]; + stack = new byte[1 << maxBits]; + stackP = stack.Length; + + for (int idx = 255; idx >= 0; idx--) + tabSuffix[idx] = (byte)idx; + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get + { + return baseInputStream.CanRead; + } + } + + /// + /// Gets a value of false indicating seeking is not supported for this stream. + /// + public override bool CanSeek + { + get + { + return false; + } + } + + /// + /// Gets a value of false indicating that this stream is not writeable. + /// + public override bool CanWrite + { + get + { + return false; + } + } + + /// + /// A value representing the length of the stream in bytes. + /// + public override long Length + { + get + { + return got; + } + } + + /// + /// The current position within the stream. + /// Throws a NotSupportedException when attempting to set the position + /// + /// Attempting to set the position + public override long Position + { + get + { + return baseInputStream.Position; + } + set + { + throw new NotSupportedException("InflaterInputStream Position not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + baseInputStream.Flush(); + } + + /// + /// Sets the position within the current stream + /// Always throws a NotSupportedException + /// + /// The relative offset to seek to. + /// The defining where to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Seek not supported"); + } + + /// + /// Set the length of the current stream + /// Always throws a NotSupportedException + /// + /// The new length value for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("InflaterInputStream SetLength not supported"); + } + + /// + /// Writes a sequence of bytes to stream and advances the current position + /// This method always throws a NotSupportedException + /// + /// Thew buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("InflaterInputStream Write not supported"); + } + + /// + /// Writes one byte to the current stream and advances the current position + /// Always throws a NotSupportedException + /// + /// The byte to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("InflaterInputStream WriteByte not supported"); + } + + /// + /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. + /// + /// The buffer to write data from + /// Offset of first byte to write + /// The maximum number of bytes to write + /// The method to be called when the asynchronous write operation is completed + /// A user-provided object that distinguishes this particular asynchronous write request from other requests + /// An IAsyncResult that references the asynchronous write + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); + } + + /// + /// Closes the input stream. When + /// is true the underlying stream is also closed. + /// + public override void Close() + { + if (!isClosed) + { + isClosed = true; + if (isStreamOwner) + { + baseInputStream.Close(); + } + } + } + + #endregion + + #region Instance Fields + + Stream baseInputStream; + + /// + /// Flag indicating wether this instance is designated the stream owner. + /// When closing if this flag is true the underlying stream is closed. + /// + bool isStreamOwner = true; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + readonly byte[] one = new byte[1]; + bool headerParsed; + + // string table stuff + private const int TBL_CLEAR = 0x100; + private const int TBL_FIRST = TBL_CLEAR + 1; + + private int[] tabPrefix; + private byte[] tabSuffix; + private readonly int[] zeros = new int[256]; + private byte[] stack; + + // various state + private bool blockMode; + private int nBits; + private int maxBits; + private int maxMaxCode; + private int maxCode; + private int bitMask; + private int oldCode; + private byte finChar; + private int stackP; + private int freeEnt; + + // input buffer + private readonly byte[] data = new byte[1024 * 8]; + private int bitPos; + private int end; + int got; + private bool eof; + private const int EXTRA = 64; + #endregion + } +} diff --git a/类库/Update/ZIP/SharpZipBaseException.cs b/类库/Update/ZIP/SharpZipBaseException.cs new file mode 100644 index 0000000..7a5d136 --- /dev/null +++ b/类库/Update/ZIP/SharpZipBaseException.cs @@ -0,0 +1,94 @@ +// SharpZipBaseException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib +{ + /// + /// SharpZipBaseException is the base exception class for the SharpZipLibrary. + /// All library exceptions are derived from this. + /// + /// NOTE: Not all exceptions thrown will be derived from this class. + /// A variety of other exceptions are possible for example +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class SharpZipBaseException : ApplicationException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected SharpZipBaseException(SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } +#endif + + /// + /// Initializes a new instance of the SharpZipBaseException class. + /// + public SharpZipBaseException() + { + } + + /// + /// Initializes a new instance of the SharpZipBaseException class with a specified error message. + /// + /// A message describing the exception. + public SharpZipBaseException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the SharpZipBaseException class with a specified + /// error message and a reference to the inner exception that is the cause of this exception. + /// + /// A message describing the exception. + /// The inner exception + public SharpZipBaseException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/类库/Update/ZIP/Tar/InvalidHeaderException.cs b/类库/Update/ZIP/Tar/InvalidHeaderException.cs new file mode 100644 index 0000000..bac9343 --- /dev/null +++ b/类库/Update/ZIP/Tar/InvalidHeaderException.cs @@ -0,0 +1,109 @@ +// InvalidHeaderException.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Tar { + + /// + /// This exception is used to indicate that there is a problem + /// with a TAR archive header. + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class InvalidHeaderException : TarException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected InvalidHeaderException(SerializationInfo information, StreamingContext context) + : base(information, context) + + { + } +#endif + + /// + /// Initialise a new instance of the InvalidHeaderException class. + /// + public InvalidHeaderException() + { + } + + /// + /// Initialises a new instance of the InvalidHeaderException class with a specified message. + /// + /// Message describing the exception cause. + public InvalidHeaderException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of InvalidHeaderException + /// + /// Message describing the problem. + /// The exception that is the cause of the current exception. + public InvalidHeaderException(string message, Exception exception) + : base(message, exception) + { + } + } +} + +/* The original Java file had this header: +** Authored by Timothy Gerard Endres +** +** +** This work has been placed into the public domain. +** You may use this work in any way and for any purpose you wish. +** +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR +** REDISTRIBUTION OF THIS SOFTWARE. +** +*/ + diff --git a/类库/Update/ZIP/Tar/TarArchive.cs b/类库/Update/ZIP/Tar/TarArchive.cs new file mode 100644 index 0000000..5a5510b --- /dev/null +++ b/类库/Update/ZIP/Tar/TarArchive.cs @@ -0,0 +1,894 @@ +// TarArchive.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 28-01-2010 DavidPierson Added IsStreamOwner + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + /// + /// Used to advise clients of 'events' while processing archives + /// + public delegate void ProgressMessageHandler(TarArchive archive, TarEntry entry, string message); + + /// + /// The TarArchive class implements the concept of a + /// 'Tape Archive'. A tar archive is a series of entries, each of + /// which represents a file system object. Each entry in + /// the archive consists of a header block followed by 0 or more data blocks. + /// Directory entries consist only of the header block, and are followed by entries + /// for the directory's contents. File entries consist of a + /// header followed by the number of blocks needed to + /// contain the file's contents. All entries are written on + /// block boundaries. Blocks are 512 bytes long. + /// + /// TarArchives are instantiated in either read or write mode, + /// based upon whether they are instantiated with an InputStream + /// or an OutputStream. Once instantiated TarArchives read/write + /// mode can not be changed. + /// + /// There is currently no support for random access to tar archives. + /// However, it seems that subclassing TarArchive, and using the + /// TarBuffer.CurrentRecord and TarBuffer.CurrentBlock + /// properties, this would be rather trivial. + /// + public class TarArchive : IDisposable + { + /// + /// Client hook allowing detailed information to be reported during processing + /// + public event ProgressMessageHandler ProgressMessageEvent; + + /// + /// Raises the ProgressMessage event + /// + /// The TarEntry for this event + /// message for this event. Null is no message + protected virtual void OnProgressMessageEvent(TarEntry entry, string message) + { + ProgressMessageHandler handler = ProgressMessageEvent; + if (handler != null) { + handler(this, entry, message); + } + } + + #region Constructors + /// + /// Constructor for a default . + /// + protected TarArchive() + { + } + + /// + /// Initalise a TarArchive for input. + /// + /// The to use for input. + protected TarArchive(TarInputStream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + tarIn = stream; + } + + /// + /// Initialise a TarArchive for output. + /// + /// The to use for output. + protected TarArchive(TarOutputStream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + tarOut = stream; + } + #endregion + + #region Static factory methods + /// + /// The InputStream based constructors create a TarArchive for the + /// purposes of extracting or listing a tar archive. Thus, use + /// these constructors when you wish to extract files from or list + /// the contents of an existing tar archive. + /// + /// The stream to retrieve archive data from. + /// Returns a new suitable for reading from. + public static TarArchive CreateInputTarArchive(Stream inputStream) + { + if ( inputStream == null ) { + throw new ArgumentNullException("inputStream"); + } + + TarInputStream tarStream = inputStream as TarInputStream; + + TarArchive result; + if ( tarStream != null ) { + result = new TarArchive(tarStream); + } + else { + result = CreateInputTarArchive(inputStream, TarBuffer.DefaultBlockFactor); + } + return result; + } + + /// + /// Create TarArchive for reading setting block factor + /// + /// A stream containing the tar archive contents + /// The blocking factor to apply + /// Returns a suitable for reading. + public static TarArchive CreateInputTarArchive(Stream inputStream, int blockFactor) + { + if ( inputStream == null ) { + throw new ArgumentNullException("inputStream"); + } + + if ( inputStream is TarInputStream ) { + throw new ArgumentException("TarInputStream not valid"); + } + + return new TarArchive(new TarInputStream(inputStream, blockFactor)); + } + + /// + /// Create a TarArchive for writing to, using the default blocking factor + /// + /// The to write to + /// Returns a suitable for writing. + public static TarArchive CreateOutputTarArchive(Stream outputStream) + { + if ( outputStream == null ) { + throw new ArgumentNullException("outputStream"); + } + + TarOutputStream tarStream = outputStream as TarOutputStream; + + TarArchive result; + if ( tarStream != null ) { + result = new TarArchive(tarStream); + } + else { + result = CreateOutputTarArchive(outputStream, TarBuffer.DefaultBlockFactor); + } + return result; + } + + /// + /// Create a tar archive for writing. + /// + /// The stream to write to + /// The blocking factor to use for buffering. + /// Returns a suitable for writing. + public static TarArchive CreateOutputTarArchive(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) { + throw new ArgumentNullException("outputStream"); + } + + if ( outputStream is TarOutputStream ) { + throw new ArgumentException("TarOutputStream is not valid"); + } + + return new TarArchive(new TarOutputStream(outputStream, blockFactor)); + } + #endregion + + /// + /// Set the flag that determines whether existing files are + /// kept, or overwritten during extraction. + /// + /// + /// If true, do not overwrite existing files. + /// + public void SetKeepOldFiles(bool keepExistingFiles) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + keepOldFiles = keepExistingFiles; + } + + /// + /// Get/set the ascii file translation flag. If ascii file translation + /// is true, then the file is checked to see if it a binary file or not. + /// If the flag is true and the test indicates it is ascii text + /// file, it will be translated. The translation converts the local + /// operating system's concept of line ends into the UNIX line end, + /// '\n', which is the defacto standard for a TAR archive. This makes + /// text files compatible with UNIX. + /// + public bool AsciiTranslate + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return asciiTranslate; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + asciiTranslate = value; + } + + } + + /// + /// Set the ascii file translation flag. + /// + /// + /// If true, translate ascii text files. + /// + [Obsolete("Use the AsciiTranslate property")] + public void SetAsciiTranslation(bool translateAsciiFiles) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + asciiTranslate = translateAsciiFiles; + } + + /// + /// PathPrefix is added to entry names as they are written if the value is not null. + /// A slash character is appended after PathPrefix + /// + public string PathPrefix + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return pathPrefix; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + pathPrefix = value; + } + + } + + /// + /// RootPath is removed from entry names if it is found at the + /// beginning of the name. + /// + public string RootPath + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return rootPath; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + rootPath = value; + } + } + + /// + /// Set user and group information that will be used to fill in the + /// tar archive's entry headers. This information is based on that available + /// for the linux operating system, which is not always available on other + /// operating systems. TarArchive allows the programmer to specify values + /// to be used in their place. + /// is set to true by this call. + /// + /// + /// The user id to use in the headers. + /// + /// + /// The user name to use in the headers. + /// + /// + /// The group id to use in the headers. + /// + /// + /// The group name to use in the headers. + /// + public void SetUserInfo(int userId, string userName, int groupId, string groupName) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + this.userId = userId; + this.userName = userName; + this.groupId = groupId; + this.groupName = groupName; + applyUserInfoOverrides = true; + } + + /// + /// Get or set a value indicating if overrides defined by SetUserInfo should be applied. + /// + /// If overrides are not applied then the values as set in each header will be used. + public bool ApplyUserInfoOverrides + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return applyUserInfoOverrides; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + applyUserInfoOverrides = value; + } + } + + /// + /// Get the archive user id. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current user id. + /// + public int UserId { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return userId; + } + } + + /// + /// Get the archive user name. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current user name. + /// + public string UserName { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return userName; + } + } + + /// + /// Get the archive group id. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current group id. + /// + public int GroupId { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return groupId; + } + } + + /// + /// Get the archive group name. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current group name. + /// + public string GroupName { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return groupName; + } + } + + /// + /// Get the archive's record size. Tar archives are composed of + /// a series of RECORDS each containing a number of BLOCKS. + /// This allowed tar archives to match the IO characteristics of + /// the physical device being used. Archives are expected + /// to be properly "blocked". + /// + /// + /// The record size this archive is using. + /// + public int RecordSize { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + if (tarIn != null) { + return tarIn.RecordSize; + } else if (tarOut != null) { + return tarOut.RecordSize; + } + return TarBuffer.DefaultRecordSize; + } + } + + /// + /// Sets the IsStreamOwner property on the underlying stream. + /// Set this to false to prevent the Close of the TarArchive from closing the stream. + /// + public bool IsStreamOwner { + set { + if (tarIn != null) { + tarIn.IsStreamOwner = value; + } else { + tarOut.IsStreamOwner = value; + } + } + } + + /// + /// Close the archive. + /// + [Obsolete("Use Close instead")] + public void CloseArchive() + { + Close(); + } + + /// + /// Perform the "list" command for the archive contents. + /// + /// NOTE That this method uses the progress event to actually list + /// the contents. If the progress display event is not set, nothing will be listed! + /// + public void ListContents() + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + while (true) { + TarEntry entry = tarIn.GetNextEntry(); + + if (entry == null) { + break; + } + OnProgressMessageEvent(entry, null); + } + } + + /// + /// Perform the "extract" command and extract the contents of the archive. + /// + /// + /// The destination directory into which to extract. + /// + public void ExtractContents(string destinationDirectory) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + while (true) { + TarEntry entry = tarIn.GetNextEntry(); + + if (entry == null) { + break; + } + + ExtractEntry(destinationDirectory, entry); + } + } + + /// + /// Extract an entry from the archive. This method assumes that the + /// tarIn stream has been properly set with a call to GetNextEntry(). + /// + /// + /// The destination directory into which to extract. + /// + /// + /// The TarEntry returned by tarIn.GetNextEntry(). + /// + void ExtractEntry(string destDir, TarEntry entry) + { + OnProgressMessageEvent(entry, null); + + string name = entry.Name; + + if (Path.IsPathRooted(name)) { + // NOTE: + // for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt + name = name.Substring(Path.GetPathRoot(name).Length); + } + + name = name.Replace('/', Path.DirectorySeparatorChar); + + string destFile = Path.Combine(destDir, name); + + if (entry.IsDirectory) { + EnsureDirectoryExists(destFile); + } else { + string parentDirectory = Path.GetDirectoryName(destFile); + EnsureDirectoryExists(parentDirectory); + + bool process = true; + FileInfo fileInfo = new FileInfo(destFile); + if (fileInfo.Exists) { + if (keepOldFiles) { + OnProgressMessageEvent(entry, "Destination file already exists"); + process = false; + } else if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0) { + OnProgressMessageEvent(entry, "Destination file already exists, and is read-only"); + process = false; + } + } + + if (process) { + bool asciiTrans = false; + + Stream outputStream = File.Create(destFile); + if (this.asciiTranslate) { + asciiTrans = !IsBinary(destFile); + } + + StreamWriter outw = null; + if (asciiTrans) { + outw = new StreamWriter(outputStream); + } + + byte[] rdbuf = new byte[32 * 1024]; + + while (true) { + int numRead = tarIn.Read(rdbuf, 0, rdbuf.Length); + + if (numRead <= 0) { + break; + } + + if (asciiTrans) { + for (int off = 0, b = 0; b < numRead; ++b) { + if (rdbuf[b] == 10) { + string s = Encoding.ASCII.GetString(rdbuf, off, (b - off)); + outw.WriteLine(s); + off = b + 1; + } + } + } else { + outputStream.Write(rdbuf, 0, numRead); + } + } + + if (asciiTrans) { + outw.Close(); + } else { + outputStream.Close(); + } + } + } + } + + /// + /// Write an entry to the archive. This method will call the putNextEntry + /// and then write the contents of the entry, and finally call closeEntry() + /// for entries that are files. For directories, it will call putNextEntry(), + /// and then, if the recurse flag is true, process each entry that is a + /// child of the directory. + /// + /// + /// The TarEntry representing the entry to write to the archive. + /// + /// + /// If true, process the children of directory entries. + /// + public void WriteEntry(TarEntry sourceEntry, bool recurse) + { + if ( sourceEntry == null ) { + throw new ArgumentNullException("sourceEntry"); + } + + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + try + { + if ( recurse ) { + TarHeader.SetValueDefaults(sourceEntry.UserId, sourceEntry.UserName, + sourceEntry.GroupId, sourceEntry.GroupName); + } + WriteEntryCore(sourceEntry, recurse); + } + finally + { + if ( recurse ) { + TarHeader.RestoreSetValues(); + } + } + } + + /// + /// Write an entry to the archive. This method will call the putNextEntry + /// and then write the contents of the entry, and finally call closeEntry() + /// for entries that are files. For directories, it will call putNextEntry(), + /// and then, if the recurse flag is true, process each entry that is a + /// child of the directory. + /// + /// + /// The TarEntry representing the entry to write to the archive. + /// + /// + /// If true, process the children of directory entries. + /// + void WriteEntryCore(TarEntry sourceEntry, bool recurse) + { + string tempFileName = null; + string entryFilename = sourceEntry.File; + + TarEntry entry = (TarEntry)sourceEntry.Clone(); + + if ( applyUserInfoOverrides ) { + entry.GroupId = groupId; + entry.GroupName = groupName; + entry.UserId = userId; + entry.UserName = userName; + } + + OnProgressMessageEvent(entry, null); + + if (asciiTranslate && !entry.IsDirectory) { + + if (!IsBinary(entryFilename)) { + tempFileName = Path.GetTempFileName(); + + using (StreamReader inStream = File.OpenText(entryFilename)) { + using (Stream outStream = File.Create(tempFileName)) { + + while (true) { + string line = inStream.ReadLine(); + if (line == null) { + break; + } + byte[] data = Encoding.ASCII.GetBytes(line); + outStream.Write(data, 0, data.Length); + outStream.WriteByte((byte)'\n'); + } + + outStream.Flush(); + } + } + + entry.Size = new FileInfo(tempFileName).Length; + entryFilename = tempFileName; + } + } + + string newName = null; + + if (rootPath != null) { + if (entry.Name.StartsWith(rootPath)) { + newName = entry.Name.Substring(rootPath.Length + 1 ); + } + } + + if (pathPrefix != null) { + newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName; + } + + if (newName != null) { + entry.Name = newName; + } + + tarOut.PutNextEntry(entry); + + if (entry.IsDirectory) { + if (recurse) { + TarEntry[] list = entry.GetDirectoryEntries(); + for (int i = 0; i < list.Length; ++i) { + WriteEntryCore(list[i], recurse); + } + } + } + else { + using (Stream inputStream = File.OpenRead(entryFilename)) { + byte[] localBuffer = new byte[32 * 1024]; + while (true) { + int numRead = inputStream.Read(localBuffer, 0, localBuffer.Length); + + if (numRead <=0) { + break; + } + + tarOut.Write(localBuffer, 0, numRead); + } + } + + if ( (tempFileName != null) && (tempFileName.Length > 0) ) { + File.Delete(tempFileName); + } + + tarOut.CloseEntry(); + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if ( !isDisposed ) { + isDisposed = true; + if ( disposing ) { + if ( tarOut != null ) { + tarOut.Flush(); + tarOut.Close(); + } + + if ( tarIn != null ) { + tarIn.Close(); + } + } + } + } + + /// + /// Closes the archive and releases any associated resources. + /// + public virtual void Close() + { + Dispose(true); + } + + /// + /// Ensures that resources are freed and other cleanup operations are performed + /// when the garbage collector reclaims the . + /// + ~TarArchive() + { + Dispose(false); + } + + static void EnsureDirectoryExists(string directoryName) + { + if (!Directory.Exists(directoryName)) { + try { + Directory.CreateDirectory(directoryName); + } + catch (Exception e) { + throw new TarException("Exception creating directory '" + directoryName + "', " + e.Message, e); + } + } + } + + // TODO: TarArchive - Is there a better way to test for a text file? + // It no longer reads entire files into memory but is still a weak test! + // This assumes that byte values 0-7, 14-31 or 255 are binary + // and that all non text files contain one of these values + static bool IsBinary(string filename) + { + using (FileStream fs = File.OpenRead(filename)) + { + int sampleSize = Math.Min(4096, (int)fs.Length); + byte[] content = new byte[sampleSize]; + + int bytesRead = fs.Read(content, 0, sampleSize); + + for (int i = 0; i < bytesRead; ++i) { + byte b = content[i]; + if ( (b < 8) || ((b > 13) && (b < 32)) || (b == 255) ) { + return true; + } + } + } + return false; + } + + #region Instance Fields + bool keepOldFiles; + bool asciiTranslate; + + int userId; + string userName = string.Empty; + int groupId; + string groupName = string.Empty; + + string rootPath; + string pathPrefix; + + bool applyUserInfoOverrides; + + TarInputStream tarIn; + TarOutputStream tarOut; + bool isDisposed; + #endregion + } +} + + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ + diff --git a/类库/Update/ZIP/Tar/TarBuffer.cs b/类库/Update/ZIP/Tar/TarBuffer.cs new file mode 100644 index 0000000..40b8d93 --- /dev/null +++ b/类库/Update/ZIP/Tar/TarBuffer.cs @@ -0,0 +1,624 @@ +// TarBuffer.cs +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarBuffer class implements the tar archive concept + /// of a buffered input stream. This concept goes back to the + /// days of blocked tape drives and special io devices. In the + /// C# universe, the only real function that this class + /// performs is to ensure that files have the correct "record" + /// size, or other tars will complain. + ///

+ /// You should never have a need to access this class directly. + /// TarBuffers are created by Tar IO Streams. + ///

+ ///
+ public class TarBuffer + { + +/* A quote from GNU tar man file on blocking and records + A `tar' archive file contains a series of blocks. Each block +contains `BLOCKSIZE' bytes. Although this format may be thought of as +being on magnetic tape, other media are often used. + + Each file archived is represented by a header block which describes +the file, followed by zero or more blocks which give the contents of +the file. At the end of the archive file there may be a block filled +with binary zeros as an end-of-file marker. A reasonable system should +write a block of zeros at the end, but must not assume that such a +block exists when reading an archive. + + The blocks may be "blocked" for physical I/O operations. Each +record of N blocks is written with a single 'write ()' +operation. On magnetic tapes, the result of such a write is a single +record. When writing an archive, the last record of blocks should be +written at the full size, with blocks after the zero block containing +all zeros. When reading an archive, a reasonable system should +properly handle an archive whose last record is shorter than the rest, +or which contains garbage records after a zero block. +*/ + + #region Constants + /// + /// The size of a block in a tar archive in bytes. + /// + /// This is 512 bytes. + public const int BlockSize = 512; + + /// + /// The number of blocks in a default record. + /// + /// + /// The default value is 20 blocks per record. + /// + public const int DefaultBlockFactor = 20; + + /// + /// The size in bytes of a default record. + /// + /// + /// The default size is 10KB. + /// + public const int DefaultRecordSize = BlockSize * DefaultBlockFactor; + #endregion + + /// + /// Get the record size for this buffer + /// + /// The record size in bytes. + /// This is equal to the multiplied by the + public int RecordSize + { + get { + return recordSize; + } + } + + /// + /// Get the TAR Buffer's record size. + /// + /// The record size in bytes. + /// This is equal to the multiplied by the + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return recordSize; + } + + /// + /// Get the Blocking factor for the buffer + /// + /// This is the number of blocks in each record. + public int BlockFactor { + get { + return blockFactor; + } + } + + /// + /// Get the TAR Buffer's block factor + /// + /// The block factor; the number of blocks per record. + [Obsolete("Use BlockFactor property instead")] + public int GetBlockFactor() + { + return blockFactor; + } + + /// + /// Construct a default TarBuffer + /// + protected TarBuffer() + { + } + + /// + /// Create TarBuffer for reading with default BlockFactor + /// + /// Stream to buffer + /// A new suitable for input. + public static TarBuffer CreateInputTarBuffer(Stream inputStream) + { + if ( inputStream == null ) + { + throw new ArgumentNullException("inputStream"); + } + + return CreateInputTarBuffer(inputStream, DefaultBlockFactor); + } + + /// + /// Construct TarBuffer for reading inputStream setting BlockFactor + /// + /// Stream to buffer + /// Blocking factor to apply + /// A new suitable for input. + public static TarBuffer CreateInputTarBuffer(Stream inputStream, int blockFactor) + { + if ( inputStream == null ) + { + throw new ArgumentNullException("inputStream"); + } + + if ( blockFactor <= 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("blockFactor"); +#else + throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative"); +#endif + } + + TarBuffer tarBuffer = new TarBuffer(); + tarBuffer.inputStream = inputStream; + tarBuffer.outputStream = null; + tarBuffer.Initialize(blockFactor); + + return tarBuffer; + } + + /// + /// Construct TarBuffer for writing with default BlockFactor + /// + /// output stream for buffer + /// A new suitable for output. + public static TarBuffer CreateOutputTarBuffer(Stream outputStream) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + return CreateOutputTarBuffer(outputStream, DefaultBlockFactor); + } + + /// + /// Construct TarBuffer for writing Tar output to streams. + /// + /// Output stream to write to. + /// Blocking factor to apply + /// A new suitable for output. + public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + if ( blockFactor <= 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("blockFactor"); +#else + throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative"); +#endif + } + + TarBuffer tarBuffer = new TarBuffer(); + tarBuffer.inputStream = null; + tarBuffer.outputStream = outputStream; + tarBuffer.Initialize(blockFactor); + + return tarBuffer; + } + + /// + /// Initialization common to all constructors. + /// + void Initialize(int archiveBlockFactor) + { + blockFactor = archiveBlockFactor; + recordSize = archiveBlockFactor * BlockSize; + recordBuffer = new byte[RecordSize]; + + if (inputStream != null) { + currentRecordIndex = -1; + currentBlockIndex = BlockFactor; + } + else { + currentRecordIndex = 0; + currentBlockIndex = 0; + } + } + + /// + /// Determine if an archive block indicates End of Archive. End of + /// archive is indicated by a block that consists entirely of null bytes. + /// All remaining blocks for the record should also be null's + /// However some older tars only do a couple of null blocks (Old GNU tar for one) + /// and also partial records + /// + /// The data block to check. + /// Returns true if the block is an EOF block; false otherwise. + [Obsolete("Use IsEndOfArchiveBlock instead")] + public bool IsEOFBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if ( block.Length != BlockSize ) + { + throw new ArgumentException("block length is invalid"); + } + + for (int i = 0; i < BlockSize; ++i) { + if (block[i] != 0) { + return false; + } + } + + return true; + } + + + /// + /// Determine if an archive block indicates the End of an Archive has been reached. + /// End of archive is indicated by a block that consists entirely of null bytes. + /// All remaining blocks for the record should also be null's + /// However some older tars only do a couple of null blocks (Old GNU tar for one) + /// and also partial records + /// + /// The data block to check. + /// Returns true if the block is an EOF block; false otherwise. + public static bool IsEndOfArchiveBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if ( block.Length != BlockSize ) { + throw new ArgumentException("block length is invalid"); + } + + for ( int i = 0; i < BlockSize; ++i ) { + if ( block[i] != 0 ) { + return false; + } + } + + return true; + } + + /// + /// Skip over a block on the input stream. + /// + public void SkipBlock() + { + if (inputStream == null) { + throw new TarException("no input stream defined"); + } + + if (currentBlockIndex >= BlockFactor) { + if (!ReadRecord()) { + throw new TarException("Failed to read a record"); + } + } + + currentBlockIndex++; + } + + /// + /// Read a block from the input stream. + /// + /// + /// The block of data read. + /// + public byte[] ReadBlock() + { + if (inputStream == null) { + throw new TarException("TarBuffer.ReadBlock - no input stream defined"); + } + + if (currentBlockIndex >= BlockFactor) { + if (!ReadRecord()) { + throw new TarException("Failed to read a record"); + } + } + + byte[] result = new byte[BlockSize]; + + Array.Copy(recordBuffer, (currentBlockIndex * BlockSize), result, 0, BlockSize ); + currentBlockIndex++; + return result; + } + + /// + /// Read a record from data stream. + /// + /// + /// false if End-Of-File, else true. + /// + bool ReadRecord() + { + if (inputStream == null) { + throw new TarException("no input stream stream defined"); + } + + currentBlockIndex = 0; + + int offset = 0; + int bytesNeeded = RecordSize; + + while (bytesNeeded > 0) { + long numBytes = inputStream.Read(recordBuffer, offset, bytesNeeded); + + // + // NOTE + // We have found EOF, and the record is not full! + // + // This is a broken archive. It does not follow the standard + // blocking algorithm. However, because we are generous, and + // it requires little effort, we will simply ignore the error + // and continue as if the entire record were read. This does + // not appear to break anything upstream. We used to return + // false in this case. + // + // Thanks to 'Yohann.Roussel@alcatel.fr' for this fix. + // + if (numBytes <= 0) { + break; + } + + offset += (int)numBytes; + bytesNeeded -= (int)numBytes; + } + + currentRecordIndex++; + return true; + } + + /// + /// Get the current block number, within the current record, zero based. + /// + /// Block numbers are zero based values + /// + public int CurrentBlock + { + get { return currentBlockIndex; } + } + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner_; } + set { isStreamOwner_ = value; } + } + + /// + /// Get the current block number, within the current record, zero based. + /// + /// + /// The current zero based block number. + /// + /// + /// The absolute block number = (record number * block factor) + block number. + /// + [Obsolete("Use CurrentBlock property instead")] + public int GetCurrentBlockNum() + { + return currentBlockIndex; + } + + /// + /// Get the current record number. + /// + /// + /// The current zero based record number. + /// + public int CurrentRecord + { + get { return currentRecordIndex; } + } + + /// + /// Get the current record number. + /// + /// + /// The current zero based record number. + /// + [Obsolete("Use CurrentRecord property instead")] + public int GetCurrentRecordNum() + { + return currentRecordIndex; + } + + /// + /// Write a block of data to the archive. + /// + /// + /// The data to write to the archive. + /// + public void WriteBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if (outputStream == null) { + throw new TarException("TarBuffer.WriteBlock - no output stream defined"); + } + + if (block.Length != BlockSize) { + string errorText = string.Format("TarBuffer.WriteBlock - block to write has length '{0}' which is not the block size of '{1}'", + block.Length, BlockSize ); + throw new TarException(errorText); + } + + if (currentBlockIndex >= BlockFactor) { + WriteRecord(); + } + + Array.Copy(block, 0, recordBuffer, (currentBlockIndex * BlockSize), BlockSize); + currentBlockIndex++; + } + + /// + /// Write an archive record to the archive, where the record may be + /// inside of a larger array buffer. The buffer must be "offset plus + /// record size" long. + /// + /// + /// The buffer containing the record data to write. + /// + /// + /// The offset of the record data within buffer. + /// + public void WriteBlock(byte[] buffer, int offset) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if (outputStream == null) { + throw new TarException("TarBuffer.WriteBlock - no output stream stream defined"); + } + + if ( (offset < 0) || (offset >= buffer.Length) ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ((offset + BlockSize) > buffer.Length) { + string errorText = string.Format("TarBuffer.WriteBlock - record has length '{0}' with offset '{1}' which is less than the record size of '{2}'", + buffer.Length, offset, recordSize); + throw new TarException(errorText); + } + + if (currentBlockIndex >= BlockFactor) { + WriteRecord(); + } + + Array.Copy(buffer, offset, recordBuffer, (currentBlockIndex * BlockSize), BlockSize); + + currentBlockIndex++; + } + + /// + /// Write a TarBuffer record to the archive. + /// + void WriteRecord() + { + if (outputStream == null) { + throw new TarException("TarBuffer.WriteRecord no output stream defined"); + } + + outputStream.Write(recordBuffer, 0, RecordSize); + outputStream.Flush(); + + currentBlockIndex = 0; + currentRecordIndex++; + } + + /// + /// WriteFinalRecord writes the current record buffer to output any unwritten data is present. + /// + /// Any trailing bytes are set to zero which is by definition correct behaviour + /// for the end of a tar stream. + void WriteFinalRecord() + { + if (outputStream == null) { + throw new TarException("TarBuffer.WriteFinalRecord no output stream defined"); + } + + if (currentBlockIndex > 0) { + int dataBytes = currentBlockIndex * BlockSize; + Array.Clear(recordBuffer, dataBytes, RecordSize - dataBytes); + WriteRecord(); + } + + outputStream.Flush(); + } + + /// + /// Close the TarBuffer. If this is an output buffer, also flush the + /// current block before closing. + /// + public void Close() + { + if (outputStream != null) { + WriteFinalRecord(); + + if (isStreamOwner_) { + outputStream.Close(); + } + outputStream = null; + } + else if (inputStream != null) { + if (isStreamOwner_) { + inputStream.Close(); + } + inputStream = null; + } + } + + #region Instance Fields + Stream inputStream; + Stream outputStream; + + byte[] recordBuffer; + int currentBlockIndex; + int currentRecordIndex; + + int recordSize = DefaultRecordSize; + int blockFactor = DefaultBlockFactor; + bool isStreamOwner_ = true; + #endregion + } +} + +/* The original Java file had this header: + * + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/Update/ZIP/Tar/TarEntry.cs b/类库/Update/ZIP/Tar/TarEntry.cs new file mode 100644 index 0000000..a733e32 --- /dev/null +++ b/类库/Update/ZIP/Tar/TarEntry.cs @@ -0,0 +1,559 @@ +// TarEntry.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + /// + /// This class represents an entry in a Tar archive. It consists + /// of the entry's header, as well as the entry's File. Entries + /// can be instantiated in one of three ways, depending on how + /// they are to be used. + ///

+ /// TarEntries that are created from the header bytes read from + /// an archive are instantiated with the TarEntry( byte[] ) + /// constructor. These entries will be used when extracting from + /// or listing the contents of an archive. These entries have their + /// header filled in using the header bytes. They also set the File + /// to null, since they reference an archive entry not a file.

+ ///

+ /// TarEntries that are created from files that are to be written + /// into an archive are instantiated with the CreateEntryFromFile(string) + /// pseudo constructor. These entries have their header filled in using + /// the File's information. They also keep a reference to the File + /// for convenience when writing entries.

+ ///

+ /// Finally, TarEntries can be constructed from nothing but a name. + /// This allows the programmer to construct the entry by hand, for + /// instance when only an InputStream is available for writing to + /// the archive, and the header information is constructed from + /// other information. In this case the header fields are set to + /// defaults and the File is set to null.

+ /// + ///
+ public class TarEntry : ICloneable + { + #region Constructors + /// + /// Initialise a default instance of . + /// + private TarEntry() + { + header = new TarHeader(); + } + + /// + /// Construct an entry from an archive's header bytes. File is set + /// to null. + /// + /// + /// The header bytes from a tar archive entry. + /// + public TarEntry(byte[] headerBuffer) + { + header = new TarHeader(); + header.ParseBuffer(headerBuffer); + } + + /// + /// Construct a TarEntry using the header provided + /// + /// Header details for entry + public TarEntry(TarHeader header) + { + if ( header == null ) + { + throw new ArgumentNullException("header"); + } + + this.header = (TarHeader)header.Clone(); + } + #endregion + + #region ICloneable Members + /// + /// Clone this tar entry. + /// + /// Returns a clone of this entry. + public object Clone() + { + TarEntry entry = new TarEntry(); + entry.file = file; + entry.header = (TarHeader)header.Clone(); + entry.Name = Name; + return entry; + } + #endregion + + /// + /// Construct an entry with only a name. + /// This allows the programmer to construct the entry's header "by hand". + /// + /// The name to use for the entry + /// Returns the newly created + public static TarEntry CreateTarEntry(string name) + { + TarEntry entry = new TarEntry(); + TarEntry.NameTarHeader(entry.header, name); + return entry; + } + + /// + /// Construct an entry for a file. File is set to file, and the + /// header is constructed from information from the file. + /// + /// The file name that the entry represents. + /// Returns the newly created + public static TarEntry CreateEntryFromFile(string fileName) + { + TarEntry entry = new TarEntry(); + entry.GetFileTarHeader(entry.header, fileName); + return entry; + } + + /// + /// Determine if the two entries are equal. Equality is determined + /// by the header names being equal. + /// + /// The to compare with the current Object. + /// + /// True if the entries are equal; false if not. + /// + public override bool Equals(object obj) + { + TarEntry localEntry = obj as TarEntry; + + if ( localEntry != null ) + { + return Name.Equals(localEntry.Name); + } + return false; + } + + /// + /// Derive a Hash value for the current + /// + /// A Hash code for the current + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + /// Determine if the given entry is a descendant of this entry. + /// Descendancy is determined by the name of the descendant + /// starting with this entry's name. + /// + /// + /// Entry to be checked as a descendent of this. + /// + /// + /// True if entry is a descendant of this. + /// + public bool IsDescendent(TarEntry toTest) + { + if ( toTest == null ) { + throw new ArgumentNullException("toTest"); + } + + return toTest.Name.StartsWith(Name); + } + + /// + /// Get this entry's header. + /// + /// + /// This entry's TarHeader. + /// + public TarHeader TarHeader + { + get { + return header; + } + } + + /// + /// Get/Set this entry's name. + /// + public string Name + { + get { + return header.Name; + } + set { + header.Name = value; + } + } + + /// + /// Get/set this entry's user id. + /// + public int UserId + { + get { + return header.UserId; + } + set { + header.UserId = value; + } + } + + /// + /// Get/set this entry's group id. + /// + public int GroupId + { + get { + return header.GroupId; + } + set { + header.GroupId = value; + } + } + + /// + /// Get/set this entry's user name. + /// + public string UserName + { + get { + return header.UserName; + } + set { + header.UserName = value; + } + } + + /// + /// Get/set this entry's group name. + /// + public string GroupName + { + get { + return header.GroupName; + } + set { + header.GroupName = value; + } + } + + /// + /// Convenience method to set this entry's group and user ids. + /// + /// + /// This entry's new user id. + /// + /// + /// This entry's new group id. + /// + public void SetIds(int userId, int groupId) + { + UserId = userId; + GroupId = groupId; + } + + /// + /// Convenience method to set this entry's group and user names. + /// + /// + /// This entry's new user name. + /// + /// + /// This entry's new group name. + /// + public void SetNames(string userName, string groupName) + { + UserName = userName; + GroupName = groupName; + } + + /// + /// Get/Set the modification time for this entry + /// + public DateTime ModTime { + get { + return header.ModTime; + } + set { + header.ModTime = value; + } + } + + /// + /// Get this entry's file. + /// + /// + /// This entry's file. + /// + public string File { + get { + return file; + } + } + + /// + /// Get/set this entry's recorded file size. + /// + public long Size { + get { + return header.Size; + } + set { + header.Size = value; + } + } + + /// + /// Return true if this entry represents a directory, false otherwise + /// + /// + /// True if this entry is a directory. + /// + public bool IsDirectory { + get { + if (file != null) { + return Directory.Exists(file); + } + + if (header != null) { + if ((header.TypeFlag == TarHeader.LF_DIR) || Name.EndsWith( "/" )) { + return true; + } + } + return false; + } + } + + /// + /// Fill in a TarHeader with information from a File. + /// + /// + /// The TarHeader to fill in. + /// + /// + /// The file from which to get the header information. + /// + public void GetFileTarHeader(TarHeader header, string file) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( file == null ) { + throw new ArgumentNullException("file"); + } + + this.file = file; + + // bugfix from torhovl from #D forum: + string name = file; + +#if !NETCF_1_0 && !NETCF_2_0 + // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory + if (name.IndexOf(Environment.CurrentDirectory) == 0) { + name = name.Substring(Environment.CurrentDirectory.Length); + } +#endif + +/* + if (Path.DirectorySeparatorChar == '\\') + { + // check if the OS is Windows + // Strip off drive letters! + if (name.Length > 2) + { + char ch1 = name[0]; + char ch2 = name[1]; + + if (ch2 == ':' && Char.IsLetter(ch1)) + { + name = name.Substring(2); + } + } + } +*/ + + name = name.Replace(Path.DirectorySeparatorChar, '/'); + + // No absolute pathnames + // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\", + // so we loop on starting /'s. + while (name.StartsWith("/")) { + name = name.Substring(1); + } + + header.LinkName = String.Empty; + header.Name = name; + + if (Directory.Exists(file)) { + header.Mode = 1003; // Magic number for security access for a UNIX filesystem + header.TypeFlag = TarHeader.LF_DIR; + if ( (header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') { + header.Name = header.Name + "/"; + } + + header.Size = 0; + } else { + header.Mode = 33216; // Magic number for security access for a UNIX filesystem + header.TypeFlag = TarHeader.LF_NORMAL; + header.Size = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length; + } + + header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime(); + header.DevMajor = 0; + header.DevMinor = 0; + } + + /// + /// Get entries for all files present in this entries directory. + /// If this entry doesnt represent a directory zero entries are returned. + /// + /// + /// An array of TarEntry's for this entry's children. + /// + public TarEntry[] GetDirectoryEntries() + { + if ( (file == null) || !Directory.Exists(file)) { + return new TarEntry[0]; + } + + string[] list = Directory.GetFileSystemEntries(file); + TarEntry[] result = new TarEntry[list.Length]; + + for (int i = 0; i < list.Length; ++i) { + result[i] = TarEntry.CreateEntryFromFile(list[i]); + } + + return result; + } + + /// + /// Write an entry's header information to a header buffer. + /// + /// + /// The tar entry header buffer to fill in. + /// + public void WriteEntryHeader(byte[] outBuffer) + { + header.WriteHeader(outBuffer); + } + + /// + /// Convenience method that will modify an entry's name directly + /// in place in an entry header buffer byte array. + /// + /// + /// The buffer containing the entry header to modify. + /// + /// + /// The new name to place into the header buffer. + /// + static public void AdjustEntryName(byte[] buffer, string newName) + { + TarHeader.GetNameBytes(newName, buffer, 0, TarHeader.NAMELEN); + } + + /// + /// Fill in a TarHeader given only the entry's name. + /// + /// + /// The TarHeader to fill in. + /// + /// + /// The tar entry name. + /// + static public void NameTarHeader(TarHeader header, string name) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + bool isDir = name.EndsWith("/"); + + header.Name = name; + header.Mode = isDir ? 1003 : 33216; + header.UserId = 0; + header.GroupId = 0; + header.Size = 0; + + header.ModTime = DateTime.UtcNow; + + header.TypeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL; + + header.LinkName = String.Empty; + header.UserName = String.Empty; + header.GroupName = String.Empty; + + header.DevMajor = 0; + header.DevMinor = 0; + } + + #region Instance Fields + /// + /// The name of the file this entry represents or null if the entry is not based on a file. + /// + string file; + + /// + /// The entry's header information. + /// + TarHeader header; + #endregion + } +} + + + +/* The original Java file had this header: + * + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/Update/ZIP/Tar/TarException.cs b/类库/Update/ZIP/Tar/TarException.cs new file mode 100644 index 0000000..84a6eba --- /dev/null +++ b/类库/Update/ZIP/Tar/TarException.cs @@ -0,0 +1,91 @@ +// TarException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Tar { + + /// + /// TarExceptions are used for exceptions specific to tar classes and code. + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class TarException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected TarException(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + + /// + /// Initialises a new instance of the TarException class. + /// + public TarException() + { + } + + /// + /// Initialises a new instance of the TarException class with a specified message. + /// + /// The message that describes the error. + public TarException(string message) + : base(message) + { + } + + /// + /// + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public TarException(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/Update/ZIP/Tar/TarHeader.cs b/类库/Update/ZIP/Tar/TarHeader.cs new file mode 100644 index 0000000..fc49f16 --- /dev/null +++ b/类库/Update/ZIP/Tar/TarHeader.cs @@ -0,0 +1,1156 @@ +// TarHeader.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +/* The tar format and its POSIX successor PAX have a long history which makes for compatability + issues when creating and reading files. + + This is further complicated by a large number of programs with variations on formats + One common issue is the handling of names longer than 100 characters. + GNU style long names are currently supported. + +This is the ustar (Posix 1003.1) header. + +struct header +{ + char t_name[100]; // 0 Filename + char t_mode[8]; // 100 Permissions + char t_uid[8]; // 108 Numerical User ID + char t_gid[8]; // 116 Numerical Group ID + char t_size[12]; // 124 Filesize + char t_mtime[12]; // 136 st_mtime + char t_chksum[8]; // 148 Checksum + char t_typeflag; // 156 Type of File + char t_linkname[100]; // 157 Target of Links + char t_magic[6]; // 257 "ustar" or other... + char t_version[2]; // 263 Version fixed to 00 + char t_uname[32]; // 265 User Name + char t_gname[32]; // 297 Group Name + char t_devmajor[8]; // 329 Major for devices + char t_devminor[8]; // 337 Minor for devices + char t_prefix[155]; // 345 Prefix for t_name + char t_mfill[12]; // 500 Filler up to 512 +}; + +*/ + +using System; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + + /// + /// This class encapsulates the Tar Entry Header used in Tar Archives. + /// The class also holds a number of tar constants, used mostly in headers. + /// + public class TarHeader : ICloneable + { + #region Constants + /// + /// The length of the name field in a header buffer. + /// + public const int NAMELEN = 100; + + /// + /// The length of the mode field in a header buffer. + /// + public const int MODELEN = 8; + + /// + /// The length of the user id field in a header buffer. + /// + public const int UIDLEN = 8; + + /// + /// The length of the group id field in a header buffer. + /// + public const int GIDLEN = 8; + + /// + /// The length of the checksum field in a header buffer. + /// + public const int CHKSUMLEN = 8; + + /// + /// Offset of checksum in a header buffer. + /// + public const int CHKSUMOFS = 148; + + /// + /// The length of the size field in a header buffer. + /// + public const int SIZELEN = 12; + + /// + /// The length of the magic field in a header buffer. + /// + public const int MAGICLEN = 6; + + /// + /// The length of the version field in a header buffer. + /// + public const int VERSIONLEN = 2; + + /// + /// The length of the modification time field in a header buffer. + /// + public const int MODTIMELEN = 12; + + /// + /// The length of the user name field in a header buffer. + /// + public const int UNAMELEN = 32; + + /// + /// The length of the group name field in a header buffer. + /// + public const int GNAMELEN = 32; + + /// + /// The length of the devices field in a header buffer. + /// + public const int DEVLEN = 8; + + // + // LF_ constants represent the "type" of an entry + // + + /// + /// The "old way" of indicating a normal file. + /// + public const byte LF_OLDNORM = 0; + + /// + /// Normal file type. + /// + public const byte LF_NORMAL = (byte) '0'; + + /// + /// Link file type. + /// + public const byte LF_LINK = (byte) '1'; + + /// + /// Symbolic link file type. + /// + public const byte LF_SYMLINK = (byte) '2'; + + /// + /// Character device file type. + /// + public const byte LF_CHR = (byte) '3'; + + /// + /// Block device file type. + /// + public const byte LF_BLK = (byte) '4'; + + /// + /// Directory file type. + /// + public const byte LF_DIR = (byte) '5'; + + /// + /// FIFO (pipe) file type. + /// + public const byte LF_FIFO = (byte) '6'; + + /// + /// Contiguous file type. + /// + public const byte LF_CONTIG = (byte) '7'; + + /// + /// Posix.1 2001 global extended header + /// + public const byte LF_GHDR = (byte) 'g'; + + /// + /// Posix.1 2001 extended header + /// + public const byte LF_XHDR = (byte) 'x'; + + // POSIX allows for upper case ascii type as extensions + + /// + /// Solaris access control list file type + /// + public const byte LF_ACL = (byte) 'A'; + + /// + /// GNU dir dump file type + /// This is a dir entry that contains the names of files that were in the + /// dir at the time the dump was made + /// + public const byte LF_GNU_DUMPDIR = (byte) 'D'; + + /// + /// Solaris Extended Attribute File + /// + public const byte LF_EXTATTR = (byte) 'E' ; + + /// + /// Inode (metadata only) no file content + /// + public const byte LF_META = (byte) 'I'; + + /// + /// Identifies the next file on the tape as having a long link name + /// + public const byte LF_GNU_LONGLINK = (byte) 'K'; + + /// + /// Identifies the next file on the tape as having a long name + /// + public const byte LF_GNU_LONGNAME = (byte) 'L'; + + /// + /// Continuation of a file that began on another volume + /// + public const byte LF_GNU_MULTIVOL = (byte) 'M'; + + /// + /// For storing filenames that dont fit in the main header (old GNU) + /// + public const byte LF_GNU_NAMES = (byte) 'N'; + + /// + /// GNU Sparse file + /// + public const byte LF_GNU_SPARSE = (byte) 'S'; + + /// + /// GNU Tape/volume header ignore on extraction + /// + public const byte LF_GNU_VOLHDR = (byte) 'V'; + + /// + /// The magic tag representing a POSIX tar archive. (includes trailing NULL) + /// + public const string TMAGIC = "ustar "; + + /// + /// The magic tag representing an old GNU tar archive where version is included in magic and overwrites it + /// + public const string GNU_TMAGIC = "ustar "; + + const long timeConversionFactor = 10000000L; // 1 tick == 100 nanoseconds + readonly static DateTime dateTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0); + #endregion + + #region Constructors + + /// + /// Initialise a default TarHeader instance + /// + public TarHeader() + { + Magic = TMAGIC; + Version = " "; + + Name = ""; + LinkName = ""; + + UserId = defaultUserId; + GroupId = defaultGroupId; + UserName = defaultUser; + GroupName = defaultGroupName; + Size = 0; + } + + #endregion + + #region Properties + /// + /// Get/set the name for this tar entry. + /// + /// Thrown when attempting to set the property to null. + public string Name + { + get { return name; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + name = value; + } + } + + /// + /// Get the name of this entry. + /// + /// The entry's name. + [Obsolete("Use the Name property instead", true)] + public string GetName() + { + return name; + } + + /// + /// Get/set the entry's Unix style permission mode. + /// + public int Mode + { + get { return mode; } + set { mode = value; } + } + + + /// + /// The entry's user id. + /// + /// + /// This is only directly relevant to unix systems. + /// The default is zero. + /// + public int UserId + { + get { return userId; } + set { userId = value; } + } + + + /// + /// Get/set the entry's group id. + /// + /// + /// This is only directly relevant to linux/unix systems. + /// The default value is zero. + /// + public int GroupId + { + get { return groupId; } + set { groupId = value; } + } + + + /// + /// Get/set the entry's size. + /// + /// Thrown when setting the size to less than zero. + public long Size + { + get { return size; } + set { + if ( value < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Cannot be less than zero"); +#endif + } + size = value; + } + } + + + /// + /// Get/set the entry's modification time. + /// + /// + /// The modification time is only accurate to within a second. + /// + /// Thrown when setting the date time to less than 1/1/1970. + public DateTime ModTime + { + get { return modTime; } + set { + if ( value < dateTime1970 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "ModTime cannot be before Jan 1st 1970"); +#endif + } + modTime = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second); + } + } + + + /// + /// Get the entry's checksum. This is only valid/updated after writing or reading an entry. + /// + public int Checksum + { + get { return checksum; } + } + + + /// + /// Get value of true if the header checksum is valid, false otherwise. + /// + public bool IsChecksumValid + { + get { return isChecksumValid; } + } + + + /// + /// Get/set the entry's type flag. + /// + public byte TypeFlag + { + get { return typeFlag; } + set { typeFlag = value; } + } + + + /// + /// The entry's link name. + /// + /// Thrown when attempting to set LinkName to null. + public string LinkName + { + get { return linkName; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + linkName = value; + } + } + + + /// + /// Get/set the entry's magic tag. + /// + /// Thrown when attempting to set Magic to null. + public string Magic + { + get { return magic; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + magic = value; + } + } + + + /// + /// The entry's version. + /// + /// Thrown when attempting to set Version to null. + public string Version + { + get { + return version; + } + + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + version = value; + } + } + + + /// + /// The entry's user name. + /// + public string UserName + { + get { return userName; } + set { + if (value != null) { + userName = value.Substring(0, Math.Min(UNAMELEN, value.Length)); + } + else { +#if NETCF_1_0 || NETCF_2_0 + string currentUser = "PocketPC"; +#else + string currentUser = Environment.UserName; +#endif + if (currentUser.Length > UNAMELEN) { + currentUser = currentUser.Substring(0, UNAMELEN); + } + userName = currentUser; + } + } + } + + + /// + /// Get/set the entry's group name. + /// + /// + /// This is only directly relevant to unix systems. + /// + public string GroupName + { + get { return groupName; } + set { + if ( value == null ) { + groupName = "None"; + } + else { + groupName = value; + } + } + } + + + /// + /// Get/set the entry's major device number. + /// + public int DevMajor + { + get { return devMajor; } + set { devMajor = value; } + } + + + /// + /// Get/set the entry's minor device number. + /// + public int DevMinor + { + get { return devMinor; } + set { devMinor = value; } + } + + #endregion + + #region ICloneable Members + /// + /// Create a new that is a copy of the current instance. + /// + /// A new that is a copy of the current instance. + public object Clone() + { + return MemberwiseClone(); + } + #endregion + + /// + /// Parse TarHeader information from a header buffer. + /// + /// + /// The tar entry header buffer to get information from. + /// + public void ParseBuffer(byte[] header) + { + if ( header == null ) + { + throw new ArgumentNullException("header"); + } + + int offset = 0; + + name = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString(); + offset += TarHeader.NAMELEN; + + mode = (int)TarHeader.ParseOctal(header, offset, TarHeader.MODELEN); + offset += TarHeader.MODELEN; + + UserId = (int)TarHeader.ParseOctal(header, offset, TarHeader.UIDLEN); + offset += TarHeader.UIDLEN; + + GroupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN); + offset += TarHeader.GIDLEN; + + Size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN); + offset += TarHeader.SIZELEN; + + ModTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN)); + offset += TarHeader.MODTIMELEN; + + checksum = (int)TarHeader.ParseOctal(header, offset, TarHeader.CHKSUMLEN); + offset += TarHeader.CHKSUMLEN; + + TypeFlag = header[ offset++ ]; + + LinkName = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString(); + offset += TarHeader.NAMELEN; + + Magic = TarHeader.ParseName(header, offset, TarHeader.MAGICLEN).ToString(); + offset += TarHeader.MAGICLEN; + + Version = TarHeader.ParseName(header, offset, TarHeader.VERSIONLEN).ToString(); + offset += TarHeader.VERSIONLEN; + + UserName = TarHeader.ParseName(header, offset, TarHeader.UNAMELEN).ToString(); + offset += TarHeader.UNAMELEN; + + GroupName = TarHeader.ParseName(header, offset, TarHeader.GNAMELEN).ToString(); + offset += TarHeader.GNAMELEN; + + DevMajor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN); + offset += TarHeader.DEVLEN; + + DevMinor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN); + + // Fields past this point not currently parsed or used... + + isChecksumValid = Checksum == TarHeader.MakeCheckSum(header); + } + + /// + /// 'Write' header information to buffer provided, updating the check sum. + /// + /// output buffer for header information + public void WriteHeader(byte[] outBuffer) + { + if ( outBuffer == null ) + { + throw new ArgumentNullException("outBuffer"); + } + + int offset = 0; + + offset = GetNameBytes(Name, outBuffer, offset, NAMELEN); + offset = GetOctalBytes(mode, outBuffer, offset, MODELEN); + offset = GetOctalBytes(UserId, outBuffer, offset, UIDLEN); + offset = GetOctalBytes(GroupId, outBuffer, offset, GIDLEN); + + offset = GetLongOctalBytes(Size, outBuffer, offset, SIZELEN); + offset = GetLongOctalBytes(GetCTime(ModTime), outBuffer, offset, MODTIMELEN); + + int csOffset = offset; + for (int c = 0; c < CHKSUMLEN; ++c) + { + outBuffer[offset++] = (byte)' '; + } + + outBuffer[offset++] = TypeFlag; + + offset = GetNameBytes(LinkName, outBuffer, offset, NAMELEN); + offset = GetAsciiBytes(Magic, 0, outBuffer, offset, MAGICLEN); + offset = GetNameBytes(Version, outBuffer, offset, VERSIONLEN); + offset = GetNameBytes(UserName, outBuffer, offset, UNAMELEN); + offset = GetNameBytes(GroupName, outBuffer, offset, GNAMELEN); + + if ((TypeFlag == LF_CHR) || (TypeFlag == LF_BLK)) + { + offset = GetOctalBytes(DevMajor, outBuffer, offset, DEVLEN); + offset = GetOctalBytes(DevMinor, outBuffer, offset, DEVLEN); + } + + for ( ; offset < outBuffer.Length; ) + { + outBuffer[offset++] = 0; + } + + checksum = ComputeCheckSum(outBuffer); + + GetCheckSumOctalBytes(checksum, outBuffer, csOffset, CHKSUMLEN); + isChecksumValid = true; + } + + /// + /// Get a hash code for the current object. + /// + /// A hash code for the current object. + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + /// Determines if this instance is equal to the specified object. + /// + /// The object to compare with. + /// true if the objects are equal, false otherwise. + public override bool Equals(object obj) + { + TarHeader localHeader = obj as TarHeader; + + bool result; + if ( localHeader != null ) + { + result = (name == localHeader.name) + && (mode == localHeader.mode) + && (UserId == localHeader.UserId) + && (GroupId == localHeader.GroupId) + && (Size == localHeader.Size) + && (ModTime == localHeader.ModTime) + && (Checksum == localHeader.Checksum) + && (TypeFlag == localHeader.TypeFlag) + && (LinkName == localHeader.LinkName) + && (Magic == localHeader.Magic) + && (Version == localHeader.Version) + && (UserName == localHeader.UserName) + && (GroupName == localHeader.GroupName) + && (DevMajor == localHeader.DevMajor) + && (DevMinor == localHeader.DevMinor); + } + else + { + result = false; + } + return result; + } + + /// + /// Set defaults for values used when constructing a TarHeader instance. + /// + /// Value to apply as a default for userId. + /// Value to apply as a default for userName. + /// Value to apply as a default for groupId. + /// Value to apply as a default for groupName. + static internal void SetValueDefaults(int userId, string userName, int groupId, string groupName) + { + defaultUserId = userIdAsSet = userId; + defaultUser = userNameAsSet = userName; + defaultGroupId = groupIdAsSet = groupId; + defaultGroupName = groupNameAsSet = groupName; + } + + static internal void RestoreSetValues() + { + defaultUserId = userIdAsSet; + defaultUser = userNameAsSet; + defaultGroupId = groupIdAsSet; + defaultGroupName = groupNameAsSet; + } + + /// + /// Parse an octal string from a header buffer. + /// + /// The header buffer from which to parse. + /// The offset into the buffer from which to parse. + /// The number of header bytes to parse. + /// The long equivalent of the octal string. + static public long ParseOctal(byte[] header, int offset, int length) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + long result = 0; + bool stillPadding = true; + + int end = offset + length; + for (int i = offset; i < end ; ++i) { + if (header[i] == 0) { + break; + } + + if (header[i] == (byte)' ' || header[i] == '0') { + if (stillPadding) { + continue; + } + + if (header[i] == (byte)' ') { + break; + } + } + + stillPadding = false; + + result = (result << 3) + (header[i] - '0'); + } + + return result; + } + + /// + /// Parse a name from a header buffer. + /// + /// + /// The header buffer from which to parse. + /// + /// + /// The offset into the buffer from which to parse. + /// + /// + /// The number of header bytes to parse. + /// + /// + /// The name parsed. + /// + static public StringBuilder ParseName(byte[] header, int offset, int length) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be less than zero"); +#endif + } + + if ( length < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("length"); +#else + throw new ArgumentOutOfRangeException("length", "Cannot be less than zero"); +#endif + } + + if ( offset + length > header.Length ) + { + throw new ArgumentException("Exceeds header size", "length"); + } + + StringBuilder result = new StringBuilder(length); + + for (int i = offset; i < offset + length; ++i) { + if (header[i] == 0) { + break; + } + result.Append((char)header[i]); + } + + return result; + } + + /// + /// Add name to the buffer as a collection of bytes + /// + /// The name to add + /// The offset of the first character + /// The buffer to add to + /// The index of the first byte to add + /// The number of characters/bytes to add + /// The next free index in the + public static int GetNameBytes(StringBuilder name, int nameOffset, byte[] buffer, int bufferOffset, int length) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name.ToString(), nameOffset, buffer, bufferOffset, length); + } + + /// + /// Add name to the buffer as a collection of bytes + /// + /// The name to add + /// The offset of the first character + /// The buffer to add to + /// The index of the first byte to add + /// The number of characters/bytes to add + /// The next free index in the + public static int GetNameBytes(string name, int nameOffset, byte[] buffer, int bufferOffset, int length) + { + if ( name == null ) + { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + int i; + + for (i = 0 ; i < length - 1 && nameOffset + i < name.Length; ++i) { + buffer[bufferOffset + i] = (byte)name[nameOffset + i]; + } + + for (; i < length ; ++i) { + buffer[bufferOffset + i] = 0; + } + + return bufferOffset + length; + } + + /// + /// Add an entry name to the buffer + /// + /// + /// The name to add + /// + /// + /// The buffer to add to + /// + /// + /// The offset into the buffer from which to start adding + /// + /// + /// The number of header bytes to add + /// + /// + /// The index of the next free byte in the buffer + /// + public static int GetNameBytes(StringBuilder name, byte[] buffer, int offset, int length) + { + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name.ToString(), 0, buffer, offset, length); + } + + /// + /// Add an entry name to the buffer + /// + /// The name to add + /// The buffer to add to + /// The offset into the buffer from which to start adding + /// The number of header bytes to add + /// The index of the next free byte in the buffer + public static int GetNameBytes(string name, byte[] buffer, int offset, int length) + { + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name, 0, buffer, offset, length); + } + + /// + /// Add a string to a buffer as a collection of ascii bytes. + /// + /// The string to add + /// The offset of the first character to add. + /// The buffer to add to. + /// The offset to start adding at. + /// The number of ascii characters to add. + /// The next free index in the buffer. + public static int GetAsciiBytes(string toAdd, int nameOffset, byte[] buffer, int bufferOffset, int length ) + { + if ( toAdd == null ) { + throw new ArgumentNullException("toAdd"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + for (int i = 0 ; i < length && nameOffset + i < toAdd.Length; ++i) + { + buffer[bufferOffset + i] = (byte)toAdd[nameOffset + i]; + } + return bufferOffset + length; + } + + /// + /// Put an octal representation of a value into a buffer + /// + /// + /// the value to be converted to octal + /// + /// + /// buffer to store the octal string + /// + /// + /// The offset into the buffer where the value starts + /// + /// + /// The length of the octal string to create + /// + /// + /// The offset of the character next byte after the octal string + /// + public static int GetOctalBytes(long value, byte[] buffer, int offset, int length) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + int localIndex = length - 1; + + // Either a space or null is valid here. We use NULL as per GNUTar + buffer[offset + localIndex] = 0; + --localIndex; + + if (value > 0) { + for ( long v = value; (localIndex >= 0) && (v > 0); --localIndex ) { + buffer[offset + localIndex] = (byte)((byte)'0' + (byte)(v & 7)); + v >>= 3; + } + } + + for ( ; localIndex >= 0; --localIndex ) { + buffer[offset + localIndex] = (byte)'0'; + } + + return offset + length; + } + + /// + /// Put an octal representation of a value into a buffer + /// + /// Value to be convert to octal + /// The buffer to update + /// The offset into the buffer to store the value + /// The length of the octal string + /// Index of next byte + public static int GetLongOctalBytes(long value, byte[] buffer, int offset, int length) + { + return GetOctalBytes(value, buffer, offset, length); + } + + /// + /// Add the checksum integer to header buffer. + /// + /// + /// The header buffer to set the checksum for + /// The offset into the buffer for the checksum + /// The number of header bytes to update. + /// It's formatted differently from the other fields: it has 6 digits, a + /// null, then a space -- rather than digits, a space, then a null. + /// The final space is already there, from checksumming + /// + /// The modified buffer offset + static int GetCheckSumOctalBytes(long value, byte[] buffer, int offset, int length) + { + TarHeader.GetOctalBytes(value, buffer, offset, length - 1); + return offset + length; + } + + /// + /// Compute the checksum for a tar entry header. + /// The checksum field must be all spaces prior to this happening + /// + /// The tar entry's header buffer. + /// The computed checksum. + static int ComputeCheckSum(byte[] buffer) + { + int sum = 0; + for (int i = 0; i < buffer.Length; ++i) { + sum += buffer[i]; + } + return sum; + } + + /// + /// Make a checksum for a tar entry ignoring the checksum contents. + /// + /// The tar entry's header buffer. + /// The checksum for the buffer + static int MakeCheckSum(byte[] buffer) + { + int sum = 0; + for ( int i = 0; i < CHKSUMOFS; ++i ) + { + sum += buffer[i]; + } + + for ( int i = 0; i < TarHeader.CHKSUMLEN; ++i) + { + sum += (byte)' '; + } + + for (int i = CHKSUMOFS + CHKSUMLEN; i < buffer.Length; ++i) + { + sum += buffer[i]; + } + return sum; + } + + static int GetCTime(System.DateTime dateTime) + { + return unchecked((int)((dateTime.Ticks - dateTime1970.Ticks) / timeConversionFactor)); + } + + static DateTime GetDateTimeFromCTime(long ticks) + { + DateTime result; + + try { + result = new DateTime(dateTime1970.Ticks + ticks * timeConversionFactor); + } + catch(ArgumentOutOfRangeException) { + result = dateTime1970; + } + return result; + } + + #region Instance Fields + string name; + int mode; + int userId; + int groupId; + long size; + DateTime modTime; + int checksum; + bool isChecksumValid; + byte typeFlag; + string linkName; + string magic; + string version; + string userName; + string groupName; + int devMajor; + int devMinor; + #endregion + + #region Class Fields + // Values used during recursive operations. + static internal int userIdAsSet; + static internal int groupIdAsSet; + static internal string userNameAsSet; + static internal string groupNameAsSet = "None"; + + static internal int defaultUserId; + static internal int defaultGroupId; + static internal string defaultGroupName = "None"; + static internal string defaultUser; + #endregion + } +} + +/* The original Java file had this header: + * +** Authored by Timothy Gerard Endres +** +** +** This work has been placed into the public domain. +** You may use this work in any way and for any purpose you wish. +** +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR +** REDISTRIBUTION OF THIS SOFTWARE. +** +*/ diff --git a/类库/Update/ZIP/Tar/TarInputStream.cs b/类库/Update/ZIP/Tar/TarInputStream.cs new file mode 100644 index 0000000..436b002 --- /dev/null +++ b/类库/Update/ZIP/Tar/TarInputStream.cs @@ -0,0 +1,695 @@ +// TarInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarInputStream reads a UNIX tar archive as an InputStream. + /// methods are provided to position at each successive entry in + /// the archive, and the read each entry as a normal input stream + /// using read(). + /// + public class TarInputStream : Stream + { + #region Constructors + /// + /// Construct a TarInputStream with default block factor + /// + /// stream to source data from + public TarInputStream(Stream inputStream) + : this(inputStream, TarBuffer.DefaultBlockFactor) + { + } + + /// + /// Construct a TarInputStream with user specified block factor + /// + /// stream to source data from + /// block factor to apply to archive + public TarInputStream(Stream inputStream, int blockFactor) + { + this.inputStream = inputStream; + tarBuffer = TarBuffer.CreateInputTarBuffer(inputStream, blockFactor); + } + + #endregion + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return tarBuffer.IsStreamOwner; } + set { tarBuffer.IsStreamOwner = value; } + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return inputStream.CanRead; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking + /// This property always returns false. + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value indicating if the stream supports writing. + /// This property always returns false. + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// The length in bytes of the stream + /// + public override long Length { + get { + return inputStream.Length; + } + } + + /// + /// Gets or sets the position within the stream. + /// Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException + /// + /// Any attempt to set position + public override long Position { + get { + return inputStream.Position; + } + set { + throw new NotSupportedException("TarInputStream Seek not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + inputStream.Flush(); + } + + /// + /// Set the streams position. This operation is not supported and will throw a NotSupportedException + /// + /// The offset relative to the origin to seek to. + /// The to start seeking from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("TarInputStream Seek not supported"); + } + + /// + /// Sets the length of the stream + /// This operation is not supported and will throw a NotSupportedException + /// + /// The new stream length. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("TarInputStream SetLength not supported"); + } + + /// + /// Writes a block of bytes to this stream using data from a buffer. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The buffer containing bytes to write. + /// The offset in the buffer of the frist byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("TarInputStream Write not supported"); + } + + /// + /// Writes a byte to the current position in the file stream. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The byte value to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("TarInputStream WriteByte not supported"); + } + /// + /// Reads a byte from the current tar archive entry. + /// + /// A byte cast to an int; -1 if the at the end of the stream. + public override int ReadByte() + { + byte[] oneByteBuffer = new byte[1]; + int num = Read(oneByteBuffer, 0, 1); + if (num <= 0) + { + // return -1 to indicate that no byte was read. + return -1; + } + return oneByteBuffer[0]; + } + + /// + /// Reads bytes from the current tar archive entry. + /// + /// This method is aware of the boundaries of the current + /// entry in the archive and will deal with them appropriately + /// + /// + /// The buffer into which to place bytes read. + /// + /// + /// The offset at which to place bytes read. + /// + /// + /// The number of bytes to read. + /// + /// + /// The number of bytes read, or 0 at end of stream/EOF. + /// + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + int totalRead = 0; + + if (entryOffset >= entrySize) + { + return 0; + } + + long numToRead = count; + + if ((numToRead + entryOffset) > entrySize) + { + numToRead = entrySize - entryOffset; + } + + if (readBuffer != null) + { + int sz = (numToRead > readBuffer.Length) ? readBuffer.Length : (int)numToRead; + + Array.Copy(readBuffer, 0, buffer, offset, sz); + + if (sz >= readBuffer.Length) + { + readBuffer = null; + } + else + { + int newLen = readBuffer.Length - sz; + byte[] newBuf = new byte[newLen]; + Array.Copy(readBuffer, sz, newBuf, 0, newLen); + readBuffer = newBuf; + } + + totalRead += sz; + numToRead -= sz; + offset += sz; + } + + while (numToRead > 0) + { + byte[] rec = tarBuffer.ReadBlock(); + if (rec == null) + { + // Unexpected EOF! + throw new TarException("unexpected EOF with " + numToRead + " bytes unread"); + } + + int sz = (int)numToRead; + int recLen = rec.Length; + + if (recLen > sz) + { + Array.Copy(rec, 0, buffer, offset, sz); + readBuffer = new byte[recLen - sz]; + Array.Copy(rec, sz, readBuffer, 0, recLen - sz); + } + else + { + sz = recLen; + Array.Copy(rec, 0, buffer, offset, recLen); + } + + totalRead += sz; + numToRead -= sz; + offset += sz; + } + + entryOffset += totalRead; + + return totalRead; + } + + /// + /// Closes this stream. Calls the TarBuffer's close() method. + /// The underlying stream is closed by the TarBuffer. + /// + public override void Close() + { + tarBuffer.Close(); + } + + #endregion + + /// + /// Set the entry factory for this instance. + /// + /// The factory for creating new entries + public void SetEntryFactory(IEntryFactory factory) + { + entryFactory = factory; + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + public int RecordSize + { + get { return tarBuffer.RecordSize; } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + /// + /// TarBuffer record size. + /// + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return tarBuffer.RecordSize; + } + + /// + /// Get the available data that can be read from the current + /// entry in the archive. This does not indicate how much data + /// is left in the entire archive, only in the current entry. + /// This value is determined from the entry's size header field + /// and the amount of data already read from the current entry. + /// + /// + /// The number of available bytes for the current entry. + /// + public long Available { + get { + return entrySize - entryOffset; + } + } + + /// + /// Skip bytes in the input buffer. This skips bytes in the + /// current entry's data, not the entire archive, and will + /// stop at the end of the current entry's data if the number + /// to skip extends beyond that point. + /// + /// + /// The number of bytes to skip. + /// + public void Skip(long skipCount) + { + // TODO: REVIEW efficiency of TarInputStream.Skip + // This is horribly inefficient, but it ensures that we + // properly skip over bytes via the TarBuffer... + // + byte[] skipBuf = new byte[8 * 1024]; + + for (long num = skipCount; num > 0;) { + int toRead = num > skipBuf.Length ? skipBuf.Length : (int)num; + int numRead = Read(skipBuf, 0, toRead); + + if (numRead == -1) { + break; + } + + num -= numRead; + } + } + + /// + /// Return a value of true if marking is supported; false otherwise. + /// + /// Currently marking is not supported, the return value is always false. + public bool IsMarkSupported { + get { + return false; + } + } + + /// + /// Since we do not support marking just yet, we do nothing. + /// + /// + /// The limit to mark. + /// + public void Mark(int markLimit) + { + } + + /// + /// Since we do not support marking just yet, we do nothing. + /// + public void Reset() + { + } + + /// + /// Get the next entry in this tar archive. This will skip + /// over any remaining data in the current entry, if there + /// is one, and place the input stream at the header of the + /// next entry, and read the header and instantiate a new + /// TarEntry from the header bytes and return that entry. + /// If there are no more entries in the archive, null will + /// be returned to indicate that the end of the archive has + /// been reached. + /// + /// + /// The next TarEntry in the archive, or null. + /// + public TarEntry GetNextEntry() + { + if (hasHitEOF) { + return null; + } + + if (currentEntry != null) { + SkipToNextEntry(); + } + + byte[] headerBuf = tarBuffer.ReadBlock(); + + if (headerBuf == null) { + hasHitEOF = true; + } else if (TarBuffer.IsEndOfArchiveBlock(headerBuf)) { + hasHitEOF = true; + } + + if (hasHitEOF) { + currentEntry = null; + } else { + try { + TarHeader header = new TarHeader(); + header.ParseBuffer(headerBuf); + if ( !header.IsChecksumValid ) + { + throw new TarException("Header checksum is invalid"); + } + this.entryOffset = 0; + this.entrySize = header.Size; + + StringBuilder longName = null; + + if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME) { + + byte[] nameBuffer = new byte[TarBuffer.BlockSize]; + long numToRead = this.entrySize; + + longName = new StringBuilder(); + + while (numToRead > 0) { + int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead)); + + if (numRead == -1) { + throw new InvalidHeaderException("Failed to read long name entry"); + } + + longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString()); + numToRead -= numRead; + } + + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_GHDR) { // POSIX global extended header + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_XHDR) { // POSIX extended header + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR) { + // TODO: could show volume name when verbose + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag != TarHeader.LF_NORMAL && + header.TypeFlag != TarHeader.LF_OLDNORM && + header.TypeFlag != TarHeader.LF_DIR) { + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = tarBuffer.ReadBlock(); + } + + if (entryFactory == null) { + currentEntry = new TarEntry(headerBuf); + if (longName != null) { + currentEntry.Name = longName.ToString(); + } + } else { + currentEntry = entryFactory.CreateEntry(headerBuf); + } + + // Magic was checked here for 'ustar' but there are multiple valid possibilities + // so this is not done anymore. + + entryOffset = 0; + + // TODO: Review How do we resolve this discrepancy?! + entrySize = this.currentEntry.Size; + } catch (InvalidHeaderException ex) { + entrySize = 0; + entryOffset = 0; + currentEntry = null; + string errorText = string.Format("Bad header in record {0} block {1} {2}", + tarBuffer.CurrentRecord, tarBuffer.CurrentBlock, ex.Message); + throw new InvalidHeaderException(errorText); + } + } + return currentEntry; + } + + /// + /// Copies the contents of the current tar archive entry directly into + /// an output stream. + /// + /// + /// The OutputStream into which to write the entry's data. + /// + public void CopyEntryContents(Stream outputStream) + { + byte[] tempBuffer = new byte[32 * 1024]; + + while (true) { + int numRead = Read(tempBuffer, 0, tempBuffer.Length); + if (numRead <= 0) { + break; + } + outputStream.Write(tempBuffer, 0, numRead); + } + } + + void SkipToNextEntry() + { + long numToSkip = entrySize - entryOffset; + + if (numToSkip > 0) + { + Skip(numToSkip); + } + + readBuffer = null; + } + + /// + /// This interface is provided, along with the method , to allow + /// the programmer to have their own subclass instantiated for the + /// entries return from . + /// + public interface IEntryFactory + { + /// + /// Create an entry based on name alone + /// + /// + /// Name of the new EntryPointNotFoundException to create + /// + /// created TarEntry or descendant class + TarEntry CreateEntry(string name); + + /// + /// Create an instance based on an actual file + /// + /// + /// Name of file to represent in the entry + /// + /// + /// Created TarEntry or descendant class + /// + TarEntry CreateEntryFromFile(string fileName); + + /// + /// Create a tar entry based on the header information passed + /// + /// + /// Buffer containing header information to create an an entry from. + /// + /// + /// Created TarEntry or descendant class + /// + TarEntry CreateEntry(byte[] headerBuffer); + } + + /// + /// Standard entry factory class creating instances of the class TarEntry + /// + public class EntryFactoryAdapter : IEntryFactory + { + /// + /// Create a based on named + /// + /// The name to use for the entry + /// A new + public TarEntry CreateEntry(string name) + { + return TarEntry.CreateTarEntry(name); + } + + /// + /// Create a tar entry with details obtained from file + /// + /// The name of the file to retrieve details from. + /// A new + public TarEntry CreateEntryFromFile(string fileName) + { + return TarEntry.CreateEntryFromFile(fileName); + } + + /// + /// Create an entry based on details in header + /// + /// The buffer containing entry details. + /// A new + public TarEntry CreateEntry(byte[] headerBuffer) + { + return new TarEntry(headerBuffer); + } + } + + #region Instance Fields + /// + /// Flag set when last block has been read + /// + protected bool hasHitEOF; + + /// + /// Size of this entry as recorded in header + /// + protected long entrySize; + + /// + /// Number of bytes read for this entry so far + /// + protected long entryOffset; + + /// + /// Buffer used with calls to Read() + /// + protected byte[] readBuffer; + + /// + /// Working buffer + /// + protected TarBuffer tarBuffer; + + /// + /// Current entry being read + /// + TarEntry currentEntry; + + /// + /// Factory used to create TarEntry or descendant class instance + /// + protected IEntryFactory entryFactory; + + /// + /// Stream used as the source of input data. + /// + readonly Stream inputStream; + #endregion + } +} + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ + diff --git a/类库/Update/ZIP/Tar/TarOutputStream.cs b/类库/Update/ZIP/Tar/TarOutputStream.cs new file mode 100644 index 0000000..fcac26f --- /dev/null +++ b/类库/Update/ZIP/Tar/TarOutputStream.cs @@ -0,0 +1,525 @@ +// TarOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarOutputStream writes a UNIX tar archive as an OutputStream. + /// Methods are provided to put entries, and then write their contents + /// by writing to this stream using write(). + /// + /// public + public class TarOutputStream : Stream + { + #region Constructors + /// + /// Construct TarOutputStream using default block factor + /// + /// stream to write to + public TarOutputStream(Stream outputStream) + : this(outputStream, TarBuffer.DefaultBlockFactor) + { + } + + /// + /// Construct TarOutputStream with user specified block factor + /// + /// stream to write to + /// blocking factor + public TarOutputStream(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + this.outputStream = outputStream; + buffer = TarBuffer.CreateOutputTarBuffer(outputStream, blockFactor); + + assemblyBuffer = new byte[TarBuffer.BlockSize]; + blockBuffer = new byte[TarBuffer.BlockSize]; + } + #endregion + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return buffer.IsStreamOwner; } + set { buffer.IsStreamOwner = value; } + } + + /// + /// true if the stream supports reading; otherwise, false. + /// + public override bool CanRead + { + get + { + return outputStream.CanRead; + } + } + + /// + /// true if the stream supports seeking; otherwise, false. + /// + public override bool CanSeek + { + get + { + return outputStream.CanSeek; + } + } + + /// + /// true if stream supports writing; otherwise, false. + /// + public override bool CanWrite + { + get + { + return outputStream.CanWrite; + } + } + + /// + /// length of stream in bytes + /// + public override long Length + { + get + { + return outputStream.Length; + } + } + + /// + /// gets or sets the position within the current stream. + /// + public override long Position + { + get + { + return outputStream.Position; + } + set + { + outputStream.Position = value; + } + } + + /// + /// set the position within the current stream + /// + /// The offset relative to the to seek to + /// The to seek from. + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + return outputStream.Seek(offset, origin); + } + + /// + /// Set the length of the current stream + /// + /// The new stream length. + public override void SetLength(long value) + { + outputStream.SetLength(value); + } + + /// + /// Read a byte from the stream and advance the position within the stream + /// by one byte or returns -1 if at the end of the stream. + /// + /// The byte value or -1 if at end of stream + public override int ReadByte() + { + return outputStream.ReadByte(); + } + + /// + /// read bytes from the current stream and advance the position within the + /// stream by the number of bytes read. + /// + /// The buffer to store read bytes in. + /// The index into the buffer to being storing bytes at. + /// The desired number of bytes to read. + /// The total number of bytes read, or zero if at the end of the stream. + /// The number of bytes may be less than the count + /// requested if data is not avialable. + public override int Read(byte[] buffer, int offset, int count) + { + return outputStream.Read(buffer, offset, count); + } + + /// + /// All buffered data is written to destination + /// + public override void Flush() + { + outputStream.Flush(); + } + + /// + /// Ends the TAR archive without closing the underlying OutputStream. + /// The result is that the EOF block of nulls is written. + /// + public void Finish() + { + if ( IsEntryOpen ) + { + CloseEntry(); + } + WriteEofBlock(); + } + + /// + /// Ends the TAR archive and closes the underlying OutputStream. + /// + /// This means that Finish() is called followed by calling the + /// TarBuffer's Close(). + public override void Close() + { + if ( !isClosed ) + { + isClosed = true; + Finish(); + buffer.Close(); + } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + public int RecordSize + { + get { return buffer.RecordSize; } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + /// + /// The TarBuffer record size. + /// + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return buffer.RecordSize; + } + + /// + /// Get a value indicating wether an entry is open, requiring more data to be written. + /// + bool IsEntryOpen + { + get { return (currBytes < currSize); } + + } + + /// + /// Put an entry on the output stream. This writes the entry's + /// header and positions the output stream for writing + /// the contents of the entry. Once this method is called, the + /// stream is ready for calls to write() to write the entry's + /// contents. Once the contents are written, closeEntry() + /// MUST be called to ensure that all buffered data + /// is completely written to the output stream. + /// + /// + /// The TarEntry to be written to the archive. + /// + public void PutNextEntry(TarEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if (entry.TarHeader.Name.Length >= TarHeader.NAMELEN) { + TarHeader longHeader = new TarHeader(); + longHeader.TypeFlag = TarHeader.LF_GNU_LONGNAME; + longHeader.Name = longHeader.Name + "././@LongLink"; + longHeader.UserId = 0; + longHeader.GroupId = 0; + longHeader.GroupName = ""; + longHeader.UserName = ""; + longHeader.LinkName = ""; + longHeader.Size = entry.TarHeader.Name.Length; + + longHeader.WriteHeader(blockBuffer); + buffer.WriteBlock(blockBuffer); // Add special long filename header block + + int nameCharIndex = 0; + + while (nameCharIndex < entry.TarHeader.Name.Length) { + Array.Clear(blockBuffer, 0, blockBuffer.Length); + TarHeader.GetAsciiBytes(entry.TarHeader.Name, nameCharIndex, this.blockBuffer, 0, TarBuffer.BlockSize); + nameCharIndex += TarBuffer.BlockSize; + buffer.WriteBlock(blockBuffer); + } + } + + entry.WriteEntryHeader(blockBuffer); + buffer.WriteBlock(blockBuffer); + + currBytes = 0; + + currSize = entry.IsDirectory ? 0 : entry.Size; + } + + /// + /// Close an entry. This method MUST be called for all file + /// entries that contain data. The reason is that we must + /// buffer data written to the stream in order to satisfy + /// the buffer's block based writes. Thus, there may be + /// data fragments still being assembled that must be written + /// to the output stream before this entry is closed and the + /// next entry written. + /// + public void CloseEntry() + { + if (assemblyBufferLength > 0) { + Array.Clear(assemblyBuffer, assemblyBufferLength, assemblyBuffer.Length - assemblyBufferLength); + + buffer.WriteBlock(assemblyBuffer); + + currBytes += assemblyBufferLength; + assemblyBufferLength = 0; + } + + if (currBytes < currSize) { + string errorText = string.Format( + "Entry closed at '{0}' before the '{1}' bytes specified in the header were written", + currBytes, currSize); + throw new TarException(errorText); + } + } + + /// + /// Writes a byte to the current tar archive entry. + /// This method simply calls Write(byte[], int, int). + /// + /// + /// The byte to be written. + /// + public override void WriteByte(byte value) + { + Write(new byte[] { value }, 0, 1); + } + + /// + /// Writes bytes to the current tar archive entry. This method + /// is aware of the current entry and will throw an exception if + /// you attempt to write bytes past the length specified for the + /// current entry. The method is also (painfully) aware of the + /// record buffering required by TarBuffer, and manages buffers + /// that are not a multiple of recordsize in length, including + /// assembling records from small buffers. + /// + /// + /// The buffer to write to the archive. + /// + /// + /// The offset in the buffer from which to get bytes. + /// + /// + /// The number of bytes to write. + /// + public override void Write(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( buffer.Length - offset < count ) + { + throw new ArgumentException("offset and count combination is invalid"); + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (currBytes + count) > currSize ) { + string errorText = string.Format("request to write '{0}' bytes exceeds size in header of '{1}' bytes", + count, this.currSize); +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", errorText); +#endif + } + + // + // We have to deal with assembly!!! + // The programmer can be writing little 32 byte chunks for all + // we know, and we must assemble complete blocks for writing. + // TODO REVIEW Maybe this should be in TarBuffer? Could that help to + // eliminate some of the buffer copying. + // + if (assemblyBufferLength > 0) { + if ((assemblyBufferLength + count ) >= blockBuffer.Length) { + int aLen = blockBuffer.Length - assemblyBufferLength; + + Array.Copy(assemblyBuffer, 0, blockBuffer, 0, assemblyBufferLength); + Array.Copy(buffer, offset, blockBuffer, assemblyBufferLength, aLen); + + this.buffer.WriteBlock(blockBuffer); + + currBytes += blockBuffer.Length; + + offset += aLen; + count -= aLen; + + assemblyBufferLength = 0; + } else { + Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count); + offset += count; + assemblyBufferLength += count; + count -= count; + } + } + + // + // When we get here we have EITHER: + // o An empty "assembly" buffer. + // o No bytes to write (count == 0) + // + while (count > 0) { + if (count < blockBuffer.Length) { + Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count); + assemblyBufferLength += count; + break; + } + + this.buffer.WriteBlock(buffer, offset); + + int bufferLength = blockBuffer.Length; + currBytes += bufferLength; + count -= bufferLength; + offset += bufferLength; + } + } + + /// + /// Write an EOF (end of archive) block to the tar archive. + /// An EOF block consists of all zeros. + /// + void WriteEofBlock() + { + Array.Clear(blockBuffer, 0, blockBuffer.Length); + buffer.WriteBlock(blockBuffer); + } + + #region Instance Fields + /// + /// bytes written for this entry so far + /// + long currBytes; + + /// + /// current 'Assembly' buffer length + /// + int assemblyBufferLength; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + /// + /// Size for the current entry + /// + protected long currSize; + + /// + /// single block working buffer + /// + protected byte[] blockBuffer; + + /// + /// 'Assembly' buffer used to assemble data before writing + /// + protected byte[] assemblyBuffer; + + /// + /// TarBuffer used to provide correct blocking factor + /// + protected TarBuffer buffer; + + /// + /// the destination stream for the archive contents + /// + protected Stream outputStream; + #endregion + } +} + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/Update/ZIP/Zip/Compression/Deflater.cs b/类库/Update/ZIP/Zip/Compression/Deflater.cs new file mode 100644 index 0000000..dadbfb6 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/Deflater.cs @@ -0,0 +1,557 @@ +// Deflater.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This is the Deflater class. The deflater class compresses input + /// with the deflate algorithm described in RFC 1951. It has several + /// compression levels and three different strategies described below. + /// + /// This class is not thread safe. This is inherent in the API, due + /// to the split of deflate and setInput. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class Deflater + { + #region Deflater Documentation + /* + * The Deflater can do the following state transitions: + * + * (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---. + * / | (2) (5) | + * / v (5) | + * (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3) + * \ | (3) | ,--------' + * | | | (3) / + * v v (5) v v + * (1) -> BUSY_STATE ----> FINISHING_STATE + * | (6) + * v + * FINISHED_STATE + * \_____________________________________/ + * | (7) + * v + * CLOSED_STATE + * + * (1) If we should produce a header we start in INIT_STATE, otherwise + * we start in BUSY_STATE. + * (2) A dictionary may be set only when we are in INIT_STATE, then + * we change the state as indicated. + * (3) Whether a dictionary is set or not, on the first call of deflate + * we change to BUSY_STATE. + * (4) -- intentionally left blank -- :) + * (5) FINISHING_STATE is entered, when flush() is called to indicate that + * there is no more INPUT. There are also states indicating, that + * the header wasn't written yet. + * (6) FINISHED_STATE is entered, when everything has been flushed to the + * internal pending output buffer. + * (7) At any time (7) + * + */ + #endregion + #region Public Constants + /// + /// The best and slowest compression level. This tries to find very + /// long and distant string repetitions. + /// + public const int BEST_COMPRESSION = 9; + + /// + /// The worst but fastest compression level. + /// + public const int BEST_SPEED = 1; + + /// + /// The default compression level. + /// + public const int DEFAULT_COMPRESSION = -1; + + /// + /// This level won't compress at all but output uncompressed blocks. + /// + public const int NO_COMPRESSION = 0; + + /// + /// The compression method. This is the only method supported so far. + /// There is no need to use this constant at all. + /// + public const int DEFLATED = 8; + #endregion + #region Local Constants + private const int IS_SETDICT = 0x01; + private const int IS_FLUSHING = 0x04; + private const int IS_FINISHING = 0x08; + + private const int INIT_STATE = 0x00; + private const int SETDICT_STATE = 0x01; + // private static int INIT_FINISHING_STATE = 0x08; + // private static int SETDICT_FINISHING_STATE = 0x09; + private const int BUSY_STATE = 0x10; + private const int FLUSHING_STATE = 0x14; + private const int FINISHING_STATE = 0x1c; + private const int FINISHED_STATE = 0x1e; + private const int CLOSED_STATE = 0x7f; + #endregion + #region Constructors + /// + /// Creates a new deflater with default compression level. + /// + public Deflater() : this(DEFAULT_COMPRESSION, false) + { + + } + + /// + /// Creates a new deflater with given compression level. + /// + /// + /// the compression level, a value between NO_COMPRESSION + /// and BEST_COMPRESSION, or DEFAULT_COMPRESSION. + /// + /// if lvl is out of range. + public Deflater(int level) : this(level, false) + { + + } + + /// + /// Creates a new deflater with given compression level. + /// + /// + /// the compression level, a value between NO_COMPRESSION + /// and BEST_COMPRESSION. + /// + /// + /// true, if we should suppress the Zlib/RFC1950 header at the + /// beginning and the adler checksum at the end of the output. This is + /// useful for the GZIP/PKZIP formats. + /// + /// if lvl is out of range. + public Deflater(int level, bool noZlibHeaderOrFooter) + { + if (level == DEFAULT_COMPRESSION) { + level = 6; + } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) { + throw new ArgumentOutOfRangeException("level"); + } + + pending = new DeflaterPending(); + engine = new DeflaterEngine(pending); + this.noZlibHeaderOrFooter = noZlibHeaderOrFooter; + SetStrategy(DeflateStrategy.Default); + SetLevel(level); + Reset(); + } + #endregion + + /// + /// Resets the deflater. The deflater acts afterwards as if it was + /// just created with the same compression level and strategy as it + /// had before. + /// + public void Reset() + { + state = (noZlibHeaderOrFooter ? BUSY_STATE : INIT_STATE); + totalOut = 0; + pending.Reset(); + engine.Reset(); + } + + /// + /// Gets the current adler checksum of the data that was processed so far. + /// + public int Adler { + get { + return engine.Adler; + } + } + + /// + /// Gets the number of input bytes processed so far. + /// + public long TotalIn { + get { + return engine.TotalIn; + } + } + + /// + /// Gets the number of output bytes so far. + /// + public long TotalOut { + get { + return totalOut; + } + } + + /// + /// Flushes the current input block. Further calls to deflate() will + /// produce enough output to inflate everything in the current input + /// block. This is not part of Sun's JDK so I have made it package + /// private. It is used by DeflaterOutputStream to implement + /// flush(). + /// + public void Flush() + { + state |= IS_FLUSHING; + } + + /// + /// Finishes the deflater with the current input block. It is an error + /// to give more input after this method was called. This method must + /// be called to force all bytes to be flushed. + /// + public void Finish() + { + state |= (IS_FLUSHING | IS_FINISHING); + } + + /// + /// Returns true if the stream was finished and no more output bytes + /// are available. + /// + public bool IsFinished { + get { + return (state == FINISHED_STATE) && pending.IsFlushed; + } + } + + /// + /// Returns true, if the input buffer is empty. + /// You should then call setInput(). + /// NOTE: This method can also return true when the stream + /// was finished. + /// + public bool IsNeedingInput { + get { + return engine.NeedsInput(); + } + } + + /// + /// Sets the data which should be compressed next. This should be only + /// called when needsInput indicates that more input is needed. + /// If you call setInput when needsInput() returns false, the + /// previous input that is still pending will be thrown away. + /// The given byte array should not be changed, before needsInput() returns + /// true again. + /// This call is equivalent to setInput(input, 0, input.length). + /// + /// + /// the buffer containing the input data. + /// + /// + /// if the buffer was finished() or ended(). + /// + public void SetInput(byte[] input) + { + SetInput(input, 0, input.Length); + } + + /// + /// Sets the data which should be compressed next. This should be + /// only called when needsInput indicates that more input is needed. + /// The given byte array should not be changed, before needsInput() returns + /// true again. + /// + /// + /// the buffer containing the input data. + /// + /// + /// the start of the data. + /// + /// + /// the number of data bytes of input. + /// + /// + /// if the buffer was Finish()ed or if previous input is still pending. + /// + public void SetInput(byte[] input, int offset, int count) + { + if ((state & IS_FINISHING) != 0) { + throw new InvalidOperationException("Finish() already called"); + } + engine.SetInput(input, offset, count); + } + + /// + /// Sets the compression level. There is no guarantee of the exact + /// position of the change, but if you call this when needsInput is + /// true the change of compression level will occur somewhere near + /// before the end of the so far given input. + /// + /// + /// the new compression level. + /// + public void SetLevel(int level) + { + if (level == DEFAULT_COMPRESSION) { + level = 6; + } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) { + throw new ArgumentOutOfRangeException("level"); + } + + if (this.level != level) { + this.level = level; + engine.SetLevel(level); + } + } + + /// + /// Get current compression level + /// + /// Returns the current compression level + public int GetLevel() { + return level; + } + + /// + /// Sets the compression strategy. Strategy is one of + /// DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact + /// position where the strategy is changed, the same as for + /// SetLevel() applies. + /// + /// + /// The new compression strategy. + /// + public void SetStrategy(DeflateStrategy strategy) + { + engine.Strategy = strategy; + } + + /// + /// Deflates the current input block with to the given array. + /// + /// + /// The buffer where compressed data is stored + /// + /// + /// The number of compressed bytes added to the output, or 0 if either + /// IsNeedingInput() or IsFinished returns true or length is zero. + /// + public int Deflate(byte[] output) + { + return Deflate(output, 0, output.Length); + } + + /// + /// Deflates the current input block to the given array. + /// + /// + /// Buffer to store the compressed data. + /// + /// + /// Offset into the output array. + /// + /// + /// The maximum number of bytes that may be stored. + /// + /// + /// The number of compressed bytes added to the output, or 0 if either + /// needsInput() or finished() returns true or length is zero. + /// + /// + /// If Finish() was previously called. + /// + /// + /// If offset or length don't match the array length. + /// + public int Deflate(byte[] output, int offset, int length) + { + int origLength = length; + + if (state == CLOSED_STATE) { + throw new InvalidOperationException("Deflater closed"); + } + + if (state < BUSY_STATE) { + // output header + int header = (DEFLATED + + ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8; + int level_flags = (level - 1) >> 1; + if (level_flags < 0 || level_flags > 3) { + level_flags = 3; + } + header |= level_flags << 6; + if ((state & IS_SETDICT) != 0) { + // Dictionary was set + header |= DeflaterConstants.PRESET_DICT; + } + header += 31 - (header % 31); + + pending.WriteShortMSB(header); + if ((state & IS_SETDICT) != 0) { + int chksum = engine.Adler; + engine.ResetAdler(); + pending.WriteShortMSB(chksum >> 16); + pending.WriteShortMSB(chksum & 0xffff); + } + + state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING)); + } + + for (;;) { + int count = pending.Flush(output, offset, length); + offset += count; + totalOut += count; + length -= count; + + if (length == 0 || state == FINISHED_STATE) { + break; + } + + if (!engine.Deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0)) { + if (state == BUSY_STATE) { + // We need more input now + return origLength - length; + } else if (state == FLUSHING_STATE) { + if (level != NO_COMPRESSION) { + /* We have to supply some lookahead. 8 bit lookahead + * is needed by the zlib inflater, and we must fill + * the next byte, so that all bits are flushed. + */ + int neededbits = 8 + ((-pending.BitCount) & 7); + while (neededbits > 0) { + /* write a static tree block consisting solely of + * an EOF: + */ + pending.WriteBits(2, 10); + neededbits -= 10; + } + } + state = BUSY_STATE; + } else if (state == FINISHING_STATE) { + pending.AlignToByte(); + + // Compressed data is complete. Write footer information if required. + if (!noZlibHeaderOrFooter) { + int adler = engine.Adler; + pending.WriteShortMSB(adler >> 16); + pending.WriteShortMSB(adler & 0xffff); + } + state = FINISHED_STATE; + } + } + } + return origLength - length; + } + + /// + /// Sets the dictionary which should be used in the deflate process. + /// This call is equivalent to setDictionary(dict, 0, dict.Length). + /// + /// + /// the dictionary. + /// + /// + /// if SetInput () or Deflate () were already called or another dictionary was already set. + /// + public void SetDictionary(byte[] dictionary) + { + SetDictionary(dictionary, 0, dictionary.Length); + } + + /// + /// Sets the dictionary which should be used in the deflate process. + /// The dictionary is a byte array containing strings that are + /// likely to occur in the data which should be compressed. The + /// dictionary is not stored in the compressed output, only a + /// checksum. To decompress the output you need to supply the same + /// dictionary again. + /// + /// + /// The dictionary data + /// + /// + /// The index where dictionary information commences. + /// + /// + /// The number of bytes in the dictionary. + /// + /// + /// If SetInput () or Deflate() were already called or another dictionary was already set. + /// + public void SetDictionary(byte[] dictionary, int index, int count) + { + if (state != INIT_STATE) { + throw new InvalidOperationException(); + } + + state = SETDICT_STATE; + engine.SetDictionary(dictionary, index, count); + } + + #region Instance Fields + /// + /// Compression level. + /// + int level; + + /// + /// If true no Zlib/RFC1950 headers or footers are generated + /// + bool noZlibHeaderOrFooter; + + /// + /// The current state. + /// + int state; + + /// + /// The total bytes of output written. + /// + long totalOut; + + /// + /// The pending output. + /// + DeflaterPending pending; + + /// + /// The deflater engine. + /// + DeflaterEngine engine; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/Compression/DeflaterConstants.cs b/类库/Update/ZIP/Zip/Compression/DeflaterConstants.cs new file mode 100644 index 0000000..a973db2 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/DeflaterConstants.cs @@ -0,0 +1,186 @@ +// DeflaterConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class contains constants used for deflation. + /// + public class DeflaterConstants + { + /// + /// Set to true to enable debugging + /// + public const bool DEBUGGING = false; + + /// + /// Written to Zip file to identify a stored block + /// + public const int STORED_BLOCK = 0; + + /// + /// Identifies static tree in Zip file + /// + public const int STATIC_TREES = 1; + + /// + /// Identifies dynamic tree in Zip file + /// + public const int DYN_TREES = 2; + + /// + /// Header flag indicating a preset dictionary for deflation + /// + public const int PRESET_DICT = 0x20; + + /// + /// Sets internal buffer sizes for Huffman encoding + /// + public const int DEFAULT_MEM_LEVEL = 8; + + /// + /// Internal compression engine constant + /// + public const int MAX_MATCH = 258; + + /// + /// Internal compression engine constant + /// + public const int MIN_MATCH = 3; + + /// + /// Internal compression engine constant + /// + public const int MAX_WBITS = 15; + + /// + /// Internal compression engine constant + /// + public const int WSIZE = 1 << MAX_WBITS; + + /// + /// Internal compression engine constant + /// + public const int WMASK = WSIZE - 1; + + /// + /// Internal compression engine constant + /// + public const int HASH_BITS = DEFAULT_MEM_LEVEL + 7; + + /// + /// Internal compression engine constant + /// + public const int HASH_SIZE = 1 << HASH_BITS; + + /// + /// Internal compression engine constant + /// + public const int HASH_MASK = HASH_SIZE - 1; + + /// + /// Internal compression engine constant + /// + public const int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH; + + /// + /// Internal compression engine constant + /// + public const int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; + + /// + /// Internal compression engine constant + /// + public const int MAX_DIST = WSIZE - MIN_LOOKAHEAD; + + /// + /// Internal compression engine constant + /// + public const int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8); + + /// + /// Internal compression engine constant + /// + public static int MAX_BLOCK_SIZE = Math.Min(65535, PENDING_BUF_SIZE - 5); + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_STORED = 0; + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_FAST = 1; + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_SLOW = 2; + + /// + /// Internal compression engine constant + /// + public static int[] GOOD_LENGTH = { 0, 4, 4, 4, 4, 8, 8, 8, 32, 32 }; + + /// + /// Internal compression engine constant + /// + public static int[] MAX_LAZY = { 0, 4, 5, 6, 4, 16, 16, 32, 128, 258 }; + + /// + /// Internal compression engine constant + /// + public static int[] NICE_LENGTH = { 0, 8, 16, 32, 16, 32, 128, 128, 258, 258 }; + + /// + /// Internal compression engine constant + /// + public static int[] MAX_CHAIN = { 0, 4, 8, 32, 16, 32, 128, 256, 1024, 4096 }; + + /// + /// Internal compression engine constant + /// + public static int[] COMPR_FUNC = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + + } +} diff --git a/类库/Update/ZIP/Zip/Compression/DeflaterEngine.cs b/类库/Update/ZIP/Zip/Compression/DeflaterEngine.cs new file mode 100644 index 0000000..3cbb5aa --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/DeflaterEngine.cs @@ -0,0 +1,869 @@ +// DeflaterEngine.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// Strategies for deflater + /// + public enum DeflateStrategy + { + /// + /// The default strategy + /// + Default = 0, + + /// + /// This strategy will only allow longer string repetitions. It is + /// useful for random data with a small character set. + /// + Filtered = 1, + + + /// + /// This strategy will not look for string repetitions at all. It + /// only encodes with Huffman trees (which means, that more common + /// characters get a smaller encoding. + /// + HuffmanOnly = 2 + } + + // DEFLATE ALGORITHM: + // + // The uncompressed stream is inserted into the window array. When + // the window array is full the first half is thrown away and the + // second half is copied to the beginning. + // + // The head array is a hash table. Three characters build a hash value + // and they the value points to the corresponding index in window of + // the last string with this hash. The prev array implements a + // linked list of matches with the same hash: prev[index & WMASK] points + // to the previous index with the same hash. + // + + + /// + /// Low level compression engine for deflate algorithm which uses a 32K sliding window + /// with secondary compression from Huffman/Shannon-Fano codes. + /// + public class DeflaterEngine : DeflaterConstants + { + #region Constants + const int TooFar = 4096; + #endregion + + #region Constructors + /// + /// Construct instance with pending buffer + /// + /// + /// Pending buffer to use + /// > + public DeflaterEngine(DeflaterPending pending) + { + this.pending = pending; + huffman = new DeflaterHuffman(pending); + adler = new Adler32(); + + window = new byte[2 * WSIZE]; + head = new short[HASH_SIZE]; + prev = new short[WSIZE]; + + // We start at index 1, to avoid an implementation deficiency, that + // we cannot build a repeat pattern at index 0. + blockStart = strstart = 1; + } + + #endregion + + /// + /// Deflate drives actual compression of data + /// + /// True to flush input buffers + /// Finish deflation with the current input. + /// Returns true if progress has been made. + public bool Deflate(bool flush, bool finish) + { + bool progress; + do + { + FillWindow(); + bool canFlush = flush && (inputOff == inputEnd); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.WriteLine("window: [" + blockStart + "," + strstart + "," + + lookahead + "], " + compressionFunction + "," + canFlush); + } +#endif + switch (compressionFunction) + { + case DEFLATE_STORED: + progress = DeflateStored(canFlush, finish); + break; + case DEFLATE_FAST: + progress = DeflateFast(canFlush, finish); + break; + case DEFLATE_SLOW: + progress = DeflateSlow(canFlush, finish); + break; + default: + throw new InvalidOperationException("unknown compressionFunction"); + } + } while (pending.IsFlushed && progress); // repeat while we have no pending output and progress was made + return progress; + } + + /// + /// Sets input data to be deflated. Should only be called when NeedsInput() + /// returns true + /// + /// The buffer containing input data. + /// The offset of the first byte of data. + /// The number of bytes of data to use as input. + public void SetInput(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( count < 0 ) + { + throw new ArgumentOutOfRangeException("count"); + } + + if (inputOff < inputEnd) + { + throw new InvalidOperationException("Old input was not completely processed"); + } + + int end = offset + count; + + /* We want to throw an ArrayIndexOutOfBoundsException early. The + * check is very tricky: it also handles integer wrap around. + */ + if ((offset > end) || (end > buffer.Length) ) + { + throw new ArgumentOutOfRangeException("count"); + } + + inputBuf = buffer; + inputOff = offset; + inputEnd = end; + } + + /// + /// Determines if more input is needed. + /// + /// Return true if input is needed via SetInput + public bool NeedsInput() + { + return (inputEnd == inputOff); + } + + /// + /// Set compression dictionary + /// + /// The buffer containing the dictionary data + /// The offset in the buffer for the first byte of data + /// The length of the dictionary data. + public void SetDictionary(byte[] buffer, int offset, int length) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (strstart != 1) ) + { + throw new InvalidOperationException("strstart not 1"); + } +#endif + adler.Update(buffer, offset, length); + if (length < MIN_MATCH) + { + return; + } + + if (length > MAX_DIST) + { + offset += length - MAX_DIST; + length = MAX_DIST; + } + + System.Array.Copy(buffer, offset, window, strstart, length); + + UpdateHash(); + --length; + while (--length > 0) + { + InsertString(); + strstart++; + } + strstart += 2; + blockStart = strstart; + } + + /// + /// Reset internal state + /// + public void Reset() + { + huffman.Reset(); + adler.Reset(); + blockStart = strstart = 1; + lookahead = 0; + totalIn = 0; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + + for (int i = 0; i < HASH_SIZE; i++) { + head[i] = 0; + } + + for (int i = 0; i < WSIZE; i++) { + prev[i] = 0; + } + } + + /// + /// Reset Adler checksum + /// + public void ResetAdler() + { + adler.Reset(); + } + + /// + /// Get current value of Adler checksum + /// + public int Adler { + get { + return unchecked((int)adler.Value); + } + } + + /// + /// Total data processed + /// + public long TotalIn { + get { + return totalIn; + } + } + + /// + /// Get/set the deflate strategy + /// + public DeflateStrategy Strategy { + get { + return strategy; + } + set { + strategy = value; + } + } + + /// + /// Set the deflate level (0-9) + /// + /// The value to set the level to. + public void SetLevel(int level) + { + if ( (level < 0) || (level > 9) ) + { + throw new ArgumentOutOfRangeException("level"); + } + + goodLength = DeflaterConstants.GOOD_LENGTH[level]; + max_lazy = DeflaterConstants.MAX_LAZY[level]; + niceLength = DeflaterConstants.NICE_LENGTH[level]; + max_chain = DeflaterConstants.MAX_CHAIN[level]; + + if (DeflaterConstants.COMPR_FUNC[level] != compressionFunction) { + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.WriteLine("Change from " + compressionFunction + " to " + + DeflaterConstants.COMPR_FUNC[level]); + } +#endif + switch (compressionFunction) { + case DEFLATE_STORED: + if (strstart > blockStart) { + huffman.FlushStoredBlock(window, blockStart, + strstart - blockStart, false); + blockStart = strstart; + } + UpdateHash(); + break; + + case DEFLATE_FAST: + if (strstart > blockStart) { + huffman.FlushBlock(window, blockStart, strstart - blockStart, + false); + blockStart = strstart; + } + break; + + case DEFLATE_SLOW: + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + if (strstart > blockStart) { + huffman.FlushBlock(window, blockStart, strstart - blockStart, false); + blockStart = strstart; + } + prevAvailable = false; + matchLen = MIN_MATCH - 1; + break; + } + compressionFunction = COMPR_FUNC[level]; + } + } + + /// + /// Fill the window + /// + public void FillWindow() + { + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (strstart >= WSIZE + MAX_DIST) + { + SlideWindow(); + } + + /* If there is not enough lookahead, but still some input left, + * read in the input + */ + while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd) + { + int more = 2 * WSIZE - lookahead - strstart; + + if (more > inputEnd - inputOff) + { + more = inputEnd - inputOff; + } + + System.Array.Copy(inputBuf, inputOff, window, strstart + lookahead, more); + adler.Update(inputBuf, inputOff, more); + + inputOff += more; + totalIn += more; + lookahead += more; + } + + if (lookahead >= MIN_MATCH) + { + UpdateHash(); + } + } + + void UpdateHash() + { +/* + if (DEBUGGING) { + Console.WriteLine("updateHash: "+strstart); + } +*/ + ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1]; + } + + /// + /// Inserts the current string in the head hash and returns the previous + /// value for this hash. + /// + /// The previous hash value + int InsertString() + { + short match; + int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)]) & HASH_MASK; + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^ + (window[strstart + 1] << HASH_SHIFT) ^ + (window[strstart + 2])) & HASH_MASK)) { + throw new SharpZipBaseException("hash inconsistent: " + hash + "/" + +window[strstart] + "," + +window[strstart + 1] + "," + +window[strstart + 2] + "," + HASH_SHIFT); + } + } +#endif + prev[strstart & WMASK] = match = head[hash]; + head[hash] = unchecked((short)strstart); + ins_h = hash; + return match & 0xffff; + } + + void SlideWindow() + { + Array.Copy(window, WSIZE, window, 0, WSIZE); + matchStart -= WSIZE; + strstart -= WSIZE; + blockStart -= WSIZE; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). + for (int i = 0; i < HASH_SIZE; ++i) { + int m = head[i] & 0xffff; + head[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0); + } + + // Slide the prev table. + for (int i = 0; i < WSIZE; i++) { + int m = prev[i] & 0xffff; + prev[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0); + } + } + + /// + /// Find the best (longest) string in the window matching the + /// string starting at strstart. + /// + /// Preconditions: + /// + /// strstart + MAX_MATCH <= window.length. + /// + /// + /// True if a match greater than the minimum length is found + bool FindLongestMatch(int curMatch) + { + int chainLength = this.max_chain; + int niceLength = this.niceLength; + short[] prev = this.prev; + int scan = this.strstart; + int match; + int best_end = this.strstart + matchLen; + int best_len = Math.Max(matchLen, MIN_MATCH - 1); + + int limit = Math.Max(strstart - MAX_DIST, 0); + + int strend = strstart + MAX_MATCH - 1; + byte scan_end1 = window[best_end - 1]; + byte scan_end = window[best_end]; + + // Do not waste too much time if we already have a good match: + if (best_len >= this.goodLength) { + chainLength >>= 2; + } + + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (niceLength > lookahead) { + niceLength = lookahead; + } + +#if DebugDeflation + + if (DeflaterConstants.DEBUGGING && (strstart > 2 * WSIZE - MIN_LOOKAHEAD)) + { + throw new InvalidOperationException("need lookahead"); + } +#endif + + do { + +#if DebugDeflation + + if (DeflaterConstants.DEBUGGING && (curMatch >= strstart) ) + { + throw new InvalidOperationException("no future"); + } +#endif + if (window[curMatch + best_len] != scan_end || + window[curMatch + best_len - 1] != scan_end1 || + window[curMatch] != window[scan] || + window[curMatch + 1] != window[scan + 1]) { + continue; + } + + match = curMatch + 2; + scan += 2; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart + 258. + */ + while ( + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + (scan < strend)) + { + // Do nothing + } + + if (scan > best_end) { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (ins_h == 0) ) + Console.Error.WriteLine("Found match: " + curMatch + "-" + (scan - strstart)); +#endif + matchStart = curMatch; + best_end = scan; + best_len = scan - strstart; + + if (best_len >= niceLength) { + break; + } + + scan_end1 = window[best_end - 1]; + scan_end = window[best_end]; + } + scan = strstart; + } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit && --chainLength != 0); + + matchLen = Math.Min(best_len, lookahead); + return matchLen >= MIN_MATCH; + } + + bool DeflateStored(bool flush, bool finish) + { + if (!flush && (lookahead == 0)) { + return false; + } + + strstart += lookahead; + lookahead = 0; + + int storedLength = strstart - blockStart; + + if ((storedLength >= DeflaterConstants.MAX_BLOCK_SIZE) || // Block is full + (blockStart < WSIZE && storedLength >= MAX_DIST) || // Block may move out of window + flush) { + bool lastBlock = finish; + if (storedLength > DeflaterConstants.MAX_BLOCK_SIZE) { + storedLength = DeflaterConstants.MAX_BLOCK_SIZE; + lastBlock = false; + } + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + Console.WriteLine("storedBlock[" + storedLength + "," + lastBlock + "]"); + } +#endif + + huffman.FlushStoredBlock(window, blockStart, storedLength, lastBlock); + blockStart += storedLength; + return !lastBlock; + } + return true; + } + + bool DeflateFast(bool flush, bool finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) { + return false; + } + + while (lookahead >= MIN_LOOKAHEAD || flush) { + if (lookahead == 0) { + // We are flushing everything + huffman.FlushBlock(window, blockStart, strstart - blockStart, finish); + blockStart = strstart; + return false; + } + + if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) { + /* slide window, as FindLongestMatch needs this. + * This should only happen when flushing and the window + * is almost full. + */ + SlideWindow(); + } + + int hashHead; + if (lookahead >= MIN_MATCH && + (hashHead = InsertString()) != 0 && + strategy != DeflateStrategy.HuffmanOnly && + strstart - hashHead <= MAX_DIST && + FindLongestMatch(hashHead)) { + // longestMatch sets matchStart and matchLen +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) { + if (window[strstart + i] != window[matchStart + i]) { + throw new SharpZipBaseException("Match failure"); + } + } + } +#endif + + bool full = huffman.TallyDist(strstart - matchStart, matchLen); + + lookahead -= matchLen; + if (matchLen <= max_lazy && lookahead >= MIN_MATCH) { + while (--matchLen > 0) { + ++strstart; + InsertString(); + } + ++strstart; + } else { + strstart += matchLen; + if (lookahead >= MIN_MATCH - 1) { + UpdateHash(); + } + } + matchLen = MIN_MATCH - 1; + if (!full) { + continue; + } + } else { + // No match found + huffman.TallyLit(window[strstart] & 0xff); + ++strstart; + --lookahead; + } + + if (huffman.IsFull()) { + bool lastBlock = finish && (lookahead == 0); + huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock); + blockStart = strstart; + return !lastBlock; + } + } + return true; + } + + bool DeflateSlow(bool flush, bool finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) { + return false; + } + + while (lookahead >= MIN_LOOKAHEAD || flush) { + if (lookahead == 0) { + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + prevAvailable = false; + + // We are flushing everything +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && !flush) + { + throw new SharpZipBaseException("Not flushing, but no lookahead"); + } +#endif + huffman.FlushBlock(window, blockStart, strstart - blockStart, + finish); + blockStart = strstart; + return false; + } + + if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) { + /* slide window, as FindLongestMatch needs this. + * This should only happen when flushing and the window + * is almost full. + */ + SlideWindow(); + } + + int prevMatch = matchStart; + int prevLen = matchLen; + if (lookahead >= MIN_MATCH) { + + int hashHead = InsertString(); + + if (strategy != DeflateStrategy.HuffmanOnly && + hashHead != 0 && + strstart - hashHead <= MAX_DIST && + FindLongestMatch(hashHead)) { + + // longestMatch sets matchStart and matchLen + + // Discard match if too small and too far away + if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TooFar))) { + matchLen = MIN_MATCH - 1; + } + } + } + + // previous match was better + if ((prevLen >= MIN_MATCH) && (matchLen <= prevLen) ) { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) { + if (window[strstart-1+i] != window[prevMatch + i]) + throw new SharpZipBaseException(); + } + } +#endif + huffman.TallyDist(strstart - 1 - prevMatch, prevLen); + prevLen -= 2; + do { + strstart++; + lookahead--; + if (lookahead >= MIN_MATCH) { + InsertString(); + } + } while (--prevLen > 0); + + strstart ++; + lookahead--; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + } else { + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + prevAvailable = true; + strstart++; + lookahead--; + } + + if (huffman.IsFull()) { + int len = strstart - blockStart; + if (prevAvailable) { + len--; + } + bool lastBlock = (finish && (lookahead == 0) && !prevAvailable); + huffman.FlushBlock(window, blockStart, len, lastBlock); + blockStart += len; + return !lastBlock; + } + } + return true; + } + + #region Instance Fields + + // Hash index of string to be inserted + int ins_h; + + /// + /// Hashtable, hashing three characters to an index for window, so + /// that window[index]..window[index+2] have this hash code. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xffff. + /// + short[] head; + + /// + /// prev[index & WMASK] points to the previous index that has the + /// same hash code as the string starting at index. This way + /// entries with the same hash code are in a linked list. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xffff. + /// + short[] prev; + + int matchStart; + // Length of best match + int matchLen; + // Set if previous match exists + bool prevAvailable; + int blockStart; + + /// + /// Points to the current character in the window. + /// + int strstart; + + /// + /// lookahead is the number of characters starting at strstart in + /// window that are valid. + /// So window[strstart] until window[strstart+lookahead-1] are valid + /// characters. + /// + int lookahead; + + /// + /// This array contains the part of the uncompressed stream that + /// is of relevance. The current character is indexed by strstart. + /// + byte[] window; + + DeflateStrategy strategy; + int max_chain, max_lazy, niceLength, goodLength; + + /// + /// The current compression function. + /// + int compressionFunction; + + /// + /// The input data for compression. + /// + byte[] inputBuf; + + /// + /// The total bytes of input read. + /// + long totalIn; + + /// + /// The offset into inputBuf, where input data starts. + /// + int inputOff; + + /// + /// The end offset of the input data. + /// + int inputEnd; + + DeflaterPending pending; + DeflaterHuffman huffman; + + /// + /// The adler checksum + /// + Adler32 adler; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/Compression/DeflaterHuffman.cs b/类库/Update/ZIP/Zip/Compression/DeflaterHuffman.cs new file mode 100644 index 0000000..8c89e59 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/DeflaterHuffman.cs @@ -0,0 +1,908 @@ +// DeflaterHuffman.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This is the DeflaterHuffman class. + /// + /// This class is not thread safe. This is inherent in the API, due + /// to the split of Deflate and SetInput. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class DeflaterHuffman + { + const int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6); + const int LITERAL_NUM = 286; + + // Number of distance codes + const int DIST_NUM = 30; + // Number of codes used to transfer bit lengths + const int BITLEN_NUM = 19; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + const int REP_3_6 = 16; + // repeat a zero length 3-10 times (3 bits of repeat count) + const int REP_3_10 = 17; + // repeat a zero length 11-138 times (7 bits of repeat count) + const int REP_11_138 = 18; + + const int EOF_SYMBOL = 256; + + // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit length codes. + static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + static readonly byte[] bit4Reverse = { + 0, + 8, + 4, + 12, + 2, + 10, + 6, + 14, + 1, + 9, + 5, + 13, + 3, + 11, + 7, + 15 + }; + + static short[] staticLCodes; + static byte[] staticLLength; + static short[] staticDCodes; + static byte[] staticDLength; + + class Tree + { + #region Instance Fields + public short[] freqs; + + public byte[] length; + + public int minNumCodes; + + public int numCodes; + + short[] codes; + int[] bl_counts; + int maxLength; + DeflaterHuffman dh; + #endregion + + #region Constructors + public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength) + { + this.dh = dh; + this.minNumCodes = minCodes; + this.maxLength = maxLength; + freqs = new short[elems]; + bl_counts = new int[maxLength]; + } + + #endregion + + /// + /// Resets the internal state of the tree + /// + public void Reset() + { + for (int i = 0; i < freqs.Length; i++) { + freqs[i] = 0; + } + codes = null; + length = null; + } + + public void WriteSymbol(int code) + { + // if (DeflaterConstants.DEBUGGING) { + // freqs[code]--; + // // Console.Write("writeSymbol("+freqs.length+","+code+"): "); + // } + dh.pending.WriteBits(codes[code] & 0xffff, length[code]); + } + + /// + /// Check that all frequencies are zero + /// + /// + /// At least one frequency is non-zero + /// + public void CheckEmpty() + { + bool empty = true; + for (int i = 0; i < freqs.Length; i++) { + if (freqs[i] != 0) { + //Console.WriteLine("freqs[" + i + "] == " + freqs[i]); + empty = false; + } + } + + if (!empty) { + throw new SharpZipBaseException("!Empty"); + } + } + + /// + /// Set static codes and length + /// + /// new codes + /// length for new codes + public void SetStaticCodes(short[] staticCodes, byte[] staticLengths) + { + codes = staticCodes; + length = staticLengths; + } + + /// + /// Build dynamic codes and lengths + /// + public void BuildCodes() + { + int numSymbols = freqs.Length; + int[] nextCode = new int[maxLength]; + int code = 0; + + codes = new short[freqs.Length]; + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("buildCodes: "+freqs.Length); + // } + + for (int bits = 0; bits < maxLength; bits++) { + nextCode[bits] = code; + code += bl_counts[bits] << (15 - bits); + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits] + // +" nextCode: "+code); + // } + } + +#if DebugDeflation + if ( DeflaterConstants.DEBUGGING && (code != 65536) ) + { + throw new SharpZipBaseException("Inconsistent bl_counts!"); + } +#endif + for (int i=0; i < numCodes; i++) { + int bits = length[i]; + if (bits > 0) { + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"), + // +bits); + // } + + codes[i] = BitReverse(nextCode[bits-1]); + nextCode[bits-1] += 1 << (16 - bits); + } + } + } + + public void BuildTree() + { + int numSymbols = freqs.Length; + + /* heap is a priority queue, sorted by frequency, least frequent + * nodes first. The heap is a binary tree, with the property, that + * the parent node is smaller than both child nodes. This assures + * that the smallest node is the first parent. + * + * The binary tree is encoded in an array: 0 is root node and + * the nodes 2*n+1, 2*n+2 are the child nodes of node n. + */ + int[] heap = new int[numSymbols]; + int heapLen = 0; + int maxCode = 0; + for (int n = 0; n < numSymbols; n++) { + int freq = freqs[n]; + if (freq != 0) { + // Insert n into heap + int pos = heapLen++; + int ppos; + while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) { + heap[pos] = heap[ppos]; + pos = ppos; + } + heap[pos] = n; + + maxCode = n; + } + } + + /* We could encode a single literal with 0 bits but then we + * don't see the literals. Therefore we force at least two + * literals to avoid this case. We don't care about order in + * this case, both literals get a 1 bit code. + */ + while (heapLen < 2) { + int node = maxCode < 2 ? ++maxCode : 0; + heap[heapLen++] = node; + } + + numCodes = Math.Max(maxCode + 1, minNumCodes); + + int numLeafs = heapLen; + int[] childs = new int[4 * heapLen - 2]; + int[] values = new int[2 * heapLen - 1]; + int numNodes = numLeafs; + for (int i = 0; i < heapLen; i++) { + int node = heap[i]; + childs[2 * i] = node; + childs[2 * i + 1] = -1; + values[i] = freqs[node] << 8; + heap[i] = i; + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + int first = heap[0]; + int last = heap[--heapLen]; + + // Propagate the hole to the leafs of the heap + int ppos = 0; + int path = 1; + + while (path < heapLen) { + if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) { + path++; + } + + heap[ppos] = heap[path]; + ppos = path; + path = path * 2 + 1; + } + + /* Now propagate the last element down along path. Normally + * it shouldn't go too deep. + */ + int lastVal = values[last]; + while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) { + heap[path] = heap[ppos]; + } + heap[path] = last; + + + int second = heap[0]; + + // Create a new node father of first and second + last = numNodes++; + childs[2 * last] = first; + childs[2 * last + 1] = second; + int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff); + values[last] = lastVal = values[first] + values[second] - mindepth + 1; + + // Again, propagate the hole to the leafs + ppos = 0; + path = 1; + + while (path < heapLen) { + if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) { + path++; + } + + heap[ppos] = heap[path]; + ppos = path; + path = ppos * 2 + 1; + } + + // Now propagate the new element down along path + while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) { + heap[path] = heap[ppos]; + } + heap[path] = last; + } while (heapLen > 1); + + if (heap[0] != childs.Length / 2 - 1) { + throw new SharpZipBaseException("Heap invariant violated"); + } + + BuildLength(childs); + } + + /// + /// Get encoded length + /// + /// Encoded length, the sum of frequencies * lengths + public int GetEncodedLength() + { + int len = 0; + for (int i = 0; i < freqs.Length; i++) { + len += freqs[i] * length[i]; + } + return len; + } + + /// + /// Scan a literal or distance tree to determine the frequencies of the codes + /// in the bit length tree. + /// + public void CalcBLFreq(Tree blTree) + { + int max_count; /* max repeat count */ + int min_count; /* min repeat count */ + int count; /* repeat count of the current code */ + int curlen = -1; /* length of current code */ + + int i = 0; + while (i < numCodes) { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else { + max_count = 6; + min_count = 3; + if (curlen != nextlen) { + blTree.freqs[nextlen]++; + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) { + i++; + if (++count >= max_count) { + break; + } + } + + if (count < min_count) { + blTree.freqs[curlen] += (short)count; + } else if (curlen != 0) { + blTree.freqs[REP_3_6]++; + } else if (count <= 10) { + blTree.freqs[REP_3_10]++; + } else { + blTree.freqs[REP_11_138]++; + } + } + } + + /// + /// Write tree values + /// + /// Tree to write + public void WriteTree(Tree blTree) + { + int max_count; // max repeat count + int min_count; // min repeat count + int count; // repeat count of the current code + int curlen = -1; // length of current code + + int i = 0; + while (i < numCodes) { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else { + max_count = 6; + min_count = 3; + if (curlen != nextlen) { + blTree.WriteSymbol(nextlen); + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) { + i++; + if (++count >= max_count) { + break; + } + } + + if (count < min_count) { + while (count-- > 0) { + blTree.WriteSymbol(curlen); + } + } else if (curlen != 0) { + blTree.WriteSymbol(REP_3_6); + dh.pending.WriteBits(count - 3, 2); + } else if (count <= 10) { + blTree.WriteSymbol(REP_3_10); + dh.pending.WriteBits(count - 3, 3); + } else { + blTree.WriteSymbol(REP_11_138); + dh.pending.WriteBits(count - 11, 7); + } + } + } + + void BuildLength(int[] childs) + { + this.length = new byte [freqs.Length]; + int numNodes = childs.Length / 2; + int numLeafs = (numNodes + 1) / 2; + int overflow = 0; + + for (int i = 0; i < maxLength; i++) { + bl_counts[i] = 0; + } + + // First calculate optimal bit lengths + int[] lengths = new int[numNodes]; + lengths[numNodes-1] = 0; + + for (int i = numNodes - 1; i >= 0; i--) { + if (childs[2 * i + 1] != -1) { + int bitLength = lengths[i] + 1; + if (bitLength > maxLength) { + bitLength = maxLength; + overflow++; + } + lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength; + } else { + // A leaf node + int bitLength = lengths[i]; + bl_counts[bitLength - 1]++; + this.length[childs[2*i]] = (byte) lengths[i]; + } + } + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Tree "+freqs.Length+" lengths:"); + // for (int i=0; i < numLeafs; i++) { + // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + // + " len: "+length[childs[2*i]]); + // } + // } + + if (overflow == 0) { + return; + } + + int incrBitLen = maxLength - 1; + do { + // Find the first bit length which could increase: + while (bl_counts[--incrBitLen] == 0) + ; + + // Move this node one down and remove a corresponding + // number of overflow nodes. + do { + bl_counts[incrBitLen]--; + bl_counts[++incrBitLen]++; + overflow -= 1 << (maxLength - 1 - incrBitLen); + } while (overflow > 0 && incrBitLen < maxLength - 1); + } while (overflow > 0); + + /* We may have overshot above. Move some nodes from maxLength to + * maxLength-1 in that case. + */ + bl_counts[maxLength-1] += overflow; + bl_counts[maxLength-2] -= overflow; + + /* Now recompute all bit lengths, scanning in increasing + * frequency. It is simpler to reconstruct all lengths instead of + * fixing only the wrong ones. This idea is taken from 'ar' + * written by Haruhiko Okumura. + * + * The nodes were inserted with decreasing frequency into the childs + * array. + */ + int nodePtr = 2 * numLeafs; + for (int bits = maxLength; bits != 0; bits--) { + int n = bl_counts[bits-1]; + while (n > 0) { + int childPtr = 2*childs[nodePtr++]; + if (childs[childPtr + 1] == -1) { + // We found another leaf + length[childs[childPtr]] = (byte) bits; + n--; + } + } + } + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("*** After overflow elimination. ***"); + // for (int i=0; i < numLeafs; i++) { + // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + // + " len: "+length[childs[2*i]]); + // } + // } + } + + } + + #region Instance Fields + /// + /// Pending buffer to use + /// + public DeflaterPending pending; + + Tree literalTree; + Tree distTree; + Tree blTree; + + // Buffer for distances + short[] d_buf; + byte[] l_buf; + int last_lit; + int extra_bits; + #endregion + + static DeflaterHuffman() + { + // See RFC 1951 3.2.6 + // Literal codes + staticLCodes = new short[LITERAL_NUM]; + staticLLength = new byte[LITERAL_NUM]; + + int i = 0; + while (i < 144) { + staticLCodes[i] = BitReverse((0x030 + i) << 8); + staticLLength[i++] = 8; + } + + while (i < 256) { + staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7); + staticLLength[i++] = 9; + } + + while (i < 280) { + staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9); + staticLLength[i++] = 7; + } + + while (i < LITERAL_NUM) { + staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8); + staticLLength[i++] = 8; + } + + // Distance codes + staticDCodes = new short[DIST_NUM]; + staticDLength = new byte[DIST_NUM]; + for (i = 0; i < DIST_NUM; i++) { + staticDCodes[i] = BitReverse(i << 11); + staticDLength[i] = 5; + } + } + + /// + /// Construct instance with pending buffer + /// + /// Pending buffer to use + public DeflaterHuffman(DeflaterPending pending) + { + this.pending = pending; + + literalTree = new Tree(this, LITERAL_NUM, 257, 15); + distTree = new Tree(this, DIST_NUM, 1, 15); + blTree = new Tree(this, BITLEN_NUM, 4, 7); + + d_buf = new short[BUFSIZE]; + l_buf = new byte [BUFSIZE]; + } + + /// + /// Reset internal state + /// + public void Reset() + { + last_lit = 0; + extra_bits = 0; + literalTree.Reset(); + distTree.Reset(); + blTree.Reset(); + } + + /// + /// Write all trees to pending buffer + /// + /// The number/rank of treecodes to send. + public void SendAllTrees(int blTreeCodes) + { + blTree.BuildCodes(); + literalTree.BuildCodes(); + distTree.BuildCodes(); + pending.WriteBits(literalTree.numCodes - 257, 5); + pending.WriteBits(distTree.numCodes - 1, 5); + pending.WriteBits(blTreeCodes - 4, 4); + for (int rank = 0; rank < blTreeCodes; rank++) { + pending.WriteBits(blTree.length[BL_ORDER[rank]], 3); + } + literalTree.WriteTree(blTree); + distTree.WriteTree(blTree); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + blTree.CheckEmpty(); + } +#endif + } + + /// + /// Compress current buffer writing data to pending buffer + /// + public void CompressBlock() + { + for (int i = 0; i < last_lit; i++) { + int litlen = l_buf[i] & 0xff; + int dist = d_buf[i]; + if (dist-- != 0) { + // if (DeflaterConstants.DEBUGGING) { + // Console.Write("["+(dist+1)+","+(litlen+3)+"]: "); + // } + + int lc = Lcode(litlen); + literalTree.WriteSymbol(lc); + + int bits = (lc - 261) / 4; + if (bits > 0 && bits <= 5) { + pending.WriteBits(litlen & ((1 << bits) - 1), bits); + } + + int dc = Dcode(dist); + distTree.WriteSymbol(dc); + + bits = dc / 2 - 1; + if (bits > 0) { + pending.WriteBits(dist & ((1 << bits) - 1), bits); + } + } else { + // if (DeflaterConstants.DEBUGGING) { + // if (litlen > 32 && litlen < 127) { + // Console.Write("("+(char)litlen+"): "); + // } else { + // Console.Write("{"+litlen+"}: "); + // } + // } + literalTree.WriteSymbol(litlen); + } + } + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.Write("EOF: "); + } +#endif + literalTree.WriteSymbol(EOF_SYMBOL); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + literalTree.CheckEmpty(); + distTree.CheckEmpty(); + } +#endif + } + + /// + /// Flush block to output with no compression + /// + /// Data to write + /// Index of first byte to write + /// Count of bytes to write + /// True if this is the last block + public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) + { +#if DebugDeflation + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Flushing stored block "+ storedLength); + // } +#endif + pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3); + pending.AlignToByte(); + pending.WriteShort(storedLength); + pending.WriteShort(~storedLength); + pending.WriteBlock(stored, storedOffset, storedLength); + Reset(); + } + + /// + /// Flush block to output with compression + /// + /// Data to flush + /// Index of first byte to flush + /// Count of bytes to flush + /// True if this is the last block + public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) + { + literalTree.freqs[EOF_SYMBOL]++; + + // Build trees + literalTree.BuildTree(); + distTree.BuildTree(); + + // Calculate bitlen frequency + literalTree.CalcBLFreq(blTree); + distTree.CalcBLFreq(blTree); + + // Build bitlen tree + blTree.BuildTree(); + + int blTreeCodes = 4; + for (int i = 18; i > blTreeCodes; i--) { + if (blTree.length[BL_ORDER[i]] > 0) { + blTreeCodes = i+1; + } + } + int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() + + literalTree.GetEncodedLength() + distTree.GetEncodedLength() + + extra_bits; + + int static_len = extra_bits; + for (int i = 0; i < LITERAL_NUM; i++) { + static_len += literalTree.freqs[i] * staticLLength[i]; + } + for (int i = 0; i < DIST_NUM; i++) { + static_len += distTree.freqs[i] * staticDLength[i]; + } + if (opt_len >= static_len) { + // Force static trees + opt_len = static_len; + } + + if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) { + // Store Block + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len + // + " <= " + static_len); + // } + FlushStoredBlock(stored, storedOffset, storedLength, lastBlock); + } else if (opt_len == static_len) { + // Encode with static tree + pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3); + literalTree.SetStaticCodes(staticLCodes, staticLLength); + distTree.SetStaticCodes(staticDCodes, staticDLength); + CompressBlock(); + Reset(); + } else { + // Encode with dynamic tree + pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3); + SendAllTrees(blTreeCodes); + CompressBlock(); + Reset(); + } + } + + /// + /// Get value indicating if internal buffer is full + /// + /// true if buffer is full + public bool IsFull() + { + return last_lit >= BUFSIZE; + } + + /// + /// Add literal to buffer + /// + /// Literal value to add to buffer. + /// Value indicating internal buffer is full + public bool TallyLit(int literal) + { + // if (DeflaterConstants.DEBUGGING) { + // if (lit > 32 && lit < 127) { + // //Console.WriteLine("("+(char)lit+")"); + // } else { + // //Console.WriteLine("{"+lit+"}"); + // } + // } + d_buf[last_lit] = 0; + l_buf[last_lit++] = (byte)literal; + literalTree.freqs[literal]++; + return IsFull(); + } + + /// + /// Add distance code and length to literal and distance trees + /// + /// Distance code + /// Length + /// Value indicating if internal buffer is full + public bool TallyDist(int distance, int length) + { + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("[" + distance + "," + length + "]"); + // } + + d_buf[last_lit] = (short)distance; + l_buf[last_lit++] = (byte)(length - 3); + + int lc = Lcode(length - 3); + literalTree.freqs[lc]++; + if (lc >= 265 && lc < 285) { + extra_bits += (lc - 261) / 4; + } + + int dc = Dcode(distance - 1); + distTree.freqs[dc]++; + if (dc >= 4) { + extra_bits += dc / 2 - 1; + } + return IsFull(); + } + + + /// + /// Reverse the bits of a 16 bit value. + /// + /// Value to reverse bits + /// Value with bits reversed + public static short BitReverse(int toReverse) + { + return (short) (bit4Reverse[toReverse & 0xF] << 12 | + bit4Reverse[(toReverse >> 4) & 0xF] << 8 | + bit4Reverse[(toReverse >> 8) & 0xF] << 4 | + bit4Reverse[toReverse >> 12]); + } + + static int Lcode(int length) + { + if (length == 255) { + return 285; + } + + int code = 257; + while (length >= 8) { + code += 4; + length >>= 1; + } + return code + length; + } + + static int Dcode(int distance) + { + int code = 0; + while (distance >= 4) { + code += 2; + distance >>= 1; + } + return code + distance; + } + } +} diff --git a/类库/Update/ZIP/Zip/Compression/DeflaterPending.cs b/类库/Update/ZIP/Zip/Compression/DeflaterPending.cs new file mode 100644 index 0000000..4cecc2e --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/DeflaterPending.cs @@ -0,0 +1,57 @@ +// DeflaterPending.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class stores the pending output of the Deflater. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class DeflaterPending : PendingBuffer + { + /// + /// Construct instance with default buffer size + /// + public DeflaterPending() : base(DeflaterConstants.PENDING_BUF_SIZE) + { + } + } +} diff --git a/类库/Update/ZIP/Zip/Compression/Inflater.cs b/类库/Update/ZIP/Zip/Compression/Inflater.cs new file mode 100644 index 0000000..16c3ef6 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/Inflater.cs @@ -0,0 +1,864 @@ +// Inflater.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + /// + /// Inflater is used to decompress data that has been compressed according + /// to the "deflate" standard described in rfc1951. + /// + /// By default Zlib (rfc1950) headers and footers are expected in the input. + /// You can use constructor public Inflater(bool noHeader) passing true + /// if there is no Zlib header information + /// + /// The usage is as following. First you have to set some input with + /// SetInput(), then Inflate() it. If inflate doesn't + /// inflate any bytes there may be three reasons: + ///
    + ///
  • IsNeedingInput() returns true because the input buffer is empty. + /// You have to provide more input with SetInput(). + /// NOTE: IsNeedingInput() also returns true when, the stream is finished. + ///
  • + ///
  • IsNeedingDictionary() returns true, you have to provide a preset + /// dictionary with SetDictionary().
  • + ///
  • IsFinished returns true, the inflater has finished.
  • + ///
+ /// Once the first output byte is produced, a dictionary will not be + /// needed at a later stage. + /// + /// author of the original java version : John Leuner, Jochen Hoenicke + ///
+ public class Inflater + { + #region Constants/Readonly + /// + /// Copy lengths for literal codes 257..285 + /// + static readonly int[] CPLENS = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 + }; + + /// + /// Extra bits for literal codes 257..285 + /// + static readonly int[] CPLEXT = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; + + /// + /// Copy offsets for distance codes 0..29 + /// + static readonly int[] CPDIST = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + /// + /// Extra bits for distance codes + /// + static readonly int[] CPDEXT = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + }; + + /// + /// These are the possible states for an inflater + /// + const int DECODE_HEADER = 0; + const int DECODE_DICT = 1; + const int DECODE_BLOCKS = 2; + const int DECODE_STORED_LEN1 = 3; + const int DECODE_STORED_LEN2 = 4; + const int DECODE_STORED = 5; + const int DECODE_DYN_HEADER = 6; + const int DECODE_HUFFMAN = 7; + const int DECODE_HUFFMAN_LENBITS = 8; + const int DECODE_HUFFMAN_DIST = 9; + const int DECODE_HUFFMAN_DISTBITS = 10; + const int DECODE_CHKSUM = 11; + const int FINISHED = 12; + #endregion + + #region Instance Fields + /// + /// This variable contains the current state. + /// + int mode; + + /// + /// The adler checksum of the dictionary or of the decompressed + /// stream, as it is written in the header resp. footer of the + /// compressed stream. + /// Only valid if mode is DECODE_DICT or DECODE_CHKSUM. + /// + int readAdler; + + /// + /// The number of bits needed to complete the current state. This + /// is valid, if mode is DECODE_DICT, DECODE_CHKSUM, + /// DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. + /// + int neededBits; + int repLength; + int repDist; + int uncomprLen; + + /// + /// True, if the last block flag was set in the last block of the + /// inflated stream. This means that the stream ends after the + /// current block. + /// + bool isLastBlock; + + /// + /// The total number of inflated bytes. + /// + long totalOut; + + /// + /// The total number of bytes set with setInput(). This is not the + /// value returned by the TotalIn property, since this also includes the + /// unprocessed input. + /// + long totalIn; + + /// + /// This variable stores the noHeader flag that was given to the constructor. + /// True means, that the inflated stream doesn't contain a Zlib header or + /// footer. + /// + bool noHeader; + + StreamManipulator input; + OutputWindow outputWindow; + InflaterDynHeader dynHeader; + InflaterHuffmanTree litlenTree, distTree; + Adler32 adler; + #endregion + + #region Constructors + /// + /// Creates a new inflater or RFC1951 decompressor + /// RFC1950/Zlib headers and footers will be expected in the input data + /// + public Inflater() : this(false) + { + } + + /// + /// Creates a new inflater. + /// + /// + /// True if no RFC1950/Zlib header and footer fields are expected in the input data + /// + /// This is used for GZIPed/Zipped input. + /// + /// For compatibility with + /// Sun JDK you should provide one byte of input more than needed in + /// this case. + /// + public Inflater(bool noHeader) + { + this.noHeader = noHeader; + this.adler = new Adler32(); + input = new StreamManipulator(); + outputWindow = new OutputWindow(); + mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; + } + #endregion + + /// + /// Resets the inflater so that a new stream can be decompressed. All + /// pending input and output will be discarded. + /// + public void Reset() + { + mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; + totalIn = 0; + totalOut = 0; + input.Reset(); + outputWindow.Reset(); + dynHeader = null; + litlenTree = null; + distTree = null; + isLastBlock = false; + adler.Reset(); + } + + /// + /// Decodes a zlib/RFC1950 header. + /// + /// + /// False if more input is needed. + /// + /// + /// The header is invalid. + /// + private bool DecodeHeader() + { + int header = input.PeekBits(16); + if (header < 0) { + return false; + } + input.DropBits(16); + + // The header is written in "wrong" byte order + header = ((header << 8) | (header >> 8)) & 0xffff; + if (header % 31 != 0) { + throw new SharpZipBaseException("Header checksum illegal"); + } + + if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) { + throw new SharpZipBaseException("Compression Method unknown"); + } + + /* Maximum size of the backwards window in bits. + * We currently ignore this, but we could use it to make the + * inflater window more space efficient. On the other hand the + * full window (15 bits) is needed most times, anyway. + int max_wbits = ((header & 0x7000) >> 12) + 8; + */ + + if ((header & 0x0020) == 0) { // Dictionary flag? + mode = DECODE_BLOCKS; + } else { + mode = DECODE_DICT; + neededBits = 32; + } + return true; + } + + /// + /// Decodes the dictionary checksum after the deflate header. + /// + /// + /// False if more input is needed. + /// + private bool DecodeDict() + { + while (neededBits > 0) { + int dictByte = input.PeekBits(8); + if (dictByte < 0) { + return false; + } + input.DropBits(8); + readAdler = (readAdler << 8) | dictByte; + neededBits -= 8; + } + return false; + } + + /// + /// Decodes the huffman encoded symbols in the input stream. + /// + /// + /// false if more input is needed, true if output window is + /// full or the current block ends. + /// + /// + /// if deflated stream is invalid. + /// + private bool DecodeHuffman() + { + int free = outputWindow.GetFreeSpace(); + while (free >= 258) + { + int symbol; + switch (mode) + { + case DECODE_HUFFMAN: + // This is the inner loop so it is optimized a bit + while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0) + { + outputWindow.Write(symbol); + if (--free < 258) + { + return true; + } + } + + if (symbol < 257) + { + if (symbol < 0) + { + return false; + } + else + { + // symbol == 256: end of block + distTree = null; + litlenTree = null; + mode = DECODE_BLOCKS; + return true; + } + } + + try + { + repLength = CPLENS[symbol - 257]; + neededBits = CPLEXT[symbol - 257]; + } + catch (Exception) + { + throw new SharpZipBaseException("Illegal rep length code"); + } + goto case DECODE_HUFFMAN_LENBITS; // fall through + + case DECODE_HUFFMAN_LENBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_LENBITS; + int i = input.PeekBits(neededBits); + if (i < 0) + { + return false; + } + input.DropBits(neededBits); + repLength += i; + } + mode = DECODE_HUFFMAN_DIST; + goto case DECODE_HUFFMAN_DIST; // fall through + + case DECODE_HUFFMAN_DIST: + symbol = distTree.GetSymbol(input); + if (symbol < 0) + { + return false; + } + + try + { + repDist = CPDIST[symbol]; + neededBits = CPDEXT[symbol]; + } + catch (Exception) + { + throw new SharpZipBaseException("Illegal rep dist code"); + } + + goto case DECODE_HUFFMAN_DISTBITS; // fall through + + case DECODE_HUFFMAN_DISTBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_DISTBITS; + int i = input.PeekBits(neededBits); + if (i < 0) + { + return false; + } + input.DropBits(neededBits); + repDist += i; + } + + outputWindow.Repeat(repLength, repDist); + free -= repLength; + mode = DECODE_HUFFMAN; + break; + + default: + throw new SharpZipBaseException("Inflater unknown mode"); + } + } + return true; + } + + /// + /// Decodes the adler checksum after the deflate stream. + /// + /// + /// false if more input is needed. + /// + /// + /// If checksum doesn't match. + /// + private bool DecodeChksum() + { + while (neededBits > 0) { + int chkByte = input.PeekBits(8); + if (chkByte < 0) { + return false; + } + input.DropBits(8); + readAdler = (readAdler << 8) | chkByte; + neededBits -= 8; + } + + if ((int) adler.Value != readAdler) { + throw new SharpZipBaseException("Adler chksum doesn't match: " + (int)adler.Value + " vs. " + readAdler); + } + + mode = FINISHED; + return false; + } + + /// + /// Decodes the deflated stream. + /// + /// + /// false if more input is needed, or if finished. + /// + /// + /// if deflated stream is invalid. + /// + private bool Decode() + { + switch (mode) { + case DECODE_HEADER: + return DecodeHeader(); + + case DECODE_DICT: + return DecodeDict(); + + case DECODE_CHKSUM: + return DecodeChksum(); + + case DECODE_BLOCKS: + if (isLastBlock) { + if (noHeader) { + mode = FINISHED; + return false; + } else { + input.SkipToByteBoundary(); + neededBits = 32; + mode = DECODE_CHKSUM; + return true; + } + } + + int type = input.PeekBits(3); + if (type < 0) { + return false; + } + input.DropBits(3); + + if ((type & 1) != 0) { + isLastBlock = true; + } + switch (type >> 1){ + case DeflaterConstants.STORED_BLOCK: + input.SkipToByteBoundary(); + mode = DECODE_STORED_LEN1; + break; + case DeflaterConstants.STATIC_TREES: + litlenTree = InflaterHuffmanTree.defLitLenTree; + distTree = InflaterHuffmanTree.defDistTree; + mode = DECODE_HUFFMAN; + break; + case DeflaterConstants.DYN_TREES: + dynHeader = new InflaterDynHeader(); + mode = DECODE_DYN_HEADER; + break; + default: + throw new SharpZipBaseException("Unknown block type " + type); + } + return true; + + case DECODE_STORED_LEN1: + { + if ((uncomprLen = input.PeekBits(16)) < 0) { + return false; + } + input.DropBits(16); + mode = DECODE_STORED_LEN2; + } + goto case DECODE_STORED_LEN2; // fall through + + case DECODE_STORED_LEN2: + { + int nlen = input.PeekBits(16); + if (nlen < 0) { + return false; + } + input.DropBits(16); + if (nlen != (uncomprLen ^ 0xffff)) { + throw new SharpZipBaseException("broken uncompressed block"); + } + mode = DECODE_STORED; + } + goto case DECODE_STORED; // fall through + + case DECODE_STORED: + { + int more = outputWindow.CopyStored(input, uncomprLen); + uncomprLen -= more; + if (uncomprLen == 0) { + mode = DECODE_BLOCKS; + return true; + } + return !input.IsNeedingInput; + } + + case DECODE_DYN_HEADER: + if (!dynHeader.Decode(input)) { + return false; + } + + litlenTree = dynHeader.BuildLitLenTree(); + distTree = dynHeader.BuildDistTree(); + mode = DECODE_HUFFMAN; + goto case DECODE_HUFFMAN; // fall through + + case DECODE_HUFFMAN: + case DECODE_HUFFMAN_LENBITS: + case DECODE_HUFFMAN_DIST: + case DECODE_HUFFMAN_DISTBITS: + return DecodeHuffman(); + + case FINISHED: + return false; + + default: + throw new SharpZipBaseException("Inflater.Decode unknown mode"); + } + } + + /// + /// Sets the preset dictionary. This should only be called, if + /// needsDictionary() returns true and it should set the same + /// dictionary, that was used for deflating. The getAdler() + /// function returns the checksum of the dictionary needed. + /// + /// + /// The dictionary. + /// + public void SetDictionary(byte[] buffer) + { + SetDictionary(buffer, 0, buffer.Length); + } + + /// + /// Sets the preset dictionary. This should only be called, if + /// needsDictionary() returns true and it should set the same + /// dictionary, that was used for deflating. The getAdler() + /// function returns the checksum of the dictionary needed. + /// + /// + /// The dictionary. + /// + /// + /// The index into buffer where the dictionary starts. + /// + /// + /// The number of bytes in the dictionary. + /// + /// + /// No dictionary is needed. + /// + /// + /// The adler checksum for the buffer is invalid + /// + public void SetDictionary(byte[] buffer, int index, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( index < 0 ) { + throw new ArgumentOutOfRangeException("index"); + } + + if ( count < 0 ) { + throw new ArgumentOutOfRangeException("count"); + } + + if (!IsNeedingDictionary) { + throw new InvalidOperationException("Dictionary is not needed"); + } + + adler.Update(buffer, index, count); + + if ((int)adler.Value != readAdler) { + throw new SharpZipBaseException("Wrong adler checksum"); + } + adler.Reset(); + outputWindow.CopyDict(buffer, index, count); + mode = DECODE_BLOCKS; + } + + /// + /// Sets the input. This should only be called, if needsInput() + /// returns true. + /// + /// + /// the input. + /// + public void SetInput(byte[] buffer) + { + SetInput(buffer, 0, buffer.Length); + } + + /// + /// Sets the input. This should only be called, if needsInput() + /// returns true. + /// + /// + /// The source of input data + /// + /// + /// The index into buffer where the input starts. + /// + /// + /// The number of bytes of input to use. + /// + /// + /// No input is needed. + /// + /// + /// The index and/or count are wrong. + /// + public void SetInput(byte[] buffer, int index, int count) + { + input.SetInput(buffer, index, count); + totalIn += (long)count; + } + + /// + /// Inflates the compressed stream to the output buffer. If this + /// returns 0, you should check, whether IsNeedingDictionary(), + /// IsNeedingInput() or IsFinished() returns true, to determine why no + /// further output is produced. + /// + /// + /// the output buffer. + /// + /// + /// The number of bytes written to the buffer, 0 if no further + /// output can be produced. + /// + /// + /// if buffer has length 0. + /// + /// + /// if deflated stream is invalid. + /// + public int Inflate(byte[] buffer) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + return Inflate(buffer, 0, buffer.Length); + } + + /// + /// Inflates the compressed stream to the output buffer. If this + /// returns 0, you should check, whether needsDictionary(), + /// needsInput() or finished() returns true, to determine why no + /// further output is produced. + /// + /// + /// the output buffer. + /// + /// + /// the offset in buffer where storing starts. + /// + /// + /// the maximum number of bytes to output. + /// + /// + /// the number of bytes written to the buffer, 0 if no further output can be produced. + /// + /// + /// if count is less than 0. + /// + /// + /// if the index and / or count are wrong. + /// + /// + /// if deflated stream is invalid. + /// + public int Inflate(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "count cannot be negative"); +#endif + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "offset cannot be negative"); +#endif + } + + if ( offset + count > buffer.Length ) { + throw new ArgumentException("count exceeds buffer bounds"); + } + + // Special case: count may be zero + if (count == 0) + { + if (!IsFinished) { // -jr- 08-Nov-2003 INFLATE_BUG fix.. + Decode(); + } + return 0; + } + + int bytesCopied = 0; + + do { + if (mode != DECODE_CHKSUM) { + /* Don't give away any output, if we are waiting for the + * checksum in the input stream. + * + * With this trick we have always: + * IsNeedingInput() and not IsFinished() + * implies more output can be produced. + */ + int more = outputWindow.CopyOutput(buffer, offset, count); + if ( more > 0 ) { + adler.Update(buffer, offset, more); + offset += more; + bytesCopied += more; + totalOut += (long)more; + count -= more; + if (count == 0) { + return bytesCopied; + } + } + } + } while (Decode() || ((outputWindow.GetAvailable() > 0) && (mode != DECODE_CHKSUM))); + return bytesCopied; + } + + /// + /// Returns true, if the input buffer is empty. + /// You should then call setInput(). + /// NOTE: This method also returns true when the stream is finished. + /// + public bool IsNeedingInput { + get { + return input.IsNeedingInput; + } + } + + /// + /// Returns true, if a preset dictionary is needed to inflate the input. + /// + public bool IsNeedingDictionary { + get { + return mode == DECODE_DICT && neededBits == 0; + } + } + + /// + /// Returns true, if the inflater has finished. This means, that no + /// input is needed and no output can be produced. + /// + public bool IsFinished { + get { + return mode == FINISHED && outputWindow.GetAvailable() == 0; + } + } + + /// + /// Gets the adler checksum. This is either the checksum of all + /// uncompressed bytes returned by inflate(), or if needsDictionary() + /// returns true (and thus no output was yet produced) this is the + /// adler checksum of the expected dictionary. + /// + /// + /// the adler checksum. + /// + public int Adler { + get { + return IsNeedingDictionary ? readAdler : (int) adler.Value; + } + } + + /// + /// Gets the total number of output bytes returned by Inflate(). + /// + /// + /// the total number of output bytes. + /// + public long TotalOut { + get { + return totalOut; + } + } + + /// + /// Gets the total number of processed compressed input bytes. + /// + /// + /// The total number of bytes of processed input bytes. + /// + public long TotalIn { + get { + return totalIn - (long)RemainingInput; + } + } + + /// + /// Gets the number of unprocessed input bytes. Useful, if the end of the + /// stream is reached and you want to further process the bytes after + /// the deflate stream. + /// + /// + /// The number of bytes of the input which have not been processed. + /// + public int RemainingInput { + // TODO: This should be a long? + get { + return input.AvailableBytes; + } + } + } +} diff --git a/类库/Update/ZIP/Zip/Compression/InflaterDynHeader.cs b/类库/Update/ZIP/Zip/Compression/InflaterDynHeader.cs new file mode 100644 index 0000000..77e87ac --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/InflaterDynHeader.cs @@ -0,0 +1,218 @@ +// InflaterDynHeader.cs +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + class InflaterDynHeader + { + #region Constants + const int LNUM = 0; + const int DNUM = 1; + const int BLNUM = 2; + const int BLLENS = 3; + const int LENS = 4; + const int REPS = 5; + + static readonly int[] repMin = { 3, 3, 11 }; + static readonly int[] repBits = { 2, 3, 7 }; + + static readonly int[] BL_ORDER = + { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + #endregion + + #region Constructors + public InflaterDynHeader() + { + } + #endregion + + public bool Decode(StreamManipulator input) + { + decode_loop: + for (;;) { + switch (mode) { + case LNUM: + lnum = input.PeekBits(5); + if (lnum < 0) { + return false; + } + lnum += 257; + input.DropBits(5); + // System.err.println("LNUM: "+lnum); + mode = DNUM; + goto case DNUM; // fall through + case DNUM: + dnum = input.PeekBits(5); + if (dnum < 0) { + return false; + } + dnum++; + input.DropBits(5); + // System.err.println("DNUM: "+dnum); + num = lnum+dnum; + litdistLens = new byte[num]; + mode = BLNUM; + goto case BLNUM; // fall through + case BLNUM: + blnum = input.PeekBits(4); + if (blnum < 0) { + return false; + } + blnum += 4; + input.DropBits(4); + blLens = new byte[19]; + ptr = 0; + // System.err.println("BLNUM: "+blnum); + mode = BLLENS; + goto case BLLENS; // fall through + case BLLENS: + while (ptr < blnum) { + int len = input.PeekBits(3); + if (len < 0) { + return false; + } + input.DropBits(3); + // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); + blLens[BL_ORDER[ptr]] = (byte) len; + ptr++; + } + blTree = new InflaterHuffmanTree(blLens); + blLens = null; + ptr = 0; + mode = LENS; + goto case LENS; // fall through + case LENS: + { + int symbol; + while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) { + /* Normal case: symbol in [0..15] */ + + // System.err.println("litdistLens["+ptr+"]: "+symbol); + litdistLens[ptr++] = lastLen = (byte)symbol; + + if (ptr == num) { + /* Finished */ + return true; + } + } + + /* need more input ? */ + if (symbol < 0) { + return false; + } + + /* otherwise repeat code */ + if (symbol >= 17) { + /* repeat zero */ + // System.err.println("repeating zero"); + lastLen = 0; + } else { + if (ptr == 0) { + throw new SharpZipBaseException(); + } + } + repSymbol = symbol-16; + } + mode = REPS; + goto case REPS; // fall through + case REPS: + { + int bits = repBits[repSymbol]; + int count = input.PeekBits(bits); + if (count < 0) { + return false; + } + input.DropBits(bits); + count += repMin[repSymbol]; + // System.err.println("litdistLens repeated: "+count); + + if (ptr + count > num) { + throw new SharpZipBaseException(); + } + while (count-- > 0) { + litdistLens[ptr++] = lastLen; + } + + if (ptr == num) { + /* Finished */ + return true; + } + } + mode = LENS; + goto decode_loop; + } + } + } + + public InflaterHuffmanTree BuildLitLenTree() + { + byte[] litlenLens = new byte[lnum]; + Array.Copy(litdistLens, 0, litlenLens, 0, lnum); + return new InflaterHuffmanTree(litlenLens); + } + + public InflaterHuffmanTree BuildDistTree() + { + byte[] distLens = new byte[dnum]; + Array.Copy(litdistLens, lnum, distLens, 0, dnum); + return new InflaterHuffmanTree(distLens); + } + + #region Instance Fields + byte[] blLens; + byte[] litdistLens; + + InflaterHuffmanTree blTree; + + /// + /// The current decode mode + /// + int mode; + int lnum, dnum, blnum, num; + int repSymbol; + byte lastLen; + int ptr; + #endregion + + } +} diff --git a/类库/Update/ZIP/Zip/Compression/InflaterHuffmanTree.cs b/类库/Update/ZIP/Zip/Compression/InflaterHuffmanTree.cs new file mode 100644 index 0000000..2f61118 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/InflaterHuffmanTree.cs @@ -0,0 +1,232 @@ +// InflaterHuffmanTree.cs +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// Huffman tree used for inflation + /// + public class InflaterHuffmanTree + { + #region Constants + const int MAX_BITLEN = 15; + #endregion + + #region Instance Fields + short[] tree; + #endregion + + /// + /// Literal length tree + /// + public static InflaterHuffmanTree defLitLenTree; + + /// + /// Distance tree + /// + public static InflaterHuffmanTree defDistTree; + + static InflaterHuffmanTree() + { + try { + byte[] codeLengths = new byte[288]; + int i = 0; + while (i < 144) { + codeLengths[i++] = 8; + } + while (i < 256) { + codeLengths[i++] = 9; + } + while (i < 280) { + codeLengths[i++] = 7; + } + while (i < 288) { + codeLengths[i++] = 8; + } + defLitLenTree = new InflaterHuffmanTree(codeLengths); + + codeLengths = new byte[32]; + i = 0; + while (i < 32) { + codeLengths[i++] = 5; + } + defDistTree = new InflaterHuffmanTree(codeLengths); + } catch (Exception) { + throw new SharpZipBaseException("InflaterHuffmanTree: static tree length illegal"); + } + } + + #region Constructors + /// + /// Constructs a Huffman tree from the array of code lengths. + /// + /// + /// the array of code lengths + /// + public InflaterHuffmanTree(byte[] codeLengths) + { + BuildTree(codeLengths); + } + #endregion + + void BuildTree(byte[] codeLengths) + { + int[] blCount = new int[MAX_BITLEN + 1]; + int[] nextCode = new int[MAX_BITLEN + 1]; + + for (int i = 0; i < codeLengths.Length; i++) { + int bits = codeLengths[i]; + if (bits > 0) { + blCount[bits]++; + } + } + + int code = 0; + int treeSize = 512; + for (int bits = 1; bits <= MAX_BITLEN; bits++) { + nextCode[bits] = code; + code += blCount[bits] << (16 - bits); + if (bits >= 10) { + /* We need an extra table for bit lengths >= 10. */ + int start = nextCode[bits] & 0x1ff80; + int end = code & 0x1ff80; + treeSize += (end - start) >> (16 - bits); + } + } + +/* -jr comment this out! doesnt work for dynamic trees and pkzip 2.04g + if (code != 65536) + { + throw new SharpZipBaseException("Code lengths don't add up properly."); + } +*/ + /* Now create and fill the extra tables from longest to shortest + * bit len. This way the sub trees will be aligned. + */ + tree = new short[treeSize]; + int treePtr = 512; + for (int bits = MAX_BITLEN; bits >= 10; bits--) { + int end = code & 0x1ff80; + code -= blCount[bits] << (16 - bits); + int start = code & 0x1ff80; + for (int i = start; i < end; i += 1 << 7) { + tree[DeflaterHuffman.BitReverse(i)] = (short) ((-treePtr << 4) | bits); + treePtr += 1 << (bits-9); + } + } + + for (int i = 0; i < codeLengths.Length; i++) { + int bits = codeLengths[i]; + if (bits == 0) { + continue; + } + code = nextCode[bits]; + int revcode = DeflaterHuffman.BitReverse(code); + if (bits <= 9) { + do { + tree[revcode] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } while (revcode < 512); + } else { + int subTree = tree[revcode & 511]; + int treeLen = 1 << (subTree & 15); + subTree = -(subTree >> 4); + do { + tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } while (revcode < treeLen); + } + nextCode[bits] = code + (1 << (16 - bits)); + } + + } + + /// + /// Reads the next symbol from input. The symbol is encoded using the + /// huffman tree. + /// + /// + /// input the input source. + /// + /// + /// the next symbol, or -1 if not enough input is available. + /// + public int GetSymbol(StreamManipulator input) + { + int lookahead, symbol; + if ((lookahead = input.PeekBits(9)) >= 0) { + if ((symbol = tree[lookahead]) >= 0) { + input.DropBits(symbol & 15); + return symbol >> 4; + } + int subtree = -(symbol >> 4); + int bitlen = symbol & 15; + if ((lookahead = input.PeekBits(bitlen)) >= 0) { + symbol = tree[subtree | (lookahead >> 9)]; + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + int bits = input.AvailableBits; + lookahead = input.PeekBits(bits); + symbol = tree[subtree | (lookahead >> 9)]; + if ((symbol & 15) <= bits) { + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + return -1; + } + } + } else { + int bits = input.AvailableBits; + lookahead = input.PeekBits(bits); + symbol = tree[lookahead]; + if (symbol >= 0 && (symbol & 15) <= bits) { + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + return -1; + } + } + } + } +} + diff --git a/类库/Update/ZIP/Zip/Compression/PendingBuffer.cs b/类库/Update/ZIP/Zip/Compression/PendingBuffer.cs new file mode 100644 index 0000000..d205845 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/PendingBuffer.cs @@ -0,0 +1,295 @@ +// PendingBuffer.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class is general purpose class for writing data to a buffer. + /// + /// It allows you to write bits as well as bytes + /// Based on DeflaterPending.java + /// + /// author of the original java version : Jochen Hoenicke + /// + public class PendingBuffer + { + #region Instance Fields + /// + /// Internal work buffer + /// + byte[] buffer_; + + int start; + int end; + + uint bits; + int bitCount; + #endregion + + #region Constructors + /// + /// construct instance using default buffer size of 4096 + /// + public PendingBuffer() : this( 4096 ) + { + } + + /// + /// construct instance using specified buffer size + /// + /// + /// size to use for internal buffer + /// + public PendingBuffer(int bufferSize) + { + buffer_ = new byte[bufferSize]; + } + + #endregion + + /// + /// Clear internal state/buffers + /// + public void Reset() + { + start = end = bitCount = 0; + } + + /// + /// Write a byte to buffer + /// + /// + /// The value to write + /// + public void WriteByte(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + } + + /// + /// Write a short value to buffer LSB first + /// + /// + /// The value to write. + /// + public void WriteShort(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + buffer_[end++] = unchecked((byte) (value >> 8)); + } + + /// + /// write an integer LSB first + /// + /// The value to write. + public void WriteInt(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + buffer_[end++] = unchecked((byte) (value >> 8)); + buffer_[end++] = unchecked((byte) (value >> 16)); + buffer_[end++] = unchecked((byte) (value >> 24)); + } + + /// + /// Write a block of data to buffer + /// + /// data to write + /// offset of first byte to write + /// number of bytes to write + public void WriteBlock(byte[] block, int offset, int length) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + System.Array.Copy(block, offset, buffer_, end, length); + end += length; + } + + /// + /// The number of bits written to the buffer + /// + public int BitCount { + get { + return bitCount; + } + } + + /// + /// Align internal buffer on a byte boundary + /// + public void AlignToByte() + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + if (bitCount > 0) + { + buffer_[end++] = unchecked((byte) bits); + if (bitCount > 8) { + buffer_[end++] = unchecked((byte) (bits >> 8)); + } + } + bits = 0; + bitCount = 0; + } + + /// + /// Write bits to internal buffer + /// + /// source of bits + /// number of bits to write + public void WriteBits(int b, int count) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("writeBits("+b+","+count+")"); + // } +#endif + bits |= (uint)(b << bitCount); + bitCount += count; + if (bitCount >= 16) { + buffer_[end++] = unchecked((byte) bits); + buffer_[end++] = unchecked((byte) (bits >> 8)); + bits >>= 16; + bitCount -= 16; + } + } + + /// + /// Write a short value to internal buffer most significant byte first + /// + /// value to write + public void WriteShortMSB(int s) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) (s >> 8)); + buffer_[end++] = unchecked((byte) s); + } + + /// + /// Indicates if buffer has been flushed + /// + public bool IsFlushed { + get { + return end == 0; + } + } + + /// + /// Flushes the pending buffer into the given output array. If the + /// output array is to small, only a partial flush is done. + /// + /// The output array. + /// The offset into output array. + /// The maximum number of bytes to store. + /// The number of bytes flushed. + public int Flush(byte[] output, int offset, int length) + { + if (bitCount >= 8) { + buffer_[end++] = unchecked((byte) bits); + bits >>= 8; + bitCount -= 8; + } + + if (length > end - start) { + length = end - start; + System.Array.Copy(buffer_, start, output, offset, length); + start = 0; + end = 0; + } else { + System.Array.Copy(buffer_, start, output, offset, length); + start += length; + } + return length; + } + + /// + /// Convert internal buffer to byte array. + /// Buffer is empty on completion + /// + /// + /// The internal buffer contents converted to a byte array. + /// + public byte[] ToByteArray() + { + byte[] result = new byte[end - start]; + System.Array.Copy(buffer_, start, result, 0, result.Length); + start = 0; + end = 0; + return result; + } + } +} diff --git a/类库/Update/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs b/类库/Update/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs new file mode 100644 index 0000000..55bdb05 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -0,0 +1,602 @@ +// DeflaterOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support + +using System; +using System.IO; + +#if !NETCF_1_0 +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Encryption; +#endif + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + /// + /// A special stream deflating or compressing the bytes that are + /// written to it. It uses a Deflater to perform actual deflating.
+ /// Authors of the original java version : Tom Tromey, Jochen Hoenicke + ///
+ public class DeflaterOutputStream : Stream + { + #region Constructors + /// + /// Creates a new DeflaterOutputStream with a default Deflater and default buffer size. + /// + /// + /// the output stream where deflated output should be written. + /// + public DeflaterOutputStream(Stream baseOutputStream) + : this(baseOutputStream, new Deflater(), 512) + { + } + + /// + /// Creates a new DeflaterOutputStream with the given Deflater and + /// default buffer size. + /// + /// + /// the output stream where deflated output should be written. + /// + /// + /// the underlying deflater. + /// + public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater) + : this(baseOutputStream, deflater, 512) + { + } + + /// + /// Creates a new DeflaterOutputStream with the given Deflater and + /// buffer size. + /// + /// + /// The output stream where deflated output is written. + /// + /// + /// The underlying deflater to use + /// + /// + /// The buffer size in bytes to use when deflating (minimum value 512) + /// + /// + /// bufsize is less than or equal to zero. + /// + /// + /// baseOutputStream does not support writing + /// + /// + /// deflater instance is null + /// + public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int bufferSize) + { + if ( baseOutputStream == null ) { + throw new ArgumentNullException("baseOutputStream"); + } + + if (baseOutputStream.CanWrite == false) { + throw new ArgumentException("Must support writing", "baseOutputStream"); + } + + if (deflater == null) { + throw new ArgumentNullException("deflater"); + } + + if (bufferSize < 512) { + throw new ArgumentOutOfRangeException("bufferSize"); + } + + baseOutputStream_ = baseOutputStream; + buffer_ = new byte[bufferSize]; + deflater_ = deflater; + } + #endregion + + #region Public API + /// + /// Finishes the stream by calling finish() on the deflater. + /// + /// + /// Not all input is deflated + /// + public virtual void Finish() + { + deflater_.Finish(); + while (!deflater_.IsFinished) { + int len = deflater_.Deflate(buffer_, 0, buffer_.Length); + if (len <= 0) { + break; + } + +#if NETCF_1_0 + if ( keys != null ) { +#else + if (cryptoTransform_ != null) { +#endif + EncryptBlock(buffer_, 0, len); + } + + baseOutputStream_.Write(buffer_, 0, len); + } + + if (!deflater_.IsFinished) { + throw new SharpZipBaseException("Can't deflate all input?"); + } + + baseOutputStream_.Flush(); + +#if NETCF_1_0 + if ( keys != null ) { + keys = null; + } +#else + if (cryptoTransform_ != null) { +#if !NET_1_1 && !NETCF_2_0 + if (cryptoTransform_ is ZipAESTransform) { + AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode(); + } +#endif + cryptoTransform_.Dispose(); + cryptoTransform_ = null; + } +#endif + } + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner_; } + set { isStreamOwner_ = value; } + } + + /// + /// Allows client to determine if an entry can be patched after its added + /// + public bool CanPatchEntries { + get { + return baseOutputStream_.CanSeek; + } + } + + #endregion + + #region Encryption + + string password; + +#if NETCF_1_0 + uint[] keys; +#else + ICryptoTransform cryptoTransform_; + + /// + /// Returns the 10 byte AUTH CODE to be appended immediately following the AES data stream. + /// + protected byte[] AESAuthCode; +#endif + + /// + /// Get/set the password used for encryption. + /// + /// When set to null or if the password is empty no encryption is performed + public string Password { + get { + return password; + } + set { + if ( (value != null) && (value.Length == 0) ) { + password = null; + } else { + password = value; + } + } + } + + /// + /// Encrypt a block of data + /// + /// + /// Data to encrypt. NOTE the original contents of the buffer are lost + /// + /// + /// Offset of first byte in buffer to encrypt + /// + /// + /// Number of bytes in buffer to encrypt + /// + protected void EncryptBlock(byte[] buffer, int offset, int length) + { +#if NETCF_1_0 + for (int i = offset; i < offset + length; ++i) { + byte oldbyte = buffer[i]; + buffer[i] ^= EncryptByte(); + UpdateKeys(oldbyte); + } +#else + cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0); +#endif + } + + /// + /// Initializes encryption keys based on given . + /// + /// The password. + protected void InitializePassword(string password) + { +#if NETCF_1_0 + keys = new uint[] { + 0x12345678, + 0x23456789, + 0x34567890 + }; + + byte[] rawPassword = ZipConstants.ConvertToArray(password); + + for (int i = 0; i < rawPassword.Length; ++i) { + UpdateKeys((byte)rawPassword[i]); + } + +#else + PkzipClassicManaged pkManaged = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password)); + cryptoTransform_ = pkManaged.CreateEncryptor(key, null); +#endif + } + +#if !NET_1_1 && !NETCF_2_0 + /// + /// Initializes encryption keys based on given password. + /// + protected void InitializeAESPassword(ZipEntry entry, string rawPassword, + out byte[] salt, out byte[] pwdVerifier) { + salt = new byte[entry.AESSaltLen]; + // Salt needs to be cryptographically random, and unique per file + if (_aesRnd == null) + _aesRnd = new RNGCryptoServiceProvider(); + _aesRnd.GetBytes(salt); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true); + pwdVerifier = ((ZipAESTransform)cryptoTransform_).PwdVerifier; + } +#endif + +#if NETCF_1_0 + + /// + /// Encrypt a single byte + /// + /// + /// The encrypted value + /// + protected byte EncryptByte() + { + uint temp = ((keys[2] & 0xFFFF) | 2); + return (byte)((temp * (temp ^ 1)) >> 8); + } + + /// + /// Update encryption keys + /// + protected void UpdateKeys(byte ch) + { + keys[0] = Crc32.ComputeCrc32(keys[0], ch); + keys[1] = keys[1] + (byte)keys[0]; + keys[1] = keys[1] * 134775813 + 1; + keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24)); + } +#endif + + #endregion + + #region Deflation Support + /// + /// Deflates everything in the input buffers. This will call + /// def.deflate() until all bytes from the input buffers + /// are processed. + /// + protected void Deflate() + { + while (!deflater_.IsNeedingInput) + { + int deflateCount = deflater_.Deflate(buffer_, 0, buffer_.Length); + + if (deflateCount <= 0) { + break; + } +#if NETCF_1_0 + if (keys != null) +#else + if (cryptoTransform_ != null) +#endif + { + EncryptBlock(buffer_, 0, deflateCount); + } + + baseOutputStream_.Write(buffer_, 0, deflateCount); + } + + if (!deflater_.IsNeedingInput) { + throw new SharpZipBaseException("DeflaterOutputStream can't deflate all input?"); + } + } + #endregion + + #region Stream Overrides + /// + /// Gets value indicating stream can be read from + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Gets a value indicating if seeking is supported for this stream + /// This property always returns false + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Get value indicating if this stream supports writing + /// + public override bool CanWrite { + get { + return baseOutputStream_.CanWrite; + } + } + + /// + /// Get current length of stream + /// + public override long Length { + get { + return baseOutputStream_.Length; + } + } + + /// + /// Gets the current position within the stream. + /// + /// Any attempt to set position + public override long Position { + get { + return baseOutputStream_.Position; + } + set { + throw new NotSupportedException("Position property not supported"); + } + } + + /// + /// Sets the current position of this stream to the given value. Not supported by this class! + /// + /// The offset relative to the to seek. + /// The to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("DeflaterOutputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. Not supported by this class! + /// + /// The new stream length. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("DeflaterOutputStream SetLength not supported"); + } + + /// + /// Read a byte from stream advancing position by one + /// + /// The byte read cast to an int. THe value is -1 if at the end of the stream. + /// Any access + public override int ReadByte() + { + throw new NotSupportedException("DeflaterOutputStream ReadByte not supported"); + } + + /// + /// Read a block of bytes from stream + /// + /// The buffer to store read data in. + /// The offset to start storing at. + /// The maximum number of bytes to read. + /// The actual number of bytes read. Zero if end of stream is detected. + /// Any access + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("DeflaterOutputStream Read not supported"); + } + + /// + /// Asynchronous reads are not supported a NotSupportedException is always thrown + /// + /// The buffer to read into. + /// The offset to start storing data at. + /// The number of bytes to read + /// The async callback to use. + /// The state to use. + /// Returns an + /// Any access + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("DeflaterOutputStream BeginRead not currently supported"); + } + + /// + /// Asynchronous writes arent supported, a NotSupportedException is always thrown + /// + /// The buffer to write. + /// The offset to begin writing at. + /// The number of bytes to write. + /// The to use. + /// The state object. + /// Returns an IAsyncResult. + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("BeginWrite is not supported"); + } + + /// + /// Flushes the stream by calling Flush on the deflater and then + /// on the underlying stream. This ensures that all bytes are flushed. + /// + public override void Flush() + { + deflater_.Flush(); + Deflate(); + baseOutputStream_.Flush(); + } + + /// + /// Calls and closes the underlying + /// stream when is true. + /// + public override void Close() + { + if ( !isClosed_ ) { + isClosed_ = true; + + try { + Finish(); +#if NETCF_1_0 + keys=null; +#else + if ( cryptoTransform_ != null ) { + GetAuthCodeIfAES(); + cryptoTransform_.Dispose(); + cryptoTransform_ = null; + } +#endif + } + finally { + if( isStreamOwner_ ) { + baseOutputStream_.Close(); + } + } + } + } + + private void GetAuthCodeIfAES() { +#if !NET_1_1 && !NETCF_2_0 + if (cryptoTransform_ is ZipAESTransform) { + AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode(); + } +#endif + } + + /// + /// Writes a single byte to the compressed output stream. + /// + /// + /// The byte value. + /// + public override void WriteByte(byte value) + { + byte[] b = new byte[1]; + b[0] = value; + Write(b, 0, 1); + } + + /// + /// Writes bytes from an array to the compressed stream. + /// + /// + /// The byte array + /// + /// + /// The offset into the byte array where to start. + /// + /// + /// The number of bytes to write. + /// + public override void Write(byte[] buffer, int offset, int count) + { + deflater_.SetInput(buffer, offset, count); + Deflate(); + } + #endregion + + #region Instance Fields + /// + /// This buffer is used temporarily to retrieve the bytes from the + /// deflater and write them to the underlying output stream. + /// + byte[] buffer_; + + /// + /// The deflater which is used to deflate the stream. + /// + protected Deflater deflater_; + + /// + /// Base stream the deflater depends on. + /// + protected Stream baseOutputStream_; + + bool isClosed_; + + bool isStreamOwner_ = true; + #endregion + + #region Static Fields + +#if !NET_1_1 && !NETCF_2_0 + // Static to help ensure that multiple files within a zip will get different random salt + private static RNGCryptoServiceProvider _aesRnd; +#endif + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/Compression/Streams/InflaterInputStream.cs b/类库/Update/ZIP/Zip/Compression/Streams/InflaterInputStream.cs new file mode 100644 index 0000000..6699444 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/Streams/InflaterInputStream.cs @@ -0,0 +1,732 @@ +// InflaterInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 11-08-2009 GeoffHart T9121 Added Multi-member gzip support + +using System; +using System.IO; + +#if !NETCF_1_0 +using System.Security.Cryptography; +#endif + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// An input buffer customised for use by + /// + /// + /// The buffer supports decryption of incoming data. + /// + public class InflaterInputBuffer + { + #region Constructors + /// + /// Initialise a new instance of with a default buffer size + /// + /// The stream to buffer. + public InflaterInputBuffer(Stream stream) : this(stream , 4096) + { + } + + /// + /// Initialise a new instance of + /// + /// The stream to buffer. + /// The size to use for the buffer + /// A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB. + public InflaterInputBuffer(Stream stream, int bufferSize) + { + inputStream = stream; + if ( bufferSize < 1024 ) { + bufferSize = 1024; + } + rawData = new byte[bufferSize]; + clearText = rawData; + } + #endregion + + /// + /// Get the length of bytes bytes in the + /// + public int RawLength + { + get { + return rawLength; + } + } + + /// + /// Get the contents of the raw data buffer. + /// + /// This may contain encrypted data. + public byte[] RawData + { + get { + return rawData; + } + } + + /// + /// Get the number of useable bytes in + /// + public int ClearTextLength + { + get { + return clearTextLength; + } + } + + /// + /// Get the contents of the clear text buffer. + /// + public byte[] ClearText + { + get { + return clearText; + } + } + + /// + /// Get/set the number of bytes available + /// + public int Available + { + get { return available; } + set { available = value; } + } + + /// + /// Call passing the current clear text buffer contents. + /// + /// The inflater to set input for. + public void SetInflaterInput(Inflater inflater) + { + if ( available > 0 ) { + inflater.SetInput(clearText, clearTextLength - available, available); + available = 0; + } + } + + /// + /// Fill the buffer from the underlying input stream. + /// + public void Fill() + { + rawLength = 0; + int toRead = rawData.Length; + + while (toRead > 0) { + int count = inputStream.Read(rawData, rawLength, toRead); + if ( count <= 0 ) { + break; + } + rawLength += count; + toRead -= count; + } + +#if !NETCF_1_0 + if ( cryptoTransform != null ) { + clearTextLength = cryptoTransform.TransformBlock(rawData, 0, rawLength, clearText, 0); + } + else +#endif + { + clearTextLength = rawLength; + } + + available = clearTextLength; + } + + /// + /// Read a buffer directly from the input stream + /// + /// The buffer to fill + /// Returns the number of bytes read. + public int ReadRawBuffer(byte[] buffer) + { + return ReadRawBuffer(buffer, 0, buffer.Length); + } + + /// + /// Read a buffer directly from the input stream + /// + /// The buffer to read into + /// The offset to start reading data into. + /// The number of bytes to read. + /// Returns the number of bytes read. + public int ReadRawBuffer(byte[] outBuffer, int offset, int length) + { + if ( length < 0 ) { + throw new ArgumentOutOfRangeException("length"); + } + + int currentOffset = offset; + int currentLength = length; + + while ( currentLength > 0 ) { + if ( available <= 0 ) { + Fill(); + if (available <= 0) { + return 0; + } + } + int toCopy = Math.Min(currentLength, available); + System.Array.Copy(rawData, rawLength - (int)available, outBuffer, currentOffset, toCopy); + currentOffset += toCopy; + currentLength -= toCopy; + available -= toCopy; + } + return length; + } + + /// + /// Read clear text data from the input stream. + /// + /// The buffer to add data to. + /// The offset to start adding data at. + /// The number of bytes to read. + /// Returns the number of bytes actually read. + public int ReadClearTextBuffer(byte[] outBuffer, int offset, int length) + { + if ( length < 0 ) { + throw new ArgumentOutOfRangeException("length"); + } + + int currentOffset = offset; + int currentLength = length; + + while ( currentLength > 0 ) { + if ( available <= 0 ) { + Fill(); + if (available <= 0) { + return 0; + } + } + + int toCopy = Math.Min(currentLength, available); + Array.Copy(clearText, clearTextLength - (int)available, outBuffer, currentOffset, toCopy); + currentOffset += toCopy; + currentLength -= toCopy; + available -= toCopy; + } + return length; + } + + /// + /// Read a from the input stream. + /// + /// Returns the byte read. + public int ReadLeByte() + { + if (available <= 0) { + Fill(); + if (available <= 0) { + throw new ZipException("EOF in header"); + } + } + byte result = rawData[rawLength - available]; + available -= 1; + return result; + } + + /// + /// Read an in little endian byte order. + /// + /// The short value read case to an int. + public int ReadLeShort() + { + return ReadLeByte() | (ReadLeByte() << 8); + } + + /// + /// Read an in little endian byte order. + /// + /// The int value read. + public int ReadLeInt() + { + return ReadLeShort() | (ReadLeShort() << 16); + } + + /// + /// Read a in little endian byte order. + /// + /// The long value read. + public long ReadLeLong() + { + return (uint)ReadLeInt() | ((long)ReadLeInt() << 32); + } + +#if !NETCF_1_0 + /// + /// Get/set the to apply to any data. + /// + /// Set this value to null to have no transform applied. + public ICryptoTransform CryptoTransform + { + set { + cryptoTransform = value; + if ( cryptoTransform != null ) { + if ( rawData == clearText ) { + if ( internalClearText == null ) { + internalClearText = new byte[rawData.Length]; + } + clearText = internalClearText; + } + clearTextLength = rawLength; + if ( available > 0 ) { + cryptoTransform.TransformBlock(rawData, rawLength - available, available, clearText, rawLength - available); + } + } else { + clearText = rawData; + clearTextLength = rawLength; + } + } + } +#endif + + #region Instance Fields + int rawLength; + byte[] rawData; + + int clearTextLength; + byte[] clearText; +#if !NETCF_1_0 + byte[] internalClearText; +#endif + + int available; + +#if !NETCF_1_0 + ICryptoTransform cryptoTransform; +#endif + Stream inputStream; + #endregion + } + + /// + /// This filter stream is used to decompress data compressed using the "deflate" + /// format. The "deflate" format is described in RFC 1951. + /// + /// This stream may form the basis for other decompression filters, such + /// as the GZipInputStream. + /// + /// Author of the original java version : John Leuner. + /// + public class InflaterInputStream : Stream + { + #region Constructors + /// + /// Create an InflaterInputStream with the default decompressor + /// and a default buffer size of 4KB. + /// + /// + /// The InputStream to read bytes from + /// + public InflaterInputStream(Stream baseInputStream) + : this(baseInputStream, new Inflater(), 4096) + { + } + + /// + /// Create an InflaterInputStream with the specified decompressor + /// and a default buffer size of 4KB. + /// + /// + /// The source of input data + /// + /// + /// The decompressor used to decompress data read from baseInputStream + /// + public InflaterInputStream(Stream baseInputStream, Inflater inf) + : this(baseInputStream, inf, 4096) + { + } + + /// + /// Create an InflaterInputStream with the specified decompressor + /// and the specified buffer size. + /// + /// + /// The InputStream to read bytes from + /// + /// + /// The decompressor to use + /// + /// + /// Size of the buffer to use + /// + public InflaterInputStream(Stream baseInputStream, Inflater inflater, int bufferSize) + { + if (baseInputStream == null) { + throw new ArgumentNullException("baseInputStream"); + } + + if (inflater == null) { + throw new ArgumentNullException("inflater"); + } + + if (bufferSize <= 0) { + throw new ArgumentOutOfRangeException("bufferSize"); + } + + this.baseInputStream = baseInputStream; + this.inf = inflater; + + inputBuffer = new InflaterInputBuffer(baseInputStream, bufferSize); + } + + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + /// + /// The default value is true. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Skip specified number of bytes of uncompressed data + /// + /// + /// Number of bytes to skip + /// + /// + /// The number of bytes skipped, zero if the end of + /// stream has been reached + /// + /// + /// The number of bytes to skip is less than or equal to zero. + /// + public long Skip(long count) + { + if (count <= 0) { + throw new ArgumentOutOfRangeException("count"); + } + + // v0.80 Skip by seeking if underlying stream supports it... + if (baseInputStream.CanSeek) { + baseInputStream.Seek(count, SeekOrigin.Current); + return count; + } + else { + int length = 2048; + if (count < length) { + length = (int) count; + } + + byte[] tmp = new byte[length]; + int readCount = 1; + long toSkip = count; + + while ((toSkip > 0) && (readCount > 0) ) { + if (toSkip < length) { + length = (int)toSkip; + } + + readCount = baseInputStream.Read(tmp, 0, length); + toSkip -= readCount; + } + + return count - toSkip; + } + } + + /// + /// Clear any cryptographic state. + /// + protected void StopDecrypting() + { +#if !NETCF_1_0 + inputBuffer.CryptoTransform = null; +#endif + } + + /// + /// Returns 0 once the end of the stream (EOF) has been reached. + /// Otherwise returns 1. + /// + public virtual int Available + { + get { + return inf.IsFinished ? 0 : 1; + } + } + + /// + /// Fills the buffer with more data to decompress. + /// + /// + /// Stream ends early + /// + protected void Fill() + { + // Protect against redundant calls + if (inputBuffer.Available <= 0) { + inputBuffer.Fill(); + if (inputBuffer.Available <= 0) { + throw new SharpZipBaseException("Unexpected EOF"); + } + } + inputBuffer.SetInflaterInput(inf); + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return baseInputStream.CanRead; + } + } + + /// + /// Gets a value of false indicating seeking is not supported for this stream. + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value of false indicating that this stream is not writeable. + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// A value representing the length of the stream in bytes. + /// + public override long Length { + get { + return inputBuffer.RawLength; + } + } + + /// + /// The current position within the stream. + /// Throws a NotSupportedException when attempting to set the position + /// + /// Attempting to set the position + public override long Position { + get { + return baseInputStream.Position; + } + set { + throw new NotSupportedException("InflaterInputStream Position not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + baseInputStream.Flush(); + } + + /// + /// Sets the position within the current stream + /// Always throws a NotSupportedException + /// + /// The relative offset to seek to. + /// The defining where to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Seek not supported"); + } + + /// + /// Set the length of the current stream + /// Always throws a NotSupportedException + /// + /// The new length value for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("InflaterInputStream SetLength not supported"); + } + + /// + /// Writes a sequence of bytes to stream and advances the current position + /// This method always throws a NotSupportedException + /// + /// Thew buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("InflaterInputStream Write not supported"); + } + + /// + /// Writes one byte to the current stream and advances the current position + /// Always throws a NotSupportedException + /// + /// The byte to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("InflaterInputStream WriteByte not supported"); + } + + /// + /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. + /// + /// The buffer to write data from + /// Offset of first byte to write + /// The maximum number of bytes to write + /// The method to be called when the asynchronous write operation is completed + /// A user-provided object that distinguishes this particular asynchronous write request from other requests + /// An IAsyncResult that references the asynchronous write + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); + } + + /// + /// Closes the input stream. When + /// is true the underlying stream is also closed. + /// + public override void Close() + { + if ( !isClosed ) { + isClosed = true; + if ( isStreamOwner ) { + baseInputStream.Close(); + } + } + } + + /// + /// Reads decompressed data into the provided buffer byte array + /// + /// + /// The array to read and decompress data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of bytes to decompress + /// + /// The number of bytes read. Zero signals the end of stream + /// + /// Inflater needs a dictionary + /// + public override int Read(byte[] buffer, int offset, int count) + { + if (inf.IsNeedingDictionary) + { + throw new SharpZipBaseException("Need a dictionary"); + } + + int remainingBytes = count; + while (true) { + int bytesRead = inf.Inflate(buffer, offset, remainingBytes); + offset += bytesRead; + remainingBytes -= bytesRead; + + if (remainingBytes == 0 || inf.IsFinished) { + break; + } + + if ( inf.IsNeedingInput ) { + Fill(); + } + else if ( bytesRead == 0 ) { + throw new ZipException("Dont know what to do"); + } + } + return count - remainingBytes; + } + #endregion + + #region Instance Fields + /// + /// Decompressor for this stream + /// + protected Inflater inf; + + /// + /// Input buffer for this stream. + /// + protected InflaterInputBuffer inputBuffer; + + /// + /// Base stream the inflater reads from. + /// + private Stream baseInputStream; + + /// + /// The compressed size + /// + protected long csize; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + /// + /// Flag indicating wether this instance is designated the stream owner. + /// When closing if this flag is true the underlying stream is closed. + /// + bool isStreamOwner = true; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/Compression/Streams/OutputWindow.cs b/类库/Update/ZIP/Zip/Compression/Streams/OutputWindow.cs new file mode 100644 index 0000000..be828e2 --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/Streams/OutputWindow.cs @@ -0,0 +1,235 @@ +// OutputWindow.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// Contains the output from the Inflation process. + /// We need to have a window so that we can refer backwards into the output stream + /// to repeat stuff.
+ /// Author of the original java version : John Leuner + ///
+ public class OutputWindow + { + #region Constants + const int WindowSize = 1 << 15; + const int WindowMask = WindowSize - 1; + #endregion + + #region Instance Fields + byte[] window = new byte[WindowSize]; //The window is 2^15 bytes + int windowEnd; + int windowFilled; + #endregion + + /// + /// Write a byte to this output window + /// + /// value to write + /// + /// if window is full + /// + public void Write(int value) + { + if (windowFilled++ == WindowSize) { + throw new InvalidOperationException("Window full"); + } + window[windowEnd++] = (byte) value; + windowEnd &= WindowMask; + } + + + private void SlowRepeat(int repStart, int length, int distance) + { + while (length-- > 0) { + window[windowEnd++] = window[repStart++]; + windowEnd &= WindowMask; + repStart &= WindowMask; + } + } + + /// + /// Append a byte pattern already in the window itself + /// + /// length of pattern to copy + /// distance from end of window pattern occurs + /// + /// If the repeated data overflows the window + /// + public void Repeat(int length, int distance) + { + if ((windowFilled += length) > WindowSize) { + throw new InvalidOperationException("Window full"); + } + + int repStart = (windowEnd - distance) & WindowMask; + int border = WindowSize - length; + if ( (repStart <= border) && (windowEnd < border) ) { + if (length <= distance) { + System.Array.Copy(window, repStart, window, windowEnd, length); + windowEnd += length; + } else { + // We have to copy manually, since the repeat pattern overlaps. + while (length-- > 0) { + window[windowEnd++] = window[repStart++]; + } + } + } else { + SlowRepeat(repStart, length, distance); + } + } + + /// + /// Copy from input manipulator to internal window + /// + /// source of data + /// length of data to copy + /// the number of bytes copied + public int CopyStored(StreamManipulator input, int length) + { + length = Math.Min(Math.Min(length, WindowSize - windowFilled), input.AvailableBytes); + int copied; + + int tailLen = WindowSize - windowEnd; + if (length > tailLen) { + copied = input.CopyBytes(window, windowEnd, tailLen); + if (copied == tailLen) { + copied += input.CopyBytes(window, 0, length - tailLen); + } + } else { + copied = input.CopyBytes(window, windowEnd, length); + } + + windowEnd = (windowEnd + copied) & WindowMask; + windowFilled += copied; + return copied; + } + + /// + /// Copy dictionary to window + /// + /// source dictionary + /// offset of start in source dictionary + /// length of dictionary + /// + /// If window isnt empty + /// + public void CopyDict(byte[] dictionary, int offset, int length) + { + if ( dictionary == null ) { + throw new ArgumentNullException("dictionary"); + } + + if (windowFilled > 0) { + throw new InvalidOperationException(); + } + + if (length > WindowSize) { + offset += length - WindowSize; + length = WindowSize; + } + System.Array.Copy(dictionary, offset, window, 0, length); + windowEnd = length & WindowMask; + } + + /// + /// Get remaining unfilled space in window + /// + /// Number of bytes left in window + public int GetFreeSpace() + { + return WindowSize - windowFilled; + } + + /// + /// Get bytes available for output in window + /// + /// Number of bytes filled + public int GetAvailable() + { + return windowFilled; + } + + /// + /// Copy contents of window to output + /// + /// buffer to copy to + /// offset to start at + /// number of bytes to count + /// The number of bytes copied + /// + /// If a window underflow occurs + /// + public int CopyOutput(byte[] output, int offset, int len) + { + int copyEnd = windowEnd; + if (len > windowFilled) { + len = windowFilled; + } else { + copyEnd = (windowEnd - windowFilled + len) & WindowMask; + } + + int copied = len; + int tailLen = len - copyEnd; + + if (tailLen > 0) { + System.Array.Copy(window, WindowSize - tailLen, output, offset, tailLen); + offset += tailLen; + len = copyEnd; + } + System.Array.Copy(window, copyEnd - len, output, offset, len); + windowFilled -= copied; + if (windowFilled < 0) { + throw new InvalidOperationException(); + } + return copied; + } + + /// + /// Reset by clearing window so GetAvailable returns 0 + /// + public void Reset() + { + windowFilled = windowEnd = 0; + } + } +} diff --git a/类库/Update/ZIP/Zip/Compression/Streams/StreamManipulator.cs b/类库/Update/ZIP/Zip/Compression/Streams/StreamManipulator.cs new file mode 100644 index 0000000..ac57e1e --- /dev/null +++ b/类库/Update/ZIP/Zip/Compression/Streams/StreamManipulator.cs @@ -0,0 +1,297 @@ +// StreamManipulator.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// This class allows us to retrieve a specified number of bits from + /// the input buffer, as well as copy big byte blocks. + /// + /// It uses an int buffer to store up to 31 bits for direct + /// manipulation. This guarantees that we can get at least 16 bits, + /// but we only need at most 15, so this is all safe. + /// + /// There are some optimizations in this class, for example, you must + /// never peek more than 8 bits more than needed, and you must first + /// peek bits before you may drop them. This is not a general purpose + /// class but optimized for the behaviour of the Inflater. + /// + /// authors of the original java version : John Leuner, Jochen Hoenicke + /// + public class StreamManipulator + { + #region Constructors + /// + /// Constructs a default StreamManipulator with all buffers empty + /// + public StreamManipulator() + { + } + #endregion + + /// + /// Get the next sequence of bits but don't increase input pointer. bitCount must be + /// less or equal 16 and if this call succeeds, you must drop + /// at least n - 8 bits in the next call. + /// + /// The number of bits to peek. + /// + /// the value of the bits, or -1 if not enough bits available. */ + /// + public int PeekBits(int bitCount) + { + if (bitsInBuffer_ < bitCount) { + if (windowStart_ == windowEnd_) { + return -1; // ok + } + buffer_ |= (uint)((window_[windowStart_++] & 0xff | + (window_[windowStart_++] & 0xff) << 8) << bitsInBuffer_); + bitsInBuffer_ += 16; + } + return (int)(buffer_ & ((1 << bitCount) - 1)); + } + + /// + /// Drops the next n bits from the input. You should have called PeekBits + /// with a bigger or equal n before, to make sure that enough bits are in + /// the bit buffer. + /// + /// The number of bits to drop. + public void DropBits(int bitCount) + { + buffer_ >>= bitCount; + bitsInBuffer_ -= bitCount; + } + + /// + /// Gets the next n bits and increases input pointer. This is equivalent + /// to followed by , except for correct error handling. + /// + /// The number of bits to retrieve. + /// + /// the value of the bits, or -1 if not enough bits available. + /// + public int GetBits(int bitCount) + { + int bits = PeekBits(bitCount); + if (bits >= 0) { + DropBits(bitCount); + } + return bits; + } + + /// + /// Gets the number of bits available in the bit buffer. This must be + /// only called when a previous PeekBits() returned -1. + /// + /// + /// the number of bits available. + /// + public int AvailableBits { + get { + return bitsInBuffer_; + } + } + + /// + /// Gets the number of bytes available. + /// + /// + /// The number of bytes available. + /// + public int AvailableBytes { + get { + return windowEnd_ - windowStart_ + (bitsInBuffer_ >> 3); + } + } + + /// + /// Skips to the next byte boundary. + /// + public void SkipToByteBoundary() + { + buffer_ >>= (bitsInBuffer_ & 7); + bitsInBuffer_ &= ~7; + } + + /// + /// Returns true when SetInput can be called + /// + public bool IsNeedingInput { + get { + return windowStart_ == windowEnd_; + } + } + + /// + /// Copies bytes from input buffer to output buffer starting + /// at output[offset]. You have to make sure, that the buffer is + /// byte aligned. If not enough bytes are available, copies fewer + /// bytes. + /// + /// + /// The buffer to copy bytes to. + /// + /// + /// The offset in the buffer at which copying starts + /// + /// + /// The length to copy, 0 is allowed. + /// + /// + /// The number of bytes copied, 0 if no bytes were available. + /// + /// + /// Length is less than zero + /// + /// + /// Bit buffer isnt byte aligned + /// + public int CopyBytes(byte[] output, int offset, int length) + { + if (length < 0) { + throw new ArgumentOutOfRangeException("length"); + } + + if ((bitsInBuffer_ & 7) != 0) { + // bits_in_buffer may only be 0 or a multiple of 8 + throw new InvalidOperationException("Bit buffer is not byte aligned!"); + } + + int count = 0; + while ((bitsInBuffer_ > 0) && (length > 0)) { + output[offset++] = (byte) buffer_; + buffer_ >>= 8; + bitsInBuffer_ -= 8; + length--; + count++; + } + + if (length == 0) { + return count; + } + + int avail = windowEnd_ - windowStart_; + if (length > avail) { + length = avail; + } + System.Array.Copy(window_, windowStart_, output, offset, length); + windowStart_ += length; + + if (((windowStart_ - windowEnd_) & 1) != 0) { + // We always want an even number of bytes in input, see peekBits + buffer_ = (uint)(window_[windowStart_++] & 0xff); + bitsInBuffer_ = 8; + } + return count + length; + } + + /// + /// Resets state and empties internal buffers + /// + public void Reset() + { + buffer_ = 0; + windowStart_ = windowEnd_ = bitsInBuffer_ = 0; + } + + /// + /// Add more input for consumption. + /// Only call when IsNeedingInput returns true + /// + /// data to be input + /// offset of first byte of input + /// number of bytes of input to add. + public void SetInput(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if (windowStart_ < windowEnd_) { + throw new InvalidOperationException("Old input was not completely processed"); + } + + int end = offset + count; + + // We want to throw an ArrayIndexOutOfBoundsException early. + // Note the check also handles integer wrap around. + if ((offset > end) || (end > buffer.Length) ) { + throw new ArgumentOutOfRangeException("count"); + } + + if ((count & 1) != 0) { + // We always want an even number of bytes in input, see PeekBits + buffer_ |= (uint)((buffer[offset++] & 0xff) << bitsInBuffer_); + bitsInBuffer_ += 8; + } + + window_ = buffer; + windowStart_ = offset; + windowEnd_ = end; + } + + #region Instance Fields + private byte[] window_; + private int windowStart_; + private int windowEnd_; + + private uint buffer_; + private int bitsInBuffer_; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/FastZip.cs b/类库/Update/ZIP/Zip/FastZip.cs new file mode 100644 index 0000000..623eea0 --- /dev/null +++ b/类库/Update/ZIP/Zip/FastZip.cs @@ -0,0 +1,729 @@ +// FastZip.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// FastZipEvents supports all events applicable to FastZip operations. + /// + public class FastZipEvents + { + /// + /// Delegate to invoke when processing directories. + /// + public ProcessDirectoryHandler ProcessDirectory; + + /// + /// Delegate to invoke when processing files. + /// + public ProcessFileHandler ProcessFile; + + /// + /// Delegate to invoke during processing of files. + /// + public ProgressHandler Progress; + + /// + /// Delegate to invoke when processing for a file has been completed. + /// + public CompletedFileHandler CompletedFile; + + /// + /// Delegate to invoke when processing directory failures. + /// + public DirectoryFailureHandler DirectoryFailure; + + /// + /// Delegate to invoke when processing file failures. + /// + public FileFailureHandler FileFailure; + + /// + /// Raise the directory failure event. + /// + /// The directory causing the failure. + /// The exception for this event. + /// A boolean indicating if execution should continue or not. + public bool OnDirectoryFailure(string directory, Exception e) + { + bool result = false; + DirectoryFailureHandler handler = DirectoryFailure; + + if ( handler != null ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the file failure handler delegate. + /// + /// The file causing the failure. + /// The exception for this failure. + /// A boolean indicating if execution should continue or not. + public bool OnFileFailure(string file, Exception e) + { + FileFailureHandler handler = FileFailure; + bool result = (handler != null); + + if ( result ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(file, e); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the ProcessFile delegate. + /// + /// The file being processed. + /// A boolean indicating if execution should continue or not. + public bool OnProcessFile(string file) + { + bool result = true; + ProcessFileHandler handler = ProcessFile; + + if ( handler != null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the delegate + /// + /// The file whose processing has been completed. + /// A boolean indicating if execution should continue or not. + public bool OnCompletedFile(string file) + { + bool result = true; + CompletedFileHandler handler = CompletedFile; + if ( handler != null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the process directory delegate. + /// + /// The directory being processed. + /// Flag indicating if the directory has matching files as determined by the current filter. + /// A of true if the operation should continue; false otherwise. + public bool OnProcessDirectory(string directory, bool hasMatchingFiles) + { + bool result = true; + ProcessDirectoryHandler handler = ProcessDirectory; + if ( handler != null ) { + DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// The minimum timespan between events. + /// + /// The minimum period of time between events. + /// + /// The default interval is three seconds. + public TimeSpan ProgressInterval + { + get { return progressInterval_; } + set { progressInterval_ = value; } + } + + #region Instance Fields + TimeSpan progressInterval_ = TimeSpan.FromSeconds(3); + #endregion + } + + /// + /// FastZip provides facilities for creating and extracting zip files. + /// + public class FastZip + { + #region Enumerations + /// + /// Defines the desired handling when overwriting files during extraction. + /// + public enum Overwrite + { + /// + /// Prompt the user to confirm overwriting + /// + Prompt, + /// + /// Never overwrite files. + /// + Never, + /// + /// Always overwrite files. + /// + Always + } + #endregion + + #region Constructors + /// + /// Initialise a default instance of . + /// + public FastZip() + { + } + + /// + /// Initialise a new instance of + /// + /// The events to use during operations. + public FastZip(FastZipEvents events) + { + events_ = events; + } + #endregion + + #region Properties + /// + /// Get/set a value indicating wether empty directories should be created. + /// + public bool CreateEmptyDirectories + { + get { return createEmptyDirectories_; } + set { createEmptyDirectories_ = value; } + } + +#if !NETCF_1_0 + /// + /// Get / set the password value. + /// + public string Password + { + get { return password_; } + set { password_ = value; } + } +#endif + + /// + /// Get or set the active when creating Zip files. + /// + /// + public INameTransform NameTransform + { + get { return entryFactory_.NameTransform; } + set { + entryFactory_.NameTransform = value; + } + } + + /// + /// Get or set the active when creating Zip files. + /// + public IEntryFactory EntryFactory + { + get { return entryFactory_; } + set { + if ( value == null ) { + entryFactory_ = new ZipEntryFactory(); + } + else { + entryFactory_ = value; + } + } + } + + /// + /// Gets or sets the setting for Zip64 handling when writing. + /// + /// + /// The default value is dynamic which is not backwards compatible with old + /// programs and can cause problems with XP's built in compression which cant + /// read Zip64 archives. However it does avoid the situation were a large file + /// is added and cannot be completed correctly. + /// NOTE: Setting the size for entries before they are added is the best solution! + /// By default the EntryFactory used by FastZip will set fhe file size. + /// + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + /// + /// Get/set a value indicating wether file dates and times should + /// be restored when extracting files from an archive. + /// + /// The default value is false. + public bool RestoreDateTimeOnExtract + { + get { + return restoreDateTimeOnExtract_; + } + set { + restoreDateTimeOnExtract_ = value; + } + } + + /// + /// Get/set a value indicating wether file attributes should + /// be restored during extract operations + /// + public bool RestoreAttributesOnExtract + { + get { return restoreAttributesOnExtract_; } + set { restoreAttributesOnExtract_ = value; } + } + #endregion + + #region Delegates + /// + /// Delegate called when confirming overwriting of files. + /// + public delegate bool ConfirmOverwriteDelegate(string fileName); + #endregion + + #region CreateZip + /// + /// Create a zip file. + /// + /// The name of the zip file to create. + /// The directory to source files from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + /// The directory filter to apply. + public void CreateZip(string zipFileName, string sourceDirectory, + bool recurse, string fileFilter, string directoryFilter) + { + CreateZip(File.Create(zipFileName), sourceDirectory, recurse, fileFilter, directoryFilter); + } + + /// + /// Create a zip file/archive. + /// + /// The name of the zip file to create. + /// The directory to obtain files and directories from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + public void CreateZip(string zipFileName, string sourceDirectory, bool recurse, string fileFilter) + { + CreateZip(File.Create(zipFileName), sourceDirectory, recurse, fileFilter, null); + } + + /// + /// Create a zip archive sending output to the passed. + /// + /// The stream to write archive data to. + /// The directory to source files from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + /// The directory filter to apply. + /// The is closed after creation. + public void CreateZip(Stream outputStream, string sourceDirectory, bool recurse, string fileFilter, string directoryFilter) + { + NameTransform = new ZipNameTransform(sourceDirectory); + sourceDirectory_ = sourceDirectory; + + using ( outputStream_ = new ZipOutputStream(outputStream) ) { + +#if !NETCF_1_0 + if ( password_ != null ) { + outputStream_.Password = password_; + } +#endif + + outputStream_.UseZip64 = UseZip64; + FileSystemScanner scanner = new FileSystemScanner(fileFilter, directoryFilter); + scanner.ProcessFile += new ProcessFileHandler(ProcessFile); + if ( this.CreateEmptyDirectories ) { + scanner.ProcessDirectory += new ProcessDirectoryHandler(ProcessDirectory); + } + + if (events_ != null) { + if ( events_.FileFailure != null ) { + scanner.FileFailure += events_.FileFailure; + } + + if ( events_.DirectoryFailure != null ) { + scanner.DirectoryFailure += events_.DirectoryFailure; + } + } + + scanner.Scan(sourceDirectory, recurse); + } + } + + #endregion + + #region ExtractZip + /// + /// Extract the contents of a zip file. + /// + /// The zip file to extract from. + /// The directory to save extracted information in. + /// A filter to apply to files. + public void ExtractZip(string zipFileName, string targetDirectory, string fileFilter) + { + ExtractZip(zipFileName, targetDirectory, Overwrite.Always, null, fileFilter, null, restoreDateTimeOnExtract_); + } + + /// + /// Extract the contents of a zip file. + /// + /// The zip file to extract from. + /// The directory to save extracted information in. + /// The style of overwriting to apply. + /// A delegate to invoke when confirming overwriting. + /// A filter to apply to files. + /// A filter to apply to directories. + /// Flag indicating whether to restore the date and time for extracted files. + public void ExtractZip(string zipFileName, string targetDirectory, + Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate, + string fileFilter, string directoryFilter, bool restoreDateTime) + { + Stream inputStream = File.Open(zipFileName, FileMode.Open, FileAccess.Read, FileShare.Read); + ExtractZip(inputStream, targetDirectory, overwrite, confirmDelegate, fileFilter, directoryFilter, restoreDateTime, true); + } + + /// + /// Extract the contents of a zip file held in a stream. + /// + /// The seekable input stream containing the zip to extract from. + /// The directory to save extracted information in. + /// The style of overwriting to apply. + /// A delegate to invoke when confirming overwriting. + /// A filter to apply to files. + /// A filter to apply to directories. + /// Flag indicating whether to restore the date and time for extracted files. + /// Flag indicating whether the inputStream will be closed by this method. + public void ExtractZip(Stream inputStream, string targetDirectory, + Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate, + string fileFilter, string directoryFilter, bool restoreDateTime, + bool isStreamOwner) + { + if ((overwrite == Overwrite.Prompt) && (confirmDelegate == null)) { + throw new ArgumentNullException("confirmDelegate"); + } + + continueRunning_ = true; + overwrite_ = overwrite; + confirmDelegate_ = confirmDelegate; + extractNameTransform_ = new WindowsNameTransform(targetDirectory); + + fileFilter_ = new NameFilter(fileFilter); + directoryFilter_ = new NameFilter(directoryFilter); + restoreDateTimeOnExtract_ = restoreDateTime; + + using (zipFile_ = new ZipFile(inputStream)) { + +#if !NETCF_1_0 + if (password_ != null) { + zipFile_.Password = password_; + } +#endif + zipFile_.IsStreamOwner = isStreamOwner; + System.Collections.IEnumerator enumerator = zipFile_.GetEnumerator(); + while (continueRunning_ && enumerator.MoveNext()) { + ZipEntry entry = (ZipEntry)enumerator.Current; + if (entry.IsFile) + { + // TODO Path.GetDirectory can fail here on invalid characters. + if (directoryFilter_.IsMatch(Path.GetDirectoryName(entry.Name)) && fileFilter_.IsMatch(entry.Name)) { + ExtractEntry(entry); + } + } + else if (entry.IsDirectory) { + if (directoryFilter_.IsMatch(entry.Name) && CreateEmptyDirectories) { + ExtractEntry(entry); + } + } + else { + // Do nothing for volume labels etc... + } + } + } + } + #endregion + + #region Internal Processing + void ProcessDirectory(object sender, DirectoryEventArgs e) + { + if ( !e.HasMatchingFiles && CreateEmptyDirectories ) { + if ( events_ != null ) { + events_.OnProcessDirectory(e.Name, e.HasMatchingFiles); + } + + if ( e.ContinueRunning ) { + if (e.Name != sourceDirectory_) { + ZipEntry entry = entryFactory_.MakeDirectoryEntry(e.Name); + outputStream_.PutNextEntry(entry); + } + } + } + } + + void ProcessFile(object sender, ScanEventArgs e) + { + if ( (events_ != null) && (events_.ProcessFile != null) ) { + events_.ProcessFile(sender, e); + } + + if ( e.ContinueRunning ) { + try { + // The open below is equivalent to OpenRead which gaurantees that if opened the + // file will not be changed by subsequent openers, but precludes opening in some cases + // were it could succeed. + using (FileStream stream = File.Open(e.Name, FileMode.Open, FileAccess.Read, FileShare.Read)) { + ZipEntry entry = entryFactory_.MakeFileEntry(e.Name); + outputStream_.PutNextEntry(entry); + AddFileContents(e.Name, stream); + } + } + catch(Exception ex) { + if (events_ != null) { + continueRunning_ = events_.OnFileFailure(e.Name, ex); + } + else { + continueRunning_ = false; + throw; + } + } + } + } + + void AddFileContents(string name, Stream stream) + { + if( stream==null ) { + throw new ArgumentNullException("stream"); + } + + if( buffer_==null ) { + buffer_=new byte[4096]; + } + + if( (events_!=null)&&(events_.Progress!=null) ) { + StreamUtils.Copy(stream, outputStream_, buffer_, + events_.Progress, events_.ProgressInterval, this, name); + } + else { + StreamUtils.Copy(stream, outputStream_, buffer_); + } + + if( events_!=null ) { + continueRunning_=events_.OnCompletedFile(name); + } + } + + void ExtractFileEntry(ZipEntry entry, string targetName) + { + bool proceed = true; + if ( overwrite_ != Overwrite.Always ) { + if ( File.Exists(targetName) ) { + if ( (overwrite_ == Overwrite.Prompt) && (confirmDelegate_ != null) ) { + proceed = confirmDelegate_(targetName); + } + else { + proceed = false; + } + } + } + + if ( proceed ) { + if ( events_ != null ) { + continueRunning_ = events_.OnProcessFile(entry.Name); + } + + if ( continueRunning_ ) { + try { + using ( FileStream outputStream = File.Create(targetName) ) { + if ( buffer_ == null ) { + buffer_ = new byte[4096]; + } + if ((events_ != null) && (events_.Progress != null)) + { + StreamUtils.Copy(zipFile_.GetInputStream(entry), outputStream, buffer_, + events_.Progress, events_.ProgressInterval, this, entry.Name, entry.Size); + } + else + { + StreamUtils.Copy(zipFile_.GetInputStream(entry), outputStream, buffer_); + } + + if (events_ != null) { + continueRunning_ = events_.OnCompletedFile(entry.Name); + } + } + +#if !NETCF_1_0 && !NETCF_2_0 + if ( restoreDateTimeOnExtract_ ) { + File.SetLastWriteTime(targetName, entry.DateTime); + } + + if ( RestoreAttributesOnExtract && entry.IsDOSEntry && (entry.ExternalFileAttributes != -1)) { + FileAttributes fileAttributes = (FileAttributes) entry.ExternalFileAttributes; + // TODO: FastZip - Setting of other file attributes on extraction is a little trickier. + fileAttributes &= (FileAttributes.Archive | FileAttributes.Normal | FileAttributes.ReadOnly | FileAttributes.Hidden); + File.SetAttributes(targetName, fileAttributes); + } +#endif + } + catch(Exception ex) { + if ( events_ != null ) { + continueRunning_ = events_.OnFileFailure(targetName, ex); + } + else { + continueRunning_ = false; + throw; + } + } + } + } + } + + void ExtractEntry(ZipEntry entry) + { + bool doExtraction = entry.IsCompressionMethodSupported(); + string targetName = entry.Name; + + if ( doExtraction ) { + if ( entry.IsFile ) { + targetName = extractNameTransform_.TransformFile(targetName); + } + else if ( entry.IsDirectory ) { + targetName = extractNameTransform_.TransformDirectory(targetName); + } + + doExtraction = !((targetName == null) || (targetName.Length == 0)); + } + + // TODO: Fire delegate/throw exception were compression method not supported, or name is invalid? + + string dirName = null; + + if ( doExtraction ) { + if ( entry.IsDirectory ) { + dirName = targetName; + } + else { + dirName = Path.GetDirectoryName(Path.GetFullPath(targetName)); + } + } + + if ( doExtraction && !Directory.Exists(dirName) ) { + if ( !entry.IsDirectory || CreateEmptyDirectories ) { + try { + Directory.CreateDirectory(dirName); + } + catch (Exception ex) { + doExtraction = false; + if ( events_ != null ) { + if ( entry.IsDirectory ) { + continueRunning_ = events_.OnDirectoryFailure(targetName, ex); + } + else { + continueRunning_ = events_.OnFileFailure(targetName, ex); + } + } + else { + continueRunning_ = false; + throw; + } + } + } + } + + if ( doExtraction && entry.IsFile ) { + ExtractFileEntry(entry, targetName); + } + } + + static int MakeExternalAttributes(FileInfo info) + { + return (int)info.Attributes; + } + +#if NET_1_0 || NET_1_1 || NETCF_1_0 + static bool NameIsValid(string name) + { + return (name != null) && + (name.Length > 0) && + (name.IndexOfAny(Path.InvalidPathChars) < 0); + } +#else + static bool NameIsValid(string name) + { + return (name != null) && + (name.Length > 0) && + (name.IndexOfAny(Path.GetInvalidPathChars()) < 0); + } +#endif + #endregion + + #region Instance Fields + bool continueRunning_; + byte[] buffer_; + ZipOutputStream outputStream_; + ZipFile zipFile_; + string sourceDirectory_; + NameFilter fileFilter_; + NameFilter directoryFilter_; + Overwrite overwrite_; + ConfirmOverwriteDelegate confirmDelegate_; + + bool restoreDateTimeOnExtract_; + bool restoreAttributesOnExtract_; + bool createEmptyDirectories_; + FastZipEvents events_; + IEntryFactory entryFactory_ = new ZipEntryFactory(); + INameTransform extractNameTransform_; + UseZip64 useZip64_=UseZip64.Dynamic; + +#if !NETCF_1_0 + string password_; +#endif + + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/IEntryFactory.cs b/类库/Update/ZIP/Zip/IEntryFactory.cs new file mode 100644 index 0000000..f0bcaee --- /dev/null +++ b/类库/Update/ZIP/Zip/IEntryFactory.cs @@ -0,0 +1,82 @@ +// IEntryFactory.cs +// +// Copyright 2006 John Reilly +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// Defines factory methods for creating new values. + /// + public interface IEntryFactory + { + /// + /// Create a for a file given its name + /// + /// The name of the file to create an entry for. + /// Returns a file entry based on the passed. + ZipEntry MakeFileEntry(string fileName); + + /// + /// Create a for a file given its name + /// + /// The name of the file to create an entry for. + /// If true get details from the file system if the file exists. + /// Returns a file entry based on the passed. + ZipEntry MakeFileEntry(string fileName, bool useFileSystem); + + /// + /// Create a for a directory given its name + /// + /// The name of the directory to create an entry for. + /// Returns a directory entry based on the passed. + ZipEntry MakeDirectoryEntry(string directoryName); + + /// + /// Create a for a directory given its name + /// + /// The name of the directory to create an entry for. + /// If true get details from the file system for this directory if it exists. + /// Returns a directory entry based on the passed. + ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem); + + /// + /// Get/set the applicable. + /// + INameTransform NameTransform { get; set; } + } +} diff --git a/类库/Update/ZIP/Zip/WindowsNameTransform.cs b/类库/Update/ZIP/Zip/WindowsNameTransform.cs new file mode 100644 index 0000000..31430c6 --- /dev/null +++ b/类库/Update/ZIP/Zip/WindowsNameTransform.cs @@ -0,0 +1,272 @@ +// WindowsNameTransform.cs +// +// Copyright 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// WindowsNameTransform transforms names to windows compatible ones. + /// + public class WindowsNameTransform : INameTransform + { + /// + /// Initialises a new instance of + /// + /// + public WindowsNameTransform(string baseDirectory) + { + if ( baseDirectory == null ) { + throw new ArgumentNullException("baseDirectory", "Directory name is invalid"); + } + + BaseDirectory = baseDirectory; + } + + /// + /// Initialise a default instance of + /// + public WindowsNameTransform() + { + // Do nothing. + } + + /// + /// Gets or sets a value containing the target directory to prefix values with. + /// + public string BaseDirectory + { + get { return _baseDirectory; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + + _baseDirectory = Path.GetFullPath(value); + } + } + + /// + /// Gets or sets a value indicating wether paths on incoming values should be removed. + /// + public bool TrimIncomingPaths + { + get { return _trimIncomingPaths; } + set { _trimIncomingPaths = value; } + } + + /// + /// Transform a Zip directory name to a windows directory name. + /// + /// The directory name to transform. + /// The transformed name. + public string TransformDirectory(string name) + { + name = TransformFile(name); + if (name.Length > 0) { + while ( name.EndsWith(@"\") ) { + name = name.Remove(name.Length - 1, 1); + } + } + else { + throw new ZipException("Cannot have an empty directory name"); + } + return name; + } + + /// + /// Transform a Zip format file name to a windows style one. + /// + /// The file name to transform. + /// The transformed name. + public string TransformFile(string name) + { + if (name != null) { + name = MakeValidName(name, _replacementChar); + + if ( _trimIncomingPaths ) { + name = Path.GetFileName(name); + } + + // This may exceed windows length restrictions. + // Combine will throw a PathTooLongException in that case. + if ( _baseDirectory != null ) { + name = Path.Combine(_baseDirectory, name); + } + } + else { + name = string.Empty; + } + return name; + } + + /// + /// Test a name to see if it is a valid name for a windows filename as extracted from a Zip archive. + /// + /// The name to test. + /// Returns true if the name is a valid zip name; false otherwise. + /// The filename isnt a true windows path in some fundamental ways like no absolute paths, no rooted paths etc. + public static bool IsValidName(string name) + { + bool result = + (name != null) && + (name.Length <= MaxPath) && + (string.Compare(name, MakeValidName(name, '_')) == 0) + ; + + return result; + } + + /// + /// Initialise static class information. + /// + static WindowsNameTransform() + { + char[] invalidPathChars; + +#if NET_1_0 || NET_1_1 || NETCF_1_0 + invalidPathChars = Path.InvalidPathChars; +#else + invalidPathChars = Path.GetInvalidPathChars(); +#endif + int howMany = invalidPathChars.Length + 3; + + InvalidEntryChars = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length); + InvalidEntryChars[howMany - 1] = '*'; + InvalidEntryChars[howMany - 2] = '?'; + InvalidEntryChars[howMany - 3] = ':'; + } + + /// + /// Force a name to be valid by replacing invalid characters with a fixed value + /// + /// The name to make valid + /// The replacement character to use for any invalid characters. + /// Returns a valid name + public static string MakeValidName(string name, char replacement) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + name = WindowsPathUtils.DropPathRoot(name.Replace("/", @"\")); + + // Drop any leading slashes. + while ( (name.Length > 0) && (name[0] == '\\')) { + name = name.Remove(0, 1); + } + + // Drop any trailing slashes. + while ( (name.Length > 0) && (name[name.Length - 1] == '\\')) { + name = name.Remove(name.Length - 1, 1); + } + + // Convert consecutive \\ characters to \ + int index = name.IndexOf(@"\\"); + while (index >= 0) { + name = name.Remove(index, 1); + index = name.IndexOf(@"\\"); + } + + // Convert any invalid characters using the replacement one. + index = name.IndexOfAny(InvalidEntryChars); + if (index >= 0) { + StringBuilder builder = new StringBuilder(name); + + while (index >= 0 ) { + builder[index] = replacement; + + if (index >= name.Length) { + index = -1; + } + else { + index = name.IndexOfAny(InvalidEntryChars, index + 1); + } + } + name = builder.ToString(); + } + + // Check for names greater than MaxPath characters. + // TODO: Were is CLR version of MaxPath defined? Can't find it in Environment. + if ( name.Length > MaxPath ) { + throw new PathTooLongException(); + } + + return name; + } + + /// + /// Gets or set the character to replace invalid characters during transformations. + /// + public char Replacement + { + get { return _replacementChar; } + set { + for ( int i = 0; i < InvalidEntryChars.Length; ++i ) { + if ( InvalidEntryChars[i] == value ) { + throw new ArgumentException("invalid path character"); + } + } + + if ((value == '\\') || (value == '/')) { + throw new ArgumentException("invalid replacement character"); + } + + _replacementChar = value; + } + } + + /// + /// The maximum windows path name permitted. + /// + /// This may not valid for all windows systems - CE?, etc but I cant find the equivalent in the CLR. + const int MaxPath = 260; + + #region Instance Fields + string _baseDirectory; + bool _trimIncomingPaths; + char _replacementChar = '_'; + #endregion + + #region Class Fields + static readonly char[] InvalidEntryChars; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/ZipConstants.cs b/类库/Update/ZIP/Zip/ZipConstants.cs new file mode 100644 index 0000000..3a19c5f --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipConstants.cs @@ -0,0 +1,632 @@ +// ZipConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support + +using System; +using System.Text; +using System.Threading; + +#if NETCF_1_0 || NETCF_2_0 +using System.Globalization; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + + #region Enumerations + + /// + /// Determines how entries are tested to see if they should use Zip64 extensions or not. + /// + public enum UseZip64 + { + /// + /// Zip64 will not be forced on entries during processing. + /// + /// An entry can have this overridden if required + Off, + /// + /// Zip64 should always be used. + /// + On, + /// + /// #ZipLib will determine use based on entry values when added to archive. + /// + Dynamic, + } + + /// + /// The kind of compression used for an entry in an archive + /// + public enum CompressionMethod + { + /// + /// A direct copy of the file contents is held in the archive + /// + Stored = 0, + + /// + /// Common Zip compression method using a sliding dictionary + /// of up to 32KB and secondary compression from Huffman/Shannon-Fano trees + /// + Deflated = 8, + + /// + /// An extension to deflate with a 64KB window. Not supported by #Zip currently + /// + Deflate64 = 9, + + /// + /// BZip2 compression. Not supported by #Zip. + /// + BZip2 = 11, + + /// + /// WinZip special for AES encryption, Now supported by #Zip. + /// + WinZipAES = 99, + + } + + /// + /// Identifies the encryption algorithm used for an entry + /// + public enum EncryptionAlgorithm + { + /// + /// No encryption has been used. + /// + None = 0, + /// + /// Encrypted using PKZIP 2.0 or 'classic' encryption. + /// + PkzipClassic = 1, + /// + /// DES encryption has been used. + /// + Des = 0x6601, + /// + /// RCS encryption has been used for encryption. + /// + RC2 = 0x6602, + /// + /// Triple DES encryption with 168 bit keys has been used for this entry. + /// + TripleDes168 = 0x6603, + /// + /// Triple DES with 112 bit keys has been used for this entry. + /// + TripleDes112 = 0x6609, + /// + /// AES 128 has been used for encryption. + /// + Aes128 = 0x660e, + /// + /// AES 192 has been used for encryption. + /// + Aes192 = 0x660f, + /// + /// AES 256 has been used for encryption. + /// + Aes256 = 0x6610, + /// + /// RC2 corrected has been used for encryption. + /// + RC2Corrected = 0x6702, + /// + /// Blowfish has been used for encryption. + /// + Blowfish = 0x6720, + /// + /// Twofish has been used for encryption. + /// + Twofish = 0x6721, + /// + /// RC4 has been used for encryption. + /// + RC4 = 0x6801, + /// + /// An unknown algorithm has been used for encryption. + /// + Unknown = 0xffff + } + + /// + /// Defines the contents of the general bit flags field for an archive entry. + /// + [Flags] + public enum GeneralBitFlags : int + { + /// + /// Bit 0 if set indicates that the file is encrypted + /// + Encrypted = 0x0001, + /// + /// Bits 1 and 2 - Two bits defining the compression method (only for Method 6 Imploding and 8,9 Deflating) + /// + Method = 0x0006, + /// + /// Bit 3 if set indicates a trailing data desciptor is appended to the entry data + /// + Descriptor = 0x0008, + /// + /// Bit 4 is reserved for use with method 8 for enhanced deflation + /// + ReservedPKware4 = 0x0010, + /// + /// Bit 5 if set indicates the file contains Pkzip compressed patched data. + /// Requires version 2.7 or greater. + /// + Patched = 0x0020, + /// + /// Bit 6 if set indicates strong encryption has been used for this entry. + /// + StrongEncryption = 0x0040, + /// + /// Bit 7 is currently unused + /// + Unused7 = 0x0080, + /// + /// Bit 8 is currently unused + /// + Unused8 = 0x0100, + /// + /// Bit 9 is currently unused + /// + Unused9 = 0x0200, + /// + /// Bit 10 is currently unused + /// + Unused10 = 0x0400, + /// + /// Bit 11 if set indicates the filename and + /// comment fields for this file must be encoded using UTF-8. + /// + UnicodeText = 0x0800, + /// + /// Bit 12 is documented as being reserved by PKware for enhanced compression. + /// + EnhancedCompress = 0x1000, + /// + /// Bit 13 if set indicates that values in the local header are masked to hide + /// their actual values, and the central directory is encrypted. + /// + /// + /// Used when encrypting the central directory contents. + /// + HeaderMasked = 0x2000, + /// + /// Bit 14 is documented as being reserved for use by PKware + /// + ReservedPkware14 = 0x4000, + /// + /// Bit 15 is documented as being reserved for use by PKware + /// + ReservedPkware15 = 0x8000 + } + + #endregion + + /// + /// This class contains constants used for Zip format files + /// + public sealed class ZipConstants + { + #region Versions + /// + /// The version made by field for entries in the central header when created by this library + /// + /// + /// This is also the Zip version for the library when comparing against the version required to extract + /// for an entry. See . + /// + public const int VersionMadeBy = 51; // was 45 before AES + + /// + /// The version made by field for entries in the central header when created by this library + /// + /// + /// This is also the Zip version for the library when comparing against the version required to extract + /// for an entry. See ZipInputStream.CanDecompressEntry. + /// + [Obsolete("Use VersionMadeBy instead")] + public const int VERSION_MADE_BY = 51; + + /// + /// The minimum version required to support strong encryption + /// + public const int VersionStrongEncryption = 50; + + /// + /// The minimum version required to support strong encryption + /// + [Obsolete("Use VersionStrongEncryption instead")] + public const int VERSION_STRONG_ENCRYPTION = 50; + + /// + /// Version indicating AES encryption + /// + public const int VERSION_AES = 51; + + /// + /// The version required for Zip64 extensions (4.5 or higher) + /// + public const int VersionZip64 = 45; + #endregion + + #region Header Sizes + /// + /// Size of local entry header (excluding variable length fields at end) + /// + public const int LocalHeaderBaseSize = 30; + + /// + /// Size of local entry header (excluding variable length fields at end) + /// + [Obsolete("Use LocalHeaderBaseSize instead")] + public const int LOCHDR = 30; + + /// + /// Size of Zip64 data descriptor + /// + public const int Zip64DataDescriptorSize = 24; + + /// + /// Size of data descriptor + /// + public const int DataDescriptorSize = 16; + + /// + /// Size of data descriptor + /// + [Obsolete("Use DataDescriptorSize instead")] + public const int EXTHDR = 16; + + /// + /// Size of central header entry (excluding variable fields) + /// + public const int CentralHeaderBaseSize = 46; + + /// + /// Size of central header entry + /// + [Obsolete("Use CentralHeaderBaseSize instead")] + public const int CENHDR = 46; + + /// + /// Size of end of central record (excluding variable fields) + /// + public const int EndOfCentralRecordBaseSize = 22; + + /// + /// Size of end of central record (excluding variable fields) + /// + [Obsolete("Use EndOfCentralRecordBaseSize instead")] + public const int ENDHDR = 22; + + /// + /// Size of 'classic' cryptographic header stored before any entry data + /// + public const int CryptoHeaderSize = 12; + + /// + /// Size of cryptographic header stored before entry data + /// + [Obsolete("Use CryptoHeaderSize instead")] + public const int CRYPTO_HEADER_SIZE = 12; + #endregion + + #region Header Signatures + + /// + /// Signature for local entry header + /// + public const int LocalHeaderSignature = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); + + /// + /// Signature for local entry header + /// + [Obsolete("Use LocalHeaderSignature instead")] + public const int LOCSIG = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); + + /// + /// Signature for spanning entry + /// + public const int SpanningSignature = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for spanning entry + /// + [Obsolete("Use SpanningSignature instead")] + public const int SPANNINGSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for temporary spanning entry + /// + public const int SpanningTempSignature = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24); + + /// + /// Signature for temporary spanning entry + /// + [Obsolete("Use SpanningTempSignature instead")] + public const int SPANTEMPSIG = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24); + + /// + /// Signature for data descriptor + /// + /// + /// This is only used where the length, Crc, or compressed size isnt known when the + /// entry is created and the output stream doesnt support seeking. + /// The local entry cannot be 'patched' with the correct values in this case + /// so the values are recorded after the data prefixed by this header, as well as in the central directory. + /// + public const int DataDescriptorSignature = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for data descriptor + /// + /// + /// This is only used where the length, Crc, or compressed size isnt known when the + /// entry is created and the output stream doesnt support seeking. + /// The local entry cannot be 'patched' with the correct values in this case + /// so the values are recorded after the data prefixed by this header, as well as in the central directory. + /// + [Obsolete("Use DataDescriptorSignature instead")] + public const int EXTSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for central header + /// + [Obsolete("Use CentralHeaderSignature instead")] + public const int CENSIG = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); + + /// + /// Signature for central header + /// + public const int CentralHeaderSignature = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); + + /// + /// Signature for Zip64 central file header + /// + public const int Zip64CentralFileHeaderSignature = 'P' | ('K' << 8) | (6 << 16) | (6 << 24); + + /// + /// Signature for Zip64 central file header + /// + [Obsolete("Use Zip64CentralFileHeaderSignature instead")] + public const int CENSIG64 = 'P' | ('K' << 8) | (6 << 16) | (6 << 24); + + /// + /// Signature for Zip64 central directory locator + /// + public const int Zip64CentralDirLocatorSignature = 'P' | ('K' << 8) | (6 << 16) | (7 << 24); + + /// + /// Signature for archive extra data signature (were headers are encrypted). + /// + public const int ArchiveExtraDataSignature = 'P' | ('K' << 8) | (6 << 16) | (7 << 24); + + /// + /// Central header digitial signature + /// + public const int CentralHeaderDigitalSignature = 'P' | ('K' << 8) | (5 << 16) | (5 << 24); + + /// + /// Central header digitial signature + /// + [Obsolete("Use CentralHeaderDigitalSignaure instead")] + public const int CENDIGITALSIG = 'P' | ('K' << 8) | (5 << 16) | (5 << 24); + + /// + /// End of central directory record signature + /// + public const int EndOfCentralDirectorySignature = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); + + /// + /// End of central directory record signature + /// + [Obsolete("Use EndOfCentralDirectorySignature instead")] + public const int ENDSIG = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); + #endregion + +#if NETCF_1_0 || NETCF_2_0 + // This isnt so great but is better than nothing. + // Trying to work out an appropriate OEM code page would be good. + // 850 is a good default for english speakers particularly in Europe. + static int defaultCodePage = CultureInfo.CurrentCulture.TextInfo.ANSICodePage; +#else + static int defaultCodePage = Thread.CurrentThread.CurrentCulture.TextInfo.OEMCodePage; +#endif + + /// + /// Default encoding used for string conversion. 0 gives the default system OEM code page. + /// Dont use unicode encodings if you want to be Zip compatible! + /// Using the default code page isnt the full solution neccessarily + /// there are many variable factors, codepage 850 is often a good choice for + /// European users, however be careful about compatability. + /// + public static int DefaultCodePage { + get { + return defaultCodePage; + } + set { + defaultCodePage = value; + } + } + + /// + /// Convert a portion of a byte array to a string. + /// + /// + /// Data to convert to string + /// + /// + /// Number of bytes to convert starting from index 0 + /// + /// + /// data[0]..data[length - 1] converted to a string + /// + public static string ConvertToString(byte[] data, int count) + { + if ( data == null ) { + return string.Empty; + } + + return Encoding.GetEncoding(DefaultCodePage).GetString(data, 0, count); + } + + /// + /// Convert a byte array to string + /// + /// + /// Byte array to convert + /// + /// + /// dataconverted to a string + /// + public static string ConvertToString(byte[] data) + { + if ( data == null ) { + return string.Empty; + } + return ConvertToString(data, data.Length); + } + + /// + /// Convert a byte array to string + /// + /// The applicable general purpose bits flags + /// + /// Byte array to convert + /// + /// The number of bytes to convert. + /// + /// dataconverted to a string + /// + public static string ConvertToStringExt(int flags, byte[] data, int count) + { + if ( data == null ) { + return string.Empty; + } + + if ( (flags & (int)GeneralBitFlags.UnicodeText) != 0 ) { + return Encoding.UTF8.GetString(data, 0, count); + } + else { + return ConvertToString(data, count); + } + } + + /// + /// Convert a byte array to string + /// + /// + /// Byte array to convert + /// + /// The applicable general purpose bits flags + /// + /// dataconverted to a string + /// + public static string ConvertToStringExt(int flags, byte[] data) + { + if ( data == null ) { + return string.Empty; + } + + if ( (flags & (int)GeneralBitFlags.UnicodeText) != 0 ) { + return Encoding.UTF8.GetString(data, 0, data.Length); + } + else { + return ConvertToString(data, data.Length); + } + } + + /// + /// Convert a string to a byte array + /// + /// + /// String to convert to an array + /// + /// Converted array + public static byte[] ConvertToArray(string str) + { + if ( str == null ) { + return new byte[0]; + } + + return Encoding.GetEncoding(DefaultCodePage).GetBytes(str); + } + + /// + /// Convert a string to a byte array + /// + /// The applicable general purpose bits flags + /// + /// String to convert to an array + /// + /// Converted array + public static byte[] ConvertToArray(int flags, string str) + { + if (str == null) { + return new byte[0]; + } + + if ((flags & (int)GeneralBitFlags.UnicodeText) != 0) { + return Encoding.UTF8.GetBytes(str); + } + else { + return ConvertToArray(str); + } + } + + + /// + /// Initialise default instance of ZipConstants + /// + /// + /// Private to prevent instances being created. + /// + ZipConstants() + { + // Do nothing + } + } +} diff --git a/类库/Update/ZIP/Zip/ZipEntry.cs b/类库/Update/ZIP/Zip/ZipEntry.cs new file mode 100644 index 0000000..febbc20 --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipEntry.cs @@ -0,0 +1,1252 @@ +// ZipEntry.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support +// 02-02-2010 DavidPierson Changed NTFS Extra Data min length to 4 + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Defines known values for the property. + /// + public enum HostSystemID + { + /// + /// Host system = MSDOS + /// + Msdos = 0, + /// + /// Host system = Amiga + /// + Amiga = 1, + /// + /// Host system = Open VMS + /// + OpenVms = 2, + /// + /// Host system = Unix + /// + Unix = 3, + /// + /// Host system = VMCms + /// + VMCms = 4, + /// + /// Host system = Atari ST + /// + AtariST = 5, + /// + /// Host system = OS2 + /// + OS2 = 6, + /// + /// Host system = Macintosh + /// + Macintosh = 7, + /// + /// Host system = ZSystem + /// + ZSystem = 8, + /// + /// Host system = Cpm + /// + Cpm = 9, + /// + /// Host system = Windows NT + /// + WindowsNT = 10, + /// + /// Host system = MVS + /// + MVS = 11, + /// + /// Host system = VSE + /// + Vse = 12, + /// + /// Host system = Acorn RISC + /// + AcornRisc = 13, + /// + /// Host system = VFAT + /// + Vfat = 14, + /// + /// Host system = Alternate MVS + /// + AlternateMvs = 15, + /// + /// Host system = BEOS + /// + BeOS = 16, + /// + /// Host system = Tandem + /// + Tandem = 17, + /// + /// Host system = OS400 + /// + OS400 = 18, + /// + /// Host system = OSX + /// + OSX = 19, + /// + /// Host system = WinZIP AES + /// + WinZipAES = 99, + } + + /// + /// This class represents an entry in a zip archive. This can be a file + /// or a directory + /// ZipFile and ZipInputStream will give you instances of this class as + /// information about the members in an archive. ZipOutputStream + /// uses an instance of this class when creating an entry in a Zip file. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ public class ZipEntry : ICloneable + { + [Flags] + enum Known : byte + { + None = 0, + Size = 0x01, + CompressedSize = 0x02, + Crc = 0x04, + Time = 0x08, + ExternalAttributes = 0x10, + } + + #region Constructors + /// + /// Creates a zip entry with the given name. + /// + /// + /// The name for this entry. Can include directory components. + /// The convention for names is 'unix' style paths with relative names only. + /// There are with no device names and path elements are separated by '/' characters. + /// + /// + /// The name passed is null + /// + public ZipEntry(string name) + : this(name, 0, ZipConstants.VersionMadeBy, CompressionMethod.Deflated) + { + } + + /// + /// Creates a zip entry with the given name and version required to extract + /// + /// + /// The name for this entry. Can include directory components. + /// The convention for names is 'unix' style paths with no device names and + /// path elements separated by '/' characters. This is not enforced see CleanName + /// on how to ensure names are valid if this is desired. + /// + /// + /// The minimum 'feature version' required this entry + /// + /// + /// The name passed is null + /// + internal ZipEntry(string name, int versionRequiredToExtract) + : this(name, versionRequiredToExtract, ZipConstants.VersionMadeBy, + CompressionMethod.Deflated) + { + } + + /// + /// Initializes an entry with the given name and made by information + /// + /// Name for this entry + /// Version and HostSystem Information + /// Minimum required zip feature version required to extract this entry + /// Compression method for this entry. + /// + /// The name passed is null + /// + /// + /// versionRequiredToExtract should be 0 (auto-calculate) or > 10 + /// + /// + /// This constructor is used by the ZipFile class when reading from the central header + /// It is not generally useful, use the constructor specifying the name only. + /// + internal ZipEntry(string name, int versionRequiredToExtract, int madeByInfo, + CompressionMethod method) + { + if (name == null) { + throw new System.ArgumentNullException("name"); + } + + if ( name.Length > 0xffff ) { + throw new ArgumentException("Name is too long", "name"); + } + + if ( (versionRequiredToExtract != 0) && (versionRequiredToExtract < 10) ) { + throw new ArgumentOutOfRangeException("versionRequiredToExtract"); + } + + this.DateTime = System.DateTime.Now; + this.name = name; + this.versionMadeBy = (ushort)madeByInfo; + this.versionToExtract = (ushort)versionRequiredToExtract; + this.method = method; + } + + /// + /// Creates a deep copy of the given zip entry. + /// + /// + /// The entry to copy. + /// + [Obsolete("Use Clone instead")] + public ZipEntry(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + known = entry.known; + name = entry.name; + size = entry.size; + compressedSize = entry.compressedSize; + crc = entry.crc; + dosTime = entry.dosTime; + method = entry.method; + comment = entry.comment; + versionToExtract = entry.versionToExtract; + versionMadeBy = entry.versionMadeBy; + externalFileAttributes = entry.externalFileAttributes; + flags = entry.flags; + + zipFileIndex = entry.zipFileIndex; + offset = entry.offset; + + forceZip64_ = entry.forceZip64_; + + if ( entry.extra != null ) { + extra = new byte[entry.extra.Length]; + Array.Copy(entry.extra, 0, extra, 0, entry.extra.Length); + } + } + + #endregion + + /// + /// Get a value indicating wether the entry has a CRC value available. + /// + public bool HasCrc + { + get { + return (known & Known.Crc) != 0; + } + } + + /// + /// Get/Set flag indicating if entry is encrypted. + /// A simple helper routine to aid interpretation of flags + /// + /// This is an assistant that interprets the flags property. + public bool IsCrypted + { + get { + return (flags & 1) != 0; + } + set { + if (value) { + flags |= 1; + } + else { + flags &= ~1; + } + } + } + + /// + /// Get / set a flag indicating wether entry name and comment text are + /// encoded in unicode UTF8. + /// + /// This is an assistant that interprets the flags property. + public bool IsUnicodeText + { + get { + return ( flags & (int)GeneralBitFlags.UnicodeText ) != 0; + } + set { + if ( value ) { + flags |= (int)GeneralBitFlags.UnicodeText; + } + else { + flags &= ~(int)GeneralBitFlags.UnicodeText; + } + } + } + + /// + /// Value used during password checking for PKZIP 2.0 / 'classic' encryption. + /// + internal byte CryptoCheckValue + { + get { + return cryptoCheckValue_; + } + + set { + cryptoCheckValue_ = value; + } + } + + /// + /// Get/Set general purpose bit flag for entry + /// + /// + /// General purpose bit flag
+ ///
+ /// Bit 0: If set, indicates the file is encrypted
+ /// Bit 1-2 Only used for compression type 6 Imploding, and 8, 9 deflating
+ /// Imploding:
+ /// Bit 1 if set indicates an 8K sliding dictionary was used. If clear a 4k dictionary was used
+ /// Bit 2 if set indicates 3 Shannon-Fanno trees were used to encode the sliding dictionary, 2 otherwise
+ ///
+ /// Deflating:
+ /// Bit 2 Bit 1
+ /// 0 0 Normal compression was used
+ /// 0 1 Maximum compression was used
+ /// 1 0 Fast compression was used
+ /// 1 1 Super fast compression was used
+ ///
+ /// Bit 3: If set, the fields crc-32, compressed size + /// and uncompressed size are were not able to be written during zip file creation + /// The correct values are held in a data descriptor immediately following the compressed data.
+ /// Bit 4: Reserved for use by PKZIP for enhanced deflating
+ /// Bit 5: If set indicates the file contains compressed patch data
+ /// Bit 6: If set indicates strong encryption was used.
+ /// Bit 7-10: Unused or reserved
+ /// Bit 11: If set the name and comments for this entry are in unicode.
+ /// Bit 12-15: Unused or reserved
+ ///
+ /// + /// + public int Flags + { + get { + return flags; + } + set { + flags = value; + } + } + + /// + /// Get/Set index of this entry in Zip file + /// + /// This is only valid when the entry is part of a + public long ZipFileIndex + { + get { + return zipFileIndex; + } + set { + zipFileIndex = value; + } + } + + /// + /// Get/set offset for use in central header + /// + public long Offset + { + get { + return offset; + } + set { + offset = value; + } + } + + /// + /// Get/Set external file attributes as an integer. + /// The values of this are operating system dependant see + /// HostSystem for details + /// + public int ExternalFileAttributes + { + get { + if ((known & Known.ExternalAttributes) == 0) { + return -1; + } + else { + return externalFileAttributes; + } + } + + set { + externalFileAttributes = value; + known |= Known.ExternalAttributes; + } + } + + /// + /// Get the version made by for this entry or zero if unknown. + /// The value / 10 indicates the major version number, and + /// the value mod 10 is the minor version number + /// + public int VersionMadeBy + { + get { + return (versionMadeBy & 0xff); + } + } + + /// + /// Get a value indicating this entry is for a DOS/Windows system. + /// + public bool IsDOSEntry + { + get { + return ((HostSystem == ( int )HostSystemID.Msdos) || + (HostSystem == ( int )HostSystemID.WindowsNT)); + } + } + + /// + /// Test the external attributes for this to + /// see if the external attributes are Dos based (including WINNT and variants) + /// and match the values + /// + /// The attributes to test. + /// Returns true if the external attributes are known to be DOS/Windows + /// based and have the same attributes set as the value passed. + bool HasDosAttributes(int attributes) + { + bool result = false; + if ( (known & Known.ExternalAttributes) != 0 ) { + if ( ((HostSystem == (int)HostSystemID.Msdos) || + (HostSystem == (int)HostSystemID.WindowsNT)) && + (ExternalFileAttributes & attributes) == attributes) { + result = true; + } + } + return result; + } + + /// + /// Gets the compatability information for the external file attribute + /// If the external file attributes are compatible with MS-DOS and can be read + /// by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value + /// will be non-zero and identify the host system on which the attributes are compatible. + /// + /// + /// + /// The values for this as defined in the Zip File format and by others are shown below. The values are somewhat + /// misleading in some cases as they are not all used as shown. You should consult the relevant documentation + /// to obtain up to date and correct information. The modified appnote by the infozip group is + /// particularly helpful as it documents a lot of peculiarities. The document is however a little dated. + /// + /// 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + /// 1 - Amiga + /// 2 - OpenVMS + /// 3 - Unix + /// 4 - VM/CMS + /// 5 - Atari ST + /// 6 - OS/2 HPFS + /// 7 - Macintosh + /// 8 - Z-System + /// 9 - CP/M + /// 10 - Windows NTFS + /// 11 - MVS (OS/390 - Z/OS) + /// 12 - VSE + /// 13 - Acorn Risc + /// 14 - VFAT + /// 15 - Alternate MVS + /// 16 - BeOS + /// 17 - Tandem + /// 18 - OS/400 + /// 19 - OS/X (Darwin) + /// 99 - WinZip AES + /// remainder - unused + /// + /// + public int HostSystem + { + get { + return (versionMadeBy >> 8) & 0xff; + } + + set { + versionMadeBy &= 0xff; + versionMadeBy |= (ushort)((value & 0xff) << 8); + } + } + + /// + /// Get minimum Zip feature version required to extract this entry + /// + /// + /// Minimum features are defined as:
+ /// 1.0 - Default value
+ /// 1.1 - File is a volume label
+ /// 2.0 - File is a folder/directory
+ /// 2.0 - File is compressed using Deflate compression
+ /// 2.0 - File is encrypted using traditional encryption
+ /// 2.1 - File is compressed using Deflate64
+ /// 2.5 - File is compressed using PKWARE DCL Implode
+ /// 2.7 - File is a patch data set
+ /// 4.5 - File uses Zip64 format extensions
+ /// 4.6 - File is compressed using BZIP2 compression
+ /// 5.0 - File is encrypted using DES
+ /// 5.0 - File is encrypted using 3DES
+ /// 5.0 - File is encrypted using original RC2 encryption
+ /// 5.0 - File is encrypted using RC4 encryption
+ /// 5.1 - File is encrypted using AES encryption
+ /// 5.1 - File is encrypted using corrected RC2 encryption
+ /// 5.1 - File is encrypted using corrected RC2-64 encryption
+ /// 6.1 - File is encrypted using non-OAEP key wrapping
+ /// 6.2 - Central directory encryption (not confirmed yet)
+ /// 6.3 - File is compressed using LZMA
+ /// 6.3 - File is compressed using PPMD+
+ /// 6.3 - File is encrypted using Blowfish
+ /// 6.3 - File is encrypted using Twofish
+ ///
+ /// + public int Version + { + get { + // Return recorded version if known. + if (versionToExtract != 0) { + return versionToExtract; + } + else { + int result = 10; + if (AESKeySize > 0) { + result = ZipConstants.VERSION_AES; // Ver 5.1 = AES + } + else if (CentralHeaderRequiresZip64) { + result = ZipConstants.VersionZip64; + } + else if (CompressionMethod.Deflated == method) { + result = 20; + } + else if (IsDirectory == true) { + result = 20; + } + else if (IsCrypted == true) { + result = 20; + } + else if (HasDosAttributes(0x08) ) { + result = 11; + } + return result; + } + } + } + + /// + /// Get a value indicating whether this entry can be decompressed by the library. + /// + /// This is based on the and + /// wether the compression method is supported. + public bool CanDecompress + { + get { + return (Version <= ZipConstants.VersionMadeBy) && + ((Version == 10) || + (Version == 11) || + (Version == 20) || + (Version == 45) || + (Version == 51)) && + IsCompressionMethodSupported(); + } + } + + /// + /// Force this entry to be recorded using Zip64 extensions. + /// + public void ForceZip64() + { + forceZip64_ = true; + } + + /// + /// Get a value indicating wether Zip64 extensions were forced. + /// + /// A value of true if Zip64 extensions have been forced on; false if not. + public bool IsZip64Forced() + { + return forceZip64_; + } + + /// + /// Gets a value indicating if the entry requires Zip64 extensions + /// to store the full entry values. + /// + /// A value of true if a local header requires Zip64 extensions; false if not. + public bool LocalHeaderRequiresZip64 + { + get { + bool result = forceZip64_; + + if ( !result ) { + ulong trueCompressedSize = compressedSize; + + if ( (versionToExtract == 0) && IsCrypted ) { + trueCompressedSize += ZipConstants.CryptoHeaderSize; + } + + // TODO: A better estimation of the true limit based on compression overhead should be used + // to determine when an entry should use Zip64. + result = + ((this.size >= uint.MaxValue) || (trueCompressedSize >= uint.MaxValue)) && + ((versionToExtract == 0) || (versionToExtract >= ZipConstants.VersionZip64)); + } + + return result; + } + } + + /// + /// Get a value indicating wether the central directory entry requires Zip64 extensions to be stored. + /// + public bool CentralHeaderRequiresZip64 + { + get { + return LocalHeaderRequiresZip64 || (offset >= uint.MaxValue); + } + } + + /// + /// Get/Set DosTime value. + /// + /// + /// The MS-DOS date format can only represent dates between 1/1/1980 and 12/31/2107. + /// + public long DosTime + { + get { + if ((known & Known.Time) == 0) { + return 0; + } + else { + return dosTime; + } + } + + set { + unchecked { + dosTime = (uint)value; + } + + known |= Known.Time; + } + } + + /// + /// Gets/Sets the time of last modification of the entry. + /// + /// + /// The property is updated to match this as far as possible. + /// + public DateTime DateTime + { + get { + uint sec = Math.Min(59, 2 * (dosTime & 0x1f)); + uint min = Math.Min(59, (dosTime >> 5) & 0x3f); + uint hrs = Math.Min(23, (dosTime >> 11) & 0x1f); + uint mon = Math.Max(1, Math.Min(12, ((dosTime >> 21) & 0xf))); + uint year = ((dosTime >> 25) & 0x7f) + 1980; + int day = Math.Max(1, Math.Min(DateTime.DaysInMonth((int)year, (int)mon), (int)((dosTime >> 16) & 0x1f))); + return new System.DateTime((int)year, (int)mon, day, (int)hrs, (int)min, (int)sec); + } + + set { + uint year = (uint) value.Year; + uint month = (uint) value.Month; + uint day = (uint) value.Day; + uint hour = (uint) value.Hour; + uint minute = (uint) value.Minute; + uint second = (uint) value.Second; + + if ( year < 1980 ) { + year = 1980; + month = 1; + day = 1; + hour = 0; + minute = 0; + second = 0; + } + else if ( year > 2107 ) { + year = 2107; + month = 12; + day = 31; + hour = 23; + minute = 59; + second = 59; + } + + DosTime = ((year - 1980) & 0x7f) << 25 | + (month << 21) | + (day << 16) | + (hour << 11) | + (minute << 5) | + (second >> 1); + } + } + + /// + /// Returns the entry name. + /// + /// + /// The unix naming convention is followed. + /// Path components in the entry should always separated by forward slashes ('/'). + /// Dos device names like C: should also be removed. + /// See the class, or + /// + public string Name + { + get { + return name; + } + } + + /// + /// Gets/Sets the size of the uncompressed data. + /// + /// + /// The size or -1 if unknown. + /// + /// Setting the size before adding an entry to an archive can help + /// avoid compatability problems with some archivers which dont understand Zip64 extensions. + public long Size + { + get { + return (known & Known.Size) != 0 ? (long)size : -1L; + } + set { + this.size = (ulong)value; + this.known |= Known.Size; + } + } + + /// + /// Gets/Sets the size of the compressed data. + /// + /// + /// The compressed entry size or -1 if unknown. + /// + public long CompressedSize + { + get { + return (known & Known.CompressedSize) != 0 ? (long)compressedSize : -1L; + } + set { + this.compressedSize = (ulong)value; + this.known |= Known.CompressedSize; + } + } + + /// + /// Gets/Sets the crc of the uncompressed data. + /// + /// + /// Crc is not in the range 0..0xffffffffL + /// + /// + /// The crc value or -1 if unknown. + /// + public long Crc + { + get { + return (known & Known.Crc) != 0 ? crc & 0xffffffffL : -1L; + } + set { + if (((ulong)crc & 0xffffffff00000000L) != 0) { + throw new ArgumentOutOfRangeException("value"); + } + this.crc = (uint)value; + this.known |= Known.Crc; + } + } + + /// + /// Gets/Sets the compression method. Only Deflated and Stored are supported. + /// + /// + /// The compression method for this entry + /// + /// + /// + public CompressionMethod CompressionMethod { + get { + return method; + } + + set { + if ( !IsCompressionMethodSupported(value) ) { + throw new NotSupportedException("Compression method not supported"); + } + this.method = value; + } + } + + /// + /// Gets the compression method for outputting to the local or central header. + /// Returns same value as CompressionMethod except when AES encrypting, which + /// places 99 in the method and places the real method in the extra data. + /// + internal CompressionMethod CompressionMethodForHeader { + get { + return (AESKeySize > 0) ? CompressionMethod.WinZipAES : method; + } + } + + /// + /// Gets/Sets the extra data. + /// + /// + /// Extra data is longer than 64KB (0xffff) bytes. + /// + /// + /// Extra data or null if not set. + /// + public byte[] ExtraData { + + get { +// TODO: This is slightly safer but less efficient. Think about wether it should change. +// return (byte[]) extra.Clone(); + return extra; + } + + set { + if (value == null) { + extra = null; + } + else { + if (value.Length > 0xffff) { + throw new System.ArgumentOutOfRangeException("value"); + } + + extra = new byte[value.Length]; + Array.Copy(value, 0, extra, 0, value.Length); + } + } + } + + +#if !NET_1_1 && !NETCF_2_0 + /// + /// For AES encrypted files returns or sets the number of bits of encryption (128, 192 or 256). + /// When setting, only 0 (off), 128 or 256 is supported. + /// + public int AESKeySize { + get { + // the strength (1 or 3) is in the entry header + switch (_aesEncryptionStrength) { + case 0: return 0; // Not AES + case 1: return 128; + case 2: return 192; // Not used by WinZip + case 3: return 256; + default: throw new ZipException("Invalid AESEncryptionStrength " + _aesEncryptionStrength); + } + } + set { + switch (value) { + case 0: _aesEncryptionStrength = 0; break; + case 128: _aesEncryptionStrength = 1; break; + case 256: _aesEncryptionStrength = 3; break; + default: throw new ZipException("AESKeySize must be 0, 128 or 256: " + value); + } + } + } + + /// + /// AES Encryption strength for storage in extra data in entry header. + /// 1 is 128 bit, 2 is 192 bit, 3 is 256 bit. + /// + internal byte AESEncryptionStrength { + get { + return (byte)_aesEncryptionStrength; + } + } +#else + /// + /// AES unsupported prior to .NET 2.0 + /// + internal int AESKeySize; +#endif + + /// + /// Returns the length of the salt, in bytes + /// + internal int AESSaltLen { + get { + // Key size -> Salt length: 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. + return AESKeySize / 16; + } + } + + /// + /// Number of extra bytes required to hold the AES Header fields (Salt, Pwd verify, AuthCode) + /// + internal int AESOverheadSize { + get { + // File format: + // Bytes Content + // Variable Salt value + // 2 Password verification value + // Variable Encrypted file data + // 10 Authentication code + return 12 + AESSaltLen; + } + } + + /// + /// Process extra data fields updating the entry based on the contents. + /// + /// True if the extra data fields should be handled + /// for a local header, rather than for a central header. + /// + internal void ProcessExtraData(bool localHeader) + { + ZipExtraData extraData = new ZipExtraData(this.extra); + + if ( extraData.Find(0x0001) ) { + // Version required to extract is ignored here as some archivers dont set it correctly + // in theory it should be version 45 or higher + + // The recorded size will change but remember that this is zip64. + forceZip64_ = true; + + if ( extraData.ValueLength < 4 ) { + throw new ZipException("Extra data extended Zip64 information length is invalid"); + } + + if ( localHeader || (size == uint.MaxValue) ) { + size = (ulong)extraData.ReadLong(); + } + + if ( localHeader || (compressedSize == uint.MaxValue) ) { + compressedSize = (ulong)extraData.ReadLong(); + } + + if ( !localHeader && (offset == uint.MaxValue) ) { + offset = extraData.ReadLong(); + } + + // Disk number on which file starts is ignored + } + else { + if ( + ((versionToExtract & 0xff) >= ZipConstants.VersionZip64) && + ((size == uint.MaxValue) || (compressedSize == uint.MaxValue)) + ) { + throw new ZipException("Zip64 Extended information required but is missing."); + } + } + + if ( extraData.Find(10) ) { + // No room for any tags. + if ( extraData.ValueLength < 4 ) { + throw new ZipException("NTFS Extra data invalid"); + } + + extraData.ReadInt(); // Reserved + + while ( extraData.UnreadCount >= 4 ) { + int ntfsTag = extraData.ReadShort(); + int ntfsLength = extraData.ReadShort(); + if ( ntfsTag == 1 ) { + if ( ntfsLength >= 24 ) { + long lastModification = extraData.ReadLong(); + long lastAccess = extraData.ReadLong(); + long createTime = extraData.ReadLong(); + + DateTime = System.DateTime.FromFileTime(lastModification); + } + break; + } + else { + // An unknown NTFS tag so simply skip it. + extraData.Skip(ntfsLength); + } + } + } + else if ( extraData.Find(0x5455) ) { + int length = extraData.ValueLength; + int flags = extraData.ReadByte(); + + // Can include other times but these are ignored. Length of data should + // actually be 1 + 4 * no of bits in flags. + if ( ((flags & 1) != 0) && (length >= 5) ) { + int iTime = extraData.ReadInt(); + + DateTime = (new System.DateTime ( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime() + + new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime(); + } + } + if (method == CompressionMethod.WinZipAES) { + ProcessAESExtraData(extraData); + } + } + + // For AES the method in the entry is 99, and the real compression method is in the extradata + // + private void ProcessAESExtraData(ZipExtraData extraData) { + +#if !NET_1_1 && !NETCF_2_0 + if (extraData.Find(0x9901)) { + // Set version and flag for Zipfile.CreateAndInitDecryptionStream + versionToExtract = ZipConstants.VERSION_AES; // Ver 5.1 = AES see "Version" getter + // Set StrongEncryption flag for ZipFile.CreateAndInitDecryptionStream + Flags = Flags | (int)GeneralBitFlags.StrongEncryption; + // + // Unpack AES extra data field see http://www.winzip.com/aes_info.htm + int length = extraData.ValueLength; // Data size currently 7 + if (length < 7) + throw new ZipException("AES Extra Data Length " + length + " invalid."); + int ver = extraData.ReadShort(); // Version number (1=AE-1 2=AE-2) + int vendorId = extraData.ReadShort(); // 2-character vendor ID 0x4541 = "AE" + int encrStrength = extraData.ReadByte(); // encryption strength 1 = 128 2 = 192 3 = 256 + int actualCompress = extraData.ReadShort(); // The actual compression method used to compress the file + _aesVer = ver; + _aesEncryptionStrength = encrStrength; + method = (CompressionMethod)actualCompress; + } else + throw new ZipException("AES Extra Data missing"); +#else + throw new ZipException("AES unsupported"); +#endif + } + + /// + /// Gets/Sets the entry comment. + /// + /// + /// If comment is longer than 0xffff. + /// + /// + /// The comment or null if not set. + /// + /// + /// A comment is only available for entries when read via the class. + /// The class doesnt have the comment data available. + /// + public string Comment { + get { + return comment; + } + set { + // This test is strictly incorrect as the length is in characters + // while the storage limit is in bytes. + // While the test is partially correct in that a comment of this length or greater + // is definitely invalid, shorter comments may also have an invalid length + // where there are multi-byte characters + // The full test is not possible here however as the code page to apply conversions with + // isnt available. + if ( (value != null) && (value.Length > 0xffff) ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "cannot exceed 65535"); +#endif + } + + comment = value; + } + } + + /// + /// Gets a value indicating if the entry is a directory. + /// however. + /// + /// + /// A directory is determined by an entry name with a trailing slash '/'. + /// The external file attributes can also indicate an entry is for a directory. + /// Currently only dos/windows attributes are tested in this manner. + /// The trailing slash convention should always be followed. + /// + public bool IsDirectory + { + get { + int nameLength = name.Length; + bool result = + ((nameLength > 0) && + ((name[nameLength - 1] == '/') || (name[nameLength - 1] == '\\'))) || + HasDosAttributes(16) + ; + return result; + } + } + + /// + /// Get a value of true if the entry appears to be a file; false otherwise + /// + /// + /// This only takes account of DOS/Windows attributes. Other operating systems are ignored. + /// For linux and others the result may be incorrect. + /// + public bool IsFile + { + get { + return !IsDirectory && !HasDosAttributes(8); + } + } + + /// + /// Test entry to see if data can be extracted. + /// + /// Returns true if data can be extracted for this entry; false otherwise. + public bool IsCompressionMethodSupported() + { + return IsCompressionMethodSupported(CompressionMethod); + } + + #region ICloneable Members + /// + /// Creates a copy of this zip entry. + /// + /// An that is a copy of the current instance. + public object Clone() + { + ZipEntry result = (ZipEntry)this.MemberwiseClone(); + + // Ensure extra data is unique if it exists. + if ( extra != null ) { + result.extra = new byte[extra.Length]; + Array.Copy(extra, 0, result.extra, 0, extra.Length); + } + + return result; + } + + #endregion + + /// + /// Gets a string representation of this ZipEntry. + /// + /// A readable textual representation of this + public override string ToString() + { + return name; + } + + /// + /// Test a compression method to see if this library + /// supports extracting data compressed with that method + /// + /// The compression method to test. + /// Returns true if the compression method is supported; false otherwise + public static bool IsCompressionMethodSupported(CompressionMethod method) + { + return + ( method == CompressionMethod.Deflated ) || + ( method == CompressionMethod.Stored ); + } + + /// + /// Cleans a name making it conform to Zip file conventions. + /// Devices names ('c:\') and UNC share names ('\\server\share') are removed + /// and forward slashes ('\') are converted to back slashes ('/'). + /// Names are made relative by trimming leading slashes which is compatible + /// with the ZIP naming convention. + /// + /// The name to clean + /// The 'cleaned' name. + /// + /// The Zip name transform class is more flexible. + /// + public static string CleanName(string name) + { + if (name == null) { + return string.Empty; + } + + if (Path.IsPathRooted(name) == true) { + // NOTE: + // for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt + name = name.Substring(Path.GetPathRoot(name).Length); + } + + name = name.Replace(@"\", "/"); + + while ( (name.Length > 0) && (name[0] == '/')) { + name = name.Remove(0, 1); + } + return name; + } + + #region Instance Fields + Known known; + int externalFileAttributes = -1; // contains external attributes (O/S dependant) + + ushort versionMadeBy; // Contains host system and version information + // only relevant for central header entries + + string name; + ulong size; + ulong compressedSize; + ushort versionToExtract; // Version required to extract (library handles <= 2.0) + uint crc; + uint dosTime; + + CompressionMethod method = CompressionMethod.Deflated; + byte[] extra; + string comment; + + int flags; // general purpose bit flags + + long zipFileIndex = -1; // used by ZipFile + long offset; // used by ZipFile and ZipOutputStream + + bool forceZip64_; + byte cryptoCheckValue_; +#if !NET_1_1 && !NETCF_2_0 + int _aesVer; // Version number (2 = AE-2 ?). Assigned but not used. + int _aesEncryptionStrength; // Encryption strength 1 = 128 2 = 192 3 = 256 +#endif + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/ZipEntryFactory.cs b/类库/Update/ZIP/Zip/ZipEntryFactory.cs new file mode 100644 index 0000000..164a80e --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipEntryFactory.cs @@ -0,0 +1,413 @@ +// ZipEntryFactory.cs +// +// Copyright 2006 John Reilly +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// Basic implementation of + /// + public class ZipEntryFactory : IEntryFactory + { + #region Enumerations + /// + /// Defines the possible values to be used for the . + /// + public enum TimeSetting + { + /// + /// Use the recorded LastWriteTime value for the file. + /// + LastWriteTime, + /// + /// Use the recorded LastWriteTimeUtc value for the file + /// + LastWriteTimeUtc, + /// + /// Use the recorded CreateTime value for the file. + /// + CreateTime, + /// + /// Use the recorded CreateTimeUtc value for the file. + /// + CreateTimeUtc, + /// + /// Use the recorded LastAccessTime value for the file. + /// + LastAccessTime, + /// + /// Use the recorded LastAccessTimeUtc value for the file. + /// + LastAccessTimeUtc, + /// + /// Use a fixed value. + /// + /// The actual value used can be + /// specified via the constructor or + /// using the with the setting set + /// to which will use the when this class was constructed. + /// The property can also be used to set this value. + Fixed, + } + #endregion + + #region Constructors + /// + /// Initialise a new instance of the class. + /// + /// A default , and the LastWriteTime for files is used. + public ZipEntryFactory() + { + nameTransform_ = new ZipNameTransform(); + } + + /// + /// Initialise a new instance of using the specified + /// + /// The time setting to use when creating Zip entries. + public ZipEntryFactory(TimeSetting timeSetting) + { + timeSetting_ = timeSetting; + nameTransform_ = new ZipNameTransform(); + } + + /// + /// Initialise a new instance of using the specified + /// + /// The time to set all values to. + public ZipEntryFactory(DateTime time) + { + timeSetting_ = TimeSetting.Fixed; + FixedDateTime = time; + nameTransform_ = new ZipNameTransform(); + } + + #endregion + + #region Properties + /// + /// Get / set the to be used when creating new values. + /// + /// + /// Setting this property to null will cause a default name transform to be used. + /// + public INameTransform NameTransform + { + get { return nameTransform_; } + set + { + if (value == null) { + nameTransform_ = new ZipNameTransform(); + } + else { + nameTransform_ = value; + } + } + } + + /// + /// Get / set the in use. + /// + public TimeSetting Setting + { + get { return timeSetting_; } + set { timeSetting_ = value; } + } + + /// + /// Get / set the value to use when is set to + /// + public DateTime FixedDateTime + { + get { return fixedDateTime_; } + set + { + if (value.Year < 1970) { + throw new ArgumentException("Value is too old to be valid", "value"); + } + fixedDateTime_ = value; + } + } + + /// + /// A bitmask defining the attributes to be retrieved from the actual file. + /// + /// The default is to get all possible attributes from the actual file. + public int GetAttributes + { + get { return getAttributes_; } + set { getAttributes_ = value; } + } + + /// + /// A bitmask defining which attributes are to be set on. + /// + /// By default no attributes are set on. + public int SetAttributes + { + get { return setAttributes_; } + set { setAttributes_ = value; } + } + + /// + /// Get set a value indicating wether unidoce text should be set on. + /// + public bool IsUnicodeText + { + get { return isUnicodeText_; } + set { isUnicodeText_ = value; } + } + + #endregion + + #region IEntryFactory Members + + /// + /// Make a new for a file. + /// + /// The name of the file to create a new entry for. + /// Returns a new based on the . + public ZipEntry MakeFileEntry(string fileName) + { + return MakeFileEntry(fileName, true); + } + + /// + /// Make a new from a name. + /// + /// The name of the file to create a new entry for. + /// If true entry detail is retrieved from the file system if the file exists. + /// Returns a new based on the . + public ZipEntry MakeFileEntry(string fileName, bool useFileSystem) + { + ZipEntry result = new ZipEntry(nameTransform_.TransformFile(fileName)); + result.IsUnicodeText = isUnicodeText_; + + int externalAttributes = 0; + bool useAttributes = (setAttributes_ != 0); + + FileInfo fi = null; + if (useFileSystem) + { + fi = new FileInfo(fileName); + } + + if ((fi != null) && fi.Exists) + { + switch (timeSetting_) + { + case TimeSetting.CreateTime: + result.DateTime = fi.CreationTime; + break; + + case TimeSetting.CreateTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.CreationTime.ToUniversalTime(); +#else + result.DateTime = fi.CreationTimeUtc; +#endif + break; + + case TimeSetting.LastAccessTime: + result.DateTime = fi.LastAccessTime; + break; + + case TimeSetting.LastAccessTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.LastAccessTime.ToUniversalTime(); +#else + result.DateTime = fi.LastAccessTimeUtc; +#endif + break; + + case TimeSetting.LastWriteTime: + result.DateTime = fi.LastWriteTime; + break; + + case TimeSetting.LastWriteTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.LastWriteTime.ToUniversalTime(); +#else + result.DateTime = fi.LastWriteTimeUtc; +#endif + break; + + case TimeSetting.Fixed: + result.DateTime = fixedDateTime_; + break; + + default: + throw new ZipException("Unhandled time setting in MakeFileEntry"); + } + + result.Size = fi.Length; + + useAttributes = true; + externalAttributes = ((int)fi.Attributes & getAttributes_); + } + else + { + if (timeSetting_ == TimeSetting.Fixed) + { + result.DateTime = fixedDateTime_; + } + } + + if (useAttributes) + { + externalAttributes |= setAttributes_; + result.ExternalFileAttributes = externalAttributes; + } + + return result; + } + + /// + /// Make a new for a directory. + /// + /// The raw untransformed name for the new directory + /// Returns a new representing a directory. + public ZipEntry MakeDirectoryEntry(string directoryName) + { + return MakeDirectoryEntry(directoryName, true); + } + + /// + /// Make a new for a directory. + /// + /// The raw untransformed name for the new directory + /// If true entry detail is retrieved from the file system if the file exists. + /// Returns a new representing a directory. + public ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem) + { + + ZipEntry result = new ZipEntry(nameTransform_.TransformDirectory(directoryName)); + result.IsUnicodeText = isUnicodeText_; + result.Size = 0; + + int externalAttributes = 0; + + DirectoryInfo di = null; + + if (useFileSystem) + { + di = new DirectoryInfo(directoryName); + } + + + if ((di != null) && di.Exists) + { + switch (timeSetting_) + { + case TimeSetting.CreateTime: + result.DateTime = di.CreationTime; + break; + + case TimeSetting.CreateTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.CreationTime.ToUniversalTime(); +#else + result.DateTime = di.CreationTimeUtc; +#endif + break; + + case TimeSetting.LastAccessTime: + result.DateTime = di.LastAccessTime; + break; + + case TimeSetting.LastAccessTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.LastAccessTime.ToUniversalTime(); +#else + result.DateTime = di.LastAccessTimeUtc; +#endif + break; + + case TimeSetting.LastWriteTime: + result.DateTime = di.LastWriteTime; + break; + + case TimeSetting.LastWriteTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.LastWriteTime.ToUniversalTime(); +#else + result.DateTime = di.LastWriteTimeUtc; +#endif + break; + + case TimeSetting.Fixed: + result.DateTime = fixedDateTime_; + break; + + default: + throw new ZipException("Unhandled time setting in MakeDirectoryEntry"); + } + + externalAttributes = ((int)di.Attributes & getAttributes_); + } + else + { + if (timeSetting_ == TimeSetting.Fixed) + { + result.DateTime = fixedDateTime_; + } + } + + // Always set directory attribute on. + externalAttributes |= (setAttributes_ | 16); + result.ExternalFileAttributes = externalAttributes; + + return result; + } + + #endregion + + #region Instance Fields + INameTransform nameTransform_; + DateTime fixedDateTime_ = DateTime.Now; + TimeSetting timeSetting_; + bool isUnicodeText_; + + int getAttributes_ = -1; + int setAttributes_; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/ZipException.cs b/类库/Update/ZIP/Zip/ZipException.cs new file mode 100644 index 0000000..1cf4f16 --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipException.cs @@ -0,0 +1,94 @@ +// ZipException.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Represents exception conditions specific to Zip archive handling + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class ZipException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected ZipException(SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } +#endif + + /// + /// Initializes a new instance of the ZipException class. + /// + public ZipException() + { + } + + /// + /// Initializes a new instance of the ZipException class with a specified error message. + /// + /// The error message that explains the reason for the exception. + public ZipException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of ZipException. + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public ZipException(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/Update/ZIP/Zip/ZipExtraData.cs b/类库/Update/ZIP/Zip/ZipExtraData.cs new file mode 100644 index 0000000..aaeb0a6 --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipExtraData.cs @@ -0,0 +1,987 @@ +// +// ZipExtraData.cs +// +// Copyright 2004-2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Zip +{ + // TODO: Sort out wether tagged data is useful and what a good implementation might look like. + // Its just a sketch of an idea at the moment. + + /// + /// ExtraData tagged value interface. + /// + public interface ITaggedData + { + /// + /// Get the ID for this tagged data value. + /// + short TagID { get; } + + /// + /// Set the contents of this instance from the data passed. + /// + /// The data to extract contents from. + /// The offset to begin extracting data from. + /// The number of bytes to extract. + void SetData(byte[] data, int offset, int count); + + /// + /// Get the data representing this instance. + /// + /// Returns the data for this instance. + byte[] GetData(); + } + + /// + /// A raw binary tagged value + /// + public class RawTaggedData : ITaggedData + { + /// + /// Initialise a new instance. + /// + /// The tag ID. + public RawTaggedData(short tag) + { + _tag = tag; + } + + #region ITaggedData Members + + /// + /// Get the ID for this tagged data value. + /// + public short TagID + { + get { return _tag; } + set { _tag = value; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int offset, int count) + { + if( data==null ) + { + throw new ArgumentNullException("data"); + } + + _data=new byte[count]; + Array.Copy(data, offset, _data, 0, count); + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + return _data; + } + + #endregion + + /// + /// Get /set the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] Data + { + get { return _data; } + set { _data=value; } + } + + #region Instance Fields + /// + /// The tag ID for this instance. + /// + short _tag; + + byte[] _data; + #endregion + } + + /// + /// Class representing extended unix date time values. + /// + public class ExtendedUnixData : ITaggedData + { + /// + /// Flags indicate which values are included in this instance. + /// + [Flags] + public enum Flags : byte + { + /// + /// The modification time is included + /// + ModificationTime = 0x01, + + /// + /// The access time is included + /// + AccessTime = 0x02, + + /// + /// The create time is included. + /// + CreateTime = 0x04, + } + + #region ITaggedData Members + + /// + /// Get the ID + /// + public short TagID + { + get { return 0x5455; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int index, int count) + { + using (MemoryStream ms = new MemoryStream(data, index, count, false)) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + // bit 0 if set, modification time is present + // bit 1 if set, access time is present + // bit 2 if set, creation time is present + + _flags = (Flags)helperStream.ReadByte(); + if (((_flags & Flags.ModificationTime) != 0) && (count >= 5)) + { + int iTime = helperStream.ReadLEInt(); + + _modificationTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + + if ((_flags & Flags.AccessTime) != 0) + { + int iTime = helperStream.ReadLEInt(); + + _lastAccessTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + + if ((_flags & Flags.CreateTime) != 0) + { + int iTime = helperStream.ReadLEInt(); + + _createTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + } + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + using (MemoryStream ms = new MemoryStream()) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.IsStreamOwner = false; + helperStream.WriteByte((byte)_flags); // Flags + if ( (_flags & Flags.ModificationTime) != 0) { + TimeSpan span = _modificationTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + if ( (_flags & Flags.AccessTime) != 0) { + TimeSpan span = _lastAccessTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + if ( (_flags & Flags.CreateTime) != 0) { + TimeSpan span = _createTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + return ms.ToArray(); + } + } + + #endregion + + /// + /// Test a value to see if is valid and can be represented here. + /// + /// The value to test. + /// Returns true if the value is valid and can be represented; false if not. + /// The standard Unix time is a signed integer data type, directly encoding the Unix time number, + /// which is the number of seconds since 1970-01-01. + /// Being 32 bits means the values here cover a range of about 136 years. + /// The minimum representable time is 1901-12-13 20:45:52, + /// and the maximum representable time is 2038-01-19 03:14:07. + /// + public static bool IsValidValue(DateTime value) + { + return (( value >= new DateTime(1901, 12, 13, 20, 45, 52)) || + ( value <= new DateTime(2038, 1, 19, 03, 14, 07) )); + } + + /// + /// Get /set the Modification Time + /// + /// + /// + public DateTime ModificationTime + { + get { return _modificationTime; } + set + { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.ModificationTime; + _modificationTime=value; + } + } + + /// + /// Get / set the Access Time + /// + /// + /// + public DateTime AccessTime + { + get { return _lastAccessTime; } + set { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.AccessTime; + _lastAccessTime=value; + } + } + + /// + /// Get / Set the Create Time + /// + /// + /// + public DateTime CreateTime + { + get { return _createTime; } + set { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.CreateTime; + _createTime=value; + } + } + + /// + /// Get/set the values to include. + /// + Flags Include + { + get { return _flags; } + set { _flags = value; } + } + + #region Instance Fields + Flags _flags; + DateTime _modificationTime = new DateTime(1970,1,1); + DateTime _lastAccessTime = new DateTime(1970, 1, 1); + DateTime _createTime = new DateTime(1970, 1, 1); + #endregion + } + + /// + /// Class handling NT date time values. + /// + public class NTTaggedData : ITaggedData + { + /// + /// Get the ID for this tagged data value. + /// + public short TagID + { + get { return 10; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int index, int count) + { + using (MemoryStream ms = new MemoryStream(data, index, count, false)) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.ReadLEInt(); // Reserved + while (helperStream.Position < helperStream.Length) + { + int ntfsTag = helperStream.ReadLEShort(); + int ntfsLength = helperStream.ReadLEShort(); + if (ntfsTag == 1) + { + if (ntfsLength >= 24) + { + long lastModificationTicks = helperStream.ReadLELong(); + _lastModificationTime = DateTime.FromFileTime(lastModificationTicks); + + long lastAccessTicks = helperStream.ReadLELong(); + _lastAccessTime = DateTime.FromFileTime(lastAccessTicks); + + long createTimeTicks = helperStream.ReadLELong(); + _createTime = DateTime.FromFileTime(createTimeTicks); + } + break; + } + else + { + // An unknown NTFS tag so simply skip it. + helperStream.Seek(ntfsLength, SeekOrigin.Current); + } + } + } + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + using (MemoryStream ms = new MemoryStream()) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.IsStreamOwner = false; + helperStream.WriteLEInt(0); // Reserved + helperStream.WriteLEShort(1); // Tag + helperStream.WriteLEShort(24); // Length = 3 x 8. + helperStream.WriteLELong(_lastModificationTime.ToFileTime()); + helperStream.WriteLELong(_lastAccessTime.ToFileTime()); + helperStream.WriteLELong(_createTime.ToFileTime()); + return ms.ToArray(); + } + } + + /// + /// Test a valuie to see if is valid and can be represented here. + /// + /// The value to test. + /// Returns true if the value is valid and can be represented; false if not. + /// + /// NTFS filetimes are 64-bit unsigned integers, stored in Intel + /// (least significant byte first) byte order. They determine the + /// number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", + /// which is "01-Jan-1601 00:00:00 UTC". 28 May 60056 is the upper limit + /// + public static bool IsValidValue(DateTime value) + { + bool result = true; + try + { + value.ToFileTimeUtc(); + } + catch + { + result = false; + } + return result; + } + + /// + /// Get/set the last modification time. + /// + public DateTime LastModificationTime + { + get { return _lastModificationTime; } + set { + if (! IsValidValue(value)) + { + throw new ArgumentOutOfRangeException("value"); + } + _lastModificationTime = value; + } + } + + /// + /// Get /set the create time + /// + public DateTime CreateTime + { + get { return _createTime; } + set { + if ( !IsValidValue(value)) { + throw new ArgumentOutOfRangeException("value"); + } + _createTime = value; + } + } + + /// + /// Get /set the last access time. + /// + public DateTime LastAccessTime + { + get { return _lastAccessTime; } + set { + if (!IsValidValue(value)) { + throw new ArgumentOutOfRangeException("value"); + } + _lastAccessTime = value; + } + } + + #region Instance Fields + DateTime _lastAccessTime = DateTime.FromFileTime(0); + DateTime _lastModificationTime = DateTime.FromFileTime(0); + DateTime _createTime = DateTime.FromFileTime(0); + #endregion + } + + /// + /// A factory that creates tagged data instances. + /// + interface ITaggedDataFactory + { + /// + /// Get data for a specific tag value. + /// + /// The tag ID to find. + /// The data to search. + /// The offset to begin extracting data from. + /// The number of bytes to extract. + /// The located value found, or null if not found. + ITaggedData Create(short tag, byte[] data, int offset, int count); + } + + /// + /// + /// A class to handle the extra data field for Zip entries + /// + /// + /// Extra data contains 0 or more values each prefixed by a header tag and length. + /// They contain zero or more bytes of actual data. + /// The data is held internally using a copy on write strategy. This is more efficient but + /// means that for extra data created by passing in data can have the values modified by the caller + /// in some circumstances. + /// + sealed public class ZipExtraData : IDisposable + { + #region Constructors + /// + /// Initialise a default instance. + /// + public ZipExtraData() + { + Clear(); + } + + /// + /// Initialise with known extra data. + /// + /// The extra data. + public ZipExtraData(byte[] data) + { + if ( data == null ) + { + _data = new byte[0]; + } + else + { + _data = data; + } + } + #endregion + + /// + /// Get the raw extra data value + /// + /// Returns the raw byte[] extra data this instance represents. + public byte[] GetEntryData() + { + if ( Length > ushort.MaxValue ) { + throw new ZipException("Data exceeds maximum length"); + } + + return (byte[])_data.Clone(); + } + + /// + /// Clear the stored data. + /// + public void Clear() + { + if ( (_data == null) || (_data.Length != 0) ) { + _data = new byte[0]; + } + } + + /// + /// Gets the current extra data length. + /// + public int Length + { + get { return _data.Length; } + } + + /// + /// Get a read-only for the associated tag. + /// + /// The tag to locate data for. + /// Returns a containing tag data or null if no tag was found. + public Stream GetStreamForTag(int tag) + { + Stream result = null; + if ( Find(tag) ) { + result = new MemoryStream(_data, _index, _readValueLength, false); + } + return result; + } + + /// + /// Get the tagged data for a tag. + /// + /// The tag to search for. + /// Returns a tagged value or null if none found. + private ITaggedData GetData(short tag) + { + ITaggedData result = null; + if (Find(tag)) + { + result = Create(tag, _data, _readValueStart, _readValueLength); + } + return result; + } + + static ITaggedData Create(short tag, byte[] data, int offset, int count) + { + ITaggedData result = null; + switch ( tag ) + { + case 0x000A: + result = new NTTaggedData(); + break; + case 0x5455: + result = new ExtendedUnixData(); + break; + default: + result = new RawTaggedData(tag); + break; + } + result.SetData(data, offset, count); + return result; + } + + /// + /// Get the length of the last value found by + /// + /// This is only valid if has previously returned true. + public int ValueLength + { + get { return _readValueLength; } + } + + /// + /// Get the index for the current read value. + /// + /// This is only valid if has previously returned true. + /// Initially the result will be the index of the first byte of actual data. The value is updated after calls to + /// , and . + public int CurrentReadIndex + { + get { return _index; } + } + + /// + /// Get the number of bytes remaining to be read for the current value; + /// + public int UnreadCount + { + get + { + if ((_readValueStart > _data.Length) || + (_readValueStart < 4) ) { + throw new ZipException("Find must be called before calling a Read method"); + } + + return _readValueStart + _readValueLength - _index; + } + } + + /// + /// Find an extra data value + /// + /// The identifier for the value to find. + /// Returns true if the value was found; false otherwise. + public bool Find(int headerID) + { + _readValueStart = _data.Length; + _readValueLength = 0; + _index = 0; + + int localLength = _readValueStart; + int localTag = headerID - 1; + + // Trailing bytes that cant make up an entry (as there arent enough + // bytes for a tag and length) are ignored! + while ( (localTag != headerID) && (_index < _data.Length - 3) ) { + localTag = ReadShortInternal(); + localLength = ReadShortInternal(); + if ( localTag != headerID ) { + _index += localLength; + } + } + + bool result = (localTag == headerID) && ((_index + localLength) <= _data.Length); + + if ( result ) { + _readValueStart = _index; + _readValueLength = localLength; + } + + return result; + } + + /// + /// Add a new entry to extra data. + /// + /// The value to add. + public void AddEntry(ITaggedData taggedData) + { + if (taggedData == null) + { + throw new ArgumentNullException("taggedData"); + } + AddEntry(taggedData.TagID, taggedData.GetData()); + } + + /// + /// Add a new entry to extra data + /// + /// The ID for this entry. + /// The data to add. + /// If the ID already exists its contents are replaced. + public void AddEntry(int headerID, byte[] fieldData) + { + if ( (headerID > ushort.MaxValue) || (headerID < 0)) { + throw new ArgumentOutOfRangeException("headerID"); + } + + int addLength = (fieldData == null) ? 0 : fieldData.Length; + + if ( addLength > ushort.MaxValue ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("fieldData"); +#else + throw new ArgumentOutOfRangeException("fieldData", "exceeds maximum length"); +#endif + } + + // Test for new length before adjusting data. + int newLength = _data.Length + addLength + 4; + + if ( Find(headerID) ) + { + newLength -= (ValueLength + 4); + } + + if ( newLength > ushort.MaxValue ) { + throw new ZipException("Data exceeds maximum length"); + } + + Delete(headerID); + + byte[] newData = new byte[newLength]; + _data.CopyTo(newData, 0); + int index = _data.Length; + _data = newData; + SetShort(ref index, headerID); + SetShort(ref index, addLength); + if ( fieldData != null ) { + fieldData.CopyTo(newData, index); + } + } + + /// + /// Start adding a new entry. + /// + /// Add data using , , , or . + /// The new entry is completed and actually added by calling + /// + public void StartNewEntry() + { + _newEntry = new MemoryStream(); + } + + /// + /// Add entry data added since using the ID passed. + /// + /// The identifier to use for this entry. + public void AddNewEntry(int headerID) + { + byte[] newData = _newEntry.ToArray(); + _newEntry = null; + AddEntry(headerID, newData); + } + + /// + /// Add a byte of data to the pending new entry. + /// + /// The byte to add. + /// + public void AddData(byte data) + { + _newEntry.WriteByte(data); + } + + /// + /// Add data to a pending new entry. + /// + /// The data to add. + /// + public void AddData(byte[] data) + { + if ( data == null ) { + throw new ArgumentNullException("data"); + } + + _newEntry.Write(data, 0, data.Length); + } + + /// + /// Add a short value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeShort(int toAdd) + { + unchecked { + _newEntry.WriteByte(( byte )toAdd); + _newEntry.WriteByte(( byte )(toAdd >> 8)); + } + } + + /// + /// Add an integer value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeInt(int toAdd) + { + unchecked { + AddLeShort(( short )toAdd); + AddLeShort(( short )(toAdd >> 16)); + } + } + + /// + /// Add a long value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeLong(long toAdd) + { + unchecked { + AddLeInt(( int )(toAdd & 0xffffffff)); + AddLeInt(( int )(toAdd >> 32)); + } + } + + /// + /// Delete an extra data field. + /// + /// The identifier of the field to delete. + /// Returns true if the field was found and deleted. + public bool Delete(int headerID) + { + bool result = false; + + if ( Find(headerID) ) { + result = true; + int trueStart = _readValueStart - 4; + + byte[] newData = new byte[_data.Length - (ValueLength + 4)]; + Array.Copy(_data, 0, newData, 0, trueStart); + + int trueEnd = trueStart + ValueLength + 4; + Array.Copy(_data, trueEnd, newData, trueStart, _data.Length - trueEnd); + _data = newData; + } + return result; + } + + #region Reading Support + /// + /// Read a long in little endian form from the last found data value + /// + /// Returns the long value read. + public long ReadLong() + { + ReadCheck(8); + return (ReadInt() & 0xffffffff) | ((( long )ReadInt()) << 32); + } + + /// + /// Read an integer in little endian form from the last found data value. + /// + /// Returns the integer read. + public int ReadInt() + { + ReadCheck(4); + + int result = _data[_index] + (_data[_index + 1] << 8) + + (_data[_index + 2] << 16) + (_data[_index + 3] << 24); + _index += 4; + return result; + } + + /// + /// Read a short value in little endian form from the last found data value. + /// + /// Returns the short value read. + public int ReadShort() + { + ReadCheck(2); + int result = _data[_index] + (_data[_index + 1] << 8); + _index += 2; + return result; + } + + /// + /// Read a byte from an extra data + /// + /// The byte value read or -1 if the end of data has been reached. + public int ReadByte() + { + int result = -1; + if ( (_index < _data.Length) && (_readValueStart + _readValueLength > _index) ) { + result = _data[_index]; + _index += 1; + } + return result; + } + + /// + /// Skip data during reading. + /// + /// The number of bytes to skip. + public void Skip(int amount) + { + ReadCheck(amount); + _index += amount; + } + + void ReadCheck(int length) + { + if ((_readValueStart > _data.Length) || + (_readValueStart < 4) ) { + throw new ZipException("Find must be called before calling a Read method"); + } + + if (_index > _readValueStart + _readValueLength - length ) { + throw new ZipException("End of extra data"); + } + + if ( _index + length < 4 ) { + throw new ZipException("Cannot read before start of tag"); + } + } + + /// + /// Internal form of that reads data at any location. + /// + /// Returns the short value read. + int ReadShortInternal() + { + if ( _index > _data.Length - 2) { + throw new ZipException("End of extra data"); + } + + int result = _data[_index] + (_data[_index + 1] << 8); + _index += 2; + return result; + } + + void SetShort(ref int index, int source) + { + _data[index] = (byte)source; + _data[index + 1] = (byte)(source >> 8); + index += 2; + } + + #endregion + + #region IDisposable Members + + /// + /// Dispose of this instance. + /// + public void Dispose() + { + if ( _newEntry != null ) { + _newEntry.Close(); + } + } + + #endregion + + #region Instance Fields + int _index; + int _readValueStart; + int _readValueLength; + + MemoryStream _newEntry; + byte[] _data; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/ZipFile.cs b/类库/Update/ZIP/Zip/ZipFile.cs new file mode 100644 index 0000000..af4000b --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipFile.cs @@ -0,0 +1,4486 @@ +// ZipFile.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2009-12-22 Z-1649 Added AES support +// 2010-03-02 Z-1650 Fixed updating ODT archives in memory. Exposed exceptions in updating. +// 2010-05-25 Z-1663 Fixed exception when testing local header compressed size of -1 + +using System; +using System.Collections; +using System.IO; +using System.Text; +using System.Globalization; + +#if !NETCF_1_0 +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Encryption; +#endif + +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using ICSharpCode.SharpZipLib.Zip.Compression; + +namespace ICSharpCode.SharpZipLib.Zip +{ + #region Keys Required Event Args + /// + /// Arguments used with KeysRequiredEvent + /// + public class KeysRequiredEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The name of the file for which keys are required. + public KeysRequiredEventArgs(string name) + { + fileName = name; + } + + /// + /// Initialise a new instance of + /// + /// The name of the file for which keys are required. + /// The current key value. + public KeysRequiredEventArgs(string name, byte[] keyValue) + { + fileName = name; + key = keyValue; + } + + #endregion + #region Properties + /// + /// Gets the name of the file for which keys are required. + /// + public string FileName + { + get { return fileName; } + } + + /// + /// Gets or sets the key value + /// + public byte[] Key + { + get { return key; } + set { key = value; } + } + #endregion + + #region Instance Fields + string fileName; + byte[] key; + #endregion + } + #endregion + + #region Test Definitions + /// + /// The strategy to apply to testing. + /// + public enum TestStrategy + { + /// + /// Find the first error only. + /// + FindFirstError, + /// + /// Find all possible errors. + /// + FindAllErrors, + } + + /// + /// The operation in progress reported by a during testing. + /// + /// TestArchive + public enum TestOperation + { + /// + /// Setting up testing. + /// + Initialising, + + /// + /// Testing an individual entries header + /// + EntryHeader, + + /// + /// Testing an individual entries data + /// + EntryData, + + /// + /// Testing an individual entry has completed. + /// + EntryComplete, + + /// + /// Running miscellaneous tests + /// + MiscellaneousTests, + + /// + /// Testing is complete + /// + Complete, + } + + /// + /// Status returned returned by during testing. + /// + /// TestArchive + public class TestStatus + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The this status applies to. + public TestStatus(ZipFile file) + { + file_ = file; + } + #endregion + + #region Properties + + /// + /// Get the current in progress. + /// + public TestOperation Operation + { + get { return operation_; } + } + + /// + /// Get the this status is applicable to. + /// + public ZipFile File + { + get { return file_; } + } + + /// + /// Get the current/last entry tested. + /// + public ZipEntry Entry + { + get { return entry_; } + } + + /// + /// Get the number of errors detected so far. + /// + public int ErrorCount + { + get { return errorCount_; } + } + + /// + /// Get the number of bytes tested so far for the current entry. + /// + public long BytesTested + { + get { return bytesTested_; } + } + + /// + /// Get a value indicating wether the last entry test was valid. + /// + public bool EntryValid + { + get { return entryValid_; } + } + #endregion + + #region Internal API + internal void AddError() + { + errorCount_++; + entryValid_ = false; + } + + internal void SetOperation(TestOperation operation) + { + operation_ = operation; + } + + internal void SetEntry(ZipEntry entry) + { + entry_ = entry; + entryValid_ = true; + bytesTested_ = 0; + } + + internal void SetBytesTested(long value) + { + bytesTested_ = value; + } + #endregion + + #region Instance Fields + ZipFile file_; + ZipEntry entry_; + bool entryValid_; + int errorCount_; + long bytesTested_; + TestOperation operation_; + #endregion + } + + /// + /// Delegate invoked during testing if supplied indicating current progress and status. + /// + /// If the message is non-null an error has occured. If the message is null + /// the operation as found in status has started. + public delegate void ZipTestResultHandler(TestStatus status, string message); + #endregion + + #region Update Definitions + /// + /// The possible ways of applying updates to an archive. + /// + public enum FileUpdateMode + { + /// + /// Perform all updates on temporary files ensuring that the original file is saved. + /// + Safe, + /// + /// Update the archive directly, which is faster but less safe. + /// + Direct, + } + #endregion + + #region ZipFile Class + /// + /// This class represents a Zip archive. You can ask for the contained + /// entries, or get an input stream for a file entry. The entry is + /// automatically decompressed. + /// + /// You can also update the archive adding or deleting entries. + /// + /// This class is thread safe for input: You can open input streams for arbitrary + /// entries in different threads. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// + /// + /// using System; + /// using System.Text; + /// using System.Collections; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// static public void Main(string[] args) + /// { + /// using (ZipFile zFile = new ZipFile(args[0])) { + /// Console.WriteLine("Listing of : " + zFile.Name); + /// Console.WriteLine(""); + /// Console.WriteLine("Raw Size Size Date Time Name"); + /// Console.WriteLine("-------- -------- -------- ------ ---------"); + /// foreach (ZipEntry e in zFile) { + /// if ( e.IsFile ) { + /// DateTime d = e.DateTime; + /// Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize, + /// d.ToString("dd-MM-yy"), d.ToString("HH:mm"), + /// e.Name); + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipFile : IEnumerable, IDisposable + { + #region KeyHandling + + /// + /// Delegate for handling keys/password setting during compresion/decompression. + /// + public delegate void KeysRequiredEventHandler( + object sender, + KeysRequiredEventArgs e + ); + + /// + /// Event handler for handling encryption keys. + /// + public KeysRequiredEventHandler KeysRequired; + + /// + /// Handles getting of encryption keys when required. + /// + /// The file for which encryption keys are required. + void OnKeysRequired(string fileName) + { + if (KeysRequired != null) { + KeysRequiredEventArgs krea = new KeysRequiredEventArgs(fileName, key); + KeysRequired(this, krea); + key = krea.Key; + } + } + + /// + /// Get/set the encryption key value. + /// + byte[] Key + { + get { return key; } + set { key = value; } + } + +#if !NETCF_1_0 + /// + /// Password to be used for encrypting/decrypting files. + /// + /// Set to null if no password is required. + public string Password + { + set + { + if ( (value == null) || (value.Length == 0) ) { + key = null; + } + else { + rawPassword_ = value; + key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(value)); + } + } + } +#endif + + /// + /// Get a value indicating wether encryption keys are currently available. + /// + bool HaveKeys + { + get { return key != null; } + } + #endregion + + #region Constructors + /// + /// Opens a Zip file with the given name for reading. + /// + /// The name of the file to open. + /// The argument supplied is null. + /// + /// An i/o error occurs + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(string name) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + name_ = name; + + baseStream_ = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read); + isStreamOwner = true; + + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } + + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// The supplied argument is null. + /// + /// An i/o error occurs. + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(FileStream file) + { + if ( file == null ) { + throw new ArgumentNullException("file"); + } + + if ( !file.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "file"); + } + + baseStream_ = file; + name_ = file.Name; + isStreamOwner = true; + + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } + + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// + /// An i/o error occurs + /// + /// + /// The stream doesn't contain a valid zip archive.
+ ///
+ /// + /// The stream doesnt support seeking. + /// + /// + /// The stream argument is null. + /// + public ZipFile(Stream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + if ( !stream.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "stream"); + } + + baseStream_ = stream; + isStreamOwner = true; + + if ( baseStream_.Length > 0 ) { + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } else { + entries_ = new ZipEntry[0]; + isNewArchive_ = true; + } + } + + /// + /// Initialises a default instance with no entries and no file storage. + /// + internal ZipFile() + { + entries_ = new ZipEntry[0]; + isNewArchive_ = true; + } + + #endregion + + #region Destructors and Closing + /// + /// Finalize this instance. + /// + ~ZipFile() + { + Dispose(false); + } + + /// + /// Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. + /// Once closed, no further instance methods should be called. + /// + /// + /// An i/o error occurs. + /// + public void Close() + { + DisposeInternal(true); + GC.SuppressFinalize(this); + } + + #endregion + + #region Creators + /// + /// Create a new whose data will be stored in a file. + /// + /// The name of the archive to create. + /// Returns the newly created + /// is null + public static ZipFile Create(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + FileStream fs = File.Create(fileName); + + ZipFile result = new ZipFile(); + result.name_ = fileName; + result.baseStream_ = fs; + result.isStreamOwner = true; + return result; + } + + /// + /// Create a new whose data will be stored on a stream. + /// + /// The stream providing data storage. + /// Returns the newly created + /// is null + /// doesnt support writing. + public static ZipFile Create(Stream outStream) + { + if ( outStream == null ) { + throw new ArgumentNullException("outStream"); + } + + if ( !outStream.CanWrite ) { + throw new ArgumentException("Stream is not writeable", "outStream"); + } + + if ( !outStream.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "outStream"); + } + + ZipFile result = new ZipFile(); + result.baseStream_ = outStream; + return result; + } + + #endregion + + #region Properties + /// + /// Get/set a flag indicating if the underlying stream is owned by the ZipFile instance. + /// If the flag is true then the stream will be closed when Close is called. + /// + /// + /// The default value is true in all cases. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Get a value indicating wether + /// this archive is embedded in another file or not. + /// + public bool IsEmbeddedArchive + { + // Not strictly correct in all circumstances currently + get { return offsetOfFirstEntry > 0; } + } + + /// + /// Get a value indicating that this archive is a new one. + /// + public bool IsNewArchive + { + get { return isNewArchive_; } + } + + /// + /// Gets the comment for the zip file. + /// + public string ZipFileComment + { + get { return comment_; } + } + + /// + /// Gets the name of this zip file. + /// + public string Name + { + get { return name_; } + } + + /// + /// Gets the number of entries in this zip file. + /// + /// + /// The Zip file has been closed. + /// + [Obsolete("Use the Count property instead")] + public int Size + { + get + { + return entries_.Length; + } + } + + /// + /// Get the number of entries contained in this . + /// + public long Count + { + get + { + return entries_.Length; + } + } + + /// + /// Indexer property for ZipEntries + /// + [System.Runtime.CompilerServices.IndexerNameAttribute("EntryByIndex")] + public ZipEntry this[int index] + { + get { + return (ZipEntry) entries_[index].Clone(); + } + } + + #endregion + + #region Input Handling + /// + /// Gets an enumerator for the Zip entries in this Zip file. + /// + /// Returns an for this archive. + /// + /// The Zip file has been closed. + /// + public IEnumerator GetEnumerator() + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + return new ZipEntryEnumerator(entries_); + } + + /// + /// Return the index of the entry with a matching name + /// + /// Entry name to find + /// If true the comparison is case insensitive + /// The index position of the matching entry or -1 if not found + /// + /// The Zip file has been closed. + /// + public int FindEntry(string name, bool ignoreCase) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + // TODO: This will be slow as the next ice age for huge archives! + for (int i = 0; i < entries_.Length; i++) { + if (string.Compare(name, entries_[i].Name, ignoreCase, CultureInfo.InvariantCulture) == 0) { + return i; + } + } + return -1; + } + + /// + /// Searches for a zip entry in this archive with the given name. + /// String comparisons are case insensitive + /// + /// + /// The name to find. May contain directory components separated by slashes ('/'). + /// + /// + /// A clone of the zip entry, or null if no entry with that name exists. + /// + /// + /// The Zip file has been closed. + /// + public ZipEntry GetEntry(string name) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + int index = FindEntry(name, true); + return (index >= 0) ? (ZipEntry) entries_[index].Clone() : null; + } + + /// + /// Gets an input stream for reading the given zip entry data in an uncompressed form. + /// Normally the should be an entry returned by GetEntry(). + /// + /// The to obtain a data for + /// An input containing data for this + /// + /// The ZipFile has already been closed + /// + /// + /// The compression method for the entry is unknown + /// + /// + /// The entry is not found in the ZipFile + /// + public Stream GetInputStream(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + long index = entry.ZipFileIndex; + if ( (index < 0) || (index >= entries_.Length) || (entries_[index].Name != entry.Name) ) { + index = FindEntry(entry.Name, true); + if (index < 0) { + throw new ZipException("Entry cannot be found"); + } + } + return GetInputStream(index); + } + + /// + /// Creates an input stream reading a zip entry + /// + /// The index of the entry to obtain an input stream for. + /// + /// An input containing data for this + /// + /// + /// The ZipFile has already been closed + /// + /// + /// The compression method for the entry is unknown + /// + /// + /// The entry is not found in the ZipFile + /// + public Stream GetInputStream(long entryIndex) + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + long start = LocateEntry(entries_[entryIndex]); + CompressionMethod method = entries_[entryIndex].CompressionMethod; + Stream result = new PartialInputStream(this, start, entries_[entryIndex].CompressedSize); + + if (entries_[entryIndex].IsCrypted == true) { +#if NETCF_1_0 + throw new ZipException("decryption not supported for Compact Framework 1.0"); +#else + result = CreateAndInitDecryptionStream(result, entries_[entryIndex]); + if (result == null) { + throw new ZipException("Unable to decrypt this entry"); + } +#endif + } + + switch (method) { + case CompressionMethod.Stored: + // read as is. + break; + + case CompressionMethod.Deflated: + // No need to worry about ownership and closing as underlying stream close does nothing. + result = new InflaterInputStream(result, new Inflater(true)); + break; + + default: + throw new ZipException("Unsupported compression method " + method); + } + + return result; + } + + #endregion + + #region Archive Testing + /// + /// Test an archive for integrity/validity + /// + /// Perform low level data Crc check + /// true if all tests pass, false otherwise + /// Testing will terminate on the first error found. + public bool TestArchive(bool testData) + { + return TestArchive(testData, TestStrategy.FindFirstError, null); + } + + /// + /// Test an archive for integrity/validity + /// + /// Perform low level data Crc check + /// The to apply. + /// The handler to call during testing. + /// true if all tests pass, false otherwise + /// The object has already been closed. + public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandler resultHandler) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + TestStatus status = new TestStatus(this); + + if ( resultHandler != null ) { + resultHandler(status, null); + } + + HeaderTest test = testData ? (HeaderTest.Header | HeaderTest.Extract) : HeaderTest.Header; + + bool testing = true; + + try { + int entryIndex = 0; + + while ( testing && (entryIndex < Count) ) { + if ( resultHandler != null ) { + status.SetEntry(this[entryIndex]); + status.SetOperation(TestOperation.EntryHeader); + resultHandler(status, null); + } + + try { + TestLocalHeader(this[entryIndex], test); + } + catch(ZipException ex) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, + string.Format("Exception during test - '{0}'", ex.Message)); + } + + if ( strategy == TestStrategy.FindFirstError ) { + testing = false; + } + } + + if ( testing && testData && this[entryIndex].IsFile ) { + if ( resultHandler != null ) { + status.SetOperation(TestOperation.EntryData); + resultHandler(status, null); + } + + Crc32 crc = new Crc32(); + + using (Stream entryStream = this.GetInputStream(this[entryIndex])) + { + + byte[] buffer = new byte[4096]; + long totalBytes = 0; + int bytesRead; + while ((bytesRead = entryStream.Read(buffer, 0, buffer.Length)) > 0) + { + crc.Update(buffer, 0, bytesRead); + + if (resultHandler != null) + { + totalBytes += bytesRead; + status.SetBytesTested(totalBytes); + resultHandler(status, null); + } + } + } + + if (this[entryIndex].Crc != crc.Value) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, "CRC mismatch"); + } + + if ( strategy == TestStrategy.FindFirstError ) { + testing = false; + } + } + + if (( this[entryIndex].Flags & (int)GeneralBitFlags.Descriptor) != 0 ) { + ZipHelperStream helper = new ZipHelperStream(baseStream_); + DescriptorData data = new DescriptorData(); + helper.ReadDataDescriptor(this[entryIndex].LocalHeaderRequiresZip64, data); + if (this[entryIndex].Crc != data.Crc) { + status.AddError(); + } + + if (this[entryIndex].CompressedSize != data.CompressedSize) { + status.AddError(); + } + + if (this[entryIndex].Size != data.Size) { + status.AddError(); + } + } + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.EntryComplete); + resultHandler(status, null); + } + + entryIndex += 1; + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.MiscellaneousTests); + resultHandler(status, null); + } + + // TODO: the 'Corrina Johns' test where local headers are missing from + // the central directory. They are therefore invisible to many archivers. + } + catch (Exception ex) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, string.Format("Exception during test - '{0}'", ex.Message)); + } + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.Complete); + status.SetEntry(null); + resultHandler(status, null); + } + + return (status.ErrorCount == 0); + } + + [Flags] + enum HeaderTest + { + Extract = 0x01, // Check that this header represents an entry whose data can be extracted + Header = 0x02, // Check that this header contents are valid + } + + /// + /// Test a local header against that provided from the central directory + /// + /// + /// The entry to test against + /// + /// The type of tests to carry out. + /// The offset of the entries data in the file + long TestLocalHeader(ZipEntry entry, HeaderTest tests) + { + lock(baseStream_) + { + bool testHeader = (tests & HeaderTest.Header) != 0; + bool testData = (tests & HeaderTest.Extract) != 0; + + baseStream_.Seek(offsetOfFirstEntry + entry.Offset, SeekOrigin.Begin); + if ((int)ReadLEUint() != ZipConstants.LocalHeaderSignature) { + throw new ZipException(string.Format("Wrong local header signature @{0:X}", offsetOfFirstEntry + entry.Offset)); + } + + short extractVersion = ( short )ReadLEUshort(); + short localFlags = ( short )ReadLEUshort(); + short compressionMethod = ( short )ReadLEUshort(); + short fileTime = ( short )ReadLEUshort(); + short fileDate = ( short )ReadLEUshort(); + uint crcValue = ReadLEUint(); + long compressedSize = ReadLEUint(); + long size = ReadLEUint(); + int storedNameLength = ReadLEUshort(); + int extraDataLength = ReadLEUshort(); + + byte[] nameData = new byte[storedNameLength]; + StreamUtils.ReadFully(baseStream_, nameData); + + byte[] extraData = new byte[extraDataLength]; + StreamUtils.ReadFully(baseStream_, extraData); + + ZipExtraData localExtraData = new ZipExtraData(extraData); + + // Extra data / zip64 checks + if (localExtraData.Find(1)) + { + // 2010-03-04 Forum 10512: removed checks for version >= ZipConstants.VersionZip64 + // and size or compressedSize = MaxValue, due to rogue creators. + + size = localExtraData.ReadLong(); + compressedSize = localExtraData.ReadLong(); + + if ((localFlags & (int)GeneralBitFlags.Descriptor) != 0) + { + // These may be valid if patched later + if ( (size != -1) && (size != entry.Size)) { + throw new ZipException("Size invalid for descriptor"); + } + + if ((compressedSize != -1) && (compressedSize != entry.CompressedSize)) { + throw new ZipException("Compressed size invalid for descriptor"); + } + } + } + else + { + // No zip64 extra data but entry requires it. + if ((extractVersion >= ZipConstants.VersionZip64) && + (((uint)size == uint.MaxValue) || ((uint)compressedSize == uint.MaxValue))) + { + throw new ZipException("Required Zip64 extended information missing"); + } + } + + if ( testData ) { + if ( entry.IsFile ) { + if ( !entry.IsCompressionMethodSupported() ) { + throw new ZipException("Compression method not supported"); + } + + if ( (extractVersion > ZipConstants.VersionMadeBy) + || ((extractVersion > 20) && (extractVersion < ZipConstants.VersionZip64)) ) { + throw new ZipException(string.Format("Version required to extract this entry not supported ({0})", extractVersion)); + } + + if ( (localFlags & ( int )(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0 ) { + throw new ZipException("The library does not support the zip version required to extract this entry"); + } + } + } + + if (testHeader) + { + if ((extractVersion <= 63) && // Ignore later versions as we dont know about them.. + (extractVersion != 10) && + (extractVersion != 11) && + (extractVersion != 20) && + (extractVersion != 21) && + (extractVersion != 25) && + (extractVersion != 27) && + (extractVersion != 45) && + (extractVersion != 46) && + (extractVersion != 50) && + (extractVersion != 51) && + (extractVersion != 52) && + (extractVersion != 61) && + (extractVersion != 62) && + (extractVersion != 63) + ) + { + throw new ZipException(string.Format("Version required to extract this entry is invalid ({0})", extractVersion)); + } + + // Local entry flags dont have reserved bit set on. + if ((localFlags & (int)(GeneralBitFlags.ReservedPKware4 | GeneralBitFlags.ReservedPkware14 | GeneralBitFlags.ReservedPkware15)) != 0) + { + throw new ZipException("Reserved bit flags cannot be set."); + } + + // Encryption requires extract version >= 20 + if (((localFlags & (int)GeneralBitFlags.Encrypted) != 0) && (extractVersion < 20)) + { + throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion)); + } + + // Strong encryption requires encryption flag to be set and extract version >= 50. + if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0) + { + if ((localFlags & (int)GeneralBitFlags.Encrypted) == 0) + { + throw new ZipException("Strong encryption flag set but encryption flag is not set"); + } + + if (extractVersion < 50) + { + throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion)); + } + } + + // Patched entries require extract version >= 27 + if (((localFlags & (int)GeneralBitFlags.Patched) != 0) && (extractVersion < 27)) + { + throw new ZipException(string.Format("Patched data requires higher version than ({0})", extractVersion)); + } + + // Central header flags match local entry flags. + if (localFlags != entry.Flags) + { + throw new ZipException("Central header/local header flags mismatch"); + } + + // Central header compression method matches local entry + if (entry.CompressionMethod != (CompressionMethod)compressionMethod) + { + throw new ZipException("Central header/local header compression method mismatch"); + } + + if (entry.Version != extractVersion) + { + throw new ZipException("Extract version mismatch"); + } + + // Strong encryption and extract version match + if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0) + { + if (extractVersion < 62) + { + throw new ZipException("Strong encryption flag set but version not high enough"); + } + } + + if ((localFlags & (int)GeneralBitFlags.HeaderMasked) != 0) + { + if ((fileTime != 0) || (fileDate != 0)) + { + throw new ZipException("Header masked set but date/time values non-zero"); + } + } + + if ((localFlags & (int)GeneralBitFlags.Descriptor) == 0) + { + if (crcValue != (uint)entry.Crc) + { + throw new ZipException("Central header/local header crc mismatch"); + } + } + + // Crc valid for empty entry. + // This will also apply to streamed entries where size isnt known and the header cant be patched + if ((size == 0) && (compressedSize == 0)) + { + if (crcValue != 0) + { + throw new ZipException("Invalid CRC for empty entry"); + } + } + + // TODO: make test more correct... can't compare lengths as was done originally as this can fail for MBCS strings + // Assuming a code page at this point is not valid? Best is to store the name length in the ZipEntry probably + if (entry.Name.Length > storedNameLength) + { + throw new ZipException("File name length mismatch"); + } + + // Name data has already been read convert it and compare. + string localName = ZipConstants.ConvertToStringExt(localFlags, nameData); + + // Central directory and local entry name match + if (localName != entry.Name) + { + throw new ZipException("Central header and local header file name mismatch"); + } + + // Directories have zero actual size but can have compressed size + if (entry.IsDirectory) + { + if (size > 0) + { + throw new ZipException("Directory cannot have size"); + } + + // There may be other cases where the compressed size can be greater than this? + // If so until details are known we will be strict. + if (entry.IsCrypted) + { + if (compressedSize > ZipConstants.CryptoHeaderSize + 2) + { + throw new ZipException("Directory compressed size invalid"); + } + } + else if (compressedSize > 2) + { + // When not compressed the directory size can validly be 2 bytes + // if the true size wasnt known when data was originally being written. + // NOTE: Versions of the library 0.85.4 and earlier always added 2 bytes + throw new ZipException("Directory compressed size invalid"); + } + } + + if (!ZipNameTransform.IsValidName(localName, true)) + { + throw new ZipException("Name is invalid"); + } + } + + // Tests that apply to both data and header. + + // Size can be verified only if it is known in the local header. + // it will always be known in the central header. + if (((localFlags & (int)GeneralBitFlags.Descriptor) == 0) || + ((size > 0) || (compressedSize > 0))) { + + if (size != entry.Size) { + throw new ZipException( + string.Format("Size mismatch between central header({0}) and local header({1})", + entry.Size, size)); + } + + if (compressedSize != entry.CompressedSize && + compressedSize != 0xFFFFFFFF && compressedSize != -1) { + throw new ZipException( + string.Format("Compressed size mismatch between central header({0}) and local header({1})", + entry.CompressedSize, compressedSize)); + } + } + + int extraLength = storedNameLength + extraDataLength; + return offsetOfFirstEntry + entry.Offset + ZipConstants.LocalHeaderBaseSize + extraLength; + } + } + + #endregion + + #region Updating + + const int DefaultBufferSize = 4096; + + /// + /// The kind of update to apply. + /// + enum UpdateCommand + { + Copy, // Copy original file contents. + Modify, // Change encryption, compression, attributes, name, time etc, of an existing file. + Add, // Add a new file to the archive. + } + + #region Properties + /// + /// Get / set the to apply to names when updating. + /// + public INameTransform NameTransform + { + get { + return updateEntryFactory_.NameTransform; + } + + set { + updateEntryFactory_.NameTransform = value; + } + } + + /// + /// Get/set the used to generate values + /// during updates. + /// + public IEntryFactory EntryFactory + { + get { + return updateEntryFactory_; + } + + set { + if (value == null) { + updateEntryFactory_ = new ZipEntryFactory(); + } + else { + updateEntryFactory_ = value; + } + } + } + + /// + /// Get /set the buffer size to be used when updating this zip file. + /// + public int BufferSize + { + get { return bufferSize_; } + set { + if ( value < 1024 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "cannot be below 1024"); +#endif + } + + if ( bufferSize_ != value ) { + bufferSize_ = value; + copyBuffer_ = null; + } + } + } + + /// + /// Get a value indicating an update has been started. + /// + public bool IsUpdating + { + get { return updates_ != null; } + } + + /// + /// Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + /// + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + #endregion + + #region Immediate updating +// TBD: Direct form of updating +// +// public void Update(IEntryMatcher deleteMatcher) +// { +// } +// +// public void Update(IScanner addScanner) +// { +// } + #endregion + + #region Deferred Updating + /// + /// Begin updating this archive. + /// + /// The archive storage for use during the update. + /// The data source to utilise during updating. + /// ZipFile has been closed. + /// One of the arguments provided is null + /// ZipFile has been closed. + public void BeginUpdate(IArchiveStorage archiveStorage, IDynamicDataSource dataSource) + { + if ( archiveStorage == null ) { + throw new ArgumentNullException("archiveStorage"); + } + + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + if ( IsEmbeddedArchive ) { + throw new ZipException ("Cannot update embedded/SFX archives"); + } + + archiveStorage_ = archiveStorage; + updateDataSource_ = dataSource; + + // NOTE: the baseStream_ may not currently support writing or seeking. + + updateIndex_ = new Hashtable(); + + updates_ = new ArrayList(entries_.Length); + foreach(ZipEntry entry in entries_) { + int index = updates_.Add(new ZipUpdate(entry)); + updateIndex_.Add(entry.Name, index); + } + + // We must sort by offset before using offset's calculated sizes + updates_.Sort(new UpdateComparer()); + + int idx = 0; + foreach (ZipUpdate update in updates_) { + //If last entry, there is no next entry offset to use + if (idx == updates_.Count - 1) + break; + + update.OffsetBasedSize = ((ZipUpdate)updates_[idx + 1]).Entry.Offset - update.Entry.Offset; + idx++; + } + updateCount_ = updates_.Count; + + contentsEdited_ = false; + commentEdited_ = false; + newComment_ = null; + } + + /// + /// Begin updating to this archive. + /// + /// The storage to use during the update. + public void BeginUpdate(IArchiveStorage archiveStorage) + { + BeginUpdate(archiveStorage, new DynamicDiskDataSource()); + } + + /// + /// Begin updating this archive. + /// + /// + /// + /// + public void BeginUpdate() + { + if ( Name == null ) { + BeginUpdate(new MemoryArchiveStorage(), new DynamicDiskDataSource()); + } + else { + BeginUpdate(new DiskArchiveStorage(this), new DynamicDiskDataSource()); + } + } + + /// + /// Commit current updates, updating this archive. + /// + /// + /// + /// ZipFile has been closed. + public void CommitUpdate() + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + CheckUpdating(); + + try { + updateIndex_.Clear(); + updateIndex_=null; + + if( contentsEdited_ ) { + RunUpdates(); + } + else if( commentEdited_ ) { + UpdateCommentOnly(); + } + else { + // Create an empty archive if none existed originally. + if( entries_.Length==0 ) { + byte[] theComment=(newComment_!=null)?newComment_.RawComment:ZipConstants.ConvertToArray(comment_); + using( ZipHelperStream zhs=new ZipHelperStream(baseStream_) ) { + zhs.WriteEndOfCentralDirectory(0, 0, 0, theComment); + } + } + } + + } + finally { + PostUpdateCleanup(); + } + } + + /// + /// Abort updating leaving the archive unchanged. + /// + /// + /// + public void AbortUpdate() + { + PostUpdateCleanup(); + } + + /// + /// Set the file comment to be recorded when the current update is commited. + /// + /// The comment to record. + /// ZipFile has been closed. + public void SetComment(string comment) + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + CheckUpdating(); + + newComment_ = new ZipString(comment); + + if ( newComment_.RawLength > 0xffff ) { + newComment_ = null; + throw new ZipException("Comment length exceeds maximum - 65535"); + } + + // We dont take account of the original and current comment appearing to be the same + // as encoding may be different. + commentEdited_ = true; + } + + #endregion + + #region Adding Entries + + void AddUpdate(ZipUpdate update) + { + contentsEdited_ = true; + + int index = FindExistingUpdate(update.Entry.Name); + + if (index >= 0) { + if ( updates_[index] == null ) { + updateCount_ += 1; + } + + // Direct replacement is faster than delete and add. + updates_[index] = update; + } + else { + index = updates_.Add(update); + updateCount_ += 1; + updateIndex_.Add(update.Entry.Name, index); + } + } + + /// + /// Add a new entry to the archive. + /// + /// The name of the file to add. + /// The compression method to use. + /// Ensure Unicode text is used for name and comment for this entry. + /// Argument supplied is null. + /// ZipFile has been closed. + /// Compression method is not supported. + public void Add(string fileName, CompressionMethod compressionMethod, bool useUnicodeText ) + { + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + if (!ZipEntry.IsCompressionMethodSupported(compressionMethod)) { + throw new ArgumentOutOfRangeException("compressionMethod"); + } + + CheckUpdating(); + contentsEdited_ = true; + + ZipEntry entry = EntryFactory.MakeFileEntry(fileName); + entry.IsUnicodeText = useUnicodeText; + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(fileName, entry)); + } + + /// + /// Add a new entry to the archive. + /// + /// The name of the file to add. + /// The compression method to use. + /// ZipFile has been closed. + /// The compression method is not supported. + public void Add(string fileName, CompressionMethod compressionMethod) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + if ( !ZipEntry.IsCompressionMethodSupported(compressionMethod) ) { + throw new ArgumentOutOfRangeException("compressionMethod"); + } + + CheckUpdating(); + contentsEdited_ = true; + + ZipEntry entry = EntryFactory.MakeFileEntry(fileName); + entry.CompressionMethod = compressionMethod; + AddUpdate(new ZipUpdate(fileName, entry)); + } + + /// + /// Add a file to the archive. + /// + /// The name of the file to add. + /// Argument supplied is null. + public void Add(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(fileName, EntryFactory.MakeFileEntry(fileName))); + } + + /// + /// Add a file to the archive. + /// + /// The name of the file to add. + /// The name to use for the on the Zip file created. + /// Argument supplied is null. + public void Add(string fileName, string entryName) + { + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(fileName, EntryFactory.MakeFileEntry(entryName))); + } + + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + public void Add(IStaticDataSource dataSource, string entryName) + { + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(dataSource, EntryFactory.MakeFileEntry(entryName, false))); + } + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + /// The compression method to use. + public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod) + { + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + + ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false); + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(dataSource, entry)); + } + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + /// The compression method to use. + /// Ensure Unicode text is used for name and comments for this entry. + public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod, bool useUnicodeText) + { + if (dataSource == null) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + + ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false); + entry.IsUnicodeText = useUnicodeText; + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(dataSource, entry)); + } + + /// + /// Add a that contains no data. + /// + /// The entry to add. + /// This can be used to add directories, volume labels, or empty file entries. + public void Add(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + CheckUpdating(); + + if ( (entry.Size != 0) || (entry.CompressedSize != 0) ) { + throw new ZipException("Entry cannot have any data"); + } + + AddUpdate(new ZipUpdate(UpdateCommand.Add, entry)); + } + + /// + /// Add a directory entry to the archive. + /// + /// The directory to add. + public void AddDirectory(string directoryName) + { + if ( directoryName == null ) { + throw new ArgumentNullException("directoryName"); + } + + CheckUpdating(); + + ZipEntry dirEntry = EntryFactory.MakeDirectoryEntry(directoryName); + AddUpdate(new ZipUpdate(UpdateCommand.Add, dirEntry)); + } + + #endregion + + #region Modifying Entries +/* Modify not yet ready for public consumption. + Direct modification of an entry should not overwrite original data before its read. + Safe mode is trivial in this sense. + public void Modify(ZipEntry original, ZipEntry updated) + { + if ( original == null ) { + throw new ArgumentNullException("original"); + } + + if ( updated == null ) { + throw new ArgumentNullException("updated"); + } + + CheckUpdating(); + contentsEdited_ = true; + updates_.Add(new ZipUpdate(original, updated)); + } +*/ + #endregion + + #region Deleting Entries + /// + /// Delete an entry by name + /// + /// The filename to delete + /// True if the entry was found and deleted; false otherwise. + public bool Delete(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + CheckUpdating(); + + bool result = false; + int index = FindExistingUpdate(fileName); + if ( (index >= 0) && (updates_[index] != null) ) { + result = true; + contentsEdited_ = true; + updates_[index] = null; + updateCount_ -= 1; + } + else { + throw new ZipException("Cannot find entry to delete"); + } + return result; + } + + /// + /// Delete a from the archive. + /// + /// The entry to delete. + public void Delete(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + CheckUpdating(); + + int index = FindExistingUpdate(entry); + if ( index >= 0 ) { + contentsEdited_ = true; + updates_[index] = null; + updateCount_ -= 1; + } + else { + throw new ZipException("Cannot find entry to delete"); + } + } + + #endregion + + #region Update Support + + #region Writing Values/Headers + void WriteLEShort(int value) + { + baseStream_.WriteByte(( byte )(value & 0xff)); + baseStream_.WriteByte(( byte )((value >> 8) & 0xff)); + } + + /// + /// Write an unsigned short in little endian byte order. + /// + void WriteLEUshort(ushort value) + { + baseStream_.WriteByte(( byte )(value & 0xff)); + baseStream_.WriteByte(( byte )(value >> 8)); + } + + /// + /// Write an int in little endian byte order. + /// + void WriteLEInt(int value) + { + WriteLEShort(value & 0xffff); + WriteLEShort(value >> 16); + } + + /// + /// Write an unsigned int in little endian byte order. + /// + void WriteLEUint(uint value) + { + WriteLEUshort((ushort)(value & 0xffff)); + WriteLEUshort((ushort)(value >> 16)); + } + + /// + /// Write a long in little endian byte order. + /// + void WriteLeLong(long value) + { + WriteLEInt(( int )(value & 0xffffffff)); + WriteLEInt(( int )(value >> 32)); + } + + void WriteLEUlong(ulong value) + { + WriteLEUint(( uint )(value & 0xffffffff)); + WriteLEUint(( uint )(value >> 32)); + } + + void WriteLocalEntryHeader(ZipUpdate update) + { + ZipEntry entry = update.OutEntry; + + // TODO: Local offset will require adjusting for multi-disk zip files. + entry.Offset = baseStream_.Position; + + // TODO: Need to clear any entry flags that dont make sense or throw an exception here. + if (update.Command != UpdateCommand.Copy) { + if (entry.CompressionMethod == CompressionMethod.Deflated) { + if (entry.Size == 0) { + // No need to compress - no data. + entry.CompressedSize = entry.Size; + entry.Crc = 0; + entry.CompressionMethod = CompressionMethod.Stored; + } + } + else if (entry.CompressionMethod == CompressionMethod.Stored) { + entry.Flags &= ~(int)GeneralBitFlags.Descriptor; + } + + if (HaveKeys) { + entry.IsCrypted = true; + if (entry.Crc < 0) { + entry.Flags |= (int)GeneralBitFlags.Descriptor; + } + } + else { + entry.IsCrypted = false; + } + + switch (useZip64_) { + case UseZip64.Dynamic: + if (entry.Size < 0) { + entry.ForceZip64(); + } + break; + + case UseZip64.On: + entry.ForceZip64(); + break; + + case UseZip64.Off: + // Do nothing. The entry itself may be using Zip64 independantly. + break; + } + } + + // Write the local file header + WriteLEInt(ZipConstants.LocalHeaderSignature); + + WriteLEShort(entry.Version); + WriteLEShort(entry.Flags); + + WriteLEShort((byte)entry.CompressionMethod); + WriteLEInt(( int )entry.DosTime); + + if ( !entry.HasCrc ) { + // Note patch address for updating CRC later. + update.CrcPatchOffset = baseStream_.Position; + WriteLEInt(( int )0); + } + else { + WriteLEInt(unchecked(( int )entry.Crc)); + } + + if (entry.LocalHeaderRequiresZip64) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + if ( (entry.CompressedSize < 0) || (entry.Size < 0) ) { + update.SizePatchOffset = baseStream_.Position; + } + + WriteLEInt(( int )entry.CompressedSize); + WriteLEInt(( int )entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if ( name.Length > 0xFFFF ) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.LocalHeaderRequiresZip64 ) { + ed.StartNewEntry(); + + // Local entry header always includes size and compressed size. + // NOTE the order of these fields is reversed when compared to the normal headers! + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + ed.AddNewEntry(1); + } + else { + ed.Delete(1); + } + + entry.ExtraData = ed.GetEntryData(); + + WriteLEShort(name.Length); + WriteLEShort(entry.ExtraData.Length); + + if ( name.Length > 0 ) { + baseStream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 ) { + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cannot find extra data"); + } + + update.SizePatchOffset = baseStream_.Position + ed.CurrentReadIndex; + } + + if ( entry.ExtraData.Length > 0 ) { + baseStream_.Write(entry.ExtraData, 0, entry.ExtraData.Length); + } + } + + int WriteCentralDirectoryHeader(ZipEntry entry) + { + if ( entry.CompressedSize < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown csize"); + } + + if ( entry.Size < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown size"); + } + + if ( entry.Crc < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown crc"); + } + + // Write the central file header + WriteLEInt(ZipConstants.CentralHeaderSignature); + + // Version made by + WriteLEShort(ZipConstants.VersionMadeBy); + + // Version required to extract + WriteLEShort(entry.Version); + + WriteLEShort(entry.Flags); + + unchecked { + WriteLEShort((byte)entry.CompressionMethod); + WriteLEInt((int)entry.DosTime); + WriteLEInt((int)entry.Crc); + } + + if ( (entry.IsZip64Forced()) || (entry.CompressedSize >= 0xffffffff) ) { + WriteLEInt(-1); + } + else { + WriteLEInt((int)(entry.CompressedSize & 0xffffffff)); + } + + if ( (entry.IsZip64Forced()) || (entry.Size >= 0xffffffff) ) { + WriteLEInt(-1); + } + else { + WriteLEInt((int)entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if ( name.Length > 0xFFFF ) { + throw new ZipException("Entry name is too long."); + } + + WriteLEShort(name.Length); + + // Central header extra data is different to local header version so regenerate. + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.CentralHeaderRequiresZip64 ) { + ed.StartNewEntry(); + + if ( (entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) ) + { + ed.AddLeLong(entry.Size); + } + + if ( (entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) ) + { + ed.AddLeLong(entry.CompressedSize); + } + + if ( entry.Offset >= 0xffffffff ) { + ed.AddLeLong(entry.Offset); + } + + // Number of disk on which this file starts isnt supported and is never written here. + ed.AddNewEntry(1); + } + else { + // Should have already be done when local header was added. + ed.Delete(1); + } + + byte[] centralExtraData = ed.GetEntryData(); + + WriteLEShort(centralExtraData.Length); + WriteLEShort(entry.Comment != null ? entry.Comment.Length : 0); + + WriteLEShort(0); // disk number + WriteLEShort(0); // internal file attributes + + // External file attributes... + if ( entry.ExternalFileAttributes != -1 ) { + WriteLEInt(entry.ExternalFileAttributes); + } + else { + if ( entry.IsDirectory ) { + WriteLEUint(16); + } + else { + WriteLEUint(0); + } + } + + if ( entry.Offset >= 0xffffffff ) { + WriteLEUint(0xffffffff); + } + else { + WriteLEUint((uint)(int)entry.Offset); + } + + if ( name.Length > 0 ) { + baseStream_.Write(name, 0, name.Length); + } + + if ( centralExtraData.Length > 0 ) { + baseStream_.Write(centralExtraData, 0, centralExtraData.Length); + } + + byte[] rawComment = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : new byte[0]; + + if ( rawComment.Length > 0 ) { + baseStream_.Write(rawComment, 0, rawComment.Length); + } + + return ZipConstants.CentralHeaderBaseSize + name.Length + centralExtraData.Length + rawComment.Length; + } + #endregion + + void PostUpdateCleanup() + { + updateDataSource_ = null; + updates_ = null; + updateIndex_ = null; + + if (archiveStorage_ != null) + { + archiveStorage_.Dispose(); + archiveStorage_=null; + } + } + + string GetTransformedFileName(string name) + { + INameTransform transform = NameTransform; + return (transform != null) ? + transform.TransformFile(name) : + name; + } + + string GetTransformedDirectoryName(string name) + { + INameTransform transform = NameTransform; + return (transform != null) ? + transform.TransformDirectory(name) : + name; + } + + /// + /// Get a raw memory buffer. + /// + /// Returns a raw memory buffer. + byte[] GetBuffer() + { + if ( copyBuffer_ == null ) { + copyBuffer_ = new byte[bufferSize_]; + } + return copyBuffer_; + } + + void CopyDescriptorBytes(ZipUpdate update, Stream dest, Stream source) + { + int bytesToCopy = GetDescriptorSize(update); + + if ( bytesToCopy > 0 ) { + byte[] buffer = GetBuffer(); + + while ( bytesToCopy > 0 ) { + int readSize = Math.Min(buffer.Length, bytesToCopy); + + int bytesRead = source.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + dest.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + } + else { + throw new ZipException("Unxpected end of stream"); + } + } + } + } + + void CopyBytes(ZipUpdate update, Stream destination, Stream source, + long bytesToCopy, bool updateCrc) + { + if ( destination == source ) { + throw new InvalidOperationException("Destination and source are the same"); + } + + // NOTE: Compressed size is updated elsewhere. + Crc32 crc = new Crc32(); + byte[] buffer = GetBuffer(); + + long targetBytes = bytesToCopy; + long totalBytesRead = 0; + + int bytesRead; + do { + int readSize = buffer.Length; + + if ( bytesToCopy < readSize ) { + readSize = (int)bytesToCopy; + } + + bytesRead = source.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + if ( updateCrc ) { + crc.Update(buffer, 0, bytesRead); + } + destination.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + totalBytesRead += bytesRead; + } + } + while ( (bytesRead > 0) && (bytesToCopy > 0) ); + + if ( totalBytesRead != targetBytes ) { + throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); + } + + if ( updateCrc ) { + update.OutEntry.Crc = crc.Value; + } + } + + /// + /// Get the size of the source descriptor for a . + /// + /// The update to get the size for. + /// The descriptor size, zero if there isnt one. + int GetDescriptorSize(ZipUpdate update) + { + int result = 0; + if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) { + result = ZipConstants.DataDescriptorSize - 4; + if ( update.Entry.LocalHeaderRequiresZip64 ) { + result = ZipConstants.Zip64DataDescriptorSize - 4; + } + } + return result; + } + + void CopyDescriptorBytesDirect(ZipUpdate update, Stream stream, ref long destinationPosition, long sourcePosition) + { + int bytesToCopy = GetDescriptorSize(update); + + while ( bytesToCopy > 0 ) { + int readSize = (int)bytesToCopy; + byte[] buffer = GetBuffer(); + + stream.Position = sourcePosition; + int bytesRead = stream.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + stream.Position = destinationPosition; + stream.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + destinationPosition += bytesRead; + sourcePosition += bytesRead; + } + else { + throw new ZipException("Unxpected end of stream"); + } + } + } + + void CopyEntryDataDirect(ZipUpdate update, Stream stream, bool updateCrc, ref long destinationPosition, ref long sourcePosition) + { + long bytesToCopy = update.Entry.CompressedSize; + + // NOTE: Compressed size is updated elsewhere. + Crc32 crc = new Crc32(); + byte[] buffer = GetBuffer(); + + long targetBytes = bytesToCopy; + long totalBytesRead = 0; + + int bytesRead; + do + { + int readSize = buffer.Length; + + if ( bytesToCopy < readSize ) { + readSize = (int)bytesToCopy; + } + + stream.Position = sourcePosition; + bytesRead = stream.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + if ( updateCrc ) { + crc.Update(buffer, 0, bytesRead); + } + stream.Position = destinationPosition; + stream.Write(buffer, 0, bytesRead); + + destinationPosition += bytesRead; + sourcePosition += bytesRead; + bytesToCopy -= bytesRead; + totalBytesRead += bytesRead; + } + } + while ( (bytesRead > 0) && (bytesToCopy > 0) ); + + if ( totalBytesRead != targetBytes ) { + throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); + } + + if ( updateCrc ) { + update.OutEntry.Crc = crc.Value; + } + } + + int FindExistingUpdate(ZipEntry entry) + { + int result = -1; + string convertedName = GetTransformedFileName(entry.Name); + + if (updateIndex_.ContainsKey(convertedName)) { + result = (int)updateIndex_[convertedName]; + } +/* + // This is slow like the coming of the next ice age but takes less storage and may be useful + // for CF? + for (int index = 0; index < updates_.Count; ++index) + { + ZipUpdate zu = ( ZipUpdate )updates_[index]; + if ( (zu.Entry.ZipFileIndex == entry.ZipFileIndex) && + (string.Compare(convertedName, zu.Entry.Name, true, CultureInfo.InvariantCulture) == 0) ) { + result = index; + break; + } + } + */ + return result; + } + + int FindExistingUpdate(string fileName) + { + int result = -1; + + string convertedName = GetTransformedFileName(fileName); + + if (updateIndex_.ContainsKey(convertedName)) { + result = (int)updateIndex_[convertedName]; + } + +/* + // This is slow like the coming of the next ice age but takes less storage and may be useful + // for CF? + for ( int index = 0; index < updates_.Count; ++index ) { + if ( string.Compare(convertedName, (( ZipUpdate )updates_[index]).Entry.Name, + true, CultureInfo.InvariantCulture) == 0 ) { + result = index; + break; + } + } + */ + + return result; + } + + /// + /// Get an output stream for the specified + /// + /// The entry to get an output stream for. + /// The output stream obtained for the entry. + Stream GetOutputStream(ZipEntry entry) + { + Stream result = baseStream_; + + if ( entry.IsCrypted == true ) { +#if NETCF_1_0 + throw new ZipException("Encryption not supported for Compact Framework 1.0"); +#else + result = CreateAndInitEncryptionStream(result, entry); +#endif + } + + switch ( entry.CompressionMethod ) { + case CompressionMethod.Stored: + result = new UncompressedStream(result); + break; + + case CompressionMethod.Deflated: + DeflaterOutputStream dos = new DeflaterOutputStream(result, new Deflater(9, true)); + dos.IsStreamOwner = false; + result = dos; + break; + + default: + throw new ZipException("Unknown compression method " + entry.CompressionMethod); + } + return result; + } + + void AddEntry(ZipFile workFile, ZipUpdate update) + { + Stream source = null; + + if ( update.Entry.IsFile ) { + source = update.GetSource(); + + if ( source == null ) { + source = updateDataSource_.GetSource(update.Entry, update.Filename); + } + } + + if ( source != null ) { + using ( source ) { + long sourceStreamLength = source.Length; + if ( update.OutEntry.Size < 0 ) { + update.OutEntry.Size = sourceStreamLength; + } + else { + // Check for errant entries. + if ( update.OutEntry.Size != sourceStreamLength ) { + throw new ZipException("Entry size/stream size mismatch"); + } + } + + workFile.WriteLocalEntryHeader(update); + + long dataStart = workFile.baseStream_.Position; + + using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) { + CopyBytes(update, output, source, sourceStreamLength, true); + } + + long dataEnd = workFile.baseStream_.Position; + update.OutEntry.CompressedSize = dataEnd - dataStart; + + if ((update.OutEntry.Flags & (int)GeneralBitFlags.Descriptor) == (int)GeneralBitFlags.Descriptor) + { + ZipHelperStream helper = new ZipHelperStream(workFile.baseStream_); + helper.WriteDataDescriptor(update.OutEntry); + } + } + } + else { + workFile.WriteLocalEntryHeader(update); + update.OutEntry.CompressedSize = 0; + } + + } + + void ModifyEntry(ZipFile workFile, ZipUpdate update) + { + workFile.WriteLocalEntryHeader(update); + long dataStart = workFile.baseStream_.Position; + + // TODO: This is slow if the changes don't effect the data!! + if ( update.Entry.IsFile && (update.Filename != null) ) { + using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) { + using ( Stream source = this.GetInputStream(update.Entry) ) { + CopyBytes(update, output, source, source.Length, true); + } + } + } + + long dataEnd = workFile.baseStream_.Position; + update.Entry.CompressedSize = dataEnd - dataStart; + } + + void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition) + { + bool skipOver = false; + if ( update.Entry.Offset == destinationPosition ) { + skipOver = true; + } + + if ( !skipOver ) { + baseStream_.Position = destinationPosition; + workFile.WriteLocalEntryHeader(update); + destinationPosition = baseStream_.Position; + } + + long sourcePosition = 0; + + const int NameLengthOffset = 26; + + // TODO: Add base for SFX friendly handling + long entryDataOffset = update.Entry.Offset + NameLengthOffset; + + baseStream_.Seek(entryDataOffset, SeekOrigin.Begin); + + // Clumsy way of handling retrieving the original name and extra data length for now. + // TODO: Stop re-reading name and data length in CopyEntryDirect. + uint nameLength = ReadLEUshort(); + uint extraLength = ReadLEUshort(); + + sourcePosition = baseStream_.Position + nameLength + extraLength; + + if (skipOver) { + if (update.OffsetBasedSize != -1) + destinationPosition += update.OffsetBasedSize; + else + // TODO: Find out why this calculation comes up 4 bytes short on some entries in ODT (Office Document Text) archives. + // WinZip produces a warning on these entries: + // "caution: value of lrec.csize (compressed size) changed from ..." + destinationPosition += + (sourcePosition - entryDataOffset) + NameLengthOffset + // Header size + update.Entry.CompressedSize + GetDescriptorSize(update); + } + else { + if ( update.Entry.CompressedSize > 0 ) { + CopyEntryDataDirect(update, baseStream_, false, ref destinationPosition, ref sourcePosition ); + } + CopyDescriptorBytesDirect(update, baseStream_, ref destinationPosition, sourcePosition); + } + } + + void CopyEntry(ZipFile workFile, ZipUpdate update) + { + workFile.WriteLocalEntryHeader(update); + + if ( update.Entry.CompressedSize > 0 ) { + const int NameLengthOffset = 26; + + long entryDataOffset = update.Entry.Offset + NameLengthOffset; + + // TODO: This wont work for SFX files! + baseStream_.Seek(entryDataOffset, SeekOrigin.Begin); + + uint nameLength = ReadLEUshort(); + uint extraLength = ReadLEUshort(); + + baseStream_.Seek(nameLength + extraLength, SeekOrigin.Current); + + CopyBytes(update, workFile.baseStream_, baseStream_, update.Entry.CompressedSize, false); + } + CopyDescriptorBytes(update, workFile.baseStream_, baseStream_); + } + + void Reopen(Stream source) + { + if ( source == null ) { + throw new ZipException("Failed to reopen archive - no source"); + } + + isNewArchive_ = false; + baseStream_ = source; + ReadEntries(); + } + + void Reopen() + { + if (Name == null) { + throw new InvalidOperationException("Name is not known cannot Reopen"); + } + + Reopen(File.Open(Name, FileMode.Open, FileAccess.Read, FileShare.Read)); + } + + void UpdateCommentOnly() + { + long baseLength = baseStream_.Length; + + ZipHelperStream updateFile = null; + + if ( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { + Stream copyStream = archiveStorage_.MakeTemporaryCopy(baseStream_); + updateFile = new ZipHelperStream(copyStream); + updateFile.IsStreamOwner = true; + + baseStream_.Close(); + baseStream_ = null; + } + else { + if (archiveStorage_.UpdateMode == FileUpdateMode.Direct) { + // TODO: archiveStorage wasnt originally intended for this use. + // Need to revisit this to tidy up handling as archive storage currently doesnt + // handle the original stream well. + // The problem is when using an existing zip archive with an in memory archive storage. + // The open stream wont support writing but the memory storage should open the same file not an in memory one. + + // Need to tidy up the archive storage interface and contract basically. + baseStream_ = archiveStorage_.OpenForDirectUpdate(baseStream_); + updateFile = new ZipHelperStream(baseStream_); + } + else { + baseStream_.Close(); + baseStream_ = null; + updateFile = new ZipHelperStream(Name); + } + } + + using ( updateFile ) { + long locatedCentralDirOffset = + updateFile.LocateBlockWithSignature(ZipConstants.EndOfCentralDirectorySignature, + baseLength, ZipConstants.EndOfCentralRecordBaseSize, 0xffff); + if ( locatedCentralDirOffset < 0 ) { + throw new ZipException("Cannot find central directory"); + } + + const int CentralHeaderCommentSizeOffset = 16; + updateFile.Position += CentralHeaderCommentSizeOffset; + + byte[] rawComment = newComment_.RawComment; + + updateFile.WriteLEShort(rawComment.Length); + updateFile.Write(rawComment, 0, rawComment.Length); + updateFile.SetLength(updateFile.Position); + } + + if ( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { + Reopen(archiveStorage_.ConvertTemporaryToFinal()); + } + else { + ReadEntries(); + } + } + + /// + /// Class used to sort updates. + /// + class UpdateComparer : IComparer + { + /// + /// Compares two objects and returns a value indicating whether one is + /// less than, equal to or greater than the other. + /// + /// First object to compare + /// Second object to compare. + /// Compare result. + public int Compare( + object x, + object y) + { + ZipUpdate zx = x as ZipUpdate; + ZipUpdate zy = y as ZipUpdate; + + int result; + + if (zx == null) { + if (zy == null) { + result = 0; + } + else { + result = -1; + } + } + else if (zy == null) { + result = 1; + } + else { + int xCmdValue = ((zx.Command == UpdateCommand.Copy) || (zx.Command == UpdateCommand.Modify)) ? 0 : 1; + int yCmdValue = ((zy.Command == UpdateCommand.Copy) || (zy.Command == UpdateCommand.Modify)) ? 0 : 1; + + result = xCmdValue - yCmdValue; + if (result == 0) { + long offsetDiff = zx.Entry.Offset - zy.Entry.Offset; + if (offsetDiff < 0) { + result = -1; + } + else if (offsetDiff == 0) { + result = 0; + } + else { + result = 1; + } + } + } + return result; + } + } + + void RunUpdates() + { + long sizeEntries = 0; + long endOfStream = 0; + bool directUpdate = false; + long destinationPosition = 0; // NOT SFX friendly + + ZipFile workFile; + + if ( IsNewArchive ) { + workFile = this; + workFile.baseStream_.Position = 0; + directUpdate = true; + } + else if ( archiveStorage_.UpdateMode == FileUpdateMode.Direct ) { + workFile = this; + workFile.baseStream_.Position = 0; + directUpdate = true; + + // Sort the updates by offset within copies/modifies, then adds. + // This ensures that data required by copies will not be overwritten. + updates_.Sort(new UpdateComparer()); + } + else { + workFile = ZipFile.Create(archiveStorage_.GetTemporaryOutput()); + workFile.UseZip64 = UseZip64; + + if (key != null) { + workFile.key = (byte[])key.Clone(); + } + } + + try { + foreach ( ZipUpdate update in updates_ ) { + if (update != null) { + switch (update.Command) { + case UpdateCommand.Copy: + if (directUpdate) { + CopyEntryDirect(workFile, update, ref destinationPosition); + } + else { + CopyEntry(workFile, update); + } + break; + + case UpdateCommand.Modify: + // TODO: Direct modifying of an entry will take some legwork. + ModifyEntry(workFile, update); + break; + + case UpdateCommand.Add: + if (!IsNewArchive && directUpdate) { + workFile.baseStream_.Position = destinationPosition; + } + + AddEntry(workFile, update); + + if (directUpdate) { + destinationPosition = workFile.baseStream_.Position; + } + break; + } + } + } + + if ( !IsNewArchive && directUpdate ) { + workFile.baseStream_.Position = destinationPosition; + } + + long centralDirOffset = workFile.baseStream_.Position; + + foreach ( ZipUpdate update in updates_ ) { + if (update != null) { + sizeEntries += workFile.WriteCentralDirectoryHeader(update.OutEntry); + } + } + + byte[] theComment = (newComment_ != null) ? newComment_.RawComment : ZipConstants.ConvertToArray(comment_); + using ( ZipHelperStream zhs = new ZipHelperStream(workFile.baseStream_) ) { + zhs.WriteEndOfCentralDirectory(updateCount_, sizeEntries, centralDirOffset, theComment); + } + + endOfStream = workFile.baseStream_.Position; + + // And now patch entries... + foreach ( ZipUpdate update in updates_ ) { + if (update != null) + { + // If the size of the entry is zero leave the crc as 0 as well. + // The calculated crc will be all bits on... + if ((update.CrcPatchOffset > 0) && (update.OutEntry.CompressedSize > 0)) { + workFile.baseStream_.Position = update.CrcPatchOffset; + workFile.WriteLEInt((int)update.OutEntry.Crc); + } + + if (update.SizePatchOffset > 0) { + workFile.baseStream_.Position = update.SizePatchOffset; + if (update.OutEntry.LocalHeaderRequiresZip64) { + workFile.WriteLeLong(update.OutEntry.Size); + workFile.WriteLeLong(update.OutEntry.CompressedSize); + } + else { + workFile.WriteLEInt((int)update.OutEntry.CompressedSize); + workFile.WriteLEInt((int)update.OutEntry.Size); + } + } + } + } + } + catch { + workFile.Close(); + if (!directUpdate && (workFile.Name != null)) { + File.Delete(workFile.Name); + } + throw; + } + + if (directUpdate) { + workFile.baseStream_.SetLength(endOfStream); + workFile.baseStream_.Flush(); + isNewArchive_ = false; + ReadEntries(); + } + else { + baseStream_.Close(); + Reopen(archiveStorage_.ConvertTemporaryToFinal()); + } + } + + void CheckUpdating() + { + if ( updates_ == null ) { + throw new InvalidOperationException("BeginUpdate has not been called"); + } + } + + #endregion + + #region ZipUpdate class + /// + /// Represents a pending update to a Zip file. + /// + class ZipUpdate + { + #region Constructors + public ZipUpdate(string fileName, ZipEntry entry) + { + command_ = UpdateCommand.Add; + entry_ = entry; + filename_ = fileName; + } + + [Obsolete] + public ZipUpdate(string fileName, string entryName, CompressionMethod compressionMethod) + { + command_ = UpdateCommand.Add; + entry_ = new ZipEntry(entryName); + entry_.CompressionMethod = compressionMethod; + filename_ = fileName; + } + + [Obsolete] + public ZipUpdate(string fileName, string entryName) + : this(fileName, entryName, CompressionMethod.Deflated) + { + // Do nothing. + } + + [Obsolete] + public ZipUpdate(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod) + { + command_ = UpdateCommand.Add; + entry_ = new ZipEntry(entryName); + entry_.CompressionMethod = compressionMethod; + dataSource_ = dataSource; + } + + public ZipUpdate(IStaticDataSource dataSource, ZipEntry entry) + { + command_ = UpdateCommand.Add; + entry_ = entry; + dataSource_ = dataSource; + } + + public ZipUpdate(ZipEntry original, ZipEntry updated) + { + throw new ZipException("Modify not currently supported"); + /* + command_ = UpdateCommand.Modify; + entry_ = ( ZipEntry )original.Clone(); + outEntry_ = ( ZipEntry )updated.Clone(); + */ + } + + public ZipUpdate(UpdateCommand command, ZipEntry entry) + { + command_ = command; + entry_ = ( ZipEntry )entry.Clone(); + } + + + /// + /// Copy an existing entry. + /// + /// The existing entry to copy. + public ZipUpdate(ZipEntry entry) + : this(UpdateCommand.Copy, entry) + { + // Do nothing. + } + #endregion + + /// + /// Get the for this update. + /// + /// This is the source or original entry. + public ZipEntry Entry + { + get { return entry_; } + } + + /// + /// Get the that will be written to the updated/new file. + /// + public ZipEntry OutEntry + { + get { + if ( outEntry_ == null ) { + outEntry_ = (ZipEntry)entry_.Clone(); + } + + return outEntry_; + } + } + + /// + /// Get the command for this update. + /// + public UpdateCommand Command + { + get { return command_; } + } + + /// + /// Get the filename if any for this update. Null if none exists. + /// + public string Filename + { + get { return filename_; } + } + + /// + /// Get/set the location of the size patch for this update. + /// + public long SizePatchOffset + { + get { return sizePatchOffset_; } + set { sizePatchOffset_ = value; } + } + + /// + /// Get /set the location of the crc patch for this update. + /// + public long CrcPatchOffset + { + get { return crcPatchOffset_; } + set { crcPatchOffset_ = value; } + } + + /// + /// Get/set the size calculated by offset. + /// Specifically, the difference between this and next entry's starting offset. + /// + public long OffsetBasedSize + { + get { return _offsetBasedSize; } + set { _offsetBasedSize = value; } + } + + public Stream GetSource() + { + Stream result = null; + if ( dataSource_ != null ) { + result = dataSource_.GetSource(); + } + + return result; + } + + #region Instance Fields + ZipEntry entry_; + ZipEntry outEntry_; + UpdateCommand command_; + IStaticDataSource dataSource_; + string filename_; + long sizePatchOffset_ = -1; + long crcPatchOffset_ = -1; + long _offsetBasedSize = -1; + #endregion + } + + #endregion + #endregion + + #region Disposing + + #region IDisposable Members + void IDisposable.Dispose() + { + Close(); + } + #endregion + + void DisposeInternal(bool disposing) + { + if ( !isDisposed_ ) { + isDisposed_ = true; + entries_ = new ZipEntry[0]; + + if ( IsStreamOwner && (baseStream_ != null) ) { + lock(baseStream_) { + baseStream_.Close(); + } + } + + PostUpdateCleanup(); + } + } + + /// + /// Releases the unmanaged resources used by the this instance and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + DisposeInternal(disposing); + } + + #endregion + + #region Internal routines + #region Reading + /// + /// Read an unsigned short in little endian byte order. + /// + /// Returns the value read. + /// + /// The stream ends prematurely + /// + ushort ReadLEUshort() + { + int data1 = baseStream_.ReadByte(); + + if ( data1 < 0 ) { + throw new EndOfStreamException("End of stream"); + } + + int data2 = baseStream_.ReadByte(); + + if ( data2 < 0 ) { + throw new EndOfStreamException("End of stream"); + } + + + return unchecked((ushort)((ushort)data1 | (ushort)(data2 << 8))); + } + + /// + /// Read a uint in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + uint ReadLEUint() + { + return (uint)(ReadLEUshort() | (ReadLEUshort() << 16)); + } + + ulong ReadLEUlong() + { + return ReadLEUint() | ((ulong)ReadLEUint() << 32); + } + + #endregion + // NOTE this returns the offset of the first byte after the signature. + long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + { + using ( ZipHelperStream les = new ZipHelperStream(baseStream_) ) { + return les.LocateBlockWithSignature(signature, endLocation, minimumBlockSize, maximumVariableData); + } + } + + /// + /// Search for and read the central directory of a zip file filling the entries array. + /// + /// + /// An i/o error occurs. + /// + /// + /// The central directory is malformed or cannot be found + /// + void ReadEntries() + { + // Search for the End Of Central Directory. When a zip comment is + // present the directory will start earlier + // + // The search is limited to 64K which is the maximum size of a trailing comment field to aid speed. + // This should be compatible with both SFX and ZIP files but has only been tested for Zip files + // If a SFX file has the Zip data attached as a resource and there are other resources occuring later then + // this could be invalid. + // Could also speed this up by reading memory in larger blocks. + + if (baseStream_.CanSeek == false) { + throw new ZipException("ZipFile stream must be seekable"); + } + + long locatedEndOfCentralDir = LocateBlockWithSignature(ZipConstants.EndOfCentralDirectorySignature, + baseStream_.Length, ZipConstants.EndOfCentralRecordBaseSize, 0xffff); + + if (locatedEndOfCentralDir < 0) { + throw new ZipException("Cannot find central directory"); + } + + // Read end of central directory record + ushort thisDiskNumber = ReadLEUshort(); + ushort startCentralDirDisk = ReadLEUshort(); + ulong entriesForThisDisk = ReadLEUshort(); + ulong entriesForWholeCentralDir = ReadLEUshort(); + ulong centralDirSize = ReadLEUint(); + long offsetOfCentralDir = ReadLEUint(); + uint commentSize = ReadLEUshort(); + + if ( commentSize > 0 ) { + byte[] comment = new byte[commentSize]; + + StreamUtils.ReadFully(baseStream_, comment); + comment_ = ZipConstants.ConvertToString(comment); + } + else { + comment_ = string.Empty; + } + + bool isZip64 = false; + + // Check if zip64 header information is required. + if ( (thisDiskNumber == 0xffff) || + (startCentralDirDisk == 0xffff) || + (entriesForThisDisk == 0xffff) || + (entriesForWholeCentralDir == 0xffff) || + (centralDirSize == 0xffffffff) || + (offsetOfCentralDir == 0xffffffff) ) { + isZip64 = true; + + long offset = LocateBlockWithSignature(ZipConstants.Zip64CentralDirLocatorSignature, locatedEndOfCentralDir, 0, 0x1000); + if ( offset < 0 ) { + throw new ZipException("Cannot find Zip64 locator"); + } + + // number of the disk with the start of the zip64 end of central directory 4 bytes + // relative offset of the zip64 end of central directory record 8 bytes + // total number of disks 4 bytes + ReadLEUint(); // startDisk64 is not currently used + ulong offset64 = ReadLEUlong(); + uint totalDisks = ReadLEUint(); + + baseStream_.Position = (long)offset64; + long sig64 = ReadLEUint(); + + if ( sig64 != ZipConstants.Zip64CentralFileHeaderSignature ) { + throw new ZipException(string.Format("Invalid Zip64 Central directory signature at {0:X}", offset64)); + } + + // NOTE: Record size = SizeOfFixedFields + SizeOfVariableData - 12. + ulong recordSize = ReadLEUlong(); + int versionMadeBy = ReadLEUshort(); + int versionToExtract = ReadLEUshort(); + uint thisDisk = ReadLEUint(); + uint centralDirDisk = ReadLEUint(); + entriesForThisDisk = ReadLEUlong(); + entriesForWholeCentralDir = ReadLEUlong(); + centralDirSize = ReadLEUlong(); + offsetOfCentralDir = (long)ReadLEUlong(); + + // NOTE: zip64 extensible data sector (variable size) is ignored. + } + + entries_ = new ZipEntry[entriesForThisDisk]; + + // SFX/embedded support, find the offset of the first entry vis the start of the stream + // This applies to Zip files that are appended to the end of an SFX stub. + // Or are appended as a resource to an executable. + // Zip files created by some archivers have the offsets altered to reflect the true offsets + // and so dont require any adjustment here... + // TODO: Difficulty with Zip64 and SFX offset handling needs resolution - maths? + if ( !isZip64 && (offsetOfCentralDir < locatedEndOfCentralDir - (4 + (long)centralDirSize)) ) { + offsetOfFirstEntry = locatedEndOfCentralDir - (4 + (long)centralDirSize + offsetOfCentralDir); + if (offsetOfFirstEntry <= 0) { + throw new ZipException("Invalid embedded zip archive"); + } + } + + baseStream_.Seek(offsetOfFirstEntry + offsetOfCentralDir, SeekOrigin.Begin); + + for (ulong i = 0; i < entriesForThisDisk; i++) { + if (ReadLEUint() != ZipConstants.CentralHeaderSignature) { + throw new ZipException("Wrong Central Directory signature"); + } + + int versionMadeBy = ReadLEUshort(); + int versionToExtract = ReadLEUshort(); + int bitFlags = ReadLEUshort(); + int method = ReadLEUshort(); + uint dostime = ReadLEUint(); + uint crc = ReadLEUint(); + long csize = (long)ReadLEUint(); + long size = (long)ReadLEUint(); + int nameLen = ReadLEUshort(); + int extraLen = ReadLEUshort(); + int commentLen = ReadLEUshort(); + + int diskStartNo = ReadLEUshort(); // Not currently used + int internalAttributes = ReadLEUshort(); // Not currently used + + uint externalAttributes = ReadLEUint(); + long offset = ReadLEUint(); + + byte[] buffer = new byte[Math.Max(nameLen, commentLen)]; + + StreamUtils.ReadFully(baseStream_, buffer, 0, nameLen); + string name = ZipConstants.ConvertToStringExt(bitFlags, buffer, nameLen); + + ZipEntry entry = new ZipEntry(name, versionToExtract, versionMadeBy, (CompressionMethod)method); + entry.Crc = crc & 0xffffffffL; + entry.Size = size & 0xffffffffL; + entry.CompressedSize = csize & 0xffffffffL; + entry.Flags = bitFlags; + entry.DosTime = (uint)dostime; + entry.ZipFileIndex = (long)i; + entry.Offset = offset; + entry.ExternalFileAttributes = (int)externalAttributes; + + if ((bitFlags & 8) == 0) { + entry.CryptoCheckValue = (byte)(crc >> 24); + } + else { + entry.CryptoCheckValue = (byte)((dostime >> 8) & 0xff); + } + + if (extraLen > 0) { + byte[] extra = new byte[extraLen]; + StreamUtils.ReadFully(baseStream_, extra); + entry.ExtraData = extra; + } + + entry.ProcessExtraData(false); + + if (commentLen > 0) { + StreamUtils.ReadFully(baseStream_, buffer, 0, commentLen); + entry.Comment = ZipConstants.ConvertToStringExt(bitFlags, buffer, commentLen); + } + + entries_[i] = entry; + } + } + + /// + /// Locate the data for a given entry. + /// + /// + /// The start offset of the data. + /// + /// + /// The stream ends prematurely + /// + /// + /// The local header signature is invalid, the entry and central header file name lengths are different + /// or the local and entry compression methods dont match + /// + long LocateEntry(ZipEntry entry) + { + return TestLocalHeader(entry, HeaderTest.Extract); + } + +#if !NETCF_1_0 + Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) + { + CryptoStream result = null; + + if ( (entry.Version < ZipConstants.VersionStrongEncryption) + || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { + PkzipClassicManaged classicManaged = new PkzipClassicManaged(); + + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for encrypted stream"); + } + + result = new CryptoStream(baseStream, classicManaged.CreateDecryptor(key, null), CryptoStreamMode.Read); + CheckClassicPassword(result, entry); + } + else { +#if !NET_1_1 && !NETCF_2_0 + if (entry.Version == ZipConstants.VERSION_AES) { + // + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for AES encrypted stream"); + } + int saltLen = entry.AESSaltLen; + byte[] saltBytes = new byte[saltLen]; + int saltIn = baseStream.Read(saltBytes, 0, saltLen); + if (saltIn != saltLen) + throw new ZipException("AES Salt expected " + saltLen + " got " + saltIn); + // + byte[] pwdVerifyRead = new byte[2]; + baseStream.Read(pwdVerifyRead, 0, 2); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + ZipAESTransform decryptor = new ZipAESTransform(rawPassword_, saltBytes, blockSize, false); + byte[] pwdVerifyCalc = decryptor.PwdVerifier; + if (pwdVerifyCalc[0] != pwdVerifyRead[0] || pwdVerifyCalc[1] != pwdVerifyRead[1]) + throw new Exception("Invalid password for AES"); + result = new ZipAESStream(baseStream, decryptor, CryptoStreamMode.Read); + } + else +#endif + { + throw new ZipException("Decryption method not supported"); + } + } + + return result; + } + + Stream CreateAndInitEncryptionStream(Stream baseStream, ZipEntry entry) + { + CryptoStream result = null; + if ( (entry.Version < ZipConstants.VersionStrongEncryption) + || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { + PkzipClassicManaged classicManaged = new PkzipClassicManaged(); + + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for encrypted stream"); + } + + // Closing a CryptoStream will close the base stream as well so wrap it in an UncompressedStream + // which doesnt do this. + result = new CryptoStream(new UncompressedStream(baseStream), + classicManaged.CreateEncryptor(key, null), CryptoStreamMode.Write); + + if ( (entry.Crc < 0) || (entry.Flags & 8) != 0) { + WriteEncryptionHeader(result, entry.DosTime << 16); + } + else { + WriteEncryptionHeader(result, entry.Crc); + } + } + return result; + } + + static void CheckClassicPassword(CryptoStream classicCryptoStream, ZipEntry entry) + { + byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize]; + StreamUtils.ReadFully(classicCryptoStream, cryptbuffer); + if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue) { + throw new ZipException("Invalid password"); + } + } +#endif + + static void WriteEncryptionHeader(Stream stream, long crcValue) + { + byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize]; + Random rnd = new Random(); + rnd.NextBytes(cryptBuffer); + cryptBuffer[11] = (byte)(crcValue >> 24); + stream.Write(cryptBuffer, 0, cryptBuffer.Length); + } + + #endregion + + #region Instance Fields + bool isDisposed_; + string name_; + string comment_; + string rawPassword_; + Stream baseStream_; + bool isStreamOwner; + long offsetOfFirstEntry; + ZipEntry[] entries_; + byte[] key; + bool isNewArchive_; + + // Default is dynamic which is not backwards compatible and can cause problems + // with XP's built in compression which cant read Zip64 archives. + // However it does avoid the situation were a large file is added and cannot be completed correctly. + // Hint: Set always ZipEntry size before they are added to an archive and this setting isnt needed. + UseZip64 useZip64_ = UseZip64.Dynamic ; + + #region Zip Update Instance Fields + ArrayList updates_; + long updateCount_; // Count is managed manually as updates_ can contain nulls! + Hashtable updateIndex_; + IArchiveStorage archiveStorage_; + IDynamicDataSource updateDataSource_; + bool contentsEdited_; + int bufferSize_ = DefaultBufferSize; + byte[] copyBuffer_; + ZipString newComment_; + bool commentEdited_; + IEntryFactory updateEntryFactory_ = new ZipEntryFactory(); + #endregion + #endregion + + #region Support Classes + /// + /// Represents a string from a which is stored as an array of bytes. + /// + class ZipString + { + #region Constructors + /// + /// Initialise a with a string. + /// + /// The textual string form. + public ZipString(string comment) + { + comment_ = comment; + isSourceString_ = true; + } + + /// + /// Initialise a using a string in its binary 'raw' form. + /// + /// + public ZipString(byte[] rawString) + { + rawComment_ = rawString; + } + #endregion + + /// + /// Get a value indicating the original source of data for this instance. + /// True if the source was a string; false if the source was binary data. + /// + public bool IsSourceString + { + get { return isSourceString_; } + } + + /// + /// Get the length of the comment when represented as raw bytes. + /// + public int RawLength + { + get { + MakeBytesAvailable(); + return rawComment_.Length; + } + } + + /// + /// Get the comment in its 'raw' form as plain bytes. + /// + public byte[] RawComment + { + get { + MakeBytesAvailable(); + return (byte[])rawComment_.Clone(); + } + } + + /// + /// Reset the comment to its initial state. + /// + public void Reset() + { + if ( isSourceString_ ) { + rawComment_ = null; + } + else { + comment_ = null; + } + } + + void MakeTextAvailable() + { + if ( comment_ == null ) { + comment_ = ZipConstants.ConvertToString(rawComment_); + } + } + + void MakeBytesAvailable() + { + if ( rawComment_ == null ) { + rawComment_ = ZipConstants.ConvertToArray(comment_); + } + } + + /// + /// Implicit conversion of comment to a string. + /// + /// The to convert to a string. + /// The textual equivalent for the input value. + static public implicit operator string(ZipString zipString) + { + zipString.MakeTextAvailable(); + return zipString.comment_; + } + + #region Instance Fields + string comment_; + byte[] rawComment_; + bool isSourceString_; + #endregion + } + + /// + /// An enumerator for Zip entries + /// + class ZipEntryEnumerator : IEnumerator + { + #region Constructors + public ZipEntryEnumerator(ZipEntry[] entries) + { + array = entries; + } + + #endregion + #region IEnumerator Members + public object Current + { + get { + return array[index]; + } + } + + public void Reset() + { + index = -1; + } + + public bool MoveNext() + { + return (++index < array.Length); + } + #endregion + #region Instance Fields + ZipEntry[] array; + int index = -1; + #endregion + } + + /// + /// An is a stream that you can write uncompressed data + /// to and flush, but cannot read, seek or do anything else to. + /// + class UncompressedStream : Stream + { + #region Constructors + public UncompressedStream(Stream baseStream) + { + baseStream_ = baseStream; + } + + #endregion + + /// + /// Close this stream instance. + /// + public override void Close() + { + // Do nothing + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Write any buffered data to underlying storage. + /// + public override void Flush() + { + baseStream_.Flush(); + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + public override bool CanWrite + { + get { + return baseStream_.CanWrite; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek + { + get { + return false; + } + } + + /// + /// Get the length in bytes of the stream. + /// + public override long Length + { + get { + return 0; + } + } + + /// + /// Gets or sets the position within the current stream. + /// + public override long Position + { + get { + return baseStream_.Position; + } + + set + { + } + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + + /// + /// Sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// + /// The new position within the current stream. + /// + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. + public override long Seek(long offset, SeekOrigin origin) + { + return 0; + } + + /// + /// Sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. + public override void SetLength(long value) + { + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. + public override void Write(byte[] buffer, int offset, int count) + { + baseStream_.Write(buffer, offset, count); + } + + #region Instance Fields + Stream baseStream_; + #endregion + } + + /// + /// A is an + /// whose data is only a part or subsection of a file. + /// + class PartialInputStream : Stream + { + #region Constructors + /// + /// Initialise a new instance of the class. + /// + /// The containing the underlying stream to use for IO. + /// The start of the partial data. + /// The length of the partial data. + public PartialInputStream(ZipFile zipFile, long start, long length) + { + start_ = start; + length_ = length; + + // Although this is the only time the zipfile is used + // keeping a reference here prevents premature closure of + // this zip file and thus the baseStream_. + + // Code like this will cause apparently random failures depending + // on the size of the files and when garbage is collected. + // + // ZipFile z = new ZipFile (stream); + // Stream reader = z.GetInputStream(0); + // uses reader here.... + zipFile_ = zipFile; + baseStream_ = zipFile_.baseStream_; + readPos_ = start; + end_ = start + length; + } + #endregion + + /// + /// Read a byte from this stream. + /// + /// Returns the byte read or -1 on end of stream. + public override int ReadByte() + { + if (readPos_ >= end_) { + // -1 is the correct value at end of stream. + return -1; + } + + lock( baseStream_ ) { + baseStream_.Seek(readPos_++, SeekOrigin.Begin); + return baseStream_.ReadByte(); + } + } + + /// + /// Close this partial input stream. + /// + /// + /// The underlying stream is not closed. Close the parent ZipFile class to do that. + /// + public override void Close() + { + // Do nothing at all! + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. + public override int Read(byte[] buffer, int offset, int count) + { + lock(baseStream_) { + if (count > end_ - readPos_) { + count = (int) (end_ - readPos_); + if (count == 0) { + return 0; + } + } + + baseStream_.Seek(readPos_, SeekOrigin.Begin); + int readCount = baseStream_.Read(buffer, offset, count); + if (readCount > 0) { + readPos_ += readCount; + } + return readCount; + } + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + /// + /// When overridden in a derived class, sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + /// + /// When overridden in a derived class, sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// + /// The new position within the current stream. + /// + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. + public override long Seek(long offset, SeekOrigin origin) + { + long newPos = readPos_; + + switch ( origin ) + { + case SeekOrigin.Begin: + newPos = start_ + offset; + break; + + case SeekOrigin.Current: + newPos = readPos_ + offset; + break; + + case SeekOrigin.End: + newPos = end_ + offset; + break; + } + + if ( newPos < start_ ) { + throw new ArgumentException("Negative position is invalid"); + } + + if ( newPos >= end_ ) { + throw new IOException("Cannot seek past end"); + } + readPos_ = newPos; + return readPos_; + } + + /// + /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. + /// + /// An I/O error occurs. + public override void Flush() + { + // Nothing to do. + } + + /// + /// Gets or sets the position within the current stream. + /// + /// + /// The current position within the stream. + /// An I/O error occurs. + /// The stream does not support seeking. + /// Methods were called after the stream was closed. + public override long Position { + get { return readPos_ - start_; } + set { + long newPos = start_ + value; + + if ( newPos < start_ ) { + throw new ArgumentException("Negative position is invalid"); + } + + if ( newPos >= end_ ) { + throw new InvalidOperationException("Cannot seek past end"); + } + readPos_ = newPos; + } + } + + /// + /// Gets the length in bytes of the stream. + /// + /// + /// A long value representing the length of the stream in bytes. + /// A class derived from Stream does not support seeking. + /// Methods were called after the stream was closed. + public override long Length { + get { return length_; } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + /// false + /// true if the stream supports writing; otherwise, false. + public override bool CanWrite { + get { return false; } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + /// true + /// true if the stream supports seeking; otherwise, false. + public override bool CanSeek { + get { return true; } + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + /// true. + /// true if the stream supports reading; otherwise, false. + public override bool CanRead { + get { return true; } + } + +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + /// + /// Gets a value that determines whether the current stream can time out. + /// + /// + /// A value that determines whether the current stream can time out. + public override bool CanTimeout { + get { return baseStream_.CanTimeout; } + } +#endif + #region Instance Fields + ZipFile zipFile_; + Stream baseStream_; + long start_; + long length_; + long readPos_; + long end_; + #endregion + } + #endregion + } + + #endregion + + #region DataSources + /// + /// Provides a static way to obtain a source of data for an entry. + /// + public interface IStaticDataSource + { + /// + /// Get a source of data by creating a new stream. + /// + /// Returns a to use for compression input. + /// Ideally a new stream is created and opened to achieve this, to avoid locking problems. + Stream GetSource(); + } + + /// + /// Represents a source of data that can dynamically provide + /// multiple data sources based on the parameters passed. + /// + public interface IDynamicDataSource + { + /// + /// Get a data source. + /// + /// The to get a source for. + /// The name for data if known. + /// Returns a to use for compression input. + /// Ideally a new stream is created and opened to achieve this, to avoid locking problems. + Stream GetSource(ZipEntry entry, string name); + } + + /// + /// Default implementation of a for use with files stored on disk. + /// + public class StaticDiskDataSource : IStaticDataSource + { + /// + /// Initialise a new instnace of + /// + /// The name of the file to obtain data from. + public StaticDiskDataSource(string fileName) + { + fileName_ = fileName; + } + + #region IDataSource Members + + /// + /// Get a providing data. + /// + /// Returns a provising data. + public Stream GetSource() + { + return File.Open(fileName_, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + #endregion + #region Instance Fields + string fileName_; + #endregion + } + + + /// + /// Default implementation of for files stored on disk. + /// + public class DynamicDiskDataSource : IDynamicDataSource + { + /// + /// Initialise a default instance of . + /// + public DynamicDiskDataSource() + { + } + + #region IDataSource Members + /// + /// Get a providing data for an entry. + /// + /// The entry to provide data for. + /// The file name for data if known. + /// Returns a stream providing data; or null if not available + public Stream GetSource(ZipEntry entry, string name) + { + Stream result = null; + + if ( name != null ) { + result = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + return result; + } + + #endregion + } + + #endregion + + #region Archive Storage + /// + /// Defines facilities for data storage when updating Zip Archives. + /// + public interface IArchiveStorage + { + /// + /// Get the to apply during updates. + /// + FileUpdateMode UpdateMode { get; } + + /// + /// Get an empty that can be used for temporary output. + /// + /// Returns a temporary output + /// + Stream GetTemporaryOutput(); + + /// + /// Convert a temporary output stream to a final stream. + /// + /// The resulting final + /// + Stream ConvertTemporaryToFinal(); + + /// + /// Make a temporary copy of the original stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + Stream MakeTemporaryCopy(Stream stream); + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The current stream. + /// Returns a stream suitable for direct updating. + /// This may be the current stream passed. + Stream OpenForDirectUpdate(Stream stream); + + /// + /// Dispose of this instance. + /// + void Dispose(); + } + + /// + /// An abstract suitable for extension by inheritance. + /// + abstract public class BaseArchiveStorage : IArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The update mode. + protected BaseArchiveStorage(FileUpdateMode updateMode) + { + updateMode_ = updateMode; + } + #endregion + + #region IArchiveStorage Members + + /// + /// Gets a temporary output + /// + /// Returns the temporary output stream. + /// + public abstract Stream GetTemporaryOutput(); + + /// + /// Converts the temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + /// + public abstract Stream ConvertTemporaryToFinal(); + + /// + /// Make a temporary copy of a . + /// + /// The to make a copy of. + /// Returns a temporary output that is a copy of the input. + public abstract Stream MakeTemporaryCopy(Stream stream); + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The to open for direct update. + /// Returns a stream suitable for direct updating. + public abstract Stream OpenForDirectUpdate(Stream stream); + + /// + /// Disposes this instance. + /// + public abstract void Dispose(); + + /// + /// Gets the update mode applicable. + /// + /// The update mode. + public FileUpdateMode UpdateMode + { + get { + return updateMode_; + } + } + + #endregion + + #region Instance Fields + FileUpdateMode updateMode_; + #endregion + } + + /// + /// An implementation suitable for hard disks. + /// + public class DiskArchiveStorage : BaseArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The file. + /// The update mode. + public DiskArchiveStorage(ZipFile file, FileUpdateMode updateMode) + : base(updateMode) + { + if ( file.Name == null ) { + throw new ZipException("Cant handle non file archives"); + } + + fileName_ = file.Name; + } + + /// + /// Initializes a new instance of the class. + /// + /// The file. + public DiskArchiveStorage(ZipFile file) + : this(file, FileUpdateMode.Safe) + { + } + #endregion + + #region IArchiveStorage Members + + /// + /// Gets a temporary output for performing updates on. + /// + /// Returns the temporary output stream. + public override Stream GetTemporaryOutput() + { + if ( temporaryName_ != null ) { + temporaryName_ = GetTempFileName(temporaryName_, true); + temporaryStream_ = File.Open(temporaryName_, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + else { + // Determine where to place files based on internal strategy. + // Currently this is always done in system temp directory. + temporaryName_ = Path.GetTempFileName(); + temporaryStream_ = File.Open(temporaryName_, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + + return temporaryStream_; + } + + /// + /// Converts a temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + public override Stream ConvertTemporaryToFinal() + { + if ( temporaryStream_ == null ) { + throw new ZipException("No temporary stream has been created"); + } + + Stream result = null; + + string moveTempName = GetTempFileName(fileName_, false); + bool newFileCreated = false; + + try { + temporaryStream_.Close(); + File.Move(fileName_, moveTempName); + File.Move(temporaryName_, fileName_); + newFileCreated = true; + File.Delete(moveTempName); + + result = File.Open(fileName_, FileMode.Open, FileAccess.Read, FileShare.Read); + } + catch(Exception) { + result = null; + + // Try to roll back changes... + if ( !newFileCreated ) { + File.Move(moveTempName, fileName_); + File.Delete(temporaryName_); + } + + throw; + } + + return result; + } + + /// + /// Make a temporary copy of a stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + public override Stream MakeTemporaryCopy(Stream stream) + { + stream.Close(); + + temporaryName_ = GetTempFileName(fileName_, true); + File.Copy(fileName_, temporaryName_, true); + + temporaryStream_ = new FileStream(temporaryName_, + FileMode.Open, + FileAccess.ReadWrite); + return temporaryStream_; + } + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The current stream. + /// Returns a stream suitable for direct updating. + /// If the stream is not null this is used as is. + public override Stream OpenForDirectUpdate(Stream stream) + { + Stream result; + if ((stream == null) || !stream.CanWrite) + { + if (stream != null) { + stream.Close(); + } + + result = new FileStream(fileName_, + FileMode.Open, + FileAccess.ReadWrite); + } + else + { + result = stream; + } + + return result; + } + + /// + /// Disposes this instance. + /// + public override void Dispose() + { + if ( temporaryStream_ != null ) { + temporaryStream_.Close(); + } + } + + #endregion + + #region Internal routines + static string GetTempFileName(string original, bool makeTempFile) + { + string result = null; + + if ( original == null ) { + result = Path.GetTempFileName(); + } + else { + int counter = 0; + int suffixSeed = DateTime.Now.Second; + + while ( result == null ) { + counter += 1; + string newName = string.Format("{0}.{1}{2}.tmp", original, suffixSeed, counter); + if ( !File.Exists(newName) ) { + if ( makeTempFile) { + try { + // Try and create the file. + using ( FileStream stream = File.Create(newName) ) { + } + result = newName; + } + catch { + suffixSeed = DateTime.Now.Second; + } + } + else { + result = newName; + } + } + } + } + return result; + } + #endregion + + #region Instance Fields + Stream temporaryStream_; + string fileName_; + string temporaryName_; + #endregion + } + + /// + /// An implementation suitable for in memory streams. + /// + public class MemoryArchiveStorage : BaseArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + public MemoryArchiveStorage() + : base(FileUpdateMode.Direct) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The to use + /// This constructor is for testing as memory streams dont really require safe mode. + public MemoryArchiveStorage(FileUpdateMode updateMode) + : base(updateMode) + { + } + + #endregion + + #region Properties + /// + /// Get the stream returned by if this was in fact called. + /// + public MemoryStream FinalStream + { + get { return finalStream_; } + } + + #endregion + + #region IArchiveStorage Members + + /// + /// Gets the temporary output + /// + /// Returns the temporary output stream. + public override Stream GetTemporaryOutput() + { + temporaryStream_ = new MemoryStream(); + return temporaryStream_; + } + + /// + /// Converts the temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + public override Stream ConvertTemporaryToFinal() + { + if ( temporaryStream_ == null ) { + throw new ZipException("No temporary stream has been created"); + } + + finalStream_ = new MemoryStream(temporaryStream_.ToArray()); + return finalStream_; + } + + /// + /// Make a temporary copy of the original stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + public override Stream MakeTemporaryCopy(Stream stream) + { + temporaryStream_ = new MemoryStream(); + stream.Position = 0; + StreamUtils.Copy(stream, temporaryStream_, new byte[4096]); + return temporaryStream_; + } + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The original source stream + /// Returns a stream suitable for direct updating. + /// If the passed is not null this is used; + /// otherwise a new is returned. + public override Stream OpenForDirectUpdate(Stream stream) + { + Stream result; + if ((stream == null) || !stream.CanWrite) { + + result = new MemoryStream(); + + if (stream != null) { + stream.Position = 0; + StreamUtils.Copy(stream, result, new byte[4096]); + + stream.Close(); + } + } + else { + result = stream; + } + + return result; + } + + /// + /// Disposes this instance. + /// + public override void Dispose() + { + if ( temporaryStream_ != null ) { + temporaryStream_.Close(); + } + } + + #endregion + + #region Instance Fields + MemoryStream temporaryStream_; + MemoryStream finalStream_; + #endregion + } + + #endregion +} diff --git a/类库/Update/ZIP/Zip/ZipHelperStream.cs b/类库/Update/ZIP/Zip/ZipHelperStream.cs new file mode 100644 index 0000000..a2f905d --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipHelperStream.cs @@ -0,0 +1,623 @@ +// ZipHelperStream.cs +// +// Copyright 2006, 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Holds data pertinent to a data descriptor. + /// + public class DescriptorData + { + /// + /// Get /set the compressed size of data. + /// + public long CompressedSize + { + get { return compressedSize; } + set { compressedSize = value; } + } + + /// + /// Get / set the uncompressed size of data + /// + public long Size + { + get { return size; } + set { size = value; } + } + + /// + /// Get /set the crc value. + /// + public long Crc + { + get { return crc; } + set { crc = (value & 0xffffffff); } + } + + #region Instance Fields + long size; + long compressedSize; + long crc; + #endregion + } + + class EntryPatchData + { + public long SizePatchOffset + { + get { return sizePatchOffset_; } + set { sizePatchOffset_ = value; } + } + + public long CrcPatchOffset + { + get { return crcPatchOffset_; } + set { crcPatchOffset_ = value; } + } + + #region Instance Fields + long sizePatchOffset_; + long crcPatchOffset_; + #endregion + } + + /// + /// This class assists with writing/reading from Zip files. + /// + internal class ZipHelperStream : Stream + { + #region Constructors + /// + /// Initialise an instance of this class. + /// + /// The name of the file to open. + public ZipHelperStream(string name) + { + stream_ = new FileStream(name, FileMode.Open, FileAccess.ReadWrite); + isOwner_ = true; + } + + /// + /// Initialise a new instance of . + /// + /// The stream to use. + public ZipHelperStream(Stream stream) + { + stream_ = stream; + } + #endregion + + /// + /// Get / set a value indicating wether the the underlying stream is owned or not. + /// + /// If the stream is owned it is closed when this instance is closed. + public bool IsStreamOwner + { + get { return isOwner_; } + set { isOwner_ = value; } + } + + #region Base Stream Methods + public override bool CanRead + { + get { return stream_.CanRead; } + } + + public override bool CanSeek + { + get { return stream_.CanSeek; } + } + +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + public override bool CanTimeout + { + get { return stream_.CanTimeout; } + } +#endif + + public override long Length + { + get { return stream_.Length; } + } + + public override long Position + { + get { return stream_.Position; } + set { stream_.Position = value; } + } + + public override bool CanWrite + { + get { return stream_.CanWrite; } + } + + public override void Flush() + { + stream_.Flush(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + return stream_.Seek(offset, origin); + } + + public override void SetLength(long value) + { + stream_.SetLength(value); + } + + public override int Read(byte[] buffer, int offset, int count) + { + return stream_.Read(buffer, offset, count); + } + + public override void Write(byte[] buffer, int offset, int count) + { + stream_.Write(buffer, offset, count); + } + + /// + /// Close the stream. + /// + /// + /// The underlying stream is closed only if is true. + /// + override public void Close() + { + Stream toClose = stream_; + stream_ = null; + if (isOwner_ && (toClose != null)) + { + isOwner_ = false; + toClose.Close(); + } + } + #endregion + + // Write the local file header + // TODO: ZipHelperStream.WriteLocalHeader is not yet used and needs checking for ZipFile and ZipOuptutStream usage + void WriteLocalHeader(ZipEntry entry, EntryPatchData patchData) + { + CompressionMethod method = entry.CompressionMethod; + bool headerInfoAvailable = true; // How to get this? + bool patchEntryHeader = false; + + WriteLEInt(ZipConstants.LocalHeaderSignature); + + WriteLEShort(entry.Version); + WriteLEShort(entry.Flags); + WriteLEShort((byte)method); + WriteLEInt((int)entry.DosTime); + + if (headerInfoAvailable == true) { + WriteLEInt((int)entry.Crc); + if ( entry.LocalHeaderRequiresZip64 ) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + WriteLEInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize); + WriteLEInt((int)entry.Size); + } + } else { + if (patchData != null) { + patchData.CrcPatchOffset = stream_.Position; + } + WriteLEInt(0); // Crc + + if ( patchData != null ) { + patchData.SizePatchOffset = stream_.Position; + } + + // For local header both sizes appear in Zip64 Extended Information + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + WriteLEInt(0); // Compressed size + WriteLEInt(0); // Uncompressed size + } + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xFFFF) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if (entry.LocalHeaderRequiresZip64 && (headerInfoAvailable || patchEntryHeader)) { + ed.StartNewEntry(); + if (headerInfoAvailable) { + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + } + else { + ed.AddLeLong(-1); + ed.AddLeLong(-1); + } + ed.AddNewEntry(1); + + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cant find extra data"); + } + + if ( patchData != null ) { + patchData.SizePatchOffset = ed.CurrentReadIndex; + } + } + else { + ed.Delete(1); + } + + byte[] extra = ed.GetEntryData(); + + WriteLEShort(name.Length); + WriteLEShort(extra.Length); + + if ( name.Length > 0 ) { + stream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + patchData.SizePatchOffset += stream_.Position; + } + + if ( extra.Length > 0 ) { + stream_.Write(extra, 0, extra.Length); + } + } + + /// + /// Locates a block with the desired . + /// + /// The signature to find. + /// Location, marking the end of block. + /// Minimum size of the block. + /// The maximum variable data. + /// Eeturns the offset of the first byte after the signature; -1 if not found + public long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + { + long pos = endLocation - minimumBlockSize; + if ( pos < 0 ) { + return -1; + } + + long giveUpMarker = Math.Max(pos - maximumVariableData, 0); + + // TODO: This loop could be optimised for speed. + do { + if ( pos < giveUpMarker ) { + return -1; + } + Seek(pos--, SeekOrigin.Begin); + } while ( ReadLEInt() != signature ); + + return Position; + } + + /// + /// Write Zip64 end of central directory records (File header and locator). + /// + /// The number of entries in the central directory. + /// The size of entries in the central directory. + /// The offset of the dentral directory. + public void WriteZip64EndOfCentralDirectory(long noOfEntries, long sizeEntries, long centralDirOffset) + { + long centralSignatureOffset = stream_.Position; + WriteLEInt(ZipConstants.Zip64CentralFileHeaderSignature); + WriteLELong(44); // Size of this record (total size of remaining fields in header or full size - 12) + WriteLEShort(ZipConstants.VersionMadeBy); // Version made by + WriteLEShort(ZipConstants.VersionZip64); // Version to extract + WriteLEInt(0); // Number of this disk + WriteLEInt(0); // number of the disk with the start of the central directory + WriteLELong(noOfEntries); // No of entries on this disk + WriteLELong(noOfEntries); // Total No of entries in central directory + WriteLELong(sizeEntries); // Size of the central directory + WriteLELong(centralDirOffset); // offset of start of central directory + // zip64 extensible data sector not catered for here (variable size) + + // Write the Zip64 end of central directory locator + WriteLEInt(ZipConstants.Zip64CentralDirLocatorSignature); + + // no of the disk with the start of the zip64 end of central directory + WriteLEInt(0); + + // relative offset of the zip64 end of central directory record + WriteLELong(centralSignatureOffset); + + // total number of disks + WriteLEInt(1); + } + + /// + /// Write the required records to end the central directory. + /// + /// The number of entries in the directory. + /// The size of the entries in the directory. + /// The start of the central directory. + /// The archive comment. (This can be null). + public void WriteEndOfCentralDirectory(long noOfEntries, long sizeEntries, + long startOfCentralDirectory, byte[] comment) + { + + if ( (noOfEntries >= 0xffff) || + (startOfCentralDirectory >= 0xffffffff) || + (sizeEntries >= 0xffffffff) ) { + WriteZip64EndOfCentralDirectory(noOfEntries, sizeEntries, startOfCentralDirectory); + } + + WriteLEInt(ZipConstants.EndOfCentralDirectorySignature); + + // TODO: ZipFile Multi disk handling not done + WriteLEShort(0); // number of this disk + WriteLEShort(0); // no of disk with start of central dir + + + // Number of entries + if ( noOfEntries >= 0xffff ) { + WriteLEUshort(0xffff); // Zip64 marker + WriteLEUshort(0xffff); + } + else { + WriteLEShort(( short )noOfEntries); // entries in central dir for this disk + WriteLEShort(( short )noOfEntries); // total entries in central directory + } + + // Size of the central directory + if ( sizeEntries >= 0xffffffff ) { + WriteLEUint(0xffffffff); // Zip64 marker + } + else { + WriteLEInt(( int )sizeEntries); + } + + + // offset of start of central directory + if ( startOfCentralDirectory >= 0xffffffff ) { + WriteLEUint(0xffffffff); // Zip64 marker + } + else { + WriteLEInt(( int )startOfCentralDirectory); + } + + int commentLength = (comment != null) ? comment.Length : 0; + + if ( commentLength > 0xffff ) { + throw new ZipException(string.Format("Comment length({0}) is too long can only be 64K", commentLength)); + } + + WriteLEShort(commentLength); + + if ( commentLength > 0 ) { + Write(comment, 0, comment.Length); + } + } + + #region LE value reading/writing + /// + /// Read an unsigned short in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + public int ReadLEShort() + { + int byteValue1 = stream_.ReadByte(); + + if (byteValue1 < 0) { + throw new EndOfStreamException(); + } + + int byteValue2 = stream_.ReadByte(); + if (byteValue2 < 0) { + throw new EndOfStreamException(); + } + + return byteValue1 | (byteValue2 << 8); + } + + /// + /// Read an int in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + public int ReadLEInt() + { + return ReadLEShort() | (ReadLEShort() << 16); + } + + /// + /// Read a long in little endian byte order. + /// + /// The value read. + public long ReadLELong() + { + return (uint)ReadLEInt() | ((long)ReadLEInt() << 32); + } + + /// + /// Write an unsigned short in little endian byte order. + /// + /// The value to write. + public void WriteLEShort(int value) + { + stream_.WriteByte(( byte )(value & 0xff)); + stream_.WriteByte(( byte )((value >> 8) & 0xff)); + } + + /// + /// Write a ushort in little endian byte order. + /// + /// The value to write. + public void WriteLEUshort(ushort value) + { + stream_.WriteByte(( byte )(value & 0xff)); + stream_.WriteByte(( byte )(value >> 8)); + } + + /// + /// Write an int in little endian byte order. + /// + /// The value to write. + public void WriteLEInt(int value) + { + WriteLEShort(value); + WriteLEShort(value >> 16); + } + + /// + /// Write a uint in little endian byte order. + /// + /// The value to write. + public void WriteLEUint(uint value) + { + WriteLEUshort(( ushort )(value & 0xffff)); + WriteLEUshort(( ushort )(value >> 16)); + } + + /// + /// Write a long in little endian byte order. + /// + /// The value to write. + public void WriteLELong(long value) + { + WriteLEInt(( int )value); + WriteLEInt(( int )(value >> 32)); + } + + /// + /// Write a ulong in little endian byte order. + /// + /// The value to write. + public void WriteLEUlong(ulong value) + { + WriteLEUint(( uint )(value & 0xffffffff)); + WriteLEUint(( uint )(value >> 32)); + } + + #endregion + + /// + /// Write a data descriptor. + /// + /// The entry to write a descriptor for. + /// Returns the number of descriptor bytes written. + public int WriteDataDescriptor(ZipEntry entry) + { + if (entry == null) { + throw new ArgumentNullException("entry"); + } + + int result=0; + + // Add data descriptor if flagged as required + if ((entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) + { + // The signature is not PKZIP originally but is now described as optional + // in the PKZIP Appnote documenting trhe format. + WriteLEInt(ZipConstants.DataDescriptorSignature); + WriteLEInt(unchecked((int)(entry.Crc))); + + result+=8; + + if (entry.LocalHeaderRequiresZip64) + { + WriteLELong(entry.CompressedSize); + WriteLELong(entry.Size); + result+=16; + } + else + { + WriteLEInt((int)entry.CompressedSize); + WriteLEInt((int)entry.Size); + result+=8; + } + } + + return result; + } + + /// + /// Read data descriptor at the end of compressed data. + /// + /// if set to true [zip64]. + /// The data to fill in. + /// Returns the number of bytes read in the descriptor. + public void ReadDataDescriptor(bool zip64, DescriptorData data) + { + int intValue = ReadLEInt(); + + // In theory this may not be a descriptor according to PKZIP appnote. + // In practise its always there. + if (intValue != ZipConstants.DataDescriptorSignature) { + throw new ZipException("Data descriptor signature not found"); + } + + data.Crc = ReadLEInt(); + + if (zip64) { + data.CompressedSize = ReadLELong(); + data.Size = ReadLELong(); + } + else { + data.CompressedSize = ReadLEInt(); + data.Size = ReadLEInt(); + } + } + + #region Instance Fields + bool isOwner_; + Stream stream_; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/ZipInputStream.cs b/类库/Update/ZIP/Zip/ZipInputStream.cs new file mode 100644 index 0000000..b481ea1 --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipInputStream.cs @@ -0,0 +1,675 @@ +// ZipInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2010-05-25 Z-1663 Fixed exception when testing local header compressed size of -1 + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +#if !NETCF_1_0 +using ICSharpCode.SharpZipLib.Encryption; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// This is an InflaterInputStream that reads the files baseInputStream an zip archive + /// one after another. It has a special method to get the zip entry of + /// the next file. The zip entry contains information about the file name + /// size, compressed size, Crc, etc. + /// It includes support for Stored and Deflated entries. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// + /// This sample shows how to read a zip file + /// + /// using System; + /// using System.Text; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using ( ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]))) { + /// + /// ZipEntry theEntry; + /// const int size = 2048; + /// byte[] data = new byte[2048]; + /// + /// while ((theEntry = s.GetNextEntry()) != null) { + /// if ( entry.IsFile ) { + /// Console.Write("Show contents (y/n) ?"); + /// if (Console.ReadLine() == "y") { + /// while (true) { + /// size = s.Read(data, 0, data.Length); + /// if (size > 0) { + /// Console.Write(new ASCIIEncoding().GetString(data, 0, size)); + /// } else { + /// break; + /// } + /// } + /// } + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipInputStream : InflaterInputStream + { + #region Instance Fields + + /// + /// Delegate for reading bytes from a stream. + /// + delegate int ReadDataHandler(byte[] b, int offset, int length); + + /// + /// The current reader this instance. + /// + ReadDataHandler internalReader; + + Crc32 crc = new Crc32(); + ZipEntry entry; + + long size; + int method; + int flags; + string password; + #endregion + + #region Constructors + /// + /// Creates a new Zip input stream, for reading a zip archive. + /// + /// The underlying providing data. + public ZipInputStream(Stream baseInputStream) + : base(baseInputStream, new Inflater(true)) + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + } + + /// + /// Creates a new Zip input stream, for reading a zip archive. + /// + /// The underlying providing data. + /// Size of the buffer. + public ZipInputStream( Stream baseInputStream, int bufferSize ) + : base(baseInputStream, new Inflater(true), bufferSize) + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + } + #endregion + + /// + /// Optional password used for encryption when non-null + /// + /// A password for all encrypted entries in this + public string Password + { + get { + return password; + } + set { + password = value; + } + } + + + /// + /// Gets a value indicating if there is a current entry and it can be decompressed + /// + /// + /// The entry can only be decompressed if the library supports the zip features required to extract it. + /// See the ZipEntry Version property for more details. + /// + public bool CanDecompressEntry { + get { + return (entry != null) && entry.CanDecompress; + } + } + + /// + /// Advances to the next entry in the archive + /// + /// + /// The next entry in the archive or null if there are no more entries. + /// + /// + /// If the previous entry is still open CloseEntry is called. + /// + /// + /// Input stream is closed + /// + /// + /// Password is not set, password is invalid, compression method is invalid, + /// version required to extract is not supported + /// + public ZipEntry GetNextEntry() + { + if (crc == null) { + throw new InvalidOperationException("Closed."); + } + + if (entry != null) { + CloseEntry(); + } + + int header = inputBuffer.ReadLeInt(); + + if (header == ZipConstants.CentralHeaderSignature || + header == ZipConstants.EndOfCentralDirectorySignature || + header == ZipConstants.CentralHeaderDigitalSignature || + header == ZipConstants.ArchiveExtraDataSignature || + header == ZipConstants.Zip64CentralFileHeaderSignature) { + // No more individual entries exist + Close(); + return null; + } + + // -jr- 07-Dec-2003 Ignore spanning temporary signatures if found + // Spanning signature is same as descriptor signature and is untested as yet. + if ( (header == ZipConstants.SpanningTempSignature) || (header == ZipConstants.SpanningSignature) ) { + header = inputBuffer.ReadLeInt(); + } + + if (header != ZipConstants.LocalHeaderSignature) { + throw new ZipException("Wrong Local header signature: 0x" + String.Format("{0:X}", header)); + } + + short versionRequiredToExtract = (short)inputBuffer.ReadLeShort(); + + flags = inputBuffer.ReadLeShort(); + method = inputBuffer.ReadLeShort(); + uint dostime = (uint)inputBuffer.ReadLeInt(); + int crc2 = inputBuffer.ReadLeInt(); + csize = inputBuffer.ReadLeInt(); + size = inputBuffer.ReadLeInt(); + int nameLen = inputBuffer.ReadLeShort(); + int extraLen = inputBuffer.ReadLeShort(); + + bool isCrypted = (flags & 1) == 1; + + byte[] buffer = new byte[nameLen]; + inputBuffer.ReadRawBuffer(buffer); + + string name = ZipConstants.ConvertToStringExt(flags, buffer); + + entry = new ZipEntry(name, versionRequiredToExtract); + entry.Flags = flags; + + entry.CompressionMethod = (CompressionMethod)method; + + if ((flags & 8) == 0) { + entry.Crc = crc2 & 0xFFFFFFFFL; + entry.Size = size & 0xFFFFFFFFL; + entry.CompressedSize = csize & 0xFFFFFFFFL; + + entry.CryptoCheckValue = (byte)((crc2 >> 24) & 0xff); + + } else { + + // This allows for GNU, WinZip and possibly other archives, the PKZIP spec + // says these values are zero under these circumstances. + if (crc2 != 0) { + entry.Crc = crc2 & 0xFFFFFFFFL; + } + + if (size != 0) { + entry.Size = size & 0xFFFFFFFFL; + } + + if (csize != 0) { + entry.CompressedSize = csize & 0xFFFFFFFFL; + } + + entry.CryptoCheckValue = (byte)((dostime >> 8) & 0xff); + } + + entry.DosTime = dostime; + + // If local header requires Zip64 is true then the extended header should contain + // both values. + + // Handle extra data if present. This can set/alter some fields of the entry. + if (extraLen > 0) { + byte[] extra = new byte[extraLen]; + inputBuffer.ReadRawBuffer(extra); + entry.ExtraData = extra; + } + + entry.ProcessExtraData(true); + if ( entry.CompressedSize >= 0 ) { + csize = entry.CompressedSize; + } + + if ( entry.Size >= 0 ) { + size = entry.Size; + } + + if (method == (int)CompressionMethod.Stored && (!isCrypted && csize != size || (isCrypted && csize - ZipConstants.CryptoHeaderSize != size))) { + throw new ZipException("Stored, but compressed != uncompressed"); + } + + // Determine how to handle reading of data if this is attempted. + if (entry.IsCompressionMethodSupported()) { + internalReader = new ReadDataHandler(InitialRead); + } else { + internalReader = new ReadDataHandler(ReadingNotSupported); + } + + return entry; + } + + /// + /// Read data descriptor at the end of compressed data. + /// + void ReadDataDescriptor() + { + if (inputBuffer.ReadLeInt() != ZipConstants.DataDescriptorSignature) { + throw new ZipException("Data descriptor signature not found"); + } + + entry.Crc = inputBuffer.ReadLeInt() & 0xFFFFFFFFL; + + if ( entry.LocalHeaderRequiresZip64 ) { + csize = inputBuffer.ReadLeLong(); + size = inputBuffer.ReadLeLong(); + } else { + csize = inputBuffer.ReadLeInt(); + size = inputBuffer.ReadLeInt(); + } + entry.CompressedSize = csize; + entry.Size = size; + } + + /// + /// Complete cleanup as the final part of closing. + /// + /// True if the crc value should be tested + void CompleteCloseEntry(bool testCrc) + { + StopDecrypting(); + + if ((flags & 8) != 0) { + ReadDataDescriptor(); + } + + size = 0; + + if ( testCrc && + ((crc.Value & 0xFFFFFFFFL) != entry.Crc) && (entry.Crc != -1)) { + throw new ZipException("CRC mismatch"); + } + + crc.Reset(); + + if (method == (int)CompressionMethod.Deflated) { + inf.Reset(); + } + entry = null; + } + + /// + /// Closes the current zip entry and moves to the next one. + /// + /// + /// The stream is closed + /// + /// + /// The Zip stream ends early + /// + public void CloseEntry() + { + if (crc == null) { + throw new InvalidOperationException("Closed"); + } + + if (entry == null) { + return; + } + + if (method == (int)CompressionMethod.Deflated) { + if ((flags & 8) != 0) { + // We don't know how much we must skip, read until end. + byte[] tmp = new byte[4096]; + + // Read will close this entry + while (Read(tmp, 0, tmp.Length) > 0) { + } + return; + } + + csize -= inf.TotalIn; + inputBuffer.Available += inf.RemainingInput; + } + + if ( (inputBuffer.Available > csize) && (csize >= 0) ) { + inputBuffer.Available = (int)((long)inputBuffer.Available - csize); + } else { + csize -= inputBuffer.Available; + inputBuffer.Available = 0; + while (csize != 0) { + long skipped = base.Skip(csize); + + if (skipped <= 0) { + throw new ZipException("Zip archive ends early."); + } + + csize -= skipped; + } + } + + CompleteCloseEntry(false); + } + + /// + /// Returns 1 if there is an entry available + /// Otherwise returns 0. + /// + public override int Available { + get { + return entry != null ? 1 : 0; + } + } + + /// + /// Returns the current size that can be read from the current entry if available + /// + /// Thrown if the entry size is not known. + /// Thrown if no entry is currently available. + public override long Length + { + get { + if ( entry != null ) { + if ( entry.Size >= 0 ) { + return entry.Size; + } else { + throw new ZipException("Length not available for the current entry"); + } + } + else { + throw new InvalidOperationException("No current entry"); + } + } + + } + + /// + /// Reads a byte from the current zip entry. + /// + /// + /// The byte or -1 if end of stream is reached. + /// + public override int ReadByte() + { + byte[] b = new byte[1]; + if (Read(b, 0, 1) <= 0) { + return -1; + } + return b[0] & 0xff; + } + + /// + /// Handle attempts to read by throwing an . + /// + /// The destination array to store data in. + /// The offset at which data read should be stored. + /// The maximum number of bytes to read. + /// Returns the number of bytes actually read. + int ReadingNotAvailable(byte[] destination, int offset, int count) + { + throw new InvalidOperationException("Unable to read from this stream"); + } + + /// + /// Handle attempts to read from this entry by throwing an exception + /// + int ReadingNotSupported(byte[] destination, int offset, int count) + { + throw new ZipException("The compression method for this entry is not supported"); + } + + /// + /// Perform the initial read on an entry which may include + /// reading encryption headers and setting up inflation. + /// + /// The destination to fill with data read. + /// The offset to start reading at. + /// The maximum number of bytes to read. + /// The actual number of bytes read. + int InitialRead(byte[] destination, int offset, int count) + { + if ( !CanDecompressEntry ) { + throw new ZipException("Library cannot extract this entry. Version required is (" + entry.Version.ToString() + ")"); + } + + // Handle encryption if required. + if (entry.IsCrypted) { +#if NETCF_1_0 + throw new ZipException("Encryption not supported for Compact Framework 1.0"); +#else + if (password == null) { + throw new ZipException("No password set."); + } + + // Generate and set crypto transform... + PkzipClassicManaged managed = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password)); + + inputBuffer.CryptoTransform = managed.CreateDecryptor(key, null); + + byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize]; + inputBuffer.ReadClearTextBuffer(cryptbuffer, 0, ZipConstants.CryptoHeaderSize); + + if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue) { + throw new ZipException("Invalid password"); + } + + if (csize >= ZipConstants.CryptoHeaderSize) { + csize -= ZipConstants.CryptoHeaderSize; + } + else if ( (entry.Flags & (int)GeneralBitFlags.Descriptor) == 0 ) { + throw new ZipException(string.Format("Entry compressed size {0} too small for encryption", csize)); + } +#endif + } else { +#if !NETCF_1_0 + inputBuffer.CryptoTransform = null; +#endif + } + + if ((csize > 0) || ((flags & (int)GeneralBitFlags.Descriptor) != 0)) { + if ((method == (int)CompressionMethod.Deflated) && (inputBuffer.Available > 0)) { + inputBuffer.SetInflaterInput(inf); + } + + internalReader = new ReadDataHandler(BodyRead); + return BodyRead(destination, offset, count); + } + else { + internalReader = new ReadDataHandler(ReadingNotAvailable); + return 0; + } + } + + /// + /// Read a block of bytes from the stream. + /// + /// The destination for the bytes. + /// The index to start storing data. + /// The number of bytes to attempt to read. + /// Returns the number of bytes read. + /// Zero bytes read means end of stream. + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (buffer.Length - offset) < count ) { + throw new ArgumentException("Invalid offset/count combination"); + } + + return internalReader(buffer, offset, count); + } + + /// + /// Reads a block of bytes from the current zip entry. + /// + /// + /// The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. + /// + /// + /// An i/o error occured. + /// + /// + /// The deflated stream is corrupted. + /// + /// + /// The stream is not open. + /// + int BodyRead(byte[] buffer, int offset, int count) + { + if ( crc == null ) { + throw new InvalidOperationException("Closed"); + } + + if ( (entry == null) || (count <= 0) ) { + return 0; + } + + if ( offset + count > buffer.Length ) { + throw new ArgumentException("Offset + count exceeds buffer size"); + } + + bool finished = false; + + switch (method) { + case (int)CompressionMethod.Deflated: + count = base.Read(buffer, offset, count); + if (count <= 0) { + if (!inf.IsFinished) { + throw new ZipException("Inflater not finished!"); + } + inputBuffer.Available = inf.RemainingInput; + + // A csize of -1 is from an unpatched local header + if ((flags & 8) == 0 && + (inf.TotalIn != csize && csize != 0xFFFFFFFF && csize != -1 || inf.TotalOut != size)) { + throw new ZipException("Size mismatch: " + csize + ";" + size + " <-> " + inf.TotalIn + ";" + inf.TotalOut); + } + inf.Reset(); + finished = true; + } + break; + + case (int)CompressionMethod.Stored: + if ( (count > csize) && (csize >= 0) ) { + count = (int)csize; + } + + if ( count > 0 ) { + count = inputBuffer.ReadClearTextBuffer(buffer, offset, count); + if (count > 0) { + csize -= count; + size -= count; + } + } + + if (csize == 0) { + finished = true; + } else { + if (count < 0) { + throw new ZipException("EOF in stored block"); + } + } + break; + } + + if (count > 0) { + crc.Update(buffer, offset, count); + } + + if (finished) { + CompleteCloseEntry(true); + } + + return count; + } + + /// + /// Closes the zip input stream + /// + public override void Close() + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + crc = null; + entry = null; + + base.Close(); + } + } +} diff --git a/类库/Update/ZIP/Zip/ZipNameTransform.cs b/类库/Update/ZIP/Zip/ZipNameTransform.cs new file mode 100644 index 0000000..9dc1176 --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipNameTransform.cs @@ -0,0 +1,269 @@ +// ZipNameTransform.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +using System; +using System.IO; +using System.Text; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// ZipNameTransform transforms names as per the Zip file naming convention. + /// + /// The use of absolute names is supported although its use is not valid + /// according to Zip naming conventions, and should not be used if maximum compatability is desired. + public class ZipNameTransform : INameTransform + { + #region Constructors + /// + /// Initialize a new instance of + /// + public ZipNameTransform() + { + } + + /// + /// Initialize a new instance of + /// + /// The string to trim from the front of paths if found. + public ZipNameTransform(string trimPrefix) + { + TrimPrefix = trimPrefix; + } + #endregion + + /// + /// Static constructor. + /// + static ZipNameTransform() + { + char[] invalidPathChars; +#if NET_1_0 || NET_1_1 || NETCF_1_0 + invalidPathChars = Path.InvalidPathChars; +#else + invalidPathChars = Path.GetInvalidPathChars(); +#endif + int howMany = invalidPathChars.Length + 2; + + InvalidEntryCharsRelaxed = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryCharsRelaxed, 0, invalidPathChars.Length); + InvalidEntryCharsRelaxed[howMany - 1] = '*'; + InvalidEntryCharsRelaxed[howMany - 2] = '?'; + + howMany = invalidPathChars.Length + 4; + InvalidEntryChars = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length); + InvalidEntryChars[howMany - 1] = ':'; + InvalidEntryChars[howMany - 2] = '\\'; + InvalidEntryChars[howMany - 3] = '*'; + InvalidEntryChars[howMany - 4] = '?'; + } + + /// + /// Transform a windows directory name according to the Zip file naming conventions. + /// + /// The directory name to transform. + /// The transformed name. + public string TransformDirectory(string name) + { + name = TransformFile(name); + if (name.Length > 0) { + if ( !name.EndsWith("/") ) { + name += "/"; + } + } + else { + throw new ZipException("Cannot have an empty directory name"); + } + return name; + } + + /// + /// Transform a windows file name according to the Zip file naming conventions. + /// + /// The file name to transform. + /// The transformed name. + public string TransformFile(string name) + { + if (name != null) { + string lowerName = name.ToLower(); + if ( (trimPrefix_ != null) && (lowerName.IndexOf(trimPrefix_) == 0) ) { + name = name.Substring(trimPrefix_.Length); + } + + name = name.Replace(@"\", "/"); + name = WindowsPathUtils.DropPathRoot(name); + + // Drop any leading slashes. + while ((name.Length > 0) && (name[0] == '/')) + { + name = name.Remove(0, 1); + } + + // Drop any trailing slashes. + while ((name.Length > 0) && (name[name.Length - 1] == '/')) + { + name = name.Remove(name.Length - 1, 1); + } + + // Convert consecutive // characters to / + int index = name.IndexOf("//"); + while (index >= 0) + { + name = name.Remove(index, 1); + index = name.IndexOf("//"); + } + + name = MakeValidName(name, '_'); + } + else { + name = string.Empty; + } + return name; + } + + /// + /// Get/set the path prefix to be trimmed from paths if present. + /// + /// The prefix is trimmed before any conversion from + /// a windows path is done. + public string TrimPrefix + { + get { return trimPrefix_; } + set { + trimPrefix_ = value; + if (trimPrefix_ != null) { + trimPrefix_ = trimPrefix_.ToLower(); + } + } + } + + /// + /// Force a name to be valid by replacing invalid characters with a fixed value + /// + /// The name to force valid + /// The replacement character to use. + /// Returns a valid name + static string MakeValidName(string name, char replacement) + { + int index = name.IndexOfAny(InvalidEntryChars); + if (index >= 0) { + StringBuilder builder = new StringBuilder(name); + + while (index >= 0 ) { + builder[index] = replacement; + + if (index >= name.Length) { + index = -1; + } + else { + index = name.IndexOfAny(InvalidEntryChars, index + 1); + } + } + name = builder.ToString(); + } + + if (name.Length > 0xffff) { + throw new PathTooLongException(); + } + + return name; + } + + /// + /// Test a name to see if it is a valid name for a zip entry. + /// + /// The name to test. + /// If true checking is relaxed about windows file names and absolute paths. + /// Returns true if the name is a valid zip name; false otherwise. + /// Zip path names are actually in Unix format, and should only contain relative paths. + /// This means that any path stored should not contain a drive or + /// device letter, or a leading slash. All slashes should forward slashes '/'. + /// An empty name is valid for a file where the input comes from standard input. + /// A null name is not considered valid. + /// + public static bool IsValidName(string name, bool relaxed) + { + bool result = (name != null); + + if ( result ) { + if ( relaxed ) { + result = name.IndexOfAny(InvalidEntryCharsRelaxed) < 0; + } + else { + result = + (name.IndexOfAny(InvalidEntryChars) < 0) && + (name.IndexOf('/') != 0); + } + } + + return result; + } + + /// + /// Test a name to see if it is a valid name for a zip entry. + /// + /// The name to test. + /// Returns true if the name is a valid zip name; false otherwise. + /// Zip path names are actually in unix format, + /// and should only contain relative paths if a path is present. + /// This means that the path stored should not contain a drive or + /// device letter, or a leading slash. All slashes should forward slashes '/'. + /// An empty name is valid where the input comes from standard input. + /// A null name is not considered valid. + /// + public static bool IsValidName(string name) + { + bool result = + (name != null) && + (name.IndexOfAny(InvalidEntryChars) < 0) && + (name.IndexOf('/') != 0) + ; + return result; + } + + #region Instance Fields + string trimPrefix_; + #endregion + + #region Class Fields + static readonly char[] InvalidEntryChars; + static readonly char[] InvalidEntryCharsRelaxed; + #endregion + } +} diff --git a/类库/Update/ZIP/Zip/ZipOutputStream.cs b/类库/Update/ZIP/Zip/ZipOutputStream.cs new file mode 100644 index 0000000..eae4171 --- /dev/null +++ b/类库/Update/ZIP/Zip/ZipOutputStream.cs @@ -0,0 +1,900 @@ +// ZipOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 Z-1649 Added AES support +// 22-02-2010 Z-1648 Zero byte entries would create invalid zip files + +using System; +using System.IO; +using System.Collections; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// This is a DeflaterOutputStream that writes the files into a zip + /// archive one after another. It has a special method to start a new + /// zip entry. The zip entries contains information about the file name + /// size, compressed size, CRC, etc. + /// + /// It includes support for Stored and Deflated entries. + /// This class is not thread safe. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// This sample shows how to create a zip file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// string[] filenames = Directory.GetFiles(args[0]); + /// byte[] buffer = new byte[4096]; + /// + /// using ( ZipOutputStream s = new ZipOutputStream(File.Create(args[1])) ) { + /// + /// s.SetLevel(9); // 0 - store only to 9 - means best compression + /// + /// foreach (string file in filenames) { + /// ZipEntry entry = new ZipEntry(file); + /// s.PutNextEntry(entry); + /// + /// using (FileStream fs = File.OpenRead(file)) { + /// StreamUtils.Copy(fs, s, buffer); + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipOutputStream : DeflaterOutputStream + { + #region Constructors + /// + /// Creates a new Zip output stream, writing a zip archive. + /// + /// + /// The output stream to which the archive contents are written. + /// + public ZipOutputStream(Stream baseOutputStream) + : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true)) + { + } + + /// + /// Creates a new Zip output stream, writing a zip archive. + /// + /// The output stream to which the archive contents are written. + /// Size of the buffer to use. + public ZipOutputStream( Stream baseOutputStream, int bufferSize ) + : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), bufferSize) + { + } + #endregion + + /// + /// Gets a flag value of true if the central header has been added for this archive; false if it has not been added. + /// + /// No further entries can be added once this has been done. + public bool IsFinished + { + get { + return entries == null; + } + } + + /// + /// Set the zip file comment. + /// + /// + /// The comment text for the entire archive. + /// + /// + /// The converted comment is longer than 0xffff bytes. + /// + public void SetComment(string comment) + { + // TODO: Its not yet clear how to handle unicode comments here. + byte[] commentBytes = ZipConstants.ConvertToArray(comment); + if (commentBytes.Length > 0xffff) { + throw new ArgumentOutOfRangeException("comment"); + } + zipComment = commentBytes; + } + + /// + /// Sets the compression level. The new level will be activated + /// immediately. + /// + /// The new compression level (1 to 9). + /// + /// Level specified is not supported. + /// + /// + public void SetLevel(int level) + { + deflater_.SetLevel(level); + defaultCompressionLevel = level; + } + + /// + /// Get the current deflater compression level + /// + /// The current compression level + public int GetLevel() + { + return deflater_.GetLevel(); + } + + /// + /// Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + /// + /// Older archivers may not understand Zip64 extensions. + /// If backwards compatability is an issue be careful when adding entries to an archive. + /// Setting this property to off is workable but less desirable as in those circumstances adding a file + /// larger then 4GB will fail. + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + /// + /// Write an unsigned short in little endian byte order. + /// + private void WriteLeShort(int value) + { + unchecked { + baseOutputStream_.WriteByte((byte)(value & 0xff)); + baseOutputStream_.WriteByte((byte)((value >> 8) & 0xff)); + } + } + + /// + /// Write an int in little endian byte order. + /// + private void WriteLeInt(int value) + { + unchecked { + WriteLeShort(value); + WriteLeShort(value >> 16); + } + } + + /// + /// Write an int in little endian byte order. + /// + private void WriteLeLong(long value) + { + unchecked { + WriteLeInt((int)value); + WriteLeInt((int)(value >> 32)); + } + } + + /// + /// Starts a new Zip entry. It automatically closes the previous + /// entry if present. + /// All entry elements bar name are optional, but must be correct if present. + /// If the compression method is stored and the output is not patchable + /// the compression for that entry is automatically changed to deflate level 0 + /// + /// + /// the entry. + /// + /// + /// if entry passed is null. + /// + /// + /// if an I/O error occured. + /// + /// + /// if stream was finished + /// + /// + /// Too many entries in the Zip file
+ /// Entry name is too long
+ /// Finish has already been called
+ ///
+ public void PutNextEntry(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if (entries == null) { + throw new InvalidOperationException("ZipOutputStream was finished"); + } + + if (curEntry != null) { + CloseEntry(); + } + + if (entries.Count == int.MaxValue) { + throw new ZipException("Too many entries for Zip file"); + } + + CompressionMethod method = entry.CompressionMethod; + int compressionLevel = defaultCompressionLevel; + + // Clear flags that the library manages internally + entry.Flags &= (int)GeneralBitFlags.UnicodeText; + patchEntryHeader = false; + + bool headerInfoAvailable; + + // No need to compress - definitely no data. + if (entry.Size == 0) + { + entry.CompressedSize = entry.Size; + entry.Crc = 0; + method = CompressionMethod.Stored; + headerInfoAvailable = true; + } + else + { + headerInfoAvailable = (entry.Size >= 0) && entry.HasCrc; + + // Switch to deflation if storing isnt possible. + if (method == CompressionMethod.Stored) + { + if (!headerInfoAvailable) + { + if (!CanPatchEntries) + { + // Can't patch entries so storing is not possible. + method = CompressionMethod.Deflated; + compressionLevel = 0; + } + } + else // entry.size must be > 0 + { + entry.CompressedSize = entry.Size; + headerInfoAvailable = entry.HasCrc; + } + } + } + + if (headerInfoAvailable == false) { + if (CanPatchEntries == false) { + // Only way to record size and compressed size is to append a data descriptor + // after compressed data. + + // Stored entries of this form have already been converted to deflating. + entry.Flags |= 8; + } else { + patchEntryHeader = true; + } + } + + if (Password != null) { + entry.IsCrypted = true; + if (entry.Crc < 0) { + // Need to append a data descriptor as the crc isnt available for use + // with encryption, the date is used instead. Setting the flag + // indicates this to the decompressor. + entry.Flags |= 8; + } + } + + entry.Offset = offset; + entry.CompressionMethod = (CompressionMethod)method; + + curMethod = method; + sizePatchPos = -1; + + if ( (useZip64_ == UseZip64.On) || ((entry.Size < 0) && (useZip64_ == UseZip64.Dynamic)) ) { + entry.ForceZip64(); + } + + // Write the local file header + WriteLeInt(ZipConstants.LocalHeaderSignature); + + WriteLeShort(entry.Version); + WriteLeShort(entry.Flags); + WriteLeShort((byte)entry.CompressionMethodForHeader); + WriteLeInt((int)entry.DosTime); + + // TODO: Refactor header writing. Its done in several places. + if (headerInfoAvailable == true) { + WriteLeInt((int)entry.Crc); + if ( entry.LocalHeaderRequiresZip64 ) { + WriteLeInt(-1); + WriteLeInt(-1); + } + else { + WriteLeInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize); + WriteLeInt((int)entry.Size); + } + } else { + if (patchEntryHeader) { + crcPatchPos = baseOutputStream_.Position; + } + WriteLeInt(0); // Crc + + if ( patchEntryHeader ) { + sizePatchPos = baseOutputStream_.Position; + } + + // For local header both sizes appear in Zip64 Extended Information + if ( entry.LocalHeaderRequiresZip64 || patchEntryHeader ) { + WriteLeInt(-1); + WriteLeInt(-1); + } + else { + WriteLeInt(0); // Compressed size + WriteLeInt(0); // Uncompressed size + } + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xFFFF) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if (entry.LocalHeaderRequiresZip64) { + ed.StartNewEntry(); + if (headerInfoAvailable) { + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + } + else { + ed.AddLeLong(-1); + ed.AddLeLong(-1); + } + ed.AddNewEntry(1); + + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cant find extra data"); + } + + if ( patchEntryHeader ) { + sizePatchPos = ed.CurrentReadIndex; + } + } + else { + ed.Delete(1); + } + +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + AddExtraDataAES(entry, ed); + } +#endif + byte[] extra = ed.GetEntryData(); + + WriteLeShort(name.Length); + WriteLeShort(extra.Length); + + if ( name.Length > 0 ) { + baseOutputStream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + sizePatchPos += baseOutputStream_.Position; + } + + if ( extra.Length > 0 ) { + baseOutputStream_.Write(extra, 0, extra.Length); + } + + offset += ZipConstants.LocalHeaderBaseSize + name.Length + extra.Length; + // Fix offsetOfCentraldir for AES + if (entry.AESKeySize > 0) + offset += entry.AESOverheadSize; + + // Activate the entry. + curEntry = entry; + crc.Reset(); + if (method == CompressionMethod.Deflated) { + deflater_.Reset(); + deflater_.SetLevel(compressionLevel); + } + size = 0; + + if (entry.IsCrypted) { +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + WriteAESHeader(entry); + } else +#endif + { + if (entry.Crc < 0) { // so testing Zip will says its ok + WriteEncryptionHeader(entry.DosTime << 16); + } else { + WriteEncryptionHeader(entry.Crc); + } + } + } + } + + /// + /// Closes the current entry, updating header and footer information as required + /// + /// + /// An I/O error occurs. + /// + /// + /// No entry is active. + /// + public void CloseEntry() + { + if (curEntry == null) { + throw new InvalidOperationException("No open entry"); + } + + long csize = size; + + // First finish the deflater, if appropriate + if (curMethod == CompressionMethod.Deflated) { + if (size >= 0) { + base.Finish(); + csize = deflater_.TotalOut; + } + else { + deflater_.Reset(); + } + } + + // Write the AES Authentication Code (a hash of the compressed and encrypted data) + if (curEntry.AESKeySize > 0) { + baseOutputStream_.Write(AESAuthCode, 0, 10); + } + + if (curEntry.Size < 0) { + curEntry.Size = size; + } else if (curEntry.Size != size) { + throw new ZipException("size was " + size + ", but I expected " + curEntry.Size); + } + + if (curEntry.CompressedSize < 0) { + curEntry.CompressedSize = csize; + } else if (curEntry.CompressedSize != csize) { + throw new ZipException("compressed size was " + csize + ", but I expected " + curEntry.CompressedSize); + } + + if (curEntry.Crc < 0) { + curEntry.Crc = crc.Value; + } else if (curEntry.Crc != crc.Value) { + throw new ZipException("crc was " + crc.Value + ", but I expected " + curEntry.Crc); + } + + offset += csize; + + if (curEntry.IsCrypted) { + if (curEntry.AESKeySize > 0) { + curEntry.CompressedSize += curEntry.AESOverheadSize; + + } else { + curEntry.CompressedSize += ZipConstants.CryptoHeaderSize; + } + } + + // Patch the header if possible + if (patchEntryHeader) { + patchEntryHeader = false; + + long curPos = baseOutputStream_.Position; + baseOutputStream_.Seek(crcPatchPos, SeekOrigin.Begin); + WriteLeInt((int)curEntry.Crc); + + if ( curEntry.LocalHeaderRequiresZip64 ) { + + if ( sizePatchPos == -1 ) { + throw new ZipException("Entry requires zip64 but this has been turned off"); + } + + baseOutputStream_.Seek(sizePatchPos, SeekOrigin.Begin); + WriteLeLong(curEntry.Size); + WriteLeLong(curEntry.CompressedSize); + } + else { + WriteLeInt((int)curEntry.CompressedSize); + WriteLeInt((int)curEntry.Size); + } + baseOutputStream_.Seek(curPos, SeekOrigin.Begin); + } + + // Add data descriptor if flagged as required + if ((curEntry.Flags & 8) != 0) { + WriteLeInt(ZipConstants.DataDescriptorSignature); + WriteLeInt(unchecked((int)curEntry.Crc)); + + if ( curEntry.LocalHeaderRequiresZip64 ) { + WriteLeLong(curEntry.CompressedSize); + WriteLeLong(curEntry.Size); + offset += ZipConstants.Zip64DataDescriptorSize; + } + else { + WriteLeInt((int)curEntry.CompressedSize); + WriteLeInt((int)curEntry.Size); + offset += ZipConstants.DataDescriptorSize; + } + } + + entries.Add(curEntry); + curEntry = null; + } + + void WriteEncryptionHeader(long crcValue) + { + offset += ZipConstants.CryptoHeaderSize; + + InitializePassword(Password); + + byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize]; + Random rnd = new Random(); + rnd.NextBytes(cryptBuffer); + cryptBuffer[11] = (byte)(crcValue >> 24); + + EncryptBlock(cryptBuffer, 0, cryptBuffer.Length); + baseOutputStream_.Write(cryptBuffer, 0, cryptBuffer.Length); + } + +#if !NET_1_1 && !NETCF_2_0 + private static void AddExtraDataAES(ZipEntry entry, ZipExtraData extraData) { + + // Vendor Version: AE-1 IS 1. AE-2 is 2. With AE-2 no CRC is required and 0 is stored. + const int VENDOR_VERSION = 2; + // Vendor ID is the two ASCII characters "AE". + const int VENDOR_ID = 0x4541; //not 6965; + extraData.StartNewEntry(); + // Pack AES extra data field see http://www.winzip.com/aes_info.htm + //extraData.AddLeShort(7); // Data size (currently 7) + extraData.AddLeShort(VENDOR_VERSION); // 2 = AE-2 + extraData.AddLeShort(VENDOR_ID); // "AE" + extraData.AddData(entry.AESEncryptionStrength); // 1 = 128, 2 = 192, 3 = 256 + extraData.AddLeShort((int)entry.CompressionMethod); // The actual compression method used to compress the file + extraData.AddNewEntry(0x9901); + } + + // Replaces WriteEncryptionHeader for AES + // + private void WriteAESHeader(ZipEntry entry) { + byte[] salt; + byte[] pwdVerifier; + InitializeAESPassword(entry, Password, out salt, out pwdVerifier); + // File format for AES: + // Size (bytes) Content + // ------------ ------- + // Variable Salt value + // 2 Password verification value + // Variable Encrypted file data + // 10 Authentication code + // + // Value in the "compressed size" fields of the local file header and the central directory entry + // is the total size of all the items listed above. In other words, it is the total size of the + // salt value, password verification value, encrypted data, and authentication code. + baseOutputStream_.Write(salt, 0, salt.Length); + baseOutputStream_.Write(pwdVerifier, 0, pwdVerifier.Length); + } +#endif + + /// + /// Writes the given buffer to the current entry. + /// + /// The buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Archive size is invalid + /// No entry is active. + public override void Write(byte[] buffer, int offset, int count) + { + if (curEntry == null) { + throw new InvalidOperationException("No open entry."); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (buffer.Length - offset) < count ) { + throw new ArgumentException("Invalid offset/count combination"); + } + + crc.Update(buffer, offset, count); + size += count; + + switch (curMethod) { + case CompressionMethod.Deflated: + base.Write(buffer, offset, count); + break; + + case CompressionMethod.Stored: + if (Password != null) { + CopyAndEncrypt(buffer, offset, count); + } else { + baseOutputStream_.Write(buffer, offset, count); + } + break; + } + } + + void CopyAndEncrypt(byte[] buffer, int offset, int count) + { + const int CopyBufferSize = 4096; + byte[] localBuffer = new byte[CopyBufferSize]; + while ( count > 0 ) { + int bufferCount = (count < CopyBufferSize) ? count : CopyBufferSize; + + Array.Copy(buffer, offset, localBuffer, 0, bufferCount); + EncryptBlock(localBuffer, 0, bufferCount); + baseOutputStream_.Write(localBuffer, 0, bufferCount); + count -= bufferCount; + offset += bufferCount; + } + } + + /// + /// Finishes the stream. This will write the central directory at the + /// end of the zip file and flush the stream. + /// + /// + /// This is automatically called when the stream is closed. + /// + /// + /// An I/O error occurs. + /// + /// + /// Comment exceeds the maximum length
+ /// Entry name exceeds the maximum length + ///
+ public override void Finish() + { + if (entries == null) { + return; + } + + if (curEntry != null) { + CloseEntry(); + } + + long numEntries = entries.Count; + long sizeEntries = 0; + + foreach (ZipEntry entry in entries) { + WriteLeInt(ZipConstants.CentralHeaderSignature); + WriteLeShort(ZipConstants.VersionMadeBy); + WriteLeShort(entry.Version); + WriteLeShort(entry.Flags); + WriteLeShort((short)entry.CompressionMethodForHeader); + WriteLeInt((int)entry.DosTime); + WriteLeInt((int)entry.Crc); + + if ( entry.IsZip64Forced() || + (entry.CompressedSize >= uint.MaxValue) ) + { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.CompressedSize); + } + + if ( entry.IsZip64Forced() || + (entry.Size >= uint.MaxValue) ) + { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xffff) { + throw new ZipException("Name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.CentralHeaderRequiresZip64 ) { + ed.StartNewEntry(); + if ( entry.IsZip64Forced() || + (entry.Size >= 0xffffffff) ) + { + ed.AddLeLong(entry.Size); + } + + if ( entry.IsZip64Forced() || + (entry.CompressedSize >= 0xffffffff) ) + { + ed.AddLeLong(entry.CompressedSize); + } + + if ( entry.Offset >= 0xffffffff ) + { + ed.AddLeLong(entry.Offset); + } + + ed.AddNewEntry(1); + } + else { + ed.Delete(1); + } + +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + AddExtraDataAES(entry, ed); + } +#endif + byte[] extra = ed.GetEntryData(); + + byte[] entryComment = + (entry.Comment != null) ? + ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : + new byte[0]; + + if (entryComment.Length > 0xffff) { + throw new ZipException("Comment too long."); + } + + WriteLeShort(name.Length); + WriteLeShort(extra.Length); + WriteLeShort(entryComment.Length); + WriteLeShort(0); // disk number + WriteLeShort(0); // internal file attributes + // external file attributes + + if (entry.ExternalFileAttributes != -1) { + WriteLeInt(entry.ExternalFileAttributes); + } else { + if (entry.IsDirectory) { // mark entry as directory (from nikolam.AT.perfectinfo.com) + WriteLeInt(16); + } else { + WriteLeInt(0); + } + } + + if ( entry.Offset >= uint.MaxValue ) { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.Offset); + } + + if ( name.Length > 0 ) { + baseOutputStream_.Write(name, 0, name.Length); + } + + if ( extra.Length > 0 ) { + baseOutputStream_.Write(extra, 0, extra.Length); + } + + if ( entryComment.Length > 0 ) { + baseOutputStream_.Write(entryComment, 0, entryComment.Length); + } + + sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length; + } + + using ( ZipHelperStream zhs = new ZipHelperStream(baseOutputStream_) ) { + zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment); + } + + entries = null; + } + + #region Instance Fields + /// + /// The entries for the archive. + /// + ArrayList entries = new ArrayList(); + + /// + /// Used to track the crc of data added to entries. + /// + Crc32 crc = new Crc32(); + + /// + /// The current entry being added. + /// + ZipEntry curEntry; + + int defaultCompressionLevel = Deflater.DEFAULT_COMPRESSION; + + CompressionMethod curMethod = CompressionMethod.Deflated; + + /// + /// Used to track the size of data for an entry during writing. + /// + long size; + + /// + /// Offset to be recorded for each entry in the central header. + /// + long offset; + + /// + /// Comment for the entire archive recorded in central header. + /// + byte[] zipComment = new byte[0]; + + /// + /// Flag indicating that header patching is required for the current entry. + /// + bool patchEntryHeader; + + /// + /// Position to patch crc + /// + long crcPatchPos = -1; + + /// + /// Position to patch size. + /// + long sizePatchPos = -1; + + // Default is dynamic which is not backwards compatible and can cause problems + // with XP's built in compression which cant read Zip64 archives. + // However it does avoid the situation were a large file is added and cannot be completed correctly. + // NOTE: Setting the size for entries before they are added is the best solution! + UseZip64 useZip64_ = UseZip64.Dynamic; + #endregion + } +} diff --git a/类库/Update/ZipArchive.cs b/类库/Update/ZipArchive.cs new file mode 100644 index 0000000..812efa4 --- /dev/null +++ b/类库/Update/ZipArchive.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; + +using System.Reflection; +using System.Web; +using System.Windows.Forms; +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip; + + + +namespace OnlineUpdate +{ + internal class ZipArchive + { + /// + /// 功能:解压zip格式的文件。 + /// + /// 压缩文件路径 + /// 解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 + /// 出错信息 + /// 解压是否成功 + public static void UnZip(string zipFilePath, string unZipDir) + { + try + { + if (zipFilePath == string.Empty) + { + throw new Exception("压缩文件不能为空!"); + } + if (!File.Exists(zipFilePath)) + { + throw new System.IO.FileNotFoundException("压缩文件不存在!"); + } + //解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 + if (unZipDir == string.Empty) + unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), + Path.GetFileNameWithoutExtension(zipFilePath)); + if (!unZipDir.EndsWith("/")) + unZipDir += "/"; + if (!Directory.Exists(unZipDir)) + Directory.CreateDirectory(unZipDir); + + using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath))) + { + + ZipEntry theEntry; + while ((theEntry = s.GetNextEntry()) != null) + { + string directoryName = Path.GetDirectoryName(theEntry.Name); + string fileName = Path.GetFileName(theEntry.Name); + if (directoryName.Length > 0) + { + Directory.CreateDirectory(unZipDir + directoryName); + } + if (!directoryName.EndsWith("/")) + directoryName += "/"; + if (fileName != String.Empty) + { + if (theEntry.Name == "OnlineUpdate.exe") continue; + using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name)) + { + + int size = 5048; + byte[] data = new byte[size]; + while (true) + { + size = s.Read(data, 0, data.Length); + if (size > 0) + { + streamWriter.Write(data, 0, size); + } + else + { + break; + } + } + } + } + } + } + } + catch (Exception ex) + { } + } + } +} \ No newline at end of file diff --git a/类库/Update/gtk_refresh_reload_update_32px_2205_easyicon.net.ico b/类库/Update/gtk_refresh_reload_update_32px_2205_easyicon.net.ico new file mode 100644 index 0000000..b4b9fd0 Binary files /dev/null and b/类库/Update/gtk_refresh_reload_update_32px_2205_easyicon.net.ico differ diff --git a/类库/VersionUpdate/Client.cs b/类库/VersionUpdate/Client.cs new file mode 100644 index 0000000..010b235 --- /dev/null +++ b/类库/VersionUpdate/Client.cs @@ -0,0 +1,574 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; +using System.Web.Script.Serialization; +using System.Windows.Forms; +using System.Xml; + +namespace VersionUpdate +{ + public class UpdateClass + { + public string Name { get; set; } + public string Url { get; set; } + public string Version { get; set; } + public List Message { get; set; } + } + public class Client + { + public delegate void DownLoadSuccessDelegate(List updateList); + + /// + /// 更新用户信息事件 + /// + public static DownLoadSuccessDelegate DownLoadSuccessEvent; + + public static void OnDownLoadSuccessEvent(List updateList) + { + if (DownLoadSuccessEvent != null) + { + DownLoadSuccessEvent?.Invoke(updateList); + } + } + + + static string Path = System.IO.Directory.GetCurrentDirectory(); + static string XMLPath = string.Empty; + + static Client() + { + //VersionUpdate + //OnlineUpdate + //LevelUpdate + XMLPath = Path + "\\VersionUpdate.xml"; + if (!File.Exists(XMLPath)) + { + var old_path = Path + "\\OnlineUpdate.xml"; + if (!File.Exists(old_path)) throw new Exception("丢失【VersionUpdate.xml】更新包文件!"); + else + { + if (File.Exists(Path + "\\OnlineUpdate.exe")) + { + try + { + File.Delete(Path + "\\OnlineUpdate.exe"); + } + catch (Exception) + { + } + } + File.Move(old_path, XMLPath); + } + } + } + #region XmlDocument读取 + + //public List GetVersions() + //{ + // List msgs = new List(); + // XmlDocument XmlDoc = new XmlDocument(); + + // if (!File.Exists(XMLPath)) throw new Exception("找不到VersionUpdate.xml必备文件!"); + // //使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件. + + // XmlReaderSettings settings = new XmlReaderSettings(); + // settings.IgnoreComments = true;//忽略文档里面的注释 + // using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + // { + // XmlDoc.Load(reader); + // XmlNode xn = XmlDoc.SelectSingleNode("Files"); + // // 得到根节点的所有子节点 + // XmlNodeList xnl = xn.ChildNodes; + // foreach (XmlNode node in xnl) + // { + // try + // { + // //更新文件的别名 + // var Name = node.Attributes["Name"].Value; + // //之前的配置文件地址 + // var Url = node.Attributes["Url"].Value; + // var zipNameReg = Regex.Match(Url, @"([^/]+).xml"); + // //文件名称 + // var zipName = string.Empty; + // if (zipNameReg.Success) + // zipName = zipNameReg.Groups[1].Value; + // //版本号 + // var CurVersion = Version.Parse(node.Attributes["Version"].Value); + + // //XmlDocument temp_xml = new XmlDocument(); + // //temp_xml.Load(Url); + // //var temp_node = temp_xml.SelectSingleNode("History"); + + // //var temp_datas = temp_node.SelectNodes("Data"); + // ////更新内容 + // //List temp_update = new List(); + // //foreach (XmlNode item in temp_datas) + // //{ + // // var ver = Version.Parse(item.Attributes["Ver"].Value); + // // if (ver > CurVersion) + // // { + // // //发现有更新 + // // temp_update.Add(item); + // // } + // //} + + // var result = HttpPost(zipName, ""); + + // //解析web返回的json消息 + // //{"code":0,"data":{"Id":23,"key":23,"Active":true,"SoftName":"MainUpdate","Version":"2021.02.26.2","VersionLong":2021000200260002,"DownUrl":"http://fr-1303123972.cos.ap-chengdu.myqcloud.com/504e4621-0134-621d-b810-d30c0e41abca.zip","Message":"4444444555555666666666666","CreteTime":"\/Date(1614312406000)\/","CreateStr":"2021-02-26 12:06:46"}} + // if (!string.IsNullOrWhiteSpace(result)) + // { + // var ver = string.Empty; + // var downUrl = string.Empty; + // var updateMesss = new List(); + // JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer(); + // var dicResult = javaScriptSerializer.Deserialize>(result); + // if (dicResult != null) + // { + // if (dicResult["code"].ToString() != "0") throw new Exception("连接服务器失败,请稍后重试!"); + // var data = dicResult["data"] as Dictionary; + // if (data != null) + // { + // if ((bool)data["Active"]) + // { + // if (string.IsNullOrWhiteSpace(ver)) + // ver = data["Version"].ToString(); + // if (string.IsNullOrWhiteSpace(downUrl)) + // downUrl = data["DownUrl"].ToString(); + + // var temps = data["Message"].ToString().Split(new string[] { "[br]" }, StringSplitOptions.None); + // foreach (var temp in temps) updateMesss.Add(temp); + // } + + // var MSG = new UpdateClass() { Name = Name, Url = downUrl, Message = updateMesss, Version = ver }; + // msgs.Add(MSG); + + // } + // } + // } + + // //if (temp_update.Count > 0) + // //{ + // // var MSG = new UpdateClass() { Name = Name, Url = temp_update[0].Attributes["Url"].Value, Message = new List(), Version = temp_update[0].Attributes["Ver"].Value }; + // // msgs.Add(MSG); + // // foreach (var item in temp_update) + // // { + // // var temps = item.Attributes["Msg"].Value.Split(new string[] { "[br]" }, StringSplitOptions.None); + // // foreach (var temp in temps) MSG.Message.Add(temp); + // // } + // //} + + // } + // catch (Exception) + // { + // } + // #region xxx + // //try + // //{ + // // var Name = node.Attributes["Name"].Value; + // // var Url = node.Attributes["Url"].Value; + // // var CurVersion = Version.Parse(node.Attributes["Version"].Value); + + // // XmlDocument temp_xml = new XmlDocument(); + // // temp_xml.Load(Url); + // // var temp_node = temp_xml.SelectSingleNode("History"); + + // // var temp_datas = temp_node.SelectNodes("Data"); + // // //更新内容 + // // List temp_update = new List(); + // // foreach (XmlNode item in temp_datas) + // // { + // // var ver = Version.Parse(item.Attributes["Ver"].Value); + // // if (ver > CurVersion) + // // { + // // //发现有更新 + // // temp_update.Add(item); + // // } + // // } + // // if (temp_update.Count > 0) + // // { + // // var MSG = new UpdateClass() { Name = Name, Url = temp_update[0].Attributes["Url"].Value, Message = new List(), Version = temp_update[0].Attributes["Ver"].Value }; + // // msgs.Add(MSG); + // // foreach (var item in temp_update) + // // { + // // var temps = item.Attributes["Msg"].Value.Split(new string[] { "[br]" }, StringSplitOptions.None); + // // foreach (var temp in temps) MSG.Message.Add(temp); + // // } + // // } + + // //} + // //catch (Exception) + // //{ + // //} + // #endregion + // } + // } + // return msgs; + //} + + public List GetVersions() + { + List msgs = new List(); + XmlDocument XmlDoc = new XmlDocument(); + + if (!File.Exists(XMLPath)) throw new Exception("找不到VersionUpdate.xml必备文件!"); + //使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件. + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + XmlNode xn = XmlDoc.SelectSingleNode("Files"); + // 得到根节点的所有子节点 + XmlNodeList xnl = xn.ChildNodes; + foreach (XmlNode node in xnl) + { + try + { + var Name = node.Attributes["Name"].Value; + var Url = node.Attributes["Url"].Value; + var CurVersion = Version.Parse(node.Attributes["Version"].Value); + + XmlDocument temp_xml = new XmlDocument(); + temp_xml.Load(Url); + var temp_node = temp_xml.SelectSingleNode("History"); + + var temp_datas = temp_node.SelectNodes("Data"); + //更新内容 + List temp_update = new List(); + foreach (XmlNode item in temp_datas) + { + var ver = Version.Parse(item.Attributes["Ver"].Value); + if (ver > CurVersion) + { + //发现有更新 + temp_update.Add(item); + } + } + + if (temp_update.Count > 0) + { + var MSG = new UpdateClass() { Name = Name, Url = temp_update[0].Attributes["Url"].Value, Message = new List(), Version = temp_update[0].Attributes["Ver"].Value }; + msgs.Add(MSG); + foreach (var item in temp_update) + { + var temps = item.Attributes["Msg"].Value.Split(new string[] { "[br]" }, StringSplitOptions.None); + foreach (var temp in temps) MSG.Message.Add(temp); + } + } + } + catch (Exception) + { + + } + } + } + + return msgs; + } + + //private string HttpPost(string softname, string version) + //{ + // string content = $"SoftName={softname}"; + // string url = "http://106.52.154.242:82/soft/GetLast?{content}"; + // try + // { + // //获取提交的字节 + // byte[] bs = Encoding.UTF8.GetBytes(content); + // //设置提交的相关参数 + // HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url); + // req.Method = "POST"; + // req.ContentType = "application/x-www-form-urlencoded"; + // req.ContentLength = bs.Length; + // //提交请求数据 + // Stream reqStream = req.GetRequestStream(); + // reqStream.Write(bs, 0, bs.Length); + // reqStream.Close(); + // //接收返回的页面,必须的,不能省略 + // WebResponse wr = req.GetResponse(); + // System.IO.Stream respStream = wr.GetResponseStream(); + // System.IO.StreamReader reader = new System.IO.StreamReader(respStream, System.Text.Encoding.GetEncoding("utf-8")); + // string t = reader.ReadToEnd(); + // Console.WriteLine(t); + // wr.Close(); + // return t; + // } + // catch (Exception ex) + // { + // System.Web.HttpContext.Current.Response.Write("异常在getPostRespone:" + ex.Source + ":" + ex.Message); + // } + // return string.Empty; + //} + + + + + public delegate void NeedRestupdate(); + public static NeedRestupdate NeedRestupdateEvent; + + + + internal void DownFile(List update_msg, ProgressBar prog, Label label) + { + int i = 1; + foreach (var item in update_msg) + { + label?.Invoke(new Action(delegate { label.Text = $"正在下载第{i}个文件的更新包...(共{update_msg.Count}个)"; })); + DownloadFile(item.Url, MapFile($"{item.Name}_{item.Version}.zip", "Cache\\VersionUpdate"), prog); + i++; + } + label?.Invoke(new Action(delegate { label.Text = $"下载完成,请重启安装!"; })); + NeedRestupdateEvent?.BeginInvoke(null, null); + } + + /// + /// 检查是否有需要安装的程序 + /// + public bool CheckInstall() + { + var files = GetInstallFiles(); + if (files.Count > 0) + { + new InstallFileForm(files, this).ShowDialog(); + return true; + } + return false; + } + + public static bool StartProcess(string filename, string param = null) + { + try + { + if (!File.Exists(filename)) + return false; + + try + { + if (!System.IO.File.Exists(filename)) + return false; + + if (param != null) + System.Diagnostics.Process.Start(filename, param); + else + System.Diagnostics.Process.Start(filename); + System.Threading.Thread.Sleep(100); + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + + } + catch (Exception) + { + // MessageBox.Show("启动应用程序时出错!原因:" + ex.Message); + } + return false; + } + + + /// + /// 检查是否有新版本 + /// + public bool CheckVersion() + { + var ves = GetVersions(); + if (ves.Count > 0) + { + var f = new DownloadForm(ves, this); + f.ShowDialog(); + return f.IsOk; + } + return false; + } + + public bool DownloadFile(List updateList) + { + if (updateList.Count > 0) + { + var f = new DownloadForm(updateList, this); + f.ShowDialog(); + return f.IsOk; + } + return false; + } + + /// + /// 获得需要安装的文件 + /// + /// + public List GetInstallFiles() + { + var path = MapPath("Cache\\VersionUpdate"); + DirectoryInfo dir = new DirectoryInfo(path); + var zips = dir.GetFiles("*_*.zip", SearchOption.TopDirectoryOnly); + var files = new List(); + foreach (var item in zips) + { + var reg = Regex.Match(item.Name, "^(.*?)_(.*?)\\.zip$"); + if (reg.Success) + { + try + { + var name = item.Name; + var version = Version.Parse(reg.Groups[2].Value); + files.Add(item); + } + catch (Exception) + { } + } + } + + return files; + } + public void StartInstall() + { + var name = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName; + if (name == "VersionUpdate.exe") return; + StartProcess("VersionUpdate.exe", name); + } + + public void InstallFile(FileInfo file) + { + try + { + var data = file.Name.Split('_'); + var reg = Regex.Match(file.Name, "^(.*?)_(.*?).zip$"); + if (!reg.Success) return; + Version version = null; + if (!Version.TryParse(reg.Groups[2].Value, out version)) return; + var name = reg.Groups[1].Value; + + ZipArchive.UnZip(file.FullName, Path); + XmlDocument XmlDoc = new XmlDocument(); + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + foreach (XmlNode _temp in XmlDoc.SelectSingleNode("Files").ChildNodes) + { + if (name == _temp.Attributes["Name"].Value) + { + _temp.Attributes["Version"].Value = version.ToString(); + break; + } + } + } + XmlDoc.Save(XMLPath); + + File.Delete(file.FullName); + + } + catch (Exception ex) + { } + } + + public static string MapFile(string file, string path = "") + { + return System.IO.Path.Combine(MapPath(path, true), file); + } + public static string MapPath(string path = "", bool CreateDirectory = true) + { + try + { + if (string.IsNullOrWhiteSpace(path)) + { + return System.Windows.Forms.Application.StartupPath.ToString() + "\\"; + } + path = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath.ToString() + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + } + catch (Exception) + { } + return path; + } + + public void DownloadFile(string URL, string filename, ProgressBar prog) + { + try + { + + float percent = 0; + if (File.Exists(filename)) File.Delete(filename); + + Stream st = null; + Stream so = null; + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + prog.Invoke(new Action(delegate + { + prog.Value = 0; + prog.Maximum = (int)totalBytes; + })); + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + + totalDownloadedByte = osize + totalDownloadedByte; + Application.DoEvents(); + so.Write(by, 0, osize); + + prog.Invoke(new Action(delegate { prog.Value = (int)totalDownloadedByte; })); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + catch (Exception ex) + { + } + } + + #endregion XmlDocument读取 + } +} diff --git a/类库/VersionUpdate/DownloadForm.Designer.cs b/类库/VersionUpdate/DownloadForm.Designer.cs new file mode 100644 index 0000000..b619ec8 --- /dev/null +++ b/类库/VersionUpdate/DownloadForm.Designer.cs @@ -0,0 +1,108 @@ +namespace VersionUpdate +{ + partial class DownloadForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DownloadForm)); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.button1 = new System.Windows.Forms.Button(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // progressBar1 + // + this.progressBar1.Location = new System.Drawing.Point(8, 367); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(479, 25); + this.progressBar1.TabIndex = 6; + // + // button1 + // + this.button1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.button1.Location = new System.Drawing.Point(177, 399); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(136, 34); + this.button1.TabIndex = 5; + this.button1.Text = "开始下载"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // richTextBox1 + // + this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richTextBox1.Location = new System.Drawing.Point(2, 2); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ReadOnly = true; + this.richTextBox1.Size = new System.Drawing.Size(488, 332); + this.richTextBox1.TabIndex = 4; + this.richTextBox1.Text = ""; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(3, 338); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(482, 23); + this.label1.TabIndex = 7; + this.label1.Text = "等待下载"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // DownloadForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(495, 439); + this.Controls.Add(this.label1); + this.Controls.Add(this.progressBar1); + this.Controls.Add(this.button1); + this.Controls.Add(this.richTextBox1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "DownloadForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "下载新版本"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DownloadForm_FormClosing); + this.Load += new System.EventHandler(this.DownloadForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/VersionUpdate/DownloadForm.cs b/类库/VersionUpdate/DownloadForm.cs new file mode 100644 index 0000000..691e100 --- /dev/null +++ b/类库/VersionUpdate/DownloadForm.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace VersionUpdate +{ + public partial class DownloadForm : Form + { + List updateClass; + Client client; + public DownloadForm(List updateClass, Client client) + { + InitializeComponent(); + this.updateClass = updateClass; + this.client = client; + } + public bool IsOk = false; + Thread thread; + private void button1_Click(object sender, EventArgs e) + { + try + { + this.button1.Enabled = false; + thread = new Thread(new ThreadStart(delegate + { + try + { + client.DownFile(updateClass, this.progressBar1, this.label1); + IsOk = true; + Client.OnDownLoadSuccessEvent(updateClass); + this.Invoke(new Action(delegate + { + this.Close(); + })); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + MessageBox.Show(ex.Message, "下载失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + })); + } + })); + thread.IsBackground = true; + thread.Start(); + } + catch (Exception ex) + { } + } + + private void DownloadForm_Load(object sender, EventArgs e) + { + try + { + StringBuilder sb = new StringBuilder(); + foreach (var item in updateClass) + { + sb.Append($"{item.Name} -- {item.Version}\r\n"); + + for (int i = 0; i < item.Message.Count; i++) + { + sb.AppendLine($"{i + 1}、{item.Message[i]}"); + } + sb.AppendLine(""); + sb.AppendLine(""); + } + this.richTextBox1.Text = sb.ToString().Trim(); + } + catch (Exception ex) + { } + } + + private void DownloadForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (thread != null && !IsOk) + { + try + { + thread.Abort(); + } + catch (Exception ex1) + { } + } + } + catch (Exception ex) + { } + } + } +} diff --git a/类库/VersionUpdate/DownloadForm.resx b/类库/VersionUpdate/DownloadForm.resx new file mode 100644 index 0000000..1bbaeaa --- /dev/null +++ b/类库/VersionUpdate/DownloadForm.resx @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhSMALXdEABCALwAQfC4AAIkPAxGBMC4lhj9wLIlEoyqK + RM0rjEXwK4xF6iqLRdQriUS8K4lEnx+EO1sKgisbPXtQAB2BOAAWiDQAHYQ4AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAC6TSgAAgh0AAIQjAAAAAAAAAAAAAAAAACR6PAASfzAAAI8cAgp6KDcTejCRH4E50y2M + R/w8mFT/TaJk/1epbv9Tp2r/TKNl/0efX/87llP/KolE8h6AOb8TfDB2FIExJSw9NgAKgysACIIpAAAA + AAAAAAAAAAAAAAAAAAAAAAAALpRKHuxTxQAYfjMABoIoABGCMAAdjD0AGnw1AAyAKxUYezN4HH434DqT + Uv9frXT/h8SY/4/Jn/+Jxpr/hcOW/3/AkP94vYr/crmF/2u2f/9drnL/RZ5d/zONTPsmgj/TGX40VQCF + HwYUgTEAAJonAA2MLwAAAAAAAAAAAAAAAAAphELEHH02aRiFNhIfZzIADocvABp1MgAWfjMvFHcvriuH + RPplr3n/ksui/5vNqf+TyaL/jMac/4XClv99v5D/d7yK/3K5hf9stoD/ZrN6/1+wdf9brnH/Uqpq/z2Y + Vv8kgD3pGXozehqGNQ8jejsAMnNGAACFJAAAAAAAAAAAACqBQv8of0D3GXYytw91Kk4Jjy0IHn85Mx95 + N8dAk1b/hcKV/6HRrv+azqj/k8qi/36/kP9otH3/Waxv/02nZf9KpmP/UKlo/1Oqa/9WrG3/Wa1v/1Op + av9NpmX/R6Vh/zqaVP8rg0P4Inw6nhqCNxkbfjYAMlI7AAAAAAAAAAAALINE/n65jv9YoWz/H3g36x51 + N6gedTbKR5Zd/5fMpf+i0a//ms6o/4LClP9WrG3/PJ9X/y+ZTP8wmkz/MZtO/zKcT/8xm07/MJpN/zWc + Uf8/oFn/SKRh/0akYP9AoVr/O6BW/zSaUP8qgkL8HHY0kACAIgoOfSwACYQrAAAAAAAqf0H+oMys/8Lj + y/+GwJb/PY1T/0mWXf+azqj/o9Kw/5bLpP9qtn//Op5V/y+ZTP8ynE//NZ1R/zOYT/8xkUv/MI9J/zCR + Sv8ylk3/NJ1Q/zOcT/81nFH/PJ9X/zueVf81nFH/NJxQ/zOYTv8ieTr0E3EsagCcIgMLhCwAG3k1ACp+ + Qf2WxqT/vN/G/7Xbv/+g0Kz/m86p/6LSr/+Wy6T/W69y/zGaTf8ym07/NZ5R/zGTS/8pfkD8JHc77Bty + M8wSayu0F28vxiF1OOkpf0H9MZNM/zWdUf80nFD/NZxR/zSbUP80m1D/NZ1R/zCSS/8hdDjiGnUzSSM3 + KgAZfzQAK3xB/JPDof+027//qdS0/6XSsf+g0K3/lsqk/1isb/8wmUz/M5xP/zSbUP8tiEb/H3E25BZu + LYUTdi4zCnAnEwBuFQ0AbB0REnQtMxluMIkgbzbnLIlF/zSdUf80nFD/NJtQ/zSbUP81nlH/M5lP/yZ4 + PP8bbjGvFIExDRh4MgAsekH8kMKe/67Zuv+j0bD/nc6r/5vNqP9ms3v/MJlN/zObT/80m1D/K4BB/yNr + NvcbdjR3AJgkCBVxLgAQcysAAm0gAAttJgAXbzAAAJQqAw5rJ1QYaC3WK4VE/zWeUf81nlH/NZxR/y6K + R/8fcDX1FWksqRJwKz0MgioEEHgsACx4QfyMv5r/qNa1/53Pq/+bzqn/eLyK/zSbUP8ymk//NJtQ/zSc + Uf8ylk3/Kn5B/htpMN4TZiqBD3UrJQDBGwAAiiQAAHQKAA91LAAJfCgARh9CAAhpI0cZZy7jMI5K/zGT + TP8ldjv+HGYwyxJrKWEAdyENHGUxABF4LAAlfT0ALHZA+4i8lv+i06//ms6o/4fEl/9AoVr/MZlN/zSb + UP80m1D/NJtQ/zWdUf82oVP/L4tI/x5kMf8OYCSsA3UhIQR0IwAAdAoAAAAAAAZ2IwAKdCYAALMYAhRm + K3IfZzL2IGg06RZlK4sOciklLTwyAAVtIAAadTMACGwgEyV+PVcsdD/6hLqS/53Qq/+RyaD/Tqhn/y+Z + TP80m1D/NJtQ/zSbUP81nlH/NJtQ/yyERP8gajPxGWMtpwxrJjwBdSAGBHMjAAB0CgAAAAAAAAAAABVh + KQAQcyoADXwrDgxiI3ATaypFE5Q3BRNqKgAIbyIAAGAJBw9xKUYfeDe0Jnw97SxxP/qAt4//m8+p/2y3 + gP8wmk3/M5tP/zSbUP81nVH/NZ5R/y+MSf8gazX6FFwoxBBiJlcNfywOEGYnAAN1IQAEcyMAAHQKAAAA + AAAAAAAAAYkmABtjLgATbiwAGlYtABpgLgAKcCUAAFgAAQBnFykNbieSRItY6EqSXv8meT35K289+X21 + jf+LyJz/QqJc/zGZTf80nFH/NZ9S/zGSTP8kcTn/Glws2BRfKXQIbyQZITknAA96LAAWcy8AAYkmAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAGERAABaBgALcSUAD3ApAABpGxgNbydvKX0/1m+lfv+izK7/P5lY/yV1 + O/krbT74e7SL/2i2ff8xmk3/NZ5S/zOZTv8nej7/GV0s7BFYJZQRaikwAP+hAA5lJQAHgCgADG4mAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9zKgAHcSIAFngyAAFrGQkDah1NEnEsuEyRX/mYwqP/weDJ/3W+ + iP8rjkb/JXE6+i1uP/durYD/QKVc/zKcT/8shET/HmMx9g5VIrAJXyFFBJMqBxRjKgAQmjUAE34wAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtvJgAFaRwADXApAACCEgEPcSg0EXErmjKCSO96roj/tdi+/7ne + w/+bzqj/P6JZ/y2OR/8kbTj6MHBC9kudYf8vj0n/IWo1/RZZKM0TXihjCnwqEhBaJAAMbiYAALwrAAGL + JwAAAAAAAAAAAAAAAAAAAAAAAAAAAABXDAAUfTMADnMoACiBRQAEbCEbEHAqdyJ5Otpam2z/pMyu/7nd + w/+t17n/qNS0/2Kxd/8vm0z/MI9K/yNpNvsmaDf2Imk1/xRZJ94OWSGCDGslHioAAAAOeywAH5I/ACuW + SwAZiTcAMpZNAAmBKQAAAAAAAAAAAAAAAAAAYxEAAGEOABR2LgALciYNEXEpVxRyLsQ9iVL7iryX/7fb + wv+y2r3/pdOx/6HRrv+Fw5b/NZtR/zOdUP8wjkn/IWMz+x5kMeMOViKiBmIfNwCzIAMMZyQAHpA9AACB + GwMVjDU6GI04cQ+GLhUYiDYAap9+AAAAAAAAAAAAAAAAAABjEQAAXwoFD3IpOR55N6QtgUTwbKl9/6vT + tv+13MD/qdW1/6HQrv+azaj/ksqh/06oZ/8wmUz/NZ5R/y+NSP8gXzH8KIFAPgx/KgsKVyAADoswACaU + RQAXjTcdGY04fiSRQeEwlUv5HYk7ghOEMwUXgTQAEXYtAACGJAAAAAAAAGIRAABhDhoUciygI3g6/Wqm + ev+33MH/stu+/6LRr/+bzan/lMqj/5HIoP9rtn//MppO/zObT/81nlH/L4xI/x5bL/whbjYABmwgAByQ + OwAEhScJG487UiKRQL9CoFz8o9Cv/5bIo/8likHrFH0wWP///wARdCwAHHg1AAAAAAAALAAAJKZaAA9u + KB4TbCt3HW802E2OX/2FuJP/mMyn/5DIn/+JxZr/fr+Q/z+gWf8xmk7/NJtQ/zWeUf8vi0j/HVgt/QCB + IQAAbgACFIszMyWTQ5kok0bwcreE/+Hw5f/6/Pv/7/fx/3OzhP8ZfDTfGHkyYA5yKAYVbiwACGIfAABc + FgAMYSEAEWopAABRAAUSZSlqGGQt8jp8TP+Cu5L/hMOV/37Akf9Vq23/MJpN/zSbUP80m1D/NZ5R/y+L + SP8dVy39B4InAAB0DQgcjTuXMZZM/y+YTP+KxZr/9fr2/+n07P/k8ef/1Ora/3Cwgf8kfjztEW8rkwxq + JDoFYRsSAFsQDgtjIRIJXx8zCVsfgRtkL99LjFz/e7mM/4HCk/96vYz/Y7J5/zacUv8zm0//NJxQ/zSb + UP81nlH/L4tI/x1YLf4KgyoAR5lgAB+LPTwrjkbaL5RL/zKbT/+czqn/4O/j/9br2//Q6Nf/yOXQ/4m+ + l/9Cjlj+HXEz7ApgIcsHXB24Dl8kyyJrNes4e0r8YqFz/4PDlP98v47/dLqG/2aze/87n1f/MpxP/zSb + T/80m0//NZ5R/zWeUv8vi0j/HVgt/gqDKgABeSIAAFsAARmANWQnh0HzLpVK/zScUP+Gw5b/yeTQ/8bj + zf+73sT/ut7E/6fTs/+Eu5P/cayB/2Cgcf9mpHj/crGD/4C+kP+AwpL/dbuI/2+4gv9hsXf/QKFa/zKc + T/80m1D/JnM7/yJnNf8vi0j/NqFT/y+OSf8dWC3+AAAAAAZ6JwAOeSsAAG4aCh59OI4rhUT5L5RK/y+a + Tf9brnL/nM6q/7LZvP+q1bX/otGv/57Qq/+Yzab/jsme/4jGmf+BwpL/d7yJ/2+4g/9ptX7/Wa1w/zuf + Vv8znE//NJtQ/yVxOv8YUSjZGFAnrhZSJuskcTn/K4FD/x1ZLv4AAAAAAAAAAP///wAdfzkAGnkzFBt1 + NI8jejr3L5BJ/y6aTP86n1b/XrB0/4fEmP+TyqL/jsie/4nEmf+BwZL/eb2M/3K5hv9rtX7/Xq90/0ak + X/82nFL/M55Q/zKXTv8jbjf/FVAl2Q1NHkYAUw8KBEYTTwtHGbgVUyb4HFYs/wAAAAAAAAAAAF0OACSB + PwAWdC8AAGIWDA1oJn4ecDXvLIVE/zCWTP8wnE3/M5xQ/0ChW/9Uq2z/XrB0/16wdP9arnH/Tqdm/0Gh + Wv82nVH/M51P/zSeUf8th0b/G14t/gpGGcEFRxY/ED8wAAFPEQAOTTEAAEIGEglKGGoZVinHAAAAAAAA + AAAAAAAAAIckABNoKwAFZB4AAFsQCg9iJFkXYyvIIW42+y2HRv8ymE7/M5xP/zGcTv8wnE7/MJxN/zGc + Tv8ynU//M51P/zScUP8tiEX/Ims1/xlVKesNSh2MAEIKIQxKGwAJURkABkgOAABDAAABRA4AN3NvACBi + MSEAAAAAAAAAAAAAAAAAAAAAAAAAAABfFwAAXhYAN4JfAAJXFh0TWSZ4GVwrzxxfLvYkbzn/Kn9C/y2G + Rf8uiUb/LolH/yqAQv8mczv/HV4v/hFOId8GQxWiBUgTSQlWGQUGRBMAGDooAAAAAAAAAAAAAAAAAAA/ + AAAAOAAAH2ExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhcHAACWBEACloeAAAzAAEATxIsDlIgWx1Z + LaAcVSzaG1Mr7BxVK/UcViz2G1Qr3RxVLLUTTyR/AUcSPQA+AAgMShYADFAcAAAeAAAATA0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/AAAPxwAAB8AAAAHAAAAAwAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAA + AAAAACAAAAAwAAAAMAAAAPgAAAPwAAAPwAAAHwAAAA4AAAAOAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAA + AACAAAAAwAAAAMAAAADgAAAA+AAAOPwAAD8= + + + \ No newline at end of file diff --git a/类库/VersionUpdate/InstallFileForm.Designer.cs b/类库/VersionUpdate/InstallFileForm.Designer.cs new file mode 100644 index 0000000..0543344 --- /dev/null +++ b/类库/VersionUpdate/InstallFileForm.Designer.cs @@ -0,0 +1,70 @@ +namespace VersionUpdate +{ + partial class InstallFileForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InstallFileForm)); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label1 + // + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(2, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(406, 82); + this.label1.TabIndex = 0; + this.label1.Text = "准备安装"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // InstallFileForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(411, 103); + this.Controls.Add(this.label1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "InstallFileForm"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "正在安装"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.InstallFileForm_FormClosing); + this.Load += new System.EventHandler(this.InstallFileForm_Load); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/VersionUpdate/InstallFileForm.cs b/类库/VersionUpdate/InstallFileForm.cs new file mode 100644 index 0000000..aefbc27 --- /dev/null +++ b/类库/VersionUpdate/InstallFileForm.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Management; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace VersionUpdate +{ + public partial class InstallFileForm : Form + { + List infos; + Client client; + public InstallFileForm(List infos, Client client) + { + InitializeComponent(); + this.client = client; + this.infos = infos; + } + + public void Kill(string filePath) + { + try + { + if (string.IsNullOrWhiteSpace(filePath)) return; + var wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process"; + using (var searcher = new ManagementObjectSearcher(wmiQueryString)) + using (var results = searcher.Get()) + { + var query = from p in Process.GetProcesses() + join mo in results.Cast() + on p.Id equals (int)(uint)mo["ProcessId"] + select new + { + Process = p, + Path = (string)mo["ExecutablePath"], + CommandLine = (string)mo["CommandLine"], + }; + + foreach (var item in query) + { + if (filePath == item.Path) + { + item.Process.Kill(); + item.Process.WaitForExit(); + } + } + } + } + catch (Exception ex) + { } + } + + private bool IsClose = false; + private void InstallFileForm_Load(object sender, EventArgs e) + { + var method = new Action(delegate () + { + try + { + int i = 1; + Thread.Sleep(2000); + + Kill(Program.ExeName); + + foreach (var item in infos) + { + this.Invoke(new Action(delegate + { + this.label1.Text = $"正在安装第{i}个文件包...(共{infos.Count}个)"; + })); + this.client.InstallFile(item); + Application.DoEvents(); + } + this.Invoke(new Action(delegate + { + this.label1.Text = $"安装完成!"; + IsClose = true; + this.Close(); + })); + } + catch (Exception ex) + { + this.Invoke(new Action(delegate + { + this.label1.Text = $"安装失败:" + ex.Message; + })); + } + finally + { + IsClose = true; + } + }); + method.BeginInvoke(null, null); + } + + private void InstallFileForm_FormClosing(object sender, FormClosingEventArgs e) + { + try + { + if (!IsClose) + { + MessageBox.Show("安装还未结束,不能中途退出!", "友情提醒", MessageBoxButtons.OK, MessageBoxIcon.Error); + e.Cancel = true; + } + } + catch (Exception) + { } + } + } +} diff --git a/类库/VersionUpdate/InstallFileForm.resx b/类库/VersionUpdate/InstallFileForm.resx new file mode 100644 index 0000000..1bbaeaa --- /dev/null +++ b/类库/VersionUpdate/InstallFileForm.resx @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhSMALXdEABCALwAQfC4AAIkPAxGBMC4lhj9wLIlEoyqK + RM0rjEXwK4xF6iqLRdQriUS8K4lEnx+EO1sKgisbPXtQAB2BOAAWiDQAHYQ4AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAC6TSgAAgh0AAIQjAAAAAAAAAAAAAAAAACR6PAASfzAAAI8cAgp6KDcTejCRH4E50y2M + R/w8mFT/TaJk/1epbv9Tp2r/TKNl/0efX/87llP/KolE8h6AOb8TfDB2FIExJSw9NgAKgysACIIpAAAA + AAAAAAAAAAAAAAAAAAAAAAAALpRKHuxTxQAYfjMABoIoABGCMAAdjD0AGnw1AAyAKxUYezN4HH434DqT + Uv9frXT/h8SY/4/Jn/+Jxpr/hcOW/3/AkP94vYr/crmF/2u2f/9drnL/RZ5d/zONTPsmgj/TGX40VQCF + HwYUgTEAAJonAA2MLwAAAAAAAAAAAAAAAAAphELEHH02aRiFNhIfZzIADocvABp1MgAWfjMvFHcvriuH + RPplr3n/ksui/5vNqf+TyaL/jMac/4XClv99v5D/d7yK/3K5hf9stoD/ZrN6/1+wdf9brnH/Uqpq/z2Y + Vv8kgD3pGXozehqGNQ8jejsAMnNGAACFJAAAAAAAAAAAACqBQv8of0D3GXYytw91Kk4Jjy0IHn85Mx95 + N8dAk1b/hcKV/6HRrv+azqj/k8qi/36/kP9otH3/Waxv/02nZf9KpmP/UKlo/1Oqa/9WrG3/Wa1v/1Op + av9NpmX/R6Vh/zqaVP8rg0P4Inw6nhqCNxkbfjYAMlI7AAAAAAAAAAAALINE/n65jv9YoWz/H3g36x51 + N6gedTbKR5Zd/5fMpf+i0a//ms6o/4LClP9WrG3/PJ9X/y+ZTP8wmkz/MZtO/zKcT/8xm07/MJpN/zWc + Uf8/oFn/SKRh/0akYP9AoVr/O6BW/zSaUP8qgkL8HHY0kACAIgoOfSwACYQrAAAAAAAqf0H+oMys/8Lj + y/+GwJb/PY1T/0mWXf+azqj/o9Kw/5bLpP9qtn//Op5V/y+ZTP8ynE//NZ1R/zOYT/8xkUv/MI9J/zCR + Sv8ylk3/NJ1Q/zOcT/81nFH/PJ9X/zueVf81nFH/NJxQ/zOYTv8ieTr0E3EsagCcIgMLhCwAG3k1ACp+ + Qf2WxqT/vN/G/7Xbv/+g0Kz/m86p/6LSr/+Wy6T/W69y/zGaTf8ym07/NZ5R/zGTS/8pfkD8JHc77Bty + M8wSayu0F28vxiF1OOkpf0H9MZNM/zWdUf80nFD/NZxR/zSbUP80m1D/NZ1R/zCSS/8hdDjiGnUzSSM3 + KgAZfzQAK3xB/JPDof+027//qdS0/6XSsf+g0K3/lsqk/1isb/8wmUz/M5xP/zSbUP8tiEb/H3E25BZu + LYUTdi4zCnAnEwBuFQ0AbB0REnQtMxluMIkgbzbnLIlF/zSdUf80nFD/NJtQ/zSbUP81nlH/M5lP/yZ4 + PP8bbjGvFIExDRh4MgAsekH8kMKe/67Zuv+j0bD/nc6r/5vNqP9ms3v/MJlN/zObT/80m1D/K4BB/yNr + NvcbdjR3AJgkCBVxLgAQcysAAm0gAAttJgAXbzAAAJQqAw5rJ1QYaC3WK4VE/zWeUf81nlH/NZxR/y6K + R/8fcDX1FWksqRJwKz0MgioEEHgsACx4QfyMv5r/qNa1/53Pq/+bzqn/eLyK/zSbUP8ymk//NJtQ/zSc + Uf8ylk3/Kn5B/htpMN4TZiqBD3UrJQDBGwAAiiQAAHQKAA91LAAJfCgARh9CAAhpI0cZZy7jMI5K/zGT + TP8ldjv+HGYwyxJrKWEAdyENHGUxABF4LAAlfT0ALHZA+4i8lv+i06//ms6o/4fEl/9AoVr/MZlN/zSb + UP80m1D/NJtQ/zWdUf82oVP/L4tI/x5kMf8OYCSsA3UhIQR0IwAAdAoAAAAAAAZ2IwAKdCYAALMYAhRm + K3IfZzL2IGg06RZlK4sOciklLTwyAAVtIAAadTMACGwgEyV+PVcsdD/6hLqS/53Qq/+RyaD/Tqhn/y+Z + TP80m1D/NJtQ/zSbUP81nlH/NJtQ/yyERP8gajPxGWMtpwxrJjwBdSAGBHMjAAB0CgAAAAAAAAAAABVh + KQAQcyoADXwrDgxiI3ATaypFE5Q3BRNqKgAIbyIAAGAJBw9xKUYfeDe0Jnw97SxxP/qAt4//m8+p/2y3 + gP8wmk3/M5tP/zSbUP81nVH/NZ5R/y+MSf8gazX6FFwoxBBiJlcNfywOEGYnAAN1IQAEcyMAAHQKAAAA + AAAAAAAAAYkmABtjLgATbiwAGlYtABpgLgAKcCUAAFgAAQBnFykNbieSRItY6EqSXv8meT35K289+X21 + jf+LyJz/QqJc/zGZTf80nFH/NZ9S/zGSTP8kcTn/Glws2BRfKXQIbyQZITknAA96LAAWcy8AAYkmAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAGERAABaBgALcSUAD3ApAABpGxgNbydvKX0/1m+lfv+izK7/P5lY/yV1 + O/krbT74e7SL/2i2ff8xmk3/NZ5S/zOZTv8nej7/GV0s7BFYJZQRaikwAP+hAA5lJQAHgCgADG4mAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9zKgAHcSIAFngyAAFrGQkDah1NEnEsuEyRX/mYwqP/weDJ/3W+ + iP8rjkb/JXE6+i1uP/durYD/QKVc/zKcT/8shET/HmMx9g5VIrAJXyFFBJMqBxRjKgAQmjUAE34wAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtvJgAFaRwADXApAACCEgEPcSg0EXErmjKCSO96roj/tdi+/7ne + w/+bzqj/P6JZ/y2OR/8kbTj6MHBC9kudYf8vj0n/IWo1/RZZKM0TXihjCnwqEhBaJAAMbiYAALwrAAGL + JwAAAAAAAAAAAAAAAAAAAAAAAAAAAABXDAAUfTMADnMoACiBRQAEbCEbEHAqdyJ5Otpam2z/pMyu/7nd + w/+t17n/qNS0/2Kxd/8vm0z/MI9K/yNpNvsmaDf2Imk1/xRZJ94OWSGCDGslHioAAAAOeywAH5I/ACuW + SwAZiTcAMpZNAAmBKQAAAAAAAAAAAAAAAAAAYxEAAGEOABR2LgALciYNEXEpVxRyLsQ9iVL7iryX/7fb + wv+y2r3/pdOx/6HRrv+Fw5b/NZtR/zOdUP8wjkn/IWMz+x5kMeMOViKiBmIfNwCzIAMMZyQAHpA9AACB + GwMVjDU6GI04cQ+GLhUYiDYAap9+AAAAAAAAAAAAAAAAAABjEQAAXwoFD3IpOR55N6QtgUTwbKl9/6vT + tv+13MD/qdW1/6HQrv+azaj/ksqh/06oZ/8wmUz/NZ5R/y+NSP8gXzH8KIFAPgx/KgsKVyAADoswACaU + RQAXjTcdGY04fiSRQeEwlUv5HYk7ghOEMwUXgTQAEXYtAACGJAAAAAAAAGIRAABhDhoUciygI3g6/Wqm + ev+33MH/stu+/6LRr/+bzan/lMqj/5HIoP9rtn//MppO/zObT/81nlH/L4xI/x5bL/whbjYABmwgAByQ + OwAEhScJG487UiKRQL9CoFz8o9Cv/5bIo/8likHrFH0wWP///wARdCwAHHg1AAAAAAAALAAAJKZaAA9u + KB4TbCt3HW802E2OX/2FuJP/mMyn/5DIn/+JxZr/fr+Q/z+gWf8xmk7/NJtQ/zWeUf8vi0j/HVgt/QCB + IQAAbgACFIszMyWTQ5kok0bwcreE/+Hw5f/6/Pv/7/fx/3OzhP8ZfDTfGHkyYA5yKAYVbiwACGIfAABc + FgAMYSEAEWopAABRAAUSZSlqGGQt8jp8TP+Cu5L/hMOV/37Akf9Vq23/MJpN/zSbUP80m1D/NZ5R/y+L + SP8dVy39B4InAAB0DQgcjTuXMZZM/y+YTP+KxZr/9fr2/+n07P/k8ef/1Ora/3Cwgf8kfjztEW8rkwxq + JDoFYRsSAFsQDgtjIRIJXx8zCVsfgRtkL99LjFz/e7mM/4HCk/96vYz/Y7J5/zacUv8zm0//NJxQ/zSb + UP81nlH/L4tI/x1YLf4KgyoAR5lgAB+LPTwrjkbaL5RL/zKbT/+czqn/4O/j/9br2//Q6Nf/yOXQ/4m+ + l/9Cjlj+HXEz7ApgIcsHXB24Dl8kyyJrNes4e0r8YqFz/4PDlP98v47/dLqG/2aze/87n1f/MpxP/zSb + T/80m0//NZ5R/zWeUv8vi0j/HVgt/gqDKgABeSIAAFsAARmANWQnh0HzLpVK/zScUP+Gw5b/yeTQ/8bj + zf+73sT/ut7E/6fTs/+Eu5P/cayB/2Cgcf9mpHj/crGD/4C+kP+AwpL/dbuI/2+4gv9hsXf/QKFa/zKc + T/80m1D/JnM7/yJnNf8vi0j/NqFT/y+OSf8dWC3+AAAAAAZ6JwAOeSsAAG4aCh59OI4rhUT5L5RK/y+a + Tf9brnL/nM6q/7LZvP+q1bX/otGv/57Qq/+Yzab/jsme/4jGmf+BwpL/d7yJ/2+4g/9ptX7/Wa1w/zuf + Vv8znE//NJtQ/yVxOv8YUSjZGFAnrhZSJuskcTn/K4FD/x1ZLv4AAAAAAAAAAP///wAdfzkAGnkzFBt1 + NI8jejr3L5BJ/y6aTP86n1b/XrB0/4fEmP+TyqL/jsie/4nEmf+BwZL/eb2M/3K5hv9rtX7/Xq90/0ak + X/82nFL/M55Q/zKXTv8jbjf/FVAl2Q1NHkYAUw8KBEYTTwtHGbgVUyb4HFYs/wAAAAAAAAAAAF0OACSB + PwAWdC8AAGIWDA1oJn4ecDXvLIVE/zCWTP8wnE3/M5xQ/0ChW/9Uq2z/XrB0/16wdP9arnH/Tqdm/0Gh + Wv82nVH/M51P/zSeUf8th0b/G14t/gpGGcEFRxY/ED8wAAFPEQAOTTEAAEIGEglKGGoZVinHAAAAAAAA + AAAAAAAAAIckABNoKwAFZB4AAFsQCg9iJFkXYyvIIW42+y2HRv8ymE7/M5xP/zGcTv8wnE7/MJxN/zGc + Tv8ynU//M51P/zScUP8tiEX/Ims1/xlVKesNSh2MAEIKIQxKGwAJURkABkgOAABDAAABRA4AN3NvACBi + MSEAAAAAAAAAAAAAAAAAAAAAAAAAAABfFwAAXhYAN4JfAAJXFh0TWSZ4GVwrzxxfLvYkbzn/Kn9C/y2G + Rf8uiUb/LolH/yqAQv8mczv/HV4v/hFOId8GQxWiBUgTSQlWGQUGRBMAGDooAAAAAAAAAAAAAAAAAAA/ + AAAAOAAAH2ExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhcHAACWBEACloeAAAzAAEATxIsDlIgWx1Z + LaAcVSzaG1Mr7BxVK/UcViz2G1Qr3RxVLLUTTyR/AUcSPQA+AAgMShYADFAcAAAeAAAATA0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/AAAPxwAAB8AAAAHAAAAAwAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAA + AAAAACAAAAAwAAAAMAAAAPgAAAPwAAAPwAAAHwAAAA4AAAAOAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAA + AACAAAAAwAAAAMAAAADgAAAA+AAAOPwAAD8= + + + \ No newline at end of file diff --git a/类库/VersionUpdate/Program.cs b/类库/VersionUpdate/Program.cs new file mode 100644 index 0000000..e644462 --- /dev/null +++ b/类库/VersionUpdate/Program.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +namespace VersionUpdate +{ + static class Program + { + + internal static string ExeName { get; private set; } + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main(string[] param) + { + try + { + #region 系统捕获异常 + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.Automatic); + Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); + AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); + SetAllowUnsafeHeaderParsing20(true); + #endregion + + Client client = new Client(); + if (param.Length > 0) + { + ExeName = Client.MapFile(param[0]); + } + if (client.CheckInstall()) + { + if (param.Length > 0) + { + Client.StartProcess(param[0]); + return; + } + } + else + { + if (client.CheckVersion()) + { + if (client.CheckInstall()) + { + if (param.Length > 0) + { + Client.StartProcess(param[0]); + return; + } + } + } + else if (client.GetVersions().Count == 0 && param.Length == 0) + MessageBox.Show("没有发现新版本!", "友情提示", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + } + catch (Exception ex) + { } + } + + + + #region 系统异常捕获 + static bool SetAllowUnsafeHeaderParsing20(bool useUnsafe) + { + try + { + //Get the assembly that contains the internal class + System.Reflection.Assembly aNetAssembly = System.Reflection.Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection)); + if (aNetAssembly != null) + { + //Use the assembly in order to get the internal type for the internal class + Type aSettingsType = aNetAssembly.GetType("System.Net.Configuration.SettingsSectionInternal"); + if (aSettingsType != null) + { + //Use the internal static property to get an instance of the internal settings class. + //If the static instance isn't created allready the property will create it for us. + object anInstance = aSettingsType.InvokeMember("Section", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.NonPublic, null, null, new object[] { }); + + if (anInstance != null) + { + //Locate the private bool field that tells the framework is unsafe header parsing should be allowed or not + System.Reflection.FieldInfo aUseUnsafeHeaderParsing = aSettingsType.GetField("useUnsafeHeaderParsing", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + if (aUseUnsafeHeaderParsing != null) + { + aUseUnsafeHeaderParsing.SetValue(anInstance, useUnsafe); + return true; + } + } + } + } + return false; + } + catch (Exception ex) + { + //MessageBox.Show(ex.Message + " - " + ex.StackTrace); + } + return false; + } + static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) + { + try + { + string str = GetExceptionMsg(e.Exception, e.ToString()); + //MessageBox.Show(str, "子线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + throw new Exception(str); + } + catch (Exception ex) + { + //MessageBox.Show(ex.Message, "子线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + try + { + string str = GetExceptionMsg(e.ExceptionObject as Exception, e.ToString()); + // MessageBox.Show(str, "主线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + throw new Exception(str); + } + catch (Exception ex) + { + //MessageBox.Show(ex.Message, "主线程错误", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + static string GetExceptionMsg(Exception ex, string backStr) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("****************************异常文本****************************"); + sb.AppendLine("【出现时间】:" + DateTime.Now.ToString()); + if (ex != null) + { + sb.AppendLine("【异常类型】:" + ex.GetType().Name); + sb.AppendLine("【异常信息】:" + ex.Message); + sb.AppendLine("【堆栈调用】:" + ex.StackTrace); + } + else + { + sb.AppendLine("【未处理异常】:" + backStr); + } + sb.AppendLine("***************************************************************"); + return sb.ToString(); + } + + /// + /// 退出 + /// + public static void Exit(bool start = false) + { + try + { + if (start) + { + //程序位置 + string strAppFileName = Process.GetCurrentProcess().MainModule.FileName; + Process myNewProcess = new Process(); + //要启动的应用程序 + myNewProcess.StartInfo.FileName = strAppFileName; + // 设置要启动的进程的初始目录 + myNewProcess.StartInfo.WorkingDirectory = Application.ExecutablePath; + //启动程序 + myNewProcess.Start(); + } + //结束该程序 + // Application.Exit(); + //结束该所有线程 + //Environment.Exit(0); + Process.GetCurrentProcess().Kill(); + } + catch (Exception) + { } + } + + #endregion + } +} diff --git a/类库/VersionUpdate/Properties/AssemblyInfo.cs b/类库/VersionUpdate/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f9689bb --- /dev/null +++ b/类库/VersionUpdate/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("VersionUpdate")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("VersionUpdate")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +//将 ComVisible 设置为 false 将使此程序集中的类型 +//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("38b69c05-86d3-49ec-bc45-698e8b5919f4")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/类库/VersionUpdate/Properties/Resources.Designer.cs b/类库/VersionUpdate/Properties/Resources.Designer.cs new file mode 100644 index 0000000..823dacb --- /dev/null +++ b/类库/VersionUpdate/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace VersionUpdate.Properties { + using System; + + + /// + /// 一个强类型的资源类,用于查找本地化的字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// 返回此类使用的缓存的 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VersionUpdate.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性 + /// 重写当前线程的 CurrentUICulture 属性。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/类库/VersionUpdate/Properties/Resources.resx b/类库/VersionUpdate/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/类库/VersionUpdate/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/类库/VersionUpdate/Properties/Settings.Designer.cs b/类库/VersionUpdate/Properties/Settings.Designer.cs new file mode 100644 index 0000000..c2a2f17 --- /dev/null +++ b/类库/VersionUpdate/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 +// +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 +// +//------------------------------------------------------------------------------ + +namespace VersionUpdate.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/类库/VersionUpdate/Properties/Settings.settings b/类库/VersionUpdate/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/类库/VersionUpdate/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/类库/VersionUpdate/UpdateForm.Designer.cs b/类库/VersionUpdate/UpdateForm.Designer.cs new file mode 100644 index 0000000..6b5a919 --- /dev/null +++ b/类库/VersionUpdate/UpdateForm.Designer.cs @@ -0,0 +1,106 @@ +namespace LevelUpdate +{ + partial class UpdateForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UpdateForm)); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.button1 = new System.Windows.Forms.Button(); + this.progressBar1 = new System.Windows.Forms.ProgressBar(); + this.label1 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // richTextBox1 + // + this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.richTextBox1.Location = new System.Drawing.Point(-1, 1); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.ReadOnly = true; + this.richTextBox1.Size = new System.Drawing.Size(487, 326); + this.richTextBox1.TabIndex = 1; + this.richTextBox1.Text = ""; + // + // button1 + // + this.button1.Enabled = false; + this.button1.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.button1.Location = new System.Drawing.Point(172, 395); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(136, 34); + this.button1.TabIndex = 2; + this.button1.Text = "开始更新"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // progressBar1 + // + this.progressBar1.Location = new System.Drawing.Point(3, 362); + this.progressBar1.Name = "progressBar1"; + this.progressBar1.Size = new System.Drawing.Size(479, 25); + this.progressBar1.TabIndex = 3; + // + // label1 + // + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); + this.label1.Location = new System.Drawing.Point(1, 332); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(482, 23); + this.label1.TabIndex = 4; + this.label1.Text = "准备就绪..."; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // UpdateForm + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.ClientSize = new System.Drawing.Size(485, 436); + this.Controls.Add(this.label1); + this.Controls.Add(this.progressBar1); + this.Controls.Add(this.button1); + this.Controls.Add(this.richTextBox1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UpdateForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = " 检 查 更 新"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.UpdateForm_FormClosing); + this.Load += new System.EventHandler(this.UpdateForm_Load); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.RichTextBox richTextBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.ProgressBar progressBar1; + private System.Windows.Forms.Label label1; + } +} \ No newline at end of file diff --git a/类库/VersionUpdate/UpdateForm.cs b/类库/VersionUpdate/UpdateForm.cs new file mode 100644 index 0000000..3897658 --- /dev/null +++ b/类库/VersionUpdate/UpdateForm.cs @@ -0,0 +1,413 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Xml; +using System.Xml.Linq; + +namespace LevelUpdate +{ + public partial class UpdateForm : Form + { + public UpdateForm() + { + InitializeComponent(); + } + + private void UpdateForm_Load(object sender, EventArgs e) + { + if (!Program.NotRelationEXE) + { + this.button1.Text = "重启更新"; + } + var thraed = new Thread(new ThreadStart(delegate { + try + { + CheckUpdate(); + } + catch (Exception ex) + { + ChangeStatus("更新失败:" + ex.Message); + } + })); + thraed.IsBackground = true; + thraed.Start(); + + + } + private void ChangeStatus(string text,params object[] objs) + { + if (!this.IsDisposed && !this.IsClose) + { + var temp = string.Format(text, objs); + this.label1.Invoke(new Action(delegate + { + this.label1.Text = temp; + + })); + } + + } + + string Path = System.IO.Directory.GetCurrentDirectory(); + string XMLPath = string.Empty; + XmlDocument XmlDoc = new XmlDocument(); + #region XmlDocument读取 + List need_update = new List(); + InstallFileForm lodingUpdate = null; + public void CheckUpdate() + { + + + XMLPath = Path + "\\LevelUpdate.xml"; + if (!File.Exists(XMLPath)) throw new Exception("找不到LevelUpdate.xml必备文件!"); + //使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件. + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true;//忽略文档里面的注释 + using (XmlReader reader = XmlReader.Create(XMLPath, settings)) + { + XmlDoc.Load(reader); + XmlNode xn = XmlDoc.SelectSingleNode("Files"); + // 得到根节点的所有子节点 + XmlNodeList xnl = xn.ChildNodes; + StringBuilder sb = new StringBuilder(); + foreach (XmlNode node in xnl) + { + try + { + var Name = node.Attributes["Name"].Value; + var Url = node.Attributes["Url"].Value; + var CurVersion = Version.Parse(node.Attributes["Version"].Value); + ChangeStatus("正在检测{0}文件包...",Name); + XmlDocument temp_xml = new XmlDocument(); + temp_xml.Load(Url); + var temp_node = temp_xml.SelectSingleNode("History"); + + var temp_datas = temp_node.SelectNodes("Data"); + //更新内容 + List temp_update = new List(); + foreach (XmlNode item in temp_datas) + { + var ver = Version.Parse(item.Attributes["Ver"].Value); + if (ver > CurVersion) temp_update.Add(item); + } + + if (temp_update.Count > 0) + { + sb.AppendLine(Name + "文件包更新内容如下:"); + sb.AppendLine("-------------------------------"); + foreach (var item in temp_update) + { + sb.AppendLine(item.Attributes["Ver"].Value); + sb.AppendLine(item.Attributes["Msg"].Value.Replace("[br]", "\r\n")); + sb.AppendLine(); + } + var new_data = temp_update[0]; + this.richTextBox1.Invoke(new Action(delegate + { + this.richTextBox1.Text = sb.ToString(); + })); + var t = temp_update[0]; + XmlAttribute attr = t.OwnerDocument.CreateAttribute("Name"); + attr.Value = Name; + t.Attributes.Append(attr); + need_update.Add(temp_update[0]); + sb.AppendLine(""); + + } + else ChangeStatus("正在检测{0}文件包无新版本!", Name); + + } + catch (Exception ex) + { + ChangeStatus("更新错误:{0}", ex.Message); + } + } + } + + + if (need_update.Count > 0) + { + ChangeStatus("发现有{0}个新文件包!", need_update.Count); + this.button1.Invoke(new Action(delegate + { + this.button1.Enabled = true; + //if(Program.NotRelationEXE) button1_Click(null,null); + })); + } + else + { + ChangeStatus("没有发现新版本文件包!"); + Thread.Sleep(1000); + if (!this.IsDisposed && !IsClose) + { + this.Invoke(new Action(delegate + { + this.Close(); + })); + } + } + + } + + #endregion XmlDocument读取 + + + + + + + + /// + /// 退出 + /// + private static void Exit(bool start = false) + { + try + { + if (start) + { + //程序位置 + string strAppFileName = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; + System.Diagnostics.Process myNewProcess = new System.Diagnostics.Process(); + //要启动的应用程序 + myNewProcess.StartInfo.FileName = strAppFileName; + // 设置要启动的进程的初始目录 + myNewProcess.StartInfo.WorkingDirectory = Application.ExecutablePath; + //启动程序 + myNewProcess.Start(); + } + //结束该程序 + // Application.Exit(); + //结束该所有线程 + //Environment.Exit(0); + System.Diagnostics.Process.GetCurrentProcess().Kill(); + } + catch (Exception) + { } + } + + public static string MapFile(string file, string path = "") + { + return System.IO.Path.Combine(MapPath(path, true), file); + } + public static string MapPath(string path = "", bool CreateDirectory = true) + { + if (string.IsNullOrWhiteSpace(path)) + { + return System.Windows.Forms.Application.StartupPath.ToString() + "\\"; + } + path = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath.ToString() + "\\", path); + if (!(!CreateDirectory || Directory.Exists(path))) + { + Directory.CreateDirectory(path); + } + return path; + } + + class Cmd + { + private static string CmdPath = @"C:\Windows\System32\cmd.exe"; + /// + /// 执行cmd命令 返回cmd窗口显示的信息 + /// 多命令请使用批处理命令连接符: + /// + /// + /// 执行的命令 + public static string RunCmd(string cmd) + { + cmd = cmd.Trim().TrimEnd('&') + "&exit";//说明:不管命令是否成功均执行exit命令,否则当调用ReadToEnd()方法时,会处于假死状态 + using (Process p = new Process()) + { + p.StartInfo.FileName = CmdPath; + p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动 + p.StartInfo.RedirectStandardInput = true; //接受来自调用程序的输入信息 + p.StartInfo.RedirectStandardOutput = true; //由调用程序获取输出信息 + p.StartInfo.RedirectStandardError = true; //重定向标准错误输出 + p.StartInfo.CreateNoWindow = true; //不显示程序窗口 + p.Start();//启动程序 + + //向cmd窗口写入命令 + p.StandardInput.WriteLine(cmd); + p.StandardInput.AutoFlush = true; + + //获取cmd窗口的输出信息 + string output = p.StandardOutput.ReadToEnd(); + p.WaitForExit();//等待程序执行完退出进程 + p.Close(); + + return output; + } + } + } + + + + private void button1_Click(object sender, EventArgs e) + { + if (!Program.NotRelationEXE) + { + var name = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName; + var update = MapFile("LevelUpdate.exe"); + Program.StartProcess(update, name); + //this.Visible = false; + Thread.Sleep(500); + Exit(); + return; + } + + try + { + this.button1.Text = "更新中.."; + this.button1.Enabled = false; + var thread = new Thread(new ThreadStart(delegate + { + int number = 1; + try + { + + foreach (var item in need_update) + { + var filename = MapFile(item.Attributes["Ver"].Value + "_" + DateTime.Now.Ticks + ".zip", "Cache\\Update"); //GetPath("Cache")+ "\\Update\\"+Guid.NewGuid().ToString() + "_"+ item.Attributes["Ver"].Value + ".zip"; + ChangeStatus("开始更新{0}文件包,共{1}/{2}个文件包..", item.Attributes["Name"].Value, number, need_update.Count); + foreach (XmlNode _temp in XmlDoc.SelectSingleNode("Files").ChildNodes) + { + + if (item.Attributes["Name"].Value == _temp.Attributes["Name"].Value) + { + _temp.Attributes["Version"].Value = item.Attributes["Ver"].Value; + break; + } + } + + DownloadFile(item.Attributes["Url"].Value, filename, this.progressBar1); + ChangeStatus("正在安装{0}文件包..", item.Attributes["Name"].Value); + ZipArchive.UnZip(filename, Path); + XmlDoc.Save(XMLPath); + number++; + } + ChangeStatus("更新完成!"); + + var file_name = MapFile(Program.ExeName); + Program.StartProcess(file_name); + if (!IsClose && !this.IsDisposed) + { + this.Invoke(new Action(delegate () { + this.Close(); + })); + } + } + catch (Exception ex) + { + ChangeStatus("更新失败:" + ex.Message); + if (!IsClose) MessageBox.Show(ex.Message, "更新失败", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + })); + thread.IsBackground = true; + thread.Start(); + + } + catch (Exception ex) + { + ChangeStatus("更新失败:"+ex.Message); + if(!IsClose) + MessageBox.Show(ex.Message,"更新失败",MessageBoxButtons.OK,MessageBoxIcon.Error); + } + } + + private static Stream st = null; + private static Stream so = null; + private void DownloadFile(string URL, string filename, ProgressBar prog) + { + float percent = 0; + try + { + if (File.Exists(filename)) + File.Delete(filename); + System.Net.HttpWebRequest Myrq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(URL); + System.Net.HttpWebResponse myrp = (System.Net.HttpWebResponse)Myrq.GetResponse(); + long totalBytes = myrp.ContentLength; + prog.Invoke(new Action(delegate + { + prog.Maximum = (int)totalBytes; + + })); + + st = myrp.GetResponseStream(); + so = new System.IO.FileStream(filename, System.IO.FileMode.Create); + try + { + long totalDownloadedByte = 0; + byte[] by = new byte[1024]; + int osize = st.Read(by, 0, (int)by.Length); + while (osize > 0) + { + + totalDownloadedByte = osize + totalDownloadedByte; + Application.DoEvents(); + so.Write(by, 0, osize); + if (IsClose) return; + prog.Invoke(new Action(delegate { prog.Value = (int)totalDownloadedByte; })); + osize = st.Read(by, 0, (int)by.Length); + percent = (float)totalDownloadedByte / (float)totalBytes * 100; + Application.DoEvents(); //必须加注这句代码,否则label1将因为循环执行太快而来不及显示信息 + } + } + catch (Exception ex) + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + throw ex; + } + finally + { + if (so != null) + { + so.Close(); + so.Dispose(); + so = null; + } + if (st != null) + { + st.Close(); + st.Dispose(); + st = null; + } + } + } + catch (Exception ex) + { + throw ex; + } + } + private bool IsClose = false; + private void UpdateForm_FormClosing(object sender, FormClosingEventArgs e) + { + IsClose = true; + } + } +} diff --git a/类库/VersionUpdate/UpdateForm.resx b/类库/VersionUpdate/UpdateForm.resx new file mode 100644 index 0000000..1bbaeaa --- /dev/null +++ b/类库/VersionUpdate/UpdateForm.resx @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAABMLAAATCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhSMALXdEABCALwAQfC4AAIkPAxGBMC4lhj9wLIlEoyqK + RM0rjEXwK4xF6iqLRdQriUS8K4lEnx+EO1sKgisbPXtQAB2BOAAWiDQAHYQ4AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAC6TSgAAgh0AAIQjAAAAAAAAAAAAAAAAACR6PAASfzAAAI8cAgp6KDcTejCRH4E50y2M + R/w8mFT/TaJk/1epbv9Tp2r/TKNl/0efX/87llP/KolE8h6AOb8TfDB2FIExJSw9NgAKgysACIIpAAAA + AAAAAAAAAAAAAAAAAAAAAAAALpRKHuxTxQAYfjMABoIoABGCMAAdjD0AGnw1AAyAKxUYezN4HH434DqT + Uv9frXT/h8SY/4/Jn/+Jxpr/hcOW/3/AkP94vYr/crmF/2u2f/9drnL/RZ5d/zONTPsmgj/TGX40VQCF + HwYUgTEAAJonAA2MLwAAAAAAAAAAAAAAAAAphELEHH02aRiFNhIfZzIADocvABp1MgAWfjMvFHcvriuH + RPplr3n/ksui/5vNqf+TyaL/jMac/4XClv99v5D/d7yK/3K5hf9stoD/ZrN6/1+wdf9brnH/Uqpq/z2Y + Vv8kgD3pGXozehqGNQ8jejsAMnNGAACFJAAAAAAAAAAAACqBQv8of0D3GXYytw91Kk4Jjy0IHn85Mx95 + N8dAk1b/hcKV/6HRrv+azqj/k8qi/36/kP9otH3/Waxv/02nZf9KpmP/UKlo/1Oqa/9WrG3/Wa1v/1Op + av9NpmX/R6Vh/zqaVP8rg0P4Inw6nhqCNxkbfjYAMlI7AAAAAAAAAAAALINE/n65jv9YoWz/H3g36x51 + N6gedTbKR5Zd/5fMpf+i0a//ms6o/4LClP9WrG3/PJ9X/y+ZTP8wmkz/MZtO/zKcT/8xm07/MJpN/zWc + Uf8/oFn/SKRh/0akYP9AoVr/O6BW/zSaUP8qgkL8HHY0kACAIgoOfSwACYQrAAAAAAAqf0H+oMys/8Lj + y/+GwJb/PY1T/0mWXf+azqj/o9Kw/5bLpP9qtn//Op5V/y+ZTP8ynE//NZ1R/zOYT/8xkUv/MI9J/zCR + Sv8ylk3/NJ1Q/zOcT/81nFH/PJ9X/zueVf81nFH/NJxQ/zOYTv8ieTr0E3EsagCcIgMLhCwAG3k1ACp+ + Qf2WxqT/vN/G/7Xbv/+g0Kz/m86p/6LSr/+Wy6T/W69y/zGaTf8ym07/NZ5R/zGTS/8pfkD8JHc77Bty + M8wSayu0F28vxiF1OOkpf0H9MZNM/zWdUf80nFD/NZxR/zSbUP80m1D/NZ1R/zCSS/8hdDjiGnUzSSM3 + KgAZfzQAK3xB/JPDof+027//qdS0/6XSsf+g0K3/lsqk/1isb/8wmUz/M5xP/zSbUP8tiEb/H3E25BZu + LYUTdi4zCnAnEwBuFQ0AbB0REnQtMxluMIkgbzbnLIlF/zSdUf80nFD/NJtQ/zSbUP81nlH/M5lP/yZ4 + PP8bbjGvFIExDRh4MgAsekH8kMKe/67Zuv+j0bD/nc6r/5vNqP9ms3v/MJlN/zObT/80m1D/K4BB/yNr + NvcbdjR3AJgkCBVxLgAQcysAAm0gAAttJgAXbzAAAJQqAw5rJ1QYaC3WK4VE/zWeUf81nlH/NZxR/y6K + R/8fcDX1FWksqRJwKz0MgioEEHgsACx4QfyMv5r/qNa1/53Pq/+bzqn/eLyK/zSbUP8ymk//NJtQ/zSc + Uf8ylk3/Kn5B/htpMN4TZiqBD3UrJQDBGwAAiiQAAHQKAA91LAAJfCgARh9CAAhpI0cZZy7jMI5K/zGT + TP8ldjv+HGYwyxJrKWEAdyENHGUxABF4LAAlfT0ALHZA+4i8lv+i06//ms6o/4fEl/9AoVr/MZlN/zSb + UP80m1D/NJtQ/zWdUf82oVP/L4tI/x5kMf8OYCSsA3UhIQR0IwAAdAoAAAAAAAZ2IwAKdCYAALMYAhRm + K3IfZzL2IGg06RZlK4sOciklLTwyAAVtIAAadTMACGwgEyV+PVcsdD/6hLqS/53Qq/+RyaD/Tqhn/y+Z + TP80m1D/NJtQ/zSbUP81nlH/NJtQ/yyERP8gajPxGWMtpwxrJjwBdSAGBHMjAAB0CgAAAAAAAAAAABVh + KQAQcyoADXwrDgxiI3ATaypFE5Q3BRNqKgAIbyIAAGAJBw9xKUYfeDe0Jnw97SxxP/qAt4//m8+p/2y3 + gP8wmk3/M5tP/zSbUP81nVH/NZ5R/y+MSf8gazX6FFwoxBBiJlcNfywOEGYnAAN1IQAEcyMAAHQKAAAA + AAAAAAAAAYkmABtjLgATbiwAGlYtABpgLgAKcCUAAFgAAQBnFykNbieSRItY6EqSXv8meT35K289+X21 + jf+LyJz/QqJc/zGZTf80nFH/NZ9S/zGSTP8kcTn/Glws2BRfKXQIbyQZITknAA96LAAWcy8AAYkmAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAGERAABaBgALcSUAD3ApAABpGxgNbydvKX0/1m+lfv+izK7/P5lY/yV1 + O/krbT74e7SL/2i2ff8xmk3/NZ5S/zOZTv8nej7/GV0s7BFYJZQRaikwAP+hAA5lJQAHgCgADG4mAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9zKgAHcSIAFngyAAFrGQkDah1NEnEsuEyRX/mYwqP/weDJ/3W+ + iP8rjkb/JXE6+i1uP/durYD/QKVc/zKcT/8shET/HmMx9g5VIrAJXyFFBJMqBxRjKgAQmjUAE34wAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtvJgAFaRwADXApAACCEgEPcSg0EXErmjKCSO96roj/tdi+/7ne + w/+bzqj/P6JZ/y2OR/8kbTj6MHBC9kudYf8vj0n/IWo1/RZZKM0TXihjCnwqEhBaJAAMbiYAALwrAAGL + JwAAAAAAAAAAAAAAAAAAAAAAAAAAAABXDAAUfTMADnMoACiBRQAEbCEbEHAqdyJ5Otpam2z/pMyu/7nd + w/+t17n/qNS0/2Kxd/8vm0z/MI9K/yNpNvsmaDf2Imk1/xRZJ94OWSGCDGslHioAAAAOeywAH5I/ACuW + SwAZiTcAMpZNAAmBKQAAAAAAAAAAAAAAAAAAYxEAAGEOABR2LgALciYNEXEpVxRyLsQ9iVL7iryX/7fb + wv+y2r3/pdOx/6HRrv+Fw5b/NZtR/zOdUP8wjkn/IWMz+x5kMeMOViKiBmIfNwCzIAMMZyQAHpA9AACB + GwMVjDU6GI04cQ+GLhUYiDYAap9+AAAAAAAAAAAAAAAAAABjEQAAXwoFD3IpOR55N6QtgUTwbKl9/6vT + tv+13MD/qdW1/6HQrv+azaj/ksqh/06oZ/8wmUz/NZ5R/y+NSP8gXzH8KIFAPgx/KgsKVyAADoswACaU + RQAXjTcdGY04fiSRQeEwlUv5HYk7ghOEMwUXgTQAEXYtAACGJAAAAAAAAGIRAABhDhoUciygI3g6/Wqm + ev+33MH/stu+/6LRr/+bzan/lMqj/5HIoP9rtn//MppO/zObT/81nlH/L4xI/x5bL/whbjYABmwgAByQ + OwAEhScJG487UiKRQL9CoFz8o9Cv/5bIo/8likHrFH0wWP///wARdCwAHHg1AAAAAAAALAAAJKZaAA9u + KB4TbCt3HW802E2OX/2FuJP/mMyn/5DIn/+JxZr/fr+Q/z+gWf8xmk7/NJtQ/zWeUf8vi0j/HVgt/QCB + IQAAbgACFIszMyWTQ5kok0bwcreE/+Hw5f/6/Pv/7/fx/3OzhP8ZfDTfGHkyYA5yKAYVbiwACGIfAABc + FgAMYSEAEWopAABRAAUSZSlqGGQt8jp8TP+Cu5L/hMOV/37Akf9Vq23/MJpN/zSbUP80m1D/NZ5R/y+L + SP8dVy39B4InAAB0DQgcjTuXMZZM/y+YTP+KxZr/9fr2/+n07P/k8ef/1Ora/3Cwgf8kfjztEW8rkwxq + JDoFYRsSAFsQDgtjIRIJXx8zCVsfgRtkL99LjFz/e7mM/4HCk/96vYz/Y7J5/zacUv8zm0//NJxQ/zSb + UP81nlH/L4tI/x1YLf4KgyoAR5lgAB+LPTwrjkbaL5RL/zKbT/+czqn/4O/j/9br2//Q6Nf/yOXQ/4m+ + l/9Cjlj+HXEz7ApgIcsHXB24Dl8kyyJrNes4e0r8YqFz/4PDlP98v47/dLqG/2aze/87n1f/MpxP/zSb + T/80m0//NZ5R/zWeUv8vi0j/HVgt/gqDKgABeSIAAFsAARmANWQnh0HzLpVK/zScUP+Gw5b/yeTQ/8bj + zf+73sT/ut7E/6fTs/+Eu5P/cayB/2Cgcf9mpHj/crGD/4C+kP+AwpL/dbuI/2+4gv9hsXf/QKFa/zKc + T/80m1D/JnM7/yJnNf8vi0j/NqFT/y+OSf8dWC3+AAAAAAZ6JwAOeSsAAG4aCh59OI4rhUT5L5RK/y+a + Tf9brnL/nM6q/7LZvP+q1bX/otGv/57Qq/+Yzab/jsme/4jGmf+BwpL/d7yJ/2+4g/9ptX7/Wa1w/zuf + Vv8znE//NJtQ/yVxOv8YUSjZGFAnrhZSJuskcTn/K4FD/x1ZLv4AAAAAAAAAAP///wAdfzkAGnkzFBt1 + NI8jejr3L5BJ/y6aTP86n1b/XrB0/4fEmP+TyqL/jsie/4nEmf+BwZL/eb2M/3K5hv9rtX7/Xq90/0ak + X/82nFL/M55Q/zKXTv8jbjf/FVAl2Q1NHkYAUw8KBEYTTwtHGbgVUyb4HFYs/wAAAAAAAAAAAF0OACSB + PwAWdC8AAGIWDA1oJn4ecDXvLIVE/zCWTP8wnE3/M5xQ/0ChW/9Uq2z/XrB0/16wdP9arnH/Tqdm/0Gh + Wv82nVH/M51P/zSeUf8th0b/G14t/gpGGcEFRxY/ED8wAAFPEQAOTTEAAEIGEglKGGoZVinHAAAAAAAA + AAAAAAAAAIckABNoKwAFZB4AAFsQCg9iJFkXYyvIIW42+y2HRv8ymE7/M5xP/zGcTv8wnE7/MJxN/zGc + Tv8ynU//M51P/zScUP8tiEX/Ims1/xlVKesNSh2MAEIKIQxKGwAJURkABkgOAABDAAABRA4AN3NvACBi + MSEAAAAAAAAAAAAAAAAAAAAAAAAAAABfFwAAXhYAN4JfAAJXFh0TWSZ4GVwrzxxfLvYkbzn/Kn9C/y2G + Rf8uiUb/LolH/yqAQv8mczv/HV4v/hFOId8GQxWiBUgTSQlWGQUGRBMAGDooAAAAAAAAAAAAAAAAAAA/ + AAAAOAAAH2ExAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhcHAACWBEACloeAAAzAAEATxIsDlIgWx1Z + LaAcVSzaG1Mr7BxVK/UcViz2G1Qr3RxVLLUTTyR/AUcSPQA+AAgMShYADFAcAAAeAAAATA0AAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/AAAPxwAAB8AAAAHAAAAAwAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAA + AAAAACAAAAAwAAAAMAAAAPgAAAPwAAAPwAAAHwAAAA4AAAAOAAAAAgAAAAIAAAAAAAAAAAAAAAAAAAAA + AACAAAAAwAAAAMAAAADgAAAA+AAAOPwAAD8= + + + \ No newline at end of file diff --git a/类库/VersionUpdate/VersionUpdate.csproj b/类库/VersionUpdate/VersionUpdate.csproj new file mode 100644 index 0000000..06bc4d7 --- /dev/null +++ b/类库/VersionUpdate/VersionUpdate.csproj @@ -0,0 +1,168 @@ + + + + + Debug + AnyCPU + {56F1DE55-930D-479C-B127-FAF0CD9026EC} + WinExe + Properties + VersionUpdate + VersionUpdate + v4.0 + 512 + + + x86 + true + full + false + ..\..\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + gtk_refresh_reload_update_32px_2205_easyicon.net.ico + + + + + + + + + + + + + + + + + + + + Form + + + InstallFileForm.cs + + + + + Form + + + DownloadForm.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InstallFileForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + DownloadForm.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + \ No newline at end of file diff --git a/类库/VersionUpdate/VersionUpdate.sln b/类库/VersionUpdate/VersionUpdate.sln new file mode 100644 index 0000000..562c8cf --- /dev/null +++ b/类库/VersionUpdate/VersionUpdate.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.1340 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VersionUpdate", "VersionUpdate.csproj", "{38B69C05-86D3-49EC-BC45-698E8B5919F4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {38B69C05-86D3-49EC-BC45-698E8B5919F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38B69C05-86D3-49EC-BC45-698E8B5919F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38B69C05-86D3-49EC-BC45-698E8B5919F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38B69C05-86D3-49EC-BC45-698E8B5919F4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E9ADDA6C-1669-4FAA-AFC0-4B2036EC00B9} + EndGlobalSection +EndGlobal diff --git a/类库/VersionUpdate/ZIP/BZip2/BZip2.cs b/类库/VersionUpdate/ZIP/BZip2/BZip2.cs new file mode 100644 index 0000000..91669a8 --- /dev/null +++ b/类库/VersionUpdate/ZIP/BZip2/BZip2.cs @@ -0,0 +1,105 @@ +// BZip2.cs +// +// Copyright (C) 2010 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// Suppress this in CF and 1.1, not needed. Static classes introduced in C# version 2.0 +#if !NETCF_2_0 && !NET_1_1 + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.BZip2 { + + /// + /// An example class to demonstrate compression and decompression of BZip2 streams. + /// + public static class BZip2 + { + /// + /// Decompress the input writing + /// uncompressed data to the output stream + /// + /// The readable stream containing data to decompress. + /// The output stream to receive the decompressed data. + /// Both streams are closed on completion if true. + public static void Decompress(Stream inStream, Stream outStream, bool isStreamOwner) + { + if (inStream == null || outStream == null) { + throw new Exception("Null Stream"); + } + + try { + using (BZip2InputStream bzipInput = new BZip2InputStream(inStream)) { + bzipInput.IsStreamOwner = isStreamOwner; + Core.StreamUtils.Copy(bzipInput, outStream, new byte[4096]); + } + } finally { + if (isStreamOwner) { + // inStream is closed by the BZip2InputStream if stream owner + outStream.Close(); + } + } + } + + /// + /// Compress the input stream sending + /// result data to output stream + /// + /// The readable stream to compress. + /// The output stream to receive the compressed data. + /// Both streams are closed on completion if true. + /// Block size acts as compression level (1 to 9) with 1 giving + /// the lowest compression and 9 the highest. + public static void Compress(Stream inStream, Stream outStream, bool isStreamOwner, int level) + { + if (inStream == null || outStream == null) { + throw new Exception("Null Stream"); + } + + try { + using (BZip2OutputStream bzipOutput = new BZip2OutputStream(outStream, level)) { + bzipOutput.IsStreamOwner = isStreamOwner; + Core.StreamUtils.Copy(inStream, bzipOutput, new byte[4096]); + } + } finally { + if (isStreamOwner) { + // outStream is closed by the BZip2OutputStream if stream owner + inStream.Close(); + } + } + } + + } +} +#endif diff --git a/类库/VersionUpdate/ZIP/BZip2/BZip2Constants.cs b/类库/VersionUpdate/ZIP/BZip2/BZip2Constants.cs new file mode 100644 index 0000000..ad3f40d --- /dev/null +++ b/类库/VersionUpdate/ZIP/BZip2/BZip2Constants.cs @@ -0,0 +1,197 @@ +// BZip2Constants.cs +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + /// + /// Defines internal values for both compression and decompression + /// + internal sealed class BZip2Constants + { + /// + /// Random numbers used to randomise repetitive blocks + /// + public readonly static int[] RandomNumbers = { + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, + 936, 638 + }; + + /// + /// When multiplied by compression parameter (1-9) gives the block size for compression + /// 9 gives the best compression but uses the most memory. + /// + public const int BaseBlockSize = 100000; + + /// + /// Backend constant + /// + public const int MaximumAlphaSize = 258; + + /// + /// Backend constant + /// + public const int MaximumCodeLength = 23; + + /// + /// Backend constant + /// + public const int RunA = 0; + + /// + /// Backend constant + /// + public const int RunB = 1; + + /// + /// Backend constant + /// + public const int GroupCount = 6; + + /// + /// Backend constant + /// + public const int GroupSize = 50; + + /// + /// Backend constant + /// + public const int NumberOfIterations = 4; + + /// + /// Backend constant + /// + public const int MaximumSelectors = (2 + (900000 / GroupSize)); + + /// + /// Backend constant + /// + public const int OvershootBytes = 20; + + private BZip2Constants() + { + } + } +} + +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/VersionUpdate/ZIP/BZip2/BZip2Exception.cs b/类库/VersionUpdate/ZIP/BZip2/BZip2Exception.cs new file mode 100644 index 0000000..3b7c8ff --- /dev/null +++ b/类库/VersionUpdate/ZIP/BZip2/BZip2Exception.cs @@ -0,0 +1,90 @@ +// BZip2.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + /// + /// BZip2Exception represents exceptions specific to Bzip2 algorithm + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class BZip2Exception : SharpZipBaseException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected BZip2Exception(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + /// + /// Initialise a new instance of BZip2Exception. + /// + public BZip2Exception() + { + } + + /// + /// Initialise a new instance of BZip2Exception with its message set to message. + /// + /// The message describing the error. + public BZip2Exception(string message) : base(message) + { + } + + /// + /// Initialise an instance of BZip2Exception + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public BZip2Exception(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/VersionUpdate/ZIP/BZip2/BZip2InputStream.cs b/类库/VersionUpdate/ZIP/BZip2/BZip2InputStream.cs new file mode 100644 index 0000000..162c9d0 --- /dev/null +++ b/类库/VersionUpdate/ZIP/BZip2/BZip2InputStream.cs @@ -0,0 +1,1003 @@ +// BZip2InputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + /// + /// An input stream that decompresses files in the BZip2 format + /// + public class BZip2InputStream : Stream + { + #region Constants + const int START_BLOCK_STATE = 1; + const int RAND_PART_A_STATE = 2; + const int RAND_PART_B_STATE = 3; + const int RAND_PART_C_STATE = 4; + const int NO_RAND_PART_A_STATE = 5; + const int NO_RAND_PART_B_STATE = 6; + const int NO_RAND_PART_C_STATE = 7; + #endregion + #region Constructors + /// + /// Construct instance for reading from stream + /// + /// Data source + public BZip2InputStream(Stream stream) + { + // init arrays + for (int i = 0; i < BZip2Constants.GroupCount; ++i) + { + limit[i] = new int[BZip2Constants.MaximumAlphaSize]; + baseArray[i] = new int[BZip2Constants.MaximumAlphaSize]; + perm[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + BsSetStream(stream); + Initialize(); + InitBlock(); + SetupBlock(); + } + + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + + #region Stream Overrides + /// + /// Gets a value indicating if the stream supports reading + /// + public override bool CanRead + { + get { + return baseStream.CanRead; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek { + get { + return baseStream.CanSeek; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// This property always returns false + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// Gets the length in bytes of the stream. + /// + public override long Length { + get { + return baseStream.Length; + } + } + + /// + /// Gets or sets the streams position. + /// Setting the position is not supported and will throw a NotSupportException + /// + /// Any attempt to set the position + public override long Position { + get { + return baseStream.Position; + } + set { + throw new NotSupportedException("BZip2InputStream position cannot be set"); + } + } + + /// + /// Flushes the stream. + /// + public override void Flush() + { + if (baseStream != null) { + baseStream.Flush(); + } + } + + /// + /// Set the streams position. This operation is not supported and will throw a NotSupportedException + /// + /// A byte offset relative to the parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// The new position of the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("BZip2InputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. + /// This operation is not supported and will throw a NotSupportedExceptionortedException + /// + /// The new length for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("BZip2InputStream SetLength not supported"); + } + + /// + /// Writes a block of bytes to this stream using data from a buffer. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The buffer to source data from. + /// The offset to start obtaining data from. + /// The number of bytes of data to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("BZip2InputStream Write not supported"); + } + + /// + /// Writes a byte to the current position in the file stream. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The value to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("BZip2InputStream WriteByte not supported"); + } + + /// + /// Read a sequence of bytes and advances the read position by one byte. + /// + /// Array of bytes to store values in + /// Offset in array to begin storing data + /// The maximum number of bytes to read + /// The total number of bytes read into the buffer. This might be less + /// than the number of bytes requested if that number of bytes are not + /// currently available or zero if the end of the stream is reached. + /// + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + for (int i = 0; i < count; ++i) { + int rb = ReadByte(); + if (rb == -1) { + return i; + } + buffer[offset + i] = (byte)rb; + } + return count; + } + + /// + /// Closes the stream, releasing any associated resources. + /// + public override void Close() + { + if ( IsStreamOwner && (baseStream != null) ) { + baseStream.Close(); + } + } + /// + /// Read a byte from stream advancing position + /// + /// byte read or -1 on end of stream + public override int ReadByte() + { + if (streamEnd) + { + return -1; // ok + } + + int retChar = currentChar; + switch (currentState) + { + case RAND_PART_B_STATE: + SetupRandPartB(); + break; + case RAND_PART_C_STATE: + SetupRandPartC(); + break; + case NO_RAND_PART_B_STATE: + SetupNoRandPartB(); + break; + case NO_RAND_PART_C_STATE: + SetupNoRandPartC(); + break; + case START_BLOCK_STATE: + case NO_RAND_PART_A_STATE: + case RAND_PART_A_STATE: + break; + default: + break; + } + return retChar; + } + + #endregion + + void MakeMaps() + { + nInUse = 0; + for (int i = 0; i < 256; ++i) { + if (inUse[i]) { + seqToUnseq[nInUse] = (byte)i; + unseqToSeq[i] = (byte)nInUse; + nInUse++; + } + } + } + + void Initialize() + { + char magic1 = BsGetUChar(); + char magic2 = BsGetUChar(); + + char magic3 = BsGetUChar(); + char magic4 = BsGetUChar(); + + if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') { + streamEnd = true; + return; + } + + SetDecompressStructureSizes(magic4 - '0'); + computedCombinedCRC = 0; + } + + void InitBlock() + { + char magic1 = BsGetUChar(); + char magic2 = BsGetUChar(); + char magic3 = BsGetUChar(); + char magic4 = BsGetUChar(); + char magic5 = BsGetUChar(); + char magic6 = BsGetUChar(); + + if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) { + Complete(); + return; + } + + if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) { + BadBlockHeader(); + streamEnd = true; + return; + } + + storedBlockCRC = BsGetInt32(); + + blockRandomised = (BsR(1) == 1); + + GetAndMoveToFrontDecode(); + + mCrc.Reset(); + currentState = START_BLOCK_STATE; + } + + void EndBlock() + { + computedBlockCRC = (int)mCrc.Value; + + // -- A bad CRC is considered a fatal error. -- + if (storedBlockCRC != computedBlockCRC) { + CrcError(); + } + + // 1528150659 + computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31); + computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC; + } + + void Complete() + { + storedCombinedCRC = BsGetInt32(); + if (storedCombinedCRC != (int)computedCombinedCRC) { + CrcError(); + } + + streamEnd = true; + } + + void BsSetStream(Stream stream) + { + baseStream = stream; + bsLive = 0; + bsBuff = 0; + } + + void FillBuffer() + { + int thech = 0; + + try { + thech = baseStream.ReadByte(); + } catch (Exception) { + CompressedStreamEOF(); + } + + if (thech == -1) { + CompressedStreamEOF(); + } + + bsBuff = (bsBuff << 8) | (thech & 0xFF); + bsLive += 8; + } + + int BsR(int n) + { + while (bsLive < n) { + FillBuffer(); + } + + int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1); + bsLive -= n; + return v; + } + + char BsGetUChar() + { + return (char)BsR(8); + } + + int BsGetIntVS(int numBits) + { + return BsR(numBits); + } + + int BsGetInt32() + { + int result = BsR(8); + result = (result << 8) | BsR(8); + result = (result << 8) | BsR(8); + result = (result << 8) | BsR(8); + return result; + } + + void RecvDecodingTables() + { + char[][] len = new char[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + len[i] = new char[BZip2Constants.MaximumAlphaSize]; + } + + bool[] inUse16 = new bool[16]; + + //--- Receive the mapping table --- + for (int i = 0; i < 16; i++) { + inUse16[i] = (BsR(1) == 1); + } + + for (int i = 0; i < 16; i++) { + if (inUse16[i]) { + for (int j = 0; j < 16; j++) { + inUse[i * 16 + j] = (BsR(1) == 1); + } + } else { + for (int j = 0; j < 16; j++) { + inUse[i * 16 + j] = false; + } + } + } + + MakeMaps(); + int alphaSize = nInUse + 2; + + //--- Now the selectors --- + int nGroups = BsR(3); + int nSelectors = BsR(15); + + for (int i = 0; i < nSelectors; i++) { + int j = 0; + while (BsR(1) == 1) { + j++; + } + selectorMtf[i] = (byte)j; + } + + //--- Undo the MTF values for the selectors. --- + byte[] pos = new byte[BZip2Constants.GroupCount]; + for (int v = 0; v < nGroups; v++) { + pos[v] = (byte)v; + } + + for (int i = 0; i < nSelectors; i++) { + int v = selectorMtf[i]; + byte tmp = pos[v]; + while (v > 0) { + pos[v] = pos[v - 1]; + v--; + } + pos[0] = tmp; + selector[i] = tmp; + } + + //--- Now the coding tables --- + for (int t = 0; t < nGroups; t++) { + int curr = BsR(5); + for (int i = 0; i < alphaSize; i++) { + while (BsR(1) == 1) { + if (BsR(1) == 0) { + curr++; + } else { + curr--; + } + } + len[t][i] = (char)curr; + } + } + + //--- Create the Huffman decoding tables --- + for (int t = 0; t < nGroups; t++) { + int minLen = 32; + int maxLen = 0; + for (int i = 0; i < alphaSize; i++) { + maxLen = Math.Max(maxLen, len[t][i]); + minLen = Math.Min(minLen, len[t][i]); + } + HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize); + minLens[t] = minLen; + } + } + + void GetAndMoveToFrontDecode() + { + byte[] yy = new byte[256]; + int nextSym; + + int limitLast = BZip2Constants.BaseBlockSize * blockSize100k; + origPtr = BsGetIntVS(24); + + RecvDecodingTables(); + int EOB = nInUse+1; + int groupNo = -1; + int groupPos = 0; + + /*-- + Setting up the unzftab entries here is not strictly + necessary, but it does save having to do it later + in a separate pass, and so saves a block's worth of + cache misses. + --*/ + for (int i = 0; i <= 255; i++) { + unzftab[i] = 0; + } + + for (int i = 0; i <= 255; i++) { + yy[i] = (byte)i; + } + + last = -1; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + int zt = selector[groupNo]; + int zn = minLens[zt]; + int zvec = BsR(zn); + int zj; + + while (zvec > limit[zt][zn]) { + if (zn > 20) { // the longest code + throw new BZip2Exception("Bzip data error"); + } + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive-1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) { + throw new BZip2Exception("Bzip data error"); + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + + while (true) { + if (nextSym == EOB) { + break; + } + + if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) { + int s = -1; + int n = 1; + do { + if (nextSym == BZip2Constants.RunA) { + s += (0 + 1) * n; + } else if (nextSym == BZip2Constants.RunB) { + s += (1 + 1) * n; + } + + n <<= 1; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + + while (zvec > limit[zt][zn]) { + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive - 1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + } while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB); + + s++; + byte ch = seqToUnseq[yy[0]]; + unzftab[ch] += s; + + while (s > 0) { + last++; + ll8[last] = ch; + s--; + } + + if (last >= limitLast) { + BlockOverrun(); + } + continue; + } else { + last++; + if (last >= limitLast) { + BlockOverrun(); + } + + byte tmp = yy[nextSym - 1]; + unzftab[seqToUnseq[tmp]]++; + ll8[last] = seqToUnseq[tmp]; + + for (int j = nextSym-1; j > 0; --j) { + yy[j] = yy[j - 1]; + } + yy[0] = tmp; + + if (groupPos == 0) { + groupNo++; + groupPos = BZip2Constants.GroupSize; + } + + groupPos--; + zt = selector[groupNo]; + zn = minLens[zt]; + zvec = BsR(zn); + while (zvec > limit[zt][zn]) { + zn++; + while (bsLive < 1) { + FillBuffer(); + } + zj = (bsBuff >> (bsLive-1)) & 1; + bsLive--; + zvec = (zvec << 1) | zj; + } + nextSym = perm[zt][zvec - baseArray[zt][zn]]; + continue; + } + } + } + + void SetupBlock() + { + int[] cftab = new int[257]; + + cftab[0] = 0; + Array.Copy(unzftab, 0, cftab, 1, 256); + + for (int i = 1; i <= 256; i++) { + cftab[i] += cftab[i - 1]; + } + + for (int i = 0; i <= last; i++) { + byte ch = ll8[i]; + tt[cftab[ch]] = i; + cftab[ch]++; + } + + cftab = null; + + tPos = tt[origPtr]; + + count = 0; + i2 = 0; + ch2 = 256; /*-- not a char and not EOF --*/ + + if (blockRandomised) { + rNToGo = 0; + rTPos = 0; + SetupRandPartA(); + } else { + SetupNoRandPartA(); + } + } + + void SetupRandPartA() + { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + ch2 ^= (int)((rNToGo == 1) ? 1 : 0); + i2++; + + currentChar = ch2; + currentState = RAND_PART_B_STATE; + mCrc.Update(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + void SetupNoRandPartA() + { + if (i2 <= last) { + chPrev = ch2; + ch2 = ll8[tPos]; + tPos = tt[tPos]; + i2++; + + currentChar = ch2; + currentState = NO_RAND_PART_B_STATE; + mCrc.Update(ch2); + } else { + EndBlock(); + InitBlock(); + SetupBlock(); + } + } + + void SetupRandPartB() + { + if (ch2 != chPrev) { + currentState = RAND_PART_A_STATE; + count = 1; + SetupRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + if (rNToGo == 0) { + rNToGo = BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + z ^= (byte)((rNToGo == 1) ? 1 : 0); + j2 = 0; + currentState = RAND_PART_C_STATE; + SetupRandPartC(); + } else { + currentState = RAND_PART_A_STATE; + SetupRandPartA(); + } + } + } + + void SetupRandPartC() + { + if (j2 < (int)z) { + currentChar = ch2; + mCrc.Update(ch2); + j2++; + } else { + currentState = RAND_PART_A_STATE; + i2++; + count = 0; + SetupRandPartA(); + } + } + + void SetupNoRandPartB() + { + if (ch2 != chPrev) { + currentState = NO_RAND_PART_A_STATE; + count = 1; + SetupNoRandPartA(); + } else { + count++; + if (count >= 4) { + z = ll8[tPos]; + tPos = tt[tPos]; + currentState = NO_RAND_PART_C_STATE; + j2 = 0; + SetupNoRandPartC(); + } else { + currentState = NO_RAND_PART_A_STATE; + SetupNoRandPartA(); + } + } + } + + void SetupNoRandPartC() + { + if (j2 < (int)z) { + currentChar = ch2; + mCrc.Update(ch2); + j2++; + } else { + currentState = NO_RAND_PART_A_STATE; + i2++; + count = 0; + SetupNoRandPartA(); + } + } + + void SetDecompressStructureSizes(int newSize100k) + { + if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) { + throw new BZip2Exception("Invalid block size"); + } + + blockSize100k = newSize100k; + + if (newSize100k == 0) { + return; + } + + int n = BZip2Constants.BaseBlockSize * newSize100k; + ll8 = new byte[n]; + tt = new int[n]; + } + + static void CompressedStreamEOF() + { + throw new EndOfStreamException("BZip2 input stream end of compressed stream"); + } + + static void BlockOverrun() + { + throw new BZip2Exception("BZip2 input stream block overrun"); + } + + static void BadBlockHeader() + { + throw new BZip2Exception("BZip2 input stream bad block header"); + } + + static void CrcError() + { + throw new BZip2Exception("BZip2 input stream crc error"); + } + + static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize) + { + int pp = 0; + + for (int i = minLen; i <= maxLen; ++i) + { + for (int j = 0; j < alphaSize; ++j) + { + if (length[j] == i) + { + perm[pp] = j; + ++pp; + } + } + } + + for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) + { + baseArray[i] = 0; + } + + for (int i = 0; i < alphaSize; i++) + { + ++baseArray[length[i] + 1]; + } + + for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++) + { + baseArray[i] += baseArray[i - 1]; + } + + for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) + { + limit[i] = 0; + } + + int vec = 0; + + for (int i = minLen; i <= maxLen; i++) + { + vec += (baseArray[i + 1] - baseArray[i]); + limit[i] = vec - 1; + vec <<= 1; + } + + for (int i = minLen + 1; i <= maxLen; i++) + { + baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i]; + } + } + + #region Instance Fields + /*-- + index of the last char in the block, so + the block size == last + 1. + --*/ + int last; + + /*-- + index in zptr[] of original string after sorting. + --*/ + int origPtr; + + /*-- + always: in the range 0 .. 9. + The current block size is 100000 * this number. + --*/ + int blockSize100k; + + bool blockRandomised; + + int bsBuff; + int bsLive; + IChecksum mCrc = new StrangeCRC(); + + bool[] inUse = new bool[256]; + int nInUse; + + byte[] seqToUnseq = new byte[256]; + byte[] unseqToSeq = new byte[256]; + + byte[] selector = new byte[BZip2Constants.MaximumSelectors]; + byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors]; + + int[] tt; + byte[] ll8; + + /*-- + freq table collected to save a pass over the data + during decompression. + --*/ + int[] unzftab = new int[256]; + + int[][] limit = new int[BZip2Constants.GroupCount][]; + int[][] baseArray = new int[BZip2Constants.GroupCount][]; + int[][] perm = new int[BZip2Constants.GroupCount][]; + int[] minLens = new int[BZip2Constants.GroupCount]; + + Stream baseStream; + bool streamEnd; + + int currentChar = -1; + + int currentState = START_BLOCK_STATE; + + int storedBlockCRC, storedCombinedCRC; + int computedBlockCRC; + uint computedCombinedCRC; + + int count, chPrev, ch2; + int tPos; + int rNToGo; + int rTPos; + int i2, j2; + byte z; + bool isStreamOwner = true; + #endregion + } +} +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/VersionUpdate/ZIP/BZip2/BZip2OutputStream.cs b/类库/VersionUpdate/ZIP/BZip2/BZip2OutputStream.cs new file mode 100644 index 0000000..582f7a4 --- /dev/null +++ b/类库/VersionUpdate/ZIP/BZip2/BZip2OutputStream.cs @@ -0,0 +1,1916 @@ +// BZip2OutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.BZip2 +{ + + // TODO: Update to BZip2 1.0.1, 1.0.2 + + /// + /// An output stream that compresses into the BZip2 format + /// including file header chars into another stream. + /// + public class BZip2OutputStream : Stream + { + #region Constants + const int SETMASK = (1 << 21); + const int CLEARMASK = (~SETMASK); + const int GREATER_ICOST = 15; + const int LESSER_ICOST = 0; + const int SMALL_THRESH = 20; + const int DEPTH_THRESH = 10; + + /*-- + If you are ever unlucky/improbable enough + to get a stack overflow whilst sorting, + increase the following constant and try + again. In practice I have never seen the + stack go above 27 elems, so the following + limit seems very generous. + --*/ + const int QSORT_STACK_SIZE = 1000; + + /*-- + Knuth's increments seem to work better + than Incerpi-Sedgewick here. Possibly + because the number of elems to sort is + usually small, typically <= 20. + --*/ + readonly int[] increments = new int[] { + 1, 4, 13, 40, 121, 364, 1093, 3280, + 9841, 29524, 88573, 265720, + 797161, 2391484 + }; + #endregion + + #region Constructors + /// + /// Construct a default output stream with maximum block size + /// + /// The stream to write BZip data onto. + public BZip2OutputStream(Stream stream) : this(stream, 9) + { + } + + /// + /// Initialise a new instance of the + /// for the specified stream, using the given blocksize. + /// + /// The stream to write compressed data to. + /// The block size to use. + /// + /// Valid block sizes are in the range 1..9, with 1 giving + /// the lowest compression and 9 the highest. + /// + public BZip2OutputStream(Stream stream, int blockSize) + { + BsSetStream(stream); + + workFactor = 50; + if (blockSize > 9) { + blockSize = 9; + } + + if (blockSize < 1) { + blockSize = 1; + } + blockSize100k = blockSize; + AllocateCompressStructures(); + Initialize(); + InitBlock(); + } + #endregion + + #region Destructor + /// + /// Ensures that resources are freed and other cleanup operations + /// are performed when the garbage collector reclaims the BZip2OutputStream. + /// + ~BZip2OutputStream() + { + Dispose(false); + } + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + + #region Stream overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value indicating whether the current stream supports writing + /// + public override bool CanWrite { + get { + return baseStream.CanWrite; + } + } + + /// + /// Gets the length in bytes of the stream + /// + public override long Length { + get { + return baseStream.Length; + } + } + + /// + /// Gets or sets the current position of this stream. + /// + public override long Position { + get { + return baseStream.Position; + } + set { + throw new NotSupportedException("BZip2OutputStream position cannot be set"); + } + } + + /// + /// Sets the current position of this stream to the given value. + /// + /// The point relative to the offset from which to being seeking. + /// The reference point from which to begin seeking. + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("BZip2OutputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. + /// + /// The new stream length. + public override void SetLength(long value) + { + throw new NotSupportedException("BZip2OutputStream SetLength not supported"); + } + + /// + /// Read a byte from the stream advancing the position. + /// + /// The byte read cast to an int; -1 if end of stream. + public override int ReadByte() + { + throw new NotSupportedException("BZip2OutputStream ReadByte not supported"); + } + + /// + /// Read a block of bytes + /// + /// The buffer to read into. + /// The offset in the buffer to start storing data at. + /// The maximum number of bytes to read. + /// The total number of bytes read. This might be less than the number of bytes + /// requested if that number of bytes are not currently available, or zero + /// if the end of the stream is reached. + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("BZip2OutputStream Read not supported"); + } + + /// + /// Write a block of bytes to the stream + /// + /// The buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + public override void Write(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( count < 0 ) + { + throw new ArgumentOutOfRangeException("count"); + } + + if ( buffer.Length - offset < count ) + { + throw new ArgumentException("Offset/count out of range"); + } + + for (int i = 0; i < count; ++i) { + WriteByte(buffer[offset + i]); + } + } + + /// + /// Write a byte to the stream. + /// + /// The byte to write to the stream. + public override void WriteByte(byte value) + { + int b = (256 + value) % 256; + if (currentChar != -1) { + if (currentChar == b) { + runLength++; + if (runLength > 254) { + WriteRun(); + currentChar = -1; + runLength = 0; + } + } else { + WriteRun(); + runLength = 1; + currentChar = b; + } + } else { + currentChar = b; + runLength++; + } + } + + /// + /// End the current block and end compression. + /// Close the stream and free any resources + /// + public override void Close() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + void MakeMaps() + { + nInUse = 0; + for (int i = 0; i < 256; i++) { + if (inUse[i]) { + seqToUnseq[nInUse] = (char)i; + unseqToSeq[i] = (char)nInUse; + nInUse++; + } + } + } + + /// + /// Get the number of bytes written to output. + /// + void WriteRun() + { + if (last < allowableBlockSize) { + inUse[currentChar] = true; + for (int i = 0; i < runLength; i++) { + mCrc.Update(currentChar); + } + + switch (runLength) { + case 1: + last++; + block[last + 1] = (byte)currentChar; + break; + case 2: + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + break; + case 3: + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + break; + default: + inUse[runLength - 4] = true; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)currentChar; + last++; + block[last + 1] = (byte)(runLength - 4); + break; + } + } else { + EndBlock(); + InitBlock(); + WriteRun(); + } + } + + /// + /// Get the number of bytes written to the output. + /// + public int BytesWritten + { + get { return bytesOut; } + } + + /// + /// Releases the unmanaged resources used by the and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. +#if NET_1_0 || NET_1_1 || NETCF_1_0 + protected virtual void Dispose(bool disposing) +#else + override protected void Dispose(bool disposing) +#endif + { + try { +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + base.Dispose(disposing); +#endif + if( !disposed_ ) { + disposed_=true; + + if( runLength>0 ) { + WriteRun(); + } + + currentChar=-1; + EndBlock(); + EndCompression(); + Flush(); + } + } + finally { + if ( disposing ) { + if ( IsStreamOwner ) { + baseStream.Close(); + } + } + } + } + + /// + /// Flush output buffers + /// + public override void Flush() + { + baseStream.Flush(); + } + + void Initialize() + { + bytesOut = 0; + nBlocksRandomised = 0; + + /*--- Write header `magic' bytes indicating file-format == huffmanised, + followed by a digit indicating blockSize100k. + ---*/ + + BsPutUChar('B'); + BsPutUChar('Z'); + + BsPutUChar('h'); + BsPutUChar('0' + blockSize100k); + + combinedCRC = 0; + } + + void InitBlock() + { + mCrc.Reset(); + last = -1; + + for (int i = 0; i < 256; i++) { + inUse[i] = false; + } + + /*--- 20 is just a paranoia constant ---*/ + allowableBlockSize = BZip2Constants.BaseBlockSize * blockSize100k - 20; + } + + void EndBlock() + { + if (last < 0) { // dont do anything for empty files, (makes empty files compatible with original Bzip) + return; + } + + blockCRC = unchecked((uint)mCrc.Value); + combinedCRC = (combinedCRC << 1) | (combinedCRC >> 31); + combinedCRC ^= blockCRC; + + /*-- sort the block and establish position of original string --*/ + DoReversibleTransformation(); + + /*-- + A 6-byte block header, the value chosen arbitrarily + as 0x314159265359 :-). A 32 bit value does not really + give a strong enough guarantee that the value will not + appear by chance in the compressed datastream. Worst-case + probability of this event, for a 900k block, is about + 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits. + For a compressed file of size 100Gb -- about 100000 blocks -- + only a 48-bit marker will do. NB: normal compression/ + decompression do *not* rely on these statistical properties. + They are only important when trying to recover blocks from + damaged files. + --*/ + BsPutUChar(0x31); + BsPutUChar(0x41); + BsPutUChar(0x59); + BsPutUChar(0x26); + BsPutUChar(0x53); + BsPutUChar(0x59); + + /*-- Now the block's CRC, so it is in a known place. --*/ + unchecked { + BsPutint((int)blockCRC); + } + + /*-- Now a single bit indicating randomisation. --*/ + if (blockRandomised) { + BsW(1,1); + nBlocksRandomised++; + } else { + BsW(1,0); + } + + /*-- Finally, block's contents proper. --*/ + MoveToFrontCodeAndSend(); + } + + void EndCompression() + { + /*-- + Now another magic 48-bit number, 0x177245385090, to + indicate the end of the last block. (sqrt(pi), if + you want to know. I did want to use e, but it contains + too much repetition -- 27 18 28 18 28 46 -- for me + to feel statistically comfortable. Call me paranoid.) + --*/ + BsPutUChar(0x17); + BsPutUChar(0x72); + BsPutUChar(0x45); + BsPutUChar(0x38); + BsPutUChar(0x50); + BsPutUChar(0x90); + + unchecked { + BsPutint((int)combinedCRC); + } + + BsFinishedWithStream(); + } + + void BsSetStream(Stream stream) + { + baseStream = stream; + bsLive = 0; + bsBuff = 0; + bytesOut = 0; + } + + void BsFinishedWithStream() + { + while (bsLive > 0) + { + int ch = (bsBuff >> 24); + baseStream.WriteByte((byte)ch); // write 8-bit + bsBuff <<= 8; + bsLive -= 8; + bytesOut++; + } + } + + void BsW(int n, int v) + { + while (bsLive >= 8) { + int ch = (bsBuff >> 24); + unchecked{baseStream.WriteByte((byte)ch);} // write 8-bit + bsBuff <<= 8; + bsLive -= 8; + ++bytesOut; + } + bsBuff |= (v << (32 - bsLive - n)); + bsLive += n; + } + + void BsPutUChar(int c) + { + BsW(8, c); + } + + void BsPutint(int u) + { + BsW(8, (u >> 24) & 0xFF); + BsW(8, (u >> 16) & 0xFF); + BsW(8, (u >> 8) & 0xFF); + BsW(8, u & 0xFF); + } + + void BsPutIntVS(int numBits, int c) + { + BsW(numBits, c); + } + + void SendMTFValues() + { + char[][] len = new char[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + len[i] = new char[BZip2Constants.MaximumAlphaSize]; + } + + int gs, ge, totc, bt, bc, iter; + int nSelectors = 0, alphaSize, minLen, maxLen, selCtr; + int nGroups; + + alphaSize = nInUse + 2; + for (int t = 0; t < BZip2Constants.GroupCount; t++) { + for (int v = 0; v < alphaSize; v++) { + len[t][v] = (char)GREATER_ICOST; + } + } + + /*--- Decide how many coding tables to use ---*/ + if (nMTF <= 0) { + Panic(); + } + + if (nMTF < 200) { + nGroups = 2; + } else if (nMTF < 600) { + nGroups = 3; + } else if (nMTF < 1200) { + nGroups = 4; + } else if (nMTF < 2400) { + nGroups = 5; + } else { + nGroups = 6; + } + + /*--- Generate an initial set of coding tables ---*/ + int nPart = nGroups; + int remF = nMTF; + gs = 0; + while (nPart > 0) { + int tFreq = remF / nPart; + int aFreq = 0; + ge = gs - 1; + while (aFreq < tFreq && ge < alphaSize - 1) { + ge++; + aFreq += mtfFreq[ge]; + } + + if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups - nPart) % 2 == 1)) { + aFreq -= mtfFreq[ge]; + ge--; + } + + for (int v = 0; v < alphaSize; v++) { + if (v >= gs && v <= ge) { + len[nPart - 1][v] = (char)LESSER_ICOST; + } else { + len[nPart - 1][v] = (char)GREATER_ICOST; + } + } + + nPart--; + gs = ge + 1; + remF -= aFreq; + } + + int[][] rfreq = new int[BZip2Constants.GroupCount][]; + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + rfreq[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + int[] fave = new int[BZip2Constants.GroupCount]; + short[] cost = new short[BZip2Constants.GroupCount]; + /*--- + Iterate up to N_ITERS times to improve the tables. + ---*/ + for (iter = 0; iter < BZip2Constants.NumberOfIterations; ++iter) { + for (int t = 0; t < nGroups; ++t) { + fave[t] = 0; + } + + for (int t = 0; t < nGroups; ++t) { + for (int v = 0; v < alphaSize; ++v) { + rfreq[t][v] = 0; + } + } + + nSelectors = 0; + totc = 0; + gs = 0; + while (true) { + /*--- Set group start & end marks. --*/ + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.GroupSize - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + /*-- + Calculate the cost of this group as coded + by each of the coding tables. + --*/ + for (int t = 0; t < nGroups; t++) { + cost[t] = 0; + } + + if (nGroups == 6) { + short cost0, cost1, cost2, cost3, cost4, cost5; + cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0; + for (int i = gs; i <= ge; ++i) { + short icv = szptr[i]; + cost0 += (short)len[0][icv]; + cost1 += (short)len[1][icv]; + cost2 += (short)len[2][icv]; + cost3 += (short)len[3][icv]; + cost4 += (short)len[4][icv]; + cost5 += (short)len[5][icv]; + } + cost[0] = cost0; + cost[1] = cost1; + cost[2] = cost2; + cost[3] = cost3; + cost[4] = cost4; + cost[5] = cost5; + } else { + for (int i = gs; i <= ge; ++i) { + short icv = szptr[i]; + for (int t = 0; t < nGroups; t++) { + cost[t] += (short)len[t][icv]; + } + } + } + + /*-- + Find the coding table which is best for this group, + and record its identity in the selector table. + --*/ + bc = 999999999; + bt = -1; + for (int t = 0; t < nGroups; ++t) { + if (cost[t] < bc) { + bc = cost[t]; + bt = t; + } + } + totc += bc; + fave[bt]++; + selector[nSelectors] = (char)bt; + nSelectors++; + + /*-- + Increment the symbol frequencies for the selected table. + --*/ + for (int i = gs; i <= ge; ++i) { + ++rfreq[bt][szptr[i]]; + } + + gs = ge+1; + } + + /*-- + Recompute the tables based on the accumulated frequencies. + --*/ + for (int t = 0; t < nGroups; ++t) { + HbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20); + } + } + + rfreq = null; + fave = null; + cost = null; + + if (!(nGroups < 8)) { + Panic(); + } + + if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZip2Constants.GroupSize)))) { + Panic(); + } + + /*--- Compute MTF values for the selectors. ---*/ + char[] pos = new char[BZip2Constants.GroupCount]; + char ll_i, tmp2, tmp; + + for (int i = 0; i < nGroups; i++) { + pos[i] = (char)i; + } + + for (int i = 0; i < nSelectors; i++) { + ll_i = selector[i]; + int j = 0; + tmp = pos[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = pos[j]; + pos[j] = tmp2; + } + pos[0] = tmp; + selectorMtf[i] = (char)j; + } + + int[][] code = new int[BZip2Constants.GroupCount][]; + + for (int i = 0; i < BZip2Constants.GroupCount; ++i) { + code[i] = new int[BZip2Constants.MaximumAlphaSize]; + } + + /*--- Assign actual codes for the tables. --*/ + for (int t = 0; t < nGroups; t++) { + minLen = 32; + maxLen = 0; + for (int i = 0; i < alphaSize; i++) { + if (len[t][i] > maxLen) { + maxLen = len[t][i]; + } + if (len[t][i] < minLen) { + minLen = len[t][i]; + } + } + if (maxLen > 20) { + Panic(); + } + if (minLen < 1) { + Panic(); + } + HbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize); + } + + /*--- Transmit the mapping table. ---*/ + bool[] inUse16 = new bool[16]; + for (int i = 0; i < 16; ++i) { + inUse16[i] = false; + for (int j = 0; j < 16; ++j) { + if (inUse[i * 16 + j]) { + inUse16[i] = true; + } + } + } + + for (int i = 0; i < 16; ++i) { + if (inUse16[i]) { + BsW(1,1); + } else { + BsW(1,0); + } + } + + for (int i = 0; i < 16; ++i) { + if (inUse16[i]) { + for (int j = 0; j < 16; ++j) { + if (inUse[i * 16 + j]) { + BsW(1,1); + } else { + BsW(1,0); + } + } + } + } + + /*--- Now the selectors. ---*/ + BsW(3, nGroups); + BsW(15, nSelectors); + for (int i = 0; i < nSelectors; ++i) { + for (int j = 0; j < selectorMtf[i]; ++j) { + BsW(1,1); + } + BsW(1,0); + } + + /*--- Now the coding tables. ---*/ + for (int t = 0; t < nGroups; ++t) { + int curr = len[t][0]; + BsW(5, curr); + for (int i = 0; i < alphaSize; ++i) { + while (curr < len[t][i]) { + BsW(2, 2); + curr++; /* 10 */ + } + while (curr > len[t][i]) { + BsW(2, 3); + curr--; /* 11 */ + } + BsW (1, 0); + } + } + + /*--- And finally, the block data proper ---*/ + selCtr = 0; + gs = 0; + while (true) { + if (gs >= nMTF) { + break; + } + ge = gs + BZip2Constants.GroupSize - 1; + if (ge >= nMTF) { + ge = nMTF - 1; + } + + for (int i = gs; i <= ge; i++) { + BsW(len[selector[selCtr]][szptr[i]], code[selector[selCtr]][szptr[i]]); + } + + gs = ge + 1; + ++selCtr; + } + if (!(selCtr == nSelectors)) { + Panic(); + } + } + + void MoveToFrontCodeAndSend () + { + BsPutIntVS(24, origPtr); + GenerateMTFValues(); + SendMTFValues(); + } + + void SimpleSort(int lo, int hi, int d) + { + int i, j, h, bigN, hp; + int v; + + bigN = hi - lo + 1; + if (bigN < 2) { + return; + } + + hp = 0; + while (increments[hp] < bigN) { + hp++; + } + hp--; + + for (; hp >= 0; hp--) { + h = increments[hp]; + + i = lo + h; + while (true) { + /*-- copy 1 --*/ + if (i > hi) + break; + v = zptr[i]; + j = i; + while (FullGtU(zptr[j-h]+d, v+d)) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) + break; + } + zptr[j] = v; + i++; + + /*-- copy 2 --*/ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU ( zptr[j-h]+d, v+d )) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + /*-- copy 3 --*/ + if (i > hi) { + break; + } + v = zptr[i]; + j = i; + while (FullGtU ( zptr[j-h]+d, v+d)) { + zptr[j] = zptr[j-h]; + j = j - h; + if (j <= (lo + h - 1)) { + break; + } + } + zptr[j] = v; + i++; + + if (workDone > workLimit && firstAttempt) { + return; + } + } + } + } + + void Vswap(int p1, int p2, int n ) + { + int temp = 0; + while (n > 0) { + temp = zptr[p1]; + zptr[p1] = zptr[p2]; + zptr[p2] = temp; + p1++; + p2++; + n--; + } + } + + void QSort3(int loSt, int hiSt, int dSt) + { + int unLo, unHi, ltLo, gtHi, med, n, m; + int lo, hi, d; + + StackElement[] stack = new StackElement[QSORT_STACK_SIZE]; + + int sp = 0; + + stack[sp].ll = loSt; + stack[sp].hh = hiSt; + stack[sp].dd = dSt; + sp++; + + while (sp > 0) { + if (sp >= QSORT_STACK_SIZE) { + Panic(); + } + + sp--; + lo = stack[sp].ll; + hi = stack[sp].hh; + d = stack[sp].dd; + + if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) { + SimpleSort(lo, hi, d); + if (workDone > workLimit && firstAttempt) { + return; + } + continue; + } + + med = Med3(block[zptr[lo] + d + 1], + block[zptr[hi ] + d + 1], + block[zptr[(lo + hi) >> 1] + d + 1]); + + unLo = ltLo = lo; + unHi = gtHi = hi; + + while (true) { + while (true) { + if (unLo > unHi) { + break; + } + n = ((int)block[zptr[unLo]+d + 1]) - med; + if (n == 0) { + int temp = zptr[unLo]; + zptr[unLo] = zptr[ltLo]; + zptr[ltLo] = temp; + ltLo++; + unLo++; + continue; + } + if (n > 0) { + break; + } + unLo++; + } + + while (true) { + if (unLo > unHi) { + break; + } + n = ((int)block[zptr[unHi]+d + 1]) - med; + if (n == 0) { + int temp = zptr[unHi]; + zptr[unHi] = zptr[gtHi]; + zptr[gtHi] = temp; + gtHi--; + unHi--; + continue; + } + if (n < 0) { + break; + } + unHi--; + } + + if (unLo > unHi) { + break; + } + + { + int temp = zptr[unLo]; + zptr[unLo] = zptr[unHi]; + zptr[unHi] = temp; + unLo++; + unHi--; + } + } + + if (gtHi < ltLo) { + stack[sp].ll = lo; + stack[sp].hh = hi; + stack[sp].dd = d+1; + sp++; + continue; + } + + n = ((ltLo-lo) < (unLo-ltLo)) ? (ltLo-lo) : (unLo-ltLo); + Vswap(lo, unLo-n, n); + m = ((hi-gtHi) < (gtHi-unHi)) ? (hi-gtHi) : (gtHi-unHi); + Vswap(unLo, hi-m+1, m); + + n = lo + unLo - ltLo - 1; + m = hi - (gtHi - unHi) + 1; + + stack[sp].ll = lo; + stack[sp].hh = n; + stack[sp].dd = d; + sp++; + + stack[sp].ll = n + 1; + stack[sp].hh = m - 1; + stack[sp].dd = d+1; + sp++; + + stack[sp].ll = m; + stack[sp].hh = hi; + stack[sp].dd = d; + sp++; + } + } + + void MainSort() + { + int i, j, ss, sb; + int[] runningOrder = new int[256]; + int[] copy = new int[256]; + bool[] bigDone = new bool[256]; + int c1, c2; + int numQSorted; + + /*-- + In the various block-sized structures, live data runs + from 0 to last+NUM_OVERSHOOT_BYTES inclusive. First, + set up the overshoot area for block. + --*/ + + // if (verbosity >= 4) fprintf ( stderr, " sort initialise ...\n" ); + for (i = 0; i < BZip2Constants.OvershootBytes; i++) { + block[last + i + 2] = block[(i % (last + 1)) + 1]; + } + for (i = 0; i <= last + BZip2Constants.OvershootBytes; i++) { + quadrant[i] = 0; + } + + block[0] = (byte)(block[last + 1]); + + if (last < 4000) { + /*-- + Use simpleSort(), since the full sorting mechanism + has quite a large constant overhead. + --*/ + for (i = 0; i <= last; i++) { + zptr[i] = i; + } + firstAttempt = false; + workDone = workLimit = 0; + SimpleSort(0, last, 0); + } else { + numQSorted = 0; + for (i = 0; i <= 255; i++) { + bigDone[i] = false; + } + for (i = 0; i <= 65536; i++) { + ftab[i] = 0; + } + + c1 = block[0]; + for (i = 0; i <= last; i++) { + c2 = block[i + 1]; + ftab[(c1 << 8) + c2]++; + c1 = c2; + } + + for (i = 1; i <= 65536; i++) { + ftab[i] += ftab[i - 1]; + } + + c1 = block[1]; + for (i = 0; i < last; i++) { + c2 = block[i + 2]; + j = (c1 << 8) + c2; + c1 = c2; + ftab[j]--; + zptr[ftab[j]] = i; + } + + j = ((block[last + 1]) << 8) + (block[1]); + ftab[j]--; + zptr[ftab[j]] = last; + + /*-- + Now ftab contains the first loc of every small bucket. + Calculate the running order, from smallest to largest + big bucket. + --*/ + + for (i = 0; i <= 255; i++) { + runningOrder[i] = i; + } + + int vv; + int h = 1; + do { + h = 3 * h + 1; + } while (h <= 256); + do { + h = h / 3; + for (i = h; i <= 255; i++) { + vv = runningOrder[i]; + j = i; + while ((ftab[((runningOrder[j-h])+1) << 8] - ftab[(runningOrder[j-h]) << 8]) > (ftab[((vv)+1) << 8] - ftab[(vv) << 8])) { + runningOrder[j] = runningOrder[j-h]; + j = j - h; + if (j <= (h - 1)) { + break; + } + } + runningOrder[j] = vv; + } + } while (h != 1); + + /*-- + The main sorting loop. + --*/ + for (i = 0; i <= 255; i++) { + + /*-- + Process big buckets, starting with the least full. + --*/ + ss = runningOrder[i]; + + /*-- + Complete the big bucket [ss] by quicksorting + any unsorted small buckets [ss, j]. Hopefully + previous pointer-scanning phases have already + completed many of the small buckets [ss, j], so + we don't have to sort them at all. + --*/ + for (j = 0; j <= 255; j++) { + sb = (ss << 8) + j; + if(!((ftab[sb] & SETMASK) == SETMASK)) { + int lo = ftab[sb] & CLEARMASK; + int hi = (ftab[sb+1] & CLEARMASK) - 1; + if (hi > lo) { + QSort3(lo, hi, 2); + numQSorted += (hi - lo + 1); + if (workDone > workLimit && firstAttempt) { + return; + } + } + ftab[sb] |= SETMASK; + } + } + + /*-- + The ss big bucket is now done. Record this fact, + and update the quadrant descriptors. Remember to + update quadrants in the overshoot area too, if + necessary. The "if (i < 255)" test merely skips + this updating for the last bucket processed, since + updating for the last bucket is pointless. + --*/ + bigDone[ss] = true; + + if (i < 255) { + int bbStart = ftab[ss << 8] & CLEARMASK; + int bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart; + int shifts = 0; + + while ((bbSize >> shifts) > 65534) { + shifts++; + } + + for (j = 0; j < bbSize; j++) { + int a2update = zptr[bbStart + j]; + int qVal = (j >> shifts); + quadrant[a2update] = qVal; + if (a2update < BZip2Constants.OvershootBytes) { + quadrant[a2update + last + 1] = qVal; + } + } + + if (!(((bbSize-1) >> shifts) <= 65535)) { + Panic(); + } + } + + /*-- + Now scan this big bucket so as to synthesise the + sorted order for small buckets [t, ss] for all t != ss. + --*/ + for (j = 0; j <= 255; j++) { + copy[j] = ftab[(j << 8) + ss] & CLEARMASK; + } + + for (j = ftab[ss << 8] & CLEARMASK; j < (ftab[(ss+1) << 8] & CLEARMASK); j++) { + c1 = block[zptr[j]]; + if (!bigDone[c1]) { + zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1; + copy[c1] ++; + } + } + + for (j = 0; j <= 255; j++) { + ftab[(j << 8) + ss] |= SETMASK; + } + } + } + } + + void RandomiseBlock() + { + int i; + int rNToGo = 0; + int rTPos = 0; + for (i = 0; i < 256; i++) { + inUse[i] = false; + } + + for (i = 0; i <= last; i++) { + if (rNToGo == 0) { + rNToGo = (int)BZip2Constants.RandomNumbers[rTPos]; + rTPos++; + if (rTPos == 512) { + rTPos = 0; + } + } + rNToGo--; + block[i + 1] ^= (byte)((rNToGo == 1) ? 1 : 0); + // handle 16 bit signed numbers + block[i + 1] &= 0xFF; + + inUse[block[i + 1]] = true; + } + } + + void DoReversibleTransformation() + { + workLimit = workFactor * last; + workDone = 0; + blockRandomised = false; + firstAttempt = true; + + MainSort(); + + if (workDone > workLimit && firstAttempt) { + RandomiseBlock(); + workLimit = workDone = 0; + blockRandomised = true; + firstAttempt = false; + MainSort(); + } + + origPtr = -1; + for (int i = 0; i <= last; i++) { + if (zptr[i] == 0) { + origPtr = i; + break; + } + } + + if (origPtr == -1) { + Panic(); + } + } + + bool FullGtU(int i1, int i2) + { + int k; + byte c1, c2; + int s1, s2; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + i1++; + i2++; + + k = last + 1; + + do { + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + c1 = block[i1 + 1]; + c2 = block[i2 + 1]; + if (c1 != c2) { + return c1 > c2; + } + s1 = quadrant[i1]; + s2 = quadrant[i2]; + if (s1 != s2) { + return s1 > s2; + } + i1++; + i2++; + + if (i1 > last) { + i1 -= last; + i1--; + } + if (i2 > last) { + i2 -= last; + i2--; + } + + k -= 4; + ++workDone; + } while (k >= 0); + + return false; + } + + void AllocateCompressStructures() + { + int n = BZip2Constants.BaseBlockSize * blockSize100k; + block = new byte[(n + 1 + BZip2Constants.OvershootBytes)]; + quadrant = new int[(n + BZip2Constants.OvershootBytes)]; + zptr = new int[n]; + ftab = new int[65537]; + + if (block == null || quadrant == null || zptr == null || ftab == null) { + // int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537; + // compressOutOfMemory ( totalDraw, n ); + } + + /* + The back end needs a place to store the MTF values + whilst it calculates the coding tables. We could + put them in the zptr array. However, these values + will fit in a short, so we overlay szptr at the + start of zptr, in the hope of reducing the number + of cache misses induced by the multiple traversals + of the MTF values when calculating coding tables. + Seems to improve compression speed by about 1%. + */ + // szptr = zptr; + + + szptr = new short[2 * n]; + } + + void GenerateMTFValues() + { + char[] yy = new char[256]; + int i, j; + char tmp; + char tmp2; + int zPend; + int wr; + int EOB; + + MakeMaps(); + EOB = nInUse+1; + + for (i = 0; i <= EOB; i++) { + mtfFreq[i] = 0; + } + + wr = 0; + zPend = 0; + for (i = 0; i < nInUse; i++) { + yy[i] = (char) i; + } + + + for (i = 0; i <= last; i++) { + char ll_i; + + ll_i = unseqToSeq[block[zptr[i]]]; + + j = 0; + tmp = yy[j]; + while (ll_i != tmp) { + j++; + tmp2 = tmp; + tmp = yy[j]; + yy[j] = tmp2; + } + yy[0] = tmp; + + if (j == 0) { + zPend++; + } else { + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short)BZip2Constants.RunA; + wr++; + mtfFreq[BZip2Constants.RunA]++; + break; + case 1: + szptr[wr] = (short)BZip2Constants.RunB; + wr++; + mtfFreq[BZip2Constants.RunB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + zPend = 0; + } + szptr[wr] = (short)(j + 1); + wr++; + mtfFreq[j + 1]++; + } + } + + if (zPend > 0) { + zPend--; + while (true) { + switch (zPend % 2) { + case 0: + szptr[wr] = (short)BZip2Constants.RunA; + wr++; + mtfFreq[BZip2Constants.RunA]++; + break; + case 1: + szptr[wr] = (short)BZip2Constants.RunB; + wr++; + mtfFreq[BZip2Constants.RunB]++; + break; + } + if (zPend < 2) { + break; + } + zPend = (zPend - 2) / 2; + } + } + + szptr[wr] = (short)EOB; + wr++; + mtfFreq[EOB]++; + + nMTF = wr; + } + + static void Panic() + { + throw new BZip2Exception("BZip2 output stream panic"); + } + + static void HbMakeCodeLengths(char[] len, int[] freq, int alphaSize, int maxLen) + { + /*-- + Nodes and heap entries run from 1. Entry 0 + for both the heap and nodes is a sentinel. + --*/ + int nNodes, nHeap, n1, n2, j, k; + bool tooLong; + + int[] heap = new int[BZip2Constants.MaximumAlphaSize + 2]; + int[] weight = new int[BZip2Constants.MaximumAlphaSize * 2]; + int[] parent = new int[BZip2Constants.MaximumAlphaSize * 2]; + + for (int i = 0; i < alphaSize; ++i) + { + weight[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8; + } + + while (true) + { + nNodes = alphaSize; + nHeap = 0; + + heap[0] = 0; + weight[0] = 0; + parent[0] = -2; + + for (int i = 1; i <= alphaSize; ++i) + { + parent[i] = -1; + nHeap++; + heap[nHeap] = i; + int zz = nHeap; + int tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) + { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + if (!(nHeap < (BZip2Constants.MaximumAlphaSize+2))) + { + Panic(); + } + + while (nHeap > 1) + { + n1 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + int zz = 1; + int yy = 0; + int tmp = heap[zz]; + while (true) + { + yy = zz << 1; + if (yy > nHeap) + { + break; + } + if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) + { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) + { + break; + } + + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + n2 = heap[1]; + heap[1] = heap[nHeap]; + nHeap--; + + zz = 1; + yy = 0; + tmp = heap[zz]; + while (true) + { + yy = zz << 1; + if (yy > nHeap) + { + break; + } + if (yy < nHeap && weight[heap[yy+1]] < weight[heap[yy]]) + { + yy++; + } + if (weight[tmp] < weight[heap[yy]]) + { + break; + } + heap[zz] = heap[yy]; + zz = yy; + } + heap[zz] = tmp; + nNodes++; + parent[n1] = parent[n2] = nNodes; + + weight[nNodes] = (int)((weight[n1] & 0xffffff00) + (weight[n2] & 0xffffff00)) | + (int)(1 + (((weight[n1] & 0x000000ff) > (weight[n2] & 0x000000ff)) ? (weight[n1] & 0x000000ff) : (weight[n2] & 0x000000ff))); + + parent[nNodes] = -1; + nHeap++; + heap[nHeap] = nNodes; + + zz = nHeap; + tmp = heap[zz]; + while (weight[tmp] < weight[heap[zz >> 1]]) + { + heap[zz] = heap[zz >> 1]; + zz >>= 1; + } + heap[zz] = tmp; + } + if (!(nNodes < (BZip2Constants.MaximumAlphaSize * 2))) + { + Panic(); + } + + tooLong = false; + for (int i = 1; i <= alphaSize; ++i) + { + j = 0; + k = i; + while (parent[k] >= 0) + { + k = parent[k]; + j++; + } + len[i - 1] = (char)j; + if (j > maxLen) + { + tooLong = true; + } + } + + if (!tooLong) + { + break; + } + + for (int i = 1; i < alphaSize; ++i) + { + j = weight[i] >> 8; + j = 1 + (j / 2); + weight[i] = j << 8; + } + } + } + + static void HbAssignCodes (int[] code, char[] length, int minLen, int maxLen, int alphaSize) + { + int vec = 0; + for (int n = minLen; n <= maxLen; ++n) + { + for (int i = 0; i < alphaSize; ++i) + { + if (length[i] == n) + { + code[i] = vec; + ++vec; + } + } + vec <<= 1; + } + } + + static byte Med3(byte a, byte b, byte c ) + { + byte t; + if (a > b) + { + t = a; + a = b; + b = t; + } + if (b > c) + { + t = b; + b = c; + c = t; + } + if (a > b) + { + b = a; + } + return b; + } + + struct StackElement + { + public int ll; + public int hh; + public int dd; + } + + #region Instance Fields + bool isStreamOwner = true; + + /*-- + index of the last char in the block, so + the block size == last + 1. + --*/ + int last; + + /*-- + index in zptr[] of original string after sorting. + --*/ + int origPtr; + + /*-- + always: in the range 0 .. 9. + The current block size is 100000 * this number. + --*/ + int blockSize100k; + + bool blockRandomised; + + int bytesOut; + int bsBuff; + int bsLive; + IChecksum mCrc = new StrangeCRC(); + + bool[] inUse = new bool[256]; + int nInUse; + + char[] seqToUnseq = new char[256]; + char[] unseqToSeq = new char[256]; + + char[] selector = new char[BZip2Constants.MaximumSelectors]; + char[] selectorMtf = new char[BZip2Constants.MaximumSelectors]; + + byte[] block; + int[] quadrant; + int[] zptr; + short[] szptr; + int[] ftab; + + int nMTF; + + int[] mtfFreq = new int[BZip2Constants.MaximumAlphaSize]; + + /* + * Used when sorting. If too many long comparisons + * happen, we stop sorting, randomise the block + * slightly, and try again. + */ + int workFactor; + int workDone; + int workLimit; + bool firstAttempt; + int nBlocksRandomised; + + int currentChar = -1; + int runLength; + uint blockCRC, combinedCRC; + int allowableBlockSize; + Stream baseStream; + bool disposed_; + #endregion + } +} + +/* This file was derived from a file containing this license: + * + * This file is a part of bzip2 and/or libbzip2, a program and + * library for lossless, block-sorting data compression. + * + * Copyright (C) 1996-1998 Julian R Seward. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 3. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Java version ported by Keiron Liddle, Aftex Software 1999-2001 + */ diff --git a/类库/VersionUpdate/ZIP/Checksums/Adler32.cs b/类库/VersionUpdate/ZIP/Checksums/Adler32.cs new file mode 100644 index 0000000..6e358bc --- /dev/null +++ b/类库/VersionUpdate/ZIP/Checksums/Adler32.cs @@ -0,0 +1,237 @@ +// Adler32.cs - Computes Adler32 data checksum of a data stream +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Computes Adler32 checksum for a stream of data. An Adler32 + /// checksum is not as reliable as a CRC32 checksum, but a lot faster to + /// compute. + /// + /// The specification for Adler32 may be found in RFC 1950. + /// ZLIB Compressed Data Format Specification version 3.3) + /// + /// + /// From that document: + /// + /// "ADLER32 (Adler-32 checksum) + /// This contains a checksum value of the uncompressed data + /// (excluding any dictionary data) computed according to Adler-32 + /// algorithm. This algorithm is a 32-bit extension and improvement + /// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + /// standard. + /// + /// Adler-32 is composed of two sums accumulated per byte: s1 is + /// the sum of all bytes, s2 is the sum of all s1 values. Both sums + /// are done modulo 65521. s1 is initialized to 1, s2 to zero. The + /// Adler-32 checksum is stored as s2*65536 + s1 in most- + /// significant-byte first (network) order." + /// + /// "8.2. The Adler-32 algorithm + /// + /// The Adler-32 algorithm is much faster than the CRC32 algorithm yet + /// still provides an extremely low probability of undetected errors. + /// + /// The modulo on unsigned long accumulators can be delayed for 5552 + /// bytes, so the modulo operation time is negligible. If the bytes + /// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + /// and order sensitive, unlike the first sum, which is just a + /// checksum. That 65521 is prime is important to avoid a possible + /// large class of two-byte errors that leave the check unchanged. + /// (The Fletcher checksum uses 255, which is not prime and which also + /// makes the Fletcher check insensitive to single byte changes 0 - + /// 255.) + /// + /// The sum s1 is initialized to 1 instead of zero to make the length + /// of the sequence part of s2, so that the length does not have to be + /// checked separately. (Any sequence of zeroes has a Fletcher + /// checksum of zero.)" + /// + /// + /// + public sealed class Adler32 : IChecksum + { + /// + /// largest prime smaller than 65536 + /// + const uint BASE = 65521; + + /// + /// Returns the Adler32 data checksum computed so far. + /// + public long Value { + get { + return checksum; + } + } + + /// + /// Creates a new instance of the Adler32 class. + /// The checksum starts off with a value of 1. + /// + public Adler32() + { + Reset(); + } + + /// + /// Resets the Adler32 checksum to the initial value. + /// + public void Reset() + { + checksum = 1; + } + + /// + /// Updates the checksum with a byte value. + /// + /// + /// The data value to add. The high byte of the int is ignored. + /// + public void Update(int value) + { + // We could make a length 1 byte array and call update again, but I + // would rather not have that overhead + uint s1 = checksum & 0xFFFF; + uint s2 = checksum >> 16; + + s1 = (s1 + ((uint)value & 0xFF)) % BASE; + s2 = (s1 + s2) % BASE; + + checksum = (s2 << 16) + s1; + } + + /// + /// Updates the checksum with an array of bytes. + /// + /// + /// The source of the data to update with. + /// + public void Update(byte[] buffer) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Updates the checksum with the bytes taken from the array. + /// + /// + /// an array of bytes + /// + /// + /// the start of the data used for this update + /// + /// + /// the number of bytes to use for this update + /// + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if (offset < 0) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "cannot be negative"); +#endif + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "cannot be negative"); +#endif + } + + if (offset >= buffer.Length) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "not a valid index into buffer"); +#endif + } + + if (offset + count > buffer.Length) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "exceeds buffer size"); +#endif + } + + //(By Per Bothner) + uint s1 = checksum & 0xFFFF; + uint s2 = checksum >> 16; + + while (count > 0) { + // We can defer the modulo operation: + // s1 maximally grows from 65521 to 65521 + 255 * 3800 + // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 + int n = 3800; + if (n > count) { + n = count; + } + count -= n; + while (--n >= 0) { + s1 = s1 + (uint)(buffer[offset++] & 0xff); + s2 = s2 + s1; + } + s1 %= BASE; + s2 %= BASE; + } + + checksum = (s2 << 16) | s1; + } + + #region Instance Fields + uint checksum; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Checksums/CRC32.cs b/类库/VersionUpdate/ZIP/Checksums/CRC32.cs new file mode 100644 index 0000000..41d5b4b --- /dev/null +++ b/类库/VersionUpdate/ZIP/Checksums/CRC32.cs @@ -0,0 +1,223 @@ +// CRC32.cs - Computes CRC32 data checksum of a data stream +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + /// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + /// + /// Polynomials over GF(2) are represented in binary, one bit per coefficient, + /// with the lowest powers in the most significant bit. Then adding polynomials + /// is just exclusive-or, and multiplying a polynomial by x is a right shift by + /// one. If we call the above polynomial p, and represent a byte as the + /// polynomial q, also with the lowest power in the most significant bit (so the + /// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + /// where a mod b means the remainder after dividing a by b. + /// + /// This calculation is done using the shift-register method of multiplying and + /// taking the remainder. The register is initialized to zero, and for each + /// incoming bit, x^32 is added mod p to the register if the bit is a one (where + /// x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + /// x (which is shifting right by one and adding x^32 mod p if the bit shifted + /// out is a one). We start with the highest power (least significant bit) of + /// q and repeat for all eight bits of q. + /// + /// The table is simply the CRC of all possible eight bit values. This is all + /// the information needed to generate CRC's on data a byte at a time for all + /// combinations of CRC register values and incoming bytes. + /// + public sealed class Crc32 : IChecksum + { + const uint CrcSeed = 0xFFFFFFFF; + + readonly static uint[] CrcTable = new uint[] { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, + 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, + 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, + 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, + 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, + 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, + 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, + 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, + 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, + 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, + 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, + 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, + 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, + 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, + 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, + 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, + 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, + 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, + 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, + 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, + 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, + 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, + 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, + 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, + 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, + 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, + 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, + 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, + 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, + 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, + 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, + 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, + 0x2D02EF8D + }; + + internal static uint ComputeCrc32(uint oldCrc, byte value) + { + return (uint)(Crc32.CrcTable[(oldCrc ^ value) & 0xFF] ^ (oldCrc >> 8)); + } + + /// + /// The crc data checksum so far. + /// + uint crc; + + /// + /// Returns the CRC32 data checksum computed so far. + /// + public long Value { + get { + return (long)crc; + } + set { + crc = (uint)value; + } + } + + /// + /// Resets the CRC32 data checksum as if no update was ever called. + /// + public void Reset() + { + crc = 0; + } + + /// + /// Updates the checksum with the int bval. + /// + /// + /// the byte is taken as the lower 8 bits of value + /// + public void Update(int value) + { + crc ^= CrcSeed; + crc = CrcTable[(crc ^ value) & 0xFF] ^ (crc >> 8); + crc ^= CrcSeed; + } + + /// + /// Updates the checksum with the bytes taken from the array. + /// + /// + /// buffer an array of bytes + /// + public void Update(byte[] buffer) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Adds the byte array to the data checksum. + /// + /// + /// The buffer which contains the data + /// + /// + /// The offset in the buffer where the data starts + /// + /// + /// The number of data bytes to update the CRC with. + /// + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Count cannot be less than zero"); +#endif + } + + if (offset < 0 || offset + count > buffer.Length) { + throw new ArgumentOutOfRangeException("offset"); + } + + crc ^= CrcSeed; + + while (--count >= 0) { + crc = CrcTable[(crc ^ buffer[offset++]) & 0xFF] ^ (crc >> 8); + } + + crc ^= CrcSeed; + } + } +} diff --git a/类库/VersionUpdate/ZIP/Checksums/IChecksum.cs b/类库/VersionUpdate/ZIP/Checksums/IChecksum.cs new file mode 100644 index 0000000..e2679f9 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Checksums/IChecksum.cs @@ -0,0 +1,93 @@ +// IChecksum.cs - Interface to compute a data checksum +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Checksums +{ + + /// + /// Interface to compute a data checksum used by checked input/output streams. + /// A data checksum can be updated by one byte or with a byte array. After each + /// update the value of the current checksum can be returned by calling + /// getValue. The complete checksum object can also be reset + /// so it can be used again with new data. + /// + public interface IChecksum + { + /// + /// Returns the data checksum computed so far. + /// + long Value + { + get; + } + + /// + /// Resets the data checksum as if no update was ever called. + /// + void Reset(); + + /// + /// Adds one byte to the data checksum. + /// + /// + /// the data value to add. The high byte of the int is ignored. + /// + void Update(int value); + + /// + /// Updates the data checksum with the bytes taken from the array. + /// + /// + /// buffer an array of bytes + /// + void Update(byte[] buffer); + + /// + /// Adds the byte array to the data checksum. + /// + /// + /// The buffer which contains the data + /// + /// + /// The offset in the buffer where the data starts + /// + /// + /// the number of data bytes to add. + /// + void Update(byte[] buffer, int offset, int count); + } +} diff --git a/类库/VersionUpdate/ZIP/Checksums/StrangeCRC.cs b/类库/VersionUpdate/ZIP/Checksums/StrangeCRC.cs new file mode 100644 index 0000000..6ed7679 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Checksums/StrangeCRC.cs @@ -0,0 +1,208 @@ +// StrangeCRC.cs - computes a crc used in the bziplib +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Checksums +{ + /// + /// Bzip2 checksum algorithm + /// + public class StrangeCRC : IChecksum + { + readonly static uint[] crc32Table = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + }; + + int globalCrc; + + /// + /// Initialise a default instance of + /// + public StrangeCRC() + { + Reset(); + } + + /// + /// Reset the state of Crc. + /// + public void Reset() + { + globalCrc = -1; + } + + /// + /// Get the current Crc value. + /// + public long Value { + get { + return ~globalCrc; + } + } + + /// + /// Update the Crc value. + /// + /// data update is based on + public void Update(int value) + { + int temp = (globalCrc >> 24) ^ value; + if (temp < 0) { + temp = 256 + temp; + } + globalCrc = unchecked((int)((globalCrc << 8) ^ crc32Table[temp])); + } + + /// + /// Update Crc based on a block of data + /// + /// The buffer containing data to update the crc with. + public void Update(byte[] buffer) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + Update(buffer, 0, buffer.Length); + } + + /// + /// Update Crc based on a portion of a block of data + /// + /// block of data + /// index of first byte to use + /// number of bytes to use + public void Update(byte[] buffer, int offset, int count) + { + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "cannot be less than zero"); +#endif + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "cannot be less than zero"); +#endif + } + + if ( offset + count > buffer.Length ) + { + throw new ArgumentOutOfRangeException("count"); + } + + for (int i = 0; i < count; ++i) { + Update(buffer[offset++]); + } + } + } +} diff --git a/类库/VersionUpdate/ZIP/Core/FileSystemScanner.cs b/类库/VersionUpdate/ZIP/Core/FileSystemScanner.cs new file mode 100644 index 0000000..4077a45 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Core/FileSystemScanner.cs @@ -0,0 +1,533 @@ +// FileSystemScanner.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +using System; + +namespace ICSharpCode.SharpZipLib.Core +{ + #region EventArgs + /// + /// Event arguments for scanning. + /// + public class ScanEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file or directory name. + public ScanEventArgs(string name) + { + name_ = name; + } + #endregion + + /// + /// The file or directory name for this event. + /// + public string Name + { + get { return name_; } + } + + /// + /// Get set a value indicating if scanning should continue or not. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + #region Instance Fields + string name_; + bool continueRunning_ = true; + #endregion + } + + /// + /// Event arguments during processing of a single file or directory. + /// + public class ProgressEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file or directory name if known. + /// The number of bytes processed so far + /// The total number of bytes to process, 0 if not known + public ProgressEventArgs(string name, long processed, long target) + { + name_ = name; + processed_ = processed; + target_ = target; + } + #endregion + + /// + /// The name for this event if known. + /// + public string Name + { + get { return name_; } + } + + /// + /// Get set a value indicating wether scanning should continue or not. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + /// + /// Get a percentage representing how much of the has been processed + /// + /// 0.0 to 100.0 percent; 0 if target is not known. + public float PercentComplete + { + get + { + float result; + if (target_ <= 0) + { + result = 0; + } + else + { + result = ((float)processed_ / (float)target_) * 100.0f; + } + return result; + } + } + + /// + /// The number of bytes processed so far + /// + public long Processed + { + get { return processed_; } + } + + /// + /// The number of bytes to process. + /// + /// Target may be 0 or negative if the value isnt known. + public long Target + { + get { return target_; } + } + + #region Instance Fields + string name_; + long processed_; + long target_; + bool continueRunning_ = true; + #endregion + } + + /// + /// Event arguments for directories. + /// + public class DirectoryEventArgs : ScanEventArgs + { + #region Constructors + /// + /// Initialize an instance of . + /// + /// The name for this directory. + /// Flag value indicating if any matching files are contained in this directory. + public DirectoryEventArgs(string name, bool hasMatchingFiles) + : base (name) + { + hasMatchingFiles_ = hasMatchingFiles; + } + #endregion + + /// + /// Get a value indicating if the directory contains any matching files or not. + /// + public bool HasMatchingFiles + { + get { return hasMatchingFiles_; } + } + + #region Instance Fields + bool hasMatchingFiles_; + #endregion + } + + /// + /// Arguments passed when scan failures are detected. + /// + public class ScanFailureEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The name to apply. + /// The exception to use. + public ScanFailureEventArgs(string name, Exception e) + { + name_ = name; + exception_ = e; + continueRunning_ = true; + } + #endregion + + /// + /// The applicable name. + /// + public string Name + { + get { return name_; } + } + + /// + /// The applicable exception. + /// + public Exception Exception + { + get { return exception_; } + } + + /// + /// Get / set a value indicating wether scanning should continue. + /// + public bool ContinueRunning + { + get { return continueRunning_; } + set { continueRunning_ = value; } + } + + #region Instance Fields + string name_; + Exception exception_; + bool continueRunning_; + #endregion + } + + #endregion + + #region Delegates + /// + /// Delegate invoked before starting to process a directory. + /// + public delegate void ProcessDirectoryHandler(object sender, DirectoryEventArgs e); + + /// + /// Delegate invoked before starting to process a file. + /// + /// The source of the event + /// The event arguments. + public delegate void ProcessFileHandler(object sender, ScanEventArgs e); + + /// + /// Delegate invoked during processing of a file or directory + /// + /// The source of the event + /// The event arguments. + public delegate void ProgressHandler(object sender, ProgressEventArgs e); + + /// + /// Delegate invoked when a file has been completely processed. + /// + /// The source of the event + /// The event arguments. + public delegate void CompletedFileHandler(object sender, ScanEventArgs e); + + /// + /// Delegate invoked when a directory failure is detected. + /// + /// The source of the event + /// The event arguments. + public delegate void DirectoryFailureHandler(object sender, ScanFailureEventArgs e); + + /// + /// Delegate invoked when a file failure is detected. + /// + /// The source of the event + /// The event arguments. + public delegate void FileFailureHandler(object sender, ScanFailureEventArgs e); + #endregion + + /// + /// FileSystemScanner provides facilities scanning of files and directories. + /// + public class FileSystemScanner + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The file filter to apply when scanning. + public FileSystemScanner(string filter) + { + fileFilter_ = new PathFilter(filter); + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + /// The directory filter to apply. + public FileSystemScanner(string fileFilter, string directoryFilter) + { + fileFilter_ = new PathFilter(fileFilter); + directoryFilter_ = new PathFilter(directoryFilter); + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + public FileSystemScanner(IScanFilter fileFilter) + { + fileFilter_ = fileFilter; + } + + /// + /// Initialise a new instance of + /// + /// The file filter to apply. + /// The directory filter to apply. + public FileSystemScanner(IScanFilter fileFilter, IScanFilter directoryFilter) + { + fileFilter_ = fileFilter; + directoryFilter_ = directoryFilter; + } + #endregion + + #region Delegates + /// + /// Delegate to invoke when a directory is processed. + /// + public ProcessDirectoryHandler ProcessDirectory; + + /// + /// Delegate to invoke when a file is processed. + /// + public ProcessFileHandler ProcessFile; + + /// + /// Delegate to invoke when processing for a file has finished. + /// + public CompletedFileHandler CompletedFile; + + /// + /// Delegate to invoke when a directory failure is detected. + /// + public DirectoryFailureHandler DirectoryFailure; + + /// + /// Delegate to invoke when a file failure is detected. + /// + public FileFailureHandler FileFailure; + #endregion + + /// + /// Raise the DirectoryFailure event. + /// + /// The directory name. + /// The exception detected. + bool OnDirectoryFailure(string directory, Exception e) + { + DirectoryFailureHandler handler = DirectoryFailure; + bool result = (handler != null); + if ( result ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e); + handler(this, args); + alive_ = args.ContinueRunning; + } + return result; + } + + /// + /// Raise the FileFailure event. + /// + /// The file name. + /// The exception detected. + bool OnFileFailure(string file, Exception e) + { + FileFailureHandler handler = FileFailure; + + bool result = (handler != null); + + if ( result ){ + ScanFailureEventArgs args = new ScanFailureEventArgs(file, e); + FileFailure(this, args); + alive_ = args.ContinueRunning; + } + return result; + } + + /// + /// Raise the ProcessFile event. + /// + /// The file name. + void OnProcessFile(string file) + { + ProcessFileHandler handler = ProcessFile; + + if ( handler!= null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Raise the complete file event + /// + /// The file name + void OnCompleteFile(string file) + { + CompletedFileHandler handler = CompletedFile; + + if (handler != null) + { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Raise the ProcessDirectory event. + /// + /// The directory name. + /// Flag indicating if the directory has matching files. + void OnProcessDirectory(string directory, bool hasMatchingFiles) + { + ProcessDirectoryHandler handler = ProcessDirectory; + + if ( handler != null ) { + DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles); + handler(this, args); + alive_ = args.ContinueRunning; + } + } + + /// + /// Scan a directory. + /// + /// The base directory to scan. + /// True to recurse subdirectories, false to scan a single directory. + public void Scan(string directory, bool recurse) + { + alive_ = true; + ScanDir(directory, recurse); + } + + void ScanDir(string directory, bool recurse) + { + + try { + string[] names = System.IO.Directory.GetFiles(directory); + bool hasMatch = false; + for (int fileIndex = 0; fileIndex < names.Length; ++fileIndex) { + if ( !fileFilter_.IsMatch(names[fileIndex]) ) { + names[fileIndex] = null; + } else { + hasMatch = true; + } + } + + OnProcessDirectory(directory, hasMatch); + + if ( alive_ && hasMatch ) { + foreach (string fileName in names) { + try { + if ( fileName != null ) { + OnProcessFile(fileName); + if ( !alive_ ) { + break; + } + } + } + catch (Exception e) { + if (!OnFileFailure(fileName, e)) { + throw; + } + } + } + } + } + catch (Exception e) { + if (!OnDirectoryFailure(directory, e)) { + throw; + } + } + + if ( alive_ && recurse ) { + try { + string[] names = System.IO.Directory.GetDirectories(directory); + foreach (string fulldir in names) { + if ((directoryFilter_ == null) || (directoryFilter_.IsMatch(fulldir))) { + ScanDir(fulldir, true); + if ( !alive_ ) { + break; + } + } + } + } + catch (Exception e) { + if (!OnDirectoryFailure(directory, e)) { + throw; + } + } + } + } + + #region Instance Fields + /// + /// The file filter currently in use. + /// + IScanFilter fileFilter_; + /// + /// The directory filter currently in use. + /// + IScanFilter directoryFilter_; + /// + /// Flag indicating if scanning should continue running. + /// + bool alive_; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Core/INameTransform.cs b/类库/VersionUpdate/ZIP/Core/INameTransform.cs new file mode 100644 index 0000000..88c934f --- /dev/null +++ b/类库/VersionUpdate/ZIP/Core/INameTransform.cs @@ -0,0 +1,57 @@ +// INameTransform.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// INameTransform defines how file system names are transformed for use with archives, or vice versa. + /// + public interface INameTransform + { + /// + /// Given a file name determine the transformed value. + /// + /// The name to transform. + /// The transformed file name. + string TransformFile(string name); + + /// + /// Given a directory name determine the transformed value. + /// + /// The name to transform. + /// The transformed directory name + string TransformDirectory(string name); + } +} diff --git a/类库/VersionUpdate/ZIP/Core/IScanFilter.cs b/类库/VersionUpdate/ZIP/Core/IScanFilter.cs new file mode 100644 index 0000000..64c99a8 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Core/IScanFilter.cs @@ -0,0 +1,50 @@ +// IScanFilter.cs +// +// Copyright 2006 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// Scanning filters support filtering of names. + /// + public interface IScanFilter + { + /// + /// Test a name to see if it 'matches' the filter. + /// + /// The name to test. + /// Returns true if the name matches the filter, false if it does not match. + bool IsMatch(string name); + } +} diff --git a/类库/VersionUpdate/ZIP/Core/NameFilter.cs b/类库/VersionUpdate/ZIP/Core/NameFilter.cs new file mode 100644 index 0000000..eea8fbe --- /dev/null +++ b/类库/VersionUpdate/ZIP/Core/NameFilter.cs @@ -0,0 +1,290 @@ +// NameFilter.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2010-03-03 Z-1654 Fixed bug where escape characters were excluded in SplitQuoted() + +using System; +using System.Collections; +using System.Text; +using System.Text.RegularExpressions; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// NameFilter is a string matching class which allows for both positive and negative + /// matching. + /// A filter is a sequence of independant regular expressions separated by semi-colons ';'. + /// To include a semi-colon it may be quoted as in \;. Each expression can be prefixed by a plus '+' sign or + /// a minus '-' sign to denote the expression is intended to include or exclude names. + /// If neither a plus or minus sign is found include is the default. + /// A given name is tested for inclusion before checking exclusions. Only names matching an include spec + /// and not matching an exclude spec are deemed to match the filter. + /// An empty filter matches any name. + /// + /// The following expression includes all name ending in '.dat' with the exception of 'dummy.dat' + /// "+\.dat$;-^dummy\.dat$" + /// + public class NameFilter : IScanFilter + { + #region Constructors + /// + /// Construct an instance based on the filter expression passed + /// + /// The filter expression. + public NameFilter(string filter) + { + filter_ = filter; + inclusions_ = new ArrayList(); + exclusions_ = new ArrayList(); + Compile(); + } + #endregion + + /// + /// Test a string to see if it is a valid regular expression. + /// + /// The expression to test. + /// True if expression is a valid false otherwise. + public static bool IsValidExpression(string expression) + { + bool result = true; + try { + Regex exp = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + catch (ArgumentException) { + result = false; + } + return result; + } + + /// + /// Test an expression to see if it is valid as a filter. + /// + /// The filter expression to test. + /// True if the expression is valid, false otherwise. + public static bool IsValidFilterExpression(string toTest) + { + if ( toTest == null ) { + throw new ArgumentNullException("toTest"); + } + + bool result = true; + + try { + string[] items = SplitQuoted(toTest); + for (int i = 0; i < items.Length; ++i) { + if ((items[i] != null) && (items[i].Length > 0)) { + string toCompile; + + if (items[i][0] == '+') { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else if (items[i][0] == '-') { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else { + toCompile = items[i]; + } + + Regex testRegex = new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Singleline); + } + } + } + catch (ArgumentException) { + result = false; + } + + return result; + } + + /// + /// Split a string into its component pieces + /// + /// The original string + /// Returns an array of values containing the individual filter elements. + public static string[] SplitQuoted(string original) + { + char escape = '\\'; + char[] separators = { ';' }; + + ArrayList result = new ArrayList(); + + if ((original != null) && (original.Length > 0)) { + int endIndex = -1; + StringBuilder b = new StringBuilder(); + + while (endIndex < original.Length) { + endIndex += 1; + if (endIndex >= original.Length) { + result.Add(b.ToString()); + } + else if (original[endIndex] == escape) { + endIndex += 1; + if (endIndex >= original.Length) { +#if NETCF_1_0 + throw new ArgumentException("Missing terminating escape character"); +#else + throw new ArgumentException("Missing terminating escape character", "original"); +#endif + } + // include escape if this is not an escaped separator + if (Array.IndexOf(separators, original[endIndex]) < 0) + b.Append(escape); + + b.Append(original[endIndex]); + } + else { + if (Array.IndexOf(separators, original[endIndex]) >= 0) { + result.Add(b.ToString()); + b.Length = 0; + } + else { + b.Append(original[endIndex]); + } + } + } + } + + return (string[])result.ToArray(typeof(string)); + } + + /// + /// Convert this filter to its string equivalent. + /// + /// The string equivalent for this filter. + public override string ToString() + { + return filter_; + } + + /// + /// Test a value to see if it is included by the filter. + /// + /// The value to test. + /// True if the value is included, false otherwise. + public bool IsIncluded(string name) + { + bool result = false; + if ( inclusions_.Count == 0 ) { + result = true; + } + else { + foreach ( Regex r in inclusions_ ) { + if ( r.IsMatch(name) ) { + result = true; + break; + } + } + } + return result; + } + + /// + /// Test a value to see if it is excluded by the filter. + /// + /// The value to test. + /// True if the value is excluded, false otherwise. + public bool IsExcluded(string name) + { + bool result = false; + foreach ( Regex r in exclusions_ ) { + if ( r.IsMatch(name) ) { + result = true; + break; + } + } + return result; + } + + #region IScanFilter Members + /// + /// Test a value to see if it matches the filter. + /// + /// The value to test. + /// True if the value matches, false otherwise. + public bool IsMatch(string name) + { + return (IsIncluded(name) && !IsExcluded(name)); + } + #endregion + + /// + /// Compile this filter. + /// + void Compile() + { + // TODO: Check to see if combining RE's makes it faster/smaller. + // simple scheme would be to have one RE for inclusion and one for exclusion. + if ( filter_ == null ) { + return; + } + + string[] items = SplitQuoted(filter_); + for ( int i = 0; i < items.Length; ++i ) { + if ( (items[i] != null) && (items[i].Length > 0) ) { + bool include = (items[i][0] != '-'); + string toCompile; + + if ( items[i][0] == '+' ) { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else if ( items[i][0] == '-' ) { + toCompile = items[i].Substring(1, items[i].Length - 1); + } + else { + toCompile = items[i]; + } + + // NOTE: Regular expressions can fail to compile here for a number of reasons that cause an exception + // these are left unhandled here as the caller is responsible for ensuring all is valid. + // several functions IsValidFilterExpression and IsValidExpression are provided for such checking + if ( include ) { + inclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)); + } + else { + exclusions_.Add(new Regex(toCompile, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)); + } + } + } + } + + #region Instance Fields + string filter_; + ArrayList inclusions_; + ArrayList exclusions_; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Core/PathFilter.cs b/类库/VersionUpdate/ZIP/Core/PathFilter.cs new file mode 100644 index 0000000..03b8ff3 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Core/PathFilter.cs @@ -0,0 +1,334 @@ +// PathFilter.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// PathFilter filters directories and files using a form of regular expressions + /// by full path name. + /// See NameFilter for more detail on filtering. + /// + public class PathFilter : IScanFilter + { + #region Constructors + /// + /// Initialise a new instance of . + /// + /// The filter expression to apply. + public PathFilter(string filter) + { + nameFilter_ = new NameFilter(filter); + } + #endregion + + #region IScanFilter Members + /// + /// Test a name to see if it matches the filter. + /// + /// The name to test. + /// True if the name matches, false otherwise. + /// is used to get the full path before matching. + public virtual bool IsMatch(string name) + { + bool result = false; + + if ( name != null ) { + string cooked = (name.Length > 0) ? Path.GetFullPath(name) : ""; + result = nameFilter_.IsMatch(cooked); + } + return result; + } + #endregion + + #region Instance Fields + NameFilter nameFilter_; + #endregion + } + + /// + /// ExtendedPathFilter filters based on name, file size, and the last write time of the file. + /// + /// Provides an example of how to customise filtering. + public class ExtendedPathFilter : PathFilter + { + #region Constructors + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + public ExtendedPathFilter(string filter, + long minSize, long maxSize) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + } + + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum to include. + /// The maximum to include. + public ExtendedPathFilter(string filter, + DateTime minDate, DateTime maxDate) + : base(filter) + { + MinDate = minDate; + MaxDate = maxDate; + } + + /// + /// Initialise a new instance of ExtendedPathFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + /// The minimum to include. + /// The maximum to include. + public ExtendedPathFilter(string filter, + long minSize, long maxSize, + DateTime minDate, DateTime maxDate) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + MinDate = minDate; + MaxDate = maxDate; + } + #endregion + + #region IScanFilter Members + /// + /// Test a filename to see if it matches the filter. + /// + /// The filename to test. + /// True if the filter matches, false otherwise. + /// The doesnt exist + public override bool IsMatch(string name) + { + bool result = base.IsMatch(name); + + if ( result ) { + FileInfo fileInfo = new FileInfo(name); + result = + (MinSize <= fileInfo.Length) && + (MaxSize >= fileInfo.Length) && + (MinDate <= fileInfo.LastWriteTime) && + (MaxDate >= fileInfo.LastWriteTime) + ; + } + return result; + } + #endregion + + #region Properties + /// + /// Get/set the minimum size/length for a file that will match this filter. + /// + /// The default value is zero. + /// value is less than zero; greater than + public long MinSize + { + get { return minSize_; } + set + { + if ( (value < 0) || (maxSize_ < value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + minSize_ = value; + } + } + + /// + /// Get/set the maximum size/length for a file that will match this filter. + /// + /// The default value is + /// value is less than zero or less than + public long MaxSize + { + get { return maxSize_; } + set + { + if ( (value < 0) || (minSize_ > value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + maxSize_ = value; + } + } + + /// + /// Get/set the minimum value that will match for this filter. + /// + /// Files with a LastWrite time less than this value are excluded by the filter. + public DateTime MinDate + { + get + { + return minDate_; + } + + set + { + if ( value > maxDate_ ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Exceeds MaxDate"); +#endif + } + + minDate_ = value; + } + } + + /// + /// Get/set the maximum value that will match for this filter. + /// + /// Files with a LastWrite time greater than this value are excluded by the filter. + public DateTime MaxDate + { + get + { + return maxDate_; + } + + set + { + if ( minDate_ > value ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Exceeds MinDate"); +#endif + } + + maxDate_ = value; + } + } + #endregion + + #region Instance Fields + long minSize_; + long maxSize_ = long.MaxValue; + DateTime minDate_ = DateTime.MinValue; + DateTime maxDate_ = DateTime.MaxValue; + #endregion + } + + /// + /// NameAndSizeFilter filters based on name and file size. + /// + /// A sample showing how filters might be extended. + [Obsolete("Use ExtendedPathFilter instead")] + public class NameAndSizeFilter : PathFilter + { + + /// + /// Initialise a new instance of NameAndSizeFilter. + /// + /// The filter to apply. + /// The minimum file size to include. + /// The maximum file size to include. + public NameAndSizeFilter(string filter, long minSize, long maxSize) + : base(filter) + { + MinSize = minSize; + MaxSize = maxSize; + } + + /// + /// Test a filename to see if it matches the filter. + /// + /// The filename to test. + /// True if the filter matches, false otherwise. + public override bool IsMatch(string name) + { + bool result = base.IsMatch(name); + + if ( result ) { + FileInfo fileInfo = new FileInfo(name); + long length = fileInfo.Length; + result = + (MinSize <= length) && + (MaxSize >= length); + } + return result; + } + + /// + /// Get/set the minimum size for a file that will match this filter. + /// + public long MinSize + { + get { return minSize_; } + set { + if ( (value < 0) || (maxSize_ < value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + minSize_ = value; + } + } + + /// + /// Get/set the maximum size for a file that will match this filter. + /// + public long MaxSize + { + get { return maxSize_; } + set + { + if ( (value < 0) || (minSize_ > value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + maxSize_ = value; + } + } + + #region Instance Fields + long minSize_; + long maxSize_ = long.MaxValue; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Core/StreamUtils.cs b/类库/VersionUpdate/ZIP/Core/StreamUtils.cs new file mode 100644 index 0000000..7abdce8 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Core/StreamUtils.cs @@ -0,0 +1,246 @@ +// StreamUtils.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// Provides simple " utilities. + /// + public sealed class StreamUtils + { + /// + /// Read from a ensuring all the required data is read. + /// + /// The stream to read. + /// The buffer to fill. + /// + static public void ReadFully(Stream stream, byte[] buffer) + { + ReadFully(stream, buffer, 0, buffer.Length); + } + + /// + /// Read from a " ensuring all the required data is read. + /// + /// The stream to read data from. + /// The buffer to store data in. + /// The offset at which to begin storing data. + /// The number of bytes of data to store. + /// Required parameter is null + /// and or are invalid. + /// End of stream is encountered before all the data has been read. + static public void ReadFully(Stream stream, byte[] buffer, int offset, int count) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + // Offset can equal length when buffer and count are 0. + if ( (offset < 0) || (offset > buffer.Length) ) { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( (count < 0) || (offset + count > buffer.Length) ) { + throw new ArgumentOutOfRangeException("count"); + } + + while ( count > 0 ) { + int readCount = stream.Read(buffer, offset, count); + if ( readCount <= 0 ) { + throw new EndOfStreamException(); + } + offset += readCount; + count -= readCount; + } + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + static public void Copy(Stream source, Stream destination, byte[] buffer) + { + if (source == null) { + throw new ArgumentNullException("source"); + } + + if (destination == null) { + throw new ArgumentNullException("destination"); + } + + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + // Ensure a reasonable size of buffer is used without being prohibitive. + if (buffer.Length < 128) { + throw new ArgumentException("Buffer is too small", "buffer"); + } + + bool copying = true; + + while (copying) { + int bytesRead = source.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) { + destination.Write(buffer, 0, bytesRead); + } + else { + destination.Flush(); + copying = false; + } + } + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + /// The progress handler delegate to use. + /// The minimum between progress updates. + /// The source for this event. + /// The name to use with the event. + /// This form is specialised for use within #Zip to support events during archive operations. + static public void Copy(Stream source, Stream destination, + byte[] buffer, ProgressHandler progressHandler, TimeSpan updateInterval, object sender, string name) + { + Copy(source, destination, buffer, progressHandler, updateInterval, sender, name, -1); + } + + /// + /// Copy the contents of one to another. + /// + /// The stream to source data from. + /// The stream to write data to. + /// The buffer to use during copying. + /// The progress handler delegate to use. + /// The minimum between progress updates. + /// The source for this event. + /// The name to use with the event. + /// A predetermined fixed target value to use with progress updates. + /// If the value is negative the target is calculated by looking at the stream. + /// This form is specialised for use within #Zip to support events during archive operations. + static public void Copy(Stream source, Stream destination, + byte[] buffer, + ProgressHandler progressHandler, TimeSpan updateInterval, + object sender, string name, long fixedTarget) + { + if (source == null) { + throw new ArgumentNullException("source"); + } + + if (destination == null) { + throw new ArgumentNullException("destination"); + } + + if (buffer == null) { + throw new ArgumentNullException("buffer"); + } + + // Ensure a reasonable size of buffer is used without being prohibitive. + if (buffer.Length < 128) { + throw new ArgumentException("Buffer is too small", "buffer"); + } + + if (progressHandler == null) { + throw new ArgumentNullException("progressHandler"); + } + + bool copying = true; + + DateTime marker = DateTime.Now; + long processed = 0; + long target = 0; + + if (fixedTarget >= 0) { + target = fixedTarget; + } + else if (source.CanSeek) { + target = source.Length - source.Position; + } + + // Always fire 0% progress.. + ProgressEventArgs args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + + bool progressFired = true; + + while (copying) { + int bytesRead = source.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) { + processed += bytesRead; + progressFired = false; + destination.Write(buffer, 0, bytesRead); + } + else { + destination.Flush(); + copying = false; + } + + if (DateTime.Now - marker > updateInterval) { + progressFired = true; + marker = DateTime.Now; + args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + + copying = args.ContinueRunning; + } + } + + if (!progressFired) { + args = new ProgressEventArgs(name, processed, target); + progressHandler(sender, args); + } + } + + /// + /// Initialise an instance of + /// + private StreamUtils() + { + // Do nothing. + } + } +} diff --git a/类库/VersionUpdate/ZIP/Core/WindowsPathUtils.cs b/类库/VersionUpdate/ZIP/Core/WindowsPathUtils.cs new file mode 100644 index 0000000..2091945 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Core/WindowsPathUtils.cs @@ -0,0 +1,94 @@ +// WindowsPathUtils.cs +// +// Copyright 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Core +{ + /// + /// WindowsPathUtils provides simple utilities for handling windows paths. + /// + public abstract class WindowsPathUtils + { + /// + /// Initializes a new instance of the class. + /// + internal WindowsPathUtils() + { + } + + /// + /// Remove any path root present in the path + /// + /// A containing path information. + /// The path with the root removed if it was present; path otherwise. + /// Unlike the class the path isnt otherwise checked for validity. + public static string DropPathRoot(string path) + { + string result = path; + + if ( (path != null) && (path.Length > 0) ) { + if ((path[0] == '\\') || (path[0] == '/')) { + // UNC name ? + if ((path.Length > 1) && ((path[1] == '\\') || (path[1] == '/'))) { + int index = 2; + int elements = 2; + + // Scan for two separate elements \\machine\share\restofpath + while ((index <= path.Length) && + (((path[index] != '\\') && (path[index] != '/')) || (--elements > 0))) { + index++; + } + + index++; + + if (index < path.Length) { + result = path.Substring(index); + } + else { + result = ""; + } + } + } + else if ((path.Length > 1) && (path[1] == ':')) { + int dropCount = 2; + if ((path.Length > 2) && ((path[2] == '\\') || (path[2] == '/'))) { + dropCount = 3; + } + result = result.Remove(0, dropCount); + } + } + return result; + } + } +} diff --git a/类库/VersionUpdate/ZIP/Encryption/PkzipClassic.cs b/类库/VersionUpdate/ZIP/Encryption/PkzipClassic.cs new file mode 100644 index 0000000..7bed67a --- /dev/null +++ b/类库/VersionUpdate/ZIP/Encryption/PkzipClassic.cs @@ -0,0 +1,498 @@ +// +// PkzipClassic encryption +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + + +#if !NETCF_1_0 + +using System; +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.Encryption +{ + /// + /// PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives. + /// While it has been superceded by more recent and more powerful algorithms, its still in use and + /// is viable for preventing casual snooping + /// + public abstract class PkzipClassic : SymmetricAlgorithm + { + /// + /// Generates new encryption keys based on given seed + /// + /// The seed value to initialise keys with. + /// A new key value. + static public byte[] GenerateKeys(byte[] seed) + { + if ( seed == null ) { + throw new ArgumentNullException("seed"); + } + + if ( seed.Length == 0 ) { + throw new ArgumentException("Length is zero", "seed"); + } + + uint[] newKeys = new uint[] { + 0x12345678, + 0x23456789, + 0x34567890 + }; + + for (int i = 0; i < seed.Length; ++i) { + newKeys[0] = Crc32.ComputeCrc32(newKeys[0], seed[i]); + newKeys[1] = newKeys[1] + (byte)newKeys[0]; + newKeys[1] = newKeys[1] * 134775813 + 1; + newKeys[2] = Crc32.ComputeCrc32(newKeys[2], (byte)(newKeys[1] >> 24)); + } + + byte[] result = new byte[12]; + result[0] = (byte)(newKeys[0] & 0xff); + result[1] = (byte)((newKeys[0] >> 8) & 0xff); + result[2] = (byte)((newKeys[0] >> 16) & 0xff); + result[3] = (byte)((newKeys[0] >> 24) & 0xff); + result[4] = (byte)(newKeys[1] & 0xff); + result[5] = (byte)((newKeys[1] >> 8) & 0xff); + result[6] = (byte)((newKeys[1] >> 16) & 0xff); + result[7] = (byte)((newKeys[1] >> 24) & 0xff); + result[8] = (byte)(newKeys[2] & 0xff); + result[9] = (byte)((newKeys[2] >> 8) & 0xff); + result[10] = (byte)((newKeys[2] >> 16) & 0xff); + result[11] = (byte)((newKeys[2] >> 24) & 0xff); + return result; + } + } + + /// + /// PkzipClassicCryptoBase provides the low level facilities for encryption + /// and decryption using the PkzipClassic algorithm. + /// + class PkzipClassicCryptoBase + { + /// + /// Transform a single byte + /// + /// + /// The transformed value + /// + protected byte TransformByte() + { + uint temp = ((keys[2] & 0xFFFF) | 2); + return (byte)((temp * (temp ^ 1)) >> 8); + } + + /// + /// Set the key schedule for encryption/decryption. + /// + /// The data use to set the keys from. + protected void SetKeys(byte[] keyData) + { + if ( keyData == null ) { + throw new ArgumentNullException("keyData"); + } + + if ( keyData.Length != 12 ) { + throw new InvalidOperationException("Key length is not valid"); + } + + keys = new uint[3]; + keys[0] = (uint)((keyData[3] << 24) | (keyData[2] << 16) | (keyData[1] << 8) | keyData[0]); + keys[1] = (uint)((keyData[7] << 24) | (keyData[6] << 16) | (keyData[5] << 8) | keyData[4]); + keys[2] = (uint)((keyData[11] << 24) | (keyData[10] << 16) | (keyData[9] << 8) | keyData[8]); + } + + /// + /// Update encryption keys + /// + protected void UpdateKeys(byte ch) + { + keys[0] = Crc32.ComputeCrc32(keys[0], ch); + keys[1] = keys[1] + (byte)keys[0]; + keys[1] = keys[1] * 134775813 + 1; + keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24)); + } + + /// + /// Reset the internal state. + /// + protected void Reset() + { + keys[0] = 0; + keys[1] = 0; + keys[2] = 0; + } + + #region Instance Fields + uint[] keys; + #endregion + } + + /// + /// PkzipClassic CryptoTransform for encryption. + /// + class PkzipClassicEncryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform + { + /// + /// Initialise a new instance of + /// + /// The key block to use. + internal PkzipClassicEncryptCryptoTransform(byte[] keyBlock) + { + SetKeys(keyBlock); + } + + #region ICryptoTransform Members + + /// + /// Transforms the specified region of the specified byte array. + /// + /// The input for which to compute the transform. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + /// The computed transform. + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + byte[] result = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, result, 0); + return result; + } + + /// + /// Transforms the specified region of the input byte array and copies + /// the resulting transform to the specified region of the output byte array. + /// + /// The input for which to compute the transform. + /// The offset into the input byte array from which to begin using data. + /// The number of bytes in the input byte array to use as data. + /// The output to which to write the transform. + /// The offset into the output byte array from which to begin writing data. + /// The number of bytes written. + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + for (int i = inputOffset; i < inputOffset + inputCount; ++i) { + byte oldbyte = inputBuffer[i]; + outputBuffer[outputOffset++] = (byte)(inputBuffer[i] ^ TransformByte()); + UpdateKeys(oldbyte); + } + return inputCount; + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform + { + get { + return true; + } + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks + { + get { + return true; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Cleanup internal state. + /// + public void Dispose() + { + Reset(); + } + + #endregion + } + + + /// + /// PkzipClassic CryptoTransform for decryption. + /// + class PkzipClassicDecryptCryptoTransform : PkzipClassicCryptoBase, ICryptoTransform + { + /// + /// Initialise a new instance of . + /// + /// The key block to decrypt with. + internal PkzipClassicDecryptCryptoTransform(byte[] keyBlock) + { + SetKeys(keyBlock); + } + + #region ICryptoTransform Members + + /// + /// Transforms the specified region of the specified byte array. + /// + /// The input for which to compute the transform. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the byte array to use as data. + /// The computed transform. + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) + { + byte[] result = new byte[inputCount]; + TransformBlock(inputBuffer, inputOffset, inputCount, result, 0); + return result; + } + + /// + /// Transforms the specified region of the input byte array and copies + /// the resulting transform to the specified region of the output byte array. + /// + /// The input for which to compute the transform. + /// The offset into the input byte array from which to begin using data. + /// The number of bytes in the input byte array to use as data. + /// The output to which to write the transform. + /// The offset into the output byte array from which to begin writing data. + /// The number of bytes written. + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) + { + for (int i = inputOffset; i < inputOffset + inputCount; ++i) { + byte newByte = (byte)(inputBuffer[i] ^ TransformByte()); + outputBuffer[outputOffset++] = newByte; + UpdateKeys(newByte); + } + return inputCount; + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform + { + get { + return true; + } + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize + { + get { + return 1; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks + { + get { + return true; + } + } + + #endregion + + #region IDisposable Members + + /// + /// Cleanup internal state. + /// + public void Dispose() + { + Reset(); + } + + #endregion + } + + /// + /// Defines a wrapper object to access the Pkzip algorithm. + /// This class cannot be inherited. + /// + public sealed class PkzipClassicManaged : PkzipClassic + { + /// + /// Get / set the applicable block size in bits. + /// + /// The only valid block size is 8. + public override int BlockSize + { + get { + return 8; + } + + set { + if (value != 8) { + throw new CryptographicException("Block size is invalid"); + } + } + } + + /// + /// Get an array of legal key sizes. + /// + public override KeySizes[] LegalKeySizes + { + get { + KeySizes[] keySizes = new KeySizes[1]; + keySizes[0] = new KeySizes(12 * 8, 12 * 8, 0); + return keySizes; + } + } + + /// + /// Generate an initial vector. + /// + public override void GenerateIV() + { + // Do nothing. + } + + /// + /// Get an array of legal block sizes. + /// + public override KeySizes[] LegalBlockSizes + { + get { + KeySizes[] keySizes = new KeySizes[1]; + keySizes[0] = new KeySizes(1 * 8, 1 * 8, 0); + return keySizes; + } + } + + /// + /// Get / set the key value applicable. + /// + public override byte[] Key + { + get { + if ( key_ == null ) { + GenerateKey(); + } + + return (byte[]) key_.Clone(); + } + + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + + if ( value.Length != 12 ) { + throw new CryptographicException("Key size is illegal"); + } + + key_ = (byte[]) value.Clone(); + } + } + + /// + /// Generate a new random key. + /// + public override void GenerateKey() + { + key_ = new byte[12]; + Random rnd = new Random(); + rnd.NextBytes(key_); + } + + /// + /// Create an encryptor. + /// + /// The key to use for this encryptor. + /// Initialisation vector for the new encryptor. + /// Returns a new PkzipClassic encryptor + public override ICryptoTransform CreateEncryptor( + byte[] rgbKey, + byte[] rgbIV) + { + key_ = rgbKey; + return new PkzipClassicEncryptCryptoTransform(Key); + } + + /// + /// Create a decryptor. + /// + /// Keys to use for this new decryptor. + /// Initialisation vector for the new decryptor. + /// Returns a new decryptor. + public override ICryptoTransform CreateDecryptor( + byte[] rgbKey, + byte[] rgbIV) + { + key_ = rgbKey; + return new PkzipClassicDecryptCryptoTransform(Key); + } + + #region Instance Fields + byte[] key_; + #endregion + } +} +#endif diff --git a/类库/VersionUpdate/ZIP/Encryption/ZipAESStream.cs b/类库/VersionUpdate/ZIP/Encryption/ZipAESStream.cs new file mode 100644 index 0000000..d57dc34 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Encryption/ZipAESStream.cs @@ -0,0 +1,170 @@ +// +// ZipAESStream.cs +// +// Copyright 2009 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + +#if !NET_1_1 && !NETCF_2_0 + +using System; +using System.IO; +using System.Security.Cryptography; + +namespace ICSharpCode.SharpZipLib.Encryption { + + // Based on information from http://www.winzip.com/aes_info.htm + // and http://www.gladman.me.uk/cryptography_technology/fileencrypt/ + + /// + /// Encrypts and decrypts AES ZIP + /// + internal class ZipAESStream : CryptoStream { + + /// + /// Constructor + /// + /// The stream on which to perform the cryptographic transformation. + /// Instance of ZipAESTransform + /// Read or Write + public ZipAESStream(Stream stream, ZipAESTransform transform, CryptoStreamMode mode) + : base(stream, transform, mode) { + + _stream = stream; + _transform = transform; + _slideBuffer = new byte[1024]; + + _blockAndAuth = CRYPTO_BLOCK_SIZE + AUTH_CODE_LENGTH; + + // mode: + // CryptoStreamMode.Read means we read from "stream" and pass decrypted to our Read() method. + // Write bypasses this stream and uses the Transform directly. + if (mode != CryptoStreamMode.Read) { + throw new Exception("ZipAESStream only for read"); + } + } + + // The final n bytes of the AES stream contain the Auth Code. + private const int AUTH_CODE_LENGTH = 10; + + private Stream _stream; + private ZipAESTransform _transform; + private byte[] _slideBuffer; + private int _slideBufStartPos; + private int _slideBufFreePos; + // Blocksize is always 16 here, even for AES-256 which has transform.InputBlockSize of 32. + private const int CRYPTO_BLOCK_SIZE = 16; + private int _blockAndAuth; + + /// + /// Reads a sequence of bytes from the current CryptoStream into buffer, + /// and advances the position within the stream by the number of bytes read. + /// + public override int Read(byte[] outBuffer, int offset, int count) { + int nBytes = 0; + while (nBytes < count) { + // Calculate buffer quantities vs read-ahead size, and check for sufficient free space + int byteCount = _slideBufFreePos - _slideBufStartPos; + + // Need to handle final block and Auth Code specially, but don't know total data length. + // Maintain a read-ahead equal to the length of (crypto block + Auth Code). + // When that runs out we can detect these final sections. + int lengthToRead = _blockAndAuth - byteCount; + if (_slideBuffer.Length - _slideBufFreePos < lengthToRead) { + // Shift the data to the beginning of the buffer + int iTo = 0; + for (int iFrom = _slideBufStartPos; iFrom < _slideBufFreePos; iFrom++, iTo++) { + _slideBuffer[iTo] = _slideBuffer[iFrom]; + } + _slideBufFreePos -= _slideBufStartPos; // Note the -= + _slideBufStartPos = 0; + } + int obtained = _stream.Read(_slideBuffer, _slideBufFreePos, lengthToRead); + _slideBufFreePos += obtained; + + // Recalculate how much data we now have + byteCount = _slideBufFreePos - _slideBufStartPos; + if (byteCount >= _blockAndAuth) { + // At least a 16 byte block and an auth code remains. + _transform.TransformBlock(_slideBuffer, + _slideBufStartPos, + CRYPTO_BLOCK_SIZE, + outBuffer, + offset); + nBytes += CRYPTO_BLOCK_SIZE; + offset += CRYPTO_BLOCK_SIZE; + _slideBufStartPos += CRYPTO_BLOCK_SIZE; + } else { + // Last round. + if (byteCount > AUTH_CODE_LENGTH) { + // At least one byte of data plus auth code + int finalBlock = byteCount - AUTH_CODE_LENGTH; + _transform.TransformBlock(_slideBuffer, + _slideBufStartPos, + finalBlock, + outBuffer, + offset); + + nBytes += finalBlock; + _slideBufStartPos += finalBlock; + } + else if (byteCount < AUTH_CODE_LENGTH) + throw new Exception("Internal error missed auth code"); // Coding bug + // Final block done. Check Auth code. + byte[] calcAuthCode = _transform.GetAuthCode(); + for (int i = 0; i < AUTH_CODE_LENGTH; i++) { + if (calcAuthCode[i] != _slideBuffer[_slideBufStartPos + i]) { + throw new Exception("AES Authentication Code does not match. This is a super-CRC check on the data in the file after compression and encryption. \r\n" + + "The file may be damaged."); + } + } + + break; // Reached the auth code + } + } + return nBytes; + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + public override void Write(byte[] buffer, int offset, int count) { + // ZipAESStream is used for reading but not for writing. Writing uses the ZipAESTransform directly. + throw new NotImplementedException(); + } + } +} +#endif \ No newline at end of file diff --git a/类库/VersionUpdate/ZIP/Encryption/ZipAESTransform.cs b/类库/VersionUpdate/ZIP/Encryption/ZipAESTransform.cs new file mode 100644 index 0000000..134c1eb --- /dev/null +++ b/类库/VersionUpdate/ZIP/Encryption/ZipAESTransform.cs @@ -0,0 +1,219 @@ +// +// ZipAESTransform.cs +// +// Copyright 2009 David Pierson +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. +// + +#if !NET_1_1 && !NETCF_2_0 +// Framework version 2.0 required for Rfc2898DeriveBytes + +using System; +using System.Security.Cryptography; + +namespace ICSharpCode.SharpZipLib.Encryption { + + /// + /// Transforms stream using AES in CTR mode + /// + internal class ZipAESTransform : ICryptoTransform { + + private const int PWD_VER_LENGTH = 2; + + // WinZip use iteration count of 1000 for PBKDF2 key generation + private const int KEY_ROUNDS = 1000; + + // For 128-bit AES (16 bytes) the encryption is implemented as expected. + // For 256-bit AES (32 bytes) WinZip do full 256 bit AES of the nonce to create the encryption + // block but use only the first 16 bytes of it, and discard the second half. + private const int ENCRYPT_BLOCK = 16; + + private int _blockSize; + private ICryptoTransform _encryptor; + private readonly byte[] _counterNonce; + private byte[] _encryptBuffer; + private int _encrPos; + private byte[] _pwdVerifier; + private HMACSHA1 _hmacsha1; + private bool _finalised; + + private bool _writeMode; + + /// + /// Constructor. + /// + /// Password string + /// Random bytes, length depends on encryption strength. + /// 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. + /// The encryption strength, in bytes eg 16 for 128 bits. + /// True when creating a zip, false when reading. For the AuthCode. + /// + public ZipAESTransform(string key, byte[] saltBytes, int blockSize, bool writeMode) { + + if (blockSize != 16 && blockSize != 32) // 24 valid for AES but not supported by Winzip + throw new Exception("Invalid blocksize " + blockSize + ". Must be 16 or 32."); + if (saltBytes.Length != blockSize / 2) + throw new Exception("Invalid salt len. Must be " + blockSize / 2 + " for blocksize " + blockSize); + // initialise the encryption buffer and buffer pos + _blockSize = blockSize; + _encryptBuffer = new byte[_blockSize]; + _encrPos = ENCRYPT_BLOCK; + + // Performs the equivalent of derive_key in Dr Brian Gladman's pwd2key.c + Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, saltBytes, KEY_ROUNDS); + RijndaelManaged rm = new RijndaelManaged(); + rm.Mode = CipherMode.ECB; // No feedback from cipher for CTR mode + _counterNonce = new byte[_blockSize]; + byte[] byteKey1 = pdb.GetBytes(_blockSize); + byte[] byteKey2 = pdb.GetBytes(_blockSize); + _encryptor = rm.CreateEncryptor(byteKey1, byteKey2); + _pwdVerifier = pdb.GetBytes(PWD_VER_LENGTH); + // + _hmacsha1 = new HMACSHA1(byteKey2); + _writeMode = writeMode; + } + + /// + /// Implement the ICryptoTransform method. + /// + public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { + + // Pass the data stream to the hash algorithm for generating the Auth Code. + // This does not change the inputBuffer. Do this before decryption for read mode. + if (!_writeMode) { + _hmacsha1.TransformBlock(inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset); + } + // Encrypt with AES in CTR mode. Regards to Dr Brian Gladman for this. + int ix = 0; + while (ix < inputCount) { + if (_encrPos == ENCRYPT_BLOCK) { + /* increment encryption nonce */ + int j = 0; + while (++_counterNonce[j] == 0) { + ++j; + } + /* encrypt the nonce to form next xor buffer */ + _encryptor.TransformBlock(_counterNonce, 0, _blockSize, _encryptBuffer, 0); + _encrPos = 0; + } + outputBuffer[ix + outputOffset] = (byte)(inputBuffer[ix + inputOffset] ^ _encryptBuffer[_encrPos++]); + // + ix++; + } + if (_writeMode) { + // This does not change the buffer. + _hmacsha1.TransformBlock(outputBuffer, outputOffset, inputCount, outputBuffer, outputOffset); + } + return inputCount; + } + + /// + /// Returns the 2 byte password verifier + /// + public byte[] PwdVerifier { + get { + return _pwdVerifier; + } + } + + /// + /// Returns the 10 byte AUTH CODE to be checked or appended immediately following the AES data stream. + /// + public byte[] GetAuthCode() { + // We usually don't get advance notice of final block. Hash requres a TransformFinal. + if (!_finalised) { + byte[] dummy = new byte[0]; + _hmacsha1.TransformFinalBlock(dummy, 0, 0); + _finalised = true; + } + return _hmacsha1.Hash; + } + + #region ICryptoTransform Members + + /// + /// Not implemented. + /// + public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { + + throw new NotImplementedException("ZipAESTransform.TransformFinalBlock"); + } + + /// + /// Gets the size of the input data blocks in bytes. + /// + public int InputBlockSize { + get { + return _blockSize; + } + } + + /// + /// Gets the size of the output data blocks in bytes. + /// + public int OutputBlockSize { + get { + return _blockSize; + } + } + + /// + /// Gets a value indicating whether multiple blocks can be transformed. + /// + public bool CanTransformMultipleBlocks { + get { + return true; + } + } + + /// + /// Gets a value indicating whether the current transform can be reused. + /// + public bool CanReuseTransform { + get { + return true; + } + } + + /// + /// Cleanup internal state. + /// + public void Dispose() { + _encryptor.Dispose(); + } + + #endregion + + } +} +#endif \ No newline at end of file diff --git a/类库/VersionUpdate/ZIP/GZip/GZIPConstants.cs b/类库/VersionUpdate/ZIP/GZip/GZIPConstants.cs new file mode 100644 index 0000000..1c0e389 --- /dev/null +++ b/类库/VersionUpdate/ZIP/GZip/GZIPConstants.cs @@ -0,0 +1,97 @@ +// GZipConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This class contains constants used for gzip. + /// + sealed public class GZipConstants + { + /// + /// Magic number found at start of GZIP header + /// + public const int GZIP_MAGIC = 0x1F8B; + + /* The flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + */ + + /// + /// Flag bit mask for text + /// + public const int FTEXT = 0x1; + + /// + /// Flag bitmask for Crc + /// + public const int FHCRC = 0x2; + + /// + /// Flag bit mask for extra + /// + public const int FEXTRA = 0x4; + + /// + /// flag bitmask for name + /// + public const int FNAME = 0x8; + + /// + /// flag bit mask indicating comment is present + /// + public const int FCOMMENT = 0x10; + + /// + /// Initialise default instance. + /// + /// Constructor is private to prevent instances being created. + GZipConstants() + { + } + } +} diff --git a/类库/VersionUpdate/ZIP/GZip/GZipException.cs b/类库/VersionUpdate/ZIP/GZip/GZipException.cs new file mode 100644 index 0000000..7f42931 --- /dev/null +++ b/类库/VersionUpdate/ZIP/GZip/GZipException.cs @@ -0,0 +1,91 @@ +// GZipException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.GZip +{ + /// + /// GZipException represents a Gzip specific exception + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class GZipException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected GZipException(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + + /// + /// Initialise a new instance of GZipException + /// + public GZipException() + { + } + + /// + /// Initialise a new instance of GZipException with its message string. + /// + /// A that describes the error. + public GZipException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of . + /// + /// A that describes the error. + /// The that caused this exception. + public GZipException(string message, Exception innerException) + : base (message, innerException) + { + } + } +} diff --git a/类库/VersionUpdate/ZIP/GZip/GzipInputStream.cs b/类库/VersionUpdate/ZIP/GZip/GzipInputStream.cs new file mode 100644 index 0000000..4cbad94 --- /dev/null +++ b/类库/VersionUpdate/ZIP/GZip/GzipInputStream.cs @@ -0,0 +1,384 @@ +// GzipInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 11-08-2009 GeoffHart T9121 Added Multi-member gzip support + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This filter stream is used to decompress a "GZIP" format stream. + /// The "GZIP" format is described baseInputStream RFC 1952. + /// + /// author of the original java version : John Leuner + /// + /// This sample shows how to unzip a gzipped file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.GZip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream inStream = new GZipInputStream(File.OpenRead(args[0]))) + /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + /// byte[] buffer = new byte[4096]; + /// StreamUtils.Copy(inStream, outStream, buffer); + /// } + /// } + /// } + /// + /// + public class GZipInputStream : InflaterInputStream + { + #region Instance Fields + /// + /// CRC-32 value for uncompressed data + /// + protected Crc32 crc; + + /// + /// Flag to indicate if we've read the GZIP header yet for the current member (block of compressed data). + /// This is tracked per-block as the file is parsed. + /// + bool readGZIPHeader; + #endregion + + #region Constructors + /// + /// Creates a GZipInputStream with the default buffer size + /// + /// + /// The stream to read compressed data from (baseInputStream GZIP format) + /// + public GZipInputStream(Stream baseInputStream) + : this(baseInputStream, 4096) + { + } + + /// + /// Creates a GZIPInputStream with the specified buffer size + /// + /// + /// The stream to read compressed data from (baseInputStream GZIP format) + /// + /// + /// Size of the buffer to use + /// + public GZipInputStream(Stream baseInputStream, int size) + : base(baseInputStream, new Inflater(true), size) + { + } + #endregion + + #region Stream overrides + /// + /// Reads uncompressed data into an array of bytes + /// + /// + /// The buffer to read uncompressed data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of uncompressed bytes to be read + /// + /// Returns the number of bytes actually read. + public override int Read(byte[] buffer, int offset, int count) + { + // A GZIP file can contain multiple blocks of compressed data, although this is quite rare. + // A compressed block could potentially be empty, so we need to loop until we reach EOF or + // we find data. + while (true) { + + // If we haven't read the header for this block, read it + if (! readGZIPHeader) { + + // Try to read header. If there is no header (0 bytes available), this is EOF. If there is + // an incomplete header, this will throw an exception. + if (! ReadHeader()) { + return 0; + } + } + + // Try to read compressed data + int bytesRead = base.Read(buffer, offset, count); + if (bytesRead > 0) { + crc.Update(buffer, offset, bytesRead); + } + + // If this is the end of stream, read the footer + if (inf.IsFinished) { + ReadFooter(); + } + + if (bytesRead > 0) { + return bytesRead; + } + } + } + #endregion + + #region Support routines + bool ReadHeader() + { + // Initialize CRC for this block + crc = new Crc32(); + + // Make sure there is data in file. We can't rely on ReadLeByte() to fill the buffer, as this could be EOF, + // which is fine, but ReadLeByte() throws an exception if it doesn't find data, so we do this part ourselves. + if (inputBuffer.Available <= 0) { + inputBuffer.Fill(); + if (inputBuffer.Available <= 0) { + // No header, EOF. + return false; + } + } + + // 1. Check the two magic bytes + Crc32 headCRC = new Crc32(); + int magic = inputBuffer.ReadLeByte(); + + if (magic < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + headCRC.Update(magic); + if (magic != (GZipConstants.GZIP_MAGIC >> 8)) { + throw new GZipException("Error GZIP header, first magic byte doesn't match"); + } + + //magic = baseInputStream.ReadByte(); + magic = inputBuffer.ReadLeByte(); + + if (magic < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + if (magic != (GZipConstants.GZIP_MAGIC & 0xFF)) { + throw new GZipException("Error GZIP header, second magic byte doesn't match"); + } + + headCRC.Update(magic); + + // 2. Check the compression type (must be 8) + int compressionType = inputBuffer.ReadLeByte(); + + if ( compressionType < 0 ) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + if ( compressionType != 8 ) { + throw new GZipException("Error GZIP header, data not in deflate format"); + } + headCRC.Update(compressionType); + + // 3. Check the flags + int flags = inputBuffer.ReadLeByte(); + if (flags < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(flags); + + /* This flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + */ + + // 3.1 Check the reserved bits are zero + + if ((flags & 0xE0) != 0) { + throw new GZipException("Reserved flag bits in GZIP header != 0"); + } + + // 4.-6. Skip the modification time, extra flags, and OS type + for (int i=0; i< 6; i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + // 7. Read extra field + if ((flags & GZipConstants.FEXTRA) != 0) { + // Skip subfield id + for (int i=0; i< 2; i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + if (inputBuffer.ReadLeByte() < 0 || inputBuffer.ReadLeByte() < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + int len1, len2; + len1 = inputBuffer.ReadLeByte(); + len2 = inputBuffer.ReadLeByte(); + if ((len1 < 0) || (len2 < 0)) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(len1); + headCRC.Update(len2); + + int extraLen = (len1 << 8) | len2; + for (int i = 0; i < extraLen;i++) { + int readByte = inputBuffer.ReadLeByte(); + if (readByte < 0) + { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + } + + // 8. Read file name + if ((flags & GZipConstants.FNAME) != 0) { + int readByte; + while ( (readByte = inputBuffer.ReadLeByte()) > 0) { + headCRC.Update(readByte); + } + + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + headCRC.Update(readByte); + } + + // 9. Read comment + if ((flags & GZipConstants.FCOMMENT) != 0) { + int readByte; + while ( (readByte = inputBuffer.ReadLeByte()) > 0) { + headCRC.Update(readByte); + } + + if (readByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + headCRC.Update(readByte); + } + + // 10. Read header CRC + if ((flags & GZipConstants.FHCRC) != 0) { + int tempByte; + int crcval = inputBuffer.ReadLeByte(); + if (crcval < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + tempByte = inputBuffer.ReadLeByte(); + if (tempByte < 0) { + throw new EndOfStreamException("EOS reading GZIP header"); + } + + crcval = (crcval << 8) | tempByte; + if (crcval != ((int) headCRC.Value & 0xffff)) { + throw new GZipException("Header CRC value mismatch"); + } + } + + readGZIPHeader = true; + return true; + } + + void ReadFooter() + { + byte[] footer = new byte[8]; + + // End of stream; reclaim all bytes from inf, read the final byte count, and reset the inflator + long bytesRead = inf.TotalOut & 0xffffffff; + inputBuffer.Available += inf.RemainingInput; + inf.Reset(); + + // Read footer from inputBuffer + int needed = 8; + while (needed > 0) { + int count = inputBuffer.ReadClearTextBuffer(footer, 8 - needed, needed); + if (count <= 0) { + throw new EndOfStreamException("EOS reading GZIP footer"); + } + needed -= count; // Jewel Jan 16 + } + + // Calculate CRC + int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8) | ((footer[2] & 0xff) << 16) | (footer[3] << 24); + if (crcval != (int) crc.Value) { + throw new GZipException("GZIP crc sum mismatch, theirs \"" + crcval + "\" and ours \"" + (int) crc.Value); + } + + // NOTE The total here is the original total modulo 2 ^ 32. + uint total = + (uint)((uint)footer[4] & 0xff) | + (uint)(((uint)footer[5] & 0xff) << 8) | + (uint)(((uint)footer[6] & 0xff) << 16) | + (uint)((uint)footer[7] << 24); + + if (bytesRead != total) { + throw new GZipException("Number of bytes mismatch in footer"); + } + + // Mark header read as false so if another header exists, we'll continue reading through the file + readGZIPHeader = false; + } + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/GZip/GzipOutputStream.cs b/类库/VersionUpdate/ZIP/GZip/GzipOutputStream.cs new file mode 100644 index 0000000..0db2e4b --- /dev/null +++ b/类库/VersionUpdate/ZIP/GZip/GzipOutputStream.cs @@ -0,0 +1,261 @@ +// GZipOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.GZip +{ + + /// + /// This filter stream is used to compress a stream into a "GZIP" stream. + /// The "GZIP" format is described in RFC 1952. + /// + /// author of the original java version : John Leuner + /// + /// This sample shows how to gzip a file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.GZip; + /// using ICSharpCode.SharpZipLib.Core; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz"))) + /// using (FileStream fs = File.OpenRead(args[0])) { + /// byte[] writeData = new byte[4096]; + /// Streamutils.Copy(s, fs, writeData); + /// } + /// } + /// } + /// } + /// + /// + public class GZipOutputStream : DeflaterOutputStream + { + enum OutputState + { + Header, + Footer, + Finished, + Closed, + }; + + #region Instance Fields + /// + /// CRC-32 value for uncompressed data + /// + protected Crc32 crc = new Crc32(); + OutputState state_ = OutputState.Header; + #endregion + + #region Constructors + /// + /// Creates a GzipOutputStream with the default buffer size + /// + /// + /// The stream to read data (to be compressed) from + /// + public GZipOutputStream(Stream baseOutputStream) + : this(baseOutputStream, 4096) + { + } + + /// + /// Creates a GZipOutputStream with the specified buffer size + /// + /// + /// The stream to read data (to be compressed) from + /// + /// + /// Size of the buffer to use + /// + public GZipOutputStream(Stream baseOutputStream, int size) : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size) + { + } + #endregion + + #region Public API + /// + /// Sets the active compression level (1-9). The new level will be activated + /// immediately. + /// + /// The compression level to set. + /// + /// Level specified is not supported. + /// + /// + public void SetLevel(int level) + { + if (level < Deflater.BEST_SPEED) { + throw new ArgumentOutOfRangeException("level"); + } + deflater_.SetLevel(level); + } + + /// + /// Get the current compression level. + /// + /// The current compression level. + public int GetLevel() + { + return deflater_.GetLevel(); + } + #endregion + + #region Stream overrides + /// + /// Write given buffer to output updating crc + /// + /// Buffer to write + /// Offset of first byte in buf to write + /// Number of bytes to write + public override void Write(byte[] buffer, int offset, int count) + { + if ( state_ == OutputState.Header ) { + WriteHeader(); + } + + if( state_!=OutputState.Footer ) + { + throw new InvalidOperationException("Write not permitted in current state"); + } + + crc.Update(buffer, offset, count); + base.Write(buffer, offset, count); + } + + /// + /// Writes remaining compressed output data to the output stream + /// and closes it. + /// + public override void Close() + { + try { + Finish(); + } + finally { + if ( state_ != OutputState.Closed ) { + state_ = OutputState.Closed; + if( IsStreamOwner ) { + baseOutputStream_.Close(); + } + } + } + } + #endregion + + #region DeflaterOutputStream overrides + /// + /// Finish compression and write any footer information required to stream + /// + public override void Finish() + { + // If no data has been written a header should be added. + if ( state_ == OutputState.Header ) { + WriteHeader(); + } + + if( state_ == OutputState.Footer) + { + state_=OutputState.Finished; + base.Finish(); + + uint totalin=(uint)(deflater_.TotalIn&0xffffffff); + uint crcval=(uint)(crc.Value&0xffffffff); + + byte[] gzipFooter; + + unchecked + { + gzipFooter=new byte[] { + (byte) crcval, (byte) (crcval >> 8), + (byte) (crcval >> 16), (byte) (crcval >> 24), + + (byte) totalin, (byte) (totalin >> 8), + (byte) (totalin >> 16), (byte) (totalin >> 24) + }; + } + + baseOutputStream_.Write(gzipFooter, 0, gzipFooter.Length); + } + } + #endregion + + #region Support Routines + void WriteHeader() + { + if ( state_ == OutputState.Header ) + { + state_=OutputState.Footer; + + int mod_time = (int)((DateTime.Now.Ticks - new DateTime(1970, 1, 1).Ticks) / 10000000L); // Ticks give back 100ns intervals + byte[] gzipHeader = { + // The two magic bytes + (byte) (GZipConstants.GZIP_MAGIC >> 8), (byte) (GZipConstants.GZIP_MAGIC & 0xff), + + // The compression type + (byte) Deflater.DEFLATED, + + // The flags (not set) + 0, + + // The modification time + (byte) mod_time, (byte) (mod_time >> 8), + (byte) (mod_time >> 16), (byte) (mod_time >> 24), + + // The extra flags + 0, + + // The OS type (unknown) + (byte) 255 + }; + baseOutputStream_.Write(gzipHeader, 0, gzipHeader.Length); + } + } + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Lzw/LzwConstants.cs b/类库/VersionUpdate/ZIP/Lzw/LzwConstants.cs new file mode 100644 index 0000000..699ed09 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Lzw/LzwConstants.cs @@ -0,0 +1,94 @@ +// LzwConstants.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.LZW { + + /// + /// This class contains constants used for LZW + /// + sealed public class LzwConstants { + /// + /// Magic number found at start of LZW header: 0x1f 0x9d + /// + public const int MAGIC = 0x1f9d; + + /// + /// Maximum number of bits per code + /// + public const int MAX_BITS = 16; + + /* 3rd header byte: + * bit 0..4 Number of compression bits + * bit 5 Extended header + * bit 6 Free + * bit 7 Block mode + */ + + /// + /// Mask for 'number of compression bits' + /// + public const int BIT_MASK = 0x1f; + + /// + /// Indicates the presence of a fourth header byte + /// + public const int EXTENDED_MASK = 0x20; + //public const int FREE_MASK = 0x40; + + /// + /// Reserved bits + /// + public const int RESERVED_MASK = 0x60; + + /// + /// Block compression: if table is full and compression rate is dropping, + /// clear the dictionary. + /// + public const int BLOCK_MODE_MASK = 0x80; + + /// + /// LZW file header size (in bytes) + /// + public const int HDR_SIZE = 3; + + /// + /// Initial number of bits per code + /// + public const int INIT_BITS = 9; + + LzwConstants() { + } + } +} diff --git a/类库/VersionUpdate/ZIP/Lzw/LzwException.cs b/类库/VersionUpdate/ZIP/Lzw/LzwException.cs new file mode 100644 index 0000000..10a9547 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Lzw/LzwException.cs @@ -0,0 +1,88 @@ +// LzwException.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.LZW +{ + + /// + /// LzwException represents a LZW specific exception + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class LzwException : SharpZipBaseException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected LzwException(SerializationInfo info, StreamingContext context) + : base(info, context) { + } +#endif + + /// + /// Initialise a new instance of LzwException + /// + public LzwException() { + } + + /// + /// Initialise a new instance of LzwException with its message string. + /// + /// A that describes the error. + public LzwException(string message) + : base(message) { + } + + /// + /// Initialise a new instance of . + /// + /// A that describes the error. + /// The that caused this exception. + public LzwException(string message, Exception innerException) + : base(message, innerException) { + } + } +} diff --git a/类库/VersionUpdate/ZIP/Lzw/LzwInputStream.cs b/类库/VersionUpdate/ZIP/Lzw/LzwInputStream.cs new file mode 100644 index 0000000..94b8b66 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Lzw/LzwInputStream.cs @@ -0,0 +1,598 @@ +// LzwInputStream.cs +// +// Copyright (C) 2009 Gabriel Burca +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.LZW +{ + + /// + /// This filter stream is used to decompress a LZW format stream. + /// Specifically, a stream that uses the LZC compression method. + /// This file format is usually associated with the .Z file extension. + /// + /// See http://en.wikipedia.org/wiki/Compress + /// See http://wiki.wxwidgets.org/Development:_Z_File_Format + /// + /// The file header consists of 3 (or optionally 4) bytes. The first two bytes + /// contain the magic marker "0x1f 0x9d", followed by a byte of flags. + /// + /// Based on Java code by Ronald Tschalar, which in turn was based on the unlzw.c + /// code in the gzip package. + /// + /// This sample shows how to unzip a compressed file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.LZW; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using (Stream inStream = new LzwInputStream(File.OpenRead(args[0]))) + /// using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + /// byte[] buffer = new byte[4096]; + /// StreamUtils.Copy(inStream, outStream, buffer); + /// // OR + /// inStream.Read(buffer, 0, buffer.Length); + /// // now do something with the buffer + /// } + /// } + /// } + /// + /// + public class LzwInputStream : Stream + { + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + /// + /// The default value is true. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Creates a LzwInputStream + /// + /// + /// The stream to read compressed data from (baseInputStream LZW format) + /// + public LzwInputStream(Stream baseInputStream) { + this.baseInputStream = baseInputStream; + } + + /// + /// See + /// + /// + public override int ReadByte() { + int b = Read(one, 0, 1); + if (b == 1) + return (one[0] & 0xff); + return -1; + } + + /// + /// Reads decompressed data into the provided buffer byte array + /// + /// + /// The array to read and decompress data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of bytes to decompress + /// + /// The number of bytes read. Zero signals the end of stream + public override int Read(byte[] buffer, int offset, int count) { + if (!headerParsed) ParseHeader(); + + if (eof) return -1; + int start = offset; + + /* Using local copies of various variables speeds things up by as + * much as 30% in Java! Performance not tested in C#. + */ + int[] lTabPrefix = tabPrefix; + byte[] lTabSuffix = tabSuffix; + byte[] lStack = stack; + int lNBits = nBits; + int lMaxCode = maxCode; + int lMaxMaxCode = maxMaxCode; + int lBitMask = bitMask; + int lOldCode = oldCode; + byte lFinChar = finChar; + int lStackP = stackP; + int lFreeEnt = freeEnt; + byte[] lData = data; + int lBitPos = bitPos; + + + // empty stack if stuff still left + int sSize = lStack.Length - lStackP; + if (sSize > 0) { + int num = (sSize >= count) ? count : sSize; + Array.Copy(lStack, lStackP, buffer, offset, num); + offset += num; + count -= num; + lStackP += num; + } + + if (count == 0) { + stackP = lStackP; + return offset - start; + } + + + // loop, filling local buffer until enough data has been decompressed + MainLoop: do { + if (end < EXTRA) { + Fill(); + } + + int bitIn = (got > 0) ? (end - end % lNBits) << 3 : + (end << 3) - (lNBits - 1); + + while (lBitPos < bitIn) { + #region A + // handle 1-byte reads correctly + if (count == 0) { + nBits = lNBits; + maxCode = lMaxCode; + maxMaxCode = lMaxMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + return offset - start; + } + + // check for code-width expansion + if (lFreeEnt > lMaxCode) { + int nBytes = lNBits << 3; + lBitPos = (lBitPos - 1) + + nBytes - (lBitPos - 1 + nBytes) % nBytes; + + lNBits++; + lMaxCode = (lNBits == maxBits) ? lMaxMaxCode : + (1 << lNBits) - 1; + + lBitMask = (1 << lNBits) - 1; + lBitPos = ResetBuf(lBitPos); + goto MainLoop; + } + #endregion + + #region B + // read next code + int pos = lBitPos >> 3; + int code = (((lData[pos] & 0xFF) | + ((lData[pos + 1] & 0xFF) << 8) | + ((lData[pos + 2] & 0xFF) << 16)) >> + (lBitPos & 0x7)) & lBitMask; + + lBitPos += lNBits; + + // handle first iteration + if (lOldCode == -1) { + if (code >= 256) throw new LzwException("corrupt input: " + code + " > 255"); + + lFinChar = (byte) (lOldCode = code); + buffer[offset++] = lFinChar; + count--; + continue; + } + + // handle CLEAR code + if (code == TBL_CLEAR && blockMode) { + Array.Copy(zeros, 0, lTabPrefix, 0, zeros.Length); + lFreeEnt = TBL_FIRST - 1; + + int nBytes = lNBits << 3; + lBitPos = (lBitPos - 1) + nBytes - (lBitPos - 1 + nBytes) % nBytes; + lNBits = LzwConstants.INIT_BITS; + lMaxCode = (1 << lNBits) - 1; + lBitMask = lMaxCode; + + // Code tables reset + + lBitPos = ResetBuf(lBitPos); + goto MainLoop; + } + #endregion + + #region C + // setup + int inCode = code; + lStackP = lStack.Length; + + // Handle KwK case + if (code >= lFreeEnt) { + if (code > lFreeEnt) { + throw new LzwException("corrupt input: code=" + code + + ", freeEnt=" + lFreeEnt); + } + + lStack[--lStackP] = lFinChar; + code = lOldCode; + } + + // Generate output characters in reverse order + while (code >= 256) { + lStack[--lStackP] = lTabSuffix[code]; + code = lTabPrefix[code]; + } + + lFinChar = lTabSuffix[code]; + buffer[offset++] = lFinChar; + count--; + + // And put them out in forward order + sSize = lStack.Length - lStackP; + int num = (sSize >= count) ? count : sSize; + Array.Copy(lStack, lStackP, buffer, offset, num); + offset += num; + count -= num; + lStackP += num; + #endregion + + #region D + // generate new entry in table + if (lFreeEnt < lMaxMaxCode) { + lTabPrefix[lFreeEnt] = lOldCode; + lTabSuffix[lFreeEnt] = lFinChar; + lFreeEnt++; + } + + // Remember previous code + lOldCode = inCode; + + // if output buffer full, then return + if (count == 0) { + nBits = lNBits; + maxCode = lMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + return offset - start; + } + #endregion + } // while + + lBitPos = ResetBuf(lBitPos); + + } while (got > 0); // do..while + + nBits = lNBits; + maxCode = lMaxCode; + bitMask = lBitMask; + oldCode = lOldCode; + finChar = lFinChar; + stackP = lStackP; + freeEnt = lFreeEnt; + bitPos = lBitPos; + + eof = true; + return offset - start; + } + + /// + /// Moves the unread data in the buffer to the beginning and resets + /// the pointers. + /// + /// + /// + private int ResetBuf(int bitPosition) { + int pos = bitPosition >> 3; + Array.Copy(data, pos, data, 0, end - pos); + end -= pos; + return 0; + } + + + private void Fill() { + got = baseInputStream.Read(data, end, data.Length - 1 - end); + if (got > 0) { + end += got; + } + } + + + private void ParseHeader() { + headerParsed = true; + + byte[] hdr = new byte[LzwConstants.HDR_SIZE]; + + int result = baseInputStream.Read(hdr, 0, hdr.Length); + + // Check the magic marker + if (result < 0) + throw new LzwException("Failed to read LZW header"); + + if (hdr[0] != (LzwConstants.MAGIC >> 8) || hdr[1] != (LzwConstants.MAGIC & 0xff)) { + throw new LzwException(String.Format( + "Wrong LZW header. Magic bytes don't match. 0x{0:x2} 0x{1:x2}", + hdr[0], hdr[1])); + } + + // Check the 3rd header byte + blockMode = (hdr[2] & LzwConstants.BLOCK_MODE_MASK) > 0; + maxBits = hdr[2] & LzwConstants.BIT_MASK; + + if (maxBits > LzwConstants.MAX_BITS) { + throw new LzwException("Stream compressed with " + maxBits + + " bits, but decompression can only handle " + + LzwConstants.MAX_BITS + " bits."); + } + + if ((hdr[2] & LzwConstants.RESERVED_MASK) > 0) { + throw new LzwException("Unsupported bits set in the header."); + } + + // Initialize variables + maxMaxCode = 1 << maxBits; + nBits = LzwConstants.INIT_BITS; + maxCode = (1 << nBits) - 1; + bitMask = maxCode; + oldCode = -1; + finChar = 0; + freeEnt = blockMode ? TBL_FIRST : 256; + + tabPrefix = new int[1 << maxBits]; + tabSuffix = new byte[1 << maxBits]; + stack = new byte[1 << maxBits]; + stackP = stack.Length; + + for (int idx = 255; idx >= 0; idx--) + tabSuffix[idx] = (byte)idx; + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get + { + return baseInputStream.CanRead; + } + } + + /// + /// Gets a value of false indicating seeking is not supported for this stream. + /// + public override bool CanSeek + { + get + { + return false; + } + } + + /// + /// Gets a value of false indicating that this stream is not writeable. + /// + public override bool CanWrite + { + get + { + return false; + } + } + + /// + /// A value representing the length of the stream in bytes. + /// + public override long Length + { + get + { + return got; + } + } + + /// + /// The current position within the stream. + /// Throws a NotSupportedException when attempting to set the position + /// + /// Attempting to set the position + public override long Position + { + get + { + return baseInputStream.Position; + } + set + { + throw new NotSupportedException("InflaterInputStream Position not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + baseInputStream.Flush(); + } + + /// + /// Sets the position within the current stream + /// Always throws a NotSupportedException + /// + /// The relative offset to seek to. + /// The defining where to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Seek not supported"); + } + + /// + /// Set the length of the current stream + /// Always throws a NotSupportedException + /// + /// The new length value for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("InflaterInputStream SetLength not supported"); + } + + /// + /// Writes a sequence of bytes to stream and advances the current position + /// This method always throws a NotSupportedException + /// + /// Thew buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("InflaterInputStream Write not supported"); + } + + /// + /// Writes one byte to the current stream and advances the current position + /// Always throws a NotSupportedException + /// + /// The byte to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("InflaterInputStream WriteByte not supported"); + } + + /// + /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. + /// + /// The buffer to write data from + /// Offset of first byte to write + /// The maximum number of bytes to write + /// The method to be called when the asynchronous write operation is completed + /// A user-provided object that distinguishes this particular asynchronous write request from other requests + /// An IAsyncResult that references the asynchronous write + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); + } + + /// + /// Closes the input stream. When + /// is true the underlying stream is also closed. + /// + public override void Close() + { + if (!isClosed) + { + isClosed = true; + if (isStreamOwner) + { + baseInputStream.Close(); + } + } + } + + #endregion + + #region Instance Fields + + Stream baseInputStream; + + /// + /// Flag indicating wether this instance is designated the stream owner. + /// When closing if this flag is true the underlying stream is closed. + /// + bool isStreamOwner = true; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + readonly byte[] one = new byte[1]; + bool headerParsed; + + // string table stuff + private const int TBL_CLEAR = 0x100; + private const int TBL_FIRST = TBL_CLEAR + 1; + + private int[] tabPrefix; + private byte[] tabSuffix; + private readonly int[] zeros = new int[256]; + private byte[] stack; + + // various state + private bool blockMode; + private int nBits; + private int maxBits; + private int maxMaxCode; + private int maxCode; + private int bitMask; + private int oldCode; + private byte finChar; + private int stackP; + private int freeEnt; + + // input buffer + private readonly byte[] data = new byte[1024 * 8]; + private int bitPos; + private int end; + int got; + private bool eof; + private const int EXTRA = 64; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/SharpZipBaseException.cs b/类库/VersionUpdate/ZIP/SharpZipBaseException.cs new file mode 100644 index 0000000..7a5d136 --- /dev/null +++ b/类库/VersionUpdate/ZIP/SharpZipBaseException.cs @@ -0,0 +1,94 @@ +// SharpZipBaseException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib +{ + /// + /// SharpZipBaseException is the base exception class for the SharpZipLibrary. + /// All library exceptions are derived from this. + /// + /// NOTE: Not all exceptions thrown will be derived from this class. + /// A variety of other exceptions are possible for example +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class SharpZipBaseException : ApplicationException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected SharpZipBaseException(SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } +#endif + + /// + /// Initializes a new instance of the SharpZipBaseException class. + /// + public SharpZipBaseException() + { + } + + /// + /// Initializes a new instance of the SharpZipBaseException class with a specified error message. + /// + /// A message describing the exception. + public SharpZipBaseException(string message) + : base(message) + { + } + + /// + /// Initializes a new instance of the SharpZipBaseException class with a specified + /// error message and a reference to the inner exception that is the cause of this exception. + /// + /// A message describing the exception. + /// The inner exception + public SharpZipBaseException(string message, Exception innerException) + : base(message, innerException) + { + } + } +} diff --git a/类库/VersionUpdate/ZIP/Tar/InvalidHeaderException.cs b/类库/VersionUpdate/ZIP/Tar/InvalidHeaderException.cs new file mode 100644 index 0000000..bac9343 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Tar/InvalidHeaderException.cs @@ -0,0 +1,109 @@ +// InvalidHeaderException.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Tar { + + /// + /// This exception is used to indicate that there is a problem + /// with a TAR archive header. + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class InvalidHeaderException : TarException + { + +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected InvalidHeaderException(SerializationInfo information, StreamingContext context) + : base(information, context) + + { + } +#endif + + /// + /// Initialise a new instance of the InvalidHeaderException class. + /// + public InvalidHeaderException() + { + } + + /// + /// Initialises a new instance of the InvalidHeaderException class with a specified message. + /// + /// Message describing the exception cause. + public InvalidHeaderException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of InvalidHeaderException + /// + /// Message describing the problem. + /// The exception that is the cause of the current exception. + public InvalidHeaderException(string message, Exception exception) + : base(message, exception) + { + } + } +} + +/* The original Java file had this header: +** Authored by Timothy Gerard Endres +** +** +** This work has been placed into the public domain. +** You may use this work in any way and for any purpose you wish. +** +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR +** REDISTRIBUTION OF THIS SOFTWARE. +** +*/ + diff --git a/类库/VersionUpdate/ZIP/Tar/TarArchive.cs b/类库/VersionUpdate/ZIP/Tar/TarArchive.cs new file mode 100644 index 0000000..5a5510b --- /dev/null +++ b/类库/VersionUpdate/ZIP/Tar/TarArchive.cs @@ -0,0 +1,894 @@ +// TarArchive.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 28-01-2010 DavidPierson Added IsStreamOwner + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + /// + /// Used to advise clients of 'events' while processing archives + /// + public delegate void ProgressMessageHandler(TarArchive archive, TarEntry entry, string message); + + /// + /// The TarArchive class implements the concept of a + /// 'Tape Archive'. A tar archive is a series of entries, each of + /// which represents a file system object. Each entry in + /// the archive consists of a header block followed by 0 or more data blocks. + /// Directory entries consist only of the header block, and are followed by entries + /// for the directory's contents. File entries consist of a + /// header followed by the number of blocks needed to + /// contain the file's contents. All entries are written on + /// block boundaries. Blocks are 512 bytes long. + /// + /// TarArchives are instantiated in either read or write mode, + /// based upon whether they are instantiated with an InputStream + /// or an OutputStream. Once instantiated TarArchives read/write + /// mode can not be changed. + /// + /// There is currently no support for random access to tar archives. + /// However, it seems that subclassing TarArchive, and using the + /// TarBuffer.CurrentRecord and TarBuffer.CurrentBlock + /// properties, this would be rather trivial. + /// + public class TarArchive : IDisposable + { + /// + /// Client hook allowing detailed information to be reported during processing + /// + public event ProgressMessageHandler ProgressMessageEvent; + + /// + /// Raises the ProgressMessage event + /// + /// The TarEntry for this event + /// message for this event. Null is no message + protected virtual void OnProgressMessageEvent(TarEntry entry, string message) + { + ProgressMessageHandler handler = ProgressMessageEvent; + if (handler != null) { + handler(this, entry, message); + } + } + + #region Constructors + /// + /// Constructor for a default . + /// + protected TarArchive() + { + } + + /// + /// Initalise a TarArchive for input. + /// + /// The to use for input. + protected TarArchive(TarInputStream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + tarIn = stream; + } + + /// + /// Initialise a TarArchive for output. + /// + /// The to use for output. + protected TarArchive(TarOutputStream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + tarOut = stream; + } + #endregion + + #region Static factory methods + /// + /// The InputStream based constructors create a TarArchive for the + /// purposes of extracting or listing a tar archive. Thus, use + /// these constructors when you wish to extract files from or list + /// the contents of an existing tar archive. + /// + /// The stream to retrieve archive data from. + /// Returns a new suitable for reading from. + public static TarArchive CreateInputTarArchive(Stream inputStream) + { + if ( inputStream == null ) { + throw new ArgumentNullException("inputStream"); + } + + TarInputStream tarStream = inputStream as TarInputStream; + + TarArchive result; + if ( tarStream != null ) { + result = new TarArchive(tarStream); + } + else { + result = CreateInputTarArchive(inputStream, TarBuffer.DefaultBlockFactor); + } + return result; + } + + /// + /// Create TarArchive for reading setting block factor + /// + /// A stream containing the tar archive contents + /// The blocking factor to apply + /// Returns a suitable for reading. + public static TarArchive CreateInputTarArchive(Stream inputStream, int blockFactor) + { + if ( inputStream == null ) { + throw new ArgumentNullException("inputStream"); + } + + if ( inputStream is TarInputStream ) { + throw new ArgumentException("TarInputStream not valid"); + } + + return new TarArchive(new TarInputStream(inputStream, blockFactor)); + } + + /// + /// Create a TarArchive for writing to, using the default blocking factor + /// + /// The to write to + /// Returns a suitable for writing. + public static TarArchive CreateOutputTarArchive(Stream outputStream) + { + if ( outputStream == null ) { + throw new ArgumentNullException("outputStream"); + } + + TarOutputStream tarStream = outputStream as TarOutputStream; + + TarArchive result; + if ( tarStream != null ) { + result = new TarArchive(tarStream); + } + else { + result = CreateOutputTarArchive(outputStream, TarBuffer.DefaultBlockFactor); + } + return result; + } + + /// + /// Create a tar archive for writing. + /// + /// The stream to write to + /// The blocking factor to use for buffering. + /// Returns a suitable for writing. + public static TarArchive CreateOutputTarArchive(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) { + throw new ArgumentNullException("outputStream"); + } + + if ( outputStream is TarOutputStream ) { + throw new ArgumentException("TarOutputStream is not valid"); + } + + return new TarArchive(new TarOutputStream(outputStream, blockFactor)); + } + #endregion + + /// + /// Set the flag that determines whether existing files are + /// kept, or overwritten during extraction. + /// + /// + /// If true, do not overwrite existing files. + /// + public void SetKeepOldFiles(bool keepExistingFiles) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + keepOldFiles = keepExistingFiles; + } + + /// + /// Get/set the ascii file translation flag. If ascii file translation + /// is true, then the file is checked to see if it a binary file or not. + /// If the flag is true and the test indicates it is ascii text + /// file, it will be translated. The translation converts the local + /// operating system's concept of line ends into the UNIX line end, + /// '\n', which is the defacto standard for a TAR archive. This makes + /// text files compatible with UNIX. + /// + public bool AsciiTranslate + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return asciiTranslate; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + asciiTranslate = value; + } + + } + + /// + /// Set the ascii file translation flag. + /// + /// + /// If true, translate ascii text files. + /// + [Obsolete("Use the AsciiTranslate property")] + public void SetAsciiTranslation(bool translateAsciiFiles) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + asciiTranslate = translateAsciiFiles; + } + + /// + /// PathPrefix is added to entry names as they are written if the value is not null. + /// A slash character is appended after PathPrefix + /// + public string PathPrefix + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return pathPrefix; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + pathPrefix = value; + } + + } + + /// + /// RootPath is removed from entry names if it is found at the + /// beginning of the name. + /// + public string RootPath + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return rootPath; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + rootPath = value; + } + } + + /// + /// Set user and group information that will be used to fill in the + /// tar archive's entry headers. This information is based on that available + /// for the linux operating system, which is not always available on other + /// operating systems. TarArchive allows the programmer to specify values + /// to be used in their place. + /// is set to true by this call. + /// + /// + /// The user id to use in the headers. + /// + /// + /// The user name to use in the headers. + /// + /// + /// The group id to use in the headers. + /// + /// + /// The group name to use in the headers. + /// + public void SetUserInfo(int userId, string userName, int groupId, string groupName) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + this.userId = userId; + this.userName = userName; + this.groupId = groupId; + this.groupName = groupName; + applyUserInfoOverrides = true; + } + + /// + /// Get or set a value indicating if overrides defined by SetUserInfo should be applied. + /// + /// If overrides are not applied then the values as set in each header will be used. + public bool ApplyUserInfoOverrides + { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return applyUserInfoOverrides; + } + + set { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + applyUserInfoOverrides = value; + } + } + + /// + /// Get the archive user id. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current user id. + /// + public int UserId { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return userId; + } + } + + /// + /// Get the archive user name. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current user name. + /// + public string UserName { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return userName; + } + } + + /// + /// Get the archive group id. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current group id. + /// + public int GroupId { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return groupId; + } + } + + /// + /// Get the archive group name. + /// See ApplyUserInfoOverrides for detail + /// on how to allow setting values on a per entry basis. + /// + /// + /// The current group name. + /// + public string GroupName { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + return groupName; + } + } + + /// + /// Get the archive's record size. Tar archives are composed of + /// a series of RECORDS each containing a number of BLOCKS. + /// This allowed tar archives to match the IO characteristics of + /// the physical device being used. Archives are expected + /// to be properly "blocked". + /// + /// + /// The record size this archive is using. + /// + public int RecordSize { + get { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + if (tarIn != null) { + return tarIn.RecordSize; + } else if (tarOut != null) { + return tarOut.RecordSize; + } + return TarBuffer.DefaultRecordSize; + } + } + + /// + /// Sets the IsStreamOwner property on the underlying stream. + /// Set this to false to prevent the Close of the TarArchive from closing the stream. + /// + public bool IsStreamOwner { + set { + if (tarIn != null) { + tarIn.IsStreamOwner = value; + } else { + tarOut.IsStreamOwner = value; + } + } + } + + /// + /// Close the archive. + /// + [Obsolete("Use Close instead")] + public void CloseArchive() + { + Close(); + } + + /// + /// Perform the "list" command for the archive contents. + /// + /// NOTE That this method uses the progress event to actually list + /// the contents. If the progress display event is not set, nothing will be listed! + /// + public void ListContents() + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + while (true) { + TarEntry entry = tarIn.GetNextEntry(); + + if (entry == null) { + break; + } + OnProgressMessageEvent(entry, null); + } + } + + /// + /// Perform the "extract" command and extract the contents of the archive. + /// + /// + /// The destination directory into which to extract. + /// + public void ExtractContents(string destinationDirectory) + { + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + while (true) { + TarEntry entry = tarIn.GetNextEntry(); + + if (entry == null) { + break; + } + + ExtractEntry(destinationDirectory, entry); + } + } + + /// + /// Extract an entry from the archive. This method assumes that the + /// tarIn stream has been properly set with a call to GetNextEntry(). + /// + /// + /// The destination directory into which to extract. + /// + /// + /// The TarEntry returned by tarIn.GetNextEntry(). + /// + void ExtractEntry(string destDir, TarEntry entry) + { + OnProgressMessageEvent(entry, null); + + string name = entry.Name; + + if (Path.IsPathRooted(name)) { + // NOTE: + // for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt + name = name.Substring(Path.GetPathRoot(name).Length); + } + + name = name.Replace('/', Path.DirectorySeparatorChar); + + string destFile = Path.Combine(destDir, name); + + if (entry.IsDirectory) { + EnsureDirectoryExists(destFile); + } else { + string parentDirectory = Path.GetDirectoryName(destFile); + EnsureDirectoryExists(parentDirectory); + + bool process = true; + FileInfo fileInfo = new FileInfo(destFile); + if (fileInfo.Exists) { + if (keepOldFiles) { + OnProgressMessageEvent(entry, "Destination file already exists"); + process = false; + } else if ((fileInfo.Attributes & FileAttributes.ReadOnly) != 0) { + OnProgressMessageEvent(entry, "Destination file already exists, and is read-only"); + process = false; + } + } + + if (process) { + bool asciiTrans = false; + + Stream outputStream = File.Create(destFile); + if (this.asciiTranslate) { + asciiTrans = !IsBinary(destFile); + } + + StreamWriter outw = null; + if (asciiTrans) { + outw = new StreamWriter(outputStream); + } + + byte[] rdbuf = new byte[32 * 1024]; + + while (true) { + int numRead = tarIn.Read(rdbuf, 0, rdbuf.Length); + + if (numRead <= 0) { + break; + } + + if (asciiTrans) { + for (int off = 0, b = 0; b < numRead; ++b) { + if (rdbuf[b] == 10) { + string s = Encoding.ASCII.GetString(rdbuf, off, (b - off)); + outw.WriteLine(s); + off = b + 1; + } + } + } else { + outputStream.Write(rdbuf, 0, numRead); + } + } + + if (asciiTrans) { + outw.Close(); + } else { + outputStream.Close(); + } + } + } + } + + /// + /// Write an entry to the archive. This method will call the putNextEntry + /// and then write the contents of the entry, and finally call closeEntry() + /// for entries that are files. For directories, it will call putNextEntry(), + /// and then, if the recurse flag is true, process each entry that is a + /// child of the directory. + /// + /// + /// The TarEntry representing the entry to write to the archive. + /// + /// + /// If true, process the children of directory entries. + /// + public void WriteEntry(TarEntry sourceEntry, bool recurse) + { + if ( sourceEntry == null ) { + throw new ArgumentNullException("sourceEntry"); + } + + if ( isDisposed ) { + throw new ObjectDisposedException("TarArchive"); + } + + try + { + if ( recurse ) { + TarHeader.SetValueDefaults(sourceEntry.UserId, sourceEntry.UserName, + sourceEntry.GroupId, sourceEntry.GroupName); + } + WriteEntryCore(sourceEntry, recurse); + } + finally + { + if ( recurse ) { + TarHeader.RestoreSetValues(); + } + } + } + + /// + /// Write an entry to the archive. This method will call the putNextEntry + /// and then write the contents of the entry, and finally call closeEntry() + /// for entries that are files. For directories, it will call putNextEntry(), + /// and then, if the recurse flag is true, process each entry that is a + /// child of the directory. + /// + /// + /// The TarEntry representing the entry to write to the archive. + /// + /// + /// If true, process the children of directory entries. + /// + void WriteEntryCore(TarEntry sourceEntry, bool recurse) + { + string tempFileName = null; + string entryFilename = sourceEntry.File; + + TarEntry entry = (TarEntry)sourceEntry.Clone(); + + if ( applyUserInfoOverrides ) { + entry.GroupId = groupId; + entry.GroupName = groupName; + entry.UserId = userId; + entry.UserName = userName; + } + + OnProgressMessageEvent(entry, null); + + if (asciiTranslate && !entry.IsDirectory) { + + if (!IsBinary(entryFilename)) { + tempFileName = Path.GetTempFileName(); + + using (StreamReader inStream = File.OpenText(entryFilename)) { + using (Stream outStream = File.Create(tempFileName)) { + + while (true) { + string line = inStream.ReadLine(); + if (line == null) { + break; + } + byte[] data = Encoding.ASCII.GetBytes(line); + outStream.Write(data, 0, data.Length); + outStream.WriteByte((byte)'\n'); + } + + outStream.Flush(); + } + } + + entry.Size = new FileInfo(tempFileName).Length; + entryFilename = tempFileName; + } + } + + string newName = null; + + if (rootPath != null) { + if (entry.Name.StartsWith(rootPath)) { + newName = entry.Name.Substring(rootPath.Length + 1 ); + } + } + + if (pathPrefix != null) { + newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName; + } + + if (newName != null) { + entry.Name = newName; + } + + tarOut.PutNextEntry(entry); + + if (entry.IsDirectory) { + if (recurse) { + TarEntry[] list = entry.GetDirectoryEntries(); + for (int i = 0; i < list.Length; ++i) { + WriteEntryCore(list[i], recurse); + } + } + } + else { + using (Stream inputStream = File.OpenRead(entryFilename)) { + byte[] localBuffer = new byte[32 * 1024]; + while (true) { + int numRead = inputStream.Read(localBuffer, 0, localBuffer.Length); + + if (numRead <=0) { + break; + } + + tarOut.Write(localBuffer, 0, numRead); + } + } + + if ( (tempFileName != null) && (tempFileName.Length > 0) ) { + File.Delete(tempFileName); + } + + tarOut.CloseEntry(); + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if ( !isDisposed ) { + isDisposed = true; + if ( disposing ) { + if ( tarOut != null ) { + tarOut.Flush(); + tarOut.Close(); + } + + if ( tarIn != null ) { + tarIn.Close(); + } + } + } + } + + /// + /// Closes the archive and releases any associated resources. + /// + public virtual void Close() + { + Dispose(true); + } + + /// + /// Ensures that resources are freed and other cleanup operations are performed + /// when the garbage collector reclaims the . + /// + ~TarArchive() + { + Dispose(false); + } + + static void EnsureDirectoryExists(string directoryName) + { + if (!Directory.Exists(directoryName)) { + try { + Directory.CreateDirectory(directoryName); + } + catch (Exception e) { + throw new TarException("Exception creating directory '" + directoryName + "', " + e.Message, e); + } + } + } + + // TODO: TarArchive - Is there a better way to test for a text file? + // It no longer reads entire files into memory but is still a weak test! + // This assumes that byte values 0-7, 14-31 or 255 are binary + // and that all non text files contain one of these values + static bool IsBinary(string filename) + { + using (FileStream fs = File.OpenRead(filename)) + { + int sampleSize = Math.Min(4096, (int)fs.Length); + byte[] content = new byte[sampleSize]; + + int bytesRead = fs.Read(content, 0, sampleSize); + + for (int i = 0; i < bytesRead; ++i) { + byte b = content[i]; + if ( (b < 8) || ((b > 13) && (b < 32)) || (b == 255) ) { + return true; + } + } + } + return false; + } + + #region Instance Fields + bool keepOldFiles; + bool asciiTranslate; + + int userId; + string userName = string.Empty; + int groupId; + string groupName = string.Empty; + + string rootPath; + string pathPrefix; + + bool applyUserInfoOverrides; + + TarInputStream tarIn; + TarOutputStream tarOut; + bool isDisposed; + #endregion + } +} + + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ + diff --git a/类库/VersionUpdate/ZIP/Tar/TarBuffer.cs b/类库/VersionUpdate/ZIP/Tar/TarBuffer.cs new file mode 100644 index 0000000..40b8d93 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Tar/TarBuffer.cs @@ -0,0 +1,624 @@ +// TarBuffer.cs +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarBuffer class implements the tar archive concept + /// of a buffered input stream. This concept goes back to the + /// days of blocked tape drives and special io devices. In the + /// C# universe, the only real function that this class + /// performs is to ensure that files have the correct "record" + /// size, or other tars will complain. + ///

+ /// You should never have a need to access this class directly. + /// TarBuffers are created by Tar IO Streams. + ///

+ ///
+ public class TarBuffer + { + +/* A quote from GNU tar man file on blocking and records + A `tar' archive file contains a series of blocks. Each block +contains `BLOCKSIZE' bytes. Although this format may be thought of as +being on magnetic tape, other media are often used. + + Each file archived is represented by a header block which describes +the file, followed by zero or more blocks which give the contents of +the file. At the end of the archive file there may be a block filled +with binary zeros as an end-of-file marker. A reasonable system should +write a block of zeros at the end, but must not assume that such a +block exists when reading an archive. + + The blocks may be "blocked" for physical I/O operations. Each +record of N blocks is written with a single 'write ()' +operation. On magnetic tapes, the result of such a write is a single +record. When writing an archive, the last record of blocks should be +written at the full size, with blocks after the zero block containing +all zeros. When reading an archive, a reasonable system should +properly handle an archive whose last record is shorter than the rest, +or which contains garbage records after a zero block. +*/ + + #region Constants + /// + /// The size of a block in a tar archive in bytes. + /// + /// This is 512 bytes. + public const int BlockSize = 512; + + /// + /// The number of blocks in a default record. + /// + /// + /// The default value is 20 blocks per record. + /// + public const int DefaultBlockFactor = 20; + + /// + /// The size in bytes of a default record. + /// + /// + /// The default size is 10KB. + /// + public const int DefaultRecordSize = BlockSize * DefaultBlockFactor; + #endregion + + /// + /// Get the record size for this buffer + /// + /// The record size in bytes. + /// This is equal to the multiplied by the + public int RecordSize + { + get { + return recordSize; + } + } + + /// + /// Get the TAR Buffer's record size. + /// + /// The record size in bytes. + /// This is equal to the multiplied by the + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return recordSize; + } + + /// + /// Get the Blocking factor for the buffer + /// + /// This is the number of blocks in each record. + public int BlockFactor { + get { + return blockFactor; + } + } + + /// + /// Get the TAR Buffer's block factor + /// + /// The block factor; the number of blocks per record. + [Obsolete("Use BlockFactor property instead")] + public int GetBlockFactor() + { + return blockFactor; + } + + /// + /// Construct a default TarBuffer + /// + protected TarBuffer() + { + } + + /// + /// Create TarBuffer for reading with default BlockFactor + /// + /// Stream to buffer + /// A new suitable for input. + public static TarBuffer CreateInputTarBuffer(Stream inputStream) + { + if ( inputStream == null ) + { + throw new ArgumentNullException("inputStream"); + } + + return CreateInputTarBuffer(inputStream, DefaultBlockFactor); + } + + /// + /// Construct TarBuffer for reading inputStream setting BlockFactor + /// + /// Stream to buffer + /// Blocking factor to apply + /// A new suitable for input. + public static TarBuffer CreateInputTarBuffer(Stream inputStream, int blockFactor) + { + if ( inputStream == null ) + { + throw new ArgumentNullException("inputStream"); + } + + if ( blockFactor <= 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("blockFactor"); +#else + throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative"); +#endif + } + + TarBuffer tarBuffer = new TarBuffer(); + tarBuffer.inputStream = inputStream; + tarBuffer.outputStream = null; + tarBuffer.Initialize(blockFactor); + + return tarBuffer; + } + + /// + /// Construct TarBuffer for writing with default BlockFactor + /// + /// output stream for buffer + /// A new suitable for output. + public static TarBuffer CreateOutputTarBuffer(Stream outputStream) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + return CreateOutputTarBuffer(outputStream, DefaultBlockFactor); + } + + /// + /// Construct TarBuffer for writing Tar output to streams. + /// + /// Output stream to write to. + /// Blocking factor to apply + /// A new suitable for output. + public static TarBuffer CreateOutputTarBuffer(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + if ( blockFactor <= 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("blockFactor"); +#else + throw new ArgumentOutOfRangeException("blockFactor", "Factor cannot be negative"); +#endif + } + + TarBuffer tarBuffer = new TarBuffer(); + tarBuffer.inputStream = null; + tarBuffer.outputStream = outputStream; + tarBuffer.Initialize(blockFactor); + + return tarBuffer; + } + + /// + /// Initialization common to all constructors. + /// + void Initialize(int archiveBlockFactor) + { + blockFactor = archiveBlockFactor; + recordSize = archiveBlockFactor * BlockSize; + recordBuffer = new byte[RecordSize]; + + if (inputStream != null) { + currentRecordIndex = -1; + currentBlockIndex = BlockFactor; + } + else { + currentRecordIndex = 0; + currentBlockIndex = 0; + } + } + + /// + /// Determine if an archive block indicates End of Archive. End of + /// archive is indicated by a block that consists entirely of null bytes. + /// All remaining blocks for the record should also be null's + /// However some older tars only do a couple of null blocks (Old GNU tar for one) + /// and also partial records + /// + /// The data block to check. + /// Returns true if the block is an EOF block; false otherwise. + [Obsolete("Use IsEndOfArchiveBlock instead")] + public bool IsEOFBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if ( block.Length != BlockSize ) + { + throw new ArgumentException("block length is invalid"); + } + + for (int i = 0; i < BlockSize; ++i) { + if (block[i] != 0) { + return false; + } + } + + return true; + } + + + /// + /// Determine if an archive block indicates the End of an Archive has been reached. + /// End of archive is indicated by a block that consists entirely of null bytes. + /// All remaining blocks for the record should also be null's + /// However some older tars only do a couple of null blocks (Old GNU tar for one) + /// and also partial records + /// + /// The data block to check. + /// Returns true if the block is an EOF block; false otherwise. + public static bool IsEndOfArchiveBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if ( block.Length != BlockSize ) { + throw new ArgumentException("block length is invalid"); + } + + for ( int i = 0; i < BlockSize; ++i ) { + if ( block[i] != 0 ) { + return false; + } + } + + return true; + } + + /// + /// Skip over a block on the input stream. + /// + public void SkipBlock() + { + if (inputStream == null) { + throw new TarException("no input stream defined"); + } + + if (currentBlockIndex >= BlockFactor) { + if (!ReadRecord()) { + throw new TarException("Failed to read a record"); + } + } + + currentBlockIndex++; + } + + /// + /// Read a block from the input stream. + /// + /// + /// The block of data read. + /// + public byte[] ReadBlock() + { + if (inputStream == null) { + throw new TarException("TarBuffer.ReadBlock - no input stream defined"); + } + + if (currentBlockIndex >= BlockFactor) { + if (!ReadRecord()) { + throw new TarException("Failed to read a record"); + } + } + + byte[] result = new byte[BlockSize]; + + Array.Copy(recordBuffer, (currentBlockIndex * BlockSize), result, 0, BlockSize ); + currentBlockIndex++; + return result; + } + + /// + /// Read a record from data stream. + /// + /// + /// false if End-Of-File, else true. + /// + bool ReadRecord() + { + if (inputStream == null) { + throw new TarException("no input stream stream defined"); + } + + currentBlockIndex = 0; + + int offset = 0; + int bytesNeeded = RecordSize; + + while (bytesNeeded > 0) { + long numBytes = inputStream.Read(recordBuffer, offset, bytesNeeded); + + // + // NOTE + // We have found EOF, and the record is not full! + // + // This is a broken archive. It does not follow the standard + // blocking algorithm. However, because we are generous, and + // it requires little effort, we will simply ignore the error + // and continue as if the entire record were read. This does + // not appear to break anything upstream. We used to return + // false in this case. + // + // Thanks to 'Yohann.Roussel@alcatel.fr' for this fix. + // + if (numBytes <= 0) { + break; + } + + offset += (int)numBytes; + bytesNeeded -= (int)numBytes; + } + + currentRecordIndex++; + return true; + } + + /// + /// Get the current block number, within the current record, zero based. + /// + /// Block numbers are zero based values + /// + public int CurrentBlock + { + get { return currentBlockIndex; } + } + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner_; } + set { isStreamOwner_ = value; } + } + + /// + /// Get the current block number, within the current record, zero based. + /// + /// + /// The current zero based block number. + /// + /// + /// The absolute block number = (record number * block factor) + block number. + /// + [Obsolete("Use CurrentBlock property instead")] + public int GetCurrentBlockNum() + { + return currentBlockIndex; + } + + /// + /// Get the current record number. + /// + /// + /// The current zero based record number. + /// + public int CurrentRecord + { + get { return currentRecordIndex; } + } + + /// + /// Get the current record number. + /// + /// + /// The current zero based record number. + /// + [Obsolete("Use CurrentRecord property instead")] + public int GetCurrentRecordNum() + { + return currentRecordIndex; + } + + /// + /// Write a block of data to the archive. + /// + /// + /// The data to write to the archive. + /// + public void WriteBlock(byte[] block) + { + if ( block == null ) { + throw new ArgumentNullException("block"); + } + + if (outputStream == null) { + throw new TarException("TarBuffer.WriteBlock - no output stream defined"); + } + + if (block.Length != BlockSize) { + string errorText = string.Format("TarBuffer.WriteBlock - block to write has length '{0}' which is not the block size of '{1}'", + block.Length, BlockSize ); + throw new TarException(errorText); + } + + if (currentBlockIndex >= BlockFactor) { + WriteRecord(); + } + + Array.Copy(block, 0, recordBuffer, (currentBlockIndex * BlockSize), BlockSize); + currentBlockIndex++; + } + + /// + /// Write an archive record to the archive, where the record may be + /// inside of a larger array buffer. The buffer must be "offset plus + /// record size" long. + /// + /// + /// The buffer containing the record data to write. + /// + /// + /// The offset of the record data within buffer. + /// + public void WriteBlock(byte[] buffer, int offset) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if (outputStream == null) { + throw new TarException("TarBuffer.WriteBlock - no output stream stream defined"); + } + + if ( (offset < 0) || (offset >= buffer.Length) ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ((offset + BlockSize) > buffer.Length) { + string errorText = string.Format("TarBuffer.WriteBlock - record has length '{0}' with offset '{1}' which is less than the record size of '{2}'", + buffer.Length, offset, recordSize); + throw new TarException(errorText); + } + + if (currentBlockIndex >= BlockFactor) { + WriteRecord(); + } + + Array.Copy(buffer, offset, recordBuffer, (currentBlockIndex * BlockSize), BlockSize); + + currentBlockIndex++; + } + + /// + /// Write a TarBuffer record to the archive. + /// + void WriteRecord() + { + if (outputStream == null) { + throw new TarException("TarBuffer.WriteRecord no output stream defined"); + } + + outputStream.Write(recordBuffer, 0, RecordSize); + outputStream.Flush(); + + currentBlockIndex = 0; + currentRecordIndex++; + } + + /// + /// WriteFinalRecord writes the current record buffer to output any unwritten data is present. + /// + /// Any trailing bytes are set to zero which is by definition correct behaviour + /// for the end of a tar stream. + void WriteFinalRecord() + { + if (outputStream == null) { + throw new TarException("TarBuffer.WriteFinalRecord no output stream defined"); + } + + if (currentBlockIndex > 0) { + int dataBytes = currentBlockIndex * BlockSize; + Array.Clear(recordBuffer, dataBytes, RecordSize - dataBytes); + WriteRecord(); + } + + outputStream.Flush(); + } + + /// + /// Close the TarBuffer. If this is an output buffer, also flush the + /// current block before closing. + /// + public void Close() + { + if (outputStream != null) { + WriteFinalRecord(); + + if (isStreamOwner_) { + outputStream.Close(); + } + outputStream = null; + } + else if (inputStream != null) { + if (isStreamOwner_) { + inputStream.Close(); + } + inputStream = null; + } + } + + #region Instance Fields + Stream inputStream; + Stream outputStream; + + byte[] recordBuffer; + int currentBlockIndex; + int currentRecordIndex; + + int recordSize = DefaultRecordSize; + int blockFactor = DefaultBlockFactor; + bool isStreamOwner_ = true; + #endregion + } +} + +/* The original Java file had this header: + * + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/VersionUpdate/ZIP/Tar/TarEntry.cs b/类库/VersionUpdate/ZIP/Tar/TarEntry.cs new file mode 100644 index 0000000..a733e32 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Tar/TarEntry.cs @@ -0,0 +1,559 @@ +// TarEntry.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + /// + /// This class represents an entry in a Tar archive. It consists + /// of the entry's header, as well as the entry's File. Entries + /// can be instantiated in one of three ways, depending on how + /// they are to be used. + ///

+ /// TarEntries that are created from the header bytes read from + /// an archive are instantiated with the TarEntry( byte[] ) + /// constructor. These entries will be used when extracting from + /// or listing the contents of an archive. These entries have their + /// header filled in using the header bytes. They also set the File + /// to null, since they reference an archive entry not a file.

+ ///

+ /// TarEntries that are created from files that are to be written + /// into an archive are instantiated with the CreateEntryFromFile(string) + /// pseudo constructor. These entries have their header filled in using + /// the File's information. They also keep a reference to the File + /// for convenience when writing entries.

+ ///

+ /// Finally, TarEntries can be constructed from nothing but a name. + /// This allows the programmer to construct the entry by hand, for + /// instance when only an InputStream is available for writing to + /// the archive, and the header information is constructed from + /// other information. In this case the header fields are set to + /// defaults and the File is set to null.

+ /// + ///
+ public class TarEntry : ICloneable + { + #region Constructors + /// + /// Initialise a default instance of . + /// + private TarEntry() + { + header = new TarHeader(); + } + + /// + /// Construct an entry from an archive's header bytes. File is set + /// to null. + /// + /// + /// The header bytes from a tar archive entry. + /// + public TarEntry(byte[] headerBuffer) + { + header = new TarHeader(); + header.ParseBuffer(headerBuffer); + } + + /// + /// Construct a TarEntry using the header provided + /// + /// Header details for entry + public TarEntry(TarHeader header) + { + if ( header == null ) + { + throw new ArgumentNullException("header"); + } + + this.header = (TarHeader)header.Clone(); + } + #endregion + + #region ICloneable Members + /// + /// Clone this tar entry. + /// + /// Returns a clone of this entry. + public object Clone() + { + TarEntry entry = new TarEntry(); + entry.file = file; + entry.header = (TarHeader)header.Clone(); + entry.Name = Name; + return entry; + } + #endregion + + /// + /// Construct an entry with only a name. + /// This allows the programmer to construct the entry's header "by hand". + /// + /// The name to use for the entry + /// Returns the newly created + public static TarEntry CreateTarEntry(string name) + { + TarEntry entry = new TarEntry(); + TarEntry.NameTarHeader(entry.header, name); + return entry; + } + + /// + /// Construct an entry for a file. File is set to file, and the + /// header is constructed from information from the file. + /// + /// The file name that the entry represents. + /// Returns the newly created + public static TarEntry CreateEntryFromFile(string fileName) + { + TarEntry entry = new TarEntry(); + entry.GetFileTarHeader(entry.header, fileName); + return entry; + } + + /// + /// Determine if the two entries are equal. Equality is determined + /// by the header names being equal. + /// + /// The to compare with the current Object. + /// + /// True if the entries are equal; false if not. + /// + public override bool Equals(object obj) + { + TarEntry localEntry = obj as TarEntry; + + if ( localEntry != null ) + { + return Name.Equals(localEntry.Name); + } + return false; + } + + /// + /// Derive a Hash value for the current + /// + /// A Hash code for the current + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + /// Determine if the given entry is a descendant of this entry. + /// Descendancy is determined by the name of the descendant + /// starting with this entry's name. + /// + /// + /// Entry to be checked as a descendent of this. + /// + /// + /// True if entry is a descendant of this. + /// + public bool IsDescendent(TarEntry toTest) + { + if ( toTest == null ) { + throw new ArgumentNullException("toTest"); + } + + return toTest.Name.StartsWith(Name); + } + + /// + /// Get this entry's header. + /// + /// + /// This entry's TarHeader. + /// + public TarHeader TarHeader + { + get { + return header; + } + } + + /// + /// Get/Set this entry's name. + /// + public string Name + { + get { + return header.Name; + } + set { + header.Name = value; + } + } + + /// + /// Get/set this entry's user id. + /// + public int UserId + { + get { + return header.UserId; + } + set { + header.UserId = value; + } + } + + /// + /// Get/set this entry's group id. + /// + public int GroupId + { + get { + return header.GroupId; + } + set { + header.GroupId = value; + } + } + + /// + /// Get/set this entry's user name. + /// + public string UserName + { + get { + return header.UserName; + } + set { + header.UserName = value; + } + } + + /// + /// Get/set this entry's group name. + /// + public string GroupName + { + get { + return header.GroupName; + } + set { + header.GroupName = value; + } + } + + /// + /// Convenience method to set this entry's group and user ids. + /// + /// + /// This entry's new user id. + /// + /// + /// This entry's new group id. + /// + public void SetIds(int userId, int groupId) + { + UserId = userId; + GroupId = groupId; + } + + /// + /// Convenience method to set this entry's group and user names. + /// + /// + /// This entry's new user name. + /// + /// + /// This entry's new group name. + /// + public void SetNames(string userName, string groupName) + { + UserName = userName; + GroupName = groupName; + } + + /// + /// Get/Set the modification time for this entry + /// + public DateTime ModTime { + get { + return header.ModTime; + } + set { + header.ModTime = value; + } + } + + /// + /// Get this entry's file. + /// + /// + /// This entry's file. + /// + public string File { + get { + return file; + } + } + + /// + /// Get/set this entry's recorded file size. + /// + public long Size { + get { + return header.Size; + } + set { + header.Size = value; + } + } + + /// + /// Return true if this entry represents a directory, false otherwise + /// + /// + /// True if this entry is a directory. + /// + public bool IsDirectory { + get { + if (file != null) { + return Directory.Exists(file); + } + + if (header != null) { + if ((header.TypeFlag == TarHeader.LF_DIR) || Name.EndsWith( "/" )) { + return true; + } + } + return false; + } + } + + /// + /// Fill in a TarHeader with information from a File. + /// + /// + /// The TarHeader to fill in. + /// + /// + /// The file from which to get the header information. + /// + public void GetFileTarHeader(TarHeader header, string file) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( file == null ) { + throw new ArgumentNullException("file"); + } + + this.file = file; + + // bugfix from torhovl from #D forum: + string name = file; + +#if !NETCF_1_0 && !NETCF_2_0 + // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory + if (name.IndexOf(Environment.CurrentDirectory) == 0) { + name = name.Substring(Environment.CurrentDirectory.Length); + } +#endif + +/* + if (Path.DirectorySeparatorChar == '\\') + { + // check if the OS is Windows + // Strip off drive letters! + if (name.Length > 2) + { + char ch1 = name[0]; + char ch2 = name[1]; + + if (ch2 == ':' && Char.IsLetter(ch1)) + { + name = name.Substring(2); + } + } + } +*/ + + name = name.Replace(Path.DirectorySeparatorChar, '/'); + + // No absolute pathnames + // Windows (and Posix?) paths can start with UNC style "\\NetworkDrive\", + // so we loop on starting /'s. + while (name.StartsWith("/")) { + name = name.Substring(1); + } + + header.LinkName = String.Empty; + header.Name = name; + + if (Directory.Exists(file)) { + header.Mode = 1003; // Magic number for security access for a UNIX filesystem + header.TypeFlag = TarHeader.LF_DIR; + if ( (header.Name.Length == 0) || header.Name[header.Name.Length - 1] != '/') { + header.Name = header.Name + "/"; + } + + header.Size = 0; + } else { + header.Mode = 33216; // Magic number for security access for a UNIX filesystem + header.TypeFlag = TarHeader.LF_NORMAL; + header.Size = new FileInfo(file.Replace('/', Path.DirectorySeparatorChar)).Length; + } + + header.ModTime = System.IO.File.GetLastWriteTime(file.Replace('/', Path.DirectorySeparatorChar)).ToUniversalTime(); + header.DevMajor = 0; + header.DevMinor = 0; + } + + /// + /// Get entries for all files present in this entries directory. + /// If this entry doesnt represent a directory zero entries are returned. + /// + /// + /// An array of TarEntry's for this entry's children. + /// + public TarEntry[] GetDirectoryEntries() + { + if ( (file == null) || !Directory.Exists(file)) { + return new TarEntry[0]; + } + + string[] list = Directory.GetFileSystemEntries(file); + TarEntry[] result = new TarEntry[list.Length]; + + for (int i = 0; i < list.Length; ++i) { + result[i] = TarEntry.CreateEntryFromFile(list[i]); + } + + return result; + } + + /// + /// Write an entry's header information to a header buffer. + /// + /// + /// The tar entry header buffer to fill in. + /// + public void WriteEntryHeader(byte[] outBuffer) + { + header.WriteHeader(outBuffer); + } + + /// + /// Convenience method that will modify an entry's name directly + /// in place in an entry header buffer byte array. + /// + /// + /// The buffer containing the entry header to modify. + /// + /// + /// The new name to place into the header buffer. + /// + static public void AdjustEntryName(byte[] buffer, string newName) + { + TarHeader.GetNameBytes(newName, buffer, 0, TarHeader.NAMELEN); + } + + /// + /// Fill in a TarHeader given only the entry's name. + /// + /// + /// The TarHeader to fill in. + /// + /// + /// The tar entry name. + /// + static public void NameTarHeader(TarHeader header, string name) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + bool isDir = name.EndsWith("/"); + + header.Name = name; + header.Mode = isDir ? 1003 : 33216; + header.UserId = 0; + header.GroupId = 0; + header.Size = 0; + + header.ModTime = DateTime.UtcNow; + + header.TypeFlag = isDir ? TarHeader.LF_DIR : TarHeader.LF_NORMAL; + + header.LinkName = String.Empty; + header.UserName = String.Empty; + header.GroupName = String.Empty; + + header.DevMajor = 0; + header.DevMinor = 0; + } + + #region Instance Fields + /// + /// The name of the file this entry represents or null if the entry is not based on a file. + /// + string file; + + /// + /// The entry's header information. + /// + TarHeader header; + #endregion + } +} + + + +/* The original Java file had this header: + * + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/VersionUpdate/ZIP/Tar/TarException.cs b/类库/VersionUpdate/ZIP/Tar/TarException.cs new file mode 100644 index 0000000..84a6eba --- /dev/null +++ b/类库/VersionUpdate/ZIP/Tar/TarException.cs @@ -0,0 +1,91 @@ +// TarException.cs +// +// Copyright 2004 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Tar { + + /// + /// TarExceptions are used for exceptions specific to tar classes and code. + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class TarException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected TarException(SerializationInfo info, StreamingContext context) + : base(info, context) + + { + } +#endif + + /// + /// Initialises a new instance of the TarException class. + /// + public TarException() + { + } + + /// + /// Initialises a new instance of the TarException class with a specified message. + /// + /// The message that describes the error. + public TarException(string message) + : base(message) + { + } + + /// + /// + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public TarException(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/VersionUpdate/ZIP/Tar/TarHeader.cs b/类库/VersionUpdate/ZIP/Tar/TarHeader.cs new file mode 100644 index 0000000..fc49f16 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Tar/TarHeader.cs @@ -0,0 +1,1156 @@ +// TarHeader.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +/* The tar format and its POSIX successor PAX have a long history which makes for compatability + issues when creating and reading files. + + This is further complicated by a large number of programs with variations on formats + One common issue is the handling of names longer than 100 characters. + GNU style long names are currently supported. + +This is the ustar (Posix 1003.1) header. + +struct header +{ + char t_name[100]; // 0 Filename + char t_mode[8]; // 100 Permissions + char t_uid[8]; // 108 Numerical User ID + char t_gid[8]; // 116 Numerical Group ID + char t_size[12]; // 124 Filesize + char t_mtime[12]; // 136 st_mtime + char t_chksum[8]; // 148 Checksum + char t_typeflag; // 156 Type of File + char t_linkname[100]; // 157 Target of Links + char t_magic[6]; // 257 "ustar" or other... + char t_version[2]; // 263 Version fixed to 00 + char t_uname[32]; // 265 User Name + char t_gname[32]; // 297 Group Name + char t_devmajor[8]; // 329 Major for devices + char t_devminor[8]; // 337 Minor for devices + char t_prefix[155]; // 345 Prefix for t_name + char t_mfill[12]; // 500 Filler up to 512 +}; + +*/ + +using System; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + + /// + /// This class encapsulates the Tar Entry Header used in Tar Archives. + /// The class also holds a number of tar constants, used mostly in headers. + /// + public class TarHeader : ICloneable + { + #region Constants + /// + /// The length of the name field in a header buffer. + /// + public const int NAMELEN = 100; + + /// + /// The length of the mode field in a header buffer. + /// + public const int MODELEN = 8; + + /// + /// The length of the user id field in a header buffer. + /// + public const int UIDLEN = 8; + + /// + /// The length of the group id field in a header buffer. + /// + public const int GIDLEN = 8; + + /// + /// The length of the checksum field in a header buffer. + /// + public const int CHKSUMLEN = 8; + + /// + /// Offset of checksum in a header buffer. + /// + public const int CHKSUMOFS = 148; + + /// + /// The length of the size field in a header buffer. + /// + public const int SIZELEN = 12; + + /// + /// The length of the magic field in a header buffer. + /// + public const int MAGICLEN = 6; + + /// + /// The length of the version field in a header buffer. + /// + public const int VERSIONLEN = 2; + + /// + /// The length of the modification time field in a header buffer. + /// + public const int MODTIMELEN = 12; + + /// + /// The length of the user name field in a header buffer. + /// + public const int UNAMELEN = 32; + + /// + /// The length of the group name field in a header buffer. + /// + public const int GNAMELEN = 32; + + /// + /// The length of the devices field in a header buffer. + /// + public const int DEVLEN = 8; + + // + // LF_ constants represent the "type" of an entry + // + + /// + /// The "old way" of indicating a normal file. + /// + public const byte LF_OLDNORM = 0; + + /// + /// Normal file type. + /// + public const byte LF_NORMAL = (byte) '0'; + + /// + /// Link file type. + /// + public const byte LF_LINK = (byte) '1'; + + /// + /// Symbolic link file type. + /// + public const byte LF_SYMLINK = (byte) '2'; + + /// + /// Character device file type. + /// + public const byte LF_CHR = (byte) '3'; + + /// + /// Block device file type. + /// + public const byte LF_BLK = (byte) '4'; + + /// + /// Directory file type. + /// + public const byte LF_DIR = (byte) '5'; + + /// + /// FIFO (pipe) file type. + /// + public const byte LF_FIFO = (byte) '6'; + + /// + /// Contiguous file type. + /// + public const byte LF_CONTIG = (byte) '7'; + + /// + /// Posix.1 2001 global extended header + /// + public const byte LF_GHDR = (byte) 'g'; + + /// + /// Posix.1 2001 extended header + /// + public const byte LF_XHDR = (byte) 'x'; + + // POSIX allows for upper case ascii type as extensions + + /// + /// Solaris access control list file type + /// + public const byte LF_ACL = (byte) 'A'; + + /// + /// GNU dir dump file type + /// This is a dir entry that contains the names of files that were in the + /// dir at the time the dump was made + /// + public const byte LF_GNU_DUMPDIR = (byte) 'D'; + + /// + /// Solaris Extended Attribute File + /// + public const byte LF_EXTATTR = (byte) 'E' ; + + /// + /// Inode (metadata only) no file content + /// + public const byte LF_META = (byte) 'I'; + + /// + /// Identifies the next file on the tape as having a long link name + /// + public const byte LF_GNU_LONGLINK = (byte) 'K'; + + /// + /// Identifies the next file on the tape as having a long name + /// + public const byte LF_GNU_LONGNAME = (byte) 'L'; + + /// + /// Continuation of a file that began on another volume + /// + public const byte LF_GNU_MULTIVOL = (byte) 'M'; + + /// + /// For storing filenames that dont fit in the main header (old GNU) + /// + public const byte LF_GNU_NAMES = (byte) 'N'; + + /// + /// GNU Sparse file + /// + public const byte LF_GNU_SPARSE = (byte) 'S'; + + /// + /// GNU Tape/volume header ignore on extraction + /// + public const byte LF_GNU_VOLHDR = (byte) 'V'; + + /// + /// The magic tag representing a POSIX tar archive. (includes trailing NULL) + /// + public const string TMAGIC = "ustar "; + + /// + /// The magic tag representing an old GNU tar archive where version is included in magic and overwrites it + /// + public const string GNU_TMAGIC = "ustar "; + + const long timeConversionFactor = 10000000L; // 1 tick == 100 nanoseconds + readonly static DateTime dateTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0); + #endregion + + #region Constructors + + /// + /// Initialise a default TarHeader instance + /// + public TarHeader() + { + Magic = TMAGIC; + Version = " "; + + Name = ""; + LinkName = ""; + + UserId = defaultUserId; + GroupId = defaultGroupId; + UserName = defaultUser; + GroupName = defaultGroupName; + Size = 0; + } + + #endregion + + #region Properties + /// + /// Get/set the name for this tar entry. + /// + /// Thrown when attempting to set the property to null. + public string Name + { + get { return name; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + name = value; + } + } + + /// + /// Get the name of this entry. + /// + /// The entry's name. + [Obsolete("Use the Name property instead", true)] + public string GetName() + { + return name; + } + + /// + /// Get/set the entry's Unix style permission mode. + /// + public int Mode + { + get { return mode; } + set { mode = value; } + } + + + /// + /// The entry's user id. + /// + /// + /// This is only directly relevant to unix systems. + /// The default is zero. + /// + public int UserId + { + get { return userId; } + set { userId = value; } + } + + + /// + /// Get/set the entry's group id. + /// + /// + /// This is only directly relevant to linux/unix systems. + /// The default value is zero. + /// + public int GroupId + { + get { return groupId; } + set { groupId = value; } + } + + + /// + /// Get/set the entry's size. + /// + /// Thrown when setting the size to less than zero. + public long Size + { + get { return size; } + set { + if ( value < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "Cannot be less than zero"); +#endif + } + size = value; + } + } + + + /// + /// Get/set the entry's modification time. + /// + /// + /// The modification time is only accurate to within a second. + /// + /// Thrown when setting the date time to less than 1/1/1970. + public DateTime ModTime + { + get { return modTime; } + set { + if ( value < dateTime1970 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "ModTime cannot be before Jan 1st 1970"); +#endif + } + modTime = new DateTime(value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second); + } + } + + + /// + /// Get the entry's checksum. This is only valid/updated after writing or reading an entry. + /// + public int Checksum + { + get { return checksum; } + } + + + /// + /// Get value of true if the header checksum is valid, false otherwise. + /// + public bool IsChecksumValid + { + get { return isChecksumValid; } + } + + + /// + /// Get/set the entry's type flag. + /// + public byte TypeFlag + { + get { return typeFlag; } + set { typeFlag = value; } + } + + + /// + /// The entry's link name. + /// + /// Thrown when attempting to set LinkName to null. + public string LinkName + { + get { return linkName; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + linkName = value; + } + } + + + /// + /// Get/set the entry's magic tag. + /// + /// Thrown when attempting to set Magic to null. + public string Magic + { + get { return magic; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + magic = value; + } + } + + + /// + /// The entry's version. + /// + /// Thrown when attempting to set Version to null. + public string Version + { + get { + return version; + } + + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + version = value; + } + } + + + /// + /// The entry's user name. + /// + public string UserName + { + get { return userName; } + set { + if (value != null) { + userName = value.Substring(0, Math.Min(UNAMELEN, value.Length)); + } + else { +#if NETCF_1_0 || NETCF_2_0 + string currentUser = "PocketPC"; +#else + string currentUser = Environment.UserName; +#endif + if (currentUser.Length > UNAMELEN) { + currentUser = currentUser.Substring(0, UNAMELEN); + } + userName = currentUser; + } + } + } + + + /// + /// Get/set the entry's group name. + /// + /// + /// This is only directly relevant to unix systems. + /// + public string GroupName + { + get { return groupName; } + set { + if ( value == null ) { + groupName = "None"; + } + else { + groupName = value; + } + } + } + + + /// + /// Get/set the entry's major device number. + /// + public int DevMajor + { + get { return devMajor; } + set { devMajor = value; } + } + + + /// + /// Get/set the entry's minor device number. + /// + public int DevMinor + { + get { return devMinor; } + set { devMinor = value; } + } + + #endregion + + #region ICloneable Members + /// + /// Create a new that is a copy of the current instance. + /// + /// A new that is a copy of the current instance. + public object Clone() + { + return MemberwiseClone(); + } + #endregion + + /// + /// Parse TarHeader information from a header buffer. + /// + /// + /// The tar entry header buffer to get information from. + /// + public void ParseBuffer(byte[] header) + { + if ( header == null ) + { + throw new ArgumentNullException("header"); + } + + int offset = 0; + + name = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString(); + offset += TarHeader.NAMELEN; + + mode = (int)TarHeader.ParseOctal(header, offset, TarHeader.MODELEN); + offset += TarHeader.MODELEN; + + UserId = (int)TarHeader.ParseOctal(header, offset, TarHeader.UIDLEN); + offset += TarHeader.UIDLEN; + + GroupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN); + offset += TarHeader.GIDLEN; + + Size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN); + offset += TarHeader.SIZELEN; + + ModTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN)); + offset += TarHeader.MODTIMELEN; + + checksum = (int)TarHeader.ParseOctal(header, offset, TarHeader.CHKSUMLEN); + offset += TarHeader.CHKSUMLEN; + + TypeFlag = header[ offset++ ]; + + LinkName = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString(); + offset += TarHeader.NAMELEN; + + Magic = TarHeader.ParseName(header, offset, TarHeader.MAGICLEN).ToString(); + offset += TarHeader.MAGICLEN; + + Version = TarHeader.ParseName(header, offset, TarHeader.VERSIONLEN).ToString(); + offset += TarHeader.VERSIONLEN; + + UserName = TarHeader.ParseName(header, offset, TarHeader.UNAMELEN).ToString(); + offset += TarHeader.UNAMELEN; + + GroupName = TarHeader.ParseName(header, offset, TarHeader.GNAMELEN).ToString(); + offset += TarHeader.GNAMELEN; + + DevMajor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN); + offset += TarHeader.DEVLEN; + + DevMinor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN); + + // Fields past this point not currently parsed or used... + + isChecksumValid = Checksum == TarHeader.MakeCheckSum(header); + } + + /// + /// 'Write' header information to buffer provided, updating the check sum. + /// + /// output buffer for header information + public void WriteHeader(byte[] outBuffer) + { + if ( outBuffer == null ) + { + throw new ArgumentNullException("outBuffer"); + } + + int offset = 0; + + offset = GetNameBytes(Name, outBuffer, offset, NAMELEN); + offset = GetOctalBytes(mode, outBuffer, offset, MODELEN); + offset = GetOctalBytes(UserId, outBuffer, offset, UIDLEN); + offset = GetOctalBytes(GroupId, outBuffer, offset, GIDLEN); + + offset = GetLongOctalBytes(Size, outBuffer, offset, SIZELEN); + offset = GetLongOctalBytes(GetCTime(ModTime), outBuffer, offset, MODTIMELEN); + + int csOffset = offset; + for (int c = 0; c < CHKSUMLEN; ++c) + { + outBuffer[offset++] = (byte)' '; + } + + outBuffer[offset++] = TypeFlag; + + offset = GetNameBytes(LinkName, outBuffer, offset, NAMELEN); + offset = GetAsciiBytes(Magic, 0, outBuffer, offset, MAGICLEN); + offset = GetNameBytes(Version, outBuffer, offset, VERSIONLEN); + offset = GetNameBytes(UserName, outBuffer, offset, UNAMELEN); + offset = GetNameBytes(GroupName, outBuffer, offset, GNAMELEN); + + if ((TypeFlag == LF_CHR) || (TypeFlag == LF_BLK)) + { + offset = GetOctalBytes(DevMajor, outBuffer, offset, DEVLEN); + offset = GetOctalBytes(DevMinor, outBuffer, offset, DEVLEN); + } + + for ( ; offset < outBuffer.Length; ) + { + outBuffer[offset++] = 0; + } + + checksum = ComputeCheckSum(outBuffer); + + GetCheckSumOctalBytes(checksum, outBuffer, csOffset, CHKSUMLEN); + isChecksumValid = true; + } + + /// + /// Get a hash code for the current object. + /// + /// A hash code for the current object. + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + /// + /// Determines if this instance is equal to the specified object. + /// + /// The object to compare with. + /// true if the objects are equal, false otherwise. + public override bool Equals(object obj) + { + TarHeader localHeader = obj as TarHeader; + + bool result; + if ( localHeader != null ) + { + result = (name == localHeader.name) + && (mode == localHeader.mode) + && (UserId == localHeader.UserId) + && (GroupId == localHeader.GroupId) + && (Size == localHeader.Size) + && (ModTime == localHeader.ModTime) + && (Checksum == localHeader.Checksum) + && (TypeFlag == localHeader.TypeFlag) + && (LinkName == localHeader.LinkName) + && (Magic == localHeader.Magic) + && (Version == localHeader.Version) + && (UserName == localHeader.UserName) + && (GroupName == localHeader.GroupName) + && (DevMajor == localHeader.DevMajor) + && (DevMinor == localHeader.DevMinor); + } + else + { + result = false; + } + return result; + } + + /// + /// Set defaults for values used when constructing a TarHeader instance. + /// + /// Value to apply as a default for userId. + /// Value to apply as a default for userName. + /// Value to apply as a default for groupId. + /// Value to apply as a default for groupName. + static internal void SetValueDefaults(int userId, string userName, int groupId, string groupName) + { + defaultUserId = userIdAsSet = userId; + defaultUser = userNameAsSet = userName; + defaultGroupId = groupIdAsSet = groupId; + defaultGroupName = groupNameAsSet = groupName; + } + + static internal void RestoreSetValues() + { + defaultUserId = userIdAsSet; + defaultUser = userNameAsSet; + defaultGroupId = groupIdAsSet; + defaultGroupName = groupNameAsSet; + } + + /// + /// Parse an octal string from a header buffer. + /// + /// The header buffer from which to parse. + /// The offset into the buffer from which to parse. + /// The number of header bytes to parse. + /// The long equivalent of the octal string. + static public long ParseOctal(byte[] header, int offset, int length) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + long result = 0; + bool stillPadding = true; + + int end = offset + length; + for (int i = offset; i < end ; ++i) { + if (header[i] == 0) { + break; + } + + if (header[i] == (byte)' ' || header[i] == '0') { + if (stillPadding) { + continue; + } + + if (header[i] == (byte)' ') { + break; + } + } + + stillPadding = false; + + result = (result << 3) + (header[i] - '0'); + } + + return result; + } + + /// + /// Parse a name from a header buffer. + /// + /// + /// The header buffer from which to parse. + /// + /// + /// The offset into the buffer from which to parse. + /// + /// + /// The number of header bytes to parse. + /// + /// + /// The name parsed. + /// + static public StringBuilder ParseName(byte[] header, int offset, int length) + { + if ( header == null ) { + throw new ArgumentNullException("header"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be less than zero"); +#endif + } + + if ( length < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("length"); +#else + throw new ArgumentOutOfRangeException("length", "Cannot be less than zero"); +#endif + } + + if ( offset + length > header.Length ) + { + throw new ArgumentException("Exceeds header size", "length"); + } + + StringBuilder result = new StringBuilder(length); + + for (int i = offset; i < offset + length; ++i) { + if (header[i] == 0) { + break; + } + result.Append((char)header[i]); + } + + return result; + } + + /// + /// Add name to the buffer as a collection of bytes + /// + /// The name to add + /// The offset of the first character + /// The buffer to add to + /// The index of the first byte to add + /// The number of characters/bytes to add + /// The next free index in the + public static int GetNameBytes(StringBuilder name, int nameOffset, byte[] buffer, int bufferOffset, int length) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name.ToString(), nameOffset, buffer, bufferOffset, length); + } + + /// + /// Add name to the buffer as a collection of bytes + /// + /// The name to add + /// The offset of the first character + /// The buffer to add to + /// The index of the first byte to add + /// The number of characters/bytes to add + /// The next free index in the + public static int GetNameBytes(string name, int nameOffset, byte[] buffer, int bufferOffset, int length) + { + if ( name == null ) + { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + int i; + + for (i = 0 ; i < length - 1 && nameOffset + i < name.Length; ++i) { + buffer[bufferOffset + i] = (byte)name[nameOffset + i]; + } + + for (; i < length ; ++i) { + buffer[bufferOffset + i] = 0; + } + + return bufferOffset + length; + } + + /// + /// Add an entry name to the buffer + /// + /// + /// The name to add + /// + /// + /// The buffer to add to + /// + /// + /// The offset into the buffer from which to start adding + /// + /// + /// The number of header bytes to add + /// + /// + /// The index of the next free byte in the buffer + /// + public static int GetNameBytes(StringBuilder name, byte[] buffer, int offset, int length) + { + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name.ToString(), 0, buffer, offset, length); + } + + /// + /// Add an entry name to the buffer + /// + /// The name to add + /// The buffer to add to + /// The offset into the buffer from which to start adding + /// The number of header bytes to add + /// The index of the next free byte in the buffer + public static int GetNameBytes(string name, byte[] buffer, int offset, int length) + { + + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + return GetNameBytes(name, 0, buffer, offset, length); + } + + /// + /// Add a string to a buffer as a collection of ascii bytes. + /// + /// The string to add + /// The offset of the first character to add. + /// The buffer to add to. + /// The offset to start adding at. + /// The number of ascii characters to add. + /// The next free index in the buffer. + public static int GetAsciiBytes(string toAdd, int nameOffset, byte[] buffer, int bufferOffset, int length ) + { + if ( toAdd == null ) { + throw new ArgumentNullException("toAdd"); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + for (int i = 0 ; i < length && nameOffset + i < toAdd.Length; ++i) + { + buffer[bufferOffset + i] = (byte)toAdd[nameOffset + i]; + } + return bufferOffset + length; + } + + /// + /// Put an octal representation of a value into a buffer + /// + /// + /// the value to be converted to octal + /// + /// + /// buffer to store the octal string + /// + /// + /// The offset into the buffer where the value starts + /// + /// + /// The length of the octal string to create + /// + /// + /// The offset of the character next byte after the octal string + /// + public static int GetOctalBytes(long value, byte[] buffer, int offset, int length) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + int localIndex = length - 1; + + // Either a space or null is valid here. We use NULL as per GNUTar + buffer[offset + localIndex] = 0; + --localIndex; + + if (value > 0) { + for ( long v = value; (localIndex >= 0) && (v > 0); --localIndex ) { + buffer[offset + localIndex] = (byte)((byte)'0' + (byte)(v & 7)); + v >>= 3; + } + } + + for ( ; localIndex >= 0; --localIndex ) { + buffer[offset + localIndex] = (byte)'0'; + } + + return offset + length; + } + + /// + /// Put an octal representation of a value into a buffer + /// + /// Value to be convert to octal + /// The buffer to update + /// The offset into the buffer to store the value + /// The length of the octal string + /// Index of next byte + public static int GetLongOctalBytes(long value, byte[] buffer, int offset, int length) + { + return GetOctalBytes(value, buffer, offset, length); + } + + /// + /// Add the checksum integer to header buffer. + /// + /// + /// The header buffer to set the checksum for + /// The offset into the buffer for the checksum + /// The number of header bytes to update. + /// It's formatted differently from the other fields: it has 6 digits, a + /// null, then a space -- rather than digits, a space, then a null. + /// The final space is already there, from checksumming + /// + /// The modified buffer offset + static int GetCheckSumOctalBytes(long value, byte[] buffer, int offset, int length) + { + TarHeader.GetOctalBytes(value, buffer, offset, length - 1); + return offset + length; + } + + /// + /// Compute the checksum for a tar entry header. + /// The checksum field must be all spaces prior to this happening + /// + /// The tar entry's header buffer. + /// The computed checksum. + static int ComputeCheckSum(byte[] buffer) + { + int sum = 0; + for (int i = 0; i < buffer.Length; ++i) { + sum += buffer[i]; + } + return sum; + } + + /// + /// Make a checksum for a tar entry ignoring the checksum contents. + /// + /// The tar entry's header buffer. + /// The checksum for the buffer + static int MakeCheckSum(byte[] buffer) + { + int sum = 0; + for ( int i = 0; i < CHKSUMOFS; ++i ) + { + sum += buffer[i]; + } + + for ( int i = 0; i < TarHeader.CHKSUMLEN; ++i) + { + sum += (byte)' '; + } + + for (int i = CHKSUMOFS + CHKSUMLEN; i < buffer.Length; ++i) + { + sum += buffer[i]; + } + return sum; + } + + static int GetCTime(System.DateTime dateTime) + { + return unchecked((int)((dateTime.Ticks - dateTime1970.Ticks) / timeConversionFactor)); + } + + static DateTime GetDateTimeFromCTime(long ticks) + { + DateTime result; + + try { + result = new DateTime(dateTime1970.Ticks + ticks * timeConversionFactor); + } + catch(ArgumentOutOfRangeException) { + result = dateTime1970; + } + return result; + } + + #region Instance Fields + string name; + int mode; + int userId; + int groupId; + long size; + DateTime modTime; + int checksum; + bool isChecksumValid; + byte typeFlag; + string linkName; + string magic; + string version; + string userName; + string groupName; + int devMajor; + int devMinor; + #endregion + + #region Class Fields + // Values used during recursive operations. + static internal int userIdAsSet; + static internal int groupIdAsSet; + static internal string userNameAsSet; + static internal string groupNameAsSet = "None"; + + static internal int defaultUserId; + static internal int defaultGroupId; + static internal string defaultGroupName = "None"; + static internal string defaultUser; + #endregion + } +} + +/* The original Java file had this header: + * +** Authored by Timothy Gerard Endres +** +** +** This work has been placed into the public domain. +** You may use this work in any way and for any purpose you wish. +** +** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, +** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR +** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY +** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR +** REDISTRIBUTION OF THIS SOFTWARE. +** +*/ diff --git a/类库/VersionUpdate/ZIP/Tar/TarInputStream.cs b/类库/VersionUpdate/ZIP/Tar/TarInputStream.cs new file mode 100644 index 0000000..436b002 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Tar/TarInputStream.cs @@ -0,0 +1,695 @@ +// TarInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarInputStream reads a UNIX tar archive as an InputStream. + /// methods are provided to position at each successive entry in + /// the archive, and the read each entry as a normal input stream + /// using read(). + /// + public class TarInputStream : Stream + { + #region Constructors + /// + /// Construct a TarInputStream with default block factor + /// + /// stream to source data from + public TarInputStream(Stream inputStream) + : this(inputStream, TarBuffer.DefaultBlockFactor) + { + } + + /// + /// Construct a TarInputStream with user specified block factor + /// + /// stream to source data from + /// block factor to apply to archive + public TarInputStream(Stream inputStream, int blockFactor) + { + this.inputStream = inputStream; + tarBuffer = TarBuffer.CreateInputTarBuffer(inputStream, blockFactor); + } + + #endregion + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return tarBuffer.IsStreamOwner; } + set { tarBuffer.IsStreamOwner = value; } + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return inputStream.CanRead; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking + /// This property always returns false. + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value indicating if the stream supports writing. + /// This property always returns false. + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// The length in bytes of the stream + /// + public override long Length { + get { + return inputStream.Length; + } + } + + /// + /// Gets or sets the position within the stream. + /// Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException + /// + /// Any attempt to set position + public override long Position { + get { + return inputStream.Position; + } + set { + throw new NotSupportedException("TarInputStream Seek not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + inputStream.Flush(); + } + + /// + /// Set the streams position. This operation is not supported and will throw a NotSupportedException + /// + /// The offset relative to the origin to seek to. + /// The to start seeking from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("TarInputStream Seek not supported"); + } + + /// + /// Sets the length of the stream + /// This operation is not supported and will throw a NotSupportedException + /// + /// The new stream length. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("TarInputStream SetLength not supported"); + } + + /// + /// Writes a block of bytes to this stream using data from a buffer. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The buffer containing bytes to write. + /// The offset in the buffer of the frist byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("TarInputStream Write not supported"); + } + + /// + /// Writes a byte to the current position in the file stream. + /// This operation is not supported and will throw a NotSupportedException + /// + /// The byte value to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("TarInputStream WriteByte not supported"); + } + /// + /// Reads a byte from the current tar archive entry. + /// + /// A byte cast to an int; -1 if the at the end of the stream. + public override int ReadByte() + { + byte[] oneByteBuffer = new byte[1]; + int num = Read(oneByteBuffer, 0, 1); + if (num <= 0) + { + // return -1 to indicate that no byte was read. + return -1; + } + return oneByteBuffer[0]; + } + + /// + /// Reads bytes from the current tar archive entry. + /// + /// This method is aware of the boundaries of the current + /// entry in the archive and will deal with them appropriately + /// + /// + /// The buffer into which to place bytes read. + /// + /// + /// The offset at which to place bytes read. + /// + /// + /// The number of bytes to read. + /// + /// + /// The number of bytes read, or 0 at end of stream/EOF. + /// + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + int totalRead = 0; + + if (entryOffset >= entrySize) + { + return 0; + } + + long numToRead = count; + + if ((numToRead + entryOffset) > entrySize) + { + numToRead = entrySize - entryOffset; + } + + if (readBuffer != null) + { + int sz = (numToRead > readBuffer.Length) ? readBuffer.Length : (int)numToRead; + + Array.Copy(readBuffer, 0, buffer, offset, sz); + + if (sz >= readBuffer.Length) + { + readBuffer = null; + } + else + { + int newLen = readBuffer.Length - sz; + byte[] newBuf = new byte[newLen]; + Array.Copy(readBuffer, sz, newBuf, 0, newLen); + readBuffer = newBuf; + } + + totalRead += sz; + numToRead -= sz; + offset += sz; + } + + while (numToRead > 0) + { + byte[] rec = tarBuffer.ReadBlock(); + if (rec == null) + { + // Unexpected EOF! + throw new TarException("unexpected EOF with " + numToRead + " bytes unread"); + } + + int sz = (int)numToRead; + int recLen = rec.Length; + + if (recLen > sz) + { + Array.Copy(rec, 0, buffer, offset, sz); + readBuffer = new byte[recLen - sz]; + Array.Copy(rec, sz, readBuffer, 0, recLen - sz); + } + else + { + sz = recLen; + Array.Copy(rec, 0, buffer, offset, recLen); + } + + totalRead += sz; + numToRead -= sz; + offset += sz; + } + + entryOffset += totalRead; + + return totalRead; + } + + /// + /// Closes this stream. Calls the TarBuffer's close() method. + /// The underlying stream is closed by the TarBuffer. + /// + public override void Close() + { + tarBuffer.Close(); + } + + #endregion + + /// + /// Set the entry factory for this instance. + /// + /// The factory for creating new entries + public void SetEntryFactory(IEntryFactory factory) + { + entryFactory = factory; + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + public int RecordSize + { + get { return tarBuffer.RecordSize; } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + /// + /// TarBuffer record size. + /// + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return tarBuffer.RecordSize; + } + + /// + /// Get the available data that can be read from the current + /// entry in the archive. This does not indicate how much data + /// is left in the entire archive, only in the current entry. + /// This value is determined from the entry's size header field + /// and the amount of data already read from the current entry. + /// + /// + /// The number of available bytes for the current entry. + /// + public long Available { + get { + return entrySize - entryOffset; + } + } + + /// + /// Skip bytes in the input buffer. This skips bytes in the + /// current entry's data, not the entire archive, and will + /// stop at the end of the current entry's data if the number + /// to skip extends beyond that point. + /// + /// + /// The number of bytes to skip. + /// + public void Skip(long skipCount) + { + // TODO: REVIEW efficiency of TarInputStream.Skip + // This is horribly inefficient, but it ensures that we + // properly skip over bytes via the TarBuffer... + // + byte[] skipBuf = new byte[8 * 1024]; + + for (long num = skipCount; num > 0;) { + int toRead = num > skipBuf.Length ? skipBuf.Length : (int)num; + int numRead = Read(skipBuf, 0, toRead); + + if (numRead == -1) { + break; + } + + num -= numRead; + } + } + + /// + /// Return a value of true if marking is supported; false otherwise. + /// + /// Currently marking is not supported, the return value is always false. + public bool IsMarkSupported { + get { + return false; + } + } + + /// + /// Since we do not support marking just yet, we do nothing. + /// + /// + /// The limit to mark. + /// + public void Mark(int markLimit) + { + } + + /// + /// Since we do not support marking just yet, we do nothing. + /// + public void Reset() + { + } + + /// + /// Get the next entry in this tar archive. This will skip + /// over any remaining data in the current entry, if there + /// is one, and place the input stream at the header of the + /// next entry, and read the header and instantiate a new + /// TarEntry from the header bytes and return that entry. + /// If there are no more entries in the archive, null will + /// be returned to indicate that the end of the archive has + /// been reached. + /// + /// + /// The next TarEntry in the archive, or null. + /// + public TarEntry GetNextEntry() + { + if (hasHitEOF) { + return null; + } + + if (currentEntry != null) { + SkipToNextEntry(); + } + + byte[] headerBuf = tarBuffer.ReadBlock(); + + if (headerBuf == null) { + hasHitEOF = true; + } else if (TarBuffer.IsEndOfArchiveBlock(headerBuf)) { + hasHitEOF = true; + } + + if (hasHitEOF) { + currentEntry = null; + } else { + try { + TarHeader header = new TarHeader(); + header.ParseBuffer(headerBuf); + if ( !header.IsChecksumValid ) + { + throw new TarException("Header checksum is invalid"); + } + this.entryOffset = 0; + this.entrySize = header.Size; + + StringBuilder longName = null; + + if (header.TypeFlag == TarHeader.LF_GNU_LONGNAME) { + + byte[] nameBuffer = new byte[TarBuffer.BlockSize]; + long numToRead = this.entrySize; + + longName = new StringBuilder(); + + while (numToRead > 0) { + int numRead = this.Read(nameBuffer, 0, (numToRead > nameBuffer.Length ? nameBuffer.Length : (int)numToRead)); + + if (numRead == -1) { + throw new InvalidHeaderException("Failed to read long name entry"); + } + + longName.Append(TarHeader.ParseName(nameBuffer, 0, numRead).ToString()); + numToRead -= numRead; + } + + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_GHDR) { // POSIX global extended header + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_XHDR) { // POSIX extended header + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag == TarHeader.LF_GNU_VOLHDR) { + // TODO: could show volume name when verbose + SkipToNextEntry(); + headerBuf = this.tarBuffer.ReadBlock(); + } else if (header.TypeFlag != TarHeader.LF_NORMAL && + header.TypeFlag != TarHeader.LF_OLDNORM && + header.TypeFlag != TarHeader.LF_DIR) { + // Ignore things we dont understand completely for now + SkipToNextEntry(); + headerBuf = tarBuffer.ReadBlock(); + } + + if (entryFactory == null) { + currentEntry = new TarEntry(headerBuf); + if (longName != null) { + currentEntry.Name = longName.ToString(); + } + } else { + currentEntry = entryFactory.CreateEntry(headerBuf); + } + + // Magic was checked here for 'ustar' but there are multiple valid possibilities + // so this is not done anymore. + + entryOffset = 0; + + // TODO: Review How do we resolve this discrepancy?! + entrySize = this.currentEntry.Size; + } catch (InvalidHeaderException ex) { + entrySize = 0; + entryOffset = 0; + currentEntry = null; + string errorText = string.Format("Bad header in record {0} block {1} {2}", + tarBuffer.CurrentRecord, tarBuffer.CurrentBlock, ex.Message); + throw new InvalidHeaderException(errorText); + } + } + return currentEntry; + } + + /// + /// Copies the contents of the current tar archive entry directly into + /// an output stream. + /// + /// + /// The OutputStream into which to write the entry's data. + /// + public void CopyEntryContents(Stream outputStream) + { + byte[] tempBuffer = new byte[32 * 1024]; + + while (true) { + int numRead = Read(tempBuffer, 0, tempBuffer.Length); + if (numRead <= 0) { + break; + } + outputStream.Write(tempBuffer, 0, numRead); + } + } + + void SkipToNextEntry() + { + long numToSkip = entrySize - entryOffset; + + if (numToSkip > 0) + { + Skip(numToSkip); + } + + readBuffer = null; + } + + /// + /// This interface is provided, along with the method , to allow + /// the programmer to have their own subclass instantiated for the + /// entries return from . + /// + public interface IEntryFactory + { + /// + /// Create an entry based on name alone + /// + /// + /// Name of the new EntryPointNotFoundException to create + /// + /// created TarEntry or descendant class + TarEntry CreateEntry(string name); + + /// + /// Create an instance based on an actual file + /// + /// + /// Name of file to represent in the entry + /// + /// + /// Created TarEntry or descendant class + /// + TarEntry CreateEntryFromFile(string fileName); + + /// + /// Create a tar entry based on the header information passed + /// + /// + /// Buffer containing header information to create an an entry from. + /// + /// + /// Created TarEntry or descendant class + /// + TarEntry CreateEntry(byte[] headerBuffer); + } + + /// + /// Standard entry factory class creating instances of the class TarEntry + /// + public class EntryFactoryAdapter : IEntryFactory + { + /// + /// Create a based on named + /// + /// The name to use for the entry + /// A new + public TarEntry CreateEntry(string name) + { + return TarEntry.CreateTarEntry(name); + } + + /// + /// Create a tar entry with details obtained from file + /// + /// The name of the file to retrieve details from. + /// A new + public TarEntry CreateEntryFromFile(string fileName) + { + return TarEntry.CreateEntryFromFile(fileName); + } + + /// + /// Create an entry based on details in header + /// + /// The buffer containing entry details. + /// A new + public TarEntry CreateEntry(byte[] headerBuffer) + { + return new TarEntry(headerBuffer); + } + } + + #region Instance Fields + /// + /// Flag set when last block has been read + /// + protected bool hasHitEOF; + + /// + /// Size of this entry as recorded in header + /// + protected long entrySize; + + /// + /// Number of bytes read for this entry so far + /// + protected long entryOffset; + + /// + /// Buffer used with calls to Read() + /// + protected byte[] readBuffer; + + /// + /// Working buffer + /// + protected TarBuffer tarBuffer; + + /// + /// Current entry being read + /// + TarEntry currentEntry; + + /// + /// Factory used to create TarEntry or descendant class instance + /// + protected IEntryFactory entryFactory; + + /// + /// Stream used as the source of input data. + /// + readonly Stream inputStream; + #endregion + } +} + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ + diff --git a/类库/VersionUpdate/ZIP/Tar/TarOutputStream.cs b/类库/VersionUpdate/ZIP/Tar/TarOutputStream.cs new file mode 100644 index 0000000..fcac26f --- /dev/null +++ b/类库/VersionUpdate/ZIP/Tar/TarOutputStream.cs @@ -0,0 +1,525 @@ +// TarOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Tar +{ + + /// + /// The TarOutputStream writes a UNIX tar archive as an OutputStream. + /// Methods are provided to put entries, and then write their contents + /// by writing to this stream using write(). + /// + /// public + public class TarOutputStream : Stream + { + #region Constructors + /// + /// Construct TarOutputStream using default block factor + /// + /// stream to write to + public TarOutputStream(Stream outputStream) + : this(outputStream, TarBuffer.DefaultBlockFactor) + { + } + + /// + /// Construct TarOutputStream with user specified block factor + /// + /// stream to write to + /// blocking factor + public TarOutputStream(Stream outputStream, int blockFactor) + { + if ( outputStream == null ) + { + throw new ArgumentNullException("outputStream"); + } + + this.outputStream = outputStream; + buffer = TarBuffer.CreateOutputTarBuffer(outputStream, blockFactor); + + assemblyBuffer = new byte[TarBuffer.BlockSize]; + blockBuffer = new byte[TarBuffer.BlockSize]; + } + #endregion + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return buffer.IsStreamOwner; } + set { buffer.IsStreamOwner = value; } + } + + /// + /// true if the stream supports reading; otherwise, false. + /// + public override bool CanRead + { + get + { + return outputStream.CanRead; + } + } + + /// + /// true if the stream supports seeking; otherwise, false. + /// + public override bool CanSeek + { + get + { + return outputStream.CanSeek; + } + } + + /// + /// true if stream supports writing; otherwise, false. + /// + public override bool CanWrite + { + get + { + return outputStream.CanWrite; + } + } + + /// + /// length of stream in bytes + /// + public override long Length + { + get + { + return outputStream.Length; + } + } + + /// + /// gets or sets the position within the current stream. + /// + public override long Position + { + get + { + return outputStream.Position; + } + set + { + outputStream.Position = value; + } + } + + /// + /// set the position within the current stream + /// + /// The offset relative to the to seek to + /// The to seek from. + /// The new position in the stream. + public override long Seek(long offset, SeekOrigin origin) + { + return outputStream.Seek(offset, origin); + } + + /// + /// Set the length of the current stream + /// + /// The new stream length. + public override void SetLength(long value) + { + outputStream.SetLength(value); + } + + /// + /// Read a byte from the stream and advance the position within the stream + /// by one byte or returns -1 if at the end of the stream. + /// + /// The byte value or -1 if at end of stream + public override int ReadByte() + { + return outputStream.ReadByte(); + } + + /// + /// read bytes from the current stream and advance the position within the + /// stream by the number of bytes read. + /// + /// The buffer to store read bytes in. + /// The index into the buffer to being storing bytes at. + /// The desired number of bytes to read. + /// The total number of bytes read, or zero if at the end of the stream. + /// The number of bytes may be less than the count + /// requested if data is not avialable. + public override int Read(byte[] buffer, int offset, int count) + { + return outputStream.Read(buffer, offset, count); + } + + /// + /// All buffered data is written to destination + /// + public override void Flush() + { + outputStream.Flush(); + } + + /// + /// Ends the TAR archive without closing the underlying OutputStream. + /// The result is that the EOF block of nulls is written. + /// + public void Finish() + { + if ( IsEntryOpen ) + { + CloseEntry(); + } + WriteEofBlock(); + } + + /// + /// Ends the TAR archive and closes the underlying OutputStream. + /// + /// This means that Finish() is called followed by calling the + /// TarBuffer's Close(). + public override void Close() + { + if ( !isClosed ) + { + isClosed = true; + Finish(); + buffer.Close(); + } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + public int RecordSize + { + get { return buffer.RecordSize; } + } + + /// + /// Get the record size being used by this stream's TarBuffer. + /// + /// + /// The TarBuffer record size. + /// + [Obsolete("Use RecordSize property instead")] + public int GetRecordSize() + { + return buffer.RecordSize; + } + + /// + /// Get a value indicating wether an entry is open, requiring more data to be written. + /// + bool IsEntryOpen + { + get { return (currBytes < currSize); } + + } + + /// + /// Put an entry on the output stream. This writes the entry's + /// header and positions the output stream for writing + /// the contents of the entry. Once this method is called, the + /// stream is ready for calls to write() to write the entry's + /// contents. Once the contents are written, closeEntry() + /// MUST be called to ensure that all buffered data + /// is completely written to the output stream. + /// + /// + /// The TarEntry to be written to the archive. + /// + public void PutNextEntry(TarEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if (entry.TarHeader.Name.Length >= TarHeader.NAMELEN) { + TarHeader longHeader = new TarHeader(); + longHeader.TypeFlag = TarHeader.LF_GNU_LONGNAME; + longHeader.Name = longHeader.Name + "././@LongLink"; + longHeader.UserId = 0; + longHeader.GroupId = 0; + longHeader.GroupName = ""; + longHeader.UserName = ""; + longHeader.LinkName = ""; + longHeader.Size = entry.TarHeader.Name.Length; + + longHeader.WriteHeader(blockBuffer); + buffer.WriteBlock(blockBuffer); // Add special long filename header block + + int nameCharIndex = 0; + + while (nameCharIndex < entry.TarHeader.Name.Length) { + Array.Clear(blockBuffer, 0, blockBuffer.Length); + TarHeader.GetAsciiBytes(entry.TarHeader.Name, nameCharIndex, this.blockBuffer, 0, TarBuffer.BlockSize); + nameCharIndex += TarBuffer.BlockSize; + buffer.WriteBlock(blockBuffer); + } + } + + entry.WriteEntryHeader(blockBuffer); + buffer.WriteBlock(blockBuffer); + + currBytes = 0; + + currSize = entry.IsDirectory ? 0 : entry.Size; + } + + /// + /// Close an entry. This method MUST be called for all file + /// entries that contain data. The reason is that we must + /// buffer data written to the stream in order to satisfy + /// the buffer's block based writes. Thus, there may be + /// data fragments still being assembled that must be written + /// to the output stream before this entry is closed and the + /// next entry written. + /// + public void CloseEntry() + { + if (assemblyBufferLength > 0) { + Array.Clear(assemblyBuffer, assemblyBufferLength, assemblyBuffer.Length - assemblyBufferLength); + + buffer.WriteBlock(assemblyBuffer); + + currBytes += assemblyBufferLength; + assemblyBufferLength = 0; + } + + if (currBytes < currSize) { + string errorText = string.Format( + "Entry closed at '{0}' before the '{1}' bytes specified in the header were written", + currBytes, currSize); + throw new TarException(errorText); + } + } + + /// + /// Writes a byte to the current tar archive entry. + /// This method simply calls Write(byte[], int, int). + /// + /// + /// The byte to be written. + /// + public override void WriteByte(byte value) + { + Write(new byte[] { value }, 0, 1); + } + + /// + /// Writes bytes to the current tar archive entry. This method + /// is aware of the current entry and will throw an exception if + /// you attempt to write bytes past the length specified for the + /// current entry. The method is also (painfully) aware of the + /// record buffering required by TarBuffer, and manages buffers + /// that are not a multiple of recordsize in length, including + /// assembling records from small buffers. + /// + /// + /// The buffer to write to the archive. + /// + /// + /// The offset in the buffer from which to get bytes. + /// + /// + /// The number of bytes to write. + /// + public override void Write(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( buffer.Length - offset < count ) + { + throw new ArgumentException("offset and count combination is invalid"); + } + + if ( count < 0 ) + { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (currBytes + count) > currSize ) { + string errorText = string.Format("request to write '{0}' bytes exceeds size in header of '{1}' bytes", + count, this.currSize); +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", errorText); +#endif + } + + // + // We have to deal with assembly!!! + // The programmer can be writing little 32 byte chunks for all + // we know, and we must assemble complete blocks for writing. + // TODO REVIEW Maybe this should be in TarBuffer? Could that help to + // eliminate some of the buffer copying. + // + if (assemblyBufferLength > 0) { + if ((assemblyBufferLength + count ) >= blockBuffer.Length) { + int aLen = blockBuffer.Length - assemblyBufferLength; + + Array.Copy(assemblyBuffer, 0, blockBuffer, 0, assemblyBufferLength); + Array.Copy(buffer, offset, blockBuffer, assemblyBufferLength, aLen); + + this.buffer.WriteBlock(blockBuffer); + + currBytes += blockBuffer.Length; + + offset += aLen; + count -= aLen; + + assemblyBufferLength = 0; + } else { + Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count); + offset += count; + assemblyBufferLength += count; + count -= count; + } + } + + // + // When we get here we have EITHER: + // o An empty "assembly" buffer. + // o No bytes to write (count == 0) + // + while (count > 0) { + if (count < blockBuffer.Length) { + Array.Copy(buffer, offset, assemblyBuffer, assemblyBufferLength, count); + assemblyBufferLength += count; + break; + } + + this.buffer.WriteBlock(buffer, offset); + + int bufferLength = blockBuffer.Length; + currBytes += bufferLength; + count -= bufferLength; + offset += bufferLength; + } + } + + /// + /// Write an EOF (end of archive) block to the tar archive. + /// An EOF block consists of all zeros. + /// + void WriteEofBlock() + { + Array.Clear(blockBuffer, 0, blockBuffer.Length); + buffer.WriteBlock(blockBuffer); + } + + #region Instance Fields + /// + /// bytes written for this entry so far + /// + long currBytes; + + /// + /// current 'Assembly' buffer length + /// + int assemblyBufferLength; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + /// + /// Size for the current entry + /// + protected long currSize; + + /// + /// single block working buffer + /// + protected byte[] blockBuffer; + + /// + /// 'Assembly' buffer used to assemble data before writing + /// + protected byte[] assemblyBuffer; + + /// + /// TarBuffer used to provide correct blocking factor + /// + protected TarBuffer buffer; + + /// + /// the destination stream for the archive contents + /// + protected Stream outputStream; + #endregion + } +} + +/* The original Java file had this header: + ** Authored by Timothy Gerard Endres + ** + ** + ** This work has been placed into the public domain. + ** You may use this work in any way and for any purpose you wish. + ** + ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, + ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR + ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY + ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR + ** REDISTRIBUTION OF THIS SOFTWARE. + ** + */ diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/Deflater.cs b/类库/VersionUpdate/ZIP/Zip/Compression/Deflater.cs new file mode 100644 index 0000000..dadbfb6 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/Deflater.cs @@ -0,0 +1,557 @@ +// Deflater.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This is the Deflater class. The deflater class compresses input + /// with the deflate algorithm described in RFC 1951. It has several + /// compression levels and three different strategies described below. + /// + /// This class is not thread safe. This is inherent in the API, due + /// to the split of deflate and setInput. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class Deflater + { + #region Deflater Documentation + /* + * The Deflater can do the following state transitions: + * + * (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---. + * / | (2) (5) | + * / v (5) | + * (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3) + * \ | (3) | ,--------' + * | | | (3) / + * v v (5) v v + * (1) -> BUSY_STATE ----> FINISHING_STATE + * | (6) + * v + * FINISHED_STATE + * \_____________________________________/ + * | (7) + * v + * CLOSED_STATE + * + * (1) If we should produce a header we start in INIT_STATE, otherwise + * we start in BUSY_STATE. + * (2) A dictionary may be set only when we are in INIT_STATE, then + * we change the state as indicated. + * (3) Whether a dictionary is set or not, on the first call of deflate + * we change to BUSY_STATE. + * (4) -- intentionally left blank -- :) + * (5) FINISHING_STATE is entered, when flush() is called to indicate that + * there is no more INPUT. There are also states indicating, that + * the header wasn't written yet. + * (6) FINISHED_STATE is entered, when everything has been flushed to the + * internal pending output buffer. + * (7) At any time (7) + * + */ + #endregion + #region Public Constants + /// + /// The best and slowest compression level. This tries to find very + /// long and distant string repetitions. + /// + public const int BEST_COMPRESSION = 9; + + /// + /// The worst but fastest compression level. + /// + public const int BEST_SPEED = 1; + + /// + /// The default compression level. + /// + public const int DEFAULT_COMPRESSION = -1; + + /// + /// This level won't compress at all but output uncompressed blocks. + /// + public const int NO_COMPRESSION = 0; + + /// + /// The compression method. This is the only method supported so far. + /// There is no need to use this constant at all. + /// + public const int DEFLATED = 8; + #endregion + #region Local Constants + private const int IS_SETDICT = 0x01; + private const int IS_FLUSHING = 0x04; + private const int IS_FINISHING = 0x08; + + private const int INIT_STATE = 0x00; + private const int SETDICT_STATE = 0x01; + // private static int INIT_FINISHING_STATE = 0x08; + // private static int SETDICT_FINISHING_STATE = 0x09; + private const int BUSY_STATE = 0x10; + private const int FLUSHING_STATE = 0x14; + private const int FINISHING_STATE = 0x1c; + private const int FINISHED_STATE = 0x1e; + private const int CLOSED_STATE = 0x7f; + #endregion + #region Constructors + /// + /// Creates a new deflater with default compression level. + /// + public Deflater() : this(DEFAULT_COMPRESSION, false) + { + + } + + /// + /// Creates a new deflater with given compression level. + /// + /// + /// the compression level, a value between NO_COMPRESSION + /// and BEST_COMPRESSION, or DEFAULT_COMPRESSION. + /// + /// if lvl is out of range. + public Deflater(int level) : this(level, false) + { + + } + + /// + /// Creates a new deflater with given compression level. + /// + /// + /// the compression level, a value between NO_COMPRESSION + /// and BEST_COMPRESSION. + /// + /// + /// true, if we should suppress the Zlib/RFC1950 header at the + /// beginning and the adler checksum at the end of the output. This is + /// useful for the GZIP/PKZIP formats. + /// + /// if lvl is out of range. + public Deflater(int level, bool noZlibHeaderOrFooter) + { + if (level == DEFAULT_COMPRESSION) { + level = 6; + } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) { + throw new ArgumentOutOfRangeException("level"); + } + + pending = new DeflaterPending(); + engine = new DeflaterEngine(pending); + this.noZlibHeaderOrFooter = noZlibHeaderOrFooter; + SetStrategy(DeflateStrategy.Default); + SetLevel(level); + Reset(); + } + #endregion + + /// + /// Resets the deflater. The deflater acts afterwards as if it was + /// just created with the same compression level and strategy as it + /// had before. + /// + public void Reset() + { + state = (noZlibHeaderOrFooter ? BUSY_STATE : INIT_STATE); + totalOut = 0; + pending.Reset(); + engine.Reset(); + } + + /// + /// Gets the current adler checksum of the data that was processed so far. + /// + public int Adler { + get { + return engine.Adler; + } + } + + /// + /// Gets the number of input bytes processed so far. + /// + public long TotalIn { + get { + return engine.TotalIn; + } + } + + /// + /// Gets the number of output bytes so far. + /// + public long TotalOut { + get { + return totalOut; + } + } + + /// + /// Flushes the current input block. Further calls to deflate() will + /// produce enough output to inflate everything in the current input + /// block. This is not part of Sun's JDK so I have made it package + /// private. It is used by DeflaterOutputStream to implement + /// flush(). + /// + public void Flush() + { + state |= IS_FLUSHING; + } + + /// + /// Finishes the deflater with the current input block. It is an error + /// to give more input after this method was called. This method must + /// be called to force all bytes to be flushed. + /// + public void Finish() + { + state |= (IS_FLUSHING | IS_FINISHING); + } + + /// + /// Returns true if the stream was finished and no more output bytes + /// are available. + /// + public bool IsFinished { + get { + return (state == FINISHED_STATE) && pending.IsFlushed; + } + } + + /// + /// Returns true, if the input buffer is empty. + /// You should then call setInput(). + /// NOTE: This method can also return true when the stream + /// was finished. + /// + public bool IsNeedingInput { + get { + return engine.NeedsInput(); + } + } + + /// + /// Sets the data which should be compressed next. This should be only + /// called when needsInput indicates that more input is needed. + /// If you call setInput when needsInput() returns false, the + /// previous input that is still pending will be thrown away. + /// The given byte array should not be changed, before needsInput() returns + /// true again. + /// This call is equivalent to setInput(input, 0, input.length). + /// + /// + /// the buffer containing the input data. + /// + /// + /// if the buffer was finished() or ended(). + /// + public void SetInput(byte[] input) + { + SetInput(input, 0, input.Length); + } + + /// + /// Sets the data which should be compressed next. This should be + /// only called when needsInput indicates that more input is needed. + /// The given byte array should not be changed, before needsInput() returns + /// true again. + /// + /// + /// the buffer containing the input data. + /// + /// + /// the start of the data. + /// + /// + /// the number of data bytes of input. + /// + /// + /// if the buffer was Finish()ed or if previous input is still pending. + /// + public void SetInput(byte[] input, int offset, int count) + { + if ((state & IS_FINISHING) != 0) { + throw new InvalidOperationException("Finish() already called"); + } + engine.SetInput(input, offset, count); + } + + /// + /// Sets the compression level. There is no guarantee of the exact + /// position of the change, but if you call this when needsInput is + /// true the change of compression level will occur somewhere near + /// before the end of the so far given input. + /// + /// + /// the new compression level. + /// + public void SetLevel(int level) + { + if (level == DEFAULT_COMPRESSION) { + level = 6; + } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) { + throw new ArgumentOutOfRangeException("level"); + } + + if (this.level != level) { + this.level = level; + engine.SetLevel(level); + } + } + + /// + /// Get current compression level + /// + /// Returns the current compression level + public int GetLevel() { + return level; + } + + /// + /// Sets the compression strategy. Strategy is one of + /// DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact + /// position where the strategy is changed, the same as for + /// SetLevel() applies. + /// + /// + /// The new compression strategy. + /// + public void SetStrategy(DeflateStrategy strategy) + { + engine.Strategy = strategy; + } + + /// + /// Deflates the current input block with to the given array. + /// + /// + /// The buffer where compressed data is stored + /// + /// + /// The number of compressed bytes added to the output, or 0 if either + /// IsNeedingInput() or IsFinished returns true or length is zero. + /// + public int Deflate(byte[] output) + { + return Deflate(output, 0, output.Length); + } + + /// + /// Deflates the current input block to the given array. + /// + /// + /// Buffer to store the compressed data. + /// + /// + /// Offset into the output array. + /// + /// + /// The maximum number of bytes that may be stored. + /// + /// + /// The number of compressed bytes added to the output, or 0 if either + /// needsInput() or finished() returns true or length is zero. + /// + /// + /// If Finish() was previously called. + /// + /// + /// If offset or length don't match the array length. + /// + public int Deflate(byte[] output, int offset, int length) + { + int origLength = length; + + if (state == CLOSED_STATE) { + throw new InvalidOperationException("Deflater closed"); + } + + if (state < BUSY_STATE) { + // output header + int header = (DEFLATED + + ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8; + int level_flags = (level - 1) >> 1; + if (level_flags < 0 || level_flags > 3) { + level_flags = 3; + } + header |= level_flags << 6; + if ((state & IS_SETDICT) != 0) { + // Dictionary was set + header |= DeflaterConstants.PRESET_DICT; + } + header += 31 - (header % 31); + + pending.WriteShortMSB(header); + if ((state & IS_SETDICT) != 0) { + int chksum = engine.Adler; + engine.ResetAdler(); + pending.WriteShortMSB(chksum >> 16); + pending.WriteShortMSB(chksum & 0xffff); + } + + state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING)); + } + + for (;;) { + int count = pending.Flush(output, offset, length); + offset += count; + totalOut += count; + length -= count; + + if (length == 0 || state == FINISHED_STATE) { + break; + } + + if (!engine.Deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0)) { + if (state == BUSY_STATE) { + // We need more input now + return origLength - length; + } else if (state == FLUSHING_STATE) { + if (level != NO_COMPRESSION) { + /* We have to supply some lookahead. 8 bit lookahead + * is needed by the zlib inflater, and we must fill + * the next byte, so that all bits are flushed. + */ + int neededbits = 8 + ((-pending.BitCount) & 7); + while (neededbits > 0) { + /* write a static tree block consisting solely of + * an EOF: + */ + pending.WriteBits(2, 10); + neededbits -= 10; + } + } + state = BUSY_STATE; + } else if (state == FINISHING_STATE) { + pending.AlignToByte(); + + // Compressed data is complete. Write footer information if required. + if (!noZlibHeaderOrFooter) { + int adler = engine.Adler; + pending.WriteShortMSB(adler >> 16); + pending.WriteShortMSB(adler & 0xffff); + } + state = FINISHED_STATE; + } + } + } + return origLength - length; + } + + /// + /// Sets the dictionary which should be used in the deflate process. + /// This call is equivalent to setDictionary(dict, 0, dict.Length). + /// + /// + /// the dictionary. + /// + /// + /// if SetInput () or Deflate () were already called or another dictionary was already set. + /// + public void SetDictionary(byte[] dictionary) + { + SetDictionary(dictionary, 0, dictionary.Length); + } + + /// + /// Sets the dictionary which should be used in the deflate process. + /// The dictionary is a byte array containing strings that are + /// likely to occur in the data which should be compressed. The + /// dictionary is not stored in the compressed output, only a + /// checksum. To decompress the output you need to supply the same + /// dictionary again. + /// + /// + /// The dictionary data + /// + /// + /// The index where dictionary information commences. + /// + /// + /// The number of bytes in the dictionary. + /// + /// + /// If SetInput () or Deflate() were already called or another dictionary was already set. + /// + public void SetDictionary(byte[] dictionary, int index, int count) + { + if (state != INIT_STATE) { + throw new InvalidOperationException(); + } + + state = SETDICT_STATE; + engine.SetDictionary(dictionary, index, count); + } + + #region Instance Fields + /// + /// Compression level. + /// + int level; + + /// + /// If true no Zlib/RFC1950 headers or footers are generated + /// + bool noZlibHeaderOrFooter; + + /// + /// The current state. + /// + int state; + + /// + /// The total bytes of output written. + /// + long totalOut; + + /// + /// The pending output. + /// + DeflaterPending pending; + + /// + /// The deflater engine. + /// + DeflaterEngine engine; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterConstants.cs b/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterConstants.cs new file mode 100644 index 0000000..a973db2 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterConstants.cs @@ -0,0 +1,186 @@ +// DeflaterConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class contains constants used for deflation. + /// + public class DeflaterConstants + { + /// + /// Set to true to enable debugging + /// + public const bool DEBUGGING = false; + + /// + /// Written to Zip file to identify a stored block + /// + public const int STORED_BLOCK = 0; + + /// + /// Identifies static tree in Zip file + /// + public const int STATIC_TREES = 1; + + /// + /// Identifies dynamic tree in Zip file + /// + public const int DYN_TREES = 2; + + /// + /// Header flag indicating a preset dictionary for deflation + /// + public const int PRESET_DICT = 0x20; + + /// + /// Sets internal buffer sizes for Huffman encoding + /// + public const int DEFAULT_MEM_LEVEL = 8; + + /// + /// Internal compression engine constant + /// + public const int MAX_MATCH = 258; + + /// + /// Internal compression engine constant + /// + public const int MIN_MATCH = 3; + + /// + /// Internal compression engine constant + /// + public const int MAX_WBITS = 15; + + /// + /// Internal compression engine constant + /// + public const int WSIZE = 1 << MAX_WBITS; + + /// + /// Internal compression engine constant + /// + public const int WMASK = WSIZE - 1; + + /// + /// Internal compression engine constant + /// + public const int HASH_BITS = DEFAULT_MEM_LEVEL + 7; + + /// + /// Internal compression engine constant + /// + public const int HASH_SIZE = 1 << HASH_BITS; + + /// + /// Internal compression engine constant + /// + public const int HASH_MASK = HASH_SIZE - 1; + + /// + /// Internal compression engine constant + /// + public const int HASH_SHIFT = (HASH_BITS + MIN_MATCH - 1) / MIN_MATCH; + + /// + /// Internal compression engine constant + /// + public const int MIN_LOOKAHEAD = MAX_MATCH + MIN_MATCH + 1; + + /// + /// Internal compression engine constant + /// + public const int MAX_DIST = WSIZE - MIN_LOOKAHEAD; + + /// + /// Internal compression engine constant + /// + public const int PENDING_BUF_SIZE = 1 << (DEFAULT_MEM_LEVEL + 8); + + /// + /// Internal compression engine constant + /// + public static int MAX_BLOCK_SIZE = Math.Min(65535, PENDING_BUF_SIZE - 5); + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_STORED = 0; + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_FAST = 1; + + /// + /// Internal compression engine constant + /// + public const int DEFLATE_SLOW = 2; + + /// + /// Internal compression engine constant + /// + public static int[] GOOD_LENGTH = { 0, 4, 4, 4, 4, 8, 8, 8, 32, 32 }; + + /// + /// Internal compression engine constant + /// + public static int[] MAX_LAZY = { 0, 4, 5, 6, 4, 16, 16, 32, 128, 258 }; + + /// + /// Internal compression engine constant + /// + public static int[] NICE_LENGTH = { 0, 8, 16, 32, 16, 32, 128, 128, 258, 258 }; + + /// + /// Internal compression engine constant + /// + public static int[] MAX_CHAIN = { 0, 4, 8, 32, 16, 32, 128, 256, 1024, 4096 }; + + /// + /// Internal compression engine constant + /// + public static int[] COMPR_FUNC = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterEngine.cs b/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterEngine.cs new file mode 100644 index 0000000..3cbb5aa --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterEngine.cs @@ -0,0 +1,869 @@ +// DeflaterEngine.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Checksums; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// Strategies for deflater + /// + public enum DeflateStrategy + { + /// + /// The default strategy + /// + Default = 0, + + /// + /// This strategy will only allow longer string repetitions. It is + /// useful for random data with a small character set. + /// + Filtered = 1, + + + /// + /// This strategy will not look for string repetitions at all. It + /// only encodes with Huffman trees (which means, that more common + /// characters get a smaller encoding. + /// + HuffmanOnly = 2 + } + + // DEFLATE ALGORITHM: + // + // The uncompressed stream is inserted into the window array. When + // the window array is full the first half is thrown away and the + // second half is copied to the beginning. + // + // The head array is a hash table. Three characters build a hash value + // and they the value points to the corresponding index in window of + // the last string with this hash. The prev array implements a + // linked list of matches with the same hash: prev[index & WMASK] points + // to the previous index with the same hash. + // + + + /// + /// Low level compression engine for deflate algorithm which uses a 32K sliding window + /// with secondary compression from Huffman/Shannon-Fano codes. + /// + public class DeflaterEngine : DeflaterConstants + { + #region Constants + const int TooFar = 4096; + #endregion + + #region Constructors + /// + /// Construct instance with pending buffer + /// + /// + /// Pending buffer to use + /// > + public DeflaterEngine(DeflaterPending pending) + { + this.pending = pending; + huffman = new DeflaterHuffman(pending); + adler = new Adler32(); + + window = new byte[2 * WSIZE]; + head = new short[HASH_SIZE]; + prev = new short[WSIZE]; + + // We start at index 1, to avoid an implementation deficiency, that + // we cannot build a repeat pattern at index 0. + blockStart = strstart = 1; + } + + #endregion + + /// + /// Deflate drives actual compression of data + /// + /// True to flush input buffers + /// Finish deflation with the current input. + /// Returns true if progress has been made. + public bool Deflate(bool flush, bool finish) + { + bool progress; + do + { + FillWindow(); + bool canFlush = flush && (inputOff == inputEnd); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.WriteLine("window: [" + blockStart + "," + strstart + "," + + lookahead + "], " + compressionFunction + "," + canFlush); + } +#endif + switch (compressionFunction) + { + case DEFLATE_STORED: + progress = DeflateStored(canFlush, finish); + break; + case DEFLATE_FAST: + progress = DeflateFast(canFlush, finish); + break; + case DEFLATE_SLOW: + progress = DeflateSlow(canFlush, finish); + break; + default: + throw new InvalidOperationException("unknown compressionFunction"); + } + } while (pending.IsFlushed && progress); // repeat while we have no pending output and progress was made + return progress; + } + + /// + /// Sets input data to be deflated. Should only be called when NeedsInput() + /// returns true + /// + /// The buffer containing input data. + /// The offset of the first byte of data. + /// The number of bytes of data to use as input. + public void SetInput(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) + { + throw new ArgumentOutOfRangeException("offset"); + } + + if ( count < 0 ) + { + throw new ArgumentOutOfRangeException("count"); + } + + if (inputOff < inputEnd) + { + throw new InvalidOperationException("Old input was not completely processed"); + } + + int end = offset + count; + + /* We want to throw an ArrayIndexOutOfBoundsException early. The + * check is very tricky: it also handles integer wrap around. + */ + if ((offset > end) || (end > buffer.Length) ) + { + throw new ArgumentOutOfRangeException("count"); + } + + inputBuf = buffer; + inputOff = offset; + inputEnd = end; + } + + /// + /// Determines if more input is needed. + /// + /// Return true if input is needed via SetInput + public bool NeedsInput() + { + return (inputEnd == inputOff); + } + + /// + /// Set compression dictionary + /// + /// The buffer containing the dictionary data + /// The offset in the buffer for the first byte of data + /// The length of the dictionary data. + public void SetDictionary(byte[] buffer, int offset, int length) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (strstart != 1) ) + { + throw new InvalidOperationException("strstart not 1"); + } +#endif + adler.Update(buffer, offset, length); + if (length < MIN_MATCH) + { + return; + } + + if (length > MAX_DIST) + { + offset += length - MAX_DIST; + length = MAX_DIST; + } + + System.Array.Copy(buffer, offset, window, strstart, length); + + UpdateHash(); + --length; + while (--length > 0) + { + InsertString(); + strstart++; + } + strstart += 2; + blockStart = strstart; + } + + /// + /// Reset internal state + /// + public void Reset() + { + huffman.Reset(); + adler.Reset(); + blockStart = strstart = 1; + lookahead = 0; + totalIn = 0; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + + for (int i = 0; i < HASH_SIZE; i++) { + head[i] = 0; + } + + for (int i = 0; i < WSIZE; i++) { + prev[i] = 0; + } + } + + /// + /// Reset Adler checksum + /// + public void ResetAdler() + { + adler.Reset(); + } + + /// + /// Get current value of Adler checksum + /// + public int Adler { + get { + return unchecked((int)adler.Value); + } + } + + /// + /// Total data processed + /// + public long TotalIn { + get { + return totalIn; + } + } + + /// + /// Get/set the deflate strategy + /// + public DeflateStrategy Strategy { + get { + return strategy; + } + set { + strategy = value; + } + } + + /// + /// Set the deflate level (0-9) + /// + /// The value to set the level to. + public void SetLevel(int level) + { + if ( (level < 0) || (level > 9) ) + { + throw new ArgumentOutOfRangeException("level"); + } + + goodLength = DeflaterConstants.GOOD_LENGTH[level]; + max_lazy = DeflaterConstants.MAX_LAZY[level]; + niceLength = DeflaterConstants.NICE_LENGTH[level]; + max_chain = DeflaterConstants.MAX_CHAIN[level]; + + if (DeflaterConstants.COMPR_FUNC[level] != compressionFunction) { + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.WriteLine("Change from " + compressionFunction + " to " + + DeflaterConstants.COMPR_FUNC[level]); + } +#endif + switch (compressionFunction) { + case DEFLATE_STORED: + if (strstart > blockStart) { + huffman.FlushStoredBlock(window, blockStart, + strstart - blockStart, false); + blockStart = strstart; + } + UpdateHash(); + break; + + case DEFLATE_FAST: + if (strstart > blockStart) { + huffman.FlushBlock(window, blockStart, strstart - blockStart, + false); + blockStart = strstart; + } + break; + + case DEFLATE_SLOW: + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + if (strstart > blockStart) { + huffman.FlushBlock(window, blockStart, strstart - blockStart, false); + blockStart = strstart; + } + prevAvailable = false; + matchLen = MIN_MATCH - 1; + break; + } + compressionFunction = COMPR_FUNC[level]; + } + } + + /// + /// Fill the window + /// + public void FillWindow() + { + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (strstart >= WSIZE + MAX_DIST) + { + SlideWindow(); + } + + /* If there is not enough lookahead, but still some input left, + * read in the input + */ + while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd) + { + int more = 2 * WSIZE - lookahead - strstart; + + if (more > inputEnd - inputOff) + { + more = inputEnd - inputOff; + } + + System.Array.Copy(inputBuf, inputOff, window, strstart + lookahead, more); + adler.Update(inputBuf, inputOff, more); + + inputOff += more; + totalIn += more; + lookahead += more; + } + + if (lookahead >= MIN_MATCH) + { + UpdateHash(); + } + } + + void UpdateHash() + { +/* + if (DEBUGGING) { + Console.WriteLine("updateHash: "+strstart); + } +*/ + ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1]; + } + + /// + /// Inserts the current string in the head hash and returns the previous + /// value for this hash. + /// + /// The previous hash value + int InsertString() + { + short match; + int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)]) & HASH_MASK; + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^ + (window[strstart + 1] << HASH_SHIFT) ^ + (window[strstart + 2])) & HASH_MASK)) { + throw new SharpZipBaseException("hash inconsistent: " + hash + "/" + +window[strstart] + "," + +window[strstart + 1] + "," + +window[strstart + 2] + "," + HASH_SHIFT); + } + } +#endif + prev[strstart & WMASK] = match = head[hash]; + head[hash] = unchecked((short)strstart); + ins_h = hash; + return match & 0xffff; + } + + void SlideWindow() + { + Array.Copy(window, WSIZE, window, 0, WSIZE); + matchStart -= WSIZE; + strstart -= WSIZE; + blockStart -= WSIZE; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). + for (int i = 0; i < HASH_SIZE; ++i) { + int m = head[i] & 0xffff; + head[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0); + } + + // Slide the prev table. + for (int i = 0; i < WSIZE; i++) { + int m = prev[i] & 0xffff; + prev[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0); + } + } + + /// + /// Find the best (longest) string in the window matching the + /// string starting at strstart. + /// + /// Preconditions: + /// + /// strstart + MAX_MATCH <= window.length. + /// + /// + /// True if a match greater than the minimum length is found + bool FindLongestMatch(int curMatch) + { + int chainLength = this.max_chain; + int niceLength = this.niceLength; + short[] prev = this.prev; + int scan = this.strstart; + int match; + int best_end = this.strstart + matchLen; + int best_len = Math.Max(matchLen, MIN_MATCH - 1); + + int limit = Math.Max(strstart - MAX_DIST, 0); + + int strend = strstart + MAX_MATCH - 1; + byte scan_end1 = window[best_end - 1]; + byte scan_end = window[best_end]; + + // Do not waste too much time if we already have a good match: + if (best_len >= this.goodLength) { + chainLength >>= 2; + } + + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (niceLength > lookahead) { + niceLength = lookahead; + } + +#if DebugDeflation + + if (DeflaterConstants.DEBUGGING && (strstart > 2 * WSIZE - MIN_LOOKAHEAD)) + { + throw new InvalidOperationException("need lookahead"); + } +#endif + + do { + +#if DebugDeflation + + if (DeflaterConstants.DEBUGGING && (curMatch >= strstart) ) + { + throw new InvalidOperationException("no future"); + } +#endif + if (window[curMatch + best_len] != scan_end || + window[curMatch + best_len - 1] != scan_end1 || + window[curMatch] != window[scan] || + window[curMatch + 1] != window[scan + 1]) { + continue; + } + + match = curMatch + 2; + scan += 2; + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart + 258. + */ + while ( + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + (scan < strend)) + { + // Do nothing + } + + if (scan > best_end) { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (ins_h == 0) ) + Console.Error.WriteLine("Found match: " + curMatch + "-" + (scan - strstart)); +#endif + matchStart = curMatch; + best_end = scan; + best_len = scan - strstart; + + if (best_len >= niceLength) { + break; + } + + scan_end1 = window[best_end - 1]; + scan_end = window[best_end]; + } + scan = strstart; + } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit && --chainLength != 0); + + matchLen = Math.Min(best_len, lookahead); + return matchLen >= MIN_MATCH; + } + + bool DeflateStored(bool flush, bool finish) + { + if (!flush && (lookahead == 0)) { + return false; + } + + strstart += lookahead; + lookahead = 0; + + int storedLength = strstart - blockStart; + + if ((storedLength >= DeflaterConstants.MAX_BLOCK_SIZE) || // Block is full + (blockStart < WSIZE && storedLength >= MAX_DIST) || // Block may move out of window + flush) { + bool lastBlock = finish; + if (storedLength > DeflaterConstants.MAX_BLOCK_SIZE) { + storedLength = DeflaterConstants.MAX_BLOCK_SIZE; + lastBlock = false; + } + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + Console.WriteLine("storedBlock[" + storedLength + "," + lastBlock + "]"); + } +#endif + + huffman.FlushStoredBlock(window, blockStart, storedLength, lastBlock); + blockStart += storedLength; + return !lastBlock; + } + return true; + } + + bool DeflateFast(bool flush, bool finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) { + return false; + } + + while (lookahead >= MIN_LOOKAHEAD || flush) { + if (lookahead == 0) { + // We are flushing everything + huffman.FlushBlock(window, blockStart, strstart - blockStart, finish); + blockStart = strstart; + return false; + } + + if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) { + /* slide window, as FindLongestMatch needs this. + * This should only happen when flushing and the window + * is almost full. + */ + SlideWindow(); + } + + int hashHead; + if (lookahead >= MIN_MATCH && + (hashHead = InsertString()) != 0 && + strategy != DeflateStrategy.HuffmanOnly && + strstart - hashHead <= MAX_DIST && + FindLongestMatch(hashHead)) { + // longestMatch sets matchStart and matchLen +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) { + if (window[strstart + i] != window[matchStart + i]) { + throw new SharpZipBaseException("Match failure"); + } + } + } +#endif + + bool full = huffman.TallyDist(strstart - matchStart, matchLen); + + lookahead -= matchLen; + if (matchLen <= max_lazy && lookahead >= MIN_MATCH) { + while (--matchLen > 0) { + ++strstart; + InsertString(); + } + ++strstart; + } else { + strstart += matchLen; + if (lookahead >= MIN_MATCH - 1) { + UpdateHash(); + } + } + matchLen = MIN_MATCH - 1; + if (!full) { + continue; + } + } else { + // No match found + huffman.TallyLit(window[strstart] & 0xff); + ++strstart; + --lookahead; + } + + if (huffman.IsFull()) { + bool lastBlock = finish && (lookahead == 0); + huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock); + blockStart = strstart; + return !lastBlock; + } + } + return true; + } + + bool DeflateSlow(bool flush, bool finish) + { + if (lookahead < MIN_LOOKAHEAD && !flush) { + return false; + } + + while (lookahead >= MIN_LOOKAHEAD || flush) { + if (lookahead == 0) { + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + prevAvailable = false; + + // We are flushing everything +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && !flush) + { + throw new SharpZipBaseException("Not flushing, but no lookahead"); + } +#endif + huffman.FlushBlock(window, blockStart, strstart - blockStart, + finish); + blockStart = strstart; + return false; + } + + if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) { + /* slide window, as FindLongestMatch needs this. + * This should only happen when flushing and the window + * is almost full. + */ + SlideWindow(); + } + + int prevMatch = matchStart; + int prevLen = matchLen; + if (lookahead >= MIN_MATCH) { + + int hashHead = InsertString(); + + if (strategy != DeflateStrategy.HuffmanOnly && + hashHead != 0 && + strstart - hashHead <= MAX_DIST && + FindLongestMatch(hashHead)) { + + // longestMatch sets matchStart and matchLen + + // Discard match if too small and too far away + if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TooFar))) { + matchLen = MIN_MATCH - 1; + } + } + } + + // previous match was better + if ((prevLen >= MIN_MATCH) && (matchLen <= prevLen) ) { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) + { + for (int i = 0 ; i < matchLen; i++) { + if (window[strstart-1+i] != window[prevMatch + i]) + throw new SharpZipBaseException(); + } + } +#endif + huffman.TallyDist(strstart - 1 - prevMatch, prevLen); + prevLen -= 2; + do { + strstart++; + lookahead--; + if (lookahead >= MIN_MATCH) { + InsertString(); + } + } while (--prevLen > 0); + + strstart ++; + lookahead--; + prevAvailable = false; + matchLen = MIN_MATCH - 1; + } else { + if (prevAvailable) { + huffman.TallyLit(window[strstart-1] & 0xff); + } + prevAvailable = true; + strstart++; + lookahead--; + } + + if (huffman.IsFull()) { + int len = strstart - blockStart; + if (prevAvailable) { + len--; + } + bool lastBlock = (finish && (lookahead == 0) && !prevAvailable); + huffman.FlushBlock(window, blockStart, len, lastBlock); + blockStart += len; + return !lastBlock; + } + } + return true; + } + + #region Instance Fields + + // Hash index of string to be inserted + int ins_h; + + /// + /// Hashtable, hashing three characters to an index for window, so + /// that window[index]..window[index+2] have this hash code. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xffff. + /// + short[] head; + + /// + /// prev[index & WMASK] points to the previous index that has the + /// same hash code as the string starting at index. This way + /// entries with the same hash code are in a linked list. + /// Note that the array should really be unsigned short, so you need + /// to and the values with 0xffff. + /// + short[] prev; + + int matchStart; + // Length of best match + int matchLen; + // Set if previous match exists + bool prevAvailable; + int blockStart; + + /// + /// Points to the current character in the window. + /// + int strstart; + + /// + /// lookahead is the number of characters starting at strstart in + /// window that are valid. + /// So window[strstart] until window[strstart+lookahead-1] are valid + /// characters. + /// + int lookahead; + + /// + /// This array contains the part of the uncompressed stream that + /// is of relevance. The current character is indexed by strstart. + /// + byte[] window; + + DeflateStrategy strategy; + int max_chain, max_lazy, niceLength, goodLength; + + /// + /// The current compression function. + /// + int compressionFunction; + + /// + /// The input data for compression. + /// + byte[] inputBuf; + + /// + /// The total bytes of input read. + /// + long totalIn; + + /// + /// The offset into inputBuf, where input data starts. + /// + int inputOff; + + /// + /// The end offset of the input data. + /// + int inputEnd; + + DeflaterPending pending; + DeflaterHuffman huffman; + + /// + /// The adler checksum + /// + Adler32 adler; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterHuffman.cs b/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterHuffman.cs new file mode 100644 index 0000000..8c89e59 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterHuffman.cs @@ -0,0 +1,908 @@ +// DeflaterHuffman.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This is the DeflaterHuffman class. + /// + /// This class is not thread safe. This is inherent in the API, due + /// to the split of Deflate and SetInput. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class DeflaterHuffman + { + const int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6); + const int LITERAL_NUM = 286; + + // Number of distance codes + const int DIST_NUM = 30; + // Number of codes used to transfer bit lengths + const int BITLEN_NUM = 19; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + const int REP_3_6 = 16; + // repeat a zero length 3-10 times (3 bits of repeat count) + const int REP_3_10 = 17; + // repeat a zero length 11-138 times (7 bits of repeat count) + const int REP_11_138 = 18; + + const int EOF_SYMBOL = 256; + + // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit length codes. + static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + static readonly byte[] bit4Reverse = { + 0, + 8, + 4, + 12, + 2, + 10, + 6, + 14, + 1, + 9, + 5, + 13, + 3, + 11, + 7, + 15 + }; + + static short[] staticLCodes; + static byte[] staticLLength; + static short[] staticDCodes; + static byte[] staticDLength; + + class Tree + { + #region Instance Fields + public short[] freqs; + + public byte[] length; + + public int minNumCodes; + + public int numCodes; + + short[] codes; + int[] bl_counts; + int maxLength; + DeflaterHuffman dh; + #endregion + + #region Constructors + public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength) + { + this.dh = dh; + this.minNumCodes = minCodes; + this.maxLength = maxLength; + freqs = new short[elems]; + bl_counts = new int[maxLength]; + } + + #endregion + + /// + /// Resets the internal state of the tree + /// + public void Reset() + { + for (int i = 0; i < freqs.Length; i++) { + freqs[i] = 0; + } + codes = null; + length = null; + } + + public void WriteSymbol(int code) + { + // if (DeflaterConstants.DEBUGGING) { + // freqs[code]--; + // // Console.Write("writeSymbol("+freqs.length+","+code+"): "); + // } + dh.pending.WriteBits(codes[code] & 0xffff, length[code]); + } + + /// + /// Check that all frequencies are zero + /// + /// + /// At least one frequency is non-zero + /// + public void CheckEmpty() + { + bool empty = true; + for (int i = 0; i < freqs.Length; i++) { + if (freqs[i] != 0) { + //Console.WriteLine("freqs[" + i + "] == " + freqs[i]); + empty = false; + } + } + + if (!empty) { + throw new SharpZipBaseException("!Empty"); + } + } + + /// + /// Set static codes and length + /// + /// new codes + /// length for new codes + public void SetStaticCodes(short[] staticCodes, byte[] staticLengths) + { + codes = staticCodes; + length = staticLengths; + } + + /// + /// Build dynamic codes and lengths + /// + public void BuildCodes() + { + int numSymbols = freqs.Length; + int[] nextCode = new int[maxLength]; + int code = 0; + + codes = new short[freqs.Length]; + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("buildCodes: "+freqs.Length); + // } + + for (int bits = 0; bits < maxLength; bits++) { + nextCode[bits] = code; + code += bl_counts[bits] << (15 - bits); + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits] + // +" nextCode: "+code); + // } + } + +#if DebugDeflation + if ( DeflaterConstants.DEBUGGING && (code != 65536) ) + { + throw new SharpZipBaseException("Inconsistent bl_counts!"); + } +#endif + for (int i=0; i < numCodes; i++) { + int bits = length[i]; + if (bits > 0) { + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"), + // +bits); + // } + + codes[i] = BitReverse(nextCode[bits-1]); + nextCode[bits-1] += 1 << (16 - bits); + } + } + } + + public void BuildTree() + { + int numSymbols = freqs.Length; + + /* heap is a priority queue, sorted by frequency, least frequent + * nodes first. The heap is a binary tree, with the property, that + * the parent node is smaller than both child nodes. This assures + * that the smallest node is the first parent. + * + * The binary tree is encoded in an array: 0 is root node and + * the nodes 2*n+1, 2*n+2 are the child nodes of node n. + */ + int[] heap = new int[numSymbols]; + int heapLen = 0; + int maxCode = 0; + for (int n = 0; n < numSymbols; n++) { + int freq = freqs[n]; + if (freq != 0) { + // Insert n into heap + int pos = heapLen++; + int ppos; + while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) { + heap[pos] = heap[ppos]; + pos = ppos; + } + heap[pos] = n; + + maxCode = n; + } + } + + /* We could encode a single literal with 0 bits but then we + * don't see the literals. Therefore we force at least two + * literals to avoid this case. We don't care about order in + * this case, both literals get a 1 bit code. + */ + while (heapLen < 2) { + int node = maxCode < 2 ? ++maxCode : 0; + heap[heapLen++] = node; + } + + numCodes = Math.Max(maxCode + 1, minNumCodes); + + int numLeafs = heapLen; + int[] childs = new int[4 * heapLen - 2]; + int[] values = new int[2 * heapLen - 1]; + int numNodes = numLeafs; + for (int i = 0; i < heapLen; i++) { + int node = heap[i]; + childs[2 * i] = node; + childs[2 * i + 1] = -1; + values[i] = freqs[node] << 8; + heap[i] = i; + } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + do { + int first = heap[0]; + int last = heap[--heapLen]; + + // Propagate the hole to the leafs of the heap + int ppos = 0; + int path = 1; + + while (path < heapLen) { + if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) { + path++; + } + + heap[ppos] = heap[path]; + ppos = path; + path = path * 2 + 1; + } + + /* Now propagate the last element down along path. Normally + * it shouldn't go too deep. + */ + int lastVal = values[last]; + while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) { + heap[path] = heap[ppos]; + } + heap[path] = last; + + + int second = heap[0]; + + // Create a new node father of first and second + last = numNodes++; + childs[2 * last] = first; + childs[2 * last + 1] = second; + int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff); + values[last] = lastVal = values[first] + values[second] - mindepth + 1; + + // Again, propagate the hole to the leafs + ppos = 0; + path = 1; + + while (path < heapLen) { + if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) { + path++; + } + + heap[ppos] = heap[path]; + ppos = path; + path = ppos * 2 + 1; + } + + // Now propagate the new element down along path + while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) { + heap[path] = heap[ppos]; + } + heap[path] = last; + } while (heapLen > 1); + + if (heap[0] != childs.Length / 2 - 1) { + throw new SharpZipBaseException("Heap invariant violated"); + } + + BuildLength(childs); + } + + /// + /// Get encoded length + /// + /// Encoded length, the sum of frequencies * lengths + public int GetEncodedLength() + { + int len = 0; + for (int i = 0; i < freqs.Length; i++) { + len += freqs[i] * length[i]; + } + return len; + } + + /// + /// Scan a literal or distance tree to determine the frequencies of the codes + /// in the bit length tree. + /// + public void CalcBLFreq(Tree blTree) + { + int max_count; /* max repeat count */ + int min_count; /* min repeat count */ + int count; /* repeat count of the current code */ + int curlen = -1; /* length of current code */ + + int i = 0; + while (i < numCodes) { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else { + max_count = 6; + min_count = 3; + if (curlen != nextlen) { + blTree.freqs[nextlen]++; + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) { + i++; + if (++count >= max_count) { + break; + } + } + + if (count < min_count) { + blTree.freqs[curlen] += (short)count; + } else if (curlen != 0) { + blTree.freqs[REP_3_6]++; + } else if (count <= 10) { + blTree.freqs[REP_3_10]++; + } else { + blTree.freqs[REP_11_138]++; + } + } + } + + /// + /// Write tree values + /// + /// Tree to write + public void WriteTree(Tree blTree) + { + int max_count; // max repeat count + int min_count; // min repeat count + int count; // repeat count of the current code + int curlen = -1; // length of current code + + int i = 0; + while (i < numCodes) { + count = 1; + int nextlen = length[i]; + if (nextlen == 0) { + max_count = 138; + min_count = 3; + } else { + max_count = 6; + min_count = 3; + if (curlen != nextlen) { + blTree.WriteSymbol(nextlen); + count = 0; + } + } + curlen = nextlen; + i++; + + while (i < numCodes && curlen == length[i]) { + i++; + if (++count >= max_count) { + break; + } + } + + if (count < min_count) { + while (count-- > 0) { + blTree.WriteSymbol(curlen); + } + } else if (curlen != 0) { + blTree.WriteSymbol(REP_3_6); + dh.pending.WriteBits(count - 3, 2); + } else if (count <= 10) { + blTree.WriteSymbol(REP_3_10); + dh.pending.WriteBits(count - 3, 3); + } else { + blTree.WriteSymbol(REP_11_138); + dh.pending.WriteBits(count - 11, 7); + } + } + } + + void BuildLength(int[] childs) + { + this.length = new byte [freqs.Length]; + int numNodes = childs.Length / 2; + int numLeafs = (numNodes + 1) / 2; + int overflow = 0; + + for (int i = 0; i < maxLength; i++) { + bl_counts[i] = 0; + } + + // First calculate optimal bit lengths + int[] lengths = new int[numNodes]; + lengths[numNodes-1] = 0; + + for (int i = numNodes - 1; i >= 0; i--) { + if (childs[2 * i + 1] != -1) { + int bitLength = lengths[i] + 1; + if (bitLength > maxLength) { + bitLength = maxLength; + overflow++; + } + lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength; + } else { + // A leaf node + int bitLength = lengths[i]; + bl_counts[bitLength - 1]++; + this.length[childs[2*i]] = (byte) lengths[i]; + } + } + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Tree "+freqs.Length+" lengths:"); + // for (int i=0; i < numLeafs; i++) { + // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + // + " len: "+length[childs[2*i]]); + // } + // } + + if (overflow == 0) { + return; + } + + int incrBitLen = maxLength - 1; + do { + // Find the first bit length which could increase: + while (bl_counts[--incrBitLen] == 0) + ; + + // Move this node one down and remove a corresponding + // number of overflow nodes. + do { + bl_counts[incrBitLen]--; + bl_counts[++incrBitLen]++; + overflow -= 1 << (maxLength - 1 - incrBitLen); + } while (overflow > 0 && incrBitLen < maxLength - 1); + } while (overflow > 0); + + /* We may have overshot above. Move some nodes from maxLength to + * maxLength-1 in that case. + */ + bl_counts[maxLength-1] += overflow; + bl_counts[maxLength-2] -= overflow; + + /* Now recompute all bit lengths, scanning in increasing + * frequency. It is simpler to reconstruct all lengths instead of + * fixing only the wrong ones. This idea is taken from 'ar' + * written by Haruhiko Okumura. + * + * The nodes were inserted with decreasing frequency into the childs + * array. + */ + int nodePtr = 2 * numLeafs; + for (int bits = maxLength; bits != 0; bits--) { + int n = bl_counts[bits-1]; + while (n > 0) { + int childPtr = 2*childs[nodePtr++]; + if (childs[childPtr + 1] == -1) { + // We found another leaf + length[childs[childPtr]] = (byte) bits; + n--; + } + } + } + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("*** After overflow elimination. ***"); + // for (int i=0; i < numLeafs; i++) { + // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]] + // + " len: "+length[childs[2*i]]); + // } + // } + } + + } + + #region Instance Fields + /// + /// Pending buffer to use + /// + public DeflaterPending pending; + + Tree literalTree; + Tree distTree; + Tree blTree; + + // Buffer for distances + short[] d_buf; + byte[] l_buf; + int last_lit; + int extra_bits; + #endregion + + static DeflaterHuffman() + { + // See RFC 1951 3.2.6 + // Literal codes + staticLCodes = new short[LITERAL_NUM]; + staticLLength = new byte[LITERAL_NUM]; + + int i = 0; + while (i < 144) { + staticLCodes[i] = BitReverse((0x030 + i) << 8); + staticLLength[i++] = 8; + } + + while (i < 256) { + staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7); + staticLLength[i++] = 9; + } + + while (i < 280) { + staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9); + staticLLength[i++] = 7; + } + + while (i < LITERAL_NUM) { + staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8); + staticLLength[i++] = 8; + } + + // Distance codes + staticDCodes = new short[DIST_NUM]; + staticDLength = new byte[DIST_NUM]; + for (i = 0; i < DIST_NUM; i++) { + staticDCodes[i] = BitReverse(i << 11); + staticDLength[i] = 5; + } + } + + /// + /// Construct instance with pending buffer + /// + /// Pending buffer to use + public DeflaterHuffman(DeflaterPending pending) + { + this.pending = pending; + + literalTree = new Tree(this, LITERAL_NUM, 257, 15); + distTree = new Tree(this, DIST_NUM, 1, 15); + blTree = new Tree(this, BITLEN_NUM, 4, 7); + + d_buf = new short[BUFSIZE]; + l_buf = new byte [BUFSIZE]; + } + + /// + /// Reset internal state + /// + public void Reset() + { + last_lit = 0; + extra_bits = 0; + literalTree.Reset(); + distTree.Reset(); + blTree.Reset(); + } + + /// + /// Write all trees to pending buffer + /// + /// The number/rank of treecodes to send. + public void SendAllTrees(int blTreeCodes) + { + blTree.BuildCodes(); + literalTree.BuildCodes(); + distTree.BuildCodes(); + pending.WriteBits(literalTree.numCodes - 257, 5); + pending.WriteBits(distTree.numCodes - 1, 5); + pending.WriteBits(blTreeCodes - 4, 4); + for (int rank = 0; rank < blTreeCodes; rank++) { + pending.WriteBits(blTree.length[BL_ORDER[rank]], 3); + } + literalTree.WriteTree(blTree); + distTree.WriteTree(blTree); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + blTree.CheckEmpty(); + } +#endif + } + + /// + /// Compress current buffer writing data to pending buffer + /// + public void CompressBlock() + { + for (int i = 0; i < last_lit; i++) { + int litlen = l_buf[i] & 0xff; + int dist = d_buf[i]; + if (dist-- != 0) { + // if (DeflaterConstants.DEBUGGING) { + // Console.Write("["+(dist+1)+","+(litlen+3)+"]: "); + // } + + int lc = Lcode(litlen); + literalTree.WriteSymbol(lc); + + int bits = (lc - 261) / 4; + if (bits > 0 && bits <= 5) { + pending.WriteBits(litlen & ((1 << bits) - 1), bits); + } + + int dc = Dcode(dist); + distTree.WriteSymbol(dc); + + bits = dc / 2 - 1; + if (bits > 0) { + pending.WriteBits(dist & ((1 << bits) - 1), bits); + } + } else { + // if (DeflaterConstants.DEBUGGING) { + // if (litlen > 32 && litlen < 127) { + // Console.Write("("+(char)litlen+"): "); + // } else { + // Console.Write("{"+litlen+"}: "); + // } + // } + literalTree.WriteSymbol(litlen); + } + } + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + Console.Write("EOF: "); + } +#endif + literalTree.WriteSymbol(EOF_SYMBOL); + +#if DebugDeflation + if (DeflaterConstants.DEBUGGING) { + literalTree.CheckEmpty(); + distTree.CheckEmpty(); + } +#endif + } + + /// + /// Flush block to output with no compression + /// + /// Data to write + /// Index of first byte to write + /// Count of bytes to write + /// True if this is the last block + public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) + { +#if DebugDeflation + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Flushing stored block "+ storedLength); + // } +#endif + pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3); + pending.AlignToByte(); + pending.WriteShort(storedLength); + pending.WriteShort(~storedLength); + pending.WriteBlock(stored, storedOffset, storedLength); + Reset(); + } + + /// + /// Flush block to output with compression + /// + /// Data to flush + /// Index of first byte to flush + /// Count of bytes to flush + /// True if this is the last block + public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock) + { + literalTree.freqs[EOF_SYMBOL]++; + + // Build trees + literalTree.BuildTree(); + distTree.BuildTree(); + + // Calculate bitlen frequency + literalTree.CalcBLFreq(blTree); + distTree.CalcBLFreq(blTree); + + // Build bitlen tree + blTree.BuildTree(); + + int blTreeCodes = 4; + for (int i = 18; i > blTreeCodes; i--) { + if (blTree.length[BL_ORDER[i]] > 0) { + blTreeCodes = i+1; + } + } + int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() + + literalTree.GetEncodedLength() + distTree.GetEncodedLength() + + extra_bits; + + int static_len = extra_bits; + for (int i = 0; i < LITERAL_NUM; i++) { + static_len += literalTree.freqs[i] * staticLLength[i]; + } + for (int i = 0; i < DIST_NUM; i++) { + static_len += distTree.freqs[i] * staticDLength[i]; + } + if (opt_len >= static_len) { + // Force static trees + opt_len = static_len; + } + + if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) { + // Store Block + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len + // + " <= " + static_len); + // } + FlushStoredBlock(stored, storedOffset, storedLength, lastBlock); + } else if (opt_len == static_len) { + // Encode with static tree + pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3); + literalTree.SetStaticCodes(staticLCodes, staticLLength); + distTree.SetStaticCodes(staticDCodes, staticDLength); + CompressBlock(); + Reset(); + } else { + // Encode with dynamic tree + pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3); + SendAllTrees(blTreeCodes); + CompressBlock(); + Reset(); + } + } + + /// + /// Get value indicating if internal buffer is full + /// + /// true if buffer is full + public bool IsFull() + { + return last_lit >= BUFSIZE; + } + + /// + /// Add literal to buffer + /// + /// Literal value to add to buffer. + /// Value indicating internal buffer is full + public bool TallyLit(int literal) + { + // if (DeflaterConstants.DEBUGGING) { + // if (lit > 32 && lit < 127) { + // //Console.WriteLine("("+(char)lit+")"); + // } else { + // //Console.WriteLine("{"+lit+"}"); + // } + // } + d_buf[last_lit] = 0; + l_buf[last_lit++] = (byte)literal; + literalTree.freqs[literal]++; + return IsFull(); + } + + /// + /// Add distance code and length to literal and distance trees + /// + /// Distance code + /// Length + /// Value indicating if internal buffer is full + public bool TallyDist(int distance, int length) + { + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("[" + distance + "," + length + "]"); + // } + + d_buf[last_lit] = (short)distance; + l_buf[last_lit++] = (byte)(length - 3); + + int lc = Lcode(length - 3); + literalTree.freqs[lc]++; + if (lc >= 265 && lc < 285) { + extra_bits += (lc - 261) / 4; + } + + int dc = Dcode(distance - 1); + distTree.freqs[dc]++; + if (dc >= 4) { + extra_bits += dc / 2 - 1; + } + return IsFull(); + } + + + /// + /// Reverse the bits of a 16 bit value. + /// + /// Value to reverse bits + /// Value with bits reversed + public static short BitReverse(int toReverse) + { + return (short) (bit4Reverse[toReverse & 0xF] << 12 | + bit4Reverse[(toReverse >> 4) & 0xF] << 8 | + bit4Reverse[(toReverse >> 8) & 0xF] << 4 | + bit4Reverse[toReverse >> 12]); + } + + static int Lcode(int length) + { + if (length == 255) { + return 285; + } + + int code = 257; + while (length >= 8) { + code += 4; + length >>= 1; + } + return code + length; + } + + static int Dcode(int distance) + { + int code = 0; + while (distance >= 4) { + code += 2; + distance >>= 1; + } + return code + distance; + } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterPending.cs b/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterPending.cs new file mode 100644 index 0000000..4cecc2e --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/DeflaterPending.cs @@ -0,0 +1,57 @@ +// DeflaterPending.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class stores the pending output of the Deflater. + /// + /// author of the original java version : Jochen Hoenicke + /// + public class DeflaterPending : PendingBuffer + { + /// + /// Construct instance with default buffer size + /// + public DeflaterPending() : base(DeflaterConstants.PENDING_BUF_SIZE) + { + } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/Inflater.cs b/类库/VersionUpdate/ZIP/Zip/Compression/Inflater.cs new file mode 100644 index 0000000..16c3ef6 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/Inflater.cs @@ -0,0 +1,864 @@ +// Inflater.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + /// + /// Inflater is used to decompress data that has been compressed according + /// to the "deflate" standard described in rfc1951. + /// + /// By default Zlib (rfc1950) headers and footers are expected in the input. + /// You can use constructor public Inflater(bool noHeader) passing true + /// if there is no Zlib header information + /// + /// The usage is as following. First you have to set some input with + /// SetInput(), then Inflate() it. If inflate doesn't + /// inflate any bytes there may be three reasons: + ///
    + ///
  • IsNeedingInput() returns true because the input buffer is empty. + /// You have to provide more input with SetInput(). + /// NOTE: IsNeedingInput() also returns true when, the stream is finished. + ///
  • + ///
  • IsNeedingDictionary() returns true, you have to provide a preset + /// dictionary with SetDictionary().
  • + ///
  • IsFinished returns true, the inflater has finished.
  • + ///
+ /// Once the first output byte is produced, a dictionary will not be + /// needed at a later stage. + /// + /// author of the original java version : John Leuner, Jochen Hoenicke + ///
+ public class Inflater + { + #region Constants/Readonly + /// + /// Copy lengths for literal codes 257..285 + /// + static readonly int[] CPLENS = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 + }; + + /// + /// Extra bits for literal codes 257..285 + /// + static readonly int[] CPLEXT = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 + }; + + /// + /// Copy offsets for distance codes 0..29 + /// + static readonly int[] CPDIST = { + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + /// + /// Extra bits for distance codes + /// + static readonly int[] CPDEXT = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13 + }; + + /// + /// These are the possible states for an inflater + /// + const int DECODE_HEADER = 0; + const int DECODE_DICT = 1; + const int DECODE_BLOCKS = 2; + const int DECODE_STORED_LEN1 = 3; + const int DECODE_STORED_LEN2 = 4; + const int DECODE_STORED = 5; + const int DECODE_DYN_HEADER = 6; + const int DECODE_HUFFMAN = 7; + const int DECODE_HUFFMAN_LENBITS = 8; + const int DECODE_HUFFMAN_DIST = 9; + const int DECODE_HUFFMAN_DISTBITS = 10; + const int DECODE_CHKSUM = 11; + const int FINISHED = 12; + #endregion + + #region Instance Fields + /// + /// This variable contains the current state. + /// + int mode; + + /// + /// The adler checksum of the dictionary or of the decompressed + /// stream, as it is written in the header resp. footer of the + /// compressed stream. + /// Only valid if mode is DECODE_DICT or DECODE_CHKSUM. + /// + int readAdler; + + /// + /// The number of bits needed to complete the current state. This + /// is valid, if mode is DECODE_DICT, DECODE_CHKSUM, + /// DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. + /// + int neededBits; + int repLength; + int repDist; + int uncomprLen; + + /// + /// True, if the last block flag was set in the last block of the + /// inflated stream. This means that the stream ends after the + /// current block. + /// + bool isLastBlock; + + /// + /// The total number of inflated bytes. + /// + long totalOut; + + /// + /// The total number of bytes set with setInput(). This is not the + /// value returned by the TotalIn property, since this also includes the + /// unprocessed input. + /// + long totalIn; + + /// + /// This variable stores the noHeader flag that was given to the constructor. + /// True means, that the inflated stream doesn't contain a Zlib header or + /// footer. + /// + bool noHeader; + + StreamManipulator input; + OutputWindow outputWindow; + InflaterDynHeader dynHeader; + InflaterHuffmanTree litlenTree, distTree; + Adler32 adler; + #endregion + + #region Constructors + /// + /// Creates a new inflater or RFC1951 decompressor + /// RFC1950/Zlib headers and footers will be expected in the input data + /// + public Inflater() : this(false) + { + } + + /// + /// Creates a new inflater. + /// + /// + /// True if no RFC1950/Zlib header and footer fields are expected in the input data + /// + /// This is used for GZIPed/Zipped input. + /// + /// For compatibility with + /// Sun JDK you should provide one byte of input more than needed in + /// this case. + /// + public Inflater(bool noHeader) + { + this.noHeader = noHeader; + this.adler = new Adler32(); + input = new StreamManipulator(); + outputWindow = new OutputWindow(); + mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; + } + #endregion + + /// + /// Resets the inflater so that a new stream can be decompressed. All + /// pending input and output will be discarded. + /// + public void Reset() + { + mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER; + totalIn = 0; + totalOut = 0; + input.Reset(); + outputWindow.Reset(); + dynHeader = null; + litlenTree = null; + distTree = null; + isLastBlock = false; + adler.Reset(); + } + + /// + /// Decodes a zlib/RFC1950 header. + /// + /// + /// False if more input is needed. + /// + /// + /// The header is invalid. + /// + private bool DecodeHeader() + { + int header = input.PeekBits(16); + if (header < 0) { + return false; + } + input.DropBits(16); + + // The header is written in "wrong" byte order + header = ((header << 8) | (header >> 8)) & 0xffff; + if (header % 31 != 0) { + throw new SharpZipBaseException("Header checksum illegal"); + } + + if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) { + throw new SharpZipBaseException("Compression Method unknown"); + } + + /* Maximum size of the backwards window in bits. + * We currently ignore this, but we could use it to make the + * inflater window more space efficient. On the other hand the + * full window (15 bits) is needed most times, anyway. + int max_wbits = ((header & 0x7000) >> 12) + 8; + */ + + if ((header & 0x0020) == 0) { // Dictionary flag? + mode = DECODE_BLOCKS; + } else { + mode = DECODE_DICT; + neededBits = 32; + } + return true; + } + + /// + /// Decodes the dictionary checksum after the deflate header. + /// + /// + /// False if more input is needed. + /// + private bool DecodeDict() + { + while (neededBits > 0) { + int dictByte = input.PeekBits(8); + if (dictByte < 0) { + return false; + } + input.DropBits(8); + readAdler = (readAdler << 8) | dictByte; + neededBits -= 8; + } + return false; + } + + /// + /// Decodes the huffman encoded symbols in the input stream. + /// + /// + /// false if more input is needed, true if output window is + /// full or the current block ends. + /// + /// + /// if deflated stream is invalid. + /// + private bool DecodeHuffman() + { + int free = outputWindow.GetFreeSpace(); + while (free >= 258) + { + int symbol; + switch (mode) + { + case DECODE_HUFFMAN: + // This is the inner loop so it is optimized a bit + while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0) + { + outputWindow.Write(symbol); + if (--free < 258) + { + return true; + } + } + + if (symbol < 257) + { + if (symbol < 0) + { + return false; + } + else + { + // symbol == 256: end of block + distTree = null; + litlenTree = null; + mode = DECODE_BLOCKS; + return true; + } + } + + try + { + repLength = CPLENS[symbol - 257]; + neededBits = CPLEXT[symbol - 257]; + } + catch (Exception) + { + throw new SharpZipBaseException("Illegal rep length code"); + } + goto case DECODE_HUFFMAN_LENBITS; // fall through + + case DECODE_HUFFMAN_LENBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_LENBITS; + int i = input.PeekBits(neededBits); + if (i < 0) + { + return false; + } + input.DropBits(neededBits); + repLength += i; + } + mode = DECODE_HUFFMAN_DIST; + goto case DECODE_HUFFMAN_DIST; // fall through + + case DECODE_HUFFMAN_DIST: + symbol = distTree.GetSymbol(input); + if (symbol < 0) + { + return false; + } + + try + { + repDist = CPDIST[symbol]; + neededBits = CPDEXT[symbol]; + } + catch (Exception) + { + throw new SharpZipBaseException("Illegal rep dist code"); + } + + goto case DECODE_HUFFMAN_DISTBITS; // fall through + + case DECODE_HUFFMAN_DISTBITS: + if (neededBits > 0) + { + mode = DECODE_HUFFMAN_DISTBITS; + int i = input.PeekBits(neededBits); + if (i < 0) + { + return false; + } + input.DropBits(neededBits); + repDist += i; + } + + outputWindow.Repeat(repLength, repDist); + free -= repLength; + mode = DECODE_HUFFMAN; + break; + + default: + throw new SharpZipBaseException("Inflater unknown mode"); + } + } + return true; + } + + /// + /// Decodes the adler checksum after the deflate stream. + /// + /// + /// false if more input is needed. + /// + /// + /// If checksum doesn't match. + /// + private bool DecodeChksum() + { + while (neededBits > 0) { + int chkByte = input.PeekBits(8); + if (chkByte < 0) { + return false; + } + input.DropBits(8); + readAdler = (readAdler << 8) | chkByte; + neededBits -= 8; + } + + if ((int) adler.Value != readAdler) { + throw new SharpZipBaseException("Adler chksum doesn't match: " + (int)adler.Value + " vs. " + readAdler); + } + + mode = FINISHED; + return false; + } + + /// + /// Decodes the deflated stream. + /// + /// + /// false if more input is needed, or if finished. + /// + /// + /// if deflated stream is invalid. + /// + private bool Decode() + { + switch (mode) { + case DECODE_HEADER: + return DecodeHeader(); + + case DECODE_DICT: + return DecodeDict(); + + case DECODE_CHKSUM: + return DecodeChksum(); + + case DECODE_BLOCKS: + if (isLastBlock) { + if (noHeader) { + mode = FINISHED; + return false; + } else { + input.SkipToByteBoundary(); + neededBits = 32; + mode = DECODE_CHKSUM; + return true; + } + } + + int type = input.PeekBits(3); + if (type < 0) { + return false; + } + input.DropBits(3); + + if ((type & 1) != 0) { + isLastBlock = true; + } + switch (type >> 1){ + case DeflaterConstants.STORED_BLOCK: + input.SkipToByteBoundary(); + mode = DECODE_STORED_LEN1; + break; + case DeflaterConstants.STATIC_TREES: + litlenTree = InflaterHuffmanTree.defLitLenTree; + distTree = InflaterHuffmanTree.defDistTree; + mode = DECODE_HUFFMAN; + break; + case DeflaterConstants.DYN_TREES: + dynHeader = new InflaterDynHeader(); + mode = DECODE_DYN_HEADER; + break; + default: + throw new SharpZipBaseException("Unknown block type " + type); + } + return true; + + case DECODE_STORED_LEN1: + { + if ((uncomprLen = input.PeekBits(16)) < 0) { + return false; + } + input.DropBits(16); + mode = DECODE_STORED_LEN2; + } + goto case DECODE_STORED_LEN2; // fall through + + case DECODE_STORED_LEN2: + { + int nlen = input.PeekBits(16); + if (nlen < 0) { + return false; + } + input.DropBits(16); + if (nlen != (uncomprLen ^ 0xffff)) { + throw new SharpZipBaseException("broken uncompressed block"); + } + mode = DECODE_STORED; + } + goto case DECODE_STORED; // fall through + + case DECODE_STORED: + { + int more = outputWindow.CopyStored(input, uncomprLen); + uncomprLen -= more; + if (uncomprLen == 0) { + mode = DECODE_BLOCKS; + return true; + } + return !input.IsNeedingInput; + } + + case DECODE_DYN_HEADER: + if (!dynHeader.Decode(input)) { + return false; + } + + litlenTree = dynHeader.BuildLitLenTree(); + distTree = dynHeader.BuildDistTree(); + mode = DECODE_HUFFMAN; + goto case DECODE_HUFFMAN; // fall through + + case DECODE_HUFFMAN: + case DECODE_HUFFMAN_LENBITS: + case DECODE_HUFFMAN_DIST: + case DECODE_HUFFMAN_DISTBITS: + return DecodeHuffman(); + + case FINISHED: + return false; + + default: + throw new SharpZipBaseException("Inflater.Decode unknown mode"); + } + } + + /// + /// Sets the preset dictionary. This should only be called, if + /// needsDictionary() returns true and it should set the same + /// dictionary, that was used for deflating. The getAdler() + /// function returns the checksum of the dictionary needed. + /// + /// + /// The dictionary. + /// + public void SetDictionary(byte[] buffer) + { + SetDictionary(buffer, 0, buffer.Length); + } + + /// + /// Sets the preset dictionary. This should only be called, if + /// needsDictionary() returns true and it should set the same + /// dictionary, that was used for deflating. The getAdler() + /// function returns the checksum of the dictionary needed. + /// + /// + /// The dictionary. + /// + /// + /// The index into buffer where the dictionary starts. + /// + /// + /// The number of bytes in the dictionary. + /// + /// + /// No dictionary is needed. + /// + /// + /// The adler checksum for the buffer is invalid + /// + public void SetDictionary(byte[] buffer, int index, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( index < 0 ) { + throw new ArgumentOutOfRangeException("index"); + } + + if ( count < 0 ) { + throw new ArgumentOutOfRangeException("count"); + } + + if (!IsNeedingDictionary) { + throw new InvalidOperationException("Dictionary is not needed"); + } + + adler.Update(buffer, index, count); + + if ((int)adler.Value != readAdler) { + throw new SharpZipBaseException("Wrong adler checksum"); + } + adler.Reset(); + outputWindow.CopyDict(buffer, index, count); + mode = DECODE_BLOCKS; + } + + /// + /// Sets the input. This should only be called, if needsInput() + /// returns true. + /// + /// + /// the input. + /// + public void SetInput(byte[] buffer) + { + SetInput(buffer, 0, buffer.Length); + } + + /// + /// Sets the input. This should only be called, if needsInput() + /// returns true. + /// + /// + /// The source of input data + /// + /// + /// The index into buffer where the input starts. + /// + /// + /// The number of bytes of input to use. + /// + /// + /// No input is needed. + /// + /// + /// The index and/or count are wrong. + /// + public void SetInput(byte[] buffer, int index, int count) + { + input.SetInput(buffer, index, count); + totalIn += (long)count; + } + + /// + /// Inflates the compressed stream to the output buffer. If this + /// returns 0, you should check, whether IsNeedingDictionary(), + /// IsNeedingInput() or IsFinished() returns true, to determine why no + /// further output is produced. + /// + /// + /// the output buffer. + /// + /// + /// The number of bytes written to the buffer, 0 if no further + /// output can be produced. + /// + /// + /// if buffer has length 0. + /// + /// + /// if deflated stream is invalid. + /// + public int Inflate(byte[] buffer) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + return Inflate(buffer, 0, buffer.Length); + } + + /// + /// Inflates the compressed stream to the output buffer. If this + /// returns 0, you should check, whether needsDictionary(), + /// needsInput() or finished() returns true, to determine why no + /// further output is produced. + /// + /// + /// the output buffer. + /// + /// + /// the offset in buffer where storing starts. + /// + /// + /// the maximum number of bytes to output. + /// + /// + /// the number of bytes written to the buffer, 0 if no further output can be produced. + /// + /// + /// if count is less than 0. + /// + /// + /// if the index and / or count are wrong. + /// + /// + /// if deflated stream is invalid. + /// + public int Inflate(byte[] buffer, int offset, int count) + { + if ( buffer == null ) + { + throw new ArgumentNullException("buffer"); + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "count cannot be negative"); +#endif + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "offset cannot be negative"); +#endif + } + + if ( offset + count > buffer.Length ) { + throw new ArgumentException("count exceeds buffer bounds"); + } + + // Special case: count may be zero + if (count == 0) + { + if (!IsFinished) { // -jr- 08-Nov-2003 INFLATE_BUG fix.. + Decode(); + } + return 0; + } + + int bytesCopied = 0; + + do { + if (mode != DECODE_CHKSUM) { + /* Don't give away any output, if we are waiting for the + * checksum in the input stream. + * + * With this trick we have always: + * IsNeedingInput() and not IsFinished() + * implies more output can be produced. + */ + int more = outputWindow.CopyOutput(buffer, offset, count); + if ( more > 0 ) { + adler.Update(buffer, offset, more); + offset += more; + bytesCopied += more; + totalOut += (long)more; + count -= more; + if (count == 0) { + return bytesCopied; + } + } + } + } while (Decode() || ((outputWindow.GetAvailable() > 0) && (mode != DECODE_CHKSUM))); + return bytesCopied; + } + + /// + /// Returns true, if the input buffer is empty. + /// You should then call setInput(). + /// NOTE: This method also returns true when the stream is finished. + /// + public bool IsNeedingInput { + get { + return input.IsNeedingInput; + } + } + + /// + /// Returns true, if a preset dictionary is needed to inflate the input. + /// + public bool IsNeedingDictionary { + get { + return mode == DECODE_DICT && neededBits == 0; + } + } + + /// + /// Returns true, if the inflater has finished. This means, that no + /// input is needed and no output can be produced. + /// + public bool IsFinished { + get { + return mode == FINISHED && outputWindow.GetAvailable() == 0; + } + } + + /// + /// Gets the adler checksum. This is either the checksum of all + /// uncompressed bytes returned by inflate(), or if needsDictionary() + /// returns true (and thus no output was yet produced) this is the + /// adler checksum of the expected dictionary. + /// + /// + /// the adler checksum. + /// + public int Adler { + get { + return IsNeedingDictionary ? readAdler : (int) adler.Value; + } + } + + /// + /// Gets the total number of output bytes returned by Inflate(). + /// + /// + /// the total number of output bytes. + /// + public long TotalOut { + get { + return totalOut; + } + } + + /// + /// Gets the total number of processed compressed input bytes. + /// + /// + /// The total number of bytes of processed input bytes. + /// + public long TotalIn { + get { + return totalIn - (long)RemainingInput; + } + } + + /// + /// Gets the number of unprocessed input bytes. Useful, if the end of the + /// stream is reached and you want to further process the bytes after + /// the deflate stream. + /// + /// + /// The number of bytes of the input which have not been processed. + /// + public int RemainingInput { + // TODO: This should be a long? + get { + return input.AvailableBytes; + } + } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/InflaterDynHeader.cs b/类库/VersionUpdate/ZIP/Zip/Compression/InflaterDynHeader.cs new file mode 100644 index 0000000..77e87ac --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/InflaterDynHeader.cs @@ -0,0 +1,218 @@ +// InflaterDynHeader.cs +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + class InflaterDynHeader + { + #region Constants + const int LNUM = 0; + const int DNUM = 1; + const int BLNUM = 2; + const int BLLENS = 3; + const int LENS = 4; + const int REPS = 5; + + static readonly int[] repMin = { 3, 3, 11 }; + static readonly int[] repBits = { 2, 3, 7 }; + + static readonly int[] BL_ORDER = + { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + + #endregion + + #region Constructors + public InflaterDynHeader() + { + } + #endregion + + public bool Decode(StreamManipulator input) + { + decode_loop: + for (;;) { + switch (mode) { + case LNUM: + lnum = input.PeekBits(5); + if (lnum < 0) { + return false; + } + lnum += 257; + input.DropBits(5); + // System.err.println("LNUM: "+lnum); + mode = DNUM; + goto case DNUM; // fall through + case DNUM: + dnum = input.PeekBits(5); + if (dnum < 0) { + return false; + } + dnum++; + input.DropBits(5); + // System.err.println("DNUM: "+dnum); + num = lnum+dnum; + litdistLens = new byte[num]; + mode = BLNUM; + goto case BLNUM; // fall through + case BLNUM: + blnum = input.PeekBits(4); + if (blnum < 0) { + return false; + } + blnum += 4; + input.DropBits(4); + blLens = new byte[19]; + ptr = 0; + // System.err.println("BLNUM: "+blnum); + mode = BLLENS; + goto case BLLENS; // fall through + case BLLENS: + while (ptr < blnum) { + int len = input.PeekBits(3); + if (len < 0) { + return false; + } + input.DropBits(3); + // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len); + blLens[BL_ORDER[ptr]] = (byte) len; + ptr++; + } + blTree = new InflaterHuffmanTree(blLens); + blLens = null; + ptr = 0; + mode = LENS; + goto case LENS; // fall through + case LENS: + { + int symbol; + while (((symbol = blTree.GetSymbol(input)) & ~15) == 0) { + /* Normal case: symbol in [0..15] */ + + // System.err.println("litdistLens["+ptr+"]: "+symbol); + litdistLens[ptr++] = lastLen = (byte)symbol; + + if (ptr == num) { + /* Finished */ + return true; + } + } + + /* need more input ? */ + if (symbol < 0) { + return false; + } + + /* otherwise repeat code */ + if (symbol >= 17) { + /* repeat zero */ + // System.err.println("repeating zero"); + lastLen = 0; + } else { + if (ptr == 0) { + throw new SharpZipBaseException(); + } + } + repSymbol = symbol-16; + } + mode = REPS; + goto case REPS; // fall through + case REPS: + { + int bits = repBits[repSymbol]; + int count = input.PeekBits(bits); + if (count < 0) { + return false; + } + input.DropBits(bits); + count += repMin[repSymbol]; + // System.err.println("litdistLens repeated: "+count); + + if (ptr + count > num) { + throw new SharpZipBaseException(); + } + while (count-- > 0) { + litdistLens[ptr++] = lastLen; + } + + if (ptr == num) { + /* Finished */ + return true; + } + } + mode = LENS; + goto decode_loop; + } + } + } + + public InflaterHuffmanTree BuildLitLenTree() + { + byte[] litlenLens = new byte[lnum]; + Array.Copy(litdistLens, 0, litlenLens, 0, lnum); + return new InflaterHuffmanTree(litlenLens); + } + + public InflaterHuffmanTree BuildDistTree() + { + byte[] distLens = new byte[dnum]; + Array.Copy(litdistLens, lnum, distLens, 0, dnum); + return new InflaterHuffmanTree(distLens); + } + + #region Instance Fields + byte[] blLens; + byte[] litdistLens; + + InflaterHuffmanTree blTree; + + /// + /// The current decode mode + /// + int mode; + int lnum, dnum, blnum, num; + int repSymbol; + byte lastLen; + int ptr; + #endregion + + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/InflaterHuffmanTree.cs b/类库/VersionUpdate/ZIP/Zip/Compression/InflaterHuffmanTree.cs new file mode 100644 index 0000000..2f61118 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/InflaterHuffmanTree.cs @@ -0,0 +1,232 @@ +// InflaterHuffmanTree.cs +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// Huffman tree used for inflation + /// + public class InflaterHuffmanTree + { + #region Constants + const int MAX_BITLEN = 15; + #endregion + + #region Instance Fields + short[] tree; + #endregion + + /// + /// Literal length tree + /// + public static InflaterHuffmanTree defLitLenTree; + + /// + /// Distance tree + /// + public static InflaterHuffmanTree defDistTree; + + static InflaterHuffmanTree() + { + try { + byte[] codeLengths = new byte[288]; + int i = 0; + while (i < 144) { + codeLengths[i++] = 8; + } + while (i < 256) { + codeLengths[i++] = 9; + } + while (i < 280) { + codeLengths[i++] = 7; + } + while (i < 288) { + codeLengths[i++] = 8; + } + defLitLenTree = new InflaterHuffmanTree(codeLengths); + + codeLengths = new byte[32]; + i = 0; + while (i < 32) { + codeLengths[i++] = 5; + } + defDistTree = new InflaterHuffmanTree(codeLengths); + } catch (Exception) { + throw new SharpZipBaseException("InflaterHuffmanTree: static tree length illegal"); + } + } + + #region Constructors + /// + /// Constructs a Huffman tree from the array of code lengths. + /// + /// + /// the array of code lengths + /// + public InflaterHuffmanTree(byte[] codeLengths) + { + BuildTree(codeLengths); + } + #endregion + + void BuildTree(byte[] codeLengths) + { + int[] blCount = new int[MAX_BITLEN + 1]; + int[] nextCode = new int[MAX_BITLEN + 1]; + + for (int i = 0; i < codeLengths.Length; i++) { + int bits = codeLengths[i]; + if (bits > 0) { + blCount[bits]++; + } + } + + int code = 0; + int treeSize = 512; + for (int bits = 1; bits <= MAX_BITLEN; bits++) { + nextCode[bits] = code; + code += blCount[bits] << (16 - bits); + if (bits >= 10) { + /* We need an extra table for bit lengths >= 10. */ + int start = nextCode[bits] & 0x1ff80; + int end = code & 0x1ff80; + treeSize += (end - start) >> (16 - bits); + } + } + +/* -jr comment this out! doesnt work for dynamic trees and pkzip 2.04g + if (code != 65536) + { + throw new SharpZipBaseException("Code lengths don't add up properly."); + } +*/ + /* Now create and fill the extra tables from longest to shortest + * bit len. This way the sub trees will be aligned. + */ + tree = new short[treeSize]; + int treePtr = 512; + for (int bits = MAX_BITLEN; bits >= 10; bits--) { + int end = code & 0x1ff80; + code -= blCount[bits] << (16 - bits); + int start = code & 0x1ff80; + for (int i = start; i < end; i += 1 << 7) { + tree[DeflaterHuffman.BitReverse(i)] = (short) ((-treePtr << 4) | bits); + treePtr += 1 << (bits-9); + } + } + + for (int i = 0; i < codeLengths.Length; i++) { + int bits = codeLengths[i]; + if (bits == 0) { + continue; + } + code = nextCode[bits]; + int revcode = DeflaterHuffman.BitReverse(code); + if (bits <= 9) { + do { + tree[revcode] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } while (revcode < 512); + } else { + int subTree = tree[revcode & 511]; + int treeLen = 1 << (subTree & 15); + subTree = -(subTree >> 4); + do { + tree[subTree | (revcode >> 9)] = (short) ((i << 4) | bits); + revcode += 1 << bits; + } while (revcode < treeLen); + } + nextCode[bits] = code + (1 << (16 - bits)); + } + + } + + /// + /// Reads the next symbol from input. The symbol is encoded using the + /// huffman tree. + /// + /// + /// input the input source. + /// + /// + /// the next symbol, or -1 if not enough input is available. + /// + public int GetSymbol(StreamManipulator input) + { + int lookahead, symbol; + if ((lookahead = input.PeekBits(9)) >= 0) { + if ((symbol = tree[lookahead]) >= 0) { + input.DropBits(symbol & 15); + return symbol >> 4; + } + int subtree = -(symbol >> 4); + int bitlen = symbol & 15; + if ((lookahead = input.PeekBits(bitlen)) >= 0) { + symbol = tree[subtree | (lookahead >> 9)]; + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + int bits = input.AvailableBits; + lookahead = input.PeekBits(bits); + symbol = tree[subtree | (lookahead >> 9)]; + if ((symbol & 15) <= bits) { + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + return -1; + } + } + } else { + int bits = input.AvailableBits; + lookahead = input.PeekBits(bits); + symbol = tree[lookahead]; + if (symbol >= 0 && (symbol & 15) <= bits) { + input.DropBits(symbol & 15); + return symbol >> 4; + } else { + return -1; + } + } + } + } +} + diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/PendingBuffer.cs b/类库/VersionUpdate/ZIP/Zip/Compression/PendingBuffer.cs new file mode 100644 index 0000000..d205845 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/PendingBuffer.cs @@ -0,0 +1,295 @@ +// PendingBuffer.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression +{ + + /// + /// This class is general purpose class for writing data to a buffer. + /// + /// It allows you to write bits as well as bytes + /// Based on DeflaterPending.java + /// + /// author of the original java version : Jochen Hoenicke + /// + public class PendingBuffer + { + #region Instance Fields + /// + /// Internal work buffer + /// + byte[] buffer_; + + int start; + int end; + + uint bits; + int bitCount; + #endregion + + #region Constructors + /// + /// construct instance using default buffer size of 4096 + /// + public PendingBuffer() : this( 4096 ) + { + } + + /// + /// construct instance using specified buffer size + /// + /// + /// size to use for internal buffer + /// + public PendingBuffer(int bufferSize) + { + buffer_ = new byte[bufferSize]; + } + + #endregion + + /// + /// Clear internal state/buffers + /// + public void Reset() + { + start = end = bitCount = 0; + } + + /// + /// Write a byte to buffer + /// + /// + /// The value to write + /// + public void WriteByte(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + } + + /// + /// Write a short value to buffer LSB first + /// + /// + /// The value to write. + /// + public void WriteShort(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + buffer_[end++] = unchecked((byte) (value >> 8)); + } + + /// + /// write an integer LSB first + /// + /// The value to write. + public void WriteInt(int value) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) value); + buffer_[end++] = unchecked((byte) (value >> 8)); + buffer_[end++] = unchecked((byte) (value >> 16)); + buffer_[end++] = unchecked((byte) (value >> 24)); + } + + /// + /// Write a block of data to buffer + /// + /// data to write + /// offset of first byte to write + /// number of bytes to write + public void WriteBlock(byte[] block, int offset, int length) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + System.Array.Copy(block, offset, buffer_, end, length); + end += length; + } + + /// + /// The number of bits written to the buffer + /// + public int BitCount { + get { + return bitCount; + } + } + + /// + /// Align internal buffer on a byte boundary + /// + public void AlignToByte() + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + if (bitCount > 0) + { + buffer_[end++] = unchecked((byte) bits); + if (bitCount > 8) { + buffer_[end++] = unchecked((byte) (bits >> 8)); + } + } + bits = 0; + bitCount = 0; + } + + /// + /// Write bits to internal buffer + /// + /// source of bits + /// number of bits to write + public void WriteBits(int b, int count) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } + + // if (DeflaterConstants.DEBUGGING) { + // //Console.WriteLine("writeBits("+b+","+count+")"); + // } +#endif + bits |= (uint)(b << bitCount); + bitCount += count; + if (bitCount >= 16) { + buffer_[end++] = unchecked((byte) bits); + buffer_[end++] = unchecked((byte) (bits >> 8)); + bits >>= 16; + bitCount -= 16; + } + } + + /// + /// Write a short value to internal buffer most significant byte first + /// + /// value to write + public void WriteShortMSB(int s) + { +#if DebugDeflation + if (DeflaterConstants.DEBUGGING && (start != 0) ) + { + throw new SharpZipBaseException("Debug check: start != 0"); + } +#endif + buffer_[end++] = unchecked((byte) (s >> 8)); + buffer_[end++] = unchecked((byte) s); + } + + /// + /// Indicates if buffer has been flushed + /// + public bool IsFlushed { + get { + return end == 0; + } + } + + /// + /// Flushes the pending buffer into the given output array. If the + /// output array is to small, only a partial flush is done. + /// + /// The output array. + /// The offset into output array. + /// The maximum number of bytes to store. + /// The number of bytes flushed. + public int Flush(byte[] output, int offset, int length) + { + if (bitCount >= 8) { + buffer_[end++] = unchecked((byte) bits); + bits >>= 8; + bitCount -= 8; + } + + if (length > end - start) { + length = end - start; + System.Array.Copy(buffer_, start, output, offset, length); + start = 0; + end = 0; + } else { + System.Array.Copy(buffer_, start, output, offset, length); + start += length; + } + return length; + } + + /// + /// Convert internal buffer to byte array. + /// Buffer is empty on completion + /// + /// + /// The internal buffer contents converted to a byte array. + /// + public byte[] ToByteArray() + { + byte[] result = new byte[end - start]; + System.Array.Copy(buffer_, start, result, 0, result.Length); + start = 0; + end = 0; + return result; + } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs b/类库/VersionUpdate/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs new file mode 100644 index 0000000..3e9fea9 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/Streams/DeflaterOutputStream.cs @@ -0,0 +1,603 @@ +// DeflaterOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support + +using System; +using System.IO; + +#if !NETCF_1_0 +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Encryption; +using ICSharpCode.SharpZipLib.Zip1; +#endif + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + /// + /// A special stream deflating or compressing the bytes that are + /// written to it. It uses a Deflater to perform actual deflating.
+ /// Authors of the original java version : Tom Tromey, Jochen Hoenicke + ///
+ public class DeflaterOutputStream : Stream + { + #region Constructors + /// + /// Creates a new DeflaterOutputStream with a default Deflater and default buffer size. + /// + /// + /// the output stream where deflated output should be written. + /// + public DeflaterOutputStream(Stream baseOutputStream) + : this(baseOutputStream, new Deflater(), 512) + { + } + + /// + /// Creates a new DeflaterOutputStream with the given Deflater and + /// default buffer size. + /// + /// + /// the output stream where deflated output should be written. + /// + /// + /// the underlying deflater. + /// + public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater) + : this(baseOutputStream, deflater, 512) + { + } + + /// + /// Creates a new DeflaterOutputStream with the given Deflater and + /// buffer size. + /// + /// + /// The output stream where deflated output is written. + /// + /// + /// The underlying deflater to use + /// + /// + /// The buffer size in bytes to use when deflating (minimum value 512) + /// + /// + /// bufsize is less than or equal to zero. + /// + /// + /// baseOutputStream does not support writing + /// + /// + /// deflater instance is null + /// + public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int bufferSize) + { + if ( baseOutputStream == null ) { + throw new ArgumentNullException("baseOutputStream"); + } + + if (baseOutputStream.CanWrite == false) { + throw new ArgumentException("Must support writing", "baseOutputStream"); + } + + if (deflater == null) { + throw new ArgumentNullException("deflater"); + } + + if (bufferSize < 512) { + throw new ArgumentOutOfRangeException("bufferSize"); + } + + baseOutputStream_ = baseOutputStream; + buffer_ = new byte[bufferSize]; + deflater_ = deflater; + } + #endregion + + #region Public API + /// + /// Finishes the stream by calling finish() on the deflater. + /// + /// + /// Not all input is deflated + /// + public virtual void Finish() + { + deflater_.Finish(); + while (!deflater_.IsFinished) { + int len = deflater_.Deflate(buffer_, 0, buffer_.Length); + if (len <= 0) { + break; + } + +#if NETCF_1_0 + if ( keys != null ) { +#else + if (cryptoTransform_ != null) { +#endif + EncryptBlock(buffer_, 0, len); + } + + baseOutputStream_.Write(buffer_, 0, len); + } + + if (!deflater_.IsFinished) { + throw new SharpZipBaseException("Can't deflate all input?"); + } + + baseOutputStream_.Flush(); + +#if NETCF_1_0 + if ( keys != null ) { + keys = null; + } +#else + if (cryptoTransform_ != null) { +#if !NET_1_1 && !NETCF_2_0 + if (cryptoTransform_ is ZipAESTransform) { + AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode(); + } +#endif + cryptoTransform_.Dispose(); + cryptoTransform_ = null; + } +#endif + } + + /// + /// Get/set flag indicating ownership of the underlying stream. + /// When the flag is true will close the underlying stream also. + /// + public bool IsStreamOwner + { + get { return isStreamOwner_; } + set { isStreamOwner_ = value; } + } + + /// + /// Allows client to determine if an entry can be patched after its added + /// + public bool CanPatchEntries { + get { + return baseOutputStream_.CanSeek; + } + } + + #endregion + + #region Encryption + + string password; + +#if NETCF_1_0 + uint[] keys; +#else + ICryptoTransform cryptoTransform_; + + /// + /// Returns the 10 byte AUTH CODE to be appended immediately following the AES data stream. + /// + protected byte[] AESAuthCode; +#endif + + /// + /// Get/set the password used for encryption. + /// + /// When set to null or if the password is empty no encryption is performed + public string Password { + get { + return password; + } + set { + if ( (value != null) && (value.Length == 0) ) { + password = null; + } else { + password = value; + } + } + } + + /// + /// Encrypt a block of data + /// + /// + /// Data to encrypt. NOTE the original contents of the buffer are lost + /// + /// + /// Offset of first byte in buffer to encrypt + /// + /// + /// Number of bytes in buffer to encrypt + /// + protected void EncryptBlock(byte[] buffer, int offset, int length) + { +#if NETCF_1_0 + for (int i = offset; i < offset + length; ++i) { + byte oldbyte = buffer[i]; + buffer[i] ^= EncryptByte(); + UpdateKeys(oldbyte); + } +#else + cryptoTransform_.TransformBlock(buffer, 0, length, buffer, 0); +#endif + } + + /// + /// Initializes encryption keys based on given . + /// + /// The password. + protected void InitializePassword(string password) + { +#if NETCF_1_0 + keys = new uint[] { + 0x12345678, + 0x23456789, + 0x34567890 + }; + + byte[] rawPassword = ZipConstants.ConvertToArray(password); + + for (int i = 0; i < rawPassword.Length; ++i) { + UpdateKeys((byte)rawPassword[i]); + } + +#else + PkzipClassicManaged pkManaged = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password)); + cryptoTransform_ = pkManaged.CreateEncryptor(key, null); +#endif + } + +#if !NET_1_1 && !NETCF_2_0 + /// + /// Initializes encryption keys based on given password. + /// + protected void InitializeAESPassword(ZipEntry entry, string rawPassword, + out byte[] salt, out byte[] pwdVerifier) { + salt = new byte[entry.AESSaltLen]; + // Salt needs to be cryptographically random, and unique per file + if (_aesRnd == null) + _aesRnd = new RNGCryptoServiceProvider(); + _aesRnd.GetBytes(salt); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + cryptoTransform_ = new ZipAESTransform(rawPassword, salt, blockSize, true); + pwdVerifier = ((ZipAESTransform)cryptoTransform_).PwdVerifier; + } +#endif + +#if NETCF_1_0 + + /// + /// Encrypt a single byte + /// + /// + /// The encrypted value + /// + protected byte EncryptByte() + { + uint temp = ((keys[2] & 0xFFFF) | 2); + return (byte)((temp * (temp ^ 1)) >> 8); + } + + /// + /// Update encryption keys + /// + protected void UpdateKeys(byte ch) + { + keys[0] = Crc32.ComputeCrc32(keys[0], ch); + keys[1] = keys[1] + (byte)keys[0]; + keys[1] = keys[1] * 134775813 + 1; + keys[2] = Crc32.ComputeCrc32(keys[2], (byte)(keys[1] >> 24)); + } +#endif + + #endregion + + #region Deflation Support + /// + /// Deflates everything in the input buffers. This will call + /// def.deflate() until all bytes from the input buffers + /// are processed. + /// + protected void Deflate() + { + while (!deflater_.IsNeedingInput) + { + int deflateCount = deflater_.Deflate(buffer_, 0, buffer_.Length); + + if (deflateCount <= 0) { + break; + } +#if NETCF_1_0 + if (keys != null) +#else + if (cryptoTransform_ != null) +#endif + { + EncryptBlock(buffer_, 0, deflateCount); + } + + baseOutputStream_.Write(buffer_, 0, deflateCount); + } + + if (!deflater_.IsNeedingInput) { + throw new SharpZipBaseException("DeflaterOutputStream can't deflate all input?"); + } + } + #endregion + + #region Stream Overrides + /// + /// Gets value indicating stream can be read from + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Gets a value indicating if seeking is supported for this stream + /// This property always returns false + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Get value indicating if this stream supports writing + /// + public override bool CanWrite { + get { + return baseOutputStream_.CanWrite; + } + } + + /// + /// Get current length of stream + /// + public override long Length { + get { + return baseOutputStream_.Length; + } + } + + /// + /// Gets the current position within the stream. + /// + /// Any attempt to set position + public override long Position { + get { + return baseOutputStream_.Position; + } + set { + throw new NotSupportedException("Position property not supported"); + } + } + + /// + /// Sets the current position of this stream to the given value. Not supported by this class! + /// + /// The offset relative to the to seek. + /// The to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("DeflaterOutputStream Seek not supported"); + } + + /// + /// Sets the length of this stream to the given value. Not supported by this class! + /// + /// The new stream length. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("DeflaterOutputStream SetLength not supported"); + } + + /// + /// Read a byte from stream advancing position by one + /// + /// The byte read cast to an int. THe value is -1 if at the end of the stream. + /// Any access + public override int ReadByte() + { + throw new NotSupportedException("DeflaterOutputStream ReadByte not supported"); + } + + /// + /// Read a block of bytes from stream + /// + /// The buffer to store read data in. + /// The offset to start storing at. + /// The maximum number of bytes to read. + /// The actual number of bytes read. Zero if end of stream is detected. + /// Any access + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("DeflaterOutputStream Read not supported"); + } + + /// + /// Asynchronous reads are not supported a NotSupportedException is always thrown + /// + /// The buffer to read into. + /// The offset to start storing data at. + /// The number of bytes to read + /// The async callback to use. + /// The state to use. + /// Returns an + /// Any access + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("DeflaterOutputStream BeginRead not currently supported"); + } + + /// + /// Asynchronous writes arent supported, a NotSupportedException is always thrown + /// + /// The buffer to write. + /// The offset to begin writing at. + /// The number of bytes to write. + /// The to use. + /// The state object. + /// Returns an IAsyncResult. + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("BeginWrite is not supported"); + } + + /// + /// Flushes the stream by calling Flush on the deflater and then + /// on the underlying stream. This ensures that all bytes are flushed. + /// + public override void Flush() + { + deflater_.Flush(); + Deflate(); + baseOutputStream_.Flush(); + } + + /// + /// Calls and closes the underlying + /// stream when is true. + /// + public override void Close() + { + if ( !isClosed_ ) { + isClosed_ = true; + + try { + Finish(); +#if NETCF_1_0 + keys=null; +#else + if ( cryptoTransform_ != null ) { + GetAuthCodeIfAES(); + cryptoTransform_.Dispose(); + cryptoTransform_ = null; + } +#endif + } + finally { + if( isStreamOwner_ ) { + baseOutputStream_.Close(); + } + } + } + } + + private void GetAuthCodeIfAES() { +#if !NET_1_1 && !NETCF_2_0 + if (cryptoTransform_ is ZipAESTransform) { + AESAuthCode = ((ZipAESTransform)cryptoTransform_).GetAuthCode(); + } +#endif + } + + /// + /// Writes a single byte to the compressed output stream. + /// + /// + /// The byte value. + /// + public override void WriteByte(byte value) + { + byte[] b = new byte[1]; + b[0] = value; + Write(b, 0, 1); + } + + /// + /// Writes bytes from an array to the compressed stream. + /// + /// + /// The byte array + /// + /// + /// The offset into the byte array where to start. + /// + /// + /// The number of bytes to write. + /// + public override void Write(byte[] buffer, int offset, int count) + { + deflater_.SetInput(buffer, offset, count); + Deflate(); + } + #endregion + + #region Instance Fields + /// + /// This buffer is used temporarily to retrieve the bytes from the + /// deflater and write them to the underlying output stream. + /// + byte[] buffer_; + + /// + /// The deflater which is used to deflate the stream. + /// + protected Deflater deflater_; + + /// + /// Base stream the deflater depends on. + /// + protected Stream baseOutputStream_; + + bool isClosed_; + + bool isStreamOwner_ = true; + #endregion + + #region Static Fields + +#if !NET_1_1 && !NETCF_2_0 + // Static to help ensure that multiple files within a zip will get different random salt + private static RNGCryptoServiceProvider _aesRnd; +#endif + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/Streams/InflaterInputStream.cs b/类库/VersionUpdate/ZIP/Zip/Compression/Streams/InflaterInputStream.cs new file mode 100644 index 0000000..6699444 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/Streams/InflaterInputStream.cs @@ -0,0 +1,732 @@ +// InflaterInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 11-08-2009 GeoffHart T9121 Added Multi-member gzip support + +using System; +using System.IO; + +#if !NETCF_1_0 +using System.Security.Cryptography; +#endif + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// An input buffer customised for use by + /// + /// + /// The buffer supports decryption of incoming data. + /// + public class InflaterInputBuffer + { + #region Constructors + /// + /// Initialise a new instance of with a default buffer size + /// + /// The stream to buffer. + public InflaterInputBuffer(Stream stream) : this(stream , 4096) + { + } + + /// + /// Initialise a new instance of + /// + /// The stream to buffer. + /// The size to use for the buffer + /// A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB. + public InflaterInputBuffer(Stream stream, int bufferSize) + { + inputStream = stream; + if ( bufferSize < 1024 ) { + bufferSize = 1024; + } + rawData = new byte[bufferSize]; + clearText = rawData; + } + #endregion + + /// + /// Get the length of bytes bytes in the + /// + public int RawLength + { + get { + return rawLength; + } + } + + /// + /// Get the contents of the raw data buffer. + /// + /// This may contain encrypted data. + public byte[] RawData + { + get { + return rawData; + } + } + + /// + /// Get the number of useable bytes in + /// + public int ClearTextLength + { + get { + return clearTextLength; + } + } + + /// + /// Get the contents of the clear text buffer. + /// + public byte[] ClearText + { + get { + return clearText; + } + } + + /// + /// Get/set the number of bytes available + /// + public int Available + { + get { return available; } + set { available = value; } + } + + /// + /// Call passing the current clear text buffer contents. + /// + /// The inflater to set input for. + public void SetInflaterInput(Inflater inflater) + { + if ( available > 0 ) { + inflater.SetInput(clearText, clearTextLength - available, available); + available = 0; + } + } + + /// + /// Fill the buffer from the underlying input stream. + /// + public void Fill() + { + rawLength = 0; + int toRead = rawData.Length; + + while (toRead > 0) { + int count = inputStream.Read(rawData, rawLength, toRead); + if ( count <= 0 ) { + break; + } + rawLength += count; + toRead -= count; + } + +#if !NETCF_1_0 + if ( cryptoTransform != null ) { + clearTextLength = cryptoTransform.TransformBlock(rawData, 0, rawLength, clearText, 0); + } + else +#endif + { + clearTextLength = rawLength; + } + + available = clearTextLength; + } + + /// + /// Read a buffer directly from the input stream + /// + /// The buffer to fill + /// Returns the number of bytes read. + public int ReadRawBuffer(byte[] buffer) + { + return ReadRawBuffer(buffer, 0, buffer.Length); + } + + /// + /// Read a buffer directly from the input stream + /// + /// The buffer to read into + /// The offset to start reading data into. + /// The number of bytes to read. + /// Returns the number of bytes read. + public int ReadRawBuffer(byte[] outBuffer, int offset, int length) + { + if ( length < 0 ) { + throw new ArgumentOutOfRangeException("length"); + } + + int currentOffset = offset; + int currentLength = length; + + while ( currentLength > 0 ) { + if ( available <= 0 ) { + Fill(); + if (available <= 0) { + return 0; + } + } + int toCopy = Math.Min(currentLength, available); + System.Array.Copy(rawData, rawLength - (int)available, outBuffer, currentOffset, toCopy); + currentOffset += toCopy; + currentLength -= toCopy; + available -= toCopy; + } + return length; + } + + /// + /// Read clear text data from the input stream. + /// + /// The buffer to add data to. + /// The offset to start adding data at. + /// The number of bytes to read. + /// Returns the number of bytes actually read. + public int ReadClearTextBuffer(byte[] outBuffer, int offset, int length) + { + if ( length < 0 ) { + throw new ArgumentOutOfRangeException("length"); + } + + int currentOffset = offset; + int currentLength = length; + + while ( currentLength > 0 ) { + if ( available <= 0 ) { + Fill(); + if (available <= 0) { + return 0; + } + } + + int toCopy = Math.Min(currentLength, available); + Array.Copy(clearText, clearTextLength - (int)available, outBuffer, currentOffset, toCopy); + currentOffset += toCopy; + currentLength -= toCopy; + available -= toCopy; + } + return length; + } + + /// + /// Read a from the input stream. + /// + /// Returns the byte read. + public int ReadLeByte() + { + if (available <= 0) { + Fill(); + if (available <= 0) { + throw new ZipException("EOF in header"); + } + } + byte result = rawData[rawLength - available]; + available -= 1; + return result; + } + + /// + /// Read an in little endian byte order. + /// + /// The short value read case to an int. + public int ReadLeShort() + { + return ReadLeByte() | (ReadLeByte() << 8); + } + + /// + /// Read an in little endian byte order. + /// + /// The int value read. + public int ReadLeInt() + { + return ReadLeShort() | (ReadLeShort() << 16); + } + + /// + /// Read a in little endian byte order. + /// + /// The long value read. + public long ReadLeLong() + { + return (uint)ReadLeInt() | ((long)ReadLeInt() << 32); + } + +#if !NETCF_1_0 + /// + /// Get/set the to apply to any data. + /// + /// Set this value to null to have no transform applied. + public ICryptoTransform CryptoTransform + { + set { + cryptoTransform = value; + if ( cryptoTransform != null ) { + if ( rawData == clearText ) { + if ( internalClearText == null ) { + internalClearText = new byte[rawData.Length]; + } + clearText = internalClearText; + } + clearTextLength = rawLength; + if ( available > 0 ) { + cryptoTransform.TransformBlock(rawData, rawLength - available, available, clearText, rawLength - available); + } + } else { + clearText = rawData; + clearTextLength = rawLength; + } + } + } +#endif + + #region Instance Fields + int rawLength; + byte[] rawData; + + int clearTextLength; + byte[] clearText; +#if !NETCF_1_0 + byte[] internalClearText; +#endif + + int available; + +#if !NETCF_1_0 + ICryptoTransform cryptoTransform; +#endif + Stream inputStream; + #endregion + } + + /// + /// This filter stream is used to decompress data compressed using the "deflate" + /// format. The "deflate" format is described in RFC 1951. + /// + /// This stream may form the basis for other decompression filters, such + /// as the GZipInputStream. + /// + /// Author of the original java version : John Leuner. + /// + public class InflaterInputStream : Stream + { + #region Constructors + /// + /// Create an InflaterInputStream with the default decompressor + /// and a default buffer size of 4KB. + /// + /// + /// The InputStream to read bytes from + /// + public InflaterInputStream(Stream baseInputStream) + : this(baseInputStream, new Inflater(), 4096) + { + } + + /// + /// Create an InflaterInputStream with the specified decompressor + /// and a default buffer size of 4KB. + /// + /// + /// The source of input data + /// + /// + /// The decompressor used to decompress data read from baseInputStream + /// + public InflaterInputStream(Stream baseInputStream, Inflater inf) + : this(baseInputStream, inf, 4096) + { + } + + /// + /// Create an InflaterInputStream with the specified decompressor + /// and the specified buffer size. + /// + /// + /// The InputStream to read bytes from + /// + /// + /// The decompressor to use + /// + /// + /// Size of the buffer to use + /// + public InflaterInputStream(Stream baseInputStream, Inflater inflater, int bufferSize) + { + if (baseInputStream == null) { + throw new ArgumentNullException("baseInputStream"); + } + + if (inflater == null) { + throw new ArgumentNullException("inflater"); + } + + if (bufferSize <= 0) { + throw new ArgumentOutOfRangeException("bufferSize"); + } + + this.baseInputStream = baseInputStream; + this.inf = inflater; + + inputBuffer = new InflaterInputBuffer(baseInputStream, bufferSize); + } + + #endregion + + /// + /// Get/set flag indicating ownership of underlying stream. + /// When the flag is true will close the underlying stream also. + /// + /// + /// The default value is true. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Skip specified number of bytes of uncompressed data + /// + /// + /// Number of bytes to skip + /// + /// + /// The number of bytes skipped, zero if the end of + /// stream has been reached + /// + /// + /// The number of bytes to skip is less than or equal to zero. + /// + public long Skip(long count) + { + if (count <= 0) { + throw new ArgumentOutOfRangeException("count"); + } + + // v0.80 Skip by seeking if underlying stream supports it... + if (baseInputStream.CanSeek) { + baseInputStream.Seek(count, SeekOrigin.Current); + return count; + } + else { + int length = 2048; + if (count < length) { + length = (int) count; + } + + byte[] tmp = new byte[length]; + int readCount = 1; + long toSkip = count; + + while ((toSkip > 0) && (readCount > 0) ) { + if (toSkip < length) { + length = (int)toSkip; + } + + readCount = baseInputStream.Read(tmp, 0, length); + toSkip -= readCount; + } + + return count - toSkip; + } + } + + /// + /// Clear any cryptographic state. + /// + protected void StopDecrypting() + { +#if !NETCF_1_0 + inputBuffer.CryptoTransform = null; +#endif + } + + /// + /// Returns 0 once the end of the stream (EOF) has been reached. + /// Otherwise returns 1. + /// + public virtual int Available + { + get { + return inf.IsFinished ? 0 : 1; + } + } + + /// + /// Fills the buffer with more data to decompress. + /// + /// + /// Stream ends early + /// + protected void Fill() + { + // Protect against redundant calls + if (inputBuffer.Available <= 0) { + inputBuffer.Fill(); + if (inputBuffer.Available <= 0) { + throw new SharpZipBaseException("Unexpected EOF"); + } + } + inputBuffer.SetInflaterInput(inf); + } + + #region Stream Overrides + /// + /// Gets a value indicating whether the current stream supports reading + /// + public override bool CanRead + { + get { + return baseInputStream.CanRead; + } + } + + /// + /// Gets a value of false indicating seeking is not supported for this stream. + /// + public override bool CanSeek { + get { + return false; + } + } + + /// + /// Gets a value of false indicating that this stream is not writeable. + /// + public override bool CanWrite { + get { + return false; + } + } + + /// + /// A value representing the length of the stream in bytes. + /// + public override long Length { + get { + return inputBuffer.RawLength; + } + } + + /// + /// The current position within the stream. + /// Throws a NotSupportedException when attempting to set the position + /// + /// Attempting to set the position + public override long Position { + get { + return baseInputStream.Position; + } + set { + throw new NotSupportedException("InflaterInputStream Position not supported"); + } + } + + /// + /// Flushes the baseInputStream + /// + public override void Flush() + { + baseInputStream.Flush(); + } + + /// + /// Sets the position within the current stream + /// Always throws a NotSupportedException + /// + /// The relative offset to seek to. + /// The defining where to seek from. + /// The new position in the stream. + /// Any access + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("Seek not supported"); + } + + /// + /// Set the length of the current stream + /// Always throws a NotSupportedException + /// + /// The new length value for the stream. + /// Any access + public override void SetLength(long value) + { + throw new NotSupportedException("InflaterInputStream SetLength not supported"); + } + + /// + /// Writes a sequence of bytes to stream and advances the current position + /// This method always throws a NotSupportedException + /// + /// Thew buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Any access + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException("InflaterInputStream Write not supported"); + } + + /// + /// Writes one byte to the current stream and advances the current position + /// Always throws a NotSupportedException + /// + /// The byte to write. + /// Any access + public override void WriteByte(byte value) + { + throw new NotSupportedException("InflaterInputStream WriteByte not supported"); + } + + /// + /// Entry point to begin an asynchronous write. Always throws a NotSupportedException. + /// + /// The buffer to write data from + /// Offset of first byte to write + /// The maximum number of bytes to write + /// The method to be called when the asynchronous write operation is completed + /// A user-provided object that distinguishes this particular asynchronous write request from other requests + /// An IAsyncResult that references the asynchronous write + /// Any access + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); + } + + /// + /// Closes the input stream. When + /// is true the underlying stream is also closed. + /// + public override void Close() + { + if ( !isClosed ) { + isClosed = true; + if ( isStreamOwner ) { + baseInputStream.Close(); + } + } + } + + /// + /// Reads decompressed data into the provided buffer byte array + /// + /// + /// The array to read and decompress data into + /// + /// + /// The offset indicating where the data should be placed + /// + /// + /// The number of bytes to decompress + /// + /// The number of bytes read. Zero signals the end of stream + /// + /// Inflater needs a dictionary + /// + public override int Read(byte[] buffer, int offset, int count) + { + if (inf.IsNeedingDictionary) + { + throw new SharpZipBaseException("Need a dictionary"); + } + + int remainingBytes = count; + while (true) { + int bytesRead = inf.Inflate(buffer, offset, remainingBytes); + offset += bytesRead; + remainingBytes -= bytesRead; + + if (remainingBytes == 0 || inf.IsFinished) { + break; + } + + if ( inf.IsNeedingInput ) { + Fill(); + } + else if ( bytesRead == 0 ) { + throw new ZipException("Dont know what to do"); + } + } + return count - remainingBytes; + } + #endregion + + #region Instance Fields + /// + /// Decompressor for this stream + /// + protected Inflater inf; + + /// + /// Input buffer for this stream. + /// + protected InflaterInputBuffer inputBuffer; + + /// + /// Base stream the inflater reads from. + /// + private Stream baseInputStream; + + /// + /// The compressed size + /// + protected long csize; + + /// + /// Flag indicating wether this instance has been closed or not. + /// + bool isClosed; + + /// + /// Flag indicating wether this instance is designated the stream owner. + /// When closing if this flag is true the underlying stream is closed. + /// + bool isStreamOwner = true; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/Streams/OutputWindow.cs b/类库/VersionUpdate/ZIP/Zip/Compression/Streams/OutputWindow.cs new file mode 100644 index 0000000..be828e2 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/Streams/OutputWindow.cs @@ -0,0 +1,235 @@ +// OutputWindow.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// Contains the output from the Inflation process. + /// We need to have a window so that we can refer backwards into the output stream + /// to repeat stuff.
+ /// Author of the original java version : John Leuner + ///
+ public class OutputWindow + { + #region Constants + const int WindowSize = 1 << 15; + const int WindowMask = WindowSize - 1; + #endregion + + #region Instance Fields + byte[] window = new byte[WindowSize]; //The window is 2^15 bytes + int windowEnd; + int windowFilled; + #endregion + + /// + /// Write a byte to this output window + /// + /// value to write + /// + /// if window is full + /// + public void Write(int value) + { + if (windowFilled++ == WindowSize) { + throw new InvalidOperationException("Window full"); + } + window[windowEnd++] = (byte) value; + windowEnd &= WindowMask; + } + + + private void SlowRepeat(int repStart, int length, int distance) + { + while (length-- > 0) { + window[windowEnd++] = window[repStart++]; + windowEnd &= WindowMask; + repStart &= WindowMask; + } + } + + /// + /// Append a byte pattern already in the window itself + /// + /// length of pattern to copy + /// distance from end of window pattern occurs + /// + /// If the repeated data overflows the window + /// + public void Repeat(int length, int distance) + { + if ((windowFilled += length) > WindowSize) { + throw new InvalidOperationException("Window full"); + } + + int repStart = (windowEnd - distance) & WindowMask; + int border = WindowSize - length; + if ( (repStart <= border) && (windowEnd < border) ) { + if (length <= distance) { + System.Array.Copy(window, repStart, window, windowEnd, length); + windowEnd += length; + } else { + // We have to copy manually, since the repeat pattern overlaps. + while (length-- > 0) { + window[windowEnd++] = window[repStart++]; + } + } + } else { + SlowRepeat(repStart, length, distance); + } + } + + /// + /// Copy from input manipulator to internal window + /// + /// source of data + /// length of data to copy + /// the number of bytes copied + public int CopyStored(StreamManipulator input, int length) + { + length = Math.Min(Math.Min(length, WindowSize - windowFilled), input.AvailableBytes); + int copied; + + int tailLen = WindowSize - windowEnd; + if (length > tailLen) { + copied = input.CopyBytes(window, windowEnd, tailLen); + if (copied == tailLen) { + copied += input.CopyBytes(window, 0, length - tailLen); + } + } else { + copied = input.CopyBytes(window, windowEnd, length); + } + + windowEnd = (windowEnd + copied) & WindowMask; + windowFilled += copied; + return copied; + } + + /// + /// Copy dictionary to window + /// + /// source dictionary + /// offset of start in source dictionary + /// length of dictionary + /// + /// If window isnt empty + /// + public void CopyDict(byte[] dictionary, int offset, int length) + { + if ( dictionary == null ) { + throw new ArgumentNullException("dictionary"); + } + + if (windowFilled > 0) { + throw new InvalidOperationException(); + } + + if (length > WindowSize) { + offset += length - WindowSize; + length = WindowSize; + } + System.Array.Copy(dictionary, offset, window, 0, length); + windowEnd = length & WindowMask; + } + + /// + /// Get remaining unfilled space in window + /// + /// Number of bytes left in window + public int GetFreeSpace() + { + return WindowSize - windowFilled; + } + + /// + /// Get bytes available for output in window + /// + /// Number of bytes filled + public int GetAvailable() + { + return windowFilled; + } + + /// + /// Copy contents of window to output + /// + /// buffer to copy to + /// offset to start at + /// number of bytes to count + /// The number of bytes copied + /// + /// If a window underflow occurs + /// + public int CopyOutput(byte[] output, int offset, int len) + { + int copyEnd = windowEnd; + if (len > windowFilled) { + len = windowFilled; + } else { + copyEnd = (windowEnd - windowFilled + len) & WindowMask; + } + + int copied = len; + int tailLen = len - copyEnd; + + if (tailLen > 0) { + System.Array.Copy(window, WindowSize - tailLen, output, offset, tailLen); + offset += tailLen; + len = copyEnd; + } + System.Array.Copy(window, copyEnd - len, output, offset, len); + windowFilled -= copied; + if (windowFilled < 0) { + throw new InvalidOperationException(); + } + return copied; + } + + /// + /// Reset by clearing window so GetAvailable returns 0 + /// + public void Reset() + { + windowFilled = windowEnd = 0; + } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/Compression/Streams/StreamManipulator.cs b/类库/VersionUpdate/ZIP/Zip/Compression/Streams/StreamManipulator.cs new file mode 100644 index 0000000..ac57e1e --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/Compression/Streams/StreamManipulator.cs @@ -0,0 +1,297 @@ +// StreamManipulator.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams +{ + + /// + /// This class allows us to retrieve a specified number of bits from + /// the input buffer, as well as copy big byte blocks. + /// + /// It uses an int buffer to store up to 31 bits for direct + /// manipulation. This guarantees that we can get at least 16 bits, + /// but we only need at most 15, so this is all safe. + /// + /// There are some optimizations in this class, for example, you must + /// never peek more than 8 bits more than needed, and you must first + /// peek bits before you may drop them. This is not a general purpose + /// class but optimized for the behaviour of the Inflater. + /// + /// authors of the original java version : John Leuner, Jochen Hoenicke + /// + public class StreamManipulator + { + #region Constructors + /// + /// Constructs a default StreamManipulator with all buffers empty + /// + public StreamManipulator() + { + } + #endregion + + /// + /// Get the next sequence of bits but don't increase input pointer. bitCount must be + /// less or equal 16 and if this call succeeds, you must drop + /// at least n - 8 bits in the next call. + /// + /// The number of bits to peek. + /// + /// the value of the bits, or -1 if not enough bits available. */ + /// + public int PeekBits(int bitCount) + { + if (bitsInBuffer_ < bitCount) { + if (windowStart_ == windowEnd_) { + return -1; // ok + } + buffer_ |= (uint)((window_[windowStart_++] & 0xff | + (window_[windowStart_++] & 0xff) << 8) << bitsInBuffer_); + bitsInBuffer_ += 16; + } + return (int)(buffer_ & ((1 << bitCount) - 1)); + } + + /// + /// Drops the next n bits from the input. You should have called PeekBits + /// with a bigger or equal n before, to make sure that enough bits are in + /// the bit buffer. + /// + /// The number of bits to drop. + public void DropBits(int bitCount) + { + buffer_ >>= bitCount; + bitsInBuffer_ -= bitCount; + } + + /// + /// Gets the next n bits and increases input pointer. This is equivalent + /// to followed by , except for correct error handling. + /// + /// The number of bits to retrieve. + /// + /// the value of the bits, or -1 if not enough bits available. + /// + public int GetBits(int bitCount) + { + int bits = PeekBits(bitCount); + if (bits >= 0) { + DropBits(bitCount); + } + return bits; + } + + /// + /// Gets the number of bits available in the bit buffer. This must be + /// only called when a previous PeekBits() returned -1. + /// + /// + /// the number of bits available. + /// + public int AvailableBits { + get { + return bitsInBuffer_; + } + } + + /// + /// Gets the number of bytes available. + /// + /// + /// The number of bytes available. + /// + public int AvailableBytes { + get { + return windowEnd_ - windowStart_ + (bitsInBuffer_ >> 3); + } + } + + /// + /// Skips to the next byte boundary. + /// + public void SkipToByteBoundary() + { + buffer_ >>= (bitsInBuffer_ & 7); + bitsInBuffer_ &= ~7; + } + + /// + /// Returns true when SetInput can be called + /// + public bool IsNeedingInput { + get { + return windowStart_ == windowEnd_; + } + } + + /// + /// Copies bytes from input buffer to output buffer starting + /// at output[offset]. You have to make sure, that the buffer is + /// byte aligned. If not enough bytes are available, copies fewer + /// bytes. + /// + /// + /// The buffer to copy bytes to. + /// + /// + /// The offset in the buffer at which copying starts + /// + /// + /// The length to copy, 0 is allowed. + /// + /// + /// The number of bytes copied, 0 if no bytes were available. + /// + /// + /// Length is less than zero + /// + /// + /// Bit buffer isnt byte aligned + /// + public int CopyBytes(byte[] output, int offset, int length) + { + if (length < 0) { + throw new ArgumentOutOfRangeException("length"); + } + + if ((bitsInBuffer_ & 7) != 0) { + // bits_in_buffer may only be 0 or a multiple of 8 + throw new InvalidOperationException("Bit buffer is not byte aligned!"); + } + + int count = 0; + while ((bitsInBuffer_ > 0) && (length > 0)) { + output[offset++] = (byte) buffer_; + buffer_ >>= 8; + bitsInBuffer_ -= 8; + length--; + count++; + } + + if (length == 0) { + return count; + } + + int avail = windowEnd_ - windowStart_; + if (length > avail) { + length = avail; + } + System.Array.Copy(window_, windowStart_, output, offset, length); + windowStart_ += length; + + if (((windowStart_ - windowEnd_) & 1) != 0) { + // We always want an even number of bytes in input, see peekBits + buffer_ = (uint)(window_[windowStart_++] & 0xff); + bitsInBuffer_ = 8; + } + return count + length; + } + + /// + /// Resets state and empties internal buffers + /// + public void Reset() + { + buffer_ = 0; + windowStart_ = windowEnd_ = bitsInBuffer_ = 0; + } + + /// + /// Add more input for consumption. + /// Only call when IsNeedingInput returns true + /// + /// data to be input + /// offset of first byte of input + /// number of bytes of input to add. + public void SetInput(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if (windowStart_ < windowEnd_) { + throw new InvalidOperationException("Old input was not completely processed"); + } + + int end = offset + count; + + // We want to throw an ArrayIndexOutOfBoundsException early. + // Note the check also handles integer wrap around. + if ((offset > end) || (end > buffer.Length) ) { + throw new ArgumentOutOfRangeException("count"); + } + + if ((count & 1) != 0) { + // We always want an even number of bytes in input, see PeekBits + buffer_ |= (uint)((buffer[offset++] & 0xff) << bitsInBuffer_); + bitsInBuffer_ += 8; + } + + window_ = buffer; + windowStart_ = offset; + windowEnd_ = end; + } + + #region Instance Fields + private byte[] window_; + private int windowStart_; + private int windowEnd_; + + private uint buffer_; + private int bitsInBuffer_; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/FastZip.cs b/类库/VersionUpdate/ZIP/Zip/FastZip.cs new file mode 100644 index 0000000..70be02b --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/FastZip.cs @@ -0,0 +1,730 @@ +// FastZip.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// FastZipEvents supports all events applicable to FastZip operations. + /// + public class FastZipEvents + { + /// + /// Delegate to invoke when processing directories. + /// + public ProcessDirectoryHandler ProcessDirectory; + + /// + /// Delegate to invoke when processing files. + /// + public ProcessFileHandler ProcessFile; + + /// + /// Delegate to invoke during processing of files. + /// + public ProgressHandler Progress; + + /// + /// Delegate to invoke when processing for a file has been completed. + /// + public CompletedFileHandler CompletedFile; + + /// + /// Delegate to invoke when processing directory failures. + /// + public DirectoryFailureHandler DirectoryFailure; + + /// + /// Delegate to invoke when processing file failures. + /// + public FileFailureHandler FileFailure; + + /// + /// Raise the directory failure event. + /// + /// The directory causing the failure. + /// The exception for this event. + /// A boolean indicating if execution should continue or not. + public bool OnDirectoryFailure(string directory, Exception e) + { + bool result = false; + DirectoryFailureHandler handler = DirectoryFailure; + + if ( handler != null ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the file failure handler delegate. + /// + /// The file causing the failure. + /// The exception for this failure. + /// A boolean indicating if execution should continue or not. + public bool OnFileFailure(string file, Exception e) + { + FileFailureHandler handler = FileFailure; + bool result = (handler != null); + + if ( result ) { + ScanFailureEventArgs args = new ScanFailureEventArgs(file, e); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the ProcessFile delegate. + /// + /// The file being processed. + /// A boolean indicating if execution should continue or not. + public bool OnProcessFile(string file) + { + bool result = true; + ProcessFileHandler handler = ProcessFile; + + if ( handler != null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the delegate + /// + /// The file whose processing has been completed. + /// A boolean indicating if execution should continue or not. + public bool OnCompletedFile(string file) + { + bool result = true; + CompletedFileHandler handler = CompletedFile; + if ( handler != null ) { + ScanEventArgs args = new ScanEventArgs(file); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// Fires the process directory delegate. + /// + /// The directory being processed. + /// Flag indicating if the directory has matching files as determined by the current filter. + /// A of true if the operation should continue; false otherwise. + public bool OnProcessDirectory(string directory, bool hasMatchingFiles) + { + bool result = true; + ProcessDirectoryHandler handler = ProcessDirectory; + if ( handler != null ) { + DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles); + handler(this, args); + result = args.ContinueRunning; + } + return result; + } + + /// + /// The minimum timespan between events. + /// + /// The minimum period of time between events. + /// + /// The default interval is three seconds. + public TimeSpan ProgressInterval + { + get { return progressInterval_; } + set { progressInterval_ = value; } + } + + #region Instance Fields + TimeSpan progressInterval_ = TimeSpan.FromSeconds(3); + #endregion + } + + /// + /// FastZip provides facilities for creating and extracting zip files. + /// + public class FastZip + { + #region Enumerations + /// + /// Defines the desired handling when overwriting files during extraction. + /// + public enum Overwrite + { + /// + /// Prompt the user to confirm overwriting + /// + Prompt, + /// + /// Never overwrite files. + /// + Never, + /// + /// Always overwrite files. + /// + Always + } + #endregion + + #region Constructors + /// + /// Initialise a default instance of . + /// + public FastZip() + { + } + + /// + /// Initialise a new instance of + /// + /// The events to use during operations. + public FastZip(FastZipEvents events) + { + events_ = events; + } + #endregion + + #region Properties + /// + /// Get/set a value indicating wether empty directories should be created. + /// + public bool CreateEmptyDirectories + { + get { return createEmptyDirectories_; } + set { createEmptyDirectories_ = value; } + } + +#if !NETCF_1_0 + /// + /// Get / set the password value. + /// + public string Password + { + get { return password_; } + set { password_ = value; } + } +#endif + + /// + /// Get or set the active when creating Zip files. + /// + /// + public INameTransform NameTransform + { + get { return entryFactory_.NameTransform; } + set { + entryFactory_.NameTransform = value; + } + } + + /// + /// Get or set the active when creating Zip files. + /// + public IEntryFactory EntryFactory + { + get { return entryFactory_; } + set { + if ( value == null ) { + entryFactory_ = new ZipEntryFactory(); + } + else { + entryFactory_ = value; + } + } + } + + /// + /// Gets or sets the setting for Zip64 handling when writing. + /// + /// + /// The default value is dynamic which is not backwards compatible with old + /// programs and can cause problems with XP's built in compression which cant + /// read Zip64 archives. However it does avoid the situation were a large file + /// is added and cannot be completed correctly. + /// NOTE: Setting the size for entries before they are added is the best solution! + /// By default the EntryFactory used by FastZip will set fhe file size. + /// + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + /// + /// Get/set a value indicating wether file dates and times should + /// be restored when extracting files from an archive. + /// + /// The default value is false. + public bool RestoreDateTimeOnExtract + { + get { + return restoreDateTimeOnExtract_; + } + set { + restoreDateTimeOnExtract_ = value; + } + } + + /// + /// Get/set a value indicating wether file attributes should + /// be restored during extract operations + /// + public bool RestoreAttributesOnExtract + { + get { return restoreAttributesOnExtract_; } + set { restoreAttributesOnExtract_ = value; } + } + #endregion + + #region Delegates + /// + /// Delegate called when confirming overwriting of files. + /// + public delegate bool ConfirmOverwriteDelegate(string fileName); + #endregion + + #region CreateZip + /// + /// Create a zip file. + /// + /// The name of the zip file to create. + /// The directory to source files from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + /// The directory filter to apply. + public void CreateZip(string zipFileName, string sourceDirectory, + bool recurse, string fileFilter, string directoryFilter) + { + CreateZip(File.Create(zipFileName), sourceDirectory, recurse, fileFilter, directoryFilter); + } + + /// + /// Create a zip file/archive. + /// + /// The name of the zip file to create. + /// The directory to obtain files and directories from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + public void CreateZip(string zipFileName, string sourceDirectory, bool recurse, string fileFilter) + { + CreateZip(File.Create(zipFileName), sourceDirectory, recurse, fileFilter, null); + } + + /// + /// Create a zip archive sending output to the passed. + /// + /// The stream to write archive data to. + /// The directory to source files from. + /// True to recurse directories, false for no recursion. + /// The file filter to apply. + /// The directory filter to apply. + /// The is closed after creation. + public void CreateZip(Stream outputStream, string sourceDirectory, bool recurse, string fileFilter, string directoryFilter) + { + NameTransform = new ZipNameTransform(sourceDirectory); + sourceDirectory_ = sourceDirectory; + + using ( outputStream_ = new ZipOutputStream(outputStream) ) { + +#if !NETCF_1_0 + if ( password_ != null ) { + outputStream_.Password = password_; + } +#endif + + outputStream_.UseZip64 = UseZip64; + FileSystemScanner scanner = new FileSystemScanner(fileFilter, directoryFilter); + scanner.ProcessFile += new ProcessFileHandler(ProcessFile); + if ( this.CreateEmptyDirectories ) { + scanner.ProcessDirectory += new ProcessDirectoryHandler(ProcessDirectory); + } + + if (events_ != null) { + if ( events_.FileFailure != null ) { + scanner.FileFailure += events_.FileFailure; + } + + if ( events_.DirectoryFailure != null ) { + scanner.DirectoryFailure += events_.DirectoryFailure; + } + } + + scanner.Scan(sourceDirectory, recurse); + } + } + + #endregion + + #region ExtractZip + /// + /// Extract the contents of a zip file. + /// + /// The zip file to extract from. + /// The directory to save extracted information in. + /// A filter to apply to files. + public void ExtractZip(string zipFileName, string targetDirectory, string fileFilter) + { + ExtractZip(zipFileName, targetDirectory, Overwrite.Always, null, fileFilter, null, restoreDateTimeOnExtract_); + } + + /// + /// Extract the contents of a zip file. + /// + /// The zip file to extract from. + /// The directory to save extracted information in. + /// The style of overwriting to apply. + /// A delegate to invoke when confirming overwriting. + /// A filter to apply to files. + /// A filter to apply to directories. + /// Flag indicating whether to restore the date and time for extracted files. + public void ExtractZip(string zipFileName, string targetDirectory, + Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate, + string fileFilter, string directoryFilter, bool restoreDateTime) + { + Stream inputStream = File.Open(zipFileName, FileMode.Open, FileAccess.Read, FileShare.Read); + ExtractZip(inputStream, targetDirectory, overwrite, confirmDelegate, fileFilter, directoryFilter, restoreDateTime, true); + } + + /// + /// Extract the contents of a zip file held in a stream. + /// + /// The seekable input stream containing the zip to extract from. + /// The directory to save extracted information in. + /// The style of overwriting to apply. + /// A delegate to invoke when confirming overwriting. + /// A filter to apply to files. + /// A filter to apply to directories. + /// Flag indicating whether to restore the date and time for extracted files. + /// Flag indicating whether the inputStream will be closed by this method. + public void ExtractZip(Stream inputStream, string targetDirectory, + Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate, + string fileFilter, string directoryFilter, bool restoreDateTime, + bool isStreamOwner) + { + if ((overwrite == Overwrite.Prompt) && (confirmDelegate == null)) { + throw new ArgumentNullException("confirmDelegate"); + } + + continueRunning_ = true; + overwrite_ = overwrite; + confirmDelegate_ = confirmDelegate; + extractNameTransform_ = new WindowsNameTransform(targetDirectory); + + fileFilter_ = new NameFilter(fileFilter); + directoryFilter_ = new NameFilter(directoryFilter); + restoreDateTimeOnExtract_ = restoreDateTime; + + using (zipFile_ = new ZipFile(inputStream)) { + +#if !NETCF_1_0 + if (password_ != null) { + zipFile_.Password = password_; + } +#endif + zipFile_.IsStreamOwner = isStreamOwner; + System.Collections.IEnumerator enumerator = zipFile_.GetEnumerator(); + while (continueRunning_ && enumerator.MoveNext()) { + ZipEntry entry = (ZipEntry)enumerator.Current; + if (entry.IsFile) + { + // TODO Path.GetDirectory can fail here on invalid characters. + if (directoryFilter_.IsMatch(Path.GetDirectoryName(entry.Name)) && fileFilter_.IsMatch(entry.Name)) { + ExtractEntry(entry); + } + } + else if (entry.IsDirectory) { + if (directoryFilter_.IsMatch(entry.Name) && CreateEmptyDirectories) { + ExtractEntry(entry); + } + } + else { + // Do nothing for volume labels etc... + } + } + } + } + #endregion + + #region Internal Processing + void ProcessDirectory(object sender, DirectoryEventArgs e) + { + if ( !e.HasMatchingFiles && CreateEmptyDirectories ) { + if ( events_ != null ) { + events_.OnProcessDirectory(e.Name, e.HasMatchingFiles); + } + + if ( e.ContinueRunning ) { + if (e.Name != sourceDirectory_) { + ZipEntry entry = entryFactory_.MakeDirectoryEntry(e.Name); + outputStream_.PutNextEntry(entry); + } + } + } + } + + void ProcessFile(object sender, ScanEventArgs e) + { + if ( (events_ != null) && (events_.ProcessFile != null) ) { + events_.ProcessFile(sender, e); + } + + if ( e.ContinueRunning ) { + try { + // The open below is equivalent to OpenRead which gaurantees that if opened the + // file will not be changed by subsequent openers, but precludes opening in some cases + // were it could succeed. + using (FileStream stream = File.Open(e.Name, FileMode.Open, FileAccess.Read, FileShare.Read)) { + ZipEntry entry = entryFactory_.MakeFileEntry(e.Name); + outputStream_.PutNextEntry(entry); + AddFileContents(e.Name, stream); + } + } + catch(Exception ex) { + if (events_ != null) { + continueRunning_ = events_.OnFileFailure(e.Name, ex); + } + else { + continueRunning_ = false; + throw; + } + } + } + } + + void AddFileContents(string name, Stream stream) + { + if( stream==null ) { + throw new ArgumentNullException("stream"); + } + + if( buffer_==null ) { + buffer_=new byte[4096]; + } + + if( (events_!=null)&&(events_.Progress!=null) ) { + StreamUtils.Copy(stream, outputStream_, buffer_, + events_.Progress, events_.ProgressInterval, this, name); + } + else { + StreamUtils.Copy(stream, outputStream_, buffer_); + } + + if( events_!=null ) { + continueRunning_=events_.OnCompletedFile(name); + } + } + + void ExtractFileEntry(ZipEntry entry, string targetName) + { + bool proceed = true; + if ( overwrite_ != Overwrite.Always ) { + if ( File.Exists(targetName) ) { + if ( (overwrite_ == Overwrite.Prompt) && (confirmDelegate_ != null) ) { + proceed = confirmDelegate_(targetName); + } + else { + proceed = false; + } + } + } + + if ( proceed ) { + if ( events_ != null ) { + continueRunning_ = events_.OnProcessFile(entry.Name); + } + + if ( continueRunning_ ) { + try { + using ( FileStream outputStream = File.Create(targetName) ) { + if ( buffer_ == null ) { + buffer_ = new byte[4096]; + } + if ((events_ != null) && (events_.Progress != null)) + { + StreamUtils.Copy(zipFile_.GetInputStream(entry), outputStream, buffer_, + events_.Progress, events_.ProgressInterval, this, entry.Name, entry.Size); + } + else + { + StreamUtils.Copy(zipFile_.GetInputStream(entry), outputStream, buffer_); + } + + if (events_ != null) { + continueRunning_ = events_.OnCompletedFile(entry.Name); + } + } + +#if !NETCF_1_0 && !NETCF_2_0 + if ( restoreDateTimeOnExtract_ ) { + File.SetLastWriteTime(targetName, entry.DateTime); + } + + if ( RestoreAttributesOnExtract && entry.IsDOSEntry && (entry.ExternalFileAttributes != -1)) { + FileAttributes fileAttributes = (FileAttributes) entry.ExternalFileAttributes; + // TODO: FastZip - Setting of other file attributes on extraction is a little trickier. + fileAttributes &= (FileAttributes.Archive | FileAttributes.Normal | FileAttributes.ReadOnly | FileAttributes.Hidden); + File.SetAttributes(targetName, fileAttributes); + } +#endif + } + catch(Exception ex) { + if ( events_ != null ) { + continueRunning_ = events_.OnFileFailure(targetName, ex); + } + else { + continueRunning_ = false; + throw; + } + } + } + } + } + + void ExtractEntry(ZipEntry entry) + { + bool doExtraction = entry.IsCompressionMethodSupported(); + string targetName = entry.Name; + + if ( doExtraction ) { + if ( entry.IsFile ) { + targetName = extractNameTransform_.TransformFile(targetName); + } + else if ( entry.IsDirectory ) { + targetName = extractNameTransform_.TransformDirectory(targetName); + } + + doExtraction = !((targetName == null) || (targetName.Length == 0)); + } + + // TODO: Fire delegate/throw exception were compression method not supported, or name is invalid? + + string dirName = null; + + if ( doExtraction ) { + if ( entry.IsDirectory ) { + dirName = targetName; + } + else { + dirName = Path.GetDirectoryName(Path.GetFullPath(targetName)); + } + } + + if ( doExtraction && !Directory.Exists(dirName) ) { + if ( !entry.IsDirectory || CreateEmptyDirectories ) { + try { + Directory.CreateDirectory(dirName); + } + catch (Exception ex) { + doExtraction = false; + if ( events_ != null ) { + if ( entry.IsDirectory ) { + continueRunning_ = events_.OnDirectoryFailure(targetName, ex); + } + else { + continueRunning_ = events_.OnFileFailure(targetName, ex); + } + } + else { + continueRunning_ = false; + throw; + } + } + } + } + + if ( doExtraction && entry.IsFile ) { + ExtractFileEntry(entry, targetName); + } + } + + static int MakeExternalAttributes(FileInfo info) + { + return (int)info.Attributes; + } + +#if NET_1_0 || NET_1_1 || NETCF_1_0 + static bool NameIsValid(string name) + { + return (name != null) && + (name.Length > 0) && + (name.IndexOfAny(Path.InvalidPathChars) < 0); + } +#else + static bool NameIsValid(string name) + { + return (name != null) && + (name.Length > 0) && + (name.IndexOfAny(Path.GetInvalidPathChars()) < 0); + } +#endif + #endregion + + #region Instance Fields + bool continueRunning_; + byte[] buffer_; + ZipOutputStream outputStream_; + ZipFile zipFile_; + string sourceDirectory_; + NameFilter fileFilter_; + NameFilter directoryFilter_; + Overwrite overwrite_; + ConfirmOverwriteDelegate confirmDelegate_; + + bool restoreDateTimeOnExtract_; + bool restoreAttributesOnExtract_; + bool createEmptyDirectories_; + FastZipEvents events_; + IEntryFactory entryFactory_ = new ZipEntryFactory(); + INameTransform extractNameTransform_; + UseZip64 useZip64_=UseZip64.Dynamic; + +#if !NETCF_1_0 + string password_; +#endif + + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/IEntryFactory.cs b/类库/VersionUpdate/ZIP/Zip/IEntryFactory.cs new file mode 100644 index 0000000..ed7001c --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/IEntryFactory.cs @@ -0,0 +1,83 @@ +// IEntryFactory.cs +// +// Copyright 2006 John Reilly +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// Defines factory methods for creating new values. + /// + public interface IEntryFactory + { + /// + /// Create a for a file given its name + /// + /// The name of the file to create an entry for. + /// Returns a file entry based on the passed. + ZipEntry MakeFileEntry(string fileName); + + /// + /// Create a for a file given its name + /// + /// The name of the file to create an entry for. + /// If true get details from the file system if the file exists. + /// Returns a file entry based on the passed. + ZipEntry MakeFileEntry(string fileName, bool useFileSystem); + + /// + /// Create a for a directory given its name + /// + /// The name of the directory to create an entry for. + /// Returns a directory entry based on the passed. + ZipEntry MakeDirectoryEntry(string directoryName); + + /// + /// Create a for a directory given its name + /// + /// The name of the directory to create an entry for. + /// If true get details from the file system for this directory if it exists. + /// Returns a directory entry based on the passed. + ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem); + + /// + /// Get/set the applicable. + /// + INameTransform NameTransform { get; set; } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/WindowsNameTransform.cs b/类库/VersionUpdate/ZIP/Zip/WindowsNameTransform.cs new file mode 100644 index 0000000..31430c6 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/WindowsNameTransform.cs @@ -0,0 +1,272 @@ +// WindowsNameTransform.cs +// +// Copyright 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; +using System.Text; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// WindowsNameTransform transforms names to windows compatible ones. + /// + public class WindowsNameTransform : INameTransform + { + /// + /// Initialises a new instance of + /// + /// + public WindowsNameTransform(string baseDirectory) + { + if ( baseDirectory == null ) { + throw new ArgumentNullException("baseDirectory", "Directory name is invalid"); + } + + BaseDirectory = baseDirectory; + } + + /// + /// Initialise a default instance of + /// + public WindowsNameTransform() + { + // Do nothing. + } + + /// + /// Gets or sets a value containing the target directory to prefix values with. + /// + public string BaseDirectory + { + get { return _baseDirectory; } + set { + if ( value == null ) { + throw new ArgumentNullException("value"); + } + + _baseDirectory = Path.GetFullPath(value); + } + } + + /// + /// Gets or sets a value indicating wether paths on incoming values should be removed. + /// + public bool TrimIncomingPaths + { + get { return _trimIncomingPaths; } + set { _trimIncomingPaths = value; } + } + + /// + /// Transform a Zip directory name to a windows directory name. + /// + /// The directory name to transform. + /// The transformed name. + public string TransformDirectory(string name) + { + name = TransformFile(name); + if (name.Length > 0) { + while ( name.EndsWith(@"\") ) { + name = name.Remove(name.Length - 1, 1); + } + } + else { + throw new ZipException("Cannot have an empty directory name"); + } + return name; + } + + /// + /// Transform a Zip format file name to a windows style one. + /// + /// The file name to transform. + /// The transformed name. + public string TransformFile(string name) + { + if (name != null) { + name = MakeValidName(name, _replacementChar); + + if ( _trimIncomingPaths ) { + name = Path.GetFileName(name); + } + + // This may exceed windows length restrictions. + // Combine will throw a PathTooLongException in that case. + if ( _baseDirectory != null ) { + name = Path.Combine(_baseDirectory, name); + } + } + else { + name = string.Empty; + } + return name; + } + + /// + /// Test a name to see if it is a valid name for a windows filename as extracted from a Zip archive. + /// + /// The name to test. + /// Returns true if the name is a valid zip name; false otherwise. + /// The filename isnt a true windows path in some fundamental ways like no absolute paths, no rooted paths etc. + public static bool IsValidName(string name) + { + bool result = + (name != null) && + (name.Length <= MaxPath) && + (string.Compare(name, MakeValidName(name, '_')) == 0) + ; + + return result; + } + + /// + /// Initialise static class information. + /// + static WindowsNameTransform() + { + char[] invalidPathChars; + +#if NET_1_0 || NET_1_1 || NETCF_1_0 + invalidPathChars = Path.InvalidPathChars; +#else + invalidPathChars = Path.GetInvalidPathChars(); +#endif + int howMany = invalidPathChars.Length + 3; + + InvalidEntryChars = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length); + InvalidEntryChars[howMany - 1] = '*'; + InvalidEntryChars[howMany - 2] = '?'; + InvalidEntryChars[howMany - 3] = ':'; + } + + /// + /// Force a name to be valid by replacing invalid characters with a fixed value + /// + /// The name to make valid + /// The replacement character to use for any invalid characters. + /// Returns a valid name + public static string MakeValidName(string name, char replacement) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + name = WindowsPathUtils.DropPathRoot(name.Replace("/", @"\")); + + // Drop any leading slashes. + while ( (name.Length > 0) && (name[0] == '\\')) { + name = name.Remove(0, 1); + } + + // Drop any trailing slashes. + while ( (name.Length > 0) && (name[name.Length - 1] == '\\')) { + name = name.Remove(name.Length - 1, 1); + } + + // Convert consecutive \\ characters to \ + int index = name.IndexOf(@"\\"); + while (index >= 0) { + name = name.Remove(index, 1); + index = name.IndexOf(@"\\"); + } + + // Convert any invalid characters using the replacement one. + index = name.IndexOfAny(InvalidEntryChars); + if (index >= 0) { + StringBuilder builder = new StringBuilder(name); + + while (index >= 0 ) { + builder[index] = replacement; + + if (index >= name.Length) { + index = -1; + } + else { + index = name.IndexOfAny(InvalidEntryChars, index + 1); + } + } + name = builder.ToString(); + } + + // Check for names greater than MaxPath characters. + // TODO: Were is CLR version of MaxPath defined? Can't find it in Environment. + if ( name.Length > MaxPath ) { + throw new PathTooLongException(); + } + + return name; + } + + /// + /// Gets or set the character to replace invalid characters during transformations. + /// + public char Replacement + { + get { return _replacementChar; } + set { + for ( int i = 0; i < InvalidEntryChars.Length; ++i ) { + if ( InvalidEntryChars[i] == value ) { + throw new ArgumentException("invalid path character"); + } + } + + if ((value == '\\') || (value == '/')) { + throw new ArgumentException("invalid replacement character"); + } + + _replacementChar = value; + } + } + + /// + /// The maximum windows path name permitted. + /// + /// This may not valid for all windows systems - CE?, etc but I cant find the equivalent in the CLR. + const int MaxPath = 260; + + #region Instance Fields + string _baseDirectory; + bool _trimIncomingPaths; + char _replacementChar = '_'; + #endregion + + #region Class Fields + static readonly char[] InvalidEntryChars; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipConstants.cs b/类库/VersionUpdate/ZIP/Zip/ZipConstants.cs new file mode 100644 index 0000000..3a19c5f --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipConstants.cs @@ -0,0 +1,632 @@ +// ZipConstants.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support + +using System; +using System.Text; +using System.Threading; + +#if NETCF_1_0 || NETCF_2_0 +using System.Globalization; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + + #region Enumerations + + /// + /// Determines how entries are tested to see if they should use Zip64 extensions or not. + /// + public enum UseZip64 + { + /// + /// Zip64 will not be forced on entries during processing. + /// + /// An entry can have this overridden if required + Off, + /// + /// Zip64 should always be used. + /// + On, + /// + /// #ZipLib will determine use based on entry values when added to archive. + /// + Dynamic, + } + + /// + /// The kind of compression used for an entry in an archive + /// + public enum CompressionMethod + { + /// + /// A direct copy of the file contents is held in the archive + /// + Stored = 0, + + /// + /// Common Zip compression method using a sliding dictionary + /// of up to 32KB and secondary compression from Huffman/Shannon-Fano trees + /// + Deflated = 8, + + /// + /// An extension to deflate with a 64KB window. Not supported by #Zip currently + /// + Deflate64 = 9, + + /// + /// BZip2 compression. Not supported by #Zip. + /// + BZip2 = 11, + + /// + /// WinZip special for AES encryption, Now supported by #Zip. + /// + WinZipAES = 99, + + } + + /// + /// Identifies the encryption algorithm used for an entry + /// + public enum EncryptionAlgorithm + { + /// + /// No encryption has been used. + /// + None = 0, + /// + /// Encrypted using PKZIP 2.0 or 'classic' encryption. + /// + PkzipClassic = 1, + /// + /// DES encryption has been used. + /// + Des = 0x6601, + /// + /// RCS encryption has been used for encryption. + /// + RC2 = 0x6602, + /// + /// Triple DES encryption with 168 bit keys has been used for this entry. + /// + TripleDes168 = 0x6603, + /// + /// Triple DES with 112 bit keys has been used for this entry. + /// + TripleDes112 = 0x6609, + /// + /// AES 128 has been used for encryption. + /// + Aes128 = 0x660e, + /// + /// AES 192 has been used for encryption. + /// + Aes192 = 0x660f, + /// + /// AES 256 has been used for encryption. + /// + Aes256 = 0x6610, + /// + /// RC2 corrected has been used for encryption. + /// + RC2Corrected = 0x6702, + /// + /// Blowfish has been used for encryption. + /// + Blowfish = 0x6720, + /// + /// Twofish has been used for encryption. + /// + Twofish = 0x6721, + /// + /// RC4 has been used for encryption. + /// + RC4 = 0x6801, + /// + /// An unknown algorithm has been used for encryption. + /// + Unknown = 0xffff + } + + /// + /// Defines the contents of the general bit flags field for an archive entry. + /// + [Flags] + public enum GeneralBitFlags : int + { + /// + /// Bit 0 if set indicates that the file is encrypted + /// + Encrypted = 0x0001, + /// + /// Bits 1 and 2 - Two bits defining the compression method (only for Method 6 Imploding and 8,9 Deflating) + /// + Method = 0x0006, + /// + /// Bit 3 if set indicates a trailing data desciptor is appended to the entry data + /// + Descriptor = 0x0008, + /// + /// Bit 4 is reserved for use with method 8 for enhanced deflation + /// + ReservedPKware4 = 0x0010, + /// + /// Bit 5 if set indicates the file contains Pkzip compressed patched data. + /// Requires version 2.7 or greater. + /// + Patched = 0x0020, + /// + /// Bit 6 if set indicates strong encryption has been used for this entry. + /// + StrongEncryption = 0x0040, + /// + /// Bit 7 is currently unused + /// + Unused7 = 0x0080, + /// + /// Bit 8 is currently unused + /// + Unused8 = 0x0100, + /// + /// Bit 9 is currently unused + /// + Unused9 = 0x0200, + /// + /// Bit 10 is currently unused + /// + Unused10 = 0x0400, + /// + /// Bit 11 if set indicates the filename and + /// comment fields for this file must be encoded using UTF-8. + /// + UnicodeText = 0x0800, + /// + /// Bit 12 is documented as being reserved by PKware for enhanced compression. + /// + EnhancedCompress = 0x1000, + /// + /// Bit 13 if set indicates that values in the local header are masked to hide + /// their actual values, and the central directory is encrypted. + /// + /// + /// Used when encrypting the central directory contents. + /// + HeaderMasked = 0x2000, + /// + /// Bit 14 is documented as being reserved for use by PKware + /// + ReservedPkware14 = 0x4000, + /// + /// Bit 15 is documented as being reserved for use by PKware + /// + ReservedPkware15 = 0x8000 + } + + #endregion + + /// + /// This class contains constants used for Zip format files + /// + public sealed class ZipConstants + { + #region Versions + /// + /// The version made by field for entries in the central header when created by this library + /// + /// + /// This is also the Zip version for the library when comparing against the version required to extract + /// for an entry. See . + /// + public const int VersionMadeBy = 51; // was 45 before AES + + /// + /// The version made by field for entries in the central header when created by this library + /// + /// + /// This is also the Zip version for the library when comparing against the version required to extract + /// for an entry. See ZipInputStream.CanDecompressEntry. + /// + [Obsolete("Use VersionMadeBy instead")] + public const int VERSION_MADE_BY = 51; + + /// + /// The minimum version required to support strong encryption + /// + public const int VersionStrongEncryption = 50; + + /// + /// The minimum version required to support strong encryption + /// + [Obsolete("Use VersionStrongEncryption instead")] + public const int VERSION_STRONG_ENCRYPTION = 50; + + /// + /// Version indicating AES encryption + /// + public const int VERSION_AES = 51; + + /// + /// The version required for Zip64 extensions (4.5 or higher) + /// + public const int VersionZip64 = 45; + #endregion + + #region Header Sizes + /// + /// Size of local entry header (excluding variable length fields at end) + /// + public const int LocalHeaderBaseSize = 30; + + /// + /// Size of local entry header (excluding variable length fields at end) + /// + [Obsolete("Use LocalHeaderBaseSize instead")] + public const int LOCHDR = 30; + + /// + /// Size of Zip64 data descriptor + /// + public const int Zip64DataDescriptorSize = 24; + + /// + /// Size of data descriptor + /// + public const int DataDescriptorSize = 16; + + /// + /// Size of data descriptor + /// + [Obsolete("Use DataDescriptorSize instead")] + public const int EXTHDR = 16; + + /// + /// Size of central header entry (excluding variable fields) + /// + public const int CentralHeaderBaseSize = 46; + + /// + /// Size of central header entry + /// + [Obsolete("Use CentralHeaderBaseSize instead")] + public const int CENHDR = 46; + + /// + /// Size of end of central record (excluding variable fields) + /// + public const int EndOfCentralRecordBaseSize = 22; + + /// + /// Size of end of central record (excluding variable fields) + /// + [Obsolete("Use EndOfCentralRecordBaseSize instead")] + public const int ENDHDR = 22; + + /// + /// Size of 'classic' cryptographic header stored before any entry data + /// + public const int CryptoHeaderSize = 12; + + /// + /// Size of cryptographic header stored before entry data + /// + [Obsolete("Use CryptoHeaderSize instead")] + public const int CRYPTO_HEADER_SIZE = 12; + #endregion + + #region Header Signatures + + /// + /// Signature for local entry header + /// + public const int LocalHeaderSignature = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); + + /// + /// Signature for local entry header + /// + [Obsolete("Use LocalHeaderSignature instead")] + public const int LOCSIG = 'P' | ('K' << 8) | (3 << 16) | (4 << 24); + + /// + /// Signature for spanning entry + /// + public const int SpanningSignature = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for spanning entry + /// + [Obsolete("Use SpanningSignature instead")] + public const int SPANNINGSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for temporary spanning entry + /// + public const int SpanningTempSignature = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24); + + /// + /// Signature for temporary spanning entry + /// + [Obsolete("Use SpanningTempSignature instead")] + public const int SPANTEMPSIG = 'P' | ('K' << 8) | ('0' << 16) | ('0' << 24); + + /// + /// Signature for data descriptor + /// + /// + /// This is only used where the length, Crc, or compressed size isnt known when the + /// entry is created and the output stream doesnt support seeking. + /// The local entry cannot be 'patched' with the correct values in this case + /// so the values are recorded after the data prefixed by this header, as well as in the central directory. + /// + public const int DataDescriptorSignature = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for data descriptor + /// + /// + /// This is only used where the length, Crc, or compressed size isnt known when the + /// entry is created and the output stream doesnt support seeking. + /// The local entry cannot be 'patched' with the correct values in this case + /// so the values are recorded after the data prefixed by this header, as well as in the central directory. + /// + [Obsolete("Use DataDescriptorSignature instead")] + public const int EXTSIG = 'P' | ('K' << 8) | (7 << 16) | (8 << 24); + + /// + /// Signature for central header + /// + [Obsolete("Use CentralHeaderSignature instead")] + public const int CENSIG = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); + + /// + /// Signature for central header + /// + public const int CentralHeaderSignature = 'P' | ('K' << 8) | (1 << 16) | (2 << 24); + + /// + /// Signature for Zip64 central file header + /// + public const int Zip64CentralFileHeaderSignature = 'P' | ('K' << 8) | (6 << 16) | (6 << 24); + + /// + /// Signature for Zip64 central file header + /// + [Obsolete("Use Zip64CentralFileHeaderSignature instead")] + public const int CENSIG64 = 'P' | ('K' << 8) | (6 << 16) | (6 << 24); + + /// + /// Signature for Zip64 central directory locator + /// + public const int Zip64CentralDirLocatorSignature = 'P' | ('K' << 8) | (6 << 16) | (7 << 24); + + /// + /// Signature for archive extra data signature (were headers are encrypted). + /// + public const int ArchiveExtraDataSignature = 'P' | ('K' << 8) | (6 << 16) | (7 << 24); + + /// + /// Central header digitial signature + /// + public const int CentralHeaderDigitalSignature = 'P' | ('K' << 8) | (5 << 16) | (5 << 24); + + /// + /// Central header digitial signature + /// + [Obsolete("Use CentralHeaderDigitalSignaure instead")] + public const int CENDIGITALSIG = 'P' | ('K' << 8) | (5 << 16) | (5 << 24); + + /// + /// End of central directory record signature + /// + public const int EndOfCentralDirectorySignature = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); + + /// + /// End of central directory record signature + /// + [Obsolete("Use EndOfCentralDirectorySignature instead")] + public const int ENDSIG = 'P' | ('K' << 8) | (5 << 16) | (6 << 24); + #endregion + +#if NETCF_1_0 || NETCF_2_0 + // This isnt so great but is better than nothing. + // Trying to work out an appropriate OEM code page would be good. + // 850 is a good default for english speakers particularly in Europe. + static int defaultCodePage = CultureInfo.CurrentCulture.TextInfo.ANSICodePage; +#else + static int defaultCodePage = Thread.CurrentThread.CurrentCulture.TextInfo.OEMCodePage; +#endif + + /// + /// Default encoding used for string conversion. 0 gives the default system OEM code page. + /// Dont use unicode encodings if you want to be Zip compatible! + /// Using the default code page isnt the full solution neccessarily + /// there are many variable factors, codepage 850 is often a good choice for + /// European users, however be careful about compatability. + /// + public static int DefaultCodePage { + get { + return defaultCodePage; + } + set { + defaultCodePage = value; + } + } + + /// + /// Convert a portion of a byte array to a string. + /// + /// + /// Data to convert to string + /// + /// + /// Number of bytes to convert starting from index 0 + /// + /// + /// data[0]..data[length - 1] converted to a string + /// + public static string ConvertToString(byte[] data, int count) + { + if ( data == null ) { + return string.Empty; + } + + return Encoding.GetEncoding(DefaultCodePage).GetString(data, 0, count); + } + + /// + /// Convert a byte array to string + /// + /// + /// Byte array to convert + /// + /// + /// dataconverted to a string + /// + public static string ConvertToString(byte[] data) + { + if ( data == null ) { + return string.Empty; + } + return ConvertToString(data, data.Length); + } + + /// + /// Convert a byte array to string + /// + /// The applicable general purpose bits flags + /// + /// Byte array to convert + /// + /// The number of bytes to convert. + /// + /// dataconverted to a string + /// + public static string ConvertToStringExt(int flags, byte[] data, int count) + { + if ( data == null ) { + return string.Empty; + } + + if ( (flags & (int)GeneralBitFlags.UnicodeText) != 0 ) { + return Encoding.UTF8.GetString(data, 0, count); + } + else { + return ConvertToString(data, count); + } + } + + /// + /// Convert a byte array to string + /// + /// + /// Byte array to convert + /// + /// The applicable general purpose bits flags + /// + /// dataconverted to a string + /// + public static string ConvertToStringExt(int flags, byte[] data) + { + if ( data == null ) { + return string.Empty; + } + + if ( (flags & (int)GeneralBitFlags.UnicodeText) != 0 ) { + return Encoding.UTF8.GetString(data, 0, data.Length); + } + else { + return ConvertToString(data, data.Length); + } + } + + /// + /// Convert a string to a byte array + /// + /// + /// String to convert to an array + /// + /// Converted array + public static byte[] ConvertToArray(string str) + { + if ( str == null ) { + return new byte[0]; + } + + return Encoding.GetEncoding(DefaultCodePage).GetBytes(str); + } + + /// + /// Convert a string to a byte array + /// + /// The applicable general purpose bits flags + /// + /// String to convert to an array + /// + /// Converted array + public static byte[] ConvertToArray(int flags, string str) + { + if (str == null) { + return new byte[0]; + } + + if ((flags & (int)GeneralBitFlags.UnicodeText) != 0) { + return Encoding.UTF8.GetBytes(str); + } + else { + return ConvertToArray(str); + } + } + + + /// + /// Initialise default instance of ZipConstants + /// + /// + /// Private to prevent instances being created. + /// + ZipConstants() + { + // Do nothing + } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipEntry.cs b/类库/VersionUpdate/ZIP/Zip/ZipEntry.cs new file mode 100644 index 0000000..0e34784 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipEntry.cs @@ -0,0 +1,1253 @@ +// ZipEntry.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 DavidPierson Added AES support +// 02-02-2010 DavidPierson Changed NTFS Extra Data min length to 4 + +using ICSharpCode.SharpZipLib.Zip; +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Zip1 +{ + + /// + /// Defines known values for the property. + /// + public enum HostSystemID + { + /// + /// Host system = MSDOS + /// + Msdos = 0, + /// + /// Host system = Amiga + /// + Amiga = 1, + /// + /// Host system = Open VMS + /// + OpenVms = 2, + /// + /// Host system = Unix + /// + Unix = 3, + /// + /// Host system = VMCms + /// + VMCms = 4, + /// + /// Host system = Atari ST + /// + AtariST = 5, + /// + /// Host system = OS2 + /// + OS2 = 6, + /// + /// Host system = Macintosh + /// + Macintosh = 7, + /// + /// Host system = ZSystem + /// + ZSystem = 8, + /// + /// Host system = Cpm + /// + Cpm = 9, + /// + /// Host system = Windows NT + /// + WindowsNT = 10, + /// + /// Host system = MVS + /// + MVS = 11, + /// + /// Host system = VSE + /// + Vse = 12, + /// + /// Host system = Acorn RISC + /// + AcornRisc = 13, + /// + /// Host system = VFAT + /// + Vfat = 14, + /// + /// Host system = Alternate MVS + /// + AlternateMvs = 15, + /// + /// Host system = BEOS + /// + BeOS = 16, + /// + /// Host system = Tandem + /// + Tandem = 17, + /// + /// Host system = OS400 + /// + OS400 = 18, + /// + /// Host system = OSX + /// + OSX = 19, + /// + /// Host system = WinZIP AES + /// + WinZipAES = 99, + } + + /// + /// This class represents an entry in a zip archive. This can be a file + /// or a directory + /// ZipFile and ZipInputStream will give you instances of this class as + /// information about the members in an archive. ZipOutputStream + /// uses an instance of this class when creating an entry in a Zip file. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ public class ZipEntry : ICloneable + { + [Flags] + enum Known : byte + { + None = 0, + Size = 0x01, + CompressedSize = 0x02, + Crc = 0x04, + Time = 0x08, + ExternalAttributes = 0x10, + } + + #region Constructors + /// + /// Creates a zip entry with the given name. + /// + /// + /// The name for this entry. Can include directory components. + /// The convention for names is 'unix' style paths with relative names only. + /// There are with no device names and path elements are separated by '/' characters. + /// + /// + /// The name passed is null + /// + public ZipEntry(string name) + : this(name, 0, ZipConstants.VersionMadeBy, CompressionMethod.Deflated) + { + } + + /// + /// Creates a zip entry with the given name and version required to extract + /// + /// + /// The name for this entry. Can include directory components. + /// The convention for names is 'unix' style paths with no device names and + /// path elements separated by '/' characters. This is not enforced see CleanName + /// on how to ensure names are valid if this is desired. + /// + /// + /// The minimum 'feature version' required this entry + /// + /// + /// The name passed is null + /// + internal ZipEntry(string name, int versionRequiredToExtract) + : this(name, versionRequiredToExtract, ZipConstants.VersionMadeBy, + CompressionMethod.Deflated) + { + } + + /// + /// Initializes an entry with the given name and made by information + /// + /// Name for this entry + /// Version and HostSystem Information + /// Minimum required zip feature version required to extract this entry + /// Compression method for this entry. + /// + /// The name passed is null + /// + /// + /// versionRequiredToExtract should be 0 (auto-calculate) or > 10 + /// + /// + /// This constructor is used by the ZipFile class when reading from the central header + /// It is not generally useful, use the constructor specifying the name only. + /// + internal ZipEntry(string name, int versionRequiredToExtract, int madeByInfo, + CompressionMethod method) + { + if (name == null) { + throw new System.ArgumentNullException("name"); + } + + if ( name.Length > 0xffff ) { + throw new ArgumentException("Name is too long", "name"); + } + + if ( (versionRequiredToExtract != 0) && (versionRequiredToExtract < 10) ) { + throw new ArgumentOutOfRangeException("versionRequiredToExtract"); + } + + this.DateTime = System.DateTime.Now; + this.name = name; + this.versionMadeBy = (ushort)madeByInfo; + this.versionToExtract = (ushort)versionRequiredToExtract; + this.method = method; + } + + /// + /// Creates a deep copy of the given zip entry. + /// + /// + /// The entry to copy. + /// + [Obsolete("Use Clone instead")] + public ZipEntry(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + known = entry.known; + name = entry.name; + size = entry.size; + compressedSize = entry.compressedSize; + crc = entry.crc; + dosTime = entry.dosTime; + method = entry.method; + comment = entry.comment; + versionToExtract = entry.versionToExtract; + versionMadeBy = entry.versionMadeBy; + externalFileAttributes = entry.externalFileAttributes; + flags = entry.flags; + + zipFileIndex = entry.zipFileIndex; + offset = entry.offset; + + forceZip64_ = entry.forceZip64_; + + if ( entry.extra != null ) { + extra = new byte[entry.extra.Length]; + Array.Copy(entry.extra, 0, extra, 0, entry.extra.Length); + } + } + + #endregion + + /// + /// Get a value indicating wether the entry has a CRC value available. + /// + public bool HasCrc + { + get { + return (known & Known.Crc) != 0; + } + } + + /// + /// Get/Set flag indicating if entry is encrypted. + /// A simple helper routine to aid interpretation of flags + /// + /// This is an assistant that interprets the flags property. + public bool IsCrypted + { + get { + return (flags & 1) != 0; + } + set { + if (value) { + flags |= 1; + } + else { + flags &= ~1; + } + } + } + + /// + /// Get / set a flag indicating wether entry name and comment text are + /// encoded in unicode UTF8. + /// + /// This is an assistant that interprets the flags property. + public bool IsUnicodeText + { + get { + return ( flags & (int)GeneralBitFlags.UnicodeText ) != 0; + } + set { + if ( value ) { + flags |= (int)GeneralBitFlags.UnicodeText; + } + else { + flags &= ~(int)GeneralBitFlags.UnicodeText; + } + } + } + + /// + /// Value used during password checking for PKZIP 2.0 / 'classic' encryption. + /// + internal byte CryptoCheckValue + { + get { + return cryptoCheckValue_; + } + + set { + cryptoCheckValue_ = value; + } + } + + /// + /// Get/Set general purpose bit flag for entry + /// + /// + /// General purpose bit flag
+ ///
+ /// Bit 0: If set, indicates the file is encrypted
+ /// Bit 1-2 Only used for compression type 6 Imploding, and 8, 9 deflating
+ /// Imploding:
+ /// Bit 1 if set indicates an 8K sliding dictionary was used. If clear a 4k dictionary was used
+ /// Bit 2 if set indicates 3 Shannon-Fanno trees were used to encode the sliding dictionary, 2 otherwise
+ ///
+ /// Deflating:
+ /// Bit 2 Bit 1
+ /// 0 0 Normal compression was used
+ /// 0 1 Maximum compression was used
+ /// 1 0 Fast compression was used
+ /// 1 1 Super fast compression was used
+ ///
+ /// Bit 3: If set, the fields crc-32, compressed size + /// and uncompressed size are were not able to be written during zip file creation + /// The correct values are held in a data descriptor immediately following the compressed data.
+ /// Bit 4: Reserved for use by PKZIP for enhanced deflating
+ /// Bit 5: If set indicates the file contains compressed patch data
+ /// Bit 6: If set indicates strong encryption was used.
+ /// Bit 7-10: Unused or reserved
+ /// Bit 11: If set the name and comments for this entry are in unicode.
+ /// Bit 12-15: Unused or reserved
+ ///
+ /// + /// + public int Flags + { + get { + return flags; + } + set { + flags = value; + } + } + + /// + /// Get/Set index of this entry in Zip file + /// + /// This is only valid when the entry is part of a + public long ZipFileIndex + { + get { + return zipFileIndex; + } + set { + zipFileIndex = value; + } + } + + /// + /// Get/set offset for use in central header + /// + public long Offset + { + get { + return offset; + } + set { + offset = value; + } + } + + /// + /// Get/Set external file attributes as an integer. + /// The values of this are operating system dependant see + /// HostSystem for details + /// + public int ExternalFileAttributes + { + get { + if ((known & Known.ExternalAttributes) == 0) { + return -1; + } + else { + return externalFileAttributes; + } + } + + set { + externalFileAttributes = value; + known |= Known.ExternalAttributes; + } + } + + /// + /// Get the version made by for this entry or zero if unknown. + /// The value / 10 indicates the major version number, and + /// the value mod 10 is the minor version number + /// + public int VersionMadeBy + { + get { + return (versionMadeBy & 0xff); + } + } + + /// + /// Get a value indicating this entry is for a DOS/Windows system. + /// + public bool IsDOSEntry + { + get { + return ((HostSystem == ( int )HostSystemID.Msdos) || + (HostSystem == ( int )HostSystemID.WindowsNT)); + } + } + + /// + /// Test the external attributes for this to + /// see if the external attributes are Dos based (including WINNT and variants) + /// and match the values + /// + /// The attributes to test. + /// Returns true if the external attributes are known to be DOS/Windows + /// based and have the same attributes set as the value passed. + bool HasDosAttributes(int attributes) + { + bool result = false; + if ( (known & Known.ExternalAttributes) != 0 ) { + if ( ((HostSystem == (int)HostSystemID.Msdos) || + (HostSystem == (int)HostSystemID.WindowsNT)) && + (ExternalFileAttributes & attributes) == attributes) { + result = true; + } + } + return result; + } + + /// + /// Gets the compatability information for the external file attribute + /// If the external file attributes are compatible with MS-DOS and can be read + /// by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value + /// will be non-zero and identify the host system on which the attributes are compatible. + /// + /// + /// + /// The values for this as defined in the Zip File format and by others are shown below. The values are somewhat + /// misleading in some cases as they are not all used as shown. You should consult the relevant documentation + /// to obtain up to date and correct information. The modified appnote by the infozip group is + /// particularly helpful as it documents a lot of peculiarities. The document is however a little dated. + /// + /// 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + /// 1 - Amiga + /// 2 - OpenVMS + /// 3 - Unix + /// 4 - VM/CMS + /// 5 - Atari ST + /// 6 - OS/2 HPFS + /// 7 - Macintosh + /// 8 - Z-System + /// 9 - CP/M + /// 10 - Windows NTFS + /// 11 - MVS (OS/390 - Z/OS) + /// 12 - VSE + /// 13 - Acorn Risc + /// 14 - VFAT + /// 15 - Alternate MVS + /// 16 - BeOS + /// 17 - Tandem + /// 18 - OS/400 + /// 19 - OS/X (Darwin) + /// 99 - WinZip AES + /// remainder - unused + /// + /// + public int HostSystem + { + get { + return (versionMadeBy >> 8) & 0xff; + } + + set { + versionMadeBy &= 0xff; + versionMadeBy |= (ushort)((value & 0xff) << 8); + } + } + + /// + /// Get minimum Zip feature version required to extract this entry + /// + /// + /// Minimum features are defined as:
+ /// 1.0 - Default value
+ /// 1.1 - File is a volume label
+ /// 2.0 - File is a folder/directory
+ /// 2.0 - File is compressed using Deflate compression
+ /// 2.0 - File is encrypted using traditional encryption
+ /// 2.1 - File is compressed using Deflate64
+ /// 2.5 - File is compressed using PKWARE DCL Implode
+ /// 2.7 - File is a patch data set
+ /// 4.5 - File uses Zip64 format extensions
+ /// 4.6 - File is compressed using BZIP2 compression
+ /// 5.0 - File is encrypted using DES
+ /// 5.0 - File is encrypted using 3DES
+ /// 5.0 - File is encrypted using original RC2 encryption
+ /// 5.0 - File is encrypted using RC4 encryption
+ /// 5.1 - File is encrypted using AES encryption
+ /// 5.1 - File is encrypted using corrected RC2 encryption
+ /// 5.1 - File is encrypted using corrected RC2-64 encryption
+ /// 6.1 - File is encrypted using non-OAEP key wrapping
+ /// 6.2 - Central directory encryption (not confirmed yet)
+ /// 6.3 - File is compressed using LZMA
+ /// 6.3 - File is compressed using PPMD+
+ /// 6.3 - File is encrypted using Blowfish
+ /// 6.3 - File is encrypted using Twofish
+ ///
+ /// + public int Version + { + get { + // Return recorded version if known. + if (versionToExtract != 0) { + return versionToExtract; + } + else { + int result = 10; + if (AESKeySize > 0) { + result = ZipConstants.VERSION_AES; // Ver 5.1 = AES + } + else if (CentralHeaderRequiresZip64) { + result = ZipConstants.VersionZip64; + } + else if (CompressionMethod.Deflated == method) { + result = 20; + } + else if (IsDirectory == true) { + result = 20; + } + else if (IsCrypted == true) { + result = 20; + } + else if (HasDosAttributes(0x08) ) { + result = 11; + } + return result; + } + } + } + + /// + /// Get a value indicating whether this entry can be decompressed by the library. + /// + /// This is based on the and + /// wether the compression method is supported. + public bool CanDecompress + { + get { + return (Version <= ZipConstants.VersionMadeBy) && + ((Version == 10) || + (Version == 11) || + (Version == 20) || + (Version == 45) || + (Version == 51)) && + IsCompressionMethodSupported(); + } + } + + /// + /// Force this entry to be recorded using Zip64 extensions. + /// + public void ForceZip64() + { + forceZip64_ = true; + } + + /// + /// Get a value indicating wether Zip64 extensions were forced. + /// + /// A value of true if Zip64 extensions have been forced on; false if not. + public bool IsZip64Forced() + { + return forceZip64_; + } + + /// + /// Gets a value indicating if the entry requires Zip64 extensions + /// to store the full entry values. + /// + /// A value of true if a local header requires Zip64 extensions; false if not. + public bool LocalHeaderRequiresZip64 + { + get { + bool result = forceZip64_; + + if ( !result ) { + ulong trueCompressedSize = compressedSize; + + if ( (versionToExtract == 0) && IsCrypted ) { + trueCompressedSize += ZipConstants.CryptoHeaderSize; + } + + // TODO: A better estimation of the true limit based on compression overhead should be used + // to determine when an entry should use Zip64. + result = + ((this.size >= uint.MaxValue) || (trueCompressedSize >= uint.MaxValue)) && + ((versionToExtract == 0) || (versionToExtract >= ZipConstants.VersionZip64)); + } + + return result; + } + } + + /// + /// Get a value indicating wether the central directory entry requires Zip64 extensions to be stored. + /// + public bool CentralHeaderRequiresZip64 + { + get { + return LocalHeaderRequiresZip64 || (offset >= uint.MaxValue); + } + } + + /// + /// Get/Set DosTime value. + /// + /// + /// The MS-DOS date format can only represent dates between 1/1/1980 and 12/31/2107. + /// + public long DosTime + { + get { + if ((known & Known.Time) == 0) { + return 0; + } + else { + return dosTime; + } + } + + set { + unchecked { + dosTime = (uint)value; + } + + known |= Known.Time; + } + } + + /// + /// Gets/Sets the time of last modification of the entry. + /// + /// + /// The property is updated to match this as far as possible. + /// + public DateTime DateTime + { + get { + uint sec = Math.Min(59, 2 * (dosTime & 0x1f)); + uint min = Math.Min(59, (dosTime >> 5) & 0x3f); + uint hrs = Math.Min(23, (dosTime >> 11) & 0x1f); + uint mon = Math.Max(1, Math.Min(12, ((dosTime >> 21) & 0xf))); + uint year = ((dosTime >> 25) & 0x7f) + 1980; + int day = Math.Max(1, Math.Min(DateTime.DaysInMonth((int)year, (int)mon), (int)((dosTime >> 16) & 0x1f))); + return new System.DateTime((int)year, (int)mon, day, (int)hrs, (int)min, (int)sec); + } + + set { + uint year = (uint) value.Year; + uint month = (uint) value.Month; + uint day = (uint) value.Day; + uint hour = (uint) value.Hour; + uint minute = (uint) value.Minute; + uint second = (uint) value.Second; + + if ( year < 1980 ) { + year = 1980; + month = 1; + day = 1; + hour = 0; + minute = 0; + second = 0; + } + else if ( year > 2107 ) { + year = 2107; + month = 12; + day = 31; + hour = 23; + minute = 59; + second = 59; + } + + DosTime = ((year - 1980) & 0x7f) << 25 | + (month << 21) | + (day << 16) | + (hour << 11) | + (minute << 5) | + (second >> 1); + } + } + + /// + /// Returns the entry name. + /// + /// + /// The unix naming convention is followed. + /// Path components in the entry should always separated by forward slashes ('/'). + /// Dos device names like C: should also be removed. + /// See the class, or + /// + public string Name + { + get { + return name; + } + } + + /// + /// Gets/Sets the size of the uncompressed data. + /// + /// + /// The size or -1 if unknown. + /// + /// Setting the size before adding an entry to an archive can help + /// avoid compatability problems with some archivers which dont understand Zip64 extensions. + public long Size + { + get { + return (known & Known.Size) != 0 ? (long)size : -1L; + } + set { + this.size = (ulong)value; + this.known |= Known.Size; + } + } + + /// + /// Gets/Sets the size of the compressed data. + /// + /// + /// The compressed entry size or -1 if unknown. + /// + public long CompressedSize + { + get { + return (known & Known.CompressedSize) != 0 ? (long)compressedSize : -1L; + } + set { + this.compressedSize = (ulong)value; + this.known |= Known.CompressedSize; + } + } + + /// + /// Gets/Sets the crc of the uncompressed data. + /// + /// + /// Crc is not in the range 0..0xffffffffL + /// + /// + /// The crc value or -1 if unknown. + /// + public long Crc + { + get { + return (known & Known.Crc) != 0 ? crc & 0xffffffffL : -1L; + } + set { + if (((ulong)crc & 0xffffffff00000000L) != 0) { + throw new ArgumentOutOfRangeException("value"); + } + this.crc = (uint)value; + this.known |= Known.Crc; + } + } + + /// + /// Gets/Sets the compression method. Only Deflated and Stored are supported. + /// + /// + /// The compression method for this entry + /// + /// + /// + public CompressionMethod CompressionMethod { + get { + return method; + } + + set { + if ( !IsCompressionMethodSupported(value) ) { + throw new NotSupportedException("Compression method not supported"); + } + this.method = value; + } + } + + /// + /// Gets the compression method for outputting to the local or central header. + /// Returns same value as CompressionMethod except when AES encrypting, which + /// places 99 in the method and places the real method in the extra data. + /// + internal CompressionMethod CompressionMethodForHeader { + get { + return (AESKeySize > 0) ? CompressionMethod.WinZipAES : method; + } + } + + /// + /// Gets/Sets the extra data. + /// + /// + /// Extra data is longer than 64KB (0xffff) bytes. + /// + /// + /// Extra data or null if not set. + /// + public byte[] ExtraData { + + get { +// TODO: This is slightly safer but less efficient. Think about wether it should change. +// return (byte[]) extra.Clone(); + return extra; + } + + set { + if (value == null) { + extra = null; + } + else { + if (value.Length > 0xffff) { + throw new System.ArgumentOutOfRangeException("value"); + } + + extra = new byte[value.Length]; + Array.Copy(value, 0, extra, 0, value.Length); + } + } + } + + +#if !NET_1_1 && !NETCF_2_0 + /// + /// For AES encrypted files returns or sets the number of bits of encryption (128, 192 or 256). + /// When setting, only 0 (off), 128 or 256 is supported. + /// + public int AESKeySize { + get { + // the strength (1 or 3) is in the entry header + switch (_aesEncryptionStrength) { + case 0: return 0; // Not AES + case 1: return 128; + case 2: return 192; // Not used by WinZip + case 3: return 256; + default: throw new ZipException("Invalid AESEncryptionStrength " + _aesEncryptionStrength); + } + } + set { + switch (value) { + case 0: _aesEncryptionStrength = 0; break; + case 128: _aesEncryptionStrength = 1; break; + case 256: _aesEncryptionStrength = 3; break; + default: throw new ZipException("AESKeySize must be 0, 128 or 256: " + value); + } + } + } + + /// + /// AES Encryption strength for storage in extra data in entry header. + /// 1 is 128 bit, 2 is 192 bit, 3 is 256 bit. + /// + internal byte AESEncryptionStrength { + get { + return (byte)_aesEncryptionStrength; + } + } +#else + /// + /// AES unsupported prior to .NET 2.0 + /// + internal int AESKeySize; +#endif + + /// + /// Returns the length of the salt, in bytes + /// + internal int AESSaltLen { + get { + // Key size -> Salt length: 128 bits = 8 bytes, 192 bits = 12 bytes, 256 bits = 16 bytes. + return AESKeySize / 16; + } + } + + /// + /// Number of extra bytes required to hold the AES Header fields (Salt, Pwd verify, AuthCode) + /// + internal int AESOverheadSize { + get { + // File format: + // Bytes Content + // Variable Salt value + // 2 Password verification value + // Variable Encrypted file data + // 10 Authentication code + return 12 + AESSaltLen; + } + } + + /// + /// Process extra data fields updating the entry based on the contents. + /// + /// True if the extra data fields should be handled + /// for a local header, rather than for a central header. + /// + internal void ProcessExtraData(bool localHeader) + { + ZipExtraData extraData = new ZipExtraData(this.extra); + + if ( extraData.Find(0x0001) ) { + // Version required to extract is ignored here as some archivers dont set it correctly + // in theory it should be version 45 or higher + + // The recorded size will change but remember that this is zip64. + forceZip64_ = true; + + if ( extraData.ValueLength < 4 ) { + throw new ZipException("Extra data extended Zip64 information length is invalid"); + } + + if ( localHeader || (size == uint.MaxValue) ) { + size = (ulong)extraData.ReadLong(); + } + + if ( localHeader || (compressedSize == uint.MaxValue) ) { + compressedSize = (ulong)extraData.ReadLong(); + } + + if ( !localHeader && (offset == uint.MaxValue) ) { + offset = extraData.ReadLong(); + } + + // Disk number on which file starts is ignored + } + else { + if ( + ((versionToExtract & 0xff) >= ZipConstants.VersionZip64) && + ((size == uint.MaxValue) || (compressedSize == uint.MaxValue)) + ) { + throw new ZipException("Zip64 Extended information required but is missing."); + } + } + + if ( extraData.Find(10) ) { + // No room for any tags. + if ( extraData.ValueLength < 4 ) { + throw new ZipException("NTFS Extra data invalid"); + } + + extraData.ReadInt(); // Reserved + + while ( extraData.UnreadCount >= 4 ) { + int ntfsTag = extraData.ReadShort(); + int ntfsLength = extraData.ReadShort(); + if ( ntfsTag == 1 ) { + if ( ntfsLength >= 24 ) { + long lastModification = extraData.ReadLong(); + long lastAccess = extraData.ReadLong(); + long createTime = extraData.ReadLong(); + + DateTime = System.DateTime.FromFileTime(lastModification); + } + break; + } + else { + // An unknown NTFS tag so simply skip it. + extraData.Skip(ntfsLength); + } + } + } + else if ( extraData.Find(0x5455) ) { + int length = extraData.ValueLength; + int flags = extraData.ReadByte(); + + // Can include other times but these are ignored. Length of data should + // actually be 1 + 4 * no of bits in flags. + if ( ((flags & 1) != 0) && (length >= 5) ) { + int iTime = extraData.ReadInt(); + + DateTime = (new System.DateTime ( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime() + + new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime(); + } + } + if (method == CompressionMethod.WinZipAES) { + ProcessAESExtraData(extraData); + } + } + + // For AES the method in the entry is 99, and the real compression method is in the extradata + // + private void ProcessAESExtraData(ZipExtraData extraData) { + +#if !NET_1_1 && !NETCF_2_0 + if (extraData.Find(0x9901)) { + // Set version and flag for Zipfile.CreateAndInitDecryptionStream + versionToExtract = ZipConstants.VERSION_AES; // Ver 5.1 = AES see "Version" getter + // Set StrongEncryption flag for ZipFile.CreateAndInitDecryptionStream + Flags = Flags | (int)GeneralBitFlags.StrongEncryption; + // + // Unpack AES extra data field see http://www.winzip.com/aes_info.htm + int length = extraData.ValueLength; // Data size currently 7 + if (length < 7) + throw new ZipException("AES Extra Data Length " + length + " invalid."); + int ver = extraData.ReadShort(); // Version number (1=AE-1 2=AE-2) + int vendorId = extraData.ReadShort(); // 2-character vendor ID 0x4541 = "AE" + int encrStrength = extraData.ReadByte(); // encryption strength 1 = 128 2 = 192 3 = 256 + int actualCompress = extraData.ReadShort(); // The actual compression method used to compress the file + _aesVer = ver; + _aesEncryptionStrength = encrStrength; + method = (CompressionMethod)actualCompress; + } else + throw new ZipException("AES Extra Data missing"); +#else + throw new ZipException("AES unsupported"); +#endif + } + + /// + /// Gets/Sets the entry comment. + /// + /// + /// If comment is longer than 0xffff. + /// + /// + /// The comment or null if not set. + /// + /// + /// A comment is only available for entries when read via the class. + /// The class doesnt have the comment data available. + /// + public string Comment { + get { + return comment; + } + set { + // This test is strictly incorrect as the length is in characters + // while the storage limit is in bytes. + // While the test is partially correct in that a comment of this length or greater + // is definitely invalid, shorter comments may also have an invalid length + // where there are multi-byte characters + // The full test is not possible here however as the code page to apply conversions with + // isnt available. + if ( (value != null) && (value.Length > 0xffff) ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "cannot exceed 65535"); +#endif + } + + comment = value; + } + } + + /// + /// Gets a value indicating if the entry is a directory. + /// however. + /// + /// + /// A directory is determined by an entry name with a trailing slash '/'. + /// The external file attributes can also indicate an entry is for a directory. + /// Currently only dos/windows attributes are tested in this manner. + /// The trailing slash convention should always be followed. + /// + public bool IsDirectory + { + get { + int nameLength = name.Length; + bool result = + ((nameLength > 0) && + ((name[nameLength - 1] == '/') || (name[nameLength - 1] == '\\'))) || + HasDosAttributes(16) + ; + return result; + } + } + + /// + /// Get a value of true if the entry appears to be a file; false otherwise + /// + /// + /// This only takes account of DOS/Windows attributes. Other operating systems are ignored. + /// For linux and others the result may be incorrect. + /// + public bool IsFile + { + get { + return !IsDirectory && !HasDosAttributes(8); + } + } + + /// + /// Test entry to see if data can be extracted. + /// + /// Returns true if data can be extracted for this entry; false otherwise. + public bool IsCompressionMethodSupported() + { + return IsCompressionMethodSupported(CompressionMethod); + } + + #region ICloneable Members + /// + /// Creates a copy of this zip entry. + /// + /// An that is a copy of the current instance. + public object Clone() + { + ZipEntry result = (ZipEntry)this.MemberwiseClone(); + + // Ensure extra data is unique if it exists. + if ( extra != null ) { + result.extra = new byte[extra.Length]; + Array.Copy(extra, 0, result.extra, 0, extra.Length); + } + + return result; + } + + #endregion + + /// + /// Gets a string representation of this ZipEntry. + /// + /// A readable textual representation of this + public override string ToString() + { + return name; + } + + /// + /// Test a compression method to see if this library + /// supports extracting data compressed with that method + /// + /// The compression method to test. + /// Returns true if the compression method is supported; false otherwise + public static bool IsCompressionMethodSupported(CompressionMethod method) + { + return + ( method == CompressionMethod.Deflated ) || + ( method == CompressionMethod.Stored ); + } + + /// + /// Cleans a name making it conform to Zip file conventions. + /// Devices names ('c:\') and UNC share names ('\\server\share') are removed + /// and forward slashes ('\') are converted to back slashes ('/'). + /// Names are made relative by trimming leading slashes which is compatible + /// with the ZIP naming convention. + /// + /// The name to clean + /// The 'cleaned' name. + /// + /// The Zip name transform class is more flexible. + /// + public static string CleanName(string name) + { + if (name == null) { + return string.Empty; + } + + if (Path.IsPathRooted(name) == true) { + // NOTE: + // for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt + name = name.Substring(Path.GetPathRoot(name).Length); + } + + name = name.Replace(@"\", "/"); + + while ( (name.Length > 0) && (name[0] == '/')) { + name = name.Remove(0, 1); + } + return name; + } + + #region Instance Fields + Known known; + int externalFileAttributes = -1; // contains external attributes (O/S dependant) + + ushort versionMadeBy; // Contains host system and version information + // only relevant for central header entries + + string name; + ulong size; + ulong compressedSize; + ushort versionToExtract; // Version required to extract (library handles <= 2.0) + uint crc; + uint dosTime; + + CompressionMethod method = CompressionMethod.Deflated; + byte[] extra; + string comment; + + int flags; // general purpose bit flags + + long zipFileIndex = -1; // used by ZipFile + long offset; // used by ZipFile and ZipOutputStream + + bool forceZip64_; + byte cryptoCheckValue_; +#if !NET_1_1 && !NETCF_2_0 + int _aesVer; // Version number (2 = AE-2 ?). Assigned but not used. + int _aesEncryptionStrength; // Encryption strength 1 = 128 2 = 192 3 = 256 +#endif + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipEntryFactory.cs b/类库/VersionUpdate/ZIP/Zip/ZipEntryFactory.cs new file mode 100644 index 0000000..aa02d2d --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipEntryFactory.cs @@ -0,0 +1,414 @@ +// ZipEntryFactory.cs +// +// Copyright 2006 John Reilly +// +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// Basic implementation of + /// + public class ZipEntryFactory : IEntryFactory + { + #region Enumerations + /// + /// Defines the possible values to be used for the . + /// + public enum TimeSetting + { + /// + /// Use the recorded LastWriteTime value for the file. + /// + LastWriteTime, + /// + /// Use the recorded LastWriteTimeUtc value for the file + /// + LastWriteTimeUtc, + /// + /// Use the recorded CreateTime value for the file. + /// + CreateTime, + /// + /// Use the recorded CreateTimeUtc value for the file. + /// + CreateTimeUtc, + /// + /// Use the recorded LastAccessTime value for the file. + /// + LastAccessTime, + /// + /// Use the recorded LastAccessTimeUtc value for the file. + /// + LastAccessTimeUtc, + /// + /// Use a fixed value. + /// + /// The actual value used can be + /// specified via the constructor or + /// using the with the setting set + /// to which will use the when this class was constructed. + /// The property can also be used to set this value. + Fixed, + } + #endregion + + #region Constructors + /// + /// Initialise a new instance of the class. + /// + /// A default , and the LastWriteTime for files is used. + public ZipEntryFactory() + { + nameTransform_ = new ZipNameTransform(); + } + + /// + /// Initialise a new instance of using the specified + /// + /// The time setting to use when creating Zip entries. + public ZipEntryFactory(TimeSetting timeSetting) + { + timeSetting_ = timeSetting; + nameTransform_ = new ZipNameTransform(); + } + + /// + /// Initialise a new instance of using the specified + /// + /// The time to set all values to. + public ZipEntryFactory(DateTime time) + { + timeSetting_ = TimeSetting.Fixed; + FixedDateTime = time; + nameTransform_ = new ZipNameTransform(); + } + + #endregion + + #region Properties + /// + /// Get / set the to be used when creating new values. + /// + /// + /// Setting this property to null will cause a default name transform to be used. + /// + public INameTransform NameTransform + { + get { return nameTransform_; } + set + { + if (value == null) { + nameTransform_ = new ZipNameTransform(); + } + else { + nameTransform_ = value; + } + } + } + + /// + /// Get / set the in use. + /// + public TimeSetting Setting + { + get { return timeSetting_; } + set { timeSetting_ = value; } + } + + /// + /// Get / set the value to use when is set to + /// + public DateTime FixedDateTime + { + get { return fixedDateTime_; } + set + { + if (value.Year < 1970) { + throw new ArgumentException("Value is too old to be valid", "value"); + } + fixedDateTime_ = value; + } + } + + /// + /// A bitmask defining the attributes to be retrieved from the actual file. + /// + /// The default is to get all possible attributes from the actual file. + public int GetAttributes + { + get { return getAttributes_; } + set { getAttributes_ = value; } + } + + /// + /// A bitmask defining which attributes are to be set on. + /// + /// By default no attributes are set on. + public int SetAttributes + { + get { return setAttributes_; } + set { setAttributes_ = value; } + } + + /// + /// Get set a value indicating wether unidoce text should be set on. + /// + public bool IsUnicodeText + { + get { return isUnicodeText_; } + set { isUnicodeText_ = value; } + } + + #endregion + + #region IEntryFactory Members + + /// + /// Make a new for a file. + /// + /// The name of the file to create a new entry for. + /// Returns a new based on the . + public ZipEntry MakeFileEntry(string fileName) + { + return MakeFileEntry(fileName, true); + } + + /// + /// Make a new from a name. + /// + /// The name of the file to create a new entry for. + /// If true entry detail is retrieved from the file system if the file exists. + /// Returns a new based on the . + public ZipEntry MakeFileEntry(string fileName, bool useFileSystem) + { + ZipEntry result = new ZipEntry(nameTransform_.TransformFile(fileName)); + result.IsUnicodeText = isUnicodeText_; + + int externalAttributes = 0; + bool useAttributes = (setAttributes_ != 0); + + FileInfo fi = null; + if (useFileSystem) + { + fi = new FileInfo(fileName); + } + + if ((fi != null) && fi.Exists) + { + switch (timeSetting_) + { + case TimeSetting.CreateTime: + result.DateTime = fi.CreationTime; + break; + + case TimeSetting.CreateTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.CreationTime.ToUniversalTime(); +#else + result.DateTime = fi.CreationTimeUtc; +#endif + break; + + case TimeSetting.LastAccessTime: + result.DateTime = fi.LastAccessTime; + break; + + case TimeSetting.LastAccessTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.LastAccessTime.ToUniversalTime(); +#else + result.DateTime = fi.LastAccessTimeUtc; +#endif + break; + + case TimeSetting.LastWriteTime: + result.DateTime = fi.LastWriteTime; + break; + + case TimeSetting.LastWriteTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = fi.LastWriteTime.ToUniversalTime(); +#else + result.DateTime = fi.LastWriteTimeUtc; +#endif + break; + + case TimeSetting.Fixed: + result.DateTime = fixedDateTime_; + break; + + default: + throw new ZipException("Unhandled time setting in MakeFileEntry"); + } + + result.Size = fi.Length; + + useAttributes = true; + externalAttributes = ((int)fi.Attributes & getAttributes_); + } + else + { + if (timeSetting_ == TimeSetting.Fixed) + { + result.DateTime = fixedDateTime_; + } + } + + if (useAttributes) + { + externalAttributes |= setAttributes_; + result.ExternalFileAttributes = externalAttributes; + } + + return result; + } + + /// + /// Make a new for a directory. + /// + /// The raw untransformed name for the new directory + /// Returns a new representing a directory. + public ZipEntry MakeDirectoryEntry(string directoryName) + { + return MakeDirectoryEntry(directoryName, true); + } + + /// + /// Make a new for a directory. + /// + /// The raw untransformed name for the new directory + /// If true entry detail is retrieved from the file system if the file exists. + /// Returns a new representing a directory. + public ZipEntry MakeDirectoryEntry(string directoryName, bool useFileSystem) + { + + ZipEntry result = new ZipEntry(nameTransform_.TransformDirectory(directoryName)); + result.IsUnicodeText = isUnicodeText_; + result.Size = 0; + + int externalAttributes = 0; + + DirectoryInfo di = null; + + if (useFileSystem) + { + di = new DirectoryInfo(directoryName); + } + + + if ((di != null) && di.Exists) + { + switch (timeSetting_) + { + case TimeSetting.CreateTime: + result.DateTime = di.CreationTime; + break; + + case TimeSetting.CreateTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.CreationTime.ToUniversalTime(); +#else + result.DateTime = di.CreationTimeUtc; +#endif + break; + + case TimeSetting.LastAccessTime: + result.DateTime = di.LastAccessTime; + break; + + case TimeSetting.LastAccessTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.LastAccessTime.ToUniversalTime(); +#else + result.DateTime = di.LastAccessTimeUtc; +#endif + break; + + case TimeSetting.LastWriteTime: + result.DateTime = di.LastWriteTime; + break; + + case TimeSetting.LastWriteTimeUtc: +#if NETCF_1_0 || NETCF_2_0 + result.DateTime = di.LastWriteTime.ToUniversalTime(); +#else + result.DateTime = di.LastWriteTimeUtc; +#endif + break; + + case TimeSetting.Fixed: + result.DateTime = fixedDateTime_; + break; + + default: + throw new ZipException("Unhandled time setting in MakeDirectoryEntry"); + } + + externalAttributes = ((int)di.Attributes & getAttributes_); + } + else + { + if (timeSetting_ == TimeSetting.Fixed) + { + result.DateTime = fixedDateTime_; + } + } + + // Always set directory attribute on. + externalAttributes |= (setAttributes_ | 16); + result.ExternalFileAttributes = externalAttributes; + + return result; + } + + #endregion + + #region Instance Fields + INameTransform nameTransform_; + DateTime fixedDateTime_ = DateTime.Now; + TimeSetting timeSetting_; + bool isUnicodeText_; + + int getAttributes_ = -1; + int setAttributes_; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipException.cs b/类库/VersionUpdate/ZIP/Zip/ZipException.cs new file mode 100644 index 0000000..1cf4f16 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipException.cs @@ -0,0 +1,94 @@ +// ZipException.cs +// +// Copyright (C) 2001 Mike Krueger +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; + +#if !NETCF_1_0 && !NETCF_2_0 +using System.Runtime.Serialization; +#endif + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Represents exception conditions specific to Zip archive handling + /// +#if !NETCF_1_0 && !NETCF_2_0 + [Serializable] +#endif + public class ZipException : SharpZipBaseException + { +#if !NETCF_1_0 && !NETCF_2_0 + /// + /// Deserialization constructor + /// + /// for this constructor + /// for this constructor + protected ZipException(SerializationInfo info, StreamingContext context ) + : base( info, context ) + { + } +#endif + + /// + /// Initializes a new instance of the ZipException class. + /// + public ZipException() + { + } + + /// + /// Initializes a new instance of the ZipException class with a specified error message. + /// + /// The error message that explains the reason for the exception. + public ZipException(string message) + : base(message) + { + } + + /// + /// Initialise a new instance of ZipException. + /// + /// A message describing the error. + /// The exception that is the cause of the current exception. + public ZipException(string message, Exception exception) + : base(message, exception) + { + } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipExtraData.cs b/类库/VersionUpdate/ZIP/Zip/ZipExtraData.cs new file mode 100644 index 0000000..aaeb0a6 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipExtraData.cs @@ -0,0 +1,987 @@ +// +// ZipExtraData.cs +// +// Copyright 2004-2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using System; +using System.IO; + +namespace ICSharpCode.SharpZipLib.Zip +{ + // TODO: Sort out wether tagged data is useful and what a good implementation might look like. + // Its just a sketch of an idea at the moment. + + /// + /// ExtraData tagged value interface. + /// + public interface ITaggedData + { + /// + /// Get the ID for this tagged data value. + /// + short TagID { get; } + + /// + /// Set the contents of this instance from the data passed. + /// + /// The data to extract contents from. + /// The offset to begin extracting data from. + /// The number of bytes to extract. + void SetData(byte[] data, int offset, int count); + + /// + /// Get the data representing this instance. + /// + /// Returns the data for this instance. + byte[] GetData(); + } + + /// + /// A raw binary tagged value + /// + public class RawTaggedData : ITaggedData + { + /// + /// Initialise a new instance. + /// + /// The tag ID. + public RawTaggedData(short tag) + { + _tag = tag; + } + + #region ITaggedData Members + + /// + /// Get the ID for this tagged data value. + /// + public short TagID + { + get { return _tag; } + set { _tag = value; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int offset, int count) + { + if( data==null ) + { + throw new ArgumentNullException("data"); + } + + _data=new byte[count]; + Array.Copy(data, offset, _data, 0, count); + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + return _data; + } + + #endregion + + /// + /// Get /set the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] Data + { + get { return _data; } + set { _data=value; } + } + + #region Instance Fields + /// + /// The tag ID for this instance. + /// + short _tag; + + byte[] _data; + #endregion + } + + /// + /// Class representing extended unix date time values. + /// + public class ExtendedUnixData : ITaggedData + { + /// + /// Flags indicate which values are included in this instance. + /// + [Flags] + public enum Flags : byte + { + /// + /// The modification time is included + /// + ModificationTime = 0x01, + + /// + /// The access time is included + /// + AccessTime = 0x02, + + /// + /// The create time is included. + /// + CreateTime = 0x04, + } + + #region ITaggedData Members + + /// + /// Get the ID + /// + public short TagID + { + get { return 0x5455; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int index, int count) + { + using (MemoryStream ms = new MemoryStream(data, index, count, false)) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + // bit 0 if set, modification time is present + // bit 1 if set, access time is present + // bit 2 if set, creation time is present + + _flags = (Flags)helperStream.ReadByte(); + if (((_flags & Flags.ModificationTime) != 0) && (count >= 5)) + { + int iTime = helperStream.ReadLEInt(); + + _modificationTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + + if ((_flags & Flags.AccessTime) != 0) + { + int iTime = helperStream.ReadLEInt(); + + _lastAccessTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + + if ((_flags & Flags.CreateTime) != 0) + { + int iTime = helperStream.ReadLEInt(); + + _createTime = (new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime() + + new TimeSpan(0, 0, 0, iTime, 0)).ToLocalTime(); + } + } + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + using (MemoryStream ms = new MemoryStream()) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.IsStreamOwner = false; + helperStream.WriteByte((byte)_flags); // Flags + if ( (_flags & Flags.ModificationTime) != 0) { + TimeSpan span = _modificationTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + if ( (_flags & Flags.AccessTime) != 0) { + TimeSpan span = _lastAccessTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + if ( (_flags & Flags.CreateTime) != 0) { + TimeSpan span = _createTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0).ToUniversalTime(); + int seconds = (int)span.TotalSeconds; + helperStream.WriteLEInt(seconds); + } + return ms.ToArray(); + } + } + + #endregion + + /// + /// Test a value to see if is valid and can be represented here. + /// + /// The value to test. + /// Returns true if the value is valid and can be represented; false if not. + /// The standard Unix time is a signed integer data type, directly encoding the Unix time number, + /// which is the number of seconds since 1970-01-01. + /// Being 32 bits means the values here cover a range of about 136 years. + /// The minimum representable time is 1901-12-13 20:45:52, + /// and the maximum representable time is 2038-01-19 03:14:07. + /// + public static bool IsValidValue(DateTime value) + { + return (( value >= new DateTime(1901, 12, 13, 20, 45, 52)) || + ( value <= new DateTime(2038, 1, 19, 03, 14, 07) )); + } + + /// + /// Get /set the Modification Time + /// + /// + /// + public DateTime ModificationTime + { + get { return _modificationTime; } + set + { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.ModificationTime; + _modificationTime=value; + } + } + + /// + /// Get / set the Access Time + /// + /// + /// + public DateTime AccessTime + { + get { return _lastAccessTime; } + set { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.AccessTime; + _lastAccessTime=value; + } + } + + /// + /// Get / Set the Create Time + /// + /// + /// + public DateTime CreateTime + { + get { return _createTime; } + set { + if ( !IsValidValue(value) ) { + throw new ArgumentOutOfRangeException("value"); + } + + _flags |= Flags.CreateTime; + _createTime=value; + } + } + + /// + /// Get/set the values to include. + /// + Flags Include + { + get { return _flags; } + set { _flags = value; } + } + + #region Instance Fields + Flags _flags; + DateTime _modificationTime = new DateTime(1970,1,1); + DateTime _lastAccessTime = new DateTime(1970, 1, 1); + DateTime _createTime = new DateTime(1970, 1, 1); + #endregion + } + + /// + /// Class handling NT date time values. + /// + public class NTTaggedData : ITaggedData + { + /// + /// Get the ID for this tagged data value. + /// + public short TagID + { + get { return 10; } + } + + /// + /// Set the data from the raw values provided. + /// + /// The raw data to extract values from. + /// The index to start extracting values from. + /// The number of bytes available. + public void SetData(byte[] data, int index, int count) + { + using (MemoryStream ms = new MemoryStream(data, index, count, false)) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.ReadLEInt(); // Reserved + while (helperStream.Position < helperStream.Length) + { + int ntfsTag = helperStream.ReadLEShort(); + int ntfsLength = helperStream.ReadLEShort(); + if (ntfsTag == 1) + { + if (ntfsLength >= 24) + { + long lastModificationTicks = helperStream.ReadLELong(); + _lastModificationTime = DateTime.FromFileTime(lastModificationTicks); + + long lastAccessTicks = helperStream.ReadLELong(); + _lastAccessTime = DateTime.FromFileTime(lastAccessTicks); + + long createTimeTicks = helperStream.ReadLELong(); + _createTime = DateTime.FromFileTime(createTimeTicks); + } + break; + } + else + { + // An unknown NTFS tag so simply skip it. + helperStream.Seek(ntfsLength, SeekOrigin.Current); + } + } + } + } + + /// + /// Get the binary data representing this instance. + /// + /// The raw binary data representing this instance. + public byte[] GetData() + { + using (MemoryStream ms = new MemoryStream()) + using (ZipHelperStream helperStream = new ZipHelperStream(ms)) + { + helperStream.IsStreamOwner = false; + helperStream.WriteLEInt(0); // Reserved + helperStream.WriteLEShort(1); // Tag + helperStream.WriteLEShort(24); // Length = 3 x 8. + helperStream.WriteLELong(_lastModificationTime.ToFileTime()); + helperStream.WriteLELong(_lastAccessTime.ToFileTime()); + helperStream.WriteLELong(_createTime.ToFileTime()); + return ms.ToArray(); + } + } + + /// + /// Test a valuie to see if is valid and can be represented here. + /// + /// The value to test. + /// Returns true if the value is valid and can be represented; false if not. + /// + /// NTFS filetimes are 64-bit unsigned integers, stored in Intel + /// (least significant byte first) byte order. They determine the + /// number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", + /// which is "01-Jan-1601 00:00:00 UTC". 28 May 60056 is the upper limit + /// + public static bool IsValidValue(DateTime value) + { + bool result = true; + try + { + value.ToFileTimeUtc(); + } + catch + { + result = false; + } + return result; + } + + /// + /// Get/set the last modification time. + /// + public DateTime LastModificationTime + { + get { return _lastModificationTime; } + set { + if (! IsValidValue(value)) + { + throw new ArgumentOutOfRangeException("value"); + } + _lastModificationTime = value; + } + } + + /// + /// Get /set the create time + /// + public DateTime CreateTime + { + get { return _createTime; } + set { + if ( !IsValidValue(value)) { + throw new ArgumentOutOfRangeException("value"); + } + _createTime = value; + } + } + + /// + /// Get /set the last access time. + /// + public DateTime LastAccessTime + { + get { return _lastAccessTime; } + set { + if (!IsValidValue(value)) { + throw new ArgumentOutOfRangeException("value"); + } + _lastAccessTime = value; + } + } + + #region Instance Fields + DateTime _lastAccessTime = DateTime.FromFileTime(0); + DateTime _lastModificationTime = DateTime.FromFileTime(0); + DateTime _createTime = DateTime.FromFileTime(0); + #endregion + } + + /// + /// A factory that creates tagged data instances. + /// + interface ITaggedDataFactory + { + /// + /// Get data for a specific tag value. + /// + /// The tag ID to find. + /// The data to search. + /// The offset to begin extracting data from. + /// The number of bytes to extract. + /// The located value found, or null if not found. + ITaggedData Create(short tag, byte[] data, int offset, int count); + } + + /// + /// + /// A class to handle the extra data field for Zip entries + /// + /// + /// Extra data contains 0 or more values each prefixed by a header tag and length. + /// They contain zero or more bytes of actual data. + /// The data is held internally using a copy on write strategy. This is more efficient but + /// means that for extra data created by passing in data can have the values modified by the caller + /// in some circumstances. + /// + sealed public class ZipExtraData : IDisposable + { + #region Constructors + /// + /// Initialise a default instance. + /// + public ZipExtraData() + { + Clear(); + } + + /// + /// Initialise with known extra data. + /// + /// The extra data. + public ZipExtraData(byte[] data) + { + if ( data == null ) + { + _data = new byte[0]; + } + else + { + _data = data; + } + } + #endregion + + /// + /// Get the raw extra data value + /// + /// Returns the raw byte[] extra data this instance represents. + public byte[] GetEntryData() + { + if ( Length > ushort.MaxValue ) { + throw new ZipException("Data exceeds maximum length"); + } + + return (byte[])_data.Clone(); + } + + /// + /// Clear the stored data. + /// + public void Clear() + { + if ( (_data == null) || (_data.Length != 0) ) { + _data = new byte[0]; + } + } + + /// + /// Gets the current extra data length. + /// + public int Length + { + get { return _data.Length; } + } + + /// + /// Get a read-only for the associated tag. + /// + /// The tag to locate data for. + /// Returns a containing tag data or null if no tag was found. + public Stream GetStreamForTag(int tag) + { + Stream result = null; + if ( Find(tag) ) { + result = new MemoryStream(_data, _index, _readValueLength, false); + } + return result; + } + + /// + /// Get the tagged data for a tag. + /// + /// The tag to search for. + /// Returns a tagged value or null if none found. + private ITaggedData GetData(short tag) + { + ITaggedData result = null; + if (Find(tag)) + { + result = Create(tag, _data, _readValueStart, _readValueLength); + } + return result; + } + + static ITaggedData Create(short tag, byte[] data, int offset, int count) + { + ITaggedData result = null; + switch ( tag ) + { + case 0x000A: + result = new NTTaggedData(); + break; + case 0x5455: + result = new ExtendedUnixData(); + break; + default: + result = new RawTaggedData(tag); + break; + } + result.SetData(data, offset, count); + return result; + } + + /// + /// Get the length of the last value found by + /// + /// This is only valid if has previously returned true. + public int ValueLength + { + get { return _readValueLength; } + } + + /// + /// Get the index for the current read value. + /// + /// This is only valid if has previously returned true. + /// Initially the result will be the index of the first byte of actual data. The value is updated after calls to + /// , and . + public int CurrentReadIndex + { + get { return _index; } + } + + /// + /// Get the number of bytes remaining to be read for the current value; + /// + public int UnreadCount + { + get + { + if ((_readValueStart > _data.Length) || + (_readValueStart < 4) ) { + throw new ZipException("Find must be called before calling a Read method"); + } + + return _readValueStart + _readValueLength - _index; + } + } + + /// + /// Find an extra data value + /// + /// The identifier for the value to find. + /// Returns true if the value was found; false otherwise. + public bool Find(int headerID) + { + _readValueStart = _data.Length; + _readValueLength = 0; + _index = 0; + + int localLength = _readValueStart; + int localTag = headerID - 1; + + // Trailing bytes that cant make up an entry (as there arent enough + // bytes for a tag and length) are ignored! + while ( (localTag != headerID) && (_index < _data.Length - 3) ) { + localTag = ReadShortInternal(); + localLength = ReadShortInternal(); + if ( localTag != headerID ) { + _index += localLength; + } + } + + bool result = (localTag == headerID) && ((_index + localLength) <= _data.Length); + + if ( result ) { + _readValueStart = _index; + _readValueLength = localLength; + } + + return result; + } + + /// + /// Add a new entry to extra data. + /// + /// The value to add. + public void AddEntry(ITaggedData taggedData) + { + if (taggedData == null) + { + throw new ArgumentNullException("taggedData"); + } + AddEntry(taggedData.TagID, taggedData.GetData()); + } + + /// + /// Add a new entry to extra data + /// + /// The ID for this entry. + /// The data to add. + /// If the ID already exists its contents are replaced. + public void AddEntry(int headerID, byte[] fieldData) + { + if ( (headerID > ushort.MaxValue) || (headerID < 0)) { + throw new ArgumentOutOfRangeException("headerID"); + } + + int addLength = (fieldData == null) ? 0 : fieldData.Length; + + if ( addLength > ushort.MaxValue ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("fieldData"); +#else + throw new ArgumentOutOfRangeException("fieldData", "exceeds maximum length"); +#endif + } + + // Test for new length before adjusting data. + int newLength = _data.Length + addLength + 4; + + if ( Find(headerID) ) + { + newLength -= (ValueLength + 4); + } + + if ( newLength > ushort.MaxValue ) { + throw new ZipException("Data exceeds maximum length"); + } + + Delete(headerID); + + byte[] newData = new byte[newLength]; + _data.CopyTo(newData, 0); + int index = _data.Length; + _data = newData; + SetShort(ref index, headerID); + SetShort(ref index, addLength); + if ( fieldData != null ) { + fieldData.CopyTo(newData, index); + } + } + + /// + /// Start adding a new entry. + /// + /// Add data using , , , or . + /// The new entry is completed and actually added by calling + /// + public void StartNewEntry() + { + _newEntry = new MemoryStream(); + } + + /// + /// Add entry data added since using the ID passed. + /// + /// The identifier to use for this entry. + public void AddNewEntry(int headerID) + { + byte[] newData = _newEntry.ToArray(); + _newEntry = null; + AddEntry(headerID, newData); + } + + /// + /// Add a byte of data to the pending new entry. + /// + /// The byte to add. + /// + public void AddData(byte data) + { + _newEntry.WriteByte(data); + } + + /// + /// Add data to a pending new entry. + /// + /// The data to add. + /// + public void AddData(byte[] data) + { + if ( data == null ) { + throw new ArgumentNullException("data"); + } + + _newEntry.Write(data, 0, data.Length); + } + + /// + /// Add a short value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeShort(int toAdd) + { + unchecked { + _newEntry.WriteByte(( byte )toAdd); + _newEntry.WriteByte(( byte )(toAdd >> 8)); + } + } + + /// + /// Add an integer value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeInt(int toAdd) + { + unchecked { + AddLeShort(( short )toAdd); + AddLeShort(( short )(toAdd >> 16)); + } + } + + /// + /// Add a long value in little endian order to the pending new entry. + /// + /// The data to add. + /// + public void AddLeLong(long toAdd) + { + unchecked { + AddLeInt(( int )(toAdd & 0xffffffff)); + AddLeInt(( int )(toAdd >> 32)); + } + } + + /// + /// Delete an extra data field. + /// + /// The identifier of the field to delete. + /// Returns true if the field was found and deleted. + public bool Delete(int headerID) + { + bool result = false; + + if ( Find(headerID) ) { + result = true; + int trueStart = _readValueStart - 4; + + byte[] newData = new byte[_data.Length - (ValueLength + 4)]; + Array.Copy(_data, 0, newData, 0, trueStart); + + int trueEnd = trueStart + ValueLength + 4; + Array.Copy(_data, trueEnd, newData, trueStart, _data.Length - trueEnd); + _data = newData; + } + return result; + } + + #region Reading Support + /// + /// Read a long in little endian form from the last found data value + /// + /// Returns the long value read. + public long ReadLong() + { + ReadCheck(8); + return (ReadInt() & 0xffffffff) | ((( long )ReadInt()) << 32); + } + + /// + /// Read an integer in little endian form from the last found data value. + /// + /// Returns the integer read. + public int ReadInt() + { + ReadCheck(4); + + int result = _data[_index] + (_data[_index + 1] << 8) + + (_data[_index + 2] << 16) + (_data[_index + 3] << 24); + _index += 4; + return result; + } + + /// + /// Read a short value in little endian form from the last found data value. + /// + /// Returns the short value read. + public int ReadShort() + { + ReadCheck(2); + int result = _data[_index] + (_data[_index + 1] << 8); + _index += 2; + return result; + } + + /// + /// Read a byte from an extra data + /// + /// The byte value read or -1 if the end of data has been reached. + public int ReadByte() + { + int result = -1; + if ( (_index < _data.Length) && (_readValueStart + _readValueLength > _index) ) { + result = _data[_index]; + _index += 1; + } + return result; + } + + /// + /// Skip data during reading. + /// + /// The number of bytes to skip. + public void Skip(int amount) + { + ReadCheck(amount); + _index += amount; + } + + void ReadCheck(int length) + { + if ((_readValueStart > _data.Length) || + (_readValueStart < 4) ) { + throw new ZipException("Find must be called before calling a Read method"); + } + + if (_index > _readValueStart + _readValueLength - length ) { + throw new ZipException("End of extra data"); + } + + if ( _index + length < 4 ) { + throw new ZipException("Cannot read before start of tag"); + } + } + + /// + /// Internal form of that reads data at any location. + /// + /// Returns the short value read. + int ReadShortInternal() + { + if ( _index > _data.Length - 2) { + throw new ZipException("End of extra data"); + } + + int result = _data[_index] + (_data[_index + 1] << 8); + _index += 2; + return result; + } + + void SetShort(ref int index, int source) + { + _data[index] = (byte)source; + _data[index + 1] = (byte)(source >> 8); + index += 2; + } + + #endregion + + #region IDisposable Members + + /// + /// Dispose of this instance. + /// + public void Dispose() + { + if ( _newEntry != null ) { + _newEntry.Close(); + } + } + + #endregion + + #region Instance Fields + int _index; + int _readValueStart; + int _readValueLength; + + MemoryStream _newEntry; + byte[] _data; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipFile.cs b/类库/VersionUpdate/ZIP/Zip/ZipFile.cs new file mode 100644 index 0000000..7be203c --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipFile.cs @@ -0,0 +1,4487 @@ +// ZipFile.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2009-12-22 Z-1649 Added AES support +// 2010-03-02 Z-1650 Fixed updating ODT archives in memory. Exposed exceptions in updating. +// 2010-05-25 Z-1663 Fixed exception when testing local header compressed size of -1 + +using System; +using System.Collections; +using System.IO; +using System.Text; +using System.Globalization; + +#if !NETCF_1_0 +using System.Security.Cryptography; +using ICSharpCode.SharpZipLib.Encryption; +#endif + +using ICSharpCode.SharpZipLib.Core; +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + #region Keys Required Event Args + /// + /// Arguments used with KeysRequiredEvent + /// + public class KeysRequiredEventArgs : EventArgs + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The name of the file for which keys are required. + public KeysRequiredEventArgs(string name) + { + fileName = name; + } + + /// + /// Initialise a new instance of + /// + /// The name of the file for which keys are required. + /// The current key value. + public KeysRequiredEventArgs(string name, byte[] keyValue) + { + fileName = name; + key = keyValue; + } + + #endregion + #region Properties + /// + /// Gets the name of the file for which keys are required. + /// + public string FileName + { + get { return fileName; } + } + + /// + /// Gets or sets the key value + /// + public byte[] Key + { + get { return key; } + set { key = value; } + } + #endregion + + #region Instance Fields + string fileName; + byte[] key; + #endregion + } + #endregion + + #region Test Definitions + /// + /// The strategy to apply to testing. + /// + public enum TestStrategy + { + /// + /// Find the first error only. + /// + FindFirstError, + /// + /// Find all possible errors. + /// + FindAllErrors, + } + + /// + /// The operation in progress reported by a during testing. + /// + /// TestArchive + public enum TestOperation + { + /// + /// Setting up testing. + /// + Initialising, + + /// + /// Testing an individual entries header + /// + EntryHeader, + + /// + /// Testing an individual entries data + /// + EntryData, + + /// + /// Testing an individual entry has completed. + /// + EntryComplete, + + /// + /// Running miscellaneous tests + /// + MiscellaneousTests, + + /// + /// Testing is complete + /// + Complete, + } + + /// + /// Status returned returned by during testing. + /// + /// TestArchive + public class TestStatus + { + #region Constructors + /// + /// Initialise a new instance of + /// + /// The this status applies to. + public TestStatus(ZipFile file) + { + file_ = file; + } + #endregion + + #region Properties + + /// + /// Get the current in progress. + /// + public TestOperation Operation + { + get { return operation_; } + } + + /// + /// Get the this status is applicable to. + /// + public ZipFile File + { + get { return file_; } + } + + /// + /// Get the current/last entry tested. + /// + public ZipEntry Entry + { + get { return entry_; } + } + + /// + /// Get the number of errors detected so far. + /// + public int ErrorCount + { + get { return errorCount_; } + } + + /// + /// Get the number of bytes tested so far for the current entry. + /// + public long BytesTested + { + get { return bytesTested_; } + } + + /// + /// Get a value indicating wether the last entry test was valid. + /// + public bool EntryValid + { + get { return entryValid_; } + } + #endregion + + #region Internal API + internal void AddError() + { + errorCount_++; + entryValid_ = false; + } + + internal void SetOperation(TestOperation operation) + { + operation_ = operation; + } + + internal void SetEntry(ZipEntry entry) + { + entry_ = entry; + entryValid_ = true; + bytesTested_ = 0; + } + + internal void SetBytesTested(long value) + { + bytesTested_ = value; + } + #endregion + + #region Instance Fields + ZipFile file_; + ZipEntry entry_; + bool entryValid_; + int errorCount_; + long bytesTested_; + TestOperation operation_; + #endregion + } + + /// + /// Delegate invoked during testing if supplied indicating current progress and status. + /// + /// If the message is non-null an error has occured. If the message is null + /// the operation as found in status has started. + public delegate void ZipTestResultHandler(TestStatus status, string message); + #endregion + + #region Update Definitions + /// + /// The possible ways of applying updates to an archive. + /// + public enum FileUpdateMode + { + /// + /// Perform all updates on temporary files ensuring that the original file is saved. + /// + Safe, + /// + /// Update the archive directly, which is faster but less safe. + /// + Direct, + } + #endregion + + #region ZipFile Class + /// + /// This class represents a Zip archive. You can ask for the contained + /// entries, or get an input stream for a file entry. The entry is + /// automatically decompressed. + /// + /// You can also update the archive adding or deleting entries. + /// + /// This class is thread safe for input: You can open input streams for arbitrary + /// entries in different threads. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// + /// + /// using System; + /// using System.Text; + /// using System.Collections; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// static public void Main(string[] args) + /// { + /// using (ZipFile zFile = new ZipFile(args[0])) { + /// Console.WriteLine("Listing of : " + zFile.Name); + /// Console.WriteLine(""); + /// Console.WriteLine("Raw Size Size Date Time Name"); + /// Console.WriteLine("-------- -------- -------- ------ ---------"); + /// foreach (ZipEntry e in zFile) { + /// if ( e.IsFile ) { + /// DateTime d = e.DateTime; + /// Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize, + /// d.ToString("dd-MM-yy"), d.ToString("HH:mm"), + /// e.Name); + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipFile : IEnumerable, IDisposable + { + #region KeyHandling + + /// + /// Delegate for handling keys/password setting during compresion/decompression. + /// + public delegate void KeysRequiredEventHandler( + object sender, + KeysRequiredEventArgs e + ); + + /// + /// Event handler for handling encryption keys. + /// + public KeysRequiredEventHandler KeysRequired; + + /// + /// Handles getting of encryption keys when required. + /// + /// The file for which encryption keys are required. + void OnKeysRequired(string fileName) + { + if (KeysRequired != null) { + KeysRequiredEventArgs krea = new KeysRequiredEventArgs(fileName, key); + KeysRequired(this, krea); + key = krea.Key; + } + } + + /// + /// Get/set the encryption key value. + /// + byte[] Key + { + get { return key; } + set { key = value; } + } + +#if !NETCF_1_0 + /// + /// Password to be used for encrypting/decrypting files. + /// + /// Set to null if no password is required. + public string Password + { + set + { + if ( (value == null) || (value.Length == 0) ) { + key = null; + } + else { + rawPassword_ = value; + key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(value)); + } + } + } +#endif + + /// + /// Get a value indicating wether encryption keys are currently available. + /// + bool HaveKeys + { + get { return key != null; } + } + #endregion + + #region Constructors + /// + /// Opens a Zip file with the given name for reading. + /// + /// The name of the file to open. + /// The argument supplied is null. + /// + /// An i/o error occurs + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(string name) + { + if ( name == null ) { + throw new ArgumentNullException("name"); + } + + name_ = name; + + baseStream_ = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read); + isStreamOwner = true; + + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } + + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// The supplied argument is null. + /// + /// An i/o error occurs. + /// + /// + /// The file doesn't contain a valid zip archive. + /// + public ZipFile(FileStream file) + { + if ( file == null ) { + throw new ArgumentNullException("file"); + } + + if ( !file.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "file"); + } + + baseStream_ = file; + name_ = file.Name; + isStreamOwner = true; + + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } + + /// + /// Opens a Zip file reading the given . + /// + /// The to read archive data from. + /// + /// An i/o error occurs + /// + /// + /// The stream doesn't contain a valid zip archive.
+ ///
+ /// + /// The stream doesnt support seeking. + /// + /// + /// The stream argument is null. + /// + public ZipFile(Stream stream) + { + if ( stream == null ) { + throw new ArgumentNullException("stream"); + } + + if ( !stream.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "stream"); + } + + baseStream_ = stream; + isStreamOwner = true; + + if ( baseStream_.Length > 0 ) { + try { + ReadEntries(); + } + catch { + DisposeInternal(true); + throw; + } + } else { + entries_ = new ZipEntry[0]; + isNewArchive_ = true; + } + } + + /// + /// Initialises a default instance with no entries and no file storage. + /// + internal ZipFile() + { + entries_ = new ZipEntry[0]; + isNewArchive_ = true; + } + + #endregion + + #region Destructors and Closing + /// + /// Finalize this instance. + /// + ~ZipFile() + { + Dispose(false); + } + + /// + /// Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. + /// Once closed, no further instance methods should be called. + /// + /// + /// An i/o error occurs. + /// + public void Close() + { + DisposeInternal(true); + GC.SuppressFinalize(this); + } + + #endregion + + #region Creators + /// + /// Create a new whose data will be stored in a file. + /// + /// The name of the archive to create. + /// Returns the newly created + /// is null + public static ZipFile Create(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + FileStream fs = File.Create(fileName); + + ZipFile result = new ZipFile(); + result.name_ = fileName; + result.baseStream_ = fs; + result.isStreamOwner = true; + return result; + } + + /// + /// Create a new whose data will be stored on a stream. + /// + /// The stream providing data storage. + /// Returns the newly created + /// is null + /// doesnt support writing. + public static ZipFile Create(Stream outStream) + { + if ( outStream == null ) { + throw new ArgumentNullException("outStream"); + } + + if ( !outStream.CanWrite ) { + throw new ArgumentException("Stream is not writeable", "outStream"); + } + + if ( !outStream.CanSeek ) { + throw new ArgumentException("Stream is not seekable", "outStream"); + } + + ZipFile result = new ZipFile(); + result.baseStream_ = outStream; + return result; + } + + #endregion + + #region Properties + /// + /// Get/set a flag indicating if the underlying stream is owned by the ZipFile instance. + /// If the flag is true then the stream will be closed when Close is called. + /// + /// + /// The default value is true in all cases. + /// + public bool IsStreamOwner + { + get { return isStreamOwner; } + set { isStreamOwner = value; } + } + + /// + /// Get a value indicating wether + /// this archive is embedded in another file or not. + /// + public bool IsEmbeddedArchive + { + // Not strictly correct in all circumstances currently + get { return offsetOfFirstEntry > 0; } + } + + /// + /// Get a value indicating that this archive is a new one. + /// + public bool IsNewArchive + { + get { return isNewArchive_; } + } + + /// + /// Gets the comment for the zip file. + /// + public string ZipFileComment + { + get { return comment_; } + } + + /// + /// Gets the name of this zip file. + /// + public string Name + { + get { return name_; } + } + + /// + /// Gets the number of entries in this zip file. + /// + /// + /// The Zip file has been closed. + /// + [Obsolete("Use the Count property instead")] + public int Size + { + get + { + return entries_.Length; + } + } + + /// + /// Get the number of entries contained in this . + /// + public long Count + { + get + { + return entries_.Length; + } + } + + /// + /// Indexer property for ZipEntries + /// + [System.Runtime.CompilerServices.IndexerNameAttribute("EntryByIndex")] + public ZipEntry this[int index] + { + get { + return (ZipEntry) entries_[index].Clone(); + } + } + + #endregion + + #region Input Handling + /// + /// Gets an enumerator for the Zip entries in this Zip file. + /// + /// Returns an for this archive. + /// + /// The Zip file has been closed. + /// + public IEnumerator GetEnumerator() + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + return new ZipEntryEnumerator(entries_); + } + + /// + /// Return the index of the entry with a matching name + /// + /// Entry name to find + /// If true the comparison is case insensitive + /// The index position of the matching entry or -1 if not found + /// + /// The Zip file has been closed. + /// + public int FindEntry(string name, bool ignoreCase) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + // TODO: This will be slow as the next ice age for huge archives! + for (int i = 0; i < entries_.Length; i++) { + if (string.Compare(name, entries_[i].Name, ignoreCase, CultureInfo.InvariantCulture) == 0) { + return i; + } + } + return -1; + } + + /// + /// Searches for a zip entry in this archive with the given name. + /// String comparisons are case insensitive + /// + /// + /// The name to find. May contain directory components separated by slashes ('/'). + /// + /// + /// A clone of the zip entry, or null if no entry with that name exists. + /// + /// + /// The Zip file has been closed. + /// + public ZipEntry GetEntry(string name) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + int index = FindEntry(name, true); + return (index >= 0) ? (ZipEntry) entries_[index].Clone() : null; + } + + /// + /// Gets an input stream for reading the given zip entry data in an uncompressed form. + /// Normally the should be an entry returned by GetEntry(). + /// + /// The to obtain a data for + /// An input containing data for this + /// + /// The ZipFile has already been closed + /// + /// + /// The compression method for the entry is unknown + /// + /// + /// The entry is not found in the ZipFile + /// + public Stream GetInputStream(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + long index = entry.ZipFileIndex; + if ( (index < 0) || (index >= entries_.Length) || (entries_[index].Name != entry.Name) ) { + index = FindEntry(entry.Name, true); + if (index < 0) { + throw new ZipException("Entry cannot be found"); + } + } + return GetInputStream(index); + } + + /// + /// Creates an input stream reading a zip entry + /// + /// The index of the entry to obtain an input stream for. + /// + /// An input containing data for this + /// + /// + /// The ZipFile has already been closed + /// + /// + /// The compression method for the entry is unknown + /// + /// + /// The entry is not found in the ZipFile + /// + public Stream GetInputStream(long entryIndex) + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + long start = LocateEntry(entries_[entryIndex]); + CompressionMethod method = entries_[entryIndex].CompressionMethod; + Stream result = new PartialInputStream(this, start, entries_[entryIndex].CompressedSize); + + if (entries_[entryIndex].IsCrypted == true) { +#if NETCF_1_0 + throw new ZipException("decryption not supported for Compact Framework 1.0"); +#else + result = CreateAndInitDecryptionStream(result, entries_[entryIndex]); + if (result == null) { + throw new ZipException("Unable to decrypt this entry"); + } +#endif + } + + switch (method) { + case CompressionMethod.Stored: + // read as is. + break; + + case CompressionMethod.Deflated: + // No need to worry about ownership and closing as underlying stream close does nothing. + result = new InflaterInputStream(result, new Inflater(true)); + break; + + default: + throw new ZipException("Unsupported compression method " + method); + } + + return result; + } + + #endregion + + #region Archive Testing + /// + /// Test an archive for integrity/validity + /// + /// Perform low level data Crc check + /// true if all tests pass, false otherwise + /// Testing will terminate on the first error found. + public bool TestArchive(bool testData) + { + return TestArchive(testData, TestStrategy.FindFirstError, null); + } + + /// + /// Test an archive for integrity/validity + /// + /// Perform low level data Crc check + /// The to apply. + /// The handler to call during testing. + /// true if all tests pass, false otherwise + /// The object has already been closed. + public bool TestArchive(bool testData, TestStrategy strategy, ZipTestResultHandler resultHandler) + { + if (isDisposed_) { + throw new ObjectDisposedException("ZipFile"); + } + + TestStatus status = new TestStatus(this); + + if ( resultHandler != null ) { + resultHandler(status, null); + } + + HeaderTest test = testData ? (HeaderTest.Header | HeaderTest.Extract) : HeaderTest.Header; + + bool testing = true; + + try { + int entryIndex = 0; + + while ( testing && (entryIndex < Count) ) { + if ( resultHandler != null ) { + status.SetEntry(this[entryIndex]); + status.SetOperation(TestOperation.EntryHeader); + resultHandler(status, null); + } + + try { + TestLocalHeader(this[entryIndex], test); + } + catch(ZipException ex) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, + string.Format("Exception during test - '{0}'", ex.Message)); + } + + if ( strategy == TestStrategy.FindFirstError ) { + testing = false; + } + } + + if ( testing && testData && this[entryIndex].IsFile ) { + if ( resultHandler != null ) { + status.SetOperation(TestOperation.EntryData); + resultHandler(status, null); + } + + Crc32 crc = new Crc32(); + + using (Stream entryStream = this.GetInputStream(this[entryIndex])) + { + + byte[] buffer = new byte[4096]; + long totalBytes = 0; + int bytesRead; + while ((bytesRead = entryStream.Read(buffer, 0, buffer.Length)) > 0) + { + crc.Update(buffer, 0, bytesRead); + + if (resultHandler != null) + { + totalBytes += bytesRead; + status.SetBytesTested(totalBytes); + resultHandler(status, null); + } + } + } + + if (this[entryIndex].Crc != crc.Value) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, "CRC mismatch"); + } + + if ( strategy == TestStrategy.FindFirstError ) { + testing = false; + } + } + + if (( this[entryIndex].Flags & (int)GeneralBitFlags.Descriptor) != 0 ) { + ZipHelperStream helper = new ZipHelperStream(baseStream_); + DescriptorData data = new DescriptorData(); + helper.ReadDataDescriptor(this[entryIndex].LocalHeaderRequiresZip64, data); + if (this[entryIndex].Crc != data.Crc) { + status.AddError(); + } + + if (this[entryIndex].CompressedSize != data.CompressedSize) { + status.AddError(); + } + + if (this[entryIndex].Size != data.Size) { + status.AddError(); + } + } + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.EntryComplete); + resultHandler(status, null); + } + + entryIndex += 1; + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.MiscellaneousTests); + resultHandler(status, null); + } + + // TODO: the 'Corrina Johns' test where local headers are missing from + // the central directory. They are therefore invisible to many archivers. + } + catch (Exception ex) { + status.AddError(); + + if ( resultHandler != null ) { + resultHandler(status, string.Format("Exception during test - '{0}'", ex.Message)); + } + } + + if ( resultHandler != null ) { + status.SetOperation(TestOperation.Complete); + status.SetEntry(null); + resultHandler(status, null); + } + + return (status.ErrorCount == 0); + } + + [Flags] + enum HeaderTest + { + Extract = 0x01, // Check that this header represents an entry whose data can be extracted + Header = 0x02, // Check that this header contents are valid + } + + /// + /// Test a local header against that provided from the central directory + /// + /// + /// The entry to test against + /// + /// The type of tests to carry out. + /// The offset of the entries data in the file + long TestLocalHeader(ZipEntry entry, HeaderTest tests) + { + lock(baseStream_) + { + bool testHeader = (tests & HeaderTest.Header) != 0; + bool testData = (tests & HeaderTest.Extract) != 0; + + baseStream_.Seek(offsetOfFirstEntry + entry.Offset, SeekOrigin.Begin); + if ((int)ReadLEUint() != ZipConstants.LocalHeaderSignature) { + throw new ZipException(string.Format("Wrong local header signature @{0:X}", offsetOfFirstEntry + entry.Offset)); + } + + short extractVersion = ( short )ReadLEUshort(); + short localFlags = ( short )ReadLEUshort(); + short compressionMethod = ( short )ReadLEUshort(); + short fileTime = ( short )ReadLEUshort(); + short fileDate = ( short )ReadLEUshort(); + uint crcValue = ReadLEUint(); + long compressedSize = ReadLEUint(); + long size = ReadLEUint(); + int storedNameLength = ReadLEUshort(); + int extraDataLength = ReadLEUshort(); + + byte[] nameData = new byte[storedNameLength]; + StreamUtils.ReadFully(baseStream_, nameData); + + byte[] extraData = new byte[extraDataLength]; + StreamUtils.ReadFully(baseStream_, extraData); + + ZipExtraData localExtraData = new ZipExtraData(extraData); + + // Extra data / zip64 checks + if (localExtraData.Find(1)) + { + // 2010-03-04 Forum 10512: removed checks for version >= ZipConstants.VersionZip64 + // and size or compressedSize = MaxValue, due to rogue creators. + + size = localExtraData.ReadLong(); + compressedSize = localExtraData.ReadLong(); + + if ((localFlags & (int)GeneralBitFlags.Descriptor) != 0) + { + // These may be valid if patched later + if ( (size != -1) && (size != entry.Size)) { + throw new ZipException("Size invalid for descriptor"); + } + + if ((compressedSize != -1) && (compressedSize != entry.CompressedSize)) { + throw new ZipException("Compressed size invalid for descriptor"); + } + } + } + else + { + // No zip64 extra data but entry requires it. + if ((extractVersion >= ZipConstants.VersionZip64) && + (((uint)size == uint.MaxValue) || ((uint)compressedSize == uint.MaxValue))) + { + throw new ZipException("Required Zip64 extended information missing"); + } + } + + if ( testData ) { + if ( entry.IsFile ) { + if ( !entry.IsCompressionMethodSupported() ) { + throw new ZipException("Compression method not supported"); + } + + if ( (extractVersion > ZipConstants.VersionMadeBy) + || ((extractVersion > 20) && (extractVersion < ZipConstants.VersionZip64)) ) { + throw new ZipException(string.Format("Version required to extract this entry not supported ({0})", extractVersion)); + } + + if ( (localFlags & ( int )(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0 ) { + throw new ZipException("The library does not support the zip version required to extract this entry"); + } + } + } + + if (testHeader) + { + if ((extractVersion <= 63) && // Ignore later versions as we dont know about them.. + (extractVersion != 10) && + (extractVersion != 11) && + (extractVersion != 20) && + (extractVersion != 21) && + (extractVersion != 25) && + (extractVersion != 27) && + (extractVersion != 45) && + (extractVersion != 46) && + (extractVersion != 50) && + (extractVersion != 51) && + (extractVersion != 52) && + (extractVersion != 61) && + (extractVersion != 62) && + (extractVersion != 63) + ) + { + throw new ZipException(string.Format("Version required to extract this entry is invalid ({0})", extractVersion)); + } + + // Local entry flags dont have reserved bit set on. + if ((localFlags & (int)(GeneralBitFlags.ReservedPKware4 | GeneralBitFlags.ReservedPkware14 | GeneralBitFlags.ReservedPkware15)) != 0) + { + throw new ZipException("Reserved bit flags cannot be set."); + } + + // Encryption requires extract version >= 20 + if (((localFlags & (int)GeneralBitFlags.Encrypted) != 0) && (extractVersion < 20)) + { + throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion)); + } + + // Strong encryption requires encryption flag to be set and extract version >= 50. + if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0) + { + if ((localFlags & (int)GeneralBitFlags.Encrypted) == 0) + { + throw new ZipException("Strong encryption flag set but encryption flag is not set"); + } + + if (extractVersion < 50) + { + throw new ZipException(string.Format("Version required to extract this entry is too low for encryption ({0})", extractVersion)); + } + } + + // Patched entries require extract version >= 27 + if (((localFlags & (int)GeneralBitFlags.Patched) != 0) && (extractVersion < 27)) + { + throw new ZipException(string.Format("Patched data requires higher version than ({0})", extractVersion)); + } + + // Central header flags match local entry flags. + if (localFlags != entry.Flags) + { + throw new ZipException("Central header/local header flags mismatch"); + } + + // Central header compression method matches local entry + if (entry.CompressionMethod != (CompressionMethod)compressionMethod) + { + throw new ZipException("Central header/local header compression method mismatch"); + } + + if (entry.Version != extractVersion) + { + throw new ZipException("Extract version mismatch"); + } + + // Strong encryption and extract version match + if ((localFlags & (int)GeneralBitFlags.StrongEncryption) != 0) + { + if (extractVersion < 62) + { + throw new ZipException("Strong encryption flag set but version not high enough"); + } + } + + if ((localFlags & (int)GeneralBitFlags.HeaderMasked) != 0) + { + if ((fileTime != 0) || (fileDate != 0)) + { + throw new ZipException("Header masked set but date/time values non-zero"); + } + } + + if ((localFlags & (int)GeneralBitFlags.Descriptor) == 0) + { + if (crcValue != (uint)entry.Crc) + { + throw new ZipException("Central header/local header crc mismatch"); + } + } + + // Crc valid for empty entry. + // This will also apply to streamed entries where size isnt known and the header cant be patched + if ((size == 0) && (compressedSize == 0)) + { + if (crcValue != 0) + { + throw new ZipException("Invalid CRC for empty entry"); + } + } + + // TODO: make test more correct... can't compare lengths as was done originally as this can fail for MBCS strings + // Assuming a code page at this point is not valid? Best is to store the name length in the ZipEntry probably + if (entry.Name.Length > storedNameLength) + { + throw new ZipException("File name length mismatch"); + } + + // Name data has already been read convert it and compare. + string localName = ZipConstants.ConvertToStringExt(localFlags, nameData); + + // Central directory and local entry name match + if (localName != entry.Name) + { + throw new ZipException("Central header and local header file name mismatch"); + } + + // Directories have zero actual size but can have compressed size + if (entry.IsDirectory) + { + if (size > 0) + { + throw new ZipException("Directory cannot have size"); + } + + // There may be other cases where the compressed size can be greater than this? + // If so until details are known we will be strict. + if (entry.IsCrypted) + { + if (compressedSize > ZipConstants.CryptoHeaderSize + 2) + { + throw new ZipException("Directory compressed size invalid"); + } + } + else if (compressedSize > 2) + { + // When not compressed the directory size can validly be 2 bytes + // if the true size wasnt known when data was originally being written. + // NOTE: Versions of the library 0.85.4 and earlier always added 2 bytes + throw new ZipException("Directory compressed size invalid"); + } + } + + if (!ZipNameTransform.IsValidName(localName, true)) + { + throw new ZipException("Name is invalid"); + } + } + + // Tests that apply to both data and header. + + // Size can be verified only if it is known in the local header. + // it will always be known in the central header. + if (((localFlags & (int)GeneralBitFlags.Descriptor) == 0) || + ((size > 0) || (compressedSize > 0))) { + + if (size != entry.Size) { + throw new ZipException( + string.Format("Size mismatch between central header({0}) and local header({1})", + entry.Size, size)); + } + + if (compressedSize != entry.CompressedSize && + compressedSize != 0xFFFFFFFF && compressedSize != -1) { + throw new ZipException( + string.Format("Compressed size mismatch between central header({0}) and local header({1})", + entry.CompressedSize, compressedSize)); + } + } + + int extraLength = storedNameLength + extraDataLength; + return offsetOfFirstEntry + entry.Offset + ZipConstants.LocalHeaderBaseSize + extraLength; + } + } + + #endregion + + #region Updating + + const int DefaultBufferSize = 4096; + + /// + /// The kind of update to apply. + /// + enum UpdateCommand + { + Copy, // Copy original file contents. + Modify, // Change encryption, compression, attributes, name, time etc, of an existing file. + Add, // Add a new file to the archive. + } + + #region Properties + /// + /// Get / set the to apply to names when updating. + /// + public INameTransform NameTransform + { + get { + return updateEntryFactory_.NameTransform; + } + + set { + updateEntryFactory_.NameTransform = value; + } + } + + /// + /// Get/set the used to generate values + /// during updates. + /// + public IEntryFactory EntryFactory + { + get { + return updateEntryFactory_; + } + + set { + if (value == null) { + updateEntryFactory_ = new ZipEntryFactory(); + } + else { + updateEntryFactory_ = value; + } + } + } + + /// + /// Get /set the buffer size to be used when updating this zip file. + /// + public int BufferSize + { + get { return bufferSize_; } + set { + if ( value < 1024 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("value"); +#else + throw new ArgumentOutOfRangeException("value", "cannot be below 1024"); +#endif + } + + if ( bufferSize_ != value ) { + bufferSize_ = value; + copyBuffer_ = null; + } + } + } + + /// + /// Get a value indicating an update has been started. + /// + public bool IsUpdating + { + get { return updates_ != null; } + } + + /// + /// Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + /// + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + #endregion + + #region Immediate updating +// TBD: Direct form of updating +// +// public void Update(IEntryMatcher deleteMatcher) +// { +// } +// +// public void Update(IScanner addScanner) +// { +// } + #endregion + + #region Deferred Updating + /// + /// Begin updating this archive. + /// + /// The archive storage for use during the update. + /// The data source to utilise during updating. + /// ZipFile has been closed. + /// One of the arguments provided is null + /// ZipFile has been closed. + public void BeginUpdate(IArchiveStorage archiveStorage, IDynamicDataSource dataSource) + { + if ( archiveStorage == null ) { + throw new ArgumentNullException("archiveStorage"); + } + + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + if ( IsEmbeddedArchive ) { + throw new ZipException ("Cannot update embedded/SFX archives"); + } + + archiveStorage_ = archiveStorage; + updateDataSource_ = dataSource; + + // NOTE: the baseStream_ may not currently support writing or seeking. + + updateIndex_ = new Hashtable(); + + updates_ = new ArrayList(entries_.Length); + foreach(ZipEntry entry in entries_) { + int index = updates_.Add(new ZipUpdate(entry)); + updateIndex_.Add(entry.Name, index); + } + + // We must sort by offset before using offset's calculated sizes + updates_.Sort(new UpdateComparer()); + + int idx = 0; + foreach (ZipUpdate update in updates_) { + //If last entry, there is no next entry offset to use + if (idx == updates_.Count - 1) + break; + + update.OffsetBasedSize = ((ZipUpdate)updates_[idx + 1]).Entry.Offset - update.Entry.Offset; + idx++; + } + updateCount_ = updates_.Count; + + contentsEdited_ = false; + commentEdited_ = false; + newComment_ = null; + } + + /// + /// Begin updating to this archive. + /// + /// The storage to use during the update. + public void BeginUpdate(IArchiveStorage archiveStorage) + { + BeginUpdate(archiveStorage, new DynamicDiskDataSource()); + } + + /// + /// Begin updating this archive. + /// + /// + /// + /// + public void BeginUpdate() + { + if ( Name == null ) { + BeginUpdate(new MemoryArchiveStorage(), new DynamicDiskDataSource()); + } + else { + BeginUpdate(new DiskArchiveStorage(this), new DynamicDiskDataSource()); + } + } + + /// + /// Commit current updates, updating this archive. + /// + /// + /// + /// ZipFile has been closed. + public void CommitUpdate() + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + CheckUpdating(); + + try { + updateIndex_.Clear(); + updateIndex_=null; + + if( contentsEdited_ ) { + RunUpdates(); + } + else if( commentEdited_ ) { + UpdateCommentOnly(); + } + else { + // Create an empty archive if none existed originally. + if( entries_.Length==0 ) { + byte[] theComment=(newComment_!=null)?newComment_.RawComment:ZipConstants.ConvertToArray(comment_); + using( ZipHelperStream zhs=new ZipHelperStream(baseStream_) ) { + zhs.WriteEndOfCentralDirectory(0, 0, 0, theComment); + } + } + } + + } + finally { + PostUpdateCleanup(); + } + } + + /// + /// Abort updating leaving the archive unchanged. + /// + /// + /// + public void AbortUpdate() + { + PostUpdateCleanup(); + } + + /// + /// Set the file comment to be recorded when the current update is commited. + /// + /// The comment to record. + /// ZipFile has been closed. + public void SetComment(string comment) + { + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + CheckUpdating(); + + newComment_ = new ZipString(comment); + + if ( newComment_.RawLength > 0xffff ) { + newComment_ = null; + throw new ZipException("Comment length exceeds maximum - 65535"); + } + + // We dont take account of the original and current comment appearing to be the same + // as encoding may be different. + commentEdited_ = true; + } + + #endregion + + #region Adding Entries + + void AddUpdate(ZipUpdate update) + { + contentsEdited_ = true; + + int index = FindExistingUpdate(update.Entry.Name); + + if (index >= 0) { + if ( updates_[index] == null ) { + updateCount_ += 1; + } + + // Direct replacement is faster than delete and add. + updates_[index] = update; + } + else { + index = updates_.Add(update); + updateCount_ += 1; + updateIndex_.Add(update.Entry.Name, index); + } + } + + /// + /// Add a new entry to the archive. + /// + /// The name of the file to add. + /// The compression method to use. + /// Ensure Unicode text is used for name and comment for this entry. + /// Argument supplied is null. + /// ZipFile has been closed. + /// Compression method is not supported. + public void Add(string fileName, CompressionMethod compressionMethod, bool useUnicodeText ) + { + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + + if ( isDisposed_ ) { + throw new ObjectDisposedException("ZipFile"); + } + + if (!ZipEntry.IsCompressionMethodSupported(compressionMethod)) { + throw new ArgumentOutOfRangeException("compressionMethod"); + } + + CheckUpdating(); + contentsEdited_ = true; + + ZipEntry entry = EntryFactory.MakeFileEntry(fileName); + entry.IsUnicodeText = useUnicodeText; + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(fileName, entry)); + } + + /// + /// Add a new entry to the archive. + /// + /// The name of the file to add. + /// The compression method to use. + /// ZipFile has been closed. + /// The compression method is not supported. + public void Add(string fileName, CompressionMethod compressionMethod) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + if ( !ZipEntry.IsCompressionMethodSupported(compressionMethod) ) { + throw new ArgumentOutOfRangeException("compressionMethod"); + } + + CheckUpdating(); + contentsEdited_ = true; + + ZipEntry entry = EntryFactory.MakeFileEntry(fileName); + entry.CompressionMethod = compressionMethod; + AddUpdate(new ZipUpdate(fileName, entry)); + } + + /// + /// Add a file to the archive. + /// + /// The name of the file to add. + /// Argument supplied is null. + public void Add(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(fileName, EntryFactory.MakeFileEntry(fileName))); + } + + /// + /// Add a file to the archive. + /// + /// The name of the file to add. + /// The name to use for the on the Zip file created. + /// Argument supplied is null. + public void Add(string fileName, string entryName) + { + if (fileName == null) { + throw new ArgumentNullException("fileName"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(fileName, EntryFactory.MakeFileEntry(entryName))); + } + + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + public void Add(IStaticDataSource dataSource, string entryName) + { + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + AddUpdate(new ZipUpdate(dataSource, EntryFactory.MakeFileEntry(entryName, false))); + } + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + /// The compression method to use. + public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod) + { + if ( dataSource == null ) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + + ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false); + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(dataSource, entry)); + } + + /// + /// Add a file entry with data. + /// + /// The source of the data for this entry. + /// The name to give to the entry. + /// The compression method to use. + /// Ensure Unicode text is used for name and comments for this entry. + public void Add(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod, bool useUnicodeText) + { + if (dataSource == null) { + throw new ArgumentNullException("dataSource"); + } + + if ( entryName == null ) { + throw new ArgumentNullException("entryName"); + } + + CheckUpdating(); + + ZipEntry entry = EntryFactory.MakeFileEntry(entryName, false); + entry.IsUnicodeText = useUnicodeText; + entry.CompressionMethod = compressionMethod; + + AddUpdate(new ZipUpdate(dataSource, entry)); + } + + /// + /// Add a that contains no data. + /// + /// The entry to add. + /// This can be used to add directories, volume labels, or empty file entries. + public void Add(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + CheckUpdating(); + + if ( (entry.Size != 0) || (entry.CompressedSize != 0) ) { + throw new ZipException("Entry cannot have any data"); + } + + AddUpdate(new ZipUpdate(UpdateCommand.Add, entry)); + } + + /// + /// Add a directory entry to the archive. + /// + /// The directory to add. + public void AddDirectory(string directoryName) + { + if ( directoryName == null ) { + throw new ArgumentNullException("directoryName"); + } + + CheckUpdating(); + + ZipEntry dirEntry = EntryFactory.MakeDirectoryEntry(directoryName); + AddUpdate(new ZipUpdate(UpdateCommand.Add, dirEntry)); + } + + #endregion + + #region Modifying Entries +/* Modify not yet ready for public consumption. + Direct modification of an entry should not overwrite original data before its read. + Safe mode is trivial in this sense. + public void Modify(ZipEntry original, ZipEntry updated) + { + if ( original == null ) { + throw new ArgumentNullException("original"); + } + + if ( updated == null ) { + throw new ArgumentNullException("updated"); + } + + CheckUpdating(); + contentsEdited_ = true; + updates_.Add(new ZipUpdate(original, updated)); + } +*/ + #endregion + + #region Deleting Entries + /// + /// Delete an entry by name + /// + /// The filename to delete + /// True if the entry was found and deleted; false otherwise. + public bool Delete(string fileName) + { + if ( fileName == null ) { + throw new ArgumentNullException("fileName"); + } + + CheckUpdating(); + + bool result = false; + int index = FindExistingUpdate(fileName); + if ( (index >= 0) && (updates_[index] != null) ) { + result = true; + contentsEdited_ = true; + updates_[index] = null; + updateCount_ -= 1; + } + else { + throw new ZipException("Cannot find entry to delete"); + } + return result; + } + + /// + /// Delete a from the archive. + /// + /// The entry to delete. + public void Delete(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + CheckUpdating(); + + int index = FindExistingUpdate(entry); + if ( index >= 0 ) { + contentsEdited_ = true; + updates_[index] = null; + updateCount_ -= 1; + } + else { + throw new ZipException("Cannot find entry to delete"); + } + } + + #endregion + + #region Update Support + + #region Writing Values/Headers + void WriteLEShort(int value) + { + baseStream_.WriteByte(( byte )(value & 0xff)); + baseStream_.WriteByte(( byte )((value >> 8) & 0xff)); + } + + /// + /// Write an unsigned short in little endian byte order. + /// + void WriteLEUshort(ushort value) + { + baseStream_.WriteByte(( byte )(value & 0xff)); + baseStream_.WriteByte(( byte )(value >> 8)); + } + + /// + /// Write an int in little endian byte order. + /// + void WriteLEInt(int value) + { + WriteLEShort(value & 0xffff); + WriteLEShort(value >> 16); + } + + /// + /// Write an unsigned int in little endian byte order. + /// + void WriteLEUint(uint value) + { + WriteLEUshort((ushort)(value & 0xffff)); + WriteLEUshort((ushort)(value >> 16)); + } + + /// + /// Write a long in little endian byte order. + /// + void WriteLeLong(long value) + { + WriteLEInt(( int )(value & 0xffffffff)); + WriteLEInt(( int )(value >> 32)); + } + + void WriteLEUlong(ulong value) + { + WriteLEUint(( uint )(value & 0xffffffff)); + WriteLEUint(( uint )(value >> 32)); + } + + void WriteLocalEntryHeader(ZipUpdate update) + { + ZipEntry entry = update.OutEntry; + + // TODO: Local offset will require adjusting for multi-disk zip files. + entry.Offset = baseStream_.Position; + + // TODO: Need to clear any entry flags that dont make sense or throw an exception here. + if (update.Command != UpdateCommand.Copy) { + if (entry.CompressionMethod == CompressionMethod.Deflated) { + if (entry.Size == 0) { + // No need to compress - no data. + entry.CompressedSize = entry.Size; + entry.Crc = 0; + entry.CompressionMethod = CompressionMethod.Stored; + } + } + else if (entry.CompressionMethod == CompressionMethod.Stored) { + entry.Flags &= ~(int)GeneralBitFlags.Descriptor; + } + + if (HaveKeys) { + entry.IsCrypted = true; + if (entry.Crc < 0) { + entry.Flags |= (int)GeneralBitFlags.Descriptor; + } + } + else { + entry.IsCrypted = false; + } + + switch (useZip64_) { + case UseZip64.Dynamic: + if (entry.Size < 0) { + entry.ForceZip64(); + } + break; + + case UseZip64.On: + entry.ForceZip64(); + break; + + case UseZip64.Off: + // Do nothing. The entry itself may be using Zip64 independantly. + break; + } + } + + // Write the local file header + WriteLEInt(ZipConstants.LocalHeaderSignature); + + WriteLEShort(entry.Version); + WriteLEShort(entry.Flags); + + WriteLEShort((byte)entry.CompressionMethod); + WriteLEInt(( int )entry.DosTime); + + if ( !entry.HasCrc ) { + // Note patch address for updating CRC later. + update.CrcPatchOffset = baseStream_.Position; + WriteLEInt(( int )0); + } + else { + WriteLEInt(unchecked(( int )entry.Crc)); + } + + if (entry.LocalHeaderRequiresZip64) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + if ( (entry.CompressedSize < 0) || (entry.Size < 0) ) { + update.SizePatchOffset = baseStream_.Position; + } + + WriteLEInt(( int )entry.CompressedSize); + WriteLEInt(( int )entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if ( name.Length > 0xFFFF ) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.LocalHeaderRequiresZip64 ) { + ed.StartNewEntry(); + + // Local entry header always includes size and compressed size. + // NOTE the order of these fields is reversed when compared to the normal headers! + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + ed.AddNewEntry(1); + } + else { + ed.Delete(1); + } + + entry.ExtraData = ed.GetEntryData(); + + WriteLEShort(name.Length); + WriteLEShort(entry.ExtraData.Length); + + if ( name.Length > 0 ) { + baseStream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 ) { + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cannot find extra data"); + } + + update.SizePatchOffset = baseStream_.Position + ed.CurrentReadIndex; + } + + if ( entry.ExtraData.Length > 0 ) { + baseStream_.Write(entry.ExtraData, 0, entry.ExtraData.Length); + } + } + + int WriteCentralDirectoryHeader(ZipEntry entry) + { + if ( entry.CompressedSize < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown csize"); + } + + if ( entry.Size < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown size"); + } + + if ( entry.Crc < 0 ) { + throw new ZipException("Attempt to write central directory entry with unknown crc"); + } + + // Write the central file header + WriteLEInt(ZipConstants.CentralHeaderSignature); + + // Version made by + WriteLEShort(ZipConstants.VersionMadeBy); + + // Version required to extract + WriteLEShort(entry.Version); + + WriteLEShort(entry.Flags); + + unchecked { + WriteLEShort((byte)entry.CompressionMethod); + WriteLEInt((int)entry.DosTime); + WriteLEInt((int)entry.Crc); + } + + if ( (entry.IsZip64Forced()) || (entry.CompressedSize >= 0xffffffff) ) { + WriteLEInt(-1); + } + else { + WriteLEInt((int)(entry.CompressedSize & 0xffffffff)); + } + + if ( (entry.IsZip64Forced()) || (entry.Size >= 0xffffffff) ) { + WriteLEInt(-1); + } + else { + WriteLEInt((int)entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if ( name.Length > 0xFFFF ) { + throw new ZipException("Entry name is too long."); + } + + WriteLEShort(name.Length); + + // Central header extra data is different to local header version so regenerate. + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.CentralHeaderRequiresZip64 ) { + ed.StartNewEntry(); + + if ( (entry.Size >= 0xffffffff) || (useZip64_ == UseZip64.On) ) + { + ed.AddLeLong(entry.Size); + } + + if ( (entry.CompressedSize >= 0xffffffff) || (useZip64_ == UseZip64.On) ) + { + ed.AddLeLong(entry.CompressedSize); + } + + if ( entry.Offset >= 0xffffffff ) { + ed.AddLeLong(entry.Offset); + } + + // Number of disk on which this file starts isnt supported and is never written here. + ed.AddNewEntry(1); + } + else { + // Should have already be done when local header was added. + ed.Delete(1); + } + + byte[] centralExtraData = ed.GetEntryData(); + + WriteLEShort(centralExtraData.Length); + WriteLEShort(entry.Comment != null ? entry.Comment.Length : 0); + + WriteLEShort(0); // disk number + WriteLEShort(0); // internal file attributes + + // External file attributes... + if ( entry.ExternalFileAttributes != -1 ) { + WriteLEInt(entry.ExternalFileAttributes); + } + else { + if ( entry.IsDirectory ) { + WriteLEUint(16); + } + else { + WriteLEUint(0); + } + } + + if ( entry.Offset >= 0xffffffff ) { + WriteLEUint(0xffffffff); + } + else { + WriteLEUint((uint)(int)entry.Offset); + } + + if ( name.Length > 0 ) { + baseStream_.Write(name, 0, name.Length); + } + + if ( centralExtraData.Length > 0 ) { + baseStream_.Write(centralExtraData, 0, centralExtraData.Length); + } + + byte[] rawComment = (entry.Comment != null) ? Encoding.ASCII.GetBytes(entry.Comment) : new byte[0]; + + if ( rawComment.Length > 0 ) { + baseStream_.Write(rawComment, 0, rawComment.Length); + } + + return ZipConstants.CentralHeaderBaseSize + name.Length + centralExtraData.Length + rawComment.Length; + } + #endregion + + void PostUpdateCleanup() + { + updateDataSource_ = null; + updates_ = null; + updateIndex_ = null; + + if (archiveStorage_ != null) + { + archiveStorage_.Dispose(); + archiveStorage_=null; + } + } + + string GetTransformedFileName(string name) + { + INameTransform transform = NameTransform; + return (transform != null) ? + transform.TransformFile(name) : + name; + } + + string GetTransformedDirectoryName(string name) + { + INameTransform transform = NameTransform; + return (transform != null) ? + transform.TransformDirectory(name) : + name; + } + + /// + /// Get a raw memory buffer. + /// + /// Returns a raw memory buffer. + byte[] GetBuffer() + { + if ( copyBuffer_ == null ) { + copyBuffer_ = new byte[bufferSize_]; + } + return copyBuffer_; + } + + void CopyDescriptorBytes(ZipUpdate update, Stream dest, Stream source) + { + int bytesToCopy = GetDescriptorSize(update); + + if ( bytesToCopy > 0 ) { + byte[] buffer = GetBuffer(); + + while ( bytesToCopy > 0 ) { + int readSize = Math.Min(buffer.Length, bytesToCopy); + + int bytesRead = source.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + dest.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + } + else { + throw new ZipException("Unxpected end of stream"); + } + } + } + } + + void CopyBytes(ZipUpdate update, Stream destination, Stream source, + long bytesToCopy, bool updateCrc) + { + if ( destination == source ) { + throw new InvalidOperationException("Destination and source are the same"); + } + + // NOTE: Compressed size is updated elsewhere. + Crc32 crc = new Crc32(); + byte[] buffer = GetBuffer(); + + long targetBytes = bytesToCopy; + long totalBytesRead = 0; + + int bytesRead; + do { + int readSize = buffer.Length; + + if ( bytesToCopy < readSize ) { + readSize = (int)bytesToCopy; + } + + bytesRead = source.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + if ( updateCrc ) { + crc.Update(buffer, 0, bytesRead); + } + destination.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + totalBytesRead += bytesRead; + } + } + while ( (bytesRead > 0) && (bytesToCopy > 0) ); + + if ( totalBytesRead != targetBytes ) { + throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); + } + + if ( updateCrc ) { + update.OutEntry.Crc = crc.Value; + } + } + + /// + /// Get the size of the source descriptor for a . + /// + /// The update to get the size for. + /// The descriptor size, zero if there isnt one. + int GetDescriptorSize(ZipUpdate update) + { + int result = 0; + if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) { + result = ZipConstants.DataDescriptorSize - 4; + if ( update.Entry.LocalHeaderRequiresZip64 ) { + result = ZipConstants.Zip64DataDescriptorSize - 4; + } + } + return result; + } + + void CopyDescriptorBytesDirect(ZipUpdate update, Stream stream, ref long destinationPosition, long sourcePosition) + { + int bytesToCopy = GetDescriptorSize(update); + + while ( bytesToCopy > 0 ) { + int readSize = (int)bytesToCopy; + byte[] buffer = GetBuffer(); + + stream.Position = sourcePosition; + int bytesRead = stream.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + stream.Position = destinationPosition; + stream.Write(buffer, 0, bytesRead); + bytesToCopy -= bytesRead; + destinationPosition += bytesRead; + sourcePosition += bytesRead; + } + else { + throw new ZipException("Unxpected end of stream"); + } + } + } + + void CopyEntryDataDirect(ZipUpdate update, Stream stream, bool updateCrc, ref long destinationPosition, ref long sourcePosition) + { + long bytesToCopy = update.Entry.CompressedSize; + + // NOTE: Compressed size is updated elsewhere. + Crc32 crc = new Crc32(); + byte[] buffer = GetBuffer(); + + long targetBytes = bytesToCopy; + long totalBytesRead = 0; + + int bytesRead; + do + { + int readSize = buffer.Length; + + if ( bytesToCopy < readSize ) { + readSize = (int)bytesToCopy; + } + + stream.Position = sourcePosition; + bytesRead = stream.Read(buffer, 0, readSize); + if ( bytesRead > 0 ) { + if ( updateCrc ) { + crc.Update(buffer, 0, bytesRead); + } + stream.Position = destinationPosition; + stream.Write(buffer, 0, bytesRead); + + destinationPosition += bytesRead; + sourcePosition += bytesRead; + bytesToCopy -= bytesRead; + totalBytesRead += bytesRead; + } + } + while ( (bytesRead > 0) && (bytesToCopy > 0) ); + + if ( totalBytesRead != targetBytes ) { + throw new ZipException(string.Format("Failed to copy bytes expected {0} read {1}", targetBytes, totalBytesRead)); + } + + if ( updateCrc ) { + update.OutEntry.Crc = crc.Value; + } + } + + int FindExistingUpdate(ZipEntry entry) + { + int result = -1; + string convertedName = GetTransformedFileName(entry.Name); + + if (updateIndex_.ContainsKey(convertedName)) { + result = (int)updateIndex_[convertedName]; + } +/* + // This is slow like the coming of the next ice age but takes less storage and may be useful + // for CF? + for (int index = 0; index < updates_.Count; ++index) + { + ZipUpdate zu = ( ZipUpdate )updates_[index]; + if ( (zu.Entry.ZipFileIndex == entry.ZipFileIndex) && + (string.Compare(convertedName, zu.Entry.Name, true, CultureInfo.InvariantCulture) == 0) ) { + result = index; + break; + } + } + */ + return result; + } + + int FindExistingUpdate(string fileName) + { + int result = -1; + + string convertedName = GetTransformedFileName(fileName); + + if (updateIndex_.ContainsKey(convertedName)) { + result = (int)updateIndex_[convertedName]; + } + +/* + // This is slow like the coming of the next ice age but takes less storage and may be useful + // for CF? + for ( int index = 0; index < updates_.Count; ++index ) { + if ( string.Compare(convertedName, (( ZipUpdate )updates_[index]).Entry.Name, + true, CultureInfo.InvariantCulture) == 0 ) { + result = index; + break; + } + } + */ + + return result; + } + + /// + /// Get an output stream for the specified + /// + /// The entry to get an output stream for. + /// The output stream obtained for the entry. + Stream GetOutputStream(ZipEntry entry) + { + Stream result = baseStream_; + + if ( entry.IsCrypted == true ) { +#if NETCF_1_0 + throw new ZipException("Encryption not supported for Compact Framework 1.0"); +#else + result = CreateAndInitEncryptionStream(result, entry); +#endif + } + + switch ( entry.CompressionMethod ) { + case CompressionMethod.Stored: + result = new UncompressedStream(result); + break; + + case CompressionMethod.Deflated: + DeflaterOutputStream dos = new DeflaterOutputStream(result, new Deflater(9, true)); + dos.IsStreamOwner = false; + result = dos; + break; + + default: + throw new ZipException("Unknown compression method " + entry.CompressionMethod); + } + return result; + } + + void AddEntry(ZipFile workFile, ZipUpdate update) + { + Stream source = null; + + if ( update.Entry.IsFile ) { + source = update.GetSource(); + + if ( source == null ) { + source = updateDataSource_.GetSource(update.Entry, update.Filename); + } + } + + if ( source != null ) { + using ( source ) { + long sourceStreamLength = source.Length; + if ( update.OutEntry.Size < 0 ) { + update.OutEntry.Size = sourceStreamLength; + } + else { + // Check for errant entries. + if ( update.OutEntry.Size != sourceStreamLength ) { + throw new ZipException("Entry size/stream size mismatch"); + } + } + + workFile.WriteLocalEntryHeader(update); + + long dataStart = workFile.baseStream_.Position; + + using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) { + CopyBytes(update, output, source, sourceStreamLength, true); + } + + long dataEnd = workFile.baseStream_.Position; + update.OutEntry.CompressedSize = dataEnd - dataStart; + + if ((update.OutEntry.Flags & (int)GeneralBitFlags.Descriptor) == (int)GeneralBitFlags.Descriptor) + { + ZipHelperStream helper = new ZipHelperStream(workFile.baseStream_); + helper.WriteDataDescriptor(update.OutEntry); + } + } + } + else { + workFile.WriteLocalEntryHeader(update); + update.OutEntry.CompressedSize = 0; + } + + } + + void ModifyEntry(ZipFile workFile, ZipUpdate update) + { + workFile.WriteLocalEntryHeader(update); + long dataStart = workFile.baseStream_.Position; + + // TODO: This is slow if the changes don't effect the data!! + if ( update.Entry.IsFile && (update.Filename != null) ) { + using ( Stream output = workFile.GetOutputStream(update.OutEntry) ) { + using ( Stream source = this.GetInputStream(update.Entry) ) { + CopyBytes(update, output, source, source.Length, true); + } + } + } + + long dataEnd = workFile.baseStream_.Position; + update.Entry.CompressedSize = dataEnd - dataStart; + } + + void CopyEntryDirect(ZipFile workFile, ZipUpdate update, ref long destinationPosition) + { + bool skipOver = false; + if ( update.Entry.Offset == destinationPosition ) { + skipOver = true; + } + + if ( !skipOver ) { + baseStream_.Position = destinationPosition; + workFile.WriteLocalEntryHeader(update); + destinationPosition = baseStream_.Position; + } + + long sourcePosition = 0; + + const int NameLengthOffset = 26; + + // TODO: Add base for SFX friendly handling + long entryDataOffset = update.Entry.Offset + NameLengthOffset; + + baseStream_.Seek(entryDataOffset, SeekOrigin.Begin); + + // Clumsy way of handling retrieving the original name and extra data length for now. + // TODO: Stop re-reading name and data length in CopyEntryDirect. + uint nameLength = ReadLEUshort(); + uint extraLength = ReadLEUshort(); + + sourcePosition = baseStream_.Position + nameLength + extraLength; + + if (skipOver) { + if (update.OffsetBasedSize != -1) + destinationPosition += update.OffsetBasedSize; + else + // TODO: Find out why this calculation comes up 4 bytes short on some entries in ODT (Office Document Text) archives. + // WinZip produces a warning on these entries: + // "caution: value of lrec.csize (compressed size) changed from ..." + destinationPosition += + (sourcePosition - entryDataOffset) + NameLengthOffset + // Header size + update.Entry.CompressedSize + GetDescriptorSize(update); + } + else { + if ( update.Entry.CompressedSize > 0 ) { + CopyEntryDataDirect(update, baseStream_, false, ref destinationPosition, ref sourcePosition ); + } + CopyDescriptorBytesDirect(update, baseStream_, ref destinationPosition, sourcePosition); + } + } + + void CopyEntry(ZipFile workFile, ZipUpdate update) + { + workFile.WriteLocalEntryHeader(update); + + if ( update.Entry.CompressedSize > 0 ) { + const int NameLengthOffset = 26; + + long entryDataOffset = update.Entry.Offset + NameLengthOffset; + + // TODO: This wont work for SFX files! + baseStream_.Seek(entryDataOffset, SeekOrigin.Begin); + + uint nameLength = ReadLEUshort(); + uint extraLength = ReadLEUshort(); + + baseStream_.Seek(nameLength + extraLength, SeekOrigin.Current); + + CopyBytes(update, workFile.baseStream_, baseStream_, update.Entry.CompressedSize, false); + } + CopyDescriptorBytes(update, workFile.baseStream_, baseStream_); + } + + void Reopen(Stream source) + { + if ( source == null ) { + throw new ZipException("Failed to reopen archive - no source"); + } + + isNewArchive_ = false; + baseStream_ = source; + ReadEntries(); + } + + void Reopen() + { + if (Name == null) { + throw new InvalidOperationException("Name is not known cannot Reopen"); + } + + Reopen(File.Open(Name, FileMode.Open, FileAccess.Read, FileShare.Read)); + } + + void UpdateCommentOnly() + { + long baseLength = baseStream_.Length; + + ZipHelperStream updateFile = null; + + if ( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { + Stream copyStream = archiveStorage_.MakeTemporaryCopy(baseStream_); + updateFile = new ZipHelperStream(copyStream); + updateFile.IsStreamOwner = true; + + baseStream_.Close(); + baseStream_ = null; + } + else { + if (archiveStorage_.UpdateMode == FileUpdateMode.Direct) { + // TODO: archiveStorage wasnt originally intended for this use. + // Need to revisit this to tidy up handling as archive storage currently doesnt + // handle the original stream well. + // The problem is when using an existing zip archive with an in memory archive storage. + // The open stream wont support writing but the memory storage should open the same file not an in memory one. + + // Need to tidy up the archive storage interface and contract basically. + baseStream_ = archiveStorage_.OpenForDirectUpdate(baseStream_); + updateFile = new ZipHelperStream(baseStream_); + } + else { + baseStream_.Close(); + baseStream_ = null; + updateFile = new ZipHelperStream(Name); + } + } + + using ( updateFile ) { + long locatedCentralDirOffset = + updateFile.LocateBlockWithSignature(ZipConstants.EndOfCentralDirectorySignature, + baseLength, ZipConstants.EndOfCentralRecordBaseSize, 0xffff); + if ( locatedCentralDirOffset < 0 ) { + throw new ZipException("Cannot find central directory"); + } + + const int CentralHeaderCommentSizeOffset = 16; + updateFile.Position += CentralHeaderCommentSizeOffset; + + byte[] rawComment = newComment_.RawComment; + + updateFile.WriteLEShort(rawComment.Length); + updateFile.Write(rawComment, 0, rawComment.Length); + updateFile.SetLength(updateFile.Position); + } + + if ( archiveStorage_.UpdateMode == FileUpdateMode.Safe ) { + Reopen(archiveStorage_.ConvertTemporaryToFinal()); + } + else { + ReadEntries(); + } + } + + /// + /// Class used to sort updates. + /// + class UpdateComparer : IComparer + { + /// + /// Compares two objects and returns a value indicating whether one is + /// less than, equal to or greater than the other. + /// + /// First object to compare + /// Second object to compare. + /// Compare result. + public int Compare( + object x, + object y) + { + ZipUpdate zx = x as ZipUpdate; + ZipUpdate zy = y as ZipUpdate; + + int result; + + if (zx == null) { + if (zy == null) { + result = 0; + } + else { + result = -1; + } + } + else if (zy == null) { + result = 1; + } + else { + int xCmdValue = ((zx.Command == UpdateCommand.Copy) || (zx.Command == UpdateCommand.Modify)) ? 0 : 1; + int yCmdValue = ((zy.Command == UpdateCommand.Copy) || (zy.Command == UpdateCommand.Modify)) ? 0 : 1; + + result = xCmdValue - yCmdValue; + if (result == 0) { + long offsetDiff = zx.Entry.Offset - zy.Entry.Offset; + if (offsetDiff < 0) { + result = -1; + } + else if (offsetDiff == 0) { + result = 0; + } + else { + result = 1; + } + } + } + return result; + } + } + + void RunUpdates() + { + long sizeEntries = 0; + long endOfStream = 0; + bool directUpdate = false; + long destinationPosition = 0; // NOT SFX friendly + + ZipFile workFile; + + if ( IsNewArchive ) { + workFile = this; + workFile.baseStream_.Position = 0; + directUpdate = true; + } + else if ( archiveStorage_.UpdateMode == FileUpdateMode.Direct ) { + workFile = this; + workFile.baseStream_.Position = 0; + directUpdate = true; + + // Sort the updates by offset within copies/modifies, then adds. + // This ensures that data required by copies will not be overwritten. + updates_.Sort(new UpdateComparer()); + } + else { + workFile = ZipFile.Create(archiveStorage_.GetTemporaryOutput()); + workFile.UseZip64 = UseZip64; + + if (key != null) { + workFile.key = (byte[])key.Clone(); + } + } + + try { + foreach ( ZipUpdate update in updates_ ) { + if (update != null) { + switch (update.Command) { + case UpdateCommand.Copy: + if (directUpdate) { + CopyEntryDirect(workFile, update, ref destinationPosition); + } + else { + CopyEntry(workFile, update); + } + break; + + case UpdateCommand.Modify: + // TODO: Direct modifying of an entry will take some legwork. + ModifyEntry(workFile, update); + break; + + case UpdateCommand.Add: + if (!IsNewArchive && directUpdate) { + workFile.baseStream_.Position = destinationPosition; + } + + AddEntry(workFile, update); + + if (directUpdate) { + destinationPosition = workFile.baseStream_.Position; + } + break; + } + } + } + + if ( !IsNewArchive && directUpdate ) { + workFile.baseStream_.Position = destinationPosition; + } + + long centralDirOffset = workFile.baseStream_.Position; + + foreach ( ZipUpdate update in updates_ ) { + if (update != null) { + sizeEntries += workFile.WriteCentralDirectoryHeader(update.OutEntry); + } + } + + byte[] theComment = (newComment_ != null) ? newComment_.RawComment : ZipConstants.ConvertToArray(comment_); + using ( ZipHelperStream zhs = new ZipHelperStream(workFile.baseStream_) ) { + zhs.WriteEndOfCentralDirectory(updateCount_, sizeEntries, centralDirOffset, theComment); + } + + endOfStream = workFile.baseStream_.Position; + + // And now patch entries... + foreach ( ZipUpdate update in updates_ ) { + if (update != null) + { + // If the size of the entry is zero leave the crc as 0 as well. + // The calculated crc will be all bits on... + if ((update.CrcPatchOffset > 0) && (update.OutEntry.CompressedSize > 0)) { + workFile.baseStream_.Position = update.CrcPatchOffset; + workFile.WriteLEInt((int)update.OutEntry.Crc); + } + + if (update.SizePatchOffset > 0) { + workFile.baseStream_.Position = update.SizePatchOffset; + if (update.OutEntry.LocalHeaderRequiresZip64) { + workFile.WriteLeLong(update.OutEntry.Size); + workFile.WriteLeLong(update.OutEntry.CompressedSize); + } + else { + workFile.WriteLEInt((int)update.OutEntry.CompressedSize); + workFile.WriteLEInt((int)update.OutEntry.Size); + } + } + } + } + } + catch { + workFile.Close(); + if (!directUpdate && (workFile.Name != null)) { + File.Delete(workFile.Name); + } + throw; + } + + if (directUpdate) { + workFile.baseStream_.SetLength(endOfStream); + workFile.baseStream_.Flush(); + isNewArchive_ = false; + ReadEntries(); + } + else { + baseStream_.Close(); + Reopen(archiveStorage_.ConvertTemporaryToFinal()); + } + } + + void CheckUpdating() + { + if ( updates_ == null ) { + throw new InvalidOperationException("BeginUpdate has not been called"); + } + } + + #endregion + + #region ZipUpdate class + /// + /// Represents a pending update to a Zip file. + /// + class ZipUpdate + { + #region Constructors + public ZipUpdate(string fileName, ZipEntry entry) + { + command_ = UpdateCommand.Add; + entry_ = entry; + filename_ = fileName; + } + + [Obsolete] + public ZipUpdate(string fileName, string entryName, CompressionMethod compressionMethod) + { + command_ = UpdateCommand.Add; + entry_ = new ZipEntry(entryName); + entry_.CompressionMethod = compressionMethod; + filename_ = fileName; + } + + [Obsolete] + public ZipUpdate(string fileName, string entryName) + : this(fileName, entryName, CompressionMethod.Deflated) + { + // Do nothing. + } + + [Obsolete] + public ZipUpdate(IStaticDataSource dataSource, string entryName, CompressionMethod compressionMethod) + { + command_ = UpdateCommand.Add; + entry_ = new ZipEntry(entryName); + entry_.CompressionMethod = compressionMethod; + dataSource_ = dataSource; + } + + public ZipUpdate(IStaticDataSource dataSource, ZipEntry entry) + { + command_ = UpdateCommand.Add; + entry_ = entry; + dataSource_ = dataSource; + } + + public ZipUpdate(ZipEntry original, ZipEntry updated) + { + throw new ZipException("Modify not currently supported"); + /* + command_ = UpdateCommand.Modify; + entry_ = ( ZipEntry )original.Clone(); + outEntry_ = ( ZipEntry )updated.Clone(); + */ + } + + public ZipUpdate(UpdateCommand command, ZipEntry entry) + { + command_ = command; + entry_ = ( ZipEntry )entry.Clone(); + } + + + /// + /// Copy an existing entry. + /// + /// The existing entry to copy. + public ZipUpdate(ZipEntry entry) + : this(UpdateCommand.Copy, entry) + { + // Do nothing. + } + #endregion + + /// + /// Get the for this update. + /// + /// This is the source or original entry. + public ZipEntry Entry + { + get { return entry_; } + } + + /// + /// Get the that will be written to the updated/new file. + /// + public ZipEntry OutEntry + { + get { + if ( outEntry_ == null ) { + outEntry_ = (ZipEntry)entry_.Clone(); + } + + return outEntry_; + } + } + + /// + /// Get the command for this update. + /// + public UpdateCommand Command + { + get { return command_; } + } + + /// + /// Get the filename if any for this update. Null if none exists. + /// + public string Filename + { + get { return filename_; } + } + + /// + /// Get/set the location of the size patch for this update. + /// + public long SizePatchOffset + { + get { return sizePatchOffset_; } + set { sizePatchOffset_ = value; } + } + + /// + /// Get /set the location of the crc patch for this update. + /// + public long CrcPatchOffset + { + get { return crcPatchOffset_; } + set { crcPatchOffset_ = value; } + } + + /// + /// Get/set the size calculated by offset. + /// Specifically, the difference between this and next entry's starting offset. + /// + public long OffsetBasedSize + { + get { return _offsetBasedSize; } + set { _offsetBasedSize = value; } + } + + public Stream GetSource() + { + Stream result = null; + if ( dataSource_ != null ) { + result = dataSource_.GetSource(); + } + + return result; + } + + #region Instance Fields + ZipEntry entry_; + ZipEntry outEntry_; + UpdateCommand command_; + IStaticDataSource dataSource_; + string filename_; + long sizePatchOffset_ = -1; + long crcPatchOffset_ = -1; + long _offsetBasedSize = -1; + #endregion + } + + #endregion + #endregion + + #region Disposing + + #region IDisposable Members + void IDisposable.Dispose() + { + Close(); + } + #endregion + + void DisposeInternal(bool disposing) + { + if ( !isDisposed_ ) { + isDisposed_ = true; + entries_ = new ZipEntry[0]; + + if ( IsStreamOwner && (baseStream_ != null) ) { + lock(baseStream_) { + baseStream_.Close(); + } + } + + PostUpdateCleanup(); + } + } + + /// + /// Releases the unmanaged resources used by the this instance and optionally releases the managed resources. + /// + /// true to release both managed and unmanaged resources; + /// false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + DisposeInternal(disposing); + } + + #endregion + + #region Internal routines + #region Reading + /// + /// Read an unsigned short in little endian byte order. + /// + /// Returns the value read. + /// + /// The stream ends prematurely + /// + ushort ReadLEUshort() + { + int data1 = baseStream_.ReadByte(); + + if ( data1 < 0 ) { + throw new EndOfStreamException("End of stream"); + } + + int data2 = baseStream_.ReadByte(); + + if ( data2 < 0 ) { + throw new EndOfStreamException("End of stream"); + } + + + return unchecked((ushort)((ushort)data1 | (ushort)(data2 << 8))); + } + + /// + /// Read a uint in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + uint ReadLEUint() + { + return (uint)(ReadLEUshort() | (ReadLEUshort() << 16)); + } + + ulong ReadLEUlong() + { + return ReadLEUint() | ((ulong)ReadLEUint() << 32); + } + + #endregion + // NOTE this returns the offset of the first byte after the signature. + long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + { + using ( ZipHelperStream les = new ZipHelperStream(baseStream_) ) { + return les.LocateBlockWithSignature(signature, endLocation, minimumBlockSize, maximumVariableData); + } + } + + /// + /// Search for and read the central directory of a zip file filling the entries array. + /// + /// + /// An i/o error occurs. + /// + /// + /// The central directory is malformed or cannot be found + /// + void ReadEntries() + { + // Search for the End Of Central Directory. When a zip comment is + // present the directory will start earlier + // + // The search is limited to 64K which is the maximum size of a trailing comment field to aid speed. + // This should be compatible with both SFX and ZIP files but has only been tested for Zip files + // If a SFX file has the Zip data attached as a resource and there are other resources occuring later then + // this could be invalid. + // Could also speed this up by reading memory in larger blocks. + + if (baseStream_.CanSeek == false) { + throw new ZipException("ZipFile stream must be seekable"); + } + + long locatedEndOfCentralDir = LocateBlockWithSignature(ZipConstants.EndOfCentralDirectorySignature, + baseStream_.Length, ZipConstants.EndOfCentralRecordBaseSize, 0xffff); + + if (locatedEndOfCentralDir < 0) { + throw new ZipException("Cannot find central directory"); + } + + // Read end of central directory record + ushort thisDiskNumber = ReadLEUshort(); + ushort startCentralDirDisk = ReadLEUshort(); + ulong entriesForThisDisk = ReadLEUshort(); + ulong entriesForWholeCentralDir = ReadLEUshort(); + ulong centralDirSize = ReadLEUint(); + long offsetOfCentralDir = ReadLEUint(); + uint commentSize = ReadLEUshort(); + + if ( commentSize > 0 ) { + byte[] comment = new byte[commentSize]; + + StreamUtils.ReadFully(baseStream_, comment); + comment_ = ZipConstants.ConvertToString(comment); + } + else { + comment_ = string.Empty; + } + + bool isZip64 = false; + + // Check if zip64 header information is required. + if ( (thisDiskNumber == 0xffff) || + (startCentralDirDisk == 0xffff) || + (entriesForThisDisk == 0xffff) || + (entriesForWholeCentralDir == 0xffff) || + (centralDirSize == 0xffffffff) || + (offsetOfCentralDir == 0xffffffff) ) { + isZip64 = true; + + long offset = LocateBlockWithSignature(ZipConstants.Zip64CentralDirLocatorSignature, locatedEndOfCentralDir, 0, 0x1000); + if ( offset < 0 ) { + throw new ZipException("Cannot find Zip64 locator"); + } + + // number of the disk with the start of the zip64 end of central directory 4 bytes + // relative offset of the zip64 end of central directory record 8 bytes + // total number of disks 4 bytes + ReadLEUint(); // startDisk64 is not currently used + ulong offset64 = ReadLEUlong(); + uint totalDisks = ReadLEUint(); + + baseStream_.Position = (long)offset64; + long sig64 = ReadLEUint(); + + if ( sig64 != ZipConstants.Zip64CentralFileHeaderSignature ) { + throw new ZipException(string.Format("Invalid Zip64 Central directory signature at {0:X}", offset64)); + } + + // NOTE: Record size = SizeOfFixedFields + SizeOfVariableData - 12. + ulong recordSize = ReadLEUlong(); + int versionMadeBy = ReadLEUshort(); + int versionToExtract = ReadLEUshort(); + uint thisDisk = ReadLEUint(); + uint centralDirDisk = ReadLEUint(); + entriesForThisDisk = ReadLEUlong(); + entriesForWholeCentralDir = ReadLEUlong(); + centralDirSize = ReadLEUlong(); + offsetOfCentralDir = (long)ReadLEUlong(); + + // NOTE: zip64 extensible data sector (variable size) is ignored. + } + + entries_ = new ZipEntry[entriesForThisDisk]; + + // SFX/embedded support, find the offset of the first entry vis the start of the stream + // This applies to Zip files that are appended to the end of an SFX stub. + // Or are appended as a resource to an executable. + // Zip files created by some archivers have the offsets altered to reflect the true offsets + // and so dont require any adjustment here... + // TODO: Difficulty with Zip64 and SFX offset handling needs resolution - maths? + if ( !isZip64 && (offsetOfCentralDir < locatedEndOfCentralDir - (4 + (long)centralDirSize)) ) { + offsetOfFirstEntry = locatedEndOfCentralDir - (4 + (long)centralDirSize + offsetOfCentralDir); + if (offsetOfFirstEntry <= 0) { + throw new ZipException("Invalid embedded zip archive"); + } + } + + baseStream_.Seek(offsetOfFirstEntry + offsetOfCentralDir, SeekOrigin.Begin); + + for (ulong i = 0; i < entriesForThisDisk; i++) { + if (ReadLEUint() != ZipConstants.CentralHeaderSignature) { + throw new ZipException("Wrong Central Directory signature"); + } + + int versionMadeBy = ReadLEUshort(); + int versionToExtract = ReadLEUshort(); + int bitFlags = ReadLEUshort(); + int method = ReadLEUshort(); + uint dostime = ReadLEUint(); + uint crc = ReadLEUint(); + long csize = (long)ReadLEUint(); + long size = (long)ReadLEUint(); + int nameLen = ReadLEUshort(); + int extraLen = ReadLEUshort(); + int commentLen = ReadLEUshort(); + + int diskStartNo = ReadLEUshort(); // Not currently used + int internalAttributes = ReadLEUshort(); // Not currently used + + uint externalAttributes = ReadLEUint(); + long offset = ReadLEUint(); + + byte[] buffer = new byte[Math.Max(nameLen, commentLen)]; + + StreamUtils.ReadFully(baseStream_, buffer, 0, nameLen); + string name = ZipConstants.ConvertToStringExt(bitFlags, buffer, nameLen); + + ZipEntry entry = new ZipEntry(name, versionToExtract, versionMadeBy, (CompressionMethod)method); + entry.Crc = crc & 0xffffffffL; + entry.Size = size & 0xffffffffL; + entry.CompressedSize = csize & 0xffffffffL; + entry.Flags = bitFlags; + entry.DosTime = (uint)dostime; + entry.ZipFileIndex = (long)i; + entry.Offset = offset; + entry.ExternalFileAttributes = (int)externalAttributes; + + if ((bitFlags & 8) == 0) { + entry.CryptoCheckValue = (byte)(crc >> 24); + } + else { + entry.CryptoCheckValue = (byte)((dostime >> 8) & 0xff); + } + + if (extraLen > 0) { + byte[] extra = new byte[extraLen]; + StreamUtils.ReadFully(baseStream_, extra); + entry.ExtraData = extra; + } + + entry.ProcessExtraData(false); + + if (commentLen > 0) { + StreamUtils.ReadFully(baseStream_, buffer, 0, commentLen); + entry.Comment = ZipConstants.ConvertToStringExt(bitFlags, buffer, commentLen); + } + + entries_[i] = entry; + } + } + + /// + /// Locate the data for a given entry. + /// + /// + /// The start offset of the data. + /// + /// + /// The stream ends prematurely + /// + /// + /// The local header signature is invalid, the entry and central header file name lengths are different + /// or the local and entry compression methods dont match + /// + long LocateEntry(ZipEntry entry) + { + return TestLocalHeader(entry, HeaderTest.Extract); + } + +#if !NETCF_1_0 + Stream CreateAndInitDecryptionStream(Stream baseStream, ZipEntry entry) + { + CryptoStream result = null; + + if ( (entry.Version < ZipConstants.VersionStrongEncryption) + || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { + PkzipClassicManaged classicManaged = new PkzipClassicManaged(); + + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for encrypted stream"); + } + + result = new CryptoStream(baseStream, classicManaged.CreateDecryptor(key, null), CryptoStreamMode.Read); + CheckClassicPassword(result, entry); + } + else { +#if !NET_1_1 && !NETCF_2_0 + if (entry.Version == ZipConstants.VERSION_AES) { + // + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for AES encrypted stream"); + } + int saltLen = entry.AESSaltLen; + byte[] saltBytes = new byte[saltLen]; + int saltIn = baseStream.Read(saltBytes, 0, saltLen); + if (saltIn != saltLen) + throw new ZipException("AES Salt expected " + saltLen + " got " + saltIn); + // + byte[] pwdVerifyRead = new byte[2]; + baseStream.Read(pwdVerifyRead, 0, 2); + int blockSize = entry.AESKeySize / 8; // bits to bytes + + ZipAESTransform decryptor = new ZipAESTransform(rawPassword_, saltBytes, blockSize, false); + byte[] pwdVerifyCalc = decryptor.PwdVerifier; + if (pwdVerifyCalc[0] != pwdVerifyRead[0] || pwdVerifyCalc[1] != pwdVerifyRead[1]) + throw new Exception("Invalid password for AES"); + result = new ZipAESStream(baseStream, decryptor, CryptoStreamMode.Read); + } + else +#endif + { + throw new ZipException("Decryption method not supported"); + } + } + + return result; + } + + Stream CreateAndInitEncryptionStream(Stream baseStream, ZipEntry entry) + { + CryptoStream result = null; + if ( (entry.Version < ZipConstants.VersionStrongEncryption) + || (entry.Flags & (int)GeneralBitFlags.StrongEncryption) == 0) { + PkzipClassicManaged classicManaged = new PkzipClassicManaged(); + + OnKeysRequired(entry.Name); + if (HaveKeys == false) { + throw new ZipException("No password available for encrypted stream"); + } + + // Closing a CryptoStream will close the base stream as well so wrap it in an UncompressedStream + // which doesnt do this. + result = new CryptoStream(new UncompressedStream(baseStream), + classicManaged.CreateEncryptor(key, null), CryptoStreamMode.Write); + + if ( (entry.Crc < 0) || (entry.Flags & 8) != 0) { + WriteEncryptionHeader(result, entry.DosTime << 16); + } + else { + WriteEncryptionHeader(result, entry.Crc); + } + } + return result; + } + + static void CheckClassicPassword(CryptoStream classicCryptoStream, ZipEntry entry) + { + byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize]; + StreamUtils.ReadFully(classicCryptoStream, cryptbuffer); + if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue) { + throw new ZipException("Invalid password"); + } + } +#endif + + static void WriteEncryptionHeader(Stream stream, long crcValue) + { + byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize]; + Random rnd = new Random(); + rnd.NextBytes(cryptBuffer); + cryptBuffer[11] = (byte)(crcValue >> 24); + stream.Write(cryptBuffer, 0, cryptBuffer.Length); + } + + #endregion + + #region Instance Fields + bool isDisposed_; + string name_; + string comment_; + string rawPassword_; + Stream baseStream_; + bool isStreamOwner; + long offsetOfFirstEntry; + ZipEntry[] entries_; + byte[] key; + bool isNewArchive_; + + // Default is dynamic which is not backwards compatible and can cause problems + // with XP's built in compression which cant read Zip64 archives. + // However it does avoid the situation were a large file is added and cannot be completed correctly. + // Hint: Set always ZipEntry size before they are added to an archive and this setting isnt needed. + UseZip64 useZip64_ = UseZip64.Dynamic ; + + #region Zip Update Instance Fields + ArrayList updates_; + long updateCount_; // Count is managed manually as updates_ can contain nulls! + Hashtable updateIndex_; + IArchiveStorage archiveStorage_; + IDynamicDataSource updateDataSource_; + bool contentsEdited_; + int bufferSize_ = DefaultBufferSize; + byte[] copyBuffer_; + ZipString newComment_; + bool commentEdited_; + IEntryFactory updateEntryFactory_ = new ZipEntryFactory(); + #endregion + #endregion + + #region Support Classes + /// + /// Represents a string from a which is stored as an array of bytes. + /// + class ZipString + { + #region Constructors + /// + /// Initialise a with a string. + /// + /// The textual string form. + public ZipString(string comment) + { + comment_ = comment; + isSourceString_ = true; + } + + /// + /// Initialise a using a string in its binary 'raw' form. + /// + /// + public ZipString(byte[] rawString) + { + rawComment_ = rawString; + } + #endregion + + /// + /// Get a value indicating the original source of data for this instance. + /// True if the source was a string; false if the source was binary data. + /// + public bool IsSourceString + { + get { return isSourceString_; } + } + + /// + /// Get the length of the comment when represented as raw bytes. + /// + public int RawLength + { + get { + MakeBytesAvailable(); + return rawComment_.Length; + } + } + + /// + /// Get the comment in its 'raw' form as plain bytes. + /// + public byte[] RawComment + { + get { + MakeBytesAvailable(); + return (byte[])rawComment_.Clone(); + } + } + + /// + /// Reset the comment to its initial state. + /// + public void Reset() + { + if ( isSourceString_ ) { + rawComment_ = null; + } + else { + comment_ = null; + } + } + + void MakeTextAvailable() + { + if ( comment_ == null ) { + comment_ = ZipConstants.ConvertToString(rawComment_); + } + } + + void MakeBytesAvailable() + { + if ( rawComment_ == null ) { + rawComment_ = ZipConstants.ConvertToArray(comment_); + } + } + + /// + /// Implicit conversion of comment to a string. + /// + /// The to convert to a string. + /// The textual equivalent for the input value. + static public implicit operator string(ZipString zipString) + { + zipString.MakeTextAvailable(); + return zipString.comment_; + } + + #region Instance Fields + string comment_; + byte[] rawComment_; + bool isSourceString_; + #endregion + } + + /// + /// An enumerator for Zip entries + /// + class ZipEntryEnumerator : IEnumerator + { + #region Constructors + public ZipEntryEnumerator(ZipEntry[] entries) + { + array = entries; + } + + #endregion + #region IEnumerator Members + public object Current + { + get { + return array[index]; + } + } + + public void Reset() + { + index = -1; + } + + public bool MoveNext() + { + return (++index < array.Length); + } + #endregion + #region Instance Fields + ZipEntry[] array; + int index = -1; + #endregion + } + + /// + /// An is a stream that you can write uncompressed data + /// to and flush, but cannot read, seek or do anything else to. + /// + class UncompressedStream : Stream + { + #region Constructors + public UncompressedStream(Stream baseStream) + { + baseStream_ = baseStream; + } + + #endregion + + /// + /// Close this stream instance. + /// + public override void Close() + { + // Do nothing + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + public override bool CanRead + { + get { + return false; + } + } + + /// + /// Write any buffered data to underlying storage. + /// + public override void Flush() + { + baseStream_.Flush(); + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + public override bool CanWrite + { + get { + return baseStream_.CanWrite; + } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + public override bool CanSeek + { + get { + return false; + } + } + + /// + /// Get the length in bytes of the stream. + /// + public override long Length + { + get { + return 0; + } + } + + /// + /// Gets or sets the position within the current stream. + /// + public override long Position + { + get { + return baseStream_.Position; + } + + set + { + } + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + + /// + /// Sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// + /// The new position within the current stream. + /// + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. + public override long Seek(long offset, SeekOrigin origin) + { + return 0; + } + + /// + /// Sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. + public override void SetLength(long value) + { + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. + public override void Write(byte[] buffer, int offset, int count) + { + baseStream_.Write(buffer, offset, count); + } + + #region Instance Fields + Stream baseStream_; + #endregion + } + + /// + /// A is an + /// whose data is only a part or subsection of a file. + /// + class PartialInputStream : Stream + { + #region Constructors + /// + /// Initialise a new instance of the class. + /// + /// The containing the underlying stream to use for IO. + /// The start of the partial data. + /// The length of the partial data. + public PartialInputStream(ZipFile zipFile, long start, long length) + { + start_ = start; + length_ = length; + + // Although this is the only time the zipfile is used + // keeping a reference here prevents premature closure of + // this zip file and thus the baseStream_. + + // Code like this will cause apparently random failures depending + // on the size of the files and when garbage is collected. + // + // ZipFile z = new ZipFile (stream); + // Stream reader = z.GetInputStream(0); + // uses reader here.... + zipFile_ = zipFile; + baseStream_ = zipFile_.baseStream_; + readPos_ = start; + end_ = start + length; + } + #endregion + + /// + /// Read a byte from this stream. + /// + /// Returns the byte read or -1 on end of stream. + public override int ReadByte() + { + if (readPos_ >= end_) { + // -1 is the correct value at end of stream. + return -1; + } + + lock( baseStream_ ) { + baseStream_.Seek(readPos_++, SeekOrigin.Begin); + return baseStream_.ReadByte(); + } + } + + /// + /// Close this partial input stream. + /// + /// + /// The underlying stream is not closed. Close the parent ZipFile class to do that. + /// + public override void Close() + { + // Do nothing at all! + } + + /// + /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. + /// + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// buffer is null. + /// An I/O error occurs. + /// offset or count is negative. + public override int Read(byte[] buffer, int offset, int count) + { + lock(baseStream_) { + if (count > end_ - readPos_) { + count = (int) (end_ - readPos_); + if (count == 0) { + return 0; + } + } + + baseStream_.Seek(readPos_, SeekOrigin.Begin); + int readCount = baseStream_.Read(buffer, offset, count); + if (readCount > 0) { + readPos_ += readCount; + } + return readCount; + } + } + + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// buffer is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + /// + /// When overridden in a derived class, sets the length of the current stream. + /// + /// The desired length of the current stream in bytes. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// An I/O error occurs. + /// Methods were called after the stream was closed. + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + /// + /// When overridden in a derived class, sets the position within the current stream. + /// + /// A byte offset relative to the origin parameter. + /// A value of type indicating the reference point used to obtain the new position. + /// + /// The new position within the current stream. + /// + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. + public override long Seek(long offset, SeekOrigin origin) + { + long newPos = readPos_; + + switch ( origin ) + { + case SeekOrigin.Begin: + newPos = start_ + offset; + break; + + case SeekOrigin.Current: + newPos = readPos_ + offset; + break; + + case SeekOrigin.End: + newPos = end_ + offset; + break; + } + + if ( newPos < start_ ) { + throw new ArgumentException("Negative position is invalid"); + } + + if ( newPos >= end_ ) { + throw new IOException("Cannot seek past end"); + } + readPos_ = newPos; + return readPos_; + } + + /// + /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. + /// + /// An I/O error occurs. + public override void Flush() + { + // Nothing to do. + } + + /// + /// Gets or sets the position within the current stream. + /// + /// + /// The current position within the stream. + /// An I/O error occurs. + /// The stream does not support seeking. + /// Methods were called after the stream was closed. + public override long Position { + get { return readPos_ - start_; } + set { + long newPos = start_ + value; + + if ( newPos < start_ ) { + throw new ArgumentException("Negative position is invalid"); + } + + if ( newPos >= end_ ) { + throw new InvalidOperationException("Cannot seek past end"); + } + readPos_ = newPos; + } + } + + /// + /// Gets the length in bytes of the stream. + /// + /// + /// A long value representing the length of the stream in bytes. + /// A class derived from Stream does not support seeking. + /// Methods were called after the stream was closed. + public override long Length { + get { return length_; } + } + + /// + /// Gets a value indicating whether the current stream supports writing. + /// + /// false + /// true if the stream supports writing; otherwise, false. + public override bool CanWrite { + get { return false; } + } + + /// + /// Gets a value indicating whether the current stream supports seeking. + /// + /// true + /// true if the stream supports seeking; otherwise, false. + public override bool CanSeek { + get { return true; } + } + + /// + /// Gets a value indicating whether the current stream supports reading. + /// + /// true. + /// true if the stream supports reading; otherwise, false. + public override bool CanRead { + get { return true; } + } + +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + /// + /// Gets a value that determines whether the current stream can time out. + /// + /// + /// A value that determines whether the current stream can time out. + public override bool CanTimeout { + get { return baseStream_.CanTimeout; } + } +#endif + #region Instance Fields + ZipFile zipFile_; + Stream baseStream_; + long start_; + long length_; + long readPos_; + long end_; + #endregion + } + #endregion + } + + #endregion + + #region DataSources + /// + /// Provides a static way to obtain a source of data for an entry. + /// + public interface IStaticDataSource + { + /// + /// Get a source of data by creating a new stream. + /// + /// Returns a to use for compression input. + /// Ideally a new stream is created and opened to achieve this, to avoid locking problems. + Stream GetSource(); + } + + /// + /// Represents a source of data that can dynamically provide + /// multiple data sources based on the parameters passed. + /// + public interface IDynamicDataSource + { + /// + /// Get a data source. + /// + /// The to get a source for. + /// The name for data if known. + /// Returns a to use for compression input. + /// Ideally a new stream is created and opened to achieve this, to avoid locking problems. + Stream GetSource(ZipEntry entry, string name); + } + + /// + /// Default implementation of a for use with files stored on disk. + /// + public class StaticDiskDataSource : IStaticDataSource + { + /// + /// Initialise a new instnace of + /// + /// The name of the file to obtain data from. + public StaticDiskDataSource(string fileName) + { + fileName_ = fileName; + } + + #region IDataSource Members + + /// + /// Get a providing data. + /// + /// Returns a provising data. + public Stream GetSource() + { + return File.Open(fileName_, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + #endregion + #region Instance Fields + string fileName_; + #endregion + } + + + /// + /// Default implementation of for files stored on disk. + /// + public class DynamicDiskDataSource : IDynamicDataSource + { + /// + /// Initialise a default instance of . + /// + public DynamicDiskDataSource() + { + } + + #region IDataSource Members + /// + /// Get a providing data for an entry. + /// + /// The entry to provide data for. + /// The file name for data if known. + /// Returns a stream providing data; or null if not available + public Stream GetSource(ZipEntry entry, string name) + { + Stream result = null; + + if ( name != null ) { + result = File.Open(name, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + return result; + } + + #endregion + } + + #endregion + + #region Archive Storage + /// + /// Defines facilities for data storage when updating Zip Archives. + /// + public interface IArchiveStorage + { + /// + /// Get the to apply during updates. + /// + FileUpdateMode UpdateMode { get; } + + /// + /// Get an empty that can be used for temporary output. + /// + /// Returns a temporary output + /// + Stream GetTemporaryOutput(); + + /// + /// Convert a temporary output stream to a final stream. + /// + /// The resulting final + /// + Stream ConvertTemporaryToFinal(); + + /// + /// Make a temporary copy of the original stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + Stream MakeTemporaryCopy(Stream stream); + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The current stream. + /// Returns a stream suitable for direct updating. + /// This may be the current stream passed. + Stream OpenForDirectUpdate(Stream stream); + + /// + /// Dispose of this instance. + /// + void Dispose(); + } + + /// + /// An abstract suitable for extension by inheritance. + /// + abstract public class BaseArchiveStorage : IArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The update mode. + protected BaseArchiveStorage(FileUpdateMode updateMode) + { + updateMode_ = updateMode; + } + #endregion + + #region IArchiveStorage Members + + /// + /// Gets a temporary output + /// + /// Returns the temporary output stream. + /// + public abstract Stream GetTemporaryOutput(); + + /// + /// Converts the temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + /// + public abstract Stream ConvertTemporaryToFinal(); + + /// + /// Make a temporary copy of a . + /// + /// The to make a copy of. + /// Returns a temporary output that is a copy of the input. + public abstract Stream MakeTemporaryCopy(Stream stream); + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The to open for direct update. + /// Returns a stream suitable for direct updating. + public abstract Stream OpenForDirectUpdate(Stream stream); + + /// + /// Disposes this instance. + /// + public abstract void Dispose(); + + /// + /// Gets the update mode applicable. + /// + /// The update mode. + public FileUpdateMode UpdateMode + { + get { + return updateMode_; + } + } + + #endregion + + #region Instance Fields + FileUpdateMode updateMode_; + #endregion + } + + /// + /// An implementation suitable for hard disks. + /// + public class DiskArchiveStorage : BaseArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + /// The file. + /// The update mode. + public DiskArchiveStorage(ZipFile file, FileUpdateMode updateMode) + : base(updateMode) + { + if ( file.Name == null ) { + throw new ZipException("Cant handle non file archives"); + } + + fileName_ = file.Name; + } + + /// + /// Initializes a new instance of the class. + /// + /// The file. + public DiskArchiveStorage(ZipFile file) + : this(file, FileUpdateMode.Safe) + { + } + #endregion + + #region IArchiveStorage Members + + /// + /// Gets a temporary output for performing updates on. + /// + /// Returns the temporary output stream. + public override Stream GetTemporaryOutput() + { + if ( temporaryName_ != null ) { + temporaryName_ = GetTempFileName(temporaryName_, true); + temporaryStream_ = File.Open(temporaryName_, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + else { + // Determine where to place files based on internal strategy. + // Currently this is always done in system temp directory. + temporaryName_ = Path.GetTempFileName(); + temporaryStream_ = File.Open(temporaryName_, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + } + + return temporaryStream_; + } + + /// + /// Converts a temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + public override Stream ConvertTemporaryToFinal() + { + if ( temporaryStream_ == null ) { + throw new ZipException("No temporary stream has been created"); + } + + Stream result = null; + + string moveTempName = GetTempFileName(fileName_, false); + bool newFileCreated = false; + + try { + temporaryStream_.Close(); + File.Move(fileName_, moveTempName); + File.Move(temporaryName_, fileName_); + newFileCreated = true; + File.Delete(moveTempName); + + result = File.Open(fileName_, FileMode.Open, FileAccess.Read, FileShare.Read); + } + catch(Exception) { + result = null; + + // Try to roll back changes... + if ( !newFileCreated ) { + File.Move(moveTempName, fileName_); + File.Delete(temporaryName_); + } + + throw; + } + + return result; + } + + /// + /// Make a temporary copy of a stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + public override Stream MakeTemporaryCopy(Stream stream) + { + stream.Close(); + + temporaryName_ = GetTempFileName(fileName_, true); + File.Copy(fileName_, temporaryName_, true); + + temporaryStream_ = new FileStream(temporaryName_, + FileMode.Open, + FileAccess.ReadWrite); + return temporaryStream_; + } + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The current stream. + /// Returns a stream suitable for direct updating. + /// If the stream is not null this is used as is. + public override Stream OpenForDirectUpdate(Stream stream) + { + Stream result; + if ((stream == null) || !stream.CanWrite) + { + if (stream != null) { + stream.Close(); + } + + result = new FileStream(fileName_, + FileMode.Open, + FileAccess.ReadWrite); + } + else + { + result = stream; + } + + return result; + } + + /// + /// Disposes this instance. + /// + public override void Dispose() + { + if ( temporaryStream_ != null ) { + temporaryStream_.Close(); + } + } + + #endregion + + #region Internal routines + static string GetTempFileName(string original, bool makeTempFile) + { + string result = null; + + if ( original == null ) { + result = Path.GetTempFileName(); + } + else { + int counter = 0; + int suffixSeed = DateTime.Now.Second; + + while ( result == null ) { + counter += 1; + string newName = string.Format("{0}.{1}{2}.tmp", original, suffixSeed, counter); + if ( !File.Exists(newName) ) { + if ( makeTempFile) { + try { + // Try and create the file. + using ( FileStream stream = File.Create(newName) ) { + } + result = newName; + } + catch { + suffixSeed = DateTime.Now.Second; + } + } + else { + result = newName; + } + } + } + } + return result; + } + #endregion + + #region Instance Fields + Stream temporaryStream_; + string fileName_; + string temporaryName_; + #endregion + } + + /// + /// An implementation suitable for in memory streams. + /// + public class MemoryArchiveStorage : BaseArchiveStorage + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + public MemoryArchiveStorage() + : base(FileUpdateMode.Direct) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The to use + /// This constructor is for testing as memory streams dont really require safe mode. + public MemoryArchiveStorage(FileUpdateMode updateMode) + : base(updateMode) + { + } + + #endregion + + #region Properties + /// + /// Get the stream returned by if this was in fact called. + /// + public MemoryStream FinalStream + { + get { return finalStream_; } + } + + #endregion + + #region IArchiveStorage Members + + /// + /// Gets the temporary output + /// + /// Returns the temporary output stream. + public override Stream GetTemporaryOutput() + { + temporaryStream_ = new MemoryStream(); + return temporaryStream_; + } + + /// + /// Converts the temporary to its final form. + /// + /// Returns a that can be used to read + /// the final storage for the archive. + public override Stream ConvertTemporaryToFinal() + { + if ( temporaryStream_ == null ) { + throw new ZipException("No temporary stream has been created"); + } + + finalStream_ = new MemoryStream(temporaryStream_.ToArray()); + return finalStream_; + } + + /// + /// Make a temporary copy of the original stream. + /// + /// The to copy. + /// Returns a temporary output that is a copy of the input. + public override Stream MakeTemporaryCopy(Stream stream) + { + temporaryStream_ = new MemoryStream(); + stream.Position = 0; + StreamUtils.Copy(stream, temporaryStream_, new byte[4096]); + return temporaryStream_; + } + + /// + /// Return a stream suitable for performing direct updates on the original source. + /// + /// The original source stream + /// Returns a stream suitable for direct updating. + /// If the passed is not null this is used; + /// otherwise a new is returned. + public override Stream OpenForDirectUpdate(Stream stream) + { + Stream result; + if ((stream == null) || !stream.CanWrite) { + + result = new MemoryStream(); + + if (stream != null) { + stream.Position = 0; + StreamUtils.Copy(stream, result, new byte[4096]); + + stream.Close(); + } + } + else { + result = stream; + } + + return result; + } + + /// + /// Disposes this instance. + /// + public override void Dispose() + { + if ( temporaryStream_ != null ) { + temporaryStream_.Close(); + } + } + + #endregion + + #region Instance Fields + MemoryStream temporaryStream_; + MemoryStream finalStream_; + #endregion + } + + #endregion +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipHelperStream.cs b/类库/VersionUpdate/ZIP/Zip/ZipHelperStream.cs new file mode 100644 index 0000000..1998b72 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipHelperStream.cs @@ -0,0 +1,624 @@ +// ZipHelperStream.cs +// +// Copyright 2006, 2007 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +using ICSharpCode.SharpZipLib.Zip1; +using System; +using System.IO; +using System.Text; + +namespace ICSharpCode.SharpZipLib.Zip +{ + + /// + /// Holds data pertinent to a data descriptor. + /// + public class DescriptorData + { + /// + /// Get /set the compressed size of data. + /// + public long CompressedSize + { + get { return compressedSize; } + set { compressedSize = value; } + } + + /// + /// Get / set the uncompressed size of data + /// + public long Size + { + get { return size; } + set { size = value; } + } + + /// + /// Get /set the crc value. + /// + public long Crc + { + get { return crc; } + set { crc = (value & 0xffffffff); } + } + + #region Instance Fields + long size; + long compressedSize; + long crc; + #endregion + } + + class EntryPatchData + { + public long SizePatchOffset + { + get { return sizePatchOffset_; } + set { sizePatchOffset_ = value; } + } + + public long CrcPatchOffset + { + get { return crcPatchOffset_; } + set { crcPatchOffset_ = value; } + } + + #region Instance Fields + long sizePatchOffset_; + long crcPatchOffset_; + #endregion + } + + /// + /// This class assists with writing/reading from Zip files. + /// + internal class ZipHelperStream : Stream + { + #region Constructors + /// + /// Initialise an instance of this class. + /// + /// The name of the file to open. + public ZipHelperStream(string name) + { + stream_ = new FileStream(name, FileMode.Open, FileAccess.ReadWrite); + isOwner_ = true; + } + + /// + /// Initialise a new instance of . + /// + /// The stream to use. + public ZipHelperStream(Stream stream) + { + stream_ = stream; + } + #endregion + + /// + /// Get / set a value indicating wether the the underlying stream is owned or not. + /// + /// If the stream is owned it is closed when this instance is closed. + public bool IsStreamOwner + { + get { return isOwner_; } + set { isOwner_ = value; } + } + + #region Base Stream Methods + public override bool CanRead + { + get { return stream_.CanRead; } + } + + public override bool CanSeek + { + get { return stream_.CanSeek; } + } + +#if !NET_1_0 && !NET_1_1 && !NETCF_1_0 + public override bool CanTimeout + { + get { return stream_.CanTimeout; } + } +#endif + + public override long Length + { + get { return stream_.Length; } + } + + public override long Position + { + get { return stream_.Position; } + set { stream_.Position = value; } + } + + public override bool CanWrite + { + get { return stream_.CanWrite; } + } + + public override void Flush() + { + stream_.Flush(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + return stream_.Seek(offset, origin); + } + + public override void SetLength(long value) + { + stream_.SetLength(value); + } + + public override int Read(byte[] buffer, int offset, int count) + { + return stream_.Read(buffer, offset, count); + } + + public override void Write(byte[] buffer, int offset, int count) + { + stream_.Write(buffer, offset, count); + } + + /// + /// Close the stream. + /// + /// + /// The underlying stream is closed only if is true. + /// + override public void Close() + { + Stream toClose = stream_; + stream_ = null; + if (isOwner_ && (toClose != null)) + { + isOwner_ = false; + toClose.Close(); + } + } + #endregion + + // Write the local file header + // TODO: ZipHelperStream.WriteLocalHeader is not yet used and needs checking for ZipFile and ZipOuptutStream usage + void WriteLocalHeader(ZipEntry entry, EntryPatchData patchData) + { + CompressionMethod method = entry.CompressionMethod; + bool headerInfoAvailable = true; // How to get this? + bool patchEntryHeader = false; + + WriteLEInt(ZipConstants.LocalHeaderSignature); + + WriteLEShort(entry.Version); + WriteLEShort(entry.Flags); + WriteLEShort((byte)method); + WriteLEInt((int)entry.DosTime); + + if (headerInfoAvailable == true) { + WriteLEInt((int)entry.Crc); + if ( entry.LocalHeaderRequiresZip64 ) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + WriteLEInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize); + WriteLEInt((int)entry.Size); + } + } else { + if (patchData != null) { + patchData.CrcPatchOffset = stream_.Position; + } + WriteLEInt(0); // Crc + + if ( patchData != null ) { + patchData.SizePatchOffset = stream_.Position; + } + + // For local header both sizes appear in Zip64 Extended Information + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + WriteLEInt(-1); + WriteLEInt(-1); + } + else { + WriteLEInt(0); // Compressed size + WriteLEInt(0); // Uncompressed size + } + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xFFFF) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if (entry.LocalHeaderRequiresZip64 && (headerInfoAvailable || patchEntryHeader)) { + ed.StartNewEntry(); + if (headerInfoAvailable) { + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + } + else { + ed.AddLeLong(-1); + ed.AddLeLong(-1); + } + ed.AddNewEntry(1); + + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cant find extra data"); + } + + if ( patchData != null ) { + patchData.SizePatchOffset = ed.CurrentReadIndex; + } + } + else { + ed.Delete(1); + } + + byte[] extra = ed.GetEntryData(); + + WriteLEShort(name.Length); + WriteLEShort(extra.Length); + + if ( name.Length > 0 ) { + stream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + patchData.SizePatchOffset += stream_.Position; + } + + if ( extra.Length > 0 ) { + stream_.Write(extra, 0, extra.Length); + } + } + + /// + /// Locates a block with the desired . + /// + /// The signature to find. + /// Location, marking the end of block. + /// Minimum size of the block. + /// The maximum variable data. + /// Eeturns the offset of the first byte after the signature; -1 if not found + public long LocateBlockWithSignature(int signature, long endLocation, int minimumBlockSize, int maximumVariableData) + { + long pos = endLocation - minimumBlockSize; + if ( pos < 0 ) { + return -1; + } + + long giveUpMarker = Math.Max(pos - maximumVariableData, 0); + + // TODO: This loop could be optimised for speed. + do { + if ( pos < giveUpMarker ) { + return -1; + } + Seek(pos--, SeekOrigin.Begin); + } while ( ReadLEInt() != signature ); + + return Position; + } + + /// + /// Write Zip64 end of central directory records (File header and locator). + /// + /// The number of entries in the central directory. + /// The size of entries in the central directory. + /// The offset of the dentral directory. + public void WriteZip64EndOfCentralDirectory(long noOfEntries, long sizeEntries, long centralDirOffset) + { + long centralSignatureOffset = stream_.Position; + WriteLEInt(ZipConstants.Zip64CentralFileHeaderSignature); + WriteLELong(44); // Size of this record (total size of remaining fields in header or full size - 12) + WriteLEShort(ZipConstants.VersionMadeBy); // Version made by + WriteLEShort(ZipConstants.VersionZip64); // Version to extract + WriteLEInt(0); // Number of this disk + WriteLEInt(0); // number of the disk with the start of the central directory + WriteLELong(noOfEntries); // No of entries on this disk + WriteLELong(noOfEntries); // Total No of entries in central directory + WriteLELong(sizeEntries); // Size of the central directory + WriteLELong(centralDirOffset); // offset of start of central directory + // zip64 extensible data sector not catered for here (variable size) + + // Write the Zip64 end of central directory locator + WriteLEInt(ZipConstants.Zip64CentralDirLocatorSignature); + + // no of the disk with the start of the zip64 end of central directory + WriteLEInt(0); + + // relative offset of the zip64 end of central directory record + WriteLELong(centralSignatureOffset); + + // total number of disks + WriteLEInt(1); + } + + /// + /// Write the required records to end the central directory. + /// + /// The number of entries in the directory. + /// The size of the entries in the directory. + /// The start of the central directory. + /// The archive comment. (This can be null). + public void WriteEndOfCentralDirectory(long noOfEntries, long sizeEntries, + long startOfCentralDirectory, byte[] comment) + { + + if ( (noOfEntries >= 0xffff) || + (startOfCentralDirectory >= 0xffffffff) || + (sizeEntries >= 0xffffffff) ) { + WriteZip64EndOfCentralDirectory(noOfEntries, sizeEntries, startOfCentralDirectory); + } + + WriteLEInt(ZipConstants.EndOfCentralDirectorySignature); + + // TODO: ZipFile Multi disk handling not done + WriteLEShort(0); // number of this disk + WriteLEShort(0); // no of disk with start of central dir + + + // Number of entries + if ( noOfEntries >= 0xffff ) { + WriteLEUshort(0xffff); // Zip64 marker + WriteLEUshort(0xffff); + } + else { + WriteLEShort(( short )noOfEntries); // entries in central dir for this disk + WriteLEShort(( short )noOfEntries); // total entries in central directory + } + + // Size of the central directory + if ( sizeEntries >= 0xffffffff ) { + WriteLEUint(0xffffffff); // Zip64 marker + } + else { + WriteLEInt(( int )sizeEntries); + } + + + // offset of start of central directory + if ( startOfCentralDirectory >= 0xffffffff ) { + WriteLEUint(0xffffffff); // Zip64 marker + } + else { + WriteLEInt(( int )startOfCentralDirectory); + } + + int commentLength = (comment != null) ? comment.Length : 0; + + if ( commentLength > 0xffff ) { + throw new ZipException(string.Format("Comment length({0}) is too long can only be 64K", commentLength)); + } + + WriteLEShort(commentLength); + + if ( commentLength > 0 ) { + Write(comment, 0, comment.Length); + } + } + + #region LE value reading/writing + /// + /// Read an unsigned short in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + public int ReadLEShort() + { + int byteValue1 = stream_.ReadByte(); + + if (byteValue1 < 0) { + throw new EndOfStreamException(); + } + + int byteValue2 = stream_.ReadByte(); + if (byteValue2 < 0) { + throw new EndOfStreamException(); + } + + return byteValue1 | (byteValue2 << 8); + } + + /// + /// Read an int in little endian byte order. + /// + /// Returns the value read. + /// + /// An i/o error occurs. + /// + /// + /// The file ends prematurely + /// + public int ReadLEInt() + { + return ReadLEShort() | (ReadLEShort() << 16); + } + + /// + /// Read a long in little endian byte order. + /// + /// The value read. + public long ReadLELong() + { + return (uint)ReadLEInt() | ((long)ReadLEInt() << 32); + } + + /// + /// Write an unsigned short in little endian byte order. + /// + /// The value to write. + public void WriteLEShort(int value) + { + stream_.WriteByte(( byte )(value & 0xff)); + stream_.WriteByte(( byte )((value >> 8) & 0xff)); + } + + /// + /// Write a ushort in little endian byte order. + /// + /// The value to write. + public void WriteLEUshort(ushort value) + { + stream_.WriteByte(( byte )(value & 0xff)); + stream_.WriteByte(( byte )(value >> 8)); + } + + /// + /// Write an int in little endian byte order. + /// + /// The value to write. + public void WriteLEInt(int value) + { + WriteLEShort(value); + WriteLEShort(value >> 16); + } + + /// + /// Write a uint in little endian byte order. + /// + /// The value to write. + public void WriteLEUint(uint value) + { + WriteLEUshort(( ushort )(value & 0xffff)); + WriteLEUshort(( ushort )(value >> 16)); + } + + /// + /// Write a long in little endian byte order. + /// + /// The value to write. + public void WriteLELong(long value) + { + WriteLEInt(( int )value); + WriteLEInt(( int )(value >> 32)); + } + + /// + /// Write a ulong in little endian byte order. + /// + /// The value to write. + public void WriteLEUlong(ulong value) + { + WriteLEUint(( uint )(value & 0xffffffff)); + WriteLEUint(( uint )(value >> 32)); + } + + #endregion + + /// + /// Write a data descriptor. + /// + /// The entry to write a descriptor for. + /// Returns the number of descriptor bytes written. + public int WriteDataDescriptor(ZipEntry entry) + { + if (entry == null) { + throw new ArgumentNullException("entry"); + } + + int result=0; + + // Add data descriptor if flagged as required + if ((entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) + { + // The signature is not PKZIP originally but is now described as optional + // in the PKZIP Appnote documenting trhe format. + WriteLEInt(ZipConstants.DataDescriptorSignature); + WriteLEInt(unchecked((int)(entry.Crc))); + + result+=8; + + if (entry.LocalHeaderRequiresZip64) + { + WriteLELong(entry.CompressedSize); + WriteLELong(entry.Size); + result+=16; + } + else + { + WriteLEInt((int)entry.CompressedSize); + WriteLEInt((int)entry.Size); + result+=8; + } + } + + return result; + } + + /// + /// Read data descriptor at the end of compressed data. + /// + /// if set to true [zip64]. + /// The data to fill in. + /// Returns the number of bytes read in the descriptor. + public void ReadDataDescriptor(bool zip64, DescriptorData data) + { + int intValue = ReadLEInt(); + + // In theory this may not be a descriptor according to PKZIP appnote. + // In practise its always there. + if (intValue != ZipConstants.DataDescriptorSignature) { + throw new ZipException("Data descriptor signature not found"); + } + + data.Crc = ReadLEInt(); + + if (zip64) { + data.CompressedSize = ReadLELong(); + data.Size = ReadLELong(); + } + else { + data.CompressedSize = ReadLEInt(); + data.Size = ReadLEInt(); + } + } + + #region Instance Fields + bool isOwner_; + Stream stream_; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipInputStream.cs b/类库/VersionUpdate/ZIP/Zip/ZipInputStream.cs new file mode 100644 index 0000000..9c00125 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipInputStream.cs @@ -0,0 +1,676 @@ +// ZipInputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 2010-05-25 Z-1663 Fixed exception when testing local header compressed size of -1 + +using System; +using System.IO; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using ICSharpCode.SharpZipLib.Zip; + +#if !NETCF_1_0 +using ICSharpCode.SharpZipLib.Encryption; +#endif + +namespace ICSharpCode.SharpZipLib.Zip1 +{ + /// + /// This is an InflaterInputStream that reads the files baseInputStream an zip archive + /// one after another. It has a special method to get the zip entry of + /// the next file. The zip entry contains information about the file name + /// size, compressed size, Crc, etc. + /// It includes support for Stored and Deflated entries. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// + /// This sample shows how to read a zip file + /// + /// using System; + /// using System.Text; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// using ( ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]))) { + /// + /// ZipEntry theEntry; + /// const int size = 2048; + /// byte[] data = new byte[2048]; + /// + /// while ((theEntry = s.GetNextEntry()) != null) { + /// if ( entry.IsFile ) { + /// Console.Write("Show contents (y/n) ?"); + /// if (Console.ReadLine() == "y") { + /// while (true) { + /// size = s.Read(data, 0, data.Length); + /// if (size > 0) { + /// Console.Write(new ASCIIEncoding().GetString(data, 0, size)); + /// } else { + /// break; + /// } + /// } + /// } + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipInputStream : InflaterInputStream + { + #region Instance Fields + + /// + /// Delegate for reading bytes from a stream. + /// + delegate int ReadDataHandler(byte[] b, int offset, int length); + + /// + /// The current reader this instance. + /// + ReadDataHandler internalReader; + + Crc32 crc = new Crc32(); + ZipEntry entry; + + long size; + int method; + int flags; + string password; + #endregion + + #region Constructors + /// + /// Creates a new Zip input stream, for reading a zip archive. + /// + /// The underlying providing data. + public ZipInputStream(Stream baseInputStream) + : base(baseInputStream, new Inflater(true)) + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + } + + /// + /// Creates a new Zip input stream, for reading a zip archive. + /// + /// The underlying providing data. + /// Size of the buffer. + public ZipInputStream( Stream baseInputStream, int bufferSize ) + : base(baseInputStream, new Inflater(true), bufferSize) + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + } + #endregion + + /// + /// Optional password used for encryption when non-null + /// + /// A password for all encrypted entries in this + public string Password + { + get { + return password; + } + set { + password = value; + } + } + + + /// + /// Gets a value indicating if there is a current entry and it can be decompressed + /// + /// + /// The entry can only be decompressed if the library supports the zip features required to extract it. + /// See the ZipEntry Version property for more details. + /// + public bool CanDecompressEntry { + get { + return (entry != null) && entry.CanDecompress; + } + } + + /// + /// Advances to the next entry in the archive + /// + /// + /// The next entry in the archive or null if there are no more entries. + /// + /// + /// If the previous entry is still open CloseEntry is called. + /// + /// + /// Input stream is closed + /// + /// + /// Password is not set, password is invalid, compression method is invalid, + /// version required to extract is not supported + /// + public ZipEntry GetNextEntry() + { + if (crc == null) { + throw new InvalidOperationException("Closed."); + } + + if (entry != null) { + CloseEntry(); + } + + int header = inputBuffer.ReadLeInt(); + + if (header == ZipConstants.CentralHeaderSignature || + header == ZipConstants.EndOfCentralDirectorySignature || + header == ZipConstants.CentralHeaderDigitalSignature || + header == ZipConstants.ArchiveExtraDataSignature || + header == ZipConstants.Zip64CentralFileHeaderSignature) { + // No more individual entries exist + Close(); + return null; + } + + // -jr- 07-Dec-2003 Ignore spanning temporary signatures if found + // Spanning signature is same as descriptor signature and is untested as yet. + if ( (header == ZipConstants.SpanningTempSignature) || (header == ZipConstants.SpanningSignature) ) { + header = inputBuffer.ReadLeInt(); + } + + if (header != ZipConstants.LocalHeaderSignature) { + throw new ZipException("Wrong Local header signature: 0x" + String.Format("{0:X}", header)); + } + + short versionRequiredToExtract = (short)inputBuffer.ReadLeShort(); + + flags = inputBuffer.ReadLeShort(); + method = inputBuffer.ReadLeShort(); + uint dostime = (uint)inputBuffer.ReadLeInt(); + int crc2 = inputBuffer.ReadLeInt(); + csize = inputBuffer.ReadLeInt(); + size = inputBuffer.ReadLeInt(); + int nameLen = inputBuffer.ReadLeShort(); + int extraLen = inputBuffer.ReadLeShort(); + + bool isCrypted = (flags & 1) == 1; + + byte[] buffer = new byte[nameLen]; + inputBuffer.ReadRawBuffer(buffer); + + string name = ZipConstants.ConvertToStringExt(flags, buffer); + + entry = new ZipEntry(name, versionRequiredToExtract); + entry.Flags = flags; + + entry.CompressionMethod = (CompressionMethod)method; + + if ((flags & 8) == 0) { + entry.Crc = crc2 & 0xFFFFFFFFL; + entry.Size = size & 0xFFFFFFFFL; + entry.CompressedSize = csize & 0xFFFFFFFFL; + + entry.CryptoCheckValue = (byte)((crc2 >> 24) & 0xff); + + } else { + + // This allows for GNU, WinZip and possibly other archives, the PKZIP spec + // says these values are zero under these circumstances. + if (crc2 != 0) { + entry.Crc = crc2 & 0xFFFFFFFFL; + } + + if (size != 0) { + entry.Size = size & 0xFFFFFFFFL; + } + + if (csize != 0) { + entry.CompressedSize = csize & 0xFFFFFFFFL; + } + + entry.CryptoCheckValue = (byte)((dostime >> 8) & 0xff); + } + + entry.DosTime = dostime; + + // If local header requires Zip64 is true then the extended header should contain + // both values. + + // Handle extra data if present. This can set/alter some fields of the entry. + if (extraLen > 0) { + byte[] extra = new byte[extraLen]; + inputBuffer.ReadRawBuffer(extra); + entry.ExtraData = extra; + } + + entry.ProcessExtraData(true); + if ( entry.CompressedSize >= 0 ) { + csize = entry.CompressedSize; + } + + if ( entry.Size >= 0 ) { + size = entry.Size; + } + + if (method == (int)CompressionMethod.Stored && (!isCrypted && csize != size || (isCrypted && csize - ZipConstants.CryptoHeaderSize != size))) { + throw new ZipException("Stored, but compressed != uncompressed"); + } + + // Determine how to handle reading of data if this is attempted. + if (entry.IsCompressionMethodSupported()) { + internalReader = new ReadDataHandler(InitialRead); + } else { + internalReader = new ReadDataHandler(ReadingNotSupported); + } + + return entry; + } + + /// + /// Read data descriptor at the end of compressed data. + /// + void ReadDataDescriptor() + { + if (inputBuffer.ReadLeInt() != ZipConstants.DataDescriptorSignature) { + throw new ZipException("Data descriptor signature not found"); + } + + entry.Crc = inputBuffer.ReadLeInt() & 0xFFFFFFFFL; + + if ( entry.LocalHeaderRequiresZip64 ) { + csize = inputBuffer.ReadLeLong(); + size = inputBuffer.ReadLeLong(); + } else { + csize = inputBuffer.ReadLeInt(); + size = inputBuffer.ReadLeInt(); + } + entry.CompressedSize = csize; + entry.Size = size; + } + + /// + /// Complete cleanup as the final part of closing. + /// + /// True if the crc value should be tested + void CompleteCloseEntry(bool testCrc) + { + StopDecrypting(); + + if ((flags & 8) != 0) { + ReadDataDescriptor(); + } + + size = 0; + + if ( testCrc && + ((crc.Value & 0xFFFFFFFFL) != entry.Crc) && (entry.Crc != -1)) { + throw new ZipException("CRC mismatch"); + } + + crc.Reset(); + + if (method == (int)CompressionMethod.Deflated) { + inf.Reset(); + } + entry = null; + } + + /// + /// Closes the current zip entry and moves to the next one. + /// + /// + /// The stream is closed + /// + /// + /// The Zip stream ends early + /// + public void CloseEntry() + { + if (crc == null) { + throw new InvalidOperationException("Closed"); + } + + if (entry == null) { + return; + } + + if (method == (int)CompressionMethod.Deflated) { + if ((flags & 8) != 0) { + // We don't know how much we must skip, read until end. + byte[] tmp = new byte[4096]; + + // Read will close this entry + while (Read(tmp, 0, tmp.Length) > 0) { + } + return; + } + + csize -= inf.TotalIn; + inputBuffer.Available += inf.RemainingInput; + } + + if ( (inputBuffer.Available > csize) && (csize >= 0) ) { + inputBuffer.Available = (int)((long)inputBuffer.Available - csize); + } else { + csize -= inputBuffer.Available; + inputBuffer.Available = 0; + while (csize != 0) { + long skipped = base.Skip(csize); + + if (skipped <= 0) { + throw new ZipException("Zip archive ends early."); + } + + csize -= skipped; + } + } + + CompleteCloseEntry(false); + } + + /// + /// Returns 1 if there is an entry available + /// Otherwise returns 0. + /// + public override int Available { + get { + return entry != null ? 1 : 0; + } + } + + /// + /// Returns the current size that can be read from the current entry if available + /// + /// Thrown if the entry size is not known. + /// Thrown if no entry is currently available. + public override long Length + { + get { + if ( entry != null ) { + if ( entry.Size >= 0 ) { + return entry.Size; + } else { + throw new ZipException("Length not available for the current entry"); + } + } + else { + throw new InvalidOperationException("No current entry"); + } + } + + } + + /// + /// Reads a byte from the current zip entry. + /// + /// + /// The byte or -1 if end of stream is reached. + /// + public override int ReadByte() + { + byte[] b = new byte[1]; + if (Read(b, 0, 1) <= 0) { + return -1; + } + return b[0] & 0xff; + } + + /// + /// Handle attempts to read by throwing an . + /// + /// The destination array to store data in. + /// The offset at which data read should be stored. + /// The maximum number of bytes to read. + /// Returns the number of bytes actually read. + int ReadingNotAvailable(byte[] destination, int offset, int count) + { + throw new InvalidOperationException("Unable to read from this stream"); + } + + /// + /// Handle attempts to read from this entry by throwing an exception + /// + int ReadingNotSupported(byte[] destination, int offset, int count) + { + throw new ZipException("The compression method for this entry is not supported"); + } + + /// + /// Perform the initial read on an entry which may include + /// reading encryption headers and setting up inflation. + /// + /// The destination to fill with data read. + /// The offset to start reading at. + /// The maximum number of bytes to read. + /// The actual number of bytes read. + int InitialRead(byte[] destination, int offset, int count) + { + if ( !CanDecompressEntry ) { + throw new ZipException("Library cannot extract this entry. Version required is (" + entry.Version.ToString() + ")"); + } + + // Handle encryption if required. + if (entry.IsCrypted) { +#if NETCF_1_0 + throw new ZipException("Encryption not supported for Compact Framework 1.0"); +#else + if (password == null) { + throw new ZipException("No password set."); + } + + // Generate and set crypto transform... + PkzipClassicManaged managed = new PkzipClassicManaged(); + byte[] key = PkzipClassic.GenerateKeys(ZipConstants.ConvertToArray(password)); + + inputBuffer.CryptoTransform = managed.CreateDecryptor(key, null); + + byte[] cryptbuffer = new byte[ZipConstants.CryptoHeaderSize]; + inputBuffer.ReadClearTextBuffer(cryptbuffer, 0, ZipConstants.CryptoHeaderSize); + + if (cryptbuffer[ZipConstants.CryptoHeaderSize - 1] != entry.CryptoCheckValue) { + throw new ZipException("Invalid password"); + } + + if (csize >= ZipConstants.CryptoHeaderSize) { + csize -= ZipConstants.CryptoHeaderSize; + } + else if ( (entry.Flags & (int)GeneralBitFlags.Descriptor) == 0 ) { + throw new ZipException(string.Format("Entry compressed size {0} too small for encryption", csize)); + } +#endif + } else { +#if !NETCF_1_0 + inputBuffer.CryptoTransform = null; +#endif + } + + if ((csize > 0) || ((flags & (int)GeneralBitFlags.Descriptor) != 0)) { + if ((method == (int)CompressionMethod.Deflated) && (inputBuffer.Available > 0)) { + inputBuffer.SetInflaterInput(inf); + } + + internalReader = new ReadDataHandler(BodyRead); + return BodyRead(destination, offset, count); + } + else { + internalReader = new ReadDataHandler(ReadingNotAvailable); + return 0; + } + } + + /// + /// Read a block of bytes from the stream. + /// + /// The destination for the bytes. + /// The index to start storing data. + /// The number of bytes to attempt to read. + /// Returns the number of bytes read. + /// Zero bytes read means end of stream. + public override int Read(byte[] buffer, int offset, int count) + { + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (buffer.Length - offset) < count ) { + throw new ArgumentException("Invalid offset/count combination"); + } + + return internalReader(buffer, offset, count); + } + + /// + /// Reads a block of bytes from the current zip entry. + /// + /// + /// The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. + /// + /// + /// An i/o error occured. + /// + /// + /// The deflated stream is corrupted. + /// + /// + /// The stream is not open. + /// + int BodyRead(byte[] buffer, int offset, int count) + { + if ( crc == null ) { + throw new InvalidOperationException("Closed"); + } + + if ( (entry == null) || (count <= 0) ) { + return 0; + } + + if ( offset + count > buffer.Length ) { + throw new ArgumentException("Offset + count exceeds buffer size"); + } + + bool finished = false; + + switch (method) { + case (int)CompressionMethod.Deflated: + count = base.Read(buffer, offset, count); + if (count <= 0) { + if (!inf.IsFinished) { + throw new ZipException("Inflater not finished!"); + } + inputBuffer.Available = inf.RemainingInput; + + // A csize of -1 is from an unpatched local header + if ((flags & 8) == 0 && + (inf.TotalIn != csize && csize != 0xFFFFFFFF && csize != -1 || inf.TotalOut != size)) { + throw new ZipException("Size mismatch: " + csize + ";" + size + " <-> " + inf.TotalIn + ";" + inf.TotalOut); + } + inf.Reset(); + finished = true; + } + break; + + case (int)CompressionMethod.Stored: + if ( (count > csize) && (csize >= 0) ) { + count = (int)csize; + } + + if ( count > 0 ) { + count = inputBuffer.ReadClearTextBuffer(buffer, offset, count); + if (count > 0) { + csize -= count; + size -= count; + } + } + + if (csize == 0) { + finished = true; + } else { + if (count < 0) { + throw new ZipException("EOF in stored block"); + } + } + break; + } + + if (count > 0) { + crc.Update(buffer, offset, count); + } + + if (finished) { + CompleteCloseEntry(true); + } + + return count; + } + + /// + /// Closes the zip input stream + /// + public override void Close() + { + internalReader = new ReadDataHandler(ReadingNotAvailable); + crc = null; + entry = null; + + base.Close(); + } + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipNameTransform.cs b/类库/VersionUpdate/ZIP/Zip/ZipNameTransform.cs new file mode 100644 index 0000000..9dc1176 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipNameTransform.cs @@ -0,0 +1,269 @@ +// ZipNameTransform.cs +// +// Copyright 2005 John Reilly +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + + +using System; +using System.IO; +using System.Text; + +using ICSharpCode.SharpZipLib.Core; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// ZipNameTransform transforms names as per the Zip file naming convention. + /// + /// The use of absolute names is supported although its use is not valid + /// according to Zip naming conventions, and should not be used if maximum compatability is desired. + public class ZipNameTransform : INameTransform + { + #region Constructors + /// + /// Initialize a new instance of + /// + public ZipNameTransform() + { + } + + /// + /// Initialize a new instance of + /// + /// The string to trim from the front of paths if found. + public ZipNameTransform(string trimPrefix) + { + TrimPrefix = trimPrefix; + } + #endregion + + /// + /// Static constructor. + /// + static ZipNameTransform() + { + char[] invalidPathChars; +#if NET_1_0 || NET_1_1 || NETCF_1_0 + invalidPathChars = Path.InvalidPathChars; +#else + invalidPathChars = Path.GetInvalidPathChars(); +#endif + int howMany = invalidPathChars.Length + 2; + + InvalidEntryCharsRelaxed = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryCharsRelaxed, 0, invalidPathChars.Length); + InvalidEntryCharsRelaxed[howMany - 1] = '*'; + InvalidEntryCharsRelaxed[howMany - 2] = '?'; + + howMany = invalidPathChars.Length + 4; + InvalidEntryChars = new char[howMany]; + Array.Copy(invalidPathChars, 0, InvalidEntryChars, 0, invalidPathChars.Length); + InvalidEntryChars[howMany - 1] = ':'; + InvalidEntryChars[howMany - 2] = '\\'; + InvalidEntryChars[howMany - 3] = '*'; + InvalidEntryChars[howMany - 4] = '?'; + } + + /// + /// Transform a windows directory name according to the Zip file naming conventions. + /// + /// The directory name to transform. + /// The transformed name. + public string TransformDirectory(string name) + { + name = TransformFile(name); + if (name.Length > 0) { + if ( !name.EndsWith("/") ) { + name += "/"; + } + } + else { + throw new ZipException("Cannot have an empty directory name"); + } + return name; + } + + /// + /// Transform a windows file name according to the Zip file naming conventions. + /// + /// The file name to transform. + /// The transformed name. + public string TransformFile(string name) + { + if (name != null) { + string lowerName = name.ToLower(); + if ( (trimPrefix_ != null) && (lowerName.IndexOf(trimPrefix_) == 0) ) { + name = name.Substring(trimPrefix_.Length); + } + + name = name.Replace(@"\", "/"); + name = WindowsPathUtils.DropPathRoot(name); + + // Drop any leading slashes. + while ((name.Length > 0) && (name[0] == '/')) + { + name = name.Remove(0, 1); + } + + // Drop any trailing slashes. + while ((name.Length > 0) && (name[name.Length - 1] == '/')) + { + name = name.Remove(name.Length - 1, 1); + } + + // Convert consecutive // characters to / + int index = name.IndexOf("//"); + while (index >= 0) + { + name = name.Remove(index, 1); + index = name.IndexOf("//"); + } + + name = MakeValidName(name, '_'); + } + else { + name = string.Empty; + } + return name; + } + + /// + /// Get/set the path prefix to be trimmed from paths if present. + /// + /// The prefix is trimmed before any conversion from + /// a windows path is done. + public string TrimPrefix + { + get { return trimPrefix_; } + set { + trimPrefix_ = value; + if (trimPrefix_ != null) { + trimPrefix_ = trimPrefix_.ToLower(); + } + } + } + + /// + /// Force a name to be valid by replacing invalid characters with a fixed value + /// + /// The name to force valid + /// The replacement character to use. + /// Returns a valid name + static string MakeValidName(string name, char replacement) + { + int index = name.IndexOfAny(InvalidEntryChars); + if (index >= 0) { + StringBuilder builder = new StringBuilder(name); + + while (index >= 0 ) { + builder[index] = replacement; + + if (index >= name.Length) { + index = -1; + } + else { + index = name.IndexOfAny(InvalidEntryChars, index + 1); + } + } + name = builder.ToString(); + } + + if (name.Length > 0xffff) { + throw new PathTooLongException(); + } + + return name; + } + + /// + /// Test a name to see if it is a valid name for a zip entry. + /// + /// The name to test. + /// If true checking is relaxed about windows file names and absolute paths. + /// Returns true if the name is a valid zip name; false otherwise. + /// Zip path names are actually in Unix format, and should only contain relative paths. + /// This means that any path stored should not contain a drive or + /// device letter, or a leading slash. All slashes should forward slashes '/'. + /// An empty name is valid for a file where the input comes from standard input. + /// A null name is not considered valid. + /// + public static bool IsValidName(string name, bool relaxed) + { + bool result = (name != null); + + if ( result ) { + if ( relaxed ) { + result = name.IndexOfAny(InvalidEntryCharsRelaxed) < 0; + } + else { + result = + (name.IndexOfAny(InvalidEntryChars) < 0) && + (name.IndexOf('/') != 0); + } + } + + return result; + } + + /// + /// Test a name to see if it is a valid name for a zip entry. + /// + /// The name to test. + /// Returns true if the name is a valid zip name; false otherwise. + /// Zip path names are actually in unix format, + /// and should only contain relative paths if a path is present. + /// This means that the path stored should not contain a drive or + /// device letter, or a leading slash. All slashes should forward slashes '/'. + /// An empty name is valid where the input comes from standard input. + /// A null name is not considered valid. + /// + public static bool IsValidName(string name) + { + bool result = + (name != null) && + (name.IndexOfAny(InvalidEntryChars) < 0) && + (name.IndexOf('/') != 0) + ; + return result; + } + + #region Instance Fields + string trimPrefix_; + #endregion + + #region Class Fields + static readonly char[] InvalidEntryChars; + static readonly char[] InvalidEntryCharsRelaxed; + #endregion + } +} diff --git a/类库/VersionUpdate/ZIP/Zip/ZipOutputStream.cs b/类库/VersionUpdate/ZIP/Zip/ZipOutputStream.cs new file mode 100644 index 0000000..4f93763 --- /dev/null +++ b/类库/VersionUpdate/ZIP/Zip/ZipOutputStream.cs @@ -0,0 +1,901 @@ +// ZipOutputStream.cs +// +// Copyright (C) 2001 Mike Krueger +// Copyright (C) 2004 John Reilly +// +// This file was translated from java, it was part of the GNU Classpath +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// Linking this library statically or dynamically with other modules is +// making a combined work based on this library. Thus, the terms and +// conditions of the GNU General Public License cover the whole +// combination. +// +// As a special exception, the copyright holders of this library give you +// permission to link this library with independent modules to produce an +// executable, regardless of the license terms of these independent +// modules, and to copy and distribute the resulting executable under +// terms of your choice, provided that you also meet, for each linked +// independent module, the terms and conditions of the license of that +// module. An independent module is a module which is not derived from +// or based on this library. If you modify this library, you may extend +// this exception to your version of the library, but you are not +// obligated to do so. If you do not wish to do so, delete this +// exception statement from your version. + +// HISTORY +// 22-12-2009 Z-1649 Added AES support +// 22-02-2010 Z-1648 Zero byte entries would create invalid zip files + +using System; +using System.IO; +using System.Collections; + +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; +using ICSharpCode.SharpZipLib.Zip1; + +namespace ICSharpCode.SharpZipLib.Zip +{ + /// + /// This is a DeflaterOutputStream that writes the files into a zip + /// archive one after another. It has a special method to start a new + /// zip entry. The zip entries contains information about the file name + /// size, compressed size, CRC, etc. + /// + /// It includes support for Stored and Deflated entries. + /// This class is not thread safe. + ///
+ ///
Author of the original java version : Jochen Hoenicke + ///
+ /// This sample shows how to create a zip file + /// + /// using System; + /// using System.IO; + /// + /// using ICSharpCode.SharpZipLib.Core; + /// using ICSharpCode.SharpZipLib.Zip; + /// + /// class MainClass + /// { + /// public static void Main(string[] args) + /// { + /// string[] filenames = Directory.GetFiles(args[0]); + /// byte[] buffer = new byte[4096]; + /// + /// using ( ZipOutputStream s = new ZipOutputStream(File.Create(args[1])) ) { + /// + /// s.SetLevel(9); // 0 - store only to 9 - means best compression + /// + /// foreach (string file in filenames) { + /// ZipEntry entry = new ZipEntry(file); + /// s.PutNextEntry(entry); + /// + /// using (FileStream fs = File.OpenRead(file)) { + /// StreamUtils.Copy(fs, s, buffer); + /// } + /// } + /// } + /// } + /// } + /// + /// + public class ZipOutputStream : DeflaterOutputStream + { + #region Constructors + /// + /// Creates a new Zip output stream, writing a zip archive. + /// + /// + /// The output stream to which the archive contents are written. + /// + public ZipOutputStream(Stream baseOutputStream) + : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true)) + { + } + + /// + /// Creates a new Zip output stream, writing a zip archive. + /// + /// The output stream to which the archive contents are written. + /// Size of the buffer to use. + public ZipOutputStream( Stream baseOutputStream, int bufferSize ) + : base(baseOutputStream, new Deflater(Deflater.DEFAULT_COMPRESSION, true), bufferSize) + { + } + #endregion + + /// + /// Gets a flag value of true if the central header has been added for this archive; false if it has not been added. + /// + /// No further entries can be added once this has been done. + public bool IsFinished + { + get { + return entries == null; + } + } + + /// + /// Set the zip file comment. + /// + /// + /// The comment text for the entire archive. + /// + /// + /// The converted comment is longer than 0xffff bytes. + /// + public void SetComment(string comment) + { + // TODO: Its not yet clear how to handle unicode comments here. + byte[] commentBytes = ZipConstants.ConvertToArray(comment); + if (commentBytes.Length > 0xffff) { + throw new ArgumentOutOfRangeException("comment"); + } + zipComment = commentBytes; + } + + /// + /// Sets the compression level. The new level will be activated + /// immediately. + /// + /// The new compression level (1 to 9). + /// + /// Level specified is not supported. + /// + /// + public void SetLevel(int level) + { + deflater_.SetLevel(level); + defaultCompressionLevel = level; + } + + /// + /// Get the current deflater compression level + /// + /// The current compression level + public int GetLevel() + { + return deflater_.GetLevel(); + } + + /// + /// Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + /// + /// Older archivers may not understand Zip64 extensions. + /// If backwards compatability is an issue be careful when adding entries to an archive. + /// Setting this property to off is workable but less desirable as in those circumstances adding a file + /// larger then 4GB will fail. + public UseZip64 UseZip64 + { + get { return useZip64_; } + set { useZip64_ = value; } + } + + /// + /// Write an unsigned short in little endian byte order. + /// + private void WriteLeShort(int value) + { + unchecked { + baseOutputStream_.WriteByte((byte)(value & 0xff)); + baseOutputStream_.WriteByte((byte)((value >> 8) & 0xff)); + } + } + + /// + /// Write an int in little endian byte order. + /// + private void WriteLeInt(int value) + { + unchecked { + WriteLeShort(value); + WriteLeShort(value >> 16); + } + } + + /// + /// Write an int in little endian byte order. + /// + private void WriteLeLong(long value) + { + unchecked { + WriteLeInt((int)value); + WriteLeInt((int)(value >> 32)); + } + } + + /// + /// Starts a new Zip entry. It automatically closes the previous + /// entry if present. + /// All entry elements bar name are optional, but must be correct if present. + /// If the compression method is stored and the output is not patchable + /// the compression for that entry is automatically changed to deflate level 0 + /// + /// + /// the entry. + /// + /// + /// if entry passed is null. + /// + /// + /// if an I/O error occured. + /// + /// + /// if stream was finished + /// + /// + /// Too many entries in the Zip file
+ /// Entry name is too long
+ /// Finish has already been called
+ ///
+ public void PutNextEntry(ZipEntry entry) + { + if ( entry == null ) { + throw new ArgumentNullException("entry"); + } + + if (entries == null) { + throw new InvalidOperationException("ZipOutputStream was finished"); + } + + if (curEntry != null) { + CloseEntry(); + } + + if (entries.Count == int.MaxValue) { + throw new ZipException("Too many entries for Zip file"); + } + + CompressionMethod method = entry.CompressionMethod; + int compressionLevel = defaultCompressionLevel; + + // Clear flags that the library manages internally + entry.Flags &= (int)GeneralBitFlags.UnicodeText; + patchEntryHeader = false; + + bool headerInfoAvailable; + + // No need to compress - definitely no data. + if (entry.Size == 0) + { + entry.CompressedSize = entry.Size; + entry.Crc = 0; + method = CompressionMethod.Stored; + headerInfoAvailable = true; + } + else + { + headerInfoAvailable = (entry.Size >= 0) && entry.HasCrc; + + // Switch to deflation if storing isnt possible. + if (method == CompressionMethod.Stored) + { + if (!headerInfoAvailable) + { + if (!CanPatchEntries) + { + // Can't patch entries so storing is not possible. + method = CompressionMethod.Deflated; + compressionLevel = 0; + } + } + else // entry.size must be > 0 + { + entry.CompressedSize = entry.Size; + headerInfoAvailable = entry.HasCrc; + } + } + } + + if (headerInfoAvailable == false) { + if (CanPatchEntries == false) { + // Only way to record size and compressed size is to append a data descriptor + // after compressed data. + + // Stored entries of this form have already been converted to deflating. + entry.Flags |= 8; + } else { + patchEntryHeader = true; + } + } + + if (Password != null) { + entry.IsCrypted = true; + if (entry.Crc < 0) { + // Need to append a data descriptor as the crc isnt available for use + // with encryption, the date is used instead. Setting the flag + // indicates this to the decompressor. + entry.Flags |= 8; + } + } + + entry.Offset = offset; + entry.CompressionMethod = (CompressionMethod)method; + + curMethod = method; + sizePatchPos = -1; + + if ( (useZip64_ == UseZip64.On) || ((entry.Size < 0) && (useZip64_ == UseZip64.Dynamic)) ) { + entry.ForceZip64(); + } + + // Write the local file header + WriteLeInt(ZipConstants.LocalHeaderSignature); + + WriteLeShort(entry.Version); + WriteLeShort(entry.Flags); + WriteLeShort((byte)entry.CompressionMethodForHeader); + WriteLeInt((int)entry.DosTime); + + // TODO: Refactor header writing. Its done in several places. + if (headerInfoAvailable == true) { + WriteLeInt((int)entry.Crc); + if ( entry.LocalHeaderRequiresZip64 ) { + WriteLeInt(-1); + WriteLeInt(-1); + } + else { + WriteLeInt(entry.IsCrypted ? (int)entry.CompressedSize + ZipConstants.CryptoHeaderSize : (int)entry.CompressedSize); + WriteLeInt((int)entry.Size); + } + } else { + if (patchEntryHeader) { + crcPatchPos = baseOutputStream_.Position; + } + WriteLeInt(0); // Crc + + if ( patchEntryHeader ) { + sizePatchPos = baseOutputStream_.Position; + } + + // For local header both sizes appear in Zip64 Extended Information + if ( entry.LocalHeaderRequiresZip64 || patchEntryHeader ) { + WriteLeInt(-1); + WriteLeInt(-1); + } + else { + WriteLeInt(0); // Compressed size + WriteLeInt(0); // Uncompressed size + } + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xFFFF) { + throw new ZipException("Entry name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if (entry.LocalHeaderRequiresZip64) { + ed.StartNewEntry(); + if (headerInfoAvailable) { + ed.AddLeLong(entry.Size); + ed.AddLeLong(entry.CompressedSize); + } + else { + ed.AddLeLong(-1); + ed.AddLeLong(-1); + } + ed.AddNewEntry(1); + + if ( !ed.Find(1) ) { + throw new ZipException("Internal error cant find extra data"); + } + + if ( patchEntryHeader ) { + sizePatchPos = ed.CurrentReadIndex; + } + } + else { + ed.Delete(1); + } + +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + AddExtraDataAES(entry, ed); + } +#endif + byte[] extra = ed.GetEntryData(); + + WriteLeShort(name.Length); + WriteLeShort(extra.Length); + + if ( name.Length > 0 ) { + baseOutputStream_.Write(name, 0, name.Length); + } + + if ( entry.LocalHeaderRequiresZip64 && patchEntryHeader ) { + sizePatchPos += baseOutputStream_.Position; + } + + if ( extra.Length > 0 ) { + baseOutputStream_.Write(extra, 0, extra.Length); + } + + offset += ZipConstants.LocalHeaderBaseSize + name.Length + extra.Length; + // Fix offsetOfCentraldir for AES + if (entry.AESKeySize > 0) + offset += entry.AESOverheadSize; + + // Activate the entry. + curEntry = entry; + crc.Reset(); + if (method == CompressionMethod.Deflated) { + deflater_.Reset(); + deflater_.SetLevel(compressionLevel); + } + size = 0; + + if (entry.IsCrypted) { +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + WriteAESHeader(entry); + } else +#endif + { + if (entry.Crc < 0) { // so testing Zip will says its ok + WriteEncryptionHeader(entry.DosTime << 16); + } else { + WriteEncryptionHeader(entry.Crc); + } + } + } + } + + /// + /// Closes the current entry, updating header and footer information as required + /// + /// + /// An I/O error occurs. + /// + /// + /// No entry is active. + /// + public void CloseEntry() + { + if (curEntry == null) { + throw new InvalidOperationException("No open entry"); + } + + long csize = size; + + // First finish the deflater, if appropriate + if (curMethod == CompressionMethod.Deflated) { + if (size >= 0) { + base.Finish(); + csize = deflater_.TotalOut; + } + else { + deflater_.Reset(); + } + } + + // Write the AES Authentication Code (a hash of the compressed and encrypted data) + if (curEntry.AESKeySize > 0) { + baseOutputStream_.Write(AESAuthCode, 0, 10); + } + + if (curEntry.Size < 0) { + curEntry.Size = size; + } else if (curEntry.Size != size) { + throw new ZipException("size was " + size + ", but I expected " + curEntry.Size); + } + + if (curEntry.CompressedSize < 0) { + curEntry.CompressedSize = csize; + } else if (curEntry.CompressedSize != csize) { + throw new ZipException("compressed size was " + csize + ", but I expected " + curEntry.CompressedSize); + } + + if (curEntry.Crc < 0) { + curEntry.Crc = crc.Value; + } else if (curEntry.Crc != crc.Value) { + throw new ZipException("crc was " + crc.Value + ", but I expected " + curEntry.Crc); + } + + offset += csize; + + if (curEntry.IsCrypted) { + if (curEntry.AESKeySize > 0) { + curEntry.CompressedSize += curEntry.AESOverheadSize; + + } else { + curEntry.CompressedSize += ZipConstants.CryptoHeaderSize; + } + } + + // Patch the header if possible + if (patchEntryHeader) { + patchEntryHeader = false; + + long curPos = baseOutputStream_.Position; + baseOutputStream_.Seek(crcPatchPos, SeekOrigin.Begin); + WriteLeInt((int)curEntry.Crc); + + if ( curEntry.LocalHeaderRequiresZip64 ) { + + if ( sizePatchPos == -1 ) { + throw new ZipException("Entry requires zip64 but this has been turned off"); + } + + baseOutputStream_.Seek(sizePatchPos, SeekOrigin.Begin); + WriteLeLong(curEntry.Size); + WriteLeLong(curEntry.CompressedSize); + } + else { + WriteLeInt((int)curEntry.CompressedSize); + WriteLeInt((int)curEntry.Size); + } + baseOutputStream_.Seek(curPos, SeekOrigin.Begin); + } + + // Add data descriptor if flagged as required + if ((curEntry.Flags & 8) != 0) { + WriteLeInt(ZipConstants.DataDescriptorSignature); + WriteLeInt(unchecked((int)curEntry.Crc)); + + if ( curEntry.LocalHeaderRequiresZip64 ) { + WriteLeLong(curEntry.CompressedSize); + WriteLeLong(curEntry.Size); + offset += ZipConstants.Zip64DataDescriptorSize; + } + else { + WriteLeInt((int)curEntry.CompressedSize); + WriteLeInt((int)curEntry.Size); + offset += ZipConstants.DataDescriptorSize; + } + } + + entries.Add(curEntry); + curEntry = null; + } + + void WriteEncryptionHeader(long crcValue) + { + offset += ZipConstants.CryptoHeaderSize; + + InitializePassword(Password); + + byte[] cryptBuffer = new byte[ZipConstants.CryptoHeaderSize]; + Random rnd = new Random(); + rnd.NextBytes(cryptBuffer); + cryptBuffer[11] = (byte)(crcValue >> 24); + + EncryptBlock(cryptBuffer, 0, cryptBuffer.Length); + baseOutputStream_.Write(cryptBuffer, 0, cryptBuffer.Length); + } + +#if !NET_1_1 && !NETCF_2_0 + private static void AddExtraDataAES(ZipEntry entry, ZipExtraData extraData) { + + // Vendor Version: AE-1 IS 1. AE-2 is 2. With AE-2 no CRC is required and 0 is stored. + const int VENDOR_VERSION = 2; + // Vendor ID is the two ASCII characters "AE". + const int VENDOR_ID = 0x4541; //not 6965; + extraData.StartNewEntry(); + // Pack AES extra data field see http://www.winzip.com/aes_info.htm + //extraData.AddLeShort(7); // Data size (currently 7) + extraData.AddLeShort(VENDOR_VERSION); // 2 = AE-2 + extraData.AddLeShort(VENDOR_ID); // "AE" + extraData.AddData(entry.AESEncryptionStrength); // 1 = 128, 2 = 192, 3 = 256 + extraData.AddLeShort((int)entry.CompressionMethod); // The actual compression method used to compress the file + extraData.AddNewEntry(0x9901); + } + + // Replaces WriteEncryptionHeader for AES + // + private void WriteAESHeader(ZipEntry entry) { + byte[] salt; + byte[] pwdVerifier; + InitializeAESPassword(entry, Password, out salt, out pwdVerifier); + // File format for AES: + // Size (bytes) Content + // ------------ ------- + // Variable Salt value + // 2 Password verification value + // Variable Encrypted file data + // 10 Authentication code + // + // Value in the "compressed size" fields of the local file header and the central directory entry + // is the total size of all the items listed above. In other words, it is the total size of the + // salt value, password verification value, encrypted data, and authentication code. + baseOutputStream_.Write(salt, 0, salt.Length); + baseOutputStream_.Write(pwdVerifier, 0, pwdVerifier.Length); + } +#endif + + /// + /// Writes the given buffer to the current entry. + /// + /// The buffer containing data to write. + /// The offset of the first byte to write. + /// The number of bytes to write. + /// Archive size is invalid + /// No entry is active. + public override void Write(byte[] buffer, int offset, int count) + { + if (curEntry == null) { + throw new InvalidOperationException("No open entry."); + } + + if ( buffer == null ) { + throw new ArgumentNullException("buffer"); + } + + if ( offset < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("offset"); +#else + throw new ArgumentOutOfRangeException("offset", "Cannot be negative"); +#endif + } + + if ( count < 0 ) { +#if NETCF_1_0 + throw new ArgumentOutOfRangeException("count"); +#else + throw new ArgumentOutOfRangeException("count", "Cannot be negative"); +#endif + } + + if ( (buffer.Length - offset) < count ) { + throw new ArgumentException("Invalid offset/count combination"); + } + + crc.Update(buffer, offset, count); + size += count; + + switch (curMethod) { + case CompressionMethod.Deflated: + base.Write(buffer, offset, count); + break; + + case CompressionMethod.Stored: + if (Password != null) { + CopyAndEncrypt(buffer, offset, count); + } else { + baseOutputStream_.Write(buffer, offset, count); + } + break; + } + } + + void CopyAndEncrypt(byte[] buffer, int offset, int count) + { + const int CopyBufferSize = 4096; + byte[] localBuffer = new byte[CopyBufferSize]; + while ( count > 0 ) { + int bufferCount = (count < CopyBufferSize) ? count : CopyBufferSize; + + Array.Copy(buffer, offset, localBuffer, 0, bufferCount); + EncryptBlock(localBuffer, 0, bufferCount); + baseOutputStream_.Write(localBuffer, 0, bufferCount); + count -= bufferCount; + offset += bufferCount; + } + } + + /// + /// Finishes the stream. This will write the central directory at the + /// end of the zip file and flush the stream. + /// + /// + /// This is automatically called when the stream is closed. + /// + /// + /// An I/O error occurs. + /// + /// + /// Comment exceeds the maximum length
+ /// Entry name exceeds the maximum length + ///
+ public override void Finish() + { + if (entries == null) { + return; + } + + if (curEntry != null) { + CloseEntry(); + } + + long numEntries = entries.Count; + long sizeEntries = 0; + + foreach (ZipEntry entry in entries) { + WriteLeInt(ZipConstants.CentralHeaderSignature); + WriteLeShort(ZipConstants.VersionMadeBy); + WriteLeShort(entry.Version); + WriteLeShort(entry.Flags); + WriteLeShort((short)entry.CompressionMethodForHeader); + WriteLeInt((int)entry.DosTime); + WriteLeInt((int)entry.Crc); + + if ( entry.IsZip64Forced() || + (entry.CompressedSize >= uint.MaxValue) ) + { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.CompressedSize); + } + + if ( entry.IsZip64Forced() || + (entry.Size >= uint.MaxValue) ) + { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.Size); + } + + byte[] name = ZipConstants.ConvertToArray(entry.Flags, entry.Name); + + if (name.Length > 0xffff) { + throw new ZipException("Name too long."); + } + + ZipExtraData ed = new ZipExtraData(entry.ExtraData); + + if ( entry.CentralHeaderRequiresZip64 ) { + ed.StartNewEntry(); + if ( entry.IsZip64Forced() || + (entry.Size >= 0xffffffff) ) + { + ed.AddLeLong(entry.Size); + } + + if ( entry.IsZip64Forced() || + (entry.CompressedSize >= 0xffffffff) ) + { + ed.AddLeLong(entry.CompressedSize); + } + + if ( entry.Offset >= 0xffffffff ) + { + ed.AddLeLong(entry.Offset); + } + + ed.AddNewEntry(1); + } + else { + ed.Delete(1); + } + +#if !NET_1_1 && !NETCF_2_0 + if (entry.AESKeySize > 0) { + AddExtraDataAES(entry, ed); + } +#endif + byte[] extra = ed.GetEntryData(); + + byte[] entryComment = + (entry.Comment != null) ? + ZipConstants.ConvertToArray(entry.Flags, entry.Comment) : + new byte[0]; + + if (entryComment.Length > 0xffff) { + throw new ZipException("Comment too long."); + } + + WriteLeShort(name.Length); + WriteLeShort(extra.Length); + WriteLeShort(entryComment.Length); + WriteLeShort(0); // disk number + WriteLeShort(0); // internal file attributes + // external file attributes + + if (entry.ExternalFileAttributes != -1) { + WriteLeInt(entry.ExternalFileAttributes); + } else { + if (entry.IsDirectory) { // mark entry as directory (from nikolam.AT.perfectinfo.com) + WriteLeInt(16); + } else { + WriteLeInt(0); + } + } + + if ( entry.Offset >= uint.MaxValue ) { + WriteLeInt(-1); + } + else { + WriteLeInt((int)entry.Offset); + } + + if ( name.Length > 0 ) { + baseOutputStream_.Write(name, 0, name.Length); + } + + if ( extra.Length > 0 ) { + baseOutputStream_.Write(extra, 0, extra.Length); + } + + if ( entryComment.Length > 0 ) { + baseOutputStream_.Write(entryComment, 0, entryComment.Length); + } + + sizeEntries += ZipConstants.CentralHeaderBaseSize + name.Length + extra.Length + entryComment.Length; + } + + using ( ZipHelperStream zhs = new ZipHelperStream(baseOutputStream_) ) { + zhs.WriteEndOfCentralDirectory(numEntries, sizeEntries, offset, zipComment); + } + + entries = null; + } + + #region Instance Fields + /// + /// The entries for the archive. + /// + ArrayList entries = new ArrayList(); + + /// + /// Used to track the crc of data added to entries. + /// + Crc32 crc = new Crc32(); + + /// + /// The current entry being added. + /// + ZipEntry curEntry; + + int defaultCompressionLevel = Deflater.DEFAULT_COMPRESSION; + + CompressionMethod curMethod = CompressionMethod.Deflated; + + /// + /// Used to track the size of data for an entry during writing. + /// + long size; + + /// + /// Offset to be recorded for each entry in the central header. + /// + long offset; + + /// + /// Comment for the entire archive recorded in central header. + /// + byte[] zipComment = new byte[0]; + + /// + /// Flag indicating that header patching is required for the current entry. + /// + bool patchEntryHeader; + + /// + /// Position to patch crc + /// + long crcPatchPos = -1; + + /// + /// Position to patch size. + /// + long sizePatchPos = -1; + + // Default is dynamic which is not backwards compatible and can cause problems + // with XP's built in compression which cant read Zip64 archives. + // However it does avoid the situation were a large file is added and cannot be completed correctly. + // NOTE: Setting the size for entries before they are added is the best solution! + UseZip64 useZip64_ = UseZip64.Dynamic; + #endregion + } +} diff --git a/类库/VersionUpdate/ZipArchive.cs b/类库/VersionUpdate/ZipArchive.cs new file mode 100644 index 0000000..b8c536b --- /dev/null +++ b/类库/VersionUpdate/ZipArchive.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; + +using System.Reflection; +using System.Web; +using System.Windows.Forms; +using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Zip; +using ICSharpCode.SharpZipLib.Zip1; + +namespace VersionUpdate +{ + internal class ZipArchive + { + /// + /// 功能:解压zip格式的文件。 + /// + /// 压缩文件路径 + /// 解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 + /// 出错信息 + /// 解压是否成功 + public static void UnZip(string zipFilePath, string unZipDir) + { + try + { + if (zipFilePath == string.Empty) + { + throw new Exception("压缩文件不能为空!"); + } + if (!File.Exists(zipFilePath)) + { + throw new System.IO.FileNotFoundException("压缩文件不存在!"); + } + //解压文件夹为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹 + if (unZipDir == string.Empty) + unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), + Path.GetFileNameWithoutExtension(zipFilePath)); + if (!unZipDir.EndsWith("/")) + unZipDir += "/"; + if (!Directory.Exists(unZipDir)) + Directory.CreateDirectory(unZipDir); + + using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath))) + { + + ZipEntry theEntry; + while ((theEntry = s.GetNextEntry()) != null) + { + string directoryName = Path.GetDirectoryName(theEntry.Name); + string fileName = Path.GetFileName(theEntry.Name); + if (directoryName.Length > 0) + { + Directory.CreateDirectory(unZipDir + directoryName); + } + if (!directoryName.EndsWith("/")) + directoryName += "/"; + if (fileName != String.Empty) + { + if (theEntry.Name == "VersionUpdate.exe") continue; + using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name)) + { + + int size = 5048; + byte[] data = new byte[size]; + while (true) + { + size = s.Read(data, 0, data.Length); + if (size > 0) + { + streamWriter.Write(data, 0, size); + } + else + { + break; + } + } + } + } + } + } + } + catch (Exception ex) + { } + } + } +} \ No newline at end of file diff --git a/类库/VersionUpdate/gtk_refresh_reload_update_32px_2205_easyicon.net.ico b/类库/VersionUpdate/gtk_refresh_reload_update_32px_2205_easyicon.net.ico new file mode 100644 index 0000000..b4b9fd0 Binary files /dev/null and b/类库/VersionUpdate/gtk_refresh_reload_update_32px_2205_easyicon.net.ico differ diff --git a/网站/index.aspx b/网站/index.aspx new file mode 100644 index 0000000..81da7e0 --- /dev/null +++ b/网站/index.aspx @@ -0,0 +1,305 @@ +<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %> + + + + + + + <%=html_title%> + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+
+

<%=html_name %>

+

<%=html_describe %>

+ + +
+
+ + + +
+ + + + + + + + + + +
+
+
+ + +
+

+ 支持批量登录
+ 模拟多设备
+

+

+  采用TCP/UDP通信、模拟设备信息、不会封号、节约服务器成本、数据互通、一站式管理 +

+
+
+
+ +
+
+ + +
+

+ 支持断点调试
+ 可调试快速开发
+

+

+  团队如果有技术员、我们可以提供技术协助、开发协助、便于你们开发各种适用于自己的功能 +

+
+
+
+ +
+
+ + +
+

+ 高速逻辑处理
+ 自动清理
+

+

+ 自动清理冗余垃圾、图片数据、日志信息、语音视频内容、自动回收内存 +

+
+
+
+ +
+
+ + +
+

+ 高可扩展空间
+ 完美兼容Windows
+

+

+   由于应用与主程序分离、我们随时可以应对各种政策 +

+
+
+
+ +
+
+ + +
+

+ 原生开发
+ 高速运作
+

+

+ 采用微软提供.NET C# 、高效运作环境、完美运行在自己平台下、部分类库采用C++开发 + +

+
+
+
+ +
+
+ + +
+

+ 内置多个联盟
+ 多平台分佣金
+

+

+ 支持阿里妈妈、拼多多、京东(开发中)、以后会扩展更多联盟 +

+
+
+
+ +
+
+ + +
+

+ 多社交平台
+ 统一管理
+

+

+  目前支持微信、未来会增加QQ、公众号、等更多社交平台 +

+
+
+
+ + +
+ + +
+ + +
+ +
+
+ + + +
+ +
+

+

+

+
+ 扫一扫
+ 添加微信客服 +

+ 加盟合作 +
+
+ + + + + + + diff --git a/网站/index.aspx.cs b/网站/index.aspx.cs new file mode 100644 index 0000000..fd0ebe5 --- /dev/null +++ b/网站/index.aspx.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +public partial class index : System.Web.UI.Page +{ + protected void Page_Load(object sender, EventArgs e) + { + + } + + + public string html_kefu_text = "售前咨询QQ:1077151162"; + public string html_chat_text = "交流QQ群:894902737"; + public string html_name = "秒单客"; + public string html_title = "秒单客-返利机器人(fanli.miaodanke.com)"; + public string html_describe = "支持淘宝、拼多多、京东返利
自动发朋友圈、发红包、转发、点赞、批量挂机"; + public string[] html_homelink = new string[] + { + "TitleHome|index.aspx|首页", + "Help|http://help.flsystem.miaodanke.com|查看使用文档", + "Auth|http://user.52cmg.cn/common/login/code/1001|机器人授权管理" + }; + public string[] html_helplink = new string[] + { + "http://download.microsoft.com/download/1/4/A/14A6C422-0D3C-4811-A31F-5EF91A83C368/NDP46-KB3045560-Web.exe|.NET 4.61运行环境下载" + }; + public string html_down_url = "https://www.lanzous.com/i391scd"; + public string html_down_text = "下载最新系统"; + + /// + /// 输出超链接 + /// + public void write_homelink() + { + foreach (string item in html_homelink) + { + string[] temp = item.Split('|'); + Response.Write(string.Format("
  • {2}
  • ",temp[0],temp[1],temp[2],temp[1].StartsWith("http")?"_blank":"")); + } + + } + + public void write_helplinke() + { + + int number = 0; + foreach (string item in html_helplink) + { + number++; + string[] temp = item.Split('|'); + Response.Write(string.Format(" {1} ", temp[0], temp[1])); + if (number != html_helplink.Length) Response.Write("    "); + } + } + +} \ No newline at end of file diff --git a/网站/style/css/bootstrap.min.css b/网站/style/css/bootstrap.min.css new file mode 100644 index 0000000..592cab1 --- /dev/null +++ b/网站/style/css/bootstrap.min.css @@ -0,0 +1,6574 @@ +/*! + * Bootstrap v3.0.3 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world @twitter by @mdo and @fat. + */ + +article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { + display: block; +} + +audio, canvas, video { + display: inline-block; +} + + audio:not([controls]) { + display: none; + height: 0; + } + +[hidden], template { + display: none; +} + +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} + +body { + margin: 0; +} + +a { + background: transparent; +} + + a:focus { + outline: thin dotted; + } + + a:active, a:hover { + outline: 0; + } + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +b, strong { + font-weight: bold; +} + +dfn { + font-style: italic; +} + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +mark { + background: #ff0; + color: #000; +} + +code, kbd, pre, samp { + font-family: monospace, serif; + font-size: 1em; +} + +pre { + white-space: pre-wrap; +} + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +small { + font-size: 80%; +} + +sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + border: 0; +} + +svg:not(:root) { + overflow: hidden; +} + +figure { + margin: 0; +} + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +legend { + border: 0; + padding: 0; +} + +button, input, select, textarea { + font-family: inherit; + font-size: 100%; + margin: 0; +} + +button, input { + line-height: normal; +} + +button, select { + text-transform: none; +} + +button, html input[type="button"], input[type="reset"], input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} + + button[disabled], html input[disabled] { + cursor: default; + } + +input[type="checkbox"], input[type="radio"] { + box-sizing: border-box; + padding: 0; +} + +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + + input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; + } + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; + padding: 0; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +@media print { + * { + text-shadow: none !important; + color: #000 !important; + background: transparent !important; + box-shadow: none !important; + } + + a, a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + a[href^="javascript:"]:after, a[href^="#"]:after { + content: ""; + } + + pre, blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + @page { + margin: 2cm .5cm; + } + + p, h2, h3 { + orphans: 3; + widows: 3; + } + + h2, h3 { + page-break-after: avoid; + } + + select { + background: #fff !important; + } + + .navbar { + display: none; + } + + .table td, .table th { + background-color: #fff !important; + } + + .btn > .caret, .dropup > .btn > .caret { + border-top-color: #000 !important; + } + + .label { + border: 1px solid #000; + } + + .table { + border-collapse: collapse !important; + } + + .table-bordered th, .table-bordered td { + border: 1px solid #ddd !important; + } +} + +*, *:before, *:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +html { + font-size: 62.5%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +body { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 14px; + line-height: 1.428571429; + color: #333333; + background-color: #ffffff; +} + +input, button, select, textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +a { + color: #428bca; + text-decoration: none; +} + + a:hover, a:focus { + color: #2a6496; + text-decoration: underline; + } + + a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; + } + +img { + vertical-align: middle; +} + +.img-responsive { + display: block; + max-width: 100%; + height: auto; +} + +.img-rounded { + border-radius: 6px; +} + +.img-thumbnail { + padding: 4px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} + +.img-circle { + border-radius: 50%; +} + +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-weight: 500; + line-height: 1.1; + color: inherit; +} + + h1 small, h2 small, h3 small, h4 small, h5 small, h6 small, .h1 small, .h2 small, .h3 small, .h4 small, .h5 small, .h6 small, h1 .small, h2 .small, h3 .small, h4 .small, h5 .small, h6 .small, .h1 .small, .h2 .small, .h3 .small, .h4 .small, .h5 .small, .h6 .small { + font-weight: normal; + line-height: 1; + color: #999999; + } + +h1, h2, h3 { + margin-top: 20px; + margin-bottom: 10px; +} + + h1 small, h2 small, h3 small, h1 .small, h2 .small, h3 .small { + font-size: 65%; + } + +h4, h5, h6 { + margin-top: 10px; + margin-bottom: 10px; +} + + h4 small, h5 small, h6 small, h4 .small, h5 .small, h6 .small { + font-size: 75%; + } + +h1, .h1 { + font-size: 36px; +} + +h2, .h2 { + font-size: 30px; +} + +h3, .h3 { + font-size: 24px; +} + +h4, .h4 { + font-size: 18px; +} + +h5, .h5 { + font-size: 14px; +} + +h6, .h6 { + font-size: 12px; +} + +p { + margin: 0 0 10px; +} + +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 200; + line-height: 1.4; +} + +@media (min-width:768px) { + .lead { + font-size: 21px; + } +} + +small, .small { + font-size: 85%; +} + +cite { + font-style: normal; +} + +.text-muted { + color: #999999; +} + +.text-primary { + color: #428bca; +} + + .text-primary:hover { + color: #3071a9; + } + +.text-warning { + color: #8a6d3b; +} + + .text-warning:hover { + color: #66512c; + } + +.text-danger { + color: #a94442; +} + + .text-danger:hover { + color: #843534; + } + +.text-success { + color: #3c763d; +} + + .text-success:hover { + color: #2b542c; + } + +.text-info { + color: #31708f; +} + + .text-info:hover { + color: #245269; + } + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} + +ul, ol { + margin-top: 0; + margin-bottom: 10px; +} + + ul ul, ol ul, ul ol, ol ol { + margin-bottom: 0; + } + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + + .list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; + } + + .list-inline > li:first-child { + padding-left: 0; + } + +dl { + margin-top: 0; + margin-bottom: 20px; +} + +dt, dd { + line-height: 1.428571429; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 0; +} + +@media (min-width:768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .dl-horizontal dd { + margin-left: 180px; + } + + .dl-horizontal dd:before, .dl-horizontal dd:after { + content: " "; + display: table; + } + + .dl-horizontal dd:after { + clear: both; + } + + .dl-horizontal dd:before, .dl-horizontal dd:after { + content: " "; + display: table; + } + + .dl-horizontal dd:after { + clear: both; + } +} + +abbr[title], abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} + + blockquote p { + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; + } + + blockquote p:last-child { + margin-bottom: 0; + } + + blockquote small, blockquote .small { + display: block; + line-height: 1.428571429; + color: #999999; + } + + blockquote small:before, blockquote .small:before { + content: '\2014 \00A0'; + } + + blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + } + + blockquote.pull-right p, blockquote.pull-right small, blockquote.pull-right .small { + text-align: right; + } + + blockquote.pull-right small:before, blockquote.pull-right .small:before { + content: ''; + } + + blockquote.pull-right small:after, blockquote.pull-right .small:after { + content: '\00A0 \2014'; + } + + blockquote:before, blockquote:after { + content: ""; + } + +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.428571429; +} + +code, kbd, pre, samp { + font-family: Menlo,Monaco,Consolas,"Courier New",monospace; +} + +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + white-space: nowrap; + border-radius: 4px; +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.428571429; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} + + pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; + } + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} + + .container:before, .container:after { + content: " "; + display: table; + } + + .container:after { + clear: both; + } + + .container:before, .container:after { + content: " "; + display: table; + } + + .container:after { + clear: both; + } + +@media (min-width:768px) { + .container { + width: 750px; + } +} + +@media (min-width:992px) { + .container { + width: 970px; + } +} + +@media (min-width:1200px) { + .container { + width: 1170px; + } +} + +.row { + margin-left: -15px; + margin-right: -15px; +} + + .row:before, .row:after { + content: " "; + display: table; + } + + .row:after { + clear: both; + } + + .row:before, .row:after { + content: " "; + display: table; + } + + .row:after { + clear: both; + } + +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} + +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} + +.col-xs-12 { + width: 100%; +} + +.col-xs-11 { + width: 91.66666666666666%; +} + +.col-xs-10 { + width: 83.33333333333334%; +} + +.col-xs-9 { + width: 75%; +} + +.col-xs-8 { + width: 66.66666666666666%; +} + +.col-xs-7 { + width: 58.333333333333336%; +} + +.col-xs-6 { + width: 50%; +} + +.col-xs-5 { + width: 41.66666666666667%; +} + +.col-xs-4 { + width: 33.33333333333333%; +} + +.col-xs-3 { + width: 25%; +} + +.col-xs-2 { + width: 16.666666666666664%; +} + +.col-xs-1 { + width: 8.333333333333332%; +} + +.col-xs-pull-12 { + right: 100%; +} + +.col-xs-pull-11 { + right: 91.66666666666666%; +} + +.col-xs-pull-10 { + right: 83.33333333333334%; +} + +.col-xs-pull-9 { + right: 75%; +} + +.col-xs-pull-8 { + right: 66.66666666666666%; +} + +.col-xs-pull-7 { + right: 58.333333333333336%; +} + +.col-xs-pull-6 { + right: 50%; +} + +.col-xs-pull-5 { + right: 41.66666666666667%; +} + +.col-xs-pull-4 { + right: 33.33333333333333%; +} + +.col-xs-pull-3 { + right: 25%; +} + +.col-xs-pull-2 { + right: 16.666666666666664%; +} + +.col-xs-pull-1 { + right: 8.333333333333332%; +} + +.col-xs-pull-0 { + right: 0%; +} + +.col-xs-push-12 { + left: 100%; +} + +.col-xs-push-11 { + left: 91.66666666666666%; +} + +.col-xs-push-10 { + left: 83.33333333333334%; +} + +.col-xs-push-9 { + left: 75%; +} + +.col-xs-push-8 { + left: 66.66666666666666%; +} + +.col-xs-push-7 { + left: 58.333333333333336%; +} + +.col-xs-push-6 { + left: 50%; +} + +.col-xs-push-5 { + left: 41.66666666666667%; +} + +.col-xs-push-4 { + left: 33.33333333333333%; +} + +.col-xs-push-3 { + left: 25%; +} + +.col-xs-push-2 { + left: 16.666666666666664%; +} + +.col-xs-push-1 { + left: 8.333333333333332%; +} + +.col-xs-push-0 { + left: 0%; +} + +.col-xs-offset-12 { + margin-left: 100%; +} + +.col-xs-offset-11 { + margin-left: 91.66666666666666%; +} + +.col-xs-offset-10 { + margin-left: 83.33333333333334%; +} + +.col-xs-offset-9 { + margin-left: 75%; +} + +.col-xs-offset-8 { + margin-left: 66.66666666666666%; +} + +.col-xs-offset-7 { + margin-left: 58.333333333333336%; +} + +.col-xs-offset-6 { + margin-left: 50%; +} + +.col-xs-offset-5 { + margin-left: 41.66666666666667%; +} + +.col-xs-offset-4 { + margin-left: 33.33333333333333%; +} + +.col-xs-offset-3 { + margin-left: 25%; +} + +.col-xs-offset-2 { + margin-left: 16.666666666666664%; +} + +.col-xs-offset-1 { + margin-left: 8.333333333333332%; +} + +.col-xs-offset-0 { + margin-left: 0%; +} + +@media (min-width:768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + + .col-sm-12 { + width: 100%; + } + + .col-sm-11 { + width: 91.66666666666666%; + } + + .col-sm-10 { + width: 83.33333333333334%; + } + + .col-sm-9 { + width: 75%; + } + + .col-sm-8 { + width: 66.66666666666666%; + } + + .col-sm-7 { + width: 58.333333333333336%; + } + + .col-sm-6 { + width: 50%; + } + + .col-sm-5 { + width: 41.66666666666667%; + } + + .col-sm-4 { + width: 33.33333333333333%; + } + + .col-sm-3 { + width: 25%; + } + + .col-sm-2 { + width: 16.666666666666664%; + } + + .col-sm-1 { + width: 8.333333333333332%; + } + + .col-sm-pull-12 { + right: 100%; + } + + .col-sm-pull-11 { + right: 91.66666666666666%; + } + + .col-sm-pull-10 { + right: 83.33333333333334%; + } + + .col-sm-pull-9 { + right: 75%; + } + + .col-sm-pull-8 { + right: 66.66666666666666%; + } + + .col-sm-pull-7 { + right: 58.333333333333336%; + } + + .col-sm-pull-6 { + right: 50%; + } + + .col-sm-pull-5 { + right: 41.66666666666667%; + } + + .col-sm-pull-4 { + right: 33.33333333333333%; + } + + .col-sm-pull-3 { + right: 25%; + } + + .col-sm-pull-2 { + right: 16.666666666666664%; + } + + .col-sm-pull-1 { + right: 8.333333333333332%; + } + + .col-sm-pull-0 { + right: 0%; + } + + .col-sm-push-12 { + left: 100%; + } + + .col-sm-push-11 { + left: 91.66666666666666%; + } + + .col-sm-push-10 { + left: 83.33333333333334%; + } + + .col-sm-push-9 { + left: 75%; + } + + .col-sm-push-8 { + left: 66.66666666666666%; + } + + .col-sm-push-7 { + left: 58.333333333333336%; + } + + .col-sm-push-6 { + left: 50%; + } + + .col-sm-push-5 { + left: 41.66666666666667%; + } + + .col-sm-push-4 { + left: 33.33333333333333%; + } + + .col-sm-push-3 { + left: 25%; + } + + .col-sm-push-2 { + left: 16.666666666666664%; + } + + .col-sm-push-1 { + left: 8.333333333333332%; + } + + .col-sm-push-0 { + left: 0%; + } + + .col-sm-offset-12 { + margin-left: 100%; + } + + .col-sm-offset-11 { + margin-left: 91.66666666666666%; + } + + .col-sm-offset-10 { + margin-left: 83.33333333333334%; + } + + .col-sm-offset-9 { + margin-left: 75%; + } + + .col-sm-offset-8 { + margin-left: 66.66666666666666%; + } + + .col-sm-offset-7 { + margin-left: 58.333333333333336%; + } + + .col-sm-offset-6 { + margin-left: 50%; + } + + .col-sm-offset-5 { + margin-left: 41.66666666666667%; + } + + .col-sm-offset-4 { + margin-left: 33.33333333333333%; + } + + .col-sm-offset-3 { + margin-left: 25%; + } + + .col-sm-offset-2 { + margin-left: 16.666666666666664%; + } + + .col-sm-offset-1 { + margin-left: 8.333333333333332%; + } + + .col-sm-offset-0 { + margin-left: 0%; + } +} + +@media (min-width:992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + + .col-md-12 { + width: 100%; + } + + .col-md-11 { + width: 91.66666666666666%; + } + + .col-md-10 { + width: 83.33333333333334%; + } + + .col-md-9 { + width: 75%; + } + + .col-md-8 { + width: 66.66666666666666%; + } + + .col-md-7 { + width: 58.333333333333336%; + } + + .col-md-6 { + width: 50%; + } + + .col-md-5 { + width: 41.66666666666667%; + } + + .col-md-4 { + width: 33.33333333333333%; + } + + .col-md-3 { + width: 25%; + } + + .col-md-2 { + width: 16.666666666666664%; + } + + .col-md-1 { + width: 8.333333333333332%; + } + + .col-md-pull-12 { + right: 100%; + } + + .col-md-pull-11 { + right: 91.66666666666666%; + } + + .col-md-pull-10 { + right: 83.33333333333334%; + } + + .col-md-pull-9 { + right: 75%; + } + + .col-md-pull-8 { + right: 66.66666666666666%; + } + + .col-md-pull-7 { + right: 58.333333333333336%; + } + + .col-md-pull-6 { + right: 50%; + } + + .col-md-pull-5 { + right: 41.66666666666667%; + } + + .col-md-pull-4 { + right: 33.33333333333333%; + } + + .col-md-pull-3 { + right: 25%; + } + + .col-md-pull-2 { + right: 16.666666666666664%; + } + + .col-md-pull-1 { + right: 8.333333333333332%; + } + + .col-md-pull-0 { + right: 0%; + } + + .col-md-push-12 { + left: 100%; + } + + .col-md-push-11 { + left: 91.66666666666666%; + } + + .col-md-push-10 { + left: 83.33333333333334%; + } + + .col-md-push-9 { + left: 75%; + } + + .col-md-push-8 { + left: 66.66666666666666%; + } + + .col-md-push-7 { + left: 58.333333333333336%; + } + + .col-md-push-6 { + left: 50%; + } + + .col-md-push-5 { + left: 41.66666666666667%; + } + + .col-md-push-4 { + left: 33.33333333333333%; + } + + .col-md-push-3 { + left: 25%; + } + + .col-md-push-2 { + left: 16.666666666666664%; + } + + .col-md-push-1 { + left: 8.333333333333332%; + } + + .col-md-push-0 { + left: 0%; + } + + .col-md-offset-12 { + margin-left: 100%; + } + + .col-md-offset-11 { + margin-left: 91.66666666666666%; + } + + .col-md-offset-10 { + margin-left: 83.33333333333334%; + } + + .col-md-offset-9 { + margin-left: 75%; + } + + .col-md-offset-8 { + margin-left: 66.66666666666666%; + } + + .col-md-offset-7 { + margin-left: 58.333333333333336%; + } + + .col-md-offset-6 { + margin-left: 50%; + } + + .col-md-offset-5 { + margin-left: 41.66666666666667%; + } + + .col-md-offset-4 { + margin-left: 33.33333333333333%; + } + + .col-md-offset-3 { + margin-left: 25%; + } + + .col-md-offset-2 { + margin-left: 16.666666666666664%; + } + + .col-md-offset-1 { + margin-left: 8.333333333333332%; + } + + .col-md-offset-0 { + margin-left: 0%; + } +} + +@media (min-width:1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + + .col-lg-12 { + width: 100%; + } + + .col-lg-11 { + width: 91.66666666666666%; + } + + .col-lg-10 { + width: 83.33333333333334%; + } + + .col-lg-9 { + width: 75%; + } + + .col-lg-8 { + width: 66.66666666666666%; + } + + .col-lg-7 { + width: 58.333333333333336%; + } + + .col-lg-6 { + width: 50%; + } + + .col-lg-5 { + width: 41.66666666666667%; + } + + .col-lg-4 { + width: 33.33333333333333%; + } + + .col-lg-3 { + width: 25%; + } + + .col-lg-2 { + width: 16.666666666666664%; + } + + .col-lg-1 { + width: 8.333333333333332%; + } + + .col-lg-pull-12 { + right: 100%; + } + + .col-lg-pull-11 { + right: 91.66666666666666%; + } + + .col-lg-pull-10 { + right: 83.33333333333334%; + } + + .col-lg-pull-9 { + right: 75%; + } + + .col-lg-pull-8 { + right: 66.66666666666666%; + } + + .col-lg-pull-7 { + right: 58.333333333333336%; + } + + .col-lg-pull-6 { + right: 50%; + } + + .col-lg-pull-5 { + right: 41.66666666666667%; + } + + .col-lg-pull-4 { + right: 33.33333333333333%; + } + + .col-lg-pull-3 { + right: 25%; + } + + .col-lg-pull-2 { + right: 16.666666666666664%; + } + + .col-lg-pull-1 { + right: 8.333333333333332%; + } + + .col-lg-pull-0 { + right: 0%; + } + + .col-lg-push-12 { + left: 100%; + } + + .col-lg-push-11 { + left: 91.66666666666666%; + } + + .col-lg-push-10 { + left: 83.33333333333334%; + } + + .col-lg-push-9 { + left: 75%; + } + + .col-lg-push-8 { + left: 66.66666666666666%; + } + + .col-lg-push-7 { + left: 58.333333333333336%; + } + + .col-lg-push-6 { + left: 50%; + } + + .col-lg-push-5 { + left: 41.66666666666667%; + } + + .col-lg-push-4 { + left: 33.33333333333333%; + } + + .col-lg-push-3 { + left: 25%; + } + + .col-lg-push-2 { + left: 16.666666666666664%; + } + + .col-lg-push-1 { + left: 8.333333333333332%; + } + + .col-lg-push-0 { + left: 0%; + } + + .col-lg-offset-12 { + margin-left: 100%; + } + + .col-lg-offset-11 { + margin-left: 91.66666666666666%; + } + + .col-lg-offset-10 { + margin-left: 83.33333333333334%; + } + + .col-lg-offset-9 { + margin-left: 75%; + } + + .col-lg-offset-8 { + margin-left: 66.66666666666666%; + } + + .col-lg-offset-7 { + margin-left: 58.333333333333336%; + } + + .col-lg-offset-6 { + margin-left: 50%; + } + + .col-lg-offset-5 { + margin-left: 41.66666666666667%; + } + + .col-lg-offset-4 { + margin-left: 33.33333333333333%; + } + + .col-lg-offset-3 { + margin-left: 25%; + } + + .col-lg-offset-2 { + margin-left: 16.666666666666664%; + } + + .col-lg-offset-1 { + margin-left: 8.333333333333332%; + } + + .col-lg-offset-0 { + margin-left: 0%; + } +} + +table { + max-width: 100%; + background-color: transparent; +} + +th { + text-align: left; +} + +.table { + width: 100%; + margin-bottom: 20px; +} + + .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { + padding: 8px; + line-height: 1.428571429; + vertical-align: top; + border-top: 1px solid #dddddd; + } + + .table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; + } + + .table > caption + thead > tr:first-child > th, .table > colgroup + thead > tr:first-child > th, .table > thead:first-child > tr:first-child > th, .table > caption + thead > tr:first-child > td, .table > colgroup + thead > tr:first-child > td, .table > thead:first-child > tr:first-child > td { + border-top: 0; + } + + .table > tbody + tbody { + border-top: 2px solid #dddddd; + } + + .table .table { + background-color: #ffffff; + } + +.table-condensed > thead > tr > th, .table-condensed > tbody > tr > th, .table-condensed > tfoot > tr > th, .table-condensed > thead > tr > td, .table-condensed > tbody > tr > td, .table-condensed > tfoot > tr > td { + padding: 5px; +} + +.table-bordered { + border: 1px solid #dddddd; +} + + .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; + } + + .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { + border-bottom-width: 2px; + } + +.table-striped > tbody > tr:nth-child(odd) > td, .table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +.table-hover > tbody > tr:hover > td, .table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} + +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} + +table td[class*="col-"], table th[class*="col-"] { + float: none; + display: table-cell; +} + +.table > thead > tr > .active, .table > tbody > tr > .active, .table > tfoot > tr > .active, .table > thead > .active > td, .table > tbody > .active > td, .table > tfoot > .active > td, .table > thead > .active > th, .table > tbody > .active > th, .table > tfoot > .active > th { + background-color: #f5f5f5; +} + +.table-hover > tbody > tr > .active:hover, .table-hover > tbody > .active:hover > td, .table-hover > tbody > .active:hover > th { + background-color: #e8e8e8; +} + +.table > thead > tr > .success, .table > tbody > tr > .success, .table > tfoot > tr > .success, .table > thead > .success > td, .table > tbody > .success > td, .table > tfoot > .success > td, .table > thead > .success > th, .table > tbody > .success > th, .table > tfoot > .success > th { + background-color: #dff0d8; +} + +.table-hover > tbody > tr > .success:hover, .table-hover > tbody > .success:hover > td, .table-hover > tbody > .success:hover > th { + background-color: #d0e9c6; +} + +.table > thead > tr > .danger, .table > tbody > tr > .danger, .table > tfoot > tr > .danger, .table > thead > .danger > td, .table > tbody > .danger > td, .table > tfoot > .danger > td, .table > thead > .danger > th, .table > tbody > .danger > th, .table > tfoot > .danger > th { + background-color: #f2dede; +} + +.table-hover > tbody > tr > .danger:hover, .table-hover > tbody > .danger:hover > td, .table-hover > tbody > .danger:hover > th { + background-color: #ebcccc; +} + +.table > thead > tr > .warning, .table > tbody > tr > .warning, .table > tfoot > tr > .warning, .table > thead > .warning > td, .table > tbody > .warning > td, .table > tfoot > .warning > td, .table > thead > .warning > th, .table > tbody > .warning > th, .table > tfoot > .warning > th { + background-color: #fcf8e3; +} + +.table-hover > tbody > tr > .warning:hover, .table-hover > tbody > .warning:hover > td, .table-hover > tbody > .warning:hover > th { + background-color: #faf2cc; +} + +@media (max-width:767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + overflow-x: scroll; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #dddddd; + -webkit-overflow-scrolling: touch; + } + + .table-responsive > .table { + margin-bottom: 0; + } + + .table-responsive > .table > thead > tr > th, .table-responsive > .table > tbody > tr > th, .table-responsive > .table > tfoot > tr > th, .table-responsive > .table > thead > tr > td, .table-responsive > .table > tbody > tr > td, .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + + .table-responsive > .table-bordered { + border: 0; + } + + .table-responsive > .table-bordered > thead > tr > th:first-child, .table-responsive > .table-bordered > tbody > tr > th:first-child, .table-responsive > .table-bordered > tfoot > tr > th:first-child, .table-responsive > .table-bordered > thead > tr > td:first-child, .table-responsive > .table-bordered > tbody > tr > td:first-child, .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + + .table-responsive > .table-bordered > thead > tr > th:last-child, .table-responsive > .table-bordered > tbody > tr > th:last-child, .table-responsive > .table-bordered > tfoot > tr > th:last-child, .table-responsive > .table-bordered > thead > tr > td:last-child, .table-responsive > .table-bordered > tbody > tr > td:last-child, .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + + .table-responsive > .table-bordered > tbody > tr:last-child > th, .table-responsive > .table-bordered > tfoot > tr:last-child > th, .table-responsive > .table-bordered > tbody > tr:last-child > td, .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +label { + display: inline-block; + margin-bottom: 5px; + font-weight: bold; +} + +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +input[type="radio"], input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} + +input[type="file"] { + display: block; +} + +select[multiple], select[size] { + height: auto; +} + +select optgroup { + font-size: inherit; + font-style: inherit; + font-family: inherit; +} + +input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button { + height: auto; +} + +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.428571429; + color: #555555; + vertical-align: middle; +} + +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + color: #555555; + vertical-align: middle; + background-color: #ffffff; + background-image: none; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} + + .form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + } + + .form-control:-moz-placeholder { + color: #999999; + } + + .form-control::-moz-placeholder { + color: #999999; + opacity: 1; + } + + .form-control:-ms-input-placeholder { + color: #999999; + } + + .form-control::-webkit-input-placeholder { + color: #999999; + } + + .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + } + +textarea.form-control { + height: auto; +} + +.form-group { + margin-bottom: 15px; +} + +.radio, .checkbox { + display: block; + min-height: 20px; + margin-top: 10px; + margin-bottom: 10px; + padding-left: 20px; + vertical-align: middle; +} + + .radio label, .checkbox label { + display: inline; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; + } + + .radio input[type="radio"], .radio-inline input[type="radio"], .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] { + float: left; + margin-left: -20px; + } + + .radio + .radio, .checkbox + .checkbox { + margin-top: -5px; + } + +.radio-inline, .checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} + + .radio-inline + .radio-inline, .checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; + } + + input[type="radio"][disabled], input[type="checkbox"][disabled], .radio[disabled], .radio-inline[disabled], .checkbox[disabled], .checkbox-inline[disabled], fieldset[disabled] input[type="radio"], fieldset[disabled] input[type="checkbox"], fieldset[disabled] .radio, fieldset[disabled] .radio-inline, fieldset[disabled] .checkbox, fieldset[disabled] .checkbox-inline { + cursor: not-allowed; + } + +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +select.input-sm { + height: 30px; + line-height: 30px; +} + +textarea.input-sm { + height: auto; +} + +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +select.input-lg { + height: 46px; + line-height: 46px; +} + +textarea.input-lg { + height: auto; +} + +.has-warning .help-block, .has-warning .control-label, .has-warning .radio, .has-warning .checkbox, .has-warning .radio-inline, .has-warning .checkbox-inline { + color: #8a6d3b; +} + +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #c0a16b; + } + +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} + +.has-error .help-block, .has-error .control-label, .has-error .radio, .has-error .checkbox, .has-error .radio-inline, .has-error .checkbox-inline { + color: #a94442; +} + +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #ce8483; + } + +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} + +.has-success .help-block, .has-success .control-label, .has-success .radio, .has-success .checkbox, .has-success .radio-inline, .has-success .checkbox-inline { + color: #3c763d; +} + +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + + .has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #67b168; + } + +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} + +.form-control-static { + margin-bottom: 0; +} + +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} + +@media (min-width:768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .form-control { + display: inline-block; + } + + .form-inline select.form-control { + width: auto; + } + + .form-inline .radio, .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; + } + + .form-inline .radio input[type="radio"], .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } +} + +.form-horizontal .control-label, .form-horizontal .radio, .form-horizontal .checkbox, .form-horizontal .radio-inline, .form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} + +.form-horizontal .radio, .form-horizontal .checkbox { + min-height: 27px; +} + +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} + + .form-horizontal .form-group:before, .form-horizontal .form-group:after { + content: " "; + display: table; + } + + .form-horizontal .form-group:after { + clear: both; + } + + .form-horizontal .form-group:before, .form-horizontal .form-group:after { + content: " "; + display: table; + } + + .form-horizontal .form-group:after { + clear: both; + } + +.form-horizontal .form-control-static { + padding-top: 7px; +} + +@media (min-width:768px) { + .form-horizontal .control-label { + text-align: right; + } +} + +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + + .btn:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; + } + + .btn:hover, .btn:focus { + color: #333333; + text-decoration: none; + } + + .btn:active, .btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + } + + .btn.disabled, .btn[disabled], fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + } + +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} + + .btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default { + color: #333333; + background-color: #ebebeb; + border-color: #adadad; + } + + .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default { + background-image: none; + } + + .btn-default.disabled, .btn-default[disabled], fieldset[disabled] .btn-default, .btn-default.disabled:hover, .btn-default[disabled]:hover, fieldset[disabled] .btn-default:hover, .btn-default.disabled:focus, .btn-default[disabled]:focus, fieldset[disabled] .btn-default:focus, .btn-default.disabled:active, .btn-default[disabled]:active, fieldset[disabled] .btn-default:active, .btn-default.disabled.active, .btn-default[disabled].active, fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; + } + + .btn-default .badge { + color: #ffffff; + background-color: #fff; + } + +.btn-primary { + color: #ffffff; + background-color: #428bca; + border-color: #357ebd; +} + + .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #3276b1; + border-color: #285e8e; + } + + .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { + background-image: none; + } + + .btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; + } + + .btn-primary .badge { + color: #428bca; + background-color: #fff; + } + +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} + + .btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ed9c28; + border-color: #d58512; + } + + .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning { + background-image: none; + } + + .btn-warning.disabled, .btn-warning[disabled], fieldset[disabled] .btn-warning, .btn-warning.disabled:hover, .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning:hover, .btn-warning.disabled:focus, .btn-warning[disabled]:focus, fieldset[disabled] .btn-warning:focus, .btn-warning.disabled:active, .btn-warning[disabled]:active, fieldset[disabled] .btn-warning:active, .btn-warning.disabled.active, .btn-warning[disabled].active, fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; + } + + .btn-warning .badge { + color: #f0ad4e; + background-color: #fff; + } + +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} + + .btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #d2322d; + border-color: #ac2925; + } + + .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger { + background-image: none; + } + + .btn-danger.disabled, .btn-danger[disabled], fieldset[disabled] .btn-danger, .btn-danger.disabled:hover, .btn-danger[disabled]:hover, fieldset[disabled] .btn-danger:hover, .btn-danger.disabled:focus, .btn-danger[disabled]:focus, fieldset[disabled] .btn-danger:focus, .btn-danger.disabled:active, .btn-danger[disabled]:active, fieldset[disabled] .btn-danger:active, .btn-danger.disabled.active, .btn-danger[disabled].active, fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; + } + + .btn-danger .badge { + color: #d9534f; + background-color: #fff; + } + +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} + + .btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #47a447; + border-color: #398439; + } + + .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success { + background-image: none; + } + + .btn-success.disabled, .btn-success[disabled], fieldset[disabled] .btn-success, .btn-success.disabled:hover, .btn-success[disabled]:hover, fieldset[disabled] .btn-success:hover, .btn-success.disabled:focus, .btn-success[disabled]:focus, fieldset[disabled] .btn-success:focus, .btn-success.disabled:active, .btn-success[disabled]:active, fieldset[disabled] .btn-success:active, .btn-success.disabled.active, .btn-success[disabled].active, fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; + } + + .btn-success .badge { + color: #5cb85c; + background-color: #fff; + } + +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} + + .btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #39b3d7; + border-color: #269abc; + } + + .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { + background-image: none; + } + + .btn-info.disabled, .btn-info[disabled], fieldset[disabled] .btn-info, .btn-info.disabled:hover, .btn-info[disabled]:hover, fieldset[disabled] .btn-info:hover, .btn-info.disabled:focus, .btn-info[disabled]:focus, fieldset[disabled] .btn-info:focus, .btn-info.disabled:active, .btn-info[disabled]:active, fieldset[disabled] .btn-info:active, .btn-info.disabled.active, .btn-info[disabled].active, fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; + } + + .btn-info .badge { + color: #5bc0de; + background-color: #fff; + } + +.btn-link { + color: #428bca; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} + + .btn-link, .btn-link:active, .btn-link[disabled], fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; + } + + .btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active { + border-color: transparent; + } + + .btn-link:hover, .btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; + } + + .btn-link[disabled]:hover, fieldset[disabled] .btn-link:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; + } + +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +.btn-sm { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-xs { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-block { + display: block; + width: 100%; + padding-left: 0; + padding-right: 0; +} + + .btn-block + .btn-block { + margin-top: 5px; + } + +input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { + width: 100%; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + + .fade.in { + opacity: 1; + } + +.collapse { + display: none; +} + + .collapse.in { + display: block; + } + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('fonts/glyphicons-halflings-regular.eot'); + src: url('fonts/glyphicons-halflings-regular.eot') format('embedded-opentype'),url('fonts/glyphicons-halflings-regular.woff') format('woff'),url('fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('fonts/glyphicons-halflings-regular.svg') format('svg'); +} + +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + + .glyphicon:empty { + width: 1em; + } + +.glyphicon-asterisk:before { + content: "\2a"; +} + +.glyphicon-plus:before { + content: "\2b"; +} + +.glyphicon-euro:before { + content: "\20ac"; +} + +.glyphicon-minus:before { + content: "\2212"; +} + +.glyphicon-cloud:before { + content: "\2601"; +} + +.glyphicon-envelope:before { + content: "\2709"; +} + +.glyphicon-pencil:before { + content: "\270f"; +} + +.glyphicon-glass:before { + content: "\e001"; +} + +.glyphicon-music:before { + content: "\e002"; +} + +.glyphicon-search:before { + content: "\e003"; +} + +.glyphicon-heart:before { + content: "\e005"; +} + +.glyphicon-star:before { + content: "\e006"; +} + +.glyphicon-star-empty:before { + content: "\e007"; +} + +.glyphicon-user:before { + content: "\e008"; +} + +.glyphicon-film:before { + content: "\e009"; +} + +.glyphicon-th-large:before { + content: "\e010"; +} + +.glyphicon-th:before { + content: "\e011"; +} + +.glyphicon-th-list:before { + content: "\e012"; +} + +.glyphicon-ok:before { + content: "\e013"; +} + +.glyphicon-remove:before { + content: "\e014"; +} + +.glyphicon-zoom-in:before { + content: "\e015"; +} + +.glyphicon-zoom-out:before { + content: "\e016"; +} + +.glyphicon-off:before { + content: "\e017"; +} + +.glyphicon-signal:before { + content: "\e018"; +} + +.glyphicon-cog:before { + content: "\e019"; +} + +.glyphicon-trash:before { + content: "\e020"; +} + +.glyphicon-home:before { + content: "\e021"; +} + +.glyphicon-file:before { + content: "\e022"; +} + +.glyphicon-time:before { + content: "\e023"; +} + +.glyphicon-road:before { + content: "\e024"; +} + +.glyphicon-download-alt:before { + content: "\e025"; +} + +.glyphicon-download:before { + content: "\e026"; +} + +.glyphicon-upload:before { + content: "\e027"; +} + +.glyphicon-inbox:before { + content: "\e028"; +} + +.glyphicon-play-circle:before { + content: "\e029"; +} + +.glyphicon-repeat:before { + content: "\e030"; +} + +.glyphicon-refresh:before { + content: "\e031"; +} + +.glyphicon-list-alt:before { + content: "\e032"; +} + +.glyphicon-lock:before { + content: "\e033"; +} + +.glyphicon-flag:before { + content: "\e034"; +} + +.glyphicon-headphones:before { + content: "\e035"; +} + +.glyphicon-volume-off:before { + content: "\e036"; +} + +.glyphicon-volume-down:before { + content: "\e037"; +} + +.glyphicon-volume-up:before { + content: "\e038"; +} + +.glyphicon-qrcode:before { + content: "\e039"; +} + +.glyphicon-barcode:before { + content: "\e040"; +} + +.glyphicon-tag:before { + content: "\e041"; +} + +.glyphicon-tags:before { + content: "\e042"; +} + +.glyphicon-book:before { + content: "\e043"; +} + +.glyphicon-bookmark:before { + content: "\e044"; +} + +.glyphicon-print:before { + content: "\e045"; +} + +.glyphicon-camera:before { + content: "\e046"; +} + +.glyphicon-font:before { + content: "\e047"; +} + +.glyphicon-bold:before { + content: "\e048"; +} + +.glyphicon-italic:before { + content: "\e049"; +} + +.glyphicon-text-height:before { + content: "\e050"; +} + +.glyphicon-text-width:before { + content: "\e051"; +} + +.glyphicon-align-left:before { + content: "\e052"; +} + +.glyphicon-align-center:before { + content: "\e053"; +} + +.glyphicon-align-right:before { + content: "\e054"; +} + +.glyphicon-align-justify:before { + content: "\e055"; +} + +.glyphicon-list:before { + content: "\e056"; +} + +.glyphicon-indent-left:before { + content: "\e057"; +} + +.glyphicon-indent-right:before { + content: "\e058"; +} + +.glyphicon-facetime-video:before { + content: "\e059"; +} + +.glyphicon-picture:before { + content: "\e060"; +} + +.glyphicon-map-marker:before { + content: "\e062"; +} + +.glyphicon-adjust:before { + content: "\e063"; +} + +.glyphicon-tint:before { + content: "\e064"; +} + +.glyphicon-edit:before { + content: "\e065"; +} + +.glyphicon-share:before { + content: "\e066"; +} + +.glyphicon-check:before { + content: "\e067"; +} + +.glyphicon-move:before { + content: "\e068"; +} + +.glyphicon-step-backward:before { + content: "\e069"; +} + +.glyphicon-fast-backward:before { + content: "\e070"; +} + +.glyphicon-backward:before { + content: "\e071"; +} + +.glyphicon-play:before { + content: "\e072"; +} + +.glyphicon-pause:before { + content: "\e073"; +} + +.glyphicon-stop:before { + content: "\e074"; +} + +.glyphicon-forward:before { + content: "\e075"; +} + +.glyphicon-fast-forward:before { + content: "\e076"; +} + +.glyphicon-step-forward:before { + content: "\e077"; +} + +.glyphicon-eject:before { + content: "\e078"; +} + +.glyphicon-chevron-left:before { + content: "\e079"; +} + +.glyphicon-chevron-right:before { + content: "\e080"; +} + +.glyphicon-plus-sign:before { + content: "\e081"; +} + +.glyphicon-minus-sign:before { + content: "\e082"; +} + +.glyphicon-remove-sign:before { + content: "\e083"; +} + +.glyphicon-ok-sign:before { + content: "\e084"; +} + +.glyphicon-question-sign:before { + content: "\e085"; +} + +.glyphicon-info-sign:before { + content: "\e086"; +} + +.glyphicon-screenshot:before { + content: "\e087"; +} + +.glyphicon-remove-circle:before { + content: "\e088"; +} + +.glyphicon-ok-circle:before { + content: "\e089"; +} + +.glyphicon-ban-circle:before { + content: "\e090"; +} + +.glyphicon-arrow-left:before { + content: "\e091"; +} + +.glyphicon-arrow-right:before { + content: "\e092"; +} + +.glyphicon-arrow-up:before { + content: "\e093"; +} + +.glyphicon-arrow-down:before { + content: "\e094"; +} + +.glyphicon-share-alt:before { + content: "\e095"; +} + +.glyphicon-resize-full:before { + content: "\e096"; +} + +.glyphicon-resize-small:before { + content: "\e097"; +} + +.glyphicon-exclamation-sign:before { + content: "\e101"; +} + +.glyphicon-gift:before { + content: "\e102"; +} + +.glyphicon-leaf:before { + content: "\e103"; +} + +.glyphicon-fire:before { + content: "\e104"; +} + +.glyphicon-eye-open:before { + content: "\e105"; +} + +.glyphicon-eye-close:before { + content: "\e106"; +} + +.glyphicon-warning-sign:before { + content: "\e107"; +} + +.glyphicon-plane:before { + content: "\e108"; +} + +.glyphicon-calendar:before { + content: "\e109"; +} + +.glyphicon-random:before { + content: "\e110"; +} + +.glyphicon-comment:before { + content: "\e111"; +} + +.glyphicon-magnet:before { + content: "\e112"; +} + +.glyphicon-chevron-up:before { + content: "\e113"; +} + +.glyphicon-chevron-down:before { + content: "\e114"; +} + +.glyphicon-retweet:before { + content: "\e115"; +} + +.glyphicon-shopping-cart:before { + content: "\e116"; +} + +.glyphicon-folder-close:before { + content: "\e117"; +} + +.glyphicon-folder-open:before { + content: "\e118"; +} + +.glyphicon-resize-vertical:before { + content: "\e119"; +} + +.glyphicon-resize-horizontal:before { + content: "\e120"; +} + +.glyphicon-hdd:before { + content: "\e121"; +} + +.glyphicon-bullhorn:before { + content: "\e122"; +} + +.glyphicon-bell:before { + content: "\e123"; +} + +.glyphicon-certificate:before { + content: "\e124"; +} + +.glyphicon-thumbs-up:before { + content: "\e125"; +} + +.glyphicon-thumbs-down:before { + content: "\e126"; +} + +.glyphicon-hand-right:before { + content: "\e127"; +} + +.glyphicon-hand-left:before { + content: "\e128"; +} + +.glyphicon-hand-up:before { + content: "\e129"; +} + +.glyphicon-hand-down:before { + content: "\e130"; +} + +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} + +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} + +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} + +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} + +.glyphicon-globe:before { + content: "\e135"; +} + +.glyphicon-wrench:before { + content: "\e136"; +} + +.glyphicon-tasks:before { + content: "\e137"; +} + +.glyphicon-filter:before { + content: "\e138"; +} + +.glyphicon-briefcase:before { + content: "\e139"; +} + +.glyphicon-fullscreen:before { + content: "\e140"; +} + +.glyphicon-dashboard:before { + content: "\e141"; +} + +.glyphicon-paperclip:before { + content: "\e142"; +} + +.glyphicon-heart-empty:before { + content: "\e143"; +} + +.glyphicon-link:before { + content: "\e144"; +} + +.glyphicon-phone:before { + content: "\e145"; +} + +.glyphicon-pushpin:before { + content: "\e146"; +} + +.glyphicon-usd:before { + content: "\e148"; +} + +.glyphicon-gbp:before { + content: "\e149"; +} + +.glyphicon-sort:before { + content: "\e150"; +} + +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} + +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} + +.glyphicon-sort-by-order:before { + content: "\e153"; +} + +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} + +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} + +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} + +.glyphicon-unchecked:before { + content: "\e157"; +} + +.glyphicon-expand:before { + content: "\e158"; +} + +.glyphicon-collapse-down:before { + content: "\e159"; +} + +.glyphicon-collapse-up:before { + content: "\e160"; +} + +.glyphicon-log-in:before { + content: "\e161"; +} + +.glyphicon-flash:before { + content: "\e162"; +} + +.glyphicon-log-out:before { + content: "\e163"; +} + +.glyphicon-new-window:before { + content: "\e164"; +} + +.glyphicon-record:before { + content: "\e165"; +} + +.glyphicon-save:before { + content: "\e166"; +} + +.glyphicon-open:before { + content: "\e167"; +} + +.glyphicon-saved:before { + content: "\e168"; +} + +.glyphicon-import:before { + content: "\e169"; +} + +.glyphicon-export:before { + content: "\e170"; +} + +.glyphicon-send:before { + content: "\e171"; +} + +.glyphicon-floppy-disk:before { + content: "\e172"; +} + +.glyphicon-floppy-saved:before { + content: "\e173"; +} + +.glyphicon-floppy-remove:before { + content: "\e174"; +} + +.glyphicon-floppy-save:before { + content: "\e175"; +} + +.glyphicon-floppy-open:before { + content: "\e176"; +} + +.glyphicon-credit-card:before { + content: "\e177"; +} + +.glyphicon-transfer:before { + content: "\e178"; +} + +.glyphicon-cutlery:before { + content: "\e179"; +} + +.glyphicon-header:before { + content: "\e180"; +} + +.glyphicon-compressed:before { + content: "\e181"; +} + +.glyphicon-earphone:before { + content: "\e182"; +} + +.glyphicon-phone-alt:before { + content: "\e183"; +} + +.glyphicon-tower:before { + content: "\e184"; +} + +.glyphicon-stats:before { + content: "\e185"; +} + +.glyphicon-sd-video:before { + content: "\e186"; +} + +.glyphicon-hd-video:before { + content: "\e187"; +} + +.glyphicon-subtitles:before { + content: "\e188"; +} + +.glyphicon-sound-stereo:before { + content: "\e189"; +} + +.glyphicon-sound-dolby:before { + content: "\e190"; +} + +.glyphicon-sound-5-1:before { + content: "\e191"; +} + +.glyphicon-sound-6-1:before { + content: "\e192"; +} + +.glyphicon-sound-7-1:before { + content: "\e193"; +} + +.glyphicon-copyright-mark:before { + content: "\e194"; +} + +.glyphicon-registration-mark:before { + content: "\e195"; +} + +.glyphicon-cloud-download:before { + content: "\e197"; +} + +.glyphicon-cloud-upload:before { + content: "\e198"; +} + +.glyphicon-tree-conifer:before { + content: "\e199"; +} + +.glyphicon-tree-deciduous:before { + content: "\e200"; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} + +.dropdown { + position: relative; +} + +.dropdown-toggle:focus { + outline: 0; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} + + .dropdown-menu.pull-right { + right: 0; + left: auto; + } + + .dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; + } + + .dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; + color: #333333; + white-space: nowrap; + } + + .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; + } + + .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; + } + + .dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { + color: #999999; + } + + .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; + } + +.open > .dropdown-menu { + display: block; +} + +.open > a { + outline: 0; +} + +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.428571429; + color: #999999; +} + +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, .navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid; + content: ""; +} + +.dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +@media (min-width:768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } +} + +.btn-group, .btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} + + .btn-group > .btn, .btn-group-vertical > .btn { + position: relative; + float: left; + } + + .btn-group > .btn:hover, .btn-group-vertical > .btn:hover, .btn-group > .btn:focus, .btn-group-vertical > .btn:focus, .btn-group > .btn:active, .btn-group-vertical > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn.active { + z-index: 2; + } + + .btn-group > .btn:focus, .btn-group-vertical > .btn:focus { + outline: none; + } + + .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, .btn-group .btn-group + .btn-group { + margin-left: -1px; + } + +.btn-toolbar:before, .btn-toolbar:after { + content: " "; + display: table; +} + +.btn-toolbar:after { + clear: both; +} + +.btn-toolbar:before, .btn-toolbar:after { + content: " "; + display: table; +} + +.btn-toolbar:after { + clear: both; +} + +.btn-toolbar .btn-group { + float: left; +} + +.btn-toolbar > .btn + .btn, .btn-toolbar > .btn-group + .btn, .btn-toolbar > .btn + .btn-group, .btn-toolbar > .btn-group + .btn-group { + margin-left: 5px; +} + +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +.btn-group > .btn:first-child { + margin-left: 0; +} + + .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + +.btn-group > .btn:last-child:not(:first-child), .btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.btn-group > .btn-group { + float: left; +} + + .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; + } + + .btn-group > .btn-group:first-child > .btn:last-child, .btn-group > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + + .btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + } + +.btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} + +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} + +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + + .btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; + } + +.btn .caret { + margin-left: 0; +} + +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} + +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} + +.btn-group-vertical > .btn, .btn-group-vertical > .btn-group, .btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} + + .btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after { + content: " "; + display: table; + } + + .btn-group-vertical > .btn-group:after { + clear: both; + } + + .btn-group-vertical > .btn-group:before, .btn-group-vertical > .btn-group:after { + content: " "; + display: table; + } + + .btn-group-vertical > .btn-group:after { + clear: both; + } + + .btn-group-vertical > .btn-group > .btn { + float: none; + } + + .btn-group-vertical > .btn + .btn, .btn-group-vertical > .btn + .btn-group, .btn-group-vertical > .btn-group + .btn, .btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; + } + + .btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; + } + + .btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } + + .btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; + } + + .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; + } + + .btn-group-vertical > .btn-group:first-child > .btn:last-child, .btn-group-vertical > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } + + .btn-group-vertical > .btn-group:last-child > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; + } + +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} + + .btn-group-justified > .btn, .btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; + } + + .btn-group-justified > .btn-group .btn { + width: 100%; + } + +[data-toggle="buttons"] > .btn > input[type="radio"], [data-toggle="buttons"] > .btn > input[type="checkbox"] { + display: none; +} + +.input-group { + position: relative; + display: table; + border-collapse: separate; +} + + .input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; + } + + .input-group .form-control { + width: 100%; + margin-bottom: 0; + } + +.input-group-lg > .form-control, .input-group-lg > .input-group-addon, .input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +select.input-group-lg > .form-control, select.input-group-lg > .input-group-addon, select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} + +textarea.input-group-lg > .form-control, textarea.input-group-lg > .input-group-addon, textarea.input-group-lg > .input-group-btn > .btn { + height: auto; +} + +.input-group-sm > .form-control, .input-group-sm > .input-group-addon, .input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +select.input-group-sm > .form-control, select.input-group-sm > .input-group-addon, select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} + +textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group-addon, textarea.input-group-sm > .input-group-btn > .btn { + height: auto; +} + +.input-group-addon, .input-group-btn, .input-group .form-control { + display: table-cell; +} + + .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child), .input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; + } + +.input-group-addon, .input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} + +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} + + .input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; + } + + .input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; + } + + .input-group-addon input[type="radio"], .input-group-addon input[type="checkbox"] { + margin-top: 0; + } + + .input-group .form-control:first-child, .input-group-addon:first-child, .input-group-btn:first-child > .btn, .input-group-btn:first-child > .dropdown-toggle, .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + + .input-group-addon:first-child { + border-right: 0; + } + + .input-group .form-control:last-child, .input-group-addon:last-child, .input-group-btn:last-child > .btn, .input-group-btn:last-child > .dropdown-toggle, .input-group-btn:first-child > .btn:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + } + + .input-group-addon:last-child { + border-left: 0; + } + +.input-group-btn { + position: relative; + white-space: nowrap; +} + + .input-group-btn:first-child > .btn { + margin-right: -1px; + } + + .input-group-btn:last-child > .btn { + margin-left: -1px; + } + + .input-group-btn > .btn { + position: relative; + } + + .input-group-btn > .btn + .btn { + margin-left: -4px; + } + + .input-group-btn > .btn:hover, .input-group-btn > .btn:active { + z-index: 2; + } + +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} + + .nav:before, .nav:after { + content: " "; + display: table; + } + + .nav:after { + clear: both; + } + + .nav:before, .nav:after { + content: " "; + display: table; + } + + .nav:after { + clear: both; + } + + .nav > li { + position: relative; + display: block; + } + + .nav > li > a { + position: relative; + display: block; + padding: 10px 15px; + } + + .nav > li > a:hover, .nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; + } + + .nav > li.disabled > a { + color: #999999; + } + + .nav > li.disabled > a:hover, .nav > li.disabled > a:focus { + color: #999999; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; + } + + .nav .open > a, .nav .open > a:hover, .nav .open > a:focus { + background-color: #eeeeee; + border-color: #428bca; + } + + .nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; + } + + .nav > li > a > img { + max-width: none; + } + +.nav-tabs { + border-bottom: 1px solid #dddddd; +} + + .nav-tabs > li { + float: left; + margin-bottom: -1px; + } + + .nav-tabs > li > a { + margin-right: 2px; + line-height: 1.428571429; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; + } + + .nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; + } + + .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { + color: #555555; + background-color: #ffffff; + border: 1px solid #dddddd; + border-bottom-color: transparent; + cursor: default; + } + + .nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; + } + + .nav-tabs.nav-justified > li { + float: none; + } + + .nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; + } + + .nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; + } + +@media (min-width:768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} + +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} + +.nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #dddddd; +} + +@media (min-width:768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + + .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} + +.nav-pills > li { + float: left; +} + + .nav-pills > li > a { + border-radius: 4px; + } + + .nav-pills > li + li { + margin-left: 2px; + } + + .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #428bca; + } + +.nav-stacked > li { + float: none; +} + + .nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; + } + +.nav-justified { + width: 100%; +} + + .nav-justified > li { + float: none; + } + + .nav-justified > li > a { + text-align: center; + margin-bottom: 5px; + } + + .nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; + } + +@media (min-width:768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + + .nav-justified > li > a { + margin-bottom: 0; + } +} + +.nav-tabs-justified { + border-bottom: 0; +} + + .nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; + } + + .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { + border: 1px solid #dddddd; + } + +@media (min-width:768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + + .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} + +.tab-content > .tab-pane { + display: none; +} + +.tab-content > .active { + display: block; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} + + .navbar:before, .navbar:after { + content: " "; + display: table; + } + + .navbar:after { + clear: both; + } + + .navbar:before, .navbar:after { + content: " "; + display: table; + } + + .navbar:after { + clear: both; + } + +@media (min-width:768px) { + .navbar { + border-radius: 4px; + } +} + +.navbar-header:before, .navbar-header:after { + content: " "; + display: table; +} + +.navbar-header:after { + clear: both; +} + +.navbar-header:before, .navbar-header:after { + content: " "; + display: table; +} + +.navbar-header:after { + clear: both; +} + +@media (min-width:768px) { + .navbar-header { + float: left; + } +} + +.navbar-collapse { + max-height: 340px; + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} + + .navbar-collapse:before, .navbar-collapse:after { + content: " "; + display: table; + } + + .navbar-collapse:after { + clear: both; + } + + .navbar-collapse:before, .navbar-collapse:after { + content: " "; + display: table; + } + + .navbar-collapse:after { + clear: both; + } + + .navbar-collapse.in { + overflow-y: auto; + } + +@media (min-width:768px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + + .navbar-collapse.in { + overflow-y: visible; + } + + .navbar-fixed-top .navbar-collapse, .navbar-static-top .navbar-collapse, .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} + +.container > .navbar-header, .container > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} + +@media (min-width:768px) { + .container > .navbar-header, .container > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} + +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} + +@media (min-width:768px) { + .navbar-static-top { + border-radius: 0; + } +} + +.navbar-fixed-top, .navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} + +@media (min-width:768px) { + .navbar-fixed-top, .navbar-fixed-bottom { + border-radius: 0; + } +} + +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} + +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} + +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} + + .navbar-brand:hover, .navbar-brand:focus { + text-decoration: none; + } + +@media (min-width:768px) { + .navbar > .container .navbar-brand { + margin-left: -15px; + } +} + +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} + + .navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; + } + + .navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; + } + +@media (min-width:768px) { + .navbar-toggle { + display: none; + } +} + +.navbar-nav { + margin: 7.5px -15px; +} + + .navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; + } + +@media (max-width:767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + + .navbar-nav .open .dropdown-menu > li > a, .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + + .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} + +@media (min-width:768px) { + .navbar-nav { + float: left; + margin: 0; + } + + .navbar-nav > li { + float: left; + } + + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } + + .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } +} + +@media (min-width:768px) { + .navbar-left { + float: left !important; + } + + .navbar-right { + float: right !important; + } +} + +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1),0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 8px; + margin-bottom: 8px; +} + +@media (min-width:768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .form-control { + display: inline-block; + } + + .navbar-form select.form-control { + width: auto; + } + + .navbar-form .radio, .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; + } + + .navbar-form .radio input[type="radio"], .navbar-form .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } +} + +@media (max-width:767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } +} + +@media (min-width:768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + + .navbar-form.navbar-right:last-child { + margin-right: -15px; + } +} + +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.navbar-nav.pull-right > li > .dropdown-menu, .navbar-nav > li > .dropdown-menu.pull-right { + left: auto; + right: 0; +} + +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} + + .navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; + } + + .navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; + } + +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} + +@media (min-width:768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } + + .navbar-text.navbar-right:last-child { + margin-right: 0; + } +} + +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} + + .navbar-default .navbar-brand { + color: #777777; + } + + .navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; + } + + .navbar-default .navbar-text { + color: #777777; + } + + .navbar-default .navbar-nav > li > a { + color: #777777; + } + + .navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; + } + + .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + + .navbar-default .navbar-nav > .disabled > a, .navbar-default .navbar-nav > .disabled > a:hover, .navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } + + .navbar-default .navbar-toggle { + border-color: #dddddd; + } + + .navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { + background-color: #dddddd; + } + + .navbar-default .navbar-toggle .icon-bar { + background-color: #cccccc; + } + + .navbar-default .navbar-collapse, .navbar-default .navbar-form { + border-color: #e7e7e7; + } + + .navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus { + background-color: #e7e7e7; + color: #555555; + } + +@media (max-width:767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} + +.navbar-default .navbar-link { + color: #777777; +} + + .navbar-default .navbar-link:hover { + color: #333333; + } + +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} + + .navbar-inverse .navbar-brand { + color: #999999; + } + + .navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; + } + + .navbar-inverse .navbar-text { + color: #999999; + } + + .navbar-inverse .navbar-nav > li > a { + color: #999999; + } + + .navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; + } + + .navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + + .navbar-inverse .navbar-nav > .disabled > a, .navbar-inverse .navbar-nav > .disabled > a:hover, .navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; + } + + .navbar-inverse .navbar-toggle { + border-color: #333333; + } + + .navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { + background-color: #333333; + } + + .navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; + } + + .navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { + border-color: #101010; + } + + .navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:hover, .navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #ffffff; + } + +@media (max-width:767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999999; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} + +.navbar-inverse .navbar-link { + color: #999999; +} + + .navbar-inverse .navbar-link:hover { + color: #ffffff; + } + +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} + + .breadcrumb > li { + display: inline-block; + } + + .breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; + } + + .breadcrumb > .active { + color: #999999; + } + +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} + + .pagination > li { + display: inline; + } + + .pagination > li > a, .pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.428571429; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; + margin-left: -1px; + } + + .pagination > li:first-child > a, .pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; + } + + .pagination > li:last-child > a, .pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; + } + + .pagination > li > a:hover, .pagination > li > span:hover, .pagination > li > a:focus, .pagination > li > span:focus { + background-color: #eeeeee; + } + + .pagination > .active > a, .pagination > .active > span, .pagination > .active > a:hover, .pagination > .active > span:hover, .pagination > .active > a:focus, .pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #428bca; + border-color: #428bca; + cursor: default; + } + + .pagination > .disabled > span, .pagination > .disabled > span:hover, .pagination > .disabled > span:focus, .pagination > .disabled > a, .pagination > .disabled > a:hover, .pagination > .disabled > a:focus { + color: #999999; + background-color: #ffffff; + border-color: #dddddd; + cursor: not-allowed; + } + +.pagination-lg > li > a, .pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} + +.pagination-lg > li:first-child > a, .pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} + +.pagination-lg > li:last-child > a, .pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} + +.pagination-sm > li > a, .pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} + +.pagination-sm > li:first-child > a, .pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} + +.pagination-sm > li:last-child > a, .pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} + +.pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} + + .pager:before, .pager:after { + content: " "; + display: table; + } + + .pager:after { + clear: both; + } + + .pager:before, .pager:after { + content: " "; + display: table; + } + + .pager:after { + clear: both; + } + + .pager li { + display: inline; + } + + .pager li > a, .pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 15px; + } + + .pager li > a:hover, .pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; + } + + .pager .next > a, .pager .next > span { + float: right; + } + + .pager .previous > a, .pager .previous > span { + float: left; + } + + .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { + color: #999999; + background-color: #ffffff; + cursor: not-allowed; + } + +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} + + .label[href]:hover, .label[href]:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; + } + + .label:empty { + display: none; + } + +.btn .label { + position: relative; + top: -1px; +} + +.label-default { + background-color: #999999; +} + + .label-default[href]:hover, .label-default[href]:focus { + background-color: #808080; + } + +.label-primary { + background-color: #428bca; +} + + .label-primary[href]:hover, .label-primary[href]:focus { + background-color: #3071a9; + } + +.label-success { + background-color: #5cb85c; +} + + .label-success[href]:hover, .label-success[href]:focus { + background-color: #449d44; + } + +.label-info { + background-color: #5bc0de; +} + + .label-info[href]:hover, .label-info[href]:focus { + background-color: #31b0d5; + } + +.label-warning { + background-color: #f0ad4e; +} + + .label-warning[href]:hover, .label-warning[href]:focus { + background-color: #ec971f; + } + +.label-danger { + background-color: #d9534f; +} + + .label-danger[href]:hover, .label-danger[href]:focus { + background-color: #c9302c; + } + +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #999999; + border-radius: 10px; +} + + .badge:empty { + display: none; + } + +.btn .badge { + position: relative; + top: -1px; +} + +a.badge:hover, a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +a.list-group-item.active > .badge, .nav-pills > .active > a > .badge { + color: #428bca; + background-color: #ffffff; +} + +.nav-pills > li > a > .badge { + margin-left: 3px; +} + +.jumbotron { + padding: 30px; + margin-bottom: 30px; + font-size: 21px; + font-weight: 200; + line-height: 2.1428571435; + color: inherit; + background-color: #eeeeee; +} + + .jumbotron h1, .jumbotron .h1 { + line-height: 1; + color: inherit; + } + + .jumbotron p { + line-height: 1.4; + } + +.container .jumbotron { + border-radius: 6px; +} + +.jumbotron .container { + max-width: 100%; +} + +@media screen and (min-width:768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + + .container .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + + .jumbotron h1, .jumbotron .h1 { + font-size: 63px; + } +} + +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + + .thumbnail > img, .thumbnail a > img { + display: block; + max-width: 100%; + height: auto; + margin-left: auto; + margin-right: auto; + } + +a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active { + border-color: #428bca; +} + +.thumbnail .caption { + padding: 9px; + color: #333333; +} + +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} + + .alert h4 { + margin-top: 0; + color: inherit; + } + + .alert .alert-link { + font-weight: bold; + } + + .alert > p, .alert > ul { + margin-bottom: 0; + } + + .alert > p + p { + margin-top: 5px; + } + +.alert-dismissable { + padding-right: 35px; +} + + .alert-dismissable .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; + } + +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; +} + + .alert-success hr { + border-top-color: #c9e2b3; + } + + .alert-success .alert-link { + color: #2b542c; + } + +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; +} + + .alert-info hr { + border-top-color: #a6e1ec; + } + + .alert-info .alert-link { + color: #245269; + } + +.alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; +} + + .alert-warning hr { + border-top-color: #f7e1b5; + } + + .alert-warning .alert-link { + color: #66512c; + } + +.alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; +} + + .alert-danger hr { + border-top-color: #e4b9c0; + } + + .alert-danger .alert-link { + color: #843534; + } + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + + to { + background-position: 0 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + + to { + background-position: 0 0; + } +} + +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #ffffff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress-striped .progress-bar { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} + +.progress.active .progress-bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-bar-success { + background-color: #5cb85c; +} + +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-info { + background-color: #5bc0de; +} + +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-warning { + background-color: #f0ad4e; +} + +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-danger { + background-color: #d9534f; +} + +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.media, .media-body { + overflow: hidden; + zoom: 1; +} + + .media, .media .media { + margin-top: 15px; + } + + .media:first-child { + margin-top: 0; + } + +.media-object { + display: block; +} + +.media-heading { + margin: 0 0 5px; +} + +.media > .pull-left { + margin-right: 10px; +} + +.media > .pull-right { + margin-left: 10px; +} + +.media-list { + padding-left: 0; + list-style: none; +} + +.list-group { + margin-bottom: 20px; + padding-left: 0; +} + +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} + + .list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; + } + + .list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + } + + .list-group-item > .badge { + float: right; + } + + .list-group-item > .badge + .badge { + margin-right: 5px; + } + +a.list-group-item { + color: #555555; +} + + a.list-group-item .list-group-item-heading { + color: #333333; + } + + a.list-group-item:hover, a.list-group-item:focus { + text-decoration: none; + background-color: #f5f5f5; + } + + a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #428bca; + border-color: #428bca; + } + + a.list-group-item.active .list-group-item-heading, a.list-group-item.active:hover .list-group-item-heading, a.list-group-item.active:focus .list-group-item-heading { + color: inherit; + } + + a.list-group-item.active .list-group-item-text, a.list-group-item.active:hover .list-group-item-text, a.list-group-item.active:focus .list-group-item-text { + color: #e1edf7; + } + +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} + +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} + +.panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.panel-body { + padding: 15px; +} + + .panel-body:before, .panel-body:after { + content: " "; + display: table; + } + + .panel-body:after { + clear: both; + } + + .panel-body:before, .panel-body:after { + content: " "; + display: table; + } + + .panel-body:after { + clear: both; + } + +.panel > .list-group { + margin-bottom: 0; +} + + .panel > .list-group .list-group-item { + border-width: 1px 0; + } + + .panel > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; + } + + .panel > .list-group .list-group-item:last-child { + border-bottom: 0; + } + +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} + +.panel > .table, .panel > .table-responsive > .table { + margin-bottom: 0; +} + +.panel > .panel-body + .table, .panel > .panel-body + .table-responsive { + border-top: 1px solid #dddddd; +} + +.panel > .table > tbody:first-child th, .panel > .table > tbody:first-child td { + border-top: 0; +} + +.panel > .table-bordered, .panel > .table-responsive > .table-bordered { + border: 0; +} + + .panel > .table-bordered > thead > tr > th:first-child, .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, .panel > .table-bordered > tbody > tr > th:first-child, .panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, .panel > .table-bordered > tfoot > tr > th:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, .panel > .table-bordered > thead > tr > td:first-child, .panel > .table-responsive > .table-bordered > thead > tr > td:first-child, .panel > .table-bordered > tbody > tr > td:first-child, .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, .panel > .table-bordered > tfoot > tr > td:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + + .panel > .table-bordered > thead > tr > th:last-child, .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, .panel > .table-bordered > tbody > tr > th:last-child, .panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, .panel > .table-bordered > tfoot > tr > th:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, .panel > .table-bordered > thead > tr > td:last-child, .panel > .table-responsive > .table-bordered > thead > tr > td:last-child, .panel > .table-bordered > tbody > tr > td:last-child, .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, .panel > .table-bordered > tfoot > tr > td:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + + .panel > .table-bordered > thead > tr:last-child > th, .panel > .table-responsive > .table-bordered > thead > tr:last-child > th, .panel > .table-bordered > tbody > tr:last-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, .panel > .table-bordered > tfoot > tr:last-child > th, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th, .panel > .table-bordered > thead > tr:last-child > td, .panel > .table-responsive > .table-bordered > thead > tr:last-child > td, .panel > .table-bordered > tbody > tr:last-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, .panel > .table-bordered > tfoot > tr:last-child > td, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } + +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} + +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} + + .panel-heading > .dropdown .dropdown-toggle { + color: inherit; + } + +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} + + .panel-title > a { + color: inherit; + } + +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; + overflow: hidden; +} + + .panel-group .panel + .panel { + margin-top: 5px; + } + +.panel-group .panel-heading { + border-bottom: 0; +} + + .panel-group .panel-heading + .panel-collapse .panel-body { + border-top: 1px solid #dddddd; + } + +.panel-group .panel-footer { + border-top: 0; +} + + .panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; + } + +.panel-default { + border-color: #dddddd; +} + + .panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; + } + + .panel-default > .panel-heading + .panel-collapse .panel-body { + border-top-color: #dddddd; + } + + .panel-default > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #dddddd; + } + +.panel-primary { + border-color: #428bca; +} + + .panel-primary > .panel-heading { + color: #ffffff; + background-color: #428bca; + border-color: #428bca; + } + + .panel-primary > .panel-heading + .panel-collapse .panel-body { + border-top-color: #428bca; + } + + .panel-primary > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #428bca; + } + +.panel-success { + border-color: #d6e9c6; +} + + .panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; + } + + .panel-success > .panel-heading + .panel-collapse .panel-body { + border-top-color: #d6e9c6; + } + + .panel-success > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #d6e9c6; + } + +.panel-warning { + border-color: #faebcc; +} + + .panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; + } + + .panel-warning > .panel-heading + .panel-collapse .panel-body { + border-top-color: #faebcc; + } + + .panel-warning > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #faebcc; + } + +.panel-danger { + border-color: #ebccd1; +} + + .panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; + } + + .panel-danger > .panel-heading + .panel-collapse .panel-body { + border-top-color: #ebccd1; + } + + .panel-danger > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #ebccd1; + } + +.panel-info { + border-color: #bce8f1; +} + + .panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; + } + + .panel-info > .panel-heading + .panel-collapse .panel-body { + border-top-color: #bce8f1; + } + + .panel-info > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #bce8f1; + } + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + + .well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); + } + +.well-lg { + padding: 24px; + border-radius: 6px; +} + +.well-sm { + padding: 9px; + border-radius: 3px; +} + +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + + .close:hover, .close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); + } + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.modal-open { + overflow: hidden; +} + +.modal { + display: none; + overflow: auto; + overflow-y: scroll; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; +} + + .modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; + } + + .modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); + } + +.modal-dialog { + position: relative; + width: auto; + margin: 10px; + z-index: 1050; +} + +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; + outline: none; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; + background-color: #000000; +} + + .modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); + } + + .modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); + } + +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.428571429px; +} + + .modal-header .close { + margin-top: -2px; + } + +.modal-title { + margin: 0; + line-height: 1.428571429; +} + +.modal-body { + position: relative; + padding: 20px; +} + +.modal-footer { + margin-top: 15px; + padding: 19px 20px 20px; + text-align: right; + border-top: 1px solid #e5e5e5; +} + + .modal-footer:before, .modal-footer:after { + content: " "; + display: table; + } + + .modal-footer:after { + clear: both; + } + + .modal-footer:before, .modal-footer:after { + content: " "; + display: table; + } + + .modal-footer:after { + clear: both; + } + + .modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; + } + + .modal-footer .btn-group .btn + .btn { + margin-left: -1px; + } + + .modal-footer .btn-block + .btn-block { + margin-left: 0; + } + +@media screen and (min-width:768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + visibility: visible; + font-size: 12px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} + + .tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); + } + + .tooltip.top { + margin-top: -3px; + padding: 5px 0; + } + + .tooltip.right { + margin-left: 3px; + padding: 0 5px; + } + + .tooltip.bottom { + margin-top: 3px; + padding: 5px 0; + } + + .tooltip.left { + margin-left: -3px; + padding: 0 5px; + } + +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} + +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} + +.tooltip.top-right .tooltip-arrow { + bottom: 0; + right: 5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} + +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} + +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + background-color: #ffffff; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} + + .popover.top { + margin-top: -10px; + } + + .popover.right { + margin-left: 10px; + } + + .popover.bottom { + margin-top: 10px; + } + + .popover.left { + margin-left: -10px; + } + +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} + +.popover-content { + padding: 9px 14px; +} + +.popover .arrow, .popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow { + border-width: 11px; +} + + .popover .arrow:after { + border-width: 10px; + content: ""; + } + +.popover.top .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} + + .popover.top .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; + } + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} + + .popover.right .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; + } + +.popover.bottom .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} + + .popover.bottom .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; + } + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} + + .popover.left .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; + } + +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} + + .carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; + } + + .carousel-inner > .item > img, .carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; + line-height: 1; + } + + .carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { + display: block; + } + + .carousel-inner > .active { + left: 0; + } + + .carousel-inner > .next, .carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; + } + + .carousel-inner > .next { + left: 100%; + } + + .carousel-inner > .prev { + left: -100%; + } + + .carousel-inner > .next.left, .carousel-inner > .prev.right { + left: 0; + } + + .carousel-inner > .active.left { + left: -100%; + } + + .carousel-inner > .active.right { + left: 100%; + } + +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} + + .carousel-control.left { + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0%), color-stop(rgba(0, 0, 0, 0.0001) 100%)); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + } + + .carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0%), color-stop(rgba(0, 0, 0, 0.5) 100%)); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + } + + .carousel-control:hover, .carousel-control:focus { + outline: none; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); + } + + .carousel-control .icon-prev, .carousel-control .icon-next, .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + } + + .carousel-control .icon-prev, .carousel-control .glyphicon-chevron-left { + left: 50%; + } + + .carousel-control .icon-next, .carousel-control .glyphicon-chevron-right { + right: 50%; + } + + .carousel-control .icon-prev, .carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + font-family: serif; + } + + .carousel-control .icon-prev:before { + content: '\2039'; + } + + .carousel-control .icon-next:before { + content: '\203a'; + } + +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} + + .carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + } + + .carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; + } + +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} + + .carousel-caption .btn { + text-shadow: none; + } + +@media screen and (min-width:768px) { + .carousel-control .glyphicons-chevron-left, .carousel-control .glyphicons-chevron-right, .carousel-control .icon-prev, .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + margin-left: -15px; + font-size: 30px; + } + + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + + .carousel-indicators { + bottom: 20px; + } +} + +.clearfix:before, .clearfix:after { + content: " "; + display: table; +} + +.clearfix:after { + clear: both; +} + +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} + +.pull-right { + float: right !important; +} + +.pull-left { + float: left !important; +} + +.hide { + display: none !important; +} + +.show { + display: block !important; +} + +.invisible { + visibility: hidden; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.hidden { + display: none !important; + visibility: hidden !important; +} + +.affix { + position: fixed; +} + +@-ms-viewport { + width: device-width; +} + +.visible-xs, tr.visible-xs, th.visible-xs, td.visible-xs { + display: none !important; +} + +@media (max-width:767px) { + .visible-xs { + display: block !important; + } + + table.visible-xs { + display: table; + } + + tr.visible-xs { + display: table-row !important; + } + + th.visible-xs, td.visible-xs { + display: table-cell !important; + } +} + +@media (min-width:768px) and (max-width:991px) { + .visible-xs.visible-sm { + display: block !important; + } + + table.visible-xs.visible-sm { + display: table; + } + + tr.visible-xs.visible-sm { + display: table-row !important; + } + + th.visible-xs.visible-sm, td.visible-xs.visible-sm { + display: table-cell !important; + } +} + +@media (min-width:992px) and (max-width:1199px) { + .visible-xs.visible-md { + display: block !important; + } + + table.visible-xs.visible-md { + display: table; + } + + tr.visible-xs.visible-md { + display: table-row !important; + } + + th.visible-xs.visible-md, td.visible-xs.visible-md { + display: table-cell !important; + } +} + +@media (min-width:1200px) { + .visible-xs.visible-lg { + display: block !important; + } + + table.visible-xs.visible-lg { + display: table; + } + + tr.visible-xs.visible-lg { + display: table-row !important; + } + + th.visible-xs.visible-lg, td.visible-xs.visible-lg { + display: table-cell !important; + } +} + +.visible-sm, tr.visible-sm, th.visible-sm, td.visible-sm { + display: none !important; +} + +@media (max-width:767px) { + .visible-sm.visible-xs { + display: block !important; + } + + table.visible-sm.visible-xs { + display: table; + } + + tr.visible-sm.visible-xs { + display: table-row !important; + } + + th.visible-sm.visible-xs, td.visible-sm.visible-xs { + display: table-cell !important; + } +} + +@media (min-width:768px) and (max-width:991px) { + .visible-sm { + display: block !important; + } + + table.visible-sm { + display: table; + } + + tr.visible-sm { + display: table-row !important; + } + + th.visible-sm, td.visible-sm { + display: table-cell !important; + } +} + +@media (min-width:992px) and (max-width:1199px) { + .visible-sm.visible-md { + display: block !important; + } + + table.visible-sm.visible-md { + display: table; + } + + tr.visible-sm.visible-md { + display: table-row !important; + } + + th.visible-sm.visible-md, td.visible-sm.visible-md { + display: table-cell !important; + } +} + +@media (min-width:1200px) { + .visible-sm.visible-lg { + display: block !important; + } + + table.visible-sm.visible-lg { + display: table; + } + + tr.visible-sm.visible-lg { + display: table-row !important; + } + + th.visible-sm.visible-lg, td.visible-sm.visible-lg { + display: table-cell !important; + } +} + +.visible-md, tr.visible-md, th.visible-md, td.visible-md { + display: none !important; +} + +@media (max-width:767px) { + .visible-md.visible-xs { + display: block !important; + } + + table.visible-md.visible-xs { + display: table; + } + + tr.visible-md.visible-xs { + display: table-row !important; + } + + th.visible-md.visible-xs, td.visible-md.visible-xs { + display: table-cell !important; + } +} + +@media (min-width:768px) and (max-width:991px) { + .visible-md.visible-sm { + display: block !important; + } + + table.visible-md.visible-sm { + display: table; + } + + tr.visible-md.visible-sm { + display: table-row !important; + } + + th.visible-md.visible-sm, td.visible-md.visible-sm { + display: table-cell !important; + } +} + +@media (min-width:992px) and (max-width:1199px) { + .visible-md { + display: block !important; + } + + table.visible-md { + display: table; + } + + tr.visible-md { + display: table-row !important; + } + + th.visible-md, td.visible-md { + display: table-cell !important; + } +} + +@media (min-width:1200px) { + .visible-md.visible-lg { + display: block !important; + } + + table.visible-md.visible-lg { + display: table; + } + + tr.visible-md.visible-lg { + display: table-row !important; + } + + th.visible-md.visible-lg, td.visible-md.visible-lg { + display: table-cell !important; + } +} + +.visible-lg, tr.visible-lg, th.visible-lg, td.visible-lg { + display: none !important; +} + +@media (max-width:767px) { + .visible-lg.visible-xs { + display: block !important; + } + + table.visible-lg.visible-xs { + display: table; + } + + tr.visible-lg.visible-xs { + display: table-row !important; + } + + th.visible-lg.visible-xs, td.visible-lg.visible-xs { + display: table-cell !important; + } +} + +@media (min-width:768px) and (max-width:991px) { + .visible-lg.visible-sm { + display: block !important; + } + + table.visible-lg.visible-sm { + display: table; + } + + tr.visible-lg.visible-sm { + display: table-row !important; + } + + th.visible-lg.visible-sm, td.visible-lg.visible-sm { + display: table-cell !important; + } +} + +@media (min-width:992px) and (max-width:1199px) { + .visible-lg.visible-md { + display: block !important; + } + + table.visible-lg.visible-md { + display: table; + } + + tr.visible-lg.visible-md { + display: table-row !important; + } + + th.visible-lg.visible-md, td.visible-lg.visible-md { + display: table-cell !important; + } +} + +@media (min-width:1200px) { + .visible-lg { + display: block !important; + } + + table.visible-lg { + display: table; + } + + tr.visible-lg { + display: table-row !important; + } + + th.visible-lg, td.visible-lg { + display: table-cell !important; + } +} + +.hidden-xs { + display: block !important; +} + +table.hidden-xs { + display: table; +} + +tr.hidden-xs { + display: table-row !important; +} + +th.hidden-xs, td.hidden-xs { + display: table-cell !important; +} + +@media (max-width:767px) { + .hidden-xs, tr.hidden-xs, th.hidden-xs, td.hidden-xs { + display: none !important; + } +} + +@media (min-width:768px) and (max-width:991px) { + .hidden-xs.hidden-sm, tr.hidden-xs.hidden-sm, th.hidden-xs.hidden-sm, td.hidden-xs.hidden-sm { + display: none !important; + } +} + +@media (min-width:992px) and (max-width:1199px) { + .hidden-xs.hidden-md, tr.hidden-xs.hidden-md, th.hidden-xs.hidden-md, td.hidden-xs.hidden-md { + display: none !important; + } +} + +@media (min-width:1200px) { + .hidden-xs.hidden-lg, tr.hidden-xs.hidden-lg, th.hidden-xs.hidden-lg, td.hidden-xs.hidden-lg { + display: none !important; + } +} + +.hidden-sm { + display: block !important; +} + +table.hidden-sm { + display: table; +} + +tr.hidden-sm { + display: table-row !important; +} + +th.hidden-sm, td.hidden-sm { + display: table-cell !important; +} + +@media (max-width:767px) { + .hidden-sm.hidden-xs, tr.hidden-sm.hidden-xs, th.hidden-sm.hidden-xs, td.hidden-sm.hidden-xs { + display: none !important; + } +} + +@media (min-width:768px) and (max-width:991px) { + .hidden-sm, tr.hidden-sm, th.hidden-sm, td.hidden-sm { + display: none !important; + } +} + +@media (min-width:992px) and (max-width:1199px) { + .hidden-sm.hidden-md, tr.hidden-sm.hidden-md, th.hidden-sm.hidden-md, td.hidden-sm.hidden-md { + display: none !important; + } +} + +@media (min-width:1200px) { + .hidden-sm.hidden-lg, tr.hidden-sm.hidden-lg, th.hidden-sm.hidden-lg, td.hidden-sm.hidden-lg { + display: none !important; + } +} + +.hidden-md { + display: block !important; +} + +table.hidden-md { + display: table; +} + +tr.hidden-md { + display: table-row !important; +} + +th.hidden-md, td.hidden-md { + display: table-cell !important; +} + +@media (max-width:767px) { + .hidden-md.hidden-xs, tr.hidden-md.hidden-xs, th.hidden-md.hidden-xs, td.hidden-md.hidden-xs { + display: none !important; + } +} + +@media (min-width:768px) and (max-width:991px) { + .hidden-md.hidden-sm, tr.hidden-md.hidden-sm, th.hidden-md.hidden-sm, td.hidden-md.hidden-sm { + display: none !important; + } +} + +@media (min-width:992px) and (max-width:1199px) { + .hidden-md, tr.hidden-md, th.hidden-md, td.hidden-md { + display: none !important; + } +} + +@media (min-width:1200px) { + .hidden-md.hidden-lg, tr.hidden-md.hidden-lg, th.hidden-md.hidden-lg, td.hidden-md.hidden-lg { + display: none !important; + } +} + +.hidden-lg { + display: block !important; +} + +table.hidden-lg { + display: table; +} + +tr.hidden-lg { + display: table-row !important; +} + +th.hidden-lg, td.hidden-lg { + display: table-cell !important; +} + +@media (max-width:767px) { + .hidden-lg.hidden-xs, tr.hidden-lg.hidden-xs, th.hidden-lg.hidden-xs, td.hidden-lg.hidden-xs { + display: none !important; + } +} + +@media (min-width:768px) and (max-width:991px) { + .hidden-lg.hidden-sm, tr.hidden-lg.hidden-sm, th.hidden-lg.hidden-sm, td.hidden-lg.hidden-sm { + display: none !important; + } +} + +@media (min-width:992px) and (max-width:1199px) { + .hidden-lg.hidden-md, tr.hidden-lg.hidden-md, th.hidden-lg.hidden-md, td.hidden-lg.hidden-md { + display: none !important; + } +} + +@media (min-width:1200px) { + .hidden-lg, tr.hidden-lg, th.hidden-lg, td.hidden-lg { + display: none !important; + } +} + +.visible-print, tr.visible-print, th.visible-print, td.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: block !important; + } + + table.visible-print { + display: table; + } + + tr.visible-print { + display: table-row !important; + } + + th.visible-print, td.visible-print { + display: table-cell !important; + } + + .hidden-print, tr.hidden-print, th.hidden-print, td.hidden-print { + display: none !important; + } +} diff --git a/网站/style/css/font-awesome.min.css b/网站/style/css/font-awesome.min.css new file mode 100644 index 0000000..c54e1f5 --- /dev/null +++ b/网站/style/css/font-awesome.min.css @@ -0,0 +1,2104 @@ +/*! + * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +@font-face { + font-family: 'FontAwesome'; + src: url('fonts/fontawesome-webfont.eot'); + src: url('fonts/fontawesome-webfont01.eot') format('embedded-opentype'),url('fonts/fontawesome-webfont.woff') format('woff'),url('fonts/fontawesome-webfont.ttf') format('truetype'),url('fonts/fontawesome-webfont.svg') format('svg'); + font-weight: normal; + font-style: normal; +} + +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.fa-lg { + font-size: 1.33333333em; + line-height: .75em; + vertical-align: -15%; +} + +.fa-2x { + font-size: 2em; +} + +.fa-3x { + font-size: 3em; +} + +.fa-4x { + font-size: 4em; +} + +.fa-5x { + font-size: 5em; +} + +.fa-fw { + width: 1.28571429em; + text-align: center; +} + +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} + + .fa-ul > li { + position: relative; + } + +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: .14285714em; + text-align: center; +} + + .fa-li.fa-lg { + left: -1.85714286em; + } + +.fa-border { + padding: .2em .25em .15em; + border: solid .08em #eee; + border-radius: .1em; +} + +.pull-right { + float: right; +} + +.pull-left { + float: left; +} + +.fa.pull-left { + margin-right: .3em; +} + +.fa.pull-right { + margin-left: .3em; +} + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} + +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} + +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} + +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} + +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} + +:root .fa-rotate-90, :root .fa-rotate-180, :root .fa-rotate-270, :root .fa-flip-horizontal, :root .fa-flip-vertical { + filter: none; +} + +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} + +.fa-stack-1x, .fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} + +.fa-stack-1x { + line-height: inherit; +} + +.fa-stack-2x { + font-size: 2em; +} + +.fa-inverse { + color: #fff; +} + +.fa-glass:before { + content: "\f000"; +} + +.fa-music:before { + content: "\f001"; +} + +.fa-search:before { + content: "\f002"; +} + +.fa-envelope-o:before { + content: "\f003"; +} + +.fa-heart:before { + content: "\f004"; +} + +.fa-star:before { + content: "\f005"; +} + +.fa-star-o:before { + content: "\f006"; +} + +.fa-user:before { + content: "\f007"; +} + +.fa-film:before { + content: "\f008"; +} + +.fa-th-large:before { + content: "\f009"; +} + +.fa-th:before { + content: "\f00a"; +} + +.fa-th-list:before { + content: "\f00b"; +} + +.fa-check:before { + content: "\f00c"; +} + +.fa-remove:before, .fa-close:before, .fa-times:before { + content: "\f00d"; +} + +.fa-search-plus:before { + content: "\f00e"; +} + +.fa-search-minus:before { + content: "\f010"; +} + +.fa-power-off:before { + content: "\f011"; +} + +.fa-signal:before { + content: "\f012"; +} + +.fa-gear:before, .fa-cog:before { + content: "\f013"; +} + +.fa-trash-o:before { + content: "\f014"; +} + +.fa-home:before { + content: "\f015"; +} + +.fa-file-o:before { + content: "\f016"; +} + +.fa-clock-o:before { + content: "\f017"; +} + +.fa-road:before { + content: "\f018"; +} + +.fa-download:before { + content: "\f019"; +} + +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} + +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} + +.fa-inbox:before { + content: "\f01c"; +} + +.fa-play-circle-o:before { + content: "\f01d"; +} + +.fa-rotate-right:before, .fa-repeat:before { + content: "\f01e"; +} + +.fa-refresh:before { + content: "\f021"; +} + +.fa-list-alt:before { + content: "\f022"; +} + +.fa-lock:before { + content: "\f023"; +} + +.fa-flag:before { + content: "\f024"; +} + +.fa-headphones:before { + content: "\f025"; +} + +.fa-volume-off:before { + content: "\f026"; +} + +.fa-volume-down:before { + content: "\f027"; +} + +.fa-volume-up:before { + content: "\f028"; +} + +.fa-qrcode:before { + content: "\f029"; +} + +.fa-barcode:before { + content: "\f02a"; +} + +.fa-tag:before { + content: "\f02b"; +} + +.fa-tags:before { + content: "\f02c"; +} + +.fa-book:before { + content: "\f02d"; +} + +.fa-bookmark:before { + content: "\f02e"; +} + +.fa-print:before { + content: "\f02f"; +} + +.fa-camera:before { + content: "\f030"; +} + +.fa-font:before { + content: "\f031"; +} + +.fa-bold:before { + content: "\f032"; +} + +.fa-italic:before { + content: "\f033"; +} + +.fa-text-height:before { + content: "\f034"; +} + +.fa-text-width:before { + content: "\f035"; +} + +.fa-align-left:before { + content: "\f036"; +} + +.fa-align-center:before { + content: "\f037"; +} + +.fa-align-right:before { + content: "\f038"; +} + +.fa-align-justify:before { + content: "\f039"; +} + +.fa-list:before { + content: "\f03a"; +} + +.fa-dedent:before, .fa-outdent:before { + content: "\f03b"; +} + +.fa-indent:before { + content: "\f03c"; +} + +.fa-video-camera:before { + content: "\f03d"; +} + +.fa-photo:before, .fa-image:before, .fa-picture-o:before { + content: "\f03e"; +} + +.fa-pencil:before { + content: "\f040"; +} + +.fa-map-marker:before { + content: "\f041"; +} + +.fa-adjust:before { + content: "\f042"; +} + +.fa-tint:before { + content: "\f043"; +} + +.fa-edit:before, .fa-pencil-square-o:before { + content: "\f044"; +} + +.fa-share-square-o:before { + content: "\f045"; +} + +.fa-check-square-o:before { + content: "\f046"; +} + +.fa-arrows:before { + content: "\f047"; +} + +.fa-step-backward:before { + content: "\f048"; +} + +.fa-fast-backward:before { + content: "\f049"; +} + +.fa-backward:before { + content: "\f04a"; +} + +.fa-play:before { + content: "\f04b"; +} + +.fa-pause:before { + content: "\f04c"; +} + +.fa-stop:before { + content: "\f04d"; +} + +.fa-forward:before { + content: "\f04e"; +} + +.fa-fast-forward:before { + content: "\f050"; +} + +.fa-step-forward:before { + content: "\f051"; +} + +.fa-eject:before { + content: "\f052"; +} + +.fa-chevron-left:before { + content: "\f053"; +} + +.fa-chevron-right:before { + content: "\f054"; +} + +.fa-plus-circle:before { + content: "\f055"; +} + +.fa-minus-circle:before { + content: "\f056"; +} + +.fa-times-circle:before { + content: "\f057"; +} + +.fa-check-circle:before { + content: "\f058"; +} + +.fa-question-circle:before { + content: "\f059"; +} + +.fa-info-circle:before { + content: "\f05a"; +} + +.fa-crosshairs:before { + content: "\f05b"; +} + +.fa-times-circle-o:before { + content: "\f05c"; +} + +.fa-check-circle-o:before { + content: "\f05d"; +} + +.fa-ban:before { + content: "\f05e"; +} + +.fa-arrow-left:before { + content: "\f060"; +} + +.fa-arrow-right:before { + content: "\f061"; +} + +.fa-arrow-up:before { + content: "\f062"; +} + +.fa-arrow-down:before { + content: "\f063"; +} + +.fa-mail-forward:before, .fa-share:before { + content: "\f064"; +} + +.fa-expand:before { + content: "\f065"; +} + +.fa-compress:before { + content: "\f066"; +} + +.fa-plus:before { + content: "\f067"; +} + +.fa-minus:before { + content: "\f068"; +} + +.fa-asterisk:before { + content: "\f069"; +} + +.fa-exclamation-circle:before { + content: "\f06a"; +} + +.fa-gift:before { + content: "\f06b"; +} + +.fa-leaf:before { + content: "\f06c"; +} + +.fa-fire:before { + content: "\f06d"; +} + +.fa-eye:before { + content: "\f06e"; +} + +.fa-eye-slash:before { + content: "\f070"; +} + +.fa-warning:before, .fa-exclamation-triangle:before { + content: "\f071"; +} + +.fa-plane:before { + content: "\f072"; +} + +.fa-calendar:before { + content: "\f073"; +} + +.fa-random:before { + content: "\f074"; +} + +.fa-comment:before { + content: "\f075"; +} + +.fa-magnet:before { + content: "\f076"; +} + +.fa-chevron-up:before { + content: "\f077"; +} + +.fa-chevron-down:before { + content: "\f078"; +} + +.fa-retweet:before { + content: "\f079"; +} + +.fa-shopping-cart:before { + content: "\f07a"; +} + +.fa-folder:before { + content: "\f07b"; +} + +.fa-folder-open:before { + content: "\f07c"; +} + +.fa-arrows-v:before { + content: "\f07d"; +} + +.fa-arrows-h:before { + content: "\f07e"; +} + +.fa-bar-chart-o:before, .fa-bar-chart:before { + content: "\f080"; +} + +.fa-twitter-square:before { + content: "\f081"; +} + +.fa-facebook-square:before { + content: "\f082"; +} + +.fa-camera-retro:before { + content: "\f083"; +} + +.fa-key:before { + content: "\f084"; +} + +.fa-gears:before, .fa-cogs:before { + content: "\f085"; +} + +.fa-comments:before { + content: "\f086"; +} + +.fa-thumbs-o-up:before { + content: "\f087"; +} + +.fa-thumbs-o-down:before { + content: "\f088"; +} + +.fa-star-half:before { + content: "\f089"; +} + +.fa-heart-o:before { + content: "\f08a"; +} + +.fa-sign-out:before { + content: "\f08b"; +} + +.fa-linkedin-square:before { + content: "\f08c"; +} + +.fa-thumb-tack:before { + content: "\f08d"; +} + +.fa-external-link:before { + content: "\f08e"; +} + +.fa-sign-in:before { + content: "\f090"; +} + +.fa-trophy:before { + content: "\f091"; +} + +.fa-github-square:before { + content: "\f092"; +} + +.fa-upload:before { + content: "\f093"; +} + +.fa-lemon-o:before { + content: "\f094"; +} + +.fa-phone:before { + content: "\f095"; +} + +.fa-square-o:before { + content: "\f096"; +} + +.fa-bookmark-o:before { + content: "\f097"; +} + +.fa-phone-square:before { + content: "\f098"; +} + +.fa-twitter:before { + content: "\f099"; +} + +.fa-facebook:before { + content: "\f09a"; +} + +.fa-github:before { + content: "\f09b"; +} + +.fa-unlock:before { + content: "\f09c"; +} + +.fa-credit-card:before { + content: "\f09d"; +} + +.fa-rss:before { + content: "\f09e"; +} + +.fa-hdd-o:before { + content: "\f0a0"; +} + +.fa-bullhorn:before { + content: "\f0a1"; +} + +.fa-bell:before { + content: "\f0f3"; +} + +.fa-certificate:before { + content: "\f0a3"; +} + +.fa-hand-o-right:before { + content: "\f0a4"; +} + +.fa-hand-o-left:before { + content: "\f0a5"; +} + +.fa-hand-o-up:before { + content: "\f0a6"; +} + +.fa-hand-o-down:before { + content: "\f0a7"; +} + +.fa-arrow-circle-left:before { + content: "\f0a8"; +} + +.fa-arrow-circle-right:before { + content: "\f0a9"; +} + +.fa-arrow-circle-up:before { + content: "\f0aa"; +} + +.fa-arrow-circle-down:before { + content: "\f0ab"; +} + +.fa-globe:before { + content: "\f0ac"; +} + +.fa-wrench:before { + content: "\f0ad"; +} + +.fa-tasks:before { + content: "\f0ae"; +} + +.fa-filter:before { + content: "\f0b0"; +} + +.fa-briefcase:before { + content: "\f0b1"; +} + +.fa-arrows-alt:before { + content: "\f0b2"; +} + +.fa-group:before, .fa-users:before { + content: "\f0c0"; +} + +.fa-chain:before, .fa-link:before { + content: "\f0c1"; +} + +.fa-cloud:before { + content: "\f0c2"; +} + +.fa-flask:before { + content: "\f0c3"; +} + +.fa-cut:before, .fa-scissors:before { + content: "\f0c4"; +} + +.fa-copy:before, .fa-files-o:before { + content: "\f0c5"; +} + +.fa-paperclip:before { + content: "\f0c6"; +} + +.fa-save:before, .fa-floppy-o:before { + content: "\f0c7"; +} + +.fa-square:before { + content: "\f0c8"; +} + +.fa-navicon:before, .fa-reorder:before, .fa-bars:before { + content: "\f0c9"; +} + +.fa-list-ul:before { + content: "\f0ca"; +} + +.fa-list-ol:before { + content: "\f0cb"; +} + +.fa-strikethrough:before { + content: "\f0cc"; +} + +.fa-underline:before { + content: "\f0cd"; +} + +.fa-table:before { + content: "\f0ce"; +} + +.fa-magic:before { + content: "\f0d0"; +} + +.fa-truck:before { + content: "\f0d1"; +} + +.fa-pinterest:before { + content: "\f0d2"; +} + +.fa-pinterest-square:before { + content: "\f0d3"; +} + +.fa-google-plus-square:before { + content: "\f0d4"; +} + +.fa-google-plus:before { + content: "\f0d5"; +} + +.fa-money:before { + content: "\f0d6"; +} + +.fa-caret-down:before { + content: "\f0d7"; +} + +.fa-caret-up:before { + content: "\f0d8"; +} + +.fa-caret-left:before { + content: "\f0d9"; +} + +.fa-caret-right:before { + content: "\f0da"; +} + +.fa-columns:before { + content: "\f0db"; +} + +.fa-unsorted:before, .fa-sort:before { + content: "\f0dc"; +} + +.fa-sort-down:before, .fa-sort-desc:before { + content: "\f0dd"; +} + +.fa-sort-up:before, .fa-sort-asc:before { + content: "\f0de"; +} + +.fa-envelope:before { + content: "\f0e0"; +} + +.fa-linkedin:before { + content: "\f0e1"; +} + +.fa-rotate-left:before, .fa-undo:before { + content: "\f0e2"; +} + +.fa-legal:before, .fa-gavel:before { + content: "\f0e3"; +} + +.fa-dashboard:before, .fa-tachometer:before { + content: "\f0e4"; +} + +.fa-comment-o:before { + content: "\f0e5"; +} + +.fa-comments-o:before { + content: "\f0e6"; +} + +.fa-flash:before, .fa-bolt:before { + content: "\f0e7"; +} + +.fa-sitemap:before { + content: "\f0e8"; +} + +.fa-umbrella:before { + content: "\f0e9"; +} + +.fa-paste:before, .fa-clipboard:before { + content: "\f0ea"; +} + +.fa-lightbulb-o:before { + content: "\f0eb"; +} + +.fa-exchange:before { + content: "\f0ec"; +} + +.fa-cloud-download:before { + content: "\f0ed"; +} + +.fa-cloud-upload:before { + content: "\f0ee"; +} + +.fa-user-md:before { + content: "\f0f0"; +} + +.fa-stethoscope:before { + content: "\f0f1"; +} + +.fa-suitcase:before { + content: "\f0f2"; +} + +.fa-bell-o:before { + content: "\f0a2"; +} + +.fa-coffee:before { + content: "\f0f4"; +} + +.fa-cutlery:before { + content: "\f0f5"; +} + +.fa-file-text-o:before { + content: "\f0f6"; +} + +.fa-building-o:before { + content: "\f0f7"; +} + +.fa-hospital-o:before { + content: "\f0f8"; +} + +.fa-ambulance:before { + content: "\f0f9"; +} + +.fa-medkit:before { + content: "\f0fa"; +} + +.fa-fighter-jet:before { + content: "\f0fb"; +} + +.fa-beer:before { + content: "\f0fc"; +} + +.fa-h-square:before { + content: "\f0fd"; +} + +.fa-plus-square:before { + content: "\f0fe"; +} + +.fa-angle-double-left:before { + content: "\f100"; +} + +.fa-angle-double-right:before { + content: "\f101"; +} + +.fa-angle-double-up:before { + content: "\f102"; +} + +.fa-angle-double-down:before { + content: "\f103"; +} + +.fa-angle-left:before { + content: "\f104"; +} + +.fa-angle-right:before { + content: "\f105"; +} + +.fa-angle-up:before { + content: "\f106"; +} + +.fa-angle-down:before { + content: "\f107"; +} + +.fa-desktop:before { + content: "\f108"; +} + +.fa-laptop:before { + content: "\f109"; +} + +.fa-tablet:before { + content: "\f10a"; +} + +.fa-mobile-phone:before, .fa-mobile:before { + content: "\f10b"; +} + +.fa-circle-o:before { + content: "\f10c"; +} + +.fa-quote-left:before { + content: "\f10d"; +} + +.fa-quote-right:before { + content: "\f10e"; +} + +.fa-spinner:before { + content: "\f110"; +} + +.fa-circle:before { + content: "\f111"; +} + +.fa-mail-reply:before, .fa-reply:before { + content: "\f112"; +} + +.fa-github-alt:before { + content: "\f113"; +} + +.fa-folder-o:before { + content: "\f114"; +} + +.fa-folder-open-o:before { + content: "\f115"; +} + +.fa-smile-o:before { + content: "\f118"; +} + +.fa-frown-o:before { + content: "\f119"; +} + +.fa-meh-o:before { + content: "\f11a"; +} + +.fa-gamepad:before { + content: "\f11b"; +} + +.fa-keyboard-o:before { + content: "\f11c"; +} + +.fa-flag-o:before { + content: "\f11d"; +} + +.fa-flag-checkered:before { + content: "\f11e"; +} + +.fa-terminal:before { + content: "\f120"; +} + +.fa-code:before { + content: "\f121"; +} + +.fa-mail-reply-all:before, .fa-reply-all:before { + content: "\f122"; +} + +.fa-star-half-empty:before, .fa-star-half-full:before, .fa-star-half-o:before { + content: "\f123"; +} + +.fa-location-arrow:before { + content: "\f124"; +} + +.fa-crop:before { + content: "\f125"; +} + +.fa-code-fork:before { + content: "\f126"; +} + +.fa-unlink:before, .fa-chain-broken:before { + content: "\f127"; +} + +.fa-question:before { + content: "\f128"; +} + +.fa-info:before { + content: "\f129"; +} + +.fa-exclamation:before { + content: "\f12a"; +} + +.fa-superscript:before { + content: "\f12b"; +} + +.fa-subscript:before { + content: "\f12c"; +} + +.fa-eraser:before { + content: "\f12d"; +} + +.fa-puzzle-piece:before { + content: "\f12e"; +} + +.fa-microphone:before { + content: "\f130"; +} + +.fa-microphone-slash:before { + content: "\f131"; +} + +.fa-shield:before { + content: "\f132"; +} + +.fa-calendar-o:before { + content: "\f133"; +} + +.fa-fire-extinguisher:before { + content: "\f134"; +} + +.fa-rocket:before { + content: "\f135"; +} + +.fa-maxcdn:before { + content: "\f136"; +} + +.fa-chevron-circle-left:before { + content: "\f137"; +} + +.fa-chevron-circle-right:before { + content: "\f138"; +} + +.fa-chevron-circle-up:before { + content: "\f139"; +} + +.fa-chevron-circle-down:before { + content: "\f13a"; +} + +.fa-html5:before { + content: "\f13b"; +} + +.fa-css3:before { + content: "\f13c"; +} + +.fa-anchor:before { + content: "\f13d"; +} + +.fa-unlock-alt:before { + content: "\f13e"; +} + +.fa-bullseye:before { + content: "\f140"; +} + +.fa-ellipsis-h:before { + content: "\f141"; +} + +.fa-ellipsis-v:before { + content: "\f142"; +} + +.fa-rss-square:before { + content: "\f143"; +} + +.fa-play-circle:before { + content: "\f144"; +} + +.fa-ticket:before { + content: "\f145"; +} + +.fa-minus-square:before { + content: "\f146"; +} + +.fa-minus-square-o:before { + content: "\f147"; +} + +.fa-level-up:before { + content: "\f148"; +} + +.fa-level-down:before { + content: "\f149"; +} + +.fa-check-square:before { + content: "\f14a"; +} + +.fa-pencil-square:before { + content: "\f14b"; +} + +.fa-external-link-square:before { + content: "\f14c"; +} + +.fa-share-square:before { + content: "\f14d"; +} + +.fa-compass:before { + content: "\f14e"; +} + +.fa-toggle-down:before, .fa-caret-square-o-down:before { + content: "\f150"; +} + +.fa-toggle-up:before, .fa-caret-square-o-up:before { + content: "\f151"; +} + +.fa-toggle-right:before, .fa-caret-square-o-right:before { + content: "\f152"; +} + +.fa-euro:before, .fa-eur:before { + content: "\f153"; +} + +.fa-gbp:before { + content: "\f154"; +} + +.fa-dollar:before, .fa-usd:before { + content: "\f155"; +} + +.fa-rupee:before, .fa-inr:before { + content: "\f156"; +} + +.fa-cny:before, .fa-rmb:before, .fa-yen:before, .fa-jpy:before { + content: "\f157"; +} + +.fa-ruble:before, .fa-rouble:before, .fa-rub:before { + content: "\f158"; +} + +.fa-won:before, .fa-krw:before { + content: "\f159"; +} + +.fa-bitcoin:before, .fa-btc:before { + content: "\f15a"; +} + +.fa-file:before { + content: "\f15b"; +} + +.fa-file-text:before { + content: "\f15c"; +} + +.fa-sort-alpha-asc:before { + content: "\f15d"; +} + +.fa-sort-alpha-desc:before { + content: "\f15e"; +} + +.fa-sort-amount-asc:before { + content: "\f160"; +} + +.fa-sort-amount-desc:before { + content: "\f161"; +} + +.fa-sort-numeric-asc:before { + content: "\f162"; +} + +.fa-sort-numeric-desc:before { + content: "\f163"; +} + +.fa-thumbs-up:before { + content: "\f164"; +} + +.fa-thumbs-down:before { + content: "\f165"; +} + +.fa-youtube-square:before { + content: "\f166"; +} + +.fa-youtube:before { + content: "\f167"; +} + +.fa-xing:before { + content: "\f168"; +} + +.fa-xing-square:before { + content: "\f169"; +} + +.fa-youtube-play:before { + content: "\f16a"; +} + +.fa-dropbox:before { + content: "\f16b"; +} + +.fa-stack-overflow:before { + content: "\f16c"; +} + +.fa-instagram:before { + content: "\f16d"; +} + +.fa-flickr:before { + content: "\f16e"; +} + +.fa-adn:before { + content: "\f170"; +} + +.fa-bitbucket:before { + content: "\f171"; +} + +.fa-bitbucket-square:before { + content: "\f172"; +} + +.fa-tumblr:before { + content: "\f173"; +} + +.fa-tumblr-square:before { + content: "\f174"; +} + +.fa-long-arrow-down:before { + content: "\f175"; +} + +.fa-long-arrow-up:before { + content: "\f176"; +} + +.fa-long-arrow-left:before { + content: "\f177"; +} + +.fa-long-arrow-right:before { + content: "\f178"; +} + +.fa-apple:before { + content: "\f179"; +} + +.fa-windows:before { + content: "\f17a"; +} + +.fa-android:before { + content: "\f17b"; +} + +.fa-linux:before { + content: "\f17c"; +} + +.fa-dribbble:before { + content: "\f17d"; +} + +.fa-skype:before { + content: "\f17e"; +} + +.fa-foursquare:before { + content: "\f180"; +} + +.fa-trello:before { + content: "\f181"; +} + +.fa-female:before { + content: "\f182"; +} + +.fa-male:before { + content: "\f183"; +} + +.fa-gittip:before { + content: "\f184"; +} + +.fa-sun-o:before { + content: "\f185"; +} + +.fa-moon-o:before { + content: "\f186"; +} + +.fa-archive:before { + content: "\f187"; +} + +.fa-bug:before { + content: "\f188"; +} + +.fa-vk:before { + content: "\f189"; +} + +.fa-weibo:before { + content: "\f18a"; +} + +.fa-renren:before { + content: "\f18b"; +} + +.fa-pagelines:before { + content: "\f18c"; +} + +.fa-stack-exchange:before { + content: "\f18d"; +} + +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} + +.fa-arrow-circle-o-left:before { + content: "\f190"; +} + +.fa-toggle-left:before, .fa-caret-square-o-left:before { + content: "\f191"; +} + +.fa-dot-circle-o:before { + content: "\f192"; +} + +.fa-wheelchair:before { + content: "\f193"; +} + +.fa-vimeo-square:before { + content: "\f194"; +} + +.fa-turkish-lira:before, .fa-try:before { + content: "\f195"; +} + +.fa-plus-square-o:before { + content: "\f196"; +} + +.fa-space-shuttle:before { + content: "\f197"; +} + +.fa-slack:before { + content: "\f198"; +} + +.fa-envelope-square:before { + content: "\f199"; +} + +.fa-wordpress:before { + content: "\f19a"; +} + +.fa-openid:before { + content: "\f19b"; +} + +.fa-institution:before, .fa-bank:before, .fa-university:before { + content: "\f19c"; +} + +.fa-mortar-board:before, .fa-graduation-cap:before { + content: "\f19d"; +} + +.fa-yahoo:before { + content: "\f19e"; +} + +.fa-google:before { + content: "\f1a0"; +} + +.fa-reddit:before { + content: "\f1a1"; +} + +.fa-reddit-square:before { + content: "\f1a2"; +} + +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} + +.fa-stumbleupon:before { + content: "\f1a4"; +} + +.fa-delicious:before { + content: "\f1a5"; +} + +.fa-digg:before { + content: "\f1a6"; +} + +.fa-pied-piper:before { + content: "\f1a7"; +} + +.fa-pied-piper-alt:before { + content: "\f1a8"; +} + +.fa-drupal:before { + content: "\f1a9"; +} + +.fa-joomla:before { + content: "\f1aa"; +} + +.fa-language:before { + content: "\f1ab"; +} + +.fa-fax:before { + content: "\f1ac"; +} + +.fa-building:before { + content: "\f1ad"; +} + +.fa-child:before { + content: "\f1ae"; +} + +.fa-paw:before { + content: "\f1b0"; +} + +.fa-spoon:before { + content: "\f1b1"; +} + +.fa-cube:before { + content: "\f1b2"; +} + +.fa-cubes:before { + content: "\f1b3"; +} + +.fa-behance:before { + content: "\f1b4"; +} + +.fa-behance-square:before { + content: "\f1b5"; +} + +.fa-steam:before { + content: "\f1b6"; +} + +.fa-steam-square:before { + content: "\f1b7"; +} + +.fa-recycle:before { + content: "\f1b8"; +} + +.fa-automobile:before, .fa-car:before { + content: "\f1b9"; +} + +.fa-cab:before, .fa-taxi:before { + content: "\f1ba"; +} + +.fa-tree:before { + content: "\f1bb"; +} + +.fa-spotify:before { + content: "\f1bc"; +} + +.fa-deviantart:before { + content: "\f1bd"; +} + +.fa-soundcloud:before { + content: "\f1be"; +} + +.fa-database:before { + content: "\f1c0"; +} + +.fa-file-pdf-o:before { + content: "\f1c1"; +} + +.fa-file-word-o:before { + content: "\f1c2"; +} + +.fa-file-excel-o:before { + content: "\f1c3"; +} + +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} + +.fa-file-photo-o:before, .fa-file-picture-o:before, .fa-file-image-o:before { + content: "\f1c5"; +} + +.fa-file-zip-o:before, .fa-file-archive-o:before { + content: "\f1c6"; +} + +.fa-file-sound-o:before, .fa-file-audio-o:before { + content: "\f1c7"; +} + +.fa-file-movie-o:before, .fa-file-video-o:before { + content: "\f1c8"; +} + +.fa-file-code-o:before { + content: "\f1c9"; +} + +.fa-vine:before { + content: "\f1ca"; +} + +.fa-codepen:before { + content: "\f1cb"; +} + +.fa-jsfiddle:before { + content: "\f1cc"; +} + +.fa-life-bouy:before, .fa-life-buoy:before, .fa-life-saver:before, .fa-support:before, .fa-life-ring:before { + content: "\f1cd"; +} + +.fa-circle-o-notch:before { + content: "\f1ce"; +} + +.fa-ra:before, .fa-rebel:before { + content: "\f1d0"; +} + +.fa-ge:before, .fa-empire:before { + content: "\f1d1"; +} + +.fa-git-square:before { + content: "\f1d2"; +} + +.fa-git:before { + content: "\f1d3"; +} + +.fa-hacker-news:before { + content: "\f1d4"; +} + +.fa-tencent-weibo:before { + content: "\f1d5"; +} + +.fa-qq:before { + content: "\f1d6"; +} + +.fa-wechat:before, .fa-weixin:before { + content: "\f1d7"; +} + +.fa-send:before, .fa-paper-plane:before { + content: "\f1d8"; +} + +.fa-send-o:before, .fa-paper-plane-o:before { + content: "\f1d9"; +} + +.fa-history:before { + content: "\f1da"; +} + +.fa-circle-thin:before { + content: "\f1db"; +} + +.fa-header:before { + content: "\f1dc"; +} + +.fa-paragraph:before { + content: "\f1dd"; +} + +.fa-sliders:before { + content: "\f1de"; +} + +.fa-share-alt:before { + content: "\f1e0"; +} + +.fa-share-alt-square:before { + content: "\f1e1"; +} + +.fa-bomb:before { + content: "\f1e2"; +} + +.fa-soccer-ball-o:before, .fa-futbol-o:before { + content: "\f1e3"; +} + +.fa-tty:before { + content: "\f1e4"; +} + +.fa-binoculars:before { + content: "\f1e5"; +} + +.fa-plug:before { + content: "\f1e6"; +} + +.fa-slideshare:before { + content: "\f1e7"; +} + +.fa-twitch:before { + content: "\f1e8"; +} + +.fa-yelp:before { + content: "\f1e9"; +} + +.fa-newspaper-o:before { + content: "\f1ea"; +} + +.fa-wifi:before { + content: "\f1eb"; +} + +.fa-calculator:before { + content: "\f1ec"; +} + +.fa-paypal:before { + content: "\f1ed"; +} + +.fa-google-wallet:before { + content: "\f1ee"; +} + +.fa-cc-visa:before { + content: "\f1f0"; +} + +.fa-cc-mastercard:before { + content: "\f1f1"; +} + +.fa-cc-discover:before { + content: "\f1f2"; +} + +.fa-cc-amex:before { + content: "\f1f3"; +} + +.fa-cc-paypal:before { + content: "\f1f4"; +} + +.fa-cc-stripe:before { + content: "\f1f5"; +} + +.fa-bell-slash:before { + content: "\f1f6"; +} + +.fa-bell-slash-o:before { + content: "\f1f7"; +} + +.fa-trash:before { + content: "\f1f8"; +} + +.fa-copyright:before { + content: "\f1f9"; +} + +.fa-at:before { + content: "\f1fa"; +} + +.fa-eyedropper:before { + content: "\f1fb"; +} + +.fa-paint-brush:before { + content: "\f1fc"; +} + +.fa-birthday-cake:before { + content: "\f1fd"; +} + +.fa-area-chart:before { + content: "\f1fe"; +} + +.fa-pie-chart:before { + content: "\f200"; +} + +.fa-line-chart:before { + content: "\f201"; +} + +.fa-lastfm:before { + content: "\f202"; +} + +.fa-lastfm-square:before { + content: "\f203"; +} + +.fa-toggle-off:before { + content: "\f204"; +} + +.fa-toggle-on:before { + content: "\f205"; +} + +.fa-bicycle:before { + content: "\f206"; +} + +.fa-bus:before { + content: "\f207"; +} + +.fa-ioxhost:before { + content: "\f208"; +} + +.fa-angellist:before { + content: "\f209"; +} + +.fa-cc:before { + content: "\f20a"; +} + +.fa-shekel:before, .fa-sheqel:before, .fa-ils:before { + content: "\f20b"; +} + +.fa-meanpath:before { + content: "\f20c"; +} diff --git a/网站/style/css/fonts/fontawesome-webfont.eot b/网站/style/css/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..84677bc Binary files /dev/null and b/网站/style/css/fonts/fontawesome-webfont.eot differ diff --git a/网站/style/css/fonts/fontawesome-webfont.svg b/网站/style/css/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..8ec0cc1 --- /dev/null +++ b/网站/style/css/fonts/fontawesome-webfont.svg @@ -0,0 +1 @@ +网站防火墙
    网站服务器返回状态码404

    管理员已屏蔽了此状态的详细信息
    如果您是网站管理员点击这里查看详情
    \ No newline at end of file diff --git a/网站/style/css/fonts/fontawesome-webfont.ttf b/网站/style/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..96a3639 Binary files /dev/null and b/网站/style/css/fonts/fontawesome-webfont.ttf differ diff --git a/网站/style/css/fonts/fontawesome-webfont.woff b/网站/style/css/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..8ec0cc1 --- /dev/null +++ b/网站/style/css/fonts/fontawesome-webfont.woff @@ -0,0 +1 @@ +网站防火墙
    网站服务器返回状态码404

    管理员已屏蔽了此状态的详细信息
    如果您是网站管理员点击这里查看详情
    \ No newline at end of file diff --git a/网站/style/css/fonts/fontawesome-webfont01.eot b/网站/style/css/fonts/fontawesome-webfont01.eot new file mode 100644 index 0000000..84677bc Binary files /dev/null and b/网站/style/css/fonts/fontawesome-webfont01.eot differ diff --git a/网站/style/css/fonts/glyphicons-halflings-regular.eot b/网站/style/css/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..4a4ca86 Binary files /dev/null and b/网站/style/css/fonts/glyphicons-halflings-regular.eot differ diff --git a/网站/style/css/fonts/glyphicons-halflings-regular.svg b/网站/style/css/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..8ec0cc1 --- /dev/null +++ b/网站/style/css/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1 @@ +网站防火墙
    网站服务器返回状态码404

    管理员已屏蔽了此状态的详细信息
    如果您是网站管理员点击这里查看详情
    \ No newline at end of file diff --git a/网站/style/css/fonts/glyphicons-halflings-regular.ttf b/网站/style/css/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..67fa00b Binary files /dev/null and b/网站/style/css/fonts/glyphicons-halflings-regular.ttf differ diff --git a/网站/style/css/fonts/glyphicons-halflings-regular.woff b/网站/style/css/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..8ec0cc1 --- /dev/null +++ b/网站/style/css/fonts/glyphicons-halflings-regular.woff @@ -0,0 +1 @@ +网站防火墙
    网站服务器返回状态码404

    管理员已屏蔽了此状态的详细信息
    如果您是网站管理员点击这里查看详情
    \ No newline at end of file diff --git a/网站/style/css/img/bs-docs-masthead-pattern.png b/网站/style/css/img/bs-docs-masthead-pattern.png new file mode 100644 index 0000000..75c46a1 Binary files /dev/null and b/网站/style/css/img/bs-docs-masthead-pattern.png differ diff --git a/网站/style/css/index.min.css b/网站/style/css/index.min.css new file mode 100644 index 0000000..edd90f9 --- /dev/null +++ b/网站/style/css/index.min.css @@ -0,0 +1,213 @@ +.jumbotron { + position: relative; + padding: 40px 0; + color: #fff; + text-align: center; + text-shadow: 0 1px 3px rgba(0,0,0,.4),0 0 30px rgba(0,0,0,.075); + background: #020031; + background: -moz-linear-gradient(45deg,#020031 0,#6d3353 100%); + background: -webkit-gradient(linear,left bottom,right top,color-stop(0%,#020031),color-stop(100%,#6d3353)); + background: -webkit-linear-gradient(45deg,#020031 0,#6d3353 100%); + background: -o-linear-gradient(45deg,#020031 0,#6d3353 100%); + background: -ms-linear-gradient(45deg,#020031 0,#6d3353 100%); + background: linear-gradient(45deg,#020031 0,#6d3353 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#020031', endColorstr='#6d3353', GradientType=1); + -webkit-box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); + box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); +} + + .jumbotron a { + color: #fff; + color: rgba(255,255,255,.5); + -webkit-transition: all .2s ease-in-out; + -moz-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; + } + + .jumbotron aa:hover { + color: #fff; + text-shadow: 0 0 10px rgba(255,255,255,.25); + } + + .jumbotron .container { + position: relative; + z-index: 2; + } + + .jumbotron:after { + content: ''; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: url(img/bs-docs-masthead-pattern.png) repeat center center; + opacity: .4; + } + +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (-o-min-device-pixel-ratio:2/1) { + .jumbotron:after { + background-size: 150px 150px; + } +} + +.masthead { + padding: 60px 0 80px; + margin-bottom: 0; + color: #fff; +} + +@media screen and (min-width:768px) { + .masthead { + padding: 90px 0 110px; + } +} + +.masthead h1 { + font-size: 60px; + line-height: 1; + letter-spacing: -2px; + font-weight: 700; +} + +@media screen and (min-width:768px) { + .masthead h1 { + font-size: 90px; + } +} + +@media screen and (min-width:992px) { + .masthead h1 { + font-size: 100px; + } +} + +.masthead h2 { + font-size: 18px; + font-weight: 200; + line-height: 1.25; +} + +@media screen and (min-width:768px) { + .masthead h2 { + font-size: 24px; + } +} + +@media screen and (min-width:992px) { + .masthead h2 { + font-size: 30px; + } +} + +.masthead p { + font-size: 40px; + font-weight: 200; + line-height: 1.25; +} + +.masthead .masthead-button-links { + margin-top: 30px; +} + +.masthead-links { + margin: 0; + padding: 0; + list-style: none; +} + + .masthead-links li { + display: inline; + padding: 0 10px; + color: rgba(255,255,255,.25); + } + + .masthead-links li a:hover { + color: #fff; + } + +.subhead { + text-align: center; + border-bottom: 1px solid #ddd; +} + +@media screen and (min-width:768px) { + .subhead { + text-align: left; + } +} + +.subhead h1 { + font-size: 60px; +} + +.subhead p { + margin-bottom: 20px; +} + +@media screen and (min-width:768px) { + .subhead p { + text-align: left; + } +} + +.btn-primary.btn-shadow { + -webkit-box-shadow: inset 0 -4px 0 #2a6496; + box-shadow: inset 0 -4px 0 #2a6496; + border: 0; + color: #fff; +} + +.btn-lg.btn-shadow { + padding: 13px 35px 17px; +} + +.bc-social { + padding: 15px 0; + text-align: center; + background-color: #f5f5f5; + border-top: 1px solid #fff; + border-bottom: 1px solid #ddd; +} + +.bc-social-buttons { + margin-left: 0; + margin-bottom: 0; + padding-left: 0; + list-style: none; +} + + .bc-social-buttons li { + display: inline-block; + line-height: 1; + color: #555; + } + + .bc-social-buttons li .fa { + font-size: 18px; + margin-right: 3px; + } + + .bc-social-buttons li .fa-bbs { + font-size: 20px; + } + + .bc-social-buttons li a { + color: #555; + } + + .bc-social-buttons li.social-qq:hover { + color: #428bca; + } + + .bc-social-buttons li.social-bbs a:hover { + color: #d9534f; + } + + .bc-social-buttons > li + li:before { + padding: 0 10px; + color: #ccc; + content: "|"; + } diff --git a/网站/style/css/site.min.css b/网站/style/css/site.min.css new file mode 100644 index 0000000..3eac3cc --- /dev/null +++ b/网站/style/css/site.min.css @@ -0,0 +1,682 @@ +body { + font-family: "Helvetica Neue",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3","WenQuanYi Micro Hei",sans-serif; +} + +h1, .h1, h2, .h2, h3, .h3, h4, .h4, .lead { + font-family: "Helvetica Neue",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3","Microsoft YaHei UI","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif; +} + +body { + padding-top: 30px; +} + +@media (min-width:768px) { + .navbar { + min-height: 40px; + } + + .navbar-nav > li > a { + font-size: 14px; + padding-top: 11px; + padding-bottom: 11px; + } + + .navbar-brand { + padding-top: 0; + padding-bottom: 0; + line-height: 42px; + height: 42px; + } +} + +.jumbotron { + position: relative; + padding: 40px 0; + color: #fff; + text-align: center; + text-shadow: 0 1px 3px rgba(0,0,0,.4),0 0 30px rgba(0,0,0,.075); + background: #020031; + background: -moz-linear-gradient(45deg,#020031 0,#6d3353 100%); + background: -webkit-gradient(linear,left bottom,right top,color-stop(0%,#020031),color-stop(100%,#6d3353)); + background: -webkit-linear-gradient(45deg,#020031 0,#6d3353 100%); + background: -o-linear-gradient(45deg,#020031 0,#6d3353 100%); + background: -ms-linear-gradient(45deg,#020031 0,#6d3353 100%); + background: linear-gradient(45deg,#020031 0,#6d3353 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#020031', endColorstr='#6d3353', GradientType=1); + -webkit-box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); + -moz-box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); + box-shadow: inset 0 3px 7px rgba(0,0,0,.2),inset 0 -3px 7px rgba(0,0,0,.2); +} + + .jumbotron a { + color: #fff; + color: rgba(255,255,255,.5); + -webkit-transition: all .2s ease-in-out; + -moz-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; + } + + .jumbotron aa:hover { + color: #fff; + text-shadow: 0 0 10px rgba(255,255,255,.25); + } + + .jumbotron .container { + position: relative; + z-index: 2; + } + + .jumbotron:after { + content: ''; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: url(img/bs-docs-masthead-pattern.png) repeat center center; + opacity: .4; + } + +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (-o-min-device-pixel-ratio:2/1) { + .jumbotron:after { + background-size: 150px 150px; + } +} + +.masthead { + padding: 60px 0 80px; + margin-bottom: 0; + color: #fff; +} + +@media screen and (min-width:768px) { + .masthead { + padding: 90px 0 110px; + } +} + +.masthead h1 { + font-size: 60px; + line-height: 1; + letter-spacing: -2px; + font-weight: 700; +} + +@media screen and (min-width:768px) { + .masthead h1 { + font-size: 90px; + } +} + +@media screen and (min-width:992px) { + .masthead h1 { + font-size: 100px; + } +} + +.masthead h2 { + font-size: 18px; + font-weight: 200; + line-height: 1.25; +} + +@media screen and (min-width:768px) { + .masthead h2 { + font-size: 24px; + } +} + +@media screen and (min-width:992px) { + .masthead h2 { + font-size: 30px; + } +} + +.masthead p { + font-size: 40px; + font-weight: 200; + line-height: 1.25; +} + +.masthead .masthead-button-links { + margin-top: 30px; +} + +.masthead-links { + margin: 0; + padding: 0; + list-style: none; +} + + .masthead-links li { + display: inline; + padding: 0 10px; + color: rgba(255,255,255,.25); + } + + .masthead-links li a:hover { + color: #fff; + } + +.subhead { + text-align: center; + border-bottom: 1px solid #ddd; +} + +@media screen and (min-width:768px) { + .subhead { + text-align: left; + } +} + +.subhead h1 { + font-size: 60px; +} + +.subhead p { + margin-bottom: 20px; +} + +@media screen and (min-width:768px) { + .subhead p { + text-align: left; + } +} + +.btn-primary.btn-shadow { + -webkit-box-shadow: inset 0 -4px 0 #2a6496; + box-shadow: inset 0 -4px 0 #2a6496; + border: 0; + color: #fff; +} + +.btn-lg.btn-shadow { + padding: 13px 35px 17px; +} + +.bc-social { + padding: 15px 0; + text-align: center; + background-color: #f5f5f5; + border-top: 1px solid #fff; + border-bottom: 1px solid #ddd; +} + +.bc-social-buttons { + margin-left: 0; + margin-bottom: 0; + padding-left: 0; + list-style: none; +} + + .bc-social-buttons li { + display: inline-block; + line-height: 1; + color: #555; + } + + .bc-social-buttons li .fa { + font-size: 18px; + margin-right: 3px; + } + + .bc-social-buttons li .fa-weibo { + font-size: 20px; + } + + .bc-social-buttons li a { + color: #555; + } + + .bc-social-buttons li.social-qq:hover { + color: #428bca; + } + + .bc-social-buttons li.social-weibo a:hover { + color: #d9534f; + } + + .bc-social-buttons > li + li:before { + padding: 0 10px; + color: #ccc; + content: "|"; + } + +.projects .thumbnail { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; + max-width: 310px; + margin-bottom: 30px; + border-radius: 0; +} + + .projects .thumbnail .caption { + height: 200px; + overflow-y: hidden; + color: #555; + } + + .projects .thumbnail .caption a:hover, .projects .thumbnail .caption a:focus { + text-decoration: none; + } + + .projects .thumbnail img { + max-width: 100%; + height: auto; + } + +.projects-header { + width: 60%; + text-align: center; + margin: 60px 0 10px; + font-weight: 200; + margin-bottom: 40px; + display: block; + margin-left: auto; + margin-right: auto; +} + + .projects-header h2 { + font-size: 30px; + letter-spacing: -1px; + } + +@media screen and (min-width:768px) { + .projects-header h2 { + font-size: 42px; + } +} + +.nav-sub { + padding-top: 10px; + padding-bottom: 10px; + margin-top: 70px; + border-top: 1px solid #eee; +} + +.footer { + color: #777; + padding: 30px 0; + border-top: 1px solid #e5e5e5; + margin-top: 70px; +} + + .footer a { + color: #777; + } + +.footer-top .about > div { + height: 110px; + margin-bottom: 10px; +} + + .footer-top .about > div h4 { + color: #563d7c; + font-size: 16px; + } + +.footer-bottom { + font-size: 13px; +} + + .footer-bottom ul > li { + padding: 0; + } + + .footer-bottom ul > li + li:before { + padding: 0 10px; + color: #ccc; + content: "|"; + } + +#scrollUp { + background-color: #777; + color: #eee; + font-size: 40px; + line-height: 1; + text-align: center; + text-decoration: none; + bottom: 20px; + right: 20px; + overflow: hidden; + width: 46px; + height: 46px; + border: none; + opacity: .8; +} + + #scrollUp:hover { + background-color: #333; + } + +@media screen and (min-width:992px) { + #scrollUp { + bottom: 100px; + } +} + +.bc-sidebar { + margin-top: 30px; +} + + .bc-sidebar > ul > li > a { + display: block; + margin: 0 0 -1px; + padding: 8px 14px; + border: 1px solid #e5e5e5; + } + +.excerpt-list { + margin-top: 60px; +} + +.excerpt { + min-height: 120px; + border: 1px solid #eee; + position: relative; + margin-bottom: 10px; + padding: 20px 20px 20px 24px; +} + +.excerpt-title { + font-size: 24px; + margin-top: 0; +} + + .excerpt-title a { + color: #555; + } + + .excerpt-title a:hover, .excerpt-title a:active { + color: #3071a9; + } + +.excerpt-meta { + position: absolute; + bottom: 12px; +} + +.excerpt-tags { + color: #777; +} + + .excerpt-tags .glyphicon { + position: relative; + top: 2px; + color: #eee; + } + + .excerpt-tags a, .excerpt-tags span { + color: #777; + font-size: 12px; + } + +.post { + position: relative; + margin-top: 60px; + max-width: 680px; + display: block; + margin-left: auto; + margin-right: auto; +} + +.post-header h1, .post-header h2 { + font-size: 32px; + margin: 0 0 45px; + position: relative; + text-align: center; +} + +@media (min-width:768px) { + .post-header h1, .post-header h2 { + font-size: 36px; + } +} + +.post-header h1:after, .post-header h2:after { + border-top: 1px solid #e5e5e5; + bottom: 0; + content: ""; + left: 50%; + margin: 0 0 0 -30%; + position: absolute; + width: 60%; +} + +.post-header h1 a, .post-header h2 a { + color: #363636; + display: block; + padding: 65px 0 20px; + position: relative; +} + + .post-header h1 a:hover, .post-header h2 a:hover { + color: #428bca; + } + + .post-header h1 a:before, .post-header h2 a:before { + border-top: 1px solid #e5e5e5; + bottom: -4px; + content: ""; + left: 50%; + margin: 0 0 0 -27%; + position: absolute; + width: 60%; + } + + .post-header h1 a:after, .post-header h2 a:after { + border-top: 1px solid #e5e5e5; + bottom: -3px; + content: ""; + left: 50%; + margin: 0 0 0 -28%; + position: absolute; + width: 60%; + } + +@media (min-width:768px) { + .post-header h1 a, .post-header h2 a { + padding-left: 65px; + padding-right: 65px; + } +} + +.post-content { + font-size: 16px; + line-height: 1.8; + padding-top: 20px; + padding-bottom: 20px; +} + + .post-content p, .post-content pre, .post-content ul, .post-content ol, .post-content dl, .post-content form, .post-content hr, .post-content table, .post-content blockquote { + margin-bottom: 1.8em; + } + + .post-content blockquote { + font-size: 16px; + } + + .post-content pre { + margin-top: -20px; + } + + .post-content li > p { + margin-bottom: 5px; + } + + .post-content img, .post-content video, .post-content embed, .post-content iframe { + max-width: 100%; + } + + .post-content img { + height: auto; + } + +article.page { + margin-top: 0; + max-width: none; +} + + article.page .post-content { + padding-top: 0; + } + + article.page .post-content h2 { + font-size: 36px; + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; + } + +/*格外添加CSS*/ + +.bc-sidenav { + width: 100%; + margin: 30px 0 0; + padding: 0; + background-color: #fff; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 1px 4px rgba(0,0,0,0.065); + -moz-box-shadow: 0 1px 4px rgba(0,0,0,0.065); + box-shadow: 0 1px 4px rgba(0,0,0,0.065); +} + + .bc-sidenav > li > a { + display: block; + margin: 0 0 -1px; + padding: 8px 14px; + border: 1px solid #e5e5e5; + } + + .bc-sidenav .glyphicon { + float: right; + margin-top: 2px; + margin-right: -6px; + opacity: .25; + } + +.subhead { + padding-top: 50px; + padding-bottom: 0px; + color: #fff; + background-repeat: repeat-x; + background-image: -webkit-linear-gradient(45deg, #020031, #6d3353); + background-image: -moz-linear-gradient(45deg, #020031, #6d3353); + background-image: linear-gradient(45deg, #020031, #6d3353); +} + + .subhead:after { + content: ''; + display: block; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: url(img/bs-docs-masthead-pattern.png) repeat center center; + opacity: .4; + } + +@media screen and (min-width:768px) { + .masthead h1 { + font-size: 90px; + } + + .masthead h2 { + font-size: 24px; + } +} + +@media screen and (min-width:992px) { + .masthead h1 { + font-size: 100px; + } + + .masthead h2 { + font-size: 30px; + } +} + +.bc-social { + padding: 15px 0; + text-align: center; + background-color: #f5f5f5; + border-top: 1px solid #fff; + border-bottom: 1px solid #ddd; +} + +.subhead h1 { + font-size: 50px; +} + +.jumbotron { + margin-bottom: 0px; +} + +@media all and (min-width:992px) { + .col-md-3 { + width: 20%; + } +} + +.bc-sidenav { + margin-top: 20px; +} + +.page-header { + margin-top: 20px; +} + +.text-small { + width: 300px; +} + +.bc-sidenav .active a { + font-weight: bold; +} + +.o-ver { + list-style: none; + margin-top: 5px; + padding-left: 15px; +} + + .o-ver > li { + margin: 0px; + padding: 0px; + height: 25px; + } + + .o-ver .active a { + font-weight: bold; + } + +.bs-example { + margin-top: 50px; +} + +.carousel-inner .item img { + width: 100%; +} + +.margintop10 { + margin-top: 10px; +} + +.pad10 { + padding: 10px; +} + +.tabborder { + border: 1px solid #DDDDDD; + border-top: 0px; +} + +.hide { + display: none; +} diff --git a/网站/style/images/alpha.png b/网站/style/images/alpha.png new file mode 100644 index 0000000..a1898eb Binary files /dev/null and b/网站/style/images/alpha.png differ diff --git a/网站/style/images/buju.png b/网站/style/images/buju.png new file mode 100644 index 0000000..eb7fe92 Binary files /dev/null and b/网站/style/images/buju.png differ diff --git a/网站/style/images/kongjian.png b/网站/style/images/kongjian.png new file mode 100644 index 0000000..15d8216 Binary files /dev/null and b/网站/style/images/kongjian.png differ diff --git a/网站/style/images/logo.png b/网站/style/images/logo.png new file mode 100644 index 0000000..bac1c5d Binary files /dev/null and b/网站/style/images/logo.png differ diff --git a/网站/style/images/neicun.png b/网站/style/images/neicun.png new file mode 100644 index 0000000..c9922a5 Binary files /dev/null and b/网站/style/images/neicun.png differ diff --git a/网站/style/images/sediao.png b/网站/style/images/sediao.png new file mode 100644 index 0000000..e3de8e2 Binary files /dev/null and b/网站/style/images/sediao.png differ diff --git a/网站/style/images/vs.png b/网站/style/images/vs.png new file mode 100644 index 0000000..2ac9091 Binary files /dev/null and b/网站/style/images/vs.png differ diff --git a/网站/style/images/xuanran.png b/网站/style/images/xuanran.png new file mode 100644 index 0000000..3b76c71 Binary files /dev/null and b/网站/style/images/xuanran.png differ diff --git a/网站/style/images/zhuti.png b/网站/style/images/zhuti.png new file mode 100644 index 0000000..0ab2fd0 Binary files /dev/null and b/网站/style/images/zhuti.png differ diff --git a/网站/style/js/aaeb0b49702a4f3a9867f381bbb019c6.js b/网站/style/js/aaeb0b49702a4f3a9867f381bbb019c6.js new file mode 100644 index 0000000..ac00f88 --- /dev/null +++ b/网站/style/js/aaeb0b49702a4f3a9867f381bbb019c6.js @@ -0,0 +1,21 @@ +;(function(global){ + global.Ta=global.Ta||{}; + Ta.hack=function(){ + return { + params:'', + conf:{sid:40649130,pf:1,logo:255,hot:{}} }; + }; +})(this); + +(function(h,n){function v(c){c+="";var a,b,d,e,f,g;d=c.length;b=0;for(a="";b>2);a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((e&3)<<4);a+="==";break}f=c.charCodeAt(b++);if(b==d){a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(e>>2);a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((e&3)<<4|(f&240)>> +4);a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((f&15)<<2);a+="=";break}g=c.charCodeAt(b++);a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(e>>2);a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((e&3)<<4|(f&240)>>4);a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt((f&15)<<2|(g&192)>>6);a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(g&63)}return a}function p(c){return(c= +document.cookie.match(new RegExp("(?:^|;\\s)"+c+"=(.*?)(?:;\\s|$)")))?c[1]:""}function q(c,a,b){var d=window.location.host,e={"com.cn":1,"net.cn":1,"gov.cn":1,"com.hk":1,"co.nz":1,"org.cn":1,"edu.cn":1},f=d.split(".");2]*)?(?:\?([^\'\"\\<>#]*))?(?:#(\w+))?/i)|| +[],c=d[1],a=d[2],b=d[3],d=d[4]);void 0!==d&&(d=encodeURI(d.replace(/\"|\'|\<|\>/ig,"M")));if(b)for(var f=b.split("&"),g=0,h=f.length;g'};document.write(['',a[c]||a.df,""].join(""))}var k={afs:{key:1,id:"ssid",c_id:"pgv_afsid",fr:"hash"},afc:{key:2,id:"__tacid",c_id:"pgv_afcid",fr:"param"},gdt:{key:11, +id:"qz_gdt",c_id:"pgv_gdtid",fr:"param"}};n.taClick=function(c,a){var b=Ta.src.replace(/ext=[^&]*/,function(){return"ext="+("evtid"==a?"ty=0;evtid=":"clickid"==a?"ty=1;clickid=":"adid=")+c}).replace(/r2=([^&]*)/,function(b,c){return"r2="+("clickid"==a?"b":"a")+c});(new Image(1,1)).src=b};n.Ta=n.Ta||{};Ta.pgv=u;!Ta.async&&u(Ta.hack?Ta.hack():"")})({sid:"",pf:"",hot:{url:"",isValid:!1}},this); \ No newline at end of file diff --git a/网站/style/js/ajax.js b/网站/style/js/ajax.js new file mode 100644 index 0000000..048b5a2 --- /dev/null +++ b/网站/style/js/ajax.js @@ -0,0 +1,40 @@ +function ajaxYzm(yzm, backFunction) { + var parm = { "yzm": yzm }; + ajaxTextPost("/UserVerifyCode.aspx", parm, backFunction); +} +function ajaxDown(id, backFunction) { + var parm = { "id": id }; + ajaxTextPost("/search", parm, backFunction); +} +function ajaxTextPost(link, parm, backFunction) { + $.ajax({ + type: "POST", + //contentType: "application/json; charset=utf-8", + url: link, + data: parm, + dataType: "text", //json + async: false, + success: function (data) { + backFunction(data); + }, + error: function (e) { + alert("发生错误:" + e.responseText); + } + }); +} +function ajaxJsonPost(link, parm, backFunction) { + $.ajax({ + type: "POST", + contentType: "application/json; charset=utf-8", + url: link, + data: parm, + dataType: "json", + async: false, + success: function (data) { + backFunction(data); + }, + error: function (e) { + alert("发生错误:" + e.responseText); + } + }); +} \ No newline at end of file diff --git a/网站/style/js/bootstrap.min.js b/网站/style/js/bootstrap.min.js new file mode 100644 index 0000000..d839865 --- /dev/null +++ b/网站/style/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.1",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.1",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.1",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c="prev"==a?-1:1,d=this.getItemIndex(b),e=(d+c)%this.$items.length;return this.$items.eq(e)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i="next"==b?"first":"last",j=this;if(!f.length){if(!this.options.wrap)return;f=this.$element.find(".item")[i]()}if(f.hasClass("active"))return this.sliding=!1;var k=f[0],l=a.Event("slide.bs.carousel",{relatedTarget:k,direction:h});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var m=a(this.$indicators.children()[this.getItemIndex(f)]);m&&m.addClass("active")}var n=a.Event("slid.bs.carousel",{relatedTarget:k,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),j.sliding=!1,setTimeout(function(){j.$element.trigger(n)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(n)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a(this.options.trigger).filter('[href="#'+b.id+'"], [data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.1",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0,trigger:'[data-toggle="collapse"]'},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.find("> .panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":a.extend({},e.data(),{trigger:this});c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.1",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('